From bbb5a56f4e0f48b57c942db967bae54d27587d12 Mon Sep 17 00:00:00 2001 From: Zygo Blaxell Date: Fri, 19 Oct 2012 07:56:35 -0400 Subject: [PATCH 1/1] From http://www.jwz.org/xscreensaver/xscreensaver-5.20.tar.gz -rw-r--r-- 1 zblaxell zblaxell 7380256 Oct 16 15:48 xscreensaver-5.20.tar.gz 052cc6676fe7818ec4131f41942266c237acdced xscreensaver-5.20.tar.gz --- INSTALL | 183 + Makefile.in | 374 + OSX/Default-568h@2x.png | Bin 0 -> 18594 bytes OSX/English.lproj/InfoPlist.strings | Bin 0 -> 92 bytes .../SaverRunner.nib/designable.nib | 1790 + .../SaverRunner.nib/keyedobjects.nib | Bin 0 -> 13707 bytes OSX/InvertedSlider.h | 33 + OSX/InvertedSlider.m | 159 + OSX/Makefile | 158 + OSX/PrefsReader.h | 50 + OSX/PrefsReader.m | 386 + OSX/README | 10 + OSX/SaverListController.h | 36 + OSX/SaverListController.m | 348 + OSX/SaverRunner.h | 74 + OSX/SaverRunner.icns | Bin 0 -> 62554 bytes OSX/SaverRunner.m | 1010 + OSX/SaverRunner.plist | 39 + OSX/XScreenSaver.icns | Bin 0 -> 187557 bytes OSX/XScreenSaver.plist | 30 + OSX/XScreenSaverConfigSheet.h | 77 + OSX/XScreenSaverConfigSheet.m | 3494 ++ OSX/XScreenSaverDMG.icns | Bin 0 -> 110173 bytes OSX/XScreenSaverGLView.h | 39 + OSX/XScreenSaverGLView.m | 483 + OSX/XScreenSaverSubclass.m | 33 + OSX/XScreenSaverView.h | 120 + OSX/XScreenSaverView.m | 1685 + OSX/bindist-DS_Store | Bin 0 -> 12292 bytes OSX/bindist.rtf | 71 + OSX/build-fntable.pl | 113 + OSX/iSaverRunner.ai | 3593 ++ OSX/iSaverRunner.plist | 67 + OSX/iSaverRunner.xib | 176 + OSX/iSaverRunner1024.png | Bin 0 -> 46983 bytes OSX/iSaverRunner114.png | Bin 0 -> 3809 bytes OSX/iSaverRunner29.png | Bin 0 -> 845 bytes OSX/iSaverRunner29t.png | Bin 0 -> 906 bytes OSX/iSaverRunner50.png | Bin 0 -> 1506 bytes OSX/iSaverRunner57.png | Bin 0 -> 1688 bytes OSX/iSaverRunner72.png | Bin 0 -> 2224 bytes OSX/icmp-warning.pl | 49 + OSX/ios_function_tables.h | 396 + OSX/iosgrabimage.m | 125 + OSX/iostextclient.m | 575 + OSX/jwxyz-timers.h | 29 + OSX/jwxyz-timers.m | 408 + OSX/jwxyz.h | 740 + OSX/jwxyz.m | 3287 ++ OSX/main.m | 29 + OSX/osxgrabscreen.m | 445 + OSX/update-info-plist.pl | 317 + OSX/update-thumbnail.pl | 150 + OSX/xscreensaver_Prefix.pch | 33 + README | 1413 + README.VMS | 57 + README.hacking | 180 + aclocal.m4 | 443 + config.guess | 1516 + config.h-vms | 284 + config.h.in | 489 + config.sub | 1626 + configure | 23193 ++++++++++ configure.in | 4464 ++ driver/.gdbinit | 27 + driver/Makefile.in | 1011 + driver/README | 6 + driver/XScreenSaver-Xm.ad | 126 + driver/XScreenSaver.ad.in | 503 + driver/XScreenSaver_Xm_ad.h | 108 + driver/XScreenSaver_ad.h | 364 + driver/auth.h | 54 + driver/compile_axp.com | 15 + driver/compile_decc.com | 15 + driver/demo-Gtk-conf.c | 1996 + driver/demo-Gtk-conf.h | 31 + driver/demo-Gtk-stubs.h | 90 + driver/demo-Gtk-support.c | 219 + driver/demo-Gtk-support.h | 61 + driver/demo-Gtk-widgets.c | 1764 + driver/demo-Gtk-widgets.h | 6 + driver/demo-Gtk.c | 5334 +++ driver/demo-Xm-widgets.c | 907 + driver/demo-Xm.c | 1875 + driver/dpms.c | 296 + driver/exec.c | 299 + driver/exec.h | 21 + driver/link_axp.com | 15 + driver/link_decc.com | 15 + driver/lock.c | 2263 + driver/mlstring.c | 229 + driver/mlstring.h | 57 + driver/passwd-helper.c | 162 + driver/passwd-kerberos.c | 251 + driver/passwd-pam.c | 514 + driver/passwd-pwent.c | 312 + driver/passwd.c | 334 + driver/pdf2jpeg.m | 152 + driver/pdf2jpeg.man | 43 + driver/prefs.c | 1650 + driver/prefs.h | 35 + driver/remote.c | 595 + driver/remote.h | 24 + driver/screens.c | 1077 + driver/screensaver-properties.desktop.in | 8 + driver/setuid.c | 361 + driver/splash.c | 866 + driver/stderr.c | 560 + driver/subprocs.c | 1375 + driver/test-apm.c | 101 + driver/test-fade.c | 123 + driver/test-grab.c | 89 + driver/test-mlstring.c | 312 + driver/test-passwd.c | 303 + driver/test-randr.c | 339 + driver/test-screens.c | 208 + driver/test-uid.c | 209 + driver/test-vp.c | 213 + driver/test-xdpms.c | 179 + driver/test-xinerama.c | 112 + driver/timers.c | 1669 + driver/types.h | 437 + driver/vms-getpwnam.c | 129 + driver/vms-hpwd.c | 75 + driver/vms-pwd.h | 48 + driver/vms-validate.c | 75 + driver/vms_axp.opt | 5 + driver/vms_axp_12.opt | 5 + driver/vms_decc.opt | 5 + driver/vms_decc_12.opt | 5 + driver/windows.c | 2001 + driver/xdpyinfo.c | 1098 + driver/xscreensaver-command.c | 439 + driver/xscreensaver-command.man | 263 + driver/xscreensaver-demo.glade2 | 3136 ++ driver/xscreensaver-demo.glade2p | 19 + driver/xscreensaver-demo.man | 398 + driver/xscreensaver-getimage-desktop | 207 + driver/xscreensaver-getimage-desktop.man | 55 + driver/xscreensaver-getimage-file | 1003 + driver/xscreensaver-getimage-file.man | 66 + driver/xscreensaver-getimage-video | 178 + driver/xscreensaver-getimage-video.man | 51 + driver/xscreensaver-getimage.c | 1951 + driver/xscreensaver-getimage.man | 73 + driver/xscreensaver-text | 808 + driver/xscreensaver-text.man | 85 + driver/xscreensaver.c | 2386 + driver/xscreensaver.h | 208 + driver/xscreensaver.man | 903 + driver/xscreensaver.pam.in | 13 + driver/xset.c | 389 + hacks/.gdbinit | 12 + hacks/Makefile.in | 2810 ++ hacks/README | 6 + hacks/abstractile.c | 1590 + hacks/abstractile.man | 52 + hacks/analogtv.c | 2209 + hacks/analogtv.h | 312 + hacks/anemone.c | 444 + hacks/anemone.man | 74 + hacks/anemotaxis.c | 752 + hacks/anemotaxis.man | 78 + hacks/ant.c | 1371 + hacks/ant.man | 96 + hacks/apollonian.c | 846 + hacks/apollonian.man | 70 + hacks/apple2-main.c | 1811 + hacks/apple2.c | 860 + hacks/apple2.h | 121 + hacks/apple2.man | 206 + hacks/asm6502.c | 2268 + hacks/asm6502.h | 181 + hacks/attraction.c | 1049 + hacks/attraction.man | 227 + hacks/automata.h | 64 + hacks/barcode.c | 1987 + hacks/barcode.man | 61 + hacks/blaster.c | 1187 + hacks/blaster.man | 65 + hacks/blitspin.c | 431 + hacks/blitspin.man | 96 + hacks/bouboule.c | 864 + hacks/bouboule.man | 80 + hacks/boxfit.c | 556 + hacks/boxfit.man | 102 + hacks/braid.c | 473 + hacks/braid.man | 69 + hacks/bsod.c | 4178 ++ hacks/bsod.man | 140 + hacks/bubbles-default.c | 151 + hacks/bubbles.c | 1433 + hacks/bubbles.h | 224 + hacks/bubbles.man | 140 + hacks/bumps.c | 732 + hacks/bumps.man | 80 + hacks/ccurve.c | 856 + hacks/ccurve.man | 60 + hacks/celtic.c | 1116 + hacks/celtic.man | 64 + hacks/check-configs.pl | 353 + hacks/cloudlife.c | 416 + hacks/cloudlife.man | 87 + hacks/compass.c | 978 + hacks/compass.man | 57 + hacks/compile_axp.com | 148 + hacks/compile_decc.com | 148 + hacks/config/README | 249 + hacks/config/abstractile.xml | 32 + hacks/config/anemone.xml | 50 + hacks/config/anemotaxis.xml | 36 + hacks/config/ant.xml | 63 + hacks/config/antinspect.xml | 21 + hacks/config/antmaze.xml | 19 + hacks/config/antspotlight.xml | 21 + hacks/config/apollonian.xml | 38 + hacks/config/apple2.xml | 62 + hacks/config/atlantis.xml | 46 + hacks/config/attraction.xml | 83 + hacks/config/atunnel.xml | 22 + hacks/config/barcode.xml | 32 + hacks/config/blaster.xml | 59 + hacks/config/blinkbox.xml | 31 + hacks/config/blitspin.xml | 38 + hacks/config/blocktube.xml | 30 + hacks/config/boing.xml | 47 + hacks/config/bouboule.xml | 30 + hacks/config/bouncingcow.xml | 28 + hacks/config/boxed.xml | 54 + hacks/config/boxfit.xml | 55 + hacks/config/braid.xml | 35 + hacks/config/bsod.xml | 88 + hacks/config/bubble3d.xml | 21 + hacks/config/bubbles.xml | 38 + hacks/config/bumps.xml | 32 + hacks/config/cage.xml | 23 + hacks/config/carousel.xml | 53 + hacks/config/ccurve.xml | 28 + hacks/config/celtic.xml | 28 + hacks/config/circuit.xml | 33 + hacks/config/cloudlife.xml | 37 + hacks/config/companioncube.xml | 52 + hacks/config/compass.xml | 20 + hacks/config/coral.xml | 32 + hacks/config/crackberg.xml | 48 + hacks/config/critical.xml | 27 + hacks/config/crystal.xml | 44 + hacks/config/cube21.xml | 73 + hacks/config/cubenetic.xml | 57 + hacks/config/cubestorm.xml | 38 + hacks/config/cubicgrid.xml | 28 + hacks/config/cwaves.xml | 27 + hacks/config/cynosure.xml | 28 + hacks/config/dangerball.xml | 33 + hacks/config/decayscreen.xml | 45 + hacks/config/deco.xml | 41 + hacks/config/deluxe.xml | 35 + hacks/config/demon.xml | 37 + hacks/config/discrete.xml | 28 + hacks/config/distort.xml | 49 + hacks/config/dnalogo.xml | 36 + hacks/config/drift.xml | 27 + hacks/config/endgame.xml | 25 + hacks/config/engine.xml | 40 + hacks/config/epicycle.xml | 52 + hacks/config/eruption.xml | 49 + hacks/config/euler2d.xml | 44 + hacks/config/extrusion.xml | 41 + hacks/config/fadeplot.xml | 31 + hacks/config/fiberlamp.xml | 27 + hacks/config/fireworkx.xml | 28 + hacks/config/flag.xml | 37 + hacks/config/flame.xml | 35 + hacks/config/flipflop.xml | 48 + hacks/config/flipscreen3d.xml | 23 + hacks/config/fliptext.xml | 47 + hacks/config/flow.xml | 56 + hacks/config/fluidballs.xml | 49 + hacks/config/flurry.xml | 28 + hacks/config/flyingtoasters.xml | 38 + hacks/config/fontglide.xml | 44 + hacks/config/forest.xml | 26 + hacks/config/fuzzyflakes.xml | 62 + hacks/config/galaxy.xml | 33 + hacks/config/gears.xml | 36 + hacks/config/gflux.xml | 57 + hacks/config/glblur.xml | 43 + hacks/config/glcells.xml | 60 + hacks/config/gleidescope.xml | 37 + hacks/config/glforestfire.xml | 42 + hacks/config/glhanoi.xml | 44 + hacks/config/glknots.xml | 59 + hacks/config/glmatrix.xml | 50 + hacks/config/glplanet.xml | 38 + hacks/config/glschool.xml | 41 + hacks/config/glslideshow.xml | 56 + hacks/config/glsnake.xml | 53 + hacks/config/gltext.xml | 47 + hacks/config/goop.xml | 61 + hacks/config/grav.xml | 32 + hacks/config/greynetic.xml | 21 + hacks/config/halftone.xml | 55 + hacks/config/halo.xml | 38 + hacks/config/helix.xml | 23 + hacks/config/hilbert.xml | 73 + hacks/config/hopalong.xml | 55 + hacks/config/hyperball.xml | 61 + hacks/config/hypercube.xml | 71 + hacks/config/hypertorus.xml | 114 + hacks/config/hypnowheel.xml | 50 + hacks/config/ifs.xml | 61 + hacks/config/imsmap.xml | 42 + hacks/config/interaggregate.xml | 29 + hacks/config/interference.xml | 53 + hacks/config/intermomentary.xml | 33 + hacks/config/jigglypuff.xml | 88 + hacks/config/jigsaw.xml | 47 + hacks/config/juggle.xml | 56 + hacks/config/juggler3d.xml | 51 + hacks/config/julia.xml | 35 + hacks/config/kaleidescope.xml | 38 + hacks/config/klein.xml | 127 + hacks/config/kumppa.xml | 28 + hacks/config/lament.xml | 26 + hacks/config/laser.xml | 34 + hacks/config/lavalite.xml | 86 + hacks/config/lcdscrub.xml | 51 + hacks/config/lightning.xml | 26 + hacks/config/lisa.xml | 40 + hacks/config/lissie.xml | 39 + hacks/config/lmorph.xml | 41 + hacks/config/lockward.xml | 63 + hacks/config/loop.xml | 33 + hacks/config/m6502.xml | 49 + hacks/config/maze.xml | 56 + hacks/config/memscroller.xml | 30 + hacks/config/menger.xml | 47 + hacks/config/metaballs.xml | 51 + hacks/config/mirrorblob.xml | 70 + hacks/config/mismunch.xml | 40 + hacks/config/moebius.xml | 25 + hacks/config/moebiusgears.xml | 43 + hacks/config/moire.xml | 34 + hacks/config/moire2.xml | 30 + hacks/config/molecule.xml | 57 + hacks/config/morph3d.xml | 30 + hacks/config/mountain.xml | 27 + hacks/config/munch.xml | 58 + hacks/config/nerverot.xml | 59 + hacks/config/noof.xml | 19 + hacks/config/noseguy.xml | 15 + hacks/config/pacman.xml | 24 + hacks/config/pedal.xml | 29 + hacks/config/penetrate.xml | 30 + hacks/config/penrose.xml | 52 + hacks/config/petri.xml | 83 + hacks/config/phosphor.xml | 39 + hacks/config/photopile.xml | 62 + hacks/config/piecewise.xml | 42 + hacks/config/pinion.xml | 45 + hacks/config/pipes.xml | 45 + hacks/config/polyhedra.xml | 195 + hacks/config/polyominoes.xml | 32 + hacks/config/polytopes.xml | 109 + hacks/config/pong.xml | 36 + hacks/config/popsquares.xml | 52 + hacks/config/providence.xml | 25 + hacks/config/pulsar.xml | 39 + hacks/config/pyro.xml | 33 + hacks/config/qix.xml | 70 + hacks/config/queens.xml | 27 + hacks/config/rd-bomb.xml | 62 + hacks/config/rdbomb.xml | 62 + hacks/config/ripples.xml | 51 + hacks/config/rocks.xml | 42 + hacks/config/rorschach.xml | 34 + hacks/config/rotor.xml | 36 + hacks/config/rotzoomer.xml | 37 + hacks/config/rubik.xml | 36 + hacks/config/rubikblocks.xml | 63 + hacks/config/sballs.xml | 33 + hacks/config/shadebobs.xml | 35 + hacks/config/sierpinski.xml | 34 + hacks/config/sierpinski3d.xml | 30 + hacks/config/skytentacles.xml | 67 + hacks/config/slidescreen.xml | 50 + hacks/config/slip.xml | 43 + hacks/config/sonar.xml | 84 + hacks/config/speedmine.xml | 58 + hacks/config/sphere.xml | 26 + hacks/config/spheremonics.xml | 56 + hacks/config/spiral.xml | 34 + hacks/config/spotlight.xml | 30 + hacks/config/sproingies.xml | 32 + hacks/config/squiral.xml | 47 + hacks/config/stairs.xml | 21 + hacks/config/starfish.xml | 39 + hacks/config/starwars.xml | 59 + hacks/config/stonerview.xml | 23 + hacks/config/strange.xml | 30 + hacks/config/substrate.xml | 41 + hacks/config/superquadrics.xml | 32 + hacks/config/surfaces.xml | 67 + hacks/config/swirl.xml | 29 + hacks/config/t3d.xml | 49 + hacks/config/tangram.xml | 41 + hacks/config/thornbird.xml | 33 + hacks/config/timetunnel.xml | 39 + hacks/config/topblock.xml | 60 + hacks/config/triangle.xml | 24 + hacks/config/tronbit.xml | 37 + hacks/config/truchet.xml | 37 + hacks/config/twang.xml | 57 + hacks/config/vermiculate.xml | 18 + hacks/config/vidwhacker.xml | 26 + hacks/config/vines.xml | 26 + hacks/config/voronoi.xml | 59 + hacks/config/wander.xml | 45 + hacks/config/webcollage.xml | 52 + hacks/config/whirlwindwarp.xml | 24 + hacks/config/whirlygig.xml | 86 + hacks/config/worm.xml | 35 + hacks/config/wormhole.xml | 27 + hacks/config/xanalogtv.xml | 39 + hacks/config/xflame.xml | 31 + hacks/config/xjack.xml | 21 + hacks/config/xlyap.xml | 48 + hacks/config/xmatrix.xml | 63 + hacks/config/xrayswarm.xml | 19 + hacks/config/xspirograph.xml | 28 + hacks/config/xss.dtd | 109 + hacks/config/xss.xsd | 375 + hacks/config/zoom.xml | 50 + hacks/coral.c | 303 + hacks/coral.man | 64 + hacks/critical.c | 452 + hacks/critical.man | 94 + hacks/crystal.c | 1279 + hacks/crystal.man | 81 + hacks/cwaves.c | 208 + hacks/cwaves.man | 76 + hacks/cynosure.c | 432 + hacks/cynosure.man | 64 + hacks/decayscreen.c | 380 + hacks/decayscreen.man | 92 + hacks/deco.c | 333 + hacks/deco.man | 105 + hacks/deluxe.c | 453 + hacks/deluxe.man | 72 + hacks/demon.c | 988 + hacks/demon.man | 69 + hacks/discrete.c | 461 + hacks/discrete.man | 61 + hacks/distort.c | 862 + hacks/distort.man | 137 + hacks/drift.c | 701 + hacks/drift.man | 79 + hacks/epicycle.c | 779 + hacks/epicycle.man | 204 + hacks/eruption.c | 520 + hacks/eruption.man | 77 + hacks/euler2d.c | 887 + hacks/euler2d.man | 69 + hacks/euler2d.tex | 337 + hacks/fadeplot.c | 245 + hacks/fadeplot.man | 65 + hacks/fiberlamp.c | 473 + hacks/fiberlamp.man | 65 + hacks/fireworkx.c | 499 + hacks/fireworkx.man | 90 + hacks/fireworkx_mmx.S | 226 + hacks/flag.c | 568 + hacks/flag.man | 92 + hacks/flame.c | 456 + hacks/flame.man | 74 + hacks/flow.c | 1231 + hacks/flow.man | 137 + hacks/fluidballs.c | 805 + hacks/fluidballs.man | 90 + hacks/fontglide.c | 1681 + hacks/fontglide.man | 124 + hacks/forest.c | 260 + hacks/forest.man | 62 + hacks/fps.c | 251 + hacks/fps.h | 35 + hacks/fpsI.h | 42 + hacks/fuzzyflakes.c | 639 + hacks/fuzzyflakes.man | 112 + hacks/galaxy.c | 468 + hacks/galaxy.man | 87 + hacks/glx/Makefile.in | 2893 ++ hacks/glx/README | 10 + hacks/glx/antinspect.c | 723 + hacks/glx/antinspect.man | 56 + hacks/glx/antmaze.c | 1648 + hacks/glx/antmaze.man | 52 + hacks/glx/ants.h | 45 + hacks/glx/antspotlight.c | 824 + hacks/glx/antspotlight.man | 56 + hacks/glx/atlantis.c | 579 + hacks/glx/atlantis.h | 129 + hacks/glx/atlantis.man | 78 + hacks/glx/atunnel.c | 330 + hacks/glx/atunnel.man | 83 + hacks/glx/b_draw.c | 239 + hacks/glx/b_lockglue.c | 237 + hacks/glx/b_sphere.c | 219 + hacks/glx/blinkbox.c | 597 + hacks/glx/blinkbox.man | 73 + hacks/glx/blocktube.c | 449 + hacks/glx/blocktube.man | 73 + hacks/glx/boing.c | 683 + hacks/glx/boing.man | 105 + hacks/glx/bouncingcow.c | 544 + hacks/glx/bouncingcow.man | 73 + hacks/glx/boxed.c | 1315 + hacks/glx/boxed.h | 4116 ++ hacks/glx/boxed.man | 56 + hacks/glx/bubble3d.c | 281 + hacks/glx/bubble3d.h | 100 + hacks/glx/bubble3d.man | 62 + hacks/glx/buildlwo.c | 96 + hacks/glx/buildlwo.h | 38 + hacks/glx/cage.c | 489 + hacks/glx/cage.man | 61 + hacks/glx/carousel.c | 916 + hacks/glx/carousel.man | 109 + hacks/glx/chessgames.h | 343 + hacks/glx/chessmodels.c | 1733 + hacks/glx/chessmodels.h | 44 + hacks/glx/circuit.c | 2283 + hacks/glx/circuit.man | 72 + hacks/glx/companion.c | 614 + hacks/glx/companion_disc.c | 9593 +++++ hacks/glx/companion_heart.c | 653 + hacks/glx/companion_quad.c | 389 + hacks/glx/companioncube.man | 85 + hacks/glx/cow_face.c | 341 + hacks/glx/cow_hide.c | 13055 ++++++ hacks/glx/cow_hoofs.c | 1037 + hacks/glx/cow_horns.c | 1025 + hacks/glx/cow_tail.c | 464 + hacks/glx/cow_udder.c | 1520 + hacks/glx/crackberg.c | 1463 + hacks/glx/crackberg.man | 123 + hacks/glx/cube21.c | 968 + hacks/glx/cube21.man | 147 + hacks/glx/cubenetic.c | 610 + hacks/glx/cubenetic.man | 89 + hacks/glx/cubestorm.c | 429 + hacks/glx/cubestorm.man | 77 + hacks/glx/cubicgrid.c | 295 + hacks/glx/cubicgrid.man | 83 + hacks/glx/dangerball.c | 388 + hacks/glx/dangerball.man | 72 + hacks/glx/dnalogo.c | 2467 ++ hacks/glx/dnapizza.h | 122 + hacks/glx/dolphin.c | 2061 + hacks/glx/dropshadow.c | 181 + hacks/glx/dropshadow.h | 51 + hacks/glx/dxf2gl.pl | 501 + hacks/glx/e_textures.h | 1478 + hacks/glx/endgame.c | 993 + hacks/glx/endgame.man | 72 + hacks/glx/engine.c | 1022 + hacks/glx/engine.man | 80 + hacks/glx/extrusion-helix2.c | 47 + hacks/glx/extrusion-helix3.c | 46 + hacks/glx/extrusion-helix4.c | 63 + hacks/glx/extrusion-joinoffset.c | 148 + hacks/glx/extrusion-screw.c | 114 + hacks/glx/extrusion-taper.c | 218 + hacks/glx/extrusion-twistoid.c | 213 + hacks/glx/extrusion.c | 560 + hacks/glx/extrusion.h | 55 + hacks/glx/extrusion.man | 71 + hacks/glx/flipflop.c | 874 + hacks/glx/flipflop.man | 95 + hacks/glx/flipscreen3d.c | 545 + hacks/glx/flipscreen3d.man | 61 + hacks/glx/fliptext.c | 1008 + hacks/glx/fliptext.man | 114 + hacks/glx/flurry-smoke.c | 1442 + hacks/glx/flurry-spark.c | 285 + hacks/glx/flurry-star.c | 106 + hacks/glx/flurry-texture.c | 224 + hacks/glx/flurry.c | 567 + hacks/glx/flurry.h | 296 + hacks/glx/flurry.man | 73 + hacks/glx/flyingtoasters.c | 874 + hacks/glx/flyingtoasters.man | 86 + hacks/glx/font-ximage.c | 254 + hacks/glx/font-ximage.h | 30 + hacks/glx/fps-gl.c | 113 + hacks/glx/gears.c | 946 + hacks/glx/gears.man | 79 + hacks/glx/gflux.c | 838 + hacks/glx/gflux.man | 111 + hacks/glx/glblur.c | 640 + hacks/glx/glblur.man | 76 + hacks/glx/glcells.c | 1328 + hacks/glx/glcells.man | 97 + hacks/glx/gleidescope.c | 1630 + hacks/glx/gleidescope.man | 77 + hacks/glx/glforestfire.c | 1147 + hacks/glx/glforestfire.man | 130 + hacks/glx/glhanoi.c | 2065 + hacks/glx/glhanoi.man | 83 + hacks/glx/glknots.c | 463 + hacks/glx/glknots.man | 81 + hacks/glx/gllist.c | 9 + hacks/glx/gllist.h | 28 + hacks/glx/glmatrix.c | 1069 + hacks/glx/glmatrix.man | 116 + hacks/glx/glplanet.c | 662 + hacks/glx/glplanet.man | 70 + hacks/glx/glschool.c | 222 + hacks/glx/glschool.h | 17 + hacks/glx/glschool.man | 126 + hacks/glx/glschool_alg.c | 364 + hacks/glx/glschool_alg.h | 126 + hacks/glx/glschool_gl.c | 274 + hacks/glx/glschool_gl.h | 47 + hacks/glx/glslideshow.c | 1260 + hacks/glx/glslideshow.man | 131 + hacks/glx/glsnake.c | 2694 ++ hacks/glx/glsnake.man | 98 + hacks/glx/gltext.c | 678 + hacks/glx/gltext.man | 123 + hacks/glx/gltrackball.c | 157 + hacks/glx/gltrackball.h | 59 + hacks/glx/glut_roman.h | 2455 ++ hacks/glx/glut_stroke.c | 57 + hacks/glx/glut_swidth.c | 73 + hacks/glx/glutstroke.h | 47 + hacks/glx/glxfonts.c | 671 + hacks/glx/glxfonts.h | 58 + hacks/glx/grab-ximage.c | 839 + hacks/glx/grab-ximage.h | 76 + hacks/glx/hilbert.c | 1150 + hacks/glx/hilbert.man | 103 + hacks/glx/hypertorus.c | 1031 + hacks/glx/hypertorus.man | 188 + hacks/glx/hypnowheel.c | 298 + hacks/glx/hypnowheel.man | 80 + hacks/glx/involute.c | 968 + hacks/glx/involute.h | 77 + hacks/glx/jigglypuff.c | 1089 + hacks/glx/jigglypuff.man | 121 + hacks/glx/jigsaw.c | 1534 + hacks/glx/jigsaw.man | 90 + hacks/glx/juggler3d.c | 3097 ++ hacks/glx/juggler3d.man | 183 + hacks/glx/jwzgles.c | 3807 ++ hacks/glx/jwzgles.h | 519 + hacks/glx/jwzglesI.h | 313 + hacks/glx/klein.c | 2044 + hacks/glx/klein.man | 299 + hacks/glx/lament.c | 2062 + hacks/glx/lament.man | 68 + hacks/glx/lavalite.c | 1569 + hacks/glx/lavalite.man | 160 + hacks/glx/lockward.c | 934 + hacks/glx/lockward.man | 79 + hacks/glx/marching.c | 641 + hacks/glx/marching.h | 48 + hacks/glx/menger.c | 555 + hacks/glx/menger.man | 78 + hacks/glx/mirrorblob.c | 1862 + hacks/glx/mirrorblob.man | 107 + hacks/glx/moebius.c | 816 + hacks/glx/moebius.man | 65 + hacks/glx/moebiusgears.c | 414 + hacks/glx/moebiusgears.man | 86 + hacks/glx/molecule.c | 1735 + hacks/glx/molecule.man | 160 + hacks/glx/molecules.sh | 22 + hacks/glx/morph3d.c | 833 + hacks/glx/morph3d.man | 57 + hacks/glx/noof.c | 477 + hacks/glx/noof.man | 52 + hacks/glx/normals.c | 52 + hacks/glx/normals.h | 44 + hacks/glx/photopile.c | 785 + hacks/glx/photopile.man | 113 + hacks/glx/pinion.c | 1534 + hacks/glx/pinion.man | 82 + hacks/glx/pipeobjs.c | 3262 ++ hacks/glx/pipes.c | 1252 + hacks/glx/pipes.man | 85 + hacks/glx/polyhedra-gl.c | 758 + hacks/glx/polyhedra.c | 2458 ++ hacks/glx/polyhedra.h | 52 + hacks/glx/polyhedra.man | 124 + hacks/glx/polytopes.c | 3213 ++ hacks/glx/polytopes.man | 207 + hacks/glx/providence.c | 820 + hacks/glx/providence.man | 66 + hacks/glx/pulsar.c | 521 + hacks/glx/pulsar.man | 102 + hacks/glx/queens.c | 657 + hacks/glx/queens.man | 66 + hacks/glx/rotator.c | 247 + hacks/glx/rotator.h | 60 + hacks/glx/rubik.c | 2167 + hacks/glx/rubik.man | 69 + hacks/glx/rubikblocks.c | 662 + hacks/glx/rubikblocks.man | 117 + hacks/glx/s1_1.c | 1733 + hacks/glx/s1_2.c | 1733 + hacks/glx/s1_3.c | 1733 + hacks/glx/s1_4.c | 1733 + hacks/glx/s1_5.c | 1733 + hacks/glx/s1_6.c | 1733 + hacks/glx/s1_b.c | 505 + hacks/glx/sballs.c | 873 + hacks/glx/sballs.man | 125 + hacks/glx/shark.c | 1395 + hacks/glx/sierpinski3d.c | 583 + hacks/glx/sierpinski3d.man | 67 + hacks/glx/skytentacles.c | 1095 + hacks/glx/skytentacles.man | 102 + hacks/glx/sonar-icmp.c | 1417 + hacks/glx/sonar-sim.c | 112 + hacks/glx/sonar.c | 1047 + hacks/glx/sonar.h | 71 + hacks/glx/sonar.man | 169 + hacks/glx/sphere.c | 138 + hacks/glx/sphere.h | 23 + hacks/glx/spheremonics.c | 927 + hacks/glx/spheremonics.man | 92 + hacks/glx/sproingies.c | 928 + hacks/glx/sproingies.h | 25 + hacks/glx/sproingies.man | 68 + hacks/glx/sproingiewrap.c | 252 + hacks/glx/stairs.c | 627 + hacks/glx/stairs.man | 56 + hacks/glx/starwars.c | 1051 + hacks/glx/starwars.h | 312 + hacks/glx/starwars.man | 181 + hacks/glx/starwars.txt | 311 + hacks/glx/stonerview-move.c | 155 + hacks/glx/stonerview-move.h | 32 + hacks/glx/stonerview-osc.c | 341 + hacks/glx/stonerview-osc.h | 175 + hacks/glx/stonerview-view.c | 116 + hacks/glx/stonerview.c | 189 + hacks/glx/stonerview.h | 67 + hacks/glx/stonerview.man | 53 + hacks/glx/superquadrics.c | 797 + hacks/glx/superquadrics.man | 70 + hacks/glx/surfaces.c | 683 + hacks/glx/surfaces.man | 127 + hacks/glx/swim.c | 232 + hacks/glx/tangram.c | 1095 + hacks/glx/tangram.man | 67 + hacks/glx/tangram_shapes.c | 236 + hacks/glx/tangram_shapes.h | 15 + hacks/glx/teapot.c | 282 + hacks/glx/teapot.h | 7 + hacks/glx/teapot2.h | 6330 +++ hacks/glx/texfont.c | 585 + hacks/glx/texfont.h | 37 + hacks/glx/timetunnel.c | 1267 + hacks/glx/timetunnel.man | 105 + hacks/glx/toast.c | 185 + hacks/glx/toast2.c | 209 + hacks/glx/toaster.c | 371 + hacks/glx/toaster_base.c | 125 + hacks/glx/toaster_handle.c | 59 + hacks/glx/toaster_handle2.c | 35 + hacks/glx/toaster_jet.c | 173 + hacks/glx/toaster_knob.c | 71 + hacks/glx/toaster_slots.c | 101 + hacks/glx/toaster_wing.c | 38 + hacks/glx/topblock.c | 890 + hacks/glx/topblock.h | 45 + hacks/glx/topblock.man | 170 + hacks/glx/trackball.c | 331 + hacks/glx/trackball.h | 82 + hacks/glx/tronbit.c | 550 + hacks/glx/tronbit.man | 79 + hacks/glx/tronbit_idle1.c | 247 + hacks/glx/tronbit_idle2.c | 175 + hacks/glx/tronbit_no.c | 1087 + hacks/glx/tronbit_yes.c | 31 + hacks/glx/tube.c | 400 + hacks/glx/tube.h | 32 + hacks/glx/tunnel_draw.c | 512 + hacks/glx/tunnel_draw.h | 11 + hacks/glx/voronoi.c | 506 + hacks/glx/voronoi.man | 88 + hacks/glx/vrml2gl.pl | 361 + hacks/glx/wfront2gl.pl | 361 + hacks/glx/whale.c | 1887 + hacks/glx/xlock-gl-utils.c | 219 + hacks/glx/xpm-ximage.c | 462 + hacks/glx/xpm-ximage.h | 31 + hacks/glx/xscreensaver-gl-helper.c | 74 + hacks/glx/xscreensaver-gl-helper.man | 33 + hacks/goop.c | 600 + hacks/goop.man | 84 + hacks/grav.c | 363 + hacks/grav.man | 78 + hacks/greynetic.c | 290 + hacks/greynetic.man | 56 + hacks/halftone.c | 394 + hacks/halftone.man | 83 + hacks/halo.c | 436 + hacks/halo.man | 75 + hacks/helix.c | 353 + hacks/helix.man | 62 + hacks/hopalong.c | 579 + hacks/hopalong.man | 82 + hacks/hyperball.c | 2463 ++ hacks/hyperball.man | 88 + hacks/hypercube.c | 571 + hacks/hypercube.man | 97 + hacks/ifs.c | 532 + hacks/ifs.man | 111 + hacks/images/6x10font.xbm | 190 + hacks/images/amiga.xpm | 269 + hacks/images/apple2font.xbm | 41 + hacks/images/atari.xbm | 6 + hacks/images/atm.xbm | 246 + hacks/images/blocktube.xpm | 320 + hacks/images/bob.xbm | 43 + hacks/images/bubbles/blood.pov | 24 + hacks/images/bubbles/blood1.xpm | 75 + hacks/images/bubbles/blood10.xpm | 159 + hacks/images/bubbles/blood11.xpm | 170 + hacks/images/bubbles/blood2.xpm | 101 + hacks/images/bubbles/blood3.xpm | 112 + hacks/images/bubbles/blood4.xpm | 116 + hacks/images/bubbles/blood5.xpm | 121 + hacks/images/bubbles/blood6.xpm | 128 + hacks/images/bubbles/blood7.xpm | 135 + hacks/images/bubbles/blood8.xpm | 143 + hacks/images/bubbles/blood9.xpm | 149 + hacks/images/bubbles/blue.pov | 22 + hacks/images/bubbles/blue1.xpm | 64 + hacks/images/bubbles/blue10.xpm | 157 + hacks/images/bubbles/blue11.xpm | 169 + hacks/images/bubbles/blue2.xpm | 90 + hacks/images/bubbles/blue3.xpm | 104 + hacks/images/bubbles/blue4.xpm | 116 + hacks/images/bubbles/blue5.xpm | 122 + hacks/images/bubbles/blue6.xpm | 128 + hacks/images/bubbles/blue7.xpm | 132 + hacks/images/bubbles/blue8.xpm | 142 + hacks/images/bubbles/blue9.xpm | 149 + hacks/images/bubbles/glass.pov | 27 + hacks/images/bubbles/glass1.xpm | 79 + hacks/images/bubbles/glass10.xpm | 155 + hacks/images/bubbles/glass11.xpm | 167 + hacks/images/bubbles/glass2.xpm | 95 + hacks/images/bubbles/glass3.xpm | 112 + hacks/images/bubbles/glass4.xpm | 118 + hacks/images/bubbles/glass5.xpm | 120 + hacks/images/bubbles/glass6.xpm | 128 + hacks/images/bubbles/glass7.xpm | 133 + hacks/images/bubbles/glass8.xpm | 140 + hacks/images/bubbles/glass9.xpm | 147 + hacks/images/bubbles/jade.pov | 24 + hacks/images/bubbles/jade1.xpm | 76 + hacks/images/bubbles/jade10.xpm | 158 + hacks/images/bubbles/jade11.xpm | 171 + hacks/images/bubbles/jade2.xpm | 96 + hacks/images/bubbles/jade3.xpm | 113 + hacks/images/bubbles/jade4.xpm | 116 + hacks/images/bubbles/jade5.xpm | 123 + hacks/images/bubbles/jade6.xpm | 128 + hacks/images/bubbles/jade7.xpm | 133 + hacks/images/bubbles/jade8.xpm | 143 + hacks/images/bubbles/jade9.xpm | 149 + hacks/images/chromesphere.xpm | 350 + hacks/images/earth.xpm | 303 + hacks/images/ground.xpm | 227 + hacks/images/hmac.xpm | 52 + hacks/images/jigglymap.xpm | 350 + hacks/images/lament128.xpm | 791 + hacks/images/lament512.xpm | 3094 ++ hacks/images/m6502/amiga.asm | 120 + hacks/images/m6502/breakout.asm | 195 + hacks/images/m6502/byterun.asm | 100 + hacks/images/m6502/cellular-30.asm | 67 + hacks/images/m6502/cellular-600.asm | 209 + hacks/images/m6502/colors.asm | 46 + hacks/images/m6502/crunch6502.asm | 292 + hacks/images/m6502/demoscene.asm | 457 + hacks/images/m6502/disco.asm | 23 + hacks/images/m6502/dmsc.asm | 108 + hacks/images/m6502/dragon-fractal.asm | 49 + hacks/images/m6502/fullscreenlogo.asm | 107 + hacks/images/m6502/keftal.asm | 82 + hacks/images/m6502/matrix.asm | 67 + hacks/images/m6502/noise.asm | 16 + hacks/images/m6502/random-walk.asm | 82 + hacks/images/m6502/random.asm | 11 + hacks/images/m6502/random2.asm | 11 + hacks/images/m6502/rorschach.asm | 124 + hacks/images/m6502/santa.asm | 142 + hacks/images/m6502/selfmodify.asm | 12 + hacks/images/m6502/sierpinsky.asm | 131 + hacks/images/m6502/softsprite.asm | 132 + hacks/images/m6502/spacer.asm | 235 + hacks/images/m6502/starfield2d.asm | 50 + hacks/images/m6502/wave6502.asm | 164 + hacks/images/m6502/zookeeper.asm | 109 + hacks/images/mac.xbm | 14 + hacks/images/macbomb.xbm | 474 + hacks/images/matrix1.xbm | 1260 + hacks/images/matrix1.xpm | 392 + hacks/images/matrix1b.xbm | 307 + hacks/images/matrix1b.xpm | 227 + hacks/images/matrix2.xbm | 1260 + hacks/images/matrix2.xpm | 393 + hacks/images/matrix2b.xbm | 307 + hacks/images/matrix2b.xpm | 233 + hacks/images/matrix3.xpm | 692 + hacks/images/molecules/adenine.pdb | 37 + hacks/images/molecules/adrenochrome.pdb | 55 + hacks/images/molecules/bucky.pdb | 156 + hacks/images/molecules/caffeine.pdb | 54 + hacks/images/molecules/capsaicin.pdb | 49 + hacks/images/molecules/chlordecone.pdb | 49 + hacks/images/molecules/cocaine.pdb | 93 + hacks/images/molecules/codeine.pdb | 93 + hacks/images/molecules/cyclohexane.pdb | 151 + hacks/images/molecules/cytosine.pdb | 33 + hacks/images/molecules/dna.pdb | 972 + hacks/images/molecules/dodecahedrane.pdb | 87 + hacks/images/molecules/dthc.pdb | 107 + hacks/images/molecules/dynamite.pdb | 47 + hacks/images/molecules/glycol.pdb | 27 + hacks/images/molecules/guanine.pdb | 39 + hacks/images/molecules/heroin.pdb | 107 + hacks/images/molecules/hexahelicene.pdb | 90 + hacks/images/molecules/ibuprofen.pdb | 72 + hacks/images/molecules/lsd.pdb | 104 + hacks/images/molecules/menthol.pdb | 69 + hacks/images/molecules/mescaline.pdb | 71 + hacks/images/molecules/methamphetamine.pdb | 88 + hacks/images/molecules/morphine.pdb | 87 + hacks/images/molecules/nicotine.pdb | 59 + hacks/images/molecules/novocaine.pdb | 81 + hacks/images/molecules/olestra.pdb | 913 + hacks/images/molecules/penicillin.pdb | 89 + hacks/images/molecules/salvinorin.pdb | 92 + hacks/images/molecules/sarin.pdb | 43 + hacks/images/molecules/strychnine.pdb | 101 + hacks/images/molecules/sucrose.pdb | 97 + hacks/images/molecules/thalidomide.pdb | 65 + hacks/images/molecules/thymine.pdb | 37 + hacks/images/molecules/viagra.pdb | 133 + hacks/images/molecules/vitaminb6.pdb | 56 + hacks/images/molecules/vitaminc.pdb | 47 + hacks/images/molecules/vx.pdb | 92 + hacks/images/noseguy/nose-f1.xbm | 46 + hacks/images/noseguy/nose-f1.xpm | 74 + hacks/images/noseguy/nose-f2.xbm | 46 + hacks/images/noseguy/nose-f2.xpm | 74 + hacks/images/noseguy/nose-f3.xbm | 46 + hacks/images/noseguy/nose-f3.xpm | 74 + hacks/images/noseguy/nose-f4.xbm | 46 + hacks/images/noseguy/nose-f4.xpm | 73 + hacks/images/noseguy/nose-l1.xbm | 46 + hacks/images/noseguy/nose-l1.xpm | 74 + hacks/images/noseguy/nose-l2.xbm | 46 + hacks/images/noseguy/nose-l2.xpm | 74 + hacks/images/noseguy/nose-r1.xbm | 46 + hacks/images/noseguy/nose-r1.xpm | 74 + hacks/images/noseguy/nose-r2.xbm | 46 + hacks/images/noseguy/nose-r2.xpm | 74 + hacks/images/osx_10_2.xpm | 298 + hacks/images/osx_10_3.xpm | 279 + hacks/images/pacman/eyes-d.xpm | 70 + hacks/images/pacman/eyes-l.xpm | 70 + hacks/images/pacman/eyes-r.xpm | 70 + hacks/images/pacman/eyes-u.xpm | 70 + hacks/images/pacman/ghost-d1.xpm | 72 + hacks/images/pacman/ghost-d2.xpm | 72 + hacks/images/pacman/ghost-l1.xpm | 72 + hacks/images/pacman/ghost-l2.xpm | 73 + hacks/images/pacman/ghost-mask.xpm | 69 + hacks/images/pacman/ghost-r1.xpm | 72 + hacks/images/pacman/ghost-r2.xpm | 72 + hacks/images/pacman/ghost-s1.xpm | 71 + hacks/images/pacman/ghost-s2.xpm | 71 + hacks/images/pacman/ghost-sf1.xpm | 71 + hacks/images/pacman/ghost-sf2.xpm | 71 + hacks/images/pacman/ghost-u1.xpm | 72 + hacks/images/pacman/ghost-u2.xpm | 72 + hacks/images/pacman/pacman-0.xpm | 69 + hacks/images/pacman/pacman-d1.xpm | 69 + hacks/images/pacman/pacman-d2.xpm | 69 + hacks/images/pacman/pacman-ds1.xpm | 69 + hacks/images/pacman/pacman-ds2.xpm | 69 + hacks/images/pacman/pacman-ds3.xpm | 69 + hacks/images/pacman/pacman-ds4.xpm | 69 + hacks/images/pacman/pacman-ds5.xpm | 69 + hacks/images/pacman/pacman-ds6.xpm | 69 + hacks/images/pacman/pacman-ds7.xpm | 69 + hacks/images/pacman/pacman-ds8.xpm | 69 + hacks/images/pacman/pacman-l1.xpm | 69 + hacks/images/pacman/pacman-l2.xpm | 69 + hacks/images/pacman/pacman-r1.xpm | 69 + hacks/images/pacman/pacman-r2.xpm | 69 + hacks/images/pacman/pacman-u1.xpm | 69 + hacks/images/pacman/pacman-u2.xpm | 69 + hacks/images/sball-bg.xpm | 355 + hacks/images/sball.xpm | 131 + hacks/images/scales.xpm | 204 + hacks/images/sea-texture.xpm | 199 + hacks/images/som.xbm | 1685 + hacks/images/timetunnel0.xpm | 343 + hacks/images/timetunnel1.xpm | 1111 + hacks/images/timetunnel2.xpm | 599 + hacks/images/toast.xpm | 222 + hacks/images/tree.xpm | 226 + hacks/images/tunnel0.xpm | 198 + hacks/images/tunnel1.xpm | 134 + hacks/images/tunnel2.xpm | 206 + hacks/images/tunnel3.xpm | 150 + hacks/images/tunnel4.xpm | 134 + hacks/images/tunnel5.xpm | 134 + hacks/images/tunnelstar.xpm | 323 + hacks/images/wood.xpm | 70 + hacks/imsmap.c | 416 + hacks/imsmap.man | 64 + hacks/interaggregate.c | 971 + hacks/interaggregate.man | 72 + hacks/interference.c | 476 + hacks/interference.man | 86 + hacks/intermomentary.c | 572 + hacks/intermomentary.man | 82 + hacks/juggle.c | 2823 ++ hacks/juggle.man | 181 + hacks/julia.c | 456 + hacks/julia.man | 81 + hacks/kaleidescope.c | 487 + hacks/kaleidescope.man | 89 + hacks/kumppa.c | 533 + hacks/kumppa.man | 65 + hacks/laser.c | 366 + hacks/laser.man | 68 + hacks/lcdscrub.c | 204 + hacks/lcdscrub.man | 73 + hacks/lightning.c | 614 + hacks/lightning.man | 62 + hacks/link_axp.com | 107 + hacks/link_decc.com | 107 + hacks/lisa.c | 751 + hacks/lisa.man | 71 + hacks/lissie.c | 329 + hacks/lissie.man | 69 + hacks/ljlatest | 18 + hacks/ljlatest.man | 61 + hacks/lmorph.c | 568 + hacks/lmorph.man | 65 + hacks/loop.c | 1703 + hacks/loop.man | 65 + hacks/m6502.c | 290 + hacks/m6502.sh | 25 + hacks/maze.c | 1650 + hacks/maze.man | 148 + hacks/memscroller.c | 653 + hacks/memscroller.man | 78 + hacks/metaballs.c | 429 + hacks/metaballs.man | 73 + hacks/moire.c | 294 + hacks/moire.man | 68 + hacks/moire2.c | 351 + hacks/moire2.man | 63 + hacks/mountain.c | 298 + hacks/mountain.man | 60 + hacks/munch.c | 456 + hacks/munch.man | 153 + hacks/munge-ad.pl | 243 + hacks/nerverot.c | 1350 + hacks/nerverot.man | 132 + hacks/noseguy.c | 622 + hacks/noseguy.man | 84 + hacks/pacman.c | 1802 + hacks/pacman.h | 231 + hacks/pacman.man | 67 + hacks/pacman_ai.c | 876 + hacks/pacman_ai.h | 32 + hacks/pacman_level.c | 772 + hacks/pacman_level.h | 33 + hacks/pedal.c | 326 + hacks/pedal.man | 60 + hacks/penetrate.c | 988 + hacks/penetrate.man | 98 + hacks/penrose.c | 1355 + hacks/penrose.man | 106 + hacks/petri.c | 758 + hacks/petri.man | 129 + hacks/phosphor.c | 1261 + hacks/phosphor.man | 173 + hacks/piecewise.c | 997 + hacks/piecewise.man | 77 + hacks/polyominoes.c | 2381 + hacks/polyominoes.man | 65 + hacks/pong.c | 790 + hacks/pong.man | 82 + hacks/popsquares.c | 267 + hacks/pyro.c | 368 + hacks/pyro.man | 64 + hacks/qix.c | 621 + hacks/qix.man | 132 + hacks/rd-bomb.c | 590 + hacks/rd-bomb.man | 100 + hacks/ripples.c | 1131 + hacks/ripples.man | 96 + hacks/rocks.c | 545 + hacks/rocks.man | 90 + hacks/rorschach.c | 205 + hacks/rorschach.man | 75 + hacks/rotor.c | 401 + hacks/rotor.man | 68 + hacks/rotzoomer.c | 483 + hacks/rotzoomer.man | 88 + hacks/screenhack.c | 931 + hacks/screenhack.h | 61 + hacks/screenhackI.h | 138 + hacks/shadebobs.c | 465 + hacks/shadebobs.man | 65 + hacks/sierpinski.c | 230 + hacks/sierpinski.man | 69 + hacks/slidescreen.c | 485 + hacks/slidescreen.man | 97 + hacks/slip.c | 367 + hacks/slip.man | 86 + hacks/speedmine.c | 1644 + hacks/speedmine.man | 246 + hacks/sphere.c | 308 + hacks/sphere.man | 62 + hacks/spiral.c | 335 + hacks/spiral.man | 71 + hacks/spotlight.c | 333 + hacks/spotlight.man | 80 + hacks/squiral.c | 278 + hacks/squiral.man | 80 + hacks/starfish.c | 545 + hacks/starfish.man | 84 + hacks/strange.c | 701 + hacks/strange.man | 62 + hacks/substrate.c | 739 + hacks/substrate.man | 73 + hacks/swirl.c | 1488 + hacks/swirl.man | 70 + hacks/t3d.c | 970 + hacks/t3d.man | 131 + hacks/thornbird.c | 281 + hacks/thornbird.man | 64 + hacks/triangle.c | 369 + hacks/triangle.man | 56 + hacks/truchet.c | 533 + hacks/truchet.man | 139 + hacks/twang.c | 791 + hacks/twang.man | 132 + hacks/vermiculate.c | 1219 + hacks/vermiculate.man | 48 + hacks/vidwhacker | 506 + hacks/vidwhacker.man | 89 + hacks/vines.c | 203 + hacks/vines.man | 66 + hacks/vms_axp.opt | 4 + hacks/vms_axp_12.opt | 4 + hacks/vms_decc.opt | 4 + hacks/vms_decc_12.opt | 4 + hacks/wander.c | 260 + hacks/wander.man | 76 + hacks/webcollage | 3886 ++ hacks/webcollage-cocoa.m | 420 + hacks/webcollage-helper-cocoa.m | 407 + hacks/webcollage-helper.c | 504 + hacks/webcollage.man | 247 + hacks/whirlwindwarp.c | 502 + hacks/whirlwindwarp.man | 64 + hacks/whirlygig.c | 733 + hacks/whirlygig.man | 137 + hacks/worm.c | 442 + hacks/worm.man | 65 + hacks/wormhole.c | 721 + hacks/wormhole.man | 69 + hacks/xanalogtv.c | 617 + hacks/xanalogtv.man | 84 + hacks/xflame.c | 816 + hacks/xflame.man | 72 + hacks/xjack.c | 484 + hacks/xjack.man | 52 + hacks/xlockmore.c | 557 + hacks/xlockmore.h | 198 + hacks/xlockmoreI.h | 170 + hacks/xlyap.c | 1918 + hacks/xlyap.man | 223 + hacks/xmatrix.c | 1850 + hacks/xmatrix.man | 146 + hacks/xml2man.pl | 250 + hacks/xpm-pixmap.c | 363 + hacks/xpm-pixmap.h | 26 + hacks/xrayswarm.c | 1220 + hacks/xrayswarm.man | 50 + hacks/xscreensaver-sgigl.c | 266 + hacks/xspirograph.c | 330 + hacks/xspirograph.man | 71 + hacks/xsublim.c | 798 + hacks/xsublim.man | 91 + hacks/zoom.c | 269 + hacks/zoom.man | 111 + install-sh | 250 + intltool-extract.in | 309 + intltool-merge.in | 567 + intltool-update.in | 613 + makevms.com | 57 + po/ChangeLog | 300 + po/Makefile.in.in | 385 + po/POTFILES.in | 230 + po/ca.po | 8905 ++++ po/da.po | 9938 +++++ po/de.po | 9219 ++++ po/es.po | 10021 +++++ po/et.po | 8995 ++++ po/fi.po | 8939 ++++ po/fr.po | 9248 ++++ po/hu.po | 9760 +++++ po/it.po | 8967 ++++ po/ja.po | 9039 ++++ po/ko.po | 9340 ++++ po/nb.po | 9071 ++++ po/nl.po | 11325 +++++ po/pl.po | 9387 ++++ po/pt.po | 9995 +++++ po/pt_BR.po | 9563 +++++ po/ru.po | 9132 ++++ po/sk.po | 9242 ++++ po/sv.po | 11236 +++++ po/update.sh | 24 + po/vi.po | 9347 ++++ po/wa.po | 9138 ++++ po/zh_CN.po | 9513 ++++ po/zh_TW.po | 9358 ++++ setup.com | 123 + utils/Makefile.in | 307 + utils/README | 6 + utils/ad2c | 42 + utils/alpha.c | 215 + utils/alpha.h | 22 + utils/colorbars.c | 144 + utils/colorbars.h | 24 + utils/colors.c | 701 + utils/colors.h | 140 + utils/compile_axp.com | 26 + utils/compile_decc.com | 26 + utils/erase.c | 758 + utils/erase.h | 20 + utils/fade.c | 962 + utils/fade.h | 21 + utils/grabclient.c | 931 + utils/grabscreen.c | 925 + utils/grabscreen.h | 102 + utils/hsv.c | 81 + utils/hsv.h | 27 + utils/images/logo-180.gif | Bin 0 -> 3328 bytes utils/images/logo-180.xpm | 207 + utils/images/logo-50.gif | Bin 0 -> 857 bytes utils/images/logo-50.xpm | 77 + utils/images/logo-big.gif | Bin 0 -> 17019 bytes utils/images/logo.eps | 8058 ++++ utils/images/screensaver-cmndln.png | Bin 0 -> 1040 bytes utils/images/screensaver-colorselector.png | Bin 0 -> 1104 bytes utils/images/screensaver-diagnostic.png | Bin 0 -> 1307 bytes utils/images/screensaver-locking.png | Bin 0 -> 944 bytes utils/images/screensaver-power.png | Bin 0 -> 973 bytes utils/images/screensaver-snap.png | Bin 0 -> 1272 bytes utils/logo.c | 75 + utils/minixpm.c | 235 + utils/minixpm.h | 28 + utils/overlay.c | 158 + utils/resources.c | 265 + utils/resources.h | 33 + utils/spline.c | 319 + utils/spline.h | 51 + utils/textclient.c | 502 + utils/textclient.h | 31 + utils/usleep.c | 64 + utils/usleep.h | 20 + utils/utils.h | 27 + utils/version.h | 2 + utils/visual-gl.c | 308 + utils/visual.c | 544 + utils/visual.h | 32 + utils/vms-gtod.c | 31 + utils/vms-gtod.h | 85 + utils/vms-strdup.c | 25 + utils/vroot.h | 156 + utils/xdbe.c | 75 + utils/xdbe.h | 27 + utils/xmu.c | 173 + utils/xmu.h | 14 + utils/xscreensaver-intl.h | 36 + utils/xshm.c | 229 + utils/xshm.h | 37 + utils/yarandom.c | 139 + utils/yarandom.h | 65 + xscreensaver.spec | 204 + xscreensaver.xcodeproj/project.pbxproj | 35849 ++++++++++++++++ 1309 files changed, 750775 insertions(+) create mode 100644 INSTALL create mode 100644 Makefile.in create mode 100644 OSX/Default-568h@2x.png create mode 100644 OSX/English.lproj/InfoPlist.strings create mode 100644 OSX/English.lproj/SaverRunner.nib/designable.nib create mode 100644 OSX/English.lproj/SaverRunner.nib/keyedobjects.nib create mode 100644 OSX/InvertedSlider.h create mode 100644 OSX/InvertedSlider.m create mode 100644 OSX/Makefile create mode 100644 OSX/PrefsReader.h create mode 100644 OSX/PrefsReader.m create mode 100644 OSX/README create mode 100644 OSX/SaverListController.h create mode 100644 OSX/SaverListController.m create mode 100644 OSX/SaverRunner.h create mode 100644 OSX/SaverRunner.icns create mode 100644 OSX/SaverRunner.m create mode 100644 OSX/SaverRunner.plist create mode 100644 OSX/XScreenSaver.icns create mode 100644 OSX/XScreenSaver.plist create mode 100644 OSX/XScreenSaverConfigSheet.h create mode 100644 OSX/XScreenSaverConfigSheet.m create mode 100644 OSX/XScreenSaverDMG.icns create mode 100644 OSX/XScreenSaverGLView.h create mode 100644 OSX/XScreenSaverGLView.m create mode 100644 OSX/XScreenSaverSubclass.m create mode 100644 OSX/XScreenSaverView.h create mode 100644 OSX/XScreenSaverView.m create mode 100644 OSX/bindist-DS_Store create mode 100644 OSX/bindist.rtf create mode 100755 OSX/build-fntable.pl create mode 100644 OSX/iSaverRunner.ai create mode 100644 OSX/iSaverRunner.plist create mode 100644 OSX/iSaverRunner.xib create mode 100644 OSX/iSaverRunner1024.png create mode 100644 OSX/iSaverRunner114.png create mode 100644 OSX/iSaverRunner29.png create mode 100644 OSX/iSaverRunner29t.png create mode 100644 OSX/iSaverRunner50.png create mode 100644 OSX/iSaverRunner57.png create mode 100644 OSX/iSaverRunner72.png create mode 100755 OSX/icmp-warning.pl create mode 100644 OSX/ios_function_tables.h create mode 100644 OSX/iosgrabimage.m create mode 100644 OSX/iostextclient.m create mode 100644 OSX/jwxyz-timers.h create mode 100644 OSX/jwxyz-timers.m create mode 100644 OSX/jwxyz.h create mode 100644 OSX/jwxyz.m create mode 100644 OSX/main.m create mode 100644 OSX/osxgrabscreen.m create mode 100755 OSX/update-info-plist.pl create mode 100755 OSX/update-thumbnail.pl create mode 100644 OSX/xscreensaver_Prefix.pch create mode 100644 README create mode 100644 README.VMS create mode 100644 README.hacking create mode 100644 aclocal.m4 create mode 100755 config.guess create mode 100644 config.h-vms create mode 100644 config.h.in create mode 100755 config.sub create mode 100755 configure create mode 100644 configure.in create mode 100644 driver/.gdbinit create mode 100644 driver/Makefile.in create mode 100644 driver/README create mode 100644 driver/XScreenSaver-Xm.ad create mode 100644 driver/XScreenSaver.ad.in create mode 100644 driver/XScreenSaver_Xm_ad.h create mode 100644 driver/XScreenSaver_ad.h create mode 100644 driver/auth.h create mode 100644 driver/compile_axp.com create mode 100644 driver/compile_decc.com create mode 100644 driver/demo-Gtk-conf.c create mode 100644 driver/demo-Gtk-conf.h create mode 100644 driver/demo-Gtk-stubs.h create mode 100644 driver/demo-Gtk-support.c create mode 100644 driver/demo-Gtk-support.h create mode 100644 driver/demo-Gtk-widgets.c create mode 100644 driver/demo-Gtk-widgets.h create mode 100644 driver/demo-Gtk.c create mode 100644 driver/demo-Xm-widgets.c create mode 100644 driver/demo-Xm.c create mode 100644 driver/dpms.c create mode 100644 driver/exec.c create mode 100644 driver/exec.h create mode 100644 driver/link_axp.com create mode 100644 driver/link_decc.com create mode 100644 driver/lock.c create mode 100644 driver/mlstring.c create mode 100644 driver/mlstring.h create mode 100644 driver/passwd-helper.c create mode 100644 driver/passwd-kerberos.c create mode 100644 driver/passwd-pam.c create mode 100644 driver/passwd-pwent.c create mode 100644 driver/passwd.c create mode 100644 driver/pdf2jpeg.m create mode 100644 driver/pdf2jpeg.man create mode 100644 driver/prefs.c create mode 100644 driver/prefs.h create mode 100644 driver/remote.c create mode 100644 driver/remote.h create mode 100644 driver/screens.c create mode 100644 driver/screensaver-properties.desktop.in create mode 100644 driver/setuid.c create mode 100644 driver/splash.c create mode 100644 driver/stderr.c create mode 100644 driver/subprocs.c create mode 100644 driver/test-apm.c create mode 100644 driver/test-fade.c create mode 100644 driver/test-grab.c create mode 100644 driver/test-mlstring.c create mode 100644 driver/test-passwd.c create mode 100644 driver/test-randr.c create mode 100644 driver/test-screens.c create mode 100644 driver/test-uid.c create mode 100644 driver/test-vp.c create mode 100644 driver/test-xdpms.c create mode 100644 driver/test-xinerama.c create mode 100644 driver/timers.c create mode 100644 driver/types.h create mode 100644 driver/vms-getpwnam.c create mode 100644 driver/vms-hpwd.c create mode 100644 driver/vms-pwd.h create mode 100644 driver/vms-validate.c create mode 100644 driver/vms_axp.opt create mode 100644 driver/vms_axp_12.opt create mode 100644 driver/vms_decc.opt create mode 100644 driver/vms_decc_12.opt create mode 100644 driver/windows.c create mode 100644 driver/xdpyinfo.c create mode 100644 driver/xscreensaver-command.c create mode 100644 driver/xscreensaver-command.man create mode 100644 driver/xscreensaver-demo.glade2 create mode 100644 driver/xscreensaver-demo.glade2p create mode 100644 driver/xscreensaver-demo.man create mode 100755 driver/xscreensaver-getimage-desktop create mode 100644 driver/xscreensaver-getimage-desktop.man create mode 100755 driver/xscreensaver-getimage-file create mode 100644 driver/xscreensaver-getimage-file.man create mode 100755 driver/xscreensaver-getimage-video create mode 100644 driver/xscreensaver-getimage-video.man create mode 100644 driver/xscreensaver-getimage.c create mode 100644 driver/xscreensaver-getimage.man create mode 100755 driver/xscreensaver-text create mode 100644 driver/xscreensaver-text.man create mode 100644 driver/xscreensaver.c create mode 100644 driver/xscreensaver.h create mode 100644 driver/xscreensaver.man create mode 100644 driver/xscreensaver.pam.in create mode 100644 driver/xset.c create mode 100644 hacks/.gdbinit create mode 100644 hacks/Makefile.in create mode 100644 hacks/README create mode 100644 hacks/abstractile.c create mode 100644 hacks/abstractile.man create mode 100644 hacks/analogtv.c create mode 100644 hacks/analogtv.h create mode 100644 hacks/anemone.c create mode 100644 hacks/anemone.man create mode 100644 hacks/anemotaxis.c create mode 100644 hacks/anemotaxis.man create mode 100644 hacks/ant.c create mode 100644 hacks/ant.man create mode 100644 hacks/apollonian.c create mode 100644 hacks/apollonian.man create mode 100644 hacks/apple2-main.c create mode 100644 hacks/apple2.c create mode 100644 hacks/apple2.h create mode 100644 hacks/apple2.man create mode 100644 hacks/asm6502.c create mode 100644 hacks/asm6502.h create mode 100644 hacks/attraction.c create mode 100644 hacks/attraction.man create mode 100644 hacks/automata.h create mode 100644 hacks/barcode.c create mode 100644 hacks/barcode.man create mode 100644 hacks/blaster.c create mode 100644 hacks/blaster.man create mode 100644 hacks/blitspin.c create mode 100644 hacks/blitspin.man create mode 100644 hacks/bouboule.c create mode 100644 hacks/bouboule.man create mode 100644 hacks/boxfit.c create mode 100644 hacks/boxfit.man create mode 100644 hacks/braid.c create mode 100644 hacks/braid.man create mode 100644 hacks/bsod.c create mode 100644 hacks/bsod.man create mode 100644 hacks/bubbles-default.c create mode 100644 hacks/bubbles.c create mode 100644 hacks/bubbles.h create mode 100644 hacks/bubbles.man create mode 100644 hacks/bumps.c create mode 100644 hacks/bumps.man create mode 100644 hacks/ccurve.c create mode 100644 hacks/ccurve.man create mode 100644 hacks/celtic.c create mode 100644 hacks/celtic.man create mode 100755 hacks/check-configs.pl create mode 100644 hacks/cloudlife.c create mode 100644 hacks/cloudlife.man create mode 100644 hacks/compass.c create mode 100644 hacks/compass.man create mode 100644 hacks/compile_axp.com create mode 100644 hacks/compile_decc.com create mode 100644 hacks/config/README create mode 100644 hacks/config/abstractile.xml create mode 100644 hacks/config/anemone.xml create mode 100644 hacks/config/anemotaxis.xml create mode 100644 hacks/config/ant.xml create mode 100644 hacks/config/antinspect.xml create mode 100644 hacks/config/antmaze.xml create mode 100644 hacks/config/antspotlight.xml create mode 100644 hacks/config/apollonian.xml create mode 100644 hacks/config/apple2.xml create mode 100644 hacks/config/atlantis.xml create mode 100644 hacks/config/attraction.xml create mode 100644 hacks/config/atunnel.xml create mode 100644 hacks/config/barcode.xml create mode 100644 hacks/config/blaster.xml create mode 100644 hacks/config/blinkbox.xml create mode 100644 hacks/config/blitspin.xml create mode 100644 hacks/config/blocktube.xml create mode 100644 hacks/config/boing.xml create mode 100644 hacks/config/bouboule.xml create mode 100644 hacks/config/bouncingcow.xml create mode 100644 hacks/config/boxed.xml create mode 100644 hacks/config/boxfit.xml create mode 100644 hacks/config/braid.xml create mode 100644 hacks/config/bsod.xml create mode 100644 hacks/config/bubble3d.xml create mode 100644 hacks/config/bubbles.xml create mode 100644 hacks/config/bumps.xml create mode 100644 hacks/config/cage.xml create mode 100644 hacks/config/carousel.xml create mode 100644 hacks/config/ccurve.xml create mode 100644 hacks/config/celtic.xml create mode 100644 hacks/config/circuit.xml create mode 100644 hacks/config/cloudlife.xml create mode 100644 hacks/config/companioncube.xml create mode 100644 hacks/config/compass.xml create mode 100644 hacks/config/coral.xml create mode 100644 hacks/config/crackberg.xml create mode 100644 hacks/config/critical.xml create mode 100644 hacks/config/crystal.xml create mode 100644 hacks/config/cube21.xml create mode 100644 hacks/config/cubenetic.xml create mode 100644 hacks/config/cubestorm.xml create mode 100644 hacks/config/cubicgrid.xml create mode 100644 hacks/config/cwaves.xml create mode 100644 hacks/config/cynosure.xml create mode 100644 hacks/config/dangerball.xml create mode 100644 hacks/config/decayscreen.xml create mode 100644 hacks/config/deco.xml create mode 100644 hacks/config/deluxe.xml create mode 100644 hacks/config/demon.xml create mode 100644 hacks/config/discrete.xml create mode 100644 hacks/config/distort.xml create mode 100644 hacks/config/dnalogo.xml create mode 100644 hacks/config/drift.xml create mode 100644 hacks/config/endgame.xml create mode 100644 hacks/config/engine.xml create mode 100644 hacks/config/epicycle.xml create mode 100644 hacks/config/eruption.xml create mode 100644 hacks/config/euler2d.xml create mode 100644 hacks/config/extrusion.xml create mode 100644 hacks/config/fadeplot.xml create mode 100644 hacks/config/fiberlamp.xml create mode 100644 hacks/config/fireworkx.xml create mode 100644 hacks/config/flag.xml create mode 100644 hacks/config/flame.xml create mode 100644 hacks/config/flipflop.xml create mode 100644 hacks/config/flipscreen3d.xml create mode 100644 hacks/config/fliptext.xml create mode 100644 hacks/config/flow.xml create mode 100644 hacks/config/fluidballs.xml create mode 100644 hacks/config/flurry.xml create mode 100644 hacks/config/flyingtoasters.xml create mode 100644 hacks/config/fontglide.xml create mode 100644 hacks/config/forest.xml create mode 100644 hacks/config/fuzzyflakes.xml create mode 100644 hacks/config/galaxy.xml create mode 100644 hacks/config/gears.xml create mode 100644 hacks/config/gflux.xml create mode 100644 hacks/config/glblur.xml create mode 100644 hacks/config/glcells.xml create mode 100644 hacks/config/gleidescope.xml create mode 100644 hacks/config/glforestfire.xml create mode 100644 hacks/config/glhanoi.xml create mode 100644 hacks/config/glknots.xml create mode 100644 hacks/config/glmatrix.xml create mode 100644 hacks/config/glplanet.xml create mode 100644 hacks/config/glschool.xml create mode 100644 hacks/config/glslideshow.xml create mode 100644 hacks/config/glsnake.xml create mode 100644 hacks/config/gltext.xml create mode 100644 hacks/config/goop.xml create mode 100644 hacks/config/grav.xml create mode 100644 hacks/config/greynetic.xml create mode 100644 hacks/config/halftone.xml create mode 100644 hacks/config/halo.xml create mode 100644 hacks/config/helix.xml create mode 100644 hacks/config/hilbert.xml create mode 100644 hacks/config/hopalong.xml create mode 100644 hacks/config/hyperball.xml create mode 100644 hacks/config/hypercube.xml create mode 100644 hacks/config/hypertorus.xml create mode 100644 hacks/config/hypnowheel.xml create mode 100644 hacks/config/ifs.xml create mode 100644 hacks/config/imsmap.xml create mode 100644 hacks/config/interaggregate.xml create mode 100644 hacks/config/interference.xml create mode 100644 hacks/config/intermomentary.xml create mode 100644 hacks/config/jigglypuff.xml create mode 100644 hacks/config/jigsaw.xml create mode 100644 hacks/config/juggle.xml create mode 100644 hacks/config/juggler3d.xml create mode 100644 hacks/config/julia.xml create mode 100644 hacks/config/kaleidescope.xml create mode 100644 hacks/config/klein.xml create mode 100644 hacks/config/kumppa.xml create mode 100644 hacks/config/lament.xml create mode 100644 hacks/config/laser.xml create mode 100644 hacks/config/lavalite.xml create mode 100644 hacks/config/lcdscrub.xml create mode 100644 hacks/config/lightning.xml create mode 100644 hacks/config/lisa.xml create mode 100644 hacks/config/lissie.xml create mode 100644 hacks/config/lmorph.xml create mode 100644 hacks/config/lockward.xml create mode 100644 hacks/config/loop.xml create mode 100644 hacks/config/m6502.xml create mode 100644 hacks/config/maze.xml create mode 100644 hacks/config/memscroller.xml create mode 100644 hacks/config/menger.xml create mode 100644 hacks/config/metaballs.xml create mode 100644 hacks/config/mirrorblob.xml create mode 100644 hacks/config/mismunch.xml create mode 100644 hacks/config/moebius.xml create mode 100644 hacks/config/moebiusgears.xml create mode 100644 hacks/config/moire.xml create mode 100644 hacks/config/moire2.xml create mode 100644 hacks/config/molecule.xml create mode 100644 hacks/config/morph3d.xml create mode 100644 hacks/config/mountain.xml create mode 100644 hacks/config/munch.xml create mode 100644 hacks/config/nerverot.xml create mode 100644 hacks/config/noof.xml create mode 100644 hacks/config/noseguy.xml create mode 100644 hacks/config/pacman.xml create mode 100644 hacks/config/pedal.xml create mode 100644 hacks/config/penetrate.xml create mode 100644 hacks/config/penrose.xml create mode 100644 hacks/config/petri.xml create mode 100644 hacks/config/phosphor.xml create mode 100644 hacks/config/photopile.xml create mode 100644 hacks/config/piecewise.xml create mode 100644 hacks/config/pinion.xml create mode 100644 hacks/config/pipes.xml create mode 100644 hacks/config/polyhedra.xml create mode 100644 hacks/config/polyominoes.xml create mode 100644 hacks/config/polytopes.xml create mode 100644 hacks/config/pong.xml create mode 100644 hacks/config/popsquares.xml create mode 100644 hacks/config/providence.xml create mode 100644 hacks/config/pulsar.xml create mode 100644 hacks/config/pyro.xml create mode 100644 hacks/config/qix.xml create mode 100644 hacks/config/queens.xml create mode 100644 hacks/config/rd-bomb.xml create mode 100644 hacks/config/rdbomb.xml create mode 100644 hacks/config/ripples.xml create mode 100644 hacks/config/rocks.xml create mode 100644 hacks/config/rorschach.xml create mode 100644 hacks/config/rotor.xml create mode 100644 hacks/config/rotzoomer.xml create mode 100644 hacks/config/rubik.xml create mode 100644 hacks/config/rubikblocks.xml create mode 100644 hacks/config/sballs.xml create mode 100644 hacks/config/shadebobs.xml create mode 100644 hacks/config/sierpinski.xml create mode 100644 hacks/config/sierpinski3d.xml create mode 100644 hacks/config/skytentacles.xml create mode 100644 hacks/config/slidescreen.xml create mode 100644 hacks/config/slip.xml create mode 100644 hacks/config/sonar.xml create mode 100644 hacks/config/speedmine.xml create mode 100644 hacks/config/sphere.xml create mode 100644 hacks/config/spheremonics.xml create mode 100644 hacks/config/spiral.xml create mode 100644 hacks/config/spotlight.xml create mode 100644 hacks/config/sproingies.xml create mode 100644 hacks/config/squiral.xml create mode 100644 hacks/config/stairs.xml create mode 100644 hacks/config/starfish.xml create mode 100644 hacks/config/starwars.xml create mode 100644 hacks/config/stonerview.xml create mode 100644 hacks/config/strange.xml create mode 100644 hacks/config/substrate.xml create mode 100644 hacks/config/superquadrics.xml create mode 100644 hacks/config/surfaces.xml create mode 100644 hacks/config/swirl.xml create mode 100644 hacks/config/t3d.xml create mode 100644 hacks/config/tangram.xml create mode 100644 hacks/config/thornbird.xml create mode 100644 hacks/config/timetunnel.xml create mode 100644 hacks/config/topblock.xml create mode 100644 hacks/config/triangle.xml create mode 100644 hacks/config/tronbit.xml create mode 100644 hacks/config/truchet.xml create mode 100644 hacks/config/twang.xml create mode 100644 hacks/config/vermiculate.xml create mode 100644 hacks/config/vidwhacker.xml create mode 100644 hacks/config/vines.xml create mode 100644 hacks/config/voronoi.xml create mode 100644 hacks/config/wander.xml create mode 100644 hacks/config/webcollage.xml create mode 100644 hacks/config/whirlwindwarp.xml create mode 100644 hacks/config/whirlygig.xml create mode 100644 hacks/config/worm.xml create mode 100644 hacks/config/wormhole.xml create mode 100644 hacks/config/xanalogtv.xml create mode 100644 hacks/config/xflame.xml create mode 100644 hacks/config/xjack.xml create mode 100644 hacks/config/xlyap.xml create mode 100644 hacks/config/xmatrix.xml create mode 100644 hacks/config/xrayswarm.xml create mode 100644 hacks/config/xspirograph.xml create mode 100644 hacks/config/xss.dtd create mode 100644 hacks/config/xss.xsd create mode 100644 hacks/config/zoom.xml create mode 100644 hacks/coral.c create mode 100644 hacks/coral.man create mode 100644 hacks/critical.c create mode 100644 hacks/critical.man create mode 100644 hacks/crystal.c create mode 100644 hacks/crystal.man create mode 100644 hacks/cwaves.c create mode 100644 hacks/cwaves.man create mode 100644 hacks/cynosure.c create mode 100644 hacks/cynosure.man create mode 100644 hacks/decayscreen.c create mode 100644 hacks/decayscreen.man create mode 100644 hacks/deco.c create mode 100644 hacks/deco.man create mode 100644 hacks/deluxe.c create mode 100644 hacks/deluxe.man create mode 100644 hacks/demon.c create mode 100644 hacks/demon.man create mode 100644 hacks/discrete.c create mode 100644 hacks/discrete.man create mode 100644 hacks/distort.c create mode 100644 hacks/distort.man create mode 100644 hacks/drift.c create mode 100644 hacks/drift.man create mode 100644 hacks/epicycle.c create mode 100644 hacks/epicycle.man create mode 100644 hacks/eruption.c create mode 100644 hacks/eruption.man create mode 100644 hacks/euler2d.c create mode 100644 hacks/euler2d.man create mode 100644 hacks/euler2d.tex create mode 100644 hacks/fadeplot.c create mode 100644 hacks/fadeplot.man create mode 100644 hacks/fiberlamp.c create mode 100644 hacks/fiberlamp.man create mode 100644 hacks/fireworkx.c create mode 100644 hacks/fireworkx.man create mode 100644 hacks/fireworkx_mmx.S create mode 100644 hacks/flag.c create mode 100644 hacks/flag.man create mode 100644 hacks/flame.c create mode 100644 hacks/flame.man create mode 100644 hacks/flow.c create mode 100644 hacks/flow.man create mode 100644 hacks/fluidballs.c create mode 100644 hacks/fluidballs.man create mode 100644 hacks/fontglide.c create mode 100644 hacks/fontglide.man create mode 100644 hacks/forest.c create mode 100644 hacks/forest.man create mode 100644 hacks/fps.c create mode 100644 hacks/fps.h create mode 100644 hacks/fpsI.h create mode 100644 hacks/fuzzyflakes.c create mode 100644 hacks/fuzzyflakes.man create mode 100644 hacks/galaxy.c create mode 100644 hacks/galaxy.man create mode 100644 hacks/glx/Makefile.in create mode 100644 hacks/glx/README create mode 100644 hacks/glx/antinspect.c create mode 100644 hacks/glx/antinspect.man create mode 100644 hacks/glx/antmaze.c create mode 100644 hacks/glx/antmaze.man create mode 100644 hacks/glx/ants.h create mode 100644 hacks/glx/antspotlight.c create mode 100644 hacks/glx/antspotlight.man create mode 100644 hacks/glx/atlantis.c create mode 100644 hacks/glx/atlantis.h create mode 100644 hacks/glx/atlantis.man create mode 100644 hacks/glx/atunnel.c create mode 100644 hacks/glx/atunnel.man create mode 100644 hacks/glx/b_draw.c create mode 100644 hacks/glx/b_lockglue.c create mode 100644 hacks/glx/b_sphere.c create mode 100644 hacks/glx/blinkbox.c create mode 100644 hacks/glx/blinkbox.man create mode 100644 hacks/glx/blocktube.c create mode 100644 hacks/glx/blocktube.man create mode 100644 hacks/glx/boing.c create mode 100644 hacks/glx/boing.man create mode 100644 hacks/glx/bouncingcow.c create mode 100644 hacks/glx/bouncingcow.man create mode 100644 hacks/glx/boxed.c create mode 100644 hacks/glx/boxed.h create mode 100644 hacks/glx/boxed.man create mode 100644 hacks/glx/bubble3d.c create mode 100644 hacks/glx/bubble3d.h create mode 100644 hacks/glx/bubble3d.man create mode 100644 hacks/glx/buildlwo.c create mode 100644 hacks/glx/buildlwo.h create mode 100644 hacks/glx/cage.c create mode 100644 hacks/glx/cage.man create mode 100644 hacks/glx/carousel.c create mode 100644 hacks/glx/carousel.man create mode 100644 hacks/glx/chessgames.h create mode 100644 hacks/glx/chessmodels.c create mode 100644 hacks/glx/chessmodels.h create mode 100644 hacks/glx/circuit.c create mode 100644 hacks/glx/circuit.man create mode 100644 hacks/glx/companion.c create mode 100644 hacks/glx/companion_disc.c create mode 100644 hacks/glx/companion_heart.c create mode 100644 hacks/glx/companion_quad.c create mode 100644 hacks/glx/companioncube.man create mode 100644 hacks/glx/cow_face.c create mode 100644 hacks/glx/cow_hide.c create mode 100644 hacks/glx/cow_hoofs.c create mode 100644 hacks/glx/cow_horns.c create mode 100644 hacks/glx/cow_tail.c create mode 100644 hacks/glx/cow_udder.c create mode 100644 hacks/glx/crackberg.c create mode 100644 hacks/glx/crackberg.man create mode 100644 hacks/glx/cube21.c create mode 100644 hacks/glx/cube21.man create mode 100644 hacks/glx/cubenetic.c create mode 100644 hacks/glx/cubenetic.man create mode 100644 hacks/glx/cubestorm.c create mode 100644 hacks/glx/cubestorm.man create mode 100644 hacks/glx/cubicgrid.c create mode 100644 hacks/glx/cubicgrid.man create mode 100644 hacks/glx/dangerball.c create mode 100644 hacks/glx/dangerball.man create mode 100644 hacks/glx/dnalogo.c create mode 100644 hacks/glx/dnapizza.h create mode 100644 hacks/glx/dolphin.c create mode 100644 hacks/glx/dropshadow.c create mode 100644 hacks/glx/dropshadow.h create mode 100755 hacks/glx/dxf2gl.pl create mode 100644 hacks/glx/e_textures.h create mode 100644 hacks/glx/endgame.c create mode 100644 hacks/glx/endgame.man create mode 100644 hacks/glx/engine.c create mode 100644 hacks/glx/engine.man create mode 100644 hacks/glx/extrusion-helix2.c create mode 100644 hacks/glx/extrusion-helix3.c create mode 100644 hacks/glx/extrusion-helix4.c create mode 100644 hacks/glx/extrusion-joinoffset.c create mode 100644 hacks/glx/extrusion-screw.c create mode 100644 hacks/glx/extrusion-taper.c create mode 100644 hacks/glx/extrusion-twistoid.c create mode 100644 hacks/glx/extrusion.c create mode 100644 hacks/glx/extrusion.h create mode 100644 hacks/glx/extrusion.man create mode 100644 hacks/glx/flipflop.c create mode 100644 hacks/glx/flipflop.man create mode 100644 hacks/glx/flipscreen3d.c create mode 100644 hacks/glx/flipscreen3d.man create mode 100644 hacks/glx/fliptext.c create mode 100644 hacks/glx/fliptext.man create mode 100644 hacks/glx/flurry-smoke.c create mode 100644 hacks/glx/flurry-spark.c create mode 100644 hacks/glx/flurry-star.c create mode 100644 hacks/glx/flurry-texture.c create mode 100644 hacks/glx/flurry.c create mode 100644 hacks/glx/flurry.h create mode 100644 hacks/glx/flurry.man create mode 100644 hacks/glx/flyingtoasters.c create mode 100644 hacks/glx/flyingtoasters.man create mode 100644 hacks/glx/font-ximage.c create mode 100644 hacks/glx/font-ximage.h create mode 100644 hacks/glx/fps-gl.c create mode 100644 hacks/glx/gears.c create mode 100644 hacks/glx/gears.man create mode 100644 hacks/glx/gflux.c create mode 100644 hacks/glx/gflux.man create mode 100644 hacks/glx/glblur.c create mode 100644 hacks/glx/glblur.man create mode 100644 hacks/glx/glcells.c create mode 100644 hacks/glx/glcells.man create mode 100644 hacks/glx/gleidescope.c create mode 100644 hacks/glx/gleidescope.man create mode 100644 hacks/glx/glforestfire.c create mode 100644 hacks/glx/glforestfire.man create mode 100644 hacks/glx/glhanoi.c create mode 100644 hacks/glx/glhanoi.man create mode 100644 hacks/glx/glknots.c create mode 100644 hacks/glx/glknots.man create mode 100644 hacks/glx/gllist.c create mode 100644 hacks/glx/gllist.h create mode 100644 hacks/glx/glmatrix.c create mode 100644 hacks/glx/glmatrix.man create mode 100644 hacks/glx/glplanet.c create mode 100644 hacks/glx/glplanet.man create mode 100644 hacks/glx/glschool.c create mode 100644 hacks/glx/glschool.h create mode 100644 hacks/glx/glschool.man create mode 100644 hacks/glx/glschool_alg.c create mode 100644 hacks/glx/glschool_alg.h create mode 100644 hacks/glx/glschool_gl.c create mode 100644 hacks/glx/glschool_gl.h create mode 100644 hacks/glx/glslideshow.c create mode 100644 hacks/glx/glslideshow.man create mode 100644 hacks/glx/glsnake.c create mode 100644 hacks/glx/glsnake.man create mode 100644 hacks/glx/gltext.c create mode 100644 hacks/glx/gltext.man create mode 100644 hacks/glx/gltrackball.c create mode 100644 hacks/glx/gltrackball.h create mode 100644 hacks/glx/glut_roman.h create mode 100644 hacks/glx/glut_stroke.c create mode 100644 hacks/glx/glut_swidth.c create mode 100644 hacks/glx/glutstroke.h create mode 100644 hacks/glx/glxfonts.c create mode 100644 hacks/glx/glxfonts.h create mode 100644 hacks/glx/grab-ximage.c create mode 100644 hacks/glx/grab-ximage.h create mode 100644 hacks/glx/hilbert.c create mode 100644 hacks/glx/hilbert.man create mode 100644 hacks/glx/hypertorus.c create mode 100644 hacks/glx/hypertorus.man create mode 100644 hacks/glx/hypnowheel.c create mode 100644 hacks/glx/hypnowheel.man create mode 100644 hacks/glx/involute.c create mode 100644 hacks/glx/involute.h create mode 100644 hacks/glx/jigglypuff.c create mode 100644 hacks/glx/jigglypuff.man create mode 100644 hacks/glx/jigsaw.c create mode 100644 hacks/glx/jigsaw.man create mode 100644 hacks/glx/juggler3d.c create mode 100644 hacks/glx/juggler3d.man create mode 100644 hacks/glx/jwzgles.c create mode 100644 hacks/glx/jwzgles.h create mode 100644 hacks/glx/jwzglesI.h create mode 100644 hacks/glx/klein.c create mode 100644 hacks/glx/klein.man create mode 100644 hacks/glx/lament.c create mode 100644 hacks/glx/lament.man create mode 100644 hacks/glx/lavalite.c create mode 100644 hacks/glx/lavalite.man create mode 100644 hacks/glx/lockward.c create mode 100644 hacks/glx/lockward.man create mode 100644 hacks/glx/marching.c create mode 100644 hacks/glx/marching.h create mode 100644 hacks/glx/menger.c create mode 100644 hacks/glx/menger.man create mode 100644 hacks/glx/mirrorblob.c create mode 100644 hacks/glx/mirrorblob.man create mode 100644 hacks/glx/moebius.c create mode 100644 hacks/glx/moebius.man create mode 100644 hacks/glx/moebiusgears.c create mode 100644 hacks/glx/moebiusgears.man create mode 100644 hacks/glx/molecule.c create mode 100644 hacks/glx/molecule.man create mode 100755 hacks/glx/molecules.sh create mode 100644 hacks/glx/morph3d.c create mode 100644 hacks/glx/morph3d.man create mode 100644 hacks/glx/noof.c create mode 100644 hacks/glx/noof.man create mode 100644 hacks/glx/normals.c create mode 100644 hacks/glx/normals.h create mode 100644 hacks/glx/photopile.c create mode 100644 hacks/glx/photopile.man create mode 100644 hacks/glx/pinion.c create mode 100644 hacks/glx/pinion.man create mode 100644 hacks/glx/pipeobjs.c create mode 100644 hacks/glx/pipes.c create mode 100644 hacks/glx/pipes.man create mode 100644 hacks/glx/polyhedra-gl.c create mode 100644 hacks/glx/polyhedra.c create mode 100644 hacks/glx/polyhedra.h create mode 100644 hacks/glx/polyhedra.man create mode 100644 hacks/glx/polytopes.c create mode 100644 hacks/glx/polytopes.man create mode 100644 hacks/glx/providence.c create mode 100644 hacks/glx/providence.man create mode 100644 hacks/glx/pulsar.c create mode 100644 hacks/glx/pulsar.man create mode 100644 hacks/glx/queens.c create mode 100644 hacks/glx/queens.man create mode 100644 hacks/glx/rotator.c create mode 100644 hacks/glx/rotator.h create mode 100644 hacks/glx/rubik.c create mode 100644 hacks/glx/rubik.man create mode 100644 hacks/glx/rubikblocks.c create mode 100644 hacks/glx/rubikblocks.man create mode 100644 hacks/glx/s1_1.c create mode 100644 hacks/glx/s1_2.c create mode 100644 hacks/glx/s1_3.c create mode 100644 hacks/glx/s1_4.c create mode 100644 hacks/glx/s1_5.c create mode 100644 hacks/glx/s1_6.c create mode 100644 hacks/glx/s1_b.c create mode 100644 hacks/glx/sballs.c create mode 100644 hacks/glx/sballs.man create mode 100644 hacks/glx/shark.c create mode 100644 hacks/glx/sierpinski3d.c create mode 100644 hacks/glx/sierpinski3d.man create mode 100644 hacks/glx/skytentacles.c create mode 100644 hacks/glx/skytentacles.man create mode 100644 hacks/glx/sonar-icmp.c create mode 100644 hacks/glx/sonar-sim.c create mode 100644 hacks/glx/sonar.c create mode 100644 hacks/glx/sonar.h create mode 100644 hacks/glx/sonar.man create mode 100644 hacks/glx/sphere.c create mode 100644 hacks/glx/sphere.h create mode 100644 hacks/glx/spheremonics.c create mode 100644 hacks/glx/spheremonics.man create mode 100644 hacks/glx/sproingies.c create mode 100644 hacks/glx/sproingies.h create mode 100644 hacks/glx/sproingies.man create mode 100644 hacks/glx/sproingiewrap.c create mode 100644 hacks/glx/stairs.c create mode 100644 hacks/glx/stairs.man create mode 100644 hacks/glx/starwars.c create mode 100644 hacks/glx/starwars.h create mode 100644 hacks/glx/starwars.man create mode 100644 hacks/glx/starwars.txt create mode 100644 hacks/glx/stonerview-move.c create mode 100644 hacks/glx/stonerview-move.h create mode 100644 hacks/glx/stonerview-osc.c create mode 100644 hacks/glx/stonerview-osc.h create mode 100644 hacks/glx/stonerview-view.c create mode 100644 hacks/glx/stonerview.c create mode 100644 hacks/glx/stonerview.h create mode 100644 hacks/glx/stonerview.man create mode 100644 hacks/glx/superquadrics.c create mode 100644 hacks/glx/superquadrics.man create mode 100644 hacks/glx/surfaces.c create mode 100644 hacks/glx/surfaces.man create mode 100644 hacks/glx/swim.c create mode 100644 hacks/glx/tangram.c create mode 100644 hacks/glx/tangram.man create mode 100644 hacks/glx/tangram_shapes.c create mode 100644 hacks/glx/tangram_shapes.h create mode 100644 hacks/glx/teapot.c create mode 100644 hacks/glx/teapot.h create mode 100644 hacks/glx/teapot2.h create mode 100644 hacks/glx/texfont.c create mode 100644 hacks/glx/texfont.h create mode 100644 hacks/glx/timetunnel.c create mode 100644 hacks/glx/timetunnel.man create mode 100644 hacks/glx/toast.c create mode 100644 hacks/glx/toast2.c create mode 100644 hacks/glx/toaster.c create mode 100644 hacks/glx/toaster_base.c create mode 100644 hacks/glx/toaster_handle.c create mode 100644 hacks/glx/toaster_handle2.c create mode 100644 hacks/glx/toaster_jet.c create mode 100644 hacks/glx/toaster_knob.c create mode 100644 hacks/glx/toaster_slots.c create mode 100644 hacks/glx/toaster_wing.c create mode 100644 hacks/glx/topblock.c create mode 100644 hacks/glx/topblock.h create mode 100644 hacks/glx/topblock.man create mode 100644 hacks/glx/trackball.c create mode 100644 hacks/glx/trackball.h create mode 100644 hacks/glx/tronbit.c create mode 100644 hacks/glx/tronbit.man create mode 100644 hacks/glx/tronbit_idle1.c create mode 100644 hacks/glx/tronbit_idle2.c create mode 100644 hacks/glx/tronbit_no.c create mode 100644 hacks/glx/tronbit_yes.c create mode 100644 hacks/glx/tube.c create mode 100644 hacks/glx/tube.h create mode 100644 hacks/glx/tunnel_draw.c create mode 100644 hacks/glx/tunnel_draw.h create mode 100644 hacks/glx/voronoi.c create mode 100644 hacks/glx/voronoi.man create mode 100755 hacks/glx/vrml2gl.pl create mode 100755 hacks/glx/wfront2gl.pl create mode 100644 hacks/glx/whale.c create mode 100644 hacks/glx/xlock-gl-utils.c create mode 100644 hacks/glx/xpm-ximage.c create mode 100644 hacks/glx/xpm-ximage.h create mode 100644 hacks/glx/xscreensaver-gl-helper.c create mode 100644 hacks/glx/xscreensaver-gl-helper.man create mode 100644 hacks/goop.c create mode 100644 hacks/goop.man create mode 100644 hacks/grav.c create mode 100644 hacks/grav.man create mode 100644 hacks/greynetic.c create mode 100644 hacks/greynetic.man create mode 100644 hacks/halftone.c create mode 100644 hacks/halftone.man create mode 100644 hacks/halo.c create mode 100644 hacks/halo.man create mode 100644 hacks/helix.c create mode 100644 hacks/helix.man create mode 100644 hacks/hopalong.c create mode 100644 hacks/hopalong.man create mode 100644 hacks/hyperball.c create mode 100644 hacks/hyperball.man create mode 100644 hacks/hypercube.c create mode 100644 hacks/hypercube.man create mode 100644 hacks/ifs.c create mode 100644 hacks/ifs.man create mode 100644 hacks/images/6x10font.xbm create mode 100644 hacks/images/amiga.xpm create mode 100644 hacks/images/apple2font.xbm create mode 100644 hacks/images/atari.xbm create mode 100644 hacks/images/atm.xbm create mode 100644 hacks/images/blocktube.xpm create mode 100644 hacks/images/bob.xbm create mode 100644 hacks/images/bubbles/blood.pov create mode 100644 hacks/images/bubbles/blood1.xpm create mode 100644 hacks/images/bubbles/blood10.xpm create mode 100644 hacks/images/bubbles/blood11.xpm create mode 100644 hacks/images/bubbles/blood2.xpm create mode 100644 hacks/images/bubbles/blood3.xpm create mode 100644 hacks/images/bubbles/blood4.xpm create mode 100644 hacks/images/bubbles/blood5.xpm create mode 100644 hacks/images/bubbles/blood6.xpm create mode 100644 hacks/images/bubbles/blood7.xpm create mode 100644 hacks/images/bubbles/blood8.xpm create mode 100644 hacks/images/bubbles/blood9.xpm create mode 100644 hacks/images/bubbles/blue.pov create mode 100644 hacks/images/bubbles/blue1.xpm create mode 100644 hacks/images/bubbles/blue10.xpm create mode 100644 hacks/images/bubbles/blue11.xpm create mode 100644 hacks/images/bubbles/blue2.xpm create mode 100644 hacks/images/bubbles/blue3.xpm create mode 100644 hacks/images/bubbles/blue4.xpm create mode 100644 hacks/images/bubbles/blue5.xpm create mode 100644 hacks/images/bubbles/blue6.xpm create mode 100644 hacks/images/bubbles/blue7.xpm create mode 100644 hacks/images/bubbles/blue8.xpm create mode 100644 hacks/images/bubbles/blue9.xpm create mode 100644 hacks/images/bubbles/glass.pov create mode 100644 hacks/images/bubbles/glass1.xpm create mode 100644 hacks/images/bubbles/glass10.xpm create mode 100644 hacks/images/bubbles/glass11.xpm create mode 100644 hacks/images/bubbles/glass2.xpm create mode 100644 hacks/images/bubbles/glass3.xpm create mode 100644 hacks/images/bubbles/glass4.xpm create mode 100644 hacks/images/bubbles/glass5.xpm create mode 100644 hacks/images/bubbles/glass6.xpm create mode 100644 hacks/images/bubbles/glass7.xpm create mode 100644 hacks/images/bubbles/glass8.xpm create mode 100644 hacks/images/bubbles/glass9.xpm create mode 100644 hacks/images/bubbles/jade.pov create mode 100644 hacks/images/bubbles/jade1.xpm create mode 100644 hacks/images/bubbles/jade10.xpm create mode 100644 hacks/images/bubbles/jade11.xpm create mode 100644 hacks/images/bubbles/jade2.xpm create mode 100644 hacks/images/bubbles/jade3.xpm create mode 100644 hacks/images/bubbles/jade4.xpm create mode 100644 hacks/images/bubbles/jade5.xpm create mode 100644 hacks/images/bubbles/jade6.xpm create mode 100644 hacks/images/bubbles/jade7.xpm create mode 100644 hacks/images/bubbles/jade8.xpm create mode 100644 hacks/images/bubbles/jade9.xpm create mode 100644 hacks/images/chromesphere.xpm create mode 100644 hacks/images/earth.xpm create mode 100644 hacks/images/ground.xpm create mode 100644 hacks/images/hmac.xpm create mode 100644 hacks/images/jigglymap.xpm create mode 100644 hacks/images/lament128.xpm create mode 100644 hacks/images/lament512.xpm create mode 100644 hacks/images/m6502/amiga.asm create mode 100644 hacks/images/m6502/breakout.asm create mode 100644 hacks/images/m6502/byterun.asm create mode 100644 hacks/images/m6502/cellular-30.asm create mode 100644 hacks/images/m6502/cellular-600.asm create mode 100644 hacks/images/m6502/colors.asm create mode 100644 hacks/images/m6502/crunch6502.asm create mode 100644 hacks/images/m6502/demoscene.asm create mode 100644 hacks/images/m6502/disco.asm create mode 100644 hacks/images/m6502/dmsc.asm create mode 100644 hacks/images/m6502/dragon-fractal.asm create mode 100644 hacks/images/m6502/fullscreenlogo.asm create mode 100644 hacks/images/m6502/keftal.asm create mode 100644 hacks/images/m6502/matrix.asm create mode 100644 hacks/images/m6502/noise.asm create mode 100644 hacks/images/m6502/random-walk.asm create mode 100644 hacks/images/m6502/random.asm create mode 100644 hacks/images/m6502/random2.asm create mode 100644 hacks/images/m6502/rorschach.asm create mode 100644 hacks/images/m6502/santa.asm create mode 100644 hacks/images/m6502/selfmodify.asm create mode 100644 hacks/images/m6502/sierpinsky.asm create mode 100644 hacks/images/m6502/softsprite.asm create mode 100644 hacks/images/m6502/spacer.asm create mode 100644 hacks/images/m6502/starfield2d.asm create mode 100644 hacks/images/m6502/wave6502.asm create mode 100644 hacks/images/m6502/zookeeper.asm create mode 100644 hacks/images/mac.xbm create mode 100644 hacks/images/macbomb.xbm create mode 100644 hacks/images/matrix1.xbm create mode 100644 hacks/images/matrix1.xpm create mode 100644 hacks/images/matrix1b.xbm create mode 100644 hacks/images/matrix1b.xpm create mode 100644 hacks/images/matrix2.xbm create mode 100644 hacks/images/matrix2.xpm create mode 100644 hacks/images/matrix2b.xbm create mode 100644 hacks/images/matrix2b.xpm create mode 100644 hacks/images/matrix3.xpm create mode 100644 hacks/images/molecules/adenine.pdb create mode 100644 hacks/images/molecules/adrenochrome.pdb create mode 100644 hacks/images/molecules/bucky.pdb create mode 100644 hacks/images/molecules/caffeine.pdb create mode 100644 hacks/images/molecules/capsaicin.pdb create mode 100644 hacks/images/molecules/chlordecone.pdb create mode 100644 hacks/images/molecules/cocaine.pdb create mode 100644 hacks/images/molecules/codeine.pdb create mode 100644 hacks/images/molecules/cyclohexane.pdb create mode 100644 hacks/images/molecules/cytosine.pdb create mode 100644 hacks/images/molecules/dna.pdb create mode 100644 hacks/images/molecules/dodecahedrane.pdb create mode 100644 hacks/images/molecules/dthc.pdb create mode 100644 hacks/images/molecules/dynamite.pdb create mode 100644 hacks/images/molecules/glycol.pdb create mode 100644 hacks/images/molecules/guanine.pdb create mode 100644 hacks/images/molecules/heroin.pdb create mode 100644 hacks/images/molecules/hexahelicene.pdb create mode 100644 hacks/images/molecules/ibuprofen.pdb create mode 100644 hacks/images/molecules/lsd.pdb create mode 100644 hacks/images/molecules/menthol.pdb create mode 100644 hacks/images/molecules/mescaline.pdb create mode 100644 hacks/images/molecules/methamphetamine.pdb create mode 100644 hacks/images/molecules/morphine.pdb create mode 100644 hacks/images/molecules/nicotine.pdb create mode 100644 hacks/images/molecules/novocaine.pdb create mode 100644 hacks/images/molecules/olestra.pdb create mode 100644 hacks/images/molecules/penicillin.pdb create mode 100644 hacks/images/molecules/salvinorin.pdb create mode 100644 hacks/images/molecules/sarin.pdb create mode 100644 hacks/images/molecules/strychnine.pdb create mode 100644 hacks/images/molecules/sucrose.pdb create mode 100644 hacks/images/molecules/thalidomide.pdb create mode 100644 hacks/images/molecules/thymine.pdb create mode 100644 hacks/images/molecules/viagra.pdb create mode 100644 hacks/images/molecules/vitaminb6.pdb create mode 100644 hacks/images/molecules/vitaminc.pdb create mode 100644 hacks/images/molecules/vx.pdb create mode 100644 hacks/images/noseguy/nose-f1.xbm create mode 100644 hacks/images/noseguy/nose-f1.xpm create mode 100644 hacks/images/noseguy/nose-f2.xbm create mode 100644 hacks/images/noseguy/nose-f2.xpm create mode 100644 hacks/images/noseguy/nose-f3.xbm create mode 100644 hacks/images/noseguy/nose-f3.xpm create mode 100644 hacks/images/noseguy/nose-f4.xbm create mode 100644 hacks/images/noseguy/nose-f4.xpm create mode 100644 hacks/images/noseguy/nose-l1.xbm create mode 100644 hacks/images/noseguy/nose-l1.xpm create mode 100644 hacks/images/noseguy/nose-l2.xbm create mode 100644 hacks/images/noseguy/nose-l2.xpm create mode 100644 hacks/images/noseguy/nose-r1.xbm create mode 100644 hacks/images/noseguy/nose-r1.xpm create mode 100644 hacks/images/noseguy/nose-r2.xbm create mode 100644 hacks/images/noseguy/nose-r2.xpm create mode 100644 hacks/images/osx_10_2.xpm create mode 100644 hacks/images/osx_10_3.xpm create mode 100644 hacks/images/pacman/eyes-d.xpm create mode 100644 hacks/images/pacman/eyes-l.xpm create mode 100644 hacks/images/pacman/eyes-r.xpm create mode 100644 hacks/images/pacman/eyes-u.xpm create mode 100644 hacks/images/pacman/ghost-d1.xpm create mode 100644 hacks/images/pacman/ghost-d2.xpm create mode 100644 hacks/images/pacman/ghost-l1.xpm create mode 100644 hacks/images/pacman/ghost-l2.xpm create mode 100644 hacks/images/pacman/ghost-mask.xpm create mode 100644 hacks/images/pacman/ghost-r1.xpm create mode 100644 hacks/images/pacman/ghost-r2.xpm create mode 100644 hacks/images/pacman/ghost-s1.xpm create mode 100644 hacks/images/pacman/ghost-s2.xpm create mode 100644 hacks/images/pacman/ghost-sf1.xpm create mode 100644 hacks/images/pacman/ghost-sf2.xpm create mode 100644 hacks/images/pacman/ghost-u1.xpm create mode 100644 hacks/images/pacman/ghost-u2.xpm create mode 100644 hacks/images/pacman/pacman-0.xpm create mode 100644 hacks/images/pacman/pacman-d1.xpm create mode 100644 hacks/images/pacman/pacman-d2.xpm create mode 100644 hacks/images/pacman/pacman-ds1.xpm create mode 100644 hacks/images/pacman/pacman-ds2.xpm create mode 100644 hacks/images/pacman/pacman-ds3.xpm create mode 100644 hacks/images/pacman/pacman-ds4.xpm create mode 100644 hacks/images/pacman/pacman-ds5.xpm create mode 100644 hacks/images/pacman/pacman-ds6.xpm create mode 100644 hacks/images/pacman/pacman-ds7.xpm create mode 100644 hacks/images/pacman/pacman-ds8.xpm create mode 100644 hacks/images/pacman/pacman-l1.xpm create mode 100644 hacks/images/pacman/pacman-l2.xpm create mode 100644 hacks/images/pacman/pacman-r1.xpm create mode 100644 hacks/images/pacman/pacman-r2.xpm create mode 100644 hacks/images/pacman/pacman-u1.xpm create mode 100644 hacks/images/pacman/pacman-u2.xpm create mode 100644 hacks/images/sball-bg.xpm create mode 100644 hacks/images/sball.xpm create mode 100644 hacks/images/scales.xpm create mode 100644 hacks/images/sea-texture.xpm create mode 100644 hacks/images/som.xbm create mode 100644 hacks/images/timetunnel0.xpm create mode 100644 hacks/images/timetunnel1.xpm create mode 100644 hacks/images/timetunnel2.xpm create mode 100644 hacks/images/toast.xpm create mode 100644 hacks/images/tree.xpm create mode 100644 hacks/images/tunnel0.xpm create mode 100644 hacks/images/tunnel1.xpm create mode 100644 hacks/images/tunnel2.xpm create mode 100644 hacks/images/tunnel3.xpm create mode 100644 hacks/images/tunnel4.xpm create mode 100644 hacks/images/tunnel5.xpm create mode 100644 hacks/images/tunnelstar.xpm create mode 100644 hacks/images/wood.xpm create mode 100644 hacks/imsmap.c create mode 100644 hacks/imsmap.man create mode 100644 hacks/interaggregate.c create mode 100644 hacks/interaggregate.man create mode 100644 hacks/interference.c create mode 100644 hacks/interference.man create mode 100644 hacks/intermomentary.c create mode 100644 hacks/intermomentary.man create mode 100644 hacks/juggle.c create mode 100644 hacks/juggle.man create mode 100644 hacks/julia.c create mode 100644 hacks/julia.man create mode 100644 hacks/kaleidescope.c create mode 100644 hacks/kaleidescope.man create mode 100644 hacks/kumppa.c create mode 100644 hacks/kumppa.man create mode 100644 hacks/laser.c create mode 100644 hacks/laser.man create mode 100644 hacks/lcdscrub.c create mode 100644 hacks/lcdscrub.man create mode 100644 hacks/lightning.c create mode 100644 hacks/lightning.man create mode 100644 hacks/link_axp.com create mode 100644 hacks/link_decc.com create mode 100644 hacks/lisa.c create mode 100644 hacks/lisa.man create mode 100644 hacks/lissie.c create mode 100644 hacks/lissie.man create mode 100755 hacks/ljlatest create mode 100644 hacks/ljlatest.man create mode 100644 hacks/lmorph.c create mode 100644 hacks/lmorph.man create mode 100644 hacks/loop.c create mode 100644 hacks/loop.man create mode 100644 hacks/m6502.c create mode 100755 hacks/m6502.sh create mode 100644 hacks/maze.c create mode 100644 hacks/maze.man create mode 100644 hacks/memscroller.c create mode 100644 hacks/memscroller.man create mode 100644 hacks/metaballs.c create mode 100644 hacks/metaballs.man create mode 100644 hacks/moire.c create mode 100644 hacks/moire.man create mode 100644 hacks/moire2.c create mode 100644 hacks/moire2.man create mode 100644 hacks/mountain.c create mode 100644 hacks/mountain.man create mode 100644 hacks/munch.c create mode 100644 hacks/munch.man create mode 100755 hacks/munge-ad.pl create mode 100644 hacks/nerverot.c create mode 100644 hacks/nerverot.man create mode 100644 hacks/noseguy.c create mode 100644 hacks/noseguy.man create mode 100644 hacks/pacman.c create mode 100644 hacks/pacman.h create mode 100644 hacks/pacman.man create mode 100644 hacks/pacman_ai.c create mode 100644 hacks/pacman_ai.h create mode 100644 hacks/pacman_level.c create mode 100644 hacks/pacman_level.h create mode 100644 hacks/pedal.c create mode 100644 hacks/pedal.man create mode 100644 hacks/penetrate.c create mode 100644 hacks/penetrate.man create mode 100644 hacks/penrose.c create mode 100644 hacks/penrose.man create mode 100644 hacks/petri.c create mode 100644 hacks/petri.man create mode 100644 hacks/phosphor.c create mode 100644 hacks/phosphor.man create mode 100644 hacks/piecewise.c create mode 100644 hacks/piecewise.man create mode 100644 hacks/polyominoes.c create mode 100644 hacks/polyominoes.man create mode 100644 hacks/pong.c create mode 100644 hacks/pong.man create mode 100644 hacks/popsquares.c create mode 100644 hacks/pyro.c create mode 100644 hacks/pyro.man create mode 100644 hacks/qix.c create mode 100644 hacks/qix.man create mode 100644 hacks/rd-bomb.c create mode 100644 hacks/rd-bomb.man create mode 100644 hacks/ripples.c create mode 100644 hacks/ripples.man create mode 100644 hacks/rocks.c create mode 100644 hacks/rocks.man create mode 100644 hacks/rorschach.c create mode 100644 hacks/rorschach.man create mode 100644 hacks/rotor.c create mode 100644 hacks/rotor.man create mode 100644 hacks/rotzoomer.c create mode 100644 hacks/rotzoomer.man create mode 100644 hacks/screenhack.c create mode 100644 hacks/screenhack.h create mode 100644 hacks/screenhackI.h create mode 100644 hacks/shadebobs.c create mode 100644 hacks/shadebobs.man create mode 100644 hacks/sierpinski.c create mode 100644 hacks/sierpinski.man create mode 100644 hacks/slidescreen.c create mode 100644 hacks/slidescreen.man create mode 100644 hacks/slip.c create mode 100644 hacks/slip.man create mode 100644 hacks/speedmine.c create mode 100644 hacks/speedmine.man create mode 100644 hacks/sphere.c create mode 100644 hacks/sphere.man create mode 100644 hacks/spiral.c create mode 100644 hacks/spiral.man create mode 100644 hacks/spotlight.c create mode 100644 hacks/spotlight.man create mode 100644 hacks/squiral.c create mode 100644 hacks/squiral.man create mode 100644 hacks/starfish.c create mode 100644 hacks/starfish.man create mode 100644 hacks/strange.c create mode 100644 hacks/strange.man create mode 100644 hacks/substrate.c create mode 100644 hacks/substrate.man create mode 100644 hacks/swirl.c create mode 100644 hacks/swirl.man create mode 100644 hacks/t3d.c create mode 100644 hacks/t3d.man create mode 100644 hacks/thornbird.c create mode 100644 hacks/thornbird.man create mode 100644 hacks/triangle.c create mode 100644 hacks/triangle.man create mode 100644 hacks/truchet.c create mode 100644 hacks/truchet.man create mode 100644 hacks/twang.c create mode 100644 hacks/twang.man create mode 100644 hacks/vermiculate.c create mode 100644 hacks/vermiculate.man create mode 100755 hacks/vidwhacker create mode 100644 hacks/vidwhacker.man create mode 100644 hacks/vines.c create mode 100644 hacks/vines.man create mode 100644 hacks/vms_axp.opt create mode 100644 hacks/vms_axp_12.opt create mode 100644 hacks/vms_decc.opt create mode 100644 hacks/vms_decc_12.opt create mode 100644 hacks/wander.c create mode 100644 hacks/wander.man create mode 100755 hacks/webcollage create mode 100644 hacks/webcollage-cocoa.m create mode 100644 hacks/webcollage-helper-cocoa.m create mode 100644 hacks/webcollage-helper.c create mode 100644 hacks/webcollage.man create mode 100644 hacks/whirlwindwarp.c create mode 100644 hacks/whirlwindwarp.man create mode 100644 hacks/whirlygig.c create mode 100644 hacks/whirlygig.man create mode 100644 hacks/worm.c create mode 100644 hacks/worm.man create mode 100644 hacks/wormhole.c create mode 100644 hacks/wormhole.man create mode 100644 hacks/xanalogtv.c create mode 100644 hacks/xanalogtv.man create mode 100644 hacks/xflame.c create mode 100644 hacks/xflame.man create mode 100644 hacks/xjack.c create mode 100644 hacks/xjack.man create mode 100644 hacks/xlockmore.c create mode 100644 hacks/xlockmore.h create mode 100644 hacks/xlockmoreI.h create mode 100644 hacks/xlyap.c create mode 100644 hacks/xlyap.man create mode 100644 hacks/xmatrix.c create mode 100644 hacks/xmatrix.man create mode 100755 hacks/xml2man.pl create mode 100644 hacks/xpm-pixmap.c create mode 100644 hacks/xpm-pixmap.h create mode 100644 hacks/xrayswarm.c create mode 100644 hacks/xrayswarm.man create mode 100644 hacks/xscreensaver-sgigl.c create mode 100644 hacks/xspirograph.c create mode 100644 hacks/xspirograph.man create mode 100644 hacks/xsublim.c create mode 100644 hacks/xsublim.man create mode 100644 hacks/zoom.c create mode 100644 hacks/zoom.man create mode 100644 install-sh create mode 100644 intltool-extract.in create mode 100644 intltool-merge.in create mode 100644 intltool-update.in create mode 100644 makevms.com create mode 100644 po/ChangeLog create mode 100644 po/Makefile.in.in create mode 100644 po/POTFILES.in create mode 100644 po/ca.po create mode 100644 po/da.po create mode 100644 po/de.po create mode 100644 po/es.po create mode 100644 po/et.po create mode 100644 po/fi.po create mode 100644 po/fr.po create mode 100644 po/hu.po create mode 100644 po/it.po create mode 100644 po/ja.po create mode 100644 po/ko.po create mode 100644 po/nb.po create mode 100644 po/nl.po create mode 100644 po/pl.po create mode 100644 po/pt.po create mode 100644 po/pt_BR.po create mode 100644 po/ru.po create mode 100644 po/sk.po create mode 100644 po/sv.po create mode 100755 po/update.sh create mode 100644 po/vi.po create mode 100644 po/wa.po create mode 100644 po/zh_CN.po create mode 100644 po/zh_TW.po create mode 100644 setup.com create mode 100644 utils/Makefile.in create mode 100644 utils/README create mode 100755 utils/ad2c create mode 100644 utils/alpha.c create mode 100644 utils/alpha.h create mode 100644 utils/colorbars.c create mode 100644 utils/colorbars.h create mode 100644 utils/colors.c create mode 100644 utils/colors.h create mode 100644 utils/compile_axp.com create mode 100644 utils/compile_decc.com create mode 100644 utils/erase.c create mode 100644 utils/erase.h create mode 100644 utils/fade.c create mode 100644 utils/fade.h create mode 100644 utils/grabclient.c create mode 100644 utils/grabscreen.c create mode 100644 utils/grabscreen.h create mode 100644 utils/hsv.c create mode 100644 utils/hsv.h create mode 100644 utils/images/logo-180.gif create mode 100644 utils/images/logo-180.xpm create mode 100644 utils/images/logo-50.gif create mode 100644 utils/images/logo-50.xpm create mode 100644 utils/images/logo-big.gif create mode 100644 utils/images/logo.eps create mode 100644 utils/images/screensaver-cmndln.png create mode 100644 utils/images/screensaver-colorselector.png create mode 100644 utils/images/screensaver-diagnostic.png create mode 100644 utils/images/screensaver-locking.png create mode 100644 utils/images/screensaver-power.png create mode 100644 utils/images/screensaver-snap.png create mode 100644 utils/logo.c create mode 100644 utils/minixpm.c create mode 100644 utils/minixpm.h create mode 100644 utils/overlay.c create mode 100644 utils/resources.c create mode 100644 utils/resources.h create mode 100644 utils/spline.c create mode 100644 utils/spline.h create mode 100644 utils/textclient.c create mode 100644 utils/textclient.h create mode 100644 utils/usleep.c create mode 100644 utils/usleep.h create mode 100644 utils/utils.h create mode 100644 utils/version.h create mode 100644 utils/visual-gl.c create mode 100644 utils/visual.c create mode 100644 utils/visual.h create mode 100644 utils/vms-gtod.c create mode 100644 utils/vms-gtod.h create mode 100644 utils/vms-strdup.c create mode 100644 utils/vroot.h create mode 100644 utils/xdbe.c create mode 100644 utils/xdbe.h create mode 100644 utils/xmu.c create mode 100644 utils/xmu.h create mode 100644 utils/xscreensaver-intl.h create mode 100644 utils/xshm.c create mode 100644 utils/xshm.h create mode 100644 utils/yarandom.c create mode 100644 utils/yarandom.h create mode 100644 xscreensaver.spec create mode 100644 xscreensaver.xcodeproj/project.pbxproj diff --git a/INSTALL b/INSTALL new file mode 100644 index 00000000..50dbe439 --- /dev/null +++ b/INSTALL @@ -0,0 +1,183 @@ +Basic Installation +================== + + These are generic installation instructions. + + The `configure' shell script attempts to guess correct values for +various system-dependent variables used during compilation. It uses +those values to create a `Makefile' in each directory of the package. +It may also create one or more `.h' files containing system-dependent +definitions. Finally, it creates a shell script `config.status' that +you can run in the future to recreate the current configuration, a file +`config.cache' that saves the results of its tests to speed up +reconfiguring, and a file `config.log' containing compiler output +(useful mainly for debugging `configure'). + + If you need to do unusual things to compile the package, please try +to figure out how `configure' could check whether to do them, and mail +diffs or instructions to the address given in the `README' so they can +be considered for the next release. If at some point `config.cache' +contains results you don't want to keep, you may remove or edit it. + + The file `configure.in' is used to create `configure' by a program +called `autoconf'. You only need `configure.in' if you want to change +it or regenerate `configure' using a newer version of `autoconf'. + +The simplest way to compile this package is: + + 1. `cd' to the directory containing the package's source code and type + `./configure' to configure the package for your system. If you're + using `csh' on an old version of System V, you might need to type + `sh ./configure' instead to prevent `csh' from trying to execute + `configure' itself. + + Running `configure' takes awhile. While running, it prints some + messages telling which features it is checking for. + + 2. Type `make' to compile the package. + + 3. Optionally, type `make check' to run any self-tests that come with + the package. + + 4. Type `make install' to install the programs and any data files and + documentation. + + 5. You can remove the program binaries and object files from the + source code directory by typing `make clean'. To also remove the + files that `configure' created (so you can compile the package for + a different kind of computer), type `make distclean'. There is + also a `make maintainer-clean' target, but that is intended mainly + for the package's developers. If you use it, you may have to get + all sorts of other programs in order to regenerate files that came + with the distribution. + +Compilers and Options +===================== + + Some systems require unusual options for compilation or linking that +the `configure' script does not know about. You can give `configure' +initial values for variables by setting them in the environment. Using +a Bourne-compatible shell, you can do that on the command line like +this: + CC=c89 CFLAGS=-O2 LIBS=-lposix ./configure + +Or on systems that have the `env' program, you can do it like this: + env CPPFLAGS=-I/usr/local/include LDFLAGS=-s ./configure + +Compiling For Multiple Architectures +==================================== + + You can compile the package for more than one kind of computer at the +same time, by placing the object files for each architecture in their +own directory. To do this, you must use a version of `make' that +supports the `VPATH' variable, such as GNU `make'. `cd' to the +directory where you want the object files and executables to go and run +the `configure' script. `configure' automatically checks for the +source code in the directory that `configure' is in and in `..'. + + If you have to use a `make' that does not supports the `VPATH' +variable, you have to compile the package for one architecture at a time +in the source code directory. After you have installed the package for +one architecture, use `make distclean' before reconfiguring for another +architecture. + +Installation Names +================== + + By default, `make install' will install the package's files in +`/usr/local/bin', `/usr/local/man', etc. You can specify an +installation prefix other than `/usr/local' by giving `configure' the +option `--prefix=PATH'. + + You can specify separate installation prefixes for +architecture-specific files and architecture-independent files. If you +give `configure' the option `--exec-prefix=PATH', the package will use +PATH as the prefix for installing programs and libraries. +Documentation and other data files will still use the regular prefix. + + In addition, if you use an unusual directory layout you can give +options like `--bindir=PATH' to specify different values for particular +kinds of files. Run `configure --help' for a list of the directories +you can set and what kinds of files go in them. + + If the package supports it, you can cause programs to be installed +with an extra prefix or suffix on their names by giving `configure' the +option `--program-prefix=PREFIX' or `--program-suffix=SUFFIX'. + +Optional Features +================= + + Some packages pay attention to `--enable-FEATURE' options to +`configure', where FEATURE indicates an optional part of the package. +They may also pay attention to `--with-PACKAGE' options, where PACKAGE +is something like `gnu-as' or `x' (for the X Window System). The +`README' should mention any `--enable-' and `--with-' options that the +package recognizes. + + For packages that use the X Window System, `configure' can usually +find the X include and library files automatically, but if it doesn't, +you can use the `configure' options `--x-includes=DIR' and +`--x-libraries=DIR' to specify their locations. + +Specifying the System Type +========================== + + There may be some features `configure' can not figure out +automatically, but needs to determine by the type of host the package +will run on. Usually `configure' can figure that out, but if it prints +a message saying it can not guess the host type, give it the +`--host=TYPE' option. TYPE can either be a short name for the system +type, such as `sun4', or a canonical name with three fields: + CPU-COMPANY-SYSTEM + +See the file `config.sub' for the possible values of each field. If +`config.sub' isn't included in this package, then this package doesn't +need to know the host type. + + If you are building compiler tools for cross-compiling, you can also +use the `--target=TYPE' option to select the type of system they will +produce code for and the `--build=TYPE' option to select the type of +system on which you are compiling the package. + +Sharing Defaults +================ + + If you want to set default values for `configure' scripts to share, +you can create a site shell script called `config.site' that gives +default values for variables like `CC', `cache_file', and `prefix'. +`configure' looks for `PREFIX/share/config.site' if it exists, then +`PREFIX/etc/config.site' if it exists. Or, you can set the +`CONFIG_SITE' environment variable to the location of the site script. +A warning: not all `configure' scripts look for a site script. + +Operation Controls +================== + + `configure' recognizes the following options to control how it +operates. + +`--cache-file=FILE' + Use and save the results of the tests in FILE instead of + `./config.cache'. Set FILE to `/dev/null' to disable caching, for + debugging `configure'. + +`--help' + Print a summary of the options to `configure', and exit. + +`--quiet' +`--silent' +`-q' + Do not print messages saying which checks are being made. To + suppress all normal output, redirect it to `/dev/null' (any error + messages will still be shown). + +`--srcdir=DIR' + Look for the package's source code in directory DIR. Usually + `configure' can determine that directory automatically. + +`--version' + Print the version of Autoconf used to generate the `configure' + script, and exit. + +`configure' also accepts some other, not widely useful, options. + diff --git a/Makefile.in b/Makefile.in new file mode 100644 index 00000000..a99184a2 --- /dev/null +++ b/Makefile.in @@ -0,0 +1,374 @@ +# Makefile.in --- xscreensaver, Copyright (c) 1999-2010 Jamie Zawinski. +# the `../configure' script generates `Makefile' from this file. + +@SET_MAKE@ +srcdir = @srcdir@ +VPATH = @srcdir@ + +SHELL = /bin/sh +SUBDIRS = utils driver hacks hacks/glx po +#SUBDIRS = utils driver hacks hacks/glx +SUBDIRS2 = $(SUBDIRS) OSX +TARFILES = README README.hacking README.VMS INSTALL \ + configure configure.in Makefile.in config.h.in \ + config.h-vms install-sh setup.com config.guess aclocal.m4 \ + config.sub makevms.com \ + intltool-merge.in intltool-extract.in intltool-update.in \ + xscreensaver.spec \ + xscreensaver.xcodeproj/project.pbxproj + +TAR = tar + +MAKE_SUBDIR = for dir in $(SUBDIRS); do (cd $$dir; $(MAKE) $@) || exit 5; done +MAKE_SUBDIR2 = for dir in $(SUBDIRS2);do (cd $$dir; $(MAKE) $@) || exit 5; done + +default:: + @$(MAKE_SUBDIR) +all:: + @$(MAKE_SUBDIR) +install:: + @$(MAKE_SUBDIR) +install-program:: + @$(MAKE_SUBDIR) +install-man:: + @$(MAKE_SUBDIR) +install-strip:: + @$(MAKE_SUBDIR) +uninstall:: + @$(MAKE_SUBDIR) +uninstall-program:: + @$(MAKE_SUBDIR) +uninstall-man:: + @$(MAKE_SUBDIR) +depend:: + @$(MAKE_SUBDIR) +distdepend:: + @$(MAKE) update_spec_version + @$(MAKE_SUBDIR2) + @cd po ; $(MAKE) update-po + +TAGS:: tags +tags:: + @$(MAKE_SUBDIR) + +clean:: + @$(MAKE_SUBDIR2) + +distclean:: clean + -rm -f config.h Makefile config.status config.cache config.log TAGS *~ "#"* intltool-extract intltool-merge intltool-update + @$(MAKE_SUBDIR2) + +dist:: tar + +# This really makes me sick... +tar:: + @ \ + sh config.status ; \ + rm -f configure ; \ + $(MAKE) configure ; \ + $(MAKE) version-date distdepend ; \ + VERS=`sed -n 's/[^0-9]*\([0-9]\.[0-9][^. ]*\).*/\1/p' utils/version.h` ; \ + NAME="xscreensaver-$$VERS" ; \ + rm -rf $$NAME ; ln -s . $$NAME ; \ + FILES= ; \ + ADIR=archive/ ; \ + for subdir in $(SUBDIRS2) ; do \ + d=`pwd` ; \ + cd $$subdir ; \ + FILES="$$FILES `$(MAKE) echo_tarfiles \ + | grep -v '^.*make\[' \ + | sed \"s|^|$$subdir/|g;s| | $$subdir/|g\" \ + ` "; \ + cd $$d ; done ; \ + echo creating tar file $$ADIR$$NAME.tar.gz... ; \ + export COPYFILE_DISABLE=true ; \ + GZIP="-9v" $(TAR) -vchzf $$ADIR$$NAME.tar.gz \ + `echo $(TARFILES) $$FILES | sed "s|^|$$NAME/|g; s| | $$NAME/|g" ` ; \ + rm $$NAME + + +# This also makes me sick... +# autoconf generates a configure script that begins with a very hard to read, +# nearly impossible to customize --help blurb. This horrid set of regexps +# go through and clean up the help text, by inserting whitespace and ripping +# out options we don't use. Odds are good that this will fail with any version +# of autoconf other than the ones I've tried (2.12 and 2.13.) +# +# NOTE: we now require autoconf 2.63 or earlier, because later versions have +# the "Expanded-Before-Required" change and I can't make any sense of it. +# If someone wants to send me a patch to make configure.in work with 2.64 +# or later, feel free. Personally, I can't be bothered. +# +configure:: + autoconf263 + autoheader263 + @TMP=configure.$$$$ ; \ + echo "munging configure's --help message..." ; \ + ( perl -e ' \ + my $$file=""; \ + while (<>) { $$file .= $$_; } \ + $$_ = $$file; \ + \ + s/^(Configuration:)$$/\n$$1\n/m; \ + s/^(Directory and file names:)$$/\n$$1\n/m; \ + s/^ --sbindir=.*\n//m; \ + s/^ --sysconfdir.*\n//m; \ + s/^ --sharedstatedir.*\n.*\n//m; \ + s/^ --localstatedir.*\n//m; \ + s/^ --infodir.*\n//m; \ + s/^(Host type:)$$/\n$$1\n/m; \ + s/\nFeatures and packages:\n.*library files are in DIR\n/\n/s;\ + s/--enable and --with options recognized://m; \ + s/\n --with-x .*?(["\n])/$$1/s; \ + s/\n(Installation options:\n)/$$1/s; \ + \ + s/^ --oldincludedir=.*$$/ \ + --x-includes=DIR X include files are in DIR\n \ + --x-libraries=DIR X library files are in DIR/m; \ + \ + s@mandir=.\$${prefix}/man.@mandir=\\\$${datadir}/man@; \ + \ + s@rm -f conftest@rm -rf conftest@g; \ + \ + print;' \ + < configure \ + > $$TMP && \ + cat $$TMP > configure ) ; \ + rm -f $$TMP + +bump-version:: + @ \ + SRC=utils/version.h ; \ + VERS=`sed -n 's/[^0-9]*\([0-9]\)\.\([0-9][^. ]*\).*/\1 \2/p' $$SRC` ; \ + set - $$VERS ; \ + MAJOR="$$1"; MINOR="$$2"; \ + NEW=`echo $$MINOR + 1 | bc` ; \ + NEW=`echo $$NEW | sed 's/^\([0-9]\)$$/0\1/'` ; \ + D=`date '+%d-%b-%Y'`; \ + ADIR=archive/ ; \ + if [ ! -f $${ADIR}xscreensaver-$$MAJOR.$$MINOR.tar.gz ]; then \ + echo "WARNING: $${ADIR}xscreensaver-$$MAJOR.$$MINOR.tar.gz does not exist.";\ + fi ; \ + if [ -f $${ADIR}xscreensaver-$$MAJOR.$$NEW.tar.gz ]; then \ + echo "WARNING: $${ADIR}xscreensaver-$$MAJOR.$$NEW.tar.gz already exists.";\ + fi ; \ + /bin/echo -n "Bumping $$MAJOR.$$MINOR to $$MAJOR.$$NEW ($$D), ok? "; \ + read line; \ + if [ "x$$line" != "xyes" -a "x$$line" != "xy" ]; then \ + exit 1 ; \ + fi ; \ + TMP=/tmp/bv.$$ ; \ + sed -e "s/\([0-9]\.[0-9][0-9]*\)/$$MAJOR.$$NEW/" \ + -e "s/\(([0-9][0-9]*-[A-Za-z][a-z][a-z]-[0-9][0-9][0-9]*\))/($$D)/" \ + $$SRC > $$TMP ; \ + /bin/echo -n "New version and date are "; \ + sed -n "s/[^0-9]*\([0-9]\.[0-9][0-9]*\) (\([-A-Za-z0-9]*\)).*/\1, \2./p" \ + $$TMP; \ + cat $$TMP > $$SRC ; \ + rm -f $$TMP; \ + echo "overwrote $$SRC"; \ + ls -lFd $$SRC + +bump_version:: bump-version +tick-version:: bump-version +tick_version:: bump-version + +version-date:: + @ \ + SRC=utils/version.h ; \ + D=`date '+%d-%b-%Y'`; \ + TMP=/tmp/bv.$$ ; \ + sed -e "s/([0-9][^()]*)/($$D)/" < $$SRC > $$TMP ; \ + /bin/echo -n "Updating date in $$SRC to \"$$D\"... " ; \ + if cmp -s $$SRC $$TMP ; then \ + echo "unchanged." ; \ + else \ + cat $$TMP > $$SRC ; \ + echo "done." ; \ + fi ; \ + rm -f $$TMP + + +update_spec_version:: + @S=$(srcdir)/xscreensaver.spec ; \ + U=$(srcdir)/utils/version.h ; \ + VERS=`sed -n 's/[^0-9]*\([0-9]\.[0-9][^. ]*\).*/\1/p' < $$U` ; \ + /bin/echo -n "Updating $$S to \"$$VERS\"... " ; \ + T=/tmp/xs.$$$$ ; \ + sed "s/^\(%define.version[^0-9]*\)\(.*\)/\1$$VERS/" \ + < $$S > $$T ; \ + if cmp -s $$S $$T ; then \ + echo "unchanged." ; \ + else \ + cat $$T > $$S ; \ + echo "done." ; \ + fi ; \ + rm $$T + +rpm:: + @ \ + VERS=`sed -n 's/[^0-9]*\([0-9]\.[0-9][^. ]*\).*/\1/p' utils/version.h` ; \ + DIR=`pwd`/rpm_build ; \ + ARCH=`rpm --showrc | sed -n 's/^build arch *: //p'` ; \ + ADIR=archive/ ; \ + TGZ=xscreensaver-$$VERS.tar.gz ; \ + if [ ! -f $${ADIR}$$TGZ ]; then \ + echo "$${ADIR}$$TGZ does not exist! Did you forget to \`make tar'?" ; \ + exit 1 ; \ + fi ; \ + rm -rf /var/tmp/xscreensaver-$$VERS-root ; \ + rm -rf $$DIR ; \ + mkdir $$DIR ; \ + ( cd $$DIR; mkdir BUILD RPMS RPMS/$$ARCH SOURCES SPECS SRPMS ) ; \ + cp -p $${ADIR}$$TGZ $$DIR/SOURCES/ ; \ + rpmbuild --define "_topdir $$DIR" \ + --define "USE_GL yes" \ + -v -ba xscreensaver.spec ; \ + echo '' ; \ + echo 'RPM build complete' ; \ + echo '' ; \ + rm -f $$DIR/$$TGZ ; \ + rm -rf $$DIR/BUILD/xscreensaver-$$VERS ; \ + mv $$DIR/SRPMS/xscreensaver*-$$VERS-*.rpm . ; \ + mv $$DIR/RPMS/$$ARCH/xscreensaver*-$$VERS-*.rpm . ; \ + rm -rf $$DIR ; \ + echo '' ; \ + ls -lFG xscreensaver*-$$VERS-*.rpm + +test-tar:: + @ \ + VERS=`sed -n 's/[^0-9]*\([0-9]\.[0-9][^. ]*\).*/\1/p' utils/version.h` ; \ + D=xscreensaver-$$VERS ; \ + ADIR=archive/ ; \ + NAME="$${ADIR}$$D.tar.gz" ; \ + if [ ! -f $$NAME ]; then \ + echo "$$NAME does not exist! Did you forget to \`make tar'?" ; \ + exit 1 ; \ + fi ; \ + \ + set -e ; \ + set -x ; \ + \ + if [ -d $$D ]; then \ + chmod -R u+w $$D ; \ + fi ; \ + rm -rf $$D ; \ + zcat $${ADIR}$$D.tar.gz | tar -xf - ; \ + cd $$D ; \ + chmod -R a-w . ; \ + chmod u+w . ; \ + mkdir BIN ; \ + mkdir BIN/motif ; \ + mkdir BIN/lesstif ; \ + chmod a-w . ; \ + \ + ( cd BIN/motif ; \ + CC=cc ; \ + export CC ; \ + ../../configure --without-xpm --without-xdbe --without-xshm \ + --with-motif=/usr/local/motif ; \ + echo --------------------------------------------------------------- ; \ + gmake all ; \ + ( cd driver; gmake tests ) ; \ + echo --------------------------------------------------------------- ); \ + \ + ( cd BIN/lesstif ; \ + CC=cc ; \ + export CC ; \ + ../../configure --with-motif=/usr/local/lesstif --without-gnome ; \ + echo --------------------------------------------------------------- ; \ + ( cd utils; gmake all ) ; \ + ( cd driver; gmake all ) ; \ + echo --------------------------------------------------------------- ); \ + \ + chmod -R u+w . + +dmg:: + cd OSX ; $(MAKE) release dmg + +www:: + @ \ + DEST=$$HOME/www/xscreensaver ; \ + VERS=`sed -n 's/[^0-9]*\([0-9]\.[0-9][^. ]*\).*/\1/p' utils/version.h` ; \ + HEAD="xscreensaver-$$VERS" ; \ + ADIR=archive/ ; \ + BNAME="$$HEAD.tar.gz" ; \ + NAME="$$ADIR$$BNAME" ; \ + DNAME="$$DEST/$$HEAD.tar.gz" ; \ + BNAME2="$$HEAD.dmg" ; \ + NAME2="$$ADIR$$BNAME2" ; \ + DNAME2="$$DEST/$$HEAD.dmg" ; \ + \ + if [ ! -f $$NAME ]; then \ + echo "$$NAME does not exist! Did you forget to \`make tar'?" ; \ + exit 1 ; \ + fi ; \ + if [ ! -f $$NAME2 ]; then \ + echo "$$NAME2 does not exist! Did you forget to \`make dmg'?" ; \ + exit 1 ; \ + fi ; \ + chmod a-w $$NAME ; \ + if [ -f $$DNAME ]; then \ + /bin/echo -n "WARNING: $$DNAME already exists! Overwrite? "; \ + read line; \ + if [ "x$$line" != "xyes" -a "x$$line" != "xy" ]; then \ + exit 1 ; \ + fi ; \ + fi ; \ + if [ -f $$DNAME2 ]; then \ + /bin/echo -n "WARNING: $$DNAME2 already exists! Overwrite? "; \ + read line; \ + if [ "x$$line" != "xyes" -a "x$$line" != "xy" ]; then \ + exit 1 ; \ + fi ; \ + fi ; \ + cp -p $$NAME $$DNAME ; \ + cp -p $$NAME2 $$DNAME2 ; \ + chmod u+w $$DNAME $$DNAME2 ; \ + cd $$DEST ; \ + \ + TMP=/tmp/xd.$$$$ ; \ + sed "s/xscreensaver-5\.[0-9][0-9ab]*/$$HEAD/g" download.html > $$TMP ; \ + echo '' ; \ + diff -U0 download.html $$TMP ; \ + echo '' ; \ + \ + for EXT in tar.gz dmg ; do \ + OLDEST=`ls xscreensaver*.$$EXT | head -n 1` ; \ + /bin/echo -n "Delete $$DEST/$$OLDEST? "; \ + read line; \ + if [ "x$$line" = "xyes" -o "x$$line" = "xy" ]; then \ + set -x ; \ + rm $$OLDEST ; \ + cvs remove $$OLDEST ; \ + set +x ; \ + fi ; \ + done ; \ + set -x ; \ + cvs add -kb $$BNAME $$BNAME2 ; \ + cat $$TMP > download.html ; \ + rm -f $$TMP ; \ + \ + (cd ..; $(MAKE) xscreensaver/changelog.html \ + xscreensaver/screenshots/index.html ); \ + cvs diff -U0 changelog.html ; \ + set +x ; \ + \ + /bin/echo -n "Ok? "; \ + read line; \ + if [ "x$$line" != "xyes" -a "x$$line" != "xy" ]; then \ + exit 1 ; \ + fi ; \ + \ + cvs commit -m "$$VERS" + + +count:: + @ \ + /bin/echo -n "Current hack count: " ; \ + ( ( cd hacks; make -s INSTALL=true install-program install-scripts ) ; \ + ( cd hacks/glx; make -s INSTALL=true install-program ) ) | \ + grep true | \ + grep -v helper | \ + grep -v ljlatest | \ + wc -l diff --git a/OSX/Default-568h@2x.png b/OSX/Default-568h@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..0891b7aabfcf3422423b109c8beed2bab838c607 GIT binary patch literal 18594 zcmeI4X;f257Jx&9fS`ixvS;&$x8J@slQFSel)6zJN=?13FB7H(lQjRkSy8x_-S~tvu2gzn1oS+dLcF#eqtq$ z%tf9TTvX?`)R@}3uBI;jzS-=ZR-Td&MHaS&;!0?Ni*#$#`n*~CcQK)Q9vAQ~TUpnI!j)a2biYK^R)M~A5wUDZhx?ULMX z3x1P&qt=trOY6P2U67L=m=U?F|5#Uj(eCueNTZaHs_ceWiHeET+j+tp3Jt9g(ekqP z2WOvfR{qV+9r+o4J5?qK>7;;^+I7tGv-i)es$X_D=EoKF+S?zsyj^oRFElP}c}JT< zd8SUs-?O?}2YD#ngKbnHgzHBcboxK_2r9l(?eNCl-pEzkJm}fY?WC*jnS?VBE4EpY zO$fEejz6fU;W2Kl>JeQBZBl-%Irg`obSlg*@4QB;Dd1H7^Oi5wvt4d{RZ!8Og?^aE z)k0$1g+V3fd(gdQ3d&q2q-FL*uy#}|bc^=VhFsl0jBgUGJ+-s3U8MK9A!YJJMxpci z5hJ%|{DwV48fZn0{n5l$N_KcSb#NKE4plB`9I6Zt=Z!~-zw0{9tg$L&Ju1F0X)Cy8 zKF;(&lJ>x)Jw(=;p~sF(Sd9VWGwFE2rnyS9!f^DZ8+aCLq zQ};>lcJ1GDLqjm6Hd>|Eabno@P`~Bn(~6^aD_#yoEH(a?Nm1S<;S+hSxI5d16^<1lEM3NPFi zkqPrpL)+ zgnseFikg`gJVBha1&7C4;O6>h=dt~`ND+;Zd?W(4v2JIb7Pt>Td42%M-Ju-XAH#Pns762L}K3 zDhvsRqN0Ni(1UrishD2YvV?4*h2iFj$+&N||Fn$4n|^NSU+o?~jq`0jVQt8T9l{7b zXiwwODFh2V!Q6sqP9S>WH$oOf$N~=d0-bqTlD61!=`&0eAP-F>XN?*|gtOXX{ zQVTWyYo4ZK0GAw!GHf|pz9`D;-bbb*5LBX*{bnz|+)$@&P9|ORM2o?95{;ejvo&r- zq8cBhTN6nn)7~W>54U)%-F_-b?YKdfk5I8MHcuzBD5)!;yv#Z&R&^y=@=>VTIMy#r zX&U<=BsPkdqcMe<_}2+>H%XKyrr5ZR8_KVe>ZqYN z^=^~TFD};;rHJ$U;{~w^hYojl4hRI@SH$^K{YEo=sg)WY87r!*7blQK&qnpDo0`Vn zkl)9u9g=mCh&ZCJS(L4yN3k0kQ zuvg$h2KEEk51T+O0JQ+r0`R>g{jvqM0Mr6d3qUOZwE!?PI7HY@CE|dr sfw?Q;rAv?G4&^^8-z_>&sWXMxvD*gPOU4CBe-*@OtE+wfmVJNyHv)PfH~;_u literal 0 HcmV?d00001 diff --git a/OSX/English.lproj/InfoPlist.strings b/OSX/English.lproj/InfoPlist.strings new file mode 100644 index 0000000000000000000000000000000000000000..dea12de4cad936a6204d4da70d2ca96aef900b31 GIT binary patch literal 92 zcmW-Z!3uyN5C!M#S9tbN-x2r|Q3;V~qzLu#)x*oq?lA28G2*azG7B@2orjH8u89{# bCX+-f2F*!V&^~bXzEEWk)pxI)ej3aVcM}l{ literal 0 HcmV?d00001 diff --git a/OSX/English.lproj/SaverRunner.nib/designable.nib b/OSX/English.lproj/SaverRunner.nib/designable.nib new file mode 100644 index 00000000..1facee5e --- /dev/null +++ b/OSX/English.lproj/SaverRunner.nib/designable.nib @@ -0,0 +1,1790 @@ + + + + 1050 + 10K549 + 851 + 1038.36 + 461.00 + + com.apple.InterfaceBuilder.CocoaPlugin + 851 + + + + + + com.apple.InterfaceBuilder.CocoaPlugin + + + PluginDependencyRecalculationVersion + + + + + + NSApplication + + + + FirstResponder + + + NSApplication + + + MainMenu + + + + XScreenSaver + + 1048576 + 2147483647 + + NSImage + NSMenuCheckmark + + + NSImage + NSMenuMixedState + + submenuAction: + + XScreenSaver + + + + About XScreenSaver + + 2147483647 + + + + + + YES + YES + + + 1048576 + 2147483647 + + + + + + YES + Preferences… + , + 1048576 + 2147483647 + + + + + + YES + YES + + + 1048576 + 2147483647 + + + + + + Services + + 1048576 + 2147483647 + + + submenuAction: + + + Services + + + _NSServicesMenu + + + + + YES + YES + + + 1048576 + 2147483647 + + + + + + Hide XScreenSaver + h + 1048576 + 2147483647 + + + + + + Hide Others + h + 1572864 + 2147483647 + + + + + + Show All + + 1048576 + 2147483647 + + + + + + YES + YES + + + 1048576 + 2147483647 + + + + + + Quit XScreenSaver + q + 1048576 + 2147483647 + + + + + _NSAppleMenu + + + + + File + + 1048576 + 2147483647 + + + submenuAction: + + + File + + + + + Close + w + 1048576 + 2147483647 + + + + + + YES + YES + + + 1048576 + 2147483647 + + + + + + Page Setup… + P + 1048576 + 2147483647 + + + + + + Print… + p + 1048576 + 2147483647 + + + + + + + + + Edit + + 1048576 + 2147483647 + + + submenuAction: + + + Edit + + + + + Undo + z + 1048576 + 2147483647 + + + + + + Redo + Z + 1048576 + 2147483647 + + + + + + YES + YES + + + 1048576 + 2147483647 + + + + + + Cut + x + 1048576 + 2147483647 + + + + + + Copy + c + 1048576 + 2147483647 + + + + + + Paste + v + 1048576 + 2147483647 + + + + + + Paste and Match Style + V + 1572864 + 2147483647 + + + + + + Delete + + 1048576 + 2147483647 + + + + + + Select All + a + 1048576 + 2147483647 + + + + + + YES + YES + + + 1048576 + 2147483647 + + + + + + Find + + 1048576 + 2147483647 + + + submenuAction: + + + Find + + + + + Find… + f + 1048576 + 2147483647 + + + 1 + + + + Find Next + g + 1048576 + 2147483647 + + + 2 + + + + Find Previous + G + 1048576 + 2147483647 + + + 3 + + + + Use Selection for Find + e + 1048576 + 2147483647 + + + 7 + + + + Jump to Selection + j + 1048576 + 2147483647 + + + + + + + + + Spelling + + 1048576 + 2147483647 + + + submenuAction: + + Spelling + + + + Spelling… + : + 1048576 + 2147483647 + + + + + + Check Spelling + ; + 1048576 + 2147483647 + + + + + + Check Spelling as You Type + + 1048576 + 2147483647 + + + + + + + + + + + + Window + + 1048576 + 2147483647 + + + submenuAction: + + + Window + + + + + Minimize + m + 1048576 + 2147483647 + + + + + + Zoom + + 1048576 + 2147483647 + + + + + + YES + YES + + + 1048576 + 2147483647 + + + + + + Bring All to Front + + 1048576 + 2147483647 + + + + + _NSWindowsMenu + + + + + Help + + 1048576 + 2147483647 + + + submenuAction: + + Help + + + + YES + XScreenSaver Help + ? + 1048576 + 2147483647 + + + + + + + + _NSMainMenu + + + SaverRunner + + + + + + + performMiniaturize: + + + + 37 + + + + arrangeInFront: + + + + 39 + + + + print: + + + + 86 + + + + runPageLayout: + + + + 87 + + + + showHelp: + + + + 122 + + + + terminate: + + + + 139 + + + + hideOtherApplications: + + + + 146 + + + + hide: + + + + 152 + + + + unhideAllApplications: + + + + 153 + + + + cut: + + + + 175 + + + + paste: + + + + 176 + + + + redo: + + + + 178 + + + + selectAll: + + + + 179 + + + + undo: + + + + 180 + + + + copy: + + + + 181 + + + + showGuessPanel: + + + + 188 + + + + checkSpelling: + + + + 190 + + + + toggleContinuousSpellChecking: + + + + 192 + + + + performClose: + + + + 193 + + + + delete: + + + + 195 + + + + performZoom: + + + + 198 + + + + performFindPanelAction: + + + + 199 + + + + performFindPanelAction: + + + + 200 + + + + performFindPanelAction: + + + + 201 + + + + performFindPanelAction: + + + + 202 + + + + centerSelectionInVisibleArea: + + + + 203 + + + + pasteAsPlainText: + + + + 205 + + + + delegate + + + + 207 + + + + menubar + + + + 209 + + + + openPreferences: + + + + 212 + + + + aboutPanel: + + + + 213 + + + + + + 0 + + + + + + -2 + + + File's Owner + + + -1 + + + First Responder + + + -3 + + + Application + + + 29 + + + + + + + + + + MainMenu + + + 19 + + + + + + + + 24 + + + + + + + + + + + 5 + + + + + 23 + + + + + 92 + + + + + 197 + + + + + 56 + + + + + + + + 57 + + + + + + + + + + + + + + + + + + 58 + + + + + 129 + + + + + 131 + + + + + + + + 130 + + + + + 134 + + + + + 136 + + + + + 143 + + + + + 144 + + + + + 145 + + + + + 149 + + + + + 150 + + + + + 196 + + + + + 83 + + + + + + + + 81 + + + + + + + + + + + 73 + + + + + 74 + + + + + 77 + + + + + 78 + + + + + 103 + + + + + + + + 106 + + + + + + + + 111 + + + + + 163 + + + + + + + + 169 + + + + + + + + + + + + + + + + + + + 156 + + + + + 157 + + + + + 158 + + + + + 160 + + + + + 164 + + + + + 168 + + + + + + + + 159 + + + + + + + + + + + + 154 + + + + + 155 + + + + + 161 + + + + + 162 + + + + + 167 + + + + + 171 + + + + + 172 + + + + + 173 + + + + + 174 + + + + + 184 + + + + + + + + 185 + + + + + + + + + + 187 + + + + + 189 + + + + + 191 + + + + + 204 + + + + + 206 + + + SaverRunner + + + + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + {{72, 1365}, {344, 20}} + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + {{84, 1182}, {225, 183}} + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + + + + + + 213 + + + + + SaverRunner + NSObject + + id + id + + + + aboutPanel: + id + + + openPreferences: + id + + + + menubar + NSMenu + + + menubar + + menubar + NSMenu + + + + IBProjectSource + OSX/SaverRunner.h + + + + + + NSApplication + NSResponder + + IBFrameworkSource + AppKit.framework/Headers/NSApplication.h + + + + NSApplication + + IBFrameworkSource + AppKit.framework/Headers/NSApplicationScripting.h + + + + NSApplication + + IBFrameworkSource + AppKit.framework/Headers/NSColorPanel.h + + + + NSApplication + + IBFrameworkSource + AppKit.framework/Headers/NSHelpManager.h + + + + NSApplication + + IBFrameworkSource + AppKit.framework/Headers/NSPageLayout.h + + + + NSBrowser + NSControl + + IBFrameworkSource + AppKit.framework/Headers/NSBrowser.h + + + + NSControl + NSView + + IBFrameworkSource + AppKit.framework/Headers/NSControl.h + + + + NSDocument + NSObject + + id + id + id + id + id + id + + + + printDocument: + id + + + revertDocumentToSaved: + id + + + runPageLayout: + id + + + saveDocument: + id + + + saveDocumentAs: + id + + + saveDocumentTo: + id + + + + IBFrameworkSource + AppKit.framework/Headers/NSDocument.h + + + + NSDocument + + IBFrameworkSource + AppKit.framework/Headers/NSDocumentScripting.h + + + + NSMatrix + NSControl + + IBFrameworkSource + AppKit.framework/Headers/NSMatrix.h + + + + NSMenu + NSObject + + IBFrameworkSource + AppKit.framework/Headers/NSMenu.h + + + + NSMenuItem + NSObject + + IBFrameworkSource + AppKit.framework/Headers/NSMenuItem.h + + + + NSMovieView + NSView + + IBFrameworkSource + AppKit.framework/Headers/NSMovieView.h + + + + NSObject + + IBFrameworkSource + AppKit.framework/Headers/NSAccessibility.h + + + + NSObject + + IBFrameworkSource + AppKit.framework/Headers/NSAlert.h + + + + NSObject + + IBFrameworkSource + AppKit.framework/Headers/NSAnimation.h + + + + NSObject + + + + NSObject + + + + NSObject + + + + NSObject + + + + NSObject + + IBFrameworkSource + AppKit.framework/Headers/NSComboBox.h + + + + NSObject + + IBFrameworkSource + AppKit.framework/Headers/NSComboBoxCell.h + + + + NSObject + + + + NSObject + + IBFrameworkSource + AppKit.framework/Headers/NSDatePickerCell.h + + + + NSObject + + IBFrameworkSource + AppKit.framework/Headers/NSDragging.h + + + + NSObject + + IBFrameworkSource + AppKit.framework/Headers/NSDrawer.h + + + + NSObject + + IBFrameworkSource + AppKit.framework/Headers/NSFontManager.h + + + + NSObject + + IBFrameworkSource + AppKit.framework/Headers/NSFontPanel.h + + + + NSObject + + IBFrameworkSource + AppKit.framework/Headers/NSImage.h + + + + NSObject + + IBFrameworkSource + AppKit.framework/Headers/NSKeyValueBinding.h + + + + NSObject + + + + NSObject + + IBFrameworkSource + AppKit.framework/Headers/NSNibLoading.h + + + + NSObject + + IBFrameworkSource + AppKit.framework/Headers/NSOutlineView.h + + + + NSObject + + IBFrameworkSource + AppKit.framework/Headers/NSPasteboard.h + + + + NSObject + + IBFrameworkSource + AppKit.framework/Headers/NSSavePanel.h + + + + NSObject + + IBFrameworkSource + AppKit.framework/Headers/NSSound.h + + + + NSObject + + IBFrameworkSource + AppKit.framework/Headers/NSSpeechRecognizer.h + + + + NSObject + + IBFrameworkSource + AppKit.framework/Headers/NSSpeechSynthesizer.h + + + + NSObject + + IBFrameworkSource + AppKit.framework/Headers/NSSplitView.h + + + + NSObject + + IBFrameworkSource + AppKit.framework/Headers/NSTabView.h + + + + NSObject + + IBFrameworkSource + AppKit.framework/Headers/NSTableView.h + + + + NSObject + + IBFrameworkSource + AppKit.framework/Headers/NSText.h + + + + NSObject + + IBFrameworkSource + AppKit.framework/Headers/NSTextStorage.h + + + + NSObject + + IBFrameworkSource + AppKit.framework/Headers/NSTextView.h + + + + NSObject + + IBFrameworkSource + AppKit.framework/Headers/NSTokenField.h + + + + NSObject + + IBFrameworkSource + AppKit.framework/Headers/NSTokenFieldCell.h + + + + NSObject + + IBFrameworkSource + AppKit.framework/Headers/NSToolbar.h + + + + NSObject + + IBFrameworkSource + AppKit.framework/Headers/NSToolbarItem.h + + + + NSObject + + IBFrameworkSource + AppKit.framework/Headers/NSView.h + + + + NSObject + + IBFrameworkSource + AppKit.framework/Headers/NSWindow.h + + + + NSResponder + + IBFrameworkSource + AppKit.framework/Headers/NSInterfaceStyle.h + + + + NSResponder + NSObject + + IBFrameworkSource + AppKit.framework/Headers/NSResponder.h + + + + NSTableView + NSControl + + + + NSText + NSView + + + + NSView + + IBFrameworkSource + AppKit.framework/Headers/NSClipView.h + + + + NSView + + IBFrameworkSource + AppKit.framework/Headers/NSRulerView.h + + + + NSView + NSResponder + + + + NSWindow + + + + NSWindow + NSResponder + + + + NSWindow + + IBFrameworkSource + AppKit.framework/Headers/NSWindowScripting.h + + + + + 0 + IBCocoaFramework + + com.apple.InterfaceBuilder.CocoaPlugin.macosx + + + + com.apple.InterfaceBuilder.CocoaPlugin.macosx + + + YES + ../../xscreensaver.xcodeproj + 3 + + {9, 8} + {7, 2} + + + diff --git a/OSX/English.lproj/SaverRunner.nib/keyedobjects.nib b/OSX/English.lproj/SaverRunner.nib/keyedobjects.nib new file mode 100644 index 0000000000000000000000000000000000000000..96d6891c19180e3ef02fa68453004348827e9178 GIT binary patch literal 13707 zcmb_?2Xs?M)AsJYcO_f(s#~&(F_v_lKoSy?&_f3U28@j{rW#v-!M2Pg)5~6Z?=AG2 z&>;{)@22H8Ud09Zf#55zTtyf$ zh(#PCNG4OuG+9XleIe^FMFzgItBZZOa}DW@d2Z$30Zk^K9o0i`p@yg_YKi)x5>$!?qCsdFqG%$Tgl3^NXf1jNZA6>UX0#2xk9MLD&^~k; zT}B_GYv>d7E&2{ULce1U6D-3@tid{L!e(s6Nw_+G3BQbM;o7({Zi3t5PB;s9#@X11 zd*eR1KQ6+hcqAT$DV~Do;(2&JUXEAbm3R~0jJM$JcqcBy=kW!65#PkO@NN7#euTfr zKj7c-ANWs(V+bQ-v<%Pa7#kDMBr$Hr!_;8vG4+`SOk<`QlgeZX$INFIF)Nt$%m!v7^FFha`G7gZ9A?fk=a}=%hs-tRF7r9_ z1@k5I1M?&E7fVOAao4#U z+)eHlcbmJz-R16a_qhk$N8HEUC)}spXWZx97u=WJSKQa!L+%^yTkbpV2ks}*maHcm z$VRe>Y$jXCReA!o@sa-Liu7s(}ZnS4mDkgMbxxlV47o8%U`P41Apzr3yMQlWJB@DjvUB|Tqprm zL5Zj;Nl++|_Uv%4G*BY*7Zrhn0AB%Y0vF|6 zRdCT3m?&Swlhc=z`b#97=Ki8!YEDs3A72Ul6`~4bh8<^Bpga8D|NhzUPCou87~EbCHX~tCq3I@}b_S59*8Zse)?hyL1EHM7PjwbUS^Yen5BAy>vf4NDtGa zw2Yphr|21amY$;*=tX*&UZL0M4SI{-q4%!B8v3IGREUa@9~Gm7PHofMS*EkccH=`AbW3eN;o$R7shLzJj15RhRS}I9@uGf<2XF<@pMHeR6`nuowoTAw75_ zm_>fCcBR1rU$DY-R-?gaD5?vxhQ5l{XnsbZk*F9Ze24N>c@>Gk>S#0ujYZ?ocr*bF zCDm6{niBLC24J5^_5!?TLPv1?X(Zi&xV6cTj%E5PKtuwB-n^=JbKu!AoU zQch^kSZN%!fFweQp^YuE(xk61w|`+yN&m1~wxF#c*AzDM2>mLw1=W2Fz8!6#RvJ$& zp`j8=h}HBUXt#SHywb2V>O9uYF3`>%w3<3W1@)*gBKZTf`bKmR9YTlE5p)zCLuKeV zI)P52Q`AKhX;tc>Uiu2HL2J@CXf0a%#uK_&Qm%yypoL2ypi1IN=)vn7_41bn6Qacw zUg;Hd6@)J_FImbebOqJD4ceVkfqxy{0DX@E+*_dSu&(c;`{*OI0#ua}NcR=zl;i~c zC7`O5K-2ty(p(asy&b8A1bl@D_T(*+El^Uvn~7&^e6f&0)a7Fg;|;$Uf2sy3R%cX_mvFH zhePgpy2o-f4##2ztp>V(iM}Z59$Yt8Q?7!x+#WDbtA`yW)?)*haJi#wR8o>NWHq!I zQC+a%(4Sz#JtVIgo?OyoNVC|2@fm)7@buvaR;UI(x@^$=c2J6$rL3b5C^grM35`$7=^ zG(?@qQt(><(I}dq3Rm%FR(fCmpoB&R1<$b=+$@3;5=fi>AAz(hUqd?100uIn8K@f( zNF5MJT4{dey_hzjE9g)I z5;`Ns;J#po{b*yb!bTArETmkBB4U5VwE7x60GHqZ4$>yHIc-5(JuUEozz=u?JQNQD zZbn3Sk#yE9vfid0n-us1zO+HlllSN_2pl1j0Zw`>?}lM7RQTMQ(wi`fci!>bykGBQ$`0LP-j2S5blOC$_?Su z$A-}Ue>8+I%BO#bzk%t$i=Mt~Wcn@;v<_2P3WnN=yMj)8lz)W3Q6lTXy%MBvJ zP$9UkqP%BsAm%MJj%h>(zy>NV-#|>$kh3ewE8jp&3kZ9emP`uMifPTXp(V7G4yMEC z$XiU?C(k^l9n+qvDQy%cgXsudb%Kl~Bc~6KBfLo)CK%x?;6u%k%vCK_o_1ZiMrX^ja|rkd90SwMZ5zU4p#Od$aI`EpzIhj!1<2+)vjA)xjp zzJdAv(m+~^XMqKnU^&=eW(a@{GF6u^&U41K^D>O76LsT^w?^B!RBh{l={!J6DXl&K^{){<8DX`EeQ z9Pj}90q0;ePK5`U)`PcIMoP#DBy{$dCS(jL_B~tLN0_6`vB;UmoC54KbY>WR){|%2 zjLdL3=LuO?AL>ghd>Y}aFak*JJ3#n88lggJ3p29) z{=(;Zyq_WnA&>XRV~;oMe>%UIzayk9gI2NJGbdjRSzKeOz9acvX?rv;fyz>Mh#Si* zXU~ls*%&sKRYWw$YGDc;T^^of#gm#_meJBzQ2d16%A*n1gvJ5sO3>M|a{aJ2T74xO zPggxNvtykwFX)9$MEBVw)*VT|R)i$7raZG-4SPO1Gfj{b zDf{k^3fULgYG4lQ={mXy@}C??i;DXAQi?(%sT0b7*jLyZaBfD*C&3bbK}8j1HFUoE zRBh!k_Up_|z}`sb_TUZ0z7p_hg_7yy1WQZ6dLWxGFA4!0bzo;7gu$Dk>f`E?BW2m` zbBcTgbsnQN!~5ZD zWfp@4MEA4<*{`QN>8j2F$ZI6QRbnp#*gFgZb^&`;p-$m1_7#Ea@9it`6+x<6X>2wG z$Yn5g4`pbLj(s6%tJK{Sx=%s(KIpEU9rTqHO2x0rV|v4w<1pp`jHwA{g9H-F)}qRh zl_xC#iW5L_2q@kFiqay91}wZ1#baTXFfC#95n2L8<#KUK$4yA)<;9lAg9pKBzMdYV zBYW_UTwf9JTyapP6qT2q8W?+23Ov|Gnq2>7BpM7$e1PSW&_r4R#0b&SXR zpyM>n&d9B#vl6B?v>&0v9`jSevZd!s5 zK+`4KGqYFKuC+A@2LEu)`o zS!4~^6SA+jL-o|eP>7iep4Si6z43G@R9f3Z zt#z=JWkb#51<1G;&=vF}+K`TgjXO+QEmZ&6f1#TE@iU71*vK)fq?%B$IVB}~mw2%Z2UTLKH0+NMiF!rdTG zo{ElwIF5m^63{e!3?(o%f!*n_kXgWVdsv3_(?0Y~`jlE%z=9vQghxnYr0{`<(f&|B z10r+4XsIm~{` A&AHepR+(%42VjEPk&^!4W-rAezpGq{=DEN(V8hnvgI#4s z;ojxeaqGDa+(vE_x0&0*ZRNIc?{V9?9Vp1{q+if4=~wh?`jCD@zop;NNA!F81O1Wy zhyFzWOMj-n&|m3q^mqCP{geJh|EB-Ye?^Q$j71DLT&##W5fc&1L@XC^jEG~YPQ(fk zD@Cjlv0B6$5o<-vix}GVA~uNFC}NX{%_6plI8MY?5!*x@Phq&dOGWXy`kURP@FzhC z$3n?))P??*irNW+RCjVX|xa;ykmQV^CD+LANdm(%iLRBZ}R_lr4H+lkBs?b1_GYa?V zs1XKuq6So6b#x{G107KVpNi6;Umw*UE-OHzIjZq-wIEtV5S&FLhYGvV@Bk96ugIYT z&C!~b&i-iB*DIqwRcL(@wY(Ob+*K-uwZ3r5LZLL-Eb*eV;z z(-%Zwi>Bvr^He_jq!mhmC@>Tk#ZV>Xmh(|Am1sdpiU3M$6lG|Mk%9$qWqA%)&#dzz zAkaUTpd^%#Lm^jMfFUfLN{mK!s8F%ZD{t*kEDyBNOOOJYh@?Y;=n@soR%jr!%<%RX zqO3bHYT?f=tt3azz3=HKa7h#jgt-4ieg9cH9kRe-^g$VLD%OPSaUXLN^?(BL0k{%x zhjN+a=pYWj#raW`31Lx3l!XVd@o?pM3NC+VKx~i#SLu0hsh*AZpw@Ul%7HvC6+)}O zm^N_Y_kv&w;s>TRT)LM*{BROtif)i;OlMl6G<*;WCQH#F_BV(LTH$@nEgXbv%?{`o z6sZrPbbJ)f+mWafa|bT(r$Qi>4^FKuY6I8vx8Q2NIh^+=-~xUwT*!BZqV*lPxW5b` zl?#HSGKc~8LIHa>T-`T;Agd+>R`ns~m<1KPb8u~c3a;}r;ljTgT;#8SOMef9QX?T^ zxCp_R2oc3FxaO|`@kT9(FB(E%l?s8_HYkfvf*>pr!Yu|uuxtpuTEPjv9j;r`A!K_W zqLH^D3fT{V-C>AA-k|s3ali(uEtfoLACfjnBOORO$sip`Ch0`7NN18wx{$7<8|hAZ zke(!m^dh+=kN8M$(uedV`J^A|PYOsODI$JSOa_n=5+FfRN(PcaWH1>*hLT}qI2l1k zl2L>bk&Gr|$XGItj3*PwL^6p?CR4~%GL1|pGssLbi_9i-$Xqgy%qI)TLh?3QL>7}J zWGPujmXj4^C0RvQlQm>5d5649)`_@^h!aIzRm4dmc8k~}Vy}n=5hsiI1rfg};%XwU zF5;I&{IZB&5pfL>zbfL_L|jwEuZ#E%5x*(oS|YA3;yNO(E8==0t}o&SB7RH64Mp5Y z#EnJVM8r)++)TvHMchKfEk&Fn;#MMVE#fvJP8D%m5w{a@dl9FJxPyq(MVukxjv~$! zaVHUHiMX?fvqjuR#9c+)O~lX%wOb}@~8NI zyqBNBkLDNiefVwsCVn@+hhNE`;m7mq`FVV8K8?S?ujUu=o%nP70e&A}W`GwA(!am? z>-;Ky1%I4x%Zq#_Ka*d^ui=OC>-es`gP+Y4{v=)2lii{226Ng-Y zO!n9X$YMj^;oXl+DO17yaZ2OxTb-sk!JJhxrSx70o;1Om3twKN^5>72Wm*~EEv0e! zQ=L2*Nin>Ew4y}xBD{jEgWiIddrjEs@ZxSCdz!t&e#t)K6kHtV=BjaTaE-WjTn<+V z!RG=9B-cR*xe0>D_qZMK`fd-rx;q5#?aJV#-6?owcOKr?U53|mU%;!mhulxx-`u}M zP0XYUd4bd;O-LKqM%`g+lz_QU2UC^|c`dx2+XL_9PLVUPC^c}alNn?tnMG!m#mgKr zm#m7cs?06(%93R-%Bss=mer8GCVO4>rmVKCuB^W7EmcfEE^&l zCL19eB@<an$A>&Nzv z4aSPGV`3-9PL7=#J3V%0?5x<i@v z2damuN2o`sMfDiDn=ZI-s1wuhE#$7v^MCuyf>r)g(v=W6F`7i*VlPiRkR&ucGgFKe%8 zuW7GqZ)opo?`!|%IbO!c@CshV>%f7Tcq<>z*W(-UP55Sf3vh02`SyGVa88}U^Na#N zG=?9?PvEEW)4?Cj2M4$Zyw73&C|?E+@+|nGi~N`T*E)qxtJCQWI+M<#v+JC?1f5sc zQkSZ0r%ThN>pJSPbzODcb@{sfy1Bafy2ZMsy5+i+y4AWhy0y9ux=p%kx*NK?y8F71 zbf4%x(|w`)M)#fWd)4;rfw!svoDHpr53ltDmpmr$3-SsxQ-@(4W$u(O=YG)?d-z(?2k92AM%=P#d%c zoxxy;GuRAv!wZILhBQOEA8EYHs8tWV1GPX3fGNu{RjUA1hjDw9M zjH8UAag1@Cak6o$ak_D(aka6`c-nZ@c;0x?c-eT}c++^>__gsHlggws8B8XV#bh-( zO$nw%(_5y#rhX>BX@DtUDm4u<4Ka;0QPXJCB-29EdecVJX46*Fd#1gn{ib84bEXTX z8>U;PJEnW42WDg@X1O`mtTe05db81NHoMGK%#F=0%qiy9=2UY#bA~z7oMrB29&es# zo@Sn5o@Jh6o@btKUSM8gUS>XIE;FAnpE92@pEF-JUol@ZKQ#YtNwg$ck}WSaLf>0!ySs@1Txr~(xG`}v<7UUr zjhi30Chons9dSG3cEz2DyApRT?nd0LxR2t#i~BzA$GD&3{CTFusEYaMGn zYXfUTYh!CmYiDa0Yd32TYmT+RI>I{2Dq6=_$61$Iw_4w`?y&B(?y_F8-m^Zier)~J z`nOGCQ`s~&-u8;EzU?hrBU=+&iY?QYWy`j8we_<3Z3AopTd8fRZGvr*ZHjH0ZINw> zZJBL_ZL@8w?LFHL+dkVV+Zo$A+XdSl+dbO@+sC%AY(Lw6wf%1UGhP;Nh&RPs;;r$n z_-gSl#lI5&YJAi9wD|P+j`5x1d&dXjOXCN{4~btC|8D&H_>J+KsP_Cxj~ z_G9+r_LKJ0_Otf$_KWtL_S^Qm_J{VL?7um%gLMpa40a5440nu#%H3$kSjTwBM8{;u zRL6A3Ovh};T*rLJLdPP<62~&f3dbtP8pk`1b&d^=O^z*&ZI11Z_Z=TNc02Yu_B#$b z4m*xI${Z&gryOS-=NuOtmmD8Dt~#zeZaQu|?mF%}K5~5G_{{Nz<9o-C&fdg;j2Ra8khdPHlM>?rJzc$Ad9L2BzOH_*0#}i%*j3^Rx(2!iyN0@kyGFXGYqV>u zYrJcsYqD#qYldsKYo2SNYq4vYYo%+A>s{9d*Cy9i*LK%V*KXH7*Fo12SDEXi>x}EX z>yqn=>$>Zf>#pm8>l4>!t}k6bCEx^O!ixzl6FMYxPbf_g6XqqXOW2$6T@_TNN|jbs z`c)ZKWnq;yRm!T|sq(1GABnca8i@@Ovl0gF1aewCi!u^%| zq5E6+Bli#P|G59_{>A;9`w#bD?teVU!+1E4%oF2LcvK#Zhxh0`MvvJO=dpS09;YY4 zljuqEcszpV1y424OP*IeuX<{F-tg4&)bZ5wH1IU^H1;(0H21XhwDPp^wDq+2bns+& zGCf(IY)@BDcTZ1GFHfGQ(BteZ#!=X zZ%1#Iw~M#CH^-aj?c?p|E%X+91Kxq&A>QHMQQpzsao&mEDcCzc1>Qy8rQQ|Z z)!ui!>%E)2TfN)8JH5NT`@9FeN4#a;lioAl^WIC|E8gqgTi(0g2i{M-pL@UZe&c=Q z{n7hh@2}oJynhQwU +* +* 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. +* +* This is a subclass of NSSlider that is flipped horizontally: +* the high value is on the left and the low value is on the right. +*/ + +#ifdef USE_IPHONE +# import +# define NSSlider UISlider +# define NSRect CGRect +# define minValue minimumValue +# define maxValue maximumValue +#else +# import +#endif + +@interface InvertedSlider : NSSlider +{ + BOOL inverted; + BOOL integers; +} + +- (id) initWithFrame:(NSRect)r inverted:(BOOL)_inv integers:(BOOL)_int; + +@end diff --git a/OSX/InvertedSlider.m b/OSX/InvertedSlider.m new file mode 100644 index 00000000..c4fd5e37 --- /dev/null +++ b/OSX/InvertedSlider.m @@ -0,0 +1,159 @@ +/* xscreensaver, Copyright (c) 2006-2012 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. +* +* This is a subclass of NSSlider that is flipped horizontally: +* the high value is on the left and the low value is on the right. +*/ + +#import "InvertedSlider.h" + +@implementation InvertedSlider + +- (id) initWithFrame:(NSRect)r +{ + self = [super initWithFrame:r]; + if (! self) return 0; + inverted = YES; + integers = NO; + return self; +} + +- (id) initWithFrame:(NSRect)r inverted:(BOOL)_inv integers:(BOOL)_int +{ + self = [self initWithFrame:r]; + inverted = _inv; + integers = _int; + return self; +} + + +-(double) transformValue:(double) value +{ + double v2 = (integers + ? (int) (value + (value < 0 ? -0.5 : 0.5)) + : value); + double low = [self minValue]; + double high = [self maxValue]; + double range = high - low; + double off = v2 - low; + if (inverted) + v2 = low + (range - off); + // NSLog (@" ... %.1f -> %.1f [%.1f - %.1f]", value, v2, low, high); + return v2; +} + +-(double) doubleValue; +{ +# ifdef USE_IPHONE + return [self transformValue:[self value]]; +# else + return [self transformValue:[super doubleValue]]; +# endif +} + +-(void) setDoubleValue:(double)v +{ +# ifdef USE_IPHONE + return [super setValue:[self transformValue:v]]; +# else + return [super setDoubleValue:[self transformValue:v]]; +# endif +} + + +#ifdef USE_IPHONE + +- (void)setValue:(float)v animated:(BOOL)a +{ + return [super setValue:[self transformValue:v] animated:a]; +} + + +/* Draw the thumb in the right place by also inverting its position + relative to the track. + */ +- (CGRect)thumbRectForBounds:(CGRect)bounds + trackRect:(CGRect)rect + value:(float)value +{ + CGRect thumb = [super thumbRectForBounds:bounds trackRect:rect value:value]; + if (inverted) + thumb.origin.x = rect.size.width - thumb.origin.x - thumb.size.width; + return thumb; +} + +#endif // !USE_IPHONE + + + +/* Implement all accessor methods in terms of "doubleValue" above. + (Note that these normally exist only on MacOS, not on iOS.) + */ + +-(float) floatValue; +{ + return (float) [self doubleValue]; +} + +-(int) intValue; +{ + return (int) [self doubleValue]; +} + +-(id) objectValue; +{ + return [NSNumber numberWithDouble:[self doubleValue]]; +} + +-(NSString *) stringValue; +{ + return [NSString stringWithFormat:@"%f", [self floatValue]]; +} + +- (NSAttributedString *)attributedStringValue; +{ + // #### "Build and Analyze" says this leaks. Unsure whether this is true. + return [[NSAttributedString alloc] initWithString:[self stringValue]]; +} + + +/* Implment all setter methods in terms of "setDoubleValue", above. + */ + +-(void) setFloatValue:(float)v +{ + [self setDoubleValue:(double)v]; +} + +-(void) setIntValue:(int)v +{ + [self setDoubleValue:(double)v]; +} + +-(void) setObjectValue:(id )v +{ + NSAssert2((v == nil) || + [(NSObject *) v respondsToSelector:@selector(doubleValue)], + @"argument %@ to %s does not respond to doubleValue", + v, __PRETTY_FUNCTION__); + [self setDoubleValue:[((NSNumber *) v) doubleValue]]; +} + +-(void) setStringValue:(NSString *)v +{ + [self setDoubleValue:[v doubleValue]]; +} + +-(void) setAttributedStringValue:(NSAttributedString *)v +{ + [self setStringValue:[v string]]; +} + +@end diff --git a/OSX/Makefile b/OSX/Makefile new file mode 100644 index 00000000..67d19efa --- /dev/null +++ b/OSX/Makefile @@ -0,0 +1,158 @@ +# XScreenSaver for MacOS X, Copyright (c) 2006-2012 by Jamie Zawinski. + +XCODEBUILD = /usr/bin/xcodebuild +TARGETS = -target "All Savers" +ARCH = -arch i386 -arch x86_64 +CERT = 'Jamie Zawinski' +CERT = 'iPhone Developer: Jamie Zawinski (Y5M82TL69N)' +THUMBDIR = $(HOME)/www/xscreensaver/screenshots/ + +default: release +all: debug release + +clean: + -rm -rf build +# cd ..; $(XCODEBUILD) -target $(TARGETS) clean + +distclean: + -rm -f config.status config.cache config.log \ + *.bak *.rej TAGS *~ "#"* + -rm -rf autom4te*.cache + -rm -rf build + +distdepend:: update_plist_version + +debug: distdepend + cd ..; $(XCODEBUILD) $(ARCH) $(TARGETS) -configuration Debug build + +release:: distdepend + cd ..; $(XCODEBUILD) $(ARCH) $(TARGETS) -configuration Release build + +release:: check_versions +release:: update_thumbs +release:: sign + +sign: + @for f in build/Release/*.{saver,app} ; do \ + codesign -vfs $(CERT) $$f ; \ + done + +check_versions: + @\ + SRC=../utils/version.h ; \ + V=`sed -n 's/[^0-9]*\([0-9]\.[0-9][^. ]*\).*/\1/p' $$SRC` ; \ + DIR=build/Release ; \ + RESULT=0 ; \ + for S in $$DIR/*.{saver,app} ; do \ + for P in $$S/Contents/Info.plist ; do \ + V2=`perl -0000 -n -e \ + 'm@CFBundleVersion\s*(.*?)@si \ + && print $$1' < $$P` ; \ + if [ "$$V2" != "$$V" ] ; then \ + echo "Wrong version: $$S ($$V2)" ; \ + RESULT=1 ; \ + fi ; \ + done ; \ + done ; \ + if [ "$$RESULT" = 0 ]; then echo "Versions match ($$V2)" ; fi ; \ + exit $$RESULT + +update_thumbs:: + ./update-thumbnail.pl $(THUMBDIR) build/Release/*.saver + + +# Arrrrgh +ios_function_tables.h:: + @./build-fntable.pl build/Debug-iphoneos/XScreenSaver.app $@ + + +echo_tarfiles: + @echo `find . \ + \( \( -name '.??*' -o -name build -o -name CVS -o -name '*~*' \ + -o -name 'jwz.*' \) \ + -prune \) \ + -o -type f -print \ + | sed 's@^\./@@' \ + | sort` + +update_plist_version: + @ \ + SRC=../utils/version.h ; \ + V=`sed -n 's/[^0-9]*\([0-9]\.[0-9][^. ]*\).*/\1/p' $$SRC` ; \ + T=/tmp/xs.$$$$ ; \ + for S in XScreenSaver.plist SaverRunner.plist iSaverRunner.plist ; do \ + /bin/echo -n "Updating version number in $$S to \"$$V\"... " ; \ + KEYS="CFBundleVersion|CFBundleShortVersionString" ; \ + perl -0777 -pne \ + "s@(($$KEYS)\s*)[^<>]+()@\$${1}$$V\$${3}@g" \ + < $$S > $$T ; \ + if cmp -s $$S $$T ; then \ + echo "unchanged." ; \ + else \ + cat $$T > $$S ; \ + echo "done." ; \ + fi ; \ + done ; \ + rm $$T + + +# -format UDBZ saves 4% (~1.2 MB) over UDZO. +dmg:: distdepend check_versions + @ \ + set -e ; \ + SRC=../utils/version.h ; \ + V=`sed -n 's/[^0-9]*\([0-9]\.[0-9][^. ]*\).*/\1/p' $$SRC` ; \ + TMPDIR="build" ; \ + SRC="build/Release" ; \ + EXTRAS=../../xdaliclock/OSX/build/Release/*.saver ; \ + BASE="xscreensaver-$$V" ; \ + OUTDIR="../archive" ; \ + DMG="$$OUTDIR/$$BASE.dmg" ; \ + TMPDMG="$$TMPDIR/tmp.dmg" ; \ + VOLNAME="XScreenSaver $$V" ; \ + STAGE="$$TMPDIR/dmg_stage" ; \ + rm -f "$$DMG" ; \ + rm -rf "$$STAGE" ; \ + echo + mkdir "$$STAGE" ; \ + mkdir "$$STAGE" ; \ + \ + retired=`perl -0 -ne \ + 's/\\\\\\n//g; m/^RETIRED_EXES\s*=\s*(.*)$$/m && print "$$1\n"' \ + ../hacks/Makefile.in ; \ + perl -0 -ne \ + 's/\\\\\\n//g; m/^RETIRED_GL_EXES\s*=\s*(.*)$$/m && print "$$1\n"' \ + ../hacks/glx/Makefile.in ; \ + echo xscreensaver` ; \ + \ + for f in $$SRC/*.{saver,app} $$EXTRAS ; do \ + ok=yes ; \ + ff=`echo $$f | perl -e '$$_=<>; s@^.*/(.*)\..*$$@\L$$1@; print'`; \ + for r in $$retired ; do \ + if [ "$$ff" = "$$r" ]; then ok=no ; fi ; \ + done ; \ + if [ "$$ok" = yes ]; then \ + echo + cp -pr "$$f" "$$STAGE/" ; \ + cp -pr "$$f" "$$STAGE/" ; \ + else \ + echo skipping "$$f" ; \ + fi ; \ + done ; \ + set -x ; \ + cp -p bindist.rtf "$$STAGE/ READ ME.rtf" ; \ + cp -p bindist-DS_Store "$$STAGE/.DS_Store" ; \ + cp -p XScreenSaverDMG.icns "$$STAGE/.VolumeIcon.icns" ; \ + /Developer/Tools/SetFile -a C "$$STAGE" ; \ + /Developer/Tools/SetFile -a E "$$STAGE/ READ ME.rtf" ; \ + seticon -d ../../xdaliclock/OSX/daliclockSaver.icns $$STAGE/DaliClock.saver;\ + hdiutil makehybrid -quiet -ov -hfs -hfs-volume-name "$$VOLNAME" \ + -hfs-openfolder "$$STAGE" "$$STAGE" -o "$$TMPDMG" ; \ + rm -rf "$$STAGE" ; \ + hdiutil convert -quiet -ov -format UDBZ -imagekey zlib-level=9 \ + "$$TMPDMG" -o "$$DMG" ; \ + rm -f "$$TMPDMG" ; \ + ls -ldhgF "$$DMG" + +# Adding this is cute: +# hdiutil internet-enable -yes -quiet "$$DMG" +# but means that nobody will ever see the display settings I used! +# When finder copies the .dmg to a folder, it doesn't preserve them. diff --git a/OSX/PrefsReader.h b/OSX/PrefsReader.h new file mode 100644 index 00000000..06963740 --- /dev/null +++ b/OSX/PrefsReader.h @@ -0,0 +1,50 @@ +/* xscreensaver, Copyright (c) 2006-2012 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. + */ + +/* This implements the substrate of the xscreensaver preferences code: + It does this by writing defaults to, and reading values from, the + NSUserDefaultsController (and ScreenSaverDefaults/NSUserDefaults) + and thereby reading the preferences that may have been edited by + the UI (XScreenSaverConfigSheet). + */ + +#ifdef USE_IPHONE +# import +# import +# define NSUserDefaultsController NSUserDefaults +#else +# import +#endif + + +#import "jwxyz.h" + +@interface PrefsReader : NSObject +{ + NSString *saver_name; + NSUserDefaultsController *userDefaultsController; + NSUserDefaults *userDefaults; // this is actually a 'ScreenSaverDefaults' + NSDictionary *defaultOptions; // Hardcoded defaults before any changes. +} + +- (id) initWithName: (NSString *) name + xrmKeys: (const XrmOptionDescRec *) opts + defaults: (const char * const *) defs; + +- (NSUserDefaultsController *) userDefaultsController; +- (NSDictionary *) defaultOptions; + +- (char *) getStringResource: (const char *) name; +- (double) getFloatResource: (const char *) name; +- (int) getIntegerResource: (const char *) name; +- (BOOL) getBooleanResource: (const char *) name; + +@end diff --git a/OSX/PrefsReader.m b/OSX/PrefsReader.m new file mode 100644 index 00000000..97abe294 --- /dev/null +++ b/OSX/PrefsReader.m @@ -0,0 +1,386 @@ +/* xscreensaver, Copyright (c) 2006-2012 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. + */ + +/* This implements the substrate of the xscreensaver preferences code: + It does this by writing defaults to, and reading values from, the + NSUserDefaultsController (and ScreenSaverDefaults/NSUserDefaults) + and thereby reading the preferences that may have been edited by + the UI (XScreenSaverConfigSheet). + */ + +#ifndef USE_IPHONE +# import +#endif + +#import "PrefsReader.h" +#import "screenhackI.h" + +@implementation PrefsReader + +/* Normally we read resources by looking up "KEY" in the database + "org.jwz.xscreensaver.SAVERNAME". But in the all-in-one iPhone + app, everything is stored in the database "org.jwz.xscreensaver" + instead, so transform keys to "SAVERNAME.KEY". + + NOTE: This is duplicated in XScreenSaverConfigSheet.m, cause I suck. +*/ +- (NSString *) makeKey:(NSString *)key +{ +# ifdef USE_IPHONE + NSString *prefix = [saver_name stringByAppendingString:@"."]; + if (! [key hasPrefix:prefix]) // Don't double up! + key = [prefix stringByAppendingString:key]; +# endif + return key; +} + +- (NSString *) makeCKey:(const char *)key +{ + return [self makeKey:[NSString stringWithCString:key + encoding:NSUTF8StringEncoding]]; +} + + +/* Converts an array of "key:value" strings to an NSDictionary. + */ +- (NSDictionary *) defaultsToDict: (const char * const *) defs +{ + NSDictionary *dict = [NSMutableDictionary dictionaryWithCapacity:20]; + while (*defs) { + char *line = strdup (*defs); + char *key, *val; + key = line; + while (*key == '.' || *key == '*' || *key == ' ' || *key == '\t') + key++; + val = key; + while (*val && *val != ':') + val++; + if (*val != ':') abort(); + *val++ = 0; + while (*val == ' ' || *val == '\t') + val++; + + int L = strlen(val); + while (L > 0 && (val[L-1] == ' ' || val[L-1] == '\t')) + val[--L] = 0; + + // When storing into preferences, look at the default string and + // decide whether it's a boolean, int, float, or string, and store + // an object of the appropriate type in the prefs. + // + NSString *nskey = [self makeCKey:key]; + NSObject *nsval; + int dd; + double ff; + char cc; + if (!strcasecmp (val, "true") || !strcasecmp (val, "yes")) + nsval = [NSNumber numberWithBool:YES]; + else if (!strcasecmp (val, "false") || !strcasecmp (val, "no")) + nsval = [NSNumber numberWithBool:NO]; + else if (1 == sscanf (val, " %d %c", &dd, &cc)) + nsval = [NSNumber numberWithInt:dd]; + else if (1 == sscanf (val, " %lf %c", &ff, &cc)) + nsval = [NSNumber numberWithDouble:ff]; + else + nsval = [NSString stringWithCString:val encoding:NSUTF8StringEncoding]; + +// NSLog (@"default: \"%@\" = \"%@\" [%@]", nskey, nsval, [nsval class]); + [dict setValue:nsval forKey:nskey]; + free (line); + defs++; + } + return dict; +} + + +/* Initialize the Cocoa preferences database: + - sets the default preferences values from the 'defaults' array; + - binds 'self' to each preference as an observer; + - ensures that nothing is mentioned in 'options' and not in 'defaults'; + - ensures that nothing is mentioned in 'defaults' and not in 'options'. + */ +- (void) registerXrmKeys: (const XrmOptionDescRec *) opts + defaults: (const char * const *) defs +{ + // Store the contents of 'defaults' into the real preferences database. + NSDictionary *defsdict = [self defaultsToDict:defs]; + [userDefaults registerDefaults:defsdict]; + + // Save a copy of the default options, since iOS doesn't have + // [userDefaultsController initialValues]. + // + if (defaultOptions) + [defaultOptions release]; + defaultOptions = [[NSMutableDictionary dictionaryWithCapacity:20] + retain]; + for (NSString *key in defsdict) { + [defaultOptions setValue:[defsdict objectForKey:key] forKey:key]; + } + +# ifndef USE_IPHONE + userDefaultsController = + [[NSUserDefaultsController alloc] initWithDefaults:userDefaults + initialValues:defsdict]; +# else // USE_IPHONE + userDefaultsController = userDefaults; +# endif // USE_IPHONE + + NSDictionary *optsdict = [NSMutableDictionary dictionaryWithCapacity:20]; + + while (opts[0].option) { + //const char *option = opts->option; + const char *resource = opts->specifier; + + while (*resource == '.' || *resource == '*') + resource++; + NSString *nsresource = [self makeCKey:resource]; + + // make sure there's no resource mentioned in options and not defaults. + if (![defsdict objectForKey:nsresource]) { + if (! (!strcmp(resource, "font") || // don't warn about these + !strcmp(resource, "textLiteral") || + !strcmp(resource, "textFile") || + !strcmp(resource, "textURL") || + !strcmp(resource, "textProgram") || + !strcmp(resource, "imageDirectory"))) + NSLog (@"warning: \"%s\" is in options but not defaults", resource); + } + [optsdict setValue:nsresource forKey:nsresource]; + + opts++; + } + +#if 0 + // make sure there's no resource mentioned in defaults and not options. + for (NSString *key in defsdict) { + if (! [optsdict objectForKey:key]) + if (! ([key isEqualToString:@"foreground"] || // don't warn about these + [key isEqualToString:@"background"] || + [key isEqualToString:@"Background"] || + [key isEqualToString:@"geometry"] || + [key isEqualToString:@"font"] || + [key isEqualToString:@"dontClearRoot"] || + + // fps.c settings + [key isEqualToString:@"fpsSolid"] || + [key isEqualToString:@"fpsTop"] || + [key isEqualToString:@"titleFont"] || + + // analogtv.c settings + [key isEqualToString:@"TVBrightness"] || + [key isEqualToString:@"TVColor"] || + [key isEqualToString:@"TVContrast"] || + [key isEqualToString:@"TVTint"] + )) + NSLog (@"warning: \"%@\" is in defaults but not options", key); + } +#endif /* 0 */ + +#if 0 + // Dump the entire resource database. + NSDictionary *d = [userDefaults dictionaryRepresentation]; + for (NSObject *key in [[d allKeys] + sortedArrayUsingSelector:@selector(compare:)]) { + NSObject *val = [d objectForKey:key]; + NSLog (@"%@ = %@", key, val); + } +#endif + +} + +- (NSUserDefaultsController *) userDefaultsController +{ + NSAssert(userDefaultsController, @"userDefaultsController uninitialized"); + return userDefaultsController; +} + +- (NSDictionary *) defaultOptions +{ + NSAssert(defaultOptions, @"userDefaultsController uninitialized"); + return defaultOptions; +} + + +- (NSObject *) getObjectResource: (const char *) name +{ + while (1) { + NSString *key = [self makeCKey:name]; + NSObject *obj = [userDefaults objectForKey:key]; + if (obj) + return obj; + + // If key is "foo.bar.baz", check "foo.bar.baz", "bar.baz", and "baz". + // + const char *dot = strchr (name, '.'); + if (dot && dot[1]) + name = dot + 1; + else + return nil; + } +} + + +- (char *) getStringResource: (const char *) name +{ + NSObject *o = [self getObjectResource:name]; + //NSLog(@"%s = %@",name,o); + if (o == nil) { + if (! (!strcmp(name, "eraseMode") || // erase.c + // xlockmore.c reads all of these whether used or not... + !strcmp(name, "right3d") || + !strcmp(name, "left3d") || + !strcmp(name, "both3d") || + !strcmp(name, "none3d") || + !strcmp(name, "font") || + !strcmp(name, "labelFont") || // grabclient.c + !strcmp(name, "titleFont") || + !strcmp(name, "fpsFont") || // fps.c + !strcmp(name, "foreground") || // fps.c + !strcmp(name, "background") || + !strcmp(name, "textLiteral") + )) + NSLog(@"warning: no preference \"%s\" [string]", name); + return NULL; + } + if (! [o isKindOfClass:[NSString class]]) { + NSLog(@"asked for %s as a string, but it is a %@", name, [o class]); + o = [(NSNumber *) o stringValue]; + } + + NSString *os = (NSString *) o; + char *result = strdup ([os cStringUsingEncoding:NSUTF8StringEncoding]); + + // Kludge: if the string is surrounded with single-quotes, remove them. + // This happens when the .xml file says things like arg="-foo 'bar baz'" + if (result[0] == '\'' && result[strlen(result)-1] == '\'') { + result[strlen(result)-1] = 0; + strcpy (result, result+1); + } + + // Kludge: assume that any string that begins with "~" and has a "/" + // anywhere in it should be expanded as if it is a pathname. + if (result[0] == '~' && strchr (result, '/')) { + os = [NSString stringWithCString:result encoding:NSUTF8StringEncoding]; + free (result); + result = strdup ([[os stringByExpandingTildeInPath] + cStringUsingEncoding:NSUTF8StringEncoding]); + } + + return result; +} + + +- (double) getFloatResource: (const char *) name +{ + NSObject *o = [self getObjectResource:name]; + if (o == nil) { + // xlockmore.c reads all of these whether used or not... + if (! (!strcmp(name, "cycles") || + !strcmp(name, "size") || + !strcmp(name, "use3d") || + !strcmp(name, "delta3d") || + !strcmp(name, "wireframe") || + !strcmp(name, "showFPS") || + !strcmp(name, "fpsSolid") || + !strcmp(name, "fpsTop") || + !strcmp(name, "mono") || + !strcmp(name, "count") || + !strcmp(name, "ncolors") || + !strcmp(name, "doFPS") || // fps.c + !strcmp(name, "eraseSeconds") // erase.c + )) + NSLog(@"warning: no preference \"%s\" [float]", name); + return 0.0; + } + if ([o isKindOfClass:[NSString class]]) { + return [(NSString *) o doubleValue]; + } else if ([o isKindOfClass:[NSNumber class]]) { + return [(NSNumber *) o doubleValue]; + } else { + NSAssert2(0, @"%s = \"%@\" but should have been an NSNumber", name, o); + abort(); + } +} + + +- (int) getIntegerResource: (const char *) name +{ + // Sliders might store float values for integral resources; round them. + float v = [self getFloatResource:name]; + int i = (int) (v + (v < 0 ? -0.5 : 0.5)); // ignore sign or -1 rounds to 0 + // if (i != v) NSLog(@"%s: rounded %.3f to %d", name, v, i); + return i; +} + + +- (BOOL) getBooleanResource: (const char *) name +{ + NSObject *o = [self getObjectResource:name]; + if (! o) { + return NO; + } else if ([o isKindOfClass:[NSNumber class]]) { + double n = [(NSNumber *) o doubleValue]; + if (n == 0) return NO; + else if (n == 1) return YES; + else goto FAIL; + } else if ([o isKindOfClass:[NSString class]]) { + NSString *s = [((NSString *) o) lowercaseString]; + if ([s isEqualToString:@"true"] || + [s isEqualToString:@"yes"] || + [s isEqualToString:@"1"]) + return YES; + else if ([s isEqualToString:@"false"] || + [s isEqualToString:@"no"] || + [s isEqualToString:@"0"] || + [s isEqualToString:@""]) + return NO; + else + goto FAIL; + } else { + FAIL: + NSAssert2(0, @"%s = \"%@\" but should have been a boolean", name, o); + abort(); + } +} + + +- (id) initWithName: (NSString *) name + xrmKeys: (const XrmOptionDescRec *) opts + defaults: (const char * const *) defs +{ + self = [self init]; + if (!self) return nil; + +# ifndef USE_IPHONE + userDefaults = [ScreenSaverDefaults defaultsForModuleWithName:name]; +# else // USE_IPHONE + userDefaults = [NSUserDefaults standardUserDefaults]; +# endif // USE_IPHONE + + // Convert "org.jwz.xscreensaver.NAME" to just "NAME". + NSRange r = [name rangeOfString:@"." options:NSBackwardsSearch]; + if (r.length) + name = [name substringFromIndex:r.location+1]; + name = [name stringByReplacingOccurrencesOfString:@" " withString:@""]; + saver_name = [name retain]; + + [self registerXrmKeys:opts defaults:defs]; + return self; +} + +- (void) dealloc +{ + [saver_name release]; + [userDefaultsController release]; + [super dealloc]; +} + +@end diff --git a/OSX/README b/OSX/README new file mode 100644 index 00000000..551e3bb6 --- /dev/null +++ b/OSX/README @@ -0,0 +1,10 @@ + +This directory contains the MacOS-specific code for building a Cocoa +version of xscreensaver without using X11. + +To build it, just type "make", or use the included XCode project. The +executables will show up in the "build/Release/" and/or "build/Debug/" +directories. + +To build these programs, XCode 2.4 or later is required. +To run them, MacOS 10.4.0 or later is required. diff --git a/OSX/SaverListController.h b/OSX/SaverListController.h new file mode 100644 index 00000000..fef8a78e --- /dev/null +++ b/OSX/SaverListController.h @@ -0,0 +1,36 @@ +/* xscreensaver, Copyright (c) 2012 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. + * + * This implements the top-level screen-saver selection list in the iOS app. + */ + +#ifdef USE_IPHONE + +#import + +@interface SaverListController : UITableViewController { + + int active_section_count; + NSMutableArray *list_by_letter[26]; // 27 to get "#" after "Z". + NSMutableArray *letter_sections; + NSMutableArray *section_titles; + NSDictionary *descriptions; + + int tap_count; + NSTimer *tap_timer; + NSIndexPath *last_tap; +} + +- (id)initWithNames:(NSArray *)names descriptions:(NSDictionary *)descs; +- (void) reload:(NSArray *)names descriptions:(NSDictionary *)descs; +- (void) scrollTo:(NSString *)name; +@end + +#endif // USE_IPHONE diff --git a/OSX/SaverListController.m b/OSX/SaverListController.m new file mode 100644 index 00000000..484cb168 --- /dev/null +++ b/OSX/SaverListController.m @@ -0,0 +1,348 @@ +/* xscreensaver, Copyright (c) 2012 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. + * + * This implements the top-level screen-saver selection list in the iOS app. + */ + +#ifdef USE_IPHONE // whole file + + +#import "SaverListController.h" +#import "SaverRunner.h" +#import "yarandom.h" +#import "version.h" + +#undef countof +#define countof(x) (sizeof((x))/sizeof((*x))) + + +@implementation SaverListController + +- (void) titleTapped:(id) sender +{ + [[UIApplication sharedApplication] + openURL:[NSURL URLWithString:@"http://www.jwz.org/xscreensaver/"]]; +} + + +- (void)makeTitleBar +{ + // Extract the version number and release date from the version string. + // Here's an area where I kind of wish I had "Two Problems". + + NSArray *a = [[NSString stringWithCString: screensaver_id + encoding:NSASCIIStringEncoding] + componentsSeparatedByCharactersInSet: + [NSCharacterSet + characterSetWithCharactersInString:@" ()-"]]; + NSString *vers = [a objectAtIndex: 3]; + NSString *year = [a objectAtIndex: 7]; + + NSString *line1 = [@"XScreenSaver " stringByAppendingString: vers]; + NSString *line2 = [@"\u00A9 " stringByAppendingString: + [year stringByAppendingString: + @" Jamie Zawinski "]]; + + UIView *v = [[UIView alloc] initWithFrame:CGRectZero]; + + // The "go to web page" button on the right + + UIImage *img = [UIImage imageWithContentsOfFile: + [[[NSBundle mainBundle] bundlePath] + stringByAppendingPathComponent: + @"iSaverRunner29t.png"]]; + UIBarButtonItem *button = [[[UIBarButtonItem alloc] + initWithImage: img + style: UIBarButtonItemStylePlain + target: self + action: @selector(titleTapped:)] + autorelease]; + button.width = img.size.width; + self.navigationItem.rightBarButtonItem = button; + + // The title bar + + UILabel *label1 = [[UILabel alloc] initWithFrame:CGRectZero]; + UILabel *label2 = [[UILabel alloc] initWithFrame:CGRectZero]; + [label1 setText: line1]; + [label2 setText: line2]; + [label1 setBackgroundColor:[UIColor clearColor]]; + [label2 setBackgroundColor:[UIColor clearColor]]; + + [label1 setFont: [UIFont boldSystemFontOfSize: 17]]; + [label2 setFont: [UIFont systemFontOfSize: 12]]; + [label1 sizeToFit]; + [label2 sizeToFit]; + + CGRect r1 = [label1 frame]; + CGRect r2 = [label2 frame]; + CGRect r3 = r2; + + CGRect win = [self view].frame; + if (win.size.width > 320) { // iPad + [label1 setTextAlignment: UITextAlignmentLeft]; + [label2 setTextAlignment: UITextAlignmentRight]; + label2.autoresizingMask = UIViewAutoresizingFlexibleLeftMargin; + r3.size.width = win.size.width; + r1 = r3; + r1.origin.x += 6; + r1.size.width -= 12; + r2 = r1; + + } else { // iPhone + r3.size.width = 320; // force it to be flush-left + [label1 setTextAlignment: UITextAlignmentLeft]; + [label2 setTextAlignment: UITextAlignmentLeft]; + r1.origin.y = -1; // make it fit in landscape + r2.origin.y = r1.origin.y + r1.size.height - 2; + r3.size.height = r1.size.height + r2.size.height; + } + v.autoresizingMask = UIViewAutoresizingFlexibleWidth; + [label1 setFrame:r1]; + [label2 setFrame:r2]; + [v setFrame:r3]; + + [v addSubview:label1]; + [v addSubview:label2]; + + self.navigationItem.titleView = v; +} + + +- (id)initWithNames:(NSArray *)names descriptions:(NSDictionary *)descs; +{ + self = [self init]; + if (! self) return 0; + [self reload:names descriptions:descs]; + [self makeTitleBar]; + return self; +} + + +- (NSArray *)sectionIndexTitlesForTableView:(UITableView *)tv +{ + int n = countof(list_by_letter); + NSMutableArray *a = [NSMutableArray arrayWithCapacity: n]; + for (int i = 0; i < n; i++) { + char s[2]; + s[0] = (i == 'Z'-'A'+1 ? '#' : i+'A'); + s[1] = 0; + [a addObject: [NSString stringWithCString:s + encoding:NSASCIIStringEncoding]]; + } + return a; +} + + +- (void) reload:(NSArray *)names descriptions:(NSDictionary *)descs +{ + if (descriptions) + [descriptions release]; + descriptions = [descs retain]; + + int n = countof(list_by_letter); + for (int i = 0; i < n; i++) { + list_by_letter[i] = [[NSMutableArray alloc] init]; + } + + for (NSString *name in names) { + int index = ([name cStringUsingEncoding: NSASCIIStringEncoding])[0]; + if (index >= 'a' && index <= 'z') + index -= 'a'-'A'; + if (index >= 'A' && index <= 'Z') + index -= 'A'; + else + index = n-1; + [list_by_letter[index] addObject: name]; + } + + active_section_count = 0; + letter_sections = [[[NSMutableArray alloc] init] retain]; + section_titles = [[[NSMutableArray alloc] init] retain]; + for (int i = 0; i < n; i++) { + if ([list_by_letter[i] count] > 0) { + active_section_count++; + [letter_sections addObject: list_by_letter[i]]; + if (i <= 'Z'-'A') + [section_titles addObject: [NSString stringWithFormat: @"%c", i+'A']]; + else + [section_titles addObject: @"#"]; + } + } + [self.tableView reloadData]; +} + + +- (NSString *)tableView:(UITableView *)tv + titleForHeaderInSection:(NSInteger)section +{ + return [section_titles objectAtIndex: section]; +} + +- (NSInteger)numberOfSectionsInTableView:(UITableView *)tv +{ + return active_section_count; +} + + +- (NSInteger)tableView:(UITableView *)tv + numberOfRowsInSection:(NSInteger)section +{ + return [[letter_sections objectAtIndex: section] count]; +} + +- (NSInteger)tableView:(UITableView *)tv + sectionForSectionIndexTitle:(NSString *)title + atIndex:(NSInteger) index +{ + int i = 0; + for (NSString *sectionTitle in section_titles) { + if ([sectionTitle isEqualToString: title]) + return i; + i++; + } + return -1; +} + + +- (UITableViewCell *)tableView:(UITableView *)tv + cellForRowAtIndexPath:(NSIndexPath *)ip +{ + NSString *id = + [[letter_sections objectAtIndex: [ip indexAtPosition: 0]] + objectAtIndex: [ip indexAtPosition: 1]]; + NSString *desc = [descriptions objectForKey:id]; + + UITableViewCell *cell = [tv dequeueReusableCellWithIdentifier: id]; + if (!cell) { + cell = [[[UITableViewCell alloc] + initWithStyle: (desc + ? UITableViewCellStyleSubtitle + : UITableViewCellStyleDefault) + reuseIdentifier: id] + autorelease]; + cell.textLabel.text = id; + + cell.accessoryType = UITableViewCellAccessoryDetailDisclosureButton; + if (desc) + cell.detailTextLabel.text = desc; + } + return cell; +} + + +/* Selecting a row launches the saver. + */ +- (void)tableView:(UITableView *)tv + didSelectRowAtIndexPath:(NSIndexPath *)ip +{ + UITableViewCell *cell = [tv cellForRowAtIndexPath: ip]; + SaverRunner *s = + (SaverRunner *) [[UIApplication sharedApplication] delegate]; + if (! s) return; + NSAssert ([s isKindOfClass:[SaverRunner class]], @"not a SaverRunner"); + [s loadSaver: cell.textLabel.text]; +} + +/* Selecting a row's Disclosure Button opens the preferences. + */ +- (void)tableView:(UITableView *)tv + accessoryButtonTappedForRowWithIndexPath:(NSIndexPath *)ip +{ + UITableViewCell *cell = [tv cellForRowAtIndexPath: ip]; + SaverRunner *s = + (SaverRunner *) [[UIApplication sharedApplication] delegate]; + if (! s) return; + NSAssert ([s isKindOfClass:[SaverRunner class]], @"not a SaverRunner"); + [s openPreferences: cell.textLabel.text]; +} + + +- (void) scrollTo: (NSString *) name +{ + int i = 0; + int j = 0; + Bool ok = NO; + for (NSArray *a in letter_sections) { + j = 0; + for (NSString *n in a) { + ok = [n isEqualToString: name]; + if (ok) goto DONE; + j++; + } + i++; + } + DONE: + if (ok) { + NSIndexPath *ip = [NSIndexPath indexPathForRow: j inSection: i]; + [self.tableView selectRowAtIndexPath:ip + animated:NO + scrollPosition: UITableViewScrollPositionMiddle]; + } +} + + +- (BOOL)shouldAutorotateToInterfaceOrientation: (UIInterfaceOrientation)o +{ + return YES; +} + + +/* We need this to respond to "shake" gestures + */ +- (BOOL)canBecomeFirstResponder +{ + return YES; +} + +- (void)motionBegan:(UIEventSubtype)motion withEvent:(UIEvent *)event +{ +} + +- (void)motionCancelled:(UIEventSubtype)motion withEvent:(UIEvent *)event +{ +} + + +/* Shake means load a random screen saver. + */ +- (void)motionEnded:(UIEventSubtype)motion withEvent:(UIEvent *)event +{ + NSMutableArray *a = [NSMutableArray arrayWithCapacity: 200]; + for (NSArray *sec in letter_sections) + for (NSString *s in sec) + [a addObject: s]; + int n = [a count]; + if (! n) return; + NSString *which = [a objectAtIndex: (random() % n)]; + + SaverRunner *s = + (SaverRunner *) [[UIApplication sharedApplication] delegate]; + if (! s) return; + NSAssert ([s isKindOfClass:[SaverRunner class]], @"not a SaverRunner"); + [self scrollTo: which]; + [s loadSaver: which]; +} + + +- (void)dealloc +{ + for (int i = 0; i < countof(list_by_letter); i++) + [list_by_letter[i] release]; + [letter_sections release]; + [section_titles release]; + [descriptions release]; + [super dealloc]; +} + +@end + + +#endif // USE_IPHONE -- whole file diff --git a/OSX/SaverRunner.h b/OSX/SaverRunner.h new file mode 100644 index 00000000..0284ccf5 --- /dev/null +++ b/OSX/SaverRunner.h @@ -0,0 +1,74 @@ +/* xscreensaver, Copyright (c) 2006-2012 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. + */ + +#ifdef USE_IPHONE +# import +# import +# import +# import +# import +# import +# define NSView UIView +# define NSRect CGRect +# define NSSize CGSize +# define NSColor UIColor +# define NSImage UIImage +# define NSEvent UIEvent +# define NSWindow UIWindow +# define NSButton UIButton +# define NSApplication UIApplication +# define NSScreen UIScreen +#else +# import +# import +#endif + +@class ScreenSaverView; + +@interface SaverRunner : NSObject +{ + NSString *saverName; // the one currently loaded + NSArray *saverNames; // Names of available savers + NSString *saverDir; // Where we find saver bundles + +# ifndef USE_IPHONE + + NSBundle *saverBundle; + NSArray *windows; + IBOutlet NSMenu *menubar; + +# else // USE_IPHONE + + ScreenSaverView *saverView; + UIView *backgroundView; + UINavigationController *rootViewController; + IBOutlet UIWindow *window; + EAGLContext *eagl_ctx; + GLuint gl_framebuffer, gl_renderbuffer; + IBOutlet UIView *view; + UIImage *saved_screenshot; + +# endif // USE_IPHONE +} + +- (void) loadSaver: (NSString *)name launch:(BOOL)launch; +- (void) loadSaver: (NSString *)name; +- (void) selectedSaverDidChange:(NSDictionary *)change; + +#ifndef USE_IPHONE +- (void) aboutPanel: (id)sender; +- (void) openPreferences: (id)sender; +#else // USE_IPHONE +- (void) openPreferences: (NSString *)which; +- (UIImage *) screenshot; +#endif // USE_IPHONE + +@end diff --git a/OSX/SaverRunner.icns b/OSX/SaverRunner.icns new file mode 100644 index 0000000000000000000000000000000000000000..0f052ae1bde28f2b299ddaa77c786f833a14a43d GIT binary patch literal 62554 zcmZ5`V~}P&)a}#uv~AnAZQHh|ZQHhO+qS!>ZEM=T^L`gUZffuBwJO=EbLu2HRavn# zwsQsm9Re&=CTtGvF{0bJxPk$s(Y|I0??F(7wMFT`F7N`94;*K$3hR@z(0+0(4aFV? zG_KmxH*}D%noC9ETQ#Ctr~*6!Izh#{BM7=u7P`%W*g4IMBNqj;$0u=u*A=qb;wqSR z-M(|8oH`~qLn;&{`~+m3GLbNH|EXbng+i<-C*+HtEdWk)K@yJFz)=Ws^3BiyqfGMn zSdA&O?7@16Vx4mubv81@Ry&lPe|_{y*EvrVd*>%{47JH|95yct!LY8*>}dq*8Pkev z$-0V9_S~TSU^2Gdp1hd6ll#Osx4HE78^?~|R@s{D1ZU_%C9qS5A!{J<(0&V9;p43f z3GAMJFHA&m=4SB9OwEP@6~!})y_#ZNmQ54MH5@dvNQy&^alhDLgdvggVML{M11^J9 z)Nx+)YdV}rCMT3|Ly;Q2XEz5tr~tlxoITJ7-$RZ%h;36$*vW|IzEqk;e)|!pG@KKx-r>@Vs7}%$igU=aaVrT_#0H;b;*Gsc z0P~~$3Mv3q0+4%1&GyU0w%wc){yvjqXufhB zGsEQ;b{M%nOHYm2Rr>J<{*FYjjy1nH6PIj+V~cMuU}(}3T+oQ2S;>FG<}MuDx0st9 z4%^rCx6eaE+yZ5rX1XA@6%Km#Fckx?pl)S_7@5HR3bZCd?v?KO71S|@Qgz_{t!=qytdoOZjFqSio7(&JQnBS zYXeDW2Z@jL97f*Y$YKkaku&s5QwyDjm=S*NM<1;<$U~6rE4Rc;^K%xJHsQvUS1@-9-9BxS^47!;*e0M~`afio-9zwM4M!iFYGqoHJA z6`kK0+=|We3l`7WiekhzL7|c-O4wsH&g0F~V@ZQ>QCeW3+GX+Fn<=Uq?tJH@Eaagq ziY?=}@I949G;Y^Y7azs(RXz4zB`YsjA zxkAJV;urRok(}J^E>x^X`K%l9vZnGjRfbC3cpKe!qX`dPH$g6G16bBy6=^!wtbKOh zMg%;JSHCe!{X!HM*H_g#g|WRlh~+ehKlK6X?qfoy>?&o<(*`0&XIiCiX_G;EZ}UGM+uOHL^O1 z;I=Z(pS{-w5N^8=$%O1%f`$(yeCFcQ+`kD!9rxv811Tl_f7dTe(qSpR9EXMY&6N1@ zNDOQZPeEv9Q*PGU4q>vob0*#Mo!QWmnwtFZNt?81a7wQHs4mbTmlb?XJV$w-YiP(g zzwg|1dz8LtD#%+L1{7HSnVY%c2OszSCE!W?Zs+bpag!2qV3U=;{*2N*6Bg{l%du%b zO8}#>&GxBIGPpX9A>6aHqE2`geg6Gw7Ovjzp~;Pg_Re?E1&vsf9-WI-n+hI;^qFyh zNXyw_GPaLBoGl`xM~De=R&F09*cN2=7co>|2bY^a-tArN%01p?$MTJ}x!6_Thvq@) z!3bMsA5?trW^_taxJjjQ!;6TVuHSdjmL@!wlfshHj4U7WY!8dp1(sn4E{G9@mS5>k zyL=I|X4cO4iwE(56t=LdtV|n;Y=3S>-QcMMoy&)YVCv(Z`!C&|VaCE9i=uW%O(50x zAW{EDJnA=mME8|IXp>QFr8VLg3#M(zT?l=bUY|LRFJ|5{(8vR>t$=(gi&g_+qu)ZX zH$Lqz{y8~V(8K7XzFRoaRMjzkLI|4n5yW(B`SCl4O7wwN2#+pZOtDZ~kB2$X_u2gr zkQv+QkC~{ky$<}qV1AH(D$n$y6sMhMF9JMu;!l`2D=6fx>`T$;&iF)6V96B3>$+*h6pTe+gp1uOj|9gtmmij9~E(+ zYncYx)7Ju3frL0%W`Y%8ThE*+IrnDCzJm-g8fbhAXf`b5+ttj}xw)eAw?{<$+;zZc zxuZx@v&ecsA_!l%jwCbUPQR7y3@PI1H%4*i!QJc!OKb#$DOy$|y4K_DXjgeF6k+?k z+%h#i#2C{hOEPtEk-TBC7gk!%e_~20F;s0?US}W|TnEq97J0 zQdR3&=rHn?2a+I|P&ms;?YEH6le~3XyQ$lywuD6Kj4&7iS2;v~I?^~|_2gz}R_phk zr;K!|rgc08l%FcVFU!u01QgySPYH1iRQ| z=AsnXb*3Ucr6|WB{>drNH4~))=@F>Vlj!cNv)sPQD=WJR=^j#HK9pW-ATm|s^$B~O{ z2NG(8ttKP_axp@iGnqU+PDH$UQK_v|AsU$#b6p=BSumbV2TpGIjJD=?HXs++b59$!U`+eV?0<~<(?NxlrlW|+%a0CdRz=eV$_IK zAN*hU29$j5zL$9eYy+!q>AoMdEzcO_F!AIM>W`_Kvt__J-SeTAGvi>L+tYwl)Cd#m zM|M=G?gx5dL#}K3!;cY{T?6)FgXN-&dQYbU;QUwDzK5G0t+C4O3hGm_i#vpIjkoS% zFf1a0VM3MRB_;KaEmJ3j>g0=p%4I}TedP}h>5%^f!Rr4>-EoX})aV&B$JM7Ff&293Ntu^Qq7`-oz zf=T0HfW@l>wIE7wrC z2e0U~%SKVDl?e-W_E*-{Q~BE78fZm+q`||(e7rokwN(I&Wj#EregC(DLU$omXCiEd zQESO_wxR|Y)e)y*V>B{2-vdnC=mLFPtqt!Aw1O=gZCQ7c=%a`sMknX{Z#@)vAjK}; zu)K(h>a`QcR&QqNKv9&uhOEk5IarE=u@qha4Y5b+y-f)l*za9*`wswoX4!eJl zq_rfCuub+#g;3zy)rINK+m zDPu>cv5Q;J6s>RzwD>0%v`L}wV`fvJasue|BeoH38cy#*N$MQPjcf3gp}9p`aqtplNhhSo zcOE_1Z2pvH*B^#Y)jQ9PgC48xzO@C!iK`o+?dmD-B{L@fD``{d6 zFT8R6?23z zlu6s5`%UTSbnYcxNAy8zPz);9N&Y++!xdRnR@dDaQ8g1)tRFKWQ1VDpI|LU`Lbb@(n68O$6~@+e#{lt%jdw zM)aX@__Y_KpU&R`eJs|ZGayAxK&Q6zdIz2YKE9Fq*M zvv!Ou^A^^;rWrvr=iktn23MaqpQv$bj~Pu;K3=yLazt`xOXgD1H(icu?pB{~3z)=% zX;%rh^xSTBcFAvI7Sn?{V`}^EU&)Kn#gc1W6yri6F*q1|F&Ci()nswv?leetyJVe6 zAyG&ux_3d^x>dKy|Jn;;OoWs840T&$CgXBVHLvfe2tiogY}_P2jYkm#(4(ub3!P(q zoGbFiHtKl3JLC(pF{XEJN0uCEg(c-uiZ%1FKG~eyo`?Z@(0c_q`X|RKQ))CO2i+#|PG{uBqCAJ^`e9;S^rHpL&6sMvl>4 zV{~{go0_*;R{pIbEI}6bo}xS#@c3iCWhycqwyJ@8rCQJRSHF-Q#$bWU3=8L%T7CPe2}WeQD2WC17B`gH|r-f(BgqW&^~Xgq{KjOEdT zCtf|ib-?JYOD9ETlAcBPS*AJ5J;kGw@ktjtsX%OtO{P@Rmu@hax<>s}D8P_(|;F88Mj(U$c{{qx6{i!*AsRRL1M! zSzA`$eMCc2F6Ukftw_)sI(>hBbqZQif6xB0u0ND2d_px^lw z3MT?L8^2}}b5lh;_TF1eyhzFS9cPcVjD)OP4kINRQYWLqfhf*|=#_Eh_uLvLOU%5% zOiDKA9-j!8B5sR@b-9A8G3Z~yDt4!yE#yl+<3GX8@B;fHb!N_Hp1--0>S&Q*A>MpL zp$YhHkMPBCtz~tW=W9+q=F#t*x;M#9y|1OobL`%De4ESk4v`ceo&4tjpqQtCn|GYU z<=g-=^9meHLj|+4n@Rg=fP?skLjT;%VYt$5ifXS<(71~?59j$Zpy-Cp`B*%%KXYht z9v>zx2Uy-W+6j!0dykH%h5*vaI9&{AQbSZ?xNvG+mraYifut*}J~a9nq?Xg{wKRJi zf5w{!#PJhPev&y`DcO1Quo<>Z_emJdoQNx}d5iX_D>P@Llr{zlC0e-x$)kGcRkNn! z{OY&=QN_lniOFwNfp9pVDtQqVk%#NVm6N5V@7n#Hv3>Qq*_^PwMHvC!wDpDBx)6EF zz52c%<%30%Rq=kbp?ZhUhK0Z^&e?%x$}vq~2nWZ?bABdD5LSQT1zhurcBK`2c{^1K z#37SaCef109zVweI9bSyM5o8TNx~&MlJh6zb^VZ6;Q@&xFsujzcL<&v;bW;igs&4u zdrABFU*f=H9&t@2=FtW|QjoOs0yE7)(MU_j}&ugjGI@G{g7Ct7%rh(fq&DeSHxZ#aRXRXP2i%veU-=(8pj1Z}fWf zvz;bp(}|iko<$#4ATwV{Bme~H)P8Tu?ykb1S0sd16)Z9iyTKN;Ci#ml?@JD8DzG`s zq-QHFG4aj#de9yVgqllp;6i}xtx%#v=sJYSQ`GF{qh_%lC2z3BzFCXT$M znD2h|Z*ZLrbR^1J==5S71|Xt&zKe=4lPL|qjzKMb0qH;H{Fz=jK&dZCn~1YzC?iS={+U|Ne(j&8)R* z#g6{sd;L5g1}_UiO#5@=An7-eoT{t**(bd$hpW1ST&Tdr9Q(k*GJs?n!&0=$WH4l^h|6eFDFfN6OzCL-&pxv4hS%y^v(|8a(k z*j(|b{L^wNO-%HvUFCjbXuGs(Qp=6hq5)HNaERBC?3t@*Ev*dAf>aXzN8$q{cuvK1 z2-q3~Yknpu980$XMy%2N6mCO^3kHjlkT{jRmSaVE4{g@mjMr>%?K2Z4 zQYf0;z+UuEznOQ@TcUZg@YMBC&Z1K~`TiD*w9|kii@f0WJY&LF8 zK9GtOk;$oIaxb$-s*Eci*=N**=)dq~BXWGPb{~D2#V>|&vDquVuATe@(gJNk5NDXw z|M82!KY@%WI>KGu9>JxLZ7uqCVH{^pDpr_J`5pr#7s%>4$A6n|oZmX!G;;4M`s%jh z$rLMA>h@F#Ic;9MW*3#JEPtSQ^jduwu}5=IMvaL0-Xljj*j+Fctwp%EO^Xq>+7DD8 zGnIM$fFskMXfFy0B>zS+6!bT24h1r>UGHvRp#kq_>jlQpqUq6Gy3`0=hrA?x>L1O+jLqYc|J@Ou6U7lqZM8wH1o=lnpgIp{i z1q(5vbO81KWv)gxSzX@`)9$w>bZRy|>uXs~F;=Q=kA}^g6JK3El~O)D zHe)AQaTr+1ocTSnDl>+XL8Ky*_~79O2tE~IE?^|;~69mxH?rrJc}#UOUESs zmz6AsH^uga-CSc+1Op3hAt*_!J0fn-i}4l{l{lpUErkv<-fuIAXO@tAB_aa=s=*$Y z!8c{qXY}8lW+zB*WpxJ48welO^td~yUtV(GL^^Uudq~-%_kf-s(=@MPWAh)1nr{pH z12z~gH$mj)2sn{CzMFmR@ZrdtY*@-y@*B};m-|6+V=PxTtGh4zC8)g{@_K=Ejds+i z5vQc11fo>a4qdY2MUu7iNNm4{%MVhH(5P5j7#&Aiq>PJgMdX4kU+6=L^=zL=<4qsX z0ygZ>C!-&?r4JLZXW9n`zQ|gvZZ`KP)+vwOT6D%!+9n`SI(z=UJu ze1i$`&9a^i?FpWy3jj9HjTlt_THh2d&EHac+wbZGBBts!8%xW>qfyc`V}I3!k!gqB zgItPkrFl$5O+|-@_2ZmISj>H}Vi9Aa)S1He1IhQkY%P|24%ljW4l3s8KK(`kRDTzLhXiB4ocf z@%M@yHoV+92T7&37o7R7o)Be~q-u5Ks?fGcW*YB(>{*SGW~y+-gw6&@tXopPWgcGp zeI)Z5Jvy)5re_pAiglwF`deF@n0hJo#u_@Kr)bH2ogF_zd;bC2Eb+&MU`-tB2b=I4 zTpE8et5{ShRt%}9SbdLxC34r9O?IQo_yYnbjdW>PE0#^sxMR5_wJP@&IHLggP|mt7 z$J7s-tb_9nFD$jhQFg9WN~e1|_PMKIdAL1PS5uma2X>|3u8KVlP(C&_uZ#v81$7Bc z2kG}TINCq?#()9j*LwkS0Rfp><894L8pi>%_VxlTieH@Nc-l%n%Wh0G{}gCP#Ttw~>7x?#KhZ&?7dt#0Tk#FIU6wAXcOm zO?o0{jHB2jOM~WYV~psaYq1qr&cGIFE?{gblE%rEh5+v-NKNcbt6Tagr9OhR)qt^O zqp1rQ*gN9Dkx-{#sL0TUfVu&=LNYl;us9-U7Bl7n9$S96Uz0Gl%k*yt?$CDXK^MG) zjfoKFWeFDVt-@GCMt^(Z%jteI5;fB*JxR+6%O$%;^5amQv=Q%+Etg+e+$Hz{h`zYz zd1grkNBs%q%1-)n=5}7(=EHa5TAOvhiO{}vX|X5x#Avm~;TtS#Ebhux!)k){N~@Kf zBuS#UThOJA(oy0+s9Wv+h7tT*)(q}zAveM3x4EZLw`tq@&vvKzmOVmJTyCi@Is^rAsb)drah0(u2l47W+JH2(9IwYQw`u5P-7W0XbB-%J!%;d9-2v{~K!_v~3Eu35Y!V7n)t zm@<3B><05J*deG^Ylwn{0BL5SQT)aq@*JRmo5-~4blBT9%$%0UNJ4Z1)KTD{HHZF=8AXDVqP}!2js~RCB*LvzAfzrk=DkuX1e0B)UZ^tQT~C{BDv; z@%}K|0t!`jDWV1uz!z3j;gWogbfqj2sT*+Sva^drjI6n*o|m*kfZo3Oz*a_kAPAVY zuN$B;Bm7va4!&{DpEkasVy0__(*c`_61$u;6lQdH>w*B=36ez2@vEnr?j}s5T@rX5 z(?f@@Zk^V82e>ulnuC;Pc=mN<>l&K-zE*tz3WEY(-E<09yvmd1@hd#p1;Mw|15>Q6 zrhTcyT8g|TNl`ZJMZC@(ne7^t;D3t(0N_Z!MXfN&{~!Ec1w^ObB{Pp&r)UdqPaW`t z%6ev@sP8I8Tff==5#+rt4jbIShZK6=EiKusmUD{1sE|up(Q>N=gK@DvrQPH<4quOS zSp7FoUqAN9Et=|2`60-+YnQ~8%aD^K2|MwsxEZd_MEZYoEa9J~b7%nDB~tiHhD8$-;JOfSZi7K}?AT(^m=}Ih5zyok^d!pQm5`C~8=trm#-ZM)gm^U?2 zeP8{or?YAbt>Z7@VcJl*Vs5P>;*5*m;-``uiBlhqMIbh6(3)d0aV?Jv*2^FQ^x0>9 z&SM4_RHXsWmKw8Hqs;4l5l;y(yoPdm_1U@ficzXqz~I#8H;a-ENf17ugi7W zJOxFiSF&-ITE4;kqNi#L5Rnvny~Ca{T4QiNL43Y9`Dr6CrUQQ?{p2B zds^txyG~u&W%>{p^N-k!`GY-$Utp*0ksB7CvL*p}DT{6)@eu#0*@YL?fflcMs--N1 zEJ6?dB63_6MMeoU_(ug8ojj@L*~8cJ8bG#a?9%E1E!bm#!jkEP7!DB{w$0$R|JuUZyouLcQ5>qkvB`;#WvB`BR+Y(D{OCvi_qq-Fs1bbCo(s*7{SBAM7(L z!U_TbEt`@q&_rc+gmV(ZOgzfK0`#9%pdJ5a&*ASjuDCV!i&?kkp)9oliufNHZbN@n z8A-%JX97V%A-Jj1K^bIg1N`aG8FR#VF)mJv3H1>%ZrRV`8g8ySVph|Bf&oFhDF`lg zhHQmlo*lv5%n_*4v$P({yaTig=SElV#00}!YYmebE%a9fo(irCl8U)Ei#(zVC&g#Zy-RdEEU~X!D#ewd;ivc&$nsiIAg|jm&xm7Cm|bXy$$IE>qOPByAPO+3$|u27 zia#IK_c1lg-T(gSeF?8N%lvS&%e){6EQJw~mIH^<)0k}n8z8vc|{x7^|A z7xbZ^sEiEa%S8?dqw_n-t1Cfpr8jof;iH(6+bP9flk$g{`|-UW51aoVE9L&v)IO(uz@jAJ!Gb5)Y`JY1IA^Z z>IZskZR7{txAm{zsAHBkYsqRU5LtDN`A#!raJ8p2t`Jxs=*r&t=*;{vl*oV2k z_;bf}tMdk~6guHti7R!kyx8yY2WMvudYQ?VuS6$6QeoGE5OnTrd+XY?_feWbMI zJ)vTU$AW0kKbCdqgcG%m11OAnNgCuc!I;J(8Q*c)zJI&f-XUb{=|Pn+u%A{vqb zV|_&4m&F`^cz)$O;;lYcgr*Kh(z4upal_@V@isV+NQ>HhH!YPAqtKvp0KKDi6KGU4 zX0!_gURvxPsQ=3O?xxYR+?4S{ViR=BF?|ir1|gO0bTfL-lieoja={l_RBSeG357$# zL!!w!U%nBstVcRE=^PBe37z)UK-X<3@<`hs<+tQ%DzD6v0(6%U85k5h#Xo5(6j7f-b79 zLHlbVERholTa_7qL_9d5!>EShD-oy?w;=>?naZZ4N6F4C4(UY%)CqK_rgRD0F5w~p zPNgWeUnpH^?dCIblgJCA?(gcH9rW$yIlms;b0Y=+Er>>MC!nwS#>IcV zepqDfYu`lQRW}3UCX*&~Ep93t3(u*RF?v?ON{RDl-4?Ce47eNc9y1vJ*&x*XD{Dj~ ziv9#hADSBrZ2LlQ+8|sgP=d8siRIc%Sq)Mw=*5(mWP0F`<^cBA+Z8RQ$A9IOKIxLZeHt33~L%aC#MhiLB5C$p*WX^m&kl)sxu zdeLsU%L>HG`jUbzPX);OilUA7w`SMp28!)q4OUuZu8YTK{)SfdJU8Lws9pQ&zo6;c zlVtbyGO-X|)`yw)gl4gijJEiFeLv;xEHHk!9`M?mJFaJUHHOVwMGfT2eyh}}P6lFd zWw?$oy~3Bm$;kN{lKe3pBDcKU=~q4TEY&0EUeH}$?1a~=fPM$|DCv1}55y>N*?!@> zxN^)3oAI5P;Djk%_$M*MH~yY|6TTqlOdidS25$cE6b^OeZGcs=vI0A6BGPQe!Yk+Z zG|0&Dv+#R8`hu=_wE8vabZj4KJ5UX+nvqZYV_J4jyh{?oO$;!E_H6B8XGQ*b9d|SS z@rSpZKRpaYkYNhy%Bay&rhPkYM~F06e#%PG{$6f7W-$xIt5Cwz{mY zLfv7~Ut2xcO8k>8Kk=oTAgNfC3uM)nnd1(2L(Z+Q>B*+Lge(uqZh6Vj=2XUST}{uK zfV%d6O*ic!xr73b(i!tBt=@yJ=O-zs%EiQJyY^I;==j|Fk}ZSg!_)?D{JB5sR|Zp9 z*0%>XZes9e%Nne(-Ii^AIOY_@h0@jd1i$D{2|NGl{3b*6h}KZPv<+mM4Bhbi77Z0Q#_rk%p_t2XUGE9eqgqL8F2e?8JF}o zE-#*0=iSDE>Y&YpXC9Ir6lC}_-`EO+2M*S;BncKuk}z*!F(gN!YCvRP{~UXg#K=m; zt9dg{+}`>1gwAt4c&23ZVid~0ie=2;IM};MK#lr0P>LmD6x18MgqHp@X5dxtX>0#; z#b$;vjnPq^0D+1D7^#Xgo_l1Kv8*~-=m%K=QcRZpdkY!NX_!ntb1#KJ>B+y|fI&Ox zmw1ISk9)X{=R4@lD_&}*GYy2&UMNuL`wN~v!OAbSuPEL_&uvim+fSS7qzvBq!D zu_JHbYGa4kqJq_VrS388CdlB6cpAI6!MtZ)j4tClJLb%6#u(kr*M9McN8TQrcQYqG z6XC84$Rol+QaxDWhjc^*c+_-+)05&u!7ulc&WdRIa zlt~tkBbs1M!eVCvSf$HQ+Q<0s_L;~cKr6LU12^+&0xi$~;VR16+n=PP!u&jhCJ}Tg zb`-b@GPnToPP=|{80c~x8yAhRUYxt2pEBimX`ERbc^}twj!V)peO5(|OmrC2EY-M7 z!?#EoUJmU~6ufvJLUG)TR^rDI&$d|hqYX>6Yv?hoZg54lytT||Sgq#sPCBpC1&TxB zwE1<6MqY4jw&C92VwIA{--mnS^ldyvlRi1in5j=T=(odm)&OC_n8tfb7u@T%@TFNH zgYk-w@fz6S>t@6&EE7SVGmm9X%{3ruy5>ZCCORLwOEcdXOZ1b{%eps~>Z%nlN70 zcB%;#1co;=rq8aUaB0@oZefsdiAdoe6cUtGYhujX-U}7ioNB?O=xG)ncswNpO4y@D z+lf|^yzh;@b5KI8Zub!y)NF&mWs;}g5@5+!MA2&snra8KD(vhnQ9ovgtj>s%o381! ztULv_*qo|#@oia|zPS&YcV9A(XJ3WFom9d5WV8V)LU}EZad@A^TWZKtk#={4V-UQA z1eA0fko5*2TG2p@mMN;=nm+O6e$jAi_E+;ZMrDQ^T6BIqQ6XdHyvpARKZ2t4l4$P^ z2->)T;Bs0zOKgxo!WZ*jeOm(wMJ8n_oNqlD@}2lZVMn(Bw#^TTR%tjg7Xx;qk1j(O z+Wo6Q-3T-9LX-;lKUAT1tqDPkl(6>iR2mUz8CrlM3q*`2ew7EY`sT6yO2$_U7Je95 zKNjki0^3k^!R-RvcE1DZEZESoA4fQj?s=^BdrmK~MIfl@+ShA?m5LV~c3X!&zaO{! z{bUlCWP9Zc{hU)+9OId8H0kZO1@8s@hB9bRsb3h-nUDxyR=M8wAOYXJ-V^A>v@iqUB=(^NV|0_1Uty|8~Y*VQ8iNk$O&5S2B zO@)rxT5G+5WiyZqCG0Q$xE~P|4s3vWqBi~z=r#1dER~-*k{>?z3f%|9f|EX|4OMkMnBA)Ht56F-75rax@u*{6W5_#ZeTA?@5br|Q34_xkZn z)%GVz!@83|@;@O?T}0SiV-@vN#otG&io~`g+Oa{cN1^J8rC{ta$A~XKyokZDdA~;^ zVsktl^nLY~8MEV#`Q`j0El4nqY879h0{fZ67|eV$pqhpjM;61r&baye3MsBc^p;p9 zm{y&1F9B@842VCH$vt?j2tyq60>TTK&Qa7Svt<|iliF(c6`_lGS;9B`LMq6ooY3-- z>HF>5M^tdu{)gFW=M-$9@9^h$@c&6^91Bk}apVIV=3Zfu<$DI=O=9DNrsU2LX#t6f9*{L3sS zn=>ffyishPhGVFoW5VDbwkBJ&KJ&akB)hBt@fwQd2`NsXPoKu8AzsFx zNZ~Em!PvVWyzmZ%v!mwV_sxJ96LgWr#il-FHrjRlu;5fgtPF`@coA?M*eGVX{zDk@Lo$D@_HG#j@{6o-hW5VM1g|GB(1A8yHh|{x~fi03NSO zVEkWx489?^#~j|~p4vtt?&zRsuVNKA7iDI3+Q$3|&>nLWi*+UyMlaejRAnd{dlPNX z%%5FF|4xBZEL5|S>4TX}v>u1zO?Yw>u9xcsp2<&#*bbil~ld8vqLI zBjI67nMa<#R7k_5kPz1g@Q{=(oxp~n2E#B*Cg4iRVQGHRP%)Xi&F9=@t!vSpE#i1! z`@a;C%ld1UmS@S8oJxX+@%A;`{3yA2QV;@i#&Jih<$8ACq&ywC7d`*&(PdUPv?sPz1Iu#ovxZ1A|=>!8A7`L;|FOBAEjxB%wnlIm{U>Eks-oeWO zCz&3r=QUE!RHSw6R#Sye9f^)o(Y6(fYIG$KuWtdF{^krM7r)|gd>jaHP7lh`?x0t? z*m@KAJw>L^Sw~^}bpZpGyn&Jh<(>5gx7G?I~v6gqpI!GUFr;E)y0uGqiF%sKc6Xb@`vMN#AC2els`8Fx=H z3BnzsK*os0fwt7$fXWz)>X;x=T)7GKICs_udmmB{6z>v%dn2Nf;wABiCV!ILs~7$EGtb~==^KGH6rp9#t1^k|^DHOG=-tX-mxAG{34|)R>4K{j zO56FaAYn#~h&G6Ny4GCX5_d_^nGHL`zje7~WdEeD@En zwSfVFSnIs3$#&fHL?g53X?DtBT73fgOCHn739S>_``{&V4M?GcP|IH-leB*#&wT~I zwmDM(XZHH2td3jVQLR(3t{*?pun*bCoH#TTduJ%sC;N15up_T7%MbXQXS00-;!4{d zwuD_UPY)V2K7E@1-xzmh#~~RT5WGU)%*_6=kYyy@R1His*cpOk~EdCOL^)BYq#QoHO2B&{-MkAz&mK z79{LL-EFQTRljRz#>BDD0{gyqu?gkCoce0yj0YD}?J{?+k#UKna7O39ia>0W3I!%| zug()+`>Aw05iF`NW^2C1a`^l^o7a|YB@5`oE1;Rw2Z*n;z6j|_>Gx3T#~&IKx0vb_gh~fy<@buCx2uM|A#pvzPn2W*64aIO-D4^X8|0 zP^%1)5r9uXn#YfE!LMc*xYHoW8fR5E#g^|8W5nkLk-dzJ1noKi{YnofO9B=-{PFCX$nl14q!!X;^7FpkYyoRE;&joM$ArtBdCda|??6S51D4{)f(K@Wp zkYTjK+$BBl7zy50P1y7<b z<%y|Y&Qi+Mx7HWeZtzDIYPV4Ir)EDhu^`wo9=fq}DPzs&?=#}Wac28>8x4Ke^0uIy z^wHzg7H8Qb{~h|%NQiyPHR$&inHB$Vsor%=I?mQ_-EN*z#2P;^G*1exC3wE9kk&kY zoTy6L04p4>H5?hDly^6c8~*xm4q^0Z93g%!WNe=xODks;(*=V$;@+%eExV@2e0c&T z|5E+yt&`O)dUcR?yWL3vD{IFS)mQngSQ-YQV~x+K?R~`>ikM~MjFp+$2h7BDh94d# zhSyLb6$B^f95F$RlCLH2m#YXzs+IIj9(?S`Y);s6CI)MIKwH3w-Yd-d7;U;eteuro zrNzUhqKtKI>WI^R-{q2+9pmI=`ItZ#bh;nRIQE)V_NOcy>?QH|VT)YAiInPgixO7c z{H(&d5lBS5&O8$dZERlyrst>x$$eX0@C%GLrAbr-HBlM8kkxQ%6bxY-q;-&Z=T)oJ zu1K}VV5;B(_q{`9OR@SHir!&VYhqF8j%&()&0JvHq-T1?ut;&iZnP{9$&vFwHp<;={caY-ZNRtWt0Nr zr7In`lDS-$ve43|tMeupEO>8|oL8MIGBJ8p15ua$phGd$IDZzvF6M#X^P{#gabr{Y ztzQ+#Islx)-hVaGnvf$`zx}spt6}c#nmf!Uc!t~)V1V?wf+_P{l6i(wZzj={;Xwdl#}?phVkRrmZdi- z{>sxa9Ak33Cht1qz>AMNRW^+Y7h=%9M||P!LFi4ef3ebP6ZZw(=ZX#Uq9N7a3-c7J zr|%U4d!^{k+i3)An109e5iDqmUQ~@OUWs2c;o*6WQklU6dl-~CX1)op4}*Qr$c{ey zP8zY~t#3$Nd_^iQLb%D%w>_>fY|TD<_rd174>Ow(b6T2S%Xs108Z0@?PxFlJt}!MV zfe3qtGo>20rg7^Lw28zpIgWysY2 z6Ww!aX65K_gs7$t>mrIz21c48;263xfg(MF=|&)5WMrLl{;R!{cYs?%$di&64~hO7 zeh&3sHd)^uq-A@4zcxnL%t1PRkX*=^i1;P1N^P1?#X z6b-rs1z2oitzysQH^621FYy920>m56AsvR&g#Lh*v1)+%$Gy>wHSQZru*Zq-mZ}I8 zPy?(%x7b~<%yIxqG;nFWe1i4ZC9#=DS%4v7Fh2`c^dHjBe=RFf0twH7km(5{Rj*kDN4Y@E;^@DAvv0kQxKwOK$L7#9cWSRoalERLv zq<@!b_xt&uQa4#_^Ejo(LMH@_TM_YBRtzP%WuvcLfPUE0x{F*5Xf0hHYi5-6vPUb& z)Xu*%+rcOQZ`^btasw%QTis`m#;@b{N%^uhXa^Qhy@e~aQ;X9dL-Y7|HXSHH5<|dm za3bsqZwn}~U&V$*#AK61ctK@Y7$r-YV|rHgW4-V%WLdJGzvtb~EyDf(!|VBviLc+t z*Qg5Nn(b-2{xEWH=;nr^_n44pjLZLRz4Ke(22c6cuF3J=7{6adr^GTgseS>nA z+AB*lBxAH-E(GcUB86UgeBci9KMtrZ5k@XaZ3QOkV9T}9r}Ph0tLa|h{STkzf6Upc zKJNV!;mJtHtSCcC7K`2xzGNrag}G#@u-aoB<_<^ov8vCTGbQjr>}&mxVP&937KR(X z1eDxLc??;tCH=&b9j5?jwXhQxR2AyyS{^M92{pS1=T@~mK4IKwC1$cBymcsSAH_Ut zC9%P~E#$G!nYfzs0Wu3dxn4%zaT-(?!uyJKMwvs@ZtXRRk_@VHC=R<f~A2c|MjPI)c{lEXaIpmsS<#{gM%vCc?3X+evWX zmW)yieB1hdI0 zS2iix2H?oem8QMK+zf7>tY1!PioOSo%rT2(I3R4%>7b4zZK3GdClq#GtU4YW&gP)_Y%=yL z6UgIV&1+M6QIsAk91-3cEwH#^;YR;Y5d8b5@gW>~7ZzJfmQ?gKeIgJh>H8pAy4#BV zaL9w616@*CS-McgppZZU{G{8GjuDk(YTwl|iz)n}QwP;j1TA)#@CDoGZ@$Dtf}*j| z;`fRFW&Zt_X4SHC-fXHDvU=>MO3q#0#-O$?-r36bH{Wzo-tIM-SB#f4#KUzvqBVkR zBq-lW!Xq+fF*7Mi?4r~%`xCDz?VVGpNj0lJeO3ktxAI;c{?Gs0Yl6t|KbW}Ldo6kQ zQ0=Wfju{YxRHBKkz11L~9j+^#dx(l{i5JKi8>WDNbcvFyNff)! zV$BDb{>42fzm!}d(-4rG3P~0aSWw>_~!^_>o6{+mC)vZI$jWY#v8y?}2mFVm0|Ay^P5k#N4-v#1INo{{WoU zsf9dB#6Hjw9_y`JG~WhHCRe)odhRc|zepiGY2PdW)mYvy2L2hL^(~eUD|Jx#@9JQS z8rK;#{far;MJ@)>0WM>EnqWGI8JHa8Ib+p z{2xrvi3eRU9!0n-;aovSDlGV@@^e?d!ql?vm?WM2`19`D8mBswP8VsdM02^jl z*SMBZ;uk%UzNbgKTnE;|5-c_faw4&Ign!Q zSC$?flECoc8>9zpvH@oFTftZhwXuhoz5-p6=ZDmA_xCk1YqzDUd8B2@grl0WLMJVRcUb}&l%`SO3q z?f-11HKd}Zg;8vh3L+3Fo|D#Y@F0Vd{%XD zrmhS%kZ2|-(CF_l{GV;CoQ{SQT6Im+bBOYwf(D3Bfs+kL$@9lYAUPA0t_mzdzDbIv_eJo zc5;2&wQr_>qi*?y_oSx^J@{lsx}G-+IHp6kmj8jxY}_pFjX5v>PkIchE9E$vyH z|4hzxc=sXzPbY}Qso#i&dW}WDE1b#}RNQ2SLGN3CcszLJh?O486dv#m;|51ba*N*P z&s|Vor|j5rr!3BOshh*$Ko@JW&1iq5>J5ivLsUat3yi7Oi$?p+9Bqir73QGkvK5p@ zw}pgy;x(5NGW%j9X`*54CIi%W1P?{L47>jJ$P~M1KHS!p%EC6oaA+OVl)Q zoUhIz@a=dc9`=9%K5@)(UM=Z#sf?cvSnPHPX~Pz+Yr?rbs&2z9fd{gdqY8!(ssCUz7p&>ga;8>s)Z)`fJ&yBz)?NVdyUKldBA56s!@%`SVb>e7yo8g}h3dsTGFKy2nhZZ`|1-T5^O{k0^sPYmD_@AV@YH{lB< zS9~yK$jO<{^_?Fp*7jkc;n{MRBkqz_E+Z-EJK{Llg~-uZf;6Fnv5Fw-Y^wys>|!vF z)6DH~)4XHOT$M4>g-x2q2`vWC1ZvRn+`x>hEXdr9A^bR__fp;V7oOuL%+gQ<6={N? z>aI9?kWdcl40%!M){)!9%@gJEjLDqM8PA|Uq&Y`jXv00$l!#O7lNB1EcL%qWGK}An z8qobo^L@=(v&bd)n>WDKVHHDCL0#X2TvO;#D`76une~6(!1d0-bx&tJfW{reE)ROs! zl^W?IHz(b?+-EZTu$r$PyCUFkU|+X|_JdZG7EHsR!+>dMIzzqVk#o-R%A`PY%E}y+Gk|?Z+1rC3Y%NO|{t-b+ zSs=XMPK8maIV9_3gO!u67*cHYlB3nN5`CxhI(+NTy~ zd^mImTaD$v&yFtn+w}#A60eYJ-Fy|Led*kHHUv4yTBui{A>$_jzHEbWgV6v^{1ZSK zzqMkbk59?U9-Zh<*LEabfDJl}xr9%H~ZL#@-%cP`5N>$&YBL+ggjnXq4 zOO5yT5!LDRuX~lt@3r#ZJVmX)Lg!B}UJ&!h7x#K3Nso+7f9IWl0QG-V@aIWd=pFd8 zR7e~tBKu(QZC%@^*K0c=Fgvqr>UI#q2PI!Da2fk}QO>iRFMAd1P`BYMuvXh!%l=5< z;^$u(3%ri=TN`^6D)V03cMD{2eeh4`M$A#6#@*e#M~9Cdhz97+3Z6}n zC+xPNp5!dr$zWGl`MR{}l0kMik4*Q|)Gq{~lEJ5xVIO{l0I*H>pon}z<0JRmwU$!C zEZPZ)GSogYDB$|!hhs!15xDt&12||{7^qUcC#3y0_!p8idGWEMl%!_K2iArVun}XM zyNYvaG#eD5zPLovGARlsrjG~iY+cnTKTHMJ`Q?fTBflTm@4xOfw4)JvWhi3Mdob}y zpI5~pLEh6z5UjSM>T9$8*kkYCnfS93%JZ*8RQ)nHOp}0PrhPGX4K}L}ce#Croe$e} z6%A*%4Y8r~L|b^rJxLozAOwy>J+A{JLXtodTc ze%tqh4dCM4$(xShg9ZMWnBZK}a;(z%FL{~HRWe;7$Mh^KH5Zbc%~5FU?AL}ZG;}>L zqLfGbp_H=ivn7$5YB!H`P{BVO*u)+Fz?Ybucpfr*RI8x4=Ryi*8InFmQIOEjamis? z`0B4`nie_Hp+hWxAB+-ewD}+n?(`+?2sHoF7;Dq+`(CeHhC$1FH3v{!hsNJ|&d?iB zx)-#@1%zYLd*DPgpSLwZ!U@&6E!Yf}p+2vXOz?3UfkUZTMGIRiFL)%YqU)-wOtQKB zfLKh$icwp#dHq;JV=h8G?1WN*pi^8nos+xk=Xu84yPL^Eo@g-zlg($lY8e^ZC3)QsF2)o;phi+6xMyr=<+i5{L_;9QEu&&*A z_yP9-JXvykzsLBf%H5ULf3n$rSXExP(YMrWU>jr@zEfkM?8}c@>bP5{5*|Tr`Ja%Q zlvo~Tmj7D5tY&Ax;~QiPk8~J1lBIP&ziaW|eV;n_oO0JZcNv73Lak&%-Mvn?jZ6CQ zY9YRC6bZ94RFudeAd6ZViCXE&jvkyv1~9_KAp?3ozG~f(*Ht3T0EK#=mnMhuQ@y{T zZzW=EBu%eFyk6@(H{6Prax!gGe6pTZmoP!q@CJM<4H)Fj88=gLs2;9%7FaYp z)8^Z;h3K6KWW8meK7-K4{lM_$!DqJCl`D{0sJ?;55z{xTBrtUxkaq>fmwg34LSLC_ z7WL2U;%T$tVA;Uxu*0 zCkt#fA;W9AW11^qB(aqry{EY!#k^0kQiVg{3tqca3#qI)`BGX1Q$^*}M2UgO*P#GP zqP<*$as?T%P_C%OCEfL$u!sanq1nV~9jDZ{P9Le>It2(?V&I#x>c6!;u_g6#E9FG_ zDSHYN9PW$@mI(*4a__qy+#mT)!0uIlvqZngZ;o^RA>x zDqUU|Ieq+O`Z4;VuqYT5Z206>Qh5tcXZOM^PvVZz+Eoi@_9IW<5j|=}+Ep0mkSf+d zRE&&#rrU1&2io1(lI)WQ(-mJSFPVr@`_R_#va#(E%Wk!B;+ema$ePJZ@vbB z9iud=2YJl-6NP+B#HVhh)Ls9Q8#Wp|%PoWi++r6BS)HwiKJf_5S{WUV=+lEsiY~OJ z5$V#^Z}|s{1o*IXz09~?^iH%4J6pK*zvK(`2PM$t8>48ffeVdbvrB{?n7N8fs4>Pv z*-XtT;Q2-OS)}p)7MRpGisg8e4(OaD*wcVh0nNHYvEBtlfY+JE%f*y&67~auq{NpMyo)&yi2YrLq-7v3ff(=&~5ZYsuKE=C6m||^>{$03I z^RT&@-Se$D(p&pR8 z(NO24x7DzqJl1+rrjOA1M<_U#m2j17g?y9>P+o!Jg&}dGPi!oD#*^)DS(P6AS@YWf zN4md>Sw|C|2?VJTVjQol!*CL4p1`j~~72 zZC@PX6YdbRyr|j4?DfDMqZU;s4U8&L_v)R`RtUN4eD2MGR}Dh_S1KN*kd;g;@s}r- z{%xto`jGOwQ(?~}Q!9MA@f!w4$KdlAt>*rw@*`83X)) zN10*$RmcnXY0I|{nvdrb3cA9-zHDYR*`;+FSgHE`0K)<E?!?UJq7{kiMSawVieKVs>;*y?z|NQ3S2Vgz_lDo~ZQ2LlNhp=e1d^lgD6T)RSG(23qG9RX3Cz*r~-mgJ9UQU7SUu0fAfvY}ek zG=isx_BKuTuyKV&tc2(ZLtl>whPc8GQ&0CQhs?vgKBFj8Fg3I8gdfuxp_H>3zJgD0 zdl%tv&kG+e5rj~e-V?k= z;VRdzq_F&r6>XFOVY9})tUxG=`O9pSZrE>0tDGYK0#nQ>6kR9=PwT8J{k-(>wgj%F z$QVbHyI%=BTQM0Q;(h$QGRbwVe%`i&4~A?AXyNspDCZ8j9?j6r<>Cl6Ii`40kdiQ3 z>ftJ%Oa-B%cg3UhF$)o#f~zu?vJ40TXk&jv!IK{q-f!+vP_&}d;WfgBh^~lAF}Qwh z{Rc(!Z~qUW!K7YC5RaAdrFQ)yH+VHGd@gi3i!i>Jnm;>PjwfPi7Dk>dyC{Z0$x|YF zRyK12;P3K7x?;fLQ|c6>?hb~yM+PN>pJs3j6oa;P>TEZgS75pxtiQbPd}BuYIZId2-V-y ze)!5KMBrjH_zo4eh-LWlHV$l{QLhj*yco`@s4XWm)VR!G8;(p=2!qsJ^0??vWi~kB z>=U~`Uqb`B#~X@^EmY2G56q0uYc|-`1`y`*6~0RxhC%kfJn&=?w44s<%K=wg%}w82 zmoN2@WCyq8jeTm}zERPxKP)MWIF=Q^3ww%;X`h;%n#=`6W}puGXvVfaW()^$n!sh|2U(=DkliE-l4_rHq*C z&tCf);hf*(`^mmizp;zh-1%=mN{>KUxl7VyZqe3{u>5m=ZKDZlpXD&FWYbAF=P7GT zXfUgy3KmQ()fn+?7GtZDK^mP9Vlw@L1~=7M&!++^gtJzH$9Ud4XJ;N)00AOqRm%{- z1J977+9ge40d}5895x81h~e+$FJcb&WfzE)NDZa7{l&q-j14mKriY(AR9f@kOE{N{ zABSX5t6Jm)pLaz(8f&vka$-sKTF+MhvJQ+h}?J?UD-BM(m+J z&8x-<@F>vsh3wm}8CJ1Z6u44L6Fsg^N7 zOUq`Nq*YJT@bgsqAg%7A`go>ehr|XZ0jcK{udEz0gQBWaE5AO0Hr~t5(RnCgk2IRD z21|IBsv??1anRN?c66IV5L0d92hSn|Gk2Ix8h`E*l9*^JUhtVN4Jh$f|0{a=-NY?a zgEAJ|jKfE#f~*^~f6f%G=V`ks?7U9MO1j73x~CYT^_?r^@)yBGiC7EyS6+7&Vy)KE zbq!d7g$>n#(+00+UlHF5quiW$cCf<`*j8=uO`8gRHi1T(e(HXFc0nTK**3zK;7c$kS+%!A=-h zb$$dctsbU%7Q4BOnFy)X`|#Dp?vn-Q)r#+~r{1RvZ69?uY$c9ea4>wwnOSZF?;!FJ?OS zp|$HdD3I;16a5AS8Jlop{%N%_bTfs5y&|;yC@x1_Tvb?8peBOtKn>n~t%c9r6xqvU zgK~wd^^r9sp4h4vd){uOVJTXdJ%V~0g#Dl-p+?umn=ueu%T__$1TFI7ADi;z5l%5R zZJbMUMC7>0fFB)qB(Tw(4tf8~7P=BSrqbT})gPvYWqvv@2He62@6&Uc>c58Vx)lC-Lm(Lm3zst*zB>V(`s4E$uj}Lpz>P(+c4) z9VNUKV(`~x3m?9LhrKsNFuO@i=e%RaAEHc-zeVSJUa;y`J_bfd$8+*tBQsJCFIDro zt}tnF7?g?EhXARNru+hwBb3)ng2|J;}R6yFRy4UIoE5$r`%e=#evHE>UnD4?izw z2Ms4ip4=p?ui|71%vwzxAy=>ta&JKk#8fdQ7k;%Y!bCw&5ggb4`RO9(Q zf^&e8@MuMFFq+lyHZYCd)Ak&cv!k^)Lkhn7>vvBjC&d|t_z@ft*|DVCJy6W$%>I%A z65n9)ZUI;wlA2(k5vT3NxsRd3o}PihxmXT8;;X6d%!$9GB4PN#&8cCjXZ)%_zZii@ zdUGE030Y9LG|mQQx^@@#JN0KGnip2D%=8af(Oz2Ze{V9+19!D@OrVfroQ4r|g)lS9 z$-%=SvTd@moLQrLKm=e;Z9Vh!FFy;NX$x967=!dXEMoV-*=uJneD$J9cFQ#f+;gco zk-fabE6N4D1=hEBd2bptpV|b|q1px&t%9rX+nBmrJ#}=+J5XH5L;;Djo-;s{(9oaG zo1v!mbENWBbE9TUNSO7_fwn-sWh z_9$`omHl54+J))?9zzn3^_!H&E0ad|wE~&_kav)IY2)n8H-B%4mDMU9 z=I~FOtm^C>Ra&MpLPjfHGDxrP+gkKeeO5VM<<2WqPO4okB@7f{B_Q zjcv;ONV0DTNy52)bPR;S7|$7YI%`D?&SQ>RWea6v98RJ1(U;@wJ3)IcfyGbnCp%J% zPB0Uf`2(;}f8_%W7DG;}Rq;(ZktB0+JMSv&6)Ab+5zIGBW_4ZYJF;w7)L=vS&DdF@ zOX$D#tKTN*f_|#th(3!8q0@rCQs%TL59|*kh4_fTF#BihaHBbsAP1(lRNY^}%1Gz{ zUD33s@4hk)&iUs{U)=UVN&{n8BDDpF@lp2&r(Ee!)Dd2 z&5eN{LOw_87xbVWaz}cdX=+L@4~X10e@`#?VwT<5(PCe+UhJnnXaO9ZTX_F!Osrdm z)Umhaq`n=8avhQ6Tg%LVg_{Sq9dziOC)^*OxBD73vJ2mEuPcGmd2`4c_6pXa z3$MiHKTptL29>FZ=vm~ndBk6|WA#^VZDfZzw{JM(t24dcFcJ4e?s6Xo`VF%;mnEf+ zyn`gX`lL^dP+Q+Ayh9F1I8Lb1){XBCNWu+{DLlgdFDtsB4uCc3VGQZT^gWb)hl9=-bw0_cqqJ&}6pj%w- zGCV@?w`^`1Nv>Zzw`?FW~3Jv=sN``%nrj|IrG zpS>K-Qi;9b5<`y+pTxonPezs$VY16vD!sS{zk8h;I%-8ZK-&DP(m8WxHcP6rgc|sJ zflcL$d}L7O>JRzes5shDZc_BMVkFibZd}#t5dNs$e>EB~js=n<1t#yijPtfyTf+JZ zgaqOp>uk(ykx3i(Udta4MUIYEK~Lofy?!{Tv@d7Dx+j~BtsHZookcqy7niFw@yJ+| zWFnD^_trOoaMEPHSsNO%&&62tGPh4iLx%n%M+T%$yLl%j5*__`;7rp=!adIv_ z4w);~PKgV*K`{zS_j1f=Ugcr-Bd{%h2vaa|AWOVz|K%j?WqKb!@l>R9 zOC@RVqXQ7R%S*P)bpJRULFE%q&Bt-K< z5hU;)U}c(ZG-RXDD^h`=jKa+3p|>i(TB-$6Go=omlB)P5WS4J3DK9n-ZvH6y$FM+} zgj01)-i)p2ALRJHXMleOjLRFfX#2=IS)b~mvWl=@pW_)^dPl5JcK;(nb{(w3=r^NYD%~DajiAI2lClE!Cy=~ z<2fFlE&!hz)>mFlOWw9KQ5d1+QWRV=Hp)Fr+hfIBja__DKIwLS8alQpp-9c43r=kZ zuzai9u;E;`NEjww{YqHa)-gIlfBf)!*iaeHWOaccqHQ4P*{|7gNBHB=_Uaj3BTkC@ z!|&53sANRv*Vk4T{j3lBZx+Bl-m=X(qY+b^{?uSKeJB?9zxh5>DB^cL4&bxI7J_Z% zyP6mmPn=R@iM}S2p=pce%Aa?x)nGVKpiE8!_d_mj39-OfTcF5>ML7p1`HJFh$G8n( zx7U*ze}-%B#hSc%>qR&k9L@bM&BtE{kimgm~1JuV9&DRe1 zrd0%r!cJen&!<`vXQWPQoQ{V$T8?>JX`mDY$viuRv+Ys=+?T|NYB0cO2HQH4GQLXs z%yFQHX0{~TRzhgMiUp)h#!Yum(zcTMLG|o%-<*Lp7N1a6KpqD1DAL=(X(M>z3MN2e z{Z8w_de>dDtxYs7H>|EHmX9CBMc-E{PVZ(9&={DZOJEHucW@9~! zD~2}mIop!APOMUS>yxc8cA?yqe%fd1o+0EL%Xp3XZ*z+q)pp{wwDYwQQ&9-9lJATS zS&_utY4S(eJwG*63&Z8*Ji9%Cph{xmMkEebJWA5Nojx?zFBFp0Zf+yc&}gYzW-{4_ z0mwUaF>3U;aJXI9`M}w=pv8rz=$szbu$Ybdt7L?f5R2>MDAYA|2=`le6i?}2F(3(L zWsDmfRJ>QF?)Is}4K;<=6#$DnOttb$2%A2uhD~hs?5Ak?Qmb>kWuA8Bi)u|AWF1*^ zK?M#Xc5Vr2zM-SAkHaLSu$w6GFiSR;`Es(+{rew%dt!#iwSd ziP0}J*0Lh~gY@A5QqmAww{*j-L$tC({zB9`QcZy8eS87 zOGTB_+BdnjXPOKQu$E=Z>26>tcWTB1?_3b3aP2NomtE6cvIi)8GDPML?B1H{^*bf< z3_EqOVA`7Vhn7>1WE}wMOpG!eo_l}|DE5BOGX4#>QbbP&B2Z@=bs#tsuElpF+&@cpd(`g}v#|7mIO^-9q7c&FK9bVn ziX&y5vkwaxy|K(L&w@#eCw_l4V))jr|Ecjm*=@kpHt&$)D1}~|;@C!nYX-1X5M6F; z1iG^p+F2pR_t5j?wfNHVe@jwX=Z>YkK1z_A4HW{-&d12q$7Z4^z5mtf#nz1v&g%ld z`#fT*=N$d>JNSzP$vO59(5%7fe8V@}{=14vE?3w0yy)*w%mT{o!kaPvfgntB#`88{*Dvr7&jw2 zrjHk+$`i;-6}RhlIDb9$2%{I9)0U@g`67#C=Jz9XS3@rS7D#*o!xdr{JOx6D5>r5y zh!!!p1lMF}g;f{mgy6Vn@}mu4)O5BTA#;vrm@G0U9t?Ty?Yy@;ugK@la(E}e|6??& zSOClFKZtJ8Pi-vbUt`vk7mP}-7wohfn~ipM=x1)MFn)#z`Q^Xh{w{3(KmZK=NKHr~ zti;jb!`0i|`gvd-5xPChFF|{<-_6^@9giOd{+30H=TN{)M6lGoHP>JN&B>Wd^dEiD zJ4DCij6Q=cy?09*z{<~)#-An=2#6srbc59KWWx6HG=N}Kfp4>16Ql5YRAJZU4%tgJ z=@JlV2j15x%JNUZF+0Tr!p7K=VUOyo40E^$?H}sC{hcxgSKB5(t0d^8Sn*cvw9OVf zAkuQz`CGDG=ZB)Xm4nQ-=EITU`<#;#;2>-JY77g?9U@nSH%oHAxr|J6HN)jj{H?Tc8hg3x@l+c3W(t@~tpTVi669imi%7bd4yoDze=6cNR>yOb7PwNaaxJ`d)I{HotG@ z9swh}H=|k09_Wn$>1{EE(k3T_k`OW7db5weak;m6 zgCA`$0G_fZ;S^=w--1+9Zu^gR+>(S5m)t@@5E1O14nu~=XR#&FTjkM453ib9?4c_F z>0Ryjq*Tz30^}f2cu}7OwHdKj;annF0|t&b$zG~XwXj}_OyCh*L@Le(N0GFLPlVnu z%iOzlzdg547QI(b_#cQXKUlGEZ1zu1xE~>3zmV)t`r7@x-hu0HbT__%#BaQkAA`=` zfux>Qzx~bCyB+$y{9P;f=j&VEYCzAt-oEw^#LN#w_Yb(==qsKdLPPIkStJ$n zbG2TeT+r^9yxMwsvN;-fv%4GI&FdgR>%r&TcdkXV55v_NC>q5fnRyKv@S-au{0~h6 zpb%^_#yQP+DYIH$Ti9LG=2i?`Q;2;fC37ddC_Z1=SU@;cVTh&=Z(PdB1EXwF-_J_C z`zv?LWMIJdaI({m(fKrAWQ_~KK4T`%<@b=r;ad!_&lue-tH>%9j6Tz(d&6W#PUbi+ za@yuH{|YkycB^Zplk{Q=d#}D$<@c4cT~2b*JWUOD=M0WaFs9)KxY;O#O^74Q7f=fb zmY?AyYTT>}Wy~ z%HWy}Zu+**zSyGc5}ElPOeh~Qg`tqU51*}js;^(;Q88T8bA;uipoI@WTGMS54Awd6 zDcPEY81*E%5(#aSB_%W1E2>|UuEkRRTb@UJgBTEOreTc>bfiC6QsJQ^+mYX1qpzeU z4TMC&i&T&>e9}?&kgrGxQ~R9JK{LOZH;Z8dhO)R40%Pq0IaKLNJU+ zS^+!o170DX&=5&ABTb)kex9wFWWf9bw&Py0;HH)b5xDO#n$+JbXF~Z%E%rt~*5#B_ zz9^a#l#>{~j|#ZY3)CXO-uVdG%LuWeP@^Zg__L>!xQZG>04Ey{jq%>aO#IZ=1nDD#)W06?TIxk zrP;~hzW~0jUt*|Hy>SBpzs##82%ZiZ*M(%pYs4yAmq)G?PY$3n08b&~cPR+AGt5btC z@18UosR&%d0vpd!ntxExb_M(mZ5#$JkTl-}FAC_e#pF~@k{lZ&UzLiRHThv+(%;E- ze}WiS60NsUenXu0*0SE>nCA82v z8L@4enmDD?;UC)pU;accRms|f&snKdP!8YdugS~6<$#D}uu8jiDD>VX*7s%cqxrIw z0uX0fS)5l{iyN=Kos3EceP~4ej{-GUIWEoZ!U2hhRtRs3Vil)@cKX9e)ZK*=w{_t* zA}7x|C>zOLW8vfRDpO04En8r*J>8a?D)jP_5E6%pjq2-2wC)BPD5-l2#rewsqnlmlF)}@K-tSm!a#5$pu7dhs%?~aNKY5i zpTWop^@$QNnM8iBQctaU5=IU5Pyt6fO#G zf?ITVp^bda`CIN^EAo-5KqSndL0?Q6IV>O*P!a)&a7DRoyo`%fOo>!1%Gk?eU8Hhw z_bcs>Ck($SRL>7+31wk8C$JMv<|7Cu=TN4oAoAjJ5FF-K941_GK>u#)05X> zO<)FN1;tZ;BuKE}{(zNyBn?*IKH>Y=N{*OzPIl6@08KNva#R@`{A+Us03o$FV1Jsk zd?d)I9`U}#AN|V#s7o_DEgpMjf1lV-*jSBDo#lLF{HsHrYQUEy)=i-{mHpm+MRicO z#PU$4ctlN1oPfun3t3SfbHalU{}G~2-*9pMZmNVHd|>2NdPAU>Qr~0(U5n{gNW>6g zI?!l)U9x^M4_x(9?VCNvvXz=b^gD}qc$|V>4UJ!eks+dN1vuxG18il2{-nqJ{!&ui zl7her6l@0P>-ZRDnOu4wHegFF500}xz3T%)9z13x8E}IB!kT-2L!KhCA3%7{8Q*a` zOaXsZhg1x=B1f1p_evrpWIJ_?*Jg}cHe(#(2~S!pt@)>WSV;W!DzAcOb@DT@rUA4pEhhj83a8pbbCn z``(55*lJq=DQQ~$N_7|+jgM5~ZZOdn@6p3uV_=U+3v_VspDMEc#=IMhc7wt_8$@+P zaiu-u_BeZ;6Mg07jmO_B_a|ZWZRnnYnjQi|M8*P_lvtyvzMc|Njlp~T%2y$$dJ2cDV`7u=YC9+_pAuF_axAO`CGpnZgw~tf-o(mfq%%vw*)`f& zYRfufWQ|YxNhLaDFqT+jT-v99iqYaK#|(3f!Mtcu5YQEpUsen2jnTwav|>n`6}q9& zCtc0rr=78mf#7zpbK+HLF)@=9%aKAsu1}W!+zjpD35R5-m69w3chFBa*13?5@`T^q zS+i`oSgLT{oQGc?-i?)#SEUfXiHD_`0)PX0Be@6wqsLPw)@BFdW-Q@zuoF?-t;{BO z_dDLm+WwSx<>Zt#-Aa+l|Haoi00|N_3wmsuJGSi|+qP}nwry+2wyho8w(XlA_uhXm z?k=*Uqq?FqTNzbd-C19nx-1#81unq2au36nN|# zjL0)UXzWwoO{V1e|_`c)Tn`0r|Z^s z>d`T~`H2M!$q{(l>kIqMHLqW!QJ~wXW*lkw&^>YikUm3)97U_*=9@+oTfiI8?qDbP z@pM(x)GLxO{wx|vfSi=C)Zvc*JJx~CIn&GC2l4jUih2zAlA+PUWZB((!V2C`_~B8 z*8LqoJ?Z|>uDy5gdm@{c>j1xVmpqfN@`x~|u&#@Dz(w+VaT?-R$AD6&tis}r;g}e@ z>3{B?uzvc@aN5U{D3?+>6GLL9sFkjHssWV-XRrFg7L+NxGBJ@p`j+x0Q(f|sW@U>i zk}V(Z?eUBkF_48D2apL?39KF%%~}Zz?RDKA$dSA8j&=+@X0oL}!i6OmkGZRL zS%3AEGa%Qsa^0D%a#4L#H<1IhEvN^Rvl`=z^=R80!R*s~Rp&6}G4MK*fidRa`No@AN$gWRErR@63H@y}p@)|>T+je?}dPon@B zp2PbcH{#?ZnvB914+5ru$!kce;2#$gmODZWu^G!cXpVi%+-p`J6;6x07V=TB)-88! zny|7iq$RlFLM?HtBH7BIARQhkAb+n5Shl|lCnl{`;?f=wrdwf-)Uw7T>%#ncxtfa7 zxq1z})nuzGN2LQ_pVY-@;Ze83xB*fK;?tIW0eher|I))m1X@~cyq%_Z(*Bm*2*KWbkFY66uspRPYEr}(h6 zsx61TI~z4Yu3W5-rtmN}%QeqEVB%c88<^Ea7e>~Dkmw%V)y z5Ior)hC}D>M{XD~bE;xD?2gBmFvb9vJRXiIm+p)uXRSj2-dFA}@cX|Xm-F#xG@80m zN>c*#=S69fz<#(v-Zq;8j>|l`G@fq)_o@uDsn}hwmGEKZ1ZQtpT&yXCSf-0Eaa98? z-(E$Pe*?i0NCC>!bPw8ceGK$4vL1skZ~0V&GfsNtqwrk;0wJcbP0sIWvDm1n=JnVy^K^Vh>vF7!fMlXkB=4 z=cq6f1$W7@P0LyiBPWN|v2NpC>4AlKDbV$;lV8MxN7Nbb_NBGz-d{dOU9a!iFW zQ}y8#$s2Q^y_m>nV>+D6z5FFOkC278OLXLn|DiyE#Msu73EG+bY>_uf43ytgFR3oJ zE-%jvRD96^7_xPESUQe@gz|~lx9eFtSS}QXI1178!mEg z!)|fX4Gj~+%QE{kwF#8{(H9Gg6Z!DK7zar7Jc#RE_7P=v(WQXQ*`z2QL^z5np35k&`|Qsv9J(9%e}bR>LXR{3c>= z>EqjE(_E27N_&1SFuMsDoGf%K@xamtJ2m9`+pxu!Z&NXE8Nvb39p_5$M|( zUH86CnvF8{u_DOalEP|);+)@HK%reN24V{3eYNDaCl_&(BOugREnIe6O3n(ww`KI? zC)oVwH9_5;AcyPkrQ|GkncRV$Wofhnh$kr<$K##6#5RVuaa8&rcA#lXxk7a|(k0Pf zpMUOLRaZjW4KVh#jk^Zx!7eZw<*-mxqXqFjC5sIE`4c5Hp2oux{S}tqBkj@=@3h#Ll zR|}f%n!$BlFqNhQJ!?|$0BgOPU}g5YcL$Y|;S;6%Z7;Z&3|XsSJQHu^ll6l$Hw)uc z4L^x=pRT7Y0O|yVHPd}ph^&oz*ks(L?gMx24Mup$PTp`o z(}V+X(!Zmujqvw1IwGhY{OXx7;|{K}4c)w)EDeg*8~ieBOI|?~a2zJ|0ukom=pJJs z_VaA&WdJ_D%{NWL9Scol(uadNRd&cM6q&w?hUTynCP8PBo9>pc9g!PkmzrRy8h=(# z89(d-6WSRR)qLYEbmXH9G=X$%PtcqMmqGoju94chiV&A*;-$=+BDuQUr2N6Tefd}C zprkLBZy`xmP&1m9S={ij<#%tv6MdbA10P5V8em{W7R|EB-`=J=XMRPm%5OUSIY*w> zEv_X%edq~`@NnJex~R>A!%?PZJ6jTC0q1kpwdSMGv{zn@LPr@-;(t?Wtefj5ue0nl z4I?C1G-@a`q7w~(!YAfU;k+^}u-W8hhfMc|{w7s~hEGf~J>`-5safJDY~;%KyPTbuQ16dYJ-v=@Ch zQO>L0HDyorv1ow~d1rI>G5|ZwTqx+^Ptn*`yeFqGm^*<6o!Gn8rh;i@2kH2g)}in@ zNrw5qrZF+Se?2TtcHPM;u94{}T?E{dfk~94BrTS+)`pjMChuJuideMJ?k|axjq|-| z<`)i>#M<@vRV|Jt5R+T}+v^+QNPrHNT`!v}R&;TYta5Bh;-ymyaL@1XY(`d1SMfJPql0tP0%$CjW>R(Cj;@4izdb+ zkJ^vA-@l<9!YjO}%lPFGD2VIloxU~D)^zkHtqXre`8#`SXunsLetQpa$xcc~$ zGF?Z7!}odEby|AK&$&U0E>d;*!I~v<7akdla1Sdr3Q4c{ts3fS?Q#88+1J&S#H_Ak zu;J@WCo@(5wy`WxVv9{Y84mgg5d!h&qdMKUkO*hr&_VOCoWx{UTmj7sBn)?k%L9PX z(o3|^z=g4Y|CTAX22{mvjz4+&FAx29!OtJae%Cbsk^om^TV=W+FLHlJpQfDIe>fbg%!wiAi)F zW_MGepLHWnWz3r&;~kM5e7opk;$#Q^LLmHRz5}=LzX_CY`V9hNc^Yk|R%r~$72#lt zQf%@#Ct1aBFWKI)sE^Dw6@*C zYnM<6ta2QJ#A0T7+Idj!s`0Vc7S@LN+5a$Q^^p1khIhK1IQ<4|yPH6e$Y5R{fIgAw z=V%ClBt1EXr?S4(dI5E)F9nY4qAkX?Y*P>eNUZ_pU%MGB`V%TwYPr9il=)vqnebG- zy!k{#&C?71qmfSZ@W8CeoJyBd_>an%bgCIBgB$d2pHC}yROzoHAG$J33AkuhxX;~;D2jRA0g}xQW9R=;z z$`B(3yeActeGeY{KJN`)V5i8ZLS|2gs6_d{@#*p>5t)5jlLuS1(6>!#p(rq4R^zlB(#JffLuxl z&v3tCFFn5Q#V1y2RxaE)MGexBhe{R6)9VPo*dI}}9nQAt|BN)K-_#9f`7qg_--&Hf zgh~kL)|4Tq9g5h5MV0IbG%+9VI09#CT3vLgXrcXKhbMAb8+m^}l|*nQP!|{)Kdi}| zN#sEids;XX_JMY6pax1oCe8IAj5 zP^x1fM=@Ho=wpuJ9UQ5=ruF$4*^@2VZWCy*3t658(s$~;Kf^}J(f2L6IZ z(+Z?>1#H%q8iJ(|?#Ny{XhHFH+h|W72bCGmQ`y%y>-5{kw1~hWaJm5m-27Lp>EdE7 zQqJU1^4l9<+hi8m<^F2}ax02brqQVafgari+o_RDT`bAdu8m@?`R#ABWWPS*0ud4t zb9RNxX31;T%amK|(r&cqFdcINFrVF+^R^x5lCCkLB848;tx|!atKk^Y*TwtUCF9&pz3sZd|BtzV1*_pow3Sv0CKJ;g&A#VjXrTTYZKTh^QHWnS0mmaw@c0)=lQQEY&MKSzgW8Vl*wZx+6XC;SZQi zINUf1_-3$&5$eEPw9+O*5KzH^b*Z{LbuJ_aj4FriPjrMh+=^*aND|r2Q&DxP4Ly2I zHcz(gcAw@dW(7Lqu@4ZqJ@y8m7z@Jy43OHW33e$2t!Ii5e^gJbOBv)R=G2)CQ0^@n3A!J3AtbB-8;|PG)4< z)J#-spqn1|utaul6t0nk?fv>}GcY$nuNSMT99~x> zIdgiCifnh@=_?vX;5*|~Jsw0MhHu$4j{Oif3}Ct-l5y=nTpeBnGgDRD@zK|lUoUb3 z1sgIOS?>D=Ks7$iX~$5H(a;Q5KoY_xSBWD@A6C(WqINy$~ub50z0rrga^I=7_sa`ig?h7K-J$25r>U(j4HtS09A zCDG}IW-r|DE^;pG*QrL~G2^f^ssFn5gd}S&ssn>d`1I1hRufbelSlvlP{8;iI7|6U z&pps)0uq4Z^P?0#$0kst{Wp7Vor)rCh31|<3e%!Ljd#1*A*0&C)oGS~22`Sseos9_ z5wmG@c-Z8I_>Hul>yw%2H<57&3G%CEk2w#T;(S&M!u1mV6sM?val%eMB{(Lx@>)Vc z7up3|j7CfOh+yP_6I-iW3a&1=3kw7If@aTD0>4?!;MS7%qfjf25PG`-{pq4_<+E|eVOIkm8cqOytO9o?!PpNFO^6E*3R%^%%FQDs<& zr#vxkx;zt{U2Md?UYt$FV6V)JV8iQ6yrdrC9jU4nth0|>Z$z+(J z>!^20w1yg<1?R7lnEgzy;PQIKlPsH{jK-dg)(-6qOXFd4!x!a;Jd(hwnGVW0>QO?? zYB!I&%n#Is}2u6!pC=$+=L-cn&1zJnG&&mq=&zliE#n&ZNcFgmVL zc*aZEoFbcc`438EMJI+)86Xs$evlXvNtq52KoSk$J~G{qV6*g-mIkKEI}uDWSeZ4Z z8YEU+X_>M>V>)m6-&bf%H={BD3A$Zg&MF~v)gVP!8%j^dndgE$M?M23 z$fg$?4Ua0`ey!qzAQ*+VwIKT0Mj1r(Xy>ww#D9fffvbBw93%nr{e3XQKQ+p+fnr0| z;T8~mR1x)wzld;roO7jb#PFb1(uel{j$O`rHx_ZmI%AB2#C>!Cuog8>BUMN+O{(w- zZ|SJb`t%%R*6h<29koe6Kk5WeH0$s0qbAtpNj8nrte`(0^=p#_uy_g zW(O-NFZ53(0Dwk_6DqypUqK)qzhtUzM?k1B%6N)O)lN~N?orr51TpT4>Csin^>bD^ zGogdO;_x&;4F0XDHi#b=+K9liRbg>{s%Cxdx?!ii7Diw#(7|n}qp`VBJA0PR&ly$t zW=Nr)@g@dEj9u#YFICFADQ#2+WRv_x18GH~iG#rhc|eeXss$CVhg{z>K%b~bof&HU*=!^%u+QnYd z#^-c{dEemCU@V746!`|Nn+mh6cX3nTFctSFy+bBtbMBoJLbn)gcv(DxkDs{uT5vq; z!4wxohjHr}s zurt1TB0(LS)sda*hryjL9b;z?n{T%I)=6Gc zX>-RkB?K{i7y)U|@;1yXUk>qkzx9oaaqurC(8>Bq+Z`Z=hHC4}21Begk5z5s?QNpo zmpkzIv!d}dHsCAn_t*xC_vfcwyjKEbDt^9yDgtjD^D6)R!8br{n0-2YL;j<)&jl0; zwhPty0bYTbazAn4()Kt)M6HifdSeq)I_;(}^LxcJEch~K*E*r%Jo*uLY)ibioCjz$ zOXR^5TjuXoNp)jb2YCuVTH+#oL4}}=!1>_^;*Y0>>Who17`pZ6F%dQs z8gb#_6SAx&>#s=i0RXZWNn0fPsjk~TMMm&^B!7MpmHN0S_yGXoLB8I7FwMe(e2Lo^ zx6vri^?w=b_W}R_R#=`nM-*$q^*UaezhHwIeZB}ycBU2>58M*3gVSur9WApODcttJ z9T|gVOBvFg_CWB;l~Byw1aiq&^3!*b*4sv0Tw#Sty}!%XjxU~YiGksS4<^c+P2c+B z(%Lh$2^$#(oE9pu2JSS+r!aN4=_upuQ@VgSLaqs2_hco4TgieeD%rdY8#Eq`J^D(r z5HHkMXV`(ZUm4LD0pJ{8eE~N{=D|oXcluy$lRN4asVoPQAT#@KYQw~wgJTN4rQ}pX z*;98AD`pI)8}`fHBoe(Gq_JAXcK@zvw*;s!?LMn_rn)cQ0wzPKTRe8uB%YO)@;Jx} zah^(l*ME&s#0dFio!NW{tYs2x-e(jOepG8B)+oi172vTnv{Z_%lR!qAueEG zB!CPRwa%GS1mL4F!Va2#4Qrhql1);DdPD_4@?;h%TAk1hq+Tx5fkXfN5Uf%wT$lV|$t=q$)7{xD8vYfwxmlCj)M+X6RGAcUzOp@1 zc?Rnof`{cf3UZxbJl9XtCDN8DX&SnoSl+iYGlF@)oNsuF<`bMkM1u{sm>6}ak&P7k zD0!MYLXwL}ft_m$o5H8eQ9vi@Z|e3$|90eHik-$bB%dMz)fGwG$Nl1#zKH?~_R(ac z*1LN$RV@j^?E)HGGp@_4J1Iu5;nNtxNeVOHcY&97TiV z@fOWR`I|8c*tC-Er8VT|H-e5}={FqJmq1Rcv<|=Pi<2?5E zL;c@XE3h3MSWGpSQI}W``kpUAm2%jI&Vt4P{7|=9_LCN3L=_lDD;Aq?N=20UQo~Ov zNnxXi{jg^p5gB7k%`*sR%nt>IBJ?5}{JfKa(MD7_J@M|e11$~R=r(kcV*}0mHw!p_ z{R4g#g~VVX$PcWtb$!8#@^J)-ZnkrNtrjN`anO(5pbd|Xu?YL|Fa0KP z@x$Ak)`R*Rj8k0{s*~4{)uoJ93l!2P4b~_T9@zc}@Fhty%RvYRH&ga&;`on6iL=Vyy#Sn&nWSxMk1AH`J`>qr`6^qwzHG%GBmz zjxp1-$Z?Gtq{!nqA0z#5J$m)!Vh3aX#iwBeWcJP}65t`h-CTwzfqAFiI~3I0ysiYLRKT}7ROEQyth#VTgpg;KdF!l zY1g+pvp}cj>750N6T9X)Ya)Lu`eEspwDZ zB(W6N929nBS=sj06A}@s6DnNrllt-mw2lhzDhpsJGIGT(Tu;H&M{Y2b)7b}JYDZ&# z$LnSYk|1B{MdvufZ6{mY2|@X`YDG*H)tc;>fDnWnhN#aeLG0s zeFIDwChT=T8vr=Py$KtolY74EAf+EQSLtmL`W6iTPO*|OlOICZ40X~REPeORo)#}O z-veC^pl)Fr=d|ZQad|^XV+=kL zh8{pVEB`rCVhsC7?z(cB<Nh<99-3UDmmq!PcBA}Kof&i^ZObtn&Lhi z1!QtyaB2_;Y8mk7qksPUoGmL%Tyq-YANgigYwwX zi4S6@@SeaQb=hS{*9_Tdj2InF(T@7p+>gXBU0Pfh+a~C6%NQV^1`m-u{(_8#_Hb5a z#L|?u%$}#>_!qbP%<8}_5Nsp~-xmyq@>lO_B0hO_~@5IQBAY=ur z7J!&Ae*V|ODU1xqPg)l3dx&f`?}ThI+}u3c;692Q?E!5kJxZmPT$vi^U{UswmJ@+cxy|lnLAXd;ra13t*`~+d;c_AO1LgsMO zTOd8Xj4P!}FMUX<)2(Le#8p2sDK$C3jf29<)#)$FIL=({X60E&A6i@+TFi2cLQFK_ zFE9_=?2)9@r}ni%5)*sjJb5TR6tIo(rTlzma88|FXq)U1*vWH_vSc*p>i|kbPNSeq z+sWH9(usDyYWYuS={TTOBowY5)MM8sI&C~3oxonHO)h1_C>m|nHNy#p`V@5i`ClXA z&O7(jl)cE1bvQ{pu7L-Ise9biqV}uxK-EjpxUJ{d^fzLD;XW=bIs4BHV~fw5-fXw& zwR_lqPZhVy4{4=vYO1eowV4zC&bAsW4dEoc?D$&g`JeuZJ7VHTqZOp^Mh^nX)Yf5z zbzG@9M#uoEOrB|~=s5e-3e`zPaQun)^a#U}P&Zc@IJo*H4x*>PwNbZe@+lwa-h;D< zrTZLE^$DhfhWBnMt2nGyc4(O5UxrZy^hi`r2y#RZtBmIGB-~W)oy}9~$zzTs@r0HW ztWrmn6ezC`CZN?_r#<)wLUpuX@RgB8@R@_63>Jnt^iu4Y@%PKE< z__eauwGp`4o+DZU3<2Drj!TXX7>Gs{yT+hOy>orFWQ5h5`|A-{^qj+rR(omtO&dLQ z_W8_lV$WPVb^yR~j6ZjO_}a=Y9GBRGN(>MDJ=J=6rRsz&+smF78=euQiT^}G6)uuc zu(ul>YjxG+95H&dtpdu~8Vd4tG#|j8((Qbt=O`?t9#4PZ4exUf-2INJDyHR^M7C2- zjf1Lk;0Eu4Shg_ikq_KkWg0Bd(vuih@_mXogMVJq6i)2+%%vixAob!6DTx>Gg|dHq z1*o*cM6;t;-@$lAT(#uyfoR2(V3@*ifCDE83B_zki5ZG)vN8CC66;Z65ZLaag&+py zoSkI)t3Xpj>NbaI8L18^sCXJZr{E+2`jUpz)R1mFa`eVlA3Zid6Uo1U-gzb!KC!DRpqvu$6RD%sVE*IHgigNn_&!C zepvCX__v@PtM)#{_Q-1?LDYvfkG*5g7f6C}v>?a2Q8KowK;zQAN>U>}W0hxNIJyIz z;-P69Rzi_`e_9O~I1N%?HFLj#3@En$It4%1{wX*BPx*#MeF0sdm7ZQbH~)n!#rNCT zGrtHvE!CE*Yck>o4Y0xRO_OcK&yXSE?0l-MD@^|fBi|Ql9Htsg@XPt~4vaO=00_J-_Yi!7fT^Zff#-Ilc}US>%DAN7XEs4aV4b@*IOxy~ zyXE;prJ=yCwnMcpKW-q3+SG*Ns{_$iR$17auQ|*-Ovo zn?h`T`lIinDRL$}X6(n=zB5y0M1JhgRC>?ca{++9U_0Rf2Y*()qJn0<-IG3rU;SZY zP-M*#k^`$nIYVYrKytg0cHe3x@UP_3&V)d;G7e#(d80Lyr`CXT3&To;T0iIt+a4j6BUKfYX zzxAFAqr3{}3|-QtW;yWion@b&RuX%F?Jtp$T___O+7>=iULfkBw|-nl3gY!;%T&WL z6<#RJufS9-YiVW=s9N90q1vG70KUFYmE1=Vhw>;x4zCQXd`|Z--K-gfh;{B#2@rB*_3e)3F~WPIQ@Db2Yf)2OxeZ`C0h% zb-dlwX*li4Kz#TCm^Lx%izJ7axHB%5;Vm-sux%m3)TP_YuuI&LGFffXH*_ykx(f^! zhtC4tN#UUQqU8`)2AE*PEs^9nq*d_LI_@vgC0}i!PD+kx*%bgnf`PdB z#z@TCcMCTRQ!d9%CDW}>8+e8~oq`&|iDk~z_)=fW)w?4C;)0b5R~KW(!P;@R6aN!o&0AhPtd2W>LqYF8f3pbx*B^p`mL06yA1gTi2XhrXy)H?9Y8ka zg%Mn$v4rc6)xjUG3b`JULDBtItHNb6yexeJYu(`J1OgsPV*$kV<(|#X=f%s~NysKd zX$LKZfm`@dHACamc8$Hy%njt5&xHjiS)|&U11!}U{MX#(33>Nem9GMptl3(arr0cN zf1sj^Z*foeXM0bl_hXl6!BxBxVti7Kb*9xTlg=n}xyNG1(!pGE$6~^?*&kr`5(;Lr zlChdnfzckVc=rvx3md^K?B4OMW++;`u~?|b@&=s@ zMy*Nj({*YoDR9@(v`k(Zz_-GEl$xfWTtdV(P;fb_N-;VQNCFfxQuHXx$MHgny?Kd- z6YhKz9y1Rz_iox=;^aLgstqUg{(?0D#FtiYl$PBa54F35aiybVAR{K3^?9>USuSm= zFVNqUxfqrcVt23b)~q2oU`uDrk}jU;PgZaxNkV1P91Sh~PA-TYotD^Sh0B6jE?XY%3G)G;L~YH*%en1_Y3CsCoUSJw?Yy;~7$qJ; zkzB=g%FaEQZqPCH3FD2`Rx{zIamfRCB639Ea61!@NlmtBwZV!EM#(!rR36C!=;UCB zU2{$$v!p>6h}D*di!2}?&RKO3SmOm8MBqf!8Rx?C`%hC=tw(#Dld9V&L##FYYtTvX z%@D^E#-2IORt?ePX~r{OXWq5>UoRZ~;T3PUHZ#lsqo&dBAydf30f#n`o+Pkdjn1W} z7=+%2WpqgO9DdA4n)2o-MNhdIzW_`Fot5aZjyf;)+mM}82MacjuE&iA)^=y?KH=d&)2>25(8*TM1k*to$_iU-b?Nb(lfb}*dr9ej*V&<=3D~es^=mo zJKM@6bVuv~x-~$Jx77wnsR^0ZuMkv)V2+JmL0s1f%43ZO(ZRjkpJxQ51xNzR>doe^ z%^x`c(?vevjXa(I}6`+{pVOGL|y+3z`lh&k{vk|>CTk9}YK;xK~CUlh)UJPx?09BWje^Qme z15BRa7ApkE-`>o#R6IU#huAI(@|fh}wW~kZM=!x{oNcYfqxK%13ug&E3?7#UxyRZ|OoJ@AO@=CgVGan!RdTkDvQ#zX=z0pdE<%@+Wr|JG&s>(paXF z4RjmO)#vlbtAjePovhwAC_d}*mR%`)$*8dwfAvlS;IFDE3t`>6gLRs$?S6ujI3k!ALcL>Q&(cPo zS&N?+0D_kv4J_3eo9T8bJ`(5buw~etfGJJ{!lhxurp3d@ zv9x}0=H#~oo4$YS(VS4gb8$5Z!O$uQ7gG=)egV>cU~+Ui&7vAY^(J@Ff28kPE;4@l zGPMWU76T2o?|qwH2Ekd4>asg*Lg== zN%HBn#ZFL&n+Fr*je+d&AJ1Nu{c0TpUV@lTkE4t8008D)rSXE^uwE?9>j z4>ZvR)yBdBBB!D|ati{awYhE&3s1Q>`}Kga(^}~3g3BKUb>>QKD})Fv9DmXBSKs#0 zZl$w^-4%{g5CEFLuRW+4Mr1i=C}mf?>FdA(&o6%H9GoIUEc?e3cD@}p&W79V$1j?g zp=n_T)PB*m;hh-!J|DQ- zb98&rA3ro9eoxs-kDaR)?kI&>NPml3LoT7QqL`TenMnUSwFO)|Aq0lBueyuvY_u(i zN0TBrFzvt}#IY?IL&foCvkEQ;&X&;is>0E?qj$dFguya;jGpqCsRa z{Zy)=^;z?#Fil|mNkiL+EYA|QhLw$HojqJS=doz)eT>~lNqCaP3U_>oHI+ER9HRz7 zyka_$qNbTy+of~zwu&$v$&@QPltloaC(O=J6K9~bOFI|3MAzxRJ`6V8jh9! ze+3XR@6HU>on-CMDUhO0x{2kPv*WqVMVDD;ujRT|pEN--WaPv8s_@pt6^vBn_>$zD znO1Zfw7l4^Tu*dUqYui%WKfv-f$@OED`ranE3&g5w1c9>A0N@=W01wVtDH_5+l(h6 z8&Ic|47F{ky{VLeRy<;)=l^!Q!sl2JMax)rZ>LA#M}Iw}e}Z*# z2&eW#nk2yhlgAP+7vITs)YnWa+bK8Zhw4zgk9v$POYmf{>cqZi+=hoe>tL;SE8L7O z%j>Ril=X7aCvJm7L{)LW5S|-7Ml@XDRo{%YuxSi(tSwnF@dw>-x!J|sV%|#20ewD*X7sSLzeYJJMVp+=J1hv*wiY-OOg$ z8n%rbo<+toiW&YOoT~AZ#WC$x@CV(noP1}NP2b526;tQrgmWIKlDM9lyt_IA&GWeO zATzV4o}*rtu9M}Oxzkz$3H%sw^6pZPJWmTBy4VtrRMN*OQJgM1=PtzC+@I~C?Fws% z_sa;SOQCSglrepSH^c70q+vrVoj~eWmAel&vRQd%`t;W}^J3z*3_??&y=;O^qsThXelwQWIx86*%*5X86u?&d!AAY_Hn zD57l@)ySyPyj8|yGt3%w@Pad4ebx}_Y7I0@*E^u z?G94IA8YAPV|qLvb7{o|mXBHB%%kAHV^l`lL$5QFdMGYE3Y^+ zS)?&}vow`m#;g?dKP5WywJmZ-3hUG$Ex<5&hBb_@!5TDZ5ux9G>Iq7?@s<=L{(=jw z7F~~xkuCAIr-h65UW=C7*m@S}cdcQ&_xh7o9y3Y*cG}BZ>_tLO6|2j=814%b&R~#z zjg!&f*3IKnhGI(>+98l1?AT7?<%JWTEylmeB?>jT-&Vb|OSEgDypzU4l)^cV#w z1SInCGuRbk@L~qju60>-=-8FTIfCk(_6wk#mnF0{iaIR4-q6Aq4U3-I?J)MPD`2H zdHAFK-x7%?cob5-SIRj{ZPR#ZGdU198j!@OCXKJjN8wGWlY~^G^T$;OFwqkW4cjJ= zAQt4=k!#EHtt zh~trJ-cEU@o5zU}jgk58{7FSqPnRpEMZGtE82i1p?_(j}ZWDZaD?v;6X|gxcHmSS( zh|cVf@COsJ(T_~(G=Mu-CB^y3Fo=r8nQ-qyk z9yNnG{@(ecAGgTo6stloxy?C@XNbUqd*|N9XG1+KFOB+`5n`clgKQWZO0&MW?nvh* zpGk=GGA#l1knF4>?h|@x-37%hrR; z>rxf@P`yyHoKyQYDovu`Y5U-&Zj<&e+bm26eihf0fc&Ch3_nqDP}ERMi7s>sUasN4 z8Bp5xx$wh&0qy@MjVI@R7R-w}oNTU^xR}uV;+UDDi~`GQoAE=qtEpP^oaIMg_h4*r zlHz#I2%T1bYInF2WEi~#c*hsmGq;Wp2oZ+hdVJNNkM~nM07lkNx{CN;v!A>P`XC{d z!OaG}=tzMkqB2O_{cc=tS(Id%2AxCyRz4L*n_W66ge;g)kClGU|FH zGMOeuIgETvquGi)*Q4#PmO$JEn|Q2T9o`G^j;l0!Uy@D(hXl!?uP%{x`W$o3O>3zmo%o*L<5gv;CG4H4YGp-y`w?+* zu9hvPrt*<58Q%2kQe;e42b;{eoe^dDfUHqdKGU;o&fyr40#SR;L$AfWRqE7AIbuZW zlifayEDz|YbhL3l*j}j;W>I|B?kJvs-6mu_*!Qm4u)|5#C!V0cW1U>4DV?=m4-4S17qH3|4^5T}LwM)J z@1|f>`&uC!cb`d1bUB8kRk>2k>HZrN{{>*a)l2Q|68m-KziTJ$*p2&j%>A^V?WGzo z)vEjTP|N3}ey*^8R-?J|)jw{n|68Qz?W{j-Qqcb0S^qYJUs6x)>jU=cyS}9_+p2%< z(jYLS#a)27)H5I*aP@Swgs`q%C2ZgI1w4ZS?#1a{etH zJLlbO#tsC<`SBksR7sITn!<>3{0{+cPjWDEfoalPFNqRZvR$9iz&p?$I|lJ&PgNAW z*n7ts3$oqJ;Bfuu?~bsM9fdgk=@I6%T%t0Ng=Bz?q0yGgI3L%V_yaS2SoPbthY1O*4whbV*=nCLghK@u?HsK%q`5GHk@Xs9q6XE=i4T(Y-m4B5 zEA37O%2y!=r(qw?FaYk|gtoPB;k00=cL+!1yc143oOm*LYSIB?<@`n=Aq!tbV zL#`nICB$#@M^&4q*fyahU%<9jo#SNm9IPqRHQ#L{XK1UkVTo+8kw6`qFN|{nLnJLl zo;64STyav=_q_irp^P~cm>%y^e>!svN8UFBvQx4WQH_go|sM^okDI&!tup2-bmtWd2O`|B`^&Sxn zxlue2nrKa1Yj1kA$BFRIeOHNLE0&I4@FnC8?rf>f{!k08qw-0Wfs?-j51TH=8Ghed z;Tl!5$M*7)Y;G!y&CFtG1FhcX*SICI!((h=;%#>4bLF|E9NX4G&HD)J z_%t>mUlL2FaF>vOEzBvYCkY$i*mAkf$SczCehL<}CwaD)4&zX}%A)hf5fC8S8<2_& z=e0gMkQLv3n>vU+W7jjBUIRA?Qv{Pda4!reL!RrWrep6 z+;Z-$2TW_cF3!Aj5ky0k1Xm@3U{~sJUiZ(THgwmO6ABP96YR2o#M|W?e*~lUcHqEJ z;+V4#d2eReciF}h1sT18SFE1E0-OYg;99Vq;&RhpG|i(S72d{^t5a9B{e~%cJ`3Lf zT4FcK0N)BEk3b{1flwc9B28oP!YGVO%uha7Nw5HN%lqBOe(|)Liw|d)O!ARl!?W;O} z%cTm}6NUM+f34?4oW*A^I~}^LXcFt;a5oAHPj`J!cu#Rrfl)?e`1Lo_Hiu&$-*FvW z)!sUT`P0k;Prt;v+1+d^r#5}plOBS|R z+wv-LiQN27cIZR>b#ryb&&Fg{kj)l8FpY`>TA169nBVCum~=vb96I>njKC4Dl=Q6{ z14a)}f5LUbp&$Kl&2;CiqZg)>hTs2QX^?L45d?g6j^%-C)^PTOj3?7RXDTM)Zz4lt2Y7Z%BKss9H+zx9mND3xW0$QrydM0%6&q5DRVgk; z`_W<|5*4GPdhv6^boGTOXY82F&;ZfcGwTR#k*3n4aVs{dL#?D>S*OgGIk@`6t+)H~ zvrAH7ep(KbXnMKvz|G#use50J@j1%b5I0~UxlQ~beQ7PfzAJ~=6#30TyXiPi5`s5`~RbI}wK=X$i|`v~Xa2sP4SjSf6)H3jNR2rv3MaA`U55 zYxk4;40#bsD{L(nk0IqOi586&MYTo5bYK5Pq>b1| zT&F^?W^#pyoCN9WmK+DqX;kU|cN3dAHT^uQ{V4XaBKKf!j?G~sX{Yo1AOJVTO@lPN z*Z>HmMMHm(mLv|h&jo|>Y@!?tCBdUAGOEM$u-Yl2RmRi3v%sm@i(>azWPq+Da7O0( z+D#F*DUtS;O?vHX0BR8nygyaC0_5p*o|=X^WvZVkDen^%X=6>U_1Y92lTIupjrfkL zv8x20I;FiJ|8D~wC3z_t8%mR)n%$*CwNFl__!V7v0}?|=@T6U~7D{kk9ka&+5!k8YhKzJ3jj>93gEG3A|P zPQDUVV5qCj~ra@>cmF$CHzU~Wps zcG46>ali-zI~Mf&{e>Y~5=Za8%~l_WjSJ3=(AhdLIdXCA>sWQ!>l#yTPVuRiTo-o5 zb}&C~X@IcqCQ$gB-hmzKph6b&EbPQ%y44$~2v+LqDAa^`TdmASD7_iioru3VMh1c6 z5%@9lG5NbrJ(Ji6k|6Vg4(s6QJ9&CBFUcKJg^~w!?h9s%V5Va7hjaZE#=TGsowz=5 zi-L1QOzEkdVQF~#RA{6t(E1$0E?_({~6)=I4&Y| za5C*@IQJ)KZsEa5n#}DkXEllQ&|^-%;SE9g&-FX#CU=CCD=dSSwSn|ho05NKn6pQe z>-`l>4#ny>EZ}|ya!Wl={AczzWn>!CR;J)r))(Bf>G*ZMC-nD%E82$lY$q{!ex!gr ztE#0PC!+&|hgReIDapAbPI`c`gD>M7MHXlJ$d4%&tDPOO(!QTjVP5wvxC*Wbc5O4@Khg< zOqXj%4Fnpk)V9kW1`9@Gp0nTdrV+>7j`ZX43B55E+O^P2fSe04m5)hZnxELJ;*gW_ z^#hso)R?IlF;1(`eU}#JY%-m`4OVvFEC=nu=W-tK)%465l!)d(n#KU>Q4y-G?rzQo zK24-k5bua?bG1-nX~tz+un_XIKrHS&gg&_`*U>ZjD9O;d7U%n>s$`3wpkaxJqm^vC z&8P}AhmI<&i^m-DzUM)j;YbApdm77uk`nY)vUh@N?GUUgt@8SA#+jy|v26tINDbBx zNdIj-fpFexm>c&N#I)2I8w>cUac20*blD?Xro)wL?noPE_A#%t7Qka}!ICMwztSg{ zky5}o`U8$PNa=M9g#RDGTx-ga59zvo{3iBy-V`KC_9FR)y`FhJedhHJRM3;F0PQm2 z?HUK=ilbSCbn#0uqYyjhKwneq|79C^uR#d#KkZe#u)Q2xh9GuQg9ATT;U~}YZdBJu zQl{5kgD3r$HAIMkS4g`5mmmRS_hc}gz&OG4jz zTayM{oh9xDNN7$4e-1liZ1Bvp!-0~BYl5rLA9*K;gP$6Ojcx%D)4zaSi>MUxitMf5 zo)Pc_>Mc2lU><8l2j#PrVmU?e%4zV8AY8NJ3)6U zoKSogXMjrHUwF|2{vl1)jqzSVV2^+j6Y(u;ZS8~-qgH+a`$r=!(R-${!!9G5eR}e& zpXM$iFfiEU1;)a?ql0N|ITsl~?_=4^vMaz4W0twDb9}SPb(zJCB^WEA7>Gxj8e(8z z=>VRdOyV&gPE3`LW0vSfh)q4i5|}|{^HdJv&!20TDL)#0oF3&o<&uPKxg;g1_uPyv zkO68LpzfT+^MGM*Lv0FA9lKxCOzXu?Y;wo}D+itl<(X?WJVv6D?(pdsGB?UE6b%4t zardyM;8VekiC91m50%C;?)h&R1#Uv%o*>aXe9h&wr8;G{WKvogBuud9W!u0BjCI~y ziy}+MH=hv7RzUkMx4q9_P}!q*2v12bb-vp4`su@mSd9NjKjW%W3l~IytViIj;{14Dqr&bCNXT%i|mIIX=`zOgrQ)1kG5|ZPz#-9i+C~^;nz)DBnwiK*jB5z2ROu&zDbx?Ms zfZd!`ZUTQiCtsJD&MWPK0PqYX_8wKrbpKS)S^fU=jIb!8OBh7?%!C{G@E{CUJ%E!G zUldTR9vo&40FCH$UQbUGpEDGI-H~~~fQbfGqe>dpFS=aM-MaRMI6jV$v5p_Z-_J1< znE?)~=*1QI5Mg^eEu)cG~PS? zrVRA&ukR0qbzy}T(KC|$^GrY13SmWUDTTt!dT~_|#1`%nnRXHDFXo*)6TV*%T1%-S zi07ZycHKGYAo{DvCrWxgiGm?9ae<2?loy3 zNI)n2D8fr}9~Wf|yNn!n{|vh~idbj>zR9`Wdo|MWJlOgkU!sBnA=vHXo3}5f-T)_# z#HVM_{yagzXbNo;+TWg5or0$)iM228H)Ij9&q3aX)x9C1$Z%3+a-{E2oJPU&wGw(K zomCPgYo6dikqqVLjC2oyP4eTejAROncqmBHtvcez|As$d=}%JUs;rlWE0;>7j9&&+ z$t#`a6xpr|VF%d0+DM|6kh^tNSAIKu!EaI>m_Z24{7hpIQODfXKLupI<=j2hML&tm zfZ$Zx&FL23%f!)RRJRy)gn8--=nov1IyKW{6kdY-2QIbQDx&8_krCH;=eJB{*;3jk zra^8|Y`91|8Rw( zG0nu{PJH=6>)H3M+%?G{XIzD!f+BeJFRB&<&bw)wF=cztvojOta2|JSYT%eeDy%SO zqH80FCt_lSOllRehc;`j#AsxSPj;J#rc}s+*OKKC>z=BO3bG0*em&JMyE5AVUD{|0tY;c)5QmVMMgUe4#13Pp|T|F4& z!}cR9_3Uo4l^Rg8?SwX6mKdip}vx;1YzW!0xA zj1ffBBvrs)L(DvvbA>6y@3Fo8f?ki)MZ5?mg70a2@~7_RtR_!T>P6jQ{&u7W7r-c`$@p7XVaNdK%pi-2^tn9fWz+Xl%n?t zJ>d859sXGoL=rI}gNRk?THc{pai3#z3A!9MPUyqZn-Q@=#*C|Wu-%D$6z$C@6a#GL zHzfJP)W9Yt5{=B$#9@)8u*VH;%;Kyo=NAmG$=+=QCAu*c^Exfb4_881+}xFz7kjtR zRqf6rqU4hQFR=3}W?TIG)N(2bOe90v4f zD34dI(qK_~GN(5-E3`g-PQ5wfvsic0R~U)S9Y9MopUWhyqJgYJ&QZ|K3mDGu9&<$^ zl9c%RvBJU1c#Sc{jXS|?Wg25HTW#K zASTGUn*t1{2bgA4N-yUy;c%Rq+Okg=39Gp4*HkT=G{eurF85{Hg+O?LoGdPPJG*|H zPnN7in{<>KKh~_#RdT^}dh6sf7(|0J_8mr)2mWST-rx1#-Q8cv2Dyo>4riBWx~4un zUJt~sE+^*`eS}>cs|Sn$E#^ndd*1EjdF6g^UcgQ1hm`(dRu4Hd-=N>|(4$kKlaHlx zZ&fSJ__j~68ICQRl#(7P1PwVJ8cdI8vb7R*+)ofgG0ut{$?i&%_Hp*iHT1~fk=AKF zao+JOPpa2(Kv$7jalycKdVosVv&~5%ZVA%_`fBOA z0?-(3F9j=X!TQyvh6zz`q+F*{6i1i?Ds~Ghsxbxr9RfR}$N?w+p{NoyKV3^dm)361|svuj5PAyh| zh0tkMaA%2v2n$RGlaiJ?1##|1`H0#zQrorx#Eq@|uOET>#+_?_>fyAEuNQ}bBDJjB z`WPVHzEme2=#cviPU-^^FZ7`u&~$i|=*<5nFueawL#^2r=pK|$VJd!=c#J2`HJSfK zs{uiUSdGaQSQ2z+i%deZ?IIIdHHGYVEL-e27_l%~uu5^!!!)YuofVYyfj23)3n@lK32UYsJ7QCtCwuF&Kd04Zu z$vIapg;pmCIOUizX`@*jwy)5Ih7&xDisZ#*MsXQUy%PO8vZKkc9*Q@a(I5r9yZZcM zmw^XA)l928GKAXQ=*v8HYF{);)RxDLZamGYf`)<^z!6HX={`Dj$p)eayESDV0HP9c z>q-bv8gY9A<8r!tN}*ONMWzscOun+7yModDVFlK2sY&h>kSfzLraw8a4CyS`MTxRx zACU2skU_~j`9FhG1c!Iu(rL4jA{OB1)&tW3O(@TeDra$>#a`ES|5o!UdZJN~jzGxB zk`L{GJ*o#E#TZG^;(|aSJ40AtF0c0d2LeRTMuG%{ICHIan{>1p-=QBgA!G{EK*tI1 zAn_9Qh=>S7%8ABA8{ey}G-}~of@0oG?dV}Bs~nij zrQAQTBM&)i68;E5?Of;ysxQyCX$R_F#zTD$IIZh$r0&5Y4`>%)(O-ZQ_`A!Cm0PtIbW$rP(#bLt9iSwFLd*sRh?%CL)J9bQ>yB<^A1&?3vUoyPDHD4@uim^`XNA zAE`E9kH9CW)UbTV$)KuJe8YBVi$P<;*v+!MAPFF;&!u636sAYHO;Jmd6yf2dBV$yDA=66M6%ByN=paAJfW!0 zHAo)QPM~YEG$TWCT_$7G@JX*FhZXw@!<)>6NMVVChL3R_i5e6tt=^B}s5t2D4$_Z; zu_c1%fPyQizu{-YUTdo4*5OWNBlN@cdwLc>-0bu=`1o@C1gJb92#A4=>wzA~7tq^h z{kK291ExX_H=^H#+l5I#429yzndUNGw)=`0hzu4Of_`dv(E&_(mRv(moYKydZ>F2k zE1=Q31DF{noh0!VU^%0pWVY<-z7VBPOp+F7 z__0UmCmMR9vvSFKmL%b502M&YA6KRG!}##zyoEb~`;Rr&#Xr?;%}L-VgRN233I&q- z+ViZz-yBE%#mcajAEIR$dz^Wl64uTr!weL1UGCg{iV zUll%KSq=JQBwNB&{WUnDN-1~{XRr8N;HgS8fK3im(u=ZBdik1G9(i5w_p@5?dP{Ck zZ|6up)H1L$Ct0n!sP3ViH*#(fAE+>L7UbgdeWc&RPk-S}-)SxOgde~zU*Hjb(sTG7 z^8KeDw^09Zt#7pA9|)vAK(c>ToFRQcl7DF-{iI;{ zVx;e9jr)j$!&o_&OXd;uIgA_+U9aBsQ%CjWn1b0BLS+V4jzjhof^C9-NLrwL!`wpxP~>;&NDcH(mZED;=F zo5q|mX5{YUU?X=h79G!k*d!*wj|*i9jne2|s&x1$(G<1NrZ>SGaEME431zM~bC#^V zM*!zsTvBPFE2<13VX>@Hu>o;Ma^iwzvV3W!S3_>zfVzxd`73r8V~ z2_;e4i-YCN0cZ;$nqxDw-m@|DK#me4h1tT$3=xeG@I~VM7p0SsdNuIqC`PZ#<1}Hf z^0yfle#-W?O^s}W({3@!tq!vPPtLgi0d-winw=Ju*u3uPQQ84)NH#gjO~56qUng%p zC*qx}#_FLecAeNMoknLJ3X>Wy_pZ}eslxu3Tam&}K6Pu~wS-NZHIwmv4-j@9;eR}< zI)SP)*OPZwcdnh=N=V9c}pqTN})>g^l<8{mfpV^%t`lp@=H%u!CRDp*#(X~rpq zrNdV5YXZL+%>MyEF*cACoZ&I+Q9S-RCI#H~LWy-o@qNioLS@W!d`f1aOj^;&sXz6y zzKv$~tJ((@@&7`&)FbU$=KBd3K0VXlmL&;KfV zTlX(&vnmjT$}^%ek?#s}Pt|FiHfw_py4UL$CFX#$XTl9oIGh zsns#~lW1AVu>UFSZuqO&{{W$w=`1k?0O0Ysb^=~63q}0%b09*~Qx!b{ekW4;giVr( zT~hav>Tc?(Xi|P4crq2F<@<35ZZIB*GWh{#k}*(RB9(Cd6e%*>aTUh!+a|au@FvUv4oo{#k)XV)-v=#Qz#q^T}%^YLq17s*s2Ka1IwQ|_$osMn581{sY**OifUD7z@H{P2VtnkosLGCWN-C^R zF4bj%$pCOuAI+H?%o)^ZYW72nB08WfZfN=NJ8?p^i{8CrsU>R_%^IucUouH#kTu}s zv)DURq?!;Cr5Z)$Ymp$jdllxT<1bQJg7N_#M~=q(VkkD} z;eM>VaHOS7{ib;Q0qMTG=pX5tbl(`!&utL{FxkAcqijbN6GbQ<0wd z20$u~hUw$@20$u~hUw$@20$ul%5&#-FpI9#TVBiG4i9pf&xu9h>DQIHkW)p;>Jl|7 zhIDZ6dEUM+YIX(0Nw*C%8ZSgxOV-N#dTt&6#%5%DApfS+d_l1eA*tkg+)n6Ogei7hR2V1-?ebY&$XZ4z5^o?bQRV zkz6@dQ$TdE1KE!F@Cwg{@RSU=6?ivvLE`bLXy@nU_Z@^^$y zM-hCo4p8hX@WyDs zB-qbD0|P4A(jo~EbnNxoi#45^?unlfi`c2^is((%@ZT~r*yG&5=urM&(kBKWVFwB# z_sG{h2YH5duGNM3HxAoaBaXjQ7v3K?l3|T<8MHX*W_2?M%19FkFjfL5!en&>#hPA! z9QYc&rj233xAq;~d+$9(optNmY#=aFb-p4^s*}=)@-gCTEBCN)&T`|Vy4vT=6AY_= lzZmT>gU7h*rQ;zkRdOGaC_FsA|Ji9{ZdL#Q01Ur?002U1X+8h| literal 0 HcmV?d00001 diff --git a/OSX/SaverRunner.m b/OSX/SaverRunner.m new file mode 100644 index 00000000..526f62eb --- /dev/null +++ b/OSX/SaverRunner.m @@ -0,0 +1,1010 @@ +/* xscreensaver, Copyright (c) 2006-2012 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. + */ + +/* This program serves three purposes: + + First, It is a test harness for screen savers. When it launches, it + looks around for .saver bundles (in the current directory, and then in + the standard directories) and puts up a pair of windows that allow you + to select the saver to run. This is less clicking than running them + through System Preferences. This is the "SaverTester.app" program. + + Second, it can be used to transform any screen saver into a standalone + program. Just put one (and only one) .saver bundle into the app + bundle's Contents/PlugIns/ directory, and it will load and run that + saver at start-up (without the saver-selection menu or other chrome). + This is how the "Phosphor.app" and "Apple2.app" programs work. + + Third, it is the scaffolding which turns a set of screen savers into + a single iPhone / iPad program. In that case, all of the savers are + linked in to this executable, since iOS does not allow dynamic loading + of bundles that have executable code in them. Bleh. + */ + +#import +#import "SaverRunner.h" +#import "SaverListController.h" +#import "XScreenSaverGLView.h" +#import "yarandom.h" + +#ifdef USE_IPHONE + +@interface RotateyViewController : UINavigationController +@end + +@implementation RotateyViewController +- (BOOL)shouldAutorotateToInterfaceOrientation: (UIInterfaceOrientation)o +{ + return YES; +} +@end + +#endif // USE_IPHONE + + +@implementation SaverRunner + + +- (ScreenSaverView *) makeSaverView: (NSString *) module + withSize: (NSSize) size +{ + Class new_class = 0; + +# ifndef USE_IPHONE + + // Load the XScreenSaverView subclass and code from a ".saver" bundle. + + NSString *name = [module stringByAppendingPathExtension:@"saver"]; + NSString *path = [saverDir stringByAppendingPathComponent:name]; + + if (! [[NSFileManager defaultManager] fileExistsAtPath:path]) { + NSLog(@"bundle \"%@\" does not exist", path); + return 0; + } + + NSLog(@"Loading %@", path); + + // NSBundle *obundle = saverBundle; + + saverBundle = [NSBundle bundleWithPath:path]; + if (saverBundle) + new_class = [saverBundle principalClass]; + + // Not entirely unsurprisingly, this tends to break the world. + // if (obundle && obundle != saverBundle) + // [obundle unload]; + +# else // USE_IPHONE + + // Determine whether to create an X11 view or an OpenGL view by + // looking for the "gl" tag in the xml file. This is kind of awful. + + NSString *path = [saverDir + stringByAppendingPathComponent: + [[[module lowercaseString] + stringByReplacingOccurrencesOfString:@" " + withString:@""] + stringByAppendingPathExtension:@"xml"]]; + NSString *xml = [NSString stringWithContentsOfFile:path + encoding:NSISOLatin1StringEncoding + error:nil]; + NSAssert (xml, @"no XML: %@", path); + Bool gl_p = (xml && [xml rangeOfString:@"gl=\"yes\""].length > 0); + + new_class = (gl_p + ? [XScreenSaverGLView class] + : [XScreenSaverView class]); + +# endif // USE_IPHONE + + if (! new_class) + return 0; + + NSRect rect; + rect.origin.x = rect.origin.y = 0; + rect.size.width = size.width; + rect.size.height = size.height; + + XScreenSaverView *instance = + [(XScreenSaverView *) [new_class alloc] + initWithFrame:rect + saverName:module + isPreview:YES]; + if (! instance) return 0; + + + /* KLUGE: Inform the underlying program that we're in "standalone" + mode, e.g. running as "Phosphor.app" rather than "Phosphor.saver". + This is kind of horrible but I haven't thought of a more sensible + way to make this work. + */ +# ifndef USE_IPHONE + if ([saverNames count] == 1) { + putenv (strdup ("XSCREENSAVER_STANDALONE=1")); + } +# endif + + return (ScreenSaverView *) instance; +} + + +#ifndef USE_IPHONE + +static ScreenSaverView * +find_saverView_child (NSView *v) +{ + NSArray *kids = [v subviews]; + int nkids = [kids count]; + int i; + for (i = 0; i < nkids; i++) { + NSObject *kid = [kids objectAtIndex:i]; + if ([kid isKindOfClass:[ScreenSaverView class]]) { + return (ScreenSaverView *) kid; + } else { + ScreenSaverView *sv = find_saverView_child ((NSView *) kid); + if (sv) return sv; + } + } + return 0; +} + + +static ScreenSaverView * +find_saverView (NSView *v) +{ + while (1) { + NSView *p = [v superview]; + if (p) v = p; + else break; + } + return find_saverView_child (v); +} + + +/* Changes the contents of the menubar menus to correspond to + the running saver. Desktop only. + */ +static void +relabel_menus (NSObject *v, NSString *old_str, NSString *new_str) +{ + if ([v isKindOfClass:[NSMenu class]]) { + NSMenu *m = (NSMenu *)v; + [m setTitle: [[m title] stringByReplacingOccurrencesOfString:old_str + withString:new_str]]; + NSArray *kids = [m itemArray]; + int nkids = [kids count]; + int i; + for (i = 0; i < nkids; i++) { + relabel_menus ([kids objectAtIndex:i], old_str, new_str); + } + } else if ([v isKindOfClass:[NSMenuItem class]]) { + NSMenuItem *mi = (NSMenuItem *)v; + [mi setTitle: [[mi title] stringByReplacingOccurrencesOfString:old_str + withString:new_str]]; + NSMenu *m = [mi submenu]; + if (m) relabel_menus (m, old_str, new_str); + } +} + + +- (void) openPreferences: (id) sender +{ + ScreenSaverView *sv; + if ([sender isKindOfClass:[NSView class]]) { // Sent from button + sv = find_saverView ((NSView *) sender); + } else { + int i; + NSWindow *w = 0; + for (i = [windows count]-1; i >= 0; i--) { // Sent from menubar + w = [windows objectAtIndex:i]; + if ([w isKeyWindow]) break; + } + sv = find_saverView ([w contentView]); + } + + NSAssert (sv, @"no saver view"); + NSWindow *prefs = [sv configureSheet]; + + [NSApp beginSheet:prefs + modalForWindow:[sv window] + modalDelegate:self + didEndSelector:@selector(preferencesClosed:returnCode:contextInfo:) + contextInfo:nil]; + int code = [NSApp runModalForWindow:prefs]; + + /* Restart the animation if the "OK" button was hit, but not if "Cancel". + We have to restart *both* animations, because the xlockmore-style + ones will blow up if one re-inits but the other doesn't. + */ + if (code != NSCancelButton) { + if ([sv isAnimating]) + [sv stopAnimation]; + [sv startAnimation]; + } +} + + +- (void) preferencesClosed: (NSWindow *) sheet + returnCode: (int) returnCode + contextInfo: (void *) contextInfo +{ + [NSApp stopModalWithCode:returnCode]; +} + +#else // USE_IPHONE + + +- (UIImage *) screenshot +{ + return saved_screenshot; +} + +- (void) saveScreenshot +{ + // Most of this is from: + // http://developer.apple.com/library/ios/#qa/qa1703/_index.html + // The rotation stuff is by me. + + CGSize size = [[UIScreen mainScreen] bounds].size; + + UIInterfaceOrientation orient = + [[window rootViewController] interfaceOrientation]; + if (orient == UIInterfaceOrientationLandscapeLeft || + orient == UIInterfaceOrientationLandscapeRight) { + // Rotate the shape of the canvas 90 degrees. + double s = size.width; + size.width = size.height; + size.height = s; + } + + + // Create a graphics context with the target size + // On iOS 4 and later, use UIGraphicsBeginImageContextWithOptions to + // take the scale into consideration + // On iOS prior to 4, fall back to use UIGraphicsBeginImageContext + + if (UIGraphicsBeginImageContextWithOptions) + UIGraphicsBeginImageContextWithOptions (size, NO, 0); + else + UIGraphicsBeginImageContext (size); + + CGContextRef ctx = UIGraphicsGetCurrentContext(); + + + // Rotate the graphics context to match current hardware rotation. + // + switch (orient) { + case UIInterfaceOrientationPortraitUpsideDown: + CGContextTranslateCTM (ctx, [window center].x, [window center].y); + CGContextRotateCTM (ctx, M_PI); + CGContextTranslateCTM (ctx, -[window center].x, -[window center].y); + break; + case UIInterfaceOrientationLandscapeLeft: + case UIInterfaceOrientationLandscapeRight: + CGContextTranslateCTM (ctx, + ([window frame].size.height - + [window frame].size.width) / 2, + ([window frame].size.width - + [window frame].size.height) / 2); + CGContextTranslateCTM (ctx, [window center].x, [window center].y); + CGContextRotateCTM (ctx, + (orient == UIInterfaceOrientationLandscapeLeft + ? M_PI/2 + : -M_PI/2)); + CGContextTranslateCTM (ctx, -[window center].x, -[window center].y); + break; + default: + break; + } + + // Iterate over every window from back to front + // + for (UIWindow *win in [[UIApplication sharedApplication] windows]) { + if (![win respondsToSelector:@selector(screen)] || + [win screen] == [UIScreen mainScreen]) { + + // -renderInContext: renders in the coordinate space of the layer, + // so we must first apply the layer's geometry to the graphics context + CGContextSaveGState (ctx); + + // Center the context around the window's anchor point + CGContextTranslateCTM (ctx, [win center].x, [win center].y); + + // Apply the window's transform about the anchor point + CGContextConcatCTM (ctx, [win transform]); + + // Offset by the portion of the bounds left of and above anchor point + CGContextTranslateCTM (ctx, + -[win bounds].size.width * [[win layer] anchorPoint].x, + -[win bounds].size.height * [[win layer] anchorPoint].y); + + // Render the layer hierarchy to the current context + [[win layer] renderInContext:ctx]; + + // Restore the context + CGContextRestoreGState (ctx); + } + } + + if (saved_screenshot) + [saved_screenshot release]; + saved_screenshot = [UIGraphicsGetImageFromCurrentImageContext() retain]; + + UIGraphicsEndImageContext(); +} + + +- (void) openPreferences: (NSString *) saver +{ + [self loadSaver:saver launch:NO]; + if (! saverView) return; + + NSUserDefaults *prefs = [NSUserDefaults standardUserDefaults]; + [prefs setObject:saver forKey:@"selectedSaverName"]; + [prefs synchronize]; + + [rootViewController pushViewController: [saverView configureView] + animated:YES]; +} + + +#endif // USE_IPHONE + + + +- (void)loadSaver:(NSString *)name launch:(BOOL)launch +{ + // NSLog (@"selecting saver \"%@\"", name); + +# ifndef USE_IPHONE + + if (saverName && [saverName isEqualToString: name]) { + if (launch) + for (NSWindow *win in windows) { + ScreenSaverView *sv = find_saverView ([win contentView]); + if (![sv isAnimating]) + [sv startAnimation]; + } + return; + } + + saverName = name; + + for (NSWindow *win in windows) { + NSView *cv = [win contentView]; + NSString *old_title = [win title]; + if (!old_title) old_title = @"XScreenSaver"; + [win setTitle: name]; + relabel_menus (menubar, old_title, name); + + ScreenSaverView *old_view = find_saverView (cv); + NSView *sup = old_view ? [old_view superview] : cv; + + if (old_view) { + if ([old_view isAnimating]) + [old_view stopAnimation]; + [old_view removeFromSuperview]; + } + + NSSize size = [cv frame].size; + ScreenSaverView *new_view = [self makeSaverView:name withSize: size]; + NSAssert (new_view, @"unable to make a saver view"); + + [new_view setFrame: (old_view ? [old_view frame] : [cv frame])]; + [sup addSubview: new_view]; + [win makeFirstResponder:new_view]; + [new_view setAutoresizingMask:NSViewWidthSizable|NSViewHeightSizable]; + [new_view retain]; + if (launch) + [new_view startAnimation]; + } + + NSUserDefaultsController *ctl = + [NSUserDefaultsController sharedUserDefaultsController]; + [ctl save:self]; + +# else // USE_IPHONE + + NSUserDefaults *prefs = [NSUserDefaults standardUserDefaults]; + [prefs setObject:name forKey:@"selectedSaverName"]; + [prefs synchronize]; + + if (saverName && [saverName isEqualToString: name]) { + if ([saverView isAnimating]) + return; + else + goto LAUNCH; + } + + saverName = name; + + if (! backgroundView) { + // This view is the parent of the XScreenSaverView, and exists only + // so that there is a black background behind it. Without this, when + // rotation is in progresss, the scrolling-list window's corners show + // through in the corners. + backgroundView = [[[NSView class] alloc] initWithFrame:[window frame]]; + [backgroundView setBackgroundColor:[NSColor blackColor]]; + } + + if (saverView) { + if ([saverView isAnimating]) + [saverView stopAnimation]; + [saverView removeFromSuperview]; + [backgroundView removeFromSuperview]; + } + + NSSize size = [window frame].size; + saverView = [self makeSaverView:name withSize: size]; + + if (! saverView) { + [[[UIAlertView alloc] initWithTitle: name + message: @"Unable to load!" + delegate: nil + cancelButtonTitle: @"Bummer" + otherButtonTitles: nil] + show]; + return; + } + + [saverView setFrame: [window frame]]; + [saverView retain]; + [[NSNotificationCenter defaultCenter] + addObserver:saverView + selector:@selector(didRotate:) + name:UIDeviceOrientationDidChangeNotification object:nil]; + + LAUNCH: + if (launch) { + [self saveScreenshot]; + [window addSubview: backgroundView]; + [backgroundView addSubview: saverView]; + [saverView becomeFirstResponder]; + [saverView startAnimation]; + } +# endif // USE_IPHONE +} + + +- (void)loadSaver:(NSString *)name +{ + [self loadSaver:name launch:YES]; +} + + +# ifndef USE_IPHONE + +- (void)aboutPanel:(id)sender +{ + NSDictionary *bd = [saverBundle infoDictionary]; + NSMutableDictionary *d = [NSMutableDictionary dictionaryWithCapacity:20]; + + [d setValue:[bd objectForKey:@"CFBundleName"] forKey:@"ApplicationName"]; + [d setValue:[bd objectForKey:@"CFBundleVersion"] forKey:@"Version"]; + [d setValue:[bd objectForKey:@"CFBundleShortVersionString"] + forKey:@"ApplicationVersion"]; + [d setValue:[bd objectForKey:@"NSHumanReadableCopyright"] forKey:@"Copy"]; + [d setValue:[[NSAttributedString alloc] + initWithString: (NSString *) + [bd objectForKey:@"CFBundleGetInfoString"]] + forKey:@"Credits"]; + + [[NSApplication sharedApplication] + orderFrontStandardAboutPanelWithOptions:d]; +} + +# endif // USE_IPHONE + + + +- (void)selectedSaverDidChange:(NSDictionary *)change +{ + NSUserDefaults *prefs = [NSUserDefaults standardUserDefaults]; + NSString *name = [prefs stringForKey:@"selectedSaverName"]; + + if (! name) return; + + if (! [saverNames containsObject:name]) { + NSLog (@"saver \"%@\" does not exist", name); + return; + } + + [self loadSaver: name]; +} + + +- (NSArray *) listSaverBundleNamesInDir:(NSString *)dir +{ +# ifndef USE_IPHONE + NSString *ext = @"saver"; +# else + NSString *ext = @"xml"; +# endif + + NSArray *files = [[NSFileManager defaultManager] + contentsOfDirectoryAtPath:dir error:nil]; + if (! files) return 0; + NSMutableArray *result = [NSMutableArray arrayWithCapacity: [files count]+1]; + + for (NSString *p in files) { + if ([[p pathExtension] caseInsensitiveCompare: ext]) + continue; + +# ifndef USE_IPHONE + NSString *name = [[p lastPathComponent] stringByDeletingPathExtension]; +# else // !USE_IPHONE + + // Get the saver name's capitalization right by reading the XML file. + + p = [dir stringByAppendingPathComponent: p]; + NSString *name = [NSString stringWithContentsOfFile:p + encoding:NSISOLatin1StringEncoding + error:nil]; + NSRange r = [name rangeOfString:@"_label=\"" options:0]; + name = [name substringFromIndex: r.location + r.length]; + r = [name rangeOfString:@"\"" options:0]; + name = [name substringToIndex: r.location]; + + NSAssert1 (name, @"no name in %@", p); + +# endif // !USE_IPHONE + + [result addObject: name]; + } + + return result; +} + + + +- (NSArray *) listSaverBundleNames +{ + NSMutableArray *dirs = [NSMutableArray arrayWithCapacity: 10]; + +# ifndef USE_IPHONE + // On MacOS, look in the "Contents/PlugIns/" directory in the bundle. + [dirs addObject: [[NSBundle mainBundle] builtInPlugInsPath]]; + + // Also look in the same directory as the executable. + [dirs addObject: [[[NSBundle mainBundle] bundlePath] + stringByDeletingLastPathComponent]]; + + // Finally, look in standard MacOS screensaver directories. + [dirs addObject: @"~/Library/Screen Savers"]; + [dirs addObject: @"/Library/Screen Savers"]; + [dirs addObject: @"/System/Library/Screen Savers"]; + +# else + // On iOS, just look in the bundle's root directory. + [dirs addObject: [[NSBundle mainBundle] bundlePath]]; +# endif + + int i; + for (i = 0; i < [dirs count]; i++) { + NSString *dir = [dirs objectAtIndex:i]; + NSArray *names = [self listSaverBundleNamesInDir:dir]; + if (! names) continue; + saverDir = [dir retain]; + saverNames = [names retain]; + return names; + } + + NSString *err = @"no .saver bundles found in: "; + for (i = 0; i < [dirs count]; i++) { + if (i) err = [err stringByAppendingString:@", "]; + err = [err stringByAppendingString:[[dirs objectAtIndex:i] + stringByAbbreviatingWithTildeInPath]]; + err = [err stringByAppendingString:@"/"]; + } + NSLog (@"%@", err); + return [NSArray array]; +} + + +/* Create the popup menu of available saver names. + */ +#ifndef USE_IPHONE + +- (NSPopUpButton *) makeMenu +{ + NSRect rect; + rect.origin.x = rect.origin.y = 0; + rect.size.width = 10; + rect.size.height = 10; + NSPopUpButton *popup = [[NSPopUpButton alloc] initWithFrame:rect + pullsDown:NO]; + int i; + float max_width = 0; + for (i = 0; i < [saverNames count]; i++) { + NSString *name = [saverNames objectAtIndex:i]; + [popup addItemWithTitle:name]; + [[popup itemWithTitle:name] setRepresentedObject:name]; + [popup sizeToFit]; + NSRect r = [popup frame]; + if (r.size.width > max_width) max_width = r.size.width; + } + + // Bind the menu to preferences, and trigger a callback when an item + // is selected. + // + NSString *key = @"values.selectedSaverName"; + NSUserDefaultsController *prefs = + [NSUserDefaultsController sharedUserDefaultsController]; + [prefs addObserver:self + forKeyPath:key + options:0 + context:@selector(selectedSaverDidChange:)]; + [popup bind:@"selectedObject" + toObject:prefs + withKeyPath:key + options:nil]; + [prefs setAppliesImmediately:YES]; + + NSRect r = [popup frame]; + r.size.width = max_width; + [popup setFrame:r]; + return popup; +} + +#else // USE_IPHONE + +/* Create a dictionary of one-line descriptions of every saver, + for display on the UITableView. + */ +- (NSDictionary *)makeDescTable +{ + NSMutableDictionary *dict = + [NSMutableDictionary dictionaryWithCapacity:[saverNames count]]; + + for (NSString *saver in saverNames) { + NSString *desc = 0; + NSString *path = [saverDir stringByAppendingPathComponent: + [[saver lowercaseString] + stringByReplacingOccurrencesOfString:@" " + withString:@""]]; + NSRange r; + + path = [path stringByAppendingPathExtension:@"xml"]; + desc = [NSString stringWithContentsOfFile:path + encoding:NSISOLatin1StringEncoding + error:nil]; + if (! desc) goto FAIL; + + r = [desc rangeOfString:@"<_description>" + options:NSCaseInsensitiveSearch]; + if (r.length == 0) { + desc = 0; + goto FAIL; + } + desc = [desc substringFromIndex: r.location + r.length]; + r = [desc rangeOfString:@"" + options:NSCaseInsensitiveSearch]; + if (r.length > 0) + desc = [desc substringToIndex: r.location]; + + // Leading and trailing whitespace. + desc = [desc stringByTrimmingCharactersInSet: + [NSCharacterSet whitespaceAndNewlineCharacterSet]]; + + // Let's see if we can find a year on the last line. + r = [desc rangeOfString:@"\n" options:NSBackwardsSearch]; + NSString *year = 0; + for (NSString *word in + [[desc substringFromIndex:r.location + r.length] + componentsSeparatedByCharactersInSet: + [NSCharacterSet characterSetWithCharactersInString: + @" \t\n-."]]) { + int n = [word doubleValue]; + if (n > 1970 && n < 2100) + year = word; + } + + // Delete everything after the first blank line. + r = [desc rangeOfString:@"\n\n" options:0]; + if (r.length > 0) + desc = [desc substringToIndex: r.location]; + + // Truncate really long ones. + int max = 140; + if ([desc length] > max) + desc = [desc substringToIndex: max]; + + if (year) + desc = [year stringByAppendingString: + [@": " stringByAppendingString: desc]]; + + FAIL: + if (! desc) { + desc = @"Oops, this module appears to be incomplete."; + // NSLog(@"broken saver: %@", path); + } + + [dict setObject:desc forKey:saver]; + } + + return dict; +} + + +#endif // USE_IPHONE + + + +/* This is called when the "selectedSaverName" pref changes, e.g., + when a menu selection is made. + */ +- (void)observeValueForKeyPath:(NSString *)keyPath + ofObject:(id)object + change:(NSDictionary *)change + context:(void *)context +{ + SEL dispatchSelector = (SEL)context; + if (dispatchSelector != NULL) { + [self performSelector:dispatchSelector withObject:change]; + } else { + [super observeValueForKeyPath:keyPath + ofObject:object + change:change + context:context]; + } +} + + +# ifndef USE_IPHONE + +/* Create the desktop window shell, possibly including a preferences button. + */ +- (NSWindow *) makeWindow +{ + NSRect rect; + static int count = 0; + Bool simple_p = ([saverNames count] == 1); + NSButton *pb = 0; + NSPopUpButton *menu = 0; + NSBox *gbox = 0; + NSBox *pbox = 0; + + NSRect sv_rect; + sv_rect.origin.x = sv_rect.origin.y = 0; + sv_rect.size.width = 320; + sv_rect.size.height = 240; + ScreenSaverView *sv = [[ScreenSaverView alloc] // dummy placeholder + initWithFrame:sv_rect + isPreview:YES]; + + // make a "Preferences" button + // + if (! simple_p) { + rect.origin.x = 0; + rect.origin.y = 0; + rect.size.width = rect.size.height = 10; + pb = [[NSButton alloc] initWithFrame:rect]; + [pb setTitle:@"Preferences"]; + [pb setBezelStyle:NSRoundedBezelStyle]; + [pb sizeToFit]; + + rect.origin.x = ([sv frame].size.width - + [pb frame].size.width) / 2; + [pb setFrameOrigin:rect.origin]; + + // grab the click + // + [pb setTarget:self]; + [pb setAction:@selector(openPreferences:)]; + + // Make a saver selection menu + // + menu = [self makeMenu]; + rect.origin.x = 2; + rect.origin.y = 2; + [menu setFrameOrigin:rect.origin]; + + // make a box to wrap the saverView + // + rect = [sv frame]; + rect.origin.x = 0; + rect.origin.y = [pb frame].origin.y + [pb frame].size.height; + gbox = [[NSBox alloc] initWithFrame:rect]; + rect.size.width = rect.size.height = 10; + [gbox setContentViewMargins:rect.size]; + [gbox setTitlePosition:NSNoTitle]; + [gbox addSubview:sv]; + [gbox sizeToFit]; + + // make a box to wrap the other two boxes + // + rect.origin.x = rect.origin.y = 0; + rect.size.width = [gbox frame].size.width; + rect.size.height = [gbox frame].size.height + [gbox frame].origin.y; + pbox = [[NSBox alloc] initWithFrame:rect]; + [pbox setTitlePosition:NSNoTitle]; + [pbox setBorderType:NSNoBorder]; + [pbox addSubview:gbox]; + if (menu) [pbox addSubview:menu]; + if (pb) [pbox addSubview:pb]; + [pbox sizeToFit]; + + [pb setAutoresizingMask:NSViewMinXMargin|NSViewMaxXMargin]; + [menu setAutoresizingMask:NSViewMinXMargin|NSViewMaxXMargin]; + [gbox setAutoresizingMask:NSViewWidthSizable|NSViewHeightSizable]; + [pbox setAutoresizingMask:NSViewWidthSizable|NSViewHeightSizable]; + } + + [sv setAutoresizingMask:NSViewWidthSizable|NSViewHeightSizable]; + + + // and make a window to hold that. + // + NSScreen *screen = [NSScreen mainScreen]; + rect = pbox ? [pbox frame] : [sv frame]; + rect.origin.x = ([screen frame].size.width - rect.size.width) / 2; + rect.origin.y = ([screen frame].size.height - rect.size.height) / 2; + + rect.origin.x += rect.size.width * (count ? 0.55 : -0.55); + + NSWindow *win = [[NSWindow alloc] + initWithContentRect:rect + styleMask:(NSTitledWindowMask | + NSClosableWindowMask | + NSMiniaturizableWindowMask | + NSResizableWindowMask) + backing:NSBackingStoreBuffered + defer:YES + screen:screen]; + [win setMinSize:[win frameRectForContentRect:rect].size]; + [[win contentView] addSubview: (pbox ? (NSView *) pbox : (NSView *) sv)]; + + [win makeKeyAndOrderFront:win]; + + [sv startAnimation]; // this is the dummy saver + + count++; + + return win; +} + +# endif // !USE_IPHONE + + +- (void)applicationDidFinishLaunching: +# ifndef USE_IPHONE + (NSNotification *) notif +# else // USE_IPHONE + (UIApplication *) application +# endif // USE_IPHONE +{ + [self listSaverBundleNames]; + +# ifndef USE_IPHONE + int window_count = ([saverNames count] <= 1 ? 1 : 2); + NSMutableArray *a = [[NSMutableArray arrayWithCapacity: window_count+1] + retain]; + windows = a; + + int i; + // Create either one window (for standalone, e.g. Phosphor.app) + // or two windows for SaverTester.app. + for (i = 0; i < window_count; i++) { + NSWindow *win = [self makeWindow]; + // Get the last-saved window position out of preferences. + [win setFrameAutosaveName: + [NSString stringWithFormat:@"XScreenSaverWindow%d", i]]; + [win setFrameUsingName:[win frameAutosaveName]]; + [a addObject: win]; + } +# else // USE_IPHONE + +# undef ya_rand_init + ya_rand_init (0); // Now's a good time. + + rootViewController = [[[RotateyViewController alloc] init] retain]; + [window setRootViewController: rootViewController]; + + SaverListController *menu = [[SaverListController alloc] + initWithNames:saverNames + descriptions:[self makeDescTable]]; + [rootViewController pushViewController:menu animated:YES]; + [menu becomeFirstResponder]; + + [window makeKeyAndVisible]; + [window setAutoresizesSubviews:YES]; + [window setAutoresizingMask: + (UIViewAutoresizingFlexibleWidth | + UIViewAutoresizingFlexibleHeight)]; + + application.applicationSupportsShakeToEdit = YES; + +# endif // USE_IPHONE + + NSString *forced = 0; + /* In the XCode project, each .saver scheme sets this env var when + launching SaverTester.app so that it knows which one we are + currently debugging. If this is set, it overrides the default + selection in the popup menu. If unset, that menu persists to + whatever it was last time. + */ + const char *f = getenv ("SELECTED_SAVER"); + if (f && *f) + forced = [NSString stringWithCString:(char *)f + encoding:NSUTF8StringEncoding]; + + if (forced && ![saverNames containsObject:forced]) { + NSLog(@"forced saver \"%@\" does not exist", forced); + forced = 0; + } + + // If there's only one saver, run that. + if (!forced && [saverNames count] == 1) + forced = [saverNames objectAtIndex:0]; + + NSUserDefaults *prefs = [NSUserDefaults standardUserDefaults]; + +# ifdef USE_IPHONE + NSString *prev = [prefs stringForKey:@"selectedSaverName"]; + + if (forced) + prev = forced; + + // If nothing was selected (e.g., this is the first launch) + // then scroll randomly instead of starting up at "A". + // + if (!prev) + prev = [saverNames objectAtIndex: (random() % [saverNames count])]; + + if (prev) + [menu scrollTo: prev]; +# endif // USE_IPHONE + + if (forced) + [prefs setObject:forced forKey:@"selectedSaverName"]; + +# ifdef USE_IPHONE + /* Don't auto-launch the saver unless it was running last time. + XScreenSaverView manages this, on crash_timer. + */ + if (! [prefs boolForKey:@"wasRunning"]) + return; +# endif + + [self selectedSaverDidChange:nil]; +} + + +#ifndef USE_IPHONE + +/* When the window closes, exit (even if prefs still open.) +*/ +- (BOOL) applicationShouldTerminateAfterLastWindowClosed: (NSApplication *) n +{ + return YES; +} + +# else // USE_IPHONE + +- (void)applicationWillResignActive:(UIApplication *)app +{ + [(XScreenSaverView *)view setScreenLocked:YES]; +} + +- (void)applicationDidBecomeActive:(UIApplication *)app +{ + [(XScreenSaverView *)view setScreenLocked:NO]; +} + +- (void)applicationDidEnterBackground:(UIApplication *)application +{ + [(XScreenSaverView *)view setScreenLocked:YES]; +} + +#endif // USE_IPHONE + + +@end diff --git a/OSX/SaverRunner.plist b/OSX/SaverRunner.plist new file mode 100644 index 00000000..cc673f8e --- /dev/null +++ b/OSX/SaverRunner.plist @@ -0,0 +1,39 @@ + + + + + CFBundleDevelopmentRegion + English + CFBundleExecutable + ${EXECUTABLE_NAME} + CFBundleGetInfoString + XScreenSaver 5.15, © 2001-2012 Jamie Zawinski. +http://www.jwz.org/xscreensaver/ + CFBundleIconFile + SaverRunner + CFBundleIdentifier + org.jwz.xscreensaver.${EXECUTABLE_NAME} + CFBundleInfoDictionaryVersion + 6.0 + CFBundleLongVersionString + XScreenSaver 5.15, © 2001-2012 Jamie Zawinski. + CFBundleName + ${PRODUCT_NAME} + CFBundlePackageType + APPL + CFBundleShortVersionString + 5.20 + CFBundleSignature + ???? + CFBundleVersion + 5.20 + LSMinimumSystemVersion + 10.4 + NSHumanReadableCopyright + XScreenSaver 5.15, © 2001-2012 Jamie Zawinski. + NSMainNibFile + SaverRunner + NSPrincipalClass + NSApplication + + diff --git a/OSX/XScreenSaver.icns b/OSX/XScreenSaver.icns new file mode 100644 index 0000000000000000000000000000000000000000..c82eb94a8be3d6ad72425a693fc0dc6dcc34edac GIT binary patch literal 187557 zcmeEv1z40#)b`n8>4q&zmd5VJj@JMK?C$Qa-KCTe5fuZw#V#x?Y`{Vh38j`UQ99;3 z&n_q+_WOR<_5YtM$UZwW_nbL%=FB{E&v|ynq`8ZL9(#Dkq87~o=E=XYukZ z>2T_CYATu2x$07LY()i$v}-H7JVU12uD;~kq0O2yD)WW(ThTKuj9pR#Q!nD>shm5n z?nk_N7IEQYAYLAL{2<`u1Fu_d*RJiv%bf{#?!F8Ue{e4*)?ZB2S_~gHX3WU3BPNa< z-HMQJwYa>fMvIe6K0N*0;&QU}H2LtLy2W9|n;RYe6e_N2@z(wQjJxdcKTy@;t}IO+ zjBGA%@mXS_*Ov)rb~UMLVi&Ms!f>xH)FtCAX=5b3Jlr!m6i_c`;dUgA4Wax|2A5Kv%-W9M^w14d8pVM#aypOxE4TKs) zTU58Wk&c4^&hDsgaaU+#!JOn}SEYdFR+?6tJ;zkHczU%NA*bf1GOxDpuPLFlFF z{ax@qy(>v~PhloTy+|AAEWgfhPi3Vfg}kclE}=f?Ml!`|swuf8DQW5HX_3LCw3}G| zd6qa`Dfe}FMM`>RMs%=x%r6^mljTv5 zlX&m;Et@uYKaY}jkR_Eb*^}`4Wx&C+&-U+2e)~2qZuV|My2_G@0^)aXTmSZ1uMZJ3 zwr%zIetv5gAw67)T6a=n?=1 zv^QDLPgQDnJX|AbE6gW1Ho(1DPYM5#1^oQpGSe>hMkJ4cp8 zvw!`mGC`V1-t0}%w5v*DV$uzF5zuVoL`3<6A<&`4q0{nG-3d7y?9jVwuf?LhzUKBr zx^~-i?vPAEs+32Ch|uynhylc6!o0ZibD8Cr-$qAE?B~y$Ii>%ex6yCb1$-9b!D|2Q z+s_|6dF*lcrJehB99Z~Trgj+WM_>qQ@*lEx=b_`Trcb#YxZiR5{)p8}X9u3>OGaQ) zf3h%S)0(IDbAylU8ZrCM;>iO%ZtrPN>@jH=xp(_UP{7-e7x&J+eR1~w)2qeL!)}w| zXs>n%+{Km9m|9{@EiDcF)z(ng(ook_*V59|V(usZsfE9aCiPl)K~(pIqHkC@>1|Cu zzNl;A&O|*Bl049>)Hd-@KmYCi*CxY6t4(|TxA?5DVd9JT#7D>NhlAtbNfKq^v%Z-4 zuJ}DZ8(XP+He)&O+OpOA`E7aUF)0)G76a2*4-}Ya;jL;~_$E;6uSsjv43uYI+Qsfx z)584#Rt*7WV+CkTh<58Q7G8OA3xI{Y3g`#`t`N=kUy{&PX#h^W09XLaF{#SJmC))g z`7v>gVI%>?e~5l{0-G{oKNw=`0*Y;kY1=9TR+N9d>?X?@6n(QaJ5_y7WxwGDpf3Ss zI_Ls4t6|oMf*pExo<5qTro&$_(5_2Ov)+Jat&r^qDBK#f>q|R6+x4nzu`#hOLl!Nb zGtFUNOx##1WIm5&!MGw#_-Y z>(qYlYnMC@Uf7&+{)i7%3c4UL`YXz=wY7A$b#(RgwKR0JG_*Bz^>nlu|FvDe{gz$# zNGSf6T{|?Z->!oo()(ClyQW`zSiHBcU2nt{lcFuCG?vt{YhTdl-jd(2Lj#o&R|44GYuhz@(gc=`m5ENnx^}%8 z8ko(sZD3$%1LrB@t>M%+gHXNK5M47LmSt`3SemNr7r254T##O)@H=NfSh z=GfbHt!d&i&z&DYNjgWcTiUI~Shcd+x~Q;43~ygZ$Gj2X3QE$t)a)5QnLyt*xc4i$A)0 znv{uaY3S<8OnkO%vBt#38i0+*hV|924IYb(sLyJ?CVg4{Q142*)l9_qPPNkssguF6 zZhD;zU#Hj3P)~ZT4E3eg%usJSY4f=i^`{r;RA;C^ojCp=eb^7uhx|>KYv3FD{Xe6h z5nqiD*$1EP=d1B0&;Qx}wA!?4`PHjc8`-T?wT*r2?~KLN&B~~MsB~`<2fGQb9%x#+ z$F*qM+F~t+whB}00Dg+=47JypvB%>?F^bVK(UDJsRt(YDTa}PY3Xc`h3kwQFpV%Mr zJ{6PPCvEn~(^TJ;Bp;K~l9NS=O7ZXFq9b3uDah@=yDIU0iS$?sO)3>7DP!W>x38by zizOohYNl#RlarDXZfdn?O$>nPu0N; z$qDiAv5FVr4{lyK`X)Ko!M|n>T`ETsRY_FD)5mwN>`VR- z7Z#H_(61^_LRo5Hntp0(id34E_#Sb>?ga(JR;IiQi_RFh`Aeo#X?m$rY<7Iy+t*L; zU)%kHWTnQ1MQ7Uk*35%I6wbTo$mb7(_dX<_vZYjQ_M7CH)Dp_mPNj3w(y+SZ__(N- zPi`N)Mam1ZrLj~lpD(#i%X1|s#J!COy?q$B14?AMu)>XBa_vf|rKR~`*3^{b#JK2J z;dhQ)CZxP7YnHwDm#jO}8PXCW-I&g$Do=WcnM00WB&4z`cTBdu*O%No(pkwBuO3&V zdZ(+Pw9=&aF|WfzPF%u!HhF=#u-I$|&#D5673teE*y*3%EKn~jP4&u9!P{?Xazaex z^ZTbRi$50$kIQlJs8uA5+-L(+Nap7vv8cB*K@zG+X+d^M993jPRgt91j2)TmEaGbf zH%O{yrb@{aBQc+5&J3KDeVSUXais|I;Ndx5%m1!QbGO5zUxHr$A zoV&H2C={echsEU$a<7?RDWmw&+4sx~NivxknOTKdq6{Of8;vO<^zM~Y0iL2&t5z;sws7|3 z(Zhz#^gNqOdb?C1B$LdYS<0CeH@A{fu2Nn_x+u#kBcG6>jI6B8jP%sx_c5=YKDcpi z|0d_P>qP6;u3EVge-=&}Is1B92j?#!yRxi4#&60Xci$l-(g_wC)gN3@&0Ysa?DzAKM8 z*8*un4&2VqdV8hG5|aPXV;-{=4#_Hz#MrkHVUO-!54w2%?3q(1PX-2_IDY)-;RE{v zcKO`vAgU>f4LNYLKq?I#W{X=Cdt1VKl8Gp&mQ+-2^qUu9k8nre+SRL9E(cu^T~@k; zh^GRN?Yrw$1I0CaOO{sU?uR+$;hvnmB!1%^pXnOUgU_;|N}Lpu?UF;wDBVKTeWEi91AFu##P3eXk{+R6goQ&n z|3j`gTPrX5@srRej~_m`7joyu!)ux~N;~H;GfDBj^=>}2O`F6%de{Lz{_`Y7AZTN3>Dd+sn&igS)G%vqUTwX|G*zso>Sih?g&(KMj5IF!GLSHE1fy zk>oORiZh#S0p=Z&ePRRN(qAQ)PITS@8vbQ(qNCrwiF_3ik@Oh1F6I4;MVxb4WGQs@ zUGL@&ZqDwyF8Si`p_UKaepH>CyJL{RyKPJR;&m#RQyk@}g>& zQ}{rpLm7oq9^tANUvV_{GN)+mGM9nG2+m(+ZqH}c#Ny&PB z-UV+KBmK&fl1a#r_M3@vPIgWqX$r4MR<<}xAv2>gNv&G%=_F6`q2Wg|1A%gL2zeV7 z6B8Sg^knXag)isFeo8Dmb#vs9oRrN+NK$ga^EC}Fr$>uoA%^-D$7)b{UuBT|tYUFN6|@vgK{ zNf!16x$6k3u4O& zur7nHq!Cq?EKMpuchnw?U?52oNfnaHul5Bafj3{-0LGF^1dJpfoby>9>H;cN0X|^s zi1~_oka7m-ZA!95Ql)h1=~-X`ebHQ`3dtoeM5ZbRE_|8*>jnHp;E4#_v>ssWK*>j? z0=c9JEaEE}(pr+40R1W9loH9+1r0Q4EsAo)h+KBT9t?TTe31YQBz(F7Ob`(!1)J~u zk(Ey}J}W>5%lQH;;PVa9Pp;|&?MYe+;-(fJ=%%O)uPTx#4HQMWw_vKf1I-Aft%9Z0 zP%o_h7g#=Dpv`<$bZw-aUvj2cs+;uj(@N;%wSy!|aRrw^E-!`|7oB%71GaT!8~qr$ zhQNHj0kkEFAp_RFxloKUs-z^8W)GmK9ckwl49F@a>XfHikX0xCGMFfCvRWVsS{FEIFm`i6XT z{>1u7GSsVvZXHxMqVnJZ$-n4lnY=kG)mf?-PvXsCa$#OFsy8KpgdS})6j3|NQ72-r zHG!{DGs!1OfklyA)`x6uzCf9iSVT^pXb^tp7)g>!ajB0x_>UUFMwz$>d})qWipy8P zpPUO=pGf9sab>{VYG71?0U&=FUa zLRLX7MN}i>mfb^C1P^_0k~Bkl$dy6-Zj>fDOWDaEq7LZJlF5rz!X7zlO>3whwHQY& zg^K;A4?&2UNRA%0UQ;Y0iE;&NCRJYU$N!Lv{fNG?;w?=2NoYe#6;;rBv>P%@DBS4+ zWqWU;_f8R`%!P4tP+6#OW=aOJ=KmNtixf(V3`?tYtU$?pg#u12dAXx&pL7qBn35uq zDkPM?7<*f$;*=yZ2QnpfY%PiuIv24DN!DjulL2c~1EVr{$e5u9l;X(^SEbWuZWkoG zNSTR+Bs;-b%1k0>;nEjSxuMkt#rt{nEaF_OQ6?Am5ejPvvq+Le$|h&~Gz>aKl3b+p z6lsd9l$l)e9$dcQp&c+N!*wlYR*6`RrdfvFh354LB{Wdt=M>;5P)y1y+Rd1LBROr8 zl#yAf)4MKE)DM8r@^+AT?2m-Pg8n+5(I0%UKcu7!r!LTUB~s84@D1tBNVY_(5>M_y zlL(x%aO`_XSt-dVb+Pz!C!oHtef5c@Roy-c4g26UiO25DAa-z>pg)BaPfGbd@LUdt zHBysFJz&|yxkS7Cv+AjtglSWhhoep*q2x`gyCuoaQU)3{rTrvw5l(!OPOg2Fu7pXl zWd=fNp8`}WuhPDPwn)I@Yr{Tjys;7rOVSfl+)z5PRFQIaNhA~`KLFG~z*40O1Vp|Q zjYA|*FaQVl$Cc>anaSCyQf#UWEV=R-e?(odx5Tv+rPH81J4*Kj3~l4F0?x;51L*&D zNkInM2Q4MV49L0iBV2%x!$upZ4X%TB^(u~Opkc69~1pEjSTIj$w#V@B26eN)9OeHKYlDK+N_|5O9#U*64iw&Hy~9K z;aKJi_(mLPU~blewvD7E$%YN~enJiz0&Q(Yrc5(a(5KcSH2}-&$R-CwjiaV0K)wN& zt)QT!3j0yKloS_K7|s*%AILo5Yq3OZrUIL5AYVCsR@+yYN|cZkrh>K$Uo22CRtJBQ zAMZk073IMb2#zt1fwO>tE03QAyT{Poz*jcbgaw3TCg5Bkkt!ui6Z6TtPQWqr;4=gU zFh(}4u?xNuNx4dI&p_K?gMeeC53O;-sx&JVcLSvvxy7W|TOAAyy##b)82(KZl`53- z)}XAofz4LJ8_RY(-xN!TVti!8ULmOSSYkF)k8GPLNgWvZw`t02k! z^-M&jAQYJj8kh=AO&ge+o9lo^yWw+|&s%op%y0k!uc2)NiK$KlDp6=E6dG7;!(}!u z;1Rf@PM>}T#$#$ZIi4Swd1M-BIfIfzFI5dg16;f3dwx*P!kr|{P(K1o-cV7657B-? z*A@s23SS)+o;a(9Crsw9=8mK;wq2CyZR#){N})^@J9F&Mk;>M zG5!g{t)w8@l`GCc&iKp3kAtqbd!MUJcuvTN>z@dT+j>AkSSe`4F*!Ije5fF=J^Z|1Ak3?5NgZTG z36GF-IQbtDfw>rWYkI-7Vp1|01a5?!$Kk<$M0$gc-XOA-o{h_hhvbF`V3wHZH}WFH zx*s7Y^vd$tz|-|68NI+_A095Op#c#wdj-Lyn<61hUcw3>$p8+xygv=QU$G98tq@09 zJGYyt!kX-co#Y`_V5t1o4^j#FM9oo+@yz5jAPKOiqN1Fvf;++R9L={z6=Gs27(=wC z69UUfTnF+D{{&qiUf84UCy~9(0x_XkjuaE4U0{!iw~3k)DQpo-aEfU_h#M4>7Htq8 zkNvR*n-XHWwJyBI65Xrt1W#|yz_Y337F-n*rOl8|n*BopSUHF;93>{In?boK7S0fU zf82l<5%t{w_sIj?Qlc#_9^nNf)L=>CD8ax_t zRSB)d#2-!_#uZ8cZS5f(x3;{)0dI*94aP^{0ffG=>;THmHJaO{6(Rb|Uo#TO3)W*iVJt+Fp-YX-3cGaWr#h7+c#a~Y`UV$at$ zLyf0Oi*%9*xe`Yrl+$0qHN@Vko31hew{saE5nC_@t#G9QIvU1ZawCFd>fIn6^oEYY zeI48yL+|~ZT7of0wt5e{>Vg|i*CuLfQIP2*Q8z0Lo{>kx$PPU+R-NF$!Sy%Iq%EQ^ z5s+vaJRll9NQL18Vhn}=EeL6bJ`b%BPpdK=TN2aGU!gMxlYVGLYBuC4WIlv@WD$_V zO5_qwf;*uM(GBepeLRN{8werhIwXts>J@mAgjSfNH=xsr0_+FYNE6%v#^X;lH6tQz zZ{x5#jk~qWperbp=Hf9Eu)x7zRsgffUKla^pR2?|VTt|tk}+ud^WYrW1f5l&*v$}E zh0)+lM(T=)>RV{Nr0;q%Oo2RxLtj;K$s5O=-F}<|v^$3oa;h0`$a`|4Wf>Vfo`knF zGQ|BzvAF@q>fvJR`26Zyy2nohvubSW2$VktTc=jfwt!M2T+z3?O z!(ZoGO{?vvYhGzp;#DP*&$1f=^`wG`TxLO1_5CePQ%B>4CQCy{6VHh4mJ!Yr=^Tfx zm%m)eUmE%^4UHzj0#HRh`xM1z+$taJr8;*N>ze+>PPZ*Hi|)IklGPK+JUjg5sHR3m(kF8jHDI~eH+Q>@6ymPLj=mrIt(JX*oDF7kw`;V zlu|UbC`UW{`#f|ODc(Av*+20DFCQ>31^l|_AZ9tD?uiNX##K+8$W z7--T!1at?pCrCgy#g*2#3Fv8Xk|LlP*?GhbPr@%Xn?`VN3YdMYJU-LUw9E{NoPBQk zefD`;HT$eUvClc=k{A^DYZdU8Z#Y7>wjNU-_uLp>evf;eD#Oev-au$M>SCZf4rznU z6W}}Dj_u^Ea}jPOM0|^N#v5S@qKb9KbH52u6C`spM&j}4l{Qmy(k?jztGD5ew3t}0 z7?moPxe1ck^|H*!22*XMSY|e!NM~_XK>>IYV6&W?YjC-mG<@5oBXG5~b#z49dOAAV z_)iC~RCJMPEpY!DbrL` z#L7$+6=f9_k+Q0i8Uxv8IrKN!W+gc?4qZ(VPm#;z^XR&K0~JJ8TWO}j73jJEqra^> zPs9bDv+NgX+#$F-^i9GU`C&>Abk|n3`M;hszbv75D-@7hv@n0el%EZHQ1q#ARX{ha-_= z@?rcpFlDT;ZUIVpoRIrW>>Cb8pa;r)0~C(M9&ez@*K-AZo54&zC7k?+N4@3nU>tIQ zjZx5gIbme5<)92r5m%98s0!A2hMI;=w(PH}>kf>e%~e#~aZf_TW&8;1vw#d)qxno2 z*kQ_KH(<6hv^%5d3QV2JFz>v0yTXp`yS8><@kLxZ561tLbWD_v&DR4MXno)%N@c76 zZj&1@n%G+wQdF`bo5w-vzJVnteRT^zw-ohafVTzR`Z#8~V|alH=X4_k>)Dx^gH&%% zKrHMEnOu?e6UchiShDUlz_aYO6NF?Sf~gy|a$>mweHIr_!?Qa9cGS1AWbCe9kz6jy zRJc4Yx;%xYstHfm14FL`PZj0T7@?7g)N7~Oa@EV|s@1^a2z1d)&9j+B3=zx1PKkkH z_2Rh8p|Gkd!-%Y(9R3W&(BN_e8VJ>9h9Wt(0cd?&xdUCtrrQ^wYF<6Oy)SCGz$? zq|BBYrcAN&ZlaDd>5ovSqfFMONk}_j^C+3Bq3UI7Yd~?h0wsj%K3HF0>^(k(WIYSW!3{v~*^-9irn4O9i*-hlx=oYu zu4<*#T0$HF+Xa{-8V)8p*faqXk9X*&A;D8iMQ`foZ@=JRw;3oQ4r4Neo!kO+CS0z@ z;8%5hZH#JyRjmw9NFj;#5Qi~Wpn>DopsQ^v*N=kOB!{RnYDVLF8Cvyf0BUsbxHMN_ zG}7>0yA@!HtT_LN#iz;Ymk%x#90JB&+?g1X)}^X;u53tsyY?Ez1$tOq&8VOD7N9jK zLb8n-lHV|eb*{p z#f!>%Tvi-KZ;D&PwP2sOel8o2|!WFzI?m%6_1tVaQjdGglA8n#E~tl za4j%eHYC0W^%T^_JQ|nl!eerIM*2#gz*6NIqI4oIjmH)7#Avr%LvZ>gP_>%NTLD|d zqBEH+5mTAP!oSFKDycJFK|#xqBQVgQi<#>9Ih8{F&jvXCEzk<&OQ^m>>a(A&k%_Uy zgl=qNA~MFe7R~rPeQiy3CEcD*-OM>0T^nl?V@#xeFrPBlY%4DLh^!atBR*xY6!Dqs zNgb4&1bn{8K$UCKqn)M}8bWXKG0y|Z&oUYLSw9L=lN1U?elniWG`V7qGEbka!bPLj zh2z!S=htPc*h^X2D(+L2h08!12m4Wp>N$ZbU_eC`{V4engJoBym)zx{^4uWci##j%+8# zaeY9yK900(IC7+%uQ*ah*!i2m8-uvPcY<$T3%YXq*3ICctJi{puHHa?^y9PeftkD zJ2ooS9AFh`DFRI` zlG=j_n&-(C9FoE)(pL<$Ny!pW3Uh!hWC@5#Kg`9DB5e!Ji4>rS41gP#@djI&>=6O2 zMHUX@8dRo;43gl38B`(d8K|!60I&Ds4HeL^qXxUcU@{b@U%#F4610y7hZPROqc=XV zB?Fkt{=v$~E}-QWE5K7?3JIsc?((hI#1a$Hg`S&qf{xK`DaGhLwol4{j0!8V!f>qx)cpAxbUrAtYO2 zaTF*eqD&t+EPS-UVGtjKsl=CB@hDW7!Y3(ostd0XsmRpJBVhoIhKG>F5FjQU`$4av zxN|uOY$uKQ^pdXBZ}e``2{g?5!~A?2SUKUdQSRa0l3H;b^qP)5p$iy}86HloU}!H` zQo8~f0XYmUX&oAkVv#raA#>VS1Uz~W>5dJ9v>3WRKtIw0n3{^n4Q^Ewf#5mW4>nfl z2&p&r0r%`!w#N%MFbS*DRI@+ysEv=-UuncxjD~OrG{^-A+K#fVgm+WmN?YWB2ZJ{@ z;1MWgW5%YC;(_YQ2SC2@zysVs2Th1bpaC9?@Bw?u{P|iTs%&g*P5s~)4hHiwW5`Sf zR>W#Jkdt!JBvtBkc}Su>7#QDHyvFSWIq)k<6R-A3x3}&u>3^7(sF|AEaWx z=iG^MCCvADwCovDwMBPB9zS?bo?O63BD|}uo|-hQW^T=^zohKn*xt7~ihr%z$2B(qh45oI@&y%uc%{6d;;TJ=LWu)v<5aJ^5H%ZxxV6F3K zq->h0o()4c@6Slt-b^cV7$hfUD}IZVZH-Gq3rjBE*ioUuJ|lmNlx>KlESOuE(*>VO z(ko)@M*J2j+ct}A2cem{0E3%y$zZ{6va+^WxSkdYElg1{kq+ zVhC_8(NM#}Oc!1uE!*S=v}{#ea2|06Q%j)$Z|3lR!%~Pwv-1y#Sy@GtnS}|5 zYs}?n8C!^iEDK{zb*{Fzj*6nP4gce46o4Cq+82t^xG@W1^v5eN05vE!a zE=%96fxbRpY^H=zd=yKcZ!R`t;)A=m95>uNAdfFGV+$=B=qfHh zw_UP>NpZ5czxNsU+l;YX3oP7XRz)pZ7{cXnu#(BEXl|~pndFHUFE(RgFR|K`%R+tG zNbbpbP>M3I!$iyZS*60y+7)5%7+IJb!{j7&LrT9?_gg8do@%RaCK9so+QJxgF^HHV zYrg=0gRHFutd53hZcMi#4s=TjmeQ&v*o@(bQ5R-rRAUy(h}-Yt%7|M|4YC#Yu&Dv5 z4e1ZTQY6$z5zT}a7HmCyW*k}s{HRAE;#^JVxg)G&4RCE zOpRRhQbG$e==C$eNb)xSO!A_{*mo$EDHrEojutf}C>5AlG|=Ok$p;9kN<}%XnqigO z1toJ`W;Bx^v{5Z+*`xL>3>n7wd|qn`77dMQF3>f$5DOLX%F+mq%7FRRcJV`CnKC#S zc!t_Qp?4E~ZJBCCW}2uT9iB`tSe3as%=$@alWLh+R0qnS%`8pWia6(4%leEOgj{V| zg4m311#Rjo@ZNX-#472=d3WcO{>n)W8a+6utktyd5V zExD>@<{~o?N)Sx0U6GJs!C}a`>*`@q4{B9-uS};%g^IZfd<}s$VxY@47wS>QCXQ`m}rr`Sn-0Emwxv_l0k~i zG-TaIUE&+GxGuj0OY!T96h$5ihUVC06$+ISocfiR(eVxTnYjsA{4%UMk0Q^P;dCs= z6boHtcoHGg+(H>{{xTravPh>h+kmYQC8cA7DYrtko3dC1l-o)l0&pN8%}%+P`n6gW zH(YI7IJ9`s4EN)UgesJzLX?uSSgQXSs7^7u!`5;<`M^R>_$%5S!#>kxU_fVdKh8K^mFEF*RFsB-)h$7)zV~+kt9!73c z#Jnu3{3}&q_^_-uk(gIh@MP&QXqpXhDzLyG3v*K=o*rL|;mQI9XBGol0V)hxM)}so zsleDQ3a5f3^+zt=q`?LgmSrOyF5f_8sAM4EbM!b|JsWFR6KLQ}(eJXjV;R!->36RW zOx(ohah&x5kAO1y6!lJp9sfM@uEpEHrR&16A2ROL!&5}n(Z(zT4=$??(f$qYnkrWv zXKdibWf-z+kn7(mQypWhXza~r^Dw%-2C4p?Vn0u+Q-aA!^`3*a{1k~ky^2IfOZzs7 zZd)&jjv=UCNTLtlgao>?6Uz~)b4SO`$f7$rj_(6{`85!cosq{8kEl0}m>G6HI2dDw zF?iTDNbLrG`^43tD>rZ6xDj;as_2U1b&4Jj4yMA3nG|b|IT=?j-z@wASAKL8AgVBO{PviQ9#QG(C0eF%jXt8{d0a|10G9K>I-xDvmEKCl4luA@Swp_yD=`dCy6O z*GWQ>4&;@KdOP;tfDE_ym9Mz+#t@F&^#;-fS#TqgVb2DBFu8|8agE;*e0DT#Rt|FI zZyYh2LxMcq2+XB|Ja7y$+ZZBPicd}qxrs!RJ~@nBxgCZw*WuZ`@EJ_nkQ)i=zC9rB zB%aX%MKTe_Y=seIB&>Y!I6DsbL60JehC?r86Zd=on#V9eivJj}Kb5QFQpN_-F2lgP zk7ALaT)P@P>Q-U&9$H6YsNyYXNe)5OUTE=V`Yhz(Ul6dx2QgenZN*X(qfsBwC_Vz4 z(lMksgktZO0`k$_;TBO+#whBg7#V2>q!dQft^jH2X7moY|8x`a^G;N{!fa$y2VxKs z-Goem^9UaW)(GDn_rR~figYj`CC9U5Jnnqr0Y{^ePCW`s5Z)TnQ=ms(c;qvI8G_GK zvBcowm9QSs2Vp2P%ZQAF%ZUDr5?&dJ_XUSxWh&@kth7dvDFac@fZJsxUjtx1g4+Pe zhwgR3HR9F5qzJi8Xfrk(iTk6-lMe>Rao|XXL7VAQilUjyBPQ%8y+FC~WLQzef@Y&` zU<55)ldV&p4EC$B-|<1`Q%651O=%PDVO{MCkSA|XO%;lsDmXSu@nN*clMfaFgLRAa z7lT%Aq5?9LPNWZTv`lf6ZJ&+^^rHx#eV{l`LsfI64ZHx$o}kWZ(DduDgh&h*TEHk= zgJj+53Q314Ep~7OE^Q~l^BqcCKawYGXo+-bN5)u94)th^kN1b+qc>*4_T{jZ`~$$v z#=Tvb9ZyIL&}QJUsA--^lVk9Vh7@UXU$`&pBPAz{Xjn&(&GyBXhST&5aM!XO{bB<( zScEkBDLgjN0$!a%-ghyc2ghd>!catM1q>R79M{G+TnAcs=p${CA2|p&j>BqF@d$^@ zY`Q5y5}WGTmomF)4{uRW*UG8RNOt>|D65$^#=bues4mc; zp};`~_||@W9ML*Rp8=0M;zr(Z*n!eVfEG$`)CThW0DLNuBYzGjA}Eeo1!B?|@&hSD z&~!}oUaP9&lMQQDfDZ+DgojUrke>-E@#`UICoG9+3fERa_*$gLM`O@M8OFj2#KZ~* zs1)#2f-*$!g~Pj{&2wKxJc}Zrw!Ze@4jDda!yJ-(Lr~os28r@aL120!;eSfrZ$!Js9tOKJAUv@^FARN;40#&HK}R7&UK|=0@hp|R2qxr~v^IE6PW)eH z$QR3=sNV&bMRi`ZI@kZ(mo!ClYs+7KSy>q=P=fxs@N}>!Bh}xR^b3DK#avw7RCc`M z&lE=a^xuA+wWZFN{Lza6U4FZILJI!@`k(aygVyU0>c=R%KNNsL>-|Ud0{k2G|A_$qO8tKzz`s-f?+frR)&JW9{9E<^t^og9{l6)| zzgPe73Ggr0|62n5oAv*W0RL+JzahZCTmP>M@GsZ@%L4q{_5Z2>|9btuD8Rp8|E~$~ zAJqR#0{j>C|B3+rN&UYdz<*Oe9F^%n_$ zN`U{Yev+W{GdHLIUHxR=&nVzOtRDlXemn^N%ldKW{f8sqzpOun`@`yS6ZOyT|G#_l z-tNa1_+Qpv`4a~4pVn_j`=J5+r}cNC|E>QAL*TFe|GV*D`Pcsbj=#U-@4FiK>wo_G zpYN`r{vh$M|NXoE`L6T9#J~RMumAZ27xUesfBny2|MS=Xd|v~9{qJA@`&}pc2Z?|E z?_dA>eed&k{rA`Z{`J3q;9|d9^soQ@>wo|H-|uVSumAn)f4}QQ{~+FSmP#!sC(ScFSIEEr z;&Zf>f8q!@4Zm*ZKYB6$Brx>*ZsTw2|Dzh1F{x=={Dz92D8A}U2NM%DWp`zKuRC?| ziup6=H#ec0RrS{%|4zqC{Tb6IFOtbtAB<&I1I-JFKGd---KBcCNF8Uv{mEgjho?@)l*G_fZ*hQ)iF0%^=>so1|Gwxo` z<_{X`4{H=P@|fsy*AamaqijMlcn(&_w)rI6?N+%orV*q6O*4b(r<(y+Gd`>_Y;oJ0 zycPY=z8P*ksi9hvC+9Eia^ke^HhuNNi}6#Vn+Y1;yV>=W`^R+ahD)x$ZE4uae^*!g zjh$MyemqF)VZ5KQILnUl+%)|K%TvG{f23qlvvs}=)>ORqjqG?c;NWZ++QOjKp^HHm zJgt_cy}jS~y8e4Tzb7tJ%{wnmz5c*vUtZG8R(&c|hel*-HhXa7(Okm@>^nC{-gNCU zHGk^GmunnP+MItN_6jZw&~xn3@t*{T9vTCN&FiYwFnNCKXu(om=|9JuuiRtbnmcsF z`B(33W9MA!wLPTC2S%I9A${DJoH`KOL1$=yg8!&c^>E)i$t#=N>}oK4<5rUZ&q$~6 zOQFez#ZS#PAF=H?D|1=IodVU{C1G7k-9gxdee_=WgaH5R`(k=Fy)tO?gQ4f6941Y- z?ALhB{AUA4$8HI@ec{oQJzWl$I`%Y;zj@zGyWPy?vkFG6NMk*?ceurpT@h3LFEuK2 zD3Rz{J&dPqJA->XZ_OPBWC%>uO>R1{xR5+dyeNs8+!O4ip`&REcF#f|+6aMwp zu5(9rN?tVKy+^j`g`Im-%r`|Swyij!xkI0>xtN%jR^)K@J=HLLyWnAbZ(~vU+DRt* zqR^bMLOZXML({@$Wtpx`uu$f#mI}LRaoSH5ua2R6m}MDuOy2z7@Z_bw^Uu4jJuoJ7 z-TGZkZXBET{{AM{WP_Knwy{}#C+KHi;e|<58yG(A;@n|UqcP4=ZFc$_m4gcI(S|p@i<}IqK{ymf8zE{F@inX z36b<>3s@@{d)P+1wHI9#Pmj9yPwE-2;Ksr=iTy;1=j~sNEo)jidP7U2o?A;aw%qKo z&gGhI!v)c|&UA9(X1Z?Om|EnV=x6aA{q$aT zi*V^(!B|2@(GITmpD<6odBk3(>Y&q=A=BT5?RwU`$H)So4zD%$ck&*}992~4uDo)z z_sP7DHk^xF`~u!24GHH@weFF&j^o_lbP{8g>4f$HLr+;;Thsi#((R6RaY>6kCNAw` zzsUaJy@vxIrY~r+;L!2V$9{t@-!3ijo3}qbFg(=!+~o7ynyuMAbn3F)u?Y|27meGs zea4-_Q*pBvk;Wc-`Un(n%-fp&?$!DeoS^ohEj5n&XSCw_4!eG>rD^m~;oU}8vxiO_ zU~HG`|KW0TH{SuhZl&+LG5AxLM&s^I^$h49%8A-FWt#6srvI*+C(aF6er#2rPxlh1 z6fB9kJTd(JiRLTQd#}y+TiU|uLeB?5hjwjv({7w*SWE*&~t$c^H*3cA315pDCry4nx(x?jvc#HO|2n) zu+SAw?0=NPRlYu`(pmGI=RDKkd+A05bPxyI?G@3IN)u0GArIaY4KY3QPxIK{EQ z%|e3<@w4wtz2kGcP<#1op3}%psoVH>l@EEJUDST`5Dm|9GuB()@{M#n*s#OeknDcq zk1tHhhKMAMmsUPc89T1WEOC)7uknuPm*MvqOEX_Kz~ zLA=hk=O<&S-vHKWf7df=#xckLdAj77>GR>7-~~==dYaDe+VFzj$~g-+c9=HGyLoed z-`4|%q^7GZUu`jW$q`?N#}^uR8fETnSJvuSKuVAG&%$roDMYPR7fD*~2+y**zx8Tz z?9_{46YWDsb$)r&WZg4`=zFsVM$K{(uYB}U<3Nl1d=*C9?!Kmhg?-zYI~^-qG&wO~ z?4`uOhFhAqN-o&)a$E33R!F13lD@a{JU(r>#?B8I67b-ez1F4^y-%!dvtU}A5hGd) zFN^kXby}Sg|IX53RF2S^X=1%5ikY+_G;~Puygm!t5t1gIY&?h<}^jGjfX3_ShY(y^b0sTuBTYa(UW_ z1x0(gl97u~woE#2mAziP?BV+zjoiAlKEK8NltSKWgTN>h zJlv~=*P_%Gl`C=%Jm1CW9eGbUiLTmTZNuS}hTSf&87{f8C#-m}qx-=2hrJ{6Zy${7 z=%&Bxt$#O5jVJU5O=h9sR7}Q0CJskDc~5 zX_&>6bWY=j*|drrXLY9_GO?MBWJ$gU${C`_6;yTOIk^JAj+sf#<@ zosdD>N;B4RQrJ86)r_`I2_v)?m`+k;i%!vQMiy-6`Poms*4xgV?jUN?@nDk|OXyc~ zuBj&;w(rtAcIp~-xcY)a!C7#@%421xfJ%cBZRyUrFCs%Y?x5v;%X&VZa4J#$RZFlan zK5bN%=40h+^@OWEO690?|B&lVU+Xn6*)nD6#nFBH-_$&KBbhd(|Gw^X7#AYY zcILRDJ4|N<%Fioeyb zw$flN)uy5a8*MZ;bbB;)Nsf>4V@Ne*Z z=wscubNw3yYBO#awN;z*(TscPK7W4kyVc8Pr!?B`x;u1w^Qitt7aUJ?$q(GqJZ0gb zZUxreSKUt*FTW*PIecHkMk*=I+UIT)*!A8Kpf=IRA;`Pol2C4+!DZ)OGIsT8ImvVX zF|V*s%$3`AC!#151b=e)P=BoU1P3MEVGcN9l*#BI?gEKv{ z(ad&t?8n-TC{-v5?Bp>0$keubZqk~E+>XfJnH&@nv~2xR$7ePR9_Q`1_tQSsP;Ks% z3w*au4XxH3&}+4%>$DEq?YtA?*CxK6cX96OK?AQUzjj!;vdBp3pykHpEB9aAo;+!b zrgfirYR?W9Y~r3uYGUQ>pfEL3dzlJj&g6g#0oN9}1}FA8KfU{e^EnGIEooD^z2QgW zsip^Wy5YC{zBssP&oHN!i&iI94ly3f_9hP66n{LAj2{?7?RCDik z<+BZTEN{+Ty%TH(Zw_rU*Sn;|D@Q?nwBL&Zy^d+VjkTCR#yxh-*sUXs95cdBHc9St zefSb-%Lk6uN8--tJaTH;;p5^bC!E48hIToWm)fwm*6K&1Rzl-p6N07~1fEM0S6)3c z_weHVK8wS|3t`78)3ruhB8=Q~Dx}G;PHfaJ>!!CN}x3xNdZfrra(z3fwV~-E^oa2A+GRyWzr?Y|c^PaBdn!oBYGrwzO zSjM`%r<3j08H)F==s53O_EOs7CPU&cU7j>_sP7J2K5OBOH5O%s}~2I+g7G}uw|z?O`NlW$c!Tqjc!GnhAeNe zG%Pygx6=YjxCe#Nh{v!j-nEJX{pWC@^|HzLkBKd z&{VH&N6p;8Zt+pH;~`m_J4YPh#uw}EKdM&QJ7ho~_V)gqpwK4lA+xW~c(ZWOwxjwh zq1?aD<=GVU5?3*fE_`Iv(|%{(j)q(MAJiAD=O08C}iqggrBe=1ypuVK-*WwJqub2AEjC=Y_rDM#>^i80YVYPQ z{l-a1(^R8xa<1sdh6D7-Tc1y`BLBG?`~?WYBAzXlh}=}>NB+*ZMRxA zO78CvFKx2IG>LV+tgw9kmE%rhQiCt|7lr6|IU1yX+Ayu#y6Z2e-OtYqf9#tk9+bLo zt5=6l(rTb|T!;{Cq& zUE{EPc6WuyR!t`>Y+qbB-Fm(Bqi2kBM!Vb(N?lZ~XKg82LwFh=qe|~O^iDAxV{m(E z%L%mUXB;HWvx9tvwmo+Y37THwm;4~Q=u(d}t2a5cp5dWz-23s0>uVInx4a&nEJ~Te z_q{tJtw*uOLhXGmKa}kkSFW`^!m-_VyW!nlfql<(d!lh`M#+=LyKW{~1dWjxM3lEJ zh`4biu^{Zu-hH-j{UW1m^gEDcr+lLwUEPy*^YmN`HfeWS)3D;j!gbr`6sIhYPI=L8G)^%^9k;!d)zG8yMEJ+sfhE%etuaYn2mxU_j3SN4o|% zhj(*%`6_bDl+MjswJKh+=Gdj~8v+a)sLuK{#%7kWRB40w#I*3irhT^;nZD^#bfhIc zBU!O$yvCE|M<#~eZWZW#Lhm1~8LqHx&ym7Doz|UHy?CH;YOh8m|5#i$e7D#-dTFq5 z&7D&I>g$oKo2|8FWIkDIp|M|Yr}grQ(r#^AsHpW=IxKWpXh`<8@ueq+caC{}V^dUP zLExL5;+KQkK246kJiGD#08l`$zZNR9SNS84nmUYx&`fJA*6oS zf|seb)p8bjzGZ!CMKK3>5$2)f)y95Sh@!3x&3X|Z^;{n%PMPgCx`;8@{PBwF zGjwc%^>pewU{c`bN}nHolE)<$hb_1R<*0IzB@mADFt!IiHw#)?V3d?c{~zn?;5#uZ z3r)-GJZUpjwFH->e-fw)_NCC@^FfvBco68hsJ^#(ZO)mLK*TY-LT9^oWqUdy$X)gb z!U2sk&b@xu;D{nt{h?pQcTXlnn1biHGsGZC?HprPw6C8~E zmKW*uEjctllg(b6vPF%PB8lHwhqmKj;RvtJmcKe$NwsZ+CB!lFpy=X#)G0T*KGbp-~`PAeXOqidQ`Eo*O|7u3u+4EO z9HScEhHUIYiS=l5XVBQMU3I%da0lR{$j+{F$nmyEV^@q($(hin8FDS(t)dx5Q=2Cz zw3|Nd7#5Q2Py@6QA;;2+8YDeWs2b^+5F+0D5fI=S%Z+w^)1EuWpkd>w)slsC;Azz{ z;HAjtdz?{@>5^r4H;bS-WVciV@jjcp0wsHl#2=kG$ZyzRc8>IhGIQA15dML=RGu1M zWP7he?p$k@W&wOYQ%599JSf8fggOpZ>3;8i!&3%2+fbya?=t{6VScE9UIg@7ORPbSXQwQG-ZNK(C@tg?M0A7okNn|t8P%DGVPQtslvQOmkg*$Qx4S= zO1y6e8>01wcBa4RXFN7r4{6;WI7kI-umV>Sr>I0Ok*plT0S^%-a88cM`d(dhsA;)9 zgd8+nEPow1dZq->WGG3egf)aoodgu@&1{gpxlZ&}VOK3$mRY#R!7r(+y(*k;68PU*i8nB-Se81yTzHw%}_mx=(V^&85U zR%>9<19oC?+r&b$O``H66^{X=q7F_4_&T2CPDnZyNY~l6--Qamd8rTMYY_nR9-m4;-O;nxd+m&D zRBb)jf-?MvAzlqMfm2H754lRP320)aC=)T%gJGxam@FR7smjPZ$_h7zewdoPLK5zd;Vq4ATF|Z_{aW0PJ`$3q ziBe9}WK;8hml#7}5K&|%j$pmAVt`Fh6Ci51l}#@DVNjWd+O@~wM91LG55Vxkw)=H4 z)R#pq0dhV{Od|8=_Crx6@+5!H46>^$lZfy5kgEWwy^7nfH1ISl2bX8Yn>ILV3Z8j$ zxJ~nX-!~xjCZMOb3Avw$0M3t3Qc{L_3dMl34gD+ zf**uS+b`X}{QAU=8E|n%o!8CteBU?C^Mpl5bFvM@R{>~G_}^6jBJ8m(J&ITQX17Bd ze&U-X9vlB-xQay^n=Av^jDm;&w~0D00_6kY@_$-HnO#E# zxqE-)3(ysAd96u^7z|UB`2FdmxBvhE08V#cv~TE93KapuA8T%RG!LEC5Rhxw!M139 z5Ks2l(RH^y;N`UdDb1*Aa^k$awDGUN@RDDGtLK?3%WrJN=L_2%3#Y0h-qAEO1fMUplW~cQ zu@n%mQ}f$2b>A%INZJDU?J3feHx9_1=`_k=b5}WRN1(d2-ru(yd1Jgrj@{o8*+U6U zLP>W2Tbe1CkUjj9w_0&jr5oajB9J>ok}XB?d>8)y{}Wu^C%+?*&Ph4zR_JKKFc0|u zA|2(a?ZHfI`bId)2Wykl8>PB{Y5#_lDhe15I3OgRIybg?5DRAG)V;7(c}lrduvbTnW@3aJ57AM3jT)Fvgc?eaxHhgIsv|=x$WdS=iPCO76_g1(=0AE z$nh!>gib3Ah>LAka_Jtd<}xwswEj`93I7yz26?nK54)29y%2sd(N~u8fd&Om6hp5a zp--UA)|@ileLRMjWDxEa6LFd#qHzjmsMNY-4{9Q8tG^-K=X*y|6a#^r5E_5{m7%*m=5h$<_&#oCI?N9;Hn&744np~(_HacJ59KB( zF-2VS1Ro%KFs%o4Q)ac@^bEA#?FD*Rc}b~e%PzJG!~j8Y_ncIygd)zi-1;Oiq!9DV z^qQ)M`f>Ro8y)NMqhDgE3|iW12AeWLYceZ8?Ny0gZ%DxKYFv|(kub4duQ@KQolhOV=lGj9ORv0%XQm!T^qr4Fxg_<@fkcMs%Zf!TGA)pxT+|9) zdL($viTE{oU|%!KGbAVYDU`j!k)!$H^>r)&VOg4;pP-_p2Q&)b0jV_`pA^m*3cu}~ zQUPHi=1iORUG*N_P2*M<1yuvKEREXtPa=kshk6LCas)sQrd!*sy_HxYhGdmUQ2Cnl z%9jF2^h408zEqRgaIjP42-~ffBxrUE_Qw4O(KC|x+MlB~e|ONAy-ZzAE1TPxqmBhk zanKnbq|M8uj4|(fLIgh5upox_+F{K1- ze0t6(aF^t59qRn+2K(vHIR}yRl*{~T1fIT+JZ;CGxa%W%-|Yd;fzmkdoaCd$g@G%3 z=UyvEVT^2!8yaX1UN#b|kKSi3UAy8l<;`2GWq*+%Y4R z4#@_T-KbW7W5Fxg1H;EE7(2{jhlvZJ4} zRrQ(k+$(4GtWc)~*Wt_hnDx*55I5hCq6ZVJXBwKKaycFz*m1)|kG(L*w}5l}tuo&Z zs?s)y>N%33MzXK5iu1P$9&cE9;K z#zwGMFUuQ+EqCkmv$r!vo9+fpt{FeDqZ_4v(dX}Q;BL*|5u23LtOVg=7l?^0EVx(a z;m^$&Sdqfa6St(EzUZr~fX6`;YAFqTy)PL*M!4=6qzX7A$gi>vinws=7Wgq=Ry~qp zYAdR$6!|grR-Tt=vno?6V?855C^LTG1)i#3)4LSYBoO1oTnVW9+igcC;Q z>tcUrudsQve=OqEHU*dlW2x)wkXg@(VkK=qsUJ&P5s_nRqJfMvy;x96=z`LC3eE#~ z(0&jy$~sSSs#1I-aq0*A;UjZ?NAns=HyB*)0tbY+2*|c-XdZ>xScr{nLd2zq?}k)P zAvH#yb!T^)o*VO8?eJm^c-jl??cidP6gkExWr({m1p>ZP=21*!WFgtu$O6T9fB-Ov zHGJX95p=H)V=ZYtGq>@ckf*Ar-k4GN=*3DZ6;9Q5Qy0QX040H+)D#Gfv}G;57L342 z9@KJJ3#v`db*q)K9G#|6G5Hp2oX*0(`xRUSiA9SIIF*ifkIA?*BJ)}8Mk)y?r^jEyaw0-0JG7%H~ishof|9}5^L~;OO z7ofzrDVib^WKLt!FcpM^Y;!VH1sdF82mkb8NKUNQ_|5zn125(SA^`BrHwQbyrhe( ztA&Xsf+WuN9c0ablw3L~a;?Cwd(`-@9ofP&emTqhTEEt>;ejwI+9!0cR0?y^)Qi~= zgTsxTR(p=3>ikURG1wix!A+P~=r|z!)@U&?*;0aD)7VyI@@;AcK_gf5H6K?AKSK;( zLU{4xH4p*A_V?hGM>gqduCtckE%ZBF8mRi?IC(=4|9#eF`C;lwSk2nH}peK&FaC5P_IWHJIN>=n|J49BrQAoEwUo(PEWh zFmvq7%wr+Dtha2Il&n1KM;W9jHsq2?B$7!al1U_zNxK)cmL@t?Ni-^{KTR?-&+z^a z*v)|gxQgz;bCREEXD;M1&0m`!9NZ=nTo4qaO2pNAmDDKQ%Il>l7g=_6%aSHJP+j5mB?NHRxIXa^)nkINZgB7 z#({`g2C~<8w5&>3+Uths90th4B|z~R;#s0v8g!y>^eFG8DrHzvH?`B8vtuxDuAKuu z-3nK=n!Na^@bngfl`tdyZLM;Cjqod3Gl>gGE@?EGG^gG@S}P2fskjor^b1LN z;;9OJfrS2!9q{2KFEh(VTuMQrnfR3!Rk7xhw$c&wr2|Bk5mAT|v-JQ(|7@UdHyZws z^EJl>)2N!?JP#hfZjSsW6_14}JsB*h%2RWsxl2`Y@56XQH=k&c2B?v1=04qNL^_EV4rn7F^DT~dOkRwe0mY~XI!lye>ikN)n#J=8olgI z;Yyetp;TuWYKL7+M5rz^4$;0-j)=Tlh> z=#8Zcewc-5uJN_pky&R$Kl6^)$%Xhrk%Gh>ki?pX>cWG+78!Wz#erHtI3B8=?PV&7 z{MMrqbkGzD4fm=h#D`67Yydsm<4I_zxo@)3n#W!Vv{(2SV{Ga zPj4NQV(G+Suyv+1umo-oWU{erx~*_WU@bW74ECB!CHqmdjU)ijtad3Vam0mflmqbg z6e|9cA|_Y1+hVPDp*>?vxUkTfizv6L|897We#6J-c6Q69EAw*?`}&}i2;1D&>s|)H z&P|xxtRJV4sM`qZ;6Or_Q#Ua8uG*}m22`9TxOaS(lbCY#-*{cGVva>fkT_}M<$Arv zX{=ycS`dy_|A0T%Z7bV}i@`p6ZuTT3*PbPOmS6RF3o%4F%Lr*u1!gFkQHhJ56+PC2 zVm5Sv*iNBd2%K2JAkw&c)9(je*5EQ25Z_9!o9ck>95-=e#`$c1-Q%Bf>`=6evmDFn z2WZOS+FfW}k(?=nALJCfw)FuQzS~`+d`mi4ku2)%8%i6|C(6w{gssSifUvMQF!nx% z0Q<}`pzKwo#Mp)A<2dbz_fj$yRHp4wETF>4kn^k0tGs{4R8`35?S+Vnt7PQGUS=RO{b-j@`!7D%qgcTC6kMa2v6-D75X# z2nVW%(5Fj30Q|B9#4>4li$ymeLH`^t=Rx^Yg|>g~_=fzG_C+PgB*p568I*y!Z^z3w z%uHrwkZ5So_QWwbTe#dz?aPVWWYYC<jjnD*U zJ$Byj(kgvVpu5l4t4W8hK3u(~kg!`8tUbS<86KSJIK@>>~fPhsK0&h>) zyXkyGztxAp+?K!u@V*s3+pw$UCuIp)(G69S4F;}?@5kZR+&N75x%sdG={6f6iPIdt3DOY(xMDHg7Z$RJ|poGtJ- zDjMSZwP&Di;gsu(HWNiIB*guWT)X$NwqmdKm{8qWlstfAt_r0W_G&n!e7VMIQRwVv zBy~|DZDHNA%&1J@!lI|_O0M#%fFUuOY@|lxG!G&*@!LgUbiC+tsbO?OcN}~dJ$a7J z6(JD#U$)}cJlrTJ_bqnyu#IHHil<~5Fu#8qEkuh7U%UfyN;5MM(@K9`ko-MNVQ3ho zfs?HU|47+yN29H{#U7^UC#(ED2UXUyST{(VH|)U%nzk3VlN9TzkVdW4MdY}kzTA|z zp;OmX4+-YR=Ii#><3xxI?|JXd^0$|Tk0k4l8Y`y)qi=xh53=1~M#VlTG?mPn{{ClG zU%ta}n_iu+ZQt6&8{G<*Myepi7t%d!OxjLAJIYb)Ukgc?fYHttS^GDWV8rwv9SplO zZ=C_)cY-B-)~DrDXH%Hz0VgW$T8{(Xzsn;)q%4j}Fo)3My<%JWExL=*u|0!C^KW;9 zhCn`F5;(siB?}ae`JQfceWNarL&OnUc~Wp)s2khn9vil@5jGi;y!kT%X@(r>lyt|i7iO$cAG8TQfMW6d0$*c z&{nWbsG-&tuU2URv#r7>_6d@SM?^CNMZM}CgsVn$@9{6RKykM>Ltf@@sMEQp_Bf6U zC@fyfn1v3ArCu^bF8OIje;O3Ix0J=*Yl>V!0h5$}tI z2|T1PZ6+9Hn+pm-am#fi%NJQ_)2}O`&~-n-{MPtI?BMTz{dRys%A2qFUzKC@4Zn0! z>JzoY`QwlNY}`fVTQM*Pq{Z@2`lZNxPH#U=Z5knA+)9@Z#5kOh9`GSacsSj3Mg=C_ zh3Bv)jBlc`=I7kuHL)qm8=2(G?gB-e`cZP>*97#`Vuvj=Yv`}M{GAEb_|ZX%6%UNY zpMsh>dMPOog?5_#HPKZgO0eEsFYSy>cIBbbLZ=3*D@=Lp50*BQ8Bo4b>LrSldzNwg zDsI5bCGS{Fk}krL4v-Z?k`e<&;}N3Va4M3&wB-8MJNOPB`$*!+t@TNyps8}qwv+R= z+i~+w@su#vi-Dsz$3(_8&XvW`uATLVMaqZ(WGhrVc3>|v`GVB`3{B_CYl1I7=!bvK zWA?R)!!E^694#=D4z_6w(&BP17vl-g92gqm0S8%GxYde2=jVgN29g_UoqImzLzSZt z&T&9n>4V@m2H6T2;;ah%^i5UmX)DK~pa34>22~+&cv2Gn&L3b7R|%X^3B2Yj-R^!6 z8#*a-?>e%D<8~jFwIwqW+k4HbtFx+ykp+J`Ri%y~O=l@zv$rE{vBoX?x?R%uG8tVn# zRKQ&jw7>-JIUrkEXeiq1S?pjY{bY7e;%_pK6Z6Tbt^#i)#s6De`XaT-3pE|6TM|W5 z0DZ+OueH7zG*Tm#IWhZ>6swppM{2-)Cl%><{6b3uU$Hcxp-$rMV;Fj6s`M&Bzr@~= z;@^;J?y$My6iLD{kD=(b?okT6y588IE=H9@=u{TyQqE2id5RrkJk3=p42l7>tzS`wF(2m>6O}76V5Hk)F~?WAI3)fV4oK^V zZ_z+K_O@!rKolxr(w&>xAdWr7#6omq2BqGtAjkkk8eO6wZTbK$A4zE;3uJm|zfUct zR9aoD&*(SC(0-2?)$?^s5d5*Wis-{SuAG-w*>SaK{#Ydg5{_0B-1l!Js`q-<+boyY zy!y!l&KMStlm+k0zv)>M$M*EKwxWNxM*;*WZJ2s40pXgMcvSYZ=AZPtI4T-yKgL!P z!epz@GIAb}{lI7}_}Kow_b3CVzypP`m=(?rqPa}NkS+N2a;mZ_50?U49FBSJ{>`D< zSnNovQ(dQv@6sN1qI?f(R#QTq_~rKD@z9Kqyoh5M zux8Des?w5BJl)~51!^S&mF!%RQ%YP+*I8P8(-jAdXx!&->sgeGXfl1dFk2r*TTztmgh8$OVsAzLWqzQ(SYQoV03H~DYmnQ^>cP@|2{y)=V7W+ zv;pWF;~T}ng=&ENgi&AyC})ez$W#6jc56%{a|yTMw~+rI-$ zh3b+R|5g-Os3m)Z_F*RMGCXuJL+Gs;1-sABz3BWqY>&gdkmb1tZ|Da1vJ<#Q=yLRL za7H|Gepg`<`mIDgD-?%i_n4_P%77=1cY=B77L}h9rP@i+8QmFrVQv@c@~XNw>N)No z1jV+b5H~s_MaII+#+XNuLQWEBAM6bJFj28tbqZ69MsPt$O~A^!V$Q6N0(W!8Zku?E zM-R8e&W!hNt^@CV_eU7@EY;-En2-o#>1~n=+Pbj0ZlecSj^~aVLtx~`vj1*@#fN$D zLnj8A8IO2=>XfH$y60|gmV@L@6bbeVj2m*6Q9Q*W!qykMpSTFaGT$>tTpX^Fwb%6y zU08V!J|pAW?!s1yjfWYGzzO(z)O_{E`n=QK+KkV3-!Ps$S@|LN>zUQmvP`baU{@O3 zc+MYzp+(x3a)k(TDP#C!Uy=@*hY^sCn%u@(RsIQxLQka-e)3m9RzzN5?{jBb(aIfv zWovxE{6yS-7Ci*>GYBzI4>XG{8nG*QU3@l48odMTaXU3`;o=AAmq8UqLzpKQ?ETgo zl}?=8`0nW|fLhB90f=y~Bxrs+Flzpdo-*AONL<1x(fW-D58O{wg7zU@)L2&kS6#QLM zl7Ibr9gP-(4d@y#mw-Z}_K~hT{RQAemghoqA~5QJ;l3axnr+I9-Sww$oUr0OT_O3a zDc+b-hV^AalC`ivKcuaB!1kVPJaIw?%|a0#Mj$*&b86$3JBi?Bf(YZGWx+87O8n(s zxm52OW;uDOzliT}E}sRqHzn7eyqnd9&+zzy3L(Q_5EaQY~edIL5J-ce>1a z_NUHpgCQ3%b3u&E%lJdF8>HzbQ~kkcoB$LLRT>G}IzU+!G7_+fZ&2NJMFQ-A<`n0m z-W4c_fC0)2w67`uexsS)?f~8wr)qFxV}oJ6y7x;IPC|Mj3Ywd)5eRDh6GU&|H&yPU zCb^49+3 zu|(7#or$<%_hvHp1!J=}WBB{O@# zyuIrPzovZ+aWLQSem8n{@M08(9aZp=w+(;F4Z5iF_%_Qx79m;AMo#9Q zvD{d0O)S`858XB=Cw3z{l$z&k#Hm4}2UHo7a91q!ov0`-&4ChmrMO`yh?CNW;mH0% zYZXSYVr$wy-ofNFkfiO;(`0VtFA}p*aks-3T^COBHSo`E;Yh`Q8+fnPDQpoj+S4Py^;oo*c+Umh>YT{e zR_T+$Qy=hkRMowi@zr<}zW-LQZx=|Ghuy5=>$`FwvH|+Z8 zX}LNef#BqFniHI8983+!q^)E@Pdj-xe0QKZ<^i54JtZ~^Wpd;%(St8H6$;MxbE5|^ z@5*pd#o&5f;&(YZHX>U3s#oqOJnR=2Gwm?`Xs^l1ZMK=nJ^fY4`~lQ&F~9 zd8{S{BNK5e=82NWhtqd@2N8Cw0fd2wq8iIPRJu&XJ451N_!v$&=YDiw*Qhx`fsUJc z8m4WeZ^ziABZv4jGYxtt%-DZQ;fV4tNA}VQM)f0ss!(j86YORUvl%fxvG+<4{nYk( zosvMw_Z{{G(56DjYSzaq20HLoy9&Gx12AU5cR%lr zc#2`u#~)o4-6bgmpLH7Pk{5DFK#ThUzD!tJRq=pQV$lPg-7!kGKsX@49~ji=34T1M z?{|IrGFErl8Acsv+1*qrT5uY_r!PQ^PjIvJ)DgEZgLdv~7X$h#qwSXElx;i*I==N- z4d-9rc%E8<;Ix6GNWxh7qvFKCeTP;}sK{}SGzfIzFL4NBGF}JK&4|9o=S|5s{kD_B z;JvQ0?7}|ta5u|xhR@7_4s6D}2+*p&?RhX~o|zW9RU z8|$7GLQ}l)*SQ7bdBxy=dX)4%F0@qtS6PPe(e3g0l$Kkw5=@g`#@G%w`7j@FAouUF zO6a!FxFyC={8Vor5N4qdTui}v4Y=d0NmG5R^QxTq2E~jy7vyOWn+4h0CM4VLI?Ozc zF-NmX&yKoU_sNqPQadvel-VvohRhsgXE2RZ-SKXZ%4#YpdgthgJZ%M zcyo9EfM$7&TatpCriL-B?^v0S{sHW?II1-f`)#sTNs_=Wh+T1bx22M3fF2_M#~CAB1tr$Ox!!uDq@ljKglL;BSV`|>bOp2G|83hE0;f&A7+x#@uQK4 z3bZ)AQCe4DArn!fD{cFS-;QRK?-7ybnTCJhd8{vOthMZNnx&rB>PK(PQ^kKrgnbCB zTa$6vs(T>hE#KjgMlCTljcr*HHwp!G0H_2e5cDUeJvBztw6?cav}4VN3Oer$LeUl*N^RJ46@{;4Z-LBDc_%7$;Dh-ORc)&pM!dwDTfFJ;wOU1%OsO5+*6nYz1!lVbpLkCu}3AEQVtSi zHB$+I*oD>(H^aL8BPKz#UtRVvH%zN1qzRF!9=jk*i_{irD+1-)=JSnHv5EEwZ_Fq( z^V7fnEt?u9(lR4w8$ZmgIjWhEH_aY;*V*q6?=oU%^X;%9tmQ2O09^ld4je?@@zz|{ z;TklQOm7)Kom8Gc-zTKR(~dU`f9Exn6KduozckFWk&PX8j|@h0f`FP-?$@?Y(sZ z59c&P^~fmR#j-eD$KiIz;a$hz(B}%fs9cG}+KMp$eJR0$|2~L#s@O{8J zb(tYESMVivk-b<*5NQODuw@5$JjckD^gjj<{R2G7oRz_O3fr%n=J~#Fo96ff9os$o zIhv62-C3LTPUJfEx>{hR!H1K1w`_{^Yuh2VXJhrCR?BFocDkm_sK z@)aN9kO^`;nhmouPF9>FHm99TSpJ)?-qXyYdKi@@{0(SF^Hkst#g>CgR&a`ub^X?zDm3(w_Qxu}ju z!^o%r007Xs@e(l!&l2LQdbdrNgb}*CqjR@ z%A|=_E7f0He1T(&S?w!4xk4MNkqZHtwA~r)IUkA!5GbebN*U^MEiB<-Qi~4+bIul7 z*vMn1(ojh~hpw_Hxn0X=u5A%&1nO)r;=KVbf#>k-i}-fw{5>GQhoe@14v{anukYdB z5Ag1*AH#Zohfdeq*Nyh|gkPq$w`Y4t%YKIh|5#AJCTkgSJbqhyIC!0=fK@-SlS@OB zG40E~02MfaCZOTX8DYI8`e8${j-ko7!aiOGp zN;-nlFYb@qXI%-f>~&?eqVQC*J|zCm*GDRV^-ZVAN{YnCGSL@7*hn=oWobK>Dx z)~tO#?)Eu81?^7t+mp0X1TqXfzPu%0gKaPALKypKk*JzO+-pm;1NU<_Gikkdt+#U1 zI{$hJv>k-Q?I$V=QO*_|OJ+p~!JSr(+HOLJ%SRj(Dv$DF@m{rBPcAg0ym9=km2nBa zKfr|1BSw1rsL*tQOv+?7s@Bsl0;WuzaXla0Oz)XHBpGA&$I3;{r|%aS4(Rbe#xNK& z^H-pmD&fy|-KCIHwe#}9&o{h^uo0bZZ1l9;U0G;N`<{5r-|NV4uYM7R{tEm@V<7DU zFqUxJf9DmKW42yPULV_<0|O>_AX+Z=hqXeMJq6exf2ZLMa(M396;;^Kz`qOdzYgkX zeNKDa3j$;7x9!IoYyRHb zsk~B0ZS5Jnfh=eX!Tq>}=s`ETfNXK_#F)lLyQ$Z?4U?CZCt%QZMu9l1Cgb^93+6Gt zCzvw|cM=53VWaTB3-G@RVd!H-7An9sD8xI*OvDP7&ihc)75@(IX1L}+?NKB)Ey9m5 zY@;%u&?r^m+7{k%5eK4si9VlS34KpI-8#1vQ{0V%6tJ@1KR~HTU)6SSmc(h_6g>Or z;%2gX;+ycbd={Z11#CoME~0vD*cSW)c}zrGbjNw6=^4i|CtVrk_RKCx-atwYX>6l3 zwt4NFMdxq!&15IMeB(A0{q9}}T5$DHEs(*4_>Z1POcqRfUK;WxC~dqis5Y6}T#%Qv z8!|7+S*`)*`AirQFkM(c43VX>2cTUh`8EE~ErJhDZNL*VDFQC>I)Js%s)rL$t-bI6 zeR?&7Ob7s55{m5J%W$F2UsDVPB!fM;U@}hxYMv&D5|e3Jd|^n~xrD#|QFbel46tlo z9Q?^_<%`bLRSaGL)r$NYjVh_2;nt+xL|0@^%h0V z;1zxlDoAzM9k^7C7L(WA#Tv_p^tJK+D7&sdB<3P7CqvOxJU++Zl!Sr0WqjnIPFT{X zBGBp6c|rIn3z_u94{f5p?Gb;O;n+3WmiPRbwz^Qx_G0HSjUj*N^mPU>9^nh5wxCjZ zzz>0P@QD@3QwaHOxK7+38s4pAwOD8UAHFm4je#8&%k{#mcAC^N3=79Fb_My=C=lT+ zz}9%@wQ1MbMYvRqd>_(&Fx&dc)ewtbt~-e7FBzZJte&=uSXR{;48!gZ1u=|0AHw5G z=A)8|du`ztTNo_#VGHbi=7m{cdN=k$2V6w=XY?lzCrFiM3xs9w$oK*4l2#AF%81Uu zp*@*_+qClIoRFoepphE9)>SZ%G0g~}YG4zH9oC7A@00=*O&kyN&0&AK`LYPkq_PsB z2H?p0@bOHVf;*f!mKfx(UcroI(jA^X*Pb_5i)rUdqE`Zvz4q2e>{?t{5~W>6@elcc7Ibca`%cWfG#}{D7aIOU>x^olCf%HKM7`OT0qsyleuj3W zMZj)oU&$Gi70cnrV?2X~8@Wa>B)#1=krTFrgaBvgBzz17Zy~O+HXS#rzWN!ti1Hq2*`bgP|u$DjC1G80tH4bcNYU|m`l3J z)7!^(GO~(RbS`6K4tkkZ^;?C20*TH?s9wTDpq7+-DNp&I$yzJrVf+kJBH!!e=?EpW zHl4>eO)t@~K36Xsv~F#-S_(HhDLlQ#(bBF0BI)P-LHw$xGd@&=CgH|rC4IsqhnL&_ z5)l-7$LfW;pv@#GAUU9_*}*FV5MN(~NRV~@hCXKzr8)kz_~$k9Oz^DP z^umU=5@DG))$-WnKS{?(1C9q?f6D4K=#2+P>!+3JU|Ps>GWWqmVSJv^1jdIy4bR9N z0z5xl`af9m3j$KoOF1A)ultAWTJcE-N}JUBdkrTjgo+r6c??}#E&ODUyYf(^hFR53 zqf|YuyEjk#LWSik81vykz+$w%$+yC-e^W^ICYd-Vk9fjG<#iW8&z!A!s({KhC-RH} z%r@e*)w02c5sO_Gp~Cm*Cp?Oj2q`N{CSQNb^Vc23mo9nJuyLHXN1YvT*GCFsM>KvZ zA{P}~N$4a<{9CQ=0JEs=IJ@D$F6qRn7=R(aB67&K4ge?t*|Ayrx27A^Cox(k8b)dW zc6!@dOm78@%XUgQ~-&Zyt!zdJ1Aw_IIzq}q*MuCo}W~-$oGI7Fr);X)$t{PhOY@Y*{i;&No1SoXin%({+{ zan=RNKL8PvEd;0dZ9s}4*Ds<)cOBC$WJ$k))Su)z7lW=A$@a1Wn)-!^iYoUZ$Y6l+ z9~`hITW8Guf)NR8CAku3V^EyrVvn>dXExR3{)3iNlP{3hux{yOYv5AT$8&?g=;-5% zkdf&`Bk?oOv0fTRvG%}O{AV$SP2!|~d4V{=7sB>U!m$%)M%&>nhl(MYo0lLQ$k&_w z?D;7H+AA(6HN8`lu9;IoKo6aeyr`Aia-Ef#X481E@#{0kEH5{}I(@Ad_u$m!_XcmM zh{mt-Sg3tfi&qYW5ihS-)feu1EkRx86x@B|F?ZSHV}CF@OO746vf$;vZMI2=)D4 zD6qU8@}@uRcw-N33UW(lDi)fPEIm%`$tXJ2MvP8t*MjJLZOYTuLZ_~j?)Uv11yH&(U!TK+6F=VpT8g^;)j1hVm8k2IHH*nm&XJgwChI!S8 z;XIb&(ixsfYj-9~dS`SI&Std%R_cClC=}ko=`) zg8)wxR_t+DPDVl*M8moDNM(g~QB`ma&WrCr^dX1N(ldMu%`nb8@K-8!@OAXu&+D6< z9>&4N?N$)Zw;Gw8d)%D-Cu*)`7kalk-)5aZqiqO}b77!4>DU6AuWpr0b3nA3EKm2^ z!XCAtPw}8*!Jtp&IFB1pkfuue1rOU%j@u)S_>a*9J;d-4cU*mXsh`8#&$>Ex>9u1Y zu}>vbY*5kOhK#41=r2O~_+dsamA|c)r3uAf6qO*>bXPh50svWa7;&n?I~KLVyID2k z?uAOg&0u4VOz>=LC~Oci#)>5k^4n>td{8FIpB$wN1CNtoMCZ;UDD%++XgjmfSFg47 z#Y5G@5*QwMCMKmi_k%`S_ZUo7l%4baFJ1dkhO(L zSb-yhh~!UWu>zVSlKcEXv8KGr9@SCT%SmyeBB(HX3y38Q9l#!R^|%Uby5zq$VIsjCRS9t#TgXO$03tixL1DU`-LFtpv**FOocz@w(A zyWa?Lm1le%@7F^QVgS(gvbE;?FS4W)TI6sPk`HRzv1ImttO_2yml985|0iaUunydg zgUFTNAA(21m*80mK=9BADh;C4E5;7^)G_UieE^ ze$qUK$Hp)bjim`i-9CYNGeJ>8z~-XsD#{Ctf+y z0(BN)IX-mxd0PwK3bs3|D7=%?$}MFeXH)aAASO_)05FhT1lRF##=xuYSD_+1sZfxQ z6N*|LYQuJ)M1LvJvsg<{Zc19JdP*n}mQ=La_73j8z@oz6qhdqfaC-@W$OwrJlH1I! z@qHCZ2^$ra?Zn&F|86z-diu^$5D= zHsag~Kr3>{9LD*6k?(V`Wq0aGT7Uom0000000bpdj?Y5-!&l>Qf5KbE*gk8DxkvaF zuBZ+`q>`nwZE)Ue2uHD6bf<3vavQgE;{QP%{fdgU5CBq`!xJ(|#jbv?k^^0XQIdiR z^@goRMFD##5PMYe2L8vmK-aHjU#GDu9>n6a_HlwhWJ+$^_eI%0h+DkZRcmcd{pG7o zg@UDkLH`7|i>?O)rWI9cs)aKeKX*ISsH7(-dk#a0)*T7ir;?oujV(6PbV}RJVq&8T zO&pD(SCRjH!L$JczDL%t@u`?#z?W0;)x`OeNIZbxPn`U&*Ji{cdG8bqctR5=K5>1K zT*oaovOVRF@B=qP1@#`^B+V8lqeJ8>E2&zg^?ym5f#o}v>=AE?NJxSf58}kp9TqqP zu0L^#)%Ln!O0Fm5*>ts)!ZL2DNG~6oB=<^hzy>+C+Z)+M*yivCh$Y@HLN2H5t=?&Q zf01+WV1bs_GKSW*XyehudX&n(d$B}jyEq0fM!V>7rNTW&|F)Tw;%?q^_WByN>ittKYU@MJ_rgDZL@cy+_sWK2x z9k>K1HzZri|2esO)b3N6FWI;ru08H*+e2+tNE z0JMe!Buw#>78twTbOO&G>14K>-;F)?L1mFbQP<$0o+fx(na?qJ1+$$*j1JZa2_q?r z{O6pE42iPC6)4hGfVyN9JF#1<9n@EnwgEBr-zv4TXt(OXRR2aTyxDIhsSTv#awye~VhN${6!nhoQ6;{&p&7{pleUmZV@!t+xWR6KwV5Mt60$cSk( zL^AuO=APNYMy{Yyz;kru_3z&ig(WB%rYlwdUEw>Fb`iotx<@d*40qUO)sQga4=B)w zqNIl(Tzu3^3J{BT7GvcNo_5J!%ri%qZUKWSD&eF$3=kWnfZu|2-FazsMhnKH zR?q)j>uIuBie3wKjh$z=LowWH=vmYoUzyvN0In|D*NSCh3t=8O|4EoV8go_@0GMC3 z2|b~k@Du<5!a?j?WxjnQg-8IwE5&oYn}CH8)Hm8IX`}3f5FsBVd|e=Lnt{bLqN(4_ z9`nyF&&7MP0qm0@q{aa5lYD7=@(1#t*La@_ox@V)^Y#j%+RjAHt2uy>m|a5wgD1w4 zmz3pU5=kVINgJV8!b&d*=}TU2=3<8^;a{NTD9F@AYS`&l=_p^A3yAsu5IrD#Qca(4 z@0R&wCWF8kMT!ebQGLHNFqY)lsDQQCrn4g)9t)cDj`1fCvE;5k6z-!$3xDEr<#H+! zdFgC(2f5&2^$WIqnEL2y9KpT6*|gaLFUKrdf^-0?!c>w;B$7r+DZrw6$Gy3k*@SX& z8>-dTbG( z>81}45E7>iN~zxn#laF+(rM=*LV_~eAf;!P6J<|+XV?iuPJxAJK?=f|xulR5OUT=8w%cs~LG6*GE6LmIS%t>=7OZ{UpP|}A zuXX=K0+x&cT?<=g0>1k+5)!}QDx^9mxJX6`(%*685HGeCC|effiQCk29e!{6)(rNUs@oR)`8W>J|k-@B@$%N}I1(Sp@+ zOj^5tF%xsGq7MgY%f*BMt1fT&1q^MitBQ&Q7lY;p)SW{N6F2+VxDMh^ZL|%}eq4@~ zYA&BUG06@In28Pf@&ooBe{+w5*Ab3@GI)NU-3}s94f8k0z~Eb760tLf);;`<*6RxK zgpOi(Gq=dT$8Jf1-X!GpHg&8e*-p^t43x>72V93dMeP^VtSNLdY1(!QB|OrlYwSms zT$F=j7SYNx{~}^>8kgoStNa3Fp+{wknvkp!(7@UC-#T@92QkNQ%;$^r$Ml?*k$W?< zTu^SS;-X)ecoZ7WCqudMMN2U6FPvu8Nxv&7B)n4AD`@bv`aoCVG&KBZC4ktl!9WzsX$ZRZPBs!SXr!|*(^WEO!0%3ok}PAC4BBbmDa z>Wo@_jFFT}E`q~O&sqBrf2Iq|kN^O}LSBd281Q*#FeXFHwJjT7ZBW-SW`dQ1IZlz> z`n)vDnKLl3n~pkvd{s*@&nZ3Uy_p=OEi>ahPS z<)|4e@l_1_6IEkX;Cv(hM_Oj@2=kU$Q%K}6cMy^iNhDY^=AtWJ__>s3|SU zqd6}yoPd#pgs5dki?9e!{}vL?tRidJ{tHrtt6@^Gsrz)Fk>uw6!X^oC1nzDDO+oO|L+So>rW{ z4=!b?YJc-lg}(c52ue*m5>%2&7FbeC_%NY^DtJ#%hP*7J_K;m+|5f$UJYApRn%(rE z4tRke_cZFEI5YvosJ2`5@i|FZ6?m_8glwJMd_fx9zSxN{nZ<^axqRfhCI|zY3%GEP zpCl~irClSYQg*o%wNF2MqjH%?ATl8OkC>qKBD8Cqz}w zHVLTdP?iSIx;R8tp~1XwiFf2q9!l(J*HTb@{vqnT72GX_81c{DqC^_07L5VAIYC9o z?>x470#{iis|X>jMev``5{Fg|3Et&Ixr-p}SF zw7bc*l4asxS@-^8!_-d1{&n@y_@)>o5+tQ&+rNwWJHf7z+|4#SK|!Eh;@=$vVNlaK zK)Wh(M(8)v40inOEomaWqEP^fpM=;2wYz~{*i;u@-MhV?=5pxoINsE8cR@QKGchh< z#Z-2VM@4W@E!_s#bWp>9BiyiiV1iP3P*}obsq4)IrETUK>jG$gM!g)JaNR!?C?et3ofw}){Dv~sUNutKBlYA8x zYY-}LK~`PKCo2xW@UfyywX44p35COgtjkl|ad;(4tC?}S25|mNc^`CAVFwvt^#jd(fFv=e@gs8OrF7o5!t}XShwBkLmq^Bo-O9xlpFMd{3XM(0lkGpuAqJE?U*`)eMLNNvMWM@-UVZk6u{r~ooEPr z6naV^{>X-dA>2NC#P(pwR1(USHvU4u-NAq>d#8?iw1~N1q;}hgS@`wXIP1pbkA0b2 z#ez3q?3t#1l}COzLYcHE6<}&Kj>VxOY=vngfli}%G-9!pKn#2 zf$#BJPg%~X1f<#FJ~5V*DRRV5x@?Y!mj;F?{-CMzpsEp9qQrVsN6rO!IjIBkkX7ii z^JVIj5F8bt=BK?-i2|c8{Q8!IT9pUf54I}nc2N>W$oKoYSO~S1*Rbyz5Y%JF?w&n zV;i70T0$puU>-BUX0CtTDyh;T+?UO=_u33t^)wf3w$GC8*KlLj7{iDn9>=Em1*6l} z!EX$MOjSudOORJT8)`N`d`RSow*#U0t0?s*k_cT!K`uh3jgWy5D0{Bk7DW`j6{?TR zT*1tkLg3tY{7KFv*4VodNve#bQx6}%`iOF0FY6S+06kK=ldNzqjF?s9f0=PZahd(d z_!=i%i0*??3%HCY$~*agEfS)@q2~A+$s0^C-2rqP%>iu?pbuu90WwW?DR;v?R*4tEnru%1z`d z!?UU!-ANRq@x%E)?Ul~rpVY=3dXU2(U7iSVDc1!(k{W-sN_>7dUfq|qXiZ4I1A!y|TA0(=opGTSi&#o23nqC{`~m zuzfM3redV6wl{f?%2`9d-JuD`UK;R$#$M1Zl%{NJQ5n1~A^qm*g~qIn?<*460B9dh zQOYPgphT!wAJ4dFBe(RsUEirGw+Zv5@?#Xq%#%C)487x!aD8$r`#v%O*sAKJQ}j;L zK@S^%ANt8|Eg4-|{Li{Q_Ii}F7N8P+9*H{FX;c$ggceSRzJb+7oryt8JVZdx`_%w0 z!-c4nvW%ulJ_x9_g)H9A@pcY?rG>}P86eS&C<4X&mGYol3!ve7>Fg)ZhjWrlU*!%M z)8s-uhUUT|wj;cl5O8w-x!ckhBhDi9G*&GVE`O~Z0)-zb6xzp21ix7Ox&Ii%XckQA zP>fE0HMDUB&n-mcc9K>u)$607_0UV|M|liryhM8fu2eJK|@R~4B8 z?2cXyNX`T%h488L&-?ZqyqbgXA0d$l;=$S!q(gSs5eV@wTUUhSxnD3^T%+U(u?yxd zfjAH#U4ja>?AC>{l$hAB2?=Q5)*v+sVD(01&0j)DG^7v$ffsIh&GA<#u}d(Ww;;=) zF><6q9Mqxa_Hj673vC}P6*9Xz03+V~275;OT1$eiYZ3Oj1H_J&PiV{X+@RL$$;A;0 zDT;P;pxyP5^zaWzMj3HcRld4FtYhMW~-2WR*egPi*?0(X;#Rmi&++BfWj{oo^CAl++ey3y?GY% zn{MTvVK;o_dJqa)Lmiktn88w<)6)&H`lQQ~sGvetF&)=X#Eyn3bwR0}ZwRafVlJ2| z0OY-kO|egS%yoaAC`(};S#G0sDOI+RR9E8W?G9Eq!?^|5rv_gD%u8JW+Gy^$Ht*&& zfvoL4)g4*!bK6@%GFf5(BOTaVK?A7ox321k3jawn;>qZ;*$F~7()`KsX#&n8O;D$h zBhuM$wfMXBqqw6zi;CioJItoKikQ`kLVogCrFYSj_x7>TD!9+Zd&OYF%CAAG=wqbC zw=-Cpa_+4;*iW*yO>ow?H@)CI46(wR2(2P`NIH4u54Cp{HX!8Es02=~HS4RWWo$a# z?@BEkup@_R#~fu~EGVqa+y6IPizF|+hlP|-DNER4ujIS1e;=3Q_U)hT&|llvH|^@< z6X)vH^<2~E^#l8QUBmY5KkdH1Z&bI{)0px?I=so51ldeA29acN^JHL5XjU`_rbn<} zFV}?e0=l@hxoA~yhNY4yjxTE;P3arNvPmxuk6TjH-(gbgYho!L5RO9dkCE8pO_luRnq%5w?(}ve97@`n&dod1C-3S|el3?FM2e*jnkbAQsXi@8b&n7O!($@$f!j zBI%xk{YRe8`ZNbrFhXPILOHb*6OT?*5LMp8h?2A-Yp<&l_wL2i+Z3Bw*!fn|LS~B} z(|%F|k0EBR1P;)Uo)Y=jO(Fp4!*hos&o1A}c0Ws#ES@=YXlqzeeWvwmE#ZQs6cnLO zDhTtD#hp@`YpDwZb_2RVt*!`1#!daOd6MI>K@R|Y zIF-(@1xl>nDy(H&Jf9Va-M+dsab6%x5UDD%0JQ%wC?H}z+}gYA_-Bw(djnP^@7M+k z7wIXtB(5TVgDL(W+wxvjOxXi# zx7<>03tXhiS%*)5F_$aw#ipxKmh!cmUkkT-&yeSUwL>YVucWgqG>6qNVt7#OMcrd@ zQKJKQEn%*8iCNccXqcbFEP00FJ5|oeN)~d?mg$S6Nr}rN+gU>%X{897mT&B4m+b3kFpCIMX|%6mlTWiQL?tWg8H(L?;ktr@KW|R@tkO+x0q#vaZ>!v zxDD|$A1d$zENTx7hW~b}!jOdZ*T}X?tShRI$jT$*yY#ItfUvhsHeQv9D*nhF`n6`b z$3|9;6%U8IawVoy!nj?!E*-;0vTgJa)goIlq|PU%1wn6+)WAL}1r>!P(uHA!-7>g2 z2}7&jVv=gCaa5-~>&CeIg=%NbSkaT(*lD83I!IeTvyMxgSmE<1p*LpwNTD{3 zkv1K&PlTq6!Gy3KuaiwgQ-FQwCPj}I3wuSM^)JC*koH7i^{_^%I-BRv*)zAj1`sO% zfAv|0wGCSD?cL;a)!LN8W8jC>u|ZZlrPs<;Jd#zT{4)*3?U3^W)<*>Wl{6r7h1TE_ zauWJZ+JtojFKFyMc!qK#Q!Qw|O{A~uWIm0Ug(8rH z#o0S03EG)_OezyPy$UNomvY2uVQ{{V1=x`IT7Z&_PKjTmX6JC9>{q+JO!d5uS-n>4 z#~eSOFp>DKuVe$MMN4cI`>%>?=DtW(lS?2crlt7#co_2h#z}s37t-Xf(5r-l+D3z}b6fvf>4U~SLs+l0V(sj?**ndDak@49gmbpK4CtS0`4x0;2E z(PqP4M~&TDF4MF!l@(f(ol)==XlAwb0A_&|G>2>_G^H_OKK{bIUHqi)|{7LLB>&uZ-sb9#H z2sFHI7_?kBeDqi5b=W7i%DdedLP%%7s=K+@$}g)bk+w-)uzkKDE0^uwV(P zcHJv43%M*G;YZ>Ltd)><~@h31kW`k#J>GQLk9$ouO)eCBNBAQC%*XqEA#iyium8 zfa|@$jz)BY2i&GJIx8(2NX)b*(ZZ2PWb7twp8t5mW<70+$m5DKLre+6z$L6IGc9Q4 z>WyjqV@hVMInW}vv^(-atxbg0DK0==_12|%bdaG0nhTUyU1@c8OdL+gL3hu}Y1uC?+RICRY48O-YwZ4Iz^dTaSd2^CFbs8Z6LQTOuGAj!9 zCa`cAa(Gy!CvPTAZNYeFO|P)leH)d1vLuXW4cai-rWcLSlI;Q!xKzFaW2u*gL+udA zq81m;c=E0&>&cZ6RzS(u?sQMUJuIE^kfqvRObs?^>j>ZT2$jIc8p(mJ>@|t9eQ0QmQ9X zGKedh@A+25`)Lo+5>mA<@68bL(AEcnh;`$^B3;6s3OP+#iw@lS-xpbwCCh~f7-zC= zzP$V!Kf{e;dksSLQ?V2rly8}oUsFWYYSOF$pZ$Q!=_3JT^=BAN&gjsNt5UwRwnRn) zZnWG~W?j|4BefLBe_91YekQeRTo{YM^X|0X+*UFZ$kV-W^rDQRX%SHciMNvNG#KaN zjTPd@9B9RUXmnq4a`5s=xjL=bSZgPg;$hB(%Q@_&DO`}P06*b3&fl~Roz8K>Vlh3DMP>Ns@rlH`+)aFXW?i!{=a|rx0Nwa86 zN>_rA)1{#dSM)Gn2R(a$(|9Ie3iP_w-Y#tPh>%DCS9b(MenM=dZ3ANlZF#AJNXv4d z;<|5Wwyx6DAY}IqYuktd%HNf8QZb&1m1P2$Qqq}+YvlaERm(bl27vp(!LY~-n$820 zKlrQuBYBRRjX9Y=&jYrqkPNoD3R2=p!|sbq2b>zyxz;wbTbIsuC_DOE)`!JJ*b?>y zQNNU~nNq0OqsdszPEix_cN7p^E@$y0*BAoa9T=`bE!ex!>D<)RmCm6d~*bNUO@|i7n_kah`>|W?F&)!lvmiwxW-f%Sxj)TaizjD`%a5MF8OGt8MC6{tJs`)sK>M!BK?i-a1Ea=dRt`KZex` zp8pNO6Iwb2i6x@i7tU-QEfls&*^Fb*Td~`kkK%@dsXJ^+M@|J#6FlJW;O7J%*Sd^Zg*SL?3ht5YSX?%99`0@k%O~;!JcVmke2mc{Svb z5mdZfPqrQvf-p0L9$HEmo;omjOgf1T88kXVb(R6d4)s}!*H#s z9T6&=?5&t5)AE8Rr=%JF8wRR-W`bt|;G#$$VwfzHUgE6!qlKKlLhyxYgAP913mONj zG=R{mKLBKJMYJ<5{C!axaFeQK3%iGY%-=OAQyq{h0}6t(LXT468cKxv;cp!%WLa;%gH`Ouk9FH4hojI*2ItEo z*)VdWUQlM*oNe$Y<=lM8+@TjOsU%p|~5$Ec+^Oy|5RMYHeX%XjGi6QSVQ)WERlO# zL;oEUIeU_z?e$;5xwGrc;8@D5sT4; zT@K{=SV|B+TZ_Xit3~mnygP@cQ6V&$-oQ>k;pQaI;YD#AZk9%C73+>wGHS)^}PKl~51NnyI~h z%|%0XC;_ZBvfGA@WQ$rst}2M*h$~$GeV9dXcKeWAAjdsE6{5|f%j5q`T787uB&uqH z1udiV&eE<3P4o6Ed=oGi=e{2;z_^RMQKd9xc8u}C;$s2tNds$Jds!@WLnTqGWFf6a z2dS-#G21RtcaQ9p;$!7vighp9q*<<(8HcD~?1=7_23vtK`D zR<=YS_Jh*mE2ylm=Wdc0t~GiOq*mdCIOm4^J;m;UdehHrQP@>=-Fv0z%=8SO1xqI5 zE(Qx72dbI8<)B}okFjEJ%l+Oc+5&R@JJMeiMKt(JQ*C-CT!?5CtI;J>!KisjQ$|yp zuLV4SwPz0eN_&NZwn>8R3ua~luTgIce3T%cVA7|WqXt>`6gPVsH&PuiXw+Z87O451UzCb!vvSxH!et7xVVG4~*g~ph9u2Airv#G9NGx>QfZuOau^lw?$??j=7i||7Z}hq%z<(bk{l-L$dl+0 zvuIx-jkH{EJoJHHQ=12id=#!;s(LB5$@(MSQq%R%0`5b zh`Xh`4g(H?v~`)>8O|cf;$^=%DO7DE1Mx=XRlzn42m@KCIlFzvmpI&; z{HuJbU&-TxO$2iWn`<20hKT2+RAjrOIqa`iQoXb2B_*UPd`gw1>P zi9%8%V`yFLlx1XCFQ92h2N9J3)d54`qeQu`Pd+6+5uB-tPt0xW=4#!JZX4F#M7FH( zEaO&c+{%PMk7rGm{11|b%g^o2Mlf!G(0jlIn{?9c6~cJCJr2?`zl(^A(zc2dTS~{~ z6=70IYF~}>8^Na|?%oTcYGNlVUW$SuFa3tn7=HnsR77nj=D$6%;a2HU|b!W)_>Jo;pBa%KjoHA(;m{k~HU72Ci!lg=QnUz%i?_}cKe zWW_@k0T&rlCqCI$>_7ev`_Cpmae-T?E(PUmFY2jLalKY&Plny5g!5>narzf3$QnG)8bhe6U&6)0)E0N#K&k|W8F$aP+yX>ANVhKM)lCt=pVTJo*qjw zn;<^$N`HTcUF+>-pVAXehJHteVsOc# zL19(8LVnK9;k4vgqAM)c5C+_$2OhXt#jTbixT*c2lH>97%bS8a3J3s$aR}16rmp54 zA=#_9TCwca?ogUvpDd&FMXnN~}RKz0(iWQ0WQ!CoBlXa#^TxI1XA_M7(J zMWlP>p9Gkt#JTed6Q*`Fg``m6NiN0=`8Ee`x3*{Zq-qEBkPbI8iOB`dQqP{~PBu~j zDIMUCj~QZVKuhY1j;t-SGejE2o%F})7k1#9+G}IHx;dqee7K37v0=7;cJ}aZaqEI2 zYInZ8-c`;{86>^=RpIn9)>pQm;b_srO!X_yE|Cwc>K@v#<12)(H1m4~*E?LTpNFeG)QX#N=mVw(2 z-D~MWpDil#V;$}QB)i03ecYJj^*SntT3VN+%<1B#Y4ur%f_kop%VdJQFlm}dpl z>~w=h+H$Xk=leE@T0h)9GDu#lt)De$Sv-uXbt4=$&U$(yIr0st`nLk5WR{g~oXm>n z@aW(8X)o~f2mT%6W%ljl`m|5@cLV%8LdWpmFX5wK!?~~F+BoxD#BPFhLOUJt9KMty zv!&rP_GAS`yZIIOJbNIqh7z)&VRg}ML)^f_ejBopvcQDP^y<`3-Y2?*?#HHJU4mYm zTPP(-eYdBk|5{2)=7wn&3;nuyITZ81vxjTz_o?BRr8UuuOlY1j8m+SK3({-f{qf?9 zo0dpPucPP7fnpvO|6QVY4YtKH1tx9bfwC+%Sc+_db>gCL#7oZOn)aNQ7-IGYSMIp+ zOOQD9d{w{}mhixn^DN3aWyL1>{haY+QCsdI<%av^m`k8BTtj@Q@&`nJKnJ&XM-bDf zPPF>Q+2$naMjcZ4M)eE5pq@%Vh>4>`JtfZis)<0&)0%ZdDslT5H1v2=pekGYmGhZvSfo3}lap=OgABF#5Rj4TY z(J^!G^htpj#aH$tPIjoYq+m;{iem;$U{c7L0TvpIWnO|`n!bYMM1dX_r$YZ!z7Do~ zus5|{0*~Z>_D3?@cf}JoG`J~mzG%K;j>F5M*~;p}_0j1*-P2>#3OttS&Z|@rr$8F> zkhw8#PL49!N+ENOmZD)Oq0?c_n1{K+w#m|zwa>(+Vtkhj;U%`-Z9Tva49Z_ijDjX&8X2E*l<_#EhA-Yw3IPG)H&ubUy{L6z zO))n!IYI~Umjy#o7L1Dsh(#>Y*p?8adDx^auhJ4ZPmn8{Y?&KpS)0Y<;)r~MD+G)O z-Ik~*Zhs*mQy(uitRDEgEZL_;5mrqh1{6|nuK#x`9fn-3sq8ZRGWGJ)M8nqiT%b{b zVUFpobu{d35=r1@##zR)9vF?Yym||cKY}M}L&rJh_=^Xo%34QR`({9rl`j^~MkC}G zhh43(x25y`mAdz<137w==5X=`M|U2{!il`KK1~pnxygAbr&)1@FW?q$d|?lrvE8Kc z*FjO;c9s7SBHFtfzpZ5|64|pr{?9SOX<6**nKTsiXXTuxFFbqOUB9+RXV|WT*tq(@v=` zjzrw^Ms+s&>;VvUzpd|IYDN+t7LO9myVBlc&y>Yp@*8F_?>?F@GT~>`zfa5<@y9H( zbUI|3z1OFWN+oH#epjO6TuPYp@K-~y;^(thdHRYtXSy1H?}m*Z0)dOFu3d@nuxW0A zN0%&)k6(hu!d=1`o5|T30jBr&7a#z335|RKrpeaoqTHu^AoVrhtgm`br|9upOx1Zs zrOOR{K-2UR zsDq<60QfI%m-(|?lMOMGjA(pTc^lCo;u*&grU5pE?nFv>_Vr=|Nd&?C;vP$3`~QAo z`Mr1+<4(l#M69&qlF1I8zHpdj4t;Hc6l{QXNl%X1W86c9-Wby3^Sk1sLmkbcR3s!{^& z%3af}@;fEslz_04?rm>j;&949Maf-yn(6n%PZEV?blHnl!KR2t zOt10zV?tu9e+X)+ooj!Afj3{rDJuE%xjE8oURB+WNhE?Et8xumm=5+G0ZR4@6y*$_ z8b&&Fu)*(@WZjLflTnWn?cMc2`3-NpQ;q1RKTZfn*~TXE3r|+&J+2slLTX|q3IYTF zTh=B#1DW0?W&cRt2{*Mb-j%v({oct<7NKQW%OZ+iJyArlx?sKel8J;q=wUyk4kNMD zf_0&U0}2hZvi`C4cAvR(ZOOE^+Ezzc*$FTnOydb0dA+ifynXVh#fD%2VL}9GAF&$X ziq`Ne`JC^R&)+A{Y6_m_F_k^8um@u2UO_gT{Cbd_rln42nc|sVnH|p9_{wrw(vw&i zaJKMTMXIzEJzM2hn+5$@ZL{>>#G-Vie91G#!DE1C#xn9##@BvQ2M9(t)_b+|D$(43 zq~E@yeGGL_b5M4gFp~XQin;2k2&gBdBGo9&Glf9~0!pLyvwHP9M}mEQkx3)D6F`Q+ zZPlh$>IXEM^{dgY%k4k8?ETZ#e3>S+{RM22|19w*;`}A37B{4L1oun8$^SIta*7b9CNc2ZL zQ*=Nock*E%ul5vTf<8mJ|A1U|F+xFNOf6ndW*dK> zHcjA9UvYcw%l075zoLYpJ?=v* z{PLiv%e$E>j4mT=`q%d@sGFuG+b{|0tHiV1Z}sLNH{si-;c2OOJ2OEBb`PTzTO_k% zya8z@dF=2t;rFb~yvR0AjK3s#UBb%Pxu1q=@;{bZXQ+D~7p^e{i1nnYO>Z z#=gj4hBxpS7+`k?O{#-IyhUAw;x7r3zI8=(z#4rSo?gVRU$?dWPSdE&Rb`h;I0=Odmqa;Iz{<8;Xs2BM@W5^1?x zE3jROs*9g<^nd`P9}ewWXk`pqZVN%kG^ZgKVLm7Dl@#0`aGRM{4~JCN$QMZvb)hts zw<6L4sb(4zktM(4334h+xCsK;9~&TEBKX%VU~s)=EiIYsD?NPwbIzRXS`$sWAP~8O zux=Hasv>7+!`!Xe(AWy23fiwat~v=>W_F*;fDLrQc!qeYa59pPKPf{02H#Y;+?RGl z@{WJ$VU0s&lUq>GJbI~+eL&m3$^fQ6u7+$8M$alCA5-8Gh_QBkwLnn_y7n>89rxdb zkO$YpwvHekQr50aKV|Ogn8zRzGg*MA%#-NeV`dNjFhgw(IJ3TG!tS-#2v0s|O^U8? z2MjWV0f#ng*7t}R0sftx6r15FS}@XauZBtr9^I~w+ZK}5>!L4=>;B*At_n?4$27vW zb~NJ$h1~;R+ybsvQkoYeM`e=VId7_I?^6*g7XAcRY(8Ru&w9#qB3_X!)h0BpY8Y>F z$ki%aPCteo1AjUz7@8bTj3mkf#j?&mz*AjXH>_#tMn#I%8fCfYDK#G^2+UMz<+L^* z2z6tjVXpHTipb^LZuD9xpni)0w~KI9^#s+yvlF!47dGzH}Dw5pMb`)8sw^{~|N!SrR+(tk>#y9JY|+kbW8Ca7A? zJ!Dz$yhIjx0kFRI4ST&D1En;1A{c3IX-#^xWWVxU8l7P`E-u0kc{0phkqLfWiS}-nAR7VNc&x&hNfA?>5a- zuo)|rZFR`^7|QPjX=MpU1nkxGX+XAj%E@d6*pRs^IniPO(nT|Chn z3=k08xBH_xEN$zSAm!`IXC@og<_0Xj(jGF8S3O8Ivb5g$_S=kWqIT-Go5>F6x>H5|5ZAQ8**l6C-3_y@*@vUWZ+Vos`L#9eoAi5ZhNPAb@j}e<0G>R?1WBm*K}KF zw_s+d2V^~8@WmgffBnueEN-Er%DPJUFS5g*O{ekX!8W(za!t%ecY{eL&dpKNJLV@U zGmUagk9#0O=H+UD$%Rx*oHRwIHTSMHIw8je&3MuWdDQpVq+!a@`EXdZVdcv9&AQ2a zRVDH~TR6H=dGR@b%|qd2zN_I5O~Iazu||7i%`G-Vv|0)YH_azHQx_eCf8Hw?7IFcs z#Ivwv$}w!%-H$D2U`xUrmnF~b-lXSv2Es{pB67G3V&$9)-tg0#&l|1hwm<&@Us1|s zdI0tFdsLgy+@=X!r-*4n)$mJHin#&G)E+}!_Rk%~$W{L}`SNTJg ze0z@1He43@?Fju$Ap!2cKg#C5@Nl(__Eh1CDlTorN3B=ZsH0zWB9K+(@#v;=LobUR zY0O=CeGB8WW#Jw|W>0ro;C@f?piwKkEMFivH}ef0wi-tjq2`_c6CckKJ&!LQ;I&&e zV2|A^9H)YKHf2qV22uA=-LwV@Ij8te^2FBA0$cmPQo;)CVlz)$rmm(<-lVK}gGJeP zSdI*I{k(i<(Yda^f3ci{-uk{wec*k}FVk@kyHtB)Z(n;HKq3JIPg#y{&dQQwAZj3n zRGEcQ6)l_Ufj!a!Z!OEud8uqfK-5; zx}sP=P!O8CHq&*vvp>2;CN(kXg3821fOCqPAfgKjd7Y)uzVu!bp-x8(7lJay$sNqt zMmwn>Ub;v&bfAqziKK%6R@Jg7M3`u4w2bl^ewYC_l5M!Qxjb8TJU;{fE(*CF-47av zd@a~2i~}UjVcBLjn#C2ZjErCpQ|{PMWbv7hQ7XrG`x9@^Hngxc%z&Hfcm3LnHq%5@;bOSxWP|;?0oWR;_)Ng;6^da1oG;DQNE5VN^TAw z1RM#i&j`be;{xKL9MM~5C(2x>-{aQj;JUT% z2@d3(PpUQXd$XXc<8=0f#9mRkQe30w=qp|jj%dL>N~$4*t--DWJPOaKTEQm0B2TMz z>gx?~t9@}1v}_+A%#0vPG>k5f)a?CyZjGq`;WKzhwdjG3vusytwW8Yi@Z}z@+|h54 zw5XYhkZG|BsF;r6V{~cl)3@76PH}0GpS@ATY4fzXuD$sK^h=8wv(naqYuM9R|0(G= zW*AnafGMOO+^6G>zUQ*~@7HEcVN^SGPr;UM4B)*_%fraJ1D#h9Ih!vadS3EBL5L27=v~_NZ^nB z?3=f{f-&pj>gGMi|}?}3sun@D}A~hWAa<(&)Ayt#vM^oD1K66 z;B&_2J|3!uf4zs%ZT^+%4XO#g>lQ038eG)7p$)Y%Sd;}&;F&V{t#3iMHTJYE^-6V3 z2$ zF4ZP*9ETRGfJMsAB*FE26GfBK*_0(ND~mD=uyRxOV~Ly%Lk{n($&)LLEE&*nxUgM~o^VvIV z@OqGPEzQN%BEKwv!Rp13UO)l-q^dUwMln~obLLYpUN`)u%7hAX)Fxt2Bl{A1z>q#s zKrHbvC2hV;4xFSzQgF?JkpveE44f}P!S45h57(R%Jozav+gZ;aAyQ{nkT%4;^qE!v zaj(Jhbj^Tpe+U%$W1gLq2QG(w{GMy@ZuN0sO5g^C5vJ6W$zqlehG}S)+hFEModWPu`TbO!Ow{tl@ z9pmt+yngt#Vn5_^vZ!OF6^iLB547n*=<>x(2OBcY>En2==oLlf%oD~4q%Xw_i>fpIr6Hf%eg9|> zH=+6?Kzps#aJoafc>gp1e|#QCc)x*f^aLlEHopu0FP3?<@vtL`pEM%{;g#E5rK&~# zka^Yl_~p}XDYd&!ITWN~vR)E#$V=v&n+?6$f6iQr1GEJ==L^$Efsm}#--_!v1u$y0ef1=?3AU)&i zFAC5(EHJ_fLIH5-qa8)hI9sEB5Cbd#U4=g+nKD#A00!4h{2qeuSPFL`!DbV4m^XHW z&o%Bou_=ho+Gv@Q<52t&sl?-(z)# zG)WB(_6DnTJ6x0TdT0@r2!-|tf3JjYz(c%ln8+L7Dj?+A6r`>O8`As;1kI1owev)2 zsj=XPDwD+rqxYi#%MFL+FWsJ+rNb}Mj=Rw)z~c1w1E_U2l`s=GbA;7gePfU&P0;N# zwr$(CZQHhO+qP}n+Oc=EWA51I-S@lral5M`Govf3qdWRXMfRz4{$?#2apkzT_r#{o z%H{HtR2)>sV;hcIwtPQ>pjRtaP6&u8KIOk9S+I$PU`!wl;X~QY-B%h38lTCoO!9@w z*WS=o)4W40)=f`6%TBEz-fF25KrDBD?(k6HEEB>8xKYAbN4CFQ*GT&bO`%%SA0r=D z5tx=9r`&_T2|l%bkYFAk>xjFYptk-EjG239GspH4jvyHM6 zLQE%p!Bb>1`yYLVd%Zd|k}ZIEV}lBic9P=31|V-GR7s!}IMKcpk*+nRyFJQt6#OV0 z3XG@GD0Y4@IyoAIyPL~jUBykvzgjP#+azM)Lw)kGvrS3QB>WMo% z@0Pp!hc-|QiAlG~8l=6z@($1sUPY)X9FkY@OJ)Q^8|;8-IPhY`>nB!Gb)Dq8|3nJhII4 zxSax24Afh0E`78H%twI_G(#S4NH<;7p5MkfTu657|B9Q>1=(X7_?@g6V@#!HNfBIH z&&V9Tn;`aYr#gf43c_OD-VO;8grH2OxPk^*YZdjfEj0*<{SC2!_wT<9I_s1l zb~`8AA)RiG6D@1Q@6JyqCHoS5`=>(7mq7AN1P9QYrNVChzmEy6i}d=-#`-ra9TYw9 zw|ZmEPfk-nC*`xJJkfG<3q^_`e2(Jv=`6X~6)1junr!Lw(MgYU6_i_QzycwxLS#IR z1icQWP`JDnZ}<-=s%$g0XSPue*2qkW_6QAx&N~FCWK!}xhY^aA4lu=w9^vfwuXc2M z;kL=gG(Q;8DMun`?P-!|uOPJk5JK^^B4$_&c>GhZerXj^bA;gU-iX|kWk<@z?_HNM zq?Lhn4?}kI#XxctZvYh>;G--}sY#D1Elzo5Z*0Dao?qalA9k27xQ(w`Li{~OMK=z= zD2}9&eA%$Sn}n9SSGYoE+eD=HVIrY4C*3HDeD7dUNE+0F7&iGx_`J!7cbsU%BeN-m z0do63Vgo!Yqj%AV?&pvEC^!aNwZ;Gz{kXa0$m6F9#sb9A$;^WPr(UpMkD2%7my7!B zSdcDs!YNAgZWhbw{-pWemK1tcl^hkzKf3J5R=J9k)@Nm*3VdIKMq)L`aTk(z%I2PR z5ahMhZ7iAGBXslV^Ne_NrRvjMh@+ZhwRZVntdT0|)Qa=pc(JLB>L(aDKTm3Q? zf7jvaXBAPrK5LiV@8N<;$sovM2s}z-t@T()#Ri5LZtgks#S?E^~$ReAZEiX@a>Tf&u?Zc$=ty~D$mb8^qU9W2M1wrGvq%2uC5 zus(iJDz?D?X*~2*1Cn2H-aoT~DA?ME5)#|JEKCI1_Z98D193czzE&Vca;nlxl$I+QkLy&4lFRwri%cDjx?(x_wYsW71Jp}CI? zlpXJ3_-aiTUTN-!6Dxbs)B$IAO7q9hQ-1=IRZpB?SG00sgsN6h;ynZk_+0Q`lUN7N%*XSKC4ffc7zj=gzER~jM)?tR4K4K$vRFo5bJlp5h<`vn?H>GUf%fX^=0YGi=nFehwu9IZ1^xGmwcf@NpM zskVYM-$CE#ii22kz~P~Sq@mB$zh~Y8^Kb=G>!pH&srTfNLZhI%Wl;CSH{~^dh`=5^ z5@@En2|HXt_I1_)fsVr2Dx`T%JDK7e0H8>*f{la1mQABTr{0r;pdOyJ6a(j~W~ETY zv<8Ny*>jm!I9U;#4xUUXNOBLMi!O@gi7zOjbj8+ee0Dj*Z15TGyy@t}Iod)6NLA?9 zuUCr6TFX0M2_q-$UaeD19{8x4E!N;;Y#5W)JAmb}@I7IpBP?Mpm3$+i6#OEx2!dyq z5Ou0w;Y!Slz28pWFPvMz%gcu#itCoOhdJJ1dk7`{iqCENb{KvI&j}8Ghl*Cg_d&Av zDU2~*dXOS46QszHsQhM1J(N5G-!NiQ(ikrOCBb%U*1OT}yM65td%_ZVXMpplIXpM+ zwMJ4Y^#{Dkv)$7sLk$gV`z7Eqf53RZzdR3MI?s?d_3}L#QZf?1!e$YVnSs2qX)*Vm z6ktsWS&E4uUe&U@YFyZEi&_@2v07*Ke5|&^T&ceEI2#g$f)*bY<_=nE!*sB?kw06$mo&#k(N{Ll9ORv! zXZnmqPmb=*278$+Hnw6EGiNPKKXGHV?2L^q&aM{8T<2~SkuS$k0y#yGPXKkPciGQm z=x}Od7PCFWHBsXtKuZdN?GrT)?t#}g%pLo{1$p4J>@}4D*NVjybA(s~vo6fNI;aPz zojIBGAAIj`QSu-xl&%(?Gh!)e#K72;K0)yyJlcs|_A08zpPq^0%8u9u*c}0Z5F`k% z&OXK7Uau0YWFl+^W_^h1RbBg#vAlBwTPhP9S#Y!*yvP2qclDPf{2562qxWH1@W<^# zzOjIF{?88q7tJ}cL+Qd#0NFK8$QCrBO`!PIV)zdQv=OG>YFmFPQD|sb;&Emy`j zaUOjT0ER_C;79Q82{T*Hy_;bjpgtjij=5501fx=@_2JXm_u1~|;#B!tf^e__0KQ=F zt#!Og^lTu=nCM_Bb+T`roqtM9dJG8kl;mBF!DQ2*f9N?+|51PX+w=B8=4w!kIBna~ z{U62saSe~dKGJ^AX`9Izq>(p7Mtny9qXY9%Xk>(6EM?pCB}h>a-uwg8CvYIwNVB-R zj}d^GNhV^b2s8*FqNe(t>wV4Vf!~v$S4AmCIt2Y8rl1_JqZMVZ*V6IXU}_3sK)}?q z@74G!2q0#B0{~!22^%$t${ptYK)7hz7;o)ZWCsTU08C7tfKT!i3gIk{runyS?2?RI z3GQem$p4{5gXVah8n}z%o<=Zkzxdz0{QpDF|3W?*rN*>&aU_XLD-1&q)LPSASb}M5 zp~i#{;0F2~5MEMMjcc8=_^4a^ri4s2- z3dkeF@m}3ErnSuef0EM?u%5C?wy_o8Xj}0jrPpw-p=mh7K%t2F;?alvx2b~G5eoSr zEypw7;Mj=3V1eNfbSZRPXu6vDfe%KFB1RnWQ#Kzsr&%;)xF}+rTF8X}095_+-i(G+ z+)9@_&NQhi$?uG>*u6Pc3|z;Ls=vh2w)Qr2Rb&%G@1L=QJdtyhO1e}=+eLOC3a zmd~evs=FS@eOR7Fkud|1M_JoKfDvJIHV72N>-~@j08^4m_lhPE)F@V=GC@}hLL`8- zRWA1V=7-$wASEvx?o8Kc7(7UWMnvk*2a~Yi^gI}A%rL4sK^$+Gk7R_Hk|3%!!STn1 zW=vO17M1z74+Pj)ST{inzYkKfAv1rSj|xVI&h&I~>e1FUTfWnoefpVw+Lw!+LAlem zXzi$TCT9J?t4mtw*pO0$p z>g8zd$V~Xp2mBwa@XuQQ3(>7CO`QP%;D7GF4hjJQ^xq%^69-%8|M38b|3YFDQ!{e_ z=zmuLKmd?`{XhF(#(#Mr|N4K^n*1pIC;^!Ni~i4a|GEEj{C_bh1Q5{wYd^{W*nfk7 zfWSaO0YE>x02D$+O-;l9+cXswHGfP2NB|%iBO4=AH#&DVdS-g2pG3faj|POC>Cr;=2g+Oik2|yeQQjzolibI4CL(D+M`K>WuO*lrKw~YsjhsD` z?dh1+dpRuSimKX$0d-jQMY?VfmD4spagIt7V+Xz@uIDXfRJ6v0&Ntm}BTZ_C6^qj! zJysL9*BE8Ul7o?)$g%NM0srGY1RgxAeYCli6;6+F#x-@r5mX{#B+Eg0D_!LdFlqi& z(vu`-8<|1=w9)i0$gQ0Rn7VFn~!#*U- zq@ht<7{w9Lj5Pk#G=Oo42!`DK_T-a4f|AU#q=VRlanI8cVna3`p6%_#?fpmBM5w3F zC*TO}Arkdq(0vtV4n-}B&LO-Rj{Uo-*b;K3@tQ!$BstBac>zE{UwN6UjGNDi*VVeF z)vH33>GQ*VNQS%GuNYr2;z|rFjO#@8a;wBRK>pNT>*IVe`-f}D?m#nyq5x#a4PcSZ z^FCD+ww++jz5F)t**|8c(7Jjf(dKOPQIcZLaE$r>5l|V!9J}(N_c%=^(J`dlz-zj! zN##7)poGckTdOB^+w62>O%`bAs~W={y4Y$(m*n_$F^(ki9c-Wy6k^;RmY!8P_QT~G z_^D_9SV@NN$WF#Gugv?#NKfya`$f81;~)i)QBC;46&hQ2DNE8GRpa{(3Ugx#a~&9K z}@3QvP&O<5`y~ zk2NIPnVCS(?(Qe`E$x>Kr_DuLXF+tMJ!Y+bg|u$`{_^{TjH5Yqwlj-wFhwuqw8~p} z>$>jRhs@M;H7mphKVGsvNK37Yt!v*UZ+fHIwXofw-etRAsfN;U+0D2iqH*IKRq?Kz z`$c?-5RIipD*b|}7B}N+pMlJar06;Mme;wXhb+%&1|> z+WJxON1=*f1?t*K3Jye8lsn)MjW37@y6>{R46s^tSW&7l{6vowCAtiZDMMk96;deN zyT((-E+d1r!wcsk1M@&PC?dkmke(>^TB{V!NQAU3vLOfrObyN#iZR+5;4-pY3DkAz z%a(LzG|Ih`JVF&hgYcgXLqVBnCT5xy-?Y!63 zGKS>j)%*7h!lt@^W@2+xWa!ItUCmF zN}5@_P%usTJi{kFY?n5*q^sq?yp(+?m?>^`i^)R3&hM&6L zU?lsa`R#C(nL|MlN!JV6BlYW^P3>}J6zo}nRkAyD3f--fj#4O34P2o!IDTXuS)+Z- z{JK!D3{x``R594JA;inGj|j17KEmiLJ7dvjSO;}xVKq@S+j|OT;O(l=8$K#m*IFoucPA+r))G5NUhm zEhEzNv%>=5nf~yC!K_*1xLs2U%y_cX%`vyYj!e$4&Qg_4m>Q?`^TH1VSV&JbyKIIn9_I)=&kFWq1tNDFTEouGFnJx z5b9`(+{AboAErkm(i;DYb|woeY3jab3%g}AFG`9q-L&4u(7FUT?g8IXSv(Cuj4cGGU@~Dr$Sbpm}yY*y92}K~?`!5NY_t zt1lI=ZnE_arn@dEoK(YyMpUz7_yu{4?`F{jJ`SN0LcHc^=lP97V29FU!;cnYb=-GM zx&Yqe<(cRqUny4F#doWc10d{pP?02}G8!}}2{x{*D3NZEZPCWk*PVE0fwk^Vld4*x z7F9PWgREP@Q!j(CK6qY@oX+K#xEBoIJz*z+8M}qX_wopWjs$=caY`@dIvqg?kY3Sb z|Iyi|oetsiEmQxy$%q<7`Vb_n#0c9|WUf%GE5~;Q2}5hDnDH)xMuRxF10=y!zmrUBO_B!P*E+LMo);BDK`PX`sT`ohU}$;E=}rn;a}IUG#JG^}eQL z*9Ynpem0m{V$O(ldvWZ=J$?+hp~d*o-Ymrw`urhy^3>hc%3^kstPIn)u-T6S#`N4T zX_{;P8ZVO@`efCR1j4IQsL_SGbHBdWqA15RPf*G0S;nBHeJvf4eqM|O+3O)cYOC@e zpn;YPzT!7DVia;Qp|RgDCFVzN2i#381y1!YTF#xvPk1gWBAPKLVA`=+3$>l!q6o55 zX4ff{-NAt|8!hI%t5l7)Hv!PU`e|)|=)oXf7N{`i3ggUy+3w(PlH3uK0yDG5oia2o zi8`I@H)Oh*)0#*1*GE9IA=QAKy=aEjSMj5PzZ4~4Z8dhtX!rXBO=$ZEEd$9Wc{&>r zDoQAQ_fS77E@4Oxd}n@fSM!7D0f_Y440VOKBZmD`g_7GA5Uah9FWGD|P1)F^s3B4`LA;kQX!DpL*06gI7cCj{A)uHa<3SNT z6TlPFo;F=@wV~7_+wC<(s@ZU$i0M3HNGhx8qso1&D7!Uyq^?Es66S`0B{?|9nZm=( zBq*c=H zKVTSJk6U8#SFV~FN;bXGrKrEO2w4Ju*~QoV+mV z5#mU%b^0-=)bA_Q>G0b{T*au1v{{sI!_E_y5>$QZH0yXE7rte*rKz~;Z?SMO`;}Q10{oU$o z&P+1UC!ElAk*P5z)^unm4oG%KM~HUYcP7<0BK+Ovc(bCJ_kzx=(}h$v zAakCI_ST_QMWGk>@HFXpg`ZnvDg@CncryrnQiv8Fo<$VM`23B|m|$%ArGfBbBD?j{ zPK=R_oMKwv^hIl#C7Ta~K7`qC`%837Y3ypsM}b-z+OzwEU#Vx=PfccBUW9qp+Cuf@cDZ(G{R!m7`bV#J%aTumplny|Cht@B+(?oNPrG_gP1**AqkNh= zLdlZHW+ZE(&tXK+G9C1TPBbDbPMD#L3nlBCi&#>)0K?HC{)?&2K7a=N6Cs~c^)kg* zwKZ~JJ~{$HuA<#6f&n!L{qCVK7hnVKYCEJp;~;XY&%XP&nsu4Cm!+E7EK3A^OMLLh zyO)-c-zQD%9R*jdR{~I=9O02dyfVvDS?1&5HgS~)Io?7pcv|(3Q};}slh_Xvlhwhu2&DqPhbt%mJN;E5x@{68 zK6d1)ckjK{lYg_b_aFb(6LwEr zz3{*==Ru;jg?D}8bZu$lzhdkP2lXK_C7GVW6a;XhKC@gq=qgyP^!8!*AurSpYh~X0^zoIQ z&UJS;{rvR7@7i=ELf@l+B}2Sn2oztmcZNVGTrUo$aF}*sxhS1Cy1;2XHvuT9go##> z9~q($N4uK%$LBnCk->2izI6a1Ey+!Mr5q}*kk$|3hvnLx$-Q=i zfsb(pk3zWd*x4+E55PbCy^gkV1_Ba$gFzJ~uQ@h8{uJ39_?vL~xr&$sz#7TlB#eqj(9o@OyCqN7!=w z%!fQM&FL$=vw%O#%s#2e)13T+y9dY+ziOvr_zW@leY$^ObPj4%n8|Ztu5bp0;$nr; zAijnHs8A$I5ZFZ_zNQ))TISQ#C7cb>M;?4lLMC=u@uV~Z?BkeTqPde&;S=I?1o~jusHLmWbK*4c$XJ zG0Cu7+^rI4Tb5Wid=KgG^l3X%en@ZAmqHur2^1M~G2aN=ZAHVbX?-RdaP$kRaDHC3 z4=vd_7WCk%a-BaEcVrFBO&btk~ZDC+pn@l9>ZBdtGvEXC5 zO=jhB(+f<{4a9WQ-M?B)EH;*8Y`3GE?@NJpnG?b`|Izj0;k0v#QDz(vMpadfv}(J4 z6^t>liBzTOqD@qk_`>vV^5p8Wp%(JU42KtI!8zAaXW5_S+?XS@tPph_$KZ{8+RTFvbSh z&5iL;Ely%o$t@^0^zFg{Q;=^q8Jj8RkncJZnd@zJvegvdMJ(oECzna%nr(HBbIuMh z$Kv-f0+*XYP;?tZWKB7bdwadQ4{@|#L*LLx(cG|v%U096m4(P~cXZtgM7kpK zQIPf4*ea2>9a(qtt?f)+P0Z>eN=9org!#FpnG+QJ;QAWkx6i4+sQ22ABVqFAz~-Y_ zrP;QzY{=inC^Li3)HVwE>Lin+NZMuyB7H?CB1t}#L;;gKgl1-4_O;ShZs&qc^y!zN zF9r(Ma0N>ZbEDf|fMLjjA>79&b$NF($fM$Y&4jNn|70p(?cT3It=6lNJXn1?u+WdA z!M1s)40VUo`=JVQYII?%KXsnN?fc) zud5AAyO=HHR(g4)W&&M!BiZCy2AXm6z4U(XVXrH)ks5&hAQyD998EcD597li`zVhH zm5LUi+rL%*Gta1jSbMY~ax(Uq z_8?HrA=@l7)1d*p)fq06Nb?{&H_wN)0`+J#orn3heXC5u6pBK1j1tRD(Z1$s-IvAz zI3=hTq-J|AArg7;m}r;1YN0XHN2hCyPo?VHk;|ta`V(_Ep$A^e&xaNfro?LNs`wz= zo##1C&FJ4thh&EFf*_abPIbJ)Tne^A3Kz3blpaZkFeI-%CeTmcs4hj#@eP`$I7zWJ z%>aa9e#C+3;XXvcmZ;FKI+3@~$WdXHXd!1n0;=~mbWCaB-RbK>BwrNZ4>o1AgJLOzd_^)A zGwPRS*4ri?s8{bBtdAGzsb|N=_nrtsLzwQI+ zJekIVsQlWYUi3`Wtin@b@M67)p*flya0Z{t!w+9sTV;T7lW_EODReHZ_D5Zs;YKxp zEEQgNRey*to9OtWHQvoTL~y?jF77s3+I4!%|28eWwJXibQ>;4$Gol=-dF~xhOBzyz zaCOkOViyjJ;Fu5SPYvuA-C`+KcXH`4GEaPDh}c?LD>TLjhyU(5gd(p70D3(PTOCf7 zpwZxb2WTBYC)%`PR-wVr$my~gaO*l4cB49tDh;cTs3l#(e?%-@)LF})^}flLLg(lI z+zTLRTYi2q3LadeqUWaKQwN#i28zuVA|2r?%UV3y^4rb-2p&?>nG>`;OykJ5C5fWCs%Bf0D8eS)$|1*#4-9KvBKkL(w_cRLt(k28fg3`6GWYOpf!?WF1-?t10dnKp?neWo6k2c4}IQC?rB_bl(^K4$!oJhm!L#WgT? zOD*n966U7Z>fpk6?(aN>RpvzZkCIVOFIU4jOhHIf?-LV)g7KlU5M+g}*2fIjPJa9V ztFpa=!#l`#>zvHl#CeoS0RCin*1{eeCiGcRf*`^krkUOv6r@svJPw%$pou!{Lr@(Jw0U5WQFL3BJK>td-|lzNNSwm zn$VFJk1db?R|`S));#P6jGuFjlpY$t{Wc#Hs7X_T(F|eUqtSHfs3vL=)!UW&sPt#e z`yP!ViK^b&6OgI;yTiFsWns@#M6i3q`q^N)2%O<1e;8wREu4Cugw*n5D#84oZy@c^ z5!%}qH9N&k;=n)u`wNu|Rt`&GbaNQAVZ_>k{?G!@Ih3OT->@ zUFNH=_kF>V{nPnW#70d6Syy`Q!Ki&{UdQ9W4H%{Zy6hjMQC@@4f^03s;}}n~A>{~& z4UJ&wl7>j%9M}Q&PC027Jg!@@(93qz&}dSmvtm_`n9|{Hc(mmL+2c+JOQ3Bqm(@<0 zL#iSTS|!^{P5ifoD?(-=R4c4UU6K|aSV7^Z2*6AfR3xtP0?j1`D-l2OoLE-+bRd4b z{=2<7Ocetl*7*0>Df(a>Lmy2Ln?z4Vm19EcRK5&y5R@bg6X2pGu5BQNw}l+Mx_aC^ zbawHBFRWLta(CT#1$IvyUjmaT*!nf# z1+>y@FffKajef>@ru+|SH%)gj_a|3%JO>7BdqPG2M0;DBwuqPS0-nFGCjelCOB)#6 zpXXN%+W{5Tchd)l!S#!&qrg_YbhgGJclBPbSA2sxm1{9TQy`wNe7&5X7LC+i2ZAJ1 zws`o+AHN$46^m8)nhA!u^Aqmc_z^fO$$VHpf{ID|mUmfPtJ##Sj$r#PquI%Z9YgxM zVRKE$va#L}TBO}3`(`ZV7x6VE%69qTTsPK^W8?;@#@WYTyvve2!nu3+GZaZ(?n;9s zcvW-sleni}a5NL(CBH8a8emR4ynIk5d8WF4?Rn7|`oa&_e+pLc(PnJwy)__{xc!7b z9r``Ou3n1mira~Nn7&f2%Qnv+PFWU>S)`^0r7E-Zj~o~se9aRaSU+_N6~aDRn{wA% zzBMHrXYDBK*LP(CXuGz5fJ(fj(j!mIeN?q1F9i_SF(#`qoW9`|fnyL>71>daLZh zg&R%z$WbL(#NXbrb+#)6Fqa%U_1r7fXgf-KR&6o^LB)%bba0wh{%;Hb0F_$;Rl(;q z;;k~4imRrsTuW$hnPFny{^AjL5$o#R5PS4Co7C7rV!&_YUZJ|YGaWq;Z5oDQy&u`s!xQJP-5)=8Q|13K0qhIARC3u$ zWbArP3Z2a?$r*k$%-?QQ&(2X+-Qo59%o-s~_=$K|#F+adXezpj{J)T9c4}1revmwFOK)g69H~=evCk&26w+4f#os8meH=}tr%76rT#c=4?lMhdirf->KkrX6WOWMer{_JB_0Tf(_j{V|haqX?< z(1UrdpNZ#S!j54jOcY4f zoQa5U3S++B!~7k*O+0Q0G_3ReyN?c4xO5gB@SGWD3x7If&+g$uu*m%VG`&R5Q{jtS zM6!cU3dz;Ho0u(3aEe%!m^>6uMTXSaPV|`7w#f^7Y)!DG^hph>X}!c<9=c^J{ok!6 zVE>YlcWT*y?XUo~pji!$OBZVEzAqQTAa><)uH|f*xN#?wmSK}IJ^N}_P2=yUQ-}72 zeAjVa4LC0ie65v5?UaXI^15GW@q9 zQ2gs6hH3$5q2?go2v?P!;hwqK%AVU>khwI<-L)2A?EvTX2i@0ZxhQvbIAyH>%8zmk zzDQk=G&}ii1vvgJ$jL4+KVzAC4$^FV60n;Y|^es+|WRr|7KUhLL47}E9(C6 zqdjlje(UK_|D^DD#M{sc!U=1yX=0~X>r1YkS;JVXJUbF_ z7&B?b9xAhum*vKJzyGKpyXCx#HC^D#LF9QqGwQacxU<}|{km-!6spTN9U3-2UmFtL z9Nbo=f|}rN5mWm@Ic`ra-p?G!<_8wo*WEr|2Cy zgrP5PrXg{UNR#*?v?4(MCDT-F7=!*p1N~_`avJAXJ(`wNrja{@iWoN0X_g`H)OyF2 z^Oh;$hU<*Z+i9~5Y4<`Q?KZjOnUf=odlaK$pPMpGJ#LmawQf4$7VRf1%L;4{gPMnq z#Rhcw#OEz;r91f8USEI>;#_c>>2*P<{~5&_d&3h#0772Bhc8VF_a9Ht#!fTVOR#mC z7qTa;=6GcWvD@hTvN7m45&7eoEWSxjZ?f5`N{TOf=VP$^pn-&_d&3zX+Q=vD_7nD= z)a#t63a0z?-I;A8??h`X5jw1>wvCsFoKn7UaU*I`RI0~<&tpH)$3oNErD0qT?&xH{ z%c6)C9EWrN+PYJngWSLA13gP@BQ!CNg9_!HEi4S~_4+zH!donhnNEWU#WBB@m|M`IzdV_)H!hdDf zu*k9rvM)z;EhryR1=TC$(ZX_sO#8-fuSwt_(8{onwKtRCzuY<~DH^(yW?cKFx3x3c zY66-xTMAmv<)5CywXIolb}qx6^R^NtKJw_(c)09dtFAwv8ePwS{b@{!9)Wsl5dQjY z8Fez9oG1$VRRe{Tkd#!o1{CVukK*KAl;&U~j&(4r4>meQi}%LjwCZMPSK_Tz3(jwEAMQdm7=IB=ga)L&1m4JERx*FRlx zy}(Xg`JqZ(pZj?K7$^;hI}c;SR$vJVgGEOEarN4uN&jV7u@U_M)U-qreli-xAoAx2 zm|Pk)u&6Tn)^Ub&@67MK5-Z^^1`-US)`!?sGx6Sd_JtY`MO;-BRLX27>kk&i_74+; zmMqX@1QAno!V{@w7%EtRcDA?T_OzDDIlzoR0mF{NyOpWok2G{QT@+7$+XWOX! zNJib8oA-~MRekv8N#A{S3d8nLX1VL@Wx>2cD zJk+y}hKGhoVwiMskP<&*leiz3se8QG=(m1tY9UXbpGaC#uj8G6^4PTn`-TSGPuKtc zo*<(JAvC|IUvIy49_cg8LNWyE`owS4=-rLbhHb(Upv?RAwAv!WhGI~Duwq-F)1gmSl4~sy@?3#Ua!B{oYm|8abJ!j_Zxbcg zfa>C^QvJb()}HZWsW>iMoFs_~Ps<*wU)QdVLRJNfNr75AH%dK0^rhnn9d6Gd;xUAN z#O7c_wf*gilaFg3>kZN#G&P)JB!eTfgwl@nx0luBbS(%)`nAxZA6VP7))pKo^BWNE z%VqWB+E98!-L84b5UONK1{&@)D(LQ?8kcN*<)yon#p7Pb(%!XX7geia1N6jn7M7~@ zDS9KhK*=7oB-Qho8)sppqyia&7w=Fhpw;W2=WNQOuepkM`KZoxGCem9{!~Dj050(Cf4Mw*u`2w*-yuv=Gal->;cG zD?=z2(nt5l@`VfkO~l{Jx%xtz54UDLBhQtLBIdFjkYPq8QZQmAj`s$~z4iLZ|HNjI zvzBY?*B(t8u?e%Cxxt6^Md0LKet89*(6k?>d9^a&nIdsiCDm$}-cn2$HoAe(oFvsJ zUSb!N9V`CRZNp=EmUGYAaWRc?24ZW_{LY9t&4p#{;xy=7bt;3MsX8kZ@t{BdmSS;^ zy3Do@{tg(OCe?T2&hf;~WwJ%?_Fo9>__e~l>I6e|B$p=xO&JNi#A*B|vv;S|xnpJO zmR+fP?CS>@Y_4%b3Wg;5@i%MHIVzNBwEWEPH>DU}xR&L{kLJ&OS|rb7ZcXn^L?u4v z-eO8hjZY7f61tt8GH*pTiO?&`im(;76NA+JI~G&DYrQsZQu~bl=b1g_YB;jt3`n%` zxzy|=q@muR%1(kc77U2Z>v)+*_&U?q!P}Y?tZ%~*G__`J-Sc2iXsw3ZchJ?=*vAp) zFx=(s>=sLwj~sFG^m8mki_2q1b_b?Dl_o{b!g&?qtnCajEzAvoi*;@z!WLX5)LPN| za0w_PWj(g-DAbms`&e-4G#!{qdDm4fh9qe`C>QPzL)+j+B3Emi?{8UxTI}Ci8Y?IS zaihQNLsLmAM?q4OE}i2aN|W=MIw3~6PI^3O3oHeBfmzl{r%r93vO%5%j`wA6cdxma zl!xUGij8SiV)Cj;>*fj}mUWVm8CRaUw^CDFV)(Whf#5gpI42)DndU#sI%Wuuaojo9 z9=5Jc<*fAoRH-TH4FptBX@D;3|BYHHA!2$QeG{lOo@1UOkqGD)WRfWCm+UMRp(}i$ zlNgG^REZ=mbs}j&9ls#{R>tiWzS4lA_@z%2iu|ucJ?&i3R?NVtl^8BRPG_X#t-Jk% z^s-7TtB<$IcJj$I!Ho9605KxN%U|ZPiQ?g?o0&nrwBn{gvbb)?s-+D(mVVIo_hW=j zpUY|g93O-iS$2Rxk3h~;H9)Fy7_dEqQB-+w3##4C{0d%5!0U;R5=Nz_IGgom_~Gav z_HLcLq8Nto4y}~^@FTAu?+6BSqoo(0l)Y%8%Jq9g3$>PY{3Vlr&Ieg-<}`&Wjmb0r zkhVRdIV~bn(@@P>joq&H)DbH2#r`*^yJpHQlTrDvj>ILwE7fZ~A7cSaeXFX$_)kz$ zLn^Qg-w?yr984^ys$M3J38V{1JV}VffRq|+y7rgB%)`k^i|(F*n=RrEvNC+`0GKE# zJ+iOerkt|TKo%@^`8wbfoWvgp$W<@CT_`(Bs7pyKRgp`N`JgIv@Z{^M%+I4ibxFrf zE2m}FK(7j6TXRG1_H^nNOPv1Bri)gN0~spNp#|Q*g@&FHywvywg>xC>vBvdIO?(^q zBN`TiWR?4hKW^4MTHo*DBSIS(5LG_hnH)y;MfS=Du)ZeNx(cUIY2OwC@f0{k_fUXB z6K}wx)1!ubjQ*3Pao+LK>@S@Nfs%J=&^#&U#hqY=xosD$s;Sswwc7S~c@0p@WS03i zGtBNsNOxoGN1=-e0>K}aXa=CvtVRu=^=+X)`T}SX_c0TMu=J+rMT6K%d5MPTgOSSkRyMmBluu$nc-_1&r zWX7=M`kB^8`hgX(TctnhfyXDl2pk-rT-R!3^;`=2)_75p8b6M)U0hf^Q;aRCnedSv zgA82}7MIGL8Qr0@+Mn9SuVGN*+~PDQ_h7rHM>r>6xu1|_$h)6J&M5i_Nklz(A>6}_ zxYV}F82z7FclBhe*G?^Un05>Psk#ZVz$Efg*H&Vho&sMWMp4Ic$hAoXi$Qv>#F?l! z_R>UCl+wEH_b;*U|KK_Hg_P{8@4yE!C-QFL?T!*E=n)_rS3sbvg!^{k>nwGe%yk`+ zO-qo4l8~}UhmwKki}$+g$s=uggedA({UG55yHjU64j-l;GV#>62CJ{6Zn^}GN4~t5 zWvc*@f#T(q*uEVZipB12HBxicA}x}?29;_r<_eVdvzx*yST_8*J4*ajsX`;cyj)U! zjz^$!7HRneb8}bQuvE=&fpCk!3d-XI*vu|cYwg%{Q09m&5VI}H?#8al5xXk@cH9zMCEU# zIrOSZzSI_Q3`7wDM(sU8MA6j0F$$aZ=qps%$k2Un=JCJ|W$~9kyf$3iOv_nmaS`7J}D|syU>7 z^+jnMf2?xEU^3+JgDnu9a9=EsL=Nux*aED(t}{4;Ef%~^kHE+T$^$)_(S+J`K{WrV zS436PaAZX6+#w>$!=CVoeH({RSG42SgEp@9G}G4iKd2pfJ$HRDAj)8^sE7t2PLj|Q zB^y?9fCcjj{LofgV`nP?9rIu+C~RM(IJv7gNr=rzLxbd}iOxpjO_8h70GF45I%&dJ zK^N^bx#ZYalga-t06sv$zt7$5_o_^O0zsH5(O}DT!)^SkGcY^*>$6n;23p5@Q==y2?5}Q>?DN|^Y|bSKV4YS)PK>X8G8MtH>*-~yXUYJns0R_ zZ@@kYtBs-+3Z&D#?9i67F6!%!#8P)fv*H?FoCU2dSj)dz5$`f29J6YUlXJQ`j}05= zC%`Gq^s2u7JJ>GVi#kkMzp}y*_HPkICEZ5J2gnauO72P??HbvX=e&INeK?xS2#e+H zd>dGOR^jk<@ggKE7a3u2;Svk)3Cc9OdNSxfmM%6JNiwQ6W63nwA#A$oh6_L@awUBD zwN}mIV?%%BzPRWw7~)WkB)5hzG887k#|-4kz$v)~OiM=8QcNmQlH{L}I@D)tv1+U6 zD}z3^NujRNKS(;io{!mwC}S6x+?d{uOGU?5!Yl#_c8oiY2q?Fhu6wQ zO@NZD14GYIx_g5aK6f6LLSbJ7NgNEklH15fwwN}OmO%|FdHC7$e%{v(*?!RIPnuB1 zBeX=>81;+YtzL{hQpqRG{p#q8_u-D4P=s4gisXJeOm|AL)SdFi#kBBF zvvFVf(<&gJ+kao)ef_(iHZ#;r2M>R^Wat{l?wvMZDBt-qVc|UvE~5QF1sPX|?}yiS z6k}l{d0IWj4bm4%-pE!YE^*)-5B@NUjb_khaMc0`F`RjJnpmOam#I^CG02XAgAkk0 zO%?kka2o1u>16d8Ia|G>t+C&O%^k1t{;tBAbregrb1|G#QN7W;*5P&i2OVJjy5MF@ zjz4Z`OuED>(rt&EO}xI-*ZH(5=|SR75~#Oi0I){I57;(F#5Y_M#;PIML0GL>cGFg% z)pi3GSU07ny}e`d&7~prD1NNP#X*?W(vy43$4_N`pc9HY!CIHoS)=A~V~j7?kVG9p>M2~+vJ4{&_l3#U%? z+5JqW6kFfs665*Xdh^bx5_+0em?_WYFUft_9rraBb8Sa6nF!fp&mt137RQl>V~w%+D}@mq}B-D(>pYu0Poo^{Hn z6;8-}ae5bpy_YKb4^RyN3&Sb55=3lYv&9Er<+w9uYD}z1C%~(y%ZHa2ud)LH zl|;l@`Q~p_juWoVmldI*xpi{Ie)>5sHdxEUTjX!O{kp~~gH*Sk$R+=Si5@98%?xzl z2XfkL`^833DBiK#A%6i~r-i^%&{N+?B7vIE_Gy;pgYdei*||}zuptPM>6HmexZQIi zLo+vLF)L>&4VdfPDOqYbbvv4xmT-H9h+@t&Wj|A}n!O+NOf@{_g7Sat-*t&bz2^(Y zR6iv%wA6V;`s`aowwC>}tld3lKmCXh9U>XC+mis+c}GW*bklr)HKxCmOs4hJDG@0% zwDPNGs$P0_;Op&2dA5|Z#sr;y*?x2~sHZkps8tBz3h~OCkv4Il%3}Dk7~KzLUyTD_ zLG(Mk3F*_T-cy7#Ky|dsivI;!_7ISpJd7cbF#8F=^j_MoKY)bV5MdjZpqqF<-p)t{EZ-;}ZcOwVv$4-iDs>6rUiPmGxcICktEK|}vb-czMn z%g(td9Oq(23`AhFa8*$n$~=|9Ii4K^iqA+?p~(03#P~pP?;(+qRk{aC-=`}`A3~9% z5Gf7cODOuQKfX>mMaMF1N(piqtXNBpHcOEqgFy=ESui>B(uW2UVeT=(op+%;NuQU7b|^qHyja9NmFoXrcK6XrFZY{}9a@q@iIH7z zLt!Z|6II2>P0eO(cOEiWDX`wwu(mY)d<0H8q?VSuU9ui_4oG%q7vcDECtrWc=NyMT z4DV8HWF?j>&t^gBZk;_`GuI44PH4Y{gUA{qID+6(aVHe2>^c+b2J$Bc zJR9Noki{Si0N)5D9&PDA{v1Q*0r4x#U^#IYdPk*(^q+}tVxdB) zARu%NcZ&feOoczPO8C!v_a?0G8Hab?CQ8C-#K1@6); zMTG007SNTC=TiLx1Ssn~w76G3c)JwPkbVhMlmKg_`GWrB{g3?^0N6I!6Fy_r|6(Lbc#wVT_R#)a zoLElY5l7nlzEYfm%F25NR59x90fd8$A64>8gfsx^zZEcfslz?A#$iXN)#|qypA`FNvJ-egab2owfv?fH>CFKbz8E7dwhoI)qwL;M`exNa8u zRdN>NL79Y-tFZJiV&xtaz>X=2O1lf3uUHXU`L9Vt^V^elbZK>8n z%u&OriiX0%auFiby(Cyz>K1B;ZoF#8QaRyRP-~{LqL}dBy(J-7p5;S}5)>BY?&Euu z-gm@p{5#VEr*suaYyy37vwynMy1L8Ci%}mtffphX>}D@^3`X+cM4%8$a%%8KmK|K( zCtJX;&w43bjJE-VzT(lHYqIBUdV1~H(A~8tECab%GO`F@CmqdZqY0Sx=TVEdqPokM zTfoq#=K2EjCot4i`cjzx2atC+&yCxX^v#@(GYuSCpcXmja$Na$_q7)<6c};HlMv(L zi-}Z8M-S8<={nzANcUu*`fWW6`w8tlwu4OlZvpodYh1mr?p%w6Ovg}3Q$a1fT?nMi zR|>{b));Q!C`a|+x_s`dWhUj)-U||iCVbqEU?g-~d9}4juEB7kkiXJG+^v0=y%_xP zWS&F}f9d%sL^DdpmgZg+nLn#UAO%X_`o>2`I9jmMTCX6G;U%@LVJe5bMoXA2TcXqR z_`VMq_BGWgBvZ-}#zOd7S^LGig>a13s9$pueK0=IS)d28T-l%}tq&YZ)p2%=L(WX6H=Yt}XRT>8piGNc z5sQJHc`He3Akxg??(CXJ`pCF??4uCkvV-+hxyz~y-~fVJqEtN>4n_^zJ_gwwW~1$+ z76OHKoGwlUH>yg_2IWA{A!vwd%1Y_?!PZY;7D2+LV&6gY%xgBzRqPPv+-~!lsMcy| zZGgaXH^%19N@KI(mIq80yjaS^r^d$T_>Fj-wPFR5H%@}re=8VjAvDinEsBBFxu%|- z%EmBLN>WjlxXtS;;ai{$i-pFFrmr?-xbKg4Gg_nlo^$bAVIg*{wKuU=X+(}UfpL!o zt5iG#l4r7MW_IRBy~vCt-9C`K_;fOy)yD6D{#i7a-t-GP9TaDI`Xm<1a*m~!g*;f& zu*e|$cRKtK@`I0M_z2pZSy(SVIczn=k??~Vp$1;O;7rm4^{w{GW9E1Bbepl>N@DB2 z@6?lT9E+ne2!lTR@9g4b9k$tpjy|}q2_~|Uv7%uc0-zAz9#XM0X@~&|7T*q0w;UH- zf2S~YwX>~sE|_(?gh&on5yd!QTi=V~fGgZxofuJon|eYa*p@FOd&p&xaSgSt4Dnju zJN|M8jeZjFf>EV|qonqweVMqpzQc@mpl42}rxj&EIgyG;3eWC_I$s#ty!$ie$%VP& z$}yv4jZHJLL1STlg-RNz#L%mUL-4zxk5jBsN9WvR1Vz#_uGVkKHCSj74WSR5$mzwY z=fbHPO#sDEkj^ESlt+yb9%ZcJP{OM}1c%>zr1zFq&UWbq^spcxn zEa7$^vzPiKtD!CxuWXcmNbMF{8h}Ltj$(OV{+B49f4%TojxyR7Q&!m!Ra=So!yrlD zyaT7Hd=T-rNfe(6y@Z_Z z%|uRCK`-sLybdOtz$LgU{O!SZWeRPya$NgRT?ec`o+9n=0bR~6jCJI7Z}SUq%>O3{nU5Vj24-Ze{vj51V?&{s9>`NwfUYj=`r(#<);wt9c6p?>o1I3y zsw^=tPeLqlcJYR<5%l#8k@Z!Iu6pQt>Y55@J)jw|=0PYm?+L=&{qnXN+dh4%_=#M~G zWXi0p81)KPtiwnZ`&iaEj;`uiqCchpJJC>Eo6@8bnlo#7{kU{Dt0#rF_M@Zl{~001(BlS?PIYQFf^Dx|76CV_tq3rIRWZ3x!YGYSf8{7bKJTr zSjk2IHELVl1>kgWe)BWroVvjn-@=B&ubDkhau&HO!Wq2wC&He^+eY$Q4{o7uTk${g z%r%N+AI`fB!SbDI8oB0#H86R_8P>95xrF0?_dzOipW-YX5TrY?r=|FB4y+ZReVhF! zI9)Mkf{=0{Yk{<-!4ROry`tO;;jS(kGT$1e9BuKB`{@;sDteF$c)XMX^CC3iGSQ%d z6u>D=XCD7+jm>+Fud~LubrTc{gY`zncs6)D{}l{6cgj)LNFw;YJ13L01!ami-!I>v zbD@WpJM&yk5$SolN1QBzfdl=b^&tbQ;9^O($Y;s)>5k}nZ?;4{!?$wI0djnTY~$oE zR#L^o?TpAG5`8G}bcKaTqLn+G9`jNj>6_iwInS}rvozVLG%e^21A6LQogW)VuuPB5 z)hZE)6f-a7fF$|j3;5s&h40Q8OMcO`i^;;~9TOrI@LFf-T|#N<5s6*Ft>{n&fJDO* z>Z3O}MyiDgRvx}tg!UK^k;QY-Q%c2hdwVy(NvO4zVG$ZdSYfOlt}q%H%1+VARWArS+lg9RZH zb6zOlI&H1{(of_y4t(4cn<<9za^jeurfbFpq(+rT*9$Hy_3nWq{muDGay^WsrhCDb z^Z*sYm6n>c&d1i$c@;1zxVtybAgy(hrA}J3=oN?N4s~^I%H#~t==xr39erjp4oZ>a z_AA8pdG~)WK>=U2TQo!z*EpReIBI^u=Xb)2t^mE{M);GHL0D)_FL^7?8sDY_oY1Ev zyIXv=XvM6T&&hSYzOiW4G8X#dN;MJQxNF z6fNNc6m<=RtclJa!wqx{7Qr$H+Ly11{Vw94s13|>C|7%6{6OBo_;x(vxicfqZOCCN;J7DTi;(f0y zK5>QRV*X8P+kyZJSoy0Wxx*JuBA&8Ws+c;K!NZ=T(iE-A1K=CkrtRzcE6KlI?vJj| zQw}`Z%OyqP^8EY?0#RPR_y8s2WZnwsxr^D1|9e>MiW3SU_4N-eO2k1|rW)jTLF_8E zFUmz@g}1_EubDEF=xygV(U+)c7{%*ovcE0zPCb)t#H=-0KcTWr%fT1fL z54shlk`Z=8Z+j|sGJz17Jiq+FNxL_#np*v;^4#FADvi52D=Iq;$vpC;j!um&_{ z?Er)_-f|ljw^LF^h36ykgb)1XDeR8Et4wrP>*H`G&$7$FgSu)rd|t$)9FHWN3zyU} zPG%F{G)Az4zrL_if!yC8rW@qk+=;8AY$3)c4k0sJ^Ua)c+M#Q?$AZ^f>b9bJHE^Xb zm6B+lUR6G_`)%MS)Qz}Q^6x%84CoU(ZLLNOqiYJ^9k~#sJ%r$p*c9} z!C~;sD;`ic&g-ja2g@1uf)hcehJv@wp&HplAMFv)%tmT;N(*Z=cP@p#a4#KyvVqx( zh?@lg7cUR+XM%u?dFfB*BD{#;kb|=ctt9JixIRrTrEsUD0V7k$6-I~$qanXkLvH-Z zh^-TPa8?6xO;~d6Sei7slf48zsY}y)<`)8qsc8`3&dOLIe^5S(@O*H1;v|YUY>sc@ zP#7!MQ6P(ouaD5KY+NOQ#-v97QBj@g%#3v7|6AMWqu$Y5ag@Y&%Xam9@yUHo_FdWA z7EuHGw$r49J)^Dl2e}Pj6H~)g|4C^LbOx#nk7+2yKYnEUH?FK6<>LWosXF{k)!r6D zLY#U3OVu1$+tqqCXiaq$5Rg>I!ul~m)XZWI9?{IbQ(VH!k>+k&i#Hdh)GY<5zfL|! zuzO}%nConAICXub(i{h|TKXiunpyJNlk z_Z>inR=Po=Lmxn7#uiFCPj_Pxzy1qCjW8IoG40(;L{WqML%|QwT{*q^vC?<`QV@J% zf;T`AE5{}8Ku$>B6PR4z=P-!`^ax5bPQPHSY-RdCd1|_19BPY?R;n}SmrK?vaUuJ$ zxNsGu_);JM36C&X=Hl#%m?>% zqe^kaU-618lQ6717j0H?zLFYvQXgY;M2fkdncD4|SaoCK#sM^{b=7jB1M$cm^5DDv zOHv!F*-xT#zZ5qkoZVqrI6Dv zca-3I3{YzujdsS&ndzKY{Hj@)Ba7rk@pEmPj8albRF-(DP)r6vymaw~wp~?p`91lF zNC6WB9}d%YLB-`MLC}Sto=uI-bM2cGvw1(-*WVP#m^iPUK~gRtbB zaWn(s+GCy0MQ6>06ni$l<(*B_UZER#Euqe#HW&rlO%v3@5u;raF`5t zMx=zmzwjjJUa-Ca??MJyz6kpPTI2YmOn!Z-^aX|FWY^M5afOn(RtH?R2Ku$sB0Y77 zqM%M8;9Uw}ho@rAHrE{C6V7tSa`3QLFNN;JZ`;ZEfZ$>rPnSUB9KqyZ1Sc)-3?Wh^ z3AY$PoGsfeB;$nEcjZwBjLt+*@{CvwWjqLz3VQJf044BLCyv8-1}MS860!cvISEIj zkvog`&E^Yi^(w{wh-NCO)XHXob8b_DR*@(jKf|8GAcD)1ZZPU>dtp@WYmT~_X-5{- zkKPI6w}0iw@|okf%Yg7p=@GtW(fneS}dA!dBG>Rp(ef8cTM4ztimUgu*0zOgve-vs|k zlG|W|ky%UW%xtQcHuKb<1rTI+wQ>aLf3Puu(e#cgs*I~D?(z`%Jl--(g;{>sFpZ2` zxjhwnuT`OML$h!&InKbQK?f0|HfsG$Q@wZg062=bzn3G_z zAJH|}EkS>4v|RW@kiV2iBRJgOBQEwPYL@!Z z(i$?}Qhf*7|2jl=W@bHM0rf=HBrTFzm6l|{Fy4n6>Q#t0Nd;>r19tg;!oBT(Si6&f4{D zo|=id&;1R^-*$Ql`D(*D-63N@8uqgt>o#z7-2)G_SWw^{DvrG_$d38>$|KIa!U=ND z;cOqqa(G8weI=23P0=#*i?i-Tp(AhdZiD`ZyGw>d$jdaN!00PVBYA#!AX9-iZgcPW z5|m#`bV>_0RMJ#N8o{mNRO9KFu=Tb?VsC4VgUjfC;a<)G?CpPVE3fwSeKi}wS$(lu z^^xO;(1dn|2G|Q7$+7=ly3kGiz2zG(&BL)iyNRqHW)@S{UDK4)W98;@j+-1Av($h8 z8roIHZARgJ55qf3e!|`N+y@19Cu#wg1Gl>$-%P%U?Z*JR9Plb>nE@)-`bZ?=0KwA) zCt^^NJci)6w+J#i;h4R;LR-GDJ^&ik#h04rVf~{9XR6_APeJ895?@FDWDh=O#R1lQ{K&ns zjk}I}@YZV#_2Oa;@mZsk(pQ`4+UvPr{c7*~^h-bU(P9P3;(s7$2NzFa|5K1o_jZ>Go-Yv%MfiPOS95r-D;dw5oRxbgW-1 z@xF{Br7KWD?h#*S%q%k9E0E{C)!vm{me_oGG0UKsPA$rPG8k#9wm%)vqx*+^pjpk3l1jnp!c^l>ZVF%+O1NIEFXM4Nd zKfyY5-EN$>Of11UNt8%ev_7=Yurzp?M8C8mh4UPHrUUZ6B&IPvdY~G)d!1q`-Lc_B zyzjG!D;`V#P?Imitr7x&fqCFjzfc_N)K~Jaw|*?`e0oTCz|{VOs#Bx@H=x)HJSu!e z#`cKFayLV?1RE}ReHeixOm&1Np*d)em@Y@f57)}pZ^U@04MT3 zqO`nq*oc9iE{KLg8ovjcdXx12H*5T8^$UAgX4A4WMWK3?6!7bEh`@7j00D$l%mrE0q{Gp{`*3oGHejO5m{RaSaBPDY~1ao3VF-FTI-MADvG5n#d z%x>`@;vAHJUk(}pcX!DL5|z4|LAC{ZX*#{5s}hsCf0YlNIjQJRet@ciw?%wX<&i+a zCzi5Lx8Y`7boll;%NO@8*gR^r{0PV+IwxIP*w3lRxqH^G9?!)P0BFhGXAuvaW?5^_ zfk3>l;Bn?mP*)3HFODi&M&_cpx+&sO;}H4u|9}5aNn7h0&JofO6~|&;IbU8Bo<5XlM78D*$wNiuIdnoPi-mWabmY=GLsth~b ztSFN3z#U9${x)ULU^ZBP;~8dA2rdC?No`xNBn!}b1TYXxlh~-5=J2J6-xJ7g5s8f7 zTclx%2Emg@&%4?Kflk0)hVx2tV(T+Pv+CQH8_z{~au?|5*6c(7?y_V0<))`0uv&pdBo& z{dkI}jO>@-bBV85r{Io8v646qM=5PHy;2a{`Yx~wV3&LnyCxn&7cXQC=%KaW+O&29 zIklHq8@)>Ys~x^5wlOk#4zQ7tRuG(xAw5`wejo4Mbp6W&D$CT)rcv_~k z*Ihv)Jco9wA!@ILEsp89oUndqX;z2YF)Mnasj zGA-UlEM90l)p6O0k}7KKaIExvp`)>O9*mVI915jmyhe~nfw{-iZIRG?iuXak5PVAd zN#}_+Tg5A=rizQ)<-;Y0+605iJ$Gy_O!U2UZNl>|({*yoy|0DPr^R~F(Uv&{rJ_H# za6Rq}xJf)NN@SJXX1k{ltAw5PNSA=3Bo0Kuq>nrPFeTvkQ{Jp&H8k-*P(BU-Gn{)P zvEPh$zB6!L{Le^Y(Cx(zgiw;k=WMg<7S6_3{TgARog<&=1tbQZ7o=-8VBmaqtJXF| z=g^c@MMyq<-O_!z1lS14oDN{hy*CGj2SWw#RTr$dHUn5XA|w!ao7?uAci$sy-oYvi zZG>R~J3ggKdv=O(_EkC+Yximgt|4sqE{?(qALxyFgJnk;&B}%eQx|j7+-tisB1syk zj{vKqE|hr~RJP=Y{%z1#P#q;6N-R5#GYjc;Sua(;3jl|%&k)vK0Vnvines*<}c6BEBLUSOWqbF~o&A5^iOCP1#iK&(?`OK9_Z`PD51jPB%7ZUYj6=1q(Jdk7e!o-e z5zXi5hX~ymcj-q?VQG1LW{Lh$yAJnNXA*al{q@7xRffZf^doVV`b@7&4#b477O{y> zBJIiKF18m^{ZP#J4dCQ?{4mkvI8vU*54nVQWJ9R5%nUOXp^4y~*|r!6ZW-?$P_J1= zH{(K5_l=U50;CHq_-dAWHQ^|~N_O|_?Vzyy=`U6A_v(h651dbyoQwGld7PJ`$r-G5 z+o%Kgt#1bL)Gs_AuSR`3wFVQL$7|U1yv#YzQQgBY4LiO=4IQ=4fG(`~s8pPD17Jci z<%!ADdbXTKP%_3{TF$94gQhyS5~-VyN>2+7$vBu~zmCWKm}G#|j_^fj#w5~!=Sb(e`5ESnyqhB%Eop03z{l-gBOBiqq>(@j@KQ}%L zY5tZt^^?GV#sQ6KOyMN#*cE0JL87e^4_I(`_|NN-{M81w(BdeAI8%MWSsjErnX@EF z$0300Jt%l>pV;L~4_zavuJ++3i46;XE93yt(?pzs=<#{DH2EsK5V2Xt)$UBC*j^Bn zA|^hv+L1*GpXYQ7q`Ge<)7j*PRAYcNaRJ)3_;6DO`VvBLl(u3lCJWu^)EvXk;3#>z zIgv5YM+ilk44J)?M)JnVPaeDyrC-7>0tP=<3~$L)-5>dK^h(pd^j4gfckAfb&-|!W z$#C_WW6U4$VLL=mo#N2kKTj*vqH-jOmu3Vi)mV7ZEkL&sz^}hG#q-Y19+z_c&C=i3 zqNev)C8o%?mP7qn4VCWldT=HPcJ^8dHq*=S))~!0kP;;#QArE8$g{l-e{I6u)%~@~ z)MAU8I)Dz!_dV(joGC3u?;{Jr%Qm( z4}XE30Ddb=Kvv?(2!YsZOFRi0>d5ji!W?J1aFOoGN&TWVQ%EVq^}mCd2?#S>VRlLO zVvG9>%d55;c+_B!IjgKMr*gPc zci2`zcjj5fYha9mD=ODtrEOy{{&gX@F*tmH)MGFI9A<3>bl8c_GR2qFG9Dc~cb=(2 z$#CG^wzzCYB$oSw%i)Rned8P={c((B^Qp1EG77xeTgtpRRt{|M)6FYQWrT8ihxQ8$ zmk8}z8YEQNG`0KBzy3ap-i{w}7&jmiPnU6rb&fK~{OeXixX|sPSkJ4+wn?Z%;X z$BG_rBqb_v3D368j59GL8Pjxt>dk7o7_}C|+l_dRps;zp+%1u<7Rj?euXfHa%?wrq z-E3M%aKdSFOZl?9Bj3ty-$sOf``Q(<%h3N}&iJSWF>4cH;J%E}Mg#BTvVpDZpFt)w z0nVw(Dk&)}C<#*ovxW0Rzh)AcWWpy;z1`NdTS$&1e0v*O#LbFjQ=MO*>7(KEdd*cB ztoAta3wc%<98B%Ndh}+FqeY!F&Zcgmq$I1SZ6LyBS2pnvvxc=Y9qc@{__-!csrxho z2>?dK)+%P58m)d&lj?8NVbr?Nscn|^ST}Y*;?2w2Byt48WBdHM;(c!r`6>Y5-rrQo zk%FmaBzeb~<`H|r>+UA=Zivliar@lCSj#$&Kr$s`^AiC7Eenj-9pvCvQwT9%v}Y6N zNPK*X;8k=-nzjpT{|c{8pnKsYaDk{DwP*KiJN8oa6MvW@GUJ13hwQFvO52rUABSbb z!m=NP^n*yKzV6uJfMbm$=D`iDhpX(MGEg7|**0^_vRWbYoLc=^={ED_AdSwq#d~Z* zEYHU7SEI|&$BXBFv!Ps5!H}>1DT_lxJOHt_fbH;mM`_wgK|A_|Aba;Ct+C*mlwqs2 z`+S&$`GTxrEXbk661s?6hPth+lYM0J_`$?Al{q=?PZjx7;}w1I{$vYq)YnrwM8^Fd z(&{e;VxOc2IR9r1Tz78K!LEYNB1xh$|06eC0Bj@e6M3(BTC5YJ5^jY^d>R{Ic)R+s zQDBzKjr{LTUB3iZn$2)JoEvWT=Y<1#R>VFHW@JIq;FzX&13MdVfNBEPM)%!RtC7P40o3@z6%vZCY}%|ani-E7bZUQ* z6U-TB$juo`2A8}X_iiG!of0K+P`z*&nVuEP@%-kKgWscd$FU}(rm%T+seH0h#Q#>M z`SUorHfe|WsO-vOA3T~R@mYXi*kZOl1vA_Duh1z*f`SI{B!U8L1n8ITDx*qeDF!Mw zlvxmuJzMyBT+6cdh!D^Hv+y3_s+nya))Np!8&H|Xb$PZ;VSrT(7}{*JcdvVrlIEmM z;RT3h^GWGeWjj#5zm%q>$ee^nBrR77amgl2F2oTWBQ~M z&$?WkSm$}vHuuB?CigjG(4^NOI+cw^tqQNmI4U#i>`O?c@`4ZXW6;}sACOPLXoZ=2 zUi{)oi8qG3WYvHbmGc2Ze&_V@?>#jOBLtY%$fC-zA@UhD0oiKC>$F}>4~?r>Cze@b z_p!Id;f~PfjsBD2n(Ql}8=o4SCs%<9{x51AFgsD-NC8^4G6D9TlKQ&Dbg>^nn|Mu+ zN8_FzMGHKu*RW*)Ag)A(NSvPbnK9$|Z9nk6Z?~}9?d$Uk>eQR+w(qN`@7vQRFSlm@ zLqhMjuF3UvX7WNp68d4R=JE)rNqIBYRrc?-NdF)dLNRkTf?o!-(hxn{MElQ#>8co> zg8qIA5sjo+9}9%aC)l{wE`+&ON17UG!4P0ovpbcuK?=e|9N>rcp9Ej71_+zNZ39ex z9w_qj>RZmT*iHCC!JCL6#F{EmnBP%L`X`^XB>QgX#+{VYvA7a;to&uG(dtm!gTCw8 zwg_dl0!vk|WH@#n-Q2OMKj!~ zIYKHs0fZmuzT7083hAJbJ#RR}ejNU$z6ev$)eNn$%6aK`#Okud{sb@1Ecw7a!J>N^ zdfUGdy)e4l0uHmDr+Oe)_0;w3%c4{MyC^P^cHd!)4$dUyU+RURlZ`4Rb8@4NMhXpwto0k^zZaosy!3hIB=zxuSi*rcbPT^Hd^)0O8 zrDmavH%(v{awRN`ok{CN@^N!?!GJNXjN%`dDUib4X7yvvyvmm5ZCw1G9RA{p!|=PV8{@faFxt+2my9)>Rznht$>XZ__elvDB}Q=6B9`ri~pLn@5b-QLZj(37pl zPK$-t3&OzsRT=o_n3)>P!;a_5q=lUJV`G7I*$8ja=mA^Wo3SClmGn*YlMJzdhxy78 zsbu{xt`8dTDieA?Oem4X4{La7Uz((+XwZIKXrSL&FgF#%Fk$LRDaiFE&u+^;O`USq zZAS_n>WD3F`g2+QOc8s;7U{g9z{&#di)4Yp>fi4jZ)R3LbHE~&xCmpjIarmZ{{R;p z6uu9~Va6IPVy<~+SC%vdxgj*^zVz;MxZHzUpnUDvdw6c40rd0dP z=$3t|YajUdFZ5lG7S%{{fx)D`2aHNybkstcpMvO|#U8*oHkQDsq$2uhQKrH(3qDxm z?okI%vE?vfSpQKXM~Pd+-&Q`HLAH`vR*a`;k+E_DAMG#Y!Kru66FXH{D zQul=gs&IE&Rvo0hKcK+^Hhd?8+;ntoZ_YK-RoM$gsk80*zZ?;OTP~SD%KsRW4jb?H zXsaELy)WvnhZ|uNtx%a}U8V9(Gp6XlbUN(z**U%lF0%KC=}wM;SUzf*u{*sux=3Zn z85Q76bO-!EdT|>mvGM7XaoFsk|8D^lcy6Q%$CvF=!7vR%MOE~vf9L%KC_N^}qyvbF z{)naU6rQ9UcNW|Dkwfmz@k$eOVV}SD4PWxIJ&ZTTsyUt-X-X0crK! zdWAbMIm2)66sw|FpS_%n;!2;VcT4wIul0gdL@h@GzDoO0#1 zUtrekVm-9|mgt0!ZjrI7)VGfm#rPLN#Rz%CZNNtsz$g5SeXNb=O*aTBmctdcCbq=j z<=-=%^Ktr#CRt&i&GP2rOr5$SmbZcTN9R!_%`}8gf)VM*{YEQdtz*kGx|!F|*2lvmZn%k7dJs`5`8o;}F*0Pj);SHgEg5x5ck7v|Kdc%r(i}9~Vnm6GR za=-wSuGZLP%Z_#eoUJ?#mh1SToLtD=T=@nTHj4P+9C8YTsxaoyJ}qp7|9_`tb>{5w zeiFANbt{`-a+)`;y<$weI*0vepHJCeBC$4`5MQ?E80AT(LF|(`XtUTQro-2<$+F^L zgtLEbkLT>9jb>JxBBW?HGEEi_OIWW}p=zk)<{KwzS1o=&jE6y@{uBUIVGML?EWx8vrk$H%kBAN5?k!d>_6`C4`noM$nAPDD{5 z5r4R3w;OKd@z~Icy3!)Phe1@E;1nMRSw)TW{jd4Kq`tefG#r%K<__>4vAf;t`9fQb zhHnNEgh)7LfKSW1h6uMY@sYDLqmx=Wuq(Rt!x5YaXAo3}vIv$+sQr4|BVO2ViSltR zMMn9cYeKZb;MgUlV+6mLp4}>)O_hFG|0SM=B3yyfhmyrp1j8Fe#J}jY^p>?M!54gS z-`UOf(fas2{D54)ZIpVe>QbBp(tMpnZ2o>x+E8HDQ`bi$WblhHXX*;4eNe08aLWr58|0YqLMugw!tG6fiknmv;ppydRRutso(Jz@xi~&_d00 zc+t)veoyytm$(oYMXTET_8P)BzKua+i1-F*(p~cH zdWpc{Y0;Kg{g!IIEZswTT2z2M2n#l+JbOJ#V`*&*@#$%g3mI>UE;PAe1$C-nw3X8* ztoqzf!d#Ti=PM7AhiRT?B&R~e7*P%wvZSCBsXfRg(E9_Q6Nz%PR`?jZ!AHM}b$Ue+emwKd;mdS@HRb0LQ_KpA7J_R4B+p z`E?H7pyJpwj~Ao9(4@!FyhR-AN58;lS1EKq%Ep*ih4WxYl}>pjE(*NDk`nY7#<%>f zUN{g*f=i6kI04Q1JpFxL4-FiV`hEgM9lD!!2@jSak5L%_?sa{{+}y9GS_K!xevkwX zQhbNO-q|P_2p{O~FE=Y~(tQ3Ayh(b26yPC0kJ<2^^RPkt(qtdsL^Zw0i5cX8LXQg4 z42jw40A}n}vZuSG#Tzfc=i-pHtFGJv+6G25fQB-)EIq;vSpk!KhKl5WUw>HG#LfLc zw20w!-ZE-ft;rzUI(J{%`Pxd!$4be7HW?O?KGmy8I8R0#c$H@Fm4L7*)hf>@BwA^s z4Om?;{KR;~!w1%p&PDDTju5RP#IVD7xE@ko+89W$I%u6%h~eCHN#^==fw{r72e}3| z=Q0OOo$u~4v2~jODd>lyxFJd-!5^H2LIN$Gq=^z#y<@O2JkX|jY}>YN+qP}vIks)v zwr$(CZEN0dXJ@yjD%HP|AKg_+rPJx__UPf6PifEFo0#05l|!!bSJf$?_J|UYKM`l@ z9-T0(-*hl(**tyV_^h?7b1hkqqkKQx$`B}hx95WXFQZ}F*7%nR$XHy0no)YdENu(I zeC5sf#@{jJNPlL=?>jI;XTt}N^hXx{`?V8?GrmXK9^_Sv9Cn}PY8|AG#KW)LPt9~e zBbnu2kC}B=yy0&8cC684I+^wni>H#5Qj-Z}OBH{+iQ0{G&+9HMLq_~I$h%&5hzIan zyDUX@g7`9!^4Z#%kT>doHzX0N14EG(8&fLd6s##C8cNtK>~nUVLS}Yd2f7GPr)vdl z2W?}o#A{ZwCl-Ho6B3WotB#zW`D^onAs`g^p?oEAy1fq+fx%IU=^8X%;}`^E2HiF>TXD>WoGr__;16CkuGPuL^h7iSvNn`X&E(#XC*a_JQp~a zTGG$Y8(a011vC)~$2zoF$Pn`((w=%8I_33B$lR*q_ax3IUGZOswWU;Uu~|<*>CLXWwV+VL>(x zB0LkFGV?W;mYhu~=q@(02<3(`<&>dej<{w5urBCqzq!+QGWxuN2MJKc^6X5hnw*)%NC34D`PVfMvO# zf=JB3QPk$V?0RGxdODpX1A2r0GQ>xzD*PwI$j}M2y2J?mt2Kg z<8@O%;g!5as*=;NdihG{E+nN6ZSbl5k@hQ08f1QDFy6H~*gl=O!Ofq#T;tT9@Y z0}@E~=h_rxvvtq;)7+^-|8TtEsJXc>7ey3sqLnyNbSg5OU3aKn$WK}hgUe|nbg&6e zCtYYgoJZk-QWXU^Ou7YmID8zJmSqPSvvh9Lj9UktVVEnT57CF2MqtOY*C1rS)R*M? zPg+2i6X?4e(!ls92qQtiP}a*kT&3%i-xb^Fex5bB6%|z828e7Y5&5uCVz;J2#pg%g z!7GdbEWf_w5&hfFFP~l2za_Viuq`4YZF=se?n?bQ58zaD@)yrWdAvqNG_00k;T3Y9VENi1~ISk7s-JNh|R z95R0R`*7`&n}k@EyAp-Kr`R>7Gz@($%ScnPza7D9X9=|)7D(4P+6{f)k3o-ezQ;_J z!j+V6nFFyQ2>hlW2x*~>C;{QX=nb4{G9#$zk+C2#mq_djZHMXWX@KXh$qjS2aPsYp zAo1oRg3X9@{PAR#=m;e>JJHc#U~{q@!lAk$Vy(WOk`kV;pEHa9L&8k%BrfULC@Ul| z9UJKCTV^?U0u?zZniGafP@p<$n0GN5zijiZ%yo06o8r=6toe0|6u3FTe`s*ahp~NF z>|(TF+5?o>H<>z*117b(nU^FH_yaL@GOsobICr zM%m62iXmBsUut8IWG2mSOFB4s5VzDh*i@s%y`*hjhD=ZK@poxzl z&Yz1Ww3YBJJI-_oilUEr$`?;J7Wtv`^Z z$y(&~TkHO#70POT9|=asNl?AZ?mK|pqFJOWkSguoBc0PRG8|5G)wSf#PN@m7zebAr= zB}W_FD5+TLy%yEn8^Q~XU*+8Od~ZHYpQmy7bFzJ=5+WYZFcbp`pG@BP;{!;d<3qj_IYuVGQMB&!w7bu2D|zVWuJB@+k0 z*APBQHa@;Oe3dBb%0Jn=EEv^gqkj~feU>|UHPr-q$7lPaP4pkkCIR|R{ip5XJ-tCY zlk7({>dzA_AJQ7W9h{PlHafN<(ef?BfoUe`YxS<>9LX5|_5h*;Bt6hAKkJ{S9PVMH zlflIWLcTc5;CxZN?>|FmTRWwf^c`=<1v7!5oQQefsqO;1Z<qQJ4ACej75?qfgWaMiX&harE=V zSYd>S)0{+5iPNJEP1qWpgq}0E2gm3^a7<4`hzmy9Cd#dms03SGhzS*h_2~9M_$r7F z|BBT;Eq+JD0)TZ+r{>E$Z-n97$R%CPO-%9Nuww zk86Oz$Ek?h1Htj!Eh`M5rK8WB#AB5S8x<@}vcF)vXVr62J3#}P{Le#LNn)N-L9n!a zUOGKz-&5iKSi+KjKcibIOP7vN3}y48umks0Oo6Nq<64AG8IR9BL4c9yuyF!; z_5lx)md!3FU^{3_Gl&N*MOY{3Vrvvhju+y@`b%l_-1;7u_2$GIZv&_bh+`&GFbH-- zC_h0VhGHjW%>7%WFSBWNx2trV8IJujO(Z41pY5khy^rx_S0v2K#N+6Jly`byd=M@1 zw6xaqK?8yk*n&(rAsz=*pJdl90iW!c;Abpa)GR(ByPqR zcS~{$q4*pXXR&6Fke5@%KVwwHx>h>Nv<{tcu1Drjtpol0_V4Qm$1%A_rtJIoVj4tc zl|%uDonxfqdh`fghRgx@&qrJHb-#yjOro{u;?)YNcwA|s58w9HYsx_KO&8hz00`W& z(zp|lp9UYdX9wHdPX41j_+qhs|G@d><@buOv@*U}fWEt_et&7roz2TXE##f;g+1N+ z-znEgrdzwTbR$Rd{&)?NIDmzQ7B9Q|O+blN!qge>@qK%2!5R$L4CLm4TAx&HY0oej zJ|m;_2)&Dz`3SH<^T>^--a!*}BY=#5bX zHS?;09X)Z$)oNmeEP^T?H7X}#9AvvQ`#~nl$RGOJe3Zu7AjQkhqOr?JHos-2TP#U2 zvAPkON|AoD_3=e|Vtj2cD$7p#WA_LlHS>Q%Q>}~=Q3Q#n)Z{0+Xc-3uzMEc1-qtF- zx0HLx(JR9)vd3$OE3xAxEWq%*fDVON$UZQNbVa_4&b)>bMno zQ{N7#Ob@5|S8T>Rvly&hvCPaGkkn(VZ=)W#$@^IA1ge!YvJI$1Ds~PeYvlZCaefV*fuNbt(5rz#CUxWS4D z=O74>W^55^1Du0jw>x~WD|5vH|IoB!OL$ugs+%K^G?vIvr$qPdt5u}HSD)Q5Jm{~gDM=X8a*n6c*)D-1Rn6~2lL06x zbZnpcIEmP#2$TYKGq5<21iu7K%FqMy#eSfK!=X3paIw+C!iI*oiY=-S&YIBgAapy4 zrZ1Z7R?KBI!DW?LWEwK$QC~7?d>gC;lyy5({u$f=i{21b^(n}QZ3?|-8jnm?EN?KE zr!wt&vWIX1-mFhc5>_Xhk!A;L5ZXD;w&vR94|*9{W4Db^d2G(cWM$c$2{#>hY8rUAe-+4f7FhXi4( zH1FnMG9@FjB*AAp?OAOejgWe!!H{t(8F9m*g-df4gwt6YPp4Fu#Dm?qU?n|=aS0A@ zCi83HJI4v#o3jujk4~bHFH^4i5+Ub*dM@HLFR_j6%E1_XO+*-QwVvO_P$5%B!$IM+rVqI{_@|cJYxOaOs&1X zbNTq zX!bm(>Ilsr=oN>e8w)*s2i4GRD!>Xa=`vI6aF1wc6hUl(Ipzlc{RRO!J4rtl^nLoj z$4wqO^9FqF0~|bIBx4{w{hFl?jew)I8CQSvqPm_K+P;00rjf%#@j{|`5J!ps{zcJOq3?$ z?KA}n#?*JS1cNXQ`j4~iXM|rib+oV?f-HWX1KoTa=tLN z{nXtWHWq;(F(BaR`&uzGaQueGpK9KZzq)+k%f zO3e7TWR0uckRJ9GAl%saZRHSh55&z*WTit%cCRyJx+bszKM@M96`|R<*I5%p*uV41 zV=xo!oPFO_gnyIo+}g5e}o4pVTfdlKAF%@a1; z5*q#Szh9pIg34`uRSn_}Jygey*fd)lM5{ zuvM-q)vDfK{iu_7DUkzKVuJ#2>s_yJ9`)7-wa)=gH5=ccVEJnMI?5!%uu@RvkOT%h zq6yHGxi^8CbMW8i#3Sq>wmWD*Vui-EeQbs1ZKc1=3Icv70$HXh(+klSa6zZ?KNP;I z{FQ;?Fk9ZZc)7Wl(*zweEc5;i?u{~I$%8WQG+_lvjg2Q~g3@*VED`n^tnr3~C3Q|}7gg!b zDaAg*w0>S$`48i1FU1l0J-bT?_?0E$qUP)jLTy7`M(oWbweST^x$59HXP&-M!wXVn zieu_-gh&Hr^AIr5rG?;SqBz3P>NG3uyCKh5GrL1u zbx4l5<(6=frhP2G*lUP7S>n8`>Bt{mpwLt4D}^m9@T$bVi8dp>4kf`kS{`CV6MNOuh}s? zlho;poD@1tRIUk#`@w@z@1VDPu0kVqTC+^rS(tS_qisewM3TyL^#}aE{g=c;LY?RU z?%(0peqk7vNlD*f+zAtBJSAm}bt?nd^bM);FH=iA<(>0}5UfjEP*lO_jevD)WIkR= zoHLdQz3Md%DZk5^+Iw5vrj?T63A#wGNb;rb_a}a z`gXA>=4lAQrx_l^#&GF_e`Jbi70AkBLzsl>{zh7te1T@|sBcd5=fGH5fcB}15>u!g z>yt!4S>C!b;WA+duMekx6u}-h#@JZemAcz-h=nbf+szb-S0~FQt~bYA7WqVgFNd7p zomLR2XT*ZxX~9y4Ofv~{>R1B;bV~qhv2P9$=lQjXZI=J8+uj(PPIDrLTop-kaP7f# zf5Sr_(F0CvSl*Lh(uY-m^7SpT-F7A;n9sfHVOT@spJpu?aMO#W7=e$Ry#GtS0_XS!J1Rv^zQoKLbL|eXf#@fdSwNjZA5Th*aH_7lXb5)OTBG~L7-e-7_%#0+IS@0aSptHQtPUtFqP>t zZLc`P1~ru7YrqYzv9I`jlSNXn4K1Bm0_tx&-?)rZTH)LdB#!sPI&fcz>+g_(=byoK zR2|)4AWTEdSNW`TduTEZ_x94Z=hh{psi|ZNE^FYQPpo8^wlet_<}2h=Jm01Yu{ibu z7!5U|_PbKd4P*?LBjA(SV#40Y7xSWJHB9pn?@do+5`Ju2oWi>RI1JD?H6cEhfE@4p zu2n9l1|lWbsfQd~0iml`TKZn74GsyrA)|w=+*yG0V%xrhhgAjQp-76I%8CbCp?!4!N3@t@c`WMt(jpTnKU2%=pRYHWx+rAR?@&mYd9 ziYQrR)4>V=yA=cen0wcCO!@jxFHbNQS?V8dcX#t3n+xrwrD%S4O)fg3)^muaeXSPB zH_YO_y|I<9sjlv1^Y>-~6(>q$$0K zMi*4>f8U=^v>77mj?38Yq^vO-6mhw%i0AUPB4*dU?5Y zczlh^fkHReSG537O5K zM05*!!ovt)cASuoO%3OSMl9&kz?7Dbst;7p%A>nZmZE|1ZhI%tIOUU+H5Z>=8ACvQ zdUvog4yZJGUPogkFe#BP^4^^2`!OBQL0>_k;4{`@(|9H`M zp^_NWxrblBM#eB2%diU+@VJOYP<{ zeFn5SRC2Ara*Io=U5WqTm(EHN9O7(P0_00vj{Rr->QIA%wkVPy-zaW0q%vJNUr)KF zI6PJQ3wu8dK9Jw~b?CS))DM7jOVK#5>X2KP^R^sLeXng;qrIu;mj1P3PQTECU4103 zoNTnwJZr2{@P=n6gYBt;g-YawhNC;9J$sswRU;8U0GB$brm3@Ius%`(D@=8L2>#81T?~7vmpfZUhlt-2V2`4@GK&i=<7>!m7I3iQkYnOjP%w@n)&(clf*2 z#oLe~!D(Rwu?qey8*?Z>YJcP>RdS@cZ+A^aWx#w0Z-??0S)d3$jfQJWONlHf0pukv z0tD`9)T`EY8Fkq<;r7#WlJHH--?-`t{FjwsyN?}iGiNrkBoAKq5RpZN!TG!W2h~(P zy$F3P-S<5;V^OqG-&@vSkUh_`>`;tI_65W=L*i~Tm*KQb@gO&!IbP0pK-K4vQq+wQ zFL+WBUX)>MCXoksr>CnO+u3daI)+Fp0JDG3V-}F_p^@wHx~{?YT799o(8*X zdow5Qp3!jV(xqkRf%dLm4B>8AIA&%l=s8v`sAd`?D4NU2r7CI@koKS1pUzchSD zj-|b);3S-=pP+pE{UI7Z#og1ULPvx!(zMtgN1!h%{kDn598i@>LRmhXTU6*(IGDCP z+dBAx2l(o}bPfDt;({ra-}TAc6m0DNK#7eQrSsiC^Zdz41F*KJZI8kSA6coBq1+r%|w%6N*6dIs#V-I z9d59tbr)+bMN*4s{mTTyl>$!F*h>rKxM8Cfmx}Wj*mQ-fA-#?F{sD`7o|HQJ_}99| z*w0Ireje3gn66?D2nVpXR^gO}G@tFI=;H5!?CEY<$bI9eW4b+5TZ7oq2)AtcPS(#aBP;q~$MD2f?lV`=bFbQYN~veJK%2)su<5M)2%+JLZ$ z^P$Ch++<6(wP!LuX{8=4oh@xdy0h-Gq82y^5F0dvH~2B;9}-bW9FcDq78=E^e+0iS z(u{`eta2P#On_KX{#=%9IP2%_@4z1uxa6eK`)PYUy+xUBe4G+=Z!t+%sfq(#s5{ zf-t{)rfsnCJZ2j)i3pMxm&r5k4o5kWhd6L8FefprzIsK8uhlko!_V4M`26|kv~KS} z9^egWnwia%*fvvC{aeT(epVwIWRZT9&Ux(T8GCaYoug(2Wg+^32CSCF;qN@JOb%7| z_uaT8-V>}))c?LK0o0zshKgt^npRY!+tx@3c?0Tf<1LB$I&2xq4x;=d2>t51O%i7A z0cbo#!M%vP6yG+Va*F$;&b_0J+|0$VT-9`3CnQFYBz8|M&HAF0wPJvgs%zO)9<>Ru z-dFmm*=S%F;(~h8uO&7i`PytOMSNAw!$EV_Oy?B-u`=&%p zJ;Un%IX)U&Q4*R@aqGp>Rd0Ue=V)_bS~hA?C*vs&Yn&9!OS$qGP!2~J9Q-8MXGuC~ zlkbJOfuvS09i)(dGUnh7UA~=o_NR-@fHr$@S~n?H1$&KIJMZ-ggN-sRr*z(K>Furz z_u7;@k2+t9azFV%2?2|oeKxJNC^L6g-$$hu-zI31IfDaB%*Mzx9#hG^!SJl@ma)|l zj{`}QaNtnOdZ~f)+Lwsdmg^tiOK956v)5y78Ml2KqqewS7bcDoi!rNHs;;Jgwm)@e zd7m1Aalq6EWf$5GUSX!N`TjfqN?zyHyopsWKMR_-kL|5s;G6VUIDfo=Y~4oq zl(;h^Yj1uX6lv34^2yJbhBQb!&#Z8p(7CeOr+8zTLf?}?SaG>uc-}qIvI{xK@1d!o zGA>lC-Q+$dPp=Xu?WKWbj$=HPl**W{9{WGB_It^Q#3MVl)8D)?Sl(TDQ1wIX>{0ltWp3ysal6iG@**wuf=S=pi&iPdI}hhp z7tx-Vyb%G{Ubr81!yl$B`Rh;U99+PQQ$>0nR;btq@8XLexe4`6%MQUPs8O(k={kv+ z)=IN)DH0ofarB34EnDr1U*9Ioe2ARF?NQ<#i#rKE09^?yc@*HZRlhaehLP7#{k}(% zaSionu5NSJY)V1KT!R*1$V7A#WSS0r%{_hT(rgu78VpVjHMj`nTnD-DAM}X(Klg5m z53hk@{f*}<{@dNIZJEicS`b}sm>h$V&Y!RoQ>*G8Q$YfpzrGOCcl|m5g&r%*MHVT4i^5VX)`)sv9Q%9C%h)IOEfw1sI2@p5B1zcY z{eb?End53sN0>cpt5PVl&c*cBjaacoz<3;|MnloZid(`Aqhfec$0*I^V!EDiJsmUk0K5sBLM|kf4%wuOsww>6kcI6_7VJ*-Hz&cr z^!`gk0LsjkNr^w!*I?wA@Xl_6b;Mr0UXo5F;~E<0Dw}?LLnUXBTdRlJJB{adzxIt= zJEQ#eQdO#p}9 z=t2{|h+~oMWZkChkMo090;s;?*dw!|fSg3I3*~4g6rRt0(1rcXcD62EifCPoBn&ZG zX&k+&FGo({_;<2>DNziRidGbj0$h<^sRyvr^uwir;6TWg$}?8a?UGR55&rdyn%H{6 zx9(fqvcX-T&4`X;Lc#J|G~^jade1+1?0^!i{n5&>1r6b{2)r1b6;iZo0}TjG-ZVwh zRKDxGMNBPFE?JmJg=3*(B_?evRlWr zzC#gS)jr=E<8$Ws>`&ym_~zXX15)!H8sjSK%k#?H^e^O9>1Gg}K0h@gJn;txu1hqT zt;DL6Sk>eC4@j>80(nm)u6jzx*-36!gz z*#f6bu1(@nv_GSjf}x)Y;lYCUh=0LCa66=_Q7qs(rLQ^!YR6zakAR0b!EvX3UU#}o zMv?!+Y>V_*mIz6`Jme9)v8U-C`!&#Tw{Y4(H&% z+6h#r`Xv7ZN8Y9^rqRQK2bn@}6Ry{v*No`(n4)xCht;3hpg;6S=&~6-HJCnf_zyYA zq`<-z2V|X%9nco!u=b5BerfG;9VttX9C)ymfQQZVp9CdQaii`J)g3~`1*c}<0uuyP z5LjhMjRjVG=np|26lNlAK>}fU%|jZd{DgfX#nO)%p;4FeYVysqRb3@FYIDVXSfU?K zI{0?-Fil5hL*osy9?c0B^e4*#o}>iKsx!xW>)_3}87kF99K)0gv@S@lX_I!lmmCCE z;}Ow3CN_`!s&-mTUTcz`c<9fiKl@0?8%w#Efr1Vm^6;c|I~LCo;fhm+VVxp(=_2N! z$be^{|BX*S@wK~|^rLs-U_)ed6dzpYM;~re*j5UWajPE;mDd}&mlQ!l z&=#Ij!j0>XxAG;^cy@N)Csv;2XLQO&T{Z`Lzy3#+d5Tpp^TRvWsp@UR_NdC#j)JDz z=Dud4k?K;oV^06l)rNz$Y25JHf@@=Tp@@s{QM&PZ>^d0)bec;|$=SvRrmFuo4v?l? zBIVYVRPjno>`*jMq$swZO=hw6Pf~OAS`*Agk(QpFRWRXBY^1^3&T{B0m-jBq@7vYM zql%X7D8xD>eE+eOtc{z-uyneEUzXvu6$Wp9y*(ZZ={g<30U;f>J zlzh36k5ImS@%*13>8FaDD@*)RXeXyYzab&|DD^GZ8hk$kH?6@pwOy}$*6GLpF|ER~ zlNzFbex0f)Q{BEQ2#^#HFBmCXg38_%z-E8m$8-{cdq1yBOqVAgJM4nWO$w?f7 zD}m~lH^FPq0yvIE&fbwD}Xi(vZow?=>_ z8p(W{0fC<{bU;*)Rrw|Gyh@<{|5vQ~ zgzJOUBJHmNj0))+p@jO(#qnf&6`^imn3Vr-y%EeI7x7BqE zh{hN+;-=scul)M{KIErjnbVhO)&l>}%%fi(c~FSvkvG2jO5!bU5dq=@Z(&357BFB) zaH`q0@fxNR{(7*IgQztvMSbl9!4bdxfrd!}7!tTtMt4s8*K>f1hb{CL`pli{lIz>VR27`>t%y*b7kKlN3p(9mgAY2|542evqh zCzQb8pzVM)0RztJdJP3BX=Txi$`y{3y;LiP<8E__UN_y{e&mXuQ>%0bexsL2F&X*U zQFQ4=?P&dF+Sz%L59OyDdaYj_dx;%}8+pafo?av4`RM9g8KXh2tzNQhYih(d&b|CF zd!Gdk-~r|(FsPch`jzz0ou$_UcSa?`rCfv1BKNqSC!g}PE%`sgHS_x=>zfk(umbS= zo2_>%c%M4Ip#r@x&xBvJviqH?n`hZyytKR_^A6vIKilTMgH_bmOZ*%0pPmMNd!wbx zHjfv)KXBnccNcK*A=7Wxpm$G{KXAW4!)hG$W#}(U{dZUWZx-&?0^i;BySBLK8TOT%_V_P4!3pEAYq&mlt`-%=s+eQ~-CJ|OXGzvoQXW`Z#FtR$?5OIyj*9=OYNwL>``ZC;)v)S@B z__owX`x&g zr>KhtUv`h>*YL$Re85^>(KdZ+;bhh?4@=}xV@u#8UL0GmGLBqgYolJ$Sj!0yp*dN3 zXNGgL2lgYpL%VW_q zF^fpFh}A(3nmB0I9sN?PZy%|Vy@RZIPSmmQ)JXMiI@}T(QN`vXQD~o}GKaR(7B&;n z?J37NDZdDG7Z(c;!2Kk1O?I3PGgJ_~4>v)}B_t3LuQ8_1;TS?iwN9Du!GF-co@ zDpLQju&K!iPzfiPJb(B@{xM$1-$F$=GIDYG!y6aCq+!~qB_=)&ddg*5W4HK|?4lhb zp(RT8$y<;lG!x7c09c6(G%_Vij@~**xw5z~qdFb)6|Y+R-L7LFN1Sg08Yui9D*Gu! zS8Ay#USC44c$Hcv^=ZbC5-l%qXd}{?^@i~DsOXNY_e_}h)bk&d$y{<|-hxD^#xHTQ zwol}1oH~Rma`ru5O^tjNvDVw5UkQaT?l!`U8IG$UbiNTiYcdAVu{fTp1oVcQV zx1ZD@kM)bve#ai0pGo^I6x8Ln=9U+u$v+03eIbUs?zmha?FpW--Oj1~sKT<9nRk&b z1n3Q&oAZKl)!cuM4>N>(SOAk{C=1|7jOm4+%-thV^_|@Ai)LqwM|{mPf>Yo1^L_UP ztb=R*JgGc-)p+(mJA)hj^Oy84=iX?2hD{z})AcD$NuZkS4w2k3Ra9!JL~9_0S^V8~ zsE{4M(|LLOlt}A*hml{ayAe{ zGVMiA6{cv4|Ia8$17p&Wc=}Wc&r7e2ny8hBPLAJb98w2DCP+~|IgI{%joe4Nkik~~ z`iA?8W)wC5vx^)4te|*p2_)X7dGy!K3cr39t!@4Ko}LqDyM0}nj<)NRaiqwwkpv;X zcz{(Ipw-#`SM1OFq`09+dr=P0MuHe5D5k2Tq6Vpw>01mFlf=SXL;>`DmtWw z4GYa_6u()|&jQw>h`iqi_nV#~?5q4>h6oy@siy$9@rDu1GsCYD4!70&9rthUhhke1 zzy4z?H;afi!C#DcUVgu`7J*5_IYsM2CG!DZL_I~|24?;km*Sgn)iV++>V`0N{9OOh zj5M*`txX*ehOCiT+X3RkNsX_w0%28lxmtXt*j_C98@PS!j^f)^er(*ohI>}7EHPu1 ztG@&(C?m2K{v@;vFL%Sr(OJ$ix?`htGr^388Vse;hf)iB;8AI0^62NS;h~95{CmH< zRfI&hJBLAcBjtGcKIZ1m6PXS+qtcDfC=c2~$Ul&Zr0%P`V6zjJj+$3a3ItbFkA%@H zc}hy$1!dJFx6*C>ZsEwTn%+X4hO*ugn#O7>?5u)5l%mCTHJ?h{4-TZ){ayJ`7>d|U z$Z&ILkFVk+OD@!@jp;ZI^%mhXwc_MnxChOzR7oN?TY3sb@@ciSo}BO^mqnfRFogpA zcm6|>Xw)vcn?Q4JQKr3J;C=}W!e0-yRpkM^!?k#O9^IYf=o6=cTCNv=2?*iS5$Bdk zFI8wuwcnxG?FPV+U&)0NPc32j$@hqlLQL!VZF0~L;`;o(wA2)x{JOL~cm1ME@=tD3 z`U-*DL%C;1#{T=lx!AEkTy8}$t%z)i&h(? z4(D++ZYcV?85MuX1@#z!^+E*Hv-pzyje3lTnghM*zx+jup&selATX zgNZ++g>k~$V$a?z#7&PsWlf%NdtbJEb+@nQ*3%sRZK@Ag?ap^ZIZ|SS$R%%y**F97n*OIfh7(TC6Unn3(pD{7o zrr3%>sZ7Ik)1F%xRK(pFb8uY^oBXf{vl^N9cHqfw5&K5LFv^0cEf{Mv=TLzoc>Lb7 z7q**LXD=&=(kvQP(_V7p0;?Ygb{htBu`Gp1(jGOURZK?{-%F^}bF|@>%jJls+t*cB z*MJh1zjyw_&2CTF%rGX!0L0zOrerj_V7st`Rjbu zywAC{G`ktcin2|Unr4aX<`lc=DsDg=@XRP{#|ObhKd(3L_-J{J8G-nHbMp>}>c|t%jyrenIfr>f?=(+z?xX9O`+W{9#U!gLH zEuJR_!4p1gm-{>M*3DvxR1Dz91Pg2n%n-U`4S|sdL&klD*3_?I+!e`nhEtEvMGXOs zz#!2`B!eY>HH3L(bYf|Km>y!?(7{$rmvO59m{Fy?0WvtWj8T^~frxmM%lcIg|EF-8 zm9H>`J%|Kj%B1TSq041f#H?Ilw-v038E@UX5I+<3FlEP-H6-^`9w{HT<`5}cfon$5 zhh4|jgo$r9k~rg0{uRQ3Q;0v%dtta>@m%nTW25L6AgtRdP;x9oN=d1dJ&hHkYuZfCZhgQ6g?HsPudm}d?FRkv{M$X z@0@D|MAPmfz1vaD1q^T^yA%Ft8*2P<|Bf^@AUWujiq$0x*e;R{p>c$x5N2iS{_Zv! znD_`J8QT~0eBx~i>@TVIl8K4|PJN?j%<1s>y`U=k4 z`Qg-fdS(58-Yje#&6{?0t0rzcIoI{egK0c^L4Iyh62+#3h=Sx4PC3lxuyLVBi zuBVsU{_Y_U3+rM24tkQly?^*q&3o^$&piE)c}@6G^m^FaHCk_xGRml?*c`-)Ysgc1TvMieY zd1qgL`m;=@sp>LwJjd^4ZEVrt?6N7l!aILHhDLdmBMsi|k~E(v_t&t1q;|*CMa(L@ z(`F(GravgO$E8Gt?Pe5P5k(zA3oT!T89LnRdm5-8X(XAOiUK#pcq(Srk4W%v z$+7Izgvns-(BDXKbP&tG^dwK^5-E0$dw2kH7vOt>FOvbDH}lF1O_+Uuek*TXF}|Z> zQ1WGw`o9qK53|N1w->*GOzRG|!atWO3I}WLG{G};BQ{vDUPq|K5a=5z-_}MySC3Xc z(lb5OD3&Q|HJMVd^k{Z0i#6rZ*M2yD1b zT++lc~6yZD*mi8pY3TC75|Zf8Vwvh z`=V3M2|w-|LT(D+DkWj6Zv{ll_DgA$;k6S=KCS#|3{g@)poGS8PipGSUts=bA&G;6 z-93oZAn+h=U*2daom2*HI)=5NtJiWrB3hNxXM<(4RviWdPRG65HDzqecc+aP5-d<; zBagC))mC@KtadYIQpeE_I%Ehzupol+0EYA3&1w{w7tXToc3SqNN}4x=GDNoVUZFjQ zdFBqcy;EDfuafluen9;%0D(Y$zo$ePa>(bvI8oNY1xSwKu~SIxnT7`tyNGpr`dT`P zLYdP|^@B#wFphMK%;eqYV&AR{B-Ak>1O2HQyGl%n0VgYzDvT#LyRj&V0It3-(0-vx z5I2cys`P@#tjBTVEm!t*!A`=S3`!9g*OUBpihf5xAiJq+(i_`Sd>^5d#HfaV{ zlN7`?4GvffgxU1IAGr@`mQXNaCC3rygk z0TgCt1LGm+HI<+bscXhax67O-nIaW@v@Ho`X|O*lHwi)i2ojfR8S7OOHl%?uE4+yT zxGh?+BwLw_4U!3^mS# zT|FS~mNI~sKl}KsnY9?WxZH#J&{hQ-CFSb?O)a$fULW%(U~di4zuF0~*lac-{f3#0 z1@O~WBBIst%Bj`IRSy_ynWcJugz0*Nb!y)i{#U8!t#w@yWOEk-wgh}7oWAQV)Z;Rh z@)JU=K+XU*h1aIh4&-;}rmgI>UyXNtxe-#)SQ!p!lEiBey0?%IH4opFLY@LGQ4aC3 zdQI}X6h=K*_9h8Jl-dstORwxyE_K;^9>GNM4Mfs*a#hzU$(>`Rr7kn_VuGRMBRV}f zBVmLAbJoA*$g^-weQPS2!9Gz@1Fep&!~bSxkQ-XDd3X531O|-RpZUesE+DZ9Jl_M( zCxoliSRtL0a-84v$@{I{y7GY-v}>*V!K0AD{8Hl(Y_)4M&x4tKZj*pSZ zJ=y-%>jp;9rTKGqt8~UCuw!mZyubf?-pHQ2<%h-gEyq(g6!+&`Mz(P=fJPh`Np-`KVXbLQ11EBhss_~ z&HJSoP}GQ|j6PEJ_PEoSrX1O@t`n{F#+1IcmsZm1+i#gm?%;1g;}9r!=GtWd^>mvq zy1J^96{ch6N!qS3oy8Bz*n{ucO^>>e)YAY{=KnmazzL&_Mb=$@o?;6c1H4f%LOQn60t~V3u~oIwD*y%Ch%O zF%6gxug2neK(;~UGY8FYxGUSZcc9t~k)+?rV%(1r7L%yueM^GrO?Dn6xHlS=rGf-o z7$7{^?!Rc`Z7D_g6$4w|ADh;`O?q{*Sn^UR}1=MFZF9zDnm;WUaC z{N>fsN4|7`q$i6cPLrL$@*YQ8G5=EA0zttW6wL>~S87SpcarQqGSly`BK*Y_;Tjd(7-o{4U$+i&;afcQzLcU+}dsHh44%)(mxg(O~;!A zmt#INKVWG0A#^1`rnmW`!G#=#FP-i!{xsD}ziE;9>1%i&9j0YFZ^>B_ijcS#w1{5< zxV%65@!d>FldLbgU7Z1|o`_OR78fJJFR(J8)i;=+fiBLM9NQy98*pwLiWH^HA)BM} zlH^P15CArH0DP`M??ZIvoE_AASZXxogi&PUL{UQ%^%KHv}mr%Tk{CsO_{Ay-;^Q6#047MTCnN;xq*!Yc?VWF!hk2GdoW4|jq*jPmcQsKa z++#@MRO?PXlYr8B4mST6v3ufm+8(m?l+1i&KQu&U8~R!A0?SyiwB^#YP>sH`37MpV zSSEf9k!a+!qeRX?_6f6#7ZzrjK6n?;X?5QqG|>ZTXmCgDNgsJ*ps{is=v_okya?Ye zRJoS|WaH{1PA=AeyC%74-4VF9$l#Ak8cN-|uQ!WxrkITanSR$e1P}LMrwz2royY7t zAr1o&S7odY#*e5StFE}MT-R9D76ySVFgBossS1gVUDJj;*Rj>FqzII`ujiU0Vd=4J zAG3Pe9g4#t(G-Cn?Ohcna;2eA@Ht9;*HF!fx!(UeeH;N3MPa(`^7SrXY&m^etD(3` zU{O}Jnw5mf3#_jNr!`P4q`KqKr{=Lmo@AmVohaoLK~DM>+nK#)qq6JaO|G-?Y>sJR={*I7rU zNrrA@rVfd!rD({Is#LoYtX%j7LP?<~g}bdQb8Vb6eH5B_gYacb4c?C?)r#Bb*~vp+ zPO@a46S%__qPf8oGZ71guaHSp7f_$ef#NI(<5b^kc7fy1V$E>7{PXr_QU7ZPl(%la z11qoCb>z^oCO`qiF}hOU3ph0AB|pt8s9uPN5@IL*r5Z4m$Kz;5e8V9@h5>;mZuTkTV}E zvKDwqn3kkA4YJv*?+cv^c8@nE(kD9KBY-^re}NXVsxwE$9_*oKQ(orNWBS+)SAC6Z zapQ0}D~!Yo)b&{5#1c2%;wo>@KOhWrAk-2BG1y6Qs+HiSf;mOp1SbUQ4^~3^Rj39R zrz%rGhp)Ps7!8BVmP^Pgs$zNaCuwifci2El(ztwEe2T?Lsv-6pKU-|f5&vb-;=I09 z=G5Wr-2ye5SUnb@`ghq9e&+O^X0cNaDpY(R;sy=r*O|dskT|{P_;0g^ESDFME-<*n z=R7lmSK=OZ~{*?|uLz^0qgrvg%0I|DY_U?U@MSTOg6ix}F6Qwx_Yc7~_0fU)HN8SMY z=Zn**&gw5#lXqU3QS+(( zb3g_)03-wN9|4{gtCqzw`68(cPbUGcm~83XbnZC9$>NFd!&Xp}nlae{W0t~6^ z|3ZR6fLxJ~bLr=f-d(v0^IKx!6LZzEF6G8itDx=I`~3&FTyWUb=(30Kso{cX6@8>y zNg@!o`~BfK|8pr`sJhYXF_#Osz0PB78H4P1tgtQGk`-$WpokkaO7SK0ju$s~k#T3V z$!)rDVHDat=XG|ngH=P{GxGrKxg|lxhB@WJNxjU|REhKrSr4V1kbRD|-R>@=v0 zCK#tq=ZH$ZiCYgqKg5g1)j4^?+rMj6pttK`ZN=ra#G+e9P-&vKD<&As=fuIomobLL zv=Y!s`hQ=CUSq8x&}-n=uGn~$yHR%Xyp2$$;2Rb3UF~iH`jw2v6V#YFtt6X zFEygf;_ht+h}a_ta98LBoEL5tmHtaHcWtRTRK{}OEWeLu^b=2uBF-!Y%k5gy#sF|rQ2Ptmg=Js1y2m8u(Y@%FJaY+!D`qKT(d7}S4&5nT8@zNu% z30Pcg8H6qu&;j09&4Qo&mB^eu@`tzUW>(&a7lxGQz#eJj4vBa*{W@30DNIX_aa8P2 zXQ)J~EX{Y97*z!Q&s82FgjA@A3zp{QH9}F7=|NTsf2SCfKBBJs|6+5X%S;skG$EAX zDB~q{rD`_pM^o2D!#eX*?u@nJfWjcTqRco=Uf==e!X^A|!J~*%L z#?VElMrvlXfKG^0ZHo=(IY@Kb1jJ99;d7EY*P_Ltij1d-sPP)kO53$KYWw6iH2E*0 zi#hWW>nZ@Ew&08BYmq-g#V=WrL^{!zBp~*>SMBv+x6UdrEk5oOUHEEW8rh__n~^cH z1(hliWj`+Bp4a_`XEbk$q3u|s;!p)%*Io+%8y5iLBv$Zn-tBeUjw!gj3TKYY<6?2y-U-JgMA+j4R5)H%_)N-O53` zEk^?pCjt-~$w0g*Os7bZ4^~LO`2ilMB9juyQPyDe(ZHRVZa%sNtlLPVEx@<1iL9>! zO0M8%4|`qAT*a4Z#@b_#x|>)g?i{bxAxKBO_`vv@_7}xhdx(XC*G?OJz<|IrjoH4{ zYs?^XV&%FLb44z}9X8`Tz#xnnZ?&oU=PVDCGiAb0Iti2dfv~X0_&wkX7cRU_gW1_3 zcKd0E(?CCkbM2}S|7CNjY&p8(bD;Nx`2$~7V=vQ}cAhtX3_1u*()CA5TDyn|bfItk z7W9Q8{&;XO2+Qyzy{Ldu7xWxC{}S-t7|X5Xn;qv{L=k~~-b3O2S{%R_{b4yQJ^}UQfa%b zutEU*U`%)Pq}OiKMqP{9tT~%HcmHsMJ%V7T!AiI|-mJie91uwrz1TeVRu!H#hXy=^ z)d*MgsVq%Gx)yH(g9Bk|rM-$Tsv>{bLd83msPc$VS<#!C8&x1|48F%0#+Mo0A1b2( zggQ-M{}BRg=SlmWGYq{93KB$6_d7wtElKp&q(xo<-ZD4cdkS+@+g1?5)uK}Wui#u za{xc=fDXno7C|FEKWX&8dz^4fFMgOu5p1dU_&BxxWz2G@|2SD{ zaZVH3bq-^>C0LT%8UaW4%Bt@Ami%IY8%0*3ZEDYd{q{XDf{#EZRaArikcw4NlrrVY z$aXQnti;^Cg9y9qrk(JHmc6As5WT>3+ar@;^AHFBSg~kqU~-I*Y*!ew3~Xd0afzw3 zCg1fPxlKW#kok`qgWW$e1^vR_Dh*+Q4pFuI{wJ&n1pS1n9M1z?+yL_%^7=9{ z^n1sdr6NxyCo|Q{PMlCDd=H&|`7MZ6mn@Zm53>iMkTXs z_MnRJEOt5yTl~;<(A~i0S4;w)#EUU}W1KdnwC^%JAUXT$F(Wav;cq5;q?N6mB0iHw z)S*A0#~;tx$qpN8R3D)(bOs(eA{Gj!!aK(}H0LrOMlTRT+86iYg{R^CJJ)_R*~L`y zV$V1cvs5HbtWzW_m((uft{9AuUZW4@#x%IUVq-Z)fu+6$dY!Bg)pkL=DwcI?60Ox1 z{PL^OHGVMX=@Tk@LQ%pQB$?tt9e8_JK#;1z1EuTu$X%UUFqJqX=w0Yq3_P!V8Usqf z?o;reD!EH(GqW(Y#m=`}2=*D)j3(R(Vk|oI!U}_E@@mB0oQ{XUk!Zg^%yN&?NqyJc z2$wR_Gw~&tWTKPod=DtLOr7JB>d)Qg$PuWp98f)gD;Av<|0b@X31Ouips%JP)a{2< z2rySfo+E-;M=I`$Qm509KmMrzJ9!;Y+Ia0PvT2J|wktz^t&M@i+u{B^U=0?wy-|}t zQ|zmi(}&3&W*||^1**w&93RYES-cL~ru)lg@%#b?C;k!4vtWQpio!&ysk0bq<~@t& z3k}V!{^2$`Fz5s36p2`7NsVE3`8A6r9s{+lMpY;>pi-slEDe^AnNJv5}19O1@q!X-UlHR@SXE_LYB zz=0=)+aL?KyXho7K7O>EU16|VSZJ^+b>PDu6)%(HqvzJ3-0R{yZ%+yUN;`J+o7#+* zz8wBwM9TnH%5}(W2mT}r(1)y*n#yRx=QhW@^mL5e4m_ozYXWg*o)EtTtsLL zME0#P;U%RkGT=<0*AnvPZN~I{Z#HB53or)yYdZ|}JOaP(2s%@P{dR+L@rz4;gm)d~ z<+*$VLB&FjFsmf!9RDvyzEvL^`r{i;awb1~`c*c5v|W{%%EPz3RvKP{iLRy>C^LFY zL9h?GHgT4R*=*o4lgp2uI#sQrH#RBF;^%I(`+| ztWvj~o}UBYf4rvCf9~2i+DbzBc~t?BnpoNj$$tD;O2DSbbKdwLn#`HYzp{$ z0(&7c5#FoCKJm{j1|G1@1172>x8PpfZ?4NQ#K&*x_nSFh=$Xy0bY!fO=94dEM(%vb zdJX~2(%D3&tEy+A0XpJ&tj*JewQ}cP# z8f>5d000F$5RZ^-wf_g&Z~nF}n+`}UZ1qR4-G{c*+)`NS&3yeI!;OI^;47`d8=QuQ zY!rlGi3zS<-j&XgnB9p@b`aYfecMlVu<91>n6P%9+dRSs4zTkkdn@6-pm8pBJt=QyNpZDv zPED&~le>f+zXRBk)<}1o{|JO*C^S(25eAz;R+(5ZxWW8C7T@mXWbr|D=Z3i*^m)s) z1J_N?27!l3Sj<^UR$DDfmN!Crm+)6jvSpJ1rfTf><&yZPz?+Dw`YwCa!;+DG7{qbQ z{(>8mTyGJwrI;-Z>hwM8(4Rar+1d|GB+QhB(dOzE;SH<}DC&?v3>jXXp|hxHKBGI> zD`}Oao6xkBF&R&Rog8OQDeM}t7Nef6M8xULWb4iaAY~Iy%cgwo4veLk!e; zXIEe#00rhlt+k0SJ>AZ3a>j$^(lmBN+yYS4CDzsuH+ge*zuejoBn%81j)@bvqaQ2& z)r{VWLfG_YG$cGjbghcMMiSW*1@N9oAyAQ_FxI0dU#3KXuDF^qAQOiULNywsK?||D zq=Rsj(u`4BV%WSN4$_wujuu)3zi0;3yNOT?FDJmz1P7&FrpEsc*jDqhkX8R$5Qqjd z?2e+`Ya|9&h4}SS{bUO^4CI+jybedk??~fw~Et`k`eGzc>v;+ zV0)Iq| zDMElHBBTzh!TV>RXNo4gj>)he2%g6k)4*7BDQlUO=a*r`>v9x#d79UgEjrL z7GmSrSyFA-ALU@7g))Eu_jxDBvJ@+30+R_FLjms&GOXGANa($ESyK|s$n8)l0`#dQ zF}cE6PiQuBV@t76Mj5u+4zPit!}Lqs%~==bDn8Rl$Xs?xH?MxR#Ya+o;7_1I$9+#^ zZR-4b^-T9}a0wP$47s%s^g@Sf7~cTlsgj2%UMjI8*QeCHzREMrf9w$8w${dITZ8XR z`rU<3qNhNlA-z4tt<>rkgOC_4H~S^@(_jmr>q{MP*<>9zIgeJIaO60dCdi~&|7Q;~*|U~o74kA27RYR|@JJk+c&{}u$0WtO0G~&d4lJkz z!k&W&S$HYH@S+u2asNEBYLftxMf&>fq#OI6weC(g{&SVx2p|d5mM1!=pi5xckK=ae z^7v%SGvuA_tLdhrILc2DmIqq}e9*Yi*KAunY9hYjjq@j(Ij+~hdAWC9&v$B9 zx`SEN&r+|<^XDTtt^@~iB{!jDA{Uu8^Wd;k#jfNI6`y2g18$UWNt?<5{EAysy75pN z;l>J8QD~BeRv#JMaFp@%fZzewi zzjo!JiylLOflya6S-AF%8jO!OdmB}lm6^EKvSmN6jW*1jX^v2f?31krJE)!$1KYgE zHrxt$0j7_v{8aA3sL{?>%#7ro8@LBSj1o2t+Xu~@I%ZZ zF9e+U=|eLbqETa4>rz{WyqIOlcRWlW!^9V`-*>NBunDFU{5wx-J+dMgO=gk`TyjZ@ zpgcv(kwyzsZ9{j*g?&HIeD2PypuAfBA%h+=@Btj~f+fJYiAgClswn@1lL@PA`dpEP z_D#PC#(Q!wyhFt&WW<}MAc!C>=Ls?|zL6}E(*=fGHBb{#| zF}M$ZQn!IORs>NHYv3~5@Q2CozR0;nB5@?)=Xbh9&&R*W$G%BaE3=R9zGi|She5eT zwCdTBUqV3?EC8?&E{6fVHR z%J1H4ge-(qLHH@_WS(>QqNqLlwfv^_)|9b^X>+tt*oCN~I@(`(h-y zFA>-0w7S zcd>FVnZ?35piMb6xAnFn=l=NkaNwD?KF(lt()0QSDds#59pFJZc?*3`TEEX3hRbmD zAoKtLf}ZAiFt28-}_2LDxiD#o$#@JlAX&fFR6A!U| zJE4Spui~@^Dy7H{qDZvyOh?QP*<;eWyao~Da&_b|ORc*lykksXUhp-`!eqS9!}i_< z56A$Qj}9eVIkWemxk(bDDZ)Ub#hjSYGSpN2!$G_QJBI^)-)C_%eDg4TnlSy`@B)Eo zX=wdms1!4&uUrbT;9Q`7hc?b^Q}$H-_8z_8)? zmwjPHV6_Q;ReP>B46FIXw_7jUjdzz-iu-}Nn%=iYZyhFQy*z${v(8LH7#a z`7uq7U_x-SLa0I!b=*pwT&+=+G}MZOQJ$O4H?l+JFhQ2mv&smi)#yM`R2}-KXgfrC zCp!kIqUZ3kz!*py^q>H$IwDK;osI2KlOeRniWb=S2^DJJyJgQ&J%Gk|9!AH?=lTeO z6v{6wevI#)yE6BN)hy@lwo1^0AT#-%U`;K5)LaMfFp7Wx00D%AS(bnPJWLd@X18?B z$|vi1Iu8b^|0M52{m}IRh;)`mHN1))kBq1S7S8Y}674`K8DHdQ{^c(7XG4cS!ofYX zu~-{&ik0-@lb@lCt}#hK`tT{B8|E6p@f8y#WgsF52w|Bu~<6jiaP2s>~RnP000+I-dyq7}UH8vkVp)RKBI&D&FFd(1HN9_aQ!}N@BeV!XWpM0h%^-KcDJ(W8#ozCa z+OyRK278FukNconu+H8PoqQqGFAgOF@=EM50|kTUm?Qf!htj(z(`%da%6h%Kz56oI zso4)OD%jxE$-k9&xSO(DJ41G}+>UqGD|krt9+*}bH> z$Hll7D!!#*XBnNr2dxKmMoPpW17CGS_D=@Twv)49{y-9knkOE#;h*=@gglW#e|Jsv z@CBd_F*bY0T`yv*Z@}?$X_5iw*1?vM9;{L0R+-pq>Y zIc~{O6aPa1FY0t(F0n<$Nz4L2?&ASV)heS1c9>eX?`2*~aeWv5Iz6^vaveTHin?7* z)yR^QIhgt_@|Tq6&?kSkhWaCV#YyPX*3itTUEiBh_>IPXnF`~R=B9o=4@6fYH|g?q zC!{v&Ew9rPI*uB@vF;e0W9*I>{ElqR&6JetMjiYcNq?Qchy}mEg<+Qz*js*|ek>AH zxA*=L_#8&$o_6oDULdD4j!8;hejSjvFkEv+ zWZ=H~Mk9ULbe@f^S)@Jqoy5YlTa!cMFoOvQ)e$1S^6(4)Bb}S(3NUIvfB<13BwiUX zHor^`Gtv+_5~~6%sXTcd=}~S=Ss&kjhNCqyOHW&-(=J+RE3{=ok~*Z{7p@utRT^!B zRw&F?8~ANaaaloN|5(F|`forHUDSAS=Z8$}s~3kEimv zz%Y=LYr!!QN5PG3S+gGag14We2$XV}sJ=9vq&H$xfhB0N=75P{U>h#Xnc6wp=gzjg zSMXK;fBz5_nk%MUk+H~*8yjs}kFq}T`xkE5spJiHaK>J8#K;w(7Rev9*X|vBEez39 zI17~2kKP)2WKR}tKpFjDJnWKs^{eNcD2!xtJm}S{m2W?lzK4-m2^15hSoAb zzE$Y{xPuGE2IC6L_;)eAg}FVapoAbDX3VOiaD-@^4Rl|vCs#wMRMt%Z-bg;Ti9wSw z5DX+F$<P#MJ_79J~cG-qDuBGk^DB&w3H>6WzI z;OL4^7GJ^NJY@fYUOZF8!QDvWtdt+lG4PP5d*>~gL&^4Br0NuchEUnBrL*EEJR%~L zIR&zE6MUXq019X&C!mm7gJN@$Cx-8P6b)MbIr6GPl1bFZ}^>fxr0> zRP3HYHwcDh0K!5`;zCrD^maw&^q>H!UY~WUUTGW=?2I&4|2*g?=AHc3ugil)e;M_( z*3I&tkN^V-0PJRZ`EH<=o!q!f919YH6Mlb#G>qgoQ0`j->6FG(G_VIZT2n_-MnOECpuIG!9dhI(F1RTA#{G*ykvpx5TW7Uwqlu1|cLWM}kW_x# zFDeQncp@`E4Lp$LQ|yk`e630aq*URACKk*GPbV&X+I)QYpdW~n)*!CW0R*#}a(!Vu zrvEUH!X?n=Rx#Y5!x!FdNmDv7vz0Z*jQ8GyNnS`_SHR2D_T6+Dtss88w$~Lg{6@Ub z85{FNaDd%algOSF&NBplBP(Gag0MpZ7*-FQ!>zefe)5H-J#ToS6~WJNq{ZWDNz&s$ z6;oD&ofM&!hHr<7J^uxKK2r_HgWGXNd6LzfSV2B_R(tnn8g?+QgKiCb2PG|pelpO3 zpqGLetS=I$k^BmtsP$Hl>Nam4XNpgK?QY}JSEfh{K8L0n1{PYLi1_~;6Ar2f68Ayl zDLdL+E`5_~RjNZoq!803?iQ5YP2$8dVqEt2J%JP#*jYkFAZWAkN@eVx^3%O|a5vAo z!?G;ggfB|%7gr8JBmg1W)^J)2Ur}qlQw~q46O@B!yzfUnl?N#-$PeRrW zhfQEyJV!E=4}Bd)uZn4vwcHS z1b)fBwHO+bO^8myJlN(%YYWXl7JFX}HI6Q$8} zL%zOo4JUdJgaEGV;BiniHJ9c;2pTUakKqfJ41scnl$Wn|as{mKu?M>kFW*yD#?y_O zW2XmE2~tBWz^X7o-t{&5OG8(yMZfl&CH8uy=LrZh^SxtYa@8 zgEi4!OV7S^SLKxY(7e~ZKu0V5Y1X@RW~ESM!M$}{En$vK7lo&=P{*lmSca*znPAIY z^>fB~DeQ)4P5itf_X%KyC%NDAe&`3_%dFAwo({aPfbvZphrXD2alq6K2y86ARm#Er zqAKC3d4eIcXXNyG^hL{`eJX?XS^7lN_RE(UVO+U@h?-ZpFMD~fb20IeVpWy5w@rZ= zPFP_>Y%-==Zs$d6%0zo=RqGqKT|Vz|$LE|!@iOjawmxo;t$%m02(5OK$bPodiBBEV zfFjm(WKXCA*2iGyfCvov!OgZe8IFqYjBs%{@p&7sV4U1uN@6%HB;*B{*GGp_;o&}$(G&VfauOiHA5br z=iA24U%3Yeg*D=fK^Elk6%T!L`Na8p&UuQ(XbDizg5QU;*;xS5F34xjyfuTNC*Br3 zfI^=!{in|1&NSgDV*JS(_*qiClnkwZ?F63j8Vyit`&7vTKWmph>CINnAewwgbk~2ny9xRf*333 zy`w^uZK>D_rnyJ=8HvbV9sZg$*PBSFcA9Q^#c`R9FSA$CSBUF?%K2V5EH%&v*DHdNjy%>y8)@wSVhaRw9X}Y z)BKa|jK!a5#P^y(Q=wmZ%M6Z^DtUG{8UWS4%s6x=0?Xc0;7)*vM3-X+bJ!<$TYx{X z3v9HhHEN!YzyonsSK56fMAM0)t=J0OluPbDk5#=mjBqqp5zDFDDCQ>Hhd;D%@zvIo zhoRY_=}WGcF?LyUv>MNQyS&g%pTCZ7Ba)XA&EjmbWJ01M1a4j>8fXfHX#*}-`lJR6PyeC5=t8;VR~7uw#~d% z<@B%7Ap(d;n+Wi5dT$X8|5OPm7*`vXB){qlt&=5!hfIY}+v*jzu_)-QT6^iVHrZP) zAUad>IVI3Q*n(nK+Sz}1K)_UQf+%T~q<6DZ{w(XYQF6~(viAhAk+KT;F&-*7?bN|` zxW}+xa?f?o2je;nfROz0hH#Bd zhr4?KRIcSNUXh9{ynfiBq47_l-bPx(eWyPH_Ning^dmbNIZO;upnc_?G+@`&KpI}aji8_)R9%3 z&|cQH&@L1XU6RQdwys+CI(RtUP*d_=Yb7;{?=c}szhg;y_{4D-CKzs1F_D&5C5yY; zC5|p1TArC5mVXIJ757raUy!)8W9J4-W^%bVH#jX#mxqoBenvdTF!=5c4Znoo^}-HX zRf$*=x$??f-N)8X_TDM)-rqH>5tVJjH=84Yic6cx#f4tkGf}Q8643X8JHJ;Q)=AXh z0=;;~9~3@`8A4oer~!~{8;4E#_^mvmCGvZYe{eFCdq+6C`Pvd~Sas{Uvk?S&Ivwqb zhZJ@=$8cPsjUr|k;S`3=Y0t;G0$y^Gjx?iHOEk^95GHcXGG>ZAoG0tqQRWGCu`o#X zAqh3xFo7SRmZd{uDFlk9Rr(fOk9-FwFTD01^xzDOM|6o0`UZX7TE-@P^lXVdRXa>3 z^b;Nmu=E^<5RT$W`lUCr*zEze8U$0@S|w@6*+I|7Y4ogq8U)H;#;JEL(sM{e>j~qf z)Bk%Xq5}@tVE(uyKHKdy^M5U7R(NkWAqR&+9nLb{J}Gd~Sn&(V{xpn7{yf$ryMi6{ z1#WT)t@jN$+(DXrl7uc{>w14eaSyruedQ{+T;^egjWy)J``Ufw(pfHk&RDH$U*h_u zw~axErowe8w#N7-nB6;b3F0MYc0XvtS07PrUq0sUx8c?kJecECB^L%`Q_v z#<40Q3Onhjgt`I?`S_U&^TTyVXUqARKMibt^&TR$c>-vq?2BYSqzQ$NdUDK&;CEda zNj3Yd^MVZiPDr#{I4$j*z`(eZL%%A!_6Jjnr5oR92tE@{{q(ouqQo2nUI8l{L%^11 zZ2qYtz;6b54i+}DM;{B09z|j2x9w$yw9-EOo;%Gn5V%pgJ6_@=QcUM6KzbYyO0vq4+OZ`<@7eJbMX(JFx@^+8fyS*X3u2vw~&VQz)H@ZWx2| zhk2UJ)d9yI3sX{sz8O(=^`(BbH!mw>;!aHj@KC5Beq39ueOFy@$lud9bAHXqh!A#f z0|G<2cETO-itj-ew(_0%9!zd@fum;kW7U50u^M^Z;bs(%%xdhBApXY|z#XPIsZ{c8CE^5g5@Oc%oCb2w@}! zqTu^Wd|CME!Hv!*;@#MGv`l@ujK;09orEj*B2`U`($2W}S=y)b|0X5d+`^N*>o&9X z_MSB#0lX6jYEN4nIHxG>go;|~d@P|LMkJ@SF3O5#6><#VJWeAh{-YUd`wGPW4p}wa zCBT=tYNsph=yEx=)QZ+?EC7+Yt^n#&P{sN#)K-;eno4%?8qB~QLxW5*O~+?icjl5(N`=%WAJ^TpPxXqU!grvT)2y8?q)-H(Yacl&KaC`hLuA(L3ZJg(?b{M zf1|vb)=QvKr;}M?Sqp5ip$#1yZe2NYstl8PcKUH$dZuR%qzLHxhdB>7)RU3OoMxr2 z`frR}ZmWTB4Z|4|=$H?nB+G?$mxa+_K5tU?_skcDFtHMY7tJe#M@{wA+x-TCE0?5P ziZ1L-hZROWC7kCpeTJAQuhQ=2pp2d0hIO>q={DefmA#8;?RHPUr^gKxf-!XNa2jc_ zPgl42N7{faN`Z+~p9mh6x~V@+xKgDa)~mx0h93697b5{+_9DEl2k}(+$l?!GNkqBt z99H(!sj*hWft9Di1@qSO-@wc1M=W;2et*0Gp#UCe4cK=pC~ol{E{9?-WTM3G`5&R| z6)WBCMl3Xyie&x*3yx|}2vgBNOyat(hf%yx){I;y9SyQrKa7w1goblw}uTnc)= zD1%DoPpkH;b~%G;_Cmk))96fXH!Fs0h&Kdg&%AXVQwuz^I^`CL?EAA%dk4a%Rjmcw zyMF(J$fMs`2+hTrB-%=(V=%Ft0O%gkUadU4hhA-P7v6K)9*kM$2EhE-EhIG5k7tOb zqi5-8S2KfeSpjXR@f{19Zz5x{^aS_NBm}9g+C|KV;x3Y)RVS=0OV^SnijrY*WBUTD zalgOGvyz!!v)fs*zcgN?z0mR1UO{ zr)+J&NS$xgCj#tvt?YO9-E68hK(tF7-4)hS8&k zn5!Uzj5x4jmWCK4!`yNcKlF>XLys&EV_JB% zw@`UkS=i}m%hHYiQ`lgda_6BKOtA|PGyJ@2rLwky3_mM<7CO1HIwG2ei7dKm6}P(jvq--bGT_ zo8D01!u8L`%av6VP!Gxy&^l~WTI|)$oV`)j=60%QShyVF!1>%`)K_4whx&x{wQFW+ z`33P`gVM|3ZL5d*K#k;n5^Gr^Sa00UlqPq`S>$0UL#TVmW9agtbVdW0ZyfH#Z|7^g zKT@QU*u>kHY%g5xShE60%*56dnYC}-fF#|I;lv0TpW#v6Md4mQyqW7^3!3xi^-Hh2 z3$=LjMxcslXz!@Y=qS?&?dYflUEhvsGuGD&5X!%vx{iT7r??5~ZLQ*W&*ZLjHZ5i3Ubj!fF@9Z$=y5!;*1B9>?MXQ?lmXnJTU!7{WA}u%V*2&870gY)}hs zC;_rzT5u*sgWz^+1;1e|RRqX9upjA{xeqSmlZeC_)bWINjGpi%NC z5eq7n1ggEOa&k&SmBgrbUPp}5V!)V(M&yyD@T%)}8M~nO+6S=_kV&ojMegk=?S__@LFRfZ4V+vB4Y4 zgTS3pP%0+OwFJbP{%=wpXLB@y-Rbl0K^+J27E_|tA`|3Y}G*pc0ftT`u*!(ei^r+G0P z0j6tM$~r0&_JSi7;9NF#L+m28Uz$KHxarYP3FvMPA1X0!7!Qg@_XU3mxB47e%khuF zgy&;E-6UsKqCHHeqT4tPLBR1GC8g5XFY2ej!jR>E&=t#Xggm>BknFz|;n%7RG-5aZ z0b{Bi)H3%SG4}nxjjg>VCgpaV$$eyd9X&q4C6+%()D0i}h(r+LLu!Ju<((adAK7TO zwyGMuSNpsEzF>WoW3_>t#{_f>H|y43oHOKKM9E}@S29n*TTK6FN9i>ayY^TDZ)Uj3 zccm6JTX{j0lDsrxV~pvfzfaOnQ0DEa6)Y%};(Q84&V8Qpt#CD`1>xB?cwT3?+-ggD zkrybcaTLzs*%#5#_i?f!$gqgeEdIUSWup%D|98Cv5d?$u>}+Y=PSkvRkYdKRS0OL3 z_Z=oi+dfK$D-Ie$PnhMPu9mnCp0OI~nuEMUwh*0o@Q)JUkBZOeHxY{oVg^89??kCl z`e9UdQ!CLUaH$`M%t8}JDi{?;#)1hh7{D)4Zl|XV6JWLd+;*!9GotxJwl(lcQ;Fr8;}$spJX4O|r`4q)-ZKB(0cDv$C?W+wDiqVGQz2+PQ5$72kyQoMbT_etd&Lp?sB?lyYY@ zmQA3QnzG%;=-*P00z@6qzi*+3?dwtw&~SH7{k?^Mx2t$NSw4P{PoLYQ`Tg-vpP+gr z@=&x9!5nt;^ZNR)q1tT@>;F~R{{3Bc!?rWz+!N&WQ9e&xv*g!6_>4`y3eI)74$idxe}0$Hz*f+O z15$@;dM8JCa`2OMC$Kf!)g_P$&;Z_@cc5ON8Hip8K7j~Ay@v`oeci~3Y(eo88@y00YbkDRBd z?zF`rFzQ&tf@dA>KFsSXto&5RqIG%Od-Il}S6ra4tQ4af4BElfL@-h+isG^SO={La zj_s8amy&`7cX0e9qyv@)pfbH3(tcgU8DhXTdFu|b!KCo>h8%QWb}~<_;9m4rtx*mr z7;&`|63Lw`*_tAW=4PWcP)cTmT#1bVRRo*93HeU z(BACgZ2P89Y!ku03Wo+E+~FC(4>6Q59a6fOUit~YyQ|53FLXwWlV?Pl7Ar%UQH_1%u@xIvlel(Jz0`9i zW3Y>oOglSGaJt3Nl~C7ld6ux4*&ZRsM&=Y}#Y&O~{XT=aPpZ^Mih2p$hsqmw&Uj;@ z1$lUGrxM`Oul&?nhY8mn53ujXn>SIU+y89xS`d1`W=?Fr)wU%O$UqX-8i`P6FapbTe*a8(MHw7n0a(2; zX8s*MDVP4`W1wuODTovx(C!cYw!x)kx3PLd)uw}_Gc&m7V=q0;hT5o8vFya@0+cLf zT?Agz-CWPPX zimb{hg6Z%^h#S%frpJp6zUsl=9im)4{G%vsp^Z+9SiLyZILNEWX@)(OwqZ&cpEZIo z6m{uL0`-^r86>b-{vB(TO&)9&o5fEn3~S~V5c_@y>-B_l5ed{!XP~^EoY|d>)`wgW ztM9Vi3vecoa0SiiCj0lX-&X_{HH_v2i}xLUc_Qq~r9hb?{xsV{+-LxiMOVh}+XLyi z=WV8oOIt{BhJ7SHNZsx&gKoG+ho1GD<}Fm!vZ%F$?}Gk*$e4pzdnfV$SZ_@>fzTQ# zrFgWf=t1tz8&1TgU26YZM>pPp0#PJ-V? zhyg1m?Jxl*5@M54N2J!WOmrBtu}00)wX!_And(5$E)Li@fZ=}P0yoi%gQT|0IEbq* z6SVCr*~K-yDJ=qQUmu~VGHkvj*5QB8@}dC3FcslY%s!FbF&v4nVq$1N3{sG)lIBTt z0}aH?Qi#U^4@R0(T|R}|TX8YEOB@7fYKdME3&@67Ksd1PeU31+m5chr;j#p~%W_-Z z%{FO#7To4_`h;7EeQ~mR*F}l0xj(A~Au(t6931C6aaX(fw1ImK<>??kS%9p_`at6C z2x-)<-Mu;c*mkO0z~zs(z(x3hJwd%QR{g6ZppdHCe98}C)ebXNh3g3t9Q)8l!R<;?FxbL9ZcB{I+6WdQT5`CTJOLzd0Pc#*R& zc1}D)(74)ST6>N&ZPx2)E3GW<-^_9q#ZKbcC#&ij9Xb$G zV>32OTL;~cwQR4I zFi`~NpQkvu|Dj#TdDFm{jPS_AIoYt;nhygY>xegsc?FDB>bAklNO09U=ymQ7{@*C;dVR@v zKeE9_&}lXEUTV~PycIA^o%V1?TDx1${N3A&stg&*-0ZvHsx)fc#_&@KCW}UVm}1g< zUr8J9Imj3u#Kn_YEFoTeefTRH-n>-B>XsD0^6c=f4$42jh-wSmN=MimMhz)I*||f&PnSe)Qie zIR(%AZb%y3xrPd87Y`}pQ3gi}EF5K^(|5}*~RzpmUnKrTAQ<$WH0(UXrX4Rj6TX5|i;eJkq(A2h3 z`~-@ii?kdd?ULZab`<|`Oako4L-+W!p=0gxsyc)7M%M_brbnF(Rqr0`6+9VkIYv$^ z371SMfMiS(?9c?ai(2ff^L_9YS*2D0lP$K6LuWoRdlm@Sl8XCwjEnPQ;wOU`uT}+} zEhJ1ThAxmACV4D@2-T=z1fB`=Ln?SVLatcB+K*|9q0AN!q`bvPm!3``RQE;aUOFG? zzGR%j`|HD2YgR2T%2f;>!@cYQy?I5!vtj{Q=!|iy!uoVj%itIPCB~V1T~6_D9%9Oyl<-@FLzMI&hc0(1JgkRZN8PceSWdzwMXy}Y z5vN>$ei?(YTi&iIsFGzZP!BvNpX&jV=Qs4~RN7W~t{~7KO}wH|XvPGEc3DJIj&z>k zb_?$Yj#4K+{EJQb1#qg9<3akJe{tg}c9l7-JHYcPv1CO#I7+)g z7q8kM#*73gB3p~fiw`jWRMf__N$d^aENO>5L!R+0z5^Ak-wEtio&E)nqD2Xl4S?;t>rIsUG!BiSr%xDrm$OdbInuz{u zCcJo>o)hBgc}6t_41o^*_bXf`3}<55pBZZRvAw?y1h%;t3sOONpijsEr;hZ3eM|)7Yz$uzuKXz*1fY zF4G5lSr0BjwO|yTD$%Z=&%iO>I{fjOuKzZR8F4OP#S$c42-@N%)v_1Yb*ej?7VpU_ zRf$oETN~r9BHZPyC)NbSD|q%i=dbp_&-3H8m*nvk!kxSH?Kb2y{FIb=i#nwI zSfFC$86@e^QZPOKMMnhp=@>Iw;+AvJouthNMMf#vim5f#?dI}TN9FqG>ZX}E0l;HV zkzLv%`Fc(ylcd|jNZXtJr|;lUG#mPV({i6wHIcRFK4{6Dn>BPwr|H)3JL*2u!%Gnr zcsUxXNYTqvcKTlDbHerE4pPGxbn+u{Q|ciU-~$Rwq2w`<LREHF8&Do9B z2|F#}_lrX#1iZrEI=ja1D1)yWWQG(p^3BM#FoKDcz+PM_okeA|q*xg&snx&;;O7Y$ zdC9fN8y>enS?41Sp6$j%>eUW0+9F2b&k9F8IktBNa(w>be>{OtkK&#MoMl&inabta z<}V~`&yh*=qC4TYCr&rb);H(K*QBa}rBY~IhC>8sM>SXy9S5|hJ2`~7?xFfzXXApm zW{1a;3||=>F@cKcoV-C6A5aP+4FNpX?5F4^ni}-0=?Odl*W@C(tgD)WI~?v~=#hn% zVjL*3i!HprYH#f2dMQn_NzQAff-8dXN$_drd&(|f66_%$CxIKuhN0I7nU5Kj6&LIRmep7w1PFdro7KIZi(ak1Pg?1!hqR->c?Fbg(V;_UJvO%?8~+@ zzJ?m_h5ZUVu|Tix{OEUO3b$~x><<a;&u0PMB30++{l2Qkle8G7|I@?c-%t{EKb zW*Of&h9-evlVR&6f;D#*16ef~Q+T|fuF==+Ca22}JFTqiUZNEPVB{8QR-Pb62t$X~ zv@jzG-F#T!_h&~hk8wSMBdEIKLVDv9rDWSor3|c7X$BgPbH9R(vV%%0uemqY;E{P+--1$mJp2_iBsafNyeWo;8t!c}+Q%kI zM!5#=H?PwAY&m_VOCZN!8bJ~2F$=lXJQ;!_%1q+?DL zmC9bUc2kzHiY=Lc8UgPLW8qqm&@CLtJwzM_h`cf|E9C666BtxXckC}fvnW3!AVc9{j{p(4k{N1Vll zHkLCR7M)s=F4XnWWSAnd3*O4wF~~DOIEvvT5Xp>X-^Byh*|qnb1i2NBvksZu`Z?X* zh%IYC1#S=9i%>S(W0e5;+wm9(g|UiS*hHjK!OI%R2LeHI=^mOB9KvmTwjZ~@?r3nI zm40ya?iJeHFJ2FrQW>c>y3?^I^V&@*4&{!@4z_G%HLHV8jEVZ17Dy${hHWd(*{703 zgh%s$Y9*%0Kl4`vjov__cVIWU6^W}{nn=sGfw~QD{W3-64p?B3 z4*8x3EgMxwDH7#Xzhq%P>tZ}r=I@|?7)$jAYGi4(!~mQ3&U}Z278@Q znmWzVArzyTZxJ3AYIpjd$EdX=j89&dtHOe27^QSDgxd(^Esz|5- z1ovrKfQ3I3xSoY9Mi{6zQO;_r=lcH>^;oG(vgOs3rT5>yP1_w)bxV+qiDKl_$aQDQ ztlgRqj&zf_NZA+W_2Cm^8pN32=O>vJ>fzn#ft-c3>Db1RBQ|$Z>~PE2Rp>a7!_uGb z&5JmQip;*BicyO5tC85J+9U0*i<5=uL3+bmbk1BuN-((kF6&ZxLf~ti_w~Er)KpUm z4?zBd0D{P1jeRkN|1E!;`F)EjZ`#71C=J4N0d4+XhtqyIW3V$B7~He(6<$QL0sgcP z(=}C8=zYXv_T@}%$;j=hcf{4O{&ahNbr>EjV~#3r?choI@Ll3v97Y2f`NG|x_qP%S zC>v$O-B_7Cp3Lsk<$p{dYfQRE#(!7c(3PdQaI#EA7e5UXWhKNoQ>#EYa|1*-?O_XWXEX}>ZQ*jj3h0>-5ykR=zc=m+TsN^I;1lOfWK4pj#iS^&><$9$ z$X_YWT#;hZ2-FT<K~3@ zsfC5k!KX73R037yH0Yxxqa$pms2nvcixl#RF0~qY)I-LOkQ1DL6v z=J(?lR2Asl|p7GF_p*Ol596w2JHHwAsgXg z_PrR8Ztsy3(T$}ZHr}J3ybwQf`tDj^Sv9cG717x_eZJ6WzdKsP#FOgpJucxw-?db6I>hoNa3V1aQT0~I zA}(^*L8Xr_EN=UIv!AeAQ1wHzfloszt|a!WGbNp`Ie^8@ksKC`HGPIug3n-HN!AuK zDStcY%o+Yjmzo9&QqvBV)qG)PdjBDwxtBRM4<8}1F4Y*_vyqhhch_Nqu50FFV;%~l z*)3ADw%vNBJbm99gS0b%iQi3lk^Roa>7!K0Oa*}{S^fDHdV|b!a~CcgNu@tUOO{;V z-^h=hnd#MgM@}~NS)xrS)Qu!SA{uDE|6Bc=Sr$|qfar0FM(*Ci9Rdm?)h6G5G({nI z$0{?QA*3%q`T=^1^;?UJFR<{(OD0o~MD*BR*w|jU!eaWGo}@)hT9V8kYT=PE;^s?d z*W2AHK0NoVAnD@lS!PNDk8dI5)V;(<=&RSeUz2FbUgSmV&>LtwdLF9N_?2;)#Y&tk zv>-9-j84evHde#bo#V;wJG1_9UbuIR)0wH$m?93SKiz4;p?^U~}HoK)gI zjJE*ht9>vU6`t?auvQ)V>h%LH@T=UT^6ao6S2AqL?4Dix%>ZP?qkVxlqLILS#Kyia zg>|C>w)*a7HuIc8HZ)%5klwiUyy`_GsYjEoOn}WrmFNNWc7jVPsv^g|!R({8E_n%M z-2r`#-v+Tn=I|Kf8#P!5gB3SP!a4@Q41RGx<0sbx-KCVx;N!Wull@;1u9pT%ObMF%#A@$n3oMJ^o~DsnZ#0 zhH>(AQ|U#jZS`*&h0E-ccA00o@)bQPUhyT8E*NEXy(6CzT1?utbq{&9`M*o^PYaJi zdQCV=)e~)LDF~SXi4jRdKC?uswU|TQIs!l@M$id?UMkhOR{Cte9P zKB|ofoeg9b?N3Dc97K;oO`M309+Ew>3iojPl=AK*Sn+2oe9OWyTjD=3<2XEJ?t`SL zrzz=ikPbMMLw}KESF0q|n`d)-rP3h7&?s^ltkx_|@A) zku>_~gIn!f_eFLoU_?dd=Ew&Dy2d|jp^y8^>&0*kQO0WhyDsslI}z>Sw-@a(Sv~h# zQy>D+Z5WOyo!fA0Dbq8lAAQ~FZuXH*J?Kjum9H7l<{ty2h|6ztYb`x)@RPhlr1ydmj`_*{2j$^!J_CEA)GFyM7f%~F=hHApP zZ`vjg&xN6u^cu1kXm^u2{^wgcU-4%1XDYGdMdKI6#U2alt$bt9b!bY^tfcKO(n8xG z3!4VRU7@woBN3(`UD=4uhQEU--j6e(55it1e7bE34h5{0`o zZDa;1$XKsck3jw|^qo~9({rupctfzF6HO|m?d?tGRWn>9Cj^k-OE6&_ z+k+35ajO}bn3Y8R1dB-wz3}iISeEppBpjfi{VDT6@$dnid7~W#ne*jJQ zP(mYcqA~Ot>wa1keSYW-V(8ElV8QqhLkSCoTK3cD8H%v+)2ItN#R3w^SH`0FZYu!1 z%!&NDIXo1`7*+_mqP=?BhPg{%L9R*NNN*=x>seOHN`+isG4ehA#!Kt$Y`m@{`tI&-* z{RInt=VuTxw5SPn3xNOULR>eXG z71B740g5(OAVcBhLB+6}hnLVx*VIE=_4ykXdJIKB{KpmAwvftN4go*?Ar;HDg7l6RCt@zD z(tFYIznF-HZv~PjFeg08L^nmcjqTyo>}Kx$ZNOO6NXxU%lULRcE)O9)xl;Ur@XsBR zx1QXuTK7h&72%`R{|@H`36OFQ)P_#1I$i7|V0Bu)g2RFXH@N+-v`(@K3so(o;eg(L z8m0wy9D{t%Y}KwOCg;KI#fdZN&*WoGTE09pVA60(R5vt)`7LeoTkloG%mVk6v+!wA z2*f(vRRco&3f^5s1`AYSNP873(l8MfceJpUf92u%y`AoX>*RY1Q3}uw_PN@fY;$qq z`Ifv&&wa;PdA?%6WR2F>C+Jqpkr!`0rdZ^yv}$MtMLPLTQzN8x0dsHml#jxX3G+4N zI!<d#pj4cjvlCt=)7f%bMxpRihfZnc^hqrh4P$!@*oJjnokD2LJ zPah}+_zP6;;>W~_=>&z{x@*jyQI#+lBeS)3>v$v4sed6ic?}HI<*>}k)Ri=M_KvVU zJ`vUNvj7S8yk7o-XvOE1=ms3@_EEfvdVfJ3*BfC38-Td$pE6#hgZBjSGFF;dyeg|X zY(kyG57+My{8wdG2r$wfzCXoKCl)Z)RQS#eCDY-DzS|^y$%!i_dD==3u1u#}K}jv% zKwF19+{j9XGPHnTasZ=*ysbp=?I?(t2$9HCmK=3GZZz7y!n7D*?9VMM*<4S=X)i4z*jdfpNlN9B+z zuJnJimx*bJ9wmah?RYV#PB2|m^~|Mtjvj=Oj&%eTa^BGcx2+wDUpTUFANher>|hs8 z+)+)6LnwH!ekGiKUQni@>A~K#Qe_uIUZ`G^F<5jy0Dej5NfS)#)XuqXQ@L4-tKy*5H%TiB`kUqf)iAAg6Oh$|sKk|Cr%TRI9V ztPWhBHva5YEI05`TCK(2tq1`}e?hyx*?&U z0!Gs=#9hSj^M7hI9D|QXO8xkXrZM{$rV&E*KyC`D368VCk=6dT5p6Ct4D;PPP&)r; ze(lzmp*hD1qQ2ILYX%ua1ry@0$Zjos?<7Sy(Q4DW#&nGETl_G+Cv~N6;3%gcvyv&+Q_JGmQX-j`0-OwW0sB!L(0{+ip{wpTV zk^)%57oEU81lB1XfRZn6jRJlE%?5laFC~vC0Q~Yb(1JQ*Ddx<}&XU5NqQgCvRDq|u!F@SC6FAuj z%Je^=PJ&Wm++P-4qZK}rDWJAGwFDYm@1Ngq7Er%SYO$uCR4iziD@le+*~7-T&Zl~r zeHpu#CPzPD*u|-SuuXMz`{ORM@9Slw`|e|aWXs^QD%p%v7^7gSXM|3SGB;Q&)4{XI zvJu`}$|%L251a88K({c+xW6OCYMi8{Go~h!G2}J@ewDJEJyIfn3%nbxQN0s@XN-nb zsjpBR)`yOM4=L>gHC@YUc5zm>!ue|g0F^<@q z&wGT$WeIF|$jA7X_H2PLM5()t<%0=M`f@oAKJet;XqGzBWJak?E+uXF=<7Urk^WxN z+YX&;*5PR|DRiY!Q;zo=hd`Aj&;`sa;=>hZOro8~g2@4uF5>{9L8~OTdd)^&N0S)4 zBj;hRVhidzEO<#~KmSA;JvA81=gky?ZNR6uk&abg6lGRLLE15@7`WNYUKV?~@3ST7 z+pp}++jVr9pqqJuD!foH*Xgz6T-6NR2NM222lAxxM?72gC)jU72S`Q9)DXU+kmcw5 ze)%_2F#l0Ui9n?Cs50IG>phbg>Fnciqv@~diV|N~+s9_5rYCZ5e-S$16ukU3K{=JJ zV%S(Yq^r=OE0N9b9N9>)#DeI30Ooo7Kl7TRTXC?lu)UbR6UFSQQJQCNHAapd% zyo-GbV&rxUX`v14>61aL+4!$nYXBj6QNG}Z&{Hl7<>r`JU~?a9KICc4{2qfW5j|u( z(;c*BCTwR2U+7<_oRNaoSfOt=_&qjd>^*7vEx-xLSvS_?OtL16>H~fw zS&azqOEg=%i#_cgthO}h72;o3l`-}Bp~?W8`02Gqn3}0~DKfeuyyTqF)GfCKRSpJx zP>#!N?Cov#>GG8y*iPYzyfv@4^9Uw|eS56M)_=Kt|F(_xFL{Tt1w=x)MYQ?(jK4B^R4%>;#Zcj6Sh%6+O)1=jC#^OV)GQd9G?ek zOw%M}teBHH1pSd?w_BV+MOuqssgPNX#{4uIagd{%q!H)JGj_D&s=Ef`E4pP$YbYj* ztaBatW@GzdbsCfEcbhlHHxplJ1EgKL>csG14IxKK$G>Kh*&?y$9^-~6yl-6xoOq#; zFrPsmV0?Ru$4pfi%IjC>8O@1L@Xu4xO7jxLp-eYwwJ(;I_@vYLAz+(?hYdM+H82ve zx-!3X))RdR*^ledFZNQ)6z+Pi!N7s5@<;b|JGC6mh8G_q9T|a;4v8|WRkn2TG!EFH zf3!bIDSr^nm5iqf*`G_iMTGZ_xHp<+4`d2-58GY@O})&Vk2CLgD=E9A+MsdO;G2Rj zjE{qi28f*z%_!8*xSIZFcG5}Vo7Hkd_!*6_AM3~db98%XngjyQ% zc~uJO%MT+Klt9~9;B0l!Mk*XpE)I0^6D1E%nOnuQ`fsDvT*8ar2?Fp>>=hW}$gj^f z2HfEqLZ%H5?&aJumH$6vC)QNY9>b?<8(rx3y20um@j%&z-gD986enaydE;BR4f+Na z`QM=!64>J|fFa;x(pc`P)pc-(4jR+=N{=Yr;h1x?e(@CFR!&*+j(Y6|f|D^Po<|8y zbahJa;zA@s$nY~FL{UfVt{aX2ZsQhW*M8HH??djo4E!DHq_`pyNxET=?q;nIN~tHY z&cjsVEZdH_~kznAQcg z(X1M8u9bfA_o!tO`L&~`0FM>B%g7;er=xXB77$IjI#>ksZA2Q4NyJtwg*q(WUL)_@ zt*c(8NWmKZKPd1JZ3+O^{i0;3Kpsvjr;zEq=MT9Dh0|vhP(3|C3|@!Kbpqn`ndOn`qeVtQB&+Zj4WLtJzXM#< z_<0LX1LS8>TBpfN-?%F-wEk`F@z)9M%vo57B}=AO{2oM>*?CKr`S0@~TH*>Z&{T}xdvwnJ}{zdT^Gtcp?0XAMV( zqB1aK-}x`8p-ADlwoRI!F`oe>>cPQRAjiERtJ2toJ26%eh)1u-D8%J~zgFw~ap3e~ z?^Q@CpaEG2&VFK(gb#SD9ERSaVw5{H7den%XH~5OV{JZLcLH_b1y7*}U9z)p31Kk@GEDdaV^J zm?tbD9TQ_Eq@U42Pm{ctp!}>q3M%3+!{ME_58J_yHN2>_77XS6?23#%QPXvf8@fEo zk}}LCJU4sot7pWnJqbNheNw?iLW&uAVY(07vI<|My^H!s?xhAYvAaDfR;Ny-m0;fw z<^tK<;cZN^SJR2%s*qH9Q><>liQURH-~x;pwkMF#ajfIiIlC8}5{h%wI#Z{MP6f+y zjq_ItlSoRb1v0v|&n$cZ+*kaMdE|0B#k4*JqDZBhgQRI9zq=5mBI{1u+ zNw-69pQD$GZNl&d_V&E_SC&2z9of$JjX$`c5V&$MY)(~h9k z@bOz1mC!zJ#k1NxO<+Z(UDF6BSd#x1YVAB=26(KUdf`$UbC1a4l=$yrw_Q&%kkjgWAvW5U z*v6MeKr+scrsA65V6b2VPz{k;!`_L;bI$-EQ~iRi51;=9QfC>k`0VYuI_EYKfZtP~ zpS(Pmj|~X;9{HJ*=@+F~Di&_87sXh08T8#XWPbJ^<8UXS-+li~(kTI6EG= zuI$fA<;QAhrsd2Ni~AVie9tE~`u*N-gt(}^RG{>_jnJW6?B#THhi3!(B#QiByhx)A z7<3G7LN~olRm%uC{EE3h${BX|dhBx2q^ItK^_G7X6Dr@3`pX0L=>o2`O`Hwa?3w{$ z+o<9^=eXJTethVK!a+Y*M@f{%N8)wDLY6smSfZ1Mg3~#n5)WZ%33T9Hi~(}#nN_`7 zueCWXo1P4XbDGM*pPGnVHkmD|zEY73ihVcDJz5H0{4raOqpC@#+PiKEv1TFbeHasr zLCdna)0`Cqyu8cAA8EC3=jPV_gpV8hDyB8za<4`C_)ES9!cx_4klC^L*GTkG{Vszk zE*y7TrRUHXU6Qn4&sNX>Jx}(7Jz!fZPxG-#uKuu)%UevxUZ7^gbK3u z_5Er!3V`1SAo3qXe&8{xD~8V4jl6Qe?sxQ6vb0W7-OQE0)t-?byl4@9`a$b#QR$lh zO5Zed523rvI(_NiG@gFowk}S3GV!y@N=sa`y}Gbw9u9ydSkye>d3Q4_VAbaLG0wI6 zw{$EQIj4cb;wsnoL}NYtY?I+HhewX>n`USlR!a|Ct+GDw9#WV`=?pUr$p{vgr3K#= z1}OAIL|W*vta<2a2<5;VrNj?;$vMlzlYQHe@TyU$+_@L6{L*ILnw^uBaE|Dzqek2s z3+texBm$1hINVc4zV|A+3R~)~F6FqmIH*Wp<5cUe@>c%N^96DU&O)%5JFH(hjVE4W z`56rNxJCrW1brE`YQ48WN91o?Q<*cee=3phy1qA*@}zjK|9O#AzmhR+k=Uj%mnK?9 zY`?}RV<{OA8)X2T$65!Ij1Z{ zXcXyEj+^zfsCP{(KarBJjY6d!r5PX&j~FkvbHMb;6*Z02F3Cn(tWExfWQzR48hG7) zeiwb5I|>fJ<*Qq2o*S2T=!JfI7Sy+mO7Q)zF)*dHW|jG;qA%v`tNvhsV@%x!i!9L0 zY!Xl4irW)@=-90=AM&bCSIKyb7k(eJ9Fcg)0&7)}erF9YjdYg~1k}?=q2|R%kvfiL zq>Q?>06{;1QToODcK)EhmVicVUOd-EFbpw73wwyHuH%{3E=SQi6lDQ38JH9v8g_;N zUimszcQT4Dak#wHcYLGw&E3hIYj9va4YrI6QqBARi=IPE zKwt8rkXn*{7ST^C6bi+=xHYx*Z=1ksfhXa(W4Z7t9}s8F*-oowtQfySlS$2t#k36ZFaUpJmGP@x zg^5U7RpvXjQiWsk)Cj`iqE}%iqUyPP$p_Mps-ON@1y@EQt_uS?m$ul>D)_;ri=s*venAu z$nO;YwR)q+GcMm{Av2_;U)pwDwT9G%yw{fpXc^f{SA}_O?xt3u%CT1G~b@p>{&EI zjSZ3+u_r{B!ZO5WC){74MzW5-i!BGxn(|6C^2*h3vJX)7S1AySsO2}vn|;v$O+d20q=3Qc=iH{R>Uj+N0f$-`Q=N|ZZHFyyK)IU=n%DzRnYHCX zZ$|#7DQ!8o+?M9Qy%g>_?U8WrM6sg%GhwJAG&TgOr^?y5R>apymR$*nU76HNrp2`< zEOyDfKQUF=X;I4H3Gas_H0WzP)&lE~z|8f=T+$-}PDy{1KeX8dHe~>MM|_n-od%{J zpk-7gPU2+e;X*pt-L%x1A4K2(Zv>CFZKAfQ^mOjq)zl6#-%oU4>x|fE%$?U77b?xFN8By( zYSMQ*2!}bxYKuxTY_@Iw&ihv|O8O3#eKs6gNI>mCMhOT2fAh6M=OzGdWZS{_CO{f< z4(G6BO0RP){kx9^^of0G0|O(^{`qIBsbuOxN%H3>q}@6FHjjTPESgG$F&H7QO)(aU z#~hT@b8s&wW-#U^VPv2;0j4==#5*e;1?J8jlBav z4|2k>B#BvQ6lnOX)`dxER!R>Zdj1ovmX=!D8pPoGtaad_2X#i#uIu#q>Ud@dw_-W& z{k(MUn^DOh)3=gE-xUSSd1i5eklqX1SB0}SbW3~H`AI9(u0^y-F-ABLx_Z!Oo(rK^ zmRZ|Ve%hGBg0nFTeZ8K3Twt03^!tM){a}o3pUbr#MOJuT^M#)@Xn#`>5(G0YsvfWV9V)G-wk;^=y`vu)T7}o*~j03s5O5G4Qci(s(pic zynq05<^$*VF3igAZNHncz_0JWApJX^=tJb2HPT73%wF(s{HyEP?AHGu?ILg=KL+Hz zUe2nh8B5c)tFEXbv`sy1UKp-Ubm6*h(Phl*PgsQ30;Xa8KhJ#FsiRb1QbAC)9LNg2 z5AXrOnhu6^UsVIFlU*GaU7r55dx9dk3B-`TLaG4n$t8Z-T9K+Mqvz#b$XRO4zeIV9 ztQlUOL+^2Vl9+Oc=|PbicKJ#AlpAM}1PcmEd2nj3%~{YY>F4*X-+}i-!rkDv<#yF) zpM0SIKQD8?@a$;i3wW{y^_W>wyP&X`jei#I3&i0cZzZPT z0x?C+U8(VUK)vUZyPdn%>s-G%>ZQzW&A`|2$?1WB=pbWJADwjVAO9J;zws;46j$1v zZnBI=r!|VEcL$gR;=Vj8(gjc{SAibmiisi;j_B;iYyOl3wLKJ!fsA&{c)ss`BA-A>U!BceshN7GolAG8*(`=ub;KYEG;@+jAjFQMrY zksGIoP0>iIM#W~i1|87P1!#LWNX#@oX#*n{Pcr^YuM*O&LQ6iuZ_{w@;2gdP+xUfO zR`Z}Bx9c-C;&W63@y2MYO-T4wx}{hofeq){3jq!rVqZEaaWL}PoS`aRE3o| zXy=!Yced+M_d=B_b>LN)3TOaonu6?fkY?O^b`@eM^T9s=8kf`TiHOBd;)RW*kj!qq z*9=A(+v2$EOTLx`7rb@t)6JZ6@$<)uxl{VH6>}xSsZm4l@Va?%fYCmsJ>9q|E`>D) z;`k(~4oa8Qdd~fUsza+u(RsV$J>JF=u{RC3TxaV}*dND*C+Q*pus>)#l=UQ^dLN4o zn*bm2*qsC(3{w{(d8c?(q3{V4&D?OTUK9x(_l4m5z7g!i8|sm9^$ae&C6M>;K4AZP z(jnnJOF4xU(5_jcKN+m21O3yt;pRWvb|GpUg41yhUe2H``L~>zB6-`cF5E>YPXPcOvpX?Sx_#d+0t@%K9yMXS*k&?;WhS9BCH+9522!ls zybh&7hG^731?0rwt!~GBv8D&FwuVJufyHI$+lS*i-rh2);a!OPMxxmDE`GI$ftE!% z2%na?$fHG_zrN&dlh2YFs3DByzIlz!{=j5*`ujf2M|cyGBKsk@*(}`{MAU`&C|tjy z6koN&($DHLu+?enKOGpseKT%y!_e;BBN0J@PW8fsoza}g3DF`CPhCcH-fp-1RR&5s9+7W z95^=awMWT>BasL1<#>aw;(Q554j?t`HP2w^-w>pvFb!$B8~;jc%u=?7AP*wDNjriK zzCHAeF`+dT5$v!nxA69j@fJP?BF+q( zeSL~@($NM_z@8arR>?swTxwg+kIgB{fTlRuFY0mX%`5?tpq~NWVu+KqtpWX8DiNbH zGb41^M>S{oZ5Q4v;4=dCLvUajhu_;(q0E!h*o>?CXnY!qe{B14RmTe)1x0zsKR5#r z{V6~hvaq5c{O1|$$5zGQv3{OKtam?`FkLyy+8RSy!b4`@xX0_M=mxXAb!^{XVW<(X z4#ICm20L0E(ffTGRJ!1madR7bx_^=(iQse~`e&w7aolzRavKR>bn%gjZ}2mV6|4j| zf11F6_4O%r3}pBfOm}K-#l9?A1I!%Jm@X*bRpCVerGT9b&21_toaEj`bm7UYc#L?K zgdd0sZx`)5J8s{)_6TJZVLBaz0{g6(%jc-P#b`tt?K87*nDO02QjZh-V3RELdj zGkQB)72KnR^ZK|KE1ee#GQ#zHh}+urXyAoLC%1Jvyt~8A+Bq7i9tqb&6fw15L+o`> zP_3ZmH>IS`W{F&fXQKG*xSa;C9cS-CfIGN>$J=<#pB+#N*ckhnnKO*kz#89Lh3 zkt7luS%WenjD z^B*4o!u_!>zrdg@?mIwP7SPKlu)0FpiTXX1{hCi%8#C7c`^vluS7cDyvFhbBiim~qwj1;Oq^3-1>GLOfvFzn&bpMPPqR z(`7?8wb()P3WD?B7e4mD8ku@LZC^Po1cvtu47;5Z%t;;acSTEF@P;~uoh|ppreVI zfWo$WOBH*ZSo2t{wBz%kk^e5I7cgD82QG%b;bDaAawux6I7!k36ykVManBm4KCg6% zWK!#AVPdYYwnsJ`tMA(Sg*vF*dB^BcSe8ylE)-%H{n=Y_tMY@`bUnQB6?Ex{ncGid zfwG@9G#51PsTgM+xq$vABWw7j zPdvdqc>h%A<8_y;9$%J9cYk)=m;n>*9xp{-1F|ANccMlNTVclNOLT8YSRcN-ddlfF|j`T-6K!5~brh_Pf&rUdQ+tPIex4lOQR&YI z)#wiC>LhQ3tepIN7SDD^noG;Boz8@bG1uC-QJ>%Quoy#P
d#whV1d6<|OI503` z$;i$}aHOsmiUx75=o}*el^rQnwc1OLTN2qlqraPQ%}3+XiHQ=if*RCBqYn^0*7w9U zBIS}R1r_*Li)SphS$I}bTw-*G5Icsauf!ec`Q>7k0D+TY?;=IGUHE`=MMlR7U$i6D z>8txPtOD&ax+tv&?tOEftj&{E)G8r;coFD zHd8rdlf-z7ooMZ!Q4&=T5Gf=v;VtzkY0zctWkJMKV}=697Ltlu=%8_bpc$|EuzyCz zL@1sO)A(L{f62L$V&g}HHm-x`tcNjm{r!O3!R3;6(& zP4y^qri&b_yEX1v0&unpd62XG zw%uz_kw_Sgms$}xwWHav4u#V}1KJpvk2_#~&nw({-wIX*5Z=Zi80=!@qC^)Di7@D} zl@3g5a@mn<=3R9H!96Y~#R|_pXqD8?G+&FKMVlcTq7i5oE2}yp;Ul)L3n`B!cHg=o3XoO_isrubVj8it%lUWI^YgFiMqo_?sp zGLg%8m%4L^a+*X+cY6601$km@mgUqZePcz{VMjJx`G5X0oJZ!zzC)k!>+k(po6q}> z+ywH5?y6YPW}9;*ptihQK_$DUv^<)W{F`^U8xnc1{NY!>Zr)qL6Xtb73RKZp!|D@F z#jUOv`4tVRb@LK7kTo-8=HXUREUrLArycnpKnQrkm{~lnYlv>Tga#D;Dm9K9jY0W zS6L1dw@P7Ytb2&sunsKzJSsq>l;sL?zp2&^_yj0Tn9{i9oj?ni7z^AT2ZgHrF|5qv zZmRH6Z1$J(4ZynEyzPiuifA8w*0-xw+WO6VhAXvA?1(cs5c&f3!slF3%33S{+d%gAfqpeLSz0Wu3+0_ZRk?A*^T>(MF$wSq%k$EhY75(}Bg?V-{+S;Ddr`&B*o43M$eG1fNC?RNTWfB7 zI2ON2F090o_^&m@R~6IvQn~J8tfeIh3lr4zm7sQs;UgvNJTMOSq8tzw{>a$Ow~86h zxa1QL{N3Z{4e|D8ij>E|$lRt{@kCNDh^JJG^lg&9!c*Kc0NEm&QQo&Mtk)|a8?%g~ z4i_Af8Ti`OcOqybI>woQBw++H7-B(JI|1F_AQ$z*OP#QEg+y?h1lhQcG6vLSmaOc4 zFj|-azS#UG9t$u)GulC^0^Y2Q54=22yyTkgby>Ph`&I;jOR_q*$BI`HR+{>!Zr#K) zo<-c(5q4roC5+v;cCx>St;wJP=m-5l{lziC$U{FphX89G0^;5%wcq+kb;J}#cTiLp zDm8km1%G|XljR}9-)$K*1=GCsKc9bND0_Z^C3|b9Vo@>va3pe5SdEzF=iWoD zhWqw9IB5(7^jj3(oS5;i>;8)fdH^-rC%^+dbzgp6FALl^Ml39ks8`wQ1LMrJX|+oi zJ07c2?#xEYU*c);dB88T(M3>>8PzaaPI*0{84412+03#?#)R^VfXJD60s+P&^1_Mr z{NnT=J*`j7aZMXl{8D|MS6eXa(rA{DEz`xkcFwB~uMZf#794T~-M_%(YpSN(6{0eL z&#IB$4Q(*C9AP_-q{u^Qu(ZSV$KAxT*Tv<1X6WE-7*DrBLb{8NibsZEPg3vX1fMk7 zM1UxM%+DCRgxO%A33A(Hxix$F`(ce-OE8YeTA%L5m32=sR9trstkK?gyh6}I|~F}H5_~HYd*2##*+B<5#t$Z zzRKvaxv@O^lA&3%&yhVL0f`ARNo+1O8n6ez`f^est!ZJ_PB&Px%!-cYoMtq!M_olLp{$?0znVD4ue+vs1Ma>sr6PI>Vx_O)QjN0 zvP93=G#LE%ss!iw3N4=D68!;ruuwqJ_z*9=1i(D7PC zAcU-uwV$`NR`7g!xnZ@WR&?fCEpwe#!Zv8y@!YM!>qr6ZnFx}tG$qL(e~ zD40r@Lb?YLQ_K%7YBh~u-xA2d&FTSY`U-iRlg-y&*>j5jyV2TghjE8&lcs9G1v?`L**JN7CYa2BN242vx+i z%ocWMilOVqI`M=7Ew&sB7gDSfB5L}`<^&g5*HYWlgo8;Av7$(0V}NJcO%Ftv)x?ln zU3>u(grs;9y(f*vZZXugt7y{5w{)+kTBS&8&Efv zp5bj)VOJUl8N99K>@FfOMYwxHIXQmSIvit26WapnT0IzeDMzc0PPy8MBOE*7d~{k| zh0X}7CYlU|Q|#a4rYw-Ng*#FC;8y*W@ARes~(UE3Ha+xaoY4c`2Y9 zwkCVt=$M~+usdt$X^9bv8a^>Nc>+n&VpI0QQA~eBy3_FOOb>Tb3*}VQ-!V@RB^1O;@)BIrB7quns z?|0@bx^+XLKt;_K(!R_e#r^H@#z@(E{H4Z}Yv9i^cfyy1R`L;014Af->-i07-<*Tj zAFQ;0g&&k!$T=n0T#qVu@_Z*3ya?|jrvBA? zj@sbUMmE^O8!G9hK znJDQLq3A9}RKn09uq<6R?)WPS%4o?Y5V+@#GC);235dslNKJ8pKTZyx@FimH$P^{V z{e=<{lJ~Ogh_wOmbQg{KBgswyVs%{s?%h#1hIKxhy^F@XY2UB;EM4hZN?DFGe)T^n z{xR*ZDD9U^N+7L)_9!_u)|INs<3!EHv)jpY#87w(F6UeYrs3H+9BwUHR{QG`+@>T; zA4r&fJVNG3Q%5a0M;Cgk#as>v@B9I}sWyJ8=7K}U@r@4LCW=b6u)uo5vMTx@E}LC^ z4$!;Gm&5hMX6STlVSS<=pHq={pS%A95u+8HhtUHTh7KKKdzvAsDtufx(h4oi=B3Ts z3-)}f+88L!g-t%}I%6Ub9ytA#xVO09?_n5$Y7(#S_(hm*%&P8Z>KaPYzgWIhVE655 zUmkKZa{7docD#_Swvj~13~I!o{Mt*ZA)t~;EC$a5=luTcQP7Q=_7T9u ze&yz-{?Rf&bhoVh$IY>O^+r^F7<-DtsLqpK`f5S!V~Os@dDU^T2D^_03DG=AWe?)^ z)@gT z^ZM1rcj^N@9oaI$X%$B>c4r9?$!ii5yH(fdhR1l8U-UD{$%TWrfPuBKZcPllZMaiv z2&WaLEJ+!I`7d-(VsL09=(=z)Bwq&>JZ&X?Mq zg7;C*OT%AI-l|)sv z7nSuy267!!5VR1V0=qMt5FIoxyF4u39?mAJ=OP!~5#j8pGSWkvz~*lSE22bdxs)16 z6ROe;h;V>!fas7&zady9cJTI*1GTUe*zPL!gOD`~XQD!gr^lNv*@5)-a~*tl;50LR z?ZfWh;dV)L@}<8&z2x1eS!`Na+l+mkJbI)#+6(H1tHOP@0T}b`NPSK|?vchHZJZ#1 zJ8CZu=vS6Sy2*@fgCt1a`cpPl_*i4*TDU0jUCif{@sW162EuMZ4+-5RBB2Zd&z^Bh2<4a^0jqq@}d$ zjx9w%29PkLIgGsF9ul8jiWHnp>-Erp2uATTiWWHrt9`X<;iIn9|qB2*#GmxQiF^?Z2Ulqzy)f)xk!D}&)gWsi?1 zYMrX!SE!p6aH0PDxbBx0b7+!A>(`i`3gC1#Y45+9Fk8kY_=kJD{(%~Pb!`B5QlLNi z#V4|*qIm;{-PzkgzFe1qzHssv0MmGMkEZo=oqc^mEoB*DKd;R86$6Mo?XU;Urm0G) zZ(E{%Wq~Mjm%(*itKL(p$n?ey&5~e^7l5L%SOX0^4RD1_J$q3rKfoUTm`(=fy}1Kh!(baB=l_{CGGr_Y!* zdF0mqyVLJMl4%obaO^efWfD_)#OqCy06)3x$;#w938V#EwbeQ(EeAv9XpCY7=U)k05mm}W<+^`Cz+SW>j>Em(gAmNl`CyTOwI*lrVG z+!_OWhL>SLjikke#y2j?IYDB1j+l;9 ziWA^i*^rec0h5&DB+ed+0AHdp_eoHc{|pqxQJ>UfZO3nt&~nBTNM8KMGr5srBcqK} zEAMi&)B6!TqmcwbEWVc$|0`3`Jx*x{yK|sMsIZ;cH<4vBRbQyxBPOsT$7#)t*y}35 zoF$4lJ=@iPJbQAN#U#u|%~X}-P^uG4qWdX?h_GyyRU;o?kU2NFAyG`$vR+6f#--3! zZS+@Ix4-`l3=rGZ&uo>pViII5`A{=|<795AfNP}En;3v)<<9V4$d}=5Ajk; zd}v987PE3cfT}Q|wTU?IDfJlnx=?cF>~k(5CaGZY5vk4xpjs}g9_1{$=Pv17h8=Jw z+T5*S3fn_#7bMc=VzA_Xy2vIamxmF)j6$vo) z@SR@*Fk3N1aASV%4$j;S@>uxsMBUj#OV|Ecy(7RPO;|vx6p_;%sYETA3^Ea};xChQli0yejeo7X6h51EN0!Lw?4 zXIR-Oe{j_r`f!QqYj?Do)||SL(n*;X=A`hvB@at%OblatjUD|jbwW=uNR6x`L4#w@ zYMw}y1?0*;(e7@6L<~*1R}aL(o-<4FL&BCwI<2h|?ym#}JFkq+a1T;oHRUQh2J@^^ ze4q-GbAu5x%ll$|dPzR*(ajD!VYOACLREr%GiEuS||7cWN zf*r1;Ud&P6n<*gwLz&<0t0q6xX|%MvHyLk@UCwnL=N)NpCiwb{n*TDZ0j@qnnbKCT zfH6GA^&!I9eO(zDn@*k+Y<%F!Q=D-1N2_Nkd>nc2Sif*u~!qY;d8B54CN@Wq$^i(kk z;gjW4*%!r#a5vCgDNGFnPN@j+V546)cOe~zt$j)%-R3{W60Z>Bc#3*+&Wd^(m$JXb zTlA;d_7F7whAHzs_@Kb>6aOP(FCHR_IKEANgzqu-V;dJIiZzFV5)L<5(igaD6_)Nj zVh8!xdr0v}0QMXkTnsa?8q=*XciK75^3C%Wr*BHL1qYDcMmyNT3AC(k{8}}fOQ8ww zp=LRp^uw@b-+3G!JZ+I>qnd0n3VQX_6xiGX_r!5ENM15P(3aJd;%9!z%Jv?$*)qRf zTG9M78)97=5qa%?zqG(}p4T=@Y}@HWN|ScY?89c2<0@%31?C)Nf5piFXYy!(P+)3X z!6)ghq@y@>Y?mD?{Pcz_vUyNZq1V3&{msfYu@aRQ2>tg_QeU&AL#K$dMr!T~_T*iw z=(~^3h~g5K>=LtCPb9B^l2@dgXoA#vzV9>47aK_R@2O9ICRr3~^+4q{b1Un=(*Gg& zvg6Sa4DE`B%;t#R?)_$SwbI-~RWZZ{B7VOuO>{0K)iuyTj&PxX7mD?Zg3CMNt}JM6|GajK$z(ESak>pW;F7M|ITLaAjS8Hd9u+o0|&M*I(mbbv^VjC8-J zO=9IYhpsUW?~qsN-F``KRRdj2-_Wlfy9l?pQE{q*#M4x zpiS3AYzGkS3xy%x`{VH$T9dbs)*{yyHQXjM;%4bxloy;syQr_9D)3`e)V-@ixJt#Q zQ2Lm(r1$e}<~+W|sjZGh0etX9v;!p)s4XR|=+FR_)N34?Xn1v&WpiPH%=rEyi}s!e z05)FfKbk!OY%QC9H)9NPS)9NTceoA&S|?_DFkdQh+A5*8QgTe-^IokHvTcuP++$R} z3}4Vc8|u?Y_8d_tL`Ekc>@0zmdvbvJIx98&Ewcysfj7;@f6jU}le#?9*P@|WK)?m~ z`d>z20T?e=0sjTO&qEfd{}T}<-Lmu;&M!FQ7#PG6@9M}ciRS+f3yA1pmW^>)Ufp0# z-Lv3D#sMKznp3}FuT(XbuZdOyLT|0kqW1{A6zMZ{kaV4mTyb45a3k^6LR-s=Cx0JF z1J<%tfL{cx!z8kAm$7X1G{h>Mb&`_abHw>mR`UZ3Sl`^yD%8}{;3lzbkXyyk9a=eRaFgxyM=)%>2t4k1 zJ0X1*eSiupE?r(p*+$^Qqh|V*X3xsg@)q+k+X5hX60EmNlAgNpJk*?uibQL!u4ux~ z%guuJ5QcpgsLQQ|@rE!*T@TL8o@d99)m*I^ndDH}QZAF89>h`7H`H?{czwKY6z%4| zQ&Pemp2Cj&*Cm)4X#%1mW6tf<+U&P|ONe>qWi7@GHKK7U#{&RWi6SQUUSeXH^-g>7 zY~I4@yQ!>zARS4XwSFh@Nqdfvt#!YZnYG@%rafa%u`n~9+M5CfFk3+{`-+Gk{%pZX z#!c(C9LJ$(KeDEfl5?P}SuM3}KxFD%>}_f(^ekEww7JcQim3qGd~hhx&!NNmn04u* zVEf@q8ve6xH?r+ed6Pz4nf8El^(u+_zBvyA;%zf>+YCZc_sbEz2NbSlLvb!zB}WMw z^|0}MHa)Uz0NQdADx}RTPT3yR;5CfXyxqw1#ln>IHdMFF+G8pKdnxT%#lem;XCzF! zTEg{?{t7)-gkP5*DyFEh{)aiUC-&Jl|0Xf*`o-x{7~lXeUjAg#l6YAx^PQm(vJh;ehAOUA>PyBD^PmGLo)sAXg zak&?&)bbCcde=Xrc37-!KTt5SU_)-a0v5pGGBbK@uqArKJw+OQ&_v!~9 z5H|6lMg+9ToM9Vf(;ep7y2_+r;`Yq{eZ;X>V0=Y_JM{UiL%xQc{8`KrG142H#!* zbR94j(X*4EAd~GXG5H&EIlOhv1H1Vwn=F)H0L=5~J(Q0?_zDes961oq4i`no#9Rx^zM+d*wgrporuirk}$mFYy$eBG61r z91z%IF)j!QJR*s=kfxxY8$6pRU2e=yZctBl1Q1(vESe3=c-0-v1-9GA(+$Q9zF67! zd~S2wxr!(^u?pWO=$w--!?bL7O8K7sS7$(A+$(xt(niG1JVecY(hCVY3jZ0uwp?Ta zJ?liva-D6ybybp*h=kKCh(RlW+08X>VPch|8Evp-#U+e@glFC}ZPhtOjg71TU`JPb zQu_xN&@3GF0`o8REWX7Dj2vY;@M7l2qjEwLAb12BgttWuGp;L?r z9=Ykfoxi+^lnd2}RSh~>&dj+y+r{wPg@go2o_y}9hCeM zn9~Rnxv3T6ii;4?mb5Yjw7UB>>2s%GWpr-AvZ>j)V7_eUH8~y2SUB1`vFjrJhTG9= z670GqLtJNT*^Np>y*{V{i!0lchp+s2^7|>N0ArHs|65gI#+oO1IPuEt0OfNmu_I$f zhna*hCuVrwSMpbT6*_@{Ve;31{$MH_R$mD8PK4wjL745{Uz$-?E_F!+oU=TD4#n2N zm%T${voe(FwpCfO(Z_lY`!g2wn&T)*DTBp@=x=Yiu_;S|a!b5_+~Gi3EVJO-&RuNW z7pklc`^9vfVZC387qN!5nK@>^L$8=K6>+eI`O*Qlba1cv*T<&+D}kw~=1LQV<@Bmb z&Sho9LbKO9D#yxOIho1pbT-x$7pL38q%m8gq(;Mu=baxM-@60^O;QuBH1Fz$5+!#8 z{bt8bl~9RlF<=It@>@R7@%l$OP4)06Ss%W1gA*YXdsdFIsUi8CQ|6ZDyr_2<-i)!5 zk9Z}O0FKB;XdZog)Vu0nTCY%Wni!L~9}aeGfcNPgM-D-VKFcIdE~%$A^TG10rkCbN@xr%{CyVV^FlP z)X%q`0m3Ht9Xh}OwFG$7weckMvx-m!bKB2Y#qi=bNAXl|)|q+sJ*>RhZTXeS^6!Q*Mf5-0bvRk9jEEt66{$ETfyHj>B4E8Jo{K*2~TK3<<$)S*kpt#BbQO5(ec_V zr@%7x{+{tz)lI2eUC|x^=se8@rX+_y1-G*>FKp$NJLTz6VRJr z81N^wF5eI|aKoZxl^v44dwL7iqKMJbe+cB|^L02iTa6JnT?UOwuqZ~k?5cT2O8iQ! zV{N(S9kXD4+T`cV|0yvyTiA5VY9~eD(M{K;e@X&dx>mbQvl`(d{|6s8WF>y<8O1rX z9x~`IJB3*=MaWK$88}kJl0rQ!`yE^NYZuHRp&}B+#zos(Gw2|=(+R-dL!7fP#P%gQ zSs#eGgpi&$zE<_Dpuw>nBu-rYHf-|xHI-ovU@l8S9&Ff2e8-dBA0AymHhh}o!!D-` ze|H60iAzbZk&!MR)@uJ;#GMPphIx=0qzNe?8%I@;f?DWh@-7=dW5H!HTH+Xz`(OEa zQurtck_>M;h_@&!0H%YZ>_asI4RI54%7AT(7;m?#_^8&1Up~NQ7By>UsMUJ9HLK3M z!43@~&_4(efeEOi@9L+A`tSJye&MAIEvH`3#|Uk<&+qMoXYI$C5-zibb~Y2wNY38( zR9jk7Y^UUh$%|P!fk?PEgr=79|5%n-rd;coRbbfnr6tvQxF9k3X!p0K4#!knnB7jf zq$PwY^&+X(pU_>I(w-?WjzW28UE`H}FLx(lIQO{_b~TdiH^>i*0jeB+D!Z+Y72J`V zDu@pZ3VZUNCim$)qURoR8znh!Q`*hD!5Yy)*r!^)6)~jAPduS?smo)PvI&7|;dTd_ z;Xtkg95X20F~q%i?RQx+y85@lw%>i;uh{omyg*O>?4zgE9TA`(q!FLD>^3q*Y|uKByEONG#|nZ=%-+Y` zNcl<^|0P9@w*WEaW!$tE8Rcp*8|W1zkMy<~+Z*D+OLdqMV)lQ)2GDpynan2%2|Nm2 zVKIGsqlX)IR+B+s=9&Pg`O0Fyji>~On04`j5YtFj9*zYUM<_H`9}+2iTzR)d&jH#+;qR<=m=19MWZdU{8yB^<0*t5=cUS z^-TDEkTB|%z>bauIOEB58UpRkGli-@ZmZ5v^OZne13+4#rnWSdKlU{~^cf8^pF&{8 zH?ldI)9^+dHobeKGfb~<)t++Ey#1&DV+>AUq-P?lYgrlr`HodXph7nz5VaGX*0RmU zZ{G&lQ)XPsN!H=8xKGu0R#@OXmdlac-U@8nSfQIn$V7XegqI$G@oyMAMVfpF70CxSh|0>6E-di30;t+G-4%-aCKeL97<2q8UjgO9pvo9W3j2=zrOBGcozsaK3 zWBZfZGq}rZQWP}&a2`0g20)Xx^)IifpRT|AHw7?FFrE(vpErtZcDq2|x*ROpHu`ud zS8+p0ijG76tlM`M19(IdFnxKW2vE!@k>n%@{9IaMAIL}~QdzXZ1^;>RW+caP-Psn3 zX%To#ZjHP#xHx(;H{oMkoz3Zz7c*S~3*cV6(lVsxe`%cM*iY~Xy6Z-FWivb~98Rv& zMuoFtD@#L8+P%}E#QJRrfk`WIAsh7bJ8YqW*yns_8HaD-9@rQ2S=FHOEDgy)Pi#Wi zju79l+{@%c;{KoZQLCk-fB@d_14wQ2{A4|ay0D5G&B?mA=^x7}tjO|Vk#@x4!JiQq;22Pvn(SNdaArau;ysfBL=+$du1<}97e@D7+mDZqJiFU zavPp&K$lJmxHa{;TnY)C5lfHK-g@O&I`q*5xp}FYa(t|fk#GUB?Fif9{D zmYd;0u~pGnisD3G{`IEiejR@gVB|*XIW|ICI3wkp_1+gN;XfFbTSeNEMkY#iAQDqM z{!Ja+=nTq13Sl{w^Wt?qY%+8$??n;fxBMIvKg)se1J^|nk0#p?+knj%$%UO&P#iwE z_7`{8;#!J3#obwoySrO)*CLDSBE@}icXxMpEn3`4fz$uY_g$VjnM`gnlf0AMMBeB5 z`6>I~NLs-@S)HQk6F$ATv+Kdku6vM`9lC}6hQ}YblW0!u1>0*gFc>qHd`1z-4kj9H zUOF4;zyd#D6hjv=b+QOXN{!OP$tL#j%(^Nn7gN3tG5|05PX)-f*>>z%8v(y`=4{aD zPHN`G%nRyk?)y^avg~$&eKJ!=V&Hp%3H84LpLh2$HMv3-x+br%S{jN|mHt|okBkrf zs@o=fkCm7wQMYsQq%;$quLAM=hQZ4rD}NAqDM`aj!RDnC0PSD+21XxK`DP%CD^x`M zKYtboWURxe{!qICduiw#3vn4ShFMZ7>Kzk zo%I*WCytY*fSX}3lE-$56vUW76tn9`ru!UuA<^)>**o=LNSF&VU8d3 zn^cvw3a@xJUyBa031pTf=4 zy#!D3J&STtV~d?ie}Lwm-sS5GavCH2d!milexUW4v4)@M6=92Egw0x}&tQi>&z`y)xX%sY66VVY@--|20ED&|oS* zO!oL(L^7`~3+0&v?&fm!TdngQul8b;C+{L(0d`Mf)Y?fC19Sh6&!8=e!nG!>52>R# zNCnZiX2ZFfgqh^Zrk!&B@~)x4^SNQ2$&7^M{tT@P^G!B12T+(?FTsWDtexNeXLLfc zLM=iCg=z!o(822XPYsI~_#fIV6o&KCZxc{$i0+T;#5A!}b_`sQ6=v+mAN47N`a@ZS zJMZ3IjHKN-UZ2lBn*t#$Z#1#|Yx63n(P|VG?GIc>)JyQzQy5CISE!Xs! zkh1o@n8N1Euy3#{1cir0U%X{BgtVBmNno$rF%sO8H}ZM@O6^$FM#H$^rsNTIir+6L z6JI1pg-ibX0NH&(jGtUVmz?F3dAGd$K>wQPZj#iO#4-Vhc}B7n@MNM88Brtb`jvas zM8Bu`wiBPy4~;hdGr_u7>bS`C8cI^mSE6P|;;{mhPhDOGd)5N0#}O6Hf!O zUF(1r;}aQItkFqTavUka>vXXUdT#S{y+rjiUHfshl@~W`nbk8*>S*-4@~f=?Z`>?X z#}+=WT(~-97k~;1#!@pyRQY_k5{FIZyZrCI+o#nz66D&weXmxIdWcrzxvyGd6DXq9k@D84|*7(S4B%X zPj22yt|wu?Jbp)BT#Zs`ajxgxm8vNLYMY(-l@D+8R+K|wI^)@HpzZk7QRNG4cvcvmdGNjN$qMeCa z4U^6iJIF@d_J}&9!0*AWbvf$_0NwDdSnzOI916h-o%JBk3!GKZuZVet+hl{+MOfM8 ze`srOZo*K_cbn5o33V1Lixr)tx<*7DuGq0wY1(UO<0JZu8jpEg@shos;598vh9&Vy z%Wfxc#oShe($53GUGj_I2$w?W2oz{(?XtxCPhlw*8tL%|3jC|)oPMpphwSV;%EkIu zPu2kQ;*yZ`;<=^obS83@0~OE56AM*DzcE&!1a2c@ZQ&VdT5l1Q@Ei_ob<*FR19#<) zh8#?>?!)_ECN7X0$Gx`YnuysEK&^93BFq{`Mkb8EQ)BNCRJjD_29nE6Sw zXoBJ~?SE(u$Eeo^a5Q{q4n2QY&@K+{(y=E+{Zx&wxnqV)a6l)j!<;e3pU^@=lr(m- zEe2&x8v=0A1cnwMeoMPClGt7o;i{7iz+- zHB6-fLe?C$CenOsd}?^PeG$yYV93iB{cR&7Oerad$S%`LSa>IRocXdI_2K5*jrGO@&kf@iI zR=TRN*WF)3uduHYS(dv0+%V&PmugP>vl4(v{z1=yK9cvE!ivTG7aJJeM;h$<=k`Hl zuf!kUU6^rwH>Fv5(MK^l`lXm>iSvdH;r>! zn#x1;mN_)YNC9JdbSTcC@Mv0O5d&<7uZk9&MRb?+zt>;|$MWMafY{D^5~4zPF_ZXU zvIpUD&z{VU*R{)o0rhX)(M=R`isVq^m@7>Jr5zN|MyYQfr1RDVm01LvJr8&I`k;91 zM>RoIVOLLFn6ky&gof#&lzlOUQKgmfd&(723N1P`EWY6%9-=~I2Y|>z2ce$RWA#0X znNAj4o~j;4DnnF~@?`Dn?cF=|@3m^GtgJ6lf!RjNzviR%5G&Saum&K%;X;m&ei*tG zDu$~dki)N3)8^5UzT`@m5>A^0seD5hgK-n(!vKjV^hvKr{q}ue$c^grZhZa6eOG_< zx7fHZpTr9*7gP=h=FaqgUGHux!nfFYR|j>*n2Scj=z%eo7K_iBB(h9Ko&I##rC_Io zC@p7;WQ9*ez_bHQM>4YKZK79UE|Ce2VCM=beVBFTJEd;e--i-5@LC{CFwr%@j9oK@ zeOky<*L->`)HeSQ}wOww}1v}|C;Pc6cnzfo91e3tUBiU?n5wG(e}kti~c zPH@B?awFMGpgyB4%H+qJQV|dz_J4VSs!_#D3pvMZok3|r?a*2R;VK!=i(yT)JFuP@ z$rB8!+%%PAhuc_yUDs2?2G$EN6&Ca+OL|IS;Iz2I#-nBbMgnP&eh|4hzA>XgG7h{h z9wzi_gWNb7SyBW&pjEb_#fYagjuZiHkW<&el#U^i%Zqcl^p#${)mm3R8dr>5ClTy; z3DtYP{Nry+;ovMstvu^vimfe+MaY1>fcjpE96%IX*i=6PWM@Gk-$aXhXOC$b<~%`F z>5e*)x-+{zWJol(CZIdgjwxJgpa+{j<^hugwkOy0=^2%lSQD^f-TTV90=-)%X27zh z=8D-1^F^>BA6ebVG3Al+G-lAxwwx^aA0SSLkNBT2n5{3-fk`zk+@dKiouJRJ~NyCDAjF0y}KfDolSvwNGo`rhhw}TKu3M8QxWH| zgMmZ`|8v2C%YWu@R+r0bQ0m4z%}$CTqtz6lI1J%``zt65BXXum2e!ux(2esW5xO0i zVV{*z+|D+DG<|$)LQvf(rEU#0zC;ZWWvNC~S&(Hf1_2)H#%jx%72l=L+-6ib^lxf6Dqwu6okhE;t4nV}C zeB%GSN8_!Om0nRebYkpewipl}0-jeE4uXYPsP01P%bV>IjoJk68YDz1!(=-1TmS`( z@n?TZx%K%h2?;yH=ZZunZd3^`l2Y-``}-JIm zn={#4?gmWI2#TOI?fCL8m}lrRF$(nEci~34+f&r4t}XzdJ?UxQWgx$GE!qOdeFzpKZYhkXIc1dPe4dFq z5N=ay(@z{wm;|J4mc)JFNGoDg#2j>YsNE8T?PoWZ>6lrTY$OOF^zutIP&grjuKrwP23v$BLJT1Q*cKkq~y*ejC!WCR>NNC>;_1FOxjZjTWL?MC@!|=sr zH`K}v5R2GZ-E$8DY+YC20|>Td0TyQrRvBe)c-Sj`TU$cec4j&m0a|=_xWt&eNRr#Db>$pxUbssV>qAF0NdWKT5 zd*nqidIBHm_zS{Nv!gB!#V)J{(O6~v;=i*{uEn7J5>w5)*#Jr{)AQ1V?t_DSeSIKu z%1yuL_nHuL>b3nnGm60zao^$~}{2Kis)~0y^bP->km{*R$E?f#07`h_PFQf@_uvj zVQj-)mU2;{~obm?n*@K==IEQBU9f88`05NV;Fq&+`) zf9J7oJ3cuirAs?bY$|-6omgHK(2CXeGjm{FEm5{=2T~}NfY}-9$&Jkdmsf>!bGfXR z-dJrOyS*75+zO9MFj3`FY|zyqt#lxd1zkHOGkZlLCPjS~O}tdcZs7UydGP0@b`!Eh zNA|-hj%W24TRFCa^O7uH>E0OmO-d)oUF1Xfdk-1+JA{tzw$_cu%)AiGLK(WPyzqpc zeu*FfxlMIVU7n+j@Ks`gd&k6T3VIc9P8hwmRuEHt^wYhpixp#$U{H;DW;t#26Q%w zdERUOrFWy5Y>YbChj`si?R$-p;4A2L>B!+j53@7Q2Yot9S8?3%lskrszgp>)*?u_b zjP}NpE7-p;_S(Yi&%A|Luf8c-NangsmgUp+HUfJIYi4{RoCdIvwkR8RiL>VNQ|egh zaniVFb>spI(AL?hk&qXYzW08OD{BrAwU0?G8Y3K?q|wZUVu(JJ*L@C z!1aCd)5#Nb#YGpZ#;7aWvVBDo-fqT|CDEj;zb!hXb@@+CzCqOuqrG9g7L0Muw&LHE zlPu_Z=w#!OGZRIr!D_WqU4s`w!x$Rhhj2QiwYNyL#*cu_fF8f(Z3XV7AvQ{PH7yP$ zozXVlG&xYPRoXDOC(dZ-MHK?{WZft@BtQK-eIMU|CvChwqMsK=_;!8+oRlN?hlO%)W5!V^Jo!?o-VY{xG=ohHF-Gsj zJpO<|Nm1^ABh4!^;MOfCIO@Y!?j3%S{Q%!d%)gH7z(<>3RzaBbFrgnpdCvG zDWV!vbH&4~2fHj`cMyXZ^xjwnoz$>GRQ=rq+YJW_1m>7>s@&PK&OC@nT8H)Dfh3ps z=1#ZtnT)XTN?+w$ZEB~Gjr%npB}U)e^Tv|1YDbAOIUm^Ghgm9(M$C-D7g*7_b&;wnqUs*}SP092kcw-h{+GJ;e!W0}mTI znzhS1YT=`6pQ1zizwEYZC=D?UK@lmmC}}X&(+^M!-BTyM>;K(Q6Vp-ExtD`|;CYwz zDws7zC(ruxYoM>}&Y?G1HD8Gj&hPcHt#q{Q==WR&1ExtPhK7g$eByzlwkMX}+$J@$ zSRCToy{81R^CbD{DG)YU_cqYnc98%#<^%259a1|60!5Q6B~7#dIOhjpei zp$b#Z*1R>r=oE=nPX^Pj$~^niJ|kPj+q%3c5OkA=gc}5BJRPK;)Qr^Azh$HuW|Gxz zB#2`koq|rAawgJVV=!k3YUPUhRdpmX0SCnZUu3zQ{wCx5vj&oJ9X5v_@NVd%J9MKG zSWRJR@T-88lW^bdr{XtrE7Tz}*Sru@jyq;DW;W>)j!)0k(5(q9Z?od9Qxji^L?yh$ zD-Lt3YL-#c`6Ro3hI5)Vi@6VaYj9lz-cN5i?kEZ)?B}C$%)6{`x!Y9ESbvE8t}wGn zolin@SNW#u8kFfg|K=btA;78hhf2%%6ZCJ>257 zWTdnLPBn?GA6W_O-BTw05EteqEvb2p$%v}ygUtT3m_Z|dv~vrd1+1xqas_d?8Y0fE zZxVcZDhj=|eBKpa*g!=5bUcE8OM&xt;&LM#<0iH@K%WSn=lSi>nZj6Z6!X!vjgYyLV2`hFDP4hw#~! z`I386;A$miX&L*1!wj0#I%&FsI(WR`!sfFj(yoV4oHXj3$%pA_4Qrt>>NOKEJweHT z5Pg~Mk&P;wJ2NRc(?hy!#mq%b?ForgY_T?5;!rAtl0SkfHs5a_8C7!?tN*b+f-F6ewZ9H5_FDW<5qAe4pSSWVF3g zvpUAAo!P%S3(gn`fBh=lqNe8@+$S= zP|aGdZ=~XuyYBre6WHkanCIN1eE!zBb7?}}*sbt@13sf1a$_{kW)s~AKv6!9T)+1E z2QfaczE>=gd=!d}Is`!Rz^Bkl*YT!+IgNftCuSnrO0;n&MU_RMWuu7oleN3j#?&|@ zAryu#*>CdUac8pX3JqaW^V$>$bfi)@V~BuLp`Ciwj|aT~I6`fyx9We;7(J$yd%i>h zu}RZ2D$F<#eR0p+`Ln;NW(-4#!r9bc7Ms+?p#>1%0)Pf`QFa+Z$)@s0yeC)47p~G* z58!KflwvE%4X0-_lPE7@yiU^m^Be#Rp9y2q#kLPQK0S6uLQmi_5J~ipW&U;c7&f(} zRhfd5VXZYec8C{4E+hdw@+a3?SO6&pgg4m4nwY_^^uc81Z1I+84L}T&Iva`vtyK?W zV|zP>q!ughwO^9IvtHn_HU^EARa+<@hq*3O^pb4-jru2|B5DtW9RYpEe^tlb1<{PH z&0%O?{|Y-_XwZ!R43i7%w-3qiYzlIR@&OYx_b|KI#K%d{Sa3`t_-9eL8UNGg<>u$g9q?tioqbQY%F9jX0@gjR_%hu6emo z$;eBopy|I6|4n#%teV?`cC_9L6&9N0;HVL)Ez2Ki-Al{tvj4%C#jH(HGK;DQZTo6? zi!~%4l8p&0D954esx&bcLEfnOf8mf5m+^f|x`9aH#9WbQrv{l278AeoJUzd`*12f< z&I8Q$w<}cz;$gZNd3*{n!S@iBZRCFff26s9r{}_*UH~c$4LF{PeUN+{svNL5&8H1t z%GO=oo2~kW`~d3m?MnQX85|tY=EZ6(zQQcF;^&7fyQ6=^1yk z{nX@b?MRP=wQ3{Sx2Ec25b)N9+sXd*?D)+o7q0iE_8uTr`U$f?v(92|hc@pMbF!K+yvDo3rLEZfhe;+$J&u9uU2g+v?#Q)b2-Fedub;UXi6DHo*|Z&OJ_R*!w>i0?K?W*-!d z%V+S}w+GKY;b7Gq#e-b;&IOF~g8qoFm7fsX1K6_I$VASDPb{?Gp{LHGI6Ss$7o~bO z0RaOMDff8*2tRci4vXl&{h);h6Uxfd)XjY=93Y>Eg8RQZ%M5efi*uIhWl^c>n4$Uw z$Fm&@n_No|tbWK6m9c?Mi;hAWsqjclHs=($E5Gx{7^Ann3h9-Q#)Xwae@gs|tg1t> zM8hSoKr{|!Z^o#PyEjo6cq}xeGn}OXc*LUteZ^! z)0obTdis6g$nrZDiyI|C;A*~whSA?xExHE$S7J9cY}+}a&j?QF!`se+zcUk4MZrjR zdc>+hv;+J1g<99*auO((0a7DBaLst3c;V3u^@iI>tP)LjBR1!nk9iCanhlKM>|PYq z4l2yDf6aYZn`iUjqsS#$hhkqm<6WM{j<75}|Na_ovTvAYU&b&@nCVW9$BD^gP+D_= ztN}!Ap)_9*8sKG^M8V9Yseps?0Ya{;(~BQvCCnxpj*$ zY}zqA uKdzlONo40tOYP=-8uF8~ej2t$qd#l)Zy6y + + + + CFBundleDevelopmentRegion + English + CFBundleExecutable + ${EXECUTABLE_NAME} + CFBundleIdentifier + org.jwz.xscreensaver.${EXECUTABLE_NAME} + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + ${PRODUCT_NAME} + CFBundlePackageType + BNDL + CFBundleShortVersionString + 5.20 + CFBundleSignature + ???? + CFBundleVersion + 5.20 + LSMinimumSystemVersion + 10.4 + NSMainNibFile + SaverRunner + NSPrincipalClass + XScreenSaver${EXECUTABLE_NAME}View + + diff --git a/OSX/XScreenSaverConfigSheet.h b/OSX/XScreenSaverConfigSheet.h new file mode 100644 index 00000000..452c2672 --- /dev/null +++ b/OSX/XScreenSaverConfigSheet.h @@ -0,0 +1,77 @@ +/* xscreensaver, Copyright (c) 2006-2012 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. + */ + +/* XScreenSaver uses XML files to describe the user interface for configuring + the various screen savers. These files live in .../hacks/config/ and + say relatively high level things like: "there should be a checkbox + labelled "Leave Trails", and when it is checked, add the option '-trails' + to the command line when launching the program." + + This code reads that XML and constructs a Cocoa interface from it. + The Cocoa controls are hooked up to NSUserDefaultsController to save + those settings into the MacOS preferences system. The Cocoa preferences + names are the same as the resource names specified in the screenhack's + 'options' array (we use that array to map the command line switches + specified in the XML to the resource names to use). + */ + +#ifdef USE_IPHONE +# import +# import +# define NSView UIView +# define NSUserDefaultsController NSUserDefaults +#else +# import +#endif + +#import "jwxyz.h" + +#import + +#undef USE_PICKER_VIEW + +@interface XScreenSaverConfigSheet : +# ifdef USE_IPHONE + UITableViewController +# else + NSWindow +# endif +{ + NSString *saver_name; + NSUserDefaultsController *userDefaultsController; + NSDictionary *defaultOptions; + const XrmOptionDescRec *opts; + id xml_root, xml_parsing; + +# ifdef USE_IPHONE + UITextField *active_text_field; + NSMutableArray *controls; + NSMutableArray *pref_ctls; // UIControl objects, with index = c.tag + NSMutableArray *pref_keys; // ...and their corresponding resources +# ifdef USE_PICKER_VIEW + NSMutableArray *picker_values; +# endif +# endif + +} + +- (id)initWithXMLFile: (NSString *) xml_file + options: (const XrmOptionDescRec *) opts + controller: (NSUserDefaultsController *) prefs + defaults: (NSDictionary *) defs; + +@end diff --git a/OSX/XScreenSaverConfigSheet.m b/OSX/XScreenSaverConfigSheet.m new file mode 100644 index 00000000..b32e4761 --- /dev/null +++ b/OSX/XScreenSaverConfigSheet.m @@ -0,0 +1,3494 @@ +/* xscreensaver, Copyright (c) 2006-2012 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. + */ + +/* XScreenSaver uses XML files to describe the user interface for configuring + the various screen savers. These files live in .../hacks/config/ and + say relatively high level things like: "there should be a checkbox + labelled "Leave Trails", and when it is checked, add the option '-trails' + to the command line when launching the program." + + This code reads that XML and constructs a Cocoa interface from it. + The Cocoa controls are hooked up to NSUserDefaultsController to save + those settings into the MacOS preferences system. The Cocoa preferences + names are the same as the resource names specified in the screenhack's + 'options' array (we use that array to map the command line switches + specified in the XML to the resource names to use). + */ + +#import "XScreenSaverConfigSheet.h" + +#import "jwxyz.h" +#import "InvertedSlider.h" + +#ifdef USE_IPHONE +# define NSView UIView +# define NSRect CGRect +# define NSSize CGSize +# define NSTextField UITextField +# define NSButton UIButton +# define NSFont UIFont +# define NSStepper UIStepper +# define NSMenuItem UIMenuItem +# define NSText UILabel +# define minValue minimumValue +# define maxValue maximumValue +# define setMinValue setMinimumValue +# define setMaxValue setMaximumValue +# define LABEL UILabel +#else +# define LABEL NSTextField +#endif // USE_IPHONE + +#undef LABEL_ABOVE_SLIDER +#define USE_HTML_LABELS + + +#pragma mark XML Parser + +/* I used to use the "NSXMLDocument" XML parser, but that doesn't exist + on iOS. The "NSXMLParser" parser exists on both OSX and iOS, so I + converted to use that. However, to avoid having to re-write all of + the old code, I faked out a halfassed implementation of the + "NSXMLNode" class that "NSXMLDocument" used to return. + */ + +#define NSXMLNode SimpleXMLNode +#define NSXMLElement SimpleXMLNode +#define NSXMLCommentKind SimpleXMLCommentKind +#define NSXMLElementKind SimpleXMLElementKind +#define NSXMLAttributeKind SimpleXMLAttributeKind +#define NSXMLTextKind SimpleXMLTextKind + +typedef enum { SimpleXMLCommentKind, + SimpleXMLElementKind, + SimpleXMLAttributeKind, + SimpleXMLTextKind, +} SimpleXMLKind; + +@interface SimpleXMLNode : NSObject +{ + SimpleXMLKind kind; + NSString *name; + SimpleXMLNode *parent; + NSMutableArray *children; + NSMutableArray *attributes; + id object; +} + +@property(nonatomic) SimpleXMLKind kind; +@property(nonatomic, retain) NSString *name; +@property(nonatomic, retain) SimpleXMLNode *parent; +@property(nonatomic, retain) NSMutableArray *children; +@property(nonatomic, retain) NSMutableArray *attributes; +@property(nonatomic, retain, getter=objectValue, setter=setObjectValue:) + id object; + +@end + +@implementation SimpleXMLNode + +@synthesize kind; +@synthesize name; +//@synthesize parent; +@synthesize children; +@synthesize attributes; +@synthesize object; + +- (id) init +{ + self = [super init]; + attributes = [NSMutableArray arrayWithCapacity:10]; + return self; +} + + +- (id) initWithName:(NSString *)n +{ + self = [self init]; + [self setKind:NSXMLElementKind]; + [self setName:n]; + return self; +} + + +- (void) setAttributesAsDictionary:(NSDictionary *)dict +{ + for (NSString *key in dict) { + NSObject *val = [dict objectForKey:key]; + SimpleXMLNode *n = [[SimpleXMLNode alloc] init]; + [n setKind:SimpleXMLAttributeKind]; + [n setName:key]; + [n setObjectValue:val]; + [attributes addObject:n]; + } +} + +- (SimpleXMLNode *) parent { return parent; } + +- (void) setParent:(SimpleXMLNode *)p +{ + NSAssert (!parent, @"parent already set"); + if (!p) return; + parent = p; + NSMutableArray *kids = [p children]; + if (!kids) { + kids = [NSMutableArray arrayWithCapacity:10]; + [p setChildren:kids]; + } + [kids addObject:self]; +} +@end + + +#pragma mark Implementing radio buttons + +/* The UIPickerView is a hideous and uncustomizable piece of shit. + I can't believe Apple actually released that thing on the world. + Let's fake up some radio buttons instead. + */ + +#if defined(USE_IPHONE) && !defined(USE_PICKER_VIEW) + +@interface RadioButton : UILabel +{ + int index; + NSArray *items; +} + +@property(nonatomic) int index; +@property(nonatomic, retain) NSArray *items; + +@end + +@implementation RadioButton + +@synthesize index; +@synthesize items; + +- (id) initWithIndex:(int)_index items:_items +{ + self = [super initWithFrame:CGRectZero]; + index = _index; + items = [_items retain]; + + [self setText: [[items objectAtIndex:index] objectAtIndex:0]]; + [self setBackgroundColor:[UIColor clearColor]]; + [self sizeToFit]; + + return self; +} + +@end + + +# endif // !USE_PICKER_VIEW + + +# pragma mark Implementing labels with clickable links + +#if defined(USE_IPHONE) && defined(USE_HTML_LABELS) + +@interface HTMLLabel : UIView +{ + NSString *html; + UIFont *font; + UIWebView *webView; +} + +@property(nonatomic, retain) NSString *html; +@property(nonatomic, retain) UIWebView *webView; + +- (id) initWithHTML:(NSString *)h font:(UIFont *)f; +- (id) initWithText:(NSString *)t font:(UIFont *)f; +- (void) setHTML:(NSString *)h; +- (void) setText:(NSString *)t; +- (void) sizeToFit; + +@end + +@implementation HTMLLabel + +@synthesize html; +@synthesize webView; + +- (id) initWithHTML:(NSString *)h font:(UIFont *)f +{ + self = [super init]; + if (! self) return 0; + font = [f retain]; + webView = [[UIWebView alloc] init]; + webView.delegate = self; + webView.dataDetectorTypes = UIDataDetectorTypeNone; + self. autoresizingMask = (UIViewAutoresizingFlexibleWidth | + UIViewAutoresizingFlexibleHeight); + webView.autoresizingMask = (UIViewAutoresizingFlexibleWidth | + UIViewAutoresizingFlexibleHeight); + [self addSubview: webView]; + [self setHTML: h]; + return self; +} + +- (id) initWithText:(NSString *)t font:(UIFont *)f +{ + self = [self initWithHTML:@"" font:f]; + if (! self) return 0; + [self setText: t]; + return self; +} + + +- (void) setHTML: (NSString *)h +{ + if (! h) return; + [h retain]; + if (html) [html release]; + html = h; + NSString *h2 = + [NSString stringWithFormat: + @"" + "" + "" +// "" + "" + "" + "" + "%@" + "" + "", + [font fontName], + [font pointSize], + [font lineHeight], + h]; + [webView loadHTMLString:h2 baseURL:[NSURL URLWithString:@""]]; +} + + +static char *anchorize (const char *url); + +- (void) setText: (NSString *)t +{ + t = [t stringByReplacingOccurrencesOfString:@"&" withString:@"&"]; + t = [t stringByReplacingOccurrencesOfString:@"<" withString:@"<"]; + t = [t stringByReplacingOccurrencesOfString:@">" withString:@">"]; + t = [t stringByReplacingOccurrencesOfString:@"\n\n" withString:@"

"]; + t = [t stringByReplacingOccurrencesOfString:@"

" + withString:@"

        "]; + t = [t stringByReplacingOccurrencesOfString:@"\n " + withString:@"
        "]; + + NSString *h = @""; + for (NSString *s in + [t componentsSeparatedByCharactersInSet: + [NSCharacterSet whitespaceAndNewlineCharacterSet]]) { + if ([s hasPrefix:@"http://"] || + [s hasPrefix:@"https://"]) { + char *anchor = anchorize ([s cStringUsingEncoding:NSUTF8StringEncoding]); + NSString *a2 = [NSString stringWithCString: anchor + encoding: NSUTF8StringEncoding]; + s = [NSString stringWithFormat: @"
%@
", s, a2]; + free (anchor); + } + h = [NSString stringWithFormat: @"%@ %@", h, s]; + } + [self setHTML: h]; +} + + +-(BOOL) webView:(UIWebView *)wv + shouldStartLoadWithRequest:(NSURLRequest *)req + navigationType:(UIWebViewNavigationType)type +{ + // Force clicked links to open in Safari, not in this window. + if (type == UIWebViewNavigationTypeLinkClicked) { + [[UIApplication sharedApplication] openURL:[req URL]]; + return NO; + } + return YES; +} + + +- (void) setFrame: (CGRect)r +{ + [super setFrame: r]; + r.origin.x = 0; + r.origin.y = 0; + [webView setFrame: r]; + [self setHTML: html]; + [webView reload]; +} + + +- (NSString *) stripTags:(NSString *)str +{ + NSString *result = @""; + + str = [str stringByReplacingOccurrencesOfString:@"

" + withString:@"

" + options:NSCaseInsensitiveSearch + range:NSMakeRange(0, [str length])]; + str = [str stringByReplacingOccurrencesOfString:@"
" + withString:@"\n" + options:NSCaseInsensitiveSearch + range:NSMakeRange(0, [str length])]; + + for (NSString *s in [str componentsSeparatedByString: @"<"]) { + NSRange r = [s rangeOfString:@">"]; + if (r.length > 0) + s = [s substringFromIndex: r.location + r.length]; + result = [result stringByAppendingString: s]; + } + return result; +} + + +- (void) sizeToFit +{ + CGRect r = [self frame]; + + /* It would be sensible to just ask the UIWebView how tall the page is, + instead of hoping that NSString and UIWebView measure fonts and do + wrapping in exactly the same way, but I can't make that work. + Maybe because it loads async? + */ +# if 0 + r.size.height = [[webView + stringByEvaluatingJavaScriptFromString: + @"document.body.offsetHeight"] + doubleValue]; +# else + NSString *text = [self stripTags: html]; + CGSize s = r.size; + s.height = 999999; + s = [text sizeWithFont: font + constrainedToSize: s + lineBreakMode:NSLineBreakByWordWrapping]; + + // GAAAH. Add one more line, or the UIWebView is still scrollable! + // The text is sized right, but it lets you scroll it up anyway. + s.height += [font pointSize]; + + r.size.height = s.height; +# endif + + [self setFrame: r]; +} + + +- (void) dealloc +{ + [html release]; + [font release]; + [webView release]; + [super dealloc]; +} + +@end + +#endif // USE_IPHONE && USE_HTML_LABELS + + +@interface XScreenSaverConfigSheet (Private) + +- (void)traverseChildren:(NSXMLNode *)node on:(NSView *)parent; + +# ifndef USE_IPHONE +- (void) placeChild: (NSView *)c on:(NSView *)p right:(BOOL)r; +- (void) placeChild: (NSView *)c on:(NSView *)p; +static NSView *last_child (NSView *parent); +static void layout_group (NSView *group, BOOL horiz_p); +# else // USE_IPHONE +- (void) placeChild: (NSObject *)c on:(NSView *)p right:(BOOL)r; +- (void) placeChild: (NSObject *)c on:(NSView *)p; +- (void) placeSeparator; +- (void) bindResource:(NSObject *)ctl key:(NSString *)k reload:(BOOL)r; +- (void) refreshTableView; +# endif // USE_IPHONE + +@end + + +@implementation XScreenSaverConfigSheet + +# define LEFT_MARGIN 20 // left edge of window +# define COLUMN_SPACING 10 // gap between e.g. labels and text fields +# define LEFT_LABEL_WIDTH 70 // width of all left labels +# define LINE_SPACING 10 // leading between each line + +# define FONT_SIZE 17 // Magic hardcoded UITableView font size. + +#pragma mark Talking to the resource database + + +/* Normally we read resources by looking up "KEY" in the database + "org.jwz.xscreensaver.SAVERNAME". But in the all-in-one iPhone + app, everything is stored in the database "org.jwz.xscreensaver" + instead, so transform keys to "SAVERNAME.KEY". + + NOTE: This is duplicated in PrefsReader.m, cause I suck. +*/ +- (NSString *) makeKey:(NSString *)key +{ +# ifdef USE_IPHONE + NSString *prefix = [saver_name stringByAppendingString:@"."]; + if (! [key hasPrefix:prefix]) // Don't double up! + key = [prefix stringByAppendingString:key]; +# endif + return key; +} + + +- (NSString *) makeCKey:(const char *)key +{ + return [self makeKey:[NSString stringWithCString:key + encoding:NSUTF8StringEncoding]]; +} + + +/* Given a command-line option, returns the corresponding resource name. + Any arguments in the switch string are ignored (e.g., "-foo x"). + */ +- (NSString *) switchToResource:(NSString *)cmdline_switch + opts:(const XrmOptionDescRec *)opts_array + valRet:(NSString **)val_ret +{ + char buf[255]; + char *tail = 0; + NSAssert(cmdline_switch, @"cmdline switch is null"); + if (! [cmdline_switch getCString:buf maxLength:sizeof(buf) + encoding:NSUTF8StringEncoding]) { + NSAssert1(0, @"unable to convert %@", cmdline_switch); + return 0; + } + char *s = strpbrk(buf, " \t\r\n"); + if (s && *s) { + *s = 0; + tail = s+1; + while (*tail && (*tail == ' ' || *tail == '\t')) + tail++; + } + + while (opts_array[0].option) { + if (!strcmp (opts_array[0].option, buf)) { + const char *ret = 0; + + if (opts_array[0].argKind == XrmoptionNoArg) { + if (tail && *tail) + NSAssert1 (0, @"expected no args to switch: \"%@\"", + cmdline_switch); + ret = opts_array[0].value; + } else { + if (!tail || !*tail) + NSAssert1 (0, @"expected args to switch: \"%@\"", + cmdline_switch); + ret = tail; + } + + if (val_ret) + *val_ret = (ret + ? [NSString stringWithCString:ret + encoding:NSUTF8StringEncoding] + : 0); + + const char *res = opts_array[0].specifier; + while (*res && (*res == '.' || *res == '*')) + res++; + return [self makeCKey:res]; + } + opts_array++; + } + + NSAssert1 (0, @"\"%@\" not present in options", cmdline_switch); + return 0; +} + + +#ifdef USE_IPHONE + +// Called when a slider is bonked. +// +- (void)sliderAction:(UISlider*)sender +{ + if ([active_text_field canResignFirstResponder]) + [active_text_field resignFirstResponder]; + NSString *pref_key = [pref_keys objectAtIndex: [sender tag]]; + double v = [sender value]; + if (v == (int) v) + [userDefaultsController setInteger:v forKey:pref_key]; + else + [userDefaultsController setDouble:v forKey:pref_key]; +} + +// Called when a checkbox/switch is bonked. +// +- (void)switchAction:(UISwitch*)sender +{ + if ([active_text_field canResignFirstResponder]) + [active_text_field resignFirstResponder]; + NSString *pref_key = [pref_keys objectAtIndex: [sender tag]]; + NSString *v = ([sender isOn] ? @"true" : @"false"); + [userDefaultsController setObject:v forKey:pref_key]; +} + +# ifdef USE_PICKER_VIEW +// Called when a picker is bonked. +// +- (void)pickerView:(UIPickerView *)pv + didSelectRow:(NSInteger)row + inComponent:(NSInteger)column +{ + if ([active_text_field canResignFirstResponder]) + [active_text_field resignFirstResponder]; + + NSAssert (column == 0, @"internal error"); + NSArray *a = [picker_values objectAtIndex: [pv tag]]; + if (! a) return; // Too early? + a = [a objectAtIndex:row]; + NSAssert (a, @"missing row"); + +//NSString *label = [a objectAtIndex:0]; + NSString *pref_key = [a objectAtIndex:1]; + NSObject *pref_val = [a objectAtIndex:2]; + [userDefaultsController setObject:pref_val forKey:pref_key]; +} +# else // !USE_PICKER_VIEW + +// Called when a RadioButton is bonked. +// +- (void)radioAction:(RadioButton*)sender +{ + if ([active_text_field canResignFirstResponder]) + [active_text_field resignFirstResponder]; + + NSArray *item = [[sender items] objectAtIndex: [sender index]]; + NSString *pref_key = [item objectAtIndex:1]; + NSObject *pref_val = [item objectAtIndex:2]; + [userDefaultsController setObject:pref_val forKey:pref_key]; +} + +- (BOOL)textFieldShouldBeginEditing:(UITextField *)tf +{ + active_text_field = tf; + return YES; +} + +- (void)textFieldDidEndEditing:(UITextField *)tf +{ + NSString *pref_key = [pref_keys objectAtIndex: [tf tag]]; + NSString *txt = [tf text]; + [userDefaultsController setObject:txt forKey:pref_key]; +} + +- (BOOL)textFieldShouldReturn:(UITextField *)tf +{ + active_text_field = nil; + [tf resignFirstResponder]; + return YES; +} + +# endif // !USE_PICKER_VIEW + +#endif // USE_IPHONE + + +# ifndef USE_IPHONE + +- (void) okAction:(NSObject *)arg +{ + [userDefaultsController commitEditing]; + [userDefaultsController save:self]; + [NSApp endSheet:self returnCode:NSOKButton]; + [self close]; +} + +- (void) cancelAction:(NSObject *)arg +{ + [userDefaultsController revert:self]; + [NSApp endSheet:self returnCode:NSCancelButton]; + [self close]; +} +# endif // !USE_IPHONE + + +- (void) resetAction:(NSObject *)arg +{ +# ifndef USE_IPHONE + [userDefaultsController revertToInitialValues:self]; +# else // USE_IPHONE + + for (NSString *key in defaultOptions) { + NSObject *val = [defaultOptions objectForKey:key]; + [userDefaultsController setObject:val forKey:key]; + } + + for (UIControl *ctl in pref_ctls) { + NSString *pref_key = [pref_keys objectAtIndex: ctl.tag]; + [self bindResource:ctl key:pref_key reload:YES]; + } + + [self refreshTableView]; +# endif // USE_IPHONE +} + + +/* Connects a control (checkbox, etc) to the corresponding preferences key. + */ +- (void) bindResource:(NSObject *)control key:(NSString *)pref_key + reload:(BOOL)reload_p +{ +# ifndef USE_IPHONE + NSString *bindto = ([control isKindOfClass:[NSPopUpButton class]] + ? @"selectedObject" + : ([control isKindOfClass:[NSMatrix class]] + ? @"selectedIndex" + : @"value")); + [control bind:bindto + toObject:userDefaultsController + withKeyPath:[@"values." stringByAppendingString: pref_key] + options:nil]; +# else // USE_IPHONE + SEL sel; + NSObject *val = [userDefaultsController objectForKey:pref_key]; + NSString *sval = 0; + double dval = 0; + + if ([val isKindOfClass:[NSString class]]) { + sval = (NSString *) val; + if (NSOrderedSame == [sval caseInsensitiveCompare:@"true"] || + NSOrderedSame == [sval caseInsensitiveCompare:@"yes"] || + NSOrderedSame == [sval caseInsensitiveCompare:@"1"]) + dval = 1; + else + dval = [sval doubleValue]; + } else if ([val isKindOfClass:[NSNumber class]]) { + // NSBoolean (__NSCFBoolean) is really NSNumber. + dval = [(NSNumber *) val doubleValue]; + sval = [(NSNumber *) val stringValue]; + } + + if ([control isKindOfClass:[UISlider class]]) { + sel = @selector(sliderAction:); + [(UISlider *) control setValue: dval]; + } else if ([control isKindOfClass:[UISwitch class]]) { + sel = @selector(switchAction:); + [(UISwitch *) control setOn: ((int) dval != 0)]; +# ifdef USE_PICKER_VIEW + } else if ([control isKindOfClass:[UIPickerView class]]) { + sel = 0; + [(UIPickerView *) control selectRow:((int)dval) inComponent:0 + animated:NO]; +# else // !USE_PICKER_VIEW + } else if ([control isKindOfClass:[RadioButton class]]) { + sel = 0; // radioAction: sent from didSelectRowAtIndexPath. + } else if ([control isKindOfClass:[UITextField class]]) { + sel = 0; // #### + [(UITextField *) control setText: sval]; +# endif // !USE_PICKER_VIEW + } else { + NSAssert (0, @"unknown class"); + } + + // NSLog(@"\"%@\" = \"%@\" [%@, %.1f]", pref_key, val, [val class], dval); + + if (!reload_p) { + if (! pref_keys) { + pref_keys = [[NSMutableArray arrayWithCapacity:10] retain]; + pref_ctls = [[NSMutableArray arrayWithCapacity:10] retain]; + } + + [pref_keys addObject: [self makeKey:pref_key]]; + [pref_ctls addObject: control]; + ((UIControl *) control).tag = [pref_keys count] - 1; + + if (sel) { + [(UIControl *) control addTarget:self action:sel + forControlEvents:UIControlEventValueChanged]; + } + } + +# endif // USE_IPHONE + +# if 0 + NSObject *def = [[userDefaultsController defaults] objectForKey:pref_key]; + NSString *s = [NSString stringWithFormat:@"bind: \"%@\"", pref_key]; + s = [s stringByPaddingToLength:18 withString:@" " startingAtIndex:0]; + s = [NSString stringWithFormat:@"%@ = \"%@\"", s, def]; + s = [s stringByPaddingToLength:28 withString:@" " startingAtIndex:0]; + NSLog (@"%@ %@/%@", s, [def class], [control class]); +# endif +} + + +- (void) bindResource:(NSObject *)control key:(NSString *)pref_key +{ + [self bindResource:(NSObject *)control key:(NSString *)pref_key reload:NO]; +} + + + +- (void) bindSwitch:(NSObject *)control + cmdline:(NSString *)cmd +{ + [self bindResource:control + key:[self switchToResource:cmd opts:opts valRet:0]]; +} + + +#pragma mark Text-manipulating utilities + + +static NSString * +unwrap (NSString *text) +{ + // Unwrap lines: delete \n but do not delete \n\n. + // + NSArray *lines = [text componentsSeparatedByString:@"\n"]; + int nlines = [lines count]; + BOOL eolp = YES; + int i; + + text = @"\n"; // start with one blank line + + // skip trailing blank lines in file + for (i = nlines-1; i > 0; i--) { + NSString *s = (NSString *) [lines objectAtIndex:i]; + if ([s length] > 0) + break; + nlines--; + } + + // skip leading blank lines in file + for (i = 0; i < nlines; i++) { + NSString *s = (NSString *) [lines objectAtIndex:i]; + if ([s length] > 0) + break; + } + + // unwrap + Bool any = NO; + for (; i < nlines; i++) { + NSString *s = (NSString *) [lines objectAtIndex:i]; + if ([s length] == 0) { + text = [text stringByAppendingString:@"\n\n"]; + eolp = YES; + } else if ([s characterAtIndex:0] == ' ' || + [s hasPrefix:@"Copyright "] || + [s hasPrefix:@"http://"]) { + // don't unwrap if the following line begins with whitespace, + // or with the word "Copyright", or if it begins with a URL. + if (any && !eolp) + text = [text stringByAppendingString:@"\n"]; + text = [text stringByAppendingString:s]; + any = YES; + eolp = NO; + } else { + if (!eolp) + text = [text stringByAppendingString:@" "]; + text = [text stringByAppendingString:s]; + eolp = NO; + any = YES; + } + } + + return text; +} + + +# ifndef USE_IPHONE +/* Makes the text up to the first comma be bold. + */ +static void +boldify (NSText *nstext) +{ + NSString *text = [nstext string]; + NSRange r = [text rangeOfString:@"," options:0]; + r.length = r.location+1; + + r.location = 0; + + NSFont *font = [nstext font]; + font = [NSFont boldSystemFontOfSize:[font pointSize]]; + [nstext setFont:font range:r]; +} +# endif // !USE_IPHONE + + +/* Creates a human-readable anchor to put on a URL. + */ +static char * +anchorize (const char *url) +{ + const char *wiki = "http://en.wikipedia.org/wiki/"; + const char *math = "http://mathworld.wolfram.com/"; + if (!strncmp (wiki, url, strlen(wiki))) { + char *anchor = (char *) malloc (strlen(url) * 3 + 10); + strcpy (anchor, "Wikipedia: \""); + const char *in = url + strlen(wiki); + char *out = anchor + strlen(anchor); + while (*in) { + if (*in == '_') { + *out++ = ' '; + } else if (*in == '#') { + *out++ = ':'; + *out++ = ' '; + } else if (*in == '%') { + char hex[3]; + hex[0] = in[1]; + hex[1] = in[2]; + hex[2] = 0; + int n = 0; + sscanf (hex, "%x", &n); + *out++ = (char) n; + in += 2; + } else { + *out++ = *in; + } + in++; + } + *out++ = '"'; + *out = 0; + return anchor; + + } else if (!strncmp (math, url, strlen(math))) { + char *anchor = (char *) malloc (strlen(url) * 3 + 10); + strcpy (anchor, "MathWorld: \""); + const char *start = url + strlen(wiki); + const char *in = start; + char *out = anchor + strlen(anchor); + while (*in) { + if (*in == '_') { + *out++ = ' '; + } else if (in != start && *in >= 'A' && *in <= 'Z') { + *out++ = ' '; + *out++ = *in; + } else if (!strncmp (in, ".htm", 4)) { + break; + } else { + *out++ = *in; + } + in++; + } + *out++ = '"'; + *out = 0; + return anchor; + + } else { + return strdup (url); + } +} + + +#if !defined(USE_IPHONE) || !defined(USE_HTML_LABELS) + +/* Converts any http: URLs in the given text field to clickable links. + */ +static void +hreffify (NSText *nstext) +{ +# ifndef USE_IPHONE + NSString *text = [nstext string]; + [nstext setRichText:YES]; +# else + NSString *text = [nstext text]; +# endif + + int L = [text length]; + NSRange start; // range is start-of-search to end-of-string + start.location = 0; + start.length = L; + while (start.location < L) { + + // Find the beginning of a URL... + // + NSRange r2 = [text rangeOfString:@"http://" options:0 range:start]; + if (r2.location == NSNotFound) + break; + + // Next time around, start searching after this. + start.location = r2.location + r2.length; + start.length = L - start.location; + + // Find the end of a URL (whitespace or EOF)... + // + NSRange r3 = [text rangeOfCharacterFromSet: + [NSCharacterSet whitespaceAndNewlineCharacterSet] + options:0 range:start]; + if (r3.location == NSNotFound) // EOF + r3.location = L, r3.length = 0; + + // Next time around, start searching after this. + start.location = r3.location; + start.length = L - start.location; + + // Set r2 to the start/length of this URL. + r2.length = start.location - r2.location; + + // Extract the URL. + NSString *nsurl = [text substringWithRange:r2]; + const char *url = [nsurl UTF8String]; + + // If this is a Wikipedia URL, make the linked text be prettier. + // + char *anchor = anchorize(url); + +# ifndef USE_IPHONE + + // Construct the RTF corresponding to anchor + // + const char *fmt = "{\\field{\\*\\fldinst{HYPERLINK \"%s\"}}%s}"; + char *rtf = malloc (strlen (fmt) + strlen(url) + strlen(anchor) + 10); + sprintf (rtf, fmt, url, anchor); + + NSData *rtfdata = [NSData dataWithBytesNoCopy:rtf length:strlen(rtf)]; + [nstext replaceCharactersInRange:r2 withRTF:rtfdata]; + +# else // !USE_IPHONE + // *anchor = 0; // Omit Wikipedia anchor + text = [text stringByReplacingCharactersInRange:r2 + withString:[NSString stringWithCString:anchor + encoding:NSUTF8StringEncoding]]; + // text = [text stringByReplacingOccurrencesOfString:@"\n\n\n" + // withString:@"\n\n"]; +# endif // !USE_IPHONE + + free (anchor); + + int L2 = [text length]; // might have changed + start.location -= (L - L2); + L = L2; + } + +# ifdef USE_IPHONE + [nstext setText:text]; + [nstext sizeToFit]; +# endif +} + +#endif /* !USE_IPHONE || !USE_HTML_LABELS */ + + + +#pragma mark Creating controls from XML + + +/* Parse the attributes of an XML tag into a dictionary. + For input, the dictionary should have as attributes the keys, each + with @"" as their value. + On output, the dictionary will set the keys to the values specified, + and keys that were not specified will not be present in the dictionary. + Warnings are printed if there are duplicate or unknown attributes. + */ +- (void) parseAttrs:(NSMutableDictionary *)dict node:(NSXMLNode *)node +{ + NSArray *attrs = [(NSXMLElement *) node attributes]; + int n = [attrs count]; + int i; + + // For each key in the dictionary, fill in the dict with the corresponding + // value. The value @"" is assumed to mean "un-set". Issue a warning if + // an attribute is specified twice. + // + for (i = 0; i < n; i++) { + NSXMLNode *attr = [attrs objectAtIndex:i]; + NSString *key = [attr name]; + NSString *val = [attr objectValue]; + NSString *old = [dict objectForKey:key]; + + if (! old) { + NSAssert2 (0, @"unknown attribute \"%@\" in \"%@\"", key, [node name]); + } else if ([old length] != 0) { + NSAssert3 (0, @"duplicate %@: \"%@\", \"%@\"", key, old, val); + } else { + [dict setValue:val forKey:key]; + } + } + + // Remove from the dictionary any keys whose value is still @"", + // meaning there was no such attribute specified. + // + NSArray *keys = [dict allKeys]; + n = [keys count]; + for (i = 0; i < n; i++) { + NSString *key = [keys objectAtIndex:i]; + NSString *val = [dict objectForKey:key]; + if ([val length] == 0) + [dict removeObjectForKey:key]; + } + +# ifdef USE_IPHONE + // Kludge for starwars.xml: + // If there is a "_low-label" and no "_label", but "_low-label" contains + // spaces, divide them. + NSString *lab = [dict objectForKey:@"_label"]; + NSString *low = [dict objectForKey:@"_low-label"]; + if (low && !lab) { + NSArray *split = + [[[low stringByTrimmingCharactersInSet: + [NSCharacterSet whitespaceAndNewlineCharacterSet]] + componentsSeparatedByString: @" "] + filteredArrayUsingPredicate: + [NSPredicate predicateWithFormat:@"length > 0"]]; + if (split && [split count] == 2) { + [dict setValue:[split objectAtIndex:0] forKey:@"_label"]; + [dict setValue:[split objectAtIndex:1] forKey:@"_low-label"]; + } + } +# endif // USE_IPHONE +} + + +/* Handle the options on the top level tag. + */ +- (NSString *) parseXScreenSaverTag:(NSXMLNode *)node +{ + NSMutableDictionary *dict = + [NSMutableDictionary dictionaryWithObjectsAndKeys: + @"", @"name", + @"", @"_label", + @"", @"gl", + nil]; + [self parseAttrs:dict node:node]; + NSString *name = [dict objectForKey:@"name"]; + NSString *label = [dict objectForKey:@"_label"]; + + NSAssert1 (label, @"no _label in %@", [node name]); + NSAssert1 (name, @"no name in \"%@\"", label); + return label; +} + + +/* Creates a label: an un-editable NSTextField displaying the given text. + */ +- (LABEL *) makeLabel:(NSString *)text +{ + NSRect rect; + rect.origin.x = rect.origin.y = 0; + rect.size.width = rect.size.height = 10; +# ifndef USE_IPHONE + NSTextField *lab = [[NSTextField alloc] initWithFrame:rect]; + [lab setSelectable:NO]; + [lab setEditable:NO]; + [lab setBezeled:NO]; + [lab setDrawsBackground:NO]; + [lab setStringValue:text]; + [lab sizeToFit]; +# else // USE_IPHONE + UILabel *lab = [[UILabel alloc] initWithFrame:rect]; + [lab setText: [text stringByTrimmingCharactersInSet: + [NSCharacterSet whitespaceAndNewlineCharacterSet]]]; + [lab setBackgroundColor:[UIColor clearColor]]; + [lab setNumberOfLines:0]; // unlimited + // [lab setLineBreakMode:UILineBreakModeWordWrap]; + [lab setLineBreakMode:NSLineBreakByTruncatingHead]; + [lab setAutoresizingMask: (UIViewAutoresizingFlexibleWidth | + UIViewAutoresizingFlexibleHeight)]; +# endif // USE_IPHONE + return lab; +} + + +/* Creates the checkbox (NSButton) described by the given XML node. + */ +- (void) makeCheckbox:(NSXMLNode *)node on:(NSView *)parent +{ + NSMutableDictionary *dict = + [NSMutableDictionary dictionaryWithObjectsAndKeys: + @"", @"id", + @"", @"_label", + @"", @"arg-set", + @"", @"arg-unset", + nil]; + [self parseAttrs:dict node:node]; + NSString *label = [dict objectForKey:@"_label"]; + NSString *arg_set = [dict objectForKey:@"arg-set"]; + NSString *arg_unset = [dict objectForKey:@"arg-unset"]; + + if (!label) { + NSAssert1 (0, @"no _label in %@", [node name]); + return; + } + if (!arg_set && !arg_unset) { + NSAssert1 (0, @"neither arg-set nor arg-unset provided in \"%@\"", + label); + } + if (arg_set && arg_unset) { + NSAssert1 (0, @"only one of arg-set and arg-unset may be used in \"%@\"", + label); + } + + // sanity-check the choice of argument names. + // + if (arg_set && ([arg_set hasPrefix:@"-no-"] || + [arg_set hasPrefix:@"--no-"])) + NSLog (@"arg-set should not be a \"no\" option in \"%@\": %@", + label, arg_set); + if (arg_unset && (![arg_unset hasPrefix:@"-no-"] && + ![arg_unset hasPrefix:@"--no-"])) + NSLog(@"arg-unset should be a \"no\" option in \"%@\": %@", + label, arg_unset); + + NSRect rect; + rect.origin.x = rect.origin.y = 0; + rect.size.width = rect.size.height = 10; + +# ifndef USE_IPHONE + + NSButton *button = [[NSButton alloc] initWithFrame:rect]; + [button setButtonType:NSSwitchButton]; + [button setTitle:label]; + [button sizeToFit]; + [self placeChild:button on:parent]; + +# else // USE_IPHONE + + LABEL *lab = [self makeLabel:label]; + [self placeChild:lab on:parent]; + UISwitch *button = [[UISwitch alloc] initWithFrame:rect]; + [self placeChild:button on:parent right:YES]; + [lab release]; + +# endif // USE_IPHONE + + [self bindSwitch:button cmdline:(arg_set ? arg_set : arg_unset)]; + [button release]; +} + + +/* Creates the number selection control described by the given XML node. + If "type=slider", it's an NSSlider. + If "type=spinbutton", it's a text field with up/down arrows next to it. +*/ +- (void) makeNumberSelector:(NSXMLNode *)node on:(NSView *)parent +{ + NSMutableDictionary *dict = + [NSMutableDictionary dictionaryWithObjectsAndKeys: + @"", @"id", + @"", @"_label", + @"", @"_low-label", + @"", @"_high-label", + @"", @"type", + @"", @"arg", + @"", @"low", + @"", @"high", + @"", @"default", + @"", @"convert", + nil]; + [self parseAttrs:dict node:node]; + NSString *label = [dict objectForKey:@"_label"]; + NSString *low_label = [dict objectForKey:@"_low-label"]; + NSString *high_label = [dict objectForKey:@"_high-label"]; + NSString *type = [dict objectForKey:@"type"]; + NSString *arg = [dict objectForKey:@"arg"]; + NSString *low = [dict objectForKey:@"low"]; + NSString *high = [dict objectForKey:@"high"]; + NSString *def = [dict objectForKey:@"default"]; + NSString *cvt = [dict objectForKey:@"convert"]; + + NSAssert1 (arg, @"no arg in %@", label); + NSAssert1 (type, @"no type in %@", label); + + if (! low) { + NSAssert1 (0, @"no low in %@", [node name]); + return; + } + if (! high) { + NSAssert1 (0, @"no high in %@", [node name]); + return; + } + if (! def) { + NSAssert1 (0, @"no default in %@", [node name]); + return; + } + if (cvt && ![cvt isEqualToString:@"invert"]) { + NSAssert1 (0, @"if provided, \"convert\" must be \"invert\" in %@", + label); + } + + // If either the min or max field contains a decimal point, then this + // option may have a floating point value; otherwise, it is constrained + // to be an integer. + // + NSCharacterSet *dot = + [NSCharacterSet characterSetWithCharactersInString:@"."]; + BOOL float_p = ([low rangeOfCharacterFromSet:dot].location != NSNotFound || + [high rangeOfCharacterFromSet:dot].location != NSNotFound); + + if ([type isEqualToString:@"slider"] +# ifdef USE_IPHONE // On iPhone, we use sliders for all numeric values. + || [type isEqualToString:@"spinbutton"] +# endif + ) { + + NSRect rect; + rect.origin.x = rect.origin.y = 0; + rect.size.width = 150; + rect.size.height = 23; // apparent min height for slider with ticks... + NSSlider *slider; + slider = [[InvertedSlider alloc] initWithFrame:rect + inverted: !!cvt + integers: !float_p]; + [slider setMaxValue:[high doubleValue]]; + [slider setMinValue:[low doubleValue]]; + + int range = [slider maxValue] - [slider minValue] + 1; + int range2 = range; + int max_ticks = 21; + while (range2 > max_ticks) + range2 /= 10; + + // If we have elided ticks, leave it at the max number of ticks. + if (range != range2 && range2 < max_ticks) + range2 = max_ticks; + + // If it's a float, always display the max number of ticks. + if (float_p && range2 < max_ticks) + range2 = max_ticks; + +# ifndef USE_IPHONE + [slider setNumberOfTickMarks:range2]; + + [slider setAllowsTickMarkValuesOnly: + (range == range2 && // we are showing the actual number of ticks + !float_p)]; // and we want integer results +# endif // !USE_IPHONE + + // #### Note: when the slider's range is large enough that we aren't + // showing all possible ticks, the slider's value is not constrained + // to be an integer, even though it should be... + // Maybe we need to use a value converter or something? + + LABEL *lab; + if (label) { + lab = [self makeLabel:label]; + [self placeChild:lab on:parent]; +# ifdef USE_IPHONE + if (low_label) { + CGFloat s = [NSFont systemFontSize] + 4; + [lab setFont:[NSFont boldSystemFontOfSize:s]]; + } +# endif + [lab release]; + } + + if (low_label) { + lab = [self makeLabel:low_label]; + [lab setFont:[NSFont systemFontOfSize:[NSFont smallSystemFontSize]]]; +# ifndef USE_IPHONE + [lab setAlignment:1]; // right aligned + rect = [lab frame]; + if (rect.size.width < LEFT_LABEL_WIDTH) + rect.size.width = LEFT_LABEL_WIDTH; // make all left labels same size + rect.size.height = [slider frame].size.height; + [lab setFrame:rect]; + [self placeChild:lab on:parent]; +# else // USE_IPHONE + [lab setTextAlignment: NSTextAlignmentRight]; + [self placeChild:lab on:parent right:(label ? YES : NO)]; +# endif // USE_IPHONE + + [lab release]; + } + +# ifndef USE_IPHONE + [self placeChild:slider on:parent right:(low_label ? YES : NO)]; +# else // USE_IPHONE + [self placeChild:slider on:parent right:(label || low_label ? YES : NO)]; +# endif // USE_IPHONE + + if (low_label) { + // Make left label be same height as slider. + rect = [lab frame]; + rect.size.height = [slider frame].size.height; + [lab setFrame:rect]; + } + + if (! low_label) { + rect = [slider frame]; + if (rect.origin.x < LEFT_LABEL_WIDTH) + rect.origin.x = LEFT_LABEL_WIDTH; // make unlabelled sliders line up too + [slider setFrame:rect]; + } + + if (high_label) { + lab = [self makeLabel:high_label]; + [lab setFont:[NSFont systemFontOfSize:[NSFont smallSystemFontSize]]]; + rect = [lab frame]; + + // Make right label be same height as slider. + rect.size.height = [slider frame].size.height; + [lab setFrame:rect]; + [self placeChild:lab on:parent right:YES]; + [lab release]; + } + + [self bindSwitch:slider cmdline:arg]; + [slider release]; + +#ifndef USE_IPHONE // On iPhone, we use sliders for all numeric values. + + } else if ([type isEqualToString:@"spinbutton"]) { + + if (! label) { + NSAssert1 (0, @"no _label in spinbutton %@", [node name]); + return; + } + NSAssert1 (!low_label, + @"low-label not allowed in spinbutton \"%@\"", [node name]); + NSAssert1 (!high_label, + @"high-label not allowed in spinbutton \"%@\"", [node name]); + NSAssert1 (!cvt, @"convert not allowed in spinbutton \"%@\"", + [node name]); + + NSRect rect; + rect.origin.x = rect.origin.y = 0; + rect.size.width = rect.size.height = 10; + + NSTextField *txt = [[NSTextField alloc] initWithFrame:rect]; + [txt setStringValue:@"0000.0"]; + [txt sizeToFit]; + [txt setStringValue:@""]; + + if (label) { + LABEL *lab = [self makeLabel:label]; + //[lab setFont:[NSFont systemFontOfSize:[NSFont smallSystemFontSize]]]; + [lab setAlignment:1]; // right aligned + rect = [lab frame]; + if (rect.size.width < LEFT_LABEL_WIDTH) + rect.size.width = LEFT_LABEL_WIDTH; // make all left labels same size + rect.size.height = [txt frame].size.height; + [lab setFrame:rect]; + [self placeChild:lab on:parent]; + [lab release]; + } + + [self placeChild:txt on:parent right:(label ? YES : NO)]; + + if (! label) { + rect = [txt frame]; + if (rect.origin.x < LEFT_LABEL_WIDTH) + rect.origin.x = LEFT_LABEL_WIDTH; // make unlabelled spinbtns line up + [txt setFrame:rect]; + } + + rect.size.width = rect.size.height = 10; + NSStepper *step = [[NSStepper alloc] initWithFrame:rect]; + [step sizeToFit]; + [self placeChild:step on:parent right:YES]; + rect = [step frame]; + rect.origin.x -= COLUMN_SPACING; // this one goes close + rect.origin.y += ([txt frame].size.height - rect.size.height) / 2; + [step setFrame:rect]; + + [step setMinValue:[low doubleValue]]; + [step setMaxValue:[high doubleValue]]; + [step setAutorepeat:YES]; + [step setValueWraps:NO]; + + double range = [high doubleValue] - [low doubleValue]; + if (range < 1.0) + [step setIncrement:range / 10.0]; + else if (range >= 500) + [step setIncrement:range / 100.0]; + else + [step setIncrement:1.0]; + + NSNumberFormatter *fmt = [[[NSNumberFormatter alloc] init] autorelease]; + [fmt setFormatterBehavior:NSNumberFormatterBehavior10_4]; + [fmt setNumberStyle:NSNumberFormatterDecimalStyle]; + [fmt setMinimum:[NSNumber numberWithDouble:[low doubleValue]]]; + [fmt setMaximum:[NSNumber numberWithDouble:[high doubleValue]]]; + [fmt setMinimumFractionDigits: (float_p ? 1 : 0)]; + [fmt setMaximumFractionDigits: (float_p ? 2 : 0)]; + + [fmt setGeneratesDecimalNumbers:float_p]; + [[txt cell] setFormatter:fmt]; + + [self bindSwitch:step cmdline:arg]; + [self bindSwitch:txt cmdline:arg]; + + [step release]; + [txt release]; + +# endif // USE_IPHONE + + } else { + NSAssert2 (0, @"unknown type \"%@\" in \"%@\"", type, label); + } +} + + +# ifndef USE_IPHONE +static void +set_menu_item_object (NSMenuItem *item, NSObject *obj) +{ + /* If the object associated with this menu item looks like a boolean, + store an NSNumber instead of an NSString, since that's what + will be in the preferences (due to similar logic in PrefsReader). + */ + if ([obj isKindOfClass:[NSString class]]) { + NSString *string = (NSString *) obj; + if (NSOrderedSame == [string caseInsensitiveCompare:@"true"] || + NSOrderedSame == [string caseInsensitiveCompare:@"yes"]) + obj = [NSNumber numberWithBool:YES]; + else if (NSOrderedSame == [string caseInsensitiveCompare:@"false"] || + NSOrderedSame == [string caseInsensitiveCompare:@"no"]) + obj = [NSNumber numberWithBool:NO]; + else + obj = string; + } + + [item setRepresentedObject:obj]; + //NSLog (@"menu item \"%@\" = \"%@\" %@", [item title], obj, [obj class]); +} +# endif // !USE_IPHONE + + +/* Creates the popup menu described by the given XML node (and its children). +*/ +- (void) makeOptionMenu:(NSXMLNode *)node on:(NSView *)parent +{ + NSArray *children = [node children]; + int i, count = [children count]; + + if (count <= 0) { + NSAssert1 (0, @"no menu items in \"%@\"", [node name]); + return; + } + + // get the "id" attribute off the + //

or in the XML. + */ +- (void) makeGroup:(NSXMLNode *)node + on:(NSView *)parent + horizontal:(BOOL) horiz_p +{ +# ifdef USE_IPHONE + if (!horiz_p) [self placeSeparator]; + [self traverseChildren:node on:parent]; + if (!horiz_p) [self placeSeparator]; +# else // !USE_IPHONE + NSRect rect; + rect.size.width = rect.size.height = 1; + rect.origin.x = rect.origin.y = 0; + NSView *group = [[NSView alloc] initWithFrame:rect]; + [self traverseChildren:node on:group]; + + layout_group (group, horiz_p); + + rect.size.width = rect.size.height = 0; + NSBox *box = [[NSBox alloc] initWithFrame:rect]; + [box setTitlePosition:NSNoTitle]; + [box setBorderType:NSNoBorder]; + [box setContentViewMargins:rect.size]; + [box setContentView:group]; + [box sizeToFit]; + + [self placeChild:box on:parent]; +# endif // !USE_IPHONE +} + + +#ifndef USE_IPHONE +static void +layout_group (NSView *group, BOOL horiz_p) +{ + NSArray *kids = [group subviews]; + int nkids = [kids count]; + int i; + double maxx = 0, miny = 0; + for (i = 0; i < nkids; i++) { + NSView *kid = [kids objectAtIndex:i]; + NSRect r = [kid frame]; + + if (horiz_p) { + maxx += r.size.width + COLUMN_SPACING; + if (r.size.height > -miny) miny = -r.size.height; + } else { + if (r.size.width > maxx) maxx = r.size.width; + miny = r.origin.y - r.size.height; + } + } + + NSRect rect; + rect.origin.x = 0; + rect.origin.y = 0; + rect.size.width = maxx; + rect.size.height = -miny; + [group setFrame:rect]; + + double x = 0; + for (i = 0; i < nkids; i++) { + NSView *kid = [kids objectAtIndex:i]; + NSRect r = [kid frame]; + if (horiz_p) { + r.origin.y = rect.size.height - r.size.height; + r.origin.x = x; + x += r.size.width + COLUMN_SPACING; + } else { + r.origin.y -= miny; + } + [kid setFrame:r]; + } +} +#endif // !USE_IPHONE + + +/* Create some kind of control corresponding to the given XML node. + */ +-(void)makeControl:(NSXMLNode *)node on:(NSView *)parent +{ + NSString *name = [node name]; + + if ([node kind] == NSXMLCommentKind) + return; + + if ([node kind] == NSXMLTextKind) { + NSString *s = [(NSString *) [node objectValue] + stringByTrimmingCharactersInSet: + [NSCharacterSet whitespaceAndNewlineCharacterSet]]; + if (! [s isEqualToString:@""]) { + NSAssert1 (0, @"unexpected text: %@", s); + } + return; + } + + if ([node kind] != NSXMLElementKind) { + NSAssert2 (0, @"weird XML node kind: %d: %@", (int)[node kind], node); + return; + } + + if ([name isEqualToString:@"hgroup"] || + [name isEqualToString:@"vgroup"]) { + + [self makeGroup:node on:parent + horizontal:[name isEqualToString:@"hgroup"]]; + + } else if ([name isEqualToString:@"command"]) { + // do nothing: this is the "-root" business + + } else if ([name isEqualToString:@"boolean"]) { + [self makeCheckbox:node on:parent]; + + } else if ([name isEqualToString:@"string"]) { + [self makeTextField:node on:parent withLabel:NO horizontal:NO]; + + } else if ([name isEqualToString:@"file"]) { + [self makeFileSelector:node on:parent + dirsOnly:NO withLabel:YES editable:NO]; + + } else if ([name isEqualToString:@"number"]) { + [self makeNumberSelector:node on:parent]; + + } else if ([name isEqualToString:@"select"]) { + [self makeOptionMenu:node on:parent]; + + } else if ([name isEqualToString:@"_description"]) { + [self makeDescLabel:node on:parent]; + + } else if ([name isEqualToString:@"xscreensaver-text"]) { + [self makeTextLoaderControlBox:node on:parent]; + + } else if ([name isEqualToString:@"xscreensaver-image"]) { + [self makeImageLoaderControlBox:node on:parent]; + + } else { + NSAssert1 (0, @"unknown tag: %@", name); + } +} + + +/* Iterate over and process the children of this XML node. + */ +- (void)traverseChildren:(NSXMLNode *)node on:(NSView *)parent +{ + NSArray *children = [node children]; + int i, count = [children count]; + for (i = 0; i < count; i++) { + NSXMLNode *child = [children objectAtIndex:i]; + [self makeControl:child on:parent]; + } +} + + +# ifndef USE_IPHONE + +/* Kludgey magic to make the window enclose the controls we created. + */ +static void +fix_contentview_size (NSView *parent) +{ + NSRect f; + NSArray *kids = [parent subviews]; + int nkids = [kids count]; + NSView *text = 0; // the NSText at the bottom of the window + double maxx = 0, miny = 0; + int i; + + /* Find the size of the rectangle taken up by each of the children + except the final "NSText" child. + */ + for (i = 0; i < nkids; i++) { + NSView *kid = [kids objectAtIndex:i]; + if ([kid isKindOfClass:[NSText class]]) { + text = kid; + continue; + } + f = [kid frame]; + if (f.origin.x + f.size.width > maxx) maxx = f.origin.x + f.size.width; + if (f.origin.y - f.size.height < miny) miny = f.origin.y; +// NSLog(@"start: %3.0f x %3.0f @ %3.0f %3.0f %3.0f %@", +// f.size.width, f.size.height, f.origin.x, f.origin.y, +// f.origin.y + f.size.height, [kid class]); + } + + if (maxx < 400) maxx = 400; // leave room for the NSText paragraph... + + /* Now that we know the width of the window, set the width of the NSText to + that, so that it can decide what its height needs to be. + */ + if (! text) abort(); + f = [text frame]; +// NSLog(@"text old: %3.0f x %3.0f @ %3.0f %3.0f %3.0f %@", +// f.size.width, f.size.height, f.origin.x, f.origin.y, +// f.origin.y + f.size.height, [text class]); + + // set the NSText's width (this changes its height). + f.size.width = maxx - LEFT_MARGIN; + [text setFrame:f]; + + // position the NSText below the last child (this gives us a new miny). + f = [text frame]; + f.origin.y = miny - f.size.height - LINE_SPACING; + miny = f.origin.y - LINE_SPACING; + [text setFrame:f]; + + // Lock the width of the field and unlock the height, and let it resize + // once more, to compute the proper height of the text for that width. + // + [(NSText *) text setHorizontallyResizable:NO]; + [(NSText *) text setVerticallyResizable:YES]; + [(NSText *) text sizeToFit]; + + // Now lock the height too: no more resizing this text field. + // + [(NSText *) text setVerticallyResizable:NO]; + + // Now reposition the top edge of the text field to be back where it + // was before we changed the height. + // + float oh = f.size.height; + f = [text frame]; + float dh = f.size.height - oh; + f.origin.y += dh; + + // #### This is needed in OSX 10.5, but is wrong in OSX 10.6. WTF?? + // If we do this in 10.6, the text field moves down, off the window. + // So instead we repair it at the end, at the "WTF2" comment. + [text setFrame:f]; + + // Also adjust the parent height by the change in height of the text field. + miny -= dh; + +// NSLog(@"text new: %3.0f x %3.0f @ %3.0f %3.0f %3.0f %@", +// f.size.width, f.size.height, f.origin.x, f.origin.y, +// f.origin.y + f.size.height, [text class]); + + + /* Set the contentView to the size of the children. + */ + f = [parent frame]; +// float yoff = f.size.height; + f.size.width = maxx + LEFT_MARGIN; + f.size.height = -(miny - LEFT_MARGIN*2); +// yoff = f.size.height - yoff; + [parent setFrame:f]; + +// NSLog(@"max: %3.0f x %3.0f @ %3.0f %3.0f", +// f.size.width, f.size.height, f.origin.x, f.origin.y); + + /* Now move all of the kids up into the window. + */ + f = [parent frame]; + float shift = f.size.height; +// NSLog(@"shift: %3.0f", shift); + for (i = 0; i < nkids; i++) { + NSView *kid = [kids objectAtIndex:i]; + f = [kid frame]; + f.origin.y += shift; + [kid setFrame:f]; +// NSLog(@"move: %3.0f x %3.0f @ %3.0f %3.0f %3.0f %@", +// f.size.width, f.size.height, f.origin.x, f.origin.y, +// f.origin.y + f.size.height, [kid class]); + } + +/* +Bad: + parent: 420 x 541 @ 0 0 + text: 380 x 100 @ 20 22 miny=-501 + +Good: + parent: 420 x 541 @ 0 0 + text: 380 x 100 @ 20 50 miny=-501 +*/ + + // #### WTF2: See "WTF" above. If the text field is off the screen, + // move it up. We need this on 10.6 but not on 10.5. Auugh. + // + f = [text frame]; + if (f.origin.y < 50) { // magic numbers, yay + f.origin.y = 50; + [text setFrame:f]; + } + + /* Set the kids to track the top left corner of the window when resized. + Set the NSText to track the bottom right corner as well. + */ + for (i = 0; i < nkids; i++) { + NSView *kid = [kids objectAtIndex:i]; + unsigned long mask = NSViewMaxXMargin | NSViewMinYMargin; + if ([kid isKindOfClass:[NSText class]]) + mask |= NSViewWidthSizable|NSViewHeightSizable; + [kid setAutoresizingMask:mask]; + } +} +# endif // !USE_IPHONE + + + +#ifndef USE_IPHONE +static NSView * +wrap_with_buttons (NSWindow *window, NSView *panel) +{ + NSRect rect; + + // Make a box to hold the buttons at the bottom of the window. + // + rect = [panel frame]; + rect.origin.x = rect.origin.y = 0; + rect.size.height = 10; + NSBox *bbox = [[NSBox alloc] initWithFrame:rect]; + [bbox setTitlePosition:NSNoTitle]; + [bbox setBorderType:NSNoBorder]; + + // Make some buttons: Default, Cancel, OK + // + rect.origin.x = rect.origin.y = 0; + rect.size.width = rect.size.height = 10; + NSButton *reset = [[NSButton alloc] initWithFrame:rect]; + [reset setTitle:@"Reset to Defaults"]; + [reset setBezelStyle:NSRoundedBezelStyle]; + [reset sizeToFit]; + + rect = [reset frame]; + NSButton *ok = [[NSButton alloc] initWithFrame:rect]; + [ok setTitle:@"OK"]; + [ok setBezelStyle:NSRoundedBezelStyle]; + [ok sizeToFit]; + rect = [bbox frame]; + rect.origin.x = rect.size.width - [ok frame].size.width; + [ok setFrameOrigin:rect.origin]; + + rect = [ok frame]; + NSButton *cancel = [[NSButton alloc] initWithFrame:rect]; + [cancel setTitle:@"Cancel"]; + [cancel setBezelStyle:NSRoundedBezelStyle]; + [cancel sizeToFit]; + rect.origin.x -= [cancel frame].size.width + 10; + [cancel setFrameOrigin:rect.origin]; + + // Bind OK to RET and Cancel to ESC. + [ok setKeyEquivalent:@"\r"]; + [cancel setKeyEquivalent:@"\e"]; + + // The correct width for OK and Cancel buttons is 68 pixels + // ("Human Interface Guidelines: Controls: Buttons: + // Push Button Specifications"). + // + rect = [ok frame]; + rect.size.width = 68; + [ok setFrame:rect]; + + rect = [cancel frame]; + rect.size.width = 68; + [cancel setFrame:rect]; + + // It puts the buttons in the box or else it gets the hose again + // + [bbox addSubview:ok]; + [bbox addSubview:cancel]; + [bbox addSubview:reset]; + [bbox sizeToFit]; + + // make a box to hold the button-box, and the preferences view + // + rect = [bbox frame]; + rect.origin.y += rect.size.height; + NSBox *pbox = [[NSBox alloc] initWithFrame:rect]; + [pbox setTitlePosition:NSNoTitle]; + [pbox setBorderType:NSBezelBorder]; + + // Enforce a max height on the dialog, so that it's obvious to me + // (on a big screen) when the dialog will fall off the bottom of + // a small screen (e.g., 1024x768 laptop with a huge bottom dock). + { + NSRect f = [panel frame]; + int screen_height = (768 // shortest "modern" Mac display + - 22 // menu bar + - 56 // System Preferences toolbar + - 140 // default magnified bottom dock icon + ); + if (f.size.height > screen_height) { + NSLog(@"%@ height was %.0f; clipping to %d", + [panel class], f.size.height, screen_height); + f.size.height = screen_height; + [panel setFrame:f]; + } + } + + [pbox addSubview:panel]; + [pbox addSubview:bbox]; + [pbox sizeToFit]; + + [reset setAutoresizingMask:NSViewMaxXMargin]; + [cancel setAutoresizingMask:NSViewMinXMargin]; + [ok setAutoresizingMask:NSViewMinXMargin]; + [bbox setAutoresizingMask:NSViewWidthSizable]; + + // grab the clicks + // + [ok setTarget:window]; + [cancel setTarget:window]; + [reset setTarget:window]; + [ok setAction:@selector(okAction:)]; + [cancel setAction:@selector(cancelAction:)]; + [reset setAction:@selector(resetAction:)]; + + return pbox; +} +#endif // !USE_IPHONE + + +/* Iterate over and process the children of the root node of the XML document. + */ +- (void)traverseTree +{ +# ifdef USE_IPHONE + NSView *parent = [self view]; +# else + NSWindow *parent = self; +#endif + NSXMLNode *node = xml_root; + + if (![[node name] isEqualToString:@"screensaver"]) { + NSAssert (0, @"top level node is not "); + } + + saver_name = [self parseXScreenSaverTag: node]; + saver_name = [saver_name stringByReplacingOccurrencesOfString:@" " + withString:@""]; + [saver_name retain]; + +# ifndef USE_IPHONE + + NSRect rect; + rect.origin.x = rect.origin.y = 0; + rect.size.width = rect.size.height = 1; + + NSView *panel = [[NSView alloc] initWithFrame:rect]; + [self traverseChildren:node on:panel]; + fix_contentview_size (panel); + + NSView *root = wrap_with_buttons (parent, panel); + [userDefaultsController setAppliesImmediately:NO]; + + [panel setAutoresizingMask:NSViewWidthSizable|NSViewHeightSizable]; + + rect = [parent frameRectForContentRect:[root frame]]; + [parent setFrame:rect display:NO]; + [parent setMinSize:rect.size]; + + [parent setContentView:root]; + +# else // USE_IPHONE + + CGRect r = [parent frame]; + r.size = [[UIScreen mainScreen] bounds].size; + [parent setFrame:r]; + [self traverseChildren:node on:parent]; + +# endif // USE_IPHONE +} + + +- (void)parser:(NSXMLParser *)parser + didStartElement:(NSString *)elt + namespaceURI:(NSString *)ns + qualifiedName:(NSString *)qn + attributes:(NSDictionary *)attrs +{ + NSXMLElement *e = [[NSXMLElement alloc] initWithName:elt]; + [e setKind:SimpleXMLElementKind]; + [e setAttributesAsDictionary:attrs]; + NSXMLElement *p = xml_parsing; + [e setParent:p]; + xml_parsing = e; + if (! xml_root) + xml_root = xml_parsing; +} + +- (void)parser:(NSXMLParser *)parser + didEndElement:(NSString *)elt + namespaceURI:(NSString *)ns + qualifiedName:(NSString *)qn +{ + NSXMLElement *p = xml_parsing; + if (! p) { + NSLog(@"extra close: %@", elt); + } else if (![[p name] isEqualToString:elt]) { + NSLog(@"%@ closed by %@", [p name], elt); + } else { + NSXMLElement *n = xml_parsing; + xml_parsing = [n parent]; + } +} + + +- (void)parser:(NSXMLParser *)parser foundCharacters:(NSString *)string +{ + NSXMLElement *e = [[NSXMLElement alloc] initWithName:@"text"]; + [e setKind:SimpleXMLTextKind]; + NSXMLElement *p = xml_parsing; + [e setParent:p]; + [e setObjectValue: string]; +} + + +# ifdef USE_IPHONE +# ifdef USE_PICKER_VIEW + +#pragma mark UIPickerView delegate methods + +- (NSInteger)numberOfComponentsInPickerView:(UIPickerView *)pv +{ + return 1; // Columns +} + +- (NSInteger)pickerView:(UIPickerView *)pv + numberOfRowsInComponent:(NSInteger)column +{ + NSAssert (column == 0, @"weird column"); + NSArray *a = [picker_values objectAtIndex: [pv tag]]; + if (! a) return 0; // Too early? + return [a count]; +} + +- (CGFloat)pickerView:(UIPickerView *)pv + rowHeightForComponent:(NSInteger)column +{ + return FONT_SIZE; +} + +- (CGFloat)pickerView:(UIPickerView *)pv + widthForComponent:(NSInteger)column +{ + NSAssert (column == 0, @"weird column"); + NSArray *a = [picker_values objectAtIndex: [pv tag]]; + if (! a) return 0; // Too early? + + UIFont *f = [UIFont systemFontOfSize:[NSFont systemFontSize]]; + CGFloat max = 0; + for (NSArray *a2 in a) { + NSString *s = [a2 objectAtIndex:0]; + CGSize r = [s sizeWithFont:f]; + if (r.width > max) max = r.width; + } + + max *= 1.7; // WTF!! + + if (max > 320) + max = 320; + else if (max < 120) + max = 120; + + return max; + +} + + +- (NSString *)pickerView:(UIPickerView *)pv + titleForRow:(NSInteger)row + forComponent:(NSInteger)column +{ + NSAssert (column == 0, @"weird column"); + NSArray *a = [picker_values objectAtIndex: [pv tag]]; + if (! a) return 0; // Too early? + a = [a objectAtIndex:row]; + NSAssert (a, @"internal error"); + return [a objectAtIndex:0]; +} + +# endif // USE_PICKER_VIEW + + +#pragma mark UITableView delegate methods + +- (void) addResetButton +{ + [[self navigationItem] + setRightBarButtonItem: [[UIBarButtonItem alloc] + initWithTitle: @"Reset to Defaults" + style: UIBarButtonItemStyleBordered + target:self + action:@selector(resetAction:)]]; + NSString *s = saver_name; + if ([self view].frame.size.width > 320) + s = [s stringByAppendingString: @" Settings"]; + [self navigationItem].title = s; +} + + +- (BOOL)shouldAutorotateToInterfaceOrientation: (UIInterfaceOrientation)o +{ + return YES; +} + +- (NSInteger)numberOfSectionsInTableView:(UITableView *)tv { + // Number of vertically-stacked white boxes. + return [controls count]; +} + +- (NSInteger)tableView:(UITableView *)tableView + numberOfRowsInSection:(NSInteger)section +{ + // Number of lines in each vertically-stacked white box. + NSAssert (controls, @"internal error"); + return [[controls objectAtIndex:section] count]; +} + +- (NSString *)tableView:(UITableView *)tv + titleForHeaderInSection:(NSInteger)section +{ + // Titles above each vertically-stacked white box. +// if (section == 0) +// return [saver_name stringByAppendingString:@" Settings"]; + return nil; +} + + +- (CGFloat)tableView:(UITableView *)tv + heightForRowAtIndexPath:(NSIndexPath *)ip +{ + CGFloat h = [tv rowHeight]; + + NSView *ctl = [[controls objectAtIndex:[ip indexAtPosition:0]] + objectAtIndex:[ip indexAtPosition:1]]; + + if ([ctl isKindOfClass:[NSArray class]]) { + NSArray *set = (NSArray *) ctl; + switch ([set count]) { + case 4: +# ifdef LABEL_ABOVE_SLIDER + h *= 1.7; break; // label + left/slider/right: 2 1/2 lines +# endif + case 3: h *= 1.2; break; // left/slider/right: 1 1/2 lines + case 2: + if ([[set objectAtIndex:1] isKindOfClass:[UITextField class]]) + h *= 1.2; + break; + } + } else if ([ctl isKindOfClass:[UILabel class]]) { + UILabel *t = (UILabel *) ctl; + CGRect r = t.frame; + r.size.width = 250; // WTF! Black magic! + r.size.width -= LEFT_MARGIN; + [t setFrame:r]; + [t sizeToFit]; + r = t.frame; + h = r.size.height + LINE_SPACING * 3; +# ifdef USE_HTML_LABELS + + } else if ([ctl isKindOfClass:[HTMLLabel class]]) { + + HTMLLabel *t = (HTMLLabel *) ctl; + CGRect r = t.frame; + r.size.width = [tv frame].size.width; + r.size.width -= LEFT_MARGIN * 2; + [t setFrame:r]; + [t sizeToFit]; + r = t.frame; + h = r.size.height + LINE_SPACING * 3; + +# endif // USE_HTML_LABELS + } else { + CGFloat h2 = [ctl frame].size.height; + h2 += LINE_SPACING * 2; + if (h2 > h) h = h2; + } + + return h; +} + + +- (void)refreshTableView +{ + UITableView *tv = (UITableView *) [self view]; + NSMutableArray *a = [NSMutableArray arrayWithCapacity:20]; + int rows = [self numberOfSectionsInTableView:tv]; + for (int i = 0; i < rows; i++) { + int cols = [self tableView:tv numberOfRowsInSection:i]; + for (int j = 0; j < cols; j++) { + NSUInteger ip[2]; + ip[0] = i; + ip[1] = j; + [a addObject: [NSIndexPath indexPathWithIndexes:ip length:2]]; + } + } + + [tv beginUpdates]; + [tv reloadRowsAtIndexPaths:a withRowAnimation:UITableViewRowAnimationNone]; + [tv endUpdates]; +} + + +- (void)didRotateFromInterfaceOrientation:(UIInterfaceOrientation)o +{ + [NSTimer scheduledTimerWithTimeInterval: 0 + target:self + selector:@selector(refreshTableView) + userInfo:nil + repeats:NO]; +} + + +#ifndef USE_PICKER_VIEW + +- (void)updateRadioGroupCell:(UITableViewCell *)cell + button:(RadioButton *)b +{ + NSArray *item = [[b items] objectAtIndex: [b index]]; + NSString *pref_key = [item objectAtIndex:1]; + NSObject *pref_val = [item objectAtIndex:2]; + NSObject *current = [userDefaultsController objectForKey:pref_key]; + + // Convert them both to strings and compare those, so that + // we don't get screwed by int 1 versus string "1". + // Will boolean true/1 screw us here too? + // + NSString *pref_str = ([pref_val isKindOfClass:[NSString class]] + ? (NSString *) pref_val + : [(NSNumber *) pref_val stringValue]); + NSString *current_str = ([current isKindOfClass:[NSString class]] + ? (NSString *) current + : [(NSNumber *) current stringValue]); + BOOL match_p = [current_str isEqualToString:pref_str]; + + // NSLog(@"\"%@\" = \"%@\" | \"%@\" ", pref_key, pref_val, current_str); + + if (match_p) + [cell setAccessoryType:UITableViewCellAccessoryCheckmark]; + else + [cell setAccessoryType:UITableViewCellAccessoryNone]; +} + + +- (void)tableView:(UITableView *)tv + didSelectRowAtIndexPath:(NSIndexPath *)ip +{ + RadioButton *ctl = [[controls objectAtIndex:[ip indexAtPosition:0]] + objectAtIndex:[ip indexAtPosition:1]]; + if (! [ctl isKindOfClass:[RadioButton class]]) + return; + + [self radioAction:ctl]; + [self refreshTableView]; +} + + +#endif // !USE_PICKER_VIEW + + + +- (UITableViewCell *)tableView:(UITableView *)tv + cellForRowAtIndexPath:(NSIndexPath *)ip +{ +#if 0 + /* #### If we re-use cells, then clicking on a checkbox RadioButton + (in non-USE_PICKER_VIEW mode) makes all the cells disappear. + This doesn't happen if we don't re-use any cells. Oh well. + */ + NSString *id = [NSString stringWithFormat: @"%d:%d", + [ip indexAtPosition:0], + [ip indexAtPosition:1]]; + UITableViewCell *cell = [tv dequeueReusableCellWithIdentifier: id]; + + if (cell) return cell; +#else + NSString *id = nil; + UITableViewCell *cell; +#endif + + cell = [[[UITableViewCell alloc] initWithStyle: UITableViewCellStyleDefault + reuseIdentifier: id] + autorelease]; + cell.selectionStyle = UITableViewCellSelectionStyleNone; + + CGRect p = [cell frame]; + CGRect r; + + p.size.height = [self tableView:tv heightForRowAtIndexPath:ip]; + [cell setFrame:p]; + + // Allocate more space to the controls on iPad screens, + // and on landscape-mode iPhones. + CGFloat ww = [tv frame].size.width; + CGFloat left_edge = (ww > 700 + ? p.size.width * 0.9 + : ww > 320 + ? p.size.width * 0.5 + : p.size.width * 0.3); + CGFloat right_edge = p.origin.x + p.size.width - LEFT_MARGIN; + + + NSView *ctl = [[controls objectAtIndex:[ip indexAtPosition:0]] + objectAtIndex:[ip indexAtPosition:1]]; + + if ([ctl isKindOfClass:[NSArray class]]) { + // This cell has a set of objects in it. + NSArray *set = (NSArray *) ctl; + switch ([set count]) { + case 2: + { + // With 2 elements, the first of the pair must be a label. + UILabel *label = (UILabel *) [set objectAtIndex: 0]; + NSAssert ([label isKindOfClass:[UILabel class]], @"unhandled type"); + ctl = [set objectAtIndex: 1]; + + r = [ctl frame]; + if ([ctl isKindOfClass:[UISwitch class]]) { + // Flush right checkboxes. + ctl.autoresizingMask = UIViewAutoresizingFlexibleLeftMargin; + r.size.width = 80; // Magic. + r.origin.x = right_edge - r.size.width; + } else { + // Expandable sliders. + ctl.autoresizingMask = UIViewAutoresizingFlexibleWidth; + r.origin.x = left_edge; + r.size.width = right_edge - r.origin.x; + } + r.origin.y = (p.size.height - r.size.height) / 2; + [ctl setFrame:r]; + + // Make a box. + NSView *box = [[UIView alloc] initWithFrame:p]; + [box addSubview: ctl]; + + // cell.textLabel.text = [(UILabel *) ctl text]; + r = [label frame]; + r.origin.x = LEFT_MARGIN; + r.origin.y = 0; + r.size.width = [ctl frame].origin.x - r.origin.x; + r.size.height = p.size.height; + [label setFrame:r]; + [label setFont:[NSFont boldSystemFontOfSize: FONT_SIZE]]; + label.autoresizingMask = UIViewAutoresizingFlexibleRightMargin; + box. autoresizingMask = UIViewAutoresizingFlexibleWidth; + [box addSubview: label]; + + ctl = box; + } + break; + case 3: + case 4: + { + // With 3 elements, the first and last must be labels. + // With 4 elements, the first, second and last must be labels. + int i = 0; + UILabel *top = ([set count] == 4 + ? [set objectAtIndex: i++] + : 0); + UILabel *left = [set objectAtIndex: i++]; + NSView *mid = [set objectAtIndex: i++]; + UILabel *right = [set objectAtIndex: i++]; + NSAssert (!top || [top isKindOfClass:[UILabel class]], @"WTF"); + NSAssert ( [left isKindOfClass:[UILabel class]], @"WTF"); + NSAssert ( ![mid isKindOfClass:[UILabel class]], @"WTF"); + NSAssert ( [right isKindOfClass:[UILabel class]], @"WTF"); + + // 3 elements: control at top of cell. + // 4 elements: center the control vertically. + r = [mid frame]; +# ifdef LABEL_ABOVE_SLIDER + left_edge = LEFT_MARGIN; +# endif + r.origin.x = left_edge; + r.size.width = right_edge - r.origin.x; + r.origin.y = ([set count] == 3 + ? 8 + : (p.size.height - r.size.height) / 2); + [mid setFrame:r]; + + // Top label goes above, flush center/top. + if (top) { + r.size = [[top text] sizeWithFont:[top font] + constrainedToSize: + CGSizeMake (p.size.width - LEFT_MARGIN*2, + 100000) + lineBreakMode:[top lineBreakMode]]; + r.origin.x = (p.size.width - r.size.width) / 2; + r.origin.y = 4; + [top setFrame:r]; + } + + // Left label goes under control, flush left/bottom. + r.size = [[left text] sizeWithFont:[left font] + constrainedToSize: + CGSizeMake(p.size.width - LEFT_MARGIN*2, + 100000) + lineBreakMode:[left lineBreakMode]]; + r.origin.x = [mid frame].origin.x; + r.origin.y = p.size.height - r.size.height - 4; + [left setFrame:r]; + + // Right label goes under control, flush right/bottom. + r = [right frame]; + r.size = [[right text] sizeWithFont:[right font] + constrainedToSize: + CGSizeMake(p.size.width - LEFT_MARGIN*2, + 1000000) + lineBreakMode:[right lineBreakMode]]; + r.origin.x = ([mid frame].origin.x + [mid frame].size.width - + r.size.width); + r.origin.y = [left frame].origin.y; + [right setFrame:r]; + + // Then make a box. + ctl = [[UIView alloc] initWithFrame:p]; + if (top) { +# ifdef LABEL_ABOVE_SLIDER + [ctl addSubview: top]; + top.autoresizingMask = (UIViewAutoresizingFlexibleLeftMargin| + UIViewAutoresizingFlexibleRightMargin); +# else + r = [top frame]; + r.origin.x = LEFT_MARGIN; + r.origin.y = 0; + r.size.width = [mid frame].origin.x - r.origin.x; + r.size.height = p.size.height; + [top setFrame:r]; + top.autoresizingMask = UIViewAutoresizingFlexibleRightMargin; + [ctl addSubview: top]; +# endif + } + [ctl addSubview: left]; + [ctl addSubview: mid]; + [ctl addSubview: right]; + + left. autoresizingMask = UIViewAutoresizingFlexibleRightMargin; + mid. autoresizingMask = UIViewAutoresizingFlexibleWidth; + right.autoresizingMask = UIViewAutoresizingFlexibleLeftMargin; + ctl. autoresizingMask = UIViewAutoresizingFlexibleWidth; + } + break; + default: + NSAssert (0, @"unhandled size"); + } + } else { + // A single view, not a pair. + + r = [ctl frame]; + r.origin.x = LEFT_MARGIN; + r.origin.y = LINE_SPACING; + r.size.width = right_edge - r.origin.x; + [ctl setFrame:r]; + + ctl.autoresizingMask = UIViewAutoresizingFlexibleWidth; + +# ifndef USE_PICKER_VIEW + if ([ctl isKindOfClass:[RadioButton class]]) + [self updateRadioGroupCell:cell button:(RadioButton *)ctl]; +# endif // USE_PICKER_VIEW + } + + if ([ctl isKindOfClass:[UILabel class]]) { + // Make label full height to allow text to line-wrap if necessary. + r = [ctl frame]; + r.origin.y = p.origin.y; + r.size.height = p.size.height; + [ctl setFrame:r]; + } + + [cell.contentView addSubview: ctl]; + + return cell; +} +# endif // USE_IPHONE + + +/* When this object is instantiated, it parses the XML file and creates + controls on itself that are hooked up to the appropriate preferences. + The default size of the view is just big enough to hold them all. + */ +- (id)initWithXMLFile: (NSString *) xml_file + options: (const XrmOptionDescRec *) _opts + controller: (NSUserDefaultsController *) _prefs + defaults: (NSDictionary *) _defs +{ +# ifndef USE_IPHONE + self = [super init]; +# else // !USE_IPHONE + self = [super initWithStyle:UITableViewStyleGrouped]; + self.title = [saver_name stringByAppendingString:@" Settings"]; +# endif // !USE_IPHONE + if (! self) return 0; + + // instance variables + opts = _opts; + defaultOptions = _defs; + userDefaultsController = _prefs; + [userDefaultsController retain]; + + NSURL *furl = [NSURL fileURLWithPath:xml_file]; + + if (!furl) { + NSAssert1 (0, @"can't URLify \"%@\"", xml_file); + return nil; + } + +#if 0 // -- the old way + NSError *err = nil; + NSXMLDocument *xmlDoc = [[NSXMLDocument alloc] + initWithContentsOfURL:furl + options:(NSXMLNodePreserveWhitespace | + NSXMLNodePreserveCDATA) + error:&err]; + if (!xmlDoc || err) { + if (err) + NSAssert2 (0, @"XML Error: %@: %@", + xml_file, [err localizedDescription]); + return nil; + } + + traverse_tree (prefs, self, opts, [xmlDoc rootElement]); +#endif /* 0 */ + + + NSXMLParser *xmlDoc = [[NSXMLParser alloc] initWithContentsOfURL:furl]; + if (!xmlDoc) { + NSAssert1 (0, @"XML Error: %@", xml_file); + return nil; + } + [xmlDoc setDelegate:self]; + if (! [xmlDoc parse]) { + NSError *err = [xmlDoc parserError]; + NSAssert2 (0, @"XML Error: %@: %@", xml_file, err); + return nil; + } + + [self traverseTree]; + xml_root = 0; + +# ifdef USE_IPHONE + [self addResetButton]; +# endif + + return self; +} + + +- (void) dealloc +{ + [saver_name release]; + [userDefaultsController release]; +# ifdef USE_IPHONE + [controls release]; + [pref_keys release]; + [pref_ctls release]; +# ifdef USE_PICKER_VIEW + [picker_values release]; +# endif +# endif + [super dealloc]; +} + +@end diff --git a/OSX/XScreenSaverDMG.icns b/OSX/XScreenSaverDMG.icns new file mode 100644 index 0000000000000000000000000000000000000000..2a38ebd0137a62c291511f56e558d05374cf8f1b GIT binary patch literal 110173 zcmeFa1y~zd8~2?6Nq`!4clWK^*4@2Z@7CR2i4cf;LJ02e-a>JAcP~z%NQ4A3@0rkc z+byNL&vU`|UhnrzX_K7H`QJzHIdlK!(CZiPJVYSf&Rl=AWHADHM>(_4{d@C_%+qd{&&G+v^L&HKt!@~&?xJY~yCOSIO*FE@;ah3@5`ZS)6Pf!>( z92pUTjl@PFqoc7g*jPjyHXfUxo|u@FgiS`Kq+nCAX~^_+Tm~)^nU#ghCgfmq_3{Y$ z=)8pYZl-UeEfDBTf~9v*WFj^hp*kCpjs+(pz`58QWNt1#50{TEz!&0+kj2G>5_~DL ztc*~OufTr5RFd)dLwVXeE8Op92+i6Twn35cIn_1zT5KJz9^Zidh-<_*AwPY>H{)86t*!VroERyQ z;G}pNvb~)u$0!uCh72FFyBR{une5~rkyu#&@gu&wJa{P%&V!TV6v&PaT&JFr0-=)LGI4lL|-Zq6g=q;-#sKgvl{oM zgSt#(L2IEZi$3y$K(X;%jZIMUAXH~Vascx;Q0k-iMV?^^IkincSj9`xveu-ILRuPD zjskt#k}HRMiVu3KG3_l!Y=Y2+9+-MZB<0pObqxyGCcbM-;A8{hT00{Jm2!|X!_!`l z1@$!qS(`J0_zA#n)DsKe$mINnPhVR3b6w$~F{nMIS={L3BUZ?ZoM>4cz^V{rZOwi! zas_pDd|~Aul~UA*|EqgGkHbOj?ODyO;(YrGg(TEi)Cz2hKt^$1m^tVn3=L-+7?WDu zi2G{*!wrO!>9n`Y<(aK*Ey=dE9f?I;KN&%344PM35N;zlYK+jr>Dj-FO)G6`?lOsQ zLy4Ok8=IQ+Kj}0#x3oy&q>@6{#PNeB9R5oqLR6sO?$jPg&w zFx*IJvAEdB&fXs9KyV!F)`Gg&5ShbTcC%JFv6`qt`)6&xA0@NkRlmhIRIjN(_`p_ZEPW0)NWy!@Yaeh)Zq*lX> zr-C6@o8(8^FG6Tvx^LngnVehqSpY4O#8L~TT?#n)5QUc!TpVpMg<4@vGHGpZYm?{45$OhrGEgd6oiBqyW1?Awki@}S z40l*tUYIpk*9f6$VBqvVA+xNd%U$E87}+N)o96ah7M3=Ij`yjdQoWQCvADe^hC|Vh z0ct3zB+G=xBr^1vs9Z?uVcMkf&IMpF13BH7G}q9itcq5Z_s2_z%4GE-mlk;jjYg+a z^((S@`tOuDFsN5=b0u@a0}{xO8bpcoKH2nvCTN`u<{4Qt^d%8H|$N!yGNT2I;T z;mO&RZDP;?@O(s9@_ohfL>iW^sb|@q<;hD>NU&nGv^9)j7}x?!O68?)G*@@Li<+AW z70*N^K#EXa1uWWL8skp-Lx|`X{XpOqnUYi0CYDHGuYztbWxtooqi}RBd`xG4$h+ER zDX@o@H@MoSR)cz@#qE+Ts~|bPO03ITq30-(mL_;re~?PVppPWV3LAb_ zCnz;a-0?BpxP|~By-7edPzL2PQ@~*Cs7VT7Gzk%ysZT5eV>1dre!kRV;@m&u!kt zXBIYoy@XDRrk5&O-02J&saz&$&i2f#sF8v~fHxc6@WH1G&y0t+c z*rBj$V_J}*6R7-KUHjmKtm0;A*D?YpAE9{9tmex%gW-qb}>PMQWV+*!zI-aOQmiuKr)(+W1_7ap+=EM2i#9B*S6?g#PL^+CT@2lLj>DpOG0w-8pWDR0OT z<(JgT;quCItg1Rx<(1b`OMq}HlMaMM)ljRQbqg#kE{Jk6*d{<|t$)Syib~6?lzd*b zjO=K#bPy}cMNB5u4+1?UkynS9HRQ?lfM1hVwSvK_E|nXH0?{ls4T$n9Ac>plM_5!^ z6ys(PCqQUNKNkANWaQUK+uPwK*qDxvI+2G|Su9{OX%2GGQ4(o;k=48MM!0p=q#aU% zL|qI8SOd{K4i$*9iy^76VKpo&D~Md$_3D>ubx^2#%C4Q z%ix8NR!3*2vV;?^fHJWR4H_**2^hZY5x=N-x9=nhz{UCc=bV%0); zA|)z26PcN?SVv8AAhSS#z$ z%yLNf7RS_JQ2feepd&lLS7`2$ zY5C=1EWGB#12I$(y9Sc@g0mS0`I*g9eF;uXmT1XZ3M}g(NMZ$a&^}_Qn&%Jh1<=ao zoNycZdLE*`E}rETm688Js!+gp3V0>D!#f_esyD({IimxzC>80gygocl6xyu zFZ7VZO09X3j>K&|M8EY|fp1J^VU>rXkIOEsY45skLATghv?}ZEa7;}Gr5S2ZZ|o4W zfp=C&9gXY2koPcPVi{ z3mj96L8*iwS%F+GW&$NClprj{LF!6J3M^$&2emnw)WK4+(s*x!3qb1CGwYzF+~NiW z7Oa%9kY=@!C%96Wzz#=?=3G!*6qyLg+vt)3VhL0uv@a?tEGmxY&~Xg3Ni`(#GW-Cm zwO1tgQN*Bz$6ndJPtGg(2&Rml5(lBn`GM`qVk0bL0F%ieF$G|WRD}YJTabPEb(-gf3u5$f0~b4%VZS zNo0z?VXjgk7L(x1dS|o00hNv=qevt&UF9*kMNoS26I{a6@=IHQ zpdN(IVuE>?#m0g43YtMQ%#bN$1`>=^uBi1gps=t^H3ox@Wq|%(N;7S8AYG zU}2OFb*940T6AYaMu-Vdmy5s{(Y>NG3oFEUr9Om;X67rQLK<@jg=CXlCkFQy3b{eJYUh6I70p{79SC5E74mTLMn=S0{MLpTWSqXeOUd`@vyyHZJl z)I0q-)nMX_bJHjpLo)L%C?pDl!{NJn@u>_Z_g#@H5JAjPOUspDA@vHbZ`XA%FUnbO zBnP1t^3o(QF|VXXt|UY1?H+~=Y)GThgh8j_DE+8Z3UFC0Z{S|RowRz5pg-rJ(2m+P8pz3D@WSLu2Bh9#V&4q+v7|W8OMfTG z>HEU=Js35roK05Ntqe#_UTRHd;u-4PkY?Cela*!HrKvQ*mm~vOR=;)(ODimG>;%SY zO`RlENJA;DjW8mE_C_(;4!JD~Dx}`xU{V8Hl9ea<)AB&J3Y<$g7z0hf@u*iAdV*|f zl0Yt;iNHi!<$^429){&zLpnK-?E|tT>$^u~7L_-{SqgapGH_0lvxT*R4a(Zu%F5cB zV54Sj14f6s#Gk8LKPswIg9PRvrwzp`CcC(z70#K>iteNVV-hJ5TqDJ8Ai|*sE}0Uz zlpPUlaM8dh6}9Q_jTyRZgr#&%iolrtr~pU;daDC7D96x z(I_w}ADm8wkYZ;c=pz#*(oGDX)07+KNT>$qB)&EaN-ij?Y0n2O*qk5Zg0lsw)o-jq zQVYv#<#1|iVXTMVL6B}mL~d9QbDQ| z?-rF^QqibNm6az4vYbF_D$z40r}RU!5;Az&XbydC6P8i(p{~6UoZOrr>yDocQvZ14 z5RqB(pRW)_uHfZMk`F-9hDDv0wohz1!dajxM}fvyft zI2VR1!_D5E;-Ts8^)56z(wkxjz7HfiJDQ3tJi@V&geY7zK86sBjEf`0>m^_liAls{ zd};9#N@f&EH1j5MM%6lumagMj^>{vgT37(GmTv_?8}# zDcRtT==0sn_c6FYP>H4_FLRbI4bdMmV%h}6rsdVZ=YEdyeT~-@E{CezW`!yp4))IT~XhL zm5`-mnO=L494%`pPkv|k1bllJ?;Mp^+0X{E<#l4DEgwH*hL}D8U)-Vvq?gw=w#Wo> zb~{7Hl9It1Nwc-FzA`_?=Fv$iLi3(kOhNgFit-BK2a^h6IjKyuyu6~UAi?$NO$tKu z=u5Zcy!@QZ3|yKh-6X>>T`x^DJtI3WC&~M@1qFdV{>CRcGc6ULk_-N#Q&ZED{ICWT zgvJ7rS3)X1B^vzINKWv>v8V_&qFW3hnVaH~%1t38tH(Iq*-k~M>)A&p=_hMMI`Z^z zSZtIo7OR2N<2gnWlQojUEv}9Sr{FBZ6Nt&`k;1Egr0h}uYeZu4U{&UULBHi6KJJ?Igci~d}Wz@w#&m2EPhffG3{|QbwL-39PC)nM+ zdh7n&=Km_1VQoC#IPiC zvVNj^d=UEt1ED_irDHfYftTo!q?bra1_}x45e^R)F%cT8-`Ky8)lY~{L?$N^lJyfb z;==5nZ(t+P)2}m}-iCxTBbib5k)#NGI4U&Am3e(34}qF@>H(HSGhhg4R4R?4PsWq< z_3=cMzQMEO3s6D?5~X7?JU|E8PYpu+{g3>AyyE`_UJ+WX3TOdG`ycR%0^xtbD@xhy z|Atq1vdsP)UXj9LxctYw!iY|P{~z)SXMHB;KjanuWRkIoidUq2*#1ji5kWU#+QGb{ z(2AP*uXsfQgG92m0KCGIVf^oSMHHP(wYRG6h~RO3{|T@7_z@;kxX;AGokB8ph?LcH z1g>HKkXU%z*x3>7@eYF>UHBxbhrq(!ielnx?BwL^Om|Up_A3V~#h!VEkOh#3o+H+2 zkgF4qO0;yh^s-=+M4l$jELU|mL*6f7MH(soE36o#NZ}jM-rCf5MlmQHx8Qb)0?~n2 z0A4{)RNX7~z$-}k-|&ib5t(S?@7pPJq)?cyJ}|GSrpLj7k)QL581i?#qF6vCQG)F2 zJIf6zRH~f=%qyyxVX7$2PkBWMrHfY-7nhWj$HcrVu%?g=1feFC)j-OFZ5Kchii9+v#C0$<#0wEd`a-lx z0)Q4mPgw2e(87%epoI~EGLXfk&{$*&Mc>880Nku$sTvfjjWLx@N5cUabH`sH3wu$c ztbmQD45G7{6ebfW8JPMTfV(~%RfBA3#{j?p%_xM#c9v~$kNp%_jFWw`umZq>K>@8x zVX^2`4vkEql36}%3Y~$Yq9_zQ5sgly>CsU+kkrk%M_w^rCaW`Y0=z<{MyIod`XCGe z+KFUoOQz8AR5Xe2#G;Xiczq<1M4-dG!cXuEUh#qJ19$}mOT|#wWUhme85v7KQz>*? zu9*XYiZZaWqq?}^oz+~7$#^;pD?&J`8_FJFMF}fdDv!icwJ9{VfzT}?5=R00XbRid zCC7*iYE7m%nglCgSWzz^Aa)`Ufc z1xd~@qEHJWF|c%$3t$w?5Lof2jAED~m|oe@)l zpplHsRD6O0%4iSx1lPZ7)^*D#hAR}lton`y8z9K1Q>kROw^4NwiAYr^+SxJ*RCNl? z+#N;}R2&^``4RePn`d^M^$B2w;GMg~Ji-^j_N)k=>>01k%&>=3AG3|a&XC72W- z$}NY)F2+4Vi2(pg7`Xu`!2_afI+mhIr5e~6zt13mq9Q3|eJYaW1Oo{c83-}~knk2% z!Q=cVKtc-!5}W&{m-c zR+s|HpaU@mn}!FS!m@C5)MLO>bQOo-k$_Yh;1J9_)%@#$L!fgRaUD4{yl?&laHo}Ldp9f6MI(?PSdSuCm=ne7Zjnv7vz@LmoT&?8}yo)84R z3`CT1bPXCMSVS=Zy+@%@HAyBWFnutCWdfy888Zl8d-Omb-ZHBpu{SKER}l&(KLR*A zEQJibE7`*c1`w8dVD6*6+n_3rF9?_QOdz~C-~#9dY}53r#3uUsprygMB~!J?%m5Y) zA#8yAM7shAA#nQ@gm5+j5W*2h$I$evp-hqijYriYnF&E=Kp{Z=&<>xVMiYD0CGzJK z!p0m>2wNOolSXQR6oGg$jRWQ+lVMg5LkJ=m9BAv0P_vcAFCc`eeVek%T%}V5K?-+$ zG8@c78pG&=3PF%yAv1s=97R1Nh$=&OfFMM47~xZ#3W`di*%UI1I)cKcxfGTZ78b{` zfq$pd0Jao+3VH?*W!wM&APljzeqc5m(3vbAheM+>bMKYt9qJilQv}jZV1FXKf0Vo+53v2)$!k9gQhfI1L z0E$c;Sa_gmbPkv&V1S~*0A+HSz*DOMZ;qvb9%N)gia7euxkC~?tpiG?gSI8owSdFs zF=_BM6n0x+P|?{OxEZlDBo%xQoI+4KWpcSJIvsXZG!~D?hAV}q z>C;gKfIHB^(=&&Xhm(XumBn~PG}c*5ZV5m zJ2YBYs<=amB^flGI{SSWcd#)3Id`Zrb^sA`m^*|UlIchqJYnc`rd>`Kd$1FAf$#3v zL%G01#U29Ks*E@q@SGMZ{NTp#V%wG7;RlYt3O_iRSsGX&Ev;~t1S>U5D{u#+F7ag- zz)jjMe8^%%{S-bZ!kOSg@iX|4NRJWI+Q|x}Tn=u!VDQiup&F4t0S{bL|3F%Rejq-8 z97qk&2=p`N{v15CISE0Nnb46gZSV;FA9(m5c=+b2*Z+Zs{|mtb76uQ5e-9q6{0cl^ ze*zxf@O};+o-zJY@PPk0c+mSN;6Yaf9v<}!9v*iC9$3eJ1|IIKz{6|1pMZyJ^dG?k z;|dHO=A68*OQPw4Rcs&%+;He5fsG)R*=?xbS1q4Fte+1(H z)g2R||ILnxg8yd6L@De4O9GL~|1SuH8TUUX5UybP{vQ&E01n5<=re(^`?myw$L1S( z!vw;T_U{NpynxN-v0(ziH2HS~B7)E13WR__7_$EZ0^z~s2>DU6dVx?F`cDajt(_gt zp5QRd(b2)lMabb9GOXOKxJE`M&i@KR=sV(_1_J~EO2D)AHWzS=42@k}!6O;!?!sR} z2=ZSLLPwDzVhaT3b)8X$Ts|-8^NxvM6A1Em1i}oIgB#c>bLMjSM(+O+fe>-o0z>15 z&N5Rjk0&yzhbac@pAZOSeG#q%RUQohge{ia-;iToRUIS%B1Qsu!^FP=5IDgIp%IH_ z1cn7y$YC2933)(BV8j>FjJnu^QP1oFtzr)%5Su|!*gPtYhvT9|95{xD!kWUADBSLUgO(u_H$c@fp za0ongBaVj`fv3S0m@wn?AT@V5^7d=iFdW_&L4{cZ2+vSCJdP2|x6YiU$5R(@Erqb2 zp&_$@0I7L{2P{>fA@>)c0hLGvJ0iSsG)*3l%V%4C3Stp?>c)Jo02God;sgLOe*;(y zK!%cEKn7G46>NrZ1Mvkq7$kfFv#6BMC4hG0f*HxzF1$P)Lz$FBopkcxY z%b+qr>#1-;J{#r}EPxYy1U>C=rqWbpWSRiin&GWiTpD0&?nSL3UO9K5ID*DL{*#{kb#C%~~wjsSF~ zh;PB=0x2Oi6G&AHRI}k9f`s(1Ac4sRT?m#6u#$ip43z4PRFm`<7y%CM!Mhm%M(9vs z1TY4$po!GDOeY`$D1yp!{0bvrl^6($_{tHeL8e?#H9na1TslvaVbnzuU?~+!=wTxR zPPHrI9Sa1lePEVAEDvRqcvvolrzJ3AHNY4FE)v=sY-Hg2{SqU1a{)$h2LWP$5!%dH zU{r!j3Xe)~O*q-%K_U1SR@Lbj#j|~ZqM+51>iwGk3dIIu?8As8cP6# zGz2^b9eh>?Fo6biIR6A20DQ&*G7LOjody<=R4^R*JO&8(B4CyPctJ-Gya1I%2m2I~ zsUW({!tzOQUO))oydby_?@Rb6cwjJ%!Ql&lRUZ5!5CZ1F{O4%E5TF4a(12h;#5XiF z5*Ql`=rkq`Kmo%pD4^nTKZOG9FWV8))c_O#gNn&wfomoQOV{AMElf)zrGvc)T~NTM z>pIju6mW;30J2g<0L=*YBf!qo3kPovs1~^Pzyln<@Bk`Zo%?zFfyk~03}D%X0ZJ_y z^sf-W(&C>$fCwRruEDhbyz{{RpG5yTd^*xn74~=UDeTYv9QHT2wUY=;MbvkgAT%9TMXzuY%%y(k$$n$TRPJ9f7=WGx4qzh+YA1$++KkDZhOHiGKliO zas7UK!A*F3!7IC-wijH0qx>%|y4_x2d>%aU|HAmk?FAs-j(X1NHp<56d%c7OQU3dIl>Y+nyX^(cqaeyZ^>H`b z3vMp}+Y44c{UOS4`{;MDyNq8fwrm^PwCa>w!Os@IP94`z8XhK@)YQ~;eeQbg`uHUg{tCSBdQrVs zo%`kMu8h@{*-qQEeq!;vWX+o;oltKa%38{h?<{ruLG1*1CaISW$!m1CHor|A3mz2i zwWDIix2C#%zwJ}6S%)C`y>4xOn|Mdwi}sZwwQp^8_g=4~H|@LrY5=GiD|^vC6h5H4 zI)9UfcJ58{P|DD6Y<2gx|GQqbUof#dqu-fai*P_2_uho!PHx7i7I^9X#02 z{A#PaH*b2^{Q(E)pwXS(FKNu)x%K&`Q3HCq4b-sjW%ma`i9OweX$O2$(%yNSGyY3k zck?X79Z1(E;|l`vaRBdUAlPdfWX02YCKVV|Vk~>+TPN zI&{0S`z7goZ@a%=IKWG5ZI*UlK-V_KwN#RO^<0G55pk?27Ns?41v7dw#I{C1Gh@ z@0k2fRd(i!xgTElw0(DG?|kTZ@q^tj31@oW{Q(C^`C{&e*B8CL`h#0kY4cMDNbLjn z*MkG>6ZhAH1MCy`2SGn|fPLcrAn2zKaCBDh%(%a)*8j`__KEw0ptij~OuVjy#kGGc zY43cL9{-8`o#5Bc_Q9ce^b`9hqbCw% z`^No2kn}{i_IHElRr}=V=-vVLk^2Jwh=Ku#q^qKwA>D|@9j{LCz+nf8$zT)AJ_L0Z?X7vYGvXk^91x7yV%?EG3Z(60x$@K-=^CHtN++8Dsu#A2~FtS1o=oUOM{+`(yfQ^#_-vcKP2YfZA;E zi1jQ*Q_)cwA5 zf55)6*5B-7`T~9Y)eW8lzaM~V+P(YS;a`@!-bIX5|LzK`Hqhhmr}XOQ>WSY^0FB{c zy=w38;-8j%Hvy2SiM{>c$@e9YZU1fpAW^^dP3-GSDLO7|emek>m|cAl`u}1bOu*M# z-`ZExJl{95udgNGX@5Hb)U@C9;pzu2ghzjkzdR69qo1G;S3j`*u)*I9K%~aNzKVUp zw&5dl4Cb5qqlSccCHL9CrBlC|07%TpzPtJBs$#>!Zzh16=7_$#`R%e_HvO9kpr$$0 zr_Wlx%TV^Det%6sHO*mGeLVi-$MpN_3Iyzv`q+NJ$bNr005$Dlx_#__+(&)mfYh~z zUGB@}7x4c)VE^k1L|uFMsXo5`=#T!c{=;|nRq(ZI_;=j>#y(PAd&K&tKAnK_^P>m+ zHU5D8r62m#e%pb+*`M9F>%ZdV-`dyE9zOj=UoJqDR^!UYwzvWOpKrZ+G?qoPF7I12d(0q=+SdgTQbT*_qy_8toxc7E{HIyqf7$%S zLGSMPMIQKTI{2;JPi~$&v}w_l5&h9$7vM;whUTEr)0b@Ad*b}HTX*i=yLZ1g4xoGY z_VtUW4sKa7YwTdHzq%iRR73R}GIqw|wcGa}J8}AK?;WR49y_#i!?HOOhYi4}e{FtX zUjs8>*!UR>SFGE-edn${y>;x~wSCKmRf}d#95GN!Vzzv`^aQL{XvllK|zH)W% z9V?eF{cY~_2_tm0zZre-WmruEtvzt)$Z?aW&zLp4_l{XJrcaqLde}g1j0W%Ieqt$P~z=4Bwdg~Z8aNvM` z+L~zC`ghe=wE$90T?2*2U@)4!bpUNN3e;Wg`^Hz*|NpQ5T)+6+Dg<)+WKjS9Hx5ji zG(g(`h7-fCJbHfb#=XUp;CA`^x*xp4`xi%Czjo;Xm^0ul_^W~Gx|1Dr@$Rh$UA+oF zUoz$5rOQ_kU29wA>;he}4Hne&E1y=n`Tu0=fJA&GVNY&wsLP!QusrAQl3y8gklF zkcXQR-Z9Xc9!77cH058iYC4kO$tt#8_ii>L&}C?g<1>Q#b71k8< zrNu^H?6{R)LM&68ox1Zt}4RlAl83UZom1v@Akxnm73Ql>7p*Q9h`vA zKXGWMKF8Zcd+;bbpU$WiQ_R+EqRcEC^9S?L_~yBhhl?Ix(?pf0@WY~M_kFkOZXdkl zWqO#HydHmXvVE#qzr-Vx9agOu`nYM&9_aZfGv{hEKKT6VMJZ2~5A+e6OsqR{&uY$j zwUN)Q&mOrK*6Kl6dHX?Ab;N*a8|Mr^bcgjRC|z$iHu8kg^(A*V&-l3F**Wf{Nf*sW zMWJh-t_?ugmB!@1!Wk5$Vtp&>bjSF0H=Jmi&36_dyjT8_S@?`FPixdz z%9=H~*`GGB=bEivu*~L}y$(?taqY_V87bk>gCAH^7T7!$-+bVK8T0gLQOwvmYlpnA zG~d1jxA#Qrij3{9mT!hUwz_l2PBclRtj)WE-2i@fhUB+7{a0O28~0|*9oyU6UPj-4 z{KxxoG&QjXW8BrDCl2pr=@>7`8;!Qwm8<@)zkP$KitKeO?DG95si#mLnOu|VRT*S< zcFVH62elQrg^%5L-!u7>y$+XkKz(_^nkoa~?6^5=><%_k8iMz@DCSJD*}K4MOuv^q z(ij<|HCaz4O}ex`=#S`(tneajn?w5^n$)jNNe*C!`x%t&MqE%2m_PT3!KzNv&c)-- z?l4qyy?{T_ z2A;Ec6f1pwV24Mc^OJEQdhWWdmJ|NP5N(t?8gPR&r@fy9-LHanhqfU`C``dpv@aX_MRN> z-jPx?X(oS!M=QpLzwBZEL4xH&$)kK3Q&0YJY`nZZRQ>9q<4e(7q?(-(BE5u%^^c4? z59L0m*PNa_{+Q_6(70`CckV1ab!5QiI}^tH4M0z_e-=Jt|XqXN?YAySUSKe%mp-{W>f9Teop-r;V~otKXXK={kJ5P571 zF_c@Hhm6BMUN5M=TV$`?p6Zad+&VF5jK_n~oMAy48e686Aoy98v>o}JsN&5_%S{$w z$hSx9%|UV1X4ln<*FqG_O}ctPCgtQs5`l3<3GoIxlQJ~XAqLOLlUFZ&Fg4Yjj()PP)m;8yU6`d7 zy1?nG?gs8W^eo?i_gm^Z9a*}@^WLMpCF7}Co9?wf+_Sk=%d%kE!t9)f)k9_{_})RX zZVtzXw&!kmMX^}-6oEUN)_ifjPRTRbKf*{YB9_2odTHaFyGmX$X2M)0Cp)|_SR+`F z)#kW}E2t~YbX}|~%Nad4lD@`$e(h$3tIU+K3U~2TKFBIZD-f62tm)A6iMI%i${}B;4==9v7s^h zZyJ{6PhEceycSDg=GU?Nu4LY5Q{rHXlhyGn)8BY!IB5^#2b*Tjbm5QRI{x~k^X#od zW8B}ou%R?xald3;WAN%x*f{E)%#n_N&N)=Do+mq|FA382k$XGtihEE#t-hN4bfi%Z z={KV28gF&;_L#EwX|lU6>jxN2iu{Cbe&;bMZ%D0=!>ITu_NFpB=@RMy(^NC}JNjdJd1y|n{Ic^JDSjo^?OuBzKN_WxhgEJxA zWLcFbS8q>dlVbUspsj^B-a-2w&(1jaaBWWcfYEEm9Ac=wUV0kuw(ZRy>2Xm7yRSu@ zUg$c?ZY-ku{@D5}n|9bI?ke_b*m?G7-axO8#bH`!mk{DEN4u^MYb|cMq&4{ZMAvhP zi2~)~n80c~ALx4UxChSdyN{edpM3g=ZU^3W+}(Q%XHO%ay=k1j#COy53+??+Z$5XG zZ;ID_x=MI@s|IRd>FiU1x6=l0pSn4$dB>5N3#ryNn>FTEZM@Jw%jDtsgAryUl^bR! zrr$!9F$*!ncdq;M*u~;Gnq240##gs3bMIW3uvKo$;kVwt_og3fFKha|jlboznOJXT za+j_=nXPXNcDF?*W%=l$ge6n=xx+ zqLca7$jC)H?Poli%JPdI;E&yYbMwyprT1qttdH7E5rw3sWM=D)+gH%J%7JDUxOW2a zu)hpD=IDiU&;Hyno`Ff;!QeN?~pcKx*D1+ll1K3eQtQb9_?HTg_^c{YBTj?SOi z$3~kux@)I3RK;kb7vv1`SY8p-lyUAtq3w(nD-g}0H=Cza{pqE+mDXv3yO->unSS{Z zvSxmN+x;2-nbRgbI`d+}a6?;rs$u%n$1ymR>jIABjB#c;+oZBtb3>OjhU@K@Upf=t z5l*)ZdbRo{EAXS-_ISVLSM-NWn#OwBPC2?xHvR}_=QPgFsRM4Dv7B|QGegW8AHc66 zKism!H{?F*w^!>4L64_4zI1zYWq!O8kwr8wr`At*w%$ANz@wVXSu*Su(?Rq$2M;sP z$E#=B359mg?PaCXkirTt;?eor#td3k;y>i*6IXZlcd}VK1^a!cO`N&$q|FBdtfS&zacSy``MDr#piao>L1S!EjvDTq4_MsZHkua?Wf14w@)tEg}~3B zMGXFc!!nn~VDTS|KM{sa+he+_{KJ!nakYCia=jkg^KUA{e8;_AlD58GeTy4`rL$}5 zz$V`f2%YumNz(^f|4zGQoJ7^>*mZQJ=S+Ix#bJ-f7G80*=_f6|ca!uk&e>u1i`E^- zZLPPb?p_bAS3`Pl^)4-H+Ij4vtDEPv$3u&0BLfz#?EHWoSUSbIiryMaVh_RJPZ_Uv~hKc^oh)D6S0*}=IqaAe}D!~K_3 z97!s9c2X@j4I_RXh#P}BbkI>JW%EI+vyG!_QZNp)f^hE_TF%VBe5GIF?foM&8&@8g zf9sU~y_uSYE5{T$mE9$6s+)S&KZmubg1KP*Z;$Z_hg#1*FP-W7KBHy%vzn`ipUkLJ z><*-k%8oO*=NS>=9dSdb%nlPDIE z_&8+MhQ-mYxFq6MOM|n8Z%~Vp1X71luRk3SEqIL0dYW=`r(0V7xTEw{Hq+8RRXf~i zai{F8-}r_TAvu73K@IPrbbZT}j>YzP}TjIO|qKtoh9cns*2386A$6J}rG!H*{v5vD2I3PcxD? zyn1bC{jnH%*>>`pvx!5e7R0@Zx;@o>fy)ldwV#Hu5xb80NPppa z{80P2+lLB0L^r3dUcWqT!K^pbkjT4l@RfNZrNKA1Po03A_hCxtzKwUsI_`d(bRzQH zfRXd|Zx~kYv@S*HoOf+o%gdqtuH@&(c&1F>B&msAsyl&k^;G}s&u;hE*>a$sz@IR&pZj#=ATkj^kjH_8{5$~3Yi1J+(_(6!Xrg3KO^o*yyq;U3}0;jP!( zrVWtFYKlsXwT9zPmgiwlMB_{;St-%+{>9_k{pjk+vx4%2f6LskBX0hEOxutLA&1!! z9~~!4GIU=1?hq-Kzm_Z#-ObDlSSUKN>Z0C=kQ>UPJK6gy*Q`JFJK|W~ZT2P6>OBSz z56tQa3A+~klxQE38IeqCem82~{PKy4TM<$Fk(L2!>JqK3QH^alx%oo-!OLzZ9WTt5 zQY>CypMHII@Dbb7)G3qp7uf}!{qDE?IeckjT?mPoJA9b zj25`ezIkERIKR~~1GUc_GsgyZ)J%#s->dNq+Jw=txVu=NIaJs=G<|9(kv@1~&Eu_Q z$j%8@44#qZ{I2uj{>`aX8%S3XbGVwi4I>uW9$DGB^;GDL(dV;EW(Z^E*hj5?IR2hN z^}LB#Xu+8K9=WrJC-1*EV20q$_9~@xy7nJK)E7(dJaVtyoH%@Ed=vGQ?N8CD{=Rk7*nQ?c>+%jilhzZATAJRvjCeuXH+`)8+B%cdF=fZLmz~`F z$zsDS+yeHbP`yJ5F;y<;qxyd|4avD?DOxmc`RH-6f@klo4DsuhY#cf;=4ITyx-t9b zq}%Ob7ROs9D)l839%+qtYPnEpz7yfPe~NMt^l<*+s>yQmp=TFx_C{yS$78spYw=s$Y0WGKn13*g6Ihm zy6#8DO3R*-nwF1EJ902Z?B4(EuzQcPQx`>B9k0Hy$?kXSms3aVi(DVR)qC`;sD7K` zt}VF~I%>;&@1Ty!Hdg}mrd@ceVk=%Ls zy~vXx)Ap3V4L)Ukq~ZjFdphi6_5CqEdHJjJkJv0-zRXuJBz=RA)fErT{PHWwUa=v! z8taqlQfWTC*R3A=r#iYX3V*#LZZq2_$FRhdZ~0q)GgAVgRYKyKhqZ)`QATLZNPT^B zQorjn7GFGD@~B?0%nW@Et@waB*npj)R@r)F3QsYt)YOC5diKg2&V=ZxmLIL1PR?v^ zI9A7}yv|$J585?(SqJY7GX27HPqs^bt>&Qprp43F$fn)KB@djG>XM6daki}-yT%5Z zZ1ZvGk*i}Yv#ywp_qct8+^>Dpb)BT?h^>Uv$ono&V#;cz>(}qsd^0{3YrETcf$gFL z%G(=QQvYfw~v3z4?TT< z7Gsr3jHBC4J>4d@et2qAuBpO?~a~gT0#u8ojt5maj?_#*o@yB8x+LI zC-3iuCp8SOn!Bz>?NaM)!Gn{$;bU^N{bfW*$ z3WMM^*H6dlE|VGgwytrw7QJr}mw4mW-oW5#!>;=YHConf9B+Lh?!xYEB?Cmm20b|Y zdk1RUTk{K(99}NUHGRGa8o6Y3{M_7md93Lj=1!*#cN`&0pFg_RI&%aWXVB(xc(eA3 ztxF|kYib+snC5h9>y6klO=_3Y?0^4)f`5XIbvt{7To{;NkZ_q%X8d^LxieQB&n_Eg zOT3BQHI^RNaAoqomk9=k-yPn$j=Fy1(E~Qz_L(1?s|sHpZX03EY#EsTF;E#VT&Y9+ zVEj0EpNyY${1q>Kp84BFPRqHYgq!+jt~b@XbC*b6V~P~Zp-uCi58gjgt)U`tvZMre z*C%U2_=A{YM(Q?iqoqrHbTbrFI`T;#haBCbu4vT!UY2lm&-mCe_VXTi?Uz5rOf|RF zSvfIf_T!rB3#O?Y<-zr1p0pW}OHK|NSzYXV<#F1$!CDzf8wX5IDR}8?uGRV{<~Tz< z>HUOD*ydu@Z548Tg=Pb`(&OS=dOQR4XxBH+I@4y(Cc_N zQS#Yi5~4BLTK-OEAFwBR3D03`^XbQF6GCxkj}J_}V%BnX_~3IvYQ?D{;a1lNzn$F? zYd+*AbFOu4z9Hty#D`)`IP3T8Pxj97TvbrAsix4kVQ%n-r)OL`%f`6e*lqM${`$$$ z=vVrqhx2{_inMoLlLqt5BZxMPni zW4(N}a?Pg{9Jc%oy)i39=WQna20eDfwP3?Dt-m`S4DdU>eDbqvzPE^H21}`z$d~Ff z$Ire$-^3%_h-LI?q{V<6hcipdnGq>APPj}*p64RLqt551^PDCvsoXP_x53u@^vO}I zfDNlhx9^lW4aJzB>$f;|>FKzZRP>;nq5V4fdcF;;$eH7KB{Tf}2F{!^Gjd<$q42`n zp-l%ETZ|W_4@Eu=+gdky!!h|3MExZ@us+Hja-t=|-#l!MjExw6<n%I__`bYk@M*+J7r4K=?v#|I~m z3^BHzKK__lMUB&v`lNB|j+m*ZU7LA!x20m5c7{>#*ipOUrka}Gytu8zsOV-;$Vqm} z0Cn4SqneKoF@&b2=FDxKqEpQpY}cW`&(cRT<@xYe!~hSsDIt89+v}58#M#_O&)6aH z%#rtpo_WuR-k34&pblXMp<%gb)pJUehsM<)RLt*_&{4DG*I5bEK1NiZ-*w+QXL zH}8LMLha9ad2;Q(Bf9Q8b0)_PE_~>#YxmG@J( zcr@)|Y;D_|PYhTxebLw#kS;Vo;FW#kyU+sPk_KZ3iSg(O zJH68f9v{=RP>QRVkauGK%q368;~8s&>ZgqkQSr6AA50mP{_N8})XJIYFyaYk%84a- zTbjelgM7ywhgv4k7l&uq{@Fi^C#9d zU(CL8Y$(Ojw)U;1En@Y)_6^s~=2=WLWf$+l{hm22Fu(qfeY(x0Df7l(^&9}bvKeQc zX}ymX%b3r26LIN0$D#|MAkgC^&T~w-j(K}C)(L9jH?JBh9|p}+P84m5zwt7>$#dxe zX7(Kd!>4KDC_STWaduES@k4&WWVxZ{h*pSAP&rZ=P z%iRx(Tc(CRabt`1TyF{^4-T-rZg_K!4qB7_;lZlm??!Lm!c*PjgWLRR+}Yy?+df}V zaNFbLJJSz7JbKXNz}h9{n#0uHZ#)nYH)y=L*&6=r zi6wd4%uNp$u1H!izcH+Fi_aK8qbL$VsC8WLWqsD2U9JZAs4w{D=P#roNL<$TlXuwn z3Z7nlIb`R$t$)6wB)1q57n40cFemzIpWk(iw5mPk&Zd%0iq;IgWJCWX!%2G$O^@#0 zD4p@pD9d8+u%wfVXBcpm3$F-{^HxwBJKoT`_6KX>oO# zPNx|LdIYU{7_$ADpFOY&+T5 zwr$(CZQHhO-2Lu7-}!Ur$5dBMO;7jC)bQzUGID6UmjwB4VI&C$e%h@dQ(nD}9+_%Q$;A=g9I3-OCqBJxtdey~J z8W7R^J0^-7`929ntTHN_cFAW{aUa`p%q4u0;^lbM^$?b%OEd{)T>e~ zW$%hOEbP=LeH?Rvzxs&r*I8Nk@Z1GtPYo=fZogG5g}&qspmiBjl;ZpxJBhPtHE4e`m|~6@qy7gCH1nRSp+!>?#c_Ai0fx4trh0gJ-}V zV_Dq|a9B}jYB+d3BLV$zOZx=?Nkq<5ry}8g?`mkeD<3%AkB6UCr11Y+`y5ERN+lc9 z#aX@;D`sJcsU^=r<{F=F)|d8okp>c{icI_sqnP{zcr@&k0fyNvei>@+O72r zET8unV>%$MHjS5~IIZ$@KUyk!@vwnqr%PQH1fjb;6hh<)@}50GfZ>Y5H&Q394q9ZE zIH%etf@8#pKh2>YMT{pYvx4W8%wsm6Shh-mS^-zQtlqN>2ww|IO~&fmkNXtkBjlzP z1*~dCNxbjOP`MsYw$A)Vd{oD(hl&M;IYjKv@(8Ye$aMk-(<^4F5cY$vco{^ z`uUxd^4zKs@qV}ud*Cs|iHu5&NjUfvW7TuZk(&y?6>Je9i35a2 z!6_5Zu~ljZr<%MDyTN(tRGk{jgSJhHzUL`=H3myEjFjJu0}1D^Z*`S>TlYSXFgS{2 zGp!3|s|m>>T-Ew)%)7b!{tm!Htireahi&r%#g*`+?e4Q%q3pt%{w~C9v0PBhR%;KH z)n~0QnA+JB=^e*#18-R!M*Jod^09C>FXTu%a9XYed(>hb@=@v9VU7{Bgo=&oo5ncK zGFZIZi$-4gy*OFgWu`-}S)~1x#QeLm^iTUOJs0{cLaigFJ6(!kIZS2p(&^aY4HDNfi>HahlSC9jf0*$~7Ybx9omVwoOWbo>|5`E` z)$&Pm`6AeZTBEPgmg*3BPCA-6WXJq5?`F$o9r7+UZKiN?3GmX>#0n;#l`l^FRD40L zEnpbZq`_EXR;QBFOk^j6Qn!#ZAiA=?am-iM>ef51@iV~p!D4B*VU3RF$;&#*2%5WA z-|U*X9luZKcd>^pl=nnHC63ogCEeUCm(y0%m%=4Sx&RcE>{t7%ETL#VloHNYhtZqi zhkg+3sM{&3Af3*;6SEJvD-_o2j&#GPTWQWO*uDwuu7hD+Gl=|}N;T|c{zpX7;u@@d zyI1}YP<*>N_xA^x;x_#6fZQWQ#s}m_7*cQt&Uey6&&_kw8fYB}_WaS6pS?mEao%bSKpAa(Dex)d1K{(@NoV z?ebvQA<8Rj4GVnF>p8u?m16+uBI-aOTg&DI7O^kGkI(l96fq#_Lb^Gan(R9t*gU8m z>ep^?vQ8XlM=5R2gS|w7U$0LX zR3gN_g=~24t6xM1hl=54^Q=B-_no?e59pQ(>O|?-QheYitI8o62b&{0ca+YEyRQ>p zM77JL!!NGOk znk)p?rBM$-#y0BfRPA0%NiX(%_QPzHln^)R+MJbc2*9-~)#;zN?h8PYs7|f7*~tz! zbP>{2tzB@Cib@ILWTN^RZIx54OBMx><+O{m4N>R3&Wmo~X%0x)RzK9{qpkTl5^%$;)Mv_HSC)XNk_ zUSuG)h?cJ)Of?TDif0WDB;9Q=2bZnC-5IWp_ld!oEzs+@{c#5AAqJS;lDbXiS^G5t zRCZAoAwVcJW^m9Q$ zjCSi^WVFngVe!&RAPK?V^L^cut2iod>;6(m(h+n#pE za{8!|?A=U04~NT6mE1um{?26~!n~x~5fP?M(tfNFdvy5>qJG454y~8>b2DiKMmTk}45_Yp&;h(?6QG zNd$#F)Z6+><7&~86K@dVT!HhL^s+oMPp^WnDcWv2pFMi^tg2n>6Z56#Q;mphI#Cg) zr|$;FTZ^T=EPh=|E&NhM@wN_P7qT40hd`;F2)zYCUl82jRzr-=7C9``Ml&6 zGjZW&ZKTm9vyM(w81RBGW}@&032h%Kf1u^6B(>=GZ6i~ot&`}c!`F@hsGFNO7LiTA$CMc-n(t|svq-} z?4A0y=gEEPa$QeWE5M}NC-|{VwpT-LdAaxj1kW|IlH}ixhu6gomCf8y()%w)s+A%n z5$fuz>W?^vAf~???L#bq61`Vu^k~5o70C0_-s=(qLvww6BsJwI66ji zN#!V63i96}!^Ynudu4I27H|Tvokehn4pM{&1eiBC@hVM?)2Wu$_gHv9iqKFw8N)Or z!4yBX`tnvHYa^oqQCD?tI_XN-z>cle*Y*6R`RL9lxoZVxzu6%utxnl@A4KVu43+l0 zd2NG$nGK|UF-KU~$FkXTQmNVI-8eEwg?0tb^L5A_cI|{|i^5AgXy3@BscnMt8k4IsKPI3^Tn@Jmp>I?rDoQr zsi%u670#jy*Yf$_wCz9ZntoOPA()-sOXEWx%DEy;2?*bWy2kJ?CR`IF1K@jTy=qjK z^MY5MVO(#|4%E~v1#k98dV5fQNPdGKNDH2_?7j`{oUQ3@$NbuHb8%Cct zF#YW&@IyyjKpkQ+e^KP&^W*B3V>2FS2|$qX$PMCAo?t}$cH>GM#g3zLILjgt;-?xI zuR-!p=th=w$Pf;}0B(`N8{`k`NN4^1?}ywqc^35_;t{SS7OyNGDBnN-4Ag6=IhK+Z zssNAc55h10mg_H(>T;9YeG-=GTg0#*pQ%u<{HfX#T6~;@)==E>qiG#ZlVte}@zsNV zXq`zZV981HB1*1lhkx+N|34eCIkK-3wQ|5O2mW=U(GWUrpJ02#5Wwn%6;|_>q=Q=HF@5|JWZh{* z=}eHzXCyfiYF}Q|PipgnBH_7$bzxowS8}@d)<{Eb&{JAl=)B7@&c;6Xyr#+iBeSK$ zIc6Wy)W;5#>)A7q$FSFq^^ITdgD~O~qS-T04yS8t>@!fMd9`+N zwYb|Y$3(zJp)5r0&>UPYg@+R z>dkdChGx}5ZnZ4NUC3VbI5a28vU)*@i4!pO82mVR`I+wH%OG0Kw%mVKQjSeBHc zSddhBxC>-LDy*r3lvO<~C8=rE06H?tohM+Af(i7=h%;NPQUMN%H(1J_R9`!3A+{ z#arktr9@Y@f*=9V^#Y4&72QLBJFrB6N({F&Ki~cMsC1Jw5&!i}S>|WLh~k0|&x6mm zuY0t~;Fyl@y?BJ&?-L3usb$Jo>!EKl*)YCmFH$hnEs-khTzIE>;xO(&#VqcTBC8+} zf8z<$yAi#|3vuH47F^)oU8{BDlU;eyS&(eawM_|e*_okiRw#B{%uw273XVG63}n%{ zq}O=pwe{Age1j6-WU<}WLUooAC*)X!obVzMu<|-#sHQ~}Iklxp~; zsHsz*l5GnDOO*0qn7S6o@?je&b-KWFn?urTAHmEr)ZmhT=l-w|>%KZ(wE5`RfWq{$ zp!@Ez{;1Nkt=)M89YzAb%U_#2J`RN@7y%WB1n|aTz%fA6(;P?pE!HCqHUBshIv4#` z<~wssGUv1#aSa&SeanUOyi`D`Ur4P|ILjoZZ*($wpu20ANq|2a-_RQaTa{e)#qZ3Q zzvR$giSHSa1=O>vgDsYXDI>YOmOIN3joDwV8>xP83Gy&>BqUe_K+i>u33zkV;8PJS z9SYu2W6i(Jh>KV`*tdo}#}@ZV1K*o0WgGVjJ)n}YsqU@ z4#il#t}g^APPeekU8e0~qDAM>E6;@9l|noAGT(k4|D|}ZVA`3X>0%NNJqJ@V3r;`% zYj^UT$aJ@}azi79l1ck^>gxYZgb5X;uB*^5orjqU`s#V8)h6qPC1fss!O!&49kEb$&bcZiAz8qzkK7}{~~1bHPso1FDb!GzG< zLzl&D7_U2;5HwNel8^n_)pgDk^8w}WKaRQ87g`?>kV`%q(MKUj;0Y06N-W z6b(FlKStbLTuHXFF_yntL%EtuJiim_VPTe=pbIDAF%35=*Y6Fh@nEMBFPMra_UF>s zphL71m2ZNjJKwoM2Spkt_=AuVdIWJQy97avPzaXI?V#R*!hJ?$d20J*%kD|+%&ON`37~*!2ZRs)utyPFdZ1VZB7?hx@A*- zmRAhrwZU&|1nUgi;kwb9aOzpq4Iz<}>E&eY3#LK0-6PW5DC-qe2ZT-t&Ibd{gFr?7 zC^4`bhu`(I>(dn~CcR=wewcZBU6NR`}O)gs>f$={w zT~UY7+THd?m)SvlqmYF~4KXWH=NG!7EV(g{)5eI_eG5H#=wRm=!zYMtm< zX!hVww3=72@ZJS3^}@Mx=lQu9rIQpJ1*j7PcD}0S$RCC@=&xOvQ5)Kc@U%nv!_kfe zQ618LKS*D(%Agl;Y?fMoVu^Fl*eX^hj!2boQQW@4>-LhJo0S?;d#{qTa6yO9hc{l9 z1y<^UHh8)EL@9^;XjC-9)`y$xI@yeInr|OsBf#J8hJ_7HOj`(1 zP}@a|>n+J^pacWyo!>)Ap3f|OvK<&BOmH(4{(HzXw8bP-8u9nb>+?=}3dTE;!2{P{ zOSHVV=$bEA>xrEsbQR}nQ6Ep6@TCD!3T{%%3|ntzX}Cl4)yEmQ^sy?)#&|}5<`(;+ zws0SQVfcIhO>^!GC&L`3xv^LIM6fBt*3z*T;AQvqMQ1>laPHg4T);zEstRIgAD)}t zuFa=0C497*TNVx_iy)?zTj<0U%Ca!wPX4eV6#sZ#pfkL-uB1GN=G!z1QR}Z{%ZwvF z7u1_E8#=Iqtv{cmse9`veG<>$^F{+li@s$IOv}APVdRbS+M~h;+Z!S2|8eJ&)S~?! zVZY&7J#Z;!3n>8#9No%tGphlpr>I#J9&)=NA7UE{Tyn%V?WYc+LP3)96I_7_hjGrH z7g?eV_%@Y*6nqzW=zMt`sSg`(Az}ll56ZW&c^8v$P^)rodj8&q6J)3GM$-C3{7#+w zweW-V9v;u=`2y?G@qx<@7sT2J&g-H5fZOOUjj6l;WLoD)mpmQIgRAb0F#3aKB{kbX zY+tZLs#Q%L0kHbL>8kWPi`t|LRkDhGv0Vt85X-8q8ViOS4f74F|MMb)lI9q;PB~9C~r?b z)V#$`gDaNzbd#`f2TGwgbll?))y2b$wkrQi&uHcNCP5$MEI^TwKo1{Q11nE>0KHvj z#3gCS`CS*Gw_Ws2u>jDMLWD5w#z zk%>7GRkLks=K1+DV#fVLW67gaUNlCn9K2xs%P1unwLSEO*HwyscFClxg6EtgGlY2~0?A5D3+a?3`$+PBQD5qj zs-ggQZwvA^a1t`M3PzE=Hfv>}&ASe6kMMqKTd6Du3Zu9Wg7!<0hG9 zruSiIJUvDNfIJ3NU0atU_mV=DR(Q<&6R$9ah`Md2B-;W>;DIY1RO28RjpZK`BbOP- zaUuf2wp?dK(*{eVP>e!c+{L_Li)qHRK-!2xn;K5-PJSJKg%s7`Lfm=xqYp`!X|`em zw-e|s$H>xE6K>cn51$YH2qlQ=V#rteenH@2boJP5@FOaSL zSE`eNvBvextn;%$q9KEIcZc`g14NT*<^?nc|4Ah7NpWbl>%SS2=1AzjH7aRWV`U;pQwsT9q9N`u0%% zv}g-E2nbM1g(_MYxUqmAqD&C~^1TxQkqxUff_KQz&zP@wi}s zKnN~vbQw1h^lGGVSqkd+%=h`vew2P}??P#;?Y+BrrdW3K+{;d$!tutrR+#kNPw{?0 z-&quM(1{KI1sE>aQCvT9Y-8U@AwNlBRJZ<9Qzm)nO^jzo$k|)l%Vq8PyG2@3

a1 z{xDK_(T0`x#%;%h2wIaj8ddpTUnwI1-V&`3%5xv5mG!`*)(e9?~r|CzI z$WM&5zkvSNwIiiAf4fNGWK-z5dOb@l5Aauo?6=`2c>d7G{Dpw*3#u=~NHKzW-TTAhR50V7wAZZX5Oq8G6wDvee;n>Ze@rKAt|rd9Rg z=_Xp6A%g#2a^xfL{9`~g*xvRN)n;9c!vl}sloWvGYWyZg_eUny->yVPvxhD>b zp`0@7v+^Iy!X6lTem!K9U3__C2MS>tnB?A4~B`*EeE?3bECw3RShP^|HV!)Z1Z?4c~l(*w#h_svaG5Ct(lNI zyDD2Z7ak-PSJEMs~5olIlo>L3O$#S-;P3&SMpS;|sIl+d$lvaEr4Tkwx%W zT)T)Y8FenJ zMdmH({5yX2ZKlcVDs#*k; zOUN&FVf7(vhD$0aJ||#b#-4x=_$Yvtws2`2^d#`Z;Py_2gIJGQn!1B=W%HzXRked; z_^y8_$^YG)8TVuljAEyf2dA_>BQEdY`kpkKw&C6E?Jdu;EKNN>H6SA;ziI_i=_!2< zH7W?i7>oC)77I`#C3>}x_E?;*B!&p2a9x83CJ155cXx00d{`OuL9s>=2Q&n9LKCx7{f9u{VysA?u|_fTY03gEIi`1cR;H*J?Es>9ph<- znZe+*RA;F~>~XEf{mm~L9^L>nkC&qb&*^*AXKfOLy4;L@#K9CO5M9AUd%=SQMMLX+ z`xJQhKa9PV_gNrc)ItRq_OzJQ!oLgOtmA^EeE-|*7uqAK1!9jgwErgre*Lhn_PQt1 z+%Q-$*TA2e+xD&SJzxk{>%j`8O0VZJ&}O_T8LgXW^zGQ7nD3rO)jG@^d@-^c?VPy9 zJBlg`R|NRbmew2I{Pp$vJwzzg0~mfbk^c>$fse!sQ9?LDjL!nw5GnXJyOgpFO!Z$e zbh>crv1plh~hX?DMGPxx&*Ty*_u{>8P$+6P+0#Qd2IvMOMu-UJYpFD^g z3q7ub=54fxH>}+h2<(%I2jL+M_i9>X@eDe~hz}R4sFMOhyU#yv@V6;FM^tPp58&@E z8ZA=q8!>r!IBBq&Ok)<**?g1M5&HN8= zN!f2@X$fU9=a9!vf9g;F5lIhVa<*J8<&L}o{P$KFnG?$c~E9!}g0ozJ| zZ#@O#E6(u>@P(wOVQ=8CeEIgyr}Q+JzPh92m*C8=QM2Obh}Zq+xB_4y#>tA(Ac!!y z2=85%4M^UCJDomb*B%Cyf@5IbtstpWraxa&lMpnvMuH>5w9O>Lw1+by=Ha_hLidcG z@>Ntc{dzgxmU7X4xADNOCFtY>{`$7@iZ33P0s`u%msJje{Jg4$oWRuGX4SonWLExv z9R!>WAqWJ$eNubWLrrcR@;eYtZpaI<;YD)cW3EMH7N0k#_)eHrW(~Ll_Nbx!N6g8N zYaRv&UdtFWBKC1r`G4G5{NL1BIOj(K=N8fPkQUdpJK+H7<+Zp*zVsFfSrBO2lUWBL~QcU9ijF-nI%! zpk3bJqzobvluP(gqW_cv0YQ@p|Ca^>(w0``HoaY6Y2OIjTewdo__dR#v!dlO7v@#< zV{Ht0{C>k*XkPXn6&CI2Lr_wx@mz)yI`q@_nEpk2v$~@Gy}-IU9gxG}w zA*|1lU$&4^YPo{HhRhV?iUf5S6RE94t4Z?!Z)GpRDBFT=GN1;=8urq@R|rYTES(m& zNux*MgU^YS2&~9w8eMa_1R4W_veCaGuhn=%GX3=RWsaKOq zrO9o@R?k;;sxe)_7Wxs3sX#b)5}wb#t8PsYCvrN8C;U_2fCMx8W4LK+-RHBuQxy|4ebt%nBf6pgnd?|~w z@*f~A9%~iU8U|snmj6Qa@#XfDknxFm34v4%c6n zgG#gd7R;$M#A_=TWykB0)d6X+#%iismZ<>ON3#OXs>?CRlPRKyBl$+HygT?L@Q%}C zmzcB=eLPH1(d9W;*}1Wk5k8SlY8*_K`lI}m|CD~paaBfY(qfSaRg*4o2^$@|XEdM-h;KT?3g8r696Gv((D z`e^g7kpoJ->3E4~GWK(n0j|k30xw;-(4djX44$p%*}%?IL(ETw9E55`>Ts$jlR$R973ZU>HQ@DQ9rAYRq4-XT z0;wL^BLCXT$PD2bRsUI|=~I8~jSUC?c14;k6nGk>+r7l_%qBV%{B86`VB)zD&PJLuxUD;%P(;Yx2_g9d9E6(NMlu z9mcft@%5Q2``cO=jd&pM1KlvjRZ%hvskl!P?_b0LwHuw&XLD|EO%7?&V?Ol zqucXoM_xE_g;6@nG8VZ$5D-^(KlavA>_v&yBDF;4wgK~lMpes@#duIAB3Z?Sg8>p` zZUj$}mt>U5hTi`R(yTg%>jrPtLvX>AQ*Xtb?}wV3VH}rIati-0l%BIP zTL01{gA(x)ks|32G>C*|f{b><06W7tEibHpz;sF2n0~%cQmVPyfd4(#^cs!|Z-qgO z;G&Cdfx+o311Rp*1GH*w+-1{d!9o#x+s(l!nbxOS`+M6bX^v|8&e9YUW!B%4(~YpM@BjSJ%T$kesENSXGlBEjxIrAO=ChVE)w?r}Xy zHcX`JNucmp@1Uj?tuWbthJct~6ci}Sgm7PYn-^t^2~s7HEhWisN_8hfY>2oAKo6Kj z(Cev%o2pR}np4{w|H}5U|7s3K51xon$FuO0)2L}nU>A_9`!Q|9bbN6Xmcp_Mh4NS~ zQI6l-H)+!{{B$t%}qWrk@0SRRU zG>=U$IaVeD9DlSyIdu#kTw<*PXMfmvFrJfws*#8IY7e8{eI8Oii_EYmZLY5Eh~BbscS^QJgEDr|oNF=J@_-yz>Y4l6hMwmnDjH+s;Hhm4slXMGJA)wZ52YMhwN1=qG-TtXhbJBDvGx4A-24p#i z@;&{5S4-|9i&M+Vb&FN7eqdap9kvmXXn>kpd8r;y+EkbB zUot%NZTe@}5b-N(?p|Tz&3{cF>BojEQ=-)+ZMHQ*uNMmL*6BtM@!LjPYn00}9ntr> z-z$fyzfB>s-xu%ddPI`T3YL+AOn^+6f#uq*e-VSG>e`)m%=b08o#V~jJIu3Ye&w(7 z-6xZ%Ahk3V+^HSCylsndda(biPB+n2z_hr)z6eYjw6~VXlFM1Gk}5)=0)#9#jJ00b zB-=^>q-N`Bo=A7!B*P3OLoBLTyKz%1n69oq_&+=8`{FwR{j<|F*zy=J(5K>9XPuYM zHn3QaB$VYeIKtVZa6zO^ctLki8>w}o6JxD#;X5hcP>wFolGX9ft z_FIaqFh3$tpRW~4=qTDLW(h>IWMevk}@=OWYQZm1YGsQ&a@^Un*%G1cV}sgD&J z-i!atRMryZBOk;K|BCUpc_>&F=HH11*UloB<;Yijqedl#fa#%fu*5gND&Gk8 z>&m7~lvcfe5m0gfrhMpV7!{TkrHa#=7>&zml)fs47{&-&XcPUHUR8E zfDHK?ePQ#2RMD07AAt;ZzcjtxoB8oq^tW8V-gq$In<4Pm^R`kDH#%OHT4r5rLk8M` zE=u8m{SC|k7b(BkF5(MIy#3eW_VPnPAo-KWW!kFKWqVQ=rZ(F(w8i?9GsK$q>-4=z zXU{~QtauaB#HT#&?oj3H;+KXvHFH&_eorWbUN4gk8<#`~!Uf!c7`|ezNYp=ym){Ua z;>&C6siEdbs>qC>Sk4bUbq6=uyyXmPt)Uvm-gmgSw9^SnZ`0d3MAF4jZLO-_2;{)Z zb)oera$R*MU0l4({ADRxg`)RRU&8FB-x_nft8FE@UC%uC`y#BaOSNGdZmu#SpAeO? zt%&nEEmjlCB0D+oqDom=!5@XGuG-JjiKgjHZlVV?$XCIYbkF{Z(I)PX7)dL)Wo?N4 zaMj=P`E>x{xvSWDPUUbAtl@MO2UnJjzA0lor7|^?s`0iINRwwA09IiSUyzN8Wp7LT z_x|s^SL5YAIjhYR(yU5~RqTk{AGi3OOduM&n3fJ1DWf9??ulTwLdCK2A-&F5T4Wr| z=c;KgXm}5vQqL~C*4@(`vf4KLV9Y+KZdLipB+Ond-qK%uA*xN%eJA}dh;cIv?diUksa8 za~2utE9*n+a9T{wUbfPw(eehlGr@eOb>&=Zlnh|k>r~57?^j7Ku5IeBI%Y7Ub$WdR zqX_nxMWDLVctNm~wMbWF&a&MlydBrvNou+ug>CF2@M4cE9}0h9*g`HPu;Euy|00a? zU?5Vw&)G%jwjkYD;U!ZJ3uUjpIGyQ1q+Q-rBuxr5!$v62VHmrE0kBk6ayk=FG9?Cg zEa~UR(sH>e|A2{|5I3%1J%yL(g`X-Obr-KuPYQw7F{?~$G3N~$?M&<;d%HmXT~KIA zvEAVEJaMTi4!MdFpy2RLLBAv;54;TGnVW-2BIY^)b<~_HKJ@O6qr2TKBLc(=kDk)d zD!_@$SnVe34fORF>R-7Oj-xPOvOvutqselM15r?aTW*_qe_N&WDsepu4MIpmLK)KN zSHB<6T3?pv+iI|%S=tBn6@o31-M!b%Go<@@#xa>!A8fsRi^ZZww(u|*Z+%{{I}`jimf z`1RKPq-LO=j`c>om@D!HS`&{)r+otV$#Qcn;$9{SUWQ*KC4(fTD~r;m@g%5C?VRH!#;jrN;?OqC+TXwE{O zA%thFvoE2r!rdjZcXUoX6)e)f{~i+dyMl@X

c;;RgICG`*+Kd|@vzg1w_rOKdl? z=HyBoj zVAADwiP9Rz7ro8>f%+5a1N_y+vPuTBm3V4Uqj{>(G>6;Y^Sdt`IZYQf|e=VcV!Q9+@6a4D+*CYu|1C8q>|Ba8f(i z7>tc;91~tu+()>W>n&wT*FnM-80FcoHrf(Lwli%6ta!ly?~Ie}1$KShjp)t8RvmNc z?r2WMpMX7DJE71F2Kp+x%O1vbdwY|ZL+_g_bAjfL#qmCol4Y93HW`Uw*Yhai`cZzv zjrUMuvOdW;IB$fxK_;j(2mNp$S~p0W%1?9I3EXCg3YkLhgDclEfLIpEGSdNarQ=CP z7GN21E<)e}4z`ntcFCP`-NMLOkcwmrAMg`Kio7>A{9Mb=AlXOtdNMctmp zM2EF}`yv|6cykTSf7W~7dHu zqm1s#=i-@DK2`LQh^B?#V>oC#wCAF=%>Jl73eN12g^f#ap^^zp`7s$ah0`!m3RwzF z4Ntu6Yo2GGcQ@)oET`OAm4{OiK?*q`${W)hiWMhI2b|mm;ttBC|*uf z>N8vT*JMemZQ15xG3vw&<6HE=QMq~|gpfoXbp1BhKB5;PFJZ$(l~cbES56Z331j6; z5bqC?GtLx@N@{707GTzIUx08;QG!h>MPIk6U@OK~^O%q4-)SD$t^ITF+w+{_I@sDS zDZ5etdg)$;PwpNt0F%B1a0VbrCumjEq0UY^T^2=Tu&wg~ zmF3tEgxO<~rltDY&4GC3`7BH2FrOE%a6H*Tfu7{nTb8CHZe>^J&zRu0 zi~sChL~NKSHaX(?(DAo~RSn74HE$eKDK^!Z_DyYw4z6hWXF;-)IPh|~LN^LzvkBrZ zo5gw#FY!9MNFWPN<`x@m{@nKoHuK#p^@RL6n!AYjwyS$#w7k9o50!A}CI{!r#84_4 z$SE5ik9mMRPbjZu>^HjX@)pu^p7c~@IY`lNF+0o9ruC|#`Gg2TyBapz;5J2vEmTb! z4_|Ui5zPGf6ntuqeAtX35yD9zcuB*)ZA&1B*q`L>T{nGz#K9OOhRy=O;X-3W#~<&| z5h8`q4<~{Ig zuc+(52idT+4xoA+O^Hcw7cz5QC1tp{X++QF=DJk7R%(m zxby5uu0T6Gmc{q31z%Tg35kJUMBGxi#r^c>K`_EcE>gQY7*9CUgb=7by+q9p%&r>^ z0e0wwSCFeD!b@M=Vkg=m#TBHVE6C2#qP{8YM~tB{u5Z^+ zo^}$1g`+diz&=>>Ot+3n;*8QwlD36|QP|w8@6_G2XiP^m ziW;c`xNeK0y;xD4FH>uq+s`>2e&9jw3(#-)RiD{=XaYMTV*#F+i`*VFAixS_t#ujO z8IWB@k$rbfTLLe2AcGO)0B-j_Q(hoW} zD=Ur6k$(LVJy>)rDfM$i@dao6;wQH&vxB25W5mi#jYtb|4JtlbHZ100xrn4PgUIz-$_`#T2UY&iiJjwKHd6+ty*vZ~iZg5JbdVKPMs+s?I|dMs z#}78qZs2L$8u*QRQ{<%wU&k8f6`=$SB-)UJ z3LJB&+gLGdNfq{y=A`NHJl>E#&_YDnIR&}!uBt+cl6#0%B=8TgphHH6KhIx>!|>zm zQX=6EC*Q>{I}B~L)tc0M2b1miRyqG40GvQ$zZ;ZD<`v%2Pz{1}E7V#iDek2LNkx0V zzuqpU|9KRsNa(I0Z4Y|l`fLeRL~-t~U1^fsLT@x2awnO(>ao&;@T|z6(2Z`+Qb3=s zbL(_mHMg^^tX+x~L9_eBpxQG}!j}u(acx&_xA*!y|4PA#x35;?b%vX^H?O6&b)l=7 zx?~a9xq`HHQ9O?avE(2*YcF1(G|y<684mw=i#g})gClCH%5R0vouTl90ml*rhAoY5 zEYg8ng}8t&z`ap`{|*)q(Ai;@TaP$4R6D>e%g+zZW->chpI_rDy)2cqD^QP7=exjO z_jk>A73I!cyXl$CB(qB~r#`a&BQjAbzWbBQW1@ng>FqaV+MTY;QGT=P4~;4vybp^R zCAJprtL5+K2*U7(-azPtoJ-++D}i)>9MzfkAR@J7v{`0%#wPA zWN<8NMltcyN_Dx@bLm6r*wlm0HrY0uxDMZ8Y*>@@nHJUH8KkTp(Jv+iZF%YD?v$bm z1;tt9=aevL*z{5_daFYdYA8)Aj-Jt2JbQhrWQ`!|D!`>sJ_wM`kcG`xkI@rnxn>sN8Ha5? zFuX^&fcqv!&x?aycuz&13{8sPxfzf{SxuKk6C`sHAJ49t9!Wt=M0GSCxL z*EuY=JS?z9r(_ae`to-Kt2g)ntGD-Bd26lVZeCA9c-MV8IMOtVb+Y7i#+LU&QaklJ z=OXfXmMhOa47j4r;gmk$MrUCv5su($ORvu`%VVi{Be_;ePIj4TOt)`1-wj#Oof`N? zVjEIB82bu_OE0z_d~xz2!%gm})|}Q%@^Gt(K$bq0jd=e|nlln*{&n8}bJAJ<3}JSRGEi;{>ou~KUL zhCi=7*aJwsox|dpNsj$axBh?i`vsS?oe9X;>dsy-xEo*%X>bjU%K1!xy}JoHG5lk~ zJvsYrH}IQF&-zQa`!lJo-d66>y^rFZ#Asr?#rOT~H$=9vKZuY7!kMTKJT~j*CkQ&e{BmjUfi&Z73eDK|;%47& z9$ud%d=Gs$kZ#+LKDK%$ME#(ExGS7;1Zs-Or|dzdK1Pu9q|b$^aKigt)o7;HHv*#Y ziA_kS2C0loJib#kMIG?+?vLD`K1GBKA5$43 zoGT?;LFyTMNgX(ynS%W-t(jGA&5dkR8uxYqDU2~@5#oBeL+x{ z6)JEkmrnMK+L*gn@j;r6Bk1&;ArcXx~Ezv8X;cwto(_MwE`oMkCQMPP`Xw zt1<+|QZ3?j`Kz?_sEnlxavBZMo&P{10G7|f6OhnzQxnk~>n1v?JacHE^uE{)O1Tev zuEzb7iM%n#m{D|0KRMFe`n6UtZt2ld4ky;G2AQpq_n#Q2ZuOEhR!~HZH3UkSj390d zq0kTW+tV%rA(<&JyHP$E)pu+fB6lt5}1%Kis3?$NiNtIT$pX&%A4QJ1(Al3uS}m4 zu%qJ)1780Wfwzdd!pJEVY71=G!CWs%a?^8?h0885=EAmLiF#{)B+TV>G&j!AE2N3Q_j$Lajyy0mjuQji_{=(Nb=rL9mqTn`Vfp&%WOB@nLk+FWd#g@$y*QLG6 z;#2D%EXxGTd!wHgi%*d@?47mL6`Is!8nr`ZDMO7)R1ZLMtsPiIVu10GN2oYB^Sqqq zJ>uVN)^O~!#c1O(pCMijX33zi|A7>pHZINLE8FQmgI@&B*flQ@7S-P zZ4r*Zhzr0YH`3-#(mb`g5ro>}Fva(UeBOdO@bCHwr_6z`>G1qx&{l)ysm!_lkU z5^s_$ae-hlqwjHt!K>~^X=e*ng(f!AU`kcnc|HV3JwO%GLBJm{7h-B7AUizS1y$So zq(=Q$z%_XS*O*Xf?b$Km3$?GF3l@sYUj+by#YLIWV}U1UmyS0!PDPW|EEK43oDsTq zGnwh{f(J>8*m#mR~C%#Fsy@ z))=Q6c-GCTy#GzJp*-hbYFGFs0o*-YiwD`K8_oeK{zbAYVZZ=WGQ0YFSuu#&Vy|8! z+A;zbir-oUNWWpy2i!z@eswcn_@POg5V`^^InQtC{0Fn-1pPfExqk!y56xX&MrQr* zEm~h{hNy_)E#7=$Q~+vmT|0^dxAPV)ubI|l*wxcc27@&uK_bM?Sr8^Y=jf?&gniib z6<>p_T_)?gJ6kkn!?=e?Dz1MB~`2y}iAV|Ch> zus-7k1u<1q)G08l6|7r+`j^|l25x0ZFfqX1l*KIn7`~{W8rVs(xZ+w}l93zIT_zJW zd6VoGQB>gAtrdVkUYe4WK-bu15zaDfVXb_ZZ)u7*4nmy!HuOcye}tC?tLPQ+%2u(7 zGP>_F8OOIPjlTiX3w_vnk1c)(Bl7)N{0pZHV{TCQWzDqCgbr@)mErWno;X^E_KL3= zk&5ZNlhDA(W{pbAg{CVVw8}=eZ@(o{ds&oubyUyxE$Td2d|rJUskzQd@L8}bWeHbC z)t|_UQdVg4q4y$dQFZfiFYDi!zP8N^+voZ;L(TS5Z^Ta-+b|~^9o6BJFj7mfJBRsW zU`X;6zGw}$YC1-FN#?|hn{4U^T{B*}o;5ua^V&qQ__9qu^OAe}mgR-l6l5wWBDq1` z|5fMC<^<)u1v0*F>2~Zia=LE2A^w@~faZAdRZZi*sXQJ9v51W0c&8KfmBk|Ay-}!; zVmx+AHN163{HZX)rZ0mK^(KU~h0I_AC>gsIjFwxRYW`Q$p=-xRWsEsF28gXEO3l;$ zI-s2XgOB&dF^I7ieHY}#0gWYduCeDdQG~PLCij5!3sCly<59p&M!rj0P^tFeryQ30 zko65_L(^Pn}ju>r-g6>^a^-$|_82Yur1*|$ZmN5n|Kdj6K8RPg=SKCqFZEbzEmLIm4 z{j_EERo}L?$M9*s*30dpueO4~LUhSb{}t$HHl?q~l5PW#_aUSr<0>+EvwOPn>n0!+ zp*}7$6xbCO>VO5MS0UNrZdgr>Y}X4k@D%@haT?VG$_5sVWbi{f4g>Ef9PVi&kgym^ zskclhmHWeQ7$0c2_h8sWRIu13=u-*_vJEicz_zg+WPQWtT~pdflJC~jPo)P(;cOsN z>1sSCme}4K#FPEYkr`@AH119LQpd$AZsnl35?lI_>*I?O-ypcqUsxQojzIkW zYlkpZ(rFwY$A~;%>+9*F(A;7CYVj*$1&N#>=+^!FwI$S(LV_s{x17dbc${E$<=-xP z!@3!53M%pUa_v-?jfPItElp%f+|cW9c=Mhpbv{J}PtFok?vLg~-ogI2lN!1jy3srP zUM^HrKF47-rsENi+ zCw)B7itoSL_RBx43iE9-=CSN$vRaaoK*QMQ#(2ZwG3Qs=jYt-%bc!G% z!oQV8X$RwDv3I$>4-_h9fkjn#ggVn`Gwmv! zp<-pQl^8+Xa#H=Zb!^~l&$jFa*s|o?dbEz)D8S9Dj;iMu9&8lWDsP&|wpHo8A*73i zpW#Mnx+}@5w$rpQXvfexsa_y!tG-E@w0iT9IVG&*`!i2FH*cGj)tPn*w{^7UH3#WEq;q5(AQHctg&4LhezH{U}DZ&K&`G8b`ewNsL)g5vE<@3zx1U#s9F($B*H;{ zaV&UW;_SE&A8!#MZ4HU<_lbTpw9tlXOSrdU-8I^?HgIet30C|hMMHp2?M*th9c3rQ+jFrZQ0aXkLANB5NhFd< zB$7!Rh=;NFX!16z2xbFlx~__0T`{7Rs5)99o#E4B%FoGQ7hS+r?s5)q^-)Nx0o`AM_u@Ht((>cyp9 zyB}J3=-Y?eNL`5V>w{q{=~V3RgO*j-{72VBg$CS`NhFdO@VIf) zTRw^XLu_XkA~RKlQc^}2la9E^Fwgjw2H%9KSg_6achPJis7e@N(`kmVw%iq6us{)L zmiA;>ek0`x^F_;rVc8vg%kex?VA5kT@c4-th@~yFItYP;=>X}hvC#*39e^glUM6Ii zg84C$ddzR9SG*jfamAIjtbF9=q8ywG?lRf?9hQtH!NL2?zYT=6gzY{V&=WI%YqbcZ zv`NOLHA|aYWc@aHRg}e6lBi--HdgzE?_BMLMJN`@gTys=%yocKD9CH!d`N!frXzs{ zAc9f#@~zf(kosENEYVD%>mT$5^3Ir+>OB}?%k89kk%<=jj^Wn2VcvaWlfu`%7VfL~apg3#4X7BvOag7^8 z%8CnPYLf9&`S*I`>w6M$|2C{YYOUSI(lkI6Thb2ydORUH2~7`HKc5SKpp`jH)VL<% zu>kXtO2Pugo-N~2aT*!ialE;Z@|$-m-4sFc<~n}Y4mAuU%RaWD=8FvXO8Z3SfceEP zn1{`X`o8p(|2re|{5INsT{Cm)-cRAV-@|7o)!sz@k{u*~au9SK8ZvS{{WFHTw6YA^=eO+|H@cL8#2GU2*)LtJZ?Y`Y4{u&tp zX+T$h3-I!fHr`MP6%maK!gJDX4Z-NZYybdZ9wx=j79ecN36s~{UH;%R#sPP9cqc`3 zFaC4u?5ly$5HImN``StLA2JY@@owWVHY)^Vu9`yJhk=pMHu_$cS@hTiKCTJ(76(b9 zh*5s4EB1g6qKLX0Sn#N$!W)%Cbc0!hT?C&7?|6sD0+c0m9yK3D`pxAvED z@xF5yEF$F*LzBmimc3VmL@F!J-;d*1=oR(IB}L1ozfi%WLjXc_MokP+TUz*SN(x)H z*#+&d0ClFoz!bb0%bx(sO6%%GXie`xqWGdnLRS%;3w*Dt23MuVDz}rYUI{zUa2rOw z1fkL7r={+A)AYxVk!#q=T+E(M8`8PhONGRH!8AUVAwQEC1X|x6Q25)uc)v#v8M zWl1onL7-G={fWA%KQZah)ceo;A?@0X&HUQm>|BnKcL{F@zO$c=$=D!(4*Qnp);eKv z<~hr-FKvyD48dZ)>+5ny)0kQ}fO|b}JsjQ>24TbGusyh)ra%Ot9{IVtn+dR!0-U9q z)>J$jDiF}1*I>KKqdwO15{P%HoU#q@=` zq3k2}Q)R21%GIK-T^T6XWW7}Cc98TCv)rmX z&VAc7Ehy$hWG7Qm#yC{Tu${>6Ga~0(*DV%rHs}xaDJ0CVGg`QUV85O<&K`Qd=B@R=tJZT*{L_W#h5nbUa%g8i$?YTMqU6RuH4Vfk7!>EiPj3iFI z_{Zbvw|YvIY$VoB$MocVmcyDR&MC(Q7k8P4AmR5JXrI68b1REkgiBBo+4H)f1ZUXJR_knQTm~48bxjm`9-ATfiikxahTm zEY~)-|6#3MceannEp{-?N(A#qR?cJ(QYBq|*$Aet+NcY~cIlSKwK#NEcQ7s|cI{rB z`qdi8N<-Q)0IB?(c|k~glc9UWu6P~k61bFjlP;*MN2j@(;?OveB;FL8w@P?E)?$iX zUMe`FxOF;2@ONC}E6}{|aw!60iU#bjr$14H@^TL2@5x(uWDvD-FRD&b+$H@hM8M?V zhj6DFWbp<;F6?Z;BYI+mMt%VgPf2YZaz?u;y3dqzLqXMx;-{P~6o_N6NS=&841Xg@ z9RGj=BI9->UB?pO*+`4_TQTx`DoRj5S=&w?{JWYS$1s~`b5zYjn7eo0}*Ff5=)09VlQwnekKHxr(F0BqNG zK=aetEYg?$2Gf@$>IeF!9Pb@COrFmNW+t;eo=Tz@<(|CiEXv_RamXeG*mm9uwut$T zqSY`H0=txhZS67{78|IZq|l3+TdC)^-+NxDIh$c}*^y7M`+i1Mx@kvq0N0u{EGVvL z4~0yLbuI9P)a*E{CuR`_Uohip4;d#-adn&2X{0HIjX|phSc5%&AGq>lb^3Dmgy;ur z<60^uXR9r^)zR2)0f-u=7O|dTTv~Ghe;BVwH@dwnqI5CQx`S9B3#9{}NN<%Z>ef@4m z&YyQkcmak-g$R!j^}utC>M*_3lmOqHFBKbiyI)V0#JV!uxEn#PO&eex0?59dxu3_j`DCo-4s37dG3vUw9N z%BOqPUALpE5m7WCrMPrW>mWbfcVaR08z``I*cO(grI;bSTl_DTTTkTxbki2HKwd`U zXG2&K0z*q^0aVcH>Y3!u&4KC@4h>qU0ZkH|d+(Fw`y_FP=hbO$l=h3hASWPuFypjAv-3rjg! z0C93@7~P`F*fdl*s>-@+ts@Sdvm0e3jWo(pT6gIu0;hai{qZ+kV-yo_OL``0 zz8}`XoJjOQoQhudbsukK$BT>u06)(8#-L8hZ0fKdPr=FLt;$DCJPBBj+Rb@~&z9{4X4P2xC$yJrNHnN}MH0W2aIA_;ymvfMA z`NCbp9rmCLiRF(_)d~>X#xSJZl15F0Hrxe*9@=Fv!p;oX$REqzj=1=fVR(+x4)i{B zyEm0)czkFEHa#3i?VziY0=uZYuc3*itG1ZzcC*>-vO}q{qQ8p|HO8T_90NryY>PLy zyZOHY%yVLi)rCHcuvtp30IS0%j3~pXG*l+h6H&*v#h}+$tu#^@F&RYZeKQG-`%g z(-icb4wMfYClr<)ly#{4U+qE&0Mh8~#9PJ|V1>|(p_{VH`gkkok_&blu6yXQ|5fhE zT<*A=^7dVx)4tM@Rs8CiTPpz%tT`{;vqX*`L021%)AUpwsgeIofLhd9m7H9fec;=F z&!cH4)uePC>hThKCP%?Im$vkfQ#T2Pq!|JFvUCJtALbPvErR@S43HDJ>R*$PyTMGw z3LqaZ(`t**O@bbD*hvnQd-jzbi&JRlMYDPgFBxwQERn*S&Sjm12IOmdI;gC7WTtO~ zX`Kj)JwV{T(LtIyb4tQ{C#>{$KA~veI0h#~eOs60fht*c{~Ew=xhPB_4?z5(C}_Du zeYfCZ@T6YTo3-SWM9e=WGyMU(0iYzK9oXzFT)1+lw+<1(K zh;hBAOI1bfiw)A>vi0n6PPpYRo&cTJHhD&Qyml(7yw@@|y`C~C6lVM0U+~(#c zGemCUr)o~9r39`tA2up*b#ZT!_~9QtSr9IAN0e9~iWHuYUkvLeTwfgi%JIABqE(ZF zDP1~@YW2r?Ro|J8#j#kq{z!I(s-PfLtjzi;K8KK*GegJh6FP_9wlOMX%b>9Joqv>s z>tOXf+RH8h7^5`_ti4^Vr%Q*C;tyOr1Q4rnsW2hp)%|YNm+lb!+-0v}mt8ZOQOwbR&OA^#-Sa$XSCRim-%F?{nUcFX5h z=)Cx6Q|7hAkh!VD%0WyGlEwUB0Msg?aQ>E^af_~M+He0t{JyDJ)xg#4n(H|N-(VT&4oc7 zo3ds)zU=v=qcN^kOZ2)Qui+H#Y8Q|MP=h|LA{j&%uDz{q$cbR~M7S_gE=&q{_WN|> zwIU5-TIRy~piD#CA{1Db!lM&;*e_6}Y*U1;r4Nn2653@3bA)ljM%+&#)T>ww24+r-M-a*7{4>r{!s zPJnUK-P^ZEZw&f?Eol`^L<7H2K|}FQp*B7_y|_~~Lj=Ufg0P+pZV7F5xH!8^+SQ}i zV=6lRB@&~Jx{qT@=tC-BFGG3JWAcB58|4iZ?RARBJEt8 z-TqqydeDb33H%;iRrq?!aLc?^QBW9KY?fA+>Oe6l&NSFW1gK^dL}^C)i3h9TS}yDK zh3~Ktf$hesT<;CIcvHJ7=E%KiWP6oKXUtw@n-0?9U@DBISPZ)~biBuW?X#E9To+Yl z-0xCbW@{Xc&i2Z7ml0mhBgM_UwVImlqF_3paSoc=!O~Jh?(Py!qwWF2t-D)TqX#Me zcqULq?IITa17t)~OYDfON=yn5tgd&*)^UGBII^QIN0=!1eVpEh_kmV24ovX=hDw|1 z_Yr^kpsQ%yeNaI^4WO-37=5fe$kMTiU|9uz5{=#LNaC)&<&@W~2f8o`bAK0+BP0+Y z9=V|wYU4FcW5gd2QGJTzLQ*H;xJSq&4_{N z71zVVu>-inmk(DdL$diXtZco)-x;TpAiwP2Z-(tibxnlr4I&Y>2HXlTLIr-YYq|R; zq~7uzz*DoPinB5TjETG#b;$`7sAT8uHa4KjCRkI3!1|oL_XI?L|Y>Jbm?H5`Tj(ELv7dq2c^&l`2KcGpDa4q2PFR-?c4GyC? zI~x#l_071k2o;{F*QJ`XGSdVF_Gxm-n6J=~hK+F&!74o#*w`s|Z;3Y`VfW3}73GGm z&$&q&P@cnfKn?Xbmj<43LIt}o&{VD&BT0f2;plkP4l_4F= zDjdiD%rannI6Q`^IqP`wx7<8cyax8wyDYtm{XuQ{pJe`N7w#1|7WqvYqR3iaWtNs0 zO4Zspqtj<3xclNlNq&^;@sA6*&a>G1}k8)B3Lw)7PWg@u+eOrMzVm=QY|*1URrI1)_TO zal*9WWk9#)C$G548{}}QRNatzJ@-s zKh5NXauZ;J5}25p2+v{E%D$q41P(e>&Tkd$e4s41{Zif|5&lQ5m65wR?rzW}m4Zxu zT~xV+6T+*m#WHrVLKa4tK8Q4nq)TJ*w6H#SDW=Rs^~I{7SItu{Wn~i7% zIo#7-S^ih6Y%6?%E(`L(>byOR*ylcZy2;t0l?M;&8^Suq)-B@K1LZ0M3?Mrd|2KiI zQd3Iz!iG2m^AGJa)7l&zsXPJE4Q8NbS)1pGNyf%X^}U}$PoS;@AxnB%E}ZBl?o}-L z(sUt1@J8~z%x5c`xApVQOS8YXbR%Ri%&9|6avryxd+zIOz69oR$|atbAJa`<+JdX# zF3?TYuUK%E;4l6Gjso$1P1!ZVDZCxeBXxnMIK{EC2dSdCamw(BXRkB|BS3Zi);5-d zEN+3T+FSQ|v1Fg$R$(PXhZPbVVTVGKQtIxF9CAnMEj|_Z6`|PYD|Kop!@dU!_suH^ zpp0ZM&=3CRb(!HI9lywb2fKf%%;w(`g-8YiKepQ8hv3Z*v8<<5^*)Y5*`NR{RZjkQ zlCMNUYy~vogW;yK!VjPUZ9|x{>A^jdn%l4NO+Hyhy>?SM%W^bq#-Ad*s9RdRy;UI` zRZP8&(CuQN@Na8E1QBZ^`XNClMmx=tYK@>kIp%j3j+IKXqyIMciJs7%&|siK!6KPV zRp_UgJCgeq#gva0ANzj52Bzv>b~Lli3JR)+lt5AM^DOHs{D>aeT82?HCfDO=_`*pusYld&Mu(HG%Nhi$YGE7OVKBqfj*O z0YJ!PJPXu52lntmURFl)QwnzwykGNkAYB+gY<_hf?+0PLy2p>upc>!{*Tl(AcS0}N zSD@w0@U7mlq!-s?vAq;wugaq_YrY&@!la6LyfpKC%zf0i2JApPdp9fxIYJ0ft3c?Lk1iQGhM|hqYBgz&`maqvbHZ zNIN^GvAuOFx_6>B^9-$4Pvt}Hk;1C!XmIJhZfwE?Y(dGWXcVPGm>h3dre3-hC{Pv3 z(yH~_fqwEUbLM@)A`d6d=^X9!lN=1wwItK?^(TcTDA+HM?G=)<*9w=mvM1K%CRPsWRIFqTF#FT(0wI zL6XVc5Ue6i4KXQq^+*R_&$q=q)kKzqWPwGkzd3rN+_BFK8I2l)uTsD;kEirPZ8T6Q z!w&yy8z(>U-d*33@qR9coL%ATngB6IfIZbWfR2F9+=&uZ(*O?$`56go2%Xvz{1Zev zvBVHFbp!MBPDInHEl*I)QN6j{%c#e{(M@fn@u8fkg6wA00&$7!U2_c2gESc1I;kOG zBB+8ZCc0EB&f2i*FmnQ(3-8ML>jZgXZaBZUMiLWRCet)x7^ju;5_%!R)QNS(kr!#%_585#n^CS z%V(YV&nH6!VLGDT4`seiI~~2|mA&-(!*9-|E_JgjZiL!AKh@T8>NG}gGxj;CNYy7* z9C)CCL&%B#{eC#fP zGtn+ruz)QlERLZIxhO;0BMU_l2`4!szX*9!sR3TPg0CcP7*{gwQaHRc+d07y>O_@| zUS)IO@YE{&L3u!;zf1B70)UEI`8C2&c5Hf+Y zw%2135C$H92F!B0UE$HE^2vzkd|}r??PS`?Gu{jTcZAqinT7QDjjf$AK!y9#QM|FN0jz>r-Ius{pz60f%1w031?n zw%cvC+ik~7?vw;@lsEv9=a(SpfQB5lbns@$s3jQD@8Sp~h{nTxPHS>YSi?4f#LY7kbaAx784;s7)_g{ ztYhDloNK1N7l-$&BS4mVdA%;J(B$p;!c54&7b6Gv*eT<@BHhc0rZ+->0_bSu1N>@e zM-VrH19o}|&L!@@>$yNzU&NhUZmHFzuPF1~<-_friqWwc87*+fE8S{&G`p$8vvjYG zSHR$R_KT0>sZ{4dY^6&>W`%W$2hDYY+6{*7av=0+s4anbOQiWUOCYR#-ei9+ISnn< zXsXjk%uIa1w#iy;ZeJS?c-l`iz3VrH-Wy&4nBD61{D9DIblVRoZvTJP9MKSDhH7Ey zn#XT9EBqY~XQX#z!WF?BCL5%4{x>V!1}$d%$*B04cRacTq_4tr zxzl@1OU$zGRXnc_4&+~bl{ok1CfjYc+ikYnZMNHOw%a~z#B0z_ZsI3+eM7InkstqOkF>c;UfhmfV>^5^ly>Xo+qi`{_Cjp*U@k?asb5BD zMkZlZW#UFQRO8=;_C|wkTp(=;QCdl6D)ac0J=Tc6R3%1=8SZcE5|Vhl?n0{c< zEH&&68@rGMAwOxk;1wAPMItmCZF9p;lO#B% zo6KW>O=k7EOkP3|0$=Uy`8jWFal;Z*+O)a`099vscLIRPNxD(OpjSYu`LmKaq2!A! zP5Vy34X>@n)kNjR5t#==Ev|+s?q{@Q-bnvd7jIxmDnVP+%yS$bgZK67^p~<_4UI)1 zu0||@u;!8offEi2=KxyxX4RS|N~4*up-uz~&KPS_RFHxDE7pJkrSvZfZp9@$0Ma%K zo5C?R{pOZ(|3C;|O*z+PdEgMmS81mRM3Qh5<+K?b)?{x4jm>u^)=bjAEy9SEH-%v& zhgy&7`v5e4`_S~kkoi)Pzczvi`oJJYj55vV7sRt0Q zh3N3ku2@GGcS+!E6_w4k%MMt_iXFWPkIXJNi(eCmm~cn`i3buVLkAZUT|>7K`cBLL zYn`JbX09%T3?Tqo&}#HkthY$fa{eB`iJv-e+Y7OXuh9D=$Z2v|OzFiXFVq=`F};Yc z*=)Da%Y|noc1_k3uk=OWJG~Y)5{we9+9Es(fO{?{rF$~u9KNYdTdwSK zz3oVM4lxZ-;dnJu!m}}T**HB zInhDad)?^DQC?M%J&1eaf>w7l_E?!A+s4X00|~aq>Oj`s5!o)B=Ccp){3Fxq40Tt* zriBcE4l*2b!uXUEDa*lic%DTO%nuY65uJjU-DUL5bfeb-0htjX&Ek~RRpkOwqvlXn zXB}rOgz4AB2AqA;mDN{z%hG26F}6zk#XeS(WoAe$%i%Y>5(YB2ADTo_j*m?R9*f@9 zLy~n1h=d`lSo&m>=@^Qe#|m@gX4)U-UVaUWiF>H<`{k>?OY0!|5c4%kMq9%jmd`g$ z#mpa{J;DmnF{IBpHL-Oj^0wX^rh0TzG+n+IzyJUMtO4jFd)TwUwE$g?a_r{L(9oeX zBQbMlkZdR|%cdXpRi){wZN!Ffw?na-G}|9x2ZY-0Sc6QML7! zRyfgT!KW+0KgGQ^MzVij8>DO#U-bdcxv>;CmjkjdYjK2VVW*LnJG#nkBW)50HQy15 z!|aQU&#)}1h!HGD6ej#mw8A`UNCW6^M+octu@Kpr0hky;=@q4;^=|=3JP0@pSjA-5 z;=9UKc3%Wm?IL(ry)4x0$4D|E9NfuzZ+(Tk_VHl9tTO|K zVOt7Ly&oue_ZOUc$yubef32WdRacd7wS9jS6$Gr-SH_QvF27F6eB3VTSh&2(1bIY>b#Nmlsl0qPjO4@k+Jih-Ee}ZCjtz>Pi!BGRL{vL;5E0e# z==-zna7DlE9{apDTg;;NVqcZ!c%PD9Y_eLKG1b@cFi7*sJ|?r&ZT*QCI=wy*Rg^kv zt>w97fUXSA#&sqArKYAL9*t}g{Mk$YY4k}E2I59G+WCvC68N%RvJ3{8vJf^z6eQZD zdUe`?j6rsI@pe?j8()OKaj^gZ00D0e3&FXyHG>{blT%FB#Y@E9kH}*v$(6PKc4;(5 z7}~gfvGd?#OGLD_n=#f^4+WJOvlAye(*=$If#Cgpe)1#(7W56VK>d?&OiJ%iY0@^Ni3##=h){VSe3dXB|Sk zg%kHjfXoVvDK;fQ0HOj9(SZs87Vx$2^wv<2GLaU=5r%TzTUsgQQD!#6#cOnDLbQxL+IijQ4{%*I+4~f3duw3r>5ZkaGflM zT(OWKZ;6co5Cq-19Qb(vOEm`OWopo2!RF#Y86hL9Hs7S5x*9iLJ{zhi=#~QJY5Mak z=_-9Poc?;pChglBcfy|5H6;>-gQZ!i-5#Z;3|J3SvSM~#H@{|4nk+Tx(g-SORS5g} zv^`ord0?-*{aSb<2<=dV-Rl#t#3`D8W6d4i#=YzCLYRyQ&}6q5C*^M}+TKZm$6#Qc zIB=|qq|}wGi3#FC(Hd4NXfD~X^M@R^1c;w|2$knZSY zc0HsS^^(!qC7*FZ^W|`A)%iD-fTF<1=GnRYf;GFxQDUR6(k@Io)eHb{P zaV*SvGj2Ne5A~E;QKZh?DBYR2Q7@g1t_I9h%Yqd#^UE)>bZ`yxeIV`&H-!QbPH#zw zYwyN7erV|!{Q1dCC6`^JDOFg|&#a5CK$aIs8Vp(DH<$=TVv{XAD*l8@U}o&)3%|164& zaUib4FmKq$&-u$t130PZemTi-w8aSV^Z{}deW))7!$oFEH+^#HQN|f2mx@j{h0>Gt zvp2*F`a(`BI1HKCUT7e7v6uHAcy3fTd9N(HsMo1Z|1q6O-D?~kIw$L?=?S#{9bPA| ze9}8Z0)CT>k3~;wpG5SxjyS2v4qhXmV%J0u370T02q<-Q@=of@7ja6kh5AS-stYZ< zO0sKs1g}bA{##`wd^|;z~=37p62-a+CS1bS|A-&WlwQHvzzMG@0|etpfM zh&0$kplavB*`2XV@!^1TK}Ss;0*hEuUj;E~$xAu36wFJUa_AjNVV)r|;{OTTyP7A2 zBz*7;s=Jj=(1phc?dYm>{s0M$5Ks+qP}nwr$(C zZQFL2ZFSkM*Ymx_%yKqaCs~C5JttqnipD5RupvXr8jPvd*4zAZqf4QI45!8 z31EzIRpIKyQE1j;@sDQCIl2sq9<9bA0#SDX2|~w7_+uag4y5sr(g_cEY7DAJcKGNE zeqW^NToX6{Tui~?pNAM)H?oYnxGS^?L+wmNzROMaLEMI=8y!Y$5yQMBczkrjK@zbi zIGMtXx4{bOdPZsT3O_QDXo8nGe*QnHH7Xw#X0YwwolSa%(3mIX&mcR-rpFz?Mhq8( z5>!VByq@B;3ZpA*NzOCd+3o8Yb~wy`8K9KWQG2Y}-BIq1Q4&vlj#IDcMWk@f0mD;S z(h8c#NhknGs~DIqz?FY>CV#?+Im6-@`>v=5g~UPjMQm$1=_;Uqiu~#!PZ*#5Pz}J2 z$xqDF9aXpKNJv($4;d#@>LCPAe3v&B0Bl*SIuM!rqFs`!5hupGYfwxE6oJdnjYjw3 zV|solFsS6O6&5lj_}|OlSWWDCypyls<9E~Xw9e6{KK&x=Nlcxf4L~lHlOaN392riO z%YaA@ff+9Y^5q1M&;Kf?;I=LV0MefI=!%WwQ5;DYRU`F06X&>;qAu#nU7!el3{A!5 z{Ost3f6i>5E+9oI@lbey5|;y=U8vh&0+`;VD!&?0axXyd{668@9HI->avXCx;OHt^D-8LtXFa5R=+<|D_P8SY_#jN zJZC~oBW9O;NF=01vK8MBMEF2B)DX$ z&drm21xUJdYkey(Gp`R{9(9llVV`isQ{5793(Dw9*`R^Xn&t@$>G}I&+GTLX!x@j^ z?f?`#-6Is7EFH~~*4BIP4Db57axxs@2JyW)#{L)IzY?LS_?O$iL>#Pm;QsN~N4#}M zMDS@bzU{!neq`7BGlD(LG=;y+1fq3W-Jo3dl2>~ys%0%LFtfwit+<-aj~(`v+9%+d zGucT^{>C#WC{j)8(staq88^uR)Kl9y@0liKhc`*iyGwNbeq zv4wo*?fpjBc|B6R8^Tt5CVx+0i@O^v`d?wDIYen5J18oqX+}m4Jv0Oh(c?}%9!&KO zbxF$QJ%l@isKFf%(!p_3;v^s#P9r1?9L6J0B-_OirveZb7PP+~M-Jme>Mp0uCj*W` z45?Z5$c>wB`)hK~wgO_c)F84%1cHVI05r}Bo^^{jdp$ubF*qaTwgW%P@yxZgk%|RT zP$Qaq2tx4QqBhWA{}^xwaelJ370Hy8px7$1mRfe+mpH=C*=>)~RINQ306Es~FpRQx zabESTLD2=MG+91zbE>F32fq61kvmq|@m88%H{N(%cr3{2)z!^2^41ClPo4yh53ez@ zVTmFQM~)AjHW4s)sw1(e@o|KiKXf;oJT6_I);h8n%{bCyf_@u9a#PXEd`Y!_#8ty* z;IMO8FjNqsYE32TAR!_eIvraq9KgaYA_MWKa!7~^#~*+b4sJ8{1NK1?Nuw*RYRf}< z(=3K)GV2)5@}V(I(i_KES=YubT^i!6wxMmdMq4hNOK7X)N0SKrxUDC86Xety zgRIfYoYfTvavBa0B#877^@L6*T2#p(@#;hsupKdRl^`kALyXqHVJDbots)^=t;vaxHI z)m*oO_YxJ~fH%xVaW-hz{%Gd_0Kkxt{0Sc%`A0b`g;$h01;ufYiS$O# zSJl6A_=lm4U9E;F0t`j`XW$Bwqc0U_EWfj1^B@yp(fFSkh*c;6fOfwmy^H$VO(@v< z-@3p5cJW_}OPI{~%8s6%BR88|}!(`F`HH{ z#&j{H_k?faRX0@D*j;rA&Th$HehH3CPP?5-W_(Kg2oxccU|3fWFBB+^$vofb7M4mh zxF_9@#wiJhaK^R*%QX_99%@vGfqaHDz^tK9$Aor6&6vtIHtOky*DA7TE8J^d5&8fa zB_DGg73VmAOX|CBP}Y=X%sZRw4corj1~fDht23c$*4i%kZ46}Sm_kq*I1PZ#WU+q_ zsCazgb+f95i16pX9%2_a34cbJZAp%I+{lkMB_UsW!&9ZlZoECJ#UZkkvnVbE3V?f7 zc@=_@STgUEI45X;+jj zzPiXow?kZ^nVH5S%)B=o4w61eLP)#Vx)3G`4b1->+jCH})IxXH0-QQ0RKc%Lh58Ku z`*1#koI6)i6wTGYT1bv9q`RdH`u~C`GxQ3>?~NRc(A!ovS$AgT7I!PfT(NAxJl%xi z#*5+HU}TA&4IMv1U4u_>N_+P{>Y+XxktWmx$gnTPb z73t!vb_w6+_JbAs_qd9o|_+BoY?Q8h~&0avgFBv_s+UH{N3I3XEEdp?<=on;-X>Hwr zJ&U$s$Lxqm))nZhk!kPq=vjgfb-MX=85p`^qK-Ze%gb3Yd>x9SCl4<6QVVGQ_=Q** z5pa#SlE3yd54mIKR732K56^TP`ZcXNKirJj;9G`v<~~}`fW*I4i~Gxj8-Z=DD$&W{ zG{MgkajI{_)k5FSn|4Fr(YpYs*Vz1~(EDzw88lJpXpz=HgA4L5owmiYC(S^5r9#Q{ zi$%#x4ZHQGu&q!pATb|t`x(2jg*QT(dT%u+wh1pXGj0deZJ`O~tS`8Gx zPOFt>8%WVQsuch!_G5`#D&fU;IC+%*t7npO&L15ISx1A`way_BAsdka35*swv_xPc zi;;p0^K;R*B5g#v5l&(MI`2d#TmcP(!wLhyuz=fjB?(r)ztYZoe1S^BwgWDH+hbRQ zxcg0Si~5SYU%n6Fs*|*a3ERa$1`-l2LIYp$8eZl){GOE$+(_gQ?M6IR=EhnMxF!xt zj4qM)B;35d?&j7H5kQ(FM&kyUZg;C?V{CwP{ZU}NS-#-ib;yn7J82U4!7fx?xqVR{ zrBe~%aENKOQ;tC32f%b-$^Mgw31f#W0fc?x^g*YRN;nabi7Y_RgpL#&=@^pS|&ALi$u3ODWs+XTP3bEEj!x7E_MYDC=X9ErhA+SNCdxa%?UlgH2@_u%vGV1nr+y zMJjIEc1NtX3XHed83+*(JTNK<*+Q!WXL0%8Z^;<=*jzkRu57lSOFcgiRe~s zm&YQg_kvPP9e+Msm8H~BZQ1iVO!7sutni}aRDicuI{li%{+fX5QlRRmpOsBt;{C;; z6Q;1_&;|TB?!$E9zhwK?Jki_lwbdWr8;I-(a#j6X>)dT@Kp((g`ph}$TJ+px0xH;s z*~&-RGm|h)lL0Z`5u)8l(K1mAoe?o=IA{^;Y=e5K%5hlanUW4&h-WrSk+H%9Zuu?4 z&bJvcU(I6p_}uc9C)`4MMp6ZE>~H?X9j5_Tk${d}u;J7&Pue_i0pVSd?Fn``e0kAk z%mwSi7zzk(nD^k-KUQi_~#dm!DO30rA3ioY;l_ll{5DHgO=KqdVjd7D094ytKr!Q&IZT&;0OC8WbP^9 zcianXIBdyrXdBV5=FcslmhpGWl;WvK?o(i=v7@s`ywNvLLg5_~sLXHQ?`U=qd4QRe z|B^53^q83c1ApV)=xkiJ2;HMZRh|%~xDFSEw)-}3o+SvadgjaUw}k{B5o?ad92?M3 zWh9xkToVwmucyNvpnMKozmi6&3R|0pac6sZIuF;!n8^09RiBCOz&_h~8Qo!s>bSqu zl&!w1Uxo*h1C{~F`RPahl=0WOy2*{9m=B6rZaTx(f3ep;S|K5;+VGNjGizJ5h#T1q zIe4_7Knth5Ki@+Rlf~TN5PcmRn|)N!*%Cogrg3_GG!hA5cIYzdj~MdiYicgyT?qPi zq!pa%kzDr5^n&5Oi}LadC26lcbd=T6~!Ey!!0`HJ$$3cnjJZ{nqHK= zi^DDIW3_R*Y}m_6F5#gl|9YTvzFjVA<*=a?-MdE8BQ>Ge*ToJaK!optMae@`s>*cV?gY_lD{W?*d3_4uYd)z-eW_zLkgNwb5*l6! z{z~I~`Za1qfG%4W-Lp)9^*|;AusxrjD+zd$^s_+B$b_pob(HQIgbm4=K1+2$#OPCU z3i8RB_|oG*!Ca}C4p<9JVu@}DgQ0muOt*F%zWdXR1I*^m%{il19Of21`Mz?Cf^RK z+P@0nY)nc~{woCFwts6Mj{s1(?G3$o0a7ZtvY#uY7Z`eg9z*6OegegMGY%Am@Kc5pEYv5^;RCMIP}~k){gG_6fAPMiKg0Qt!x{cLSYGIRLB{ zSkzR+6V*1EJeAzoIPKtwW}DA-8NSn|)X{?o%_`=&YRqQ^v;_r_0jkzrA~3k66!FB9 zn$?cH#8z$}hj@aO=snzlrO2TSrtsg{i?IDjGw2Ly6%7BGpMTGI(`_ujxU=Y^uxOw@%;+{A`CPE9<}8;IV`|dFiY*+%amxlIk8i}&Z%_ugO=$o$d>%!Yqhv=oDTV=`8`JhQH% zjIKxj*dmM14dlQI{OY<%O|KnWtSJ{mzoMiuMth)bXiPW%isasNyNx4_I zJzb9B8HTA|4>NsBYPscEvWk%`+?!tB^5j3>^51loAZ+rL6JN2+sCdKbChAb&<4XTl z#6ZF2`+12kXsQNn@E=d0d7Kcb(_n0OGl0Zyaa)oH7-7(FN}1tt9|lju`6FGmBh&H2 zq3v-zB7IB70cz6T3a=!{J`T6?=b0UDZwbcyO(4Dp2qknT)+0WI$!+T(x#9}rx_}B5>WYd(=?Hl5|2c>D~!gAmn!yc6Pm4ivIuTK7wM;LNvR0Kb=ru1wyYo;0l zoIz~ms`Oo+Z)y#SJEHyu$T&-HAgFm$!MzCm-m9UwN1zkXGohq!;8=##bqQ=snq5q6 zkuYs=h(f;oV3+jPg zyki{wzf4a-c=rbhK=5GzGRCpTV0|4LcAHGC=NXDfd05|~v-;GKRqs~YWq8SKi0Z|Z z^~~bF9t2R8NrL6(K*FW4+vZ{=HbFR8%zgr!>#GhZ3_t1fE~<=O>21vZ z;UW_n;+BiPEN!JMgW5q6zRWC3uQK$nZS09ppPcmc9IPfAJEzuJ$F27=b6!{H`XX%3tx$v485*B`qz)4N8vBZ}VTx90Wa3}f0 zC$ZA6P>%?ix|8#2W6;_3_9Lf%0;B%{M4!EFzfiz!Jn@qMvK_o>p=$WXZWH2wMOZEkLy9NpaE$o zWOuM5nYDt7pI!D&;~d~z5z>FhDvZHjLZ6~`!)Ec)Y#Dwr%A&f4mzuoaC;IdA4BZFC3+rPVabjS2Y!$nysjSeqn zgT{yi)=zRsNfV`q^-rp{!R+AWPAlLn`K_oHBgvjj$0f7!j)d=i3nLe0gK{i--KxEW z!GR{xj%NAdukq5RTh{=RvQ5aeMj1`0q4ycBo*u|@fX&=^jz}VmEufZ@C_>3W{=L;~ z`9W?DVGrc6aljEiL(^Y3Z-9;hHZB}w0^R2$JI!kbj@GM;z08>^ah&5f>R@|D^&v5b zYE;-|h#*QX8*RS6O8b|CJ~J6=j&D=B6_l~%lgv^PS(RfxfT2D=@S!GI;|_%I!+*iq zvtYb;JUi|$>)`@%L_xzoHw0?)j(=N6cj?RnMA7wb09nUDML;Ow!q&5U9MV#3%L>2iFK|W{jD1q% zcV=U41Ybo%ELTg+=E*RUpObi!aRw22&r#qB^&}9lEXC`umrj}j>g|Sb$8wfBUPM6| zvfhPou~){l32N3P6ioG}f2>!v((*Ydev7OtamXXPZKu^e%epTj#@8_Jd7}{GV5qJg zb_Im4MrL2yCdLwdI7MV%aC46FQH-~<@|mfde~a*m=@R+miIO|DAZ(7z)~)oNl~(S{ zxUE{u$!&*y=7NY@?#bJj&b*6di9wiId$u+e1UHHn0swqHrOFNaY)3dMF1`-x}H7em0U!NMX(%!F0zvWPl{p)qS+8< z$V&)0X>Nwx=((k$wZg>@Q*hd<{zp1+=ZCFH2NtFW6BGPK$Vz}2K0~nY{1FhoJ**uQ zq!g{+JraNF9)vp~F*`kU3~&YH>)jW=9Qy$aYK81t8&Jczo=cmpe>5s7=KGNG z!}ohX?4VoTpv5RfohE(;ViZ#IM~noSfEi#1i%LS50uGyBmHR51giq#sYu5Gg8Z(Nf zZ^(m&r}Bj1Pr~ci>n{Nv!pJRNXe(ltMe02tn*`&+7dc4m`_qOk%_?t-}YdG65UYU({yp;czWUQUG_7kc7S zEqh?P6`rf=@1?HM&vYFm80X9AOuCq`y>{5UvHSuF?0OHFHujVkJaLy1upMjvD&Y^J zhD2mUn}6RAAs=sXRiFBq;!);NHi=blK9IMg>tM%8g2xS*;c%RfetkqE1jUxmnYYgN z>5#X!fBifNZ!XMO?A3k5V;LgOMzm5$k1B{{I>dvPJSH)KF~{5;jdqbv@uWpnZG z(qB|3ISsJrWxm&A|6Bt>R&n+Q1Tm2}Wnn??NPy{)9w<1RUp)G!HgM_~TnZd7nWzbjxIZ7v8DwaBy@tt4m4KN@JhoF9UuBntNgn(laEOv?; zJXvu*)ceSkM(pUnjD>g)zS*e)CwKqq8sk_gfK%UlNLB`t(v`{tG5=c^DI?*Qw?V;M zfNiY3b5{lu&1nX1Ss8HMZ+1Z()zFq9U@`(8ma#li1hSXBf~B~-Qjlkt zgQJgrV~sx_iA|t$yYvN(jFvmC61+ zocbF~-EHeS@(w(BH{50V_$vLa^$mByaC7_7_2*lcPq-I5yj#3?HoSNCrV0n+X4)sW z={C9LekX~0;aC20`tc(z?%9oZ*Y{S&`y9QS!hvx&^y?@1*ZlU%-7W4p|LjHl{X1~n zn;h@ywJ+0nPmXtI;K)Od`wHJ>rIQO|t37?8Hv)iC z??(JDI1%iLXW_jF&%#~ROgO(0O#gvp^(#9tOuGSnS7@_+%ahNuaeZ{opRG7zU>G?r z8H~OA%0ioLW=;G%s#i%I6G>KSS0ImRBc}ozJ8~dq(o-wl!vayp9$WqWF|9T$y!{1_;lOqs(tWy=cF`WKLKc)b{rg7(}js&dgNk;fVn|A7L0o>#;W$1mld!<`35tW zjta{-5(AU1{J=rTzOdcK^J?0$nn3)Ew9$gdweUktC+I2;g@?T^ICh!+BjHbEu~ z*MCYTqYRMUV&v>^*LGrud)o<3hu7Il2en4QaK%-5T^rK5SM&XT4pdcR4Txl%S>$N+ z5>@nN8GF?dxM?3idENqoKJ$`@24|He1z2`}l(;TyeT`_4A(NsOW%vX0?j*8K?32pH zyQx@jv;?UPT&JBVC^M{(CaeIAj?tsEhu9DWT_w;9wJ2`p!g7>p4E|m|3WlB9g`fZerwq6Yn^Ckq=QC|4J!Pc^awXU0c%HCs71$;TM7AXV9M3RcJ&jR??!YtE;uvmfFgzH2y3pyy=H1%HH2?B zT+fknEl=W9u$)Idv<&CKU_@SHbQZ<{702kvmQ1>z`1R~`u@0HY$k9j6Lp!seY4jzM zwbI0YC674+kh~StBGEb8?Br_bYa1@!HpxI!P=~{{Q}IA()R-h}IGNj4N_eU+aj;G` z>AH=oPw1Mb(k1=~6N~%YOEZl$sYk_&X5&#mG#77hd-F1e<8;%`U+d+J63%YQHvqKw z)8**onXh%nEU-VRg#HB{)U21<>yIZ_K$eN(AyxSi6Vh$TUEAByIMAsyd?tjS!rEc7 z=-#bRw9z3`vX@0(G{yCD0h10IopE`j{+GCVYQn#v(x)gi3+wdr>L!a)Q?Wi}Q#yGY z@mGU)c9wh|bPUa{vA`apFZm5w;&r8VYJARQfr*u3)gXd0X5mzgsc8;3(B!fID>(|p zN`17|t#0(|)??x{+&R7%CJB`v@4p@~Vhl5$mm)!ueNLuwO@83XkiL+#I&w6G)D0@b zbXlONB&tQb?NhqEvr#3lIdo^~;K!8t*|JL$e+2Jy7;*e)#|qF$n>eX#FpAwxtRhR( zO5X-8wzYFXIdjDRcUXkLOVuWJE%aMA!?SPA-m?WJ8+d-?yjyMBM6ckg%~FG`AP#)W zEP7gFH3}=HO~f(+%vw7syJ0kFu*0Kwt^=dPZVrRH+d-Udc{vu=(BNkn)`~LzvrAwk zynv5?X#nL{Ag`As;D?(Y zkBVFaV8TOz&!S$=RSV{t6Z+;^&J>Zi2m=x&$5p5yw!`-rI@=82Hp}jy zg;=jYTLL|i%PP&Ch*JUpF$7H725FX|6k^UtY?ca!3oW`3qL*Es)Ad&F|Rb(soRd=<<=o6w`6 z$eLUd5oaz|Yr&Q?gkkIO*p4~pA2;pI=zkWv>uT?-REE)ggropo&+L%v)4^-bt@wU< z;y=~aP@gWLY8vv35n_y&8-cETBN^uzf&vYdGiv*>{1wuNJBm7uFd#`$7N|8Aq4rM0 zq245@yX1|dU?FPsf8p4;trr9q)t_=p^6j@MsOkHB@GLmv=#|H7F)n^)D3HW%LTOjnI&#OGbPIyjF?kebo;$2Y=};Vfm`8lYgP-OmDY=w0QqjtrGQg%IUCJUyGFddZB2&Ts(FN z@03K7Tj-PdsoWu=Tpa^-;-oCbTJNP#<)*f@8+fVj^>|h6E+l&^u}49TYMi1}8~U@z z$`-*{>tjkMK!M#wq~T7{A**m+t=g)$KT{FkS7qN#t=OYw=L8nf(ktJmED8esH(akE8;#@19f# z?1p>YYXVuXmRwf`#AY%=GT&6R9%%*V#?0rj)KiDRjo`oLHJxjmsSE6)YF@5v%0_Jb z>N?Jb|J)$VFzxU35dP&SVOvR%OOcj?l`3q=YxI6cS$@c(9dNbca?Jo6RR=DBYPP(C z(lRhaORvERFB^h?!?6tc{;*dO!G>Y>nPfRmpjN&*fs+HTUfO_5(~Ym04PX!lfvc8FKe;X5>z=^CYMMFoicQVwD^I<4dHXUcU>6sK z4&WELPUx~wq0oIn*5j%9&IXt<7Gd3mZ)s92{#3b)+nsr73MuqBUP`;aHKouuoy`!v zu=S^zw3EIJ_u=F>__Ljz+Fis{_GSbf(y|HnQSQ|5s6Jz!I;DMQ8$C_j2=7|2rC3GQ z&2O{bso-&6JrYqTgaVLH*91;pFfB9!CuS~@8s(9zNR8`-im>AO0_}aGlkpMmMy?x) zWZ6DPbn+cf#OeY;AlqlIHVDYPD+L+14UeTZxs?f#t(EH~wWTT9QYvU)9@Ee0LG~`1 z_@gt#G2Ag7NB>DZaXI$*1x;@d6L`Yi`NK@!9{r2w_{$R_6IK3IhzTqrbRJkIDj;yP zS}@abwHQ>BwwSobCpUSv4g6S{F-D1FIgOJy?4Q%JT#XLHI(=DjfC6;tj!%C4FD&C0 zs8>J*TyS{@4J)0$xK*5J{fGWx$5*>#cVZd}FSX(kO-0!{J!-9w2sd;Hxcvb(>qbwo zz20vfDxtSA^az7>Z~y_gFXQHx-d+iWFtBMWgv5M;vB+F&X49l8c$rD213^r|RmV-o zs!fO%3a!(}D`^8gs5t6x+|+&i=IhbQ(P&(f2&~(+87*FGNMOs^2RS#rM}ph%8p17? z;>T>9jBFUk6P5+htfAXw`)=@e z@j`mm7}K8Z=)42Kd2)vjAgMYqzn)$DxGT!@wo%5k=ERn2Yf>T&(w2}=qfq3|0P=xV zr=YQojDPUYfT50i>)>%F9O2c;Shhw&23*G7_p?w}KMwnOFZJfULEdFIpELR+(N0^^ z^(Jm!m{v2>%Luz;Q0arEIybBHpymm=z~>#QUtyzpN-UD59p13dx9*B_f8Fu~+b~2a zNYfuY^7{+p(7zH8`{SGpbHIa6KNcgoY0kK4S@TZ0D1*SOqpsgSqkNV&W-5I>Ibn$+ zk;pBDejbJ}K}|v;!y?SwIq;)HNT7FhKLsuo%zd!tMzzsK?4au6xa>gx+Ed>aR4mAGum0cI=S_<%?cj1xck$R>5-OzP*( zZfb7vj_iYl8+#E(T%A=#&^V^)f#m*FFO8ahR>9k$wKD_J>-LW4k}PNSPhLL8H_Yza z-sq_NuaRdHCsCcuQz;tmgdgq8dl_(4+ayUs;(@+h&Y;UJy*Q)aLH60<3Nh`xRrT*o z2s{NpJE)R2&arI^62<&5V->nvPL5WCtqv$0F1^MU4?9<8PUC&t;4KyL32eO=HFpJ# z`5y`49X`8fPF9AEAwYPU)h}BNh}d$26AzDsqv1JfSQ*~DLyw%t8Tc?#t6OxKqkMrv`bwVH&$os$`4<=)4(lhql>% zq)}=F6RJ|r{_3GvQMJs|#HO1*weM3I5$L?KM5eGP;F%z!{jL9+1CNgQ-UCzCVk5r* zbtw-x?P2Hl74qG47nk??CHpchaq`QdpjfLxlE}Q}^dO#+q_k@T!yX)>DxpIKx*rVy zf!rP*o!H~yk}MhQauYR_UnteWj~A=hDSZ+{10LKol>F5IL^LC|2HWor&F@T6_xawh zMh;RsKbR#9H*vwqFr(SgtK7;zeSU^gXeI*B@A4fxAm7iYn;Xi0*b(2#z~e@Le9JdI zH~#_CHy6ZNM@QlIT+D~DCfqD%tkE*&Aguq(xkkL>N$9#NsL()gcOCwgvVGqdQN5Kg zeugLtq-*eGs4W6*mXp;Io+{P(3|B&_+xQ#82@*lYkwg6g2zH@dI8lm|s`(^f+bd_%LBkEyVs@wfyMAN3UclVT)Pa!gha1SRyECOiRc zLSL=BdeB9DC_2#325M@)kK*fPQ8tDaIl`UgGk|6T9Vet^kei5HBH%C3526PbX{#!7 zrm-R~T;IHG!ny7J{<7)}5zjHdYH$m<(^s%plgfUIFgbE~IevISz?XIetXVM>ZS&~G zmz4hL0B%DB`?{^+8nnVtMyf6l|0BV746N7N|9NR}c*N5s^PH)d<(T`Iyop)`TF=}r z7&5Lg5tg0xiPl#YL#&EpOOV3tS&+3%A7JE{ATa}U={F!ou;iELdi+o#4lgAK*?)4+ zU=pGew#}sBWoUl`{9s=B=Hc&TI6*_@;>vsPiBw)17lqCZPfOYO)vrSE@PlIA>VU+` zIbR|z`mR?gC$Tu)z5R ztb4KfKD#JPa}&ujDBgZ`zXMD9!&9deE`9x~GH{2QFj@VQ`Hzl#n!f1?Sp&z@4)}N8 z<}|l?X|d+pm6gbSU+Ul-nlzUgumc0E^2blm{yLLjRJ=im-H|x4T^|C9Kk%-sH@k=+ zmu7${8 z7>0@PK~Ml4llgA76tjT=H3bIKC&~5Ck?$kU)m|T0ru75j7WiB>MWvm6dR0poi#=?8 zF8n&u=?je}UnNuwY@p*t9Q z-0W^2n(`*W`;w5gf1sIzhNedMwiJH@K={8mIj^->24-OEI1fsTf|!fyVnNoNZ+b6^(20EKyNIxZ0`ak()7ug0vH?Tk9Ki8$ zi$|MCb)SZ5@Eoq5+%@fkVd~zp$7CS{?c+070N&xctbC|OYobcjNZc0nClE%v%q8;l z{)DP^LM~!x<&m)Aq(pt&J-I0Uy;gvt6f@2sK&7=`TMin|DXg$Z4pu{oUY{3>ie4x^ zyeCZv7aK;`0X?~UIv3*#AAkwa7^Js9%e6DJ&&QVUlh&LycCC*C7OaGlmVOQMkVVW6 z3pL605i+L6=j>6?DGiC#DAYq*0`sjK({MIFS{u>_0ydaM$V#QK~fFinR!l|yeD3}H40s_iO5Taww~ek;YA|wCr^#Y zGGq`|k*^iV%ITsYfv+BNHkxHe3v$0@7hE#tbz_Z!jz@xXX`~V-;q*wOx0o`NzAy4y zy-cBxy{IYmP%J;hYp`(P8KV?&ljhMM8_(3)jDh3*av|Kwdc{Js4CIGb?ZSAdvj~J& z6N}@b``G%h3UH*LWFZyiD;>Eu`Gf|#~bbt<1aZWG4e`)k- zuD78K3>>a@eM(_p2U6$V~Gfvag z8g@WcE_*}l%~^#86Cf?UEHOSSc#a>QqG_y?qYn_a`FW^lV$$GH`6GvlMdWk*vrjvh zOaT(gx_^d)VQl@C(rwH)l4I7i$Q6v*xl?MQ!*=pIyJE|tY#RtdwgP_DL==X98Z+W9 zQ-;ZCEM%}i%#s4gXDz#F3dbJ2FY5DcTJ&65%Oi2+?4t3h|D1M0BfzO%>v)F0+eQwI z14DaJ4g!DresBSxI&cO%FRuDHsJwgpOsWhK4^pZQJ%xuwgxPQBWy3Xkkx*9eGED~1-yQGqb zly-;JvChd6ash9iRJN7g9a*ZZM{!scWh`j)FEMj5ks4P&y3Lx5yY+7M2wV@rtHn^F zkQJ8yHbb@G@VDQxyVZ=KoIit`9A}I#t7^)3p2Al$D z5_WqyZ)LM7S1P}=(iwOpcOYOGLWrLOaMr>GUJWYXh7EEu73Vv|ya&~&WJ3hy$X8rD z>?wk+&iJK_%uJhQ00oaQ3RvQYYr%!-1V6L7EZ*CB8|eZEeKrhC)V*jD^1?s^;^5WD z#nTd6l^`oXaX;Ef{*D(K`gFY$6vCY~Xa7dd5AP1(B?-RDcz6xN#YHVY2l@^9nb{P|cVcEf- znZcBPpRQ%=SWKNoaM-!{!aO6`sE6Ni@s5 z$3apHu)Mcyg?IhtVuQ5Gr4PnfQGecsvy-w>*1oVylpJn$|4QCo7s99xRHYt%+z1cw zXG^^5c$=%(tcSPj`A*V!H@@Q*(3hmcY!jf?7pk8bfJ0TsrwUG3E{_bQ@r+uFA;$1< zk3H4=Vcohff}C5Ko7IO% ztHR9|AMzw(+3Q%@alG>b)*wNhF7FNzQeHsU$eg?Q7ut*(bn0yiXF;$Uh|_ zwEXy^vgAEALMz*JP}su6#dl&Llkz@)rmU}E`-Sp#bsgyp^WG7mxw4M|8%pM911Fih zsqb7zw&{;u(K?1r1~>3lo1BrolVvJ$1;g}es|jCX5hdB;9V5GaZK+UMeR+RKp9xc8 zw22?i)_NJf3V%@^xRn&G=H`Em0~vcRr+BZ0e=)x%#7xySkB~SRL7g$k;`<)e=OtRL zl2lo4Shlj-)!DhTH^NLg+S=b7!<%{81|fPrS}5ay5aCJm-P^Xb2Vc+UWe z@ez((eT=pVS=#(k_;~B&dK^R!6~)OU3!iTdS{gdlS1LwX;d2={D3(~hz34aGAcJeq z`EO%@_1OY=K+&*B48ulmYwn!lCa#j&Bt8aEA&R8KA;v|Td*R~Gl-pH}Hl3=+?K$(9 zc7YYk6NDSp&fcVmRvIRnUJi;W83P1{2bWgcUaZ}9#3aC#5(>XF6XcPVv9j^h7d6VO z8?H;P_Wr@`j6L{J8RrrJdmv_Wv`9#{%xdJgcaq@R7Q?Pm1YO=aTRM@{^AqK8l<$-#t2GJR&3BX}t_P8 zQ@?5R#)S2l{CH^U>cpdH{49u7=@*nAt1b9DXl?s=x}((s)+$OU=BOsEKce5jij8Gh zmhK}>T05v2S=bHj*y$LzdX7r!p4RO&Lp_L}eqsyX)?4S7Z+T?8Xv z8VuziMQD%!z{K%hOy)6#F(AxaH|R<-r2%=Nf_gjpRlhNeT%?+%;L&JC_CS%PmomQy z&)MN8rP!94ks4;57vFt>1R$I5cs^cU*@fa|z}^T$Y)3DVEkLg$HeH_bb8%6Z zR@Lw@t>MSW2i;3-iv?ns9Iq#1sFwUA)a>2J!?z$dyksXTz_^XY9;@Emvl}33z(w>F zJYagNd+iB$Z78iz^TD`3eL#`YNcInXcs-nSRa&^MpEp}00Z)4FU#Y*Jg5#IdCf7u$ zz#5%DEM2*|9np)b2&Sl&Zk!zG8-zQWc1%NYgB^cD5!06CvT1{Z=W5PFNbu9M|h4;%uL9tNFq?}`HL3ww$X|Wt>Irv*kuWua5Qc6*GI%nc6)&eTky(U zNC`i*MllS28bVY72u8k;@p}~ITC0PjmfgSHR$ARH7pHE9A1emiG_7VmDN^OOXid0&&wArC%4oHInru(h|K)Fxty&3a zmop?iOTN42$d62anMn=Jsk@qmjS`=8gj*9Z{Gti?(gswr$(CZQHhO+qTWq zwr#t6{!HcxrtYeeFLhg~?7h~9j92XZc0$*9RL&^b{-=zob3f;qVGS_;ADQWSNG&9@ z)OFCdhB-~U__Uu7R_22ruB%zRED5dI?7o`7hfqXPpmFdzT6nN!Sg=1^#*0|z$zCwI z@u63?e;6?}+7BmC@v?RG!-pHuMSkmC;{;Fny{Txa6a6nj5cG?6NZq+R3PL|_JY#FY zJ6!*|Ja-E{>Rj?46)FrRrtkR+o4h8yj09gr_ib=Tp2hhe9GigX(6I5LrCLHT7UU|C z*5~S8aubv@)+X~E>-CRDrOH#KXoli@yDu+KZkrgiZ^iP;1Pw7%TtOP586&=He#GvV zuQFAf*TrI(cfwDDB*I}y+;0IbkFY>ilg z^R8ZEnYjv6k!5@_h`c-159u8sp`Iz-I855m+4`F<2w)ek^PX=}V zV-rxK17OF*aq9_v*-a4JV$z1nb@52%Fh1P~j>xbqmh|4oSdAGHRpoiFY?Xh1HFlWFsm2aWm2_G`rohI83!OmLNd-5cJ5=*HiJ zPlJe4<%tXDD17@F#um||CPN3nd4^>W(44pypuKJA<;&|f|G6U+YQ}uU4QWHoriJZ; z%6A}T>)@!o=&^RR{5NNdY#pw+@lWR1DRBO{j4AEQ5}X%ScmnZ+RD^WVvRmr5ivy5P zAA(++e&n-5zRbVMnH#O`N3CwOI2sow@~Ox8-RsvJV@KS5TQEWJ{8;|}52+G@W~7GWB&*Wh^)Lz>=9^mR4+-cUZe97&QUv@n+2(6J~?C2$Mf>aI4R z_O{QHt73t?4Jt~-_H>lLp+n;615Kj%fVs<9Wz1 zf)icS;`*?5pTfvXC}mgaH)gUJk$j_YwEIdJxuax-P@PwaA~_uf9uU_^h;||`FrU!k z@>3r20~0k{o>);2Tov_<#c_I&xzk-ufk|vJ&48XC)0!Nb1QG*6tf?hA0=!LRv6AW` z3XQZp&5>{Hjs6LUV~a2=rk?|@#(^J6m}WxDZ%^?!z-zV54=2-{30Ze9KM#bJ3AV)JtOPNx`mTa$b+25zF40PW&~4 z+0XbV9zZ@8m)|O^FH-FIz@JDDFho{>@ahW5I0mwU8s)^M`Xm)Vy1HcK3fJs=@Z7D3 zt)TH2J!u748b&sfrN|GKqxkiiL%_LU6SS)AdtK`|U#J-Gd`R*JjBmya=5w%`^?uKv z>D7~zU4C*6naDw26JUz8vk}Wlomx;%bYxP@8=r|P{iMDyB#s&59Ad5Ommn05&d8`t zJ!8;CASc3Qeqh$6AflHZ)(oyx_4e2aced_$B)g-M4*A%bg; z#m%q-4mS@mDMd)d2{{U-Y0Pl4%b?3sLpqY{OAwe3bj*3Rl!+mt z!i_yEqI8Y-n$uR8l2CEa0?&q*EvUQideALGFOv?*?#_%(ZJ5L=?LD8#<;Zme&IH$y zy)iu}ehGchxbaon!-wBC)PKp4x*-W`Mrf`jS~)3hJ_ZrA_Vs(xbc#26tm4W!V%VGf zuR0c@BC=P%t34vh_z03&cGaL9^ZT!I1|WbIFSvb&uHt2 zZFK}?ESgU4Aw8 z`$E5(!@+RR?N^rCKf4gay})oU_g1#{F0Ws4uVZ*G_<=OxvDl~!pdWy}e%I|fMFd#%rk;nK1rRxkIc6JV zSl2dv{mTsf@tC78sMilaK?{|_OW@M~TjT=1}Y${%gk0>f*BI zG1H%}csNt=)jK|oy(3_#kpH=9gV*vzk<8U1gUdl7HC72mQ1=|jtF|So8i-N~xHvCO zuOL;!;K^3Y;BLd4|LhKcA0cox>myl`lR(`v7g^xWnHt)ROl(>>VvZYmE@J0yCMXAt zPUp`wtxC@6EoVE+2n!BV?;ykL?5W<$s%roqdC>$-ik)*vbml{=B{q7faYW~ z{D9?wYk{?3b3IkPPZlM~1{;fXNK4J>v#!3d<45Q7YqLmp;*zp*ClvZlqJ~abK|~md zm;ovkZKqVmeNIKC9({M8XMc|=0;FFsQ|^6{*9FAdadNY-Qmw&8#*(yPy3gxE3a8e) zaIk@lc5EEl<;vVmioZj@GkMcnnKEu+W=%fJ8atFm zkbq_k|Kr9~Jl|Wo%Z0wM8LQ0x5tkqOO06HIC~Agl9mrtTr<=f(Ma%@lEGs-kXw-ZO z^ve25>6|y|H){tfF?r$A)(`pbafY0RW zO5x({Nn0QYtZn~(BQ(E=fao>oRC_sttfkQX%M) z)^a9vx;BC9a?5Utg~A`oB%l^p)lPD}ZeK4x70i_2rT2oenotc_GHb50yx7lW-SG{( zY~2u!h1;%2q8B$ehv!Qfj{>mh|EB4FmWKp&`0$ubh*Mz5&)JU&WC+`*Twr(2jgKT1 z09v5)Q|}>4fwP1~Q=ZlaVp2k+)H?Sv-9ZpcR0_ z5a1B8OB^G`{JU7J{5*YN`D~Ds&ppiD+5*hR8H2bE%=o=n*1Eu@EF*k*p2fWYZL zpR!BSKYL!+ir$P(iXtki(uG9s%&)f-KW&gOKGq2eBgUc2ao1K1ofFW9kav3>QJdZ3 z>W!+jvSej`YAV2VHK*3$biWVSmM77!(IQbj+3$V7 z|Go`6w7#w}oLcfS@vGe~Uv+r4GcfEL=@>#)<2FzZ^rNeBCAgTXWJ9g(cN6q0TMw>- z1d3(m{}ZBIJEJw^_#Fq))F(YTU5g#jw>N$$k|vZ39GWh|RfnhQ9n}83@bZ?|7XB+m zNY!|yIbT9^HY(f{eKSMz0pqb0py>5b)Nry0Z}l75i%8|~Dpjer*84zfTKbJ;;#JSU z!GxzMgGHVxVD+05^r5{4fOXUhWNMpe*3U44)sp#@lA zv(C<{;KZ!QAvh22%fUFhOMHE!QUqWJ&!gNW?iLWn3YFB1fFz1lpXsd7ava3Jr7IB! z4=jKTgswl25h-=QS~fmz&MP~H#gfziXx+gzObJ%m88M?Qz0P6)|1zz*bf%pX3!$ofDeJ++|jK8Pi~9z~KP%+G2=k5)d=DeG;M7t0H2s`?-_wDNp=%yefALr*`Uqq4-K~fl)N&`wX@Gv zsq4?%279qew`DbGznWc<>Jil)KOC9#1Evq}kzA=$7?^1aZ7Z6Qnd>B!w6ISgxyI80 zaZY-V#@HR__nla5q=nRw}tfm0Kx^3Rbe!RLD%`4Iu-Tk@_y8f3ao z;)+t)Q-G2-TV6*94r8cyRu$JVpl-anHgL584vhn?cSPOGlc=rvKuaoAvS2Nkx;T=8=v>#VL z3_1|eTso4OCk9BSNI~hUxA`D=+>f$Ovh8YPNSLJyd%3AllxMALR>>Y^vJ1_eKazZ3yPbQ8&(9!gHPpjMdB228N#=K$^=h6n+ki(<&KHbs9rX;uUJ;eFoK{Xm@ zrUWW@ig{5|-u^a)b90aLTINXc3ktPQ+I8BD$DOupJC}uwdJJOTJ?eC`saQNSK+RNQ z?ab#o@@>p`aJ4>&K6m1NU0cRKADaJRf~=4paVp^FJV2Te>QXoim<(?ZWk(YM{D5#| zTVzeC2F%>(>rf1Rel=mn8Gh0>YC1s7>ds zPS|~oHuMATg^-4Yaf>yTD_{nmfLeKsv8>6;e)V(JuW5)0`@iNl z?%U+g(=VJ6iSdOmFk0gQHBBgxl zrq6MMkA$!h&#kd3!quixTXzRb!AKs|BlT!9wNY(O|# zCd@n2_KPAF23%!0(TRHjL9>9@Q-#f|)y!}cZZYoYYxF`D)*LXWauJ7tLp^;nPDuZ3 zV{o%g&Kt+byBfMjcFF)FqB&9Gzs6_PM2`c#4XD;1vn9)J>Phvk%4DNmpj`F2&0K?> zV|{3Gc43TaYv@tq@`4yQknKOaaiv_JE_GJ}yrme1yKz*W)x*m_QFQ|tOl&r{waEZg zJ!OW8tE%G`l!1}k3-<=Z66qCT(ep;mzN)aQ=p*VFJ1!b#kyt01weH1%qif9Xos-P3 zzJlzMWXYX9(TjTj=_QUn!wZ{p7f6f-*YbB^!Lv@c$U;xT^}T{v+|T5RSA!*Q6uK-e zJ}vI{H|Lwh8W6kRtCl22vrN(2Nw##o0$zv1MUdic!j4nr1;p=^ye<7&KjTQ#$BwnK ztEJ8DLmfxlky_xBTVDT2-Jc5e6k{Ht_LJK1@HOy2QRSVRsuUy)$#bJJLq13zP?4hq zZZ}!ldcWvF-WFM}fDI_HE0-H?b3=fuW?ZAnS~j4SE)IPc*a(>(ysC4*%#=WEV)&gv5|r4OS&JJSXKUks$RU{b|6=MLq5jVCgdWG{Wd*&Btq`XtH)L~< zSQZJPrFk`Sn}N>Q#ZQ~Vf$Kph!IZ?GpS2dg)#DE2PL>><@%GG%D?Il@^o-b{1)5)u z_5S_R*W5=@5@)^ znqxYRey!OW-q=&64&D2?McivRdca8pXFdIGGp9@6I=?@zXo=3UYEVL~@Wb^NXtBJaI} zAK+ltf2Vh>q0z;^5QeIu1c0LQYw+c6#xL?*o@7_3vWh4_Z<-QP8CQC~{F#Z((Pp>e zf!-%QZ&~>UrifKFeXk7?=>*#X5XW7QhKm+3jQKt#@Hhi1Xtehdj`0*tRzcQ0Lbl+c z*tE8gc5CI`8JJSFE8DS}*n0#f?m#M@kX~-Nx#=y${Uk5%$G5Op!z%GDFcErioG@gK za4V$k#Y-YYljMnVX6}Rq(RsIPy3)yQh3z*_jq{$hcawIOdQwIhHtK|O{xBT^dpS0v9IU%8$;L?2F_s?rEOF%?u<&qN#Vcm3M0X^pNYW5(qnzB5e{&>q=0;#_V$wP3%WZ2$NOVVYaA_zw(OnC&xc;< zs)Mk>^Z4R_-vEzoDhP!lnZgVbhIY7q5Gf6FX7$B0GmbyiYvpTG2K=)!& zIeT$zr{pL4CHCcy;<+Lr0;X`K!GNXV=Efe>6DPK1G< z3i6%}FnqFijTY7`kTB1#p%t0J_`OKZje8eIt#^{{bulw^ zU^H_Vwg_WCLoS&@cdHICtn8gXx%>r^`2+XlC@mTGe;P(V^j_8>NvxO0aG!eZ-CHg6 zB+4RXXAq-r9Bvh4+e^)a_y&q)vp6t*>!4P{0fFrW&EN+!-+@Oe>}q~m&;yUG$pL0; zwXZ7g|H9GIZj@Y*^i;2A=e&U6Y{FEd0I~b@;XGALTp=p9))R%gmMS}zJTOw$3n3-& zbXi^#3|+)ocFU_KwBXH2$cJc~0LZ&*4O*M`XAe**)n^McwCk)z>KAiLcm~jGk2`g$ zz=jFf_3J5xuTfJAj2ul4Eh_AXLCpo$FhPcrH}9R#q_4liIKuJ-lIYLRI0T4Sd03!SV}e zhZav`n%5DPcprXmEhui!OGNAZn}U+MObLohqN2N-734Zyk{qQ-mBfV?d1pQevBWhe zPY#r4nNBM+vpkDVUj*x}XlN~jp-k-U5{C7K)bwbc4BulK(-fj~A4`FSHMbp&u)Ehb zoP(}ELJN-Cu;t?JDC^K1PM&Vn%n?8A4^bPISNi~aS+JH18e|w<|1rWB3qT~^KCH%8 zX8()J7+R*_sh-R*jM>i!3Gx$KcJ{}s;h;KBCunS0FLC!|bT#T3T>#xi^q7=pI)H1fUTd`Ju3@D6m%mTlr#V zYDf#qYe4#u#7^>>+O@iE2hKA-VL^vDihD_@5*|pG6h*_gdjQ;E9w(%|G7shI>mpRg zI_ixmOQwT=PQWn_@eIujU(0BXU6rg2qP><2`=vHGKqkSaqsfk38NY(y;4*)OAh8|0t?DHH!tZh(1I*Tu+A1dETs{vZE>y3 zQ!5@C(Xn`a>ZgJ+s$w$Wq6uPiJDP=`A3xNA@{LT?|LE7q)cw7XY(ERg>M{&rpMzfg z2yqP5xP>t!Jwe^OPI(brCE#xqUkFnJN=n2DwiPWAP?k9FE!vbo>HMe-)w3WxDQCt_ zosOMC6!z5m1x*Z^+KCk&CD>FAiQ`>}J}pu>CXlTICrASmyVPc8sKEUVVh%Q~sgHi2 zXKYKa{3??|%FHfFOJ+&L5V$Y&lk~J;t92HrYtH6o&TX;UV#pRU@U`|NoZzM37Oz%` zGWV{zA@k?#XIpYsaLSSDBtW^`LGQJ?{T%K>V;vbjR$uYl>s?Upl4X#HX#!DHS4&nbCy8!ijQQ}$rK!Jj93c`afN4Hvy zMi8ZZCvfQ78k&9?Rl)yEa38G+%l!s&jc>#+M9&RqcV;{|Nim1wzG7la1Wbpkh_2cm z-rRTq>C~!%;5IeLJZ$ww<_ca`FD<)iWgv_fDjLIG2QZ#(bc={?vbc)91FXt5CYZ{) z-SXrRPM;y99{xQ)mFD?{g*Ecl@0{GADC46F=);Ks|aAjP}GZ9H^`f&_%KgbLLV) z)qYkpm!x0bPnY2QHq4cgq91fwzb8a55NO^DiQqh`x#7s&wn8sPfPG2->O?4aNdZIW zA86}8Zb-!m{HHR}8@D|M72tSn`I)5TByKYJY1CUci0M~`7`G|RLfL$w4?;qP`q1Dv zmMiaz0}{1W-7+O=3_H9gFer5D1JABb;>cU>e-XU(*27${2O3X0QyzeF`6~(j4D`$* zhu`4EIL4>{2N0lmp*5Y6$|LzBsXqmj{HZnQt$*X!z%i;HDYQvPo!lMR6}i?N_h1^$ zic1Rila^4GE|=_k?u7!O`&I#IBWr<%>-4R~_B<;(7K4>7501j^=1`J=3=GN3HCdxn zF$)pNXp=O-YHkT?_LeybBrkq7eB(keRkfa@DQ%W7R(?eF?T)JVoVhjwHPVZX8$esj zmUq3`7{H`LfNDl;62GrS6)k`wl}$%kk$Wp?t2re5fKzvOlJK6>q>0Bs9>?5Ar&CjSi7(*G4b1kEIW1 z&#JmfKUVtvfU-lGlhAAyNZ%3)*(4pZnjYhrc*41*C+L9Bu&gc`75HH#!Kl!a7}$+< zy>STh@(Moy?2W+yHQm1u-4cn5rfzxWSsn=%c`oHkIAX@E* zbg~j!ACWiR=hp(}`vdHnBOHMH9teoINV0Jq=mHKMDJGQR#h%HeMDFjwBql%3M|jp{ zPW7DOKHO@Td;(^z&Fyb@@0|zg_s_d;AYOu`x&jkSdY`X|2ELa|v3Ni>;n2SP`X5YL za3}f>1@)NOV1mt}DR4|?8~kZji>#-prBwC^;0ad?dP_ej22QqI2upZ%;K97^WK0d8+6z zGz{}}>`kE3x<3HKzP@v5VFFnrB7Wc#t%a$yYE8#6q!WS1rA0*I%=wgI z&n<;DbgF{>qP^45xtyBT$LcTTu=0u3WiGYLK6X~PGfU%kOnqa{Z&}VwZZBqtE0H>UA9w=U4*9G zz{*Po1^4JR3qt^K7i(0v5k58e*Bxh}G=xh;8fqHkXdmthBEm*uOsz4cM!R5w(d~R0 zyVV%@+gfaWZw8PR(EGC%(}y5NO7E6}l!Co3M%`O;#wpC|qtr_9`%znh(duBGf-*de zsJLXnSzz~x1d>=6?KkK(31;P=;8;FZ1RDW(+sqb_Js9dy8QmIV`qtJ@cC@=4tmJjC~|Q=MHmv z%oUsv6+kR*d`qvn_Z~4Cp|6hsO;uSlydk@1g@eACq19#V@$64Xu+Qf-38D0#{4M1X zWcNIAxZy@-@_1}HEL4Wf?mjivp)`$aqOt;i;ZZH`u=KItUh27nG9pVp9WIJpoE)wrj>!6r$-e+4TuNz8Sj*f3?-|)vFmteZ z7Q_*ElfXv~N|TbzP#Hdnfkv627yV!l7kpk!DCSxZeLUPguN5 z@wJ+FPaG2Ez;yK#RvwZ9;Vg?Ek7YzxuWb;}%Vh$X$!z>I#d$GLY5AWW!-yg8iI~@~ z(H~hr5|rS#=<{|>3}aC;GV2w`U3CcH6wdfOfgr}c(8Raut1!+CD-7TC`S~c7?(9HR& z75&OYxJ{aE^ZAbS5CT22BTtBof9&8q0t4eA;Oc9c(gbqZ5YrE#s#m24)V8$1L2j9)L;#_7-KM^!CJAl|d z2Ph3xgxS73IeA|-ZF5Y0ZIAug(TJ{NO_)lS4E1Km=Hb-3Q!)QpsMPM#(_8jBm*3aJ z7g$}s$e=f5xEgp99t_FNBDOE&x_4>L}}J4et({m0(&Y!ttM4j&`Kp1irBn4X@KjCu}p zlj;iNJU`dzABx_RFF1qg7JtZm-uOTea3d&yBEb1^|3wa4`+F<gO ziyy44S$>s~bF>Zz{C;%p^6{Tqr^_aH4R4zu&&{*O>_KkaO7MIl>Y2+Q0<(r`Y;`u8 zr8N}(0F}dn%6h8jOIg{l3V4oI@1_e+I&3^5uN3kvSSC2T2l*u}T#qiIYcOPe@4bkr zyWgwq*qEY=!d1bmY}P&zcZza$-c<}`5s+!x?54GCU0n8@yu{aGEC^)t@yh;q=BQbN zM;yEiTxVUxe2F%1u;RVgf_$My9dh_ZH5TyK87~@3nVI%^_0MsI--%>r!gooj_e-br z0Bf@T2c7xS)1bFH5inosv^r?c5${Up^LPW5C&p_X)Boj5eBsj`IoQ zz1m};-DmHur{-v{aFf4KfgYEu6`XdbyxFd`p9TvZ#eei%|BVC`sI*ZCu}5JO`(M1*;hiZ+Zu#DXgNNT zr=TAUMliO_(^GK!R)CDcZ8(`^%LNzo zOZbMh*~xc8JOJT1OWehNNs=+4K>Wu;=v7mOD}jOOw>`(T?Y#n>N8|gC^{*)SN1R=J z_Tp51-pa&3K}jI{?0i@3mA=Kw6GwxsA0g4)es9}YsEajPSi1=o`nV1xXK?nuOtV8S zmisTP_4NeM>{qJRFPO8~aAry%7GQ0Zey)V(IfgC|F9#EYIxGW-TMl1ZtxMX}43&|bs(DZupZljAfG5$vYHbK-qd@ga?|?Np8;~`KeDFi zp@})ek?%%2mDVT7VZ@c)=w^sCylwdR#3OBHd~sAV7^QXBX%;fVBWty^x^`1Q6Hmxz zKp0rGJYR49dtF3BIlzDVl@~gu(}?c1XwW=6iys)LmtaLKa`#Vk!?`&3`iU)0yWju; zoA-v)KzV!%8`EmkpZ!;Njk!oZFr+^m)BmuNI54qE@f7oyO6Xm<$=r(+E+h`W={rXq z%u<=Zyz&Gs0g)`N+|v(*z_g}Q^|BP$!anr+@Ks3zjJt40!@(NP76<{^XAB!PX)K*U z+2{ef@%bUqJia$!^)gUqK}VCucu<22Xni>3#>Z0XHZ z^?Hc=LN$cjUk9GJR$&5E=9-j3^bumVwml~$^&V0);$t(u3gi5FV!VlN?9_ z9iZX=0Mw+W*qj`V@GqL}B<*m?S_#-HM;pl)v4kYYarO#M^K`0E88j1>Ra-p9pwU)Ssk)CTR>%l3Bu9QPGkEx_s>;~Yr} z;cj&KCWA9c1vw zZf7Zr`Z7aNWE-dtDr7IK4YAVUsoB#Y=arly6hdXVDz6kG|M1WFXz?xJk2tOrptjG7 z4QM-?u9QH7CES7NVfCQn^+!u(HTV(aMNV&a{X_IOF;UH`?yMc7&x=b@At6iKic;Gw zZpXkppEjVM1}M1Tbp1{4%6Eic2j$X&FD#qSSkH7oF>`IQUZT7S-P03dS3Kl(dtYr% zIMy(E`=~A$w!s^}Uq(0f1%8?Q7e7Qxo8SB6HNrg6<6Kq;XqbT_z+_poWM6-&EBf=E zQ`shSn()j&L4=mWV_!6V$MBmDYV{^PHKoRcmlSIauHvdNu-Og;!#3ZR`Z#k(i3~Jm zz3HibzCetH&!ljG8PS`2aauJjt1o`h?uF_D;ZwQo{fp8c7kUMr;T zJh}Q)C*g1$cIt9HxNDCytsC0a3!k}55@b%QrTQ-324Vs2+h4GW0sxUz^d9F!OM7iI zk~tzAVI;3eOXy-zO&}f`;}k4_!TJ526{l>G?7wkXs|0nBy4|99(<}Hg3~s^4W|6#)jWBA?mmhR+ zC}$lWa9UEOqVD2CrCONus*CiAxKoYEyqop-Az1Hu5qe)2uuVL^!^3^2h0T_#Z?5H1P&UX$`BdbLyPbR z)?G1B4&J@ZIK>FUJV7V*awq2|Pe9 zz|QD;5IpP%2Jezbh6^%q09NUm$Ms?yjiE~quwx;X;IT?v3Q3^5+39-VQnM|6{O60y zys$pP%epTD15%H^s)Ml{P_`RTJ!fYKBVL;~Sd_-#$r2kRlmdtHJ{Y;9%0w9lxLzQW zM)Z%}{cD?mwBxPmTSe_(ufDWQ4!@s|e^m9xe>ta1*x%^c8qPo| z*7P$(4}z#~l{AD*&}Wo^35F*AcT8$9{91z-(K2aX?mQr<^OPff0$WM;qbOmiRp9L- zr>qnAea`v2s|9gpLVCy`?y~!DZD*lr*!yS3sT;CUa3yW#sx}d5i9ivZnBTxZ;2>o2 z_Tx`Vu|RbfysEYPdzODJpUgJl*0H=rBA|I;dw#7CJ}DsZUJNBcqR11#*?3~K^^ikQ0C2Gq1X9)H{tOey^mk$RBPOOQ)`wFjW>!W}@tYl~yP=+3qL z+RyiKOcr2fqh@y1b*0BUuvFb2nQe2w5I8K9#HBun^+-6>5@p6ml%8u`TGO~Gq&Ioo ziiq(DN`EM?(3MwK=TBSQO1mfOf2JOLuA#>_gG7gH@iv6IEZTZ9F`NHp$*y|v=O}Cv zGbV~|Uy*fjxFWli_bpyq`10K!T#{g`sk#>Prg=6;(Dk-)`T&bjQOQ?|3+)&a3lAy2 zKM(H;Z%+I5VAvU|ooYA>#x8T$CrRS-gjV<}>y@CS7R}BsITflQQZws`Fyj)SC2ChB zOB6QU7yUH1k31LA`0H?a$BkQN$}V*LGtjGBzkr2aMS=4B%W>S$;99V5Hp>4j zeEI%?A>Kx&2!`BUSIZt|>{*~=&e&1nTnKa3kyPuaepcFQwGxqT^Q1}j0y;>NxIcX$ zx+nF;!ssZVfXzbXm=hw3T*A=hvwV-&VZVoOYrbetYvj3Tov<$HNwNJ(>^>p3Dysr@NC*ZhjV znpkNy^PLotk)dz)r9V}u#Ah_BV;G5mZ@6~Z&943-henrOk8Zwy2zp&d8u9O~k@O<+ z(`3~?{ImxBZnnSv6Td0#-%_H#srX}i3nalse%;0Kx264(`LkvIsZV%!QG(mBcz0

d5sej+8MjKSTHZz|R&#z4q|qT?ESuxe&Ob*-`VFPN7TCu0CCS?IC)wCxxd$v_G0 z!*6lC_3kblSmrD@F4^#>8#x`n?I+8|>55u+@%LnF4FsLdvXqW1FD}w2#0Vp+wTdp~ zQzZSSgX{m}e{Wv{i*Qp}Am!ISKr@6aW9)oS66j;I!HK36W($0Vwm6h$B z0o9pMyORsY(B4+>uq;t*{0iv5#X$QapzQ~Ls@m7{O^>?8xGZ6R5|0-@##I9=SHBZ3 z#|w}zebH`Hi>Iti~Hy)cxb(sYGNmA!GO{WNYKP*OcxZ#_Oo^_np zY{ImpWMyHmEXb0fDXg0sTN)R!?b#pSn$lSuQ znaM-nZ$~|W2L(A6NPY-n?3+p~F(j_3F#xcJLG`BC>hL6YI?pa+U1@B1@LeL(ep{t! z$l_G&MHK$U)!stVvlrPJfNBiV$5vgxhh)unYS~bD$L=bUZ05F*fq%5M7`Zdd8ua_+ zz$3!b{8`GIXY>lm*s~PO8)c&;DW-ZuX$wiQ*eaLtCE=$vlJ?m!eW{%J=?0#kp;a0L^=0GmqwgT$%x`ZSaJuzh*La=&m%hoI1N4tCS3vsr z%jytSGp67PBl0s!nAHnn&eSBl1NVuRxX0r0^Y?1ONrkqopOn)y2JJ&t#1u5s(nd@u ziRPk-a5DF+a+>@k@6-3vbHK}1tNuu!;#ucT9S~~ zkyz=GniphzE)#oN2E$msX=GX8+P6A+Jz^x9C4K1@98=Wax}loo;Y1-&fJkr*wLky& zMwt*!Dg}W5T}*H}fBv(f^^^a%|KCF(5XP_$p4Nc>T*vhPuMtJ*^ih-17QnK2t#fcu zO{7|3PDP+UJuXRynvzUHLp2m=-9qJQB04bxY3H<5002~mJvpq+pIjkdAZ%ihbSJT; z_917!ZCbd20qtRVAl;=958gMet(6PMh@;A_QszV}#kHiFj@IjUHcXuMJaD=I0`+9W z&2T}GVOI)P>8gjw{-B#Nn!)6Me9|F9Vz}q^{DsEf{}T-d^7ywu2UGBQLtQF{t%0 zE{7~jAs;o@A(4b0Cg8K&3rlFYe^kEzEG9PP-|`4y*t5gPj}!!%r26Birphw&*PbR% zZ4*Spo|H|r>wp8r@lIQ6r4mmLEOh)VdHknY&0D6*nA{KT$-}GpZA6+!pK8Zkq^MWD z^K~uf05YwOdpzWm^2RW!2SS)t%lcY*m{`v*X~|$s_`k;?EM~5UNhmMr38-F*(_`h# zpsa`JND!8kZodf-+1E%QK{S&nZ0)lfPEP;;000B7h;Raw2P;83;ZadG@f4&2ppA^b z;(y(;Py=30+Tr7F*Lg6zvMm^+gL_FE-@Z_*tpUh9gFhm$7B7c*qOaEDTc}8%;}lfC zcMASEtZJja-n&j4xl2$aAPRZE4?BhhW2immgSEuj0-M8X+%D_a71i-jX&t{e>&viqYd!)d*nB<+7z_{iSu<()}jbt z7mDm_r}KIG6Tklr*AU1pW@qw%Y97}WvM|X|000000000002(NVQNPy=iFWg;d`uDp zbMtxn6Tklr*AU1pW@qw%YGy%MBMg-Q00000000000006d8~t#|m&qUam?Q@C37x!B zLP>%9fL;la1XD7`?8>R&b((WF=|u5nkLC`ltmpSyP1s|1NQrqQU!e>@MoF@+7sm0j3%g)pg$<}|~epDqURPpzJnC|;7y5<%V z!6ea!Ni%PB{d#>g*g?5Dl5TahMcyni4T$7W|?(c$>5fCMS zN=UG#*ChqVJ`-?=Bj<&;*?2v0b~?a-;x_!9?_}P4=73`Btj`7J&4HojkFIn`KQV~) zx6F>pr9YIM90=YqwAXxY76*_&4G`XJODa!9yb~j+GfR=3kY}&>`dpJUo>hSD`!moz zmq=~%8NFdhhIRtqD0ln;D%@T2qf#9Avlg`SkrCzJRLkul7~Wpfvh4+;`CZBtdu#DJ zW-ijU<*?nyg5*T>9^lLL zG~_<BXjI>t%N8d*O=)%8z~B0p+4Hk_=2Hs%~}6+IFrF;VtHQ-8k)qd@h~hhtl*S zIX<4atxkFj9!-$X<=~(;b_ZzO5<_@}LXUepW#kzpsm4%CErA}$D2}{ZytU!#whXXe zd_JY8I6_v+-hVP?QX2C3jFY~$%cj`%kwZrGXSEME2(BByOm>?WP8_R;#sMsKtStD$ ze+S0|swt8_b_Rr&EAfv{x{*VY7m4j_^FqlP3;Ygwq51p``E|lE{=kG_ur%9d#{CGR z2%;}nJP3Z;mJPx$+Tq|JVv>$)$`YW+naVwrtboI-<gTbm}i&GHjYowfQKWCxmTb!!8sb~4_Fa&Op zgG89LwVB=7Q;bM_pRg(T-_6x)1BT$5?v$FH{Mu@~sxupE5>U^z|6)MFnZxY+!Wr7P zc(`w*!Hm+`VPy1qhxBwy@%P})fv##tAA!>I>qcdc?kIUpxf=51)6ptR)dvu6x8l&F!VKFKR~6F|{TstCl!T9@<>0%7%a4&NBZ z2M+WbS}b+IKYTcm>gWm}si#>m@vn*u=zQ5NmPwBP8Jyxz7{nBQz(-S9q#BGeleHH> aN@+zNA0C@-%KzDEV{TRe000cXfB*nUruGp4 literal 0 HcmV?d00001 diff --git a/OSX/XScreenSaverGLView.h b/OSX/XScreenSaverGLView.h new file mode 100644 index 00000000..365cfba4 --- /dev/null +++ b/OSX/XScreenSaverGLView.h @@ -0,0 +1,39 @@ +/* xscreensaver, Copyright (c) 2006-2012 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. +*/ + +/* This is a subclass of Apple's ScreenSaverView that knows how to run + xscreensaver programs without X11 via the dark magic of the "jwxyz" + library. In xscreensaver terminology, this is the replacement for + the "screenhack.c" module. + */ + +#import "XScreenSaverView.h" + +#ifdef USE_IPHONE +# import +# import +# import +# import +# define NSOpenGLContext EAGLContext +#else +# import +#endif + +@interface XScreenSaverGLView : XScreenSaverView +{ + NSOpenGLContext *ogl_ctx; // OpenGL rendering context + +# ifdef USE_IPHONE + GLuint gl_framebuffer, gl_renderbuffer, gl_depthbuffer; +# endif /* USE_IPHONE */ +} + +@end diff --git a/OSX/XScreenSaverGLView.m b/OSX/XScreenSaverGLView.m new file mode 100644 index 00000000..3d3aeeab --- /dev/null +++ b/OSX/XScreenSaverGLView.m @@ -0,0 +1,483 @@ +/* xscreensaver, Copyright (c) 2006-2012 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. +*/ + +/* This is a subclass of Apple's ScreenSaverView that knows how to run + xscreensaver programs without X11 via the dark magic of the "jwxyz" + library. In xscreensaver terminology, this is the replacement for + the "screenhack.c" module. + */ + +#import "XScreenSaverGLView.h" +#import "XScreenSaverConfigSheet.h" +#import "screenhackI.h" +#import "xlockmoreI.h" + +#ifdef USE_IPHONE +# include "jwzgles.h" +#else +# import +#endif + +/* used by the OpenGL screen savers + */ +extern GLXContext *init_GL (ModeInfo *); +extern void glXSwapBuffers (Display *, Window); +extern void glXMakeCurrent (Display *, Window, GLXContext); +extern void clear_gl_error (void); +extern void check_gl_error (const char *type); + + +@implementation XScreenSaverGLView + +- (void)stopAnimation +{ + [super stopAnimation]; + + // Without this, the GL frame stays on screen when switching tabs + // in System Preferences. + // +# ifndef USE_IPHONE + [NSOpenGLContext clearCurrentContext]; +# endif // !USE_IPHONE + + clear_gl_error(); // This hack is defunct, don't let this linger. +} + + +// #### maybe this could/should just be on 'lockFocus' instead? +- (void) prepareContext +{ + if (ogl_ctx) { +#ifdef USE_IPHONE + [EAGLContext setCurrentContext:ogl_ctx]; +#else // !USE_IPHONE + [ogl_ctx makeCurrentContext]; +// check_gl_error ("makeCurrentContext"); + [ogl_ctx update]; +#endif // !USE_IPHONE + } +} + + +- (void) resizeContext +{ +# ifndef USE_IPHONE + if (ogl_ctx) + [ogl_ctx setView:self]; +# endif // !USE_IPHONE +} + + +- (NSOpenGLContext *) oglContext +{ + return ogl_ctx; +} + + +#ifdef USE_IPHONE +/* With GL programs, drawing at full resolution isn't a problem. + */ +- (CGFloat) hackedContentScaleFactor +{ + return [self contentScaleFactor]; +} +#endif // USE_IPHONE + + +- (void) setOglContext: (NSOpenGLContext *) ctx +{ + ogl_ctx = ctx; + +# ifdef USE_IPHONE + [EAGLContext setCurrentContext: ogl_ctx]; + + double s = [self hackedContentScaleFactor]; + int w = s * [self bounds].size.width; + int h = s * [self bounds].size.height; + + if (gl_framebuffer) glDeleteFramebuffersOES (1, &gl_framebuffer); + if (gl_renderbuffer) glDeleteRenderbuffersOES (1, &gl_renderbuffer); + if (gl_depthbuffer) glDeleteRenderbuffersOES (1, &gl_depthbuffer); + + glGenFramebuffersOES (1, &gl_framebuffer); + glBindFramebufferOES (GL_FRAMEBUFFER_OES, gl_framebuffer); + + glGenRenderbuffersOES (1, &gl_renderbuffer); + glBindRenderbufferOES (GL_RENDERBUFFER_OES, gl_renderbuffer); + +// redundant? +// glRenderbufferStorageOES (GL_RENDERBUFFER_OES, GL_RGBA8_OES, w, h); + [ogl_ctx renderbufferStorage:GL_RENDERBUFFER_OES + fromDrawable:(CAEAGLLayer*)self.layer]; + + glFramebufferRenderbufferOES (GL_FRAMEBUFFER_OES, GL_COLOR_ATTACHMENT0_OES, + GL_RENDERBUFFER_OES, gl_renderbuffer); + + glGenRenderbuffersOES (1, &gl_depthbuffer); + // renderbufferStorage: must be called before this. + glBindRenderbufferOES (GL_RENDERBUFFER_OES, gl_depthbuffer); + glRenderbufferStorageOES (GL_RENDERBUFFER_OES, GL_DEPTH_COMPONENT16_OES, + w, h); + glFramebufferRenderbufferOES (GL_FRAMEBUFFER_OES, GL_DEPTH_ATTACHMENT_OES, + GL_RENDERBUFFER_OES, gl_depthbuffer); + + int err = glCheckFramebufferStatusOES (GL_FRAMEBUFFER_OES); + switch (err) { + case GL_FRAMEBUFFER_COMPLETE_OES: + break; + case GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT_OES: + NSAssert (0, @"framebuffer incomplete attachment"); + break; + case GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT_OES: + NSAssert (0, @"framebuffer incomplete missing attachment"); + break; + case GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS_OES: + NSAssert (0, @"framebuffer incomplete dimensions"); + break; + case GL_FRAMEBUFFER_INCOMPLETE_FORMATS_OES: + NSAssert (0, @"framebuffer incomplete formats"); + break; + case GL_FRAMEBUFFER_UNSUPPORTED_OES: + NSAssert (0, @"framebuffer unsupported"); + break; +/* + case GL_FRAMEBUFFER_UNDEFINED: + NSAssert (0, @"framebuffer undefined"); + break; + case GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER: + NSAssert (0, @"framebuffer incomplete draw buffer"); + break; + case GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER: + NSAssert (0, @"framebuffer incomplete read buffer"); + break; + case GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE: + NSAssert (0, @"framebuffer incomplete multisample"); + break; + case GL_FRAMEBUFFER_INCOMPLETE_LAYER_TARGETS: + NSAssert (0, @"framebuffer incomplete layer targets"); + break; + */ + default: + NSAssert (0, @"framebuffer incomplete, unknown error 0x%04X", err); + break; + } + + check_gl_error ("setOglContext"); + +# endif // USE_IPHONE + + [self resizeContext]; +} + +#ifdef USE_IPHONE ++ (Class) layerClass +{ + return [CAEAGLLayer class]; +} + +- (void) swapBuffers +{ + glBindRenderbufferOES (GL_RENDERBUFFER_OES, gl_renderbuffer); + [ogl_ctx presentRenderbuffer:GL_RENDERBUFFER_OES]; +} +#endif // USE_IPHONE + + +#ifdef USE_BACKBUFFER + +- (void) initLayer +{ + // Do nothing. +} + +- (void)drawRect:(NSRect)rect +{ +} + + +- (void) animateOneFrame +{ +# ifdef USE_IPHONE + UIGraphicsPushContext (backbuffer); +#endif + + [self render_x11]; + +# ifdef USE_IPHONE + UIGraphicsPopContext(); +#endif +} + + +/* The backbuffer isn't actually used for GL programs, but it needs to + be there for X11 calls to not error out. However, nothing done with + X11 calls will ever show up! It all gets written into the backbuffer + and discarded. That's ok, though, because mostly it's just calls to + XClearWindow and housekeeping stuff like that. So we make a tiny one. + */ +- (void) createBackbuffer +{ + // Don't resize the X11 window to match rotation. + // Rotation and scaling are handled in GL. + // +# ifdef USE_IPHONE + double s = [self hackedContentScaleFactor]; +# else + double s = 1; +# endif + NSRect f = [self bounds]; + backbuffer_size.width = (int) (s * f.size.width); + backbuffer_size.height = (int) (s * f.size.height); + + if (! backbuffer) { + CGColorSpaceRef cs = CGColorSpaceCreateDeviceRGB(); + int w = 8; + int h = 8; + backbuffer = CGBitmapContextCreate (NULL, w, h, + 8, w*4, cs, + kCGImageAlphaPremultipliedLast); + CGColorSpaceRelease (cs); + } +} +# endif // USE_IPHONE + + +- (void)dealloc { + // ogl_ctx + // gl_framebuffer + // gl_renderbuffer + // gl_depthbuffer + [super dealloc]; +} + +@end + + +/* Utility functions... + */ + + +// redefine NSAssert, etc. here since they don't work when not inside +// an ObjC method. + +#undef NSAssert +#undef NSAssert1 +#undef NSAssert2 +#define NSASS(S) \ + jwxyz_abort ("%s", [(S) cStringUsingEncoding:NSUTF8StringEncoding]) +#define NSAssert(CC,S) do { if (!(CC)) { NSASS((S)); }} while(0) +#define NSAssert1(CC,S,A) do { if (!(CC)) { \ + NSASS(([NSString stringWithFormat: S, A])); }} while(0) +#define NSAssert2(CC,S,A,B) do { if (!(CC)) { \ + NSASS(([NSString stringWithFormat: S, A, B])); }} while(0) + + +/* Called by OpenGL savers using the XLockmore API. + */ +GLXContext * +init_GL (ModeInfo *mi) +{ + Window win = mi->window; + XScreenSaverGLView *view = (XScreenSaverGLView *) jwxyz_window_view (win); + NSAssert1 ([view isKindOfClass:[XScreenSaverGLView class]], + @"wrong view class: %@", view); + NSOpenGLContext *ctx = [view oglContext]; + +# ifndef USE_IPHONE + + if (!ctx) { + + NSOpenGLPixelFormatAttribute attrs[40]; + int i = 0; + attrs[i++] = NSOpenGLPFAColorSize; attrs[i++] = 24; + attrs[i++] = NSOpenGLPFAAlphaSize; attrs[i++] = 8; + attrs[i++] = NSOpenGLPFADepthSize; attrs[i++] = 16; + + if (get_boolean_resource (mi->dpy, "doubleBuffer", "DoubleBuffer")) + attrs[i++] = NSOpenGLPFADoubleBuffer; + + Bool ms_p = get_boolean_resource (mi->dpy, "multiSample", "MultiSample"); + + /* Sometimes, turning on multisampling kills performance. At one point, + I thought the answer was, "only run multisampling on one screen, and + leave it turned off on other screens". That's what this code does, + but it turns out, that solution is insufficient. I can't really tell + what causes poor performance with multisampling, but it's not + predictable. Without changing the code, some times a given saver will + perform fine with multisampling on, and other times it will perform + very badly. Without multisampling, they always perform fine. + */ +// if (ms_p && [[view window] screen] != [[NSScreen screens] objectAtIndex:0]) +// ms_p = 0; + + if (ms_p) { + attrs[i++] = NSOpenGLPFASampleBuffers; attrs[i++] = 1; + attrs[i++] = NSOpenGLPFASamples; attrs[i++] = 6; + // Don't really understand what this means: + // attrs[i++] = NSOpenGLPFANoRecovery; + } + + attrs[i] = 0; + + NSOpenGLPixelFormat *pixfmt = + [[NSOpenGLPixelFormat alloc] initWithAttributes:attrs]; + + if (ms_p && !pixfmt) { // Retry without multisampling. + i -= 2; + attrs[i] = 0; + pixfmt = [[NSOpenGLPixelFormat alloc] initWithAttributes:attrs]; + } + + NSAssert (pixfmt, @"unable to create NSOpenGLPixelFormat"); + + ctx = [[NSOpenGLContext alloc] + initWithFormat:pixfmt + shareContext:nil]; +// [pixfmt release]; // #### ??? + } + + // Sync refreshes to the vertical blanking interval + GLint r = 1; + [ctx setValues:&r forParameter:NSOpenGLCPSwapInterval]; +// check_gl_error ("NSOpenGLCPSwapInterval"); // SEGV sometimes. Too early? + + // #### "Build and Analyze" says that ctx leaks, because it doesn't + // seem to realize that makeCurrentContext retains it (right?) + // Not sure what to do to make this warning go away. + + [ctx makeCurrentContext]; + check_gl_error ("makeCurrentContext"); + + [view setOglContext:ctx]; + + // Clear frame buffer ASAP, else there are bits left over from other apps. + glClearColor (0, 0, 0, 1); + glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); +// glFinish (); +// glXSwapBuffers (mi->dpy, mi->window); + + + // Enable multi-threading, if possible. This runs most OpenGL commands + // and GPU management on a second CPU. + { +# ifndef kCGLCEMPEngine +# define kCGLCEMPEngine 313 // Added in MacOS 10.4.8 + XCode 2.4. +# endif + CGLContextObj cctx = CGLGetCurrentContext(); + CGLError err = CGLEnable (cctx, kCGLCEMPEngine); + if (err != kCGLNoError) { + NSLog (@"enabling multi-threaded OpenGL failed: %d", err); + } + } + + check_gl_error ("init_GL"); + +# else // USE_IPHONE + + EAGLContext *ogl_ctx = ctx; + if (!ogl_ctx) { + + Bool dbuf_p = + get_boolean_resource (mi->dpy, "doubleBuffer", "DoubleBuffer"); + + /* There seems to be no way to actually turn off double-buffering in + EAGLContext (e.g., no way to draw to the front buffer directly) + but if we turn on "retained backing" for non-buffering apps like + "pipes", at least the back buffer isn't auto-cleared on them. + */ + CAEAGLLayer *eagl_layer = (CAEAGLLayer *) view.layer; + eagl_layer.opaque = TRUE; + eagl_layer.drawableProperties = + [NSDictionary dictionaryWithObjectsAndKeys: + kEAGLColorFormatRGBA8, kEAGLDrawablePropertyColorFormat, + [NSNumber numberWithBool:!dbuf_p], kEAGLDrawablePropertyRetainedBacking, + nil]; + + // Without this, the GL frame buffer is half the screen resolution! + eagl_layer.contentsScale = [UIScreen mainScreen].scale; + + ogl_ctx = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES1]; + } + + if (!ogl_ctx) + return 0; + [view setOglContext:ogl_ctx]; + + check_gl_error ("OES_init"); + +# endif // USE_IPHONE + + // Caller expects a pointer to an opaque struct... which it dereferences. + // Don't ask me, it's historical... + static int blort = -1; + return (void *) &blort; +} + + +/* Copy the back buffer to the front buffer. + */ +void +glXSwapBuffers (Display *dpy, Window window) +{ + XScreenSaverGLView *view = (XScreenSaverGLView *) jwxyz_window_view (window); + NSAssert1 ([view isKindOfClass:[XScreenSaverGLView class]], + @"wrong view class: %@", view); +#ifndef USE_IPHONE + NSOpenGLContext *ctx = [view oglContext]; + if (ctx) [ctx flushBuffer]; // despite name, this actually swaps +#else /* USE_IPHONE */ + [view swapBuffers]; +#endif /* USE_IPHONE */ +} + +/* Does nothing - prepareContext already did the work. + */ +void +glXMakeCurrent (Display *dpy, Window window, GLXContext context) +{ +} + + +/* clear away any lingering error codes */ +void +clear_gl_error (void) +{ + while (glGetError() != GL_NO_ERROR) + ; +} + + +/* report a GL error. */ +void +check_gl_error (const char *type) +{ + char buf[100]; + GLenum i; + const char *e; + switch ((i = glGetError())) { + case GL_NO_ERROR: return; + case GL_INVALID_ENUM: e = "invalid enum"; break; + case GL_INVALID_VALUE: e = "invalid value"; break; + case GL_INVALID_OPERATION: e = "invalid operation"; break; + case GL_STACK_OVERFLOW: e = "stack overflow"; break; + case GL_STACK_UNDERFLOW: e = "stack underflow"; break; + case GL_OUT_OF_MEMORY: e = "out of memory"; break; +#ifdef GL_TABLE_TOO_LARGE_EXT + case GL_TABLE_TOO_LARGE_EXT: e = "table too large"; break; +#endif +#ifdef GL_TEXTURE_TOO_LARGE_EXT + case GL_TEXTURE_TOO_LARGE_EXT: e = "texture too large"; break; +#endif + default: + e = buf; sprintf (buf, "unknown GL error %d", (int) i); break; + } + NSAssert2 (0, @"%s GL error: %s", type, e); +} diff --git a/OSX/XScreenSaverSubclass.m b/OSX/XScreenSaverSubclass.m new file mode 100644 index 00000000..6a5f8c23 --- /dev/null +++ b/OSX/XScreenSaverSubclass.m @@ -0,0 +1,33 @@ +/* xscreensaver, Copyright (c) 2006 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. +*/ + +/* This stub is compiled differently for each saver, just to ensure that + each one has a different class name. If multiple savers use the + XScreenSaver class directly, System Preferences gets really confused. + */ + +#ifndef CLASS + ERROR! -DCLASS missing +#endif + +#ifdef USE_GL +# import "XScreenSaverGLView.h" +# define SUPERCLASS XScreenSaverGLView +#else +# import "XScreenSaverView.h" +# define SUPERCLASS XScreenSaverView +#endif + +@interface CLASS : SUPERCLASS { } +@end + +@implementation CLASS +@end diff --git a/OSX/XScreenSaverView.h b/OSX/XScreenSaverView.h new file mode 100644 index 00000000..0fe2046c --- /dev/null +++ b/OSX/XScreenSaverView.h @@ -0,0 +1,120 @@ +/* xscreensaver, Copyright (c) 2006-2012 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. +*/ + +/* This is a subclass of Apple's ScreenSaverView that knows how to run + xscreensaver programs without X11 via the dark magic of the "jwxyz" + library. In xscreensaver terminology, this is the replacement for + the "screenhack.c" module. + */ + +#ifdef USE_IPHONE +# import +# import +# define NSView UIView +# define NSRect CGRect +# define NSSize CGSize +# define NSColor UIColor +# define NSImage UIImage +# define NSEvent UIEvent +# define NSWindow UIWindow +#else +# import +# import +#endif + + +#import "screenhackI.h" +#import "PrefsReader.h" + +#ifdef USE_IPHONE +@interface ScreenSaverView : NSView +- (id)initWithFrame:(NSRect)frame isPreview:(BOOL)isPreview; +- (NSTimeInterval)animationTimeInterval; +- (void)setAnimationTimeInterval:(NSTimeInterval)timeInterval; +- (void)startAnimation; +- (void)stopAnimation; +- (BOOL)isAnimating; +- (void)animateOneFrame; +- (BOOL)hasConfigureSheet; +//- (NSWindow*)configureSheet; +- (UIViewController*)configureView; +- (BOOL)isPreview; +@end + +#endif // USE_IPHONE + + +#ifdef USE_IPHONE +# define USE_BACKBUFFER /* must be in sync with jwxyz.h */ +#endif + + +@interface XScreenSaverView : ScreenSaverView +# ifdef USE_IPHONE + +# endif +{ + struct xscreensaver_function_table *xsft; + PrefsReader *prefsReader; + + BOOL setup_p; // whether xsft->setup_cb() has been run + BOOL initted_p; // whether xsft->init_cb() has been run + BOOL resized_p; // whether to run the xsft->reshape_cb() soon + double next_frame_time; // time_t in milliseconds of when to tick the frame + + // Data used by the Xlib-flavored screensaver + Display *xdpy; + Window xwindow; + void *xdata; + fps_state *fpst; + +# ifdef USE_IPHONE + UIDeviceOrientation orientation, new_orientation; + double tap_time; + CGPoint tap_point; + BOOL screenLocked; + + GLfloat rotation_ratio; // ratio thru rotation anim, or -1 + NSSize rot_from, rot_to; // start size rect, end size rect + GLfloat angle_from, angle_to; // start angle, end angle + double rot_start_time; + + NSSize rot_current_size; + GLfloat rot_current_angle; + + NSTimer *crash_timer; + +# endif // USE_IPHONE + +# ifdef USE_BACKBUFFER + CGContextRef backbuffer; + CGSize backbuffer_size; +# endif // USE_BACKBUFFER +} + +- (id)initWithFrame:(NSRect)frame saverName:(NSString*)n isPreview:(BOOL)p; + +- (void) render_x11; +- (void) prepareContext; +- (void) resizeContext; +- (NSUserDefaultsController *) userDefaultsController; + +#ifdef USE_IPHONE +- (void)didRotate:(NSNotification *)notification; +- (void)setScreenLocked:(BOOL)locked; +#endif // USE_IPHONE + +#ifdef USE_BACKBUFFER +- (void)initLayer; +- (void)createBackbuffer; +#endif // USE_BACKBUFFER + +@end diff --git a/OSX/XScreenSaverView.m b/OSX/XScreenSaverView.m new file mode 100644 index 00000000..a0dc3813 --- /dev/null +++ b/OSX/XScreenSaverView.m @@ -0,0 +1,1685 @@ +/* xscreensaver, Copyright (c) 2006-2012 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. +*/ + +/* This is a subclass of Apple's ScreenSaverView that knows how to run + xscreensaver programs without X11 via the dark magic of the "jwxyz" + library. In xscreensaver terminology, this is the replacement for + the "screenhack.c" module. + */ + +#import +#import "XScreenSaverView.h" +#import "XScreenSaverConfigSheet.h" +#import "screenhackI.h" +#import "xlockmoreI.h" +#import "jwxyz-timers.h" + +#ifdef USE_IPHONE +# include "ios_function_tables.h" +static NSDictionary *function_tables = 0; +#endif + + +/* Garbage collection only exists if we are being compiled against the + 10.6 SDK or newer, not if we are building against the 10.4 SDK. + */ +#ifndef MAC_OS_X_VERSION_10_6 +# define MAC_OS_X_VERSION_10_6 1060 /* undefined in 10.4 SDK, grr */ +#endif +#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_6 /* 10.6 SDK */ +# import +# define DO_GC_HACKERY +#endif + +extern struct xscreensaver_function_table *xscreensaver_function_table; + +/* Global variables used by the screen savers + */ +const char *progname; +const char *progclass; +int mono_p = 0; + + +# ifdef USE_IPHONE + +/* Stub definition of the superclass, for iPhone. + */ +@implementation ScreenSaverView +{ + NSTimeInterval anim_interval; + Bool animating_p; + NSTimer *anim_timer; +} + +- (id)initWithFrame:(NSRect)frame isPreview:(BOOL)isPreview { + self = [super initWithFrame:frame]; + if (! self) return 0; + anim_interval = 1.0/30; + return self; +} +- (NSTimeInterval)animationTimeInterval { return anim_interval; } +- (void)setAnimationTimeInterval:(NSTimeInterval)i { anim_interval = i; } +- (BOOL)hasConfigureSheet { return NO; } +- (NSWindow *)configureSheet { return nil; } +- (NSView *)configureView { return nil; } +- (BOOL)isPreview { return NO; } +- (BOOL)isAnimating { return animating_p; } +- (void)animateOneFrame { } + +- (void)startAnimation { + if (animating_p) return; + animating_p = YES; + anim_timer = [NSTimer scheduledTimerWithTimeInterval: anim_interval + target:self + selector:@selector(animateOneFrame) + userInfo:nil + repeats:YES]; +} + +- (void)stopAnimation { + if (anim_timer) { + [anim_timer invalidate]; + anim_timer = 0; + } + animating_p = NO; +} +@end + +# endif // !USE_IPHONE + + + +@interface XScreenSaverView (Private) +- (void) stopAndClose; +- (void) stopAndClose:(Bool)relaunch; +@end + +@implementation XScreenSaverView + +// Given a lower-cased saver name, returns the function table for it. +// If no name, guess the name from the class's bundle name. +// +- (struct xscreensaver_function_table *) findFunctionTable:(NSString *)name +{ + NSBundle *nsb = [NSBundle bundleForClass:[self class]]; + NSAssert1 (nsb, @"no bundle for class %@", [self class]); + + NSString *path = [nsb bundlePath]; + CFURLRef url = CFURLCreateWithFileSystemPath(kCFAllocatorDefault, + (CFStringRef) path, + kCFURLPOSIXPathStyle, + true); + CFBundleRef cfb = CFBundleCreate (kCFAllocatorDefault, url); + CFRelease (url); + NSAssert1 (cfb, @"no CFBundle for \"%@\"", path); + + if (! name) + name = [[path lastPathComponent] stringByDeletingPathExtension]; + + name = [[name lowercaseString] + stringByReplacingOccurrencesOfString:@" " + withString:@""]; + +# ifndef USE_IPHONE + // CFBundleGetDataPointerForName doesn't work in "Archive" builds. + // I'm guessing that symbol-stripping is mandatory. Fuck. + NSString *table_name = [name stringByAppendingString: + @"_xscreensaver_function_table"]; + void *addr = CFBundleGetDataPointerForName (cfb, (CFStringRef) table_name); + CFRelease (cfb); + + if (! addr) + NSLog (@"no symbol \"%@\" for \"%@\"", table_name, path); + +# else // USE_IPHONE + // Remember: any time you add a new saver to the iOS app, + // manually run "make ios_function_tables.h"! + if (! function_tables) + function_tables = [make_function_tables_dict() retain]; + NSValue *v = [function_tables objectForKey: name]; + void *addr = v ? [v pointerValue] : 0; +# endif // USE_IPHONE + + return (struct xscreensaver_function_table *) addr; +} + + +// Add the "Contents/Resources/" subdirectory of this screen saver's .bundle +// to $PATH for the benefit of savers that include helper shell scripts. +// +- (void) setShellPath +{ + NSBundle *nsb = [NSBundle bundleForClass:[self class]]; + NSAssert1 (nsb, @"no bundle for class %@", [self class]); + + NSString *nsdir = [nsb resourcePath]; + NSAssert1 (nsdir, @"no resourcePath for class %@", [self class]); + const char *dir = [nsdir cStringUsingEncoding:NSUTF8StringEncoding]; + const char *opath = getenv ("PATH"); + if (!opath) opath = "/bin"; // $PATH is unset when running under Shark! + char *npath = (char *) malloc (strlen (opath) + strlen (dir) + 30); + strcpy (npath, "PATH="); + strcat (npath, dir); + strcat (npath, ":"); + strcat (npath, opath); + if (putenv (npath)) { + perror ("putenv"); + NSAssert1 (0, @"putenv \"%s\" failed", npath); + } + + /* Don't free (npath) -- MacOS's putenv() does not copy it. */ +} + + +// set an $XSCREENSAVER_CLASSPATH variable so that included shell scripts +// (e.g., "xscreensaver-text") know how to look up resources. +// +- (void) setResourcesEnv:(NSString *) name +{ + NSBundle *nsb = [NSBundle bundleForClass:[self class]]; + NSAssert1 (nsb, @"no bundle for class %@", [self class]); + + const char *s = [name cStringUsingEncoding:NSUTF8StringEncoding]; + char *env = (char *) malloc (strlen (s) + 40); + strcpy (env, "XSCREENSAVER_CLASSPATH="); + strcat (env, s); + if (putenv (env)) { + perror ("putenv"); + NSAssert1 (0, @"putenv \"%s\" failed", env); + } + /* Don't free (env) -- MacOS's putenv() does not copy it. */ +} + + +static void +add_default_options (const XrmOptionDescRec *opts, + const char * const *defs, + XrmOptionDescRec **opts_ret, + const char ***defs_ret) +{ + /* These aren't "real" command-line options (there are no actual command-line + options in the Cocoa version); but this is the somewhat kludgey way that + the and tags in the + ../hacks/config/\*.xml files communicate with the preferences database. + */ + static const XrmOptionDescRec default_options [] = { + { "-text-mode", ".textMode", XrmoptionSepArg, 0 }, + { "-text-literal", ".textLiteral", XrmoptionSepArg, 0 }, + { "-text-file", ".textFile", XrmoptionSepArg, 0 }, + { "-text-url", ".textURL", XrmoptionSepArg, 0 }, + { "-text-program", ".textProgram", XrmoptionSepArg, 0 }, + { "-grab-desktop", ".grabDesktopImages", XrmoptionNoArg, "True" }, + { "-no-grab-desktop", ".grabDesktopImages", XrmoptionNoArg, "False"}, + { "-choose-random-images", ".chooseRandomImages",XrmoptionNoArg, "True" }, + { "-no-choose-random-images",".chooseRandomImages",XrmoptionNoArg, "False"}, + { "-image-directory", ".imageDirectory", XrmoptionSepArg, 0 }, + { "-fps", ".doFPS", XrmoptionNoArg, "True" }, + { "-no-fps", ".doFPS", XrmoptionNoArg, "False"}, + { 0, 0, 0, 0 } + }; + static const char *default_defaults [] = { + ".doFPS: False", + ".doubleBuffer: True", + ".multiSample: False", +# ifndef USE_IPHONE + ".textMode: date", +# else + ".textMode: url", +# endif + // ".textLiteral: ", + // ".textFile: ", + ".textURL: http://twitter.com/statuses/public_timeline.atom", + // ".textProgram: ", + ".grabDesktopImages: yes", +# ifndef USE_IPHONE + ".chooseRandomImages: no", +# else + ".chooseRandomImages: yes", +# endif + ".imageDirectory: ~/Pictures", + ".relaunchDelay: 2", + 0 + }; + + int count = 0, i, j; + for (i = 0; default_options[i].option; i++) + count++; + for (i = 0; opts[i].option; i++) + count++; + + XrmOptionDescRec *opts2 = (XrmOptionDescRec *) + calloc (count + 1, sizeof (*opts2)); + + i = 0; + j = 0; + while (default_options[j].option) { + opts2[i] = default_options[j]; + i++, j++; + } + j = 0; + while (opts[j].option) { + opts2[i] = opts[j]; + i++, j++; + } + + *opts_ret = opts2; + + + /* now the defaults + */ + count = 0; + for (i = 0; default_defaults[i]; i++) + count++; + for (i = 0; defs[i]; i++) + count++; + + const char **defs2 = (const char **) calloc (count + 1, sizeof (*defs2)); + + i = 0; + j = 0; + while (default_defaults[j]) { + defs2[i] = default_defaults[j]; + i++, j++; + } + j = 0; + while (defs[j]) { + defs2[i] = defs[j]; + i++, j++; + } + + *defs_ret = defs2; +} + + +#ifdef USE_IPHONE +/* Returns the current time in seconds as a double. + */ +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)); +} +#endif // USE_IPHONE + + +- (id) initWithFrame:(NSRect)frame + saverName:(NSString *)saverName + isPreview:(BOOL)isPreview +{ +# ifdef USE_IPHONE + rot_current_size = frame.size; // needs to be early, because + rot_from = rot_current_size; // [self setFrame] is called by + rot_to = rot_current_size; // [super initWithFrame]. + rotation_ratio = -1; +# endif + + if (! (self = [super initWithFrame:frame isPreview:isPreview])) + return 0; + + xsft = [self findFunctionTable: saverName]; + if (! xsft) { + [self release]; + return 0; + } + + [self setShellPath]; + +# ifdef USE_IPHONE + [self setMultipleTouchEnabled:YES]; + orientation = UIDeviceOrientationUnknown; + [self didRotate:nil]; +# endif // USE_IPHONE + + setup_p = YES; + if (xsft->setup_cb) + xsft->setup_cb (xsft, xsft->setup_arg); + + /* The plist files for these preferences show up in + $HOME/Library/Preferences/ByHost/ in a file named like + "org.jwz.xscreensaver...plist" + */ + NSString *name = [NSString stringWithCString:xsft->progclass + encoding:NSISOLatin1StringEncoding]; + name = [@"org.jwz.xscreensaver." stringByAppendingString:name]; + [self setResourcesEnv:name]; + + + XrmOptionDescRec *opts = 0; + const char **defs = 0; + add_default_options (xsft->options, xsft->defaults, &opts, &defs); + prefsReader = [[PrefsReader alloc] + initWithName:name xrmKeys:opts defaults:defs]; + free (defs); + // free (opts); // bah, we need these! #### leak! + xsft->options = opts; + + progname = progclass = xsft->progclass; + + next_frame_time = 0; + +# ifdef USE_BACKBUFFER + [self createBackbuffer]; + [self initLayer]; +# endif + +# ifdef USE_IPHONE + // So we can tell when we're docked. + [UIDevice currentDevice].batteryMonitoringEnabled = YES; +# endif // USE_IPHONE + + return self; +} + +- (void) initLayer +{ +# ifndef USE_IPHONE + [self setLayer: [CALayer layer]]; + [self setWantsLayer: YES]; +# endif +} + + +- (id) initWithFrame:(NSRect)frame isPreview:(BOOL)p +{ + return [self initWithFrame:frame saverName:0 isPreview:p]; +} + + +- (void) dealloc +{ + NSAssert(![self isAnimating], @"still animating"); + NSAssert(!xdata, @"xdata not yet freed"); + if (xdpy) + jwxyz_free_display (xdpy); + +# ifdef USE_BACKBUFFER + if (backbuffer) + CGContextRelease (backbuffer); +# endif + + [prefsReader release]; + + // xsft + // fpst + + [super dealloc]; +} + +- (PrefsReader *) prefsReader +{ + return prefsReader; +} + + +#ifdef USE_IPHONE +- (void) lockFocus { } +- (void) unlockFocus { } +#endif // USE_IPHONE + + + +# ifdef USE_IPHONE +/* A few seconds after the saver launches, we store the "wasRunning" + preference. This is so that if the saver is crashing at startup, + we don't launch it again next time, getting stuck in a crash loop. + */ +- (void) allSystemsGo: (NSTimer *) timer +{ + NSAssert (timer == crash_timer, @"crash timer screwed up"); + crash_timer = 0; + + NSUserDefaults *prefs = [NSUserDefaults standardUserDefaults]; + [prefs setBool:YES forKey:@"wasRunning"]; + [prefs synchronize]; +} +#endif // USE_IPHONE + + +- (void) startAnimation +{ + NSAssert(![self isAnimating], @"already animating"); + NSAssert(!initted_p && !xdata, @"already initialized"); + [super startAnimation]; + /* We can't draw on the window from this method, so we actually do the + initialization of the screen saver (xsft->init_cb) in the first call + to animateOneFrame() instead. + */ + +# ifdef USE_IPHONE + if (crash_timer) + [crash_timer invalidate]; + + NSUserDefaults *prefs = [NSUserDefaults standardUserDefaults]; + [prefs removeObjectForKey:@"wasRunning"]; + [prefs synchronize]; + + crash_timer = [NSTimer scheduledTimerWithTimeInterval: 5 + target:self + selector:@selector(allSystemsGo:) + userInfo:nil + repeats:NO]; +# endif // USE_IPHONE + + // Never automatically turn the screen off if we are docked, + // and an animation is running. + // +# ifdef USE_IPHONE + [UIApplication sharedApplication].idleTimerDisabled = + ([UIDevice currentDevice].batteryState != UIDeviceBatteryStateUnplugged); +# endif +} + + +- (void)stopAnimation +{ + NSAssert([self isAnimating], @"not animating"); + + if (initted_p) { + + [self lockFocus]; // in case something tries to draw from here + [self prepareContext]; + + /* I considered just not even calling the free callback at all... + But webcollage-cocoa needs it, to kill the inferior webcollage + processes (since the screen saver framework never generates a + SIGPIPE for them...) Instead, I turned off the free call in + xlockmore.c, which is where all of the bogus calls are anyway. + */ + xsft->free_cb (xdpy, xwindow, xdata); + [self unlockFocus]; + +// setup_p = NO; // #### wait, do we need this? + initted_p = NO; + xdata = 0; + } + +# ifdef USE_IPHONE + if (crash_timer) + [crash_timer invalidate]; + crash_timer = 0; + NSUserDefaults *prefs = [NSUserDefaults standardUserDefaults]; + [prefs removeObjectForKey:@"wasRunning"]; + [prefs synchronize]; +# endif // USE_IPHONE + + [super stopAnimation]; + + // When an animation is no longer running (e.g., looking at the list) + // then it's ok to power off the screen when docked. + // +# ifdef USE_IPHONE + [UIApplication sharedApplication].idleTimerDisabled = NO; +# endif +} + + +/* Hook for the XScreenSaverGLView subclass + */ +- (void) prepareContext +{ +} + +/* Hook for the XScreenSaverGLView subclass + */ +- (void) resizeContext +{ +} + + +static void +screenhack_do_fps (Display *dpy, Window w, fps_state *fpst, void *closure) +{ + fps_compute (fpst, 0, -1); + fps_draw (fpst); +} + + +#ifdef USE_IPHONE + +/* On iPhones with Retina displays, we can draw the savers in "real" + pixels, and that works great. The 320x480 "point" screen is really + a 640x960 *pixel* screen. However, Retina iPads have 768x1024 + point screens which are 1536x2048 pixels, and apparently that's + enough pixels that copying those bits to the screen is slow. Like, + drops us from 15fps to 7fps. So, on Retina iPads, we don't draw in + real pixels. This will probably make the savers look better + anyway, since that's a higher resolution than most desktop monitors + have even today. (This is only true for X11 programs, not GL + programs. Those are fine at full rez.) + */ +- (CGFloat) hackedContentScaleFactor +{ + GLfloat s = [self contentScaleFactor]; + CGRect frame = [self bounds]; + if (frame.size.width >= 1024 || + frame.size.height >= 1024) + s = 1; + return s; +} + + +static GLfloat _global_rot_current_angle_kludge; + +double current_device_rotation (void) +{ + return -_global_rot_current_angle_kludge; +} + + +- (void) hackRotation +{ + if (rotation_ratio >= 0) { // in the midst of a rotation animation + +# define CLAMP180(N) while (N < 0) N += 360; while (N > 180) N -= 360 + GLfloat f = angle_from; + GLfloat t = angle_to; + CLAMP180(f); + CLAMP180(t); + GLfloat dist = -(t-f); + CLAMP180(dist); + + // Intermediate angle. + rot_current_angle = f - rotation_ratio * dist; + + // Intermediate frame size. + rot_current_size.width = rot_from.width + + rotation_ratio * (rot_to.width - rot_from.width); + rot_current_size.height = rot_from.height + + rotation_ratio * (rot_to.height - rot_from.height); + + // Tick animation. Complete rotation in 1/6th sec. + double now = double_time(); + double duration = 1/6.0; + rotation_ratio = 1 - ((rot_start_time + duration - now) / duration); + + if (rotation_ratio > 1) { // Done animating. + orientation = new_orientation; + rot_current_angle = angle_to; + rot_current_size = rot_to; + rotation_ratio = -1; + + // Check orientation again in case we rotated again while rotating: + // this is a no-op if nothing has changed. + [self didRotate:nil]; + } + } else { // Not animating a rotation. + rot_current_angle = angle_to; + rot_current_size = rot_to; + } + + CLAMP180(rot_current_angle); + _global_rot_current_angle_kludge = rot_current_angle; + +# undef CLAMP180 + + double s = [self hackedContentScaleFactor]; + if (((int) backbuffer_size.width != (int) (s * rot_current_size.width) || + (int) backbuffer_size.height != (int) (s * rot_current_size.height)) +/* && rotation_ratio == -1*/) + [self resize_x11]; +} + + +- (void)alertView:(UIAlertView *)av clickedButtonAtIndex:(NSInteger)i +{ + if (i == 0) exit (-1); // Cancel + [self stopAndClose]; // Keep going +} + +- (void) handleException: (NSException *)e +{ + NSLog (@"Caught exception: %@", e); + [[[UIAlertView alloc] initWithTitle: + [NSString stringWithFormat: @"%s crashed!", + xsft->progclass] + message: + [NSString stringWithFormat: + @"The error message was:" + "\n\n%@\n\n" + "If it keeps crashing, try " + "resetting its options.", + e] + delegate: self + cancelButtonTitle: @"Exit" + otherButtonTitles: @"Keep going", nil] + show]; + [self stopAnimation]; +} + +#endif // USE_IPHONE + + +#ifdef USE_BACKBUFFER + +/* Create a bitmap context into which we render everything. + If the desired size has changed, re-created it. + */ +- (void) createBackbuffer +{ +# ifdef USE_IPHONE + double s = [self hackedContentScaleFactor]; + int new_w = s * rot_current_size.width; + int new_h = s * rot_current_size.height; +# else + int new_w = [self bounds].size.width; + int new_h = [self bounds].size.height; +# endif + + if (backbuffer && + backbuffer_size.width == new_w && + backbuffer_size.height == new_h) + return; + + CGSize osize = backbuffer_size; + CGContextRef ob = backbuffer; + + backbuffer_size.width = new_w; + backbuffer_size.height = new_h; + + CGColorSpaceRef cs = CGColorSpaceCreateDeviceRGB(); + backbuffer = CGBitmapContextCreate (NULL, + backbuffer_size.width, + backbuffer_size.height, + 8, + backbuffer_size.width * 4, + cs, + kCGImageAlphaPremultipliedLast); + CGColorSpaceRelease (cs); + NSAssert (backbuffer, @"unable to allocate back buffer"); + + // Clear it. + CGRect r; + r.origin.x = r.origin.y = 0; + r.size = backbuffer_size; + CGContextSetGrayFillColor (backbuffer, 0, 1); + CGContextFillRect (backbuffer, r); + + if (ob) { + // Restore old bits, as much as possible, to the X11 upper left origin. + CGRect rect; + rect.origin.x = 0; + rect.origin.y = (backbuffer_size.height - osize.height); + rect.size = osize; + CGImageRef img = CGBitmapContextCreateImage (ob); + CGContextDrawImage (backbuffer, rect, img); + CGImageRelease (img); + CGContextRelease (ob); + } +} + +#endif // USE_BACKBUFFER + + +/* Inform X11 that the size of our window has changed. + */ +- (void) resize_x11 +{ + if (!xwindow) return; // early + +# ifdef USE_BACKBUFFER + [self createBackbuffer]; + jwxyz_window_resized (xdpy, xwindow, + 0, 0, + backbuffer_size.width, backbuffer_size.height, + backbuffer); +# else // !USE_BACKBUFFER + NSRect r = [self frame]; // ignoring rotation is closer + r.size = [self bounds].size; // to what XGetGeometry expects. + jwxyz_window_resized (xdpy, xwindow, + r.origin.x, r.origin.y, + r.size.width, r.size.height, + 0); +# endif // !USE_BACKBUFFER + + // Next time render_x11 is called, run the saver's reshape_cb. + resized_p = YES; +} + + +- (void) render_x11 +{ +# ifdef USE_IPHONE + @try { + + if (orientation == UIDeviceOrientationUnknown) + [self didRotate:nil]; + [self hackRotation]; +# endif + + if (!initted_p) { + + if (! xdpy) { +# ifdef USE_BACKBUFFER + NSAssert (backbuffer, @"no back buffer"); + xdpy = jwxyz_make_display (self, backbuffer); +# else + xdpy = jwxyz_make_display (self, 0); +# endif + xwindow = XRootWindow (xdpy, 0); + [self resize_x11]; + } + + if (!setup_p) { + setup_p = YES; + if (xsft->setup_cb) + xsft->setup_cb (xsft, xsft->setup_arg); + } + initted_p = YES; + resized_p = NO; + NSAssert(!xdata, @"xdata already initialized"); + +# undef ya_rand_init + ya_rand_init (0); + + XSetWindowBackground (xdpy, xwindow, + get_pixel_resource (xdpy, 0, + "background", "Background")); + XClearWindow (xdpy, xwindow); + +# ifndef USE_IPHONE + [[self window] setAcceptsMouseMovedEvents:YES]; +# endif + + /* In MacOS 10.5, this enables "QuartzGL", meaning that the Quartz + drawing primitives will run on the GPU instead of the CPU. + It seems like it might make things worse rather than better, + though... Plus it makes us binary-incompatible with 10.4. + +# if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5 + [[self window] setPreferredBackingLocation: + NSWindowBackingLocationVideoMemory]; +# endif + */ + + /* Kludge: even though the init_cb functions are declared to take 2 args, + actually call them with 3, for the benefit of xlockmore_init() and + xlockmore_setup(). + */ + void *(*init_cb) (Display *, Window, void *) = + (void *(*) (Display *, Window, void *)) xsft->init_cb; + + xdata = init_cb (xdpy, xwindow, xsft->setup_arg); + + if (get_boolean_resource (xdpy, "doFPS", "DoFPS")) { + fpst = fps_init (xdpy, xwindow); + if (! xsft->fps_cb) xsft->fps_cb = screenhack_do_fps; + } + } + + + /* I don't understand why we have to do this *every frame*, but we do, + or else the cursor comes back on. + */ +# ifndef USE_IPHONE + if (![self isPreview]) + [NSCursor setHiddenUntilMouseMoves:YES]; +# endif + + + if (fpst) + { + /* This is just a guess, but the -fps code wants to know how long + we were sleeping between frames. + */ + long usecs = 1000000 * [self animationTimeInterval]; + usecs -= 200; // caller apparently sleeps for slightly less sometimes... + if (usecs < 0) usecs = 0; + fps_slept (fpst, usecs); + } + + + /* It turns out that [ScreenSaverView setAnimationTimeInterval] does nothing. + This is bad, because some of the screen hacks want to delay for long + periods (like 5 seconds or a minute!) between frames, and running them + all at 60 FPS is no good. + + So, we don't use setAnimationTimeInterval, and just let the framework call + us whenever. But, we only invoke the screen hack's "draw frame" method + when enough time has expired. + + This means two extra calls to gettimeofday() per frame. For fast-cycling + screen savers, that might actually slow them down. Oh well. + + #### Also, we do not run the draw callback faster than the system's + animationTimeInterval, so if any savers are pickier about timing + than that, this may slow them down too much. If that's a problem, + then we could call draw_cb in a loop here (with usleep) until the + next call would put us past animationTimeInterval... But a better + approach would probably be to just change the saver to not do that. + */ + struct timeval tv; + gettimeofday (&tv, 0); + double now = tv.tv_sec + (tv.tv_usec / 1000000.0); + if (now < next_frame_time) return; + + [self prepareContext]; + + if (resized_p) { + // We do this here instead of in setFrame so that all the + // Xlib drawing takes place under the animation timer. + [self resizeContext]; + NSRect r; +# ifndef USE_BACKBUFFER + r = [self bounds]; +# else // USE_BACKBUFFER + r.origin.x = 0; + r.origin.y = 0; + r.size.width = backbuffer_size.width; + r.size.height = backbuffer_size.height; +# endif // USE_BACKBUFFER + + xsft->reshape_cb (xdpy, xwindow, xdata, r.size.width, r.size.height); + resized_p = NO; + } + + // Run any XtAppAddInput callbacks now. + // (Note that XtAppAddTimeOut callbacks have already been run by + // the Cocoa event loop.) + // + jwxyz_sources_run (display_sources_data (xdpy)); + + + // And finally: + // +# ifndef USE_IPHONE + NSDisableScreenUpdates(); +# endif + unsigned long delay = xsft->draw_cb (xdpy, xwindow, xdata); + if (fpst) xsft->fps_cb (xdpy, xwindow, fpst, xdata); +# ifndef USE_IPHONE + NSEnableScreenUpdates(); +# endif + + gettimeofday (&tv, 0); + now = tv.tv_sec + (tv.tv_usec / 1000000.0); + next_frame_time = now + (delay / 1000000.0); + +# ifdef USE_IPHONE // Allow savers on the iPhone to run full-tilt. + if (delay < [self animationTimeInterval]) + [self setAnimationTimeInterval:(delay / 1000000.0)]; +# endif + +# ifdef DO_GC_HACKERY + /* Current theory is that the 10.6 garbage collector sucks in the + following way: + + It only does a collection when a threshold of outstanding + collectable allocations has been surpassed. However, CoreGraphics + creates lots of small collectable allocations that contain pointers + to very large non-collectable allocations: a small CG object that's + collectable referencing large malloc'd allocations (non-collectable) + containing bitmap data. So the large allocation doesn't get freed + until GC collects the small allocation, which triggers its finalizer + to run which frees the large allocation. So GC is deciding that it + doesn't really need to run, even though the process has gotten + enormous. GC eventually runs once pageouts have happened, but by + then it's too late, and the machine's resident set has been + sodomized. + + So, we force an exhaustive garbage collection in this process + approximately every 5 seconds whether the system thinks it needs + one or not. + */ + { + static int tick = 0; + if (++tick > 5*30) { + tick = 0; + objc_collect (OBJC_EXHAUSTIVE_COLLECTION); + } + } +# endif // DO_GC_HACKERY + +# ifdef USE_IPHONE + } + @catch (NSException *e) { + [self handleException: e]; + } +# endif // USE_IPHONE +} + + +/* drawRect always does nothing, and animateOneFrame renders bits to the + screen. This is (now) true of both X11 and GL on both MacOS and iOS. + */ + +- (void)drawRect:(NSRect)rect +{ + if (xwindow) // clear to the X window's bg color, not necessarily black. + XClearWindow (xdpy, xwindow); + else + [super drawRect:rect]; // early: black. +} + + +#ifndef USE_BACKBUFFER + +- (void) animateOneFrame +{ + [self render_x11]; +} + +#else // USE_BACKBUFFER + +- (void) animateOneFrame +{ + // Render X11 into the backing store bitmap... + + NSAssert (backbuffer, @"no back buffer"); + +# ifdef USE_IPHONE + UIGraphicsPushContext (backbuffer); +# endif + + [self render_x11]; + +# ifdef USE_IPHONE + UIGraphicsPopContext(); +# endif + +# ifdef USE_IPHONE + // Then compute the transformations for rotation. + + // The rotation origin for layer.affineTransform is in the center already. + CGAffineTransform t = + CGAffineTransformMakeRotation (rot_current_angle / (180.0 / M_PI)); + + // Correct the aspect ratio. + CGRect frame = [self bounds]; + double s = [self hackedContentScaleFactor]; + t = CGAffineTransformScale(t, + backbuffer_size.width / (s * frame.size.width), + backbuffer_size.height / (s * frame.size.height)); + + self.layer.affineTransform = t; +# endif // USE_IPHONE + + // Then copy that bitmap to the screen, by just stuffing it into + // the layer. The superclass drawRect method will handle the rest. + + CGImageRef img = CGBitmapContextCreateImage (backbuffer); + self.layer.contents = (id)img; + CGImageRelease (img); +} + +#endif // !USE_BACKBUFFER + + + +- (void) setFrame:(NSRect) newRect +{ + [super setFrame:newRect]; + + if (xwindow) // inform Xlib that the window has changed now. + [self resize_x11]; +} + + +# ifndef USE_IPHONE // Doesn't exist on iOS +- (void) setFrameSize:(NSSize) newSize +{ + [super setFrameSize:newSize]; + if (xwindow) + [self resize_x11]; +} +# endif // !USE_IPHONE + + ++(BOOL) performGammaFade +{ + return YES; +} + +- (BOOL) hasConfigureSheet +{ + return YES; +} + +#ifndef USE_IPHONE +- (NSWindow *) configureSheet +#else +- (UIViewController *) configureView +#endif +{ + NSBundle *bundle = [NSBundle bundleForClass:[self class]]; + NSString *file = [NSString stringWithCString:xsft->progclass + encoding:NSISOLatin1StringEncoding]; + file = [file lowercaseString]; + NSString *path = [bundle pathForResource:file ofType:@"xml"]; + if (!path) { + NSLog (@"%@.xml does not exist in the application bundle: %@/", + file, [bundle resourcePath]); + return nil; + } + +# ifdef USE_IPHONE + UIViewController *sheet; +# else // !USE_IPHONE + NSWindow *sheet; +# endif // !USE_IPHONE + + sheet = [[XScreenSaverConfigSheet alloc] + initWithXMLFile:path + options:xsft->options + controller:[prefsReader userDefaultsController] + defaults:[prefsReader defaultOptions]]; + + // #### am I expected to retain this, or not? wtf. + // I thought not, but if I don't do this, we (sometimes) crash. + [sheet retain]; + + return sheet; +} + + +- (NSUserDefaultsController *) userDefaultsController +{ + return [prefsReader userDefaultsController]; +} + + +/* Announce our willingness to accept keyboard input. +*/ +- (BOOL)acceptsFirstResponder +{ + return YES; +} + + +#ifndef USE_IPHONE + +/* Convert an NSEvent into an XEvent, and pass it along. + Returns YES if it was handled. + */ +- (BOOL) doEvent: (NSEvent *) e + type: (int) type +{ + if (![self isPreview] || // no event handling if actually screen-saving! + ![self isAnimating] || + !initted_p) + return NO; + + XEvent xe; + memset (&xe, 0, sizeof(xe)); + + int state = 0; + + int flags = [e modifierFlags]; + if (flags & NSAlphaShiftKeyMask) state |= LockMask; + if (flags & NSShiftKeyMask) state |= ShiftMask; + if (flags & NSControlKeyMask) state |= ControlMask; + if (flags & NSAlternateKeyMask) state |= Mod1Mask; + if (flags & NSCommandKeyMask) state |= Mod2Mask; + + NSPoint p = [[[e window] contentView] convertPoint:[e locationInWindow] + toView:self]; +# ifdef USE_IPHONE + double s = [self hackedContentScaleFactor]; +# else + int s = 1; +# endif + int x = s * p.x; + int y = s * ([self bounds].size.height - p.y); + + xe.xany.type = type; + switch (type) { + case ButtonPress: + case ButtonRelease: + xe.xbutton.x = x; + xe.xbutton.y = y; + xe.xbutton.state = state; + if ([e type] == NSScrollWheel) + xe.xbutton.button = ([e deltaY] > 0 ? Button4 : + [e deltaY] < 0 ? Button5 : + [e deltaX] > 0 ? Button6 : + [e deltaX] < 0 ? Button7 : + 0); + else + xe.xbutton.button = [e buttonNumber] + 1; + break; + case MotionNotify: + xe.xmotion.x = x; + xe.xmotion.y = y; + xe.xmotion.state = state; + break; + case KeyPress: + case KeyRelease: + { + NSString *ns = (([e type] == NSFlagsChanged) ? 0 : + [e charactersIgnoringModifiers]); + KeySym k = 0; + + if (!ns || [ns length] == 0) // dead key + { + // Cocoa hides the difference between left and right keys. + // Also we only get KeyPress events for these, no KeyRelease + // (unless we hack the mod state manually. Bleh.) + // + if (flags & NSAlphaShiftKeyMask) k = XK_Caps_Lock; + else if (flags & NSShiftKeyMask) k = XK_Shift_L; + else if (flags & NSControlKeyMask) k = XK_Control_L; + else if (flags & NSAlternateKeyMask) k = XK_Alt_L; + else if (flags & NSCommandKeyMask) k = XK_Meta_L; + } + else if ([ns length] == 1) // real key + { + switch ([ns characterAtIndex:0]) { + case NSLeftArrowFunctionKey: k = XK_Left; break; + case NSRightArrowFunctionKey: k = XK_Right; break; + case NSUpArrowFunctionKey: k = XK_Up; break; + case NSDownArrowFunctionKey: k = XK_Down; break; + case NSPageUpFunctionKey: k = XK_Page_Up; break; + case NSPageDownFunctionKey: k = XK_Page_Down; break; + case NSHomeFunctionKey: k = XK_Home; break; + case NSPrevFunctionKey: k = XK_Prior; break; + case NSNextFunctionKey: k = XK_Next; break; + case NSBeginFunctionKey: k = XK_Begin; break; + case NSEndFunctionKey: k = XK_End; break; + default: + { + const char *s = + [ns cStringUsingEncoding:NSISOLatin1StringEncoding]; + k = (s && *s ? *s : 0); + } + break; + } + } + + if (! k) return YES; // E.g., "KeyRelease XK_Shift_L" + + xe.xkey.keycode = k; + xe.xkey.state = state; + break; + } + default: + NSAssert (0, @"unknown X11 event type: %d", type); + break; + } + + [self lockFocus]; + [self prepareContext]; + BOOL result = xsft->event_cb (xdpy, xwindow, xdata, &xe); + [self unlockFocus]; + return result; +} + + +- (void) mouseDown: (NSEvent *) e +{ + if (! [self doEvent:e type:ButtonPress]) + [super mouseDown:e]; +} + +- (void) mouseUp: (NSEvent *) e +{ + if (! [self doEvent:e type:ButtonRelease]) + [super mouseUp:e]; +} + +- (void) otherMouseDown: (NSEvent *) e +{ + if (! [self doEvent:e type:ButtonPress]) + [super otherMouseDown:e]; +} + +- (void) otherMouseUp: (NSEvent *) e +{ + if (! [self doEvent:e type:ButtonRelease]) + [super otherMouseUp:e]; +} + +- (void) mouseMoved: (NSEvent *) e +{ + if (! [self doEvent:e type:MotionNotify]) + [super mouseMoved:e]; +} + +- (void) mouseDragged: (NSEvent *) e +{ + if (! [self doEvent:e type:MotionNotify]) + [super mouseDragged:e]; +} + +- (void) otherMouseDragged: (NSEvent *) e +{ + if (! [self doEvent:e type:MotionNotify]) + [super otherMouseDragged:e]; +} + +- (void) scrollWheel: (NSEvent *) e +{ + if (! [self doEvent:e type:ButtonPress]) + [super scrollWheel:e]; +} + +- (void) keyDown: (NSEvent *) e +{ + if (! [self doEvent:e type:KeyPress]) + [super keyDown:e]; +} + +- (void) keyUp: (NSEvent *) e +{ + if (! [self doEvent:e type:KeyRelease]) + [super keyUp:e]; +} + +- (void) flagsChanged: (NSEvent *) e +{ + if (! [self doEvent:e type:KeyPress]) + [super flagsChanged:e]; +} + +#else // USE_IPHONE + + +- (void) stopAndClose +{ + if ([self isAnimating]) + [self stopAnimation]; + + /* Need to make the SaverListController be the firstResponder again + so that it can continue to receive its own shake events. I + suppose that this abstraction-breakage means that I'm adding + XScreenSaverView to the UINavigationController wrong... + */ + UIViewController *v = [[self window] rootViewController]; + if ([v isKindOfClass: [UINavigationController class]]) { + UINavigationController *n = (UINavigationController *) v; + [[n topViewController] becomeFirstResponder]; + } + + UIView *fader = [self superview]; // the "backgroundView" view is our parent + [UIView animateWithDuration: 0.5 + animations:^{ fader.alpha = 0.0; } + completion:^(BOOL finished) { + [fader removeFromSuperview]; + fader.alpha = 1.0; + }]; +} + + +- (void) stopAndClose:(Bool)relaunch_p +{ + [self stopAndClose]; + + if (relaunch_p) { // Fake a shake on the SaverListController. + UIViewController *v = [[self window] rootViewController]; + if ([v isKindOfClass: [UINavigationController class]]) { + UINavigationController *n = (UINavigationController *) v; + [[n topViewController] motionEnded: UIEventSubtypeMotionShake + withEvent: nil]; + } + } +} + + +/* Called after the device's orientation has changed. + + Note: we could include a subclass of UIViewController which + contains a shouldAutorotateToInterfaceOrientation method that + returns YES, in which case Core Animation would auto-rotate our + View for us in response to rotation events... but, that interacts + badly with the EAGLContext -- if you introduce Core Animation into + the path, the OpenGL pipeline probably falls back on software + rendering and performance goes to hell. Also, the scaling and + rotation that Core Animation does interacts incorrectly with the GL + context anyway. + + So, we have to hack the rotation animation manually, in the GL world. + + Possibly XScreenSaverView should use Core Animation, and + XScreenSaverGLView should override that. +*/ +- (void)didRotate:(NSNotification *)notification +{ + UIDeviceOrientation current = [[UIDevice currentDevice] orientation]; + + /* If the simulator starts up in the rotated position, sometimes + the UIDevice says we're in Portrait when we're not -- but it + turns out that the UINavigationController knows what's up! + So get it from there. + */ + if (current == UIDeviceOrientationUnknown) { + switch ([[[self window] rootViewController] interfaceOrientation]) { + case UIInterfaceOrientationPortrait: + current = UIDeviceOrientationPortrait; + break; + case UIInterfaceOrientationPortraitUpsideDown: + current = UIDeviceOrientationPortraitUpsideDown; + break; + case UIInterfaceOrientationLandscapeLeft: // It's opposite day + current = UIDeviceOrientationLandscapeRight; + break; + case UIInterfaceOrientationLandscapeRight: + current = UIDeviceOrientationLandscapeLeft; + break; + default: + break; + } + } + + /* On the iPad (but not iPhone 3GS, or the simulator) sometimes we get + an orientation change event with an unknown orientation. Those seem + to always be immediately followed by another orientation change with + a *real* orientation change, so let's try just ignoring those bogus + ones and hoping that the real one comes in shortly... + */ + if (current == UIDeviceOrientationUnknown) + return; + + if (rotation_ratio >= 0) return; // in the midst of rotation animation + if (orientation == current) return; // no change + + // When transitioning to FaceUp or FaceDown, pretend there was no change. + if (current == UIDeviceOrientationFaceUp || + current == UIDeviceOrientationFaceDown) + return; + + new_orientation = current; // current animation target + rotation_ratio = 0; // start animating + rot_start_time = double_time(); + + switch (orientation) { + case UIDeviceOrientationLandscapeLeft: angle_from = 90; break; + case UIDeviceOrientationLandscapeRight: angle_from = 270; break; + case UIDeviceOrientationPortraitUpsideDown: angle_from = 180; break; + default: angle_from = 0; break; + } + + switch (new_orientation) { + case UIDeviceOrientationLandscapeLeft: angle_to = 90; break; + case UIDeviceOrientationLandscapeRight: angle_to = 270; break; + case UIDeviceOrientationPortraitUpsideDown: angle_to = 180; break; + default: angle_to = 0; break; + } + + NSRect ff = [self bounds]; + + switch (orientation) { + case UIDeviceOrientationLandscapeRight: // from landscape + case UIDeviceOrientationLandscapeLeft: + rot_from.width = ff.size.height; + rot_from.height = ff.size.width; + break; + default: // from portrait + rot_from.width = ff.size.width; + rot_from.height = ff.size.height; + break; + } + + switch (new_orientation) { + case UIDeviceOrientationLandscapeRight: // to landscape + case UIDeviceOrientationLandscapeLeft: + rot_to.width = ff.size.height; + rot_to.height = ff.size.width; + break; + default: // to portrait + rot_to.width = ff.size.width; + rot_to.height = ff.size.height; + break; + } + + if (! initted_p) { + // If we've done a rotation but the saver hasn't been initialized yet, + // don't bother going through an X11 resize, but just do it now. + rot_start_time = 0; // dawn of time + [self hackRotation]; + } +} + + +/* I believe we can't use UIGestureRecognizer for tracking touches + because UIPanGestureRecognizer doesn't give us enough detail in its + callbacks. + + Currently we don't handle multi-touches (just the first touch) but + I'm leaving this comment here for future reference: + + In the simulator, multi-touch sequences look like this: + + touchesBegan [touchA, touchB] + touchesEnd [touchA, touchB] + + But on real devices, sometimes you get that, but sometimes you get: + + touchesBegan [touchA, touchB] + touchesEnd [touchB] + touchesEnd [touchA] + + Or even + + touchesBegan [touchA] + touchesBegan [touchB] + touchesEnd [touchA] + touchesEnd [touchB] + + So the only way to properly detect a "pinch" gesture is to remember + the start-point of each touch as it comes in; and the end-point of + each touch as those come in; and only process the gesture once the + number of touchEnds matches the number of touchBegins. + */ + +- (void) rotateMouse:(int)rot x:(int*)x y:(int *)y w:(int)w h:(int)h +{ + CGRect frame = [self bounds]; // Correct aspect ratio and scale. + double s = [self hackedContentScaleFactor]; + *x *= (backbuffer_size.width / frame.size.width) / s; + *y *= (backbuffer_size.height / frame.size.height) / s; +} + + +#if 0 // AudioToolbox/AudioToolbox.h +- (void) beep +{ + // There's no way to play a standard system alert sound! + // We'd have to include our own WAV for that. Eh, fuck it. + AudioServicesPlaySystemSound (kSystemSoundID_Vibrate); +# if TARGET_IPHONE_SIMULATOR + NSLog(@"BEEP"); // The sim doesn't vibrate. +# endif +} +#endif + + +/* We distinguish between taps and drags. + - Drags (down, motion, up) are sent to the saver to handle. + - Single-taps exit the saver. + This means a saver cannot respond to a single-tap. Only a few try to. + */ + +- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event +{ + tap_time = 0; + + if (xsft->event_cb && xwindow) { + double s = [self hackedContentScaleFactor]; + XEvent xe; + memset (&xe, 0, sizeof(xe)); + int i = 0; + // #### 'frame' here or 'bounds'? + int w = s * [self frame].size.width; + int h = s * [self frame].size.height; + for (UITouch *touch in touches) { + CGPoint p = [touch locationInView:self]; + xe.xany.type = ButtonPress; + xe.xbutton.button = i + 1; + xe.xbutton.button = i + 1; + xe.xbutton.x = s * p.x; + xe.xbutton.y = s * p.y; + [self rotateMouse: rot_current_angle + x: &xe.xbutton.x y: &xe.xbutton.y w: w h: h]; + jwxyz_mouse_moved (xdpy, xwindow, xe.xbutton.x, xe.xbutton.y); + + // Ignore return code: don't care whether the hack handled it. + xsft->event_cb (xdpy, xwindow, xdata, &xe); + + // Remember when/where this was, to determine tap versus drag or hold. + tap_time = double_time(); + tap_point = p; + + i++; + break; // No pinches: only look at the first touch. + } + } +} + + +- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event +{ + if (xsft->event_cb && xwindow) { + double s = [self hackedContentScaleFactor]; + XEvent xe; + memset (&xe, 0, sizeof(xe)); + int i = 0; + // #### 'frame' here or 'bounds'? + int w = s * [self frame].size.width; + int h = s * [self frame].size.height; + for (UITouch *touch in touches) { + CGPoint p = [touch locationInView:self]; + + // If the ButtonRelease came less than half a second after ButtonPress, + // and didn't move far, then this was a tap, not a drag or a hold. + // Interpret it as "exit". + // + double dist = sqrt (((p.x - tap_point.x) * (p.x - tap_point.x)) + + ((p.y - tap_point.y) * (p.y - tap_point.y))); + if (tap_time + 0.5 >= double_time() && dist < 20) { + [self stopAndClose]; + return; + } + + xe.xany.type = ButtonRelease; + xe.xbutton.button = i + 1; + xe.xbutton.x = s * p.x; + xe.xbutton.y = s * p.y; + [self rotateMouse: rot_current_angle + x: &xe.xbutton.x y: &xe.xbutton.y w: w h: h]; + jwxyz_mouse_moved (xdpy, xwindow, xe.xbutton.x, xe.xbutton.y); + xsft->event_cb (xdpy, xwindow, xdata, &xe); + i++; + break; // No pinches: only look at the first touch. + } + } +} + + +- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event +{ + if (xsft->event_cb && xwindow) { + double s = [self hackedContentScaleFactor]; + XEvent xe; + memset (&xe, 0, sizeof(xe)); + int i = 0; + // #### 'frame' here or 'bounds'? + int w = s * [self frame].size.width; + int h = s * [self frame].size.height; + for (UITouch *touch in touches) { + CGPoint p = [touch locationInView:self]; + xe.xany.type = MotionNotify; + xe.xmotion.x = s * p.x; + xe.xmotion.y = s * p.y; + [self rotateMouse: rot_current_angle + x: &xe.xbutton.x y: &xe.xbutton.y w: w h: h]; + jwxyz_mouse_moved (xdpy, xwindow, xe.xmotion.x, xe.xmotion.y); + xsft->event_cb (xdpy, xwindow, xdata, &xe); + i++; + break; // No pinches: only look at the first touch. + } + } +} + + +/* We need this to respond to "shake" gestures + */ +- (BOOL)canBecomeFirstResponder +{ + return YES; +} + +- (void)motionBegan:(UIEventSubtype)motion withEvent:(UIEvent *)event +{ +} + + +- (void)motionCancelled:(UIEventSubtype)motion withEvent:(UIEvent *)event +{ +} + +/* Shake means exit and launch a new saver. + */ +- (void)motionEnded:(UIEventSubtype)motion withEvent:(UIEvent *)event +{ + [self stopAndClose:YES]; +} + + +- (void)setScreenLocked:(BOOL)locked +{ + if (screenLocked == locked) return; + screenLocked = locked; + if (locked) { + if ([self isAnimating]) + [self stopAnimation]; + } else { + if (! [self isAnimating]) + [self startAnimation]; + } +} + + +#endif // USE_IPHONE + + +@end + +/* Utility functions... + */ + +static PrefsReader * +get_prefsReader (Display *dpy) +{ + XScreenSaverView *view = jwxyz_window_view (XRootWindow (dpy, 0)); + if (!view) return 0; + return [view prefsReader]; +} + + +char * +get_string_resource (Display *dpy, char *name, char *class) +{ + return [get_prefsReader(dpy) getStringResource:name]; +} + +Bool +get_boolean_resource (Display *dpy, char *name, char *class) +{ + return [get_prefsReader(dpy) getBooleanResource:name]; +} + +int +get_integer_resource (Display *dpy, char *name, char *class) +{ + return [get_prefsReader(dpy) getIntegerResource:name]; +} + +double +get_float_resource (Display *dpy, char *name, char *class) +{ + return [get_prefsReader(dpy) getFloatResource:name]; +} diff --git a/OSX/bindist-DS_Store b/OSX/bindist-DS_Store new file mode 100644 index 0000000000000000000000000000000000000000..726c495cc9ce994f95c2adf17133142b53db3734 GIT binary patch literal 12292 zcmeI0O>Y}T7{~u(r&6jW#m$RURaLb@2v7lUB2^+a7uUEn6-_{`r~;SP_O9)f_a*H5 zg6hvdvB;LJzh!ZG}3XKY+MpdL6>>hnl5&oeL2%rn1P&+Zt2 zstvqt;39x!Cap{7n4KcJU8e;p*qT*pMSmnsS}S$GT{}8i=q(jOKnMr{As_^V!1F+W z?`$p0|MK29t&$4?A@D*H(C350q;=KmvC;X_!7RT5P%p7M7uqFlP&-yvtsWcA7K$>i z)W%iWD~2-etaog`s?}qojXRXRd?-7!vNsf!&(86kygO9YXvu|u5LhH&?(XH<`?u=N zaQ6QG=V$6k;U_vMlyAR#|AS_dg!;F~;+=a>72Bg=%lek^t-4uwZRwN!FdMR~7CN*? z*(glnPF}V(!*141QWicpeS%gev7=1>Y|uY#dIzoHq~#LrYj_wZvENMkk)1&wKQ=VB z_szIivEFfe;{7^s{7!M-MgbI0=49#ecauiW%Oy-a@6g^ZqU6PmXjy0YTB*bCqYQTo zD(enYe5_QIcpknfs7BWE@N)sZAolQ=QemSR!c%BPQD428LouVzMS2*t`i4O9st$uW z54n{aUNDH9181webA1w>)yEqrzwW+)Gc2xM@S;ww(du>5WDtAh!zt}KpZ_SXbG%+`$Z8?$Ivl9OLag1lNS%PD5~Q2yPyNdrAmchjM{Uu4z?2ojS?; zf9^Svq7ZmC0!7p9qCP!t@?gExaR!Z^pv&hk3fg%A(Ix}Z)|k# z!Yuzzq|RT*)ch_qLfg?6b=B&z(X64!9|1WA$%KFq5CTF#2nYcoAOwVf5D)@FKnMr{ MAs_^V!2e3%Z#WzrGXMYp literal 0 HcmV?d00001 diff --git a/OSX/bindist.rtf b/OSX/bindist.rtf new file mode 100644 index 00000000..718e9a54 --- /dev/null +++ b/OSX/bindist.rtf @@ -0,0 +1,71 @@ +{\rtf1\mac\ansicpg10000\cocoartf824\cocoasubrtf330 +\readonlydoc1{\fonttbl\f0\fswiss\fcharset77 Arial-BoldMT;\f1\fswiss\fcharset77 ArialMT;} +{\colortbl;\red255\green255\blue255;\red0\green0\blue240;} +{\info +{\title XScreenSaver Installation Instructions}}\vieww10380\viewh13000\viewkind0 +\deftab360 +\pard\pardeftab360\qc +\ +\b\fs36 +XScreenSaver\ +\b0\fs28 + +\b A collection of free screen savers for MacOS X\ +\ +\b0 +by Jamie Zawinski\ +and many others\ +\ +version 5.20\ +06-Oct-2012\ +\ +{\field{\*\fldinst{HYPERLINK "http://www.jwz.org/xscreensaver/"}}{\fldrslt \cf2 \ul \ulc2 http://www.jwz.org/xscreensaver/}} +\ +\pard +\b To Install:\ +\b0\li360 +\ +Simply double-click each of the savers you want to install.\ +\ +To install \i all \i0 of them, drag all of the .saver +files to the "Screen Savers" folder in your "Library" folder. +You may need to create the "Screen Savers" folder first.\ +\ +\pard +\b When upgrading:\ +\b0\li360 +\ +If you selected \i "Install for all users" \i0 last time, make sure +you do that again this time, or you will have both the new and old +versions of the screen savers installed. That can be confusing!\ +\ +That is, be careful not to end up with copies in "/Library/Screen Savers/"\ + as well as in +"/Users/ +\i \ul YourName\ulnone\i0 +/Library/Screen Savers/".\ +\ +\pard +\b To Uninstall:\ +\b0\li360 +\ +Open the "Screen Savers" folder and drag any unwanted savers to Trash.\ +\ +\pard +\b For More Information:\ +\b0\li360 +\ +Please visit the +{\field{\*\fldinst{HYPERLINK "http://www.jwz.org/xscreensaver/"}} +{\fldrslt \cf2 \ul \ulc2 XScreenSaver web site}}. +The XScreenSaver collection is free software, and all source code is +available there.\ +\ +\pard +\b iPhone and iPad:\ +\b0\li360 +\ +XScreenSaver also runs on iOS! It is available in the +{\field{\*\fldinst{HYPERLINK "http://itunes.apple.com/app/xscreensaver/id539014593?mt=8"}} +{\fldrslt \cf2 \ul \ulc2 iTunes App Store}}, and it's free! +} diff --git a/OSX/build-fntable.pl b/OSX/build-fntable.pl new file mode 100755 index 00000000..f5e3b1f3 --- /dev/null +++ b/OSX/build-fntable.pl @@ -0,0 +1,113 @@ +#!/usr/bin/perl -w +# Copyright © 2012 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. +# +# Generates a .h file that lists all the function tables we use, because +# CFBundleGetDataPointerForName doesn't work in "Archive" builds. +# What a crock of shit. +# +# There's no real way to integrate this into the Xcode build system, so +# run this manually each time a new saver is added to the iOS app. +# +# Created: 14-Jul-2012. + +require 5; +#use diagnostics; # Fails on some MacOS 10.5 systems +use strict; + +my $progname = $0; $progname =~ s@.*/@@g; +my $version = q{ $Revision: 1.1 $ }; $version =~ s/^[^0-9]+([0-9.]+).*$/$1/; + +my $verbose = 1; + +sub build_h($$) { + my ($app_dir, $outfile) = @_; + + opendir (my $dh, $app_dir) || error ("$app_dir: $!"); + print STDERR "$progname: scanning $app_dir...\n" if ($verbose > 1); + + my @names = (); + foreach (sort (readdir ($dh))) { + next unless (m/^(.*)\.xml$/); + push @names, $1; + } + closedir $dh; + + my $suf = 'xscreensaver_function_table'; + + my $body = "extern struct $suf"; + foreach my $s (@names) { + $body .= "\n *${s}_${suf},"; + } + $body =~ s/,\s*$/;/s; + + $body .= ("\n\n" . + "static NSDictionary *make_function_tables_dict(void)\n{\n" . + " return\n [NSDictionary dictionaryWithObjectsAndKeys:\n"); + foreach my $s (@names) { + $body .= "\t[NSValue valueWithPointer:&${s}_${suf}], @\"${s}\",\n"; + } + $body .= ("\tnil];\n" . + "}\n"); + + my $obody = ''; + if (open (my $in, '<', $outfile)) { + local $/ = undef; # read entire file + $obody = <$in>; + close $in; + } + + if ($obody eq $body) { + print STDERR "$progname: $outfile: unchanged\n" if ($verbose > 1); + } else { + my $file_tmp = "$outfile.tmp"; + open (my $out, '>', $file_tmp) || error ("$file_tmp: $!"); + print $out $body || error ("$file_tmp: $!"); + close $out || error ("$file_tmp: $!"); + + if (!rename ("$file_tmp", "$outfile")) { + unlink "$file_tmp"; + error ("mv \"$file_tmp\" \"$outfile\": $!"); + } + print STDERR "$progname: wrote $outfile\n" if ($verbose); + } +} + + +sub error($) { + my ($err) = @_; + print STDERR "$progname: $err\n"; + exit 1; +} + +sub usage() { + print STDERR "usage: $progname [--verbose] program.app output.h\n"; + exit 1; +} + +sub main() { + + my ($app, $out); + while ($_ = $ARGV[0]) { + shift @ARGV; + if (m/^--?verbose$/s) { $verbose++; } + elsif (m/^-v+$/) { $verbose += length($_)-1; } + elsif (m/^--?q(uiet)?$/s) { $verbose = 0; } + elsif (m/^-/s) { usage(); } + elsif (! $app) { $app = $_; } + elsif (! $out) { $out = $_; } + else { usage(); } + } + usage() unless ($out && $app); + build_h ($app, $out); +} + +main(); +exit 0; diff --git a/OSX/iSaverRunner.ai b/OSX/iSaverRunner.ai new file mode 100644 index 00000000..a91e23c9 --- /dev/null +++ b/OSX/iSaverRunner.ai @@ -0,0 +1,3593 @@ +%PDF-1.5 %âãÏÓ +1 0 obj <>/OCGs[18 0 R 93 0 R]>>/Type/Catalog>> endobj 108 0 obj <>stream + + + + + application/pdf + + + iSaverRunner + + + + + Adobe Illustrator CS3 + 2012-06-04T14:04:08-07:00 + 2012-06-04T14:30:53-07:00 + 2012-06-04T14:30:53-07:00 + + + + 244 + 256 + JPEG + /9j/4AAQSkZJRgABAgEASABIAAD/7QAsUGhvdG9zaG9wIDMuMAA4QklNA+0AAAAAABAASAAAAAEA AQBIAAAAAQAB/+4ADkFkb2JlAGTAAAAAAf/bAIQABgQEBAUEBgUFBgkGBQYJCwgGBggLDAoKCwoK DBAMDAwMDAwQDA4PEA8ODBMTFBQTExwbGxscHx8fHx8fHx8fHwEHBwcNDA0YEBAYGhURFRofHx8f Hx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8f/8AAEQgBAAD0AwER AAIRAQMRAf/EAaIAAAAHAQEBAQEAAAAAAAAAAAQFAwIGAQAHCAkKCwEAAgIDAQEBAQEAAAAAAAAA AQACAwQFBgcICQoLEAACAQMDAgQCBgcDBAIGAnMBAgMRBAAFIRIxQVEGE2EicYEUMpGhBxWxQiPB UtHhMxZi8CRygvElQzRTkqKyY3PCNUQnk6OzNhdUZHTD0uIIJoMJChgZhJRFRqS0VtNVKBry4/PE 1OT0ZXWFlaW1xdXl9WZ2hpamtsbW5vY3R1dnd4eXp7fH1+f3OEhYaHiImKi4yNjo+Ck5SVlpeYmZ qbnJ2en5KjpKWmp6ipqqusra6voRAAICAQIDBQUEBQYECAMDbQEAAhEDBCESMUEFURNhIgZxgZEy obHwFMHR4SNCFVJicvEzJDRDghaSUyWiY7LCB3PSNeJEgxdUkwgJChgZJjZFGidkdFU38qOzwygp 0+PzhJSktMTU5PRldYWVpbXF1eX1RlZmdoaWprbG1ub2R1dnd4eXp7fH1+f3OEhYaHiImKi4yNjo +DlJWWl5iZmpucnZ6fkqOkpaanqKmqq6ytrq+v/aAAwDAQACEQMRAD8AG56I+cOxV2KuxV2KuxV2 KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KvRfyZ/46eo/8YE/4nmh7 d+iPvd/2B9cvc9XzmXqHzHnoj5w7FXYq7FXYq7FXYq7FXYq7FUNd6jZ2s1vDcSiKS7cxW3IHi0gU tw5UoCQNgTv2yueSMSATz5NkMUpAkC+Hmlfk7zE+uaSZblUh1K1lkttQtkrSOWNiNgSTQjfKNHqP FhZ2kDRHm363TeFOhvEiwfJPcy3EdirsVdirsVdirsVdirsVdirsVdirsVdirsVdirsVei/kz/x0 9R/4wJ/xPND279Efe7/sD65e56vnMvUPmPPRHzh2KuxV2KuxV2KuxV2KuxV2KpN5w0Ma15eurJV5 XAAmtd6Umi+JN+1SOJPgcxNbp/FxGPXp73N7P1Pg5ozP03v7uryfQ9d1bQfNX6XIa50zUYRNekfa kiUDnLxHWWIfG/8AsjsDtyWj7VOPLxS6mpfr/HX3vedt+zvDjAx74yOLGfL+afd1+b263uIbiCO4 gcSQzKHikU1DKwqCD7jO2jISFjkXziUTE0eYX5Ji7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7 FXov5M/8dPUf+MCf8TzQ9u/RH3u/7A+uXuer5zL1D5jz0R84dirsVdirsVdirsVdirsVdirsVeZ6 ppixapqOngmIwzi7spQASguP3gYA7UEhkXidiBTpnnfben8PUSFemW/zfevYvLHtDsvwZ/VjNeY/ mn7/AIbLvI3mFtIvxol7+60+4lKWe5K21y3xegCd/Sl3aEn3Xcg023YPadHwZn+qfx+L94fPPars KWGZmBRH1frHl3eXmC9KzrniHYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq9F/Jn/AI6eo/8A GBP+J5oe3foj73f9gfXL3PV85l6h8x56I+cOxV2KuxV2KuxV2KuxV2KuxV2KsM85QiLX7C5HS6t5 YJPnCyyR/hJJnJe0+L6J/B9U/wCBfqzHPkxdJRv4/wBjG9ZsYZoWlkjaSMIUuY0+20NeVU/4siYc 4/cU6Mc5ME9NiOXv/UeRfS/aDswajFxAXKI+ceo945j5dWY+TNenuo5NI1GVZdVsFRvrC/ZuraQA w3UfiHUjl4HPQOxe0xqsW/1x5/j73557a7MOly7fRLl+PuZNm5dM7FUgk876HGurysz/AFXReKXN zQem0rVrFGa/E6kAH3OYZ12McZ6Q5nz7g5o0GT0DrPkPLvKbaXfG/wBOtr0wvb/WI1kEMtA6hhUB qE5kYp8cRKqtxssOCRjd0icsa3Yq7FXYq7FXYq7FXYq7FXYq7FXov5M/8dPUf+MCf8TzQ9u/RH3u /wCwPrl7nq+cy9Q+Y89EfOHYq7FXYq7FXYq7FXYq7FXYq7FWL+fVpBpMg6rfcfoe3mBH30OaD2jF 6f8Azh+l7j/geT4e1I/1ZfckWcG/Q6jHHPb6TJq9kK3/AJRn9QoOsuk3dXkhPj6b+oUr9kDLNFrj pNZGX8OTn7xt9or4vlntR2PGccmMfw+qP9WW/wBkr+D0i3niuII54W5xSqrxuOhVhUH7s9VjIEWH xSUSDR5hjfnzzC+maY1tbOUvblHYuv2ooIxWWUe9PhT/ACiPDNX2vrvAx0PrlsP1vQeznZH5zPcv 7rGOKfuG7z3TrEanrmieU4UppNhI1zqrDdJruNQ86nxWMsIRmrwxE8kNOPphvLzPX9Tm6nIYwnqT tKe0PKPSv909pzqnkXYq7FXYq7FXYq7FXYq7FXYq7FXYq9F/Jn/jp6j/AMYE/wCJ5oe3foj73f8A YH1y9z1fOZeofMeeiPnDsVdirsVdirsVdirsVdirsVdirFvPkgKaTAPtPeGQj/Jjt5an/gmXOf8A aSYGnA75Pdf8DvEZdpxPQRl9yR5wj9CrFe7TQJobZuN/52lTT7BSK8NPtw/rXJHgyyvT2IODTaU6 vWQxjlj3P9Y/qr7C+Y+0na0YwyZukhwx/qxvf/OJNe8PQYIrXT7COJSIrW0iCAsdljiWm59lGesx AhGugH3PiJMpyvnKR+95Zrj6hrMN1ewr/puqywW1hG+3CF51jgQ16V58292Oed9odoeLnOQ/TG69 wfdezOwzoexpCv3uXhv/ADpAAfayjy7oFppXnW6sLYlk0XS7W0aQ9XluZHuJJG/ynYVzP9jpHKJ5 pc5H8f7l8+9sAMXBiHID8fezLO4eIdirsVdirsVdirsVdirsVdirsVdir0X8mf8Ajp6j/wAYE/4n mh7d+iPvd/2B9cvc9XzmXqHzHnoj5w7FXYq7FXYq7FXYq7FXYq7FXYqwHXr9dR8xyNGeVtpiG1Rh uGnkIaen+rxRfnyzh/aLVieQQHKH3vtX/Az7Jljxz1Mh9fpj7lCDTZtY1G20aElfrhJupF2MdrHQ zMCOhIIRT/Mwzl8+cYoGZ6cvf0/W9521qTHGMcT6sm3uj/Ef0e8p3oHpaz5m1DXo1VdMsB+idCjU URYYNppEA2o77KfAUzr/AGQ7OOLD4svrn+Px8Xwr2u7R8XL4Ufpj+P2/Jd58vSbO30dD8epMfrFO 1rFQy/8ABkrH8mObXt7V+Fg4R9U9vh1R7E9j/nddHiF48fqkx8sqXOnudljv7F2/1Uu4mP4DPPco uEv6svuL7z20P8GP9aH+7iyiwr/ysXzdy3JXTSp8F+rsAP8AggxzqPYevyx/HWT4X7bX+Yj+OkWQ Z2zxTsVdirsVdirsVdirsVdirsVdirsVei/kz/x09R/4wJ/xPND279Efe7/sD65e56vnMvUPmPPR Hzh2KuxV2KuxV2KuxV2KuxV2KsY81+YponOkaY/G/dQ1zcjcW0TdD4GRx9gdvtHtXR9sdqjTx4Y/ 3h+x7D2S9l59pZrlthjzPf5BjtvbxW8CQRLxjQUUdT8yT1J7nOClIk2X6J0+CGGAxwFRiKCNtrif SvJmp6/BX9K69Iul6GBUEKzGJGXwLN6kte4C5gSxnU6uGEco7n3/AIofN4LtntEAZM97fTH3Dr8d 5e6mXaHpMGkaRaabB/d2sSx16ciB8TH3Zqk57HgxDHARHQPhGfMckzM9SwrUbo33mLUbvrHAwsbf /Vgr6h+mZmH0DOF7f1PiagjpHZ92/wCBx2Z4OiOYj1ZT9g/H2IPVVlbTbn0v75Y2eL/XQcl/4YZp Y1e723aWMz0+SI58Jr39GVw3UbfmNdSxH9xrOj2l/ER0Ijdox8zRxm69h51CeM8wT9n9r4X7bY7l CY6/p/sZJnfvBOxV2KuxV2KuxV2KuxV2KuxV2KuxV6L+TP8Ax09R/wCMCf8AE80Pbv0R97v+wPrl 7nq+cy9Q+Y89EfOHYq7FXYq7FXYq7FXYqkUfnPRGu9Thd2ih0pOdxdsP3RoSrhCCWPBhxO252Fcw o6/EZTjf93zLsMnZmaOPHMjbL9KprPmS3s9BTU7Wk73ioNNQ1HqvMOUfWhA4/E3goOOr1scWHxel bed8mfZvZeXVamOniPUTR8u9htrA0SMZHMtxKxluZ2+1JI27Mf4DsNs83z5pZZmUuZfpvsrs3Fos EcOMbR+0962+E7W5htzS5uWS2tz4STuIkP0M4yniA3PIb/Jl2pnOLTykPqqh75ekfeyrXLW3k86e XtAt142Hl+xa99LtyNLa3B90ClhmX7FaY5c0s0uf4/X9j477Z6nw8McUfx+K+1PNQvI7KwubyT+7 tonmf/VjUsf1Z6bkmIRMj0FvmmLGZyER1NPONMikisIFlNZioeZvGR/ic/SxOeV5ZmUjI9S/VvZe lGDTY8YFcMR8+v2onK3PX2d4YE8o6gx2066ufLt5/qSqGswfYIEP05nez2bwdfKPTJR+ex/2T4v7 X6E/lzHrikR8BvH/AGL0LPTXyh2KuxV2KuxV2KuxV2KuxV2KuxV2KvRfyZ/46eo/8YE/4nmh7d+i Pvd/2B9cvc9XzmXqHzHnoj5w7FXYq7FUi86+YW0Dy7c6kih5UosSnpyc8R+JzXdp6o4cVx+omnY9 l6UZstS+kC3gF351803U7TS6lMHbsjcB9wpnHyyykbJJL2UcUYigAAo/4r8y/wDVzuP+RjYOI97L hHcidN1zzVf30NnFqVxzmYLX1G2Hc9ew3yMshAu3K0WjOfLHHEbyP4+S/wA33jR6jJp1tIy2kEUd uyBtn9P4/i8SHY9e+VYL4b73a+0RgNT4cPpxREB8Of2ksg8hDUL1Hvb24knitv3NmjsSqGg5FQel FoMq1WQ7Rd57G6AEyzkcvSP0/jzLMcwnv19nw/Tejc/sfX7evhXl8P8Aw1Mp1P8AdTr+aXTdt/3I /rxYl+cmr6nZfmNfm0uZID6NulYzxPH0g1NvdjmR2JtpxXefvfMu2N85vuH3MRtNe169uobOfUJ5 Ibh1jkRnJDKxoQR75tZzNFxNHhjPNCNc5Afa9YzUPuLsVUfqLX8Oq6EhIk1i2E2nkbEahYfvYwD2 MsYpXwXKM8vDlDL/ADDR/qy/V+l432j0XFIkf5SP+yjuPmP9y8oPmrzKCQdSuQR1HqNm/wCI975v wDud/ivzL/1c7j/kY2HiPevCO53+K/Mv/VzuP+RjY8R714R3O/xX5l/6udx/yMbHiPevCO53+K/M v/VzuP8AkY2PEe9eEdzv8V+Zf+rncf8AIxseI968I7nf4r8y/wDVzuP+RjY8R714R3Mp8gfmLrlr rVtZX1w91ZXUgiKvuys5oCD7nbfMvR66eGYN+nqHD1mhhmgRQ4uhe8527wzsVdirsVei/kz/AMdP Uf8AjAn/ABPND279Efe7/sD65e56vnMvUPmPPRHzh2KuxV2KsH/OT/lCp/8AjLF/xMZpO3P7of1n edg/3p/q/pfP+cs9W7FWa/lzpy87nU5R8EQ9KM+5FXP0LT78xdTLkHt/Y/Ri555co7D7z8h96Qa9 YzwraX1xtPqySXoQ9o2meNf+CMbH5UyeHIJEgco7fZf6Xk9YTKfiS55Ll8yXonk+2Fv5ds1/adTI x8ebEj8KZiZjci+p+z2Hw9FjHeL+Z/UnOVO6UbyOd4OVuwW5iZJrZz0E0LCSMn/ZqMaB2PI7OH2h pvHwygOfT3jcfaGN/nRFFqF5pXmu0Ui01e2EcoPWO5tyVkjfwZQQv+xOR7HJgJYZc4H7C+V9rwuQ yfzhR8iOYYHorhNYsXPRJ42/4Fwc20/pLidmy4dTjPdOJ+17Nmrfa3YqpXIuVVJ7Rgl7ayLcWjHo JYzyUH/Jb7LexOJiJAxPI7OD2jpTnwmI+rnH+sOXz5HyLAvzK0aGHVYddsIymk6+pu4Af91T1pcw N/lRyV2y7s7KTE45fXj2+HQ/EPkvaODhnxAVGe/uPUfAsOzYuvdirsVdirsVdiqY+XP+Uh0v/mLg /wCTq4q+p89EfOHYq7FXYq9F/Jn/AI6eo/8AGBP+J5oe3foj73f9gfXL3PV85l6h8x56I+cOxV2K uxVg/wCcn/KFT/8AGWL/AImM0nbn90P6zvOwf70/1f0vn/OWerbAqaYq9V06xOneUTDTjKLaSR69 eboW3+XTNdKXFP4vrOk0p03Zpj/F4cifeQT9nJEfmN5C8xa95o0bSPK+my6jLaaDAwt4aFxDDM8Z c1I2BkQfTmP2LPihMnmZk/c+edrw4ZwA5cA/Sr6LDPb6XBbXMbQ3NsDBPEwoySRMY3UjxDKRl2Ue ovpvYmQS0eMj+b92yOyt2rsVQGoW1pJY3enX546NqBEksoFTZ3aikd2o/kP2ZgP2d+xyEokSGSH1 x/2Q/m/q83kfaDsoGJyD6JfV/RP8/wDRL597BtJ/LDz5qmrXmm6RpMt/facVNzFblGZVb7Ei1ILI 3VWGxzbYssckRKPIvnU4Sxzo8w9DtJZJbaN5EMUxFJomBVkkXZ0YHoVYEHNdKNGn2nRakZ8Mcg/i F/r+1VyLlOxVCy6dZ6jbXHl2/cRWWqyCXTrtulrqVKKT4R3A+Fv8r3bKcplCQzR5x+od8f1j8cni /aDswWZfwZD/AKWff7pff72AaT+V3n7WNRvtO0vRpry+01gl7bxFC8dfssVLA8W/Zboc3OLLHJES ibBfPsmOUJGMhRCbf8qB/OT/AKlO+/4Ff+assYO/5UD+cn/Up33/AAK/81Yq035B/nIqlj5Tv6AV NEUnbwAauKsEuLe4triW2uYnhuIXaOaGRSjo6GjKymhBBFCDiqniqY+XP+Uh0v8A5i4P+Tq4q+p8 9EfOHYq7FXYq9F/Jn/jp6j/xgT/ieaHt36I+93/YH1y9z1fOZeofMeeiPnDsVdirsVYP+cn/AChU /wDxli/4mM0nbn90P6zvOwf70/1f0vn/ADlnq0w0Cx+vazaWxAZXkBdT3Rfib/hQchklUSXYdlaX x9TDH0Mt/cNz9j166h9a2mh/34jJ/wAEKZrAaL7Hnx8eOUf5wI+b0f8ALzWFt/zB/LnWnNItZ0+f S7qQnpJLbpPEu/czRFcxuxzw5cuPul+v9j5R2sOLHjn5fj9KT/mz5fbQPzK1q2C8bbU3Gr2Z8Vuy TP8ASLlZD8iM2OpjRt6z2P1nHgliPOBse4/t+9iuYz2DsVcQCKHcHqMUKOlajrHl3WbDUdHuRaah Ytw0i7f+6Cufi0+83HK1m6ISf3beAoVMZnGTMcv4h/vh59/f73ge3+wxD1Q+jp/RPcf6J6fzTtyT fzNqGmapqbeZNNgayg1mZ11jSn+3p+tKOVzbtsKpOAZo2/aPPpSgycwEgJx3BZeyfaJhI6We3WPv 6j9Pz70uzFe9diqyeCGeF4ZkDxSAq6HoQcINNeXFHJExkLieaY6FqGurfLe6VePb+eNFhMul3tdt SskIL2d2vSUrsu++6t1qcxRlOlmJD+5kdx/NPePL8dz572x2SYyMDvKrgf5w/mnzH6j3vrXyH5w0 /wA4+UdM8yWAKQahFzaI/ajlUlJYj7pIrL9GdA8an2KuxV+en/ORyIn52eagqhQbiI0Apu1vESfp JxV5tiqY+XP+Uh0v/mLg/wCTq4q+p89EfOHYq7FXYq9F/Jn/AI6eo/8AGBP+J5oe3foj73f9gfXL 3PV85l6h8x56I+cOxV2KuxVg/wCcn/KFT/8AGWL/AImM0nbn90P6zvOwf70/1f0vn/OWerZZ+XNr 6msSzkVWCI0PgzED9VcxtSfTT1vsfg4tTKf82P2nb7rej5gvpaP0+a9k8lXcWnmms+UL+PV9MG5N I5DdRmny9WMD2zAlLwdXGf8ADkFH7v1F887X0m2TH/NlxR9x3/XH4PZfzqsLLzj+WmkfmDo49Q6b Ct/RfiZtOu1X60hp3hosp8ODDvnRZYcUadB2Jr/yupjM/Sdpe4/q5/B4WCCAQag9DmsfYQbdil2K rZYo5onilUPG4Kuh3BB6g4QaYZMcZxMZC4nmgLyG6ksbySJ2fUbCBTej7TXenRMDFcUqOVxYyBd6 jkmzEhiDHFkGKfCf7vJ/sZfql975x2t2fPTZeKB9UPVE98R+mPI94oq+mX8d9ZR3KEfEKOF3AYbG nt4HuMsnHhNPe9na2Opwxyx68/I9UVkHNdiqlM91BJDf2VPr9jIJ7WuwZlBDRn/JkUlG9jgnATiY y5Sdd2ppDmxHh+uPqj7+748ntf8Azjr5jtoPMuveW4GP6M1iGPzPoanbitxSK8jp24y8TwHTfMjs 3ITi4ZfVA8J+H7HybtHGI5bH0z9Q+P7XvebBwXYq/Pb/AJyR/wDJ2+af+M8P/UNFirzTFUx8uf8A KQ6X/wAxcH/J1cVfU+eiPnDsVdirsVei/kz/AMdPUf8AjAn/ABPND279Efe7/sD65e56vnMvUPmP PRHzh2KuxV2KsH/OT/lCp/8AjLF/xMZpO3P7of1nedg/3p/q/pfP+cs9Wz78s4aW99L3do1HyUN/ XMPVHcPoHsVjqGSXeY/ZbNcxHuFbSdWXRNct9Uk2s3H1TUvAQSMCspH/ABU+5/yS2Y2s0/i4zEfU Nx+r4/fToO29PQGYfw7S/qnr/mn7CXs/5D6xFpWo61+WGp8Xsh6mo+W0kAKSWFyx+sWwB2PoyMdu 4Ynpmx7N1XjYgf4hsff+18z1+m8HKR0O4eS+a/LEvlPzVqXlpw3o2Lh9OkfcyWM1Wt2qftcQDEx7 shwZ4cMve+j+zHaP5jTCJ+vHt8Oh/R8Esyh6R2KuxVTe8bTrm21dByOnyepKgFeduw43EdO/KMmg 8QMhlxeJAw7/AL+n2un7a0/Hh4x9WP1fD+IfL7QEsOnxeXPN99okTV0+7pd6W1RxaGVS6cN6tQK6 E/5AyeDN42ETP1DaXv8Ax97z3s7n8DUy0/8ABP1R/Hu/3Kb4vcuxV2Kpj+XmuN5f8+eWrwtwisdV FlJ2X6jritGeX+TFdIX9qjLNOeHN/Xj9sf2H7HzH2l0nhZDXK+Ie6fP5SB+YfaGbN5V2Kvz2/wCc kf8Aydvmn/jPD/1DRYq80xVMfLn/ACkOl/8AMXB/ydXFX1Pnoj5w7FXYq7FXov5M/wDHT1H/AIwJ /wATzQ9u/RH3u/7A+uXuer5zL1D5jz0R84dirsVdirB/zk/5Qqf/AIyxf8TGaTtz+6H9Z3nYP96f 6v6Xz/nLPVvQ/wAtpFOm3UY+0soJ/wBkv9mYWq5h9G9jJDwJjul+j9jMMxXsmnRXUo4DKwIZTuCD 1BwsZRBFHkUdo+o6t6VlHp0nHzb5Vf695anav+lWqbS2b/zfu/3bD9peJ/mzE4vy2bxB/dz2l5Hv /Hn5PnvbHZZjeLu3ge8fzfeP1HvepfmqdM8//lvo/wCZ+gpWbTUI1ODrIlpIwW6ikA/atZgJN+ih yPtZvMsOKLpewu0PyupEj9B9Mvcf1c3kGa19edirsVcQCCCKg9Rigi0n1O01a4fSIQFki0uQLbXn LjKtmWBa2kB+2q8f3bA1HQjvhxQjEyI/j5jz7/1vIZOws0NTjnjo44SB8xG94+fl9venGB7B2Kux VKPMMcn1eR4m4PJBLEHGxDxgXcJH+V61sqj/AFskDRB7iP1H7C8n7V6bixCfdY/3w+2NfF9x+VNb j17yvpGtx04anZW92AO3rxLJT6OWbV8zTXFX57f85I/+Tt80/wDGeH/qGixV5piqY+XP+Uh0v/mL g/5Orir6nz0R84dirsVdir0X8mf+OnqP/GBP+J5oe3foj73f9gfXL3PV85l6h8x56I+cOxV2KuxV g/5yf8oVP/xli/4mM0nbn90P6zvOwf70/wBX9L5/zlnq2W/l1qKwanLZuaC6Sqf68dSB/wACTmNq Y2L7nr/Y/WCGeWI/5QfbH9lvRswX0l2KqU0UrGOWCU293buJbW5X7Uci9G9x2YdxtiQCCCLBcPXa OOox8J2PMHuPf+vvDOPyk89WekeZ5bLUYkj8secZPqGvacx/c2eryoVWUBj/AHF6m1fHqfhpluhm YfupG6+k98f1jkXyvtbRyx5CSKN1Idx7x5S5hieo6NNoOsaloEzMz6PdS2au/wBp4kNYHPu8DI30 45o1J9F9ntZ4+kiT9UfSfh+ylDKnduxV2KuxV2KuxV2KoPViEsJJynP6sVueH83oMJafTwphAvbv 2+brO2MXHpZ+Q4v9L6v0Pp7/AJxt1Frn8pNMs5X53GjzXemTH/mGuHEY/wCRRTNnjlxRB7w+OTjw yI7np+TYvz2/5yR/8nb5p/4zw/8AUNFirzTFUx8uf8pDpf8AzFwf8nVxV9T56I+cOxV2KuxV6L+T P/HT1H/jAn/E80Pbv0R97v8AsD65e56vnMvUPmPPRHzh2KuxV2KsH/OT/lCp/wDjLF/xMZpO3P7o f1nedg/3p/q/pfP+cs9WrWl1La3UVzEaSQsHU+6muCQsU3afPLFkjOP1RNvZdPvYb6yhu4T+7mUM B4HuD7g7Zq5Ro0+06TUxz4o5I8pC/wBnw5IjIuS7FUv1WCH0pXm2tbmI218f5Y2PKKf5283GT5ch 3xIOxH1RNj9I+I2ea9o9AMmLxAPpFS/q9/8Amnf3WmmpeZ4/MmrrqUhb9MSadYr5gRwQ66jbiS0l 5e7paxvtXZhmTqCDUh1dd7GTkI5YH+Ex+2/1KeYz2zsVdirsVdirsVdiqyaNZYnjb7LqVPyIphBY ZICUTE9RT2b/AJxG1B/0N5k0lz8UNxZamwoPtalZIXp/s4GzP08rj7iR8iQ+I6mJE9/I/MPfsvaH 57f85I/+Tt80/wDGeH/qGixV5piqY+XP+Uh0v/mLg/5Orir6nz0R84dirsVdir0X8mf+OnqP/GBP +J5oe3foj73f9gfXL3PV85l6h8x56I+cOxV2KuxVg/5yf8oVP/xli/4mM0nbn90P6zvOwf70/wBX 9L5/zlnq3Yqzr8utUmCTWMoJt+Y9GTssjhjwr/lLGxHyOYmpx/xPceyHafDI6eR57x9/Ufp+fezn MN9AdirTKrKVYAqRQg7gg4UEAiihbLTLazklkiLFpQiEueVEiBEaA9aKDQV7bdAMJLgaLs3FpjI4 79dfZyHwtF5F2DsVdirsVdirsVdirsVejf8AOM1x9T89NaV4x6v5cjuR4NJZXrQgD3EcwzI0M7Mx 3T/QHxrtSFZAR1H6S+m8z3WPz2/5yR/8nb5p/wCM8P8A1DRYq80xVMfLn/KQ6X/zFwf8nVxV9T56 I+cOxV2KuxV6L+TP/HT1H/jAn/E80Pbv0R97v+wPrl7nq+cy9Q+Y89EfOHYq7FXYqwf85P8AlCp/ +MsX/Exmk7c/uh/Wd52D/en+r+l8/wCcs9W7FXvP/OK/lHTfN0nnPQb+qRXWnQ+jcKKvBMk3KKZP 8qNwG9+h2OAi2ePJKEhKJojdq907U9K1K80bVohBqunSGC7jFeJNKpLHXcxyoQ6HwPjmtyQ4TT7B 2P2lHWYBMfUNpDz/AFHopZW7V2KuxV2KuxV2KuxV2KuxV2KqF7cG3tJZgpd0UlEG5ZzsqgeLNQYQ N3G1eoGHFLIf4R/YPiXpn5XWc1t+bfk/S9ORrqXQtIubfzHPGKxwRy26+h6jdmknTZPA16ZV2OZS OTIR6Zy2+18o7W4RwQv1RG/2PpzN26d+e3/OSP8A5O3zT/xnh/6hosVeaYqmPlz/AJSHS/8AmLg/ 5Orir6nz0R84dirsVdir0X8mf+OnqP8AxgT/AInmh7d+iPvd/wBgfXL3PV85l6h8x56I+cOxV2Ku xVg/5yf8oVP/AMZYv+JjNJ25/dD+s7zsH+9P9X9L5/zlnq3Yq+kP+cJLq2Tzl5htnkVZ5tPRoYia MwjmHMqO/HkK4q9w/PH8rZfM1gnmDQ4gfM2lxlfQFB9dtQSzWxP+/FJLQk/tVU7MSK8mPiFO17I7 Uno8wmN4n6h3j9fc+b4ZkmjDpUA1BVgVZWBoysp3DKRQg9M1xBBovrun1EM0BOBuMl+RbnYq7FXY q7FXYq7FXYq7FUHbNqep+aNP0XQ7f69rDSqbO2/YNyByjeU9orcfvnPsvicn4ByDh6Hn7uvz5fN4 r2n7WECMUeY3Pv8A4R8Pq/0r6/8Ayy/LvTvI3lxdOhf61qdy31nWNUcfvbq6fd5GPXiOiL2HvU5s oxEQAOQfPpSMjZ5ll2SYvzx/5yJube4/OnzVJBIssYukjLoQRzjgjR1qO6upB98Vec4qmPlz/lId L/5i4P8Ak6uKvqfPRHzh2KuxV2KvRfyZ/wCOnqP/ABgT/ieaHt36I+93/YH1y9z1fOZeofMeeiPn DsVdirsVYP8AnJ/yhU//ABli/wCJjNJ25/dD+s7zsH+9P9X9L5/zlnq3Yqr2V9e2N1Hd2NxJa3UR rFcQu0ciGlKq6kMNj2xVOf8AlYXn7/qZdV/6Trn/AJrxVU0Dzlf2eoyzahPLeRXb87p5WMkhc9ZO TEkt4165TlxcQ83oOwu25aOdS3xS5ju8x+N3pdvcQ3EKTwOJIpByR16EZryKfVMOaOSInA3E8iqY Gx2KuxV2KuxV2KuxVJvMvmKDR7StQ13KCII+tP8AKYeA/HLcWMyLpO2+2I6PH35JfSP0ny+95tae Yddsr176x1C5s7uQFXuLeZ4pCrHkVLIVNC25HjmxEQHybLllkkZSNko//lYXn7/qZdV/6Trn/mvC 1tH8wfPrAg+ZdVIOxBvbihH/AAeKpCSSSSak7knrXFWsVTHy5/ykOl/8xcH/ACdXFX1Pnoj5w7FX Yq7FXov5M/8AHT1H/jAn/E80Pbv0R97v+wPrl7nq+cy9Q+Y89EfOHYq7FXYqwf8AOME+SbggbCWK p/56DNJ25/dD+s7zsH+9P9X9L5/zlnq3Yq7FXYq7FU98tearrR5PTYGayc1eGu4/yk8D+vKcuES9 7vuxu3cmjPCfViPMfpH43el6bqthqUAms5RIv7S9GU+DDtmDKBjzfTtFr8OphxY5X9494ReQcx2K uxV2KuxVjvmHzjZ6dG0dsRcXfQU3RT03PcjwH00y/HhMubzPa/tJi0wMcfryfYPf+ofGnm17e3N7 cvcXLmSVzVmOZ0YgCg+aanUzzTM5m5FD5JodirsVdirsVTLy2CfMWl0/5a4P+Ti4q+ps9EfOHYq7 FXYq9F/Jn/jp6j/xgT/ieaHt36I+93/YH1y9z1fOZeofMeeiPnDsVdirsVQGu6NZ6zpc+nXYrDOt CR1B7Ee4zF1emGbGYFytHqjgyCY/AeR3P5G6yszC3vY5If2WYUNPffObl2NnB2o/F6aPbWAjex8F L/lR/mH/AJaYf8/pyP8AI+fuHzZfyzp+8/J3/Kj/ADD/AMtMP+f04/yPn7h81/lnT95+Tv8AlR/m H/lph/z+nH+R8/cPmv8ALOn7z8nf8qP8w/8ALTD/AJ/Tj/I+fuHzX+WdP3n5O/5Uf5h/5aYf8/px /kfP3D5r/LOn7z8lW2/JvzXaSia3v0hkX9tCVNPobBLsbORuB827B7Q48UuLHKUZeVpTN531TSr+ ewuvS1AWzGNplBiZmH2htUbHb7OaSWmHR73Se2GogKyRE/8AYn7NvsR0X5k6UVBmtp0bwTi/6ymU nSy73c4/bPTkeqEx7qP6Qj7DznpV/MIbZW9Q9BNJb24/4OeWJPxyvJiMBZ+wE/cC5Mfa3Sy2An/s R98gySbStbhsfr94LLS7E7i6vruPie/wCATBz7BswPzuMy4Y8U5dwH66ZZvaAiNiAA75SH6Lv5vP /MvnCxo1tp9zJqLdGuGQ21sP9SGrSyfOV+P+RmxwYZneQ4fLmfny+XzeR7S9oc2a4iW3l6Y/rPxN eSQ+XdDufMmq/UluViuWTlGZOjcSBxHSmx2zZ4cRlIRjzLzGbMIRM5cgy7/lR/mH/lph/wA/pzY/ yPn7h83W/wAs6fvPyd/yo/zD/wAtMP8An9OP8j5+4fNf5Z0/efk7/lR/mH/lph/z+nH+R8/cPmv8 s6fvPyd/yo/zD/y0w/5/Tj/I+fuHzX+WdP3n5O/5Uf5h/wCWmH/P6cf5Hz9w+a/yzp+8/J3/ACo/ zD/y0w/5/Tj/ACPn7h81/lnT95+TI/Jf5QnStSj1HVLhZ5ITWGBR8IPSpNTX/P6MvSdjTExLJVDo 4es7agYGOO7PXuem50rzLsVdirsVei/kz/x09R/4wJ/xPND279Efe7/sD65e56vnMvUPmPPRHzh2 KuxV2KuxV2KuxV2KuxV2KuxVhX5k+ebfQdMe1t3DancqViTY8Qdizew/z9tH2trxGJxx+o8/J3vZ HZ5lIZJfSOXmXz8zM7F2JZmJLMdySe+cu9UtxV2Kt8jQCuw3A+eKtYqidN1C506/gvbZuM8Dh0Py 6g07EbHCDW4QQCKL6S8oebNP8x6XHc27gTqAJ4SfiVgN87Ls/XDPGj9Y5/reL7R0BwSsfQeX6k9z YutdirsVdirsVdirsVdirsVdir0X8mf+OnqP/GBP+J5oe3foj73f9gfXL3PV85l6h8x56I+cOxV2 KuxV2KuxV2KuxV2KoLV9a03SLQ3eoTCGEftHufAZi6nV48AuZ5uVpdHkzmoDk8x80fnZGUe30CEl jUfW5QQB7quzffTNBqu2Zz2gOEd/X9j0Ok7EhDfIeI93T9rym9vbu9uXuruVpp5DV5G6n/PwzSEu 8AUMVdirsVdirsVdiqYaLrup6LereafMYpR9ofssPBh3yUJmJsGixnASFSFgvXPLn51aVcosWsxm 0nAoZVBaMn6Nx9Ob7TduEbZBfmP1PP6nsIHfEa8j+t6PbXMF1Ak8DiSKQVRx0Izf4c0ckRKJsF5/ NhlikYyFEKuWtTsVdirsVdirsVdirsVei/kz/wAdPUf+MCf8TzQ9u/RH3u/7A+uXuer5zL1D5jz0 R84dirsVdirsVdirsVdirsVQWq6NpmrQCDUbdLmFTyCOKivjmNqNJjzVxi6cnTavJhJ4DVpV/wAq 78l/9WmD/gRmL/JGn7vtLl/yxqP532B3/Ku/Jf8A1aYP+BGP8kafu+0r/LGo/nfYHf8AKu/Jf/Vp g/4EY/yRp+77Sv8ALGo/nfYHf8q78l/9WmD/AIEY/wAkafu+0r/LGo/nfYHf8q78l/8AVpg/4EY/ yRp+77Sv8saj+d9gd/yrvyX/ANWmD/gRj/JGn7vtK/yxqP532B3/ACrvyX/1aYP+BGP8kafu+0r/ ACxqP532B3/Ku/Jf/Vpg/wCBGP8AJGn7vtK/yxqP532B3/Ku/Jf/AFaYP+BGP8kafu+0r/LGo/nf YHf8q78l/wDVpg/4EY/yRp+77Sv8saj+d9gT21tLe0t0t7aMRQxjiiLsAB2GZ2HDHHHhiKDgZs0s suKRsquWtTsVdirsVdirsVdirsVei/kz/wAdPUf+MCf8TzQ9u/RH3u/7A+uXuer5zL1D5jz0R84d irsVdirsVdirsVdirsVdirsVdirsVdirsVdirsVdirsVdirsVdirsVdirsVdirsVdirsVei/kz/x 09R/4wJ/xPND279Efe7/ALA+uXuer5zL1Dyj/lTOp/8AVxg/4B86b+XYfzS8v/IE/wCcHf8AKmdT /wCrjB/wD4/y7D+aV/kCf84O/wCVM6n/ANXGD/gHx/l2H80r/IE/5wd/ypnU/wDq4wf8A+P8uw/m lf5An/ODv+VM6n/1cYP+AfH+XYfzSv8AIE/5wd/ypnU/+rjB/wAA+P8ALsP5pX+QJ/zg7/lTOp/9 XGD/AIB8f5dh/NK/yBP+cHf8qZ1P/q4wf8A+P8uw/mlf5An/ADg7/lTOp/8AVxg/4B8f5dh/NK/y BP8AnB3/ACpnU/8Aq4wf8A+P8uw/mlf5An/ODv8AlTOp/wDVxg/4B8f5dh/NK/yBP+cHf8qZ1P8A 6uMH/APj/LsP5pX+QJ/zg7/lTOp/9XGD/gHx/l2H80r/ACBP+cHf8qZ1P/q4wf8AAPj/AC7D+aV/ kCf84O/5Uzqf/Vxg/wCAfH+XYfzSv8gT/nB3/KmdT/6uMH/APj/LsP5pX+QJ/wA4O/5Uzqf/AFcY P+AfH+XYfzSv8gT/AJwd/wAqZ1P/AKuMH/APj/LsP5pX+QJ/zg7/AJUzqf8A1cYP+AfH+XYfzSv8 gT/nB3/KmdT/AOrjB/wD4/y7D+aV/kCf84O/5Uzqf/Vxg/4B8f5dh/NK/wAgT/nB3/KmdT/6uMH/ AAD4/wAuw/mlf5An/ODv+VM6n/1cYP8AgHx/l2H80r/IE/5wd/ypnU/+rjB/wD4/y7D+aV/kCf8A ODv+VM6n/wBXGD/gHx/l2H80r/IE/wCcHf8AKmdT/wCrjB/wD4/y7D+aV/kCf84O/wCVM6n/ANXG D/gHx/l2H80r/IE/5wd/ypnU/wDq4wf8A+P8uw/mlf5An/ODv+VM6n/1cYP+AfH+XYfzSv8AIE/5 wZN5G8jXflu7up57qOcTxqgCKRShr3zXdo9oxzxAAqnZdndnS08iSbtmOap2zsVdirsVdirsVdir sVdirsVdirsVdirsVdirsVdirsVdirsVdirsVdirsVdirsVdirsVdirsVdirsVdirsVdirsVdirs VdirsVdirsVdirsVdirsVdirsVdirsVdirsVdirsVdirsVdirsVdirsVdirsVdir/9k= + + + + + + uuid:82D8E573DAAFE111BF0B8F740ADF4EE3 + uuid:8ccac4a0-f819-bd4b-9966-e33d3f17e366 + + uuid:b1ac9fe8-11a3-4422-b8f3-ae4b8085b7a8 + uuid:5D20892493BFDB11914A8590D31508C8 + + + + Document + Print + + + 1 + False + False + + 114.000000 + 114.000000 + Pixels + + + + Cyan + Magenta + Yellow + Black + PANTONE 485 CVC + PANTONE 152 CVC + + + + + + Default Swatch Group + 0 + + + + White + RGB + PROCESS + 255 + 255 + 255 + + + Black + RGB + PROCESS + 35 + 31 + 32 + + + CMYK Red + RGB + PROCESS + 236 + 28 + 36 + + + CMYK Yellow + RGB + PROCESS + 255 + 241 + 0 + + + CMYK Green + RGB + PROCESS + 0 + 165 + 81 + + + CMYK Cyan + RGB + PROCESS + 0 + 173 + 238 + + + CMYK Blue + RGB + PROCESS + 46 + 49 + 145 + + + CMYK Magenta + RGB + PROCESS + 235 + 0 + 139 + + + C=15 M=100 Y=90 K=10 + RGB + PROCESS + 190 + 30 + 45 + + + C=0 M=90 Y=85 K=0 + RGB + PROCESS + 238 + 64 + 54 + + + C=0 M=80 Y=95 K=0 + RGB + PROCESS + 240 + 90 + 40 + + + C=0 M=50 Y=100 K=0 + RGB + PROCESS + 246 + 146 + 30 + + + C=0 M=35 Y=85 K=0 + RGB + PROCESS + 250 + 175 + 64 + + + C=5 M=0 Y=90 K=0 + RGB + PROCESS + 249 + 236 + 49 + + + C=20 M=0 Y=100 K=0 + RGB + PROCESS + 214 + 222 + 35 + + + C=50 M=0 Y=100 K=0 + RGB + PROCESS + 139 + 197 + 63 + + + C=75 M=0 Y=100 K=0 + RGB + PROCESS + 55 + 179 + 74 + + + C=85 M=10 Y=100 K=10 + RGB + PROCESS + 0 + 147 + 69 + + + C=90 M=30 Y=95 K=30 + RGB + PROCESS + 0 + 104 + 56 + + + C=75 M=0 Y=75 K=0 + RGB + PROCESS + 41 + 180 + 115 + + + C=80 M=10 Y=45 K=0 + RGB + PROCESS + 0 + 166 + 156 + + + C=70 M=15 Y=0 K=0 + RGB + PROCESS + 38 + 169 + 224 + + + C=85 M=50 Y=0 K=0 + RGB + PROCESS + 27 + 117 + 187 + + + C=100 M=95 Y=5 K=0 + RGB + PROCESS + 43 + 56 + 143 + + + C=100 M=100 Y=25 K=25 + RGB + PROCESS + 38 + 34 + 97 + + + C=75 M=100 Y=0 K=0 + RGB + PROCESS + 101 + 45 + 144 + + + C=50 M=100 Y=0 K=0 + RGB + PROCESS + 144 + 39 + 142 + + + C=35 M=100 Y=35 K=10 + RGB + PROCESS + 158 + 31 + 99 + + + C=10 M=100 Y=50 K=0 + RGB + PROCESS + 217 + 28 + 92 + + + C=0 M=95 Y=20 K=0 + RGB + PROCESS + 236 + 41 + 123 + + + C=25 M=25 Y=40 K=0 + RGB + PROCESS + 193 + 180 + 154 + + + C=40 M=45 Y=50 K=5 + RGB + PROCESS + 154 + 132 + 121 + + + C=50 M=50 Y=60 K=25 + RGB + PROCESS + 113 + 101 + 88 + + + C=55 M=60 Y=65 K=40 + RGB + PROCESS + 90 + 74 + 66 + + + C=25 M=40 Y=65 K=0 + RGB + PROCESS + 195 + 153 + 107 + + + C=30 M=50 Y=75 K=10 + RGB + PROCESS + 168 + 124 + 79 + + + C=35 M=60 Y=80 K=25 + RGB + PROCESS + 138 + 93 + 59 + + + C=40 M=65 Y=90 K=35 + RGB + PROCESS + 117 + 76 + 40 + + + C=40 M=70 Y=100 K=50 + RGB + PROCESS + 96 + 56 + 19 + + + C=50 M=70 Y=80 K=70 + RGB + PROCESS + 59 + 35 + 20 + + + PANTONE 485 CVC + SPOT + 100.000000 + CMYK + 0.000000 + 100.000000 + 91.000000 + 0.000000 + + + PANTONE 152 CVC + SPOT + 100.000000 + CMYK + 0.000000 + 51.000000 + 100.000000 + 0.000000 + + + + + + Print Color Group + 1 + + + + C=0 M=30 Y=70 K=0 + RGB + PROCESS + 252 + 186 + 99 + + + C=5 M=70 Y=90 K=0 + RGB + PROCESS + 231 + 110 + 52 + + + C=5 M=90 Y=75 K=0 + RGB + PROCESS + 228 + 64 + 68 + + + C=30 M=0 Y=95 K=0 + RGB + PROCESS + 190 + 214 + 58 + + + C=60 M=5 Y=95 K=0 + RGB + PROCESS + 116 + 182 + 74 + + + C=30 M=0 Y=10 K=0 + RGB + PROCESS + 174 + 222 + 228 + + + C=60 M=10 Y=5 K=0 + RGB + PROCESS + 87 + 182 + 221 + + + C=80 M=5 Y=10 K=0 + RGB + PROCESS + 0 + 176 + 216 + + + + + + Grayscale + 1 + + + + K=100 + GRAY + PROCESS + 255 + + + K=90 + GRAY + PROCESS + 229 + + + K=80 + GRAY + PROCESS + 203 + + + K=70 + GRAY + PROCESS + 178 + + + K=60 + GRAY + PROCESS + 152 + + + K=50 + GRAY + PROCESS + 127 + + + K=40 + GRAY + PROCESS + 101 + + + K=30 + GRAY + PROCESS + 76 + + + K=20 + GRAY + PROCESS + 50 + + + K=10 + GRAY + PROCESS + 25 + + + K=5 + GRAY + PROCESS + 12 + + + + + + + + + Adobe PDF library 8.00 + + + + + + + + + + + + + + + + + + + + + + + + + endstream endobj 2 0 obj <> endobj 18 0 obj <> endobj 93 0 obj <> endobj 94 0 obj [/View/Design] endobj 95 0 obj <>>> endobj 19 0 obj [/View/Design] endobj 20 0 obj <>>> endobj 92 0 obj [93 0 R] endobj 5 0 obj <>/ArtBox[0.0 0.0 114.0 114.0]/Group 73 0 R/MediaBox[0.0 0.0 114.0 114.0]/Thumb 107 0 R/TrimBox[0.0 0.0 114.0 114.0]/Resources<>/Properties<>/ExtGState<>>>/Type/Page/LastModified(D:20120604143053-07'00')>> endobj 103 0 obj <>stream +H‰ì—KŽ$5†÷y +_ Ü¿½¥@#!5õ‚”xõŒ4´šÛóývVV °F jѕi§Ï/Âî§oÏîéùÜ_žÝöt~ îò悷lü֘ù՜{»|؞Þñù§·-¸àÌòüûõ‡íÇíãv›8í³ß»saX{?:›s#ù̵âCÉ]ÞÏeï·S3ßSáý•÷äKk¼ŸZö£Äúlv&o%ºËvL”è;â^ïf²¯ ƒvY§R}ÈÅ]õ\ÇÈȼõzÌ #7f´fx |É÷ŠŒ}ÊR|-‰aö9V‰`&Õ~̼Ιn嘑p“Œ[·»qñqzr7QKw7X¥ç¡bÙaÅ·t[ñ:g¢|¿î1b!åW™wã¥ô˜Ø­:ìV*OµbŒ{O£yS°öàÄä{­·ØÅÌø>Þá.Òæ[¶c¬¬¦#s×ÑÊìeÛÇ+õ¯×ácÉYÀ]@ò»-øìÞñ[Üï.»g÷@ðà?ˆàÏÛ 2ëìÏ°7SAxð©Ýá$iÚ"‡šùÈw¼ai¶v³âT:o‘òº4;„íÃ0·®÷y,Dö‰ì“)`KR"äq¸«¦}ÈþeÊ>V²§¡û8\ń«…Aµ8–óË÷rþfK”åÿ4&a6˜‘1¹$u, ÍÅêkÅä#"°ŸTðÙ\÷]]£úÎQƒï¢}xú¬âk•¯>w—Úì 5™Yسk¤ÖÑXBQæ±°ã^~‡”fmÊæe‹4%™ñ1)£¹Â–ž¦¥©»ÚÑ'7IeÆqzaˆÉ˜ÖA³4œuä ZJZËކa”q©8¢òu1‚BÖ£S]<†¬E§>bâؐp"vq +=…ˆ× 4Obrò±WÑä2 ˆš:®VŽÙ‚ øc"`8G01»ã)öÒÄ3ўþö͐Ì.lîѱOÔ ÛêjèF! Õf‡°ŒaDõ‚°“|Y<ðQ‘N³áE2 D”Fd—­#¸U<¤Z`#ëצ…(Âõ´2DJ†65ˆ8H&™UÌЁ•}Âg$2?¨å“¤LsëÓ eŸ0“§Ò&å•(FGöˆÞHÎäÏÜAMwŽZs¿ð÷µ{àüÀù?‰óћãß÷f® +bŒ<•Â=ã€9ûG§Ìt–p]E +ޓڀ™ÐÜCNx9'ÝPºŽ G$‹ ÇDp&˯¡ØPó˜›4§Å3|鄉’ÉlÀ #…hlhçœëÂÙE/y•SA?8&lì•ô"ä {±´¾ª¤RLW +€»TÃbåh&ÇI0«TE[Dü“u“ëdy(¥#O0â<©`¾á\äÁ™JU“ʲJ7CB%pc,ž;i¯Â\5ß¹%ÂlÆâOÔV4“w] ÑQ¨`tÑo¶©¾¡¹Ï&3™{d"Ì& šHp@s+oºvâ®+cS™…~õ\ÔbºÐª‚v`U, óC³¸ m³)´É¬Ú–Rj A€qz„©UŽ¶–æE7¨ èÊ%EÞ×¼˜ÕZ¿‹ÓO{ÛÕ8õóÿp„>ýWº:éWÏgÇã‹„ endstream endobj 73 0 obj <> endobj 107 0 obj <>stream +8;T`p_%?Z%#Qh!kGhIauV3no3/gB endstream endobj 96 0 obj <> endobj 97 0 obj [/ICCBased 98 0 R] endobj 99 0 obj [/Separation/PANTONE#20152#20CVC 100 0 R<>] endobj 102 0 obj [/Separation/PANTONE#20485#20CVC 100 0 R<>] endobj 100 0 obj [/ICCBased 101 0 R] endobj 101 0 obj <>stream +H‰””uTÔKÇtKˆ”ˆKJI,‚t(݋»4ìKÇÒÝ%Ò¹´H—4J#‚Ò’‚(H +w¹÷þqÏyïyßó~Ï3çù̙gÎ<3ó̄Y9El +@¸ ]äÕ!OÔÌ-@ãÀà\€ˆ¹¥+BVKK Àè:øOX×~òþ¿ÿWCa®–iHKL€…À0qÍY¦–Ë `ø5àcü€Âæk–Ë +XŠ]¶x=†äß ðš8¯ÙÚÜ üX€„Ŀ׽ƒ>Ÿ.Èf’‡›#aP§®¡¦Èünæ óD^{y8ÂËÅÖÚ  €d¡p H×Ë stå©:Yò€Äô׬cxc IŽVÈ?SÂÅ!þ:óè_úÃÆî¼9[ÂYbQ’PÒ~²+rA +SÊhª¦›«·HhÀ´†t^ôé ·'0±ß…€Â™kYæX¯ØY9îYq†q•p÷ólÝ'äãäW°Œ£…z„EÎÅèÄE$´%D>,–ê‘^|t*K)Ç%/§`¢è¦¯\¦Ò«úùñ‰•:¯†¼&D ®¦“¥[«7¨¿dplDa5–|ªmbõÌÓ4Ê,óy•y‡Å{Ëe辶5• «­œ½Žƒ©£µ“3Üìã’âš…,t+w¯ñhòl÷êõðõóõA  ö½ î é m k +¯‹xYU“›H„&%«¥È¤ +¥q¼ O'M¿zù3ãKæTÖ@v[NUnn^\¾o]¡a‘b±Tr£ä¢t»lºümE]e~Uü+¿jûאåZÑ:¶zª a·q®i ¹¡¥°5¡Íÿ};¤C¹S¤‹¥›¢û²ç[ï\_ÿۆw…ý‰þƒCa…¾Qº1¬±÷ŸÆ;>”L$Lz}4ÿ¤:%8M7Ìl̎ÎÕΧ/ø}¶XT^â]¦X>\™Ym[Ëùâ³n¸!´ycsk«ûkƶóŽÊ·;ßöv{¿§ýpßÓßúIþsû ÷0ëÈõXõ„éäàôݯÔ3ós®ó‹’ß&—$—õWÆWW˜*ØÂ)ÁãÅ!è$Ü$Æ%¡!e$cºÁHNOAKIMEq“„—úâÖÍí ÝýÃâíƕ;KLów§@˜‡YúX;ؚÙë8^Ý+çDspçñäðfßÏàKåOˆÅTC˜P°p J%†’D=ðè+å+íûÈO%$*©«˜¤”®œ¡’©šý8÷I¡Z½\£Z³^«U»K§_wLï“þ´Á¬á¼Ñ"dÙxíé¦Éö³]Ó}³£ç§æ–†»²º°>³9µ=²;°ßsøî¸ã´_G¬8/ºÌ¹N!GÝzÝ[<ª=‹½2½|B}½ýàþP”Q€z lH0Wc(EèeØnø|ÄPds::5&8Ö9îy¼F‚T"oÒídâ䳔¯©³iƒ/ZÓK^&gd:fg«äˆæ²çQçãælÎ ·£kJÐ¥™e‰åá¨J*ø+ëê篍kôj5ëÔêU”›š[”ZUÚ¿Ñh×é0ì|ÖeÙm×ãÒëÓò6ê]BÚ@ö`ñPÕpãHçèÀØÄû…ñûçñ?QM1MsψÍ*Ìiϛ.ØöZ [JYÎZ)X-]«úR»Þ¸ÑºÙ¾ÕõµwûãÎú·£ï¸?¨ö@û¼?Åä5Ž ǖ'v§N¿àgçÐ ƒß +—üW´×÷‡3ƒgƒÿŽŸL¬C#u!ó¼áMîMáMéEåvAms˔F‡V‘NŒž‹Aø¶£ÌGL’w…A¼Ì¬,ô¬äl¸l¿Ø¿s¬Ý›ááêænä©àͽŸÌÎï+€„‚!Bê²"¢¢ 'R&k?¾ÿ´3?Ã4+:§6o¾€ü¾˜¾T²\·Ò±Ú¿6úåÃúÄÆøæÈVß×ÖíʝÌoá»ðïF?LöžîüT;:ä>¢::>ž:©;ýeqÆvx^saõ›òwÝ¥úåʕóŸï'_E˜F”O\D’KšLtAnF¡F)FÅ|“èæõÔ­6š\Ú`º@z?äm+Fý;²L¼wiAh›y’¥͖Àîͽ§Á)ÁÅÎMÁý›g›wú~_ Ž@Œ ØZH_XA,Ê"F)Ž%¾/±*9ù ïaƒZ:ýQ”ŒŸ,\ÎB^_AUñ¡’€2« +­*‰êÕãƒ'[j êão5[´ª´óuR1uà­ïh`f¨m$1æxJgBdrölÇtÁläy»y¥E¦e$Ôfe¥g-g#`ËdGbwj¿î0áØáTOC9;¸¸Ê ¹Ü¨ÜÎÝ¿xŒz6zåx‡ù8ùøIû³£ÈP‡ó=A¥Á±!.¡†aÂAxۑü÷ϊ³‹˜Œ}bŽG-ø‘Þ’Ä“ª”‘•x–`—G˜/™ššê›Ôœ¿ªž–Ÿƒ q¡_¢O£?¤0¥"¦§§ý¨ó©êªâ«Û¬Õ­Ð®Ë¯Ç°Ä±Â²Á³Á´ÂµÅ¶È·Í¸Ó¹Ûºã»í¼ø¾¿À Á0Â@ÃRÄfÅzƏǦȾÉÖÊñÌ Í*ÎGÏcЀџҿÓàÕÖ'×LØsٛÚÄÛïÝÞFßsà¡áÏãäMå™æçè6é†êØì+í€î×ð1ñòïôMõª÷øZù«úöü:ý{þ»ÿÿÿ€€å´ÍTÌ?¥~òŒ”~i˜ž~L}ãÁ~cbAþ~’Da€dþ€ü¸~t‹yä~W‰²ÊÛ~Oˆ±>~\†´—/~‚…›|“~¾„º`éƒôC–ƒx¢€äƒßú£}%—âH}”1ÉX}%‘z¯Î}K•Ö}† {N}׋<_´~7‰‰AË~Àˆ-ψø¿|¢°à‚|žÉDz|+›®E|[—£”s|«”¦z} ‘æ^•}wO@¶}ÿ-Œ~ċÉ÷ {G®uÞÚ{D©zÆ{]¤Ä¬Ò{– f“{êœZxÚ|[˜»]ˆ|ϕM?¹}R’‹<}Ǝðõ…zªº]ÝYzŸ´Hħz³®‹«|zð©=‘â{L¤Nw²{ÀŸº\‹|=›>Ó|¼˜v|ېIô8z/ÆrÜ z¿;Ãbz'¸sªMzd²6ßzɬqvÒ{D§[®{À¢0> |;Ÿ| óyÑÒÈÚñy´ÊaÂIy¸Â©?yð»açzY´ÎvzÝ®Æ[{^©‡=c{ФÓI{Rò*yŒß„ÙýyfÕÓÁUy`Ìî¨Vy”Äâyþ½’uKz†·Zi{ ±Ü<Ú{z©%žzȎíí‰~+Ö~ˆ}±¾Í‡}W¦µ†0}3Ž…„}HtЄü}ŒZk„›}è=Ž„Ÿ~‹‹†z€ëɇ®‰Ն£‡}½…¹†!¥~„ø…ŒÐ„d„*s}ƒôƒˆYƒ¨ƒ<9ƒ¸‚àù…w„éû†p“øÓS…w‘u¼„œ¤ƒõ‹‰ƒu‹VrUƒ‰ÕWÿ‚؈|;,‚뇔ˆ„{‡¨èR…sžøѲ„ƒ›ºƒ²˜;¢¡ƒ•:Š8‚ ’¡q)‚PCV÷‚Ž:4‚.Œ–8ƒ‰ŠÉæȄªªÐ2ƒ»¥­¹‚ñ¡‚¡?‚U¤ˆîãšp £–çVu“ÿ9S†’ ‚šŒçåc„ µbÎփ°·µ‚Rªê ¹¦.‡ÕN¡Æný ¼U€ãš38‰€ó˜8¼ŒAä/ƒ‹ÀÚͬ‚œº‚¶’Î´zžô6®ß†è€Ó©°n1€“¤íT\€e Ø7݀tžXT‹·ã)ƒ$̯̕‚6Å;µ˜e¾Cž€Ê·Ë† €i±Ýmw€3¬Sƀ¨V7M€ +£\®€l‹GâN‚ÐØ»ËځæÐN´ÄÈa5€tÁ…N€ºzlÕß´ÍS<º°H6Ѽ¥*ôŠîÝ<’a|˜Çkz|C±VŽ²|šÇ|ƒ—‹·|IkžŠ‚|±Ru‰ˆ}26Ž‰'~2‹ÖÞÛF‘-†ËƏB…„°*ƒ„o™²‹üƒ‚ƒŠ­‚òjŒ‰‚ˆQ^ˆ£‚@5zˆI‚`Š˜ƒ†Ù³‘$ĝŽ"Ží®ýŒcŒß˜€Šñ‹&U‰³‰²ijˆ¦ˆ|PJ‡Ë‡v4v‡y‡ú‰V†»ØG›’Ã.2˜{­‹†•——Š’ý€ˆè¾hS‡æŽ¼O[‡Œÿ3†ÂŒˆ(‰„ÖéŽJ¦Áьx¢&¬$ŠÔžs•Ò‰h› +~æˆ2—êgK‡>•-N}†o’Ì2ن‘Á N‡%ˆÿÕ§±°ÇÀ›‹â¬ªöŠ>§w”´ˆÖ£A}⇤Ÿ\fX†§›ÚMµ…ݘù2,…Š—ò ¨†KˆÔ3»¥¿’‹g¶©ò‰Â°¦“¾ˆ[«¤} +‡0§ež†6¢çM …_Ÿ¯1… ? …—ˆ1Ó£ŒËÆǾ³‹ÀI©‰^º’ç‡ô´I|B†Ì¯dö…ܪwL‡…§e1$„¢¡: ®…‡æÒàŒrÒW½ûŠ°Êñ¨]‰ Ãá’1‡£½S{†z·|di…‹²ÇL „½®g0·„\ ð U„Ž‡©Ìû›ò{[¸“™G{!£ö–¸{ ŽÞ”`{&y’E{xbie{ùJrŽÚ|“/cŽ5}~ +~ÀË:šâ„ý·f˜#ƒç£•™‚üú“M‚Kx+‘CØa|ušI~÷.yWã ώ›ƒÉәߎ­¶—%ŒÂ¡å”˜ŠøŒá’[‰‰w!^ˆT`ƒŽž‡^H˜*† -§ŒŒ† 5G…èȨ˜ç˜Ž´ã–=•Î §“½“4‹»‘rív†Žÿ_ÒRG±Œf‹û,ދ̋ͯŒ…ßÇ|˜,¢†³Æ•„žúŸ{“ ›¬Š„Ò˜ªtìŽÙ•ô^1“ Fî‹Å‘Ä,;‹'‘¾<‹!…‘Æ_—›¬¥²²”õ¨Yžl’~¤J‰„J tŽS#]¸Œš'FA‹4—÷+®Š”—;ۊL…PÅf—&¶ì±É”€±Þ‰’­ˆªÕ¨šs@å¤]Œ0¡E±Š´žÓ+:Š›ÈևSS 𧠨ŒêjVPp,<XQ)‚XVl€(Js•&ÂJ!ÒûK{é½@B€ÐEŠ. œe°íÙWqQ䆓³â½ý~3ßÌ7ßÌçF£HI^ý\¨¯§¬ÁïÓ¡ƒåœ+j&YÅöÉbƒdMLÅÑÅ{#©©úè÷)Fø£ÛAŠ;q²ïT0Œ±_à ^¿£9IݤšxÖº¶Æ¢YFh“9ՅÆhX;Jõ²Æl¬ äÀín+jÅÄ¡®(Ým,Ö¼Jƒî(Va÷V/ÀÈÄaؑ”@ÈQ~.æ8_]±Èš7]ñÕÕÌÃãõÚgÕ|ÓFÕ) -—/ªºMH—|­Š¼øP´œ8™%èoFxàCÿ­<÷ªR×l® AÒ^«™ ÷QÊlÚÁzÙrJAUžUÿá™ÿd*ÿùüîNî$iÜÉ #Ÿv b7FÚ*4ނ÷ú¯ + Ëû§pv€iâx֖¼÷ŒÁIªão¥‡ìžËÝJÛ±á#ç +í¾ËW—àh…Ô‰Šlý"ùkx wVjGá“Dzˆ–ç*¸ÇߜxŸWÁŠ:Æ©d¿ÙPÀîæ$¹üЍjÀ4W·Mž¨[ÎÝ,]¢Ê«$ˆ–ÈWæî$I×&®åNˆ¬‘}ì7¨ sØþ»‹1@À9‡TɎ.íEÙÓzN¾Dfº*uwr þ„úØ ˆ *ª#Øùòë­,¥h؅Ãð"ä8=”³NÍ ¡%ƒ=(‰p¤â…QuÃ9søLӓ(î&Ãâˆwì¥Ú¾õ?±‚ER AHi.RÚ~ ԄË6õ ØÑâ¿:Ò*tД3*»–¿Û±ôx#ç‰m?r~3×û2ÿ+Êwù‰¾šp¸ÞÇ6‹yXaœTOÃ#Œã +U‹Â¼<·_)ÂIø(»Œ}¹ÓW2SÎX U€àwü õ¦ M¨–f›_T‰)•úà“Ÿ?k–YYF…ôK8ãÁu;J$óÀþ*1T…>,ë#h›%TÓ,…QÛ¥{[ëõsˆ:˜ü9󅼓¼&^!Փ˜a£â@Ò!ßÍ" yð +µ´.—÷Jl6mçHj†uÁ,béU6£+s©ì ýhܸdœ-Ê¥ª}…wiÀ-s´un=0ŠÄ½äi-_ˆ*)UÞâ_ˈ“âÚãb$ôöna+;ϧTø;pçpA7Û¨¾¨CÈ4åÏ.*·Iߥ›a‡8õ°MÌæm.‚þôACiü“€7»\j|fi³¹Õœ¹•Ô«)Ö÷]Þ­°jö¤À¡Ê„ÃÑâUò]¡3(íž ðwhöJÐÛcÉh-®4x7–“öh׿*P0¿H됎L‡žŠ®ëž‡Ú¡uê‰Õ¾°…Å×Ú,Ë{ÏBz}§…8¦v¶gÊgŸÒ²¤d[û!XTZçZ.ø·vlµA°¿g­Ñ +{;SÂm¶`vâîØ¿`~È?g¥a.œ +3žÃŒì{§­Çæ†L¨^–»¡¦ÔÅåW€ƒ¹¾ÍY¥eÆ4õ‚]¸Lû7oÞðýák˜õ¦ö!w·™™ð«Iý~»Ir»a^=¥Cë#ZÀ»hçÓ`Wï‡u}p¨Ãçê)¸À"®zœ7ff&²3© ’ß$ß©ôF’ø‘ÓÒJ8Ò¶5ãùÞmµ +u´®Râ_,^V¹àS&åaR´~PfÄÜLL_Dw¸ž*Ž‹`\Í-¦9]qîõ®¯¡ ¦Ý Â–Çô¹T¸Ií6)ÿ>u6 DÝ`eÍ¢/»–¢xq¶Y%¤9ÖÛʜ¼;«Ã¥Oêd\˾ÊP…&eRËzïç;¡]¥¹‹é.íRµ<oªÊΡù]öP{?¯:¦ r̨\˜µÝÊ»b õÒ¤â3|ª×íâm ¨s¢ØŸîÛÖW°9¢¨ñµæoZt]Rn“ÏÅ\½c…Wö#+…n•I&õgϽØÝy¸œAjsÑN‹06”HiD­±¸È'@ÿ¥ðõJ+¦ša5V~€cRˆIµõÌ«ïvwtUÓc[3+?F|l(ÑÑiÆÚU—žøô¥^+O—?Rí°Þs©šÿÿ—1ûHqilÑè$Wþhü›û™=¨ƒÀ(ÎRE +ØÁ1¯B›¹vџ¡®nÛ˜F/±ã BsßG³åÄÄÃMœYø«ëç9>£Ü–3……È—qIôƒ Ú£±¿5ƒµ¨ÕV‡Ü_À1È£¿Î²œåiÃñ¬JiXû0ÛWV–ÁîH[8g„«_î/ü¡£ +n3¥ `€ ¤Ðþ38A.|«f|ј0Iõ½6Öbå v«%Ó&ý ;Y®ý㿜Õ҄#ç‘dÿ–D.)Âì.p‚'ãï3ËJî›12K[DÌuÉ¥$s8·I<ÁR¨i©mì£J·¨8Ž}†ÿf€Ó ²åDJ¼Æ€àºƒws€!ÃÊ«®ŒÄr—æ¢RXÔÊ-\y^Í*Ó̏Ld'¨é›²9?) "Øqé×^…¦5µ/<4þ§i +¨ýQ<ŸÁÑÇ +›˜;/¹¥Ô±ìJB"¬‘ü7þØt͚ù©,mºóXdÚ¾^ë;촞Žñ&sà`«YÑ"à놠ÑYŸüŠ™¯{>ƊÕ.õßÀz^48¯‰e!¹ôR‘6}ØõvcûöìÆMiŸozî²Úoñ0¢'“=˜~µ¯Âi,3Ã:?-‹©Ý?oS,Ùõô9áÎüwß¼„µ¹þ#îÎRçOaƒìÙü£˜˜—ô;Æ ?àþäïŒåpïÍBäÒ­À +±ÖžI̝¼üO´ ݟ÷e#}Ô¯èN$í\êŠl?¼],÷ý Å·y,ÜÑ>&РôŠîä©øq]Âyhâ0AqñâK)ĝBÍF¶“ҍcH:ñì—-h-ñǟcȵêf)¯K9T£ã127]çÑä÷q·EjLˆâí•<>hÁ‹;ù|ãU +Ÿþ¼øםà”dÜp‚G +Æ«½`¹&!…Ïä8aðÉlû³›`83>Ì.‘òq„ŸÉ‚æn睅ŽÚÀ¤Aß9 +;èœ ï ¡‹­ê`¨¦H†ÚBÕyåg¼ Þ KBý ¯*kï㰗2fF„=#Ÿ OMã· éeT? +m­òTmê_¡å“ãOBۊV¡¸<ɆF('—n3u£G~†È®#Æ7Њö9•Á[ÃÙ¡`NísÞ.°P..콤 'Knpƒ–FÙ‚\„? ÇB>ƒöÆ-àî±Êõ`’ñ†½¯NÂèWßOŸOW«BƒªÊl¯f°¡xßìW ^ÐÔbžÚú-_Œx&*/¹ê(Œj´•‚µ_…=߆󑊢æŸzF–“´`éLd¯ßE:»¬—SN¸±ʔ@S 0Óþ¢3•|TÖO¹Ko³kÈÄtëßo}bF†Ùz$4á«â-ÕÐç,¨.mŒä'j*J¨œ|)JË6²Bµü¤‘°P ^Ã3ewÜ«pXúÁò.þ”*íù,0ÓÅ7xP­Ú³Å:2¿XOTç21|"7ùÄ=Ç0ãžß´©ãŽy}ĸB)Hä[èöžÝðFs´ ²òV¡+Ÿ±ò̯+Y(IŠ•™(º³‘Àx&Úá9JAIìÏã'tXmyœGÄ=œX[8éTK³)¦2œí©“<ÇTSRüv¥x£ã€lȓGO¤|Òg‚/÷{Ø>ãºÑ4Öù/’gËRçáŠF–ȶíà&æAÓ5”š2Ü uЯ*B<óiò뾘0Ògµr+OÍåA¸¾,0Ÿíî™-ŸbÅu¤g[ï\~¨-ôÛÙÐ4:I>幃A¾ÕuF‡ÇžÑ§©™ué¼DÅùº)B©,©*í?nÀ` 'qQIzÁ—K֗ö4Ž{ áB_g‡6Ÿ8­#ªÊ‰2.Aî$69¤!Ä̒Ñub1&Dð3Qxƒ"Þ >ɏnÞïνxüVG¿&•±TÛ¨ü†ö’Ó)©sx·d-5ºÄKx‹¢ÊÊàߣD&®1ä§ÁŸÂ±”¾œjðdû€GjJ•Ü|¨JÚ¹{ÅÛZ¢‹— Þ²Þf6ó½˜/vTñp̄ubšÙ ¼…P ½mBU#g«ëåB©gË·’)‘×-*ÔE +ar†Žæ>Ý>Ƶrn®[É­äFÓ-I ÊõByѸPå”=ÕþĶKâUC w…òG ùDéÁ}óØâ¤íñœ"¿µvN¯à.p•]ò]QÊÿ8uÊYµí{Ö#q¯éCÃáv}saü·¦x_o±òyÂiN™rÞÚœâ›À(« d8aÅw™2CöQç}Vš8ÓUWO\²g®……æ éÓ\«Ãôyk—@°¸d‚ óc…ê”Zñ‹t¨¿š9$ÜÙu +p†-œàú1ÏÝÛz(þ=Ôf) +‚vŠë¦ě9øØ¡Ö2ƒ w uûþ煼çïתÑõ#è…­Á{P6„+DÉËq3HIiŽû·Ù%„ûBóC‚’b¨!ÔÖÔkc5‡&U ):X®$܎–ºˆ[®Èb‰2¤*@ÀPkcӘ‚dÓoT©B_L1Uwi"É)ÉÌ=2#ù‹˜pI9, RêO>‡T@>è;¬bn¿Ðø¢€DÈþPuCý«ë›ŠfkÚéã^´^ü°\ÀŒG~•  »o—LÃRc¬HqÜ®=-8^5Ońµy*9‹û:-\òg8:T<á?*ÞýŽ´C;¢¶[‚µ·y¿XªÍïµ+±•ÙÊI©;÷lRLß­“$Dõ‹vYþTQ6üDyƒ€VmÖÛfy%/sIsƒ†mXP1ªLռȭ’¥«òvow)„QBµb™†ÐÀ_L¢V˜wuÅp§õ¦¶eėšõŽO*Ò“|Î+é]£(uH¼×°4ÊW¸U‹õ.ã{ Ê4Ó\ÿm.Q¿¿w‘ª¾ÒÕR~MAiÃçÀRz+%µBô‡ýóÈK‚ëzçª?'à{Àèñó kÏ҉ßaãêa§{ºèÛH]ÅþsX}dŠÁ°°a~ø3훧_•auƒ¹«Qz‚ ô ö‘¦žú˜VM\ĵv5I0ïL¾M£)ñºÇ„€pžæÂ1¿ý:5¡Ùð,ˆ&ºý©á4¨í %¦®Ã!$}o±“®cªÞ¤ã¨Aí]R^x„º‡T◬M&/BÔ:D¥wAêŒë2û4öÝÄÊ?šcîd&g]5¬b”¢’4³ôëa?«úèßû…iÐǐ»„ ìïĈÔý.OA 6Çvfv™sïd¡õ(5yTéÃHʐÍ/Põ”=…(¤a…›;zUs” ÎbÅWµã¶xéDa„)Eìʼ¤ $«sgÂPJár¿eÊYè3 wƒ€`¨cƒ™FÉo0|U[j5kÑçŒ.•5³Jç¡à&ª†åø°eŠT™Èo‘r …¨ÃˆÂ´´}I l­pàjC­á–û8cñ‡Ì5ÚJ=gç%U’®oó¤|L5çç­8E" +ِÿ®ß[Ak]Ùíûí„åJÛó‚͆áVBÆMí"{íNrÜòãæùQÕ¿òihЦ@€Y?ü 6³ñ^ß«ZWÙ¯î]Ø°¼c؋h¶KSLj:>®O ɲ…Õ÷.þÚáÝ°™µQŸ{5mm<Ù·?^Öv"ïÌ}Ùъw£÷9«ðOãØ&šv…ÄXÎ7‘km[ È,70nΒ7|÷éeÙážPÒÖ\I;<±çuë^`u‚!ËÍ$P´øŽ…B +ET9¢¤Ù²FÞW¬Àc»ƒã¹ám$úµ="G +}KÜe‹š6±~֔G_å³ÒìMËDÔ¿µs`± gî]£v¥p-9§\Nôžd{:´:Žgv¶HÖ_3fC;}ÐƓ PŸƒýNƒËp—H¯‹ídŠU9uÎ;ÂÁ´9$8wÈô ÿÜú3†rþ#¬AÄFÔiD1únŽà˜Ô-}õÉtþeÂÜÚ“D´í‡HÒ!5$Éš,IŠQ:¤È–RÂÜÏ1Ï3ÏÌ<Ï7ÇÇ ãj†1Œ[ÎЊTªÝmõ¾¨WwzU»xßù|öøþøÕ¾+ք{×úÈâöõW¿–>öò®p•ªœ:ʤùJRqY®ø¡^Éôê`ǯª<à~ó‰jûØ!mœr.ÜB­+‹Ù'«Ž”OyY+«äfN*żt ©WÑ$þ¨W\½2ï°Ôù½M_ê½c[ëgÕøñÿªjjö%WuU{{­,_¨°pêWœ–n%}P¬I^©WÑ|nˆ;c!¾p°…éu¼cʨÌN!k#¥´å)k„ì¯sdŸµ5nøŽû6Q{H10À×ëUì +œ¯è‡-£"{⠇TZG ôˆRØ,†ÍɇjࣶZw8j ICFöêÕ:½b [ Æ\+å?ˆ +èþ™oA n'a + +ÚôO¦j0ÀÕä`ê%µ|¶^é/si×_¦XÇ£ýLqiÔw]–Iç©Î­÷D"J¤î‘!y½!ñÔ¶®nˆ0²Rá zå WC¯³câcúh™üÈÅ«KÒ_R [úÓ*)! OSo‘©u©µ¶OÕ·Ó܌WÖãíze¯WÞCΓña½²¼ìÈϝ’Lê·Í÷/ÏQB´o³_“£kÇ/cg£ªÊ&MV?ÇÿÖ«5zõÝ !gÇôÌë"?wœ–P͚—IÏQ"´Î§ÈP­AdtE)q4þ±jŒðúGÁsƒÆÕnñ»{"” ‘óí}e®ÔUMÑrkÊùzvi89C}´ø®XóLB1W¾".ꕝ^M ”ÔûÄût?WK¢LÛwÕDP]t£U‘揊1r»J«ð·ÓÕ¸KÎÿV¹—ÈÿGM;phÌÕ·m æ‡v>èÀ-wgØõ©ë¡FNý ŒÊcIÜPþ#q‡òW• ŽÐËI –˜;ÇNáÙ¶þÅAÐ)ŃÞH~¡7iÛ tòhlƒ~ýÁ~dz²YË CûþåÎxŸ2>*c&Ÿm‰b›‰­ä{9f¢1X*²L˜ ß#>àíú + V@÷…¤g蒼]7n249=MÅÌÞìK% ¬;™’,ÙÓéœøFÎ\j˜ ð1ÅÑkl·Zå‚i¢×Ó؊’áíôœ²Î¡.|Q¼…9˜ŸÐ°¦$_.!“Ë;¤Ì¿¼l€ÎôEË,€ž²ûÉ¥Di­ùõ‡´¦êŽ}D‰É3^Êa`Y5Åg{J=mãìɳØéËyž3¸¢‰C¤M'¼jMê£-iŒÐ¦ÑmêÜ »n5? ÌSJÙE+U~ ô;·ˆí™Åq.t¶Xd÷¤Þ~œ˜Í~p*QÐeS¯¤%·.‘ŽÐ‹œ"Æ°ºöBs¡ª…ZÏ6-çîøÄ•6[\d;¤^z4’`;64藸ùú¤æͱw¶àô;ùŒÝ|ì+&®A©f¬LUàŽ3¬å¦åŸXòT»ßm°åô–¾)lãFí'l óVæɺÃgcGÙObßbɜ9ª;v \ºCƇL,Ž >B?ÝKGC¬·e"°z -@¼E´É£³Hûù»ILp<÷5¥À‘­ƒÄ'ðÐ҉¤èôàÞ$>ÜÖ8#ê„gäLÑ2®mš Áæc«ð¯Ü꨼1 èÀc‘ ®ðF¤w)™P¡ì+ÑrâkC q’p/Âu8#å!î*g‰…°ÈPaœ`vïu¡Ÿ@¾åo¡H`"Ž¤þ:üz–‹Ö_•‘Q<,DÒ>'Ӆ©ÓWP“²ó”§ .ÙÊÿ¾`¿xåW˜Ä3±|!6õ… » +£5„æù Elœ["Þ,0Ê eØòµÙ[Ozò‰Ì0~lúUO¤›+ùÓÚë&x£ì®kPù²c|uÉÙ$kþ.™?Ý{Qp""kÉí÷óÃÊrš6ÿisVûa‹ÄÏ=~‚@Wí_® +.<Ë7ª +­Å2Ë#h?c~¥m'r°ÕEÂ_ªxs…ë6‡ò¾øÍa»‰¥ÝÙü±¶Gµ+øš¶K 1¢þ4Œªä‰L^kUpø^^ù•_–ñmÓS^d‘Ш…§Ä'º­ùàµ>µ»Û}¦à5¶¾­—ð$:τ!EîÏ[«búJx&Õn› tº(ÒçmÀ;ZÿÏsF5u¦qX´.¡Õ‚£BqKPÁ € *£‚¢¸ l‚†„%{¸Ù“{³'÷æf';›,TT,¢bÁŠâhë¾Uqµ2Z”¹çŒ3çýü;ç}þžóüóT9Ävw´ÂRñR;GDž + Kû*ÃË/@hUvŽ„«…‰¯$÷jœ!@ጠÃvyבmŠû´,W²|-Í¢ –^¥ Õ~€Dô„²_Áô†­’"Æüĉâºàø#cØ禘Ï*íX/‡¸Ïœ“e>Ü|õXHÍù;û:˜Å)Ý÷‹d9gƖâ4àaBŒÈŸÿQ4óEÓ»w‘,C +Û¯B UÊ#à>ÉSV§$Lì-íÏ5gˆV ϯ*¢BüüÂ#‚ß}¶ npÃ¾Òtd½­¼ U˜$Dõb&$^¡\^Ò&Z"/˺+Ü-}¼Ò%è‚Z眅:}ðû9•‡ÆA‚ºYu§À æírTÜlP0Ô"šî·â~! Î͚*@5Kâ?óß«Zæ-â¿PÍó÷˜³µ=jô³>—Üˆ¬[üO?)¼a5û +®™›÷ñ?é¯ÆWóÓÐUs»ù‘°yÌ5^(ge›${C­‰âÏm>² "¤éÝG¸Õ£+Ú$Ø踿©—Ï«&¼æ XwÎÝÍÓêÆãÊ8?´Ígž‚,'ō=Ò"‚·—–/xÕúÏÂNþƒ¦îM)üïê'Ôòöº–ÌåÍEFÆÔq§rfÔ CįQ9ZY‘$r!ñ¤Òê6m†)–4¼ Ö÷V®9 k­Jˆ$#…Õ Fьê…X†³Ù¥úCŽ”pÐ[ç¤èģ)C¥ŒS¨;rFP#õIÊm„K£G<ƒÃh/ÜÈUÚ-,C€ÓO² kOKžYYµ;èMH-¾t–þ%û^NªŽÎ¾œB€‹Ø7" +´ãÙO²ají×X†_84ÍV(N“à-{D)´éF¡0«$½!àoJþÃdv/_øõ(ÿǀñÚUØH8ÞB§c×1•·ÅÉf¦b5u­Á&ë*®Ò½—nÛ2s ™«G4 0:¼\=Y2è߯ ”$bi”8亵Mß$ҙ:utŠNÎ)êÓEh²¶Dhªd«j£21|²*Téç¯VûË°îÀÀTª5È®M7-´^¢èSÌø¢84Te›µhRÒ¨jé[ìUîGþ»U±²Ÿ1•ààK{“Nh6vÕgÖ¨Ñ+Î…G?Ûõì` lݔ$Rq-ß.Þ¦2ÞóSòeÍ8pSՖïk!ÁXÖþCÍ\”z0µ0 nlhÉòjÂ<~Iª©®‹ý,K¿r²L„)ÀIM­ËàØ9M â_ˆùõc+"vҜݤôL©í¹$>ɺ¼’zÑü¾j>>¢îXå9,ZL-j‰«Ibk¤×ȉ8÷˚?vÎtÀ”òÌëx”žš‡©ÒP¾IO}„_ay@Äæ:à ãñì|VeÃ6Ö覫‡ubd/eÙ3<Ö­¬zÍtžÕeÌaÝÁ'˜cØLaM +Šlz&,f^ª_! ì?ãlâÛóŸÛ2x2¦X’yÎèåńÜ3Dó㌼)Ø\?ÈyÌež ~°ã4äÍOª+9$æ É +™á´øEˆV¿D<ŠO0ä‰Vbj&¦¾mLBÎ2Z܈öb9êðU¿È;nµ©â6L0 ƒ+–êoˇCrÑE.~µ>TüSؓÔ7X¬³‰®?MMå!ö½†Ô¼u–Oèôt›ñ’÷P Cbt;´·ðièñÈ•Þ°Ìãaøº@gWÙÛ#Û@ë¼ô4cœ9.Dõ¦æo‘ z2>M÷5¶þi—~Òu0¬ ¶qºsæwî®´QÃ9çǸLt–ý삟‘Mz)>©ûßkɝ£ûËI÷;º”îioï"’²›U)úÆ]$Yԏ†L >á$Ÿöíò$Tîÿ¢¢:gUo$÷öUK÷¨Ú,ÕCÙ`sCMAJMĚ×KŸ»C(ÕÁg]‘õ¸Ù®9ÔsÿUìGß0?“ˆ‡­Lóž5­ÅÌÙQM%Ìì”0O³léç5&Üéè`ÚƑ1,ÇÕxä'¾šä{ˆÄk+èmYÉ}“ÕßË-Jîs#\ÿ¥d‡“ó:Øi/àNûKõþÏäÂ\8©H½£›ŽstQ#Åá-­ND¥)….s*ŠZÆØõyžmÏnÏf›³Í\†1lØÅÂä’{¥Ž(Eé=õVGW¥Û9êsÞ:ïç“?àûów¶½’ÇŸœQûZºsCÈÕ6ªôAò1óöìƃ‡ë6KÌ@8ëõOUYå^ŠÊ`‰ßì7Ÿ„¶¯Šóºù³j6ù@£9?,yŽ‰¢Ðt4&Ë}"ÖT×ç- +ü\Y&kñâëVÉî»x—ë…£3ª¢9µô1ÙµqQ±=ébÃeMq\—Áª¨¯Žêî©`/nņ|ƒËþ2†ð͌Jkz¦DºmÍ«ŒIR4ü\~5NlðÔօ›ôÇKɁZ]TÉC¯3ål•Ì…©…Dî3jSS©)’tÍêWw$IXß[›wºV Ÿ +WT™«úUòŠw^PÙeU±‹®ô‚hÝWEµ^ؓ~WÓcÊhŽÿ¾s ±s£õI›g‘ù¨ƒ¶`Šÿw…¶gäs (€5£ªè×ßmrâÑÎÀæ] †¡ ÏB`7JfåAÞÖ°ÃaAÝ3Ɠ¥ïG³Îáê»þ?{¼O[ ü?ÌxËjø/´ÄæÄZ„*7¿e…xÍ÷XÎzà Ά¥î})¸ƒCÎûð?`ŸœKã‡cŒM£ÈúŒÕŒ¢´&)¢ð°š¡YÞ5õŒJ]q':]$ƒØžÖ]Yv xÖ(¾ƒŽµÐı¨ò†H1Æãe½U¬˜¥¬>Ì_0£b»?*ñ¸¨Žä¿bÏÚ÷ç¤،²•èæôÜD”±Þ;W´xm]|Næ¬7UÏù13* ;¦è.´=¹ð>ÖÒÂSÏÜj)¡CMŠü>”½.¤ÀeñI£¿ÜÛ1²²™/QßvÝНÄýÜ6T¾kk+Æœn\\‚F£F‹í¨V#§ˆ¹Xdˆ–£eº&~ûWEùÜ7á"Úbjª°Íúu‚•^I@ïj@ébQ× W´»kåò8ÇöŠwüÛ_ÕD …Ÿ^Áz‹¸ÙÚ x’Z‹KA Å_`‚T}Ú] +xÆ}ÃЁ‚M0Sõ,r„™ùV+ K¿×O&ÿƈ´`¨;­E{irf0F™]©— w86fŠ ÿÏðfm_8ÌèƒÍc3„™ß÷V“<)¦r1¿¯pˆêÀÇ +h‰Ès|pј!QÁéP'ïՂúÞʛËÏó¢ºÇ2òrõÓ¤eÒ×j4Y“ r©î’À, ÊrÞ?4‹! Uø÷qð]fÀ(œ¦*&umM+ª;”1® +-°•cœ8òC¹êÌj¢L=L«Î1þTDJ—º»7ÅÆë>©Òê²Î)BHå*£cúHY}~ñxI,{é©Æ7‚W…îûjWÖÞ§…ʇçãh¿g»_óÀ·YovÜMKiÖN>ü”˜ QÕÖRÒÒòǧ}È¥Aû–Qžj^¢©G ¿s› yJG"ñ?txt,LýÕ>«Öp°±_‘˜>ÞPo$¦Õ^<…%}¨ÊØK¦D”ÔS4¥ +·*S’<ܖÒyñd;’šÔéIJ»Ó~J®Mn>ÉÌȸcI6ðu¯¢†É–Ú˜€å䩊i77Ê_’5WŽ2' 9­øtÆ^}/ü˜8%wdáÉó0kšò)¹…ͦñ¢F9ÀôÆœk—ëÞihóà3úSh›ËPB“UÕLz¦ìs€±’'0®$Yá/L3Áª‚—oø“ól¼„ƒ|‘Éf ôɪ\AW#ësiŒÞSè-ãO^ÛIÓÌ+Ú3åÑ6¸Àxasíì îø…@MÜä +¤A h­ämŽ4™5VÑ-âî' ѵÈ1¦¿ð•S+ ž» ~* £%~kÓ¾ï˝×ʉl Ø*¿ +à lكÄ=ô3¹þ»_2~”–­OgP³¥s +˜C¢‚þÕÔcº¾ÆdÚú²[ÚaÚے{<Ð¥ùƒjÔA {! ߲ۓ¬Èñ;O'Èá9+wEHŸEÞÀµž¡&†J¯ÒVé?fáiÓº j0¢5瀶bhW”ZxÝo=”¥Æº 0–ˆÂz‰äöhK5å’m¢ä•oçÑv (Y€Ouô±óà¿t¹;‡ÁËe=¾ðRÉ*ÍïyMVõn²,¡$v:•ÄQçÚ³EãÔ.›yŒVlò;æsvn·Ö,ôõWi.[¡÷ÂÉ¢@•¦­„¤34SüD_!“ÔMú›ßF‰>J柣ND ü»@$ÊYÀ~³-³’µïCÎMu (+lBpБÌÈ^úâ#$œ~÷2è /@Ì£ë6 3nðhÛ +ž;÷ª¡û‘Ûª.âþ—«¬æÞæŠ3F¸¿q3ã™Ü\َvÞZnþZ"/ËvNF”ÜüÖNŽJ2V{œ#ΚV¹sØâÏÈe_쑮àTˆöa“8C¢°!ΗÌ÷>FîÎL¡ó\ÞþM{û—ü5®ìeH~7;FÎã Ù ²AäúÁ³»¤—B?³ÿÈV¬ùÂYš=Û©‹»Q i9ÌJ.sÓ¿c%–è•FVb‘dÕ¥iL–º`Ûa)kD麛=W®Á³Èœ¸œ‚ãÍ \nÀèçÃeÕ>ŠN¸X7Ƒ†2Iª¾Yf-Òto7±¶«/®~ÁòUýè„as[š†`W›®*v3_”`~©û‡æ:kêÌâÑjêR(" E +*Š€‚ +è´¢e)DDIØÙss³Ü,÷f_n6Â"¸€Š:hm±h+Ô]Aqñ•ÑQq¡âSaž¤Àç9ï{~8ç|³~bÌh6âG«îíZĠםN\Èh´ü+„Ë(E3§0ï~Ýùô–ÞÀ†kô–T‘MGºÎ²¼èüÎ1ü:zk›a'LáøG‚±¨‘2‡>ˆºýÅ,gt ÉÎîX&¥@Ù?e%œ +ýœ¸ˆ=@€ÆIhÆs¨ˆ²á)H…ÞU§OeX^mÈÁ7R7Ê~Ë,ñûê,é ñ\jí´±»¿J„ÔŒfÌͬíÝð¥ð8!*¥]˜JR:æ‚öWâRÖ]ÓMˆÉš” ‹PöœZ«ð;¨¸JÃNÞ.8ɦ®ÏÙÆÀ,Á[¶r*ýΑ¶]MˆòŒM"waX)Lbjd‘`ç>:ÿ?ü¾íù|:?uƒ>^ÒÏGÁ©û$˜ÖfaŸâ.Š +Ê¥_àƒS‹ø%²EDð–´8½ ¤J¶Æ=£Ä•K¢Àâ©{ƒ·À´Ü6r zþGÄãGêò«‰  ‰Þ óÆU‘ií<‘‚—ÄK’gçå"÷¦¶^ €qŒ +ü£ôùI6±°¬±vP¦¶‘éWÜy^,š†u¯c/5ÚÓ@¹:ǹ+[ùŠN¬þ+ðlÛiÁ{ÞŽPò#^¨Æy†úìïvë,ñ±Üæãþï¹-ÚÍNÕü˜ѳH×⺣<Ö¡gäx ­ÝVÈ</·Ýænb¬äæ6Ðýë¸ó´³œªÎ¡ ¤+nhB˾â¾PÑËoT(§W–æ#ò#ĉTwÄZU} ñ w-„ävòÄTç½½Öç-9Oá­ºHIãz)¿®Ž®ø ï zí9äR'·dÁI5ÃÑa²ÎZ©ïGS˟êag‰ÕW=Ÿ™.÷P1ٜ y?³¥ƒä2‡òÂóX¾)rÙ4VaGº¥òåÈX¬ò©æËBe`9üQ1‡ß͚@8ü5åŸÃàÉݤ·ÀÜäß$×ÁÏW?‘Dò}¿”zò†ÿ2‡*È +ƒŒÂÌ÷pt¬ +ü°;Br\ܕì'> ¬Þ-övø÷C¹NeʔÛô²ÈL-ʌ•qÔçK×H½”¯r Ä7ÉIÐ d<òŽ¤ù¤BðgNelB^փRγF2èÒAÓqCR€&ätŠƒô³7߄ü´{" D9š·Þÿu)—òCð­’w²¡æ1úˆt³}?"þ¥¾'Ç[Ý7oÉÌ©«~ž1…{Ÿ>Rìu*ô ‚íʖdÌCãôlÉÈÁuøtqf‹2[ÍlÒ~{S4Ã>±J$Œ«÷÷.nQ¸nlåPÝ#üxÛò])By`r+ÙwÞð²âçLH?‡˜ºñ¹VD:º|«æiU·G¹þ~Õªÿ+öå&+RµÜbö gPâÑ>Êú}¡úÆêàŒWÚÔ¹÷k–Qǖ]WSkqÚwÔ×ÎZ +ÔDæQ§žd¶¡‚‘V„Óídè24¥Œ±ÄKªGÌMËv«ü˜U35«˜KJ~Ù4&j´’w·J àÑ÷*µóy¡;˜êXà߉˔ÝÀOá÷£@›û5•hw)Œñ˜´•ÛoØ-9E:¦ó_ÀÓ̂îo¿¥òƒæ&˜6#¼Vþ£(ѽSé-te$ íפp}ô4Õ%Ò4m¼rn¶z‰üôöhe4‚KX*¯‡KÑð÷î2ù9‰Ê©à~Ô×ü'Ǥ»l|O5ÍB† +§;•^§ jÆ㛑Qõ`ØexHý³;±JË\*Ë`lú¬Ë´KÄh¦×k +&”ƒ–ñtùˆéF|(²Ý8VÇ¡‹Ü·ÁR×€§:ϳû´oÛG*UjSKk¨ÌnR¥“ï±gl¸ ÷Ûޅ-‘6¹ûÉ&¥±Nŗ´ÍÇÇÖÄ7Oâ4”ÑrGm´òO[du_T’×vYÖ{‚ ̏IyØ\ëaR Ky¶¼&•Pï7ݪJ)éløƒ¼"—Wÿ5Å{K¤å åÓÚS_õ¥àå¦j0WSW;¨wèixêÆF1Í^lÓО伴^£'¤1ï¢ÛÖbŒ%ôOAÏÐƬÕXÂhq)Ló7ÀŽj¥}=€9PXŸÎ=‘“n¹`ŠŸÉ—KX#Cù…A *7{È ãjœŠWÜ´TœByÕÑö¯‹ufכéÂñd=úA˜¿f±Á]蔧ÿFè…íÕ=à_u*`¨q›²‚·¥+î_i݋\Ê^`BaEò|ÔS&Ž¹¨Ÿ%Z® ‘a´8á—ª°+Qˆüg½Qÿ[ñIK«Î-Ëj¼£IKr2T¯cjuñª=A ´ʧØQÍ"7—ò²{Ù®“ûêם*æX|,YƦ¸¤zêˆñÑÊѽý¢Ž‹}ªÆˆf:÷jCo[>™]×ãx^¼ÒìhŠÚõílhNrÓϳEDkþªcÕCúÙØǪ ת9Öýc —ðîH›t<)…Ó}ÛzËÝ!ÇhE~DBÓ³Ê2ßS͆Êòi{;éo•×u…˜IøõpÉ??砃4™6Ùº«ê^"©¹€Ü±¾1•Rêû¸±…’<í“-–êš65s²jžpCµ‹óÝÚSjqi6dzھİÆ紈† 4ï‹†1Ú.·ë$Ã5E©Gü9ßãÇ:Øï=µ­oØ÷Òbšµì¾„ v#»Å[éÿx¬ï¯¦ÀAFë+T㳌€¢Œ³€Ô(C@RQFöº7¹7ã2€°I$Á^a$ÌEqƒ >µ.ôAEõµbŠëõiÿ€ï÷O0‚ž®Œœ]Т™K5ΫPیG„´æ˜ ãÖ ÃéÒðžZªdÖ¨J’ºË*¼$dôýò·’ó ^ª}E¾*Ö¤Á>?‡°©‰ÄëçƄŸ¨áæÄø¯­$d«ÝO”£³ è_t¦l‰%¦Ô$^7¯Š[“KüñSú‹ECq´zŒ"$]Ý*óûµB]øÊ}›ÎWö zT[Rk­"‰ƒç®å®n¾]¿EãçU—Yv¯ÚFUãW\þBÙí6£-RBè^M¿ì´e¶2Bœ4¯èÇ/wÕͺÍhú4EèõkÙ5˖’<1òU‘¼Î[¦táþÝD°Å>îQ!˜.kR¿Ï涧ä7˜uÆJµ­cû>òcªÂ +lûªˆ/ûüi^¸á3;i÷°š‚éڐÝ0ƒæsÜèÁôĀ­˜ZÛnÃSÆ +¥»ÀqW7ÏN³“p:ó([ˆ½Ý5Ì6‡8·½„Vùi•AFޜì~h¹9£PÚldüjì2îdO +²+íÄñŸ¿6Âü1Ÿ--üß1Eú×üwvø¦ þ=JCH«šW¼3ž’4܏&ŒxÝñ½8,¸Ëà&ºëãÐÔ#RcŠ3Dåvzý6‘…RS„¨yuè´_N/nm÷كØÐvTÖÃàòÖ¥Y˼?êåRF×°KzÁnª¡9ó¯ã•ÉþQ®æ4ùgœC×^Ù5l`ºP\ܲº€âýG£&ÿ¦¡Þ«`÷² õ±9ÏP¨ÒñÔҞٲXÜÊÎrÕ6Ô«Œ +V4,ùÖ{²a Ø„ÑÖý\tcY`]lÎÇ¿Ô¾¿a®§°r‡é´¯Ø=bèÖ!ÁÊ&ÖÉûYÃb Ó^[\ºaYt­$w +¥êø[ÝÄR¨)¡§§iÛìº[ô{$™ì7f"¥˜o ŒÓò“¢X‡‚p +»Àz¶BzðÎÒŽ'hºO|Ō4ǐ§|-•já +:ž•É}Ì´a«%Tvœƒ5ÛÚY9QK¦ üd0 ?ˆ$˜äćH|õ#òuäD3µ päôh¤éÔrÆdì@,@XmíÝVKY¯É@oò„Ûu‰°([µš´8#!OM~.…7SoJn%< çI¶îdZ‹ó=ž1ËD3‹!P#4÷£“ö(|:]SYd…„_škG’äõ²ïRh¹+OtÐB²«÷%Ð/eý䱖á&]·hऽr5¥slÿor šQ¾¥êÎ"F”,bՓ÷*2~®£:ʼ÷Šiõ®[ˆ´©¼«‹ÌtéÂ˦“ŸíÛ~M +ªUé6§DUÎeõ"udPO:ª¶Ç]£x+¿ì ¶GºÿB½®˜]´€q:óÊ¥—'ý:¶-ML3\ÑF$ç7…Kà3êCÄô*sü2µÜzÏFÊsõ'÷Ôû¥ñ  ‡Ì¼K¤„ÞsŸ§æÌӚŽ¤wER§” Ã!`%aTÆãH—êvçR¶W¸õSPÚƅTÆòÌ}FVArB«[ŒïSS &ñ™}pù`Ç ¦~ˆãºÓ_íŽàÙ1{Ý,yãàªo„‚ àÜÀŸþ{ó30…é[ÇbŒ K™¶È:wœ3Ùã¡MnÞÁµ†e6òsz/0OGò°" +Ü3NÝÃ|›ó/Ð'ëèO¬-R_—1Vh&׺ N’Pz8de™ºî 勊ZTH;X‚†ÐåŠQÊ6Æ}™ñ˜+°¢ 'h´Ï_î|ȋ¶ÆCc’“˜¤©u¨ýHù¶j£BA,·NÛOS«§È{é3ª÷Ñ L’è `]Ñç³Ì1ÆÚ> Aº¯Ç ªÚrxÓ´ü*E^ÿ.¢×ؐ`ú†Š“Q5 šv{`=W6뼟ñ\9aõ®’ÄvGOÞXc& võÈ1äÏÆw‚~êÖæâ0Wÿ:ʎ~µˆfª–: 0¾/˵‚§%þm äKRKåAÁüšÂï‘ÄcˆR %㠟P“#CS£éߥÞfÚmD¥5ÎoEx–…1‚7B«¬ðæ»0ìóÇù<&ÏæßôøYdø8"1²üwÜ¡5˜Á TaaJ3p˜†5œÛ¹î7îA>®‰+ç…ñœy¨”Iž–Má¯ã½ôcðuüð Zd?ÒBê†k1ÃËÄx-—Šr·sVˆ†9s¥H6p]DÎGâ¸g…O| y»„5ŽS¼$a´E˜`$íLs +[•¤YmÎ Ê~uå8Áíp`6*I ߕÎ`S8‚Ì»8s™nŽû9O3nX¬OE /7f•^ê…lËbNÖ[®PBµF¦O¬‚.Ü9¬€ó·ïZç¾_.Í5¡>¥F ›õ S¹µÌ‰µR×'}ΪѬ`_dÿXš|ê{´dâÐHXÔ¾3šQlZe7Pã©R¡ªq¸Ø´³O5¬ºOkZþÏrx5u`aǂ:‚£*`ØT–)›¨,¬ +DPQÊ®²²°dߓ——¼ìûJÈŠ ƒ£Rk=H+ +*­#u)£èèh§Õ) …Á)B§6ü¿sï9߹瞏øïHªZGòµzçG’†ÍTø"9ªÕ3hŠD×ͺ ³Ïs¡îr|ÆÅbã4þÅy ¤$”õTK ºá•"ù$×IÚÖ~Î$v(ˆBìÖ#].²ïqiÁ?­C°¹N ù–ú¯ñ~úÞ±Ë|ìíÜ·àLcOÀnÎö¯T~ø³ÜýäþvxjºÀ̦5<.ïÇf\K<ÏÞ2pô:CpËõá•Sây,66‘ê>|zŸC +Œ“¨ëE +T)ÔÈf/À•:X1È}J+Üç>¢½Œ_Éý…~–˜éQ;Ù^Çõㆪvs&¸Û¸>œ.®k“7‡ÆyZþ˜SÃù:‡Ë©ãœ£rØݖۜçœåÆaKaŸ³”!l–è.g5û ð7ÜKv¤0 ì!;ڗ­fï´îîe§ þ¼%‰]"XëTÖ –J3©aÕªõlwV²j=v†å§ ”αÖÉÞe=bùI/ìög…H&ü†™ ’:§²°˜g,(y 27°>a™b°aÌ8ýËÒ8fŒöVV®qßÕɌT‡ùµ0†ãNÕöŠ±Ðù‹ìãɉB¦‚ÑåÀ`( š_"f´˜o!• Ðt}WgüŸ_0}Hµ¸¬X Î9»,‰QÕÓÈxÏØÚ=Ž~JÙ¹§x‰>Ö€ô£ÿÓ±eç9úM«Ý÷2mFõ¥Séî)×Vk ¹µö-eZF«FÙ¥btøg0Éì¦O?‘DàžÇ%7eyÈښ6þ‘WªÎS¥C‘ÒyÜeäUS}Ýñló`a‰8i ˆèg"1лJÂ"ô|P¬KڝÒc¤,¿$¼Žì+Î&ÕÞÕPš°„vꖴGBoj_t4I òvq¨f熚(ñeÖßCÔË!οbÇ×¼†^°SŸ†bØYi1‚Óì¨;2ûˆWä`/7u¬h?4 +®†Šï!Œàzõœ@#(˜ãóT ¿œ¿6ªŒ ^ó¢ð!§R S”¼#Ð>E/áSÁq9¥z_ /G%ӈ0Câ9Æ[Û¼‚@”(Ù©”ÝP•é À, }ð¾XŸT…Ok‘‡p¼µQÈ«U¥G6 ª€ ¯x2¿e,¸Ú>¬áÛ -?Ï­°ÊQÞ¬Yzð/ÑTº·è5ÌFLÉä†^`ƒtÞ©‚Ì3ó\#¿¶»¨¥¬ê̬Dðª:¶,ŒvÓÞÏw[mDWÑ¿¡…›)½ãTB¦ÉZ½‰Þ`0Ֆ`3tÿBQ˟kkðûs4ë1yÉ ê`ì\è¸Þ¸ÂcV#þ‘z`XÄHhwõA¸0­Ú†FTy¦úqӵܫ*F˪¤%€¥*Éøµ/>Ó9 +ÖgS'µ"b'zL=Nª)c¨‘s×*æÈ÷“bä¿Rˆ¡ëä÷)W<ü#–S ²µç™›)Kê÷Ìý £ª +&¡ô”âLã¾\¹Œ9WËtÌW!Y1󏲫¬å«ä7i*ø%”ÕþêúwJ_°½ä¦Ü îÌ閥ñnÁWJñ„!pÉåþ³ä-0éT`¿:K6BÆ+»¥SõÅzÉl‰¯L,~“³J#ZL´HBEeÛ߈E÷q1 +Ú¸¬ÂTD}é­bB;º*OÑTCÒnՍlŒ$OYŸ¸Qœ®0m·‰z7ÝoŠ„9NÅ» |hý–DV¤[V¢’eÆÖ©b7ɍ£Y¯ÅZÖ¥H¦Çlþ¤Ûä~Iè)Ü»¬J•5§ø¤ÍòoO–Õݑù´©%(ûŽ,¾hÞZ°GøÊÒ¼mR˜d´¹ë!¤ð/NEWutV57z;ÂjôÇÿj¬s·ý»^’^lDçǾ0-a®û­_a®ÏLí؁ŠówÚûö44簍b^³ppi‡ú̍úô&nÓXì ã¾æûþuÆ»-«Ý‚ ž-cÎY4Œ½_Œ´¦¶³šg ?ÚjºGìIãfHõ±ú ¤%ÿÃJ҂[ö%Ï©¨C6OzvWÛzåÑoZ©tËA¦±˜þ$õ?z€°ã;ÝÆؼÅØéFT2÷/+˜å0…™ñ@ßÑ@S<@>0bð¢SëuqÜw;j4SÜ'°/4sÜïÝÊE®Õ©(P[¿øú×V‚^¡5ƊH’õk„g/´Û„«wø©û  0¥Ú*ÜìÖ­ ƒaËjƒyBýÍ5ÙTC› ÅJ(¿_©ÈFà4©òü˜!ÕmÙ, RÕÊNº Ë?SœŠü¹9³õ :×´Ê–Oèÿf¸“OÐVê×"յڇ1ÕÊí,V)Sâö@æ._ +Óú°#ý‘Qî`”Kõá¶ò|ͨ%cï˜j¨Í/&\™Û: [­øFƒtû^Z"ªqÕÙ¤Jm•ë™ŠjMarחµ`VCg +ªžw" ~><¡Ã óŠ8Éièú½µ}×XåT8°Ç³QÙ†VY<…Ä<ÏJ=áÀEÀۏ7G8v6Á¼Z:¢%¿·¶hBòò94^™Ô¥m!1¼ˆOD>íp%¬HüÙÞGè‡ÙðÄ/Ã›`rqÑ;¨±N…mï~MýÓñs§\©‡/žˆ¢Zh:•(¶í¦¥…MXžÐ°^FÛ.꜋‹.–Y½¬þÏs}5™`aŽ Òö(ƒ(X0ˆTˆ+JS°‚ Š4©&¡¤~ù’|iB!! !)$ô)Ê°Ž‹ ºØWFÆY]EÁ±ë¸Ž3x,Àó˽ç}ï¹›å|d´ðcâ +õ“|ï°i-‚¿0ÐWs…÷ +Q_Gå½pRjŠyÓ0˜òÑ׿’t¶©¤øj²ÑT̎óԍŠî‡‰D1·ëڅ”ڍ›NÊ:ka? ¦øç7•eê“棆k–Ø_µ%]a;ëזו¯F«=Ë9™Ô-b= &¿óMm0-­vDÅ'^Çj´Û+µ¡/5(erÀ^õ+E·çL F1ä$¨1KŠæ•×WE|fÔ×O£õFMK¬º¡¦ömèí:ƒ:1`»Ú¥fÂóƒŠXýЩMÕ*i€9ÈÊ +l?+Lw?-NxÕÃ͈Ôwɳ\C0–óÙ瑃f ÎsÒŠë·M;iđ`°Ê$èöµµO»“0zúÁ*RÙ¹œB9é@Â"´k¬5ÏÚíÛçvÀü~•.lð³B?îugØ]Ãedº¢†…è8J³AÞjý­Ù͹umÌ.­ÕD›O–ü^^ÁÕv:‹y;Á³skeÄæ+,LȶvÖ²­ÅíàæÒ¼½Ø®¥™Ã‚ÁdÃü_¾ë5÷ZüŒ¥ƒ;q®#k>ÓêÇÕ ¥MU\ƒÛJ“”«¶{l*͟¿’Ò‘¯3Doéü¹èyüèÉÂ"UDcû†¢ÍÁuÍÏ#HŠ)BPäæitèì½/ vÀ`Ó_êSʝã{Ìeù5mpñPpyÓ=±-2Ýè[Úëæm¸+v·Ï6*.WÛ¿©ÉSǔáñ]ã +^DMk„œ,2ý.#£÷ɲÝ\õ³Ò!{®^âƒI4ßԈåµ.~°Ã§ælDc‹BU\bò«"c äj¤Ûvý‚ÊÃöJGÉ|ÏH`_ÕÈ2ÜrÔÜÉ넧ëæH»³Ñ¥ä ¸§tøŽHH®†BaGŸ :‚ú‹ýBÖfšó°{–'ñª9 +[ˆj¥øaЧøñe +&hè´°z6FdÄy?¢>g¦Û‘x&él$¦ŠÙÜ^œåÎ:¬¶Áæ³^Šèøn¶‰úŽx-'-µ¸’û]èO 5×⽜äØÛÎ@Sä UÞڏy]°Tu à_,zŠáWPT„|BJ,ɕ}`8Çß´y?pŸ7gË¢uóŠÏ\JO(_ØâŽvOUue4•öÙ+Q±¸Œbi²?A.jÞÿ´Cxy“˜´R¸ÊÖJì駥þPÕÝt㸲rðƒTôúfd½d$ÖºâFR>Pâ¶aºL·ñ'ˆv÷¥¥äê2M—Òë*‰¨×µ¾TÕ]`WÖÝ*ßcDÜ*åûhøA¹e#ï"ûɆKO9öJ“ùíKL‹Ò2š¹JÍñçø( KgK3jԉf¬Z¶÷nLåå5‹ýo•‡M(½_ø¸×>éFO‡‘—ÚÓ¹Gi}<´ÃÄ@w¶¬#Ndº­áÙhoo4öYÜ Ì¾¨FÙ¸2¬…—ºÁYÔAƒšz$ÃW±„Öœ5ÃÃCoplâiÆÂ\ ³ˆÞ3Ä2‚l„;…òaá¶<;šSç?B»>‰zü“pr§j–Ðs m»ß1tôZÏcÌ¥Œë{¹sì”/¡‡þJ{™Äcü*Í#»3ûóހf–Ï¡ne£ãæhúœ-»>Bc9SJ ÿå"¬Õ¹O8á'•8ހ `yHÉϤu¼-œ*`”· x[c')OyÁ»ÖÐ\x!ë¯Qïñ­S9q*;ÿ$;Éd'=–NYÝÌ ,|ܶ3Û4§¾”ù±q¦T˜=©ka%â´õ™h±s¤€ä¬ººÖU¯X7Fl«”[õå oµš1apuxf¼9µäQ¶Gk4³;e +˸€7荇ß5ôîxB:¤y¿î¡¬Zd¥Í«,¼`2²—?_Ía[0Å~9iY Fs®3öÿ˜g¹× ¸Ã‹9u¤¾ ò<,yxí87¼þ© ´1‡‘‹¯¨JaÆ¥¢,O€@/g½½ÐOÙ㔛Ñ94 ð|.]»1÷6ýè'Å^Ô¹@1'¬èp:XtŸ±„Á€ðŒwL,j–ùVÜ÷á¬Qv@àwl{ݞ­Ì±ù¤ò\õ?R^ç½UVÐ\¸GIœ+¡­¤¯åž9ÞÏðäÎD…0×æ»ø3oæ¬yÉdç[R<ƒ""ˆ’" +.´¥2…}”´"!<ý4t¢H~(®-rñç2¢æ5DºH@ùÜlÚÀ"K”»““îæ¿£,“¼/S}ÊëÓÎÒÂÊ"+ ïÅ~w ¥™«£—F}V dRz™,¸¨:Èw&?­ÚC~Fq¨ôJ}JÝ¢ð‹˜¢ÊJý’i¤´ÕrjzEÒgUÿ#±Úp]ZFšÖã%‘Õ+Èþ [íPjewÄVjlõÊíW©7ªà«wRüœ/*žð¼C%µ%íj…òG€xÓ @EFH)&0_ýËõáՕÇ|Xuˆ +D¥¸àRNXAÐ\0JSŠ¤£H‡é30ý½7å͛7½3 C•Wc+–ÅU#Ær# aQOL4E³Ñ™?às~¿{ïïÞs¿I§èªÖyô?›y>ßҒLŽÔÖ¸Kd-Þ£J1Êvñ*fH ¢6§àh¸æÞöñz²+~BÜOó:IÝøQqöZ³¡UՍÊP±[àU’åD#ÔBMË Ó>$Î ãz|”ð?Ìë^‘¢Ìó• º!J0ÌèW8µN¼  ¼WÃzX›òfÁÏØщ@'hƒá<ð¼ +%sdŸR۔eï[þ$z,¨åZù2ÁH5ŸÿˆÊ[&Ht LÁÑ ‹UàOà ì·¯Ë<Äu–ºÉŽrEðᾀ{i¼,8+ןwM2ßÀO–œ\ŸÏ7I8Ïùi’l»2Ýewkv"9kÔr6±ªŒU\¬RšÍ*¤q¹oäGCxxy¨‡„;€:j™œY°E)a»Ô²Î°!Xidÿj¸” q(ú ¸8ÎSí“Ð=œ÷Úl(ŽPíø9Iueé&¾åk)«­‰W1Éþ¬Ñ=k˜Z¦b;8˜zBÈCŽ³ùƒû4›«ڕa¾vþÀ?àsuú¯UuPݝæŠ\Vf»>+›5Ð2ÁŽj&…PØ6»šuR»É®Ô! +aÑ+árù‘Òkô!¹o©4 í«É`¡ÌܗëP)fíô%ù¬VñœôQñ‡T™èFÂ(ZÖ]sŠö‹,”ÔTR‡|O)O?‡¨hŸoÑ# ]¿6yÄл£)ôéOçU ,FœéÙ ¯´›ÑE})gŽsá©ÚÙ´GðyÖҘp/kw~˖»¶I'Y¿Ù;TdÀÜg‚YÉUž•Ò'áñƒ‹I8ÿ@Fâ*ð‹ ”8 $¸I¸à+A2((²+yª8O¬æϋW‰»È—EÄ {Õ¢ýbÚWÕ"@œ}@‰C׌Štâe®Y¢¢gv…Öˆœ•üHáÅùoÂfE`áea±±gbN›_¥ÁÇÌ4Ê!/¼e%¥³ÁÐO;m¯ÅÈht§ÄWv6¨º·ú›´[©ÛÌiô¹˜¦åÌÅÁyF˜yÃËÓ4ʔaêt V„]ÑÍ auãƒõ ¬#ùëÌÎ쪭QÏYm3rMè/q{Ž~äÁtjÈüD»¢ ×7†Š•fàiÓƒ¾É· ‹Á„èºÀê ¶. =[ôn`4æŠêÈqSháæBéžrÐx_º5wԐ Ï%ÇènÀQˆ…ó‚ðš~x“'G[ ×`+qb«]Q›2Ô¸²iÃ=UGnŽ~»òç¤ڋJÏ(¬†£à¬ýAݪÈôd«Ç È‰E7ªÍKÊz +MÿÊ]¡ã’ˆš!}ïæ j–nh-CÕ¦_èé­º¦Ùç䃊ûíŠò›a¦Ù­¬DÙfrÎjï6–$-Ó4ôn®UõZ×F)¯Zpï•×ux'º@ü]U•ïÏ/ìÙ³¢Û¿Ø3íUg`iUì¡}…åÚ°ßÛUÖL¶»W©–Îuœ¯òù+ëÕSïØUå‰î[¸Ýû;u•¯ÓÌû¨„žXJP“v§åOâŀ©–{$•KFÛ,qƒQÏÕÞr¨uÏHìÝ.ûúÈ}iÞmõ”×ÛfZšh~a¢æåtŸ€ÛM—訅BÇb0*€ÛiW­ÎÌC䶧µ‚¯jZ®×mÙÆn¬›[nKfi c¬+.º&oV.£ô&Ê­Æ{•ÿ¤5›_°s¬9†dë¸mÿüIëA. Í*sÑ5: ‚1ù ¨Å®Ê m!â¼|f‹—¸l'Û6#NÞ +Z§Ä>øÿó\ßoMŸkÀCZ8à)* µ€bEE@¥§(2ÂÌÎ7{“IÈ" $!¬„0a…=+vU©ZŁ`-x´E½ ŠJUǺ +êðùå~®ë~ï7¹TÕSîs¦‚V6·÷¸ÉÏØØiŒ1=2J眆Jhê@ UÍ•æu¤;·¶7!³0 +ß½Ù\Ó醮õý¢ý¬—«±ƒ%-;Øþ=.ÒÜeÏ/©TÖ7DŒ$v°{·.Ê«“‚–µÂ|ÃZÑ®³mcDÖ²+-C¤Åu_Ïï{¯>ë1H±1]ÿ"—D^n×R¾ ÞÙº“:êëÖÜE3ƒ[²h9¶»¬ÏèÂÅ ‰Ù7–TJOW+3 v«œLimc @ï6'³é[Öcì`Ǧ8v§­ª!“ó÷b‘RÝ{•Ð1Ï_Óµåòu‘¶Íoù³PµE°2Øð\@;4"›mOÕÙ §Óÿüm{·Ä ߺE1Ñd‘ÄA‘¡’}C=W²¼®¾B¶}[3']\PJäG5ØV¯ò‡mnY¡G XyÊahdÃ'J„[U~ v¯óWæۅWoÌ]¼Wn÷G¥n½R°¶²9H7ÑѨÔ¡Au Ú1¢v£ö‚ëÛZmˆ]lU§rñÏTØV¨A +sjÊ6lŠhm,M†Ôy•4Aˆ–À’*0¤æ¯ÂÛv”J–²RÈ?¨ï ˜Ä´>ëîÄ2C!*Ë#±q0êMJ!:ŏÖCö‰ÜÂÀRÇ|ÿdüF¿a?Àµ2Î݂ÅcÙh3¡«dBš‘z¨ŸSIÎt?¸%‚Lý›mïëF[ÁAÚãxÁY‘Gâҏ0mê;GY1űh%[Ÿsጒ@×9é q·_8ùG>r˜ íWó¾nêå¦Ü)jod€E“…z¤Cö.qúJviN&¶IfÅÔð8b›øgŸ + ñŸv|ïs÷‰d¡ò©%:uTÉÓÛfü‘û—è&òL®ˆ0Ñç~–pï¢èÝË.(R½ŸâU +; _)§w%$ò‹Õ/à÷ Ýt#é« +~ö#œu`u[ëwø.–¥qÜsÆ‹ååYìü_•-þ‡Ç*'̳ɩåßk/§––)2* iø9¤¼$é°7fU‘zÏfl¡“×cô9}£]´¬,툏WYCÌIëê÷kSÒ-¡§t¼y7>‘T!¢ž˜ÆÌ Àä×26ŠÔ¶‰ÓKݲáç mÄ&c‡•Ó£h’¸£Œ' Ù..+œupCë6Ì&@j“5Üt«¡™døëÌåêP–0«Ÿô–=ŽÙI™Ë‚Ä–Óú¹ä +úC¨{Þ¶$tR:(Ï­uO¹ÖR4›ÞÜâ$=ðjl¥÷¡Äuq—1?פþç9î”ùSèi|cåõqÎF!¨_z^žSÂêK}¡Ÿ`d¢%DÎT íwVŸ>Å;à¿<É'’V=(è5HÁ%jú»à¸WMÑó±…VÆ#àß9ÛY‘D2ÕÊ֓Òîp~¡žˆžá~J ÚÉ}ÎD»]ážgN¾Süs•jJmƒn-‚>,v¡g&SÔLëlê#–’ãíÆ>ŸÅÝ^Åiææ¸á8®ñÊž®°%Ùñª4'ÉùR‘’JD“Ãh¯RN0hBëA0ó”(rÛ0K+úaõæ‘þ’²MõÀYÙò|"±E¶G¸ƒŒ”E_R^ÉvÁÏÒ4²/ì¢?”ùm[˨•y¬N`ØK/5[™7«1äÁ€[G„Ø’'¼ 'æ铯RªGöËhqꭁÚ]Õø>£úiI‹±Xà +5€'”\ãGBŠ „Ä‡…ÓÉÎdƒ^u•ò¿x +•¢ë[¨^Úá%e¸‰ ¨Öªúp»«xEÀò +À œ6…%!ItãÞ¨@ò•Ò¾#% Ô §¸¾ß:¶é™*‹h$rßà7שðׁ«55‰×ˆÙæՑ'I×+6‘Ý*ЮwÈ°¢Ñ%U”#¼›zDá+JÈtàü šBùa²Uؕ 6âíøñ}ñ¹uOÎrÆç7¥ñdôÿïåP˜À›Â þCu}FEuæa7£RVÍ"KS‘ª‚‚T‘¢Ò20 E†éåNŸ{§÷^˜Älkìëƕ$vWš(¨,¢F7–b ˢÞ¿ÜOÏï¼ïyÿ÷¾÷<"_–³)“ÖÉ.kîh˜àÀ[n ‚9Wñ?gÜçڈ7¢ºyș¾*¾œôöÓ¼‚uA@ ¾OpšáIäRùŒrPý(ó$e[i<ËH›—±¦££¼Ø/€\ßt®/ýâGõinQ­Àaˆ@ûšq–Iïaî¯{èYʒ]Že–°?D˜§98ߙ¬çìéy©­dx,¥8¡?“½¨½Peí1ÚNˆWŒ¦wAíi‚N,» Bçà=Ì%P—K©ÔÄò~þ҈œGò!OʽÑßR=e’"!Í]:™:BûIê\†¢MJ1ðj Gò›K)b 'xL"W?D\GêԝCÃÈ{µæÂAÊA ?u#U Þñ•ªÆÁãèUJê´òÆÃǹ— H{ÁF[Å5h’ÚÒ[N6˜á){((ãÛ%Âø>ƒVªYâR +nñÖ#ܼ°ë(a¡«ºFìqì&mqü3%—\g?ñ%ÙӆñÙM5«Ÿ¸”ø¶X‹D3‘b$ʁW×ö Ÿ‹¡öÆ¿‹5&͔D4Ó®Kƒ°ãc²ØᏊ ˆ. +úë1Zëšo +^`ú~¿`Ç6z ëq¯©Â „ãaX‘Œø½Ç°ø)±ýӼ܄'À¹84 n"Db.ƒâÊð¹yC<K¹³ú d§Í},ð§õ{œ*h® +Ú¸»hè>¼¹ôwMv^ cö¦8ÞIÆ»õ(~óÆj?¾’¥ +eðo²®y†¨l/—‚Dl5¯€úžãŻרãpùy1œùÎܣܵü‡«´Ü^004€{ ñØÃïí.™·%CÔA2¼ù2ë¡dÿWuìõ’šœQö>‰oÂkL<ÒÍßòò‚Å5.Å¿È iñ”f¦¯fh³7S­ñ-ßÉ|¥^–³Š…T¡jX[•wCòY©*¸sG^1­Ve֗ä+À˃€˜…åó·L³²·3“ —â/2y†èà{Œ†¹ì+ò½.Å;Cçt‚äJ ¢}¢þ Ðáô-³¯>Ù«y6q<ƒÁ³Í ý–£W±·åx¬Añ_P¢Z? ‹Q ŸÞy¡ÀËÍØ1ì>yîÊKö”Ð\.ë!¾O—qÈM±î² +0Cî¤l…ËçÓ];¤S¥k)ÃÍ=RZ@Õ[É·ô5…ù‘¾JBe„ǐ$ÆÿNi"ã0 -ÃºìR4HœÅ~€9.☫|DϸahÑ·-Í)²r~"êåeùoMòæÃÈâþôÝKÝ%4 _7ý"ŠÂ‘e +QD~Ÿ0Täæ.¾Œ>"x*õO¼>é…§…ã.Ey+HVy55R”ƒ•Ws•éùÑÐEk*êPxEGBü¦ß;(J³ Xâéµ(8h©iqãmh¹‘^™ Í0`óö€}ú´”_APWµDèÒüLü£Z¬‹]Š<–·4âÁzGÖ¦`Œíoy©üZÃR|½u^ŠŸg™ôCð˜F#ÌnŸr)ÜÌVaåô5ëƪwˆ–Ššó9³­nój®yIÃÁÅtó¶Æ +xI«®1bªIyâ>}•‚›-A–ðÚ¯ÑÁæõOShãšìKF¦xµŸá6xq†qQ +Ž3“°SóU„‘›\kaÆþ椚̩ÌDi©~ ·?{‘>¾J¯3mátߐÈðZƒ„øtªÝÔ»]ªY §‘N¡ju]äɒÍÚï©QYílZZÂsˆNÑ´Ñ·À“´Wé>Sã§Ý¥0ÕBÌÂj»æëËâõ+Ö7ëºÔqì҄fU7û»ð™ªmì ¸·ºœÝ:Õ8ŠÁé¿^Ó;õ#ðeÕ¿Õ+ ‚â*,Ä_ç©ì†ôñCÊY3ì®â´õMåÿßSšªU*™¶ªLùXÆ.jQ†È–g²_I¯ÅWËJ5a"9Rª†'ÈC¥\y׳qH)ÒåVÍUü¢-Z®Ö.Î\+Ñ¤Æ/—aÕÃenš/|F¥[•¯?S âPkr¿"Ô +^”YÊ×>”•˜ÝVŽH9 &yaŠòùI‚ÖxýQÕ<èzU1\–µ¥ +Ù½þl§*7ù}ûô±hu;Twfa^Çåúcn²Îü†YS q;)oZ¹uÞG!öuTÕU¬Orþ§›lk;ÛHF´-Àx/,uþ sÔm¸í>fdêä}é+] +U×.oÊ.ýÕˆù=·Ûq»-y¶]†[õÌv¿iáR»ßçîgëÄÿk*ï`/p©êþ¶LBuéû±+çºÍAº²ßÚ@‰Â[»)‡î·&P®¸ÇYQÃ?æù˜iåm/¤‹K,¶Y*g…u€±(iÐ2¢`æ½Ì؀VË"f¨ûJSsèÓ=çRU@ë÷»7+ÄËÎ>d‰ãْ¦§¼s‘m¦Y¼áš)–wÉ=U?οþÇ3D¾´Äó‹í– qjv¡é™8<ñ…Ñ!zgØ)ºbèýì^ª[$zð™RYjTõÅËÍ)ªÔ¬1ãcå?M…2qÙ=½@éæ? ”Ü£5Ûew?SIfƒq´ØÓD7þÊú kò\ãL24A<D1` (T@@+½“7{½Ùd°I؁ 3*8ŠåœÕ:@-ím©âq´*îÊå8ràýþü><÷uÝÿÿݹã\•‡id‹ÈXmümÍÝJ´ñ¬×ÛJÇÊö’²¬"§ÏUúžjb'm_êz$bï"ì¶uOì÷ðßbûM¬q_'Ñis¤äͼ?M#mp_=~müù=ÃÄ°­§í+È¡ëŠ:¢Lùâ;48lÈþmbå3ï埒-mÛ$õY|H—™nÚú]ÇcÀkk{>3Ç×½} »Ö1Ár†@vÿÁy:{­EÍ©Ô¡.öÞ¸Î,珈®¶~žCH{kâsÆvš_l‹æ¯@š”"ølûORÉ."0ÞƧFl´]]Càְ˧²Å¾±ÞMÍfˆü‹i n´q”Ø˶QÅóð{Ö5ÊìàÇÍ6ef÷ e l¬¹[I‚€u·ÔY_(i«»&;¶Àª×t„ïo¾¢é ئ±ù¬¶5•°k–ûÿßýÞZ§ü‘/”¿ jÀÆîj‘Àpíî~Ch°Å⨿íãÜ䦿ëiRês!Gª-…¹Ÿ«”Ö ŠªØ5ÍõÅá ËÕ +Çàâ¦Åå&wó«òïa7W”ÆAÆ«X…æÏU÷î²Ûr8„Î+}E)ÆoV¦ÓƒIÌ}ÀqZlúÛhˆ<Ëgw® +àˆ¹Aæ°ø?ï=‹ê$ù6-ÁÞ¡|,)!<¥*‘ǘ*z!­•³8í߀ϸu”ùPpÕÆD|èŜeÿ=s˜m4' ²¹Ò¢÷ؽüYaPøOZ(ù„èvj?VGÜgxI=V¦–-ƒ̹¬ u¾MCJÆëÕH_é-Cª]ö‹ÔûB~‘2A\¢8°¯*÷E8PóTª•Î”¯To¡ 9/Õw„¦Äh¾©½“ž¨‰Óýˆü aƒß£šbòy\Ÿ¦'ÅF,Ռ…o%¯ÌwðU/åÕª—äßnëMê*ÁÖT Ƌ{µ5NJ¦ÅÖìÔ¢TÒ9L·¡;y _fXÖD\¤ïóuÀ¿Ö·AÅêõ:x«"¬)¯V%V/*´¥]1•ˆÎ# ŒÎÄ)ԋŠžä@ìX¹"ÌSVåӅ“—™¡4u¢.Éfˆ?ÐÜUÕ¹k%¥àNj´ù¹È;cº~?]Pۺ˄áWßÞҌ=VÕ듍1ý +E© ºÖ»qd{qÕ׉Ï;’ +²N­Âæô‘–¥„ÇYH‹d×fttcâ– Çì»â#&®vŠPótQÖÚjd¡©‹ 1ùo˜ øù­ìR)Ê½@}”Áï<7õ ç³&—ßè8³w¯àyóyÒb¢ÌH¢¦04·èô͂@>ðo` °•‰µœ~î½Mž<¨Àa9‹‹úÎ(ÉènŽ…­°c9̼4òß<o˜–/ˆÂE1”Ì÷â“áìÉ:ïã¬ɕ¥Ô7e¢þ ®.{Šó“Õ‡ˆPi WEî—Y±Ž´xùޝr¨è +¥EJ…7ˆTöÏæ¶Ù|4ëê'¥r41—œ“„ãæžâ¬ nÏsÆÌ#?ÊCśhkòº6¤/Ï»¿¬——7›n Œ áHIT¶ƒ¡‚c6èß±=ðzz!ñ?z·¸_)þºc¼)¯uÚe‰T»®}nSê3ÒØ&iq4r¾‘¬ŒE¥UÂYÑX\ùKÔ¼ì—88IXú`}7yIi¦× +¢ôSëÕiG›¼‹r3æ8Eiօú$f ú·ÚÌl+n º.¶’ð®*d}0QeÊó:FŽ¨œœSµ¯S”퍆Éô°Ö¯äSȺ–8æÔ~‹%;[ژŒl0~{‰à^ÿÞ KbV+æT †sIÓÛx)èoe¯øÏqÃÀra5),k±xUõÝ°‰Q"—ØYNîפƒ¬¡ÙܾWu8GøQ‡d!Hû9í´2”'Ë¬31cÂC\ïà!Q-ž;UüŸ9£ ¦dÚZ¦oá8CÂN’T1+¹hڟl-?63ˆ‹zÆ,å=]ŽàÛAw7!üz6·û*HŠ„H*[|Cü‘¾_@m¥˜ô¬s2Uôr]^9ñnµüÅÂÙû0¡"ž°PuTó’t$‡#:HõÍù@¡Ð±jyúb€¯~°=å™›±ö*‹kuÛÄUçŠæ¦QîŠmÓ9æ]'pu „¤—ÚÛd€ºSۖHgiÛ¬€‹6r-ð×»>`Oi#çTÙ2´¥"-÷!NSn\ z•$™É¥SÔC%“QïèÉ%;‚þ¢O»ö±z‹cçT)!ûM½.wf².PàŠo¨1ŸæU=Bœ¦l1åFá©#F0HD“\u̞rڜ*¹™uÜjQ÷ O5·òu8–E$®7:"âÉІ¥‘ï(Uu£ANägulWàYEãœ*ZÖ"cT\‰õŠk—öáTx»lŒx)™$Ÿ¢<ŒhTÂè',Ê·À —ãêóÌy³={V?$¸N€)ÃDëÉPŽVl Žàìà¿Ò]:é|ædø„̏ãà"»Èíw1*§¸=3*gB'æãòë|–'#ÐsB±FáS^PR“8†?¾ +$ mþ:ð¤è@®•Ïöl¡ÆÚ(蕉9 Ea,·_܎iàǀ/O IýÂ4ÂaÜßS8!ûÙ%UJ’õÍý«à8C¢(”&2¥J:ð;{»ÊMጫ~J¸ÂÃådméâ«rFW øjg°Yý?ªë;®©s8Ҁ€Ò´Š€Z6\Fq€D,²ÃH Y'{“ÍÉ$a@QÜÞkÕ^½÷ºÐ¶ŠÕrõªh¥Ò"jÅ}+ˆmÁjÂôßóy¾ŸsÎû¾Ÿçù½Ó™Mµƒ°D]Å_CJQw’)Áê/ʹÀ5õ®¬×´2µsµ7§v†½¡}§Þå7Ä TëVÊÓøS¯†€6~Gú„”oLF¢ø YHÀ©²ŠKmÖkÂv»õ¿~öUÝô.+ýjpâo8Ɖ$Â5û)Ô\R‹‘¹²´¾(ùàgÝ–H¾m}ìw”5jœN) ++¶¢£‰›„ÛïüŒp·vO[n™ŽHj©ÍŒ%=hº• ’Ï4‡^"‹ýl’q:iƒ“Òç%S,˜ŒPîÀûË=ªÆ‹äG°±›²Tü²åï” ‡B†ULR8LW÷˜äêÒÏ$GÅxLcLSƒÀ},ù?þEÑ;ð8Q¿±Eª$?\.”e£!&¹õ¬KKûç¥øJ¬øÛéG„‹È7°ˆ|_ ÿÒžl8!>Ë8Žè“(Y«BæIúY·`[å}ì®.úB”Áõb ѼT–²ú$¿=U8OÉŧ yˆPá¿-x¯ð$¶]ú¥0Æý_Âù¬ +ájûˆ(³“sO¼¤À‹ûH|/=wKRŸØÁ—ƒÁ•¼ç`ì p±túl>f*ºÓ¡œþuU‰þ<‰=¬T­§s®(·&zpK”½A?sLÊo`N0M¥q+~*m¥î-¥‡~F7‚^ÈôÓ5惬H]ò${žö|›-Ò¶9Y&í=X'¸V£u+^°Ï–Eñ m®ÿ² +¤·Y/ç0ŽX® c˜ÍïøAæùdPcÜü_X˜ª ™VŸRx­6²ŽÔb¯|Cã6‡å‘éÚÆî´^FeC]¼…¡oÀ-¾F?f7Á˜ Q3éVÌ>͝y­Fsõ•£y]ŸÝ¯M©F®½¥íÁ͊¾£kã^NÕ¶¾¿I¥’¹öë#F›Z‡.À7¨¿Æ†–Qêfã®eÏ«CJ×n®;AjˆB JFÀ€æw +îýmԗîê6êÕt¢”Žã(úI5¥beE‘•¨l ²×X•ôè¨Q•…´¨ÍŒôõ™û i,)…6QS ƒ1zJŠezVBfžì Û¹ú¬œÊ¹•/¿Ëí HQ8¸9ê…SnE%Šoòþ‡-“4ðNJ±`¤`,£Ü)ü~u¸tŽÈyQŠ“Nˆº]çvØ­p‡´¯š+e„"“x©ìææNñ6yä*µøœ©”,“7Á$'äx×\˜Îç”Cü‹ÐQL¿ º[8.d@}›çïCõɏE)1⍑àD?@晹—ÀÛbîÄ$ó?7£ + ‚Y¦ÞMÐä• N­|ÙØÏÒ _ÏTd'wa£}†Ó0Zð„÷“ãî¦ùü<ûÑä9|•Ý3Áµ¯†Ã閗3~o=§ØY>Ûú¬l0Wb=P1‰ÜjmE ‚¬XòR[lÍo¾uv:.öC=æú;.Îa.©œBřá˜S[þnºWƒJ3ÇŸNì1='\XrÉü–8á»Û²Ÿè:KìX÷»j¶6â‰e †g΀aép£´%z"¨±K†1ê¤ï.c1õɇzÉ­°G´TàRi’VB“eßÔòþë-)K@iͬ­!÷uì@_ƒ`»&2ˆq«ê u¿p%P——õ +áéS­Ð§|NüWP´ !€ì¢o-t_àš Šƒn…y­úV|¾Ø¤ö“賐êe`HʏêE =>\½‰Tǀ¯|ÑêcҎ™kˆIS¼T!‹”…ª¦Ì%Gu,%[IRý'®ëý““Áß+#Tç}mÊëê•3ú \ªï/Êßê¯df)‚õ`Š·ü•n2Ž#ÿ·î\°MŽÖû–(ªµCQëd¹6f‘—lÀ—qGö®žµvŸì²µ).Z&²æ¤w¬I¾ùò¿¶ÌTe{Ú‹¹õ­¯JQéæÖÂòܕQ­ž•¿E\m•`¼p–`öÏÒ´ìÁÚ\éz[•v7OV¤o9ݜQõÓú¾¦}ÕØ$SSFMWÐdÂÜny„ï˜u£Ñà:¼ ·*éoœ[“ž3Ø ÅëýO ¬·FRJøˆã0ÙÐÕ¸›l÷ô¶õ€+­L+û&ò†oÛEÊ+dŒ- +­@Ô?¦ý^f›E¿ko¦oó\fyÉÜíJ×Óó«8Åz‘‰ÊΰÒXmi Ëö¿– -NwØ}‹…‹„OYÏpz&˜@>ÚÕg¼ÝªHcþ‡ .«Ã «×]7MŠü£¦z‘#Œf¢ŠàÃæe"“g¦æÎ\ÃÂaã°ì@Ö\ãqyºJc™\„¨3ܔ·‡Á Íò½ðý†r«'W§QVüEá Dè|¦ÉP½L½­‡sõ\h_h—í…#ôÐ9ÏZ-ÍTúdóÊL´>˼!õ„îWS/bžn­iAè3­ÖÑ.1Fx@Ç §3UNåN^nýPOZñ¦dÚ t<¦jGLyÁâs=‚Š³>»vW¾O&-8ךs§»hvöö‡eSȉ•`wPU_´cÛaÌéřÝ=Õ·}öm`«<<ìƒ$•+­»UV×6Ì6dòÖìÁ¤oº88{ÔÝ絁çºzkG}Ú»®Š<<ê7Ó\õÒÓjvg!5M×Á!®wž&—GmpfS¬ÙÎg€·O3x?Ì÷Ø +wZs«LRûqê/ë~lŸK]QÓVÉع¿õ:ÓoÑïmùÌ<Që'ÌÃÆ R]çAMXyÀu¢¨ º^¨ƒÈ©¢€œá ä$÷}ß!ä 9LHÈÁaH8«µh¥¥Ê¡rTtD-Å*ÐífY]]wu¤®Š¢²®u[bgÚÿßg޼ߛ÷û¾Ÿ"î÷ÕȹÚÔ I7ù•ŒØH”R·7ŒH§B—Hðu»£d¿të ÷*µá²²=e¢ JŽ¯t­jŽ|먾 á¹#T­¾•ÎIõ/¨¥W?þ{úΝ¥¯O»^ëŸÆ'º`ú·‘£õv½'$»^®óEÖ=7¨IÉÜßÖTF×2˵”­õ7-¯â^Ô'Zú"[x ;ìü“Åæ[U‹7ã–,©”þQyWrrÛ9†õE†—6cày'I§ ÀgIR“mŠ 2›¹¯Z½Q¸¾ý´ +ç{0K”,è^ÊH©/>€>G’@l`á—Tîë=FZ‹àÓðnZ¢H ¨Ñ³$mžÂ¯鵩K¬AÝ3D;w³¨Å×7⾎ԫŏw·‘^J<á«È`i$ M_¤xÐò8w¿ˆU-,ì/h!Ó»pbPê÷ 1²ª|*¾k _U¾;ìÁ£Nè“45‡ü²’”jûõÍX£šç_€:Õ]¸‘$ %¯Í«X³+éè óÃMiwzô‘z{7í”Ñ`fOEêÃù5Fo´hÆX„}»fLÏ}ƒ¼k%ºJŽq¡_b£Œ_†ôAÆ5ú¥4WK­àÌÕ»ª'h?É:lÓØTHƒmm. ÞmÕ&Æ"öX7…rÑãV7à²Þ×ïžßl̨b§]r+• ÙOë¯pKó[œ{0ƒEÃuwrf ÓµçFaëjCCP§k®ÆtïM»Ý»’Vwô[FRçû(¥YÙ-Vî²¼åÍE8£‘™Ó Á»ÿ™à€PÜð?¿)™p>ÜÐ͛ö5˜ #ÿTÈtäF%‘ú“ÌÑ3ª qhkü”Æ ¡;ã`¼LVOp¿œƒZìۓ. ºÛj¾&ü\CÊ¡ <¿*Ùgü!½°r)JÌü‹¼;ȁ³–&x§K0äNÁ\“úB¼&æ­£Ô³¶‡ùï$¥bԍ7fùp¹è¤t(Å0ú±HÉ2Š€—ª3¤Ó²G1d?źµûè +ùbßVֆ|­°®ÿ­\[æ†w+™tj§j?b7–¤öÏhÄ«§wJñCmÐmê#Íb.^V÷äBõ–ÂDR¹bÑ8¥¡E]4œJ… 7LGÏc.Xd£°à¼/ÅaÏ&ڎè ù@›é¡¢«˜zQuֈ4TÒq¨i˽èèb˕ 4ù3˽Ê~,ãyýmoθ³[ü 0þ ˜ +€l«} ûÞTóCÚuäLõBt 2¿úZÐò¬ã°WÙ>¤´EhÃ@+[‚Řüê¦yŠµÈÝ0= +ósç¦U"r]á;îû]÷(üºÌ{…Ó‚®¬eù ÃE=œm˜òa^2þ'FKv¥~.ôОmŸµ0O­j(›eñs¶ßº´€ ÕPk*!“þ3ùIËBЦŠñs4å{^§|{6ÏÆk\* à}XÌYž¥Ç å©ú‰DÆ=A %ŒÍ$’hǹW‹øŒÇ‚ORV°Ž‰ü· ²ÜâÖUB›øꯪ¢¦rÏç+C°a6¯‰ ¯ ‘ãK‡ÀÔ£eàä :ZÚ¿u6&»à?ÀWË&ïk‹).”Ù]%¯ä]Ü,l”b7MX]Þ[H"}ªìØWL)RI·rÉfõr?Aâ­ÆYÈ&íI¹~_ÂIBåë$Ø{XŒîlÿZ·°·—X¯E¾&|¯wø#ùºßþ؆û`ˆ¥_vºß¢fã–õØu¨·æ3ù—°füÞõømæ¨È8—9Ç?ÿ˜9ð£ +̟¯ë”NûՎ²º`çjz1*äÛêöüíè.Ç@’ë爎܋¹ì`øoåÙ’¼J_™·±™+-—4α6@’Ð/DWEÞjE}HRæDl¹‡†;Y+ï öÛÏz•®‰/‡–…þˆÿ1†Dçѓ(z)oι&ù;éÝ.§4š¸aZú#Ùg—êsÍbÎZ+úX½Wi;ç<~†næ"¯(Á ô´µ ¢MŒ'‰“b6›·!G ãúùlP<á^\ÌÙnM8-—-aœ G+dyXPä^Ž‡s:û¯•÷0q \p3bˆ¾ññW¬u.æ,Rå&År§„m„òž#<„HeÊĸìvQél‚˜Ã.ˍÀ±ïJ>«Ò›Þs)·àlej…(‘^ Ÿ¥,—=…/¥¡€¬FVù’ø6fjùðÆ;eð‘­²x•â%ºD³‰Ÿãk¾%!FW@aäæŠo2QT‡vs¼ §5‡Ãhí0ðŽB¦{âUò÷H—iGCO˜®ïãzL' pb¢Ižq”¼Í‹+'_1…¯¤Lvà +‰‰ÿQ¥ÁAÕÉÜÓ%ǃÄ$Ìû[H~‡}{†1Øf½KÔÙ²Â:HmWS +µ¥Ã«d}Ð2w7ñÔõá j¾¾‡­<ø ½O¯›Œ­Æ7ÖiÂ2‰GêÖ;SW•Ý’Ê!Ø@YâsœZ~ß*âî¦ÞPƐ6îx¤QþÜ¡Ž§/9iø7cñGªöHV‹fÑ3ÌáR>K•ÌüŸí2jêZãxH"Z‚"²)ûvH€Dö} ‚@ز} YÈJ64ˆT(P_Ý(*¨C]žŽ¢mi­öéSžJq·OZÑg­Aåé(nœy8}wν3÷Îÿ7÷œï;ó?߇‹*x"Dü’Ö6²Hae¢Z +Ä5Kü e +tE=H÷º·—±ÿš\ƒ·W¢8 Žù7¹¡2ƒy÷èm¡ü]L´ËŠyô‹ÚÄ ªß1N<å8͍¸@û±û±“ù:ï> Å>›Ë6p·„ü›ãÈÓ¹à¹<ÞAМš*ìµ®‹5M +àåN5Ðøƒåg¨Á³Ü¿ÑÝ]7ïcðDþ!\Æ÷¢ÖO¢Û6Nê(©·•bž¯‡H´õ‰éÖ²r¯t1gž‚“u¡ÿNÝ'w„ߢËeÎGrºÍuŒbÞJ1îÖaÔ#øgøiõ|™ÑGcŸƒ"½ÐÀÐ á'xù¾&ÚYH;£¡Ùª4›T1}‹Ï®;cÚV*¯‡™Ü²w¦f”™´Æ|œH2;ÛR±Æl›Õ{í‡ÝKÿ²*²óGÜùZPgìÖ׸z *Û¿ù©?ʗÖÁ +¦×“:ÌN£”Íæ9u¼ö”•¢L7Ûo©­¹Û|jëBñjEV—QRªî!Ū¢Ú;~;ÔZüZûËÚÝxÙ²ž +ì(Åñ†œ¦qìƒê’ïªÁE蠟ëV¥‡Éñ7å:b¹Ÿg3ìh\yˆœ²¬gå.:OšîÇé«ðÜ0ˆ7ºÒ¢›¦bÞ4=¢Nø¶Hdto{¥<ƒî¾¬çWZgHåNR•üRZ\á¨às†W*Zxˆù Æ»QÍ®ñ™l<ÆI³‘Ts|—õâX)‚…c?®€p \BÁ —ÉK‰àuðç¢eüÁ|0|/aì½hBÈ|樕ª—ÐsEG±¶ÌMâÁüs¬Mâdû‚Ä?ê*G,õ°ïHÞÁæ…ýRÀg®[)|å3…¬CëQÌå{0b•‰Iט%9*–ùXÙáÝÌôR‚MñÇU)+ë^Ü ¹P,¤põy*šŸ~uR½Hw,r„~L×îõ;í_º“°vN§øˆ"¹í¿—“‡Û¿Ê]¤ðÌ//S{̑‘êͶË^¨Áæ0X 7Õ4¼’ªžÓ㊈Å#úޒ{Y´<mg¨$…Œµ5`·ÊVs-*l¬Û»¬gÆùr¯’iŠË•[ šÉÊöL¹–X#DEhgq!N-_׸Îêc YP‹a ˆ!wÖú¯Ê|Emí±"¬ÒŸž¡PþDŽOUHSðr5¸a»+[ý– m×þ• +äWh¥*Â¥{I/1YwûôJyõ׸jùkú@p[³†ñÈåzó3*RÝeñŸñµRXwq3¯0´©Œu%­BÍAŒ%\NÐC)šWí’'5ð꡵ +&ð™F+U,ŒŒd5ò…gR "JãrØVDB‹SDO]V‰[EסdyVӃ•1,+åIevù"þŒì`Ê‚WrwÄKa¯œ¸Gø…|—óÞÆ`¹Ú%+TˆVR¥C¸Fœ÷œ{Ys*¥š÷Zó5â߬±Rùe³s¦ Q3 +ÅÉöjáQA¬4Ӌ<>ÇÆô$ù.7Ã$C$p¯ç¹ãçõ¼Aã)h©ì„îéJªè¹ewáTÑÂ*Fmž´èK™g-‹ØlïŠm„Ê*{íö{•¯–ºÑv\ܲžsØJa>3_*ݑ¹Ùüہ>ÑîVµ5ü|»¦æœWG_Ç>ÁâR÷óR_YL¢!ì´R…Fã›jz†§ Sû5fځO›2Í’<ï¶Þ `¿¶}I\:ÁõXêi Zk³R–—H*‰Ñ4„‡Ùè[(ßxúÔX›á$u|I9̺TkV—ÿ…z––œ×l£_‰×¼g¢C½µ%¬*íw¬XR ‘õnY)N.õ9+•wZñ[”ºE9ÊľW¡øŒ¡J%ðw«p`Nj“ ˜[ÅÊæ.Èb|JOsd“W,®ùRÓ~ø#Å* Ľ±yFâdwC‰’pÌûˆ*‘L(8ÉOeÅò¬lL±Ç˞)A›ÞÈ Š·vÜf¾ˆ¶F¶’ʹ.¾£Kn•dë~Aò¥¾º]ðDi‚ã(iÔÕÙ]YʯíJ½õ™Þߟ“?‚>Úwó[ä¾¾Å7ü†ûKK“6Èw"ËÊ!eýç°DÈp”ô5‚µV* Ý3VEa{:KoEDôôcɾ˜ÞôJš#¯oOU4ä“—š4¨å¨ä›l¬TjF·k…,>±{SÕ?ý»SkÁ>‰ÝSu»×ïÞñ=Î|­ëj}à€‹Š­T +¿SU÷.nkç.ü«°“„ƒÞômâc‡Å®)RxØbÛTÈ<ÀTÕV*y Ã™<+î`R‚C³;SÅ^ýŸúÓ0û-ëitp¿ù<ȗº2I—Z_0ñÈ¡¶VVKHWÛol¶—­9“=ëfdÿ j…ðb€¹%}D¹C¡ˆyã{Ásø‚I*”{ZLߏ¯›1šÀ½†óâr`n}+©D¥îŒÔ×_•*áUzÄ3Êð¹ôÀº}†i7˜§7‡ÿ9_‰kµÃjxÌLË+u ¦;¤FxLë.«mÖm×áÔQ`sK›zñÏ´¸ø¿›K#—> ¥&ÁôñõޗxiB½VÝ^Í\sË3Ú_X»è€X_ïرá¤ÓC˜+Ò­j£|SŸû kžÏ½ƒ|j|[ýŽúßX +ΆÓBL¡ûÃ.„?Ž\ÃD˜‘C±ãq÷ãߢ7nŽO(Mä&™“¿JO½Ÿ¶á˜š•™ËiÊݖw0ÿ¿ë÷ÃIÝJ÷LM,NCOYPoQ†RœS²TÉUßVöX Y#Z:[Q\f]x^Š_›`­a¾bÏcàdñfgh#i3jBkRl^mgnqozpƒqŒr”sœt£uªv±w·x½yÃzÈ{Í|Î}Í~ÌˀɁǂф¿…»†·‡³ˆ®‰©Š¤‹žŒ˜‘Ž†{p‘d’X“L”@•3–&—˜ ˜ÿ™òšä›ÖœÈ»ž­ŸŸ Ž¡|¢j£W¤E¥3¦ §§ü¨ê©×ªÅ«³¬¡­®}¯k°Y±G²6³$´µµí¶Ú·È¸µ¹£º»~¼k½Y¾G¿5À"ÁÁþÂìÃÚÄÇŵƣǑÈ~ÉlÊYËDÌ.ÍÎÎëÏÕоѧҐÓyÔaÕIÖ1×ØØæÙÍڲۘÜ}ÝbÞGß,ààôáØâ»ãžä{åWæ3ççèèÁéšêqëHììðíÃî–ïvðUñ3òòêóÃôœõsöI÷÷óøÆù•úaû)ûëü§ý\þ þ´ÿZÿÿè§,„¿ç +    üóæØÌÖÞááßÛÖ Ñ!Ë"Ä#¾$¸%³&®'ª(¦)¢* +ž,-š.•/‘01‰2†3ƒ45678€9‚:;~<|=|>|?}@A‚B…C‰DE’F˜GšH›IJŸK£L¦MªN¯O´PºQÀRÇSÎTÕU×VÙWÛXÞYàZã[ç\ê]í^ñ_õ`øaücdeeÿfügúhøiõjókðlîmënèoåpáqÞrÚsÖtÍuÃv¹w¯x¥y›z{…|z}o~dX€MA‚5ƒ)„……þ†í‡ÛˆÊ‰¸Š¦‹•ŒƒqŽ`N=‘,’“ +“ú”é•Ù–É—º˜§™“š€›mœZHž6Ÿ% ¡¡õ¢æ£Ø¤Ê¥½¦±§¦¨›©‘ª‡«¬w­o®g¯`°Z±T²O³L´IµF¶E·D¸E¹FºH»J¼N½R¾W¿]ÀcÁjÂrÃ{ĄŊƐǖȝɥʭ˶̿ÍÈÎÒÏÜÐæÑñÒûÔÕÖ×*Ø7ÙDÚQÛ^ÜkÝyކߔàœá¢â¨ã­ä²å¶æºç½èÀéÃêÔëåìõîïð ñ,ò8óCôNõYöc÷jønùoúlûdüVýDþ/ÿÿÿØhÆ 2 +R e r xzzzyuph^RE7)4=@?:4 ,!#"#$$ù%î&ã'Ø(Ì)Á*¶+«,Ÿ-“.‡/|0p1d2Y3M4A566+7!89 ::ö;í<ã=Û>Ó?Ë@ÄA½B·C²D¬E¦F¡GœH—I”JKŽL‹MŠN‰OˆPˆQ‰RˆSˆTˆUˆV‰WŠX‹YZ[‘\“]–^˜_›`aŸb c¡d£e¤f¦g§h¨i©jªkªl«m«n«o«p©q¨r¥s£t uv™w•x‘yŒz‡{‚||}v~oi€aZ‚QƒH„>…5†+‡!ˆ‰ ŠŠ÷‹íŒâØŽÍÃ¹‘¯’¥“œ”’•‰–€—x˜p™jšc›^œYUžRŸP O¡O¢P£R¤U¥Y¦_§f¨n©xª‚«Ž¬œ­«®»¯Ì°ß±ó³ ´ µ8¶Q·l¸‡¹¤ºÂ»á½¾!¿CÀeÁ‡ÂªÃÎÄñÆÇ9È^ɂʦËÊÌíÎÏ2ÐTÑtҔӲÔÏÕë×ØÙ6ÚLÛaÜt݇ޘߧà³á¾âÇãÍäÑåÒæÐçÌèÄéºê¬ë›ì‡íoîXï\ð[ñVòLó=ô*õõööÖ÷³øùbú/úôû±üfýý³þMþáÿqÿÿٍ T– ¡ +¤ Ÿ “ ‚p_L7! ðÖ»Ÿƒ}tfUA, ê!Ó"½#¦$%z&d'N(9)%**ý+ê,×-Ä.±/ž0Œ1y2g3U4D526"788ñ9â:Ó;Ä<µ=¦>˜?Š@}AoBbCUDIE~% ô€ÛÂ‚¨ƒ„r…W†;‡ ˆˆê‰ÏŠ³‹˜Œ}bŽG-ø‘Þ’Ä“ª”‘•x–`—G˜/™ššê›Ôœ¿ªž–Ÿƒ q¡_¢O£?¤0¥"¦§§ý¨ó©êªâ«Û¬Õ­Ð®Ë¯Ç°Ä±Â²Á³Á´ÂµÅ¶È·Í¸Ó¹Ûºã»í¼ø¾¿À Á0Â@ÃRÄfÅzƏǦȾÉÖÊñÌ Í*ÎGÏcЀџҿÓàÕÖ'×LØsٛÚÄÛïÝÞFßsà¡áÏãäMå™æçè6é†êØì+í€î×ð1ñòïôMõª÷øZù«úöü:ý{þ»ÿÿÿ€€æOÎX͙¨~Í´Ú™~yœ£~eƒLÆ~…j…þ~ÀQ¿€c=9€üÅ~|‹4äµ~c‰lÌ@~]‡Ì³š~n†fšØ~˜…C‚~لOiZ/ƒgP®¯‚¡8€væú¼}6–qâû}0“’ÊË}>Ï²:}iŽ^™“}¬Œ,€ï~Š ׉_L‰p‹´²‡K­-~~,*éü„~ŠÄ&E()D9ÒvüªyoŽw¿yóæÍ=ÓTS3ÝwI÷!¦D)ŠJ²ª%»­„ßOBvÿ‹ïwýN6ìÏ4àø;ç>ý¿FVWíñÑm¬Ž +Sý^ÖD±iéÀ*÷¬bPk‡ÙÙà†ÔÀpØ©È?³%"È1ˆ#!ϼK`ùµŽL±<ín-eª2*þÀÊ+Ý) X䥂C@µv2l Q?ñþ‹í(=ì0Éqåç½ Mzï«ÇƒIãz·¶¹¤7MEïY;ª¦ä Yµ¥@K (×-ì¸\ó»÷Uðù¸Ÿýžºõ&>©røäðŸIª^»¶ï“2ôò¢ÕIãMe;Ya•àÛ"·ÐVà®Né½,SÙ;¸²oª_%sœáD;»õfÞƎ. ±çìãR?l ;0Dq¶>´™á8z‹DÎKG)ò3oÁ”+Á&ï<4ý§@n͗0ÏEÐÉO¨9ò4©‘#ÖçҐµ°ð nƒW9 Âb¨å¾_Þ‡7}B¯2±yːvú„è/ąJH삻Ȧ³Õp$±È«ވy;ØÆÈÕÉǘ¯fþþo虔¸F¨LsŠà²I¦Ž‘,Kh€W2î!¡A˜×jHE^°Ï„ØâÁ¨ _ÛwÑd¯lX÷gÔgÁΩr!jU)þ[%ÊB¾†\D¿ÄCf‚pû <_€Ì\?ØkŽ,.©¯ë†wäŸÈ²ƒ²²¬irJ·Œïä½R›žñâݐ=>0Á+cvØÕñZˆ{HlÓlÏLÔø×VAåc™Û …ù‚ ^{6oÌCҏŸÎãSõˆäمðbȏã‘ï:sz à 7ÇjôP@ÝQ¯ùÚÕË;[Øw‰g“|z3Ï0Uq`!ÏP¶Óîž-~|ÜôàX·3ô°+°z2lIђ¼¨:ê_<ãòÌØaîXþ’S5\}úçýEÜ^…ÿöîGêÑè +ÉXÞùJ4†^¿Æ¬w¤ï¤/€ûI!5 +Šbnñ#ÙF§Œ‰Oìüý®æÈìŽ`.ܙ‘-âJ\Õ!gZ0¿ +)ýÝ¥q A߀«½O’°kðVÂô¬Ã^B™Ûf8KĈza>p-Fð„þOÚJ*€ŠÆÉYr(º—¨".À°Ož˜'š±ýºqÚ䦨ÚéfÕårC¡üRJ'–dc~¤‹híÕ!€Î?‰`ƒÔÆ}WÑzBd;…hѲG¯„ϲåm½T •ÖSAi©j9š<î „ +ߨ×ø%É@`æÅ8xL¢®T­qė=¬,Mk $hJÔü®ìöd˜ôÓþ€x_§r¢Ì°gʱÀ­ht­G,ÒK±ÝytomVK0õ¥¢¼XÇ?R<¬J%žämqþ–=Џ ¥]ٛ¿“aÛò`sÊ Ç7ÕàÕg&Gr§ŀç?>ÝÄr&Åz`øb>&ø“ôz¶Ë%¿•sxÛbwì®&å{ô~¤Ú…ÜÈ]"WÁR©%¼c"z•D “¡ÐãzA ´Ýýßr¶™Æs!֝=jcf]­‡rm“ýA¦¡NJl$Îäے™#ؑ é>ÜëøwTfáGF£F69¸9<×µ.ù'S³Z*¯Ëº#½-ýJl.ÑàZÆZxä‚%m*Ø|ìÿùÁí ño± Ç2Ðӝ_TÚÿWÊK4™eRsu33'jRF–B¾ÌþüWl|ôÿ +ÝíF§øgml0L×1¥, ©œ—¯Ïy¤+•HuÑÌ2‘‹f;Ë[¸T½0BEÍÊ{Ž:‘¯Åqn¶ø´àõtoÑT†]o®´”•–úkI, + „îLgV_R:­Kϋ0¢dêP?= ËÆv¿ÀE̷փ(M4èm”‹šÖ\—ùT·k׉o–ƒ´”‰,ôHœ§=³Ãù”‡¦Þïé¤Zµ»w/³®E½Iñ-LQ¦ÿµ¢[ú©ùÇ ¾8¦F/˜g֖'$‚?‡[òçu~fÄgõÔîhÜXÒjšñݚ-³ VIñmíK˜ÂՀ,%išbÁŒQŽþç*e9à7‡·ˆƒÀ—®ÏèWK«‹üÜM™YiHtÑXÆT÷¤ÅBUD”ÚúwÜ-Å4ïþ9#i¯Ô—/ñr]£hGވÕ/¤ + +lD2 h§Â‘Œ%TTòT*FÞÃédw">ö­âGüðY?é"ì°Ï[f r5ˆÌʊ4€Û`ÝùTAoº‡4H5”rWôS¨8ÂÖXy˜ ;$YrŒÿÜ'‚q ævUPñåV&Š×çèÌ4mù/5LJ¸òEÊ:•ªSË7Æì’HvŸy..ø› økâP¬X¬¸Al…¢â`Èå¥ +Ȩ,eª‘: EÁ$@B’KrÉå².!{A$AÂ,ÈCåY[EA;|Š TJkU>°ý¸4í1aÕƜdžcT.Ð×ÿéîUs Rã&ùBc±h»R¢)¿‰’¥Ä +† Pd;‘ÆÝʟH«b¯‡ŸÄl?1;_Ñ:i»^«½mùMh9Ӝ+,—xê+(‘‡j3ö=P6uü>§¯a}Ú&¨‰¿bß (ƒúÒ0ô€®=ªá.À<ø’2&îmÎ%ë…u9¶’_ª~z¼Œƒ•­L½å!îS`(ð6͟>Õ©Váú”l¼ûW䨸¤m5y‡pgó!ì2¾·<îÉ PêR%wCý>èÅuþb€v…Õï«bšFñ.0¬¯ÃUKÒ$áK¾;¤Ø‚ÿPà,ž!ôrAÔ5­Ñ%\×ÚvüÈò"Ú +[2Ég”wãõdx©ŽJú±æ“:”_Ú'ßEښ_+^CژÌÜ íŽÞÂI! vüÎ,­¶V7—2UJ§¦÷Œ÷ìL­‚N¨ITUÒK×ɎIy/R+“=+(Ö¨§°Œ²vÇð6™×â°Èø·!Mܨ²ñ ¼‹@P¶B‘%…R-›—-â3’ì|4Ý-ÊÆþ”ï˜)#Í¯Í Òwòƒ¨á.ËܘŒ<Ç;”ü b»ä#‡’;*œ…>$eó†˜G£Èì +º>à3ÆêïÍñæ"íو~A•ÉZ¡±Ë$xOU¼¬x›ä äf𜓜x;Ù¥QùÐ h XÅ(îZ”¦·–ã²x=É`dšàÆ 8…b‘†i¿•dç, ϐÉÄ!îenZ +b°èî /šÞ²ÔÔІ‘þ ßÜ2ÁôPß0~‡ “+µ›1ÙbâaŽŠkÜþtTÉö ð ? g›)¦Ô˧¤9ºÇ С¾`.ޓ§`>'4ºä\DRdí‰åÜPaxԗИ°‰®¥?i|Ü9,¾t §¥Ä´˜q]•Œ"¼ë·m-¾9«O™D Ä'ˆ«¡ExÕ>÷#BãÄÍÓÎàz6¿ºõÉNkî%­¬tmҍß6BDzV®âQ÷GÃq,2ˆO:â× yÔ{i¾îHcy[]èvòaËZÚ÷TÃ5 ºÈ¨±R 3§ä4Š5Nß@qü‚G!ýfYXr‘º³ý{î3^¼ëëM7HX1­Ÿey«ŸƒÁ™õ²ëôÖ8´¨‚¶7ҙ;NðßÂü•ÂP9†Åtn§/Dê=ÌÅüñŠ}*÷ðIƒ:œý2s›Ì‹%‹óþÜñG{êŸÄ¢7©ÿaìbÍ“œæTÓB•m…6ÛºÒ4JZmüIçÀ׶ªFÑהzé\F…D*ríE²yΓðք¿ Ì£ÝV¦µ-ï8ˉi±Ú#ˆ7•æXmŽîZ®LW:2 +$Iâ·±d­`UÄ+¸ƒíæßzÓ3„Ó 8"}×åY\úE^û\Qñ¼íܵ‚³¦)<&uZ«!FM)V×…"çڟ}ÎÃçˆ&à/éíÎå ﶻ ‹­¶5ÄÏ Öÿ¬›O546ƒPWä눤0ð ÒfŸGlEýbd¼c ­´'œÆªžrûŠÓ¬[©ò{K(ÔÔ"M/y%•“Á0=²Ÿœâ»zFŽBx}霚{w6{Y5¹í0Ëóº%,ËÇ4ù0œR}ԓ´vTôp>¬K@¥fùR¡$Ê7HìU( ¸ÞÅàªÃ/1¹¯0’f<,È÷1äB§S>¨ý˜Ù¨RI3#&ì&ÿÿ´pßaÖ5j¬àé•Å1€Ð9#yTõ®õ±H†9cùIÀÏû[ßÎÕ§Œ©jÙ¨’U̟Ã~á¡?óýÄÊÖ À+Ý7ÀÞNŒzMÕ`k†|-ækËqJÞ}(Ҙ2¨œçþÊSØÁaÓ¼Gài¿ æ;ຠíÊbË:`uǤayU“}T“€ 2÷ÉûòFtmâ̔%OpuDìÁ‰›ãU0m~L-_°¨·±µ:ÛqÞÒW¥²gÜ0~æhuwÞ-] NVº‰rPå =<×]x;Y×ýÎ1Ëiw@á­í8,áÝÐnœù™«\(zºÆq²¸ö‹ø˜„b“ !$zB³§&5d©øníÈ6ç1Q&ß &ô «ÊC¯Àu÷Ўy#«À†­c%$7ý]w'z\½‘×0Lük{8 ú;ªËfºG‘Sè —Fx¬P‹~ž®Kƒ’÷†Êm %t3ÒM÷ö€êcúúcM(¡ª¹bCÙB·§$ _Ú œÈJ±,âÿË@ø՜ †¬%Ó¸Zš;ó‘˜.6„’B˜š)éPé˜é Tï~¿û~÷Ùù:_÷«tH·NI¥TØS„‘c„ÖΤ5Ùýþ_Ø3¡ðšÂb¿Oö6É-[o­ Ã7ÿ$ý–Œc†nú•ú“:¸zN‚q–³n¨E2~Œ7\NíöTº¨ö'ë ²"[–fTT°Ë^2Fþ›©í©²&µ¿+¥Ì—ô®ác5r~ԕ¿Í(ôìÑ÷jæ÷é¼ûl 4´8mWDC]X¸#Œä×<˜¶ñÇn”_ ÖT™¸ 45 øC0 V€‹~ mñ€&AGçAø¾­ã7w¦¬Žø@Ïw‚«ØóŠ;˜½ÖQ8‚à îQ³  òä´?d‚ä9¯€÷#1ó·yÊ•q¼_eS]y|ždÌ*Ø&6Q¿ô3 0J(¡WG>ÂHêãËN§ vøµ×Ag÷¯+Ü[éo:y1ډ²GümªUVá'p´J{"„¥âíÞM@3íåX­Çÿ|Ëñ*ñ¿oƙÑޞÌ%sfJ¹<·Ìߔ§ù[ÓþÎß-0R'G äiÞ++q¢ãNPFæ¼\ÅÖÔ&ÞíàXT~yýkÎPÉxÉ>®¢àŽÂ–—ýŒ·ƒ›þç ~u2LX'»äP î MŸO±W· ÇrØ© Z?qöU·ïäü·\+wå>-”q}y/sRÂQQúú÷„ÞJ‡Ó@737ÇÊîK­a[tÌ·š°»›„Eû8X­¥,œ›T¾ÈÑñpý•°¾!ëã‰PÁïêVûK$³`ù¹üΚì×µœbÇu~*LàìlB¤z-ì÷<ËR&,Žœ+?þAP«]²oœÅèãLâKžÙ 'y¼¦¯ð ¼Yý?± +~”t-"XÏnÃv&Ãô­°ç„?úøÍÀVAìG³˜+¿‚™¢Ï7¢WÑûÑh¤KüµDâYùèZÄ%4YF¶g£[öÐ äÄC_ÔMæ6ЅLJ®¥!˜¨)¯9ÍÕ!6ÔÛ-²‡l?¯@œ±W …Ÿ³?‹t`k¦;Ýé½ýæpŸö}ý +P»ç†À>Šf†{Ë’i8DbÒÃ̯Mp/Ų›FñÊ_<`w½[ßUèq®°. ÊÏËY!é'i7ÓL'‰ ƒRüz$û‡§v]²cÁ-äÞ©%HYÙ~“ٕ­ªç Ï鞀ws{)WðaÖñ˹Ðúԑ`è¬ÊùØ{¨[zÀÎ ö¥ä“Ï¡•ö½Á¢Z¨& ­èËz +-ù† ƒòU‰Ï@uÖBP.8›jz …Bä£{G tϤ1˜Þ•q# Üßò¸^×oÍ2†ªN*`®D—èZçm錞cß@QYîÕ@ÕÌðÄOàÉÁùžy`þ†Å•^ £Í)ÓH¬?€?˜Ês %Àý¢ðÀJð@öf»à-ëÞHˆ%ª{#}řìPKn@Åu±5w:=ŒYæX9ýŒôÒ(5#p ü9#ôô½AÄv(~”-Ñ"]íQb'ä ¡y¦Ñ÷a +­¦Æàè‹ÏÉ'ðÏ玣· +¸ÅvO@¾Ù%ö7_ß*Z-r*Çé~z Ցê 4ˆŽ!ñøwÄBp‰°ÂõG-q.Öa+Ãî¡cÃÃ"wmqk=½¨ÞWfB +k^ƒ²«0‡ø¤>n‰puŸ5àÝ㞃= «m]0oüüÊÄæ-1ô·:ǒ~ê³ô%ui¤„¢;ÕpÜVœ”Où/a3’î;0†oó½KܼL·—Å6Ÿ¢EÎÅõd@þZU%¡{ òñÔô‡±^Ø Í°ÿyÌO‘íV‡NHLm®¢©uƒ?ÑuM¡äB•EQ1\úIُOéu¸iÎ@L–’‘ï7‰Nk\ÝÐddƒ [i‹|ª¯í‹ÆlRÜ°¢è3"²ú¾rW^ üˆ +¹1ë°Í9ö~±(Vì¶ýZQjsf¶ü•b÷5~Nlï, $LAE ¾±Æ\ù–ÝûY†vÄø¡‡3kŽô"³*ÆÆIežö´¦.²gj4uœä¼D•’k"Õ*TÜ~~ˆ¬œgˆ^– ò›~½¼<|ƒ1â­c©Px7 í‚kFÔ84‘K(/AIƒ\%óH©âG;‰'¡â6‹¾€æ ½à`kK’…¬ï +Ôè¸Z¯J¤äAÔFqµŒKšqÓ$5„GT´è#.öa<±ñC]”s¶zOŒ£9ÇÔÕÄ@yQђí-–D¥RPÒÇÉßGªD{˜Ÿnš¦ªùoˆ«^Â7é°PµëvU±vºƒ²ôT_F"éT‹Øe⠊ñˆ^‘9ùì¡^‹9®¯É(Zi•í*³¢”JŽ|1¿"Ë]º˜ýœ.˜g:±ÆE¼TIÄFzNõË÷%T„|ƒk&ñJ´lÅÇãIùõ3ʌª+År^¹qfŠ”SNM‰‹òX»™eÝÆ $’vî{ò…ꢫ?I¬Bð-”º-Oi×0iX’oª È葚T\£¬Å.%kR&-?(ümš¥=ó€Ôþ?~3ÂJncu ¦/·mS<ìøÐ,»ÙLeØH:ëi¢_+MSVüaù kò@\Ѓ*ÕÃ+w¸­qDS!h”²e +ô4€–9"(hÂd}+ɗ½7Œ°)T« Þ b¹ÇªÔªhmõê`Y­Õ»÷ÿ ís<ª†-´,@˜­Í‹ÀŸ‘þ¸ÏSCg—ZwÓñN² CUëcªÜWš’š¤Ê-JGm\Q²ìA]Q†]Æh&D‹¶0±íÐZvnw %’õÎá0†°zºÊMT“XÈI¶ÂÉò:¤Ól¿ŒÅ<›7åaÍ` çù™5æP` ±Ý°Dh“k?Ø(ªbþø Ÿü?²`Fº‚gÝÏ—ñÖűàîy¬¸À=î‹4EJ‹í­ú0 GvQ³O4À©W²‘Šd SAšnMÿCäÄí€ +Ò±|`ïŠ7ø_·ÎvY—£¦Io©«ÙRÅyYqE¨,Dò;É&Q‰\éBÑxWì¡rÀ‡­v tÑ Û[€¶Ë\"]£º©ËU¬ÐØˋ¥ ʤÅâwÒ髐±<¶ |Mc+…éÂåç ÛZê¬9Ú(WZ¦Ê³Í°Âäf“ïø¨t‘Ž~X)†Uái—á?¤m±ð;1 pš't.t-SSUn;Qñ›à¹Y(sўè§Ð*ÊMº8=÷œâ +BHZ# ƒ–GcDáSŒ¬ä{d'Ù,UÚt†£‚lÓ=í´,}¼*–¯vËcrÓ+Ð]‰(_ý1rœÃ˜@?A[ã˜ã±K£Dl¡v'”oî>=¦ëԏ’‡ÕÔÓ•[‹µ¨?úQÔ ¤ôn!ܘå€ÚÊeÖÞæoø…ÆiÇÜéB]²u3ùˆªßPzP'ߧ–%•4É4Qw‘ Ñ L7@ì?;ˆgSVjgoÞhoùpê7í´sy‘ªÄüRö\7”ø¹äˆâVÔ%xL| 3¬nëÛ|å´2Q|ûí-ÓÜGo¯tž©uÙV֘³Gkî}¯©fdã'å‰Ì°yQ/;^¿Ò+bÆ#Û&™~Ìôæ„úي2‡—¹¼(ßÊ<•c 3ß;¤n`9ðã2[Lqztö.˜ÿ)ô<äÍ×ßlJàaËnìæš X>ãîɚÑ×pöòTֆ‡ø)Òð$œDrƒu:5¢zøjë,|·~›û0T\~È>®*,6Y +]è·7E9!À¡7ùëÂ;aˆ—¢ÕuŒ*Àñ­8Y?ÃäÒ¢Úã#ö±¦àWñfÅiAö~ª\âûÐmB\ø$ôžOÒwDh°E©•16:_«ºçÙJä³ qBšùR%–Ÿ*Xð÷ø3 á!‚ýO»Ëþ:Ü`Iª»è¤š©o¬ßk×ì2¦+õ™}šYñºü'1ß%Y õG¬‡°ÂPMJ{rK ´²Ùæüwà˜³¢žµæ_‘æ µúL¶&N¹‹è‘óÑ øNñyA'…Õ³mﺾo4gz"ëv;L® j•eΐ† %ƜÌÃê{š¢N¾S6òÿU'*ÈÍ@†dÙÀÚjNcÏÍvêo^=‡Bi ­ŽÉ7¹95¹©Ïlµ€AÇÀⶫ62ý7ùIÒØÛÅCçkëyV_}BÕË.I=ëYR2¿ÂU^ÿcê°ÕÌ~÷oîß\Ƙa3Ƹ2Œ«è@e»ÔæU*Tl©çm«cÕÓ±½ý¾Ÿïå~í x˜¬¨„–ÿn’ÂN¾îú«ÈÚïûU¨Ÿ)o`Iχa]é¯ÚþÀæP£³ÐFÊŚVTC&ÊÏ£Ö࿋Yè=ßd]/æ§Ã.ãó.FÈBX´s+$íé=­}buMÃ>‹RWm6“Å–6ᢐÅFX ÷5ç½x{v*ñÇØÇîýj;‹zv­²<½¡¥_~‹ú•ýA¢”VUJϐ‰²^IjˆQ…x‰ï½¼uÂQ¯oÁ=l°K§_ÎÚՑ¬EÒkZ\4³¨sêqU7¥ÔvOa ëJ?èÂQ)›4C«ƒ^ŠÅÂì\ç¤ñk[{»Á3½¦y¿~ÕõÔMí|JµÍ'g¹¢4Ay,$µ0œ( j§H†¼lò:Q"V҉”1X¡í&eº½©»°ƒúí© ùs)M•Zœì(éW ×|ÒϹÙ\¯‡ò8Ñ8&ít³ícýp¦ÓҔÞÞaö ’ê…Í”«•‹ô ò­’C¹›CŠ GU®$^îfb¦·³|8u´ÓÈ̸ÇÍûÇ&áÑØA֍ü9kÕe€7”;Î㥦ì…æñk¢oÁ›ÁÕAv¤úò´…Տ0o5±‡Ÿöyœ'ð‡ò—Üø¹ŠÆ€ÿâ<ä!îÉûÁ¹HôÎ÷P’4þˆ|yÆÜCÈ{_³2eî§ÅlTrÉsôâ*¥·Idg_à¯'V +Fvz|"ïƞ¯¦Ò©n2=µ3[ï°"s¬¥ŸÙtÕ ù}Nâ8«”ûž`†ùñÒÌ1`X¼iý]àx¬£½(®U2\o[v1·d%JOO&rؗ´ß0ܵ9³YxÅݨ \–´€¼D‡m§¹ÖÄ]=Hßjíovfd—¥˜)Ì:ÓtíbèdH9\”Øϛ®YÉ?«8°Þ <%þ}ÈçdV‹Û•hšÁnuŒÓ»kV˜¶3+ª¥(+µ$ŠÞÁ-¼›¸Š‹ë¼#¯ð£Õ‹®‚QÒ°ÁØì·ÚåЖžÙãX@ßâh-NdðëÜ$Ìa«š>•M3¿¡q—œ"yÿÕè$À[YÚ@S¶õšgÏÓ=ݎÆÚP‡³±˜1·)L<Æd×"´döìrՕsÎÈÝñžW¬í ˆìDJÿ +tÃýbêÆ µcèj¥è*º!®Aq +hGÐ|î3j zŸO‰ôÀ¶öú|·Nƒ +»°*ªÏ€› òÂÓðÔ%2#ÐǓ™H¼7!¹ ;v¤¡‡'ì;äéOð­ôëÎ~hµÄ¥î%”,v6ÄBÕ¢ÕÂTxŠðDv"Lt¤Ã¯K"N#œ¶.ecÍ}fÀ‘˺ŒçdÖ&ƒTÙù R¡øASˆ;Yq!óþ¹ö–¤E,ƒŸ‹ëü‘AAúm?~•±çÜÌÐ[ý7ªÒ[“ö> \¦!ýB;U¬ø!ˆ)/×À»¥¸ÿC$NøþÖ$ïAå³uüe–uU}ü,3Y'äß/JÀœcùð .8_[O¨Íá®ÐùN-<"N¹ù™·¡awG¨…mý¼_+•yj~P™]Å¿^\y¼ XÀÚ,r-¯|à㒒›¡Ü³ííã<§æÛL^T}½ö,Ï^eDRø»,êãn€kqց%Àë|r,ø!gÿJx´±×Î=~ép{"·î\ee÷E«N;“·ÃžŸá=©òÊ$øöÒ{q@Qá¦í_À†\?¿/иLe–´>­u£ä#²¼M²œÉÑpÄ'Y¶Æn²_e<…q㼅¼±íRa8pÖLB“=ƒ’(àYK—[l¢«`BK´´‚½B#4;cŠð;HñS’ ^±íOA<è·J°¹~¹I4,ºÖì$"‰œË,B\HV'&fಀ/pO_*ø¯Û_‚_Ã#¶¥à&l”ôWcÂK B«Zí(ü¥|Zú½à b“ê+|°ñKpTœ¶ +ÿAr3vŸ*>¼õö§ð>Ʉ½x\œ+¨0lk¤àïôçÍOðÔ¼`ÅöFÓÀÓcfupê.Œ®øwlCÄnÍÂöKJIi]¨ïšÀÊ&Âðõf£©³½äXPA·ýnÍ1Ú©©©FÛTK·ÎBoI!èÑÓ®…øæZ£ý f°)~‰¹XÞ“h™ÎyŽÆ¾9ú ݨOñC5§¶´¡‡&Ò|´T2«óÖÓ²¶¾ón˜SLB5eD0ºØ:‹³yPÂ;…Ü(ìßwéÓ9m¡¡ÎªnßWhŒÔåÂKŒu¾¬Þ½{Ú`”£wØk“ØùÈÉ +û‘kH¦éÍ>*çÚ²éÈ1ùö£ ¥wÏp5õ´Èê…êQº¶àªÝŒß$Š;¬ÌÛòLvvJ1ƒóf¯›ÔÊ3nž*ÙäøTŠg@oO#9|}•¯ª˜?V0Mù5.‘Û€zÆ{" NÖK?C”_$ PÑ&B̆e>ˆ(q´ªIÁu›‹ò¨`«þ£|oùb|ã_²0l2©WꂝßsCü¦Ü´LT÷Iæa?µf(/+¬ŠP¹Iw‘¸B WÊhÿg°ÌšH ¼»EiÝÅ®´ ®(G6 +¢€®‹¢" À +"(®H2™Ì™™dfrß $ˆxàZEP>ŠÅ£ŠºµúéÖóC¬ÔÇÿáû~ì׋EÎF½:}< ï\{ +š„‚ƒ¢%“àø± rHÐ6N$(ß«Nᷘ_%ó1š¢«ƒÑ]²2Î:$ŸÈÜØoƯ-†8È¥ I-qt;ù'kŠã¾TjJW^Â}ôkÀôŽfQUr\ùuî¦lôƒNkHn᫂æH¾‚÷õ*‰W¶ã¯ø¦˜Æd6™¸M2 *{¶®¼`ÌV%¥…VR£oJJ‰²À÷`+"èyO|s8ÙÎÃñ®6ÅVÌËy8‡ µ:+¿‡˜;ÄÐ9Ýî´ɨÒ=Ú.q“qŸ‚›Ñ=¸ôàÉ¥­ñ¨^ӏöw÷ld¯‹ÞGÁ­å;<¡bShÚ ¨ˆ®(÷ÀÛàŸ±%]Û çªN™}uAܹ² õ`MV󨬵—?gê=ò&¨o:R¼ÉãüÒ(£tWS-{66Cð¢S¥ø ‰«ýšÿ”¤U®ÆÜfoEIã½òhzEœ'ûܜ–¬&úÁQÉ8,Œgÿ]-2tœ×%€ÁF@}S|†èQJĜ¦h&S콧†bor 2wàqò|éoÀÃÈÏØ/À$Û Ĭý7´AÒ£±êŽIÛMXIc>Œf–¹äH^Î2®Ø`•zBÂÈ³Ø ÅžO€*×{M2MoRŽ0øi†¦¸ü:ªTï~%Ë$œ9ED~cÃj<}‰£ð${.œ-ù—+P]cœÐ=VzëÃpwz\SÍ;!?¬ìØC:èGÛF¤ÝòÅI×±¿q‘YÈŞ ݇>;ÕÇ]„‚¶ý†m§SÌ)¼yr½¥ÔEz©_n˕²aI"lµ|säGºŽíð‡öªº®vm§Âßµ¤îØ_7e]Ö­¥>„ÓГýÿUý)i:ÊøD΂ÿGº}±V WÚ5*ßÞ{Úfüà?Ñ +ë(¯ÿ$Ëp\)9D$ZYÙr|§¾öçç(¨4D܁OÊH¶»äʳ ;Ü«òévÛ±j‡xÒLr_rû µµ©;Wi·Ô nV¨|ªRé›üu«ÊdܦÂ;þ@ðÈÑú–ç YÖNþÁl-ÌQôÈïnJ¦úȲ¸cä/øÓðËø14™µÑC:Ã'K£&‡ŒÛ̕BOÝJ{ß´z‘fŒsWñƒÊ|F-§Ùq2˜ì ?Š¯Á}Y[pXdY<\‰ävÃ+ǁM{Á¶i©rš¼8µÌ~í£LJÞ¯´ÇŨ ávlL:ÀÚ ?@Ö¢ÌoÓ[gŒ`¶²}ý>?Ur‹ǛI2¾ËL•k.Æ}GpI8‰QäRV%܂L0/PU³ ûEÕñ ?´É¹TÙÂcÍÛ¼Ûf¢HÓësÖÄ^QMò½C!º¤)Ã$ ‚; Òej¸ íuIy õWïêîË6„ÏÏ#LÜÆMi9ºÄ¦Í±å«æšPœ*ŒøHˆÊ˜…¢FÉgˆ]Ÿm¯¾ßnÝ+|“·ÄX$Z6K'Ú»OñQÔJÊq Üþømì(B~—ljçÀSu‡Z áÅ¥–bhW®ÓP"¹žz@³U’»V±¼JÈ΂\ÿ,<\H»¿Až ö·5’çë¶ÄO¥af΍ÔC75O ¡þ±ó˜UÝ®¸xà7€óÌõªF›õÜ>QöóL‹ª~:Ê¥ÿ#ï]ð[eTSì2»Œ%…Ác• žüÔÆ~EWמgØ9ÌÌiíå÷%¾3W4ފ: }Þ¼0Ä_ÁX|¡¢-ðƣ鵼‡„‚ÿV”u×8H{»àßYêF¸"qĔ-´F95E!L¸èŽ/ŸÈÁ3z„—óLw@éå“"‰œÒF‚Ÿ²Rm¨O´·éQ&õ[Ð#¤ŠÎ¿ö–ZÅO¡î/©xðºË¤Öró~9žT0ä0b³³Ü¬ ò4±ÁPߋbÔ>_nMFY%÷ý<ñip +Ê;R¯xÑðá@ý¤|‹ëŠüqj#ßlºjù?Ape¢Ü[Çۊíx¶{ý +ÑsäHýt-bM—#¢²¥t8fÆÜß5ó}sßcÌÁ0†f0 CcB¤KèRê•mc³EÑíµÕÖk÷ýÿ×¥ÿJH×[ÅۢŚéžãýMOÔa±î†N¥$ʡ˖~ &(Ÿ‹$~çÅ>ø°žü–tÕBM%^i¦Õï3®¢Ï§Ef8UB ô¸ƒà™ß'`-èicIaͨ“ô+°¬ ¹Ø¯Rž€î†§´= Z¨¥Ÿ‡¢È¾ÌèŁÀ=¸5ÑU#ÚÈ5H«îþâRžûå¤>njky/§¥¦Œs6öÑH؃âE oLº†y‹ÙþìCßGØà/¨ñ?QE%Šá‹Fâv¹—MMz)=ZáB.ßçϡƋèÄ/ô¹Â•ûç3¦ùÎíûO¼èˆ8•Ý5&éY¾ÕõŸžKìÕ¬(—STî e‹ÒðŠ¶ZV•Ëð‘x'ôxaVø4ÔËÉ*H®]z~¸h~ £i0d,ÛKëý8ÍäCZyÑ{j¦êCF')’b™|x´…ñNJ>ÇVÞ{½0Ùêeí#|S—¥ÛEì¯1b狛*_…RÚË"÷Ñ–ÆÇ37ÊÝ€ÃBßÛâ“oξìõ(p¶3_<Ý¥%-ãèt±·É« B÷eÐòtßƓ·”px H¥ÿuRuɵ)H?§mü©ð£ãŠæÁf@£IzË͂qrgM_æõ«þDü|Ceû +†ˆÓ¯_–ùw•CՄYK/¼–Ô¨ ä½¨/²“êY0ƒ¼£ý–yŸÕ̸7Í.]Â*ѳ°þÚa Œ!ëd™[ëm ˜9­„Â#{-ô;˜Wà[¡¸Ìï ·›UŽ$‡mb?ciŸ3¸Ø˜s’™Œqê6ÿĂTÀ tùÖ }ù® µdl†¨êÇv¤å­{ÂF©yt/Ù¼Žtú„¤ÇÜÌ°‹‹KŠ™Q8Ü°„ Nº"þ‡½4ÈÊ»ûcü'׸NÏâs6ôÿI½« <ó–fWϚvЕ*§Ò‡ÁT² –ï9á ÔI#Ò{Á ÑÇmVx—@µ. ™åŽ\¹EyT³©}€ÚWå*€fÒ¿S¸Ñµ:'ØÀhP³ofŽ•Ä§/7ÈÞnÛ u‹3Ö­FèüÄËc”åÖȶT—úÍ5멦yòŴѪàý“žLÂÄiÃӔ€¹¤%vÂI‡¾Gæ —ɒ3îm?PH-k« ©;?ÉvÒbkk€ôãՉy“Œ^ýÃ4o B[Ž*‚BoÁ¡åR 9¨§Þ^Fñtþb¼Iyd¯’š¨W›™$ګږ¼ÆNãêT3óVYzl ((ñmƒ‰"Uïa.\˜vzŒëCˆ5H8Hó$?sZŠ6Žœ¢=:ÈhhêB…!É8 +`,ä g6ô$cNúŠæ!LÄp©<Šb<ïÀ™Nz;¶0y%€ )°è"Î «DÜB@Ž ;€.aÿÒ$G=ØW+²ØïØvÑFöv-­‹ý…Ý|d%ºŠÝ¿ÇîgOŨÐÔ;$KF“»î²lbšu#«^$(ŸbÕ ¥‚,‡ ”jdMð[sÃÙkx÷vÿ͆¹ïc–³?sÝB–¡fl¶S ¥ÿkø€ ªMe͈Ly˜i’Ã3òTZuøgÖvñàî#¬áøV'{ÿFð,ºË8+„5Žå%\©ŸÑY`kY o¾­ÙC¾ˆ,VQÕ"˜B½k”5WjؚÃê aëx·­ÐhÝkË"è© ÕA³Æ›Ü/ðŠŠd˜XöÃ!xJ±ë(}¶~ÏÚ&¹|–ÊÿËé íh‰®?í·¾Ò.„òê¸ñøÿÁXSàªçÕýqX×}|Ö#CiÁchÙK™ÈVF @ d’·w^ÞËNH L +jkÅuÖjµ­³ˆV´JE)ž­£Çý¿swmºü^ ´«VQe¢’^*ð…¡7”cô¸·Su›5Ô.›:’Õ5!{3°A/—ýu@vÉ?êaD§åUNCþkùŒH2)ú 1¡z%­9ì­U鱛ý»éÐÊçvò¹°—Ë!ÆkšÕ0>][#À?¬wÏsb‚÷Ä,4U²á¤_ fà)…ýEêďÛ* uä6Go7°6ɵêèù¦{¹¿ Èæ'C¶É‚Ga‡â+Á¯ðRUõA=±@ù¾5_ªrgs1OU¸ŠGÿ£*ŠƒÊšëO¨&øÂQÍ¡Á4ÒÜ%¸¥©×€°nl¡c=ú%Z¨ ÷v¥Y ÿZe‚ëਝ4í‹? eC‹ƒÁ—`…àØ Þ_‚ªÙwvĦ10áKÌB/§ê*BrâvÎ4όwMèñ  0ù›à¸rë“ ó³–`ø¤ñ$½Ðï’÷C‘ܝŠGàa6;g-N_&É° .` ¸`ß0üØùM/s\¢Pœ’MƒfóªŠ`p‰¾3ÛìåÖÆå $‚ˆA7° iÚç —î¬c±û(y <ÓNÉâÀù·ò6¶ôe/ü ëcÿPOj± mê+”YЪCËzÏÂXa-…¶T‘Ñ`ao¦t°tÜ._ ,qgõªO˜ïÄöªI]@«f"µ ´?4|T¹]ÿT7[úr¾5+í¬D4UffNÕ]Ϭ¦ç‹'¢Md’dõæù¸YÚã%A'-í:›x–>œj˜‡”±Ó Æ5!’U¥iMSDÆ-rBŠFL„É&¿ÁÚÍ^:O•ãò…F¯-TüÆ4Šw ³è÷ÊèÒõT©²3c q]µ2ªRÙôdó/3²µùU›\;?åãØUp=ÔÀÔ@Óbê +TYRJ¦€3éÝøO )*+sWÀu¯.˜ê[ìL6—Ǽ§ÝAš. Ç귒ßhñ‘‚oN_…=Cÿˆ|€òHW  Gz}ýžw\ÒÜ2Œh{?ÝUàÅr_סä,[<§™¼4ÛDmˆD‘ø〷ðòú’C/ÍFÇlö MÙr_ò‘¹¾ög"ÇP\T‹MñIiÿD­¬wä$™ú=` öÆI¯Ó ü§}ÓßíÆ6Ò.íÃjYîx^›†ÿh}]ø¶Ûø"µ]Ëßÿl +¾«8"ӽ΃ǐ«öLúÁ¥ì"êHï”ڝü°k›è:^֖T¢Ïm©©éÈÆøÏ·.À‰©^—@1Š~qxT¼ÅÇlùUä¾æóÕ#U7‘¢Öü5º:ÓöLÎE|4â™&W2Ëÿ5e•¶xzãß*̖̆;õŸâÙÖMâ0™ÕdoØ^•lpm¬ÍëâaIòSö7©kD#Óùß'͊$Ï"lL­?båA˜ÑüDI§¹ò«•NÝmEhž —«8‘¬ÔŒ*ó"vÒ±ªEþßýª»ž¶ ù݌5Zž5‡¤‹ ¾`zÅ~xŸ[«MN&Ïaî|Äbª(÷Âǁ$Ïch¤ ±øãè|cq«)Mï‹_¨ðá¾Æ†w>bSО$ ýé ¿Dòp«¾ÒzŽ!G@o3ÇñƒÈÃÜÉa]PnÑN2);K4 U•´ö"¨p+q ëð7bÒáùùÒóËLíÖø…a“y¡$‚04”»iCøc9“Ì(û6ñ>E3aá{ˆ R䏡ï0`Ý?às0Âí7y9'`LÔq·ñ`SîécLr&MŸˆP.Ú½áü,ýÒ_†rÄÚu°ÙÁå/÷FÀõ»º°Æ=܏ÎÄ=1ltËŜ ô¸9>1Šlם +›ÁKX_ÿt+ ¬ €=‘çÐ#¬Ø«Líø³ +u¶uWçKìñ¢Ø̹– u)±F£@Œ†´ó»ïû…jÔRÎý_$ Ð®ÝYuBśöGõbQl+$Ö»·,o8“qÜl¸Åègš!) ÷ÛÁˆnî2QùãήÒßUÎ>YtÍwŽ(Ùþ¢^ëù'Y¦ÝòÑغŸ!…Ú %à—GËU¸û9¼·ù¾¼ã, ¿Ô&>¨YcwU­± ¨Mé÷Éj"æÿ“Zòo6VÝéWF9Õ=æa“Àl mÄyù–Ö¬¿šnqA/2æAäIºÌŠ¬Žiâþï +qÑÔAN?!9NxlÅbÀO°¹Î{ìeÙi‡Y“Q½Ì¶>S¸Òô€ZŸîª‡ .&ŒsÃÞ¿búÑj?1_ñ¡Ç¡P´Ãékœåٟè¿°x²`дY»!í¸n”ù6f®VJ•?ffãoýš‰n”ð0¡‰°šÒ6l¿)ó±7ØB¹u‰yMAƒÑ¢˜&×mæ>>ÃNjÔÁ#4J%ûÄ&|žÇòE]ۊ:íÒiû2g¢0ÀÒio*ð6zXŠÓÂø†¬h +æ҂÷Ò3;üšñ1"Æã2ҍÔ+Oô?©ˆ¨Kܳja½÷´ðÿú÷èY|£‚nßMHŸpüA/šLsI5§•cu¿*ΐDx„!W‹ {|m¯pq%ªØqeh¦rÁYb¢Bt M7»uA-™ +w%5»”,xë+ zî!Ί}|%­¿w¬pÈ©™xe¥Xx|Y üy$Mœ}yòA—Üzè5À“{ù+=Ž}5"6‰~‹{άq~„p^¨Q~Md¨¤~*XŸÄ~,L¹›U~S@é–Æ~“5½’ ~å+f2T"ˆPÒ{p«U…Ip§<„ŠdG£ƒÓX]ž¶ƒ'LzšJ‚˜@À•Ï‚5·‘)¬+‡ŒgI"ۇ¥€ó{ª~Œo³¦eŠ¾cþ¢,‰dXØˆ L;™o†»@¡”ò…}5³^„E+£‹¶ƒ#‡ízЩג–oy¥»ÃcÆ¡zŽÁWܝŒ­L˜»Š£@ƒ”Eˆ¢5·¬†¥+½‹„¦#N†¡‚ÁzŸ©O˜ïoK¥/–Šc“ è“ÝW©œˆ‘ K՘$ŽB@W“¼‹|5¨%ˆÀ+׊œ†#x†Aƒqzt¨ùŸ&oM¤Éœ9c l˜ÇWŽ›ò•Kׂ‘‚@V“Ž5³Ž¨Š‘+éŠ@‡)#š…õ„q¹£hÜf«µj’[Å°1lmPʪÿnpEÐ¥ip¢; Ÿs 0ò™Xuœ'£’éxzŒr{‡qD¸äo×f«´pÈ[Ô¯qñP䩪sNEñ¤tã;=ž%v¬15˜x™( +‘®zÄ W‹W} q(·¢vsf€²ÊvÉ[º­°wLP̨OxE뢳y +;NœÞz11c–Ò{v(_•|è ׊b~mq¶C|ÏfL±o|¢[y¬[|™P£§|ÃEÒ¡t};O›²}›1…•¼~/(¦~ä!E‰§pÞµƒf&°B‚p[Q«/àPt¥ÛgEÁ S;Pš¦€è1£”Æ€Ã(ãŽÄ€·!£ˆÞ€ºp¸´,‰Rf¯Oˆ6[Bª5‡Pc¤á…õE°Ÿ`„ð;U™·„1¾“ëƒ*)Ž‚^!ðˆH§p—³y`f ®‹È[>©fŒ P[¤ŠAE©ž—ˆŒ;Z˜ø†é1ٓ0…U)FjƒÒ"0‡Î‚op~²õ•7f ­ð“![B¨¼ÀPY£_ŽEEŸé‹Ü;T˜\‰…1撠‡C)kŒç…"d‡jƒpm²–šÙf­r˜=[M¨,•1P\¢Ç‘üE£SŽÜ;`—ЋÔ1ð’'ˆå)}Œ„†"‡ƒ›Î¡mfú»ènìi=¨µp­kq”êr^mœ€µtoÎlVuÚrX w¿tDyßw'0É|Yz>̾j´qźjlÁrä§`n­t“¾p‹u0¤rnvgkbtgw³WIv~yCtxÏz›0b{x|bÊùh§|~¸´jÒ|¥èlä|’^næ|¶~ppò|ój\s}AVtu[}–B×wÚ}û0z¬~lÉ;fׇ ¶øi† +¤9kD…ëmh„5})oœƒviNqꂿU¥tX‚BEvÿ=/·y÷€VǧeP‘{µqg¦‹¢¶i卞|l‹»{õno‰èhLpãˆ(Tâsu†SAÁv@„Z/ryX‚Æ_d›Ö´2f}™¡}hƖŽMk“/zámtLgdoþjT3r²ŠxAKuœ‡I/8xσ´Å[c&¦³5e¢[ }gܞrQj.šxyýl¥–†f¥oD’ˆSŸr Žd@êu‰þ/x\…ębp° ²vdÜ«Ÿ²g%¦”Œ€iw¡„y3køœyeøn¬—bSq‰’@—t Œo.àwý†UÄa÷¹ë±ôd`´RŸfŸ®W‹Øhè¨-x‘kk¢emn)›ÐR§q•\@?t@ŽŒ.Àw°‡ZÀ‚tÿf4¯uþh¦åvÿjõ‹xxm0xŠyosekz.qÐR|{itP?Ä|Öw-Ó~zK¿'rÈp{®sÿqԜãu#sŠ„vFtgw£wtu½dx¾w*QÏz%x®?E{Äzb-Ž}¯|X½¯pÑzŸ¬êr'zò›ssj{@‰(t¯{™vxv|c£wy|Qy +}>ºzÓ}œ-R|ä~H¼(o„™«Yp‚ƒþ™éq݃^‡Ûs=‚ÁuPtº‚;b°vS¼PPx <>Ayû€¶-|0€º»mŸŽ{©øo˜p‹‹z†r‰èt?s“ˆ^aÌuQ†âO¦w+…T=Ôy>ƒ¨,ï{“Â¹’lu˜S¨Ômü–—oou“†…{púùsGr Žlatq‹ÝOvk‰?=tx†j,É{ ƒ@¸¦kˆ¢ §èmžÜ–‚n’›l„–p—ÝrxqؔM`Ws¼¯N“uȌï=&xˆñ,©z„·÷j׫˜§4lg§ˆ•ÁmᣃÔomž‚q¿q0™å_¹s*•9N uI_<âw¥‹6,z@…¯·†ja´è¦³kí¯í•)m\ª|ƒ2nà¤Ïq)p¥Ÿ _|2s§o„|­u]Ê}@v¬LO}êxT;"~Âz-*æÕ|L°œy(xá¡*y«yr‘ z$yù ÖgWT€aË¢¨Ä®kTd@D\dPPp-HGÀ„&]¤30Àô¹½ß;s§Cg(†  1DE²*nº6ܵaïzê*«&šå<ŸÞ//6è± ¤O?ƒýQ}Ð0$ 8 _„·{¡Žˆ[w¨ ¢/«¾!f›UmxrIŒWBø”´5À(Öµ¼Š)2 ØÏ.$½Ý5U±o¶}Zƒ!O¹O“·ªæq‹‹mªÇÌõÔ õº>’>P‰3 ­Ä¸g| ú,ûXñ¦“ÿ`£ÏS$š>BG”‹ çDǕu†”#êiÚï#§þ܌-ý`­óœxJâò!wÙûÊúم:‘Î(‡«‹ÁŠ`[HÑW¥¿eQÊ2U‚áFDƒº‚‡¶`à|ö™§:CÍèd¥õŽ2Á~Tv­±Êkêè¢dEeUb2¯Ì½…èp ʠÿ†¶£½~íè[ô‡Ë@›šQd€³F!•œ7•ŒHÙÙ$‰ÌùŒäÐÑ Žˆ…Ú#—Èd¿Ltæ!BOáKš*áŸÌG-i°ÙäC–ÃrƒBú.ÒUålmO¼>Æ †,Bæ2Wü<+Õ3¡6¹7¡›µß›íÐ@µÑ ´)¤Û &KO¶ 0ޏûÏÔOþ igmúŠ82=DÈ É4FB[†ÌÓ!AãIb4½~—¤ü£Z—í *†â¤fz\½ÕOÚt®æF&”ˆíÏÁӝN&3xôàFÜê[®H–jûŠýz°¹&3n14µÂ¼böMá ­zB¹Ð!Õ Ÿœ|‡®+¿å +/—hw{ìûV³\lÞs—ýT¾jçgæ?қ¾ú¼â©ÛŸÔu «ê¹®¨D­}û”.ƒ5ïʺÄ(wM’ °ýÒ±=ÉL·üÄÎjúe³o(u\ý›» yÚPµXû³üžæƒÆ¢8ùp2¥¶¤©23Î2"uhì0 Á;ý(3˜àû-ybÝ·‘3àÑÊÕWd÷‰sFÂ@wÖ É,¾É8#åóè¿!ÆØH*9¾ã)iF^ +¿P7÷½DšgÛÄ3Iœ33D_Âè«ôºâ)ÔJœQNdOÌm2‘tØa':‰=ÂûÄJÜê.ÆÛ±¡ +sÞ`d³é+úuu—-Š ǵ‰i—ȵ\L +±kw„á/iƒð®&GÜ1|91É:Hÿ^ÙÈ£gWü¢ú@-µEí¤¯ifš?Q®·F?Â/óKvüßř„MØkzÔ݈uNÖ0:ӎ3BJ]÷PU@âÕ׊VV’z±¸D‹ñPCÿöãØ9>R¨ÅTl‡{=EŽY^ScíôyjNËå9Ûþ¿Â6b~mwj[™íŠ Zl'±d}¯°[¡YïގM¢:tU9‡±—óWI“-#…dî=ÓsÑ£½S ¯ÄI‘KuÊÆ·6i/JO{×sýŠ{®˜c@6o°©ŠP³U,Þ'9cV–~ÉM6²åíI½Qš1ÀWÉwoÍ×T+ã¼ml³ºF0‡î…\´O­·d­È?Ío䉳iº¢4çÁM™•4M·C%ŠHÑf©M[×r0pÑ[Ï€„‚pê|R»Â’¥Ã/Ld/_c8]Ï׍Àó ùYpFøKM(ÜøŒEwoŒ@Újjê£I0/¢¦Àkad[™H’>Ùþ|/ѓðLóŽð §¹|0ð0S‡ïõVRŸ±×‚V2C¸Ã¦¹üaˆÑv”é4x«ö,'LÈÓ82Ã'ú7âô¿&n­„Š&CÄ¿ñÎÍf]9é-f]i{Ÿè‹ÌT÷¾¤¦à×aéÎ4EeNٟ±¯¬¨äή"“VöÐ_ªÇ”3½Úµtõf6š‡ú5¥ÙÒ·µ¤,®  jP“úÑ6E‘«±x)ͻ֣UüSu©@Œ×6M6ødµŽ‘Àõˆ½®¨“FÔÌþ›ÏV€»SˬGÀÞØŦwÐÆ û†uÐyÿ@>.õŠåTȆÕ×éVäOdj­?#驺syc¶¿ãA)w,zl<æ¨ñÿþ÷ـ»B–*€7Ši€j,\‡©€P#„õ€;}}™~ˆÝr4–ñˆfx”O‡"Zh‘ †NMŽð…BeŒ@„(7‰—ƒ8,i†õ‚A#F„aN}˜®Îqǖ*Žlf “‰ŒÍZÛ‹ MõŽ2‰HB-‹Œ‡†7ˆß…Ç,y†Yƒý#pƒç‚9|½˜–•q—•ž”¨eےï’NYƐ*µMº}"AîŠíŠ˜6؈Uˆ,€…Û…#’ƒ„‚ý||—´(qW•,š¦e•’s—ŒY¦”!MŒö¾ANJje6ÇâŠ,…}†Ã#®ƒ5ƒtë©PcèjO¥ãf=_`¢rh¡TžÐkH¹šîm¾=o–Ùp2¾’ŸsŒ(ÀŽHvÙ "‰øzbtu¨5k#j¤¸lº_-¡$nnSÿjpDH©™ƒrB=t•ytn2ݑOv½)yL žˆÛ|t¦¼riŸ£Is ^ٟµtS±›ýuSHt˜#v­=_”.x02ëyÎ)B‹ö{›! +‡â}~s¬¥Ùt(‚o.wþº]^”«©©`c’—˜CcHl†Vf+Ž;t)i0Œaèld‰çOþȯµ>tsw…[-òwn‚¿¹w\-ž¦¨®_A›®—Mb0˜‰…ke#•SsShA’!a7k‘ŽçO|o‹’>#rሠ-Ðvö„0¸±[D¨n§ð^a¤Œ–‹aS h„ªdLœ%r›g{—ç`˜j哟On‚-=ÜrfŠv-µv’…m¸3Z¤±ê§p]­ •û`®§Ü„c¤¢r f؝C` jR—ëNŸn’b=‘qþŒŽ-ŸvB†wµ~o®`^¥£q&cc•rfBƒÇti qõu£kÚ_ôwInÅN1yqØ<¸{u8,-}py´mjy¤”nÎlp”ptnR‚Þrp/qsÏr_;u¨tMžw§v2€ãû>ƒŸ@?ÈnÀíòC)…HKс#èEu·ä$þ%à펭û¡`^>[» +ø(?`~¤^xúÍ0¬¬ÈÏ_©+“OË´§v&"YÀ˜DŠ>sÝ5x'²±]¢¹£«~¨Ð-ç€iÀfð¡~…>NF" P²ØžÙñ^O—ÌGî# » ëǖ´ªî ëª0Í<”7íӆ 7 :sÊÓÃXL’‡!kݱrÂÄçá×x{6ÜR¦tå"+·¨@ö‰q£ú*§7k—1Ç÷U誘Y‰}(­Ù~\HÝë`J䞂æ“à·\áµâ¼ +±ÒÓþ5ç£2[{Fõ;‹On·–çÛúÝ¦Ûà *Cæª{2H<¡è¬N-ßS´º2ÍUråÓu÷UKm¹³5ųBuœ• +}£·ñÏÄ3À!ãJ÷H$‡œ#h^Qv¾0ªqÓUô·ºY:‘Ê«ªa¯Z=V.ˆ¿ }VÒZ¦Ÿfsôy îå½ÝÃÖ§¹MîßÑP¬8Û:Æx-kîÕ¶(+’rÞ©ãªGãSµIå²Ð­€¥øºO ø¹ùw÷ðiιþ9јy»¸—€³Ÿ’—&÷†z8,kÊ.$†äxì=rmRMêï¼ÎRŽ€Øíu×Mb;d—íw0yÁ â2Ö¤˜Tý{¢œ¾§—¨WƊñ6m|ˆ+±8êEC`ð òGd]íÄMm²µ"ˆæWürS禜D¿ò²~AêÿSƒ‹‚»° ¨Ä+ïG6W#èÿjnA>p€ÕuÂw0ì‚D(ÃMHOÖB$õ™ŽüŽvKÑ»X¬—{Š½®'VáíÕ' 5ôc + +èshø]T4ÚIÏÌ ƒÿDµG§Ã£TDÐ(2BNlz9“eB_ Ý«.ë#­J³UÿÒbGŽ³ºÐôà¿É°€Œ¯¢ú¡ îPÌc36õ ûè߅!Ø3Š¬ü•?ào/Ë¼á ½¥4Ta1l-vKWZ§¢’¡õæAÁpšÉ¾©éã<„˜‚>\©Ð©æðހkía8¸Z5$¯GÊï§çd¥W#‡À{{à¨ß¢ßÄ! ¦eÂ8l&ÓVé¨lu4õèʚ‡ @Ô¸Q®žÔú¥½×÷WJ"­àçû׆Ò쎛’àÿò…)è9(©6gf ¦yÙ'ô¼1?·Jöî¡L)­ábåÉ¡ì­¢ü­©l’º]4ÂLþkۘëPpñuîï²¹ô)nCA ÐŶ+2d‹ØõEHÊ'æœêHøm&Y3¹uó õÑ·ÁÕkïѽˆ‹ýÓ­Š¡Ž1‰ênÝ]ú_Z—<Ú®£Rvӛ‰ðpjÊm9G݂–Š¾§®À#j}d£ÆAù-uÚ í¡¢¡û +¨0”\C"‚°ÉdhK>م¶‹ÈŒ©Ù¸Æ:IF“qž\BVhFˆ'$—[Iœ&3’—äæ°B¢™tÙâK\ DåÄ'â`;™I [¿"–ð%„#þÖôNã‡÷š\÷¾ÀëI +|?·a×ü8+ñş3"-AûöשÕ_ZZ„K±O%u6`·îÄÎX{cçͯw1Ø ÞÙÿ$¾Ñè+ÊÁO±M{›'±øšEØ],¸j¹z6¶¸¼+§ý°~¢ ›Qœ½k a=â_ˆµò/E ¸—q¦ÀŒ¿bVškÐÞ&S ß7füg\"Å&]ÐÇKOÑ:´ %ije¿B>ä%¼à™j†:l=®ºT1e~ ª/ðߪg¸ ‹”ƒI0^YÕV) <õ^Åϑë% +·Õ¦ÕQS-WõÓGpaθDû8¥ß 9•D֑ՃðXM'Ð +ÕóUÊÈJ•]Iå"­—mtª¿euuE²)ÓÌ-3`ŒÒŒù SoOŠÓÕýŸ£™«™‚6Ju@$¨Z­ZÏùǚ᧌š;œþåoŒÃö–üúaëõm>݄92)@m¯{«Öêþ†¶¡š‘»”>Õ-ÆV³|¥°³— À•´WUæ>rß$Ó²]ªqّ¸ÿÆz–EYuɔÅÛ>üGT@蚩©\Þ'ßÇ}њGÊý¡9¤mp.d.@L4c&,·”r;b ӂãá îdýlúÚÎÍt3Ñݦ©]Q<äbžÌ-w °ô©ŸNÂkÃð” kÍ búKâ%áï´ÃíH»„“@ j™à"ŠW4ñ²sfœ‘|Aêa{¨à8Âc%ŠJ@bœ W’Õ\“þEÛÔæ':EhsÓřØ=®}âó9fǹú¼T¾ÍWÿ !3ߔô% פԘÝ]YzĀ&XIkWdPÍيØb§]±9g‹ý bIêëiù ¢Æä“Ï$ õOþ1wu_)¾‰xª®S$Pî)m/þUI Ã.mÔpsf5œUwl}oyøhÓ 4á;=DUóIKSž€DSÊjŒj:?è2ž*w¼0P²Ï4‚¿oýŧ+G„Ë4O6‚jµeu˜æ ÙH”W)ϛ=öƒøݮȆŒ¢sœ51û  oº½ÕkæܨaÈIÈӽ֒WoÐ0Õ%>­ª#}?Vþ5NÚÏÁ_ÏÛØû r}¹ë%é7¥­ +ßÔ¼‚Ñ{Ä!`åD}°üÂK_á4ˆ +‰!ƒ¶ªQ\üîHÒ½¼ÏzȔôHçNÚ>«uA-^á²°²bg¦¹%+kÌ5‚ž°8ýWâ #ýwi+‹¯öqéÇ0ÞîŸk…hcûuTT™[ÀÖÁÎ`î5ØZ[›`ËJ¯ &º¶œ-áêvÍ**–öcs0”®Î:¿-Š7•Øôo‡3G„(ÖZ!žd ©¡ ‘z Q}v°x“'EÁ¬éð}èà–aQ#*ÚÕ'–Áévi½Æ·|'iÞnˆ’Ž…˵Y²çø;½eR{ñ‚îEÒ1ÌÜv–ôiúk·Y¶èTË2Ἂ¬æ4o—/Šõ;äªðKšù |O cÿê +Rr_´ñT—Ó'›Uät£Kyγ•zØa“L™= z”s#k–)Æð|O¿ŠèĀŠÜ‡­ý:aúxÓim&ò™ã¼&^c½®†ÂŽoIѓ` +‘¦îWÊñ8Ï2K/ÖױϬ˽ßòŸñ^º¯i©ÁùÊáp‘u£€óÔO£ßè:JD­:WtG±Š<Ü8YJ] + ՄÑy¬iZPí-|xm«4×Är¦Qe¼`þdZ´H ;4°SÉìí¹X1̚å`¯±wªŠªŸp¼u>Ê7¢ Hô²2ìã%¡C‚d>«zES³?«É+éæ&ÓÎeð{™\ÄQ>‡Ý+)ú ”^T9ZîPàäåF­ê†ëü«‰ðV+ú@Á£¸Š®l@ A ˆŠB„ +r‡3„„“L2÷$“™$ €x ¸¨ë‚Õ*,^-àÚ·[]ëù<**è–R®ÚíßðýôIˆnpdkŸ ŻΫ ‘:ÈÃà„£©‰Cö‚û­ÆÐâ>ÛKXi­õ<¼_ŒTTŠ‡¤Õ–¼¬qùcsØ.žJmZ¹E›ÂŒ¨„Æ:ó^΄¢œúhsVIbm8tS”äX&^ a*Ɋ‘ÍÚnð^Ým‘îšãæ=A2äs§ó^»mICca|k‘é°`‡K±…{©"YÙ¡:nf¿,Ú±šW xØ_n~  ª¨ +!fÓ睥üÜ#ƒ ÞäA¶É§oÖ(u´ +gį›Vg攷ÔÏçE)Õ?nî/Ø  bd£éSûu3ßQ·¼Q¸–ùI»B`×\áC!ž’ÄdÑ +ÙPÜ,ÎÀˆ2QC³—ë[PŸ¶å‘Ò»µnª`±žRŸ”ºƒ£šXYUé^í”Ò'ý,|Y5G 4-}Ä<¸Ÿí«kÀC÷ûÈfގoÊۆ3¨²«¯«7‚á%ÍRÍëôå/4ç…ä!=öa¯'‘mý»´fUgÉLˆ•¬(CfU]@::& Ô +¬wo²¦ß¿“ÙD[D$ú”<ÏÞHÜ×½k”¨ÕUÞÒ*Iï#;He6Åi*µø80C¥¤ÕTÎN/h%ø u£hvLµ5'‹Æ­s*=%s+Ä:V9˲OÙ%ç›û‹ž(LWӖ¨sÏwœÐn0~~ I`¼ÙÛñFÚÛ嵃v®¸¿&“äK^U÷*^Ê6U>,ŠVœµ{¦:T5zG‰Fd„Ÿ„šìx|“×4ZšÙ²ÅÖ êuÍ'úʦœ¤"¥œWw±°[þ°f^ª'0X·cxÕ…×Àþšˆ2ª›rKìJÛJáD»Œà”·¾“Jm®äB®|CÁ=ç€55oc/ƒ¼ªàðhÐÏNÁŠL9õ'0ßjIÁî.ÆÖᔑÑÂëùÿ =$!_û3²sÛ^è>pX0µ]SÐc¸„†Ô¹`giœ9ˆ¦Q?”+©,OÄ|ekòÞákC)6b«ŠÞf!),ÌM÷î§úð¯jQ­›ì‰ÉZ¬FÖÀ_û¤Y[-Éۈfiv&¿ÃþmÞHø!‰¡ÏÈÿ`5oõ—I¯šxu¿d€“P#ôF» +î”P&ÒÍÇàÓh_2ˆnÁnm½‡MsC¯?’™¬…ºÿê¾wøƒäÏôOêºtí[P¢k+Ój®ènæöA ú»Ç¹ú”­úHßځÏê§Yº*£zÒל`˜L﵋TL˜ø0ïäü®ý³1|w:4Å4oý™¡¥ð(ºÅ%úªøò±jҨ̨5YÀJ_ÑÿÔ|ÛÑ©f¥•ôò´y†l0û‡Ê0—±š•DúÓO+/Ê.5ÂT­"»á$8¨¼[g)T`MHö³?ŒÆ“”Ú\»fިÕyL/Ø\ZÌüŸáúðjò@Ν(­WÚ¢u”Ó‚d>ÂP"Y’d'$„$ßʗïËì©V¬J+W·>pG‹ž[„ç^ˆºGÚ»ßñãªß2|M 5òòkÚci{‘ÝZJb«»ILF<†fB>òP­óCº­R7<]'äwÂçõ‹KÖÍúÜQXb¦Ãã*Š +Öÿ$f»‡~ ^¬Í„:¡)É]È•}‚pèæA(žŸ+…R ©´X¨zE©‚ÌÐ;b1tš!‚óá9ÚÝ ÈB”jü`™ dã>› Àµ!×L7g¥Þåh%³ÆëÒ7n·ׅ¬§á ô_Qg1ÃR2Ǽĸ:@“nè\ÖKžXù¦å°Ÿ)Â'€WIØC0hݤù!XL}†¾»É4œ‰l5É Vh2–°,ú–?ƒžbLb#(sÀyÌtk]:ibP _"ÏÈ2S&‚FþŒ ߆*:Ü/~‰·Ù5ülÒ6ÄÄþfÝ»¡ ²¯Ó óð¯©vÍô(l1‘Êïu’™;8ãíŸqžµ·ŒóÒi¿7mœL[Ú@¨ÅWxlâäg™ÑñË íY<€#nMDý«yYùZOÃEÑXê;/C<_í•IfG‰ªuÛúR›äÄOè…M­++cØ7šS«ò +4ƊaZ²÷é­ÔƒîŠœøÍÎuª¤í¶ Mߊ]–>]o°¶ÓÐ/ôm^&=ÂNh̕.®g*>d_ò$«¥ +]ókÜñßÙoj-¤½Ö]ºŽwðzýí`ùg`¹@ÝXRËê¯ïÖÐèžSZ^6Ãu¸VŸîø^×ïo«×ÿÔg±„~X—ñQðô Èæ¿®¡ïa%{s Tú·Æp4{®³ÖHLydWû)YUÀ&R?îçFDš/€'ƒgÑHÅ7yOÃÌG +âS0᪄ïg :¤poÊ›)·-.XF:€eÙæ¸*diÌåG{.㯙nwn.ètº±ÓY€½Í<’"³þ`ö¡ôâ7ÑdÒìsSC„»!¦x$¼ì©g‰ó:SîÚíøX9ÛÍY¶»Öá•å‰%r_‚']4KÌÊ ‡. q cÈYvã.㏢‚MrÎÓm½ÜúŒìÎ*ADbW냊ä•M1âDq½by¡Ô9 ¾þm­T'bu÷q…7¶Oñƒr€®÷Âé ßö}¢y‰XKˆ8‹œÜ`”ŠÚå¾®â.;²´ÔÀ«¿~1Kü}wù¡ÂÒ­³•ÏrB;ªҏ¶Þ’ &–6 åRrº÷*?jÄÅÒ䆑luµgðICkþ¶ñMú»|¥Úþv²œ®hùZY˜Hn8£V’×zšƒQ3N?Ý?ÃôÖ«zGPöÖø‘ÙÓ5¬|Noî(RGÐJ[Ý5ªô°&Hs)qq}^í&2Õý•n:z¹ý®þÇ°–kFmPÆ03;7ÕNÑsÛÞèi+ZêŒiӍ±úµ Ó^Ãòzçsã7ÑTÛm ,ì þŒzb–@Æûp…¾°õ2¸2{¦9¤§6„‚Ê„ûž/À=ä Ç4ø)šcýñ x +t&8…3µ¯Bõã-ã(;û^S‚éeÚÙúdSyÂ7yG^íH@¶Es­¹7<ëA–³Q|•áh“[ß\j‰²–eÿÚZŠÒŽy1|iÂ-—ÞM»']£ý‚š¦|§k!¾¨õ3h{ß&«Õm¹›5&[K¨iªƒK%Ú}UEüÞÚk̀Êåu hTñô[Ÿ*îF‰÷´kkOÆÆZ £e¸è ³œe€v]G ‰Ø¼;ÀG­¼LÉÞWݺ[ä“àñº…d;oä‡àošô3xòÿ‚°¦ÀêY{OEk[@Œ|lÄ‚2„€ì„ý²^ò’¼—÷òF6a ò¹9«uUQ[¨EÎmË'*u€WA¨»ä³wÿï:^WfA×w:¨Ržcºè $DZ9-Ná±7¬É×~c +» +?µí;”A¯34VfO× –ý–ßæ 5âœÄ*DvƒÿUe_ÑRqr…_ê°ü¨«pMv–‡]€ö½{ûқ[;¶õfÕ4¯( Ìc5ڑGìùõ÷d›xþµ±…»EÒjOª˜®ü-n +|⚠ë†g8žî KƒöٶŲˆ]ï{r3ÚJ¨(°ù?Ò±’µq…lá÷u;S7¢êÇqWA}ÅÇ°³†ÃÎé=·Åo +¢nÉœxgº|ŒGCT˜pŽT§aHžìÓ͗O¥0áU`llÚ¤»Cçltîî0Ájþhý~±¯pÚ±Yú_é,xü'ù,ÉIU·jnÁ\Í[Møæ z©ÎóÆÈDBéb<Ô¾Ó]ò«ÜT7S0CùoÛ}ñ2õ%ýsÙF͘¸MQ«óÏ ś¡!¤7füSѕ&.!m›àôéFk´¼õ†(+OÐ ãºóâOȏ¢í@ ê•Wª1ù¦f­ÙôG Û0J¸èZ¬’âî-#¢=¾ÅýÄqËb>@@Ñg¤IxFzŸ|˜û½âÅÞ´\“E=ˆY®g6ÒatÀÒº*ÿ¡SYõŒÝçô5û—T9vh÷ øŽ Æ%2{}n€ü´}Iò90Ýv zRf‹¢›Ð8kOËʼ™¨jV‘oõ:*¡xÚýH3Ê_ 6ˆWWxç4Ç\;“5juÙêèK:«ã:iì²7‹rʶ‡»YAd§«~XÃâõ×:J1<Œœ¥²;îäeªî +(ú;èMÙsºÅÈrlÚªÜU[y5ÿ»¶ýävw‹(k +-Í×Olí—ÖHº«¢WeG㐣ü݆L9s›¸ªè‚ŠFp6§ i&xëÁÙИp0üC2}ÉTxmÌCûÀôH#îѽZy—Ú‡†m{ìç+ËEŠAaî­ö‘ìWÏÓd¼V¨Sy%Ûې®™8bôש"SLL„¶òé1å4Ø$BsùÈ&±¿Bµ—j±ê±&©d@ãÜYˆÒ?O¬€+82}­£ù-D^½—†„ÎݒDÝÚ(ûËP¤˜Rœ„{¹ÔÑ¬.íús¢!Ê$Š˜4Žá´PüêÛÚ£ü§¦o\á„iÒ(“ÜÆëä#Àu"„»Dùž8Ï +Ф:¡]ïC­Œ¸€¼¥>Ð6àÞæášÚ’‹¶ÇöÜÒ׶û*ö±‘ûÈÂm@1GQm ÊlìOrus¬g#ö tk-Û¤²ò<‡Šÿv+lŸUÙw +]õ@‘äV9È9'ç¹Ò3Õ«Êè ¡Pç?#Ü0eDãaã¶ÃÕSœº†#Ö[%ëÀó™µLYŸø”‡Æ‰U‡U•_n¸¢¥ÊFÀ†η4FÙ/V[ØäŽ&+‡;Õk¨+å4e[D7\ì~YCm[†D¹¯úÄ·æÏÊó»ë4MÑn/ýé«9Ó0ÌÑéÆ:/[Òo¬¥`ŸK½Ó˜Ž(Öá +™ƒT™Þo…Ír M­8«ÍæFECw…LhT¯–l¿…ç¢ÂíÈ ¥;=í×ÑL×t¹Ì^r%´¢Ë|ÊTXN©£dñR3O>¢Ö«Ä^º°¹àž¡Gû)­ y®·¯ýۂ„2ãbþ+žPgˆDWŒB¤Á;TäÑ+ô4Q”v—¡§€¡{ˆ§…À9è¼µ;Œ¯°!f»é6~/ė|@Ír~’½EÃMíŠ$,<ª²`ÿ2Á‹¦+ù´oM­Ò¿$ȵkë¤†éÄÆ)<$‚\nnu|”LXìÀ·´«¯+z-]‰:Ör"ï‚æ®åXꗺ.KWü;øªå–YFC² Ê:ÃAǔ+ÐIéU× u€œåŠ+íU>.+͋;ËSN@]Ž“ñ— ÏìãLUÛ†Èñ÷¶X»Kx»6 ͑8=Ó*ðUµ±4^qÃݗۥ>S韒¢+—Å» ‰eÝL®ñsf»í v?Á¥ímÆ!±»ñ'Õ粈€Yþ¢v0—«zæْ2GãîÏÒwTÄ1×µe{BªðHÇóMœ,Ø Ï&fr(yÑÁË)©% ­ßPÉÒùÉÍ Ehl§% +$EVDĶ¡¥Ôt o§Á \~6-s‡ð/€/²›‰EÊÔä 2<뤪tñ ‘Åù:¨ÝÚmb“Õp®´V÷±ÊçÈn(Q®7: ÏziZ¢“îàN½l*é3ÄÔmôiИ¥‹`® ß sµ‘ÒnX +ýUœ‚\ПÈb¡i0™¤Ä^Kcà=Ÿ!!{pwp y€ÄK´™H´ö&ôȘ/ùU¯DµáÆgõ#M@’êÁ1“¦¢“¡&®ÓÁyf_s‘IrÈÚùÚŔ\ ýBcŸ×¨7¬H˜eßxÔXl¶Åtbuæ!†ÿhI +&)¥å Ö©êršbp›s³˜Ô;î²Cu GFæqÝ~~c6RbOŒñ 'l—"<͖¼‹üÃz [ª”TÿÏ0}°5y Vá|E­W¹rŒ„Ñ„\˜2”aAA‚¬0 „¬/É·W&aã€A +¨åÅAK]מ ñq\k‹P­µžU´"ÎJÑ»÷?¼Wåù¶{¥¯j#¬'rG”^–‚ô$U¤Ù)~VÓHDäÎTup©áéæ7©ðe’ÖÊ⚊–˜R³"«I˜›^Çw0Ó^Ô+m¯âO©ïX¾‹ÖiM£Ái†-T‡ß5ȝ°©'ˆ†œNÙ]¢~{e‘œ ÃÄr¢©Ä5Ճè-wŽ»Aœ•…„ºÏ-œäV•˜YF~¨UgÐÖBOÙJt¼8yÇ0¶´¬.{KªèOÁ(Ùë¸vlJ¡ uÁSëœ0ü¾ÖƒyØkØ^?‘6W­…c+Ý +ÂC²½ÙlÄ]œÂEškoÆ% ¾õݼ§è„¦™“‰õg}“h0š[[¡ÑãˆtVۃw,ÑíÇU™£À^|}²X?†½Šõ4:a<X… sšá%˜Ã×هU)¦Õ<‹@Z§Q›/ç[µ6ÓóÌ Ý.ú ÿ0A=¹fˆ œxãIҗ³’Q¾lä3\¨P©BoJ]Ô´ã\>[3Ô²õ­ö‚­Œ?,·ôÆЛMOyIÆOi>§ œ'»|“àÄ2ÓökŽ¤x¥Ío»ç6‡–oy*—¸Zo×9‰—XYÊýi£¾ŠŸ”fNP?ž1…kÏð¾ £€Á *ÙÐã_BàïûÄuøpÖ²B[’ š”¶Å4XŸÑ×õÑÔφ“¼}äã렐‘P¼¿•Ø73‚d"ÎdÙ®&Ä<¥ÕÐîăTô>º–üx4ñY´…"ƒþGðÑXF%N£góÍt2®õS 8.h¢ªpq¢„܏¯#~Âð2‰Hlò’eÒ¢ü€(j =äû™‰~ðn$¢± Y9P²KàÚÐC‰/íq䢘Ö¢&lÁŒâr³èSøÁ1åË|ˆ8Óû+üìûýáÛºþǝp5q ¶Z­«‚ô‰(õQÓ¸©AX‚‚!\Ž$$$CîsrL2É$™LîÂ%,‡ –*OQ–uÁ«OłúŠBuUX뵊]‹x®¶V‘î~á£nš,ÿŠ[™|ÏnCÖ +-ÀbY@ªX?(Ûe±92í"Õ¯)fÃmˆ€6@>íÄ_æ|ÓXȼ ½ÿæL N§+VJ2¥v&¿Áœ’Ç‚•ÙgÕa:yÊ*=>ˆC¦,꽅…zq¨¡©øwΣa™çáVîbP$©àßԆ3H¦ ‰ìµ* +|™tšc^Œ7½Cûv›ó¼fÝC¦›ïºUʆNì\ƒAœ X)ŒM¢×Ȋ¬ÅQËr’K{¥ãÄFۏeÍ"jùó%§§h·¥C¿ŠùÀªi¸24¿Ô.$ÛÒ²–ɹ™DÑüÓ®Â?2ª»ðÏ]HMtî—Ôa¡¥»PZé¸+CØÍ9èJ*™á_r%QNÊH®4Òrõ{W)þ |Õem}˜^…e «ÎÙ» +¶.év–¬ö_.e'TÞ)ñV4û¦(FéïoÉÿUgzfðÓ0Õ=ÛrûºÆ£Õ[(hÃØGjKÝÝÒ¢žÚy‚}¬÷¡%ë€]Áʟ%ö€(yì­¬À¿0Üóæ·àÒL1Á½™sÚR1w^N³JÛO÷7ö „ÌنyÅoxõ™”OÅãÕ`òi0) Â¿6Tù„­@JŸ­ŽJL#†Ù×´©²C‰¿[!ì)º«9!ËÊêw+“Ž™î@,Ü&TŽ›Qö0GU5ÌËãýaãò¯ +ê5\1(ù¢â¡-è9]³‚¶¶¸†¨›s4ú±Æ1y3¿Æyʍ©ý©À/Ì ÉÈG䇫~IÄ´41î¬ñ_Þ35g%@‘ØÉ.1N§” N¸Ì¡þP°ïi'„7ó×ëŸÈ4Û˜@rÂzË8äZ?ˆ ìêiþ;Îfç +ÑcÞEÃNéO‚ri@ñDüœ¡Ž“ï¤úu{Aî6.ѱ>1óáë_Ù:,¡ ƒûJf?È/•Lèí¢CòNÉNÙç*E]Ù­!ç½×ø ämqú=pñ)²¹¿ݍî +œc«F±M¼Hõ´Œ?¨£b;t•%› 7órÁ~ãû´£ÎL&ž3>µÅﰞÁ~6slD'9ã?´ÿ6š‰T­æϙ‡¥^ 5÷;Õ +k[ }€Î»ágX0^h™q$WâKJm3ÖqV/fÔ̔¿Æ&„í|ª}3ãø¶½1—ªèsÌO[­9ï¨"6Á‘εñ6 Ç9àK¦ÿæ+´|dÔøæjÒ8aÞ&Ák ËɐˆŒž=9wåUžÍ©ÏÔ?º¯ƒ®Û¿Ó|ÍáµÒÔ0,Œ’«¡lug™³z®äeU,}*Ì ”åe-þˆÔ^u„ïG¢SÁëßoyˆž7ž¦7æñbC#Q½•Ýşánª½[Ú,( õçl•^ 6¤¢ !ùúâʌø>ó"ï:Ïj°®èbiq¼‡„¹Æå2š$V1¦\$›åÝǕwŠökGÔ£þ£îQÊ“Ž%´[ÿ„ôÅÎ`çѐ½J¦ Ή `·¼]–ªæ…+Yº)úu—!*ó5´Ñ(HáId„Ða¾oEâlw1¶•7£ïÓÈáhY³xЈr—ÈãM·èyªA39S¢ÝcLYgèBل*d‹ŽlQö·¶ å¥ÖÓP/ð…¤Ç…m¶ðòl)ÅÖIëRÆ`i™ÿ?Ğ‘¦ôAû‚Y訌ó :§Íe‡»ët¹/Ý Òyüsn琸ÛM ­‘º>dìSG¹&HÃP³ëÁe*p‹ûÖ:éê´v°¾FëòÊÓ«´}9àà|%*öC…‡d•ÚŒíàŸ•T¯»ám ؍ýžÎ¸SVØÝký‚q¬ª½Å~V÷Q< „×f±Ï +ÓC‚B¦´'ÌøL†HÉ?— 6¦û¶ÇZWzªÍjxAñ|õ+cs£hi„#aÝ43¾ü ËKÑZr?Ú'H:‚µmø2ÇèAŒÄ½ ÙešÐ­d€cÐM^ðkÃ^þCÖj#,®¤ž@DòL2Ëâ‰I~tHGÇ«íøJ̀ó¶eñ Ô W`_qÕZ•bµ¬ +„"pÄp߄CH„æ I&Çd2÷LÂ)x‚ʪ­°*j±XEtJ×J]«EZ_=@±XžºY¥¨íî÷#>§(§Uûª÷TªÊ#tgåÛE Àíª¬ÌU¦O4E±Á]cD®•ix`FfÁ¬åøw0b(½”ÑU +Õ•Yâ®ù]sAˆêvjßfh€w@A,búÆx#‚iù”ðu+•ÝE¹†Ì_÷X™¯x˼U-ÆEŸW'šÒ_ë½@ÿØc˜e2b1(·ž h±^EN±Ø +¬`V´[@-k…¤b½’°nÎ_PëáÅéeÚ:øÿ60ŽŒ„š³Ðñ€èl–u-'\õåj|Dþme;±®tHÞGDæ˪&ˆø´‡Õ¡D!ߪ¿@Ðá—M…Ä?Bâ=ër›äéΕt<‘GHß8šJd öÿlûM¹×žiÜlv>Swžo2ŽYê©!Ö;DL…é¢Å¾]²¡ò®†’±ŸÖ˶íRÔÖþœ¬f;Ë·¾Ò-rü®0Ìۏ첸ÛR}Ö"‹¨?5#ðÍmk+3§(¸¸­(.ÏõÇRÄÝÉxP{K$ ‘™ê~?uXÅ m‹ÁµÒÂ(U$C[Kží·–Il9v˜®ŒLæ"çF¿À«]C2qƒ.ÍOI®6Ž1žQÐçªxã É1i™QÑZxlµe_³Ì)O&uZõê±èCÈj7$6ôøÕã} âA~««8zXþ°ÜÓÀ¯âm¿b|®nÍ^i>¢]œäfQêë¢ùÖBchÈJDj^ðû k‚æ½]èr¥ou‡ö#I¸î”îšh +8ЂTc£1)±Ã¼ßüWÞ+Ë-Ë*îkxƒuße´I÷~€ßÁPEŒ:À¼±LR] &‹‚t-¬^à*$MŒ4-µb¼› îãÎB è¿Ÿc˜œéŽ³ñA9ZµuÿKíDۄ§«§Ñù¬T}–•pËp;dz›…x0w +ú Þï7 ? r™©ØâŽlJÁ§ûÄÑU/è3B®¥K3hÿ f@ jçm1©¨RîזD*Øï¿pù–©Á֓ƒ2ÃÿOö(VvÔÚ +n¨‹œd¦³úmMAOßëˆá¹;í1ÜS`§Mà÷Òú-a6 —)²ÂN߲,ž£_ +ßl[có.Hûі%¶Å–Ø´+#]l‡åcÙ¶ŸÕã¾ö$ ÒsÔ~’&ªÂÞbâ~In^™Yö6-Šìª¸ÊŸ£–É/FŒRˆêa` ýŽçÛEi|à•o Îò$Ô³¬¥h:)=’kÇZvö¥6ãÁŠg|V'E´Úë;ÈRèûˆÊ¥^ýt\"ZWÉÊ +Y°»ânN'⢒¤ü†LiøKÑ[ºž!6bؘƒÿjnf¯$= + *™.Ӄ¹ÆöK›vIöchP÷*%Õz˜Ùډ,1-ŠpGsÀ¨ÀDì8D±C7x†¡&µXš¸Ó8e¸!j5kLÌì4ð–Y›ü Ä·&Xqˆ¾ÏY¿LA)$•]€sÐ_g‰^.®[“…³Æfx™ ×́{’sÀÓHqÌ ‰® ¶Ž£¿Šöo¶“à݌ǃ KåúˆFa­a)1$PoגיDO̐Ѹþwèq?0$×°›ÑñÞ®xYZòNÛâ8$ôÕ8‚ _ُ$ý`‚l·cZÁ­6Ÿðݐ?ÝȇY´+û0šH5z‡á‰”kQ}Ö!•±¾~QQüýº2ñ&P{BúcH˜ó…|ó7g¢zŠ9^sy”×lïÎ÷Ûïä­u^ÚA¥ œ;ÊRâckUó>®)’§‡¬vÜQá 8ä:oV¤cƒñ‘ÇsûKèÄö6û¨8#7Æ>^nNk·_ª<wÒ*>ÙÜmç¨Ú¹3¶§Ú"Ψ­ÏÅ¢lÝ`ª§ÂÖ D#ÔýÊîö”¤Þ£7W-ó¡#Ôã›óhŽöî<ãLÐqf6«Ÿ6@”ç0}¹þª•ÙƒÄiÍÆÔhâ­ ¶• Õӛ—“RÃ$÷0Ùa–pž’s–¬—T9¼Û˟ú sJЫú’lO¬˜Iùw7±A8j^Տßork‰lèç17øx&Ôäe¤Üñ˜‚oáó U°¹d!SQ2ñïb+¬Ú(k…m\5†ôø/ÃÇÐ>ÉDÎô:G"DxA4 >…¹èXò(² â× 6b³Ü-X>ù»à®Ä*þ'qÀk’xOºäOXÚ+ë{è5íž| fP|~NE‰ãÔz®EÉy?¬’|êSãä-Æ2¢<“3¾÷}îñôÌ=ö‚‘`·[‘ç~³£´#l²é®Üt¥ÑG¾—P«§ûj_º ëœ_ÓÙß·,ˆúÒò›Ÿcñä®n±$kŠ“aš†³²ÁMê=U¹lMíQ‹÷"g¾ñɆ 5iЉì5Mó%7R›%q£þvÞLýS¹G˜[]]ÕãMÖÚÐê vKÍsàw‰ã>Èõˆq|Ç + 7épÊL=º³#.´®[ÑÌCjϨŽ†^wÖUOl’Õè€Tv·CeúÚû¤½Êöè¶Íÿ]òŠj2Íã0–uuFfÆÕ±®ŒÊªè:„AƆ"E©*‚±S¤¤'_ +!„ôZ:„¢ˆQpt±Œ4»â7Ÿrv÷윽Ys›ÿ9ÏÅ{÷<¿óžFràù׃dË+G1 F†~ /b¶m1¡&ªÂ&x“¼Æ,Š ^ù LtZn‰·D<ót"Œ„7º4Æ"¨Ž»×£.9Ô¯¢m£-±‘6§ñIq¬5£¸±£•5.1gù)œj†‡ßé⬌¹»ã!0ýÊOD<%në…{?ns žˆ³þû±Èê8¶Y°œ…£F<¼p ›œárÆwPq’DºÃ!\ üˆíFìÌÆKA®´^‚…¡ZØŨ·ËØ èR÷÷ŠíœƒõEÝÙᏥ¡†l±a¨·¶«±óÑ?ÛøaZÐ뵘lt—U¦³tÅW˜zŒŸ…þ‡ðs1¶Ð͘iea1Íâ¿ï½§MŸ1ó«¯g͞ó—¹ó¾ùv¾åwßÿ°à¯ ý¸xÉÒeËWüm¥ÕO«V¯±þûÚuëm6lüǦŸmav¿ØovøuËÖmÛw8îÜå´ÛÙÅÕmÏ^wO/oŸ}ûøôó?tøÈÑcÇNž :|úÌÙsç/\ ¿u9:&öJ\|B"D¡1X Iä¤dJÊÕÔ´ôk™YÔìœÜëyù´Bz£˜Ébs¸<¾ D(K¤2¹¢T©*+¯¨¬RWkjjë´ºz}CcSsKk[{‡¡³«»çÆÍÞ[}·wîöÜûíþƒ>z4üøÉÓg¿?ŸxñòÕë7oß½ÿ0ù´˜6múô3fB|=kÖìÙs æΛ÷ 4Å|KËï 5~Xí±p´Èâ%Ð&Ð(Ð*Ð,Ð.Ð0Ÿ–ù<ÍÔ6çó6Ð4^Þûöûô?|äX@`Pð™sBÂ#¢b®$ PX<1‰’šžA͹žO£3˜l.O I¤rù¹ñO‰SŸ#?UB™P' +•B©PëàT;üê}ú *~>22 +EOL¼€º_½~ýæÍ[¨ýý‡““Íý g ,vó˜,òcy]âzFÞþlç(§‘}FVύPÕq㫪¹ØÚJ6©AÅ$µ*ŠH¹·$ÒÏΡ™ŠÙÁì`v0;˜Ìf³Ã—9¸zL2¼‚ÆٞQC|¼QàM5ð±›x§¤zA¨R+Œ­Ô” k*x½ŠGj‘sH%Ť^VaÒݼ¼´û¦r~…LÈ¡Ø3hœã5$؋»#òÈìú2›…'$ ’ó +,ª¼F‘P].ÁÖˤV!‡ØÉfoÒèDc&2`* ÷_'ǹ{# Ý°w%{2º¥>ŒÙaQ“*Xª¯ SV*â5r1V/‚¸\‚¡ˆôä2·Òèd£©L9¸x~dºŸœà»E ‹]0ý +çôÕ^z[ÙAKm€°º<¬L!¯‰± |±¥˜t䳁®,&p#…Aºe* ×aʁ½'pBàré±Ì }¯Ü1µ·zw¾AçÁÒj$ª²° +±,¾Ž9°Kͅ| -—‹7\cÝÉLâ Sy r฾íRꈼ_½bl؞ÝÒ°—U¡KTáU|YB[ŒÓ3„@S¾ßJåãÛÓ¸€!‰Cì2•)gOç|â¥dgسò­‰u¤þûôºzw®¬2PÉW^R³d‰µÅ\=M4æ +æ Ðz•Oh'óˆ¦ò7Ã@önOPàðJ¾-äyõæ¸áV;Lg·]f¹Î“'¨R±”‘j†^[(ÅëòĀž +y¤C”B I@l3o?å ÜqìM™Ãù±zÛ¨{·6ÀõöT©Ö‡Ï*?]FW^VÓˆš|¾.Gè2 T¡!YHl" Iͦ +~œ]ž tˑ·Õ¶Á:6^ìüm5ºÂàÃÕúò +Ï)ó”ÑU¹ +¤&GŽ¯Í’êÒ¥ÝU ¡>ILÔŤSKì` `›;¨‚m\¬oÀêœöÞjœ¨c{.]wˆ{]}Až][žUŠ¬ÎTà5×䄚T9±–"#֑¥$-QJ֙ +(²…R;×7µë¼îõ®òn^¢°§ìœ†£¬ÌÚaº:VžVT¥•áËST@e²’ &—«‰ +’PkL”l‚ëvw¬ØÙ6´Ô·ì¹U8{`>§Û5#½õ8-EʦhcÉ5Iƒ–jŒ ¯ÆɱUxº(EU•¦Ê×ÃÆ–Ùu=X°U=±ôï¹uxî}{tjŸG +¹ó•Øš4Çaã™(=œ¨Gràõ(n‚Ë×âøqZ¼ÀTÞi–­ííÿvUí肝Âɇ F7†¤ :&|ðؾ“ôÐôĮȬ8CLNlG\nt{BÞåvx~T2?²]ъ¡™Êíî¹?Öÿþí:éäB':¸ÚÿÚ û³¤§n‘èA¿øýSè+ý€Ëw.‘"nG%…÷ÅPBûâRBz®^ìML½p‘zþ&*ÍT@æ–õ ÝmHÛïÿ®hÿÙæØ‡¬ƒDcññì΢³¬&Z¤T_Wj ð5yI5•¢­LOї§¤5«Èm + Ç ÇÒ»Eèâž/Åì`v0;˜Ìf‡ÿË¡pŸß;†Ï™Ö¾ØA΂‘}„ÚUÌl¦‡Kôô8¥¶SQC#kÔדtY”FUÚÕVErºAF̾!ÆÝâb7¿”ÏEŸ|üÞ{ŸeûÄ òöw¸þYÝ쓌æE‘¾8¦TË@VÔ4U4²®<7©I™Ii—¥¦öˆ“²û¸š‘A(êýRþí@÷öûƒý: j:¿ã8þ¸öÑÎvÚ®ug–±«Ö*t´âE@EQ‹€*—r ëŸ„B’î;ä !„rI†C@V@Å]îºŠÝ_³¶µÓ‡äQøàýü5ßù<ùnˆÒ.>—¥UßWÃ/)³aÅYØ/-Ry%•F·¤Þ2"Æ  InK/iÜÈ"‡tôY£{¦p—8dþ|´Q\ĐxÀi'6Ä©/ä©U÷Uiø¯5ÇÛgÔ§ye¾bLYª÷(kÍe“Í&‡\1qÜ(h©¹-³¢®ÎEv;w©‹Î›6 þ!5kC‚(x¡H¹ö@ƒÀÞÖm›ÕäNêþ&וôy UF·eÖaœf5n\+#„$Ê,—Û¾Èìá.µwò¢íƒA€Èڐ&ç¿T%_}ؗŒY6"ès¦ ö”9G°ª&†¯jƒ æÆ¡ü½R9a²WLšé„éót~Ï-‡·mï ‚ˆA˜’õNv$ï¥&©ò‘! ½2p„¶0t¬{z$›?5Z uTj¬–º]Ä ÐÆ`9ì–Âtù& f,Üùhâ؈!á%g¾S$æ½Ò&T<6n¼cK /¹ó'z&¼ùbÛp¹Î`F*õ§8bà( @‡š¢ˆH3x!}'ìŠ: yo8ÄI™ÿP&\ø»þPùËÁ†{ÎCÄå@RËt(³Ûéɓ‡ÊŒ*rH1𵐗¥‚&ÚäÐd³”x'¦McȨû`$fü >”ûm|éSÛ~䃱ؕ¹$Òx0ƒmq]Pª­e&‰ iƒ#ŽeF6AWB~’œ8‰“QChiëT´ɞ <|ÈÚøó¯ö]zîÚ[u*¾nz!žb÷gôö9òԒÁr3lª³q X«r3"· © >’’4SPh=m@ú£áÐA 8 {ϾŽ+\÷Ǖ--íFŽÍí§Ç3a™£@ì4³Mõ6–;Ò©'¸Zûª–8JԐÆpjŠ­j6 ÛDƒzßQ0°'ûåè®ÜÕ¹=Á»;QÖéøv…ï„€ï(ÔôX¯™ºÌ ÖN#ÎÎ0-z¢“¬#¹‰}Íœ–2ŠÑÒ¢Èÿ¤ûã>ñƾ#óAhûÉw¶•8Vw 5áC°/[Àr«:mU†5ÐfÆYéýÕH´7H‚žìÄë)N¬ŽæŠ6 øS PÅýX¶'>ó}™<·¼5Ó½þe©~y'NNdtOäðÛݗdô‘jM‹ ¥§Z±ý̓x3ÁYðÄA¬™dE›ÈCM&ª-ڀjG ÐoûÎõž¥Åßíõ>ْm\©-ïÆuÍ ÚZƒçÙTßÙS#%º”xG“;‚Ñ¢í8]ã0^ß`#ê‡Hƺ¡æ¨š¯b~Úºãnø×øÙAóë-9’õ¯*ºV÷¡ióéTR8· +–ö`'ªyM>¤ a¬ATçm#GђZVZãÆ˪ݐ¼ÊETDèÿÃÖõ‰_l ®}²mð»Ï’do¿8Ëz¶»”¶–PÝÎÂcò)¨ÙÒVdøjGÍT ³*„ì¾:YϪ ¢z*‚Mìò†SÀqKýPÔ}ëüôW7–öKÛ«Ov*Áo°ßm;C¹¯zœz­qít}ÝJ¦úöe¨òV©l±Š|e¡–ryI½t³žV2‡j)žk¢Íb腳ØÖh ‡ú“‘‡?ÿ|º«lIl»N^Îmz‘Qr}ý\Eå£üê+Š¯—¬•ÕÝ«l(¼[ÕXp§¶1ٔ¿Z‡Î[m@_XiÄä® ±Ñà¿üp“övôfžyÍ?qé)œ¼Ë?GZä3Ã=•‚@WƒÊÛ =T³«µÕê 2lvsdÏrÚ°÷Pì±¢¤Þzµ×E    ÿ÷†Þ Ç€—qæ5œYòTp +yOC¼Å»Øæ”ÃRéeb &Ùìl§[GhmÃÃÍÔí¶b9£ƒMð˜%ó”>]8îóˆ!pÒ€Ÿ~æ{áñ’g¢¬ëkâl’ðBÇ4ï2?È©VŒ±õžn¢ÙÙI³Ž´Òí6 +Ãe%2G-8¶o ûûQ²€¥˜P6n¾c÷ÀÇN/J/þF’Q»&= }-9ß>#,ê ò+å>n½ÎÃƙ,ŠÕЍ µ´z,Í>3¾'Џ„ԍ’´I£åþÍÿ6ôM‚´Óo$G‹¾‘¥×ÜWdáoËsÚf¥ùܐ¨T:×jGyh““K²Ú»)k[‹×Leøû›Ù“¢ø†#¾ceA>VØlï ¼ˆ—–„©Ùo¤iEÏǪ¨2p˪lúMe.{J~Iì—T©½"”ÑCƒvn³c°‹æ5µ3ü}-¬’"ÐhšI'ِ,¸ÙþkHM"Dö[YjásUZÕCM:f¥ïD˂ö+¬)U• +Ÿ²Nç–aìÈa␽Zfk@ÞÎ é¼0›,œî"IBL’tr³AlĐ øˆ N9õVžrñ…:õÚ#ÝQôª1ƒºhÌaÎ x!c¹ÄoDªÜjԀE‚éã½òš_ÀdLqœi&]8ÓN“LµS¥“›íƒNI’äSÊä‹/µ)WÒï˜ÓÉK–lƜ5==\[jTv]½Ù¨@(…WØKñsØm!fwO¸)œii“LÑÚ¤¡Íö?鑓ª#¯tɕOLÔ=ë?Ù¯“¨¦ï€ã‡9Íë,oÚ9̳³´tž‡Ú2ÏâÀ¨UAÙÅPÙ×@C6²‡¬„-!d!ûž@ BB6²BØĂQDÁŽˆk«§ãop¦Ï9ÿç4Ÿû÷úM§Üre²—½9ó¾*¡ßӍš›†ûŒ—RMð‹dÔ0WÜ:ËrçBÙ5*G1GëRÎBd; âib"P'dþh8^øý`Bõ–5yϕJ\ ž¡¯L¶Î„*nWÎ2Ò bÞß­¦L¶)˜3tç*E&' ”sd¾r* ‹Þiˆ²„@sìì?ûâ/=:Vùh,~ߗ‚½;{–´ôu15®àÛÆkµ}6¸EnA;øýxo‡bhéS$uÇ,N%œÃɕ³8©jª· òã'€îè™×q/¬qåO=Ç`›S)ˆÛËçг ù,÷T™Àì­×¨ísïÖÞ=@o5’-zê$^˚Fk¸3(l¥UAä?5(ã€!ö4°ÎÛv¹ò(_uw1­fáf:Þw-»}hâŠXë©ÓKvz†q¶®A²›ÙOñQŒÔ NϜ@ë:&‘zá$B/† Èÿ$Gc€*î8è?”ñÚz0û;ߗ—î]/ZZ‡…V’É#sY]°X&q×zlK×NC»™ìd P¶ÂGÚF¡ê½ÀµŒî‰ÞœÚ=¿¶;Îóø³ÓèjéÚ!,çz“5—Ï¥…+D”`ƒŒèCª°^ŒíÁé‘n‚á"áNJ£“f‚9˜0 2 ü˜?ÝóÌñÙâ­ßî}øɉÁí=y²­èΝ£Æòi*ùë‹m„¹JnóL€š„÷6M $_…še Aœ (êü$e­¯EUí£««½ Ȁáӏ^9þ±²ôþ‡þ»¢,¯>I–oGæs}YEßHBWÏš—‹hÈÅÊÖ¯®ÕµÃæ»ê朚YTwÕL3¯r×S1Mà—O“eS-ÂÒ)*d`ø¿[ŸûÕ¡û¿ùhhûÃ%؝ÒýjßÆÓ£¥„Í“õè\$|­[«œX½RK©¼Ñ@-_‚ÓJ—Œ’oЌ+כ™Å‹8VÑ"¡õò™]ø?¸üå/&—ßûõÈË÷ÿ¬ØÏ{’˜¯d_$]B?É,kÜʯ©¾¹¡üÛ2xÉF5¢x½uùn#ºðsé¢ùâ +[°†ÁÜÆâòoðy«DÈÂs?ÿ™íÎ{hÀowóÁÇ1,°÷8 Äf L?ßðCVAÕ÷yE%Ï +K.?)-¿ô¨²²àamUÞÃúš [5¹[ðڜˆºœȺìMtýùMì0¨€ðo»?ásÐ}*ðϜ|-ÌÌ.Ì©Ü ×{JZV¸u (álIneêCô6“¿¥Ëâ%ñFÆñ‚Q¶×æÁÈìn”j̍Ð;\Mƒ{“’w ïÞ5üŸ6ˆÞ4Ýq@pê$Í{Þ{¾bK”‡XQVxÕ œ&á\^fÓôA{ÀOëò’»­ã¾m§ÁîÆÈ.”ÚéBö¦ç0b’· ¼“±@”‘ħ/¼d–?”ä4mˆ/’o +ËÛy0Á£wõA6kÀÇloáŒzˆ=vVätbd.RãCô{,“Ç„4¹¡¢˜]@°ÓГ zÓӁ4#÷¥ìLÙ#yüž,xK|…}]XÿÊCÈÂ>ØA𵲇Çi6‰çpàDî1Œ|܎Òù,H£ÏˆêóêPý(@c‘€Ÿ Äii@–žûRqªô±2³ñ[eaU^ÈúFRÁ›6J§zšµ!Åäë` {˜ív'…ëà ½¶f…­Qú€mô)0}^(Þ6Rc$5 (Òr~P,y¢9ÓðwMî¶:Ÿ¹¬(å^“Ö‰gDHõD±ßÏ¡yØl»ƒÆñØÈ"ß0A4át!5F’5üblŸŠ· ”#@šœ +”)Ùۚô+Ou§`÷õ™Ø;ú\ú mqׂªZ4+‡+'Å8ƒ¿‡bqu2Ǭ¬NÏ ­ÇßG‘†t$턧â ÞèƒôFïÂ7 ÉG€,)¨’³·µ©ÅO 'ë6ûÎbîögSoö¶/+øWu²°£÷ˆˆ–Q.ml°½Íc`rjš($oQM +ˆš0¨rIF?ÿiˆ¢¤#@ž˜ÔIç_éSŠžõ¥×>8Z7g‘W-[—ÌåÜ«½ J?&Á[Ìü–1Ck\Õ֐°B†"Ìmф;[ô¡Žƒ + þ©¡7q§áD +Ð$fýØtù;Sj͖%qÏzŽ¸fÏg,ÛË;¦-°^¡Q`-}"ҘŠG÷HºÚüvÞ—- ·35Slº.ÔJ7 øoÉÃ@‘ þŝ5pŸNgÚmwº³ÓÙ±•Ù™mu»£ë±*ꊸ‚€Š¹/#7H äNH  Ž@HB€„\ä$77!áP¡ˆŠx¢EÐ.øo´vŸÉ[öáóþßOⶩ8—¸¦¹¹bD>±†æÏ÷ÄßîΠÙõ°«)Q‹ðÚ6AYÀ-ía×WÚj™LGU-o¸¼F7k1FjÒ@3äééÆ\=ۉï <ä„'¾Š#Gޙ¾?±Øùu×êߎ·oí à¿q¥¯xeP I÷Éøh1ênzY=‘Wu MÏÇÕ¦ÝÌg¦ŽÔ¥ŒÕ'Ý(e]-gCGi.Š];^÷üå‹É¹Ï>ï~ñ×o”[?)û µoOÄP^žM!=†aÇ à øì¹tRæl69m^œrUš4¥\û O…Þ%–%Þ-,O¸]T›B‹›*sÉ;ãŽ?MÞúôw½+ŸíPmîÜÓv{ւC)›§#H뉘ÕðÔÜ¥¸ëO¡¹)‹iˆ¤…ëhè£\LâC.á!ÿKˆ›'bç‰ù1÷ ‰Ñ÷‹HQs¥.™´ÿá·ýwþø{õϟï‚/÷2À·Tpü øc6ƒ#s6"âÓ×b¡I¯ )‰«©iñ+™±Ë°ÌèexVÔâzä:;â9þ –ŸsåYAnØS²KúG?ùvö“O›ÁŸÝêÀW{ÊÀþ£$àé…þça øR*½º÷óÕ¨è·É1‘oÒãÂ7²â¯lÀÂÖá ¡ëˆÄ˯‘WC^£¯†¬á ÁkhÐñš+óð€qf7¨ :êB|ëJÈ+*þu}Bæ2#½P“Cž«ÄѦˋ˜S%eÜñÂ*Á‘Ñ:Šg· c¥ChÜli·çµ)á +Õ`®FmË5©{òÌÛökï ÿ· ôÿ5„ÿ·!>s™™Œ^ ÃÈsUXÚt™9UJ厓«šÞ7ŒàYΆ™-PØß7 $*gƒz0W«î‡›Ô]yÛ÷¡él`\:XA>€s9ø7<î5'&c™E=ffÎÑӕDædyiÃx M8ZHë¥6°.¼à"4F½m IzÙžó¬9ÿ°)©d¶1»ú źŠF+)mjuû@a½¶7Ÿg°âDfFiUcԝR¬ÚڊÓX„x­i»>6|XþGÏß/@@+$âßâ k¯ÄaÙÏÅÑØQbќ0ƒö/¯n‚MàÒ‹Åí]%µ:c!רËZTxY§ §êjq4ÖF‚Ö¼]XÎöywÀ?çþÝ=5a'ïÎv:î´u»]»»ãŒµº¶u=©¢«,‚"È@n9 „$$!„+äàÊEä€@ÈAHGBB€p„„EA.±"( hAÅ P×뷙±Ó—}ÉЇÏûw¾ +oPùE¼i„­·„ ×ԑ9Ôq‹Í©¬[ üq)Q<\UØh.gêºY}‰°WS(35Qû•EJÖYj)zS µÝh/PókƒÈë¨ó<”^~ É'ü­Ú?aS„|¢‹ ¬´AÉ :8}F/¿RŸ+¶ˆ¨Ý|š®­Œcha +Œ 4±Y^¬´H‹´ÖjªÖZU 7 +Ûûìõ[C­ç1 ?w¨<}A‹wØ{­_ÜKýyēŽðŒû]Pâm¢p\‹+¿Ø-¶ T酟ˠäðŒRVYĐ[…tõ¯X;À-ië¯(iï³×Ç7[Ã9GPïq4zøgè‡6ŸØÍÎ@ø£ž0Ì=4kֈ \ÕcÊ-M±ANTij ´Ê*†AÂ+7V— Í|¶ÌZQÚ4Àf¶°mýl†Þd/ ²5ÔØÄŽ@áî +šÝ½Ö#ø]‡w̋ž€¤Usri07mN¥ w¢ËŒ|­®!W¥’Q´RQI§°Šcä fWlerUôòÖ:Gg¡³õ&{ýÖ q? +”n. ÅÍ ´¹½éòŠ|fò0–rg$u͚B¶ö 8†6œ¨¥9»A®$µVˊ:¹bVoi ÏLŠ,EUŠ‚Jí@!Og)ªÐ›íõ±áÌ@êv4œ>4§=A‡[À+£gøÚ $fy4"nv,9r1™ÔgJcë:±5J-AYÛLÔð +:J匞Y¹‰*©îϗȭy­5¿Zg!WêÍöµ¿6È΍®Î@çâºÎ@6,ÁGüÃîÎD†OMBӆF`ù+¢´Ù˜^-íÄ+*u¹j¶š¢/i¢u‘UcnC¥9K)ëÇ7hú³êÚúsÅz³½€ØÖ ²5È]ÍÎN ÝÙí­ÑÅûÙ°;äÁTd~>T©J”4& *íêo‡w‚Î}»Ÿ ïÙuóö?¿»¼zðXï‹cÞêçΑ’ggS¹+~™ô¥P2u.ž–÷3‚M˜ÆVà&³éãÄ*ä¥1Z,‚_eˆ“¯°%I#\iâˆP–pYRg/Pphý×ö×ýßm¿sãYÙý}ïÆ~'õkGˆä•s4÷ù¹Túj`ùޅ¼ÜX~>­3‹e¢n؈™¼2ø4¹"yª ›¤ñ'™‚ø‰²Ê¸q~t¼Zh/ Úû5èÚùõƒkùòêƒoþfÜصOýa¿‹8ús߸FÓ_ø$“‡¦ç¬@3qË°<ôR ±€¡Âïd%Íç'ÎåÓnQéq·Š±³4fÌM+úçòÒ¨|¶½€îÛÏ׆·n›û|‹qý›íj°ëpå‚ChïÝ#È/ⳟ_€c×bQˆG0lÊ +û%=+á>>'n9;7ö^^^Ì=1ú.5?j©ˆ¹D'_X,¥D,–QíµnúòÓÑñ?ýÁtÿ‹/ÔàïßJÀžÃ\pø œò&ï ìw!‘˜×‘±©±0؋¤”øgˆTèStZô*j€Ž|œ“ñ˜ˆ D„=¢bCáBÒ3‚WYx{oùÄt}Ë5›[ÿ,ÛwòÀéÀñ$ ¸Í4LBÞA# oaQQÿ…Ç\x„†¿Âą½Êˆ}IHÙÌNÞÌK Úȇß À× “ÖK’íeºúÙ'­sŸ}*_}Å;vÐÁ¾½$pâ¸;¡€ï™$pþ\,÷Ž1~ Á?$Äù € + +˜à€ ñ™! +9¡~òÂ|?Â}ÞSíØ·‚R—€éwpƒÿøá^@òž—·YH{ÊÆVDòrqQÉ"…Åž'VpoåTUÞ$ÔVÏdÈD×±Jñtz“t +Ý*›Bµ×M"{ä“i–ú1äÅúËèa¹=~oø½áÿض†R[ßÖ ó•Q!ïñq/¹ð´§e˜ÌUV.y™VH[(`²çIåÜÙÜʪY¢š¼L<SJ§0Mu“èVùª£~Ù«˜@(® ‡Céö[ÇÖÀñ=着0Ä#‚?¡±/0ÄS.2s•C -3)´…bgŽÂáß$ò…395µÓ©t2C!ŸÀ6+ÆÓµÊkhCÃ5”Iuý?Fç;ªé;ø»×?úz½Ñ{w½ö]-¯ï¼³UÔ§U‹ ""{*(CF˜ +DF$L„@ Ù;½Ç/‰d:!á¢Zu]õ{©øwþøüÿT •*Üïʇƒ FfflÀ9xɉï¹éY¯Ø9EÌÂÊG4vµ£ž¸ØŠï˜?ÛƸÞ@çÎÖ±…ÓÕBÉÕJ¹|©î/7)ǘª±²Õb@Ջ<¯†*¼óá@ñèž;Îð€ é¤f¼æe>å 1KêWiÕÄE2®c¾¹•9‡£rg0]¢«µÙD•¬g©Q])·¨ÇÊܚd¿Æ]ѯµWöiMU}:oªç@õ:£vN¬?ćѱ£@”œþF˜qê?±Î.ª[cTà—(˜öy‘1‡oçM70œh~÷8J¦«Ðh.#lºQDŸ®¯Ò­·W¹õF”[¯­öÎÇ3j;àEïÂØ#@’¤ÇO¾•¤<ÃÊ~œª½Ç.;»ÔYKžïhêœk&ñ¦qtÉd=·çrT}¡J£ª°ú+zPU¯ÑX}Ψ®9gTÔözÐ<šçйð#ý€8:Èââ€<1õÝ)y/ä™%O$yÕ„ðÆevUëm:–>Cnæ^!R$£,Å@½Pë®í18Q„r™ Õ.³ºÖeîF»ÌÒºs&o|<°#¶A„DÝ1±@q4ù7剜_•éðNJœÊ5yvATÑ<ËÆPÇhxî0‰,íÃw*\µ^j4¢5]­ÍªD;­ò:§UŒqZ—WÝs ÿ~÷ÂðŸ€,â0PDÅuü‰·š¤¬gڴ‡ÚlIJª}³»âì8Maâ¸îŽ)ÔBU™ð,½¶QdRbÖnŒÉ&Á8ì¬ÃÆmpZ9.‹7>8a¾@ºȁ*2 +hc“^ë3~1¦Ü3ÁJŒE¨i¢é¢¸†ÒÏÆr!:Aj$“Uê†^Nà›ÅMr›§·s!ˆ…ƒìÌ&§•Ñä´xtþ~8踡ۀøÈ>Ð4á‘@sìWóÑ´Ÿm)9«PVÑ-kQŸ¶¬iPŽ¢8ùõS×Y©šFRÉÈ4½°•cæ4Kl] ÔI°C4<Q •à´zãáÓsàÙ¤!{2ä Ѕ…ÿfŠNxfKH~èJμëÎΟuœF^4”à܊Ê«ÍÑp¥rf³J@ëг:ºÌô6‘BRBd’ÅÑÖ +Am-[[‹Óꍏþám@¼¨ChØ[kdì†+>é~rÚÂ`vöä¹Sˆ!ËœCƒìÐËkØÝB¬DÈÅ+Y]d=­“a&Óø¶JD ˜„;Dlw؛É›7cû_Ãsoò æÐ` + y툈zÜŸ°6š’tk4 6֗è³7Z åí*Š-–ÕKØ¢&%×ª#qèfB׆cÊ¡¦Â2 GƒìMT‡ÍÂC?€žƒ».ÈX¿è [Ž‹ZžH™¹œ‘5:˜Wît6è­¥d™¾’ÅU¡EôîFIҬŋ(¦ËZǗØkxZ¨šÙÑ,‡­žé´z0=¦ç >ø=PØŒ~„?‹Y˜9=1žžy~4§ÔÚ«t–V$“a¨¶i°Ýx%Aé!jäLs¥LdEÈÔ¶r™ÃV!tZQ<§Å Ës`úiÀ öß ,{߸÷?¹xÄåÚQ¿ë·#/N§e¸Æ`%º‘‚zÉyx+ËUÞÙnGññ–z)ÆxVY­'i‘ºNC©V`‚k•æ"Ý|FyÎT&ó`yÜ߹߁î'_ùíz>°ûÞÕ#»n/Fï›\LŒ¸‘zÒ2•ïËCs/)ƒ¥Tb%Ӌ¡\8y¹£U ‡èšBˆ¯+€ú|Ȫ/°¸õ…:ï¶ç ðß{7ӞÞ¸ÜöhÌoëí;A[¯®„Œ,ÇÅ8NœÔÞÌ(ÎäVÓ'O7µŒ•±—*¨ µÜòœ¨x¸UzjˆÞ;ÄWdõ(aCV%l`P™ãPyp<ñ¾õîï€}ç捑ÿ^¼±gÓՕ€ÃB‚kQG5wãa…gèóÕÍ7òpØkÅ­¨Y¥lª–ŸhdŸ¾ÒÂË¿Lä^b‹²/IÄ°K§(ãâÔ€ç9Èw} Û¿yÝ÷ý7«S[¾šZÞñÝðºßh=(Lý0ì¸ð~l.}-±”¸’ZƒYÊn@Ý."–ß@´Á¯ÕP +gèSDFîd{Wöƒ5ÁãdŽË¸ã:nú8ä ð”¾ÿо\¿¼éo3K>^÷Ý=Ý»_½%ø%4…ö$&ø8±ó ½ªj%·¾| ŽƒßA +oÕ´äßĶå^Ƿî‘:²f©ÔŒ&íä Ÿž6-ïLÖzH|ÿ ›ÿúbð«?ÍÝùâӑuŸ¯¡—[}U¯ö +^ÆÐ^…¦_Æåb6’‹QëYˆÒûù¨âU8úÔ2“¿Tݘ³ˆi‚-4á3ï4Òo“‰'çiÍ©·ºZRn +Z“oÊHÞÊ͟½sþóÓ¹©Ï?}ôÅçöW>ߪÞmÝÉ¿7ˆ +‚bˆï#’1¯e¡ž§”nÀŠ ”æ?‚#s"*a÷Q¨Ì{u5ék µi«xtêJK}Ê +“¼LÿËjHºË÷ +0}ùÉì…Ïþ0:÷Çÿ³[gAM vÇít»v§3ítÛљvZuÕ®]ïÕu‘Cî;r†CDD @ !`BBHHBî„r;€ \BñÀêZP´X‹Šnŋuåß Ý÷ø؇}ø¾f~/¿Ÿ÷¾ùô76Ø°Q Û÷ˆá@BbhŸ\ñ™Y²œu¬èun^þR!êø lQöwLÖs6ó—±H-M{ÊÀ#ŸÖRŸpËRžʒKʓÄéÖ7k׌MürMßô'¿°Áï?ÕÂg›Ä°kúS!"œ q8@&¡ ™ûþxæ±w¨¬¬ï‹³3–KsÒޖG¾!禼®:‘üš–—ôŠ‘Ÿø²® á%§àð’…X~Hç<¯é½¾vmñWkaýïÄ°uö~A…ÀýDˆ +(Dh>¤FåÀ‘Ø,ÈA¤C~ÐI)€óžo|J"”§&‰€ª´x ¦Å­Ô¤Ç®03bÞ×gF¿ç}P½ã­±M}ô3-üz­þð[6|þǓ°oKî@Cø—' î룐éA©’¹¡ PŽtD`#c¡Ô{xÊ¢¢ä˜H¨Š‰jl80bÀ÷!sÛ'À<¸jc¶/q/Ӄ@” Â|ä +¯8ç-» ý‚QMxFeU>¦ðiHRæ|™Šý¯ãÞ/1òç°ÖÆ{—ð.ºK<[Ô'™-<+™AIgPW¤7 ¯K¯¡ÿ ÿg–×ÀŠÞ +‚„½ N ÉÑŸH]iDç¼åâÑ/XÂ"IY¨æÑÿE–°æ‰Mœo®Ô(¸‡µ +g‹]âYt·d¦¨_6]8ìí‚|ªpR~ =)›ÀLÊ}¬UÃz¨ÚÂÃ{@† yf4HsRAŒ:öVPRô¢¾‚°X[CY qè«Du*ܹr­à.Þ šÅY%3X—lsZ~= œ*UN^išÄ\U^,¾Út{ÅgPç5Ôy ÜÈ- AìEr(Ó£A‘²¼ìeQqᯜ°È>IY`ÔÕ<<)`?¨”ñî5ÂY‚^2]b‘ßÁ¶+§0gšn£Ïªn]T_Ç\Vc/«=¸Ëš³%>¶×Àöx[@¿šýA…Œ‚¦#I Ì=º,-B- ñøg ”ÊVmÍ<Ç¾_%áß­P‰fÊZewJ-ÊÛ¸Õ?Š{5·Ð#Ú˜ í%ì„ÖSr©y°ô’®ï»UC½× ˆØ Š¸Ý >ìšäФ'‚úXÖ÷ʂ‚—Rlé³FyC§Ï×rØsT¶²I†¸0%Å­˜Ò¯ÙǞëóŠþ݌!ÜW’ªîˆiÌë õüKÌFÙM¡vWéZ†ÈfC?±½­§¼ßÜ]>jq‘F-Vò¨ÅTyÎl ø¸?d^ƒ6bè#¿Sl0˜bÞY‘ÉK–¬£O̹ÿ4¢KftDòuE5s¼‘É÷px²!¦DÓGS·vWL•v‹“|Új'»mm•›¡ÊcÕUZµÕ£_­¼EÈ&ЅmcÄ~0ǁ õ֑’øܙ™ñÈyüãW퇿kž:nv}Üþv ásv$4¢ðy4A֏‹K磻°ž2ùŒn¶˜ÔÅÏÂuJ¨ÎüüÈUaDG¥2¬óª2´ëž2ôqwQ؃®º€RÛpaÿWPgòõ’ú‡M/ú ×uL˜nmÖXíiœµ³¬™vu:3éí_0%yN䍡I/ˆÉ´Q:‡8šÌnj¤ £‡%bäPž,|ðTvè@™¢ûÖɈÎ^@qñ†«;$¸¹ËÝ8ΐîáBOGhO©ÜÛòtºòP_¯¼__ïäò—úrøÛ:!͆Ûi`ù=lŒ£Ài_(x1÷¤¥Ärìa q²µ#Ьó¨$ÚØÛƸ¶Ç ý˜ ˆ´$vº@²±°m¶³dx™‚8Ð$ö F{€€¼8ä +;»œ("½Ëa¼¡)^STÉó±çSæ• ¾–7‹½’ö +Ә>ƒ¾ÉŸAµdL£ ¦búcè!Á3쨠÷bUÿoø³¥m`kRŒ´S2i€ÈÂí@Šò1Òȏ©lìr²ü>>›ñ†^˜¸@=͚#KÕ+¸³øÚ´W¸+ülcÆ4æ–`}_8…ꎣž‰†1C¢§¸Q~uÀÖ6¤hxŽF ö0…l? È µy´;Hñ ¤!?ò’°Ë)|ò»$YÜ"3?ižVœ¢¡œå¾Š­HŸ!ÖfLãë„SØë¢I̝ÌIt«xÝ#ÁŠ{ðÃâv¤MHù³!ý¸!ÈÜM@0‡¼cér¬?HÈ+ñØe.—üŽ%f¾NÈMžcœH¥–¦Í/dLk„“„ºÌ Ü ñV-Ç<–¾ÀöIûðÏ¥„AÙÃØÁ¬û±«‚Ô=jµ2 !ÛÍò}ÿ…A¶P€t…<´dÇF¬d20Ëé)ä·©Bæë$9KÃTr_ÑKøӔrádlMæ¡N2ŽÿYöےõ۝=€Èî$d·Æ>“«Iý9wÈ«û_GÛ ²7…ë^Pú„6Pæ…ÑÈ%„¯È¨˜eaù-Ï\`ËXšÄÞLÜéŒ)jYæ©Fú’XŸõþ¦| ך3ŒëÍé"ö紒újroî/”ÞÜ&êꀣmàjÄv;!ÏÅNz™A1ŠƒàÒ +1¡+¹dÔ)“ôVÀaÎsÅìYV.o*¾X0N?'£TgÄÖå<'ÞTôZsŸ{óZI=yw)=ù?SŸ4О\¥¯¸ÚžÕÛ …ÎÆpÊã¨|Ž€*ÐN‡{­£‚?(‰Ñ‹ +Q#eÇMeX¿qåiÃÉJѳøRéSF…¼‹z9·ÜXÐFR¶’º”w©O”M´nåUzwÑOqÝÊKqOVgüþKx}E5åqcuÇî(ƒ:ãŠÊ¢2à‚ R¥‡^Œ´P)R @JHƒôC¨"BE0 A\а ¸êèg–ñnև}ŒŸ÷ï9÷üï9? ÷^Çÿ!HŒyY“‘ô”ŽÉz@-ÄüF*#ÜÂ1KÇóøcH9}¡b_ÉR×h2/s/gÜàõfÝ䩼 97y¹7¹ HóþßPå´ðÝö‰ça ÷±ŠçÅÚ0Ï÷Šè€WRXä3aìA *ýv=A)%Þ(¢‘¯âj*5ybf?ª¾¦7÷¯ Ñ+è@\´åMHƒ@‰2è ¾ü ÑÔPôã7€á¸]÷™ÇAPëeêýB<Þ*#ýæëÂËáq¿ +ràì|ôh%‰x…\Né/bÒzð|VVÎièø-¨¡ +5(n@éÅ +Œ^$͉°¡k˜ +÷­$»€ub»î +wk ¶ÔßdÎ߁z×ý ÉÝf¡ÍËîú¬ãóî0×û]1>“­ç£F•é)Ò\d7KheR«¨UŠr:[Dáòx%2Q5I%euÊè¤aYI+£‘tÒJ’^ü%Ÿ(G-÷¸i÷þl \~NúSíyäU¿ý“þ0Çß.FyëÛa‘ÃM𔋵d»CPq d»”&¢Ó؜ʳL,¢Q¤ådµœJÖÈ)­ŒBÖJ)d„B֋Í$SCÙ ÀwØN»Êyߧ6×Æ®Ó6/úýŽ> +q˜êôëJˆhMIîlÈÊm–£ðµ"YÄ+¦qªËÙ &‹WQ%‘+ë¤Å•mò¢ÊËòÂʲ¢ +­”T®“Êõbs@±©¡ÂÖ¶‚º»@³ÓžEµËoûÜ­Ÿùº-Ð~b0üÌÕÞøð‹ê䤶挥2'‘ç—rą• >•UÎepKªyÂB–B‚c^å3ûäX–VVÀÐIqUz1þ >7Ðþ±ˆí·åO;Aë‰ïºö¾tûþé¨Ï÷¿Žùÿ¨†zöÇB;»›~ICț¼†¼F-¡¢LZÊ,Ó8G€åKÅ(^“4—×#ËáJ‘]­cØz‘9 ÄÔ@·Y¤ö›A£ýÐî°ë}ßO»_\;¹û‘ÁÓê–ÞÏnäz˜GßPLhÛ%¬®ž%lÏƲ. Iå*\Y±²˜Ž¯«¨Æ(ؼ™X˜%m§K»$i²k’ ‰^œ-!øãBs@©i뱯 +Ó?Õl·u©ëØö·ûíÏô?ovµÔßô9ªÑ†¸wŽD«†Î%HúS2ª{31ÈÂâö| +®µˆ†n)c!š˜5é*!/µQ)Hjì&ª†…I AªÂ €Ë |sÙÔPsp¨3ÝF›í¦…>›M/Gl|tûĺκì¾>ímÛw3È­U¨¸ÇN‚Óӑ¥ý98üżbt±,»‹Bƒw2˜I‚j˜ºž¯Vsã:†L&9çZ&9°&óÕÔÀ·^ MïÑa½áݕ¿ÿíɤõêé‡vë´Oî¼ëeÓq'ÐEy+Ü_hˆbhÏ'“GáÙøDzCȺB(kÈÔÄAzE¿*f Ž5ÐΌÔ0"4ӌ¨Þ)ft÷ËPnjø´Xû±o]+o?سBû쨅手e÷ã36Mœ$³Poö(u +vŽ0™š†žÈÎÉ2`òRõüy=¹0^G/‰Öñɺz*T×N Ók¨¡ã·©a#3åÐᙠ+sÝr%¨Û¿ +¨­V¾»ºeùÌÝ Ë´Ï÷¬œ?²¥sÎiŸê™Ç1ñߓ¬ÇA¾Ô‡a„ñqèûÉI™w3ÓSY*v†œ5Ã(€Îð¡³õ„àY51讆toŠ4ý¨0xòQ‘9€ûírÐlµ|±ÓWӆuís‹¯^ïY§~m»³á•ãÑKwæ¿|NQ^ùáç#B‘óqÑés‰ç’æғæi1s¸Ìˆ¹’ìÐ9ZnÐ0/GûÏ·`üæ{ò|ç®åùÎßÏó{úcn[:6-›º¶2vk-äò»oV´÷ZÔm-…FÇC £ûq²Ñ÷Þâƒ4F¥c͉ÑqÆ´ø(c jÄ&†‹Rߕ¥ž}ËLó{#Èð}£Èôù½9Ëû÷®,¯×W²Ï¼3 ¨, Sý«!×ÇVCúfi´}ؼªîþMüG¬è‹N‡K?z8à–üOæ.{—Âý`Ÿbc?ø[BD/b¢>býÿSç»P™àýoö9¯¿„°3)Î{þ©J<ý¾#Éã}Yw:W@F4« ÇWAZï­Y¦Û¾æ‚ý[hÀΪ8,žvàë˜ +]Ô#ÄxAÌ7¤ú‚Ì€³èòƒ}@aˆ ‡zZ˜`CÝ? ÂO-É"ܖ#Ý>6›5Ú·Ò;²Ò2µ"{·þ+øvM%°Þ\ ì-±Àyp·I^vqàìñˆÿ2_gQM¦gÇ9Ž=Ç¥=Ggè¨ã>â(*(¨ÈŽ¬²;²H„„„ìd%| ä ,심²‰ê@EEœRµVOU–‚ ‚0Ž‚l*Žöéw¼o®{ñ»ÿ_¼ïó¾„;‡CŒÛi zC¢g нýíã|_Hõóù)OÈô÷m€;˜Ý 0Èʃ]¡Ê¬Ž›_Y4õ®²(ùÊ"6¬ÒÀö5p`ƒì63Àq' Ü­ðàc‡~„3‡ƒ!Ê>Gý þ¸P¼€~Â؎Àwr±³+ ..€º:ÊÍrÜN@¾»šuᎅEùc ãô*‹lظ +­àÕzÜHûMQà´õ xì¿Ýþ²ÇÂözAÔ¾“€ßïDkW p†¤ƒNÀ8t8‡@`s$¶Ç@fkèa;P±­Ylµèöë€én "¿b HäQÆºˆêù¡…±Œoc.᮳cºÙ‹Ñ÷9 Ñýܹè1î¯1“ܸ—ÜÑسþ?ö` v뀍5ˆ}w²äG!¸Bj¢/ðY¡À‘DÅ}¦éˆ¿S +È+¤³Ô÷ñ5ôwqŒåØ桍½ˆ»ÁYˆéæ.Äôð棇x¯cÆy/q“¼1Â4o(v†7÷¿kHÆx®– õÞAûAn8ìx‘|Aœ +‘õ“Æe=ä1ùíıô.êóŒŽ$ó€³{5p°¹Ã× qÝ +&+ȶü0ȋ9 †ø€55l eãæÔ„ßÄJÚtJ{’UÈK®?Mj>¡´"ƒäkò>ÒíŒG¤>EOâsE7åڙôý+í©ò2Ý<àb )‡×ƒâØאãòä{ÅA¡øÌ1(Šrû˜ë·hH<=«fDÏ ÂøH:í™XÃNÉô±KS2jd¿Ðš2îSBïQº”w)½™ÝÔÑÌ봑¬6úHV+c$«‰ið°í:ÈÄþÕFç-Pä½Ê¬¡,ÔþSY„Ër Þg¶€2m¤GŽkøq#(BíC²8Äzáý”Bé]NEz7³½•Ü’ÕI¿¦ºN¿£î ©/3†ÕÍÌau#kX]Ëy¢2x»VƒèÐ:ȶßyΛ¡Ôk”ŸÚ•Á‡?T†9¾­ˆ>ùk1`¢0)쉑Kx¤’P{ +Î]D#ú›Ø„t +J2:xՙíœ&ÕV›¦•ù³ö"ó_ºóìëê8CÚj‚7¬1R°ÉÁuØÓ² +œ6ÁYÏPå»÷sM ÍÒ¹½>÷×Éj‚ïèYÊéÇù,BOŽz;[ÆéRd‰:½¬MR h–g7óë5¼V]=÷†¾–{__ÍЗósʃºbÁÖàc ÒkA‡í½ENßBv?k¼÷|¬ó?0ßj7Óá8ÞH89PE +í-aàoç¦Poꤜ«Y¨ø²B#k–å¢ ©¥ÙçÄ5Ú*a³¾\pÕP&¸k,ö +Eú|ñ€>O<¨3çKb½ôXC‰ãŸ¡Êm+Ôyî~Þoߛæ`›©–°££b<Ö&„ü£œŽ»UÈ¥\5Š9—´é¢¦¬lYÂ€VɋTgÓ*uÅ©ç ’6cž¤ÛdJí3¥ýFƒt@Ÿ“6˜cv®ùþµ`°Åö^GK¨qݍ;—š}¬^] +´žh;c;ØåÞÛH é®NÂ]/eS®ä Ù ˆ¨V«”UfëÐRe¾ª ã¬Î$¯7èe—MZYW®Fþ0W-ï3ªåý•|@oΗ† lÇ1a ؜ªuÞü©ÉmÛü%¯]ÓíþVÏ;B=ºévïB\pW-%¦½‚™Ø\Ìg×åKE•R¢S£y*“ʐUªÓ(ϲѓíÌEÑ_0}&í7¢Š½9 ÄÐÖ@žÍŸ  +›SõŽß®\tùn¶ÍcûÔu¿O:ƒ>hpý{+!èZ#9úRM2¹¡œÇª* KòåHž)ÍÑT*m‘N©®6¤«šM2ÕµÜ4Õý\DÕgB²û²¬½9_2÷®›?Bõñ pÞÁòÝ%ÇM¿u¸mžøÙwËÀ­€ÿ¼îÒuØÖLŠºÐ@#ÕÔp˜¥åBA^ ’–S¨Tü—Ï:§:ßã8þ³·iQªi£mŠŠlY"ŽÝYÇYœÅ9Ž}Ï^ãPd9(RÒ6¡Å ê–D©)L¥í†I3ƒ %Í8‡îÜ)Ûûž¿îüñüûóúãóø|¿'r2$E9)yçó¥W âro•¶?(}S—Ó‘ŸÕ) âÖ© CO§¶ÏÇ¥]‹ðãî%c7M–5Y,íi±Yñê!iËãF²yÃ-_RM-Ï»¢RÌ?{9,¤èRlŒô|RRF©$5õtÖÑäâYqE¥ÒèÂËù…7  )¼É<ޑ×) â Y4P¢¸SFš“5;Êî/x´W³û©åòg-ŽÍÍ^f7ï2œ®ÝâÒ.Ԋ¸ÅU!AyW££2*R/}8éBfzì¹üc¥%9¡gÊ¥AgjóÄ¥:ó‚NwJC‹ºrgƒECîzuœÛ6W·ÏûzsëüáæmsûÚw©¿~a®ÝòäÀ¦†Ç¦5ÍôeJÉmNÁ qæõȈԪ¸¸Äk‡Rb®‘„WH•Ÿ:&*»”í_V“Ë/»ŸË+ÿwŽÿÅ_rDgßfÏIkU¯«†‹[4Pe 1vGO}°MOµ»Ó@íٛ½K›_Øo¼ùÔmϕÚþ³Yž'î ˜Yw…’úðÐÄÅFÇÜHN«M?x=Gâ_sò·úb§º:“Uݔɬy•É®|—É­˜¯RA‘b/+ôÕ¦êtUÿ|¸J¥÷Í +¥W¿mR}Üm²øN§ÝúªW®ÆÛ)6'Ÿøºå´ð|Òð’„ŠcîDŽ…6%ňÓâw³“ýŠ3ï\HeÜ©’Ð%Þw_Jè·{Òµ¿§1®Ï GV(£d2*uTþnÐVîy¾€xÕ«E´ôé«5öš.¬ýÝvmy·³áéN²¥ô5ƒ”þҏ’Ü.bÆ< á‡>‰üœÊo“DrZ³c}[‹âè-¨­U‰”ÖÆ$rÛËDòãþ$jÓû”Ù {™.¬TBí2¥·æ/^Ï#.SjПS3°giù{ݒ>'ÃüOó£¿Ñ’ßqÜbº…´Ð_B˜]Ñ\~g¢Ý‘&ftä{wœ £t\ ÷ꨎðèlŠtïzáÞ9éÑþ)z68±D W–oæÏZç?uÎ#ꇗ«T ,¸ôiÏÊÓCÖzҏNFé<,’iöQL— ¾—°?ЛÛéËìO`ÓûS¹Ôþ,W¡Ð}àœÈuàšØeð¶Øy°ULúÐ+véûSìÒ;3œÕ$~­S'žÞÓ šŸj·ÞÍ#*eß©]”o^T,7Y+·ÑO“;'Ê=Ì#e4Û@ӑ/ã¹rdbO†,œB“ô&ËùxȏúºÊóY¤Ñ¶ãh™ŸÃØu®ýX#wÿ—vžÝ— +C3ê¹¢L<»­FÜ{¨FÜx©A\ÖT:÷ύ¢¯Û´²¿š®‘|³ÕO'íŒw7S­xã [Öׁ>!r¢L„:{NF»ºN&º“&%ž¦²ÉöS…»é³T›éË´}P<4ÓMt«éç +/fô¢V™¸wW•¨kS%*º4ˆÒ©ÅÊÇ¡;÷ µRa¾:6Ãp`«®F~ ›0àcFÇÒþÖn´uF¸#ÚÛ#ÅÁG÷!×É +E$Kœs¶@…‹9ª]ÍÐ0«û·”‰ÚÊDù âT‘eÊØ8çv,ŽÉÊ`X­`¿ ¤ÍÞðØîÚN70Iàî>¡É~›Ú rï>ę["ÅÂé–fȱ2Eá>œ±Þƒ¬w£Òf6uw•ˆ²Ÿ ¢¸‹ rþ3W)˕¡«Í Ä0Òâbï +¬WSà ã— $xé9À[ßLkp·XB¸ÕAÛ̾ݱ†{´c7$;ŸC#äí@±±!ÎïšMùOŠù/ âX/A¤bÒAh)c¥Šë5˜Ø2Ÿ +ãEî0Ó"ÁZÛ+làò xÿÈ­Žj=”ûœir›ß$ù5w«ûÕë÷ ù/îU΢rèc3úƒÀ\¡¶Ë嬃hòD1w!Ì߁av%8Ÿî?)¬b|ÏùÀ§ÜôJ¼ëØ Õs¦©Í~S”6î$ù oÜë=ï¿äO¼QÊï3MƤòþð›øŠ¶¢Ad¦‰pmÄ:éà ×fÄ2ŒÉ·@H°Äq$øKÜÁË¡€Sä æYeLøT²§éµ~S´zîµ™7I}§t ¾’_(¿h#‚t™ !üÊõŸ ŠÎNuˆM5e­xÇuHð،xº1b¹´Cp ‡= È¢‚{‚v)ÌKìiÆ5¿)ŸZÞ¤w=‚ö@0A}êÿúNø7åƒPFû,¢ÿ`ȄݾrѦ<`&è©ÂOÑl¢‰X+m$9¬CŠ›’iFˆg›#Zd‡Ð“= Ì ‚WÀ§„5ÍúÁoÊ÷*o’Q+˜ ßñ÷~(üF{.ú‡Ú0Fû0LÿðÞw$àsDüš% lgËgEw‡:Âv/@¼Å2Ú¿©.úøžb„Öÿø®Ï°¦î=€ãl.R«¨-Õ:¨{R¥U¬¸p#V†$BBÈÞ Y$9Y’$Œ0BŒaod‚ˆ¢ (PW+^!,EŠ^íµÖëÕûïyú>÷Åç9/Ï÷yþçwÎù}øq“zPù!€ q©ˆO±Æè( úCTö=¢÷gd þóW o#ˆoŸ_F¼ M"æˆ#Q/IÃѯȷP¯(7bì¸5.³Í 0w~áýB~`9PXT?ú9â; Æ<ÒqÀä„ü— +…¿'jïp1ÿƘ0oÐE¸×¨*ü«¨Fⲓ<‹è£Ì ~¥L!f(#Q¿Q‡P/iý1sôkè9ú•Ø9†= nÀmqœíŸ©ÿbø5Ð_ 4!ۀú¼?PÄìÿ(Æ}ÏcžyËJ MKB¾$¥¡gãsâf°ü³Ø2ÒdLeÕNµE÷ÒF£ïÓ£žÑc~cÜDϲº1³¬ì vKœ}76¹¾¯'Pì^4û—Ôc«Aê™-àB¸ßǔè} 7bjðŸ6Ö#§èÚØqr&î)ÞDÁQa«é÷c›™ÃènÖ ú.{=ÁéÅÌpº°3ÜVÜsnCüsnÞ>@XíÈ\þ¯Vïò©?,† ¼ñ“!tÇ»4äÞ×Ì¡Y%éÔ´”jH#uìz:~˜’C¾C´ÐoáËX}¸:No\{Â5ìMÞUì¿÷Œß?ͯÅOó+‰Óürâ3»þn ­w’Íó€f×B`Øç ²áÙÈ9µþ½ñœï›¬HÿY}Là”–pü©Šuö¡Dˆ(0·9ZÂMFõ5ŸÙM.ät+yí„&A þª° ?,ª'LŠªˆ“¢2ò¤¨ˆ2%´þ€ø `¬u²Mà‚ߐð%È;¼ü“éĚ·¦Ísyá~ÓÆè€QC|Ð íì%Ù'‘bzjb7ÖÆ2²›éæ„zj© –R—XMþI\Iº-)'KŠ¨b mB\@ŸḨOÚHß8ÖW ØèÒw~r–€‚CËþsñ¨ÏkËé 3–s¾63ÒÿQ6æÈÝ4rÈÍ6¢[!¶KÄ&¡–~™—Á©æäó˙…¢F•¤Þ"½D»]¤?L ›4—9.5²Æ%Y¬ ±=7páóHÚø`Ø1äï],ÞY1W|rÍTñÙMO¬çwå£÷eCº/0mÉ|Lƒ"ÖHÕô +Q§˜o\J¸˜hæ”Kóٍ²ÖU¹‘}_žÉ“¸6HϵIÓ¹ã{nàù¸€ä î žOó¯O…?|ñ{ÉÁe/ʏ­²U¯{P¶ë¶u¨''þL‡Ù KÀT«ÅÄ2…’^é¸fq¦ OhgóK  ^\ÏëR¤ñ©üQ¹Ž?&Ó +lLjüÉwxÇѬwÆížÀò݂Å{ÿ«"ÐûYMв֞\;TêwÓ}°Ë„ nʦDÖ¤³cËtB¢5YN7)S¸92½ Cš'NÃE¢EŠ¨C™,PªGI‰£ò¤Ä1YR¢ ²PàÑJ [ïr¿¬»çÿYöý¹š}‹'}ùKý±5Uçvö” ´Y°§/ç‘Ηg1c­é|‚I'¥SÔCRšà‚Â(N‘Yd*¨R!‡Z•2¨_ɞ*!hTAc2™ÔÙ¨pƒx¹3H]çò}=@‘ŸçÛÊ]ó_ÔïY0Ö¸è^ÓÑÕ}µgwt•# cOU™ E¹ttAVÁ¨Óô©JŽN«¨S²ÄrµY&U•+UÍJ¡ê†Jô¾ŽÊEÊ1™Haƒì´UÎ@ú5¼÷ÂóiÞêþ¿Òí¯kwxN·ìö|Ò¹Çk°5ÈçzCÈö¶êóûëÊÐ'K­ñáÍԘœ<^Ÿ-¢j3äì$½†/K5ˆu&ˆ¯-Qp5 J¶æš’­Qr4£rnò˜,AmƒìŒ•Î@7dÀïìK[Ü>TluÙ°Õ}¢s‡ûëþ oýtxՕ–`ߦËû*«P'¬¥¸°¼B2Êp‘¯5 (ª\ˆÕåR' ÏGÑ&×w5\gZ×»Œ^ßì<|}÷ç½ÝW´wœÞVÛPr9꘩{.³œ¥+aÄ%òÈR‹˜!(Pq9ù„Œ<£˜’c…ˆ952|N§<>÷gÞ83mR²aÜ.°Ì $åráç¢tóï >ÎSWV:ýrkµÓí>¿ùW®XÞØ}rKEGèK 2È؀9›ZG@$UÓb¥\‚ TDc+Ø´B-hÍâ.YÄK•}©6(E[Æ%XÓ¸$.wBlÀ÷×y;ó +§OU+æÚ¼Gû½†î®r꽳ݳ­ÿҚÇ7õüèŸÛy(½¬n‰€)(A=Ç®’¨52:¡ZÃÆVf$ +̂èŠJ²¢]„¨¼#Š¬˜EO‰PÖ)¡=@ò…Ð/qÖ¯ßÕ/qxÜãépoÈÓ¡ÿÞrÇΟ}=ê¼KŽ®+èñ3ôF¦ô NȺãÎ :ÉVMiçãð­ ӒLC5˜ˆævDS7¬©Ú<›â†]~žQmP.rF/Pîåð¸mžÃ`¯‡Cß½yݏ—:6ýºÅ½âў%–ûGVg «½ ¿uDЏ fõ‘B)7ˆø^^Lìu)6úZ2>²ÇðÝuÕ䝆üc Ъh](VED$ +È*›¬²dý’/ûFI¡ +¢ ÖâŒb­Ö#ngT-.uGÜ·ºÎ0µn€ +£BŠ€„ê39½˜+rñ»þ?ïù¿ï“%ºRC]9œË»R·„¼zÇêU.y¡;w®;ßl˜`ýWâñqâþyâú-g¢á?cˆS­_Ùiç¼ïyÄÄíÏ=*³|Ë BKZä±ÿJO6>Ìbë›ó)MS‘XÑT*—4V¨Uj^cu:·ñZvc½–ÕtWËnêÈ`>èÓ³~íË´[ÇÏ9N;W/9çî¹'ž%j:f8ìéð³­#Âmã«ϲ—Lßâ¼àüviTv›:^ۖ™œÖšÇ”·.çŠ[Wó©Öïdë1§u—„ÕV#e´‘¥¶ß´j•¥´¾“%?PØbªv$šk‰«õ4¢î¨mv!˜&Øí2yÒ¶šü]7tGº۝8«¨›é›×Í Ìì/Ôt)£]º8IWN¢ «0™×µ’Áé^ËbvWrR»·s“Lûy‰¦cü„?øñ=÷¨øž*ÎÔË·åß âú/ÄÙâèm±ï‘ ±ãý$»ÍÞ΁ãKÍQîËÌ ž¹æTºÞLú¥ ŠeƒŠPÑ`F80+ŠcÉ_Ä´ŦXJãU$& U%Å ïJŽ>”=r25jä"#òC##âÃK›nÕD]=qäš=±§É‘øáågDåGwûï>ѝW!p|!Âݲ7=É^Jp|ÄøRùq¡^À„>(9!‹Q’…±( ÆÆÈHüŽÝÑa¨YŠ“1!¸Œ;±¶ÔÿBG.Äî;QõȞX?2În ¦ÚÁÛ)~c3:Qè/¥Hœ&à r"ïd(|¡¡Ç!ó/1ÈñBá¼”ø…¡Ì?­ÇÈTúã`ŽÏGMGë bÏ ‚Øò Ö¶ÄjŒ·+„›}<ÓAw‘#`¬ 'p3‰ÅnI`ºÇƒœÑ´(ȦG@=# :dÏ ÂRÏÏòïy¨˜=[¼éØ9Çû}æ Æ¦½—­óß·¾ÿ„ V˜í‰|Œ³Óa¢½S„ðtä‚—D„}‹è±ÑHp GÊøP°'ƒÿň'úC>i>ԓ}¡Ÿ<9S|Pà6%_z¡ÌÝÜ=P5uvØ1Ýü Ä¡ÎP/r….É ™Ü™ÐIéHÏ@Z^(ä%Q| áæDðJ¹/Ü&8ÇX`ŸaƒÕÀó:Œ$ÏI¤¾á!µ÷aæ ²†x½ìa²‹;Â{KŽîÿ¤!ÎȈr…a±²93aÓ¡Õ@“ +eq¤åqýu1ÛSÀÛËyˆn-œÓ\°H°nðÀläƒÑfÕÅÿÄ裆XƒT?gˆo"‡ù¼aªÃHè i9Cé +c‚rY3aÒaH @FVҖECþm<$›’ ü1Ôn&xÙ k¹àž&Áiàƒ}ƒV3æ ëêš#¬~Á{Pði¼æ Ú©aa5, ¤>. Aè C¸+–Ĺ!Ÿá<Š£2úÌ0¤DCµ:²õÉoe@XÍu€ ÞQÈS|pÏSà\€Ó(üÄn°»Dö{Ñ;rPô†o½ ,â'Â!Éï6@fÍ ñ§Aà cØ8ÄLÁש(äû _î£6 ú¼h¤¯L€j] +䛙üāhÂÃÔ'ê¸à#¿NôwYŸŸ3ò‚Çaù¢)X‘<Åä,“úa©&Fc42‹Q–ò)mkD±’í¦,’B³øgñ€ð´¤_Ð íܒ½£ZäÝT§ü OÖ.Pü&6+%ƒª_eÕ- Ÿã•/ _'E‰µë}“4ßp¼±R4ËÓBoˆþ`,LÊ\jÖV°ûÕ[x½ª‚Å~±IvXÚ%=!+9§x-¾¦ì7+_Š_)[ÅïT-’õ=™YsSnÖ\V˜Ó/*G…5ƒf. 9sPlí8¥‘“P–øÊY^X#ðÅ*EðP‘.r`i^|onIª)k-ç­®’ÿßôEêÝҗªƒòvE­ò¹ülÚSÙeõcÙM‹ì…¦Y֓~Gþ>ãªò½¶Aõ^W—Ö¯;«”ÞÐú8"߇†UcPñ¾wGÃëøs-å²}«5á¦bcÜëÂå)¯òÖpÚ³×SÏ2«$¿kwÊ[4ûUՇ5ª“÷•çµw•·t·•Oô7T]úKª¾Ìzu¯á”¦×p<½×p,ctPY3dz;¢ÐÚ/Jý?GÅ Øë†Ê”C›È9}ëÅ~ÝkUa¥†˜¶ÉO¾^ÅiÉ[+h2VJﶩnë«57µ×^KÿYEsÆpI}%낺)ûŸšÎì3é=Æã=Æ£Úc®'ûþݨ6ÛÙ^Ž(²ö‹òùŸaS˜+6ÇLþX•4í}ÛËô7oçFyPë:}Ôo¥K’šVqî.[#¼¹´B~5wsÚ¥ìç {õõúš¬³ºÆSÚÿÑ]_QM¦iÇßPŽÊXPÇÆ2*:Š‚ +‚Ô қR éɗ’ ÐIh’¡%t!€Q"ʂh„ãx”wÇ#IY –fçÛoö:^ü®Ÿç¼åâßOèŽ×»âçˆí˜ERSâ"±»H¬ÃýN¨ý +8ÙáïæLAöȲ5ƒ…Ç,á2§õ_*\7ÿ»Â{û|ùŽ³%a?<ˏ=õˆ?ÿ òJI ¾ÃäEÞ¢Ĩȥ˜¢ۅoÄwà:ˆ­Øäfì0E¦4à(²¤7”*ü²„°HÅÿw #­•jcç\ —Ø[À•§¾Y’ºX-Tylý­Ê×fº"Øn¢(êäƒ<¬Û=Å·?|#åjd7+'æT”ÐJ­À5‘k‰Är¡‡ZC¸K«&<¦K‰:Z%IO‘¨¥ä7Ù8é+ê6¤9‘³(8°.?b¾\å°ú­ì̺ù:·M/ê¼·ý, °Õ”]r`\ûsH¾×3A]iœÈ¶+üØ&vAB£,IF¯"I©rj%¥‹^N€Ê(ãP)õ5TLÕх4=M@[ ~Ì¦#½™¾Ãî3…+™}‘·Xlp\óJá¼~ZîþÝ#™ÿÁ‘ʈ꒸sªB<º+‡Ԛ™)¿šSËÉM¨J)ÆW²Å¤2f=µê€P£zÈÌg¼dä1´P.SGÏaêiª!p2›ôo;Ò:È•Ú­Xª?f®k:a1Ûvz͓f7ë‡õ~îV…ï+9§,Æù´PsX2^ZŒ$=+AÄà‹S+ȅ)µ´¼äV(›­bòÙ#,^ò &/YËÈLÖA™ÉzÚ×ÀXäØHóf}g—!ÿ´ÆÖôüðŠ×mG͞wž°œhsÝ:¢¸° 6ôÇ^I´K»(Ñ[^L +”0"Ĺ©1eY¼af>?½ŒœVMËä63®rz™\Î?Yî BËàr´—££s9zš!p2;iÎk#¸|·ñrÝ“ß[þaò[×!Óg=Ç,Æ®¹l¹×‚Þw³1øXWÍeçf Æ«VDÓÃË)ÑÂütL^Nn?«„”ΓÒ8™rFJF7‹q—ÅÊxŠ˜g°3´PrºŽž|UO3& ³S¿5‚ó·¢`±Ñ—ƽÆúŽ}Æ/®0~¬²_5ªtÞ<Ðá³··9ðh[C䙆šxO©$É_TN –²£r‹Ò0µ¡ó–»\åg'í9YÚåšßŽAóZð-œÕ˜M«¿O¬ÍÁád%LM59¦º…U}ƒv¹ú!â5Jº@©X Ä–¿1f¯GÁyëP°døвpÄ.O8öûó0vï9˜´ßf< smOÁÙvÿc»ÎÃbÞ÷8€fZˆpµ(%-Ú$TÔ,ÍÚ,5ÓìK3Í4íëHDuQ¤P"KٗdéZN<¸9–ÇÅå\—ãv²updi“ä}Ïý{žïóú>¿ç÷Ïçýûþþù¾Q㊆€ œ– `´á>á7«ZN‘HM‰ùí$RåC©¸Ã†´ãGdaªî”øÙ+2Z‚ˆ±BÐ'pÁ™Ä‚p2ñS£ š¾úáHr]ŒŒ™¡°Ì +Áj· ¬›€yhðôCÓ_œšãƒK^Þh³êàybþ5bþ=©è‰´lО”†±# p¶QÁ•,Á[üí8XàG*èc–‚íÁ¸E_ùOó¡ãD¢NòC®³VNöš)ž¨šêúi³Ñ8ÍG§»á„U;ۈù·‰ùÿ&‘²_’HfPHZŒ!IñÓ!qÌ"ÓáE‰„¿mBì"Ì~>"íÁpðg¤#½!åù(OhgÃèè†ôÑ3aã‚ÕNÓQî4›ÇNÁBÃ8kãC{¾-„!v,t€’ê5×J‰ d ¤ù@T~Ù|p7‡‚µc1˜?‡#úHÍKAoí*áV¨© ¾"tÓ@í' Ó@ìƒ P{™ }dY¾7Ü` +bƒí u€:Ò ZŽ34b(µ¥ø@¼,¢¿…€¿i!¸ÛÃÀÞÖ¡%`žŒDô¹(0~¡‚ÑNýáô¿}„ïôï â‰úG6ï9Öý?CL ’ [(B [â=Ë q.Ш= 4ûBšqq„‹ÀßÞî%àˆûxØg¨`]¢yæ=¢;£{¢‡ˆ5Àã‡xÃó5,k 2ý)ùÛBlÄp'˜˜Î0‰\ Wx@cô…2;ÒU ._ QM;#ÁßÞ¸Ítp[à\û6s˜ýŒùÝÅúÊþÂêcc~æ€õŽöËpþË×ç’çGÒÏú{˜ÃœÊ˜„TÁ ˜e0è}¡Í‚ª ²5alZ‚¸º(ˆöÐ~›ß'¢‡øgYßb.³cn²ûy8=¼×œO¼Oœ1ƒì·1àv +À{*DÌ¿Dà[‘!އ·-Ló쑾h ²h‘Å›ôøÙHÖú 1%:Kè°º8|H±!rPº…6 ÙÉèïcöÆa‰=Íù,ºÀý(¼Îëþ“÷^ø‚×%ìæ½~åwÇBx/¢[bëëE†Ü‹=!ÕÏ9¡£a‰š grãܑ©òN6š²Cûõ…á=ÚµQŸTUônEó/Ùö»øƒÜ?%'bºÄçø¯ÅW/ÅwâÁsñᓸØâá¸Û’âRˆ¯È¬C‘AåI†Éƒ‚L;ä‡8bå’ñXɜ‚á¬!‹|n–>àsZzès~ÄÛĒ¨7 ѯ4[؝ªÜÅ>þsùQáSY‹è‰ôrìãø_ãÆ?ߓ¾ߑöÇ·K‡¥WäÃҋŠaÙy¥uÏ!CçNF +Ñ;óæÚ¢0xŠÃÇ¡„á™Ø|Ѹ#ùŽi{òKcmJqkjobMZŸ¡:­Oo tÄ÷gw%Ñ;×yª¼È}µþ¶ïw,pèÜ>ú·zºóÝ­B÷›äþ¿”ë/M¡6小­\!8´¼D¼ß²^¾7§ZՐU¯«ÏüÙP›q̸%½5©:½=iszGRUÆgÓÆÌcefobEf¯Áâ +bƒ,g¬":ïz×ÄÕÃæË_Jמ Û獡#ì¢Nº¹ïv¥F:¯u£náérsÔ±ÒLvSQ¾ ±pµxWÁZy}þ&õ6K­®&w¡*ç°©2û¬yCöõäòìgæu9ÝIër¿˜ÖæöËr{­A"ñrˆ¾YLtފ#¾os³éÞåeórŸùɁ`‡»{£&^ßɛu±6ÞïLµfáñJSdSy:«qM¿¡¤P\·ºT¶ee…ºª`KBE~Cbù²¦¤2Ëis©åjr‰åqòÿؤϷ&Ó,ãç%!Tª€€ ; (]@Š”Ð{ï:!PŠRƒB( R'ÒDD H‘*" ˆ °ŠºŽîêŽqwöšPagë™÷ȇßçû9ç9¼œß’‹s×ÙÅ9I$–(˜¤BÞãVK” ¬S%>žÐ ~íÒ"^õéˆ=ê7‘¸yÆ^a¡ÃsÇÔÉ`ýÑ&¦Eÿ÷‰Œ®šT·S•Y¾ÍåùAü’âðÚâʨcGùqå…'yÜ3좂sœÂ‚ùnÁÔî/.wÍ-XOâl°DÁde1Ì%ßP®D _™øý”*ñs:ñbhqИv£ÏN~Và¡qþt Þ`ë~óî¦xûv>ǵ¥6Ç_•TSq4¼¢üïÌÒÒºØ"މDn±€W4ÌÉ9z)åpÑ}Òÿ8ÙEïÙÙGדrŽl°DÁ²¯@`åVÀFExß¡³JðdT¸=bH»2`#7Õë¦>"ØÝÛaÖÑk{¢‰íÂ?~л¦>;°¢¶0¬¤ªŒy¤²&6¿¢)!»¼3)«l09£l:å`ÙÒ9éeëìŒÒõ¤Ì’ –(˜Fî Pž¼yÀyX햅—#Òð`\ÇôÅ/X˜pQèõÓí„™ž<cÓÐÆr®9‘æUÑt(€×PZø=/2¯®*æPmC|zu;+­êlrJÕ'¹ê&I˜Ì©Zg§Tn$¥Vl°DÁt²_$ X' Ú¤áE¿¬Œm‚Û“Jper7ujÜRzdÔYµgÐg穾P“Æ3QÖµ]‰Ž§SÀÝN€…A&&Èþ¼t.‹CË#I¨.Ç^h‹ñž›Òó´—Ízæ±-õ;XO#vÆ>‰Õc>N6œn¼’k°Rlí³rÌÆk¥ÉÞ}¥‹áúxÔÁåñ‚£ó“g.+¿98=úÃÉñá7Q’;¸Þ pa`` ãº4Ý£AõRP.ÜF}£CÉycJOÚÊ$ ]ㅾjQÂPÍpa´vˆ¥ð:MÏ÷õaC/áa…©«oî,lßëøfÀÂáÍ´%ã?wHo, »×Ÿ­DY\œ$û—o‰Á±Ç4(^“†‚U5"kU—’ºfJg­Ùl‰YsVˆXóV^ R x»_Ãçmœ¦çÛd-÷·;]Þåé:¾ãíf¼«Ö³{ßl`ó^`h½>jdµ~ÙØrãégc‹÷"Íô t^hX¨x@@á¿Ä!ûƒü°`ÿ©C‰ýӘùÑJ*䣃tÀ'w9ŸO~[=>‡*¹~fnsúœ êð…³ÝîK¦ú¾¯ù;¬¾–jZ|­ûÎü[«–é·í=8¾ÓtŒñ#Š42Bö/’ýkdÿ@Ás€Ìu:pPâQ•ˆD-JêSýьæ…6t7tÚ䌞[Ð_ÚCe÷!SÎ +ãö"g«f(š`¾’–*`ŠžTݍ=ª»ðœš.În×Áe‘ä4.ýÛùO¼Hü"Q(¡¨Dø£†˜'êP\Јê€æâ¶hC³FG t£›¡}Ja¸”FKé!kÓ.<°y'ælÑÂbé¿aµŒ&6Ëj`鬜:Ž‹Ô:7¢Óictì5A‡á=Ș0EƬÙ_l×WXÓið?M±1Š2¶qäс€‘J$¤Þˆ„:&$ôé*eQyPÔEY+:긺ë ì¢(«¢#ŠŠ Î~×ÊÅïúœ÷|ßÍ „G ÜE†ÀíòÁ 3N:8ͺƒã´;8OzîýÀí@¶5š­!8ÇÕøÞ&Àc˜G´Ấ®´ªÚ +|5;ÀGk ¤:{ðnq¯ã»Áó´#xö9Çgð¸í Äã€8†ÓßãfˆÓ¸/à<…æ ù.o½ÀuÜû[@²1?´s‡!píŒ@ˆ3‰§ ˆif ào^ˆ9°â-€‘j þy;Rf¾5@nrŸv' tR/ÊÒï2ï}ÃeÎû¡ë_^£®SÞï\?zqý€fLxÞ7$À¿ð½Ï>hš•p¬ A¸Ã¤N‹AF\2ʐr6€hújіÀI²†€,[ íš÷¯tœ£Ö;ÍRZq3~.Ó¾g\¿ø^Ø3EÀ&ÿŠŸ$àߑßâßøNá_“Áí%Ï|Áý +Ÿ,ÈÖèÛ @`iRkCÙ½ÂÝV@8y5„l€ ±9Hä–:¡Òf†§¶›fìž +(wúĬÁMқ\?ÐÚñþ'÷¾ó?ëö–zÙí uðš:Lów¥~v¡Î{ SÀó‘?xýJ¯;ôoe;ºêºÔ5C¶B„ý"ˆÁ/ƒoSˆ¢¯ŸlþKlñYk3)N¶Ÿd;¾åáÆ9•®¯Øuøÿ´ºtž3{ܟ1þN|ʸIü/ã‰ÇïŒWŸ¼ÐçI÷èàs‹ >@þe@³Ð>ê™AængkJ—¥ ôX©ÛO]û%–³i2Búӟ¡‘Ö¯eìǤ鎣â—§Â2üøՄ!nñ §Ýó1»Ûë!«Ïûk€tõÀçkÌçkÒ÷:Kç7ÀJ?(}\ œ[0·êƒøG}EbÑ=l Aåd<ŸL0™R‘×¼?ÀÜ8/Úò":Ìê©<Þn($Åé_AÙ{w…µ^ƒ‚fÒ-þqò ^ß5^?e€{›z…;Bíç½ó¿À›¡õñ€Ö#Z·h] ¶¹>HQçŒ@[ô!½MÚ®ÅÓé{–½W{­zê¿n4‰¿yX)Ûþ(6Úî~äç;ajüÍà<âµ ¯«Ò*Ÿ+õ¾ýâ6êEÑIÿóÂ>ú9á?½Ânj3¢qf·è ³KÌ10Û$H 0¾<”_†ú^ ꝉhŸ4 ]–­ÑÇ\ܒñ\w“Ñ,_³!5{ÓoªÀmw”rûqûqQÉ{/Ë3=.†iH}!å¾½²jϾ&Ú)iãd`OÀ‰Àˬã÷Øícì6é'v‹ØMû€U¬º€åE]sÿz=HÙ¤™[õ§ó­ þ<ä°èE!~鰆dú[6ó‡AµÈòZrˆÝå„܅øngcÒ<{¢r}ºåŔa´ŽÐ:Æ߂ÛX­²nN³ì·Iv‹× {Æ« þÀ=¬ãV‡§*8•¡ÀþˆP~¹™$ =ÔQï4×ûXh©ÿªÔÖp¤Üyñ£bUw +h¯eó-/©ƒìú’#{(ܺɞq™äö ¥5ªŒ~4¢& A~”]ÞÉ­ ;˯ +»&¨ hÃ'ø‡Ãçøeòy^©|ž[ñ-¬ÓƒHÔ7“PïÌ\¯§Ólқ(Ý¢÷¢ÂJÿÊ]‹î•»w£ˆºár>×¢/Kj{Fîܕ·÷XR¢gk‚šÜ´?—ZWL¯‰©dUE7p´QÇøå‘=’È_DőE…Qo……Q3‚CÑ:~A´ŽW=ÿ ¢ü1¨ï%£Þ™³û«höF»IïiÍV½ÖØ Vº™\-ó[¡ýSO¾xgWV¨S{zôÞæT¥gƒ*•|$1‹Z•pˆqXq˜U_Ë-ŠkhbO‰òc/‰scˆsâ^‹r⦅Ùñs‚ìx!„Þ!n꽫QßZƒM•}½üy6Tÿv¿n§áõjüŠþ +òºÞҀ­' …;ŽåË›³#ñõû=ªÓT>)éÔ2U>£(±”¥I¨ææ*›ي.Q†â¢$]qW¢V¾«•S¢4åœá§)u߀`”_vP¯Â@cŠMjM±çµ¦Øã¦õØ`£áÕ:×åç«IkOk[Ž— +lZ +÷í®Ï—ï©Î‰#j3I%éi”Ci¹ô¼ÔbVvr/]Õ$8˜Ô)NIC5ŽÞCǝ¼†/: ‡;Ã/‰î1êÈìn&ýK¤ `ŏ‹ÌéX4jFt¢è‘M@-ýè + aÈPÁ” ÆBŒzVÆYúa²åLÌçƒYㅘkÅÇ|kOÜbÃÁ¶X3ÁÙ±±Í~Þ&çÀ6r6ÜÈ»OúO’žG˜…6 ÅÉ DWŠ9Ôô¢¡Íƒi"”Ó½QE ŽÁÃh˜î˜Æœ ,Ü0Ûb*®e9ã·,'ÜaéˆÕ–S°ÎÒ›ˆ3c”’3°ñùÿ{¤ÿÀDúQï4H…0´)ځ§PüqE„! +¨<Q=0€ÊƪÊi®¨¢¹`Í 4L OÂtº=.¦Ûa.ÃÿÊ°Á"¢œaÕDíìCE©ˆ†Š™4TùÓQÂDU8 Ãc¬P™f‡Š¬É([åˆÒ .RìŠÁn(®žŽA‡ØÔÀÆÀSîxÖÛÉX·9ðøxG r09£Äçÿã¢ç—þ˜AæCú„Ú—ŽZ1µJj Ö¨I±Gբɖç„ò‚©8«hJ¿›Ž’*²µî\ïÁ'8(>M\ä¢øñ£'ŠŸotŒ b`”‚…‘‘Ö8ÛdÚLTíŒÊõ®¨ø;YúR6Ê*ÝqÖ~œu˜ƒÒF.J›=QrŽ‡’ˆNÞ¨äþ°¤›?(éãõKGy½Rä” àƒ…ï$èõ%”zQQÅ£¢ŽGC½Ž1þ Œ•±0VgÑñö•á€º¯œQ»f†Î@e‰;†íä b/CxbèQÞ¨ü$DÞ*ø,¿,’ß È ûä]Âß彂wòá9zõÈЧ[†¢—ò±0”OE-‡Šz cÉ ¾ L”Z`¢Æ +ãcì16Í£³\0j…ê +Ø#Ú­œaM™çzo0|?@uDЧjö*[¼>*/x}PÞô~¯|èÝ£|éÝ¥úèõBùYôß0œù< }Ÿ…¡ßc%ú •\*ÎfS1–¼wM\¦’ýH ¶Àt¥¦èíÐdrÏtŠÍqˆþƽ7j÷Cd ï½n§à]į7¼{´G}^kNútiÚD/5×D/4D¿j=Õ|ðýfØÿ‘~Rcà5ÝýÛuÕԙÇqüIDÅQ‹¸âŠˆȾCHrsH Ä’„„}‹ì;‚ + +#x Z¤Ê´êiëÒZëÔ±u´ÕZÛ>sûxñ9ç¾|Îïß|ƒ–ƒûñŠµnø.<ŒÙoã±{°`‚÷ZÈ$™ýÎÛúkT¬åÿ"¹»:-´~*?ô"Xuô9µâØ"Zü{J«ÝS¤çÄ·ÈûÇ䱓É3_“î:Þ'/:._;}Núèæ5YöM–AJŠ"KA¶ €Â5à©î© Áí*#p£ÑL6¯#-»pͶ†z7Ó¦úóÚÔJWn]Rc£Ô&ØËÕÜSÙ¥î"•Ä;£HáÏ+,%p jHœüVJ¢be)®Q™Ša^bß(,Dò y)˜¼|ÌZ)qà®n˜­3כ ÁX›)¸Øa zÚmVµ´º¬­oöÛR¡G,KëÃö)k£È«™vٕɎÂò³®|­Ø3­LV&–V™%ÍäXU?…¡š@£UwÐÕ(1Å¿!1ŐÌ(Z¦‚eÜW0Wi¦ Àx«ê6}=ÛA{ÏaƒÆ.'ãÊŸMê6ÒeKȞÜ&ú!‰>Î6³!é$¯.ݙ[+tOªÎñfUùÅU”FWœ#ÒËûȑåW‘ˆòyÌäÝ{R„’"µ¸äãÀwyÜÕp£þьÝôõ‚ös 8€¯>ï°ZÓﵡ°7È"·›f•Õi-hgMoK´KiIuHl¸Ä7IÝz¥7½QëÑÐÖÐCi +n˜ +®\÷+‚k—{'à«B>«àº®´p¾€6¬?‡7‚êË{qeÃv†…C·d]@?Éߓv>ú §e“Лb×Ãwˆî–8Gv廝îÔxwÔ{S;º|)WüŽ[˜E?rÛ/~äV迒g9Øjfjk`°€Ž¿ûs€òñõ@=a…SN3Èw1_õ3ã"ܑНìÿ³]§QM^iÀïû†@Aö’…H ,!! „  aÈ¢ˆµŠ ÇÑÓѶÚN­£ŽÓjkkGfܵ"¨hE . ˆâq´­ŠÊj«²ŠÊâ3·Ç/sпÏÿç½ÿ{Ï{ž“¹ü¢sfW/Î=¾4Ìrl•4óØ:¹ùè&eÊÑ¢ŒUûԉU'bª±µ¡r(ÆPñV_ÚÉî}‰P#>ëN„ŽâöWüùý8ÿ,Ö×9¢uõ ´º>üK½Ü~i]ìԅ“Ü‹/¤ÓçœÏa坟Ýy®DU»D˜^»R”jý<ÔhÝžhÝ.·î•é­Õ2µA®·>‘éÎ ÉãNODÆÖÀ{Zñ\ø¡êÝü¡¸ƒoO#´þ"‰V7ÑЊw´ìŸXÔN)iQÓæ¶ÄOÍ¿jr˹jñʺZà“Þ\Ì25/æ$7¯à'6}&ˆoÚ Ô7}×´G¤m:¬i¾Œ=iƒc®Œ‡ª l²ËÛ:…;øwP^…ÐÖœ¡Õ´ì Ϳ㌊Û|Q¡MDäÛ”[œ}–Íè”fËpNµåºۊ<ÚzÇ·•1tmk|cm_³blÛüԶݜ¨»Ç¸ª»—°v®ª­«üõ ?ò6øOvwP;øÏ„¶á;ðõyœ¡e­ôÑ*èpA¹LdéRÒÔ©¶3vΰOèJuˆïÊvÒuåOí*vÑt/vî^é®ê^ëÙ³ÙKÞ³Ã[Ösˆ.í=͐ö^cHz»’îa†¤kü=Uøì>ŒðýGhùwùK[šw‡@9©(ë…+Jïc¢Ô¾"©_LÆ÷+)qZ;Í@U=h²̦Eæ;ȇŠ#†J$릊‡¿pþ§KðËòi¢‘ +× ‘Z×À‘V7á«n7áˁ÷ìÅïp;¾ƒ¬8¿á]~QB–‡™úiÈ8êŠ c>H7Æ'´ã""zBJ*'T¤ü­–"}k „CŠ]dRƒ!—EöBXd/€•4øß8p¡Ü‘Ž~p֑ ͎,xðžñÜx¡5—qþuœoC(ç'u"4cŒŠ´à‚¢Á )…d $L„‚„‚ÄË.9t¤?$’\0Qü ›Â‚ŠÌ·£C™|nç ›©ðÕPÝ «}Ïfü>­Çù×Þågµ#”Ð…f!8w + +WÞ(Ï|Ä!Á‚…gñÁ5áq„žÅ ̤+Ì$a.9“Nð éë)°•BƒrŠ=ìH$$(ÂHˆ“-¥@´Ê¢õTP™i ÌwÅg­péZwlò„ðï¼!ü_tïÁ1 쨄ý‚Õb ¾v{„ý cã¾ãbðƒïh01Öd³U!$Ą’  §€VaÚ8*ĤÒ@=Ë ¢>re™(>õù/}K‡ˆ ˆØåÒØ_œÀÎ2AR]Ã`O™’!æ¨tŒùZ +ÌWR`H€ýR~“ç«E$ÄbºP +èev0CK‘q'й@Ì7ˆþ«'¨þæ Ê- ˆÜîŠr\Ã>&ȳ@~ «aƒüÖÌ—ÛØ£òö+ù{X>Ê”ƒß€8ýràöɀ7(q¶VH‚ ’pIj*$&ÐÀ9f̙ºÝ!v¥hÖâê7ú€z+¢bMDíbGd©*ýFU'9oTµœ×ª+œÕ-Πª“Ó§êç<‹åü®ÞSø÷ª@ÐóÎôÿê?óýIH䓐‚ç0‹)¦¢‚IOƒó0æMƒÄˆ_î=®_ã3ª[Ï|·…5»Ý略œ3¤ÝËÔæhŽóú5gx/4—xÏ57x¿kžðºµ}¼ÍÿÇ10½=„c ðþ€ÖŸ€.)~¤ HÈ¡€EnÙZ{È4:½M³L5yŒ$—Ò‡’Vùö'¬c½0lô{¿•ûnj¼§ú]ü^ýAÿn}•—î” SwQðDMЮ$øMÿ|úÝëÀ[:ÝÔAð8nƒÉ@ó,ҘÌäHB>î#/Ú~|–ÁqĒî2Uàñ<}ý©¹Ì·;u »3ù+îãÞ£¤ïý&îÜOØp/¡Bh3œüÕPxËÐtÓp_t=ᙨÙð*¤Ñ€ÿK_Â걺IÀÀ&ÀÄ À‚åã³(œNBQ(e¼(’:\çð¢ Ź77ǽ#g½={ ó·ŒU[ÚZþmóß7S¿ÞHù!ðzÊ¿E-É‚›•!ÆšÐ+Æú°Ëƛâºäñ9ã°Äjéi¬&"N}} ÈÀ{o®7sñY”ðˆ· ‚ÈáRʳùjû®âÄ)ís³\ïΞMÿoÞBVkN·Å²ZДõ¥°!c“èRú֐º´aÌ»Åç̇$VÓqéSmDéªìÓcYµi@~Ô<¡¨4ƒâVñJ' ïœs<”0,b¯KÄó%!dW©ÂîÁ"½Ãíùf×ëŹô¦Âböå‚R~]Þʀs³> ²Îü*ä´åâSÙßINf패ÎÜ';–Q©¨Ì¨‰<’Ñ <œqOy0ã¹jæ¨jo&¨ö`»³@9˜= ˜…÷Ýyî>Æs,õAƒeÔ½"€x°BBÞZ®uh)MžÖ°ÐB¿XRȶÎ[ȯ)\.<9û“ÿq]§QMÝiÀß$ì((H•* ‚"›ì@V,¸Êf„5@ !LK„@Ø÷°Ëæ(¢´¨Œöh5x˜9Óöˆ2Î§™NGǶsçöØȇ߹ç~zî}ÿï¹÷<‡gS*}.1UGfÎ5L%w]H҇Œ%MFçÆo‡ëŸû_{“Þ{’bw2ÞõNØfÈt)hßc£ÏQho…;à;±<—ì…5‰7öˆh~·8Úf™Öq‘›òÑ|^ŽÛåœB™¬ÒÓRßq–Â$M4”Ú2ÒKècŽ†w3.Gt2–";ImŒoI-Ì#uL$²9‰@›¶@ìa¡}/} ü(þþrÞ¾”9Á#™'vå<ÁlYes½$Îa¶èœóÅÂL· N¾ÇXžÀkˆ]æ;]ЛYܕÑڑÞÞÊŠÐ¥M“šÒɍi÷)ê´ Jër= !Õ§#‘ªw"6C’lÉÄR€‡7%xxQŽ‡õ +<<©r€ûU˜Ûò`³E)Õz®ì¤ÃLiâî Å,·a>Ûc €çÕË)õë̓´å*‚u9‚6»¨Éˆ¬Ïœ ×e^£*3W¨ŠÌuZMÖ?©ÕY¿Pª³2Š´r}ÿìm€ð¬àob øZfkÕVðPaå~ÌRM é|%Qz|Ǹ$~÷(ŵO˜íÞ%ànãûê +%ZnU°šSOP嵕¹½¤jö8¥’=G«`ß¡ËØ_Ò¥¹¯hÒܟ)Ò<„üÒfA®%¼˜Ãz¹)¬UšÃ#¥%Ü«³ƒe•f¡îˆÉeE䶉ª˜íò3»úÊ.â ÷ÖÒ¼ÃMB¾¯Z Pñ+‚•¼Ú°ê¦9·›$åŽP%œ+´2Î-ºˆ³%âþ&âþDqŠ¨ýól¤Z¡»`ߗàà+© kÌàs•9lá¦Ú3×àk2­"Z*?¶ï¯Šû°«"yo«”u@+a{6ˆ }jKKü«K¤ÁòbA*hŒuEü!j x÷iTo5ªˆÿ½ˆÿ–&à#YPô>„e~L`C°&ÇÁƒZSXQ›Ár£5\kÚ—´Þ¸qM˜¥¾>Ê®»ö”SkMâmeêþúŠìCJ)×»ª¼Ø_V& *WÄ"5QXÚN”è©<á ½@¸Å>B½ s…oh\!B-"y3$ÃÞò0ðT`¬Æ½z¸­5:<̶ì†É–øáæP‹ÞFšm[ɝZUüGõJæ>EMæÁʪ|o©¼èHY…8¨T*œWyå-$®¤Ÿ’W6Ec—-ÒsÊFå”ý½¾Fï*Š‚"o†dãà¥í½R€J,48XÒá`¾Íf:œ`¬ã ¶¿-ؼ£…bÓÜtÌ¡¡ñŒ³BÍp“ק{œ¯Ëõ+y~šÒ@~µ,¤ ª6<_ÞÉ®è¥dULÐ2d ôtÙçt–ì[Zºì?ÔtBɐ!䭐\€oJžÈÑÞ©ÂÀrÚ1p©Ë Æ{@ßãŽíê0Óu’ðêöèÊÖ¸]r]²Ky뀨1dzX]àÃkúsTçƒÙu +BV­–˜®ì&¥*Æ)LÅU*CqÆP|CeÔü›Â¬AÈ¿!m†pÖ˾¨øLpí~WÐþy¡ ƒz{èÖïô1Õô·){ÚË»O9•w&î)íHÝWԖu° …㕧øå4K3´Õ!iš0†¦3"Y3JJTϑãÕ+¨ r|䄆ÿ‘ê‘È­^ñþ€žÃý:€OuWÑü)´ÿ ¢ý«{ôhsÁhF}pÊ‚¥|˜f+<áX¢?»›ßÏpáôe`÷äÊêæ{³ºÄ~ÌÎÊÀ䎆„öv™öáð¸¶+±mÔ3bl뿈±-¿ b¬î}FÏáqÕ»,v\DóG†ºÐþÕi˜íèÐÍÔÍZ@՜#HçÝ1¢¹Á\„%wöcö•Ø홗Ò.¥:3.f»$Íp÷ÅÏÝ㦥‡NNÕz›jñžÔû¼è5y˟>õ•?}â•?íÂO´q$€6†nfDgpG p =ƒI=ÀÀ@+š¯B;¨ôD7í xÉxK>ؼ¥0³ì›4+ÖÍ6Ìgí“Žñ‹ž¾žï|êº`ïñ…r·èŁ¨…fÚµþC”k3žä…eOÒÂ=IW_zFοõŠ˜C¼#fßw¯ÝÃv€™~€¡Q€Ži´¢ùr´ +oá€s¹+» kå †µ„c®L“V¢-ãïÆáãî&۞¼Ë²?f`;Dx;£ e»¨†jg²A»'Òз—h˜v 7|âfø½køg/] ·ÿëz Ù¿Õ¯{x¥`ÝÁ®)Í,@å €Ò[œß™@ÚC 8÷Ø’Œ®`ôÁœ6°§Œ4“ãÆf1ƳGÌm4c–5Åȵ4–ÚW+·‡­jv„®ö8¯Nî Z]ÚøäÉÎ ã÷Ž_;{  zàÙ ¤ à†LpA8"—4`ƒö`…Î`"à’½pÐÌP, ÔRFC` +ÅÀlŠÂ¥àzb'±¨&jÆA©'…^R +½¥4TxÑP®¤£—†ŽžQ ôHÕGÉ</c¢h­ºm6F·Ý&èVjŠÂrâ +µlž&š‰âñœèe +‡Ù#nÈ#DÎÐÿ™ +e¤¯SèëNC¥áCCß@:*"è=S½æ ,ߥkŒPºÉ%;LQRÌB÷ýlt¯$jÌÐý„Šˆs_%nsFÅœ÷ΐûÙ€ÍÞ»£9ÁísG^Ÿx<”“¾RH¡?1YLÃ)ބšŽþÓõÐ/A}u¨øܽW™ ×W¦èµ…žElôÜk†²”UGɷԛÊΘ”]2‘ÝàÉþkÞ/ë6ë9hÞã‰Ü72´è–!¿K†–¡ÏXߙB51UHC'áOÇÀªcõqJ:ý¡ß2ST®e¡o¡ÙGŸœ?}ŠÍ?(ös‡•Ü!E oPq’7 hä½W4óú­¼^Å#^·â5ï•Ï€Å Z>W ÕSoÛ-¸Tj}'¨Ü润Êö–æ¸Ý M£ýuÍyûVÍM‡– g—ƒú/hF›5èÒDœÓ ëDdEa0–˜$L!g‘*¢S½i=ÉjÆËÄ0ƒŽøD£G3t¬Ñ9æ¿G.çߌøÒêzØF›ÖéßØþZd-t¯Ãm…ã%mÓ…Zçó!?9ÿÒârNÛîú£¶GØ q;¥EQ=QGÔN€Z À(òîM4LãfÚÀ°Î™êÑI©ç™Jz{z°Þý”X£[3ÓØ­ Ù¼kqyV—cWÙ\ŒYg×ýµCSÔǟ"÷8Ÿ‰(s9~PØ~ÔíTxƒ¨>좸6ì®øxx§û‘ð!IM8JE ¤úo`iǒ7gŠ`YÏáûl;x‘í +æÊ©ßgêý[at5#‰}!Ugє¼Pp6i‰íé„Õ ñëêã6»ÔÆ-‹)‰>$©‰®“VG7yTE_—UF?—UÄôËÊcPö=±LìxIÚ ¦€dsØ0<Ÿ¯Z@{Ž-ÜΑR¿.˜Â¸œjøóì8ö]ºECF¶ .-×îDÊ +Ç£É_:NÚ ¬NÜ&ú!¡È½2~Ÿ´"¾RVwÌs܏^ûâZä¥qOä%ñïäÅñ(ߓ€òoÐk"Œ!ídc@1ŒÌ3ÞE¦ð4—wóøкXD]Êõcœ[lظ †]—lq|ö,ëú…öՙùŽ3 +\+ÒÖ¹•§º—¥ìîM.‘}7ó€×ž¤ÃÞEIÿRìNºì³+©ÍgÇÌ^Ÿí3?*¾IÆ1ބüS8Ä́!9&¼Î1€¶<&Ü_b7–ráÊ2Wªi©½1_ì͍dÍIäUÏÏTfgÛ˜“ëT6k¹ë^ÝQIæÉ·Û<þ™^äµ3­Ì{{j•Ï¶Ô:ß-©ç•…©w•_§u+7¥ønJGŸé¨˜ãÈ=èCÿ<´çÒáÎR}¸¹ÂZVr y•œ^)§×.ŸjpdI«*/ŽWñyš`ÿÂÙv¥ósœŠç-q-š[ Ú5gdû¬BÙVÝ.¯ÍY¥ŠMY•¾2O(×g6©þ‘yKµ.«ÓomÖåZú>a"“Ü^.ø#ŸNúzðK\ü‚ g×8@ýž´£U+´¦Ëb¹eùÉV%y:»¢Eówåä¹n_°B´uþÿÈ.Ϩ¨Î<ÿîÌPDš ½H)#LQA£, "  t¤ÃІFpFš ‚RDŠŠ *‚1XÝQp]÷¸fƒ%'nìf‹‰=Gß}ýæÃsîÇçþÛ=÷WâR™¤à*êxåñ-^òønAIܐ°8î¼·4î†wQüSQQü;aQPø_B6ª€Ä1xüCÂÂTßÉT0^ª…¯Ë,p¢Ì•Õ_â­Ú-]©ÙQ¬×šnܔm^Ÿ`U“™fW™žë¤H+v)O­à–m«áÉRš½Š’»I¢¼¤³Þ’¤)ŸÜ¤ÇÞ¹ÉoE¹ÉD˜›BþLH$ oA÷€æ­26.Ê98»]æ¨pfõnªt–.ŸÛ*[;¯©h½Q]Á&³ê¼8+eî6»òœlDz¬BY¦œ[”QÅ+Hoò’¤u²SûE™©g|2R¯ù¤§>ôÉH{-ÊH#BŠàKÈ&àE20\—ߖ±p¾‚QÅ )qXéÄt)ø*û+ü4öÈWë֕†VË"ÍÒ­ ¶&ۖäg:Jóò $¥\IîN^vNƒWFv» -ëˆh[ÖiŸ”¬ Ÿä¬Q^‰R²ˆ"øKž³0½T꺭¤bQ’¬Ö#¾¸•¿UÚ+Œ‘‹¢¥ñÞ,½ï-})Š.ú$Œ)" +&¯€{ÙÀd1pqð5õ¯£¹k7ÐÙ¨‹Ö&+46rÙ5 ÞjŠúšò:±^qí:£üê(³œªX«Ì)¶©Ê,ÇdE¡Kü9wkE5/º¼ÙsÓönA¤ü„p£ü¢h£ü}þOQöQQFø_ò,…ޝÕ2ڃJàõ÷Óüw ™fÏm4¶š£¶Õ…¥lªÈ›ý5¤{Vëæ5…d7D˜¤ïÞb‘RŸd¸+Ã>¶6Ï)¦¦ÔuSu墈ª&ކÊ.Ïu•Cü°Êq~hå÷üНÿá‡)÷ +S’ÏxÎägz“7è.^ú܃Zàõ÷ìZiÜÝ>5ÆPt:2e^iûRuIÛ*­¬ýÒKÝn”Ôm¿7ÞrKsªÍæ=¹ö‘M2§ J—°ÆnHC§{pà OÜpÁCÜpËC¼ûßâúâ:ÂïšÍ=zW?÷  +¦þÃ-4ûµ ]@e*Ê{磤ϖ)ìsgçö.VÍèY97¥[¬“pp½þÖ®(£è±f‘)–áÙÖë:¤v!í;ƒÚê®ikwýªí¨ÛªýçÜÛnºî{áØúžØBþÀßé.^RÐÔÓ=¤õlöRMPz”æ¿A]H-‘u̕IrýÕbVύ>ªu4BcÿÃuG’LBŽdš.X°æP¹õW‡vÙÚï°¢¯ßqyß7Nþ}7ý{Ÿ;úõ¼sòë& ýÎæíÁ9:ƒtþ½´þ}ºC@ŐHÑĶQc$Ž:2±£ž¬˜Ñ%œ¨Ñ@µð‘`u#´BF6띊×_s*ÍpÕpžqÀp™éò“5~'[-—žÇˆíL.Ø¡óï õ7Çhþ2h½ ‚è1=D[!b܍Y?.b…Ž/珯Q‡©¯Ôߪ¹r#áØicÁؤ±ðÂ#þù7&üsÄÔë,1›É7ôö]Ô¿‡ú+©_6dâǁˆË„\ÕDÐU#ˆ¯ÙcÍ$«&3“+Y+&ÅlÿÉõœ¥“›U}'Ô|¦2爦Š4SJM¯©&-©mÞÔ)÷ë:îS´]{­Ã½úqw‚èÍäx+Ð}€îíõP2 +dŸ.‘W€à)6nªcémm,¹m +ßï°øŸiÀšèb1„91‡ ±q‚áBŸð¡G|¡KV@›ˆ¡EÂ1—Äaɂ:‘3j¤Q!9N¹À°ÉÄ,vP>õ'SÔߨŸÖ¾ŒÖîùXø°þ°ü˜êÔ¤N]ê›O}&ÔgI}¶ÔçD]\¨Òwa“% ¤„R¢)i…~=>BOŽÍ‚8º2Äٙ!.g.C¼XÄ~‹Ø®eë6±JàËl±Q”*Äâÿ\×iTS×ð“@H.!y`bÈ ´FdA@A™ 4 aJ˜"cD'(Š‚ +Š(‚
P눕¢Ï±´Úê+•ê‡§€â¸ß±ë}`ñá·Îþ¶ï:{¯uî¿«ÁêµÀ²I ,cÇé`ñ#ց]ÅîÐÁ²{I·|OÿdùEëƒÐ?XcÔˆ©€{“< +8b¯µ3þ7*ðý5€®3â5Á.ClU4°-¥§B 8Û°::pöaÍØQpÚ±³X'v“1Îée|â 2F9ï#¶ôa[ †lA{ˆÌ·SÉ¥À,œsì0\;‹ð¹€ +"_ †h€@ª |9 fæрW¬¼2:p·b5 àîa|áî'&¸Gˆqî bŒ{šø̽D|ä^'F¹‰aîñ†7B¼æMh¿äóXƒØt'î=çÜo¬) Æõ<<›yb*Ìõ¢Âœ p–h¬$8*µ¾ éãÂuŒÏä&â#¹ø@îÒìÓ~'8¨="he N2‡Ì7‚næÉ{Ìäsæsr˜ù79ÎzJ´'$°c}$èM³¿ö6§À3 +¸áoqŸ‰áy¸-¤‚ žÇüpÍ1q¼Ö‡oÒéïçä3†go7j¿qÞÂ|í\Ã|åT¯ó©IgÐéˆÎ€Së¹Ó9Ö3§«¬~çVŸó3^ç¡iœÆõî;þ¯N0½Ç ~™âŸþ.Æ܍,²À+çâ‹wÓ{>uÜË[cÔ}™æ[ŒÖk×ú —•ÄÀµö³ùk™ýó*tžÎ«f=ïbõ‰tÿÔýS|lÚù§ÙÌídߟ{‡Ý#î×»-š~C§Ü;çÞP‘,ôIÂF/£ PŸÄݓÐ-‰ µ;j1­3"”¸Ã:’¤wjY†ÁÉà<㶠U¦Ç—®3k]RaÑXmu8 Îú`À~ÎÿVÛýþgíý»íÙï xk¿;`bÆ®@°ÿjç°÷ƹ7‚ÞGhPªþ–²ÐýXCt3Ž‡ºbçR/IÑÎF?®ˆÒm‹Œ×o —¶„)M…ªÌšCŠ-š–o°Ú·¬Òfopm}Pƒ]]Ðá;ƒNrkƒ~âíú·-è¯*xŒ·5x[—wË@à; ¡Mô4Vý;A ݓè¶Lu%Ù¡ IÎÔÓ2Z{| Ñ* Ó=ó­~st’QãŠt“†¨óúµU]x©Íΰïmw„UÛo ÝÍ­ +iæm ião¹ä°)ä‡ïCÊC?ñË€¿1 fNKhø(h?/½2*êI¡¡[©tԝÊF6è´\DiKuÕlIò#šeËYñý=±ñFuR¹imŒÒbGtUµd5gëŠ v›£*gTDÖòÊ#ù"Ž ÖGœ'×FÜ"K#Ÿ“k"?J¢Àáÿø“A0M¬@èiB÷SpîUh îtº’®‹ÎdX¢¶L’Ò’>_³YáÍؗÄڝ©W›(5ܞdZ—nQ›cU!-ä”[j¿!¦‚».zûÌ5Ñ{Š%-d‘äŒp•ä_ŽjI¿£:ú½Päw1 À§Ãd_ŸØáh„áÌwWÐµL*º¢ÔDç•:臕fèèJ>¥Y)ÖhÈô¢×¥êÔ(ÂôªSc +“e&Iró2™Òj}‚ŠS_l_WÆ-Š­âÆÖ TÒCÂ|é)Ç3I¹] Ü'ŒË:&ŠÍº(’fÝÃ^ãzL›dÜ/ñ.<Às¸–ý?¶ë=Ê|ø÷¹ ƸŽËĽË3bf0F‘QœPI…’.Š“­])’ˆ)¤èB[(%]ä²Û•êìn‰v·­Dm¯¶vŽT[ÑUJ—ßù:ûê¼´¯óÇû5ó×|žßç÷{žy¾ÿLÅ2°ƒ,œ9Ðîl#(ÒJ¡@«¢r³=Ùì,½u™!©SM’Ó£ÌW¬/I[`°æ²…©Iö RÒbWç8Î[µ]9'y¯ó¬äj×è¤sê™É­ê™IO\g& ¸D'g¤êþ|€ÖÁ³ˆœIDz±œÿÊPQ®ä ƒ¼<'*;o$³.gŒnêÆ A҆0ãeÚéf‰YsD‹ÖÇYÅg.–Æe¬°·n 7'];äXBV¡œJ/ÔÐ)£y+·ò—nžd˜°)Âô˼h‹¿çÎÏÏYh=wã2Ù¬ )vQÚ,y¤vËðiÙ%Š)Y‡•aYõªÉYWÐCÕäõo”a™db¨»ƒÏ„d€³¸ß`þ¡ÍØΠ…Û6îàAf‘Ҋí`u± µ¢Ø‹M,§»hÇÁ‚íSb·E çn±˜U/Ž*H´Ž,X%›¶%Ó.ls>š¿ËabþAǐüSNÁù—‚7=p Éëw +É%Ž!9ŸkųxÏá)-v€ùû¶bE8{⺮`u©¬,“ÀÒ= +*¡ÌƒŽ/óãŖéŔ„ f—L7ŽÚ=[¹+Î"|W‚hÊW+­Bw¦K'çÙÛý­¸’ ,:Áýˆº¹€í}ò€mD°õs—±ƒsë±ì¾×^RŒà(’shRÀ’X\)‚øƒwPCÅTŽffUò¢*'êEL;mV1ß$´b¡Ù„ýË-‚ö¥‰÷m´W¾Câ_^!S~\æ[~ uI}÷¼’ù–ŸÒÿ²ý¤q-v P…ëß»`G)@N9@ΡKÄÕ°Sk +³km ºN3ê<©ˆ:fjm0orm˜îÄÚüÚ¹‚ñ5ñ†5KŒÇÖ¤˜úUkÍ|ª·YxWï³ü¢ú‘WõE‘×ÑNѨª—âQ‡?óJw0ï%»™w’rf@Rɼ•eú%ǘג3LŸ´‘y)½Æ<“v2O¤½Ì²·ìCáݗî?éET6@\$Ȉ+^‡ZFRÄُ"ʉ4qšA“á±ô‡Df@¾šyÃe2¯¹\¦+d^rÅì ®”}ÎígŸrGØ^®ŽíáN³¹ïÙGÜö×ÁvÉ{Øù[v9ÑýMNôîÊ ÿÎ_WÌֈð(YñÀkñt@¸#q?4ã©wêit¿Ëú¥óBæ™jÓ«LcŸ(µì#e>ûP¹÷@±‹w_±—wOq×¥¨áu*Nò:”ßòڕ—yw•í¼[ÊÝ6å~‹Šè_UÁ%1øù/ˆ;æ{x¡Ñb ¾Ø…>Žö ú¿K=÷ ¥ŸŒŒ¢ŽˆcºÝÙ.÷Ul‡&ƒ×®ÉáýæV sÇ­Xç¶[©î-u…îMu•^›ú˜ÞuõY~‹Û%þU·ÛüŸ4ôÿÃu¥yæqÿx"ˆŠ*Ê¡™ív²“lC5Þ¨x €€ˆ‚ŠxŃ¼ˆJs`Vm\Ícl®ÑT“ÉÕf3iwšN»Ùl¦×¶™Ý´M»›nûîc·™µùã3ïûßwæ÷<Ïû>ß›¾÷]ل‘¯mÂü–‘¥ÿ¡¼„qÛîØN +`ÉTÀRi€¥°àyòFxºsî³.îq|þãr·‡Ûµ„÷¶ÕyÜßÖêyo«Õ띭}Þw8Ã>·9û|nrŽol™ö½¾å„ïʖÒµ-ˤeÎ=òUΧ䋜o)‹Ìƒœç`ó¯À¶£ì"Ê&¡#Þ3©ð<#¾äÆ“´ÍðQZ2î½Ô\ü½äb$•ÇÍD½×õÞ+ mÄk ݾKñvÒÕxùrü~¿Kq”·âf(âÎø/Ä]˜»p6§âŸQÇÿ4ÿñ3ë` (;Å eû–í /rüà«*<æEŸy¯Ã»Ùq¸[¼Lüjfa9£Ôó +Wã})­†¸˜j&-¤ZÈó)=”³Éýþg’GN% <‘4IK:4›t!x&i5äXÒЩ䧡G“HÆÂ\ȑ5)XèKX’7`\wÀrÜáß>xÃ> ÞçÁ]á¸.äà–©øKü<÷ ¹Å^ó9e>gx:ÒÉ,£ßñÌfÿٌŽ€™ õMî`Ð×ü‡tWèDúL˜+ýípúí`úýðé_„ïãþ+ÂÉÅÂǐÑ5ÿ‡¥ |¾ ¾Uˆƒ‡"wxPä w‹`EĄ+â͸EQ"þ\!ÏýdA¡×œ°”8#P“§ó ”É܆€‰œVê‘kð¡ì=!ã¼½aûyã4gÖTøh֩ȑ¬ËtGÖ]úïú ï;z6¶&Òþ +,}²sQçDŸö‡%¨óIÝà¶ÔV%~pYJ‡ÙFÜii~NÂu?V,ðš•'Š”äÃZÿñüÚÀýBsS` ô„9øƒ´¡¼}yt{Þ\T_ÞbôŒÞ¼¿1zøßDwó±5Q]‚ŸÑ_Zûµ|#x„~s÷Kn)ñ°¢$ÀU9 ”48UöÌ*·â§å©„‰Ò\¯CÒ"⁒R²³Xí?"֋ꃋZBû ­´¾‚=¶‚zOþᨮüFgþyfGþ*˒ÿV{Á3f{ÁOŒ¶BlMôzà 4ƒe¨ë Îµ¢FO‡ å>pZ³`JýÞUžD/ãy:ùĽr y¨´Ì¿_ª Ü#© ¶•˜C{Š-4k±-¢CFûàêË(±õ^Ô½fjpp´–Q0f|7\»ÍÍ^âa3d{wUåûîҕøµi•M Õ¤© ©¯0ьê]‘Õå}Qúò¦NåbWªŽÇT¨.ŪU÷¿ÇV¨^°+Ê1Â\ïË"€”hÐü¯ üù:Ôùеg=ՓÁÙŽÆ×pö¾·>ÉÝjÌô²Ô +ˆ-Õb²Ù ÷oЫ©Æ*CHµ®¦×µGhµ¶(M¥ƒ¡®<ÌRifc”š‹± +Í;Èç±JÍ¿ÙJ ÆZS¦Á˜/}ŽÎÃtÝZE3¸ˆrÏ î7ƒ®€.ôÜg&£) ú›7€­é÷x«9Ðnâz67äMõEäº:™±œª¯­ +ÖÕԅijZ#Ê«»ée†!†BUªŸ‰‘êc%úÛÈgèý{¶´ +cɪ0æzO¤ï¢«ç2šÁ…F´Z¦Ú §£•ö¶`èmgƒµ}®½-ŽÐԚæÑВãcl. š$¹,°Ò¤ V7ֆ–54‡Ë뭑²ºhIÝf±ñ[d\ˆ)2ÞD>A¾c‹j1¯ó‡Û:´õçšQï´LtŒì°wxBOg tZÐf݈kêÜîVߙâ^ÓÁóÒïµ–b²º]á¯jÓP­Õ!²SXIsG„¸ÙN/lÚÇÈ7O3…æy–À|ƒ-0?a LÏYBÆ6bŒõ>@ëp½à-3ê(ÿÍ.Ôûº‘ž7°ôR ÅFÓîßâêvsðÕ¶D‚®7ó¢‡ï£ê‘Ý2?YWy€Äªw6„vXhŽ¾þ®±¨Ü]“Ñٖ³ že•É³Ñ˜úJ‘gý‘g]§È³fPìQÍ%Ãí§üLÊÿË^`}Åa`a­ÁQ íPDþ0÷Q ã)¼›Fal“7¼šLs:ž§ãàq&†3sàޜ·æ0ªe \[¶À¥%ú³%ÌùìI8·´Ã¹ù s>ý‚páÙ´ï¾úðiíû¢ +à]ʞQKù @Ä Ê?›ÜÏI¡oUÂ鲎Wôp¼ê‡«ã »6DC{=ö7fÁþf:47—BsëÏPßÞ uÛ~¨Úª`ÛvÊÛ?ÁöÖ lo>månV•¿¥±¿GãžAÙ 'ð&À¿ð:Œnœ®1ØߒBÓ¡‚ºC U§¶(»| è„¼Û YO"$=3!î™QÏ2°ž @÷ׄBzèæ=HÐÛ÷Úfº´ºXò0¿˜IÙñ”FÙã)Ûó_€Ëu@wPßlP ( PC2 …hÀèM¼ˆ? âÈtBô" ‡Ï¸A +¤ §äÜkSþRÚsïӚ¿Esž@Ùa”=î2`¸8·öí”ÝȨlñ3€q}ÛðJCè÷Hb >$˜L$)„^Šœ>Š8ͧÍÇéÐqZt^ñwKÆÐ-¨×uô·÷×D‚«'3®šÅ¸2qŲ’¬'›Év’A²—ç‘BpùaRNªH^ɛñB~ CòôËðXÎñHÁñPÁÙCåÿãnžànðÑDOµŒð£ZÂÀu TÏ Æ5ï2®^H–“ÉF²•ì"™$—°Wê셺„=WÅ3užª›Ð¯¾ŽGênj6{é’ΆF.fƒ#W°'úµì‘~#{¨ßÊúô;ÙýÖ«Ïe=úÖ¥?Ä:õå¬CœÝןd÷ô­ìöÈNvÃ¥_¸â…VW.ºD.ºrñ…a¸åûêh+iÁýœ ­‰ß8ú†—ÞñôJc=ßa} X¯aë2¬b†õì¾ak7lcwÝ¿fwܳØm÷ЗH=_2p5Y‚‹Ir4'jqb²j“Q•<‰ULž*”%Í'¾'9”°@f‰ÿȦ0n…¢ n2?öÛ¼Ø/T{cvØåÄdj²bòí3cŠµ{bª´1§t¹£ÛûØaG,wøŠlãºáx0”´O¥~‹ñgÓ4¥JñCŠªSGáèôñ(É§& –iiâý)s¥ùSß·Ù;e¡<'y™2kòJUfÒZõî¤ÏþCu™5}¦qüûK¸o„\¨µõ Z­ŠŠ€€ÜH!„ @‘„+€îû–Ã9¼T]Ä«µžuÜ{»ÝÙît§Û§ÛîÑm×µûÛÇÙ±Ò?>3oòÏ7Ïó>ÏäýxŽDöxGŽð#ûôGžó퍼â×yßù1¿3êK~{Ô·Ëo‹fý–ÆÒ_Õÿ»$òÞTà¹ßíT.n¤¸á²TˆwR7à\êvæ¤4œ3•g7‘œæp$Iå4–˜ë2’ wŠ7y ÄY<ûâ¬Þ=±¼®ØAߎ˜£~m1§ý[b~(hŽ¹-hŠýHhý\Ð÷œ`ýëÿÿ%lði<ðå?"ﻝAïìtWäΰ)ø8“¾3éAÌqÅ^Îaù»QYŠÃpZºÓ€4Û¥WªsëN)ñèL®ðjKªãµ$µú4%öùYÇýëgu 煵‰·D–ÄŸ‹ªŸŠª“ž «’Øÿ—|ü1ø™‚œSÜP“kÐ_îy¥Îdú`ZµÇT[0žÂVFr2zÒeN +•K»<×­E¦÷hJ3y5¤YxS}k¥]|‹tDP%VHçEféu±Iúc‰Qú™Ø˜úo‘1•}¼ä‹ºêÁc%õ€¼ïª–ÞÙ9ôÎUs0“í…cšÓlƐfÓ§çveÅÙ·©¤ŽÍ™.J[}FG]z©—%½’W¥¨÷­PtðÍò!A™|BT*Ÿ˗$ùã½üS‰^ñµX¯`E„аŒ§t¿–Pý7)ÿr>0Oœ¤ó„Öc¹ åm@oî6¦SÊmÍ9`ߨIv¬ÏV8ת³\«³òÜ+U¯r•™g̬ó-Ílõ/VôÊ£¢BåY‰N¹¯ü€xBüK’¯dńˆ¾ä3šÅ_Ò Ü£Ú¯é€‹…ÀÙ"`’~ǸÎCBô®GGAÓ¢ÛñæGÙÕå%8XrӜ+µ™®æœwcN‘g‰ÆÈ3d×øe7ó Ô}Â|õaQ®ú´$G}%@£~Hü‰øJ¢Q³bB”³Œ'RÚšƒÛyÀ"eÛèÉs’8Bça½+zõ|tÖ Ù°•iÐïâÔEØUÆ9”HŒ.%:»!_çY˜Wê­Ë«òÍËmäks{í¸H­=%Qi/djï þ)ÉÔ²b•–-ç÷´‹in—({ÖHÎWFÎGçÞ'´—ú ¹ì5ԗ25e;8•¥a\sIŒ}iq²£Á p)2¨Ýtú|¼¢b +ŸìÂ~VA— ³`T”¡;!Vè.J亻rÝ'Ä?$ +Kß±¢åü–îá!Ýýu=Í"åŸ!ÿ¤{¸Ks°HÏ_[p¢«"çª$ï¬bP[í‰*‹æšõ(« b –ÝœBË~»üêxmuªSv•Ò%«2ÇMYYè™^aô–•×ø¤–·òS̃‚$ó¤0ÁôŽ(Þôž8Îôq¼éKQ¼ñ[Q‚‘&”½â'à]êÁ%3í£…¼³¬Z‰Z:WtCYƒ?Š֠Ⱥ…ÑYwr´ÖpnvCŒ}V}²£²^á¬8¨v•Ìw—Ö•z&×Vók›}ãjúù15þ,ó‚(Ë-a”åW¨ê/ÑUÏ V]Éú¿äÍÿuºÿóTÿ©zò>+ÐC4å¤Å-Î(lõA~Û*hÛ7#»};£jåd´Eqm‰öim2Gi«Ê9©%×5¡Åà×\áy ÙêÕÔ볿é¨_xã,?¬ñ:_ã/øaÖÏùa ÿá‡Õ³ßãõ`ú>GùSÍ´ -ä]­ä=mä]]@^7š^/dõ‰‘Ù¿éýAõ‡0©ýœäþXnbŸÔ>¾/Ã!¦WãÝ[èÙcv ï©÷Ø×Ýå¹·û°÷îî³¼î%Þ®îŸòB:ŸòB:žù„´³ß㦉f‘z~š²tÐ.tVÊ.ïòÉ=ŠQ7¤ñ![äñ@$ŒoGÜx(3͉OäFŽÉì"ƲìÃÆòöŽ–9í­uÞ5ÚáºctÔmûÈi÷m#‹Á#?r>ô÷àáo<‚YÏå,Ð ÌQý“”}¨hï§Pv e猲c@¤b¦¼=%FÔô:ìŸÞŠˆ™]› gBgb˜=3)œ™ ÎΙîÛÓ»mÓUö?˜nqxkzØqëô §7§/œÞœú³Sàñ¯'X—Àc¯¸@ +v’ê§ì>ʵ’šº sH:D’&îuÃî9_ìš[‰s°c>oχ`Û|‚mq²¥2oÙTÌ›Žh3q6٬܍¶~î¶I»õ¶‹vël÷íÖÍ?ᮝýÊní9Ö~íÙWœ¥ücÀÐíÂÀ2 NÙg€Ô9à©áž‹@ðe.¶,x pÍ «°iq6.aÃÕ]xãjÖ_Çº%Ö,eãõ%V/Y˜UKÌÊ¥#LÀµyFrí6#Yú„‘,þ/<爯°ß1Eù#T{'õ¼Žt´”²µó€œrcIICm׀Í75ï9`åwÜñ…äÎ +ˆï®ƒèîïí€à^üïł_¿û9ð}PŸVð Áûá)x=¼χÂëÁ_áuï¼î²ß1>F»H}o ÚM³´€ô+@Ü°ïå¿ lzxý> þ×õÕ¹Åüﶰlˆe£ DË‚((`¤W%ÑÄØ 1`A,H @DņŠ(Š< âàC‰-ŠO1D!âŒODQDʝÑïgã0¿¹³;Ë=ç;{÷ûÎ9ÍÁ¢F Õ9ÌêÔPÔY“Þ0­s C ¯Y½Ò¿#ÉDHþN„øb:Dó ¼X +AC¸†FrŸ<û(g3Jßù,Zû”=ÀXŠ=æOZÕÿ8àðÐû `] hêÅ%Ò+"ˆ6ª!¸j°€&;àÚ@à:5¨Í£©1Šnþ@hóm¡¾… +}k7¡Ýj æíöGK(þœ]À4ªû8Zw }Äë0ø`Wè.–Õe@~5ƒîGn™Ðÿ+€Ûj M Üé ´÷î:÷‡¾kÔRsôˆäG´ù?Î:©àô€=¡@ON}”DoÍØGû­=˜b{¦øç}Ðó`ј]$7®•b·“ïu)ŽŒb˜Ñ½5t?+àÕä…ðʼ¦fõ 5ŒêÁ(F?¶‘ÐCÇÊ?bÚ>`ÝhÎUŗ`RšwÅ®`0„’oÉ4’H%$‹¬"ëH>)Äk£ »ðxŽCxŠjt¢©hè¯¯(möÖýÏ0k0«ž”QéÀÌìÁL‡€É¼ÁLÁDcÁ„“ÈO”WI%KÉr¼æW£‹ß€—|žóExÊÿŽN®¸ýèàþƒûÜyÜån¢ë@߅ÛB†VÿëѬ»5˜¥Õ»<ÌûRMœ)OÊÇHùD‚É¿#3ðZ> ]ò…x)[‚ç²,<•­ÄÙ:tÊ6ᑬÒá¾t7îJ+Ñ&­B«ôZ¤7pCö×ä]h2ehT¼sEÁ¸˜Î¬—9å¡¡|(—î¶T—þ”åãƒ7š¼TÇâ©j +:U3ñP•„ªÅ¸§Ê@»ê7ÜQå¢M•‡Ven)wà¦rš•{q]yMÊüWՌõCÔkºp^øZsƝ{¯æ=fK±m•`½‰­éf£ë9/ºÇcë<°ŠB»åw¸­m"nhçãº6 MÚehÔ®ÀíZ\ÖnÂ%í6\Ԗ ^»,¡Öò4j¬špÊúWýEwü ÆëÎøªÏ°~f`}å`v¦`ö*ºjñ¦Ÿ ž|ùîõvC«šu!¸ª‹Åå^“ÑÐ+õº9¸ [„ZÝÔ貸³º•ÜiÝz€;©ÛÁU۔qÇmþàŽÙœàªz_âÛ¶ól_*m™`_&Øۇ +>Áì)¾ƒÌQæDy P¡ó+K´ÙÙâz?'\îç‰z½?Îé#qÆnþ²›ÆUÛÍäŽë“¸cúî¨>;¢ÏæësùCú üýVþ}‰ Ò®B°×ÂܾUXfÿLXêÀD%L¼ó3lÅw¦Ÿé`φˆÑ1H†6Gû[¡ÎÑg\qÒÙǜƒqÄy,wÈy"·ßy_é”ÀïsšÇW8-ìqÊ”;-ìv\#,sÌ–:‰Jœv‹v:;9ß:wšlqf’‚L²™äâm|ÚN:Üh{u® â’AŠÚ!æ8éb‹£nqÐm*Ýü¹ +·®Üõ[¾Ìu_êò£ Äe–p§K²°Ø**2,m7¬֛l1l5)0ü.É7TJ6ª¥ W¥ë\:dk\^ËV»2YîgØ`ÚÚ(vËšùFµ#9œ.Æ % ï‰}#úcÏw”ðåJFsÅÃcøíž…žS…[†Å‹6›-Î÷X Þè‘f’ç‘%Yç±ZºÖ=_¶Ú½X¾Êýßò•U¦9 ¦¿ »§ÈÖ¥ÈÆþÏtÙ'˜+m¿¿‘¶÷Z#PMŽúñ88Ê>Ö(óÕc§ŸE¾ÞÜVß~³O8¿qT¬ oÔDѺ‘ÓÅk¼6Éõž+Yé•"Íñʐ-÷ʑg{å™fzmS,õÚmö«×aeº×yeš÷å/Þ/•©ÞL™:’™}ê•?>4sЬD}>͟ûÇP¯o”¢ÔØ ;ú`kÀ@äxryþ£ùµÆ`A®1Z¸òëñ¢œÑ“ÅÙ£ãL2ý¥Ëü’e¾iòtß,Ešï³TŸ-ÊŸRÕBßê¾gÕó}[ÕÉ~ÏÕóü˜ê=å©×híç(ö1:æöӑ»‡Ž™Ò Š‚Ô(¶Á†X2”Ë Ååd† 3lj2Æ|/N˜&I øIšê?WžâŸbºÐ¸Ôl¾q•rž1_5׸S3ÛX©™e°ÂâÇÀj‹¸ fòÄ<.ˆiÞSÐæGßCp" +80(§Ù¯˜®[èu^”¹ÑÖȉé‡Ì˜AȈñäÒ¢}ùÅQ‚…‘¢äˆXqRÄ÷’9áÓ¤³Â–'„ÍSÌ ûE–­Š ]¯™ºÝ|jè‹)¡Ç»Mk"-&‡1s¢ùT‹?pžjPEq÷§Ð췍®ÇÒ¼3NŽå±Z,û¦Ò¿qBj¬;·(vŸ<.@0wl˜pvLŒ8!f‚ÉÌè)Òøèxy\ÔÅô¨åÔ¨Lõäȵš" ÿÇuyGEu¦qøwgfd`€™ÁÅ.誈Ši*e60ƒ U‚RUZbì2ÇXYKˆ(nŒQ@M\)GOÔ-–h²®kÁ²nŒQ¹û“ã9ùã9÷Þ9s¿ç{ßû}÷¾¯ÖÙìbˆ<Õ31òŸ=uO\u]ÚD¨1èDõ[~:s[<ס='ˍyÜÄëµú¨ÖkPž0e £P”0I(ÐûHòôҜøy2sœÎ&3.Nž›Ô#56CiŠÉuXSìhŒ©vNŒÞ ÖGïÔÆGp‰>Ñ36úoäÏ_kã¢E Q¿åŸÃYÆ|Œñ7³ìjdÿYÏc¯?4Øb¥Ñ¥IýQ˜4ùI„\ãtÁlœ-É4„ÈÒ 6)‰1òäDƒ")!ÍΐcŸ /TÅë+bõëÔÑñÛµ ã›\¢âÛzêâ/“Nž¿ÒFŋ¢~Ë>‡Ó\Ÿ3þ¦T`'ٔ¬âuy²%&G,5õE^ŠrRÆ!+ešaò—¤š‚¤ÉÉa6IÉѶ†E +ý¢»¸$³}LÒRÕ¤r'±Vaܦ 7îw 3wY`¼ä²ÀðÐ%ÌðRf5áQý–‹|'€Ã&`_°Ô¥³ïå;€I 2ŒÛ­‚çî^Û8cGbtã8Œ²Nş¬þi ÂkÜ­z ·¦a˜5_b­[7 ÿ¼W`=.¸Z¯ +®׆—×]âï4T[è]MoÉ:À¼‘ë`+×ÀÇ@È.Àß +LÞ Œýp? ÇÐf' iî…A̓0ðà 8è ׃SÑÿú +Æ{‡tè{Ȁ>-fôn)Eϖ:¸´4@Ûrš–o¡9tšæÐ…·XÖr0ߌy ÛÑTÆ»˜Oï¬&`ÛRÏÀí3`àQ ÷19´­*hZ] nu…sÛp2Nm“àÔî U{0‰‚C{2ìOäAy¢ +víõP´7AÞþ%¹ÉóÇP´ýJ^u³qW×ó}@w&cNÜ„7sÞGè§×í80 èu +p>-ÀþœŠó*ÈÏka{¾lÎ…ìÂ(H/xArÁ‡A$üupÓupÃ}ÍDwPÐÁA;Îñú6yDžt³Š±3çæ=€ñSîþ-€ÞiôŽ¥w8½ýO.¼Õ±°û]’°è°#ŽÀ÷Zàr_àÊ`àêHD€¼)PY^ãKø:_À×KôõFà»ÁÁnÜ ·»)kàûp°ˆ9×}Î5ØÊøOô= ¼G¯æ;Àá ¿ÿ„·ã¦ø¡pKŦ@ ü؋…©+pÇ ¸ëÉBy:ð€óxÀy<äK°“¾“Iïd²;ÿB¾$gºÉcîM|Þ ¿‚èžþWúÏÓÿ Ðç"sO¯’^éï-ò/r—ü‡Ü#÷méP²AaNk€§Ìɳ!Àó1À Ì/Y$½Š^óãóšóèâ†ëbà]LzWs7¢Óˆªþíˆ0"ÜÉDâKBI I&Y¤€”¡ Ux…5x‰õx-øÛð ø{ð?|Šÿâ3¹÷DM?ˆÎ} :[žK‡ñWO2ƒ1 ¼F.~EG+§ë#þɗáK¾Ÿó q_Š¿ò«p›oÂ-~#nðÛð™ª×T]¸¢:†Ëª^ô©nâbÿ§èðç +8Kœ!N˜×>ÞC”ÇðøÙ¾<O}'ãá iøÇ dÜ”Ž[ƒ¸á[„k¾å¸â;—ü¡Ï¯Ÿø­ÆE¿f\¼ ½ƒwâüàNœrg†œÅ©!×pò/Ñ3ô¿Ì94L`º½ô"Œ"}*/¿–â§@%žSüßÂçþãpkØû¸6\‹K͸8†ÞNœQ‚³³p:  +§jp2`9N¬Å±€õè ØÂÙÎy€éy’9ØÇt>`:G}ËvŒúƒm›Þ(/»½cH?ˆ®5•¸'ã©ôIp?P;¾¸2z4.Ž™„óc§á´: 'Õi8¦¶ã¨ÚÃêèVW0Õó™.õbf¿z³WÝÈtª[Ùõ¶=h/ÛÔÃî +ºÀî ºÇn{ç¹h˸_E›Æ â¼´zy¥ÿ’ÊɓÉTb5À­É ®OàÐ7®?ÎO‚ßEOH…hq`âtì ÉDgˆƒé)`ÚCʘÝ!³Ù]ÁÕìŽàZv{ð*vkp³hsðѦàÅ­!‡ÄCΉׇÜ7OüZÒ4ñgIÃ{ÂÿYûÂ*w¤}? ¸Aåµ/‚zýPg&óè™2ÝSÕØ:¡Qh MÂÎP3³}ªÙ:5Ù<µˆý@SÎnÔTŠ6hŠZ4uâušq“¦UÒ Ù%Y£éâVkNq+5W¥õSŸH—OýQZ*H—yYêå‡ITꩤމ&ý8šùbiÞ¡'çH¸ûÃ}Ñ1 +»"'b{d86GjÑi`6D¤3-vv]„‹m /­ Ÿ%^^%^¶DR¶’[ÖÂ- Û&­ Û+[v\^Þ'_þH¾ â{BWG²7ù&”ž3Ò¿|œœ º)Þ-F{ôlM±ã±16ͱÑhŒIbÖƤ2«¢­l}´C´<º@´,ªL\5G²$jW3­NºpZ£¬zÚfyÕ´ŸyQG}*£.*æD=P̎þNQ-øx‘¿æyO |JOÜiÍ:D'Åm”ÇÖxZüѬS£Q7«u‘¨Oˆgê ÌÒx »$>[T£uŠj‹ÅÕZ¤*®Š›W+›·F^×êã‰kS”ÇRΌëU–i¿àgh¿U–jÿP”Æ ¯ðyÍj9nÒÚ/LŽ§]ÄnŠ·Òs·!I‰¦ä!X“2õ)!¨K CmJ,S“œÌ,HNeç'eŠæ%9ĕ‰’Ù‰eܬÄJiyb¬L·R^ª[¯(ÑíTéò…‰çø‚Ä»ªüÄ|~ÒïÊü$Añ&é \ÓÓ9 í£4{î±ÐÌIñFò£Ñ Ǫé¾Xn‰Z㻨1†b1Š©2ê˜ÊéÓÙÙ‹h–![\npIÊô%\©¾BZ¬_ +Ô/÷É×7+Ü)ەN}Ÿ§?£ÊÕß&ž¿ñ¹zAI(^s?¸dN‘~7µ_m™ÔçS¼Î¬Jå°Ì<‹Íñ íT¥MAeZ$SaÖ2s +[–jfKS­¢âÔ\q¡©Ë7•K]¦*™Ó´Ì'×Ô¤È1nåíÆ}ª,Ó)âF?›é?ôý•Ï2 J/ŠWü<¿h¦³Hú]ÙÔçSÛ³žâ5iÔ禋P“ÞÕþ˜›1³3߃'# e1LIF"[”nd Ò3Dîô±Ó’/ɵ”Is,sevK­O–¥AaMÛÂg¦uªÒ-õK·\'žQü ŸnøŒ4AùšÛ´½´îÒï̶؁&ŠW‹)—ù6s²†`VÖۘ™ŒÒ¬PeE1ùY ŒËf`ól‘Ö-¶Û\’l[)g³Î‘eZû¤[×(Ò¬›xsæUªõ„Êd½ÚÏdý·Ê”ù3Ÿš)¼BùšÏÈó³¤uØ´çÑ̙KP\Kí×|ÊgvŽå9~(uŒD‘c< +r5påF2y-ãp¤°v‡Y”å°‰­9y’ŒœbΒS!3ç,’›ì«F{«Ò`ÿ×ۏ©R엉§*½ý'^Ÿ-(_aðr…袙“h!êÔkS.s(§™N9Š]Qà—;yîIÈq‡#ÛËØÜIl¦ÛĦ»3Ein‡8ÕU(1º}‹ +$pöGn‘?ìÅcUkÉûÈ(‰b,% Œ¹ÄÀšJ,¢éÅv±¾Ø-I..㋪¤ Euòø¢Ÿ¸Â݊ØÂ#ʘÂO‰Çʘ‚—ÊØA›ÿ'“GHo­ÅtˆEÄ,¢þ9g0°—ñ°ÎŒŒò@X<ãaöh`òDÂèÑ2O +“â1³I›HçqŠãËK%qå•\LùRiÔÿÈ.ó°(¯+ÿ¾Ù„afØÔÔaQA¢â׺<ØTµ5Ú¨E£A¶ ¢ÀŒEE†qA&.TD0j]S4‰VmšX×Zc4DMòõ'á±>éï3ÌÂ}ï9÷ÞóݓTà84ɬŒOÚOZ”qIÿPÆ/yªŒ_,*ã‰Ê·º8Âì¥o{PÄë÷z’NóýÜØ÷-gߑ¢ÄÔn˜’Ú“Òô˜ñé1—>cÓÇ £Ó§#Ó% iïJ‡¥-”¾•–,‹KÍRĦæw‹I­pˆ^±—4;D­¸éòÄ!:ùg‡èåâk˜{ëRž‡e܋$“$Ó»0˜• +Lg«6)CŽ·×8cl¦7FgaTV?ŒÈ„„ìx Ï…¡Ù„øìéB\ö,IlÖ|ÉଥҨ¬Õ²Ye‘YÛ䙵ŠðÌ&rM¾æ±"<ã'"*ÂWýB[ +X—IYIoRðºÙ¢M^ËÞs=£ÂÐ\wÄçõD\žCŒáˆ5Æ`ã0DÇ"Ê83…ƹB„q±fL—ô7æJú·HCóvKCòŽviHÎ#iȆe!ëÅ×Ô¦°.e°.¯²I +ÿ^˜ ̦{êö~F`8[֘B99c@±"‹uˆ(AxI$ %±è_2ýJÞF_ÓT„šf!Ø´zS²ÐÛ´Nèe*Kv +º»PrQÐ? +_H +Ä×ì\ la –›dð5i÷!݉tOÜÌø‹ØR r+ZáˆàJWô©ìŽÞ•èeE9æXèÌ 0‡¿eü,sÐò¾–Õð±äÃÛb—å ´–3КïB[Ñm¹(xuQù!ëbÏ#IÉåYØÄ}XLa[8º ˆ«lú5Nð±ºÂÛê /«ÚÚxÖFÀ£6îµ#àn›7ÛL¸ÚæÃŖ-‡l…Ú¶*Û ¨joAe}u͏Dì¤t#Ï#s½*Ÿg¡˜ó1÷á6®Jï Ýô×Ò¿ð­< pnPBÝèU£NþP6êá؇Æt³€Â>2ûï µ¿‰‹kgBíæC©žü•ÜfQú–ttR@ïZ°| 0Ÿ1ÏäO'0Þá6 z?Ðï ý €Ï'€ûQ@Ó86Ë!=¡æ¥Ã•x-~¤ ã0h兠•ãV>€ÚxèÚ¸¹Ú\[ 9ÆÏ/“‘Gä0ß+ÍÀ"Æ<ÛÊ5`¼#ÑßHÿa ÿÒý8àÚ¨ÚÅiðÂAÎu#œÇyÎ㼖➼ õâŜ—äÏíœG;/"WXð¯ð _åB_-'{Ï9àȍN2¸ÖIŒ{¿šF÷(Æ;˜Þ¾ü™Ž^¯S€Ë@y\¢»|N¾ ×äÀu'^Ê5ÀMw6'݁¯t¼$¿jV¢€;¼ ßáÅà. ñ=ø{\ôû\äû ôþr²“˜žyÌù Æ=†î˜fÆß +0^-½z»½ò~I8m|E¾&ߦwŽÍœŸ³>çáÁ½ñ‚‰ɤ¿¬ëDtò…Ø­;D¼¢éM"ÉP2ž$’ydIÆOÈÀK¬Ã äáä£Åøex†JVғ…;؀ÛØDW!-¥tUÐUÅñ­¸†Ü2Gq§ñ?¹Œãžã"G½@οèêÌ\¨!ªˆ“Û/ë"éÅo™ã8Æ9ŽÎiôͦë=z–ГÂQ3pk¹Mrpq«ÓUF™ŽjF¿g¹§ÑŠSÜÄmå$3Ù‘O"š%ÿCôpb.đh8®‰ÒÏ!x ‹Â×ÒܒNÂuY"®Êæào²…¸$[Š òTœ“¯ÆYù:œ‘çáSùfœ’›Ð*/G‹|š6üEр&E Ž:´ãˆã=؝~@ƒJDý¯½dœ j¥|å<\5x¢ñÄ]•7•\u‚Kª18§ú ΨÞÁ)õ<´ªßG‹zšÕi8®^ƒ&͇8¦Ùˆ#š"֔Á®ÙŽFõÎõ8è|\Ú±Ïõln/`uQã.b÷ˆ>ôûòؐ<Þ·=¸Í||©ñÂE×>8í6­îÃpÜc<ŽyLÇaÏÙ°{þ ž‹Pï¹ =Óq@›‰ýÚ Ø§ý{´&ؼ*`õªÆnï:T{7a§÷ETù܁ŧ•¾¢PÑEy"rËÊ]–¸½Y‚t.ú:ଗ+Z|p¬GØ{Æâß(ÔùMÆ^¿DØüޅÕÿ=Ôø/Fµ2vù¯ÄÿlTùçb{@,e¨ ¨ByÀa›î°P¦;+”~#˜‚ž ÅA¢PD +ß@ dü!ôXjYî?e©=¡—¢)PÆ Ôõƞ>QÓgvéÇ¡J?ÛõïÀ¬Ÿ‹ +ý”ë—`«>eú ¡T¿NøX¿I(ћ„¢`³Pl67HòCNI6…Ü’CŸHrCEIίx̲\fimc™?Æ×Æpöž}aëçêþ¨2„ÁlˆE¹a$ÊÂ&¢4lL†Y(6ÌC¡áOBa©oø/ÓåÕ}†ñç\öì)A55ŠJ ²Â.à®{]8ÀËîÂ.Ë.·]n r[‘ÛŠ(—­Â%Œ¦*X“èèÔ±mSÓ¦i3¶Î´vò!m¦Ó´“t2M3Mš¶il¶/2füð›ÿ9çËó¼ïùߞ>f&m˜™J›`O¥fO¦-±'ö_æŽï¿É…÷¿É¥¿Ë¤ ©¿"¢Ü±Çø˜jÿ}6p/¸{ˆòVp¼\ÉàqéÀzœÏ܊5)˜Óhð¼FÓ+" ӚjLjÜÌIMs"³•ÏìfÙ!v43ÌgNsC™óÜ æ"Ò\ç4wýY¿Sôe}¬èÉ~@DùÇùPCÇéÿÔܦ£î+äå;t/åÄám"Îh“ÉUc*7'sMÏέdFµNfXëa†´Íì ¶ƒ i{Ù~í0ק=Å÷hgùníKŠ.íUEgî…ŽÜ_ í¹ íyÿÚò¢ŠÇyŸ´î“îÝBÊàrpžŽ™e®CëÑmÀ¤nNèSÖgcD¯ÇÞ‚A}Òۘ~‹éÕùØ#ºÛ¥ë悺£\‡nœoӝQ´êÎ ~Ý+B‹î¶²Y_Ù¤ÿ+ñ…Ш>B±Ê¨æ·I÷N1õ@¤œQDúäç,ù˜6ª0aL@Ø´ æ½4g"dÎGŸÙŒ“Èt›*™ ÉÁt˜UVG•–5„U~BµÞ$íåZʜ5”·ˆ!òÓM^Zé{£“ƒ§&®ÚMpÖî€Ýµ6W&dw*Ý&”»‹É]Á”º¬è®g‹]Îêêá ]£ +³+"˜\ç”F×5¥ÁuWep½«2ÔþCi¨ýJi¬‰ +øÕzÃE{Rp†âÀqb€ÞÛÉS#uôÝé‰EuýS¨ònC…wÊ}j”ù¢Ôw¢Ï‚b_cõ٘BŸ›5ûšY“¯‹3ø†x½wZ¡ó. ‡¼¯ +ùÞוyÞw”ùõŸùõÿy¢_s‡j½J`‰˜&FˆÂOÔy]Ë妔7¯Giófˆ-»PìO…ÕŸ‹ÿ +f˜"Œ™1j½¿‘=äïdóüƒ\®’?è_Tä´¼¬Ènù"Ûÿ[ÿ®Èn~ ÈiŠ~Í-ªûJ#0GLÞQ;‰ºŠ;Z€ŠPÒÆÃڇŽ0wn‡)¸†àj¡ï2@×eE~W9òºŒ¶ËËätµ±YÁVœà2‚s܁àwyuð6Ÿü5¯îü¯îø’W·GyuÛ7H÷¢ŸÖ鍽ôÜJxZ)st~P@1Éлº¾ä÷oA^ÿnhRqp@ƒœP>²Cfd…J  U!#ä†:Ô¤‡z˜´Ðq65ô<»o`™Mø>qŸMéÿˆMéû‚Kér)=k¼Ju.µÓžÐFë‘Æ ÑDÚ5¤-õ–ʞ[µÃ +dÄ!st#2ƶãÀؤ¥c8ia=RÃ|+,a_؉”pö„ƒH0»Ã§™]á ÌÎðM&)|IûIù7“4e“†Ö¸LZ³Äq¢h릐¶´Åc€qÈ=dL©“O ej=öN'â¹é$$O§`÷Œ»fbçŒI‘"ìˆÈØqãÙH+¶FBØ™Â3‘sHŒ\ÇÓ3oFâÔçHœŒ2‰§Ö8O1p¦Ö#ÑMύ!Z¤-‘vÁ87 dRLL=ìžeñì\,¶Î'`Ëüf<³„Í )H\8€§µØ´hÄÆÅlX´ã©Å|sñÖ/Ž#~qžxq‹o ná=<9ÿ)âç þ…èCæ†h_$Í¢u˜Ö­ª¹h +П²fIH^¶6]àp)ñË D"ž\ށ¸•½„ßXÑ"vŌu+žX©EÌJʕAËß¿|ìò-p—~I|îâgė‰PŸGÂ@ÕÜp°SÍ%giÎ9¤»Ÿâiò%Ò¿Lú/믱וPþŸë²«1Mãøÿ}ßSÑÇQQB_CŠRJ…SNéÛ铏hª©¤¦¢”HER !„|ÖdB¾2Ñ9>¢¢eȲZfǚ±ƒ5š5Ë0ŒÏżó¯mwí\]¿ÎÛõžžÿÿ¾Ÿç¹Ÿûњ@ҚCÔ€ eS¬eSªE؈éxèêxè¸Áuœ`E´ Dû994|Cݬ`®óóìµ@cž\ „0^_êºïœøo¶ €å!Àô(`ô ×$' ‰’ôNòRp’>šÙœ6³9m¡V†­<Z¹Ñ[9É­ ®u;ßáçyr“Ï÷»)ÚÀ½°˜É˜§ñ+Æ«f¬£´À0jÚRÓ¢ P6½‚ø€×76À +à}œ£óæ@»›R;àNlÌØ_¦ËlL:X;¸ù:8Ñ ²ƒu'íäF7yۀ´Ü‹û€ou½ŽQÿ`Óô= ˜PSŸÖyä¸äÏä +¹*_õ¾6®™ßX°A¶æE—•Ûl–ïÐÇ÷<˜ï²ðßÍâŠsÒÉDwî' ®óL7Œ;áçà0Ìx½ï0êZSלV/Rõ¾"×ÉßÈ­þN¾'w97?ÐË=àG3àsò—Ǽ´üBOٌ<ãÁóœÅî݋*à%…_꺑¥þaуBF’qd‰$ñ$o‘…×ÈÅ+â%–â9VâÖâ)6â *ñ5ø»ñõø Gp-ø'.âÍþƒoàéîï úò·Y]>ìˆ C‚ñ+"ð/Äà’¨•N­yÔYˆG(¢Î2ꬢÎ:êl¢Î§ÔØÁq÷á´¸&ÜÄ9¦î[þ<`_áGíâ¯äz²¡)s¡ä“ 1'‰#Þ`uý©Î¦Q/žZ)ÔʤN§`uŠ©SJÕÔYØÂ1·ákìâÔÕsÉ4rù´áŸ.Òáf­£ÿÙز~/È¢!ÿêӝ‹7°§î:WáG„P3‚ÙŒ¦V"uÒCþ‚¸Š.Ïbê,§Îêl N%Î3_¢gpˆšqŠoZ躙Y<Éù8I•ï +õ ÷᧾dÁ”¹À¹JÝQŒÏŸ¹Ó0’©ÔŠåhIô>›žK\êP§§±­\͜““ÌE×Å140M\íts :á´Âk4ˆ2JÿC斒¹Åe.éçFžâŽ`†¢ ®J.¸$A»"gѦ˜ŽV½84ë%ã„^:Žëeã˜^.õãˆþRÖ/ƒN¿Zƒ*4؉zƒzìïu u½Ïa¯áwØcô3v¿E­‰Œ=ì 2·Ò–˜,wwȍ>®õ6Âå^ýX‚ã´±;šMÆá¸I(M"pX2 ʏqP™Žze6>Wæ£N¹ûú”bOŸrìî³µ¦Û±Ãt?¶›6â3³/QmvU揱µ¯Œ-ýxNõ°‰È,+? bIa‰»J.ðùl?=´™*qÂ|Žö]?o°ý쵘‚ݖѨµœ–)Øn™ËyØf¹Õý‹QÕ%*ûW`‹U56YíÅƇQ1  ë^Gù ‡Xmý«¬ånÊzxjÃ3”%ˆGÎyg–{GöúöÀÑFhh:ë!Øm3;m}PcŒjÛ÷Qe‰­v±Øl—ˆMv©Ø`7v9Xg¿kí—a}9VÙoEÙ{µXñ^–nAéà+Â'Cî %¯…bY(z‡Ô¿áÊø=þ}Übi«§Ÿ}zØ5Ä 56øt¨3¶8zc££?*ðÎ1åŽÓ±Úé#”9ÍÄJ§YXR§<,u*B‰S™Pۓ÷ C¬ñ臣ì±ÌÓ%žÞ(òôC¡g( +<'b¡g$òµÒLŸCR¢Ïi†ïmE‚ï/R‚¯üÄ.®ø§©¯ a‚õÇóÎǜ|â+¢ÐW‰…㬰@=óÕ®˜«Lµ?2Ô¡HWOÄ,õT¤ªc¢N’ÕiB’:[Hô+ü–‹ñ~¥üvH±þZEŒùNíÿ„ÈÒ»\bÜÍ¡\‡l{¶±«àóJza»ŽÅ|—7ÞóÇ[ +ÀΘà‰´_¤!90I“…ñB|àÇB\`¦˜/Æ.“> \/EÖ(¦TL :¥ˆ ú–<&¿J‘AòigŽ³ÝÙÇV£2œ9àóRz)d>rIv°!æ›cvˆ RCœ⎙!c1#Ä !aˆ ™ˆØHÄ„Æ +Ñ¡IBTh†0=4WŒ -‘¦†®•¦„mSL +«'-Šˆ°kzaøù–ÈR“ÈYÎA#[Œ]dóû¼ëÐK½ä3Ùô’f€´ ¦Hž0‰$h\§ñF¬FhM0¢4ᘮ™ŒiáÑBdx¢0%|–09_#Müë2‹ºÌãøç73Š¢(à‘Bj‚+Š7&‚‚Š +"ǃ0#2L*Œ8©‰£­°©yð2×T¼2E¬Ìõ$³\³CtÝ2_Û®í¦f©­«™F»•m³o^R¯Ýýã=Ìïù|¯çy¾ß”-–´Ô}–ÔÔ–”Ô‹ÍRR¿âó¿-©)>óϜ"3¥ä*¬’{ž$³±efªEim4%íå§wW^z¤éQÊM¦ é ʶ&ËfÍP¦ÕndX§VëL#Íê1¥Z—šÆ[W™“­›,ã2öZ’2ŽÃ¸cI²þ>ó¸&ÞÄ÷ý6j!‹<@<…MsùûLì)À.gf€ò2Û˞ÕU9YÊΨ,[Œ2m#eµ%)ݖ®´ì¥d;ñÙӍäìbSR¶×”˜½Â<&{£ytv%!»>€Û–Ûóh›ï!Y>óq4öM `,e,xŠ°¥Ûòùì˜à¯ 9Á²å„*#·‡¬¹ý”f¢T{œRìc•lOÕ8‡MIŽïEà,‘²Ñö¨%ÒÐeÒÆÄF´î+¥ÕÍÕam€Ú­k§àu!¦ u‘ +¬Š‚áj[5Vm8ìªòպʭVU‹å_µZ-Öm—ߺCò[[7ä·¦A-Vÿôsèy¡\ÄÛ¾HJÇç1eRl¥4Ý^kЯBƒÔn£Ôfs µªn£–ÕíÔ¢:D~Õaj^)Kõ`™«ãeÚÊổÃf+]M"«Ë·ìƒ“4(…Ûð-ÒwZ^ÊÝ…Ä;ÿiöâr) Ÿãž“¢ÐínwFÔÎ[¥àèï’Zîi&sMk.:ƒšâ½B8ô‘jiÊj¹pk¹xjÙäµu-‹×âHíN~sÎñÜp¾ÑRb]ŒÏÓ05g9à§#ž§э܆þ‹èïA¿V +xEò{M\0pÈ°ãvƎÃ4äGÂhˆ±ã á1.ÿ:û:6zI®Ã¹:bQG,Ž½Á ¸¥…Ïr/¬’òÖ±Ë>¨¦Ðí[#…½Œ>šA‡¤VG%ËëhŸ€·š8ٜ¨Íh[ém†“ӝiÊhÊßml҉GccPÏ¡_ONêIt=‰­ß.ýœâ󸤹ë9_ ñ9é%Îtz²ÎuR šþ¤Ðà½gàl€óf1Ñ3¨] &;Jw•>é%}Š—iB®PWf2ÄPäWIðU„®Ì«8rõ´f`ÖDböª4ò05€nt;¡xZjñ~“ÞyÀlý þ—€ÒÒ§p>³HŸûK×o“[Ôȝékòrfä>Ï7vߐü’Ý@a5쇃L½í ¨‰Ð úB,$B&äé'fÝš¥ïåÑ¿´Hßêi5¨\÷µB÷˜u¿Öz}¥Mº£íº­=ºÅ¼û¥êtCïê:Æ~ή±Â5Vûìÿð)Ú@C(ô‚ÇÑMà©44sћ‚Ö ÝÕ4棱XׯuSè¬Dg-:Xs‹®êE]Ö>”®ßëc}¨‹Xô+]`åF>ü/j·h Ñ ã×ÐŽãð ½M@'_\h¸Ñ(Ac«{)ÓezO•è<‡ÆzÖ߬“ÄâM½¬7tT¯£~ kâÍaý¾ÿÁG)ùô3͉sþvÄÏ0ý™X\ 穋³²¢cgµÉh<†¶ê<õ¢S†Îot„Ú8DN‹ª¡*ê~½•ö’½D¸¥Fö4ác‹ûšQºl±/Ë[~øˆn(1ŒÀ¯Á¬0­dt²ðŁíSXy:n¢]¢Wµ%è,W-5ZCNv‹]zI;±bÑØfœ×VÓ U[´ÅâÓæfÙ>¶Ó=¶ÓlíK5äÈ9cnEžÚ鄩›Žý‡ézjò>ãþý¥^¨TPnB„Hȅ’@B.@!BÂ- !"ŠBAQDTëýRu¶ÎºÖÖεgë™Ýéz¶³Óý³ûé™Ývvºn«Ý¥]öˆžýñ9oòþó|óæ=Ïïyžâîª2|kµ¯®1áæ;n¬mÆõµm¸¶¶W׆p%f.ŌâbÌ^œ™ÁÙçpæùeœ^w§ÖÝÂÉõ÷qbýpü…GXŒ}Œ£qQ,M¦¶B­ö!µ¹ïRÛ}›òÜ[‹;ë“q+67âD¸§Ä•8.n0ãüÎnpã̆vœŽïÂr|'ã‡p"~ŽÇïÇbü!MX‘„‹8œp‡ßÂÁÄ1»ñSÌlúӛ£+¦žù,øeµ¡àj÷w¸´÷ѽW6­ÁµÄ\ڔs›xi³§’ÔXJªÆñ$+“±Ü‚ùd'wc.¹“#˜Ý2™-³˜Þºˆý[Ïb_Ê7°7å ìI}ˆ‰´O0žþv¥G1öQݟP{WH{¯€Ž1jm—脶÷ ¸}=ÛÇÑ]8ƒÎÂc,PxuÝb¾¢Ì'úký…µ‰¾&Ñÿùˆj~GIÿ¿‚F²(£}‹²LÓs™1ì.ŠÃ¨( Qvˆ 0 .EŸ¸!q‚bzŠëÐ]ìBg±âNt÷ÁW2Š¶’)ÖZ²À¼¥çXKéM於C~ʚ%Ÿ‘¯X“$º¢™|@5敏—É)p¸œêS–=eÀ勔®Ç d#ú$éJrÑ#¡K*C@Z¿ÔŸÔ‚v©­enxË:à) Â-‹°fÙ$sÉæ™Sþk”ßà4Èßæ8?&"ÿfE”9äO½O5_×Ð{HcÏq2KcØ^Ê2F9†)_¿<Ayºå)(²Ñ¡¢]QŠVE9¼Ê*´(Mp+ëФtÁ¥lƒ³¼ å;˜£|‚ÙUs¬^µÌlªë«úùˆü‘cQÿ‹®QfU=õÕ|ÆŒsdLÑè3NY†)GåëQ­F@Ÿ:­ê,xÔùp«ÅhRËáRW¢±Â€† + °WzPWÙ [å³jƙEs€ÕjN1“æǨ}ƒ|Hþ@þÉ1j¢O°'Pݛzà49D&ÉNº7@9zˆ_ÃЦ‰…G³ ÍÚt¸´|4j áÐJQ¯UÁ¦­‚­ªÖ*;,:7Ì:?Lº>fԏ±ý «Ö/1½þ*Goø6Ggø!ù=G§ÿ‰rôO±û4â\§Q|‰Ì’ÝÕ´oѽ =?eiÕѬ©_§> †TÔx° +`5”À\­@mµ¦j#Œ5u¨©iBuc:ãNVeœfZãq¦1^áTïr*LÉ#N…ñKúåTÖ¬`o+&à™&£¤ŸîuÒóh¥<͔«ÑƒzSyÃ(ôŽCèC÷ x¿IÞeùÞ_3ç¯LÐòVÐeî(»Ú%“dˆtSÍVÒ@uÍ´ªé[hæ§UIѶ +ÒöX”ú6¢¸# âD(ò£Ð¯Àv¿B¿ ‚€ù/ò½È ì?0‹œÀ2²¯€x€mŸƒçÿ¼Ž¯Y¶/ºâýsdœêõ?q»éð5­€¦êûi÷ë¢Ý§g„½ñô&#?ÈE^Ü`!ø! rB*d‡ à…lØnFf¸Üð2ÂSH/!-|©¡ûH }ŒÔàŸ‘ÖûÒz¢+NR­i2Bzé÷¶'Õ6û€ª@m’ ÕïòW7‹¬¡Dd§€;œ…Œá<¤GDH‹È©DJĄ­‘$´#i¤›GöbÓÈ"6F®à¿\—yTd‡¢"\¶ \ÙT.j:Z™S:*抢¢‚ ²ª ‹+\Ü—Ä\REG'·r­IsLçè˜:Ž§ÒFs§±´qî<z:ýñçpï÷{·ïýÞ×-{¿\³ÏÉ-ë®Ü2ŸÊ=Ãú3Ëð³ÒÑLVáh÷Gû5֢]2¤PÖŀY’O~+y8«u»< +¼e* {a˜Ü +#åZØ~/cÑ`¹Å˹h²œŠfɱ¨L…52î–}Á'2|#ÜïåÿLyV-J¡! ’‰wìdb€ö›éR,)r¦–'¢?WòXÀXb''‹³-&ð–ƒ%PKGÙ[̲³ô–­¥¿ZZF¨…%Y6– 5³Ì'áÕRévv̒+4Ä»ðxªB✓ÐM˜J̐ÞÎ&øl.@ÝÀ…è—¢¿ýå’c…­l+eSÉ0º’w¥/qÁƪxø«hòU4–jŠ«:•¿q¢jŸÙû>灼€ÍÍi06“»@¼ÿ0›{€Ï]1½ºK%ï’‰5Õe•dX+µ¨aXo/m` ßàÆ£ËP¼;61”Ö2üÔòð×Ñèë†@Ì:X»vò¹ãp ¾ã{”•KO"Þ£ó¥˜br€Ï¯.–ÂË¥ *ôÑ4­—œqÁ~³d³%dÔ³Õ³|à$í$;‰Gƒñ؍=€‡g~Iރs{ˆEc¿ÿÄïÓpnk*>'͓†•|þ]%5ˆ¹!èúðqw4ê¥V èîBÉB%}lÀN:èÈPÎBpØ$aIø˜¡øvg9Îãs‚Ë~‚DŸDè$Á<Ɂ'ø¢ =óâóëïQµÜÁ÷%_BfjD¿d{=¾ÂÂÅYpNÁ'ð)|FLN“›3Ää,19ç%]`a¸ˆ—B.ó(}IN®PäWʤ«8x§®d±8¡DÊuè:ú1>¿JŒ;¡ëŸ‡Ð§„[oÒû ÎÂp¡‰‹p ¾„«p¥ñùùŠ…í&¹ù§¿t;î1(Þãá¹Ïå{@}> °nâñp/§œ›p_…®Ðbô?Åê'vÌ5Q5Mß+[4[ÿR‘jî³cÞÓr}Ç®{Gï±·ÖêEsS{õµŽ²Ã^Ð þó=Ñß9ñכ°Ê `.àAèF¢ÛÝþhC+qè¤ê¶Òõ­rÐÈC£H_i!eœW®kªÖÕè2[ïEíBý ¡;­¿ðɳœt†Ó‹UvÐZ‚£þ+“~~vÔuGóMôéDç]쟀F3ÐÈA#bÃŽ³Z̙¤m e²‰î |öé??æ[±#(Fé×XI㠞¨ñ5µ¶h»HÒÜKS?´†àË(4ÑH¡ÓИÁé9häñb4qæR<_©ZÇõق»ÉÈ5bå.²Ô@dPÛù+^è?ƒûjFıؤóÄâsbñguCë ×|†Æh4’¸š)ڏ$/{±£;vk.ç—rîrÕkµ¶‹müµ…O×qR-YÛ¤k#™Þˆê žë?†;@ÇÐ_e‹Ÿ.hza}þD Õ­¾è Bc¸>ÀŽر¼lέر;ꔏÆ<Î-ÓzU‰­å«ùv5«¢ZV’áJ*­åçTÀ®Ó®)Wû ×êxËç­À€®+š>hv@ÏÌI½Ñy _bÐŽÆh4’¸ÐICg†V)BÎ^¤ŠfËUÞl–ÙlÖ›F-n~T––—Tj{O¥­žªÄŽ÷²‰\åë´·ÓhÓú÷Òîh{õ¶NÚÖÜCµ-ýµ¡U'­³ë¦5v¯k•}?UÙV¥ý­0īܐ¤e†-5LÑbC¦Êf«ÔažJ–h¡ã*Íw¬Õ\§Ý*v:ª"§Ë*p~ 9.ϔïbU¾ñnñܜoG‹åÉÙE»ßچ§{Ö[¨ÆÉE«Ûh¥s°V¸Dh¹±‡–û¨ÌØ_¥ÆwTb©…Æ-pMÖ<×I*v®"׸jŽ[©òÜVj–ÛFÍtoPŽûGÊ6]T–Ç}e´~֟™×üh¹¶¤DÙ(9ÊI‰Q&1·S¼9DqæpŚ»jdt/ î«aÑ44zˆ†tÓà®cÓ-Mƒºåh`÷yн\ÿgºÌ£¢:Ï0þŒ+*"àŽEP”E†a†eXT7Æ( +.ǚb´¥š&Zš¤q_cÆŒ5Ö¥1Ñx¬ñXÍÒ¨ÑZMÒäD§? æøÇï\†{ï÷¼ßû¾÷Þ÷É0¾¬tã^ƒÍø>|߂ûšñ3ÖÁs°æ1þTG9y™%ÑÝ41ÆW…1~¨ü˜PåŌV®1VÙÆ$ٍ6es”[ ŒØ2¥Ç͔-îWJ3-Wª©AÖøMJ‰Ý`‰?f°˜¯r¼îŸ1¹ 6Ó Œk`TÃþ7ƒ8¦“bŽEqgò–ÃÔO9¦Á²›†+Ë®ŒøhÙâÍ`Uš9K©æq²&”(%a†,‰ó•Ìpœ”¸F‰IÍJHÚc0'…+ð ¸ ‰?ó:cx#Ô%S˜3ù=•|K!1å'tTN¢—쉽•‘è/[ÒP¥%”5)J)Iq²$[”œœ¡¤d‡-“”`™.sÊ\ŧ<+SJ½â¬MŠµî2ÄZŒÖËïbS‚»•žIÆð•°ªÀ ¥ÄQÎg[Ú)#ÅSi)¾²Zýd±Q²5D‰©‘JH5ʜš¨ø4›Li¹ŠK+R¬mªŒ¶9Š±-QtzÆ¦oԘôÐ¢¨ôKïjŒí0­¥¹µÕÊ;1Uªe ¯† +˜Êï‰üßv~§Û˜7m]•œî­ÄŒ~2g V|F°â2Û-c¦Y1YVEgÙ56«@cì“e¯Ðh»K‘ö•Š°oPxöv…e† +³ÿGáö +Ïr+^eý†ti)̇Œâ¥ ÀÎ߶LUvyWMP*§¼ªªÕ½j4ʳrºUS·9×ä9û¾ºÏ~ înÕ¢µf@ ¶p¿‘¼WKžXÕN/`^‚õ¥ ¿Šÿ@‰£‘8šˆ£)‚¡a3/™fš«‘fl^˹-ð×~ä¢ñž**Éuvï4Ï{Ž¬•‚W¡nŸuè£Ù•-thF›t2àK¯ Æ` ùØÊP¾y;ÃèNâØŲ‹ÍnþÝ{7‰ÝM.v7ñÿ7€\ìºÄµ7TN‹(WÖRjÀžÇü–g€p­GŸË½_–º¼&h'Œƒ?ìmãMØ×^Úï!½…A9€18ÈP~ˆ!ý0q¼ËÒÂG°…¾…BAè‹·l†ƒp.ª„|çžµžç‘ì7ݾ\æ½ýGšûà‚x¯£ð`K:Ž9:Aœ$'§©Íß1 +ÇG fó:GMÎÑhçIòù Àâçކã* ß¿ç]ÐÈ{€Ý.ù¡ëCûvy¬ùHç8œZZgÚ8 ”Uçàø|J}®Ð'×|¤/ü¤¯‚¥ëFé„›ÔäkŠ~‹»E’o#v{n¯;tkÃü`Œ3¤ãóõ?M—NñÎÒ=üå]üå|îm-Ó-­ÐM<æ ­ÕW8Ë/ñ™Ÿãt?ÓºªÃºBà—9sIߦ»•‹m|Òêy= Câ魇 +ЏÉFý¯{ùoèk•ê:þòKüåçøËkÄñOâ¸B—õ<õº u:¯ú˜æ=KÑ[Dp\§¹êџDáÄœlAOЕýúpå@öÌÞF½=+ä¡1É¤ÞI *ô!q|@#ŽÓÄq’8þªÕ´Ç‹”¯™–ÙB)÷’‰½Ão“±ƒdõJOòXÿÜWGt½Èaö€Þ(öƒV2:™hä³£‰:FG‰ãq¼K]k!íº„õ—³æ*íWm¼õWxŒvjgv‘…úBÛõ­¶¡ø˜­m1<„{ð/¸H.ΐ‹“äâ}ñž"Ñ1±++ÙYëO䱜LµËY–vÇNâØAÛTúuÚLMþ¤&¢Ø¢MÜñG2Ó¤OÕøžË<¦íóŒãŸJ‚‰pßW0`6Ø`À`6`ƒÁÜÀ +$¡&!Is±MÒ4I›&kÔf]zd=Uu«¢®«¶µÓŽvÕ6µÕ¤ýQ©ÒºNÝ:mk·UíŽvÞ·d­¬Þ÷÷Úz¿ß÷ðó{>ÔI}ÎRþ’/Öÿ‘xW¼%^Õ½ø¡îŋº7ÈÓZÊ¥c×:š´ŸæïÖü\—Gåãù¸&ßdQû¤qXóžÔÍ<¯pz…ËúÕ}šá^íÖݐóÚés:ñóÒþ’DÁïv)^‰VˆY =·HÓ¨5¥K¯H:Ò©Õ »¥Ñ. fÆ¨4&¹$åã^íÇöKcEÿ’»ô¹Äi¹;¥:©Ûp\'zL»}Lçñ5iÉÞÞTx{Y<¯ðò”ž¯+ì='Í$éeK«D³Y¥ãäž5ίéàî¨ g£85Êé¨0w®½•“k8¾vÇ¢±}'G×ÝÃáuW9¸þIîXÿûc~ξ[Þc_ìÇ,oˆ°÷ÿ¼£ÐúS…ùçÅã)z­(Ä]Qxùº!šË·¸'&™s±yÜ[Æ© ՜ÜØÀñ-ÛØÉÊÆŽÆ p8nŒCqSÜ7ρ¸Eöö³l8ÆÃyn7<ÈRü슁Ûâ_gaÓûì4~Êcä+ÞTh)çæ«æê_ÊÔë43 1œŠ7r|S+Æ"-4:8àbBË ~ö&ô²;aˆÛÆYLœfWâN÷²#é(ۓÎ2—t…ÙÍיI¾Átò«L§¼Ç¶”O˜J|ÅkzýÂÃJA.©=«çyJ-ä爼J6p 9™å”\v§˜XJ­b1µŽÛR›YHõ²#-Àö´si#̦M2“>ÇtúSé gœb"ó㙏²5ë;Œeý„Ñìß2’ó±ˆ|Å+ +çO›ôúçÄ =.VÊ%?{åewV,‹Y ,de°#»ùl3³ÙÕÌäÔ3ãa*§pN7“9Œçnekî4£y Œäíg(ÿƒù(¸FÁsôþˆPá;„Šþ."7)ŒðR¹î .‹ÓJŎ¨].ƒ%ùY—ë˜Ëg¦ …m¹„ K˜(¬d¼ÐÁX¡‹Ñ¢V†‹ü õ2X4Lq˜¾â턶ì¥GIP°äݦ‡è2=K ôeñ6þÒ¿‰ˆú7¹Q×¾H¿”úÔ_ÒØNy›•—™’5„Kâ/Ib¬$“SC¦rM6úMNúJÝô–úè)í&X:@wÙ8]e³øËo§³üæs´[®â³<ƒ·ââ7âCñ_Ák‰ðœÒ«6Ý¥Gı ±Yy™Ò¾Lh_Fͱ ™ ˜Óè3çÑk6´TÒmqÐeiÄoi¥Ó⧣"D{Å(¾Ê¼U»h­:D‹õ,ëxlOá¶}ŸfÛ¯Å_Õÿ\DVyFšW”fœ•/ªÛäk\û2,ªÖªŠ'X•L—5¿µ˜«™v« ŸÕI›ÕM«­[žêaÜÕS4×,Ðd¿—ý Ž+48ž/QïxKüEýÏDd•'¤{©VwQiÆ>± fô<¡ñaùë¯QÍS³–@M5‰øìxí´ÚKñØ+qÛ4;\49ÚpÕvÑX;HCÝ$õu;p:÷SçÑ©ñ6µn5z¢q¶¨mIÄޚNuk>¶VÖ¶JªÚT¶¹¨ðz±xƒ˜½#”ûf(ó-Qê[Á仗’öGÙÒ~C¼Îß(ñý“7²Êý_”eJ¿÷¶À¼˜ƒ"(¼¢YåRƒÒâZŸòþö X;ŒTv¤Pљƒ¹³˜òN3eÕ”úë1ù[(ñؤ80EQ`…#.ßõ°xž¼®×È ¼O~àS +ü‘U.¶ê.HgIÜ*­1Ñ'üÒô´ký*•j;Á€Šîʃñ”“(éÉ`KO>Å=&Šzª(ì­¥ ·™üÞòzûÈ MÚIvè Y¡»É =DFèÛ¤‡~&~OFï'döDÈwKë ´Ĕô†DP´K·IºN•®ÕAé÷‚©?Š¢ ÉL!w(‡œ¡"²‡Ìd U“9Ü@ÆpéÃA҆GI™#yd›GΈ«$ ?KâðÅ»$ }ÌæÁÈ*wJkY©ÿœôÆE¿H·M%ZcØU¶V¨ö‚¢QÕ[cȘ06‘HêD:)“y$O–°y²‚¤ÉZ'Ý$„ýbcxšMáÝćOb_O7ù²xÃÄGÆ?#~<Š´µÎi1"ÍÑ¡5»UžÕI»JåQ٘ôUžä†!}z I³±$ÌmÂ8·™Ms™ÄÏ`˜/6âæØ8ïeÃ|/±óÄÌßÆúù£¬›¿HôÜu¢æ^díìDÏ~@ô­ÿcºL ¢<¯0ü"‹"2  +*ƒ ²ˆ5®"(Ȧ((ˆ² (8* +Ž+¢ŽË©â‚©1n&ÑDŒQc“Ô%§iŒ[5±Ç¦­MjÔ¨IÛ4©Ñ4>99=žÇ™ÿgþûÞïÞû}ÿ½ßÁTÇ:+Ñ+„Hϖs©ÃÍ'ì'- ŏ;øq?>Ə›øqƒ)öSè&ÅÕªtÞÓûüâ"Þ_Ðu•~ïuú Ÿy®®ú§zè±üYWzÑú+±øTXG¾OÃ~>á/Â~ö«°¿ûµØ·b-v7RÛ(“=z›B>C,Nóÿ)V|«íú^ÑÃÁ‰ÿóá)¶P+[©]GñðÙ9DF¡xÐÁ!‡úáNg‰uÓ%y³Öab QhŒ@#ûÉØÎ`›ä°5óõ2yi£>ZUýƏƒøq@ëÈÄVŽf*ã%Ž”cDåÇËu²ôX;õØ;Ùúà–£äM,Þ$Ç©‹WˆŽ™5Ä 1 +û㱟ŒýLV˜ý<½HîÁfü؅;ñ£I+µÚøÿoå—[°²‰ˆm${•»ž +_v£ƒ'ý l©SŽ#§º8ÈiaìÓtÂÑŠÆüNÀr +ö3¨¾l4ò´?6ᇍ¼l >UG$Öòo‹Vãá*V°‚Ì[Éèrª¹žª«cÇÕ£ßÁ_ºKïs¬œ4 Íg [{/Ç^³º£g¤ºÐ A' +áhŒEc)hd²²ÑÈcå³Ñ)E£ +»‹µŒ«ZV¾„È,""[Ã.¨vº­ê._iós°wr#í ÇkGý>>wp½•ãe³‡³l®­wòUƒS Vw ÕJçhYG¨Þ%Vu.‰ZꚢZ×L-qÍÑ"×|Y܊TãV®j·ÍïZ¯ª®ªèÖ¤yî-*s?¦R÷wTÒýc•xJ1›”l×Dó%™G(1,V a‰–¦øAي /иðrÅF,Ö؈‰lÒèÈCuR#£~÷ùþ=Ø;iAo mÆ +Úá…1Ä +ùžÇ½lü˜Šé09ÂC“"ŒJŠè­ ý•ªøˆ(ÅEÓ¸Èъ¯±Q)5U£çkTt©FF[4bȽ0d»†Ç¼¤a1íó|Á÷§`×ð!víòS\7”yŠa&äpo +K#.Éø“ÝM Ñÿ£ºÌ£¢>¯0üdQv•MvD}†}GEepcÄ `Ԉ\“Ƹ ¨‰5q‰¦iFk¢¤U“ظ/MjzbNsšÖ5MÚSÓÖTk7ãôIOûÇsf`fî{¿{ï÷ý¾×K9‰YƒeIŒPfR¬ÌIIÊHJWzr¶Ò’‹•–R%SJ½Œ©MJM]¢ãj%7)ÉôŠMG”`ºŸóþ¾’ŒŽA¶£õ,Wà}ÀžÌzÞ×@¹óy>¯9©ÎÊJõT¦q”ÌÆ¥Ãd2Ž—ј T“I)&‹’Ó +`²’Ò§)1Ý®„ŒEŠÏX©‰gÞ­Xóš`>·xÿ7Åe8نV7ºm\›3¤™0*ù»òùÌÊë¤ôǔ‘á.S†R3Æ(Å;[Ñ9%ŠÊ©VdîLEä¶(}t Íè·à±j®Kœ4l)w)·‹W—že 7Úv2ílí {Emgíó¡6Ãk|÷m~snãžæ²Öé0Š(…z§²æ8»E B×°Hò~Rr_&¹,çÒK8­p.£+©Å*.]«¹ðtqáèæÒæ‡Ã­‡Aïaa=°§ èGϾÓÏw1«]_ð»¯5 Í©PFŸs([Ú\ö!kŽ\ˆ>ºZéõiÄJÉ©mì*si-ñµä±Ž<ÖS Qòè zt!êãaØGOú¸>jÑÇbúº`;Ÿ’6úÑ{[ èV‘fõ6S²DÖEÊÁèV¡¿Fr{Íõ° ¶À6xh¯¾ç$íà2þóÞÒ.æc}ÙËÅc³±žìcÈöÑÔ}ü¿¾ǹÀ}7TG½KH1‹±IaÍ1Ôyë5 ë¹‘ÚoÒz vÃ^xƒùá2 +ûá†à 3ò#jr˜Kú‘ yô3ý6ý Y+0›ý;Š“ég6~¨ÉK8“ÑN[Á °æÐuÌ?£ãEÉ\vih2@oÂÑ!ނŸÀ18ïÀIúó59͌œ# ì• </²W/RôK Õ¥ Òe_&Øå“*F;íDjÁšÇ’¢7»¬ïàæ€ÖñøpjÀ”ÁY`›ë\‚Ÿ šUé +ü‚þ\eN>aF®Ñ—ß2£×éÉglø ÛM†ëæVéżu§õØ ïuÈ <ÀÆÁ=”wš'-Õ]UëŽêõ'üÔmüÔðu¿Ç×}›úœr Çuvxaù”Æ}‚kü˜‚}¤Ó¸Ý_ëC<ÞωüÁá <Òÿ74}t÷WEé/JD3½|t*ШÅ-6¿‘ø¿•øKˆßAüNâwë}üÝeâE|æy\ëY"ƒ·qyW(ãõ®Ð2Ç9ö?9<„{Î=õ;ô™Bõ¼î¯¨ÅDz¢QDüJÊ^GùtŽ<ΐÇ)òø)y¼‹³|‡XËû5î<Ò\‡iÕ0w´|ÑòG'X4’ÑHG# |4Jô’Ë=¶Í« ãOÓÜ»¶[;iì$Nb'Ž'±sqb×±sq“ØiRçÒÄMš‹Ó6½¥Zï:íÒum·U¥]K+T(L\¤Mh  B€6þá&B Ć m0ډ3?Ú?~:ßwü}~Î{ÎùÎû¼˜ýŒcûc/ßËÔVˆ0³î¬–Ö]ÔbÎ -ä|Qóë_‡75—ûŽæòþ©¹üO «op”}ãý©æœãú$Çì1Æs´4WG + :œkÑ¡\»öçÕi5Ï«½ù~íÎj%?¢LÁ€– F´X0¦…Âií*œ×\ъv­i¶ø´fŠ/hGɋš*¹§É’×5Qú&¼£”á>dò +éö³e¤E¬ÐãïÇi׸?€-Ye,«Æí-5j¥ÔªåÒJ-–ºµËЬyC»æ =ÚiˆjÖ׌!©Ɣ¦iM—5a<¨íNjÌÄ®1]ר鞒¦×”0¿¥ó»ð‘F,YÚ¬^F÷ºƒz¯’ø«Ð§ÝË}†c~‘±,lZ§s±æLf¥Íåš1;5mnД¹E“æ¥Ìam·ôiÜ2¤1˘F-ÓJn\ÐÈÆU c>¶nzRqëU ZïjÀöuõÛ~¤þ²?ÂÈ>ä.š/8™lجÇ>Xæz{˜f,3Œqږ¯)«Q)ë&Û³ÕiÔæUÒÖ¦„-¨‘²ˆ†Ê´µ,¡xù„Êwªónõm~LъÇÕk¿¢ˆýsÚâxUaÇà +WÞ§ÍÒÇy…ÞEÒüi—tÈ-­À<×3ôM2¶s3îÈÑ6{©’f ÛË5dw*n¯× Ý§G»ú=Š9bŠV©·r\‘ªYm©Ê(T½¦žêO©Ûù¼‚5wÔUóŠ:k¾oÇÜgòZçIñǘìè"Ìr=Iß8ce^Fː³HƒÕÔ_mUÌéPÔY§^g£¶8[®éR¨&¢žšAu׎*X;­®ºEuÔT»ëŒîËò»o«Í͉[ÿ=µÖÿ–ö¥?«kh=îRü˜‡io¤Þ¡˜yd,}®èTckDžÖ¸ÚÆTߖ–Û¿G.Ljÿ¼j7Tø2|[ÎÀ/ißW­ÿ?Õ³èœ@sµuÀ~NBâ£/ ]Ðmþ|ùü5ùÍj ”ɨRCÀ%w{äj©®c@µ£ªéœ‘³sE՝GTÕõ”*»^”£ëeٻހ_pý7úþ­Êάžæ¿øÚY‡jN~î#?÷„©¦ÎyºJäšä +ZU´«¦»VÎnª»ÛTÕTeOLŽžÙCSª-isè°ÊCO¨,| ¾$[ø[²†&[è=•…>Vy¹ý54–ИÁVˆA: …RÅÛ#Շ¨}…rn1ª*bQe¤\ŽHµì½nUôú´¹·Ce½Ù¢C²FSÚ]€CÚ;'KìªÌ±{ðM™b?‘9úWY¢ÿ’¥7«3hïÇzÏ£3N Að£Û„%nˆà»£RU_®*úKT>`RـUÖA»6 Öjã`#øe ɐ)>s2Æ÷Ãâ/À]•Æ_SIüÇ´ïÊ0ø²:ŽÎtfÃ|0„^ BÐ-½’'Fü”)ՃR¥›u¸P–„Aæ„E¦D¹6$«dLºeHú K¥É˜J’ 'w¨(¹[…Éã*H^T^ò¶r“¯*7ñCå%~(äcFg‰§ÐJ D HÌ~´½h»âè¡O™b¥l3åɘ*QIʤâÔ&¥ì*LÕª Õ¨¼T@¹a­ŸØªuL.…ä…ëELê%ø*P¤l§Ö܎‹Üþ‘ö¡3×Ç% C„Ñe{ˇvý°äLJöm’Åϳ‡Ë?åÝ¿À}í"Î ô´JH†ï%æ:bvÌ ®™RÑ°$®Hë÷®ã@ÁøíÃpíÇìÀhĈ²ó‘‘`Ö¼>¶5&ym xyõX{†g(b᜾âÝ5‹Þ s/w¦¤æ)ö1Wӏ®‰0JW©AJëc6ƒ£Ô”G1¡ÇÇ ã#óuÊÆ¡KÂ?C"<˚œeße.Îî o-ëqæ3<ƒ{>MÑzêmx_ShŽB?óÝÍ´µ¦Ù |ƒôÑ5¡[ByÇÐ=g¿Â®’ìr¤'™§¨oϳ.Ï0Žg™KŒã2{ã9ÀçØà— ò2{ó2r‰õ¸„{¿øüœçÿ¬ †8Ä|oa¾<æ!æj¶ ]Óq©øŒ”ó8zlk =ï?4ݸWáӘñ녘r ò öÇÍÿDöèöÆÖä›î6B·Ðÿ4-ëq‹õ¸EUsówJ2ß1æ»sgÔ‘ÊþÇt¹@5yžqü_!1&@€p 7ä"   ¼Vê}Z«V[;«S×nÖUë¥u®¶^ê”Z§­½¸YÙº^Ö9»ºº¶®gëtk×é¶sºZ§5ûa³çwø¾/Éóÿ¿Ïû¼ï÷>Œ×„nøZr¿1¨÷xvÀ·šщfK´0ß4&{C¥ýääYææÇÔi>ú¨>椏ÅÕÇ û~˜õqè°>ýJµ³%?ùÎAÛ¹B²>ˆþzôƸ%¨9 µöÝjÂø]çà…cÁFéõú2ur’¹9ÅA½ŸCa?/á~곟B;Øi÷ƒ8Ý'U¹„9@ÛõmÖcŽÂâ°íAÝg‚š|•FW´(ćWá$ü ^ƒ~øE°a{3ظž!'ïâã}òqžý=/…X€RlÝ $÷I¼pˆ.G·&°ê&ýÝ åҝúõ…jèK›t™>æoê¢Kšª‹š¥OèlþH·ó1ÝϺ¡éÆÎӝ£S{—Îô7$ïÖۘ~S¿Åâèõ §à¸ÝÃMúÌ«2ґZøv’>§×ýŒóϪ@§VÐOS;ñ»tF=ğIü»õ–è |¼ŽŸÓݞ¦pOÑ©þ”¢y•ïe× \¼¨¿0]×¹ Üâ¶i"±'kº£ãÝL>ÕR¶ŽXÒÈÆfæ)®Ž°½ôÃ'Z‡ê:´ÿÇ%t,óe¶v+Œ-ÀHü|';í!›ø…Ä.'v5±ë‰ÝLìqTa'±&3òiÌB/±mt9.Öh¿XI´dn9³·LïÁ?à¦îE€³Á¥v(¸Ý ,ËÍäâr±‘5²^qÄOÖCr1—Ê/$v9Ûuñë˜ý&â·q'“éÌÆ-æï[|c!.©yds.3:— +ž£Oán1°¼Ã.¶þ̓¾ÙŠ×¼ +¨‹U2 E|ñÄÏ$¾—èEÄ/×"|,ÀÇ||ÌÃÇ\òq7õÑ˺½‹§³øÕLÜOgTÓáT2ÝCe÷èOð…ºÑà8[ÚS6óú[÷³Õ.çÙR^‹Ù/i8:4ðìD# <4ŠÐ(G£J3ð1y™J}ôP§Ý\M曓´„»ÕTÌ÷p÷$™:¤ª½ƒ¤ùè`vàá [Ù6¶÷ ¼jV˜Ïý^?½á!š=8-:qèØÑHCÃÍhóÐ(f…–£S­‰wÔ«óŽMÔ¡öAS4>ä. Y¤ÖÁ«Ô2øa Ý©æЃj +=©Æ!çÔv®A@{ÐÜÄql5[ê=0f±ÍOã5Ü3\ê6„ª;Ü IC¢tg˜UaɚæR{X¶ÆõiÜе ­Tkøhµ„7ª9|œš†u©qØ 5D,P}ÄJÕEnÔèȪ‰<¨jÃIø\ëÐhn8zŒ`üÇfB7×]<ëÄK^:ŒCÕn0jœ!F­†x58ÔlÈP“!G†1”ªÞX¥:c½j­mœ¨êáÓUeš¯‘¦ûTiÚ¨ +ó•™ÂI•šß‡ª4êkîÙ#Ð[c#;zyÕöÀ\·s,kã³¼4G‡¨Ù¡F“I æ8ՙíª5§j´9KÕf¯ªÌÅU¡‘Q£UÕ¬òè•E÷È3G%1ËTlùŽŠ,ÛT{^‘/ö=¸Âõ hZ÷£»WìLŽ¤“ Zìœ1yހ¿:¼ÔƆ©ÆbT•%Z#-6UZ’Uaq©Ì’­ÒXŸü±¥*‰­RqÜƍSÁˆÉòYg+ßÊJ²­U®m«râ÷);þ%8 çþ:ô0Z+МËQt*¯ØNhåº1mž×ðy>GÚBTa‹T™Õ,¿5VŶDٜ*´eªÀæ•/¾Hyñ•ò&Ô)7¡U9‰]ÊNœ%}±ÜIk”•ô˜2“ö*#ù„\Égàs®ÿó€Ö£³ÝÞTú=Ž€íÐ õÜWó|$^h)UŠ—b{¸ +íFùìÑʳÛäµ'+מ®œ¤le'ùäI.“;¹FY)ÍÊLéT†c†Ò‹”æ|P©ÎÍr:Ÿ–#õx>“3õÏzÅhÎL§9þµeHcø_#yV†—òRùŽ!ò: Êq˜åqÄ)ˑ¨L‡SÎ,¹œyJO-QZZ•RÓåLï#}šR\ ”ìz@I®GeÏØǕ˜ñ6|ÊõW<h5ú ћ–É<ÀXŽuPÅu9~Šù¬/^ÈN‘Û¡ —I.WŒÒ\6¥ºRäÌpɑ‘£”Ì"%gV*)«Aö¬ñJt÷(Á=OñîU²y¾/«çGáù ¼•Õ}U6w@+ј‹f·›yðPP•Üû¡€Ï¼à†LîÓÝCåôåðD)Ù3BI»ìÙiJÌö(!Û§øœrÙrjeÍmӈÜ)ŠË£Xï}²xQŒw7U´÷ ¸Äõ—²ä´ŒØ½hN¢%iãèÙUPE<˸ré{ Ū¤¼H%䙟o‘-?AÖ|‡Fäg*Η§XŸ__b +Æ*º KQ½2.‡ïÊT¸ ž—±ð—^pQ¦‚C@KП‰ÞDڑ±P •P>ȅLÚÇÔ|ô}ô^…ƒd+ +W\±Q–âhŔX]’¤¨’tȑÙ_$“4ÉèŸ(cé,J—*²t=ìT„ÿ°†ùOÃÇ\ÿK‘%7´±ME£F4ª¡ Š gžÿR]æAQßg¸Ø]w‘EЪ(* +È-,»¸‡«» ˆ +BÁŒmªÄƒÄD3iÔFƒ¹¦Ui;1&ͤšÄNk’NÇcšÌ´éL56iµÓÖ£­c³ý,îdÒ?žY–ýýÞç½¾ï÷}øÌF¦L+ƒ¿‚Ý©`«ŠWJµQ‡Ødv|dÉäȕÑQ ìJvú”ä\*ƒ³C Î~Å;·+ιO±ÎcŠq¼§XÇïç¸þ¥^8V±„ÕÛœ`>(ù §Ý÷”*i¢ýådÿ_+³;IFYIžñJôdÈàÉT‚'[ñžÅy*ãu)ڋ€õ®ˆ'/ыpð| <è<Ï_h¾Ûê&¾åðáq;(ó@1τ;³~$Jš ~d›Ù«äʼnJð›°**À@0àô ¨:3ˆž"$ƒ© ú*€¦ –ˆ!ÿyð¸­U•ÒRxP Jí­lÌL_€öqÿ~Lš‘lÉu1JXbPt|ïR.·Fz#ì‘CÜH  Ñ –‚N€˜jÜų#aÖðKðgpK-ðÔ/p€ +PHÌ9ĜE̓}èO?üµð/¿QŠ_ƵœEgKO ËF+—k+:w%—KƒµÃÖF.Ú(\/¶Q¶u`;Ï°-®D¸µþ°M·ÜT\~àvPBÌsˆy&1O Â_?¼æf4`‹‡9†‹V§AZM.ºð£?ÖP“Ãpxøs {ÈEÆz–êÑ3ÈïÏñr [d÷§àïªç¨!måÄ\@̳p}jƒ”Ϋ)ðšÚ$C‡Ý7¦XÓlàaüX‡ëñ£?X†6N`àÂÝLM6s°6“‹Íôæ¦U|RM»y†žØðSp‰w®+§TQç"Í¡|™ÄÌÕ«^3uK a·A?À ¹XWY<Á£Ôe0þþ":„ÛÈÇò1Ì%7ÌÀ¦é‡ p£;q|'õØq¥…žØöøL~xÔ¹”|çÑÂӉ9c5ü=’‘Æmˆp> +¶‚í‘Åûqð„î/âO=äärò, êwéÓ}øq€KùCðM~€Âî'™ûq~gôù£<÷>¸,ùžO¾ ڙ…äzb/üÄk„—u?#|ažgåD:a/€Caq0&ŽXÒÉÉkôêðãu¥7F‚£4Ú(¹8¶!Åù8ÊÃGÞâ¹ä ¿ŠàÎ&M“¤ñÀÿ˜æÝá s½A¯Æ ";`4"hu©ô&x›ú¼ƒ`x?NsfOÓ§8§)øûœÓ÷èÍw â/Ÿ:©r¸óà΄;˜Mä6îÙïH„óhD…9pù¦ÒɈH#¥ú88rúpüužÚ\ÀË,b—©É%ý% +~±O +y‰À.þ…¡¯!˜M÷ÐwÿAÏÜQ‰þ¡jÝ@Ç|Î½†:¹Šª+¥OQ8¿ç|‚¢»Œ»HÓü–❧I~E?"ˆsp‡Ïè×hºë¸Bå„p;ÄC¤-ô>ÜU”n¢3o ï>×$}†ž¹ª|ýQúX5º€Î=¯:ì7j öÀ~ö{°¿û›°=Hj¶“¢=¤k? +óUxŽ“Â3z]WÀ]R¢tè+päk>ü\P\fýFi¤3®Ò[G¥P'Ø^„ÿuz›|¼…Â:êzö:~üùCüE©Õ0-³¥{/ŽÑJ'iÙ : ÓŒ‡Aøó ¸ïßƸE¶¤Ÿ+Z§d$†üŸˆý,¢˜ƒß%ض㷋–\D›ÔêôåK¨ÉèË”à!ØAüøž6“­Ÿ]Täyï«xs‚cuåù9ú/Ÿ¡¯pޏ#­ôN¤õŽÈÀ[f|·a +Gböó±]Šm;V]Øöa;ˆíl/Ãn«vãÇSø±‹º<Φ7vÀ²·#‚­dr ´E·Aè+|2»ðòþ‘;ú1Ø7bۊítìf‚ÙØ.Àv#ʎíØ^ˆí¶ë±ÕDZéÊ=B]¾¥FÛ •yBðz€ÌõÓ}d»Èûô%á,œÇã%2vžŽŒ¿íäbˆ\lQ*¶'a{:¶sυØ.#ÛUŒíì{±ïÇ~=Ñ7Q‰•ŒõÕêåByˆ§ÄÓ5d«‹Œ®¦¢ôf'Þ©ƒÐ~á.Â=Ëß$8#ý²`; ۓ±=äb¿ûeدÂ~ºñ£ ?:ñ£CÍZEŸ¶óKo·’‹Îê +êrz³™SÓLõ›9ñÍð‡q,ŠøãǬƒ`#£v£¿—ÿ÷pFØH±oÅ~:ö§b&'2ŽB".ƒ£ +Ž8¼p°Ù@w¬àÔtÒ±kµ„ªÔÓuÔ£–jéö §.¨¿‚»€3ÂHÝÃxßÂU32Ý_ Vq ¶ÇG©-*3VÇÑG&³àȃcŒeðTÁ³<µx²Œ¬´k1Qø舅ÔÃK‡yèt7§Í͉w3 Üô¦öùsW;#µ—k·#¼ñw3×p¿5&Ū1>Y 1ÕGÙT5IÁ¨i +DeË=G‹£‹´(º\¾˜jycÜòÄøåŽm+¶U5qÝrÆ È?¤êø½²'¼¬ª„ªL8®€›ª4ÜÓ^ø¶°zô¥¿íþJÖÄßKXkñ'€/S¼üIF-6Xå3¤Ék˜,!K.Ãl-HÌWMb±œ‰óåHªQu’Oö¤zU&¯Ðüä.UûUfR©q¯JL/«ØtBE¦Àp |©'áú6¼½\³pÅ-õÀÏõïãÿ^~w[¢å6ä2™UcJ‘Ó”®jÓTÙM3TeÊÕ|S¡*Ìå*7W«ÌìU©¹VÅ㖫hÜjͳô©À²Uù–½šk}Es¬o*Ïú!¸îð=¤pmÌ`­cmázk°ï.|q⛃¼ØSbUeMR¥Å¢ +‹Må–I*µNS‰5[ÅÖ¹*²«ÐZ©‚—òSš;¾IyãW)7urR¿£Ù©O+Ûö’fÙÞÐLÛ9pÜá{HCð÷ÁÙÁ +ØÌúU |ÀÅwä“*ñ¥_ÊñµÔ– ’T“ŠRST˜:A©“575Ksl¹Ê³*×V®DÐì´Eʞ°T³ÒÛ5#}­²2˜.»5-cD™Ç55ã,øß! ¿Îö°4`õò$“|ÿÓeÔä}Çño…Jx  b I€ðä5AI*‘ˆˆà;–ùœ¢ÎVÛYKífµn¾”Vúb»›UQ«óÚy­UÛÎÎÛº›uÕ¶»]ﶹ—ž]·›×énÝÖ9ö d½÷½'yÂóûþ^ÿÏïÛÀýz|©Á—*|­ÌW…%Ye–ty-Y*±ä©ÈR O®GîÜr¹òjU˜×(§µEk‡ +&-V¾­_vÛÙl»4É~PVû÷•g¿~«<ÛmYm£ÚÇj8! :œh0 LõÜ«æ·Jü)çÿJA±Í Í(·Í¤B[Ž6p©ÀîU¾½JöüÙò§kRA»¬Ž…Ês¬R®ã~Yœ;•ã|Vfç)e;ßוí¸%³ã?ÚÇ +øzXûÚ]ô ›p €îUò[(Áp9&ÊéHQ#]vG¶lN«¬N(V^¡O¹ˆS‹kšr\m2»{”í^¡,Ï&ezvÈäyFž“à¢Ò=¿V†û¯2¹ïhö‹•oh*¢ÿ¸ÖÉøSJøÝœ|ÎwÇÉæI’ÕcTn‘I–"‹rŠòe.r+»¸\YŵÊ, ÊTÒªŒ’ùÊðö)Ý»QiÞoÊè'”ê}üܔ±ä ­ÅöRøæSp’ Àµø@)>”ß¬È8Ki‚Ì¥©Ê*ËPf™Y¦²IÊ(/Tz¹T) ±j¬hQjE'èUŠo@ɾA%ù†”è;ªÄŠs2T\åú©’*>W?öa;‚íæR©ԃÉ|ǤJ€ pϊ|³THÙ¾x™&')½Ê¨´ªLiØÔªP¤”*Ÿ’«ýJªnRbuD†êŚX³Fw×lU|õ^ÅU¿¨ Õ¯+|þDñU·µûݬ¼mØo  ø¸W +<ÀÉw›íƒLÈF¾™jâ”V—¨ª’üJô›eð۔àwi¢¿LñþÅùƒš@ÀØ£+¢,€Xð#ü,ç~o?Ûcý-õb¿“Øfªä6WBQ9(.îåÝW -üõRZ N)S 24¦êî`ºâ¢‡Xƒ$HÓ)ZBh«B6„€ ¡)B›Ú&ȖD$4¾>·´Ž±…ÁTP *1Q +<|.¨¡HF3ńٴF4P(N†iÅOç;J˜N3‡X3ÃÛ.kᡖ&€˜lAĵ )š³0‚(Ìö4ýà–æÃ1‹ø¦¨æ{ ½å$f[ƒ”3þüÓàK†–»7“E£•ü,^®m¼øf“‹v²Ã)¬‡#Ô#²€ÏˆÈvël¶µÙ/ñ dÛïxþ–:ˆ¯4‚z0^o€³¤Q&R1´&·J ȵ „¦¹è¨N–yÑ=/Ùù¼äº­ã‡MÔƒÁœîéä>‚²›žèÞËÿ!»góØæç}¦6blSà¬å|ös>iÌm†¦d„7yp.Ü]€6Ó­E,`‹ñc 5YŠ½Ñ„šôQ“>¾‚ö9€fêq/¢r9br9Ûc/[ü²yî¦fgÎ0™Ï%Äì æÜ.mÃùmÔã¡ýÒÖã,°ùÿëšo€:ûH—»Cš„»YÄk„7±f-Åÿ×æØÒýPl,ƒ`Ø'í&'ß¡O÷Q—!ztˆ~ˆÁ"È'(â~ØÇ¿—sbÏ«üï5’ï*ò]ÜMsvü¤,!Ê{_Œ3Ê÷hlù<&Bh-ÖTlDŽÉ0 ň2é»ää=r?FèÑâì(¹8 +Á‘­Òa:tüPu¸V·ƒŸrŸ4ò›°%Æû-°ì‹ñ|Éé4.ÎF©&‘1B¤Jg蓳øqº\à偃èE?OÏAr–3óì!pF•p»áÎãvúRâ#<¿+Æ;ã<ãa¬u:ƇQôx\Œ›(±.ŽA]¦6ïáÇÌìûÔä}fõ‰¿J‘ß#È+¼{‚í^ÿ‡8¬£iþ‰¾û=syS~}ŠŽ¹¡™ú=*â:ú+”ÍG É/P]Wiԟ£%.£«~Já~BÁ.éi\:¬·Ðop÷¼þ¤s0¼^/càü_€¿ƒ¿ ­>Q\f¸ +ô4æGªÖ5tÌ»jÂÒLý?~„ʹˆòy -óJòCá†ÑxЙOEµØö‚ÛðÞ㱍—öh­4¼7ÓjvP„}¶ëhÅ©ø߄ÿ3ô,jñiÔÞ0Úî)á“(Ò'´ +ÛØÞL5¶ÓÒ{ðä #uŠÌ¼M›ß`”ïpEW€íàãhë€óàT¬ÕŸW<~§`;Û¹Øv0‚Å´i%ëômüx}¹ %ùêrǘªí¢ as9ÇÆjÆj=ÇÈ7ø{L`e º¬RÒ5ã:ú%.ÇZ;ÚöÏÅÆ}÷ØQ`ÀO#6³€ÕZˆm/®¤Úu؞‚í{°ÝŒíVlE°Ý¥ø±º è«TeÇê Ÿöе/àÙi²ôŽVқ«àŽbõXŽø÷öØ1¸™\ÜG.¾®t욱k.l{±]‰íZŽÐ쇰ÆV+¶#é]LÊb¼ø +YÇä:†ã1~6➏Íktv Ø5bׄE ÈgÜØ÷ª?–áÇRüX¢ aì¶2)sèÒnþ–áM?Ó³‰ŽÙ®:e•Ž05&9¢ÏÀ(÷F©ýøñ»•ãdè}¼{¹·”\,æ¼XH. &=ôFóڍóñc~tªŽ!셱ۦvî¶á,¼n¥/fÙ:´™z43UaêïKý‹ï£âH}$AÚÈ+oX&²fp¯‹ß:9/:¨ÉjQ6ö­LC8Já¨dRÿËr¹À¶u–aøÄ‰c;ǗÄNì8NìÄvlDZs¿:MÛ$m×´ ½ÐKÖ­ô¶¶bíºBJ©ÖA·VëS·¡©ÝVº1D¥ëm0Æ؀A h*hš6&.ZQÉÐPG‚'e=:Ççüç¿ÿþ½íèô 3HÃ¬Þ1VÎ*fížì —¦ÔÏ îc%õ±šûX½z>†ÿéA4§lsGÿX 㰔gKH —˜´¨°;µ;Ѩ$þ:uè4¢“ 2èt ÓÇo>õ.&¢ zg=;ì6Þì%ʯÒcÂ³ìx/ÁUø|ªû8fw—“´Ÿcn–ÀÿËïç•iž¥L¹"‡Ì.õ™|ê5Õ¨Ç\¯nsL]æ”:ÍYuv«½0§¶¢µ-W¦x­ZŠ·(mÙ£fËA¥,ǔ´œVÂr ¦áÜдv¢¹ÁMß{æRÓaâÿG^ï{걫ÇjSW©¡ŽÚKªÔVZ«liD™Ò¸ZJÓJ[;ÔlíWʺPɲ1%ÊÖ(nÛ¬˜m¢¶ƒj´Sƒý´"öË +Û§áÜÐ:ÛÐ\G8N +6 +CÜ÷C7Ç]'±´c«aV«£DY»]-v§ÒöJ¥ì~%íuJØ£j²§w´)æèUÔ±@ Ž1EÊ×(llV±G!ã~Տ*h<§ãG +W¹^‡kú›Ð[í›KÍBzøßNUyŽÉç9-¯ç²¼îßÃuùÜ7µ ;Ð\MZLÊ3 ÿ¹v@–giÞ%‰§‰r1OÝ5¸m +» Õ»+rW«Ö]§ 'ªO³òWäT]¹HU•+äóÞ©Jï.UøØq}Èíû¶\¾Kry§áïr{oj'“荓Ž@.Èpmƒ4ñ$x#–FÊEˆ¥Þ[¨×ª ×¡€×¥j¯WU¾ Dä«JÊ[Õ¦Êê~UTÈ㟐ۿA®Àçå |EFàpJ偋r®ÈáÿPåþOtkÑ#ÝZý!ú€kRÄç]„‰'Dفü~‹ªvy†*ªøå©©—»&.W0#g°GÎڅ2j—«<4)Gh§ì¡/Ãò…žRYè¼–­öcm¦þÕè݆]‚hƒ44O#ïÂ"ž¨âYe¨PžP™\u9ëÜrÖWɨ¯Uy}£á4tÊž'[d©Ê"kdlUidJ%‘#²DNÀ *Žü\Åád ¤Ô¿½EسAè‚,$!†=ˆð®‚P •ˀ91B†4B¶6LÖºð"üog4ŠÆt@ mM@÷µm̆Ôݍ>º¶œTÂ𚱮âÔib‹8d‰ã6âcL–ͼlìl&ôō˜àãqÆc|-0'–3/—§<~wé4\×|tz¡ÓèF¹Öaɪ{Y´× 6t-#’‰ªHb¨Æá3ı‚8VÇjâXCëˆc’1™dÑOÒ“T¾ž +Ö3ë¶oíc”e}~–Œzõ‡ÊÑÎ.hE7Á5LØÚ\=5Ð-C·h,¯I5$sÔëo%{sIߌËF¯Mı…8¶17v0&;XÔÛØíTºàï¢ð¶½ÒVæÄæåfÖç¦ÔßÏô¤H3׆Aæ!sÜÈà+º…+óš³z ))"ßö[‰/:@ënúdw±t/óô ıƒv?›û~ޗèÜ}ìS¬) +ñk”yRÚ{žòÓ꣯³ŒsŒ"!Úì¥ÍíµRÜt{^sk^ën¸h +ƂzóÉ8K!LŽt?Iñ!ÒÃÄq”8fe‘ep¢ò#Tx÷p˜lþöªC¯©ƒþN.a0ÆU´ÙX‡þRÁÖ|ûîÉëíÏë¼e€ø>oHº–Ô]Ø)aþ0K$æÇ›“¬—S¬•gX'Ï0ٟ¦“Ÿ¢qßÚ%=y„2¬ãçÕ²œ1@ۏ¶k#ãÏVR°+¯{ ¯ù@^ëëy3òxޔͺT'áé¼Y{.o¿?$Ž ôÇ%ýKŒÉE&Üúâ<{ŋÌÍsì™gŸWí Ú´mlé¦}y³õ`¾}ò{ސ͚¢çó:Lmý`VKs†‘%OÊ,ý~¿€·ˆcš½cšú·l:Wè‹ß ú{ś4썓d÷ºÅ§pþƒ·úOó/yÉþCú/s ü/dì"oGñGçÛ,’ßá~®à§~ͤy“IúKÚëL–WéÀW°ã^/ë¡}_%Ô¿é,jgàœ€'à¿èހ üUf½§yw?ó6sZ)ý +—ð:â§Äñ2q¼„¹„Óº€{‘Esx–ÉûqœÁ­~—Éó&̳ÿg¹ÌcÛ¼Ë8þõmÇ~í×v|Åñ;Ž׉8i§¹ê´Mš£é‘¶ëµµ¬´)ëF‡=¦±C¨¨Ý Ó$@ •c“ÇL †´ILHC‰Cô©ˆCêÚÁ„Ð$PøäPõéë÷}ó~Ÿç÷{žßï÷<$ÈËé%<ù¦þÈt~´nû+ký|>Äî¸ ¿Ýœ¾7å¡3 0†(_fôѯ¢=„öÚM´gP^ <ûÐ?ˆþQRã$úgH“GH—‹X†ô¹¡xú< rõ/0Òç°{ >OÃß°y ކ×áûë!·ã»Ý$ð=‡~7óVÃÿ!Rd ÝíŒcºsŒe Ýe:Ê#hŸ$…Ïêª>‰+xñyÒëKÌÊ+Dègtž·á°Š—«ÌØ*s½‘B?ØLm* ô×Òу®_×éu¯ÑÛ]Sµ2º5t·âÿ¨ž¤›ü,Ýßôv“#WȑËøq?>­2ãSü{Rý#Œâaø¼ÞÕCdÚCØþ¬À/6Óük›Ëà*< 3—™‹‹ô˜ÉϋJ³\;Ñ-£[Cw‘6Н@wÍY4Ù:0 G‰ÈÇtš7òå)T 2÷ÅdÔ ýV×9ßÝûµÍ-hm[¸°¹=c¬0g‰ÉÅ!´ËX¨¢=ÀˆGÐG¿‰æ š‹x°Ìl'[Ïp¼<ÊÝSxö<üÙó:Gϟá#~¯®Ã)Ê|¯{Ã6Û¾o 'äàhò¢€VtaEÐ.“‰UôÐF ½&™1KT–ðä0{Šl9O¤.óô:¾H½¿æøÿ€ëê:7°ÅŽ¥µ­ñãëv9Vá ì—]7Šº&DÐnƒ,úÍãÇnõ¢_G½q´§É9þߏGÇ5Å,NÁ 2iœxŒù1öŠ1vœ1v¥q|X‹ÿc3g9òŽ³¥-s]‚yŽãÝlû³äÅ.µ íG;Qô“ègYl”±QÅÆz t'ÉÖ]üÚC”îóYIÈâ§È ø«oÃp þͳU=½óspôôQÞÀÌZyÖ²QªM:,š°¸Ð÷¢ï×6rc”e­4ԁ6Êب¡7ˆî6f¥©~f©HՈj•xô²2{ÈúŠ¾?†ßÀ]ø¯>ƒ­3Ø=ÂѲ³Ð„qŽ¼QžàϰǦ!‡[[­†-&vÂ؉c'…vŠØ©`§;ÃüšÔf°L$»‰G‰S´\V—åY<þ:üށ¿Ãô(¶Naó ÇÊí¦|íayÛjiÏȓ*ʝªÊ•‘3ݔ=½$[愬™‡eÉpf(HӝiúÍÔàŽcc{S”àÃPƒ2(ÿ:xž†$¾Ä!š´(œ´*Øn—?í’/ãUKÖ/w6$gGLŽŽ”읲æ*²äè)r“ „F%Oƒ’§9Ès*ä© r¯…gÇïá}-ck†¶lÍÑë@%·!“ƒ4ï’øçÚ +AÞhߌ‚M-]N9K-²u³Éma©°À*$MG+],ljèjùž@ÓÔÃiÜCeP¡–®P où)àCù®Нê$PƒnèÄNÏS€÷!ž6Jô@e«œ‡¬½4U6ó]?MÅS'hu>ªÓ[Õéwë4quš˜:Õ@z¾ŸJ¥Ÿ†¤Ê±†µ{š-´hAz Äï<Ï2ØLrr®YÆ~û´°ÎšEÖ~ÖÚAœ!–aüh„66˜“×@¬A<ã0ǀfq„&mø&А ýŽឦ ]ú` ta/Çç)®qîà ÇÄ®Q“óa×E{HY´a“¥Na·V䡇6 ¿ÿ3]®ÁQÕg6{ËîžÝì9»›½d7›l²’˜²„[ˆ Pb F +*Ãe(P*ˆS­S +J‘Ò/PÊ¥j-2È Ê´:ÓÚ±jõ 3öú¥H«m-Óéø¡Ûßɞét˜‡äœÍ¾Ïûoÿ÷¡ýµ’el?VáÇ~¬å‚YÇpYKb×r 5ã c̉ջø»c,NÔÑÕÏY{àÄÏ&ΜâÌ&¡38¯Ïæ]ìp~ÙᣴX¢±á,¿kÀ:gÞHL6³˜}?¶Ñ¯Ò'ÒÔÛ ðv ?€±m÷I[ÉÇýÌË-¨š¯¿¥~x;g’rœ!Öq68¯w©sΕΒmó­QQ]·Ú˨#r–s[ ì 7»é—Çðc?}²&{Œ€ï‡€¹‡Ïî—v±ÍïdVí¸¬ÉÄ»H˜²Œ³Ø"òÏ8ñÜíœs­ÃIKiø&xÄA;Á.GÙâd¿#’#¶h¡^Ÿe~œ WN0?H“ç°ÇHæ3î(ýqe3~VípçáNÀÁEïj'®[œóٜ;ÀnGˆØ<¶$”¬êضH9®ªX< žWU¸Ò~ºH<^£W^ef\¢.‹ ÷euîqDæIàNÁ…Û¿Á‰ïÃï^pÐá³¹ŽýϏU‰6×Kà<`ìˆ,®D$ô+ð5ò>õñµñ>ïÉ¿JŸ¾Kbß&¿>Âf-ý | +þþ‰¶º…Îü”ÝùïìïOl¿ÝúÛûïØð¯£.> I®Q¬¿Aa½M¡¾…2zõ÷ øüó2zâ’àÖQÜ{uõºÎ¢k~Šž8Ž‚Ãà p Þ¿‚àÏà÷àºz]uq-óÛù›lð¯£$.ãÇ%ü¸Èî~Åuž¦9Gñže‡m÷~~|?žDë~—bz‚":À©÷é'¤ö—ð~BiUhŸ +^VˆXe‚û]ðš“ÚSNڟ&ãhÝq4æ8Zæj%vØ¢Ç‰Ç~†ö>ö^çôån†×.×NÝC)­¦u¾†Ž}€vÝ×!¸~D‰_Òvý·<¬ÐâmvÙ\p¸Ç²ß;Ñvâd`ÁIЈÝ"v;±;»eZu&v‡°;»#”óbl/£"VÒÎc(¼Íp<¤ 4ïz"µŽŒ­%³kЙcp¯_/;muÐi÷Gœ–Ü:ўµØŠ ¤@»ENØA´{°;»Ó±;ˆÝaªrX„íeŒÒQþ­Ã›­‘¹‹ì¬ “ËÉörݲW¡ª+b› ¶Õñf¼Î8›Sü a¯Ä@䩾"¶;°=Û}ØÀællÃ>B•~ ¥¹‚*YÅo›ðêa®šýTÎ1²v®ú|*8äŒ=¦çÄØ·¯{LÚcz™\ØócÏQlç‰z+¶Û±Ýí>l`o6 ;¨’¥š‡§s±:Ìé>GÅÜNU QuCtôº~»œ1lóEÕëо¦ìkÙ¾² Tc× Á~û­ØoÇ~öû°;@Vñd»ˆjY®dg:Yà¤ÓÈG™®-Óåe:²¬ÿ€ÊÄ5c_ £Œ÷;¹~‚σaWuM™C,‰Ålr2›Ú˜…³T2ØÏc¿ûíØïÆ^Ÿúy;u£õÅ)TE “ÉG7Y»èþ.ýü›wm…kŒUh9WÿÂÚêJ4fò<ÀûiøS&ýÔçTr2•Ú˜JöáG¯àh‚£ŽvìMÆnY·ám'±è ¢ídvQn£ÒKt\‰iUdò™~E&q 6qݏr½-e¤/`53ø½ z¹nzð§ÛW£n·ûAì‡AŽI8²p4ÁQÄ^'ÿ÷âÑtµ¡UR ÍTxý‘'óy&@#5ÑÈThÔG<¦õðßïBVÒa֟Y  ¦ðÜ:ølþ´<*ùjUò„TtGÔꊂ¸ +®”š]9x +ðLÂf·]eå\s”u¨Áu§2®U`‹Ò®tøðyãƒò$î;±B5‰ur%X|Ü –±øE€ÎŠ}¤¥ṗs&ëo/èEÐÌ»,HãK}Ü¥xÌ#+æ“iÕªDbñ ‚‰°jë£òÕÇä­O˓Ì˝lSMªG®;lq’fú¦¹Ò܆i–ßÔ €I|HÞÔbx†SÈGdQh- Ï»|Iñy"Q£XÂ+3îSD~õµ +&ƒò§ y2Õ4Xr5ðÇ 9œg—Ï¢)²ˆ¥K{¡caÍq+æX³ÜÔY–φ«$ú/ú"\C¬Þedj(fžsø‘I>'ݲê=Š&=Š#íU0ã—?;ÇðÈÓ¼MvÅ«_nFã5#\›O&~¨ÀmXàflÞؒšð! |¬|e6’¬÷;A+hâ9‹/)>«O»&ˆd\2²5 +æÜòç½r73D ÓV£:HJW §ÛØãÛÐxmˆÇ¶A€ÖlcŸoC•¸%Kˆ"›K+>´|¢¹pNç+=`hi¤y׀)üˆóÓޅÿË~™F5}faüX5 àZÜëZ«"ˆ +nUƱ®3hÝ:£ÕŠ­Z+neœ¶J;š=ˆ²HYB6BIH€@€°„PÙ !Ѻ/ÓÅNíT;Õ¶ÏK2çÌx:Ûɇù0pÎ=!üïóüÞû¾ï½ø?}fÀé^”÷LÌR³pÐφŽ¹`@Vr¸¡€ñ…@¬GæÝ ôòAÞw"0<¢ŸŸ‡A!ÃÇ\¬ÅœÔª©X<71 1 ï'#×hñGŒÂïÃñw_à¥ã±C0" š 5m ṫŽ`ø Á",BÁ",Bñ P¬Gèb†ÈP ­!ÜBpS/ ¶³æt²Á¨3ðϞ‹˜‰ß§"×$䋍÷Øî”/°Ò0ªá¦¼` %¾„Á¥»:–BÇrèXa`F6;X„Ap؆ٕæVb€\½ñr>i:ù¥_PKðüùˆÙøø ä›-ãñ:ïGÀ¯/òҐ÷9’c+.q|Äh"ð|èX… ~5.û5¨uбßFlª 0²a|x=†ÊuèÖÃç04¾‚.zõE4)÷¨àš‡x ù¦CË$¼úãýHl-¹ y½×±;'åjn€ i´\ W8tl-бk²Û°ØŽ‡nAà ÛpNlEMla¢Yã²6â{ר`ä +€ÔYð;¯ãày8ûÂï0ä´Ï_õw97º= Ec‰g»@Ҁî“=Ð Ñбõ¹¿QøR$Ή ´{P»1¨îj§æÃëÜù`€× ðBà΃í…Vݕ‹ ‰Y”k`Ոö¢°õ(,7U +UØ+Ø'F|`—€… + ^›EMBîÑðÍ@n/âù›+iúQ¾ýÃ'B/ p¼aT‚/DŽ;—¡C!ÈàXŽ¨BÔ"È0‹cˆr¢>ºQ8ô8/l0݊ûÃMÄÐ?þxy~nÈ0áë7|ä¨Ñcüǎ›0qÒä)S§MŸùâ¬ÙsæÍ^¸(dñ’¥Ë^^±2lÕ/W¯Y»nýÆ_ýzÓæW·lÛ¾ãµßîܵ{Ïï"¢ÞˆÞûÖ¾ýo|çÐá#G½ûû?¼÷þ§â>üãé3L6‡Ëğ=w>1)åBêÇé™Y"±D–-ÏÉUæ©5ùڂ¢âCi¹±¢²ÚTSûÉź†Æ¦f‹µµÝfïpvv]êé½|åê§×nܼuçî½ûŸ}þŗ_ýùëoþòí£ïþúý“~üOüÿŸû÷D%–}ày1ý<\'¶_ ¾gÀøKÄù"0X„8d$ D„‰”0QŠŠPÑ‹žp)#`ª@ÆLÐÔ6-€ÓFè8žnðé#€®ƒÐm‚èO„Ñ@zH(=&˜žþðc̾Ødݽã¬ôz¶~æýßxý °Fì‹ìßû—ÀžáEyy äí= † %€áãã ÃGŒ £Ç‡ÿXé'$`( ,„K?W-=C¦ ¸„o"[ ;éõ=QÑoî;p0æȱØïŸúð4“Ï?—˜œš–!Idr¶ Ù-úbXìwøŒAWMô1 —° Ÿ0 +§°zûÌÞ»»Ÿ}Ã_>xðŠä뇿ïo=züø;xÿþɓ§Oðßk¡M¼×ê·ü¾uDT_“_²¥ba~CٖsñªJÝÉ:CÏR¬àÚ ³¹Z ¯G#â÷©³â¯æe&\Wfœ¿©HK¾ãi hÐ0 a@À† 4ü·Ñ wÛ|—Ýk…†fßdKe°¦¡üUhØ_ݯAųès¹ö94H¡AÌïSe ®*…g¯) A–žxËӀ† · án›_To‹O²¥*HSoÜTb.ÙW]¡û Þ âZŠ A ùР†%4(„ñײ3nˆ¡ÃÓ膆ëí>Ën·ûEõ´ø$YLó !Ü`*Ù_mԝ¬/Qs­…Р… 4ä‰y—"þy–àSIfüuaƹžÑÐgc,»ióê¶0’,5šºŠpCuñ~S9Ñ riȇ•”۝+á]–‹xW¤Yü«"¡àZ:êÂÓ¸d¥Mèµ3–^µûDv æ9ùŸ7•V0•éN6CC4¨åœN¥ŒÛ#áöÊÄÜ>1tdBG*êÂÓè²ÒÆ÷@C¯Ã'Òie$5›çhÍÆÍ¥Åo×t§ôРÍåØUrŽS!ã\ʖrz$N¯:Ò #{ÄÓ脆îƒn#¢ÃÊHi¬ Кʷ”õkJ´§ +¡A“˱)sØNy6»K"cwgIÙ=éÐq:E‚+ž†³•6¾ ºœŒ›…žZg +ÔU•o-/Ó4CƒTРÈa;¤rV§(›Õ•©Ð‘„u9'æ_ö4­ôqÆb§“Ùf¡¥Õš‚ *ʶ—ô‡Ì…Ú¸Æ|5Ç¢T²Û³,»8‡åȄŽ¡#Eƾt^Ê鎗ò{<Ž6úX‡“jwУ-VZ†©zQQYÙkF}QL­V× ††œöϋÄIšÀh4ÐX¢ñ$›&’}4Éô¸9ß»µÄöwí?ÿ÷Èc‡Wƒ{YEË«¶¬ñ}£?‰éºãQ – +˱lpËûð’WDLÒ|rÊÍáV\„`Ɖ‰çÈмVÖêmÓ°iØ4l6 ÿ†m†Î{†Pdžºg0|ǐûÖ0þ­aÚÍåV]ց‰ç¡F!ʺ[KnÛ¹–lï¼{ž`¬¿¥²¦?Ã)`èŠo”èh@†½l‚îǧÜ"¢êäsf\Þ¼-R¸tɌ)êíN²¹m-¹³ónü‘ëá=Àð +•5¿çeŒ'#1=0h±tH…ŽùhÉ#EËîA¬âìÇg"²F ¸‹V®hÅ•­èIÅb½mî0;;×6 ‘ŸÃËö¬ùÀð7`ø2>¬ÇÒA :æS¢ã´vI±‡¯QÄ¢UÌ]1‹„W Bé% O±Xo·™æ¶ÛL[çÄn`ø «`ËQ/c×ñˆÍµhÞ«F'ÜJ´â”cs”_´‘+æ!Þ£DtU3(½¤˗êí³µívjÃððáÕáÇYyÛ`xN+1™€-xµè¤[VJ¬fûÌ ¶ªAÆ»¢âÿC)º,•È—êífjkÛ­Tkçíä®Ã«Ñ³òÔKŽ¬õ/cþk$f¼˜ LÀˆÖGùz›(6lœjÜ;^i<”)7²m©}UðÜÿÉ°Ìw>&õtÇ%4”»a†ï‚Sœ&œHs¢ĉe!–e;ˆl¯ƒÌÕ[±Ô°¥0ݸ/Wi<ê™kêQ•ž– %ߤCüç£ý¾®X¿Ž o¾Ñü¶üÆ®O„W÷}Ž/€áê>{âcI_ᜲkôsíÅ,Ëp!Ýmú,Õg9Ï@ÖOØv.‰Rg“u6AØÏ$Ⱥ[µ5¯‡éX÷=õښëWǖͯðsòé´ül€‘w‡rl$&ÅÑ"’Ù—;$øù&,úaqÉÇœðöJ'½=ʲ§[_vwî»MæaÓ°iøß7ìîX÷?ùښû¹c˖—9Å_è´â 0t…ãJddD†'‡%x:,&rA>'ïçðŠ>\0îEE“h`Šî“NÓ½ªŠ³GW±÷è§î·õpkózøáŽõÀ^`xöø’å€ §üà¿+WÁ±¨c"R,ÀÇB¢èãq&<$¯LcÂi7Ò_uAÒ[=këÓVÍ}ºéûí;ú—Ç—¬/ Œêb$®fÇ¢*Œ ˱\P‚åýýø¸W@–i.wÚEfœ˜x΁Hçm°jÞi«HW¹ßÖ#-Íë‘]ëÁ`ø0¼(Ì©þ §Iõ…HLÓÖ`© H±¢w›¤EÄ´‹Ï™qrxsvB¼@áÒEª¬é͌Ñý‡ý:ynò¾ã8~ ^°‡¤I3„¶¦mÂÒfځ„6MmҔKÛ IJÙ q°CŒwIÖ£çy¤Gû¾ï»­åѾoÖbK¶l˖%[^ p(t™4u†U}\Ú?àÉ©ïûk¾¿ßå3·ÿöÕýûŽ¯»µ¯Xb†?<1¨{B1 )ÖÀ通ðÊ )—žu +¨e;©Ž²5+ƒ»j¦K×´4Œ’ª^S5óx{z¶µ~q_=°a8ˆÞ £ie‡/©éÅ´„xX§ýj(ïQ@Ó¨š³‹áʨ€V³ò«f÷ =[rSÉPÔ¤tuE‚hÊx{~¶õñ {¯»¶/¼ÉÍ©0ƒêª/©½Šé‡â!=”ñk¡¼[Í8åPÙ&…­ÚªYÌü âÝV $7¥yMÄRU„LMoþgn`†#˜á#4­n÷%uŸ…b†DÈ@ÉøtPÁ­f*haTI­™åȚ^ʸ¥’°þ,—Šo‰„òe>OUåqÕ xà -"ßÝ÷8¸çøºgÿƒ3h.ù’†ÎPÌԗ™€ŒÏMºôЬ] U,*¸¦WPWÕ2ÚM©”~K(ãÝÈd+\‘²Ê¨+x{ÙòÄڍ^o_=ŒN£iÝoÒØŠYz!ËpÆg†'Ø¦³b£ +ZÒ(¡e™^Êik{£¬°dÊE–DUÁۆáaä…}B»Ž­{_k_¶ý”—ÓœB3†sޔåJ(6úy +¿à%‹¦<$iÑCPM»‡ôÓöAcqdÐ<‰§ºk[cݍœûÔGÞÄ ¿ê«ÈÛ¤Yѧ®´¤Û—’‚ 9J©‰°6ä"Y?“1ᣱ&=·è„3.’tÖET•ì]ÉJ0L ¦)<Õ݆˜áuÌp¤í®á—} ñ'®´ôº/% Æ”hT'Ãbj&À§ûØHÁCgÝ0g¥æœdé¼sX]¶’´sF’aFG2Má©îÞÚP÷`3Œn»c8Þ¿ ?)ËJ®¸Òò._JÑŒ«È±ˆN…¤pÖ/¤æ½\ڔ›IŸAi¬9Ä_°S¤Õ²ªb$kçµdýŒŠlœÂSݳax3¼öÄ`<Ö_Vœ”夗]iÅ5_JÕûovç+¸éÀãøµ 5R!¬äڃBÒ¦nñu\¹#ô.Ò@33lpŒ1–%Y²þKÛÖ´¬½÷´öÖ_Ë[¶lË6˜$„Ù4é¥ Žö_1®}Eo}ÈÃ÷å÷ð»O(®ìˆE”"9_72èáÓò®NƘƒÉž°Ñx%+,™ÑCò’Tå ¶ õ#•„yž{hXûÈ`{ë‰a¿4'ùĝ–7øPeK(®"ÇÂ*$Ã}ÞxØ-B +N½hã°J&.¹ªFä%9¢*J`mA ëG*é‘ÁûâZÌýó‡Ü]ýŽÇi­;­8ëEUÍ¡˜škàt@ ÷{dðˆKŒŒÙ…´) 9kìä~¦a÷Ìəò醪(¢k Bš~¤’þgx¥l؂»kØN(Ê?åd'Üiåi/ªi +Å´„xX ¦ýjx W:epÑÚC›1u3¯éD¼r~Ϝ¸K6-ä('ø,ÍeS—¯$̻챡·l°o~lPì•åäÇÜu՝ÅôøxXOÍøuð`¯.8”ð¤YN›ÕJ×dbö=ñ5P:Ãã)'»º4c]¾’|kˆ—ŒÛEåû²œâˆ+£ý؋êƒ1SKµ³"mnfˆâ¥:üp€~0HõA¡\^‘0ÙK “¼ôÑÌ<¬h%§«ž™\°|l|á†èç‹Þ5ýõ¹Zñõ—س52¾»ÊCõRj³²=wIM̶iñ¢¾5M6´¤(Ƌ(ÕԌæ IÈҔ„-Ÿ&hÖÆ8ÃVIùlÕ÷G‡,M”üÂú%;%÷_<Äùúµ3ÐÍmɟï!‘®ÛJ§è-Å΅±&nc¡…~/lÈEõ#íâ³Ãñ™ajÏé!Prj–Ö ÒdŸ 0+j oþ÷ÐËUËì7¼*ÖoíÂ6îï×¢|»ó$á«?6´Ü:ÒÜx½_ÿÙÒé¹ó”º«ÍÀÉÙK`íL|bš„Ÿ¦Ð>*QéÇJ ýØÌ82Eg™`±*)=Põ×ô3Ë؏6r±µ[hØ/·w`¿}ð¯ßïoùç¾£ç¾=\[÷ÍñÓuªá£»çÞnj:|«¥ùÐͶ‹oZp7ȗ|ImýðKÿáu¿ÿ:£mßlB%aæ5ó0ó†˜as5¦Þ±ë¾ìµwDGI³¼^ž{I—åvxÒ\š/ÕÅ$ٝ¡‰Ãüh ÆcâD”,IFIòd„¨B#mZ4‚7¦"­¶T Õ>mß¾3üÿV?1¼YiÞ¯½-:Bšá×óóÜ}†Kñ¤yˆ/Åe’N(ÁèŠÄ^, +ãюîd„,A#$9Z6¤ÂmÚtoJ‡Zmio«=õ´a–²Áò³˜qS5¦Ý¾ëž|OííîÃíӂS‚aþc†Oò¤0ƒÉ.v8ÎêŒÆhÜxâ'#TQ*LéI‡H²Lˆ¨Ê†Út٠ޜõâ­Yޖ~Ú0˪²aý +Ìôаm×=ÅćÈÓ“Â!A£)# xÒBª1B 3ã°ãQFg2óR!@˜ RÄÙ`», ªú}¿oîw¶YrÖ6[æiì+çaÖuÏc¦7ª1ÝÖ'†ƒ”R÷ áðœ9#lõ¤D²›úãõÕä}Çq¼N¤Ýܱó‚­ëqZÛӝNÅU»zœuu«k«@ÕzW¼¡ÈEAAP ÷äIž\ÈBx $„ÜóäFî$@Bȅ„„pAEV×Ôº9;¢mý-ʶ¿óÇûÿ×ùœï?ß««»Žíõ°¹½ôú€‹*9ÉMý‚8bÇÉ¢v¬:jÂh"(VVãÐ@ªýß ÝøõTòeÁ´ði¢ù4EJtäªÕßLpø„°»avwñk}n§ÏÅ䅜4~¿ÜµÄ1+¾=nÆ*ã(NUã´ý +<Lµ—ý;såö¬YINÁ´èiBx‰6£æ +«_ˆsøZ¨îîfFGÀìíäÕœµÜ°®Z)HÜB':ò!¯TãUr‚¦_JDƒ©ôoÎt$ ŸÌÄH¢\$Ò\ˆ„åV¿¨ÆéQÜÝ"Faø]|VÈÁaG­ ^¼j2“Ä#(Q6¢"*r¢*&!i"­$]0Õæ kæ ª¤Aš]0ݺ4!>‚DZòрè¢Õ/®rz[Iž®Vº×-¤÷9Œ~ë`q‡L4Á5Ôz]E–Ž¶“åCmdULDÑD„](ՀþÀðÂðû¤áOICVátÛ^ÒDÛA$"ÊCâ V[¥Ó+Á{º$°¯SL:šèQ Ÿ1hâ°GõŒ† 5M|CF•^k¥Ê‡Z¨Êx3UA¨ºPªÃi/ è ²¬Âén҄di=‰ۊ¬~i¹Ó+ÃzºdÏ%C6ë@èÃ>k\ËáOÉX¢["†d¬™Þ>ŒÐ•q]i ëB©6gx;iØ°¨·% » +gd9Ä Ù$*ÉMM¾Å//uxU‚Üë”Ãa«Ž›Äôkºfæ¤á×R×2Ùȕ\o`·Ô×*ëXê(© §0,OƤAÿÂðqÖÙÎÂù.â„<§1*;¬ ÊO[úTů¦ÂãÑà{j8lQƒ¨ ¾.3&…Bö×aËí:AÛ8—/áð W=ÀæhûS ÿgÈÜ4ICû΢優/Š}ڐ:·£=k÷JÝ]Æ*¯…ú *8¡l§]Khü¤ƒ-nHÖ6Îj–Ž²å &_cÖiúS 3Ҁiõr`xaؚõDþyÑ]õüMݧ 1M¶&¬ßo +Zr-½Žs.‡éj¯)ùkjT´A©AdÐGOÐÛ¸7`©p–HGáùܤŒÃM$Հé¥!ÖoÚ?fÍ*wÞÓmÇÝ2~\?hü‹2bÛ©z¾2»ln“©Ê¯Kî ×@1‘’’à'¬äTYíYÖ0F‘‹G)2ù¥U‡„êhªÓ²4`^•Œë2nKÖ¬f{Á}ãVÌmû&îpç‡ÒÞ-Zwç›ÉZÜ¥5UûUz(Ô¦…¢MjJŒ§‚ m’3GˆrÞA ”’A¡Œ%êhªóÒ4Ðñ› `Z› ÐÍÙÏЭùlVÝéyŸ1>°º©»g›Áä<âÔX.t+L5½2hA)á-áh ºš§¨ƒD{¯âbÕÂ8V#‹aUêhªŽ%iÀ²2˜ßÏú²4ÿ!ï_]¿+ÿ.¶Šx»Åìùk‡ÚqÂÕn¹Ø-1c|­Fȏ ` +…juÔ~X G(ZF”¨­ÀixX­ Z£Eªuò”–ÅiÀúÖ2`y/7eÿäZ{ü~dUÑðÔb‚kà·"UW¶YâÈs‰­e]-Ø¡ò5˜ ?×H 0 ´ M‡((#DDYa<Ê cÑú0EÂÕúÖPªÛ¯æûŠeÀöîz`]·óQ`Õþ±É%y¾©¥$4–)lóîÖ ùÄVîn´b»”ž:3ÕÇ6Óz&ØO3Òý#£ddõ ìÎÀ ` cs_ªÇ¢ùÀ¹|)p¬^ÿ´g՟oM,ÞÑwÉ9óԛ$Ib“ îiç{ÏèëÜe–:'Æɳ“Ý+µ‹e¡õÐ;`/­ƒá…ÌLÙÌòÍlÞÌíŚë{1f/Õw.œÿ“{ɒçî·Ö}›x}cøî뻬2 +dwÖàÇ6³¹ñÝMµáÓf_©’é«ÒÂ=8=ÔM4‘Û~ |ùy؟“Ž~uâùéƒGð¦? ß÷ÏÓ·mÿýHÓëè¾ozŽíýº÷øÞ¯'ö|%:ùÁWÒS»Ÿ¨Úë 8þ#à^½87Ѐí÷ñ`óSÍÉӏTç”]·=Ær‘{L&‡Êu”ë…~C*ßgNç{­i‚ë%8® Áòdp¦?ƒ3 §£ø¥x¥×׆ Ï\”aheøeh¤ šŸjOœy¤é`~¦î”ÜR²M×OU!ƒKrUœ”h“¡>•˜ÒD¯u”àÚ38ljâ,J0œÆpzÃè—ÑTÍ~¹¸Þ¡{ã&`jm™Óë˜Õµ³îkÎ˦Õt˸Šï«("¤R™(HÕɼX—&ÆQœoAq®ËqœÙ˓Í2¹,Îaôh6EeãŒËX=7eð¼NÞ¦ ;63e0´uÌêO°îëÎɧ4]¶«jn ¬ÅHµ"Q«RĀvÐߌ帶l–ãÌa,/Ž1 £Gð#‚ÇÑŒaõ†žܔÁñ>ehi3~Ø1k<ʞ1tȧ´±iØPQÓ'5²D^©LRMé±lŸ)‡ñl8Æq(˛G¡|šä㠄ˆ0#x˜ËÖeX¼+)Ãz¤ –æÖ9ó¡ŽYs{ÆxJ1©?o¯é¡¢–'u’d^­Hã2šk³˜Àˆ£Ãq2,9ʄ‹qæ0‰0‘|˜Áìh®ž€ç™aheØ>o°옵fϘ+&;júîpQNjôâ$¡•â +%–Ðàh¿>ŸéµiŽ³”fÊqf¨Œ°àbˆ5\ð³ÂÉæêéߊyƒsÛ&`Ý`ÎÖÚ1kû{ÆÚ¦˜4ŸvTá¢/û“„AšÉ©åYLª"2B™î5—“=Î+ v°:̂*;\òq`r¨!œ=Ñ\=ï ËÏÚyƒ­éÀœ£¹cÖÑʚq’OZO:ªæóᢉ/˜ù)Â,Édu²ªPÒbM9É7ÕFz\W¶ÿj¬z{Be7&¹HÞ΋æê ø(ƒÿÿ†­ À¾¯un°é̬³™ußyP>é8â¨Z?­]ñ‚µ'…[E(f”à£jY1)QUããµoh"Àõ^âjN^¨lÖ^$oæGsõ4o -ÞßҀ‹28ö´>uí9óȽyh¿lÊuØ^s´‡KöOâ3…;(jçÓzIyD. “A¾sÚÅ÷\·ó5KT1÷ÁE£É¼žž7¼×w·>uï>ýÈûã3ßé”ç€mÌu *¹Î].¸»“¸›‡¡NQ!iWcZÉDXª»ë Þ²=7ŒBÿ˜^Ut¢pQ+.hD¼ž€Ÿ2–-¾·hÀMœ;[¾õìlÿ§'ýAp—d:Ðd¹ê;,{OÅHÿ…îg¢¨¯¯p‹jˆ]<í5êÿjT:îhåCj©ÿªJ +]QIÂ%¥d¸@­•¨§ç [€»±å[ߎöA;.}ï߆w™®…[|•pRBÎ\ÎG;ÓُA¢š×-œÒÙ¤÷”û¹Þ}S¦ñKUÁªT*Kå0)“!D=eRÿoh`ˆ2xÞoþ.¸íäcxk×Ãè{ýwãÛt#;]µds¨š=cÉ?§bv> k6¯`BîÝ:·E÷M‘É{M¤ÔDZ¨"VÃE± +É×Ó¼áµg†w€oëþ‡¶œø2º¹óoÉMü{Ù Êir³e¬¸Ó‡¢Å¢#ç3P„S + ®ü}ãðfïjª×;8Áwy¯ñm±>3tE`—úuÅzAÊQ†Àðlnw›¾G6{’xç¹õœÏ«kE“7Öë³ù]ÁHúèH ~Šôäí° ¬5±_8Îóɯsü¦ëœ€g¼Ç¨q¡+®¬>~ïöŠ?Õ>].LŒm´ˆ–Ð`º=a¹ˆšcܜ>"Èˑ~R‹J½ai…VUXaS…–/Áþò%(\bxa²ž@è§ @øՅ ô«e ´nH¼Ñø„\Ùtzù±‡K?ÉÜY)†Æ¶X ƒf´#fHv§uq¦ŽõãÒ¨Fą^DJö +‹¬a]‘‰XH:â$»?y.Ôÿd€_Y«–Èë¿ËѶ<¼ñêöñ‡/Æþ±ô"|gõÀàøv³±tÈ£ÅÏÂêL÷eUŠ›”'™¸돉sü¨”àF;ªÉ3£‚µô˜ ¿õõ†ü@^~ ¯\RËÖ|Q{iíõK¶æ¾|¹ ù;­ËywÈp£Q§ª~èÏz¥D74å ý(/Æí‹÷¤… vj ÉHÊR—’ÊtwB;ڕ0Ž^LØG;“žt=Èâ@ô¥A”öÚrɊəūˆÇKÿÃ~5ŸÇ­l;ëÎζëЙŽíÎtwfeíìvu¦V@D@9…°\"¹IH"$! ¹þä" I„r‘‘TÄ£ Ò]Ô­.¨ã®€þúÇ:}^öE_|ß^<ó<ó˜~ú$¯ýñgÕÂåoX7ãXMsÙÂËS¥Rê8JIÁj‚ç'éÐC”îšÁË=Õ r€Õ[ák1^ò Œ}bc™O¹£€å7»€õ£_my~{`aaßGÃOÞ?dÞú8Võê9Гך¿;Ž£-%PÈ·rÄ¥Ü|%¿öjMkõ VŒœ"H+&ImåTyÙx£¢dœ¡,c·òT…£ +1*Sï¤öÐ]ÀñÁ¾S¡ûwB?6oí?¬¿†¶>Oo~~´ú¯˜ŠúÕÔZÜJ^]ÍrùrjùªÆÒ[µôâEóۛbÌ.¸Aå\¸ÞԒwÉͽÆáåÌ xYóbþNºëÞ²8¼ww`î—{-CÃÔàÃpŒlI¤nFœ'¼LÈǬŸ/F>Í-/û,zT‚B¬^ªÍÿ¾“÷›ûO>{¥¾.뙐ù€Vþ~1ã“”v¯…tnYHÞI×½{Bc{C¬·ö„ªßü: >g‚ÏŽPÀ‘¨:}¦$%_z–^´‘UðS~nÞË¢üìeˆÌç…Ϫ‹ÒÖÑÅçÖq%©k„Ò”IeÉ?R˒ž6^L|Ê,OxÒri' î ±ÎîÞ¥^y/ïÿŽ >9Ø}Ǿ®Ñ+ñ‘2â2AnB:@$¥‚’”dPžšô™–ø•ž°…Ɉßğ?³Ǐ۠d~u9;æ3'úç–ܝd}/Ds;d~±—>ÜO`Áá?T‚£.á@ìWYàìÑ4v,dG$‚ü¨xPt2\ŒŽ•11 ЧO|Ü @<(ñ‘ 1>0ŽnâN\x??Ý„GÃÿô€“ š)›ÍeÏUÈÇMu„•ËÔÆ¥ç6‘-Òk8‘b#SÍ¢š™•v¥íš®Ò馐†î©J³~²Ò®Ÿ¬ðèÇ*õä`w°þoø2ð`ôi(€`ƒàô!Ð8)ìÄ:«²êWÿ€Þ@¿K£óØâëD¾|ŽÐªºŠ—j§±ò®)´ª{²¶£g¥3ŒWzÇ«ÌÆqd¿q é1ú«½½>”×,À‡ ­°A„°›¸y©-ß"Ö8åÕYhÒýfóNS£à%›oà¶_%BÚ)‚X7‰oëǶ÷Ž¡;L£µº¾‘ƒye¶ŒT;-þ—Åç¨ ìßD°A  ØÀƒ ¼œÔ ¢p[ŠZåT“ï± Í·˜4èzS>KkÑL7tD‘aŒ 3â•fø„Y¯`ºlÚ^{ Æjªí·{Ðýö~8 &x@Äï ­±‡?= +²R7 +×øE¨UneÃ2Ç^dQDóL†r¦‘Ó9Iå÷Œ‘[M#D©%@P؆ñš~?Vçô£N­ÍéÁØ8 ÆÞoÂö @°A$o á@ ŒÔ (§pMˆ@­ò/6,qkً¢xŽÕ¤šf°u㍼Þ*d %v½ÂéÇk\CØn׺ÏåÅØ\ý›Ó‚µ9X»£gïh… Ò?…)lń(9 +ˆÒR7D™…k­P«PqÿŠ³ÀÅKf9Tõ$«Y?Êàö. íñcˆ(w á5îA¬Þ3€¶x‹ÛŒµº{±6—gsváíŽ`ý× ;òƒèl¤¤lHÓk’lÔª¨ a *ç,ðђY.I3Á¡÷Œ°8–aº ßO¹‰rϾÃ7€íõ91fŸköpouiñ6§¦ÎîÁÙ¶á›0 Žâ„( KJÙlK-Xo;_½*Í%/‰K8 P•ä*¿®c‚K3\iaY‡™<Ç rÚ|^|ǐk2ãLƒ=ø>_Þâí¨³ºU›SI°;‚Ä°¡ 6´mN…é™H OHÞT$¬+ÏU=Td’–Û웒rÉl+Z3! ®ð6?»Å9Ð(ôzI²!7¾3`Áz¼Ñ¯­ëPÌ^e½Õ-'ڜ2¢Ý¬·ù¶á¯a@d§#€òLҖ*1ÿ™:ùHF¼×žÓ¼(/ÍJ‘ê ÞpEH³úy,—Áp‘¥Wúëtãú:ý¨†Ð;¬¬7 ¶Í^)Éâ“m.Ù3È· '¿ò˜ Š=ûZs&ï¹6±âqg +á¾6q[“Í·—µO¶ÕèG$$‹_ÄpyØ¿"žì!hgTÄîñ6’! !›E f_+ÅâRl.ÅîÖ[ƒbÛðuÂÅ©ã@ø¦36÷….®ü}"~¥'¥ñ®>‹]WØ6£­èSãLà +ªÃ 1¦fñŒ’¢™Su<*šqˆOëóñh—fuqi6g°€ôA±m8ñ%h?ñw =™ºOe¿4Ĕ=1Åa¾·$P–­©ì[¶ÜÖk¶匭¶sH_g7)hv!oFÀVÏ·0»&9Œž6ÃègÓûØt³—Ýdu³›lÎ`½5(· _…YT8PG]‘ñÀ•ùs߉â5{4ê‘;®~eðlãòH&{a¬L0âEjmŒ­£‹<,P°¦é2Õ|£ sª‰«¥sz‡élÓ eö1š-Óê +Á?Nû¿Ù­ó·¤<€ãø´ÛèöT3ÍîÎT¶ÏTNóÔÔؔŽfšWZi[¢y噡r‰x Š((¨x¡à‰J¹š ¨¥!x$š)¦™æef5­•5M§Ÿýî>ósüûÃû÷׏oÄP‰ʝ~™Ã¨w8 Jÿ÷W1¯4G£—u'¨‹CžôÙñ0ÆàVЮ#ÕÔ«š%JFWV]ÖãRÙ-fEí`º¸¾%lèa*º2 +”œ¼& 7·Ym((C Uÿ5XšB¥ý~¸dgr[7h±õ~¯± }Ñëùhč87w*A?åËÕ‡‰ä:’Lڞ¤6³4œ^or]ÑÍÄúÚþäªú¾Ô҆¦Xѝ&jìL/RiY‚¦vCAù©…)TÙþu6‡Ae}ì£Ú +½¢³ñ{4â8=ç„Ó?p¥kï¢ùòÁéõ¨ÚbÄPÐÂVg(3»éò]¢¼BGi¸¬K”É{h•ŠnzicgªX©eˆTCýÏPý½ T!Ù¡} ·´†ÖƒN¯¯t[¶>59wèìÀ#;’vމ)¿ã‘/)+F š$ev+«•ÕÌÓ¤(󻒔’.ŠRÖ«PtSj]ÔêÆΤ +eGr©Jc(¨D 5f&P}Àj-~„&s‹wûlŸèÍ&çÌÝn.Y„hžÚÄ)æYÒQtÁ…Ð²üÒE~­£Nkb´r[iWrÔÔa;¥¥¢=¶¹VCjRic.«´ñ—Tڄj•ÆP E ²&Pó³)4üô´í6_¾±ëàÔÌ.«›K{OkVœW<>D‘Î:±Ew¼òóôa’¬>rç:­–ÙÁlHÖd(ÔÙÍqm‚–˜6Ér[uKT[ý|ks+Au¥•tÙpP.í0™ùVhúaÇëîí»f'¶™ ,í´Õ¬ìñR¼:!]:œ œseåŒûäp‡1"ö@L)ãF¢”¦K•%t³þەYݑ×@ìÉ Ú29¾ã¢Û!—‡kZÃÛÔb¨ýÎ.ïúæ£zۖ…‘¯7.nÞ­YÙá¨ø´Ç[úÊ"BôÄ>žߝ‘1íÏcŽEäÑG¢‹¨C â¸z)¹?­"êWŠïãWc{5:± £«Dª•ïUՄö¨/ +j¿DAÝ?Œ¡iÛWÏú7lZØð7íÊ·û«;œ¥°Ï[ôú†ÿÌ%š½ˆNJd&ÍDrâ'IYäñø\âhRî6£0r˜-ÄÜʺ6”WªŠCô¥’`}UI¾¾$Pß,1ÔoDAÖ/V:׍þe­öņ-ŠÕÍû¥`æ,„žÙoíƒY/ݱ)Ï|ÈÔÇ! 1ÃiÄûÄTܽشˆÙDöù™ιét^È73h’Ÿ0!àûß-Îñ/Ïñ—åúŒ]6(Ö£àê†5ú~c#턉‰üӗ¦R05Ânûl°:™¾êâCçLyí!½ Áa—1Q˜_ñäsOÉq!)” %5à#Ñ‘ä÷03Ùg!—îý 0å̃âTÏûå©èû2†¡^6£†:×¢4C_Éç¿XW ›L‹à»³ÀÜ: ìœipÂ=<ÑÄU_ßðAçޝþð[T˜ßëXŒÏ+j„÷Jr¤×K&ý‚óx‘‰?ý<—pj¹xrYåþï +’¡FÚÖ ÚuF5Œ¯1ªx»n]!üýÛL03c‚…y8Z‘áø,œvïcApÖÝBÿéá^€G£äubϜ‚É>'>±ýŽäùûsÖõCa€Ëûâ@Ci4kP z#Tù=”‘Ösaó¦Tؽ•–;‰`»ÎæÁàfáVgÀÇ ¶§ ôˆ;`ÜëxˆN®@vvø£G!ÑÅ R\!í˜pŽÛÿ„¸J®C¡Êï¢Py¿¡Œ8°ñOtغ.̾Š„½ß„€¥©?Øm?.»Nƒûî“à¹÷8øš»BÐþ£pî€Dt¼¥=~±ƒ8+[ Zú!H³±Žðÿ[Cëk#`ïX ––«0¼- -Ø Ò"<€A +|G§F¼¢1£—©<êSJ^ÊR¬0ý!Y’±@*çÝ'VeÏ.åÜÃÕçÎaù³‘Í³× +f»3áý‚éðaÁíÈÛCØÏ÷Ã6bÈ@ ÄÀF LÄÀr†Œp`E½eR°+)©1Ïhœ¤ÇÔÆ"¥0ãAlqæ<¹ŒT•;K¼˜?C¨LãESØáT¤Z8q]41(ÅÞ ân oào‰>dl2.bà"† ÄÀ>c ¼@gàaЫ\Bðï¬XÜK&=îהŒä%?}*àÎÇ_àÏŖæ͐¥‚iÒÅ¢IbhßX<»"¾‹Õ õJF±ƒ’Aü ¸—0(é&~>à ÞöµÀC ×ïëe ÙÎÀC¯fáƒßpcð/Ø´ø§LVÊbJû-?k.A”7_"˜Š©NDˊǣê%c„Æ’1üÕÒ;¸Ž²;¸þ²AÂͲ^bYgT™†ôù€‹2Cbà!†,OKÈ=ë yçЫ¹Øà7ÙÑøçÜDÊvZêC&3OÏãÏ&L%H„qâ1²¬ä©®|4JYq›ÐZy›Ð-Õû¤½¤>i'’:ºOÚJþ|ÀCÞ> 1d#†LЃ¶Ÿ3‚Ñ«ùáÁor‰„çٔ„ÇÜTæ›Ã›cääM'M$ŠÅc”òÒÑؚŠr]Õ0IU=u­fˆØ#ëî©é ÷È®ÅôÈZTÿ!¼Î¢š<Ð0ŽãŒZO¶sj­Óžq©kuÜQj-Š‚¸€"eA‚‚€` @XB$d%!@VI ûö%$lj@A¨˜A‹ VªÖGíè;ߙéuzñ¿ÿݼç‹Ù¦$ˆDbR«žf©äÖw9Wi­ÁQ^c²UT›-U3…f5URmÆJ*¢÷0P 5p¶Ì‡ÆK@¾ý Þ± »üCö?ï +ê ;61|âøµþ„Œ®î3$½-ƒ!ÓášxÊUF1‰xöÜ&µó‚Àà(â‘b¦ÙJfX,¥t«©´Úf(«FôނÚOg5p}çƒÈo1(¶­­ßf°îØùºÓÏãþý÷|Sv/¹%½³V}Æ)Ö$;͚ÓF».Meם“ÛuçEmvC‡'èh÷°QCÝ¢Yаésh]÷×,šî^½trxÝ77nû®í›úÎß9µ7Lwÿ@¢ìî‘,ÞDdu,BºžÆÌ ²Ü%â³kä§{êÉ=ê–Äîe’Õ¥:­u©S•.uºÜ¥Êt*½ôß ÉÚ¿BÛ·ó³/ûÛÔÀ’7&V,tOmÜäxº}Ÿöñîéà o*ä<í^DAñxbyލôì0“>P,8ÓOkĸ¹¢D·Tœà6ˆã.÷HO:{å‰æ9FÛ#OV{x¨AˆšW~Æ%Ÿ=½´à3Ï­/?uÿ²l©ýåúmšWۂ%/¾æ=J¦=:’U|?šHœÀ”deP2<øê”ëELÌ…“pY?ØÀhœ´ñ¸1û…±} ñÖ¾Foà/>дp¨Ïyãœ7gÔ3w¦{jþ<äÕÒUíïÖm—¼ÛvûÎ?š6œTòäXq*6;‰ÉϸAJ¹•S†+¤$Œ–Óâ<ôê˜uôè #j¤½6rÄÁˆ`D 3£ÜÃ,op®HÎÓçéûøOî±¹³m¯¾\ †ekÄ°~'üÐ ¢äÍá“Ä‘g²ŸÄg¤=Ä`O?H'œšÄOÞ½P{‡\3A+‰ú‰EŽ¸%,ûa\^~l\ƒf/¿ZvllÌk úØÚæÍéœãsipŽíÞÜ9*XðU,_ƍ۩°#°‚Ž߇EcßDǧMÇ'%¿HNIxšž÷+ö\Ì£¼¬¨‡$lÄ/¸ptl…ýÌ%ý¹17ô~K^È} 1dÒN<d8⇃ȀXˆ ‰<&(G¾‡dl±Â1À?’È ʨÀ÷¹1òù¿3?ðÎë÷Ö÷ÝÛ3vë¼à€jjqBÙn8 J¦–:j`ÙG'`Ý21|»š ;7Ð`ß&øo‹ƒPÏhß1ÞG a}C )ȁeðž¿dD#O«/¨‚ö6ØŠƒ½Áâ ÖP{]¸äˆªéF¡ Ã(”þ䠀åKù°öc¸.#»Kq¤ÀgK±°æ£hpuþÜ?ŀ׊@Ø¿òtACèê}¶Æ"×îc_zAÂW;°Þ(v@ò×ہõ;ð\·B†ÛPnÜ ¹ß :»w…#°×-ÖöyÀ˜a®~ÌÒ ¾À¦C'’Øz6þ UC™§Ñ_‘ŒŒ¹Ä +æ B û9þtú ®‘;“ÐÄ{–p™?ß*˜ŽëNÅÞNÄߎ&Œ nã +nÙéÿÇðåàlw–Ÿ pŽ¸?Æ8_àQC€Í< +LqÜ;FVâkú)ê+ª>eŽRƜ%Y8ωÕÜg„zþ4¾Q0…kMa?M¸–ñ4¾7ãqüŒ1콌!Ü}ñ ÂXÆu;1pC:b`û­Þ!7Ey‚‹!%x©‘Ø„·Liž¡¦¿¤¤ÍRKØ33ošT-˜"֋ž2žà›$“¸+ÒIl›l2¡_þ;$»‹¿'»I•õ$ŽÊ»‰‹ü厐Ž¸ˆƒ„7Fz‚, „Œ¨\ö GNþ-M•ò"Eǚ¡¸ÓT“`ŠR%~Bª“L&6È.dNà¯(&pÊGØå~H98¢ø…8¬l' +Ûì‚åÀ]ë¼mÎÀE ’P7ȌðE2‰&G½rp¿ó¤I/Ù9©³iγ”"ÁSz¹x2É*}L®Ë|DjPŽ'^81NhÎ~ˆïʾ¿•}‹8”ÝKÊé ßÉi¡ÜÉi¶1ÿ»U vƒ¬pÈ9Ž†lÔè ÿZ$¢ÎñN0gØy¼©4½x2¥L6A«TŒ'Õf=$7ä< þ¨KlÉ#ôåÞ&æö’sÛ)ƒê' ª/S՗ì¢Ï@°Æ „ˆAì» +N¹‚*ÌÔ1hÈÅb ‡½ dàç¥|Ú Q&ëO%xÂΗL¤–(Ɠ+²ÐjU÷) êQÒÅS÷ˆ×4w‰75}”M{Ҁ¶™6 ½DÐ6%hÏ'h ĈAˆDˆAºœ pÍá ‹òm|(œ"F-œ¤ãç•lú¬Tže '¹Zù8«8kŒaVÒm§F’µÃäËùwIÝýI7 +Úiýú«ô~ýÅä~ý¹”~}ãFÁY;AÆ2ýÍ ÄîΠðq¼ƒß@Á¡íP±ôÇB ù^“„›W¥Ñf•ΔT!žªÒ sF™¦¼‘›î.õýJsѯ”¾âz¯áJr¯á£×ИÚk8“ÖW\Çì+ªe^_4 1b †,oÐøŠB·!Ì ‘APwô}A"öµ†NUqØSJ©xBrR9ÆÏÏaµCŒšÂÛ´s%ƒIme]ôž²+ŒnãùÔnãYf·±žÕSVÃî)µ²)©äô ¤ˆ!cµHÃɽ_€Þo”ºCÆŒáP%Øøß ÉI/´ ֔J z¤P*ï‹5êaniÁíԚ’›ô¦ò>Z§ù*£Ó|ŽÙa9Ãê°Ø8fkz—ÉÂí.7q{Êʹ=¥‹²O@‚dˆA½û (F¯£ÿ0ïËa°DY0ÅÿÍH ÍÓR'uÁ˜Jª¸£P©¯‹ + ;Ó-ÆÖ´³WS›­çXmÖzN›µŠÛfµðÚ+Êù–2~§©DÐ]ntëƒ1ȃÆk%”ú~f¿o¡2À ª0~PŽy]ý܊Å?¶é÷K™é· +ÄòՉ¼ÖLMÑeQ©©‰k«jä\´Õr¶Uð[kÊתK…mVƒ¨½²HÔaыºLzqWùb1ÈCæÖO@·ës0ú¬ƒ +ô&¨ö÷„Úß·uaÁsõQáOëããԑÉÿ©Leõ”ðå-ZyÞÅUqƒ¼ÐR+®¬± +ÿYg¶Ô•ˆ[j‹2Zkô’kUù’6«NÒQ¡•tšµ’.ÓbA&b#åVgÐïüL{×BÕþPë·ÎzÏ7òöÃÑCÎÅF7’ð}µÉÌV3Gv±HœwV“e¨ÎÑU”+ÊmŲœ.5ŸÖÉ[ê4òŸm§ä­Õyò6kž¼½R-ï4Ûë†UNµÅŠ#rH½¹äŽñü€¶ñ|jÓx>­A2࣠9Û1PÞRíÊë¦îoÆ<œÝ‚x­.ßñNWóÖ@øÆƲè5΅ÿʃ˜ü‘vz!0$lŜŠ œKHð›ÉH"N¥â_Ô¤y=ïH÷zñgþá—04™Aìy’éÛñŸ,¿›’ÁEyŠÐÝÙ¬,õ´G} ‹ô¿Þ"}ó³ºbãg}ÊOX£Âe«¬eœKò²'!v™D _¦0YïÙÇ©o£"ȋñÑąôÓø¿sã¼^–Ÿõ˜kJ86׍zšà99“àõ`æ¼÷Ðt2~@2ȓC ByvK¹ß¿靐EÚ?)ÈÔ¯ìÞ&XÕ׺¼Š5Î\µµL^sv:³æå±F"±¾ÐþeùŠd?œ Æ¿K õ\⇻¿)Št{]uÂe±5Úyñn4nq2Úuîe´ûäüI÷Ç 1’@á&dº ƒŒt®Gº‡e¶ÉRµðÓÆRÐ؞Z`n˜væ±àbžÎ, ºS!OþÁ"ú¬†“½¿Ÿ +ðøšHuû rùœKÇ}*e:.×°Ž~¼Ávøx—cÿñOÎÑ¥Žãë$Z"ÈØoäöi¤eLMoºʲ—@[™ F{áˆ^ ؙ„ΜîÖð±÷Š˜.žzìD{¸@œ—ú…,‚ýËDÛµr’ÍZ¯õê ?«Õ²ÕÊ8Ùrå™DÍÒ݁A® bÊǤðËfL6¨lLÅ0V;fšÁ`¥Kƒ£†dp3%ë d 7 ýê l+G·q@Ÿ#[8ko ©G-ïx +œ, =‚j]Ìຠî¸b¡O¢žrí‚TŒ!HÞ4‚d€¼T2¨­-¹pÐSb‚±j˜©û€¦'àtÜÀC>Àÿ ZÇØÂMŽÀISsˆ?„…”Ç k +—ÍL ÔÜDFÐrÄÚ$jí@ç#Hî$‚¤½C´!×±AU&46Aw«'˜(¹‚ÅvG°UµÜNkpßõ+àÕÍÁo5SÓB´Œ!JÛb÷„D}àîӃœýºP¤»*ôöC•D•}èüqI™E3€ a°QŠòÚá*ëq°GÆt7Zƒñ¦#`&gV[ÃVpV0wEÀÿ¤¾Jz@Ù¦ å}²}/DîІØš¨¢.£Ý£¶r%‚`U 0µ¤j(6 +ÀpUa/S Í1f´-ÐÏá€ÆuÊ%oð/&¹Ü|Eþ@j ü ¶R×|Úi«„ÛA«„ú +~ŒñÍû9ã_ïyÆü"ã á-cžøŽ>CzϐBT0ÀBh2@EØÎjp¿BŒ „eœ(;`žuzºP/€Rè þeþ@®¢¬ùÖSWI-A+ÄvúwŸÛÌï>¬o„¬/øìeü<{Ég‘½@|˚õ]b=ó{ǖŽ£ lMi2Ø4kÁí„p/ˆð7‚0¦„DØ'Θ©^Ä'µ€ ”Rʚ¿¶B®§÷ka~ómg}#Ýæ|%ñù#ø3a&ä½Ïüÿè®Ï°&ï5Žãñˆ==-œ:+ZÇQÔ£uTD+Ôʅ¨uáBf!„ì„ ²HŒ,’'$!ÈÒ ("e¨«(U(‚L©x@eˆ¢(λO}Ÿß÷ŸÏsý7ùiÈ ©/l˜Ô>B¶G/`‡¡ŸXŒ/Ш[ÌÛ DÙˆÕ„.3ò#6'ú=¦0æ]Ä ÂÛð3ĉ°jқÐ:òëk”ñÃ÷¨cÁiÃ!iÿ{J펢¶FӚ0#Nê¬I@Zè +øï݀èçñžÀÝ뼐µÀö…xr Ð9{€"=qéáŸðHÔ{\vÌ[laSBzYF¯¢½ +»Hz1ÒÊ|ÒÇ`öD>eØ1ƒÌ¦¨¡øëXç 5Q5P7y7À„»½@¼„?Hˆ „øø½@O< ””ÈqzÜ»Ø,Â\>é5ÖF}…)£¿Œ¬bŽ…_d½»Á íä< Äy€`Û£žpnaŸp¯E?áÖãœtôݦ,p…8ÔÀÜèÿ9 Ù¹’¬i„$⷏,~È'º<ê=E‹Ÿˆ3“Æcóh/qǘcØÓ¬ç˜*Îh䥄g·xƒ=ü?1xöè~þM\¿ !¦_ð;¾_ð[¬ó€¨¨´Ò 8> ùyÈ·/å¾5  õYt ˆÉAÀc‡|bI°oéé„×#åe\ó¾˜=Š;•0‚­ cê…Ñ͢G˜ÞÄV\_â͘>ñ•Ø‡’:ÂCɹ¸>q%Ñy?Ãhó]ŒøÞî óûÒƒzÏjPo‚4L È A f„~ä ¢'ØJâ8=ƒþ‚leÆò†ñ§„CÑ5â§Q ÒÇQíIí¸^éM|or=áìñ¬Šô@v–Ü›|šÜ›ä,`¡:j ®pƒÄÜ!uÓlÐ,ý®ïAp#èÂ@³䐏bvô/‰øŠ¥f<§™¹#¤|á`l©ä î\ò¶QރëR܎íV^ŽëN9OêJ© t¥”Q»•'i= +­Gî,`Ow&ºã˜ËÝ iÍ× Þ8 ÿ…`Ú¹Ìû} 3Ô Ñ»ÞkˆÁãJ&ö¹DDâ§0³ ¼Gôñ’MÖI¨T:ð ©wc;Óê‰éçÈíªrj»ª”Þ‘nct¦3:S ˜])ÎúlˆG ìen GïÞ Ÿ™`Þ2²w,‡ì o°o~g‰üå•1öàˆ–ŠAg[ÜÃ$³K åÛÙi½PyƒR¦úƒT«©'5kk¨ÝºCWÂlÓÇ·iòYíêÅäjl|©¬(9U˜¯Ñ±r³´œ“frÎ% 5»ÙÄ0Ý3²„£oÕ'è:ž¦Mã,þÇs&ö[W8ŠnºR¯)UK¦]^6õaÓ·Ö– Ó›—Ö6ýX~%dgñEl¨õ|AWIg)ÊE§¤ +Ö •šb³è ÇKŒ1¶‹F|q B̳(ÖV=ÝìÐ1ŒmÚxC»ÚYˆÄè†0 ¡;â̂Écµó&÷ßüε³k±ëíŽõß\¶,®º³Ççčàí¹ ˜`ärlLj•žxžÃcW‹¥”Ê´|…Yuö¸6¢¢NQîÐaK:|a›6.÷¾†”Ý®¦X:ҝbMŸfôí*™7éCõÌIC×<\:»ÜÿÑôç’ÉW{}ÜÏwù/<íص®àÞÁSSø~ՍŒô™øÝuÕä•ÇqüƒuDPÊQTŒ(»¤böåIžl$$,DÀ*0Š:ŒZ;NµZµŽ:n•±ÇµZP*®ã¸á2í)¸UdKˆŠüæ9}m^|^ßïýŸûâþK.å7V¬Èú©z•¡aëZúÂÁõª†újêBK5}ª¹F_Û\c<Ô\“¹¯¥ÚòmËzG°Ši¨af±Ó›àØÒÜ0†Ü»=†Ü|îÅj|4ú쳨ñǞ$MýW?l{‹œ»ñ ê¡I]voqfÁÝ"köíò¢Œ[Õ¥ô­m+•·UÈnŸ¯”ÞzZ©h|¼š:Û^EŸh[£­m[£?ÔQÈè¡ITÁ”"Åbžŋx¨¦ Fœ„­R.öÉp\‡ËTÜÈ*þm?•Ôÿ;•Ò1¤t¤e!Wr¦Î‰¹îD¾ýyùjx,k#ü]×!Ô³Q>ňXŒ…Á&ðgk ™§€*ŠY>cùȎc–„d”%rQ•‡)ó±#5Ò¢q’…+éQhåG¢Ÿ3bwèF-!?œ&äH#!»î²¹EjàÍZÿQ¥q_‚°qYˆ™¤×_…ÔiR‚ÏHš #‡‹Ü°8΋Ŋˆh¬ŒÀÑóðMÌ\Œ ÃÉsp1nÄqÐïÈ9fGβó!›~%dÍ 3Y /ÖRLtÎF€kÓ¡Æ\ObÆ ÀõICªo2„“ ÷Ÿ: Æ©‘ÌÂ:K§‡ayUÁ¡Ø4c&¶Ïœý³Bp,4?ÎÆ Ž#GÏ2ç_%dãBþü”R¸+>aáí¤†³.|þ sÜ퇏¤xF€ï=’qs@Ÿ ݄Y0ÿ)։AX戊ISQí€-~Ÿb÷äOqpŠ?Žû;²û"sÿ;„T¶R4HH6Ñ•%ƒ‹Ït¤0 ‹`—Hp\ç"b4óGÏ—‚vøn»M…Ò-Ú1þÈ3Vw_,ûÄ•Qí1_Ž€žŽ@?Å ê`gÈÂ]!ŽgCêØzzt–Ph +á.…r=3þ¿'CúM*${yæCô½ÂÓBêEXtY þm ø­R¤w2¤ïù6©MðVÚ/z/钼—vH†?ꏚi3 ²lhS¼`ù¨DFf(ôЬ\õ_¡Üœùv¤ÿäCrHñ1D§%Ö3Oõ² ‚;r,j—ƒß¥ø°h@aدEvy·äü7é;ÅSÙÇÁ0Ù ¦A1ÏÊùlzÁ,ðƒ™ +„É8ÆüHè—ÇA³6 ªM©PnK‡|²ƒbHÿ-ä” âz9DWÞUB𘂠›z' ~Ù¨©]ùBf§ÚåoU‡ ¦Aä %Ó@Ç°‘™äl¾rÈ2p`^cI<ô«B³ÕW(w‹¡8 …¬Vé)%$uÄWT5©!zJ _Ñ6ñÝ+¤_(lt»rHó e×ý&ó¦fÐ|U7h¾ì2}`t†–ã‚ì06 +c½P’ì‹2A J•¢±$7‹?OCÖj!Lä0lSA»Gú°~DuÜøAYgV\7¿•?²¼Q¼´tR½–6º?«Iû:û?úœK†œ 9õÀÌ4d0 ³\`å°Qå‰rî$T¦OC…l6Vh£ñ¹%o eÏÙÄLp»ñqŸ¥__›Ó«ýÁÚ£¹’×I7ç?ÑþŸíúŒkòÚã~‚"Ô-­ÖÚj¹W‹u”ºDd‰ !’Iž 2 hˆìÈ‚•QP­(TëhI Š Ç­{{îóâ¾Ì‹ïçyy~ÏÿyÎùÿÏ$éAø¥'b*¡3êµ7EmŠžJ¨ÇO%\ÂOŚx4Cšðí ¢ b'iݑ/éí¸Œfü F}ÌKF-á%½:v2±2v’fŒAçi:OÇ¡s=½_Hœì`úž0ãÈZ¨:±*¶J?³÷,Úm:™ìý‚Ë 20%áà Êè§qùqC„²„hmâݨ6foT?«'jœÝ†Ÿà4Æ9uÄ NUÜ»<ÞÄ*‰ÁА^š _b`4šâ0ò6YAù÷¶PõÓ2˜í²æß4—ã·í]fˆó”2Òe\w|DÌ xŒÃ˜Š˜~j&¹‡T˜x‹XÍú…p%©=æ6òsŒŽ×@4ðjâ ¼r’ѐǓ +)㜠[`b™cí1ï` ië,¡p£<»Õf;/êÃ_ý·à˜Ã +|§ÔA;ÇsÃ÷ëT!5஘‹íáI 7XçÚó˜- eI$-¿>¾CX?˜\Ij(c‚ªžŸO3 ¹4#7›6ÎÉNœ0 ÿŸ±ÆŠÑZdü{Ìß½\ù±ÄmÍl©×·¦ÿm#Å¡ÎC¹Ñîýä€.9 Û!ƶðÔ˜LV£©¢]–Q[Åj¿¤6,ÎKeÓDŽ™ =ÿ<Àd0ŒÜ Æx’9hËÇ@ZöjK˜²Þf¡{£p—Ý?¥û–½«pùj²ú˜ƒ¾Æw˓òS?Þ+ˆ<ڕçß¡¤c›S‘X­8…Z-P²K¹j~!»B”Ïl’æ0{R2Y:©Š=,V²G“ÏrÆé=/mDP\s`z¿Š[k “ÐsBŽfÉýÎjv,œ«t^<{ñÀŠ ­Ûj]½×7ªwÿZ‚uë¼@ð¿šE מãÄVÊET$£æ²x¥b%RŸ’ν)S ¦È$¥"£B¢ç˸DÆ5ŕñhÚ·xèþHGû¸z³,߾ோ;í^5ìY¢ovYñ¸ÉcSÿ%ÿ]7+δjð~õjrXU“P¬Pó©l•,S.)’ÈDu2qrgªHô\&餢äa±H8š,Œ DOÄ7"æ@š‚Ö@¸Ò*Ñ,…ßXþSµÕúÖi©y—­®}ï’-îz.ûíh¯ um¬ÀùÖǟѨé1yÙH‚J%e+Îfð%Š b~jŒ›Ú–Ê‘ÿ!K’餈tXŒHF“yâ1_dàñ“ ˆ9´iè9%FŸçWa`ÉF‹¹ÚÍ󦛭ôíN֏oü¸¸¿ÝÍáÆUß®6œ>\w1Ò§¬"6T­¡âUŠ"OÄeå!ª<3£2%QÙ*£f<”%žÕIi#b–|TȖ 8)GjD́dtm†½”-ÇÀôÿ,_‡ù«ÞÁÂtmƒ…®k³Åƒ®]_t_w]×ÖæíÔÐ|ê`eöDAmLpf—VÆ"‰Š…tn‚KÏÏRòÊ%q¹Í)±y¿I㲇%dՈˆznLHK×óé +B—¹æ@ +º6¥X†êåÖ¬ÂÌ6Ûcô7W‚Gýë0}wvØ]ï:¼¦ùº×֋íû5-až9ÑAéZR„¸–NäVñ¨ô +›TšÉ#””$ãJšÄ‘%ý"\ÑhrLþ˜˜­çǟ7ðÈJ#—rn<ɘ€®Ï[ŠÊ%/sÚ¥àY‡-xÔg ~»ÿ5æö=§…?÷X¥íñt,»éÿS~g¨»òZ”Ÿ´…x¹BÃÓ/sI$­4IŎ¨Õ gj/óCêúø¡5z¶ÔÀ‹*4 ÑùF.!gœCȚ0 ÒÐ÷-ÂÀ¬Eàm…-xÚl®Û€»÷l@÷З }pëüƁ}öU÷Ü7ôžÜ­ê>í"»áÍ¿{ŠÑIŒÚ81øk¶5ƒÒRÌji`¶ö²šMìàKìÐÊ vX©‰QdbF¼0 ÒÑ ©và³Ú<­µ÷[æƒ_oÍ7l@ûóå é™£UÍçeE¿»mÈzè½]~?h¿àn¸³/æ$ù%8¦‡Åv‹£Cº2ˆ]Å$¿®²ow/Åçö4åäµWԀÆW´ K“´ÓÕ¯h!æAÎbô;,Ã¥` Á +t·YŽkÐ2´4ŒÙcªÇ­‹G—f»®Mûó„cò³Àݬ?ÂQáÅ ‘}#ف!ƒâÀ‡á'Gz6⼆úpǧq^½o Þ7Þ}¯½Žó»ò:Îÿò¬Y0y!˜Î`°º¯X‚¶NKÐØg jŸ,e¦ULÿ²9or^!Ÿp]/?îÈ4úí$BöâõQ.X=É㴞å0&òõÕ+¼ô…Ažm°‡±;ØÝð2Ø]÷>ÄãÁ‡0ÏÞØã·ÞGzýbLà©€;Z hkµ ·,AÕ}kPd´¹³k-•³[me³{Vòg]Ö1f=·ÄϜtÂÍØ{j†xÈ&ÑÕ{–ïî9›æéþ:ÏëÈëjïÃoÚ|½}î{ðõ׉ϾGtŸýÜ~ÿ;àèÀ߁æŒåp·€ŽF:0 ¼×¨YócÒ>:̓|üޖûÉy9íÓ¡¯‰ŸÜ7FÎy:¸-p.ìßÿÑ]gQMžyÀ? qµ +.,* ‹l!!!{ I „7Šk¬KGw©KUªŒ#-êX+:–uŽíA=zÎL[·ê8¸ ‚ +B|潚«ô|çwñ]=Ïû¿““ÿhi²l´*5{¬.]0ÖÀáºwp3ÜG²ØN RqU˜‚ç"֘[”>aæs¢bOn¡¨ï¾"ùç)ªùŠÚ{ƒ¢>»G£6bÚ¸Õ¢-GÔx}íHŸYÁœ|HC4ЄÊaX(AQ”åÑ<ÔÆf`u|¶$$c_R"Ž³âñmJn¦Æ¢/-H‹'Ç<ë> ÚñóaœÛÄ@TNš•“ý±qÊ ìòýGý¦ãë©Óq‰¸2͓ý$¿›äß¡(çŠ2»)*%`Ò8¦z¥ d±¥E!Ê; qÞó‘L›.}6DŒÈ3¡e|“Ï4Ø|üàòñEs262'aqˆhöê/È¢h²èÈf3 å2¡Ìñ…*Ϫ¢ (\¡ÖGAòi,Ä; <As +ø§R‘u– ÞÅtð:3À½ÆAæÝLd>Íç 1Êy™ïà +‘ùJ ®'ÿï J¦CšÊ€‚ÄFâ ­ÖKTaPÔ-‚´!’ÆDˆ›XK…à/lðÏd€ßÎAV'ɺÆï.ÜgÄ Ivg‘|ž›Þ[xýbd=“xM°ä‘4d'Ñ¡`1 IgB'öƒ^9Úòp¨—GCñI<¤Û’!ٟ +ñÑtˆNf@x&‚v.Yàwg!ë>Y½ð†·äƒß/ày„ÿ‘Bä ´¤ƒ‚t&xCÈ€. £À&EŒ†èí ‘[õÚD(¶¦@¶‡œ/8ÈnáBܖÑ>„B»E<ÿ’¤¾Càˆ!îρø™ ُäÜQx†Ü /(#hPÆy#o1&žŠ¤°èBPPCUòꓠù4 ʝÈò =ÎGÎ×BH¾#»3â눒Óö‘“ KG³ÝÒ×Rä9ßË é&'}HNõJ1&QÈÆO”nÕ=µ[}KûAݝ ÍÕ<Ï #4¤ƒ>Ò–(:ìqLT°}áùÃ¥ +A¹1ö’Å(ªIy †-|èv‹‘{8šTgP^R¹WÕï¿hÞʟkï4OÔïµw´£yÿÌÓý¨wë:ó?è.Ù)´á4˜Â½a#*¢}P›2Ëø3±LŒ}*‹ÃQ™Š’ºÌÖáhA£dÄÐ$§?¦ÒµjÞäžÏ}­íÌëÓÜÔõjžèz´oõ¿æºõïW £¦Ë¦QӅ‚Qã9³g0"7ŒËÊx£&ŠºäÉXśUÒ@|œŽe渱jGÊ°s)w°tèuñVé+Ëne¯ù°ö©±E×c8“ÿ8ÿ²á‘¾Ûx_ÿØø³~° Ëð®ðï¦aK»yØr®pØÒf.lµŽ˜=‘tГ|Ù{]Ċ:Ö&NÄ'œéؐ=ëÕ¡#«1ƒ+m¬WµU™Ï]õ¢žò²GöFÍýâ&ÝK³ñ_æ¯ +n´[nš®Z¯›ýd(î0ÙÎ[mmEC¶SÅCÅ-¶·Å_–¼³zÓl/çyÁA¾‹²o®"÷ñ‡øñؔî‡-ÂY#›óô‹z×Y’þ[ïäü¶|¹è×%ëå·+¶æÞpì2\+9TøcqKÑ?¬gK:-ßÛ;,·J/Y_8þZ4àhµ 8NØJ•¾±),9ä²y‚ÒÁL~#œd+È·±.”†Í±LlK2Úȟ9Ð( êý£váãÍ‹ïmp°o¯ª]_±JùSMƒîŠk{A‡s_Ñ%ÇQû{kÙ7%í㶮Š¶’žŠ“ö¾ŠfGŸópYùò×eMÎÇ>ç»'( »¦•d»È¾WOz4Ì£a[4;Y‡öp§½Ø›=ëñnÕü»†˜[›mì® .ѕÕ+”+×ëۗn)ü¦z§ítåAG«³¥âdÙ9׉²+ÕÍe¿Uá|YõyÅ+׾ʾŠÝ®~ç.×ë²®‡'0“ÓFfQCö½5¤Ï&2“‘Þï÷%Žï?1åÉAáŒd·÷袻¶[Ó~ØìýmC­êüšÕù§?Þh9µ|{ɉÚýåǪ›]‡]mK¸:jš\¿Ôî­ê]²³úEõŸ–¼tm_ÒW±íl—y8ÕyƟ³8–¥H%C¥E¡S‰²f_˖¥‡ã88‹­9v!Œ5d¡l!‘Ò´ÕôÖeFišìK4ÓLóÌï÷ýóüñùû¾¯ûþ^ßë¹ÃXYá‹A¢@ƒÐæ»3A…„™êÄîü‚²Z¾—6]M—ú©ÖDî»j+µ§¥.;øìÍfšw¥‡9´&G»7Æ%úÖƞgTF².ò«8¸MÜ<îm^÷?›7ÅÍäO‡gðg9éü9v:>$·, +ô%tƒ”IIl¾bó樒þ¾¨I^¬Ö¥NÔï{å ô‹:‹+vô—xÑo˜·f‡:4¤ ÜkR„¾e iŒ"anH^lYXVt/#ê¦à\Ԉ 5ú=/%z*"9z&,9j649j>$)j%Š=°Ö“0æ¿{‹È"_…ô©Bƒ4{Y›üS“.u´EÍp£™ê@­Ãöî +Ãk%§ÍóYö5_qO–fÄúžKf|•”’‘Pžw™— ¼.ˆF +ã&ùBáWøåLxÜÙYN\ì;.v% +ô#<°ÿ¿{Ï+­‡•UÒäÕͤ·íÛHß´ï“zÔrL¥¯ÁNûú¥“M~ÇjK‚ìÊ +ÂOæDûdg%2Ò22YIçŠÂ„)—xÑÉí‚È䇑‚” ~dÒ7*a:<:~–7ǎ.°DþDaDñr€Ùò€¥ò°xY~nS‚Ñ›j¤á®½í&Ê·šmµZÜö_¾äs´¢2ÐæÂÅP×ì"wZ~ܙ„œôàØìŽ ³Š‘Ñ*àd 8çᇧOq#RgÂy)³~Ò[¸Àž&ý„ÕÞø `À㞣A  OžË_Bý¨'=¸Áöà®q/n&¸Êyàd,@؆%`mYŠ ºå`îY…€ƒn`u£Ûþg=áw¿»4Ð{½@ð‚ï¸7|I:¼H¾á5 ï?BHÃI ‚t`{RÁñ¥"‚n>Ó|¶¢bf/s/m!Âó?Û삐OV"x·‚¬F`‡'˜ÿ¤!à,ɹê Æ0z}áßOX ҂AÁg,ô7¡ð{Ɇ_g"D.³ǃ +žQÞvˆñ·Glˆ„üYˆMtBtÊ"ðsÁ+]ð*W„5¬Fh+ !‡½À:æÖi__¤#è;?=öGÐ+b„ÀŸ¬¡ðà à¿á`>ã‚ù˜7ø¤ÃҁO=íà3â@$ñfAœà„õb³–"ºh%ø[WƒWG·Ùámtp:ýÀéf€}6aיû™è DØ @+Ìþ5zÎëq$X?ñr'j"D‘­Éu§"֕ +±›¤žS g8@> J¡dòÅHJ[Q¾+âÊ<³Í‚:ø­ D¶3q,¼ÓÁà]bûkœû,d„;2È{Çêç!´—ö8?Dƒs3œë“€ÀÙüU¶HXA…ŒP»ÛAKŸ +}Ø,èNÐ&-†*ÅòunH2Ñ ²Ð_Çx+l´Æ´Ew„ŒºÃ†ç؃Q7ÙýQ9/¯9}‚ñð§pïŀw3Wâq>ç&Ò!†ü?“È{¨ÉÖÔ¯²ÃZ{d±>@V¤#֊A¯rAr†»UUà=,7ûJ¶$6°^‹ZÂ^%´s^Ä[Ó÷%÷¹ð*·7î!ïqÜ+ÞC¡•;Q× 8/†àËDN&AÐ-™±d_Ɠ|ҶЙä-֑{äÎ@w. …ÖlÙ²Át½[¿ÞàýR[Âøª"¸WQöT¶;ü±¤ûKRgÄñIþO¢‹‚»¢{‚[âÑ7Åc±—!ì‘ î„qÇe•#¶C1„$WLhÙb-‘»Œ +#¹G‘ÿ4³g æ_4®¿egy?Y»ñH_κŸ¼s[½+▲%êßòö˜²ãÂkҞø+’o.J{ÎI‡E§eW@Ü©‚è°¢ƒj$´©ÿ>đ|)É֑‘³Àä6¦UT”ùN-gÍì7G8õ•Æ/yZ¤\ùИN»³n}À÷™%¡7Ò,Ü«ºíQ—´ÿˆ=¯ÙVÝ!þJy2é´ò²ä„òɪ7Ò£ê·ÒvÍ[Éí»¤V-÷¥@¼gˆ_Bî°Àidg¬'=Š—ØÀ¼Üö­…6åM%sz_eøœ_-Ñ ~6K]n™t^7 +r˜— …ìó9戞ŒªèÓé;âOè÷Š?O9$éÒ—w&­8’|[Ù®ý]ٖ2¦hÑ[åͩ㲦ԷÒÆ´wI “ø³ƒšdg’Q@zlZhËR›ájwêËZ¿©OkCf>¨áÿýVE¢Ëu³†v¡$ƒÙ³!}*¯$ò‹\KlWv­¨#£Ir8}¿ü`Z§jêMk귚½©}šÝé#ꆵ£ªVE}Ƹ|{Æ[)!yD‹mìHî@6oñ<l&}ª–Ø Ô­°ým——Ý£Fæ´ëyNßÔ$,»P¡¤}UžÆì.Íå+*âw˜…‡ÖW‰ädïS6gÖ4ežÐ6d\Kٙ٫­ËN®ÍQ×dªªs¬ŠªœqYUöDH$¿[G² dë”Î¥ Â‘2V»€òr×G6Oš]mï5Ón6†;^ª.í©‘{vWèº6g³?Ûh䷙6 +[ ++›Ûey»U; Ÿjks?×Õ¬»¨¯Î}¢ûØ0”RiN®0Œª-†1åVƒU¾Õ0.{$ómJÞ ŸlÞ²ÙTÍ¡ îp¤<ß½€ò°ÕÙæV«ÏÔ«{ØóÎ5Æ8Ÿ¬—xtÕhWf°lYÏßWf6•nIÜY\#¯-lTWìO©0vé·äZn|”Z^0¨3 iÍÆM™qTU–?¦(Ë·Êßyûµ³ÿ¿{)ØL|2‹Òß8›òkËÊ݃‹(7xÙ_h {¦Yðáñ†ÄÕGêՌ¶šô°½çF6Z +…õåæĚ²*yeéNõfSkʦâÎԒâž4Sñý´bÓ:SñÖT4¢1ŽªLƦ Ö   ßa&É.&»×òå÷ú”‡{¦Sî·Í |ß>ŸråÇ”³m¬ÙÝ­ü%Í"·ƒJ¿};ô¡µÙuÕÆØêʍb‹¥BfÞ\¯.1ïM),û,Õ¸éLZ^ُĀ>ӐÖX:¬)(U˜Æ”LVÅû &ßBٜ¥3(CUÓÈ沧Üi™F¹uh:å›'Ê¿Ž¸Ûjú[W[Ä¢öÖx×Ö=rzSS +«nW&·º./fk­I´iÛViqU­ÊXÙ¬5XÚõ9–S©Y–ïˆ×ºœ-CÚuåÃyTeØ4¦\¿ÑªøÛuÕä™ÅüæMBXEA«„aIXÖE@0€qWëz”ŽZ´D¥ +RŠEAPAܵEܗ#n=3Óv +cÇNUԞ‹,òŸg¦g¾À|øó~zþ÷yî}?ÜѐÃf¡À”Í‚1=ÛŧoéA­ˆî4ÓµV+ºØâÁok2?ÖmW{$QRYkð+;”£.þb‘î“Š‚¸Â}ëõë˶¤­ÞSœ±¢´"{qIÝüü’Óyy%÷˜×óówöç,Úñ>{IÑ@ÖÒmƒ˶\6‡«Eô~Ÿ¾ÛÃу*!Ý®3¢®ãFt¹mu´M原T™Õµh'lšéöy}ªOqÝÜàOjó# «—Ǭ;¸&aÕ…)Ë*>K_X¾?+wÿ᜜}móæî»Íôådï}Ÿ=×@V^ñ`æ‚O‡2òw Í YÖóéÙ§D÷ñèN€®6èâ uœ1§Ö³.ÜÑ3þ&Õí“öŸŒsÞՒ"/jÊT6慮;ºT·ªnuÜÒÛfå×î˜=¯¦,=³úËÌôê“sÓªo2/³ Uƒ™åƒYeCs²w§ç”FÃRևÍDßï"º_IÔUǧ Mµ·óèø%Sª¿,æÕ\RU\µ,=ã°½CïQØ>ÇwÝ©yÁ'G,iY5-¯yc\vSѬŒc{“SkR“N’oô / ú£Ã†”/?R«>¤*FÒÒËGRGC€žo#zTFt£šèb=ÚØî×t–G_]Ò¡k¶TÞ%”^ 1ßþM´má•D—µ—Òd+/dû/>¿08÷ìÊð¹g6èÒ;¶ÅÌ>½'^º:1¡½Uúº>¾ý…>î’f6#9ñ(’õ‡‘œTƒ¤Ñ°Žè‡Dw]ùŠ¨½‰èÛ½j/qTyÈÊîM¤’{î\Ñ]¥Éæۑ×ފ³_q3ÅmÑõ,Ùük |³ºV®®S§\Ý1«s·6¾³zڌÎÖé1×™Ó£¯ vÚyÄÅ´#>¶3ãšÇúåÏD÷]­!êh`÷?ÁòÏUtr´ë®ˆŠžšÓ–§Ž¼O}„«Ÿ„Ž[þ8Æ:ÿ‘Þ>çá—Œ‡¹©Ý˼’º×ú&<تŒ}°;húƒêèîV¶û†F×ýByÿCxø]DFvAu:íyDöÃgD7Ùœ«#jnfù§‰Ê¯•ÜâӖ‡"ÚÐkNkzż•½rþ➠ãù=Z‹¬žkCOš]JOŽxVÏ×øžÜcz>–F÷”ȵ=U޽͊ðt2ÿT„þ8èòw(CþŠ@u7‚5÷2Úýω.Õµ4>Åò/í¼NôñŽÖü͈V¾´¤Å/y¹/eü¹¯TF†WfɯfŒOx•dחa3½/ÏN×·Â!²oƒcØëí.ê×û܂ßÔM |{F¢úõ‘Dùæ7‰ò$þ/!õÿò€Ÿà5Zç!¢“õDul+XvvÞ'úÓ_ˆ=7¢Üß-)«_Ì3ô{pÉý~‚„÷j£Z“èx³¨ÁÙáƒY4Cùƒ‡ +¬UC›lü‡wÚú~¨´óùÐdï5òµƒÏIJáA±lbY?ñhí¬GXœaùD›î|K”÷#Qæ;#JÅÒÎ7n:¼øZ(᪡3 +B¼H‰c?dšø`©ã¤Øl.A‰ÅTšàŠVK\ŸèŒ_¬œ0låü_õLj*ÙPü5Ë¿C´ò)Ñ<–?ûg¢D(¤ƒ5E@ÌSÝ „現j¾Q)fÜ1Kè +ƒÐóŒÄX.š‚"[Ûà ñ$´˜X£ËÄ +Ϙ÷ LG«b3Pr™hó-¢Oˆrzˆ’žż#ŠQ(L(ˆ½…?&ñ|X2¸ñ$ðä¹BÁ9AÅ9@ÃÙAË·A,ß +I|KdðÇc¡ÀkfØ.0E…ЍBcœŠÐÍ<£ôëÿM–ÿø|=»¿¶HÍòUŒÉ`JŒ'WöŽ˜Â›'ž «Å +RÞxó,À‡ÎQœ±[9B6³œÙÌ'”2ÕÌq¦c „°=/ÀŸƒJÉGp £ P'D@¢~™&P,6‡÷:Kȋ¬áYf󶐱ƒ´e +¤öð¸â[Ì1<~bÞ8Âc€Áÿˆ!eäìÛNʱ f5(ý8ûñ¡auhBPG /‚*Ýùðûh"['Á{÷dxWÚÁë°=¼š ocg_t„üšäÝNõ:CÖÇô3pf¹ÿá/F—a?¸öŒ„½/‚C8«#"P€ð0!Bgˆ I5CHîxXAU8Åvð/·‡_¾ Žð=áß³ÎP|ãÅ]6"ß3/Ü xnj0ì|ßÿr +€û;ÜßA2BY !Þ"¼8è¼ùˆö@"„nšÚd3DæL@ø²IÐl°EÈv{íuDP•3ë\ jv…ªÝ ÊKS¡¼áåæ¹Ê_™! Xæˆ +’Á@H †ç+5<Ÿ‡B6ÂÜ9„ÉX¾”CŒ'±ÞÄ +ÅÆ+ab2,1m‘ ´k¦ r‹ỜVîŠÐš©ÐÔK iõ€ú¬êNæ¾'Ô½ž#êמCêÏ~ <WCþVï…Á§7>ßE…pVCÔ¿É.ó ¦Ï4Ž¿áY¨EjE­Ö­( Š"Aäø%¿œœ ®„#@¸#rÈ A(Ð"HêM׫­X­³VG+VW—ÑZë]Ýgߝý/ûÇgæýïûÌó|gÞùà]Ðךß$žƒïi ¼VÀcØjDœ0•Ë!D³ +hzG¬[»ÚÖC€q nü@=âüžú­Ë_þ\ßøßr}As}F}íú„ +nsþàþ[xÜ +Ï«Aày9øÿ*Φ9â|ìºüÕfú…9D¸Y@„DÛB(Ï„ÑK€—´âßÕê÷Dñº·Ì*§×ŒFç—!.†ômz<âöŒvlóï´i÷'´k¹?~å1Kƒ­wƒÀëZl»Dïi&xŸbÁ6S À‘Œ•àaç [nb<ÄÅ$^ó@`1셢—¼ —®x!JsüC¿þ)Wï?2aÇ4;N°aÇ1vŒ“àk +ìZC狰o‰—R ï#ÑÉä– ÷³~—H·{/px*Ù½â_Ñ +LJ‘j§Ù°b×»¢ªÍ·û=oò:½~æöy_#¿ò™!§|ä\Üq™¼çwž|¾ó ÔÓ$|ÀQ>P‡@‚¿)ŒwÀÅÙØuâ°sÉW`ßÀ÷Qn2«ô¶ú#5hÁœ‚óéyÔò»R™ã/’ô×£5n3Qº-߇¼/†5ûžuûM üÏ +ÆN Îî:!¸x\ð$hBð6&ÚP(õ‡APo8ö„Ã.S€Ž3‹)mOÄEHÁód¬¦ü¥Ú`ö\íiùX½Óf6“iK¶ì'Eœã²dç Rµût¬vÛ阽¾'Äõ;'£Ú¾‰è :>|$l*äë°èÃáèƒáïý@ï‰zg„´‹!¸U 4S€µ ÷»V,ö …=vÅØû–S^jÖRæ +\Íg ·[ÝÔÛͨË.¦Ç¬=—"w9™”î9)ÓxOHKýŽÄU|%i¤ Åt… D0ûĬ^ñyÂ(žewE¿&:b€hÙ ÌF 0$@¯“@ˆ)ÀÁ=ˆÄ®%ÅΩÄs¨?Aï ÐïşS~+[ov«l‹åLqàÇòÉ¥gr"§2¥.GÓRÃIZÿYEࡄºc|;³+î»#v”l•œá6Knscÿ$â€S„A +¬j)0«¤@7¸øbœ-Ç®“çȳC¯ŠíÑc½ºS¹ŠòSåf‹‹zê‚3%쥓aŽã¹±.#ª¤->½J µ;¹,¨3©†Þ*o&e=d}â0¯6áߐp]PøŒW%n… 8år ôr`édÀ0ø¸»q¶ÂÊ½-ü=Ó-@÷«ìЍ}ËÐ÷†Mçªü>š*g./­.Œqî×È<ÙJŸÎ¬jkF­Q¹—Q—ÒÀ®I>À­L”'꒮ËO¥ÉÀ+I²Xì"¦) Ä]ŒµEú7ô!Ç=*™nïµFÿØgƒfÐßœÍOÖúÚNTÓF*ø«ûËÄÎ=ERώüŸæ\µ>»€fP陕µ}z;¯DÙ/Ô*'DÊË¡ùÊ9a~ð5iÀÕ(ƒakRe +„-D}/Í +=Ë·D·u–èzõ|œo.5-Bgš7˜ß¿Ýf´6xñ@ w•qoäÆ]œGSIÒö:m†u~­<¯”YšSÃѪ[xU¯0'k,Tu!T•õH¤R}¨²€§ÊRlu:¦@îB¢‚L tOKA7*,ЕÚy8>šn³G߶a6Þ²Íz¨1hQoge§!Ì©©Râ^[.÷®*Kóחäk‹UìM/+Ï(LÏ Uæ~šš÷P”š÷^ Ì^Z6éj`§«€0¢pöX WÙØù°wÎT™£‹ –hºu:yÀMt­5éÜ2¿¯-à“®&bEKƒh}]mŒ[UMÂ6]eŠ_Q…*P£+¤«K+ˆŒ’njQ·@¡ɵgCeÚû"yÑ;ÁžBüÛä©Ð;9S w!™‚æ!tCÐå}fhºÙì´@nj ÐèÁՔ£‡UO—ÿÂÖægõ­‚uUMbW]CüVmÂ7ϐ ªÎN«Ô±u¤¬¼“/Õ ãô§D±ú{ÂXý[~|pŠLÔ[V„)‹» Dè×B¼ƒ½w‚Nµ›£c=fh´Ï þœr°ßͲýßÇûô¥Õ]¼5ºŽgm[¬Gn˞íYéþʆܠ¤úRzB­ˆÝ×NÆùQ†üHÃ~TÍ®¸ +Ș +àHt@ĖːZ¢—Yý‚ïpـp±{  ÑC |i…/CC._úØÖ¦-Ö÷‘+µ½aN¹ÆÝn™Ý‰[S¤úÊ;²©ñmŴݭՌ¨–V"¬ù0GÔö)js23ñ²Ö½Ë^;B|–3$tÌoL>,u—õ'{ÅRùF÷j©+EÆæ^O?ƒì™drŒ7œî— N0¸­Àà7]X!¦@*Bw´]ªAèd BcÝ öãü‘ÿù_ݤªžt¤èŽ{Ì+<¶sAöÃ!ý(ÿsÅX亄#qΒѤÍQÿa»N£š:Ó8€?÷&l +‘°C ³DÂaI°)Te´Z=z¬Smµ:í±g\jíÇj­=Ž¶.ŶÐZ7w‹‚ÖÁ:V2Ö±. ”©VD¨ úŸ×±ý ·߹÷Óý?ïó>÷ÃóÕkÆÊ/—¦–7¼›áªÿÐZT_ksÔ7å6¸mŸæäïDna-r[;~Óóúc³x|ÑþÍD_|J´íó§ûßÚŽÞ>êKˎEћÇԂEG->¯±‹çv…Í8T)ýÃÁ©ŠÌN˜Ð²@]Úò¦n|ó;)ŽææüæÚT{s£%·¹35§q0Ͷ¶ÝÈÌm@¦½îyW–µ³´Ô5°;ØþdÿdûßÚ&¢•GyúS»-<Dó¿çæž6zÌÊvcŠ_֍YcÒo,°ô¼dîYbìÙjèm×ÿt"\ßÛžÜý8\ۅHM¤êkˆ©™ÝÁÎíD›Ù ¬ÛÃò²üDs;ˆ¦^ ª¸,¤ÒÛþ4þ¶„·ã¹¼~o»cdÞɦ 8=Æ Tx™îV{îÎöÑ .­\æ;vh½H5´mL¯ûý•÷.ˆ•CwÅñÇ÷C׏À‘ê·ma3ð>›Á•ˆ^gùsX~µ›¨ôG¢Â[BÊ‘íQ(e>Ž¡´Ç*Î Ÿ ¯ƒM †C„ra¦xÄa–‡¯yFc…— xGa‡w$xKpÍ'÷ø„ÿÛØ l`3øvËoùg‰&_$*¾B”ÓM”ù# |Ʉ@ÒCBZ(( *.É\,Ì\ ²xòøHóᨄ`† óX&cƒÐŸ ÇࠇW˜!ÏÙÈfpU3ë+Ñl–?颢«DÖ"ó±\" ¼Hų:ˆ ¢I‚x +C =€qœ?¬œœ/Ê8Tóž˜Ë ±”籎簝'ìcÎ??g5û—|óÛùÿMä¼ÎÎþ˾Eì¼Är‰b˜(xSü(b +Dù³ZDÑhĒTä ñ¬/Äj!8˜‰ÌKÌ"f5SÃìdZžm‡$=m2] +{¦ +”-€²HE•bfy"z¡¤Ë} ];ҏ|!ÝêiÒ¯Æ ª‘9ꏨÓÌbDõ2w˜a1¤xÂÿdì]†Ä òžÔ ÑñÐkyXz“ÚLVG¡'zB9à q ¼ûÖh(þâ ÅF䏁|‡?äõbÈ÷2 ?ɜgßìfn3ž~_ÁrŸ +B,‚Ç#dXù,èT’Õ<ŒI¬•ìiÒ b@o÷€¶Ìêi^;oToø"q• ëý‘P#F¶(wB¹+Ê&æx0”ÌUæ&s/ ø]”NDØPÂïŽ}’9¤0© <ÒT<Ò5<,¬©6˜]ž0Nñ†aÎh$¿.‚n¹?´ €æà h>†zGÔõÌÞP¨…A}Š¹Äô1ƒa4{ÀÜW#‚‰Ð"òf2¢úôςå‹çËÁÇ#;‘‡Í @v¦²žÈ¨ôAÚK¾H?æ¥0­‚q}Œ5¡HÙŽ”ºpvEÀÐ,¡UòÈðOÉà ɯ)’ãcI +¢n »e@t 1W͈¹<îY0*Y¾œƒ-šCSÀêph(´‘Ÿç {™r¦ú!{®Y‹ƒ±<ôqúšðáôÓ6GÞO«ºg©—YöI-Gd–Èn[®Ëþ“Ö/ëµ<Š¹a¢Ë‚¸«Œ;ñg3&óYHeçϖrȗpp2.VO)›R“®lO÷s’h¸pVÀ½üWCíKÃrޑôÛÖGýbû›ìföÖ蟳ëbú¬_Ë{­ä=ÖSŠ®ìW²‰½dVº­H<ŸU‡ª“6¨Žå@ud¤³³ÛÙÞë eÙÌD‡*%ªd*Ó=†'ø •Uˆî”¼x«x^h_ÑIc¹´»pMôµ‚ò+ù›c/ç×Æ]Êkˆ¿hoRºí'ÎÛ/%väÝR¶?T·Ù¡iµC{$Úæh÷B³gX£8²³$å¦°^LUp˜6–0Õ,¨¶yߜäò멚xmâì°Ëå¯F^,]}Áµ*ö\ñ{ʳã?JÃ1úҴʀ﫧‡Ÿ4OömåbEۄ?+[+ÞM:Vö¾æHiîPÉv}‹«>¥ÉÕdÜïj3íq]3írÝ57”`ÜÌg¥0o/ƒiK9ŒŸŒ€<Öÿ’ÿr]žQMgyþ%DŠ +*2¢Ž2XP¤H€„TA¤D ‰@(¡„J¨¡†Þ”¢ AÇBÇ6™=»ãŠíìì–³sfçìκ»Þ½¿€žÏïÿÜ÷½÷üì{¦€b— OòøMbCx-µ'¾”I?&sÖ>›ßÄXߎMÜ9#ÛsãdÞþkQ¥Ž“5ÎáÍn—B»ÝÇN y\8¡ó ™£ …<¡œ;ñ µ?QûB¥+ yµ‡#ÏÖpä!¯ùãóÁ®u»NþñxŸ²ÞʶÀ« [ŸÒ] ÒX&w¤ÇÌg“£¬¿²™<%Ý«‹Ï:0Æ/<8Sî6|²ž¬nó:9@틼H뉸AïŠxÌh|K×D~ ·F!ZS4¢ª£¥.y} + +Àç¶|&€×âüõðt3øI¾ žäl}Ž#ñŽœfr+ãȦéÔ0k4Öf,9ÉnD$sÐ&äº JÜ{ãj<»b›©í1=ôVÞ³™7Åjä=`×ó~f×Åü—YËGŒj>¢Uñ‘wQ1”• Àå°k Œà½Äþ–n‹ÙÆð$o<.°„»öÄÅx:‡»érVȖQÏF›"´žvìI–»v$’5 +Js‚š¦t0kãµìš¸ NeÜNEüOUü{¶J€X¥Ä( Z±¿0D] +Ú(ÚïÀÞ¦ái–ü 0‚ÇE&p¿ØæJìˆ×”žFºߍ£yÇ· Ê£lú2v2±£&%ݵIª «Å¥”3ɵôªD K%ð)^òU +çý +…/ý +E¿s +ÃÌ!ºB„h`¼žü/ ॠ{o. +×Àýc¸­2‡ëå{WTî†KØ´EV}Šˆ9±{[äI ©®µ²rUª’ª:]M/‘6³ %}…ø¢_®ø7[¼È͖üÓ7[‚|äĒ‹CžŒ_ÛdD[ :·ÈøU°˜…½7Ÿ÷JHðu¹!ܪÚ“5¶„ñ*·5ÃL³þ²ËNe莖˜=j…С&ç´K…<‹\šYH)ʨ +d ìì´nßÌÔQnzÊ ÿ´Ô1¿ù¥¥!Y*bÉRSvÑ1´• 0¼…x€¿¦ü{ç·JÜ.7€[Õ$˜®5ƒËõ; çëœ×œ­¡›vUþ¼¥<ä uéÉÝÕÊST…bçâüt÷‚<%7GEϒ׳dYœ”Ìa®$óš¿8ó̯~âLđd"¶41¥2Dÿ‰·ð +÷ðXp§;O¦ëˆ kX£MÛa°Ñ‰Ô­¦®ÓÔq-Ô5Ç·UWFíR•ÇïW–%T§ÊVæze–ÐRókYE;')Oë'̝âžÊ{„ùÅ/!ùs[”˜‰Yˆþ)(šÿJúØÃÃ"ìØûj& p¡Õ´kèÕ0hkñZÛÐÄ1¯i8f­ª ÿ²è ß.¯Zä˜U™â*+—{H˔ԤÒj†°¸•¯<竼ê£|ˆù»/_‰|b +.1ãó]»°$Å[Ä=ÜÅgp³{W#vÏV€ÁôvYB{×>bc'Ù¸¦½Q¥9jUÔº#·‰·'³!á@j½ÄYR›é.:Sà%¨®¤ñ«š™'+|¢*'8•8ï|"*;R…˜Ñ%ˆÁS"¯h5Ë[øK€¾àãL«Æq¾¶ ûf`34ì&œéw3Tõ1L‹z–Ó²-£#Ê6¥-Þ.Y“ì(l‘¹Ä5+ȼ&•WdC#-¬¡¢¾Ì n¸Ç +V¿a×#Fp¢‡V#ZXþ+*_Í¿E{¸Wp㠀®`ç÷ö´`ÿ©ÞÕ#6„²áƒ¤Â!êÚl­Ÿyú¹ +é@ĉý±»Nõ‰öñ{S£»s\»JÝC:՞A=”ÀŽqï€Î;Þ¯©mˆ Aԣ͈zL(Au«yƒ{øoq¾`w0Šý³¿ í@-vвñu ¼´—ì‰òq£´1¶©øâQ á…Ð-q£¼/xçl#GNï –Û*v:ª­s9¬í>ÄՎ¹ûi¿q÷\rçœý@æ ²o/"s;Ù¿}5¯2¿G×ëp€sÝgê—ó±æN‘ kÚdÓ» ÒiWRâÝX0åo3¼9êj”UØÕømÁWÄ;'2w™(ÚËÕÕîç躰t˜ºÛŽLݒcüƒ} 9Ó. Æra®æø 檮´ ut 4Œ”ã|Å$@êMHœ3áüvÌ;bæ=IQó>ÆasëƒçÂ7›å[™M²äΦ[sf +¶³fjvÒg:¾ôž¹`Kýږ:³dëuóÏëȎüÚç1…ö{\Eö+¹W†w¸ÜA'Þ@?@ίXΟH» ¼mÑŒ!üáf[°…BÐÍਞ»Æ_l쫏^ÇÖ'˜1ô)iú¼Í}ågžú6K²þ¼•û£y+wýÏVnÿ³ÕåÚî|í8xÙ8Ý]ÍMÜÁØòðh¨È_ο…ó¿Áú-‚¾3¿'ëÁ÷©pžîŸÅCæ"ƒHvÄÀûY(Éë9ßÐãy’Ñ¡çY&®/J×9¿hZïôrÐÔñåu3‡W/Ìžý¾Á~™ïŠ,ö=AŸÛ}‚nyø´á;Pó –ógîD.~àógЗLÁ{É(¯mÁóµ#¸¿ñ ¸½aœß!:½ 5pxÇ7ø?ÙõՙÆü¹Sa†20À ÌÐf`Fª°P¤ˆ"JQ,X"q%±žUc jtíE±¬=¢Á.Y{ÔuíƏƵG"%( +þ÷!çäØýð;ïOÿç}î}ï'´~¬$¸~²ÔØ0Ofh¨¼Ú#×ÿv^®õRîÿ+äþu°ó«ƒBW e{;ø ¬ÝF´è;¢mù§ˆ†_ x(ã6QÒ}¢Ø§D›Èú֍"Þj)ü]…5GPps¬`|Ÿ(|Hü?ô´-"ŸÖÑ"ïÖ)bϏ߈5X/vÇ~‰nHÜ>6JÔ-«ß³æŽ*ù .ÞC4“ó'œæü‹D¹¼÷´»DÝÙ8?¼‘( + +†Š А:ÒÁH>0Z¤ArCOÁY‚ +y‚JL”X R`ƒÈEv¸%’£‘áÿ,ÝM4‹óËÚò/qþ-¢TÞ{Âc¢ˆçDAõD òƒ„38Ӆ<àAjt"ø“‚Èá¤@4Éэ$H%þ“ΊB+g•l»Àjٛæðùû‚û?¢-ÿQ +ï=–³9ߧ•È“kpg.\‡3”œéDö\‹ î$†7çù1# g1,‰e²|Æ/AÌb|ø±ƒ}Ï~è̂"F‹à×Mï414¹b¸C=A×l[Á*¥pݪdpÝϾg?È ¾"‡ú«cM mdpãk7ØñµÜa߁!\@ˆY@˜‰µ][ELA—,†o1: •À«TÍ4V.…f)«A³‰í”CSÍÛAsÒžØ=ö‚5²V;xáOöLO(áý?Œœo +,À*Àl!$F„ bf‹¡/ÀoŒÚIl¶ ÚErhW±õvÐnµ‡¶ŠígGОc7Ø3ö›ºÅG­:([tphÑ‘W§·þ!”s-FQ¬^ùw¤MË'b˜3Ä͓ x¤Æ 2¦Ëa˜oÃ2î_…†MJv(Xí€À#0œbWaxäØbhpl6¾wh2Âñw#œ P1—×F¸¾ êáœoÓ ˆñç/ –ëˆã^Äòýèœ"†u€‘Ce°Œ“#|Š=Ìs0/r€i•#L•l«S«©Ê¹ÅtÀùƒé˜s³é_ª&Ó}Õó¯Î æwÎ/Íp­3Á­Ö÷ÿ˜àñÌ ‡á!*€s}té$ Käz’Âxåg³[w1ñ¥ˆË—!v”]kt™òCçéï:Ïszk[êü»mêm£Ëkë×WÖj×kºÞzV]gûIýÜVëúÄöÖí‘ š[áõ³Þ÷ØM¼¯tîÑ:Î÷â\BO–¢$ 5J„ä®bôL“¾ïž+oJ,¶ýI©CC×)Î/»ÌVÕvYèú"a…úyÂ:·g [ܟÄïvÈãaÂi ?zÜMx¡¹ßä}->—㡽È.ÄCw&º“] mqm{w'ô♯·šåEÈæ^d›„Ö¬QSzÉ«´ly]jâyòhÇ'½¾P=ì9]}¿G¹û½îK4w’V{ÞJÜèu#qg§ë‰û|®&ó½œxÉ÷BÒSí¹ÄF¿Ó‰ÐŸHDÀ1öv( û»Cߺjxÿmù#ºTFtf’ˆNL‘PÍÉ®ó¨¨î+à÷ÍÀ( †}߆}fö‘ÊDTDDY‡aVePY”M* X´&F«Œ¶±M0.59îÑ´1iÐh’“ÛKsÚíŸóæøÎïÞûÞ¼[ą3r •{°ªõî ×îʏ2hËÝnڒ½Ûª1Sb_›‘ǯ–ÈÝ*Òª=ËR›Dò”nïÂäa_YÒ9¿¼¤ýs“¿öËMFïÜô""ú,ÈMBÏÅ0Rå߯iç›ËPÒÞ÷QÀt &ËVÀX¹) —»²úÊü—w•¬Ñj+Š\Ù¼w›I½l—å¾¼T»Êœl~Yv‘›<³Òs¯´Q”ŸqØ;GrÜ/+}Ò_š~Ý?#ý¹_†äŸ Š¥IÓQ(MCÏÅ0 +`~'Àý4€Tƒ?PþL)í<åã•j0RmÕ|Vw•ï²¶ŠnsÙzýº’­Æ5Å;-Ê “mK +2Šd®²<…gnn½(3§Ý[’=蛚uÆ?%kÖ?9ë™_röÏ>)Ù(NÉBQj& +S¥(Xla¾¦ûᮔö^ªÁÅÚ;éÕë4í>#û80Pk=uŽL{­˜Ó¼/xE}õZÝêŠhžBg./Ûc³·$Ã1¯8ß%«¨Ô#£p¿0µ Uœ$ë÷M”öK]ñO=¡ëO>»d(NÌGQb. +wç `1ÜJ³D}ȸºP:ÿ™}'iÿh`AÏ=èh²cZUë‚4ªëÂuû£ ‹kbMeՉV9•iöҊ~š¢Ø-¹¬FXÚâ_rÔ'N>î+¿ä+D×½·£8®E; +Q¸³‹ýB³ð`¡ù4ԃs5ԃzÚ{ÐÞÑÐvHš[­˜úCìêƒje-¡ZEM‘+ócŒ³â-$u)¶)µYŽ»÷º$ÔTzÄU7 ·Uõxm©õŽ®¼è]ùÀ;ºâ­xsŠ6—£pk +bJÐs±—ñŸS” 5¨¤PþH3@/í ­ô*ÜØɅÚ.3¨êre•vú.+ìÑÌk_§›Ù¶Ù0íÐÓ¤ƒ{,wµdØíh’9Å(wÙÒØ辩¡KÙpB´¾ár_´¾þáú:l¨EÏÈôØXµÔ z.ÍÑ,^.£ì¥üV€Ã´6ôTõªƒ¢ò~G¦ ÏK5§÷=õŒ£Z)G¢ôv÷Äòâ»M·w¥[ní̳>\êÙQç¼®ý°kDûˆ{xû°ö¿¹‡µ¾v;„îaÑ=¼Ý"—z˜NϤB€ 4ƒMC”ßÝ Ðr f hˆ ²a]ȱéˆ';m$€³gxFÂЭ¸ã[õbŽÅF¦˜lÌ6_7 ·ŽèßoÚßîÒ7ä´ºšÜÏ)¸÷Õä¯êAçUÝ輺ù‹ÝÉ¡ûQA5h8Aù½”ßz v ”V’,ÚÓNs!eÂöL83 Þì¸ÓÁœ˜Óï«GŸÚÄÝx*NgÝøýˆñLÃбB㐱³U£m +›²»kpò•µÿoÑÖoíü†È±¥>^˜êÁøAêåwP~Ã1Ú?OäŸHØ1ŁØi=ˆ™±Í3LÔL{ÃÌÕµ3–…OǨ¯™Þ¥¹zZ¢ýÞtnàT•¾ÿÔ!Ÿ©ACï©ßóÄÓ·yâóóF¢sh"œD3ÁïÐ\p-»Ds8Ió?Dýï¦ü¦ã´žM¤ŸØy`Ó%6¼U"®ò lÖBgE¢ b‚•áì e”J 2Žã§L^î£ÌU++„ÊfMOe?×ãÚY-÷k7µÜgçµ]¯ ®ËeÔw¾„+ù¡Ábç©G)¿…ò«Föž¡ü)€ø‹”O+aø5ÝX¾s\ð™3ï› ¾)¯Ï‚@x+‚܊fÅ֟ æbãtÿõÑüµRýk(¿j/™¡ü˔? ú'€ÀOD·TÀå up~  ü‡æàøÈ ‹Àþñ»`÷$lžFƒõÓÆò™”±xVÊ2ûª™eúüËøù–Ñ‹‡,£§?³xOÍ{Œ*†Pu±AÊo§üý”_t–ò? ú_ˆú#Àš?øßð¼àô%€í7j`ý­X~Çóï¬ÀôŸ|0þ^¼ù@0˜ýWA÷õNx絔ÑùAÁh¿ie´Þž`¸ogÉ?Í×ÈhΓï—ê¤ù¯§|9åg|Hùtö7Bæ|î¸Ý°{`þÀä'𐠨 zhï %h£pÑ4Ñ40Ôppè‡X%ÀB0H…Æ1B‡Âo þŸFš¿ʗRïã¯Q>Õ=ø€ø  šX=àQ¾þ[ L Ìå”É…¨Cy+)ÏØhEÿˉH #[½!ý`¡ƒ¢’|E~\BAùY”Ÿpò©îÁŸSï8R¶ÙBö7”û(èœË‰ +rèoÕ —è}bL¬ Ÿx‘`B/Hb¤Ò͇Cä<ùËhâÆ …3ƒ–Ä̕A#ƒzþ jý†AÍM,ÔH`¡Z&)&5¤™t’>2LÆÈ$¹À ÚUò)}~D^’· ªã°þKÙK˜»0híÈ  ±¢]×̝ACoúÁ êl`¡örÓI©$¤!ÇÈ 2A¦È%rƒ|IþNÞü•eýJµÿ‡µƒvv :Ø2hO»®õÂ÷ Z1È[Ë•ÛX¨—ÌBÝ\RJjÙ¨ÛB: ÕBw˜®ãä,ù\'÷þÅu}GEugq¿SF…A†"3Àu +DÊPAd¨2”¡30€ ½Š€"Š, ÅBKÀ5êZWc‹îšM¢=–hbY-ñæb'œýãsÞûýuß»÷÷Îû}9(zÀy'úóV„œ×&ïq_™ ðÿßûúN”q%]e´v ^Hi¶óØh­d£e-r8hQÂAó:²Š¬'›¹hÞÃE‹Ýä"§¹¿[|Ë}mqûBüœûLŒ¼§bä?ã¸Ç–( zÅ¨÷ëïëË-Ý,ˆ˜ØÚrwýÕØ( e£}¥”è¨o•Üw’Ü?$kxo%¼7’­¼W’ü—’½ü’Cüç’ügҋü_¥wø?Û=ãß·{'¸+Eá;ÛõoKQ˜Ü’¢Á(”[Ñ'e8s21œEÏ3‹fâNóPx³pz]£8oåÉÜW.Zî ¦„÷?¦–ÿ”YÉ̬÷ ³YðˆéüÌô 0÷˜/õî2çõ†]†7\ž +¿gÞéÿÛ'\eÐð +ƒ/“‹ä‚Ëßpú@w Ç$@/#@oZûP/æÐ^õšÍzãáÏ~>+ŒóÄ]Å}ôA&ïÁÌþݙ‚;ŠÁ°¢Uï'E‡ð†b‹ð‡;ÆÿwÆ>ýë3ë_›qÖàŠâ¦ÁÅÃ)þ0úJÆ§(:©@““3Ðä8]Ñz~@ïîI¹wŽ}҆€ô<4“{øí£é¬Ç~Þ¬>Áœ;ÞÑܛs’ùߨ\÷Z&¼êU£Ù³Ùà¢g›á7'žóødÒY>£¯=ŒÏxüÓø”Ç5Ñqχ&G<ޚ~áf‡²ËÅ#z}Ñbûø!Õô©Ï\ ¯C áaˆ ÜZd×C¦ÁÅ_öÙE y§ÆèN68”=qh~¡ñ¡y&sL®ž²?°Ý¢?`«xOÀn«>ÿAë]þg¬wüd³-à¹MwN݈6]±ÞˆVÇ@êAå½`€Wal¸¯äÂ-¥†•pM9ÎG2p:ҋ},b>H©.ŽŸp ,ݨ?$ÏäÓEËÌv/¬6ß¹ Ér{ðZëžàÍ6ÝA½¶[‚öK:ƒŽK7]·ÛôÄîã`”®'ë‚QÒŒ¶kàÔ±ÐOø×/&”²ýf~ŒeÁµ%<¸«疈à¤JGT³Øƒqüý±¡Â=ѱ†»¢’{#4¦=Êó­áå–]‹ë­7…µØnm—¶‡tÛ¯Ùã°6äˆlMÈ%YKÈ#ÙªÐwÍ¡hOìšÂPÚ†’c ÿ8ÚO”7c¾¥¼q>‘_'òádâ$8œ,…d»_íÇ۝¸P¸=>Ò°;.AÔµ$ÝlSl®EGt±Õú¨ê©m‘MÒֈ6ûe—¬Y¹Ë©1üsCø9çzåç:åïNµ(#5hWÒ±0¸àe¾ï¨þ7ÉgRYp"• ‡S'Àg6°7c{gº7¯'u¾pKJ¸áFuœ¨=1Ŭ-![ܪÒY·Ä•Û6/Yn·"¶UV³Ñ©6º—©ŠþÌ¥2ú+yyô]—²˜7Li :•Æ¢Œ8н}I ڍ™ÃÛ0€Û”ù®¨)o¥Sæ£Ì1”ņ,؛m ;s䬞l/^gÖ\á†ÌPÃué1¢ÖÔ$³U)™â&u¾MCR‰¤.±Ö¾:a¥cE|»s©ªÇe™j¿kQÜ)Wj˜¼vÑÅ£3q$2 +íǝÍxêAe õµ¹ýZ!ìÌ3‡ž|gVgþlnG®¿^[΢ «³£DÍY f iâºt­MuZ‘¤<µÊ¾$¹É±H½ŽÑ©»åùIý®¹I'Ü´I7ÝrÔ/åZ52ĉȴIè0.x82êÁÙL€cTûe¿}» +ÆAO¡)tÉX…îÜ6Ÿ eið„Æ<¥q}nœYuNŠ¸"[c]ª)g–Ûd48楯erҺ䚴OÝ2Ó¾œ–‘öƒ[FÚ yF2Ä)3 3SQFFa텑½˜ +p:‡z@õôQþÛV́Ît”Ú±ÚJœ–ŸqÅó ê +UébM˖&YçgZëòòmóµ¥öڜzGMv+“¡Ù,OÕìvKÖ™¦Ö|ç¦ÖʟŸÔPýjÊ=µ†°ªÞVÔËÙµuž¼ŠZaIõBC]U„(¯Re–Sž*Î,˶I+-”¨Kª–5;Åw01E½ò¨¢Ï]#‹.“§ò¨BdˆS´c +PFFý ðŸ‘9P¾ £g?Õï­è\Nõšõay“Ô4;³Ê›fq‹ý+‚ ´ áFšúØÉéujóäÚ,«Äš‚©qÕåҘªFYdåÇNʊmLXÅ KhÅ—ÐòÇLX9:‡•¡ãâR”…— ÃX÷U—è[<^H¹“Žá}õݍí͍”kW  ¢ÕJ×8° +×(8ù­ÞüìÕóÆg´„¦¬Š6NZ™`ªjN·ˆmú“ðzŠ²NÃþü?f`˜afnÃMP¹ÄEES“²¼”¬k¹ÙºÖÉn–]6e”¦y¿¡‰Z(¸*ÈX® +Æ)J¶«Y†ŠY®šµÒØ»µÛÎž³‡ó;0Ïÿ}ßï›ùÞ'úMZðBäø׋£Ç½¶2î®â-ñc‹÷$Œ)nJójGüó%þÎW¤?ō'±…=´vß¼pU¬ëB`ý›ìÅç¯àîµJÃì56<¹ÖYki3×dé^S`˜¶ºÐgꪉ~E+§øß·bzß + ·|NXá²ùc–.‹µtsôÈ¥Õ±KÄ,i)X,1‹$fÄ=bao§y-~À¼ËÙÿ…ù¥K€UÌ^Èõè¥îÜ)5cFi(ޔ ¦mJצ–æë‹JGîÛxiüÆÉæqoM³nx$p̆Ùö;ÖÏ .X¿$lhIix^IUDnIcDðܵ‘³Z"sVIdîÊގ±5¼þ«^ç½Èüu+7×rÌ~vð'î¢l3`JyŠ*¢qE²šX‘­Ý[Q »»¼Ðslù$ïÑåS}Fn›a¾í)kþÖ¹9[÷ÉÞúVßÌ­•öŒ­Ú3ʮ؇¼-Áé›%$}“„¦—öÖ0‡=à5PÁü·¸’-gíÅ¥œ÷ÐÇʁi\Ñ&TwW›QX‚±®þãJÃ(W®á¥ wÝ£Ëwyæº2d»f3]/ø¤»šÓªKüR\;-ƒ]³ ®¾lI®úÉ6h— Ü)wHŸžp»8ÿÍÌ_Íü¬ýÏ\ɞà:½¸P¸—;`yµVäÖöCÎûNd¿²êò‘Q7F¥××Òê§j)õ3uÉõÏêÖ{&Õ¯ñrÖo7$1÷T½(cÿ×1ñf`î6àɝÀÃ.`2Wûùf6hô‘ŽX‘t$ ‰Gãá<šgSŽFÿcwüAÄŸ¥¢ÏUQÍË´Èæ2-âãZ-¢ù¢~¬Ë£ßQÑõ;"ú°Ä³§ræo`þRæ¿ÌÞ?ÍÚÿøPTÃúëYÿ@ƇÀÀ& îcÂOò¹!g‚|&Á_$#¨%ö–;`?;}ÏMCŸóO"ðü«h-ÿ…Ý°}Ù Ûùï`;+ÊÚBgDëi#ó—3~ðÌn`k/b݅ ÀÐF ÙIÑ'Ð3@à9=.›a»k[,m±03æöLøvŒ€©ã^¯Nƒ÷·OÃй^×6Am?t¡uނvUàÑÞÛ*æ3N5ïýÌ?Œev³SO §€Hfl¿o|oaêòƒ÷ðú1:w4”;p§ÓPâ¡ûAàßüݶ›7—û µ‘ð÷½-`þs̟ɹÿŽµ2;—Ùƒ?eï[€°VÖþ`þ'`ì ·½x@‰7BÍd£¾Nq”L9ćᇡðÂ7\á….,P.‘›äW/òÚ{”³Ÿr˜ùÍÌgÝÉ̎¹ X¯>̽þýoéÉØã,vŠ$'eÐhšB| öCØÙGÿ ³¿{"$(žúCË ˆiˆáJ0Ž~OÒz™ÑJÚÀcl¡rª¤÷è}j¤Oé]§[ô¾B˜ á9â þ<“9•çÈSb(T¢/âyf(ў¦¹ô:-£µTªD•AÔª¦ýÔ@'øŸ/R'¹áæ‰ÝyN”[ߛ„3?’;nD$¤_ûÒ}öš­Ä-&ö¸ž¶P9UÒ^ªçxšè<~4^ÅÆ.Ü0‰ºá#ê;ߟi¿%æG‡÷\¿÷ãëÐîù ô)Pâça™I³‰½°°–¥´†6R™ºeÙ¡Ü—ê²Ôª›ÖÔ k‹ê´¶«ëMõM´6Ñ®ø‹ÇåÿAb™ÛßN} ±Ýø:–×Fç‘Ç9Ur¿’ éꧠǕÛþ¼ºiEý`_¤¾·¯PßÙKÔuûfÕT®¾ ªÒ:‚ökíA‡µ+ÁŸi_·© !7µó!âq6Tt-¡¢ÿâ?Îô A$²þb@÷kö"q$>“空¢Ç«ï£P׏¨«ŽÙZ»ã%­ÍñšvÙ±D»äX­}åب]t”i;µÖ¨½Ú¹¨´–¨SÚéè+ŸDßÔ7Ljç±ñ:#†#Ý¢{“¼¥-Á¾T3$¯Ó8—”8t%§âúÀ|t$ªË‰“ÕW‰Óµ ‰kçœÏi-Η=>w¾áqÚ¹\wÒY¢û»s‹î„s»¾ÙéÒsÖy6%6{6&]òjHúÁû`’ë’ÄT›$>5ÝÅç@’ÌÚÓ| ·qïÌ4A²yž¬@ü+#Wӝ¸t[ZÓF⋴ñêdÚډ´™ÇSŸÒ5¥¾¨?’úªgcêb¯Ã)+ )¼¥”yLÙe¬KÙgªMi4Hm5íM½î»'UüvSUªX*iîIÒXûægk{³Öø¾›YjveVøíÎÜc©ÌÃÛ5ì SÕ°ç|w ç·cèËöüe¶òüÿmyï”åU¾WóoªË5¨é+ ão"á äJb­ZµŠµÅEŒ(á ˜„K€!@¸„k¸‚á¢@E‚(¥µÞ¸ÔjëÝuÛnk·n»³Ž³Û±Ýévv»îtÝíöì;Óad?üæü¿=sž÷9ÿsæô¾™§¤ß°NJbMH kì˜) ^ ك{x ð »ç“±s%¹Á' ð0!n%½ï&ï¦,%¤^JRÐ/È5Œ…Ä|Ϲ„RŸÙø¿3ñÍÓqS²£Á“²։ةñØùPGì2{4ö!çxìWœ!Ùs΀Œ°ûe$ ±ÿk²gƒõŸ¤|¢Â¾£¢À½Ct¸™+J\V卵WI©ó*9}V™Æ8šë=¥0úM¦TL$[‚Æ’Û˜£I=!ÇåC¡CòœÄYž=ñ2¿/ñ.ÿHâŸùÝòù]rÂ³É ×–Dظ†®…ìÃëT†àuûYêcç¹¥ÁΕAƒåt_¸˜É—fåMMõtf<ýT†ÒãDz–·#­ÀDmZLU< lbÙu²ûRíܞT¿K1#èT¼Ö¡¸)´*ž[SkI%„‡pÂ^…àuÿ^oOqÿ¡öì<ï╻ˆëÅl/Xвá¬n38u‘Ô“¹é­Âc8;Ã{0Kço×öeš™=–[º•s8íϚ6,hUO ›ÔçD ªëâzõïÅõ÷¢º4†ÂE8«Ìᷘ?d`×AÝ÷°{. >vŸ…<œÉgÁTÁF˜0즎ÄЇò“ýyjï^]Žw®!°S[ÊlÏ© mÍná6guñ4Caͤ¨&s>¼*óIeæ#‰Yó¸BCDH˜YCøá®Bâ¾>„9ÌÂΉú×°{^.p!g é0e ‚‰b ŒGP‹ö¹5&0z +•Þ†,ÿö}`k~ ³I_ZŸ×È­Óuò«sû…f털\;')ÍY–”h?ÚP¬ý[x±–ˆJ´$  |„·ÊsœÃ—j€ß¢ÿ7 èA öÞR€7‘© +Œ›`¸Lƒå¯RúʢܺKeî‡M +¯¶’ ¿æ"]`½ÑȬ3V„VÖs͆v~YÁQaIþ˜¸H?+)Ô/n(Ѐ|+)Ð1"4è‰á#¼U¾—cpуëØû.—ã °{FÆñû¸ÙªÐ[µ•ÒUµ‡ÖQyнŜìÕXžæ[W¦]_]j6›ÊBÊJj9%Åm|cq¯ÐP4*ÖÏHtÆ+r¿Þ 5~#Ñç‰0·t…„¿–¿§`²î¡ï”aç«Bð 8Y0ŒO0{©ã‚Ͳ™ÒnyÖ\³®¾VîQS£ò©¬Î +(¯Ê2UšXEæj¶¡¢™§/ïË-唞ה^’d–Þ—d”þ×ÿŠ3MD¨1A–‰ð³J^ðW%fA‡ç=X¬ÄÔÌ4 ˆÝÐÝà‡›B ­y#45ï¢ZšöÑ«ã ©Þ¥õ™~E–¼@C]S_kÍ­iäf×Øšê!az•S¬®z;\Yuù:\Yù“HUIÂTf"P› _]Ax«k¹Š˜Cý“¨?4 +`Cíz'fà,@î€Òw +;ékW½ âj0ì\ŽÅ-ðêÒnؾ$…mˉ°uY [–u”MËe”—Wš¨/­Ø©’•)ZøÊšxåM¼ôƒ›è*¡ ¯uÂËÄ]xéçpþNÔAß{&q38ÔÎ; ¾p;è@Ä5€Í7h~ËD·‚@t[Âۛ ìNîDÿnðî¥÷^>pîWû¾ BïCȃóÀzð`Ýû…u‡P˜· •y“ÐÖ2ƒúcc}8óÜ»y3€Úi‹¨õtïuÔ`ÓÑ€ÐÜ ðcOxþØàÿ©ü>ݾ¿û>øñùÌޏë;x}~l‰Fຕ@¥öéCqÝ šè \íÙÖ¥)û§ÛÀö„±bðJî‡çr:žÉ£P-gã±< å<ܗçáž\„;òJܖ×ᦼU¶ûpÝö8®Ø^ÃE»'¨Ð 霽Î:é'¡8óáÅø^vMm ó-öø,Uîò)QîôÙ¬Úîó½j›ïiÕfßÛêM~/¬÷šµ´æ-ß¿-4ŒË©ÂŸS§Ù۟*p£µ•-lQá犓­|PÞ:‡Ma(ó‘öú÷UìöOUìðÏ°ØfÊRn1MPm6MW—šf«7™ +l0­Ô¬7m°\kÚeYbúÑêþ×­Vø×h—ù ë%µ´‹? Z+jãs¹¹Þ¸À©íl gÚXâØgzjûö~Ší:J[ÛEJ›ã,6PnLW­ ¡. «)˜l¹ÚœkµÒ\ ]n^b½Ô¼Æf‰y«\dþ·\h¾,Ï7WÛÛ9µäüaSßÛøâsæ\ NqÙ+çõH +eíuØìŽ-?Á?;µ—Öw +W”tŠ±XÝ1Qµ¢cJƒe†j–tÈ´* +ÎÖO³Y4KžTh;7hµ.?¨Ô~vP™}^P…}nÐ#ûÁÂ~z°Ð‘]N-Û:â3.mµKîžûŽvʺ{:+°=TFiXC¬÷Eq„YZªX¥, +Sv–fU6ÌzΣåY_L²ý.4W—:Ï~FÈrǜ ú©!{œ¦„œvšzßiB¨ÐŽdOºú„¸Ï%îãâ¹·Ï´•Ÿ7uÑbM7g¬ŠjŽ¥ÝÛH‹ºwP,ˆêª,ˆê©ÎL´Ì떢ÙuˆÍŒ®£lsºdë¦vÉq˜‘¯Ÿ±Ø);|­a\øNãØðÆÑwŒYo _G=9’Ù×7YƒŸ#Y.ù{{3~,°‘ŸK¢`E=÷ôÂÂ^&© W{Åì^•ßõŒVo™Óc€vJ4yRôp» ÝÇØÓ}²ãب<§¬ÈBcfd±óÈÈm.#"Ë]†EÞtɈzëғã°HáPç)Ç`e8p’¹ˆv$pŸÈøñÀŠÞ(ŠµÇüxÌéÓJÊë¨ø¶O¨2'>R=9®·åÄØ$ëìØAòØÞ_ٍîõµCfÏ ú‘=s Ãcæ;³ÊeH¹~ÙãˆkZL½tN‹r"}zŒp¬ó˜ýp©pŒùïcü-µï4CJb¾ó€Äe®ý6¹%%pë›p…j\ú&#’„éëÜéÌù€}ˆõßÎø¸åYI ¹%Åû)֘šêŒ‰ƒ›!;Í_3øÃT#R£4ƒb­† J²IOd—úÝeÕô•†á7 1P’°„,,.¸V°:,õˆU±‚HÁA@ÙÙ*›‚`-‹k1X«b]Q´êQD˜Îè´#UëѱêèØrԊÖÝ:õÎk+ڙsüãá—@¸Ïw¿ïÞÜûŤÚÆ,ÈÕF/(ÖGFWÙύÚä8;j—SxT‹ÓQWÈc‡ð(a>_è#æ ÑöÐÅ}xŠk°…ùßÏ+èö$ö|dmýŒ¥8Á…IZä%BNò(If²—4-y’YrR€"!1Ôbaâ\eLBŒUt|’Mä¢,»9‹–ê"VÂâ6:„Æíp ‰kv +Žûž Aˆ>0^舶‡K¼úgÝųô×f²ï]̐¼ Þ¹ù>-Û)9½‘˜;‹r=$±¹ãeѹ~òȜŠ9Ùaّʰ¬…êÌ4› ÌÙ$Khzè˜Ç:°ö œw=}ÕlIVæ…|¦²ï(fïYbŽ¹¥Ì.sFx™ ÂÊ<%!e¥3˦Ê˂äÓKÃþ¥Q~Ë-'-ÏVy—[M(Ycó^I­­WÉÍؒSš±Ëîڎ]*l½ŠH!)6=g°;ؖm^¬!ËI.ÝI¥À¼•ì}*$®´BP•#«† `Õh¼¿ÊKâ¿ÊWê·jºlÒªP3Ÿªyò‰U ïUeXxUYŽ©¬RzVnQyTîW»W¶«Ý+î¨Ý>j·„•Û +aå^öšcÜ{™s½Æ2 |s@Ò鎭ÂWëÙÿU[`ò |7ôƒq8¼î˜P3ãk¦HÆÕ̐Ž­ —Ž©Y ó¨I‘»ó{6–+Þ1n2w5î5w1¶™»l¸mîò‰xkÄ:²VXŽXóšƒ\s;Ø}FïZ:K+œ* ­ê<ºƒÙùmÆoÆÔªàY§‡G]¸×€[½þ\?£MþxÇ,iš+q1ÅKÞ6åH‡™VȆšjdCL»Í›NÈ×ß2T+䃶ˆ^7“Ï„¢‡=¬{ýÕtW¬ +èMÝDofm¦Õ·žÛ×]2 kPãO  Ý3CöŒÀུwîõǀÆPôoŒ†scú6.CŸ}ë$Nû¶K÷ýEâØØ%qÜó\ê°[Hv ™ÃÎ×l£#ç½z÷ÛÒ,zÒaèõÙ ¼ËžÔu?0ø Ðç°†&5ôM:èöƒîè0h›Ý`×<šcþ°=Fâ`Ӓë–rX·ÖBÝz„\…Uó3X°>"$d3ýë8÷2Î;÷sÖà `î. ¨ðý’ù§×õ00è(лв]µ:!‡e› +mv0oë EÛ2 +½NŽƒü¤?ÌÚÃ!k‡´½’vN®}'Ðñ5Ÿ·‰à) i{Mõ'܋Ÿòû¨HÞDrÎAôúÒû.½.ô ×ñ iT€ù·€ä¬5/Zà\àüà/Ç_\Jy¸ÄCð2¿h/—ð`æ¯pB—/ðù˜ˆÿ¡‚뭐yOåÜç3ß3ÐO¯çWÀÛô:赦×ò;ÀìŸàXä_à*ã¸Æ8®kx!vº7\[cÛŒ£›‡@77þ€»,ð]Nêî¿ùþ)ŸâKéOgÍ£p4“þx0mÃځ¾Ì=½jz/¼×ȏä¹I~"ÝrŽ©~¶æÅT<ì<<ãEùWÊÏy ~ +n:ÁÅ-ZÉUòð‹€˜C@(ÿ4™nOÎyØiÖþ×/ÇqCù¹.× (Ï+ŽŸ÷Ý+»ì»7&‰·FÁ‹¨,(,ȲܖEvvå²ìrY–Ë‚+  "²ˆ.!xCƒEƒ—h¢&Fmc›Æ6ÓIf:i:MS§M[§vÚ´}zâ˜é‡ß<ï¼_þç9çÌyÎ>|e >X6·—ÍÂÍeà½å7àÆòpmÅï©Å•O©K«½€\@Îÿ$” dê‡âXÁqû·u,x¼FVÊà‹e«àÓ +øÙ*üøU-Ü]ï¯)ƒ[kkàݵMp=Øï{©«ÁýÔåàaj1d‚ºrŒºr–¾r…ž_w~kÝoè7CŸ°fC ë$r"”°ãùCÈkKãä©GmŽoµŸ‡³áWkðqðKp/4 n¯RàZ¸.G˜áR„•ZˆpPçÍÔ9E;}VÑCÏ)öÓg~Ö¬â(ë”b–}Bq‘}Lq›=£øŒ=ùWΑHØH¸ãÈ둄óCHƉ£W‰Ï Ž×‡ÈG1÷7rá}…®G­Å͛`!:Î)3aNi¤Î(-Ô)¥>¡¬§)w²f”ìiå^öQåg2z‚{8ú8w}Hca klœ!Mw0¹…7¼›ßŸ¼WЧ>(ìU ìQϊ¼ê·™.õ=¦CýӞüOQ[2 ô$á÷<ê%žbÞ¿Æ{?Ì@ω¾ïlÔÇsc9•Ê…™49Lføv3ø3©áÌ ú@fk¿ÖÌîזsú´5¼ÞŒF~OF«À›Þ-ìLß/jOñ¤ïJ[¸Ó>´¤})iNÿ‡Ø•ND„"BWÚO°þ_¦àz“p}ßbè·0–éL +&tRݱ†õ‘p@Gùô©tŸ>›Õ«/`wg[¸]Ù6^Çg@ێÂÖ¬Î@wV?Ӓå»t3ÒFݼ¬^wKæÔýZV—õw©#‹ˆÆ¡#"$ð9põÁÜ7\Gß·`Â=¿` +c™Ðãži`à@îJ0†CŸ1ö“)¯QÇê0æ±Û󊸞<+ߝ[ВëºrÚE 9{ÅNÈÄa˜’ÕޒWÞ•Û ŸÉm†'2›H1ÂØõD„>ãìÃO1wŒWÌè9KŽ¡ÿ›(D}ü7˜û +—A¯) ºÍÑÐiÞNµ›3X­&{§ÉÄm.,ã5VÔ4ë +ZE5ù=âªü!©Í8)³çäåÆëAeÆ_•¿•—‰´ÌHÄS–GDÏùÖá瘃[xÿ·qõz½ßž~\ñ__‘zŠ_‚Î’h·l‚V‹ŠÚiI£]–lvcI>ÇYbá9Jl5ÅN¡½È-ª,òŠ+̃ÒRóaY‰éLP±éZÙüIÙôXn6i‘‰H¦¨ˆžó;¬ÃÌû Ô\¨À>´bð<ˆ±ôaN¼¥<Ø]&OÅp[#¡Ùºj´jhg…Žå¨ÈãTWñìåրÊr‡°¼¬ETZÚ)..š-ã²Bˬ<ßr%Èhùù‹Üh!Òü"A˜übÂÑ3¾À:ÜÇú_CÍyÖÁŽ~ ρJÔÇXÚ¬,pÛ¤Ðlÿ4V…ƒ³:–rT'ÑÕUZ–½*‡mµ›¸åör¾ÅV-(¶5š+w3•û$Fë˜,×zRn°.Êõ֟"–é+ˆ‘Ê ó=¢g|Ž}w뿈šsµèwj†«Ñï mO žµ 8+ ¶n=T;£ÁæL ¬Î4º¬.›m©+à9,<“ÃPPÛ Ì«õˆrjöŠ³kü’¬êã2]õ%™¶ú'ȟdÚ*"ɬ"âL;atv"Òٖxˆ}wW΋¨uºëàD¿Q‡9@ZzüWÓö¦—Áê +rW”ºâ¨—†6»t¬BW;¿©ˆ›Ûdåšê²ÝB]㑶aXœÞ0#ImX¦4ܗjêÿ(IqqJaRëˆ(Õñ‚Øw×1ó¨}­€¿ û  iÀo{ ú7,»dPÜú*˜=áP艁|Ïv*ϓAçxô,}k!;«µŒ“ÙZÃËØՐºË+Ô¸‡Õîif»û<“è¾Ë$¸1‰-ÿ%6Q¢‹nFÓw1—±s¨?åFߋV q#µ¸Ž—¶˜:(0v2Ûµr¼¡ ÷n‚ÝñÕ­¡2»ut†×H§yKد£ö6q·wuðU]ûâº&ۺΠc»îc;¿Æîþ·0¶cۈ`«ç7±ÿðγ€qÔëGv#Mí¶Ôï0ôèú±/ÒûWCª/R|JÐøA=N% è©DŸ‰Vù*Xq>';Öçá(}ýÜ-¾Ã¼ÍýgyQ¾Û¼¨þ¯xQ}ßñ£z ?jÒó‚«Xó³xßc^€‘.€=È.üv v)jçõd¨Ґ0Â@üÈ+w(¶RÀV,Äú“ Ư…èÑ\Ø2ZBm­¦6Žî¤þ^V¸ŒµÁ†µÞÿ{½ÿ·¬°‘±ÃNØrà1糨{¤{íi'҈ߕ>Ìjï@k¤ˆ›Ø<ɃȣP]S!> ¦·ÂkÓjX?­ƒ°7þÇvy@E}eaüûOpè}P,ˆ ƒ…±€ +(¢q]×äèÑՠƂ»¸ADET,ŠNPXªÔh{,G$1®qu]{ÖXëۏâîêÙÃùñ¨ï{·¼ûî‰@óx˜g £y±ägΑڛ‹%_ó>É`þQ2lú]f(2C¾¾ü/•)€™šë©·4‹yÀõ³ÕÀ赌A.çÏ| b3õ‹8~¥Zø–9ÀPæ Ÿrx—ë¼;<+"áQ1îír\é\—Êp®4骎Up,§2!9ýµ’VŠ3y³™‹ÔLYÇ»HÝ?çÜÄR·O VFý* gSÝ€cµíjõ°¯u#`WDÂak‰„Î26–1ÐZ¦CcI…Ú²*K%”–£\ï@]+ ©!ÕÚ=­¬bÐ×ԝC݉ÔEݸr ß6À¸‹úÕÔ¯Ü÷_¶ßÈ ª×AVï©Áhð6#GØüádeáµò²Y™PV:ÒÊ ¬—ÉSþ^¼Åú ¼ ÀjO-ÆPwmä¿ë€.û߃€k= ?Øä§À†CIl3ÀYwÒ8ߕÍÓF6eل\dáiâ…kbR5љß&·É+"þCV!ïâV`zïmþÈDQ7Œº+à|°; ¨ÎRûùžü@.óWtl†õlÈ]€ë>À 7Ù þLÜb¾Å|›I›I}g'á&w!¯‰h!…y6ƒ±·Ní(ÚF{;Q׋ºŽç]# »DÍÉuòOr“üLhûvÀ/ôÉCÆæ±?ð[7à›“çlŒžOåð ÷‚1yI#_ҐW÷Éã’èûñôûh÷Úv<xòÏôÔÕ¼ÑmÖ¼EîšÁxDžßÈ3‰àµ=‡—桍°i<‡àÃ,øðæ†`ÐÏ!Pq±¡k¡6@À‡ðkA‘?‘ $‘Ì#©dYM6RDJÉvRK¾!§Éuò/¼Æ+~ˆ·xIžµ!쨭ó„PpÎWø’®¤;H†“±ä32‹$“t²‚䐍du¶rß +¼À.ãž2ižà.ó'øW¿’Gÿ¡§¶½ „Æ™ß5ãÑæ‹H?2„|B>¥N"uæâ9R¸kC°’:k©ñ%÷2S£„VoÃÔà>ê©~ŽéòCø„ŸÓG´¬7ßA8RW¯‡°m!ç +—¶˜¼Gz‘jŽ ÞXjMf|ÎtX@Tjdⲩ±žûçs¿"Ü@#° Ç~¦ðIü ×p‰'ûž4q7Fï \¨ëhK_h®ZGž¥9&ŒÛ‡ÔíGÍxê}L­ñԙŠ0&ד«HÃæÆeæÆ%ärÿM¼ºÅ8O_œ…ߊSŒÇ žø8£t”»Z%#Rëúá®ã9”ôST¯‚hgGŸ8ã¥ÚåA´¯'5£qUŽË²Ñh’%à‚|:ÎÉçàŒbN+ÒqJ±'”98¦ÌƒUY„ê +4¨jpHՀƒš&|­½‡½ºW°Ø2cíjÞAxQŸeN¸W^/'žëíñÀÖ7´~¸¬}6}pV7§lGâ¸ÝXµ›ŒÃö3Ñ`?‡ìã`»¥8Ðnöës±W¿uú2Ô:ìAµC=ö84a‡ÓT9¿F…‹@Y¥ÎBzƒð¥¶7ˈ¥†Üðn.yJ\µ·C£½;N;tÆQ§î¨w€®Ã°ÏíÔ¹GûT{$a·ÇìôLÃÏåØ敃*¯|Tx£Ì{J½ Äç¶îHfÃKi“¯ +IA3!å·!üZËÉ=–Øk,÷»ð `™;孁ÕýýPgè†êö}°³Ã l÷ÊŽcPRÿé(ñŸbÿdl H—ŠVJæ€ Òæ³TX)åÖIy'e¹~’­ëôL–ÓYÈ֐՝ÞF¿R÷Kë…0à©Ÿ3Oöv´Çî@olë„ò®=P4[ÞŠ¯‚Gasð8O–òƒgHy!s¥!)² !™²õ!9²µ!ò5!¥òU!Õò쐣ò¬ÐëŠe¡OKC…"#TțYò?¼ þ]êÿÐ8iâÌG,=Ùc~ÀÙ3X‡²P7líó‡a(ë‡<ã`äG`½q´´Ö8AZcœ"[eL’eʳŒéòåƕŠLãFE†q«2ݸSù…±^•~E•þXµ(\(›IŠŒ­< æԝÏn_>ÿ|rë8nï”õŠÃUØÜÝ ù=ýÛ+ëLXcŠF¶i˜”e%-7•eš&Ê2L‰òtÓ\Eš)E‘jZ¦L1­S-Š0«FlSϏ8 ™gjÒÌ1=ÔÌ6 õ,“Pe ­<¤½W{ÓÔ>ÀÙs× Î:ÑÀW|j +{KÈí­ÇÚ¾>X„¬¨XÖ? +ýã¤ôþ#¤´þ£e‹£&Èÿ5E‘•¤\•¬š™¡ž¹F3+²Póyd…vfä>›ÄÈó6Ó#h§E ÍÔ(¡ž)Tm(›¹O|ǧÞJíºx Š òbØcòç«ûÛaÅ@OdFwƒ˜0¤ÅöÅâØXiQìG²…±£dócÇÉçÆNR̎™¡LŠ™§š“¦NŒÎÖN‹Î³™]ª›mÑMŠþV71úž.!Fh¢…†¨‰*a`+·"Ú}ˆÚÕÃÙc“‚¡œ·âØcòËbuX2Ø©qþHÒ Éñ&̏(͍—ÍŽ)KŠ#Ÿÿ©"qÈ4å´!³ÕSâR4“âVhâþÍu™GEyaüùfav .D‹&¢è‘¨(Ú((Š"¢¬Ã0Ì ÌŒÀ° (‹Åq¡âh]\Q0.cMðhš›4rZ=&©Ic\kmŽmš¸&úõAÆäœþñ;ßý8Ã}îû¾÷Þï}ÚÔyI¯ir“ŽjIŸjíI·4ö¤Çj{’¨²'ŠJ¢xÊUîƒ?3ÝÔ~ƒíF[Ÿ6¶aëØþ>ð¤(Ñ ˆº´Ô¦‡£Ú…*C¬PnH ’Òt‹´$=WV”^PV©ÈO«Wæ¦5©úMß¡ÍÖÑYôgÈM­YÿHc֋*‹^TZREÅS.qžaŽQû ؑläZVóÝÃuÔd¨ÍDµñ9TfŽC¹i*ÊL³—iPlJ“š²¤N“]–—Y(_˜Y®°eº•Ùƕj‹q£&˸K›™ñ†Î˜qZ—‘qC›‘ñ³&#CT ¢Ò¢—‹ñ}mðÛf`6½Ž•9àx%×RÏuԘTfõÇbK0ʬcQb‚¢ì™BAö>dÝßbüûJxŠyhêI%)à{Ûrs™ãâ~0”AZy(R+‘R‰¤Ê9H¬LT¦ ñ•I\Ež4¶¢L6»Â-ŸUÑ]Þª˜^¾WYþ>ùJ¹ø®"r‘¨ˆ,¢J‰«ÌÁáB “­÷Æ2`y)PKÊ8Î]LßWAß³H^ªFBÍ@̯}ñµa˜çž‚¹îhĺã0ǝ"ĸ3…™n»d†»X宖Ns/—½èn‘O©}M>¹ö¸<Âý…<¢æŽ<¢Z”G,!U¢|²Ÿw™óÔ•ÖÐK½REŠøžCíôZ ±ŽÞ§AŠ˜ßõÃÌÆ!ˆn…Ë&`ú²©ˆòÄ Ò³Sy_ôX…)§á©&z%<ë¥ã=Ò<ïHÃ<ç¤a?HÃDiØˤþWÞd®÷Tó<Ôp/.¥ï$‹H.µ³¨L›6×ÌXEÿ¹Z…É́ˆhƤæј¸f"Â×Db‚wÆ{ñ‚׈0¯c½¥ã­B½^a”·]é}KYÛ#„¬ù^±Z”Œh"«DIˆŸ®*ލ/ë빩¹„ò=»‘5XÄ7Ñkè¿Öã7҃µhºy Fm†‘­cÒ:#Z#ñ|[,žkKÆð63†µ9ñ›-Õº¥ C¶ló[|¼åµÞFP‹(m"Ɇ>öP{Û +Þ Œµ~÷u´†ÆÕ@‚ˆÙÀø7hYGo†· ڥŠŽ$;Fc@G8;#É\<Ó©GÿÎôÛ] +Ýî² ÚÝû î<Mç hw=†n§];ÙÑG;õ65+¨¹„P×üÖ`0‡ºÓ^ÂہÐN`Ø`ð~ — jŸŠCp(òC¡ùÂ!ñEAðÍãeÃïãaóqCùè1}ôº¾£ä›úÜC"? ¤«6j®e¬õ¤”º¶6րñÆí¢v÷1þ.êû€Aoý8•ê]@8¦âÅB{|a#üÞhBû>›Ÿn~p»és»yÀ»™èn±ûuòù󘈿°º+¶2Œ7Ÿº™ÔÏXg&Qs45ƒ©9à=@{Ÿ?0ä# pZM¸Ž¹Ž3ÁlF{›ápà3®ã,?Ægyٟå!ïa±{(pöm>/’»‹¿Ð´÷Á. d/`=Èf½CýãÌ70”šÔ§É'ÔþŒü…ü•œ€óJà‚ø"¸H£ò5›ôKãË\Ç~Œ®ò¿ƍ ¿Îb^?EnûD|B]kÀ4åR¨CÝIÔÅXŸ=ÃÚ +(züšŸ“¯É%ò-¹B®‘Rà&kóOæä»ÁÀm•ïÇ?rwØÜåÞ¸÷p¿…0Á>&üÇ?6ê”2«j4âhÇGìÇØLü¿AÜãšÜÅI¼Ã¾x×qï1’Gx“•»É¾ñPý¨ÜR*Ǎê+°GÇsMµÔÎ†PSÇÎ20›l<@ÿ±?F-5š©ÑAÕ¸Í½Å½ÉÞ¸Á5¹ÆZ¼Á¾xWXwq‰+0"<Á°¨â¢¤â‚üMTŽ8UK¾<á¨yÌX>–Ʊ¦þÌsî ‹qW\†·¥ ¼%åá¦ìÀu¥W7®hZpYӉQŸ\òéňïv ûâ¸C8?î ΍¿Œ3n§&<ĉIŸãØdGÈáo¡N¡~·:Gܧ¿ äøӊx0nîúâöøù¸11W&%atrF&Û0¬-Á­ 絜õóâŒ_Nù­ÇI¿~÷GýàHÀ) +øü^ø†?Ç` Š½STì!»Ç|†:ãlGæ˹0§§¦áä´›V„#ӝ84£ߛш3Û±æj웹 C³v`pÖöÌ>†Ý³‡10ûvÍù%¶¿ô™°å%Uè'›ŸÓ÷œ¯8V? â¨_LýHjóȹÂ{ß<µ3&â̬)8>'‡çÆàà¼$¼ör&†æçcp¾{T`÷‚: 5cgP'v­Ã¶ ~akð¡?øÐ|^è ¾.l +ù©°>ä/ÂڅªÐCք|“/˜÷¨û@܎Fcy¤GÑßñØ9¤Á¡ ¼2ƒ¡á؏]‹Ò±cq6¶-.À–ðRlw¡/Ü#ô†· û… ½Âºˆ]bOÄ~quÄi±;âŠØñ¾ØùX\ù/±=R}FÄÿø4”ÇõßåX¿–Lk¡§6c9ì£ ×b r&¶G/Ėú–$£W—…º|¬×Ù±VW.ôèj…Õ±ÍÂ*]§Ø¥[/vê¶Iº!©-ö„Ô;*·Äޕ›bÿ$7ÆþSjˆUÇ=cèžñ˜õÿ·;Þ3Ҙ?Ÿ’¨Ío¬ÉvÝ$ô/ŠÞ¸Ø°, +ëôX“n}ºô…Â+úRa¥Þ%´ë=¢Wß.¶ê×HÍ ›¥Æ„½²'á¨ìNQêô?Rjô”jýWrµ^•\ ÿEãkpŸùß4rýiӊ 2–)ô˜¬I¯~<Ö'¾€ž¤yèNGWJVRÑn0¡Í/´B³¡Bl4ԉC«ä6¬’ê ½ráUÅe8¬T.j* w4e†ß“(Nƒ*;STéë<Œ§ý¡æUڍ³fրög€±ô§Ó_±&k t§ú¡3m6:2BáÍС،&ãr4s±Hpb­±F¬66IUÆN¹Â¸Q.3îTJ3jJ2¾¯qoù؍5vãߕâ U~Jº*ٟóëDÚ2j^¶'í9¶1–MŒ¥‡5é2ŠèX®Ekæ 4g£Á Y·9µæl¡ÚlªÌ+Ä +s•XnöHNs‡\bZ§8LەbÓ~M¡éœOé¦Íô[«éKÕ¤*Ö,U&’5S•lä#æú5/åGòè±i763–µŒ¥+“w.Ö§Ù< 9Sá¶ÌG­%Õ¹ñ¨ÊMEe^–Pž—/8óìbIn…èÈuKŹmranbËݪX-û4y–3>ËuŸ˯Èš‹ªää¨ò–lUã'¬ù j^,à^°±hË71žnÆÓFÖȘÜyP“ÿ"\Ö¹¨´-B¹-΂d”,NJ‹`/(Š +œbAA­dµµHy¶Õ²ÅÖ¯dۆ4fÛiŸ,Û5ŸLÛÏ}2­ÓdZU%3_•³ÆÈS¥1î1׫Ô=W̽H;¾µXÇx:O#c©ã³ªÀåEþpÏFIñB8ì1°Ûõ(r¤£Ð‘-Ø6!ßQ"æÚ«Å{“d¶wÉYö>eyñ &£ø¤&½ø MšýCMZñMZ‘ª¤ªrúª4Æ;¬ùejŸ\ì¥ï³ó®A¼Œ©–ß+ùÛéáX¡EqÉ –Á挄Տü2r˲S–/d—ÙSY¥˜élŒÎN)ݹINuîVRœÇ5ÉÎ×5IÎ4‰¥Ÿ)I%ªœ´â)R’C•’ÉmÖ|„úGiÁJ%¬i"•¤„ß‹ÊkÅ$äUN¥jrª!Û¥ƒÉ•„,—Ë]]EBº«LHu¹ÅW»”äÚ é]ò²ª£r|Õ¨纯ÄUýUŽ«Tå¸ +UŠ+W¥ø²gÜ`í/”³*¸øì!mÄMœüVXEÏ] ˜kÇ#«ÎËݳáFz}Òêã‘êIEŠÇ„d‰žAï©–yZÅ8ÏZ1¶~‡´¤þ°SIŠªOŠrÿYŠªS¥¨ZUŠ®!ÕϸÂ\ÏR㻤ÏŽ@šH5ß5¼÷¹¬ ­IFJód$µLEbË<è[ð¬u ⽉ˆóf`©×‚X.ào¥ím¢¼ÝB„w«¸Ø{P ó‹¡Þ»bhë'bh‹*†6‘FU {ί'ê¹ÔZÏëa©'å|/¤¶¹™ú^@ß,í%¯ø#¦k&¢» jU8"W-EĪd„¯ÊÄ¢n+ºKÿÍu™G×|¦qüû»‰X²YĖ•,–$–›&ni‡©žÃTUk_Šp’ +"‚ˆ$ÉDäԒPJ‹ ÌÔ2‡ŒUcÌLU«ÆÑÚjj‰:Jû›Ï•˜:óÇGr#y¾Ïò¾Ïû<꒕¬È¬ …g³*°¬]FhÖI#tÞM#4Ó4B3`Ži M7-a° ­*tŠfpY Sa*ŒágCÑ~mŽÔw®·@Š^dQÔbOEäú*<7Ps#Ô)7Fayñ +Í믐¼Á +Ρ üÉ +̟¥ù¹jŸ_®vù;\yß)`ñÏj›cmAvÕ3yfó.°f ™øüN5`={e!ñ/–bò¥ˆ¥Rpqµ/ñR»?µ- T@i„Ú”ÆÊ¿4A~¥äkS>ö±jmŸ¦Vöùò¶ÛÕÒ¾U^ö#ò´_‘WÉOjYÌQËx?‹¾„Vv&g¦ó¨ùìžÙRÿ\)¡ý"ôKÑ/“Ê¥Ök›ÈËá%O‡¯<åî‡XµpØÔÜ1PÍoËmÝ$5q¤ÉÕQ ‹cäøXFåç²Tޕe­)× +SMÖ4PIŒ…¬Yh¦Àx>]B –I¶öϕRä)ˆ51 JjµIòØb‘Û¶2¶1 oc­†¯êžR P ¾†ÆRC¡k(b ÎWovÌm7á)˜ÄÊ +é ̉äzørjÀŸôE·§ý èo–ÚTKÞ;$÷]’++«>vöÛ½ Æûðc~ìǏZ†Z}-Í¥–b×b¼–jÀWüÎ#0ÿG±çièŽ%Ïo ûêFɺUê‚ëÁhú$µÜ/5?(Ÿ ÿGøÔ ~ŏcäã¸Ã0ü§é$~œb9E³¯ã¢×Qà:ꢮ¾‡_À|F^}ÝIÄ;l 5à×âwKÝö¡¦ÿaÉ M·ch’JV±ä0ÃøÌE:Û\:Ç¢tž%áB{é ôKøñuàñ¹Ìå¿L‘/¯—¾©…‹ðÌgds2yý¡4]Û!©ûòTò=AíOI.§õÎÁ?úH+‹˜X£¤«MXPÜ¥ëääËʆå»øq‡ù>gãA*K‡»ž×c¼þÀúzM#ßc©ï/ñv?Ž>º>Äé~Ûçá_zN­oá:p´tîÀp0©›JÉÉSjc² ˜ Ç&C’ÉÙ0¹ð&51I¶I1Í/àgÀ³ה_ã÷q0ބ10fÀXùP+` ¬‡-°öë6ПÙPŸàðOl°ùésÂà&\wî¼ò…V´†6=  ‚0’a&ÌÅ~¶žj ö‹±[†ÊZ=ÒìW«^»u_Ÿš:Rt½ûúž¿zÎmø®Àe§.Þü랍ø4æ¢+ÄÃkÄ4”xÆ “ˆF +)OÃþ<ì/Â~v—ë–VW%qmÒwÚ¡kÚ§ë:Gç6¥|"gÖ¿lä"\€óNš:u›ƒ[ãזÏjòDÑì‰æ+D1ˆ²¿ƒÎx4¦bº®j6ö³°Ÿƒýì–plVcwv·R…õ¹ø+—è4ñgý¨SX> ίu/`¶@Ûàhȉ+¸“ËÖÄ„f7rÞ}­!ø>wõ7%é,gãŒÒ¹¢YØÏÁn!öK¹¾ktœšÕvÚÈ>Ö <¹¤ƒº«Z¬€ÚÿäŘ® >üâ<ÖrÑ jr…sqQÐëAöKP_à ٤÷ùŸ4Ö*—3ZïzC·Çªljjm3S/`ÒRÁ _Z€-ö +¿N¸º§¯!Úë­ÝMúh§Ûoµ½Ùªn6\[›Óæ‰ÚÔbš6ºÏR•û\­wϑÃc™*=V©ÂcƒÊ=?ÐjÏCZéyF+¼n©Ôû©–{ó>¼@<¡½ÞiGK ¦†ÐþiùOó)r÷ÔN϶ªñ +ז–½´Ñ»ŸªZ½.G«¡ZÛz¤Ö´ž rŸ©Zå3]+}fk…ïÙ}—¨ÄÏ®b?‡Šüj´Ô¿Vþ§•ßæºrž(§­©EÏ hà!úפϣxzº ήA{ÛցgÕ¯™6ùúhˆ*ºkuÛx•µë/{ûÁ*é0LÅFkYljZÚ1I©Z˜©¼ å+'¨BÙÁ[´0x¯æŸÔ¼kÊ }¬ŒPº¤‡üÊÄ~©+OQéìˆfç×uø²6ÄPy ·V·WIH¤–…õRa§¾ZÒi ò:ÑâðáZ>NÙá‰Z‘¢ù³5/bæF*#r•Ò#7i‘{ŒYQǍԨ+ƌ¨GÆô(ÓHyNd7xòÏñ´‹gß{‰=Ê6ŸWvg¾"7Å*Œl£¼.aÊé£ìn ZЭ¿²ºÒÜ跔=Js¢'jvL’ÒbR53fž‘“g̈Ya¤ÄTïÅì2’c?5’b/ScSbM#ÑI̯\%î¿ ˜ñgûˌ\}¤2|)â©)ˆe÷Œn®E1>š¤¹=»*£—Ué½ú)­÷@Íì=D©Öáša§éÖ)šfn$[çIÖcªu¹‘huX&Åí°LŒ;by7ñqÀ´Œ‹3qÖFz›ÆWhD{ÿo¤ÍŒåýˆÏù ìqÌÚ½]•iõVúK4+>B© =5#Á¦”>4­Ï`%ۆ)É6ZSm“ŒDÛ{Æd[š1ѶИ`+²Œ³UXÆÚj,£m‡\FÙλŒ´Ý³Œ°™ ô1g$˜Æb>†þžùªÿå¹ÌãªÎ0þÞ{ KHe‰ KÃ"˜I&ËL2IfÂLB&Û$$C!² “"IT¤BR, ø@¥!µ(}¤Âc©ÐVª«V­Ëc] +B­ûÒÛ_Hê¿gî½3sÞïûÎ9÷|/>ƒ¶£Xî$–æEø êҐ®ºÅcU›8E5IsT¼@UÉ-wdªÒ‘« +G@åŽ2#èXa”:ÖŎ;ÌBG§YàØnæ;ö[yŽc–ßqÎò9.YK¶¹$¹_’môqgœìŽø.jÀõ]ÄÓL,k‰c ­a­c¸ªS®UUê +¥ÍTEÚ<•§'©,Ý© Ó£g¾Šœ¥F¡s¹Qà¬3òëL¿³Ýô¥w[¹éû,óq+Çù'+ÛyÑÊN·Í+¤ÙfNj?gÑ8žIËK+¼ÝMÍuñÜJ,«‰£†ÚT¥‡©ÒyÊ]̈QifœŠ3©È¦€;Kn¿òÝEFž»Âð¹k\÷m¦Ç½ÑÌvo³²Ü[™î£V†û¬år_°\™¶ÙGF¸ú9Æ±ÖlƒMÙԀxꉧ†º,'žr÷`•fE¨8;J…9SU3GK= ”çqÈïɔϛ«\o@^o¹‘ã­1²¼Mf¦gƒéò<`9={¬4ÏcVªçy+Å󱕒c›}¤fCV?§Ð8š+õÀ/žn¥-¿…xBÄRÆg±ÇT7\ù¹cå_-Ÿo–r}óäõ'Êãw*ÇïQ–?_nÐÈð¯0œþ#ͧ™âßb&ûw[Iþ^+ÑÚZìÿÈ\ìû¯¹x‰m&æàµÍä}$=é—î¥o…†%ô¹PF<…Üçó/o¸¼ù£•³t¢² ¦Ë]§Ì‚eRå +d)=àWZ X)å†#°ÚH +´˜‹›Í„À.sAà°x>0ã ¾7ã—Úf|>äÙæxŠü°–²hÃ×A,‡BðóeVVQ˜2Š#å*ŽRzÉT¥•ÌVjé|¥”&)¹Ô¥¤`®ƒ- +V(!x‹± ØlÌÞcÌ î4o2cƒ§ÌØÒ÷ÍؒïÌØbی-²Í¸"ۈ+´cèì/bOÒ~o€&ôj`×ù<÷–H™´ÄiåƒäX®¤Š1J¬˜¤E•Ó•P§…• ZJU|([óCùš +êæÐJņn3æ„ڍ١Y¡ƒÆÌÐ÷Œ•ß3–ÙÆÌòÊlã1tzJٓЂÞ¨‚Rî}eø¾eèWJ‹«ð>ÕC5oå(Í]¥›k¦(®æFÅÖÌӜU‰š½Ê¥WåjÖª"ͬ­ÒôÚFÅÔnÔ´ÚnM©= ÉµÏ(zÕۚ\óµ1¹Ú6&¯ègJ•m<ŠÆh‡ÛÊñ|PÁu<Ø´ôø¬ëüZé¦Õƒ4«>\3®Õô† Ši˜¦7ÎÑ´ÆxMmthJc–¢óuCÓ2MjªÓ„¦6ý¨i«¢šöi|ÓqkzCã¾Ôøz[Qk`µmDÕÙÆ#hl#ÇõËY‹°‚àçy&-ù)‹tS“4‹Ýsó!&áÍñEš²‹:ŸTK—Xܗ’.SÄË p™8.¦j–káaÖáãRº3нþ”AŽWŸeÜ4ûôހ·Rbc¥‡ð/¸L³>e~>g|…Aùƒ`Ïš›ÉfNìû€„mÄìáÜÞh5@ßõ8˜ +q ÙPË`%ÔÃ:Xí°¶ÁèÁ³>¢ïqßáB¿¡x_ë]}¥Ïô%ß~1À%øޅ·úü&¾ÒVø#â˜7B¸À%B£–ñ›¿™ñ70vãÞ¯ÏÕ¥ÿh§>Åg^Æ}~¢£”æ$%zEs÷ÿü`@û}xÎËWbCa„ADA ÌzÙè,E£LÿÖ +F¬Ó­eü;{ãv0-[˜žnrÛÅtí#¿ÃLÝq½®³úßþ•j¼Ähÿç8§¯ÄЧm>Gçuäælꖀž“iÏE£Pï0'o©šeX§×ˆã?Lýéåí…á¸0?gÊpj‘ÇÃJðê‹U˜^lÂÔb‡·àPx;†wã@xû#F°7b;&"öawÄQì\r㑗±#ò¶G~-QÅX´„MÿÇ7ÔÿšÏÌg«Ø÷¦Q;…O-ý¼ÆñSQóp2"G#q$*‡¢óq`i9ö-­ÆÄ2 v/kÂΘVŒÇø°#¶Ûc×akì6ÇíÆXÜŒ.#Ë/a8þ6Äÿë¾Ã`¢„þÇCj~Éòãc>1ï1½ŸÍŽÓÏÇ_¦—Cq‹±y,ö$È°31;VcÛÊJlYiÄæ$+6%90šìÁH²ÃÉA¬OÁPÊKL=ˆPêISßAŸì&ze?ÅZÙ#t§IÌ ›%UÂoWó9R2yÀ¹ÔWP›~Xža½ìJy;R¢±U–„±496®*Àpz9Ö§ë1´ÚŒÁÕv d¸Ìð¡?£}™ëѓ¹ݙûC—üMøä7Ð!ÿíY†'K‚Gþ=2%|Å'å>KŸËäL!×Ïrl/ýŒç°ç¢—Í™s1š‰ ò e¥c [‰àšô¯©DoŽ=9 èV8PxáWt£S9ˆåڕ{àQN£Uy^¸•ˆ–Ü g#÷?¡”ðÅ3¾¤Þm>óK,;&Y±ÆÍgßɸl`\á*cї›ŠµyÙäŸ_Î‚jø +Ìè(´Ã[Ø +OaZ ƒp«6Â¥Ú‡jJ4«Î »êš°©>ª‡ÂªzB$a-œ¥@ŸSïf÷Ïü4™(c¯CO#ô²Ž± 1.½…aèV-EWQ|řh/΃·D¶’*´–á.m„«Ô§ºÍê^4©‡aS¿$¬ê—EƒúŒ°¨¯³ú¾0©ÿ êÔÿu¥Ò3J$a"?¤ÞõJžE>ñ‡ÉN–Å›èiˆ^ú—µ¤«t!:ÔQð”%¢µ,îr\ÅpVhЬ©E“¦v6VíZÔk‡`Ñn&íAaÔ¾& Ú÷EöQ­ý½¨Öü‹H¢ºâ5咸OÍ«zà4KáI²½Š='=駛qñfܚ%pi—ÃQ)CSU6ìU…hԕêӣAgF½Þ³¾&}Fý ú­¢F@èõ§„Nÿž¨ÔßZýòO¡ÕIB[%‰Ê*%q—š—X'{Éæjîé¡}´ñ»‹¿›õá°UÇÀZ“Œ†šLXjó`®-…ÉP…:ƒFC#j -¨1tBo Ag•Æ}Bcr:#Ýƒ¬®•w¥#³K Vû5H÷æ·Að 5ЇäÀf$&±"p‰ëˆ|ÿwHìdÅꓰb† çÝ|—¨³• .â&7P[Ó³MÊó³÷`븪oRû#‘Ò‡äþ$3±2˜‹ÁR$uHYjA\¨±¡, íÅÒÐiD‡®"*ôcD¿AtŸ„¥½³ôH8ÅõMžEÒNÄLm]'{ϐÏé¿L—wXÕçÇ¿ *óÊpʐ%DqE¢ˆ×¸¨ /Bˆ«ÆE‰yj¢MlœµÆ`֓&­¶‰Ñ8ÒÖª16Mn?HõÏÃ}~ü~ï÷œóž÷=çô~ý¹’_¡¼ŠäY⦎%Þò( »)Dn¦(è/WS¢:˜ÆË`ʖ‹©@Φ%r2m”£é ìKÎʡ䶋–Ó|‹œ­2L—ÌhÂL˜cxöò,ö WŠžƒþ<ô‹$ßRÉk3`…\ÌÎr2»ËÑì#s ìÍ¡jgŽQ[ó ٙ“ekž,3ƛùÀ¼vsðZ+Ô*ŸPébË[¨åµ…OœÊï¤ÇΗú˜Ðgß +©S3`ä¼ÌVíjeSˌ[ۑCÕh€ê(Âuš:.–:».X¤n0g®<Êû̙+úË[¨F«_sa +¿SðyH1g`^.õ@×÷UÉsú«$§µ’Ýzß 4݁fp“'E—†g Ç +m=E¸ž‹­ž¤®'˜õ•°ÿ½Å{—xÿ€þÆÊK¸›Ñ4ÂbXÆ94sÐ퉮ïj©#š†M’C½dƒ;Œs¢‘ærÎ]ر;ö½Ø±;hŠ(|F‰u€l¨…]pšw¾år¦›ß‡ {é)ñ5Ò“‡Õœƒåä º½Ðõ݌>š4ÛïA³p…&ŸB‡á‚£4çÇhΏ{H¿c_N`G#I#ů‘KæÉuŠX4²`ã;ð1°'-ÍÌc³Ù®quÜë¸x-t»äÉžû%—CR[«Ö1Y~ւ÷à}8€³6Ò9‚ó4ã.ûHbÇUš(€Mö¦ém™&>ºv ~‹f³¿“ت¤×ÙâŽnÀÛäéc8!µ;ݪu.4@¬W¡ ®Á§ð9|ÉÐöé¹ú ù-ì¸M“ôÅçùyw¡t±{ñÞé>SÝý”½ƒûӆã˜#äÀIÉ? {çY÷r«¦Uë ø +nGL_ÃMÀ%݁{ց 0´=&&OVþۃA’ý…ÂcáÐYØp ¶²ÜdÒrƒ­Xw‚@ˆ€þ0ÆC̄9P ePË`•~ašûYõ̍;õ¦ÁÙ¼'ú€ óK=Ö=⭇­Ü¿Áð‰uޔœÀ±õ¯Õ_…8 £ l4rô”9÷ sîcìx„ÿƎiµþ© úž)ð>sæ]÷Žu› ~˯›|ù «| ×á\KÍ68€Ø´þµÚä Ýñ+’/û£—ˆýcÑHgýi¬?›µ ؂Ö.cÝ*üZÎÚk˜l7âùÒ£49ŠÖY}Äæ]ÅZ«æŸZ9ïÃéflAÿ‡›M¢ç‡O¡èÅ¢÷:#õWöäϚ¢ÏdÔÇØÑD<®²/W°ã2v\Ž Z«sÚÂ.ì$•ßæB§‰ˆ|¯“Dò*Vޅ£p¸Ù†gúO›Sª-±3à“7û„V8~$`ûP]dOÎ)•ã˜F֞Â\Ö.fÍ2ײ VG´žµ·r…ì×!ž¼…eˆØ~²dJVö¶²ç9Ã]¸Þ|äñÉ_|ñ#ht¢‘Èú£Y"f°¾Q±£;öcÇ^ìØ£jí"GßÔ&½A,¶“[Y¥6ÝM¨YÙü¿ê߶i9æl¾숗Xu—üèƒNöÒnÎÉNaý‰¬ŸÁúF½Ž[ȏÍ2‘ •dæ2"ñ­Ó62äP¹YËá]Án¯@õyžråßáÊÿ”«ö,ßåŠ9lk½’ÐtŧÎdX´"ÑIÀ‡Áh$¡14429ÓÑÈÓJ²æB²b‰–¢ü*_T*öc1‘­´¹­ +Û§*oC²{Æ´¯SöÎÃ1Êήڝ<ÛA ØÚÆß<8ù~Zg¢Õ¶ÑZÙf€VØ Õ²¶ÉZÚnœjÚMRuû©ªj?Sfû9ª´/Q…ýb•9Ôj¡Ã&-pÜ-“ãQ;]T‘ó-ºüԈçøŽ«¬ÉÒá‹>eo{gÊ)ÏÖQ~ÖÚh£AµN^Z椗0U¹Äi±áEUUn­E&h¡ë•ºerÍU±ë|Íw+W¡Ûr¸mз]Êw?¢<÷‹Êõ¸­Ÿ5«£¥n ký0¼I²!€vߙ‹òWÕ_ín/³›»*Ü}µ¨c°J;öU‰ç *ê4Xó;Ð<¯1*ðJÓ¯,å{ÏTž÷\åú,PŽOfú¬ÓŒÎoÈØù·šÖùœ¦v¹©¬®?)³«E™]žñ×ùïC)Ë!´°*mžU2÷aËÂ.mTêÓAE½5¯kæú†)ß7Vy~•ë7L9þɚå?^3º¥kz7£ŒÝò”P¬¬³2VkJà6¥Ò¤À3J ú»&=UjE©Ïø°7%ŸÖg¬‡¥a´z<+Ŗ¢žô7Äfn€³^ ôÔì Íê¢ÝûjzMë9XÙ=G(«çeöJSF¯,¥÷ÊÑäàB¥W(5x¥&„Ôk\ÈA yOcB®+%ä‰F‡XZ¶(.E²QÒ6XU´¥<+Ė|lÉ%69Ášì¦i!]55´‡2{‡+£wœÒû Ôä>Ã4)l”&†MPjX†&„Íиð /SJø +ŠØ¬äˆ%EœÒˆˆ¯à  †C˜E#à\ ç0–6–C9ñ,{rhÉa”ÖV™á®šá­É‘J‹ì­‰}£5¡ï 5D㢒46j¬R¢'kt´QÉÑù½@#b–jxÌF½³OCcNjHÌçð, Q-œ‰§½ƒ× À\ZãZ#mP¶¤GÙjR´‹Rc<5>Ö_ãbƒ5&.R)qñÕo’û%jd¿%ŧix|¶ãó4,Þ¤¡ñ5œðš^JØ£Nh`Â'ðPâ-ø?ªË<*ÊóŠÃ?we1 $€’n "Ê"ë° Ã2£,Š0QˆNHAAÔ(Š±ÖŒMªqµZ5qÁ4Õ¦‰M¢¡‰6mzš¦õĸÖ&©žÆš˜X§Ãüaç9óßÜß}ï½ïûÞï"ΡÓÉÔl‚åÐó’X?m‡ _fàK1ŸSÜU˜è£üÄ@Y’Æ(/i‚r’'+;Ù ³Á¤,ƒE&C‘2 2¦ÌUZJ£RSÚdHéPRÊ>%¦œRBÊNJOù·â %$»HrèíïÎTö#,…g¡–¿= 3ð§ +ùœb¬Üoe§Ȝ6R¦´pe¦E+#=IÆt£ÒÓs•jœªãLŒÕJ26(Á¸\ñÆMšœ±G±'qAÑÆ;ŠNw(¦‡4‡bS:Fë» Ö@‹QšU<—Cqóäñl6)c¨22ŸPzfÒL¡J5M”Á¯ä¬T%e™•˜U ó ř«4ÙlWŒy©¢Ì4ɼK‘æš`þnkB–C‘&Èìå0#ÑOa4Âé`…0eIFs¥f{Ȑ㣤œ@%æŽVBn„ârc59/Y±y™ŠÉ›¢è¼M²ÌÒDK½&XZaY§pË…YŽ)ÔÒ _+4Ï¡°\Èqh\¶CÌR,‡¨r(†)ŒJ¦æ¾5IVc’wU^56=VS¯¡5ËäYÓ!šýr«>—å>ç¾<ªò¬ìeëk…z˜¥P¦éÄíØ +)‚ilúŒu’Oýy-ðÔPû0yڇËÃ>ÆËÝ+7{ªÛó4È>]í5êo_¤¾öŸpðí‚S$œlþ7êSO7=Ï¡~°z&ûj¡Í"Èá9ÍFf3ûÍAŸñ(hú ÐŽ¬©ŸÜšÝ4 ÙK}ši~ši<š¹ü[¸dZ8ÐZØL-P kyÚág¼Ãຈ¡má ‹lêåyÖh‡*^/ƒ|ž3Xs"kžÄšCç£ß ù7IÚ%Ï%m’ú®,µ1ϵÑx­¤ÑXE#²Š‹¶ ¯C­ ÕN0Û1Ò¾¶ðÿC¼ËÙÆPØö"p8iFë™jòÀz§ñ™Íš õÔ î‡5JÁèúcÂ{¹ä±J¸†¦—Ðj}? ùÜ@ã·?6áÇfüè¥ à’éäp뤰;YT'†:×ñ¿½p†÷®óþ¾çpòzµÄyŸbF¬cIá¬7x…ä·ZòZ+¹oúw ½^B«mø±x¼BP\ûžáwŒíÝF³z‚w>…{¼ïpbGsÖØ ©ÃŜCÄ9‚ô…°V¿Mè¿(¹¡×gš»áU8¿€ƒ@xu˜æüˆ»ôšÍõq?NÒxœäâ;ÉAÓEqu‹®ÀO¾/øš÷Nj[9——±W’â<‘×F¡ëË^”òW]ZG€’¢Mg€_Á›p¯Þb x›˜œ%7ïÒ ŸÃó ,\~ÝÔgw-ÐîíÀ—»/“M·CO¿À½HªŒÄ9†‡¢;b?ùÿ%ú=š].­ßÀ;Àz‡¡ßÇpÁ9œ‰ÁAe€ôW•Kä/ðã +MÐÕ éõy"»±ˆÅujóúMžï©”5çàZåÁzƒÐõa»Ÿqi¾çÒûÈ¥ÁöÖgð7×`x®Àµža naÖ”»ÔÈw4Æ÷©ÑïÙ'?PŸü_‚×à\cÒ +žàázö§ â òa:̂¹`‡&h…6¦·5zÀ´õ=Ø}æ»o™­þÔx—$}£‹L™_éŽê6o÷pþ Û9oºÁ@èƒÁ ` DA +dcaª~P•º§:ì۱߄ýVì¶é_øñ“ß?™ÿÁ4zƒ"ºJ"¯¼Ë<}®ït K=|ÀYxËéC?çÜÛKWL|Y[0ëϚâÐ2¢cA£ûåدÂj¾ÀÏñãïøñ~|Ê´ù SèÙ¼™T?ÒQJæ zÒ9"ñ>–ßuqNÁ §ú?¾%wˆÅ—̺7‰Å5fÝ/”ŒN–þLN>V 1,Çv¶çb{%Ó¨ßáÇ;øñ[­¥|;Ñx…R>ÀêâçprWJU}ÑóÄs_ÖD¾ÂщÅ÷T½MNΨ@¿Æ7𣋼œÀãøñ:~ŏÃZ‰íu[±¿›Ê8¢}D|E¼› îBm'ô|î€í.85Égo‰ÿÁ¹ó-/Ö€Î(t"шÇZ:ös°_ˆíl—ñÙØ®Åæ|l6bs‰¶©ll¤2¶9=قÇlâÍdsŠ¡ç÷ýÛ®­öëè"GÙ'Ù#ûõ$:¡èD¡‘„Õ ìçb¿]P‚ýrìÏÆþ\l.`w,$ +ϓ‘µTÇV½À·W“UD²Ì® ª—£»âîr¼]æê9Ç÷Æ Ž]®€Ÿ;åA¬é1ôü°B†Ãñ9 ™(䲬h”°êr4*ѨÃf,ÖRþºÏãy ZDd²+ÉG#ºr‹ëæ"Çü›pvrÔ¾ÄÑ¿…+`³Üµ^Þè Gk4:‘èıŽT-“éT—iL\ç…ƒ±YÌn0Ë°/ÌÃ2,ÃÀ3,3˜±1ŒÙ ãÝÁ$¶Çv°c¥ëxKÒÊ­k7é’Vê´ª*«R¥¶R¤U~µ•ªV­¢.Q*µJ—Ûc;RۏîÌÝÎ{¿ûÝ÷;G:½šƒÒ r‚qéÌè+YâȦc¬n:ÃJÄFÜd)ò‹‘ï±°ùÌG}ÄüVu™ÿáWj폴ì~U¼®eï³Zr6Ôf_T=/ÄFð|Tg"S8½%›S[K8]ͱèŽlsrx[‡¶÷±²}ˆå˜½,ÅLr f…ØÄcŸe.vƒ™¸LÅÝg2î=&â> ÿ1ãñÆÿñ¾,Ðwvi9Tk¿¦í%ý?k‚5Õt2Y$Dq"nGâÓ9oæàŽr–j8à`!ÁE8ÑÃ\¢™ÄÓIãL&Í1‘´B(i±ä‹ìK¾ÎÞä{SHù9#©3œjü—õJ³–Cq'_vDœÕïSyʝªi%SKµ,'Çr %…pj6³iÅL§U1¹³ž‰­„Ò݌§÷2–±›ÑŒQöfL4-0`ØtžÝ™¯2˜y_æ» dþŒþ¬èË2žÐÿ˜LƒG²_d}>'.Èz¬i{Xû–dçU˜j™ÉŒf*3‘ýY&Æwå³/»œÑìöä4Ìi'ÛÃp®¡Ü ƒyûñç-0w”þ¼sôš_Ácþ=æoÑmþ)]ùƝoà6t=&Ïà»ezå²X✖ûãÚ.kߜ,ȔjÙ¯ZÆ͛ٗÏsü† J*¨fwa=þÂV|EnŠúè+¦·x Oñ=Å«t?‡»ä*%oÒ^òΒÓVòGa<ÁYü”we…ßй +ÖŪ˜×ÿIíW=£› Æf¸8–Ý%ÉøK³(-¤¿¬‚Þ²Z¼å<å.z*Öº•ýº"±tÇQޓDY‰Ò3%žRŠ=V +=xÚÉ÷z1{GÈõN’ã]a—÷92½ŸÁäýéÞï±ÓûkÒ=ŸÑc`ê~Ê5Ùî3ât¦ÅááRLrH»®[ú(þm $`H#Ï·‹\_!9¾ +²}uìÒàeù»1ùÉð³Ó¿Hšÿ4)þ«$ûï’è(~I¢ïï$ È=÷Ë5Š«ÒXë‚E±_Z#¢_t ½^ꓬ}ÒWt,RTÉŠ$k$S ‘Œ@:;¹¤ŠI T“h$9è")ØObp/ ÁyvO¼L\ðMb‚ß&&ð¾ø+±#r®ÃròCõ|Ç¥ûÄ ÐpÒ!Ò®‘¶Zjä”öBêØVCq$„’…‰øY”ª!6ÔBL¨‡í¡a¢CSl a‹‚Tdè¡o1þñ'"Çää÷lg¥qHL‰ Ý¢Õ§9(íJi+"åJ_±1uBp:’ع¢Ã D…SÙÎbs¸€ˆ°…Ma}Ôa½Ü°nËBywîšx f•kf?T#”ƒ›‘“œVJÙ­ïaH=AÛaÑ+\úß8¢9°JöI_ñÈ4)³ÒŸ‡ØÅMD”ùZ‘áY‘ÙXI׃(ORS_US[ÕǶª\µª[UÎ\=%®êø=«ð¶¢@vP5,O8"Y=ç¨Ô%]Ú6ë™mzæ²I0ÏH_º)K¯¸¸ý0l>.³wR¹ò¤ ×)ÕñŒŒÆZ†šL®-vëj°ëú¨Ö5ë!¡‹Ö/êøçÅC«pøÌ'ºV5œ4X–Ö„†,(zõÛ©g®›Ö Cþ¢ô¥›|Dú' z "ž•þ9ñü&5x¾óªãÅZpTÇ%Õñ’ü -vz'—5Ñ7ô` BïcㆎSç} óÿ&TÃyéiê0(:5Ö :½ò H×tRúëw¢ÎK÷’¸Âc£©ÿ)¯j<®)ß^×x¼¦÷rSïå–긭…÷ŽšßMìÛz°Û¼[¯ˆ¯è9ø›ªá5ƒYi…Gcݲª9 S OkþI7é‚Þýe½.•¹Ö5âÎӍB ²í2â‹“{2å÷ceˆù×eõyÆñ¯(”K–kÁ]XXXv]`9DPEEE-â}Ö3±ÑªÕ68ƨÑǚ&5UcըʹMššúG϶&iLšLâ9šl?“qòÇg~¿eÙçû}Ÿ÷yG¯ã£ YµÑÆ&×Fa·‘ÔVÒÊ[Oó?Ÿr‰§&û4ݑ ©CÊƹšäߢÑíÏû½Ô©Õ~á?­pÞÒª·à¼ 'ºK§ÈÉi.Äg¹¾Ëè]¼ól穋 Lè…hƒ¿óÝ·àS cÊüº)+¥·úC7`?ú¯vj¾ Çá$üÎur.Â{ðgxþ—hV.37Ÿ«¬•kz×ÙànPÜ7ÖI7ÉÅMº©›Ôæ;*ßD2f;y6ñUÄ+Ô6ýŽ¶«Só|§Î€}ý.¥¥ÂU¸„¤•’XzºM|;Ôé]jôsrŸEø€5ò‚zH]< ðƒ›t9} ô†¾Ð"Á vð@ Œ‚Z˜3a,ÒtSé|ÑÙ=¤»¯t—‚ùŽ‰û–ä}Mù•>¥Ó|¤Ûü¢«ð\„sOzÞîOúÞü BÁVȆB}¯24F£QG·Ö@ü™úÿÃǗøø‚û9 ç3ºÏÿЕþ‹b½Aá\ÕRu…”Ý!u>}³pŽ?ñ Ÿà^0zÝ£×½C.¾¡ÇüRCÐ('~nâã>®Ð_~¬fb/Ô%||ˆ÷µ¦î%Æù +Óx½¿âä6§Oïtò´Âk?ñÀÎÅøüS n)ŒqGŠ>¡ÇüH^òWBéÔŸðqçèsϨ‘سuŠîõÝçÛø8¦Mhl§”÷‘‰6´Îêu¢½F¡ô*üöÁÞ§<°k1N161´‚){:&Ê2lâÖQ|¼‰#ª&öxÆÇ!MgÄM:ˆäc¿Ö ñw’ƒÚÅ/wõEªcj/ÀvØÏwz¸×YΗ:—ÛIrq”\¡.+ vâ»Ù* +¨¸aڃÝøØIîÐ$bNgkbw%[éz\´h3n6i#‘7P›ë©ÍçP]ßIûû4ou.íw:·ö­h?¹ØK.viþðnEÃAü\âñG{4•XK¼IěNšõ¬–°RÖj5û*"¬ â/Èärfu)«f)ºOóUû’ïÊØáp—Ž-ql'¿eüZ!Œ#š1˜Ñ°¡‘ÉŒçi >Vác%>VåÌË2æe ëe‘摍šÏ¯æil¦JfSQM¬¤Ÿ£û4×9öαͷÂháóf¶þ xú%{ÆZ1žp"Æ¡“„ï4-¦6²o,P¥š« +4jИ€ÆTÍâmnq<ÌMe>¨¢Éì“ô_x ¾ù­ýÇÌËy-°÷5Å+8Þ{wÑÒn}W0z‘h%¨¹KŠšºdhVW—fvËWc·!šÞ½LÓºRƒß8Mñ›¬I~³Tßc¡&ôX«ºž[UÛs¯Æõ<¢1=/ª¦÷gªñ¤jßjàb(GÇˋlía5ï‹Ã¸öphÆßì?Íî Y½CÔè­iþf5ô±iJ_§&õÍU}ßM (Q]ÀH¨Ñ¸€‰8C5 T¸FU[U¸Wo¨<ð=ú¾ߏœ2pôFqˆæZ#-á9‡Ï3#¹þágjõҔŸ©>(B‚ŒlQmpºÆöË֘~Õô+Öè~eªê_¥ÊþãUÑšÊCæª,d¥†‡lÖ°ÝÚª!¡Tú¹ŠÃ~ï帧ýêÃq¿æÁ >Oáïõø©ÃËø𮪠И°U‡Ekt¸I£"©2¡‘9*P J4<²B¥‘cUÂåshäl–«Ðð+v*ßpX^Ã9y¢n)/ê1ON"Cm \e8æŸ3‘³Ô ¼OàoãðSƒ—Ñx©Šê£Ê¨~*ŽÔˆèx ±¨4&]Ãb³44Ö£!qÅ*Ž¡Â¸jÄÕ+ß8K^ãå×+ǸC.ã!eǟQVü¿áp;8„æ6Žøµ\E@#ÔÃØ$´ù®#ñRßS¥ñA*‰×ЄX4«h MlÊQ¾©P^S©òÌUÊ5×Émn”˼HY‰ëäLÜ.G"»\âi¥'ބ‡²›}OÈ0ùt½­É\{­ÔLå8žg5G~/ÃK)^†&vWQb€ +’B48)J^K‚<–åYìÊMv)'9_®äe§T(3¥VΔiÊH™¯ô”g”fÝ&›õ ¬ÖSJ±^ãù@ÖŸ%w°½Mè.³Ñï¥rdž±PÉç2(áûbü ¯µò¬ÁÊ4@n›Q.[’²l©ÊL͔3Õ#Gj±2R˕Nc’–Ö [Ú\YÓÖ(9íyYÒ(1í„ÌiWà¾S}JjÇæÓntÖsõ\œN-Ú©¨†r>—@ßåã)—§;½·²Òƒ”i“Ó£Œ “ìV¥gd(͑£TG¡9ÊduÔ(Ù9Yg³«drþF ÎýŠwþAFçÇ2:î)ÞáSBØ}ځγ´$óô:PË´†ó^ ùàæû,žgÙ3•–Õ_©YÙ²â5(Û¢”ìt%ggËâÊW’k˜Ì®*™\õJp5Éèf‡uoQŒûeE¹Ëຬ(×]Egûž“åS ±Wg²ђL†1P%P¹àÌæ¾é’RÝ]eÍé£äÜ`Yr#””+sžY¦<›æ9•àÉS¼gˆâ<ŠõÔ)Ú;Sï2Ez7+Âû;…y*ÔsIažïžçSDn[ÐXŽÆ,4&rý­‚áP ^pVÅæ‘,´oæÁ½4° Pñ!2W˜ ØÂdÅÚU薡¨P‘E#Q4NáE +-Z¢þEÿ'»Ìƒ¢>Ï8þdY–]p9d¡j F¼¸äÞEv À‚Ç®" «!ˆfRÏzD§1j5Œ6É$ñHӚ£‰1‰ZsØLµ5‡GÚ´4u¬Svœ´Ù~·íLúLJ=øíó}žç}Þ÷}ž­J,}Z¶Ò—e-=/kÉMيé\!iZP[O»ÑhÍgÀ€J(†<ÈE{,Ú#‹é»K¥!å‘ʨ4+ÝiSš3E©ÎL¥8³”ì#»+W]EJr¹dsÕËêZ W—,®ÍŠwýXf×Q™\gç¼.s%kÅ=~€FG!ç":õP eP“idzÑUFüè3ª8ª¤dwŒ’ ‹$ٌ4Y!J0FÈbŒW¼1Uñ5劫©‘©Æ§ØšvÅëe<¡HãyEgé¹ +_+ÊTtuP«ÐX\Â~ ÆZpA ŸóxÍA{ ÚÃ]è36:º~û°Ô0h.CM& l–XÑo‹–¶Óˆî`]~„»ñ£‡‹®‡5顸{ô Ù½ ¨‰]¿à¹k4NÁ>æ ébrK $ÏßéB]Ë)f:[`ììk¸i8`o¸g‰¤gÉÉ~rr€µ9H}¦;Â¥{„ÃïEv‘Ã$ðÐø9ÏP™,zé)YªJ\œBÌcÈóÐUì?t-ij=¬¹7¬³†çáø¼L0­cQÒqÖæ-öË)ü8Å¥|Šú<ÉBŸ$À$ïÄ!`=Þº!½ùÜÄ\DÌÙÄ|ÿf)x­»ÑR÷†æOàhXãux3<Òª_Â;ðœ L çY›ðãcöÊ'¬ÉE¸K÷e +é2A]ÁؕKpSåë9 Èõ(bΠljÏP!ݟÂ+aÍp:¬ñ+ø5œ ‡ÂÇpH¯>¶?ctÍ$Ý`]¾¤9¼ÉÅs‹Mx›B»à@w~DŽ ‘q`… +£a2”B5ÔÁXX¦±Q¾f“ÜeÂû…z‡¢¹E¡|©^&ª—õW½ÍTó¹þÂ_ð‹?ÃxNÂá™÷D„ýH„ x&@“Q³©G·Õ ¯ðãoLNיë®1É]e +ú?>Ǐ?±Y>c2ý”ºDÑ|„ÊoIÖ9Ýd¦ ê8Çá8ú>¨//w•@<)Ä3½Ñ̤‰£ûNìL® ú?>ďß0՝ãÐú?ÎâÇ{Ìwg˜RO³yNé9Êæ%¼x‡%½ªcdí5^…à ìÿ–œ\ä®ñ˜õ{%‡ƒ¼e¡3)Ø/&³.lØ®ÇöllÏÃn应Ìw±E¾ÏVوÆv¶Ï“:Äß^ž<@ÁìG!¤¹ž†½Ðöá¸.§óð®b(÷Ê?ÁhŒDcy›Ší2ìĶÛuDڄ]?Sm+Ù_Êqхò*ì?J&v±µ÷ñ÷%ªä}í Â(nóCØ +ÿDó:\êÓfk÷m÷tÌä*tìÓ3zßs¨¶Þ7ò]ÿ›/µøRk3É°Z嶥jºm°\‰ÃåL£Ê¤ïª"iªÊ’ŠUšäTÉÀZM8K…[T`ïTž}¦Øwj’ý9M´¿®ûEå$ßQnr°‰vÎJôˤþ“®ÙùÐ3i“ ¾¯Æ—éøR•-g²E)v•¥8Tš:LÅ©#5-u¼ŠÒ&©0­PùiåÊäєA^MÔ¬‰éíÊI_­ éە¾OãÒ_ÓØô ë¸ÅkÏ÷x +­G‡Ò‚ÒŠ.¢ œ õ`ð¹Šï+ñ­œÜ”9"Tâ0kš#Q…i*È¢¼Ìáú7Ûeõy†ñG (—‚A–uY`wÙ]`e…]•]6ˆ¬xâM0žxD£†â ‰Æh´ä›hÔ¦:±­©M“š4¦‰=Ò$ÅΤÓvÚI›ÔÛ´¶;³ýÿ^3æ7{ðß÷y¿÷{¿ã©Íwi¬©J>S¼¦ªMMª,˜)OÁ"•tÊ]Ð-§ù)•šËn~]6óÇp¢²Då€o ³ã}=׿%؃¹Ð +M|žÌ÷!ò©§.ãÀoNP­9M¾1#U3&_Õ«ª,UVÈSèSEᕆ嶶Êi] ‡u¥ìÖ.•Xw«ÈzH…ÖÈb=·x•µpgÐيælA»S¡‘Ï!®ƒãùŸŸ|Æòœ·(^UEÃUYœ©Šâ\•—ŒQY‰Mî’29m^•ÚÆÉa›,›-¢û<ٗ«Ð¾Yû.™íe²¿ª|û9¸)“-ª0—pv Óæ*½ˆ-˜M0 &ð]Ôðÿ*¨pĪ̑,Wiºœ¥Ù*-5Éî,’ÍéT‰³RÅ®:¹&ªÐ5UW›Ìî¥2¹7j´{§òÜ/h”û¤²Ý*Ûu]9®¨rƒìFc3×Îe.æKFB€ï|P eàä;GY¢låi*.ÏRQyž¬VØe©(—ÙãS§^&O“F{f)×Ó¡Q•”]ù¸FV>¯LÏ+áy®ñ>ª¬Š¨F–GµƒØˆ½¤¯ÍÔÆ󾪡©„«©µ*^–ꙫ3Tà͑É[ |o±F׸”[S­Q5ã”SÓ¨û|3”åkW¦o2|ەîÛ¯4ß ¯ù\UZ ·FoTéÕQ=Füµh.&þ ¸Bà‡ð€³ +}/Þ«P06F£k“”[—¦–²ýyºÏoÑH¿CY2uÊLRz`šÒ •X£ámJ<«¤Àq%Î(ÑYIþ{J®‹*¥6ª-h¬¬–棁˜µPe`GÛZ‹>Ö-oþcB¼2ƒ)Êf(=˜ &¥…Š•rkxȧ”PPÉ¡f%…æ*!´BCC݊íS\ð¨b‚o+6ø¸«¸znŽ¢ÚŒ5]ŠÆ®ÞÍ0Pp¢]Œ¶›’W>ÖmĤX¥6&*%œªäp¦’¹J[4,ìÐÐp¥¾(.ܨ˜0/¼6Þ&|„fÃ,4b¹96Dx¨Ž5‰ÆŒ@=ïë Ü|¶¡mA{ôDô'£–R›b”45AC[Rá@‰pÀDØT#EƒMaP’†Ÿ˜†¯‰<¨Æ0‚·iáÖÔBS£¬Bcþþ“a<Ÿ}PÁ{{˜$å7 eÌhÆ6©uˆâgrјÅÁ?›v6ʜœÁM¾¥ncÒښ  0“mÛx¯9c8ûü™ßGXÂøfØHê¨â½“1[sþ)»ýVô)mâ)nœql( Ò".‹É£=‹ƒžÃ¥ƒM¾ƒÅÞÁ$w¨c:<_åÿO&µý¿¹ä°(ª…è´Ó§ ãõñê&ý⩒iúXÕ tSæKÃ(kÌèRˆpÀp [Áeg%yt2'«9d×r¸¬cNÖõ/8&s-Å[»Ö³ïŒäjÌi'7ùUÑÚÐjá±ÆëçÕC­m¤^0}ƛŽnr‡¿ ]¬"W4yØÃ&걙zt‘G7õØB=ôÆV6à­,ê­Ô¢‡öðãží\¹1oÁÀvÁaM]QÍD¯™:×óêåÑR¦o ig3Þtt“:¥Ø~͍Ð[`+<„äªÆ(fð"ú$ý±‡<ö‘G/r/~/ «—~½°—[óÞ׸¸q›Þ}p±Ô¹ÝZjí^LRçZ(ÝD–TL¿æ£†ˋkòàś©åò?x§Õ0ÒAjrˆ¹ùfªô-ò8FcNŽÑÜGgñÝZ.Ïxé;\ qS‡Y‡¸S¢;žZ{–Ó«¥\ê›ÞÍøûÇù„¡Ù¯·¿_XâbS«ã@H Ø Ax^ç‚þ—ÑÓäqš÷4Ý[4ُz“õq +qê]øüC“˜&é9³©‡õÏx“Ðò¬1¶~Íc†ÎIÝ2è7e§á8c•~³ö!|D¿^ K¬ÙKŒ—Xð}4YÔ×+]$ØÅ>¸£À#œI̯e'{5N¡®±‡1¾bh¾ofì=Cc@~ áW†ad 0®ŸÁÉã*órÞ¸ÎžqƒMæ&µ¸ÉäÞ:$Ýfϼýɀç$`8dA>Ø ÆA´Îd,Á-­Ô=œÏßqBÃÝÅ~‰#¼M“ÜÀµ]Å[}®wuŸùO|ʯ~gá ¼ ¯Árøýy¤AXÀ…–zýEaÝÁ±Ü «äñNí +në2.ïSÎïY4¿£y­½”åy] ˜çõC4ÏëÝbš¢ú9¼ehŸ€ãÿ'‡{øÌ»Ja,#tZ\S ZŒ£–ø!}‚ŸêÃ5}Lá°Îâº>ÀU¾ÇÆñ3òø õxG;h“^Úåms·{†V½¬ï3šï¡ò]8 +‡áÀåÀJe|âIé·†NSÆ4hTÉO[„ˆ}?±#ĞIìy´êbZg)±Wã*7êeõÐÆ»ôïj‡¨ÅAªr€™zÁÐ}ž†}FwûÛúŒ–ㄧ ShÇäžGîV4\Ô­šØ~b‡ˆ&öTbÏ n•_Äò}Ø«õ ýÑ«mÄŠ¿ÚM-vé§,õϵÅ'`| …/>g,³“Æ’8B-^T*ñG²™ˆ_L|7¹{Ù¢üÄ»‘m«™˜Ó‰9‡˜‹Ø:—w [i³ò¸ºÉ¨‹ åFµ™™Ü¤¿ò`< WÐ;k,÷—áExö²NžT2yg?‡øfâۈ_F¥½tŸŸøAâ7 +ñZ™…9#‹9N–³Z֓I:Y'«¨Ö +ª¹\ïÓ9×yþåÔØv÷Û2»È?œø™ÄÏ#¾…Èâ—ßKÕýIJBÐh&þtª0—Uûjg´‹ÁBF5ŸÎ׏éžËp¢ÿ¦Ûù6ÇðþX¶f¶ûŽŸÍƱ¸–ZtR‹•ú'ÓeÛæ]Æñoâæ¶;v.çpì8qœÄNlçpšØ9쎛&MÓôN¶v-m³vëJWšrT+[§v êh5­´¬[‘@ÝQZXA\š¦1& + þà‚ +!:Ì'©‘øã£×ïë÷ý}Ÿßù<_+ñ–£Qˌ7 ÑŠFQ4âìÔ$íMÁ,«cŽ]³O›‰x½™aö¦YEVWòÏá^e¾Nº{‰Ô{®ˆ´JÚ;ÂõQÒÎ>žï!®ÝÊctMèØè‡:^FݏNÅtúÑf6R´;ÍI¶ha†Ó:fmœÑM²‚ÇØE£¬¼QÝÓÚ£^C÷"Çú)RîQX€Ý¯s<ÛÎÛ +²µuM!}*F«jTêÑò¡ÓÆ tj"«Wë²5ž=¦dö¤Æ²7kÄ𰆠7,jÈpV†Ëê7ÜPÌðE×,+šs_ÑÜ´bð%4—J˜{JÂCvJ.ØÁïYžm\)W‰eʘ£©£&ó¬šÈ+W*ß©d~ƒÆ +Z4ZÔHAD‰Â˜â…Ã*œÐ@#S4¯hтúŠŽk­ñŒ"ÆËê6ÞP§ñø“:MAZ]Æ´® wšRðIJãýôfaŠû žó’X’æ<™Ì1ٔ097»4dnҀ9 ~s§bÅ}ŠÇÕkIi­eF˜º, ê°WÈrFAËeµY¾*¿å]ù­²´YÒzÿéõðJ9ZMÙ `÷£<ñĉeȖ­Á’" X-Š•”«¯¤V½¶­µµ(b ©ÛÖ£.û€:ìc +Û7(hß¡öÒ} +”Ské³j.½¤¦Ò7ä-}G¥Ë\Óܓá<:ŸBó %àC¤ØYXcÜÇ)Oø/Æ;Qbé-ÏSO™Y‘r»ºÊ«ÔYáV¸¢I¡Š6+»Ô^U rD~ǤZ[ÕìØ«&ÇÇÕèxFNjr;^—Ëñ¶êäúîɊpãhî§ìÚáƒÀ8$¸ï‡¾:jâ‰0.ÕkÔQmR¨ºDí5j«q*PÓ m«ZjÃj®í•Ï—×9¡FçfyœÈí|BuÎÏÊé|A5ÎWUå| þqO…PËٍÆQ4÷` ¶z°=”^£0Èï>žE “ÿü×^—¥€«P­.‹Z\¥jvW«É]/¯Û§Æúv5ÔGT_?(·g\.Ï&9=«Æó¸ªÃA6Á2Þ¡3|43 »#7ó96ÕÚ4Uëô_ø.½Ê4&ab1æðÛ¸zésV•£W6t‹Ñ-š”ri’bAÚL±³…"c+Ƕ•DObÛIò™cNæ9TæYPs46LJs;á0ÿc`w^ã@Æn¿ËwéUf 5…Vœ1!®¾aÉ5&9°f6¦ÔŒná&<àV´·Ã<»ˆcw.‡,㱗8öÇî‡ÿ‡Éº@c ³Ëلnîތæc+Zð$_-xI¸ð™L|Š1y†¹y–uz–8–ˆc‰}²Äæ:Ç`?G£giäÌs®×yïǼÿOéé´&èï ºôÙ·=0Ïþۃ>º9g4Od´NÁi8“)À—à<|.[O—“+Äq•8®‘ô¯±O^a¿ÌX\¥á«üÅ«¼ÃšøÎîRZ#Œu}öÓgã\Æøš¢"Ó¿Ó½ç3Æã0¥”¨+FHØa¾˜“Wá øÅðMÖê›Äq›Ä›Ã÷MÝ7èä-:uqóïýSu_ýÌqp?ûaª`ûÓßÜә>^Èh^͐ëÿӎ; çsô͌Iû.¼•1ŒïÂÖêûœï³_Ê^ý “}‡þùC~wõÞ=u³e|Šš“’•­“>£ûrÆô½,!݆ïÀŠ!yûÿtVLâX1KÀ/áWð[ø–»ì•eÓ2c±Ì¦Z^äً@'î~°êyyð_¦Ë=¶Í« ãOÒ8Çv?;NDZãØñ%‰Än;7çžzI›¤m’vݺ6[E‹Öª]ÛÑ ½±B«ªÒ(° Ê À*•kÇT.ÓØT`ã@“Æ`—¢mŒ–2¶™ŸsQôS>þü¼ïwÎ{Îy+8À!h…n† Xëõ‹ó_8žwp@7)Ö8£¿ã2ßÂ}¾ÁÄ]cÂ^eàþ̽¤?èøÌ«üò +<߅oÃ7á9ü‡â|N¨ƒFb-C¡OoãcÞÀ¹\#Wp9/ã|^Âu½È¹Š|Ž<~K¿¡hM‘^Ñ#8Ìï0lO1|ÕeÔ.åc¾_ú¿ރwà&¼©2â؉ãÖ_ð3/ã©^P'ú=‹Cú%îéiœÎ/pZOà¾~†»Œ|œÍâ1òø!Åü} +ù"“zARBéLÎy½»û,|>ŸÎçðOø°séyxŸù4cñ$cñsyy‡0åÖÊ;¤ÐîG{í ´W¡=‡öíhϳ<¶â*wònûY6e6N“ÅY–ìâ]adÞZˆyNÀÇá8°Kð΋eôT¾¼/·df©¼… }?åedÛÐNëaÆãóA{í)tgÙ"Ö£=¯Säq’y9Á¦ò ¢Ü¯3ú +Ç¥èOÌTnƒðaدïwð“ü’ûj~ùŸ‘ m+ÕåÐ'ñº§`¹6¡@;vía´³hO²…Íè0y$ÌË>íf{;¢{ùÕn2¿‡ÅµSÏ°ÝހÜÛa<—_֜êúB~Ëc7EÿE]ÁëÆëÂëTúÍÚK÷2/{¨Ó]B?‹æJŽ5h®g¥ÜIÛ8Zö±rŽs̜áÎy²û)«éuþçþË&x"¿<”ߏ参½ ǃ‰Ü-hÛQtýú1ôè§Ðï£"‡ˆ‘Eo’•2K•n B>@6»X=Gµ–‘œ£Rf©Öf}†•6CìÙ<ßËo»'óGÛôÂqÈ։JúeäkC¿}7ǶŸaŽð1’¬Œ1úˆ1ŒÞ-ŒÄ4+fÕ:O¥l#«¬¢¨à‡©ž <ñ+xr ŒÃù¶dŽ™û8òö”rD–.¶w-¶ +·2k‹9ês†9YÃÞµšÚXEN³f'Ù;VR+¨ ÖË8WYž\N¦cÔço5ÌÌRÁTù#ß¯× Çõ"g‰ùÛé~Žþm0ëa–{«i ¦Égª°”XVÔÄqÇÇ;‰ÓHœV"·«›ä/‹î4­gt6«—ù覲º¨ð4«+ÅúèdgëdGè$~ +>K¼c´@» ZûbK¶†ëIç~–ï—›—hy‰Y£E6Vh¨°Fƒ…~ , )³¤Y}E õ¥ÔS”Q·iT]¦I¥LkÕiºSíÅ;•,>ªDñƒj+>§VÓ%µ˜®ª¥øºâ%9µÀib"î6Ž·NÞ&!Ëç½ßË€µXf‹2e†z˪Ôc®U—9 ´9ªTy‹:Ë;ÔQÞ£eåÃJZV¨Í2§V˼â–j¶Q“åAE-ç±\RÈrU!ëu…­9Eàqös íèmo«hnáÿ0ôÓ*÷ò]7ÏtÙ Ôµ´Ti›U)›C¶jµÛꔴ…”XSÛÒ¤ZnÅiþcƄšŒYEy…j0Ž*h|JõÆ×TgüX>ãEùìÿà:'?'Ænâ݅=XKÛ³’ö|”ÿÐý49u_;Ï-s)é(WÂa¨ÕQ©¸£V±Š€š+ÕTѦhEJg¿Âάœkpn”¿r»ê*Ë[yZžÊsrW^Ruå pSngN5pñwoc-u@[>CÐ )¶V­äÓB.1W©š«ljtU(êr+RíW¨:¬†ê¸‚Õí +¸ûäÇøÜ«äuo§æn¹kÊUsJ•5_–Óý#9ÜÏ«Â}ƒëœ*«s:„þÝÄ»v|ÚOýA?tñ¹´bq¾o&ŸFò‰xL +y,j¨µ+P[¥úZ¯üÞ ê¼Mòy“ªõuËã‘Û7)—ï6Uù>(gÝ9|'e÷="Ã÷Ù|¿×Rßuޜìpý-ĺ•V|e€:„^è„$÷Z ‰œ"ÐÀs¡ü~³|õKå­wª¶¾Fž@½Üˆª­rÒª Êd%×ÉÜ"#¸O¶à Yƒ_”%xQåÁgTxS–J}NBw3ñæhù&hÅ¡Ú¡•{Í…ðƒ—ûžP‰Üa«\a»ªÂ.UF|rFBªˆÄäˆtÈí——-:'kt³,Ñ=2GïWYô!•D.ȹ¢âÈ5•„ßWi8§{ˆ¿ Ý5سl„y€× ˆCcˆ~àå;7­zUS‘œÍårÄ ÙcN1d‹5ÊOÊïQy|Læøj•Æ7©8¾SEñc*ŒÓüÇhŠct ±×UÐü® +›9?Ñހöڣس^è€V>7C„ï‚Pǵ§Irag+Z +e´•Ê–°ÊšpȒp©œÂ1“xi²E%ɔL˜Æ%ÉI$1ILY’Ó(‰ IpB'žÄP½ø¬¶œ¶oÚ+h{Ñï‚$×qhä~ü\×r߅uc ÊHÊÖ^"sÊ¢’”!SÊ©%) +S jŠ¤ñVé `Óø«ôVà4NaRRRlœÖäÐIّÓ]hÏ Å†d “ë6hŽ3/÷«ø/¤LH/ÝS/9ôätï5þH’ÐÎu ÷‘i࿏{îvâw¿ Ø#™±±¦ÛA<ÌÊ0úˆsqsc,Ƹ1’|Írl7ßãmF1f#—ùÍ+ð>¿Ïiú<>]äsœ÷ óßÏçš4ñy%ƒ¸Ö©lH*åP_ŽŸËràsÀN0+8t&ÙܧØH¦(²)^bª˜)<Þäv ;[‰i[A×:A=Aã8Þm9d E¼–¬êùìA¢²Ÿøĵ·$+"ùo¦Ë<8ÊúŒãߐ;ÙݼÙl’Ýdw³»Ù쒓¡!¹ SAn +Š Gñ@e" +ÅJG‡CÀ)ãØ)R¨ÖZ§ÌСPflÇik©RA Te¬jÙ~ÞìÛNÿøξ×>ßç÷¿ßóe`À.˜ÉÑ†³ñ£?:ñ£›œô˜…ÖMðº'òх˜í¢.;qÄö+ü\̎©•õ ð 'Îü†)'/aÌåï¼™S‰}«É 0ÇPc7ñ!gÎ †Œyø±?QK9d–’“%Ö .ÁéÅó5±ˆ‰u!Óóüù}ñ0ókl‚¯žõVë’ÐO)å²^ތ6)±®“`Š{`©5ô=Â0¶‚úXI}¬ÆuæaÌÆÞK}ö’Ðu\‹ÓkWr@nãzcÕy¾GY<ÓD^%ÎÃù-ćiô ë5àM‡7áa‹ó»&X90ìÆOsðÝ6‚§Á&jä³>괟d+ÁV곟Xl!y}K؟“6Sϟ’žû’!ˆs=¼U|R<‹¤¹ð/²Öhr®뭁H(!0° XBŒÎqaðCð*5²?Ò+8pÐlûIì>’··—÷|ôê ¾ýLÚ}_cˆuM;9`ͅÄ9›ø¦¯°x7Zœ}—Éóò€ÂØk å-Ǹ(dD\,£FNàÇÛø?#'')ò3qË¥·ú¥£|xäßþCul¥åó©b³Šú3×»ÉZ§¹>¶W„]œËäyÃD&ÏQp°$½ ÞU\0±!V¥sÔÈ%êãµq‘ú¼@ÒϓÜsÏ ,QTg~)¾®!Ä»î<òjgÍ Û¬˜š¢çÅÉ13 BMž÷[ ’IéŒÉ>—ÀïÁÁeðWð9ñ¸IÏÞàнÁFsÆºFA}ÉpåC&ký’@&0@>‚r0Œ€Öuô-ys%ô ÊñkTåm’÷År‹Þ YWIδÕeý·þ‰{1܏é-S׀Cà¿üìXØ5‘ȵéG6(пјwUÇH}‰røúá:~\e£ø”†½ŒúúúMó! s?ΣiÎjéØOZŽÀ{šðÝ$U1Ò#¥1J ]v[>Ü_ƒ¯Àmpmu }÷)ºêôÌ'hªÐ—Q*çðã ñ8Ífy +Õõ>ºî=à»è™wðã$ñø) tŒ¦9Ïa|ƒ$ÆÓ×љ¯Y¼;Á6ÐîÂù¸f¥ð‚•â_)ûÙú…ÜØb¿ Û5خǶ©Ú&b{¶gb»ƒÖxû µOË)¥5dâÚt;m´G/QÀß'*;ˆä÷àì›ÀÓà)p ¾¿Xåô¾Uæf{&‡ÐwѺИ¯¡íöP¯àÇnâñã.ÞN”ߏíÔÈVjd ~ôÍêEá=×Kxó:\?דDtœO€Õ`X >¶Êú¤ÕÞû¬-`‡ˆU±2°›K«ú@ ¶+°\£g©§Q”Q´¨‘õÔH/5²?ÖàÇãz ûOR­ýz”æ^Nô–é·l·ß°ÅǨ Ùc~g­¶;hµ$»ñíi=±è• »ÙlYnlá þWÀPƒí:l7`{¶'Ñ!­ØnÇî-àn_Ï%sˆÅƒtAz·›Šî†×D—…w¬mÀÜ_P|û¬ت°”Ž]>ç`ÛtdûØJÔa¿ûã°7‰#u:ÕÑIDæQ±R-4ƒ,M§GZYm‹þþbÿÛVì͵›Çy,™GÛöÀ1ÙC,ºˆE'9é 'ÔF;5:KQµáÇLü˜Ž­ä¥…¼L£>¦ðf2ž™‘™HôšÉà6øñl°ãôðˆqÇ~+þë9ò–3’Ì=\·ss”°†AØOǾûٚÊÞ5E^8BpDéÒJ8jà‰½ÑØnV_ÁÛÑD¬‘¬¢*ë©àïPé#©ü‘úĸc7|›8æV¦3‚püw1ŠÌäwGðä”øÈ6Q)pd‘Gnà‡§žRxªà©…§›M؟LdÚ4‚HÖR1èÍ:g(UWÍ^1DwAŒû˜¶Ã½ÞÆxÀ÷ÇK›#>6sßÄó1ø3:m“ÒԐ`‡Ë€)®¸𔰓—ÃU W\£ášˆýxÖC”–òö v—~¼ÝÇnwœè]·Al}¶øè³Ð`ÌãhiÍ`,÷ Y̹¼«ÃŸ™I‘–¡á)Õ&;U“”¯¡É^U'‡4$y°ªRªT™R«ò”•¥LPij«¢©ÝŠ¤.V8uŠS_T(u)GÁ9%ßRQÊ}¥²_Á±ιŒ_mŒ>“@êxVË»ü©ÎJPµ=Eՙ™’a¨2Ã¥ŠLÊ2‹TšY¢Á¶rEm5ŠØ궍W±­EA{—öÅòÛ×Ékߢû^yìÇ䶝U¾í¦òíßrÓF8–Á×ÃXÞÊ¸Ñ ÁHjF¡JޗãO™‘¨²¬4•:ììÈVđ§’,ŸÂYÅ*Î*UЪ"ÄÏ î3¦©Ðè’ÇX¢|£W¹F¿\Æ~9ãÊ6>çú>`ßÄþb¸:ɧ2ó0ہZ®«yVJñ)Ê7W‚JœI*vf*äÌRÐéRÀY N@¾œ¨¼9U*È!k¬ò]S”çêËµHN×Ze»^”áÚ+‡ë˜ì®³à¦9÷ALk°=¾YH¤IŒ;cÒQ5ÜW‚Rü‰ð> BøÈK?/M¾<» +ó*Èϗ'ß'·;¬ÀÈÙ¦A׃A˜çAà‡·à?L— p”å†ßÍewÉ^òg³¹’;¹ï†ìn² ¹,$„$Ð\ TÄ ‘’ +„‹­ãD¡8Vª^¬µ”BqÅ2¥…Z†N¥ö6¥#Œ2ÚÒ¢±í ØÙ>òÛq˜—Í;ïùÎ9ßùÎËo÷Òyn”'È[鐫Ú%gÀ+{ ]Il% +e VPÈ!ÀüdŽ"Z‚ˆ¤ º"ø8Œá<À<]ÕLpUq-Ãî@™Ô‰håܛ_!˜ +²¸öc> )ë $ÈUc—£Ö¥¤ &ÄSÜa +(ŒÁH w#Éâ)Â<a–s2…9¥C§>ÔÞq-ÁîüJò€íFP ª¸.ã~1¾äñ›Íµ¿~L{‘ ®MŽH²ëiô 4Ú©“ -JG l”¢šl+@È5¡¯¢c`œ÷*oð >40E70¥c»Û­ Ô +¹WŠ/üæpí¯¿ýdK©—,1!ÊÛÌa7“¥•fÞF3ÑÐbl¢‹ál m› ¨‰B&†xjG¸´ä›؄øÐ׶;@ˆ€ |øRÄo.×ð¦ÕÁ”<“å)Æá> ?:ðc‡m9é&'½4´^6O/±èÅáòÑ3˜Jº™ÎºŠs™Üº˜bçàCg\½Øo3@¾jÊi¿y\g6À¯^g›”8 9¶@/˜}øÑoúø1DNÑØQÄCÄb¨…wDì&¶A„ÛÀù†zè‹kN#á ¬³·Ëá-à:‹²Nc½nx_âüÊÄ`ƒ=°Ü'Ðd6–âÇ2üá!'#ÓFW°?–óâr&ÄeÔåR¦çá‹Rô‡;㚅›Í¬³žÔUÃ[Ìuv ~Öë&•v–À°6ÉIZFùPêŒIú`%XEnîE㮥>Öã‡yl¤>7’Ô ,f=FÖñâ5±–º\ý3KTÕh\íð5çéíÔ!©Ë%Î>Öë擤!sÖ`¹ÂⵆÎ1kø½ÏD°†ñ- ^[ñcœ½²æêsœX|ÃÛ0´•>ñÐÞCMlFY} ˆs¡ª$ÖùóéA ‘n–¸ÔZã¨5d›||ÎXÆ÷`«5ˆ?b ¤ß%bŒ—ž&&Ï°o_`¯¼Àa°ŸMö<~ãûÖH{xy7ÓôÎß1ÐßR”XûØÄ:ƒ8{¨WYëü†ÅIøÅˆþ%@‰#_&…ÑAð’%”Ž€WLႧðã$ûäuŠý8±x‚WXÄQ>8B>¬0uUJ É&Ö^¶pòKd˜ë|GÃ|Fw³UVÂ3¦]ö“ÚÎ6ÚKD“_PâŸLpo÷ƒûÀFpÕ*%“û„U~/N”£ ›)ڇ®ÚGNö¢ívSOáÇøñ8õñjïQôåvšø85òmjd+~Ɵ9 D¹®!žMǧš)‰ª±;Lr+ªj›OU¶,UÚòà*†«‚.V_½¦ÙZUbëR±mP…¶¥*°­Qží!ªy7^ÿœ'’q~ãú&÷À¹ˆ±§—£>š@¨å^gU ÂcS…;Y))*wzTæ0Tj÷«Äž£b{¡Š¥*tTàˆ(ßѬÏjž-Jõì”×sH÷OÁUð/×ZlÃÓÇ(ÜÁ¨Ñ " Tr¯ ”àOï¤%*ÏHV^ªSSSÝÊõÊIõ++5W™©ÅÊ0*å7BòMJ3:eòKå1VËml–ËxRSŒ—å4NËa\ŸÉ‘JßÆöbøæ1ǐ' ªA9÷J@!Ïóñ%7=A9¾$eùìÊô¥(Ãç•ßç“Ï—­´ôP&#}º¼éòøcrûçÉõ?¦Ë8Ê« +Ão6»Ù$›,›Ífw“ýI6›l~vIHBHè&@˜J$ +†$•AkJJÁJ¥´RZ•j¬Å¢¢ÌXµÕZdZQ¨µ t:0ÕVªv¤Ú–aèV;èúÜìçè0/ûåÛ½ç=÷œsÏ}o +|ŸÓ·Cy¾d÷}K¹¥Çe+½ ï{²y¹3°½¾ë‘À݌‹sÁlP⼫¾¯À—`™Mþ2»|eyýù*ñËðÈ(!ªUh+ت‚`—œÁ>9‚ò7ÊœRN-àF Æ¢®‚Œ6`|K‘ZiÐ +’ Ä—¢|A|ñlòrå :ä)wÊr©(4K®P© +ùQ~¸RÎpBŽp³ìáNÙˆö/B׏܆hD †Ñ²!|½ÊÆPNc%|½aÎ#hŽpøŒƒJF¥0ߕãK Å¼›bxLq㤸Sˆ÷Ôn~ǐÐÈ Ð€ (ÙúŒ†ª¥%„¯“‘¬Ôóç]%\a8 ”gïÝ|ïJHùlÓÞH“Oq¹4d›i ­X´‹6´5òÑÆàÚÆ|ՆžoexhE©´0WÌ!ÍøДÑ./Än{y೎¿«áŠÂY|<—ðÞ ¯ ³Îsc‚ZlØŏvüè0— ý:r’楉EšEéÀ0›¦&ÒÔåuÓüŽÙ¦ó0kþ@3¼ÆúŒúÓØnIžkñ%ÆòŸeð–ðÞ o!¼y˜Ìa|å²ÄHs©vãÇBüèÁÅæÂ!'KÍA#KY¸d>`˜]‚*YÌ ÕËՃr\tŽu¨úL-³1Gêšùl œkàŒ€ËKx_ o¼ö8I/9kAàè!Šh.\òËðcÀ•½øÉÉ <ÈFV²x%ùXÉP¹b“´œ³1ÀÀ¸ì4"sq}F (ßvxšØgœU œ¿½mìÞxm”7‚%ËÙg‰#rVZ‚Ç®5ÄdÂc?ÆÌ%DNÆ)¦q63†ã£äc= +qÅ´õ¼öyÖ¼# 3Á×6\/5ð†ø»”ð¹áÍï™Qÿã´øŒÐûˆ%úÆ,áiD e§ ÄÆ$~l¡6¶“[)°Íl&`“,Ø4Åoö!š˜$>öë2ꄯ•ýÖóMSÄÙÍ~†w9XeqrđìÿÇ&Áf°ÕâÛÁíàNjänüø µq/õ¹‡Xì¦6ï,ºƒéaç“Òôo¤©©“ý¦øºš=puV?ü&¾kÁ¨Åy“ÅG«C&gð–åÈ3Üd…¹L(9!éQjägöÔÆêóky?ۇÁG>-}‘žýà)éþwÕžk)Û +öì!Îù#–¸°„î6ko,c\ɊðÿòAü(øª²f¥ï‚Cà~åÌå²y†Cv„Í&¨‡ړäã{OKß¹¨Fê*Jˆ¼¤ªÐìy“W³Ï=烀%¢ÅÍ †çqe‡#3 pÜHáÇå†\“΀³äåjô<9y™¢{‰@Ÿ&°/|N:‰gT ·î"bcö|'àkÖìðuÐâ4Ãà•Jg-®_€-¾__ƒßƒ?×Á[àmÎËrr™³z‰‚{Ò¿î”þr€ßGQ +•-¦@¡t¥÷˜%þ®"}€vĮ̂N£|S tÏLF×8$P¬ï3\¥PßE¿¿M/3y^b}ƒ¹ê"Éú3ɹ #LV¿Ô9¬ž˜™ë2l+C +3l3ÃԑÁ–Ä)e­X›Å%üx?þÁ<ó>jø*Šù + +þ-tûëL4¯áÇ&¹ßqXÏsh^¦x_¢xOãNjøqJ»tR{õLÇ(Ž£ú™žÖßPõÊ&˽Üvƒ+p^¯Z!¤‹3ûNe–8ËqŽYæ ÚýÓÄóøñSâqŒ†u”Æñ êsÝašÅ(æCº™2ù”ž ˆ¿Mñ~“]äô +¥{mfß{ÌL¶ƒmà5øÎ:'“`6Í?š)³=Å|wˆœ|_APŎê±ÛL„籟.ìöÎL²ûi$_¦y=Bãz?"÷kŠ£zûÝDZ}‚§“p_!B%•‹}'ö]À Jà)ƒ§ž(<5ükÄn öçÅt”ª¤b£ä#BŅ9!:Nˆ®¢w‡àƒ­pÜç’ôCȎnÐæ€$ïê‘îµ|_ã´)nÏSÜV êœ"xfÁã…ÇOž*xØlâ¯yœâ…x·ŒH­%k7ñ«xüxœSþspdø;£I쯇o9r£·8+Ñ[@ +ԁ8ïc Ò•£h¡C‘ü|Eò\ +;Š¶{²ûTn‚¨‚ö¸ö¤üö6•Ù»ä³÷©4wXÞ܍*ɝ’ÇöyyrÃûgÁEðo²šÑØ/óè(Ë3Š?³döoæ›%3“™¬$$`BH@¢¤ˆ ‹€U°d“­ì(Q¡"‹¨EED +TP‘M(ˆÈ–º€- âZµ"¢‚"K¦¿wæ;=§žþÑþ4œs3_æýîsï»Ýgü}àêÂߖ6¥(M@ÏrAˆk&ÉЬõØ%êvJÄé^ ;’î KÈ— gœM@™ø ú³Z|ÎâuÍ9I<Ž9âv,—}“¸l‰+팸¬ O8:ê¬Câ_ ªmkÌ÷<bÔõ™$ìµJº×.!Í)AÍ-A&.~OHtOÈŸ§H¼ZsÑ´ÖâѪŭÝ$N­VÚ±i³%M["VϱxˆÙsRÌî„Ü¢Úx:À{u€>4ù ›gqéºYBzšt»ø}NÑ}.ѽñz½âõDóEÄ£gqé%âÔ+Ä¡·›~ƒ¤éÅ¢“NÔéy}d8/aÇKbñrgÀß¾*bNEˆ} +Aß3A ƒß"¿Mü~‡èºK¼º[4¿[<~MÜ¿¸éâ ÄÄÈ[°©¤[Š%ØVÌA²[ärÈNjð?‚„ôåý]༆–¤e˜y|Î1žG@(h’`À*þ€]ô€S¼@î Kœ!Mìé>±…ƒb GÅÎs˜Ì)4 N¼§_„(| §SCú¼ø,u%¤7á­$ú–Ñ’4øœÅ³ ¦–`‚6уvñ-dwºCœa§Ø¢±Ä¼bŠ1a1Äéñâ€æ1NS§aȤϋ„Õ8!5FÎ -EÏSw'Ã:À{Uû!Æ<€\>Çy¥–ô0¤§‰?Ý*> …­âŽ¤‰3Ã&¶˜C̙"Ù,ì\&57˜œK?‘GÓš× +´4J¹C96g! -dSCI23!Ýrmœ3™ò‹AÈæ{ŒZ"ÔŠ˜%ô¨I´ “¸cfqdZ$-Ë*æÒ<˜|6xcw!^"ª0›Ã…ù("ËqëÒkÖNåƤ”‚5Œ!96"Mç%¤3±¿ CÊs˜þo²¨#ƒ:ÂÔÁ2ÏÏÜüÖÁï¬È4ås¡4æ/¢Ž¦¦%žÔÁRLZšJk¢”¸M[³‰üŽf¥˜è +öESjh’ërٓ¼³‚\¾gRG¾Ðùì…×Íßì¼ÖB Ë%ÁxPÂEWjI],-™“VÌI^T0‰ ªàG š¿‘FZќ^IRkA#VNŠ,c.š'äZ–Ï• À‘Wœ:ÂÀÏg/Ï\ðÚhÕÌL1—$ã’iêRU—kkuÑRG[ê¨bNÚ±ÙÚáE«ÊAΚh˺¼†ýنäTI‚n}RÉ»Ë@S´å3$Î(õøìå¹ Þ4Å[f\âÈ"˜À h /\4 š¹éD×SGwêèΆê†݊¹+yލC€F¶3‰­gDõv6gTû„T” Ÿa[>uÄá Áë…ׯµ¥¡µÒ4UFÀéh„®Fèºô4¥B@?ÖhöI| búaX_ôá¬êMbêõˆHŒù†Ð”–ð”°tŠ¨%Þ0>ëøìB¯¥ÒSí Î. ›¶z$Ãf*|Õ¨j@8‚:F³FÇ0'£YP£yùHŒ`ÐpΪ¡¬‰Á4°·ÐM LH9:K˜²Fðf°ý­áççæöÉ ™âT{|´«„j¡…HÀÛÀh#OSÀ4puÌdÎd¯ÞÃäÎàåÓq'óqém*i~R½Èø³RŽÞBæ7“ù ೛%lîjۛ ÎZƒo¤ÁÅ£‰Iq©@>CRMÉ}’jPØ~D&š%êx’µ±˜õù8þ(“ššD˜ç¬šÇ|Ì9*Ŭ«Üvœ‡h֘Ws/ƒw°¡QqN2ø×, ‚ðàAI5F¼Ž¨(´SBƒ)RV‰$›—M„ÂÍì׍l²ux±’Uˆy–—¬d.ß/ù¬«(ǘn+Çí‘Д¥<npÎ5øK:ٔ­+Ás’jU³†¬dÓ¨š·Ý’jb€Ù+ï1'Xøo#øMˆöðò½c[ò:ñóÈ>ÌЬBî݆Ö’j>—Ú׍l[ ® Þà{Tœà3ð8؂rš99Åú<Áäc¢Bv‚OUñÿùÏd±¦ÙN—[óúü`(‰Æâ™Y9¹y +6izEq³Òæe-Z^YqÕÕ­Õ暶UíÚ_WݱS—ë»v¿á×7öèÙ«wŸ¾ýú8¨vð­C† 1rÔè1¿7~¤ÉSn¿cÚo§ß5ãž{gκoöýs~?ïù.xè‘?.|ôñEO<¹ä©¥Ë–¯xzå3Ï®Zýü k^Z»~ÃƗ7ÿyËÖm¯nß±s×îú¿¼þÆ[{÷ýõoû¼óî{‡>øð£Oþþégÿøâ𑯎~ýí±ãß}òÔéϜ=ÿϟ.\Jü¯ÿôÿÂõ›ÌJ±]Iö YW¢ÓQ¡dg+Ýù/RÊK”ôr´·Râ+•úk‘ßAéïŒݔ7) nƃeÂ-ʅ¡Øp›òa¬2b"NLUV܉w+3~§Ü˜‹P~<¬ y G+Kþ¤<©Ã”ç”+/bË:åË&eÌ+8óš²fòæMÌy[¹sPÙó>þ|¬ ú‡¾T}£<:I?(—Î)›.^JŒ>¹\Í»%À~¾þË÷_¸_b2™Í‹lv»ÃáÄ·Ç£a…O×ý¸ áG8‚#1<Á\Á|ÁåLҚ”7?3'é Öt뮶;©fÀ Ú[‡¿mÔØq&O6}ƽ³fϝ7Áà [´xÉÒe+êØ.j·¬[È¤ÆŸILiLŠT*‘‰N„¢©hýòj~Þo¡ø»'¾Gô©~8î3gϞ;wí?]¸pñâ¥ý‰ºÆ¶ÄÓeÞÄÊÊhbm‡üÄÖ®-;zW_Ú5¨æÔîaãï3ûЖñ‹ö®›¼j×꩛¶­œ¶sÓ²»ÞZ»dæÁÕOÌý¸î±…G. 54ÔÐPCC 54ÔÐPCC ÿw +ž¡†u%^¡†]½ª/Ô¬9ùúÐ _ԏºÿ½×Æ-~kóÄçw®¼eë ·ïÞðܝûV¯¸ûåOÝ÷Ñ¢'æ~¹HÖPG ÏVFë©áÕ®å‰=½ªÏ¿1 ÿ‰}C&|±wäœwëÇ>ùÆöñ/n{y■/MÙµzÕo.¯›¾Ѳ{ß_°dî'—‹×°Š6RÃk]Ë/¾Þ³ú̾þýïÿ{t–tžp|g¦™v§zf¦šfgÚi;f§ûiçéØîÌNÔìд2/AñoF)TLP.Áðå EÅ["-¯µ´ÌÌ)'-û߶gÞ/¼õÅ÷ýçy¾Þ˜áŽ€¤N"_£ +)“U£k„aê"a¸>WÑ~›ՓĢ™¬ ð?J!ƒìÔ& vøeÞàzz¶ÓÃcòÁ-Ì£>ÿ$CkS®F–ŠkCe\ ¦)Æj3Jñ-)|’‘ʉ鱶d(;¼ÔØnZÔÚÿs®ÝõôË>w'C71}f¿DmäßäÄX4 >J´6 ÝüÙ3ÃæO;F·.×Ìþ^²h»ƒÎÊÎÜWã}®FÍ]ÇÏ…Þ +{óEÍü‘¯"‚f(/cƒ`Ó4„µ½Ñ¬ÿ¤çñ7Ÿh¦^!}wø>8¾5œÞKÇhàʙHàí€AΡ Ô5à.-F\ |é{Gq÷{ëá»ïim=Æ/ÿ¤Zý©táçUpàûpdK*8¹+Øï#€K‡ÑÀëD0€Ÿ +¨3þ{ÎàÏû’7ˆ²÷1ö7ÕÁÚ@ÁæÏAþî•àÞÁoàäPa·È.57œd0ß~DˆK2qH9íyžþµBCO¬mHLUÖÅ1tՔlƒ„Ì2Š"8–¶dX2,– K†%Ãÿe(€ %6@d¨u= +äםçëüý¦j„áò°”^A³µ€\¢ËŽ‘*´†ºÔ$,!­µ2.«KÃêãGv[ÚÃ=ÈÀú×ZP +$Aê=]æüüž+‚#†¤zwþ^ ‡X¦aFÕ*²b«ÓZ*SR»D ™&^\¾™Ëîµ4Àúh`C¡Í@v~'¨¿x¨<\æÕ¾þÏÕAÄGµ¡i]8¶^@(W±IŠÚ<Ê}IÕXžAï-ed›YÍÜDV¿¥ýa(„ e¡úü „ —·Zÿg:8éQCHz§,¬¨I^ÕÀPÕQš%ìx£Iï-ÊÊ0ç2˜™¿˜,탡2Ad¨ j—£‹ºk.sú[°g-‘ƒH†Qæê$Xi}y„J&¤èE|š‘ËNîe2æÌæ@ZFÉÒû£ÊOü ÔA†F—# zw—×/؄9Ќ¸Ýވâ©ë0RYe¸J($é9J;“CëÉ`ÑMô‚œ‡ÉÌ“¥}0° ïÀPäç·/69ùÝàæòªã&ìIÙl„ßÑ됼:y¨¤¬*LYT~?W@l»Í¥t%Æ÷SYŒÔBf¿¥ýaàC†*ÈPnû;½Ó‘×íW_ôހ™}ÈÝ]·ÕMÁœ*ª‚'Å(˜b¬öN)¾%…O2Æqbzȅ)}¤¢Ì^K…›þgX $'Öå¹mo N‡_u_qžð„ y“[»r=¢PØ"fU‡ÖdV†©è¢p­„Ø=!ð:qÜ´.Kû``ïZJ ƒìøú÷šsÛ^·9zñà²Óøè5ÓÈ-’®–&i *ઑ¥9u(Iº#O¬À©bDQHnƖP èâ”VKE¡2÷jÿðVwnëËÎ '†\G&ÜüÚǼˆõý°Ô²Ö ¼m0ÿNJœ\‹–ÆÉ°u‘Uø†ðŠH Z« %4Yà@†"È Þÿ5PÿëoÍgÿ1iºp`䉳ãÀôߦq/‚ÄìŸÄí€gÝÕ³é(M‰Eɱ•„Z¼,¬šT"V $´KÜMË2TíÿjA}ü»)ãÙÍÏö™ž9;g/û(žÞĖ>ò£æ÷ÀÓíȜ„f+Z‡á5Øb¬Š m ‰ŠèÊ@9µÊÒ2v~ jö­š½lí˜é̆¾q»ý†'GíÜ%¯Šç7BÙ#~ä̇ð„äސ´Øt&© ›nÀ磛#XÈûäB¸.† ÓÒx–—ю?¿Sî]1a<úuÿ°í†–)»ýÊß/ØW/¸zòfnÀïNøcSG‚Èqƒ(j¤9, ߏO ë%¦¡ºÉŒàÎèŒÀj–¿1!ÛÒ@ÉÆπtû/õ¿,7î]iøûuÕ䁇a\ŎUÇq\¦3:Z§¶:.gÆ +8g܁: +ElA–,DBHHB@¾„- @„%1, { „E¬¥Š" +ZDÐÖÿ|§íñ>^õ‹çþwõžó>±ýL³pæP8:HÁå"ÿ•—Oêl@Hü4†@D E> E…ߧÐñ÷h Ìx 3ø{ =–p—Ã~ß@¾ÃbI»ËbüÆΆ)Ëõšy›µ`o%†³6…àâ”öÖË5~)ð +}çOztõGr(î ‹yÊÀ‡ÌĆ¡ŸÄ_ x ÷{œL|ß@¹mÅTÿæåÆÉí+5s7*àÄNØȁ3GRà¼]xž£څøçŠÿ)Üó†|9x‰æ…^d\ \dyû¿bûø.pP¨…dß÷m®ký²Ûk—µÎm_¥ËÍ"8²ƒ'÷qÀÁ*œáò)Úc{&ÂÏB¤£?P|ñ5 +b} þüà¸\¤÷ÎhX½L3ùÇå5ðéj1|¹‰‡¶%À±/h`·?œbàÒ!4øöƒÐ£( ÷†ˆ^@9é ´S—aã±6îÀ¶½‰ïäïørö¯²Õ%'¶‚ä«ÝPíb 5—íAà¶(Å=‘)|FÌøìëIÉS|F¹!†'ÓÑòÝAcI¤n#V¶´ê4j¼Bkn    ¿{C.bÈE ¥ˆ¡ÒaԞ·…‡=Ôú»½’aƒg*"©÷tî­VîP*GhHL­ÒÅf)º¢sUíQ…ÍšH¡¶%¢²£‘PÝYµ¦ÝÜ~5ì[y‡6‚èøV!†zgkhpw€¿K +Lèy}\DMå3 û3Ù]WÑŸ¦ÖÆdkšijJ©®‘$ÕË#d=U$y—¹AÁŽ•‡ +¬7BÙñ-P¿¶Õ%P¡Ü_6†`ׅ3Æ$äô‘âè}N¬¬+5A¥ILÖ6±2ºUŒîóê`ì#%yWFÊSE½ E[V\Ks2§[•˜nh`çÔ±ÅCbšx¨˜.Õ è•½æ|Џ +Cű- °ÿÔNÖÐâæðVãí>ߊÆ=jÂÇÞVy& ¥¼»˜Þ Ée¶©³¹=™†š”Àή0šÛ¯†½k@ˆäGÿ +*ÄÐîh¹Ô÷ý\¿‡ÇÌ°O؃ì^LA›– m¸Ù(UÐ4Å2fw®„­O'p…¼¡xaé0³°|€YPa47(üt%ðƒ1Ô µÝΟ;Ï\0^°›vwŸºívgԟÝg ÉoBþ®¼™Ø l ´æÕÐ;Óe¬^Ž”cdUd˜¢Ë éâò~šPb07(úÍPf¹G?»Ï^÷œ;87ärzú¶›ûĸ~äŽ_|‡)8Wх­·„Õå5›S䶜ÞS«’rûI’ì’TdŒ¬’èÍíC!b¨@ õˆAsú/õç<»qÞvòž«ÛÝ—q†ïýXMCAÙRFÄ×àªÓ¯Tìbkt-¹#²šÖsUÆêÃV%ë±Uù}8Y±ÎÜ@€Šö®©åŸ@ydóëŽÓ;fÎþûјó©û/¸ Oy`ÛðQ\Gg”êCٝ8 §•P£&*)ÊÈ&bµWÇl ©Mì@×fvÖæ˜#b\MG6Íël·OžÝ?þÀñäw3.®}ÏÜCU(šä&:©Àš›Ò‡+au*¨mDYD+¹6¬™ZQÇ(ƒ®±¯ù«ÒÔ~ʌ&sƒÄPºçcP|¹öMÛá 3¶[ÆÇ¿Ú3òØñ”þ¹ËE͋KAòIT¤` —9ŠIK0ás¢ á…ä^RéÕŠ×E«î`JÛØ2_mŠ¥M«67n·€ò®ՁÕ/tÿ]wï¦ÍæáI‡}ºYÇSšÅóßÔ½tóN£Âxh*w ǼIHŠº‘N¦d… Òr0Œü #‹ïoH,BéSŠ}úÒÌĈA¾û£7šýarÐúã‘ûÇ>Ñ=sØß¼töDí[gçò×nžyÏQAÉÓAÖ$ŽL½N'3 cÔ8ìFBÈm}‹Íõÿ.)u#=Õg4Ãì b›4~nñ¬o·ÅèøÞUº™c[šíöËáÌQ8ý¯Ü¾MYByÅ͇ÐfÃBHOI8Âtû8š:K +šŒ |˜Hñ{…šÈ ùLdšTý}Å«¶íËoÝݸ\7½gMÓ«£[e`³·þÃG›p=ÇÔêÏ¡nÄ×Oü"ɳ@E¿dø¡çYþsì@¿\4êyj÷lf°÷lVˆ¹ê/Ëo˜Ö.Ó=Ù´Býjï:Þ*€»ÿÏn½Æ%}¨¯ã¶êl­ÎNmg[­µ¶ÖÉS›e—é²ÖJKÉÊnÞ/T^ð†¯ ‚ˆP@QQQ@@PA/]ì,«Yiåén­›múìÿéôÙûÿ»ó¢¿÷ßÏóâyžRؽ‘ +û·eƒ[ +„ìÁCä>ÄyE@²÷)H;ˆ…¬Ãaã”#Ás´£sEÇfKûϖ¡î?æ…ó,£‹æµ?_öV3|ó~lú¶¯ÎEfAx8䌃ÀíáX·HÜ©?BÆîÈþÉròê_(Ø{Jîh3[ÌÓ^^0_¾S ë3`ãòp^A€¾ˆ½kO÷úðÝØoýçtâ7‡$磐Š”¾ådmñòÖзíА +P¥+ß²£Š6/… +äfÕì^ GŸpÖ„1~Ïù)‘Ø$ÂT1|RB¿’Í.»˜Î玦ÔTMª¯Iˆ†â千±š¦è.Yo„AŽ¦7†7†7†ÿSCÙkCɦ¥ÀC µ»?‰—#4wÆPO¨Çù?­NÆÝãfo0©”qZãbNYÅùLnõ¢ ~(¹VbOKmñ²k¬ZeÄu¨õ8MÀB ̵‹€‰üՕÛ?„ú?©§#Ȏº‚,ØkNøD”s§:#ã:'‡>V\À9OeÔ “ØâtžÌšR­2'‰ÚLø掞8µN£éhmנ镡1”!?mb#ù~GPqEfVô¸ 7UO$ó²K.”R+‡é… ¶\f‹9³\cL­Ôu%×uë›MêXy¯ߪoNhkG°WüÏÀF 5ˆA²k(ö9‚ÚÇԁ˜ÙÖÓÁZâð·$)9—«3ËΕçíÅ4©™R¬éÉfôi¼ÞNb]Ÿ6µÙ*MZÄIÊnAӉ¦W†2ÄÀùv ·-‡&Ä Ú·Ú»€6ó[ÛɐiuLâ Ye¬>3ÂÏYKó”ƺÎ@eõèòæ6r½U‘ÙÔ/"4õ SÆjb«MÊCb"5bè@ þ˜ØÐ‡í¸¤IUBþEI*w¨:SÒW‘«î.+Ô·•[iÜ>9EØߔ+±U§Kør7Se@p^*6¾õˆA¶ó3Ðx¬Ý!—Yƒæ™!,ô!*y¢-žvANàÛEéM&AŽºƒCÓ«˜ £´cÓýuԆnv£C’›Ù$eš^X_/.bm[rÄ õøºüÞí‹yb ½gŒ \×ÅÑÏ)ÖÆ´&} I­æQõRV‘©Á²Ôñm•ôz;›ÒhgæÉúyÊn4½6,bhغ ;WB;bè>èòÒtóØv»/œðKWtá:A`jNmÒÖgªå‚\}CE±†Å´ð˜6N‰ÐΠ7Ò¤}…4Eš 1°1ˆƒ1t"“÷÷/,Ç1ÓýAa·úO¥\4FÙ´ñC A¢§·J„d°2ßÈ«(±°8ƒUm§3©ÅR µHaD”êðÊ Ø°$[ÿ­n+Aï¾î÷¾ß?³ÃÜ + ›°cSΙ# ͺØÊvU’D֜ÖZא­ã )F– ¨¯˜Ïê/à +(ÜF;¹Lj!—¶Ñô§¡ +14!Û +èrÿf¦³ýס£^wÎû‡Ž„¦ YÃéÝ]1|•6¡Q¬HUU5gv²Å¹=Åuts¾°ÔšSͳe׈2xRKFE‹MP8ˆ¡1H·|Z·OgîkŸÙ1Ûž÷ñ¼5æzq4„`µŸ.èèÅñdz¼XØFPV(3ÚKdä®ü&Z/¹‘aÉsû‰b‘P+íK©VÑôÊPþÕB¨ÝðÈCǎOfÌ{¿~4ìµõÎåÃû¯]=|æRP²ñÌIZ«-ŠÛ`Šñ I-Ìö´¶|M¶ž¤¢ô¤)Šz“圾¹Ð‚—ÉÌx‰¢MÀE ˆ¡þßï‚Òùos†?éß»æóÍIo±ÉcA¶«‰?c)ґŽÀ]Ç쉗RtI­™ZbAeÀ«òº£•EÆHE¹)B)2âÔ*š€‡¸ˆAìøWÐ8/™1îøèÁðž/o\ñü#ÿ=Øs#¯ǒëF#˜l{t%­/N”Õ“ %è ʸŽtM”–Ô~ºÚ¦aèB4|}˜¶¡MÀG ü5  Ùqtl^üØúÃò›ö¬º4éá4rãa¹ï ½ãÓ8–Á‹((>ÍÊŒç§õ' Ì) 1¦tIDIz²‹*5+‚ åÊ@}ª ò¨ùç; X¿p¦gÓ»·G\—^ººkåðm'ó#Œ»îñ!_Ù´_DÕTXréµõR,-s4A8K`ǧqqƒY•á9UX[~Mˆµ¸6Ю÷·ðQUˆAôåÛ ]÷ötÿw ®\ÞüÞðÔ®U¦Gî›Úg<÷´6º`**9{".#u<‰œp™HË,ˆú™\xú¥;Jg„œg”žå°üÏòÙháÇÙj‡Ý_9LŒ®q¾é´Ä4½kuÛ˽NÍsûwÕÎy(ÿÍϗþôdyI¼‡K¼’;•NÀÝ$Ã'sÓOMäg„]/Ì +¾Æ$^åýÇy9h‚:ÄжrþíÁæL~æ`švú@óÒí ìÞ(W6x»ÓÁϛ<{òq&: ñYBHì“TlÔãÌÓáÈ§¦)‘؇¸ÐÅÑÁ÷Kcî•ÇùßåÇ£ ¤ËçÿÚ»tÞÙK°_gaMßYǙñq­ZGÛuœ©ÖºUjQ°µâV n ˆ¬²‚,Â!„²Bd! K „,dåD©ÛPZ´–qð©:ZÛZ¥´g~Õyæ:ÞÍE/¾÷Ÿ»óž7\ìß™§ûÙ}E;ìY+/Wþ¨ +ü÷CøA"ÄûfÞ?²Oâ /8áעг¿”…ÅÎVž:ósMxô #âôL]dä‹Æ¨ˆç‚Ó¯ÓŒy©ËÈå….ýÿZòíìÚrp_Á‡OþF‡ýËàà6ߙ a»ñ·©^ñå ¹c àP4”Ž‚Š#‘@94ßp`ù…çX(ð^«û<ëØ|ͳ¥”º…<ضœ«JÀsmxoƒŸk¹ÅBŒûiÀ팄ôÃ°ëä}…»C¡Ä3ȞÁPµ'¨{µ÷$°÷½N}ƒs]Ôÿ˜ëÒ +Ëæðà݅TØòf¸½ »VãàÀ;±pd}l …ðÍÁûþIÀm €tאý?än;$Tá‡Ç äC? »ùE}­€Šöeó {,æî· Ñk ˆ|7(Ô„±^ÀÃû›ùœ^–ø”BÍ|XÆλ_À+ù'QTy—ÐZs'³1™Þ]û%¾§~"ÕÜ0žâàÞÄ]á_‰¿,p¶ß ¿þ/ ÕÈPá¾Xè¿àþ× ñÑ/àãO'7ê'fiÒwÕÔ¬åuùӅܲ)¢ò5¡•6™ÕÎú2]ɞHëiOíåÞJq>Ç 7 '8ÐÖ́j´');–m{Á§k åè&h ò€–ho'üÂ'DÿX_”úˆA!NW1K¿)áÔLæóY¹’†[ÿFf—èZº¶y on½š: Lõ㆚ èÈPƒ 5ۗ@ÃÇ+@t௠=² ä ò†¶¤ÀYIVìS~AÆ·õ…ST*e’\W;^Äå^'‰ÄcçÚÚF²:Û/§«—ð¦n΢¶¤ôwñç¥Ît´£¨È@s[\d ƒüðFPœôE¤t$ÍH3Î>çeOsËJï0)ô/(ÌÆk¥Éh¾@>œÓ¬Ên× f¨ôv¼ÑhN1é{ÒúºÕövgÆo´'ÈÀÿh9´ì_ ÈÐàÝ>Ðu6øEgZücinÎ=aqÅWõu7h4á(¹N~ =ç‰"½ãœÜl'h0SF¦I7˜º21MG¶Mál/ 4d`¡ÿB€ mÈ 8´4'<@sÊgVü¬;5ñQç9âTså nyÃç¬êÖá*¦r°¬Qç(–˜¬íFR÷iÚ¾Ž,&#˜{Zs¬JgæKÃ|¨Ý¶„È Û·”‡6@¿èÂ|ftgB¾×&'=Te“îÊHÔ[ÂþH}¥ü®²UÕë{˚Ìúâ6‹¶°ËªÈÓØZs´}¢I/ÊëS9ÛKØÈ Úù'hß· +T7€á¸û¯ÆPŸŸŒ1!O I¸û=ù·;sécâáPc¹ÜƪQ™¨µm%·WY.éë(í°I‹ÔýMÈÁÏ7¹…˜Úـµú•¡þƒÅ A†dÐ|LÇÜg±Ÿ±èGX"nJŸVx«+›9ÜJÚ%rS}•ZÃd5LV%´¶THûÅd•½¡Hm¯/6˜Ø%˜ÖÙ^ÈÀA†fdPì] =ÈÐ{Ì}Æìó½-*ä[[|òSJј*“9(#6aâ"¹–[¡R°©)ƒ‰©|« ºÅÎ¥t9Xe*³\of’{{œí•ý8 ®o@ËÎeЅ úÏփÅoÇs{÷“Èé¸ä WtE›ÁìïÌi2´ȕMe*icµAÄfa<&×ZO—Øki*¥ÛQCÑõÖPÌ:gƒZd`"Ú<–A72‘Áæ·ãÙ` ÷¿/F„L]8“|ÖT4dHc`JB“FF’É%%*± RÏmd`lÇʨÚkêäŽJF·ƒL×a4³ÎÙþgà!ƒÌãMPïù ˜}ޝµûnÿáÒI¯#§‚ï\ŠI¾êH(t˜SéM–@¡ ÊZ¤EÝ< Y_'¤öÒølkWÐOn”:JTŽâºKI­IïlP‡ ,d¸.92h÷ü0Ÿu/}ݾ øtúZXÐÄèiÜð…ø‚¾¾šÚÁ—ªs¤MJ¶¬LGk­6WJX}¥"ž­PÔbÏ©ìy¼ ©Ñ¤w6¨[õÊ Üº:ÑíÔïy{Öæ³ö‡‹G·=º~bÿÔxHàõkQIƒÃqùFŽÚ‰¥sÅB+GCê¢+K´UÆb9#É­¹2‰ SÚ²›uAdÒ;°‘¡ö½ù ÞººÜ—€Éó­çÞè¶/znß½ìÁ¨×ʯ'm¸yÏ×óòtÀ‰¾©SqªÛф–ñøò†ëÉ̚Ñt^ñÅìæsç‰ò4{¡g%wÇ÷Q5g,lm´EˆêÒÄÚ¬Jgƒd୛ ›çÙmÁ“‹»–Ü?°âÆÔg‡øzÚúû÷܍‘Ý‹Nç“PÀø*µ’|3“I;ÇÉ! R‡‹Å‰C䖸 5mÑçke‘çyòðÿ°_goMžiÇ#֊NǺ_¶Öъ bÝZ…ÔŠ"ˆ(² Dö KØ! ـ˜!!Á@BB Š€‚"ua¨Â(nXQ•–¢HU¼û^½æòhÞ? ßóÏÑóܿʪ€ê@ºÂÊ×þ¬-gº¶Î{òŸó~¿´oÜÙ¦ów7¬iòÈaݯ¾'Ê^â EãQ‰ÜG¤Ììû ÌäáTå¿Yü˜›Ì‚ÈŸ¹Ea|1¾¿Hx]&õ¿®’ù]«-E”"͚¹`^?÷eŸõÜ¡û¶óúžaWtL´mšqu¨~ãöñ)~?™;I Ð_)©O©Ô„Çéi¤_hYÄ=âA.3ôž€…¿+âݑq†+rýnW£äË- nµÅôù/çÜ^2§ï©í§ç¦°«gl´}'Ÿ=ì$šõqϛÅû2þ ¥½¦„&þž÷[ftôƒõ‚Cž2.LÀ?+N +z*£Œ)SüžhSѪesÀ¼ s«ß +óÓØ‹ö)[+ã,vU%8ZËÀy‡pßsÁû ð¸T zÄÅ;v6ُø.3 ò-#0l†ò&Ÿ. ž‡¾. x¥ ÷›ÒD  êþ…ꞏ¹|cæì«es`Ó"5ì^Y{×åƒÓ¸íJO‡DÞ'"EÕ5 2p!À8Œö‘ È;Bó©çq(÷òµ7ÚnŸ±Ä\ìýÓv{>F+,U°y‘v.Ïû5Ùก +.›Ià±- +v…AÄî“@²†Dl ¤î €¬ü€¹ï8p}!ßÑ„û½¡ø€”:ê.uXbÌ×,15£óç(`Õ¼b°Yȅ­K2àÛUñ°w œ×‡‚»õ ðµõü_ ØyCÜ7^¸ÍR·ƒÌí@ßqX;o§;ðw†¢]8|‹6sÏ\Œî¦Fþ‡•…V[²aý‚4°ý,¶/û•A°õqp[ãžk=À;œ\ƒÈ¯Ý fƒ+7¸@¢õ!H±þ26:C6Óæ pmœ ßmƒlúÆO ù+8{ƒÀqˆ\ׁØÇD!öP@r†üÔ£Àaù¿g +BÞdI¯RËâ&“Ô‰ñº”qõéã±MYÏ¢Ûhc„.Ɠ¨ÞœGýì{a·87NsÑô·áoÃÿ5díX¼Ý‹¡`ßJ#†o;àíA㠂”cÀcžxË⇿¦ÇL¦ŸN˜HV¥vL™žù „™7(àI¯±…½ô’ª åús©U g’ F3õLcåL£.¾S¯Iê©TSûÊÑ<ÄÀF |dãHwü*°Ë@çô4 £7vÆ„›lˆ ¯%Ç=T'ÓeY«…,ÙÅ<¾ªƒ%ªn£•Ö5gª †ôÚ¦º´–fmR[³Šz®A‘Ò­-KëU¢é£A°i”"µÃ2¨=°Œn›gM^ØiS n¢)<èq},ùŽ&‘q½,]xQ̐ux*3¯@gd•Ôëé +cuvu³&«Ñ¤Hom9vÖ(Ë8_-ͼ¤Bä"ΆyP€äہÆa)Ô!†f·ÍïZ=¦Úpã­¡ÁÑ”: +ã²2EØ)˖™‹Ø*Ÿ¯«á×kXòF%³ÒTƨo‘ÑÌæâ¬3M"ZWMí¢M‹ì,Î×ó ÐöS(C UöK¡áÀ—Ðâºi¦ÝÃá·sþ¸±öà»¦¨øëz2£»’*h“gʌ¦ª¦0O§æ֗çÊeœ +“„]k±[ÌF[³ §³öTNM¸ˆA„ˆAg¿Œû¿€6WÛ鮣ö//wíÄ µERú $zGu¢ Y™.«-¥«*Å\]Y¡ ¾D i,ÊW˜„y:3?¯¹•Çi5ñ¸z·[‹&ÈûŸ¡1T oe­ýçмÿ‹÷g]l^uÙó¼××m¤;8h =‚ÜÓCo«?ÕP™"ՖgW”—²ªK$üúBQq#¿Pnâ µf¶ÐØÊä›[˜üŽº~·MxˆAb3Ԉ¡nÏçÐâ¸úm‡ËÆÉÞ#»Ç®ú¸Üí ¼ÚFî4iÍ +_§£–(ÕJ©‚ù'ûuÕäÆq<,2ˆ´ZµVP”\Q JUd—}‘=„5@ !a ;D‚HD‚ÈŽ¬¢ìЂ VŠX«ˆ EtÄ>󞞹'—s1ŸûïÅ{Þçÿ«Î.bŠX…Ü›Œ|þmz^y3-¯¾9ÛÜDÍ^鮒d L¤‡4T ÿëä~·îþÔm®¾8d{ê嘳Ùø‡Ç@_h[;žV'Í(«‹Ìç×PJ¸I•¬kiµ)%œFš€'¦\½ÖWTÛÍonŠåuÔÅåwWIØÈæe©É¹U'à–®Òz‡Á÷+ýfjoÆl´§Ç/ŒŽºcº}IâÎÀÄê6K ŽÈËmˆ+Ψ¥U\®f\§V²ëãÊónF••ˆÉe×o‡•·ŠÃ…wE‚î*IüÝÀ> ¤áºæfh:­¸Ö¥¿óÝ°™ê˧֚Ï.šþünñ&Öõã(¥ÁéíáÜÌæ袔[‰¥ÔÆËÕ1õ¬Z²(§>D$h ÕÜ$ˆšƒkîÕ+{*%™ßKGuÕå î¸ü×öS[—ÎoŸ{dª<5mq|셽q÷¤««ø‘¾jÄ?Ž?ˆgpzB9ŒÎ(µƒRÓF/oeV[¸×ƒš¯ÖâZªEþ-M¢€Û]5¸†¾rI@Ö.iÈÙ' å7Á­crk]:›_ß×SzöÜp÷؜…æÀœ­q봋sí¤®dÅ ¤§2h¿DäÄ Æ†õӋƒû˜¥¸>n¹_¯ Ò§·ªÊ«W\åÝÓ[îÓ1(”\Ax*²P£& ­‡eµä¦~ûQaì¥Ñžþ·æšwÞØ5¼rr,›Å` ¦±¡ì)||òdh2e"š1žÈ!>LÎÁ¦øŽpøžÃW1CBzè†Àm¨Mà><\( àî”ò¦¬W•þØyPzæÑ¿dÆfµ·ö-ª´-›ŸhxomPñÎÁŽÿƒá¼ñÃ1^‡Rç#¢£gã¦iI„©””€IVšïD6Óë)/óD˜‰~Rå:.Îrï’äòÝÒЬ,õÇÐN©/T¤û´ÛV ÷Ö­]Ð,[µÒãÿyÑâÊ +Æ)uÅ߃öä»‰'/RBHo“ƒþHôŸgÇø¾âÆy½äQ0³Å èÙ +ªëL=ÍùE‹D€·] +DßI­ô(¡>݂ê]Ø+ÛòQë[ÑWý½¥_MŽ¬[èf­Û1ÖÝ-©ëþc×C\ÿDaˆŸ)Þø5:6`5Í»’‰óùäµ\ˆÇ,Ðï+ˆ®ïE$çEqˆ$ ìÔrëVÔýŸ7£z߂jZÛ'W ÚۄpN%Œ4X`®E»3@D‚ß…P Y Ò&(öþäà ©NÞÀvö® æ/ž›ûWÚm½ÜÝåË Œó—FI,ÕË£FîýÕ9"/*J×À~ùÐú– º?¤þ*\8 ¶'CÁå|Ïà X d}ˆ5ôš1RL܁iêœ ®kæ|s'Z8B•¥ˆ¬$1Ú"‹ºÛ³ uó±ªò¯od®‚šü8®”:;ãáœr8˜ €•†8ñÏãÀDCˆ–+Dê8CüN@;å)§/Sײ~²ƒœŸl¡ðŒ ÏZC¥DîݑA5ü"ƒ*{&#UÛd8p@>ý3Nl Ý]80Øã æ{Ñ`·ßÜÔÀç àÔm¤a äCVsØŽX@Òs`5æQd˜3…Üc&À?.‰Æn)TÙC*בֿ¶Ë$²\¨)àˆ¢/ò]¸ÃÙN`¼Ë,w[ƒÃ€V6/SðW1 ½F@Úgáû JUâTÏC¢ªÐ÷Ÿƒ4û€$€¢"1‡ä Bg $ê*AŠÁH·P ' `újAjÈ9HŽ7Zª $d;A, Q¥^ëäjì¿Cë>ÅAk„6Â*¾‹¸8òÞ$lû(|ÞgŠ<ã59åñjCÿoø_j@nE¬†DioK§• õüÈ0W, `{k“¨ŒX3 _¶*ÇâyžëÑBìçˆJÜZ˜ˆ°JºEZ n û€ï$/F.ŒD¿Æ>Ž™õy;é5?î5³HøoCìIH>¥,½À1S®½d{jCþ<°¢, 5Éè˜ujöSœ h5ª<äù:y)´!j‘Ø»@¸Ky4@ÇÝ¿4ã÷$iÂgŠ>æ3MöMØ$" qÈû…‚¼ã:Šyî;àš*C¾äa´‹Ó‡,²°¨.1Ò½?'qƒþLà‡.Å\‹|Q÷&¬Žúš$NzE¸sùePê äOøýÊÅN¤úM%÷úO_ÚP÷È@<Ґ¨©éÈÖ»‚ì¬<eàÛh@!Zòý €jY·u&Ão5…C\¢D.ÄS^GU$ͅß`̐n1§ƒÛÙÏñýœßpïû=àŒ³»p“©SÉù»‚4\:¦ÈÆÉ9»xÆÊ °V«a ¡€dû…ƒYˤ~Hg‡/$çÆÏ'Ñg£KÓ'×d= iäNÛó%  õáît=ÌnÃ?e5&S74¤!i Ý ™HC²³ŠŒ÷€ÐJ®9ë@‰Ñ—«û‘^Ë\Zð;=zž‘4Cã1§â„ÙO#ª +†Ô FI­%ÃÄ>aOЀð~¨¨9x,÷&i<³ž4ÁÜА͛€lÞËG6Ù8`Û…HÙ7KÝùŸ +¤Aï±êNmüÝta×Ls ç¤)û¤öJŒMŒï’ +îòòè¦ + +§¶„.ÒQY2%Y¨®")u"bŸßbää¶Øù] +q@À$Ù8ö@ášÿ50áöE Ú¿ª¬úØpÒõùü®—­þžæ0Ì¿b¢ûõ‰øv9¾ Y˜C¯ã°uå7DŠ’r™˜V©®,’é8d½I6…÷ªRr¿¨”<ĵÈH i(ß´ÄÛ‚™×µG>ÿÃtrÛVï/,Ø£O[C0LÑÑ]5×Òî¨SI ÒÌ=ŸÈV°¯ Eå ¯”«fKt šÖXBk¨¦ÑîUS©jµOL£~WiÏ_ €‰¼ 鶅 Û÷ Ô^9k>ñåÌ=ï퓝˜#Ûƒý͑Q–›q©Mz±ZA(VIòXb>YÈå”Èʙ,uIr- µ‘Rz³ºÑV]@·j +齒Bú ß  dW'`#g!Ûæ ƽŸÀ­ÃŸ½o=¾îUǹ­½˜C;‚|{Z#"[o]M©¯IÊ×jñÅRE6‹')” oTWV¨(¾ŽÄVòX5Æ֝ê¦U“[Ñ+Í+äÛ”Õh(Úà\¤A±Õjöº|l>´ümû±/^ôžýêé ï7¶îK>Ööðˆfs,Îؐ'¯N¥ñµYJdXÊ®KɆ2_ÄÓf dz‚ÀhÀ ÌF<ߪ!ðz¥ÜA=P„4ÐÖ;A%rê¯@ýžEsw¾]úºÓkÍäЙM? _pïï8·#,¼¾-:Ym¾–+jÀQYµåņ<YKçªèò G*—h“ez}¢¼IŸ$·jp’^iŠxo\GJÖ9‚ÐÕt[æƒi—ó»v÷O§ú=Wþ{ìÔúŽyè´ù{7÷†„­Q‰UmqYœ–d +݄/¥4ä°së +„šb)ÎÈR$Ī8ƒV}ÅpKsÅØ©ŠÓô‰ãUƒ•öu_8‚tƒ#TovúóöÎùÓÝý4â±tìÇã_öŸÛ×6Š=sӬꋈçw]É`X ŠÚҊsïdU¤·¸ÉÍ4a|S…$Ö$’EÝÒÈ#LòËM²ÈúaTí× ! LdN)Öσ†Mó~kßêøóÐîùcãîKž_o}vvoÓ8æ”~,è’x8<¶â»˜4jÿµ¼¼ž”¢ô®Ì’äbyœ•Æ‰¾_QyÙ"„Z4û¢`k§0¤mˆz{˜iŽÞ4èþ†þhހþµ×ýèÉ&ǁç—ÝqܵyòÌÞê ß²§9OÂ"n|@½F Œ¤ä'gR®> ݈²Ñèá6fY°M\dÓ2m&VÀp73pp¤,°g”nÐW¢A²ÊêÖ8¼µ¬vx2¶ 5ðÜÍÉòêàŠ¦éc/Oï‘O÷äýp>Dþ962{"1>m"—øS^úÕgEYQϹáϸĐ§Ò‚ µä€ñzÊÅñ6 +v|˜‚yô˜l”¯@ƒj…ÃGórÔè€ j`b™Cû´ÛÓoî+ o=]«ÞœÚÅý÷áÒ×þ§È3a¾93WÓg’C“§3"㧉1±ÓÔ¸Èé²ká¯xI!/¥¸ )uJàTmªÿ söE7óËC»€¿Ôj?EX¢z‡¢Úf–£?l^¤Ÿs_)óØÀž;±­xöÜþÂًÙ³a'Óf¯œKšÅùÄÍf`cf‰‘³ÔK—çʂCgy!Á$a—~W‡¼¯Ž¸øÞ‰}g‰ô{×e(]P£æù¨®Ž¨;# Q7ÿølž¶¸ˆaÿÊ +8´Ž +ÇÜòáì`öá äÛxˆõˆ…d¯( œ¸ y§Br&ègƒ€í¢ó ¸pô>¨÷õƒ;~¾`ÅØó}ÕÕê„jéuBÕüàŒRÂ*G!lu)ƒÝË)à¾6<קÀi·xðÝ A;/CԞPHØ i‚ Ë=Hßøõ‡1À=â bPz\ÃQohô<-^öô˜Ð(³Åe´ÍCUM-tàÁZ':¸-"Áö%ä,áÈÚX8±.λÿ¦ی…Ø-~øµà·^€ìm灴ý\ßqJwžÖ®Ó Øud»O€~Ïq¨µË|2ô P’G( £‹a­c>lpNƒ¯Çý—ýòêj2[°Ke쎻8vGEłH "Š„BH)$$Ò{$!H‘*(( ŒX°À€¢.lˆ"(Ê3öÁÃ{¾å¹9W™?p.žëïY{ío¿ï›fFûœ0ðœþ Á¡Å dI_ê±Ë}³ÜRœ¼€¼b/ÐWx"xðWîéÊ] ^µ «<À²úŸ¨¸„|¿sÜ8ųqãø0}<æNÀÃbû8øÁ!œ§—‡ÀcVx}ï s¼àÐwª¢ƒ[‹1ñ,b]•Y¥Êä•HùÒ¡Leäéôúl‹QuÒ¬`ÕZdY-IV›Q¾£gu‹DYø¶@Æé< ␋üŸ…›¾ƒ +÷™_Îx:Ÿ÷[9pá Ë£ó!Þí5QÁ-eè¸ó'ð©Õ& +㤞É-Pq$F™D¥kô +É(á›…Üš|·9ŸÇ»eâñnkx¼n1—ûP`  #•±|"ȜìÀ„̍âŸà”ÛôçöÌjò]Ñwéà¦{MÁû®×E»P™[[’L(Ï'1¬F:רgK´j¡J®PêERƒ‘+.4³Å§ò3ÅM7óXâN-Kt_Â>Úâ›kéDP"ga^c¥'qö®q÷ÜÁK>˞^=ðSgs×•úãGÏ×ÄŜ*OJ)*J¥çåS9ZS¦XžËW +tr]¶:ǐ¡,È£+*,4EC>UuӜ®ìÐ¥ËïKÓeÝ"[q`/™jä, +·ªâÇI£g·M¹¸kö@«÷â‡76Þº|tïŦðÀÚ³1Ñ¥Õ|~y +M_LaË­L‘ÀÂQ°M-àͥæXL$}™9UÎBȹn&ê;t$í=)YÓ-²0Ç™ºe pÕD¨Þ`ÿ©ÑÅaèŠÇŒç¿{9výî¿áZk gÃoaGª£Q…uèdC Žª¬ g Kév1[F?!RS +Ôz‚ÅdH¶œ4%Yêò0ùÿa¾Nÿ©Îû8ŽÿŽý¢˜²u‰©)¦H ‘­dß9„sç8gáœ[ölIƒJÅ´\u]I㚚¢G£1´h™h’êjs´P²„+]Õ¼¯ß\À¹}ÝxÞþ¾nü~ÇçÝsDrü^½ôûG{¥«TAÙPIþ ä=uzµ:Ú¬5>tÛk¿½ã¢7øØͤ﾿Mw/ukÛ zDs7›u´#)yÿÏ)òª6YAÉO9e;Ï푷TÖ¦þP{@Üüý!AsS¿¹µ‘wæZCRsÿÁ?U O>©R…¦j¨&;Žš«áŸß¨}ºü­úäM[¡‡öZ +W£}×^îwÿ±76ôÄMãàU¾°ºK,ÛՑ–»³=«8ãRA…ôbyµ¨­¦–ßÚ°Ÿsáԁ„Ö õÌÖ«õ ­uìŸTqZžV¨‚"²¡ÎD 'Í(¸`A™í^IyÝ¿’20d«uû•»Q琯Uë“P—¦è Æßãi5w¸ü²["I^OjfƵÌ<ɕüawY9¯«¦*¡³¡šÑyê;zç…Z×Õïè]ÿªŽk^wi°T”ï4¢ Ù„ò¥Ý”xwg 10dB¹õÖV»ó»IÛ°¯Õ™—!NG£|÷=‰‹ªxÈaåò~iªäw¹\p7?—ÛW^Àì­)Žëm,ím*‹îm+ßÞw4XºýƋÂèk/ TA¥!G—Rpn ñôª.qï¾.qstå× [ÝÖqÓ3c>VÇF÷¿¡nÛ=RøŠõRÄL{‘Æ e‹øŠ"I‚bw:C±/ƒ¦8’­hΎº˜CºžñB‘ñh$3bà­\ÔPpJŸxÖ®Côõü…èy¨Kü2c¦~þß띞q_vdÚËrßT€]åûp·Â÷tŸìInpú¤˜šF¼"äSÜpè},t–66û!l"F©ÒÿMlàÛë ÅIéÈð3Ff„9²X«‘!±AúN{H+‘RïñßƍQgèS‘“´ÙÈw´yª*’wŸlHÚ¨ƒTG=ÈÝ ícŒÜpsìdX"[´ò,GÈÊ\‘Zç É$7@t6ÂK¡Hê ¿‡ +/ìûÑó¬Á˜ÙøáØiÆmœ>MKÿH{·­ +D6XkB´A2]d» ÏÛ¡æ(¤["O@~bN{@¶×i‡ 9‚ä–ˆZ£ ìˆFÒõØ?x¿Ñç9ýŒ ϙÓÌaÖc<áMÜ ûãcüóøyš*“·K"ِ²^rò¦ÎÛ¬"/c”›cWŒŠø—ü­È¬òƒ¬>iÇ©œŽFò9úÑÏñŸݬ…ÄۜÜ{¼é„çü1æHÒHü„@Á˜æ?ŽŸåô³”ñªü¯!i­&R×i#gƒ.ŠœõQêi„ò@sTn·BÇÅäçz!§<èyõ“¬1v>õï eJ û?¢VÞ¬ #éCbhšw/eŒ=(}Íz›ú,~L:Àœõ%|H¼Åžc«‚d²A@6ÈÈ}“GnÞR§Å¨Üj„=˱—j…*–ÊÅn_J2}ò‹Ãærªcf32gҎñ¦$MÂIñٔqÁ¥´Q~÷Ž7ÜÞÌל¡ìGÌ᜻ ïvÜfOJ¯s¦E]¼Y¾*H±P‡¼éåk´P´N•äæÝëaˆZ¿åØn…ZÆÆÏÕwe…ÌÿCI~äT~%c"«Ž7*kHN¤¿ÉT$žßùŒ÷KácîÍ¢ܧEwØ/ ¯sG²»xïvtð'¥—g„ª@B6$“7ýù®Ï°&Ï5àoÂTÜÚ#¢G­¢Û:«âi)E¦ ‘ed“ÁY„„$oH I؄¡ld)C@+R´­´§Ç>}/¿Ã‡ßçç½Ï}¿×ó§Ö0Ò7…Hç•^Ú’0iöƟRÝO~ù™¾O$Ø,òi®³,ŽÏKš0ô)QN|BÈ¢`•ŒÁ¬Á zÎ@`·/àA\—ÿ$·%à%£!è5åvð›Èê_±kä]7Öt¹ Ò7S.l»€ÂÖø£Âõäût³9ÖnFåñ füÂà…=¤ˆÉ÷‰©ôÞ°œØ|܁Uǵ‡6ó[Bú!ã‚ڐgœªÐiznŽTŒ[$ãß®ês†°ƒÚ€‰ôÍx¤oʐÝÈ8¿dgøWžÍÁ¥—os0f3iAö“’p¯ÇZà‡Ö“@é¢ÊbÚ¢2ÙMq?…• nêÔø.a~DXŠÊ+"¼ˆU†ÍPóÂ"֐ ‘´ é›"d&R¾©0Ù òÍw~T]ùò·ÇãsJ/³)…¿Ãh +Þk0‘x—Ï ¿ÃæQšbF-•£&çð*ˆE ¥‘jQQDkbaÄ 8?RŸ9ÅQ_Ñ3£æ‰kỵ@Òó`„™‰ôãú ïܦOªË_,•Zí_¬t86]âaªÉ¿e?œõ¼'#¶‹èa <˜RÃN`V0epIt&¿ªæ‘+ÄÙ¤FI©7)ƒüD”F™ä¦P^2’)³$9enUH4 ïÓqé!uL(Ïnø_©ÙŽß+Ü;WcÿõT…û¥•]vˆgGjx@c5¬FÈ¢”óøLGçŦ 1¹¢ôèRI +­.INë–Ê迈“è< ýE¬˜þš²d  ÿþ^mŒdÈùF1øPaºí]í{fê펎«¯_.õ¶íÎòhÎ"Ô&“ÃÊ% J¡ËÌå‹àL8YÂVˆ¤±E1³F*dޑ Y“bÇñ±S,Aì u-Ÿ3АýŒGr¤kƒü¯uAééõKê‹[~²0zÑd{d´îڅþ +ŒÍU€{}.ο2ƒHP%G“s%F†(– ¤1/S”ÀUJøpµŒ ·É`î—«‰‡á) ¿ŠFÐV"Ð€ŽÌ¥ɑŽì‡ò¨Îÿ+O­û½îÂ湖ïvN¶YzØàr¾G}ú¹ÔÏM­Äú•dGàóÒ©äŒäX†\ʇŁ@˜.âÆçKX‚ +CÐ,‹ Êñc LÁ3˜ÉEGD¯æs†‘#9²h¢ÿhÿ©>¡÷®ÉdëócVÆ÷[œL:ê<¯ÔWÞº^^r«  —™M&É31‰©\_.âs¤)"†$WB—I)‰ 2’¸_F‘Œ ©‰“0U8M_ "X»Ð ¹“ä=SvXk¥î˜Î›ö³ëž÷šn¹kyð^»ãٖF+u­kQEov1›¢ŒŠJÌ¥Óù +›‘À£§ÉÈ) +11¹8)<¹^JH¹'HFÈ'¹‘Ò阵€(ä|x'ȑ,ùûРÊý¾é+í×=§t'†Înê·ø²³ÛáL}››eYƒ·K^m€wZ%.DRÉ/¢ÑXJVlt¾€KÊIŠÏÎá*qˆâ¶$XÑ- Íb3'a\ÚtÌZ ÉÀû Ò ‘Þ¹õ×íý¨·‡Ð/†¾Ò}tzcßÐ÷ûZúìOUw¹Z¶aœ2ý0ҺРAMx»ŠBŽ.gÆD•Æ± Åb^HQz| ªP觪ùªºD~Śxå3N`î4}-€bˆ ÛQ ë_(PfˆZiڍší3BMhö †Ÿœ4è1ÿwý°í‰Ò~óœ/yÇ-„Ö`?vÝ@Š$ÖÅPñµ\FpM"ÛOÆõ®.àcªÕ/u‡àFÍxÜÍÊç,ï’ÚZù’m(·5Û¡_;·@šÑ Ѓ©=¨»“'Ö5ǩª[SðÐéRꠇ¨ÏǾèݍ"vñ¸;tbP;L¹Õ*¢cZS™ž-,÷5ûzkûz›†åÖ4M÷¸=KFVØÈù)[ P¼šn2€Fz×CCÿ5€z¦÷¢›_žZ¯~nf¨š´:’©¹j"u³ä>ºéHàAÆúà‰÷£±¾pøѽ?ìÚ¯¤ºô«iΝ4§ûTçÞ¹(—Î…p—ŽÅUÁ&Pl„¦ªõ ŸÛô¡¾}¨kÂjœÛ¯U5{j£êµÙ®ÌW–‡%/í¿{îz9ææJÔ¤¿#î)Ö-pœˆñ§ûÞÐpÜ5‰Á×4éX'M!þª¦–à0ÞM°ŸxŠw[Ä^}ø[ðZ@’4¯Ò†ÕëB÷:t¡¶a}¨~~ªüÝå»o7¥¿½´K¼haÌ]°9óæÚ¹¨yÌeü|€eð<ÞÆoŽäà=Çpöšã¹ºÍIÜ®Ígx:Ïz]¯Á8¼¹ƒ±_¹i÷fþ¦íô˜µü™©V¢¡{ÚPsT3¢•¬lEå.ë¦.ŸÞ$\¾¸“³üý~Ú²õ‘ˆe§ãØ%¯3Kþç}—p¦7—IæžË ÷å8K×e±•óJºµãJ­ÃJ¥Ý‡f{Ûý6Ÿ;Xø±´ªñBê«ECM­ZPՀ6T¨Ñƒ²>í@Ë?Ñü}b#óo“$`¾®ìWù÷£à{Ì„žtC +É5@;ã ØçA‚‰_°Ùm@ñ%kPkjÚÍ~Cf–àõeK0»ªÁJjn@A•Ý((ÿg4”:£I€á?|—kXÌyÇI*§xè ‡¢$%ÏçRtšæÔšfš™f¦fjjš¦3Q*jS$¬b…°Ž­ÇéZ\«ua÷bí®­'¤„q˜(Õ÷ùïîëñâóúþ\×}ÿîßý¶Ë Tp0ÊÄzS¼çs¼ˆŽ( 2â­ãA·Ù îòh¤¯ŒB–mT«Â‰c4Û탱Û!û× ÝÑ]Ž~è^닧¯q¹‹D:ÞM"µÞ!‘ê#‘¶M)†ùÔXë‹ag˜ +'ãd¸›&Án,ÂD#fa$ȋÂÀøO0¸K!´ðG¦¥”–>(¶òB¥µ'j—º£ÙÆ ‡m6 s™+.\ÔIç9¢þM©î‰´¥D*€ñ9æN`± Ë (°7Œ…‹ÑFx‡!À$áfþˆ™ãƒ„¹^ Íókžxó]‘¾Àòë 2_K,GT-t@ýB{´,Zö¯Òö_¢þ]¢þ$’ò‰$ÅÌ)\˜N¥aþ´8XèE= …ÃŒ¸zÃs¦ü\2Ë‘ÆNØl숄Ù Î^ ¦‰RMVBd²2ÓePšÚ ØÌ•fV¨ý*`ÿuÒ}P\¦ƒµÁ\cðB瀿Ù<æ¤JmÀQۂµÝÌG0Úց~Ì´Ó® ^ÚÊ 7Pz<ôØä^O$¾ðB°7âßyÇi}>Ǎúhc'|>ÄB'ÿ:8èƒæ<WC𼍑2‚Mæ0,À—Ø€›oN¥X»×‚ÙêŒä£® w¹vÑ´kž þäʯÞHúËä¾H|å;‘ ñ×úÄúˆ›ð×ÄÁWH^: á4©.†x#=hÄ1æÓ, -GšrR·:"¥Öœ– `qó„'’ÏyƒqÅôÛ~ =õÏ@$=š &j‚µ ڐw c!o&ƒ‡¨ 0 *áÀr4ßÙb÷YÈ0CÆFsȒ,!M[t…=¥NàU»"µÉ)‡¼Áþά3`^DòÍ`0~폰Iê³ð±¤¡-Y©I‰|89Hž  #Dÿ:Øë#eDN3±aäþfȎ\E¢%ä©+‘!_q‘ „Uîà7xƒwÀ܎ pN…‚}!Ìk‘Hþ) +Œ'Ñc´þ-uh“&éÝæWä‘؁¤/1Ï(ˆê£"B`÷pà÷´„È7Y®³ëke¸9ò⬐˶E¶Ô™ù®TxAT€´æðGLroœàœùÂîŽcþ?šüK¢–ÞO~K¢ RÞSŸS?‘{i_â§cÓ#:¢u6ᐼJ‚UÙO‡ÒÅjoS„š£p³ +’í'r‚"DzR¿qÉΐ1QcÔç´ÖM#¼öø)'ÉبïXךäækF/û%m˜ÓG{Ï~B¡?dŒ%ÝKžˆ¿ËD¬.À±š¶­±võ¡X5êu3QâiŠ²`sl‰¶BÕE|çq•Üë³¢0H+«Œz/©‹}+ÜK~Í?Hâc½dŸæ¾`vóŸ1n ûèOÒÿ¤ ¥?dhø=L-ç6k”q“=N¹Æ™LÔRî +=d,×GžJœfb«‡ *`[”%¶‘íƶ¦¸h‹¥>U^Ø°¢ló`æÊóô=Ì>þ¾Ô§ÜÃÂßٝ’G¬ó¿0odÞg>õ$Èn±Þ¤_ç¼ç_Iá\âŽ2ÎsÇ)º—pàÙFn£‡[lu4Äv·ÙØé?5–c5ñvw°Ö¿)ù eGõ+ ŸÊ˙%5¼‡¢oD÷ÒHîò:2ïp»²~Léξɹ£¸ÆéÍéæÉΧ¾å}àâ°O¤2t.‘ñKõ °ÖC ‘7·™·†˜Ë:ßyã»Ã,´ ›ìÞÔÒ×Tñz·dÄüVG¹Ÿ[ʾ›µ=íVF½ø¦¸9óªðPÖiÇs.ñÏ)/ð®çãýšwšÿ"ç„`8ã˜P#ì~ä}bé©„C:1—J"ón!ú±“ȼõëÐè=çsSÈbMs´íËFêú¾])¶‰c~.SPnrn(ËW²«%3äç¤û§Åíʓ¢®üNáêcž‚Q¿ê[ñ ü øµø€ä=¿T›¢ ð,¦BBxäy³‚èÉ®Õhtž9Ñâeú±5hÑp[Ԋþ²Ë“vÀ½jaÌ­J9åj©Šs© Tð}Þvi—¢.ë¸|oîÑÌCª#Òã‡$ +Û$·ŠZ¥½…-™Š½™¯2šdA£ìCª.þqÈ êþ{‰™¨'Þió:ÃÑ&šC ŽD,{ږ°îÁ^¦ÿíú´è«;2(+r9gJ‹' +*¤GUÕY‡s”²[ó÷eu-þFv½¤Aþ¸dOöse}ö¬Nñ6½Vñž¯ ð Ùâi(&ØAìÌ;}ì_;c䰛ñp‡ßüþï­‰sº»Ÿá£‘}¹V’t¦*›ÓY®´—–IVeï˯W6嵨÷ä~[T—sªd—âJiuÎýÒje¿j§òeÖåkq•ò@H[2YDÖ,%¨!æ¢i¥ÞäAGƒ®Fƒ>sÿ:jùàhìÚ[i~Wš¹¿ß#J:Q#g·Wå Ú*J¤-e•ÙÅ»”uMêjõÁâ*Ugi¥êrY…ª§¬Bý?u…z@Q®––«5B]üã ø;sÔýŸîúŠk:Ëâ~“#-‚€  £4)ÒA)¢Ô¡¦Zˆ ¡I -¤¡ +ˆ *HDPŠ¢]@?«®ŽÀ8*£ ~ÆYѳÿÝ}ÎÃ÷sÏïžsîÁvÞ:Â× {ˆ:,¥—{íþÙç²ý~'ÍøöÅ ×B½zj£Z«øÜƲԨ3ÅY Õù‚ò¼i%9ՙÙç²ÅÂö‘p0W(œ‹D/‹DË)¢ì·‰ÙÙïy’@4–!M?a{g6—-—KRï.›‘~°‘4à¤q·‡j4Úh¥™ëÙ^åß\“À­«:Y]ž_^š+(.*NË/¨Êå×g·ædˆûÅéâ)ñ±üŒ¼åԌ¼·ü ñŸ±’@Œ:ŽmÁC–ã–§yþSçnÂë~câó+™‡×Ôǯxï¹Þ`×Ýìq±é°_ýÙ8ΩZAdùÉô¸¢ +ё¼òÂTaiEfFñajÑŜä¾Ü#Eã¹É%/„ÉÅKiG ß$¥¬ÄI±Ø;8®Œ‡Ò-88½ wà>\ÖÂ/é~½e*=3rpëÍAOƒþ^?Û¶¶[cK8£¶™Çþ¹!)¢èLj¬¸F˜”UŸ’^Y–‘\Q›Å/?/Š/¿œ[>–_ñL˜ðóRZbٛ$þ‰•8I ›Á÷Þrԫ⾶oý؁{q{nvÒhã䘽Úõa½î†õ…^–k]g¨Oå¥hVñ…Ä0qÓј¬†ÌÄ´³âdÁ™Òô„ÚêL^M“0êTWöᚢõO„Ñ5Ki1Õo’xU+q’@6‡\ET)á I}îQFË£Êè×{*èÞ´!éæ¤Ý–þ17ݶaŸ½ ƒLçê¾jiO$3¯#>$«M•Úr,îȅœ#qÍÅ)ÑMUéç2CÎuç6Žd7Ím\N ;û–~æÏ8I «ý“jÐ÷ôû€TDôˆ×fl”»¦\µšoÓ,jo:” {åFøeõDzS{““zÒbb»²ã#; „¶Wå´×§jëHjNgv̦³Ú_ Ø-ï8çßó$t¬%dõòèi×F4;$îݑFSÉh䑎Tïì^Ŗ8í¬›ö6©˜òÛ_p›í& £§ŽÆò‡ùÁ¼¡ÔðÃׄÑ!ƒq쁊DæÕú$ÿ«í߁!c`Và7ð61 ÷=/°{5J’qP)‹^^ ¢Ù>º;JB·f6¢ágdt噡mÁB¾á±ƒF՜§AÑCƾìû,Ç´™POþÝhޝÄÀˆÉ6wBš(ˆ¯ˆò¯¡wðhãñԉ9mb%š~óc„ÏÈçPI _}8-…æۤН«Ðè <F=¯Që+©†ß¬äO¾8°µø¹»Žè)Ý4miËÂuŠyåþ(<Ÿâ4' ôŸ+d1æ*9´¹s\Ê\gˆ×ühˆç£'عìýË_lï{³$2ZhBhº›€F®I¡+“DÔ>/Î¿QÆÕý¡·¡òKrák{5áï.š©ËTƒÄå@ó˜%®uøR”=w1щµ˜ê°˜íá»XäE_¬¢Rè^K>KC ÷å˜× ÷Å/>î/×i’¼¬Eèþ%„Fûð¨o”€Zgˆ¨aAÕ¬©áË× HùkäÌU»-É«ÎÛãV½´"WýôCW9FœÕH³ Õ«€Õ”}¾«B[úZÁ~ÊZůµ³/9º}¼êôã§)g×OÿrvùôÁÙeíßN’ü‚õàfB½ƒ8Ô2ŽGu³R¨bE•|Õ ä|Õ#¥5“ã¯ÛlŽYwT [÷Ð`¯Ów®iù} ÓõùÆÓ£}xÏØãù=×Øý{©ÉPcæMæÎÐeáC–0cy^aÞ[I2ކP_B-7:=ƒPÙåÃ&\hŽ‚Ά80’‰€½dØÌWPÔhà¿ÍØØ'Ì bpÁN'ÈÔt„<­ƒP¦m§uì༮-tëÚÀõÝÖ0yª'I7Vÿ:V¡Òy„DË8t p|PÃGÁ."ôIL0“a€<7y€»¢+ДœÀ_ÙØ*ö¶ÅbTm€¯¶Ò·ZAÎV (Ùf§ÔM¡QÝÚ4L _ÃnHt©« ¡’ Ÿ#”Dd\(ãY Nðm" In`!í ¶2ÁQÖÜ䬁"o¾d `n2ƒàM&¡`±Š† PԇÌÍ»!³”+iC­’4+kB»Du£Øý±d- Ä_F( +†ÎëTðn°àÚRûÁ¸Ì7X‚5Éì7óFp—ÖŠ´.0d´!PF8²;!\vÄÊj€@ndÊ©XNNÈ«ÀI‰€¡CŠ‰ø˜o€@+°öËÀ!W2°hJÄQf¼:düþ…šà{RçvƒO«>Ð/}Ðhc{€6mÔÇÆ@]Ĭ˜õ£ P¾˜eݼÁtó·7˜|‘|µÿŸÁϔA–$àØÊי ÁT%à°ÔàOX黀™¯ »Áÿ¬>ø]4ß.#`\5ƨ øL™‚ϬÐ_šý­9ÐÖ,€ö—P×-¿RÁò ,?SÁü“ÿË@5–‚"°ÍIb-aŽdóV‚¦p£·'EåêBP™>0OïÿÐ]¦QM^[“T«§zYuQЪâÀ  Š ¢ Æ9! IÈ@¾ @ æ‘A@£‚(rUZëP´º¬½ºœE¯ +*È°ïwû;ýñüÞï9û]笇ظmÞ@èXø  ªo#Dõûî‰/àÞúÁþa‹ÿ$vÒløî¿a,ø|ÂÂFk~¹`WÛeµ0½ã;xۜ€·{!p .ÀáºB ²i+nü hkrx[6é¤Ïûá²?nnüÃ̀QŸ'q–-–ý“[Fö֏8āÿûhœ—=н€³Æøç€0È Dá Aåq1ßOö#pR=•³%€~ÈhÍþ@mß ä3@ê Òµ­@¼¦ez$‰|†eÐ[IZ؀ wÏsîü“˜*ÊCfýèVæ=zGÌÚ%v?íç&õçWú0ëæêeÖ ¡'öw³aO"¬ñw6êx’ïí ½ Ú Ã†9è<“³cÉXÎ^÷Oš×;-Ï÷U¢,øiBrÄâ3p÷Fòm^ýVì!æuv3û։ثÌó¼ËŒ>~/ãϸ‹Ì÷¼nÎólì$¥ƒ;C8ɬ™ û¬T7[àºÚ|©úõفa•䮛 ÆÍN…!ßFº½Ë#{½4°ýiÅ!÷U‘¿!º¨_¥Ù”>‘‰ñoA%»‡WÏíæ‹;Ç9-<þ$ê`÷‹O²DfÞhl<º%nŠ|TQG€³ÐÐ ÿwNê::ô>rÐ~®uœ.ö›;ZºmÑ`Ù.×W&‚ç£<¦ßïAȍԄȾD ¾W‘Aí–ç3ÏJJb;DÕ|³ IØÎo·òÎKŽñ®I›yO¥ÍÂḑ%¦^×H>ˆJÿŠ­’Ž3*dSä +Ù4ÉÀpµ1:?õ­,Ôy‹Ð7«ÜËásõ†Ùïëœ_ÔïpyP]y«”êÛWÀÙ~1GyF¯ÀŸÔ¦ÐŽ'XGÔùÜE‰ 6¡&¾ZÖ,«”žL(“ô %Ò;HiÂ{I 2Â+F,,ò…jB&)Ö&:W‚ún*J.º“âe¶ÓWÙ×{;¾iÚ4ïIsȒßëö®¸VIö¹T|Ö(ˆ0gËñ-ú$Z“.U—’íN2 +TUñ%ʹ iC +nE>rSiT½‘՟âò՟Ùyê zžú Õóíß¾§C7uÞ27ۉZ»¡¦5/[|çüÙ²íÛ[‘Wjˆ»Ê™ÛN™ø»[ó¥QMÙ*jm†–U•–É-M-š4åcR<7±U‘¥>«4¨¯©2“_%di> +35£±™šñèLÍÝÀA»€,²tÔy ]l ÊÕÆrx¹í»OûgæõŽwۂ_;ñCO=aCçAÆÖ¶2îîfS<®Ö¨ TæhX%™ÜB}¾0/­D’¥=$קUèR:U©)?«RµÏîƒH§û‹«ÓŽ1tÚñhkíuNšãÀ¨ùÎf¤ÙÍæõ ÛGkfõ›·,ºÚºkyWSÔ:s-=èhUì®úRÑþ*S¥¤ ‰Y˜—››#0d¤e”§è›Ié§Uêô+*•þ±"É0$NÊá%ëǘÉúq†5€ö@:g6š£t1f¦î_˜­Km^t¸ÛÜ?çép½#`á¥áË:á¼7R·4Ô²wVW °¥e2ra±š‘S¤Í(Èhó‹â“r+åªìF$!ˬ”eõª¤Ù”HîP<’3ÂSd[XŠì1¦5@€î ÙÙòæc bf¢qæ݉ŘÇ]K0·»WÚ÷Û4¿ët˜›¹ »öÈQrÀ¡FVXY_aµ„˜S©ŒÖ—¥pRK q‰Œb¤¨\&-¬O´+„=JAÁ]¥Ø4_8̗-,‰qŒi £çOýÆ +œ1PíŒ=ö fàÌ<Ìý^g̍Kv½üœ;φº¶žÚ»úp;iSe #ÔÔÌÝ“Û &èëZJMrŒú`:/¡2O_^*”ÕÊy¥ÇNi7Â.»ð*Åü²a^\‰…W<Æ´HÑ=¤;aà€f¤~.æaûl̽ós0ýW0}W–Ûuõú8™/l_Út.Ò³ºƒàWl¦ÿî:jòÊÃ~IH  ²("›ì ;ÃBBB’@aG(‹¢âVÔ©#.­u¨Sw +µ,ƒ0Et«¢VEq=žc= ¨£•bÁʎϼÇOýùð;ç~¹çýŸûÜóžû|}&G°³±P¶µn­jãéÍé¥'ÿ’Stbo~~́¢œêêÕՍ¥šêÎҴ껥? eUåeÏÌ>6‘® ÖS9ìšG¦‘g?2ɃVéù™Env“KÝ´³7üŒ®r­k. Ü^H +Ø÷/uÄÎsYq[[ 7üsbMóFuaÓ¶Œ¼ÆÝ9Y ßækê« +Uõ EÉõÅÊúÞ┆¡uý9©§&ÓÓNMitÁæùû ÉÀ÷tò°‘InŸ3 ×.3ÉÅ^9w©^SÇ°öV¸Õ‘|§ýפœŠ®”Э3¢7\X%XÓQ"ù¼½L‘{~«:ãÜ®ôԶʬä¶ã¹ò³õy²³í«¤m½«dmC9ò³Š–éTeóŒZl7$chäI-Üif+í ÒqAÎÞ3$M‘SØÌc÷CVöÅÚïê{n»­ ØЭ _}#/¦àzq|εõâô«åIª«JŕJ•¬«*-±«A#êêHO¸r—ò{š¸kJ•xñ£BrA7좑þ£„Ü­£‘«­tÒ~NZn2Iý##r¢ß’ëw×ÿöY°Éî§QÖ۞7<–{—7óú…”›{c··ôD¥­ÜÑfå†k”nNS¦2ØÓKÈ¿R2LH.$ &zrX艨³àÃY? +^Œø3C±Â \–?bY>.‡Ôˆd#hŒÝkìŒâyË°q¾¾œo‡oLlqÄd)jMlpÆÔ-:¡2Ø{›-O)zIHÆ8!J"†‰Ã½HXÑ>ƒ--Ît?xÒ9ðÑg#ˆá†0† ¸Œeˆe:@À´ƒ„i¥5Ò !—e‰–96±Ì°Ãpõ\€C†¦8ªâÝhˆñՇ" `Bʂ,ÚR±)ÓÌ!*²BÂk÷Ø þ;[ð«íÁ¯s@\‹#âÎ/ï’x7)÷Á¤üîÞ{Ê4æ<ǃ“.Ÿfàqèqô!ócB±‚E”1ä"SÈTæ,Bâ¦%WØ"á€=„UŽœ^Ájo›3âv¡›+øw)ýnà¿¡ü×ü) +>ùH™áÃmŠW]  fà{Ó!ñև‡‰” T\c¤M¡PšC¾j1de6î°Câß!>êQ­ D®Hhuƒ°Ã«Þñ„à)å5‚Qʤðš£L ÀžÀãƒîº@èJƒM‡Œ­”å ¤° ‰0†&Þj¹Tً‘¼ÖŠíHúÚ ²C®Ö¸CRç‰Ä6Äç½ ¾ä Q÷rˆqðÒ ZŸÙ„qß鄏¾ ðý gLïQغ|šAìA‡ÒCil2} fŒlž)2¥HÏ ®Y‰Ô_8!e·+”< 8“Ë!û‡¤­¾vúCòKÀÇľÀ™Ä Iñpðñ‡1ñ\Èh"G$ð–ÂwH +Ž.Hp¡AêF‡Ú•ŽLwò8(Xa„‚hSä‹-‘§^‚ìdltf‡'Ôß,ÿ˜rØw6¹&`FQ4%o™L::!»öAz;ü½ô׈Qɛ•o%ï¹CÒ¹ˆ7I{-GÈKŸ+௠DÎ4ȝéÐPý*êy…ÞL”a5×%B )mPëø1o­ûLö6ïɌ=~ãi‚Þ«…Ž¥Ô†&7rG­Qoå1ÃI×yC²‡üWÒWñ/dcüùlL¿Üg)¢BèCBt˜š!őŽ,ªï:飔Êc}€!Ê"LPÆ·À:™Í̚ §ñ¢bϱüM¾ïrþü6s_øæ`äkõ÷ÿc»Nƒš¼Ö8€Ÿ„MEqk­K©ëXܪêŠ {HÈ’„ì @ bØ ›ÙB-@"D@ÙD– +A°^µ£VP¯ÖöÖ¶ö^µuãÜ×ïùð›9ߞ3çù¿ïÌßç)­1à ŌyDêÆ>$ …< Ýù‘ø‹ô{“ú>pš}n0¡—• 1á[ n32Þ+øÔù»$lw€Ê}  êðb¨:¹ò»î•‚±ùX‘Û¯QòƒÏÄ)Gó²¼rŠüï…U`î0kq·è&üL¨…xƒÖOš¤“­Ôû”1ê ò÷Œ·¸Q f#ôêç@O[ a#²ù’O}k½Tmµ‡ê=Ž0ÍÃù}ډÿÓ­}‘BÝüs"o×£X©Ç}i¢ç¿$߁6h’WŒ»ÆÑÆØõäÑ°Vê0³+ô +sˆ~™1Íèe9•X”E«T2KãËØÅò^Qì9A~ÌE‘6fL”óH˜ÿŠ•¯ø@ËS@‚V±¶@ö((Cú^ò +dŸ!o5ê•Þõ¼n3úaÓNû™úÃKǪý]/—wtë˜ÍùüãÍ9Q~uqÁŠXžšN-Qå1‹’J8yŠj^NB³03¾Sœ?*ÖÄ?g$ý—“©zš©„$ÎŽä é{êåæ­°ôsðòìð羚P?¶l³›lúÎe¤Öw]O~{Gý€IÇ=VŸákȉŔe&ti§¨§r˜¹©:Nf²ž§Q…©J‹8Y9$Q)ïJRR^†«ÕïèêÔy²:âm<$ò¥H–X¸|¨\^Ô¯s­«Àæ­v-îK.O®íªÁ}ݪ§í7–rŽVëÄ>åѝVAÈÏN¥fgf1ÒӋØjMOuª^˜¨>/NPJâÔ·$Š´?¸IéïIéóeÄÛH\Ì@è\Àkƒ ø¥ÙÜëX +¦:¶ GÛ.î5y¯ioÀnm>KÙW£g®(žÔKƒò‹âñÙɔ4m#%'Ÿ”]ƍϬÄf´‰eýiÆ´$:û7ž<ç-3.û#%. lb$ ŸzoöðæÌb0[·Ü=·Üê\&:7¡;ö/êj;ñE« ³¥¾¼W_v¨¤Šï•_U*є(ÉɧÓèŠB-K^P•åDjωÄÚ^±H;)–äÿʋ*|˔|¤Jó Á‰d!ÙÉÂ"ð¤ÒÜ5.7Í ÁäEg0ri=ª·{ßÂvËñUæÀMÕ-ÄÝ¥ ‚:®gvÄ_cˆÁªô‰Ä„r5-¦4‡uFÇ—xüb“€«»$ä[…Ü’ç\Aé?LQÉGª¨l2d§‚¿ŠÀ=ƒ˜ivÖ'pµoèÿÕٻǩåâѕµü7”·ãwµ†Ì6qŽišD>ªYP|]>º&…Q*4…q«ô–¾™ËÔwóèú £ê‡mø›Á©š§„WB‚-PŽ¼A†˜;ƒ?ÔÚk«#étƒö {h5h»âæÐ0ph¹¾×ÇUw·-§“ú¦ƒuHy^à×å/;,1©ðüæ +»±0”i¬dҌ,Š±‹M6Ž³ÉOÃhoht#$1êaˆ-0Ñ ¼Ôp·€ÉF;0rÞô]²Ãö mì3`Ûfouw)ö^£ÄlÑô“w+{™ßÊ/ñŽJ»#¼E]±þÜ J ˒BïÈ'Q:*(Äv#-¤½3×>ŽxJ÷¿!ÛaÉ ƒm©Ì`ú,ß· AŸ ,ýhÐrÕÔO-†©Íè’ëûi¯ÿ~%æs0ɇv9-€t9ƒ(ÇaŒxÌ@!p`ñ9¿Á÷à l °åÏ,n—0a ßŒ¤û™†ì@Õ”Ývº;®(ííݎš[G–%Ýô];ƒÛ1MÛοÁÞÞ Oʾ£\O%ö¾(wà¡Æ‹¥¼°fÂdlà‰fGì§ÚmÚršÞŸ~‹nÐü^BL Ѿ"4› I\‰ðdLC÷pfb˜ˆcù!™Åƒ5R–lOhÙî0²ÝP¡E‘ój9Nhà8b#¶ØMÀN› ŠdBËB¥ˆgC™b…ÔrÍDd9CVéI½;Äö„hód¤ïðFúoÛ¸¶Oðõí®ú@p‹ê£žSc>âÿÑÿk“˜Î ᳐E©¦³¡N²C¶Øªì‰P¸@^ᆌE­œ égސlçBòÕˆ÷ù@|Ø¢<ˆ:©ËS!ê¦RƒÔ¨/Doé/þG Þ[1|lùï ²h””fº;èÓ U:A=Ó*Ë$(j=‘õ'oÈ×s‘Ù背f2öN…ì /d~~C]ô‡ô'ê^¤O©aêMÀ)^ÉàÿR¿q|m$‚ y$ êr¢Ùȋ³ƒAàC–rr] 3»CSãõ2.TkyPþÅŠ~ÈÚ€¬¶@ȏA~Šú6˜¶ÛdþJõ‡¾Î +Ï|:’‰Ða9‚‡äz‘…[ gBƄ>”c8¦i¦8 0à ù:W‹=7ß9õ>Эòƒvc4ۂ nAöÞP¨†Au,â­òläååȗŠ›Q£Š¾è!ÅïÑ¿)^E*ùT…ð'*„ d#d@ýGÑ4ÁL‚X( aaV4æD{˜%1K튢|OÌå"¿ÖƏßæ­ y³%ü¥~Gä¸nwô¨v?DsdڐúTì õ…¸ß³Š–ý`F¿êùŒ¾ì—ñ5ˆ} EÌ=¢zõˆ°òºƒ&L´ã•°`‰dcn¼=æ +'¢\áŠÙyž0—ù¼.©ö+\2lZñb憘ç†ÆØg¹MñOs¾NÐÿ=ɪíHéӞK{¤¹*¸¯¾+¼£y&¸­O¹™ƒ„î\Äýœ‡ØÄÜ0þTAt¾LÓÞiñ£½/Œ±v¨NuĂ —7óužcżsæšëÂJ>æ?.\ÿ0sÒ}ãöÔ»y»ÒÍmßÎ9,¹©?-íÖwÉnèog\Ó?‘]Í}oDÚå|$u™0ãRâ.`ú» ¡ïÏ÷aÂÌ¥ùS™¨¡÷¨á .Éá͇瑲=ž/4ñúç[‚–/Œº[¶$þö¬•É¿¯Ü(Ü*ºnÚ)ý1wÆ÷ÆòËƎ¬K†Nåw†ëÊæ=RvÎÎ<[ñ7Eœ)FÊé$œ²zºƒ".Ú5«é,uL,¦÷Xo?²Tè4¸8˽o‘Á§÷ýҐžªù17*êfühiH½Rö‰èRéF酒ÆÌóEMŠs…-ª3‡Ô§L§4'L]Úc¦;Ú£ϳۋßd)…øˆ‚”!…J~r}˜Eóçý§oÑY–Ð{|Æ_Ëy¾"űo¹Ìíî2ý”îú¢àkµsù—«k.Ì_œÖY±B|Ʋ.ãäì͊cæíªöÒ/5‡KöëÍ9P|>wñϹ­%úVóKeëd´Z n)‡€J{Œ4·Œæ/ ÷#/x ¬ +b}Íî_›`ß»FìܽRÍý¡Á|±~vLç‡U §kêÇ,“´W®–ªøTy |«zߜº–Ù_çì);”÷•ùŒq—ùc“ù‘¡É2ªi®@Vs%dM•}Q ỐOsçÐüÚ·–ÐYVp¯Öø3? c>ØËéÙ tº¶Få}i¥1è\CiÌÉÅóÚëÞú`±´márùÞkU{*7iwÍû<狹_æí(o3~n9‘ßhé2mµôšþ:oHßXÕ¶ÿf»>£šLÓ0?Iè‚‚Ž8X€UA)ғ`B(@¡(ˆ =j¨ÁjèAš@PÔ((²2눸zÖQÇ 3{fËŠ{vV|÷ýçÇõû>_îçûNnü…MF˜»*Ä1& 8¼µxxóæot~ |ªÚNøµÎŒð¦ÑŠ´Xç´áQuëTYÙ­üÓö9É.}|¾gWF>UžVJoO©ò“&51›/×'ô…Ö&ÜàÔÄßçTÅ¿ +«NZ ’¤ ßÚ4D•¤#/ÌC +ÇÏ¿+2T¾Vk·Âró·ðRº‡¸ÐtLg¦–¼åveàî뢰%1Gz ;ry³r)R~1½)£Ü¿>½ŽY“ÚƪLéa‹“¯…‰’&ÃK“—ÂE©¿±Ä¼u¿òsèæ->‡¼T¡ÜC"Þ{٘p#¬WÀ¿7ÁÛ Æ°ØnAœ“:hO6zIüw V°­zE'í:JâÛ Ó9Uù¾ç*Τ‰%ÁIeÒÐQ'Nt=ü´hû‰/þÄL¬@Œ¤ +ä“TŽ¨ªPî![ –˞ד`¡]tkÀô ¸5°®]µRëíwҗ]&okîô7—ÈBŠÛ£ìK¤qÎù-IÙM”Œ†­7Þ9±'ÕýLW–÷©ÎBŸÈŽrß0y£¨L, +’M1e?0Y²~¡rDãÈ…#CdUˆðVð—€&z 0Œ·_ÿ@Ç]=h»»‹ÐxÇV³r⸁pÜÇD0`Æ¿Îޟ:esöZœÃé¡dçè¾÷jûJ•¥h *d¾þŠAC1…½bø)VO(¾P˜ýÈ óTµŠ{økÀœànÀÞ~ýx{Éo¡eFêg·CåÌ5á='ݼioãs“~¦)wC,âïD쏹k5‘t$ìÖ9ǐ›— ñ27ÿñzOß1™7ml€â36Eñÿ|blՋ6Š<è£È•~WõN°P0-¸Ñ  Âù7š§HP5¯ ¢#(^ØCÌ}l¯•ñgIó´­q‚LO΅›sž²d?8{ øÏ&`V`ǘ9Ðfê©32gòÌ ‹÷촋×ìï™ÎÞ÷‘#ù:JžþÚR%Àì€ñn€+Wqþ œ÷gåC5(~¢Ù/õÿr!õ…µZ í˜çƒÈçƜ%¶ ëYôÎÀgñf~ÏÒ÷Ðóöù,ž·"/Öò|&³öx6dã¶tÏÖméG·ÅU·§ëÖnߣCnO¾6ßp»`  sçãýY9P´@þ -HUÂYå.B¬ò )RyL“£ôØÀRÒ7*ƒ71”[hÊÓßP•)ÛÉÊ,SOeÉNweÍn×å6s—e……óÏw,œ~^´p\þ·…ãO¿›;¾CdòÀÐe€.|‡-¸ƒŠ{2ž!aYb3‚¨÷»œ÷V¤à÷öêþï]5é+ꊟ®÷J¨¾çJ”Ûê™MÇWӌœVóŒ}(Ûâð¡ñûÛì>o;¼6kb»öÎÄöãÊ6ە/úÊî ßa+~*§pþ<@úÀéבk:Àù¼‚>ï ø}ÞK¤­ÛÈëŽêëî®_|4¿økC¡:(rƒ:£k‹Òô!þT¾Ñ +5ìCÝ–è†á^ôûÑpZÅ>}¥w ½Žóñ <H[ˆÅùì_˜HȨhÁ ™\Ñ~¢:L:ŠIvÈMÍQÔ"†º +Ö°Dáš{PŒ¦9JÖڍr´w¢2í¨IÇué|‹†u¶£© &è9öæ+møªïàü‡8ÿ)@ Îg)èk¤îHœ‘EÛ vȜ`ö­ Ñòÿd×YTÓgðþˆŠì;Av‘5&@ $$$6!²)6Ù7Ù, à€ŠˆE*n8R†A[EQÇ}k=Å¥ã©ÓŠÖ­®Uq‘Ê3_ۙ›xñ;¹ÈÅóæ}¿srpig0 b’òÉ´A$Ó +ñZHÕ2E¶¶1Ê´ ±JÛYèeéc€¥‡ƒÄÈ'6ŒPTÝ9’•¢ÒI~Ü’ý”¢‚¦(ʵ€ì“ÌáFæpÃö [83ؘǰ„'à hðiCӐÑzˆ¤u±ˆžŽ%ÌiÈcj¡’ÉÄ&v&½ÄÎO€çNÃ߃†Ðƒ‰`ÂO B Jðπ_¶.xzà®Öǂ6p¶‚³“0‚Ï~b˜8A\4†Ïuâñœxg΁ÿ3üƒOü>CÀ|Áó™x\-ˆ…,‡é@˜0êYà—êï޾ë á»Ù¼íÆàõ{MÀ;H3÷œ)¸Wˆ;¦à=%ÞÉwøÔ/Œ§x0þȃ‘&ø’|á<BæÎD¨d,Hå:Äτ(}‚Š XiˆÀctš `«)ø»ÍÀ$˜ƒÄþ§‰ËÄ- ø?&^[€?iñæˆ >ÌÞÿÉTüÝhˆ\H>æÊD¸§”þ,„Ku ™ YªBò !®2†¨ÉÁmæî¶@Т߽V"þi áEkn°§ٓÂWì÷Âì·B°_ a5ËW²ÐÁ\R'’ïH#’ôݘùZXÈc!F¤ƒ¨](ë#,Ëò2S„Ö›C¶ÎÒMÖÙʆd·Í”dpöGñÛßÄ#vÄgí&ÄWì߉îڏ‹ux!žpx.†ÝS lŸH`ó8ìG!°Ö„`gr{Qv4bÉgمŠ£D¡)t±0Þ1&ˆ*4ŸŠ¨±š _c3ÖfûE·ý;ùv‡7¡{œ^‡îu~%;4ç¥ì„Ë é·sŸIÇ\IŸ¹>½Ÿ{7s~–Ãé¶c +ØÝRÀV$4”³ˆeÓPͦ‘2‡‰4/-¤ñ§!E:‹£ >&¦š¾Ïµ|3Soÿ"j­ÓóˆÎ9O•=®Ãw¹ý60ÿâ÷åG=ïÊ/xߑßôþIþÄûÅ;ïÃávM ×+˜3 çï"ᨠ¡¶ D[1`Á@*é»ä&™ä™äËD3>¤+õߤ©L_$«­ŸªŠì~YTã|?®Ñõç˜V÷±è.¯Ÿ¢z}nFþ•s#bˆ{=b˜wUyÚwTyÕï²ò¡ß¥ˆ7Ü Qð>³ áv&®§cᢠa$7ŽôÞdÒ;3,È!7É#÷È÷ўÈLÏ Õ{šgú c ûNÚr‡“ËçÞPÕ¹_Khößȹ×Íû&v‡ß……ýüs1ûÎD <}Ip"ú¶àXÌˀ‘Øß|Äƒs8žÃ‰p'Ü4!â÷Î¹„t¾l2K %Îôd©s¼ÔoÚãbɬ»Ñ&?æ$³¯«3¾K/šw)­Úó|ò*Ι¤µ¼“ªÿã‰=GíŽ :PôuÜiñ¸ïÅû㟈ö&LîUÁw( œ¡dx ¥ÀC¢Iîb’¿Ì€B¾ …R2Ó +{ƛ*WúI5GûneЌ›eJãÑ¢Dö¥åéNg³óÜN¨Ë½Ž¦¯ä^Òäw0µ5ð@r—p_R¯hhñÉ j_Ȁ꘴?ñ²lwâÙî¤wÁ}©èKƒoßpú–Â[bÉ RH~6é[EFV˜Q“µlƯuNŒûõîÌ×èŒV+Œ.”ÇYŸ*Ns:šŸív(·Èû@VoŸºž?˜Ñ,øréÆà=Kº%}©;¥;RC·¥ Ë·¦œWô$ßVô¤‡ô¤Cؓÿ/ÔàMˆ7&wУ°œ(#³ÔQoÌ©G³©±¿¸0®6úN»X'3åZõñˆõÕȖ¬gaks&%ë–C¸>üõä_GTä·«Iß+&ªgR¯VéRZfQ·6èQ£mvŒó­>¬ã-"ýƒ–{ë9ôצÍÛU™åÕ[^ÈÛRZÁï*^ÔQØ$ސ¿A¶.o³¢9wGxSîß#VçŒD5ä\ŽjÈ}¤\?!m,DPSÖÃO’È;ÈÒ!oQ‡z½R‡[3º¹~:õ¯ö™Ô7³©S½´·éío³hŒ³ßUŸâÚ»RíÕ]Çí\QÊo+¯®/]%n.Y'k*Ú¤XU¸MYW0Y›?U“)ººàaDmñ{Ùg¥ՕAP_¾&¤ýç²(T°¨ûõLêf ‹ºÖ¦CnšAÛlMÛä¡õU»`Ö`«Ü|wóB»mMIs»2<;?Ëån¨-ö_[])XSY/^]Ñ,­+oWԖ~¡¬*鏬(9]Vrž¸UQþ.´rÄՕÖT¯ iääiQo«hjl5M]_§M:Ï4êÒç:ÔÉ-–Ôp÷|æ¾®ÝþöP³í­Ñ¶[ZT.k–zlX½ ¥¡Ð¿©®Bаò¿l×iT“Wðç}" a‰Q‹(”B @ؑm( ‘‚¢€"Š‚"PYdYŠ¨ˆ(.PÅjg: eÚñLm 8§§ËÈ¢õTEg®Ç™3=a>üÎýð~øßsïÿžó>9 +½f–ûí?pfÃތ¶ Ý=!)÷B’3&‚wüÝ7- •éÙèºï:«Ã­ÀT~!3ß·…Œ”1áó ײ ¿~\­·btžqÒj©ñZVWdx¢,Ò¬¬d‹°èX‚]~a²ãáüt—¬¼,÷ŒÃù^é¹Ç}w:œ}.()»;x{öÄìB’ržû%FeÊT¤A¹:Œ']Hxœ ðuE:À€áÓL8˄ëM|èj2§Û$ì†Z%ÿä©ÀÕåÕá&E•›­óËâŹ¥;¥™ÅiÎûtK+ÌóL)(ñI:Z㟘ןח7¼5ïQp|þo~ ¨Ü^ˆŠ¤B”«ÃD&¼Øð}€ê8™ûjh¸]πÍ4\nåAG« ÝÔb¯yºÑWYïoP|&lmþ©M–95q¢ƒU;öUì–í.ÏpÝu<×c{i‘÷GÅÕ~[‹bŠ.n.Š.zSüÔ7¶dAW‚Šm¥(W‡I?eü½àϕ@:@ÁÍF +ºÛ:Îë@Ëycª¶C̪nsÕ-9竟ßj”s6Êü@}¬pomâúÔÓ)Ò¤“ûä 5‡q'>Vn©ªôÞTÕàUyÁ?²²? ¢òë€ÈªŸ«æ=¢«Ñus5:«Ã€‰r%÷jú®œ8OfŸæ.-¨»lHè²a–^tætz/ÏéZ} =b]Zëf«ä–xÛÍ;íã÷:ƞ͒G7(¢êË=Âëê½Âê:}Bëú|BêFÉ:íV7ç^‡òˆ:”©{–Nºxàó +€ÛµW›:?y›OæÏ^T]ׇÒ^+FÁ5);§Çƒ—ѽAO×ïﺴÉ4ñBœU\çۘó{ì>ìȔF|rTÖ^æÒ^çØvÞ= ­Ï# }Ô# mJØ6'jE§àV”ªû‘ÜÃHÀ]r×.’;h¹HæO2ÿ•õÓpl`)0¥²?µcíïWh§öù-Kºjðэ¨÷c¯ÇšD÷&Zn¼–*øàêQèÕ<»ÀžãÿžZGß+2ïž[2¯žQ™÷•)'Ÿî9‰O7Úû^F;uߑ.> gÐ_ÐEî µ“ÌŸdþ+¿?Ā¬ûÚpàþØ{߆‘ü™L3ñž—NÜpóp„~ÔÝÃð; Æ¡wRL‚†2,†ŽXû– +½km•ƒb÷Á>±ûÐßÄî·§Eîó¶îŸ¢ !T§*քðñ!ô‰>±¦üž8Ð^“®LI Åd𗩍lÙT,Çq*‰+™N׶›>¬³~ºLW4Ó g3s‰'|:DŒñÓÏx‚Éžà ê©»ÔÐDÞa5é`áÉ¿°‹äÇþ | è9ü_òÁû•!(_™SŠW"Úy֑vœuc8¼öaÚ½Ö½‰Ô°y³…e=·c‰å\º¦ù\Ût¾‚m2ßÄY·ÐÍY»pOË'´ŒçãÍÍ-ÒBÞa éàÇýÿËßò-ÀŸÆ|P¢&(Pœq%HÑìђ¡ˆ¢”¶BWÚ=iS `¬Å0†F3 1¹ +Ә+ñ°Æ{X®±YËñ2kY|üu‘S—Žõ‘þ}ö.?æ@È€çOò߁ä2ÁµÁù``AöaŠæ”1 +©5¸žZ…ŽÔJTP+Л^†4#h=Œ¥upÍÅ,†–08XKt0ØØËÐÄ»‹“75LòU$ÿ;€àxü ™#€€0Ç%°uÀ—ÂjÔ}4„åd/KÑ ôP@領ÒF)ÅAWJ½) ¦(Œ¢ˆt"¬ ê‰öEÐƖF;R!Ž"²Jh¯`¢8€…¶—  A­ÒÙhy„ƒǵÐâÑH´sÑüqè'î*.ZŒ‘o¿ω7rÐò,þɖXÑèD8ÛÐ(³g £œ‰?ÚE,Añ66Úîá 0G …Å\œ êµQÐJ\ ®·´ÑúY¿ ?ψ×r„ȝÿ/j©ÃõÖ:YÐèB(È>\E t‘1QîÍB§0M”ƲÑ!Y í2¹¸¾PÅäèÏͺ(îÐEQÑK è¡èñ ñ£ŠgôijºoĨ;K¼£ÎËÿx¡,(”›RèfB£Òœ0ÐSÊD% ݂5Ñ%šƒÎ;¸è´_ótÉ߸Jkx(i Z—¢äÑÃG‡>b˜áÏ9<æÏJ¦ø/$/ùÏ%È&Á¥Oߒ"oæ½?B§·ùÆzQèóo®Ë3ªÉ4 Ãoh""£‰ Ušt %„„ÞB 5@B ‘¦TYëX8¸VÔ;zгë¨cûXÈè¨<ûÎ?—×ù~ÞÏyïûûqY«Aè:5[¯¡tMÞ¨ ¬D`f/†ðð¯^ 4…>ÐÚ üz¾ù }¥Ž­ú‹zÈø3uÒøõŒñ<õ +qŽz—øŽú’øš:O|Iãç~`üÌV=¥Ñ.hÖ`™ t "ð7ÊN ¢qQTMˆ ֆ›—AH†ç¯ü$2øĪ3šl5žcî ~è[ý>`Äô-cŸéÆÑ5¯éSfÐÿeþ‚~Ëü ý¹Å#Ɯù}Ƃٽ0½Ã“ÛL þ— Ƌ†B°çF cJ€øµjˆûHÀ}Ä1—@LIJÏQÉz#rô߇¯zVMü#¤ÁôÅ•Ù³àn‹'A–¿³F­²­}xÜæ·ÀiÛ»×íþøÄn–õÁæzЂõL0X^ÛæW6ÀšË!`º`áÜðU8ߐ‰øŽ4|ï3¤þ-¦5Ÿªó.!qƒ§1ÄGQkîGÊ,î†7[ßÞ¸ÝæVØN»ÙÐa‡¡{×ýrÔq&ä¤ÓՐËΗBî;_ yë4öÕáìF°=Ö§#ÀòTX`Ì¿6àÜMØ{ãW"H7BÀÁdÛ²]Ôæ²¼5_g.}ʎÖ{šføk"Ïäf|±ùõØ*ëk1õvW¢Z~Þ´Ãñbä.çó‘#®ç"¸ Ÿt?>í1>Kúgø ÉÈO.Qàx,ìÅ€ÍÑ°^ „`3ÎÿÛù8úxÆØ»,ó|Â+>Iýq®ÿ’»Üð峜DÃöÓK©–’ËmÎ%Ö8œŽopšŠks=±¹Ë}2f€43J>}ØópôIÊ¡¨«^¢~÷Ú3GÞ ®ãñà4žÛÅ@„‚xì{ìåØ;W`ç2@_ŠV£·BkÂc¡³Ú"_Íù!º—y±†ç³Ù¦§9<«ŸØB»É4±ã±™Ëáä&÷C‰íäý ½ž{ㇽÆâ÷{ô‰»HŽ»GŒç5˜¸@LׁpH‡Å@~ƒ$ì{[0||GÑ +ô±Ô=/7A÷*l 7Ê)—ŠYºçQ†SüÓɜ,«#Ùö9eNû2$ncìzÒ?ÒZ×ïNÝá5˜Òïӟzw, –;XýȒpÖð>úIóÀ«–dY>¸-’–á-Ð\!B÷Eݔj oÕBWÚhº‘ˆN(œÔŽÈ}µ÷ɂWŽÔDû+“,z*2m;ÊxŽª’B·a¹±°†"4øÖå«hR~/C’·‡)Î;ªțf•çÝc‰ò?ø‹à]Y뫊À]²HÑÆ[@èY1B¿Vaß©SG—šèB³:Ùj„&ZÔ4y/Ù#g­¨‹$öHÌ;$l›61×±¹¢Àµ¡¬”TW*¡H‹ë}$B%M\ÔÍ(/ÜÍ,üÈ +Î n½§—ƒOY x–—‚Çb íï- ô;ßÍj„®ÊÕp¾:£ÔDÇUè°ÊŽ0®ô\2ÔÌÔÛÙ¾ªckœY›,ͦ©&k\Âw‘U“ªEbÏʊ:Ÿòò¿’²NFQé³ ä ‹_r*(¯äVP~é[† |Á·°(B0ßl5ôg>B¿U t]†«‘€Î*Õщvut´c%Úß±–0ÒNÖêkc,ïl 3R5n^ÓԐb]¿•ãP+Ëu‘H‹ûd÷¥³³|&3ùeæûþÞ#3ï¾0ÞÊÊx«’=©öKvçH–å»ÏÛUì=kç¿i;m_’ë0õptò¡n.ðÈ>¸Ä'³n…_Zmé}íWŠÄÚ +¥®¶>H[Û4î@o¶Æ¤ÐÕ`€®ýGºLspf=À1Zƒýe_ïØLýRsŸî`6ó`aË(˜ßâËÌnQ±§5Çñ ›õ¢üSÙ≧òí²›Š3›æJÓ¾ýÐUÿí_Ü×zŽküÒ;¾qolc½oLcéó9aò‰9ŽÞ1 è5Rk)íC:Ì{ ÀPðõWžXÒÂÀÜó\(n·†¢vW(hdòÚDzsÛµÜñíé‚ ãDQª±Ð:Ù8[¢3.²O0–8ĵ}êݶYÙ¶G¦1Ö»Œ5]ƶõ¹D´š\"ΡKø÷Ô¼‰ÎÁ€Ê +€­Õ§þ*ê/= 0· ð"&\BÖ¿l!£ÃÒ:‚!¥#š•Ô‘ÄÖufq:'óâ:§ ¢;#;?²ŒèüØ:¬k£XݵÛ&´ë°$äF«$¤«WÜ1h|í‚~ú£zó =¸}?ÀúÃÔo¤þê¦þ çô? ±Û´ÝnÐ3b{˜¨ÞXFӛ̊èÏV÷åsBû¦sƒû>à)ûKøýk÷ þ÷«„~÷…òׅòþÇByï ߎôyVüãÀÇæ÷?Kýv€‚Ë@ïx ö¡D?•€æ™ Ÿù€ú¹BžG0ÊqLà‹dÆ0‹%Ìcù Mc{ ½ÏöxùgŽûËu7Óv®‹©†+{uš+}u‹+5=åJ‡Þpñ_›ÏÀA€ÕÔ_Fý9¦\Èèw`l7@Ø0èÊJt€tôT€ªa4F1n¨ed˜Æ8ãÆ Yö8Ÿe‹bI°”eƒÛI Û›É52@¿csÀ'´ÿ?2÷ þ5€ôŸâîP»@ñ` ²ÀEԔPÓ\ÑœÑ Ðì1l1 l0¬1‘±ÄLFˆ“>Îb¸¸”a㧠ƒûÀcäú/ç£ßjÊ׃Êw‘JRCŽ“ä,¹Hn‘¯åƒ“ßï‚!? ’ÿ†šÛž Fz0åEüY¥f¡&žƒá\TOáaÈl>/ r¥*× Qù…ÛD¨('U¤Ž³DE³åï +£å°¢Óò¥¢Oô\ù\ôDù»è‘EÉùM‰Â‘0ŒúQn ƹ2ïÎà8_BëÍÆX=£&òP3]€ …^"°O,ߨ×[½VeõJ½ÓÚ¤ª°RU‹UGÄ/Tâgªs⧪+⇪nñ}õSq¯ú¸[â{j´¾öVwF@¹/ePëÄ`}¦Ð\¤Ðzèi=u\Ԏçc|¡Åpì<Ñ˘¥VtS°~U*~µÑæQäVÉ@d™íoš}v÷5uvýšû^ÍûÍ¥Qw5¿Žº¥y2êFäkûŽH´»…¶Wɕ(”›·aŒŒú€z{ÀtG³h.ÆÓÉR±0#Ž3œšÊ{‘œgñ$i¦å€n‘u¿¶DÒ;nµÝ½„ÏíïÆovø%n‡ãí¸=N7c«oÄÖK;bOI¯Ç¶Ë®Äޖ]Š}$»7,5Æ£Sk<:žOÀQçÐþû0Á‘Ž³-õmèHÓ8&É󼜤d½ÌÕ°Ÿd'òdåXôdYÞI›gs3e©]§~…õ¤5NW7HL4¸\ÒírýA·×­][ëÞ¦m}^ûÇ9íU3Ú~fݐ{S"º6&¡ìd2:ŸHF'âø6ÔQ7úÙtï̓Мº©ÐyT bõæÇq~ÉËtåæ[]͙i{iüB‡öÌåέé«\Î¥•ºMÝ8útêæ”2¯&}•w£þÏ }“ïqýùÑä_åGRžùJEϺ4t¯KG×Út”Õf ôm˜LÝ,+zºwN¥qÛ›éNðx†ôLdnG²*Òó/äZµN~Ïî»Ió[rËþMu¹G5}žqüI•K„@H &á8L¼  Ã5! !!!!BÂ-DÈý~A§uØm·γžÓMízº®ívqw—HEêÈӒÛÕÔ«|­9×Â0ñú‚¸“¡µÜ;áFîzx5÷OÕ¼×ðQQ€ŒBägÌC$kPÊû¾|½sKM„gZ;ø¸Üé>€™°  ·›.=·w¬$Ñe@Éqï‘ó<;ebï6©‚tU¢!›Å•ÔFQ=­.¯•Q#ì©Œ…U"t‚G¬rÁ V¹ðMˆNô¿“ú|D­#2ÆÏ”fƒoà+)À ì;Ÿi ðDok•vpßà‹a¶2Ôv\wzÏ`Y¼s·:íP{qŽG«2Ïˬù6“ëd:jÔH343ôâë!ZñHXiþ\„:ÿ!«$;²Dü0uÁÏt–Ê𯟠ù[ƒ8?^á¿Ûì|ØûWáAµ ,Õ€9£a²†i;d8åУ;Ð^žrðjiÖÑ&µÀ«¾¸À·F¥ô7•QõŠ*šVnbh +ÛCJdCáJé,K!½)—þ.R.û>¼Hþ_†R‚T +DQ!²5(à{îA‰½W °iÀÎe$ÀJæë÷Á/©§Ûô£wwT_ÜßZÉþ IŸq¤®<÷xu™Ø§B£ð/Wk(¥%•´’â†RÕ"W„K‹¦Y’¢{‘â¢O#ÅÊoà T?1eÅ(¨°Q0dkP6¾ î¡;Î`͈½»ß"vŸ™&'3{Â@x½1ÊþZ}ì¾&ãe·ºjÎá*÷˜¾BtB«/ôS——PTZ}¢¬Ž.+m –húÂDê©¡z™ÅW?ä«¿‰–þ›)*E´ü2D—¡kß~[¥OªpõKfì]-ã­{`°õt·R‰m-»Ì泎uñ.UõilÏR£Ð»¤ZJ*ªRÊ%•Æ“¢Š¦@ßÊÓM„çèîFdë>aeë¾çêÿÅäé-·Qù(Àšw€—ø=|¦ÃÔÜkXhÅރýk°}twK™ÐÜfWßvzoUkœ³®%ù ÆœyTeâ—7J|¤ EþùueTam5-×hfäÔt…d֌‡¥Wß ¿RýóUXz͏ŒŒ”eDL€5Ïø÷ðÉû;h¸‹çÏ´Œ`íê!@[¯+˜{} õ=LÛª®_9”w^ܧîHr+²pËÚ¸ž’V‘wÞU9)·ECÎi6P3Í&§©“‘Ú4œlºÂ6m„&™þ’lúžbB©&fBdkþ*Ã=à[\ŸÎÿž?ޅÝ;`ë@ãð¨öÃðI¢v0ʾd ÖQџà\ЛvPԓ}„ß-<Æí’zg]/&q:+È© Tv{;-±}„ß¾À¸Ô¾Îˆ³¼fÄ[Þ%X%± ‘1~Ö¼Äïái%ÎwpϿэ;èèh˜0L9‚nê(h¦(åT¸máäiñxœ“p,م7šq0k”8}Dâ™:¬ôbé|ëü. Z. QÎÌÆ<Ƽ¢Æö¿ 8߇ü/ô!Æך?”á êV®ÜÄûà°ƒ6OTÍbÿœ·ƒ¢7(\ðÉ“˜7mÇ»uÞ!kî²SúÜçԛ\7ölþ¡ÄYőK3Zϋ3µ^±Ó×Nœô==}‹3½F:5ýŠtjê­OÌ$:ñŽ™@^Ö<Ãwð ß!îïß;Š;ÀjœÃþµ ]®îþª'pW ™«DÎê»”ÕK»“î¥ìM¸—µ/nExàŠÌõܲæà™å÷SË­G¢—<¢–ç<"—×ÍbðnV€¾Å>hÕÃÄÖÉ0¾-<Ûâm[ãñ8—u{\Àºrˆ#?’óZ_#É3úM/âeÈȐñîo ewbp‚š8S-Ô]ƒYÔÄr¨NçÐaU‹y¨,"_“M|Tn'U¤šÔZú¾Ž\&M¼aåSހ²›×¯àúTÈë%=ÿÓýOÙz{½U z9ÐgªIOë1!€EÝ4ª1…C×¹z. 銌ÞéÖý¥ÝhÔ¯-öiw {µû…=Úákí a—öœð¥öº°CÛ,üC÷RøD÷NئCãò +Gõgû§„s¯ùY‚g.¶û/1nó_nÚâ÷•è‘ﳇ¾ß˜ß7ìwÏ°_Üd8"i4œ’Ü6Ô[4îX\3<³¸ìÛoqÉ%ýP|Áǝ÷CósïÁɔ;eàT3À(ª#–jšnC±îLo´7ÓÌ> åµ„¥ †Î3¾7%_Ôü…ù­ â›A_K®n”^ ,·¼PiõsÀëú€c² ?ÉÎ\—×´ÉÏtËN¢õ‰ ´¬ Béñ`”ñhD¹SE”oOu̐&Ê¡'Q Ï<™Ö8æÁôH®1&ÉèFT–é•È…æ?G|&¹^(=7µØª.¬Dv6l³ütèv›S!{lO„VԆœ´û!ä’òûûªšÊÃaƒ¶ÃP~`*Z«êp”Ž†¡æ€Ó„€qtîL¢:RÍ ¦þL•CsŠšR|˜I¡¼_ã„ÒEuq¹âÓ±KOÆ,±®^&?µÊöè´uŠšÈ-ÊѪƒûª#¾wü6¢N½/►*♺2ò­jw*vE¡ME4ʈõhn +ÃÒµ³ÐŸÆƒŽL#ø#ÓZ3Äp'S×2'2õ¼º´há©ÔÑñä,ÉÑď,¿›Q ;ÿ¹mu\‘ݾé«U{¦¯w¨ŒÝæ¸+¦ÊigÌaÍö˜Ë£¯¸lnsÙÛ§.›ŽöeqhW¶D>FŽô`  }À£lîåAÓ¸–mstÌÙl®6+Bx4s†èPz†dÚ\«½©yòʔŊŠ¤BåŽÄb‡òÄõÖ›5e Λâ«]7Äw+¯w_ÿÈcmB·KI"ªK’PU’ŒvÄv4ŒæÑ tÒ6×L睦y 4,àÃõùB¸8ßÎ,pcŽÏ7p5¹aFrâD{ç̔ìž=ÇjGæù¶Œ|Ŗ´ª6Ï\î¸!uµSiÊzçµ)å®k’÷º¯N>ê±*éœveò]]qÊ+÷âÔaMñLtX™†*b7Æ2€)Ô:óýF[\ÃB:ïäqP¿ˆ?åY@íÇÎP“çÃU/œbT5?F´37Y²-g–UYv®|cVž¢töbÕÚY…Žk2‹5ÿÊXë²2}‹Û—i•ËÓ¾Ó-K;ë¹4íÖøÂôNíҌA—¥™¨^6 í‰r´‘uè› ÐšÐHùW?¡wý|êò98™/†#j8¯g«> ì̛fúÍÂâM Ò-KçeËKr?R|•“¯Z•ý¹ãŠ9Eš¢¬5.Ëfoú/ÛuÕä™Åüÿ†²$‚FÙ!‚@èn”ª u lJA@ö5@Xö­YE#¨ ¢à.`ǕxZÇjUl«ÝFë2©ŽZ;s¦nÔg.õœ8g>ü>åäüŸçÞû&ïu)ß1»$~¿»*þ¤‡2~DVÿÐ]™ðÊY•È$ÅILLl'báoûpk¼9Àù@[D;W‡"!ö+í°»HÆÛ^à««Q¶ç†Mm•G‹š²Ìê3Ó­>Êȵ­NSÚW¦V:–¥¬u.NÞà¢LÞæVÔï¡H:.ËKº$ËMºï‘—òr–"•9æ§1{b7‹P¾Ï.ÓÎõ‰8E¯Cä`‰{JmÐ]âÎiŠênT¶„«¦×åśÕä¤XVʳmʲ ÅÅY咢LµSAF«K^z§›:kÍÐQ;‹k«ñÖi¬Z2E]±\PUnZV=CUœ`Q¨J·VåÚåª$YÕNéùM.)ù›g')v¹'(dñŠs²8Å]ٚü»&ä3§Ä&I*`â‰FÇga¼4g˨”}˜öÏ=õ@W½:êEh[+åšêæè¨ÕïéWÕ•V‡š(«¢Dù•ñæ¹å©VÙerیÒ"‡Ô’JiRqì5ªM®±ª·åhå'*o{D«þåºZŜb‹™„ˆ'z”|K}øŒjpšvÏAÊß×H{WÐA¯¡­ëLÑØlõ:O^U“niC€aÑÚ¡¢nå4¹:vfæGɖiµY6I5â5Õå’تz§èÊv—¨ŠîÙ++¹ETœu¯¸éQñO—•Lºª‚9DU0ñD÷R€/i?¥WS (»·èl£üõÀÚ BÔ¶Û rƒW²~>¿°ÍoJnë +㬖“ôu1¢ä¦D³„Æ «¸…mÌÚRûUõjÇÈúõNauÛg}PwÀ5¸n˜|ï¬þÅù5s U3b7ÑêÃ%z†©Ctÿ}­ÀŽvÚ=7õ[€*J5Pjfqùoù–Ez›ƒ S:B‰›¢Lã6ÆψiO3Úk¹¾Ø6¬­VÒÖ*YÑÚ%]Öºß)¨õŒs`ë7΁-σZ˜Ã²f&^ÞÌl'ú–~“þLÏÁ êÿ!Êß½ÐPvK'í^Ûe·.=ӑÓ#Af'—ÚíÃOìЏÛl³=Rµ-Ö4²+Y֕mÒYd±bkµuÐÖfÛM§Ø_³ÏÞOsÚa‰æk‡%[FÅ~›ßØúmf6þÌz¢‘ñÔÒPýû(›h§U¤¾(¥Õ(«Hí"yŸ5öÍæâöÍåE÷/æ¯ê_¦ÑfÚm¼7A¸|o¦iàžÑÒ=•3ýz›Ìõj,}{û­Þí=eíÓ{ÝÊg÷¨•ÏÎ7–>=ÌâÝf>ÑyzÓ  üÊßLwoÚTöÑþy€ö¯#@ÌàD Š°rH‚ˆ!O.tȇ<´TgÅ`°nÐàJý€Á8ÿÁT£Åy‚÷ʦú 4˜.8ºeú¼£}¢¹GOŠ¼®‰¼ŒŠ¼¿yb"¯ƒ“¡¥u°—ò·î ÐÝkh+: d ±´‹†žæ°lX€ a ¼¯uF€vüµ¾Üm ·HÊóÕ~¨³P›¨;_›­7W[<ÅK[gðí&COí#™ö„±ÇÙ¯Œ<†Ÿ»Ÿ~#p;Ån'™p¢c4û}”¿ò×S¾šî® Ð?K;è9¾õ0ÿ’ æ]²ÂÜËÎð¾<^W|1çJ Þ¹Æy^YÍyŒ¤òÜFòy®#Õ:.#øÎ#»øNW?æK¯~Á—^yÊw¼4¦'ùœéK.N¶Ÿæ¯›ò7R~ýA „îž}XCÙáç(ÿà{ðú’ÙßÀéÆTHoX@zS +ǛžüàCàp+ö·WC|;¶wT°¹ÓÀYßíä,ïâ,îžçÌïüƒ3¿õ‚3ÿñÌnN¶“úßAù ”_z ÓÝ×|Jù”ý>eû|¼ó5àr°¿£ ÛBØ<˜«‡¶°xè óGž˜ùhfüìÑãL{Ó'é0yZLÖA8Ú á³c<» +ãÑÇ0~2ãŸÙ$Êo¢üòœaÊ?Où”@Ù ([ö@z°ù0ÌÃÌçF=7…é 3˜¼°…𥂗î0zå ƒ×‹ ÿz9øcQÐù- ¼7ÅÀö́²1jîØ5ò„Œ‘ßþ«™ò+)?W $ÐÝïK¯ó(ۍ²(Ûâ0ý`ò +2=˜1 ™ ô™|f Ž‰æL<ÉB€ß_ý!3zøýè3:£B³‹äÞ$Ք¯ üDú(â+Àÿ;`.e»þ °»ª3eÓэ)߀z„Çøô]" &DD,‰=q!^d1 !ô¢Ìè‘5.BCÏNMÂÄ´[:8¿eçÊ1 OŽM[À1“Ž "8fœÀ1Ã3(%u¤c[ÈÒKö“ŽM9AΒÏÉwä>ù…¼mµo0îÿ’8qLJûå8 ÃƍcæÞ›áGg ¥³Äñ˜0‹¨H YG6’.²“ôÑY“cä ùŒ\#'£ÜÁ+q/…ÿóâ?d×yTSWðûÞK¾„!/@Ô Zª* ,²Ê¾…H€HXHØÔ¸ ˆ¢êТH݊Š8µmµÚ©£ãîà^ENµw~ÌŽžÎŸóNþúÝ÷ýÝûr€ÝÅOqþw¢)Ð^/  “(sÓHl—CbŽÔh&±M+è_€°Ãà<ñÞæŸÄ8ç ñšó–xÅÁÄKð‚ƒÉç¶ÿK„O>ÂŽÐNÈcÊtÈfô' ú“HbG‰ùÐZdACô6ò=½“|Gw“¿Ñ½ä8}˜|KŸ ßÐߑ¯èŸÉgôcr”?F>âcò!S˜ºîMà€§Aí\„=íàiOÈc†áOgØ#ˆÀSbH¸ýØ5—|'.¡ÆÅ5ԘhõZ´Žz%ÚB½µSÏE]Ô3QõDt€£‹NSEW¨»âGÔ-ñÆM1füìŠ×ÁOà¸úì u?³AxáÙ„}aM>nðۓÀÞóˆ÷žÄÛO“É_§)©çS ¨'zê±ÇRÆCÉ*Æ}I ãžd+ãŽdó¶äÏÌ[’}̛’~æ?$'™7$—XW<°.z¼6º0€sà;pv*f} τú¾–p¬-ö·†#k +€,æIÐøœÙÄKŸ`btVù`¦ŒºóY.uË»„ñ‹w5ó†×2ÖU¯&Öß½6]òÜn|ѳÓøÏ“óžMF<MÏy~ozÆë¶ÙI¯fCÞ¿›ðƦÇÁ€76ù#ì uç™Am„ƒa¡G‹ÑÓùÓÑý€¹Ä-ÿâƼòò\%ãÇ9ZÖy¿%FçüjMÎú®0=í»Öì”ÏfóaŸv‹o}¾°ø‹O¯å O¿Õ€Ï)«c>׬¿ñµ>èû›Õ~?lùµ¶èóÃæûü°ÙÇð\¨Ȃº „Ãa‘h<‚ž„ÓèN¨;º: ý-4„ ‰£Î˘'¨Œ‡™Îכ Ö[ 0Xö4[ößÂ>èßa³ß¿›óµÿ~Û}þ'l÷ú_°ëñ¿o×0ÆÙ'([wb+`Ù5ÿ0ñþð¹Š@hl‰FcYèqŒºe®F9¡ Ñ3ЙèâÛ¨(ÆñÈ֑p…Éá°<ó u–}¡•Ö½¡KÙ{BVq¾ +n±ín³ßÔÉí +Úë°+èogÐY^GÐ-º=øw[¶k ÅÀÖ[?‚0^õcºŸø_’t-‰…®Ä›¡‘:•èçýñaŒqñFûbe¦=‹²-º£µV»£Ê؝‘Õœvk¸íᛶ…No ëæo ;(Ø6ì¸1ì'ǖðgüõ¿;¬Äö͑ض9 +Û|ì¿/‘=‚ú7SºœŽÐ…tú>՝LµCÒOÐ!él¢/5˜Ñ“c´;)Õ´31ÓbG‚Úº=®ˆÓ[n×[ÇÝcàm\ÔL¯_Ô&XÝåØÝ'\=è¼*ú¢óÊè 1ïø†Xì쁭! ÞBwaî¼²¡ó0óœÎ$Ñ°œ‰³Ñ¡ 1êÍð&ºåT§,Ò¨Cšhº-MfٚšÍޔ¬á´$•Ø7'V94%6Ò«ÖVÆovZ¿C¸,nKCÜQQ}܈¨.þK]¸c]"¦ë’0Ø»Iûàiq'ú AýþR„úàúÕ :J™¨µÔm(sEM¥^¤¡ÄŸÑP¼Ð¸¶(Ƭ² Ų\+g—j²m‹óµÜ‚üRZ“W#P« BUîQVîW…ª×-SuÂ=#÷*x!ÊTc'… ”jLÞ¤Q8×'ú •ë\C÷T"Ô ¶ê ÔRÁFM.ÈP1hÐÏaÔ, 1ª(‹6-+I²ÔédìÂâ,[MQ¾½ºPÇSV ² +–;ej׻ȵŸ‹eš=nRÍq÷4íew©ö™8]‹…²,X\€iÀ›ôPŠÐ%ô28Zû 2¨ƒ À˜×ÔX¡µN¨¡vQSãK髂X¥•‘&Å æZ½Ô:¯\ÁQ-QÛg•9(J+øò’F§ô’uÎiºí¢ÝW®Iºcn‰º‹à©(Y÷»SŠ ªÃ¼IwàÊyÎÁôàpB{ëa4ÂÜ· ¡¦„–7X úFU7þ‰(o˜E–42 ëÍóëbÍrkS,³kälEµÊV^UÀM¯*ç¥U.$W4 *Ú\âôÝ¢XýqŒþ0ê«ÿ¾ë4ª©k ð»3€!ˆ„A4¨(ADqž—óp—U«Ö©½Z‡«­ +X+ +8"8Kl‰Uk+“âÕ.DéÕÚ:¬ÖZÀ«uÀ}_»Z¥þ¸?ž•äÏy÷÷í}rÎç?hžôL1+¦'Ǫ¦$Å;LZÞ_3~ùPí¸ecŒ^:A?òÓižÃ–Ìñ²8Ágàâ~ý³üû&îhÚ;±ÀØ+ñœ±Wƒ&½^úõI>äÝ7AþR9™ûÀ°ï{™¿u{À±dÕ*`}œªÂ¬4=f¤15½˜”©x/µ‹j\jÇÑ«;ø|¤vØÊñ †¬œ¢øÙG û­XèÕ{E²wϔLßø”m»¥nÜ5ålã®É÷ýº%½ðé–$ ݓ¤W÷åoçÁ×óy?²ÿ»8ŠlJeҁ¤5œý29ûeïg»aÂ:_Œ_„qëڋQÙqÊáÙ=ÔC³8֐9NÛwíûn½×ÎÒõX³À£Ûšåž]2ÖxuÊØjˆË8ä›Qæ»úgClús¯¸4و<ë+al܃½¬?/ ÈböÊ, q=0›³èDŽGcr5™ÛÃó04/ƒó"ÅÀ¼®Š~¹}T½s‡¨{æŽrì¾e‚¦ë–é.ræºÅå,ÕEç¬vÜœ«ï°ù GDΏˆÍ÷ôáŸëÃ7H}øzéQÏIÞ¸ï;˜¿q-¾Žç€ÙóriÛ9îâüÇѨŸÕ }¬>èmm‰žV â­±¢›5^t±öWt²SÆYÿ¡Ž¶NqˆÌŸí‘¿X–ŸæbÎߢm—¿_Û6ÿ´¶íž*mè®ç®¡;¥k莿+àÈgÿs˜¿–µ'ç ·³vöÃ÷}8 ®À±þˆ.B”- ‘¶8DØz Ü6P„ÙF ³m¢¢­m–²m‘ªµm¥ÚdÛ¤²}éÐêh‰º•Í®nyä™cà!éxP:Õ·çn+ó³9 +®dí ;¬À¤ýÀH΢ýl@—ã@‡“¡…„éѺÈÁEA0[T‹V%=вdKÆ Eé4++J“DÓÒu¢I©UøŸ>%üKïˆÆÅ¿+ü +¥ÒïÔTÙÁü ÌOÍ–°ï³¿&3{ÇÑþ_3ÿ[桧À«à_î ß îð©ðwE .†R¼.uC£Káɗ†•Óàñý"èÿ“÷ËÛ¡»rœ®AWY ÝE ]…º ombþjæ/eï?fíSX÷hf÷?Åü â rh^øUž?¨¡»åÝmw¸Ýñ¡fp½íݸػÀÙ>šª±pªšûb¨í™PÙ­P؋!ìv êIÀþÖæ/ßÃ3x˜ÊÚG³îþ¥Üÿ³@ûïS`üð¾ +诮·—j'hjÝàXëU5@‰Â¨#ñ¥¤†ãÞø5¼ékxÐk¿ ^øñ]zB/ÞHfþž¹Žñ,d~Љٖ‹@«Ë€ÿO¬ý&Ðàà|P×Ê:¼t^¸’;5âo +¤¶@] ðªñaôŠë\‡ä:$¹d‘’–wÞXÈü鮹€NR]åÕïã%žü±Š§ +RJŽ:çR¼p¾„§ÎU¨u~Œßœ%¹Hüª•x¨•â]²…/d ²…×ÁϦ¯{̽‰Ÿj  ©ç~¸O¥9Ä^è’D.U¼ÔeŠçºâ™.O<ÕíOtûÄc µºBTëÊñPw÷Ük`w%î襸M·þt³ÔÒ䤇lÉÏVìGKž‹f®§#dã¾<3#ÄKï‰âwï™â‰a¾¨5,Նâ‘!]üjÈ¿rÄ}Ãvñ³a¯¨2vÃ7âŽá¼¸á}[üèS-.û¼R\ò•Š +º@åï!ÌnӀ\!CuÄ~´a/ZólEâY`<7"Œ¦Š{ÆÙÂn\$n—‰›ÆÏÅ ãq͸AühÌ?÷ˆËÆŠJã Åŀ2EyÀuŹf¿)Ï4«S–6—Êb*¢B:UlË|³ ¤Å 2œëçšÚû Î܏ۚñ0¤#ªZ÷Å­àâ§à âŠi†¨4ÍUT˜å¦$Åw¦Tå9S¦ò¬i“²Ì´MuÚ´WUb*P™ŠÔ…¦JõÉàêcÁÏŽ¶–­¥ú~‡ Ó2W ©„Œá:b\Qíêq¯}n„EàŠ%‹󖱢Ì2YQjùPYlž¯:e^¬úƜ¬>iNs8aÎr8Ö.Çñh»Ž¶vûŽ˜O82ŸÓ0ßÕ|aù¯Æj‘š|‹tÚm‘Ž¯íªGF8BFñ¯"xÞY º³ª;ºÂ£ÇÕ¨&(n‡³1PÓO|3Bq"z¼ò«èÔQÿt8õ/ǃ‘KœöG¦höE¦ÿé2 jë¼Âð‘Ī}Eb±'{¼Åc\jl!ƒB¬!„$K€@$6±Ib·Ø±@Œ… Æ8ÂÄX$vl'®×Y&‰ÓvÆíL“Ž=iÓ&“I:MÓÔmšôö43ûÇ3÷þ{ïyÏ9÷û^ê+b?uU¼L»$¾L¿(¾Î8/~›?b.ü†±”JÐϤ´ÅT‚ºJÄ> ‘FþIÿ‰ l€Ç +|,‚ßKið #ޖí‚_ÈÒà¦LAº–YB e"®dÔD­±G_’¶Åž—vQƒéÚËéãŒeÉ sI²ÀZ”¬°OKBœ€äÇ/yȝKÿš3›þkFJ0§¥}únö3‡ÑƒL̽ø{T€¹óçƒ +¼Ÿ÷røð†r\Ëý9¬çf’W•” 9e‘AEEôr¶5öŒ¼‰º ï ²z˜þ¬!֜l’=+;ŝÎ\æù2×øS™·ÞÌ‚ Ù‚ñ¬ï¹cr‚0GåãY)kXÿŸPû!æ¾Jî«îEÀÍBl½kªd¸ J'Ÿ+RRΖDž.0ÄøóÍԓyõô™ÜÆ ¥‹5©ìçÏãŽçLóG ‚aÅŸ!Å5¡Gñ®h@ñ™h@ùDЯ$¸ý¹a!Ì0ÿ÷à«\̜¨ÿ/÷ñ¨»Ü(#AḦ́˚Ͱ¢y –4i¤Ó¥rÊ)uQäL‰6ÆWl¢zUúDQs´°=\ØÍ,â+˜ôçÏ {óƒ¢îüxwþ/\ùœÿ: >Âul„æG<Ú>G~‡¹ó=<òï˜ðž„ðýr9‚º8£ß óz1iV—Iñ•çEזƌ•¨Ã3ÝSZÏP·°ûJ\ܞ’¾»x"ÎY|RÔ¡ZŽoS­'¶ªî&¶¨>Ij)þ{|K !hQ<‡šà ì0ß*°èÁ¯õèAÀ-3æ^d­ hŒ…E“ü¦í0cJ!M¥”ñ£ÊÈaCq´G_Ní×UÐ{Ê­Ì.m#Û©mçv”õòÛ4£B‡fFÔ¤YJh,]K´—ÞN²i~»É¦ù[‚­ŒÚ´ß®%¸'Ì7؇Ç€1wÞ­F0w]©Å¼cXªŠ¿™ÓÕ[ÁkN&U&VfG TF÷˜4±nãQZçÑjF»ÁÆn5´r›õ]üFýÐ®óÅ×ëkË/'Yt·6Õè~ƒü5±Fÿ_¡EO,‚g5Ü0_ã.|\Ž}ÀºßDýWë1÷Úñ®Ïy+¦­ðZ·À¨u/iВFEtUçG9ÍêØö*=ÍQYÉh®¬c5T4sm&¿ÎäZŒ“ñÕÆ@b•ñbR¥ñÆ&“ñ#ä«Ä +ӏ¢J!@xU&‚æKîöþ>zpu¯6¢͘7ð9‹×o=Fl›ÁcÛ ½61Ù]ŸAé¨SFµÖÇ4[Ë© – +†­Æʪ­näXª;ùÕ恸Jóq‘©ÊŸp´ê|’¾êú&]ՇȗIzó"ƒ™ˆCøGÍ/Ì_p…3øúu×8mxßÇ 8ل™§‰ǚ¡§y¸šRHíéGƒ"²Ñ^m³—QëlFº¥¾†Y]gçTÖµóLµ}q†Úq‘Î:— µ“4Ö×6•ZßG¾HÔXÿ#*³qeµ_k%xa>Å}ügð6Ö¼ú—:Î:1wvŒâw ´Ò »MζmÐ֖Ljn=Lnh•GÔ; +¢­-¥±ÕÍZe³™ijªg[¹ºÆnAYè°Ô>_b9Qe5©Èþ^R¡ýs|ÿ^¤²‚b;ÁGxaþ€}xçà&Ö¼Žú+˜?º1s Çð[Ü®hhwñÁá~Ý{I6W*¹Ö•I©væFVvǘ:Ë©†Ž +zy{-«¬­™£nsóŠ[‡ã +[gDùŽåøÒ­ŽÄÁ­dZ–$¡EÉ,¸”,…siœJ÷Á±ôg˜ÔÃ|XHæCBr<(dÍò–s r€Å뀯ó‰Àhf'07Š¹!™_ÌüRÀãÐâ¤å:ØW˜ÈƊ¶°«ôƒ¡2ˆúB_}Õ(ØVM‚®* 6U« ­Ú MÕ º Me´åâä0?ƒù©›É;Ï‹€ÄÌgns­e@‡@›Ó€s%`°½¤„æ²-T—MP^q…âŠ7äW;AºT÷á†(ŽÃÑĉ¶ff>X×xãkU@íc^_“ø “c?‡ãž\È÷p/0„ÙQÿz:ŸÚU­ÎŽÃe@û+ ¿n:Ô¤n™€ßZpCìÉ͐7¦Ý€›3¶ã!Ûñˆ/þão)¨caë؉ºÀïÏ?˜Ç±ŸÊڏã×CK€þìswöُMö>´ü0U³ïµ€ò&³ïЃ÷)yoïcêÍÀ“ÖÀÓöܤû¯¸Q}ÍE¹‹Ñ.>o9á¼Ý¼ÛG윸öÁ´ÝÀxÖ~ØQ`³»Ÿ:±ÏžWXûÀxƒ}¿Í¼{ô~§çï½ —ôš5i`MÞÚ󞬉ð"¿¦C‹àFQ°‚íl‡`á‹.~ œ¼ Ì<_šÈà ¡²@€ç]„Q }Fãi +ͦ…”IÙ´†6Ò6*¤½TL'éÝÁ;<¡wxËßÞPß-ÝÙôÖl ùÙ¦-„â/ü¦õ§!ô9M¢J£%´œrhåSíaÖÞ· ¯q–%ºÉRÕ³doð”ß6zò'D+7·l9º²¬‡­/„6BÙBÏÿIhêûZ, ¥´’=ÌeB3·2³ÏX‹'(ar9‡íóç!^ññ¸ßH¸÷„»3DG¶ÃÂÙÌz´‚pèÀštÐs1ãE;w<öêˆ;A¸Þ&WÛ ÆE÷‘8ç>Uî“Qá1§=æH?y,’NxdJÇ<²¥2uÒQÏ-R‰ç.©Øóì°×iÙ¯›²½ÞOeEÞB¾‡v½Wøá§jz•­ä/Ã+«/ü xàã„ëí=ñK{+Î~†rK NX†¢Ì2Z*µLŠ-ÉÒ!KŠì€e®l¿%]¶Ï’%ûÁ’#/²äÉ÷X +ä»|ö* +}Ž)vú\Uló­Slñ}§Ì÷ŠM…bc#ß?4esZ à4ÄéþÕtU£¦“çü\qª³/ÊüƒQì]â¥}þŸIEþcd»ý¿”úO‘ï´Î”ï°¦)¶[+¶ZW(7[sUùÖͪÖÝê Ö#êõÖsê5þ÷ÕÿôoPçtêU]„*»‰²™èÊ60ÿ>§´k½€‹t&TŽÊ Ž˜QÔ?wÃ÷ÝÃQØ=F*N”m %ß4N¾)h¢"/èÊõ_«ÖÎWçf¨Wdkr6h³vج Øo³"ð´nYàoºÌ 6ABûm°ÐúcùõÌ¿ÉåîB$ÏQÀñ~<ó„)p0ÔEaøW¯ÎØ‚üðHiC¯xÙÚ°áòܰъœž_(³{NV­ ®^šªÉ +]d“²L—’k»$d‹>=¤H¿(ä˜aAh­a^èS}ZO¡#›¹=…vn˜Ð4ݛ–¹jfWpj/Äs'Ï ?FJØÓ׀‚7äGúbCdr#ûH91²•ýåËûPfö£Ê蛤^Ò'Y›Þg¦ÍÂÞiºù½3lÓz¯2Ì ßh—¾Ë8;¼Ô8«÷û™½ëíRú}J_¡#Ò6{Æ܎~fþÉÁÜçó췏×ÝlËö:lŒvÁژȉ醕1aRVtYFt¼bñ€aʅýÿªšß¼&-j¢ö›¨iºÙ‘©¶³"Ó )+ì¦G¬7N‹ØišqØ4%ò¼Cräcû¿G ;ғî=›FÿáøתâYžûöcþPæ'p¯§FnœÙñÞXoEF|ˆ”×O¶ v"-6QùÍ ªÙÇhfLÒΈIÖM‹™©Ÿ=ߐeœ½Æ41z»ÃWÑ“¢«èCRÌ[cÒ@a [Ò5{Ì砚}>•ÈðÜ÷Ãî³)8÷ú +|—`BV¢– ñÃÂÄ`)-¡·,5!Z>ëÓÁʔÁÃUӏÖL¯MŽŸ¤›7]?1n®Ý—±öbW›þ»Åq\ì>óØØró˜¸{ŽcâìÇÆ ;ғm³û|/²ÇÙÿƒ#Y.õÛh=?góo™ÃŒX<¼5æÿ/ÛeÔä™Æñ®‡Ö ©GAkµÐ¢ˆÊ!¢†#@‰ AåðâÐz@TªBt]O »®°µÖZa»Ý]ÇÚ-3Ýum«µèn­­Õ~û×êL§“ùÍ _¾|ÿ÷ù?ïû~ψµi¯ŠªÓ扫t‹$å©ñ¥))2kŠÁ±89ǹ0¹ÐՒ´J‘—T«2k7¹gk[=LڃžYÚSšLí^í &3iH™$¨²’%QùS™‡èû{Œý Kž·rèÙ»œµ>¯5é•Ø`‰:Ãd¬1ÌUæŠKõ‘kÆR‡âô$iAzºc~šÉ97Í⚣[©X®«Vuî†ÔúÔžé©'4i©ý^ºÔ›š4Ý#ušNpK× J¢æ×â?˜ÿsYÀIjËöç³çËe¿C?Öå¨1ù Ê4«LÓ±Òôº¨Ø¸P\µØ!?k™Ôœ©sÌÎÌr2ò\² V¹A¿Z™¡¯w×émꔌýžÉÇ5Iú‹^Zý ŽÔIzÁ-Y/(‰b˜kÌÃÀیû8µ²ß(b¿Áq£¨1;£Â¬A©y<¬¹/£È,²˜ÃŹ9‹$Ù9 RSvŠ,3Ûà¤_nvI_^,י*•)¦ nZc³:ѸÏ#ÁøM¼ñ‚&ÎøÇûêx£à–`”D1̧ÌÃÅLžŒ»‹Ú¿·²çbI¾c­¨°HQbQ£¨` ,È-˜-Ê)›,Q’LËR}~’,=?Ã15/Û99¯ÐU›W®HÌ]§ŠËÝæ¾ÄÜîkîòŒÉ=O®yƘT/6 *¢Œ5 Ša®pݝ§' ˜‡恥ø.–Ÿ›8VrVb±ªk}9%“`* BfI¨H_²Pœf•¤Z—I“W¤É–­09%[\âŠKå±Euʘ¢-nÑE{Ý# ;ÕEç<]UGþàQ(¨" ed æï\ÿg¹ŽSëµÛVÍk€zŽeÔçµìr9²*¼a¨ðGFå4è*CD)•á⤊EâĊx‡øòéÒòLÇÅ«r­*q‰*«–/,Û¤œ_¶[^vÌ-¬ì,ùÔ-¬ôž*¬TPÎ[É +m¥ ¦Ÿt3Œûµ[k7Ö²ï!%uÔçÿµNH­õ@rÝXh됸vâë或ÖEˆc떈cjµ’èÚ iDmŽlAÍ +§ðšÕÎsk]C«[å¯WQ„TÿYR3 YsW²Zאªçœ§'J#Ôo§nË ¡XÝ‘L¢m!®Q‰%#Û41MÓÝ‚¨¦pQDÓ"т¦qx“NÖhrm,”¾ÖX! n¨wšÝ°ÓyfÃa— †^— »Ì¨¿ã¦Â¤c>˜Øᇠx±c&ü;æb|Gü:1®S±ùÝY‰Q›1²³#:ÿßÎáÛñµÈ÷è‘ÏAìsø9‡š€Ýô|Ûž‰Œ¹ÌÎÒ©w Xг=|™}鄓ÀèÓ2øv«àÓí ïîqðê~ šî xö́GO4Ô=Ë î5Â½× +·ÞõPõ¶BÙÛEïE(z¡<ó”§(O=§Þ·Ð÷zú]ɸ-ÔÖw "N!§©ß ¼ÈötÔ;€æ<àö¾ ®ýJ¸ôiàÜ7N}“àØ7²þPHû£I2$ý9÷—CÔ¿èçƒûÎp¼Âñ;ò˜¿°“Þ7µqÐóBƝIíÄSÔï¡þÛôÿàÿ0ò"àñ@ù!àtIÑeà²ñâKo4pe" ¡WX²0û„/ã#ÜtÜpLòÀò.ùœÜ#?áo0ï5Ìw1cÏbÜËz©Ïxƒ©;…º~Ôõýà~ 3 é'þM®J€ÿp×T,†=/^`Qî|9•…Y0ÈyÜâËðüÛ\t·ß$o‘>r|O~|FÝ!žÇüÊDϵg¹/P¿d¼c©ëE]Õcªû¹An’ArKĂܑ©øÆlÈX î÷Y,?`‘ø/ƒG|ñàb‡hôE†þE>{F)×[6S•DÏ£¨̘.cþ xò6o“>ÕýŠÜ&ߦw -CÁ}1µœù<%ðăÍ=&‘Y„EºÀy<Œ…„›N é Î>Cp Ám49qÉ42‡,&©$›¬ Ud=ÙLZțÄN’rœô 乎ŸqOð?Â/ ý +Á“ý­z%qâßx:)$„D-É"d©% d+ÙAöPg?uã1º¨q +ðâ¯x€«´ékÚõøžÜ%w~…àíAãE?4ô‚t¯N"³È|G҉™XŸyñë8ÿ&>y;uvQ§ ?àuŽRã8ŸÛƒoñ>Õ?ƹpnóŽAþò+ró7Fx@ðq§nT¾\ü9æCô41$™±©[À§•1žjêl Îfê4ãh¥Ž:©Ó…/éÅu¼‹Ïñ®Ë<¨É;ãß÷HòæTê}Pem:–X5 $p 1$Œ$"B<Šâx-ÞJ=pQ¼ê¹žÕjkkÕ¶êV«cÕÚÚuWÇíÚÑm;Ý뻏«Î:ýã3¿¼ï̛çúý~Ïó½€Û´‰oÑ7(S×韮W™°Ï_'Û}Ք%åCC¾P>"úQmCTŽÆoB +~•ZðïÂC¾ øjü«Ã]¾ßóóñ¿·ùøFҊ›’6\—lÇUÉ~\–Ç_¤çqQö¾á¼BÄY¥ˆOU"Îü1J±¿”üà F* ö!ŸzR}ºÀ/Ãñ£&4ø›ºwÔ|£öãkuWÕa\QÏƗ긤þ#.hVãsÍ|¦ÙŠsš=ø´Ó1|ÒùNwþ'#ãøk"Žuq¤‹Èþb Ù€ç $?¢ø-2z÷Áýîƒp§ëÛ¸Ñ%Wºæàb7;>ïæŹîU8Ó½÷˜Žz4âÞÍ8Ù³'z®Åñ^m8ÖkŽô:ˆC½Oã`ïkØ×çŸÌî¾O˜]‘"³ãÛ_áǘ®Ù§ƒéØ÷1¸-ÇÝÈÎøºO$.EÅù×Çà“þ&œêŸQ…8åÑèEOÁŸ£g`ôf_ôBfOôræ½ï2»lav ØËlp‚éx‘ixŸm‹ù7»1Fd7ë‰w_AB> ¥«'–®ÚÀ ]ûÃ8\ŽQà|L|4hŽ¿9‡'ã€6{µ6¼§õ`§¶œÙ®­f:´S™-ڙL»v.»Y»„ݤ]ÅnÔnb×kwr­ÚÃܺ!g¹5C¾çVý™_>Tä–-È¡ÿG<&»w銿6ø‚ZÎY=ðñ[|0,‡†Ga_ìpìҍÅ6 [tyجs0›t%ÌzŸmÕÙuº:vMl·*¶‰[ÛÂ/må[b·J–Æî—,ѝ–.Òݒ6x,m!Jæ?‡Ÿ÷ +OÈþ?Èþ­$Ò[F²M|@¿Æ380Jƒ]£ûb«^‹Íq£±!ވÖø,fM\³2®]WʶÄUqKõ“¹ÅúiüB}£¤Y¿HÒ¤_%§o“ÍÑï–5êO³õW„†¸‡Â̸§²ñ¢”¼ÊO£¨%Rë¥kýLÍù™À!jy{“Io$(ñ'ClHüÖ&ÀÊ$–%™˜¥IfQ¢mNôpM‰åܦ$Š2BZó +â©¦P ÌÀ)Ҟ‡s=´n#ڌ2´¦tŪÔh´¤Çâ´1hNMaæ§f3sR­ìì÷NŠ—Ÿa¬ä§C’°1,­36 +µÉKä5Éë¡äe0ùj’ñ¼*`¼§ +¤üG11EÙ«ü`®SÜgÉöññÀ~+ÅOëfz^—Áb¹)K2ú¡9sæ™G£1sӐ™ÁÌÈÈcøº 7_k*“Ô˜Ґiª¬:½A¤/”OL_­¬LoWU¤P—§ŸQ—™î¿*ËL¢¼,Ch•½ä>åürp:Ÿ´>»iìØBëzòeE6él šrú 1çM4侍鹦>'™š“ÃÖd[¹P¶‹¯ÎòJY•Òª¬É2Ö ¡Üܤð™W(½æ6u‰y¯¦8ë´Æ“u‡øEåÉ„œ^òWÚ(æ“6ҜN`g!å€XK- ù5?O…Yù=1#?áño¡vüÔä™`¾™ äå³UyvΟçáË-RŸ%(óZÂB±e®Â“»LU”»QíÊÝ­qZ>Ô8,·;9,?«y¢Â™'ʝQxÉ·T÷ódë8ÙÜGÚ³£˜ô±²X@~Í*P`š­¦Ú¢Q3a‚6=¶$¦Òfb+ +rÙ²WZPėX}5 +²Ö .k£Âa]ª²[׫mÖ]šëÉNVëMâ_j«UTXEù „gܤ:œ![GÉæî Ý´-^šõ]4ë:¥¨u¾†³&¹´¨rD…ÓÀøœiŒ×™Í;¬œÛáâ ^‰ÓQ%µÛk›}–Âj_¬ooUçÙwj,öš\ûuâ±Úb•„‚Â3¾²Ð^ ¤Øw–ÑY¨ ÍGãðâr`¦‡ô†›Cµ»3ªÜ}Qáye¼ž1L±ÇȸÝfÖåÎçœnowKlE~©µ¨FÈ/zGn)\¨Ì)\§Ê*Ü®6½¯É,úŠx¤2‰Js¡¨ ä„ðŒKtNRöSìÛ*©4~®$š'õô®ºð—jà+텒Òx|ÃQ䋃Ë7Žqø2Ø ¥¶ t7¾ÔÍ畖Kr½!Y¶wºÜì] Èð®Q¦{;TiÞ£êTï—ďªÔQ‘V"Ê_ <ã3:ïS öPìí4v¶†¨“¹´N¡±ÜOï½~%ÜþnpUFÁQ9ªF¢ ÊÀX«Ò˜üÊlÖRiår* ù¬JŸ$Ã?IšîËRýóåFÿ*ErÅVe’ÿˆ*ÑI•XñP™T!*’ÊE9!Œ{Á:‡©;)ö¶`õTҝu´i ’/>òÅ”aB0ÁHŒ½¼¹¡1șld²B™Lf(Ÿ5…\Z¨„O N”$ë¤IÁ¹2Cp…0¶º]<¤ˆ^PÄUÿ ŸôTˆŸ$ +ñQö’S”ƒýoÙß&Ý7h"i4L#ÝUOsƒÜ: ²ë{Â\?™áa0…G!=œˆÔp:c ç0ãÂ66)ìa õ~nLý>®¾ñ¿\—yT”×Ɵ°Œ3,² +ʦ0 ‡'Æ-DkÕ$F­5O465"¸eE© 8€¸ÂHÝpjÜ%Š±©§‰&*.ÚTÓ¨(1Þ> +&©üÎÇ÷÷y—{ßû¾ª¾™EêÔÌ +9³^“œÙ¬Iθ­Ižÿ³&9]hÌéBmž×Á^îÁ]ôu õKY²+Ç¢ùVæÏwÈÛdX¶'†äø!-'¯Yã0ØÚƒ¬ý0Àš†þÖèg#Y¬¤Tëû²Ù:Ga²f)’r +”/çlV&æ¸TƜä¦Ò˜õXe\*TÆ%¿RÏ=PC_7f1³&¬àyÈeVr¬âì•Œ ƒódô³ia±¢¯=©ö¤ØÍH¶÷‡É>}òßBRþ8ôΟ,í³$ƒ}‘o·É½ìäX{­c?&Çؾ“cò~RĬäv°‹ywÒ÷RŽ@ùÔ´ÚƒÆ`5÷GÕQk×‹WÖI%0–ê‘PCi4âKˆ+MA/Ç@ôt C¬c4b嘆HGº;ráX/us씇¥°ÒëRغv)´XH¡k…üœ­ô}/²q ©;“z“8¢Žåxøû@ÿM€i3_ôpz"©G¸3Ý*£ViDhe +B*"¸r8‚*Ç¢kÕ$T͆UüªŠá[U}•ºÊVè·<„¾B@_.¤ç”S}·YԞÃqp +5ÇQod%0¨0o¥þ6 r'ÌùÔ·î%è\:­+’àã2“Aðv€—k<]SááʄÆeƒÊUe]#9Kî@UûêÝâŒ{!ãm¥ßéôyê`<5ßäX:xõkƒ‹þ7AŸzŽª>Ðô†¢ÉRS0‹\$1θل¹yáºYèÝ<ðn&ú ;¸|Æ&íy@Ä/¬a®—Ó÷Ìr`:}ž@í·ê€×ê©OÍø=@÷ý@àA@wð:(ƒ†ø_àíh¦Í´ã´8C;Îð2na±oa‘iá&o¡ƒ-\´å ¹Íß?$Ož±’9_HßgÔéó¨FêÓWó Î „Óô€c€ö$àñ9µÏ’¿“ój6@ÞÀWzàBW6¥À·.³Ao¥­¼Œ®òò»Ê¢w¿Æä^ÛÇæñKr‹üøŒÅN`Ãôî'¬ÔN£¿fêö¢nuýNÞ_Ð÷§š_“oÉÒJV\Wp(y ¸©es̘|ÂA%šÍzpvÜccpŸ…ø>‹Þ&ý7Vlc<Ú.=c6÷Ù$æz ã=ä0Â8÷¤¿¡ôWO]Ï Ô¹Ô©yÜ$ÿ&ߓ»äBwp_Éõ<vð˜1=H"aÃ,h‡`1Ü¢„0肉îgŸ0ÏPð¤B œD“Dò*Nþ@Þ#3IÉ"¹¤€“2RNªÉNÒ@šÈI<Á7ø™Æ>F;~â—vò¨óù[„.˜vB¨»ò-¨ÓŽx’J†Ñd"ù€Ì%‹ˆ•¬"«©SB Ô© N 5jñ{ð‡qç¢á¿|»Ë¿¾Cž?ŸòŸN„¯?D_/‚§„b"ƒÈäOd +µfRg>u–  Ëp6êQ§”)ÙÈõ\s;SU[ŒÅwh¦W˜Âp•ÿ}•«´’+\îDøë ôZÆÂBӅ9 à×îÄH^!¿£æêM¤?Ó¨3›ÑÍÄmæä&–SǎXC56síjnŸÝ¸ÈX|£8¯ð%­:ÇU¾àj-äÌ ˆ@oÚáÁX¨ ´^ÞzÚÂXH±Œo2ýLÍ7¨7ŽZ“©3¶ÏåñX€ Ȧ +êä󸮥F5*pš±hf,Nc<ÌGiéaæãõþ& ¸ÿUÓnOâG;ôŒ‡Ö<#pW€ + .+†â¢âmœW¾ƒsÊ)hQÍÀ窏pJµ'T98¦ÊÅQu«KpH½nu5šÔuد9€½§±Çó:½ÚPï#à"uOÑ +Ôv"©ÚA;öý®*< ·µhõŠÄ?½’pÖ{š}†ã¸ÏXÑNÄ!íûpkg¢I;û»,ÂÞ.VüU—‡OuEhЕáuú]¨ÕïÃ.ý)l÷½Ž­þm¨ +p’-/ XbEwõ(àKËeë‹Á*\Ðyã¬>'üâðY@*šº¾Ž½o¢1ð¨zuAS±;hv§cGðbl ^†š;ªCŠQ² ÎÐT„6`sØQl +»„²n?JŽp!•’’!­û "–¥¬'õ,ƒ½YÊù<Å÷ã8æ‡}á‘hˆHBm÷þØÑcj"G£:r<œQ“QõÊ£>Ħ¨ lˆZŠ¿D­ÀúèB©4z½T픊£ë¤51n©(æ¼T{G²÷²ä‘UHOicÙ{ø†WÞé¾À‘T^o}Økd4Æh±»g7ÔÄPßåñiØh‰2ÃX8 PbxņéÒÃiuB¦T˜#å'äI¶„b9/a³¼2a‡¼"aŸ¼ÜxFñqâ-ENâcEv¢³:YÚÉ=–ÓkÔ=ןóÖ@Î|¤áU –×߶Þ^pöĦ¤X¬ïcBIŸXc†Õ¦QÈ7ƒÍ4QZeú³”kš!­0}$-3-–­¦år¶©P‘e*S,1mU,65*šN*$ßPf˜)盅"ýîšêŸJ£ÿC€Æ¡ìqùs5¿•§¨±>ÅÅ}{`µ%v‹«,iȵŒÄ2ËÉj/e[&IK-ÓäŖ兖 y%[‘a±)Ó-%Êy§j®Å¥úÑeÕy†ñçޙ{D ŠK] ¢qÁD–pFf`¹âf–Ù•ÀD +5.ŒKãq-5zŒX›˜TkÔÚĜ4§mz‚5m<96ij4Iۓdú1ùãwî=÷<ßû¼ßýîûÔ/¸*×&~,×$~#Õ$…´Õýhªû¹¿€Ÿá…쁸heý¤3xÙÄ9[/ ˜‰­)ã°I?-†8¬7°Ö`Ás†l¡Ù' ý|Âzßeí—mìA6³G#¼îËäŒÉulI„–…£ð¼1kLsÐlJF£É„U&›à3-ꌡÖX,V—‹UÆZM¥±I[aÜ(•wÈc»Îm<©+1¾Vlú y¨+6…ä"SH"Úâø?ñ7©w‰Úgø‰íÌ:xÝÃu¼H?6š#°Æ<Mæ‰Xm‰Eƒ%õ–4ÔX2„EðZò„ +‹S,7{Ä2ó +Û¼Z[b~^*6o“]æýºBó‰°e–Ka–?’º‚ŒL¤KÚ^þÊZ¯eÝÔ}%Ÿs¾ƒ™“4¨Ž…k¬ah´EƒíIÔÙ¦¡Ú‡*›¶t”Û²m©Pj+Kl¥b‘Í«qÙ´…ÖµRu‹l·îÕåÛ:ÃòlÃsm¶/ÂÔ¬œkëCzÌÜ¿åÈužú]˸9Š¾D¶q-ë¹®Æl-ê³#Q£Œ…W™‚ +eʔ$¸#J”L¡HY"8»X¨‰Êr]©×æ+~)WÙ$/U~®ËQŽ‡)ʅpEy'<[ùœ÷!‘‰ô˜Û܃—YóÙöÁżÅ1t7Ùìžãº|üۊ¥ƒQ¡ŽB™Ru&ŠÕ¸ÔTª¡@Íjž¯:Å\µL£ª5ÚµIRԀ¼XÝ­ËR…YÕóäVx¦úO^¿×YՐL¤Çܢߗ¨ušúÇJÙû@¼o¤/ÕìK¹} Jí#PdŸ§c:–9âápè‘ïHGž#KPªãX&.q¸5َš,G£Öjo‘2ì;uûÙq.,Ýq3l‘ã>¯ßÉéöP/’ùÞÎá^ ÖÉà0GOÆ4l¯ä^\NèG×Vâ G¡3 +ÎñÈw>ƒ<×\¨®$丌Xâʲ]9Âb—C´¹JÄL—Wcq­Ò¦»6H&g›ltÒ¥¹^Õ¥º®“Ou©Îoå4gH꣰Ÿ+y|'‹˜{©ßáåûÀX²…¬[Ôrz²¬TB^i$ÔÒ1ÈqO‚➉ŞdyRaõXéÉ,ž|!ÝS$.òTˆFOƒ&ͽNkpo—RÜr²ûŒœä¹FîÉIîÿII¥¡>’KBÚ^Þ gŽSÿ@-ûÀH þz¸Š¹“¾dW BVåHX+' Ã; ï<˜½)XTe‚©Ê†…UªVU(¼ebŠ·NLò®Ñ,ðnÕÎ÷ÔÆ{OKqÞ«ä)®ò¿Ú¸Ê6®â'.ÒïSÔ8\Ç>¬âûÀ8²4’Ê•Ì] Ì\¥nÕ …±~ÖOFªo ¾è}©HñYäSès >·ï«çùšÅ¹¾ÍšÙ¾ýš™¾SšXß[äïšØúÿhbëBšØڟ8Çt²þöÕÀ®f`£ÈÚ5Ü ÄÃû|?`ãï ›4HnŒÄæ‘XÐ< ÍS1ß?ñþ$Ìó›0×oÃ.fù‹0Óïfø…iþ„©þ½â—8ÙYŒñßcš¿cž õ1¹±ŸÓìûQêï£Þöu@ËfύìC PD–3I&s[Â1«ef¶ŒÆŒ–hLoi­q˜ÚªÇ3­fL (˜(@L с<؈ =x*Ð)Œü†ô`|ËWÂø ¡~Ö÷óKúÝÁšwQ{s+=ØÔoÊ^ì[éÁ6 •Q1žLßLjˆ§Û¢0±m,&´MÂSÁX<ŒÇø`*Æ30–ìè`1Fkð³àZŒØنá;aXð"¢‚FԎG¶=„aÛÈ֐ÐËQêïeÝÛ©ÝBÍFêT'£¡²‡ùï%`Á^ võ÷ãˆÑ>ÃÛ£0¬} ¢Ú£1´}†tÌ'iˆì°á‰;w,Ç ŽF ì؂ˆö h?‹ðö[?øøûCˆØ×ÏAzdݛX§'Ï$ÆÁb꩹_f³1G©Þ Džqrº¢ ë¹+RW,´] »Lz?¾] „Ÿ ¾Æ|ûÚd8pa™D8vs éæ0ÐÍC¾›‡K77[7E.°˜ ̹Þç3_oI¨¬}ý^ÙÎ3™ÚvÖi=èEýW©ËG£ºA—ù €a…:-‰®Drâ:®Žå0ÈÁü‡Ãë‰À 3áGà_üløÝü]¿BèÅõGä»>Zé{#=¯`ݬ7‹º†óÔ§æ¤_£_†¼ DðQÍÛÔ¾Iþ@Þ!ïj€ÛáÀ{ƒ÷‡r ü‰aáCçя =üÞaOîpÃßaƒïÐȞߓ{¼ÔG{]EÏ Y÷bj§²ÖÙ¬5šµŽú{ÞßêÕ#´‘ᎄ|Däc‰ƒ1=¹GO>Üg`ù|C ýxÀóî/yØ=dOÒì‡4öá r·jÚãbíÊE í20ç*õ©;’ºƒoÓû¨ñ!ééÕ"\>Ã'uÈgä_äßäKòH¾üŸì2ŠêÊÂðÿÞkDTÅ} ** ¨‘EZ nèÆnh蚥YDQA@ ¸×B"2¸¡b¹M0š1ŽÆrRV&NÍRV¥œ8ff\*5qÜ¢o~T¨™êúêÝ÷ªúþçž{î=缤O~âÞÈldÚ!³H’™ˆåu„Á'3Àen²üù²ãDö·ãٍöÃ^ӉYD¢‰…d’åd©"õd3ÙAv“ý¤ƒt“Sä"ùoq?ÑØ×xWüò’¼ä?äßä" ÙÁƒ£~Æ Ú1‡ 1‘t’KŠÉ²žl¤F3Þ`'5Ú¨qsÆsçügñ#>£Æmjü O9zÂ<&È¿Ÿ?eg7ÈN®&ýÏqd™OTÄ@’¨•EꬤF5j8s#5¶P£…{8g;çìâVõà!}ñ×iÁ_2:¯¹2Ãèÿ‘G;C5²äÄ·QĝL%ïó_AԌÂ3Äs»Ó¨“CBj¬¢F%5j©ÑH-Ôø˜óíÅ_¹'ÆQîB/¾¦/îð}Å ºMËoqÖ~¾$7‡ » §/DÆÃÁc¸ øâ9}ñr]*|=¾c\| ur©QDUÔ¨¤F-5>¢ÆVÎßÊ9÷ãwèd4œÄo鋫¸Ë´°û”»wi0Z†"¡6¯;ٙ0¤eG'¼\©;‰kô¦æBü‰qñ5ŒÔJ¡N&gÍ£—‹p «y]Uâ +ê¨ÓDíÔhÃîÉ9ÆçYþÎВSœ¡G|ŒÒkwql˜Œ£Cyœe¥ç䑏¯›ÆãžäŽo$Oü^17Á¸æ Ã‡xô ³âÒ°,\pÌÇ9Çbœu,ǙáU85|zœ6ã„S Ž9íG÷ˆ#èqGF^ÁáQß Ãù1Ú]Þâ  sÔhž¤!ȓ¨ÏëíŸÓx吻|¿ã!â+Æȍ‘ãpÕy~ãâ‡ó.áè­Ç)×DœpMÃ1×lt»-C—[ :ÝÖà·jt¸mD»û6toÃ÷O°Ïã$öxô¡mÌ´Ž}„–qo°c<óÙ6„WL7OfRߛÚ7æ0L.OtÀ%wWôŽ†“ã|Ñ=^‰Î ‘蘋ö‰˜”}“–`老M.Å®ÉkÑ:¹-Sš°cJ ¶O9ˆ­S¢yêlžv Mï=D£ç+4xÊBý yÆ4óÀ—×𦠏Ïó¼îO3 ž˜: +]Ó& Ãs6L÷ÃÞ*욍gš°sf2¶Ï´a«×R4{b“Wš¼*ÑèU†Y[Q?kP7«S¨Ý+¬Ÿ}]¨žs_¨šó\¨ð–…uÿÃS^ë÷¨}‹)æ³Öù¼ZO.º˜†;¼±Žv{{bçûs±í%š}4hò1 Ñ' >VlðÍD­oj|‹Pí[Ž*ßõB¥o“°Î·UX3÷P>·G\=÷ªX6rޏbé|Y,y‡P<È÷\÷¨{-œ©]Í~‹t…±¾S²ï\ `ç*‚a­RƒÕJ=ʔñX©LA‰ÒŽ"e®°BY$,W– ˔µb¾r‹˜«Ü+-]Ô--YtIʾ#e?!²”,‹C¹Gÿ߈.1Õ÷0ÍvƲ×1-ZÖ¸´£.Ø UÁc°6Ä«C}PˆUŠT:ªŒ(P™±L•†y!E˜å_H”¥«Ü÷^ú¿‹šXòµäò<’jŽ‹éú#5Y‚%Ù É`JžcŠ/bS`H …Þ…ÅÖD[ÍÐZӅ(ëRAc-"¬Ub¸u“¨²î•B­Ç¤Ô+Rpê·R°õ9‘¥”_èã¾÷PëpûÞ|Þ l6’ +Ž iG}’dc͝> +1éc ÏxÑÞÐÙ@k[„H›Ûb¨íñˆ°[fÏBí+„û:q‘ý#1ÈÞ&.´•헥€Ì{R€ý™h“Å2Þq‘ë<–Í3IÍÝ+Øs±¨#kþËv™Ç×x¦aø>ÇY›=–Dö…lvBP&-~˜¶ª´Ú,È"d“’åˆ%‘ÄžåXƒÄVjI ¥5bÔ´Æc´1ÓZÚi«CƒªvZ3ß\‘Ìoü1\rç{ïçyÞ÷{Þçæólb™>Kz »4&ÞVqñ.ß]#‚4"!RÃhXâ0Å&>§¡‰“øŠ'ÎÔÀÄdӀĦ~‰ËM}’ªÌ½“ö˜£“Þ5G%]3G%>4G%æèVâÛhdö ³e®T‘Á>` + 3“³8ßE<ˆgTJÅ&;iHŠ§bRü48%LSûh@jŒú§ŽT¿´±ê›6Q}Ò¦+:m–¢Ò²‘¶ÄÔ+­ÂÔ3m—),í„)tîUShêShŠñ„°dÃÜÊAr¬Cc#º«±†Ë° Jsùùz®ô2“ƒ÷ãÿûgÚ©O–‹zguStV ¢²Â™Ý_Ù± +ώSÏì +˙¢ÐœçÌSPŽE9kåŸS+¿œcò͹,ßìûòÍ2L¾™†É/£·R¹ŸX¿ݲ|އB¼§…}€©0ß ƒ±ŒÑf…8*¤À]AÞ +, V@a¤ü ÂùZƨ‡e¢|,3ämIU7Ë"uµ¬”—e›<-ò°\”Ga‹<ó™XóÚð‚Ô|Ó"i z˗З–QƒbjP"M‚1+¤Xè aà·ÂFÝJÔµÔC]J}äU"ϲ(y” ’{ÙH¹•—kù«r)O’syŽž)/‘SÙf9–’CÙy9”~#ǒÇr*az.nc[5(¢XÒÅhda “Vñ>®‘ÆcËF®g øWàA+%×êŽr²:ÉÑê!«„ÈÞ-;kŒl­qêl}Q­3dcMW‡êÅ2UóP¦¶ +#[yðº†LëÛØ@î«Ñ^¾RÊE7­_Wá?7Hq›ØƒÍRÄ)`+ú5èo—kÍêTg/S·Î |!°Žadg,ŒÉ@£©ãPՑXÖâuw\ êöŸÁxº2îèÕìÚs­ìš/£õü)k¹S +܍>i¸ì“ޖlâoaHa1Œî~R=Ci}_šCP ¸æÛÀo Ðõ,^ÏÇÏÁ×<÷OXI½-äAÎ ÛèGhŽFoz‘<€^—Ã’s£dwT2GÿÝvNÇIâ8EïaÞg0?Ý:Ǚg +šhrMÙ@-šH¬‰Î| -ðßý·Š/‹:'‘ó´Ç†Ö£¦?¥ó†¿<ŕÖlíd˜løÔlÛëÑÍj֟œž%§ñhMFg&³õ…Ò9ÙäG–Eúq\#Ž«ªdÍÍú“êôGÐç(À+tƒŠ|Ç+e¨éÿ`؛ØŽ†Ô‡=ßvEÓÍHr‚Þsh½@¯¢ñ:sØét4²ÑÈC£ÕjQµN«Fïi-¤9­cä֋]DN£Èg:“Й¦CŠGaoA:»ŸƒN:KÑ(gÝJm§5¦½Úb>ªÍÎi£Í-mèøP՝ UÙª|ŠÇ´”û´ÚÊU¸Àçˆël';êà®c¿ðWCÇ(ìÅÊï±N‹zÔèMßýÊõ=©~W”íO™þ†2Àÿ|Íu{¹7WØéØ é?w1Ԅã¹ÍZßÃY«üº«Ô?TÅ}µ40VEq* §ü ‰Ê zM ƒf*7h–§+;8WYÁEÊY¥y!•²GsC+-ô¢)%ì®)¹§ašó_ÂÚ¸ŵ7+x(×û0flØ#Yiók¨ÍŠP- õ”%,@ù=#µ°× åö¡œ^£•þ+e„OÒüðiJWZxŠR#2•Qð¢Ë>ªéëŒãß_ê +h- ZåE%¼Hy!„@$ ’$µBТm«”´µõ… õ•«N»!´ÎZµ­Ò­Ç͵{œ¶ÛéÖÍ3ÏÚnÖu;í֞vNûZØñÏ!ü~Éý>÷¹Ï½÷û`͊àO= šS‰&ùÂ'¿,V¥Ý iw‰ô¹$þ àuLësŽ×쯸£ä0¯þ^5õù®K>[R£Ñ)G{Z +6¤g¡-=­é…X—aÁڌ +¬ÎpŸQ¦ ?|™mX•¹ ™Ï +oæ^áÉ:"ÜY§Dâ’X©ø\Ôfß!’¨U<ຒ¶ƒš§‹X´`ƒd?¯¹|ÖÍÜlΈö¬H´) E±k³Ó°:;Í9:ørLhÌ)GCN¼9uðäúàÎ]‡ºÜQ›Û-\Ê°¨QŠjåIY•ê¢Ì¡úTæP/*ITÇ80Œ´TfÚ?Ú¯>²§ØÎ8žb팣E5ªyhV-†O½ jêÕùð¨ Q§¶`ež®<œy ¨É[ƒêüváÈß&*ów »¦_Ø4#2«ö]Y¹ö&ùŽHâ4c¼O79÷‘rZM;렂—ìƱ™¹ ð½_3š9ðjâáÖ&c¥6.­N­Õ:ªtåpèªQ©÷À®÷æ_/¬ú'EYÁQZÐ'³ Ë̆wd%†ä["ÝG”Œñ+æà õ†¨?XÅu ;i¿ºøÿ& }6ó±Ê0î‚(ԁӰÕ9†lT4° +a+,…µ°åƕ(5ú`1„¹h‹(.z^˜ŠɊLC2£iTVhú#ù†H÷…Ec¼[LÛËy¿Bí~'°×ÅZ$[«ésùÜÏ8ܦIpšf¡Êƒ +ÓbØLËa5e¡¬XÒâXŠÍ0—ØQRâBqÉ*™[`4…Áüœ(0zËOd:Ëy™¶ôc™Öò/"É´fIèÆ¥ÆÉJžGÔ=L+ÞëžsÓë×Òë3ŒÃY&Pa‰€Õò0ÊJÂRš si:ŠK•0•éPTf‚±ÌŠÂòʽЗ?]y‡ÐXŸùÖ}"Ïz\¨loÉT¶È×Be•Æ(—„š¼me-Ðr¡þA/°{"Áz`-ãòò]c,³M‡Ùb{,ŠìKQhO…Áž‚Š|è+ŒÐU”A[Y…üJò*WC]Ù¥£[ä:öŠlÇ1¡pœYU×D–ã+~–„¢òg9þíæ ۀ}M¬Úð.¶G}\ÆáfN*KqõC0TGB_]Í"hj–!¿&y5*¨P9ÍP:+ëZ‰lW3® Ètu‰ W¯H«=*äµgDjíUòO!wIBî§F¯³Žsþ/QwÏZîÉǀ'Ɇ5ìyøÌÕ0½(ôȐ_µ{”î8云í‘CáÉA–G‹L õV¤×;‘V߈ÔúVxŸÂ2oR¼/#Ù{Z$y¯ Éû¥Hª—D’GÉ÷qKâUÎó(爺=®C÷$ ðs[‚*Æe^ èO¶o*2}QH÷ÍGZÓ"țRÚ”M*,o6`Y³ÉÍUHjö"Ñ¿Kü[ð¨'ûà?……þ÷Ém$4ßCB“„Ÿ$‘!Îsúû×;Ú¹›¸'ÉZ¶gîÇ[#cR3¦ôÖ Hi‰@RË$¶Äbië,i]G[XܪÁ¢€ ;âuˆ ¬Fl  Û1¿­1m¯anÛ%Ì Ü¼Öÿ"¦EB̺1Žqž}Ôéíà~ØÌux‚ë@šˆs `á3]9 Ë;Ùv<„¸ŽYˆíœ‹G:ã± 3ó;åˆéÌż -˜¬Áì ÑÁÇ !2x³‚ؼˆ™ŸcfÇ0kÝó}6Jøõ÷sül»·Oó\ê<ÄNŒDIäd ‰%sº§"*‰ÈÐ\™¡$’ŽˆŠ1#dÇôSC-˜ڊɡ=˜Ô}ºÏcâӟ¯1©KÂämcôqž½[™ƒï‡g¶í<؎Uï`ì4»€ ’Hâv³íf…'`Zï LîÂÄp &„ Â4Baö—½¼ü{yù„¹©Ã,¢0æ`=ìïzÞàæ¿ +ìbc¸ë'.ýÀ¾.þ¡v7u7RÇj÷ð#%L-[Jଓ¯¦ßpm¾c£r‡ù¸«î±6îñ0”¸%&^ââJïËìö¢I$‰"³É|’Hÿ£ºLÀš¾Ï8þxË¥^È©œI @’„@ ‚\*""^ ¦bÅ2T@©W=j­ó>gm©­t´³]í3ë6»v[Ÿéö´«N»ÖvݦsýïËñTûø|ž?Dò~¿ïû;þïK ÄNŠH©#«H3i#ϑm¤—ì%‡È1|ÏIð1çÌG,ÜCšý¾å¤ÉyŠ|G»ä3ò—Áy~Äg_2•„)ѐ,’OÊÈ"ƯgüFü—óåCldüÆïbüçñOì£ÚajœÄWœL¿Äîá#–è>îð[_0Âçäoä6ù¹9äaOƒ #5 &±$…dP/—:jTàι_¡ñ›¹•ñ72~ãw1þN.Ï~æv·p–Ëö:þˆkø˜ߤËß0ڍ>$÷†®É%œ¦‹×q®Î±Rg¹r§©rŠœaðgaô°ö¿·ôÈ¿oj²^ԓ2Ÿ4j™˜‹…ŒZŠ×èã}\¤ ôqŽ>ÎÐÇ)tâvpgîÇÏp/ó/^â·_ğYop€jûGØ7‚0Žú¼êîò8ÝâÕû=]ÇæèO͙xÑԓ3’ç‘I<î87+]J…j®übfÜ@Fê´Rcãnã)Ù͇¹CÎòÔ\ÁvîV¸›{³kð4‰žðWÊßy”? äõC~9èç•wyÔDîì)ŒBÍ8ê%3¢Ž§/ DìåÆÞQ¥ØíU^µèõjÀöÑMè½]c:°uÌtŽ=ˆŽ±'±yÜe´ÿ›&ÞÃÆIÑæ-`ÃS< îm^i¿æõ:À«¾?_˜Æ× ¯Ýã|px\LˆÄމR윤B¯·=ÞVtù8°ÕǃNŸ2tøTã9Ÿ%h÷]g}›±Ñw6øvcß>´úG‹šý¯cíäûhš" ‘¬x^Q¼Žy­ö‘³1À±H௸}^ØåçÿYØ:9?"Çæ56±qj66LubÝTZ§ÎGKàB<¸kW£)hVubå´]X1í¦¿‚eÓßGýŒ;¨›ùKf ?â6õ¯Iø:’çÔçóE1g ~ÞÊsš7Ú§¡mFÖÍ£eV +ž™•Ž5Áf4ç`Up>VÌ.ÆòÙX6»õ!ËQҌ%!íXº5¡‡°0ì<„_Euøg¨Šx„ÊáG|L½w’ø +æ«öd*g>÷° éIàÌǚl–°)X>«#¢±"B††ÈTÔGP™…ÚÈ\,žSˆEsæaáœjTÏ­CÕÜFTÎmCyTæG@Yô̋ ·QûoÇ +Oˆá}Åö«ŸÚ؂Õ±Õ!½|Õu² iKdŸ煕Q~X=u1‘¨cQl2ÆjPkDeœ qN̏ó ,®¥ñ‹Q¿Å⟠H¼nÉ (”œDô +ò¥ŸÂ•ðà’>áµ.SÿLç ¶>{H·h§%°’kS'öF$ $¡¨”Æ \*C™4¥ z”$d¢(ÁOB܉¥(L\€|Ù2¸dÍpÊ:àïF®ü8ìŠ7`Oú9IßaÅ0ï²Íx•ú'29g°ÝI¶°ýiãgk譞>È' B>eò`”Èç¢H![‘ŒB…ùIF¸’lp&9áH*F^r%ìÉK‘“²Ù)í°)w"KyUŸÈ¢ú(Sõ€ƒ`¥€¾Únæ:ظv`é`볎>VÑG-}”+Ç¢$Ååt(#àRÆÁ¡”#O• +»J•Ùª\ØRÝ°¦–#+­–´F˜ÕϤî…QsD”¡yUdÐÞ _AdÐüú©sŽ¹¿Ì6x¯ƒëàä:ðْÃ>Ÿµá‡í(¨}áT"O +»:ÙêX5)°h´Ä„Lm6ÌÚ˜ÒKaL¯A†nôº6ètۑ®? ­þ’Hc¸NþA‘F?ŒV'ˆ.³§©÷µw°ý/äÌÉçZþ¾”õ¨d=Üô‘§÷FŽ.V}0,ú9ÈԋaÒ+`Ô§!ЃÁ +}†ºŒ¤Bk\µq=ÒLÝH5‚Ê|Q¤4@îA¤4 "Õ F¯±'˜÷Aj?ÏxK1Ï#ŸMQóó2úËÏâÌgž€LÓd˜L3aŠ€Á Y†t³ +Z³šL ԙyH³!ÕRUÖ2¤dµ"9k’¬¡°^€Üú>dÖ{|~y–0„‚¼BcÌ{?µwp$é(ã^ «J¸ô5Ïřë”i½ÕéÖ h­!PÛ¢f“"Ֆ U¶ÊlR²íHÊqC‘SyÎRÈìÍH´oÔ¾’Üsç¾GîBlÿ$v’œaÎ3×#Ì{/u»+9ïTq/𹼜ýþ<ö»ü¿\z1:EPçyC•€”¼YH΋D’# +‡rGdŽ $:m:ó!q•AìªE¼k-b]ˆÉÑùg••|A#Ú% Ú9ÌiÆ?ÄüwQ{Û"î…î>ë9*VÐK!G½èè%Ù=²B$º§Aê…Ä ±;ñžÄyÒë± Æã@TQ æÕ`NQ#"‹7#¼xŠO!´ømò9B‹!¬H@˜‡+9Κ ~/µ;9­_ +4’ÿs]æQQXWþe‘ueߑEã=Ä-—º¢ˆfQ¶(̸ â`T 0q×8Q£U bÕ¦­AÁlVMM“`L›6{bÝCRc4ÖhÜú±äÄöoö¹¿wï»ï¾{ xmÌcîb-£×fJ½M”`ôP¼ÑW±Æ`Ř¢ÕՔ hSE™(Ò4\ãž‘¦°Œl…dZœ¹R™[¹_þ™Çå—yEþ`¢ƒoÁجloCk£i…Y²Î§6BŽ…}à3¶UÃXOÿ|)‘uFç¸(<ÇK¡9]’ªàœå$*0·Ÿr‡È?w´ürSÕ%/C¾y…òÉ{IÞy›dÈ«•WÞ{òÌ»$Cî2ä0MÌicvíEÒF±•ÅìC û™Œ©©¼µð]oÖǺÂÀÏì*_³üåc—·%NËӐ$OËó,ËL¹[òåf)•«e­\,{äd©—“ù39›oÉ¥ˆ.¾°×Ñ߸Hª\Ây`[¸ŒÀt˜CËÈHà»HokG¹[ÝåjõV'k \¬‘r¶v““µ:Z«ƒu´¬$š•M´â„µ’Dß °¥\„ßÀC “-i–×`·|91†Í]%™^&*¤‘üõYH„hð¨r“ÍU6/É֙ 4>6— ¢V•ÜvЫæÁ +œdά<Ȇ3D¾Ü$­ºÍ­lÀ×J´—aÛb“²WS×2®—m”zAWڄþfô_•œ0'»Ðxn¡é³ÓÚií]¡'Ð Ø)ôvba'©ílî–uPC!d Ý|îRš[Y¿å¯pÐÍÝÀ 1þ5Îâ6©Ïv)–ñ4˜0úì”ÜwIw£ÿ¨všòjÖQÍ:jXG àÞ.@ Z.ÿZŠ}-»–äÞK€÷b¬¦Žßÿnaç14«íü,À·tt“цN_tb«ÑßËþï“\÷K„’æžKþø3Ž4@ o²/uìËaöåñh j !j 6pøˆENÖc¨þ$\bqä'-%¾ó¶r?£= Ýçk¥gøY,zAèÐëô&Z‡¡ÞÂÉÈ@ÖÎq†µ.ÒI†…¥XÇÇ4iÃ=9]lúi‚Úx„ç3ðo¸'3áÉÚ#MF{ºýñ-Í ~FK.çwÚuNéЇv>QË@$M1p2 uÎ1(}ÁÞ\®°Ž«4§×¸ô¾¤7qț|Ám‘¦¿3Ø}¥lÒdêêÚIèÆ¿…>_{—[4ÿÒ®÷)üÎÁyøWëP(]†«ð%| ×á[òõ6ÃÓ]?é>ùñ€FùÍÑCÎê#ác6þ1¢qðÇF¦./ðlÇ~ ½`0Œ)`‚(„b°ÂJ°ÁzØ¢Ÿ˜ò~dÂ|ÄÔùiôsæú‚Yö;}Ï/îÀà\óp¶eÞd¾¥Z ¸‚„AwH‚0¦£‘Å´˜}³îk1öË°_Ž}¶×ë¶ìºÅÄù-Óî ÷:‰ó5ÖÄã5þuµ]û|g ±u Nà‚Žíñ„|êƒOCЃ©x“®›Ì¹7T€} –c¿ ûåضa{ƒ.0éž×.ýSûññ0“îŸI— èÝÑév͏áC8 ÇZ× ÿá‘ÜðÍŸ"ð§ZIúJÃña/`߈ýÙøñ"ihÁ~1ö­Ø/Ƕ Ûõ¶¡\M¿¡?éŽÐ§<~£·ˆb*-ÔÃa8ôk¸7刦©ÈNÆ Õ­AèŒBc")š†}ögc¿ûfìcߪ£¬£^¯¨N›±½ƒÝØÇ*êȎSDå2ï½Pó-ÚT+ünKëK­éï†_¾è…¯´ú±³Ï¡1šL›„Õ4ʓI¿g¿#?ªEhX±¿Š¬Ñrc;YÅvþ½O^ÃÖÌ}µ5ƒá1%÷;JÝUÊîç<Ÿf §È‹cäÅQù£?=ÑIBg~ŒE#ëihÑÈæ4ä£S„N1ÊehTh¹±oÖ±²5­ÑùHUD¸’ÓR‰nÅ|O¹¿FIùåí”7åc]OÉ;Ä99(o4ƒÑ‹Õ¯Ù“í€ÎpÖ>–h§°óiœ#:Ùèä£cFg1v—Õœ\;¯ªµ keìàÒ§.«´Ã]•:6k ”8µqÝW:DyåÚ{›+çeöŸÕPvw9º“]Ñ ×Ƨºim‡¾ZÝqªG¨ÂiœV9¥h¥sšV8õ’s¶Ê\ +´Ôe¾J]¬*éT¡âN›´Ðu·¸þA·2»_T‘Ç=z6kÞ\F·‘«ÿÝXôᷔ×Ýaôw”Ú͆§´ÎÍSUnþZå¥=´Ì£Ÿ¬žƒUê9R%žã´Ø3E‹¼¦i—IÙ …*4,Ö\ÃJ½hX¯|ïÊó~C9>Ç5Çç¢fûÞSvçæVfµsÍ÷¸¾¸öpåîN”¶ÆÓ_Fъp®ôuQ™·–ø„¨Ø7N :÷’¥s’Šº<§y]Fin—ñ*ðKUžßtåúeiŽ_¾fûÏ×,ÿeÊ +X­Œ€m2îWzà»J:§Áw4#„Š÷Ÿ ÿ^o®c®–Z ×Ÿ¡­à½­»´‚R¿$´ƒxª(0@sƒ¢”Ü]¹Á}5'd f‡ Ó¬ÐÑÊ MVFèTCӕ6[3à +5=|‰¦…Wê…»¦FÔjJäQ¥F~¦ÉQ·59º¹¨6>Ä÷£h@ h;ì™3¸bʹvK‰É|ö§ Â]9¾ÊŽ UVd¬2¢ž–1ª¿fF ֌èš=ViÑ)š=MSºf)µkRbŠ5)¦\c7+9®ZããŽh|ü‹¿©qݚyþ…÷ñ»Ý}´;†ƒ¡Ä`síØ¢¾ô—¬#;ÎE¦Xo¥Çjz\”Òâºkj|M‰V“ã‡*%~”&u› änS5¡›Qãr5.aÆt_®ÑÝ7èW=öhTbF&6jdÏѳ¹•‘‰mû/×åu™Æñ¯—T@T@Så¢Èý2à 0 È]`H°ä²¨1¨ `yä ^ÖK$ëZf*h¹YÞ)=æZֶɶ—vÝ:¶µk%Ö´Ü“›®Š¥³Ÿ€ÝãÙ?>ç÷ƒ™yžç}žç}ßç˚á£ÆŽLô¬ã}%q4Çbb\9\ö0Í ó‘-Ü_EáÓU¥‚ˆåG$+7ªœˆ\eGڔY®ÙQ5ʌª—5ºEéÑíJ‹éTjl·,±ïÉ÷5ÜãÝù?N“ÿÃøܛEr˜±a #NJ æ+âø q”‡-z´ +£Ç)?z²r£ƒ”¦¬˜X͎1*#&UÖØ,¥Ç*-ήԸjYâ—Ê¿R)†ÍJNØ¥¤„£2%öȘx~àÝ)SÂ'ÉýFàNÆÏmŒ›É[ó©q8ˆ­’8æGÁE9ñ^Ê2LT¦aª¬†J3D)Ր KBŠÌ ™JI,Prâ\%ͪ”iVŒÆ'4˸Q‰¦2˜ːô®â“.Á÷¼;ùßÇñ³?—^À÷Öb¤€9Ÿ1ô1âA¶éaòa£VÙ¦Ê0ŽQšÑG£ŸÌÆ%#”dŠ—É”$cRºf%å*1¹D ɏȐR«ø”fř¦óE[*Êò| wø›)É<@75؇¿øÞÂè¹~²ˆgא2jSHd¦“Åì®dó8™Ì“d4*Ñ£Àì‹åyS~ùNùC@žSûKèüoÅ÷Æޖt/ÏÚ*zXlȤ,bI&–XÛPÍ,­é…cR4QÁE +*š¡À¢(M+NÔÔâTçÈÏV¢)¶ +M¶-Ճ%«4±¤CJöɧ䔼K>áyC¾6§&35‹äÿ¹JzY¸îQ΅Zz-¦ˆ§€X҉oyaë+Ø>J¥ò+¯)¥“5Ù¨Iö0=hÓD{²&Ø3åSV$ï²ù_V«qåOjly»¼Ê÷ʳü¤<ÊÏ˳ì:8åe  ûÏ,â\¨ã~Zʹ€4\öS©š÷¹H£lâ2óy1†’Ÿ€ª!šPé&ïJO¯ôÕ¸J?­ HyU%ʳ*UcªòäQe—{Õ"®n’[õF¹Ví–KÕ«UõøF.•wåZá”ìÄþVümh È ÆF΅ǩï…ËéÅzr@LÄ´ýI¬ãê†ËÃ1Zí˜(7ÇT¹:BåâˆÕ(G²FÖe遺 ¯«ÒÐ: ;л¥ñXÛ_ÁméQg?Ûñߎ¿µÍÔáI©~%g#Ìã=Ržb«Óù|J“ä cš†Ê¥ÉUÛйMÞÀÒÄÐ\€\<l¨F +ØHà-4Âöñ—9xp!̖ßbhpj+ëވ¯V¾ÖÔJx«¥ùmÒH25”§?ÿ÷F¹ÂÐ5  m [m €m¾ÀàÓÆ%ÛÆEÜÆ%ØÆfn£‘WSÄÕ,b5:³õ.Ã_B±å†´ÊÙO;òo-¶W’®eë9›7°6q&m–ŒOIá0|Á3.Oã ƒoúv‹ 0€naí`ðêð‡ .þ×6tÇ#|NA·¬“žÞ¯‘øs4à5ƒ{àÔ|·âw9>kð1¯ƒ>$mIÈÒÈg¥iໝüSÎQ;ð½vÿâØM»ÉG'ùè$]ÄÑÊ0ÂP´‡‹`ÏC@ÓuQàN wäûôÄî+ +}àÔ|7²¶Å[ًøËÃO +áFwJ]øß#yÂ‘ûðùPR¸ƒˆƒƒÔåúaô#> eÔ¥›8º º¹tºÙÔÝ4v7‹íÆà1êq”zýîjÅÏiW|?ü-/҃ø +܏ÿWðOØÁ×1xNÀÉA^‡S€I½ANÞ$'g¨ÍÛãR‰ã,áY†ƒú³§h¼žmÀþèyÏþ×µ„u/`ͅ¬35Æb¥ÿº%÷ãÒ°“ƒ>ÞZ™ÀïÁ ҅Á\âèOpn„ô!µùp8>cûœá"5éec÷Ò½,¶ý†KªÜK²f+¡Å³Î`ÖéËÚÜߐ†¼…ÍßÀoá÷ÀOô!|…¿Áøz-§Kp…ú\uCÀÑ«×é É7Rn±Wosøܦ©ûHv‰¼ý;”–;¸ âãÀÂÁ™PeP h€fhµ(ÈMº‹²ûEyEև¾»…¶º‰bü7:󺮢gïéßþ‘Kp>€÷û5ïHCaxÂ$˜q`\,<¤ïÑu}èÜ[ªÃörl¯ÐwÄq8¾%Ž¢þ®¢Ì¾F^F)^Bg~I¿ AùÕgXú>?ÂYøu º!ƒyñaMÓðÉZŒøÊÄÇì—êŠ`{!¶—`{9¶›)E ¶×êïh̏Q»çÙÀh¥;Ê:ÏÐ.çi›o‰fÀï»p^‡ÿ'Ѻ7/}£ÉúJ3ðG©ÍøÈÆ~1í`×9UÐ~ YKmÒ@k6Ó¢?ªÚµzGOѺÛðÑ©ÓläSäâ$ß8Aä¯Q©n<ä¼r_ wà_pYÃX›;þ|ôrñ¾"𓈏4ìçê-ÙØ"el• +Ö±ûì×c¿ û«Xù:V;•ØŽý½tÆý’ˆ^Àâ*ׅ·ÎûØ5·ëhíú·š 9óÂß$Ö‚Ÿ— V,æa߆};öplՐõZ|Ô㣠»-Ø]¯çéÑç¨É³|k¹øÓÕÓæyF„;lÌݘ؀±m°°¹Ù@°an_€L áb ’…Ê-÷¤Mš&kš¶k«^¢5´SWU•v‘¶6Ò¤jšTišViÓ¤®Ý´n«¶UßNCÔíÇÑû}ï>ç}žç}.Wy’Ëôä%zù"Y/ç¯_{•ÂO™b> +Û»þï3>wi‹·J>EOOUE79¼ä𓣛}¸Ž!\£Ž+Ôq‰~¹€FÆ6¶øeƒÿõ­³Êè;K ¯0š—Éûÿø"ŽWœ©íÒ½÷€×úMêy…÷åޑÛÈ`¤ç‘ËHžRžÅÅsxx/YÚ±É8]§Ž§¨c•~9ËøXÆze TtšŠç™ÔOÒ¢³ø„QüB|„éÇøŒ¥æc–š29w¯²xzž£¶°8ž-™çRðLò˜ÉSγ¸hqy¼äi'Ooi=ÄlØfÂf1¾ŒÉðsß÷ Æö½„cï`4ò!F¢?Çјop4VÄðcü:‹öW»y,=Äó|¾¡`oŔ>1 ëѬD¤`1*§£u˜‹±`6Ǝ™ØjLÅzŠóa"Ώñ¸nÀhüFâ§0œpC L¸ŽÃ’{ì¢_ò‡ÿŒCI"éÿð±šå†%ÿM–—{ÄM–»«l‰¶˜bŸdK° ‹ÄII¦%é˜LTc,QcI%‘:0,­APڀ!i ŽH;0 ëE¿l‡dcdsèI^EwòUtÊïâ ümä¿DGÊçð§Šð§‰{+ñ3òïšè¶wˆëLíçYfV €3Ô7C;Éã1"—#˜’#) ¤¡/ՆC©•ÒêГքî´6t¦wâ`z?:ÒGàϘÁ÷2–Ñ–y­YwàËz ^Åω?¡9ûBü’ï¾ x±œ6`¹¿ÌuƒïKlÉfi“qú'˜þL)„¬ ô(ÔèRâ Â‚@v9üÙN´g»Ñ¦ô¢UéG‹²ޜ!4çLâÀþE4î?‡Õ-xÔoÀ­þ êsÿ@ü‡¿Ãyö×Éý<ËüŽ‹m–“6¨à¼Ç6(dᜡgmÏG—J‚€*í*%ÚÔ´ªð©­ðæVà@n šrјۊ†¼.¸ó£> uù§Q«ÙDµö\Ú×à,øø NÝ¿‘Ï{x—mð«ä½Íÿt°M¬°œc[:ÎoƒÔÑCíšx´hdðj2q@£F£VÖ ·¶ õZ'ê +ܨ-ð¢Z€K×gá1TΡR¿‡avÃ+(7~@üŽøšÁN<à™_&ÿ-7p…%~ƒXâó îRÇudŒø Ñh,L‚GŸ†z}jõTëp¬p¨2Ô¢Ò؄ +c;E즣(3@©y6óuX-/£Äò>Š‹Kü%Å"ßY™‰û´ÿ=rÞ`Ûw©™ó±p€s†¦:üÔÑT:“Õ&9œ&*M¹p˜ a7›Qn.C™Å…RKlÅm°÷ ¤$ˆâ’iX¬ga¶]ƒÉöŒ¥ïŸGQ©ˆ"›È}op¹Kþcmß*qš-ù$µ RG7u´2V<ŒU§5« åÖ ”Y÷ÃfÕÂj-B‰Í†b[,¥n˜K}0•u¢¨lÆò åËÐÛ¯@g¿‡Ǐ uü†ëWÐ9Dî‰($^#Ï/c¡­¾Ÿ£H0Ïuœï´G'}ãcŒÔ1fìöØìI(±§¢Ø®„Ùž“Ý€"G Œ µÐW4£°2]å +ª& ©ZB¾óòœw‘ë|j×'Äßø,r¨ñò‹P֊ü&âEÚý&ù.wëã‘mç ×¾ l…Ûi“&úÇIßX9¾éëã¡­—BSŸ†üúä¹5Èu¡vÛ òT!ÇãÒӆì†^(F‘Ùp +ÛHo¼´Æ"¥é!R¿ä³ˆô†=Ü%Çù.p$[;ÌÜx„ñÈu¸Ÿw’£I¿¹©Åј©E덂ª99Ír(›³Ý¬†Â«C–ׂL¯éÞ:¤ù|Hõu!Å7 yËI$·lBÖr ҖûHlýI-_ðY„Ì·‡Û´ýÓä?7¸7žÎs,› †‚Œêi¦–jÚ¥”Z ôQn Yþ8¤ù¥Hõ§!ů„ÜŸd¿2¿pAÚф¤Ž;! Ì !°†øÀ3ˆ ¼Ž˜ÀO¹þqÿF¼_|„gÉ…|›£ÀAfÇYˆã¼“#¼üVA}ÚFK=Jþ}ª io{eD$‚ + Bâ ℠+Ä +D íˆú!L`Ÿ°‚0ó•À!Jà Ôû{âëe7ß#b‡ɽ6ɼ0ÅX˜a,LÓ|öq¯†zJù] PSSm$;†„á8D'!b8û‚ +„¿-,F‚I>È d0éÌ ÿ1Èy7ȹfˆÃÜÐ{¼ôœ5¿"ØIq[ä\9 œš§N‡¹úç€î98™ˆÐ|¸§á_%~ ‡/ .Ë) ._ì»ï‘\Zá!„,8 ]àu'0ÅòÃB(5w•N““ æ§FO3˜žæœœ¡>ÏÐdÎPØgôÙÝ<ÏòY Å]ÕÏqpÀÇ8­ð…Ãç{þÃNž‡Ç!dù†çÔ¹‘^Z±Ø>\Ò¤‹Ää}jäCtü‰Áôrºt…œ\åŒ\¥È¯èk¿Æ®µ©¿KàÎÝÇ8DÄ??8{=ä<éä<çäé°Þwâçrx\Ÿ€OÁ êõ&5òy¹Í v‡áìîh©} øÚqºàµÿŠ-Ç t=€ð!À’À P Fƒj0ÌìؔþÍfó/¶ìTÿd»»ÏVù [Ù=¶ÏvÐ]Ð׿­¿éK¾u‹_}®ƒKà7à펝ץcïí„+ð XA¦¾S¥Ø‹íZÝQvgê+tÜBÇèøœ-ìïl€7Ø?c¿kÓn¸Žèc’ögþ®òËËXû¼ëä>NthÐàŽo¾ð…ò+|Éø‹ýáú+{n›* ÷Â^§k踂Ž?¢ãt\BÇ{l†Ùu¯mø¹29®wttÞÔ"w†7Á1pü†ûày¹©ÞðâG\VxÒõå¡¿ۏa» +Û°]‡íx:Û ðk %´ß^ÖÏi opÂtDoq¤>!;ßp¼(cv;Áöïiø¸ ®w”™|¾ú-±8¯8,ØáÈÆ~>^À‡rlWa»†©Ø¯Çþ°¿@­Zª=ZAÛXÇf8Zµ•_m&:-D´¶`ƒkÁwp~ >s–÷…ŽãÖŸzãK?¸"à‰'f)XËÁ~v¡cñØN^¶©F[4E›ÐтŽ&tlÐ2­£™¯!'«ùæ*,4±2ù"Ñ^ï÷qÎ6çQ{œr¶›×¨‹½ê_\1øa…#b¹€P Gcᨆc2¬õpÌÁîӜ”çõŸ.EÝÔÿ˜(>£©œ;ÀÒÿáFø¹vÎÑfó|ö¤únüÚ Ÿüá3a#<àH‡#Ž8Šñ¸ ž +-FÇ"tðÃ)¶Ír±k†K†¦wÉÕ´®ªëZ¬)®ešìZ©‰®TÛmºjºÍÕøîKUÕ}•*{lVEσÓó¬F»]W¹û=àx„óð‹æú2²÷‚u¼ndy>˜ÑƒøÌóêªÙnžšÞÓOuný5¥W´&õ²h‚{’jÜ3T힫qCUå1Bc=ÊUá9^£=§¨Üó •y.R©×J•xµh¤×÷~KÅÞm*ò¾*òqt¥éS¡â>TÔg††õY¨Bß*ðݨ|¿V ñ{Syþ+¯ï·Àñ¿0w^óÛ¿ÖsÍ6ò|–ÿš;ÇÃ:rTè¢ +?O•ûùj”_°Jü#5Òߤbÿ*ꛪa}sTØwˆ†+? \Cª•×ošõ›§ÜÀç50h²ƒv++ø¤2ƒ¯*3䞲Bð#èÞêëu £èŠ j€ýv®}˜Läê­$7£‚ÝTè­áA* 2¨ (FùÁåÛ588CƒB)7¤P9!¥Êî_©¬Ð)Ê £tÃ2¥1Œ¥†íRJØq%‡ڕáàéP +x¿wÁۜC¸^_‹²•§¡£åÔIqD7¼”gðÓ C°"”§ì°De†¥(#<[éáùJ‹¡Ôˆ +¥DNRRälÙ£–ȵZ¢wÈ}L֘Kàp(щCpí€Ã`é¥<é9°ñk6£àd>«²FÃB£‹r£<”é£Ì¨~J2(-*F)QñJŽ¶+):Cö˜Á²Å ׀Ør%ÆÖÊjœ©ã"ÅÇ­’Ù´]&ÓÏgzWqæÛ2™üïà}‡àó6ø×1¯däZžÊ§yo":*Ð1CБç¦T£·’þ²Cd3F*Ñ'k\¢¬¦T%˜Êb.T¼¹Læøj™âëe´<­XK£b¶*:ᨢ¬À—Š¶::“àP+±ßç«Ã½‹¨Ö£yé´Ô £EÔÊ r–fí.›ÅS‰_%Xe±„Él‰•)!Aq Ɋ³fËh-Plb‰¢Ç)jÀ㊰@¶…Û¶È`?¢PûïÀ-^;Âmí&ö-ð¿Â¸·¼„õ¤”zäù8ZÆ›2>†ÎÔkJJ%ؾý¾ÿóÿïó¾ïÿQ·ÑC”|¼`jK0­ó~Ïa||ø}ÚXÉz¨fžäŒXŽd/“,`0èÉo—JfJ€jü_5µ¨¦«¦ «¦é¨î ØT«¨E‹© +ÁWQÌ%+@3‚ÃT.¤Vބð;@_Küڕ|VKš«ÙH× Ò˜ƒF©7×D`aÀÐLr¸µ_hvÈ£<È£<iÄ™“F¼F6·w‚¯§Àõ›h Ðes-ô*Í*Ÿêë¨1Ë×2eXÑI˜ä3b3IÀüsøm2þƒÀQð"@òz­cn^‘N°VN “èó$‡À)ÀI&ñOœâþ/\¿T Üyp‡×²Ÿ½° ~ †é„éàhÿ +x ð©Nwà 8 ^oÜ7hð:9Ϛ¹ˆQ¸L3xm\á¼Ê|pZ¼÷+À×>VÁ4÷XÆ9Înpšá 9ö癎·Ë +ãûÀ%p¼˜b]7ÀÇàïäñ9õ¸Eƒ|›Fäkõ.›ß=tq‚ߣp_¼‰Ë ~ @èz! 8Àd +ñ¨%8¥b&qOêœÖ×,”¯´ ï¸7·G÷˜¼;¸Õ[çs}„»úF7Û}ø#8Þ¿>ÒýoD€XÐô׏xÌo•Çb绀ØEÄ.!î}FŸ’Ç'äñW\àG¸Â8Ä?#Öëˆç} +y 7{•//ñx§ƒû8xéÿäðƒBõ/üÝ?”¨»xÝÛxÌÏd!¾]Ê¥?ÉÃ8 +ôò¸J—q‘q`ïâ2ϓÇ9­cʚô¦v鷈ùuXÎðßi²<©ï˜^Ÿ^GÁó õ¡~_[ÌÍ'22–8}@-®á1/iñ­äï š›zˆ]@ì"bÏ#v9±1®¥:¦:fà)dÜ̲ù%•8 ×)=‡`ÚÙAØ€}`7x¦#vL*%¸Èêºx[f¸áéE„Aä>š¥‘Nìlb»‰=•èӉïeæç2žùįÔ~òxV«aßÈv²];aÜA-¶±…Š63Ú§am›ÁFÀn‰fÄü±”:–ÖiôyŒZ¥G”ÌúÂ1”øc´W6—ÍÜÄÏ!~>ñg¡Äbâ—»E,C ÚÀÆú™¬%ÛF¢Ö3“«QV¼µXnÁù8×±wl=‡¨Å>tñ ÖÈ3ê¡mÌI³†Á‘Bþ6òwh=úX§)päÁ1Žb8æ{±Vò·œ –òe5µ¨¢Š‹YЕ(¬އq#ˆ%ÆØYÊ/²Õ>ø`ëݍ.¶²F¶(†ñ$ÁÕ žp< +G + 68¬§jÈ£ZÓ´„<‘Gëå ž”“UJ©\ #›‹J‹õ7Ía¥Í{6h¿^b{?Ëvö[É!®{8v¶‘϶ºõ +!J$õŠ£ºÉDí Ï@Æ2Ž-DåÊ‚Ç ÏxòP¨žâW²“¬`–Ök•,@9ùÌGó‘§Y?À[ñԟöã0GÌ^ŽÝméí8rÖК¬¢.5~aŒÍ_\Ýô¸ú0žAð ‡ÇO:¬YTÀ W*NüÙÄ.gõÔðd ÙmÕ$¿VMô{Mnÿ+rޓ+È÷ÎÂ}´GXo|/ØÂýž­ìDëA]ýU¡9fyý;kfÀÏTØWùƒ5-h„rƒ,šlSN°C“ƒÝšâ‘;d–\¡%šºXã «•mh–#ì€ìaǕ~I™wõ˜Ñw™à[ùá~É8êÁŽÛ:ZÚ²…´Eó¨‰7*HùáFyÂb”ž¤Éá=41¢Ÿ\ƒåŒ© ÆT3f(Û8NYÆɲGNWfd±2"+”Y«´¨&YMû•j:.‹é²,æ/€ï>RÁ+ð·Ñ†îâhkk‡â÷Ònт”Ò–Q“|æk²9TÎ(“Æ›â•mêª,S/ÙMýõ˜y¨2Ì£d3[•n¶ËíÒØè\¥F)%fÆĬШØÍ»W#â^Öð¸wõhü ÷ý„8Þ÷ӂî%mâh«§õYÊÿ y>—šÌ NSiœ•kTFì¿Ù.¨¨Ï+Š_£‚Šl#Û 0 3Àΰƒl +(0.£D4DÃwq©;hc¬¨9©&Ù¬i’&VLlkšXS£i›&=iÏñ´Zcܲµ‰UÓtúœÛÓÎ=ÌÿÏðÞ}ï»ß÷½kPqˆQE! µ«0Ô©‚Ð,å…å+7l´F„SNx¥²Ãë”1WÆUJ3nUª©K)¦ƒrFž7äŒr+%ò.^¦önrïÆÓn-dÀòìóŒÿä߂Y?=N‘¸Ð#£_<&0Š–Ò§z’ÎÚØsú+&ÃOQAŠÌ•1#RV…g&),3]¡Yù +É*Õ°¬I2dÏPpö<å´(0§C9ûå?â(8/ÿœ›<39‚§ÈÓAþMØÓÖª»ÖlîTi&ÏSy?žžŒæ;¹pM¡gqô$*ÂrškPHn„†åÅȐ— à¼åP`~‰òÇË¿ ̖¦qHA»>+ßÂ#àC *üBƒ ܼgŽ¡ÞíŒþ«9›¦£G0»ÏÅs%\*èË(¾“E¯’Y³XÖ'btŠýT¤€¢P%ÿb›†—_q–†Òà’qò-©’OI£”,Wÿ’­êWҍ¸1 %¿åógàŸº¯Ø­Nò·Õ Ç:iV¨4‡xž Ÿû±iù|‡åU<}‰¢/!㤀òAò+ Р2ƒ|ˌò)³h`y¢ú—§ë¾r„\áršYþX +0“嘵rŒCÆ ìSÀWæÖ.jÞBÎõõ܍豉óÔ4°¼/ƖdÃ%žø„Ó› BûMñÕÀÉþêç +æã0wEß=Ì\°.ìBD.„å¢×"°c'1!MdbšÈô6ÜÚ1‹;‚œ-s8›æKópG`O+y‹ɇK*üâøžéaÉ@È¡3$Ÿxºé µ\òµ µ\ú5\t5\@5™×дŠ¬!`u+Ø-MÃ_M;…à¯"88Lu«m6{’¼«›ÑÂÎ&P»˜ð\´ýÈß U á»þðòjbÈibÀhÄ[6ҋ†PÀÒÀÓ@/ØDõ¬G=«§ÈúÕl¶ˆ¡›y‚Cø2¸ƒðÜÚD›Ö-ã\XÁ:¬äÏ` +Ÿï¹XÃáÀÂßÃXÒà G}‡Å ‚‹3Œ5ã9pÁ5Û½XÄᲈõXÄ¢.$ÈÂml|Œå|Ìê<ÌàÜ[\ +nm ×Ú5ÒÒÊ¡]ÓÖ±@!H]/YùÎû@à &ïÁóÜ +Vx´ÒVx´Â£ŸÛÊ%ÓÂå×RÓZºöq.|æj&çULÒ+q4+ÜZO¬XÐ9HfúF$‚|‹6K[ЈÀw+ù(ƒ¡ƒÝ‹¶ïÀº´ â<Úáяí dÛ¹x·£‹vzю°Ú(¶­“8èrë96ÃçÀ­5ä]@Î:r¸ˆ;zgA‡”°K2>Aÿ‘‘ÿ†‰àb{û†îÿ婋žt¡Ó} ÆÝðèA=ð=¶=ô¢‘u“hß à$ß½ÂÿÝV3uÌ"o%9Kɓ³‡ó˜˜FbvI9Vú†ýçÿŠá#ò=ü u̐ôŠÇœôc@E«?e¿b(íE½¬Éa.¢^zÑË¢CœU‡>_¨Z§>ÉQAÞ\ò%!ÓóÔ¿_pÀßû5Ðë5AG¼øøyŸ1“~ ÞÇÁ[à”/Æ gÚßåâ?‹>Ïq¼Ç&8Ç¢ž%øYzqö¢ªÉ]ÑÃ9@êŠ"g Ë5à 7çÞ<Ǽ±=fð/΀wÁ9¯Q|Pšþè5X›Ëðø„½r…Ëÿ*ú¼Æ¹Ž.®Sø Ý8ÙçyïÁøƒP  Œãq«êÜÊüÃ-œÆM\Ç׸ž¯p@ÃE~‰û_õ).ô: x•~Bƒ>ÖG¸«¿ë"QþâñUàmp¼þ›ƒƒA0ˆÒ·ø™Ûx̯5’øc‰=‰ØUº‚›¹ Kðø+<.à$ÿŒë;?á1?R‡>@¨ïk?íéÅeþšŸ«´Î­Óàx¼ +^ú?ni 5è3|Õ5¼îezqA#ˆ_Lì +ý^.ê¨Ò{ð8 3øºw𗿂ÇÛð8‰#=ŽC=†·:ªn$ó2µƒÉyÒ?t,¯àY°ï?8ÜìVrŠšüôÈEžr¤?ŸØ£éì8ýGàñ:ërX³ˆÝDìùÄ^‚³]MÖÇØ2mú›ù~žƒAÂ馲.²= ö€Ý ÃËá&¸æ•‘GZ§ÑÅq’+œžYȑLüLV·€­8†ØDžDì©ÔRKü‡©§‘øóX%Ä_ƒ"6’c§vñv'¬¶³iÚPÄ6Ô´…¬ül_‘óøÀ+uÏö:¬~ÔãG-rE¢.9ÄÏ¢²BŽ«1į þDâW¿†c³Žø Ї2— …ø›Y™NŽõçy: ³ß°Z_j%yWxñ=ð19çÝvž-ÿª÷ê¡{ÑE'{¤Cfò$ÃIÔløêqÖå1•¡Â ä˜BŽjrԑãßd—kLÛçÆî7ÛØÆ6Æ`0`n&&`CbH'@B(ÈHB¸Œ„[Fi.K›¤¹@š%Yše (m×fiÔ6AZ·N]5mÓº}˜¦mŸ6MÓ¦MÛª}ؤjÒÚ¥Õ4ïG.S¥ =zí?¿ÏyÏ9ï9σ『ðw fùå ¾8À©¦‰è$7e‚l‡{àW”ú('ß¡Ü¿$xýqéýê֐§™ó8áÉ× îÉ1Uaû#ÜÊf<ߦg¸·3Øq;¦ˆËù±Ÿ§cX5Ê#DfˆÝ=úÙü ˆ‘MðSÚÌw)ï÷h5¯±Þàû졅pÎ$v1ÂiåL.x +8K)gYÃBðDài†§žmðô`ÁÓð ³÷$Ÿ«Ÿ]vàÉ>N×K<¶n²¿î'ø2LYÿ%u )tY¶€='±e¿Ì*•³™à³í\v/ä÷q~Jüþ¶¢íŒ êM5¨+É¢mIÙښìQ{r‘ڒ˵9%¨M)aES՜USj‡6¤õª1m"éãZŸ~Dõ ªËXR(ãžj ?Rá/ª1~ +bª÷áü:mí:rã"8…œ+GS ‘¿ˆðIñږ™¬VƒQQƒUͧ6¼Ú`(Vƒ±BãZ­7Ö«Þ¸Qu¦6…Mݪ5íRiŸª3)˜yNUæ› +˜ßV¥ùUX>T¥å3S¼ÿËÕÒKH…²‹õß'‘bCØ·©ÜE¼Úȓ&Kš"æL­3ÛTgÎUØ\ Z³_5–€ÖZjUm‰(h‰ªÊÚ©€µ_•ÖQ•gͪ,ëùm×Ub{SÅöªÈþg;>S‰#¦{LoÀ·&‘çÂÇYgù¾Ÿç{ø ¯(ãC$;I!›Qk³,ª¶ekÍ­*[‘*m媰W«Ü^¯2G“J[åÏîSIöŠœ3ò9O©Q–ŸsWޜïËãú£¼®ÊwÅâ6ç¾ ÷%æÈ3š¬3ŒIcuèKZ~vlÁF9Õ{âÌIW¥3SåN›Êœ.ùù*Éñ«8' "WH>×涩 ·Gùyƒòº§åv?¯<÷U¹™åʬª‘©ªQÆ5í`‡ ÁQ¥)-¸¨Ôê[J®þ&øø›R‚ÿVj0¦œÿ²ûÌvƟ^îDw¢‡;ÁX҃][ðK> ‘'ø¤Ÿ¸êâd­MSfI¦š,kr@¾ µ¥Ê¨­Vz(¢ÔP«RB=J +)1<«øðÙGƒC˜ÎF%„™-Ÿ*.„–ÿE8O#»çwr'EÆXw3ªnçy~iÀ–jlõãñq0:™R”±Þ¨´õ¥F²•ñ()R¢ÄH•â#õŠkˆòÃÕ‚/Ó-ÝÀ ù ø+`ތ ¥àY„óä€tdw‚ŸŒ²îâûSN’¬Ýû0›çuØRÉ;ØãäHfb•ŽM ýˆŸ~fº/Ðäwà‹ø¢_ôዾÕKÁíãÂõaxõÎÚ†¸í eÝØÐÓ"Ü'qÕ!›a$ý|Þ:xĞâqb€M¶ÊÀG‰#œæÊaƾÂ{i°{™s÷ÒpñÅ Åmx â´A±çY€2`¨Û͐¸ëÁѐb: ß þ}ø0q8Âk¬]‡ÙAî(ånìÊbL4ðn"ÐLÇ„àvLaÇvL"„&i0“øb’K4A<&è‡?Ã¥C)î{—Ãþ†Æü1ˆéœÇŽJÏ®Ðw‚Ú ցJàå™í9>£«Àóøc;æ±cžÜ˜§áÏÓüçɋ9.Ò‰?7FÒ³ááëBîçÁ_HÏþƒˆéùçx| +ó¸:;_ ˜ÚÀU®:G;0‚€ ¦ ê‘Ø\|üùHäÇv,bÇb É,RØ(2 $Ôy{žœ8G^žå~žù;¢õ?š‡o’½سóEi㗩—¹‡W¨ÀH*Ç_…ã%p p ŒÿǍ' 67ÉÓ%ìXæž,“e +Ê2¾X&±–8äÒ«¼ó>_{ ðîÅ´n¸šá¨a¿"ör܄Ÿ²·*ô_üŒañ î|n]ÅàîãÁäMð>¹gV°c´B~®PøWðÅ +I·Ñʊtÿç¼÷‘†9c/gÛgè–TW6\Æۏ÷_ݛ²Â¸†ï€oƒo=^I/ÂGéÎ!†R6òä¿\—{tÓåƟÒ6½%inmzK›¦÷¦4I¡IKK EZ.¥ÊE ‡¥\„1AA‚È Û‡ŒÊ ásˆ²)Ê`âe2Ïq2&‡s“ÉӝéYöiOÎæöÇs~é/éû<ï÷ò¾ßçÔÈYzö,µÑG¯ž£G΋>ۇ“é;®h +{mfŸ5¼*c?™ìÅô,küòôs¼5‚§Á™¨1#¥ê‹šÄ àbÔ°þ¼>«œ_×8?ÿ@}^§GnÐx7Øüu6vý̀çý/b@2°(CAw6·Ú¦Ïq-gÒ¿ƒ³¹£º…óùÇu7ôg¼ÝÇ8Î?R<7´{—{B¿GÜeýEï³R?.€ŸƒÁÁÿj臤êKüÝ?ðwðv·TÃú¬=:‘uïч踂ŽË8®÷9,ÞCÇ%t¼ƒ¯z gz‘â½@ý{–཮kz _ó«¿å>üŸ†/À߈ÅMá³ó_¹p•ê·ªÒ»øÜ·t—ÞÀɜGGñ8ƒŽ×qy§qa¯â6†ŽWÐqR›Øý6ÒØKùü'HíÛz–ȁé0Øvƒ]_Ñp|ܟ>ðüݛøªóÄâ,Þî´¼:…Ÿ:©áú)îìtGÇs¸®c8¾£8À#øÜÃè8ˆŽZ‹»Ü¬}äd/ µ‡_õR@»ôm!B¾‰à#ê_Ây \—¢åõªbá3Áe‡'Ž"Ö¯¤M‚z†ÚØG<ö’—ïS»q™½šÁú¬?_;µ„õWh‡Ö‰²²‹ +9È1ö’%c›ôيP9œ`-¸ çïÀђïo±c-™Ä^,p9õ=å±R ëûô˜BÚN<¾£Q¬?–õ[92ÛÙõtÖïdýn=L<ÖéAÖßȑ¾]«Xe»¹¿»\Ÿh¼÷E±ô󟧢­x8zõ‹'¨‹môH2ÙG>eè÷k=:BÇêt5ý²J´R“ÈÂ=pt±€n¹ˆ¬Ñ½(\ÈæSÝ°té*ôO²ù.r”œŠ—ž?àä˜b¿Ì˜×C"œföã€'›½ÀQÆê~ôÙm½«m†§žIšG<º4›µ¡æªv³ƒ·û©âŸPAo“½Û ¢É ÿyš#äy®™ƒ©Ònžs´mE×»o +œö” ž8ÊáðÃÔ,ÕÁÓOUÑB$Úá™ÉúóP´”Ê]£»‰ä*§…,§£ÆéOdñ_ 2€“\ùGð³{?vòìáˆßÀX´-Ë•s^tSŸsd…+ž\x +á)‡Çcž:ª³Êh†«ž©¬ÝÉ_‹P¶’ +~”êÙÅ/k$?‚f§OþàyFŽŒ>OqÅm›¸r¿ÁѺ¼!.s¹Sc‰£>;\™°ä±§"öã¥üp᪇«®±pMdíptóv¹†‘Zª«f ³^Ðéw@dGÝ\‰øȝÅä¬çó +Þ-a4œÇuÓAL&cÔjHÖ¸A©ð9àʂÍ͞Šàò*P}LHuƒÂª4Z5±Œªê¸9Âàˆ_'üùâŸÑ`ÃKª0\REÂ-U$Fpˆ+mw¹´£‚äª_ÃÕ²¼„±‹q¬ÓÅlIŽî&&cÌqjHNQ8Á¢:Cšj²U“¯`b±ª+4$±JUIµ +$5ȗ4V•ÉíªHž%oÊ•¥¬U©q»ŠO«ÈxB…ÆwU`º¥BSDEàüOùèÆ®GÀê³m%ã#P1iï×É×(ê¤ÞbPµÉ¨!F«ÆtùŒ9ª4y4ØT*¯©Rå¦j•™†«Äܤbs› +Í*H½WžÔ5r[¶)Ïò´\–ʱ\’ËzD” öÃÿ$#Fžöá#ϯñw泥¯8!7#kȍߚ¨ +‹Yå›J-*±äªÈR¨BK¹ +¬UòX‡)ß:Jn[«rm3ä²/T¶}•²ìßR†cŸœŽ•îxGéi•3-»ˆöÂ÷Ü[×Õ1n‚ÅŒ€sð¶ÓÐÑJnFS'džR¯ƒñ*¶U`·ÈcO“Ûž¥<{¾r%r9|ÊI );­AYé㕙>MNg·Ò+åÈØ*{Æ^Ù2^5óMð©l™ÙÁöý¼›ñ³kûî‹°HŒ=S°l-~ò@­ £Fª¨‘òÜy2“”ë4+ÇiS–Ó©ÌŒ\P¨ŒÌ +93‡*=+¬4L¡={ŠlÙ]²æ< KÎ7•êÚ#³ë¸L®_Oø̔zÙÿvx75RxÚeXՅ|ž…¦v¾‡Æꤖz P#¥äÆí6(Ëe”3Ç¢´œ49\ÙÀ#»«L¶Ü*YóêeÉk’ÅÝ.³{ŽLùËddHOñô*ÙsLIžsà#>¡”|îo¸¾ ï#øØÕcð`Ÿ;Ð3 mc‰ÑHrSCn|Ĥ„˜ä–Ä*½ Y¶|³¬ùvY<™À­TO‰Ì>™ +ke,¼K)EmJ.š¥¤â¯+¡x£ ÅßU\ñQÅŸáy|Î;îröÜÃÈ» °ª…žÝã±chiCG3#àt†Ð2˜˜Ò7ÙÄÄ^ž ÔR“L%V™JÓe,u)… %— VRYH å2”·*ÎÛ¡XïÅx×K^n"/·¢—ÚË´àýŒä2K°ç-p®gä]9‘ž]mØÁ œ èjF_-CF2ó֓bâ$&Ö@¼Œ>£’*-J¨L“Á—­x_b}^ òSH~‚ègCéÓÀc˜c ê~†cÿU€×óE´þÍp>4™óq*=æNÁsµÓ¼–aXFßh©ˆ˜å11×Æ+)”¢¸`ªb‚A‘ M¤h‚PˆÂñ¡i`À†0MA Cá?ÈÄV†jæ)x6Á»–‘{ùLzÌӐßÂû‘Ø£êVB†V7ùq7 õ“Ò§¸‘É$ŠK%l\xaÖ0¦©Ãt˜‡Ù\xÀÛ ÇÄ Ç¸ÔcBê¯Huh¨cžCæÆ걓zœCO€N0yy@Ë0¾÷—"´d£×F\Œè1ŒãR‹¿ƒ¯kæRivHMdM4p…ÛġӄØ&’Û4›€â5GoÅLíLk£.KhhŒh öký\éÁni)![€ š9ŸÚ<ÚÒºh#;’?é;: “û6ÎçÖëá¶æ·+X¯¹ÌyŒ#ƒtóöp÷Ò ¨30hs¼1 ¾×;áÿü 9éâ¼tG7Úè¦&Ý4¶nrх¨ºèU]Gyî,¿A—ûÿ¡U»‘œEpܳŸÖÅ:^Jæ<ÿaÖ<2h6¶’ƺ £õÿð’gG£‡I'¨M/uéE½è³FÛG.úYë¥'ßṿª†½•À; ¾1p¥a0œpÖö¯{ðLߐ {%€W@æCa„!WŒ®Ò›ÄÑOý c *ôÍr1@áØÔö_RûœÉÛqpfÂËL´tL¬ôR€ãl`íóþuÁ€ü¦tÈ^o$6hVßӐqü ø-ø„8.sf¯pé†>¯rF®qØ®Rà+Ü_W.0Yë€ āt0R·™Î¿gj¿‰sø;Îå®éÄ×ø˜¿pH¿ÂÙ}ÁA¹Ž#ûGøGÄs"^¡@Ÿà ¯·õ‘¾ÄaùÍGÈ>|­Túp¾ˆ!X·ð4ÿT |ÉpåàŠÆ²~kÏÒg8‹Ë8K8ßÇG¸®‰ã<ÕûÄñNô]<ÍEüÝD4ËÏ(Ìy}¬×YÕÏýZ€ûYðã;bà6×ßÎÔ®OñÀÛ}¨<ý +Ÿûnâ-ÜÌÏqSýäãMâ8ûz{Ž†õSâx8Nk{ÜM)»(é3Hé4’z¹~=ÈëÇ1pÄp;ÀÍTÁþ¤_+Œ}Xኁ' Ž,ý?u§ô +Îæq¼@>zñS'ñuÏã/ŸÃ >£zŽÍ:=E;¦§N*Ò£nž<¨7ÈÌUí#Ëû`Ý :À.ðœ_ORòËìܠԍpÙùµ/±ç°öh=‰kë!G¨Ë!Ü^7îï ÊY¿ŠöñJ¨gýõz\›áhçßÚ×ÓDt†*½bn¨ÞÐ 6ëù^ Èþ489x,Ã؋®h2šG»ÊÕâØM>:p“í¸¾6üåNèv4²­¶Ç#Ô¥Y ¬¿E‰fƒŽUŸÖRÁÕ0®‚weõÀÏÿ ÀmªíàX åu’‹Ç8#» ‡ŽtâÏe‡£ÉöD®ŠítØŽ2­!ŽUÔeÿ/ç‰Z"\B.jÈäƒ(f§¤mVÃ]ÀÛþ£O{í jþÖÈ­7­\´ÈÌ~ìð¸©tûÈ þ\âχc“9Óà)„§ž2xªY»Å®C-­Z@öæ³³R\ Ú,F}óàö£œçŠ9Å(ô48ĵ×É5¼‹xèêƒWã:EÀiU5YJϨá¼.&Žjâ¨$Ž +‡çn1 öBxæÁSÎÿ¢Ú(fYjç›C(¨—êõÓi>'{·ogžçÊïáºÝG;kç}+ñl$n9¸Cà5Á¥…r²§xx’ÙK<¹ðŒ¢sG“ášÎ‰¹®x*‰jê]r¶ñí~"}ŽnwUL%oß NqÅOà*c}œëe;WÝ&âYC›¯%/‹×P8¼fòfc_1ì)žö” k.\ùp‡«®™ṕg•ªáÓÕt¸ÔÉSOñY:ïຎo'ÿž`ôúQ:9-xÛâ©w3Ӑ—…þQ‘zݯ>;\±p%°'/\™p ‡k4\5†hò‰r¹È#{#PN. +ÆiÊædgqeê—dñÏʺèYŒ‡³¥½Ã1@3¯åz©MaL$?óÉÉr2ìC¤&…X5>È¡1A.å%jTPªFgiDð «a!w+'t†²C‹”V¡Œ°:¥…7)5¼C)áO(Ù𲒠å1|!OÄwòDútÎ.®÷ÝX‚m )‘1—‘›PANŠ©O!õºÇç´†*ßdT^„U¹‡r .eGx”‘¦Œˆ¥GŽRZäyS•bœ­dS¹<¦¥J07*Þü¨Üæ¹Ì/)Ö|Q1–ëà{ÅZ|zþýxÈÆÏ- ‘k~ïkˁ撧™Ôf2µKmFØ•i1)Ý¥Ts´¼æ8%›“•dɐÇ2\ –±Š·(ÎZ(—µL±Ö%rF5(ÚÖ.‡í¨ì¶—e³]_‚[¼÷©¾}ØÃvÆ­–IŒœ¼Öãm3–ßlò4Lb ÉÇ ‹ RšÝ Í¢„(›â¢bä¶%Èeó*֖£[¾œö»mŸ%‡£TvGlŽõ²F·Ã²D¿(Sô™œ’Ùù/ÞûtþN¸Û𳛱ˆëA¶ ›4Ÿ8î§6SÑÉ42’ÚdS›wˆâœFÅ8¬r:ŠŽv˝,»3äÉ木¨˜é²ÆË»Hf×™\ÛéîR„»Wáî~Ü×ÀM>ãþdß{àÝÁ¸×< =‚ZìQ1•ð]!µ™2ŠYäQ›,j“LN\ñr¸,²¹ìŠrÅÊêNi²Ä —9~œLñSeL˜«È„*W*,q‹B=ì9¡ Ï +N¼¾UH¢O]pí†wûLúÂ,úXÆߕ|VLl÷’£)Ôf9É#'äÄCNœÞPEyL²xl2{œ2yâeLJUDÒ0’Ç(-U3å¤Ui0Ÿôv½|:É®Lô1v™ +Í¥B+×tʵr‚)—ØD]᥊yÐÙ +ݸü~0)\ü*°á¢Ö¸É½¯Ã»{‰œXfm…Õ°Èÿ³Ù2É÷V¤á|ÒßµÈ=růËĔèT£±MÐTÆÛ©ª±jE¤Z­WíÁj©^v›q–¹q˜*ËBÕ˄ΆKZã[µo¹5Öc[­¥_ƒU°`¥8,õŠïGñÑ ¶ôbK‚^2ٓ:£±hhÓ5“i|1•/jöZ­VXA>üÒך–Ï_Ùìé,Nš7Ѧ _\Êõš[=_Ôi¼uš`xÔÑD@Öyyö°_Í2%Í´¤ÍxÁ>r‡Ö؏{Ô¹r“œ`jãf>Øè+¶T±e$9 `cöäðU:› I ~Š%‰‡‹Ù±ˆ/袁/“ñh¼… _è°òs)q¾©qž…lî‡îÑ×â¾Úêµý´K·3[èj¶’ ›ù¾M¹ìL_ß>Ôüì7\;Ö²c­˜4²£Q“kTT×((kˆx¤[í«w +ôሕ¦æ¦Èå¸Kk4‘ëU»ø@ú®ò{.ÔJ£1P╢4à™ öŗqEÛÚ`ÜƎ­ü±U®nÕ\¶ÒÅɼE±ÙÌi›]lÓÁˆ'$à“Ó{.þyìÙˆǵ°ð1€Ja}ü€ ˆ ð¹!»ã÷…Ïš¿:mfG3m4‹I3]4óE35q^“÷'€Ç$ã;‚ði츎[Éuñ är@ +1³T÷ƒ<ȸѹm¸ µüa‘éÀ-ÿí߉MKvǀz«˜´(j-|ÑBL‡9÷ðÏ~×àô¢3ÿp.ÇQ3 xÔ­ê€GònÃ߶dÜÇàN¸;¹|ܛü}áï6Ü÷'Ѷ$œ3'ÙqRý<%&§4ãS|qJ~œDzRÍ>ù”çދ•x/Ã9×ÅÒf ž|®Ê¸'y®Òj= kÍâٱ ]øý0¸’Õ!,£‹Ú£p~ †œ¥Ó³´qÎ0rNÝ<ÇçˆïüQððٗcž;ÖÞ¥¸Ë`|øº<˜\ø¾“äø^ò\e>´›ö¥Pë³ÆF<?WŠÃO£cq|”€x™¯ª£¯iøoÐç›räM‰ö_¼a«{ý “u| ©= Ø&RÿŠKâïæ忚—Û6¤¿˜ÛßW$þdvÿƒ}ê÷öºßÙ*ß1?ÿšX߶¥½i¿{…#_â¬ú\ü–YŸÅ3Nmc}¾ §àË6ü>±Ó|d†ÿÀüþ¾)ü]“ú;¦ø_šì_³Ãü‚/±ã…ê9ûÔ³ +Å3¶±§%êOl»OIœ' ø•3d,‹ÓmB¹ñ²=âE;ÕÏbW8{¼;Ô +Ã,g_æì…Î^êìUÎþ*IltþB¸›t®‡l®î ¾xÀÛ÷Åý×Çá(´À¡¤ Ÿ$¹/¶‡³“gáÊÃÓÇ ç—:{¬³'Äivœ—6½l`÷ÛÄîµégÇÝvÌ;Åå˜Ýêö8hûCºžŒ›ãûÒûQú§Oõ)ØÍ s‰'éÀÓI©=Ò.ù \¹xºãèëü¡ÎÅþ±Îïì)îñç×9žó)#+œ¿ÖùyáJ×ø¹9š¼½Û‰»xs'5íÀ󠒡 Tªx>)í3ÉtSI½•‚/ WBé)t~ÿø¦-ívì·Ñí£kè´É~¹ÇÆ»›FvÑÈNZÝÁÛí™ÛâªØâM¬ÞÀsëEp]ü†z>óDk;áùdŠµ¥ßédI8š,yùb¿iŽ|ENàü­b”¨WÄVûåf{Šc–ÍrŽVրco¬“5Û(¥É‡¨÷žX‚e1/âýÜ sÐSG j+ƒG’¥Yùv¿œ™øºáꎣ7Žb%8ÊpTȊ*J¨Á3ÏL¸JYß–ËÙ²œ_h9õæ +ukŠ<©¡q쨔+cåìv”Ç0•´ ×jk*®zç/jWÎPY2„ÂÑÄ@º8~ïRø¿¡5î3~Þ¦µnÌ0^iÛè³5Ə%Fõ9F€|2™fÆ¥eàÍƙÀW€µ®~î5ˆÃñÆUƒùbµSåÚì'ƒúRYo9Z¤öRm U…ÂNÿˆÂuo‹Ýí€Öº¶û{={V 1ŽòI=ŸL3¦N ›±9)1ªkב–%©‰Ò© ¥ÅÀ”þQœ2$ú§²(µ"út½Ó¦GQÚÜ(L_=Ó7E÷Œæ(È8ù§#/ã|$2ގD—#ÑUÏÀy‹Õl¿uàjãÎ6¿×EWØmçóÉlqšb}'6åt2"·s ÎîºæD¿ŒDôÉèE]zG¯.ÅQØuXôì::zdVEAfmäg]yYË#‘µ1r³›àHädŸŽìœó‘•ó|äïÖ8†ÿÐZ¨”•#èåþ_æóyì›)N“è¤RlF‹Í0±)N¤EQnfôÈ΍îÙyQÝ3ò³ûF^ÎàHä”F·œ±‘›;9rrë"»ÛÒÈêöõÈLì‰.‰Ã‘‘8é‰Ç#-ñ*|èïÖ¸ߍVÃkZ;'}ý^kŸ\ʖ9[CŒ¤Åëkä(±)›þ=;EaAzä%²påFn·‚ÈIAqü—ý2®ñÚâø¹Id"‘¸‘AB’(‰7Q\³ „! bŠ ©)D1‰éQ5 mQ㫚Õؾš§˜ªUZ´EÍJI'÷Ïûn¼÷Ö[Ëëzß^k¯{“½ï9{ÿÏŸ³w)‡Ê¢¤c aë¨ÖeZ«2ÑÂRÛ[Xh‡ sí¡q’ý¬ö$z}&fûDöUŸY‹™¶šÀˆÈÔ[SÎFÏÙè8›0ñ…¯*á\ÎL8”µ¥´öÂV[FØ8¹k'OaUÖOX– Îu„¹s3¡qahuaq¥—u¥1v¥Ùteæu92_¸<ÓÉ;“}G2 ¦ÝKB»ñ½#ÿ‹ ¶&`T—q©&˜€I%ÆYwøªõ4vî6ÂÆÍNXº9 + 7gaæV^hÊa,¹ÝÓ½)C"ƒ¡Gú`C³îÁ‹äÁÌëA—àN îyb*ùcß4ZïÌ²IhW¾GóóV ‰LêgMb©g½Xޅ8|ÍDIQÂËNh<)OŠÇòz”DòDïF(½´73–Ï@tßi–½iN½i6½ˆÁ3OLfÿ1ì;¼ïCuIËمïQáÌ|ÄÒ{b _âð€?Zøj`&¬Þ±.v?._ŠÆ ×û¤Žþ€éςþñ(3–ÿ8”—яWҗÛ>Tz.²Ø?ƒ½‡µ¥.­7ãi<Ÿ¿%ÿoD,!`R•8¼—\à‰)ÚÖÐó`.Ð .¯jÄÈ¥HB–@H‘1°%Ú폎á@TèªXb¨’/&f:û¦.c¨K4®#1ðwsb©‹=˜8|ÁÄL´¤fÇҖœ§µxxC¹ÐCxìtœ‡ŽóÐÁ $2Nºæ(‹ê˜mt †5&j0T?ŒCpmG2Žaôè×EˆhË9K(ñU/0q&{–´ž@âAkõÁ¢XÔ =—ˆžóÐà =‡§ÇYÏ&zfͺ ·uÞêЭÕ>Hð¡VË^iPfPwމžÄЋº¤”ÂùŸž¸‚ˆ¯˜¸±Œ¸ØlxH9,4œÙ²…5 Á‹f`Ñ ,ÂxÃ808Æ!†qÐMÙ )]I†ÉÆ l„Þ"‡1Ó0BTIýà##P$CcbÑa«Ü’—2ÄS’c5#&šƒF¡Ä&ÚG;Τ-gҖ‰‹Hê#’óˆ„D‘¼ ‹´¡>[3ØFÐ5¶b( ¿Aüb${¦¼išz¡Ñз9×&žl^}„p"F;b2!µ{asÃE‚‚­ +D&Žxâˆ#Ž8j$,byüb!p,dêLðY¼õÃ]ّ!1š‰¢C¾H£l‡p…õÊÏøŒÂñ¢Á„\q .»÷…°àçâU%NšLH„ö-Rø‘dch€’Ê +Ñ^ô¡û@äDˆ•À½3Hvägxíq™|òDêp–„*Ýжhc´æHêuå»}û§6¸ñŠ7jê«ÊŒ› +?R‰#•3Iõ3<†Ã ôP€ŠSÊ,§>Ÿ†ˆÅ ؞„Eé†q…„Ž‡™\·¨=ß-øR'6û†¦;Ûø9IA³Š”zɆٜI6—|XdAî,@œÄW°æÖ¾+Y?†µ[ð»Ú“©C ÷iB”F-¦›ý™(¡ÓŠ †-A[(Äã÷¹¯üožq@jÆ †âÈ¡^s8“j$,A¨E$½hú~?‰Xhڊ½ôìÈ>Øǁõ-æוaÏ0|É!äStÅ+ŸR)5ÚDÁ@*zm«ah’CãFø±nl¢V7q¹m‹Íp›nÂyÓQњ+£{±ŸOš#Ok ¹ßRã>«ŒëÊ5yî]…€Nb‹ñs›0 ©;P¨^84~…îEš±JˆcÜÇi¡¶Âlª)ûÁŒ%dátÍU¶Ÿ[ÛPYúÕÊ‹#Œ¥Wq†¢ý€rF‡tÅGz]‹¢âî(9dj_8ôºª`¿Õî…]Äü¨à°­ìK‡J7HŠÓK‡wsÿÙþä“Ø—1TTÖ..Œ(r°Û®”ÅÝõéѵ}­4fŽ>¦z±‹{–ÏŸ·à£µ»LÝAª¨òïÊÏ»sƌzfÊzkfL°½(¿Ö„ýÔäCõ ~ h?›j¤}«CJö§3ëÕEÐ%‡/c_TV¹ÙJÓ*½p°ÎT°_ëú²xEêì×y\Íùð_’^HÙÚ¨;WiˆÙÉÅ Y¡A›"ÝÒ­[öˆl£!¤I²vå–^يRª9­$ÊV¦d2öåþnqÕy>ÏÏ=/÷™—ë<öy÷;ßsÎóýžç+N˜Èw $— ӟ°ümWy0¦’ù\°*c »†<0gלˆuNä@§Bö„‡É!“ˆÉ ‰·ñ¯+‘‹G[Yš›uï?Rê|÷^î—Èrr¯ÝýH®¬/¯坑žíëªüŸÝí,´~$¾åÒKý]×Kn±`ÅÀÿôlëï¥ò‡Á=ê»Zò5ö[7ì‹q|g‰Unr§¯Ä"~²F§8ð—ß›-cYþ¸ÙÞ đ\ೖ-K1¿EsÁÁ÷Ø)–`[ƒ©‘ŠË>©ºzy·H–•™‘™]PúF(볫Êܤ;ËdqÁóF™µV –Lk-²ÒzßPߔJäùK{×wÜWÇy~Ç×P®'C8Ød,ß´.ü†“®õ Á:ÚöÝJô£@7 òdØzqFÙ@ˆˆ` €Và"°¤ 6X˜ €#‚Ÿð¥#Î ¤Ž Z¼ÈÃÍÅÙe¾WŔõùÕíԃáþN~ÒaÉ~¿qfuÝÐ#E".Ýlßйy.ó’?XÏŠÕ µä;®ïmÛ HK¶=‡`(tu4äG!g‡ÔnÞð×_˜à:‚±^!ˆïB@——zhCÌLZ8ÄlÐ$@®ò +®²+è @ ‚eŠ°!¦OÜ¶ €Ax âCŒ8ÎÊÖ~ⷎNs]=¼/‘˜I•õûÖ£ü3Ñ¡¶M*{q6lî°jï¾K~!}9Y¯áËÖÅm!ÞóÐ!í€Û_œ7òHlêÞ°ˆ(­®Qpp†‚j¢`Ö0G°ÀXs,Dà`+‚¡ØÔÀ/xŠGÐF°@ó§ÒšSШ +sÐ=ét¢®##URuMÝTÄü„¤ó—³ò‹Ëî?|òšÇÊúôzq+[:¨º³ÖsâÀê‚åMžnþÖ´áÛÚËòú›ä‚¹3´‹å3šoƒ\P…¡7.‚B ¬<¤L 0 +wzB¨ýFÁ1¶Ê2 +òȆ×èˆ ÀDG­r€ <ƒ6§Xà`3 +üˆž83ð|6 Ô~!Æ]{=i¶»ï’5á»$€²>¡*²OE®t³OˆªŽ¯œ1À°Ñûoâï,Nõ4•ÿªðGO\ٞ~Ùêpc݌)ì àGàRÂÀ0X»èÏQAÁl²(fà4ˆ¦ ƒM<ÒAoc0n¦`—¹¿á"ú§0E°€>‚§“)hŒ@<×¹L"]ÉNÒÚJY¨·ùs·Á®«r ,¨'ùé’%‹ßìçhݹv +ÍÓÔ ݆/¢UÄ)ã öÐ|›íáJËæn¡×P‡¡W›‰ +Øx ì£À—•°k’àFÁEà‚Q®…`0|”=t€[“ 1x}Ôf«pÓÁc3Ü°A&€ŠÑ਎pJñù  ~ ˆò7%µ1ˆû¦¸ú,Û°ëPRN¹Dª,^ïHýU0u€©±Žf>Š‡èÏ7웻ñ]zQàÏZV «¸ÊÁqúˆ6 S𠎬d`Ç0  XA#ø º°G¼V´Jè[ò(ØÉÀ9 +RÔ¡àWvHýoÃ^0¢x¸3À bx +p`+gQ€£(^±£‚1£ö¦¤¡×±ÇûÙ>¡±—9¨½Ú–ã騬ÿ¡*ó®^¾œxú§ø#qb ,Y2aHwcýVMëOüb’/f=-Đȁ/} Öô‚-ö ´£`=·œç€¾}’ék஄)˜ÏÀ +Âð§à4ÎÜì€`"þ¶ Cø!À)çp3:ÊmðÄuŠ@ÁXoQÄv£ ¸£þÀn¢gn3»”ñÀŸåw:sõö+*ë÷ªòŒÓq‘ÛÂBV- ü›—‡ë¼M$Nre®O{®}v“ ¨R`ÍÅ Â8 3J°yM˜OÁ4ì)X͌ZGøyºšQðj{âDM {ÙÏ_πÑøøY ‚ÂöžÌ¸ÇÓºª|)ýweýŸUefÂᨈðÐÕËë.Aó]]éãdci¬§I~\w°„í<Á—€‹8ðº/–t•î èP°¿gÛ+÷ùe >*7E`S# Á Œñ3\ƒG„ëHpχHâŽn aKS[çÕK 5Úuîk;Åmɶc™Õ×Vùރ iEÞHDÊúòêíÓ_+ïß¾U\”'û9GVXJ¬Ýë¹9MŸ<~̨áƒô±´èփ™I+Õÿ¾qøÖ¤ij‹L9%ý¸Añ©„0pŒ‚cF"((…`¢77QØÈÅ#¦'q»Üù h[:à-H,õn#*Z_YXOõ +=V…yí!´pÁ’°Ýñ‹ñLYÊú´zY*K;—x2þð˜}{"wîü7ûeÔrÇñ„"Iwž:G”Sy¼\šV[´<¬6'RÜÜÕ¹n%Ü:溬'5Ém¥¤ÖDtbè¸Z·¦òºL\·&$ +³–ܾŸï~v珿ן{¿¶}ß»Ïç÷ùœ<%E…„&Ýg™§‡›ËÔIN£†¡DHÁJÓê"ÔNƄdDè]ƒ Qè!öcØ@ +°d *¨°>7 º8P°W% \ò² h¢`3‚^l:®9º3â Ðc<…ÍxWo67µü!ÌõúÊʺî¡Ìó·[ñЈZÙÒI‘ü4Ÿz{z?cŸvTäg‹„‚C |Þ®ø¸˜Xî.þqDh\â1ÓyâXǶC>¨M|;…“egA¸ ¨ð:܂ 8XJæ[7XôIÐ|0|ÿ—ú›¤N‹7€¿ áõw[{çEkvËàŠcàJȬÅþìÈýi%J-žöQ–#¿u¯Ý|FBòËéѵµ<~ÐÔ V©Tõwž|“„ä_¥JvV’—{J,Î͓ɯ)›ál/`¯ ¤ûùR|Vx¯ð¡®fmß „œ96 þpL1c½ÐÆ3Y0†Ïߜ,‡§/ÿ–™N‹ÎPà[@õ¶Q†t´+eK¢TÙeæ9ۏ-pó +âÈ®|BpWãù©×$ˆ ¨ï¿%IHþOÞ¿y­Óé:ß~0?_(g¦‰D¢ô,ñ™¢rE}K¾cШ+)ÊJ_*=ˆÍI,€?!ñ4Ðl=ŗ[ P½Õ®¿=¸м [˜Í÷þö ©}gö˜… OZO$oê!xLõá=é¥5ØdbBCö) ÉO¡Õ´¶>ñRÛIðrþ\šš’r"#;¯@V©2[ƒÙk©þ«‚˜›cç›Ìlz½Œi5a#*¹XÝmþ?”;¼6ñ2.Þ#œ:ĉ֙Li­Ã’¿«ßÌðü_8L+ endstream endobj 98 0 obj <>stream +H‰œ–yTSwÇoɞ•°Ãc [€°5la‘QIBHØADED„ª•2ÖmtFOE.®c­Ö}êÒõ0êè8´׎8GNg¦Óïï÷9÷wïïÝß½÷ó '¥ªµÕ0 Ö ÏJŒÅb¤  + 2y­.-;!à’ÆK°ZÜ ü‹ž^i½"LÊÀ0ðÿ‰-×é @8(”µrœ;q®ª7èLöœy¥•&†Qëñq¶4±jž½ç|æ9ÚÄ +V³)gB£0ñiœWו8#©8wÕ©•õ8_Å٥ʨQãüÜ«QÊj@é&»A)/ÇÙgº>'K‚óÈtÕ;\ú” Ó¥$ÕºF½ZUnÀÜå˜(4TŒ%)뫔ƒ0C&¯”阤Z£“i˜¿óœ8¦Úbx‘ƒE¡ÁÁBÑ;…ú¯›¿P¦ÞÎӓ̹žAü om?çW= +€x¯Íú·¶Ò-Œ¯Àòæ[›Ëû0ñ¾¾øÎ}ø¦y)7ta¾¾õõõ>j¥ÜÇTÐ7úŸ¿@ï¼ÏÇtܛò`qÊ2™±Ê€™ê&¯®ª6ê±ZL®Ä„?â_øóyxg)˔z¥ÈçL­UáíÖ*ÔuµSkÿSeØO4?׸¸c¯¯Ø°.òò· åÒR´ ߁Þô-•’2ð5ßáÞüÜÏ ú÷Sá>Ó£V­š‹“då`r£¾n~ÏôY &à+`œ;ÂA4ˆÉ 䀰ÈA9Ð=¨- t°lÃ`;»Á~pŒƒÁ ðGp| ®[`Lƒ‡`<¯ "A ˆ YA+äùCb(Š‡R¡,¨*T2B-Ð +¨ꇆ¡Ðnè÷ÐQètº}MA ï —0Óal»Á¾°ŽSàx ¬‚kà&¸^Á£ð>ø0|>_ƒ'á‡ð,ÂG!"F$H:Rˆ”!z¤éF‘Qd?r 9‹\A&‘GÈ ”ˆrQ ¢áhš‹ÊÑ´íE‡Ñ]èaô4zBgÐ×Á–àE#H ‹*B=¡‹0HØIøˆp†p0MxJ$ùD1„˜D, V›‰½Ä­ÄÄãÄKÄ»ÄY‰dEò"EÒI2’ÔEÚBÚGúŒt™4MzN¦‘Èþär!YKî ’÷?%_&ß#¿¢°(®”0J:EAi¤ôQÆ(Ç()ӔWT6U@ æP+¨íÔ!ê~êêmêæD ¥eÒÔ´å´!ÚïhŸÓ¦h/èº']B/¢éëèҏӿ¢?a0nŒhF!ÃÀXÇØÍ8Åøšñ܌kæc&5S˜µ™˜6»lö˜Iaº2c˜K™MÌAæ!æEæ#…僰d¬VÖë(ëk–Íe‹Øél »—½‡}Ž}ŸCâ¸qâ9 +N'çÎ)Î].ÂuæJ¸rî +î÷ wšGä xR^¯‡÷[ÞoƜchžgÞ`>bþ‰ù$á»ñ¥ü*~ÿ ÿ:ÿ¥…EŒ…ÒbÅ~‹ËÏ,m,£-•–Ý–,¯Y¾´Â¬â­*­6X[ݱF­=­3­ë­·YŸ±~dó ·‘ÛtÛ´¹i ÛzÚfÙ6Û~`{ÁvÖÎÞ.ÑNg·Åî”Ý#{¾}´}…ý€ý§ö¸‘j‡‡ÏþŠ™c1X6„Æfm“Ž;'_9 œr:œ8Ýq¦:‹ËœœO:ϸ8¸¤¹´¸ìu¹éJq»–»nv=ëúÌMà–ï¶ÊmÜí¾ÀR 4 ö +n»3Ü£ÜkÜGݯz=Ä•[=¾ô„=ƒ<Ë=GTB(É/ÙSòƒ,]6*›-•–¾W:#—È7Ë*¢ŠÊe¿ò^YDYÙ}U„j£êAyTù`ù#µD=¬þ¶"©b{ųÊôÊ+¬Ê¯: !kJ4Gµm¥ötµ}uCõ%—®K7YV³©fFŸ¢ßY Õ.©=bàá?SŒîƕƩºÈº‘ºçõyõ‡Ø Ú† žkï5%4ý¦m–7Ÿlqlio™Z³lG+ÔZÚz²Í¹­³mzyâò]íÔöÊö?uøuôw|¿"űN»ÎåwW&®ÜÛe֥ﺱ*|ÕöÕèjõê‰5k¶¬yÝ­èþ¢Ç¯g°ç‡^yïkEk‡Öþ¸®lÝD_p߶õÄõÚõ×7DmØÕÏîoê¿»1mãál {àûMśΠnßLÝlÜ<9”úO¤[þ˜¸™$™™üšhšÕ›B›¯œœ‰œ÷dÒž@ž®ŸŸ‹Ÿú i Ø¡G¡¶¢&¢–££v£æ¤V¤Ç¥8¥©¦¦‹¦ý§n§à¨R¨Ä©7©©ªª««u«é¬\¬Ð­D­¸®-®¡¯¯‹°°u°ê±`±Ö²K²Â³8³®´%´œµµŠ¶¶y¶ð·h·à¸Y¸Ñ¹J¹Âº;ºµ».»§¼!¼›½½¾ +¾„¾ÿ¿z¿õÀpÀìÁgÁãÂ_ÂÛÃXÃÔÄQÄÎÅKÅÈÆFÆÃÇAÇ¿È=ȼÉ:ɹÊ8Ê·Ë6˶Ì5̵Í5͵Î6ζÏ7ϸÐ9кÑ<ѾÒ?ÒÁÓDÓÆÔIÔËÕNÕÑÖUÖØ×\×àØdØèÙlÙñÚvÚûۀÜ܊ÝݖÞÞ¢ß)߯à6à½áDáÌâSâÛãcãëäsäüå„æ æ–çç©è2è¼éFéÐê[êåëpëûì†ííœî(î´ï@ïÌðXðåñrñÿòŒóó§ô4ôÂõPõÞömöû÷Šøø¨ù8ùÇúWúçûwüü˜ý)ýºþKþÜÿmÿÿ ÷„óû endstream endobj 105 0 obj [/Indexed/DeviceRGB 255 106 0 R] endobj 106 0 obj <>stream +8;X]O>EqN@%''O_@%e@?J;%+8(9e>X=MR6S?i^YgA3=].HDXF.R$lIL@"pJ+EP(%0 +b]6ajmNZn*!='OQZeQ^Y*,=]?C.B+\Ulg9dhD*"iC[;*=3`oP1[!S^)?1)IZ4dup` +E1r!/,*0[*9.aFIR2&b-C#soRZ7Dl%MLY\.?d>Mn +6%Q2oYfNRF$$+ON<+]RUJmC0InDZ4OTs0S!saG>GGKUlQ*Q?45:CI&4J'_2j$XKrcYp0n+Xl_nU*O( +l[$6Nn+Z_Nq0]s7hs]`XX1nZ8&94a\~> endstream endobj 74 0 obj [/ICCBased 98 0 R] endobj 81 0 obj <> endobj 82 0 obj <> endobj 83 0 obj <>stream +%!PS-Adobe-3.0 %%Creator: Adobe Illustrator(R) 13.0 %%AI8_CreatorVersion: 13.0.0 %%For: (Jamie Zawinski) () %%Title: (iSaverRunner.ai) %%CreationDate: 6/4/12 2:30 PM %%BoundingBox: 0 -10 117 114 %%HiResBoundingBox: 0 -9.4248 116.3867 114 %%DocumentProcessColors: Cyan Magenta Yellow Black %AI5_FileFormat 9.0 %AI12_BuildNumber: 406 %AI3_ColorUsage: Color %AI7_ImageSettings: 0 %%DocumentCustomColors: (PANTONE 152 CVC) %%+ (PANTONE 485 CVC) %%CMYKCustomColor: 0 0.51 1 0 (PANTONE 152 CVC) %%+ 0 1 0.91 0 (PANTONE 485 CVC) %%RGBProcessColor: 0 0 0 ([Registration]) %AI3_TemplateBox: 57.5 56.5 57.5 56.5 %AI3_TileBox: -231 -299 345 435 %AI3_DocumentPreview: None %AI5_ArtSize: 114 114 %AI5_RulerUnits: 6 %AI9_ColorModel: 1 %AI5_ArtFlags: 0 0 0 1 0 0 1 0 0 %AI5_TargetResolution: 800 %AI5_NumLayers: 1 %AI9_OpenToView: -12 117 8 1190 1089 18 1 0 339 90 1 0 1 1 1 0 1 %AI5_OpenViewLayers: 7 %%PageOrigin:0 0 %AI7_GridSettings: 100 10 100 10 1 0 0.8 0.8 0.8 0.9 0.9 0.9 %AI9_Flatten: 1 %AI12_CMSettings: 00.MS %%EndComments endstream endobj 84 0 obj <>stream +%%BoundingBox: 0 -10 117 114 %%HiResBoundingBox: 0 -9.4248 116.3867 114 %AI7_Thumbnail: 124 128 8 %%BeginData: 28588 Hex Bytes %0000330000660000990000CC0033000033330033660033990033CC0033FF %0066000066330066660066990066CC0066FF009900009933009966009999 %0099CC0099FF00CC0000CC3300CC6600CC9900CCCC00CCFF00FF3300FF66 %00FF9900FFCC3300003300333300663300993300CC3300FF333300333333 %3333663333993333CC3333FF3366003366333366663366993366CC3366FF %3399003399333399663399993399CC3399FF33CC0033CC3333CC6633CC99 %33CCCC33CCFF33FF0033FF3333FF6633FF9933FFCC33FFFF660000660033 %6600666600996600CC6600FF6633006633336633666633996633CC6633FF %6666006666336666666666996666CC6666FF669900669933669966669999 %6699CC6699FF66CC0066CC3366CC6666CC9966CCCC66CCFF66FF0066FF33 %66FF6666FF9966FFCC66FFFF9900009900339900669900999900CC9900FF %9933009933339933669933999933CC9933FF996600996633996666996699 %9966CC9966FF9999009999339999669999999999CC9999FF99CC0099CC33 %99CC6699CC9999CCCC99CCFF99FF0099FF3399FF6699FF9999FFCC99FFFF %CC0000CC0033CC0066CC0099CC00CCCC00FFCC3300CC3333CC3366CC3399 %CC33CCCC33FFCC6600CC6633CC6666CC6699CC66CCCC66FFCC9900CC9933 %CC9966CC9999CC99CCCC99FFCCCC00CCCC33CCCC66CCCC99CCCCCCCCCCFF %CCFF00CCFF33CCFF66CCFF99CCFFCCCCFFFFFF0033FF0066FF0099FF00CC %FF3300FF3333FF3366FF3399FF33CCFF33FFFF6600FF6633FF6666FF6699 %FF66CCFF66FFFF9900FF9933FF9966FF9999FF99CCFF99FFFFCC00FFCC33 %FFCC66FFCC99FFCCCCFFCCFFFFFF33FFFF66FFFF99FFFFCC110000001100 %000011111111220000002200000022222222440000004400000044444444 %550000005500000055555555770000007700000077777777880000008800 %000088888888AA000000AA000000AAAAAAAABB000000BB000000BBBBBBBB %DD000000DD000000DDDDDDDDEE000000EE000000EEEEEEEE0000000000FF %00FF0000FFFFFF0000FF00FFFFFF00FFFFFF %524C453D373D373D373D373D373D373D373D373D373D373D373D373D373D %373D373D373D373D373D373D373D373D373D373D373D373D373D373D373D %373D373D373D373D373D373D373D373D373D373D373D373D373D373D373D %373D373D373D373D373D373D373D373D373D373D373D373D373D373D373D %373737FD04FF363736373637363736373637363736373637363736373637 %363736373637363736373637363736373637363736373637363736373637 %363736373637363736373637363736373637363736373637363736373637 %363736373637363736373637363736373637363736373637363736373637 %363736373637A9FFFFFF37373D3737373D3737373D3737373D3737373D37 %37373D3737373D3737373D3737373D3737373D3737373D3737373D373737 %3D3737373D3737373D3737373D3737373D3737373D3737373D3737373D37 %37373D3737373D3737373D3737373D3737373D3737373D3737373D373737 %3D3737373D3737373D37AFFFFFFF36373637363736373637363736373637 %363736373637363736373637363736373637363736373637363736373637 %363736373637363736373637363736373637363736373637363736373637 %363736373637363736373637363736373637363736373637363736373637 %3637363736373637363736371437A9FFFFFF3D373D373D373D373D373D37 %3D373D373D373D373D373D373D373D373D373D373D373D373D373D373D37 %3D373D373D373D373D373D373D373D373D373D373D373D373D373D373D37 %3D373D373D373D373D373D373D373D373D373D373D373D373D373D373D37 %3D373D373D373D373D373D373D373D373D37AFFFFFFF3637363736373637 %363736373637363736373637363736373637363736373637363736373637 %36373637363D2F3037373637363736373637363736373637363736373637 %363736373637363736373637363736373637363736373637363736373637 %36373637363736373637363736373637363736373637A9FFFFFF3D373737 %3D3737373D3737373D3737373D3737373D3737373D3737373D3737373D37 %37373D3737373D3737372F003D373D3737373D3737373D3737373D373737 %3D3737373D3737373D3737373D3737373D3737373D3737373D3737373D37 %37373D3737373D3737373D3737373D3737373D3737373D373737AFFFFFFF %363736373637363736373637363736373637363736373637363736373637 %36373637363736373637363730280E050D37363736373637363736373637 %363736373637363736373637363736373637363736373637363736373637 %363736373637363736373637363736373637363736373637363736373637 %A8FFFFFF3D373D373D373D373D373D373D373D373D373D373D373D373D37 %3D373D373D373D373D373D373D373D373D05280600363D373D373D373D37 %3D373D373D373D373D373D373D373D373D373D373D373D373D373D373D37 %3D373D373D373D373D373D373D373D373D373D373D373D373D373D373D37 %3D373737FD04FF3637363736373637363736373637363736373637363736 %3736373637363736373637363736373637363737362027F8063737363736 %373637363736373637363736373637363736373637363736373637363736 %373637363736373637363736373637363736373637363736373637363736 %37363736373637A9FFFFFF37373D3737373D3737373D3737373D3737373D %3737373D3737373D3737373D3737373D3737373D3737373D374C6820F82F %373D3737373D3737373D3737373D3737373D3737373D3737373D3737373D %3737373D3737373D3737373D3737373D3737373D3737373D3737373D3737 %373D3737373D3737373D37AFFFFFFF363736373637363736373637363736 %373637363736373637363736373637363736373637363736373637363D0D %8C6826F83637373637363736373637363736373637363736373637363736 %373637363736373637363736373637363736373637363736373637363736 %373637363736373637363736371437A9FFFFFF3D373D373D373D373D373D %373D373D373D373D373D373D373D373D373D373D373D373D373D373D373D %373D373745B5694A053D373D373D373D373D373D373D373D373D373D373D %373D373D373D373D373D373D373D373D373D373D373D373D373D373D373D %373D373D373D373D373D373D373D373D373D37AFFFFFFF36373637363736 %373637363736373637363736373637363736373637363736373637363736 %3736373637363737288CB04426053D373736373637363736373637363736 %373637363736373637363736373637363736373637363736373637363736 %3736373637363736373637363736373637363736373637A9FFFFFF3D3737 %373D3737373D3737373D3737373D3737373D3737373D3737373D3737373D %3737373D3737373D3737373D0D69B0B54A26073D3737373D3737373D3737 %373D3737373D3737373D3737373D3737373D3737373D3737373D3737373D %3737373D3737373D3737373D3737373D3737373D3737373D373737AFFFFF %FF3637363736373637363736373637363736373637363736373637363736 %373637363736373637363736373637363721B08D8D26200D3D3637363736 %373637363736373637363736373637363736373637363736373637363736 %373637363736373637363736373637363736373637363736373637363736 %37A8FFFFFF3D373D373D373D373D373D373D373D373D373D373D373D373D %373D373D373D373D373D373D373D373D373D373D374C8CB5B06F4A27373D %373D373D373D373D373D373D373D373D373D373D373D373D373D373D373D %373D373D373D373D373D373D373D373D373D373D373D373D373D373D373D %373D373737FD04FF36373637363736373637363736373637363736373637 %36373637363736373637363736373637363736373637363D0C8D8DB58D4B %26063737363736373637363736FD04373D36373637363736373637363736 %373637363736373637363736373637363736373637363736373637363736 %37363736373637A9FFFFFF37373D3737373D3737373D3737373D3737373D %3737373D3737373D3737373D3737373D3737373D3737373D3737373668B5 %8DB58D6F202F3737373D3737373D3737372F3636063D3737373D3737373D %3737373D3737373D3737373D3737373D3737373D3737373D3737373D3737 %373D3737373D3737373D37AFFFFFFF363736373637363736373637363736 %373637363736373637363736373637363736373637363736373637363736 %370E6F8DB08DB04474F8363737363736373637372FF837F8063737363736 %373637363736373637363736373637363736373637363736373637363736 %373637363736373637363736371437A9FFFFFF3D373D373D373D373D373D %373D373D373D373D373D373D373D373D373D373D373D373D373D373D373D %373D373D373D4BB58DB5B0B04A75053D373D373D373D3736F8360CF8373D %373D373D373D373D373D373D373D373D373D373D373D373D373D373D373D %373D373D373D373D373D373D373D373D373D37AFFFFFFF36373637363736 %373637363736373637363736373637363736373637363736373637363736 %373637363736373637154C8CB08DB5B069744A0D3736373637363721270E %F8063D363736373637363736373637363736373637363736373637363736 %3736373637363736373637363736373637363736373637A9FFFFFF3D3737 %373D3737373D3737373D3737373D3737373D3737373D3737373D3737373D %3737373D3737373D3737373D373D27B5B0B58DB58D7598273737373D373D %28682F06F8363737373D3737373D3737373D3737373D3737373D3737373D %3737373D3737373D3737373D3737373D3737373D3737373D373737AFFFFF %FF3637363736373637363736373637363736373637363736373637363736 %373637363736373637363736373637363715288CB58DB08DB044C1203037 %3736370E454406F827143736373637363736373637363736373637363736 %373637363736373637363736373637363736373637363736373637363736 %37A8FFFFFF3D373D373D373D373D373D373D373D373D373D373D373D373D %373D373D373D373D373D373D373D373D373D373D373D28B5B0B58DB5B04B %C14A0D3D373D372E8C4B044A0661373D373D373D373D373D373D373D373D %373D373D373D373D373D373D373D373D373D373D373D373D373D373D373D %373D373737FD04FF36373637363736373637363736373637363736373637 %36373637363736373637363736373637363736373637363737288CB58DB0 %8D8D4A9FF8FD04373644B0F8754A0D373736373637363736373637363736 %373637363736373637363736373637363736373637363736373637363736 %37363736373637A9FFFFFF37373D3737373D3737373D3737373D3737373D %3737373D3737373D3737373D3737373D3737373D3737373D3737373D27B0 %8DB58DB5449F4A0D373D373D27B08D269F4B0E3D373D3737373D3737373D %3737373D3737373D3737373D3737373D3737373D3737373D3737373D3737 %373D3737373D3737373D37AFFFFFFF363736373637363736373637363736 %373637363736373637363736373637363736373637363736373637363736 %370E4B8DB08DB5684A98F80E37363D0D68B08D4AC1203637373637363736 %373637363736373637363736373637363736373637363736373637363736 %373637363736373637363736371437A9FFFFFF3D373D373D373D373D373D %373D373D373D373D373D373D373D373D373D373D373D373D373D373D373D %373D373D373668B58DB5B04B9F75063D373D37288CB68D75C127363D373D %373D373D373D373D373D373D373D373D373D373D373D373D373D373D373D %373D373D373D373D373D373D373D373D373D37AFFFFFFF36373637363736 %373637363736373637363736373637363736373637363736373637363736 %373637363736373637068D8DB08D8D4AC1F8FD04373644B08D8D4AC1F837 %373736373637363736373637363736373637363736373637363736373637 %36373637363736373637363736373637363736373637A9FFFFFF3D373737 %3D3737373D3737373D3737373D3737373D3737373D3737373D3737373D37 %37373D3737373D3737373D144BB0B5B0B544C16E06373D373D27B0B0B58D %75C127143D3737373D3737373D3737373D3737373D3737373D3737373D37 %37373D3737373D3737373D3737373D3737373D3737373D373737AFFFFFFF %363736373637363736373637363736373637363736373637363736373637 %3637363736373637363736373637152868B08DB56875BA260E3736370E45 %8DB58D8D4AC1203636373637363736373637363736373637363736373637 %363736373637363736373637363736373637363736373637363736373637 %A8FFFFFF3D373D373D373D373D373D373D373D373D373D373D373D373D37 %3D373D373D373D373D373D373D373D373D372F68B58DB5B04B9F99063D37 %3D372F8CB6B0B58D6FC14B0E3D373D373D373D373D373D373D373D373D37 %3D373D373D373D373D373D373D373D373D373D373D373D373D373D373D37 %3D373737FD04FF3637363736373637363736373637363736373637363736 %37363736373637363736373637363736373637370E44B58DB08D8D4AC120 %303737363721B08DB58DB044C14A0D373736373637363736373637363736 %373637363736373637363736373637363736373637363736373637363736 %37363736373637A9FFFFFF37373D3737373D3737373D3737373D3737373D %3737373D3737373D3737373D3737373D3737373D3737373644B08DB58DB5 %44C19805373D373D0D6FB0B58DB5B06F9875073D373D3737373D3737373D %3737373D3737373D3737373D3737373D3737373D3737373D3737373D3737 %373D3737373D3737373D37AFFFFFFF363736373637363736373637363736 %37363736373637363736373637363736373637363736373637373620B08D %B08DB5694AC14A06373637372E68B58DB08DB568756E0637373637363736 %373637363736373637363736373637363736373637363736373637363736 %373637363736373637363736371437A9FFFFFF3D373D373D373D373D373D %373D373D373D373D373D373D373D373D373D373D373D373D373D373D373D %27B5B0B58DB5B06974C12036373D373D27B5B0B58DB5B08D6EC1053D373D %373D373D373D373D373D373D373D373D373D373D373D373D373D373D373D %373D373D373D373D373D373D373D373D373D37AFFFFFFF36373637363736 %3736373637363736373637363736373637363736373637363736FD053736 %3D068CB0B58DB08DB044C174063737363D1469B0B58DB08DB58D4B982714 %373637363736373637363736373637363736373637363736373637363736 %373637363736373637363736373637363736373637A9FFFFFF3D3737373D %3737373D3737373D3737373D3737373D3737373D3737373D3737373D2F2F %3737373D0E69B0B58DB58DB56975C16E073D3737373668B58DB58DB58DB5 %689F26303737373D3737373D3737373D3737373D3737373D3737373D3737 %373D3737373D3737373D3737373D3737373D3737373D373737AFFFFFFF36 %373637363736373637363736373637363736371537363736373637363736 %3714212736F83737278CB58DB08DB5B0696EC120303737363D068D8DB08D %B58DB08D8D6E74053D373736373637363736373637363736373637363736 %3736373637363737373637363736373637363736373637363736373637A8 %FFFFFF3D373D373D373D373D373D373D373D373D373D375A2E2E272E272E %272E272E2727684BF820272768B6B0B58DB5B0B5689FC1272752272E274B %B0B58DB5B0B58DB58D6F9827272E272E272E272E272E272E272E272E272E %272E272E272E272E272E272E2F61373D373D373D373D373D373D373D373D %373737FD04FF3637363736373637363736373637363736373759FD0CF844 %93FD04F820B08DB58DB08DB58D69989FFD06F820B58DB08DB58DB08DB544 %9926FD1FF82E37373736373637363736373637363736373637A9FFFFFF37 %373D3737373D3737373D3737373D3737376127FD0CF8B568FD04F86FB0B5 %8DB58DB58DB5689F9926FD05F845B0B58DB58DB58DB5B08D6E99FD1FF826 %2F3D3737373D3737373D3737373D3737373D37AFFFFFFF36373637363736 %37363736373637363736373027FD0BF845B044FD04F88CB58DB08DB58DB0 %8D69989FFD06F844B08DB58DB08DB58DB08D4B9820FD1FF82F3737363736 %37363736373637363736371437A9FFFFFF3D373D373D373D373D373D373D %373D373D375AFD0CF88DB5FD04F820B5B0B58DB5B0B58DB669999F27FD05 %F86FB0B5B0B58DB5B0B58DB669756EFD1FF82F3D373D373D373D373D373D %373D373D373D37AFFFFFFF3637363736373637363736373637363736372F %27FD0AF820B568FD04F845B0B58DB08DB58DB08D8D4AC120FD05F844B08D %B58DB08DB58DB08DB0449FFD1FF82F373736373637363736373637363736 %373637A9FFFFFF3D3737373D3737373D3737373D3737373D375AFD0BF869 %B0692626F8F869B58DB58DB58DB58DB5B06F9975FD05F86FB0B58DB58DB5 %8DB58DB5B0697475FD1EF82F3D373D3737373D3737373D3737373D373737 %AFFFFFFF3637363736373637363736373637363736373020FD0AF88DB020 %7520F8F88D8DB08DB58DB08DB58DB08C4B98FD05F820B58DB08DB58DB08D %B58DB08D4B9820FD1DF82F373736373637363736373637363736373637A8 %FFFFFF3D373D373D373D373D373D373D373D373D375AFD0AF844B58D4B99 %26F8218DB58DB5B0B58DB5B0B58DB669756EFD04F827B0B58DB5B0B58DB5 %B0B58DB6697574FD1CF8202F3D373D373D373D373D373D373D373D373737 %FD04FF3637363736373637363736373637363736373626FD09F869B08D4A %C1F8F8F893B0B08DB58DB08DB58DB08DB5449920FD04F8938DB08DB58DB0 %8DB58DB08DB5449F4AFD1CF8533737363736373637363736373637363736 %37A9FFFFFF37373D3737373D3737373D3737373D3737375AFD09F8208DB5 %8D75C126F8F868B58DB58DB58DB58DB58DB5B0B54A99FD04F868B58DB58D %B58DB58DB58DB5B0B54AC1FD1CF82F3D3737373D3737373D3737373D3737 %373D37AFFFFFFF3637363736373637363736373637363736372F27FD08F8 %20B08D8D4AC1207E7D698DB58DB08DB58DB08DB58DB08D8D4A74F87E7D4B %8CB58DB08DB58DB08DB58DB08D694A9FF87DA8A87DA87DA87DA87DA87DA8 %7D52FD0BF82F373736373637363736373637363736371437A9FFFFFF3D37 %3D373D373D373D373D373D373D373D375AFD09F86FB0B58D6FC14BA8FF4B %B5B0B58DB5B0B58DB5B0B58DB5B08D4A7527FF7D8DB0B58DB5B0B58DB5B0 %B58DB5B069749F27AFFD0DFF52FD0AF82F3D373D373D373D373D373D373D %373D373D37AFFFFFFF3637363736373637363736373637363736372F27FD %07F8208DB08DB044C14A7DFF7668B58DB08DB58DB08DB58DB08DB5B0694A %4A27FF4BB08DB08DB58DB08DB58DB08DB5B0457499F8A8FD0CFF27FD0AF8 %2F373736373637363736373637363736373637A9FFFFFF3D3737373D3737 %373D3737373D3737373D375AFD08F820B5B0B5B06FC17452FF8469B0B58D %B58DB58DB58DB58DB58DB5B0694A4A52A868B58DB58DB58DB58DB58DB58D %B5B04B9F7527FD0CFF52FD0AF82F3D373D3737373D3737373D3737373D37 %3737AFFFFFFF3637363736373637363736373637363736373020FD07F845 %8DB58DB0449F7427FFFF4B8D8DB58DB08DB58DB08DB58DB08DB5B0694A4A %2E528CB58DB08DB58DB08DB58DB08DB58D4A98207DFD0BFF27FD0AF82F37 %3736373637363736373637363736373637A8FFFFFF3D373D373D373D373D %373D373D373D373D375AFD08F869B6B0B5B09374C120FFFF7D68B6B0B58D %B5B0B58DB5B0B58DB5B0B5B06F744B2E6FB0B58DB5B0B58DB5B0B58DB5B0 %B5689F7452FD0BFF52FD09F8202F3D373D373D373D373D373D373D373D37 %3737FD04FF3637363736373637363736373637363736373626FD07F88D8D %B58DB08D6FC14A52FFA84B8CB58DB08DB58DB08DB58DB08DB58DB08D4B74 %27278DB0B08DB58DB08DB58DB08DB58DB0449F20A8FD0AFF27FD0AF85337 %3736373637363736373637363736373637A9FFFFFF37373D3737373D3737 %373D3737373D3737375AFD07F821B0B58DB5B0B544C19827FFFF7D8DB0B5 %8DB58DB58DB58DB58DB58DB58DB58D75740545B5B0B58DB58DB58DB58DB5 %8DB5B069747452FD0AFF52FD0AF82F3D3737373D3737373D3737373D3737 %373D37AFFFFFFF3637363736373637363736373637363736372F27FD06F8 %20B58DB08DB58D694AC120A8FFAF44B08DB58DB08DB58DB08DB58DB08DB5 %8DB044994AF868B58DB08DB58DB08DB58DB08DB58D4B6E27FD0AFF27FD0A %F82F373736373637363736373637363736371437A9FFFFFF3D373D373D37 %3D373D373D373D373D373D375AFD07F86FB0B58DB5B0B58D4BC17527FFFF %7D68B6B0B58DB5B0B58DB5B0B58DB5B0B5B0B54A9FF84BB0B58DB5B0B58D %B5B0B58DB5B0B5687526A9FD09FF52FD0AF82F3D373D373D373D373D373D %373D373D373D37AFFFFFFF3637363736373637363736373637363736372F %27FD06F868B58DB08DB58DB06875C12084FFA84B8DB58DB08DB58DB08DB5 %8DB08DB58DB0B0697475F893B0B08DB58DB08DB58DB08DB58D8D4A4A59FD %09FF27FD0AF82F373736373637363736373637363736373637A9FFFFFF3D %3737373D3737373D3737373D3737373D375AFD07F893B0B58DB58DB5B0B0 %44C14A52FFFF528DB0B58DB58DB58DB58DB58DB58DB58DB58D6F9F0444B5 %B0B58DB58DB58DB58DB58DB5B06F4A52FD09FF52FD0AF82F3D373D373737 %3D3737373D3737373D373737AFFFFFFF3637363736373637363736373637 %363736373020FD06F868B08DB58DB08DB5B0694AC1F884FFAF44B08DB58D %B08DB58DB08DB58DB08DB58DB0449F4AF88CB58DB08DB58DB08DB58DB08D %B5684A26FD09FF27FD0AF82F373736373637363736373637363736373637 %A8FFFFFF3D373D373D373D373D373D373D373D373D375AFD07F893B0B5B0 %B58DB5B0B5B06F9F9927FFFF7D68B6B0B58DB5B0B58DB5B0B58DB5B0B5B0 %934A9FF893B0B58DB5B0B58DB5B0B58DB5B0B54A4B84FD08FF52FD09F820 %2F3D373D373D373D373D373D373D373D373737FD04FF3637363736373637 %363736373637363736373626FD05F8208DB08DB58DB08DB58DB08C4BC126 %52FFA8458DB58DB08DB58DB08DB58DB08DB58DB08D694A2620B58DB08DB5 %8DB08DB58DB08DB58D6F207DFD08FF27FD0AF85337373637363736373637 %3637363736373637A9FFFFFF37373D3737373D3737373D3737373D373737 %5AFD07F893B0B58DB58DB58DB58DB568759F27A8FF528DB0B58DB58DB58D %B58DB58DB58DB58DB5B06F206FB0B58DB58DB58DB58DB58DB58DB5694A52 %FD08FF52FD0AF82F3D3737373D3737373D3737373D3737373D37AFFFFFFF %3637363736373637363736373637363736372F27FD06F868B58DB08DB58D %B08DB58DB0449F4A27FFAF44B08DB58DB08DB58DB08DB58DB08DB58DB08D %B08DB08DB58DB08DB58DB08DB58DB08D8D2027FD08FF27FD0AF82F373736 %373637363736373637363736371437A9FFFFFF3D373D373D373D373D373D %373D373D373D375AFD07F86FB0B58DB5B0B58DB5B0B5B0B544C1207EFF7D %68B6B0B58DB5B0B58DB5B0B58DB5B0B58DB5B0B58DB5B0B58DB5B0B58DB5 %B0B58DB5B04B26FD08FF52FD0AF82F3D373D373D373D373D373D373D373D %373D37AFFFFFFF3637363736373637363736373637363736372F27FD06F8 %20B58DB08DB58DB08DB58DB08D8D4A99F8FFA8458DB58DB08DB58DB08DB5 %8DB08DB58DB08DB58DB08DB58DB08DB58DB08DB58DB08DB568207DFD07FF %27FD0AF82F373736373637363736373637363736373637A9FFFFFF3D3737 %373D3737373D3737373D3737373D375AFD07F8208DB58DB58DB58DB58DB5 %8DB5B0696E7427FF4BB08DB58DB58DB58DB58DB58DB58DB58DB58DB58DB5 %8DB58DB58DB58DB58DB58DB5B093F87DFD07FF52FD0AF82F3D373D373737 %3D3737373D3737373D373737AFFFFFFF3637363736373637363736373637 %363736373020FD07F8698DB58DB08DB58DB08DB58DB08D696E267E7D68B0 %8DB58DB08DB58DB08DB58DB08DB58DB08DB58DB08DB58DB08DB58DB08DB5 %8DB0682652FD07FF27FD0AF82F3737363736373637363736373637363736 %37A8FFFFFF3D373D373D373D373D373D373D373D373D375AFD08F820B5B0 %B58DB5B0B58DB5B0B58DB5B06F4A52A869B0B5B0B58DB5B0B58DB5B0B58D %B5B0B58DB5B0B58DB5B0B58DB5B0B58DB5B0B5B0B5442DFD07FF52FD09F8 %202F3D373D373D373D373D373D373D373D373737FD04FF36373637363736 %37363736373637363736373626FD08F868B58DB08DB58DB08DB58DB08DB5 %694A26846FB08DB58DB08DB58DB08DB58DB08DB58DB08DB58DB08DB58DB0 %8DB58DB08DB58DB08D4A26FD07FF27FD0AF8533737363736373637363736 %37363736373637A9FFFFFF37373D3737373D3737373D3737373D3737375A %FD09F845B0B58DB58DB58DB58DB58DB58DB5684A52768DB58DB58DB58DB5 %8DB58DB58DB58DB58DB58DB58DB58DB58DB58DB58DB58DB58DB54427A8FD %06FF52FD0AF82F3D3737373D3737373D3737373D3737373D37AFFFFFFF36 %37363736373637363736373637363736372F27FD09F8698DB58DB08DB58D %B08DB58DB08D8D202620B08DB08DB58DB08DB58DB08DB58DB08DB58DB08D %B58DB08DB58DB08DB58DB08DB58D6FF87DFD06FF27FD0AF82F3737363736 %37363736373637363736371437A9FFFFFF3D373D373D373D373D373D373D %373D373D375AFD0AF820B5B0B58DB5B0B58DB5B0B58DB5B06F264BB0B58D %B5B0B58DB5B0B58DB5B0B58DB5B0B58DB5B0B58DB5B0B58DB5B0B58DB5B0 %B5684A7DFD06FF52FD0AF82F3D373D373D373D373D373D373D373D373D37 %AFFFFFFF3637363736373637363736373637363736372F27FD0AF868B58D %B08DB58DB08DB58DB08DB58D6968B58DB08DB58DB08DB58DB08DB58DB08D %B58DB08DB58DB08DB58DB08DB58DB08DB58D6F4A52FD06FF27FD0AF82F37 %3736373637363736373637363736373637A9FFFFFF3D3737373D3737373D %3737373D3737373D375AFD0BF8208DB58DB58DB58DB58DB58DB58DB5B0B5 %8DB58DB58DB58DB58DB58DB58DB58DB58DB58DB58DB58DB58DB58DB58DB5 %8DB58DB5697427FD06FF52FD0AF82F3D373D3737373D3737373D3737373D %373737AFFFFFFF3637363736373637363736373637363736373020FD0BF8 %698DB58DB08DB58DB08DB58DB08DB58DB08DB58DB08DB58DB08DB58DB08D %B58DB08DB58DB08DB58DB08DB58DB08DB58DB08D6F7427A8FD05FF27FD0A %F82F373736373637363736373637363736373637A8FFFFFF3D373D373D37 %3D373D373D373D373D373D375AFD0BF852528DB0B58DB5B0B58DB5B0B58D %B5B0B58DB5B0B58DB5B0B58DB5B0B58DB5B0B58DB5B0B58DB5B0B58DB5B0 %B58DB5B0B58DB56E9F26FD06FF52FD09F8202F3D373D373D373D373D373D %373D373D373737FD04FF3637363736373637363736373637363736373626 %FD0AF827FF45B08DB08DB58DB08DB58DB08DB58DB08DB58DB08DB58DB08D %B58DB08DB58DB08DB58DB08DB58DB08DB58DB08DB58DB08D4BC14A7DFD05 %FF27FD0AF853373736373637363736373637363736373637A9FFFFFF3737 %3D3737373D3737373D3737373D3737375AFD0BF852FFA844B5B0B58DB58D %B58DB58DB58DB58DB58DB58DB58DB58DB58DB58DB58DB58DB58DB58DB58D %B58DB58DB58DB58DB5B08D4AC7207DFD05FF52FD0AF82F3D3737373D3737 %373D3737373D3737373D37AFFFFFFF363736373637363736373637363736 %3736372F27FD0AF827FFFF5268B58DB08DB58DB08DB58DB08DB58DB08DB5 %8DB08DB58DB08DB58DB08DB58DB08DB58DB08DB58DB08DB58DB08DB0449F %4A27A8FD05FF27FD0AF82F373736373637363736373637363736371437A9 %FFFFFF3D373D373D373D373D373D373D373D373D375AFD0BF852FFFFFF4C %8DB58DB5B0B58DB5B0B58DB5B0B58DB5B0B58DB5B0B58DB5B0B58DB5B0B5 %8DB5B0B58DB5B0B58DB5B0B58DB58D757427FD07FF52FD0AF82F3D373D37 %3D373D373D373D373D373D373D37AFFFFFFF363736373637363736373637 %3637363736372F27FD0AF827FFFFFFA84B8DB08DB58DB08DB58DB08DB58D %B08DB58DB08DB58DB08DB58DB08DB58DB08DB58DB08DB58DB08DB58DB0B0 %6F4A26A8FD07FF27FD0AF82F373736373637363736373637363736373637 %A9FFFFFF3D3737373D3737373D3737373D3737373D375AFD0BF852FD04FF %7D69B0B58DB58DB58DB58DB58DB58DB58DB58DB58DB58DB58DB58DB58DB5 %8DB58DB58DB58DB58DB58DB5B09320267DFD08FF52FD0AF82F3D373D3737 %373D3737373D3737373D373737AFFFFFFF36373637363736373637363736 %37363736373020FD0BF8FD05FF7D69B0B08DB58DB08DB58DB08DB58DB08D %B58DB08DB58DB08DB58DB08DB58DB08DB58DB08DB58DB08DB044F87DFD09 %FFFD0BF82F373736373637363736373637363736373637A8FFFFFF3D373D %373D373D373D373D373D373D373D375AFD0CF8277D52525259F869B0B5B0 %B58DB5B0B58DB5B0B58DB5B0B58DB5B0B58DB5B0B58DB5B0B58DB5B0B58D %B5B0B58DB669F8F87DFD07527D27FD0AF8202F3D373D373D373D373D373D %373D373D373737FD04FF3637363736373637363736373637363736373626 %FD13F88DB0B58DB08DB58DB08DB58DB08DB58DB08DB58DB08DB58DB08DB5 %8DB08DB58DB08DB58DB06820FD17F8533737363736373637363736373637 %36373637A9FFFFFF37373D3737373D3737373D3737373D3737375AFD15F8 %93B0B58DB58DB58DB58DB58DB58DB58DB58DB58DB58DB58DB58DB58DB58D %B58DB58DB58D20FD18F82F3D3737373D3737373D3737373D3737373D37AF %FFFFFF3637363736373637363736373637363736372F27FD15F869B0B58D %B08DB58DB08DB58DB08DB58DB08DB58DB08DB58DB08DB58DB08DB58DB08C %20FD19F82F373736373637363736373637363736371437A9FFFFFF3D373D %373D373D373D373D373D373D373D375AFD17F893B0B58DB5B0B58DB5B0B5 %8DB5B0B58DB5B0B58DB5B0B58DB5B0B58DB5B0B58D27FD1AF82F3D373D37 %3D373D373D373D373D373D373D37AFFFFFFF363736373637363736373637 %3637363736372F27FD17F869B0B08DB58DB08DB58DB08DB58DB08DB58DB0 %8DB58DB08DB58DB08DB56820FD1BF82F3737363736373637363736373637 %36373637A9FFFFFF3D3737373D3737373D3737373D3737373D375AFD19F8 %4B8DB58DB58DB58DB58DB58DB58DB58DB58DB58DB58DB58DB5B0B544FD1D %F82F3D373D3737373D3737373D3737373D373737AFFFFFFF363736373637 %3637363736373637363736373620FD19F82068B08DB58DB08DB58DB08DB5 %8DB08DB58DB08DB58DB08D8D20FD1EF85337373637363736373637363736 %3736373637A8FFFFFF3D373D373D373D373D373D373D373D373D375B27FD %1BF820938DB5B0B5B0B58DB5B0B58DB5B0B5B0B6B0B5696F20FD1EF82736 %3D373D373D373D373D373D373D373D373737FD04FF363736373637363736 %3736373637363736373736FD1DF82044698DB5B0B0B0B5B0B0B0B58D8D68 %6F4A4AFD1FF8202E3D373736373637363736373637363736373637A9FFFF %FF37373D3737373D3737373D3737373D3737373D375A2E2E282E282E282E %282E282E282E282E282E282E282E282E282E282E27F8F820204B4469446F %696F446F6E997451FD04F82752282E282E282E282E282E282E282E282E28 %2E282E282E282E28522F37373D3737373D3737373D3737373D3737373D37 %AFFFFFFF3637363736373637363736373637363736373637373736373737 %3637373736373737363737373637373736373737363D3627FD09F8262675 %989F4AFD06F8262F37363737373637373736373737363737373637373736 %37373736373637363736373637363736373637363736371437A9FFFFFF3D %373D373D373D373D373D373D373D373D373D373D373D373D373D373D373D %373D373D373D373D373D373D373D373D3753FD0DF827FD09F852373D373D %373D373D373D373D373D373D373D373D373D373D373D373D373D373D373D %373D373D373D373D373D373D37AFFFFFFF36373637363736373637363736 %373637363736373637363736373637363736373637363736373637363736 %373637375AFD19F853373736373637363736373637363736373637363736 %37363736373637363736373637363736373637363736373637A9FFFFFF3D %3737373D3737373D3737373D3737373D3737373D3737373D3737373D3737 %373D3737373D3737373D3737373D375B27FD19F8265A373D3737373D3737 %373D3737373D3737373D3737373D3737373D3737373D3737373D3737373D %3737373D373737AFFFFFFF36373637363736373637363736373637363736 %37363736373637363736373637363736373637363736373637155A27FD1C %F85A37373637363736373637363736373637363736373637363736373637 %36373637363736373637363736373637A8FFFFFF3D373D373D373D373D37 %3D373D373D373D373D373D373D373D373D373D373D373D373D373D373D37 %3D373D375A27FD1DF82059373D373D373D373D373D373D373D373D373D37 %3D373D373D373D373D373D373D373D373D373D373D373737FD04FF363736 %373637363736373637363736373637363736373637363736373637363736 %37363736373637373D362EFD21F82E2F3737373637363736373637363736 %373637363736373637363736373637363736373637363736373637A9FFFF %FF37373D3737373D3737373D3737373D3737373D3737373D3737373D3737 %373D3737373D3737373D365A2827FD23F8272859363D3737373D3737373D %3737373D3737373D3737373D3737373D3737373D3737373D3737373D37AF %FFFFFF363736373637363736373637363736373637363736373637363736 %37363736373637363736373027FD29F8272F373637363736373637363736 %37363736373637363736373637363736373637363736371437A9FFFFFF3D %373D373D373D373D373D373D373D373D373D373D373D373D373D373D373D %373D373D373D375AFD2B275A373D373D373D373D373D373D373D373D373D %373D373D373D373D373D373D373D373D373D37AFFFFFFF36373637363736 %373637363736373637363736373637363736373637363736373637363736 %373637363736373637363736373637363736373637363736373637363736 %373637363736373637363736373637363736373637363736373637363736 %3736373637363736373637363736373637363736373637A9FFFFFF3D3737 %373D3737373D3737373D3737373D3737373D3737373D3737373D3737373D %3737373D3737373D3737373D3737373D3737373D3737373D3737373D3737 %373D3737373D3737373D3737373D3737373D3737373D3737373D3737373D %3737373D3737373D3737373D3737373D3737373D3737373D373737AFFFFF %FF3637363736373637363736373637363736373637363736373637363736 %373637363736373637363736373637363736373637363736373637363736 %373637363736373637363736373637363736373637363736373637363736 %373637363736373637363736373637363736373637363736373637363736 %37A8FFFFFF3D373D373D373D373D373D373D373D373D373D373D373D373D %373D373D373D373D373D373D373D373D373D373D373D373D373D373D373D %373D373D373D373D373D373D373D373D373D373D373D373D373D373D373D %373D373D373D373D373D373D373D373D373D373D373D373D373D373D373D %373D373737FD04FF36373637363736373637363736373637363736373637 %363736373637363736373637363736373637363736373637363736373637 %363736373637363736373637363736373637363736373637363736373637 %363736373637363736373637363736373637363736373637363736373637 %3637363736373637A9FFFFFF37373D3737373D3737373D3737373D373737 %3D3737373D3737373D3737373D3737373D3737373D3737373D3737373D37 %37373D3737373D3737373D3737373D3737373D3737373D3737373D373737 %3D3737373D3737373D3737373D3737373D3737373D3737373D3737373D37 %37373D3737373D3737373D37AFFFFFFF3637363736373637363736373637 %363736373637363736373637363736373637363736373637363736373637 %363736373637363736373637363736373637363736373637363736373637 %363736373637363736373637363736373637363736373637363736373637 %36373637363736373637363736371437A9FFFFFF37373D3737373D373737 %3D3737373D3737373D3737373D3737373D3737373D3737373D3737373D37 %37373D3737373D3737373D3737373D3737373D3737373D3737373D373737 %3D3737373D3737373D3737373D3737373D3737373D3737373D3737373D37 %37373D3737373D3737373D3737373D3737373D37AFFFFFFF363736373637 %363736373637363736373637363736373637363736373637363736373637 %363736373637363736373637363736373637363736373637363736373637 %363736373637363736373637363736373637363736373637363736373637 %363736373637363736373637363736373637363736371437A9FFFFFFAFA9 %AFA9AFA9AFA9AFA9AFA9AFA9AFA9AFA9AFA9AFA9AFA9AFA9AFA9AFA9AFA9 %AFA9AFA9AFA9AFA9AFA9AFA9AFA9AFA9AFA9AFA9AFA9AFA9AFA9AFA9AFA9 %AFA9AFA9AFA9AFA9AFA9AFA9AFA9AFA9AFA9AFA9AFA9AFA9AFA9AFA9AFA9 %AFA9AFA9AFA9AFA9AFA9AFA9AFA9AFA9AFA9AFA9AFA9AFA9AFA9AFA9FDFC %FFFDFCFFFDFCFFFDFCFFFD6FFFFF %%EndData endstream endobj 85 0 obj <>stream +%AI12_CompressedDataxœì½û²Éq§ùõgÿ Ûv åýÂ]³sÕrF¼›ÒhV6ÖuCFh  ––ûôîñû<<ꠛM‘\‘;DlDœª¬S‘_º{ÆWùƒÿåŸþèö‹wÿøêGó‹áæòƒÜ¿õòû÷?¾ñޛŸ¼yóÍ×Þ[×ùÉÍXžUžtû“ã3=ñï^½ÿúõ»·?öùŸìÕ?üÏ/¿|ýêæÿzùo¯ß~ý/¯?¹ùá'åG¿zýáÍ«òÃן¾ü×WïùÍÛ·¯Þ¿xùúÞ·lèáå‡òŒí¯–¿§›éÇóp󋟖ß½ûæí¯ßþúîÝÿýã›áæGãp3Ž{ù»”þŸ¯ùêëëgœ/–i9Ê3¶ó±ñԇwŸóå«·~ñþÝ篾þúþݛwï¿þñÍýo^¾½ùéË_—Ÿ¼¼ùo¯Þ¼y÷o7wo^~þ/—òY×Ϟ^¿yU>֗/?ܜöo2NŸÝ}óúÍ?ûæË|U>ï2lÖ=æ[üۯ˦ÊVíßÖ½ö“/Kϧ¯>|(¿ay¿!ý*÷e¿û’ß䇿¸ýÙ¯~þ³Ç›qnîÿîÞöÍÿÚz—c¥÷þ§ÿí¿¤×ڇ^¬ãÍXþññ­ ö³g÷„´Á_þõ]Þ-¾A{ê?üòÕ¯_û$(ãóß?©ŸóW¯¾üêM+ßÝëþb½Y7û?þ¥g•çÏøÑ4åÿÎóf^֛eÖÏÛp¼ú×ׯþíÇ7?{÷öUÝç·ï?|úúÿ){± \<ëýå7o^½ÿÛ·¯?”]å{ü¬{ü§ï¾xõ¦<7^ûôæ¥ïhŒíÿë~õòý¯_}(³æݛo>øô=ý¨Œèß¼üÍ+‹±¾ÁÏ¿zõöWïþο•YiÏ&ÖY69çÍxø¦çù¼9뻌7uôëØìålw/;ûe>üüýë_¿~ûcýVûgýþõmŽŒƒm?þãÃ{¤¿'ëoY>ð‡¯Þê·.óóþ§i¾ /~úiy×Ç·_Ü¿ûÒöø×vP•q}[†üÍ»_ןſý'ååß|U?·?+ƒó‹÷¯ßÚ6/?óŸŸýâÍ7åGýþÝ7_ýäí?½»ü°rã/?üs9‚^½ýâërì×¾Ú¼©¯(½óú__վ€¯>ùÎíýêýËÏËÛÞüüÿÇ«Ï?”«£ýëÓo^xõÛ7ôé綛Þßܽÿæë¾ùÕ»woâ÷뿦º½×žÿ§ñ¿ð¼ýùÛº§Ÿ¿“žpýNåÐø“{—òìo‡òÃ?å­ß¿|óæõ¯ß¿üêŸ_þ±7øÈÏãêÏ~‡7+ÇøûWíõÞä¿ßcZþæË|÷æõ×_¶Ù˜z~ñòý‡×Ÿ¿yõéo¾þðêËß¾µ‡WÿTΈi·yïãÛ}õæÝW闌ž—o¿¸ù¯/ßõ]›¶aú§×o¿(GˆÏm7¾ûò+;Áß|úÏ/¿zå¿î‡~òg~ú=¦ñ›—o_¾¿ñþؤá§Ìß³Iµ/6º~VÀ˜Ñ÷£}כ»·éÇýþå¯ ml›~ûʇÚs3~rùH_¡üts÷Åå.ÿÇe¨ÆaæaÖò؆}8†³mÃ6nÓ6o˶mûvlçv»Ým÷ÛÃö¸=mOû°û´Ïû²¯û¶ïû±Ÿûí~wÙï÷‡ýqڟŽ¡|Žé(¿ÎQB”c;ÊsŽã8Ûãî¸÷¿Çcy<ÙÞ8Çs:çs)õ,ïvîgyêy^ÎÛò¸;ïËã¡<Ëãé|º-»ï¶ì"Û ·åóÞ.þXË£ü¢·åW¹-ïc/½­îÊÃÿ{ñÞÝÞëñ Ç£?žìq7øcôGÙɗÿÔƲŽ¦§èâ#ʘÞƘ> >®ß1²—2°ãc nÞ2º6¶‡îÝtï£[Çw¼ác>¯Fy¼Ä0oe˜Ï²;æaÓ8ï>ζ«êX?v£½”‰ ¿hȯý#Ã^F]ã^Fý[Çý¢¡×°§>ôö§ŽüÇÇÞÇýCŸ¾ }|ø÷Ë;åc¡Œ$cYGRcYGRj§ýX>Éýc#¹L—îýíci#™Ç²>êˆÚ¡½]t×ØùQcʡ̨Öq½YÑۋ® ïæÃˁ]Ç÷z„cF™qÖAnc}IƒÝ†Û<îò~Ð÷cùúóÿáÇô˜â1§ùXg¤ÍÉD˜ Óò£§Ž:)Yê\¬3Ñæa;_ÔxÎw—2ù}âÍ>çêIâÁNe®-~f¸-óËf×XæÔZ&ÓY&ÑC™>c™8k™0·eš<– 2•9±_ʨޏeè§2Ü{Þ»óÁÚ¥£G9 +eÇ»ùn½ÛË ßÝ=øX>===>=<Ý?Ý +Ÿeúì…:ëÓò4?MOãÓðøôøøøðxÿxWX}–)¶—9¼>–ãq.¤‡‡§‡Ç‡‡‡û‡»ÂôóRfâþ°=¬ËÃü0à÷O÷÷÷÷÷wçýQ¦÷VŽå~¾ŸÊÙv¸{º{¼{¸»/¿Ómù͎òûmå·\Êï:ݍ—»¡œ ˯o0±3ÊY>Î^>ÔZ>Ú\>àx;” ûX¦ï}ùзå£eleÆ/eöOåHÊqñXŽ;Þڞ:Ê´•Ý¶”ãj*Ç×PŽµÇrÌݗ£ï¶#GÙ½e—ݼ”=•]>?–Ý_ᶠÅQ~¼•aY¶ùRŽúqÖ§2ZeÌîÊȝeüö2Šk˹Œè¸ËSÙi…*we¬Ï2â{÷µ0g.ḠóSÑcAÒý¥°é¶Ì’£Ì•­Ì™¥Ìœ©Pl˜žÊ\z(3ꮎg™_{!ÞZfÛüûåGGòá¸üaGòn¸ÄHþÆцñò½Æñ{bÄËdË2„—ï?†å,6NÃøô?ÉX^æå{•ß{4/ c2Fóò»‘u4ËX.7?øìî}IN¬œ¶ÖÚTéùôòƒÏRÏÝח±¶â§Ñ.?+´&­"ñù~Óô‘Œi²Œi‰ŒÉÎsäGÄ`÷ådÇéÎNx³ŸðˆÄì´Gd}z„p¯Ì©L½Ëøq™ ílhçC‹Î,>#B»õ}vïqš¢nÿûägK‹Ú,n+g͋oKÙñ›Ÿ@ â,Œ³@îփ9 çî}¬ìÿœ¥Oö°Q\üänÀ~—‹çgî-úÿ5=6Ûãð‡GQžñÔÿ¿õögvw—øgyøáë“éðmm>¥V½Ûìïí“ËþkÖǽ·ñ8ô(ùR>ùª‰WÿØî)»I»Í÷ñ¸ÇáÛå›?êԜ-¯}|ô°1+2|>ŒõáŸ5ˆu}B,>5æq¼ŒñÇæM<âq?Üu[Ÿs<öëÇŃ1=|§:„V‡ÐbIâÝ ‚@ð§Ñç6è{Œ;N‹ Ž˜SˆoZ `´©¬©¤©¬©¤™|WTÐÜ_ę³pÊ4Î܋3‡O«Ê;6FŸ§>wø½Žö…Ž!¾ Ò>œ èhGœwe-Ëmãgcf‡«ºË¥ü_=–Ë+ÊNìTc';µ,~¼L~‚mìÊIÆN3õDc§š;OÙO?áØ)ÇN:vÚ! ´“Ït±Ydø(ç ; ÙyÈÎDv.ºóÌßrÃE;)ÙiÉNLvj²“Óä'¨Ñ§Ì“¦.~¦²sÕ½Ÿ¯î<­<ý¬eç­ÝÏ]vöZïë18ûYlÒDülöäg4;§=\üÄf§¶;?½Ù îô“ÜásÌNu›Ÿî˜mvڛýÔçóN:Ë úR«µ¢Qçjýs¯Çƒñ¨¿ÐÓýŽ»v Äò‘.údk<6=öxñ8ãE~íÅûKùûñxâÑ]S<æôX.>„õ±¦Ç–{÷8ºÇyý¸<ܶ‡ïÔT4Y?V$û–YÍ©©•ÔlÚë$—T£Jò” +c¹6R+bQ=!^¢båÛ‹×÷΢óxÄãç n/%2Ø 7“Ÿý`Ô/‘]-$è-쨇–Y[ˆQC‹;)žü5uYµ×a'Ìì Y<`{ÒÊ:õloTŸó÷Œ¹š?6Û,­p²é>\EÍ·v¬]Ê`ÙáhokŸüɏsûãDcÓ(×1®#|ëÃëƒëC[vÕ žÌ:£áâ#·_Ê/–qW>ÎCô“…j9ˆ¯O›Òg }òÃûã$ý,½t0}¦´Æ=`EtÕ¢©CEµÛ”¬¸öh'/°~ªœUf«Åñr_¼ÚFí´VO|þÚÇò>óŸÃ»ÿÝýöJœ×ÁxԘnÖcò‡Ï:'Àpñ@áɓ”GOTj²rï°ð‚g}/Åí^–Û¼@·*‡™=¦˜5÷©ÙϜ⒚=è´qç»òô_r÷½¼*ð-ûþâÑJWjfô xÖbý¯S÷ú‡'ÏƒÁ‹ÿçNÙFý{ë%©)Ýc¯µº‹ +v[‡ +y”óÖTÜk‘eÿïÖÚ.ßñDk-{‘þÝÞ6ýûҕõ¯ŠÁÇ´åY-Ë® }–U=FeéÓ©„É +Š†½ZL¬Ì{P5±Ðîâǜ +Ø~tÍe”wóZ¸~ô3i½ÔtD}úQÅÅÅˋ‡Ê9s¼”I̅;[–3¥#õiGÙ­Ÿëyqö’ãî—8֓¡í4x\tô3`GÆÊÅJŏî¾…ŠÇâ!*V.ދ½™'¾2NŠãD…üɏ …B¾[‡bÛzØÝ{<Ã%šv‘¦î¼VÒÏȽG=}YßC‘‹vn.ë÷…ý'…%c”ô×þš]wÉîñbQŠ +ø“┩ºLs§Ëq +WrÀRC-ÆëVm ckJ‘ó©'äGÿçþêñÐ=".¾äàøYˆœÃäë`¹…Ë4ŒNô¥‹¦SD­?ªSX}Z—E×õ NúDêtFÒ´FºÔjy×Õ¼gõ¼Ë·–ôTÔûHMï;«z•õ¾³HûU½gu½Ë÷+Ó~ÿºÞåc…½®*÷b:a¶EaÃxnƒ­³³Åqøâ±í˜Ê‰ÑV­Ë9L¶t̞6ÞL×µ¼ßw;w_—ße˜öeµ‡Ó±•–ìÓ¸n§oã,X6ëó +PùǼ—.ÛÆ2¿æãf_Ìe?·ßé´=ÿÝÚçc£çT>Œojׇ²O9Ùs¦ú1ýÓÍ¥¿L”í©ç–ü÷±ß|`·–“ëY÷ô̇Ùë6_þåõÓ 1oҐýû7ñ»ÔdYþõòM¿ŠåyßÍø—U,YÅò—U,YÅò—U,YÅòüË*–¿¬bùË*–?ەYÅòÿŸ±üŸnËw­Rùm+\þÝÓô‘Œiê3¦»g*Éw©¶Ü·?þ3\Rɉ2unìgwßÒÒ¯§ëÍÞ+è[¹§k]¢–þŸXÅsv™!'÷CÒâÄn!&f½Œ6zÆ»Føpér@ÂIË &k(YIR¿–øÕxñAqb‰/ +ûkhøè!áÜהUä´Xoó“­*?ªŽY+˜ {UùrûX –þùý9dvsävk„ø{ª|æêgª€ªJ]S·(‚Ö+·›³ãˆBç3%UC£69¥êãÚ®ç^¢¦x§ò¡—uu}¾º¢»ëŠnw=7]Ë]× o–qèjÕÓÞ=¶«ÇÚ=–î1çÇåiºzŒÝ£[åã+EÚ£ÿóPþñØÕEïºÇm÷8¯G~\|JyÔ »ßë òýO —ïwÑ ä{œ>.ß'ø]NÎþùýy\Yäª"×ÛŹ]QŒë‰õäӖ6ùåÄK\O¬g¢þŠâ£®(ÞŒ§Ã¯¯´+Š³NO£e#vŠºpEÑ/ßê\ÕVC±DÎ×Dé¼ѤŸ½j4rzc·Eq›–IuõÜa)8ÛsuqÓ?¬ÐHIï­ÖYþQ~‹qïÞü˲‡wø~Œq<ﻙ^Œeï/Žs[üµ5w».¼­å#~ã%‰Û¯¼ö0ê«lþþ7ÞüÏåŸÿ£tþÛÍróӛøïÃÍÞÿ÷¿,ÿіØ𗥫«¿‰½›÷ô¿@îʯ{ëïóóßã’üß¿ücÿŽÿ¤½7°÷ø {øÛoã‹Ý¦nyñVBë;­g=ÆñƟqú°¬Ó¶x{Ù6k/ÛtÞ|^_±Z[°M³=g+ñç ƒ¿¦lËßežW^²–yk]“ý¥½Óbírmþ’ÁÚ>‡÷›ûú«hxßX_r–í¶Â`ë&Ê!·Û0ó.Æ6ëZ÷yò§,Ûáír@Ôv}—²…ø0˛_”Óçæ}ç¸ØSösõ϶”ýmísÝ|k‰ëk–¶2Ò?ïl¿Âò¢œf&ÎnbÑÄ(?ç™×”×{W 6í)û0zûØk³œÌ|/ÛÈéû:ûhŽëê[ÝÌiÜoÚgµv9 ò’2ñ|€g;P¬m|¶_m?”ö¶{»Ìºöš’Zû<*³ç&m£œ’¼9hÚíó¿Y Büx,Á{}ÎâÏ)¡}›¡| +;FÇ!^s ƒeÜë¯6Öm)“È?NI¶ýÐ܆Øó²–픹²Øû”á,ŸÇÚå´sڔØËùÚÚ>Vš4ë>øs–ÑgMI NßÄdCTþ;”®´Kl0µ©yø۔>ÛsÆíô× ûæ‡Ñi x¬=‡€]ã³_÷´ó‹ÐG™ûµ½z{/Á¯©#V>b9ûsŽºKÊK+{Ž½î‚2EÄ˂¼Ë¾ÔÍÛkmÏÃéíu;*ÐÊìµ×<•¿ëR€µõMsÎšãÔHWÚCIÛ:ÒYßTcŸÐk9¶½‘ÎÚã²eҕ®c[é¬=®t֞מt«–[Îž2­tÞ:ÒùV÷FºÒ®Øé¼½ö¤³>ßw"µÏ©‘ζ¹Ì=éì.C#ï´±‘®´'‘/HWú +téJ»ìFºÕÊ­#ݺ ,®´¦}h¤+íe:{ҕ¾m8éJû˜öFºµD_Ãؑ®tMÓ´éJ»Œ#ýü8{ҕ¾Ù /ÒÙwüí[#]ioçړ®ôç¤[÷CÙߐΚûؓÎúŽ­‘ÎÛeŠ‚ºÒíÃfÔYŸá +ԕ¶]é ÔY{zÔÙkΡ¡.mÃPgÍyíQg}ãÜPçÏÙê¼½õ¨ó¾¹¡ÎÚëÔPg¯‚êlGîGCçØPg3ä˜{ԕ‰túNJºÒ´²K ÎçÝØ£Îææ>6ԕv‰;êJÛ_›QgsÜ^êœ-{C·uÞw6Ôùq37Ô9‹†uƚól¨óöÑPgíã|Žº’g,óّκÖm ÔY»œuÖç±C]雷a ÔY{Ž@]iO5\‡t¥g<÷#Hgí2¾A:koÇّnـœýt=§€œ·ëDrÞ5.9kP9kõ r–uç³çÔèÎgͽF„Á8ûdû|ã|o-G0®´7Ë¡2ãJß1Ô>g\iŸåDŒ[ìh,S;1®tͧÅor¥¹U°:ãJsßjŒ+}gÉ݃qËQvè°ãJ{¶ï͐+}«â,‡\iû¾r¥½MÓÖA®ôíb§C®´Ë¹}È-ö;G¹Ò7MG£\i——îP®4Ëiãè(g}S¥SÎÚcN9kÛÇ͔³¾&åJ{]k¤å”³ö<ïå¬oªq£S.mÃ(gÍMÊù[×\Â)gí½ÂÔ)W_³w”ó¾z8åümêA攳=rŽ[G9ۓö=ªPÎFÔv”+#¾Ôäl&YeA[Œ­¶9Ÿx6&Èùä\ö€œµçm Èل^·½ƒÜb'¶uÈùA0œ9og9€\Å̐s Í[†œÃª’Ç!çíi ÈY{ªœì 7ÏWëk‰«?#%®Ö¾N\K_—¸Z;'®¥}¸ZWN\K»K\íç׉ë|t‰«½$'®¾‰>qõ®”¸Z;'®Þ¾J\­/'®ÖΉ«ýf׉«}àœ¸úNK‰ki?K\ç³O\K»K\çóYâZºRâZZ]⺠Ï×Ò×%®ËÐ'®¥}¸.CŸ¸–v—¸–ö³Äuûĵ´»ÄuŸ'®¥/'®¥™Wk^'®Ö—Wk§ÄuŸ'®¥¯K\­Wk_'®Ö—×´ çÜøqõç¤ÄÕÛW‰«÷¥ÄÕß&%®¶ÍëÄÕöcN\m8sâjä:qµy”×ùìW›v׉«O͔¸Z;'®6¯×ùèW?Râêí«ÄÕûRâj휸z»O\­+'®ÞN‰«µ?–¸ÎãóÄÕúRâj͜¸–ö³ÄÕúrâ:}âjí«ÄÕ̜œ¸Z;'®Ö¾N\ç¡K\í)9qõvŸ¸úVSâ:}âêí«ÄÕúrâj휸Ú6¯Wû€9qõ–×y|ž¸ÎcŸ¸–v—¸Îã³ÄužrâZZ]âZÚÏ×Ò×%®¥Ý%®óü,q-]]âZÚ]âj?¿N\K_—¸–v—¸–ö³ÄµôåÄu^ºÄ՚׉«õåÄÕÛ)q—牫õåĵ´»ÄÕÚ׉«½&'®i†:k^'®óÒ'®þœ”¸zû*qõ¾”¸Z;'®öñ®Wۑ9qõñL‰«ÍëÄu»ÄuûÄÕçÝUâjs3'®óØ'®¥ý,qµ9žWgKJ\½}•¸z_J\ý¸I‰«³¨O\59qõvJ\­ý±ÄušŸ%®Ö•WkçÄÕÚ׉kéëWkçĵ´¯×ÒÓ%®ÖΉ«µ¯×iröӜ¸z»O\½+%®ÖΉ«µ¯×iîW{NJ\­y¸Ú'ˉ«ï­”¸–ö³Äµôu‰kiw‰ë´9Sâj휸ڄ¾N\§¹O\ý H‰«·¯WïK‰kÅLK\C}âê°J‰«·Sâjí%®ãú£wK\§3P·[âºv¨Û-q¶@ÝîÓiÔힸ®êö.qÝ-o­ØrÒힷŽ™t¶Q# ¤ÛÚJdtÖÖ±¤Û}×ÍA:;Чz@9évË[+ ƒt»ç­sî𼵑îð¼uêHg5þ£ÆFNºÃòÖaÒž·vA]ÁS™¤¨;=quVª?+Öu§%®Ç¨;=q]ê†g™kéê2×Òî2Wûùuæ:}æ:}æ:Ï3×qè2×qì2Wk^g®Ö—3Wo§ÌuŸg®Ö—3×Òî2Wk_g®öšœ¹¦m8ëÆç™ë8ö™«?'e®Þ¾Ê\½/e®ÖΙë8>Ï\mGæÌÕÆÓ>:¬;Ÿ'®‡ç­#¨³üVéè¨;žç­‡Å£ã¤órù9éåґÎÎmS ٜt‡§­Sîxž¶Z9§ÎŽšyjÝáYë”AwxÖÚ"ºÃ³Ö9@wxÖº<­õôUx™tƒç­K+Ò íû¬,sŽ>®,u=Zî:Xêê»G´,w*VÁÁcŸ¶Æ»ÁÓ× +@Þàùëñ`g3¾LÏ1h7x;œwÖ7ÚáGÇÞ`£pT"ñ†ºòì€_Ï:{yƒå±ûÚg²ƒ'²•`N½Á3Ùi ì žÊŽ[ǽÁrYÛ೏ëčϳٱ‹ñ,›]‚|c—ÍÚò¢¹¦Ç-ijdvnܛ<™]Z6kÉì²÷Ù¬%³•5›õ]4¶l֒Ùõ*›µd6Åx“ï·–ÍΞ̎}ÉΓYyVæ,óH{Ékv–Ì֓T«Ùy2;¶š%³ëÚjv–Í[_³³D´Î§Z³³d¶Ò³Öì,™­íV³ódvn5;Ï?¦¨Ùy2»ô5;Kf÷µÕì€5;Ofç¾f×'³³ç²-™Ÿç²³§²{F¦uÚ[ŒWvˆ‚±ãu¹¬Áv˜÷àžM;_$žÉg“s}ƒ'³Óì<›­uÀ€Ÿn%Y‚~v(ŒË°þ¼ÃNw€ÖiBD0È8xN[3B8xR[#4‡ààYm ·œ‚ƒ§µ‚Ÿ‹‚uûþÃÃëÏí.¢/ßÿææǥ뇷ŸÜüÕ§ÞÛ +è7¬óÛ\Ú-ë~òðÉÍÿfOù/ßú”_ýÆnpçOr0”¹˜ž{wwûùçß|ùËwüv¬õ‰ÿ{ù[þ÷·VŠm¥xù‡- ßn~øÉÍßÿ× £~ùèºè«…æv”^U&­+W&ý@ÞÒ:éóyeÒ¨´ i´]ÂÒ:éóº2é¸ØÓ2鳯LZûº2Y»S°Y´Bú|V™ô®T™tf¥Ê¤3îª2iœós++¤Ï®2iÍëʤ}²\™ô½•*“Ž°«Ê¤=7W&˻ʤñèª2é8j•Iûœ‰å¶®+“¶§reÒH’+“>W•Iâ\™ô!N•I?ž®*“vÐåÊä>ö•I;â¯+“¨LΎ‰óˆb=וIë˕IçSªL:®*“ÖwŒ-Š5ìåʤµ¯+“Ö—+“¾)¢Xk^W&ý­÷ÅZ;W&ëkúʤ÷%˜ûۤʤí‘kš;;SeÒ¶—+“ö±®*“¶7ÍmçåʤO¼«Ê¤OÎT™´v®Lژ]W&}¬SeÒ碖HŸÏ+“Þ77Š'ÌÔ%Òç³Ê¤Ã*U&½*“ÖΕÉï"øݟ2Á¿/½méÈêS¢ Ð×­³| iñy™ÂuקøÜC)èë¶,k +ÐËÔë³ O뼌í“YaëP¯8)@/ÑßP/{·½üÌG0âôÉRÅ%Åé“R–§OÃ^_C˜¾:ä Ó·u¸*L.ÊÁ¹æ0ý¨çýÓË¡Ps„¥Ïåüµ)J_‡á¬OˆÒ·]uƒ¥¯{}k¶$çÎÆ£N÷uØ«¤}jT«(ýÏJñ¥Ÿg­`(JŸÆZx%H?­Z¾õ´¬}5-;Çè^»ŠÑU|!DßÖ#]U/9ãRK»9D?–Æ+D_(Ý*D߆s¹ÑYð@ˆî˜mºÔ>B_ç}KúVsä ×d¶Џ¡ÖT —`AµÐM=¯t›Jc +ÐKà\'›ôòšã¸ +Ð×iªž"ôuQØ£]A¢û|j!ú4ŽËœCô}—ë½Ì‰-ÅèǦJ®—aˬs‡®ÑkúÝ"ôsZëySz9eYªÐ-E¬&B/ymל¬ƒ¬=Eèk +Î>ŠÍ ö­ãº-™*¿Í‘có㘎FöÒa[Ÿþ”Ñþþ*¤6sl»ˆÚ³éàT7[ûØ[@mM›6- ®ŽÚ¨pÚ¥¶½Æ–6­Lq³` §kߤҤ…ÓæQƒ­¶g[§¤pÚ,ºMU˵*pƒ]}#ž6ώP[ßT϶µ\;½ðéG@míáŒ_Ë/õ—¾í¬«Ôfn-5hö€ÚÔ­ùŒO^j›½ãÔj‹#kúQj›ëÚb–Ú·/uՀš¥"ÔåÈٖˆkD=ÖÂ-!µþT1Ú$V{DS5¤6hS ©Çº©©í¼ÚÔ&…žc ¨YC@]Ž¯‘0€ºôõªG ¨í9ºrâuižöuùÙ<ÔðÑ/õ[ÿÜ"êÍ£è[Dmƒ¡õ5Q[{[—ˆ¨mì¬ÖÙ"êªã-Š -¢ö1×R ‹¨Ýà\â5Q[ŸŸÒÙF™këÒBê͖”p¥…Ô~„L³~ ©mú.ñšª ®GQÛ°ÖZ¯Gԛ_Y?#¢öãr×xD]ú¼ÐND]Ú夿QoÒmrDm}[6RÛ&özTxHm¨-Ê!õæ +NDÔ¥¹Lõ`óˆÚ]Ò-¢p¨­o>z gõO#Âöö¸4Ô3•oŸ#¢¶öYÓM¨ Cû܇ÔÖg¡ !µ?§fhR[»Ì=*ÃD슦!'ŒÚA³ž £¶ÄwÝ£¶yZzŒš¿]çI=¢¶e£ïKÏQ;P÷±qÔNÝÇÜ8j‹Ñj»qÔûsi05}ûl,µfõQK­oØK(Œ•¥¦oSÏRÓ·ë1^Yj,YçSÓ··±‡éX£³€©í²ej0- Ykƒi ùñSÓ·×3`êúö¹u0u{;¦ö¹DJ§©ۃdxhj»ëÐîòâ„KRÛÿ»v^ßþ+‚Ò͗ẃRŸÁ­R··õ1 ¥~ôœAR?àŽ©#©ËÛû$u{»ÔÍìeì@êööyH±¹©;Ôu§H͉žÆ9@jíªÊ×Yiîs‡QºëP:Fc ¨[×ÇÖaÔßyÛ£nbk`Ô_S÷%õ®m +ŒúÛ¬{`Ôõõ±£¨íÆuƒ¢UÅ߂¢înos‡Qw·+ó£@£6閵ǨMÌ%(ZZ~AŠŽ±_EÇZ-¢²°¢Ö碣 ˆZ»n¶BÔ¦ÛÜ3T_5 µvýڂÊÐQŸ±g¨‹’uC¸U«{!œ»“ë +áܓœæŽpÖçW·p&1G˜hiŸ:¾™ù\õzǛûÖÇxs1º¶o¦lïõüìxs­ûh|óöÜáÍ»†-ð† Þ¬í×wÞÜã>æÀ›mcX§À›µë—GÝì®ótóݵÜÌf=ǎm&Å mæÍ®ëh3_Û ² m¦ãúLÚLÙ>j`èh[µî+£m]#¬s´™â« èt3eÛ¾Ú¦Ñ͌l?BE73¶°3fg+ º­[œ“œnflûw%o¥m‹u2ÝJW9íìA7ó“íêxs{éèf]¶æºy»¦N7Sž§zê +ºYß6ŽA73´çù ¼YÛJ0™onq×Áôã8¶!¾apg¾ù{×ÄÊ÷žë×5kr¾Õל™oÞµÞü]t„ÞÜYŽŽon¾×ØËùæ£YÙä|³rnSÇ7¶Çúµ~ì¯KéðÍgÞ2w|óÉY3GŸ4å?ãºàL؞׳œMqû$‡l á¼]Ñ„ó¾ú½$N8oo8gÐtt„«_ 1áâ»D8wÀEÀD8·"÷5κ<<ᬽÕ\Öç’ä¸u„3={¯ƒ¸»i9ÀÆ83š·z† ÆYßX#‡œÛÙ5¦ðãÅÚGmäL¦ëÙÓ!çöôÑboW¶å-eƒrÖö+ꢜ ÙûÒQÎÅîz:åÜ$_Ö œ›æ5¨ ÌÙç=s¾ÏæÆ9“\çèL„µÏéLžõš¡Hç®mM"ƒt®än:Ó¶1yÛǸw 3o[A—ƒÎ,_?Wtæm¯sâœIÛû²çLÚ>†58·øš±ãœIÛ˺çLڞ¶çL5^j 3i[Á«ƒÎåc›t yM"ݢ@· tnA×Ü7@gö0¬:kïó s‰{š:ÐYßR‡ÓAÛèÜ®®¥œ¿÷zèü95¯qÐy[iŠ@ç]ë¤ó·YÎ ;éÃԑÎö¤‚^'ç|él†ÌëڑÎfÒZ±ä¤[`®Hç3oÞ;Òùìœ'HgͺUÍç};Й´}.S€ÎÑr®:?&j ó¾š#;è¼]·ë¤sMSG:ßî¸é¼=ìA:äð+Ò¹ ½/™t³­Á]Z¶:k¯Hç¢e ƒtÖ7‡Hg³jrF:š·>[ù +‘Îí½e«Öžö>[5e{=Z¶êòt ùœtޞútÕ·[3'ÝìkÝö µ·š¯é\ÒÞ[ºZÅï%Hçºyï‚tn©O-]µÖҙѺ}ºê&lísҙ=;¯:wm>[u'·f´N:Ó¶·©e«‹-åª$l¤"«¤³‹Ng-Õ¬±?‡¹¼Ó ÝЈì¤+??®@g+3ז®š³½ñ]y³cïóUs¶­å«î(×*@ݨ:f×VZÂêí©%¬îA×Y#]é[†–°.ö;Íc# É4ö¤3‹tj)klҍ¶®¶OYý½k +TIgÏ©ùM%ÝØ2Hg]kKYým––²º¤Þs®ìÈ}h«fe”sÎ&È®ÌÎÙD:ז±Îg]/ç|ÞÍ}Æês³fË6g¬y.-eí;2Ö>eµ)>ׂ€ƒÎÉr¶œuÖRÿ :ï«U·×)@ç(ê9ç›[Îêí¡å¬îyÏrÖÙäîçF­€scÍ҅9¿œíòFiŽãÒ_ß°‰4W&UÌÁ[0g¯9æô•¦`ΦBÕ*æÊäYk¾Ü0gK!굊Š9˱7ÌY»æË s£† ̍ʝÀܨ ”™s¾€õlœ3©»ç+çF%È=ç&_—°eÎM|Á¨8gmÏÖ+è\¤¬b€Îülg*è¬5×ÀË@gJ³®^è&괝©ÐÇÖ2Wûù°õ™«ÙÔóÞ2ת|Ï:o}æêÛm‰«Kܵèê sK¼ntÖçäèÜŸÛ¥\ûÕÆÞèìcK\§º0:@g’ërö‰«‹°ç ›ÊŒË 3×ÖÖ-dҙ’;×äÖI7éëð Ýä_Hzt¤3qûh 3Ë÷ tfmërŽƒÎ¬mˆlYۊCtfmoKË\ÍÚ^ö9@g®1×'Ý䍖¹º¦]+:÷ §¾Fg}k‹ç¼9µÌµÚÕæLÀϖ¸ZûœæÀœµ÷±¿a}ÛØ×؆0gíaëWëšùÌöçÔÇAçí½K\½ki‰+®8 sGýìWۑËÙWÎJ)'Íµ^’ÒÙLڗ–¸NÎàO¼©Ï[mr.õ[}Òè£8gÓù\ú¼Õ¿˜`žƒs–£å­Þ®„ÎùaÒ0çÍzÝÃ1ç º +ç&­›sÓ×ÇsÓ¬s}¹q5°[«b]Æ +sÖöT½~Ö*tgÈYÏ\GpwÍҗâ rÖ¬uÁ`œ9ÏûÒ.AX{ZÛJk/k¿RÅlíºQGœ ßµèçˆóöЯVñÍÖË Î87¼ëe#gœëÜõ˜ ÆYß¾µÕ*U?ƒqÖ^kpŒ³O(v:ãF}›'Œ3—õ8úå*£÷`œy³kÊYM³=÷~¹Šé¸æÀÂ83¶+¿q£U]t½ĕ>B/g\iûÊ9g6ö8.‰qæc{ÉKŒ3{>Úrû¹˜ŒMHk9«éڇb7C\i|õW!F+e¬mµŠË×uå‰#n$ùHˆ©°ˆq# ŒgÊóTóӀœÛ×G[­2Zn5n9kºLä¬oÚj•Ø† gíeëW«ø{/S@Ο£«hK¼¦[­â]s[­âòøÜV«ØÇ378CΌíãh«U|<§) gSä¬×r£}£çҖ«ŒðV”ó©7õËUlzu¥ŒO+§Ï s¥=Ìs¿\ÅfùZ/"8æ,{[®âíš,æüH©™¬s®’fÎ9‰†~¹ŠoghËU¬­ ØÎ9oϖ«øwOî]8ç•Íy ÎÙŽ*P4ΙEy}Þj·Jv»y–ò*鬮ËS:nPgööZ/È:êìÛ”“êì˜ÜZÚºÛÊÙ¥¡ÎÚCET Î6{Œíj«´ÃЮC |gÔ¹8~N:󳧽孻-{^û¼Õ~c ¨³]6n­:g‚ë±õ\½¸¸¶¼Õ¿–rn+óìˆÜ+·u¶®p™Ú…ˆÓöNË[í KϳæN–M u¶àX´¬¨³çc¾a>ö>µ¼Õ|m˜ì¨´¨'£®ªgu¶8}[ë†v¡"X7èë:`ÕøjA ²nT­1³Î5薷z{lyë8ªä™YgöõÑòV3´÷qm¬+íuX{ÖÙ·f -omÀ:_YÜ£ÎÞºfAuö”ÎÕWty«wÍ-ouu|ny먯æêHg÷9ZÞjÃ9 ­>g_†8ï=éÊLÒ}tÆ×}l JlâGŸ·Zu|¬õ8›4VLOte>ïZ5 ;ìR\}‰ƒÎȲïí‚ëQãtþ]Æc»àê¨Yè Eƒ2K@Wú´†Ì9wø5•vÁõð³ýr͹ðAèBt¾"{Qå`O:Hfë k,@väœ#y $ãÎe³Ûy2À $/d˜gkÿ×yn_ÃÉÔCz¡ƒ€½ÐA2÷†jÀ¶e&¡ƒ@>tL¾¦ƒ}Mûš’à:q:q:HŽóðAˆóÙj ‡’=„’Y !ä²!-—•B*‹B*‹’SYé d²è ”ìÐArÉ„’V-“ÅéJvòA¢d§¼†Š|®b÷¢*ýQ±“; !]ÅNBHTìØ;!]ÉΌåa„DÍNFH®ÙI‰š„¨ÙIéjvB"••Qž„.ʓQžŒˆòd„døa„~!„@¿B2þB.„ ­n>HàPGm +"…@ÀB2à +‚a…@Á°B®0øG4¶ÿØ"¶­ó2 (k#¶6lç[³6¿Ç4ÉÞ²Kp¶VlÝcݸ{#¶Âlݶ0G¬}Öon° hM½ÄՑµÄð|×RïCQøz†:b‹Ú¶±ë]I–0G|œ 3GJ{÷%ÞÁ +³¶tn“zmEkãæÈj_µ·Åoåæˆ-®š«Òa«”|…^µ˜ÝY—º|±\ý +17GlÌåY»9âË+ÇxWþl.ù—Jµmxôƒ9bí­)nŽ¬ö=Sˆ#6]ÏxI½éŠaŠ—ØÄ÷é,g˜#v\a§›9bǦ]ÇÐkÜñ”Sˆ#¶ˆñ¨ÂÑ2jýᾑ‹#õ7Kˆ#¶}‹#¶DÓ8Ósñ{ñKýR7Gle'ߟ²Ö{õìcû*7GlÕ¢‡â2Gbu¨Ì[=z4Ô³¥vKˆ#ö”Yˆ‰#öã&ÕÕQ¾0µz .ŽøsäfÛ+Úºÿ˜#J¥ŽJ¥ŽJåŽt(•;(•=(•>Ò±TúH°TúH°TúHf©ì‘jµG‚§²G:žÊ žÊ žÊéx*{$x*{$€*{¤ªì‘ªì€*y¤ªä‘ªä€ºIÉ@Ý$Ômj´ëù¿Þø*u“<Q7“GÀé&y$ãt“>N7é#àt“>’qºI§[ÕG é&}$Ót“>"šnÕ¦Û÷D +˜n²G€é&{˜n²G2L7¹Àt«ö,ݪ=’QºÉ¥i 5‘”=’QºÉJ7É# t“<’QºÉ¥›ìPºU{$“t“="’n’G é&y$£t“<J7 J%t(­òHTöHTöHGÒjHe¤eönt •=H%H«<ÒqTòHpTòHpTòÈ5G±G2åÐG ú”ÃɔÁrÕ q($™qRH@ + ˆC!IˆÃ q$0NIF ˆÃ q$q$ ƒÄÉ É„Ã p2H8 $™oHÀ xC ÉxC o$à $㠁¼!@8’L8‡BáPH2áPH sÄI!ɄC!á0H@œ ’L8 ‡Aá0H2á°?  ˆÃ Ɍà qiÎ8 ’Ì8 1Æ!dÆÉ q$ ƒ$3ƒDŒC q$™q$0Æ!dÆ!9  ‡A’!‡Aå0HÒLð +H¦‰('È!dÊ!@9(‡@rM9 ’L9(‡BåpH2åpH  œC#ɜC#th$€$‹Ða‘:,’L:,H‡Eé°H2é°H  ¤Ã"ɨÃ"uX$bI† ´C"vH$™v’H€ °C"É°C"vH$ÀNIf ¬C#uh$™uh$°Ö¡‘dØ¡‘vX$À‹$ÓN °Ã"vX$v À‹Øa‘dØa‘»´ ‡I†‰`‡DìH2ì°H  ´Ã"É´Ã"íH I¦ ´C"vH$™vH$ÐN °Ã"É°Ã"vX$À‹$ËD°C"vH$™vH$ЉÚ!‘\Ó‹$Ӎڡ‘@;<’L;<h‡IíPI2íPI * ´C%I´Ã$v˜$Г$Ó“Úa’@;L’L;Lh‡Ií0I2í0I &‰h‡H’i‡Hí$’;D’ ;Dh‡H´“HÒÑN"IЮŠ$;‰$í¤’í†àr¥]UI:ØI% ØI% ØI%é`'•ØÉ$ ØÉ$é`'“$h'“$h7F}µÑNHÐN&IÐN&IG;™$A»¶J;™$íd’@;‰$A»1ò–F;™$A;™$A;7I:ÖÉ$uI`"If" ¬C$uˆ$™uˆ$°“Øa’dØa’;L`‡I’a‡I"Ø!’;‰$™uˆ$°‘Ö!’É%‘ØV¹$òZÉ%]^[õ’Hk¥—DZ+½¤Kk«^Y­ô’(áI/éJxÒK(áÉ.‰žì’®„'»$JxJr¨àÉ.é*x2C¢‚'»$*x²Kº +žì’¨àµmÔ +žì’®„'»„žä’¨áI.éjx²K¢†'»$jx²KºžìÒZÉ%íI.é¢=É%íI.‰hOrI r »†]’v Ä.a—d†]" +"—@ÁK2C.„!—@K®Qøgl—ز[’íë›æKleÅv´›’X{h·ìr¹ÄV[èÆÍZ{™â.¶^co÷ ±ë&Ö5.í.¶&`Ú]þ‹ynI`—ÿý«Öä–ø¢‘£ÝåÏ•´ò^¦µ.ÝÌՒҮ_R/µÄÚÃÃՒÒç÷‘”ZRW³´»üÙ„yîïògë\‹–ZRÚ»TwKlAw×}Í¤Ý ·Ä íí.‹e9á‰Ôo\ýþP2KìÛÜîòg«{nÈ!³„@˜%öšslwù³ŸÛ¥5Ì[¤^ú +ûEϱÝåÏVP ø2K|UÅÑîò·(Ä,±¶‰þ™%¾“–-Ôۉõ^!n–Ø~¶¡ÓKÜ,±¾sowùóõ!g»ËŸ ÝÌN“âëJŽv—?kë~#n–øR¤£¿ËŸõÃr“¶±ËÙêijû«ÇÛX¡Õææt¶»üÙԝÏv—?›Úë{ÀÍ_Á4µ»üÙAea7f‰-M²{÷ê5n–øZ£s µd9뭐¤–ØÂ,MWK¬om·$±-èÆãÐG`úHfúŒCqè#™qè#0}ÆádÆáÀ8ü‡?’‡>"ÆÉqØ#qØ#0{ÆadÆaÀ8ì‡=’'{Äa€8쑌8ì‡>"ÄadÄaÀ8ì‡=’!‡ùä°G€öH†öKÛØey˜<’!‡<ä°G€öH†öÃrØ#rØ#@}È¡dȍ­DjÃrØ#™rØ#P{ÌadÌa€9ì0‡=’1‡=çÐGàúHâöœÃsØ#לÃɜÃçGàòH&ò¤CtÈ# u¸# wÔáŽdÔIêpG@îHBê¨Cu¨#u¨# uÔ¡ŽdÔ¡Ž€:ÔP‡;’Q‡;êpG@îHBêˆP'sÔaŽdÔaŽ€:̑@Ì‘u2GuCc²£NæH‡:™#Á:™#Áº¡]¨ÖÉ ÖIu2G:ÖÉ ÖÉ ÖÉéX'ë#X's$X's¤cÌ‘`]ÛÆ^ñjE âH ®š#Aº±%+A:™#A:™#A:™#édŽ@:ÔH‡:’I'uD Ãt˜#t˜#€sÐaŽdÐaŽ:Ì@‡9’A‡9èPGêHÌ8‡9ç0G®9æH]˜#"]ˆ# .đ̺G€]ˆ#Ð.đ„»ðFà]x#/¼‘L¼GļðF€^x#‰zh#P/´°ÚHæ^h#€/´ȇ6’ÉÚè mö…7’á‡7qž¼‘ˆóää8OÚq^#[ ôdtž¬‘Hf«5¹¬¬‘.—­ÖH¤²²F"••5Ò¥²Õ‰LVÖH”ìdt%;Y#Q²“6BÉNÖHW²“5%;%6Tìdt;Q±“5;Y#]ÅNÖHTìÚ6öjwLZÁ×Jv’F¢f'k$jv²Fºš¬‘¨Ùɉš¬‘®f'k$RYi#åIé¢l8u +mĆ\7qmdv{"^SË~ƒÜv´‘Á.kíͱÓ|ó9ª7b±½~—½^jŸx©£…W¼Äµ»XxNM±ëvûÙ´;0¸ïIÕFF[õ>7m¤ìqÃ9ÚÈXKs j#v}{NÞÈhE˜³y#c¥|LÏÅ·³.I뒹ÐFÒÝÉB±…ÃÙ´‘Qßð6¢ \¯©ÚHù„Øh®Œu!`h#cöÆ´6ªôùmßðFì9çÚ¼ÛkÿÖHÂ(ÒÅF‘F2F‘F„Qœ0Š3’9Š4G‘Fà(ÒHæ(Ò0•5K±F2K¥K¥K¥t,•6,•6Let0•50•50•5ÒÁTÖHÀTÖ0ÅÉ0E¦x#Ðo$Óošº7JñFJÑF@)Ú(EÉ(E¥ÒF )ÚH")Ö$•5HÑF2HÑF)Ú EÉ Eú¤ÒF਴‘ŒÑÐF„ÑÐF„ÑðFFÃFÃFÃi mD mDEI mD mD m$a4´a4¼0Š7’1*oDE¢h#™¢ÒF€(ÚEÉE¢h#@TÚÈØ9cՁ¡x#0o¤chX#p!ˆpaT…4’ÒH%œœñ-œ‘Ä7¤á-¤á-¤‘„·F„·°FÄ7¬‘„7´ð†6ÞÐF2ÞÐFÀڈð&k$Ó kºÉn²F2Ûd€6¬І5’ц6ÚðF@ÞHFÞhÁnx#‰nh#Ð mº¡dº¡@·øæNáMÚH¢ÖtÃoÒF2ÝÐF ÚtCÉtCù€nh#à m$ó-´ñ-´ñ-¼‘Ä·ðFÄ·ðFÄ·ðFßÐF„·ÐF„·ÐFßBßBßBI| mD| oD| o$ñ-¼‘ +¸ÐF¸ÐFàBáBáBI„ mD„CàBI„ oD„ oD„ o¤#܂5Ò· ˆp ÖH%܂4’· TÂ-8#b܂3’· r ҈ · $È-H#‚Ü‚5"È-X#‰r‹´(·Hr‹´‘L¹EÚ”‹z•r‹¬‘Œ¹EÖ˜[dÀ¹EÖHÝ"kÒ-²F Ý"k$“n©Ú [ö±qP ·.J Ð-{Ä\,epoÐ-ÕIœ[¤À¹EÚœ[¤dÎ-ÒFàÜ"mэ$Ða:¬@‡6’I'mС:´‘ :”@‡6èÐF2èBèBèÂI  oD  oD  o¤.´‘.´‘.´‘DºÐFDºmD¤ m$‘.´‘.¼‘nÁI¤[ðF*éi#݂6’@· t ÚÈgÕF贁nAé´‘±sǪ7"Ò-x#"ݲEÞ=|Äi¤ iD¤ k¤’.¤‘DºF*éÂéÂI¤ iD¤ iD¤ i$‘.¤‘.¬‘.¬‘D:´H‡6éÐF2éÐF ڈH‡5’I‡5é°F ÖH&Ö¤“5è°F2èÐF ÞHNÞHGº!â/¤U;ÂA'o$“NÚHn$WÒUm¤´‘´‘´‘ :Y#:Y#:i#褍餍餍t¤“ò¤“6¤“6ґmÒ¡@:¼‘L:¼H‡7éƖ°œñqª6éÐF ]ÕF2çÐFàڈ8ÚHâ\h#â\x#â\x#‰sáT΅6"Ѕ6’@ڈ@ÚÈiG]“@ڈ@ڈ@‡6’8ވ8ވ8ÞHÏ9¬‘Ä9¤8'kD˜CɘCæpFÀÎHÆÒ˜CsH#sH#`kÌadÌI ÌUm$('m¤£œ´‘ œ´('k¤£œ¬‘ œ¬‘ Üw…É7xð5ÊA9Y#¹jt”“6”›ÁŒrx#™rx#PoÌá$Ì¡€9´0‡6’9‡6çÐFàÚHâ֜Ásh#™sh#pmэdΡ|À9´8‡6’9ڈ8ڈ8‡7’0‡7"ʅ7"ʅ7Ò(ڈ(ڈ(ÚHâ\h#âÚ˜CɘCsðÌádÌásh#`m$cmÌ¡€9´‘Œ9´0‡6æÐF2çðFàÞœ#A>b4΅4"΅5RAÒH]H#táŒtáŒ$Ѕ4"Ѕ4"Ѕ4’@҈@ֈ@ÖH´8‡6èÐF2èÐFڈ@‡5’A‡5è°FÖHÖ ÃtX#™th#oÒádÒÉtx#€o$mС:´‘ :´@‡6èÐFè°FÖ CÉ “6çÐFàœ´‘Œ9”0‡6æÐF2æBæBæÂIœ oD  oD  o¤.´.´.´‘ºÐFºÐFDºÐFéBéðFºðFè© CçBIœ mDœ mDœ m$qmD˜ mD˜ m$a.¼a.¼a.¼‘sa4̅4"̅5R1'i$A.¤‘ +¹pF9œ‘ĸFĸFĸFãF„¸°F„¸°FâÐF`ÚŒCɌCqh#bÖHf֌ÁqX#™qX#0kÆadÆ¡À8y# o$#oÆáÀ8¼‘Ä8´‡6ãÐF2㤍€8´‡6’‡5â°F@ÚHFÚŒCqh#r(@mÈ¡dȅ6"ȅ6"ȅ7’ ވ ވ ÞHƒ\h#‚\h#‚\h# r¡r¡r¡$ȍí 'rፈrá$ʅ7R)ڈ0ÚHÂ\h#Â\h#Â\h# s¡ˆs¡ˆs¡$΅7"΅7"΅7Òq.¬‘ƹFĹ°F*çBI¤ i¤’.œ‘.œ‘„ºF„ºF„ºFêF„º°F„º°FêÐF@Ú¨CɨCuh#BÖHFÖ¨ÃuX#uX# kÔadÔ¡€:y# o$£oÔáêädÔI Ô åŠ:i#ꤍ뤍ë†v¡bˆ—¸5¬“5¬“6Ò±NÚH°NÚH°NÚHÇ:)Á:i#Á:i#ëÐF`Ú¬“7’Q‡7êä@º±å+gû0ÇÜòÖÐF ÚH&ڈHڈHÚH"ڈ@ވ@ÞH]x#t¡t¡$Ѕ6"Ѕ6"Ѕ6’@ڈ@ڈ@ÚHވ8ވ8ÞHǹf4Ð5iD¤kÖHE]“Fëš4RaלÑ®9# wMïš4"à5i$¯I#b^³F½f$ꡍ@½ÐFÀ^h#™{¡¾ÐFD>¬‘L¾°F@_X#°/¬‘ ?¬‘ˆódDœ'k¤‹ó¤Dœ—È恞¼‘.Г7ÉlõF"—•7’sÙªD*+m$RYi#]*[µ‘Èd¥DÉNÚH.Ùɉ’¬‘(ÙIéJvÒF¢dWóš¨ØIé*vR>¢b'm$*vÒFºŠÚ;´*vx#¹d‡7BÍo„šÞHªÙ¡P³C¡f‡6’kvh#¤²h#Dyh#9ÊC!ÊÃ!ÊÃIð o¤Â¯i#¢_ÓFþš6"þ…6"þ5m$°i#"`h#"`ÓF›7"6oDlÞÈo]ügbX±Ü\¡¬X߸/¡XÁݖâXÁÝ&×ç—æXþ<¶Gfï$ŽØwÝwqÄú¬2ƒ82—þ\ÎG¬]üÞ_b­m•ÏáaäTK{x#v±a=—x÷F¦z]#¼‘©^9odª58½¦z#SùM«ñâވU§§­‰#ªNë%U1¥â<›8RæoÕlª72^ÝСöùÂËðF†z܄7Ræ}9!Õ(od¨·ˆÂ±eٍ፠uµº^ROLCͦÃêÚÒðF†zã âÈ`k8÷&ŽØqµ®M±cqdô;`…7bדŽ­y#¥m¨ö— ŽØN:Î&ŽŒõ âÈXׯé5U±K¾ãÖđ±†`!ŽLu5 ¯qqdªG|ˆ#6æõ^"U)ïoõ&½Æ Öçf{ۆoq¤´=¦à}¼ÀZæçÔ¼›¼s¼ÄßÆOM¼ÄÄ;l-$âˆg%m +qĎÃQ_âˆ_tYÂ)M¿ ’¼¿D³®Ì÷F¬Ï¼ۂî¹ãވ]ç²aLÏÅ¿UÍ8bmÃ9âˆ]æYÛí†\ñKhÇâˆ]b›IFo»¹¨×Ô›}ވ5-±`Þñ=¼ªð™W½Æ¼Žî?âë« hûwßêcŽt(•:(•:(•;Ò¡TîH TòH TòHÇRÉ#ÁRÉ#ÁRÉ#™¥rG¨Õ žÊéxŠ;OqGà)îHæ)î<ŨÈ#¨È#yD@ÅÉ@Ũ¸#C,ëç ¨áŽ¨áŽˆ¨áŽ$¢†;"¢VwD8 w$á4äá4äá4䑄ӐG*NqGDÓpGMCM‘GӐGLCLCLCI0 yD0EK‘GJ‘G@iڂùÈ#¥È#B)î(ÅÉ(E¥È# TòH&)òˆHŠ;IqG2JqG@)îH TîH‡ÒêŽI%I%t$­òH€TòH€TòHRÉ#€TîH€´º#GåŽGåŽGåŽ\s{$S}Ê¡@9ü‘L9ü(W‡@’'Ä!€8’„8ü‡?ãädą?"ą?"ą?’þˆþˆ‡@’‰‡@R‡?’ø†?"¼…?2Īþê$¼…?"¼…?"¼…?’ðþˆðþˆþH"\$"\$"\$‰p!T…?"Äá$…@"…@"Ä!$…@"…@2¶{Oõô„ D„ Dˆ $1Æ¥m8ãH2ãHÄ8ü‡?’'Ä!€8’Ì81ÆádÆáÀ8ü‡?’‡?äH€I† ”C r$™r$¢œü ‡?’)‡?åðG þÈ5å0H2åPH  + ”Ã!ɔÃ!rH$p‰$s‰Ð!‘:$’:@‡CèpH2éÂ!™â«¢«C2Å·1W‡$‘.‘.‘.$’„ºH„ºH*ëÂ!I° ‡D´ ‡D´ ‡$чD° ‡D° ‡$Á.Á.’!nØåIb]H$b]H$b]H$‰u!‘TօC"օC’`‰`‰`I¢‰`ÉؾÕj«9lÀ.$Á.$Á.$’;$`—¶Q¿@I†‰`‡CìpH2ìH  ´C"É´C"ípH I¦ ´Ã!v8$™v8$ÐN °C"É°C"vH$À‰$ÉD°Ã!v8$™v8$ЇÚá\Ó‹$Ӎڡ‘@;<’L;<h‡HíI2íI " ´C$I´Ã#vx$Џ$Ó.<’)–8WdŠEÄÕ#I´ D´ D´ ‘$Ñ.DÑ.D’J»ðHíÂ#íðH†XÞ_=’»ðHD»ðH I¦ ´“GìðH2íI Ýи|H?®`‡H"Øá‘;<’ ;D`‡HìI2ìI "ɘ.Æ֓Y£" ´C$vˆ$™vI‚vm|㉋$í$’@;y$A»1ò–F;‰$A;‰$A;I:ÖI$uòH`If ¬Ã#ux$™ux$°‘Ø!’dØ!’;D`‡H’a‡H"Øá‘;y$™ux$°Öᑠ°Ã'vø$vø$b]ø$‚]ø$ vá“vá“v!”$؅P"؅PRa>I‚]ø$‚]ø$C,ó¯>I¢]ø$¢]ø$¢]ø$‰vø$‚]ø$‚]ø$ v!”v!”v!”$؅PRa>‰`>I‚]%‚]%‚]% v%b]%bBIB]%B]%B]% u% .mÃQ‡P’Y‡P"Øá“;|’ ;„`‡PìJ2ìJ;|h‡O’i‡Oíä“;|’ ;|`'¡Ö!”dÖ!”À:„X‡P’Y'¡D¨Ã'uø$uø$ ŸÔá“\££$£¥Ô¡”€ºê”dÐá”:¤@'©$s©Î!•À9¤’Ä99%`§Ìá”d̅S"΅S"΅S’8N‰8N‰8RIâ\H%â\H%•sá”$΅S"΅S2ÄBÿê”$΅S"Îá”sá”$̅S"΅S"΅S’8R‰8R‰8RIâRIÅ\8%Â\8% s!•s!•s!•$̅T"΅T"΅T’@R‰@R‰@RIR  KÛpÐ!•dÐ!•t8%€§$ƒ©Ð!•:¤’ :¤§Ðá”dÐá”:œH‡S’I‡SéJ@RIFR ¨C*uH%uH%bN ¬Ã)ɬÃ)u8%°§äšuX%™uh%°­Öá•dÚá•@;Äh‡X’q‡XîKÀbI¼p‡WîðJ2îÂ+îÂ+îÂ+I¸ ¯D¸ ¯D¸ ±$á.Äá.ĒŠ»ðJîÂ+îÂ+Xî/¯$á.¼á¯D¸ ¯$á.¼á.¼p‡W’q‡Xî†FfÇbIÆb‰x‡Wï†ví"x‡XïKàbIæb ¼C,wˆ%™wˆ%ð±Þ!–dÞI, ÞµmTÞU±¤ÃÄpW½’ ÝiK£Ví$–í$–t´“X"Úá•@;¼’L»£¥÷«ßö¦z%À¯$ïØ!–;Ē ;Ä`‡XìK2ìK;¼`‡W’a'¯Öá•À:¼’kօY’aj ´ µ܅[’yn À ¹â…\’‘r Ì ¹è…\’¨n Ü ·ð…[’Én‰È×Ü¡¯¹%‰}Í-üš["ú…\’è×äá¯É%•Í-I ·„x·„x·$Ç{¸%Ä{n5àÃ-Én ‰­ÜòZܒœ×ªˆFZ‹\BZ‹\’ÓZÉ%ÊjqK(áá–är %<äJxÈ%¹„‡\B OI<ä’\ÁC.¡‚‡\B¹$Wð$—D¯m£Vð$—t%<É%Ôðä–D OnIWÓ\5<É%QÓ\ÒÕð$—ÖÊ-‰hOnIíÉ-‰hOnID{rK2qK`È%0䒌ÀK` r ¹$C0äQ· +†[’1n ·†[rÂ?c»ÄŠG¦e»Ä‹LËv‰µí¸Á.™”8~iv‰ª,ôÀ.±ö1/Ø%Ö^ár‰•¿Öu ¹Äê)ZjîµêÒ.¹ÛŽ]bÅ´ó¹Äêm“$“K&[V»…õAµe[u«X{¨kæ].)íuikä].±*ŽMÉ%^À9çK¬€³/ñA\.™æjˆ —”vIî÷°K¦ù궵7Æ_kÖÕ| Ù%S/–LëWbeQ»s^‰—R¹‡¼¯¾V'Ľ/­šd!¯Ä+¶º•^‰•W-’Å+™æšøá•x-wA^‰}Ø2œ!–ØsL{@,ñzÕÂǤú”3±Ävàz†Wbûxm/q¯ÄÆÁï\(¯¤´}šá•X{oîÆQ«¸^õB+±ÑÖ½F\+±Ù°µ…xùoZd¾·mÔۄ¸Tbsnݖxÿö¥å…ó«Äf­ßÔE ½J8·×˜Ub3ÿœ·°JìxÚ«XãV‰“K^Ü*±‚ä<졕L¶–¥êHKý±•¦€k%ö’ó«dÒÂN¬’ÒvÀÇ´\|3þR¬’i«GVɔîL†UbeQ‹‹°J¬þì_ñ/«¤´]lÔkêp­u 3Z‰=ÇfZ‰ý<IJºZÊ dAV‰=eÔÝIlÁ•ƒlù¸I‡PY%PY%PY%Be•Be•Be•d†J* †J* †J*é*«V©$8*©¤ã¨¤’ਤ’ਤ’Ž£’J‚£’J¤’J:J* J* Ê*é@*«$@*«b•L½P"â“@R|’LR|Hê> Å'ÉÅ'£ø$`Ÿ$cŸŒJ(¢%™¢%PTB‰ ŠO’!ŠODñI€(>I‚(2•NC¥“d„¢“€Ð´…z‹—I2B‘I@(6 Å&ÉÅ&¡Ø$ T6I&(6 E' è$¡è$B(6I T6I‡Ðj“Ae“Ae“t­6IT6IT6IPÙ$Ð1®%V€V$óS6IðS6IðS6É5?±I2Ý°I 6 tÃ&ÉtÃ&nÕ&mØ$‰m’I@2 hC&ÉhÃ&ڐI`›d’Œ6dІLڐI2ڐI@2 h“L’ɆLÙ$“6Ù$™k²IÀ6 XÃ&™z‘DXÃ#kx$kx$` ²á‘d²á‘@6<ȆG’ɆGÙI@›D’L6DȆH"´É#ÉdÃ#lx$ $‘ ²¡‘€64’Ì64ؖ¶QïâIf lÃ"mX$™m²H@ hÃ"ÉlÃ"mh$° $³ DlÃ"mX$™mX$À ‹¸a‘d¸a‘@7,è†E’é†Eݤ‘74’D7,è†EÝ°H®é†E’é†EÝ°H I¦ tÃ"oX$‰oH$‰À!‘dÀa‘pH$‰$‰Â!‘@8$’L8$7áH2âH@ ŒÃ"ɐÃ"rX$P‹dêAÈádÈá9ü '$3ÆáÀ8ü‘Ì8ü‡@ãH2äH€‰ ‡?’)'Èá9ü‘9Ô ‡>äÐG2äÐG€\چn rhCrØ#@{$C{Êa@9ì‘L9ì(‡>åÐG2åÐGD9ì(‡=’)‡=åd9ì‘ 9ì ‡=ä°G2ä°G€ú”CI”ÁrØ#P{äšrØ#™rØ#P{ÊadÊa@9ì(‡=’(‡<åG òH¦öˆ(‡<åG2åG ò”CɔCrÈ#Py$SyÊ!@9ì‘L9ì‘ô׶æ Èap;q‰#¢ÞHPNÞHG¹!Â.¤UÐsÈÉé('o$(7‰+åª7ÒANÞH@NâH@NâH9‰#9‰#@NÞH9y#A9y#A9y#™rR>‚rÒF‚rÒF:ÊI ʵmèËMé('i$('k$(7¶%('k$('k$(çÖHÇ8Y#Á8i#0m$3mDŒÃqX#™qX#0kÈadÈa9¬ ‡5’!‡5äÐF€œ´‘Ä8¬‡5ã°Fž1NÖHÇ8Y#Á¸jâdtˆ“5ˆ“5ˆ“5’'i$'i$'i¤Cœ¬'i$'i¤Cœ¤‘@\•F‚p’F:ÂI ÂI ÂIé'i$'i$7Æ:î|“_œÖ\»5ˆ«Ö„“0á¦F¯¡ª +¾~4_Âዀ8|‘Œ8|‡/âðE2ãðE`ÂŒCɌCq#b¾Hf¾ŒÃqø"‰q¨0]Æ¡‹dÆ¡‹À¸´ -dÙöq’E ¶„ÃɄÁpØ"[$3[ÆI ÄIé']ÄÁÚö%n‹tˆ“-ˆ“-ˆ“-Ò!N¶H N¶H N¶H‡8Ù"8é"8é"™q²E‚q²E‚qcäÄã&Ù"™q“l7ÉrÓ1b@n’-ä&Ù"@n’-’ 7Ir“d 7Iɐ›d‹r“d 7Iɐ›ª,ã&É"@n’,’!7¡¸r“d 7Iɐ›$‹9Àä&Ù"r“l‘x®l 7É™zQD”›ä‰@¹IžH¦Ü´táxøò! 7Éɐ›ä‰¹i û±3Éɐ›ä‰¹I¢CɐCrˆ"‚žH†œ<‡'ãä‰$Ä¡x€84‡&’‡&âÒ6êí@\ɌCrX"@K$CKÈa‰9,‘ 9, 7Ir“4‘L¹Išˆ(7UKÈM²D2ä&Y"@nª–Œ›d‰dÆM²D`Ü$KÆM²D2ã¦j‰€¸Išˆ›æ¸SN2Å|ˆ›æ¸d‰\#K$#KÄa‰€¸j‰dÀa‰8,'K$ñ I¾!‰À7$‘Ì7Y"Â’xCÉxCoH"ð I$ó I¾!‰À7$‘Ì7$ø†$ß°D2ß°Dà–|ÙzAD|“ÞðC2ÞðCà~|ÃÉ|Áoø!ð ?$óM~xCo"o"à ADxÃÉxÁoø!ð ?$µÀ¡‡8ô 8ô—¶ñÿR÷v;»äÌyÞÌ9ÌNÛÀ4ûdö¤eo$Xq–ý! c,ç˜ÏmɧŸ®ªû*V?k"ç“cX†`­š~øv³Ù7Éb]UQ +Äá*pÀ!tR:ƒAà CªÀA‡ pà!xH8ð t +R:…ƒAâ CªÄA‡ qÐ!HtH•8è4<)‚ÆA‡ qÐ!ŸR5:ƒAã CªÊA‡ rÐ!¨tH‘9àd8™©2':D2‚̇T™Aæ€C9à*sÀ!Èp2Re8™Aæ CªÌA‡ sÐ!ÈtÈþC$sâB9¸*sp!È\Hʜ¸—̉ I™ÛR‹Cæą¼dN\HêœÀÔ¹-%–Î I‚Ή y霸Ô9q!©sâBªÎ éH’:',ä¥sÂBRçV*ò5’2THª\[û“T9Q!©r¢BRåD…¼TNT*‚ʁ…T•‹„ž#©D*¤ŠT"‚ÈA…T‘ƒ +Aä B9¨*rP!ˆX"RDNT‚ÆA…|j\R!Uä’ +Aå’ +Aæ’ +©:—TB—TJ—TH‘º„Bк„B»„BªÚ%"½K(ÁK(¤*PŠ—P’—PHÕ¼„B½„BP= ªz … { … {I…Tრ+Éõ¨\߉ +a}' „õ]Q5_à‰y-ðăä6xÜ¿Šyí_•g€í«xÜ¾Šym_ƒÉÝ«€tÑ y¹è„¤‹N@.:ñ /xtÑi;ƒ‡N:Ñ ¹}’«;á ¯ÕpVw¢Aru'¤ +4—4ʗ4H•¾¤AÐ>h´/i*~Iƒ ~à ¨_â Eþ’A“A“ù”Àÿ†igmoo¥Â fj­' b;¯kUi¾>ˈpgAlC7 +â{·Ö@Aì¿ÞWþÂY³ÙŒ òüÛgXû÷³Ú‡±å7{t0ÈóïͶÆü g”zTŒ±ëñäƒ<ÿ~^xޖà ¾× ˆÅâlAëþ×lóL$üÂYÛÉØ& Äv1Bgœ±Ê«”C£¨aKÄ6þ^¢O,ˆ¹Nà!f³CI!öÛ@A„à_ÐO|Fr¿Ä±'â>‡íJ"Ä=o ÄÝ%{K ÄîôY÷&bO3„ؾ̪_„Ø¿Ímbÿ¶¡æ¿b½dï ÄzÑδ B|¿¸~ãDˆÙ†¨;Ѷ—c›ˆ{wû¹ª“ŒØšúbÿVGBlŒ<¯–߸¯Ïl­ÓF·uqO(¤YlàÙòïx¹Úg|¶±JØðÝó7±e.?1&ľ€ó¹&Ä>3[ØÀ„Øg8·,h⟤íÎ- &¤Í¨$&Ä6óÀELˆoøcÜ8bM¨ÞŽC!æ± IŽÏÓÛ¹¢jˆ3!öÏ->6gB̯r®ZC΄˜í™z’ 1ŸÁ#ÒüßÎ#ê7$¼h濁 ±ÛÒ&Äzàºïb6[-…Ø¿ï(ìãQT®gû&¤ +©R!!©ˆ—ŠAH„¤ +y)©ˆTR!©¤"B^J*"$å4TS!!/5’j*$$ÕTHÈKM…„¤š + ANE„¼äTDHÊ©ˆ”S!/9’r*"9…©r +‚œÂ… §p!UOáBÐSçBS¸"¦`!ˆ)Xb +RÅ,1‚–‚…T- AK…… ¥p!UJáBR¸¤.¤J)XR*0%R…0!Í$¤ !UHACRЄ4¤)dB +‚Š ©: +‚ŽB† £!UH!CRАR¡!/! 4’:*2䥣A†¤ŒŠ Iò’Q‘!)£"CRFƒ y©¨ÐTQ¡!©¢BC>T2¤h`"ƒ ©" ,… © +'.ƒ AààBªÀÁ… p€!(œÀ*p€!`R0 ‘À‰ ©ú‚¾‰ AÞąTu‚¸Á… np!U܀C7èÄ :¤Št₾A‡}A߀CÐ7àªo×rü»¾‡ p‚Cª¾‡ oÀ!œèªoÐ!ètúRõ ´}AàÀCªÂ‡ pن@¤*€ + ‚ˆ…‚ÀÁ‡ pð!UáàCP8ø>¤*| + ‚ˆT…‘ÄÁ‡ qð!UâàCÐ8ø4>¤j|'>‰ƒ© ‚ƈ q"R4<‘ÆA‡Tƒ‘Ƈ rÀ!Uå C9èd:¤Êt2‚́‡TAçÀCÐ9ðªsà!èxˆt:¤ +tB‚ÒA‡T©ƒAë CÐ:萪uBD:¤F¤JŒR#‚Ô‰)J"‚ҁˆ t "Ué@DP:”D¤JˆR"‚ÔÁˆT­#‚ÔÁˆ u0"Uê<: ¤H¤JR—mHêÀDªÔ‰ u`"H˜H‘:(´J­ƒ©Z%‚ÖA‰ uP"Uë DÐ:0´L¤j˜ˆ´N”R%R¥J©ƒAê DªÔA‰ uP"h”HÕ:0´L­ùÐ:(‘¢u@"hˆ´F¤jŒˆ´D­©Z#‚ÖÁˆ u0"Uë`DÐ: ´H¤jZ$‚Ö‰T­Aë€D¤u0"Uë`DÐ:´F¤jŒZ'F©ƒ©R(‚ÖAŠ¤Ö‰yiݖk°Ðº ERêDŠT­(’Z·-Qv­ Pä%uERêŠ¤Ô yI@‘”:")u"E^R'R$µN¤HjH‘—Ö óH­*’Z'Tä¥uBERëh­,òÒ:Á"©u‚ERëZîZ®òO´…Ö‰I­sVä¥tbERéĊ t°"Ué`EP:`”X¤*°ˆ”V©ƒ©R+‚ÔÁŠ u°"Uê`E:X¤N¬HU:`”X¥ùT:±"U鄊¤Ò*‚Љy H„N H +@‘—ЉI¡)’B'Rä%t"ER脊¤Ð y P‘º@ER焊¼tN¨HêœPtN¤ÈKçDŠ¤Î‰Ik™ »–pðøäÔ9‘")tAŠ¼tN¸Hêܞ‰çŋTƒAçàE:x‘"tà"¸B.R•\¥AéÀEªÒ‹ tà"(¼HU:x”^¥ƒ©JìÒŒ t#UéFPºlCJ'd¤ +td):1‚ÎAŒ s#Ué FP:#)t"F^B'b$…ÅE脌¼„NÈB'b$…NÄÈKèDŒ¤Ð‰I¡1ò:#)t"FRèDŒ¼”NÈH*‘Tº–Ûäªt#EéFP:€I¼H•:xI¸R.R¥^©ƒAêàEªÔÁ‹ u#HÀH•:#(ÀR0R¥`©‘ÔÁ‹T©ƒAêJŒtۈ˛ïí+¼R/‚ÔÁ‹T­Aë FÐ:¨‘ªu¢F:¨¤j¤HÐR4‚ԍT©Aê€F: ‘*u@#HÐR5R¥NÔJ5‚Ò‰©BòÐ t`#UèÀFºlCB8R•p©AêGŠÔÁ up#HÜH•:¸¤n­ƒ©Z7‚Ö AêGªÔŽHêč tp#UéàFP:¸”n¤*¸„n¡ƒ©B8‚ÐŽ t€#B7R„l¡‘Ð5RejD24‚Ì ©*5‚ÊA rP#UåD r`#ˆØH9°TŽÏ•©*6‚ʁHå FªÊA rP#¨ÔHU¹&j•k¢FP¹&j¤ª\:‚ʵ‹o]ìH¹Ösõå*×Ď rMìHQ¹&t•kBGP¹&t¤ª\ t‘kBG¹&t¤Š\:‚È5¡#ˆ\c RD®ái‘Ê5¶1R¹&v¤Ê\øÌ5Á#È\Re® AæÚXçi{þæ»ÒD smäI¯Ë\=Re®‰Aæšèd®‰©2×D s Åy^íøHÕ¹&|D:×D tMôHº&z¡k¢Gº&z¤ +]=‚Ò5Ñ#(]=R•® Aéšð”®]¹G®J=R”x¥‘ÒÁŽT­ƒ‘ցŽ u #Uì`G;ØÄv¤ŠØÄx±©b<‚؏ vÀ#Uì€G;à‰ìH;ØÄv±ƒ©b;‚ØÁŽ v°#UìH;$ˆI;Ä‚$ÅNI;$)vےe;$/±@’j'€$Õn[G©vHR퐤ډ y©’T;$©v"H^j'ü#ÕNIª’—Ú !Iµ£ Ô. ’—Ø "I± ˆ$µ®å¦å*¿°ÈãÔº–g¾¡ubH^Z'†­ƒ!Aë`HªÖUeêôO8 ¤ˆ¤J‰¤†©ƒ!©RC‚ÔÁ u0$Uê`H:¤†¤J ”ˆ¥"ùPºdHŠÔ%B‚Ö%B"±K‚¤ª]$’»HлHªà%A‚â%A‚ä%AR5/ T/d/’ª{ $è^"$_"$Uù!Aú!‘öATíK‚ñK‚õK‚¤ÊI®õDäZOÉk­'Œ$×zKÛb±'ŽäµØG’[ÚàHrG+Ž¤îhU׈ ­0’ÜÐ +#ymh#Éý¬0’tÝ #y¹î„‘¤ëNIºîđ¼\wâHÒu§Ý ž;q$/ϝ ôÜ $Iϝ@’—çN IzîhϝP’—ëN(Iú¤ïN(Iõ݉$IߝH’ô݉$yùîD’ä†V$I®ôD’¼Vz"Ir¥'”$WzBIªü’Hþ’$Aÿ’$©˜$ +I‚&IR%0I4’ L’¤Š`¢$È`¢$è`¢$Bøß2I²?ôBI¶8»M”ÄÔ÷(,ÉfyF’K²…5a[àôž0Éqý$`’Í<)#a‹[¿‚ÁpµŸB’Ì_bҀ$™æ¨9Ï$Iž;Û2\V$És'Ïd‘$ϝø˃$yþ}|’$Ӄ›vH; >îUVÄ6NæáÔO%±!¾Í$Iì<úÞ®$IÆGõ†3ðÝïIºE–Ï’ô_bbñe°@’ÇfO HbÓ¤Åb’Ø4ùÜ?ñŸÛâݶ€$Ýåj$¶ ¸$‰í+,l ’Ä>*/"’dØ2uœü¦”z>˃;I’á•žZ’$CóÿF$‰õ’…üA’ ¯tµ'Ibáíz“$ÃëpíI’Œ_â#‡$™Vpl_¿ÿvÕ#q’dú¡Ê•$‰Þ,É"’Ä¢vL˜V§oŸ!I,ÜÆ&gþŽ¹YmK`ëH’é”U^äyó£Ô=q’äþCUKF|ee–$‰}™ýâ7á"³åûµ@’çMÞÖ#Iš½­¬/ ‰-²÷s$¶þÝî’´PùŸ§“êîºH’ÄǵH’Rc,IˆóZ$ɦ¬ý$[°ŒúM$Û/¢Ã$Ùl|-d«0™â¤ìsØï’Ø5ª6â¡VÏ¿÷ñ·W|ú/D’T!%AHAIRX’*¤°$)0 B +LR•˜%L’J*˜d)©H’”Ó IRME’¼ÔT$Iª©H’TS‘$/5I’j*’$åT(ÉKN…’ §"IRNE’T9H’r*9$©r +H‚œ’ §€$UOIÐSIS@’*¦$ˆ)$ b +IRÅ’1I‚–B’T-…$AKE’ ¥$UJ!IRH¤’¤J)R*’%IR…’!]-„B’T!…$AH!IRH’"¤I’HH“$‘B’M’$t4Aéh‚$EH$‘&H‚’T!H‚ŽB’ £$UGE’ £$È($I•QHÉ( 2*d{d’ ¢€$¨( ɇŠ&IR4.Qi\¢$Ò¸dIŠÆ%K"L"…K˜¤(0‰˜&Iƒ$Aà IP8‘$Uà I8H’¤ +$ I‚À %©úJ"}I‚¼‰$)ê&q$AÜIª¸’ n€$ˆ I7@Ä }$©úI‚¾A’ o$U̮߮úI‚À‰$©úI‚¾A’ p"Iª¾A’ o$è$IÕ7(ô ’ƒ$© +I‚­6Bá IªÂA’ p$($IQ8H \’$¸$IŠÂ%I +— ‰.A’¢p ’Há$‘Â%HR.AI\’$’¸$IŠÄ%I"K’D—$IѸ$IBãI$q ’KD— ‰4.A’K’¤h\¢$Ò¸DI¤qɒK–D—0‰T.a’¢r “Hæ€I9`’”9Hd’™ƒ$©:I‚ÎA’ s$Uç IÐ9Ht”¤ +(‰„’¥ƒ$)RH‚Ö’ u€$Uë’ u€$H I•:@¤©HR•’¥ƒ$Aé IªÒA’ t$($I•:H¤’©ƒ$©Z'’©ƒ$Aê IªÔA u$H$I•:H¤nµRIR¥’©ƒ$Aê IŠÔ%I"­K’DZ—$IѺ$IBë$‘Ö%HR´.Ai]‚$ÒºIŠÖ%H"­ƒ$‘Ô%IR¤.II]’$’º$IŠÔ%IR— ‰´.A’í”H"­KDZ— ɇÖ%IR´.Qi]¢$ÒºdIŠÖ%K"­K˜DZ—0IѺ„I¤uÀ$h0Ij$ ZI‚ÖA’T­ƒ$Aë IÐ:H’ªu$h$ ZJRµ”DZI‚ÖA’­$Aë’ u€$UêIÐ:@’Ô:$/­H’Z IJ@’—Ö‰$I­ÛPei]$/©I’R'’$¥N$ÉKêD’¤Ô‰$I©Iò’:‘$©u"IRëD’¼´NHjH’Ô:‘$/­I’Z—mHëD’¼´N$IjH’Ôº–[–Ô:H´’­ ’¤*$‰”DJ— IQºI¤t ’Hé$)J— ‰”.II]’$Eê’$‘Ô%I"©K’¤H]’$!u ’HêI¶NÖµ?ö6A)]‚$ŸJIR•”¥kìÖCè`IªÐÁ’ tÀ$0I:`„N0I +`’%t"IRèD’¤Ð‰$y H’º IRçD’¼tN$IêœH’Ô9¡$/J‚Ή$IIRuN Iêœ@’ºI^:'$unGÃBçIªÎ’ s€$ I:H„’¡ƒ$©JI‚ÒA’ t$Ué IP:H”’¤*$ JI‚ÒA’T¥ƒAé IP:H’ªt$(Ýj#”N$I:‘$è$ :IRt.Ié\’$Ò¹$IŠÒ%IJH‚Ð’T¡$AèI:@’*t€$$ BIR…’¡ƒ$Aè IªÐA’HèI:@’ªt€$( J×r—üRº$IŠÒ%J"¥K”DR—,I‘ºdI$u “Hê&)R—0‰¤˜©&I©ƒ$Aê I:H’*u"IP:H¤’¤J$ RI‚ԁ’T©%‘Ô­4Ô!u$EêI:@¤¤j ZH‚Ö’T­H‚Ô’ u€$Uê I:H¤’¤J$ RI‚ÔA’T©ƒ$Aê I:H’*u"IP:H”N$I:(„’¡ƒ$©BI‚Э6Bè IªÒA’ u$H$I‘º$I$uI’Hê’$)R—$IH]‚$ÒºIŠÖ%H"­$‘Ô%HR¤.AI$‰”.I’¢tI’Hé’$‘Ò%IR”’$„.A ]‚$ۋ&‹P+ ]‚$ºI>„.I’"t‰’Hè%‘Љ%)2—,‰d.aÉ0IQ¹„I¤rÀ$¨0IªœHD’‘ƒ$©"I‚Êv‡ÊA’T•ƒ$Aå IP9P’ªr $R9HT’¤¨ *H‚Ê’T•$Aå’ r€$UäIP9@T¤ª$ *I‚ÊA’T•I‚ÈA’ r$Uä I9HD’¤Š$ *I‚ÊA’T™ƒAæ I9H’*s$ÈÜj#d’¤Ê$ 2I‚ÌA’™K’D2—$‰d.I’"sI’„Ì%H"™K¤È\‚$’¹I¤s ’KdKî&H ]’$Eè’$‘Ð%I"¡K’¤]’$¡t ’Hé$)J— ‰”.A)]‚$J—$IQºDI¤t‰’Hé’%)Z—,‰´.ai]Â$Eì&‘Ø“ vÀ$)v"I;HÄ’¤Š$ bI‚ØA’T±ƒ$Aì I;P’*v $;HÄ’¤ˆ bH‚Ø’T±$Aì’ v€$UìI;@’;$/±I’b·¡Ë;‘$/±I’j'’$ÕnãÈ¢¨H’T;‘$©v"I^j'’$ÕN$IªH’—Ú‰IµI’j'’ä¥v"IRí² ©]$/±I’b$Ij]ËKj$ ZI‚ÖA’T­ƒ$ ­KDZ— IÑ:@I]‚$’ºIŠÔ%H"©K’DR—$I‘º$I$uI’Hê’$)R—$IH]‚$’ºIŠÔ’Hé$‘Ò%Hò¡t‹$)R·PiÝBI$v‹%)j·XÉ݂I¤w &)‚·`)^Â$H^Â$©yI’ zI’ {I’T݃$A÷’$Aø’$©Ê—$ җ$ ÚJRµ/Q‰_’$¨_’$EþIr­'$×zI^k=$¹ÖKmÓbO Ék±'$·´’äŽVrôÚÑI’Z‘$¹¡IòÚÐI’ûY‘$éºIòr݉$IםH’t݉$y¹îD’¤ë.¶7é¹Iòò܉IϝH’ô܉$yyîD’¤ç.ېçN$ÉËu'’$}w"IÒw'’¤úî IðÝA’ໃ$©¾;HmhIXé’Ô• +=@Vz€$Eþ$‘ü-’Dú·H’"€‹$‘&I"\$I‘ÀE’„&H" \ IÁ’HH"\ Éß!^ù¿IbWÍ?…+Ù=@nq%»ÕcÚ® ø~>V?Ƃ+Ù-Âyd\ùq[å‹. F‰ÁI1º…•ìú>õ‹(_lþËóN¬d·i\ˆWËþ%ÞØWÿýóQf‘$6x-jÁsD’gid!ü ÷×z©™sÕ(ùåöòPY£Ä8¿yæ Éç- ÆC˜µmQy!ÒJ„ôéQ£Äb|®+É;Ë9zhq´Äî³ÚxÃ%60ŸoúLºd³/É +H—ØüöÌ~YuÄù’ ²d37ªèZbӌ }]í‚o-yà0lÉæ\U©RøÁö¦Kž¿õ,ÂñXûÒν­J%Ï=Œž?êQõÇjfÅ5Ηø1Ù¤„&χ^þ3&Ö[Ãw*»’ðÿ²m6{g±wŸžü(Š•<º¿í}+yæ +‚8±`ÕËf2ÏnÙl±Ëb%¿\ªCµJÌ_1óÞÂ+è(hÐ"Qêk„ÓƒZ%¿˜ì¯[;Íq®=“Ýââ¶Uªd7ü±îìöïëŒ"’"LlîôŠ›¯–ðKäÕ³(“ûNÄĪxÙ)‡“Ã_X(ÜþL ö˜œ‰˜†ø´w­’#ʧA˜Øù€Š9ab¾üãʏΠ“ÃBђ(±ßl{a²;â˜CÔ^´¿vÏ¢8±21±xo_.W¡þ,%DLìû|@LLÙn1Áÿ…“ð|ªóÙeõríŸÿùŸýúë_ÿöÿî?þkû“?dQ^â+%ÅW,JŠ¯X”—øŠEA|…¢¤ø +Ey©¯P”T_¡(©¾BQ^ê+%%ØΌm÷„SؤJ0…M` +› Á6©La$˜Â&h0•MŠSØ Ž²4X<Ê[ƒE¤, ’’ “òÒ` ”-q”ax”*Âð()¤¤C¤¼$%&%(¥(0LJ*° ”`¨”—ƒ¥XWyµC*œH³ÂIÑ߬p"ýÍ +'Ò߬pRô7ë“H©pòK“¢¾YàDê»õÍ'E}ÁR¤¾P)¨/TJU_°Ô,õ–RÅ,ñ…KA|áRªúÂ¥ ¾p)©¾âR^ê\ +â+,%ÅWXÊK|KIí–’Ú+,好ÂRR{Å¥¤ö—ò’^q))½âRRzÅ¥ ½¬–áRªÞÁ¥ wp)è\JÕ;¸é]`)¨XJU;a)ˆX +b–RÅ2± 2åL±£ÆIѺ¬q"­Ë'Òº¬qR´.kœHë²Æ‰´Ž"'Kê²Æ‰¤NdJ*Ð”—Ð NIƒNIOyé|ʖdJêhJÕ9ДÔ9ؔ”:à”—ÔA§¤Ô§¤ÔÁ§©OI©ƒOI­ ò’:•”º,v"­£ØI‘º,v"©Ëb'’º,vR¤. •Hê²ØIh]Ö:)b—µN$v«‰»¬uRÄBEb ‚بT±¡‚ÖA¨ u*Uì T;ÄD¥Šˆ +b¢‚؁¨T±Q‘ÚA¨ v*Uí T;äB¥Ê„ +r'DµQ©r¢‚܁¨ w *Ÿr¢RåD¹QAî@TªÜ¨Hî T<•*x*(„ +Š¡RHÅs(¥¯v–;)’—åN$yYîD’—åNŠäe¹I^–;‘äe½“¥yYîDš¤’¢¥òR=8•”=@•”=H•—ì UÙRIՃR©ª¥’ª¦’ª'Nå%z€*)z*)z *Eô URô@URô`U^ª¬’ª—uO¤zY÷¤ÈuO¤zY÷Dª—uOŠêeÍ©^Ö= Õ˲'Eõ²ì‰To5ª—eOŠê«Hõ`UP=X•ªzÀ*È° +²¬ReXكVAö UªìA« {Ð*È´J•=hɞ`TX¥ª° +ª¬‚ê«TÕVAõ U=h•*{Ð*È´ +²­ò){Ð*Uö U=hdZ¥Ê´ŠdXÙV©²¬‚ì« {À*UöàU=çSü%d/+ŸÙËÊ'’½¬|"ÙËÊ'Eö²ò‰d/+ŸHö²ôɒ½¬|"كWIÙXyÉÈJʞ˜•T= •—êA­lÉ«,Ù°ò’½5²ÄÊR=!+oÙ³²doK‰–ìµRUOÐÊR=Q+Kõ„­¼UOÜÊR=J  z”@©ªG d(È%PªìQ¾Ù£Šd +(Uö¨€‚ìe’=* TÙ·‚ì [IÙkliŠì‰[IÙ·’²çÜÊKôÄ­¤è \AôWªè® z€+ˆàJ=À‰Ü +ª·RUnՃ[AõàVªêÁ­ z€+¨žÀ•*z€+ˆà +¢¸òè \y‰žÀ•½WRó®¼4Oà +š'n%5OÜÊKóÄ­¤æ‰[IÍ·òÒ<¡+©yvçû iEPªæQÍS$"(Uò(‚‚äQÉ£ +J‘<Š  yBW–ä‰]yKžè•%yÂW–æ¿ò–<,[¢+)y°+Uò`WRò€WRó W^š¾’š¿’šÀRD~%E€%E‚å%z ,)zY E¢—ÕPŠèe5‰^VC‘èe5”"zYÉD¢—ÕPBô²J½,†"Ñ[M„èQ ¥hžI ’ÁR%„ÉaAò@Xªè° zbXRóÄ°¼4O KjžÔ75O ËKóÄ° yBXR󄰼4OKjž–Ô1.Kø(—‚ðQ.¥ +åR>Ê¥ |”K©ÂG©„r)>ª¥Tá£Z +—MHøT-¥êžt/—”½ÆŽ¦Èž—”=1.){b\^²'ÆÙrAö€\ªì rAõ€\P= —ªz@.R=TÆ¥ªŒ ªã‚êÁ¸TՃqAõ€\P= —ªz‚\= DÈåSôr©ª— ²G„9²—ŒKÕ=g\¦¯À]øq‰]ù…s(—*}Ž¸œî¿ íKÄñKÄ¥ª_R.èŸQ.:j\õRŠf½)ગ" \õRŠå°¹DpÕK‘ +fÁ”¥‚«^Šd0)—ÔÁÄ\^Bè²€"]ÖP¨Ë{(Öeû¹¥È±æòZ +sY[Þ¸õµãzòÞñé²6¼B]ֆW¬KÝðê²ö»b]–—O°ËÛË'Ú%C¦ÝYx¬Ý,œR½|NÁË'š'…Sª“O5óËVÝùø(›R}|”MÁÇg°ËU||ìoª“Ï‹»¤ +º¤—O¬ËËË'Ø%½|‚]ÒË'Øåååì’û]Ñ.¹úíòZý‰vÉ՟h—\ý‰v©:í"LØ!LØ¥*aÂ.H¡Ã.q”Z˜´KÃgh¥. +!LÒ¥*a’.ha’.ˆa’.—°é¿'Òå?7lúïŠÄü“Ÿþ»?ûŽõOüïýÇ¿ú÷Œÿù_ýïÿçeùïþÿâ_ÿÍ_ý‡ŸõïøÓÇ¿£Î“%Zgáícx¼¦E±ümó‚j¶ŸÿÇçÿü¿ãúùüùúùý߶ŸÿÛÿå_ÄáÕæoŦvþöS„Ò—¿õ²ñÛo?hÏlü) gþ¿< x{–T¡•O{Ü°©}”ÇÇ´µ“CBÿÜá¿õ;ü‹Ÿ¾£”þ,>½ëçÿd­Y­AÓôý[ØîùÏÇmñ§Ïê"ÊÉûyS6òoà wè6ÖmÛÔÛ‚‰ŸÓÈàQ՗Öê‡Ïˆñ—/'D¦êß[7%sZVcß¾*ÖÛ?=ñ¶ˆ]+ÒÕ<`Ì–ëˆHÛÎ5Ž˜­ÿÙOq„ÚûýzF;t?ûÌg<[ìéyÈóQ†ËÆcyHΕõç3OõHùïyž/XÒLî#ÒãÏî|ÆózôÇÂË3>ÍNóàó”»‘¹ß”ÄCþª‡l‡Ui:_ÙlN¹{>ä³ÿܯȅïéÃÆb’ËCšSëÚi[Öó8ò!mWo‡zõ!÷Í^yÆ6Ÿ—ou ôæd±¤àåŸ?ü̃W>cÛcuÏC…u½öù”ÃÚ¼<ɧ§ØCvÛÓYäwÍw·Ÿ<ÿ¼žuÕåqßv&ýôô1Z`çáqJ·.\{ö?ÿžëtmÑ¢E‘ö›ÇÃrxöð韾׾­Ý~ö0Û-ÉBõ¯L}ìñH§¨…ËvaÏ^úy×½ªË®}Ø?lí÷¶æuá »ZPjÏßñ×úÜë4àéù÷³XͤõùåúTžûÍ#%üÏyŒóE—ù‚9½ËÌ?aeãD}öü݈;úÌç÷ÍÖ#gö™ +˜¿‹>Û-û¸^}¶Û¢Â"JÔg»}ÑÏ-Ðg»­Sž7Vûl·“aëGõ™9½-ü•>³ÓÛÞUé3ó“›o>³sKòª.3÷ü1ç«Ëö—Òg»¹øƕ}¶›—rµÓž¿¼[@ ãl×æXfQ€û=^f#ÖÈ1¶ú†GèëeßN¤–´@Á[§évi1éÓ·?ï3–¯¿Æ}–œÓîsŒæ8÷¨Q?GdÜ÷3;љWfå÷ú§;|›sM¡<Ýæ¸ýëšúúŸkžÒ³©Ù­Üþø~ó¾\2!iwT‚?¯,UrܶE´?}:ÐÑvÛ{íñ|AO™èœ‚"6Uó™qJryü5{-wNû"îÇjtÚÓí24:Í£쭔N³hûFé´Ãù㖝fñÇ9_vHé´Ã¤8¼ôN³cvü-fq gœÔù­:Òi‡}guš "‹ò¦ÓŽA‡tÚqk ”Nóà V§=:÷¨"ìæUøúI§¹Î>w¿µ™fží'Îþz}îwšÙb^;‹Öv™ÛÓö˜åúy§› ÍÛ¼w$!Ú)/d§~JŽhÜ·@F"ªnh–E*{FÓçãæ'·E<ß®íôµ‡{xZµ}Š->ìT•N.>lâ}îdØ"DŽsóz†TÛíú¿ïqm÷Z}ÌËÿ¶#ttU]â«?äá\…º†¯ôv j±y&—/¶ó¿|ýqGÊ|ﶯ1<•‘Ýæuì¶³E›µÛ,Bp\çÞm‡%@ðr{Ño¶žízõ›­g,@~óõŒJQ¿Ùzæ~w›/gL~Ôm¾žñd±Ñm¶ž9<ÝÎê6[Ï ¯ÉÝv¢­ê6_ÐøYÃê6_Є{%ºÍW4χ¡n³ÏñPnë6ÛSÝfE>}$ŸJUUº­Y˜C¤” îCº²Û|…ä…¿W·Ù +ÉVåt›¯ljV·}.¬s…ôÈýæK$OõýæK¤Ù^ý¶k¹I¿ùÉ"Õo¶F¯^ûg¿¿ÇºìßÿêŸþ»?þ/Ïfî?>û¹/_Âì[¯ú~ú§ÿ·ý—ÿåÏÿý_ÿ‡ÿƒvþÁ?ÿãÿõoõo~ÞÿáOÛÏöüï¿üO?ýõóÿ^{­ï´|Ÿõå™îZÄ!YʋG.SŠ/Ϛ}Pâeþöa>ì kwsmäwÌÙÈýöþçŸÊ®ê֞ëŽÝ•Mi­ÅiâÑw÷}=ƒáò|ó}Ú³ûîfl¹À­Œñº3GÆógÁÿËfaÄ?x"käÛOÿÖÿÃÑG~½û~ÃlÔ¯›wóF˸[D¯/™x “¹C¿êÏ͑=õ,uðÂ=»#Œæъ&ì9~xW¿æíÞ¾Dôÿ`À ·³±›-ÿH§ÑôqoÇó=™ÑBµ¼›î«pg4`Ԇþ˜¯ ýÎÌmõÃ;ø·Öm¦j{ùs¿aÞvzȒńÑ˾Èø,ëdÔ;2㦾4óÜtk^)W­ª'uíï€[³°ƒ[M˜“N·fr@/[Dú[zþagSa¾ã=Û`²xy]z{ÿO=Äe Y­ pçjàÑiµjþÏ_ÕÀ9xÇ¡ÆãYÀÉ(‹£@a±áÏïtŠMÙz¶hñ=j1»ÅóÑÄï=4D½b‹-³l«ºÙVna>ïÎmÙ>[ƍqôì…/Œùœî Ø$cu |4OF÷0y،±n;Ž™ßþ­0³­ÐÂlžÑ0úÌƉmDš[6~ß­§Õìf‡Èfôð—ÁwwóZ2.Füy«Àq­míÂU!ÂØîl`tþÔ\ HŽâ¶Éû÷ÈÕ0zœŠädªuM±ó¼LßdöR÷ÑîÐ3Ó¾p.Úµ,Fܦ‘m­ö~òǭγa|&‰lÀ)^=ïìYˆl©Á#„ç2g@ +«9˜y·ž†-°½Û“®ijÔå $[~×tÔ8¬=>ßÄñiæû6Î랫M†æfkŽ¸ô‘ß}çíœjÑÂøý³ô¾™ô.ÃÕÌ8ñ£mý©¥»^¬ä"±û±#±÷Ö¹öÈÙ°a^s³ 9ßËx÷ˆÞ0Z¬.<¯”L߉닝Xýٖµ+?ŽÝkl¶ê“íÞ×㈸¿5Š]ñF÷Tiïæ4UŒ‹3lšº“V=˜™/¬GȋÙRüÂ…ŒÜhÇJñûËSh6¦—¯/nv£aù}ØnÎ÷e³µwÌ´]_¾nÏûK·£ Úì³X‰ˆÛ¥ÚÖ쾍øú$›.ÆÏ:< «ÂïͶ÷s¡yë¼3ÛÙΚ¢|%hQd Ýy6‡·71˼u\®PÏ ,ŸüiùH¼Ý=&\õâˆKí%r Ã×G»m¨s¹rÛÂn¡ä×öZJíÆ ¬ÁeÆaÛjõêð¯Àl~<ü1\® £Âlköo2÷‹whY ½‰È`¹kÂfé!ÕY¨–™ýWz±Ï‡ôMæ»ó}ŒÕìÑg®àÎSÆûÈáf‹VڍÙ·K«cµ:fË¢8¡w®e¹³]Î#¹Ž¡;nÜùlÝê <æ‹I按ÖvIžòAcû¢Ñ{k =ßzþ‰ÊÕ¸o³rúžà½÷zZí|fîh”OåaôÀsõ¡«¡›E‘ÅcÙ¹2 lƒÜ£d¾éÆfê™_­kÊ~®¯ /þÖ³BZæi íçÛåoÜKû}– ãçWÙÎÚgç ñÝ=i åµE\g!ï!x¿ê÷î-Õӎè¾2IÍ/ÁJ¼—£×äOKÆgZR_ûè–ñ¼1Ú(ŒŒ=jêÖP ½6¤ä¼·1õþ÷9ŽüµŸÎIbcF|4öYYéþÞC3šÇÝDžC H·¶w}n·.í<*b×íºÎ÷­ñsÛÛ7fßi?ÿ‹‡=şßcDœ¶~la²iXۙÔqçX‹ïÊÀú¹«KžE]í8a㶎¡ËôN¿l1˝ÏÌ1°wŒÛÞxç¼ÖèóÌõy¦B_l½Ÿÿš{.{nzf³Éí{ëÑèGªñ÷7õÀ‹Áø¹Ö)ñ¹çüzº¥¥$ÿ”E<̓Ÿûd>U«2‡nLæÓsÞêJû6ÃįßiÏ̌ÛÁ-ÝÌOÇmiQ|}½‡6pKÛ®;Ø-7îàAY%0·ñ¨>ï~Ó*ÅsÀ¬/ ŒN]h™§áf÷d’ÎÑâ$_† F–z–vXÆÜ´»-~o4j•ü°yX}AaÜgØÅ*͖Ÿ Ì-¶Ò?6[l?ÕÝۑ D‰]سùcôœl!7vÚ7Sí,*/P–½ò[K‡}äö¹:×?f“†ž2Ξ:¤{eÌx8\ü¹«ªN8/ž}гc3;cƒd+`Ë4ÍkÜY/÷HP¬Îáû²õrºÁ¼‰4l9V +ÍR%±~ñ†e<™e§ÅSÆ_»sżæ cSÒU¢¥å³Œ¿Ò«5ñ”¸Y_ãZ2ے??ñãbwp巐o·1ÖôÝÄ&`ùIM·ï)cÃ?éñáüœÙüŒT…2¶¾—”q »›m¢±ûë©ãf™Np´x\—Íñ¿ÑQ9¾·»¸Oü3žk×æád_|ϵ|O‘›=ô!VD»Þö¶SemŽ_ÒGÛglòç]œžã’Íä?ÁS¥…ÍóT…q ïñ<‹òž8°Ìœ›Ao 6“{¤]Ôj5\ݳÀ­/)œc–¢ï̽Ýa‡\éؼµy¬G:WoËÈjFËåsÕea‹~™;ÍZê>¥{ààæÖ¹ÙÏpë1–¥rã+²ýÄïӉõ˜vh¾gˆVÏ8hsø|›G]Ç}†qýÜ|p_õógñ}ó°á3ãu𺯉ÌxøÐn[>F +’Ðð +ÌØc}×ê´œ¾Õhü¾EhwôÀ–/a+k(ßçš[E³sáŠí£lHsff–ËZÜ“ÙýkØ¥ùÀVêvÌ6¹QܹsÔMáõòàïTþ-Í×\Ú-7?Ÿ³a¿n,f¾è æ•ñȏ«ùní«-ÉÖn¤Í–^¿aΩÏ÷ 2N”ÙóŽýí[ý(ÍÒ葛XfvXôÏ" zý¿üˆñŸüñß¼ÿßÎÝj ¯óÇ¿óéã0èkØó°¼Oï<[Ó*¾Ìß^fÿz{w‰Šßo)?]Ǎ›‡ø–cÇ駋à9íi‰å‡žÞ²5‹4ŽÖÌ+þ4kÉ†Ì ó›-ìÃÃI6…Û·™º­‡/ðoüRóB[}3ûõØönG¬<éóK--B2_–(ŸÉä§çU~d>vOÙc€§Eó0[©j[ˆ»Þ¯µ5ƒá#í¶{v4NñHóðՉíp"ŽA†dý7³•v˜-þN¸¯ŸÍßq»q‹åĺÈ>ƒV;‘2Þß#l­³í”÷ù؂°p-?å}Æø³4‹NßÎÈÝêãÎ'ïögfö «ß҈¾´µ•åßõ;Š%òc¼U Å:}s¿ïcÔÚÞ_š§™qßp7áýˆí~ŠçŒŠá=ìþ*6cÀ, Á~øà÷ÔmºÑAè= •¹nÝVSÏ÷Xé]õ§ Ïgž¾ýñw zO5›Õw=Öa»°0ú”Á×ÏxŠ{ú쪯ú¹-½ãç}‘ø<©¯Ê‡mwÜæcl³<=>N,UØ30¿È<|À +ôÙQ££•tŸ;©Ýìë®õ%Ê#ƒûµëñϨg¢æÎ9»¶E”–k¢ÝTܼ'pò …¦ÅƒFÕ{{Ða»ë9¹1ü|ÏîzíÀ0ljŸÆz÷ù‰²U]5'Á¹Í®>\'lÑ4㓰€!¯·ÛTxÅê_¯83s@?ÿ°gLUÿúOªVÌċFšT;eêÝ=ΈQö9Ì·.6‚¦êÚ¦Õãfã&äË2-t/fõ˜Ífnˆøü†¯78‹Â÷áê•Áãó¬$ۋ1ò#°Òݗª6aûñdz60·(‘GåÙÔf«”‹/½ÑÀ‘íÞG¦3¥±6;/¿ÃvVËÀ+¾¢HÒ e˜å®Ööd§¯NÚ¾EoÕ3ÛþåOa惱zw±>´ï̒#øçþ—?haí99¼ïæKÁ­±ôyÜÿBtÍnræFïúvÞ¾ÂÚGÜùcÜ´g{Zµ÷ïãÛÊÒÌKãÐýC!¸Gø1ü³1šT߇田\1áúrÁµó‰ýÖë{ŒVˆg;ã l ó—šÝœHõ;h7_èhñÙÎ(±ð ¤Þã3¼Œ7v}1]³Êr6ýäñ‡ãÓã}éç‡Ì–¼#¸ [|mçv7›Kx%å χ¹¦Â“ý °an™ËŒwd/ñν¬Ë~Ihü<ÐÃòv6cÏýåx¾ÛǙÇmX¹D_QY$²5³g?ð}è´N¾N*3wãæa>(wJÿí¿<ù侪w=ÎÍ~º/Âׇުç†ûK½4sók½ïvìd¾®Ïû· ï†Ë_êZφë÷ênîØƅü›OÝ˦j¢ÐæЎʦü û¦þ<†®õ8e_…iºüÁôû“Õ÷Šï&ÁN—¿7µþpþá„ý;“û?\2üpyñÃ¥Èï,Z~4üÞdóÃiéû)ìëïÎv?ž¨{á­z^‡0z0“^kI»¦=†¼•Wô +¬av¿ áåð<¾ÈG×3˜¯Ï_ÿ 9n?Бÿl×­|%7¸ùJ9Ž*«eßsþÔ¯¾·œ†ü£dCžM¨'FÙÙô,.ÏBÛÇ?û8¡í¶<öTé±8–ãÐÂùHÙM‡¶™·èNj±=¡v—Ó=w»vêï[¿#YÐ׏':Bßxоù0Ïn¶gˆyF¡õ¬ñ½^Ý÷#CßZ¤ö~_ëù?Ô}—Å3‡óK#о×!YnvªÕÍq¬NÍpE›Ñ†P¯~íÅø«x„ñûkÇݎïZõSŸ¸û4‘hmàö=„U.¥ãÒµž§I~â-vܗ8ƒÂy_Û#Gg(‘Ue{#ä¯?}ZûDÎÔ—§Ã’Ñ}ËHÛ¶^k©ívy »Ÿ´¸q7¬-öú +iq³ã3n¶àpœ­Sà®,=ª^âb0ܬ}éûÚHW="ì.m¼:{]¹G ‘7éâÆ­‡ûà §+ƒðÑá=Ì^9ŒÛŒ¹u}Ò9æ\¶_uPàŒ]½òù0BÆÌxÒ¶ó²]ׅ6^© éáT+Œeð±YÆ3– Üæ#­l‰Ó®|¶ÐžýC½µýC‹Ñ^åœFËÂ~ß5pF\wcIëðˆÓsD^g5F{„ˆ¿¯Ýsç¾úàeô¬à4€Yþá0óTqˆ`ªwbܵJâfΖ\|98æ<¿3:KËìi®Þìˆ#—0>ïQŒÑ@‹UÜûZŸ¶Ô³Î”½×/ùk·ÄPz—ΖóÃÓvã&Þ{°;a慏|_cíGXÃ"ɦíŒØ/¶ð­y½Ý«sòÉå¸XÑÚên‰´—ñW¬êÔkŸ7§;ÇÅáL5že"y™}íÆmÆùؑ£Àþ”nKFîÀ‹K~^{Gù–|k2^Ñ[ü©¯jÀÑ7‡×8wºý8™ì9DG¶øû[$—~]¹Eµ·mñqÛþ‹¯½ÍM/nìmè€4¹qŸg¼Bé@yïkÏ÷+=ôÔçòk.#;ŽՌ?Z#]uâh{1~>p¹v‹:oÓÎ1bƒêȎ¹cÐÍXr¸9BEܨà 3î1¡˜q?¯b¤w+~^/w¤2~›<·gþ˜Ð‚‡ñI'§–R€]h5v ´æç˜mܜ÷ǵ]ÆÞ}¬ñeä}=ÉÏk÷¨˜;vÏ6pÞF‹æaòz™›Ðö®Âõ~ž:åpãѼŸÎ#êôð{¸G-ãÌ +SŒvнµØ3¿Ì^V0ŒãôƒÅ «]WF[ óuM£MÝ|±?‚‡ç¸Q.µjlqfÄã.3«p‘<=IO~Ÿ‡ïìôÒèóqOŸgÎ-_ރx*ÊÿÃèˆë瀟å W£VYh¤À´pF`L‰Ûâd«\{„6GHʧÉ~‘¾šoN‡±"¬ãÿ_]ÇìµNÜA¸æ}8oþ”/ÜxôþÍ3­æïÓì>¤ÏF}déÏO†›|U×ðcušù¤!ev¤ÜÎOã§Óùø2k%F/Hç³¼IX¬ôOe˜¸žGÝf[dÁ¡/ýYÆÉtêØdd3³ç–Ôj4n¹ðšAO¿>_?nÜu­Ÿv…±…|bL‰Y¨^kYjÐ +OF]F&}÷i½¯­ÆCáUÅxÿ¢œŸf?×ñŠ·t- ¬Æ­õro´›¿9Œš‡y¶;eãç×á[ª×•gÄÙX“’ [õ¡aâaß¿*<Ì#ý®ä†³’G zø™è_ºn3´–Ã-ÛøöQF„ç[¿õ><èòKDœ§ºÈ¥÷K¸§„wîAŒÄV茗Gš‚/±oo‡ng†>=ÛC$Ëö«¼’Ó½ËõJ?r`êðë¥ÚrŽ0…ÆÍ¢++i*å7ßKÛÔE»î©Ï”d/‰yÏP–͐ÂM‘l—…šÄm9²¤èŽôæHŠëë덧MOrJª·±BV˜pìŸn"Ë)ežoÜD#^‹ÉºN2,3x,BmeàÙ9¼[wmðGYXyðzWàåÖµrÛâ<Æ÷ÆÆwö2·?•'®u›§•Š[õõÁ2Ò¯òX¿¯ÕhÛ{xx?wn^f6éÖêá˾Žsûô¨4 xþ~7³4Ü,w<–"?. 4€9= +ö´q`jÛì¹ã»øð!ÚOûù«#uÄzžþÞÃzÈv룱d&'ÆkòzŸ5J+F>¼_»EQñ˜W®t#b¼"t›–Ùà`Œ±lÁˆ=[½ÙOŽ¬®ä¥ðY‡Þ4ê"ÜÅâ®ösÿ0ž^`ÐeŽƒA7î]âH¨êw=øU‡ÁT>¤¯-»öeæÐbSGjù™_¹¥«Œ»íÎ/ÚóœE¬Npš'/׊ÃóëÆâHczÇö”ríìc,†–ñŒsüSËÌ&æmé´óòYn< %õK›ºöêáK3ãœÌ1:{݁›7 ó¥DþXwîº{¿ø9FÈò­.l›SáCa”×ÊÊøÎXöÚ¬pm{1¦ƒ2¾¨zíéïbB×$]ŒW$ð£e–|¹ÎŠXÀpûM&ióáxхς‹¿åY;b1x¼C/-+Ìyä+8¯“ðêôÒϳ¢b=5âϐË }ÌՃ}Ó²7]Üö͝»\´[Üö2âcÇq¿¯-Ÿ†çhÜ?ŒúŒlá…nmÎýÄð7ëù¥Á)¬h1^öé¾µ¼pûÎcðå?ãL‹òfñ1—¦Ü[ÌCÓ³æ\·ÍüýÕ¿7F^ÏO³²†±÷ØVÛ¤=ñɏÙUžcE;kÔ[Ña­£m´µ¬_þ{Œyáÿ¯×î„9é+¶;‚:ø@1_JR½ú¶?âûxk~#7þª“c-fêµ6¿wFÍÃÏx‘„¯rÞÝñ-X¬ç™þKE&Z ®vKËhþ…HBö6¯9ãÀç<֛™ 8Œ<‚þõÚNd´åWÿ0Êk¾˜7E1÷È«¼ãælÈ;ٍ®ÓyŠ3n¶¬Ä|ŸÿwÀkÌŒœ#œÝßØûZyºÌh[zãÀÀû¾Vß÷©iÍÃFãnÊú=ëIS–‘·pŸÇýq­1¹EºÆýa4J’G(æ3 ×/áIÏ)ÔÏÃxÜû(F\ñžxñ}íÁ Ÿ©²9"ìæˆ^Zæ0.©fYü2ž„ ¼Í^ïò‹P˜[®ƒ½+Œïâ„#ëEÅß×ޑX)Œž  ‚F±jé0ƒÝ㝮*ó9îÚé9uÛ \‚ÕxD)O³ÏaÜ:n9¯•iƁ +Fn oýú¸Ö\l'ÌS»¸QžŒùŽýóÚ»—¸Ì2šëçÚ×KÀl¡C1›ñDY:zMÁpÌÊHÚ ¾¯rdƒØ8Òir>Éøñïk¶éڞÇËæçDü¾˜éÃ3ÒÛ»"úÚøÓ8F},óíu”Ã6"Lª:qí[ÃÙëƆq‚ö¾Öcé¢Q+>ò6*Âõe&a‚CŒ’Œ÷䱎C ¤58¬ Z;>î¶ôë2Îup°¬Õë|¥2‚À8nm+F>„gºm׎Ȟ7ÀØ\Æ^v¨Å|v­êØ8$¹VmºmÚ¤;Æ×ĈÛq#zÕ)bÊ z[ׅ±éT –›†7k9úo¤óùØöXrÙq[~#ÖL¶ÃwÄÊÎϺî6[ƍÌ]I­Ü¼/éáP˜ÊöâÓÄ‘W»;\òÐ1·j‡n1mÛà¬Ngóvàû62k¿Y¯µ‰ 'îõbœáfÒì"v®teÏÊ*Ùvëñ +· %¾£^›ñÇ'¶,˜.݁úªEˆb=—˜V‚BÎè3È6‚=YFÎÂ[|GõÚÉI´ÝÁˆ±ý2–G¨æɶÌq:áxyÄoy‘ÇUŒ¹܏ëãZËçç>´¢aÎó:Š1×Q3¸r-=ÛrBx='ìç[°BG;ñ<}úºðÔ¼Œ{ėÇGÔ®aÓ1™î䗸ŽÔl!ï¦^ë¹¼ôu¥ƒb·8âg!·Ì‘ùЍ3úÐÜæ[;¿3zjX捗pF> 8˾ry©¸°ñsÑLåÊ=òÄ»P1Ëèás)\Í^ªîKݛ۞îêìWïð—bLwᶏk-’yc`liüØU²Ýœ‘\(¦Ê;=e3îSSðÉP=v̌5²S_á3BøBï šÍlx2Þ×"2#—‘̳ˆ¿¯„­žþ$ɶX\ê¨í«~/=²‰jd˜DÓº{áí3Nb0U–k=¹ÝYý2ÚöÈHe‘•"túnš)‘ùï_\mM¹Y}gè>¼ßôÝx:•˜BñcfțOóåW£L|x˜{ƘQ+‡£ô‡Æ¡ë|Ƭ+,ãŽÄ5HWLËw†¥¸N_ÚÅ:ÛÆàð€ôx®3·€·þؙÇ{ÍsÏbd:Ïm~\{åòðŠÍǧñ:ûšÂ–™£/½Ëqân¹¾^Ž¹&è?«û ó5´šÃÙÓ|ÁÜ¿3î¹î»s‡Þò¤©^{âî·/o…Éy²þð³47<—~cی#tD"ôhà–¬~÷ölÿèŸÿéËçGÄò?þϊZ¶D±êqà¸Ñ©<»ËüíÃ|D8Ç·F~ǜüñï'Ù½Ècql'`×C"Ó]pŽÇ‡Î1Îʍ]¹ÌAö8¼ð(²0ú|nÖ*òýj@»»®ör“ѝJ4ëî†=võIçâÚXTlçáLnô`Ù¯Þ@øµ0;ø׸FbM`·äî’-2==æQü:Ü®-–ß#ÎY4ÓÕæEßè\Õ!§ãÔÍú²ä›ÌÏÝöWï<«Ô_¶}¨{• ã¡=ΩQ£Ý=B²Ô Á^>Fø™Q̆#ì¼â´$¸z¾àk×µž"J Œx J>õû#ƒJ.ÜCn\àåÜØ"ՂW]j{6À”&)ü&³œ­Ö㿼ñ ÿü‰1ÌxÅrȍžð=ÚµD[·nÌ=ÃÑÀŒõ©ÏóÂ8¹±õ`WTVˆ!ãyÐcO'†yM·htD­çp†EŠß€4õë~7ܔfÿ}úÍî{äï=¥»†lã÷÷ŒßßJ +èFOˆFs{GrÇþ–§Ku£§fõk!:–ö ÷–fQ-_A›1ËÔNyvQ>àٜ‘ÝiŒ9ÙÌW@Mv¿ïC»ÚVžÊ¹F¥Œ°oì&ÉSÉ6è·FÒ]ϔ1³ç ñ·½­ ¨šðin¼ƒ¯|?²Ùûý×¢Ù=Òz®N ã‘è’-c¬™ìHRbæg.Ðín3Ú›/¸Å ]é}ô&/ž×)x­Å§{Ûáå5y°-žVd¼yw8vân# ßŒýÚèñX »qt¾1ÎÀ̬vm$qrsèR…é›ñ¼ÐŽ9AïÕb_›Fá˜íø®gp˜L~‹ñéÄq‚g;ã Äþ6ÿö—ÞŽ<./L“ˆO>Ý+g]©;ðóp D©„.^½Ó±it¼6î »`Äb÷%QŽ>ŸÅ¸)¯º¨ÈQ4c¨G«S£hŒn”‡Çõ¼³kžkcpw/æŒÖ.dWúYuôkø4íÊL‹?•N'½þT,šÝÉ ìzږvϾ~}Lbvt¶jƹ¾iŸeI‰øjî)hQ@Ÿ†Xz à{q¼àº¶7b™”ÃÉPƶŸ9`‡lrÒمç©1Ø÷8,W³ù{ù\ÊìÓë ê·40·ƒoÞο8ø¯t>bÉÓ=QêÐ!“YûÁ øٓ½JÈgZæ¤q)ŒìÜeòÁ„Cpó|{ùmGˆÏí5ÑG¶s™C£èŒ¶X„«Óÿ؜ôLl+½Ýž+èUo·1d™ï=m,ËòÈÚÍÎò(»ö²:äŒ/ϗìF?’>¨kï8£Œ®ÉÏ»_𘤊kfå] ¿~ã$ó?54{tßL2«©â„›=`/Ì÷M¬•obýÍ8sžñÀ=Úuc …KÝح䶮U†=˜MóêNßöÈ ¸n,Œd>»})6#~éŽfî=!$f\S»B§½Ñ#'Ðõnˆœ›¯¸vîï l÷ÑÓx_ÙÀâžLý›ÌrLj96fЉa¼w^¹‡²Ñ¬øy¿š'ÐÑ@ ú_ƒÐÛ³lànèÄ¥µ…å·<šŒ~.òÅsšyE;¯Æ<¾ÛI¡éfÜÛÍmŜғwöQÐÏlày£ê–¹}aéÆ®GÆ%ÐßC%„Â|5EâlqìlF¢Eo"AÝxìü©ƒïæ1 ³ƒÒoe®`I=Zø:Æ+lÓÌgg²‘K˯Õ6îÎÕ _Âh¬ß‡å|¢|®­8ïL‘ò=›ž¡÷l¯ÜZZ¦Ô£—¢ £ç‡Uϲ8±dƒoº[!ò…(ÄÇ[|!÷)Ǥ™½~l´Ñv›%pM±\kƵäñÛhàÈÅÅ­œ’Ïpɐ´ùÃxtÚNœeÂtBý›Ì–”Ûj´à™’â¶B‡{¢eó0žhöÊ-c×Í÷ƒî#ÇÍ8A€í·¹\‰[Ú Ü&ç +ÊFëÃ}œéZº#Ė–ÆæÍ_Q¨4ÐR|(mY<½r­»Yƒ™µë·.žþÔâÆÈÁ–K£a碼”ƒWFY/y°+sNòÕ- ŒAö"­ß0SÒò”n–&å쵸é‹ék%:ɱ¾£0záÚÚcŒ›—Ö¨ùúhàÌî™N¯qãu7s„ú™±çr<_Ã]Tš,òa>ó;ºÕ7w^_oGÆ~æÓö±˜S!ì‘áö1v |pn]F¾8¤h çžèŽ|—_<爐.»V;-Ë%_\'ÈÌk)¬Â“–ôqòÇÔá3CsîÌëæ Ýñ=W·\ÎñÍYºFâØÙÄÚï'SJd#tãž^$›p£;mõRÐÍ‹“c´“ì‘ý:ªv‡Ñ=lš¨øðæ–£7qWn<£Ð1®ô¼4@BDûn]ŠË±GA…/ž¼Ò«¨¬Y"~ß"¼ž6Æ¡Õ躘Qn%/š[²×_jù{˜–}Â4Ð +£âÕÍ(äÒÅ#4[äH_*óMfOø¢‰*žËX°ƒ{(ÿ¦Íøü'ѬB4!Äà´\빶ñÕh/mv{䌋ŽŒ^7` ÅÝ娲ä!vM”žS$wv蹆QŒ‹aù†²+qÇhÔꍚèà=î€õ©ÅG”;h9蕙ôL æÎM¸÷ê‰gh oŒYœÓÎkR¥;öU«ÓÑÀ•~¶ÔÝZ1¸©¨òåF<J0I÷vägwѱww:"¦vÊ}`k`ͪ¡ßd>(+÷j„q¸Äz×ðºËr:Qx¹Ñ¸4¹N½h­Pc%7m6ڎ2梛cr=½ëtîfº*_^/ž=Å¥›1j]çP¢Ýk¿aÎѬ£53*a‘/]/Ú½6Nœá¡Ýµòdb°{¸ÙTt¹ºìO¥ÃѧdP°‚ku¿¸ƒœ¯„wä¹~ï$ékå:mÆ:›¥ïc\.¥‘ËÙÔp(ô@žÜxœ9µé[îÁÂçb¶q3syÚ#ë]u2ݨÓÂ÷`´È©Q¿Sµ:q+æߍ¹:pÍ"6£ŽPk`ä 0ó¶vÄzùåæˆ*µútÈeł¼GdEI?Þ#=¿¿sQ®7æ,ìs£þÒÁ‚<—Þs¹ë{ø†5—yƒœ?n^snÞìÈu~éÂå6ðaÈ›IB¦€Î¨I®W[•¹<ƒÊ1 Ìç :,´oŸ³8f°ÍfŒÌ€1¸Y“šù^Ã{NQjˏ˜#ьŽÜō‰š²4LSëLê­ÊÌôêC†f9d» fÙ¶ºFSÒ!«„"'Eÿ…éÂӋï&ÂËðl&†=²Œyñ=w,ÍÌç)ÿ“™p×åÖ֌lA´xæç3ê×gZM½èaœ_A®„ܬõIWÎÙ0î|ßMéÍ·#×ô*õ ‘µm-¾x&yñ|§¢¸ÂÈ)XÏÂ5nfO¶+oœ!~H!cOïÀb•çDC3R$lªžÂ^fÜž >.·¦/ßõº´G°V·µéZŒšù܇Æû®ä,۝Ëé—qm—sÍdfß;«c•¥ëŽ¢·Ñ€Þ띴@K±Ks®$.Ų¢÷–ǤÑ>ÓƒD›ÙW÷ù·¾ÉZF†Íöaö J® Xs#»f•]Øz„%E«ª2æÁ¥N3[ª©âPÍx¶:ËЀxWkWñï[O)Ydá®Ù±~0 Œ(—3%¬Â ë‡0<Ý=süâ³øh–µ·­&’úctvüñN¶Þée¯a’(ߞø¢–gp}Å7µú´÷€Äk$2ôÛUvÄÒjM^o ?“‡Û¥F8ßWz5îh·'`·“9òì‹RٓRéäٌ,p7+Č{ÚÃɨ¥E&ûŠL©‘g!e)ô4À2µg +§¶ç‰@WiÑ@•Ž»#<ÉÎì¹Ò.½xäyÝ" Žò×XØÞ2!VG¼å÷én•GŒ֗ëÖ7™9ž\©=lúŠîÞhwk¸þÓsïnr끴{Üy<·’æqêªÓäµÌ8œ¼¶…#þàçe LRÜÚÈ»û‰ß“žà&Ð5õ,6‘ÎHNÖG?ÜvmË SPe Ù\Æh`/ÎT´DFy™ý$MçÞp‹Í5 +,sZ®ÞŽFÏãNwJ#M½ÇEjëùû³åïçIþÑɨã1çƏ\7pZ L'£`ÏⅤ¸è +; 2›gyÞlc¢u§ü7™¯¥öj§˜ íááR:CŽ®:òlMqöñ—Ž ˵i‰-E=û*kq²íä4k5HŠãåÜÞ3¸ýù}–U‹þö`úsŸeÞÒÎj}Ï?»å$µs¶™1×3íéL@¶ýáT$Ŧ'le)¶o^j×Òxò1¿¿€£|+šâ j=-oàR¶hËeÛéÔ;½gfnkæ¹àg½~yy<É7ïoÏU²çÍŸ–òmسê³èQ–›¶‰Ëû–ëÇòÌ+¨Ë˜ y â=smyÀ0®ì.Ψé©úÖn+*¤ô@aŽø"¿«O“­ŠÁíovç€ÁÍZœeè—7°BäþÛ³Ø[…N’l+Cª»È°å†Ú¯²‚ò „hÀòõæéý8IQ×;k¶»&g_HˆTó¬ä3‚Nèô™§ƒ9•˜:¦¨œÍî2MO¥1Ž|ùìûq¾fåµä -OCf'¡ÂÞrŠS¦ý..±+]bÖÀ`êHʯUŒVI¿zSŒÍŒY‡Ê3v//Ӆ¿Çü”ò»xÁ]´ó.|Wíæ÷x3$Àc~?êßë{T§‡'H§ +㎥³iàÙä8ìðõwÎ+ùü­­uö«–ò`W&µõoõ½¨2“H‰å‡Þg9Î”¸_A[¿î'ñ.[N¥æúËxdR4L{Åüpcœù¹¹6ßë +Ò*°¯­¬©¢È›IµÜ;FyÏ<‹Æsg—öN˜6؆_œ‘@Û Õº¬j7Þ<—ûhvN‘Ñß2ÝfÌ©%™ç~%ú{a¶ŸgŒ/õWƒ1ÆÅ¥dGË#g…G-Y'Ýí7™WäÙ±Rlo;ß·²{VK"—Щ†f>àÈܟôMæ5Ýq’æ IdÆqf ý ½§R÷ØS0h-“ÃA—Õyß 2‰D?ΚÃa)•ÝnÚ#S¹î¹Ïp\O.œN5…ØzžðMâÑË4€R_™Ú£tc²~«ŠJ¸‚V¡âc®¨3¦;ЩЕe(ì. »UúX—®šc债¹,ãÝòÂ9×ï“&ñà Ž‹d¨;é}[ž»_Åä…5‰n'¯Ÿ×à&„ܽŒP8ŤñÜ|a.l1cÂQücØxÝ匁â)®ÂŒðeW’ÿ¦)zJv!Ùç2ÞÞ3OÆÙ>L#,FF¬úµÉR!…|qíž÷ŚøãÔDeÜºÖ l{ßÄÎ%”Üàž3×ßs/¯–´Ä*ÐjMH_FF·çô¿è¬µf9 _©t– æäɊQ¨³גÇsí26l«ý9P±¬çÚ~ÞQ\M/w²i)~4ÇB¦ôùçÒUËÿ36Œ×¤o=Š‘Õà5Á¥à㻏– ̵×î™U:O l§y¡^qâ[nUù³Ý£%^ÏQöºa›~m~yœ­YíËì]ÍBæYÐ,| ƒÃ7ù•ÇpæÑYÍ%ß¾ŒH«ïñŒu[ºx2¦—¦Æãp²›O¥°³‚——?R~P¦“>Ä£¶çË".ÅžæÇ3_©x¡“‰-„kô ]%õ‰¼ËGƒ‚;î_ä¹|r—¯¼>çr]ÝÉ¡Ù§ã/&—öß`ž4háqÆ>óKœËœY§ûÌ¿NÂXlÍÃÁAF6_©G϶Œ893-Ž*lè̔–QRç/ÄÀy +֞¹]NܨFOQrráÞÒZZF³é;³3å‹~SÖ.Y÷ ‚]æC5K,Ü qÇ +‚x.Ô³z ñ +p5gœ[~“Y¹#ýyu†©p£ß¬ö›àì0晓ÅLhQwÆ*è‹m¬ï†$¦Û™Ú¹8¶3¶àñ{qéÆ=VƒõèäÌÍ3wê2pÎ½í™ ñÌâ=ñ¾É€îɸh€*gzà Yñém-7gAD-÷&g$púò +üy7°9ºÐ91bÔûyîï¶jÑʼEz³,v +(ý@í͸&ŽˆŠã»Û3Ôì.™åµ>°(Qå.ó>Œ€.ó'ð$ß<$rFlÆ7™O‘×AŒ¿øŒôa<Ï[ ¬(Æ=·²™׌„Øœ¾“RXó6Û2oAÔ'Ÿ‡Šy wgù F„k_ç‘c<Ì̓£@¼eXß³»Œ½w¾Úìׇ®Ð¨ˆnǃ›cӃîÖpÆFÔ° û‹oF™P<èþ¢ t$ìÆ|…áoÞîE»ªÝcØ Óqža¼&üÌa0 e[y±Ÿ?H*çÃX70òèö\ÕI |8=«bX’lœ«Yw•Aºã(Ÿý™X ²Õrš@@œÀq@Âïááí|}L®Uŏ3¹Ò‚@ËIaæ[ÞU{°ÀƑˆ ù§b£¼ƒÅ¶o¥ÃˆsÑIGFþž ×±8„×Oº£,o×îclΌö{&)93S¶[OŠIør!¨šuhpÆ©Û§îfV‰ÐZߌҗ¯¾û Û@4"æԘßIšR®0>šÀ£XžJœô8 ðDŠ!<’ͽÊ|¬üÀ–Õ`^d•©4ãFzV¯0÷žAXÓÀ¾¥ÄE ºÙÖ0T «_x£Ð¬œ½Y9Å¡z²‡ÉÐ"dߌŠ(; +xay,¢,¬Ísq6kI3ˆ92dÿIQ%Pü¹Â=00ã ú‡QÞÀH1eîò!ÚÊáŒø†ù$½¼Ÿ`V3+GÇcÜ.îWeê¢vòÔ+ Ý÷w ”^–ZôÎÈhÑß0_IŒŒ Ÿ,+ ‘Á"o ŒÙÖ!«Z ó‘釷u¢Û³ÄúvL¸eˆÆ¾xõžŽ¨ÝÃQˆŸì’?ž€G»rawö ¸ß0wŽcò&®Au;؉9ðê_Üî7ýÁ£t…{&“¹g8ïJ;Ý/B‡œ`ú¢ƒ¢ýÆHðº™3:U Vœép|EœÛ÷7ð5ïŒM™âR¸3V1«.¢ë£K(KœÁzÉâé`Šc1ÌñÒ¹òìãïsc–¨€^¿anÜXÏ|¯ûɉiîmÅè'¦ìø×If&MÞõÛ³J¾ÿüÊt·ÂU®Ls7÷Î!ð–;þ¹¥qå?åd®—ƒód°ÊE„Ò¨"n–-ÿ¢ü{Tôûúƒ»Šaì f׸ßd¾f¢¶à\©ÜCðíǍ¨õ>3±— +·ÿ&3Ò¾8NËC1h¤L˜é¶¬(¬5{s°¬bmÞè½ð¹ E¾¿%yë{áê|aþ晹#ŒUø†yà¹sÏ·7òÍKšÿ‰É¯¿¯òå„Ö¯òå²x\ÅÕßåË?,«|yót„%ÌPöw;ÞË +æÊóƒò,øTZ ŸYÀü¼v,ðCÁ_õ{*»ì iQ+„Ùù7θUÚÆsùÓÀ}s-ѱ^BýP O9«ÛºêRÀ±ÃA@ñ4¬kï_t÷i[õ›¶Î±?Ê`w•¾Uy% X••:òDÁ]ckƒ1ãœ9al„‹/­¤Ó´0¾­Cn‰w;Q½Må,´|#hɍÑÀQ©”u-)z”t +ãž1^«Øƒ™S«ïU@çÌéTó …v­Øø9î¯u¥­ÎÐTß|UUh™ï¬í[»Ï_z–íiêïu-¹Ví<ó8Ví¼¦¬¡6ªç9¡‰Í¤vž%ým½ŽsЫ‚Õ=s tȵ³ðòÔûþYÛڎ"ÈsWRØόCÛqþ¢âXq¯Â=G­´Šü¼+‰rí‘'u«ÈO1ªúï¯?}šI4ëg¬_‡Ê+x}^Ž´F–b žòûZKÈ 1KÅXˀ½Ìy[žÜŸYHûe2ºª]Ç÷F\GÉÀn§Zcö÷µ^ÿ’ÝçéßÆU-«˜/$ɲƒ_d–R:ž(S›¹êhÛÞb€‘×fÒΈ&ÅC¾*†¥­ƒD _ì2rĜu«eË>W|~^iÁ×öѤ¥(× ·µÑ«E<µû¢£¹¬XE–ÅÉÊ=6¨@ÿ¾ö’OT0Õ§±Ô¿¨æ,4”ù-dzE\Ä·£åX¬Q@ƒkÛ$&Ͳ_ím{U/*æR½¨‘¿T$²HG…ÁÔêE«Gâ¼Ö¼h±ê\ՋŠ±V/*æ­Æ¤{Sre¾¦Ý3ÐUc4°[ ªþݵ[¸³¼2°øZzïjbsëCQÁ[„ð}Ñâ®dåÔõ3Ä9Š‘—pJ@˵–¬œ$è„ؤÍn•œùÅÚc¹ÿ~؞…/m£ô,Æ_sË•ʵaªÞ¢žÂ2šRg5ëb¾r=e!ˆ±•YR©•e™‘U´ÊµÆalø|ÉðiôåE4P͌kõ]=éÓ軟¼ƒ4òég›89ôhŠ_ƜSö–kOÅ/Øp:÷—©V3*Fj%#õ‰Œ]ÒÚ©Ö2j +0y_kùûbT­úDÍ£G1Ò}›VåÚ±Óq[÷Aq*yoe5þ ü!njêaTÞ«OÔŒ"¼p|»V%Ù=orŒlEöxZz…ÎåTk™âí¶ØVS…Féc9àWaÖ'ô'¦D÷Hb%oŽ¶âPUbô8—™Ñs +g֔xŸ)櫆9¨¤Åq/¯‰mý⛕ñWùš”ï©^ëEjwuvŠñøe•ÊZÖgXñÉnáÖµ)ZU=ö‹g[}%n5ŽŠØNJy=Ù@àL“È÷—‘—;·(³®µ¥åìªàq©îP1Î÷èùØȉá­(l +ù&ì}ÇÒã¯9 ~p­¢]Ž¬ŸèTÆTŘÌja¼ëFGDþÂsx.£Ï ¦»ÇEÀ§}A»Jù7’"ŽGϚƒŒÖÇ ¹WàX‡Œ«ª—©–è…-K›@”¡3ÌÂ/ëP¶c‡Àï—Uy]¼øùäŒg)ÌVÌ-ƒ7£†v‹‰/ k0¿’#¾­z­÷ňÙÐCYßÆ=J³®]fv“FüƱ¡M\Y®HI6”T¡åJU°X ¥O£GæÊ4͛j6ßY¦ø´¡¿ƒV7eÅÞ1݃¦¥èR®h_sA5:®““Išs¼fÂkó à*cë&¾K%)[×íQš4Úë[û0õí-ó™Aû&ÃjÐl-­¨Q`\óí©Y¹vfí¢ƒ”WÕháôYâ9ÍF—ŸlUöNÞû¨]tÞŘÎÊÛ{ª^{üB¹ÂcfÑeLNSÐ}³vøIæN‚ŠeŒ µ]™Ø¾âçÜü$Þb™O2[P±ÿŠÑ†iË{_V?x7ª i}dJÂÈÄ"€¼\kÓUˆå¾g!µbT´PNm2g°¿Uøž> [°ô™Io”ô #bÛ{Ü@¹6SÙìWbe/£s ŒÀb¦·ª‘¬ )ª²ñ÷•äûu%·jQê;÷¿Í³é@¹ëµy9 {£ÕjôwE˜íÃÒº¹Q +ÏÞÀ}0ˆ†ÆÈÔz¾^{pÚfgÒ:E.Æ3€¡ôöË|ÿ²­Œ37ã5J©HM¨7V¢Û$jϜ…wËzðª¾)>°9u‘ °–¹Ç –)¡b +ñãŠhõ@¼Á$–G:C› ¹qrfŒéî‡è|׆;•òw§jV¦Ðê‡}ñM¤âLÜw{ð̹ø´¯ýºÑü3IÂÎ?ŒlxŸ©~|wí{H+¶BàˆÔ©¿tœ‹›ÄopÄò:ŒJ§w(®-Œ’0âS>‡kƒ vcÖ +ÆQxD™>î@KR“ã‘w “/‡xfÆvÌ[ΖýM¢Œ£å¼_úµ%ðý;PIsµõ¤#reüö¹ï¹ëUHÝ>j±Û~ՈÃUì^kހ˜Rærߜñw£¦ë\x÷£Œ~-Ì ¬º„[¦33à\ÚNG®×ë¤Ë]éïì‘ËIžÖ¿3z+_™íÈB•—öõeŸ‘;틜֛®ÜÉíŽà¦k³8qíX’Ý}ÿ~ÍÐ<æ&èW¾XzùÐ3ý֝:¼$È2RÉGy9].×µJ¥îF¼é®†²­Ã=µNN^ƒ²¿º“ã}ÿ_… +ûÿÇØ L¥JD(‹Oßýþ GxYtœùnG +rp‚§¨Ÿ`g¿É,×»Å!¥§˜?vmH"þ6Ú.ùן>Í +µòQhÁ¿ÐŠ +}ß÷büUO{Þ?¸–jÎ=κ?7Çooó¹ïÄ.ëÊփg£*?+§ }c3,s>h€*L/£cö4€yÕH§«M&3¢ð¯l¾’¾³yxî=̹s­Òj—ñtGXÄ׏avDH#ãH”£éXL@¾±t¡j×ÈèyµšÜêµé Þ³D³° ±EN#?ñPÚ07 +;´fã¼( >ã¯j oýûku¾únUIö=2^GhcÙST~Ǫhpì녛KmžÅ Ló@ïk-Ã{,Óä…KËåÎÿå2õëËPþ [7«€å ,sã× Í­×¶ˆì‹V‚;“í¶ÆJ(¾qšî+ª ݀²ëé #®#.²å}­’û—FM7BX®t@Ö>^WæJa/LF'“o\î5öF$\ÛsßîHÄ}³׋¿8~•-~~R¬\¹>…‡¿Šûç“Æ|EJÔhT'Gå;_CÜâAÛ¸r—WQ`ü{¯ Š°L®¤ûÏ旁k\N$hØ3†QðRѹ6â³!êQÇ|ÙN<’²Å¯ Àëß]yk×öc[VÊþ0‡ßˍÝwR}@«LÏ’¹áÏÿ‡½w]Žã¸ÒEŸ€ï€?Š°#6à¼UfÖè—DÙ>>A_Žå™ñŽ‰ %lƒ-kžþäº|+««A±»š"»Á¶C6´ª*;¯+×ýCîhzIì;ÚQzì'Ä ô”Å,ʹZQJÃNØ٘'Z[g}Th[êBMßíÄØë’wb’óÌAÇeÁ ´Q66J¶YX!JE¬(«ï±¬­ÎÁ”èawš’5Uˆ±8Ø)¼ÎlAÒ ™®h J! +¹ŠÖ < n»U"g:¢NvRZvúc¸Ä¿n %JTÇCD†É»ŒÚ­3 Ø® ‘òÜõóNDü¶V/,#J)h>Nˆ¢;;TáZ}W³Øˆ¨õÕ(å°f ¬Dˆ‹H]¥ÊKªå; Š P£œÉLkB¡¯žŸ±[„j>ùYb˜Í",É!ów&Žvk…ü ¦*q;†`†6Þapºì©Dõɂ™T1'óê3Œê“ OžÄÉ®¬›*‹_}—BcÒ¨|Œ‹±¯§ò+dÞÅB¼&vipÀ‹Ô`q0í&Z½`8k^%~;«D.§ci'›Çg$¬míVBÆ@ÿ)6›“8ډDö';…H„Ÿ‡‰#k…Œìšàdúœjn’/Úˆpºæ>v{×àé}žÓªÛähÅTû¢j °ôGP‰Ðª³žâÉ»d)+`ÇèDD(òdôAîDëÑYYJJ’p†l=J͓ëL‰ÊÈs/æ°B¬CB'+ + ÿ˜ÃMn¦œ€d‰éÅ+Eæ†2{×<lëÕ¦RÎ⅚Β”Ó™¼-IùaâÀÍùû Õ²¤¹šøÓiŠ""5 Riò¹ÚäMò1U½ã-BϪ„‰·ˆ¬!)¨mފ_RÒ­›ُIe­Äµ²ún¬f™ÎQ-0árôT⚢›_ë¤Ä^÷ۈÕ.Øs­…Š§ïêºÉá@De;“Ì59³a§l›CÈjRGÍê.60VafÄ ·ò®§Ñj« ¦iÌn'ÇúWÎìÈbìiÍâ…N¡阾kØj]gã•ÓåT¿ãâ4º‹M$b,¦ ªwNJŽ•  ¨Áiõ]l®•V5»hªãòîT¢jËíê ÉŐÄq?4¹ TW;ñnDõή¹ë½  +þÓnG"h@y«(°wLFØÙ°øuPjŒ°aNMÓ㫙ڝÈVr¶—kM²)q$S3Î?È®êU4Ϟ k´Üc©;YÝðÚf­aF È·ó©)Ów½ÙR¨ÚŒF†{d€x¡ëÉúúê»hbÔªªX!¦i }'3‡¶ª¼¢ö\€.5ªI<° %L­~.g¨5½kþ¯lăõ-)9ڎФ"r¿«™6ˆO›‚{PæÎ[µIŠ‘µ +È·4?æq•8e•¨å§ÐÈÙ*t`8`ÚÉB>Ô)ÓY#]í]oÙн–ï„8¬M§‘á&§Ft¨“¬ÐߘQÝ¡˜•z  «ï¦då…ÔEDÙV—fâNêåºú»+D+L9%öøÉ)Õk¾g¿9uÛَҮ*S³•ŠÁ»rP!–2#˜S²Õ°ì ò°FtÊ[¾Òˆp<:õVãXߍl˜,֜È¿øäÉTõF£‚ +q,N·+§3á¦F–z;,!¢Ú%² Bw†M‰5…É.62jɳš!é9Áj †bØeJœ]õÓwƒ!òz)‰¸B¤ˆÂÞ@'çîߢ4i¯Á1| ¨´'‡ ÄÙU;}Wƒµ8¼ƒñÙV‰Y +.c‚ÜQ Ø?’(ø°2šÏI;&rØôÝ<ZÆ°F䄝 “âQƒ“qcuÁ(’ä4ör´ˆæê×c¸(ĥזëD.mŽ!t²Æᱸ4X˜zèqK+[Ù¢O¦ïF°ÃØ+ÄNi¬C¾yâ9´ß¢à¿q@|vvÚW‘Nm–Êý]º$¤lUkUkmvÒ 5JL¼$…«1þŒø&TÒ5%! + Úí(òñô]gñXÞ´–"†EÌiäz½ŠxI9s$büï's2b@©r–ÙÅiÕ“0ñc!vwh“ÐåPDºýD)ž©ßÆåƒTS ASãxÉg+×/Ýú–YA>r):z`%ñ>©B8°RŒŠ¬=֒Ý\)ÍÞSX ³5"q…èû‰Ÿ’-DŸŒø£úmMmš'êE'{5˜óÒº™f̵NÄiQcÝô]5Qó¡Wˆ\¬ t2Š¾«×†iÈUY!rùi뀒ûº‡Û÷d)6dä ß+*Ïô݈€ŠÂÀ´ªE¹ÁöՄ:}× QæD—âh €Lº +ãæƲ1"{D…Bã:ú껥 ®Á6AÄ&br—¾dpcoÌ'–{{:ÕFW‡Ð('ïfH«āêìF¤#f™Qrí従è‹(”2'÷ Â2蓙!õ]_ÌØ3JTøœØ¶n¯L¡µ¸PiFˆUÓ£DÓ ûBkqÅ4¾ÑÔԘ ُ’R4@Z‰°"*êâä]Æ; ži©"QB¹A„‘Gæïrô–D:i¶Ì„˜Í €\ þ‚æ !?Ø òªÄ,‰*‘-j”6«Ób¸”V2¢^aÔ<¦"džÀ–ØÉy´ô3°½ +‹ÙŠÌNù.ÕîLf7 1%5ŒyN RÍwfM¦ðï­°«ÄZ‘XÍ+ÅãûN¶ +AA–øö¶T.³:‚83NßíE#ƒE¤®å t2°±&­†^ò¶£Tvš÷ öBÿq2±ˆ©%&SP¬ë= çDCa»ŠÊ¡jå +±]—èÀ0“Fð1ÌJv å0”ˆ DæäÝ.¶†×ljg.Oˆ`¿^î…é»”T´*M¬Ÿ@Á3G©CgÚ»Nª.ÔiíŒ"o4 ¿;ÈÚ¤Hü +q2„)1ÈÔی’‡€`ÇDô ×Àû\¥ ´Äå„{¢¯p ©Ã()rä)¬sÜéT©ôõ3U?)2vŒ¾ÉÕG1íÍ š*yp˜ì%(@ˆÀbq–ÒHñ¯ñ¯¡`¦é8À0£÷»ËÕ¼¢J1"q-86VÈoæä¤ —4É«qJDZYcò.w #ÚϏ‰ãšÏäÄü³Ä0%vg¤è݉vk­SUp¦ã*(¤>Œ:T+³åTœ¿«ÖŽÉ¬ûzMÈ}m¹[È{Â.pf¯XÝ1]w›ì®j•bWö!ˆ³= rßÞ&MŽAœ€¿ÚqÞJÕö7ÍVÙÏ ã™»aÊ[fýl“/_© ‘«?®r "ˆdò®ÅTw>´J4žµJVþF­¦¦Üe•8ᚫdå°D v(/æ¾®óíIìÁôÝW. ’86‰•QHVtrå]Ô.͂ØpÊ%„;  W”¢²XÑ€»¯ˆù¢‚¡Dùž4ÀÙLÞåÊ½Ó q•È{ t²••{f‹U‚9S€òQËÅsqe‡ÊY©hmc­W*†4d}ï= 8ÞI«Èâu^’++‹Ì@gïN‰UÓIpJ6q‘Â}r@y+ølúÁT%2*NÞ5©¿‹¶«DƒWÉqZó:k«Ó2ý)ĉ _Ú'§¶‹÷SâD˜’Mmà¸Uv{ )Õ×Nf¬ ¶ +‚[§ï¸ú£âK_]À½ÁD A㫦ïvÕÉ D•õÈEŽüm51-:« ÛY§Ð8¿J„ö‡:Y5Å ‹ê:% 5oªò¡‘í9}×Ě®ÕN‰ xBîÚ2GˆJy)2‰ E"U‰Ö;–½kᄰû˼õÀ4`"G)±Ed1ÅHñs™uq(ßÊȃ`"³ÓØ×É»v˜©Ղ +;q2„)yô 1‰Ê"؝!¥œ‰Kªþ«D0T.f°únH-&jtƒO¢M¢ð¾Õw1³^ÐbæDFæ«à¬AˆE4º=k•Èð-h “±a7ÓfŠæêa¤ÃRÒê»u´L³QM‰Np²fÉq”9ìvÆU¢Ù$WÉj¿ä¸æ\»ñSH.Ÿnåðeg2ò‰eÌ®Ê:‘³0{+ä•ê³å¡˜‰˜ˆ¨=5's²E½ÅÞí¹bmW8#6¹0OˆÒÀèß黫L­j¹ç qb¿Ÿ’Ù°<êE+X¦>ë6µÇü´ ±õwGÃьc¿f:qâę’³`](ӐúyQT䧠1T؈i).×ôMÎBG9â׉lùDÌEr´U¨DNÀ+Ъ€p =ÅQ$ÇáF³ ü˜¥š×œÈCÅ‚¬öqeƺ * 1'¡ù Ê"V*^gïˆkÑ c§D…ÄÃFÙBŸ&û”ÿ^".…HÑQÊMLßM¨7ÔàœWdÃ4­Má ßAÓº“t?u¨rؼ¤Mß­(ÈÓÝ´«Ds鮒QV¾ç7tG1ÿ”G)s*¥ïÌÍlgDEuUO‰_à*Y]àÓV¡{1‹±ºÕÐÒ&I;“7yZQ‚¼ÊæžU’ï;Yln§Ód +*d"U´èçƒ$nfV¬pž½[Ä&W¥Ê|Ï2L®üˆ]ØÉà+D)‰Ä¿$é’JÃïçAº¿‰®&©Þ$D@‚¥^҉Yì€jŽöî@hT3-uB$) €œûî=°p•É1 m¡-Øá‡í݊RU=`fJœ×LɈÃÀ# +Èb!;ÔWTÛµàN’‘Û¼‡qÖX´ÂƒÊK{†™Æ=}²JÕ$äiÍתē¥ÙÔô@N"%§zÉí¦Ú'åoØ.þjFîu\ è¤+R )[8Ÿq@j,QG ÌÁª)LˆQN™|>%£ê²·´–nÓ÷½Fm8ëU¡,Û¥3="¢(¸ W1dJ/Ì•|nÒrrðGŌƒ(2£ÙÈ'D½å1úNvê ô&˜÷ûx2¦éÍŵ¢¤ôòô]‹ÑïÑ F]õ¹“9.;Õ]±b®¯â +-ˆ¹ê¸êTÍed©Uô T˜0³Ç¯'=X!£tÈ´U˜Û|7à(C€í~ò.%º`\f 6"UC°Bp²±h®}SPô YÓT“QÕ+?É°¦m ‰}“wû©àRG%­»géåŠÝT7^=Dœ¥›Ä‡ÒMæÄ0%v o|è݇‰ã„87=¯tl´ú“tA–KíTØÄ•±CÜà)ØÏ(qH¶ (»P”B9ºÒäsÛgòfD~_—ΧD7 Ýîdf­x*(жÌrƒò¤ä딈J“n€«ˆ7$c“,¼ÁO5þ¤ÓVº4!÷î»qŽ}œn@”átFÜ`YúýÍòÕ'ÙiÊÄlAœ%$Lè6“ò%+;UÆ•‚pà^­’'‡Óqàfaa'µ>OùÌáôµú®ìš0’U¢12ÔJ«`eÎ#8f…í9/pg+,²g§M˜é„8e¼L‚†€w“~ÌIå‚d±v¢4PÒqún¯XEÿ +DىUŒžÒÀ”l=0/UB«Ù|²g¨È±Eιi1:ƒK R§›/O”ŒwdÚð°‡}ªCè!˜8¤Úlº³'D ·Ç€l vŒ—8u1[ɚdèTJÄ É mïrzï ¯{BœÆtò”Ë“J€8» 6aåîpö:±`LÎMWÖÓÅûêk D|þ§Û›¿Ü]ÝÜ_Ý|z*d.»1}ðäO¯é‰wòèÛÿøýï®®[3O~cžüۓßüýÏþtûâ’þüæêâþêöæü{ðåɯþõêú¦=:mݺ»úîíýå›_Ÿü¯'¿ùêîî|öÆÅW×/î.oèy8ùÍnîû3úŸûŸ^_Ò³_¹/~}ò›¿¹ºhÄo[«7߯¾øÏóë·òæ¿~þEª4BïQ'¸Wû:ŽŸ6ÇOŸ`mo<’¯^Üÿ°ñhôí½Ñ—Wßÿp¿ñðúGÓíwÿ÷òâþëÛ·7/Zÿ¾¾}ÏÙè|É翽zÿfãQ®|óчúÕžuýú‡óç~Ó1^½ho¾gLôÎÿÚ ÇûÂ&ïßÞ}÷öúòæârÓYO7\büÎGÕÍí·÷W÷ïá!}Loøí¿]]_n¾{W¾ùè# ›íæí«?_ܟÿs‹‘M?ùø÷]Ó6Ûwço.wwùßoÛþÝüö›}õÑGHGnÓÞ]¾y{½ù½×7á@ïèºÿ™®?Ìý&—Àåߦìäç;û3óþ‘äêfÓå¸}}yw~{·ñ‚ô>ú6ûööíÝÅåïïÎ_ÿpu±ñ÷ž©˜Þt7{~v®nÞÃ$W>á©yzûêõ훫ûMÍ/Ñ–ÃÞûÛ¿ùæòåɗGmo?ÆqÔööwDGmïQ—>gmïåÝyì¯ÿt{õæ¨ï”¾·ñ¶=<}ocûËQݛ í¨îÕ½£ºwT÷>;uï4<…o›‘ì¹Ê—Ê·ÅˆEåkzÐחÿ¼¼þö‡ó·?~Þ¾¯eê7÷/¾¹üçÕ9uh }aúÑ'’Xç},ÒÀw×oß#Š®$ýûó·oÞ\ß|-c<Yzã#ôbóËëŧ¸½6ÈæòċO!PlsHöýÀß¾|ùæòþëG|ìÿÌ#< ¿±ÀðæõåÅÛë󻧷7oîÏo6_“õ?ú¾Û8áÍÛ»—ç—ß^œ_on#]ýè82¶]ÂßþëõíÍå‚%ìÙàc¡éüóÛ÷LÿàyXפQÀñÅíõíÝ¿ýøƒXD6”ÈÚæÄÉۇ¤›œÎm|P÷ÜÄáÝcÙo#ÇiØf,ÿ³ñXþçÊ ¹½º¹¦æ‹Oa¼üVï‹gÊHzœÎ„-oœ}¿@ÙB¶ö&ì÷šf´“d_˜ÁùÝÕý¯.ï7wÀSØXõûGÜx8ôêÇ9Øx ï± +M’özE6gfÿø¼lóyϐ§ñŸì¦yd^ø­¥}¿:¯¯îÿr~õ>ƒÆg~wŽ®¼½™xë÷‰ò—wß_ÒL´íázŒkñËuà2´Ø öÅ#1§m•²ßÆ4ïCû1ôy%‰<½½½þúîòò6vE<ÆȨW×ç›;cʈq¶qæüÝù‹«·›o]¼~ÖÍýÖ87ȋÍòbŸrh*æoï^ÿp{}ûýO¤šÙÚ±µGÃÌ6Ï`ÙsföhÓØ’™>šØÛ-R¼öü¤o—N±ÏG}ã‘ÚY?¸ˆÛcξz¡.gã0âÃËÙßXÚ<̜ý-ù¾_I¯ÔÞ_I›k8v%d…¯6öA<ýáüææòúÛËëˋmÔéõ?úžûëÆ.£¥ƒ\ÿð£ò=ÑZ“x»4—O”ßòYòî½¹ùnã]¶÷÷ÐÆ#9´{蛫7¯¯Ï/._]ÞÜÿñüõ]F¯Î[S;&A;r'øïÉڟ~åÏMGÍm®`àõ=>_{Ï¿·«5¸Ï¼þÁ'°§ßl¼'Ï/.Þ¾zûþ`ˆéÂM>ùèc»»dÅdãá½xquõÏ-g쯓àþvsåöSh,ïÑ-&>‚ÛÜ oïorÝË»ÛW›3x~ùãÓ\ÿxþÓÆ Ô.åûó»­.qyÿ㟞Çôâ}ÙAÓ(ˆ·wŸL%9¿¹zuþÉJÃjºÓz †Ù3åçâÑÃl>’C³~ƒaöÄÜûøƒa6/;wxÑ0±p V¾ï—Ò£ ‡Ù|$‡v)Ãa\—c8ÌÇäƚÄa„Ã|–¼{ïÃa.M8Ìæ#9´{èóÀªìK8Œÿ\Âa¶àûοM8Ìæ#94žw ‡yÈnòIÃa¶86ûÎM8Ìæ#94ð¡ü?‡ͳŮÜö|}¢5<Ī[„ÊWᗠøœá—ëÀ'úñÃ/ÚøÕžÃ5{žog/ÙHf8œ+êñÖ-ÚÜxt U‹>NðOÅM·©“säh?ÏÑò‘£=FŽ¶ñ²9ڑ£=ŽöÛ»Fø¼E´Kš‚ÇÈώڑŸ}žüì³Ð-?;ÊgG~ö¹ñ³©Sçùv^øGÆÖ6üñ†ïxl696ås>6þxl>ócó¡ îdØ8ÜPºú×-"'_|ô¡5æ÷—«]^ÿåúü§çÛåq>2Îwwùêö}…$«ÖËÕ͋˗W7W››ßï.__žß³Eý䋏>¾ OÚ¡²yóšJÙl:Æc!›c!›cý—­ÆãOü—Áø¡ý¯;iÿ|Ùþnÿÿe{pòز k}¿ù®||böE†ú¸Úã'1¿>*ôÅï¶ARßóHýmÆò¹Æêtä1ú•¶:4{κ”ö>éúöÕëÛ7MñýóÛ÷œòÃå O1ÆbçwW÷?¼º¼ß|¯cØØ|ö÷„ÚL†C¯~|oぼÇË6HÚëٜ£ýãS0´ÍWä=CžÄg>ŒKtKÅà®ÐG[ñƒÜ¡‡ãâX´¦@tL<º“îä=r'oWñèN>º“îä#.Êѝü0;9º“ĝÌ×;9”ƒûr««þèB>º?°bpt!¯®Åхü¡‡tt!†©ë@]È?]^_ßþ¸é¢\_}ÿÃ}{~zAÕ-7^œùgûë§xqõòåÛ7—OooÚ%y³ùö[ûn‡('åÛ­J®¯|óñ¾¯¬·w/›¿ÝØV?Úkž¸ïw•ž‚Çr endstream endobj 86 0 obj <>stream +]m9œÏ¯÷ht;4£Û67öÑòv´¼}ü±-ocyeáËïï./o¾l‚Ë嗍}^}ûå?¯n¯/»|ñåíÝùÍ÷¯æÑ$÷‰MrŸ3ìï¾HU¾nlÂ>ÿŸ«Woïßn9e~xÿ£ï¬¼ñ˜.¯Û¿leeœ|ñÉì=ß\±¦ÿŒä«Oó((ÏTÆ; -ßnŠGosÚø¼y}yѤ¯»­­Në~‚ ä1g¶.ÅoÿõºÉê Ö°x4Aí”Ì/Ó¹‰)ûÃnv›£Ýæh·9ÚmŽv›ÏÐn£V±Û¨‡Í7G»Í\8ÚmŽv›£ÝæcØm>…@õ‹y¦?c#Ô·ªq êqÖÏX ï»Vÿ(3€÷ËTñ‹ð†c }c›:8ÖÐØ·ìy Í‹ìy ƒ²ßÁŒû}^_Ýÿåüê}ž–ãÝy¼;õ§ëÝy¬?µowç¶\y߯ÍEÊô¡\ÇºS»Íý¾\»[¯ç±æÔ6øD?~¬9u@5§¾úÃóo8qûãç ò³qIªcu½oŽù{§Co ¬ùâ§Íýú?}‚½µù@Þs/Lò¯=?$û~ào_¾|syOGâîòÅV¬ìЎÿŸy¤Ÿ‡°|U£&°/«ò¸ñďªÙ!«f§~øbÓ-¹ùõü)nçmF²¹Äô)&ŸÜÆ#ùñêÅá„úöÇQÜ|D?\¾?Bo2$¼þñ%¨ÏѨñY—šÎG£Æn"Êëk‡¦Õ¨Q£>£Ææ95@ý=´ã4j|®:ô¾¬ÊѨq4jì«Qã3SÍîÏ·´|ŒŠÙË»ó‹ûóë?Ý^mØ,o¸Æø¥^6àÛû«û‹÷Øw¦z'½ý·«ë-R²W¾ùø†¡oÞ¾ús[än1´é'?’ólãšAߝ¿¹üÝÝ忽¼¹Ø\í™}õÑxñËE™}ì‘lgÕÚ&xoGr,v´~õ‹}ùi‹mÁµŽ~vxÇZG¿Ky¼µŽÎ6F„º¿Ý\p¾ÝoÑëåÝí«Í¹>¿üчóXk}Î¥‹~£ÑßÞÞ}÷öºÝ‡dG|œµW¶P)ö\9ú8%W>‘w›ü°£©õÁ»ö‹Ç=¶ù8ö‡ç£pÜIAGnLâGuïq«{Ûl³£ÂwTøŽ +ßQá;*|G…ïñ+|˗Qá;Æ¥ªÊ·q͊ÃSù6ÚQ㛠í¨ñ5¾£ÆwÔø¶êÀák|§þ±è|یdϵ¾áÑi}[Œè¨õ=0ÊO®õýçíí‹ïïÎ7¿ï£Ê·±t}¸5" ÆV ð{žÿq¬x±wêϱŒçÏ äXñbG u û:ÖïØ[6¶üü¾ï³­³xk}lgÃu“¿OyhÿöÝõùÅ?¾<Òíëó‹«ûŸþm Óï›ûŸ®7÷Bè۟ì0ýŽ†y@géqZD·ãq¯.«9´ï¨?o¸”ãÓÇÄÐ?ÁáÑüa‹Œõk…?݀ŸLfþÙÇ·_n¬ çÓÛÆlß\Wš·¿C”SòíÅùBÄÊ7?ucÉèíÝËó‹ËíƶúÑQáÝa,ÛÂ×îùŵåp>ƒª->n|ÏÿçêÕÛ-\[öþG_æ¼q™«Ëëö/[ù&_|ôqñ­ûËUOúD2Ö7W|Ã>S'㧈h}`ÆðLŚ£´w Òpc·÷Ö?< +EŸ¦ò Vâ·ÿz}{s¹` û‡GÑo»ÅöÌGyé(/흼t—>|¾UÞp€òÒãô,`Öû~ÿ|œ0éý_§£Éü#Ôü»»ºÿáÕåu݉9l|»ÿã=õb&áW÷x ïq½O’öz ›3´| +~¶±bþ÷¼9ˆÿd·Í#‹µÝÖz¿÷×çõÕý_ίÞg8ޝǻóã3¸ãݹo+²çwçæ+²çwç¶\y߯ÍEÊôñê|WçáØ¡(û( ýâœðÖâ—ëÀm„c)"½J®Ñã…È{ôÕgy ö[ýÛÖ5¬Mn;È"K¯Î[S——8ÆîOœþ÷¡¿Œ²éù¯Íù"^?€óµïã÷íÓ7ï ;\†Á™TÄ<Žñ*yTïçÜv %>N7c÷½ÆÇé£)òñQ QyLþl²\®<Æã âÛZt{¼'hÿý)äo ‘ýí@>Äp¿9ñ!ŠÚK¶Ý¾³‰é˜6În<´³t Âö£»“h³ýýååÝï®îöÁD²/ë|þÝæk|Íp²±#‡ÇþÛY,W¾ùt¥¸ÞÞ\üõ€¸É£Ûegåĝ|ûì÷Ç}ö ÷™ÿ\ØÙן*Ą•ÊÿÛÝù͛— HìÏ~œö%¢Ú¾‹Ÿ óLÁ"CÛ¹úhѕáȹ¯®¯÷`MöeJ–mÖc¬æ6øD?¾üÓ_ýÁ»ç¿½ya0PDˆòüO·7iMpÕ£S!}ùýÕÍôÁ“?½Ö6øÑ·?½úîöš}a—'__ݽøõwòUûçï?>y;ù¯;ù¦ýóç'!'î̕44ïÌ»¡Ö ±6gy¬.ÒÓÇàóÉßϟôœ¿ÿÔþåÿmüßFúñ$üñä¿þ;yA¿ö×'§Õ§pò8œÔÊYÊ­¡WLŽí_jmäa8‹ÕדFŒõ,Ä!5bgÉÏDߺç +óY ¿.¨PÎâ0P»¹ž•6z××3?¦Øˆ¥µŸJdb<ráVdzÜþUð錿.gC-#¿˜Ïr*JôÖbMƒþúèÇQ?.gcD§ÆÑý>Ú»~¨ †ø×ÓY +nÒ@.4þÏb)üêxǪäÍàÛ< ō¡êØýY­µÙ»¶&Dtgmñ=-UUbû)CÀØdzâyö9Œ^½¦Ê¿Õ6D‚Ã(¤èƬ?߶B‰4OC›ï(kڄ·e%bi[&&&Ò<„(ÄR‹·þ—6GDn/”¡ê»µdn•šÊ¼v¡¶á¼MB›çzòôá=õìÉ˶vªócv•74ídÙƵí­HÛ¸íõ6¹îl¤×<ígjs8kßzú%š¾û´žåwTë€Ë²)wÆ»t  Y…”Î\ÛtB†¬SÕ&(;™ªÌýo´6—)Å$MÖÁñêµCû1RÛuÐ]ÞGë+5ÛúWd¡R>+‘¿£Ì£LI{‡º¢Û.æïcn¿Å«ÒþŠ4*™Ôâ" 5g9ÈD‡öØ{ù>D§ßû¡-Š#r¢E/zžÊ8Œ2û9Ë>ucÛ c–A…Ò¦‡¿wí ¥Àät֎:ÿ¾K2C<)Ķ“Ã8ÊVáù—âYͲƒÚV,r¢]•œ¾6m¥ý6[¿Ÿ•Ö@k¾÷@·:½;fy·mÏ?Öö?υ !备¢£ñí„8§G¨Då)¾1ƒ2 U9@¡ý%¿D¿YªM!¶@›‚1 «iÇ?ðoÑf/¡èYo[R7F½Ž [h;3ÐX„UÐ"4•#÷ªí‘:2OÄ~úäwÑñœþq'¥ÿ=+ٕÖ\ã C¦cÖþíÏì>µ3C‡¨MV{ñäï_µ¯¤ñ<ŽA"1çWú õÏËyˆmÈ&lÖÚdD‹’Æóå1Ó s´¶YÖ®Ò%Ä[ªMwÛ*ÊÆ0='àíef§ÒD;v™§¹š 7Ñ6h¹ Ú¾N8]=5éùÚqB±mVèíHû#ñªÒìçäa«bF1HÑUk¢qû!òƒÔsóÒøþ0xYªkÔÍVÓ ÐøҀÚÖ¬4]r1ê‰uC[ø\q8’˜2ʌÞ:@g+0s –=”¤Ûݍ¾Ê!b6,ç¥Ö¤#·Zµ]Hr['KÅér•ç¦]9EÏ¡§­3€8[Œv4»™ÌÎÇeçòóQÙù ì|LþdÊ+[Þ-"zµçŠu êÙ Ù J¥{÷™’‡4$c'¯¶A¡<'Wb™üÈ1ª\Ùvy°Vâè´ßDP›È§ðè½jË0j1ÈÁ[ÿ±§Ö‹¼Ž¥É¤ÑzáõP{‘TMAqAönJM]uæÝà!·w«ô¢5PTl?=¦‚D¹{ ]k›"«„ÖNUә¤kÜD  di^[ç¹ 4mÓé.äW^¤/mÂHffÚ+EÜÎt…®ƒîÙƪ ÕÄP¼#À§ª‚4q¬™¥ié^¤•u‡ëÁ M*J"B¶ÇzE £NrceÒh;ØÑé ±©ϔÜzãõݳ60ºª ¢Œ»q=—«nÍ8´¿žªüÖÎn]{U˜µ©Tk²bóÏs ª4¿og¶ OÛtm>USnK€SõûFt…E¯kĶ´*Êô¦Ï º!jQ´f&!ñ†l|ÝÕ¨[7¸ìU(ME{/,T Y5hméðnkU·®/~„T[Fm m}Áv e/ì°imÂáIáñNõµÐT[=&ÕA‰cÖ) Ó£‹Eš³Ü1˜„eâ#ú}*úb!-ß_tiÀu˜&kÐ{«]Úfƒn¬FnWš~ÏjÖ3UcsÁ¯56Yu\ãè”ظ;¤’Ð@MŽz§·ìÕ¦úB[<> ´è1¬ö%ëOµ[O8MÓmõòs6Wí6ÈƨúÎj +Sá£-‹^ý´®;Ë¥‚uMSÖFé–ÄÆpځÖíx(jtXl +‰º[š@¢ɤ2èÄNövSº‚sSˆøpµVC.¸Šö 4†?€á^m. J3]„‚¬Æ¡A 6OßÅ…̶&C„z¹®1§¬6"U‘¬fg®ñÂQÏg:ó£KÆ7‹>HV@ú¥®Í@GbPÊç¢âbjʨ6Û6LQDˆåª÷Ä,Ä>F‡&d•V¢‡I.äš Æ&g'¶ ÔrD¼fLJǬæ¤0:ᎄ'Ù²#Qä§Ú¦*~®m6ÁLŵPb²Ï/*ïòĉ¼Ö…Á(B†‹^Mc‹wm9‘F1&Š½{4 ʵåÈòb±"™1’ŠtÅ?S²+A»Ð©VQígΉÖ^m¼@‡ÐNz1{øühÃ¥Ý0 +»æZ‡]4ô×È,(Ĥ‰jjC“ƒÑ¯vp¥µj«ÃoÄvJ”XGDéMÆöfçpl×Sñš%™ò¤³d­XǦЌ*V\ DΣ’M‚ìïvڌÉi`)Eöç˜r†³šUICH¬!µ'éÈȄ™!4ž¢œ}²«¦QX¥êÁ‹Â Yi]Ïs£¦! 5ú¨òJcmPÔl$ÉEä•v1ŽÏ(±,pÊ&7ùA߬Ñ8]¦‹ÆKO)©ä:(ë ÅiÀ› ÅË?_Ðx²Ù™YNb ñŒC±ŒßOh—N £]Ϲˆ·GÂ¡m™A×À{3¿;uù2ĸڽ…I¹k±ˆº;ɑu²Ù~`RnäÆ]lÇ•&«¯„Ügm‚½RºcF¯ú+ŽXð£’éJG³¥$¥šø\I©ÚÙþnL éb87l°brÓ¯ªž]¯ºŠ¹+ rò!0]$H'ýìå +bµ%«‹ +Š¾YM«G¯+•}iEõ,ߕóøÑî5—!EŸ܁A÷øqÔÌUB¢Ù0žÆ„ÇF;:/¤Ð#,r`Ší(9IiŠ¥e»Cù‚{ª¹v(q7«¶IÄÒÔ="– R€ËÆë«1?ºò•©vBûªŠ¹¢Ç +,ÛZ„×;ñ2KÕë’|‚ºŠ$þf¥5 jÀQ®Óïe’)<ŽíXb~k€@ cP›¤+Q9 Ka"‰ý(¨ºDÂ]äv“ÞÍD¤Åƒ$Çbëæ(Ķ#´YÚ'p+ОƒU¡•I^ilÀÊ8±~ ,םٓ ñyÙ~ä5lÄ&Sae91ç$»MѾFˆ`exPò8oä¦y译å\¨dag¿,wEӜÕÐAf€¬ÎZ3gk>Åî€ä±ön‹u~-ˆ¡½Y<ˆ¤_¢Æ¡T‚jzoJvö|±“A-klŒÑíÅ6viÀ‹š¢dÊIK¯²”mßgÕ½½‰mK&ÐÒYÆ ¼È»MGOr1µTT–ò$^TÕKHq—ïbd'Ãsm¥mû‘÷-1¯ +hÐ6ÇÉFäÈ rŠº¿Øca†®Ã}¼d½Æq…4=n +l&â‘zçp[€!4U°1/UÝX :³þ)—Mð:1ìV ¸ˆÉÓ zk›ÆàáCEx%½uôê‚áX éAŽNUòlæ–Fnû6 ¹òLÉ¥V՞[ ðñ—aŒ šãúc$RuêÅaÁã™Z;Úu¦ò/ª¾;ðfÊ®·[ÅÒÄ&¡æ²iÉ´ÅŸ)U/22¸ÔÞ-Xa‚8τØD7Dµ•íV˜1ªfTÓÖý®ïªNÞޔP"êÁiZvq<‹¹é&êôj{IÅ<Ai] +Z!û±{ªèðÝðLÉ¥D\6Èvf=\LNÕü{NUƒÆìì†&«•+i"R=Sr +BC°™Ä ñ¬?=Ó3Õ¸ ÊO®VDv¹ê5 ‡CÌNrYÀ%²fˆ²°!&§lî6] +Y•`z8Õ¾þÿ¥ +ãÊXY³yÀfŠÂ³‡ß&Ì¿?›úçÿúÕW/n¿»<ùêîþÏ79¿ÿáäë»·o~8ùÛííõ¯ÙŸÝðïyò…K.ºà|cÝ®ºø;·ú/O_oœ&ÿ¶1‰1? .|ܐž|‘›Ÿëܓ/žÿ¦ýÔJ,íÏ{X$wæ9wáòÅsêF~ñüËöϤóìcñ$›#~IТ^ß±ª„DŠWJU['™iT.‹‰”[&:3q±™¿o‘WõBFêî ƒÅ3ùˆXFr¥©Mg43[ "m^èylW%­s ãꃽ& JT«¦· 5r ‘òPF“™ì«è tE:oÚ¯VîF b‘DÅäɝ3+-1šcÝ[@^3¸|oÎñFEh+Ÿ‚²,ví_ظ–‡ºôŽ½£;³øíÏtkÔ'ð_Û{µNNpæ¹d˜•ÈÙðìáFÔ¯M].I-S|—£õÐ:£dâÖL ÍäIë5šÑJvçjËAü6ë?÷´÷£fm"{Ä1°o¥j?²j¹»ÌUhPb„Õn°"ûaœ4«Dçt»Ð¬g«@Ï)»°ŽØ,yêpÖ¬µ—ŸY#=أ߀>ƒî Ó ßÓ0訫ìÌwDFb²¸‰nk#rE4D`²Æ‚Hê¨fÍ ‘U„tŽÅ~a"Ìä¼q…<@Ž$‰JìüsŨÅ!!“îg/ÛfQµˆ¥G‡íé*hÁ–Þûn©O#oú[A HÁ¢³³7¾v@֙ÃÀä{Š¡ÂFý&°ƒÝ¾C¿Ô-@b±Ch ”@ÚSiÀžãdÿ7g LŽ„L°L)Ä4¸‚&FØ `Lf‹ZMÖ%õÙƀ½ a]"×b×›Þö:[c°fC_rê§ó`#Ï 8]«0¢iÔ +íF¨Dï³;°¬Ñélëàtqèx_œåCFÄ[–òìÄ\ÜûŠMãKÕÕÑ0oÚHlʖ7ë$¹Æ¡0Ò ¶iT¾¦”“S¡q2@àJûc°9ç zpC]oŠSGtLýD¬pîdM³S>@á1’<í–/Qÿ‰!µ f²Ù5½R0¥Y +ª,êàH+"Rxûh.ñê6b I™ ;k¤ɌnG +fx¦äáH‚;­ÇÑ®¦zäaâr2‹8QÅÀ¯ÂÒßÈM“VÇDÒH¾lBÒ!ªŽW-˜Ú0Z»Èìˆ@(DàFÉÊ“Ä5Š¾b."×Q‹Åc w°î MÓ¨wW4Qš&¼À+̝Å:4F¥?ǎ!jä(í“ruU‰¦€;s?’;¯b/½Q“ð1½[D9'H‚9‚/9§>–Àõ,¸ ­Fõ£g3K‘Gr(ýÜ݋d²Ø·ÈÄQ…aâ'5i"ócIáqãîV›$AE±h&kãvÂ^œÔùzŽþîòí`—¢°†Ái«Ý~Ääßž©°ÈVEiuKtÙÔvTÒd~1CªûeáÜ ža—§Í–ˆ·Õ#Ɉ\фºaqˆ:,6¼Àß0¦W&ñ*O¦—‘ ˜å”DÌY­ >ŠŒBDgCÎUk Ä2æ $„ú°uK‰Õ¼ÝA)Ãh÷J’[T‰.a¶‘¦4 +{Ö®“xÌ,»õ0³UAòj… 9Bè÷1bnª†x ’ª¦Ä RŸð6ù~BÖÉ 0DŽb"x` N´+1Ït…\À•çü¨6ÎvŒ¶í<ˆ>m;,;?o—ÈcÒvX½;blÎ.Ýþf(è/I.U ¸v1'¹!bÎìœq~šžk7Ej9ÑÌÚµƒâ5‹xBµ#U2ZÍÞ¶cN]RÊýõñ¹$‘xœž8dÈ_ªzC׃ì‚HÞ¦+w¾R‚ €cÑ2ép›ži¬"„9^ÐDšê¦|r¬¯X̾Q‰8®Çjâ-܈ƒDv(q40Ø ÖªaIF$š™äÜ`[£žkbIq´¸i2±m?Š?ƒH a¨‡Ïœ‹%y}7t •Ö]ãØ [ʄì3„ßQ–ú/ÇhºML:3ޜqDÎ=X‘TDÖð‰~•àÝfsÐhÄX´?/M’$ ?7ôs2û©•a€h’Že±ŽMöy#W¯“îHA»_ƒ\3TŽ\¡¢yg?kG”azHE⺠cgZm½¡”kd +©'ÑTÒQÍŠåw¨.RL'7˜¡vcè®/önꬷZJŸµª³ZŸÇ)‹U½œu,#çlv9[‹5sìxk6­W Ã*V|7t­Ù¿^šžàUŠd¹xeÒ݊,øìá·?7w؇õ2ÔÍÊEœ^†$±o•“PÈrÝýðE¶ðìdx¨GïèÏýÙÙÇ@m¯)%œ"ñÊÈéFCW ciŽg·Ñ·{©Hzbe×djКIEÉ£I¬â0Á–!ޝ +Uã×í©u£º€Ü'ªUnh&%ÓcC»ƒi×5 gݺ9Qn-ϊ:!þFî˜Å(Î:ðԘJÓ%ê¤áWFÆBsÛ³‡ßî¼ —yÛÎ\(DF_bgˆþ k˜r†Å= ȂBl()uÐ^³l +Á=Ú4s8°uÎy¼ ÁÛ[’…ïÙ‘œ5„±k|u@†Y"¾…V^ßîš³\*/…©wµ¢scŠÙt>¤ùÑÔÆ:êäLL‚N|gLž˜›æ±7D樊쿉; Ä‹4L,T,Ns·ÌåbIb@«l»’ÌcŸn” ¡D³²¹Aˆ¥ Ö*üÏÃÊ*\þu* Š¹Ñ-°†¿>¶š0`xÁɶ¢jڌ'D¨Tœr/þŒ*ú²Ù?KB–‹¡Û`‹J8ÿÉö­¦³¿ÏY»9™•£‚‹ƒ'‘1¡tQDŽÚu}ãÂpMÉaÎ6n1í:ÌBûw¸§-i!s9„˜—ŒÝæhBå®þ‡Ýh¾ø0©!QÂԕ®… ¨ÙÔyIÍZõ£Å aê‹Ǧ…ÛfåQ:éÑZ¨‹ô¦C=™jEVœù%c‹#ö’ý‰˜pvV‚vâhÁ~èó•6³ Nvë,³Íš€-M»#oº±_Ôe´¨^.âÙ›4kh=GULb[¸xâ`|éÁK£E%t¯µ Xi“„{º© +¨;â»åÜ»¸öy¯02)ãà SƒwÅÑcµÅLÐçÈ$š˜`V)ÍGa6ª!¶nö;³[µÌ '±A¨†É—.xxèr?‘Q+X™’3² èÁˆlò;kŒ…U)ðÙÃo~î€åvn*89À¯OUU^)y@=ùwf¿Uò ø'¿–ÅU¥úšæ2g»¢äÙ ±zT±(dvºÐX¦ªD)ü†sÓõsŠ‹ùéÉ©fÙýÍ"‰«Æ¸'9½è´®dE¨À€*£I´˜‡ÑöÎîΕ&›·‰,ŽæÞ;Ë(u»Ã<£‰MfZÞÝt®­åå³ýÅó709帛çó{³³'¬ýRF5Ž¤Áœ¢Ð{’ÚÜÏ@.èW²ÍõFà ++“€Z6jX모6òˆtÙ–¡“­$PµEvÑÚúë¿ö´wCM:I*>Z7ª… Y~üúÛ •„A¢„Fz˜Äòȳ‡^í-Ĉ`›a{1¢¤ø`ŠQB°˜ÆŠ5_ÉLËÈ@Ąp¨ÁR؆^š'‰ ÍN⺐sMT™¿œŒ\ÂämÕ±g=îA®0¶Òq² YnDÄTqáEt¹ÉÎh×l•”ú«á1ÓÀ."[4—06²ÖTJf3æ$÷d›C4<^j„ ¦ +›>‘#Î/Ϭµ«V­gld«Í»²mµTÃÊÆ(Z£/ÇI—Cµý2ÙF¬ ÙâŠVÉ9MÞvˆ„Q˜fT+}%ɕÇb[¹Õ:©Uƒ<¬$Jôˆ¦N8jÙJô¥‰r}Ûë6´˜v 1ò€ÓÇÂlÓœ§8ŽèGuv$Ķ­PÈ:!±Ù„:FQ-vDtO4ˆ‡aÂy™³¢q‚­ý`æÐ^õŸ*®%ƒ(ÍáúÁRrˆ\íÝÁfaÔ%TrCdnŸ-9+LF³¼Ý`°ê2yЭ1L6l +Ä Ä ‡™Âç0¹ÈˉRu¨³„å!RŽV݃–¥¨¶Ð¬0‘3îÛ:ûjç%±ª5Z¥ˆ 'Ÿ¤ÎÓP㈬;àûΪr!ù…«Y’ iþ8Úa@Á¶qp³¦`uà*íÌ7gÄ÷à¨AS묃 +V6)Y5ø!‰²ŽÏcÀæˆ=–„z…]áb.dž´ˆ·jL¬×˜"²Ý ªRHËø`¬Õqzì´µÐ&)_dí–Ø/ÙÑڝ\W+ä á`0{=õ"c&8Â-#!eÈ]pË8ú̪lɜ]ëÓkQŒiRݙ{Va^^žwÄê=Մ³ö1’2ö6RFµÖÁ"!‰< *}Èã„lUÖ`ì%bB.’ / v•ÆÔ'E–gãÀ>™´Õ.M\ÛDÅT0;¬f÷} +«'€ó!MÓbII*1¢ÿXL&¢Y„n%©kÅQÇ~Õ¡°`/I·Òƒ€¸ ªwh,³—ˆ,m­ä„Y2.w÷0 ­\`e¡w=’¬XB}Ög\5ö Ù!ptÔ°"Fð&x_x!ò´®noõøË0ÙdÞÒèríW~èÙujCâ# Ý¥x;M&ʓì\xÄ Û,–x%ÕÕ]dN§Çé´G‰±3YDµz;b?8Ëä  Qd1ç^WCjäUDܳÅGKbcE Gˆ`!¬Uõ1M榓GŒÂRŽE–±ÎqBÎ6mÁu‘Š &":9#‚Š‹âbä˜(“| +*næ^ãŽà8°ÈÙbñùm‡²¡oE·«G'ÒévÎÈ«„ŸïñqªÌ¢Œw‡Ô§ÈFㄊpíÉvÈr !ó#²¾kNb"f«ŠÚëÐN +_j W"FÔ¨V—Ȇ›Ô˪’¬3"æœk9¹ŒÊëœ×;q^,ïjõ%&‚%qq+ÂÜE®öfAR£ô)1,ZÞiÂtöÙE;äútÃ<÷ç…Ù LŽCÈ ¬Ké’d[Zð{«nÇÈ ÈëáL^´[ªÝ³(}H‚¯éS§ºâòfÈ}-ª·Ä•a²ÆÕ®ê¨J"Ž‡'ý‡h‚¾±™A ´¿ð·OöيNGdô&òlWõPk‘ËûàêĹèÖïËä\˜é$•~.‚Û¨ÎîóaÂ~BxàžÎV%{EVXÓô» `¦9¿2r­ò;õl˜4&×>m3˜4Þ%¹¬¾ý¹ÑÞٚ˜§ÿn{sò¹"®=€©)vBÕä&vÃÕè®ÅȚòùNؚÖÄ2tM™ƒð5¥Ë6¥ ;albËQ6߱Ϟµ/ŧ±k`‚kh›ò`¼Mñ?삸 ÇrÌMžÛuS¶Ï.¸›ÀÜySšØ {½Ø}X‚Ëñ71™; pÊYÚ ƒó‹ç¿[aýGν¬Ž8œGέq8é}õZþÿ÷ï?Úњ8‡é_ró=¦ãaúӟޥˆlÜ)çd»ô5ôN»¶ãJÐʧ!).FûDËñ>…Eì„ø)Mì„ù)Mì„ú)GaÜOiaäO´°ûF™5ôO¨×;ࢉŠÒÀ. ²Î;¡€b«ì€*Mì„*o,Пᠧ»âÂ ´† +>»TZØ TÄ«pA!¡-FE˱A¥…ÐAa3YÃŃ9B¨ÐwÂEÓk(¡›—ã„J ;!…bRwÀ +ÅÊ®¡…ÊÎÝ /"ùrÄP#k˜¡`(; †Â’¸n(.°¥È¡¢ƒî„Š’B; ‡J/v•&@Ń0Da.XC…={9Ž¨´ð’(ì€%ڛXŒ&Š&vÀ…N¶Q ,ÆíjäbTQ4±†+ŠÎí€,j:órlQ4±†.ŠõÛ_MÌF¾cçj1ʨœípFÁ—#‚y­aÊƒÐFá­ZŽ7 +#㈣pºí€9*wÄ.¨£½…Ÿ£0Ù®!b€Ë±G¥…]ÐG±N;àb¿-G ÅyÚƒœr …vÀ!…°³)ÔõåX¤ha1)´úðH¡×¯!’âÁ&©=XŽJ +iu9.©ˆÌ “vå|†MŠstR¡ï„O +­}„R4–c”J;¡”Âv°§TZØ©F†5¬R¸Uv@+5s9^iw1ÍKåÁN˜¥èÞj)ì€[*M<€\ +‹L]Ž] +µ{Ž^ +úø¥f/ZŠ` +Í SۑsS<ØÇTšxÉæX¦ ¯¡™âäí€gÚÝA`šÚƒ9ª©=XŽkÚ]e`›vd†núŽ/à‡Z Øüß6 H}¾cHêó”:ˆ“~ñ¼‡“žCŽ¡ õ3 ]ðíìÜÜޜ4íÄbv‰¤^}9$0¬ÂËAqÅí l×Ðr``4±XZØ{ox`tb€`HÑ;@?¼Ýp³Pð ¼ûP]|g8Ónð”ðRyNøMM‚i¶sXakn,Ü,†^éÑ^Ø,F ;@ ÷®Ã }4üðÏV[ƒ¶sÀa<ØrM¬ãÁ°Ãð°­ãÁzØ>˜ƒ¯ØKá‡ÑÀ€ô ˆ±•æ Ä ïCl»tDl–B£9±Ñ—ã‰5@b{°’MìJܗk1,16Ír`b´°4ñ»9‰žÛ¥ðÄÆfŝ -†(–&v)–&€)ƃå@Ÿä× Šñ`°b4±®Ø>,ƃ ‹±.;€cwì[Ü/ÍÅÀÅÆΗC—Z ^lÒɾØÄ¢¥Æh` ‚ërckzclM/2¶&C£…ÀŒ­‰ÅpƦ,4¶NÌ!íÁÔØ,‡5¶&–÷M0ƒ6^°5¸±í¼9¼±=XplâÌâ¸?X rÜE¥Å0Ç&"΁ŽMÎYulM,;6QiwlÐðØøïrÈc“Ôƒ›²0‡=îZÄbàc4±úØn¹9øqè–›䶒À²=˜ƒ ۃ9 ²=X„Œ&Ö íÁb0d´°‡læ€Èö`9$2šXŠlÂÞÙ́‘ûƒ42,G6‘{ úÉ&‹Ï ’A_’Œv€IFk@É&å/‡J61–læpɶÀK“ÑÀd²=XšŒ&Ö`“M\œl§il–ƒ'›F4‡O¶‹”;ç™A(S[ ¢ŒÖ`”'LzŠn5y0‡R~‡1rj©|PÙ¬B*ÿŒ]ïåDw™+wÙr­üŽ/Ž¾ø|ñқÑ=œyV;j¯ñ? oèõðƒº†B€îV1 >G~GK«'t º?˜¡Aۃ9tס—"BO;´† +ÝõëŸÐs;ÁöÈÐS¹†ÝÌð¡ßñÅ*Ã]C‰îf8Ѷ]u·FŠFkXÑÖÑåhѦXÎñ¢íA˜!Fۃ9©¹ËQ£M ŸãF›)p9r´qÔ9v´Ù£GÛFãGOŒe¨ÛAÚnØ9†´=XŒ"Ý[˜áH›¹g1’´Íéb,i[®š´Ùz–ãI£‰¥†Eèƒå¨Òfv™áJw›ÉRdiH’;`K›\;G—6‘y1¾´Iãs„i<ØcÚT¶9Êô&¹Ñ»!M›Ò¶kÚô§åhÓ¶b‹ñ¦mÛ,Fœ6ƒÚrÌi3÷ÍQ§M£YŽ;Ýu¥Uäi;q˱§{Ó+èÓÖòrüikb1µ &Ë1¨»l³…º[™ãP[/æHÔö`ŽE݅µÅhÔ}s,Æ£¶Í1G¤î»f1&µ—9*µ=XŽKã¼†LmcS§XŽNmMÌð©Aß¡M„åÕ֋9J5¬áT÷‹‘ªÍ„´«M¬¡Uۃ¥xÕÝT¶±Ú9fµÉ‹Q«Ñ¸Õf\#WãÁvµ=˜£WۃåøՐHÖ¬íÁb k3/ÏQ¬»Ý¹ãXmŽd‹±¬Í4C³6úÏÚÌ­!®aZã‹P­MêœãZ÷3dk{°ÛM¬¡[ãÁb|kÛ=‹®moÏ1®ñ`”ëÎ_f8×ýÁ*Òµq´åX×Æpçh×ö`9ÞµÝsÄk“Ó—b^ÛÝ4G½¶Ëq¯ûí;C¾¶;u9öµ‰sôkÈ:;à_wqi†€mæØ]SYEÁ~‡åpjV| »?˜¡aÿŒnâšcbw‘s†ŠýŽ/Žžœ<9Ð÷ð°#g7/Ä;úç°£Xݟ«ûCæ‡gþçfþæɇôm>€émæ¨Þö`ŽëýŽ¦¦ÎÍнíÁßû¡”aú`1Æ÷J‡æ8ß½§3¤ïw|1ßÞw'¯"~?øújKk¸ßýÁ ùÛ,ÆþF kèßx0Çÿ6úÜÌ1À{K3t²þÅbp4±†Ž%[÷s4p{°ÜöÉÜڞc‚Ûƒ9*x°Š nô92¸=˜cƒGœ£ƒ?𠧕/–#„§[Žþ΃¢vŽnæHávHc…ƒË&æxáF_ŽŽ&Ö0ÃíÁrÔpÌÝnx0CǃåØá%-E·Ý·?¼Ž¥â8Ë1ÄÑÂbq§Â G¼÷m!’xÔfXâÖòr4qk{Ž'næˆâö`Ž)n½YŽ*nMÌqÅíÁY¼÷f[¼¯Æ ]¼x†/n`ŽÓiæãö`)ʸ50Ç7 |)ÒxßÍ«Xã},‹ÑÆ»v0÷8Xã8½DwÀï£YŒ:n›ãŽOÖ`yÜ,Ç·½6Gïføã¶Ï—#[Ë1ÈM¼™£÷KqÈM†\ŽDÞÅй‰¸s4òþ`†G>‘œ,[{\y0Ç$·ËQÉM֚ã’Ûƒ92yÿb†Mn·÷rtò.BÌðÉMè˜!”wú £ÐJy ïOvC*·&æXå&éÍÑÊíÁr¼r“ôfˆåF_ŒYޅËj¹=˜ã–Ûp–#—£‰5ìr{°½Üdù9~¹=XŽ`nk?Ç0ŸïÙ6úŽ¹mé…Hæý Í°Ìñ`Žfnô9ž¹=˜#š÷3LówØ1VkÈæýÁ Ûügìݘ³†pþ~ÙiŽr~t‰¬'·M±ï3ÅvWOùùéܖÜ®Š,ÿàz¯`ÙñÕ¼{þۛßþôê»Ûký÷¯/¿¿ºQʯ¾¾~{yò»ëÛ/ï~ý„ŒõlªÛþK†ä)¸wPCòÈZ"Y‘‹"zS‰½@ïÁøþûùò»,ü˜º0qÀA@Õ@ʊ“€]§“(ˆEމÑ呃‡}Ê{)qãÁ×j[r˜ ÿ wcQÜÇ&hJjÿƒíþï'ß=<ë¿:%T¾±Ñ_÷÷õ×_]\¼}õ×ÛûszwrÚþÝV¨MóY¦ Lºãˊ&(òNº%¿ò¶Éõ'?¶N»’µTôI*'¾b²—д ?PÀ`Ú ÑîÚó‘*Ž¼µ›L UctlÎ}JßW*3L<7F/@D„iŒˆE¬O®oDŠüã2yW"ScÒÔH"Žh•ŠÀrf[Q™FšÃ­… +WNT§Rªkׇ'Ógdœ;Ô8IdÐ$þq®oJaü5à1ý ›# ¾Z/$e0qÐìþù´ôd¤êäƒà;DÍGmDo•„¢F(R$ÏDR—3Æéƒêù4¨‚½¦G›L2}TKU-"4==R¹H-(ÀÂtÁ¤P\$w€"l’,ëؤ0*#Rõ’~ °l„ƒÄ ð‘Š~ +Ĝ0HÙjʟt;ew8W¯n P´ÆT¾à ™ë܃­Š~,)DSÂ3&]‘ú˜E­y5º*ÞîAªªRǸ¼Â)ŸX©ÿ©ºm ^¥úöĞ#cÔ']„F)°‘‰qˆm°fd¥Œ]h/UðÝj¨U*.qZo½cͪRh—ìÂ6®<°ÄZÙ`K ¸É ”»îte-.Z…ÀášÊ§P+|& nÀgYN^’ÒåȪŒ~Lâ])/ÕÆåÚSVÁâ +ܱvÐøð w(ƒLLøÈœä铗s:wò›?ÜÜ·»¨Ý$'·¯^ß¾½yqòæ‡óח'¯n_\N¸ÜÛ'¿úËíõ?ÎO¾¹½?iòÆýå]c‚ÄÖ½1xúïy“K×b ÿçäõ½•GvŒ£â +« I¦—6Ž"³.l\æœ6nÔ£KùI¤;·:Yž [¨mÑ U։ËùÉQ¡ô#ÙÆKý ¤± }Ì06ï)WU¹²Œbº‘:[ûqÊUŠØqÊ6żÅ&±JYn€„á¼½«)qlLk⤨e*9Yo²)´£xñäwï¸Ä¨0Ni|x£;쿟lïc>å¢ÝrpØ'qw^NFÐ€Ï i’ŒÛ…âJlªV¦'D.*è¼ÎÈH¦7XÖs…©º°›¬I ò +)J:£… z¸_5 +G64V¸F’[% ½]ÓH€t)ëJøbdH!ùQˆ^j‰1 ¨Ü8ÀA¦+%·!­TNõ¢ íÅ^~ª@»¬dÑN¤ô0\<ŠK0½ºbO¶q‘ÄO¹Tñ0²u¨©6Á=Šc%^®I‰¤q1w’ ãbt(½¹3eiÒQsc~h7®ìS ;º¢YÛ£”Æe±a¬’VÂ£Ò n"2ˆ +Æ¡>«WÆvI%±X‹üü (\ì ¿Sq%µ èÞ¤‘Ø)èFMV‹o‹§›+®½Ò›WÌi¼²º « 7fé,¾¾8¹ÖÚ*äÉ͛‚ŽïKÛÎ̌4 6)´OüŠ×ëé“o?kz°mÜ,óŽ@ &8«ˆ+¥8Þ7<ºTµˆŒŒ•&…ëI{o –cå02¿oÓPQ¨ðC ®dÀێ£Øqdé² ‰O*’±Æ ¨0|)èM1R¥œ"àN#xè !”$)qþTrW ©Aª²± Ä'働ŽN7›šøfæ#Ïj ý$¿HÚWø:݃H¤N*oÑ®|ÚH¾QÏʇšw¶älTI |¥dI&£ƒ€èbל³Ý$pݘ¤d9šùN%C Bãª܌kúój’j%"±Cö;_|¸#3ˆÎ¢;2äÈTˆâ.šTAɤÅ3-){Vn@*·v¡’´fmŽ£ +–Ax«q…]=ˆ‚×J[9À±¥ +û¦Hñ•Ãc£Z‚“J ÅY­"5ÄUEÀ‹\…¹‰Ž‘á®]ÕÞ­IPRø¾µähÒFX@¯YduݑŽ)ÎrsI‹Rõ—T)4V¼ Lñ…¬°i&Ár_E«¦Ïçò0«næUuáÃR+PÑUÀjÚDQL`BiÓO9 |àõ £J ¨B°¶´I‘BCªz‘oƒ”š#5°÷Î:}L¶_\€5°Í Vd>eL– ùÝ,•Ý8€xKJ¥“£Â1uŠ¹ò#XÁ¡RuŠMz<U.+:ŽZªµÝœ¸£ Ĭ*EâäÆ×Ädàwë[ðâɛ´½Ie))t ››0ْYgÔ᪖9 ãBÑÐ"Gö'±X¨Ž.jŽ“:rL.£ZqTˆ¤AG‘œTËd>Ì[þ,w3íñƒŸÅ5¾Ö‘§EæaËdQ!"snÛV/IÄéA¼Äl]É£ð¸˜a²!üÈãY9'™;|†!)K<ÛF¡¿Óå%o YᗘÀnÜÉä«reRày6áD¶W¸]$[@OÕxC…1ä7Aé¢BˆQ€!&reÐBÀÙä®ü*kÙÌj AT8g¨pÛ$J‘ÈìÊ®Q +B1`{Ç`™ä nIv/ɳfË£ªbU´~B?O¢ÉÇB•"©²!4wNL£6 Eâ¯[k­D30¤QâeÀ®Sò'ýŠ†¨<ìì ¥^&k Å,å‚µÃ¥Ê u”V‰…ia‘¤ÕPÛÍ¢õa›T¥!»è Äh¿"j_Œ0qp9â4šŽŠÂ:ýҍ–¦•¹»~z"Mˆ’ñ ‚ÊÚz:eõ’FýO´k³`rq8š~jhÊd´‰‰ +y´9h‡YW¡tUˆ¤9¹]«3£3™bTI ©cž¤W5> b'"'6¢ \ÀU!î³\-öÈ÷¹¦hC¹Z‚³2»£ °¢8ÂOD<˜áŒx«ÌjpP†¾Ü~@°~ÖbûÿTc:‹!}¹UK°-ÏW_…ÄݬûÅ9½Ši`IϧLIö‹ê)„$©•öûB{0ŠPJ¹jcº©F6€aóȚjÉ0X<²6$´+zÜ +öç`å7èªvz¾œG\)±òc$M(V¶(72 +(†T.]!²b=f”;w£¡@s}6q§°Ý&*+&HÊANt)K;›‘ÔÊñ–¢s¨©†ëLƒó^€Û…‰Õ›p&#œ«å ð¼™vœ|_QĀ‡Õ²I¦R ‹N= >p!nÕKQوò3á])“%¢BQCN€W™³(è@H(k)×RѹÌbFz“šÑZ·´øn O,†%ß«CJæ` ÷&€Xµ{8º‚SX• •™£qèŒ"aŽÔhæý$Ÿ«¤L‚ðc§U*§]0*¹ž©âU³!Æʟÿ¤&~.±ÙԆ"¨ÚW6b{–¶"Îâ(ëÌjºq#:$Îù¶£<Î}„ZáH1³J]°ãl„\¯QåÞ6 Äñ'½šÊ´ƒGêõGé*²7£b0—y €­EsðþX±â÷D‹‰Õ‰c@mê8J°£¹æ”¡iIuž¤XY¢òò­ª.›KdOõúÏ(mzØBÖ啾Ë÷±Xk]†¨Ô.Ò í8yD¬â9þ˜À°Ø†Nnð³AD*Ò²DÿL 'å~sf™%àÀv:v¥¾ù fÚ-©–TCçċKœˆuDí\L4WìkŠsÞeWG û¤ AV Ý 'ášä*ÂíJOu㐤˜*¿ªª!1 ú•‹Ö C:'òU­ÙÑNrbõ¦Ç5%Œµj÷~Š,A ^ž EÖTˆÁ EU¡›Zc0õ]X1÷Eë-À¬¼C²ÀjP=é3uR¨ +"Át¬îF N€P3@¥å{þ%$ÞTÀKµ.gû*Œ‡í‘ˆj’ÿP;Œ°"¥4_ +r%Àe4JäwÒ²•rÄ5ښdP V²€hÄ)ª»#%}£ Wæ¢fč"IY´§ª ªI€¤e-Ì«ÝäõE¥-"z¤âÄ ÐI*ꡛ)F)C-Wx1Ž:Jd9õJ +¶©Ô+(âbš:Â0ª'ÕÒ;ä÷¡8¨$ýTݐðî-ÆöÜ÷jÜ¢GjibªW±Y÷G6cÑ%s(´2<…’xgq•iÀ›žâÍRœä)šªû®–úYXBçhvéü¾‚‹XQ +OÑt0Fí–릘,ãíÍA±Eœ«jW™–ñqƒsH¦–°ÁTd¼Œºa*¼f¸'o(æHtVÄÔ’pÅ«6؝ï͖—Š@1 +LŽS0¨^#aÄià-þ§·Ê>æßãÀWzqˆœÅ—<ºaÑ„ëTT´¼Š0Ý·‰*Æ{H(qO8¯ª\PÄÊÀZºrR/Tmßxp£”K•UW;­àäMHpžÁ”0»ì £úƒvÖ]PÀlò>»!B=’]#8hjrÿ}â+ì=ذ¨±½üþêÍý7ú·Ÿ^«íȝüæëÛÛë•7{sþÝõåïß^½¸|#o…õæ~û¯×·w÷½¡m#Ÿ^ß¾}±ƒ(æ(WH"B´!œ¾D<¢ÉS$1µ]DQÍuø@à (hì¹‚ÍéÙ¬vljþÎ ¥µ¬ù÷Ø]Öì3ª´GÂ{»ø¤ûLµð­óQk‰’ÛƒKô4¢óZ¸iFgEÒnþ"L…²G$9¬kBÖY¼¹bM{“üÆÌQ}툠@ 9÷Nñ˜Ñ£&]”èG­Fq’Z'XÈDQä R\éÇò–Nk‘Êò11«E¨1&5˜Bԃ¢vOÒù9ª’ˆêÇBCVûƒ4@Þ ’ +Ô/s ¾!Ž ú}ÇøcD.™2P 6)~4"éÞ£=ÿ>€’*CRoH>'ßVõêðw +ß~Þ!]nT¼^YŠô:aÿ ¤ÿ¶3rí‘MBgE94†™¨‰ÌÁ dìa;m NÚãP 9 P8ÆÀäwEìr´Æ¬4AÊ¥r„Έ’ ¢ÐíÎS•¦A](AŠ$;bg².mçqð¼ô` ) ;Ñ቏“À—ªÛ˜b¬½NŒ¹ÁèÇÄ©I> 傎µU遁a;²ˆðp0‡)²ôÀ\Kf…®(ÎÎçɶÏߗ$yÙây*!¢R»e …~ÊaZ•¢*î7P$…щ¤pÊm!5I¤ñ©}ñºpµµ@Ó"ìrÃèåfgK +2¨ƋmBF€àvψNÌÁÒR—œÑ²Gý^ƒ'½e4圢ÍÓÂfRZáQ +®PD'2$Gñ:ÉÈ0GqeDֹȇÅütÇ,€âqµ<@RJ¿“kÛ£N®¨S‰ªk"Ý%Âiä6%D­cüêú#ׇ¨Ôkñ}Òo²QÔm!°[,>F b¤í&Þ +6â 煋Hv +ëÖt³¬'²DՉB ÜÁÊò++U#x E°3qÐâæ…W£¥lf&Z¤D-G½ªÁ Š¦<ÖV³…%~“L°âfeÉ<©¬^»0;¬ÆFV.^Â1f8Däå̜NEŒ!ZsÓ¨[• `_$<Ò 9ÊÍ©¡šn­&f1àkÄ&Îk¥§.4¹ôšZ^¤Õh—)Őq!FΪQHªŠDÌee)WF‚uˆ£s ô@↉û³€+¡¬óT}í"ѺBáÙb8Þ¶f‘›ðóãÉ‘Q¾mý?Ö{$†ƒ…9€ï/VyHrf ڍ½°¤”ÏâG͟e':H`‡£3“¬W”S‚GÑð½,.a‹´IŒ•’©=Kԑeczƒ“{èZâR ¢‡R¥Dª…-AÕO7 Å(³v$ǖLjœUÈbx’¼d÷Ï{ßڍÚ,:A¬$1<©Q—o ù}µB±Ê^«}®åSŠ†ˆã¥lq "Á6Ueƒ +GĊ¨ØÈV؅x4É4¯Qg|JÃèÆP¡ô °šPú4;¢È 0Êa“P#R<8o‘˹l^u:Ÿ,c´ß`ÿmÃf¤AÕ⠵ƪâùʙè6ßè5[«dÐJK–%çÈÚ´/Gú,iÍÁ‰@TlDÊ_—˜5’"±E&-ÕW4늈Á!co¤hL9Œ;Ï-iÀI~6ß½’^EåëZ…âZôûAîX>Ï × r7‡¯s!$ÒW ™£ê¬¬ÃˆÇŽ*!£¹HçœÓÛ\@úªãh‰QÃÐÔèJg0Ž¿òÁN@#S…#2¼I©¬Ù$¯3¨È΀‡9}%j`’ã遣¥2¤zâdŽ‹:P SPæD0ˆ¬y…’˜·€pg1³pÕ8T úãèdыøŒ«œ\gï”È*ÔÓ»¿V––ç§ø^ -¡ÐZ®8" 8¤6=Sq´IµjlH…/‰k F“Ò"@Ý5‚¸³ZM›|ò#KÜus·¦Æ$ Åùh‘…÷&¥ýhaa +‰“€øö×ÅK@E|/úÐ@‰ó‚'u*µ¨£äÒuoÅÔrÊ— 5ë¡Qµ5 RÈ7°˜3F‰#8åێŒE(rLžá ä"˜Q§lr +˜9<@®nâ,Q¡%‰®DY2^ƒ,!'Pà°$’ #H-z“½XÜWÜbJ«8ÞZ‡ž,5êl1Ó¢KÐ~3µŸo ®ÝÅÛX´­&e‘ô¡Z»—ª2¬ÖdnՑ† ú"Ý+QL'd¿ˆv ŠÎšÊNٔ6É< IÕ„¬ð†“)/¶A;äבb#8_j¢^a0/–ëYì?V_$7HÔ®S6¹Õ +†ÃÆm‘tG½ÒxmvøË»¢­ðP%ö–ˆêJ¥(å#ì–ìÀÖsNq-ÆîSy±rx¤Ó;ù|TK=Í „rFï šPªº*‡T‰²DoYEÕvýH~6›TԯΒý):%P·q¥@k%#…PkMŒ ù ¬y –2ÉϝY×¸·(J$5@ Xî"ÒA¢ŒÑ%+Fe‘ ˲Óت+ˆR˄ïb…é" FK0 „, mvqĒýTU Ÿ±3]*N;eÍ6(OãOR†Ñ64h>Cašຬ€ÅA}êÿà„BA7J +ö+=€+G9.2Ò ótHay2Žªt@2—†fÑè%Ž˜‰”r >1˜Ú¶Ýb ¤#k±FRõ$f‘‡Ç*EFl\"­D«*R$¬Éù,ÅËùs{²³Ú{ˆ r,-ýRµ¨‡(KYu-䥈ýÅՅN9@r|IøG«¨à$&‡ /9À"Jd¯—"†‹<>r,†*AÂ!òäXd< ªÝ)GvÕÄZјä–:å@y#v†ä-¢Óøžg/õs(øgˆ¢ü.=读F+Å +Ö “$%ŸdÕ¤ªªNÅ9I,§¾›GW ™ŽØFfæQÊ*HzDÔN­iä;XOÕïïÎß¼™UËxû!jflê½bo‰¥ÈGÀ$¯øFám¢v +Á#—©“\O2%ížÂè* b•“1i âÃ/BöC­³KâÒ"â(õ8¹ŒXí¹‘yZSÄê(¹ÄÉ%ü¯©$ƒÉf ˜eßï)e5]<6'b,U7-år‚àEZˆØ}é,™Nï •`C0ÌÈRT’ÈÁ§ùØþA÷OŽ4Eˆ£©Xܵ*E>)ÞXkU4 :GŽtD.e%¨hÆiƒ"Mü#K¡\ +Ú-lH§Pâ‰Ë~К½ÄvÅâÈ­À(”:>Hé̔4D|ÚQjvÈ‹µÔø +!הO(äˆTar-ˆŠÏº´ +Ì^Eª)¢¡µ$’{^ŽcŒb-R)™ç¥jȯ–`”﫬«SÃ!Û·8I¸Z¹íM ³§Ä9š")?›z"æz2úå®HnQ v©÷£¡š߀T‘Bf€ZMR–‚ª¼†TüA +‡ Á$V†2™œæk` #é¥ so)fR@UI=áë˜%§$óâ²s³ÅšÔŸ•(&W6Æu”êºHdC›.¸xè¼d‰Ð˜IqE ïõœ@-Ö.Î%G`Žâ\ºÖ‚Ä‹Ta‚ON*Bƒ FuŽÓÖV,ÒRՉLAÐÒc†)Ÿ=âRã˜@¶óP¨0r£³Æ¯kèˆ~ÀÌ°×Cn'ªã"e3)Tâ¹%D zÊÄÐP5Y“œj1$•^kÀ“Ñ*«¡J”d"5I)˜ÂKEkTGüˆ:ä·#{vµ¸ªF-¢ò‹~öäåzN÷´Ð*dÅâ¸Ñ/žÓ^õ€® ®+Ö[ +sáÄy©ÚÅѤâY`]'@בàU°Ð(Å±È ÄÞa–LÅFÅÛ^ƒ,«Õ#&~¤v#v]YýdúyÏ:#‰¹êK .aR–EQMt4½ŠA^Š¯Õ!$r_̸!”’×0Å4ªÛ*šßCk”XE€Hž•(j_FP#ÅÕQLì㙬`P\sœV1MVTJæNHÔg£ ï¼&eNu"nªV%òH@#ɨ’)@¢+Ùô˜YâÅÕS£!Ö²_²u±KOgó<[Éð"Î>n¢’m¹ú•%%[·srV‰ƒ¬‚‘kiQÓЛh'‚©§ã À©AŽ~:RZŽmd#ó +÷9²„¾JA-¶â ©lª0b"Aݔ,nðSÎÔ¥LeÉrå£Ü!…JbÜ*ÓQT$„®ðsŠRŒZS„=¨5W´B–TKW‡¬“èõéJ“¶á½œ¥,eâ´ rHÉÕIF4¯¾“„À&JÚ݂•—£1òê@¢e¹’z¬åS{ôwÕôBdärECk¶·%áëQç™RÆAÓ%iƒÁúõåhîE3$€.y±N$Íby!(8jZæ «F9F ¢>8Ù +ä^ ·pa­4¼J¡²ZÁD°!*»f«°Î™A"¯·³oRÑ+‡”2>ºä5¸“²q„—–„¦dß{E¤e1Äñ†ÍYt]'ºåŠDáÚ=âx?hõ" (IO±ùõ ˆx¡N¨ù…B‰48—"âÅK=ãNòêÅ16‡kÎ[yJꅓ#²Â8Š©–’•ÑÁŠÌ-PŽŸ¸¶¹]„3¢2=§f:*\(oÓÝùÉEÙß\õ'+kPp’ʤÄKu¡oOJ.Ò Ã"©9"—©%Ž„ùAr™ +@½nw¸s¶ë(°R#'´qaP?¢~¹åâ\6ûâ9…ÎN‹­2ÒÔJØèæzô¢Ñ‚ÑÎbÑÎBÑÎ"Ñ®ÑÎâЮÂÐ΢Ð΂Ð6bÐÆBÐÎ"ÐÎÐÎâÏÎÂÏ6¢Ï6‚ÏbÏ®BÏÎ"Ï6ÏâήÂή¢Î®‚ÎÎbÎ6BÎ6"ÎÎήâÍÎÂÍ΢ͮ‚Í6bÍÎBÍÎ"ÍÎ͟V| ­>çܘª9H 蕒ÕQìGÔʗ¾ø‘wÕ+ +8Ύ‰^ŠGSfÀ?ÓEFçç©6Ð¬UgˆØþ¿ßz¿¨¼,=Pˆ –A(Mû•Ruóc˜DÌR"•†•(8ç´7¢r\"ë± +p,‹¤ÖÁÊ(P܏Â/½^žj”šb³“U5ýÿì}‰bŵíûÿƒäL@¸º«G¸ Á`°±!„BdY¶Œ$'7|ýë5ìê>’ &!ä7\©Ô§Nu »ö¸VêâËÄ@˜#é<ë æ7s*)8äçW£„GC—¢0c:0|¶hhtÍ7öŸˆPÔÁ:;âÉ á”|Ą œÓ#ðÐ *¿ ·=Êâ8´®Ô%VÇ·üt%.:‚Ûétu]Ä +²¼é§ûõ"Nz‡¤¹é÷ÜlÝõÙnÔEI£B߽੅|ã”Nd§Êx<¬•ºêéuµ¢€5žm#CÎÂFEãtEĽA˜5‘¨´)ž3ž•êÉ›{íÐ՘³¡÷‚2ÚSÙén®}Éè͔I=[I hTͷ勏*‘š—³¡*wËÃWKÖrꢹN’€¹,z V…)бÜm#AP‹Ö(¾mZZ«HNd@cÕE¯*çh+…¨ÅêÓu°W](nwL:@ã÷Ê9nƮҴ´Tô¯úlD²‘ž¢ËfOã"W'| ªQ'åsŽÊÓÔ瑗ÕæÆôRl¬Ä•3s `PPtêÆfƒ),5ê\F–¢ž6Œ‚û¼ï}TÔ …VTF¤¡g ^BhÖ `PV3¤ñ0wUsÆ8X º×ÙñQ?‘ۙŒNJ!{kêSƽnvÏ®5ÚÚ¦¾jéTgôqêÎ%Ž›^J–·j4 pŠªÖ ˜©j¹âÏD®Ìs4Ñ$r/{·9CÞË4Ä&ÒÎb±s‚h%1£²"ʗ2€L±…þš¬ÌG‡ý¯$FR"¨ÑõäØþJ܀©8ŸÐZ L:¸¾r˜Áy.æë¦åÏLK ‹P*EøÕ­ÏR%öOŠ91eÖCÀ*s¬raá" ØŒ`´À¯J56¦£-k¸6:ÓǁҁX\Q °-•[Šà«•˜¢5=W{ÃJ Wck‰žT\À—ªk+ÉtäDµ[p”àŽ +éÏò.݉šhuöÍĤšÒœ“óÀ*qóFsãN*¥µøUZá¶DY“½8•ó}ª:„½Ymr/å#äºé=Ñ< ђ½Q·ýòÛHa䫗PËR@úžISÐ9²îÇLzZÜ4”VÒDöaÝEЅ0,a©ùµu¸Ø"»Èœð¡XM·u»æPH†À´Æ¾³’=M½Èœ×¨Á1­†?°É¢¯”°Êu°N,‡Y9í¾ê†ø¼ïr‚)OONç1:-·Ÿ8–S‚1­nÒ¡ ÝrR^-rSX`ÝßGÓÂB%©×áyl¨0ü#M±ðRŽ²E “8«–}í~Cê}Ì©âåú}§Íße¦½ªmz°N¹q™(ѓu¸á¾æÙæj'žŠ[Ѭë½ëTƒ^še‘| ÅFÌQ†ÏN†!l ëdp[ ž.ˆCç›Í:Né»Ý-¾ƒZZ¡gÝò¦3gçªöhÆô ²zË ”»Úïݖd=V©b~¼´Â\þJܮ؇½Ì´1ràSÒtd]¡Cxe¨ ÀB86uЗHw'£\!»rxƒµhÕp5ô¹ñótÈ÷֑Fq´£œ­Õ?HÑ5Ä9ªgN'@ÍïCc“RøOlN=ËmµA§F%6šàºÙPÄ@%¥(3³]7†R]™#¼8kÆÆ.ðºQþ!åk¨Lä¬Ò(·´‘;¯†§â-TùXߊ)‰Xæ}.[ëpˤH e…mqN q­ƒsuËÍó ˜Åß6ö26³¢¨ÑlôWpv¡–¹ŒMÐ Ðcʙ¼7áöq$•nº¦µþÑ)™èªè-—ɳW [©Þ¡úl–K¢zH!ˆQ_ëDpPQôœsÀA UÐn0}4W­ÇŒƒ¤z%PÍY ëî9‡¢1!ê›\>äØ ƒÂ£#ÀÁÒ>E•/îÆØ%@Ñ?§ï A{ÑÔÅÍ ç}(%ÈVÏÁyØ ñkT ëLÛT«hʐåfa°Åý`ó¾‚ +Q±ÛÁ±r#/¨zVB5h­­ïÂmY3!™e®VC  0Ý`¨Ýó,Ô>Ö»’rª±© ~ªÝvVv8²‰c‚æTŸ5J1[(‹—¿J#H¾ºxdÕA¤å•ý½·¢¹íŒ—u¸(‹‚MŒWG¶=­fÎÓDz›áA ‹¯©ÈR¦Kðµh¶> \ð³¸!‡ÁƙpÓùñ®³¯©”n“b­‰T™ ¥K«¬œ!p‹PHקÞþ_êåÚ!¼‚ !ÓK†à:€r›Â/›œýâˆF‚°5.“Š„ ™lڃ¤i-|ƒ,|='Œ m^Cǃá‚øÜ,ÿîÚÊ!¢@Ò–…³Ú1à*W`¤‰ä*ÔZG£æ<à»h±fιeW– aYƒ¤+ÜÜޛÄ“½ +¡þ$ÔùË;Ì7˜j*îW–ã)ËÞ9¬ž®L0˜œ 6*¹Á„Ö +¢÷uÌ˨€Œâ„CUm´c•ò:Ro³’›s$sج•nmàM-By–¨‘5| +8]+úƒ8Çï'?<¥Ó(WßO‰Tó>"C9ø‚èÖ»p,×:²»ã‘îkn$nÁj£TÑ"ÔtšÔ³*~8ØÒöä`±ä n ·D l;’û°xäšëãÚŒµOñÑe‡jM‘ÊL£4Xsø•à‹­K+é™àç/P衶R Ûv^©£Íb,šãóµò5Õ©hç9V£™02‘ìåµ¥z1šË¬'Ò1˺—ëÄ©å©sL¹ËÞÁõÌOB_¯ÓБå`j‡^1OΔïÝJº¤&Ð Mܬöî 龟+i;uš +'roüy­`/¤YËo‡gk…„úù`¶Hõ0_ë2‚*ÂGHûÏV¦Ñœ•èD¬FÉè±Y´óyΏϑW…|ðà €¥1kÁøÅëڕxEå·Ï62[mR`ESKϼ.ò^ðj#8¡eÍœµ“9ˆ0eÒJ*«–,D®‚ý…™ýʖW` ‘woº¦°v×fÍd¿¤TK­B”žý"UxjŒ+›¦ñ€d©ªšb¼¶jJ$hu;åL@«°[ Ý¥¨7U I +ºÑÞã½Ð+Ù[c%ƒ»•¸Ú¢ٝfêkh̵} (ÿµµÆJ}_ë05:J-ÐT”wnqÃ~nÚÖÀÝ,¢¨:É« +Ø*ôz8û*é +Ød¶ ›Ædsè²E¡x™ Ç¥Jr¦3*«`$áµ+ÿ:ŠQƒ¡ï<ê4„'nrÂ[‹"Ô-捹_¢–äl—_”ȹåÍ Û€g$!ñˆ«Åº™qž×ë$‘n(mk4:z›µµAÐ]-\'…PÍÎ"·<Ú¼Ýø`öƒäÒçå^ðkUQ'‚ß1P6›&Î@ÓàR9÷ÚsÆn¦¼Ñ(ºBÒ£!°Å僳2±•7g0°I-søpÇÞØêi÷äŒcT"qFbu¦ËUtF™v0ÇðÕb/~ÎÑÞ šyºäÍ©E-¤; ®—¾jwÁÿ‚Sê«&X¸£Ú€ c< kÊ1w­ßtwUv¶¢µ 7«q¦~áâk-Aâ–ëi(FZ—O¹N ݜÊÀÚI)¬ÒìSãXt7J§ª¤*`>£ˆ¯¼ùÙhÕƇœ¦YädU[(ё°3Œnd˜WsÛ+׈Ͷ Áa’›€€S &u!\€Y¶ý´ƒ£†$¦êb֗+Ə@Ø2CÐ<ݏÑ싗z j¾zr«3ª­&u<‘ú®XPBTمšG]h¬²ðB@²ÜFܕÌ#­šc'5]¸ì–{Á®)Ò¦Æ 4E3„ÿVÉೝ$âl.€BL÷}òI\·¸eª‚Žh0QôŽGt †n²†Ê5˜*µDn• +1ô–›ëšyK‡v}WšSOã*Rkƒ½Å¥Ù67ÄG$_àï#€[^¯2io4bÒsLo QB=¸ þV4+î„f˜³Ñ܌ñ"w™Ù“.5óXÅdbÆ)=’ZjÙU øR$µ i¤Ê˜< "cEä¸lŽª €UÈ2%ÕØ(u& |§ÖŤúxe,oDFޖI…)itÛ`þŽOI“#ñ }ƒØ’¢…(të|v+ÒäºÖý\;¬Y9“̨bsÖ}I¿©u¾PPV—t®Þx¸u VVË^*$ËÕ)mÕô†XDSRU¶©ô¤Q¡+Žy^Ù¹²P’'G;Di¯‚øŠ4±çØ0é$#ÒHYE¦‹’*c®lçwHŽ-†ÿ Y}“áSëj*Ó!õª6Tl´ª‚pÐÙ38¾Uš0âšK)o@ Y…úÀ&q'€z +O$yƒ”…|{̘Jݜ¬Ø¤ÆþºlYHûÉá26Óͤ9?©¸`ò‚˜ªç 0«ô¼oB 刪v‘É;ª‚‘1_!D²2L]10Öü*uÈ8ä`*Iu(5 CZT^U(áŒÉ+#vúP¦¹~hHÞB:´B’¢äñ{å$E zæK*—ÕñúÔϘz‰_5g¾ö²ÇÀR[G΄›Gbp),Ÿ¾sCѨiíf hNFcïïÕæ¨j§¯$,썳¥;•vSG “±T飬ä`È×í\ÝNJífšGå³1Sˆ®ÅD½«û° «½çp0£9§GéYj«ÖžTÆR‰S™PӍ<ˆTn[€eŒ‹¦q +Aý“Å«ûÔAÚ6Îr@ m1¶Ã*µpÐF97\6*,ƒ§{Œ×Â>®¢FŠJ» üµ.°Êd©mU¡®Hu§qC (r/a/š‡Ê*dïÅAm +C’N£ÆZ³6Á³Pðu„íR¤ r-A‘-¥°'¸`k1õ¡ji]]‘œññ¼¨cÇ±¹Í­Ÿ5=zUÍ3Fp•XÒÏbÿ>ýÓÅËîo¯]><¾½góøñڕçG×>=8Ø}…P‰ÓbüáΙ ©™öÆ$ÅÒôϐò´úO¥¿¤I;™ñõnLÝÕ:Õצ;­9s¡ZÃõ”žMê0³™s0_sÛ¾ÆxžAÂp +&û7 ëµß€¬²þ Èú7 ë߀¬²þ Èú¿Èúã3Õ¤í쯵]ól½ç ÿ¡¤Yw·¬ÝØ=øÛöá æ¬÷òÅѾ+zE°}Qüĸ÷ž›Í™Mn º/s„+2Ø+hU›Ó›%E¤^Û¢ï YI¤C~^¯K°6×:ý퓱¡ZohÜÔLÙ +-=ê¸dë^Ñ!ˆ·Þ<àb}ÇPTÀN»d"JܷΪ\g¦Æ¶Ô4g¬Ê¥Ž(’å¢ˋ>3?pƒìÜ}Õ8Ÿ+ÊÜàFTüe„lNAc‡,¡>˜0k»Jk•ïL¢%GB:oäšd’t¥X,È®gs.ö¦uY-{Ä=°$HÇwE ©!wj§qñ¤mÙ-k´BäōòªÂ"tn_Ö§FG¢×ÇÊBhÂ)H¸ŸÐ*’#CuvX/ÝEµ ðam9T!FTD6iBHûà å6‡ã_A¨ªu5ä–*o¯`NÒJj;Ç4õ¨ÆØX¥Â¯:?ò±C/U 1©ÇÓ­”v»[žÝŠPctÓÝP,‹F¤Q2˜'÷%תd;:–5X­©z#SJ1í{±ÂroÙñÞg¬¢«¬‹«‡iϬ±Á-JÜÑÚ\KGeo®yD–:“½XJe._ï±n¡ +Za ŒSŽ6™%›/!¤HÖµ˜ÈŽ|ʵ©!ãLvNzuZMÔ©žž±[+&ûSGze¢Tıç_;4”'$ +T0yØ䪇ì©úÖÚ°Ü1Ãå±móàÜ©Šø":#¸Ñ˜ÏT1B uÙgdYG"%Ð@™.’tp+“ý¶ÕÓ]ç[¤"è (?¥}Y#•Ÿ õæÅ7(e욌—8dÞâm§D,י¶slüČ­Në(]¥Œ +`蝜Ôq¤œú(‚âé„OCšÀ}+ùPõÒ¢·ÎÈóenDø`ŒpN¹j«‚YÍe[“êÏD›­é9Ä ‘œZUŠhdCøR;Öµ¡Š¦.ők¤\ãd?'䟒1c¯c½Áêgg‚ÛÜ¥¡}ÈQG¨4r­Ýpì"«ƒ Ì îà·Ž95׎Å1JѶW¢„nêÚá2±±®]±`ŠdÜ·¬KPGÙz5'm3ŸÈœ!0¤R£ÒXóôæa,﹘¹e@O yÏ[\f'|Æ[¨HVGn{±?ÓåKç´ªIÂ1%wwÀzc:“«È¸aD¿ÚJ׺¾uY“ç´l8”˜ÔÈÍé)— –¸œA Š ø±s NÍ»Åkš0¢cS²“*z¨cnÚ1(taþ!r]×)½6I²ü伺‘ÐÃòÔ ]`Á·—ëÂû °È»] ˆ¼ƒ.ëÕ&-A‰ð¶ˆBƇ§Y÷´‘DÉÛT$hú^F–Þ@U_LðHm«W€y|qóâ$[kûôØI­eg}“u “b‰•¼pît34Š+åÒAt¸}kÍc.Üíàò¤À÷àíؘ4˜3ß÷áóLÒPqû£R$Ö¬U"´,èœ{Þ¥ž^Z(NtÅ wk]ÉZj\vƟˆÑÛIE +hî)<kfŠM‰N÷,V^B"—· ›Æwf&4Ê#ˆÆŒúÑHöÛÑ4¼aeNŠÜ-ƒ¹ž9šLèË}ƑošìVŒÃ xJèÞbŠ'¾EÒ¾i”¤[֗v‹¤òÈ@£[¬>ÚL°]\èI³“>eôʜ˜ íA$˂-vsv}¨Ì$+° e7£€MeZZUî1è˜}?ONÌ :Æåäv³×vç— ÍôHy˜'¢ô,w^w$vH8 c(9ó¦لrØx_@‡µþ&*ݱ%G}±r(Qõ»çæA.p*ÓÙR֎٘R­„KcÙñBÀ5"ó$¡ÅPŵ34)÷¾ÀîP„yÜò‘ WƸm}%(ÿ –e‚Ç~~®NÈ¡6Ê5²sî÷l2՜ ¢™Ž’eÀ¶k£¨›‘‚ 1g+ÜÌZÜ-¸¿G§‰ÐÞà5à2g4Z¡êlRihÁ¼Ý†žFn Ë3ð¡t%|—½í^Ø½mY4„û‚l +_­o¢TÍ +æùCN“® +*Z¬B뜴•ºŒ¡ìº¥ñÁ\‹ØB)Ñv‘ÐOˆ a§!ç©Nðú + ÃläŽhŒ¡Õv† TªÂÒ&¨¼ºQN†¬tª±¡œÒä"—E®æF5HÒÈrT|ÁH“Ðì­Osߝ·Ûòã£/v”‹ˆ¬2Õ:;;hï iÓZÆüÝ[^‡4š¯Áµ`yýŒôâФŒ²­âÇU)$TúJ߅~<8Tј4›LÕüMÁX܀S‡Î“`mƒÍ‹ØX|Û¹Àw-¥R¾9³² kDt/‘Mʉ‹Ÿ$Ž³Ê`‘Ï¥ $¤kKaù•\ßÌ¢–eö­pä¨ã¦.Í0H£¦ç–Ýh†$b¦ ׃ÓÕn3pڜ6ÂHXàQˆÜTFù¬K }/•eY3GA[‡è®Š&ìsÉk´ñ‰ïR¤’4u8rŒÂ'ØéEÎ(º8†ùŒýð / ÂéÞ¥i +áf»÷i‚†äð](´°söß(QL¡HӬàgój Sû`Ȏ¶˜åŒ†áo" z5päð°b¨·7 Ürqq+úG¥bù€(î4DꨈB,ƒÉ&hæñ¹åæðõõR¸£9ü\¾£Yµ² U‚À.¨â A øÒpY«¼w98à²R¯Q9׸›Olæ0ƒ]Š‹+ øú%÷Á^e¿A©€BUMS,ëHAƒëh,x)ˆH3%‰9—E‚ ޙÂ((Rê9Üß)î#20 ÆE0¼S“ü7€k‘']º†¦E±Bª¢ø–Ù­ÉIß;å@6ˆ\ry7Ž²pŸ¹s·ž“7Ä@ Ò2qAt`ŠfÜ5ˆÁŒŠ¸$à#w +6dÆ­Gî1¨æ-¦y²¹’ûž J[ÌÍPrýûڈ㹝xGhI4v51âÞÕHfÕÞ>[]ßÓfQaÃIØè´-õy,¢¨ù]}‘ ÄÇãwµ%ï…t76jà ÉLb~e¿ä‘²ô3.ü&,ág”‰·qñMßU#¥njníȃX¯ ɍ·rŽ**Vd c¤[¶ &»Ÿï:]j˜ë¤’[Z €}sg³?,É®t3#’è“Mˆ€Mk« y_Yö˜Y +¹ñ@mz}•èxÛè];§[žÔݨIrø¡‹¼óbLqaçAxMƒŸô­+J•[õêh¸$|LM­h•0ˆgi‰pY\þ_î¨ñkÑز‘ B-쁸¿ˆ*^5Ú/x’P aì3lÕr±N‘ƒL#¶FÌZùƍ aµ©Ñ/{Õ#€(ûÑ²î}Ô³%e¿vJp†åQ‡LøèљüAڅuÄ33êÛZ[5sY€ŠY£ü¬üþŸ"X©)–—֏[qŒ±ãBÁEŸaß{ú诗ÇV´ÉD—wZdí`l R€ 9£èܐkb·bÈpæJ„ñÍ,£‘Ñ„ïÕúÑú¬¢¾£Ñ h k\685·EcjRà +µpJÇ®˜ñ}'*µ­&á꣭QúŒ&9¡‘Ù0Qr%ÞµŒL …£Z¤ìP +"#×!Ú¼¤yÝv0½Þ«ØVEäfc7äã©y\iS‡«ž¤ŽÒÎ§C­$óR)œCÿjÌ؂ƅ +|ҁ30 +/Ø£e^>­ß¶¶ÔqP6CùNkwq½ÄÍ1)nýt^àýoQ£Ãûe²Í§»Ž/eLý‰ÿ—½‰,ÝpÚr˜Ó™±ûAːÐpL¨(G›TTÚDІàq ñê×¥ùXE’™àÙèÔA¬7«—Ø™:2˹Ü;ºu,tÛvyCu„n­œÆpe‚EbãËðDÇK¼qo:Фð÷,¡±ç¢Ÿ¡ïÆ´ ‘5ó½BD´Pn;¯átеW ÉÙFԖ gq167~¯¸a²½†Z/«æðT3¶»ï©Äß~ûß!›^ˆDlÇÌ¢ðJÌ­y¾¾—ãD¶¹£-ÚecÜß*‚\yÎ7ÉþE¯s£ŸŸ[]m¹è³¨úê÷»1öWŒuåÙù]›¢¿¬¾ÿÓ×éÐd9VN„½SÍ©ÍáóßN/-ÔØ:"nŒX®˜‚–Ï2JÍÛgÑëJ#Go67œqÑiUr"¨ÂU¿:ؕgçך;=1159ë8eC[¼ÆњÁÑ!#Á'MšGj5T‹Æ¸nR%ývñ,*+ÚöD¯s£ŸŸ[#yaî³Ài-¿¿™ùˆ—c]<»|×èôäûǼôq6¦ŒÙ ±EÉÇäÕØ5–)‘‡Ü„Š‚&.¡†h’åó]̋€â(éBz pwIËyQa•ëÐðUåÑn(åÌ̆`#Ç\\ÞÒeÙA+›Y Ìïꋆ~b05ÏL½»¸AÍ«Wæ*‡+W.om=Ý»{pÌü»EÊÜ?6}E8xô텡0ö¾ŒiØoØ5¬ÕçÂT$åSÅ]_`¹GRçæ¢fõ¡ÔãËÊäˆ÷B‡;¿WéõÔ„™Ãñƒ¨3òöN5/NT4•+Ž,°Õ¢1Žs˜Æ‹g[¯ô¹lä÷G=šû¥D˜ n䃞C$h¬‹'çwZôyêý11I殤íd=8×GØxÈt›;o'|M;îÓö̐¶Ó9^û›moÕúÃkÎã^Äpt¸‘F%:æ쎼ÆTwÄüЉ«O:´@óÏäDìÔoÌ'8]*:Ng¾t&FáËM*2õ°È¢H§­s. :YۗÍ$µð¹ŠáÏ2J­^[+8³¯_5JÁ2T™:@~„dòøºj‚éômõ3ôP®ÂÛs¯ÄËÉõ¶HsßP[°&ÛÞà‚™ }`~ù‡‘œ+¸\H´ÇëÌKƒœ@¹cQÁ)Às|¯!Þ< O\€™ñžêK®aNÔZIƒÀ$®/Éð!è2&»¼"ɕmêF´Žšø²öteåÜó$Ô)\N´5ö<´^w=çFv¡ê"í¦/Õ«ŽÀàWm‰qÊ å]®Œ ¸Û£={`ú0šJð×ñn“ÚÉ#g>JõÊ)a¯¡IKžÚF‡3üœ5É ôe¹¼‚%w-ן×|¹”侏Wpp  x.¸þx¡NG¦e–m½VD¬l½7uÄvÚ¢î4sò ÁÈ)Ís Ý •¥¡IŒ±&òÌô‘نܿES¾ zä³RnŸºêêQӐJnS9‹½«±Š³6"˜¦ +jÄÅSi©" äø|‘ˆJ­ÔêÎéöÌzd H](2‚>ƒœà сã;Huýd˜pÀ­ÅSQ½€BôB^»¦*óÇZ}ÑP†„åpÊ&BõÊñBKgG㠑™r­]î4j-ªÆpv˜U!§¦w4uæ~ÉcÃæB­ï{·E=¾~ K‡kuÕß?)þþÈ#Êä"¶©Ò:e)Óud¥`Ftcê`"Ò_u«Â—ù3H T|$#>æðD[8Ø«Bp0Ú.CÂÑ¥vÖeɪd 0%RÑh5|²»–pS•#Ó¦rµ–¶øH»<òfhfçÅ¢, f|âÂñÔ¾®Œ«aѨ«%Ä2&YÆ.ç®x¼&%¹óWe÷.G³;5}Xٝ¹x6¥éFœš–aD®ŠÛU ‘Ér·ˆš w››£ëEĹùìL5iÿ`UêO®=8Ú>>Þ>U J])j@끹*Lèm§i”–Þô ŠTŸñÏAÖP]éÅ D‘Cª„‹ÆÉ{VIÄ&&Á¡d™BkÍDá;¡P?û³èÒY€€Ó­Ã•UՁ(ez FÛP×Ջ ­•8ºÌ¿b)Ã[‰9­5´(`ïT—4Ay¨ ú qÐú¦HTѰȃTUÔº¤Þ(4v0j]Ìë×vÁ¦Šdœ¶ä/ò¦SüºQ†Ssc…´.@iŽ c +E¶× ,GŒ}x¶q%QŠò7r应É6«ÍK7ÈMÚB-\•*ßÀŠï”$»Á|§UR^F%dŒÈǐFLw¹ÐWåbÇ*°Ð…œ5eÈêÍÜ¡Æx%:¶a:!ð[GÌAݹnUŸ3][s(£‚HÊcI$a|Ahiõ""Nha¨‡hb ÕN|œõNDéRw zùž5òZyVá”÷¬g;K AKßT5¹M ѕ,ÜÎirZ™^ébj3z*2™µãP3h²Æ!RC‡HŽÈ)’'éùîM“3"3?ñÉÀ½Îa$W‡PÉfIË<‚`X6låì¤ÁO4E±2NcS*×LHÉü+¬ŽÞ +Q%uy(uvM”õa¢p7÷ÁC •K*~% ¥¼ú °ÐAxg­À²}{ ‚¬³‡(Œjj4¦[ aBFE.l´uAúɸÍ"¬,ʱ@ç‚úL¯@uR>‚™õÞbìAøƒBöalõÓÇQå‹ +)2b.âNš‰K¹gqydQ¸gÕ¨5HòÅQ ]Øúdì"ƒJU¯Hérׯž†¾º[$Õ$!€Czc>ç B®–y‘üKmœ)á҅9´ +ÄźT¸Á÷,¦œ0O*UÓÓæÀ+ÃÑu|ªaÎg‹Ô>ò".3ØÝ…ŸŒÁ³ÑD]Ì?Õ +1j,=q@»A⫍ƒÈ4•äœ„☵Z‚ýU:#¸]N×·­3*–5ÄR;[9yœkÁ!á†ãªƒR³óx\õ̇8È;¨JÎB ø Nf#ô©Êð)—È#x`,ˆô² zVÕø¦S¨šâ<¨ãÂrOë0 “ŒaC'7QΊïr­ÒªÄÊY»Þ%6i%ræG“‰"6©jKTûÃ›KœCaRõEY”_ÓF+r‘¦5˛ÍÛ­º~#ÇÏÇ'sÕ#kû(#ãJ óm©õ0ÁچN…wKG‘& Õrª"AL6…Ìïé€7‘T䰂ORpMDqw=CR¨Wàïc[ŽìdÝÇ,ȪÁԘ  `&pôä(J°€î M¬ë¬òL€KŠ‡xFM`Å^»-P?,a4±r–NsjÒBE.ì(v£~‘­îÂs¡ÆÅ¥> +ðØJMTþÀÅ#ž-0ˆ8Ò¦.dhê–0Ã%jbÅðX¬e$nˆP‚èÏ(÷RÐTÒ{UÅ(šºÔO ®ã¼ƒgÝ ¤‘|Бo `”Z >cUJ«!`ûW2ÿ÷\'†…ÇüÙ"C]Ž˜ÙVWŠ¤«ÅäV•†Ü‹Ä©„뮐?^W. +­3OÈ«dୖpÒ.½ $;(è ÂBB%®¨èëÑfÛ×ñ.V„¢m¬æl,S-Ž]±ør$…c-¡mõِ®]°ƒKœt†Ábï:Ò7ŒN6úCeAR¨x Œ‹†q©f™òÌ,EYyPêC„0"pW8W^#R‡ù*¥U{€Õ! ¥Ñ\@âßÉF<ëu1‹´!õg»`qB¢c@övQ/¡‡}¡ +FÒ¾?íìG^8VtP5ÐhkÔe@)ˆEÅA]՟~/€ã¦Ø +©-¨ïFÝ \ƒw73€tŠÁSº¼ó[a\ï^Ù·º‹›¸´êQ|D*Nh‚¬Ä)>$z¬muìæ!#ÉH·!ª?¼À/èENÛ [N}(—WŽ³½Çà’ bJ‡òьÙà%6194q ½Ñû1Uœ¦@0;b®xð˜–Í2–ywڛÐæd˜¸çÅ4wEüAfHm6›™¨³aþԑ…‘¾Øڂ%,+GÖQu…ËD§oAPOn±Ü(‰|^²Õ]‚¡Ø­5içž7o”ü ò)’WiU0ÙGem§¡k9µ“gÐìj.ºõšÚšY-=¯œDüª!@Þë~ÈåøøÀ]” Ѝ  qmT#ó/,Õ.<$! GÞñ`õsúå(7›­ ?ª€µû.QB)V'ÏG/KWŠbEœâê=;ˆG„wªÜ…(‘…yØ CÃCC¨GHoqiI‡©åÉ ä +Žô>êÖ Ì9êÂé‹1KbŒð£•}ǯÁ<ÕÄ‚ûå.™gªY\šÅ´Ø3´Õ0¨%ì'™'#Ñ +)ßn’ ¥ÚŒ„o A¤jQ0Á#ÉS8ªƒV#u^]!ƒ®‚.‰¬Z´ÍchÙ¸h‘F]µÐ’Ðs@«¸r£#)ºå­ìCTRܳ²1J‡¬Õè‚âPàSkZ8wˆšÙà¢áâˆN3³$75*äÓüÚA$ ¨(wKÛÓªðbºpý¡ÐG˜kW‰4E‘C½W„,r8¨ªBÅub*á0+¨?¹€Â¾»H5é¦$nîUIˊ˰†…' ÚNÜRl*ù|ü£ò2ìEIå\ê˧/Ç¥]Þ±*@©ºQÉ72“Lß÷ÁËëÄ$p0G)æ`Z•4q@ɈC)ÏÈ6ýàQÌt 34•+o¼‰€¬mºÕUå»c+3\Š5O¨d+‡”rs»¸ Ku„ááaʶFøö8vM å…=ä¡õ&½sgà(¡¬CÆv°-@BBþ(Pˆæ± +ÏNq̌mh~ˆb_¡¹j¥œ´mL¥ù'Zƒ ÇÐú8ŸlA}ߋ•m¢IëÝsfþuÍú^¥.“[°¶ïµ‘‘% [¬UC!~šìÐZ7TøU`Š(=²yð}t½pdcñQáVq¢.Oqâu®eÜ XŽÉ‰åþ´1‰Z…Zbk .Ï>,-6ÕWt¾ôn  élçD¦s?ˆÞŽ½F©¬¶A”8ü«~7€âWBž5ÿÚ£còTôìÑ¡>òB´nQ̈́ ƒÞ.¤S";ÏÇ«_À3'ĵQ:8ÎhçŒA$Í ¼tÂR‹]da4Õ?¡l¢,ÊîL|_\_t5JÚ à"§$³~ƒ°F*$T•‰ö¨›­ôÆÙ¼& )bµí‘Þ8µBà8=®^Pz'®¹ª‰xÍ´Ýo#/ÒÒD¡³ÎQ+@äÐôÚ Ší ‹MMo0Ø·ìoUü½Áž*  +Ž]o;Å´ 2ƒ¿&ì@(é^õÑßóŽ¢ák›^¤ªù¡ K#‘-™rϝ½XÀvNQ5ÁÁ +Ì»zm•8NÝэð¨Æi˜ªIQ¢…›l`3W!•+:Ï!_ ²•Ê¶G.7”OçöCåÐ9)"€u$ø Ô®-åæB§‹CºâgК6BÖ×Ñ7³!¨b‡“b(ü®‹ 4_–`dD6n¤l°nhkQìÁØ«:Nß8#çà€(0Xb­@4a+ ;ä4£(§Zx:j4UèhZ¿SzÖòÈAŸ!¯pN‚%43ô M°"äí +½tV9ý—ÁuY…€¨Y´ÈNgò8 üQ˜àm#µ +ô ¼nÝ53žÓŸ€;aÔ.² +3ƒ!±dq© +c¤?Ü GUæ))—[Çx4*¥Ÿµñ4ֆø±Mh‰!›®¶ŸeU7&fè`$;õ2Yi³aGÉÆÄýo ½]`]ãÈ ‹ÁüNÝoŠó¤ ãэ®²òXuϺ¼gGt°d– …Êë¯81[x~Zݳ½èÓÀ[!ýj¬ç`8$C¬)œõØ|DøÐ*¸ÜÅÂ<4j\ 󖬣À¯j¤”*}Ù¿Š5ehÓ~cð„1O‚·zgY0:t‚ˏô•zãl¸Ö\™åDo,ÿnÏF¼¼³ *{ÎÅÆ,ñ{(,¬Wêkyy1d£ÝQœ”Ú™„ ÙŸˆ)Tf¤Si+•qþô¬l>4¸gEˆ)›C«Ê¢€ÁÕ*5¾žoÅÞêž Á•e̅U~_ª!ãLƒHa~ì!l¾§LOÅtðz­Í0Øëʦ}Hjhí-âµ9:{ +ëÓ9Á¢ø;ñdWà8é&å*oÊ ºaÅP€˜¢NñH)XL-öeq¢1I·–ˆ( Uv\¨ò° %ÁÄÚA¨8†” ü’e+H„CÃ~ +2Žá tÁ¥š×_èLƒOÀÒòÅMQ-EÆ-¤Úddâêk{¢ûˆþC‘ðaGŸ"ÙP#˜ö@)m\phC®„¬s£b%ÝUáï×°ê`ºP‡B4„×kÓ"ptʾx›ù}A§.?|•²Zš×õn˜ÆA3†›©—²“KQóFájUBç/ëÐU•¦›:Œ¬:ZK=l©×SE¨gîìjZŒ‹ÒÂåilÈ!.!Õ%î{&gilÙ쬷T•Œ+rçIõÍܞÀ®¬†9†JI1ZÙ »g˜ +X¡ÖèvÄ&›®ý¤¦EònÛZ+§YŒôµ 79iuqÀ‰K–d 9/‘E^mXº™]#i0Üp5öF3{@OýMyH•|YvÝõaè‰ ‹ÝŽ³è-§…ËœÂLÍÁZx>¶†v–ãÕ²3ÊŅÕ&X´ÕÐyÁß³"_·|Uåõ‚vã\§Õp)v%®°×ÑÐñPMë?"–ÜVÆòî\}˜øºˆÌ)ì“Tµ¯h]8’T¤Ãx›¸Üž„Ó.Ç>ðöęÅF:xñ/GÏ]äýÁ­=Ðj~‰»¡okµëC¯O¨]d…*ž‰„ ”Ú|BS… S­©Ðžœ!r7zûAeÆ*˹&IéLãÌ3Ô k“$Z1°ÊɘÅBÑÀœ7/ײœ{ø:#Aß.Œ7Ӏ:fðÛUìŽA»I¼¯‡~jK* ¼ðƒI Ðà•…b—–™¼¸d[ú O\‹žWâ#ðY˃ +¼ÞAÌçˆa•L˜ª©Â "ڏ’J=w‹Ø|P ÄqBì0•€âРͬ#Qî2ž,eøW +d?Ri]䐂äS@èb°o‡x¾¼]à †añ¢i`͂ÒØ>ãÔºj„>)•,^lŽ¾çåè¬oŒ²Ù3ë2ûvѼA¶ÈTñê%Ž ¨á‘oRE ˜Â‚¯ üÀ6 ǝ(ŒééäedññšÉ¨ ³VÙî2êaEÑTVc(!­$…&’Bö¤iEõF5+(vJ±µ±­ +Á·;©·«´Pèî©DñG›œŸÎ–³-¹Ã¥ti9ŠTzmÍiÁÜ*ÚÛ§nåe.-LO‚Š­zà óZfÊi™‚ÕÌÅ×i¼¼–ëÊq$ÄK}äõ¨<5òT5Å ×ýD¾´\•s.åÃs¢!­T;]Ÿ áOi~5¸ ©mYáЭÃ8œ@¨ 6®$1 +‘®³Ú5Ž4É©VÏúB±ß#^ªëÓ®†Üê`Ά÷R”~¢©èM*SÑ]¡ a¼ +L ¥Cˆ:†6Œc:ûW ˜Õ{îa¦ ã6¨B_Ó¦ÔÌïŒ œ „‘³?§`@ä¡@ÇÂÒmÒوÈKv\C‡&zM0^÷ç` .F-#¸e"' ߙ—-üìmFx¯bèÚS9ø“>ÛÉWŒ×JÏÓF B¡Ïˋþd~ÎvÄÉç×Æ}¿@iƒÔCqp§¤ˆe* í\³ažDp& +ƒÌª»*cäPϬCk 4oÅ©DisURpûÓËvÒ,aMÈÔ(:ͧ¤VŸz爪böXtﬢÿŠ°¿Ò§0¹ÀhZ)83/‚â¼Ë³£2’öáäÂ÷#W&ƒ‘ÙÊ &„ԫ䋨Zœ‹@äa€“¢ÞC‰ùôꙣ±]DFÃLšLNGB”8¢ºšl• Ê]4†¿ Ë½êΆ†MÖÀ‚Ÿoª&s:º÷…xÒgƒ4Z…lLm=°Ä€7Ý`éœAW¹ìuV4¦³bKu:Èé e)»š¿ü4ŒmèÙð¬+¬³®cƒ¬—§ü •Edg«¨‰ g© ýMÔ­¸{֖^ú½Â­`Æd»„Ú†(ŠZæùvTßAW¡ã¯‰ÕÀñô;§«âæw3:í•a‰{Ё®ÔéWBÕ»T¹UsŽ‘·Nj\Ó±êÅGֆ%šHÕÄuÀ×õöV79ÉÚ=7äL¥ßN”סÂ0ä¤ÇårNØÏòxÐÎDRÕå~¨y–ùÆ Ûe‡æÀ€¹¡¬É<ßü¹x¼!ç‚LšÈf#Æ®q™T›­FÄFÖHÑؙˆ»3¿^q(ÕJ×X=ÌV‚›EiY$5ªB©©‡Á1Ë:@a©Ü)ã•!~ÁñÁÀ½¨nF·¹fÍú¬XU*D¢)VµCµ¢Wá gš¤²ˆr©¹ ú«"‹bAš+’®M’ a*硦ĪžÃ.Ջ1²¢…u®²Û³.pJ&ßÙ̂AÙE­V„ŠQcÛ3NqB™Dµ¨ærD”kLa«1DåÁµ³°/DV¦×FOª«…¢L³¤µV㔠øÉå?#ë©gÈF€Øéj‰–³³œ"™N/bÙ² +žlÀ{õæS…®D¬‚Žœ)BôV«è›žV¥ÚÂe˜Oó³#N1´$V”ùQh­JgŒDÕº¾—XIA曋†ŒÎcx÷Ú°pÀéèÂM&HŠñ ¶tÃÖ>ՑÍy±Ò +þ.è[ò…*Ø~C˜˜Ýh0[ã›H“ ¬BºYµO:¿B¦V0§E\r&D¼¤Ù%Wʾ hìlúb)˜6z Еé’h\Ř{%×\^F¯ÐU˜Æ×F'£<—ä&늚«d àQà?%È¢>”ԁ§ðû¼[I·'ڀJ㔖Iƒv^GŠÂr +Q eP\0˜«að½gªÕÙ=©éDŽ%%ÄLÒTtL@’g·ÐÀÌñ³âî{'™ÎvşŽf…!n‡>\<ò4äH•\uN+˜©‹@aª!AöqF\©Ú„JŠgc§‘RÈ:¼Ò*ßqLŽPpDZ^TP€‹N.¯Àd6hUh7\‘DŒ”ÑÙIæ»_èñ«i¼³‰ኴ羪£¶ ï«à2¿Ø8uŸ/(&P‹UçÆüdáôÑߧrLp¥Ç™âÈ×eµRèە’×W+—ѳ††«zðd¢Ì$€¡Ž¸@"> +•UÉ/ngg2=^£À)qÎü\¬ +h‹ž7øÌz8¢#njuÔ~`X.z§¯©sAè\±#kûE`¿%$І’“šYì ¦E/ƒ òe¤'6•§P¹•ÚÃtö°%„]ç î²&(ÖézŒý ²’A1^IMUŠN„ RQÙÕА™.ú]xÕú²×G“VÂAg_(æGD¹pæ5MÎ>4?òϗüëYg/i¡³wÊaA u%›„Ü›4Ý»V0;’zMqÖêÍޖ¾Œ·Öè¿0h–­•G"–-dW¨ °ýén +-O±{:x”=š™Ä ÷éîLÏ1mΡØ£(‹‘͆ǜ¸Ó†:‡Ê.]ŒyÚåƒ/”RŽŠDÒU«(£M0‹ 4Q…"…²ëž®f¨YU„© ¬¨üe,póI±kçiõƒn!lâ礊!;ÁGÒò¨Å ÜÙø”ºBÈ …Viðý&\˜‚Ý•+Îi¡ãc,)ª]çg™û£il‰ÎF<RúÒîg”‹j:u%¥s¤ÖLدtD5yŽ WÎòÝX•#?}ù:›X7ÆåXÒÉ4»|¢ƒcÐ<·ƒuCjȃ€Lƾ•Ê½ÈJI”È5#ºù•P6Þp8ÌÒ¾dž´DO©n˜[_ÈGº^§ò^"zææŽý }¬Ìd”ÿ ˜u„·a>SòÚò‚æ¡hfga©k%ÊÌnåQC^UùÑ«Q¾MzX˜íÔÙtŠŒOÖ¿Õ]¤-)ƒÙe%ÿÊFdšk¯J’)d ©ÅfTQœaìP-~z² š=2€•è‹焺¢0“Nª‰š[”âÏ!@+ÿ¥xë,t$’Jd !橨I:òdKž¡uqÁ?dLÌ1`˜i±g(Ç:#Ò:Ô/¬ÍQ´Á¿Ç {ÊW„Õî)qs,Ü0{zæÔîµ:¸»ÉQ{æœÉC8sՉÆn'»Á»å£Ü qp“õ¡_€N¬­jÚǚx¦ÜBú\®_L¦·Zkðt?¸PjvæsÛυRs²^g5zÏoÜÑzÁFc’ŽÆR&¥në|f”SıŸ1„ F‚‰@ €ô¨Ì™Þt&ÓkE%¡pˆSG K‡5 ê$S¨} ªH«ÖN·0„YŽ².!û÷/üZ•]õ­ÓÜ p­Ó„!ÃÚð’o.Qñ£¶4Ér$ŽFËÃNŸŽ›¢Fµ²ä~ë¥S'顚•: ™V¤ Òh‡©±y¼É'däŸÑ.8ñuÍ?kq6ç—n”T¦”ë Iq+ñK «h”ZÑrŒ¿P§¨Žbx@—³–ic¶þéñìcHKmCy«îh®©Ù"p&è=¢wTnf—=䂉:­ÑN¤•¢ìRÂý˜¨»ñº´Ðž¬Èÿ¿tˆ¢(§nSZ•œš‰…ùáͪÆQ«Âø®/Û`.§lû¤mo$çzL¡eÏy¥°£Ú— /¡È&C˜­&¤¼(y’ÍBb±#‹•+Ö ++C§n#Ðç´3ÍU…L&=Óm›´—ȑ²< æJlÏd)7=`°‘Rüg+dœ¦F&"kB#’€fcYUɞáÔÄØÊÓsÓøàETYu]f¬Œõ\£%,†ßp`ðšÉàAª™Áð®™Îšãf"« Ufêû`\Šª™yôƒ@–SÉB¨B° «`}V4mlF豆Oz©ÔñÇÔ:SÙ¡0‹«!Š?)í¼ï +°M‘ÃÕ¼.¨0˜¨S:êuéõó¸«N¥9s6$Gø¤, ®QwˆPÝ4‘ARÀ Û)°l{9™4²:"âmtt„¶´élðŠrè1lÜךŽØfµ;çäÔØÿl ·Óá?æYçì˜L–J¥\wÊÅ8™0ª¯:êJ!K[p! ]X˜…“táGu¦ }û­‰)-cT „˜MáNÐ4'è6# +w܉"·1‚wp!nb}}™C© Køa$;1`%œ¯£h#P 7ZãDm¼É;àURVo¸DÆH‚ ¡ïAÃ`J +RTF"v£Ön` ΑÙ,\;cR qÎ¥¼S–Ó0ǕäXOG.˜8XËQ™º _£”ŸA:Ì}èùÙ|[Ðà2yQ2³‚…†t-žô=¿uÕ3ŒqÔÒú.6ek´Ã ê6º„ÁiSÏ$ʝr„j¥«É* ‰g€©Üß ²ZO%Ê×®Ñ $ 7ÉEǠǃϒMÛx²UÙ&t9¬±’Ëæ®TÖɨÎD7XOh³Ü{‹jà‚çIF˜±€cáY™4ƒ(¶NÅ#Ñä‘ìÊQV$;µtÂ?õoÁv¸¿oŠ¤ø9Ù¿)ô«†.†ÆtTºu¼2hr¡Ãb­—˜“ÌTìYF+‡ÂXÝ/8‡yïlÈ b,Ó`ÜJó.“â¶ÈáHõܳ·Ì$¤o£ºwu6äŸ=TD Ô×E¿Ämã]†€„KŠ/s<PË!nãò„Œ"*Ѭn˜Ñ3â{¾–]ׇU£0`K¡·­«9ZSÞò·מêÆà1˜§²{\5M*z-BÙ«KI¯BÉ=_ÊÌ1â]bXܚœ†Ø2ìqb=»ˆ|R§'aEVRCæF….Á“‰ ¬ÒÕ g4¤=ë ½ð#Z¡ûó%\=Üq M«Ñ·?|õAþNÒ%ûѶ +Eªn”A’äÃ[®Ø 8C¾F®"Ÿ¬vJf¢¿×‚Gd´c\“—^xÕ£€Ž84xžÆÎٕ’sUÀ"7Äi…V€ZOd×®ìYB%ž–„—•Á¼­ÆÊTR]@ýú3h¨hUg(lBqùL(Ö:ŸE'ÜIØ7([’_"ÔÔtòÐ:‡a躱Æ金6Ùý5ñZV0$£ç&¢w¡®ªg;0—Š5zZR䵩\¯äãÅj"ïwF‘ÆŒÀ@`e™ÁœºÈ~ÀFèxŒ k}\p…õ‘½IŒl®T«cڈ HSl[n”,–+fQX—ª `ße ¿®iŒ&#rOöÑ ¶Ê’Àn\ÓV¥èøç"øiñë×ìߙtƒãI=ØØP3i–8óñüeÐ_îì>þ{ûþ7Û[Çg.^~pp{íÊáÓ£Çkmîo>Ú>\»}ø`ûð•þۚþxuswwçÑáæ“Ç;[~òӃƒÝKkõړã××nÿusúùô£¯¬mL],Ÿoðù•G3e7v7ôyuýŒGÙÅóú¿{ðtÿÁöÍ.úÓ˜–óöþÍãÇ+OßÙÞßÚÙ]ÛXûôñÎ~<Ê.žýüÕǛ‡[ó”<û©+›ìbû0œž9Þ>ÜÆ÷÷7÷¶÷7w×®`-/½²öºvÇ´VöÆϼǞ3‡Ó^š÷ÊôK5méßnmÒë&­hú?“LýÐ8ÿ¡¯Íe_ðkóôï8ý_šþ…_ʽR¾µJ‰ÿ[üû³o»ú²íš^qäÿýk¿´,,¾´ânLúWÖÊVÿ‚ïíOLr?ýû'ùçÜùÏ:¶Ó¸®lâÈrÿ_ZûlçòŸ¸Yÿ¶ aå3¬è‚¼nGA<"ñ¿|)Ÿ3ҐCÏëZ3C¸´Æ…ÚՈV$é‰aÕÏ̋ åç\÷çIái¼§Äðs§¶Vc{º‘Ûà8^{¦ Vmíøž§MÓiB^x·üä õ—iáîÿ}wûèÌ¥÷þ¶Ï_&Åæâå}8..}<~íµ3—.OJÏ_·ã¯—®ì=Á¹½±³;ÍžŸ6ßÎþšPë+õ%?òÚ³>tïxsëÛþЕͣ­å'¾ÝþÁÔüy÷ö¡Ÿ:YêlÓ;ßÝÞÂz>Àõ˜_míE¹­^º¶ýpí͵3kÝÀáóæ¿uíÍ3k—îl?ã]®ì?xºsüœ×øâõ~xÖ~腧¯LÛ{íâgGÛ×ÿº½ûÁ ˜“öOÏBéä9sðo¥ÓxíðàÉڽǛþö +1¿ÕEüMz}sçÉ´;u +¦¶½O/®|üÒ§;Ç»?º&ÙssÿxíâÖÑáF×.ÝݞNüÅ¿n£¹enº¿ûôpå™Ç‡ß£aº-Ýò`óðÛW–Óüds‡Ÿ‰ï¹¿»Ï Ÿ®‹øÌÁ“Í­g¬Áí3¸Iঀi²ä+þ ~t@ +#íÙË´ùÂ,Ÿxne͎¶v_pË^ÙÝÞðo½Küüê&«tÀóHç?w{¹tý··žbü?û,á¶6™ã¿B÷÷éÉã0=Ä¿âÏ=ÓCêcq~¢„,[ûÞ´M§sâj_»ôÙþÎÖÁƒíp_Û9z²»ùwýúʳÄ,m»¸ûRÓÃ#I°=ø«/FÓÝöºG6íüú¹Œ¶pVÃéýSýˆ¨®ÊûmmîÆpߛîÖ»ÓÞX;ùª?¸D—–óôm=÷œEÿ«Ó™pk÷`ëÛ¿ím/ÿöٓ£Ûצ­ºWvw¾/±„"YîLÂîàë¶»üÀåß<=:†âòÛMôÜDÿ)÷ã/ð/“ríoRrÈC@×]µJ0ÀD¼Ý¸ÐCöõ#ü)„Ý¿I¶ß$ÛÿaÉÖý&Ù~aÉf—E²¦VIA³\Q³†ðîXWÝsåˆÐm¿‰¶ßDÛB´õ¿‰¶ÿ +ÑVpÖü&Ýþ»¤Û퟼Aþ ÷Üo2Ñ2qø5ÈÄè›þ‹ƒ¿~ðÏ b~ŽEÿÖºþƒ×ü¿_8^ÛÖ8ºq†k<„€þ”ê_ÊLøÕf^üxÞÅp*ï¢úñ¼‹îò.Šœí,…;ÉÛEnÂÒm»çœsZâÿÜ\Œ_Bh¾·û«”–ÿ&AáIWêã¿òøÿ,6ŒÅ퇏¶‘áøø” Ðßð§ç +Š•¿˜ ¨›rb)'ˇú›ýã'ø½<°·»³÷‚èßµÄ?iE¯Ü/›âÊãé5/Fé£ÃÍ;ÛÓ;Ý+‹]“Êѽòhúä•+ÿ„~«å½ñôûïÿ¾öÑæÑ·§V—ºþðáöÖñs—÷Æö´°˜Ë[Ú¦ð»Óû==úé·×ÿI½æ¿ÿ^¸·u¸sÿþî¯Ñ¤ý?¹ãþcœ`ÐÞ²scÉÀP#vt8å† Ú*yÿÒû÷™²669fãt-þú\Y»8#/&lŸ.+ò÷òþ£Ý핖ëmߞtñÝÍ'¿ß<ܙ£=¯§qPi«œøžçüQÝÙß>:òî?p¾óàXaª9ÿz1¢Ÿ~Qü»6mƒ²Ý…ôÕ0JBëÐMÿô¿E‡þ¹‹âñÎáÁç[w~»*~Þ«â?Iâÿj±Ïô¬r\»zp¸¿}xtJÐó¯Ï•ò'>û¾‰ÌÃU«ÿ£ D`b 'ÄtÂH¬~½F"Xq´ES”=ŒÅ_5@C”Kü›Ý…ÿÉ;£™•‡ÿÄm‘¬ª 6ÒëÈm1ZĽÞ7²´Ý¿xû÷ûŽÓ ßñ¢Ho®Û†“äÅc?Á…œN¹sûéCþÍõð"埦Öͧ»Ç_-Ê{;{Ov‹BùßíÝrÑJå‡ýÎ$‡oÂÊîëûæºî-¿³¹»}|¼Í÷¹sÿÅKN/þéîôñ£ãCZv_½Â©øÃ÷gN¶Ÿ¹³uz®.~þxçx[û'ÏÉ´ì“Vî®8Ø@ŽS-psÜÍ7* ƆĂuN®~ôŇkw·D?>å¯^«–õ‰å3_lï"‚¡ ,Þ§S5?á‰XVüdK_ïno”ª”Dêñ*cÆ?ó‡¯þ}3>;¿<¾ +óï3;D*tÏâaŒ´^ŒæÊîÓX!p wírZ£…ÓÕL@ìÄXKm>|‚{©ÁÁǤxâ•©"bêÇÙÙ[U»öÑ[@ùâ­1­}8ý«ìJð\»vÔsMIÖ®úJSW#zÚ©§¹#®—6? + Iéjª¹~kîdàpÌÓÛÆå<PÛÔc¬FÖJµØì±ExÍgtYÆ1Ì>…1V‘kז7ž{œ¾{õE'Â|vŽci†0)‡E+®±e ¢¿Õ®æ×-îµ!ƒO±úª“;[}Ý2qs—Þsóþš£é~Ã\xxÏ‰³t °äÞìýSs'¹¯¾}f_˜æ†‚H#`·\ 0¦¯Ö;«¯A›·t›wÞº96l™ÿÓ N›jõôtŠNG®nفy~Û':¥ˆ}ÑÛ¥¼r¿Ü.}ù"6›6:ÄÆ uy†/ܬtßZo,œï›˜ÚA2ÁƒbWØÄ+ËàomŠÙ4‹×j~7M!µŠ¨Ôbðœ-;U|¹Iι¥È”€,ë‘É÷°ˆJ,êüÒw9†T>/]Å×eäeWw5:«Û“{9Ià‡ўã]ªØL­$Ïb™Õ÷ÊÁ³e1OEò`ç ýýíR¶é™]fMOµ^I‡ &¦"®ô¬WR—yen—g&S(ÆÙàc+;>¶GÙ²yu¡J×íª¤ åÁ‹S¯ª qxü}‹Ëk^¯Èбq5óþ,´‡®Øm‹xñ=6+sYÞ6´‡†²ˆ;Õ§+·OÜ¡M6¦Ž µiã­Û²î~¶l€.nû’ŸÔD:SE^ +Ž¶\]]ZnÖ"®ËÀfÕ§t£ŽaÉç®1»Æ.hÊ[æÎu1Ær úØ´ø_³”œã¦ôZæ¸H\þÃr­Ê®ëB¨4qãfm2oÛ2ýʮͱyÊT EªÇÀÛ¢qÄÀ½‹Á©Vf9‡€.30Äðs ¿ˆÂâgZQf¸5º6nö]71•³ÿ!d`˕ˍ:Ütý|õµéä¶+×o¹hºSùqEýOË«¡-}sBzu}å>Ò&níìooNµ³&ªNšxÆóîk5I +“ÕÿÂݞ~þùC¬âëâu{úyt{ñóÍ¿n8Ú++èß?-zûjíÉÉO°“;»ßn®];8þIþ”4t^{xìâËzûãëk øܽþï™S­¡×·ú¾òw€ ŸþT´êÖ¾H[y…nÓÜ<}Ç֝G+ +yìÜØ°Ëk¹‡X«OÞjEgëW.žÐËg¼?¥’Ïx:åp°‡b•(¤ûOé€ÿp<=$â)C‰ +K\’‹ÎB·œƒ¤+ZyGñz²³zžÿ4ÿ؅ZPì¿ú‰qUéĸ~jð6ÆE…wEߍ TÈÊä!i|Ñ:,m˜!Þp1¬i;NÇóïG[›pmi®=:s÷K|×ô˜ÂØ:–‰™Ú¦MÈÆa^Ì韬Æ>4Žj슌ÖïEfw‹ïhf¥~þŽb„ ‹ï¨gkgþŽÙjçëÚ¹s¥8­Â7õS  oí/}x‹4 g›ž,šYu@¯D”O9ÔØû?¸X%ýIÐÐèæÿÁuõt{íÊÎ!P¯î<Åÿ¿; ìÆ4L¢MòòÛ´ ŽŽðÈÁ¦å•“€Óêõù£óL];ØzŠRÜk›Ç›@µŽß h½â¡ÅïøèÖǶŸùÇ7×.þïÞîþôçIRO³üôx›±FbeO[ößÒÅÏÐÿâ©iÙwn›¶#Mã¯øÏñߟlë¯_Ú?úú¯›‡Go.è?–þuN4=‹ö£ç<‡O=æ‘­üö:;÷wöL¯Z½ÀäL“xoûøcNÏÏÐòé×~ÙwÜ?Øސ—ï‡Úúí/ònñäÏ´üÿäÛW?øö/´®;›“ì}‘ÿ£+ùŸtÐßøë u<ú ïb¼ÞÖӣヽ_V’ýëöáG›ˆàáΛDNjnÇù¹˜Æò+ÊÃ)=zø·_ñmü ƒ£Ý­ÿtY\ò5ž»´/´¬¿´ÌÝAÓTÿØËüýE^æï¿ôËT v&søGÞæoJêþñ7ú[dÿ¢oðX£ÇÛ;¿ˆ/OþÂï NÏ{¡ûǓ*pkûáñíÝGDÑúÑW;ý™_ÁµOywïàéáÖö¤0þâ÷þt;ýÒCØÛ>Þ|0©Aÿì8ÆrçØïð"»kñ0?ü§¶ì<Ý[»»}t°ûÔH'¡Þ.߬ªµâݘô›§OH®s¼½¿}¸vçpÙ¤ +òÄÌ¥PüÉæƒåòÑÑÙcäÊi:zrp|â©ÍÝïöœ"‹ðÁ“×ÕÖDã2öø¦—o®]~z|°vwóèxûpçûí]^¾9®=Ù|2½ÀÑÎÞÓÝÅh[›žØ<<¾°yø`m ìg¿ßê¼·½ûþæñ4[·¶6w1+Güû³kyö&€ãn^[>¹üó§Ð+ñ­«üöòÍ;›‡Ó7L>º¾wûÁÃƒ‡;»ÛnÿýĜ®<ŠDäiюÊ×ÏêðóÇ;[Ou˜ŠÚ°òð½§÷§Mpã`ÿøè.¦òGFpçÚ bzòþÎîαŸ-É ïíÜßܽ»ýäéî<Ⱦ-ëR¥µ‡eÿr7þº½u|p¸6}ns뤀>ñ¼ýöá_·×þº}ø¾½£S»cåOQ`µv¼ý¿'·&Gœªµémo¯ÝG¥Kæq´syØ´©>Ú>z\ö%7Þâüý`÷ßîl}; fí‘B)åD̝ß~züdzà‡»ïZ°~>o›¯UÓøC¾Ô‹ÇŽ7÷žlN¢këïÓvLg'֏vùˆYyZ躩‡ç?[/¾þGý)݆CèG[ž¬VâNlœO§°výÁÎñær§y‡ž˜·6÷=Ý|´½vçàI,]³‚*î'O7ÑçÚ­í¿nïþðNÞÚÝy2 &ùÿNƒ~4­ðÑ"¶òöÅ"»´H >!âNæŸÜ×ïÜîc¯Ÿ–R-炏œ8kËÖk“¸Ž>î-Göã#á·\šµ¢KßÜ}ZGœÃ“wèÉǞ€æqZ˜íÕ1Ÿ|ìè۝'÷'¹òí+?ø¥‡Ózm‹âj¾‡¸oýààþÍý‡k³$OϛƒgӞ8=eØrO6÷cÿäªi–•'-à×|éÊNÌöå{WoÞÚkÛÐðÇõõõëOÇ;\ùzý‹·ßÎ×.Ý~|óÆæ…÷®Ü{øѹ[ù͏××?Oë/5ïß}÷Ûï;7>úòûáöOßxé½[O¾ÿþûõõWþrm}ýw/Ÿ]_¿øÁÙ3†öÖõÛßÏÿLß²^¿{øÉÍjúáü!~ýôrÿÕ£Ýé‡ ŸLÿ9;¼wåÝí÷8ž—ãïí»¿ÿê»W¦^~™¿^ÿËÖÍðë›üõJÞ|¿ÞÖßþqë üºÅ_/Ÿä'ÓÏ¢ïÿ¹<ÜùæáôÓ+oá×OÏ\xïå×/¿6ýü;}ýêÎѧ—ð+Ú^{ýîÆÑôÃFÅ¿Þ¸º}ø~ý ¿n\ÿËÛß]Ä›ÓÆöJýøþ!廌ÓȺvoþû«¿zëûîÝ“Ç×ïšÎÞøŸkO/¿žo½ó»|åÒƝ˟~wtáÆõ+¿«§¹¾øÕõûçßøÓµ‡/¿áڇOóŸ9eœÌ|æ'ÿÕËçÖ××næêkçÿôFúËï«»ßÿғó‡ïvÝ;ºO7¾øc}}}ãÊ¥Ç{o¿ëqæþË%Æâ}öЋ÷»oÿ¨ÆÅ_ÏNSsî,æùÕ¯Ù8}zjþ`z͗?üóÔüíN<{ö ¬Îí¯§¿Ü¼;¶çn¹òɽw†üåǯWï]ùâw/ß}ðÎKW®_:×`<_ôݟ_½öö·o]éà¿{ïʗÝ_®|ûƃ×Þý+‹­4÷z{Úgèwñú^úö»Ë{žÞøŸ7ow݇[¿¿ºóÖûo¼zý£[ջ߽³Õ¿zý֍»|þéÖ÷ß_úöƒ×_}ûø°÷ íðÆå{¯½»uçуã3ú½/ß~ýÚöÑ;ýõ?>¼qåÝ7>þæÛK>|µé÷þT}vb4½yóèýÛ×ï§×ž^þð‹s§•üæÕ+ã'ºvóÁ͗Ï\¸²ûîn¾²Û^¸ß÷—Žæˇ[7«W¿¿Âñ8ûÉÓ7ß:¸|ïéúãW¯\¯¾w¹:ÜxõÝ«/ß¿xÿ›õõkŸ7Ӟ=¼º¾þÎÇçY¯Õ+¿ûêìú+ÿá»õß½1þŽ{œë:=á{ñ+üvîÆŃ!}ß}¾±ûê»G¯<ð§ ìíõ—ÖϾôÕëç^»öñúùúÕûëúéè¾ôÖívÚû/¿‘Þ[¿øÎîŸÖ_¹~ï`ýw¾ùúú«Ÿœ½²þÚïÿüûõ/¯³þúýWÖ/=Úyk=íÝùd½:ê·×ó¹ãóëùégÝzûÒÿ|°Þ½vîÏë}õõáúðîGy}¼Ñ¼¿þÆgë^s ü~ëo½ôy¿þöÛÜ^ç÷o=Zw¿zuýÊ¿»¶~õOç¾^¿þÒáùõw¾{wýý O¾\¿yûɹõ7ž^^¿µyáëõßyõ•õ;/u7×?¹ygýÞ͏šõÏÒ>[ÿýÓoήÿáàµëëüú­ÇÓ·|ù‡Ïúõ?²ûåú_>m_[¿ÿû»÷ÖüáÉùõ‡Þ¾µþø`óxýۗÒûë{o|ñÝúÁí×ß[ÿnëóï֏_«ß?»~sóéÙsO®|tö¥+ç^:{ññ>;ûêÕwÒٍ£ 9›>Ú|ól®>Ú;sálûÍœ>~ùâÙ7ßØÿòìÛ/oþÏÙw¿øîìÕÇwñ盳7¿º¹{ö֗ïß>{ûÁGÍÙ»»ŸìŸýìø÷Ÿžý"Mý|yy÷ìÙ¯ï­}öþÞôÍß¼YŸÝùlê`ïܓ¯Î>¹3ܜ¾åøåϺsgïž?÷RóÎãs¯ìÜÿüÜƽîýsUþb8×¾”_=7L&ܹÿù˛Ͻ{÷›?ž»öñ·Ï½/Ý8wëóoß:wçËOšsŸ~óÖƹ/νòò¹¯Æ'gÏmN†À¹íG÷öÎ}Sø͙ çöï^}|îè¥ËÎŸ½ýÎÃó/¿võÑùWÿüÞãóéÍ¿9ß®¶w~üòëïοýá“õóW¯U/Ÿ?_Þ8ÿÑ«Ÿ·çï¾vôÖùÏ_ã½ó_^úýó›oœûÓù‡}øøü·9zzþÉñ{¯_Xóé[g.\xéߺðêӗ¿¼P}¼¹¡;¾üÿÙûÿDŽd$@aw±Ï>§s:! ‘$˜!£€$¢ÊePBÈw¾÷~÷ÞûÏÕ=y˜DØ[ÙÛåk3t¬®þvuU·×1¿9•p$©Û=Gî~çÞ±±¾àvìE}KŽÂxëØqñTyqÜ<>D—Wێúíõó”ý¦šrVnv¦|SÏõ©Pt|njv›>ZzXvÙS¹ÈáúÔÆq¥:µ?5½0u²“+M©‡ÐÔ]9|:UMù¦^gÜGΩæьs¦ì?v†Ï}ι¹3gr½r®níÝ8·Ï‹Î£WÝyñz¿á¼¼ÎçüꥳUYZýçL,Ø]¾Ûø±+Ìºc-W&;wìÚ­èÚ¯îM¹ÎΊ׮›µzÞõ”¤"®Vr}ÜíL–¯Ýþ”wÛÍçîŋ¦Ï{I7Ý۾ʍûx-u侪Ù×݉}ÈÅýò {é¯Ç7u:ቜ§_<‹+¡Šg%8YöìLՊžB­|áltæ©<œŸzZµËS¯Û}wî Äj—Þ¹•ñ’7}EÝz7§ÓOÞ£ã†·8Þtx7b>ok|7jsL».'’ӁìêæôüLít:ÓÌ>Lo]7'¦ çÛÁéë«`fú¹T9š¯îWff ïLtvfyfyóåhfýé¶6s> Î\mÌT|»÷3¯w'”Ï›<ÝðE¦JO¾¥û:äâ[?tùóó“¾âúÁŠïi­úä_ ÎûgvwKþØÍD؟z]¹ðoͶ‚þ“ƒµ ?bØÿ²}Q¢\®åy*x0Q¡ÃÅ,µÖڞ ïÒGTi'¦ª/íXuåmšÞtûé…=÷=½Z¤6èƒZ4@—èT®®l/ˁÀ‚ÓHÔ2OõÔE!pìñå7å½hà%?á ºÓ{Õ`$ä¾ +¦ÂWÁíhr-xŸ\ +>æïb¡ñ£-Êæù[)oha>:Z+xÇCǞÉV¨\˜l†šÁÉfØ[ñ´Âñ£èx8—J9Âþ-wøzæŽ +¿L{¢'¹‰ÑW+‘lÒ¿ÙßÝ»Œ”ž\O‘—xa*ê9 E¢q÷Mæ³ÜÅúqô0¨Do5O´yƒæ–­£ØüÊJ=¶žJ†b'‰¹ÍØÃúÒc|bk)”×·ãÉ©Ãz|'s?¿*OÂxÍOÏz +;³³Ùq;è¬ÅÜl¡|_Ÿ}Ø_HÛs“ëOµ¹P*—K§Í¹ýôy~îæhÍ9×*RGó”k"<¿”z|˜ß¾¿^/ÆÎÜó/·'W 3‹…ÔBÂsã^Ø,Þ_/\N®/Ô×ÂÁÄtn½‘XH—ΛëžÕÄåÉô~¢þPŸZœ™IU›óÅ­z~{±˜N/6êÅø’+ç_ZŽK{.‡}éæ¹R_¶_œW–ƒÅӇåÌMánùèîèvùÑY¼O:ç+ÉøÎësr½N5’ÉÜD²Þ¸öÚ)ߦ'˜Z䩽Vk-u[ʦ'_oÒÑ­ÍfzmËçKŸÝ/§ëW{ÿTâ!“Œyܙƒ3ûræÁó\È:›Ù9ÿ}<»Y®dK[­fÎ>ë^ȅgb¹U÷&ä’;w\oä^¼îÆ +_O­¤·••ãûLbåÙót·:½¿žX]v»WN¯S«ñ\cÍýØ\K”'¼k{û÷çk÷‡åĺkë´¹¾prq¸¾[.ÆA_>´ò®X£_¸ $mŽüžsٓ¿?<}ÜpÓöÍÄC2µ±ðØxLÎÙ7½Ñ»ûÍåHætó(<±¹ù<–Þòmdç¶ÒT`ëtüuzë%Sqnî‹Û«‹g¯Û—­‹ÖŽýüöu'–­ïlÅ]›cçÖqïºüÛÔîbð1º{ó/î>o¬íùËS{9ÿniïbË]ß·Ÿy÷cû‹óûÛ³®­ý»ÖméÀs}8q<]Ÿ=8Ù[Ú9hìÏUà ôáÆ}bãðv*óxäNî…lŽ£å»Ûƒ£“˜cü¨q›ÈGVΏ·¼®¹ã»ÊÆuÁ{5-¤ÏJ…óÓ@ìÄ^|¸=™½Ï/žìOÏÖNž3îü)}Ûôœ®ï.No.J‰3÷µý,åx89;+ÕçösߔÍq>·9[:?ØÙ˟×öŸ¢¡bdâbË~r{ñõ\ú2—«.:zy}|ï½r‡V_¯RUºruqÚº.N®–Ί‹K‡Gœ¥í½âëêöNinw{»txs¸]jxJ»×±ÍÖ¡Íq½×¤O¯kë«Å›ÈôÝãÍÎ5Õ¸y>ÍgvbO…Wºü<~üœx^šß{~¾dתNWÜYÍ8é³êµŸZ¨MG}­ÚÚJð¨v_JÌ×ÔÖD}{ïòª^óÚ×lŽ—ØU"ür´Zo؃¾rcÉw~ظôDsM·ã6þï¿€VX¯¦±å݀…@iMÖäÛéì%vKYCYËÜÒ¬ôӍZµv}ߨ=ãK=§¹•M+k䈪–³«Ý/K"€’`,}Èt\m±Í"ၰ^Ņ‚¯>ïÊË¥Úoœ-3(*ý–9=" U_n´þQkT’xÇJdé4šm›U²£lÑY7¿Û¯É¬oÚÝ+ê¤õ‡êfÏ´Ì Ö`éï Y†Cš-ŒÊ­Þ¯Zə6—¯µR±•/þŽÉї%$ÉêYFU~j܂¯ôëSb,ó«Õë§WÔ=Ûµ§‡ëßõ§2nÄ?7¶/¦Ô‚—ÙF¤öА¶b'šDI ’Ú‘.A‡W< \Wo mn8;¦Vs²J´ŠlŸ²^ˆt {…"‹64äãÃØæFGê`Wð$00ª­ç°VEQÏ VÝ)I©#UڄùUò©\¾ÕDW '‹¦ÑtE«UpÞ.-Ú(T}YØ.Ä»…š…Ö݇SÍe¿ñð¼QlTؚºöïaDŽðûûòØ Ù0†b`\4Çþq_®Ž5‹¿¡AR¬Ž­>ZAÇo€N£ØD_3'õ@òü®œo젉“.Mì÷ÚëX´ÙHi,HeÍ$w‡zd4=™ñ?­B㏵j(‰ëòØC ½\{*þŽv‹õ: 4f4_¯ïQñV«éróá®*$ÃäV…þ}…ÒÕn…ìšc¯Õ +:°ÅgLE@Ò׍‡ºdRµéY5¸/Ú0ÔÿÑnùNÔ]ú‚)õ{¦Êï"µ¬¡Ú ÊÐg¸ª5®__ ¬U#NXÊƆ1ÞR*7ÐOöÅIãž)ÕrÃÀh–NGB-´UV-R]g°_D-m¬köZÅêM±ÁM:õ–9è‹Uº—†=î¨1¿Õ¯ÙeÐ áÜQ¹tøPþG/Ó¸~FjµØ*ïß¿>—ªÅ‡§¦~µaP×ëem$,š=ªýW9ô)҅Fa¦Šufý›n]§bÕ,:dJ£Ð~pùZ*^°¶„¬˜–âŸZT¢ ¯a,ñ'ó(o1C՟š-üCû7¬¢¿[äÎVUá]ÊW|j]?5¬fÒy=è»m”_^uPèqI ‘ë¢ýl½¢:(:͝6ôv@ZQƒo‡:jDZ}]Ⱦ|®øT!â$Qˉ\ê9aNÙÒ— H\ô2ºÆл%ˇ=OK/£€áŒ‚>ºÓ/?râ»}­^«}yc‰ÄŒ¯>ŒK/3JT½@É€AA2&¤AéÛz…¡;Ÿ’[¨ZÒÒ08‚U3hL@Er£'bÒA£ßñm•ÔLý¡yýü;çÃã£׉âæ†Ep“Ç Ú"L‹úF ŒH*É¿©' iÕLZ¢ t5”}Q½—´…Þ4Oê”ïsÑØ78kŒ‰H #¡;i@Z&­±)‰–½í‹êH+-í!ƒjÍдµŠU2ֆ’1©S ñ»Úƒ,  Uš¯ÖQ´ñWrñEh½¶“w¢æ–µé ÀT8.È£jìò¸Z­Œ¡ƒÆ$~ë‚ï}µ&x_#Ã2•×šœÏ¦ŠV’€½!5ÂÚüKSÈ"Ÿb-ò»b‹¼Øµ¿Êý‡ŒE:)±H‹}¹™·ù3`Iʚðe&IýÚ0>²Ց¸y3ù¢“ŒÐmõ8_쑬`7–9êª7Bû»Š¹â¶b^3ÜXÌëú­%­*ó+ýºvá)\¯7|L¸¶úÞaM…ì¤M”zOm«¾%^sÁòjv3Vú},Ýxø ßø¥±ŽE¿— öö,®e%Qé^ÇԄ_Â>ÿ†ŒÈZ{5ZÂ÷ ¿Ö*XãÆWkÜù4 Ͼó›ÈÔ¬ü>ê‡KK÷½ß4JŽ_ª?ií/1ï\W›ZM +ï´tÌEõ»çŠ¯É¿­ñN ÙWtÞ¹np–,¥"ßV[¾›'I—(¾Ó|-qµRšxëMߓ« X–¦¯„ÝÊ5_©–ïŠèÂ͗Œ´ða!ï<Ñ×ØêצOdï5ï‹ʂT| í?p·+©ìhþ³îÓÝ·„wЦ°zÁá…ZýZÃ<ˆ_hjT¿póª9éhŒ`ø¹önÜ4 9x4­£ðÛÅjµ¦i5Àoéiáëg‘âpøö|cGåLdÅ(Ï3×ÞÑÖö™{췀ŽðàÞñU_pÃ;Ȳþ ÄHvobTªJ³õÄM(uƆo¨1ÑÏØ÷…>2ò›ú j¹§ªáBՍm£Ÿ0ÝÆÿ‚Ž©ÍyÈ-”¿“¨óf‹ÓZáxHû͆0‡Eês.ónI´a¤1wÖð±îì){M1$èïǵ7Íp$êÚ[­û¢H„5ß+6K­ç¢†ÎA¯2ï4ÚC'pv1ˆÖÕEEoòø¾Ä=µ&ÅZaB†B/ނ +åîÁ!£Šo᥄8-Á\‚§6Ø÷4žmËU©klü0Ó3@Boù tY Ýí­*•÷ñ«0¤‚—¢A墣P¸ÍÍ)üZCt)…ô@»%mGÇÀhé/·D[tzï6$@Wïm±šP4»àןÑVµ´Ô^æKmà]Q© ¼-Sn*X¯Þ¸­Uµ.FX²øp•÷@ûI¡‘²Ë$ Š†\¹(;CÁ›wFÔBRŒjµÅI*¿ÇøëèÉèUƒ þaéͦzÎh0[šÚö-ы5æÂg±…‰]æ^—FŽ +«p¡Æsí+bášéI–(Iæ„K´ÎæžÙð^­øÅQo"|õ.–ü”ß»áñ.Þ·‚è¯@h~g6È?ØáÿÂ悋û­dú6ž«¬Lì.Ó·T!Á? xv#÷vwpeÁ>ãwîÚvo¢2owožÄíÓ÷ðèêÖg÷¾ÎîÙ§7ŽÓöj#@ù +.œ}؞ræ.] -n]%‚ÉX09‰<ŸÌÏ\ekÑ£ u#<¥V.Ë)›£ÑH,”–§ë›kKëñf"¶2äËÖNB‡™ÆÙ •>Éö³ Ë ×´g9Zes NîxS3ž]È/Q«.S!_0Ÿ„k{)ßl4æšûÉô*åí1ÕJ֌e[‡‹ZeŠº™¢qÎ[B²sª9iÇ^½‰œ} +W÷Kºâó7c¹Pìeî>æžàׅ´4Ó³ÆùÆَr¦¹èExvõ§˜éÅäfÞæe+dyXÏ9”3·»MÚÑPÎt›> f=B¦6‡mÓ9½1£’iøÞUt2ʙ†ÜgÞùÀrMdz!›câ þ”Wª+•M®/©d™˜¬6Ü *™.¨ìí析)ÔE”mÎ>?E¯]î+fš[ ì«6oà$±…3Y,e¤}z’|öšÈ£lÝí½ê*OŸh7dªµ‰RžJ²™n;²LÃáç˺© ÉL¶—óûê¾J¦KÅH4;I+fz±xµ«–éŠÍ1t͝)×uÞ~ޜ¸/ï*gº“r'^&ŸóJ™zçžfB¦Ð/RQò,ž,m)g*¨lœÚTÌt<{Ü}l)ejsPÙóó¬J]#ŽJu#¥–i‘ÊM_*gš£–eW´€3µ9ä ܚ˜^d3-̸d ¼¸Z`›7sVÉJ2=™§òÑeê‘ejs4ÇWʵÈnq&ÙFërù͟žU2LD+7Ù µLÓԆç<Ž3E2&«ëêËìÒccsW1Ó½9gP5Óõò^RÊiþÐé µwéWªks|}¥¼yzâv)fzè¬Þ©fºw¿sU™Úíu=ÍQ‡ëõyåLóAÇAvi~A9ÓúÚ¸R¦ “Q¶‡—¹ñ–JŸnQG‹ëiåL7™Ë‹ósÅLÏ·*«8S4¿´×õ±¾Éªdz£Î›O3ʙn>֟·â± ,SÈg{¹:SUmà†cÏkWÉ´p@ež×3mΌۗÎg@A¶³/òAóz½d3-ݲAã>É=8Ӏ3áZ‘Ö4O]yf—Q¦ÓB¦ Ê’}|á”þBCži³6µÀfÚZôÊjj?+žº™L“zUª§̓„rl}íZiu×2MµÚTáÊx„Ét‘^Ÿ‘)Âézh“™i‚“³©uœ)ʅÍv²Ñ(–ª(SJ–i£±\®qò»f—eÚ ?β3ÍâìŽOÖ¼ãµòÕ¾ÅåâeDZ¨•ƒ©‹Ú¬êÓÂý|¨öôžZ¹r¼ +OÛ4?¨Þô”ʯ¡¦¼)®\å¨ìi$F_î³O›•XÛ¨ŒTïǏ•ž3Jq{uöLõi,àÙ½Rz_¼pò-Öþ|90ur­ú4ï­.ԟ–¶n焧²‹Ll_—VT~[™Z™?h2Oo/qÙo¼8½¥ÇgÛZì ´¶WUzÎh¹´·ÒP}zä(ùíêOÏÒ³ \‹)<¿r\D'UŸ>¶¶ë+ªO+‡äŽð´­Åž+Ùąگ¡H;saÕ§kPâX½Å×ÕÒ^^í×Sö©Õ3êÓÌòF©¬út-°8N«·Ø²=0éžUy^¡2 ®Î³®9ÙSïþNs‘}šòÍËGåÊþUγ,<5CÓ»ÒXŠºqž¦XýsåxBOëìr4{fTO²ÖÜdþ’è±@k­0Sö™µxV˜ûˆùÐwYûtz7…Ø^¿ñ«7FG°ùw“œækŒœ Û3¬>‡uŽ%&‚NøáÚ3h¥#þXÕ ëØãWP­ãSßí<Ÿß„ÿa¡äí4ži¼^ùf$ê¶1nsÙ╎J¦‘ ´Î9UÎ4T8QÍ&‘GZ†ÇÄuÅ+ÕLєw­–é8ÓЬ‘EÙÆ6“{¢Lo¦¦&„L1úç3 ʚ¡¾¦¹'I¦î^½Š³•4ðB@5SŒþU2…õ  ÿ !S¨‹¤®çª™B7Cê™"ô¯š©Íðÿ½r]çí>­LóNÕL1¦2Ec_’-Âû’^-ǹìñ_lG¸S'7ÏFÞ»x}®ŠÇ¾Ê›‘‰—‹Ìñ–î{á{VîXm‘„:Ÿ-³Ú²mè^¹žQëìŠ 4‰ìkƒU.S{K²ï˜˜X¢îºÙgëH'1ëýDÝ=_çStá$ñ•ÉG\ŠDÚKúïËiÏvň™µ™mñ/§Q.9qu¯ÖY›ù`¾˜B€öÕõƒÛYu,ªÁö”´y‹˜Z ;˜!<’®’” +U‰¯Ê +%.Òå«Dwc:à\¤Dv4™979hËó×äº^£#ÆžYÌ+ÔÏiW­ŸÍ!Ô3Õäúoo\¿ÿ&øúyXSª!¯e¼ÿjX>™•…ÁÆÒHŒö$³ªIٌˆ;×Xs3I– W’™‘¬ÜÙKç-¯ØînNXIî¹åɓøšv»ÛÔKªzÜíªç"#U=AUÕcÓÝÌÙjC܀|‘% 8Ũå¶»È Ã6°Jy¦3Ó cێ®*·]aÆ®ª¶ÕF%¶Ç)V­0ÞyÕij®\pñpC¯©sëSìn‚bAÒ^Y­Ä³˜¨VåmßÛûmj4¹Ö:ª’†فåܱ¨mùa(–ó+÷î8­ÒMÓuº8é\Áe`ìü]6 ¥>Kß×¼ œäˆ$u”£&¦”nwÑ.§}ܳFǝö¨ƒ¹²8~üªÙ—ôô=Ø©W´IÑ& ]™u¥î„w(bС‚!º]6 ~¼l—­¾H¢rẴrŠ%KäJMµJ.Qåց¿ …µw‰°âÛð¶wÉMN…U=•XÓæP˜ `Fáe@3§-ÕiÉæè¤s¨MV:GOJcÿ&'ÕÓ +µQ&^"µ×TçÊ­]¶xl)oD“Ÿ–uÍÊÀpE¦Nj~7%šÚKïñë}…Ä$;„M¢ÒýA'FÓ.)âLa7Õ¾ì0¤°ó©Í¡? L7(±€¯ã=>|9=†šR?g_$³˜\£5+î6Ö¬È7ð h4E I +fé¥Wv h4nõÚ ‚—'¦¯ÑlwPbÝk4~Tæk}ÐhÐkJ­ã±ét®ÑÚlL:½k4”Jï{¯8Ý é¤‹ßÅñÛJh@2 Ö´VÐâ­CeŒšÞ•ú[š§Í6Ž¾ëu–›_n/êjÈ 2KÁ8ßj) fÆߙš…Äí)Y›CUÍvéý ̇x--Y‰wP ×dNMjF?cÐ^5l‡tzwÀ©¨,¨e;ïúéH7Ý š—vpbý°U3s!ÔϋЅt6„ogzÁ÷"!-Žï6{^ñµf‰lª³áQGø^Û‹ëߟ½(ͅÎb¨×:7iµÏb(^ð½(~.ì~Ãé(à{¥TøÕ«J:FgCí¹k˜³—žgCÉ\x)ß'ƹÀ·}qGBúGÑ‹+%ÎS‚†*¸lht‰¸)§ ì¾÷b«–Ùù!±^G·¨\ +c[Û×Z£Å Á]®'Q.j+"èKŸ¡q®±{š‚ö<ôkX® ¸ÓɊ¤*Ø·GwxÉ'¦”o¦mZJùü†Ö•&¦@òøFÕ=OÝsMe½% kJƒ«Ô쟷-$¦ºwÃ[{Œ:ÔCbÁɹõ|?,$ÐbÑÎ †Š"êÉKŸ!,“˜Ê`/h:ß2aãì÷† +eP"Ú;#3CW˜Ï፪âʂí-×¼³ÏTw.Ñ]ÝûÌrðÅÍe”"蘓[z¡Ïbít²ˆ¡®cè´#è°NîC j¦8‚N5Z°Ã:í:q´`/1tÚtÔ×C v$Z°‡:í:hÁŽbè´#èp´`bè´ßcc«{Ž¡k¸’:~eÑc vÆcú1t‡d³mgV m«ûÀ«Gɜ] IÑқÖwÜö‹—ÊÊÖÈ];æåèWÁ8`ÔÒ{š–Îöuh/-wØ躝æ<q•ÆŠòs¼ËH0Xù±|¨gD‘îñi%¦í‡e¬~ØÖ§9g¸~2ËUûx1Þèþ΋¤ù¨c¹Ò*’RȪKGAs†tMFæ +"øöt@ÕêÈ„ñStéÜl¬f4Æ'ƒõl¯*ÌLhWÍf0ØMê Ù©aK2ôy¯c&ØMmÛFºJÒ vS_Ÿjo8ˆ´eFÓD²4Õ[†ddÑ ’Hac‰I]°èö›RàE/òјÎ*f;ZôâQ©¶ì-Õ](; +1űo£õ×öÐXJ{Ù<k7é+±ºÌL¿=PtšíbÇ*§ +»T£ÀDHI¦ » Çñ½êùÀwÇWҋ™­ÔCÓԃ`´¡t»¼sá~B­PKJ!šêý§ëo؋à&'µ`*öŸÑ8¾XC/&FK¤Þé(±¾Eˆ6„µÈ”Nӗxã-&5°öØbºa¢Æ+)h´®ZLjø $ 3RG§™c½B$—1,Ûfóm_fñC}WÙn©/'KB%Ê¸tFVHâ*pA#v¥9ºW ,öøŸÎbïnÅðbO-¹bIèý̟ªa,T®«º¤ôçÒ( â¦od°iš¤QTšÊ"®Mìµbäl:aζDrµy2høÀëk4\§nk÷wÝe£âñì|ñ´y<;_t:B6U­=LJ½ C!øHdUèuBbšÇÊ(é1ÕaX¨†hµwgëEEAëÏiÀ8Î†J<2¤Ó—@È´ßØ,¦›Žú‘À*§i©¹Y· ¬{šÔ*-;­Ñ=ÝnÃBÁgÚ;é.¨ùˆTz¼[QÕî*"µ8~i ˆÔ`Djq¼dÄd êחˆÔ³—þD¤¢tú‘ŠâÅzHE©ô#"¥cìhْXɯõCS;v2rÏ°½/†Ç=CY(œ²ëw(öç×ôèéG(œb¿ô=®{»¥´Å´×î¬+{…ŸA„ƒá>J(œ‚Uá#„Â)ÛÇ ®Ï +ZÀP¬ +Äç'k>Ý«úª9^ŠÇR>e‘QG/”TؐEр%¦~²]‡¦íáN7DÑèƒ[8Z§ó‚*Wšò„\ôƒ›åqugªÇáÈ'Î:ª0=ãÝ7­”ÛøŠËÄÖ}îé°x™ž¸yÍdã“KÙýÄvfÉßr‚æÏî/F øÚðôI¦±´¼Ù_K%}שTÒ¿Ž.!Ø«sӑãIZdÖâ$ÅRŠ:C«$6FéT=î,¶3»-/i°ÛÜõֆØø,Ê4|ïqÌÛkjv¡Â±V°Û_5S*»ŸÔŠ°sl=lÕ2½ÒÈ47e*Åšõ6EV8y°[èø>ÏßL( wi»Ñ>Y¦ÒûøæžÕ"ì"/‘×3µ`·S­¨³gí»Úþ¾j¦SùòýZ¦eíûøvŽÕ3ÍlžæT›w²œ»TËtGa‡{,[kü+ç³ߛSz±*HÞ å ¥ro3ï±Sg>¢D7¹UR"ûú$ŸPµlÇ\n¥Ö[eê"Ù#ڞªõ'´GßCUn5Q¿ÇêÅ@‘Dûb…ÒsNÕóó`V¯ý¼INéÚ…3U X—´n’ëÈ +wš6ì"© ‰Ï„ìÀ¯Oï9M¿>ãò¤s‰œjý”î}Ó»lÄhýôï0Üèz÷ŒÈÎRëáþ8ãã%WV¿ˆHÕÝÕètږÞn¢éº³ÃtM§´àîâì_4ÁóazŒ¦S² ÊÇKïÑtJ±tÝF>ªGÓ)Ùâ•=í{‰¦“4 ;fÏë)šN))Bºˆ¦ërFî0šNiŸ†Ÿ+ûM§K'^ï÷'šN)–ΠoOÑtJ¶vîöþEÓ)õ.¶ôö5šN ܈}GûM§K§rÚ|ÑtíEºŸPGJÝFÓ)S›£ßÑtJý§à Õc4<)Ý;…»Š¦SÖý¦3Þb½DÓɒ’ï‰÷)š®«ë8šN3ƪoÑtʱÕýŽ¦SJrés4Òn‰Ì¾ÑtJêAºzíG4ÎÎHŸ¢éôç—~DÓ)5†€ÆûM§É՟h:¥X:Õûøz_Î @Éýbݤ~‹Wû%•ò»9 >½è vIã‡jjwÙt_][‘Zh—§ß÷Õ©£ cíÔò:;j'¡•$ž(&SXI€‚JÔ³Z¡dE2ª + Ü.'ݘêªH¨Å P]»¬U$eG +U £ÑN×.«¨L4‹IWD‹ôZS¶" +NÆë:›k[æøÛ²´.ºëùš;Ñ9W!y7×Ü©Þ.·n(VÉà5wj‘\Æé 9Hhû' ÝõÖW¹BÝÈ-3šV*C×ÜéZQÃô|Í‹a´/ºëùš;&öMç¢;c›Gõõ>œs\< µ;ÑxœÅzß\”êëäî:–ª¶à6*Ÿª»<è‚:]ßC=ùDathñ¬i7HgÄ£Ù¦a¨îÄa8¾rÑp;ìÀ‰ µŽªéO*ÉÆn؂œ'œòx"thªj•Î†RÛïÉm?wØ%ñ†¡Òñ7ì Iéúö†‚ÄŒytk;6cÝחÈÇÞ·BЍ‚ǁ³½o0Cw»*¥"òìÚëÇÄ©´E²+F +ëDzãÄ ÖªÝ!¬Ý«¶ÖîUûw* J¬/cƒÒQfâ¹Kµ)÷•šR÷¾W-jOû–.ŠÄk÷ Ö\‰«ùP—›•¾D¦ð'wŽ$ړʿöëCx°­¾ElxìttQµÚîºx­g8Á¤¢åÕÙA:}8%€I§×Ûª™T¸A¨tÂag¾ª:Úáu{†á¡@Cøžo¸ãâ+Õî¸ëb*8Wt{oug7ÜiE>ö0 9Aco¸ëËMyºñDÆnÊë5žˆ¿)¯÷a¨qÝ4.ÉH|H77ÜiÝ÷Šî¸ëü†;£§š£è§ÞkÏ^˜£¶z5X ‰éÛ ÃÜM×]`­<ò1Ü«ýÅn(†CwvÎN§ ½ÙvFJ§/ñœ”±µ˜n:ê±°² &›Þ1øº¼Nâە‚˜Ä»¢HAL· ÃY—NG°kq÷¾ c2Ää\¸¯DE³˜‘0&i%ul§BR|¿¨†1ͺ E¨k.ÛùQ9ë22*19ªrðÝíºò¸£ &5"tw¢ÆLÛ0ŸT¦êԚ]÷¨sSž¿ËWÑøäÝ0 D=ëǸB‘ G=kŸ² Ôù¨r~ôCo+ ûé +Jú׎Òåµ=›#½èÝÛ_¨]y#ðWnG÷eÏ²7gb<ÍL<Ø´+²³I‚ð6wřJâálŽæÄaa[lª’ÞÃ6›:-¨ÄùՃð¯W³´T'ËÂð(Zì_db2ºë>W Â;SÍê2ž­UëJå&NT3u®–|wj÷°¹…LùH.¡·ÃQ¦Òд¦3:%Ü#”E9º]‹§OJ™Ú¨åwÎIÂðŠòØ?qó®Ïo«d™p„6ÓW‚ Vw©‘in2¢žingâD)S|ï[lEZ)ÏtWëÁõCõL3™ƒ¬Ä³ ²Dϧù¿Ø ÌWς_Úû*ïS”ê{âøJêÊ3»l Eïl­•¦I¨s!$üf kí‘Nž) ;1?Ñt›„F »ñnä3}ÇIs3¤½ lÒµ¨‡$µ»V© I²z¡RFB›ô›šýº™tunf1jIJk»V©v]ÛÍ,Á^'.hZQw²“'{ˆJÓñÐdZÉfLžd›^Ö·Z£¸»ŽoYT)R›—–|¼nôŽ¼´l­B©Û‰;+hKu?-¶&uQØb-f;ºï@]Ãdû¶F.få¦Û]o&àNmã+ýëë$%“ÛùõMvø>>U«Jè¥Í ktŽGTî~r.«ovHÖvŸEײiG2ucïèœQ‘dñ/79-Û±.—IäªÏîV‹Fm‡¡€•I¡œâs®4Bõ®4Öé?açý&§¨cXd÷+Þ2ÓAbz·è8åѵ‰Éf•ÞZL7–Çx%¥;—=¶˜î}:µX>t¦’X[¸°:d[¬Ë(@£1€†Ï!Q 3¨án +Ðh `»=¹“(@£1€â;4ˆ­Ö]GJDEc…)÷ƒí, +Ðh j±î£…öÔÖÒ«N£Æòk䮢UŠÔ(Þ¯dÊÓ^«Þ/å3~#[/—ò‰êò/åk³*|”KùôndëÏ¥|L̈6@éýR>›CöýR¾öû‘?Æ¥|ê÷#÷óR>C÷Wör)ŸØª€ +Q-ÛDz¡Áê·úõ~6ÔZ?Ά2x¯Ÿ¡³¡z¾×OTµ>œ ¥v¯_g~JÝÞë§}«_WgC)Üë§mR^‰w~¯Ÿ²ðiž ÕŽ~ú’܏{ý´=CxËU÷úéErõÉ «y«ŸÍёAWõ^?íªÉl]ßë')HÛ­~]Ü¢x¯Ÿv…”ù‹ßïñ^?͉.…g±>Üë§mîè*{ý´—ºŠ^Ð]Üë§&) ½ÞîãëCÌ{G÷úi§‚ìüý¸×O{CÅf8^ßå©ÝÞë§5E·ú‰og z¸×O6 )é­~’3»:O¡ø{ýtã^ûr¯Ÿö­~¼$÷x¯Ÿ¶Ãµ("µ§{ý„ø-%Y”sÕõ½~Ú ˆlîõÓkÍJ°O÷ñy´S1|ŸÎur†ïãëé^?>ÅáÓi4GÛ½~qºÞ¶åNïõÓFòèă~Üë§6‡¶ï$v¿eÎs;‰zÃPï^?íýf©A÷÷úI[[¾Zìö>¾Îœ4ÔïãëÃðáoõëý>>#ALz§7´ûjtvŸ<"µ·{ý$†í¶[ý˜ˆ¡ÞïõãC¥´îíù^?m˜£"cßë§}«_ϧ6±÷úõhë3x¯Ÿ¸×>Üë§}«_Ç÷ñu…+Ӗí÷úu /ºÕO”KO÷úµ›’Å·ú©rÖé½~Úî]²Y¬ë{ý´d6¥®ïõSèÑ­~Úç¿ׯ{»¥´Å:yRYWöp¯Ÿ ¸”nõëÚ{Pv¯Ÿ¦Dˆnéí^?m`Ȭ^{¿×O; –‘{¾×OZIù­~mxÌðIVÒ{ýÔAƒatN²2x¯Ÿ! Óó½~âžlßÀш®UŸÊ÷úiOšQœ} ˆeæ}¿Âôp¢…Ѷ”=>äçJÝ3'*ÊæJøVÝ´«íx/ [”H'cÂîMb¡.ŽƒglSlV.É é« Cù·Ê¾=7%+Ñ|žš÷v˜VÖìÞÓÍIÊ\‰2/¡x*ûäFbÕG¹ªvÿõi=lܯeOçñkæÙíL¾$©•»Í剗×dÄ~V¼ Â_WKŽplnejcëe7üR)œÚÑ°/tÛÈûÖ} {8Ÿ ]%w+‹7{‘£ûýòføåÐU¾ŽíLìïÚ}ދ%{àîåÐ;t.QÙäz’ÊÞ^¯Q¹ÈÔn£qw5š±£ÕæÄE¤Ô —N·ùHË}ï‚æÈÌÇǹ°·G£yVC—ÍÅ'˜Øêv"‰/;É_Ɨ¯wêhAÍ_‰î“|½¢žå¥üšRcáƀ궦P¿'íªuō®¢³¼=qx²Ÿ˜¬6üÙ©@èîuâéÆ~ƒ"I׸àPûët=´‰üÕ6ª8&ѾœÝßwP“å¼Þß®I!{]6| jÛ)QМ`oU ԚR;$"ŽÔ«Í‘>ɖñš©óÜîqd3u3¾äoͯ-ù›7sÙøDe;s´¼€f«&rO‡ÇgË+{ Ò9|á’e®ÏtÑÞJ…2.–æòö®Õòs IòòúÑÑ¥7sx¼‚þ‚ +o?ùPÐî4³¬O„ ¼r¢ü-òF¸l1šØö9¹¿h¶C‹D«ð1êÁQ¿ pVëðqak˜ 'Ìb§ ø"åã~˜õg3$»ByÓӎ׬keu•žvÞ_r]w‹Ä[EþWü カ9øG3âGÑ2ÿÀ/~POÝñhу\òElzÄ߸JøeÜû›ÓâGw¡.M¾ß^™\¢Ð”0I¯Ìdƒè š¨V¡WwÑÇqÚ¥;/jٝiæ•ëÉè,¿/ª‰W’¾žY ÑK~·ôL_/®¢fÛa“½Þ9ÀÉ¢ Öù ÔÚ^[Œ§¥É€{&„Ðÿ¾¨YîÅ¥9&—9´á½›|òÝy–·¯oóéõUûž ’ü¶@JºpuHœÉ€{%;¯”Hr·)îäø“áÖöd9w~»[Þ{|ȜÜlS¨V4–^F’¯ç¯K©‡¢Ÿ¦ü…‹ '^û!QÕӋÑk®ÃŽfpÒ;)4ù9±?‚´Kçèn¶#š…»á#]ÔÐßAæ/éÌ'Ýܒ {~Tj {<è¡Åøa?{¾UseŽ’kI÷SÅØGV’Ê·ß>ìå·æ: ô,Çð «n®Û5ΦӖ—‘äñE“òWÆ}þ‡ñí©àdü¹EQ._3s]y‰ãÁŽý˜±¹>†Ü8J—Îœ-¡³^øÇÇÓ¼.9ƒ_Rx¼¬ø0,Až#>¼¦s>´P^ñ«˜DV(^@¦Dæ ©.äºùBOSÕ+~ôâÛÐ8˜N9Jü·ìxL…†×ºO<öïüéµùEùyŠ +—Ö´Bw[Œ*Hj>F¡ªŸ-‹;žÅ&)ñzú@€XœÛŒimみ#•™‹0tãn É¡ù&ún¾‹½2/O]ÇÖE° go¹š|Û²pü¾'ç ­,?S7ŽjºÑX¨yÄs3¾Èy~fƒŸ:W®x!(€)f^t$'Ó\×S²P.I¿( :{œ£y ‡ÚÄ÷Œ&&ž“ü‰ƒ –PÿÃôlË4÷Ýá ÷]¡áتzƒ“óóWÙK÷éºÍkßÍu‰ô£Z‡Üè,†¸]¸l]^mçN†ˆO°×qb€jçÅë³â´ߊӐ+.õJ$¿$é@½Ë¢¥ G\üñÎ+.H©N‹ pX\ÀÁ’£¯#©‹½`!HèUÜF—@@ìî[/K  è—^—@@Ò\ºZXA¿ôº2°Â’ÜÛÈÀïðö¶2°²õ¾2°²9z^)-€Ðlæìm5¦ÅüS¨\Ü endstream endobj 87 0 obj <>stream +7ª¬Ìo•=L—8ö<ì@‰Aá38Q8‰àâQ¦ˆÁÒ H6V\¸ãєŽv”W8̏w€é™S/hüxšÁ²ƒG²V³µÊ­»Yw@|Ê;6áU +Y?wðJE¼+ +‹… á'uãrͲ­œ˜ÅÕpљ‹Ùyî»%<âÑ®Äî |Ìúx]s5-U’OãÕ,ž¯ð2!¥ÄÍ¿tÁ Ó¶¹·¼Úôbx&¬;þ°Åè`h,ÅÆü»¯OåÆVãáî¡:6m›³ù—Wiú zSË6Êåýò?[éÚõës¹Ú›ó/ï¥VWcátùºvSÃ[s᫨è€&wv×Ql •lG2’™¾ç*+» Åô-UHˆ6+ñRÄ\Y°Ïø»6²šÎÛezÝ>}ÿ¸‡>fpȘj-„WÐ¥ÏDºÜH¾f¼ù#وÂk‹ðS)ó è02¬„gÑùt÷§É«ÍÀ^t}iq>^ÏแµÎIlá"®‚É–P­)»{~3„ªqˆJ Ç>™ŽùíÓî¥%ôíšÝ»3¾i÷^û6уEûÌrðÆ>½q¼b÷¼L€â/¾Ä„A‚½ì +=Eϱ‚“½äÕþv ˲±†Ât~—ÀË v.Bkuôk~­îÇÑpq±=–‘_q³ãÄù‚D_ñ²g]3ì8a†,`6 €z-ná¿J ’ ƒ ç$<êˆkXðŠ'S ܃,;Dà yr°È=Zõ ‚“swËÜ٘@“9 á;qιԴȨy!Î;·êCJ׃÷̋ñ0 +_áÁ.?ìðq{IHû’5vlgñXö~,'±´¡Í‰8ùLñ[еÛ[~¤¼¦!ƒ—Iøx€“õ0ãß> ú7ö*h~Ú÷Šæ'fõ[ÈÏð™^q¹`‰?Kû‹óS³wUçAv>zٔ‹3£¨x Æ©1~‹$%¬¦„•Òc\> §ÈïˆSt¯Åvâ±\vÉYÞO¯Þ,ØÙÑT8¦ùÉ' ™|ÜO—¬xŠ!¾êE±x•¶fðÜÀªÒŸûÒ1E—ò«nøë”f§”ÒE _ @_•Šh ýmÔ4#•‡=ÛóŒ[Cl‘ûÓ/õ-åaÏëvØŸÑØïjnìhf´9ºœ;šmŽ.çƎfFéÄØúª´(ÞC ËÝkä#ŒÛÓÁ“Œwa/sƒŽŠÅ«Ñ˜_?ò +&³Ô~)$1™…W&^"¯\Wy¯¥ílÙ㠁S'µ6ÛÞBᙷí´C…m±q0\ËÊ®ž2 0›™{L¬“´ ÆÔÌàË^:îçdI¨ ։w’i7û]ñÅÃ~W÷¢þ ó`ôFbÔd¤¿#FÍíf« a×rA6$TÐqθ$²h¹” níæ6_3[N³•pd)¿9S•cÀà†OÜÔ5·M‹ÌmÈ&K(…ƒj¹“º7o2—Šöb +b$5;BÖ 6‡´®NÁBŠ­˜|çâ$®·6ÔzÒɜº'-s$­z)äIÇsÞÎË rdpŠ»¶«j0‡Ã(4%n1CՈQñ+$q.“}q“K[ìLþ¦BÛ*¥(Ô^ÓÌí²9´Êh¤’.A䨕ô^‰Ïª*=öØ»áƆ¶PûI¾K +缂K!`ìggþ¤[ƒ0 ;~LHÎ/m?*$NjÎÔÌG†ä"Ìÿ!9sJì#CrÔ/*º\¬a>$?$G2 œ‡äI¡Ë˜‘Ê‚`X“3?\ˌÀâøÌ^îf />SÑD~ÖDOý¢Íÿ3ø"ÚÀÆXfwö,1Æî…ØÑ4ëzáFÓÒ >ʍµƇ¬»Ky;Êj z§ÒO>xæöbéŒÇÎS| L +™oý +–[¯‚Ñv†±×2[ÕѲȍ’ˆ®¤®*Ë7Hƒ>1Àxfrõž7·ºy{PYø},ÜÏ-y\Øàppóß Û´Ò*M_fª7bSÍá€oöÊ­×:z!|™,ß=TóÅßË =ÆüGÁˆGãct 6‡áC}›/Ù\øÝ1Ú=–¯Ú—þåF+ýpÝz¨U‹ßÇfÑWÇùƒÕôØìóî%¼;7æ‚ÒP—ð6¬ÁðÕ?ÆBcc§çÔØ Êh×FÓ!xôlÃõA¿‚Ïyü­ðzr«\;¾Ô¯ˆCq}ÑPœ +Œ‰Š‰RáX Ž¢ã¾T¨ˆ»ð~ˆŠåàÏðØ?lñ ¢è±hØGâA(X€öÑhsî(RÜ +cü7tÌGACŒEƒ¾ Ÿi_,KÙ¸/ŒDQÜ7”/‡Ä¹$áûx,ã2å>§l¡ˆ/N _äm¡0ú¾Ðø¡ /„'tÀ¤¡TÁ¨/ŠA PÁ0$ßD‚Á ÿM}CÇPì7Áˆú7Š>#“&÷1î‹QñptìÚ&|ŒÒÐj\q¨N(ã²à>§lѨ/ Gøoòè›(MÇùo¢ÐÑp€OSøÌåÊ}ËK€+5—…PSô E5E}AG„։ġ+ -®õ"1ø ™ Î +‚ÐàñÈV Àøèp(È÷!ÿ™íeH‚ý†„¼ð+)\’œ$Ʉ/e+iH=͎ÓN„~Ù) DAÐi +†ŠŽE|T$ ¤sß@¡â¡8jî€Z/0ôEa\CãQ0Fb ‡¸/@´ƒ¾pDx$jOCC +¿ñÅCH<ùD™Ï\¶ûM,à SñJƒû‰…c\š±t"¨6Sî#J‚-÷Jƒ-<ÿ#¶v|¢Üg6ÛT[‹ämMM¥͏µ#Û¸Œ¶½„֍Lá± G©î‹@ F‹…a$@Zà{\ŒŠÑ4ÿ†+‡:qßäm2Q,îø7 Ñ|šÜg6Ӕû"ðáÆÏ ß„|‘X<<Æ%ɤèÈ—)÷9eã +Æ}“·qEç¾áªÆ¥ÉfsMÉ[#¯)ל&á 3óŸk{ysk3£R;L¹á»‚è¯ÁÓG$ã0­ÄÆ6lÁ Ô.¦’Ï6PŠñh$“&Œ(È9Õéu BŸ‡ã¾p(š”k~š2…‘„ôo,‹Fàc4! ͇‘‡ßƒš  aMó… WB4“"úAæÄ0)hŠEMŒ ÂÛ"aA¤o¡DQ“@+ã’Àã`4Ê1 š‚B²4U8ă/‹†ÇB (©8Ö1¨ÔX”] <˜äCaH,Œ2ŽPTýˆ +Âl¡¡| *ð9B‡Œ„c¾XÔp8àÕÉÀ¼N: ‡@3‚†„‘`ý2¥ÃÌTˆQ1¤Cã4”f"*JQ] ã# âG OÐTº!Nû¢QÔZh#mLZÀ< +ø¢ahgš‚rGBHîÚށÂL ⯄PƒX«ÆÐ8ÐÌüFÇ!(G4Å3`8ǒ‚©Mgq謱HÚ x—X :!}…#I‡òƒ¬@)¡æ!T¸(ôîmø‹™iA¡DÐ÷¡X´!ôYŒÆ¿Æ`rYˆGB(ø+Œã‚¨¬ ÿÐÉQ$”cR‚ÁüˆÅq⨮4„¢!ø7ò… Í¡‹ƒT,‚; +µx Dý„^‹Å‚¨ Ñ´$2ãÄê,hJÁÐ ºN<²B +üÈÂHh,‚Ft\e b½F€A\2Š +àΧѠGˆ&ŠŠ +=†>œswMó0  Á”$Åz&ŠÍÝ¡j„f`ÆƓ=¤F­¦!Kó`†´Y<m Fi˜Ú@²c1heÈ"ÓC©X0†‹£ b¦ˆðf”Fsm&ô>(:ÊÌo l²ÅâÐÑaÈ2Œ†D0„‚¦3$ +¢(I˜rchˆ1H‚¨ Ãaáü—ª BÃXQF£Á IcЃ„ã¤7‚ðƒš–Pƒ@ÊÌ aDŠ  Ó¾PrŒ!uF¿1õE !„ !ø •i¥¡ý~·Aᢡ0þ `´0JfDÐ× •Hú~³!=ˆ`äŠqHá4;DÙÙi#˜Ä¡úñ ¤pÍ 4ÖXÞ@QBa ”x c ‰¸†‚Š…˜^'q4H@Y ‘FYÅ@!¡R#4…à+h ”´eµ-l<ÿєMF:tq$Ž$ Z$Ž1…ŠƒöD ?ö¦  D@U"í áMèçP€B… +ę¿‚è úW&ç¿Ã09И£âc.÷Øñ‘Ú;¢5Wö©ØÒXpq a0÷ʀŠW~ñD+,ž˜uböá©<+Z2î›-X3Bbð›œÍŸ.ÿöp]ÞÍ%ǎ7m§¢Ï>ImÖF¿¯\/6Š¨.çì/ùYXñ—üŒÜöK´X ± Eø”u -Kx Ð0nÏÇÐ|¦QÒÇ÷FÞGϸßpÿÂÈCŽKR„^‚E5n“t±Uœ…@Xâ1Ûñê;!B„"ôÉh``@ÌYf6›M&‹Åb2Y­V“ihhÈd6™FGGM¦wï`þúðáƒÉôÅ_˜L_}õ•Éô׿þÕdúî»ïL¦¿ýío&ÓÏ?ÿl2ýýï7™ÆÇÇM¦©©)“Éãñ˜L333&MÓ&à@“)›Lóóó&ÓÒҒɔN§M¦\.g2­­­™L&Óöö¶É´··g2˜LÇÇÇ&ÓÉɉÉtvvf2ŸŸ›L———&ÓÕՕÉT,M¦R©d2]__›L777,+—Ëbv{{K؁"Dˆ!BŸŽP"ì3B„"DèÓJ„½qFˆ!B„}:"@‰°7Î"Dˆ¡OG(öÆ!B„"ôéˆ%ÂÞ8#Dˆ!B„> DØg„"DˆÐ§#”{ãŒ!B„útD€aoœ"Dˆ!BŸŽP"ì3B„"DèÓJ„½qFˆ!B„}:"@‰°7Î"Dˆ¡OG(öÆ!B„"ôéˆ%ÂÞ8#Dˆ!B„> DØg„"DˆÐ§#”{ãŒ!B„útD€aoœ"Dˆ!BŸŽP"ì3B„"DèÓJ„½qFˆ!B„}:"@‰°7Î"Dˆ¡OG(öÆ!B„"ôéˆ%ÂÞ8#Dˆ!B„> DØg„"DˆÐ§#”{ãŒ!B„útD€aoœ"Dˆ!BŸŽP"ì3B„} ±¤ÿ&{JˆÐçM(öÆ!B„z¥6(Ô33Eè³!”{ãŒ!BSÿ‘ÁM„>["@‰°7Î"dzF<ƒ<#¸‰!ŽP"ì3B„iR‡ fiø^X§‰¡?8 DØg„R$£F¢ž‘QÀ!BT"@‰°7Î"$§þÀ#3Ró0™}žD€aoœ"DHD½ì«ÀC ôYÖ3x҅LŸº) 2F(öÆ!B„êʄ¤Š‡,=0åD»‚LŸºQ Ò%”{ãŒ!Bc$ãÈȊ4¼1ÖnR*10úCJ„½qFˆÐgOÆ1’x¤„‚††×e†ÀSéS75!BíD€aoœ"ôyS0’6(FÊ]‹ 1LGêҘ¤„‘dð[Š8dôža Ì1û °›ÍÆ2ü‘cï&On’A&U“Y™Z"ôv‰%ÂÞ8#Dèó£¾b$™õH†ŒB̆”¹m€c_H™MÎ$0ª 7qiX +™¬3êÀ˜¤ì$ÃH؄Äm¤ ðˆAFˆ}aúòË/¿öåÀ_þò ¿ü…7qö& ™FåIâÆÔ%Z2´DèJ„½qFˆÐgFF=“Œa$ÖÙ›°õH¾4ìù˨p̾øúë¯ 0á_"Ü4ˆpÓ Jyå1ˆrDùrsؘÚВ°'EK-zD€aoœ"ôY‘!c’Ò†›à³Ù;‡‘äðȄÁÆ> ½¿fØ7ß|óW†}ûí·˜}ÃÿÅ<öõ z±¯nä ӗRÈôA¦w2"È42(30´Dè@(öƙLD ë#ô6I(i{&)“$v$1FàŠ¾a¨ðo¾ÿþ{̾Ø Ç¾D¯ öÍ ORÜ$@&le²!ÈôA™|Ãhi¡¥A‰óAK„Þ( DØgŸQFæ£ÿ Jºnm ™0FBêۇdôÝÀ?üð=Ã@…ÿ€Ùà?þØÆàÁ÷ˆ}7/ àIÀM2+†L L=˜ Œà¦ÿ©%£»nœ÷¶là c¤¯Mœ‰ÅH؄„ìC ìùepllì×A»Ýþw†ö˜™c7£§ˆýj†_`ðÄB&HO€Lß"È$30‰Ð’Y-!ۏ–Ì +hi€ %Bÿ1"@‰°7ΰ$ö1Ù AÒ£^€’–1ékòG2á½6 Fú Á£Ÿ@Sÿ: £‰‰ ûàäääø Ãá˜ÀÌ,a㠃WìfxyÌ?ûՂ “A& ‚L´1gŒ¾³@–ßð&-áí8-™UÑGСOF(öÆBÂzcÿ1,E SoÔ%P’„¹‰=“8cÒ_‘1IðGc$dBBI€Gƒ ®'N§cÐår9ÌÀ¦Ìn·[`ø;‡^™´ÀËÀMv üV€L?[ÐÆ‚LCé{„–¾µ ´dÁh +õ%DŒ–x¿%‚–}R"@‰°7ΰüÖ ûÈøª?¸‰˜tR›wûyԌIß1>ÛØ ïµqv¤±ÀHØzÄÂ#„‡A];Í^¯×…˜Û<==-b`. Ÿ×ì÷û§FQÔ´3øèµÀSb n²ÂϦ¬2Yd²"Èd…äµBF?[ýõ×-9»‡œ—´dQEKRoZRpð f%BƒP"ì3,u„õ‹õ ­Œâ¦.!ÓgN%¥C”vÝ8Ï$Á˜ô Úpû;ÂHölGâ0’kgƒG3fÐÔ>s ð›ƒÁ ß"cðÀg…Wf¬ž¼Vø…Ç + +^€L“VÐüv+20!´ô‹¦„­-YÛÑҗjhI§†–Z"ôQˆ%ÂÞ8ÃG˜CÓe·¬#TÕ9n"É8Jz~Ü(áóð®> +@ðLÂÆ$ä³=€ü‘ð^›#M‹àQ(¢Í ©–H$‚YЍF1 Xá#m…§”Þó[á37aÈä¶BzN+¤Œ LãÈÀ4fEÛq-ýd¸Æ¢%äê-EK6)ZQCKê.K-ê# DØgXÖëëni#(mÜd2´$&@I5àMÉ=  ÚuÞIœ1i|m¸ ¸Ýn§€‘1F +ƒ†GfÀC!s, [@S‡-³³³̬ [áAÈ +¯1n‚Ÿù‡ ™!de‚D]CÈÀ4är¹&† Ë1f;9/ hÉ +hé¯"´„N°@]ދВÂQKÑÒç,R„ú@(öÆ3ÂúÀÁA@UªàÉn"É} ô­ Ÿ€wÝÐIIŒggLš­ì­ì`ãˆC›‘áÃ#3FFsss1ËÂÂBœa‰D"n|³‚ + !Ü4=8øŠ +…B¾¡@ 0=„ LCƦ†–a´dÒFKèZ‚ªÊÑïà=È9x·¹,)¡%B„:&”{ã Ka}`hSF‘i£*U𤄛>2dúÓSïždâܓ„]7Æ3 “°1 ù# ¦¡A+ )jՌ‘Ñœôó¼eyyyÁšL&6o…ïæ‡àéìÐââb|pSt UxR æ¢x“gÔ¿s&‚I- IÐÒ·VgåÐÒ-}¡%äàÐ’ÜeI-‰€AK„z!”{ã ab†¦Ánò^Qdª¨J<ÀM6æZbɨ3·6PÂwß +@  + ¸'q»ndLr `c(dÿ`( + F£Q#â™5öaà‘%•J-Z@?/Y3™Ì’5›Í2 [‚‰!xea^žÃiY™†!©à0$J Cò3Б-9NZ’¡¥o¾ùæ/R´ôŽGKà +hÉ<¨¹ 7ð ¡¾Ò[J›››(}Þ ËaÝ0´÷¢Î´Ñ—‚’'UÜ$ƒLJV&£¦Ï -i%-u”¾3q~Üb÷$¼ë†Nðù|¬1 m¸ ‚BŽ`;ÆHæd2™ÀðÈÈ(iYYYIYWWWÓ–‚É!PÜËÃ7 #È4 iv8‘HD‡çææBñXŒ¥ïChÉ; ù:‡%hé„–~Dhé{-}-BKÈÁÛ"uð6+¸,´D¨ßôŸJ0ô€¬]P"L‘a‘"Lƒ!7à EAə*¾’!(xÒÆM½@¦ÏÚÀdüd’àǍݓ\.³ë6à÷ûÏ$lLDþHf´×fœ“0ƒB^¶€BNYe,ëëëYk>ŸÏY766V†8–‚ï²Cð43 Š;5 ¸ C¦Ä0 ­¹aÀ\1d` +ƒ¾0h °™- Z¡%˜?¾‚rc…`´Ä„Ã!´ôÞ"uðVCKƒ ¸‰L# ÇÓ#ÈÀ4éa´4;yDF ·ÀBK#Jhi||ügZBáp %ýuÊÌ¢%äà=„¼‡@ê¾DhÉfå7á,hÎÂ9x[Z² ´dÖGK&‚–i“ª1I (a•&%¬ú „•eG@ ††2PZYY!@‰0†a[$aÆÌ.ÊlrrRÌð¸ÄL U JOp“*dêÙÀô9/u”ðþ›ì®7á>\îx  Äùq3îIƒ †³Ùlʼ¶¶–3ƒ^·ÎÙDiÇhß +PèÐz~~~<z·0z÷³a`…aøîx´òáèçýøÅÎüvsTøÚèÖÖVnt{ +¡¥E-"´4 +kç„–Ü-9Z²@qAhéÇa7 ¢÷ BK_ !o첄ђ•CKÃÞeI-©¹, üa…†ÐG"í]·.֘X‹bÍ*J^¯· (Áø0”ö÷÷ PúFׄµ1˜DŒ3—Ë%fx4 +L†¯%€'mÜ$ƒLJV&U“vˆÜg¹× ô¥èdntŽJ& À~Ü †ç“ÉäÒ ·ë¶bFÆ$3(ßm èÝ= ÆH r Vж§VP´gC hχ@ǞcÏFàÁɼr</ŒÂÏvG!­QHj}͍æóù”Ô¶Fh‰ÆhiВkdzzzr$vldò—a¿!´ôÝ0Ôè¯Cÿ2„\–†`ú`E›pV¼ 'CKhÎ,%- ªl´DH îIPšK(aM¨ +”°Þ€’ßï×J™L†%ÂD 'AX7 æ™6†Ç Àd˜K£…±nR…L²¹. LoÇý)ђÞaJ(aG%É¥¸b „ÎQBý¦ +”¢R ”1’Y5ƒòÝ4ìZÐ^›åüüœÅH ^/¬ J/‡`˜^ ÝÝ݇ïïï‹Ãð×Õ|w1z—L£ð‹£QP×{£…Ba{ÒˏBʹw-½}Ÿxh)þ£¥x +ú¹ðÔõƒ–@£ËÐÒBK±wڂï T¾wP>Ï;IÇ(¡}Dï—Q¸¿ÀóÝHØ_‡A¸þ2 5ý¡¥C RïZ±ò›p +hI¾ Ç£%bV"dĘÔÑÉ(ᅢP +ëS(a…,¥¹¹¹6 ÃT ”`QÃ%XÙ ô™1ìíO˜ƒéDá¡&0lËÅL²%OnìM‚©I 2 ¾LJ{r‚©Ëí¸ž]½ß:u”ðþ›pF€”¾G(]Š‹p, ” óØãځR¥JØ=iÇ *÷Ð ŠöÄêõÂ㲄1’ Ðý £‡¡———Êp£Ñ¨ 7›ÍÊüõ8ß=ŒÔëõ»Qxïf SñÝÝÝÝù;PÍ Zzz|û= ¥õ÷€–²ïAé/¿´4ÿ~yy9ú~~~>ð$væȤëáä;@xc£ p?Â2ü‡Q°oZúz„CK¶a¨ø{„–F‡8´4dE›p-Y,¼Yɬà²4H6á!RÅH]º'½æ /F±¢ÅÊke¬Â1PZ\\dR6›5”ðJ()¹' ô§`ø@ºfx€ [p1“!-Œ’'n’™šd oÌak²ÒžœÌÀ¤´×%Zú³˜ºö薝ýJ?¢þøuτ ŸÌ͝£D3@‰Ûzc(ߍAл»æ“““#3›3 ¨Ò+ËýýýåéééÎ +éÑ + èi¨ÕjU‡^__kÿýöfÕøø<*£ðÊÃ(¼|û~Vz \¼‡¤Nރ□¥Ì‡õõõ¥0Ì!´Ah‰z29ýJê|ežx¥ÿû;|?(ÿ~„뛘{¾YèËa¨ó‡a¨ý»!ä²4„6á¬hŽAKȬģ¥A³”ˆË!D½“”Ü“”Þ:ºæ ëg¬Ì1P‚*Jb „¯y#@éócøRŒ3<˜”¶Û + GPȕ€ ð$ÃM‚½I2áoÀÀd`;î3w^R2+i{t·Ÿ œ:ù#ê ”Æ¬ÅW˜°@ €Ò€ (ÞÝ3ƒ¶=6ƒŽ=7ƒî,Zo-ÕjõÁúòòòd(TúÇ?þñ2ôûï¿7†ÿõ¯1l>¾ŒüóŸÿ¬nz…÷ßÁ/îÞ=??_¿xx¸xé>@Êû ­€–Ö>loo§ZZüÉdâ@¨C@:ý@=ïAô¦ÞC¹íï¡¿¼ƒÊüíL6ߍ‚\ýuPø_F@¤¾A›p#ôqIUØp3jLvÝ´ý¸ œ Ê-Jø¬I ”„€7(©ž @€ÒŸ‚a‰ Ì8ÃFY%†ýÿ&ƒ[‚À“ 7 ö&%Ȅ7æðZȨI¶'(`ÀyIÛÕûς–zñèn?#€Jv¤›§P¯€VÆ@‰€¾Œ @'Ï! ´<Д +(]šïîînÌOOO÷–———gËëëkÝ +©e<ôÛпÿýïýïÿþïïÃÿ÷ÿ÷ûfðñ£ÿó?ÿóúpSóÝ¿þõ¯ú{€VOïdÝ}¸uý¡%håcèñ=(ø Ûþþ~Î%X¶AYæmPªˆ đ¶dŸ¶ƒA琵ñ f¿~<þã{¨Õ÷ï ~ß¼‘ú +¡¥/F-}Az‡ÐÒÈ02+!´dEhÉbå]–,¼Y©3´Ô¼´¦ºd&‚ úIa$í 7mc’Òy܂{^Pâõ¥’·Ñ“È5oŸ3虰nÞ–1<À0S‚V‚’'7 ¦&2a±àÞ¥I¶׳óҟ-õ1ô=#:‰ºÂºÇƒ´²¥0” ÏۀhÛ hÖKóýý}ÙüüüühiüöÎÃ-ªk}ۙÞ{e``úÐÁ%1ÑhŒ£1‰é‰ PE¤(" ‚¨ HEìÝôœœœs~ß¿õ=ïf6l÷Œƒ€³¹.ŸË™Ù³ÛzÙëæmëÀ29ˆç€¢¦¦æ‚1ȨFÙØØX«:qâD­:$5¼W­Å§UZ S¥Tµ_wøðá}ee%£¥o  ¥DKیx¢o2nß¾}´ô®Á +#,v‰§6ÏnÏ7ÂêØZšf–¬{õ@ñ8(Ü©ÃEZµ°&³3“ACÒ©aCሖ”J„c´v+…iI"›„‹œàMf‹Œbã&ñgÚ?3a¤ˆenI\­›P?n¡ô¤ˆyÜBob¯É¼0Ï¢(Ï-엉'ì/&< âŠÇM<S ÈÄ~Ù£;˜b %.yiú—b-Œ{ÕiiÊÜ8­ŒnáÒ7= ©ë$ Jam¾ã6_‚±œ%ØÁ{’(m!Pú”@é« (•••í•WTTì—v*åuuu‡ǎcŒT§lnn>ªjii9¦>yò$“£¼¬Ó655Õh±Éa6>¨Ç×ÊõÕÕÕ%¢%hék#hés#žÙ[x¶o4–Þ7áïäwL0å·L0ÌE&a± 'škÜeaf©XX’(¯Ç´ãÒäì:\©E‹™É¤…!é5°!-ђZMA8á”ᔥ˜i)šoéŐÑ3¹Iü‰úp§ÏH¼2·XI\ԍk +À[¸$bzÒ´ +ÞDPú§‹¾ŠòÜÂ~x¼µLx@Ń'7q®&!dâr™x19!Ó´Âq3Iõ~ h‰7>gF÷Ó=Ri((åÑSyÒ †vE”` œG)JÒÝ»wÿ £ô$è¦\Î9(¯¯¯¯V?~¼N:ª5¨N:Õ¨jkkkTCŽk Z¼wT‹OkuØ®ZßÐÐpPï–ˆ–ŒØßFìù+Žñ© î-&<à7˜ñ×ñ3þb^e†u.5Þ˜az&\¶ 'žn*((ða\^ìÊc€I9õ°&›†dÖá ZؐNóѨ)G´¤$ZR(CA8Y–(E¢¥©«Ãži¤“¼ƒÑå¹h镰ÛWígúx+#q·çt&EºÅžC7¯…’J¯™°À«(Óö‹#$ÌGËDˆ¥8x⦈ÈÄÜÂì×9¢ƒ‰—ÁÄ ÇÅJKϙêkW“–„@é™Ý1”¾±™4(¹„µÅ<•A #ý.%IP*‘èc¥èÝ ”XF7%?±)5S"__. O1îb †qy”0ðë%0–Ì́ÒNÙþýûKe‡ªÕÖÖ–744ÔʛššŽ)@'”à¡f%ðè¤êܹs­êÎÎÎV ä¤/[´gϞmҁ›ŽëÛÚÚê @«#ÆÆÆƃFÐÒ>hi´ô´´Ã²k×®mw£gð¾VüŽ†¹Ì +#\h¨Y€ç9@y†¹¨¨ÈoƵ$špY#f!§ìm3ÀÌz\¸QóÑ-i4,ËQRʒ‚hI® »•žƒ–BP4—xôœÈôÏý‰ˆGsÂHn\™[tgoq7öç&ûë3zÔ-zz’XðöO6ð¢Ä.Ì÷QØ/'<Œây£Øï` ÈÄþЉî`ŠŽã%/M+ÕûCK›Ø2º…Kß(Q3%zHçРÑ@-’`ðÞ’à¼š%ÉTP’N¥jùñãÇëåäLR€}‚Œ¤µ©ÎŸ?ß®îîînׄ¤M‹÷Nêði³Û7´··×Ož3.(ÁŒKs›`M# Éj€ ™ô˜² :Ì`Z-îˆFˆTqA8¹•Â´$œ²D"JÏbZYnRÈt2ñÝ"Ó˲ݗò3“0¯®mƌÄÜxen¼Ì$¡n®Ö-zԍ—ž4ýÝ¢8wî\›8¥ïêêj6œ={ö¸‘hɄ6cWÐR©åðáÃ?X8𕭤¤d» îÍ6<ï×Ùa¶«í°É·ì8¿E6œi‘ p—k[²dI†óLŠžh€{̘œ&\©Í20eõ˜Át:r+iq[Ôr+©™[ 7LN´$ ÒR”›ºH8an¦)<aÂ-…$"Ég  J¤%úya6®®M(‰ÇHBIIn\™[¬Î$^­[Ĩ›Pz’˜Çý: +nQfA¢Sž„üM[mmí.û¡C‡¾vìÛ·ïSþ‘OùõNXì»N`ür'h}±W쀙å:Àã™v\FŠ&•hƒ5y¬0$§s”Í ó1›põîƒN£Ñè`4j-ìE©Á­R¨yn¥è´D" ‰Œ'|ØÁw9Q<[&ã™È$“DB¦—Ÿs7«?±âQtFŠf‹ÎHìé‘‘¸¤¤è7^™[tg¯÷ô›ˆ ôš iQ¦)ì—$¢D$(7ñüMB^&^LŽ—Á1'”¼kª÷ܵxµi)֌náÅLx¥oO÷ȧ?iç“ëo)=ŸWÑ0N€LàJ’© $e ÔÔÔÔ kkkk‘Ÿ={¶]ì9«u)ÁC=*Ñõå˗{5###½ZÈ^vëñA§›t˜úûûO™{zzš, ¥cÖööö#¶––– +{CCC‰£¦¦æ{geeåβ²²m®;wntáɿօ³Zå‚.uÁê¸`kNXXÀ‰É&Í“òÙqU 6’Û +²[`>³×ë5šÈ­dÀÍÐêq[Ô:؋JKn% ¹•„h)ÜÁ›­¥ Le$¹„èF"EØKd‘ }-,{fÇàÉò§"8˜¢ÐÒkðó"Âl¼þH\í?/iZŒ1àÆ­}˕¹ 9“"¦pO?ê&‚Òk!lE™‰¨„¸IÈËÄ!St“P8.bòÒôS½§ÕFà5 ¥çÌè敾EèG0öMzH¯¢Á[+Áyc”`C_JvíÚ5”Ž=ZK t\º9)çœV€xÎ)º•@¡^ ¨_}åʕÍÕ«W´~Ýèèh¯ïõñi§éâŋfÐR«ß=aÅ^êíØ_•£¹¹¹Üyìر=Îêêêo\Ÿ¹KJJ¶¸ñ0ÿÀ ‹}× s\î†é-vc&)rÃÂr]øƒ<ùhÑ"¿֔h‡!yl¸H§\h³ÀrÌfXŽÁ£Ñ‡F{£Ò™Íf%ђ‚hI®¦ œ-ÉBkéʤ!‘K9ˆ x”áÈhP$± +}M€›¢#“TòÚÓҜ„Ù¢§"Ed$.g;:# %%E¸ñÊÜ¢;“b¨uӓ^[aƒ,ÊlIt‚r:ŀL</ƒ‰ Çñ’—x½¢§zG/ŒûgÐRČîJßp#„Kß(±ÔL‰†b ÏJz>¯¡§òF †{[”~ð@ 8ÓH Ô*ïììì÷ööv){”—.]êW‡Õ×®]Ҍ iÇÇLJt=^öÁM=¦‘‘‘N3hé´´tÒZ:n?{öl£­­í V檯¯ÿÁC~‡ƒ·gϞqxè¯õÀ:WÅaÂXƒ›(ÏwãänL;©.X“Ï CŠwÀ†\v˜ÝŠk¶X0—Í0½Ñåri °µžÜJ:^Ž¥,ñzRBäDKA‘†…GFS‰G%ÁžGžæ&ž¿‰C&AZ +‹-ý=ƒp/+ÌÆë!9FJJ +¸q=“„Êܞә$FÝ^Gá@X”Yà‰ÇMё)ºƒIˆ–¸p¯—@¬©ÞÓZe&-*_¹î”A)DK1”¾9‚¥o¼\3%ê:I#³‚F‹Ò‡ ò6 ,â ÉΝ;ìÛ·o(I(>}ºUÞÕÕuFÞ××w^ìéU€T@¡‹jÑ°æƍ—´7oÞ¼¤ƒ\Ôãå ô™€QÝfl|Î:<<Ün-5Û»»»:Ϝ9Síjmm-w766­­ýÖsðàÁϕB…qÛ¼"´4gsÆ앾 õ`͔у{9 Ï»ôÞ@ºU‚ßA ô=R©d +(˜Jýýý= +Šº)GGG/*AA—Uà¡+àÑUí½{÷®ê £zȈñîÝ»—L@¦A Xª× +Z겏ŒŒœv µ¸z{{¹;;;«ãÚÛÛË=MMM{âëëë¿IÀÁ?óîß¿ÿ#ïîÝ»×ya¬ïxa„˼0¸…^Ì. @ñìx\Fš†ä‹›7o^‚æãvÁrì\³ÅNn%+ìEOn%­)äVz*Ç£%9n®’‰Œãæ +ÍSP„½0Ñ1‘bÏQ„6ÊnšŒL  В4- -W÷òû©Fù™FŠfãº"qa¶R‘ØӇc$ölŠÈH|xM¹jÄË>¶`“6î±ãkgØÁ)×àà`c\OOO­çìÙ³ã[[[KðÖÔÔ|‘XYY¹5±´´tCžòï%áüV$Âô'bb)ö¸r½0©Œ„¥K—úãqUÞ8\_œ–ãtÂh¬Ž””³-))É`%·’ó Ö+QBn%U¸o벤TÂJ‚B´¤’“È]˜LbŽs8ö­é' öl˜*ú Ð§2ˆ.(ø®VF»"ÑÈ°{uø*¢´ˆ´ÄUåIÿ–´4cFší0[DFbOöâú#±¿é„r¶ce$¡¤¤è7љôO¡%vyNnŠŽL3˜xá8!ZŠ˜¼1՛W'ÔF bӥ礥èÝ)_*-ÅJ¼Œîzp͔8PZMò=¯1‚[h'ƒÒ¡C‡X{€ (I§‚’œÒØØØeå͛7GUwïÞSŠÆµ=º®{üøñu=d̹j2Xîß¿ÑvçΝ>;hé¼óêÕ«îK—.µÄõ÷÷‹?þüá£ÜÛÒÒ²;ñرc_'>|x{Ryyù&ßîÝ»ß÷ÁNWù€ìo&aN™Ÿ„óÎOêeyÁÞ© ˜ž’âa>ñq˜Á\nLh6's+%''mäV²0·¬D35ÇÚQ²¥NT*%LE¥€¨å!ÑÈB"LFaÆ Àþ‚"ã >5…¸)(2A4S‘)HK,Nš’ ÑR¸?¦ (I^%PzÎT¤iUüÏ8Ì&”ŠÄõdO)®öŸ—³#ELJšVÀ-Vg’Jwyù¨ñšÊô‘Iˆ–":˜bH^Š˜ê-qmfLKB5qƒpÓ§¥9˜Dž§ôM¨G€P3¥P×ÉeJïÐð¬§qc ô¹–óR %ÉÓ Ô)앏ŒŒ )ÆÇÇG”·nݺ¦ºwïÞ¸ŒtCóäɓ›ºüñ¦þ§Ÿ~ºaÄÿÆÍx犯^¶–·oß¾à¼~ýú9÷èèè)Ïŋã{{{k¼•‰mmm%I'NœøÎW[[ûyòÁƒ·$—––®OÆÓbu2,ñ­dÜB,¬Ð‡¹'; Ö”æ… ùpi ñ˜ÁÜq0»‹ÜJNLw&ûT·’‰ZB –ÔÁæݸ}j¬D­Ä «V°0‘3~á<@!׃"CŠLRÜz&föQLrڎÄ('n"1ȱ½;ÕÉq ­œ—hIN´$ŸBK +FK²Piž,LK“ZŠ ¸•Þxhéïfã¥"qéÚì)ÅõGâÕµMŸ‘„’’"ÜDgÒ?O^>Qü3dúÈk8î9i‰W±¯éҋ ¥—š²4cP•?ÕLi +(Í·çf ´Ž†ì#ÕÏß` .a TI T; ”zzz(õɯ\¹rQع¢¼sçΘêÁƒ7ԏ?¾¥ÝÖýüóÏ·õ¿üòË-#ä†ïY€LWl ¥a¨ªß¾:766vÚæjNÀNë½à°ª$hŸ¯¥¥egò±cǾð>|x«¿¼¼üCÿîÝ»ßóÃ:Wøau‹ý˜bŠ’qö9>_FlÈïŔåMÀ_ùqž¼¼!_Єkˆˆ' @&á Áž­LäSijۙ“ß5*°+ƒ;Õ+°{]ð¸0VFijŽ–‚™S!ZâzL¦¥ÐÚ+ÁüîÈ´ôb^,#E³Eg$^˜k±-”®Íõdñqµÿ¼œíX‰—”4ý€›J¢ˆ"(³L±†ã¢'/q´$”¼4'´knå“i%x¿0·RDPzºG€:˜Ñj¦d ƒÒD3%¡®“SÚs¿M㱎žÙ ”>#c˜¥ƒò@©@©K644Ä@i˜@i”@i\õðáÛê'OžÜր‘îè~ýõ×»úß~ûíŽrˌ—×­øàš ´tف]wïÞ퉻qãÆÙø«W¯¶z‡‡‡ûúúª“:;;˓ÛÚÚvû¿N©­­ÝžRYY¹)gµ6¼*Føf +Ìlžv•— kÊôáOø”$üYŸèÅõyâ1«¹<˜älîôôt‹VbœäV¢ µ ` –4Á5ápç4jX‰V…V«dÀBŽsù0çOˆŒ&ðˆƒ"ìÊXMŽ™ØÎÄlb%±(𠋂¸)ŒLB&vÈ -)ˆ–ÌÅEA¢%%GKáŽOÝħ¸•$|ZzYn¥—ŠÄ ³=gÅ?—ŠÄ…Ùx©H#±gØ c$љ$Š(3—AKLb ¥R½…ÚÌ-E_'.Ör¸ëVz&(=µ<.J¬G@Ä®“!PšGø7ù ô#ìàۈ $ R¿|tttXÎU‚x®«=ztKýÓO?ÝÑüòË/÷tÀ£{ú?þøãžrÇüûï¿ß²â½q;hiÔ  v=xð /îöí۝ñãããmޑ‘‘Iƒƒƒµ¾îîîJ?Ž¶7¥¥¥åÛÔ£G~–ZUUõQÚþýû×¥íÚµë4XâÒTØڂ x¾WH† ¥ú0eù1Å{a/îx˜Š=ÎÜJ&r+&¹•Xßn¶Ê D«¦è4$jb‰’9z˜Ë‡ÍÈ ô +ákVù(rÈqÃrìÙÉD#ä‰C‰˜Ø•ØئÄ׬JB&%ögVbÏ&%ŽaT²ƒ-)´q´‹U)B´ÄzȧÒÒÄJuÜJ|ۚëŸ9f¤ˆÿÃlìÉ=ÌÆëŠÄ-Õ1‰×g›×‰«k‹ÎH±&n‹Œ$Š(³.ÓG¦Âq“—bHõžcZŠÞ˛£%¡æ¯ˆ[I”ð/ +(ñš)E%n“ð‚o4<›'RIIÉÞgƒÒ%9@éªâÞ½{7T?¾­ÝӀ‡îë€Gôÿú׿îÿüóÏ{füï¶ïÝ°ÿúë¯×œªËn|cÀƒïžO¸yóæéÄ«W¯6' ×'÷ööòŸ;w®,õÔ©Sߧ?~|Gڑ#G>N¯¨¨ø }ïÞ½«Óa˜o¥Áà¦Å SaMÙ~ÌQiÉ+V¬HN‚Ñ$$â"Ý 0‡Vb%·’y’[)!!µ `}»uzˆN‡›¦×ÀJôjˆAŀ…=Jæò!ç82Âüë’c§.n¸;(˜ŽÝÊ)âRá&N6v¨ð5» +;°©°+‹ +{6«p “Šf{½ŠhI¢%–>¥ +WåÛ>…iI&@K<·߶æ²ÍŬ0’PW¤R‘bh¬k˜[ΖKEâÂl\*RtFb¾u¡œíXýHbÀMQ^ˆÌ¢ƒ)†ä¥AK¼,o^wJ¡u⢗ý:n¥™×uR¨=7oÁ7J›éAŽqû”†ûÛ7¦‚’„J/^ì—l.Ɂ8×÷ïß¿¡|òäÉõ/¿ür_óûï¿?ЁŒêÿýï?4Bî›!w­@¦[v|:î-]qÿøãCžô$ܾ}ûLâøøøIßå˗ù§œ?~_j{{û䦦¦/Óëêê¶eà„>Ì(--}/ö¼<V·(3NQ¬)'sT†äO^ºt©7 þÇy ñ°[®ÞÂÜJÔ[ÉH½• f`Š!¸x.n•AL1ha%F ±Šš|¼1sÿþýk2wíÚµ2¦·$<^œkÊMÃed¦ÀrR’1—%ú-ZäI„•¸Xü¥ucn4;@&ê­d´àÞM˜HL©F=‰7ͤa¬±¨X€Œ…Ê(r¦à|FSÈ(^&(1ÿ2ñª`„AQãLÔx¯a‚M<|íÅȸ´Ø‹S‹ýٵؽMK´¤ÁqM¢% ós±€ ђ:Tš§R…Ú>)¸µWÂëúJÃn¥àºpaZzC–fËfߘղÿiuEŠ5iúa6^W$¡T$æBJEâõ|aŒ$‚’(¢Ì¦Ì˜–bMõŽµ0.VZê À­|­ª+T7“ Ü s+=”žjÏ}“h ´v*(}3 ”êêê&@ ÔÒ.½p᥁0()™©ï¾ûnŠö’”¼xñâø$.þÆҺɭDÝÌÔ[ÉD œ˜Ì˜HMFˆIB1ë¦@¬j#<¢(™SIxDá³8eÈg„"%¦ÞD%P(IÓKRáIjLÂ>’$MX´D->õj±]‚ßðèðÝ8É¥Ãþœ:ÌçvdÕá¸-ђ–ù¹B´¤Õ`x5Œ–¨í“2ÜM|b¥º0(É_(½ˆ’¶è]‘fÜX[(Ì&Tñk*‘¸T¤çd¤’’DFE”¹‘™$/½|Zâ­ÇþPäh‰—àÍKY +ÂŚÛ=ÇÙJ/ ”ÖÒÝÆ(l%ΣÄ%0 J·”î©ûí·‡Juýõ×ðè‰ñÿûßc3ä/ï:ðÁM6‹ÃƗãúé§þćž÷ݹs§Ý?66v"õòå˵iýýý•]]]{3ÛÚÚ¾Íjllü4«¦¦fs ²²òýÎïí,Øä›Y°°ù™°¦üt˜OVŒ&5ôû’1É%$͟?ßíÅ<ÈâoÁ´î`J¶lÃlÆlj6Â@,Ü*«Ž9u v Þs¨YbøÅ­Â#˜™È(Y…©7Yüj¡_ÇôkC’¬Ã{>’$=¶KÔã\ôøn¼'§ÇN]zœ•C£ÙôDKzX¬YG~.Š +êµT+Í 625ɜ %%%,VF´$ Ӓd-…ãoB´4›x4Û%m3îŠkcíç ³ELEJמFn¢ˆò2dÃq±ÆE¤¥è‘8®;%oå-ELðŽ„›·Òß”V>( 3P‘ß¾}{Lι¥ñL€ÒŸþùX÷Ÿÿüç‰xôÄôÿ÷-‡6¼¼çÀ·\ÿþ÷¿Çâ~ÿý÷‘„Ÿþy ñÑ£Gç}wïÞ=í¿~ýzSêÈÈH]úÀÀ@eÆùóçK²NŸ>ýmVSSÓgººº8«uÒÒÒ·0Ì¥Y°°ù™˜ò3>üðÃ@:þÊOKÅeùü°’&¾8£ú7GÅæÝXà‹¶a1c6µš` V&W›Ž…À(¦aID,§ÛÅ«XH &•¨bx ’‘ +—¢Æԛª†ý¥iòóóÓ´L0 §é ©z&x/ŀM’ 8ŸßH4b^#æîx#F'Έ³r‰–Œ8®ÍÀð9»XË8gõy %Öö‰µWWª ¹•dJr+)Ân%y”d³íVš;FŠ5]{¶kÇf‹Xñ1)zº¶ÈH¢ˆò·”¹K^š1-ñú-ñVÕeòÊḔ%^.b%œ[)b¶Òܹ•^1Pj"P:”T ”À>(ýH ô#Ò¥G6È}ÇÿûßÛn€Ò¸ç?þIøå—_“?~ܝ|ïÞ½Ó)7nÜhJ»råJ]úÐÐÐÁÌîîŽŽŽï8ƒÏ²q.e:th]vYYÙ;Ù0ÖeX؂,RA&,'ŽkIKÅԖìÇtç &*ár],þ¦±»0iÚhÉ\› ©Í.±™pƒìˆCÏB`7%y((>˜gÄâj!r&%mÓµg'ée…ÙDFE”×FfÒtI(q哈 Þƒp1¸•xEpB œÄ›»D¥è ÄғB ¤X×: ”é2S§€Ò|ºWKéOé· >×Ñ}f ô¹cù¤¬¬¬T$9(9vìX}”Ν;7J—/_T()§‚’6J”;3‰@é¾/ï¸ñÁxlrՋ‡“~ùå—^ÿãǏϥ”N¥”Žg^¹råHÖàààìîîîÝ9§OŸþ:·¹¹y{n}}ý¦\àÛÚ\œß*¥7s`Có”Ì=)ôF]' ”|ÁÅL` JñX„Ç ñ8pâm,’HÕg>#>ðX%?¶Ë ¢µ€vŠ ©H3›§ƒÁ-ÐÃô0Ã.1‚‚Þ4á&.5Ã:—ZôKm˜fß´C–8 ‹]xo¡ŸÎÃvEqøFßÍõ`ñ+W®ÌˆÇžâ-ù<À2o;Sœ•ËÈ·;YKŒ¢)¼RÎ³Õ˜0Ð*#ø^©j(È­$×(‘[IŽ¿M%ù³A)2-Et!M‹‘fRöCºö´R‘„Âl#Í]5Û´\H"#‰"ÊßWbH^Šµß’Ð:qÓÂEw+ñ²•bHëæÅß^X¢RDPâò¸(©éŒ´tn ”LDwV:}L6Nò–y&R]>…$P bݬwèÞ­§û¹…¦ŒÂç í÷’}ûö1P:$e ÔÚÚÚ,¥»wïŽ1PҀxîjÙR¸JÁ~ÜÿûßÿYG(›KO'Pº’øûï¿ùÀWüØÁÙTìêdúõë×2GFFögŸ?~WN{{ûW¹MMMÛrëêê6æ\%mhh8*=uêT‹¬³³óŒ¼¿¿¿G’™JêǏAIPº\ +—­ð2z임ÿÝqžnӓþüóÏˉ¿ýöÛ`òO?ýԝòðáδ۷o7gŒÍ‡Up ²ò‡œ¶¶¶/r·æÖÔÔlÈ­¬¬|/·¤¤dEÌlI6Îy^V’Ïú(ñ@É%o®9!ŽEµ@K^Ì"ÑƊóYS#jodd-°]@Ï ÓlËBÒbè0Ã.ÖÃàÞÔão`„+Œ`³•fL©«,¸}o[qoÛa¶o;1¥®rAVÆA–{ðÞ²xL¸KÀM ½0åy‰`þÂDLѹ‰Øi »OOÄ9§$✓¼ ý„Ê«ŠÈ9Y§L7 ßì. _ ¡µ+Ôfð½’ÜJ +Š¿Éu™–‹¿E%”¦ÒÒó–ýÇÐ>2ÖUÚb-iã1R ]‘¦¿~­fEQf(³MKƒpÝJBÙJ\×[ivâos +JÏ*xã:p d ³4Óäc£ÓwєO×Å@).˜R!M* Éßö%k¼KÓÆOÜ⭌’]»vý Ù¿ÿ>iuuu•ôøñã ÔÕÕuF>00У PR^¿~}D¥›Z€ÒJ€Ò@édtŸõã6À{×=\Ô-œž”JyÜé·nÝ:‘qíÚµÚ¬áááÊìÞÞޒœsçÎ}—ÛÚÚúy.NcKî‘#G>È=pàÀ»¹{÷î]žkZœy«8€“Ï 6œ¤>J©Jþ(%%2 hQ²´‹êËì #Ÿ â§~F©&0u†‘ɀsõ#a†]¨Ãþ˜ i™V·Üû[e½cÂqW[`¢ïZöïÙq.ï9`Àïº`Ê«ã ïxðrU>Xá…Q/K„Q/IÂ×ú°ƒbv•ïÃN³}°âL¬85 ¸ïK‚{qB¬¯[€ÅF °˜Ý`^£ô ·'$$h­À +µ…âo&%,@®ƒ’&”¨$ J¼øÛTáãÑÜ1×)†²¡’¶èéÚ±¦" …Ùb]¿V ³‰"Š(±ÉìÐÏ­$„‹îVâŠà¸ÞJBñ·èõo1$*ÍIG¥oÏj¡”|4Û0PʦTJ‹È߶œÜoïÑ܁¹âC nñ6 FáKÉîÝ»wJÊËË÷KÁ%‡¥Çdmmm''Ò•+W&’†ÒÏ?ÿ|Gÿûï¿ß3þùçŸ÷̀¢û´¸Û=;äŽ3ìLŠÇ§W¼\Ô-”žÔLO=:Íò¸Ïœ9óM.Ëã>vìØæ<ê ‹S{''¹,æ³03XQl#7—‘ìÌýÎ;ï0PJNbÞJ0†D7x(É ‹ðÙ!~+$•º?fP3È,#1’ûãÞL0…ÙtŒ‘0¯®0`J}ۈÙtµ ÷ë=3Lt­û¾ ¶û¾¦ü¾ gõ¾6¾Öy//W{ñÁª$l²Â‡—&ãk‹“±ƒù~Øs¡'žë‡)gùq´´ä•+W&û€û‰I\_ñ¼¼<{< Á‡¡4ºùz‡×ëÕÚÀj ÌVeƸ+Œ ”ŒF£L7%þÆ%ÁD¥è 4wŒCÙô’6¡tm¡®HÑS‘æ$Ì&ºDE”§eú5qÓª„r+ñŠàx½•"Æß"Ö¿ 5 +ˆµQ÷œ€Ò´ +ބzM¦æÐßá˜u‹è¾,¦™d1æâ΍Ì ŸH0_IöìÙ³KràÀriMMMµôĉ ²ööö“òóçϟU ö( ”T›5çÒ °ç¶t׺kݵ–îw ;“X­[°)u»sçNKÆøøøÑ,^zÒéÓ§YzÒ'”ǽ1˜Ç½oß¾U¹\Á ¤0 3]Nf¿Ì4Zë-…@)vÀ@ÉGI?I*¿w/X°Àç¤&vjŽmem²‰‘LØ$‡)Ÿ1’~ +#½EŒ´R«{ǀÙô=#îÕZfÎuXìVXñ;,{ƒ¿Ü8µ<õ ÷½5Iø5XíƒÉ¯JÆ-^¿™‚_˜ +Z*Nݼys~*Î>Š£¥ÓÙûýSÚeºAúö®ÅÛ5¹ùz'ˆBk «­0[ÅßFX€Ü JSãooLJT +ÓRdPz±Œq•6# -bËKמq*ҋh)2’(¢ü3%VZŠ„r+ ÁñÒº…âoÜÚ&\ýo¸X•^(M+=)zg€§[(MZ½DB«—HpŸ·K0_KöîÝ»[ZYYy@Z[[{DL9.°´Ê»»»Ï*†††.(GGG‡(i”´¥ëz€Ò-#@éÒ+ èŽ´tË ¹A‹»qΤ‹ÁZ·'OžtRÔ­EÝ2¯]»VGQ·ƒÙ}}}¥”žô}î©S§vðӓX7KO +¼e†:d¦ÁÒR0K¦ø”C ä‹[´hQ25+òSÇTþ—nÁ{™fXI¶‘‰õ‹Ô‡JÚX¬c¤ÕL¤kŒ¸MëL˜9?0Ãb?´Â”7ـB›»wïÞì­ÛWRR²)ò¡òAÞ[ç|®ñïÚµku +N|e*îó²4Øøâ4ìo^:ö\Žcä¤á2Rq )©˜í“h]ßødœ©; ìðb­ñ°]SlWïJJJÒ:”l0[Åß&Jà’ (i(]ž”„Jڞ“‘bm)Ô)zÙ¿#Ś®-”Š$6DEQ^¤L+C¶’PœPü×„’WÿC¢ר{úÝ3¥X£n±æq ¼qÂ-”$ÔkRBM¹%¡¦Ü{¥¬Ö×××Ț››Ë;::N)zzzÎ) ”TJê›7o^f ¤#P2”n(Ý2ÿë_ÿºM t˹á¢pãÀHWþø㏠3É÷ÓO?õP­Û™4ªuË`µnÔ€u;yòäguû(¯ººz=¥'­ÎtL¤'Á@XzËãÎNǵd¤RðÊØ ‚’WšÙ4™@ÉØ!iVb$ZO$ÛÄV!F2„i±>k 2’ÇXkÀºÞÃüЋÝdd}lÇ Ûê,++ÛêÞ·oßǞòòò- !›|û÷ïßàǧëR°Ý{iøÆÛéøîò ìåÍ \‚ ˜wQ¦í\rŠ±èa*-WçK…'øyn ؑ˜——gMÀPš<°]ƒÛçói  X¬²(™ar#R8QIª‰”H$SåÅ1RÄö‘)I¸J(Èïa½Á)Jiv¶ÒÞ Ðl¹&lWhÀ7æ#¸'3v¿VûûÀ€Is£Æú‘yçΝ[ÀkÛl¸WÛ@¡í®ŠŠŠOã*++·Çƒ1?I„lõA¶øñÞ¦ÞiØîýôÒÒÒÕ ¥•™ø]Xš…ëX”EùèY˜±óh]ß@&¦÷´t˜rrڊ+¼)°â8?øÀéÃZA¦xØ®!l¡sy½Þ P‚Ù*(QIN‰JOÒ”D¥ PšJK‚ 4wŒ±}d ­‘"–´M?]{NR‘Ä0›(¢ˆ2 ™±[)bo%Þº¹ÌÁÎëÖ-Ô(@¨QwtPzÎÒ·é‚RìΤçJOʦ /û] îßÊãž(x|/Å|^*=|øðAYCCC¼µµõ„âܹsmÊÞÞÞNÕðððõµk׆4·nݺ¬((J×Í@¡V€ÒuÈhܹ‡—Wâÿý÷á°3©;Ü8‰Ká® Á*&Õº:uŠÕº}œÇ‹ºÁ®Þ Fݨw&KO‚ dQzRºóeª@)‘¦T["x”FK«eØð2‹V¨Í1c“#6žgÀ×#-¥º¶º7®Ö1FÂ1#m2ÀN·˜p‡¶™÷îÝû©Ðö™´Ã ÚáYîðTWWïH8räÈgIíÉx¹-wrK0oc:.a}&îîš,\ÇÛß[ü,àbæÑÅäp1ÙY6lHÏĹøÓAÞ4œi\ +י ¶%a,Í  _çNLLÔ8@*ÌVi!P2(•Â Ì赞|CN" Ó”8<š#źT[¬Œ½5ÇH±–´EO׎¾6›fEQæTb %¡l¥âo1$*qÝ\£îˆݼ֓/¬GÀìDÝ¢§'Ӕ³„@ƒ•Ì)k$,³Æ6ÊãþRJoRLþûd˜è«dÀ”z9€¥IÑÙÙÙ®ìëëëT]ºt©W3666¤%PÒ(J×L¥q PhÜ(w®¹!£¼¼ìÅCIؤ7w×uc“B)ÜUٔÓÝݽ+·££ãkªu۞ǫuÛ³gÏ[\Ô-‹uOÂ<˜NéI”Û“îgöԎȋÑO‰Ç¼šâÆ5§:!évH¦ä‘mƧù&lWddː໬?Òr&×wt[¶lY£#FÒã@› 0̏`¤OL%%%ŸY;_X=_ځG_»p¯¾Ž«­­ý:¾®®î«Äúúú/}ÏýOSñÁÖtlòQ&6ސ…¯½ÀVg³VP¬¹8îý‚üEP˜Y<'€1ÉȂ=û3`ʉé 9O* Áé‡ے0”foff¦!¶«sƒ74Îøøx• f«´Àl唨$ gtK)£[ÂetÓÒoO‰dªðÛG¾TFŠµì?â"¶BŒ4“T$1Ì&Š(¢ÌÌvü-b¢’P£n¡Œîˆ­'甄h):#áŸ7q¾´v¾±ß¾uà6}ï}ïÒ}Ÿ²ü.±±±ñ›dÈW)x¹# lÏÀ&gÕÔÔl +€–Öçà¿—ê÷€¦Ksñk°0ótQÌ;7gÀ”Ÿ’ HÊÀ™zÒ@ +®”yóæÙ|às"ՏáÕŅAÉN d%mDP +Ó”„ZlÏ1#ÅÐ>Rˆ‘b-i›Åtm1Ì&Š(¢Ì•ÄZ½þM(Q)zF·PëI¡Ò·X{Ì”ž–i:“pOÕºñ¢nBݓÂm&%O§'}&Å |+---Ý+;tèÐfö#òæææEGGÇIewww‡jpp°K322Ò«Ò3PzðàÁӓ'OF-?ýôÓU@éªd4ꆌx Ã^0Ò@>½Ìz&±æ’”™”=ïÏéééٝK)Üy'Ožü4¯¡¡á£¼#GŽ¬Ïc)ܬÃ$׊;T떓NQ·ÔPÔ-¢n©uK‰¥Æ#¹ ¼Ì²‘r, ܌p3„n+u°¦wu0®u:L¤u0Â-zØîv¾ÃFúÊ hûÖR]]ýƒ ·Ó +Úåíö455íòâ†íLjiiùÞù6/¿Lð}ž‰‹ÙÀ=ý(‡Å)á*¯¼¼üí¼’’’·òpŒEy8Zq.l|¸R¨QXŽ+.­ª .œQ ×ŒŽŽöé®_¿>d¸sçÎ%#@iÄ Pºb +:EW\ ¥‘8Èp^&RÀÍDz·YÏ$VæFΤ¬°3)‡úävuu}Ÿ×ÞÞþE­ë–G)ÜyUUUkó(…›ßa’ZqgP­[93…¢nÉ\Ô Ÿê!PrCҝL;ܬø ÏütÀmÜVSÀí} +¸}¨Ã-Ù¢ƒa~¢ß³gÏÎàkceeåwf0ÒN+iì³× +*qŠJâ[[[K¼§NÚãkkkە‚ÿý†÷¾ÉÀ§_dáŠ>ͦ„+–™N%|ïçc«óËÊʖçãږäãÚæåÁÐór1½gåà„R(_L9>gïJ=ØýJ^%l7JJ¡Ò7Y¸ôMJÝ JT¥ -Ñ’9f¤ˆËÄÀH±–ýÏ8][LEEQ^ŽL+Q)zF7×Q)†Ò·çì0§ ôÔzí±9“&§p‡¢nv~­[„¨Û›L6«$¡îI©{Ò'RÜñ¯¤‚²PzÒ!9&õ:fûÊsçΝRõööžÕ€iºµ ›>=8gÈâ6}.[@A#v€ÒˆPtÙ <Ž‡ yñ²/‰ÜXöv¨gs&ÕXfçL:{öì7y`‹Oópð(…ûƒ¼ŠŠŠwÉë²"æ³$'œÂM&ƒÅôisVë–æ EÝR)ê–‡ëMsAžr&a»yÆPÖ)‰ÜÖhaWh1‡nÖâ–|¢Ûµk×çzÌלÆ÷Fä.3i¯çWfonnÞçÄéîí?}úô¾ÄŽŽŽ²deI +þ·;ï}Ÿ‰O¿9?ÏaüGYWùµµµë :ônAyyùʂ½{÷¾Y€_ƒùù°öü<œF ó~Z6ʗ…!KÈÀÙ»Ó`Åv?ˆÂâËÎÎ6zÓÓÓõ ”Ü •”¬´ÅJ“ÜJ$Ò°A‰Ã£ËHÑ[ló)†²!FŠØ9RLEEQ^ ™~¢RôŒîi×#€=¤Ùã:VPŠÞu2ÖuLbe¤3é©27n]·ˆÎ$^­[h͒§¢n˜S>’bêøTŠøFÙ-;xð`¹œÒ“”ž¤loooRuuuµ©ûûûÏj/]ºÔ­»víZŸáæ͛ƒ&% @é’  tÙPºì { C þD0҅`ööƒNp²˜3)[À™”O0‘O^—|æLÚ¿ÿÛyäLʅm, +¯ëöT +7Õº%Qԍ9“âi“œIx9áLÂ&Ep[v&­¤ +·wµ°¦uZXØ&-¬n«Æú™·ä+=Øñ{Îe·ŒTjnhhØg#°ƒ"+\@¡Ê8Qex²"©³³³<²/R’ôەdú6´ôe0=½±±qK.pCAuuõšB تÂÒÒÒ¥…8ä‚ÌÝù°ñìÔÂÖ¶haŽŸj÷ìÙó¥”öþСC» 8¡R#©Ü Fª°‚‘:psª\À£*0¯*·éPROOO¥r /Ë2Ο?¿' ›üÍêøðµÏò±ƒ­ØÕÆBìtmÐôí¢²²²e…»víZX»/,ÀUæäá¬ÒsaÔÉÙ@[o&Lٝ+v¤Y’§€’–z¨°€§@ –"ÕÂl'@‰ÜJJ2¦ (‘ÈH¤aaŒ$!F’¼,FŠØb;†ÖHÑW ™mFzùÏSQDå5”9%^¡Uß"vŒJÛs??(ñ)öžIÑ3“x“B)Ü&—áG‚igR­›4u“…¢neò#GŽT€Uj• –ã*ðËI5H¦C{ñâÅNݕ+Wz àœ~ÓíÛ·-÷ïß¿h{ôèÑExè¢d4ä!FJÀÿú’ð^w2>=ÇZ¤ß¹s§9óƍÇW¯^=’}éÒ¥ŠÜþþþ’<ÀÄ÷ù§OŸþ‚b[(mcþáÇ×æ³\gœÚ2* +[”úpS?€¬ðr%©S'¥z)ꊺEw&qÙÛïi1î×À¸6k`uŸh€_h.ßjj»ô¸%¥œU¹±©©©Ò Ø©²{ª5.ðPw¨ÆÛ××W©òC¦õöö–gàƒÒ[³´ôm®rGÁɓ'·666n*ª««[W4}§DöVÑîÝ»b<Š +p.9ù˜ü3raÔþlس7 ×—˜p¤[“aÀ¦DÀ°žzh㞥`3%J:JäVšJ$r‰4,#I^FzÎÖH"#‰"Š(g¢¥XA‰=£7SŠJ\×ÉJ11¯wÄ%ÝX™/3iŠ3iR +·„¥p³“6lø@‚‰e‹76Xë&+--Ý#gQ7Ì݇‚zŠºPwuuÒ`Þ?£îÒq.;ýf`Ï 4d + ¹ECqÀ£xb¤D¼ìñ±€ËÞ¾wï^kÆ­[·³ÆÆÆê²GFF‘3i_8bW>âë|àǧ ‡ +jkk?(À¹¼KiÎ+ò@-Kra ósș .ܙäLJ'g[®„ŸÂŠºqΤ§2“ðÝåagÒûL®5˜H·jp7>×ìÝ»÷ (m§¼V¢«¯¯/7àÔÁŽ‡Í`¤©ÎÑÓÓSïÂÍ9ê¨÷ÖùpY5~Èá4¼W™ ÜÀUîÍa±Å3gÎ|Y€KÝ^ˆ[üQèk}1Žñn1 uy1Ž»¸¿ Ņ˜ãsóq©y8IÆ-1 —±œ%Œ¯)‰@)_M=”Ô#@1©™èFªçL€¹•”„B +’I D/¥SI2­5m_FKÚDE”×C¦J\3%”؃1z×I¡öÜB Ä[Çdv|{š–žÅH1do‡œIægd&1g[®dÕ–JB“‚)ÜRÌ)Û¤ÔaR¶{÷îd ‚R9Õº)Ž;vDIQ7&õfuӂÎê._¾|ÞÎé5ݼy³ßr÷îÝAۃ¥A7ÈhÀé÷B.$‘&n,{TÕDΤ£äLªÎ¹téÒæLÊ;“ +pÈm8øFJÜY[px;à°,œIÔa¨8c>áLÂHg².Ü)\îP㤠3‰¢n™¼ pÎ$ÓTg’–œIL³h0¯~¤ÕmWïÚµë+;}û¾×ÕöjkjjöëŽ?~Ѐó«6âLkÍຣ60RƒŒt܅›sÜsñâÅ/.ë˜RŸ9’†÷ª2ñéKÂÂ7v2&,~V„ým)nhhØP|äȑ÷Š+**V—””,)Â/ļBX{^N-3h’ƒKM à<JÎTX±ÕÏ@ ¬O’ÄJäV +‚p”HdŒ‘è=éTF’Ì1#E_ÎVd$QDå-Ï J¼fJÓ%Þ:&/”¦È³‰—½Í5àŽèL +•¹q™I\?€å“œIÔ8Ijœ4‘Â]YY¹ŸR¸)딧NjTcR?©éíí=­£¨›þʕ+ÝÆñññ^ó­[·ú­÷îÝp…]¥8b¤Ho"i"àFÙÛéÔ + ß8dÕ挌Œ̝êL"˧…'Nœø¨°®®n}!+«¬Èµ,ÉcÎ$L…ÙäLÊÂHgepkߒ3Ér&¥°¨[8…;Ë.s3O-sã9“Ô°°mj܍j܍oÕ ´ÝðÚ>íÑ£G+uMMMՆ¶¶¶:ãÙ³g™ÁŽ6°O“×Ñì5{pYM^Ü¡F¤!R—²¬Îd}4AKûrq'w~[ØÑѱ£¨µµuk1ìÃbÜö5ó€e+‹KKKß,ÆïǼBœP^Á¶mÛ²òp½)98ç¤.Á“ñæ›o:Ó`ÅV?ȃ’!J>Ÿo”`» + lWn¢Ò7lWª£ø%5¹•‚ D"'‘1F"<’rŒDÖ.yNFâõGšFšIk¤é—ý¿ü'¦(¢ˆò“(IA ›DIJ +¸ 5àNLLœè™Ä+s e&- g&Mô9“¾D¾—íß¿¿„œI +PAµ²¹¹ù¨êôéÓMjL꧴ýýýgô`.ÃÕ«W{L7nÜè³Ü¹s§ß~ÿþý'@iÀ 2ꏇôz!Á€›ŸÜ°É©ŒÛ·oŸÈ"gR6vp8—œIyØé^b†ï +ˆ +[ZZ¶;vìÃBr&’3©À²,¶±0œIÔ®:­‚–IΤtL¤i©ÜÚ·agÒ¤nr&…S¸‹LážI:*sÓÂ^‚Î$5Lj‹÷)9“¾VÐvªj¥ðK…ØxX¦©ÓŸ9s¦Áˆs>a#µXÁH'@¡V7 ¨Õƒk;é½víZ³r"/¥ŽŽÖfb“ªl€fy.»èžžžï [_·ƒ7ޝ‡C®*.++[Z¼sçÎùE0ùü\tVø 5 J¬™%›?ÔuÒ@]'ƒ î:) JäVR-)‰‡$rc$²2)¹8F’Dg$¶4â´zHÎN¬mvIt!‰"Š(¯¶L¿ëäŒA‰[ð-VPâVÆ}~PŠ‰‘b ¸MÎÞ~ºw*­^Çz&M*s{#Tæ693éigÒ>yMM s&Ւ3éxЙtá…v€àœ~ddä¼qllì‚ùæ͛}Ö»wïö;îéÎÂÎÎߊÚÛÛ·755mžW__¿netϳ.+¯-(‚Ý€hù€„´\j¦ÀõÆgR×É´ بë$J¬ëä(ÅÅÅ)¬°]¹‰Jß ‹Eª£ø›,Q-)Ɋ$r²2éTF’¼Œ$†ÙDE”¿©¼PâVƝ(±9`& ¢%IP¢1Ò³*Üp4Ã3n¡ìmր;‡³+"çÙ"jC³Œz&½3iI7VæZû6VgRgЙèµÜ¾}»Ï~ïÞ½~r&õÇŠú˜3‰Ü|x9){;“œI7nÔç3)»*ÏØSÐÝÝý]á™3gvPcšÝ¢"g’ŠœI*Ú.PmŸ +ÐvP |«Ñé€t'ô==='€v3®£Ã +:ãÿuáÏz^0a»Қ‚—Mi¸a ™ ¥Z–¼ž{ñâÅ}ù}}}» Á\ßá>Z ûhˆlý<ŒÂêyåååocd…zdçoÞ¼9-'î£fJñ™¸¬É ”m ®“í¹©ëä$P‚¹L€¹•&A‘‚DN"#Ëf"eŒD¦ÆI‘‘XكÈH¢ˆ"Š(s'¯(áò9%É$P +ILŒZŸ„p³ðn¡EJ„²·ƒ ¸©ßæJ & 5ážIS™Ûçá27¡Ì¤g8“l̙tÿþý~’'p#gRõÞ>CΤ¶ lלŜIããã5¹W®\©Ì)”3‰çR)®¯¯__\UUµšŠä—’3©vÀVó(È%gR6&ͬÌõëק§“3)ìãOÆÐúəäOÀõ¦—t£¨­TÂ¥p³ÕÜôkÖ¬YFΤ·5 µj˜ÏF5îƄ3iï޽߫8P¢¯PÜªÕ€˜zMGGÇ -°ñ¤ØØn>c#uZqKº`¤.p°ËsçΝN/.úŒÿk÷㽓i¸aÁ–Qø :rœøm8ñóbp"Ëèþ`^uuõDé۞={á7`”X3%®ëä”öÜ ”ŒAP¢®“.ð‹ÊN=¬ é PñL€(H¢&ZR’(ȶ䌑ddãÒ©Œ$‰ÎH„蓉­žø‰=DFEQ^7ù›ëóü +#M$%ñZJbÞ²ñÛ%q+Þ²EJ¦ô•œÈÞÆ,Ä5àÞ,Áì²}ÒJ%O—¹S +&9“t\f9“¬œI&eoãƒÓéÀ¨ÖLàBc68¢.÷ÚµkUù—/_./ÜSØÓÓ3 \6sMM͚b@Ûª¢Pê…ø¢¼Ðú°9“21´©iäLJ!g’œI‰?EÝRÜJá¨×`¾ßXBýVh1 ¿«ÁþÖ«±çT°° 3IIÎ$%9“”uuu‡T'Nœ¨U·µµ×éZ´€»v=°ñ¬ØØe#u[AA=v\ånIݝéL‚œñ™ÚÒpÃ&úFá¡4öŠ<܃’JT*:{öìŽð=˜\úÆzà×`¢™R¸ëd×1ў{Ñ¢Eë˜P×IoFFÆdP¢Œn+ Xn†ÍÈ 0`©ŽÜJ“DM´¤$QÉÉÀ#ÉÈÆ¥SI2Fâ­×6یŐDFEQ^KyÕA‰ˆä9@ " ‚ÒZš¥)ŒÄÖ¹Ü))†¤$¡vIlÅÛPÀ-R²ì ®¯$¦Ü«mRÜÉ/‚ ¸ËÊÊöÊ@=“@õJPÁä27æLºråÊSΤô»C™I\övЙ”ÆœI‡æÀ­[·ŽåŒÉ­,.-ìëëÛYÔÕÕõUñéÓ§·ÏknnÞ<ïèÑ£ëXØ©䶼 ·¸v0¯Ã]@+žeçà2³@ +ikÖ¬IIŵùýÕä$\j²Cë÷€‘R]IQ·ð²·Á~:ì`õX«ÆN?Ta÷[U8ÐJr&)ə¤¬®®®P6ªNž<É°±YÓÝÝݦ˜èŽâ¹ÀÚ­¡„væZë#lìM€t'áå9?[­…-ýËêýp#jƒ)ZœW 7ûË`FwccãÆ0,® ö fJ¬™uÌ¡®“ê:Ií¹ã”~jÏíÃàO€ Bã‚iL%°Ì@n%¹•4°b‰šDIȤ <’“eËÈÊddèÒ©Œ$á1Ñù$Fb+%ò‰-¦qMÛÙf¤Ùiùò‡¢ˆ"Š(OËëJ¬ëd”$|P‚HÃ2áLšÂHQ·yII¡ +·Ä`…[u©ázo³vIá€Û,à†¹geo,aÙÛ´š›”eoWTTì£܇ µJPë™\©$L]D=<*:“Xö6µKJd½·ñò\* !èLÊbÎ$ U]. «*dd¤¼œIE.\ø¶øìÙ³ŸÏ|<|ðá¼Pi|°â«(´†GQ>¦ÅÜ\Œo בžEΤtÌ°þT\`r2p!™œIÉ À#uKuBXԍuáÎG݂ý´6lX­©¬Soß¾}³ +võ©ØøµÇÝ¥Àì'gR•ØXGØxBÕÙÙyJM­6µÔjSà»`¸~ý:ד<ØjӉˤî¬;µ#ŸHhgEÔA*+”§U•‡]í§D¥]”¨ôu0üˆCn¢k‹éFWíÍBj¦D°˜—‡{I ”B ”%jϝB]' ”L^ê:é¡.*}sÀ€•VJT2Ãpdr+éÈ­¤IÔ$*á‘<ÌH225éTF’1ëÏ*2’(¢ˆ"ÊËß”ØÊS@I”) …‘BÅmOuJâÚnsII8Ϥ–’,à 3ϧ5¸¢‰ +7ê½ýk—^ñvRÀm÷îÝ;){»TF·àjnÍÍÍÇÂËÞNnÀ *èáz&ÙB=“‚Î$°@Ÿ—õކt¥€ΦáÓ¶L Asѐ ¢¨ÉT^ºt©¬¨¿¿gñùó翚×Ñѱ}~KKËæùǎ[7¿ººzõ<–š†[l¶ˆÉ0?㛝»yóæÌl\LZ&9“Ò0 É)˜u}¾3)9ž@)uƒdÚxQ7– ‹öPÃ^6¨`C+af;”{öìùNQ^^^¢` íáV›l;°ñ´„×¥ë]Ёú ¸M¸ÃܶðÄw´p .k%€¼õU¸½ÁnŒM¬]’$pû^Ên˜‰°€›¼±±±ž²·O¨Î;×\Ímhh¨S*èæpS+€{¨÷D_IZì6 Ò€RG6iÍœÈLÔç²\¹r¥¼èâŋ{Š{{{¿×ÙÙ¹c~[[ÛÖù'Nœøp~}}ýšùUUU«¨*~){-æ0SÄ)ÈÕô®(%êO{ûí·}~\ª/ <ä#gR2EÝR¸¨›ujԍ¥pkׯ_ÏR¸ß§îM*L¸Û•°º¯¥¥¥»ÔAQ[[[E íõ +œ_“gÚ¦6žS{4¾îÆE=îÆe#芗?j:ýõ×7äRX Yâ€,t⻹ÉX:3 451> D12{œ‡ýõi*薿xñâW +p´ç +§OŸÞ¥p„ Ž9²S0¥ªÀR" +R³|PËed㮦Б’”†«JL&$љ”#ìˆÃ uЙ” fТn遌ºù³pS¸K¬Ø¶ŠQ·ûL]»vílDÏéj@¿zQß½{÷×õ´^z Ú@·Î$=ÐešM2ǀ_dë-7qV[Ðël¸Ê ~¸èÚ0Ò¦à£Gn +=vìØƈãǏ¯ÆkcñÝJhi‰-4ÏíiC»LJß¼yóh­–”Èè%Xoó)Îú֙ÓãŠ2R•y`[Q!Ï J¸«®t\Œ#•U']¸ÞðDVt°F@,kD¡[ÂÑIL¡LT +B/Ö{T?ô#Å’-¤%D2RôøNR#±·+d$¹)#Im`$ñD‰b®>Fò‰O|â“ßQþt $B ­ƒ’˜ÏAÌ~Åi š%ˆìÁHøOu Viœ”Dj>qÛ«RR[“’`Šî×ó“Hh¦$´ä«áÖ]îß¿_Ü+0Ç#Õ)S¦Œ×Ϛ5k +n3™†3×¼f͚…-§á4Ìx»2æСCËãEt $aÁœ¬2#+OÎÄfcs°ƒay7nÐ;핏ݿQ€½TˆC>]„ƒ?V„Óx 'Ô±§V^€“,l»Ÿ×79KÌܑCšœñÈ#8Sq/’éLrâ^Æ;èLòDÝ#J®Ð¦Q7?4I¡­¡pRG3úÆLá~œ)ÜÏp —õ½zõê¦;öÉZ*ÈmŒ:cƌÉúyóæÍÔ/]ºt¾g¿Ôà[eÞ¶mÛ: .p£mÿþýu~`¤Íà¡-AÀ£-¡'Nœ¨ ?yòdmþ[‹ïVÇcé²D¬·Ð…-f¹óېcE¢’»¢KOæΝ;÷å<0ë3îÂäh’ûóX"! Wœ#Fþ1ɄöätVLACĸXu2= ÄÁ±™™™ö(ft‡'%%™C8Æ ØØX}ºêRl %ÙB1ŒøOÒSTÁHìj +û½Ìþ&{IŒ$&mób$rz³Œ$ž7/Fä?öÿëùÄ'>ñÉ]ÈÿfP’Ü ÄÙEDö€’â/F26e¤æ§oÓ·µyn[LJº‰IIlˆ'YRò9 M÷Š[ÛMîÛ·ïÛòСC)cƌ¡Nžñ‰&-2Ò¿”Ä{Ü ”Äh6€’(NÜJ’7(5¸•d7(AÔ3–z1’ÅÃH"qûŽ¤$¯Äí;“’J˜”TE{ԉ!‡u IIÏ2)ée©!)©·Ì¤$eÔ¨QՉ'Žu;MæΝ;Ã~™Ó4Uy9S•W¹S•Á>kCš¤*¯ŽÝ_/2pðqQÌMÁ*ï¤cå)Y€‰q9[·nžؾ¦¦¦wÁŠ+Þ,yü¥hΜ9ÏO›6íñbÁƒÅ#FŒèX4pàÀòÂÞ½{ äµÇMÎÊÃ%¤±rË= ¶ÖA4ˆgÔ-ŽQ·xFÝâéLJ`ÔÍɨ[rpsQ7N2³p’;…Fø)úÕKúž={¾©Š2Rà’Á"©‚U&«h—™*Øq~͚5Ë ¸Ž5F4É8§ÎrðàÁmÖ#GŽì°?~|§? hWàéÓ§w†œ9sfGdk$>ÖřÖÇ£V'¨–& žñ7ŽLs¹ qºç»®¾– p}>·§K.Úå¡ÜtÌÅI–eãtó³ÐÛ³X˜\”H1ÈX.52‘Cß聱è~QLTŠ@W6‡¢+ƒA<†°ÞI±¡S+@‘l‚HFŠßIzv5•ý^ñ0’Ü”‘¤æI›ØVc$À쌄sþ%FÂ=÷1’O|âŸ4–֝I((‰ÜÕ;AI"ÎH@‰‹z@Ivƒ¤yFÂ*‚‘LnFº3q;ÈSM2Â;qûÎJIÅZ¥$^êC¼òÇu II/1)é øыIIýe˜Þ¡ +X`Œ +L™¤°LgÎl# f {‰@°ÂÄYåØY£^ª …¯ ­¬Ž…¬p@–:ñÝÂd,“¶ÿþàˆIÙÀ€Ñ¹[¶lÚ~ãƍýò= +—-[öZт ž/ž9sæ“ÅS¦Ly¤xìر÷6¬ª¬RZ ÈÏÇ=Ïiû›‘ ó™"¦eÔ-! ·1žQ·8FÝâu‹‹9˜ÂÀ¨[£n)Œºeˆ¨§+±qî[¦pw4³p’‘Q7çY=S¸U4Nwµ¡&ù0eÒ¤Iãœß4uá…sT´Ëb=Øq•~óæÍë h’M&\åV3èp§Œ´ÛFÚã2ÚxöìÙ=ÁçΝÛف[¢AKµqX¥ÆqìرNcí&*Mv'*a÷ƒ³p ÞÙhœ7rpðr9ß].Nèá\Ü·{rzõêUžvSÝådtíÚ5-5RX#À…ÖˆLÄå‡:˜ÑˌŒ [èÆŠŽc +ñЏô~ %ÕFZ²@d3D2R X éÉH*™\á IŒD:Œ$ Fò*¶­1’($©1’xò4FzôÑGëN°¼N‡ëøO3’”|âŸü¯’æÞa¿#(‰·r@Iü0Ö@Iä`4€’DV‘H-ã`’”XwÆ JœüÁ JÀ™$…7(ATJsŒdv'nc"qû—ªIŠ¤¤LZª<)˜'‘”TN£ÔQTJâ/õÇt •’^”X)I‚…í! 0 Ÿ<|øð!ò¸qãF+S§N(Kz°ÀlÃòåË×®]»Ä=œ t³Ú+¾ÖŒ´.Œ´žÃ¹Ö‹á\‘G] YYA/ɒ$€Òü€Ò¬t Ä´¬Ý»wÏÙ¾}ûÈvÀ€Aùëׯ»põêÕo-Y²äåâyóæ=S2cƌÇK&Nœø` XàžâÁƒWõéÓ§¨°[·níòq§³Úᮦ吺uKÌ`BNª \n£nqŒºÅ1êæ`á¤DFÝ\Œº¥²pRIí쌺Y +'ÝkQ7Váf +÷ "…[íÛ·o/•)ÜÌØÅƙ¤ ßQpº Tœørí²V¿mÛ¶Z p«ñàÁƒ;͸ò=֓'O‘öûŒž?~0do(dWÄûï¿¿= +´T ZZï8qâĪD4âb—Hå…ÐØc3ÐBC9GnŸl0ë[9¸3/åLž<ù©œÑ£GwÎAãtÊyûí·+²ñ|f±òf Jqª»$ÿ‹wqè[".?ÌQXX‹þá š¶E€n,¡S0º!¤÷C§VmèVŠ"›)Fˆd`oד‘Tö7ÅÃH²ÆH|H¤æI+¶-Iêøñã5"A™’åNàÂâd€Ò¼4€ÒÌÌ}ûöMÉ(ÍV k¿iÓ¦þëÖ­ëY x½xñâÅ/–€Aº–L›6­sÉøñãï/1bD‡â–õîÝ;¿] '÷7£nh +£nάΝ;'ˆ±ðŒºÅ1ê˨[,£nqŒº9X8©>ê†[›ÎîlNjÏÂIõQ7Q8 †ùQ:ÍÓzô«¿¨ È·TPdExÚ&L˜0VÃMUæϟ?G@.VkjjV©uuuëõ`Ç͐à#®wسß:h#ò +¸xñ⡠ȁPÈÞð .ìŒ-mKmŒï½÷Ö¸ãoÿ–ÌD¥Ô­[·ŽOGÛÏ‘õËB u˞={öË9S¦Ly:·ìќ!C†Ü— Š¬ÊƒSœ zÈË`‰ò4¤‹s‹Œ­èDft;€.Á±èÏÑèÏöôK(ú³)Øc D§Öû£G©vðb…ÈfŠ"°@Ò'%%I*Iñ0’Ü”‘¤6LH¢1’ÜÖ"#‰ÄmÁHâ!n+#ýg’–|âŸü¹¥õ7W‹éI^ $Þ¢â}*~‚¶JâM­’x™ÃšJ|ËK|ßKwJ¡¡¡(ÉnP²Û킖RBRÝ" ÿ F2zÉÂÍꓒ)˜»SÜ6NJ"5®&Ù0}›HÜ®bâv'þ\‰Û]ØÏé<‰Û·%˜ÙAòèÑ£Gʓ&M¯¼óÎ;SU`À,÷H.Xç%Æ 6¬0oÞ¼yMÓ!ïÁHµÁ`¤Ú01䝃¸¢!5î”ÐÒò$,X”p˜›ã?#  4)w×®]£Û†ä×ÖÖö-\»vm·b@Ç+% .|®dÖ¬YO”*;vì½%Æ «(îß¿QQϞ=ÛàžgåãÖ¦åÁ†ºržxâ‰ÄL\ŸƒQ·8FÝbu‹e…ÉXŽu‹cÔÍAg’“…“RèLÊ` +·ˆº0…Ûu3qî[# '`ŸÕ£;¾ªŠ™€Ü_A pS$Îo†²hÑ¢ùʪU«–)hœµ*.¦VvÙfî6â¢÷›N:uÈröìÙÃ60Òû¥K—Ž\¾|ùpäPd8¾Û ZÚ–ª‹Ã5l5[àNTÚ¾}ûDNý62¸: kɒ%=²’¯fO:õÙl´Ðã٠ܲq/;duëÖ­$gß.ב™Æ¡o)€ÀVތIä¬otêXt’€h µ=ˆc 옃ѩ ½?PHµ£{+Vˆl¦˜ˆG,•ôèp’ʯÂN§‘d‘˜'µX$©ÅB’^Œ¤ nÓI<ÉÍ1Rë·ßJ>Zò‰O|òÇÈ]½¥îʙôAIâ{\â]j”ð ¼”h:š%™ $3“Hf¢’LØ ¤x@Iu Ȩž‘ðQ0’É›‘Dâ¶`¤°°°POâv ILqÛ|5ÉJš¦{i•XM’Y±OðòŸ¥uù‹„»ð¦è-Ê£F!Oœ8q]%S‘  s<_ X‘\+LuuukÌ°Øë¬`v0Ò&˜òº £GÖ…À²×v‡lˆÙ6øo•´´,Ì°0  4; 4-Æ|ÞΝ;G¶ß²eËÀPFï"À؛ÅÀ²—JhO—Õ+´=P +8©.ȕ +Šw¹¸ÉíqWSòp/Ù=ö˜ƒQ·8FÝbé9‰á¼n1ŒºÅÆ0›Q·„pü—ĹoSéLÊdÔ-)Ü"êVaQ7˜è‡™Âý¤žQ7µG¯«ýúõë- +“+"$9mÚ´É2Zh–‚Ó]¤€ðV*›6mZ¯ 7ë÷ïß¿SKÝgÄå29s戌tÌ +:n¿råÊqÿ«W¯ „  +Ãwû".^¼¸3úý÷ß߇-6ˆø“º‰D%÷Œ&8ÆètmPæ²eËze͛7ïµìéÓ§?Ÿ=~üø.ÙÇ0(Ù1‹Cß2qöù錬4}KaF7'Že»D8˜¨‹NN큎c C§6£ѳ þ@!ՎΥX)fˆl"Øïõ`$Iõ0’ž'Ӎ){IbbœÔz€_Y$é®n-FÝ|òg0>ñÉÿ~ù7?¦Í9“ZŒºy’øY*^¾w‚’Äw¶Ô,(Á¦4¥œœ ”d‚’L`‘“ “™:Ô()d…´¤…„èIFþg¤˜¸T0’•[ع­¿;q»‘Dâv4Ù,ž÷ª&™×\5I-q›Mò[ҝ¸- 8p€4bĈá2líX0…y73•Å‹ÏSW®\¹„ Ê+Œ`¤µ&0Òz ©ÖFjT(F}K(ÈhsÄ©S§6EC6¸Ý"ønU–.M(-H‡ÝŸ•Pš’‹½Œmã?¬`óæÍý‹Àa=ŠAd¯•à¸Ï—‚Až,¦p?jàÜ·zÎ}Ëî·Ä,w +Nc¨@I™!Iyá…så+V,Upök_­º{÷îí*.p×{Ѐ68lû3ƒ‚NXÁC'í|ðÁIÿk×®„ †-ˆ¸|ùòž¨ .l‹={öl­ˆ¿%ŠÌ.Qœ“‰J©h«±é¸C2–/_þv&xò,`í‹Yh¦'³pÎ0`À=™={ö,ÏÀQŽ~ŸôKMaF·‹î¶DôìH"4=%(`ã ı…¡YBгM %ƒ?º•ÞŽ>®Z!Š…½Ý„ïd#–JzúTU#)F’ïu3šÒlpÛ]9“|´ä*Ÿøä?$ÿ‰ç­Å—›#ý*P’ˆÒ¶”d‚ˆLP’ J2 ¥PâTYt) š)Œ¿)d•¤’‡ô”zF‚‘ÌÍ0R w†“‘¢˜¸ǐŸ¨&™ÌÄí«IŠÄíGy½OÑμÈ{]Cړ‰Ûý¥áǕƍ7Fž:uêdyöìÙï0œ4Ï=ˆ«¦¦f…aÓ¦MkÅhw30`“f{³ ijÕ,°-´-F}kØéÓ§·Dž9sfm6ÄãcM"Ha¥ëäɓKÒ°ò¼LlöN6v0) 4:à5¤»ïS ãß­‡|¹¦ §ñxNèÁ2œZÇ2œdy)N·°¸W¯^¹E¸ûù¸µ)LOrævéÒÅÁô¤8¦'ňzALOŠv”b JQ%:“Cñ19 Ò9÷m 'pîÛ2Nªf +÷ƒ,œô8 '=ËÂI¯¨}úôé¡°p’((%O™2e¢Ìn™)ÜòêÕ«Wȵµµë\Ìfeß¾};U\å~=.ú]ˆç˜ìsÒ +:e#¶}øᇧý>úè£S“Aøx,´ôn8hi_Ô¥K—vÄ­êâhŠô.€×|g4IŒO– KÂöͪ½• hûKÖ¤I“žÊ5jTç,ðd§LÀ]Eš©0Ý©€Žô֗ráRãA‡Q I†Å•””Elü#ѳíaèٖВ)ÝÛàÒÛEª ¢X ² ßÉFþJ0`=IOïªJFR<Œ$“Ó5F’~eâv’’î +”Ú@K>–òÁ“O|ò{È€Ú -2Rs $Þ±M@I"8H¿ J2AI&(ÉnP‚5¨%ÀI=(1"ÁTj™ü¢dú}ÆßêA °£{TҒJ +ғ‡ #ÅD1s…«Ø¸²Ÿ›‘BCCƒÉHaD°HÂX,VŸ”“•ÎÄíúj’eee¥H¡3)øËîB¦pW°pÒ=,œô0S¸ŸÔã/¨ÀÉ×Î}«ÕÑç6Zž>}úyþüù³e6“ ”\-oÞ¼y£²k×®m +I*.õW~Ôâ9iûœ6‘ÎXEgmüñY¿O>ùäLäT>ž2 Ã*"T»£ÏŸ?/âobüÛJw¡nåÌ4ØÄԍ7ŽH_µjUÿ @e÷LÜ·W2ÑVÏdŽ=ú±ÌÁƒߟùöÛoWeà-NgFw*3ºSÐL.ú¸ÃÙ©S§hÚ <ý%8`™ŸŸol[CнÍA  cú¸Þ=LµA »¼‰b$#èXÕc I%#)F’#1q[0’ô;ÎnÛzfR@é7ӒO|ÜäŸÜ)µNFwÅH^ÞJR#PÂoØÆ {)0d¾Öe7(Á®Öƒl€%… ¤”æ)%…è¢4%N•EPRÉ9ª”‚‚‚ô =QÈ@(2RL”ÆŒ„õ#pÛ 2R()‚ŒÔ8) ¿íSy.YLܾcŠ[€ƒ¨&مý,Ûåe]7üéúöíۇ‰Ûƒ%ØÕQÒ¤I“&2’4Æ®²lÙ²E‚‘TÁH[·nÝ`$#‰Š@pÎ0`§«&œ>}zW0 h§»GmE g>nHõ.¬²< ´0›ÍΆɟš‡]ËV +ÄîûÃî÷(]³fÍ«eK—.}®|Þ¼y]Êg̘ñpùĉï-5jTEŒQiŸ>}òŠq™…¸Ó©ù0ŸILOrdãÆeÀôÆpΒhN€ÍèRt¼%ÜA7(…ῤ`|—ˆ¥Yt&µc +w1S¸«8÷í}LáîÌÂIOéы_rGÝ ԇ•7‡2É}yrºLŸ›ÌnyÆ 52ø¥NÞ»wïN¸_ÝVqù'ô.\8e¼råÊYé}  è¼õÓO?=o¿~ýú9ș@||/ Ž…a•w#®^½º7úâŋÛÝñ74Ýjw¡î}ûöÍNÞ¾}ûäTܙQih°éK–,é™1gΜ×2§Nú\& ÷‰Lftgà&WgtïÞ½$7¾}*kt§D’]èD3Å8:vìÁ¸dH zN`$~ø…£{[CÀ>æ ô+c@vv¶ÁP¤Ú Š3D6’‘ d$=¶T2’"‰‰Û2“’$&%I ¸IÍUÜ֜I‚‘Zw&ýJPj2ùêÏÅR¼¹ó‰OîFþPÔÖ×W‹xÔ#µuÃ+Wâ¯T‰ïb‰oe/P’[%… ¤”7(åææ6%¦¼2¦2kHeŽµê% ŽÊ ™žn%=ÙÇ@ +2–Œ„"ÅL±ð;ÁHv®ìïa¤î*œ;&#œ‘œ%ëׯ« ÐñrùâŋŸ)Ÿ;wîcÓ§O b„ Õå#FŒ(+8p`A)Î>§ב^ˆ+JfzR"«'ųzR,ç,‰fMŨ$–Jq¥h‚R$!]A°ÝiX%Û+··a³R vЁ)Ü°pÒcLá~Fe¼ÂÂIݐG™sß289‘)Üï°­ÊLá–7mÚ´AÆÅl•ÑL{”£GRN:uLE¼§¿|ùòYõk×Λ€B̀¢‹ÖÏ>ûì¢rÁò~ i) N†Ò­ñÁìgüm§;þ†Æ^+ +8±û¹.hjJ]]ݘT|p:N£wnÞh°2˜Ñ1|øð‡2˜ÑÞ£G²4ÖèNe¢R2 2ÕÅJSN¦r9ÐU"ÙB¡¬/‰>äⱅ¢KY‚@A¦ttƒ Hoƒ¨ö{3D62m #鱅¤’‘2’BF’p“#1à&‘‘¤Ö«4çLj13©uPj‘–~%<ùä÷âI2ùäÿ’üŽdôû Psâõbl‘‘¢n’Û™t'(ÉôýË̀’BPRš‚’JߍJPR™;­Ò©£6%=ý>zz€ôŒ¿ééV2{  #iÉH2QÌ ÅÆõŒ´ +lÊHQÜs“¡íKæÁ듒pV’’`Šîw'%±š$ÛàEފ×u½zõê©cⶎ‰Ûdœã:U‚ÝŸÍl›…ã¾Ü=Æ}˖-=ŀ¶›@7»Ì`¤=V˜í}vVM €ß2ÚÇ:@{8`ký Ûâ u  ¥õI¥Õ©Xyi@i^6¬ýŒ¼C‡MÌß»wïÈÂ;v *†Éï]ºnݺ7ÊV®\ùbù¢E‹ºV̞=»sä¾ŠqãÆU•Ãî— 0 } .!‹éI©¸¿Iíq/˜ÇÇ<îJÉ%§ÈÀ!(Å”¢8Í[8$1¶;9͔îû›cà +¬<òHS¸;²pÒCLáîÂÂIϳpÒk +ŽÛ‹…“Éh°Ñ2GJŒºI˗/_"áÄ×Hh«MòîÝ»wȸ¶} +šé°‚‹>¡¢qÎè¯^½ú¾tѺl]¶|þùç—m_|ñÅ%?ȅ|<Z:òÉ'Ÿ ÿðÃF^¹rewŒˆ¿‰ú“,ԝÈD¥$€ëôdàåøT|XN£o:Nè­ œÚK ß®#GŽ|$wúÞt\BE¬0—•“̃]¬]î«Ä'°­âÐLa Nqú;ÿpô&[(ØÇ +2€‡ ~½}Mµâ?ÅÌà³ l #鱅¤²$…7E0n2nnnR‹Ó·5çLj1êÖbŽR‹ÈÔVnòÉïE‘¿#7ýñÆÐ'>i*¿~3û´ŽB-’‘†G-2’p&yEÝðj–ù¦ö%… ¤x@I%(©ÌüQ¬†ž¬¢'(é™O­'Äèéò d`üÍ@Î1xŒd#iÉD2ŠÌ ÅÆïì\ª1R0· ##E’‘bÈaÈEOVQ-›ISíyj%<Ó*žx'þR¿#)©gϞ=týû÷ï§ó$nK‘)d&ƒH d`Ê2ÝZ£ÀoPÉHú}ûöm7‚‘v›`ü÷ZÀHûmgϞ=èF:Ȃ‰‚/]º´?ìòåË{™Y³+²-ßÕ%Ö'c½Ui`†%™¥¹9¥ií`íÇìÙ³gxÑöíÛû—lÚ´©GYMMÍ«å0ùÏU,X° Kå̙3ªœiÒ¤§3pº¦ãÄïKg¢R.¦(—•—Œ Ìpq6<'̑t‰ŽCk„³™‚™îQRRbEG·ƒ‚́èíFˆÞ&wìØ15·6ːÐγ]lyüñÇ«˜Â} '=Êî§Y8éel֍…“úq.—á,›0Þ·w$FÝ$FÝ$6˜¨Ü&8p`¯Œ¶zW>}úô …Î$Mr^ö\Ö€®B×L £Í7oÞ¼f…|`‡\ñ2] - þì³ÏÞ ýø㏏F€¯êãoçΝÛÄD¥5 ‡^âd¢R•’Ai£RW¯^=0mñâÅ=Ó½¯¦ãÖ>—ÎғéLTJgéÉ4&*¥¢3´KÆfºp©ÉNtù„ôö˜x4XD Ú%$ +=eËýÂ@KÖ`P9(nô‡ì #½ÿ)Š‰ùzF2’Œ¤#I*IŒÄ€›Üԙ$µ8‡›W=¯Ð[ën¥æ© ðä“ß•,ïž|Èä“ÿ5ò;âQ[¡¨ is/¼¡È ¼üHš3Ic$¼‹e·3IDÝðºVøâ®%ØZÕJz‚’ž ¤'(J-3°F€Àb$º JFÆߌdéÆD·’‰n%±ÇLZ2“‚,ä!+ÉÈÆÿì.à*AD«zFnE¼â¸çDº®’ÉfLJÊå¹òÔÊx¦Ixúã¥>Ífz‰7ùM]Ÿ>}zëXMR7jÔ¨‘:àÇ 2CZ°`Á<?b¢Í*&Ú¸‡·«{÷îÝ®?tèЃ(* F:dfQi«§¨´?xèHÐ|p8rF}_4þÛ4ؖPÚäKÕ¤”Vd”æœ8qbf;€Òä|Åè¢]»v .Ùºukï² 6¼Qkÿbå’%KºVD:WNŸ>½Så„ *+FŽY\>hРveo¿ývVI·nÝR™ÇÄùäªô¡Œô‘ dô±ùÖ­[Yoß¾ý¡ ÿ}à‡ï.€–„[ét(¨ê8ão‡Üñ74âfQ‘ÊqôèÑe‰LTJÌNsᖍMÁÍ’ÊD¥44Ýi ¹ҙ¨”ÎD¥´tLÃŔ¥à²ò“ñ|d»ð¤:YÅ<­ˆ‰ŒE»„Fq‚"***ü9¿‹-´d D73ùŠ vˆÞFŸªß)&,•â`Àʒž54T »¤0à&œIrSg’¤9“~%(5ç[j‘›Ú€Q>i“üJ´j+7ýJdúãͧOþ wÏHmͧnCl¬ ØÓ: +yA‘& ïÓƱ6/FҜIxI+PR J*AIOPÒ{@É@1x@ÉHP2”Œ%ã`&fV›ˆ3&Æß̌¿™É9f…´d!-Y‰B6B‘;şßp©ÆHá$­(2R,wšÀÝ»èKçqsÌgтRV“ìÀs¾N±Î¼À®l—xË^ÓõîÝ[$%õ×ÁÚ×1)IÇÄm‰‰Ût‹,–Ö¬Y³Ò]ˆ£¶˜üúZ‰°ÉŒ`¤wM°ûG,.\8f÷c=éQ&¦üH˜°çý1ønwº¢^¿~ýšþ‹/¾øØúÄ<úÔüÕW_}b|lƒ|è‡ï®`éÅ º•B°ÅÉFñ7‘ FÜÏD¥ܞN€æ •’kjj†¥0Q)•‰JiLTJ×=•ÆD¥40潩œ#7MW˜Œç-Dž§"͉‹NJ@§‰bGÅ¢Õ¢ÑLÁ€ÿ0t.{º¼%(d +ý zDµ@3ɈUdI‡DRAZ’Bg’â%¹)(I-‚’6]I‹´Ô"2µO>iEÚúÞm+rÞ=<µ™|´ä“?#ýf^y jʔ)ÕUcǎ-­6lX~ù€²K{õê•VŒ~êb=îx‹ã€·èLÜÁÈ4€RA)"‘ ›c-@)> ÿ%ã»ä,ÍðÃMγážYÐ*Lè ŒèW0…»+£n/±pқŒºõaÔm(£nãu›A¼œÏ¨Û +FÝÖK–­Zm¯Äné̙3'e\ù9muIùä“O>P?ÿüóô_~ù姆[·n]7‚Œ>3}ýõ××-ß|óͧVü÷±ß]óÇÒˁt+c‹S¡ØV‹¿íˆa¡1kžãÝwß]”ÈD¥$&*¹š#R˜¨”ÊD¥T´ßËi¬¨”ÆD¥4°Þý©}ûö­JéÞ½{q2úFž —šáÄáJÀàˆGÓEÇ¢é£ÑB!‘èWL|·s’kPyy¹9Îè22Ø ª3ń¥²Œ¤§3Ie}V7(1ê&3êö  ä•Ì­Rs´ä…L^ÜÔ¢´á…â“_ÝmÀ¨¹éwD¦?Þ¤úäÿ˜üJFjÚ@Fm  ßp^ïD/Ñޝ ROF xÔ<#áçk=#áM­zœIz¯ ,ób ( JF҈‰ dâ¨23AÉLV±”,% ƒaVÆ߬Œ¿Yé²Ò­d#ì؈=v´äGò§P)Á\àÅH1d¤xîÏI‡U +”IOV“’ +9D9O²#OüڙÇxùOóVü…IIo2)ém&% bRÒ(“’t")‰¸JLÜfèh-Ë$ÖÊ¢Lâv«GŽ9Àz҇ õ¤O°žô{VØýSv Ð)Ñ{A°â'˜x|,ÿŽ†ì-íN (¹®^½º1æ}u@iI@iN;pÄÔØø±E{÷îZº}ûö>å›6mz«²¦¦æ¥ªå˗?Uµ`Á‚ÎfΜy_ }UN¼¸—Ю¼_¿~Y¥@¿ÔbtG'¼9X;6÷2J€R*Œp„‹ Ä‘\‘q¥h‚R$>AX€U2íX¹›әTeBÓÝÇîGY8éiNz™Q·îŒºõgÔm£nu›É¨Û"6Ý*FÝjµ¨›„V;*;w;/£­®(h¡Õ/¾øâõæ͛×õà¡ÏÀ£ÏMß~ûíçfÈgVȧvÐÒG~Xêv+c‹3žøÛA‘%/jSqê¼µÐæÒÐæ'qŠkãƍ£“W¯^=(øÛ+••RYQ)„÷D*XïÁTP_u +Ú¯4v{Ú/ˉöKIàÄ/ñxbcÑù#¢ÑB¡‘h°@Æ*ýXJÁ Z2¢ó›ü!;Do…¨fˆbb-V#ëŒèLÒ”T:“Z%-GI$s7çVjη¤!“&w¾Z*ŸÜ¥Üw¶HPm঑ÉGK>ùó2R‹.¤Öñ¨Å\¡æP艧^¼^Œ^¢½@¤~Ø¿1®­d7i~$ÁHxSëéLғ7 P2’ALŒj™Jf‚’™ d!(Yø²2•ÚJñ7qÆF·’n%;9ÇN·’ƒp~ ú–ÈCB‚(Áü.”Æõ"¹E4·##%r§Éd¤t-‡Ï織’á:ðtïãÅtæ•weÛ¿À;ý:+%õd¥¤LJÁ¤¤ñ:úé:ú¹LJZ*NÖÐ#²QÞ±cÇVØÚ­pÎ Q&Qæ̙c†óçϟ4qÎ 3ëI[AAg좔4 øie/r<r8ßíAíJ„eߒ PڐPZ• ó¾(÷Ô©S³Ú;vlrá¡C‡Fƒ-•mÛ¶­wEmmíë•kÖ¬y¡jéÒ¥Ov˜?þÃp¦÷vœTTáì +‡ ’[êË(íÑ£G2ó¸óѹâòpÑ1Ù¥ ÜÆJIPŠíÔ©STš)6âÁǤ@XìTXìl;îy{+š®ÔŒ®RÍî èُ3êö,£n¯2êÖSª dÔm£n“釛ͨÛŽu[˨[£n»u;(1ê&‰¨.ÿ¢ŒÖø@ùì³Ï>V¾üòËëêíÛ·?׃‡n@F7Œß}÷Ý 3ä ä3¾ûÄK¯`½ËA7nÜ8‚mÇß°ç­±8Æúø£G.OØ¿ÿ¼Ä;wNKb¢’‹‰JÉhÄ·SXQ)uúôé/¦rê·T°Þé ¾{RÐ-ʓÑA +\xt³xòÒ9•°ƒµ:ã˜ãƒö ‹D[…£óû3ûÝÆ✖@þTðì½¢Z Š‰ŒdÄ*^ $5 JLæ ÔÈ­¤Ñ’æ[j™¼\M^՜´þòðÉ/I[ ´EŒj›ZG¦ÖL>Zòɟƒ‘šs!µš#£æxè‰çŽw¢—hïÎÑFük¢¥"ÉÍ2ÞÔõŒ3kdÔÍÈX–‰%„Í%3AÉÂQeV‚’•þAÉF÷Ž Cv‚’cc~t+ùqüéVò'ñø“}è$ +$ +™‚(!”P~Î¥‘ôAEs3ÁH ܕ‹{N£ë*›¹Q화TÌJI•¤¹{y ó¢Ÿ`‹?Çûö ++%u× 0 /+% ÕqŠ[+%é`>gë’’V1½f= ý–’Þ%Ó#"ªÿ¨§OŸ>®‡M~ÏFsnœµÀXŸ³…Îù±”t ø +ƒÄÇÃ1X°ßŒÚå$(¥À²¯O¿xñâʬsçÎ-̃yŸ™PšTtðàÁ‘%»wïX¾uë֞àW«@ÏuX²dÉæΝû`œnÇ°ñeU°ñ•¾œr Kó¸]Eè‰ ðKPŠÎÆ]LÇmŒHÁ w”  M“IÆw®@,MóÃz96lQ`Aß(cÔ­£}÷!Ú¯‹¾gϞϫýû÷Q·ÞŒº fÔm £nSu›Ë¨Û22æ:ŽuÛ¨ÛFÝÞQ7‰Q7éÚµk—e´Æ‡ò_|ñ©róæÍÏÕ¯¾úê†<ô¥dtÓøý÷ßß4ýðÃ_Zðß6|wÝþÍ7ß|äO·R ¶hõ'Y¨›óçmŒÃÑV9p܅‰»vízǹyóæ ®uëÖ O^±bE¿Ðp·Ný–ÊB©£Gîœêë”Ú¬LîÞ½{‘ Ït®žˆËw98M^š$:$…' 8œÀÌ.{0Ȉ'ÀìÏ´6Ø8 ÔÂêbfJ‹ ¤xr”d1êÍË­Ô"-y!“75GP>i»´þfm‹¶T­ç‘µ™Úê`òђOþŒäåBj+y‘Qs<Ôñ4ÿNÔޘwJý|m¢ÄvƒÔû"Òµ…ˆ|$GšI0,„‘øa¢3ÉLP²”¬%+AÉFP²”ì¤?‚’!Ɵ.Æßè + [)€°Hì $-‘–„ŠB(a”p~×#%‘‘RÉa™Ä²<¼çRNëȳ€ýÛùiÞ£—Ü·~ýúÕÜƎ;J7uêÔI:VJÒ-^¼xŽII҆ Ö1jT'¢Fî +‰Ô®‘D)iéŒÖùKIŸ·pº xè<Ëý¼ÏQìgC §Â!'¢`ÏÇ”`Ôw&”6§”ÖeÀ²¯È(-h÷Þ{ïÍ(8zôè„â /…yï_¾e˖î•ëׯ¹ +gõLœßcÕsæ̹¿\Ò¡¯¤ +¬×¾bàÀYe½{÷N-Av2ÛÑÝ,6Ý'* ÷7‚ žL/@‰£Ý#c@). ‚ÑjÉ°Óé~¸ç¹6t†B úU£n÷Ñ©aÔ­+£n/2êö&£n}Xar(˖c…ÉtÆ-`…É:œýÚo›Œ¹Q·#"ê&1ê&¡ ®Êh’ä7n\Wnß¾ý… + +º©Ý2nüñÇ[&ÈM3>Þ°‚–>·cé'þt+Þºuëb0¶=Û(þvéÒ¥]Ñ8F], Äã¸Kp³¸—““pWGºÐ’’-ZÔ#……Rp÷ŸMa¡€Pß)à¿É éžøvN\tf".?ف†HˆC“ÄÄ0Ñ+ +́V df—Ç +ZYÊÜ€ÇÀè1”ô%ՌŠ©”d7(a I$s»AIs+i´$ +ˆApÍ!“ÆMÍÁS‹ÒÚ;Â'¿,ͽw[ÒæXÊ ž¼¸©­ÈÔºƒÉGK>ùOÒ¯d¤æðÈËqÔyAQ‹ìãõÖÓގ͉ö“4Ù-¢†¤¨$Æþ‹T$Gw2’‰Î$ÄLP²0´e¥ïÆÆl ;Aɏ¬âGPò'(0Q)€ Èø[ Á&n¥ rN3°ƒ‰=Á ÒRy(”F‰àw‘\Í`]·pp['™+…Œ”Ácäðù<Râ[ž³¸=Â&~’wFÜ^sÜ<@7zôèáoÓ-\¸pžŽ•’hã×JLJb +òvYþÓm°B¢ +#üžæø¬Œô¾ñ£>ªŸn(tÉ(ºèÛ}!èË/¿<9Ž'¢±àp0jVÞéÂfu¥šL€Ò²ìt^{ì~zá‘#GÆïß¿hÙΝ;ûVà4ު ½Ô§öT5N²sõ¬Y³:UO™2¥²Ì{QÌ{^ŀ2Ë`ÞSJÐw9qI<¼ÅpÀ[d&A) 74ÜEPJ$(Å”˜mMk +I ‚䬒aG?ÈcÔ­ˆQ·Júî}ŒºufÔíiFÝþ +“Ý8Ö­£nÃu›ÈÌ®™Ì~_¤Û¸qãjݶmÛjuûöíÛ¡cR—ŽÓ•ˆ¨›Ä¨›Ä¨›ŒVûD¦3Iùꫯ¾T¾ýöÛ[*xè+=ðè+Ã_ÿúׯLÛfÈM+¾û†¥×ýTºãohâ÷=ñ·w#®\¹²' +»%͹.Ç]æÀÌMܾ}ûTgmm혤5kÖ v±P@òܹs_O™>}úó)`½.)@·’ Ô1½¤Ì…KÍw⢳qù©4„3]\,'2͉g!ˆÎ8Ž´ѱ€Nh d‡è­MAÉHP2”ђˆ¿yhIjJKîÝÍ!“ÆM^ðä%MÞ>¹iýõÚ"š¶ˆV-&á·^å¡Å9i~3-ýñ¦×'ÿKä·0’W˜­…:EwàQ‹däÅC-ÏoBíeقHDÌi+ªk7ˆâ1ì_ˆ×1¸]Hðâ6“‘,d$+iÄFP²”ì$?æù3ðÀáf¥@BLS‡‚È4Át+qBèV +!ñ„’}BIKaD¡0BQ8EàQ¿‹áÒ8ú ÜL0R2÷—N‡U6©=^̪ä銀ÛClÝ'x+žåm|™·nž€ÛVÀÛwÀmÙ²e‹u¬”$qJ2‰IIb<»»Š4S•³gϾ§lÎrºóbº “˜nÖþŠ<¶ 4¤gðve]]ÝU555/vX¾|ù“Õ ,x¸\wo5ढØ1c +«†š[ѯ_¿ô²ž={ºŠq© …è‰qíÐá¢sЯ"3ÑiÂS= ”à¥(HL8$>·Ö„¦KñǍϴ£ýÚYÑKÌè¬u»ŸQ·Çô=zôxFÅÑ^á¼n=8¯ÛÎë6’Ã'KK–,™Í¨åq­—P§hîÒ;v쐎ӕ¸£n`ÌËS¸u».ߺuë …Î$…Œ¤‚‡¾ÖƒŒ¾1üíoûÆùÊ ¹mÁw_Ú~øá‡ÏèVú˜n%»,Ê*1þŽ=páÂö +ˆÅqWÆã $€;g8ќã“X(ÀÅBÉ,üÎ;4 `~*Ô÷H2ãoÉ}ûö­páR ¸èÜDÆßðè&Ås¼X4Nt4ž”ðH4X0Û/€yðv–é´Ò­ä1” VOü Ô8þFÑÆ¿¹+*yIjŠLî9r›ã& ž¼Dc)Ÿ´]~ñUz‡´N¥­ÇH[¼Ø†‰iZ ÇùhÉ'ÿQPº{FjµNF^(¤=’ÚãìõNÔޘ-ˆÔTd·ˆùÚD‰mˆê1ößàNEa¶ÉΨ›#]þ¥²J A)ˆ ̤ê`FÄBˆ3!t+…Ò­J·Ra'ŒØNZ +'E™" EQ”h~Œ¡Äq•zF¶ÉÜKwšÅcäñ…äµržiµ;à†Ö}”7à)Þ­p{ƒ·^ ¸ dÀm$np{Çp[½zõ +úAÖIÛ¶mÛ̀ÛNÓ:ÀâˆGdfÖhU¤õàœKú+&˜è«fPÐ, }Õ&ÿ +=—‚!çÃðñL$œŒ „•÷9= ”Ž]­ÉÆN—äa÷³óq )E¥Ñ¥´AåÛ·oïU Þx­ðíùj€\—jXö‡:²w¬†e/ë˞_˞]˞V˞ÄoN\ËoQð‘!@‰–=ÉJ¬å%G¾sbiª?ÖËbÔ­=£n¥ftàj#º÷ƒ<OèA›Ï© ÍהáÇ÷’Ǐ?HmŽfÍ©)Nr.Sà—é6oÞ\£Ûµk×Krê˜ý®#hêXa’Q·+Òõë×?–@‘ŸÉt&Éß~ûímôµ +úV2úÖðÓO?}k„|c‚Zº%ÜJvÕ§þ@+‘Ö})H‹¿]»vMÄßvFãh›bY( g°Ø:+qëÖ­“œëׯ™´råÊ.Æߒg͚õJò”)SžIF·x,yØ°a÷»s1þ–„÷A»DÆßЛ’ãñè&IJÆy4ºYD$,$F AÉÏ JØ @É;þ&•ÄÐ7Ғ»P€¨¨¤Ñ’™ÜS¿ d¢ðÉÓéÄl¹B4xÒÊK4 òɯ‘_|©6©­ûúšKÇoku¬æLwOK>PòÉïÌH(ý>Œä…G͑Qs<¤=’ÚCìõNôzm6©©ÈMEq‹(±-ÊGB ”útm‘Š$Âlx]ßÁHx­” JA¥`RKA)„J·RÝJat+…Ó NΉ ñD–" @‘D¡(J4‘)†ˏñ\šÀ`]=#a‚‘2¹ç\ú +x¥<É*6S'6¬¸uáíyŽwúUܺ3à֏#܆1à6Ž·ib„›¸é8m+“j6‰€³÷Iǎ;,fÚÅ•+W®œWaã/5ši†þš<ô¡ ûš»¹ ¹†ïÎFbéÉX¬wØAPJ¶ÛSJµØßj‚Òâv¥Y0꓊Áf£ÊöîÝ;°¼Ö³ª¶¶öÕkÖ¬y¶zéÒ¥w<Ð\R]=a„Ò#GŽl_…ËʪèÓ§Oj)pÐYŒ~_€žÃ<î¨lJè\á)èMaNô—pn­”"!±aøèF?H"(¥ù¡ëeÛÐ1 ,è±e&tåŽFôö‡8¯[Îëö‚2hР7˜žô6‹ aó±, +0Eæë"+t@’õZz’ŽéI:Îë¦c…Iu“u“@‘_È_ýõMù»ï¾ûJ}«€‡¾SAFßëþùçï oMoÌøî¶ÕãVòZ}€v¾â»|ùònÆß63þVÇBñ,Àø["Útt ¸–,YÒËÅø[ò´iӞOf¡îdÆß\Œ¿¹Kbü-‘ñ·´ij<ÚÔÇé…cXm! +.4M×rüM€’;þ&Æ¿±P+*ÉîғBD¡n1£‰1G®r“DnÒ !<¹EÀ“&£Z¯|òÛ¤¹wl‹|êÅR^Õú0Fa+~GZò¹•|òïe$ ”ZÌGjŽ‘šs!µ42ÒxH{$ųêõôzcj‚÷©ä-X {DñˆJÑS 1º‡´‰tm‘Š$Âlx] Fò÷f$¼êCJ¡¥0‚R#báęº•"I7‘t+Ev¢„‹&ûD“–bˆB1„¢XJÅÁï¸Ôɕ#¥·#åð")IÜ*Ø`÷°9d‹?Îûñ oÞ_XRòMÜÞfIÉÁá6š·É ¸Íâ·E"àÆXѝ¸íß¿( -ÁÌ—apO+0½gÚ #a?2‚>fíèl°ö2wæƒ@ȕ|¼Žg£< ”à¥TàÖF‚Òª Ø¢v€±™ǏŸX|èСeŒþ@îU7n|¹Fý™jõÇ:2»#ŒzU5®£¸Œz»Êf–觔¢g'rÀ[<'.‰á o‘ðîÎãF¿rƒRoõB‚ò ¨Ú sùä×Hë¤êEUAµ˜˜ß25ç`j-yå-ù‚p>ù·Rë·©u’µNF5`O½hï:¯÷¤öm©©È[(Õ#zŠb¤˜ÜÃþŐ6‘®-R‘ #Q‚É*!¥P‚R8A)‚ŽžH‚R$ÝJQ¥hº•¢É91¤¥bO,(–´G‰' IàÇDJR#FiepW‚‘ÚóEö‡\ „\ ÁwÃaÅÏFݾ}ûdœ% Á^@iAiC&@i%Aia{Øów +;6¡äàÁƒÃËvïÞݯr˖-ݪ֯_ÿ—ê•+W>ݧ۹#N¼SÇ©S§VV7®¨Ð/¯˜QÞ»wïäRæq¡wÆå£ ¢E7¼…3;ŒÞ˜Ç-@©q7A‰éIÉ%‘ǝKP*bzR%Kqw2à èÌô¤§T4ç_˜žÔÕ“úÉhÎáÎj"«'Ídõ¤EºÚÚÚÕDÎM: çN¦'ÔÑ-§cKêX€éIIhÄÏ$FÝ$4ØW2I2(è{<ô£ +2úQÿüãGä#ä{¾ÓÜJ7ì?üðÃuº•>Ôâo¬îy< Ç8£íŒ:sæLm tut‘ ;3 ;1‘…º,ԝÄBÝ.Æß\Œ¿¹s1þ–Äø[ãoNÆßs0þÇø[Œãø7Æ/ëão,«ä)`rƒëOZÐmU u»g4¡è9ÿ›JQD'ce·Hض‘ðk,ĨfEP•O~W¹óõz³¶èúó‚§¹É ™Zw0µ–|A8ŸüÛ©õ€ÛÝ3’æBÒ¼GµNF‰GR{jµw¢×»³A¤fDöˆâì@¥è)Š‘»7QÌ k£ØÝ©Hœ¶ÁÍHX*)”›…Q¹ÓH‚RA)š8CPŠ¡(–ˆGZŠ#-œ–â @Fâä¡J"ÅÉï\\šÌõÒ<Œ$·Ûñ@")©>à†æìÄ&~˜mÿoϳ¼«/s··8‡[Îá6D7qâÄ1œÃmŠnþüù³u˗/_¬«©©YÍ|šZæÓl׉I6p“`ÙOr„ÖYQ‘³‘]U®_¿þ¡JFâ$Ÿr’ëfðÐuwÙhá߀|¹‚ïÜ -@éæ͛‡@ikZ(­ÈÅ1´?uêԌ£GŽ/9pàÀ°rœKßJxëÀoÕ+V¬èÚöü‘Ž°ç÷v„=¯¨†=/ì{ž[ {ž^Î<<îXN\ʼnK"D·%—”¼¼¡ë% +Pòäqç1»ØŒþ\Å<îû˜Çý(«'=ÃêI¯°zRVOÀêI#Y=i«'Ífõ¤%ººººµº;wÖ±9wëX=‰éI'Ez’ŽéI:V˜dzÒçZ薄ûZ¦3Iý €‡þª‚ŒþªþóŸÿü«žb€ü`ÂwßyÜJ7éVú܏iݍâoœÿ-”ñ·pÆß"ϝ;·9úäɓ5±"þ¶wïÞ9 ñ”Dêv2þ–Äø[ u»s1þæbü- =§cãoNÆßsxâo±ÿÍñoLT +c¢RAÉßJ–ž4ùáY0Úð,è-œÖÄÌùßÄD¹Š"©Q :Ù#¶h,Ä(—¨|òûŠ ÒÖ¥EfõB+ Zç& ™4/SsÓÖüfZò¹•|ò»€Rs·»Šµy…Ù¼\Hš÷HÃ#/2Ò È …Ī=ÎÚ˒oѦ"5Ù-ü5ë•¢ç® #wo¢ˆÛŠg †ýûS("Ììv! <‚D¸ ÍÄp±Ü}OZŠ'-9;bOi)”HqŠ„$yð(…«x1’HÜII%lµJOÀí6û£¼Oñ¾½¨ëÑ£ÇëîìmõÆÙÛ°ˆïè`ë³·kkk×éXR’a¢Ý:Q;š7‰7©É$×N²¡ç$ND&&Ù`ÙèÏYßç3w~1ä£ È¡Xp)«œ‹Æʍ@)¹”Öga÷+rq ùù¥éE¥q¥¥¡å Œ>ðöfx«æ€·ŽðÖqæ̙÷tœùÝÄëmÛ³z±”FPâÝîÅM2i^&/“W8îî#q>·’O~+(ýJgR[©9’yùŒ¼ HC!íYÕ^‚Ú»S_´Þ²GŠÊm…è¹?ÅÈc˜x4 ÅꮉÓðsøÇYÕ§k‹T$fƒFŠr3$–+ÇqÛxŠƒ»JàžyŒDÒÉ3pòԒHAIä!%™"ðH„ÙÒ¹ŠÈGÒIKJÒn÷±Åá,-{ûfowãü$}™½=”ÙÛc9?ÉTfoÏaöö滳·iÔwШï§÷ãkG¿ÇQìïsÆVQ;úšûû±6™æý ÷ü?üðÃVÈçöüñº?þû8rÍ Jß~û­”â±í»¥=MAiy@i^>ØlZ(ml©V¦ü x{A xëØ0àížj˜ò²j\V󸳙ǝVÖ½{÷¤ôXG!ëq·cw:aDӓ8qI'. çÄ%¬Ç]J ”RýĀ7¼ŸÝÞLžo,3ùAéy–™|M1bD/–™Ì2“cXfr*ËLÎcFür¶©ÈãÞêÎãƵ‰<îÓ:úæt€˜k:–â–nß¾}CDÝ$4Ø·Òßþö·d:“d2’2úYý¯ÿú¯ŸõŸ ¿IKn·Öûʊ-¾´7¤u·%þ{ðàÁEñŒ¿9´ø:C'ãoIŒ¿%1þ–4f̘ǒs2þæìÙ³gI"ëO:Йñ¬?ÉD¥ftÇ”"J¡¥@‚’_fpê7‹?+;z±ÁŠ~¯· S«ftoÅ‘ èí²"©øm ) ¢“="ai#ѵ.Ø©OþmBzm$^/_/*Õ0Ê ž¼üM^ÈԜƒ©­´ôû¸•þxí“?#ýg’6®­¹X›#i.$-¸¦y4ÇQsd¤ñx8Å«½ù*m*RS‘=¢p !*÷¢§¸S#wo¢˜y4+kãøñ\DU¤ žšÒ&ÒµÃ=.$ÁH1”8J<—:( Ü"‘Û:)IÜ_÷ìâ1’y´d<Å#©”4Šp!5f$ì*ߓ”TÆŠáv/½Óy²·ŸæÍ{‰ÙÛoè`ßêIãƍ©›6mÚDÝܹsëIkÖ¬YÁìíõ"{›©4{tG}—9Ç'DÀMºråÊE™ÞÙk"20Ò Î¯ñ¥‘Sk˜G_2cæ ;ä³|üÄ Jßÿýå–@iK:¬ø:7(±Ö¤”Æ°2À`‚Ro‚ÒëîÊK—.íÂou—t䀷2x˯ fW€ Óʺuë–TÌzÜÌãnÇzÜ9,3™ÁêI) %љä@׋ˆåT¸‘ŽÕrpâ’$ÏÄ%Ù¥|‚RA©#ëq?DPêÂzÜ/”ސïð6Ý=àmÆ bÀÛÝÞ½{›ÍãÖqÎӓthΛ¥¯%´ÚwÒO?ýô£LgAégdôwõ¿ÿû¿…ü¬‡Zú«Is+a‹[ZüÓš\ dü-XÄßÀ¢ÍÆßâ<ñ·Æßs.^¼¸7ão¯'1þ–Äø[ãoNÆߜ¸ò²D¼A +8ÿ[<žýT&*9™ÑNJJQ‘œÿæsê7ÿ`< ö@þàðçÑ~èÏF: ?3ŸFS»víDÖçååIªÜÜ\IèdHÍCÓ>ùO îQó¢½w½HUÃ( ž¼¸Is5i^&-0§9˜š£%¯Hœ6&ÎçVòÉ¿”îޙÔ\R’—ÐVFÒ\Hš÷HÃ#Œ¼ H<âáԞ_ñÆÔ$''GjFd.¢PTn+DÏý¸gaæÑ,<®˜¥MÌ@âÏ +ä#Ìó ¥„»3µBõa¶FrP(‰\Dqqe7K¦¤pW)Üi*w/$GK§hx$ê#åxI$nkIIõ74±(—$²·Ÿäzž7Y+Ðؙ4sæÌ©¬½]_ +`ýúõkiÏ7‰ìm:>0Bt”©4§¤K—.çDdWdæ»'"»uëÖçê×_ý%ç׸Éù5nAF·XÚç&]7ìÏðݧA°Ý†b7(Å`³“ñØÁ»N/P–”ææ³Ö$K(ՃÒöíÛ{WÖÖÖ¾ÆÊÏsÀÛ՜á­ZT€/倷ü*Xñì +N\Âþøã£aŒ¿E0þ剿Å2þÏø›,:>,:,qÙ²e}`Ñ·Dü- øãoŒ¿9ûôéS™Èùߘ¨”ËD¥Œ8<ö.VTr”bJᥐP<؁!tÅ¡[ПÍ~ü9bÃSf°â¡Ó›ù šøHù„(úììlI¥(YYYBt²G¤¦¢óÉ¿]p+ZܲzÑÞÀ^h¥”O7y!“°šƒ©­´$lOs)K>·’Oþ ÔVgRë7-g»uF?$„+Vóyá‘5 Pýcª=Ι™™šHMEöˆÂ•…¨ÜžbàþŒÜ³‰Ç°ðhV×Î3ðç¹]‚yj¡|ºÃÝÙpÎÑî,$\B½ IàÄIqQ’¹ …’Ê•Ó܂mÓ¹!Ü©LŠÀ#áBãÚD¬­ž‘DR’¨ Üð¶¨ÏÞƝy¦©3©7Kx9“f²ÀB:“Vj¥9“˜½M{~Žók\b¥Ÿk^ók¨œ_CÏ9ÈÜSk°X4Ç`ݲB¾´C¾ÀwŸai=(Þ÷€Òá_%ðژҽ{÷*jôªÜ¸qãk8®”æ̙ó gx«æ€·RxkÏoYå½zõJ-E/v¡ŸÆç㍓‡î•ž‘ΚZq'~¯†Ç P#i ”Œ.‚Rº+çZ±Y¡Ù3ÛAÌð†§§+Aé%‚Ò[¥¾%1qÉVx§ÑÄ%À¼úohX¯oWt,3©c·Näqq¾%(ý@Pr;“d2’ (ú§Fú'AézÒAég£æVúûßÿþ5Û^¤uחUӚ0þÌø[(ëO†3þyæ̙MÑ ñ·Åq»víšåؼyó¤„uë֍L?`ü­‡è÷ŠsòäÉÏ2þö¸sèС8ûõë×!±G% èf홨”ÅŒîft'rè[lÚ/’s䆆Áæ”ü J¶ù÷ îQcÑÞÀ_iåÅM^Ȥy™„5v¡uZÒ²¼K® n¥?ÞXûäÏÀHwJ^ΤIËÙöb$-̦1’øq!|´y‘‘ÆCâ¹ÔX홚š*5#²[°ŠBQ¹™ž{ÑsFŠ‰»7ó@VÒƃ‹IlÜ󎈚Ú8¿0wA$œn4Ÿn‘©-²x1‚‘’ÜxI¡¤RÒ(é\%Cˆ„-29xGH%›z„äð£¨!ÙΝÔ„‘Ä<·Ü7Q.©¡övW·3©[·n¯êðË_«+éåLšÓ²3 ˜rŒéƧu—/_¾ &ke£9Yëg2SiÍA£þ5§ÖøšÅ¢¿6 ¯ä–r#ß]'(}DPºâ¥÷Z%Î^¢Ü”F—⬁§Â}ŽSá>Q={ö쫧NZÍÞJ9Ã[{xË‷Tæq;‹ðvŒÏGnjɃÊÂOЈt–âNfÔ͉F EÆà]‰ ÅDŽ €RrVÉð€RA©ÒˆŽÞ‰ Ô™ ôAÉk†·îÞX€¹ñ‹™¿¦™‰K´oW9àíËL”nëғ~”€=?I ¿”þ)ƒŒþ¥ü¿ÿ÷ÿþ¥BþIÑhI¸•~`üí[OZ·VVé*ãoçƒq ÷Dü- wuOîï–(ÆßbÐÎËb¤sãÑÎShç1 hçÁ‰Œ¿9¤o8ÑÎ/8¤O:¤;¤÷$HËðÞ(`¢R3ºÓXz2)íÏ9r£Î ç€ÐPôâ€`<.ö@˜E«?ž(³ž-£ šÁ‚‡NoÆ㧚ð4*F<—²O¨¬ç£«¦¤¤HJƒèäääd·HMEç“ÿ ðVx îV½x‘ªFPâííÅM2‰7¿æ`ÒhIØ +/ZòÊònŽ–ÚêVòÅß|ÒFPj1ꦕëj13©õ€›–³Ý¢É˅$ܳâW‡x˜4Ÿ‘FF ÓþîùkqB!<µ0>Ó¢hd”{œ¿È&’´a œî[#¥ò*ÓX(/ƒ’)á;!Y”l–ƒ’Cd’KÉ£´ã‚ö\/ŸÛ²8q±$’’D´©¸Ý﮽ÝęT_WR8“¼2“´an-f&yœI:1³hX ñS1™(홃ìN­ñ»X´¨ê#¼J_”> Â*…beJçï +”J(äzUnØ°¡”-ZôD‚R‡)S¦Ts†·RÎðöÿ±wÞñQU[ûÏ9Óg23ém’If’„:¡( +Š zTTz•Þ{S:Ò;‚Ò;ÒA¤WQP@¯z½zïõö÷}üžgŸÌœ™ÃLn°Ü{}ßüó|Ó÷>{¯ïYkíµª²Ã[6.Éew&ó¸Ó«âÂL­„]4¥‹üä±ÂdFݼɤt\‰É. ¬+ âŽÇŸÞ\¢eœ”@U•mâ v`JJÍJm J] J=J J£XBi2Ai6A©¨Ãێ;6”ÔÊ'H EÞÀ/7JŸDÜ¿ÿs‚’HOúZö|+€g’”þ ûóŸÿ¬Ð’´dĪ[é «˜_Z·è–{% +ƒ}.8þ¶ñ·mɌ¿¹0ç+[àÆu0Óá]²dÉï¼yóºgΜ9³KæĉÛfŽ5ªYæàÁƒyñóë3Q©&•ª0Q©<3ºË”<.Œs*A)‰ GPŠŽƒ tÄ`õDFa1YtÞÚé˵a½¬X~z3V£Î„u)±Beׯž¢ËÊÊ!gff*"…¯×[*?³ˆ +œ”ñíÀ@¥'±«þ&±Ë‹ý^ìüSXߒšå]|.l¶R¨J”¥ñ·R)!(ýŒÎ$5ঞk ËH’ê=RñHCFb5ŠÅùð)Ex<ž"ÁŸ²_t|²žbàk|ßÏÌw¶p9ÛøivҒ“ß šß%Viˆï—ÈåœÂå, +"¹yäQ’´E#l¤Ge<‚T äS*ú¥Ÿ'¤²"xm Aªóyd¤Z‚‘Øéªû‚>!±\’„íáYŽ}s¿3©ç·(3I=æ6iÒ¤bŽ¹e&8“èó¸LgÒG¢È{Ýa²Ïك쾞íǔ®°Î_°â‘Ulƒ|fÇÿ}…G?&(]'(]J_qÁv¿/@) <€¥sçÎ-Uúá”j8p`¬¥:¥ºøº/Õ[±bE‡ú”f͚ÕøqÀÉõ Jõ†Z•Þ*ðÀ[n-\¶Y5p‰f( „aJ)KÊcÔ-›Q7/®Ä$76ÙSžšIgâ±7ãœãÄ^\ž T… T“ TŸ ô4A©9A©Aé‚RO‚Ò Ð6š 4… 4‡º„ ´– ´™%”v”D‡·÷•ÑõU¸Ñø4‚yܦ/@‰Q7  ô{™Œ$ƒ‘þHPúƒž´d€Zú‰n%³Ï­˜ÖÍø›“ñ·èO>ùä4ãoÇýñ·"þ–‚oµ:Õ›¾iÓ¦)ëÖ­íÁUòš×K/Æß^ʜ_X lÏíø¿;Qxôã<ï£x¼â2A鬔ƒÒúò°ÝËJóTPª¹k×®!u@s}ü Ô±þ… ëÃv7®/@ ¶[€RµÇúõë—_»{÷î¹5 JÌãΨ‚3­"vєòµä<¶+ɦ§C% qŠ ƒ­‚R¦JìòvÜ´V±áR®EPz܄q Ô‚ Ô^Pz‘ Ô‹ ôAi Aiª´xñbJK Jë”V¸,ÝI =L ފ*”nj@)‚éI"êFPú^úá‡þ@Pú£JùË_„ÑR[é+‹šÖí+«¤´5‰bü-†ñ·8Ú!Æßö0þ¶…ñ·u®C‡-cümž{ëÖ­ÓÇøÛPÆßúyñ³^aü­s&®¦Ö™Ã‡oê8p`Co¯^½ê2Q©€ݕұ”MНŠÁÎ%’1°‰‰XqñXìѱX=‚Rd–•ÅSiŽ¤W×Cj°` êÍXÝ:ïlŒX¦²ËYOÑqMëÒÒÒ"d¿HBRSS$¢Tþ5±LO‘hXJ…'•›4È$ö{±ó‡¢%5'ì‡z&N„+©[©”Jå‘)(iκŸÂ-.ÇPÎ$µH’š”$Î4¨ùHÂÏZ<#‰;±ÀB‘‘X—b™úÖ¯¤ˆËå"óO!:ŠžOÖóe¾‰oeæ›ZI_6.b;?Òɏæ׈åJPºÖâKºøuÓ¸ˆE½H¯Ä#þL'Ê!(i©ðË+SªPª²Ëg5¿TgçO!5üRÀj²wz-Y0·FbÀMbö¶ÄÚ۝I¦¢ÄÌ$ óû¢Ô§OŸî,ÀÝ_)À=qâÄb +p«5“|ÇÜN2Fq&EøœI·%áL£EŸVÑ~ŒÇ”®°Î_)y2/l{vüß]'žr› t#”Nº} ´W´0QA©"A©Ê±cǦWÇ·'@©6Aé1€R·ºË—/ïX Ô’ ôlýɓ'7¨L©SÀ¢‚R^F£”°c +Pr•ÇÝgr. 'e3êæ¡3ɍ‰R@)’‡±ÏŒÁ°ç”*ر WU@ ›ï¥g(é1ÎJ/”z”ûAiAi®Jï¼óŽ¥-â½Ê ”®²„’R€ t?‚yÜÁ ô{”E?ÈÀ£t>ù£ž´$ÜJÆ ·RQZ·¨Ö-Ê*aį2þv>Xv*Ÿ{4žñ·Ä3gÎlgümC +0ye*€y!ãoo¤ƒð&e¬Y³f¤gɒ%ëá1cÆ Œ¿µË9rds/®°g¼¸Ög¢R-&*Ue¢R7.Ì‚’—ÕÎӒ9Î¥øؼ˜8€’3†ùQ*T°:±ÀÌvM“ +Ï`¥»×‚Õ¨3a]ꌼÇ1`ÁÊz®i=×´Ž"§¤¤D‘„$''HD©ük„c ˜™"Ñ°”ؤC!“Øۋ§%a!Ô¼%a?Ԕ%µÔR(·’”B¥uþ­4Qéÿ²£ef´cW ¥¡¬ó׊Cò%Aé>Aé3'žòI ž|#p%opN% Á”rJo•(-'(Í'(Í (/( ­Pê[ ôòc¥Nu,XЪA©@éɺ£G~ì1Kõ:@—Šµp—%(eóÀ›‡ÞÜù¸&]åJ)¥ä,f&y0=”\)¬ šÈŠqø3‹]\sØ†óPÂ\ÛJX…!@iAi,Ai:Ai; /#(­'(mU@é½÷Þ;ÂZ“§JçƒAén+øAIäq+Q7‰Î$ÉJ’ÿú׿þIùAï£%Õ­ô[³˜5­Û×-·¨¬Ò'Ÿ|ò!ãoïÅaÄ$`Äw%:ujãok\ï¾ûî’4Œø7F|júºuëÆd`ćx0â}¼ñn^Œx'/~o+/~y/ÐôIÐô1&*UgÜŠÌèÎK^f¹`ÆÒSD–}"A)6+>*ëȍÅnsbY°—¦HÂmXƒ n`ôf¬K‰÷8FÞí°t%=×´.))IH„œ˜˜¨ˆ$$!!!@"Jå{€pRQ1Jå¦PÈ$övÕÁ$v~ - !l…°Â~h‚pª[IÍVú)ñ·ÒD¥R)”~rÔM=æ¦f&…r&©7‘Ã'âÓª)# G>2*Z—¾µ*qýª"+‚tŠàÉz¾ÌÀ70q›ù~V®_ׯw;NÞíÄðn'Žw; ¥dFÒS Jn ßÙCPÊ"(å”ò”“k"5›ŒD¯P?#U'ñÔ ø¥¦_jù¥¶_êÈ<×ÀHLJ’1¦OÉlv+ә$ûœI­%LOG sù‚Ô»wïîÒ AƒúJ#FŒ"?~4S¸'Ô€_ɐÐæÎle’ñ^žÆ:ÌÓXïóØú[¿$œI>g’Ò~LBdû±¯Dû1vÕø†u¢¿QêDèmüƆ?ØAKŸ”>†Å¾¾ºJP:ŸòàÁƒSi@ƒ£˜í}Y0ÛÛrð‘ʝ?~E>@iAåãǏϬ¶˜Pf{A©_m€Ò+¥Î¥Öua¶›Ô…Ù~Š T— T£6Ð¥’¥’2%¯”RË4SrX…ÛJ)n–POÁ¼ PòøA)O%\ÀÕJu,ñ&l¹ +(±àdGæ(u#(õ Ä~¸ãü 4Ÿã¼œ ô–”ö)Ç (±ä›×J¢„’¥¥¯"xà-‚yÜ¥?”~üŒä%•–T·Ò·bDµ«Z­›e•÷îÝ»Ŷ&Œ¿düípü… ö&â mMÆW{‹ñ·å©@猿ÍLß°aÄ €õpÏ¢E‹ú3þÖÝ;mÚ´.ÞqãƵõ6¬™wÀ€X( ¾[FM&*UIÇ~P> #^&—­'ƒ–Œ!NNd] ‚R AÉÃ#QX`V»ÙŽÅn²1$nÅjԛé6a…ꌼÑ1`éÊz.q=W·Ž"ÇÇÇG‘âââ%666"¢T~Iá8gA Fi¸IE&±£‡¢%Õ·$산š \(·’°8ê!¸Òø[©üëA©¤Q7µ®¤zÌMÍL7š€›8ñ ²ùÔX›ÊHª IõiðH,I±B±`¥`‘ý¢ãSô|²/3ò L|+ ßÔÊ·ä9ø‘ÑüðX~x~¡$~5¿¤›e€3J™¥2¥<žä/Ϩ[¾ÌÔl?#US|F‚Œ°œkRjé`§kKEð¨ø×c”º:’ԱⶎŒ¤cIIÛH¦3I¦3I¦3IƲo'c¢:K¸­ï&ῧ4xðàèa¸Än)(…{ »j¬a +÷;þîwiÀ1$ôâé€ UœI<%œI]5XQçëªñ[½¯òáoM?üðÃ7füë++ä‹HÆßxޝhXì[¥k ,¦DPú€ t, ´? ´ ´±,@ie€ÒÂJ¥×«‚-&V(¨‰¯Û¿@éÕ:ø Ï?†Óæ1€Òs”>†ŸZ¯~tA©rM\ãåJ9l…›Éoéù,íS–'Ö J)Y˜ž£ni¬JPr'²zz«^Å`󜘷Š!@éY‚RË 4ÔJ3(IA ´-”>ðg€©µ&5 ô-Aéû ôgùoû›":ȟôø¿?èV"(}gn%MZ·¯­É5çÝ»w/DƒÍ>ˆÅ‡cüí݄³gÏîH:yòäی¿­v¥¢g¹ÓSÒñ;Fg±_ớ7¯ão/y'NœØÁ;räÈB/ ¼1 4ð`©ÃŠJՙ¨”ïÆuš—†Ïta$ӓY´>‰µÇJ±qXGQ%{4˜Í‰¥f±3Y0æÓh…!5X°.õfúMd$#oy XĒž«['„[Ž‰‰QD ¥ò‹ ‡] F©ð¤A&Õˤ:˜TZR#qÂ. ¡  K¢f+©‡àÔJ”%¿•‚R©ü8P*AzRب[¨î°Î$5à&Î>¨ùHªIe$Յô0‰Å)q­ª"ûE§ž¢ç“ |™‘o`æÒµòMm\ºvÞè8y£C·RWm"ïqR¸jSY8 ä•°j³ J¹~L9™Åd˜ÙJ2³²•´#ÁHÄ#bOa9ס<Bêê)~<Ò2’Ž'ÜtÌÞÖљ¤£3IÆ,´–13dL^W™õdÜà÷‘˜Â-;v£AYÚg&k ÎgÔmk ªmow3ꦦpÈzY,úºbÀbWû’ÿ4–(-:©]5 "—X˜hÈ×¥/#ñè}‚Ò]‚ÒDZxíõÖH幁ÇÓñ2oÞ¼¹³ÌÕ«WßÎ(­.PZT ôF0ܤj ¹‘¥5J=j”ºÖY¸paÛ:¥fuJê”ê×°Ô¬t©R€k¼Bu\¶¹l…›U ·–¬ à.‹áLÍÁ¤¸J® FÝPb+>‚’×JePÂ|T·áz ô¤JX”:±…ÉË¥¾~P J+Jü ´_Ò Pºî¥Ï"Xk2<ùu(a8•¨Aéϒ”þJHKEn%µmZ7Ë*9ðA—”´n û Æß%`Øw'bØ7'cØ×¹ðM—¥‚Oç1þ6=Ã>Žñ·a {?Æß^aüíy/†½ ãoϱP@C†½žÃ^a¯ÌD¥riº2©¸ø=)LKÆ-ER"N|<ÖQt,•Æ`ÙGFeeeYXñf;ÓmXñ+Ãäf¬P kUgĪ• ¼ïÑs±ë¹Îu°Ó’¡Šät:$B‡ÃQ*?U4cª +Ç^‘Pð$6iÕˤq0‰]^õ-©yKÂ.¨A¸°n¥°iÝaão?%QéßoÀKå?”JšžT‚¨›zÌMĘÃ:“„ÛUdø©±6•‘TR­Fî˜\¦ªÈ~ÑñQ=ÅÀ'ù2ßÅÂ¥kå;Gò3ü´h~n,A)ß%‰ßÊÅ2Àn‚’‡ ”EPʑð;ÊʬŸ-³øIUEV¶ŽG:Õ{$ð£ñ˜RWå,¤^©ï—Çõ¸?zB‘l ç 7=Ë%éX +@Gg’Ž5“t˜Š¶:֐1«/Ê0Û=dÜà÷“GŒ1Tš0aÂiúôéS¤¹sçΒ–,Yò¦$¢nÂvïرcb‰¶·¡R¸o0êö‰¨ªX´`$Cï”#êŒü˜!ßXñ¿!(=pÀÚ´º+Ž¾‰¬:)¾¹ñ½ø´]ÙøÜM¹.\XSîôéӋóA³+”¦T(®±eË–× +`±{ÖZ±bŋµa±Û׆ÅnQû™Ú°ØOԂŮ]»Z ŒF~5\¶yUØ՞­p=¥t‚RA)5S€›ò”ÒPb+>.ÃN÷e˜F”³`ìŸ4áÞ´ A©•Ë¥”,@ië(© ´ ”¶ J·ý ô…”"| ô'ÁH’‘þ"ÿýïÿ‹Ê­X- (­[”Uºê¼sçNQZ÷µk׎Æ_¼xq_¾Õö¤'NlL:¯t¢ßLN¿áXOJ_µjÕȌE‹ ò̙3§'ão/0þ֞ñ·Œ¿5öôèÑã  +¨÷jé¸NóÝàûÜT b&+0¸“aßR’`î`øbãJQ%{4–šÍ‰eo±Ãhš"qÛb´2BnÁŠ×›±Vu&2’‘7?.v=×¹&ZH„L+.Db·Û$"”DFF–ʏ“PÊ¥ endstream endobj 88 0 obj <>stream +4ܤz™T“JKj$NØ5Ê­¤– Ö¥ñ·Ÿ’¨T +JÿG姀R¨ô¤PgÝÔ¨›šÂ-¼¦šÌ$ՙ$Ü®â<„pŊ8¶kS)"2⎩Öª™¢ãÿ Ñóy¾ÂÈך¹j-|?ßÙÎë䂍ႍã‚Mä‚M‘°`ÓJîl2%lðeØ´¼¬\PPPAƂ­DgR:“4ŒTG/ðH†¤¥¾äñpò„‹]H†ó)=O¸é1ºÏèÙ¤DOg’+¾•»½ŽJt°QÝä~ýúõ’ ÙPc8[´ŽgÔm:[´Îe/û%£n’/ê¶3 ê&l7ì¥Há¾Æ¨Û-žX±î1ꦖöQ:±âwJC Qù¦ü;#äw¥ßZðÀW6ÆßD¢R”?£[9úP:KPzŸ tÈsëÖ­ÝY°Ø›sJëÊ”–VÀ·š[éСCÓªìÙ³gl5€Òào½õVnµÞ|ó͎µf͚ղàäÙZÀ”5ñËë` ª”*”ÊVfWûŠ°Ø™å1ˆ,¡ä.ƒéI#(¥”ÒJn‚RA)ÓJåJ•J5l˜ +”ÌA ÔÙJý‚Ai¦J¢7LP:ýÏAéw<ð”€Gõ‹BK¡ÜJiݘ¼¢´nLèu–Uºuûöícð ދ»|ùòAÆßv%ž±Z­ÿ û…4¥á&LªƒI¥%5'ö{±ó  ᄅÐd+©ñ7a]BÅßÔóoa•JA©T~fP +›Ç­IO +uÖMuS¹…u&©·°Œ$VžÏ£^„GÜ1)²_t=5ðÉF¾ÌDZ2ó­¬|ÓH¾½ƒ͏Œå‡'ðk$KX«©Öjº„µê%(e3=)OÆZ-/ãÇTdÔ­ŠŽe!u0½:feë}ŒTä8‚™}Ü ƒó„FŒAÒÀ/O +F2À¼74`Å?mÀ?k`Ç[=Izܵѳ€3ØUǨ›ŽQ7™Q7yìر#š(û£nì<¶LbÔMÚºuëf)(êvÂu»äºÙn¦Í¨Î$CïX'ú{¥¡†¿ò!Aé;ä[ øš ô¥O¾çÄË>Ýâè€à\ʽ{÷N¦Ý¹sçH@io&@ik ÚúU0tèк5JÕ»wï^¹*§Ïè% ßÅÆejç2ur™Æp™Æq™&²uT +Ûkº™žäaÔ-[Æ×͕±BËәTQ‡[™ªt&Õ`À­–ž%‚©â +"žFæpbÂçY|ÿ÷´ûŒK¼1­sž·jf½P¡ SÑƈééhĄv5ÐXØ[?lØ°Aú±cǎÐÑbëÞxãéò… çÊ+V¬X"¯_¿~­´e˖MҞ={vJ‡: ±Â¤ä«0Yd¶EU_ùâÃêÁ嚎‰Ñ¢–°ÎáVúŽ ô­Õ LTbFwèërâƒΤàƒN¤á#eàÃw{/_¾¼9ûìÙ³ksOž<¹´ìÑ£GçVØ¿ÿ´Š;vì[Ð1¤Êš5kúT]²dÉËÕæ͛שúŒ3ZUŸ0aB“j#FŒxª*¢^•^½zTÆ¥\¥"˜¦B…¶mÛæ•Åè–ÉÅÌdfãêôfâêôdàêô”<¥L‚R™xöèã©· +¥*‚RdP2” PšP*¢%k…–hÀ5òÀ4ÿ2â1 ¿¤„…§°´¤Fâ4A8±ßk²•4ñ7Íù·°…4 $lT)(•Ê¿”JÇ6=I­ ‰º©™Iš€›zfEe$n‘™¢SD€ÄÀç™ø +3—©•oÉ7u”¢øA±üÈ~x²„:U +MgÔ-“Q·¹R¥J™”OgR~Qu:“jêY’û#¸üx¤Ï3–‡åikyÆÒºuëÆ ñ³ vS3†½¹&º¥©k×®mM˜¨NÆ=z¼`ìÛ·ï«ë¾ÂkúñãǏҳ¯›Ž1  Ú|¦m™Ìô$™EDz’täȑChä„.)ª0yãƍügÝ>לÁ’‚ªúüQôÒ(­} Š[É;ý vº(QI”ž(Ý$(]I‡KœL)qãÃ÷zð5¶f;wî­2§NZžwìرåÞ}÷ݙ€*nÚ´ixåµk×ö¯²lÙ²W«ÎŸ?¿Kՙ3g¶­:qâÄfUGŽùt•Aƒ=^üR».êjù¸l+–Çø•+‹©ÈÍÅôdgƒh3½°ØÞ 6ÀMÃ4f²2w N‚¦V¥z"ôf J£F +%Y€†] v>J"s¾d9J¡@éïŠü×ý×ßeH‘[‰A8}[©¨¥Z-€iÝ6_Z÷Gê%Å­„ 8 R= ؝ˆ ØÌ´îu)˜€e©˜€ùi ÕnLÀøô¥K—ÏÀôgZww&  ÓºÛ2­»û¿=Í´îÇY²V.åªé°[Ò0ö¹©ì㽆;æ.…ñ·„܎ÄÆa+ˆŠñz½öh–uÂhZ,wÉz6˜Tƒ…çWÍ< a"(ƒAI/@ &ZR@‰[JÒ¿ÁÿòËÉOá½^ÿÓ$,7…¥%5oIu+©ÙJê!8µ¶’°a•JÑ] +J¥ò˂Rñ%”4•4 ¤ö,9wj»Mz’zÖM­ ¼°¡2“Ä ËHX—B(é)>Åè%K0(9¹B£y+Ç[™D ûs +£nn¦'yu˖±8óèLª@gR%:“ª1{»@X‡7 # Rù`G!kÛ¶m…4bã”gBHc›x2ƹ‰#þœcß‚©heÆÌ´7cò:›`^2ᾇqȐ!ý 0ÖC 0Y£õ3f̘¬g)nKqëxN]†Å~Kfz’Ìô$‰¥¸%¦'ILO’®^½z%âÖ­[J…I%êƳnŒºEø¢n¿W«úôÒð×ò1@þHPú=Aé;‹ˆ¿%*ݍúöÛo?Žýú믯Å”.$>H›K»yóæ»ø;¼.\x;ûôéÓ«r€‹ÊZŠPié?Þ­ôËáÑO¡ NZJÀMaiIãVÒd+©ñ7a ÔóošD%µ­‰°.jG“° ªF@ØbJ¥ ô^~$(iJ(_ ԁ·PyܡғÂFÝ4Τ F’üŒTJ (™ý d#(ÙùÎQ¥X~Z{Ž'KXœ©Œºe0ê–)ã67GÆ o9:“*êpS•Î¤z×Ú ¸Õ5°ä‘8¥¦0’p!ùâeÏÒ®6Q`ƺ© ÒDH¤Ož¥4ŽdgŒ`yVy +»© ÃÞ̆5]hÅ}Ok 樃¥{÷îϛûôéÓÍ4pàÀž¦aÆõ7²è¡Æz¬áõ×_Ÿ¢Çýþ,àêÖ­[·Jf\™ pe–ˆfzÒQ Æð”Äô$I“ž$º³~õÕWJÓ±MÓ±àÑ¥?+n -ýÁD·’ÏÓÄß>SzäÂN;})vúÃdØé©°ÓÝø»<@ˆM™~øáÚ2'NœXš ;=·,ìô´ò°Ócó7lØ0´"ìtßJ°Ó/W‚î\yêÔ©­+ÃN?W vºQE°ããù¡ÚØ~¬\ǎ+屫F‹EgÁXçx™ZœN‹(ÊNÁ„–IÂn›•#(UŒÆüVu>ýôÓ5íÁ D¿^k“”^ ¤góá`PšOPZNPzK€’$ŠVqØC‚RP°³”0`ŃÒ?„È*-ù‚pn¥ "”Õün¥ëŽàjt+Œ?{öìnV (r+®—±ZÀ<Å­ön¥aóæÍëê™0aBïˆ#ÝJØK÷»•Üû@·ÖVJ’p+±ÿ´p+ÅÂ@:·RJJŠÅ‘˜˜hVÜJ°«+Ö¯êVÒùÝJ²Æ­ôk£¥ÉM?…‘¢Ð#IIiIãVÒÄßÔ´naB%*…Êèuô­øa‹)•‚R©””Âå.¾„R¨Êa¼iò¸5ETPRëh2“|uDÂ2’”L +(áµV.ÎH.Nß9š‹3Žw1‰RZZZ +ӓ܌º:“*W®\AW£FÊt&U×ãÕbÀí1l¨†‘„ ©HFÂdè=‰u©ˆÒÔ/MxTȳ<¹Hø§ØÅËÀHÍ#1-m˜™6V6Ï°öìÙ³‹7î/›a§{™`žšÆ7ÜÈ6ëiú… ÎѯX±b±nýúõ«u[¶ly[fÏäñ® 9&1$1YFR›Ž=œžª—ÆŸý ôZˇÖYu+™5ñ7v4Qão±¿ùÍo®Äß¿ÿ\Øìd +>üH¾ÆÞt|¡­Þ3gμ•õþûï¯È9räȂ¼}ûöÍ,»}ûö‰åA#*¬^½z@þâŋ{Tœ3gÎ §OŸÞ¾âøñã[T>|xã|°ã“0BuËcÀ +ÊâÚ­š‹I©X†Å¢³°æyqæ¤ã:Í¡#‡m[s’Øá-R>–µ& J՜x^-;^Qφ×6´ú@©•%#AÉJã”Ô0‚’,@iãƍo)ç }Õ=(©MqC»¯àdI@IúïÿþïëVz¨Z&U­ ÜJWœŸ~úé9µáVÚàV:xðà*.Ÿ7Sq!¹•pq=äV­wdµ€–¬Ö-ÜJOy°ƒº•`ÆÊ ·R*›Æ·Rr[)&.Ø­äd§!áVŠn%ҒEВp+……ÊV +Ÿàýž‰–J@²,#Å#SX·’&[Iìí¡•4…4Ýa¾…­P‚bJ¥å¹Kå‘Aé‘jM–”BxÓTO*>=)lÔM%,É"F‚ø¨ÑJ‚’ d'(EÑÝÊçG&1ê–ʨ[:Ϻeʸ¹-r&aI9“°­èñ³êðÅÙ‘³ÈHL'RðH¸0jÍçØ1ˆŠ8 ͜çœx ©"x^­ðñdf¡…‹¸U$&ªmd÷îÝ;Ú`¢»Z ðŠ…ÍëͰӃL¸£a3Œ7‚¦-Z4Wc½D¿aÆ5ºmÛ¶½#ïÝ»w§|øðá2{–0=éC‰=K$VO’½D4É_ôP¸1þl€ü`ô¹•¾3kâo¥»Q¥c¾úê«kq<¸Hø ~,_ã]÷•+Wvdœ;wîíÌS§N­Î[,ÎeÌÎÛ¹s甲ï¼óΘòk×®\aéÒ¥}òçϟß-æ̙ó'NœØ:äȑÏUº4*ߧOŸÇËá¯]ƒX#—]5Ê°Xtk z0yyé̘a~qn +Ìv^ð¨l¤B,þ¬I®æ„Q T?R€’Hc%+sûA©AiAi¬”æ‰Ô0‚Òz „§dÔ2è‘s¥«¥[á@é{¥PŠPA‰Œ¤€Òô¤¸• Án¥à"”wm¾j×Y- °%pU¸•v)n%àêºàêRV ˜—\®¸•–,YÚ­\mìVªíw+廕Òýn¥DáVŠr+EF±#³•Ìvl +&‘­¤áŠÏí֜„ U2àß_„H•ÉR%@¦G¥âñ¨È––BÅßÂ&*…Êèuôíg%aóJA©TJJ^”;l %Mãqy«ÍÝBxSA©øô$#IŒ”DÔÍJPŠä[9ø¦ÑÁQ7áLJSœI¸wɖ˗//œIùt&Ua)€úúõë×6à·ÕcÀM$%‰|¤@F üD +¾Æ¡Ô«W¯îNGlñœ>}z}æñãǗe P*Šxþ8PòÓÒ#¹•>WÜJ¾j·Ò‘¸óçÏïKÀ×ݖ„Yn¥•!ÝJ˜Õ­ÔÍïVjåÏVzʟ­T@·Ref+ ·RÅ­„;‘4º•’…[)!//¯È­„[({4v%'Áis»C• [`)D%Jé©Yý“߯¤,U<7L?(ih©x·R¨ø›¦P@ñ $쇔„ [L©´üT2˜á¨ëúõëûÓ.^¼¸=ýÃ?Üè=qâĪ¬Ã‡¿™½wïÞY9Û¶m›’ ü]vÕªUƒË.^¼¸w¹9sæt+7mÚ´ÎåƏߺÜðáß+;pàÀ§ó•OäbœËÁÌdãÚ­šÉˆ\±ùé˜FQߧ¼ ´T> xT!R1V‰Á5¢ð”Ú<¹~$^֐ fM•”z6Å51IÌPêÍDúÁ¥1¥©:€Ò‚Ò6\KPÚLPÚÍúCǞ t6”îÞ½û©”ŠRÂ@éO¥¿¨ á¥ÿREu+éT·sí A½MDµ€¢"”˜…‡ÜJ¾"”En¥3gÎìJ|ÿý÷7Ñ­´6Ø­4ÃïVîw+u§[©+ÝJ혭$ÜJÏЭô„ß­TMq+a1å1I,˅;‘ô”êÕ«»’*Uª”˜ˆû”¸xlѱØJ.¸d€ %+]Xb%J#‘I­Û­ïVœt9 –Ÿ³ÚOy«ô, KPa¹©¤´ô#A)-Ó$*…%a!45BS*”–ç.¥Rù׃’ZkRJj‡·° ªÌäÃy܏u3GÝþ¨[,?#Ar¹\"…;)ܦp‡v&=þøãjÀM$%5u Íd$‹`$ Sa$F­•#ÙځÑmãĈ·‰êÞ½{›hHëH+JËXHam‡ç5§4‹Ã,<§J,¤Y hƒçµŒîÑ£G›¨Þ½{·wâ&½³èEû°aúGŽ=º¯ –i°¤0Ê<{öìI&Øé׍¸Õ_`\¿~ýrÃæ͛×ëwíÚµUwðàÁ=º÷Þ{ï°|úôé÷eÐÈY ñŠDc-ÑXKlî¦ÉãVA)ÂJEÅét¿ÃJ2ªiݾøÛW66ʵ3þædü-t=y1þ³Ï>û0ñöíÛï%ôÑGS/_¾¼Ë}öìÙÍ'Ož\ç`,ÍjÌËÞ±cnjœwÞyg|. pxÞÒ¥K”?~²3gÎ|¡ìĉۗµæ"›ä²«}Ư~ÌL,LTA&k zpÙV¦±®˜† Íw5nÜ8?×nÅH¥8l´Ucð@¨¦M›Öq‰·Ã¼7´1¹ÞŠU!@©#Aé%#>H€Òk¥Ñz€ÒÝ… g””Ö°*Ã& €±‹ t‡ Oð°á‚Òe‚Ò ?()%>ý ôAé%¥à \ñn%¥¥ß­ôÉ£¸•4ÙJSüÙJƒƒÝJxN¸•šzqÉ7¤[©ž;HA†˜låûÌI­W¯ž×…"A¸dmnwp%JAK¢Á‰Z·ÛÂNplp¢3²œƒh'ú択pþ¾¹ÚºÁ¡µÇë/"¡>RÍÇ ^¡ªxn*™JJK’$É#¹•J +Jš£oђZLIJ +•‚R©ü@IS”;(iJ(…ª P2P +Láö’©Ø¨[Q +7>ÒŨ›âLb +w‹K8“˜™$²·ë*7_RRc¶³h*Ɋji赶c$Û80Îm›vQ={ölûé¶1@œ¶±6qø³U<¤e<-LÀóZPš'À’4KÀk›Å ÁŸÍãøh,ž×’oÐ&§CÔÀŸw2ä%îÙ{ØǎÛ/rÒ¤IC¬¸™m™;wîdóâŋß0­Zµj¡vz…aëÖ­oé÷ìÙ³UèС½º'N‘?üðÓò¥K—Î1ûªÄ<‰á ö²È«ñ»ßý.¤WC%µè¡šѸ•Óºýýß"a¢?wÀD…ºƒ¼}6&údLô‘˜è}©0ÑÛÜ0Ñ2`¢Wza¢ß̂‰ž• =¥ Lôè˜èÁ¹0Ñ}ra¢_Λ:uêó¹’¶¹ Èæ9ìj_ã÷d6.ïzYÏ?ÿ|m/k zD² c@i˜ÐJ.\»•’AF•LUâñ¯j±ø¿‚h\Ùuœ˜îÇíà«F‘˜î¦<{Øʂ9êh‡½d(õ2W_ã‰ÃQ¥É¥Y:€Ò"‚Òj‚Ò;¥¥¥÷J²iÌ%Veøˆ ô ½yŸûA)ЛWPúŸÿùEd.”[I[„ÒïV +îmÖ­T”­ôð!¸ Jm¥yóæ n%¶ÌíÊÚJíéVjÁ–¹Y[©{I–ì®Î’ÝÝXVeÓ4h•ê/ ävc!ƳÁI iÉ) +,‰'δ´4‹´¤´ƒ³á–Ç`ÁšV›çÊF¬sّôØAÑù$Bö‹N"B‰poÿŒöƒD®*aÑJCPxÒpSXdz$ZRA©xZ ++”Ô£oššbJaAISž»”Jå_ +JÔ·xPÒåVA)l % (åq?T@0ÒÃQ7›uÎ$5ꆍ6™)ÜiLá.r&•+W.Å%óeŸ3©@q&5jÔHTÜ~ÊȤ$ëZXҊÁQ)ÃÙÖºi﵏êÓ§O‡Ò± ›öqvñ¶ 6 x U"žÒ2ö£¥y"^Ö,F]‘üٜÒ"ÏkÅ7h »ß!æµ×^{> +ð’sÔ¨Q=ãǏï >bƒ‰m?þd LÖ¦Õ«W/4nܸq¥aûöí °ÓÛô‡Þ§ƒ¹;"Ÿ={ö”|ùòåóò7®2û–V¹«€,g¨<™"P +®å#kjù–‚ão0ùªuÿ–ñ·ßØð¦÷íxû»N|ÐÇÑ0Ñ×ba¢/Äݹsçt"Lôñd˜è®‹/îJƒ‰Þ”Žï¼6ß~©¿c^&~ьlü¶ eð+G”Y²dÉÀ bϘès&L˜Ð1&ºUŒÕse0ØOgãâoÉd^þg°pWKÄVuá®’Ü´iÓ*‰ªñê± ¨šÑxô1'ž÷„—|#ž[lÊénÉú ”^4Y{”ùAiO¾APz“ ´Š ô¶Œ/¾ƒu>ß%(—Ν;wšaϋ¥ë,_u› ôAé †=¿&(ýŽ ô{Žýû?”þª‚RD0#)ò˹•Ä!¸ ·Ò¢·~ïÅ­4{öì>,Ùý2k+ufÉîÖ,Ùýœà߈àê{°—ÔÌÀÀVIÇ`‹’9©O<ñD&ƒpî68IÂn‘˜P¡B…X¥n7ÛÁ±ËIdîl¬ВYiž‹•l´™ô “ތխ3›d#ŀmDÒûEç“Ù/RQv‘_ü¯õ#Uà v× •£4>(•›J€LÅ;˜~²[),(‰/ù#AISžû§€RigÜRù€’¦î/ +JRI@)(êVäLQ7áLŠã»bSMäÔFÝD=oHg’¯€()ـ·§pkbÆ4³1R;;l@'ˆ§cÌg§؅N›Nq쏛ê øW»DHÛ$<Ð:OiE)LµHÆ˚'ŠI¢$âÿ +‰V­âñŠ¶q°ûb‡ú|ôˆ#^Š‚êáœ4iRûôéӇDÂ<±ÂDO±,_¾|–yíÚµošp¿¿Òˆ;ÿ †ýû÷oÓ=ztŸîäɓGu°Ó§ä+W®œ—a ¯2û–tïÞ½»Ò—_~ù@¥ï¾ûî[æq’8¢Îô$mÑC5ØïÆÐC„[éOn%Ñ-oõµoúE$Þþs€à'ÐàFôƒ.Ç~öÙggãm'oG’ñýö¹ðM·¥-6¦;vlUƻᄏȻsçÎٙ›6mš’µnݺ1Ùø½C²,Xз 0åÕ2ìj_ƒÓ>&º0›ÍZ³€œ2q¡?¡dãR®íÆU\† ­îÂU\-¹yóæÕ1ÉÕã!±ø¿Ú1-[¶¬Õºuë'˜óFvEd‘†–VN7ë3Ò˜1c”F˜$FPz ´PPZIPÚ@PÚ.”ö³ ú1‚ÒL¤¿ÀDúk¥ Jw™öÀJß* $ž%¥Gw+ùz›„r+}àVRk+¹•DÉî™,Ù=!}Ù²e#X²{ Kv÷ðâê|à:x\ÈNpÏz±\ždɀÇ®2W‰A¸ri 6,“Z¿~}OÂ¥±nw2i)ž´‡EZ²GcË°9=Åõk¶™Œ6,gƒȤ·`љ)&¬sÙH1€ $½_t™ñ}U$L׈rX]ìH¿°¨Ÿ&D¤;¡ U…"¨PÜTdú‘´ô#•B}û…AImøV +J¥ò/%M?\q9ßW¥PÝKBÒõ&%Ñ©¤ø¨bd¸îT¦pg°@–äs&UñMUgÒczáLâ 7#n&,5Q&[©þhÃÐ)ŒÄëNQÀžÎьÅÒïãÐ9†´s"¤c¤C2þ¯] +¤M +žÒÚ‚jéÂ+ +]°ç-(ÍSð.BZ$ãÏÂ$<Ú*OnÏ7ˆ>|x—ØÑ£Gw‹?~|(PAŒÒPûܹsÇØ-Z4źbŊY–õë׿iÚ¼yóJã®]»68°]ÔدÿàƒŽêΟ?J¾zõêyùÖ­[טÇý±D;-ùì´ +J¿WӓJEµ||…¡O§ à )Æ­„·ú­E¸•€÷íß~ûíÇ×_}+ +€v-¨v!Ðv:ßêxâµk×&_¸pa—ëôéӛÓÞ{ï½uîC‡-ËسgÏ|ðc¦ 21sÕªU#³/^<( cÐ;›]í³'L˜Ð9‹]5²0ØÍ3œÏÒ¡ÑPdgࢮëîСCí4LhMP¨ PTˆI.H€ÔŠÃŸubð@½(<¥ÿÓ,ðÐ4+¥% Yu°`Ž^0\{˜JŒ˜Š¬a5Aÿæ›oÎÔ””–³4Ã[,Í°• ´ t„ tŠ tNò“*OÞ!(Ýž€ï9 ˜†=UPŠðáÑû%–v+…l™ûÏÝJš’ÝEà0‹Y²[t‚›ÊNpcÙ nˆgΜ9}=Ó¦M{ŋëôy/.Û6, T¢ô²Á ƒpµ„«Æ \> ,å1e)‹)Ké) %i)‰Ísãâ±oDÇaßpÆäääDFggg[Ø<,,bS$v£Íív¬XØz ö‰bAÉB IOÑù$BGˆ¤ +s‰…D„Qäç§H¨7ûŸ*¢š‘ܬ*£BÁS˜Æ˜!“†–ŠÇý‡€’ÚǤxPöHJÂn•‚R©ü§R¨~¸?(ÉÁ ºp’&êæOáö;“D +·—õÊ°¸d9v*©(e& gғìnûŒ F³©cЂqQ)¦·£8‡æ„Ñì ìéœéóÙ5L“y>iĈSð¯Ž.H{×°aÃÚ¦â)­Óxˆ:wÛi@¡©BxTˆՂ,UH´j•„'·å[uˆÇýy—¸qãÆu‹Áízh˜¢þNXç¡vÜǏ‰\²dÉ+¬Õ, ì֛fX°•¦Ý»wo4¨?Ai¸S1ÞPšAPšGPZ¦Ã,¬'(ma «=¬au˜5¬Þg «³¬au… t“ ô)kXÝ£Kï7¥ß”¾ãüð'ť祿”þñO@鑳•ÔCpŽàÚJÁ%»·$a*Ö³Ürv‚[†©xݍ©˜˜Ž©™©äÁTôòª•(EƒöÍ%³>Å \]á +x®r:¶‘òLYU@½lžë&-¥$aóHHÄ⌍ÏÏϏŠ-_¾¼#&///2 +Èdu™Ìv¬dS¤×ë5ÚÀMKFF†Þ љ°Îe#ő„è):<*$BV…õÜ$UØACH„FĦõS$ԛŠbrBDʦ±1jÐJÅ(APa¹é§ ÓO¡¥Ÿ”ÄàJjgÜRP*•ÿ\PšQP’Pò%s‚’Ú×­ø¨›HáQ7M +7¾K.ëT`§’*,À] ó9“ž 3©‘±e˖Ϛð˛‹jƒV S;³Tìd$ìe×(0Í 10/Òåóbüȑ#_LÓ¼4zôè®)ç]Î©ø¿Živn<¥ÕʍW´t3LäÆ´’F!K’ªZ¥°†_c‰°É]â'L˜Ð-¨GÌ̙3ûGáî}¨cá…cì˖-›b[³fÍ,ëÛo¿ý¦yÛ¶m+M0э¸ýßn8qâÄ~ý‡~xTwñâÅtׯ_¿ üñÇ×dJ<¸+}õÕW¤o¿ý6tŠŒ”Ô\⨹Ä2D¡%Ï:º•hÜJ Å­és+}ìüâ‹/®EþùçcéVŠ»yóæ{ W¯^=˜®ÛÂÛâë­OÏYáÞ³gÏÂt0È ‘Évµ÷,^¼xˆwîܹ}½,¨$cØ;x¤æÉdq§ãâoè&-¥bBë»pe×MÆü>–dz,©Û¡C‡Ç£;uêô‹[=ã`V³jicšôÕՂÉën¸ö3M:uAiAiAi.‹}.%(­Õa6”v”2IìAé Aé“Ä>b’Ø'¥Ï J_2Iì”ÄÑ7¶!VcŸPŠ¥¸•Be+ij+Ý v+ +p+áڑ„«I¸•Ö¸ðۖ¤âZ›“¶qãÆié«W¯—ÁJ”Ée*xÝ{y3À Ü3^Œd†Bëx0Îՙ²T‘G˲fCv*hÉCZJMƒLNªQ£F|BÕªUcâ+Uª‹mÄ]®\9[ÉâÀݎَ ʼn5m°Bô–¬¬,™b‚ÈFŠ"éý¢Ãó„DÈB¸# a΢V”êСD4"+„z­xgUĞ(šv5„T´R1J%¨°Ü +™4¹_„–þ“@IX¦RP*•_?(…퇔Ø։KM§%µ]IØÂILáŽNá–pƒZ–õ*ÊÎ$=I:“Œø½Ï™a/[Z0.m­É‘½{÷îì€éíêÄÎÿb4Ó«cÁ>ÝâKÎtK‚ù|)eüøñ/º ]Ó‚pãÿ:¥3&÷Øm3ðäÖ°-3ðÚ ðP‹t¿£ +S™–LÈj›‚—uHbíã„É“'w‹›>}zXܳ÷†=ê$Œ±¯X±bJ$nëgYqƒÿ¦eǎ+MûöíÛhº ß¾}ûšüÙgŸ•”‚Sd¤)2~ZR‚paÝJfZgáV²·’ÃçVº r; †;š;š€¯»? l±#ùäɓ︎=º&uÿþýKÓvîÜ9ύŸ:#?zB}ã åœ:Š=ö.Øö˜¨–éýúõ{ÎݳgÏÆi¤¥T\í \  Ç“q×OÂ$×KÀ…^?òx,þlƒАµ?³ÖsŒ´¶ŒìÛ·o{Þ¯«ïüªJÓ¦Mbœ={öX#@iª 4‡ ´XPZMPzGPÚIP: cŽ³}Ìi;¼HPºNPºÍlúÏxìð ‚Ò×̦ÿAé¡Y Jÿïÿý¿Z +˜0n¥ïMAµ•´%»éVºD·Òº•NЭt(þܹs{O:µ5éرco¥8p`…k×®] Ó6oÞü†¶Á †¤·ƒÓA¸Î^Ÿ‡ï9ž„käŘÖgÊR­ –¹JÇ=I76”\ÒR&i)=‹]ÉuêÔIJ¬Y³f\ö’è¸*Uª8cLöèüü|›‹Øâ7™ìØZŒ6ˆÁ +8Ñ[ :3Å‘DÒã)Šèð2!²v“„p« +‘£Q'ú‘Dób;TE´3…Å)D…,£A©ð¤á&5X +™Ô\¦ ât?-ýÈòÜ¥ T*ÿiò률dn”ä`P +ì}[\»’€¨[Dp +7÷¿òLá®,ã›ÖÐaW®£oØ°¡êLjBgR 36óÖŒU{Ìlg; nWLåK<‚ör pæ•8°Ï« °¯g^Iž4iÒË.ÈKiݐ.éÎ¸½îȲ|íh:ÚðlP+Æ&ZR +=€¢$¨éB7þ¯U*,q[^сoú|"ÌÎKñ¯¿þz¸9sæô‹ ‰Zºténæ§DÂPͲmÙ²åM Œ×Jó»ï¾»Á¶Øneì׃7ŽêaîNénܸq^†‰¾&ÃDL}W‚‰~ ùLô·!Mt˜\bÕ0+Ö9”[I ú˜i…[ÉÊ ÖÙJû؁¯q=Šn¥|µcoÞ¼y"þêÕ«‡Ο?¿7éôéÓےß{ï½ .vµOeWû´mÛ¶Ívû}þò‡20B=3•<~•Ý.}РA…npÎsi¤¥T,ƒF.\÷O&ã’o„I~"—üñqøóÉ<Ð(ëãYÆjæ`;¹½mðàÁ]­œx ¦±¯“2Ø*md¦Ai–P‚Ò*¾éFýzì³·Ÿ t”õN”γ>ÃUÖg¸åŸ…û¬ð•¾ç,ü‘³ð'ÿ,h•"TPòÑÒ#¹•Bv‚³ß»wï*ÝJç£oݺõA̵k׎Å]¼xñ]º•vj+QúK¤3·;cÙ²eÃ=Œ‡2׃A¸xµwàI¸Bõ²zS–êzX” ޕIKåIK9¤%/ §»Ù¸8% w1‰‰µk׎ÇMMtvG –nd4¸Éê7Y S$ÄhÃÂ6X!z Dg¦˜ð€l¤ ’¯PDǽIÇSç²_$vS„Ýê…(}ëÅnJD ÄPêÉêû ýËĹw±O +`_i0JÀ“êƒR¹Iø›4Ȥ6Wh†é4þÓh©”Jå‰üú@I +J=¥”‚œI¡ +'%‰¨[„HáÆ}™’Â-ùêT•ñuké4hPOýY8“әÔÌÔ©S§VfŒK;k÷îÝ;Ù`f»Úap_r:ôåèQ£F½‹í¿;#b=™:” “ÐÝ5uêÔWSa>_vl2 /ÐÉñ< FÇLðö™xrÛ,pS«,¼¶e& na& ¨…—BgHa:¤•Oi›ŠWtHá$͘1ã¥ÄY³fõˆô‹eölôòåËG;až&ÛÁ oØ`ZwïÞ½Ò|ðàÁ ¦ãǏo3~ðÁû à£ú+W®œÒAÎË0E ³¨‚ÒWÿ”„/ÃJÚ ì³Î¹Ý¢œp+Ñ:›h…[ɂúÒJ·Rä7ß|ó©ÖÙyÿþý«QwïÞ=óñÇ{ýúõãñÀŠ l?–äëj¯¤È¸vîܹ0•¾Œ´õë×Ov¯X±bŒC24Ù?Ž·tŒß‹nÆ>âl›FZJ%-¹`§ŸMÁÒx:Ë aVÀS‰˜é'ã!OÅáφ±XÏDc¹4‰êÑ£G3¦¤µ²8°}$f¿‹ ³ÿŠoßǂz͌e‡O2”^'(-$(­`!«·J[YÈj/ YaÅϓ2~ÛY‚Ò‚ÒMúõ>¥_ïýz_Ò¯÷ ýzE‰J”Â%*iAÉOK!ÝJ!:Á™‚:Á}fÃ׸mÇúȁ¯v) +àz&tý~,.ŸÃñW%Ê )¢d€W5·à:†A¸! ÂõõΜ9óž„ëÂxh[v9iΔ¥g˜²ôÓì됖ª“–*’–ʺ›5k–Ú¸qc«§§¥`q&'áV&!ÈdŠŠ­Y³¦#Ü…Elub§1;@¦HˆÑ1X!z Dg£²Qž,(z¼VvàíR‘°=†$„=êUQö5ˆ„ââEó +ñVªˆfb³ä×PZ¾ª¥b”ž4Ü$üMjq: 2©& -©¢J@K%h¨[ +J¥ò«–_-(±¸nxPÂÿEÝTV +wȨ[„/êVFò¥pWb +wuÖ¨££3IߤI“F:“Œø½…& D[ ‹1[{÷îÝ%wÂ/9°Ë¿5räÈî1`¤žq0•½@½’ÀC½R@2=SyBÚýú믿šy™¦_¤­è’‰G;eÁ®vÈƓÛfãe­³AA-³aD +³ -HP-hS +=x U:žÒ†¸Õ!¯}>÷ç/%͝;·{Â… ûÅ.]ºtp4 óh'IÁ;ú7"·o߾кwïÞXç ¦÷Þ{o›ñôéÓû .\8¢¿zõª +JWå{÷îÝR@ ¬RJ0šE äˎ)QЇ"?l…[IµÎ¹Ä´Ît+= [é³HZgº•>rß.Ó:Ÿñô‰÷¼Ú‘ˆ_ôŽH‘IÁ¯\êbWÔ·ß~{f*`qbÚ²eËF¥-X°`°<ٗC×= ,ú"óÃ:1¬mª8qد_¿f)˜Õ&É0ÖÏ$™éeJÀªhĚéOÇâÿÇàѦ,Þœ¥Ñ[ѕØ>’Éú¶1cƼlÅDõ¶`f™1)#M‹/žh\µjÕLVüœÏŠŸËJëXñs³_|· tˆ t‚ t†™b—˜RÿSêo”>gJý¥¯9¿#(N]C¡¦"âaPúï¹ÝÿÌ­„KàžÔ|‡n¥[t+]sÞ¹s炿åq– 8Ð7àº. ·àúº—㤠€ëHáñ$\//%z1XŽ²uæàÁƒ›²xw#ÒR}ÒR-ÒRUFâ*°ÖU®w,Y©X’é.ÜÀ¸’±B“ØÂ8>›LL¢¿víÚIÝ­[·Îé`ý®Ê°Î·äßüæ7wJ÷%PËW’”¾§uþã?%u¦%mÉZg£ß:Ó­ôß­tφop‡}n94}ÔXç= §NÚ–xìر IX•¼{÷îÅ)[¶l™ãÂLO¦LH]²dÉÈÔùóç¿ÆQë“&<|ãǏ)õÄÙCQŸAd`ùª¦I½zõz–?³\zãx +K£7aiôçX½K£·&&w°ãè9nܸ—m€Ù^VLÏ@˼yóF°4úx–FŸNPšKPZb(­ÑæÙû¥b*"ž +û §âoªsO¥ŸÅ­dÆç~áw+©%.; ®!Jåv>|xµkß¾}KØn®È>A¸ñ  cöX/¡^LÅ Œ;·Ïd^&¸óYoß¾}Ÿ$-Õ%-–*gtèС|:bNZaa¡7;Û…&%Ȕ˜Ô¨Q£8ö1ŽŽt8cÁ‘ÑXĶ(ì>Äd‡#!+Ð[ :3ž§3Ჯ•ÙèZbƒ"‰Ç7$n’ŽíÂd!7Ž¹¹IBXžG•ˆ¦M›>$b;T%ÔSÄk…ˆmS?HiS&vQ|—@ª%JÀ“ðA‰Up“ˆÝ‰íU¸š2 /“˜¹LÂÁ$h韶@(™’áJA©Tþ7ɯ +”¤bAIO)%< :“Š¢nXyÑ|«¢¨ 'Eø +'e3êVVò§pËØ}jë°#=®Ãïh¤Ç®ÜÄ œI]ºti+Z Z`*_°ÁJ¾,š¬9GÝ+7Æ}yú¬_<`§"3«SÀCýSyòÊ £Ù‡Õ÷zz!ݳðçËِËàÑçs;Ùx£].^Ö&ÜÔ*¶¶0Ò¢ Þ¯E6¤0 ¶ôâÑ6xr{7^֙Æÿ…ܤ¿š¸téÒ>ñ+W®|-vݺu#£ß~ûí‰Næ™v€Ãb¹…1*3t›Îœ9³ÇpéÒ¥ÃúëׯŸÔ?Îé"WJ7P‚m ô‚ÒoéÆ¥êÆøŸbÝJ v+ýџKü­p+YXÐÇ*N^Ñ:ۃ +úœ‚u)2ÇcÁzâ@}»ØU#$¸>‰L˜¼cǎ7S6mÚ4+eýúõS]—q®E‹ ç| JÅ öNÅl½Âäú\¤¥Ì¥¨kÕ*SÛ" ÈԌu>›&›X½iCt,°Þœ%² +£Xˉ—up°Rƒoõ² v¿—o?€ 4Ì @g(M5”f1‹J« ¥úãǏo'(í#(Ձ7N²ìç9:÷®Ð¹w“νOɬ÷èÜûRE~CPúŽQPûA¥pñ·çVúÁõ;Å­T‰òŽ¶¥¯dÀC¹Ýømo1·’A¸7„›Åì±)Jë®Ý¾^\ò¯0ý<ÍmIKÍIKϐ–ž -Õa¿“ê؂*¥cã)ën×®]–õ¤bÏIKÁ­L2‹©'$bÁÆ&€2¢Ø£Ï‹-(2b‚X“bŒÄ£+DoÁ“uf¼Lg«ÈF¼‹lÀ& áM’¤kÞ¼y„Ž››ÌºÎr˖-#$!Üõa?z!Jgz±'–@ÔWˆ TßY) -öS~¸r²]P•ŠQ*< ”ÊMÂߤA&áe9‘.L*-•¬¦¥RP*•_µüǁRq•¹%z…$bO(aý +ZҀ’)”°Î#•¨Þ †AùÀ¨›¯pR£nå%_ +wŒ=ç1ö¡zü˜g ØȄ3©µ CÒÁŒ»‹6´›mȐ!Ýí#GŽìådþn4Ë=Æg&`瘈èb]b}ú§ƒdúz ½3!=²!¯äà¦ú¥\<Ú%Ïë”»Ú¾,¬x›²xm«<@Vax¨ ªE¤0Ò2´öàyíÒù²4¼Õ .˜ãW’V¬XÑ;a͚5ƒâÞz뭑р„ Nvø°ïÝ»w~$LÖ2+Œ×:3ÌØf Ún#M›Fî}=ÌÝY‚ÒeùÁƒ7eÀɧ¥{á@éOłÒÿHAÊ­Û`EÖY['š'¯nÓ:$N^9ùu£nܸq2æʕ+Gcϟ?¿?îƒ>؏¸)áСCkñ£—%áç/H1¾‘²víÚ))˗/K¨æÂø t;{»HK<ø 7tJf–w2¦¶u+W±zz‹ÖþdAôf¬­Þ<–u­bTÑ Û9q tt°Rƒ}âĉÝ"§M›Öӆ‰êÏ2CÙCfŒ™yõ¥7J ×¥·J[YösË~Òáǜ (!(]bºØG2ñ6ÓÅ>c¢ÒãoF¨(þFÆ|´ø[[é¿B¹•ô­„ùøž´$ÜJšJ”š’åvƒÂw2·É„[–ºk×®ù ÂÍLÇÕ91ƒ•AYÂaS–z‘þ»1U¯ ^µ&-=GZjÄH\}fy×ò`—ªšÍ(?ûPk„f¥™2R±BSSÉÉ؂âÁ1 `‹¨8¬_G Ä ±:!f0Ù!Fžg°âz ¸DgÆȬ¶/ñ~}Ȓ¾mÛ¶’Ÿ!é¸×éð‘2·>ûA„$„Û¡"bwԈ覑PÏ›*ßO±½òÓ"ðáEU¤P ŒR Ö xR¹Iø›Ôò¾™Dj“̉„&ÕÁ¤†ãJVº®ˆ–)Á[ÃH¥ T*¿BùՃ’N%ˆÞïL2ñ Ÿb㓋¢nñññ±þÂIJÔ-"(ê–/á[U•ëÔ©SKÆZ}vŸ†zü¢&lU…FìpíL¦ÎæÞ½{¿h…©|•i)½h ûFMš4i@ÌôéÓŁ‘^K„Ì`Ø`D»a 2‹µ¿F³o¤[’½š 閇G»–]´hQçrà¦åð²¶å`a[•ƒýhInj‘GÉ¥ÐýTHoTk–SlÇdŽn¼K×TÀËÉ°=½×­[70h0<6y|ÔΝ;§;öïß?7’íѬï½÷ÞZËéÓ§7™`˜wa˜À'ôLÎÕ}öÙg”n”>Q@‰Y*4ÌßÐ0GPúƒ”ã=Â0Ó Pú'´$ +,… +ú¨)2>묜¼)26ŠŒãΝ;°ÎF]¿~ýD =c±gϞÝë¼=þرcoÿöÎ;Ί2ËûUusηsNäœÄGTD$ƒ‚$A@ÉÐäÐäÔäÐä&ç$猈*æFGg6Ìλ»³»ïï÷ÜÛ·n_n7³û¾2Ûüq>ô­\OÕ9ß:ç<çø=º>H²27¢ vëÖ­sâ@‘Óâ + Ǔ–FÆHsãAKýâIKq“'Oî7~üø.±làËÒ1ìyϊêm},Êëm<üÓÍ®elÓÁ ¾êDV~ÙÎIu6¦¤±‡Ì` Æh„Ã=ÎPšjäx.¥B=Îo£gºC p= ¸%(áʀø&+5ÜæxÜc¢Ò'nI\åˆñ(ûKÄü·’ÝJųÇ4*¸Þ_‰2¢d@ôÜî¢ì±`;¸sçÎm/ +Â-çL¸,ᐟ²iÓ¦‰LY•†‡?—¯ú0i¯;i©#i©-i©ó–žÉÀ‡É¬ Ð ­wïÞµR¡ ª¦@-U`¡ÐŒ$(£”D(£„x¼«±¬ꋁpûÀV µ±¬ºÅar`‘Ýúô6[hÍØV˦ÖÖýP ÐpŠ{–uxíe-TŸ¬ÅÑd Õ¡BŨPE*T–²T ¡cqºÑE4]\¢ò-½y4½«"“л"¡Iu0 ½AKj$Nä-©YÞj‰ÊÒS–T(Š&ÊA©\<ªâQ%¹8()ÅAIK¡£P£n¦3©ä¨›T,êVC®_¿~]…)Ü +鑦Y³fM´ø~k©Ã‡Ý z܈Ž†>}útc¯Š^f6õ²æåå ´Ã¸æ:óóó‡¹ñM<Â}?2rd<§Z%2¾ÀžWÃÒ@2C2`eÑïÃN÷}*’n*ai÷ÊX¯kOÇ*ج}Xñª€›ÚVÁ®ZW¢¨HQ¿µÉÆÒv™\/ [tbí㗓֬YӓN“¾±[¶lÉõÁòìÝ»w¢ 69ߎ/ú֓'O®°œ?~½éʕ+Û °eûõ°jGu¬åHPº¢ùì³ÏÞ¢ãn”è?ø[@)-E ÂE+èH‘¡u)2&XçÏÌ<+ =^6Xçwì8ç᜸Ž3.\Ñ1®íu/“°|¸Þ-~ âZÿ–ÇìÚµk!oάXR ii\nçÈ8ÒRi)nƌ¯ÆqN«^ueyÐN1@¦~Xì}¬ù#„—²NV{7VyÉÅrXNQ´c=mLÛ·²Rƒ»nf&¹ €6ÅPšÅúè Y}AiAi› ´—•Ž°RÃ)–´º ùàƒ®+E¡Ðw +ñ·Ïèá ÄßdÜ¡eÜ«ŸCñ·¿Å­V2@[Bƒ“ˆ’á¹Ý8Ó`n7ëv{EÝnú,c.]º´+®(·:ñСCK’ð`ÎcÊÒôT¶çcÁ«t¶$-½š!¦8€–:0×*÷¹iÞ·§2† ò†ãê¥õíÛ·F*tX娪lV MO‚‚JN€‚Š‡‚Ša,o „ËáðBXÝf–šXÏ`~è­ØLg†Óš± ûÓ¡~)zCÖᵗµ8¤¬éׯŸ¤¯Iʀ$çò Aƒ‚ê! ¤ÜÜÜR„XEÜVâ®$îYâ1$MÂqƒh%”´PÍ*< ÷“ª†EÄNÕÀÂË$s"<šòUi)"oỈSë-=¼[©”ÊÅ߉øû%üfäÒ²DݤbQ·Z2N­'¸<¡àğѴlÙòy-®­µ×Û^ûÒÅõÕÃ4tèÐÞØËþLÝlŸ>}ú0tûlã(pftìòåËÇijlL¿˜ÙójD:¬ó°Lˆ\6¹X¢o%,xµ2ç•*X¯kUŒNÕ°Y‡j ªb/m)ZžZÑéԊî§Ö9XÚ6 hõb¶è˜ŠtM†%ô>±Û¶mìŒôîß¿‚ –i†6j¾ 6y™å… ëLW¯^Ýf¼yóæ>ýíÛ·ß (Ö²ü5AéM k)°ƒ”>%(}EPúŽ ô#Aég‚Ò?¥¿D¥ÿøÿøwYˆh´TdÿRÜ:«3¯A8}(ÆüñKƒpfXç, ÂÙ)´“(°Îo¿ýöi׍7Žº/_¾|ÀsöìÙ]Þ'Nlö>|xß¾}Ëbvîܹ fóæÍ3IKSbqóbYxŠ³scºb¢âk±°Ó=bXÎ3†ä?~|G?¡ˆD;°DVրxɍ¥\`¤.ì³×Ý1sæÌ^vV ²q¼C6̂1cÆðL"(å”æJË ¥5úS§NmaI«Ý:æŒißzë­ãÌ;§t\erý[LTº£ð¢ãà |ËAùn¥ŸäÒºÿ¥‡r+E‚ks»ƒu»ßÿý‹žhA8<pх‰¸ü¦,ÍNa]*ø~,?$†¥34Ž÷¨'i© [ϼÈ*-3ðMÒ$cÔ¨QO2אe꤁(ª§‚#*¥€#²’¡ÃҒðš&%@}ÅÅC}ùYàÁÃNþgg«KÍN¬gt` k«ëÙ}HNJhZ3àDcĞ5P‹¢ÇÀFցÒd-Þ}Y3|øpIø&)#GŽ”dœš$C)„ 8ý !Ö‚;¸«€àî%\ª$á¸A´,%JÀ“PáBS Õ,´²PÈ"D't±Ì©&‘Ƥ†ã"hIÍòsâDˆ ÜC̈́+¥rñw" PbwïHPi ¡¥ÐQBΤhQ7Dԍê¡b(êVGÆù5dÔíIFݞÕà㬅ØN‡+輻.îf„ªzÕí؏s1#e(mãH×¼yóF{ + + +ÆúaóbéD`òp^ÌñX‚Ñøv‘1483¨"þׯ2¼V…ˆS ë½\ ÜÔ©:6ëPÜôBuì¥-¹©uUØóVU(è~j]6¥m6WÉÄ/¥a]8÷ú•DXâÞq;vì³gϞ^Ø£qî#GŽLsæÚK-/^\c¾víÚ#lòlòaLÛ)-lòE lò ‚ÒmÚä{ +@éÚä/i“¿¥Mþ¡8(ýmòŸK%Š¿§¥€‰~@Š ]%´Î"÷½Ž#}&ú2Ì8É{"„0aÇ%\u0)݉Ë:å¢wƍKÝïaʒ÷øñã›|¬Žàc‚·wh¾ ¥N‡‹´¤%–ñŽaӓú‡b€LÝüé®~Îb÷ÁlwòRxðg'¶Øëâ†=™}öº;aÞ{98µÑÎ,e3p¬¨ÑŒôD3™Mì³bdájgϳöçF=³ÐuÌGç,Ä£œ…xFKG™†é?¤×wèæ{Ÿn¾9(ŸÜJ¼/t+ýn¥?Ê¿Ü­ôoÑÜJQJDËíþ$Ûýå—_ÞQƒpî¢ Ü‰@׶7W¹5þäɓëpå˓p&ãnÌLÁ}™”Š§x4i)—´Ô7CñJç‚r¶§(,Ö<|ژá¸ße&cû“Úi@ˆj©x/+¦€n2“Á9©,š˜ö‰‹‡ðÅB¸9yÑ郰y°Š…óÍNladK†ê­@-cêZ0EcÄ{®À/Š$#ëƎ+kñÚËZ°²¬Á¹H°²¤€•%O„$ã$ƒÏK@HBà) ê!¸E@p/÷'q÷$I8n¥T‚ð¤r“ð7©È$¼L"µI$4 …,&Ð ]¬Ò’ª†EޒÈòŽÐÀjN-ãý ÝJå T.Uñ聒Jx­TFÒ@ ¿AéÁQ7©XÔ­žüÄOüFiܸñS|ˆ5ÕàŠZi¡sÚëp#ºè¡^{¡ z³Ÿ×@ ´Ù ä”ùhÔzž +~¼VwB`gB4ÿxö—ÆÌêŒ-[¶ŒÊ†I^"·þP¢OU,íYëu«kÚ¹6ëPÜôB Xñ¶ä¦ÖÕ`k[U¥ û©UEˆ69X¥]WfØÎ)ØUwVA~-¶g@ €`Ñ ÏOø©N˜§9ösçÎ-¶^¾|y•ùúõ뛍·nÝÚm¸{÷î!ý½{÷NêÀ´ ëš¯¿þúm‚Ò{´É”¾ (}CPú=Aé'‚ÒŸ¢€Òÿ Ò¿…@é¯!PŠ¤¥¨A8zD„/CË_À—AÏ ƒpߑ–¾22gb(ÊÌ œ…yoÞÓ@ˆß™ê³µn­4ÐC•T N…¼¡ɀ§”$°OBD,ë=x9ƒÑ͜|‡«Ø˜Žoq´LNðÑŽ½èmx±uVp‰Ö ҘÀ*¶£Q àE¦‘u8Y‹—µxIƒ³’|)I +žIÁ# ÉBàÉ  g_Š«ÁÍ$îEâþ$îY‚h%0J”€'áÜ$œN"v'I¨u¡¸…¦úY¨f‘ù-’¾…BV#q"oI”sâÔÉÇ"§¦TgÂýB·R9(•‹GU< $—”𧑠Ì\Åʕu“ŠGÝ䢨[cFݚiÚ·oßV‹ë}I‡›ÓM¯ÏWPÈýLТƒ-P›ÃmPi£é?Ès-^¼x‚—óÀý€˜ILž”ÈdU–$ž¶mÛ¶q™€˜1Ù°Î#*B ©Œ?Vł¾Õ`!zÕ çԀÙîR›½TvõŚØK[rSëê0å­ètjY…ÿ«Äß*`•¶ÙX¹=¬S*vÕ-yçΝ½Xl±,,ñPÿáÇÇxŽ?>ÙR˜eÇý"+¾í Í°[M°`; Jõ°jÇu°oçJW J·JïÒDPúœæøk‚Ò÷¥?”þHsü4ÇÿLKü/!Pú×h FK©¾Œ-ї¡/ +Â}k`ìÉH\ -}hf +…ÉôËÀì‘ Žèœ‰[üB&^º,dÿ,‘éIz™2©3¿«³?b¥Tˆ,¶FLcŸš¤Dˆ¸üæç„FO,Þ_'{0Ú½à +ƒ§fVö0:f̘a°cÏz+¸DgÁÐjÍs ¬+<Š§!ëðXÈZœ•¬ÅS"k@Ò#-)P’‚s–d!@ȒŒÑ)šà*Á-$î@â®$ìY’pŒ P ‚ð„g-ÈMôibw™„—I愃I$‚ e.· %¡¤…~ªYdy ­¬¦,‰ œ¨åÍ­Tb¶R‰ ‘ÊA©\ö†ñÁZõg;½>œÚ؛ˆ_õrš–G2’†´ ¦­Ÿ–n “3ëÖ­aÇc1ֆQdÅHO·€ +æ²¥L c´Òtúôéõ¬º•U@÷èÁ±‡8ñD p :jYڑñ7áVº§)îVRBÕÔl%áV’èVŠL+sÝîû ,©A¸÷Yð*„s‰ ®ã¬Wtœ´ôz ®rw®wK<®|m"îÁ2Ò҂ܗ|ÒÒDÒÒ(ÒRn†¢Kj¼’‰ۑEZÛfáÍk–djL/Ó Ì5`æwmN–«Æf?Ùk:“]ýRÙ11¿Å&`©ÝL?súñÛXøÌ «&&U=3ñuVŒ¥Ö²lÙ2 €Æˆ3P P…}ûd^vY °–58II– ²¤à5•Œ%…òÜçϟŸJR˜c3,±¾õÖ[«Í¥Í¥Ý€Ò!ݧŸ~z’ tAóÍ7ß\'(½MPz–øc‚Ò´ÄßÐeñ{‚ÒO¥?âo”Š%*i©tPºŸ–¢á-©A¸ŸtÌÊ Ð3u„ûÌȔ%ӗ_~ù¾™)K¤¥›¤¥«¤¥ v&x“–Þp–v¹Ø˅´´VВGÐ{éza¼fø`­&û`¨Æù˜b䃕æÃHçúR#7õóö¥èCÑۃßú¸™‡L÷b kÛqÀšŽ`Û½1v ÞÆwšc>ÛPZh>zôè2–K_cÂm62'Pá +„wTϸ•.äVÒ2ªÅ\û€[ISÜ­¤Ÿ§º•äb%»ËàVŠ„SÝJQÚó‚pœ%IZ +á>ÿüó·ÙîºK43¾{÷îi¦,õƒÄ^¹re'iiSÑÕI ¥%É ¥¹¤¥éi¸MãÓqÃFpÄ ÎZx-¸Ð- w·Cnvk"ÓóY›§Ùè·t5Õ'7Õd÷Ä*ì"—“ +‘ÁFÈ)Éø-ýcⱞ7[¸˜ˆæ ôÚ8ÃâÆNMN‘Á$ÑÛ0‚: FPkÆs 1áíÖq.Š8£èñ”È:œŸ¬ÅË.kðäHœ³¤àm”¼Î’ŒG*(0Ü!E. n!q[‰{‘°Ó P ‚"‚Ix‚ÜD'V2‰èœÌ “HcŠ %¡Ñ…ö嗄¦JZ ‰ZÞ¥»•ÔIpeMë.¥rñ苿+PÂo"êfåznáDÝD_7ì42ê&‹º5’uSDÔ­cǎ/jpÑ]´}úôéÉÙÁý8ó%—©#™¶gŽdƒfÊðJ¾ªt«aώ¿Ìa>õl‹™EtÉÏ8xðà´,˜ãÉ`ÇUÆÿFW…V ÕÄ*}kÃ8ô¬ÝÙ­4f§ºdŸºÐ˜m‰L­kCm¶¤¿©y Šjø­E,mY뵡›ê…Lì cö÷2M/ÎÂî â?sæÌìÑd,Ó,;Œð"+Œp¡Fx£ Fx'Aé €q\P:§t\%(Ý"(½KPú ôð×4Âß³nÏJJT* ”àeú•†^-ý%"eIGŠ^¤,Á:FKlÀ %\ÖM+¼m`Â󤥓N‡#-íwž={vg€–ØÎ-h PàōË‚38 “é`烝íc="Ó é rÓ/ìjŠ~üÙσýÝl$ãfF² › q +P®(·3džÍ´âó-@µ%fœÆ*“(ŠSÛndxÊÀ@«7œÐ3x¥cK¸•³wBn¥O4ÅÜJß+Å'Á‘–îs+ïéVŠR·ûá‚p,GÉfÆ÷Øuæ.S–Þr‚–®¹AKHK§| ¥#1x÷‘–¶Ç7$‚– +IK)x€g§âyžš†Ç;/oÔ° Ü¿™¸“½²X # /]{"S+"ÓsYàœFY žÇ«›‰—³Ë×WfGÅìTˆô,HJÂ*ñ‰` <¶ð°.„“ÓTíP«;5»@FF'ÆÍ`ÇÀë­ ¬¢5cð4F¼~Š#¨èñšÊ: £¬Å™ÊZ¼y²*)xÅ%—ò‘#G$ƒR„àҀàÊ·•¸ J!ÈR‚ ÈanN'L"X'¼L"¿I8˜D"x-‰HœÈ[]̉)Kj.­‘­$rDm¥_S£nå T.ñk%|ŔJ” ü_0êæv»m|“EÔÍS<ê–Borf êV£FêŒÌוñ1õ'ù´Ü¼yóç\GFÝ^ÒàtÓöïßÿ5Ý°aÃêóòò†¡‚ƘðY:Á•;…³¿g8 ¸g¹ñ¥)Œë<–5œςzœþ<'ZoV”àŒl¨Ã) &T†S¿ ¯1¸&VéWŠ¶WlÑ­.ônçºØAûºP‘íˆL­ë@´¨=7¯‰ÿ5¯NQK[0Š×º¶h—…tH‡¢í’ Ü#ñøñã}Ø=b°öw”÷âŋ9 ,ŸÎ l¥å€Òz‚ÒvÃG}´Ÿ t” t† t™ t“±;4Â0eøS‚ÒW4Âß”~$(ýLPº/þö@Pú(kÊÒ?‡R–-R–´T”²ô%S–>5!> аâË|ðfˆ–ÎÙ9NВCÐÒ¹sçv–6‘–Ö¸qÿ–{p; <œÄÏp\¾VrŠ—u™Á4†È4‚^¦¡ Ìåzé8ò²Þ:ÅÚځ2’Å`øy¨ w„öm´£”&Û1nùlÀ7׊‡¡ÀÂL6—Ygb<Šõ@w1P œ2¦[œáÌÄK:V n%m([I¸•4t­©n%ån¥;ó=dN ÇB[™pś3eé¶ç|Ӊ³¿âÆw΋Gï„á!ÒÒÞ8\ïÖÐÒ:ÒҊd܍…¤¥™ix!&3p=&ƒ 21ýXa£GnlgQ #w¼ËÜ?› ây’f€ê0«©Ë×WLƒÈJÅo©l#”˜„õâØñǏ!sÇb´œœ‚aób|-|“M.Œ–‘£¥·á¸:FKµf ™Æ„gCÃ"XŠŠ¢ÇIÊ:¼o2Ëœ¸¤9qâ„¤à‘’¼~’,.+(0Ȓ$ÿ ®ÜLâ^$ì/ÈRžpÈ 7 “@&áeÑ9‘Õ$RÂ#hIDâDޒÈòJ_èq¡¸EuÊ·’ÈV­NÔIp¢¶R‰ñ·ç¿E£¥rP* xô@IÃ7T×I€’ž"JøÍÂUÔ¨›7uK ‹ºU©R¥²T«V­šœðQ_þÝï~÷„üì³Ï6–uSBQ7 îPí Aƒúêð]6X?~üø‘ÆéÓ§ç™æΝ;™Í)¦Ó9?‹‘•¹n¶;õŠb†ì“ÏIMIÐpóSaçd@áÍ̆%žVbReˆ¼j#k`An-¬Ò¿6V~µ.©{=èÄÎõ°ƒõ ÛQ´&7µ¨ ƒÑ¼þ׬E5,h^Š»%ãym³±m{Y§Tì¹{ÔõkLÎ.hãÜ¥i¥y6ØߥØß5¥-FX°=¥Ã¥S¥‹ôVÜ (½CPzŸ ô1S†¿ (}KP +Æß`9ÿ”‚n¥"Pú÷’@)-Ã?¡ÈB‘²FK,R %vø`ÊÒ'F¶G3}þùçÞ&-Ý°r:œÓá-ÙAK‡IKû´ÄfÁ.6pu³Ó†‡ó÷=¸ãs9ªùdà)t0M 2%2$2 g.Ó/,v.Å`/ñÈ#–æºÙvÏÅZ.< £œýèÀþ&”¦ÛqŒÙ6m!»ð-³à V›q.›D‡Óõë×÷±ÖÕ3¡…[‰ÉdW™Lö–p+i#ÜJ¼ÅÝJ?‡¹•pÿþ,—Í­­ÖUé3áÂÊQ†53A8Ö °‹”%u4«‡m»Ö‡~‰´ôB}ëÖô2µ¨ Åݬ6Äóµ(˜ßô<3šW‚Úl•ƒÍÚfâÒ°¿.É8F(ó>±Ðã¹lO:Š=c'”ò J J+Jë JÛ Jûõ°eGu°jg´°o— J7 JwÖù€ $âo_2¬óAé‡_‹¥-•!Á[‰HYb‚wˆ–~ -}§.|m8¦Ã‘–‘´dew¸â´´—´´Ý ½É…›¸†E͗3y©€–sÃq3é`šJ·ÃDÆäƱªÀ î(ºšF0Ÿ8Å0þ9ÜCFò`•‘nNy'Nç¹°ƒ‰N€ÒTÛ;°ûylÅW`cü͊ƒ¯a?¾Íf ÙNº•ö ·’‘n%ë]³˜ÃU=ÝJ:&×òµ¼Tá¾Ð·±‘´ô#iégŽV¸[©ˆ–ÊìV*c9ʈ”¥¯IKŸ[pV‡R–î8pÎo‘–®ºqç½ ¥“¤¥#¤¥}q¸Þí W®\ِˆÇve2ø  /Éì4<ÙSYÎËÄÃ?ŒSHûgz±2Y—lNe©Œ–9¸ÙMX]¬á©!ãtu3!ª3%¼R:d±ük‹'²>k\"ÆÃǤBw,vêd[@ mY8ú&'Žktà ô6¼Q:+Þ(­ãa2™Æˆ3UXÑAÑáÄe°GÖ⑒5·nݒ¼e’‚Ç, d\e˜TÁ¥ÁÍ$܈ A xÜ$œN™„—ID焃)‚–D$Nä-‰,o1'NáD½%áVRs»E¶’PÜÐAM­¦u‹ø›PÍóß*Q)š(¥rñh‰G”bccï%”LüSDÝl\ÏÉ7ÙÃmƒéIx·"‹PÔgyÚß²(À32ι¹Œëh§à;+¸=4ì§Å‡Ø>ÉFëg̘1Á0oÞ¼i¦¥K—Îb¯ù,ŽSÀT†%.¾e^ÑzêkE<ÔërF¿–¦B½d@¹-ȆҟSbFeˆÉÕ8­&–Ž¨ d\+÷­ZêYÛ¾\Jºc:‰êÃ8´&2µ¨ѬDÓZ5(ªai³ÊX¯EØÚ6YØÁ‹éØU§ì¾{"ìþkœW4-$†{¡wǹ Ç§9 •ç±ÖÐR @i  ´• ´— t˜ tŠ t‘¦÷AéšÞ÷™Ñý1Aé šÞoñ7˜J5þö!Pú—âñ·pZ•–ÂR–ŠÓÒ¿(¡*Kj‚·–Á&¦,ý û駟-} ¥o¾ùæc#§Ã‘–޲ܻwïiébˆ–Žq6àëÇv ZÚ %¶Û`òRÃqóè`šIÓ4f0M"2÷ÁêŽ%2¦«i”æxd@‘<,Éî ™z¢ †yŠô5Ãޝã`ü͎Á[jcZ7ÍñöšÙfVÝJ°¡ÇwîÜ9c¹•-}›NÀwéüCö)ÙöKp+ñn0÷“R”Ûý¤¥0·’üß„S{Â…× (JYúʌ¡øŒ´ôié};û㐖Þta(®x@K缊~0áX¶Õ‰ÇPl%-­K³»<¯ËÂTܗ™é¸C“^‰»6$‹òñ潒ñ蔃ñhÇzÍs0(éoúEƒ,ˆÚ™U3° “Ã3R1 +)쟒„Ä$`WÞ8ìÔÅ÷×áØ[Y©ÕÌü5“g``¹V½ƒ¢³àÔ´&à‘ÆxãÆ …Y÷ +ç(Ê:ê_” “àD%J5þ&ŠPÖªU+8ÿ-Z¢Ò#( oT9(•‹_¯øÿJb~E@ ïŒ&Jx…t$#=…"JXjçz.nᥗ8–ïV"wšÆ¨[XQžFžÕïXàY¹U«V-å:¼¨à*»*}úôyU“››;@;zôèaºI“&ÕϜ9s²aá…ù¬ª2ײvíÚE6ØÁ%Ì9Yî‚Í[é…5-d‘ÇÂ8谕‰  ¡å—¦Ãð-ʵ̫1³2ÄÔjøm|M,U69·.r¿z@œ^õa º5-ul€]½ØÈԆ¦ŒÉ5« є MÏÕÄoM«A<_ë5göS+†÷ÚÑõR*vÚ5 êÝÞ/:v(AiŒzw +Ai6A©€ ThúðÃ7ñ•¿K öº¶ì8}çJW9õíAé]‚Ò‡¥ÏŠÇß~$(‰øÛ?¿ýå¡A©äïHZ¢o¤8-ý¢¥ß“–¾Õƒ-¦Ã…hé¶JK–"Z:]œ–öh‰u ],ÍTïå Ç07¾ÃYŒ´N§ƒi2‘i‚qµ21ÌæU~íÁÒ±˜èq¥ n‚’‹‰JN&*9s`Ûq´•ì^¼ÎJ·’…Õؙ f8ÓS¬zÞÀ–¹z^ƒpwt¸¶€[IK:dîkMq·’"ÜJ¸W‘n%ù –D ‡2Ô `«@ÒÒ§LðþІ¡x׎Ó}ۉ¿AZºDZ:ãÃe‹Œ-튃lNÄc»&ðÒ¼.óÓðFÍHÇ3>1æ‘Y¸kƒ²qÿzgsºhˆç¥1 Üô|îóÓÙ¿¥¨Çbc5Yôµ2+Že§aåt–KNÆâñÕágí1O,FÚéÇ(ØY€ÌêÆqÍ.À‰‘.G˵ê¬85­ã¡14…uV½’Y#TfEu™ýg$D¸TI¯Z@Hü3 ¸Š„Q’¸Yž7 d®&áe&“SiIDâDޒÈòA8QA@¸•D_QË[d+‰>qÐpAµ®ÆßDÉîFç¿EKTÝr£ê.=£»”ÊÅ#-PRŠƒ’¶8()ÌüÍZ<êæã»Ç]%1Ğ( + ғX€¡ø†’( +€3m*·iÓ¦µÜ±cǗ\t7¥_¿~½5C‡Ì&˜#Ùài¼~Μ9ÓXw–©°°pyÆ ‹Yiy¹z·ù «=`š5~z!8Ýlu"Ya +Xey:lÞâ,hÛ fWƟӪAL¬¥£kc½¡uaÔâ¼VJº{ì¥iéEÒRÒR z™šÕ#ՁxŽ9àÏUÇÒ¦U±^³Jà«9ضM&Þ> ;휌c¼’¥Ú‡³°û€£JøTÍ·”°ÖÐr3ôóz‚Òv@i?Aé(­î¦¾\¦Õ}“©/·é£¸ÇøÛ'¥/iu¿ ÅßJOëþ·°´îA© ´D£ + Z +L‡Ó„¼£ÐҗÅié½-Ý$-]%-]ÐLôÑ0ZÂhi #³Æ[¼Ü#h‰û½,%Íb•3ˆLS|ô±È÷xG䦱Bx‹D“œÆyJŒâMvcÛi.ÆߜŒ¿99ÿÍÁcØq´Õla¼ÑÊ3 c/»Î2 ·,çYÖ¿ºÄ²7„{›A¸wu!·’€û%ƒpߒ–~/r»…[‰´t+…r»£ÐÒ¿—•–4¥¥,ýHZú>²Ä~LYúĊ¡ø€´tׁ¡¸EZºîf?f/øà´Cñii?iiG[í$áòW‘–§âu™“Ž7eZôq 4ÏÂ]À™ ½rðvÍÁí|1ԒE3šžÑéԐÁº:ՙéT‰¥Í²R½©) ŒDæƲ¤†/{vÇàÀƺ“¸j`q =«é,x…´&à‘†àªÐͧ0(*sf¢ÌÓ2{ôɬ¨.)ž€¿øâ‹0! ÁÁ•%AP‚›Td^&á`RiIø–D$Nä-‰,o„D½%áVµ¼§M›, &Á©iÝB‹"”êü7¡©…’úYí–QQ©¬Ýå T.iñk%¹, %üÏÌ"êæ`ÔÍÍÍüÜA|XQ€ˆô$à©=͵Íä^x¡­ŒËê¤àò{( è§1bÄöÃ&˜“ôP73 PªID¦ !dà&þž§ñôAMô°F'ÕMscÛ|ão|†:1 Kì‚f§[Ɇgc‹Í. ÝJfXÉ7أó¼‘5YÛá&ƒp·éVzŸãt+ᢿfî{ nď¤¥Ÿ•¢Üî"-=À­T*-•R7€ “Cu‚´¤¦,±Ï²Cqώ3½CZz˅¡¸êÁPœ÷²=3iép,hi_<†b["àd};ï¤àF,JÃ-™ÅÇ{2]§cm’»ÖÓzä`P:åàv¶#75§hLxú=O XôµÃvU3°^…4l‘Á\ñ”dì%!oOL<Þo,†ÛåÇÀÛ½`$+§‹š8 £'dà\oÖŒ·GkÂ9kȬ +=| + ·Êì™(sf¢Ì®3’‚OIÇJ2.:RH\\/OÈ$ât´$"q"oIdy‹ œ¨  º•D¶’è|"&Á‰®º"þ&ª¥¯ÎÕºÕD%Q( ZF÷מ,¥rñH‹_;(%$$„ƒPHK( d 0QX „Uœ\ÙÃÍbøñLOÊÉÉÉb°½’Z€¡ø'”oÌð| ¹}ûö/Ê/¿ür÷¥—2xðàšQ£F ×Lš4)O;sæÌ):¨›Y(žÆuëÖ-1oÙ²e¥u÷îÝk8É{½˜Ô°‘…°7ÆB™oH€¢]— ݾ:ÚvEĒ +ó+C̪†SjbÆՆ®Q[ ®õߧvÐã1¨¾.Aqw -µ%-µ$-5cS”jãÏքhR KŸ«‚õž¯ˆÍZfcm3 ê;”º$â@= JýJC¼¥1¥É¨úY6¨úEÌp.4AËo4@?ï$(¤Á=F÷Ä9Ü+LTz‹ñ·»Œ¿}@Pú”n¥¯J߅âo?‡âoÿDƒûç_+-E$xi‰i8!ZúI[l:œ ¥/ŠÓÒ»Z‚)z“´t…´tþ´Ä"Únæ]³cÜbƒfl'h)ßGöáÄ©ÉD¦‰aÈT$&Pb’ÓdVÌyÊwÔÏfÖø|̉]á –ÙñDl²Ñ­deú”'tȌS;ÎF}gè˸ddéïm½p+qªŸîÛo¿ º•~üñÇ [ wã ÂýQ¹?·»d·R‰´TrÊRQ•¥?êCU–ŒLY2á4¾2c()K6 Å{vðÁm'ÐàMã²Cqև¡8ƒk{=´´;×»…´´6À²,Ïó‚4<Ùù¸9é?•…ñÌú½s0(Ýr8"#ӆâyÂÓÓt:ý&ÖËÂҸϕӱrv*nvZ +^µ¤$ì*Ž3Eýqؽ;rúpH›·ÝÂä>]±F~aèù…¡ãC£e†Ÿ†Ÿ +ß…i~2GAfâ˜Ì2÷2 ^Ilf,±…¢$’\*q=IÀ“ŠL¸/÷ђˆÄ‰¼%‘å-‚p¢‚€p+©ÙJ¢ó‰è'ÒºEümôèÑáóßÔD%µPÀO<=£ûo™úVJåâQ +(iŠƒ’> ”𧅠ì|u]|­¼|­JIObQ†âŸdP¾ Ϲ•Œëè ã*»É}ûöí­ 2d°fìر#5S¦L™ …’™®ƒº™«/,,,0nØ°a¹yûöí«-0rëìÐÀ99f³h!F‡ýÎ4ۜ¶!fvm´íªLjùˆE•ðۜªÓk`• µ@K£ê@5©Zê×Z¯çcL1"-½DZjGZjٚ°3˜ž«G<ªCPª…?Ÿ­Ž¥Mªb½¦•°Eólۚ ôB*vÚ) Ç菣õŽfÄ^[#ÝÐ÷J3Jó JËJëŒÐÊÛ¨ê÷1Žs„ñ·ÓLTºDƒ{ƒn¥wX(à}º•>&(}!‰´nXÝhiÝep+•JKK.‰–~P‹„hé¦ü DKoGн'IKo0Ú"hi·“éՂ–ÜÅiÉË6e¤¥9>Ò|Ì="2M&?‘É/sEb’O€€jªˆÝqRÝ,7³Ÿ˜5¾È….s²[®ZoÇc±Õ†ƒï²âñ9`Á ½a†©<ÅÈÏyá®Ò¡q“éø·9xïsð>&å~®-r+}r+‰Üî?)÷çv@I.›[©dZÒÞ_eé ÅïIKߒ–)KVo,Žáò_»vÍáÅq­nœÙ‰s1:pVÛû￯gíw+uix†4\‚¢â(ü̐92£×2_!‰EÉ$&üIrq! Á¥× p“@&áeŠ %‰yK"Ë[á„[IÔ[ÙJ¢–·˜§ÆßDµ€©S§ç¿E$*uèÐA’ZµjÔÙjF·PÒ¢ô¤:õ-¢F·%8‚xʐÑ]JåâÑ¿nPRÂ@ 稜<¤ €„‘BDݬa ïã¶Áô$¼Ý類%jzÒãLOzŠ'ٔáù62.¦£Œë}Eîß¿_eøðáC”qãƍÑ0ꦝ7oÞL¶ Ÿ¯_½zõãæ͛ M0wkÙÚt£ Êw ­Ú67í6”Ö6~Œn%œlæGð†4hÛ5™À”9‹+áÏyUY&»V™T +©Õ<´¶íߚÿÕÇ°«n ¡½;6„ú¡!Cj¤¥f (êB4fiÆ5 ž%(=W [Œ–p½wMœAÆ{pƒ´t™´tŽµ¼Oڋhé@-ÑcHZZí)NK>•–À>Óýôù™ÁDZšì/â&áošBÏÓTÕtz£f²"ø\Æó2k|‰ ¦|¥£ºÖÁzœtµÃÆVV3`[ããfº•LwïÞ½dÄ9_gî½wéü€ÆúSá¾Ôbð¾!-ý^SÜ­¤ËíþKZz€[©,)K8FԔ% ÎêÒÒv'-}LZº¢¥[‘´Dßi鈃´ä$-¹X2‚–¼,› %ÀÎ\«Iú™¼DZšFZR‘)(B ä5°òæ<Íg<¯@qbñËUN ízt«È.Îà€•~-ì^ÇÞÆçMìÑ ÜMFð6ƒpïÓµñƒpŸÑb¥ÅEÇ Üš‡p+…’TtÛÿÅ­¤ÒR))KE´ô ´ôµhð9iéchî}ÒÒm'Îù¦g…´tŽ´t"Cq(C±'—º5 ÏîZÒÒòT<Ï ÖÎÏ`‡ÒÒ(ÒÒ Ÿ{çà®uãì†D¦ÖMéozŠâñ,,¨›‰Uª39¼ç>dqâEjv•˜ˆÆòýõ±h¸Ûûìðâ9°ºñº˜x]Lv¼.n¶Þ4Õ±³–’Æ€ëPô¸"EGFâm— ©2ï½ÄÏ ‰QPI..$.¸J™„—IВð-‰HœÈ÷SäT·’ÈVÕ)E-o}âDWÝ 6ܗ¨4~üøðŒn¡å;vììh"JOFL}ûo%õ·rP*Œøƒ`ç>P‹#@É@a¤Q7—:¹^0= oT´ô¤Ñғ¤¢ô¤®rïÞ½_“sss)£G©LžÀ Í?Ü Í?ÎÍ?a„¹Œ¿-eüm Ã[J{Â9LP:ÉàÁ~Òºe5­ÖïsI¸•`#Òºÿá—Åßþ3*-E4=‰6®DZ¥–Šhé÷¤¥oIK_EВ©-]'-]"-%-ÑÒ~ÒÒ.AK„ã žâ´äcU$AKþ"ZÊgg›é1D¦âQL7 ‚ž§|ú fÓ5Q¼Eœ^·”EœV²œÓZQÓÁòávº•8OýcyŒÓ¯Î°Áñ%¶£¹nn%\‚êVúD³ý]A·¯,n¥ˆø›¥Ri)"ÁûÏÅi)²d)KE´ôié3+Ní#ÒÒ{œî;¤¥¤¥Ë^€È?äX,®í`<Ö] ŠMIŠÕ)¸ü%ôÖÎ%-M#-ËÄ#?œ_ ýIK½r02]ˆL/P´Èæ×Åï§{ŒùMµ˜éT5 [T`¤:ƒÓë’ù]Ï×Å‹cxØgÅɪ˜v‹ …Ɂûl dřêÌ8g­ g¯áÓ¤0«èèGҒ‘´xàdzódÆ>%!d!p7‚ÿ£TdRiIDâDÞóÂA8áVÙJ¢:¥ˆ¿‰Î'¢Z€èª+æ¿mܸ1X­[ +MàDF÷ˆ#$iÀ€ѧ¾‰Ý¥×(”Ôå T.}ñ聒>J¦(á7{”âããƒéIØA"gi”%=I*JOêÎô¤>òСCs•±cǎV¦N:I3wîܙÚ%K–,Ю^½z™~Ó¦M« ;wîÜh„ Üj†ÛÉÎ{˜F²×ÅV(­}L›Þ»;‘³œS˜Žšm»> ÿ+¬ZZRKçWƒÕͯ …<©66]ú~H}Ö=z :»gChﮤ¥¥¶¥Ì[jÊ9qϲèÒ3u!ž&(=] ž©Šõž­ Ñ4Û6§Õh“†ýµOƞ»$à=ø‰ÜׇÓÂD¥1NXØÉö÷Þ{o–Êwù`%ãoÛÉøÛÆߎ1þv6Ö ~“ÆwÂÒºaÃÝJ0án¥biÝep+E¥‡¢¥¿„J-ýsqZú9’–X˜’´ôíÛG¤¥÷IKwOy+Œ–`”-'-v°`v-±@¤ %/i‰å +´ä/¢¥Ù1E´4ƒ´4 $IüOü–ïÇRAUµ€Õ¡{Dmðcǎ­æ”» ,U°ÕQÝeǀ°Ñ­dÅÓt҂S;o†¿bb`#x÷6ƒï©n%]„[ ÷à'ÒҟDÉ¥¨d@YÜJ¡(hÉ)Kšˆ”%ìùB ޑ)KœÕ§¤¥ìxÌn¹@×=¸„‹>ÐÈ©ÐÒ¤¥ý¤¥í‰¸Þ ÉŠ•ôÖ."-Í"-MÎÄxŒÉÂÊeݲ>¬òڝÈԑ¢ sÏS<…?ÃÔ¦z¼éX¹R*>Q²8³. pwcùûbðêº J‚’ d&(™ìxJ V|¨2~üøÈ2™´ŸU†÷2 uW2´Ù¶4ˆYk*à·å•±ta5¬7«Tý”ÚPõyu¡Ÿ‡Õ‡¦Ðû{•n¥—IK/ѭԎ´Ô’´ôiiiiŽÿþýó™îTÀ¦K™UÈÔñuœr·Ù‰ípöÚqðC6<>Ǭx¤ÎX½9cý:+ˆÞ"ïÞ%ï~ Ç}´™€[I[T2àš¢’ÊV*”Ê@Kÿ¢ÒR §¦, ¾7a¾1ãiú‚´ô± çwώ3½ãÄSwӍçïªhpÞô;<‡ ܓ€Kݒ„¡XKZZFZšŸŽWhFô ¤¥|øfáz•ÞÕ®D¦IKbVh†èžÌ„xŒ T›AêªiÆ +¥ ‚Rr"Æ7>#‹»ëaåp'kˆÛÝxS,Î"P2ÚJÜbY€$”¢Ç}VX£Bæ³&kp½2Ÿ¿#‘O%YüM"‚–T·’ÈVŠˆ¿‰Î'¢YœHTÂ, ft‹BÝ¢ÿ›:õmÔ¨QÁÝjµ™‰(¦¤‚’ZL©”ÊAé£øՂ’R”´D!¡H€’‘Â%Wqse7‹ãˤ¦'U`zRµhՓDz/¦3/¿ӓÈøÔ!Oœ8q¼2sæÌéÊ… çiV¬X±D»~ýúUºíÛ·oÐÃÜm3Bí2Sö±éAÎI:äd8ÄÍ€ôؼ9E¶7‰óvÒ ¶dâÏu9X°²”ïâªPÃsk€–¦Õ‚V_;Qª~Pì¯7ÝJÝ JèVz´ÔŠ´ÔŒn¥&¬·Ô˜%*Ÿ®ñAé©êXúL¬÷lEl֔ÕÍ3 þÛpNu{ªÿ®ìѓñ·~^œÁP‚ÒXÆߦ0þ6›Óx +[ÅøÛ&‚Ò.ÆßDZ÷qÆßÎ1þv•n¥·»KPRÝJÁj0¸?ü­ÕÊJK¿ Ô’JK¢ÔiéAKl¨û)iéCæå¾Ç†º‚–nò¾\%-] -f¯¼c¤¥CZb[¶-a Ö{نÄGZò Zb}$AK±¬Ën!ZÊ'(A‰N§9ªytD‰Þ&>­`‘®Õ³âÔ>²aÞs€–ÞqáÑ{Ó ¹ìÅ(œñ㊎ł–ă–v&‚–6%a(V¥àò§1˜Î¬?ÒÒXÒÒPVyíGZêAZêDіÈԌ ô g<ü–©MõJ5è{­Ì7%›S0ÒJ‰ñxSb J>‚’› äðàîÚ\%³ge"(JzJ¦"P҄@Iá³&k‹@IŒD4•dU¨´¤ú–DN¸•Ôl%5­[T P•D¡‘Ñ}äȑ`¡n|ا¾-Y²D’æ̙s_a„ZŔTPŠVu²DPŠVž»”ÊÅ߉øõ€’JiiiAPÂû¡¡§(:(áO8éIXÙϗ)ž{Iáþ2éI¢¹[ƒ ê‰ænô¤€Ì,·ò†ÚûH ìÖ뜭³? }w*Äö ü¹1buE¬²´ +4ðüêlS[ Z~bؼÑõ€3¹  õú>-ߣ!ôxgÒR{‚Rk‚Rs‚Òs T‹¢£ +U±Þ3•`šä`Ûf™ØK«4ìï–*蔀ctgæEoÒÜ`&*dümão3[@·Òrú#Öѱñ·}¥7;M·Ò¥ân¥÷ JÁj¿Ð­ô° TZú×â´ôçÈ”ìK…–¾`ïOÅhéN§%Ü°-9هͅ{º×G`‡‡}G¼¸÷ë|¤%?«SúY)†´[DKs-ŁŒf³HK³‰Qsc°Þ?ÝJ$­e>ì¥Ð‹ý­ó`ϛY¥`«;íå\¼Cœ•wŒÕ ÎXñp…»•pâ­tOu+éJu+)ãV*•–"S–´E´ô¡”¥?–~OZú–)K_ZpVŸ’–Dî]Fᖠ£pA¸ ><“§bðt‰$싵lKÄõ®OÆ{´‚´´ ï`>ii"iiiiié5:˜^&2µgS+Š&d¤')”ꔪ”*ðMÉ (¥$`|ãã°ûÖ ÷°ÏŠ“ d'(Y(ÙqjF+NR€’Ž ¤5” !PÒ© „‹¥h´æVR³•DüM€RD¢žÄ`¡‘Ñ-**©Sß(­]»6X#@€’è‘+š™D%µêdéå¹ËÐǤ”ÊÅ߉øՁRfffé d 0RXB $ғ<üЉ¡7*{I勝Å÷¨2ӓjªÍÝxVMX3¤«‡tàµu“DzÒü“ÇŽ;Fž:uêeîܹ³|ˆhðI¶R»e˖õ:|ùoÕã+·&k¿ jéêõ ¸9fgn­ Jõ˜øqÔv$ø¯'BìKØ™±% ÖUÀ*+*ÃÖ.ªû6«&¶Rªy,ÝJÃêCëõ {îÕ*¼+A©ÝJmIK-HKM JÏÖ'(±OÜSŒ¿5"(=Åv»O³ñî³`šÒB´`m𶌿u`ü­+óÌ{1þ֟ñ·at+å1þ6•ñ·9œÿ¶˜ñ·ÕŒ¿m¦[i7ão¯3þv‚n¥óJ‘[éVÈ­ô!Aé3I¸•`¿+©Z@én¥2¤uÿÐÒ!Z +–Z‚þ„…)?0Á¾k&-YpKÞ$J^aõ©ó¬;xʁá> %ö¯uÃÌn'-mò²°¶ïĉ…þ£G.‹!-Årî,[ëƑ–âÀC³³¹`.Yj>#v‹b°ÙRFñDöÓFö6xèVâ¼»ÝNº•8ø>'­Ðsª[‰Õß1ªn%\QT·’æáÝJ!P*-E¤,éŠR–~&-E Â}ÂáLÕ Ü/FáS–Ž3eéõ80ëî\êfáV“––¤âÌ%-M#-呖†‘–ú“–zò]èLZj—%¾! žáŒ‡ßRÔ'(Õ$(UN(e'ÓJ‰l§ËïŸGs{q\‡g`uâ\Ì!P2X(áœUPÒè‹@IQA‰A`9J¸Ù’,Dˆ–$AK­S•"2º(‰BÝ”DGÑ(WÔPAI-¦$@)777XuR¨u¡Ç£’(Ï]Jå ô¿V<: „×EG( d +€þ´s‹Q7/·ˆå¶‰LOJczR6w_…qöZŒ¸?HOjÚ´ésœ +ۚ“bEzÒ+’HO†ò¸qãòäéÓ§OSæϟ?WY¾|ùͺuëVi s6jaÁ¶ë`²ö`_7BÑ1Cãlm1+ꤓ³É=°¡'¨T±̑ØՃÉÌ­HãGp&l¨€UVUÆÊKªAÁÏ­]7­6øe|]èçõ¡õÒ­ôÝJÝèVêHPjGPjIPzþ1&n”ž¡[é)º•ÕÄoªc•§ª0´Àø[“l؀fœԊ6àEö‚èÄøÛ+Œ¿õaüm° 4Šñ·‰Œ¿åsþÛBÆßVЮg Ã팿í¹•Î0þv‰ ô&Óºo‡¹• å#ÜJ"­ûέT +-…J-E¡¥ûJ-ÑÒw¡Â”Ÿ‡Ñìô]3 SZp_n–.ÛX<ÀÎRKNÜÄ7\,LÉf»=,µäŐmb™öµì°ZCZŠÅ“³8Ž´GZŠg=€xÒR<ñH¤¥¹¤%á~hµ˜´$œS«|t+1¼·™¾œk¹—éq‡èÑ s+±…Ý53Îô¡÷®öüžn%½êVÂ¥~ÏLãÚ­ôגié)KÿLZº/‡QÂáÔ"‚p7„»Ä”¥Ó ½Á Ü~áv0eiƒp+9obS–f2Á{R:ޣќLJZêMïj7Nqè@ъâ92R#&ò5$(ÕáKR T ”Áns)줋w5†?/étãà6'NÃâÀ ™lx@ <*z3wWûp ¢¥’AIMTÝ¢ƒ®:õM€’¨ ‚ÒöíۃŔ–-[v_ÕI”DyîP}LTP}LÊA©”þ7Š_7(iB ¤ãë¢%ü/JXêâzjzRߣtî4‡éIU™žT‡œ±÷§…ž§Û–s=:óz{r¢ìN™!O˜0a¼œŸŸ?C^¸pá|eåʕ˔ 6¬Õìرc³Úg—Ÿõûõ@’ÃF¨×c&(¨“@Ç)ìåilÔi–[9E}z"äq4âP§ì¤2·"lsVYS +/« +¿ :t]~-ìeb˜»Ñõ`pEü­ÝJ¯Ð­$âo/’–Z‘–š”D¢R(Õ"(ѭԈñ·§+a‹ÆŒ¿5¥…hÁø[[F^büíeÆß^eüm`ÃÇøÛ4º•æ2þ¶„ñ·5t+máì)áV:p+Áœgüíão·Jïþ?q+ý×ýWtPzZú—’h)¢ÔÒWAKjñÃ;¤¥[Lð¾nãt8úáÎ:X<ÀÉâ. ÞK-yÙô„eÚ7úYÆ;æøñã+cYq;Ž]uã<¸0¾ˆ–æ’–æ$Òœ€ (Åa麟 +¶[ƒmW2ñi S 60u\(…8Cn%ÝJìFvł§.èVÂX +·Ò‡ª[I÷?åV +óë)E´Ö.2‡Q ™ïÂÝu‚Ñßbî*ƒpç„;Á Ü¡XŒÂá¶0·†n¥¥ ÂÍ#-MgMüqœ7œ´ÔŸß =ù.t&#µ##5§x† ô[‚R}‚RM‚Re~Rd³uJ3ºcqOc J>¾Ø.@Éá(Y Jf‚’ÑŠ§Ä`Æó¢3”Œx†4zÜ]w7Jta>”"ão¥ƒ’˜ú¦ÖP‹)E%Ñ·tPÚ»qãÆѾ•ƒR9(ýo(i‹ƒ’‘ÂLaåo.u@ ïQ0» +–™Ä1ª³iQ]¦'ý† +@-3ù/¦ ¯üUÎÿę £äI“&M”g͚5S.((X¨¬Zµj…²iÓ¦õš]»vmÓÂZíÑAÔXÞ0@³ž0:N³P²˜>~ŽŽ™s.¨Ò³ôПfmáqPªo$âS¨Ö3°`[64ÜúŠÐ»+«`³‚êPð³kb/Sê@5%( Œ¿Á"Šø[‚Rs‚Òs 8͍n¥§kT>)@‰ñ·§{†ñ·&Œ94cü­5ão/2þ֙ñ·Œ¿õeü-—ñ·ÑìÎ0‰n¥™LÈYDWÄJæo`ümÝJ¢ZÀQÆ߄[é²p+ÉEn¥`Ê"·Ò··R±j¿Ø­$)B”NKQ¦ÃEÒR±Â”âºâ¥–˜àý™‘ÅLœgfñ §ÃY9Ž÷ê"«vža°ãÌP;ìƱ߃û¼Ë‹Û¾ÕQØÃÎm±xrVÆ9rdiKJÆãiZÀÂI ¤¥„"Z + +‚ii~1j!iI8¢–2€·2†n%¿èÂL·’‡n%7ÝJL•:â [Ɏs s+q,ßa1Í÷ØàîCÝJú»•”ÒÜJ tŸK¯4Z*KÎR4îCá‚¹Ý …k Â]àL¸“~\Öaº•öÒ­´•A¸µ Â-K³ÎO¡[‰¼Ç§á‘žÎÒü^èI2ê,*g0»9ÿ÷ Aé·¬ÏZŸ Tƒ/IåDl›EPJe¢R"•bS÷zpO].Œ¾‰JV&*™™¨d €’ˆ¿áÄ…@Ióÿ ”Ö¯_JÓ¦Mû¥;㖃R¹x¤Å¯”ä’A ¥øøxß#…™ÂÆߜ\êá«Ã͂yÜx§³¸çûò¸E™I‘ÇÍ2“¼¬îÌãî+ Å?)//o¬ 52U†B™+Cµ,QÖ®]»ZÙ¶mÛf LÖ. lÔ-ä Ôë tÓ#òyvݺÈÚKt1\v‚2.1ÝS´¬:ËÁÉxˆ£ILBMÅÒ=™Ðí[s`a×UÂf+ªb éVšY û›ƒÎîû€ø‹@ âÉZ­„¥O2þöãoÏ0þք1‡fŒ¿µfü­=ão]X²ãoýèVÂøÛ²ÞdÆßf™‹ÜJ…Œ¿m¤[igÀ­„üct+UŠÜJ7eQ„º]u+•X„²D·Ò¿—ìV*”‚–T<@¥¥Ðt8Nòþ†Ó½¿`)ÁOX}ù–|ׂ[ò6»}½ic‚7ié<ûçb>ÿ,qЋû¼Ç‡ÁÛîgÊR Ff]›Ýƃ––dz¥[hiQ"i‰ 4/Jńð7 –ZÄ`Ý&9-¥[)†n%È­Ä$r1ù.àVrw+YJu+é­$nb´ø[X…+¹-HUùkxÊÒ_HK¥Ï„û†A¸/„Ss»…[é&ƒpW„;ËÜîct+d9ʝ,G¹‘Å» Ù꤀­Nf¥Ð­”J·»Ãåò èMZêF<ê.f…BÆ&Hã¤3fL—,X0_^±bÅ2Jf­‚ï²­ + Õ ¾ã_×?Žé OOë¡EÏ¡@/š` ¯XØǝ™+WPÜW˜ÀpÉ qÁÏN qøßñDˆÃ)Xº/:vG6tûƊÐu«ª@ù.¦[iNMìo*ÓºóèVF·Rº•zÑ­T†øۓ¡øۓŒ¿5büíi֟|–ñ·¦´-ùÅ܎ñ·Ž¬?ٍñ7áVÄø[Э„Sn¥ùLë^F·ÒZ¦uo¥[i/ão‡™Ö}*äVºr+…÷6æÿïr+•J¥ÑÒÃO‡û£˜§+žà-R–HK“–î™™àÍF_·„»ngw8†.Ï2Ÿÿ„›)K¬>zÀ'šÚ0e)†)K±£µq°e…ñLYJ8tèÐâDö,´”DZJ"©‚´4Ÿµî§ÅtD‰L'‘ó$²ŸD”ș䷒3äVb5ƒ+Öÿ9·RP*‰–DÊR‰A8áVúÙÀ \È­ôuñÜîw™Ûý¶˜wn¥‹t+âçÈö„ÛËr”[ãéVJ¤[)‰n¥dº•ØFw|*ÝJ¥þÌGêI2êLю¢+s?Ãֈ¿e#ézlûSƒ/I%ú^³â°«TÖèN`E¥VTò²ô¤‹¥'팿YmEñ7#•ñ7ãoÅ•î‹¿ <*Jr4PŔ~% å$™rPú5˜òrñ¿”*W®Jx"@I JøÓÎ.®âåʱ¡<î4îOÍã®Íã6 åq‹zÜ"»¯2,›M&°R¾¼hÑ¢…òʕ+WÈ7n\¯ìܹs»[¶OtX ò8¡ƒ=«‡¾h€B¾Âî×ÌìµÅXÌu;Øâ]òWÙÛó’Ÿ >c©ÑðÛÑd,=˜†õvÓ­´¥tûÚÊØÁ2º•æ׀֛Á´î t+¤[iA©7A©{Düí1Æ߈øK(©‰JŒ¿ýŽñ·'{Šñ·gXò9Æߚ3þ֚_ÌíÙЪ ão=…[‰mM†Ò­4–’)t+ͦq-0ÞïV:XÜ­tån¥¢"”án%ØËÝJыP>(ýÂ⁔%m(Á›öí}””%3S–,LY²2eÉƔ%;S–œLYr1eɃ{؋[¼Ï;¾3†)K±LYŠcÊR‡v ‡ëW÷}ø¸¥díÓ¯}…zÿ#FŒî7nÜXç´iÓ¦¸4)Ív‹AºJ—F),­ŒÖýåêaÅú8E̍”BÞDÍÉH ©ŠfÒ5¬£PÞêj çS¦HÏ.(EVª£wL©¯Ø>YÉغßn!ðz [÷sغŸ ÿöÕºïAVº Y©;Mஆ–.”.ý©?IþíԀü›¥³É¿Cþí\òoç×÷.ò¹„¹¢3ÁUL×#+ݚ¥¿{7¶î^x“ÇÖýLb€¬4 YÉÓÛD1ÛÈJVo“²Rµ–¹ad¥¿¨¬ôÃÑh‰™=ˆ–j6x3¿}²”€e)QgcgU–’©²”J.*K¦¨I¸l’p9Ô È# —¯¯bL¾ž‘…šÕ† vÞ)ƲT‚e©„$œ¡¥R/-™Á<ö,5€dÝ ÒvC +æϟ?<ß++cÝ¤lý™¶¬”fd%j+ñ…®ó“•ègd¥ØP²’¾¼ï™Ê¬äÉ¿Y©¶ù7û{ ™„«­·Û–•lY)ٖ•Ò•2lY)Y‰š“ó•è 4´ÚJEÈJÅ:ýèOòw ÷q܎„Ô<êÊбDC»b=v6 tz¡^wrÞь$u@©¨Ï&šÞ&:ҁغƒd¥9!d¥M?«¬ +”Bђßr¸P–%W e)0 ÷}tPN“—IÂbF܇ˆ°+ÉNÂáç_“ÆJ¸ ’pXåd“„Ë% —G®€$\!­NŠ„8ÊI•P7 ”*K¥X– -•AKf0 Ä`D§$둶RXQQ1¼@äûyúºÇáŸlÉJt‚cÞ"#+Qõ#+á¥3T¿Ó–•R‰üd¥Ï-Yɛ3²R ¶îc¥0ÞîZËJ‰,‚3²RŠ‘•hp’Nn;“¾¹YôÍÍ¡¶k.%»óõS~—êÚoQgû%²õå'ßRO è6†ë‹u®`¸´HÀÒY…º>N”NÊ×ۚæjõIR—Ñሠ+üyMËbk:ÖĔdFc0–:“¨ß4=K_íj:-L§%ù·U|¡kiî»91°Z@¶îÚæ߃Rme%·OV¢¶RYéP%»“ôƒÛÉU¶9E§}màÒõ‰gê´Ï¥ÐT*i¥¦öð<}ü¬ó…ÿOók ÒýG=nº2t, Z_ÏÙíé|['JÍrôå5ÀtVŽý¬ˆõy$Y³SÈ¿áçOÁٟD¡­JnÅÅùòoÈJ¨•sÛ²’ JNŸ=ɀ’3JPŠ Pò‚R£FŽ”tádJù(ižÊÚ³§2ÀYgu&—½eÓáMÿ6Ç}÷Ý×Óñ¨6ÇÓÚ¯hs Ôæ®Í1N Þ¦95 ÍuŠ2–86«\Š±k\ +‘݊R[£wF vvà {c®÷÷™\ 7¼{pîL£[U&½=³õìÚ<¼U… +¥KKõŒ¬4Ӗ•üª +½ÜŠj'ëï>ֆjA²ÒéÈJÐÒeA² t® Jç´²uS„[w‡²@Y)¯º¬ôP ¬ôZ¼i™«cŽý1e%ê5ÿ²Ò1ÑRpΘ„‹¦n@`îHYi[²®¨ ©,™ 0ÇÒ ýD+èÈ6ƒÚ¨ùõ"ßÉ£%Òéóù´Ì%¯ö`¶n èfðè†Î ò±uJgæaëÆ`ւŒ²°u³ì¡„j,rÌa¹cõ´R©¬•L[Àî™â¨»kçß,PBVò%{ˆ€R”"ïkøuƒRtPJ²A)Ã%½8Ÿ·ù*4²+œB‡·ßV¸"De€Ç¨ ð •^u 4èm Þãµ9f̘1Ý©)k¾SÓN¥Ss¥K7”k]šî6¹Û£¯vEižÙc–) +Ør1ûÜöá:ݝJô êdéÙ ¹šMWçkfZQ¤xºYi²ÒԐ²MàNBVj핕î=U!üöÓ4Þpš-+†¬(](µ”Î#ÿ֖üÛ9-šAKMèmÒY©^Y)ß++ÝÌmó2²Ò£L®ý•^BVz+PVšHm¥ Yéƒ`YIáÿÀ ÉJ^Z:NPª½e •Ä”„£Ý†„ûÞ$ábHÂŒ„CVú”®ñ‡ÌOâu¥š·Q´y#²ÒêVQ€§’R< XB5›“=yzb‘¾…±–¬D®TÄ3¤L?½A墥åX–üh‰P";÷6yºÁÁß-"ÿV(P•OþªM“sòo‹Ò½ù·¬ü[€­Ûäß<¶nÍΟטû{Èü[£Rð?YIgü@é‹8ñOãŧ–¬ÄU¶#Y¾)E×àšTý&WP=FæPíh +}GFsڇR4²?k<_ÎÓÅÔ/_Ó# PO@é6ðèz†+°]ÂpÖû³ruiœF‡VÙz[@©>7eÜHRd47U§3+™ü[’î!R(¯•|Æ (ÅpN£‘ꢢl[·¡%W-y@‰ÊN½8JPŠ P + Jº4 (Åq¥$X ¤ÿ¦r­fðJ(éJ®ËþS %È´Âý‡áß +WŸ£;á¡G¸Êƒé·=Ò1A›ƒoNÍ=NaÅR§‚å*—Bä:—Àa‹[q‡[yO”"×>Há@ŒÂõGÜA4ßDEǸN÷¦`=Mg¡N¦žÝ”­Ø,+•{e¥‰ÈJïY©)ÕZÐY©²Ò£FV:ꩊã7Jם†¬(](](µ'ÿvAk¯¬Ôր’•Ó`òoçÕ7²’vp²RGjÇta‘O7&‘²½²Ò½FVJÑdó²Òsád¥©$áŽQV +Ó î§“•þïX’pÿò%á܁I8[Vò%á>³d%}òèº?ÿú¥nAVZÏ´md¥åÙúV3cÏcƞÉŸBæg|1Þî¼Ý¥‚¡e$áÊIÂùѾ%™‚A‰µsÃ)Îô>ešÆæi“rÉ¿eæßÒòo›È¿mÿióo!ù4¬¬äª.+}Ïÿ6F‡ñU¬Îøg¶¬t€3¾;Ig|+g|=g|…ñ+©š=>N%íñÙú`uÿ õ5$½g1i?Ž®÷êѝ 7‚GW3t¢êU{@éÊ:üPj (5£ŒhÃL]’u¨Á^L5û|*fÓø/ƒ€©´·IÂü•|ÆŸ1œÓh¤º¨¨Àü›Kƒ”ø—%&(ùZ˜D@)J‘áߔ̕W;PŠ +% A ”c’.œR.œzì¯ •ZQ t %}˜¨ p­p dô!xl I{΂O'Q%r&±!ä>ßd ۋdӞ"¯öp¶n èðèZ†Ë.¢¢úy4¡ù}Ž^w +UÖ[f齍9“uèJáÎ:ýåp:3qɧ%’C¥K>ãÏXΩ?(™ü›—–,FŠ€R”"ïkøu‚’®FPÒuY(éÅþ ¤kÚ”¼%”Ú—Pºë®»|%”ž°J(Ñ +×1D›cÔ¨Qïd&nfx:‚–;ŒV;,]šb¶¹D +»¥}n…Ï¢ÃE+š)æ0k¡#1b1óÁdV4§â¨H׳;2õ6çh>ZgËJ•¶[iF]Ý ûd¥!FVjnd%Ý ÷; Y©µ í6x+NQ0¿åTd¥S5-v=UÔPºPjßÆÈJ¥óNÒ`d¥¶Íšè%ç6ҋÏGVº°NXYIlv»‘•0·X²ýè=²’ŽÔ#+išõ—•ôÙ#+UËJšBËJšzFY)\.¨.bPΚ»Y gËJß3wËÜý"ÇçÌݟ rdîޗlV?YI§i}†N؇ôž_aÉJúVçÓcÖ⩬ÁšPŒ·»„$\©¾¨ae$áʱ,Ғox/Ó`Ë )1 „Q‰R–£¥ y•˜èg‘›Qi1:È +{ý›é¼³PÚUãú·àú“®0õ'kJÕÐ4DÉnKVM£¼hꓕ¾DV:š~ÌU¶Ø.üa[¨`¶ØJ:‹,¡HÃ\ÜôS©{4–µ‡Ã©Ô0Wö+T}:W¿öGьîŠnG‚ëÎp%Ã¥<֎üåYÐæiY”UB›kʙ¬@WwÑö'Ó™E:3•.•.‘â ñÀ§¥˜h_þ Z²@‰!,(97ýš< ¤Ï¥(E†ÿ8PrƒRyyy(PJæ¿©<‘ÉKry±§„’öRß.¡t%”<µ&;tèp!%”:QBéj>ÑM€Ò]”PzЯ„’@É*¡ä=zô(Çdm„›ÙžENM6+œ,xs*,mt*@mw)îvé¾q¿[¡ù BÊÇÑÞ¢}ŸX]Á4iNÐ`úŸ”‚£"MÏîÊPÄ܆¬´1W4¤¬T/PVj¦ÿZ d¥VÈJ'+0>Üږ•NÑñÝx*²´t Ô PºPºP:P:·%´d@©)9¹ÆôÒm w´««÷v@VºÔÈJ…²Ò-X2îJ7²’¦„Ç,YI‡æ‘•³CËJú€µ•>û…d¥Ð´b·›¹ûæî/ã¼Þn#+°e¥íxg6áYkd¥lý†–Òau!²Ò\bÍÀM?™%êãJðv—Š–F–™$\-™LœqynJÅ6(hƨ4Å•Cæe•Rìú“‰¾ú“AF%}"?£’_þ-ŒQ)TE¥Ð T“¬ôϲ’eëŽ6²’ès2žæ*û4ÝCÆsË7°ìðCje/ÃVA‘†i˜Àšþ÷XÝ?˜Ìòë$Ҟ#¥Ö¹¨PtxtÃÕ¬¼Œ¡=ç¯-¶ø3¥Öxã›cùj(ÕᢘәOj:›tf*]j‚# PJ §^ð˜s‹‡< ¤Ái§ðqG@)J‘!JG¥Ø ”æJõêÕ+¤2€”Zµjå«5yzp­I³©5y³_­É§žzêINjڨ5ù ô. 4Ú1E›cŽ6‡&ªÅË*@iS1q ´PÚãRÐ:àV$<„†r8Ê܆+®±ú\(Ì×éaúŸJÆQ‘ªaoº^²#S±}sŽâߺŒô;)’¾™jVk¨þ¸‚jV‹¨9›Ú“3ô¡G³^í]’ÊýYÃöÙPêðv/Pt+xt-C†‹©Huõ;Oµ…S2É¿e£’g= +T•rU$“ãtfJi¨tɨt‰À§þ¶&Q´5q›ü´äJú¯”(Ê¥(E†(Õ +”J ,PÒÕ}2—Ëï¨5yÇÒÞª5i@IŸífjMÞm՚(™Z“/Úµ&‡RkrŒƒJݳÏuhÆ1 ´Ò©À¸PÚìÔì²Ã¥PµPúPúØ-*ø4Ê;?³Ú§šòÍ +xŸÒ¨êp’þ{0…nUizÉî Å¿mYâKVÊWô“•Êd¥5¥jª?þz …æç[jº{ò$¯¬Ô³âx6ÈJ§,_¾ü@éJ@é2@éb@©= t t^KJ MX׈Î'õõKV*S´½”žW—S^æ* +È\O‚Â#+i†õÈJ: §‘•^NÐ,ÔYé]d¥Q1b½j²’ÎËÐÒzhi+Ÿ¬äüÕÉJ՝ƞK>¥#„·ÛOVÒ×}$ÁÈJÆϯïw•~¶SéÇ#+é«]…¬´Œµë‹(ò3jˆ3)=RPB®T´d’pƲäіŒË›2ކ‘X7Ä¥áùYdƒR~(áèÎ0Žno¡îµÉÆÑ­£Úž`Ýƨä%¯Qé[¬4ßÛF¥raÝ5€RMhúÏÀŒ§_µŒô_!+™«ì0EÒ°‚b7½C¶R=EÒWQ$½2UpՎ¦Q÷h†þoãÊ~ïÖ3œœÇЌîŠzЦ;CW†Ž<ÖP:›nçÓDï$@©iù·T±J T(åQ÷<‹vzé,'Lñ3*æߥ(·-+¹¼ƒÓ”ôÍx@I°¥(E†ÿPÒ5X PŠ¯”Šxo9%”pÍ4 ¥Šr÷îÝÛåîkå0`@»ÖäX@iªƒJ€Ò‡âäJ‡‚ê:§f—-€ÒN§"ð>—&–ƒ.ÁÃÁ‘(&–(7“¯øÂ*H¨¨÷…?M¤ÿB2e…-YIÁr'²Ò–l[V*”•ê +Õß½{÷(d¥w›P[©™ãË-•Z)À?v >[+„ß (ÝÚFÁ²{M®W·Ñ,ÙPêÈÒ·‹¥ É¿](×œ¡)CcüÞ h‚¬Ô¾\´t ²ÒeLÖWæYIaøFn¾{dYIGà‘•tTFVz=^SÑ ¼Ý#•Æ‘„«&+éä¬! ·É$+iê­&+iþ ++ý«–²RmA)$-Õè4þg8Yé;d¥¯-YIßt¬´ Yi+²Ò*ý¬FVªÊÑI¬DVZ@íè9$á¦Ól2­5ÆCK£K½–%-—÷3P¢ò]†¡”ö6 ô^aPšƒy”° û;ºéhrBŽîc¥ðFúÀú ~¶î(³âÐgëæN„üÛAÊ~ÙvºÉl¤Bö‡ÔÊ^FÕì¬ßŸÉJþ‰¬â|sðN¦®£7¥çI©=\ô PtxtC·,Ê*1tÈ"ÿ–Iþ-ƒü[:ù·4òo©äßR´Ób²Òù,vÈNԟÌHÐO÷åßth~ù·(“3²’>B5PÒÎ(E@)2D@©– ¤!‘ÁJeeeY\3yá@Éåöt/¹øâ‹;p|PÒ¼…¢Ü”LQî¾!ŠruPkPšçBTJ«lPÚêT$Ü(íwiâ;(} Áó9ñÏ8`¿´ú\`¦ˆçÖ7þ I”NQ<¦×íAVÚnd%¼ÝklYÉ× nj]j+5@VjdËJÍ5¥¾€¬ôT+…ÈÞ'+Àß×ZÁüŽÖ +–7µì\ (um£ƒï (] +(u”ÚµT(½ …†ó•ÎCV:¿!¦od¥ 눖.BVêHú§ ËÖ¯fYPwd¥[IÜ܍¬Ô‹~ôYIáڒ•â¬¤ÉÁÈJ“¢E}31¹MV-¶d%Í¿¿NY)ÈÛí§tDÕ,+aS3²R²WVځ¬´™Ò됕> ÓÆr:m,Î3ÞnÍݳ +MŽ•pÅ^˒–L&n˜A&ê-™a˜a¤Ĥb=û~¡¾ø1ú.’µôÍJIÞ¥o»ìғ‡lPú"léIWM¥'kJaNv؇¦Õ·t“1WÙd¥YA±Ÿþj;é´¶™žkk©þXEÈÅ)ú”sø¼SH:ŽÁ§5CvD¶—Ȧõ”z#Ý Ý +]ÇЅáâL=v~ù7@é@©% Ô8•ü[Š.ˆR.ˆt֜Dòo äßâÉ¿Q³?Ñ2*‘‹&ÿåË¿’þëJzñ1‚Ò¬Y³" ¥È%JzG5Pòv/9ãغ— 8p€¯(·JóçÏ÷€’¢£¥õNÅX?PrPRüûÔ%ØùÌÍ*!BߗttúÊ*±c&M/-IÔ‡“ BKûe¥õÈJز҂R¯¬4©²RCݯm¬ùm@SEÇWš+Ê?ÓRáºO+îOV¿§µèæ¶ÖšWoh­Y²[kü€R'@é@©}+…Òv€ÒùÍš`^j(!+]XWÓq‡r½÷R´ŒÎX‹»R‘ïZÖ݄¬t³Ë}ô£ïÍ]´GVÒäà‘•4) 瑕Û璄ûÙd¥ã¥“•˜À‘•~!+}Š¬tˆvû©‹¸‹¾dÛÒ4ÝmDVZ“e{»s·['v®„›j[–,Z²–ÃyK-`0x4‚ö'†‘Þ#ë6ªP¯[ w˜UoS|©·,oêÍJ«mPò-}Ûç%ké[”Yú¦õݏ¼ô­'ûŸ~²TJÙÏ¢¼ù7­›ü+(>¢cÈnªão¥‹Èzú‰¬¢³H%=FæSíh:uÆa·Åèm\Ù¯JϐW{ Íè~ ¨G&‚º2tä±v€ÒÙéäßÒÉ¿¥‘”꧐K&ÿƝC«B³ȿœ£ d"õhãmPŠ‰2ù7] n7´ä2´ä< DeJN}PŠ€Rdˆ€R-@I…¥ 6oPºä’K.¢{‰”ôQouôìÙӀÒ#(½òÊ+/u/qLŸ>݀Ò|E¹¥âƒõJ +‚»‚˜€ÒÇ()š}(}Éí¡1¿~M£p“0­¾Œ£ÿB‚û4IÏ~ -™$ÜhÉÈJ›lY©ªÐ–•Ê臬4¾¾¢üHd¥ÁMåßh¦øüb Eê¾-'iEߪ“Ñï=PFéËSè“&Q h*‹ß­Uo¸r†J½ƒ’©Jfé›%}ÊZ€Òÿ(ÕXÈ*¨>º•‹â»Rž»3 t) t ÔPj(]И¡!‰¹ú”_ªKÅÊ2½·#óå…Ú_Wª_G+‡›ñtÜÁm¸GVÒÌþT’æø•Þˆ×ÉñÈJ:ðq$á¦ùÉJú€Ud(×r®6Û²Ò>héPY鏿*Y)嬐²r‡õ3‹[²EµlYi·-+mÊðy»MŽKvά„ ¢¥ñ”Z[¬¯g4MOü›‘Æ1)_/žLÅé¬éšÅZøù¸rQAԔç^2õæ¥êŔjnf”~¼ü›Ëο¹É¿Eæßè¥ö1íg÷SÖ¶Ðsm-¥ª¨µ˜:‡R›SX’0»ÝP ÙýÓÉ¿aÒî›Aþ áè^ èVðè:†. §³þ-ü tJ*ù·òo)ºêJ¥€R ”(eÚ ”K¡nª÷ÇQp-6Êο¹½²’ËåLÖ-JPŠ ¿ôðÛ%í´¹ÕWíÌ@PêJ=”ÛŠ¶{¥¥Ã ô5 ô •Q¾%Uñ­ÕçÂKK_AK_$è‰#ÐÒaKVR`4ÞnOÉoƒ“•ŠòKŠåç•j›^G³é„zšMßk¨ÃÒX„òVӍ7¾ÔL‘úé´CoI9˜VŠèwŸ¤°yÛIš4»Ÿ¬OЍ†oWJ—J—JZ,\¸ðÂfÚ5™14 ;Wûw¹Þv)‹®.+Ò®®4 C©_|)œÛ(%sOºÎȃ–¬¤âfˆW•„jÉJ:úIÑú³üd%Í¿Ú²Ò6KVÒÙøñe¥ÿ;Æj'&+ùªH{e¥oƒe%Íâ>Yɔ ؚîóvû +,™•pÕii*K'‘@ïñ|3ãh¨;–a\¡†ñzÌÃH^1iFŽ×žT‘i +NjÏ~åXõæ+Ïmy”‚Ro?(ÕVV +οE¤ÈJŸ³Ôô;ÿ¶‡üÛ6“£ŸÈ|ÀJV¤ÍgmÚtV#Œã·;"üÒЫdӞA.z ºPêugèšNþ Pj—¦gÏ”NK%ÿ(5M&ÿ–¤K²Œ›†Bnr©3–EWÄ´8ŒJ€Rb ù7”bAÉ}â ¤Ë9JPŠ ¿]PÒàJ⡟”n ¥§ý@i„¶ ¤ØéJŠ{œšß| ôKS¾4 äò®¤6!ü;îzM¼oMB&Ž&èñzâóD½ÄJÂ¥h2Þn_ÉÓàäCúæ./ÔÍèÂQÙì2EÇ)u"cë I†7T¨»±âäëMudÏ7×lúT EïÞ-Ìïk¥©òΓ4sÞ|’>Áõ'UVV^(u”:J—J¥öMA&d¥ "5ÕÃù]G´tI™ÞÛ ñ¢K¡ÂðU´Àºžj3·PæùNVHßÏ<󉇾I: ½ßˆ×AŽÓᎴd%Åöi$áæ!+-±d%…ÿµÐ’‘•vBK~²´dd¥olYéO!d¥ÿ +!+pþ-´¬@KÇ#+Ù%’¼ÝÛmo·/ W•mVÂy-K~´DÍôiВé7©PßÇD?k(Ð0‰ïh2ÃT°Ö#&y³n X·¸ÄTæN³ N&Û ßìUo>3÷§ÑÞÅ ?(…8Ï!e%€Ômòo܄øòoÉÌ&>Öj>àrj- ,ä,|×QCßÇbô®ì7ÒÈ¿¥“”ŠînbèÆpYšk(µMՉý Ô:E—A3@©aù·D]Å\y,qÈf‰CzF¥Xqq’Jù7·MK(é_fpUœN½Îi’.!‡C»ò€’~%PŠ€Rdˆ€ÒO¯(=¨(Õ”¡@Iaî”þȜb|´$ú/IJ¬Zú2AÏZI¸d½ã`juo÷º\œ +U 5*•f”ëO¬«P?ª¾Žå݆ +õ+H¿ÒT¡þ™æŠ˜}Z(Ž?ÔRaýÞVŠ=Z‰snj%Pº–†o])¦t9 ÔPºPê(µo -PªÞTCS¹ÞÖqg$‹®ÌÄ×â ¾‘~·#+݋Åã!VH÷IÖ±<Ëýô+ :¾$á†Æjš¬4ْ•4o-ˆòÉJ:k˜¶Q6&´¬¤ñ×.+ýWHY)T%J4DS2@_ ·ÛW`é«Ë‰Îd¥)ÞMÝùyúùÍÉל<“šéÓ©:­@ßôT,dSÌ@zÔàÑ4†øïga+››í“¬¬[ºñqkšýÏÎz*so¶AiOˆòÕÌÜÇêQª#Õ +™Â5æß8´¯XAñYPþF[(e´–¢FU¬Ú_Ìúý9¬äŸÂj„1$͆â3êO"í%”¢¾iä߀¢{¡¥[a¤kÓÈ¿ñØŀÒy€ÒïStvO”Z$k¥º‰ÚiIù7ÔÕL{dM¥}tR F¥h“3 DþÍ”¼Œär1ÉJzG”" " ôˀÒñ¤Þ@锾rzAé;—w%õ÷¤¬!ˆ–â5XI¸$’p¶¬ä_2€¾¹y48)PŒ]\¬h;·Tä1­\ 2®žnZG6ÐíëàF +–o6Ñá½ØT¡¾_sŠçµPDïÕR`swK!Îm­ô1n€–®¡ŽÒ•€Rg@©csh PêÐZjÄÐPª§áârJ °Êê2d¥+ÈítcUwd¥[)>s6ØðyƒL3òõ-ÌÀko àÑL†ÙTt0Œ4Ÿj¡ iÙW‰˜´1i•mO2½Þü[˜ø*s‡©£TÛUo5€R½cþbŸ.“ã»}ù7XÔäߨ”ù]XöàµÚ†ëj= ôëÐ*Y‘6ŸåÓYˆ0ŽŸíˆ¡·SÉ¿!=(= +Ýõ€‘º3\É/MÕp tV +ù·dçVɺ_h’¤S\P*” +¹r¥L@)cÉT®O”|ù·hL{QÐÒñ€’þd”" þc@éDLã‰dM;ϒ}x5ASÑ@d¥a–¬¤¹br´€o6²ÒB’pËmYi£‘•HÂíAVúȒ•t†>·e%_µ€°²’¯yÆOS„òǓ•|Þn¿K©4ϵ-Kkè ç£%ÓnqŽÎî‚\çù¹ S®NûÚÌ̶‡9èÑ7Ö36#-¡ õ²t}3>1Éʺú¸÷Y½ÞZ˜„.8yœ ÄHáγÃ{ŠÿÇJ~²­‰ƒòo¤M’ÐäßL»º½Ô.ÚA£Ô3ZMe£åÔ8Z@µ£™ÈŸBßKÑ9ŒÙèu@é¹Tú¿¥êçÝ (ºFº1•þoü·Å)zö@éw€ÒɀR³$í¥A¢öWž =ÅëoäÅaT¢k: ”b’7ÿK×£·7ÿævy() +ø’ÓJÚi”" " ôã”8†:JCÔQ +¹ê͘¹Aés”¾e¢ÿ£‹¶X./(ý‰[ß?… ¥oâ’p‡¡%o7%²ñvçj"]‰¬´¤ow‰&Òée:Š uD#ï××A i 9´#ãËMèÉДPßLý¡æUUU÷¶X¾|yú,7µö\G÷«XõÖPº PºPº¤1ÈÔdªÔT/S¹^܉R‡—³¬êJê^C ±h‹uUúîf½P/|‘È臩õ¥DÍo2W¼Ã\ñ²Ò’pÓIÂÍGVªÄÛmd¥uÌ [lYi¿-+AVú2„¬ôWhéﵖ•Ž+ÿv"²’U2 ÚÛsÃS‰Òx»M­vÚÁÙI8k%œÕ<ZJTnH‡–2 ¥LÄª,M‹Ë²õM/ÉÖÙ]”£ó¼0GsEŽ¾óùf€ŒæÓíÕàÑڙ- +b$JS@5!1‰6o>{’ñq6ŵz½E´0 *8yL tŒý‰Ãåß@µjù7œó¨`&qh¼V;©‹½™ +ÙkY‚VÅb´E,K›ÃòƒÉh £“ušÞ”ÞJÑÕó" ôšÑÃ@Ñ= ·J×ð¯Ë.”ÎMÑKÎL֏¿Mù7@©Q"F¥ŒJñº8óã0*± 4ƒêb©TKŠ6ù7ŒJ(Ù²’(é¿. ”Ĭ”œPŠ€Rdˆ€Ò_pÒW™ûòÀÊÜ÷[eîP Äª7JŽ0 ôƒË;§x@ÉH f椷'´ômœæР$\5o·âä’pæé-/Ðmé¢"AǜRÅû©åŠ÷ãê*bŽ¨¯x?¸¡Âæï_l¢ØÙ¯)+xš)À÷j®(zOs!ÎmÍõn¤…ɵ€ÒUx”ºJ—J¥K¥‹ëó¯zèM嚨mؙj=WPÌðê|×õ¹B°[hùpG¦&–û¨UܳǓÈJϑ‚xÄÛ¤ †ÇêpÇ +M‰ÖG˜¥㑕ôWÛ²Òö@Yé[Vú:PVòÏ¿ye¥Ÿ¥Z@-e¥ $Ü÷!½ÝÞ$œ§Ë –%›–6Û´´ZúZZ™©Ó¹" )Kg·2K´8['{q–¾øEö°˜¾¯K2õìÒ ½ny#Q¤z=u…,1‰Ea¾¬›eOÂm„ŸÛ×××ëÍJ¾&µ¨Ì}, ä¨mþ%€Ò× »ÃVþM'v7•·Róq=ÕW™üFëy¤ˆ§JãøÅÇg4ÇÑ+xž†‚…‡zBF·1\ŸB¿h†Kxâüd½ä€Ò©€RËDí 1 TP*Ç¨‡Q‰ t R©—‘m•¢È¿ù’·a¤`PÒGpR¶-JPŠ P:P +Ûë­5—K-Z˜õz¢×[P “õ6(í¶Aé°# õf’3”þì6·¾ >Z”þ륥¯¼I8ËÛmêv“„ÛInK–þƺ¼Ýù +–K ,+Šïg–êX&•ëÎut]Ù°ú +Òê¾öµF +ÜÏ7áƸ©þ‘fbšû›‰nîj.ιµ¹ˆçZ˜\(u”ºJ—5®¨¨èØPÃ¥ ê!5ÕÁËDˌ˨ÿÜ¥ˆtô»6Oû»‘ŽX·S¥ïÖ =È:ëÇId<¬ô2I¸·¸³õû$á&"+Í°d%MFVZEÎ'+í²e¥e¥o‘•¾‡–þ(+ýó×"+q,îP•(«'á|–>¶,K:VO8‹–Ä/F[Ú-­K×ܸ:C³î:2e +™–gê/ËÔl¿Ô Ñ2VÐve #­ƒ‘¬ +“8“üŤ ¬ö¤ onï‚7OS\}Êcìõö<½.”Âçß\¡òoœXêŒñæ߶›üËô?dÁþ2@©‚µi3ø‰NÀ†=’•kƒ“õ~ öyPzz2ºƒá†«:&ë‰v€ÒÙÉúݟž¤»„“¥¦‰•ô”J…€R. ” (¥aÕKŽ¶óo,lˆu{e%(¹©7â²²nA D܉€R”"C”üA)î(Mq6lXfR«V­‚šâžÃ±´·šâ꘻ñÙn¦)îݎ‡µ9žÒfRmŽ¡Úc´Y 4W›Ý×Jôzs(ôP:à8Lè”!@Éiæ@‰`nJ¿ü%ÊÛÝÐRÈ$\’¯À’©Û·ÛJÂ)Þ¯ÉUŒ­Ê' W¨#˜W¬<½TÇ3¡\aóýº:¼!õ;û7ÔѾ҈xßXÁü‰&™‡›*”öl¶lÙ²;š vn”ºSp²fÒå€Òe4t”:Öc¨«':•“¢+%YG£Œ®4»&O»º!G;5m±î¢TßýiT O¥ ٌ•^GVDnD¬üØZØ!+ÍAVZDn²Ò&‡MÈJ;•ör&r&?…–¾pze¥°E(>[÷qÈJՓpA–¥õ%ÓR +™¸Tá̦4µõéúº×¦kŽ_nIçt•á¦ â•éê4=ñAš^²š†°ku¤-ö27ãLÚKyƏâÄ$_ÖÍÏÇíöړþXàG¥É¿±ZûPú’EzG%“ÛG5ìÔÅÞLáÇ5€Ò +J}-buælRē0"s6³Ñ›ØŽ^€ž„–‚Œîf¸™¡[²†Î€R{@©m’^w Ô:£R‚~÷ 0*ÅcTŠÃ¨Äï>‹äs: ”Â]‚(!+yòo†–4øƒ‚u”" þCA©E‹µ¥„p Th’öRPjÊîOvœy晧;Î=÷Üs:thïèܹóe(écÝä¸[›ã!m€Ò“Žµ9ÞÒæxW›c´6ÇmŽ9Ú¢‚ÅaÀJ‡î4×J[¥]E=(}†Ñò+ÊÂPÒÄJ±@É$ +ŒÄ`fN Š–•¾ó%áìK–·;ow:ÞîL’pي˜æêϚ$ÜB“„+Q؜Z¦€<®ŽBóˆº +҃ë+è¿ÙzÍÇû5VX¼IUUՃM—/_~oÓ¥K—öh*¼PºžoÝ¥+¥.€RçóçÏïTdªËP®g;Óµ í鯤=}·|Ìá¹¢¥›³µç;èûГz}±Îº ‰žáNýîÙ +½‹¬4 +YiI¸™x»+•–"+}Àõz"+íæL@V2¶îÏ8_ÕFVú lÝÇ!+z»ÿ +ûµƒ lžk,K¦'œ-%é›Þ,ˆÙ-mƒ–6§"0¥éü­Oñ¬KÓ¿& nJÓo2hXcãÑ:úœm°ÉèHÛI¸í¢põ^SÀv&1ÉT¹ªžT³=É”j.¡tÌ ä%#+¡d…Ë¿¸3zØaºªˆ±óo¬Ð_Ç´•,F[Âúý¹`üT€~ ‹Ö†%ég;ìy Pê +õŠîne¸–¡ ÃÅI +”Îä§J-0*Ju¥’8ŒJ±•øÝg §¦FÛF¥(oþ-†0(ÑAÒJÎ(E@)2D@É”bŽJz±?(éš6 t’JmÛ¶=PºPêäèÖ­ÛÕ|¢›wis<¨Íñä“O>áxA›ãMmŽ!Ú£´9&kó%a@•C‘p­Cño‹CH²Ë¡¨·ß¡¸û± J_:¾¥J\ (9}wàf¡ŽwðÑÒÐRµ$œ]`ÉJÂiòڙ¡°¹ÙJÂ)Æ®ÊÓß^Z °YQ¤ ?³DAR™bçè: +úÃê‰PÞ®¯ ÿzÊè5R¼ïÛX±ýÑƊ§4ÝÜÝDœs;Mqo”®Ãžt5 t%©·.€Rçú.«ËPx*#EG£ú+‹DKWà ÏÃ!ž#úº=‹b4èE-šG1{ô#›ñ"·ëo°h0²ÒHn¯Ç!+MCVšE[;d¥*d¥µÌ›‘•v"+íCV:(+Xµ€É¿…¢¥KÙÃz»“p–e)-%@K‰^Zړ¬¯{g²NÓö°­) SŠ¾øM©ú ndؐªŸÀzߐ¢aÃÆd=»‰®°[èx¶ÍäÚh€æc$¿„ÛQĤÀ¬Ûñ¶y«ù<הûïàüš–%Ë ˆ^Ò£’éNýI4F%@i•·QóqÕ?À^½”5™óY9OÑxÜE#¥·q½šD¡@é1@é>Èèv†î W2\ +(]„Q)£R¢ÞÖ +PjQ)£ T(åJ™Ü ¤F£MøÝÇYù7d4´ä%É¥Ç" ¥È¥c¥$†TžÈÀ¨”Ë ¸pJ¹pêqM7q´iÓ¦•ãŒ3Î8 P:ËѾ}ûvZG÷*>̍Ž;µ9zis<ñÄ}Ïk#Œ¼A@y‡Ðò>Af’c¶6z'-"­ ­¡¼ÛfZìô%Å°#Å5Jß8 (ivù™=”þfUË3ƒYCDK¡VÂÙI¸4Ð튝›²HÂ各ËÓ̹¤@óà¼"ÅÎé%‘ eB’÷ëNÞ­«˜= >A¿‹ž*¬?ÙH8Ó»±ÀæþÆBœ» vn£(÷œ¼ŽòWJWJ]¥Ëë1Ôa(ƒ JPžŠõâ« ±„çcwÊÅø”Mú‡Þ‡¬Ô›uÖO’ÈxŽ;õWqm ĵ1 ×Æh¼Ý“™5f1k,DVZîƲÎ\±Yi²Ò¸ó#[Vúܖ•¾ƒ–~°d%J8!mÝ´t"ù·ZÈJµHÂùºœxh r-Å{ié`¢¾îý‰:/{“t†v'é;ߙ¬¶=Y_ü¶dMù[A¦- ›“Í ƒù׆­Izɶ$¯„´<ڝà͵YŒDeF_Â-șômT˜dŠxíIÿüQ|ܵ•þ'PV²@É`T +›;DiÇ}4YÛA‘M,Ó_͂ýåäß uΔ&ôï%R¨PzPz¹¨<Ô+‰Bàэüë*†N£’WVŠ‚‘üAÉ,xÓ·ïtê‹w: (±œ„Z%PÒAF@)J‘á7 JÎ`Py@IdT ”t­z@IŽ”t%×c­[·nÅ:•¿{‡q£S§N—:®ºêª®|Žî„‡Šk#x<ëx]›c°6Ç{Úµ9fjsˆ +8„Ë F« K›¸“ÛAÉ·}ô]:äJŠÊß8þHóïPú«3”þæö-…MÂ%ØI¸ä $œ"ë†lÅN+ —¯ypa¡ÀmN±èÔEþqeŠü#ë(\¿SWû­úk×®}¹"ú3 àû4RP}¸Ñ²eËîkTYYyg#ϭԚ¼PºPºPê +(]QoÞ¼y]¥.åü·Œ*Öë®*Ô;®ÉÇ锋ç)÷S–ölډ>”f¼°ú»O³šèen×ßb>Â=ö{ÜcOˆ¡ÌA´Ž~>²R%³ÆJ&Œu¤ ¶ +íBVڏ¬ô1²’eëæœúòoúYmÝ¡iÉ'+Ք„ó³,Yµ"ìžp1†–ôMZú<ÎВ¾îà :‡tJŒÀ´?QgȇL»’tÖv&iúÜa ú5n·#í4êQ¢ö$è½û`$“kóg$ÜÛvÂÍW ”˜TCÖí§¥jù7/(yòo€’Ë›3…ñ¿”>‹¢Pù·ý•vQ{ ù·µäߪ¨[±•szçdòe£ñb¿Kí­D +JOBEwƒG73tcèÌc1*%bTJÀ¨(5Ç¨(•ÇiÏű¶Q %5=Ú6*qƒOþ-–äsŒ‘•,PÒ¿ÜPŠ€Rdˆ€RPÒµP ”t¥$0øƒ’žÍæÅù¼­„+¹.Ž¥–ŽÓO?ýÇÙgŸýG»víÎwtìØñBÁ•ŽîÝ»_ïèÑ£ÇíŽûï¿ÿ>ÇcÚÏhs¼öÚk¯:isŒÔ映Í1C›CTPá,£É‡Ýnn$@mGüÞËR݃´ªüÔ¡ö…”ÕAéoNïó÷´ä³,y’p¾r”$ᒴσ) +ú{M.$\¦èºlÍ~«rIÂ哄+½Í*ÖíëäÁܘ2EêáuJÕ¥—U=Ýõ¾X_±½_ƒ•+W>ÞPø÷`Ã¥K—öl´dɒ;è^r •n”®”ºJ]¥+ëh¸¢œ•òX‰^rU‘^|M&§<x9¤ò²´Ó{2ªªªzÑ/ëÑTãóЍö 8e_g*„uc8²ÒXp=Yi³Æ +d¥ÕÜYoBVڎ¬´Yé ðù‰•%ýd¥êÕ~:[w­½ÝAI8ŸeÉm[–BÒbH¬¡%}ò#ÐÒ'>É S‚A&¦}†›uÖöXƒ~ »íaMF{}xD§Ø|~$ŸŽäc¤hoÂí;_=w€.ê¿Öí˜:¼ÕöŸQÉ¥ïÜv¡@ÉÊ¿Q{wŒ1*Q(€%h«XŒ¶„_â<¤Î©ˆžcñbcùÚ@ée¨ ôPt/xt+Ãu ]õØŀÒy¼î÷€Ò) •â1*ÅcT”J¥|@)›{ƒŒhcT¢£I”1*‘ó% Q(é1J.?P”¸›‹€R”"ÿ1(™pí@É (EqIPŠåJ‰·@IC +¥[ T^^ž£»˜ÔáÂiĞ[X}LÎ:ë¬3¹ìÏ£<÷ÅV}„ëü:ã>ú裡¾­Pú» Jwy'MO!g/-ù%ᬞp +ú¾$܁ÍjþI8ÅØ5يüU¹$áòEç* Ï(VhžX¢P:ªLázhîuYù\OAõùúŠò}èôÑbÀ^ …8÷6ìÜAQî[@Kø¸¯”ºJWJ]¥®e %zâê"½äš½øú|ÑÒM¹dñ²Éçe’Ù£AVod¥'•žMÒüñ*²Òd¥¡ÈJ£•&1uÌdê¨@VZʬñÆz¼[‘•v#+@V:Œ¬dÙºe¥c²uŸ0(ÕÖÛÞ²d¼j´ô}´qyëëþ&Fõ+¦/ ¥ÏŒÀgI§äãx!Ρx¡ƒ “ᦠšMÍ°ß ðÐ{ø(Þ«ŠÓ{„ôI¬ñl‡b$ÜÛ¾„›Û»l³¶bÒqۓj‘ó +›û“ËkTúÆí5*}Jçك€Ò^@i;57RýñC\CKY`PAþmž¢ñ •P…‘H{•”Ú3 Ðc@ÑýàQ†î‰•.å‰ ¥?J§J­âm£RF¥Xۨį=3Ú6*EÙF%·WVªJzÖE­I(9ý@‰;·(E@)2D@ÉJ‰~ ¤g³¥< ”6lXǯ<·)¦ª<÷µÚ‹)õYL©¶5|Kßìfé ô½CáڀÒ_| ä ¥¿[s|ø$œvb%á“pišó¶f„Ë" —£(ºR_tó@}È{hóփZ“·J7`Oº®®Èè@éj@é*@éê ݊ôì5…zÝõùŠÏ7æê½·fk/wf‰¾zfˆÃ¢7ÖãÈJO#+½„¬ô&²Ò;ÈJ#Y:=žíid$æ1u,aê¨bÖX‹¬´™ÚJ;‘•ö!+BVò·u{«ü¼ÕºCy»}²R0-Jµ ¥?ùÑ=´d¥ãŒÀëE¦#™âô[;çå&<Š >6dçU }ëÅ#ÓÍò#ùt$›‘< ·€en!Ť/ëvœù7¿B.ۨ䶍JQ¶Q‰";è"²‰eúkX°¿œüÛB¸} 4è} Ùï@Õõ6½ëWVVÞ__Ÿônº—ô „Ò-€Ò €Òu€Òµå¢Æne €Ò5ÅT•+Zê‘ ieÁ\ÚéÃiÚ}Ze=C ¿—’̝ºã&¥‘LO㑕¦1ÌeþX̍v²Òd¥Íغw +íCVòÏ¿A‘N“C‡³mÝǞ;NP +%+…Z W3-ýÃçì·iÉ'0ý@Ë×ï¡% ™¢õñ¿â|íå&<ù Pd‘Q´O=ªŽG?R͌äM¸ý”bRX½®F£’Ó• (•Ü¶Q‰ÒŽ{£m£RŒmTâ÷WÀ9ƒTÙx’f#P…Þ&‘ö* ô (ôPt_•®g¸’Ç.áÙó¥?J§J-ã'Juc££RŒ×¨”aŒJ(éXܺtã ¥·”ô_·Ë J.§7JPŠ P2 ¤«" +ò%]œ I(é‰ ®Z(é½%$ðêbTjÌî[âè>G÷ï¹öÏ·ÝW;ºÑÒÑ=vìØqÁíqÚÌäsÛ¨äqtcT"ÿöWG@þÍ3÷0X]>}kÈh)lîÓD˜ endstream endobj 89 0 obj <>stream +Á$á ¥]iš¶¦#ÂdêõÃ,Ý}.Ï9pàÀ¢<Áܜ|ÝÍN+T¸_D±˜š5”jP¦ûj™>Õóå+V¬è[géÒ¥Õâ@• ZåYYàVà•®þ8Í×û!+½@ãב•aœβ 1ÜmOán{v´Žy!²Òr2âÚ؈¬´Yi²Rµü(é—ãüÙù·Ÿxý[-’p!iÉY=÷`É´¼ LQÞÄÜwÖ`¸É7€B~Ùdd’kÕ𨺄:×vì ·Ÿ”Bå߬BN»¢’1*¹l£ d•¢l£R´×¨´Ú•¥€ÒÌ8cTÒó= كI¤½(=õŠ`¸Fºá*þÛPjÇKΔN”ZJMâ0*Åz݅1aŒJ Q^PŠeˆ†‘j%g”" þÓ@É”t]PŠ·@IC +´”ÎK²‘Ÿò¹ˆ=Žní¯!F%ãènc·Çõ8º/×fµÇ½…y6¿®oµhfdTRèÛ®ôd°Q YéoŽ0 Š–B%á¾õ%áì$\²æ€½)$á҄›Óuë2YWe+².ÍÑá-ÈÓD0;_‡;¥Pául=@‹Ìß)ÑðV©Bý+eúhϕ)Ú>U.ºy´\÷A:¼õ,ûÜU& +ꁏûV@éf@é&@éÆ"þUÈcù<›UåÀWÈJ=3a®tÑ×£iâ°§h•õ<²Ò«,)€¬4Yi²ÒDf«™ÜmW +-eþXŬ±Yi+²Ò.d¥®cÍ¿ý+0ÿöÒ Ӓù øh)™ÜÈÄMžÁKA¾á{kð¾ä‡Pxdv¸®­Fò&Üþ'DÂ-”˜tb'ö8Jœ˨„½Ë2*ÑúÍgTŠ6F%aÊZ¾Æ¨´ZŸ ·OF( xÞ$ÿöô$<ô dtŒtÃÕü÷2†öñzÉ9ñº¢~_gŒJºÔÄRzÒ•lPÊ⎠z2²R"ù·xd%PÒÝ.=Q{P¢ì[”" þ3@É EÁC”b¹fâý@I—P/ÎãmEäßʹ„pu7èäqt·mÛÖÓõí2Ž2T3“'´…4*™Ò“AF¥ Ò“&ÿfŒJa**ùŒJ!AÉé%}´Ú²dwÐ% ghéH‚„KGìIAzIÓó¦tʚLEà•Yºs­ÌQhžŸ§ð:3_‡<©@Á˜"ÅØáŊèƒKôÞ,UйT8ólÙ²e˞,â£J@ÉcT¢•mTڃQiű7`Túg) 4Ÿát@iˆ3£Ò@°çèi@é ¨'xtÃu ¶£P:×ý´:%ÎvtÇÚF¥ãè¦Gn´Ï¨¤+ÔcTÒ¯=Î% Ñ Q~ ¤× +”h)¥(E†ÿPÒõá%].1 qŽ¼¼¼þ•ÄÊ³Uù·®ävå1*éªÁ¨t$ȨÔO›ãemá+*™ü›`b¥C±sÝ1 +°ŒJ”˜ÏÿœÜ¢¥–%›–¾…–¾Šƒâa†Dè! Á%é%U¸¶ZZŸ¡üa&Б~ä"¹¬ïÉ×l0¾@qüýBEôw‹à+Þ¿^\UUõbɲe˞.©¬¬ìS²hÑ¢Gèð֋2“=© p7>î;a¤0Òí €R@éŽ\^’Í‹³x²Rïtv…¬ôt +»GVzÚÇo³¸h²Òh“õ@VšÅ¼µ€IdwÛ +­GVÚJµ€ÝVþMtx80ÿö²Òvþ­Z¡€Ÿ>ÿvb´d§ãœ^Z +…Lÿð£žüØ'ì`^ð¶„Ä£0Œô?µf¤Ÿ”ŽjTú{H£•,£’@éåè6F%¯£{5d¾Ì•b½Žî $ÍFJƒ¥× gmG÷ý =`¤î¶£ûR@é‚xÛÑg;º¥z•JblGw´~ãþ ¤º”4ĸ (é_Q.¤›o”\>Prâ’ô%›D@)J‘á·JŽ ¤«ÑJº$= $Fò€’J)tÁí]\QQÑ«Xt t t tgÁìÙ³ï”îÌã±\žÍ-õÌ♼7½¤±?d¥è.ú²Ò@d¥¡¤9Fq?ÑLTÌ$ó1qTâv]…¬´Yi ²Ò.òoû‘•>&ÿv„üۗäß¾u£ þBÇIKµA&ûgš›‚@(bøçQð¨zš­V¹¶—‘NĨôg˨äute@ÉmŒJú í§¿ÚNݛù…­Á¨´PZÈïo 4 PzÎy‡üÛ€Òsñ^Gw/†;a¤}Žn@©/9Û8º¥“‚ݔž4F¥hãèƨå5*%¸E”bü@É”œG%WF@)J‘áß”ÌÏ»:(9k¥XGnnn;(ábªËžq·àOšBgZ….âM¡€ÚæßÂê6ù·šëOzåþÑn”ë%#+‘1²’#(ÒR oÒNA–%hé`"ÒK’pmg +y«TÝ¥®OSÜý0]¡yy& ’¥˜=7'Gw½rwGåiJ–¯àûvhðÍ}җ *++Ÿ+„s +‹ûJP=é¡ñÐdÝî”î”î”îÏÑð@–ž}(“gð¶ôE‹õMeW)Úé+ÉÚý[´fÌì¬ÇË}üî»g3“,`&YFväCòoÈ¿m#ÿ¶›üÛd¥ÃŸ‘ûŠü›”˜*q£Rmi)$29|È–›Ê7TC¡êU{y%Yû{3I{DÇÑaäßL=ä‰Ü|Ï`:™Ç¼µ„™¤Š¹l-ù·ÍäßvÛGþíF¥OYÿöù·o•þÈ,Y³£û—¥Ú +LÕ¸é¨ðtŒÃÿšµ~Mx”‚ݎ°Žn»F·Ë®Ñm9ºõóñ8ºõ“Úm×莱ktێîQqvnØçy(è »F·oé›qtwb¸ÐZú¦«çtøê$ÛÑ]ßvt"˜æòóö8ºõǓý@IC,C4bR5PÒ| ä<6PB2€R”"ÿ;( vª’ (<Šñ% I<‘ÂKÒyq—U—UûóäßtEyòo:ßú· ú“7„¬?Y½ÿÛX?[·fû%¶­{ÝQlÝ5ÉJÿ”•þågصi)¨‚·‡–PSŒe)ÏN¬&‡Ïã0<Çûí·„kû¿ø⋝I:¨-Éä²RÉ9¤éh—§+/ÊPž›©`>=kÓ¦M³Ñx²ô‡çh"œ³bŊþ¹K—.}-wñâÅ/æ.\¸ðYš»õ£pғè#=Îð ô ô8 ôD†^Ò7]/~&Mo{Á€ù·7“´ÓAteFK­Q®1÷ñә¨æqß½˜Eّ5äß6Ù ´P:HþíS—”¾ö¥êF¥_jéۏL¡áéX‡Úÿ¡_ú¼ÍÑ]”jáè>ªF·åèƹÇïoŠµôMׂYúö ô"ô”½ôínéf†n V3žõkfoš™h/ âlGw¬”²øy{@IG-Å(9# ¥ÈðÛ%óãJyyyn®PÒuËϐÈcFVJãř\Ĺ\΅ÈJ¥ì¹mRšÐÿ­%×þ©DßshçÓÿíbŽ¾ ýß®åãß¾ÿ[-Ê*…²u×\­[qPÒËã6 $Œr»th.—Þ”(Z‚Ð}Œ Ô½{÷(E@)2ü[‚’“«ÑJn@)ŠK(Ú%]¡qü+ÁÈJ©ÈJ\[Ù\[ùìª[w®ó†üµæôk­û ú¿µÅÖíéÿv5ŸæF>ëÚ½´ÕÆÖ­ÉžŸ­ÛTë6¶î j݊ş…«\­Û—ó%³:¨rsÍ´„ûZ:-}¯â@ëÆ?ûì³íItQOÆ¡‘‚(U÷«•i +áé”YŠíS3‹Çg)迟¥94°Éq²—,Yò½o_¢¯Ûó”â~&™Ô× 0Rß ý¥g¥çÓô◥×RtæúcTŒQi8ù·Q•&’3«Žæ2x@IÇç%ÞvŒJ{0*}„QÉ”H´üöÎ;Ωjëß9é=™Þ‡†¢""*‚ »`Çk/Ø®½‹Š½¡ØQ”* +"½w¤w¡÷^­×ÛÞ÷÷[Ï>IN’I†ëû¾gþXf’œœÎÚyöw}÷ڇ JF>øßá¦ÿ÷§AÄC¥*݀’á莀 +dléÛ*Gté›êÑ­ݕ–¾-Z´(n3ïÁ73áÑ }éôߐ›º> T ›x‰K-}ÃÑJrû•aÐQݺȏeˆü$wë>Ôn?¥ìPûWuh)¶1[¥þ‚¬¤hi¿ƒ¥`áv©"œ‹B•o——d>֒ù©>älgð¦„d–}d† ÈC2d>=0S¾!úfɇì•5mÚ´îY“'OÖi)[°ç}6À}—=KÞ¦qR{Öº½™ í3äoo…åÑw¥€R'@© ŽîOqtÎ7N”äÝ(ÔAI.äT¦Ü³(ÉÕ¬À¨´£’JÊ°‹Qi/õ7”´£”Ž©P%(¥stWZúut'/}s›™HŒuG73ùŠ–ñ½àœOè`ñ>·h;(èyÐþ nÛû`¤Ö„ëùõ +¸ˆ§œÍ“› “*P:æ*G¦*u³ô PʍRˆ{Ü-ђüê°Év«œ•JÖ ¤%㓠J&(™áH%u£WJØc¥®fÕAIòÒN29Š–Ü/øI°O΄¯r• +H°ÝÖ]¯^½ˆ­»1;Í)[wsùI¶u·fàP¶îÇäÇò¬üX^“Ý֝ԭ;¡[Àx‹|ÛO‹ÉJ‹tYIu ¨¼ \ê&”•»ÄÉJ–4]šãŠpÖXΖP„S´dX–¶ºaÜØ4<Ø4¼ô“ñ Ì-ò˙ΠȨ<#(£÷ä|‚±aJ`a\C2*̔á¿O¦ Í=³¦NÚ=KÆ珳&L˜Ð™½o?`»’´â~—en塚 ïJBTƒòä΀ÒǀRw@©_1}™®”†è $_ ñ $çW]P:¥¤¥o’fJf8äT.¬îÒ·„ÍLv%nf²ÆØÌÄÛÌPçfé5”ÔrLÕA¾#ìó& -^€‡žä¶}Fºƒp¿^Éó”s¸ŸO”±MÏñt¿P Tƒ#¢ZåRèË¢þ¦@)`€’=(ÉY)P²¦%¦o&(™ d†c”${âA); .‚‡¿ùx4¨ËJ’eÙdY‡ŠØºëÔ©SλU²u_ ?ɶÊ֝ԭ;©[ÀWèÛF·€4›ÀfÊ$ËJÑ=J«AK¿ÅÑR¬ç çdy˜*¹¨>¸ù®ð°úÇ+ßK}x€ü2>ÏàMʨ<1$£ò˜|W ˧œä“!_}2§OŸÞ3sʔ)Ý3僒)´ô[ºub»’Ž´â~ŸZ[`¤÷“>”> Ž?¾K@@éS@© ô_1ýøbùPúŽ*Å(@i‚JrBP’ Y ”öíۗ”°ªT Jº¥ofHª¥Ç,}i—¾íK\ú¦ïúæˆ-}sƖ¾¹ØfÐ-wÝpp揀Mo/Kߥ؝°=ô<ԆÛöAV#ÜI¸‘_¯"\£Íi¥ÚP:P:Pªx•qä"T«¼(…‘•" $ÁMpé $T%9” J&(™áØ%•(iq $ydƒŒìê"¸ùÕË£DY)7&+•røZt ¨ÇûžH·€S»u·ˆëÖ­º¨nÝIÝޓŸôÝÔ&pJVR›ÀBÊÞ-à_)e¥$ZJ²,ñ5a‹á¨"œƒ"œë³Q„sãÕðy¬ðnÞ¼y‰ONt¾KP`åʕӂò &úF‡dh–ïŠÁaþ¿Ê T–”!´ôY†`O× ¡¥Ù©¤3]¸?¤qR§p4|#u¦êÖ%(Ïë +(u÷Ëk{úä(½ùv( ”†J£uP’/‡i€Òì(ý@î•,}[ËÒ7”Ž•ÊÑýïCYú¶G÷vcé›Cî¡ +ÝKœôËPKߥ €ÒϲeËJ}¥îÀ·>“· —Ù~çiZË?D¸ Pº‰µ"´àÑsy^3Ъ1Õ€£ÔU ä‘Œ*¦þ¦ƒ¶¨(­Y³Æ-y(ÙåW”lò”(Ék# $G6AÉ%3[ ¤" (Yã@I’S’S% ^ðÇd¥Œ˜¬”¬TŒ¬TÆÕÑ»D»uŸÎ p¶Þ-ÀèÖ}+Su xD~’»$mgÈJcèb’¦ eM(«/+%t H®¿¥ ¥&ÓR´gÐҏvU„cõS«“„^„Ãíf ‡"œWÎq±Odž_é™~ôœ^¡ |aŒ +.X°`hH¾+…eRýUXé>ah)Œ4-uƒ–ºÒ€ûcšKvQ! #&u”ºdlÿPúÂ7}úô¾8`R×øP(”&¡(©7s¥… +”ìQPZg3@I.dõAÉØÃÃ¥#'æÒ·Ÿ0*íOZú(­wÄzJó]ìúæ’û~¢[²v$ 4Pêë•Ûñ3=¥wüô…žŠ&Ü (ÝÌ¿®!´äÑóxÞ€Ò)>J’=u9TÍ(åSãËÖAiÕªU§% ©(É´E%k(i‹o5”LP2ñJ’$iAÉFrÚÉ-'AÉJ‚/&+…yYVLV*Ôe¥òòòÚ¤}}œä épj\·€–-[¦î´ œ’•ºÈ.+õëׯ¯eðàÁFÊñ4¡ü’•b ”Ž–ª°,áÕ°S‚PE8hi‡“%@á6BKkݬ%ó°üÞ»qãÆE>»¹~½¿÷Ë`>%€a( ÓáQA$Ÿ|¾A!h)$#u_héË0úPXè³0ÈD_ÉOi …G„î:# Zõ¢ádÜ¥oXN=PGi 4Pš¥E€Ò2@iU*P²š tt‡C¥ØÒ7›%f v”XÓà U ´Pš (M”Fy$s¿õ +—ôƒnzø„s>”Þ€^õËÍß6 ·í£!£¿ä.¾…ý…p)œÏSÎôÓ#P:‘ÔãPµ¼B_%”äÏÀäF×AÉ%§M¨”d¸‰€ K҃£— J&(™áh%K(eggk¤¤%+yi#­(9b´/+ÉóB1Y)‡ÄŽÈJ’j5y·ºUv ¨´ œ’•ž‘6‹oBÙ­[7Մò‹XÊJ²’ Œ©e%A’m±½Möbë> Y)=-ŊpÖE8{¬ç -mq±W(²Ò7öŽi/‹Ì|k×®ã“³Ÿá—Azr@>˸€ õ#-e¤D ‚–ú…¨¡…‰Br z†à!<Û=bás©'Τ/“úPuëOÕm «„³{{FŒ”Ƴêm + 4“oy€Òb@i¹Jò%·PÚ (mW¥7@i_ܪ7”Ž²pH=ÐTAIï`—ÉÉV;.=@iµ“N¹å¸ä–Ÿé–[~²[àd4 4Pêï“Ûñs8§‹_ˆç=Ø絀ܱÏÂCAF÷n%\K¸Œ.à)g)Pâe 9@}ŸJ2(à=r܉ Dˆ€’üËiW $O±ÙäÉ6”¬&(™ d”@I((”$9'ÁÅß"²’P ( ånÿ +°éÅÝþ wûûÜíí‚@ÏÇ@龐„Ö„ëWðÀEAš)ñ¼&€ÒI¹½ó+P’ì)E«*ðÊd Ç#o” (… P"¸ò«Ó.8ì +”äÉ6›Jrd”LP2ƒ JI $e%/m$˜JN‚›<¥B@)W%y·%??´äå¾×AÉ¡@IžbOJV”LP2Ã1 J’.Uƒ’T³œº¬$ÁãJV +T)+ÕBVªWeÊ+A®c,‰ÈJ=öØ£4¡|†½M^±¼óÎ;Y©{÷îñ²Ò°aÒd¥ïãd%ú*hB/+ œìL!+ý¢ï— +ý#­¬”¶Ë’–X„³ÆŠp:-Q„³G‹pÛH4NùþØà’S[ãš«p³Ò̍•ÚƒWÈK1Ì»|ùòé&CK((ŒaYÐH?ÒnW…LC@&ÅMßúŒÀÔچŒDK¿±ˆIé‡î +|ÜkXð¶Aù¸¥íú‚7ù{Ùëí{½)PúUo§s¨ ôÏf¨"¤%Bl‚?7P ÄJ[ԛ%¹Ñ79£ T¥¹€Òt¯ÜããYÄ0œE _³ˆáË %¹Y?{ڇ£ Ô†¬ÐXì „«øÛ%<ڜ睖[þä T $‡ª}¢Ìæú%„Úi凖¼.Jò/§C*Jòd›MRÍj“,‹€Ò´iÓ4m„ q ¤™ d‚’Ž9P’ÒHÉ(InYɲ(y½^Áɯ†¬äK!+åÆÉJ M(Є2"+É9Gd¥«®ºêJšP^Ç5¸½Mî¥ eDVzíµ×^ao“·ØÛ¤{›|ÊÞ&_°·ÉWìmò{›ŒfËÜIìmò={›Ìco“%‰²ÒFd¥­1Yi²Ò~]V’¯üêËJFÅC-ÂýȊ ½‡c³í­Ì¶7ñ%²žeA«]¸¨]1Zr˔[ÑÒlì¨ßCKSYË3™åÏh­7Ž¶1céÒ7†v{£ÃüHcéU<FšÇHr¼™|CÌELZ'&ɬž´N¯ºÉùmÕíIòÅ·PÚ(ý(é Þb T骙 tĆô͔ҁүɠÄ.рÒf@i¶¼ +V{.aµg(ù£ ô  ÔPê’›º}WÛÓ¥þ¥Œ((=˜)xt'áFÂU™€4Ï =·%^v¨Ã¡jä–/òGA)K%¢€JtPBXu8ä)Õ¥þýûG@éã?6AÉ%3 ¤Ò (YAI‹’<²’hÉÍSª!+•¥ØÛä4}o9ûˆ¬$°{›Dd¥‡~8"+½ôÒKϳ·I;ö6y½Mº°"7"+ 2d­rG°·Éxö6Q²Òld¥…ìm²Œ½M"²’ қuYIe7M(#²’Œí?JY)II’• P2¾5Òá~OU„³E‹pñ´D} ZZç”)w„–wb´4Ÿa}.‹™4†™N/½©ž(2MTÜ©0>ö¯ …G2èO†‘¦ÂH3`¤Y4•™‹˜´1i1kݖ9bbö¤õTÝ6cOږž¤@)bOR µ'¥¥ÿ6Aéˆ +‡JQýÔ¥=Üã;tP’{( ”æÑc:m1&ÐDlDP +ÊÝه|º‡¥ Éä·(±ùáS@ÑCì}'á&ÂÕYò·‹_Y)-y¡%7Sùáp*P’'G@IPí  ¤™ d‚’Ž1P²Ä’$X”$߬:(IúE@IB%YIQÉJá8YÉØ2·¼¼¼ãA¼¬tæ™g6¥ esšP^LÊ+hBy×å6ö6¹‡&”Ð„ò† —ŒÚ³·É4¡ìJÊ^4¡@·€!4¡Eʉìm2Yi.M(#+-§ ¥’•6 +mÁÖ½[÷êoJVúQ—•PI•þ–^VJ¥êђnYbmPœe‰Þ|{(Âí¤åÌv,KI´´ZZɾëËÙüá—|»èȄub%1ÞÏÕyHõ« +ò”ùº„$bµ¶%ºŽ$—d·Uq7yóMʙ”BLŠ¬uKªºª=É¥#$TJQý´ +P’´Š€’ÜHëSR@@}bPîɑ!¹O‡…êûf,Y²ä³L@) PÊìy%PÊ`y8PÊ”­-€§óx´Y6 Ä+ðÚº¥,P +ÉAó¨ìeQã û£ äK%9ƒ8P²› d‚’LPª(i:(IæÙbÁNP´äªŽ¬TRR/+5hÐàxºœDÊÓèpM(ϧ[@K>o+.ÄM\Ä;iBùM(Ÿ [Às4¡|nï҄ò#º|F·€>t ø†nÃè0–nSè0‹n hB¹”&”+±u¯ÃÖ½ Yiõ·]Ôß Yé'd¥_¥ß, ½þQ Yɒ¦§o‹(½ùTî@*Z²Gii´´žíD×BK«Ø*«Â)t³Ü™€L‹Ù‹}a!ð üª“OQxäT’¼v9:R…®#É÷ÖZ +në퐛“¶ &mGLڕ,&!¼ébR”â«n†ŸË¥£ ”¬I $w„Ú¿' ”¶$’On¸ù~¹ÿ¾7@) (eJ™€R– Nçl@)PÊ”r¥<¢»ón&´"´äoçñh3€ª1¯hÀkëfÉP–!ÄS”B +”ä=tPBVòAKn¬É äH¥©S§jÖñãÇ[¬&(™ d”ô”LJÖdP’àÔiIÉJ’†[©’¬TVVV¢ËJrBõp¦9ñ¦t hÎǺ˜nWðñ¯å +ÝJ·€¿bë~˜nOÓ-à%lÝíY‘ÛƒÀ'غ{bëîO·€oé0’n°uOÇÖ=‡n‹è°[÷jº¬ÇÖmÈJ»‘•öÅd¥Ÿ-jÿ2%+¥r)W)+YÒÉJZBî¶|ˆÐož‚–¶Úqy³ùúö]琯˜5:2Á91dZ¦ˆ°ŠÑ–9E%¤•åGRµ¶4Œ´1i7bÒ>åL²bRBÕíïZšª› JGzˆ%BJP’ÿýdPr $œ­ƒ’Pò*P’»N¥  ŠR& ”(e ¦tΔr¥<@)PÊ”ò%B+BKþv6ãyyEƒÉýºÙ€R& „L•”‚€²RÀ¯@I‚J”°ùìNyr<(Éá5› J&(™Á¥ƒ€’¦ƒ’ä -&+ÉAՖ¹Ù¤}@gPFÊrNí8ºœÄ9ŸÆG8“Ot>ÝZÒ-àj.ɍغï [ÀýغÇÖýÝ^ÃÖýÝ:cë»7¶î¯±uÅÖ=[÷dºÌÄÖ=ŸnK±uWP[Kým#¶î­ÈJ;‘•ö +픪%+É·ÆaáªAK6Ê]ÐÒ¶ÊÚ-m†–6Æ&™” ¤°Gç¦(<­0‚.IX©*l +Ôka¤uʏ”ÈHÛ(¸í´Ei/bÒþôbRÕU7Ӟtd‡jƒ’-(9% ä6@Iîµ¥~@) ·ã÷AÉƉa@)PÊ”²—.]úY ”+œóv ”?gΜ§ ¥@©P"´"´äoçåJù€Rž<¹An ”²¥LJr䬠Œ²’Ûk€’°T”dÜ0AÉ%3˜ ” +”T2ES2J’t(Yã@IB%Y)Õ"¸üüü\Þ2"+Õ©S§¶îzœdlݍ±u7e9[÷Eغ/çB\Ë¥»[÷ÝغÆÖý¶î-:uz[÷û–/¿üòcËÀ?g¸~غc끭{<¶îiغgS[Hým¶îUغ×Sی­{;¶î]€Ò^êo¥ˆ¬Diø=QVª‚–ŠpÿJQ„‹l¹³,)Z²¦¢%é´¤¦;wn¶G‘)¢2¡ +éÜ…§Õ‰!ò€RÉËmTǃ‘¶ê:’ÁH˜Ü F²¦s&i•»(T!&™ t„…?”6ë $7ðJ_”æ%g„¥Œ5k֌̔ä”%¬Ò7Pʺù0PÊ” +¥B@©R%B«B[w lÝWs™n`¸ÛÙî>lݏ± ܳt-y•™ÜÛÔß>d¸ntëþ’úÛWÔß¾£þ6šMà&± Ü÷ÔßæQ[‚­{õ·5Ôß6PÛJýmõ·=Ôߔ¬ô# dÈJ;tY)±gì$OKH4)hi?´´×F“GUK˜ dڄ*´Q—†T -UPªç©W¨×* I¾¼¶ÁH;Ô{$3Rª‚K 1)]Õí¿ÌªÛѪ¥$’=(yäÞ]獁R Já(eJÙÂ*}rgºçJù€RÏ˅€R«ÞŠ¥b@‰ÐŠÐ‚¿Ë£Í +%¨ªA> „$U–#ÄS” (eÆ@ YI%ÁE@Iþ¦ƒ’ PrJŽT 4bÄ‹Õ¥Ï?ÿÜ%”Ìp ‚’J«hJ ¡%IIª%+Iž‡°ugòn9غ 8êo5±u×ÅÖ}'~2Ÿãt>Ö9Ôß.¤þv×å/ 7·P»›úÛCtënCýíêoí¨¿u [wºu÷ þ֗n݃èÖ=œúÛ8êoS©¿Í¢þ¶€úÛغWbë^Gýmõ·mÔߒd¥Ÿ¥_¥ßb²ÒEKŠ7hé—-ý¨™AKû %]`ÒqÆ@¦¨i ì³E ƒ pƒÇýM=O©GQ<ŠHHx¶9üž¸Z›b$úKŵH,¸DL2«nGvøïdPªlæ>(¹%w(UøåÆ\¢@)¥ ™J#²¥@)PÊ” +„sÞ*”Š„}ž*”J¥@‰p5¡E1 DhV(AU'ÀWuòæϟ_–¥,@)Pby]YÉ«@‰ÞJ.ïÁAÉf‚’ Jf0Aé  e¤(%ÑR´e@¼¬$ RË þ–ÍûæQ+¢þVƒú[9ݺ£þ֐ÁãT†‘3¨¿Gýí®ÆU\¿ë©¿µ¦þv¯å•W^y”úÛ3Ôß^aýÛ[Ôß> þ֕ú[/êo¨¿ ¡þ6ŠúÛDêoÓi«4—¶J‹¨¿-§þ¶šúÛzêo[¨¿mGVڍ¬´/&+ý -U*ÂEAéŸ1PJU„Kkð®DKÑJœ¢¥Ÿc´tÀ-Çí!Ón™ô °²'[4l‘ÑŽD<Ú­ª{¶£ŒdÔڒéo±æ’ê#ü³Úb’ JGXHÞÂDg¤(YӁ’Prʽ»PÚn€’/JA¥¹aI¿é€R ”# ôM®Kï|IÓnJ +¥b!ž—J¥@©TÒùÎR@‰p5¡;‚j +K UP(ˆS'PÊ”r¥l ¬Ì(…¥@”œ +”< +”äɕ@iʔ)•@©_¿~Õ%5Ž› d‚’ŽNP²$‚R*ZªBV +‡Ãâ2r8ƒ…†‡š u9稿5bý[>àÙ¬» q×êÖ¿ÝLýíNÖ¿=Àú·'©¿=Ïú·×©¿½Ëú·Xÿöõ·ÞÔß¾¦þ6”úÛXêo“©¿Í¤þ6ŸõoK¨¿U`ë^Kým#õ·­ÈJ;¥=€Ò~d¥e¥¿é²ßՔ•ªKKñ.ï„rœ.0¥D¦(7Eô¦(AíŒñÐÎØ£»b¯ØcS¶<:`ø‘¬ µ¶xFªÆ2·4b’ JGR¨””=I%Ó@é—(íK¥M^¹×*P +Hª-6@)S@i|¶dãpJy€R T( (µ/”J…}ÚÔ +z° Tƒ½ÞW.!4‡–šÂR'JE€R ”(áyÒA Y)”¡@I‚YÉí7@Iµ»(ɛG@I¯ÙMP2AÉ &((i‡ÃQIVŠº•";ÁIb{Iq?ɤþæ-³¨¿åq.…ÔßJ9ÉÚ¬«Ï¶&'²­É)lkҌÏ{.×à®Ð•¬»ŽÑç6Æ¡{Xÿöۚ{ý'ï·¼óÎ;[:wîü¬¥{÷î¯ÒòúO~HÿÉnôŸü’þ“_Ñò;úOŽ¦ÿä$Ö¿Í`ýÛ\êo‹©¿-§þ¶šúÛêo[¨¿í@Vڍ¬´PR²ÒÏÈJ¿Æd¥ße¥Ã¤¥T.o––JȔ 2ÅsS5B”Œ"êQ â$$Þò :ReF2Ť£,¤öq§%»%´WJ.@É­@iÿþý}’Vk¥åA™“, + (Í”¦JcsV¯^=4¯¢¢b`°ÊEÂ*]‹l:–J¾QCXå…2aŸ'kJß_SxèöZ‚.×®$\ 2AŽèÔ¨P*”Š% +x…xžrs”2³“@I‚; @Iþæð&’š J&(™Á¥Ã%ƒ–*ÉJj'8%+Éñ<Ôß|€RõoaúOfaTÊŨTÈù•bTªÅ¸Q¤«1F¥¦•šsI.âÒ]ŽQéZŒJ·Ð(ànŒJaTjC£€Ùÿí ŒJØÿ­ F¥•úZd¬û†þ“Ãé?9£Òêo³¨¿- þ¶”ú[õ·µÔß6"+mEVډ¬´Yi¿.+É÷‚!+U*ÂU J)hɒDKÑqå¸2ý‡LÑœÁM?ÅØ'mø)ŽŒ <’ðkœ„”´®­2#U¿àfŠIGfHÚæ- (ý=”~v ½:Qa¥nRPÚ(­(-”†·lÙ2+S2oJ¶LVÆä +(}—/)ùU¡K¯bÉÐOJlÞ¯!œÓ®LˆçùšÂ>OÔ +º¯–ðPëڒÎ×՞1cÆüë"hélª ¢ÓI5äÉÇ!D•ão*M%º„²%êoސ J&(™Á¥? ”T"¦¥xY)¡þæ"»Ý€’—÷ðón!F N#›FÝùŒŌeœx9Ÿã8ŒJ'Y.»ì²Ó0*ÉÕ8«Ö£ÒU4ê¾ÁòÒK/µÆ¨t/ºŨÔÖÒ«W¯W0*½…QéŒJ]1*õ¨4£Ò·•F²ÿÛö›N£€9ôŸ\Dýmõ·UÔßÖ#+m”¶J»•öJ•âiIÉJ-%õ[J˜â‘) 7ý’‚  ú9éyÉꑁG‰e¶CёL1騩ªnÿ•èãŽo¡„ÄJÕ-”˜aJ[¼ +”dþ± +Pú!$Y¶ Còmf–€Òä¥Ñy’ˆC +”ú °ô”>.]¸pá{eJ¯×”¬}®–°Ïcµ…î…Œn+—pm¹äôå„ ùÛYÔiˆN'•EA©6þ¦Ò"!žÌá9y’ûI ä1@É%›§JP²™ d‚’LP:4PªDKJVRûæJ†:uP’<÷ñ>Þ-À(f<Èbdȵԯ_¿€ŽJ%tTª…£».•ÐQéd:*NG¥³¹VÒQé26ʽ†ŽJ7ÓQé.¨è¨ô$å>ÏF¹¯³Q:³QnwŒJ½1* ¤QÀPŒJc0*M¦þö=õ·yÔߖP[Aým ²Òêo[¨¿í”v#+EŠpòåð3 ”T„û{µ‹p ´ôoƒ–RLi‘)‰›~‹±OÚð[Ü+¢dT 韇ËH¦˜tƃ-x3|Ü©¼!ÀJ;< +”˜uø”Vwîܹ4$Y6?cóæÍßgÉeRÎÚµkGåI"~[°bŊ~EÂ*=J”>ª!iúnM¥×jIÖ¶­-ìóh¹ Ð=0Ò­uþB¸ Pº€¿ -ŠèÔù©>®¦Z€R –ðÌá9ù@€R0”\Á((Ù ”¬‰ ¤™ d‚’ŽaP2QxÈRPRÛÁÉÊEž»Éx/Žn?ïÄѝÁ eãèÎãL‹pt×ÀÑ]Ž£»>Žî†|èS¸gp™ÎÅÑ} Žî+Œ®ÃÑ}Žî{è¨ôŽî§qt¿„£ûM:*½OG¥é¨ô9F¥~•aTŽQi¦R›Eýmý'—R«@VZKým#²ÒVd¥ÐÒ@i?²Ò‰²ÒááRÑR’À”™’¸é÷ñŒGӒQ¢„¤e¶ªÉ,¸e¡zU·T>î¸oؓ¶ããÞì“Ý@)„£;“SË¡õd­'Kø5ùDuø€ÇÓz²­'›p…Îbเ!¨%ŽîV´ž¼‘Ö“wàè¾G÷㴞|G÷«8ºßÆÑÝ G÷§tTú‚ŽJ0* ¡QÀ(ŒJ©¿M§þ6£Ò"êoː•VQ[¬´Yi; ´ Y)R„“¯‰? w˜ÈT™›â *M¨ôä„ãý3=™Œtl„d1)E›É”>nªn?:“|Ü,xS>î€dԊ ÞðqÏÉdÁ[6òè PÀ‚·":”Р¥·jÑPz +PzFº«®@ÑM„« -çAKͥƀRêtuc TœJa@)”‰ du(uéÒÅ%”Ì`‚R(YtFª +”lÀΡ1PrãèöJ~Î (epjY,}Ë” +YúVÊÒ·Ú,}«ÇÒ·Yú֘á¦)¶9Kß.²´mÛör–¾ý…¥o·X>üðûi=ù­'Ûàè~Ö“ípt¿g™4iÒG8º?ÃÑÝ£Òו†bTC£€É4 +øžúÛ<êoK•VP[ƒ¬´Yi ²R¤' ´Yé@•E¸$ZJ…GtT™â +sQnªO‡âuÈx”–‘LP:‚CuA©ö¤­Þ÷rìI ±'Íƞ4{ÒXìIC±' ĞôU·®€RGªnoÖ¢3@9 Þ“¨+ù{dtC½éÓ§_UWÂ%üÚPj +F ((Õ”ÊjH²Ñd Pʪ(ùªJÇ·X T(=÷Üs&(™ d”„‘*ђщR’¼ÖNš*Prrx ä”|œA€¥o!–¾eJ9œs>=º‹Ù#·Œ¥œÏ{×à$.Ω\É3->úèy€R zt_eyûí·¯gé[k–¾ÝËÒ·G,_}õÕ38º_¶Œ=º=ŽîŽ8º?Á¨ô9•úaT„QiF¥q•¦R›Eým²ÒRêoÈJk‘•6"+m”v"+%á"´-¥퐔ªL ܯ7J0xä$<2éØ •ÿWõÛѨºiQ1éïÖh›É¤~ܺ=‰6“†=iU@2êìI °'ÍĞ4{ÒhìIC¨º  êÖ³wÙ… ;Puk‡˜ôøà&K×®]ïdéÛý,}{œ=rŸµŒ9òUÝoãèîÄÖoŸâèþ£ÒW•†`T…Qi"õ·éÔßæ +-¢þ¶ Yi²Ò:d¥MÈJÛ‹pûS¬„«nóîT T]nªO)0*U"£ÃÄ#“‘Ž–pU7[b÷$£w¬ÍdĞÄÆ%´™œG÷¤TÝ&æ²n¾¤ßàÂå˗÷+~é=é#ªnïRu{ wÛ:J"&ÝÝ +]K¸œp!á,8 P: P:Pª]S§4”2c ä? Pš˜ô0(t7Pts=™í\C¸”p>;YéTêo'JõXúV E©P*”r(½eJÁ(yR’7J.9 M%9r”ÆŽJ}ûöµh=zôøߥ4ÝíLP2ÃLPR d”쀒ƒ7rÆ@Éùøh¦à$ÀR&ƒGÃHŸ­PªÉǯc¹å–[Žçú5²<üðçJgÒLé|š)µ”®¦™Ò €RkzÜ (= +(=ÃÒ·—qt·ÇÑÝG÷'8º?ǨÔ£Ò êo鿍£þ6Yiõ·ùÈJK‘•*•Ö +E¸ВaYJÝ7 Á»jí&>&A&‘ULF:ªBJ1ɒ(&¥ªºÙäæÿ PÚï ê椛½ªºy¨º±¹Û*¿L8–eê±0,“Y™2™’½víÚ1¹«V­š¿bŊ¯ +…P¾(ˆéZC˜¦c™Ð͛¨B/‚=mPŠ…î„Œn$\MhA8—ÐŒGJ ð(Õ”jJŘ¹ó1sg'‚’/J®(Ù%Û!’–J–T ¤¾ P’Ñ,2f› d‚’Ž1P²$‚’ÚN’5”켑PrJnÎÅ (ù9É  ”Áà‘Å0’Çg+¤ëd)¿ TK×PjL×ÉÓÙ÷@éB¶Ç½ŒfJ×ÐLé&zÜI€èðKߞ£G÷k8ºßÁÑÝ G÷§•¾ þ6€úÛ·ÔßFR›@ÿÉiÈJ³‘•"+ý€¬´Y)©W…e)–V„KÅH•©å?!¨´PT-22ñèh Iÿ¿‰ÄmˆIZ”‘~·Ê=þbÒ/6¹ù´KìsHBìvÊDb»[¦›=’3ë|»víªðK- JFÍKn}Ÿ)ӑIÙ21•[QQñm¾¤_ÿBf,´âîB+î÷@œ×çhô8t_]á¡Û ×כ:uꕄ‹ çð·Óë(L€xEºN–q”"@)PÊ”€R@}”<ôQrÑGÉH%k( ¯%ƒ’uØ°aë7ß|J}ô‘…Õ·ÖáZX‘kaÉIä‹@ ë©@IÔ +”êׯo‚’ JÇf8¦AI‹’P²%‚’Prq.@ÉËI2B€R&ÃH6Ÿ-P*æã—Jå\ºãhÏÝP:P:ƒ®“çÒuò¶Ç½‚fJ×J·Zd4û+=bé[–¾½€£»Žî÷0*}„Qé3êo½©¿ dýÛwÔßF#+MBVš[i.²Ò"d%U„[¥áäËasu,KÆV'‡EKÕâ—Œ:¤WTLF:êBš‚ÛÅJºqbR ”þf•{\‰IzÕÍþË/¿ìuHBìtJjlu˔b£g÷îÝk|2ÍXî߶mÛâ dԜð† ¦eÊtd|6+(rW¬XñM¾¤_ŸBá—ÏÀ™Î´Ó~‡ÆÚ¯Òg»-›”},ÚgŸ}V-PºöÚkãAI ×j¤nØ°¡ J&(ÃáØ%ËÁAÉÆÙ% ää\܀’éÙ(¥0&‹}Lr¥>~ —¤&—®. t‚¥M›6hÏÝP: P:Pji‘‘ëjš)Ý@3¥Öô¸—¥o²ôí‹Œz/ãènQé}êoÓQésÖ¿õ¥þö ²Ò0d¥±ÈJS•fR„›--–VP„S–¥ á¶è–¥¤.K•ié÷t´ô‚’IFf8\P2ĤØJÄ-›u1É“~BLÚoGLrHBìpIjlqïÙ³g½G&«|’=?$éè–Üš’¹zõê±Ù21š+„20_Òï‹B™±|ʶl” +Ý´gwۗj +öLJ6CK¾qIJ¹jµÙǤ t" Ô˜Ö%M1œC{î ¥Ë,½{÷¾†fJ7±=îìúöKßgéÛ³8º_Ũô6õ·NÔߺR녬ÔYi0n¥ÈJã¡¥©Ð’²,-H´,Å÷ 0º,E·:Q´ô3´ôë@K&™áš‘RˆI±ž]‘šéé®Ä$vüÙ&wûi¯]Ò`—Cb›KRc“[’d­‡¦}’=Kl”Œš¦·k¦dÙ¨ìå˗K ¬?{Õ~^(‰Ø¥XÀ¦C©äe»;Ï×8y¢–PÐýµ…‡n/2º¡Ž°ÊU„KÍëÈߚ–Ë£kËóԒWԅ¯jÖÒ*.•¹P~ñܹs³9|F¾°OPòe +y2åÍ] +”‚€R\ %yŠ%M’P²Ëa±Ë,Ëb“ùV<(É cѺwïJ¯¾újjPRCx(zê©ñ ¤Æ璒’xPR£² Jf8Šƒ J©@ÉÆ[Úi©æà\œ€’ PòJ>Î>À‡ 1 dòQs¥|.I1W­ P*g÷ãhÛÿä©èÞgОû\Ús_B×É+h¦t-͔n¥GÀÝ,}{GwŒJϳGîëÔßÞeý[gd¥îÈJ_"+}Å"¸!áFAK)ÂM§7G·,ÉWÂÐÒJ½o€ÐÒ¦ä­NŒá Z¢r‘HKÿ<8-™°c†ÿYFúïDFªBL’›Zí©ü“Mæûírßïq8p`‡sß¾}[\ÂHÜ2¥XíÙ¶mÛ2ŸdÏ€äÑì …%·ÆeJ– ÇJý ÔÒ;Á‚Ý %?,$y»DòòÕBýôS‹Ö©S' ýÜ,4,±°"×’“ÈP¯@IÆ°ÈÀ}þùçǃ’¤ëÕ«JùùùÕ¥è~å&(™áˆ &( ¤Å@ɚ Jµk×vJ.@ÉÍÙ{Fü (A>j†¥U«VـR¬P*”j³·¶€€RcÚs7¥=÷9t¼—±ôíÝ7áè¾£ÒýÔߣQ@[Ö¿½‚¬ô²RGº|-õ„–úQ„- ‡–Æê}ä‹`¦ÞeIhi ´´‚5q«õáä«c3´´ZÚ-íE`Ú2ý2ý-ý£¥¿§ ¥JËù«¦¥ÿgêHføÉ“ToRµ½M”‘~gc刘$÷óOV¹½÷ÛäFßcFÚᐠØâFÚà’‰Äj·$ÉrϦM›ù${æø%¦…‘ƳD† É ,É·¾9’y=ò„‘>*y·PRòõbA’çJ„}¯!iz_™ÀÉí5Ǎw=áÊZ.!4'4­)6†¥”É+ê֐×Ö,•£Ë4(¿P²;ËƂ9Â>~Þכ!´ä 9ƒ~ vŸ„¸KâìIƂ7zMZcÛ¼iýû÷·h2ÈX´®]»Z´Ž;Zèçf¡a‰……&œ”‘Q^ æ2†Y,-[¶´°ã·…½¿-ìJ5k֌¥ìììÔ£r*1É%3©á˜%K2(…B¡$P²a\´J¤g'"´›Y–PòJ†–Ÿ<“«‘õʷÜÿýÅ´))cyI9¶€ã˜Î5¤=÷©4SjF€sYúv1Žî+0*]‹QéêowQ{Yé d¥çp+½†[éÁu¢÷)E8eY-©¾# ¥ñÐÒTh)~«™OW@Kk˜6@K[˜’hé@ +Zúý?§¥ÿûï_3üùCU·d1ɒ(&irÛFÄ$¹ŸXåÎÞk“iÁ.»0Ò6‡dÀ&‡0Ò:—¤ÆJ·$ÉRäÌ|¯dÏL¿Ì:&eþ1&$Œ44CXe`–€È9´ÈÏFú _èæ­BIɗ‹„xž.ž0aÂÃ¥Â%­1vìØ[kÈôæ/e.'\XSÂÙeò@“2yJ£’ÎÇCUåðU H«¨húôéyÐWV¾ÀN8wΜ9lyK_¦ä¹‡3p…Šœ v¿›—à‘Ü†˜¤ªn†=ÉXð¦Z(M¹?þøc ÍI,,*±°ׂ҂A 2ÀË/2z·hÑ"Jj¤nܸ±…ýÀ#ã³%54› d‚Ò±Ž!P2h)”ÔQ PÒXá@ɚJv@É(¹%7ó-/ŠŸ¡%È'[n¸á†,.S.ín X}[‚k²&jw]¦s'0^5¢™Òi8ºÏÄÑ}F¥lfr­'¯§þv²Ò_‘•FVz +·Ò áÚAKïAK˒Œò_BK_Q‰‚oi.ï ¬‰›F9n6帅”ã~ÐiI¾:ÖBK˜¶BK;˜vCKûBK|=œ–LP2Ã!3Ru nÿÒoÂD1I“ÛöéGi¿Uîì=6™ì° #m±Ë|aƒCraµSi¹[’d‘gíÚµs¼’=ÓýÂH¨o ¡ Î`é—)Œôy¶L—\ÉÁy“'OnW )ù|¡`ÏE’¡=úŽ™ÙÜX*áê#GŽlI8¯†üzF yôTêÄRyrýyYíb9@i‘ª `êÔ©¹ùBK™pX(Gh)%ìãåÍÝaA!WP’Ýá—`÷I°y#É£VΤ81ɨºö¤¤oª3€ê5©öÃ}þùç-¨ÝtïÈØ.#—ÅrÕUWEÆl5\ t 'DÆç²²²ÈМ——w8 d ¾&(™áˆ Ç8(©\U $Ç3@IÓAIÞÜ +(Ù8«(Éé:‘£]€’‡å”ü 2AËõ×_ŸA“Ûl®n‹JŠ0”¢v×f:W Xúv2ŽîÓ1*Íf&P»”F­•nDVº·Ò½t x”EpÏ@K˒ÐÒûÐR*q= ¥>4ïþšž”C˜F#0MB`šÀ4iÓ2¦•ÐÒ:¦M:-±tZڃÀ´dúZúZúÕ¤%3ü‡ƒ2R\Á;ñ–(#ý FúU‹ÜXåVÞk•yÀ.›L ¶ÁH›ìró¯uÈÌ¡Â)Œ´Ô%I2ß³jÕª™^ɞɬ%FFú2S¤[–àL§œI“&½;a„Wò…xž) ‹G¡dè=E2©¹­xøðáוH¸‚pQ©„sMKäѓÁ¨ªºÅòښE’ÓÅàV~¾$vvž>#GÞ(˜-s!¦¤¸7,´äIž;r.¿»W‚Í#¹åQ«K1Î$‡ Ò=Iµ™TU7™oY¬ ˆØ“ ·Ñ@µPJÚ½DF.‹åÊ+¯´X.¾øb‹¥yóæKÓ¦M#ƒ´¥:uêD@©¨¨(JjT‡Ã‘QYO(%1’ Jf8ƒ J‘£$RNNN”JJJ(Ù¨ÑÛ9] ääs¸ùX>¥A&À…q…2¹ˆ9x%ó1Ó# Œé\9KߎÃÑݐ]ßNa3“fÔߚÓ(à"d¥Ë±u_ƒ[éfºÜIî~héqh©-´ô +´ô–eÑ¢Eñ-}‚ËûszRö¥÷ Ó0¦±L“˜¾G`š‹À´iÓ*¦u Ó&¦mÐÒN&EKûuZ¢š£¥¿%ÒÒ?MZ2êQp‹îš¬ܸÿnQŒDÁ FúYFúFÚ#í¶ÊM½Ã&÷øi½]nþÕ™9,wJV,rI’Ìq¯X±bºW²g‚Oòh$H28( Ö/$èòy†0ÈǙ ²…nÞȑl|!O°§M¾ÐȃÆ »«P&57}÷Ýw­—K8Ÿpf±ˆ÷q«oFg£)·±ÍÛ9çœcaKK [DÆçòòòÈМ +”Òî‡k‚’Žü`‚’J–DPÒb d¥2oãüìTëíÈÑæ[.f^n†/ÚOǶ HÂ\¿,,¹ô(ÀÑ]‚Q©&ãUv};žúÛIÔßN¥QÀÈJçÒ¨ûÜJWÐ-àZŠp·@Kwë–%OŸ¤÷}»_Ó»,ÉLXmuҁ©Si0Óp¦qLS˜f"0ÍC`ZŒÀ´i5Ózhi³NKˆÐ†Ø8ZâKI}=é´¤¦õ‡EK†og3üÂ!˜’ 1éïJLâvü FúEªÿIS7¹÷ÀH;­ÂH[m2#Øh—»}­]nþ +‡0ÒR§dÅ|—0ÒL·0ÒdÜÑc|ÂHCý ÂH_†$Õº……d>Ì7nÜÛY‚8¯f µÍöy,O’óÞü!C†´.IÍõƒ¾²PÂńæ„f…ò@ãByJƒByr=¨ª|Uiä +såäȑ3³%±C™;~°Ìöqå \A!‡OòÜî•`óÜò7«‹Z›FrÈË4»ê€3IßÜM‰Ij­›êž¤ªnj‡·:Äۓ”;iÁ[ªJÆî%j›7” + ãGe”þ _åf0Aé%R’Yã=4jïvEÓP dåülˆÐvNÜÁ|ËÉ>&.> ‡AÆËúZ?×%ÈUËÀѝÆ‡Q©é\)»¾ÕÂ/P—ŽJ'°þ­²RuŸ…[é|º´ w´±,ɘøW*qã[R]–^@`zé]©3S7Ú|2 ÀÁô-5¹‘ Óxi*Ó,¦ùLK˜V 0­F`ڀÀ´™rÜvhiÓÞ-ý-ýGKêÛ*–þ•HKÿeҒ҆ꙒRܸ ÿfQ7a¤Ÿa¤šÜ±û¬rïî² +øo·ÊM½Ù&Œ´Þ&wû*»0Ò2‡¤ÁB§dÅl—0Ò46OAk„Wòh°O&!ýÂHŸ%Õ>IÒuÈ°y#Sä…,!ž6Ù"å 4è®\™Ïܜ÷õ×__“?pàÀËH8‹Ð¤@h”/Ï;>_2¹Nž SYž¤sQ®*/Gr:;[è+#SÞ#˜!ïæ Oš4É”ìv™œ~Iq‡O‚Ý#gesË¿¬.yÀê”óÓòdÍ>~üxÍ®IÜbÎ$«!&©¦IU7µ®aO2|ÜƂ·¤Îi›r«QÙhÊm‚’Žâp¬R’¬däjBšV¥²²2+5zgjCŽ¶³‰ƒOädææózn|\’×*Ä%Τ©[“¸|êoEtTªAß·Ú¬«ÏŽ&'âVjL·€Ó)MîBh)bY’‘ðF*q·ã[º—íàE`zé%é Æu™>¢&×dê 2 ¤&7d2M &7šÜliÓR¦ +¦5L˜¶ 0mG`2héå8ƒ–~3iÉ ‡Ÿ‘ô‚›b$K”‘~„‘ökÂH{4¹wwXå.Þj•)Àimýúõ+ìÂHKóœ2‡øÞ%ù1 côh0Òw^É£¯|‚)_ú%Áº$Õ:…$éÞKú½š!xÔ6S°ç±,‘{³e*Ó:gÀ€×çöïßÿÊ\á’Kò$œKh–';%O=1OžW/W2¹TUš#é\˜-Ȕ›5lØ°ÌL9| „åÝ|¡qãÆy‚L.ÿĉ>Iq»WNÈæ&¸äW«S°:ä)šCž¬ÙiÀ­ɦ‰enVÕ@u˜4Ä$µÖM5Hªº©á_ٓÒú¸“:¤ê5™v÷’´Œd‚’ŽÀ`‚R|®ª#‡ÃawÓ¨ÂkÔã5NȊôlE„¶!Gۙoٙy9XúæÂÑíf¸ñr5|\¦W2Lý-“I\&ÊÚâ#+•!+•ãV:Žn )‚·;bY’ö" ޗS‰»ßÒM¸¼ï@`ºdz dj 2½ 2µ™Þ™º€L=@¦> Ó× Ów Óhi"6¦éLs¨É-¤&÷SÓZhicŒ–v@K»uZb➎–þnҒªªf¤$SReFÒ nœ¿ï?irc*FÚ«íÙ³g§&÷î6i“U¦ë`¤•6™ü`FZàFšå„˜êF‡ßg¸[gGò¨¯Wð£‡Oð£K@R­CP’¤ß aÁ£6Â>f + +ݕէOŸ›³Ù}([ä² Î&4ɑåÈSŽÏ‘$®“#èR–-¯-ÎdÊÏdÊÎðÊȐÃÂLþ ÀŽ7 ‰íö˛;}’ÝÎÅî‘`sK°ºNy@sUiö‘#GjªÖfS}%#áÞ¶ª‚›ê '©“JL’É™…iZ¤)€êž¤xc‡7µn’=Éðqfg”Ìp”„£”Ò2RÚ*W•|¬*î +”ä}5êñ‚³†ôlE„¶rÎ6æ[v>Œ£’“Å".†7ÂËÅñs邬,É`—Åú·\Æ«BdðÜJ5™ñ©"Üñx»•eé4hé *qçÒ·û|KWàò¾éé.}c8;Ÿ™ž™^™Þ¢0×dú„ÂÜç S_éiÎï1ؘ&acšAMnÓB¦˜V"0­¥·‘rÜVÊq;(Çí¦·/Ž–Ô·ÕaÑRªž”†oq3üo€R#¥5nǛ’éWégàý€&¿FÚ¥Éͺ]Û¾}ûfi½UîçÕ0Òr›Üè‹ìÂHsí’3ÂHY[?Ê%™2Ä-‰3$ùÂ+õ©OÐ¥“_Rí­€$Ý+A™¬´ =¹7Cò²ufϞ=¯Ï¹2«G—Î͖ЌpJ¶”m%+…˜Äe +e3^åÑ- Ep¥ájAKõtËÒ'Ÿ|҈J\|KgÑeé|šw·@`ºdºdº•éné!lLOR˜{Î"ãýk´_z/S'©+ÈÔdê2 ™†ãü‹i2Ó÷Ls©É-B`Z†ƒIÑÒ:Êq›þZú·IKf¨Þâ¶*LIŠ‘(¸qÿýhQŒ´wïÞÝ0Òi«¶e˖0ÒëÚµk+¬+W®\b[¶lÙ|›0ÒL»0Òd¶‹z˜Sék—Ì5ú€$Ÿy„U>ò +º¼ç’i痤{> é÷dPˆçÁ0È]a™ÅÜîÖ­Û5B#—eÈÌæ‚L gšeÊÇgÊSêdʓË2žŠ3$“óÃY9!9^F¨oß¾¡`ÿþýýÉi¯_`Çí4hË+‰íð7ÙݒÝ6Á)Áꀌò€f—óÓl¬k³áÙV~$+µ6«ÁHôLÒTÁM-sSÎ$Õ8I‰IÊ­x5ŽMŒª›êǝ֞t˜>ncÈ5AÉ G`0A)ÕÒ·xPŠ•4fTF%+§k¥þfãsب¿Ù©¿9ø¼.>¾=ÛÃòqýÈJ!ÜJ™ŒW9x*ó™çAK˒ nõ©ÄÈr¸ÆlwºEÚ³1/]2µ™®™n —wklL÷°¡îÃlÒ/Ó –Ñ£G¿ŽÔô.öïA¦OA¦^ S +sƒÙe8‹åÆQ“›BMî{¦yL‹˜–SŽ[E9.BKØ> ¥)héçDZúݤ%3$…ê-nK]p‹·ã^ûEg$LI†÷P"Þ©íرcŒ´I“ÛvŒ´FúÁ*wöB›L fÛ䖟fFϲú™M ¦–Õß%9Ó.ùÄ-øÑÑ3`À€öÞ>}ú¼ì°yÆ/øñH@¦-÷…‚n J^^êҥ˕!¡‘KÂlo–„mÆ¿Nɐpb†¿¼‘Ç'9íöÊû:=’Ø·PšÝ%ÙmsJ°ªà ÙåÍ.ÏÓl +¬ìObU~$Uk‹1’¦ö¾U7µÌMí릜Iªq’!&©ÍÝÔZ75H'U݌~ÜUۓª%à ‘jÜ5AÉ GB8êAI1’Ò•R媗ŒJ"´«¿Y©¿ÙøDv5"+µjÕʍ¬äå‚ù¹œAš„õ"ÜSO=¥h©Z*†–ʘ–ã[:—wCzRž‚ÀÔd:dºdºŒ^­°1ÝHCÛq~ߋÔôRÓÓHM/"5½Auî=©3ÈÔ dúd2}K,–GMn +ÓL¦yL‹q0-§·ŠrÜ:ÌKŠ–¶©o&ý;*JK?ê•5ß7iÉ ‰á?a$u#%0ÒOÜu õ½Ü‰»(o׶nݺFZ¯ ä¯Òä^#-² +#͵É=>Ã&Œ4‰½>F³×ÇwX}:…‘¾tÊ4£\ò¡[’éàÇkžž={>ç$Ô ÉSÊBòäâ ¼,?(™œnÊôËñB~Ig¿OèÆënr{%§]Éi‡[ÞÜîx²9%»U°:vù›f—G5›9‰tO™Î@ejN/‹°1]Î>q×àeº ©é¤¦û04=†Ôô RÓKHMo"5u™>™ºƒL_âeú +û÷jr#©ÉG`šŠÀ4 Ó|–È-‰ÑÒjhi=´´™o¦xZ¢þaҒR…?†‘bÆí#íãþÛ͝¸ƒñmÓ¦M`¤50Ò +Mnà%0Ò|«0ÒL«ÜãSlÂHcmÂHÃXQÿ VŸ¾™WôpÊ4£‹S²§ƒK’é ·àNjɲ§<‚G{?þêì¹Õ'Ùx­ÿÝwß½Â/ rq@&5ÍíÛ·oF8…pbPþVŸj$Kò䀼,×/ü’å—ÉOØ'Ç z%}^IgG¸ÉíØqºË.Il»SÎÀæ”ì¶:v š]þ¦ÙäQÍ&ϳX©°YÁ#«²"ÑMRcÅmš¡#)S’j ÜÛj€WËÜԘ­œIIb’jÅ­ö,Q£rªªÛ!õãNb$”Ìp¤”ªaT²¤¨¿i¬³RÆ7d%͝Ïë %‰“ ››‹)ÂÉõ pC:-=úè£ÙTâ"]–^xá…RÖÄÕb>ÙN†ÜF Ói´¨<“ÂܹpÓ%HMWÀM×ÂM7ÃMwÂMà©©-RÓË,›k2½2u™>ÃËÔ/Ó@ËÔ©S‡ 0B`š€À4 Ó,Êqó)Ç-Á¼´óÒjÌKëùfJEKûñ֚´d†?ˆ‘*·ÔiϞ=»Ñ6wÀí[¹'7jrw®ÕV¯^]#-Õ÷ÀH³`¤©Va¤ñ0Ò:3†‘úۅ‘z9$?º¢Ø|àìÕ«×[.aW\’Vm݂y$ßîó~Üî2ºÁ+˜«}íÚµké“ä<ß/“š3ý¯¾úêi„“Çêð@™_žRìã7ò}ò²ŸÀS¦W29ä•ãù=ÂM^ïqË4Èå’wsº$§íNa3»CÈæÓ°Ú£A³Éß4›<ªY)®YQ¬r€!!it“Ôä "‹Û”Žd0’êÕ®Æl5R«AZÏIb’²p'­uûcªnIF%”ÌpĄc ” ZªÚ¨T¹þfÑëo†¬T¯^=2¾•¡ÅªËJÊ­$ÕÎJ[6åí®DKÊàýÀDº,ɐ–‘ ˆ5˜Ö™êL P™N¦0ׄíO΂›Î§:×nºnºnº•Ý]pӃÁŸ D÷,RÓ+¸šÞ™:‚LS˜ë—©+澦&÷Ó(¦ 8˜¦QŽ›M9n´´󒢥5É´´K~ª¤¥¿2-™;Ÿ©!ÕÚÿê1Ò?éoɌ¤n.a¤=0ÒNi*ç&îÉuܝ+µ+V,ƒ‘i ,˜£Íž={ºUnê‰ÖI“&² +#}NJú¯lƒþÒ. ѝ‚Vg‡dÊ»Iœ×Á”ç]‚.Oº?t ~Üåü¸Ù#ìódãåޗ^zé"¯€È9Þ矾©OBcßsÏ=׀P_kù˜íø$ yr®W^–å~ {$“ƒ9žÏ-3 [ÒÙíxr:åÝNÉi»CÊæ²ÚU×lò/=X©«Y!#++þ5œÚ:a×ÖT™Mu“T~$UkKÅHFÁM5—TËÜÎ>ûì*Ĥ¤=KÒVÝÒvi1AÉ G~8vA©êŽJ©êoê\Ôú·T²’ 2j\|îâ‹/v&ÒR¤o@ëÖ­ƒ\â0îÊL†´¦|ö;)f¬+™Ê™Ö§0w"۟4†›N‡›Î†›.@oj 7]…Þt=Üt ,ÿJ§‡X;÷$RÓs Ó« ÓÛ¨LP˜û„NŸ³b®/5¹¯˜†â`Í))ÇM§7›† 0/)ZªÀê­hiCŒ–¶›´d†Ãb¤(É]ñê0’Üe;Y[ i35áõ蝫¹;—krŸ.†‘æÂHßkÂH“a¤10ÒP«0Ò70RV‹õ°õîÝ» U­vɔ7;w~ ByÚ)õˆSì—àÇm®—_~ùz·äà•nÉÆK<Ï<óÌyIÎ3–AKv][R•8¥œxÜ\!×ʇÀ @ˆË™ÁÕÍæ:çqí ù¯(e¬7ÕeÊx<®¦“˜AžŠÔ~kçšÃMÁM—ÁM×P§»‰ž·#5݋µéT¦§P™^¤0׎vï"0}HMîS¦^8˜úӍiå¸a´û‹y)BKóçϯDKê+ëPi© +—wÚr\ZÝâÿŽÉPµ„tP?R#Uj nŸèâ¶#Ém¶‘n-k2+Xoð^º…Ô‰g£N‡‘&ÂH£4¹‹¿Ó¾ýöہšLzÃHÝi8ô«ÅÞ³ +#½a“¬xÑ&óŠ§Ðn¶KöÜ°Üfˆ¹Þ!Yv•C¤…CÒï<§$â™NIÉӜ2žä”áðx§¤iB¡˜PÀ9„LžrÊ(pÈk}^=ÊåÒrÚ%vIg»MæB6›¼›U«°”–i´ŠÔЌ4êjš"#5f«‘ÚÀ#CBRëÚÔX¬üHÆ0œÄHª¯dÒ¬–¹¥r&UWLªzGr”Ìpd…c”ÉÖ­æQ ‹à*á ËR-5mÚÔÎ'wp Ôº.®Kd]¹V>®Z€ëBeÊäšf[n¹å–<.v—½”ÿ…Zü§Ôå?êêt˜Kž†ètÜt.Üt1Üt9uº¿P§» ©éé>éQT¦§é9ð"íÞÀþýSgú2uÃÁôå¸þ”ãÓî{8楱˜—&cõŽÐÒâŋê_Tê+K}yý1´¤œ+‡º0Τ¥ÿ­P +Ò!¬k«BGJh°5‘‘VÆiŒ4FšAÅxjèi(Œô5ŒÔGFêÁ&±ÃHï[e¾Ð;ôËø}ž±½üòˏÚ$]î³µiÓæv»äэðK+»€È¥É· 2ôíhݺõéõNvȨ×À!4RÏ!iZ‹PJ($äò@!Ìó‚Ib¿C’Øk—¸í’É.»Ïa—‘Õn“ÃÛl2ÚÚl’ÓV« +2*kFФ5†fQYcT֌YÅòñðê!©$$µö_Àʳ­üHU3’Qp3z&©ïÄ¤ª·Ž2AÉ G`8†@ÉjµFÂ!ÉJÕËßx˒AK5²é¾%µÕÉgœá çԷѕëâæ +y¹V~ö‰ 2…™ +fr9s¸°ùèMELk0&ÖÆzPÿü÷4â« ¢Ó™pÓyèM—P§»‚:Ý_šn™î™î§0÷…¹gèþ5¹7˜ÞÃôݙ–LÝèÆô~ï4Œy©-͛7o.´´(FK+ÓӒ2â&ђ|5FhI}_V¦¥Ã±z›å¸ÿaF:D+ÒÈHëÖ­[‹„©i™~멛Pé{i2Œ45t¤?Fê#õÔzôèñ M? áÐ[0Ò«0Ò³˜~ž°J~<`“Ɲè97ÛdþñÐårpæ"»ŒuÍí2Ì5³Kžb—ll萼¬ï)wHšÖ ò ÿŸ½÷“«ºÒµuٜ:çVF‰$ DY˜ŒÉ`’É"ƒÈ9#rΓL49ç`›Œ±1×qlό=cÏÜ wî̝ÿù¿wªÚÝG§ÊՒ0ªŸÇß3ƒº«ÎNk¿g­µ×îäÚ’–„~¯˜ØyçóüY–H2–©@+9èC–sà˔ú¾¾ÈÄóµº=Ï Ö6L®gPd>#³»v‰Ù]óÙ]$†GVCÒÂlvößεÙÕ$–a$—”äêJÆÙ]s&™9¹3© JMùBËW”âh©¦[©~Î¥,9Zr¾%Ë[²«NìLœÀÁ”äÅ.2¥1dYÞør¤1°p%º®nêÀôuѧ½¼(§‹uœH·¯ÌLc(ÖddÖf´6`çâoڒ8ݶ¸šv™ö™ö'0w•-¢LÓI8˜ÎÀÁt>L—QZàÂq7“ï}'ÉK÷‘¼d´ô$©ÞÏSyéƽU›–,¤1Zú×!´Tq0ýße:×t0-o Ähgým*ÐJNú¨„¯åøúäÀךö}PÏÓW:åaYCÑï•m¬ùŒÌÐ鋖°¶†GVCÒ\Hvößεř\ÇH–”äêJÖÌÞ¹3© JMùBK”? Â5@KvՉ‰S+ƒÐÁ4cƌ/vIÌW +C–æ/‹k<‡…+ÀM%Þ[é¿2 ºyQìÃ&bÇÑÏ+a1W¦ï§ãtZ‹ñX‡áـњË0n‰«i[i¼L{˜ÛŸr+‡ruÊÑÄäNâ°Ü$}ŸOiËÈ÷¾†Ú•7“¼´˜ËQŒ–!Õ;ž–,2,÷i•–~Ғ•¿1Z²²¶7Ú.Yƒ–O^ªŽk:˜>sRýcÿ5êl»³ÿCϵ-ÉH¿ÂH?ÖÏpFz›IèéIéé>Ž)ÜI +ÞM0ÒÕ0Ò¥0Ò¹0Òiœ¨?žÄè#}-ˆƒüÃ;lb^»úZ3Ûû{î¹çVÓ<ðhÀf`gÍ@ÖlZ ·˜)–ä„@‹sL »Öô HRâ_ H.ÐËO†¿Hó·)_+9é룾–sàk9û&ž¾Ã E«ÛÉ(þ[(!™»È,«ùŒÌ¼šãȂkfc#xd†Ö\HvößεYÎv}Fru%ãn^¯ñÚ7jc› Ô”M¾Ì T“‘ ÂEj+5JK–·dYÞv&Îî;1“)À坙 S’ŽH˜ËÐ/Y,\n*`ðZèµ6ŽÍuЉÝØÄ>út4ð4³9‰Î^…nŸÎ¬ÅPÌÆ9¿!c4qۊÝ/Ó.æö"—éL‡á`:†Ãr É`:“pÜä{/"yéZn–»™ä¥Å¤zßÏ-reZ²íÉúø¾~BZú‘~ÂãHŸê'¤%+zc%ëÓRce–ÆÁÔD¦ÏâR‘â«äεÕô#Õ`¤×˜„/0Ÿbb> +#Ý#-†‘nÆCz ç.ƒ‘΃‘Nçlý‰0ÒŽŒLNô7|™¹ÝwíàkÍÌÇ©³©¯Å´‘¯e5°™á v¦@+Zˆ+Z’c½Ô Z¡½HW ێ´ðÿ‘¼¯_Éúúå4’ò9Íá뾘&ðõy'ñ=­iÏÓ9e2ÊÄPÈÄL©A‘ùŒ™eµàšÃ#ٗrmgc­¤k‹Ú©~®k‚RS¾0ò¥Fƒp‘“pq´äÖ´Uðv…)Õ"dòI0d +@¦-Oòž—¤#Òص ý’ÅߔÇà1}-ÀSðԉMì¡'û§ÑtìxLé$¸i¸i5üM3ÈX˜Í lÄðÌc´¶b·g¿N.ÓÞÄä ÒÀa–;†sr ǝI!¦ H^ZÄ )גê}K”–ì¾-½×-™ÿ BKÚBÿõ/§z/Ž‹Ô¨ç`j"ӈñh™ÃlîNۚŒäÎþ7ÊH/¾øâPFÒÄ|Fº‹L»[`¤ka¤EøJ/à=à é$éhéO/ û‘½é?;yZ$ÛÛÜ×ꙃËg=_–k&L³:œ3Õ×ʛäË|÷µ$Gû²a}¾Vh7ÒáëE§)ñÿæ‘’á÷ÒüEÒ§f?xú”ÀÓröCÑ'{¡­LF™„É×FA&–gdÔÜEEfJ-5Ûr,¸æ¼GfYí.Ã#çB²³ÿv®ÍÙؚŒÔÀ%%Ë|Ƹ JMYÁ¥ JCi©ærŽKYªIKv1œ]£ëLB&¿ŠLM 0_ ZžÄ!ž¢#ÒX¸ oY ^x*ÒW-XÂvà©ك±ìÇvŽÁžŽ‡›&ÑÏSéñÕèû Óº ÓF Ϧx™¶&|{†vWL{ã`: ¦Ã ÇK¾÷B +ŸIòÒTú^Dª÷µád¯ëöâna£¥çõS¥¥7ÃCHïé'JK¿Ð½Ë´dþ£¥úã*¦ÿ\Φ&2-Õ¬ŠÔ@*R徶?Æ2’¥¸ÕÈGrŒô"Œô4ŒôXÈHÂø»™¢·ÂHבsw9Œt!Œt&'òFpŒ·`Á‚Ã`¤ý=Ùµ=ɎÞÙÛu×]·õvÜqÇ-ˆomâm¹å–ëã홅h _ lUèf2Ø3Á×ãk5öûZ—=H§¯eچ”|Y³ÿWÉ i~%…$=ALÂã,â{ú(ßâxCDßá…¡ˆ821Ûé È¬¨‘‘åg[pÍyÌ¨Êæ”ñÈ,«…Ù\!I3Z.)Ž‘HJjàxq”šòE•&(5~®>-¹ÕmïezCóxz/t0UÉ¯"SÀÛ]€<«)‰]KáoJó˜Áàåèœ+ƒG+3ãàœA¨×ÓBìò´$Û=-ÎVOË´ˆä‘’AÒH’_I a⇢OñF™ˆs¼vꋙHKÃ6qPdfӑ‘PËώà‘e!E\H‘³ÿ‘|¤‘3ÒÈß>ÿº d;S”š²‚ƒ’ÅÙëƒR¤æÙgJžç•eYh)’å]ÓÁ$‹äñêVF¦J`ÎÇ|ù´2Àš4:…Kò˜Â¤é,ð”Ã0Œ%Ld+ƲÚEÿõÂMtçX\òA¦) Óªôø$~Î"t=r™6fx6c´æ3x;ŽÛáއêß‘¼txø®ÍæäðÕü¢‹.º0Lû¸îºë"´t´ô0%*ŸiéeýPÐû +z7¤¥ôæœXdÅђ+#P3Õ»F8®NSý˜\£ÈôEö7ý¡Œô¿%"lúß w!Y(ôÿTi R$Iˆ44][ˆôëнhŒT¹‹ÄՐü~LÎv}FºFºF:‡i{*øøጴ/Œ´¦jª•ÍÇ@mƪØؓmZ—Ô¡„ÀV#J¶ +x4 <ïi•†nú`ŸnO ±ÃӒlõ´8KHÁÓZÍ!$¤$ÿš@Ä÷,SÑNxØ¡ØaR¶±pb143‘ŠÌg!#³Î{äðȕt.$wö¿œíFé³%ky}P²}¦ JMYÑ@É>s äêÂÖ¥úÅa?cPZ>´TÓÁäIfÉ‚LW“ óie<%0n ZžÄà¥Ö¥é,–0‡a,ÐC%,f+Ö7uѽø›éαtìDi +È´*¹5ÈešELn=NÏÁÁ´9á¸ù„ãvdTwc¸÷ 7ÛbŒ–,|qöÙg—iéòË//ÓÒ-·Ür3E—S¢ò>JT–iéYý §¥w(èýƒ0žb^ƒHÑ¥a©Þ5“—꜎k™â¼L#妞%£á‘s!-a‹;ÍV?ÉɯB¤Ÿ‡îÅʝ¶†¡Zc¤J ÉWCFzJ?Cr¶ãé’K.Y‚‘„ûG2•¿Ye¤ÝÙw„‘¶ Ifi«b=ÖÇLÒV'¶=•ØØd¼GÀ£1žVY?ˆÓìtzâ’6O«±ÅÓº,xZ¡9$‹¤‘’DH0ÊD¿ìW¥|Ì£"eÎ1âqâþÁ‰FKÃ6‰@‘ùŒYp-â=2<Š¸"a¶iù*^> dûG dûQ”lßj‚RSþú ©û™€RbGJq´Ts‰7JKÎÁ4 ™¼™Ôã&nòi ] °p‰PÔò$¦/…ÌÐY cYÀl–°§­tX¯›Ýø›úp5 ‚Lcñ2MÄòO¡³§Ñík0³Èü^ŸÃrs£Í±Û0‚;2ªKÐÒñÇ?”–.¼ð BZºV?UZºZºZzˆ‚ޏ‡´ô’~(èý:½ß ã)Ãh)’ê½DòÒR:˜C¦xWÓ_<6÷yaÔÿ•<ÐÿÄàÑÿŽGÿ=$ÂVq! Å£Š é?B’ºþߪ§Ùâ\H¨¦"ý.öHÛÇüã0,[¹ÓÖÝEòJ˜öfŒô¨~HŠ³sm2Ò&ðÁLåoTi§‘¶Új«Í«Œ´>n×Y0Ò£U1FS0FXLcXV¼ô@FQ»§5Øâi5=­Ë¼§še™fµ*I†¯<’ *~ՇìEÅÌ\}1 +rb<EŽŒ\î‘3›Î{äð(f[ŽŒ´”ÕW\ÃgJ¶G5A©)Ÿ-(í³Ï>Ë ”j^7Ô@)ýú÷2FÖôÈAiä´Ô2I<žÞÃhyUnòi›I€q 0s  Eö/…9ÌÐf•ótNn*ÁMmtX½WSV~>‡cz"y +ã`š†ƒiM"øk3ëx˜Ãëõæá&b¯Ü °tŽƒ>ø ÆÒÒ)§œr2eÎ ii‘~ ¥k(Qy%*鸞÷½ô6Zú½Ÿ óK,Šbñ”%‹.-‘¼ Ç5à`ZfdªéjZ*Óç*ÿS‹Œ¢xäAF¡Ð%Èyà‘G¯!ÿéGxäGx䑅䁫ž¸õŸ=CX Ì?1FfûÝï~÷Û!©H.]ûÇ?þñGa0ö‡?üáÂí›o¾ù)n/Wï"q5$ï¯2’ksùHF:!†‘ö¨2Ò×`¤-0F›TimìКl³ÓX)Sx͘ˆ‹àM¤—ÖÅzkSZY~EVcɱ83,Ó4’ª®Z[¿AøTy òb¤Ì9õÅQC!ÇC(2Ÿ‘s–##”ân?ˆ€’í ¶CXv–%ÛI" d•¦FJ¶¿5A©)Ÿ(¹;‡l*üΡ]`]”¿ˆ–"¦2 ã&/D¦aÜ䇢˜9“¦/I˓˜C³ÅŒe6´Ôêœ"Ö»…¾jâwÐuÝ S¯ÃƒæƑ˴ý¼2=>¾_“pÃÚá†a¯×ö¢m´´óÎ;ïÈÐîƘïÃ,)ÓÒqÇg´´0¤¥ ô-]F‰Ê«)Qy%*ï  ÷=ô~‚ޏ…ù%E±xJ¥èÒ÷BO‡~øAè]0?Òá¸È鸈ƒiè¹¥D¦ÜTÓß´"ÔÿÔ$#¯"ÿoˆ,‰Gÿ5*ŒÁ£ÿþ=Ä#uóÿ†‘þÅ­þFú“§áøGïüã< Ñß{®÷Ûßþöoqþ* ³}úé§? S‘¬~»Ý{óƒüàÝÐÑøÆo¼N¨ö%Rܞ ÷–öfÇîÒIqîì¿ËÙ®ÉHûUiçáŒ4—)¿Œ´NÈHz‡˜Žvei%ÖÌ8VÏ Î‹>ÞDºY`,µV]‰5X`5æX—$Í2M…kU’_y*â^ƒ¼!bÖlDbä$ÂCŠâȨ&E\H2ÒR‚’ûКê–”lO‰%«bÞ¥¦¬¸ dSt)A)îâ¡ú 4ò£o#¥ú´Ô2 s5y¡7Uàɧm&Ï$A£“ØD³Åf•Í>g1#y:§ˆ-i¡¯Ú0( S7¯Ã}8˜FóŠ<Ž.^‰×æ•ÃhÛ&ì¥:BK¼xZ:âˆ#Œ–Ž¡èÒBŠ.-O‰ÊK)Qi´t#´t;´ô­0óÖòK,Š2¬ŒÀD[¾ú>øàƒ÷C?Cp\$ß;â`“«LÃr™FÈMÂÓòª%è/òÐPGF à‘ä?b\He<ª¸þäáBòW’Gn™Öz\[ãq9²ÇM¶ÞÏ~ö³O<;óh©HV‘Ôî½1÷â믿þÚ Õ>#=†o-íÍànÑIqׅG/+gÿÏ®kÛÛäi[¦[Æ0ÒZUFZ…· ÇH£CFÒ:êfEu€Gm,µxT`ùåXY$ÍâL…+ÔÖjeÕC^~Ì}G7Š£ 9(ªIFâÑgÂHË|Ÿ¦í¶D@ÉNF@É +q6A©)+.(Ù­ €RÜ-Ö6åmòÛ¹ŽåxCãȗxýß-Å!S nòhBY*ðäÓ6“ÓÐÞb¶Ø¬ršŽÈ`³³ôK^¤›Z@¦6^‚;Ã×aõd_hþ–ìµÙhIÛD™–®kSƒi}R½ç0dCii÷Ýwߍ7Z:0¤¥c=Öh餐–Î?ÿüó(Qi´t½o  ÷maæ­å—TŠ.=z Ì`ž„wÞyçíл`~ÛM+á¸OÂ[ãÙuÃkã"¦JÓИ\cÈTÇÕÇMõái™1ªA‰E¡%É过Ë !#Éÿ­âÑùôò¾úæß}õÒ¿ùê¯õÁ#_}ø/>xä«sËx¤ÿ#.¤À…ôw¸~g.$’÷Ë_þòç×ýy@¯þz€°ÇéGoX*Ò«a‰ígžyæiœß!hû`¾µ´7K€³ƒ—ë'§Cs-ÝÎç1-E^}[—`u]'/Æ=¼"÷‡´d¯Íömᣥ™3gÖ¤¥ù¼yí-íÊèïÍ,9Kvƒ–Žµpᓸ_÷thé\hé +z_æÛZV‰Ý-1¬ŒÀã¡ÿÀ< ¯¿þú«áýº‘pœ9˜>ù䓟V/ÙýEÌ©8˜Ü¹HL®QdŠw5ž%¨¥¯žüw-BF>däCFȆ¢¦ýŸFðH=⑯>ý'<òñæùêñ¿÷E«¿÷W_ûë¨ Ôõ>úè£=ðׄ=N?z¸=—ŠdÕÝÍåøàƒ~;tCÞyçw„io–g,)ÎTÉê#9$ÉIvhg'Ä1ÒliF”‘dnâI먍Uf$­²<ë-ËÊË°Ó,Éd(Z¡‰êZõ‡‹7\–›‘‹C¡8(ªIF àQýÛmGtÌ­cÃõﯔí +J¶/Øae¤(Ùµv”lŸ±Çöže%·6Aé«,‚’õr%«ÊoÓہ’M~JvÖÚw@–ã]#g¤8PªOKõ‘©ÂMÞ©p“Š„b¹bŸS¡¹6í.Ʌ/¼fÖí%XF¦=4úFK¶ؖ0ZڌZ¶q´t´t(½¢ ÷‰ÐÒiô>‡“H…÷HTJTÞL¦‰;÷ ©ÞáIx +Ÿ‚»ÅÂqïŽ+;˜ØkcL¿Kñ4†Lq¹LÿžÚªÁMÃSµ$Uý©KAeZ’‡ÊPT“Œ*xôÈ¿ÿPŸþ>Pïþ6P?ÿ&¤þÊWßÿܸ~ê aê f샵¾÷=Ôõ^üõ^{íµW<Ø#Ìæq"Ò#ÉÃÑèÙ­8æ|¼ñƯ'|{%io—wΏØÑK;V`Ç1]}$YŸ`¤¯Å2ÒÚk¯]f¤éÓ§O%ø<#3¡ÊH,^IW•‘Za¤‹©ËHZƒeF²uibkµ"^ŒÄƒÍ²HŠÅ£8Fª J#7›q†1bÿê§'¹ÊP²›¶C8P²ýÁ’í.P²]Èö#ۙvÜqÇ¡ d;˜íe5AÉm†MPúŠÊR‚’›p ´ë®»–§žMÂ(m¾ùæåikb;P²‹(Yi~[5ï1‰$*ÅÅß ¥å-q6§&(Õ¤¥Šñ†#“?D*V91„–Ìp› Wod«´Th„–êù–fanփ–6®ÒÒÖChIó`O¦Ê~\r0ןÉõ'ÇCK§T¯?±¢K—E¹ŠxÊ ¡×àž{î¹ OÂ}$/=DòÒwH^zšpÜ „ã^!7ÔÁôÁ¼‡ƒéL?ÆÁd1¹Ÿ“û919‡L 2 õ2 Kÿ^ÂÕ´$7 ÓEà©‚ÆRN– ªÊü¡âò‡†K-Eƒ¢ +ýÛ2’üoðè_À£N€G ð(¡ÖÿSB½ñ ð(!<ú‡x”0û´û ±G˜Í“½;ï¼ó6Oè|£wÝu×]íá|ôÌ yÞyçM ÷TàN î(ŽŠ½:;´w•‘v ‹¥Vii¶ÊuBFZk­µVã°ÈTLËdLËŒ$ÓRf$[$¶\c¤D”‘–\µŸ%#Õ³ ËJK Oõí_Íê¼Î™T?=Éx‹»½Ä’í.¶Ï؎S”l·j‚RS>OP²ñvQ³]°ã@ɪNÆ݌©9úV?þw“cý°#7KÉC#À£:n¥F}KÃ"qÙjÞÒ´T3Ë۝‰«Tp´´.#¸´4¯JKÛBK;3#vgÒì^­[¹,î2oO"¿ä42MÎ!žr‘•E¤z_C´åF’—n'yénŽ<ÝO8îaR|¿C8îiNÇ=ƒéeL¯ã`²#rß«"Óû!2ýô§?x™Ê¹J.Óo†Dç†qÓ³sæo²Ô¦Jœn xrž§AE0jX(/JUá¡ûºâWäß"Tä_‡8‰*£?'%Jêiÿ) %!£¤Úö‡¤ùI5÷ï“jýï“àQRýò·Iáѯ“ê°_&Õu?Oª?M‚GÉO?ýôã„úùG õø õý{‰÷Þ{ïû !ì;Á;ï¼óFðÆo¼¼òÊ+//¼ðÂ3QUÿñÇÔøᇿíßÿý÷øwß}÷˜ì ˜¯÷„ÎWz—_~ù¥žpú|O`}¦g÷1ŸtÒIÇÒ]weªöÇúìE.É®ÃïkÛ<ÊH묳ÎZQF’U™À6;«2€U)3’¬JV¥7F)\.¶pl YÀ-’4̙ä)”>??҈i9ÆúGëß÷T?êæғâ*Ä݇k;Ž»æÍö#ۙš Ô”ϔ܅o”j–çŽ;ú—¨äâo‘B5ït¬Yqv)ÇòF¡¸Œî%å/¥,Uò–Õc7KВ‰3óom 2AeZ҆ÑÃÖÑÏ&©·4%¼ÔÁ®wXo½õfòš¡¥-î¯AK; ¿Z÷@héPhé(òKN ÓäTrNÎ"²r1–KIõ¾Šä¥ëI^º…ä¥; ÇÝC8®ì`zöÙgŸÀÁô ¦È`z… ¦78"÷61¹ï‘ôýCª +üÍpdúIˆL•\¦ò‰9s5Yx nrqº%àÉe:¹t§FE¼Q  +ŋˆU'ªŠ_KÂL¢aòωaòç(UÉ(!Hé‘ÿ!¥ü}J­ú}J­ü]JíýmJÍÿMJxô«”úå)áÑÿJ©Ã~–R×ý4¥>ùä“%?þøã÷“êç÷’êñw“ÂÕw’×7o½õÖ«‰×^{í¥ÄK/½ô\ðÜsÏ=<ù䓏=öØCÁƒ>xŸ¯¡½Ë× ßæßzë­7ú`²O˜Í=Aô¹žpút°öpHzæš#}³´1ÿ=a¤]02ÛÃH[Wﴝ™·róÆH3f̘ŽAYƒ2)d$í°c0(”^öß. J¥ÌHÚ¢ ár±Ãm•¤$ÇH %%ýuAiùÔò±„õ-\Í+ #EŠÄEÝ\zRýʑÛK" äîÃm‚RS>3Pªyá[”jSŠ;úITªsn¥Fi©þiÙe1-# žÆeɔÍƏù3q²ò®‚€UÆ˅AWWW©Zo©=¬·¤­£§ZrÅhibxñ•ìЪᅡ²ÐÒlÆrCüÙsä-óm˜;`dveÒì-íÏé¤CÈÁ=Z:Žœ“…dŸœÁÁ¸ó8w1©Þ—“¼t-ÉK7Ž»Zwq:î>Lá`zŒ ¦'É`z–ÛP^$&÷j 2Es–þý1éßvbîÓ(7¹³sÆM§‹ƒ§až§¡UÁ¨K¹ÔñP<'â—?‡u­:QEþÌq³! “?%†É?%œ“¨"eEiÉߥõŒ¿Oë‘—V3þ6­fý&­þ*­öþ2­æÿ<­Žø4­~ù$­úIZŒùã4x”V'¾Ÿþ裏~˜úàƒ¾ŸR?¿“R¿™|ûí·_K +\_J¾òÊ+Ï'_xᅧO?ýôã‰Çüá„ïàøV@|5ÐÐÞâk¯÷5ÜWùøK}M ’ĘАݛÐà-N,^¼øրøj ¡½&Ð _î/Z´èbÿ¢‹.:×?÷ÜsÏð5Nö.\xœ§ ²À¬½C9äOÓgoϜ”b¤`¤¯ÁH[ÂHó°%±® #ͪ2Ò´ðRC™‘Iì¦ãÙWDŽ—¶i¯íe¢wñnÐ^H"3âŠmçÃE"Pʄk¦RH2.+·ÊÜʳ…8¢*Ÿ±¬p6lÉۛ–¸(ܬ·«q&ÅEÝ"WáÖÌãye€æ}¸MYΠÔ@1¥2º#×ãÆÅßÌãÉVj”–"ÈT³X[£UKF$5¿h)eÉÒu^µ‚÷Ð2ÞJVË[½‘ oX°»*e¼sámU¥" äî‰ë ï‰ÓÆÒÇ3Èf3–W· l@“±HS±H«1xkAKkcŒÖgóšƒÚZڊɰ-dg¦ÏîԻهKBK‡’¡»€ƒqÇs0îdR½Ï Õû<’—.&yérÂq×PwðL·â`ZŒƒéJ>À¹‡‰É9dr^& ÌY.Ó[ä2}—–ߣsæjrÜd‰àÆMV¡ÉâtV¦É.'sðäQ‘¿K“ߧ*ò»4(T•¿Š~B‘äWY=Á/³zž_dõxÿ+«Gþ4«&ü,§ý4§¶}œSS?Ê©åæÔïgÕ%ïeÕCïfÕWßˊ6ßΪßȏ^ͼõÖ[/eÔÏϧÕãO§Ÿþù'ÒO?ýô£©ï|ç;¦ðÿ%ñ&ñ &ñ&ð&®»îº+\H1׀è«öÙgŸêŸvÚi'ú'tÒ1þ1Çs¸wÄG|Ó;øàƒ÷ódnöô´e}Ý3'¥¹+Íq©i6— ·!Œ4›ËL,ÈXilšÆH+±‘ŽgKµv¼Ó’ñÊÛjÊG.mˇKÃjÝ[Õ{«?¬âv.0·ÞâVãò^ñ ùLÌ\¤>f"±¶8F2+q&EŠD¢nqéIõ¼5‹r7å¯ +JõkÔOTŠ‹¿Õt+¹j.çhÉEâ"wf×¼ ©æŸ±Ä=ÁÄ] çįÞT+âtIùž8»½S}eWÄ墷êÊ,µÑÅ i7f©—`(Æðþ6­h›Ò*˜¥éŒàšlY³°Hë1È1æó˜[2#¾Æ,ّ9´+´´´´§˜&W÷ÆCª÷‰$/JòÒY„ã. w §ã®àtܵ8˜nÂÁtL‹9"w1¹ˆÉ9dz²ŠL–ËdéßvbîÍÐÕd9àâ¦w‡pӏ~ô#+þ£ðZ^«liÅÀ ž¬`“yžâJò«ð.:Ã(»Ã×XJò·á•&vš‰jtBa"“ *áq3’ªM’U 3‰‚f¿¶ÈÙ'Q…‡~nP”Ó·}šÓ—ÿ,§GùiNOö“Ì«mïçÕÔ÷òjôò£ïçÕ%ïä…GoåÔW¯çD›¯äԉ/f_ýõ粯¼òÊÓYõóã™gžyæÑÌO<ñ`úÑG½/­A¹;…ÿ/µxñâ›S·ÞzëõI¼ƒIü„‰Ë/¿üÂÄÅ_|NpÞyç} ˆÃú'œpÂÿ裏>Ô?üðÃôe‡öõddv÷dUvödK¶ódF¶öÄH›…ŽK1ÒL¸u˜z3˜„«3We¿œÂ]‰·,;Ài‡,ñÎRðºxhÇx´bSe{&Ò.ÐÒœôޗóLRFàPÆ- Õû8’—’¼t:á¸sÇ]ˆƒé2LW’Át·¡ÜÄ¹ÛˆÉ E&ó2iŒÃr–Ëô ,íÄÜK¡«ÉŽÍU¸é°ž¥Uh²¢–”I OÑÙmsvɽª OvU¯#(ÉÏ›{FI~n,åq›/7žý‚{=~^îa%¬]~˜ˆdBIT%ÎI~œ3'<„|½oPTÔW¾WÔü ¨‡z·¤‡ü^IüNIíx«¤f½QR+_+ ^. ^, +ž+ªsž.¾úê«O„Gž{ O=õÔ·óÒ{óêç»r<ðÀY À-Y£qìÕB¦é«¯¾ú’ô¢E‹ÎO]|ñÅg¥HDKjTOJj|Mh¤L}ôчý̓}}͈=|rÚ|͒í}í`ó=ٍ-<Í¡¹žvº =íyëzæ¸4¦ð|:Öb¬Åd¬Å¬ÅX¬…¥ÖY’;™ÊíLêV¦w‰‰^§¼&¿½*dXi–†½C$Ãåb ǖ-&[V‘¥fËïó6+ªD È‘‘Ye‡Gf³#±¶#EŽ¹Õw&Տº-KzR”š²¬ T3Q©~ü͝‹s+ÙKƒ½>¸ œ£%‰³µq0EÉq“ƒ''n%qdX¼¨¨•~UšÐ‰PÔ9Iº)E‡¥1Pú/|æéÓ"½[¢Ÿ[éñvú¾‹QèÁJõ32££qìV¡ÜÉX©©X©ÕÚ5y“[µ¶i#ÞßæBK[@KÛ0‘¶‡–váô÷”¨Ü—ƒqê}ÉKGŽ;–p܉8˜NÅÁtLçQPÀiIßed2/Ó½÷Þ{+µ+邏¥ۉ¹o‡®&qÓca¥çŸþ©°ž¥Uh²¢–VÜ®N±Ûæ„ oBPo“éôÝðª^#(ÅÀ¨‚QïQƒ#ê}ÇR\qö¡Pq!ì<‚z&vZ(œÅ LÄ/%L„V%«’Ýü(]•ŒäÌ°çì䃜þß÷‘¿É#¡“HòòýŠômï´è1Þjѽ٢‡|½Eüj‹Zðr‹Zôb‹ñ¹µ÷™5ÿÉõÆwJêœGJ£Kêµû‹?þø=ÅGydqA@z{Aý|s~ñâÅ×ç4Wçn¼ñÆ˳×^{í%™+®¸â‚ŒFëì´Æíô´Fpaê´ÓN;.¹pᣒÇwÜa‰ ” ½?‘Ù+Ù5ñØÑ'§Í—ÉØÊ]o#́‘6ð4›f{šW3<Í°ÕC¦öƕõI ûxà} †bƒ‹-lÜÉ6稹IKLïÖ"ǔÏ2ù3á2°¡¥‘ ׇ-“aëȏ]j_X ò™Z¤¡PäÈ(œ ©&#En5Iî¬[\Ôm™Ó“š Ô”º ´”‰Jõ ¸ø[\¶’;×-9“C&{;‰p“ƒ''ný~±EñbħÑ&a’ _ôP’¾JÑkiú/ƒ•Êҝyâ"%ï  èµV}Û«­z‚—[õ@/¶éùžoÓ3?Û¦&<ݦ=Ù¦~§Mí}´UͨU½ñ@«ðèÞáÑÝ-£;K>øà­%uçMEõîu…Ûo¿ýêÂÍ7ß|yž<²ÜUW]uAî²Ë.;;{á…žž!;?sÆgŸô:á„O „NqÄû'Ç{'HïOèh2lh˚ïkÛ—˜ë“çæi“[ϛ7oÞÚ0ÒZ0ÒjžÌƒºœ:3Í­iÈ®íÓÒèz™§,îÀF˜KԜ£E&uém/Y¦|&œü¶ ´ ’áÒ°EbË¥²püpE֖·,ûS"6Ö_GFfŸ™õ6;^“‘\ÀÍskÀ™ÔhÔmYғš ô•’¸Ñy¢RÍø›;ÿVÓ­„s%»-™Öb֖ággââ)ÂMžœØÒý‰G³"âÓr“€Þ0IÐ9&I:,Å&’¦ÿ2tgS•ÇTèç=ÞJß·3 +ŒG7#ÓË 0Zc·ñŒàJØ«)Ø«UäÕîµ0Ukó:·Ób#fÉ{_»Øñ[í£Åm£ÛÛÔM·´ª×nh¹ûm†^YRï.*ŠO/.ªÛÏ/,Z´èìüÅ_|zN0{rNX{BöÔSO=:Cž~šŒý´ô€Ô¡‡ºoRe¤6 ¯'´)퐐øZ€ )ж©/œžãkkÛÀ'ÏÍ'ãÍÛxã×ð4¥¦ÃH«xÚíÔåÜ c ¾Œf&ö‡ð®Ùi!b ·1w[˜ÅEæsóczgÉnSÞ&¿‰-[¶Hl¹Ø‰,&[`ùüûŠ*ëŒo„ŒÌ{Á#³èfÛÍÊ×d¤È17—™q&5u[æô¤&(}õd9Æß"çßâÒº#ÙJ‘ \„–"¾%Ëës&[`/“‰­F[—‚rõe¶EħùeQ—H‚JÐaI$Ş’¦3ôi{•£‹ tv‘ÞÞÛŠ¥‹áée ú²Ñ Þ8†q"ø;·Ò*ŒôtÆ|MìÕLÐy6¦j¦ÊlÓ¦L©-™p_£èҌۅpÜ„ãö¡–Àþä{“òK‡swÜPdºôÒK-0w&•¾-ýû\M—ÀM‹Âpq“•²¼êß7§³yïžîž¾<݇çé’Ä † Å%÷Ôãø ž£ž"€÷ õlˆQBça©å  èñ ¨C_ùH§ã¡N=Õ·;õ¤÷wêÁïíÞÝ©¶-îTSoïPËoéPGÜØ®~¹®]Ýtu›zíŠ6u⥭7ÜpÃE-êÝóJðiñ’K.9­xÁ,,aÏ fÎi ŽÈjÈÉuÔQf?üð}Ó²*{¦4¾»¦4Ò;%5æÛ&4ú['d64#æšš%ëùš/kûš9kùd¼ÁH«zÚ W†‘Vòf͚5F# ÂH}LÇ&f'S´=zÍظˆQÈ3ŸsÌìL8½m¢kÞ'YÉphUUñÃåYB¶¬*òù/ñZ"6ÖßÙ®Ã#çB2Ûîò‘#Ùnà)p¹3©™žÔ”¿*(5«éVª„«IK¶zl9“-0{‰p“­FçtŠ`T¨¾Ri‘#>Í/‹º$Eݔ Ã’t]*õd†ŽÍb´rôsH-Ò÷-ŒB+ãÑÎÈt1F=ŒV–kËXNÀrMÂr­ŒåZ•_£µ3bm&Èz˜ª˜>s™R›3׶æ`ܶ„ãv$÷uL{ïA&ó2Y`îXn‘;‘Ú•–þm'æΆ›Îƒ›.ÂßtiXœé¦›n² S®žnë€S1¼mÎ.èå¦ êê^bw÷ƒQßÆõõ0õõXˆQO<ñÄãžxã –òÄR&Où‘§Ã aqN„÷ì´„ —²$I1O‰_ž1I ­žÉ YÍ39ÉÓ9AÖÓyÉSɓEaϓ%É-’Ç[õß¾Ó&y4tIîÐ<=`PÔ¥o»·KOð­.=Ð]]zÈ;ºõà·u=öØc·t©Y7v©•×u©åWw +®èT¿\Öqë­·^Ü.Ú¼ íÚk¯=§Mxtf+TÚ¢Î>©$\=¾¨Q8ºpòÉ'QÐð’Û˜;âˆ#¾‘¥DFc¹kZæa§´ŒÂv) ÷ü¤^œ¶Hj +ÌKh2lœÐ´X?À…hªÌô5iÖðµñM÷5‘V‘&ÃH½™3gŽó4×ìÁó¯7tkšƒS¦ )j!âRˆöšÀy$Ë|Î0½í …$™÷‰P´‚ªøá"©±z¼`u¯ÀgTÉuf8BFf³ÍzG\HFr~$—”än‘cn‘̤8gRÜY·&(5eYA).Q)îê·úiݑl%„³ÙnNÔ8Z²•b9|vâÁÂqd²7‘8nrðäÄlMq {–úMxCD6ñCQ—˜t“I‚^KÒIz2EŸ¦éÝ –+Ggç±\ ÄP´2(í O'Õ͐õ2x ãtæk"æk2æk*æk:–k ¦ÅLhiæËúLŸ™Mó˜f[ê=Ÿpܶ8˜vÄÁôu2˜–@& ̝uÖYGâj:n:nZ7Y]¦3)eyqºó§‹€§KÃ[S®¿þú+ñ<]Ãý)×AP7@P7CP·»»‚ºÔb0ên0ê[`Ô½TÀ¼–º–zÀƒ¥¼‡zèA ò*¿”/yÄU=p5l@Œ/!ªz4i"jy4Åù¼´&2Z=šµƒø¢›GòvæLõpQòPIò`‹äÛ­’Ú$÷·KîëÐïÝÓ©?ûV—ä®.}èânƒ"}åm=úò[zô,7õèùnèÑã^Û£&\ÝsÏ=÷\Ñ­V^Ö­F_Ü¥>¸ KPyn§ð謎+¯¼òôvÁçÉí°hÛ¹çž{lë™gžyT gK'žxâÁEqìÑ¾ùC=t¯œìÆnYY†3Ðí3ڏ¶Iëui˔Æ|Ó¤Öþœ¤æÁ -ûuZö³\HæËj>.$_she_³i’§y5Fëi® zÚ/íAk¿‹éØÁÄl ]š¬E¦m œ !_ó9ƒ¤™ÞFÿö2EË ¨JyUDÖÌ0ùŠÏÁúD¬­ƒ¢™ÍŽÃ#³òfï#±¶8Fr7wÌ­¦3)î¬[£Q·&(5%”–£[)R­;.çR–-Ùª°õa™{vÎÁL™œ—É–šã¦<9‚Šˆ[¿_>Q½ñ鍲¨‡‚PÔa‰PԉIº3EǦٙ2ôs–ÏÓ÷F¡Äx´02mŒQ£ÕŸõ0‚ýŒå £:–ñ€ ›„ [¶*“a5¦ÅZ̒YX®Ù­ ˜Ms˜aó˜[à`2dÚ.D&çe:þøã÷&ó{?Ë7ى¹#(2pTxlN;û‰ÄéNžì”39Ewž§óð<]HõK ¨Ë ¨ËG‰®‚ ®Áu>¨ëÁ¨Á¨›Á¨[¨€y,u;,u,µØKÝ剥îòDw{•_ʍÜHîåÚ³{¢ª{톏¤¨ê>+fUݛF2B«{)Qtoá4þ=„ƒgß*Yzµä®V±Ïâ6ɝäÝÑ!¹½Srk—~ù–nã!}ԍ@Ñõ½ú¢k{õ½W÷ê1®ìÕ£]ޫǽ´WOq¯ZtAxnÚ{V·úàônAå)]ꡓ:/ºè¢ã;ԉǴ«OlSÖªÿf‹`ÿ҂ ö-jdö,Èx욏ràQNc¹MV/I[fô~´YZýIŠòZ)"lI"l ío3DØ͗i.$’ É×¼#†‘`¤^OS¯›Ih9ríLÌV¦h‰ÉjáΩ@Hr[°xñâÛ¢ªÛdI%%·§¸ë#-´º=CÕñ,E¡rH^Ls[Ahuk)‰sni‘ÜÜ*¹©Mrc»ä†Éõ9“\Ó­_¾ºÇxHŸrE¯>yQŸ¾ãÒ>}ïÅ}zŒ ûôTçõéIÏé»ñÆÏìScNïUÛNéÔ£æߣ.9¦[x´ K½vx'ÚÁQÄöãŽ;n¿6‘ê>­”uhJÆ*RP´åÁ£œÖùfYjŽfÄÅ¥µƒ­—­“¢ÐV’[B³dzBóej -pJ@’¯Ù4ÞDžäkaÂHýàQÒåYfœ&f[ÿ•”s7:=%&µ9BS!îWÄ^‚ªøÃŋ‘ÏÕ~1%bcñu9BFf½ãðÈì½Y~Ûl7h€‘\À­Ì¤fÔ­)Ë”jž«ïVª„s)Kõi)â`²%ä¼L枍p“ƒ'GPNl­Æ‰[Î_lY²m^TÔ&~(ê¦ u]"ug’ŽMÑÅi:; eéû£g< +ŒL kÖÊhµ1n€R ÔCü­×ø &m,&m<&m%æÁfÄTæÆtfÉ̗LŸµ1dë2¯2•½Lš§å\&qÓpÓÎø›¬ÈÀžT±ÜxÚx:`]˜ru$u4u,uéN'AP§àƒ: Œ:Œ: Œ:Œ:Œºoԅ`ÔÅx£.¥.ƒ¥yŒË=ÕžxãJïšk®¹Ê¨|1ÈÕ>Ω@@u ·Â^›U]›ä4“ùRi¡Õµ2γÜ֒£ÌA^rMA`sMQ|uu Ò*عªMre»äŠÉ坒E]’K»õ+—ôH.î5Ҝߧ=¯_N¿¾í¬~=ÁéýzªSûõ'÷ë™OìW;Žï"ÓwÁ,èÞ#<:´›Àf·zmÿ.áѾTohíÞFý«V Ŏ-™íJ¨ùEíB[À£¼t“x”%)£å¼Nš¤”fĚ)Îù')Pš I;¡94)Дš…öq!ùUxԉ´{š±­LÛ¤2’ÄbÂY$º?%æM†Ì_÷à/FV„õû…šV4bmvPäÈÈ×"xä\Hd°pÈ©æ1·úΤfÔ­)#¥ev+¹ \£´ä²¼í$ƒ­ˆƒÉ–-¦79“-?GPNÜ2uâÐêK*•¦z±¢~ñ‡ˆz-E=™ O“¡¨‹StvšnÏ0Y†"Ç ž"&­…!kŤµcÒ:ËnFµ»6ÀHfÌÇ1ú˜“˜S˜SyœÎ|Yƒ™SF¦Š—iæÚfå2Yú÷VLÛmÈjÚxډ³s_'|÷°ú·jj?ÜO‚Q‡wó +£Ž£€QǀQÇÅ;Œ:‰JN'ÃR§â: –:–:‹xÞÙ°Ô9°Ôyžã|O@u' ºÐP]ä‹<.ò¡ªª +ðPqãÙ% QÕ¥Iî‡M]uÕU—RÇúÒ4IS¡Õ¥YÒÎóœÙ+ EñÕÅ%ÑÍÅ-’‹ZY¶#’ :Å>çwéÿ:·[rNäì^séÏÎèל2 _8 o;q@_~ü€žåØ=ßÑzÜ#ûՄÃûÕ¬CúDŒõ©åôª7¾Ñ£Ú»[½¶Ge®:Õ»;w¨Çwh×:߶Uƒ²u‹öž-JT^/‚GmTåñåÀ£,x”ÒàQ +®Krl·ä˜ÉQ½ú‡}’#ûõ‡èoÐG}sP_tà ¾wÿA=Æ7õhû êI÷ î> ÆìÚ¯îܧFï؋o®G³M·zmë.uçêìM;4›´kx6nՐmТa\·¤¡]»À£Ø¢G³Y·zmn—zwN§`ÍÑzí·Ù­ÕY-¤f—HÍ.’š]ò∕sâ’ÉYËJAÌø´ÀflŠë”“ÜȖ\uÕUû’ž`êÔ©]H‡/iCZ‘’ÇA6¤(å`¤¬g6IºzÀ` Fª‹ƒ!ÎQ=‰ûZà6𸭼)KiP†Rg‘Ž##³íqxä\Hîì$©>#<àÖt&5eYi)âVZJZryKîL\ÄÁA&[85¹ÉÁ“#(‡QqâVíWR*áŊºÎ.k’ ³M’ @*GÉ0˜Ó£~Ù°[¶~—†bÝNÖÚՙmø5[5sVoJ\ÁVäšÚo hëA}ÑVƒ”óÔ³l6 G›7 Çݤ_O¿q¿Z´aŸZ¹~¯Z¾nºdn®5îÒø®Õ¡­mv툫µ 0Vmåöµn¨- +S&À£2E¸ÉÁ“#('nIF¨ª)Kˆ:Ç«%þQÇUIT%ɤª’F2HÉ!K SÅËd1¹¤‹êFì°\?_9ˆŒæ!Ç"ã±»‘IØâ)áõr’U±ÔӑՑ5‘È,dd]~o}d>`#d:—lÆ÷nγlÉäڊ¹¶5³n>“p¦ã×´<·~Ȧ*iíØ¢µc«d‡v-°í;ÈQï$½šëm»%_ë‘lÓ+™ßÇ0ýú½-ô[à)Ú|@µé P4¨/ÚdPß»ñ€cÃnÜëד®×¯§ŸÝÇÅŽjåÌ5z­nõÆ]ÚèWëQLëjLm§jv+‡ÖZH;* X&….ã +£1y1Í`NˆÓŸñôeÄ>=i¡PWj¥•VêLNœ8±iKHZI )ÜÈæë÷rÐRZÊx¢¥4´””R€RPJ†Ùô½A˜ŠäÂlŽ‘"x$(ò€"oŹ6êïìqòù/ÓNâl¬£ 'ÎH;ÃGFâ‘+$Ù(#<àÖ¥¦,+-ÕÂ-%-9S}nrðGPNܒ¬/nÕdÉÞðj‰?\‚á’@’UI!éªd,A¦VÔҘZ1¯m_;,×ÉÎÔÍæÕˆև °ÉfÏÃî7™Àf¸{ã$d +N„UU‘éÈêÈÈZÈLd¿¼².°²Ÿ·!²ß1‡oۄïËcÌã6åÑ6óô¤›{zæ--}¨Ê‡ª|ͺ­ÍÄ­MÌ­š§[sÏÙü¤&ðü”¦òü´&õüŒ¦÷ü¬fûüœæýü¼VÀÖ­…­‹H‹–ÆV­Z$[µI¶lך٢!ÇzónÉf=’M{Icï“Ìí3'‘ñþv£}žAÑú@Ñ·è Öî×SÍê×CÎèÃ׫Ƭѫ®Ö£öNëVoLío¬Ü!ü˜ÜNÉ£6­µ’vÔBÚQÇQaêÔ©ƒyMNœÓ›ñôd@]é &t¦Çߞ’´%Ǎג”b ÿV@ò¾~/çë/²¾)ãéSҞh)(%q+YørT;çoÙ,SÛ¥"Y˜Í1RÅ{äÕN‚‰Ä{â6úÈö·ÑÅ¥Q£±ÅÎH;Ãí È‘Q$¸Ö5©)+.(-%-5€LqÜd 'ÂMžœ8ŒŠ°T£â–sS¼Zâ— *‰ª$±Ž&)d(29/“æ,—IRbß*–Ó†ÖÆþÖÁN×ɞ×Åîgפô²#öã:dƒŒe¿GðeÛçJÈ$<SU©È4d:²:²²¿<™Å¬¬ÃçÍæ“×CÖçÛ6à{7ä 6ôDUyz =€Ê7ª|=ó&ž~.÷¾Îåv³¹ |UI5u^Jž—VÌ£zõ¼¬ºi^ÉkêÍ-hÆÎ¥:ÑÜÉU­šè›´Iæ´kÞÏélÜ)Ù¨K²a·dƒ šIÖëÓוֹÌÆS´N¿>eP4³_?£__¹f¿ž`>=Ðj}z¾é½zÜU{Ԏ©=jÖÊÝjïä.z­S 2±ƒãüm£q­b•1-¢–Áqµ"Ž£x”âtçD<]Y±OGF(Ԟ;vlkj̘1-II )&$$è_sHÖ×_d ¥4´”ò¸”ZJâVJJ‰°n¼¾<¨‚’?”,SÛbm5ÉáQ$&ô‰Ûü#{|d£ÿJÊÈMiÄGxÈAQ„ŒjâQ.¤F©¤¤&(5å¯EK‘¼¥8SMdŠ¸šjú›"åÄ­Æú!­¦DċŠ¬ž‰?\‚Pd"Mâ‘ÉhÉbrÚ¨2lYåÌoíeyvµr}íâ%¶»V=mlíl†l‹]@Œ]ÆÛÃ~هw¡Ÿís¨ÌhvÓ±È8"5‰l³“ÉÈdd*2 ™Îצּ¬Îß®¬ÅçÍ@fòñ³ø¢Y|åڞdnºŸíé1f{z u¹Þu]_@µ^`¢Ç]Ÿ‹ÍÖO¨ ë'µ¯ŸR‹Ö§fõúiµrý aÀ¬Z¾~)¨#Ö/r3Z‰Ev¿iS¯Ín—¬Ó‰tIÖîVwÎ궠™dá³µzqõéSV¯BÑ´>}Ûª}úò©½z–•{õhSzô¸“ºõô+u«YºÔÊñƒì—Œiç¼Z Ù-ÄÕJ£Þ"Ž£Ž£¼8§3'2êÈ +€Ú2£GnM¶ ¥ÔÀÀ@1))$$y$貁~/ãë/Ò¾h)åëRžh)鉹’€RP +<»r¤JåR‘VIY>ÝïœI•XÛ5œ#Õ$£šžŽ¸>N>ïÅùùI–5bÅA‘#£8ïQŹFÎHMgRS>3PZJZŠ8˜ê#SMnŠƒ§ˆ¸5‘Z5å/Ñæ0ñB‘Œˆí,KMd2Z²˜ÜÖ¤1iß*g~k?Ï°«eÙßr0Rž=¯ÀîWìš”¶ÅV6È6X¥tédçìbívzIdéc_µçÙfGsëÂd2žýw2™„LF¦ð¯+#« SùÛU‘i|Ôt>t5du¾c ®$3YÓӗ¯ÉU®kq©«É î/›ÁMf3=éLn’„B¹ê™iµhfF{üÌ,±Àœš:3/ˆ™Aa¢E5FI[þZ­ˆ9kG:ÔCkt’„ÕU‘ÕºIÌêÑ¿N#|¶j¯ñ>`•*MîÕMêÕ÷®Ô£g™Ø£§šÐ­‡×TvªEc:é°µ| ]xÔß&<êm%ã¨ÇQ‘ZÇQ^ˆÓžñ´eÅ>­QPK¦¿¿¿˜îëë+¤$ù¤$g’dI&Я¤ýrÊן¥ ¥$´”ôô¡ Oô•À­xvk­¾¼|á0Pò†€Ò0gR9I;RÈ9Ž‘HŒ©‰õ–F< |Õ¤¦ÝØgg½ÕtÕÇ£ˆ ©~Îv“‘š²¢Ñ҈L5‘)Ž›"ð!¨8–j@âpë«+5 žÄÃ&–ÅÁ“ďE&£% Ìi{J„¹LÚ²’l^)©\Z@»}&,Éd,9|ùðšm‹vo ›Ôm<¤˜MŠÆ÷EÝúʱÝzŒ1]z Ñ]TÈî¤d‡ÚÑ×®¶õ¶©½=m£îVáQW‹ð¨£DH­ˆã¨€ã(å„=¥¬¨˜éíí-¤{zzò)I.ÕÝݝM" I&¡ÿ–$©@¿—òõI_„–ž>4áéãÜJn%·’‚’]Þl·êI½PúK—¦F©æ‰ªHvLì4J_ ‘e3ÍëñÕÌ=ŠÃ£š.¤åKBKõ‘)ÂM5á)BP‰,ɯ®ÄÙ«šÒJ2Åq“£%‹ÉiSò« TA)Á6–`C³jLI)#¥Ãšß"€ .¤lx³œvûŒ”'"VÀ{Tdû,…÷¥j£oe_mc‡m‡n:€ÎQœN5iÒ¤îQڄ{FMœ8±é¥¹@‘ÑȘªŒEÆñË㑠|€ÉD>o%6õI¸@L&5šLE “)ÔTœ試$pX™$TS¨Â8%% š’V¦d¬€j +刦äS +’ÉœÁŸ\BZÄ“Z‘6õÁJí$™tH&S4¾“Èá³ÐIÔåxHŸ< tqmH§ž ¯SÏÒÛ¡çëéÐ3w·ëé»ÚÔ¢ÎV5µ£…\ìÒرcÛJ"™Ö"!µd”‡ŒrQVìSÈ…òé®®®\ª³³3‹d’HB’FRþ5è÷’¾þ"éëoÐRZ +<Wàé‹|ÜJ>n%”’žÊc@ËÖ(Ùí„PZâvywíEęäüHqŒI®ªÉ#ZVŸ¿øëJM«±Þ(Š8ŽêãQŒٞšŒÔ”ˆ–j†ãj"SÜO‚ŠHdI~Õ¤¦©j*kTeÿ¨IKÞZ²¤oRù°œ•Øb‹-a5¦M)`9wîÜ$~ò5)ÚSl†i¶Å dŸBRŽ`Xž=4ÏnZŠQ‰m¶œi…nZ¶Qìû£È§¥=¹s”6ÿ.¤é¥ÍÚ¤éCú‘þÕdÍߚŒá£LƲ½›ŒÃ#2Ž~¼o¢'…¢A(4!×*i" ˜Ò3O àÐJMȨ¨D4>‡ä T㋒q%Nãۙ³V’ˆÚ,“H2ºÛA:,r&0'<4Š:ñ¯uèÛº!£.#£vȨ 2jÓÓ··ªEm-äb—Ôü–¢H¦ ¢›b2ÊAFYÈ(¥;::²éöööLJ’NV$•@I2Я$ýrÂן%|}@-ž>Ù÷„`>n%·’Ïhy¨ÇXz¸ï<Øc¸½ðÂU»–Í@Éîͨ J[Ô½û"Ž‘â҈ãPhD@PŸ¾ôRÓ*Ǚð8(ªIFKéBj2RS¾´T™jºšâà)Ž ª/½Ô´M#BɚU™- ¥ræ·%í[åjLV¶ÒªXZÍï9ܐ¢=/Áî— ïá={v +FJÁHi)^ù¥í3ËFšÅ÷òàQ<*@FEH¦â”Àž–QäӌÒæߊöév¤cT___gUºîªôð+½UéãoMúù¼~6úP@+¶üAßD¼J ḈøÑ \Wԝ2Ñ3¦êÐè ’U;)G4˜C8~?X fX⠔LÔèþ¤•°¢I›ÍÈ)j§v»9‰ªž¢vÊ=Eíú¶Ȩ2jƒŒZ[!£z¨Dv‰4ì"ÉFàQ!å!£œ`'—…Œ2Qº­­Í$jmmM%+’LT$è_Cñõ¯ %ßsùž>ÞiI_îáVò7aôPü-ƒ’Я|[½’ݺ% ½Õ¼g>Rá¹æ!ôÈQ«¸´™úØ3òå÷ù›ŒÏXêéšPTŸŒ"x´”a¶å󤥥D¦úÜTžâªQ©¿ˆ¿|2"¾ªŸV³„C”´=•« +X5&m^>ۘ’ÏÖæã (ß'·á†0RFJ°#Ú}^å«+ì& «×,4HÃHi¶Ô ›kD<ʁG9ð(Ó@œØS¥Ý¹4Jû´IË(a@kUÚFio¯JG(ú‡Îªtñg&Ý¡èóºÙò{<¨*¨Ê7ї‡Â‰¯P¸®83JJ|ЛÒ3÷¦‘ŒH¡7k¢ÆôæÄ4=y¤@à°hIÕH i±$"„t¢Îªt„N¢*µQϨUÒ +µ@F-Q©ET42*ÑCEµ#_ Ù¨ ¦æòQ2ÊBFYÈ(#J§MZZZR©R©”JJ’& IÂ$п&¾~9ðõ·>´ä{úP߫ВG‡yžžÀcÈ<ÏuËn%ï(<†£ðŽ"þ6ŠÉP%»¦Öni³[I"9Jq¥@©æqôš 4õaçó_ñŸ±,¥Ý3áSß-‹ ©ÉHMYÁi)™å¦8xŠ“š@õe–e¡ÃrÁ"´T”F… dÎ$%mT[V¹Ò·É.L)_%§M®|¯6¾_Aù/»«Â®®#Yaä(«E¨=4Énšb_MáŠHKƒG¼=ð( eašœ“‡}ò£´YBCÑ.^ªJKUZ«ÒÆ‡¢0éðL *¤Óƒª|}o($2‡Â)°P’z¾NŽÐwr˜¾“cõ¡pÔ¾3k"zèÌIì¤Y(Μ-½!Ѻ-s U¤¥…RFHÉAQKŠJøŒŒŒŠtŽ‘QAOŸ²àQ&WÁ£´áQ2JCF©b±˜4IJÉB¡HT$ôßBñõ˾¯?ó¡%ßhÉÓ'{t˜G7y0¦Ç@yŒ›7ªâVùŽ"þ6ŠáÅÀb +Œ +ão³fÍ5$QÉ@ɕˆ$s7 +J5¦(•fäñùۍÏX0×qPÔ(ÕÄ£eE“ú´4rdªÉM5᩾4ºV¿,2r ŠC¦š´Ô(m_­ý9̙äñª_¾JnÞ¼yå+x‘6Ø`»¬«\sÙ* Z1fm>…`”•!¤ !~¤Œ”d_M²Ã&ÙkS¸RàQoO<ʀG˜& âdÁžì(mÛ¹P´‹ç«R¥Ý¤8Dô¥ª´ }€I«gU…¢/jõA+"N¡× +çÁBI +SBIéqÛÒ&zú֌‰¢5‹äL8n–¯JÁ’ˆbEŠCĜD&Ø¡H’«’QÖȨ@òu¾JF9È( e!£ d%ӆGB!“D2ÿÿ³wPQeËÌ:Ž3cÎ9GÌ9aBŒˆEQ‚ ˆ("¨¨`BŜEŌ9çœ3æŒ9çљqæN¸÷UÕ>§O÷á4ÓHìWµÖû×]omÛßÙ»þ]{ŸÚ™3“¤N£“Ô²X[Ãbm ÂZ疬¬àC­ðDZn þr+*+!-+ä– +ËJ©°¬” +ѦBÈ©ôÊJÊþ›RV¢ý7*+Å}PI9Ìmêåª*£¤å‘ⵉô•îᛕøOÒFç{£"þöˆ=Kʐ„X¦¸}SÜæɉÿÐýf%^Ê·dªQRú|*]Ñi1OËzƒb’“¤^ÊÔ1úâÐÝ]Õ«W—Ú RÿðHôªxjLš©1}¦ÆDš=RôHiÐ#¥Á\›³nZ,!¥E”íQ:´GéÐ¥GO“-N4@RA'É(2{&CÉl(ß ÿX‘,$Vh¨ôþŽ,XHù )z‚'œ…¤o%_’ÜI–ôðí³dÐ ¾d&$ªFÉ,Kf’ï D*É¢oŠtÎ(3þ$äŒ2ᣌ$²=J›QztF(iÒÉÎ(MÚL™2¥Nc Ö©ubM"»%+tKVVðyVVä–ào“Ü–•Q*t´©°¬” +1¦B ©p5VY‰ößTe%ÚS••´z¨ÊJÊaÞâîrÿ36 ñߎ$d’Ž{ú;u˜{’?A²°J‚-“©æ)ñ¬Õ7&ñ2Oq»¥x%¥˜¤4:W.ƒ¡Å<-ëiOK}òHte)ݗÒ{Cɨ!™„ÀŸPIf+4TzQfkEà/ϜšëW$iHàûeNK_7s:à[eB2€Ð›f™2HÆL±Eß +ɒ>™"Ù¥3tFig„’†œQz4EhR§C?Dö(mƌS§‘Å:µ¡XƒX¡Q’þ¬•º%+Å-QY ¾A*t¯©T*D– +á¥Â-S3”•â>Öm´¬”`£dêd3ڊ”. ™¸MMlX¾}1á)Ž¿o2£úfå+͓Q·d‚Q2ZL2²á¦í‘(ƒÑ e5zm‰<u¬V­šÔ0‡Þ§Wžè-qz_¼D‰䑬SÑÛäà‘¬Ñ#YcšM 75¦ÞÔè‘R£GJ) z¤4hÒ 3"I‹Æ&-:I ³§S äýôzÿ?’ FÅ +½”žÀß!Ěþ^!©I°ˆE’† KÆ´ŠÀwΘNå%³ bKúŒ±%Å¡O$S¤çŒð'ÑsF²=J­gÐ¡X“3J“!C!© ÄÊZtKV$薬·[*,+¥B©O*•*~e¥¸O+ÑÓÿÓJZe¥¸·ÞTF)^)‘ Æ·#_9ߛšN’?û±°Ä[âe™lž,EÌ㠌º¥¸’V1é«6ܤlEy‹2å2Êj”ß(ÓQÎ#Dí©Ñ y$j>H¯AÑ Qôj½$…]x0¹ZcšµÆ„k©×“°5z¤Ô˜“S£GJö(5Ú#’4hÒ »‘2;IZ!òU’N-ðß)¢g¨¬HÐUé ümé­ %5±IƒÕ-Eð52=IGBç©5$ƒ,iÕ¢ø!Å8£Ô*g¤³GÖi ‘°GéÓ§'±"±VDg”¬Hd£” +ÿå©Ð(¥Â²R*D!¥—•âõ=ZÝ´6áL(+™`”L°GIæ-¾Eùʄ‘ü™Ž…Å|ò•Ã€½”é6ʨ[2j”Tg”Œ“T§·UnF=å-òH”Ë(«Q~£LG9²åAʈÔI‡zêPwê³C¯FÑKRô^9½8E‡‚ñ­sL½ä‘¬1[ã^›5z$k´GÖhR AC€ÆFHï$iÔ6@%i…ÄöRz‚N!–`™ÊZ%ð]Òáù紊àËcz’V~¿LHºØ’&b€´„üNÒ)ÎH¶GÖiI{¤ª霑¦GÒ z¤TBà$ѹ% %*+‘QŠY žý²’Vo¥$ۄÓÚz3Õ(ý?·BfœþÙ±üÿsœoVÌh™L5Jq“âu(‰<’jÃMñH”·(ƒQ.£¬Fù2å<Ê~”i£…rc‰%¤|©“È#ÑëR²G²JEǃñ 0&a+LÇV˜˜UFÉ=’5Ú#IÐ èŒRjtA&ˆ–ƒR›,+•`ՊÄZ,g‘¤V‹]$i E¥¦wÎdIM’NKT~ÿåiIg¤³Gi ì‘ m©ý»=Je¥ˆ†QÂ;U*Å(QYIkÿ̈́²=TVRÎv“±6aη¤´ Ð:Ûÿ²R¼,,,)Vâ–L5J¦“âCI*¤u(Éè†åAʈªb’–Q¢R„l”¤ÔKI˜Ò1%æØ¥XnIË2˜'-‰UŠS¬HЕQR‰Î#Y%H4<’µ,©ÐiŠÕ¿Kª¸=’Ö֛ÖA¥ø—•ŒnÂi]÷•]–ŒY2º §*+™j”Øo°°°°˜*æ6JF‹IF7Üâ~¹‰›‘ +¨b…´übŠŒ:#U I呔:’jÃM呌“T 'öQb£ÄÂÂ’Èb£¤å–TFIkÿMëX·–[RՖ”sKq[&•oR™'•ƒRÙ(ÅKi‰’WYRª…§‚¬X!Å)¦HU32ꌔ’Ö^›â‘Tnª#ܪb’Ö®›Ö…oÜG‰………%‘%!¹RVÒڄ‹Û-i˜T–I围̓â T6JñRZ¢äP–oNŒRUÑWù!Å™àŒT%$Å#)·ãöHZïºÅ«˜Ä¹YXXXE’â ’ª¬dô%8•[RÎ-Åm™T¾É¨yRD±QŠ—R‰ÊZÅ-J†eI‰--ܪ'Bå‡S¤ÚWÓrFª’ѽ6•GÒÚpÓ*&ñ® KÒJ‚÷ßÌã–Tç–L°LZ¾IË<©”b£T¢dD£¢²[,)ZLª2@ªú–RLQÜÎH«„”()Á»nl”XXXX▄%­²’¹Ý’–eRù&U½I1OŠ(©Må¥T¢¤EË£€êQQ=Hʦ¸u-gdª=ÒÚk‹Û#™PLb£ÄÂÂÂbnI”²RüݒQˤª2)¾IË<©”ª¥ªFÅ-ª,Éò ‹ ¸UHË +)~HË©œ‘–=úJ”à“Iì‘XXXX"f,+ÅË-™j™Œú&•yR9(•Ò2T_)ªÌɒb$ÁhµžÕ#¥ø!-S¤8#UõȨ=Š¿Gâb KҊÖšÈnI«À¤²LZ¾IË<)¢$*•—R‰ÊZ}¥h¥O–äóPUy•¨ž0Õ󧪩œQÜöÈÔ½63z$6J,,,,ñ’x¥„¸¥¸-“–o2Á¦éOÙ²çȑ#'DŽÙ³é°*Ty¨¦äЛ|)SD +>stream +–(­r¹0†!Ôì¹ò,Zª\åjµضhݾc—nN½œ!z9uïâؾ R­Q¥B™E„Yⴚ2#ÔBÅJ•·Ù·©][‡ÎÝ{:÷éÛ·__—>ÎNÝ:uhc‡Tm*” ,¥U.§ÀЀZ ÖmÜܾ½cW'gW7ww×¾}zuïìШ֩nS¾4˜%J«¼ZM‰¡,i¨ªÔ¬×¤E띻SO¯¼<=Üú:÷è"Q­ŒÍ§ÕF ÖoÒ²CW§>®^Þ}}úx{º÷ëíÔ¥cۖ¶ jW«„f‰ÓjJ ½âƒÔZõm[¶uìÖËÅÝÓÛ×oðÁƒ ÐßµSW‡6-›Ô¯Uµ"š%N«)4ô+J°N͕W†j×α»s?¾ƒý‡øäãéÖ§g‡6-šÔ«YÍRþ<¼ZM™¡_ûÅâCAp¿0ýÔN=z»zúøù  +æï7ÐËÍÅ©‹CëæÁ—W¥U¦š‚B²¿ +Ô¢°¤‘ öqóò4bdpðÈAC|½Üû8uî`߬š%N«)6äùÖ4Y²þ”#O"%ËÙԨׄ ºä8bÔè1!cFæï;À ¨¶oÕ´!š%¬AäÄs\Na¡o³þ˜#wþ"%ÊV¨-Û"To¿¡AÁcBǎ76dôÈ@ÿA@µG§vv¶ Ð,QZÍÆi5ŅjM“;áe+U¯Û¸E[G‚0bTè¸ 'N?vLpÿ /·ÞÝÛ¶³D5]Zå½Õ”zN ío¾BÅËT¬V§Qó6ŽÝêàa#nj6iòäILJŒ +êëåêÜ­c›`–*—+%¥Õ,œVSVÄvJ¥+T­Ý°YëŽÝ{Ԑña“çN Ÿ2iBè¨áC}=ûõê +¸Q¬ApZM‘¡ç”¾“œØßMíº9»ÔàÐ “§MŸ1cÚÔÉǎîïëÙ·g—­š6¨-¥ÕœœVSZh%UpJ¶­:téå:À Nœî½»9´Ö¥U<²¤š€­R"Õoø-u†ÖïúÍTͱ5e+QRíÞ§ÿ a£ÆÔÅËV®‰Z»6jõÊe‹çÏ +Ÿ0&hð×^]:´RV«â$°~ãýy7µ~Ão]kh]whîúmî°2(*Ñ¢¦bµ:[¶ïêì>0 xܔ™ó/_µný†õë¢VՙáãG‚YêٙҪ´·ª·®Ñ§ª‡Tâ©×ZêúÍTÍE¥¹qQS¥vÃm;÷róö9v2B]½vÃÆM›6®_ Tç͜2.8À·?¦UQ–Óª²®±6œx•~ßô"½è–{¹›? æ_iQCIթ߀!#B'͘·xùšu7oÙºe󆵫—E̛1y,˜%L«öÍÔªZ¡tq: ¬¿®Ñ¿ÞF¿9´è­4‡æ¦ß‰VúE%±¨©T’ª‹§_PHØt„º~ÓÖmÛ·oÛ²qP;=,tøo7±Z­iS^Z×èï×ÄF*šCgÖõ†Æv³õ°2Us†Ö¢†’joßÀѧͨ6oÛ±sçÎí[7ÕEs¦M„iµSۖëV¯ŒåBÃ3£©•ûP¨çlÑî;‹®;t–,Ôô;£Üš©š7ôæ_yQS¥%UpJ£&L±°®iÚ@Ú¯ÑunÁºB:É áÄKݾ±5´è /_^ì °J-¿¹‹¥¹CQ#'UX©¶éÔÓÍ'`ôÄé󗮨û=q¨nÛ¸fÙBH«#ý}p]£š€3‹…ŠdD·o@š‡ZC”ZCȟOjùMTy¨š=b%UZ©Úwìќ҄ió–®Þ°m÷ÃÇNœØ«ŸS§¶-ô&`ê܂e¼[ CÃ0ÅÎÐyóÀÎТ5tÑ"… !V¬@5Ëw†C5¹Ë1ÿâN¹.©V«ÓÄ®Cw¯!#ÇM»dB=rüÔé3gNŸª»¶®_¹dÞ´‰£‡ùöïÓ]LÀà€ Š ø;ªe”³i¶ˆ;C+¡ßºÜñû{Uoèäþ9,#¤ùWo¥Z¾JíF-Ûw§4|ì”9‹W®¨GOœ>{îÜÙ3§ŽÞ·sóÚsÂa]ããæl8ÿHÞ'“(6dUš}+Q²Tì M­¡K–(V¤pÁüԘTš²ù”©YCIªb¥Z¸D9›š ›·íìì1(0dò¬E+ÖmÝ}ðèÉ3ç.\¸pþì©c‡öîصláÌÉ¡4£֕ ²¡£ý.³Xšþ˜ ™¡Ë–¯P±b¥J•°3tÙÒ%±áw~͆ßÉý{XF¨’*Åò8¥ÃÆLš¹p9B=vê셋ÑÑ/ Õ=Û7®^:º˜€ÑK5à|Øg–ŸXÌ*¦Þ| Å^ßrch]gèÔƝ&`>åoþЭTEùW*?Øwtêç=tÔÄ –­Ý‚PÏ]¼tùòåh zôànH«‹ç„Ç ¸WçvX/8æBï“õ{º‰*;öo—z}W²©Z­†ÔºZ›JåËUƒ~ߜTͪò¯(?4±sèÞwØßéó#£6ï:pìôùèËW®^½réÂٓG÷ïÚ¼v¹4÷íѱu³†µ¤¾èhñþ¿Ÿ¤©·hñRe+TªR­FMê -5†®R [)ˆÿ½ÞüËPÍåßì¹tN©[ÏÁ#ÆM·t€zéʵëׯ]ª'ïÛð<œ€º÷îÚÁN>‘/7~ +L½`êŶÐUkÔªSÚB7jÔ°~½:5«W‘Û}çŠÕ="¹ UùՔz£ý Ÿ»dõ¦õÂ¥«×oܼqýêå gŽÚ³mýJtÀ#† €Å*z¥jظ¨æʑ=;óˆ–üå+U©^«®ÔºY3ê ]·P-Wšþsýî Õ|aTÑ)‰šRgg÷AA¡°¦Y½‘ ^¾vãÖí[·nÀX=}ìÀ®ÍQËÌ 8½’Ø/Ç.wùòäʕ3-N!–­P¹*vúnÒ´y ;;ê Ý̶QƒºµªÙT([RôšUšG0TóE,§„ö·©°¿!“gG¬Ú¸cÿQ€zýæí;wî Õó§Žà¼dîTðJÞ®=;·mјÞZ…5_Þ{âО­ë–/š59$ÈÏÓEª+U(S‚®Ã:/®d V¯]¯‘ms»ÖmÛwpèØÑÁ¡}ÛÖ­Z4mT¿vu› +4]¶še¨æ +UMI²¿­zàš&læÂë·ïC¨7nߍ¹T¯\zTo^‹>{üà®ÍC–50úJ—,Q²TÙò•À"5´maßΡS×={÷éÓÛ¹—S·ÎÛÙ·°mPÇu1÷6Ø(™1”B!žÍWHZÓtŅêøió—­ÝŠP¯Þ¼{ÿá£Ç=ˆ¹sãʅSG¤¡4ˆvkš5ÄDY®L©R¥J—)‡¶·nClóíØ¥G¯Þ.ý\]]ûõÕšÞpe¨‰škšæmi¡:nê¼H„zŠ >züäɓGîݾ~Iª`€ýÉÃP­U­r…òe˖-‡—‹Ó¦-[wèÔÍ©w_Wwþžý=Ü]]œº:¶kÕ¼±~ïÊ,¼¤1¨ ,^¦r Z¨z ÂêÃÒ¨-{ԏž<}úôÉ£ûwoŠ¡ºnùB\«úzЉ}°?U+WªP¡BÅÊUªã](-ÛtèܽWWÏÞ>>Þ¼<\]zuïÜ¡µhHªw¸”¡š;ä}ò õªÍÚtêåîª@½uïÁã§Ïž?{úäa Õ;7®^<'|ìˆÁ^}:ÁPmP»nÃØT©Z£61uèÜù¯»§÷ÀA~~~ƒ|}€j§.¢w0CMÔP-T +]©z½¦­j`è”9KÖlÙ- >|òìù‹çϟ>~C ðž-k#çOŸ0 +wË»b“ÑzµkV¯V­ZõšuêãU(]zôîç1` ßÿ¡C±u°—{ß^ÝÛÚÙÖ¯UUõ;z¹ŠÍ¯YÃ`¡*ªÕ±§ÛÀÀ„ºYúâåËÏp¨^‹>stßv°J3'…ê mÖ«S«fÍZµë6Lz»ö÷4; + 2È»?çîRãJ|¹*_îìâ=H¨æ-¨¶öŽRpÉêÍ»PŸT úøþ—ÎIóXÖïÙ¹½}ó& ë×­S§ný†MšÙµ¦}Ü<}ü†ùêÕ«—ÏŸ<¼‡óï¡Ý[¢`©J›å؍ҮY“F 4hØضy+ÁÔkà€áÁ£CBCCƌ4t·» 5Pñå¾çMb„RR’ê„2Tu“ꋗ¯_¿zùâ飘ÛW/ž>²wëÚe fй—ÚÛ·lfÛ¸qcÛf-d¦¾CGŒ7~„ñãBF6اߞµ>A,Z0oÎl¼¢Iœˆµ‚Q¨¯^Uš¯ë%Uz·±‹CÛV-›7kÚ¬yKûvSÿÀà1ã°Ã줰‰ãB‚ƒüb×JÝ«­òä”Ì/û$s‡ #ŒÒí˜GÏê›7¯_>üà,jŽíß±aeÄìɡÇ puîæؾM+»–-[¶j­c:>lJøÔ©Sé)6˜•¡Ò±RÅüò@5oÍ©>ºœªƒú† >yp÷ÆeZ©®Â•êH÷>=ºtl×ÆÞÞ¾uÛöŽè{‘é¨Ð “§NŸ1sæŒéá“ƇŒ D-ÓìlñüK‰"ùs³OJ¤Ð\ҀûE£" >uñÚíûŸ½|P_S¨²ýÅsÝû»ôìÖÉ¡}Û¶mÛ;8v¦žé؉S¦Íœ=gîÜÙ³¦O™ˆ}ð°aÇó‡…Éüêù¤äþ%,( Ϊש“¥uª&ԃ;7‰ó0­:wïâèСƒCÇN‚é`>cöÜù ,ÀF¤“ÆaËJ€Ú®e“ºÕ+•ej.Ù'qJ5s«(õt“+J{ŸVA} TuÔ°A^®½ºuîäèØ©K7§Þýúû D¦3çÌ_±xqÄÂù³§O?šZká–zjqE#™_ž}͆‡”òjÕ~Ô;:¨"§JÕ_Õo€›K¯]»tîÒµ{OdŠýÚEÒ¥‘‘‘K/œ;3|ÂtTjU\¦¢ùeŸ”(¡±õ¦·K3/2 +÷S£¯ßyðø¹õ™Îý¢QPÝû:;uïÖ­{`êáí7ldèÄð™Ø…tùŠ•+–/˜?[çÔÕ®ZW4ÂürJ5¨7Éq?µ¡þ~ê¶}GÏ Ô'U¬S¥âï<þ‹P½=úõîåÔég¯>ÀtPÀˆ Ètéò•«×¬Y½rù’…s¦‡Q¯ˆžÚ6oX«Jù’’ù•|Ts†Ö{oòɇ‘xòaݶ}ÇÎ^ºq— ¾F¨OÅܺz‘vTW,š=e\0BuuqîÕ«—300hèð1ã§Ì˜»héŠÕQëÖ­[»fedÄ\©HÏNm*.S *—#ôV4òÁ³*µ·ìÐÍÅkHð„é —¯ß¾_õ– uµß=[Ö._8k2.U¼û»öíÓ»w—~´@7y:2]³nÃƍׯ]½|ñü“©ôïäئYƒš6åpEÃ>)‘By—\uD´ï€¡£&ÎÄs¿ŽŸ»|óîC ªn—´D.€82 ºõsqqéëêá5pH`ðØ°isÓõ7oÙ²yÓú¨K̔¡¶nV¿Få²ÒŠ†}Rb„ª•ò.£«OÀ˜I³"VmÜyðÄù+7ïTܤÁz>¤TôI«—Ì›2bè oOw×~}û¹º{ù 21|ւ%+”¾†k©«–€Ú±uÓú5p™š7'û¤Ä‰XM'ñˆ’´¢¡ÚƒØy»"m§¾ÂMò÷ðýÅþ;c†T7WW7OoH¨£ÇO™I½*±­á®;¶m^¿:r¡€Ú·GG{ÛzÕ+•Áe*CMœP·ç> ͯ‡ŸrîìâÕ[1bü Ôû° 9wâàî-QØ~güè _oO77w`êë8jì$H¨ËVӝ»÷ìÙ³kǖ k–¡£"¨­lëVÇڃþŠ†g_3†ÒȎnœÏ] H)< Oï§!ó»vÛÞ£§£¯ÝŽyP!žMï{ú(ξKçϘ468pBu¦âÕ§Î^¸tÕºÍÛvíÙ·ÿ¾=;·mŒZ1_}ôêÛÝ¡U“ºÕ*–Æe*®hØüš=´Z®W¯k+½J3q¾Jƒæ÷úûž>¦8PïÞÀ/öl]³ï´‰!#àÙß™ú‰Éwþ’k7mÛµwÿÁCìÛ½]êèP]jjX{àMâ„n êúˆ–}D¥Fä“ÐüÞ ¨Ïñ,!;;{œÞQ¥ÙwøP?„ÚßÓËg¿p¾‹–­Ù°u×Þ‡Ž9rèÀޝ[Öa—µƒV Ké/SÙüš3ôۈ~O·XSw|‘ÜcP¾H¾}˜ß»ê3ÝYî}Û7¬¯ÿ Ÿžžž^Þ¾ƒFàÕ' –®Z¿eçÞ‡;vìÈ¡}»Dëq#{¹t#¨¢ ¤¿LMîŸÂbB5P¥ /ê6i%:žÉoÒèŽr?{F•ÞºØ½eíòEXÐ1l°¯·0ÅÉ7hÔ¸IÓç-†Éwûê~'7¿[µx.Bõ¨-צ*a.†ša%Y_ÃKTkbçžøÊqØÌEôvê™èkõé3ù¥‹ÓG©™Çü™“Ǎ‚Ù×ÛËËk€Ï !’KŠÄŽ†û;yêôéSǏÜP—̝ŠPûtkß²B-œŸ +JªyÃ` êß &f_êø° R*ø¤Û1?yúôÉcz=ê½JŽ6),tdà˜}ª·¨“gÌ[¼rݖû;yúìÙ³§O;´w;íÑéA-W²°ª ”Ü?†…„`*Y_q1cñ²•t¹aöµe÷á“çÑ'!Ô'â@ÅõÌÎMk"M +€Ùw€Á@]¶fãö=ÔûîüùsgO?¼oǦÕK%¨]j­*r闗©æ +Õ@͉µ|¬s§‡‘MÂÙw€2P—¬\·u×þ#'Μ»pñâ…sgNÙOÍd¨-Õ²a¨‰zL偊 «×mbס[OÑCT̾”R* Ô«¢å®gÂ'ŒEª¯z nÚ±÷ÐñÓç.F_ºM=Òvnf¨IVºÉ—ne$ë+ Ô6zºz5a:xß-{ÄìPñ5r¨—ÏQDZžä/l’¨c'á@]¿u÷£ÔÎðʕKϝ¢¾K‘ó¦g¨‰ +SÉ%‘õµkŸþƒ‚B&ϊX¹a»<ûRk€‡1Ò@ÅÂâÙúU·F¥ºïð‰³.]¹zíê•KçOãú'*rþ´ñ#jb†Siò…5j© +b Š[i¦Q_ƒ'Î^‚Ù¡>zHõüÉ#{©ð0C¨Äz‹I“¦Ïë‹Íd¥n†×¯^¾xæø!XÔ.C¨Cj⅜PÉùÒä‹͗£;É!£ö2i,R·aåá +;4P£Ï?¸K&`ÙW¼¥ªï,¼cǾ#'ÏE_¹vãæÍׯˆ^ZT/ZÒ0ÔD…)&Tiò-^¦bµ:âöj¨Ø@mҙh1û>’*Vifò8¨¸F¥ +!Ù¤is"V¬ÃÁgD3ÃÛØösðÖuËLŸP]¤u*C5sXé'ÔLße¥É\’MÍúMí¥+q ®Û¶mÒõÛ÷ª®…L¦¸;>Q7P=qö¥õ Þy²êÕ·îܹsûæ5| °é@ f¨‰Vª„*M¾e+ƒKjÙ¾K/7°¾ÓÄ@=vl’˜}q b%¥B(*îÏ (lÒìEË×nمJêexçÖu**n_¿|ጉÁþtµ_éÜW”̱˜þ”#M¾Uk7jÞÆÑ©¯×àᡓEFÕ¨°F½uMj6i°‘Ú¿?;Á¡aÓçá•'ð§Î¹ºs/æ~ <´¡¾}ý +€:Ê@_Üz“ +ú Õ\!˜JU)¡æ+T¬48ß0ùvëãá; ¤–Üú•ZÉ™SÄ@õêïáÑ7Rƒ$›D=Ÿ/J­ ï kEo².š6j¨wßî¼õfæ°Ò1•M’”PÑù6±ÃÉ×Ûä¸ð9‹qzä”ýiò§£cX!D#+N<„…Žµ?7ó–f߅ËÀ&Á£péÚí{=¡bñ<ÐthצՋgO3l [OG<"*<ã3J_Va­b*V¨˜Pë7mÕ¡«38_œ|#V®—ýL¾Àô±d“äáb zz¸»¹{xùÐì;m.^"Få +ÜÕyB{êØíÂÉû7¯Y2gJH ¯[ÏN­›Šs¿yrü¤ÿ~S5)¬¬b¥;àÓ +¦Y~& V¨P[¶ëÜÓuÀp¾3¥‡.é.N£O°ì+Ù$ù`(T¯þînnîý½–f_± +Š†úP42|LçIOÞ³%jéÜðРAî½:·iF'ôՇ¹™ê¿…Ni¼‡™fý‰LRÉr°BmÜ¢­c¾ž~c¦#½É÷‰ÞFª´ž‘å{¸!Ô¾8ûŠE*SgŸÓ!a|EC´\Šœ7uìp?ç.m›7¨‰ïÒä͙-«þ»4LÕ0ÔcR'ò”¯€OOדñ%“T­N£æ˜P=|FM˜ +³¨´Ø¼N©O±<‚Ù×&vâKQ3' _µpÇW-Äì»JÚՑû¾|þTn¹´miï­]‹†µôßzK§»èØܑÜXâÿþ/RãD „TaJÆM¬P!¡ºcB2{•oÑùÞ¢ÔA†Gw0t.†úÉïÏxù 6g_X¤î¢MØJà¾MõâÙcê$plÿöõË Š¿åõÞO×÷% +ÖoñWàL“FðL+_kdš§™¤šõmq… + u%Ô¨Ít¿¬Kî?Ô?zîÄ!Å& ñµŸ«¬R‡Ž¢Ù©‡OÊoȽ†ï²bϏV,’JJv´P•Þ»È$®ïCª‰Ž#¹ñi„1z±BtN4}zéji¼²«ƒ¥ËÛÔ$“äÔÏË/ˆêjÜ;;EçÈî ßypïÖµhqsI¤°I~>0Pûõsuï/ºÑ;h“DϏ·oވ·Î¯œ—ª£¥…j½ê¢;‹®…3PMÇ¿&¡‘‚¹§™Z#œéÒ ž4c&éø칀)_a’\ú6z¡Ñ%T` +v‡ êŽåc5i"Ù¤þî®Õ4#CiöÅ=õs—é¥óWoÞ¾{÷›~Ü¿}õÂÉC»7ãB5ªðUù­cùþ>Âjî0Î6¹QÊ¡æiä’&MCœ‚&ò̈7K'ßž™‚ñ•MÒÀ€àñáTèÛ}H:l†Lå·o\&ï+fßQh“<`öíçF¯Ž?Eš}OQkJ¨oß½÷î ö\ºƒöW¬iÆ òpîÜV×ôAºk¨¦¥/`ՀSV}¢j~Ê «„ΌNºW:‹¸²¯7•˜6lfïЭ·»ÿȱSf-\¾V®ãßE¦/ñ5ãç¸0¡¶ùRC\¤úxŠª?ûîØLêãòêÍ»÷Þ¿ûúÅӇwÑþòÉ_zEJ´†Å[jºtêA‚Cÿç1$›2°ê!Upêó3Œô +N™æwx«ô÷Y³Òµt³t‘âÀ´Zí†`|Á$y:i&í²ˆêÝûÔ´ùµèÚsëšx%u•AC|wÜǏ¼ïyö›ôôåk`úñÃûwo^>{NIgƒÉ)µ¢wÉE}¼k±¦Oûßa†0 ¬€M~¬ +R ¨a¦”"ƒ^N¢™õ‡~ü‘.¬ÅÛM *Z¢ty`Ú i«ö]zöó,›¤í’I"¦ÔbGjÇ".Z)*þà}Ý]]]±ò0DTVH³ïí˜ÇÏ_½¦?Õ·¯ž=&§„û4‹f†¡Sê)õg) C5WvA5SƌÌz?Lz]lòc5@*ˆÊ>VÂ'E&%äÁù= NA3[6¼®6g®Ü€o7-S¡ru`jÆ·¯ç @2I+×oÛsøš$j®ö­Ô¶î&–åu)•4înn4PEåa‰Þìûâõ;`ú3P}ûúùᔰ¤?gJ(&Õ.íZ6ªS­béÆë²fùî»Ì™3™3ô~–Œ2dA6Îi'#UC¤PÝԊø2 „ºÈ’E¢©œÙs Í\¹sãݦùÅ­‰e+Ú@>¦œ\úûŒ’MÒAa’h¥ùöí»·oåþ¾çN¤]7<LjP=ÜÝÝi‘½Ln[¿†MùRt/nöl?þõûï³dùÎÜ!ý6d"+qMf¬2SRÝÂ$³Â"«.ð®w18 'Ñ̛7_¾üù ,T¸HÑâ%Ä {u‰iCƒÇM™µHg’d¦ïÞ¿ÇeÉs¬õÑV7žy˜1Yîò@güÀ&M íqÜ ¹x©Ïa þüéóçϟ>¾ûòÙû7.9¶Ϟ͘8j¨u²kD×誹rdφ÷Óg5g|¯ ü‰¾3‚\e¬ÉCU¦¢hKµƒLÂÆÒÌJü~$†rÐD+N›ùòš… +ÏbÅJ”,U¦\…JtsW³VÀ3`|'뙤›ÔÝìÍÛ÷ï?@V|óRê™Ì°u‡—g:¨lcsˆ»žâ@ýôù—_>ÃP}ûêù£˜›¢ãóʈY“CyôîÚ;®Ó5º…ðÊëœ9²gϖí'ó†ô»ü@‹˜ l† :¬ÉDU7Le¤¢v…l¬œ( 9)rI3m^16apÍâÅK”,Yªt¼_/c«Û IsûöÈÔÇDè¤&é1Ì è_%‹ &/žÑïÇBç}•—-t4Wpö}õöÃÏÀôW úñÝëOäòÃ|q$]N߶Ec¼™±LÉbE +â×¹s墯žÃ¼?N6|\.%®3ÆšlLEžj´.ɦK”"¯ˆ|4Ñ(XPŒM¤Yª4Ðœ*VªlS¥Z º*¼e›]œ\€éðÝ9@4I2ӏÑê¼{óJ@ў°¢‡¸‡öõñööñoEџ¦ šk·ï£Múøé—_!~ùôóû7/1©FŸgéÂé¿:5l*–-U¢X‘B ä‡/-¾}sþ8ø¸Þl8Ç#×̙ÅÂ8™¨*L¥í²Ì2Q\—H3+òC‚" +aÆ¡ 3-Òc³ÒÄ«õªU¯Q³vz 7maß®cמ}‰)Z+Ih|_’}%«ó¡ÆÈPéÀïøÑ#† ñóõõ4Ø?pd½…6é8ö¥„E* Ô_ûí·_?ãü +UºFadžU³uNµj +T«T*_¶TÉâŊ)\¾xAóþ0ðûÀãxqŽ—¸J£5Y¨ÆfŠH©v]¬”'¤À{†‹—(A-ҔÇ&ÀšµjÏú 5¶mÞÒ¾­CçîÎýúLñm Izúâõ[d +Nçg°:¯žËPqú]0sʄ‘Aþƒ24pĘñôž1¡!Ú$¨¿}ùò U˜ŸÓJçߨÈùÓ廉ÚáݸµªÙTªP®LéR%K”À¯^̬?L|\ +âTs}H=&ìÛ± {lϞ>9l„ æL¦‘«°Éƒ¨’MúM†ú›˜ñøÃé 8-té*g§®xëTkûVv-[´€¯Þ̌?‰­mx^p*¨]«Fµ*•Á“•,^¤Pþ¼¹r¨¨& T+ƒWÓè”Xn¦ÅJR\hÖoظ ^hGüZ·nƒÑ¢]»öí;Lyd:÷F–nîýñÎ÷° @‹3qÊô9 —®\+1•Œï»Ÿ”éSŒ4X”Àüyú؁][ׯ^¶xþœ™Ó§L™>mÆìyÀtÝfJÈWh ’M¦ÿ ¡úQX%©÷ݺ‹çRCÃ!½ÜûöîÙ½kgǎÚ·k׿|óü&öð¸ØáU‘M5¬_§Vª6˕.Q¬p|¹s"Õ̙ôÓjRALé5¦œb ´, ­ Í&M›·l%Æ"ðsìÑ¢ D×®x?Œγ82&Öó|ºÒV!ÃÀàŒ7qÊ´Yó#–­$ØwãâUÉø~ ïŠ#í÷ßå•æcêzâÐÞ›×­Z¶xÁÜÙ3g̘1söÜ‹—Si ã@}ÏÄ/¿!Ó?‘ªn¨ÒS½w֒Õ7zx€ß@/×¾½{õìѽ[·®ðÅ;›/ð÷èä ÞØ6¾¸‡ù77WW|^œ{9uïÉ»]s[¬wT._†¨æPŽ½% TÝ@¥É—^y)HL«×nФ¹]›Ž]{ôì킧Iˆß@¬ÙAøA ¾öT³E8Ɣ)“ñy?.tLðˆÀ¡~>žn.=»vlk‡T+—+U¬P¾$ª:¨Ò@Å÷ ËVÂ㜭Úu½¿€áÁ!ã&L‚ÁHü`f; )Ă .B–Ò¸D–ˆrÓ¦Í[¶nÛ¶}ÐØ»ÿàá£ÇéÅË×ðU~<éðîÃÏ:¦+êx(ûÞíëW¢ÏŸ9yìÈ¡ƒöC8tøè‰S0Ò¯áKÆb‰ ³·îÄGP^Æ ¦p¤zöäу8‡o\µjÅòÈ%‹#-\¸¿ø<óüsçÌÆçeÚÔ)a¼ƒƒ†úy÷ïçÜͱ]Óµ«U* °ª“æRtiöM'.‘Ú‘U­ÕÀÖ˜övÃ+ò‚CÆO +Ÿ>s¬+ÄĺoŸ\±‡%²”anÞº•PîÞ½gïÞ}ûwFû¾Ý;¶anŽZ³zÕÊ˗/Çoi¾€ßc =/óaM==‘êÍkW¢/œ?{æôéS§OŸ9{^»‰³72¥å4ùþóQÕMÀb´?Œ¹sóÚ¥ gO?zèÀÞÝ;wlÛºyÓÆ Ö¯_‡Wrš/àçX³f5]‰>fDÀ /WçnÛ´h\&à’b¨J¯h%v‹ƒÙ÷Çì¹óQßÀÚ ›·vèæ L‡ã5Âs.Ž\±*j-Å-[¶BlÃؾ}ûŽ;Ÿܷ_ŒKT€ï)8sæì¹óÀâÒel Héå +±ª0•‘ü‰³'!y‹ïš>Œ¹{ëƵ+—£/^¼páÂŋô!·ÄcA¡›|ÿùGùí¸1Tñ¦¢[×Åp?~ôðÁýûö`zÞ±¾ô6³þ[·àu7¬_»fՊHðÚ3Â'†ŽDª½ºâYšÚU+âP͕Þ¦L‚ù×Jº„‚.ÕÃû +Š”,g#½DÚÏËû+L›º¨õ·lݾc F{÷aP²Ãa‰,Ò°„qyöܹóˆ!:ú¸z€Þº}›t<a +S/mÌ0HÄZU¢úäÑý{wnß¼qíêÕ+W®\½v]<žH…d•O0ü|³ññƒ˜;ˆõâù³§O8~ôÈáCÀ½ÏŒ?ÆÞ=ø¼ìؾuóÆõQXڜ=- ·‡<ûõìÜήI½b¨æHªkÑ­”+MñZ§¼…ð¶˜:Øc®ž»‹7ÎF®ŒÚ€7äícñÈLrÇaTâ°<%†%°$’ˆòÚõë7ç­ÛwîދÁþHOŸ¿x<èPÑÓô'` úßöø ¸ÞºuSþ@J…šé!ª¿‰R3¶¸ƒãý’˜ÇOÆ+fžám¨¯ßЛLxÌAÍTœ}!$Þ½}ý +_A~òø~|Êk¦úC]÷ øâÁ@ªx6†üև÷cyãú51—_6gào ÏËùsx/Αƒ{wnÝ°f9vÉèçÙ·‡cëf è²ûú÷}&¦S’}’|O­tW—]{¨ôfðìEÀtÛîGŽŸ:{܊†#Æ­[8(iTJ,‘äc¼äéSìàðüù‹/( RDúIBªbª?Îh»+b}‰ï–S<Ï|ÈϪ¡þßÿƦúÇÀG¼yýò>4àïÞ½sçömüÊ7Íðk\¿~ §HÞ§°Þ±m#Þá>.x¨¾¢Õ¸N5]‹‚$Hª:¨º{jñ¦Ä¦ö{H±¥ù6¼Í/ ËC!ÅýûºQ‰,‘$‚Ä8¯^½zýpâËûï?Ð9P<¹"•ÿ6ò_%­"U|‹°¾}óú•òsñI5Ôÿ«þŒ?c?҈_¾nŒY H44àìÌIÜ4Ü°_˜ òótéî`o[¯F%ùbô$¸íÞJ¹|˜R*z_º¨§›ÏÐàñØçh=Þ=pê¬ûo¢‡½/O«"ž¨%’Dï ÞãK2xþþÓgÒXÃԐªëÇïß¿{÷ö­ø,å¹ÀX-¦JjÖÿˆwødXòOŸâ×}lÞ Žÿb* ¥õ9Ü +¦«!§Žö÷víÙI¼"[¢pþ$ºÅU6¿ä“¤ Øê4nÙ¾ko¼°€zâì:pô–\EßÖ'às/Ä˜Ô JA’@"J„ù3¾ÿŒ¯»QÃéÿþ÷?="‰]8:]øéÓÏ?üøáƒø0ù¹øë¹øßÿ´?C|ÄGiÈã{ê/ÌÏE`§ ˜ +ÜÇ:RÝ¿½Íè+^‘­]µ|©"ÔËï[N›PŸ$_éÐÝÅkðlŋï­ÁnØ9ð±°<†#…4$” +H|¿ð3Òžx^Oçêê˜þ/61X @ùüù“ô\èþ©÷ÿûŸò!†Ÿ!?اAÿÆÌA¿Å+1Ç?¦*V4žºÀÖ2s¦ŒN~Úé.ÑN’›Ñ ÌoμxYWzM[;:I÷:EŠ÷V¨ï#Zh¾¡©PŠò0Ò“2G +:ü‰‡¨ !¯Nÿ«D!" ´?ð(@ÁSÞÒ穞‹XaøŽy@+úïÍïDöÇ.$â.³ãøÎtäüi`þí׃š9a/SUÛË抅ß|…Š—­\³A³6x«Þ°1“fꮋÁí®§/^ ¯Båñ¨“2JGÁ㊻áF*Dä&qų£Êsñ»ás¡ùò`•°"×ßèÉø¬7ì6s|¹ûsá^°¸scÅ™a£©™ö2Õk{™DPÓT4¿Â'uq–î4¥kÂϊ¾ Xr¥÷Ó@Ý2’zEà $qºá/±%£ÉTŸˆ„¹"ý#ÎçBë3þž 1êՍ|³Æg‘»ßáVÂ×F6®Z<{r¨ÜÌ©¦ÞG‰ÝõÝpE“¿pÉrUj7ŸÔÇRêÔyK£ä×{éõ4\÷þE"¨ GJ}Œ:”N=¢ŠCÒ$¢CB`ÿcðiq?ZŸñ ìïb܋øÍÌñ«°ÚØˉH—Þ{;ܯï®íZè]ãšø—nèC¥MùªµÛuè¦M8½Þ+¿ö"e6õpTPrüKÁ)5‚T&"#ù[ˆÐ ž ­Ï½¯ú»¹ƒr·Ák{Göên'Ã^¦Iz5ºU,SqEÓÄΡ{ßþ£&ÎX¸bývl®€¯÷¾^{ùò»þXTÈ?Õu!îå%¥S™Èÿ‘™Hd >2îçÂë?«Žÿ$Nü!­­qÏï½ÌsæØ>½]è&•RIu“Š€*×p™J+šý¼‡âÝï+7ì8p\´¶y¥{I¢á€Œ…RÇÒ¨1*¬2XcF|>CÿKþiþ [÷E÷2»®A-]£Ü¤R inR‰–©¶ö\}ÆLš±j㮃'Ï_½%^F;ÛÒ9ÛØ50Æ¢'Q}$ÿÕúýŠ×gù®æé9ùîرx™]Ý Vë&•¤€Š¥Ò«×³µ‡e*¬h&Ï^¼zÓ®C'/Ы xtšÎü‹ç¿QŒR}$j²ñùcŸ‘hdé éev¥íÚìIc†ÉP oRID¨¥_jÓ֎=݆Lž³dõæ݇O]¼vç¾ +ªw"ó_FÑWóŒäë?ÇðÏø承u§Þ>}x‹b®]„”úñÓ¯_ôΏüÁx“4 ¬9>ü!a¥So0ÿb‡‚»×£OÞ³E\ƒPñzœŠ¥‹%%Ô´zP+U¯P{¹û†N™ ËTTL©ê¿ýZŒqsIø'$^ UõóÇwÔ#uéœ)¡¾î½ÄG¥ñÎ#QÑO2¨TÏ/S©Fý¦mjPh8BÝ{äLô»ž½~)õ÷?þŒ½ßefŠ‰‰F‡*Ì¿Ÿ~÷úÙ£»7¢ÏÙ+Ýy$ Ö—.²J‚mM¨Xúu$ nÝ{ôÌ¥÷=ýþgH©b ~k$7dªø‚Ào¿üüþõóG÷n\Âþà +Tq‘•|;YAÍ uløÜHãP“û§LA'Ô±x;Y2A•·SÔν<ê¼Èµõfl¨ÉýC¦¨ˆ õ&A]9/6T±÷–¼P÷= PëCe¦ê@ªzPÔ³G÷ÉP=ä{“**A½|3æñó7Ô¿jì ¨KPß<sórʄ:œ nÛwŒ¡þkhA=¶Oº7Tê·ÚP·¥t¨/jaõCµ„`¨ Õƒ¡Z`0T †jÁP-0ªCµÀ`¨ Õƒ¡Z`0T †jÁP-0ªCµÀ`¨ Õƒ¡Z`0T †jÁP-0ªCµÀ`¨ Õƒ¡Z`0T †jÁP-0ªCµÀ`¨ Õƒ¡Z`0T †jÁP-0ªCµÀ`¨ Õƒ¡Z`0T †jÁP-0ªCµÀ`¨ Õƒ¡Z`0T †jÁP-0ªCµÀ`¨ Õƒ¡Z`0T †jÁP-0ªCµÀ`¨ Õƒ¡Z`0T †jÁP-0ªCµÀ`¨ Õƒ¡Z`0T †jÁP-0ªCµÀ`¨ Õƒ¡Z`0T †jÁP-0ªCµÀ`¨ Õƒ¡Z`0T †jÁP-0ªCµÀ`¨ Õƒ¡Z`0T †jÁP-0ªCµÀ`¨ Õƒ¡Z`0T †jÁP-0ªCµÀ`¨ Õƒ¡Z`0T †jÁP-0ªCµÀ`¨ Õƒ¡Z`0T †jÁP-0ªCµÀ`¨ Õƒ¡Z`0T †jÁP-0ªCµÀ`¨ Õƒ¡Z`0T †jÁP-0ªCµÀ`¨ Õƒ¡Z`0T †jÁP-0ªCµÀ`¨ Õƒ¡Z`0T †jÁP-0ªCµÀ`¨ Õƒ¡Z`|£PŸ3Ô8Âêó”u+C5!´¡nMaP{y +NP +¨¯ªñ0€úZ@=JPÃÇ òè•¡^ºyOúCõ/꽛—RÔN½Üe¨{ž¨ô¡2UU S}¨ê™£{e¨î½:% Ôô¿û>6Ô¹K£êØP™ªÿ õAZ:76Ôï¿Ë˜>¹ ú…Æ •©Êñß8¡†ù&'ÔÔêõ›¶V nÙ{äLô»ž½~÷ñóo¿ÿPeªfŠdçaŽ¦õßûüñÝëgîވ>sdïjë¦õ« ¨?&Ô4 +Ôҕª×PC§ÌYºf˞#§£¯ß}øì@ýõËb¨š•ª~|Cõã1Pÿøò+@}õìáÝëѧìÙ²féœ)¡j½ê•J+PÓ$ Ô̵@±ÒªcO·!Sæ,Y³yÏa êۏŸ~ýBó/RM<®‰H6q¾.ýÓìûå×OßJPïÙ¼fɜ)!Ýz:"Ԋ¥‹@¨™*Pµ¶ÖƒZ¡ÚÚ#Ôa!“g/^½y÷áS¯ÝyðôåÛŸ ©ÒP•°š5« ³ÅßÄfß_>}xûòéƒ;×.ž:¼{óêų'‡ C¨ö¶µ¨TkëDcªµZ][ûŽN®>ÃÆLš½xÕ¦]‡N^¸zûþ,þ~¦¡úç_ˆÕlambUÃ0Oüõן4P?cé÷ÉýÛW/œ<´kӪų'æãêÔÑÞ¶nµäš=w¢¥*ÔVúùŒž4+bÕƝOœ¿r KJï>Š¡JXÿ2/Y 5Xó#5?Ì¿‘ç_„T TðIÏÇܺrþÄÁWE̚4:À§ŸSÇVµB©¢rgO:¨ie¨EJU¨Z§I+‡ý¼‡Žš8sъ ;?wùæ½GT?ÀPýíwÕ,ñ—^5/V¤z$¤0Ç¿‘þþ ԐRÝ»yùÜñ;6¬X4s⨡Þýz8´jR§j…REd¨i“ +j–²çÎ_¤TùªuÛuèÞw€ð„é –¯Û¶ïè™èëw~òìù‹—¯^½¦x“àxûŸwHЊt-aÕ£š`¦4Léohg0ù}Dˆ`$,ÄOñêÕËϟ=yü0æÎÍ«ÑçNÀ@]¿2bö”±Ã{ºtë`×D®=üô}RA¥my¡ +öœRgwßacÂf,ˆŒÚ´sÿ‘“@õÆí»1=~òôÙ³gÏE¼H`¼| O<"8úßË\똁ª”Oe¦RÌ}ˆq +ˆ„ü¤ß~‘§O?zs÷ö `zòÈþ›¢"Ì3Ì×ݹ ø$0¿Ê25q7i +ú¸¦ûkS³$U'Woÿ‘ãÂçD¬\·uׁ£'Ï]¼|íæí;÷bî?xøðÄã„ƈ§Oágã%NëÄ°brý§`™jBª<õþ.?cX"‹§Oñ[$ì߁?ÆÇîÇÜ»sûæµËϝAÕ-TÁþ*^¦Rz¶­º»xú…„͘¿tõ†m»9qæ|ôå«×oÞº}çîÿ±÷`U]éÂÿu2™$–Ø6,)ґ¢é é½÷*(  Ò¥¨ˆŠ¢bÁ®Ø{ï½ÅkŒILf2-sÿsŸ{ÿßû®½÷)¨QñöqÏúÝç›;ßscK;Å0…uäÏ?ýFA(‰¬÷ïÝ»{?ɝù*0·nݼqýڕËϝ>qôàžöÍëW-]P=· '%&ÄÏÝÑÚÌP[]T'É]ªÄš¦gï¾aRUÕÒ3±°›ê‘ž7»lþ¢e`uÇîý‡Žž8uæ܅‹—._¹rå*píã¸~ýú7oÞºM‚Ä>yöµþLö­X«UQò%ó)8Å0}E*T0úðÁ}ˆ,ââÆ ø$ñ=p(`D._ºxáܙS'ŽÚ¿{8]¶h~Ùì¼ô„ˆ@ï©v&zZª0¥ì+*~帢—¿L¥4x˜ò8 #¨= T“³f–TÔ6.[µnãÖö=û9vüä©ÓgΞ=œÿ./Âäò•«ü·nß!U¬™^þˆûV$V¹iµ³R1Pÿ‡<çü8Žïž?}ü-N~$´®‚‹K/â§éüwÁÁ8{öÌéS';rpÿžö­×­ZÖX[Q23+Õj_#qÊÃsu’|‹_©J &U&ÿ˜ZB¨„Ç¥æ”VÔ.ZÚ²¦mÓ¶ö]{ö8tøÈѣǎGN|'OžW§¾ŒÆúõëÖ®m]½²eùÒÅ ëk*æΞ™“ž:Ý{ª½•¹‘®”ICõc²¯Üë$ѤJò¯(Tõ'Bv«Q ©Yy%s+ªk66-YÖ¼|ùŠ`凳JÄêÕ«[׬ŸGÛÆMÔwíÙè.™®Þ¸ VŸ½ n?&T¹ì+ +ÔW?~OœÞ¼vùüPz`ïîöí[7oÚÐ:Ö´¶®^-þtú½p8V,_Þ¼lISã†Úꊹ%yY© QàÔ ’ïD}É@Åì+ç)U2ÿ2¥„ªŠÆHÀ6h5$2.9='¿ xNYEUMm]… -jll\Ü)šK–,Yº~+ZV­^³®mӖí;A뱓g/â3>úñ՟ÙcnÿÓ©Ë;ÿ'q—êO/¿{úèÁ[×.?}üÈÁ½»vlÝ É²uÕÊ`cÙRøHÌgëė‚ÑX´há uµ5UesŠ òsғã"CЩ $ß *¨¤Lê’ìËIÅú—ªª#Ǩjêš«þAá1 )Ù3fÎ.™3¯¬¼²²ªºº†0¿SÔuuõ ðóh\¼dÙò–UXƒmßµ÷àQ°zõæ7÷AfB•Ë¿“ʝÅeõñû· NO?¼wûÖMmkW¯\±liSã"ÐQ__WŸ«_‡ŠêêªÊÊò²ysJfΜ‘‘’äOœšêhªŽ‰ +eÖ¾] U”™PÅXy¬š–®Zê铐œ–™›7³ °hvqIIiiéœg.˼yðÛ(¯€ÇüÚú‹š–._Ùº~ÓÖv´zîÒµ[w>†PýùÏ¢üû1RIöeŠ]A§ûvmß¼aíê˖@¶¬›_S]YQQ^VŸ‹ûˆøÍ`–`+V­ÝˆV:On=}Áœ]üH©Ük<FõêÅ3'ïßµ}Óú֖æ¦E µ5•åóæ–!…øéf}à7b†"/oƌܜ쬌´Ô¤„Ø舐@?owû)Ä©ú8eL¾8£ŠË¤.‘Ê…jï~+Á´ +V M&YÙ:Nõðö  +ˆŠ‰‹OLJNIIMMKKKÿ028233³²²ñ·‘7sfô²J¨¬a¼vÃ֝ûŸ8sñ*„ê’ÿ&ºæñR#§æxñìyz}êèÝàtõŠ¥ µUåsK‹‹ +fæƒ0’NôA3>àÛÁx¤¦¦¤$'%ÆÇÅDE„øy{Lu´µšdbNaBU< _oq Ê_ªD¨bŒ xØH´ªc0ÑÜbŠÓTw¯i~ÓƒCÃ""£¢¢cbb‘¸$žˆ?Ô´ô̬œ¼™…PUÕ.XÜ ±º}÷£§Î_¹qçÉ¿ùë?¸kv#•=ŒûôÛ{·®]ÕÉnŠ…ùDt:r&_RúvQ J†*IÀ}ú«ãÔ4'è™L²œbçèìêîé=Í×z@`PPppC膄‡‡GÀ/#:&6.!195#+7¿°d^åüMËW¯ßÒ¾÷ð‰³—®ß¾ÿè™èBÀGJe¯B¼üîÉÃ;7¯œ‡@ݵmnãÕU••͚3`JRB|,8‰ŒŒˆ'ó¾;ÁÁAAÓý}§y{º»:;ÚM±œdb¤?ASmqÚ¿(ùvTQ kULÀ}Ñê屪ÚºƦæÖ6vN.®nîž^ÞÞ>>ÓßÁàïï?}zü0‚CBÃ!ŸÇ'¦¤gçÍ*ž[Y»pIËՃÇΐCndRýH©¢âë¤çÜÁ³C‡÷âc±æFÜó)ÌÏÉ$S`dxXHpP H™‘ù¬ïÿÝÈhøøx{{yz¸»¹º89ØÙX[˜›èjk¨ŽUNû’ä kÔ. +T©Pý²;kUi„òuÔjdb6ÉÂjŠ½ƒ£“³³‹ËÔ©S]ß71‡'ü,|¦ùúù…„EÆÄ'¥eÍ((žWUßؼºmëN<“ªÌ¥Btÿ›ë—Î?´gûÆ5+–,˜_^Z˜Ÿž’NR¦ï4°âéááTü±ßëkˆ¸¸8;;9:ØÛÙL±²˜dfb„JÕUÆ(Pb²É·«¤¾Éêà¡ÃGŽ«ª®©­£gh<ÑÔ|ÒdK+kë)666¶¶¶vï=‹àèèääì2CÞËÇ×?0$<*¬æ–VÌ_¸tåºÍíûŽÀ¤zS6RÿW,ïBÜ¿}ýâ™cwoÛÐÚ¼¸¾Šlä%ÇGCY“ äL7שċ£#|RîS¿ç—„q™bmme9y’¹éDcC=mMuÕ±£G:˜§(•MÀ¬Õ>ý ‚ù=‘h7Ÿdaimc+%ßÜ[ΜQ8‡•Šé÷ê-,”dTýþ7[ýB¡ôÍu&RQjMYñÌìÔ„è° ?Wg[œÍÍ ÐŒ9;÷ Þã˨hkkiijhŒWWS£Ê#‡ƒRÓ¾½¿îÉ8%ß.’ÚÁ*¬l Xûö­C”†9Jyô0«¢ª¦¦¦Œ/445áÇ ?ÐLÒ8)¼Ðª‡pDlR'•Ì©P(q'Å=&>ÔªäæƒHê (”ð@.‘:;?+5>*4À×Ë œZ[N23hdh@Bñ0_à=¾* +Œª +ø3ZyÔÈԆ€Òþ}!La-ËS «d¬öè 3+Dë@âuø4« ?à:•½±a5 +ÃH ™>Í÷ À)(Õ¡Ú r<RUÅÏÎ}w~aeô9b81:¢fSÓ¯ØÜÛÕN;XeµB´öë^ª¤4lØp Œ|F”•ñ—€¿ƒqæ Ši]}£‰f“,mìÝ¼1R“3ófÏ«Y°tÞ8~öÒõo<~þ’i1!Ùâçܲ‡Y©?ÿðâé·wo]9òðÞ×,ÇSa³rÈÏi¸ŸËJXƒú²§*„ÛXt„Ÿžùïüºd\†6LIièÁh´?¥D)_N‰TÎ* VF+„+Š³ vð!C†¾%Æáσœäï1àJ.(¥ ŒM‰TˆÔÈøÔì™%嵋š[7lßsø$sm’4#~JþþVÿOZê?ØûÝP)]8}tÿÎÍk[šê«ææ¦'F‡LóÄMÚÉf õa¢¡®Ê&Pqh =qü>Q()£”M½"§]*•³Ê+§½öîÛ¯p vßÍ îG€!Næe¦ž ËHupñ˜€fr pJmÁ)•ì=Üûw %:üüoǎ<ïw>TbK‰ì>p“ê¼Ùy™É±áA~^®NvÖ(UOG Žƒ)cNì‰ð®oƒcÔ"´Oo4Ê)唧¬­„»÷ b¿&jA.C¿wҟù  aÌݨ¬ª¨±R'[Ù:¹zùEÄ%gåÏ.«Y¸L*û~/êóoÉ ÈæT$•i¯—¹ü»¸®¢tVNZBTÈtòˆÌ¤NÐÒP#NqRd’è@FTÿw|YvTp€@ç×Dhîx‰R>JZå´¢W"Í"_sô~Ì/å’Zk¨ÒpXóŽ‡Rõ 'š[N‘ ÔÊúÅ+ֈV©Ì“·_ÅG¥{¶¼—ÑÿåNçã¡ß_™goä60Y©®\º@2Tñ!™©‘¾‘:z.FH¡CŽUõ;ˆÆ„ŒúD¡hT¤”?§µ²^‰X0KÜz¾ÖïÞ$oV™ý)5 m Tk;R&EƧdÍ,.›Ou×f;_üŒœ»&ՉkìMcr3Š}JÎméo'¡Z‰s£C¦y¸8ؐPevö PIñJ)xÄÕï ÓWŒPÖ(ßJ%¬Š´‚W f¿$r9ºÿ>Œz‹ZûÄH§:žyžgeëˆÉ7Kߢ¹Õ M-ÌvÒ¹ËÜÓÔ?s‘úïNöáúѵTöàÙ<ú¥ÙX¶p~9·ªñqw¶‡YÕØ@Gk¼Ú¸1Ê(•]Lړ•õ6$F…ŒÒD(+åÕ)k•ÓŠ^Q,še܊øò÷!ڙ2«„ê !JÃGâcL¾&æ–äôS`XL"¹P×¥ï¶ÝŽæÎ=°R“h°öfEM¯Èõñ°Ç~Ÿ>"j Twl‚¸¡pJ\D°¿·ÖJ¦øøBUy$‘Ú¿_¶ÚéÎÙz RãBFêsF(+åÏ©”V╈%f?é}_°9‹,Ü R1P!ùêâ„jã0•L¨ i9³JÊñ Íz(}1P¯³‡ QêßÙVl°Æ4­Â»ÆŒÔgoB¨Ãçä­Ëë*çÎÈà*`<{b¤VUÆ°{¶ÌÎAvvduý¢1ú#'”U¥b­ŒWF,«–ãówð'¶Æb70ȳ|7^K׀8%ERT,Q‹çU7ä{° Á՛}ñ07Hý+ۇë¿;×`izÅ5­"‡¹B©„¡º¯Ü5¬%÷]’bDŒ L«xTa¸»Oö¾ä²éۑvÄþ a”w¥H7)¯"³ïF$ýOâÍÆ~$P!ùŽÇcOfœÓxöùÌâå­ø|üÈÉs—®ß¾û•ú¶¯Gçû«‘nIlO€W¤sHôØÁÝÛ7®mÁ'åø¬&1&<З³ª«=ž9¬À<1c÷øþ$òö~£À [7RŠt󇼏Ùϙ½F”ÊïIõÀӉø¼=ÈNqêƒ×9R2g0G ùnہʜÏ'·`Ú?þJn¯Fš_ýJº±üô#sñî­ë—ÏŸ:vpώÍëð¤RÕ¼Ù3³Ó¢«6hUGSϊ ÅPýšHe·„^óöf:ŒßßD·Ddõsñãöƒ•˜clzF¦“ñ|8qšœ1£ ¤¼Ï¶m!¹Ï]ºv“\{#m^1í•>ª»éDFÚ±¼$«Pê• gðþ6HÀKÕVÎ)ÊÏJe¬N…媙±þ 5HÀª¢§ÛŸ‹œ~Ð`ð-ïwù`­ì³|,Û»ï€AP%ᄪkh2ÙÚÞٝ}Šš;«¸¬º¾qÙʵ¨‡Ÿ>]}î= ÍHžŸØÖYщŒ´"ûñì\…mŽð&ㅳ'€P]¿z9¹\ |²Š›x¤^¦UHÀª˜™sû|ðù&Þ­•‘úåWÌÙp TH¾P$M²²ub.]%‘{¯x4tEkۖ»9q/¨ÞÆ&ÙX«ZV,Ç^; êjªÊ±GÀŒ¬ôäø¨° ?<!½¦¡Rÿ«ãœ*¹L5#‡X¦AþŽO«ù³Kæ–UT׀ׅ‹71 ³–/_A:ªu¦¥Ú;š’­À¶dÍ˖.iZ܈­¬æWW–Ï+-ÆÆGé)¤Kžì¶±4#…Sż¹úU×bžÐ8»yû†FĀÕ̜3 ŠJæ€×ÊêšùµL¿,짆 Õ:ÛRí­=ÉH[2ìK¶ ¡¾®v~MuUE9ée5+/â4!&2Ûä8ÛO™LÚäðÒREQyó:•lçÚÆqª‡ZŽKLaûmÍ.)3w^YyEEeeUUu5×P­³-ÕÞܓŒ´%«®ªªª¬¬(/›7wNiIqQá¬ü 45)>&"4Ð߇ôÉ!ÏTñéóœ†J•ÞQêÁí(a¦ZÛáýE¿€à°È˜¸ÄäÔôÌìœyù3g1í²ŠKH7µNõS{Ÿ¶dؘ¬¤¸x6ö&›53?oi·“’ˆ7U™S…zÚ¢}é%¾—7ºI5Pc»2S‡PÅcؕÉÛwz`HXdtl|B6TÊÈÌÊÎÉÉ%½Ô¸njk¨öûmÉHg²¼3˜VX™¤}RŽ  šîëM.5Zàù_MÉgo]ØüHaKåžÒ°Þðp¨…µ£ ¶{𠋈ĆJñ ‰Iɤ“¶RûàfjBéM†Íɒ“âãb££"Hw_O7G;k<©¯«%ñ”¼•ú_M™þô%“1T•Ù#¿f“ñ +¹‹éÎ2=0($4ŒtˊŠŽŽŽa[©u¦Úû6&#½Ébb¢I{²ˆð°ÐàÀìhåá6ÕÉކ\iÔÕfγ0­è”ŠHLª_âq–~a÷b•Üa´&m<Ü<<™†JØ-‹ôQuRëL?µ÷ëKÆ6'#íɦû“öIž`ÔÙÑ{0­Ôؓgä8KWwÊQH¤>°çY†“ãùZ:ä¹…¶gqr& •<<½¼¼±ÓGíÛ©}`k2¦=iP†½°Hû$'ҜÅ[«oãFÂöGÜiÂÏ?ïÒN9 +‰T¨²¶ˆUUr7;>`ßl¨äà€í²œ]Hµ÷ï£ö‘L% Ê\œI+,Ò=ÉÚÊb²¹éD#Ý šãUÑ©_-­I©X³VG’‹ŒZtõ &š`K% KÒ/‹m¢ö!mÔ>ò—Ù`‹²)Ø ›'™™>̵c呬ӯپ*ÿáÈ‘nRV1÷åmÃ›äÚtõ H5ì ffNz¨½o5ã$s¦IéRf §;A[s¼šŠ¨§U_î(7­r‘T®Ñ±J.3B´’þiÚØ@MOß;¨‘jïÛCMF1=Ê áèëaë$mÒ¦L…4µRÂ9í.Õ+‡ïqåéP•nŸ6jô˜±¤ùÎx MÒ@ ;¨½g 5ق/ÛKƒi´3v ¶P’èSö?=­®–°Š½A«¸}Ú8¦ii ö¾-Ôd ó÷b—2UU•qâ>e¨´?wá\£ùŒÎ¨ˆä1}®ÍVoìÆÄ5j³¤ژ1ïÙ@M>¿~4¶)cû” …Ä‹MH $ÑÕ¨ÿèÓ¡b$­Šµöašl ÆÖJJl߬÷ìŸ&Ø6eLŸ2¶!K?QW+‰HÔéIwOc¬¾¹{Ú»û§Éò!ÞШ¬{ÇFe|©ÀÔÿLtý˜h%ÝÓúŠ»§½Oû493@ܨŒ4ØéÅ)ß`ü½CÓ‘U6X¿`ûz XéæiïÓ>MNôw*#=®˜ÎV¤÷Ü|7*SHºI«tó´žRÍÓÞÝ>M.|-Õ©¬ç;•Q§Òt“ V‘×ož&_ºS™ÂYíØ<­cï´w·O“RŸ@1;•) Ý$µ~öÖÞiïìž&':|Q{+…êT¦€ˆµŠšâ}Xï´®AºÅÕgÒM;øCÅ£›„ÖNõN“7ŸD«2…£›”W‘Y¥c3$¾GOaéÖ­£XÅüöîV|œbÓMŠ÷jÆҟ’ï1ûèö)Á÷`}Rð-ë=à{ˆ>yøÈÀ÷(P( +…B¡P( +…B¡P( +…B¡P( +…B¡P( +…B¡P( +…B¡P( +…B¡P( +…B**v)Q¶áYá½ü{©X;…Âÿß+<3+:£—[/=e÷^ºÊ±ÌÿÁ>>)ڌù¯S¢cãSØJ}¼²ž²¿üs:¶Ñ9ñ‘ÑáyÊþ6½•u'è*ëâÿà1˜`¢oll¬¬§g0A_ÏÐD9XÙÐØTÙHOOY_Ù?î}þyü¿q†ûß&ð×ÃÿÀ?ÿCeò/襢B>"~13e}Sccý^þNÝÿ +…B¡P( +…B¡P( +¢$‚ïOB‘Jo€ïÏDùÞd”zý¤y»Rªõå÷•R­Ÿ ïVJ­~j¼—Sªõ“â}R«Ÿïï”ZýTø§Ôê§Á‡9¥V?>Ô)µªø|¸SjUÑéŒSjUÁéœTjU‘é¤SjU‘¡R…G§R«ŠËGH¥V”qJ­*(Tªù8©Ôª"ò‘N©UE䣥R«Š•*@>^*µªpÈ@*µª`ÈÂ)•ª`ÈD*µªXÈF*µªPÈH*µªHP©DVR©UBfR©UÅAvR©U…J 2”J­* +²”J­*2•J­*Tª‘­TjU!±TjU! V•*@d-•ZUd.•ZåÙK¥Vù‡J ²—J­òŽ¤R«|ÓåR©ÿ.  ­vêG@éòú&Mü(G.R;Júð?Aù(äoµ„òqÈ[jgþ å#‘T¥NýÛyA!©ÄPgþ EÈÁgçá{0„ߥá{4„ߥá{4ߥá{4ß;À÷p¾5v€ïá|[ìßÃ! ø¶Ø¾ÇCð-±#|‡0àÛbøaÀ·ÅŽð=‚€o‰á{<„ß;À÷p¾-v€ïá|[ìßã!ø–ؾÇCðm±|‡0àÛbøaÀ·Åð=€o‹à{8ߥá{4ߥá{4ߥá{4ߥá{4ߥá{4„ߥà{0„ߥà{0„ߥà{0„ߥà{0„ߥà{0„ߥà{0„ß%á{,ß"%á{,„ß&%à{(„ß&%à{(„ß&%à{(„ß&Åð=‚o•bø Á·J1|„pàÛ¤¾GB@ð­R ß#! øV)†ï‘|«Ã÷H¾UŠà{ „ß.Eð=‚o•bø Á·J1|„€à[¥¾GB@ð­Rß! øV)†ï‘|«Ã÷H¾MJÀ÷P¾MJÀ÷P¾EJÂ÷X¾EJÀ÷P¾EJÂ÷X¾=JÁ÷`¾=JÁ÷`¾5JÃ÷h¾-v€ïá|Kìßã!øvø|ˆàÛákð= €o…¯Ã÷ˆ|úðmð ð=$Ÿ<| ||É§ßþÞ߃ò‰Ã·¾7Ã÷¨|Úðmï-ð=,Ÿ4|Ë{|Ë' ßêÞß#ó©Â··ß‡ïÑùá[Ù»á{„>%øvõþð=RŸ|[úPø/E‡o?ƒïQS,ø¶¡ ð­åCá{¼>AøVö{ð=6Ÿ8|ë{|‰ à[¢|†€à[%ßã 0ø։ð=„*$T© ¡J…u*H¨S!B +êTˆP§B„:"Ô©¡R…u*D¨TB +*U€P§B„J Ô©¡Ru*D¨TB¥ +êTˆP©„J Ô©¡R…•*@¨TB¥ +*U€P§B„J Tª¡R•*@¨TB¥ +*U€P©„J Tª¡R•*@¨TB +*U€P©„J Tª¡R•*@¨TB¥ +*U€P©„J Tª¡R•*@¨TB¥ +*U€P©„J Tª¡R•*@¨TB¥ +*U€P©„J Tª¡R•*@¨TB¥ +*U€P©„J Tª¡R•*@¨TB¥ +*U€P©„J Tª¡R•*@¨TB¥ +*U€P©„J Tª¡R•*@¨TB¥ +*U€P©„J Tª¡R•*@¨TB¥ +*U€P©„J Tª¡R•*@¨TB¥ +*U€P©„J Tª¡R•*@¨TB¥ +*U€P©„J Tª¡R•*@¨TB¥ +*U€P©„J Tª¡R•*@¨TB¥ +*U€P©„J Tª¡R•*@¨TB¥ +*U€P©„J Tª¡R•*@¨TB¥ +*U€P©„J Tª¡R•*@¨TB¥ +*U€P©„J Tª¡R•*@¨TB¥ +*U€P©„J Tª¡R•*@¨TB¥ +*U€P©„J Tª¡R•*@¨TB¥ +*U€P©„J Tª¡R•*@¨TB¥ +*U€P©„J Tª¡R•*@¨TB¥ +*U€P©„J Tª¡R•*@¨TB¥ +*U€P©„J Tª¡R•*@¨TB¥ +*U€P©„J Tª¡R•*@¨TB¥ +*U€ÈG*µÊ'rrJ¥ò •*@¨TB¥ +*U€P©„J Tª¡R•*@¨TB¥ +*U€P©D^R©Uþ›S*•?¨TB¥ +*U€ÈO*µÊrtJ¥ò•*@¨T"O©Ô*?ÈÕ)•ÊTª‘¯Tj•äì”JåyK¥V»¹;¥R»ùK¥V»š.pJ¥v5]!•ZíZºÄ)•ÚµtTjµ+é"§ÔjÒeN©Õ.£ R©]EWJ¥V»†.uJ­v ]ì”ZíºÜ)Õ*oøPJ­ÊžœR«r„7§T«¼àS)Õ*øVŠð=ƒo|ƒ€à[¥|† à[â›à{L>iø–÷»ð=8Ÿ |+û`ø0…„o)r„ï¡•?|0ð=æò†ïñå¾]Þð=¾üÀ÷¨Ë¾G—'øvùÂ÷èòßÃ._ø]žà{Øå ߣË|»|á{ty‚ïa—/|.Oð=ìò…ïÑå ¾‡]¾ð=º<Á÷°Ë¾G—'øvùÂ÷èòßÃ.Wø\Þà{àå ßcË|¼<á{lyƒï—'|-oð=ðò„ï±å ¾^žð=¶üÁ÷È˾G–GøzùÁ÷ÈòßC/?øY>á{ìåßãÊ+|¾¼à{\ù…ïї|*Ïð=üòïQå¾Ç_ð=¦¼Ã·9À÷*|+=|¨"À·YÃ÷x*|[-|¦¢À·YÂ÷X*|›|¤"Á· YÁ÷8*|ë|¡âÁ·‘‡ïTHø–òqð=z + ßb:ß#§Øðm§3ð=fŸ|;ú ø¬O +¾e½|Ñ'ßø +…B¡P( +…B¡P( +…B¡P( +…B¡P( +…B¡P( +…B¡P( +…B¡P( +…B¡P(á¿( +…B¡P( +…B¡P(H7|Š,èöøþL”áMF©×O±Â?pP­Ÿ6¯ }Í,ߟòt4ú¡ƒW¾?$僐TúY¨ÖO±R´øG)D^©ÕO +‘SÖèç°^©ÕO Î)£DþIÆ+£•Zýd‡)Q +"¿€x%Z¹`åûóRލd˜¢Ò/¾øòË/¿bÿŠ^Q«8XùþĔw!r*VúÕWݑøD¬H+µúIÀΧ¬SPŠF{ôèÉÑÔ²Z©ÕO §¦¨„öêõ5G¯^èõ+L¬Ôê§@G§Dé×½{÷éÓ§oß¾ðŸ½{ Z1Z©ÕOф*r +JÁg¿þ ýúõíÃhýŠIÁœU¾?8孈çSpÊ(í×ÀÀè/Ò*¶JCU‘‘H¾àÕ‚ÏÁC† † <¼¢V Vjõ@¨lœöîQ +F‡* 66LièÁ@´~݋IÁÔª‚ó§¢4løˆ‘£#G ¦Zû÷c­rÕ•ª¨HJíÞro?ӡƏ¥^CCSCc¼ºšÊ8Ð*¶J§Uņ‘ +¥/*$ßþ+ 5z¬ŠÚxM-í ::&hkiŽWS;zÔp¥7YåûP^ƒ•JfTÔ~>rôXUuMí ºzúúzº:Ú uܘQ#”†0VÙ˜N«Š‰X*Ψ}û2l¤òXÕñštõ Œ'ÆFúºÚšêªc•«°^ŘN« +ŠhJ%Ù’/8՚ ghlbjf>i’¹™©‰±¡žŽÖxÎjŸ¯{2ÅMÀ +‰TöÅu´Šº&8hj>ÙÂÒÊÊÊÒb’¹‰±®¶†Ú8°:x`?jU¡‘ȾÝ1û:\y¬š:5›limckkgkkcm9Ùl¢¡ÞÖ*¬WEÅMÀŠ‡ä”Êd_ T-]pjaecçàèäääè`o;År’©‘þMÖ*[,ÑiU!IÅ)µO?Ⱦ0£jLÐ76›lmëàä2ÕÕÍÍuª‹“½­õd3c}Mµ±ÊÇ‚Š%š€”ú+¦T̾ã0PM&YÙ:8»º{xzyyyº»¹8ÚM±0›h€VG¡U:­*.b©¤N¤4b´ÊxmTKpêáåãëëçëëãåáêì`ci>Q‚†ê˜QÆ0ŝVN*)~ûö‡)uŒª†ŽÉ$k;'Wo_ÿ€ÀÀÀ€é~Ó¼Ü]m9«#‡A±D¦Uº]¨€HK0xØÈ1jšº†¦6S=¼ý¦…„!A~>®hÕX_{¼Êh¦X¢ÓªbòšÔQcÕ´ô ûÚ:¹yù‡†GFFEF„‡MŸæéê„Võ´Õ¡f§Uº ¬€¼Aª:H5·¶wñðñ +ˆŽ‰‹‹Ž  ðõr«fFzZêP,‘i•®Vñ’F,U[â¤)S=}Ài\BbRRbB\Ldh kUK`,–è´ª¼Eêä)Ž®^þAáÑq‰É©ii©)É ±QaA~ÞnŽ6¦†:X,ÑiUQ‘Ø|j2ÙÆÑÍgzHDlBrZFfVffzjR|tx¿—«ã”É&°X¢Óª‚"¹£ëÔÁJœT'wŸ€Ð¨¸¤´ÌìœÜÜÜìÌô”„˜ð`?/W‡)“&êc±4|(]­*&’{¿¸ù0ª_H¿ uZ`XtBJFvn^þÌü¼Ù©‰1A~^Sí­¡Öê0­R« +[þŠ¥Ž% +5<&1-+7VAaaÁ¬üܬ´ÄØð _O;+,–è´ª°pùÖ4½z÷8tÄhUM=ãISˆÔؤôì¼YE³‹KŠgΜ‘–V=œm-±XÂ=ˆAx‚n+’åoヌ ­¢¡ RÝPjrFN~aq霹sç”Ì.ÈËN«Óܝl,°X"Ój:­*Ö4C†+«hè™[;¸ù©¹³ŠJ疕——Í›S\˜ŸžàãæÅكM«ôÙª"!Q)aù;lÔ¸ñ ͬì]}@j挂â9e•UU•åóJŠòsÒ£C§{»:@±¤«©ÆN«½è´ªX¼^)©k˜ZÚMõ#RKæUTÕ̟_S]YVZ43'-!*ÄJ`+3܃ ÓªB"Q)õd+%(-l]¼¦‡Æ€ÔÂҲʚںúúÚùUåsfÏÌNKˆ öót¶µ0e§ÕAtZU4Þ4©B¥dãì靔RË«jë,\¸ ¾¶º­¦ÆGùB±4÷ Þ¸ ü®¿P‚.ú–ÿiHç_2©êš[;ºûG%©Õu 566.ZPWS1wv~VJ\x )–Œõ>lZíöºôûþG ½RÅ=%œT­ܦE&¤£Ôšú…‹›–,iZ¼¨a~ÅÜ¢ü¬äØ°oW˜V$§Õw$à·¥^å@‡•*3©šX@¥Ÿ–[PZ1¿aQÓÒæææ¥M ó+çåe&ńú{¹ØYrÓ*÷lõ­ë }onMµÊ’ÙE >¨á&U¯éaq©9DjãÒæ--+š—.^P[9§pFFbTˆŸ‡³Íd“·M«Ý:ü oðI»~ˑnÜévQ3j,¬Tͧ8yø…ƤdÏ*)Ÿ¿`ñ²+W­ZµrŲŠæWÌ)ȅ8hš»ô´ú¶uM¥ohMÛCË©ü‹‹š1j줝”9³¤65·¬j]³¦uUKsX--ÈI‹ôqu ÓjÇg«R¡*e”U)Ñšvý–’ÏTqQƒ{úaRõ ŒLÌÈ+.«©+[×®[·nmëJ´Z^23;%6lº×TÑ´ŠG–:$ànÿ%­T²á7ÛZ²ë7µ*S^_ÔhèI5 <>}FÑ<º|՚õm6´­[³jyӂš²âṳ̈è?Ogñj•9 ,Ù8@2ï~&Ùð[ÔZÔšvý–5ݤ6•È¢f‚¡™µ£‡hljnáÜꆦå«×¶mÜ´yÓƶµ`µ¡fÞì<(–‚}É´Ê>[•X×HZ•PÊú”è Ívý¦VeÔ¦ÒÀ!¸¨Ñ7µtpó ‰IÎ.˜S…R×mؼeëÖ-›6€ÕÅ Õs sÓâqZe6¹iU¼®ùƒtâ÷ûþR‚/˜îПÓ^î²G*ÿ²‹2©E%eÍ*­¬_¼|õú[¶mß±}Ûæ ëV5/®¯šÅN«.v&ÚêãÈI`Éuäëm$›C3Ý¡ÅÍ¡iÓoùÐMrS‰YÔè‘I5"!#¿¤¢¥nÚº£}çÎöí[6‚ÕƺŠÒ™YÉ1Ìju¢ž»®‘|^óºR¦9tQohl7û•„VjU–¼iQC&Õ°¸´¼Ù嵍 uó¶ö]»wïÞ¹c+X]¶¨¶¼8§ÕinŽÖæFº¸](}fô3ñûPHÏÙ/™vß½DÝ¡{õ"M¿¿âºCS«²E"ÿr‹}2©B¥TT6¿±yuÛæí;÷ìÝ·oïîv°ºréšyE3ÒaZõvµ—X×°Ç >ç¡âîÄè×LshBïÞ ¶'i#ü¥Ø*•*+DùW¼¨Ñ5žŒ“jtrvἚE uˎÝ{÷8p`ߞÛ6®mY²Š%2­zºØZLÔ'gFÅKÌ,Ée^Q»oì ݯÓº__¶‹pÚó[Ho*1‹fRL̚5§zá²Uë·´ïÞðÐáC÷£Õ5+šê+Kge%G‡øº;1ë©ü9·ËÀuåïÅtûÀ4‡†ÿ ÑZÂ*•*+¸M}rûB4©:yLÏÈ/­Z°¥î9pèÈÑ£GØ»së†Öå‹ëpZMˆ bÖ5 ˜±Êî3pܙn߃2dÈPøƒIohÔ*²J{“ÊÉIµxRu÷ …J©¸¢~ÉJº÷ÀácǏ?vä Xm[ݼh~YQnZ\8¬kl-Øç5¢Î-¸¯ð'¶@ÂÄKº}ckh¦7ô°aJØzhe[~Ó.–²FrQÃMª°Ru“’;»¼®©eH=xäøIà8Xmß²~ÕR˜V ²Sp]Ó!÷`*lÄtû¥CIkè‘lkèDZ-¿‰Uª2çµI•¬T]¼£ R*«]ܲnsûÞCGOœ:}æô©GÁêæu-Kê+Kff&FMssHÀ¤s n+à»Å°14„)v†V>;C3­¡ÇŒV…Z!XÁj¯žÒ¡Ê÷p&ÿâ“rѤjh6ÅÉ3 "1«`îüÆkQ걓gΞ;wö4XݳcӚ‹kËgÏH‹`0TÀ#™ܓì}Åͦý¢Rì =VE²5ô(®ã÷×zCó=€Ϳ+U-}S+G¨”fΩ^´|Í&züÔÙó.œ?wæÄÑ»·mhm^T뚔˜PéܗÔ>ݙ͆ÞâfßcUTÕÆcghÒZUeìhå‘ÃIcR6eÓS¦2E<©2+UeM½‰–ön¾¡qéy%U –µnܱ÷ðñÓç.\ºtéâù3'ŽìßµµmÕ҆ªR’€±mAôNJ¶gfiÚ·?:Á4†ÖÐҞ0AGG;Ck¨«bÃïáoløÍ÷xƒ“*Åí¨”RgW6,]ROœ9éò•+—/¡Õ};·¬kiªc0VÀìð0ì3 +ËOÜìͤÞa#•Ç`¯o®1´¨3´ +iãN0=å/{D+Ufû—Ý~pñŠJÎ)*¯_²jÃv”záòÕk×®]«Çï…iuù¢šy˜€C|Ýq˜¹à8kŸÞ_“7Q Àþíl¯o=Cc¶1´¡¾žŽ–X•ê÷M'U™Òaû—Ù~˜âä™åo]Óʶm{8{ñʵë7n\¿zéüéã÷lÛ°šMÀ‘ÞSí,MؾXÑâûÿú±©wÌ85 m}C㉤/4ÛZ_[‰ÿ¼Dþ¥Re†Ôöï€Á¢JizxB欹ó·¬g¤^½~óÖ­›7Àê©£vA^Œ 856ÌßӉ;1ln*ôÃ$H½# õb[hc³I¤-´••åäIfô¹v߃_ëÁ÷p„ÛX)‘=¥0,kW¬Ûº¤^ºzãÖíonߺqíÒ¹“GöµoZƒð¬¬$X¬b­dˆ[Àêàà¦àP¦%¿–Ž¾‘‰9ÛÚΎô…67«šêä—ìáN¥Ê©I+%fOÉ746=¿Ö4붩×nÞ¾s÷ΝÛ«gOÚ³­mՒ†Šâ¼t¬•˜çåØånØÐÁƒ &‹S˜N5´u °Ó÷[{''ÒÚÎÆÊÂÜÄPO[C•é5+nA¥ÊŽ×*%,m™ò·¤jaóÚ-»©·¾¹{ïÞ=´zñÌ1LÀ+çC­”ìëæ`Mn­BF¦4tèP¥a°’ÁéTÏÐÄÜBÔšk Í4V—lö͔¿Tª¬WJ잒úCRþF§äή\°lÍf"õú­;÷^Ë^sKlóíãùZOhrÕJ•o\ÓØ»‘…êÜù‹W¢Ô3DꓧϞ={òèÁÝ[W¹P…8›Àª&†ºÚZšør1pjë8ÕsÚô °Èèظø„ø¸ØèˆÐ wg{kÉޕ½è’Föt:rÜx]c²PKÇ݇–¶íûŽ©ž<{þüù³'ßÞÿ† Ս«—âZ5-ŽœØ‡òÇ@WG[[{‚®¾¾ ÅÑÕÓ7 $<:.!)9%%9)1.:"$À×s*ӐTâp)•*k¸çä_~%±Pµs›–_*–zçÁ£§Ï¿{ñÝóg’P=´{˺å‹jæÌÊLŒ š¡jajŒaôô ŒM‰S/ßÀÐÈ؄äÔôŒŒŒô´°äÇô¦RåJ‡…êȱê:F“l§¢Ô¼ÒêE+ÖoßËH}üì»ß¿xñüé#U(€÷mß°²©®¬Ÿ–ûc“ÑI¦ &šMÆW¡xù†EÅ%¥fdeçäæ`ëàÄØȐé>nN6“M DR{’ËU´ø•)R Uf÷¥úǤ敠Ômb©ß¿|ùýwª7¯œ;~`'”J •%yéñظÐÆr’™Éĉ&¦æŒÓ °èøäô,ì<3?/7+=9>*4€m\‰—«† À܃¤*kÞ$ÕÆŇÝ'\±nÛÞ#§©/@*X}úí½ÛW/°ù·znëûz¸ØO±œlnff>ÙrŠ“8 IHÉÈɛYPXTT8+?735‘t#u–yþâå?üðòųÇ0ÿÙ»½ –ªäa9v£t²›beaaaimcïÌ8MLÍʝY8»¤´´¤¸¨ ?'=96‚4f¤âå>_Ӎ<o)±û„œÔFêV‘Ôï_þøã/¿þäáÝ—ÏÛ¿cê%õä\KDà4G;kkk;ÎiZVÞ¬Ù%s畕͛[R4kFfJ|d0JŒGnjTԟ®häÃkRµß*õ‡Á*É¿·$&Ur·ÑÏËÍÙÑÞÎÖÎÞÑÅݛqšWX<;ÌVV”Ï-)ÌÏNÅ®•¢«­#†b‹_Z'ɚ÷ˆT(”î>|òHýé§_¾xúè,jNܵyMóªҙYIÑ¡Ó}<\§Šœæ–Ϋ¨®™?~ iEŠ f9©äX©¸ø¥*[Þ:§¦ˆæT‘ÔŸˆÔgîß¾FVªkq¥Zèçíîêââ2ÕÍÃë^tZTZV5¿®¾¡¡¾®¦r^IAn:i™ædƒç_TFBë$9ñÆ% T¿X(•0Rž¹|óî·O¿{ù#Jý*%Ê•¿x®;5>"xú4/777/pš +Nç”W×6,\ÔظpA]u9öÁÆ=xÏ*“âW¢Nâ{$„ÔyŽëÔ*vúF©‡woeÎ?äBZ ðóñòôôòžÆ8ͧ5õ ›–,Y‚H+çbËJêî8ÅÜHg<,SsuReÌÛv”‚c¸¥}GÏvúˆTFjьôÄè° é¾Ó||¦ùM +‹ŠOÉÊC§ ‹š–5/_Þ¼´ia]õ¼Ù¤µ>R73œ€+¶ø¥ÙWæHRRzÓÞï1zO$•™SÙÝ_FjFRLDH ¿Ÿ¯Ÿ@0:Å~íLҖ•+W¶,_ÚØPSVŒ#՗©XüÒ:I.¼áћÄSšÅ+Ûðyê•[÷=}ÁJýNTýb¡ÄH +˜>= œÆ%gÌ((-¯iÀ.¤«[×´®ninZˆ­ ³˜sjV¦Ú¸¢aŠ_:¥ÊžŽÉñyª¥äóÔöÇÏ¡ÔgD*³Ne77ãñ_”šNÓsg•”¡Ó–ÕkÖ­_¿nÍêKÕU^ÁÓÜì-MôµTÙ◭“h Ê’7Ý{ãN>àɇíNœ¿zû>‘ú#J}þä᝗ÉÕÖe «ç¢ÔèˆÐPpš”ž3³x^u}㲖Öum7nÜ°~ÍÊæF¶Hð4WŠËT"•n=ȉ wðLßÔÚÑszDbVaYÝÒ՛vIý· E{¿û¶oX½tA.U’ã£#ÃÃÂÂ#¢âÈunU:]¿qó–-[6mX·zyS}Ùúòqµ³˜¨§‰+Z'É ñ]òGD#“rŠÊðÜ®}sÿ1+Uô”´¬\X Rc¢""""£ãS³ò +çTÔ.Z +N7mÙ¶}û¶­›ÚZW,ià¤Nµ›l¬«Á®hh$:´²ßeŒNÉ-®\мvËîç.^ÿæ‘Šip?¦T¬“Ö­X\WQ2+'=9!6:*2*:61%3· ¤¼fÁ’­â¾†HW-Fª÷TÛÉƸLUDë$ùðZÓI<¢Ä®hÈÞóäí:û8õ|HþèR"G±ÿNñL"5&::&.!&ÔÙóªH¯Jlk¸g÷®öm›Ö­\ÊH ôv±™d¤3—©Tª|è؞›©“°øËŸ;»|ãÎCæù÷¨ß‚æ©Ã{··aûy³ó³Ó’âbbbÁiZv^ќJ˜PW­§»÷îÛ·oÏ®í›×¯ÂŠŠHõr¶17½É ;2DÜȎ¼q~ȈÑjx@ŸÜOÍ"Åï†öýÇÏ^¹y÷ᐠ+|eÔ¾gcömiª¯œS˜—…RcÁiR*¾ú¯|þÂ¥-k7nkß³ïÀÁƒöínßÒ¶ºy!^}LŒ ðržbn8A—©¸¢¡Å¯ÌySËu#sö*My=^¥Áâ÷Ö½oŸ<ÿœb Þ¿/öíØÙ·¶¼dVnfjRB|:Í`’oÓŠÖ [Û÷ì?xøÈáCöîd;º€Ô”jfˆ{tE#D*ê#ªÂôey: ‹ßÛDê ÒýŽk~·vy#JM©ŽÖ¦d—p0•*º±¥¯ôKT'bç`¼r\Ñ°ŒÜN=wå&‘úü;îÒÅÙ㤙GSCÕÜÙù}““RÒ³Ø*i%v4º¢q>J Ÿîáh…R•‡“ ¥/©TÙ"¨’oc²/éø°¦T¨“î>|üôÙóçϞ’ëQÈUr,“*J ò² û‚Ôd&P«ê/_³qûîGNœ>{þüù³§OÙ¿“<£“ª©ªÜaC‰ïÁŒS¶ôe^Ì8NCGԙ²ïâ•mÛ÷=}ë$”úìéc T\ÏìÞº~åR&åBöM’ +ÔUë·ìÜGzß]¼xáü™“GìÚº®…•êRMô¹­_ºL•-Ý:ê T-}Üy˜“ŠÙ4xür‡{Œ`=Ó¥Oc])“0û&‰uŚ;ö&û>©xõÚÒñYÏåg3e¨s*1P7íØ{è8igxýúÕËΐ¾K+×ΣRå‹Ø)[%‘Ò— Tÿðøôü’ªÍk6ïä²/i ðø!¨¸ñ°l¡d ŠÖ¨$P=uþÒÕë7nÞ¸~õâY\ÿ´­lªW@¥Ê §lò…5ªš6¨Ì[ijI_ÂçÎ_…ì‹RŸ<&zñô±ýd㡞 Ô$f=ƒ›I•uPúb3Y¶›á­×.Ÿ;yµ«Pj•*?¸ •T¾$ùâ‹æ5É;ÉaFOÏ+©\‹ÔvÜy¸N²/@õʹ“‡÷0e¸íËl<$³»¾ ðý»;}áÊõ›·¿ùæö­ëL/-Vj"YÒP©r@ì'T6ùŽ?ÁЌy{5*6Å2éÜ&û>áwÉ󙪹¨¸F%;„¤Lª]ÔܺŸcšÞŶw8ïظjI]H`שTªŒé&9¡vïٛ$_¨’ô&N¶ua_Ɉº±}?–I·î> RE-” ™âÓñrQ &`ö%ë|çÉN¨7nß¹wïÞÝonâϛ~€ÔB*U^të0¡²ÉWCª$G¿˜(}k™@=qÊ$&ûb b%ñ!¨ø|&)•)“.[½aûüSl/Ã{wn‘Mŝ›V/­//ÌNíý²çÎ莒LxÍi¿CIò50µ²wõ ŠL̜YZĄ̊’ +kÔ;7Ùf“RRããIö-,­¨[Œ¯<?uŠ«{~û~äúÎM­ µ(;)½±úTª¬`œ²»ì„:lÔXu¨|- ùNK›ïŽZIZrK*iuÆí6T3šRóÙ2‰ô|¾Ì¶2ü–)­ÈMÖe E9ɑ^ôћŒé&rÊI섊•ï'L¾ÉÙsk-Ç5ê±3\ ÂzæÛw$vk+J +H ÆÔ¤ÔŒÜY%åó±LÚ±ïÈ) T(®øC7™[7kšTÌÎMŽ +ē’ɩԏ¢[·n¢ÜË8…jÿAJ#F㶩|Iò-ÁW—à[.Nž¿"ٓP¼ñÀž7KO†@Å£I˜}çT’2‰é áÍþ)òPçðî-k›Tç¦Dy»Ø˜w8ÎBO>tŽnÝDJY§Xø’"i¸² +N¨–vS½ÂãIò],²#½Cˆ…,sâ¡¢´`j<9o–Ìfߥ« L‚ŸÂ՛w†/_<çZ.µoÄÍ_òìÍÝÁÒDòÖ۟D/:–5|kùPÞý:êD¡D©Ø))|±H‚*L¨±8¡V/\F¶o±ò½C¦F€<¢ƒ¡¸ñ“ÁݟILɜQ€Ù©{ȉ&l%ð=Þ¦úþ»§¤“À‰ƒ;7­–ÚüՒ¸ŸÊ¼¾O.Z?ŝÐùÇ?2>?ç^kt:t)’&N¶Á*L¨³È„Ú¶¼_Ö%ß>–<záÔq™”•–«Ô¬¼"’}a‘zô4wCîG€¹ËŠ=?vmn]Æn)y9‘…*{ï¢;óú>´*w­ßúÞÀÛ콆dtŒÐ/¾`_-¯¬ÅÝAu-½‰¤H +ŠJÌÈ'ê:|vv†œw åÖ;ܹy…ysÉJ¦LÊH@ŠŠŽÇ‹nÅ¢ì‹eÓóãÕO?1·Î¯_䪳مê$#¦;‹¨…3Xýìw¾ÍÇ¢À^ßnó³7 Öù§?1>QèWÝÙ7À NIáËIñé3f—5¢ œB¹C¤ŠŽåãnR9)“âc£Qj,h +JIöÅgꮑKç?üôêçŸ_aӏoïÞ¸túÈÞm¸P-Á…ê4¼ ÊÝ:æÞßG´Êš·»å[%GGŸoù"üã¥u26ÑçWøféžÜÛ•Ð)¾\‘”š[8¯†lôí=Â6C§ÜíÅÛ×HíËdß",“â ûFŐ«ãEóªÙì{†´¦„@}õó/?ÿüö\º‡å/³¦™“Ÿêë&júÀ¾k¬~N>´Äv¬HZ%vô'ΰb$t~Åê$ï•îż²_oÊ:µ´sñš›’]0§zÁÒÕ¸}üûèô%^3~ Ò6Ÿm€‹Ô”&P%³ï®ƒ'Ø>.?üôó/þå—W?~ÿüñ},÷“³ÜÉ_rEŠi ‹oe«úSÇoðÑH´YÅÐ*¡T¬Sҟ4_ˆur6{â[¥¿îݛ¼±–¼Yzô8pjhj …/IÉY3K+ÈSf…zÿ[Ò´ùG¦kóÃ;7™+©k¥àÝñ” Rû.á²/”IÏ_þNÿòç_~þéåwO R•¿…¤Rr&wəúø®yÔúů eX,–­b¥¬P陒åK ¤ƒ“ØìݧO߾䅵øvӣƨ¨kS [g¿à¨ÄL®HÚÉIÄ)i±Ã¶ca^0´†ÙyȆÚ76::w²˜‡V6ûÞ}øôůÀé¯`õÕß=%•>§YÖP•R0۟EBuðÆj÷¯¾úR¦H Ì"»œXþµJ)eŒru,«¥».8¿&ÁÉØìß_W;hðPŠo7¯­kN ðLHÏ#EҚMíûŽžÂ"‰4W‡ +öÛ¶îܖM©dAC•ÙyX!‘}¿ÿñgpú+X}õã‹gL¥„[ú‹ªKqRõsw´23œ0ž}ãuŸÞ½zöìÑ£»,‘–¯8ɌÙ?Š*m­J+e…ŠR+êëÁ(Ñ«kSœ¢ÍÁC†à»M‡3oMԘ ó)8Ÿ–[ÄI‡™"‰¬4_½úùÕ+®¿ï…S‡ÉS7<ǒ‡RãbccÉ"µpN$î6.ûB™ôÓ/ùõ¯ýë¯þù§ïŸ?ºw‹©”V’Cúä2¹Ídc=-5ò^Üýûöéýõ×½zõ”5ìØ°’‰YÖ+ÏZ9§"¥¢…I±?Boø®w&8‰NbSIiØ°áÃGŒ¥߯‡/c3·˜bïâNS²g•VÖKIO!ƒbýÊ°Ø`òò9É~,伯ø²…èÍu̾?¼úó¯àô`õ/?ÿøý3nûa=^g, /§ws°Æ73ŽW;z$¾ózÈàÁ䣔-88ýñçrÁ,ñúÕW¯iåÍ)³OöȺ¤¿h¢D%†a$ю9’‰M´©¦6A§ö]=}CcòªpGWO¿ p:³Dt‹$Îé_þ‚¥ÎÏ?ýÀHў°¢aqçd¦¥$'§¤1·¢ÈŸ&hnÞýˤ¿üõïÿþþ×_ùé%NªWÎ2gÉ OØþ™ëMÐPS;zÔÈÃáC3Ÿ~¨,ÁÁÁŸ èí9½öèÁ,Œy²*vÊ>.ëÁÅu ›YÑd…(chB¦E›Llj£M|µž¡‘ñDS³I–Ö¶.îÞþÁ‘Ä)9´Àí$aáû’”¯¤Ôù¥>䤒¿ófϚ‘•‘–––ž™WPBnEa™tûRÂ"•ê?þùÏþão˜a¥J^£°kóÚ慢N9ۂU}- 5ÕqcnjVV†>R¶àÀÀøÀÏôbŽg½²ÑʋÕם¢R²w0«Xvžh€ï§¢B-Úäbd‚MSð9ÙÂÊÚÆÞÑÅÍË7 4*>•qŠ·%DEÒóï|…N¡ÒùJ^pR1ý.i¨.+)ÈÏÍÎÌÌÌÊɛU<Ü3Æã/d‹Ë$ ÔþöÛ?!T!ÿ¾ +UÌ¿m+›ê¸w¹ã»qM õt´5Ç««©ª¨àG+Sp`FãÏe$¦Èñèµ2Û˜‚9«])•uŠ©—݇ï?p¡Ê¢y¢OÐÀ—Ò‚KÉÙD™fææ`ÓÒÊzŠ­ƒ£‹«»—ïô`|w Yd.j†Â—-’ ð§L¥ówR¿‚T&ýÜÕï҅ó+æ̞•—›““3#¿`6Ó6©9ÇB©?ýòëßÐ)Zýäßïqû÷ +9¦ßJB5;%6,ÀÇÝÙÎz²ÙD#}= ÚZššðÉÇËUUø­Œ!9^ j2¢’pw&ÖµGi˜@eOÒ3Ëú¢R¥a#F)Á*–E𠺀žžž¾¾È¦X¦½ƒ£“³‹+¾eÄ/ 8<:>Ÿ¯ ”Õ å )’ÈÆ)̉gêW¦7{h[ÝÜXW5¯¤¨`f~~þ¬Ââ9LÛ¤vöI*)“ Pûí_ÿúí7UÌ¿—cìÙº¾¥©®¢8?3)&¬º8ØXM6Ç÷sèëéágב%8,Úä炩r¼2ÖdCP+“ƒ¿ü¢Ë­J;e—Òá£cUÔÔ54ÙÌj`¹²+a"`‚iVÒ¦½ƒ“³³ËTW7w|ň¯@PhDt-"Í!›Á)^?¼x ‹$‘S˜ÿ“âϸ)¥¾±zûÆ5+š̯˜W:»¨°°pvÉ܊šl›´=pƔI¨ÿ~û§(ÿÞ`_cζgOŒ ôõtuv°bi1ÉÜÌÔÄ>¹±,ÁA1„Ÿ‹¾ž.¤M uR“Á +j³‹…V%bµëœþÌ§ìé“þd^yÌ8Uu X–è2Ó$¤ÖI“&#ˆ¥¥••5Èdm™àÒÛgš¯Ÿÿô€ `|ñ{l^!"ã”}„úÙú+©sþÉNŠ˜?™>;í›×­\ÖX_S1oNiII露ʚ†Æe؍…\»ù†+“þñÛ¿þø×o$ÿBý{Ÿ}ÈÓ¶ +›9æ¦'ńûûxº¹89ØÙL±¶²²´Ä?Y†À¨˜ÃÏÅÔSžî- uÕq̃µWÏîìóù®›V»‰®~Á:ÅÇe£ÆŒS¯ MX–@0’XD€booïàààˆimbdúLC—ø΂аðl´Ÿœš‘=cÖl|sLÓòVâôîbáûÔ9¢9¤Â¤øü1é1yìÀ®­Øc{a}MUEYYYyEu-8]¹›<0Ê–Iÿä¤þ“É¿xüá{œ,tÉ«Bƒüñ­SS]œà£ÛÉ›)ð{ÁT`jbl¨¯ 5™ê¸Ñ£†+ ØÁj×Hí&u5œa:V”êáBs²¥õ|¢ñ7uª+⸻{xx™\d††¡Ë˜Ø¸¸x|ç{*¬Dr±Ä)¯®[´´eÍÖ)[øþü翊Ó'i°(üyöÄ¡=;6­[µ¼iQCmMuuuMmýÂÅàtã62!_'JÊ$púÿ$Tÿ”Jlﻍ­ËICìÔÄØÈ°à_o/Owwwüð®²ÆÄ~.NøªÈ)V–“ÍLŒ ô&hª«ŒU1lÈ ´Ú£»ä´ÚUR§äÓ æ¨( Í)¶öŽÎL,‚?Ÿi€/àøûãûa‚0Ïbd‚LÜÏKI…ue¬Brg@3»tnyu킦æUë@ öݸ|ƒ-|ÿLjWŒ´ý‹[i>%COÙ¿kÛƵ«–/i\ØP__ß°°qÉòUà” t Ôà7ñ÷¢Ó£UQ¨’_öÞÙ@J­¹³gæf¤&ÆEG†…LŸîÜWvàxLóŸ ü^Ü\]œím¬-'™èjk¨=²ƒÕ®‘*Tæj^y!@u ŒM'[ÙØ;¹`ËfÖ à`|}‘ ¡ 2“’S9—yyù3gÍ..3¯¢j>FYKkÛæ{X§Lá+vÊ¥O¬”ᕘ3Çímß²aíª˖4-^¼¸iisËjøQìÜǜæ ¨ÿ TágÁÎÊ·I¯H૛×W—•æ“{èñ±1Q‘ááðÁCeE!88(~/þ~Ó¼=Ý]ñ•½¨U_‚•³Ú“}}`×X*{iÈ°QcTÇkëšL²´±wvõðžElHh8ëˆÃÇ&@Bîʦ02³sf ËBp …Íœ¹óÊ+*« o.h\ÒÜÒºnã֝{;Mn·="…ï¯#3"ɞhÿ`'U¼=qþÔÑ{vlÙ°®uUËòåÍËW¬\½¶mÓ¶]ûŸ`·ŒÅúï3VágÁì*1]‚±Ma[ër¨ +a]43/'+#-%ÛFÀ“811ÑÑø{ +ðƒÉÛÕÉÞ÷;tµÆ«ÅÇÞºDª(PIò%W^F§F¦Sì\=}üƒÃ"ð4 ñ—Š{v@ùÿÚ;¸*ŽµÞ{s“›„$j=ìâéŎØŊ½€  ¢""ØÁ‚ ˆ {AAA)" +‚€¢(°€Ø{/IŒ7¦|ï;³»ç°pèÙ»O~÷*+gÏìüç}gfwæÙé®®3f`db`ÎC˜‹—x#K|=mÀŠU«ñM‰›·nߺgoôø¤ÔŒ“”)3ð¥LÈ™á+æ_˜ÔœÍ:~ôHB\̾ð°];ƒƒwïÜƝáL3r& +Ÿ~ ¢¡JÐ×ÑÔ03-éÐþ}»wnÛ¸vÕr_ïEž0ßõ˜é6ÃÕuút,û´²Ԉ“¶—Iímm ó>°v7í¨QHÚªµ¾¥ËÞ**Tu•ÝÜиE©²]g³^懌c5Þ~âä©0æqA3+h6hΜ9sç΃À$‘¹˜Àô”+eàÚµëÖoØHBlç®Ýáû¢c%&§Ï:“S˜)3¦O$LpáïÉ ¤º?j_Ğݠ=û¢öÇ%9 +­‚Ðyϛåæ2u’­ÕÈ!zw뤑·m ˜†ê*æ¥èLöý7}±cG&Sw2ë LÇÙã+òæy-ñõ_±*æ4±n÷ÏmíÀ°D–,ÌÈèh‚òàÁCññ ‡“Ž$§MK?~"+ûl„)®}@™þò«.’ß~£C%4|i*úçœ9uòxú±£©(rŽSÙçr/Q¦ì Âß0Pÿøãr +Ò.^‘‡=·H´gŸ<ўp06ûæ°Ð]!;ƒwì؁%*;A}l%íe=Ì©Wøû,ñšç1ÃÙÁÎjԐþ½ÈZšæMÔ­MB•l‘-ïü«—}ÓÖVd³wÿ!ÀtŠËÌ9žK|—㻡·lÛLù……í&ƒ—={ÂÃÃ#ظ$,”À29%õèÑ´céÇÑaùÌ9@š_pýæ{x_éº}"¤O¤z1ç\ö©¬™Çg?žy" æ\ÄìLÉtˆI¾üA¨r ˜Fûõ‚¼‹9gNÈHK=’ð@lLtä¾½áá{ð•œe'¨ŽÐÐ]Ð^vÀìkÓzòJtÏ93§M¶³iѯ§i{HÀMi¨2[´ÊÛ"F/ûVÿ¶v]â¨éÜÃ|ðH+`ê>_#¼vã– à°Ý$£¢¢A1¨ýû÷ÇÆ q™p˜Æ% Ä÷dfž8™,ΜECH@J6WШZ¦,’ß0{$q¯éõ‚üKrΝÍ>}úÔ©S§O““\¢Í‚œ‚K¾ü¡=F;>ªø¦¢K¹4ÜÓR““'Âî96 +SfªˆŽÂ×Aîßcí•þKÎEª–#p-Ff‚¡Zë[²›²òo5æ%ä¥zø¾‚†M[I˜M¤¶“]Ð_!` Þ  ß½?6‚¢1>E:; Kd™JÂâòÄɓYˆ!;û 8€^ºœ&· L!õ’3zL):We¨ÞºqõJÞå‹rΟ?wîÜùœ\Ú,nÜbš3t֞Aÿ¸³ñ浂<Äz:ëÄñŒci©)ÉG’’±‹N(CAeÄÂö»?:roxÞÚ\àƒ‡lÇлk% Õï*êµèÕ´¯4Å×:Õi€o‹i‡s£qÝõ¼EøÆÙ aø†¼x‹))ØÉ¥ATbXfа–„$¢ÌÉͽ8/]ÎË¿R€þH·ïÞ{<È¢¢×…˜þ¡›€êCÜíýZp½té"{@JšEa¦‚´T¡ ºf´ÈÃx?CóxFzú±cPä£e'ÒáC$〒|LdDØΠM+|Íusžd3Ê¢_Õ6d‹¬ŽEA9Cý‡îKõÈÛbˆ/îàÇõœ+ÖmÆYî'/ނá +Í«™'ˆN‚²hXR–H’0¸œ——ŸŸp^½†ž+·ïܽûHŸÑgm:LuˆL©B¤Ý¹^ÎW ®€ + +à4é¸=WoaJÏñV—ê#ï× +ò/_º{þÜÙ3ِȳ² È'ÊRPØí§K;Š¯%‹Û¾kûæµøZôSí­†„PUÀXDò/Û©V TúžZö%Ä Òenܼ#lot\BR +Ž?!IZ„DçΊʼ|Bàêµk×®£uäM|ÅÌ|êÃGd'.s(ÌT7Î^$Ϟ<~ø· ߺyƒÏgyˆaªêÜð´a U\CüÖëW ò!à/^ÈÍ¡¹ülY +ë";ÚKÖI|/NJRüèˆÐè’ééáâ0~ôóîÈËîÔ}ßgyŽ”ØqûžZæ]]½B ’Ák6Әƒ‰)i'²`´Â„pD]º„AI¢’a‰$oâHnßF‡»wïÝ»@!HéKi!¦ºqF—C°"Öû¸·œè.mp’…BýÏ?‹R}‹càÞ¿‡ ƒ|~~^ÞåËXä‹e*¨ÜÜLÐygàýŽ˜½øWÿÅóÜíq‹–i;9gQP*•{O-¾)±[_‹ÑŒq ZšÇàÛ|ðådÈC"B¢«W¹¨D–HA¢΃>œ¸yÿé3²W®0·×ò§¶[Eª¸‹°>~ôð#¶]¼,ê>ÇoE[ñס P܂2Öt4$à,3Fì Ó^³\lF îkÖAٖ}1z¼í¾šöåäKű/yÐX{G·yKÐç(ß=qæýq {•M«T· +%’D ' §¸I×ß¿|Å!-¦úT9¬ÏŸ=}úäÉãÇô\ÚvO`ßÅTÛ5ëžâ ¶ !û6÷fي8þÓT@¦Ö'ñQ0y5äò%ófLµ;”n‘5Õ« ·¸²ƒ_2Nb^ÀÖδ×Àã&⠈'N\bjÞr¥¾­·(À»$ïј䂒’$ %Â|‹ï_áv Jqè3ý믿tˆ¼¥OáÈê—/_¼xþüÙ3z2¶]¼.Ò.þúëÝç §x΄<îSÝ+KÝ¥B§ H×®â}0¤zø.{[éãéáL·Èjd­›5$^¦ø¾åO*ªvœÄ¾þrð(›ÉÓç /î[IA7Ht¼I‡<„#H J-HÜ_ø +iO\/ˆ«s9¤Ó¿Š¡Á +LÊ«W/‘vÁ!ýMçý¥=‰þ9ئñœÆ< úGe,RhŽ¿Iîbe㪠´– ô[4›¼ð³7÷í +y3ºÞà÷û:ø².e‡næCÆ0ïu +¢ûVˆï 2Ñ|DR!£gléÄ$ˑˆ,þÄł”Ò`g§êÑaí .E(¸Ê›9_¡vQäúçÐk󀖉úgOËXOhï.$ô]fi¸g:h}€7ä_ÛÑÄÌ ½L Ù^–?T¼ñ[·A“–bU§îýð­z«¸×Åàã®Û÷б +ÈÆ#“,JŽ#e‰zC€âÓð÷ ÕaáŠkGµíâWývñÎs°ÁÊ`E®¿–ñJ'ì_”±žÓ¾ý¹ðY0}çFðÆU> ˆ™z™êØ^VÔO TüÒqÒp+杦ä5á'¨/Þr%ûÓ(@.‚ôCR‡#®@¢«ÞÒG2ïdªK„A‚\‹nÃø`»x×9Þ0mƒFýÏ\䗩^Ѿû >Š ¤pÛÈސ-k–-d͜T:ï<*o×wýM=QÓVRM'Y;@—º|ݶ0v{/ٞ†óþW?1µáÈ¡ÔÅÈ¡dpêՎÞI„CBÀþWïlnï:Ç°¿Ò¸§ú¥Œõ3j£—Y •Åì{ö_4ÛeÒ¸zê¼Æµü_º¡ •ÌhZË4¦½Ô}M8ÙÞËn{az¶Âá¨E©Ïñ­'Kô=HY",’ßé‚£]¼ëlãÐ)ê¯e-ÒwëmÛK‰çÞN†^¦újt-T:MÅM×ރGŸ2cþҕƒÃ÷£¹nï½Çl{yý«n,ŠÈß +cäÄÞ¸g§”ï`Êùó– CVï”nzXÿø½pãøoùè 3·Æg~÷ÈfžÌ£ :]ƒÈ›TšUԛT(TöÞNSɌf´íT7|÷ûΈØÄ4jmó€ÛŒ¤ Q? ‹ äXê}ŽBXY°ïk†œC·¿•½È°î5·™3¨%¯ÇѾIåNJy“J¨0M5ëk1ÆÎq¦§ïêÍ!{ã’Ò³Î_¢›‘è“mfmQ€ïÀX„æ‰ê"ùó]çÑ=•AçxOYËBL;ù/·ì˜nf/lPû®7©TT¼¡ÔÜDÑÁ¬/LSaF³l͖]û⎤Ÿ"[Aqé4Ykð[ž£hR]$…Ér–÷£ÜȒÌfv­íÚ_Owªþ›Tʪޭ_j7ó!cí<¼–nÝy09ãtNÞ5Ü +ª³"ó#QTbžE‘”ü<úŸyOà—~çV½½|öbrNg$ë¸Wìëq´PÉ­_¼KˆP‡Žµwöðò Üu(åxvnþuèRŸ¿üùµÎú‘4˜dñÀ–Å9ÊV V²ê ò/:äçfO>E_ƒPñõ8&ÍW$ÔOt ¶Ut¨–œ=ú­…i*»T +õcDKŠñÃ\J†òR¥P_=Â@M¨Ûýz8O°¤ïb þ.@-*õwꣻ7 .ž­šPg¨1 G¨Õ» M`^‰T¨?½jLU‡zO€úéC½'@僨<”•‡ òPTJ€ÊC Py(*%@塨<”•‡ òPTJ€ÊC Py(*%@塨<”•‡ òPTJ€ÊC Py(*%@塨<”•‡ òPTJ€ÊC Py(*%@塨<”•‡ òPTJ€ÊC Py(*%@塨<”•‡ òPTJ€ÊC Py(*%@塨<”•‡ òPTJ€ÊC Py(*%@塨<”•‡ òPTJ€ÊC Py(*%@塨<”•‡ òPTJ€ÊC Py(*%@塨<”•‡ òPTJ€ÊC Py(*%@塨<”•‡ òPTJ€ÊC Py(*%@塨<”•‡ òPTJ€ÊC Py(*%@塨<”•‡ òPTJ€ÊC Py(*%@塨<”•‡ òPTJ€ÊC Py(*%@塨<”•‡ òPTJ€ÊC Py(*%@塨<”•‡ òPTJ€ÊC Py(*%@塨<”•‡ òPTJ€ÊC Py(*%@塨<”•‡ òPTJ€ÊC Py(*%@塨<”•‡ òPTJ€ÊC Py(*%@塨<”•‡ òPTJ€ÊC Py(*%@塨<”•‡ òPS¨w¨>Ô»Uj´µz7Ôè*Õrâ´Y‹ü ÔT +õ¡õý҃úBM%Pý͚6Ѳ +B=sñŠê[jQ¨oµP¯\yþê—_ßT–j©Òy”…€)@}óë/¯ž?yxçFþ…ì̔ø(-TónjõŠ‚ú/-Ôæm(T…~ÛB£¥ÏÎÍ¿~ç@ýùõªeJUW#Žºúƒê›×?Ôw®ççfO9º-Ðo¡…ÚAѶ¹ê¿*êõÇÆÍMꐱöN^~[C#%3P?ùók’‘jùq-G²åS\R¿“ìûúç—Ï3P“E†n ôóòp²;¡š4oü#Bý¢¼¡ÕüCj#„jÖ¡º{-[³eWäÁäŒÓ9y×nßüì%tª$T¬eªrçúe¦ß SȾ?½|öøþíky9§3’FîÚ²f™—;Bík†Pé@ýÇ?ʍé; Êۛõµcçèîé»fKȾ¸#é§Î_¾z oþ¾"¡úÛ[ÄZfzÚò"ZFÙèíÛßH ¾Â[¿·®^>*ýHܾ-k|=ÝíÆXô5k/¯¨ßÖþ±Q³6µÅ[Ǚ |WoÙ{ éXÖ¹KxKéÉsªëÛ²%‹* ¶ì‘–=Ìߑç[‚”*Œ“îÞ,¸t.ëXҁ½!›Wû.˜éh;Æ¢@mӬяµ¿­8¨Ÿ°P6k#k×µÏàѶSÝæ/]µ)8"61íäًWn@§ú Bõ—_)Ö2Ñ[é‘-[¬zHuH0*‹+A¤¿þú ºÔW.ž=™–¼iÕÒùnSmGîÓµ¬M³†,ÔO* +ªÑ7ßÖ®×°YkY;ÓރFŸ2cž÷Š ;öÄ$¤ffçæ]»uC¨¾¬ÀµÌ¤˜ãZvTõF3ÚÈbX”ÞÒ×ÀõÞ­ky¹Ù™© 1{vlXá=oƔñ£õ6m'kݬa½Úß~cTÁPkÕkØ´µTcÚkàH›É®s—¬Ú}(%ãôùË7ïzpçfÁåó§3REïZ°d®ëd›‘{™j¤­›6¬W«B¡~PkÖª+2n%Uwé9`ĸI.³ñ>ahdܑcYg/æ_¿uïÁã§Ï_ ֟)½^kÅ"¦d9¬eB•cÊ¥8œJy5?#Òϟ>~pïÖõü‹g³Ž‰‹ Å»„³]&1 gµ´•±¨n­šõ³ +ƒú9µ¥DÕ¹GÿaV=pN²7öðÑÌìœË7nß{ðèÉ3ÀúòÕ«ŸÊD?S1Œ™´NâU'X˄éït€ú͔¿RŠÌחÁ…¼zõ>{òèÁ½Û7 +.çdg=»7g4έ†õïÑY%iÉ@ý¼¢ þ ~]óû: š´“›¿0Q¹ÀgÕFèTã“Ó³Î^È»ŠT>~òôÙóçÏ_”Z/½zEš¢e¹2ÑZTµaÊ PߐLù !‰ß̖âeé.jäÙÓ'"Ó«yÎf¥'ÇC—ºq•Ï‚™0M%·~Å-›4¨ó}ͯð!MyC­Æ@ýòëß×!7;ÀDu´-Ž”ÖaþM<šyúüÅü«7nݬ?~òäiéõŒŠ¶ýö×_9¬¥¦ª¦)ö}ô¡ˆ(¨J{-Ož<~üÞ¹uãjþÅó§3&bö]€ã$ÛÑxïoýÖùžyòö¯ò¼¡¤ Óл]{iã0}ö"¿5›w†C¨;™}þb^Áõ›·îܽwÿÁƒ‡DJ­Ç±…y 5|çæ5~‹fOw°9¨wWöÞC¯* +*yLÃNTaø #¥áVœÝ=}Vn +ÛwàpJ:P½p9¿àڍ›·nß¹sç.Õ½Rêþ}h!ÐD0úŸ²\ë›7e@•éOY¦ Rìû'â Ò\SP#·oݼq­ ÿò`šžrøÀ¾°  +}<ݝ'X ‡q ~µÓÔò}H£Gç40ü•¨:A§:Ænꌹ‹ý7ïÜ—˜š~òôٜ‹—ó®\½výú ÐÍÒêèömh"Ð6îcZ'\+v®o0³TK¨lêý•N:^`ß™X"‹Û·±¥»¬Œëׯ]-¸’wùbÎÙÓ'ÓSã¢÷ìÜè¿xvc Kí¤’Ààg4p?Ÿ@å&ª0ümФE[e³>ƒGÙ8¸ÌòòY¹~Û®ˆ˜ƒ‰)Ç2³²ÏžÏ½xér^~~þPA)ut [ÈMŒ~HëÀ±2ÁÊÆjICU›|¦,҇$Ubdݸ~íÚ5(E©.«j$ïò¥‹¹çÏfgeKI<±kÛú•>^³\lF îcÖAÙ¶E“tFÃMSË*7RjÞFÞδ׀á–öŽnsû­Þ¸=4"&îpòÑô̬ÓÙgϝÏÉͽpáÂÅRêèòåz,#ódÖ©ÓÙÙÙg@gK§sçΝ?Ÿ““{?€½që6b}Bî[1TKª\ò%ý)0Å0}LF¨@´àJ>Daqþ<”¤ׁU5rúTÖÉ̌cG“ãDÓMË½xLs°maÞ½“ZÒº)t©ßUç¿å8£ÑéH©V]Q“–m0þ¡:Õu¶—OÀÚMÛwíÙøHJjÚ±ôŒãÇ3A'J£“ ¬,h §³Ï@ðç^¸DFa0gºÿï[‘Xe»Õ’BÅ@}Kžs¾&LñÞÀÛ7¯_ÅΏ„Ö`q*+ KSòkÁÊ8~<#ýXZjʑÃñq1ûöìÚ¾im€×lש¨aì«hÛ²‰¨n-vœT¾ƒ_½‘tª4ÿÊ4!TGYOtr›»Ð' p㶝aá‘1±q‡“Ž$'§¤¤¢Ž–Biiiǎ¥CÉþ+׬۸e[ÐŽà]¡¡aaa»K¨=Dááá{¡}DEï'I=9õ`=sž¥úäY;£³x±äP_や§)ÓK¹ç`֑ž–’t8þ ÆV҈§å*Ñ%Am„†î + Þ´mËÆukVúû,^0ÛmÚd;«‘æ=º´Wˆ[Â0é‡ïkÐì[îã$®S%ù— U© +p jëàäê1×k±_Àª5k×oØ´y˖­Û@A†k;§;vïÜ Í#lO8$õظøÄ#8e:sþP½u—<º-M¨²Ù— ÔÇï¦9gOŸÈ¤ ÄDí‹ß8vïØ¡-¡×…Õ±u˖͛6¬_»fU€ŸÏb¯¹®N¶À´?$_•T7P1û–s—ª›éP BÕ¸¥ $`3¤j9~âÔin³æz.òöYæ°bÕê5k×®]»®DZO´aƍ¡ylݶ}ÇÎ]aá{£ö֔´ãYx‹=|üŒYæö¶D›wþÔY‹KõÑý;7¯]¹”{öԉôÔ#‡ÆFd¼=h+ÐØ´ŠDËV‚‹‚Ú \³fõªþË|¼yΝå6mêÄñ–ÈÔ ’¯IKc T2LªìËBÅñ/NU!Të7jÚª­\C¨Žcmïàè2Ã}ö¼^‹–x/õõ]æççO´¼D +­X±r4µë6lÚ²m;ŽÁ¢bNªgr.æ_ƒLC•Í¿%ƒÊ®ÅeõzÁå\ˆÓôÔ¤ø1ûÂÃBvmÝ´qýÚ@À±råŠP®\­ +?¿e¾¾K½—,òZ0o¶û G{ë1#S¼m«¦êc Â0 Ǿ•Ë¿4Tq,jܬµXTÍ eicï0ÕyúŒ™³çΛ¿ÀÓËká…‹ ×bFK–@ÛXêcyÀÊՁë7n + ߃T3OÍ½\pBõÉ3.ÿ–*ɾ4Pñ¡X62=±;dÇÖM [®Xîïçëã³ÔÛÊÅÑÀ+ƒúðòò\0ÞÜÙ3gLwžê`oc9jØ sdª·nÖX„C_.PË=ûêä_ Õ¯ªc5iN¨víÑw€Åðі6v¦89»¸Îp›éîîá1‹h¶ášš;Ú4Ž…ø>~Ëq¶u{Ȥšrì>¹½vó.]»XJ¨ìk\FõLVÆѤøبðÐàm›×® +ð÷]ºdñBdÞܹXº9^­ +w÷™n3\]œ¦8L°³±=Üb@ß] ÓæMD˜|±GÕ“**ª_×ø¶VèVª\Ý¡K·^æ-†ceck?qÒä)Sœœ§&VÓ§OwumÃcöÌèÞ¾0²†ypÈî}û%ÍÈ:¡zƒäßWÜ6R@}MVÍ?¸{ëyz},9á0ݱuãÚU˖.^è9îìYˆ¸BḂºpuPNNŽŽS§Lž4ÑÞÖÆj̨áÍ{uëÒA-¦Ð¡Ö©õm¯µZþPuBÀ˜€ëÖGªmeªöºvïm>`ðÐá#Gµg3ÞÖÖÎÞ~j¢šDäàà0›†“ó´é®n³çÁlYÀêu›!V£$$;‘}þÒ’Ÿ¿ü™ÝfW¨ÌbܛWórÏfe¤&ŒÙ¼uCà +¥ÎŸƒù⠈L™ …£¥4èÂHmØÛÛÙڎ·g5vôÈáC0ïݽk§ö*Y[dZ¿.&_2ô­ @Õ U’€¿©I¨6iÖÊDªPwèܵ{¯>ý ²:lÄÈQ£ÇŒ;֒ÊÊ CY[[Û@Ë°³Ÿ0ÑaòT'י³æy-ñ]¾zý–¡{c&=~ê܅ük·¸ ¥„Êl…¸çFÁ¥œì¨±‘»ñ6ފeÞ çÏq‡ÐqŠÃ¤ ÀdüxkkRL.‹©‹±cnj=jäˆaC- èקW÷®;¨R“V͚¦5¿á’oÅ@åÀ0WÅ\©þ(jÜ´e±L©ißÉÔ¬{ÏÞ}ûõ0pÐ` ‹!C†¢†¢áD#FŒ9r4Œ±–V֐Ï'Mvœ6ÃcŽçb߀5¶í„P=œ’A¹‘Nµ”P¹Á/Ž“n_¿r ×%ÄÇb›×â=Ÿy³Ü¦“.p¼õ8˱cF”‘PDZÖâ_©!C,,8 ¿¾½{v73íÔ^£”‰Û´lÚXô#2­N’/ÌQ+(PõBõ³Ïªu~52nŽXêv:uéjÖ½GÏ^½ûôéÛ×Üܼ_1Õ_« A³2tØð£ÆXŽo?iŠ³«û\Ï%ËV®Ý¼#lß~\j™C…qRþÅs§Ž§&ÆEíÙ¹uÃêåKΛ5cš£Ã[k’2‡ T 8 ª-v±.j¤oß>}z÷êÙ£»Y×.:´S+isãF¢ë0L™ä[QPßEµÖõê7lÜ´y«6m%r¥JÓ¾CÇÎ]LM»š™™uëÖ­{±ÕƒQOP¯^½{÷ékŽ!?xÈ°£-­m'Uy }–¯Ù´+"æÐèTsÊêZ¨¸"ÿ¹¬Œ”Ã"wo^·r¹‘7u’ k „œÙ¿Ÿ9áÒ«””-u1/jꥫ©i—Î;´×¨”rIÛ6­š7mÜ°~½jUS„Ê$`†ê75¾ýRpƒ†!Z[W©\¡T©5íÚµoß¡C‡ŽÅS'VA]ºÐ6Ñ­{^½ûš÷d1lä˜q@ušÛlOo¿Õ¶…„GJJC¨e õ +㤔„Ø}aÛ7ჱyîÓì¬-G 2x@¿¾}0ʺ™uE2]°¼\á‹s¥P'íÛ·k§Q«” +¹ˆ¶†(mÜ°¤Þï¿­ñ ǔI¾•†ªUc°¬Mš6oѪµI[±D*•ÉärHY<©©Õj[4‡N]L»vëÑ«Ž©GŽµ¶spr5ñ²•ë·ԃjÙEêmúe î ݾqÍro¯9nÓ¦LÀ{ûõíÕ£›„Y§Ž” +̖½8׉U"—ËdR©DÜÖ¤u«͛6!H1LaÜ«Ë´¢• UHÀ”ê—_}]‚°Ö«/®Æ͚·hÙ²UëÖmژ˜˜´-–ÄŒ$ )i +íí;têljÖgJÃFá½åéîó1P1ýžÉŁR~ß0£_(]ý-0R§N÷X°ÄõÆí¸ õø©s¯\¿}ŸZLèZüƔYÌB¡>yp÷æÕ˹Ù'ҒFïÙ¹W…Íq#O<‡âý<˜V„Œo {6…pkŒŒ°ôô:>z¹¤^êÕ«[·Nj×B¢5k(%H+‹)ÊR%ÁJ±B¸"X hkÕ®]û‡¨§ºu±`“üݸ †Ò2¥†@…Hµ?ÉiÆl¯¥›ƒwGÅ%¥Ñm“ÄŒ@ÿ)yñ©þ©õgf7Œ”N¦'ÇïÙ¶~å²EófN›l7nÔÐAx“¶c;•\ +³–Í›2 ”DRBN¬>xáP7PCßO +AJ‘2©—cZ¡PYªL°²X‘ë×ß@ÄÖ¨YØݏë{*¶`ˆ“~™¤MÄjϾ‡ŽÂ33çb—º »Trï!ï*Þ%Ôqøù£°#O1Įչ¥Dî>°ê’Ó§N°3|p¿ÞÝMª¤mkdÚ¸¦PŒ9-'¢]5VÔQ ˆÐo¾F¢,R6L+i!ª+$áÏ¿ `¿"h.Uª&mHs7bªÆͨ»tëÝoðð16§ºÎZàí¿f“^ö½ÇyÁü¦»Ù0¦Tj¯›Ùü»n…ÏÂ9nζ–#‡GdíªIë–ÍSìiýŽ‚ªù‘‹ej+p~E€~ñ9$^‚´2™êRe±"WÉ¢¾bõõGD[Â%c­êԃ9o£&U"WµïÜU7P}W®Ûº“›¥Ò'o/´Kõ=[ŠEôvu>.ú}AŸ½‘ÝÀd¦´qµn¨âC2Bږ@mØ'#d CŽAõquBjy"P$Ê!­<¦…±2\ X KØ}ùQ1ü¿þšäío¿ªôþT³–mÚb šv'äñ“]g{z/'›@oçkŸ‘³Û¤J`±Æì4&;£˜§äì-ý(ª¾¸0w²Õ¨¡ûö4#¡JïìA ’Á+I¤4ð«Š­¬¦ÿP  ÑÊFªC•Ã +\,ýŒÀeõù‡EÑXÄZó»ï)Ô&M[Ðçy]ºõÂäkCßù‹ýV­ßFo'ežfŸ¦>c#õ·úp½å¶¥2 ÏnàÒ*‘û›Ö,_ÊÎj† èÓzU¥¬më͚4!TfBB2é— ¬÷I§VH-}J€Q-ÒJeÊPe±"W‹d)[NŸ}X;f}¡ú}í:õêãcL¾êöÉê§Ñãì'“-+ÖÂÐ7ò@BJ:»îúZÇ`ͲœéÙ>þ3³ì÷æ5ò B5:À«ü0;N´;¢?Ž•4øøBUTŸ@­Yãf´ó9Kë=Ò«RSŸP HT‹´ò˜êa%\ XBöïGô)“³q…·0T TH¾bìPÍzš“ÕÁÙmŽ×R|B +C_ ÔsÌbB„úcPBƒ5jZ…{)Ô[s TSð9yð–µ+|ÍswaGÀ¸öD!ªÆ˜{¶ôÎÁLïÈàú¸:ú ”­HµX)W +–AË꓏èßÌ‹¹Až àƒ¼­Å2” ’l`Šê¹Äoy@‡&gr ûâbn€ú’ñázS2ƒ5jzŚV‘ÅÜ0TÂP=Cöý.Sì¹Á’ºÕ–¸T¡^æF<¹wð›Mß/½Úajì:D+)ªšWŽìÇÅAÿ·öfc ¨|[ಧvX¦“˜ç3ë¶ãóñ#i™§Î]¸\À@}Îøz”Ü_¸%1ž‰]$šrø@Ԟmø¤ŸÕL¶·=Œ¥*nӂ.V O̘{|ÿ港Øj«V…¢ªiõB*ÙOè½F„JŸ¸7Àµ­TÉ0ii _ù‹|WnÚ¾+":.‘¸…à}º‘ú?üôs)üÕÐùŠ˜±<¥Û¯aþÍÂPÝ¿/,x t«Þž³Ýœ'ۏ=lPíÜ^%·n ˜„ju„Joò}òQž…+I§þ*¥žªé«p±ß«jïI}«ñy;³ ˜âunçpœîN—<@òŒ…@¥ëóÉnÆÔþø+•Ø^˜_½ n,Ò}Œ—sϝ>q,åp\tÄ.\©´lɂÙ3œì(U3¤Ú¶Us\+ö†êW*sK¨·w«P­U6Äw©šâ¨~¢}Üþ]­:t›D¡éˆëà ө.îs½–úã:°½d!w橳9dÛ± xLí•Jå®FœÈˆË}b\…P³Ofà"ýHHÀ|͟åêD©šÃtµRjÒ²$` Uîéö'Sƒ*£²á}PcežõàcÙ¯«û=Œ’°CËÕM{ôÀx¾KÇJ¡~öº6’/ ’:té֛nºšBö½âÒЭÁa{£$9šŽT/ IÀuƃ‡:g•Ì\í!gEvÿ:ìPë*âst<-ùðÁýûö„m"KEçÂÄf"{‚.ªo‚‹êéìÿè®CáÅ⋍Uº0‘."þGIM[´µ³Y¯~xÓ&yÌ[¸ÔYš¿/&.ìOE€KyW +ˆÏ­Û:Þj†¹«q"^dh™„;À4÷ü™S'2ҒŒÍÖø’u…S&Лݺ´ÇLC•Y­«µ²k¸2¤õsvkÙpE’/3™AÒÏ%ËVnغcWxä~€šzìøÉSg€êÅËyÄ[éÚuj­VroµŒE;²KrΟa¬Žpç[ØÎm›Ö®ò_ + XÛ­BæB•ìáöJTøî*#}¨ìÎèQ!PÛw†ä‹w|í';Ϙ5êڍۂCÃ#câЦ)¨fŸAž‹ŒoqV+±·ý0º‘åÓ¤œóg³OÌ¤É T´ÜÀP3“KÀÝ»´W‘P-²æjá94û6ÆU7Pq”´Øwùêu›êž}ѱ’ó-ꬔ““KŒÕJ鬆g@ ¬œóçАìÔÉÇÓÓRŽ>t &’B]³b™7ÝÍφjGµ¼m+ÜRZhûaÅ­í¬rª¦¿1²:—}í:™ÑG3vÔGb‰oÀêu·îÙsà`Bâ‘´ßAc¥SèšE}ÕJe¬FN@ýÈNeDÛ¤ci©ÉI‡ÅíÚ»'4˜@õóÆΓÙ^µs;…„Í¿¤S­à•õUP… b—Z¿!d_ ;¸Ô ³/º|ÕÚ [‚‚wÕh꼅¾JiÄ4‹Úª•ÒXÚ‘eÂɨ Öєä#‰ ñhâ±wOXÈö­›Ö­Àío³`¨¤Í¿Ji›Æ ëWü¦ÒªªÂPI—Ú´¥‰TÕ¾Kw˜£ŽÄ9ª3Dªçbÿ¸‹¨†¡GËþqh«”˜t„˜ªQWµÒùª1§H!ŽdG’'ÄB£(tñØI,V-÷]‚ûß´PM;ètªT”ÔÏ©…DÝ'©,ÔÉN®îs,ò^¶œÚ3¡E˞ˆ½‘QÑ1ûcÄÅdLÕJg«¦õ#CG²CÆ8»?&:vBC‚ƒ¶nZ¿vU€ßÒŞs=f8O™0ž.X¨2íHI€ú:P?}'TH¿ÄîÅmÖ<ÏÅKêêµëÑ¡%xç®Ð°Ýh™µXª1žj¥pUÓu$‹ŽBO²È}{÷F„ïÙ¶‹XílÞ°Ž¸-ñš?{æt§Éö6cÙH%P0PYë#j¨˜~Ɍfô8²q&qðõCƒ–u6mÞº-hûŽà!!»v…Kµ’›ª½Ë’ MÉBwQ¬íÛ¶nA¯5«Vø/[Šî®Ó¦N²7f8®ÐŸÓPÿ¯pŸª;MmG± …ük7i*P5w×bo?àº&pÝzj˜µeËVâ¨VKµ˜’mE[²Í›6nX¿n-ZY-÷ó]ºd¡'Ms$.9¸²Û¬s;2PúT­Þ=úmޚ>¡éÓßbøh+{ :ÝÍ}öÜù^‹€«¯Ÿÿòꗅ~jh¨VRKµ÷z’[2ô%[½j劀åþ~Ë|–/«9n§öã­Ð&§O®‰MN¥XªTU½{žJnçܦ—ùÀ!HÕnâdGÆokþ¯…‹/ñ^êããë»l™Ÿk¨VRKµw{’[2¿e˖ùúú,õ^²xÑB/ÏùóæÌr¤NS&ÙÛX1„øägªøô>§ êßQú‚½£Ôˆy˜jÚ÷/5vÜxû‰“§:M›>ÃÍÝcÖì9Ô.ËӋ¸©•ÈO­8¶dhLæåé¹½Éæ̞åáNìv'Oš`km9wªÒU…’6Ü}ý;J•]¹•¦jzjŒ+S“檸ì]™,†m9n¼Ý„ISÐPÉeºë 7·™ÄKuS+™¡Ú‡mɈ3™‡»;µÂšN쓦Q»ñ֖cF³ ›;áúßVºÏÞ*Ðü¨ÊJ •}JíAÃF‰ùN‹–­ˆ:¨ÓB­l…ß˸`µ¤F;¡5@Ÿ²ÿTŽ§U•;Ö¡Š^‡€UkŸÖ„šfµâZ¨•¥è÷¢KYÓ¦ÆM´>eˆ´&»ál£ù§Ð£¢t—é³6[_£kÔd‰Z£FÅ4P+‘¯oˆ6eŒOِxщX q[£þ§W‡j¥KU‹õj²U ­•ê0¾YÅôO+16eÔ§Œ1d©Á¹Zé8 LÿOß=R}·{ÚÇýÓÊ[¤ï0*û¼°QYeWi»PÿŸÜöc‚•¸§U׺§Ç>­œõ­Ö¨Œì±Hµ;ÿg÷ÐG• ÖO_«ožVû´rRu­Sñ¸¢ÎVÄ{îÓÊ6*«’ª¦¬úæi_ꙧ}Ü>­\ô•žSٗït*˜ê«šn°r\ 7O+_Ui§²*(–jaó´ÂÞi·O+镠j:•UAUÓÅúÏ÷z§}Ô=­œT¨œ½U•r*«‚ÒbåLñ óN«é[\ýSß´£²ë°ê©šÖy§•·þVeUNÕô¸rd«¨ +›!UvíUYU«VlÕü~w«Ê®¹ª­jz*–qX%H¿”•]gUû;©²+ëo¥Ê†U UvýíUÙ©*» $H A‚ $H A‚ $H A‚ $H A‚ $H A‚ $H A‚ $H A‚ $H A<‘±qwGÛnÖ®ÖF#z›öVXÁσ­§»Ú¹õ0j$‰M4"±H*’ˆFx‰á¯#l”¢æ-D#†̀ÿÄ¢Fb•\#–Âï*Uj¹LBþ"V¨Õøi±D£„#ä¿Öðûƒá÷åbFÔ~äþ No¢Í4ÒÈLÄb‰H¥0K52ÑT#©ÄD¢T(¸#æF‰\*SsG$j±D¢©d&J‰ZªýYb¢V©DfFì©ÔD"Sªð챉L'gO Ç5j¹\Ä~)û³™‘\i¢‘h˜ÉxŽÀŸR©F$—™Heð/©‰L¥’©LdrµD$êËp +8¢”ÉdÜs<"Qã9˜#2¥‰Z*SáÏR¹šûQc¢k*Ñx#í™JUȞ@—#W*DìW°?›©T&R¥BÉ1Ç#*‰DÃQA]¨RîœÚŸÙoe0ÅbOÀ–šý +í•âoˆ¥+E¥¶v”@çbkO©†ŸáË´Î4m…käÐФRîˆFi"QÈeCîg†2œ‚9Â4sí¦¥°§d[R¡ÆgfdcdlÕÖÔŵۤñ®“œ­]´~H·j0WhLr%dH®ødøRˆ$Ì¿j™R¤R*Ȅ¨& D¦>iNYDN2ÚD!…¼"—Ð3â*¥HEÀ$ ’BQTX2%ÞH©€@a¾ÁF†%Pa•@-“’À?ËTjHŽ +Èblۘ©J >¥Z¥É!QŠ5$K¨á¢D +HvR¹¾ƒž^®€x—«¡‰¨øÅJ±X‰Ë 7PJ |ÐTàg¥DŽmD¡6Qk +¤&:à4b  +éL!‡Ìþ”*eRü¤T%QЮHª«1‡j$PVè‰Ä*± ¯U*–HE +ˆ0‰š8|‡štPb`ÐHLT*¬- `ÌÆbH RèåR•êY"†r+åØîŠüºmh^ð+r¼DɪjŒs¥„öo œÊ¡R©H¨ÐhH˕CWƒÝ™`‰”2¨# xh/j5T2@Ð;(„[:”Ú +”®\Ž…S+BþF{ZH(J<.WË!3µ„|^¥†ÎڂF)Ç/€¿©dr–Ú?@Vaëâ7ÊàLP è¤j ¹ ^«CH%‡?¥r9Ô9 –‰ÕJlØ2HðXãR¹ yˀšZ-Ã2¨ÔP pŒÆ54G¸æB!] +õ:ÝȒC[á"‹Œ„DJŒ(§Â/†f40¢ VËHÉÄb)/Á ÇˆáÐ'Aß­ÄnG8rèò @d*’gdx°ï–K±fp4=6éìá< +¬E…¾š¹L +¡u¦‘BÝÁ UèÚ e«ÕPËðr|ËƔZ¦&EP‹ƒZI‹¿©’`_+‡N’€DEû72(À±•”M­Ð +øJ†4™œ|»3l +0LPá)¡ËUÃIåtƒ-H,“@8CŒJåðRZ¸\h´ +Ä +D™ƒNM=ؘɸó† > Çn +ΌƒlŒ˜X`¨ ‘CQHLäøF5¦~š)¤W2 d48‚Ö*úó0‚©ä +ò£)ð”Ð#B¾†V‰­ÏÍó˜TIF®d"Ãñö*¦7Àl8\¾FgÏ5¨’-H{ƒD …R’©!±&§Tà_4$,°IãW©!!a©q4…ÃWÈøP— +¬[ 6%éÿdØ%A•*0C.Vj°%A(jZ( dO¼P™ ÆO½ÅPØ”*1ûK%ð›ÀY.c¡¤ú7þ þY¨{@˜ ý@¥aæ Cßù·Î؊ŒÞŒ­fÀÿÄô¯†Ìcð·¹Y ž¡wÉ!d­ŠLaŒ­ŠNb †Ncà#E&2:NJ=•1¶*2™COgŒ­ŠNhÈ1æ4ðƒ'5ÆVE§5䘁øŒ¡Sú5ú“8fðô†k&º ŸâÀg +Ortwšclõ¡!,d²cH ˜Âosø|‘)ö˜!“øTái2xâƒ_^xê£s¬¸“üH‘é4xT´†ðDši“L„ðÿ M… ¸HÍ™iB'+2%‚Ôfè¤>RdZ¤s¬Ø#¸„"S#8fðä¨Hí˜4h¯AƒácÓ$ ›Â%¨É"S%HÁ†N– ï8]" Ï° “±•ÁS&øˆA“&òN› ±ÁВ›@½ç÷ڎèg>´w7Q;Qón.NÎÓ'ZÛ:Íl!j/jnÚ["¶‚À¿¶µ¦Ÿv±¦Ÿ‚™ÎpuѧO“fÙµµµpu™ä8ü*~ÜÖÉÆÎÊ´·Æj€Ít;7;[«¾vVô—¦Ó32÷四::9’bšwåžk™[{ع´icdl<Ðz‚ÝëISì\Œ&L·v³Y;::¹Z»Ú9ÿˆ&¸ØMwur±MŸè4ÀGØ_76î> ‡ÑÿTŸ endstream endobj 104 0 obj <> endobj xref 0 109 0000000003 65535 f +0000000016 00000 n +0000051018 00000 n +0000000004 00000 f +0000000006 00000 f +0000051468 00000 n +0000000007 00000 f +0000000008 00000 f +0000000009 00000 f +0000000010 00000 f +0000000011 00000 f +0000000012 00000 f +0000000013 00000 f +0000000014 00000 f +0000000015 00000 f +0000000016 00000 f +0000000017 00000 f +0000000021 00001 f +0000051069 00000 n +0000051327 00000 n +0000051358 00000 n +0000000022 00000 f +0000000023 00000 f +0000000024 00000 f +0000000025 00000 f +0000000026 00000 f +0000000027 00000 f +0000000028 00000 f +0000000029 00000 f +0000000030 00000 f +0000000031 00000 f +0000000032 00000 f +0000000033 00000 f +0000000034 00001 f +0000000035 00000 f +0000000036 00000 f +0000000037 00000 f +0000000038 00000 f +0000000039 00000 f +0000000040 00000 f +0000000041 00000 f +0000000042 00000 f +0000000043 00000 f +0000000044 00000 f +0000000045 00000 f +0000000046 00000 f +0000000047 00000 f +0000000048 00000 f +0000000049 00000 f +0000000050 00000 f +0000000051 00000 f +0000000052 00000 f +0000000053 00000 f +0000000054 00000 f +0000000055 00000 f +0000000056 00000 f +0000000057 00000 f +0000000058 00000 f +0000000059 00000 f +0000000060 00000 f +0000000061 00000 f +0000000062 00000 f +0000000063 00000 f +0000000064 00000 f +0000000065 00000 f +0000000066 00000 f +0000000067 00000 f +0000000068 00000 f +0000000069 00000 f +0000000070 00000 f +0000000071 00000 f +0000000072 00000 f +0000000075 00000 f +0000053130 00000 n +0000447035 00000 n +0000000076 00000 f +0000000077 00001 f +0000000078 00000 f +0000000079 00000 f +0000000080 00000 f +0000000091 00000 f +0000447070 00000 n +0000447144 00000 n +0000447428 00000 n +0000448499 00000 n +0000477276 00000 n +0000542864 00000 n +0000608452 00000 n +0000674040 00000 n +0000739628 00000 n +0000805216 00000 n +0000000000 00001 f +0000051443 00000 n +0000051140 00000 n +0000051211 00000 n +0000051242 00000 n +0000053446 00000 n +0000053559 00000 n +0000443823 00000 n +0000053594 00000 n +0000053953 00000 n +0000053990 00000 n +0000053773 00000 n +0000051857 00000 n +0000866269 00000 n +0000446471 00000 n +0000446521 00000 n +0000053192 00000 n +0000000163 00000 n +trailer <<1913AC01336D494EA4250E05957BB203>]>> startxref 866446 %%EOF \ No newline at end of file diff --git a/OSX/iSaverRunner.plist b/OSX/iSaverRunner.plist new file mode 100644 index 00000000..4a3e6162 --- /dev/null +++ b/OSX/iSaverRunner.plist @@ -0,0 +1,67 @@ + + + + + CFBundleName + ${PRODUCT_NAME} + NSHumanReadableCopyright + XScreenSaver 5.15, © 2001-2012 Jamie Zawinski. + CFBundleDevelopmentRegion + English + CFBundleVersion + 5.20 + NSMainNibFile + iSaverRunner + CFBundlePackageType + APPL + CFBundleIconFile + iSaverRunner57.png + UIStatusBarHidden + + CFBundleShortVersionString + 5.20 + CFBundleInfoDictionaryVersion + 6.0 + UIRequiredDeviceCapabilities + + armv7 + + CFBundleExecutable + ${EXECUTABLE_NAME} + UISupportedInterfaceOrientations~ipad + + UIInterfaceOrientationPortrait + UIInterfaceOrientationPortraitUpsideDown + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + CFBundleLongVersionString + XScreenSaver 5.15, © 2001-2012 Jamie Zawinski. + CFBundleIdentifier + org.jwz.xscreensaver + CFBundleSignature + ???? + CFBundleIconFiles + + iSaverRunner114.png + iSaverRunner72.png + iSaverRunner57.png + iSaverRunner50.png + iSaverRunner29.png + + LSRequiresIPhoneOS + + UISupportedInterfaceOrientations + + UIInterfaceOrientationPortrait + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + UIInterfaceOrientationPortraitUpsideDown + + CFBundleDisplayName + ${PRODUCT_NAME} + CFBundleGetInfoString + XScreenSaver 5.15, © 2001-2012 Jamie Zawinski. +http://www.jwz.org/xscreensaver/ + + diff --git a/OSX/iSaverRunner.xib b/OSX/iSaverRunner.xib new file mode 100644 index 00000000..577cea92 --- /dev/null +++ b/OSX/iSaverRunner.xib @@ -0,0 +1,176 @@ + + + + 512 + 11E53 + 2182 + 1138.47 + 569.00 + + com.apple.InterfaceBuilder.IBCocoaTouchPlugin + 1181 + + + YES + IBUIWindow + IBProxyObject + IBUICustomObject + + + YES + com.apple.InterfaceBuilder.IBCocoaTouchPlugin + + + PluginDependencyRecalculationVersion + + + + YES + + IBFilesOwner + IBCocoaTouchFramework + + + IBFirstResponder + IBCocoaTouchFramework + + + IBCocoaTouchFramework + + + + 1298 + + {320, 480} + + + + + 1 + MCAwIDAAA + + NO + NO + YES + IBCocoaTouchFramework + YES + YES + + + + + YES + + + delegate + + + + 9 + + + + window + + + + 5 + + + + + YES + + 0 + + YES + + + + + + 2 + + + YES + + + + + -1 + + + File's Owner + + + 3 + + + SaverRunner + + + -2 + + + + + + + YES + + YES + -1.CustomClassName + -1.IBPluginDependency + -2.CustomClassName + -2.IBPluginDependency + 2.IBAttributePlaceholdersKey + 2.IBPluginDependency + 3.CustomClassName + 3.IBPluginDependency + + + YES + UIApplication + com.apple.InterfaceBuilder.IBCocoaTouchPlugin + UIResponder + com.apple.InterfaceBuilder.IBCocoaTouchPlugin + + YES + + + + com.apple.InterfaceBuilder.IBCocoaTouchPlugin + SaverRunner + com.apple.InterfaceBuilder.IBCocoaTouchPlugin + + + + YES + + + + + + YES + + + + + 9 + + + 0 + IBCocoaTouchFramework + + com.apple.InterfaceBuilder.CocoaTouchPlugin.iPhoneOS + + + + com.apple.InterfaceBuilder.CocoaTouchPlugin.InterfaceBuilder3 + + + YES + 3 + 1181 + + diff --git a/OSX/iSaverRunner1024.png b/OSX/iSaverRunner1024.png new file mode 100644 index 0000000000000000000000000000000000000000..a548d1c6bac889284f2015a51b3fd4b467cc50f9 GIT binary patch literal 46983 zcmdqI^;cBi7e9Q5R6tM=P>?Wa1Qiga21QAUH;o{m64DCNF{8c_K_#Rcq(NFhBnFj` zMnbx~dx&A?K4*sa=XstVzJI}YEf=_0_ug~P-mhJ+y-%Q)hSDh-HW~0FKv0E% z%Dp?f9z!dmzRz_Q6Bj%OODxn%cn$5TBkBdOg0CX)O^NUyG_Ojy1farmgEmA?LIZA9?lv~b!@T)|2fj$R@97k7+_J;=zo#=O5Thx730dO&BMKzX*xGcXo>9qhAcdHjr% z7BfT4djwqx`s`lt>hw=C;>PNNZ50x=?NH!rFIc)(o_QSkF!ZyK4&m0j)7_up9dWMi zR^<3C+TWYm99?I^c^V*+fdBDK8v7(W?p^}V)I2R@lWDm{`%HwTQu7j64ajmu0C$?( zny$_5Lq@%V z??9PW<6KpqIhh$XH+y68IR_Rd+ZWF-Ql+WB{4q-jnX5b}gUp-vC0BE7=xzL#2q9Q? z6S>rbP+QHq{o&vm)W3su#|OXsM&UkK?ZLvH!$8>fFdHiqIq7tNuZ{h|;IIWNH9n{U zZS$t-%+DVvNk>C-P$r|)*L7Tqe(|} z`i8?sXPh*%qDP#g1)>JPk#_cabLvsyySR98`G8=10Fcu(`mZtt8Bu=d zRppGjN!`zU-yT-;U6;wOhhpOkqTJfglMVjAPw>-vb?U^6Ne1XNm$U83nY}+t{;tON zbtl)g?L-yu8S}7n6jbK1PtaW!aC2LGU}f*0%<|`gFJy0DZiJe{QV&l_M~2uvygNNl zkQ5vDbQ51O7YAtapQ3>3Nve?)FaMhsOP;OD;L`W!n#0SxcUx zJv>tUerbr2Bf1%XyC1ekSF@Sb$<1^^8wLK{_|*#ip*j}x?D3(0PGQ% zjbUS7_nNnr(%js0LC@QAk%Vu*Ru^sTnJ^x1;y&vGd2^-cZiZAL{$mTd7q{gtczA7l z(@m4xTi)<{YnEpZS7PG#p;lKal2)!NXVf4+%6(|dxFP9|i~G+0ko7=w1X&)kS$7O4 z+8o9S-IoulJ-f!gw+?@cS?}~PKepd@5tI>}C%C1C2L8@sug)dE8?6?1JG>Unb_}=h z%%h-;y7Nu({mQ=(TN1#GzrQ|463fwHMx9L@`0ITGt>bUK29Agd{BiIXLVR^)W5GA5 zAmzXHr?n@(u1rFMjZa;ulkB>1D?3WoO`Uts%Z{a1oN)Zwm1xI?J^LNk0_R2F9|Mb* zH#Z>G3#6Us1AGF}{KS1N$57XxzaMp>~932SFeX3SdC=T?nh8Lo>KQ6s8M#}HgS+)hbNl3ZkZP91o8MSJ2yQsd2<#uRe* zPyLR3rsGSJ{3nuDkhfjSqV4EOxDqV3bGzPT5XpIZpwcp&XpAR zEjdWhhXYO$Vjyj=^#SVT&F$in!*N|>r;P@VHKjlTKG0^7@I5Y5XY4eEqIRF_(LjeiOp!&H^Iv*Btikd!Ex|BV`AmB^5fgSJ^vxfe9 z&MmK)G8Fsh^wCoDpUnl6!|AJ`sn3L7{w^IJEao0Bv> z@e-(CR%WX;?E$bBH25cx{t7}$vXa02CaXjy)Zk6Eb_L`1MBF9($?<0f!a(5Jv~o++ zl&$hrA3c>nCCgXv0JZ+pn!(Ab-~bW+-=-wXQZ)o<`ENwuI2d?C`0L>6x0$rI*NBr# zQb8R($=a)PIpq~XM3FrB?%&f{WSVWAv0o^Zmu>9B zPdymut;g$%Pc857RntJ|pr0T|6S~Sv%kNN8XcJxWPxbr;b=ZSD*Z#N1u=`es3=Rq5 z6Pf>Q>*gf}ir-nRT8h|zC;tD>HCQ8Vb4pTbKY=zmi@9&jTcCke&H9s0Dt}#Ag(dX! zuhrWZJnmL2C7iZ5p}RJSa-P~cX$oQpknq`GpDYjp*#5#$n%7n1>=-v(sfc`I19W-a zt?3te^>KJMbW{688R2%NNL%m(p>=&!%!uweaCkWjw?s*X14S9Qv1t7mS9QAk{BSyf z^!Bzh2`uJ=Dn{~1QE}SesS+3WyYu(i;SHnXQv#ze8e_CV2;A)Z>n`~> zBgs7e7KiluT=t$NJ+1;wSGcHDJB##eV{B2^ZQtJ{h>;iNK^iC%aP>Tk@ z{c@3mOt|*^vqnd=a9ui*MT4Ul+S@3RsRdK$7r69UI^FPm-5 z=AT)wd?`ezp-sjsoCVnwa6c*8#7sa^v?(jC_&3Z zgS!%rJXBi#6n71@{@b|u9Z)`a3YR>9yWBL*iB`+k!`%D$^Eqx1MBY683a}$XFBw$!Q z6@f^1$jy)b{<_x7Sv>rNg$dp1gV{ehc{SChBq14=Ky}43J$)OdOLdcmcL#Vv51f_2PJ~&6+)>E)V#x* zUImsYz4297rf{BFqVZZEkRv8xVB_4#sf+U0m(e}g{)(@+S(ki&J|) zK{kq*e*shY9dAf=?K+Y*N&W1$8H290H=ACdd;s#DNmb3pg>o4q_lZiXngC7IOSdIk zQPIzOU;}F$-n$*{wH`#o-6gtrbT=(@LH`1oeQy5vtllZuYq}<2s$D^pg6{k4F_3B& zr1%F0P)GRV@-dtEVfb4KdXWZX(Y4!iwBdNZr;?%qVFT-!3bm6|-*Sn2uUi|5`isco zIQb=_k?aEeJeBRDwSgAnE1Hxq`vGu|89(h_XTf9$R$vo-5D=2Q9(c5s{c=9d9Nl71 zl#ICxC}Dp}O?(CUdy1LfsiQ`3h6Y>n>4KEv_~?jTeo;%)Jd|aFsF`Aq-5$XEUrl3tXOyEi=X^H~$ZunQ_4bW5 z6T+#?x^~9>MlD4`PLM>bs=cOkE3#-Q_L)Apn%VXngE$3sjhc1&OQA`)ChVfan1MGL zLEZZUSJH*^H#G1DwJH+_{oguBHX;6PSn38BLnp7W4=(_^a_K8fegPFdh?B~fw2~t1 zKCSKN2t0c-=?4(Po=y-VEaZ*5d%ZESC2B{DtzH35sQ+4~sTg-^#O3i_`;$w*B{*a5 zajUE-COfOYgpDnq%$o*sIj0klrD;hkD59s)x|`m+T9gq0fvEP;__Y*g2sQ7S-yddv zca2uKpZB@5anS$4eeL6Pz{?YxN@jRDP^17LMKBgKW&i5FffheFJux-YweZDuQ1w#i z?ZzDG+Z8ZZH2wU-q2?9?(HHRlKpHMlj<~*;dS&&m?MPMi$0^zI4k-%mGyGWzq{o%U zR+BhRvHKvJktD5OY5s_|3Xei&Tz(b#M6HX-ATy)VoSyL&on_YA7ni<3Njo4?QH~q? z^tW+-f)5G5+z$ZdLIy!RD)tl>2Pe_fFVwp5yF&HeCC0Dk9#8;&M<=$>N>EB9gWz82 z+x@|Mx(~C(u{N(tuvzf(Z-hy!>IUX;NA*MLtA$QsbFX)OWiI=w2j5HSQTlXQfqCCn z(9Zq(u36=WWs{`I-k(2$=X2T{Yv7Fal;&Ii9)~`OVtPXpfrtEn&8T9mdmM8jUHGw! z3iaNt*lP!cOwlw`1N7P8xyr&&le?R>BS< zIFj^IhCGW>^{SP&PuJZ#qiob6_~DckGbsRF|T-MVNev?FZEfvP+X9=xFQNUzxr>CqZ%L!IuiJgZo9F9n1`5OyM# z?Xtp-daCD~eN=}ClFFmkV~^5&m=s|$qMvm>DCH3+D{1D3E<(@3=n;)+Y$~dt?xQY0 z+^uc?T{UWHbSfe7sHbOuCELx)310T44sS-%$H62o?R+T-8n8GkuZVqs2B9F%?BF9S zSz?|^Tyos|`zQHhRuK7(e-l59qB%V z&|QhOM|bH?bE+*iK%np(-u|Mwj*HNdC^Fp&VXRiEfp^Pcoj;r2nE^c1$;i6GlO*%x z(%8Lb&OWqmcgD#UORkQ4OE5$OP7Tm2kxgouL?LZ-^uF_&EEuk^UfBs7{8N;(UzD$~ z#7s+aA5*CE6)9Tbv|p=6^SP}f)h~q#1{r$8^4Pw~%)MUZf%yUBQ(xF?H*%hV;hvvO zIsfa`W546LB10>z0DN@iwVb`kagU3qZJllXa_Jtv24EKtM@2CBalU^iF#-s(1)eoE z>Jy5vO4<=CQOk9V!!n3su7yn@9V)XgfEh?;llJ|VUihZBth9A?m=JK=@d*}lR}^O^ zC4WuvK$LV&O;CokHQjuGaF$u4{;nQlcp?-eprv7j-TG~BpamGEMZd@iioD~L>6D_PIYJRaj zHl!gVebhcrhX;Gk8UYfxg?37zO0e)V19t_x0Pjhk>5&hDc}gzxek(g?wwsZ`O$W%Y zFg4M`78zzYUZp=?R-f!alm>Lo?Xc+9*Sz*cM$Nkyj1G{4AEmc#kDN~5KTh@sKul7$ zuU&tdwoUU!0S#=C=lZ#UlucAz>`^kX=xw}vGfZ;cMJiAV+s?4NkmJ!Vb@|N&-`p!D z==6Hu*(N})h>nGe!AiEAwp0hlF`{IkoGJTq6>FD#uyD$5-l&%tf)}Tm`FYyS?_zqb z?2~Eu0|?_%kk%}0A;}=|=7@`g*17si<_#%VtzTKbJZU@uc&FQ#v5C`l9g$GW&?D7R zK*KPHqq^%4%mxpTE$&@;_){La4{EuNtHlg;N4O|-{ z&IiGCgB#Xu1$brv4vSehn`Mn*#}2h?o5o=e6ovp)zj}7#YT?8Er_#@*!?rJaC+GL$ zdUyIv*$E%CSJy?H(sXe+BPcYc#mA)Qf^*qdYex;hZT~A7H!d@gprj2d0gJcJ z(Oa+`6@2DcYP1(qnX;$i0)ftod4e7l`7u2{{<)2iu z+v)^T%7Er5>-*LaA2wjp5dfly7de7)5)pr70*LC(?cA~|tJQUD1X=@8_wMoPdK4d* z1YDV}^Z&i`th*nZ}?#5uWa zGW)mMtniUl*vCYD3BtG;=5CP7z5c$QxE|&@Z9H1g!q(Yu+F$-~T8(RY7Pg;MCnH5U zxo+GzR{X`mzcJr?=3atue|`V(N4nt0EYQ7pgycS)6apr?s{!3;0d4Vhj37iPI!ryWd<<8x5w*b@8f5>$brK)wY9U34a7gKy7bSFsZ3 zk@vnpfOgC{LgXc2f(>~u7ji56Hyx<{)jZo!yxk2+ z>a{Bpm=FKi&7Dt|C%e6VhE?h!LZtjGA8r%k=0g3EtspW!S?T~dytCZ-b#n0Eovrg< z2{JnYL*wE#oGHNL$b&5Ybz3l9prnh4{8h>9wO2irEs@^4@MP~K!zDLk9B}sOy@_v5 z<=^IF*2r<&%qqk#`OX@PN~&gbl1mB5{|~#-y%b^#&6^eOGE#e>?AVoC9xm$1<(eTB zgVxE~Tm3hGlh5Oq&T@m_-jcabD!~D3Voy5$XL$B%wy$#}rzF$nr_#rMRtzz1I1D^) z);v@7hc9z&KQH&AG0N)RoVulaU>PQv5_&qMcUq$Tq9U5;aG` z{yS#<2IN0|Lk77cvJ0Jm4#lRuoO$Q_-{m944jpYmpfn(3pgG;Bfm3}a1mlszt(!T4 z2bFE@SM6xW357QFlu4-ePsw-fw)$zr80b2A+kA|$Sj>}&o0scIUZVG|Mn!w_WKOnV zJgQSM`3EZiBPbd)k2K*d*I_uf*$g;(b-8N^EgaB_=U={ZLR*&_;`8ycb(ud)1CwbG z^4ZOmer5mEKPkd<`4A-X+-d>!uN;mk_a@`z5@MFOruE1j^Q!!3TgOWQI)|VlLQ_yp zMke&&TYlqTJ}BT)a*!m0y~DMK*6fb3apX~WP_Wt{e47syc*(`3(d@Z-o|!E^*6JGd z$FtlJHz*{G>hI{fX&}B|NS2Z;ElOeV$i>RpiI>!Q;Kp-7Bt1x*qFi^zZLw9GCy<@B zb>{TYkmm1hhi#T842}gBs{689H)+Y8Z!J)AxBPpLeH9+*N5~dbwXttqmZoE8L7=An z(PI*S>=5^k9YwbA$&0X3afhCD=e(z_*B9jV#LDxw&VuhBy(tt8T!kNvHEJc@HlR{~ zO88JYoag#FI4*%eM%0dYc>cos8pkBHn%g-bA2h`eyWo(wZ-`@Szwe}tpB%}=1M zmODS#xql6zx4m`j1)1+(Ae$(%J5?vGbNN?}KmARRII!8fO0Rs!iDwF`Ep+xgvtvGR9)PxW{xp55u5H7n8*6^-<$JonZC{ z2(emTdOT-J0#GFg^evbELIW;z8}Uqg^?xvcLpkr{x<{|Lios(re)kcB`d(MjZf+hQ z3Y$H2D?It{*O9EPwCNufJD;e7E4+A~y`6>|m*89XTu5PK1ZWp5-W^)AP!c58x3JmeK{x%X1OGla6)| z^)Z_Y_TTVa3=G0%SWN8Yu&=L%ha{lBF$hCRI`Qjw0`e_Gz5259+i^#;Max(ixTUG~ zj8OuzsL#pg%BNHV^15^8qz_jjZQ&4bc@LMs-RUIfr*kwH7w-XMtK7AgT1E5CEIC0uPdo&|io%A8_P8fKn zA;b7ZJ1&;&*plAqLS2)&rOiy<*0%Q&jv`%JBGb;s!C!Ab0?iUPZw4(2I+DdHuQc*( zW~ysIz-rwyIp6KgBsll&ZGIS|uUL=exM@Qu-T!Yp!a=%-k;(G=(8k=1>ExR=Dx)UMrBq3Lo5w zD%*p#FaBo;p&lOQBIQLd#`KJx0<2vpCX1Fb18+vlvhwcA^?|nj)dPX3=R2Y#&lIHy z>JN|7yua25I>62u`B1U3&JyBM!_wz^j?RKYl&Ip<;xD84f7e|== zCj1x&i}`++mCyOll+HshEAz(*u&3}PM>rrZ0l1b^A3Ku1-N>)`>OfzNPiB&UNcz-2|M@JAAU2rHF zDeEHq`uNwTPh3|(Ogv|_ioF?zXCMmRyhh+6v|*rUYz&=_CHjCCf@CRv+~rToL5Srr zJUt&0v{&@MM`wO(J@L5a((@CcXS4p`Bd9z zpsWB%Sd!iEgY4Q6Ymw0)JHOo2Wo84ls{00IO4T;Wb4U{OA{`&f!gdvf&AHajL?F-U zqq^d8>sh8)%&+gOFd(%+ULJ3vN3w6>nD0YEEV&P3@Tl8zeaVKuXRcS`k>XN$75H^e z+fuz@So@z{!Xa~Y4+;DB7e9BvgX?z1OR+xgcO&tr1^>Fw6)?uJuk(_n9;n8~^1gRu z#D)2+-gK=ast4Dxh26X&%K2`dAqTw?B;{RzatqZ6w*rh3Z6y7UP(hMo?h>H zkgfHzOfJR#MHbN&FDl>XW~_4swr`G+JZ2a7$DEQ*;Q0O~2PM&ldnMZrd~M=2h}<$G ziWD+dzTf1aogG($$GAUT3yz)sQ#oyrDUQ_Zxv*t?7P4S~Y5KnXPsN%Ygo*;Kvbt6H zeYltGdcG}T`gaRq+`#OELL_~(;EO!XEI~FB^qez3Pu~~O?b8{+Vx~8D%vO=#lF&f6 zYJO2bieQjHOmaA(VDs3tj$V_ZT*;>zypvw)QqE%Wq^|R0mG3Q<&baZEBgu^; zJN-w7#dtU^j>c)zR1g8Z6m^dfGQvI?-i(-289lY z)@l!uYDgS2+ISM9!2XsfiF#S=UomKx?hE|Paa4wXeX4UB+iVxlwr1 zmCz~T9RVwTuGB&AOo?3Aq$5FWC;js@Xc;lBFFHOe%iXm;UIj*z*&-txOlI{8OupERf%IadibRsA zhLn6@zwN43omG{pm&{NyJ*zQWt$ ztQ_+OQeRdhyKzr6B@?#O*!DFOmlXNwiFHd;Q`8U)Ttdl-{a@@*A0x|R%hqA!Pm#6d^3yj3lNaUDMzZ6Hd?|5Nk~QB(Zq zTZUe)`1W;;`_{79?PXz*5|_rrF?gpgeCgvJ&b;p^DNYA?FGzB)zhYoA!^uVD>@NL? zhzuqFeP9=0o2vI^WS+xHxdkxLgVJlEt3IlegY}iM{#OXqYbB*jauos-rt5adAVmZzt$X`s_~ z$VB^oUn_jOL8Gv_iT-29l4XIhF(E!E7<6X!tLL;^IpVd(s0g|K@B-aPhbvi%SxngH zGp9+iGXdFfy8#^hWd*g}j=J!676UpGB^v>ZK z+!+dSa)MD%kxfpNo~ve2yM7)Fpp*3{AT}PM+1Ei|co49x4!c&ketS4{^%SIgfW!(z z%FDU=ojw;h)jlfCf56C1{2_$sI$voMz}Cnb}0;;7;ng~ zlpH2=GF74GB#!KecD#rQ{?r2hqx|^snv{8>qP)s68-wNnjc&cAW{+DN^uPD|H?zQAyjbC+8JIrYX+hyZOvJgUyf=@ZhtpkWjHti3pOC-IO^Ts1n;T#}!?_in zZns-Gu)pk*<8t?-bDd5Z*fkH0*DxGJl}8S3QlwnjLS0zWNTFwPty|tLLGy#57XaFZ zuu*K2nVv70V$FX@cpuRR*B{+YY96!R7SdYd_+UG>?%g=GHBRLE^RyU;VHzIQGxLZ& zUzzaf<#-zkQrH*X1(P2tJTcY}Yt83t=G`+hu(0P0oN)e~;*;&Tw%lh1f4Fv z;C$Y3mb-=ted`yRbnG)075K%I1?7)h;SWFVt#~;<4)NR`dbmA`hmL4A2$?m`AEp&hr1C;}iz9@JY#1_^tpbit!lXIwCa!O+2N z(UKzrQQY|BHw2{WHQuq2xy|SIZNp9#_789FZnzmwh^@?2AUZr`@;iP@TVRy5_WwSW4*JD z@^KS{_3WK-s%z>zvewf#&{*D8R*jRYIpm}SUCn;UcAb<}f?0#|=$}#B(mMXpu+$EY z*xX#PwW+`=g|nlhCQhQo=~q5IK96Rsq?FN%Oa6RpM8X*}zeB}0`w9M-^Yd1^vlyc5 z=dufhpL)Vv0f!XkiFqA_O2a|W-n*G4GKcp-D*3dJe*`E-y_q`oIWm3%m-yXDvZB~>+$Eo z+Jp9T#B9nW_lRp;OgdpKr3^XL+gF-v`L(L{-nco3NMEMkc$1N>{D!1A^=B%x z3p@JD?c{SHXaO%O{C9nPj3N=t`kcXQyN-zKVbkd#5?mMv^{7kD;CBxpG2l6O31lb^SZjxAE(=7zro1AGgQf&eGF4iV8-hl!+c|<`5l*F+_x}P{9K4gp><=`fL0UWg)m20@wuZT)@9G6$PRx?esB8_X`7M3bI^im&URd>%kZJk1Juw-@2K zr5Se%GIRfoy!#nAqtP6q7FTS?!t&nt&dghiw{pgbn&m2BHaN8y6X0unC!_n zfc(j4{=Li6;Mc`-bz7D#fN0Il+;TKi35l$^kgR?6^mZFu=_Y*!%pg!e#=H{Rpd#6?V2yZsVN||Wdu*{+|oFGYXpeVJSUn*gm-7Sl=KOjwaj%O zsDhULkXF_#^3mM^f&uWrEn5bPwp3nIzii%!{`C$NAnB}*EoWhWv;y;`;?SV&{$)>J zNz3NieK^vxK{`*Lqo$AV-NS{5yb3SSQO zF3`&q5BK+8v>#Db;fMnj+dh8JE%5y=xZ9!%n&^=iz{NCCNrLDutq3z@?{@=3V{RD< z#^#nOpmJ%%!gJ4-eRri6N2xS3nvpRRVq0z7nK)XBwu}a?8g)N6Pxih3LM^#-4@6$x z{9<$RJSy44V}cMO9!DvV+VF(t9kHj#6t4Px6V3uS$NDyY&cujqWrwx8HgI%-DTMb(uP*@J z7*UPWMI<;OT4u=1s zJ4>`6Axl2^rQ}zuB?)S#T#L81g^oS=6>;B#=)cCwzX*UKeIm)~oCYW>{O(oD=Yt@B zo7B}dIXlM%U6EL?P@yb}`LkA-D-sgZj*ghtHDn3ha-0`sBpP+ABbb5^I8a(CV2U+p zkG(PQD5`s>l(}3i-^X}!?#J7|TQR)S*&V(?-y#%?UCC($X)^Wi9w3gcbuqy&;~;NFHPh;I?3`R}@B#h+pBf zGp+#yP~7KKX;^5Kz0awrlKGU^gQ?2@mBS=+PWV#B3cS|sbX3S{1d6|~eNcwO^&WD?yKwIqU5f5lO4_}7)@+d>I82wVCuFyUM)4u@!=p;4~#1`|1 zk*Q1X#EP5cu4jNm@J zPwr21U1wNar@!76h(5}`a{Sf{p<6HVMC9fIku$G<3*mm;xvu7&m?t8ORXYo2AQT|N zt!tP`vspQ0vftq%9B+pkUv)!9f1BFx7n(~RD@5V#Uf@vC6~zfdzm;nu@3tRAO0erf zNN@PdbnPy3A~Dr0&?&#=plnE=Rf`fLzg`1z%Q6~@h30+V>7ZI)-)Hw%-R^=ZdCqw( zm`SghsVM_vn3;FkEBtbf-DGn^D*C6q45xwqz?5uUT3Nb=#P05HoX~CpJQ62ix8>`l z>T_w#r6{#5p#alsEHKW5PAxWS$0d7Aos2(1yRVNilR=uZM^+i7=o?Mai^3@>2GZ89 z)>-Zo!HUygQd2L^8l;q$|3&D2Y788gx`6SW`hgVUYO-ZlVv~NG>=CRCG1@{Y!6&Sr zCUX(8+6@TvNc^gRK79KT#!oiPQ2A27T4A(QpSYx?n%Tx;R&tP9O$H5=o@HP)3=guF z*9c%ZKBg8&%;5(`LwR`l`1I_aWL16ktK3?oOlN2F-D>7LioMITUC&jHuU*F+ETDYn zFxb#qS~6%s1P@Owp$JE-X5X~MOhOY%_WF0bmoqdZu3p`u5D^=O9V?^@p_G*hxO8@y zOj(pNJ2mykTZFtpe&J_7OxqqAnEd9jb!LPhDmFg9s!6jDMk@2ieN8-dX*`Pq6Uif9 z{pO>EUwD)Ik}He^l7nT;9Wq?~@T-%0D(78^vw#a%Kmg|W1o z@7G>9Qu-(BJQNdB@JgGnwr|vNk4aOec&>Qm#<^L{{*OG^C=j6-C-u#d0?NL(+v6_f zNKh`V=xmRdEHuM(d>>B-vlBJ=-PWHXWqK{nII};=hS`YURgn41@_+rhgKUo%+noGr z3Wau%(JY^Jg(7*wl<8!#d1iRkKm_5a6Eas&vXhufC;hFb{cZ0yqyKds> zNo0}wy8l>JF=2!H4B-Mo`^rXq6Jb9Dz9mif4Cib1$mhe$l$LvEp8Fq;;DuCoMDqzs zii%#|-lC?}zn74rU_R7Blh6_>h<;yaQUPCfc|WvvH6KdJ`|wtB{{Bg*KEA1N;cbt1 z^6qVDLF)+`wI6``?RcwrYI4__V5iw`|3U2@p!5y#@S>BZiaR|$eeK?u_e|?tD`;1z zYUmX6%59cK%tl6M3fUXQn^ozU08ECz>+NwX~+5&i8tg^<-DL@|6fk z{v>%i75S+@nt_NDkQQMnYhC7`8L8@S`tA9o0p^gIH7j(sY!Zu^rGy?ino+WZL?s8s zk!1$^Bvk$T3YskLEgSxR^*7dj<}~#C@ynOGK&gs~>F2n;9|PwR!N5~*K<0aWn~yVO z4~r$tNn$3a&T{WzF@2QKC_&$pR~-y_tmJfOq65=~Q;1z8vx6rA(ULbqbuNY7^2V+J zI5bEndu((9o97duM?ft)P3>GNo^Xp9qT7$gsv0oRlDVR_H?!981ENKyfE^^jx}fQY z6KMeHBEOKU*wgMsk_*0pV!1qz#gtJ(sy-zkRyOt{Z)83EvE2TyFHMrN?XBQ#c%A_v zpXO2OF7N)TBwU!g?(0htEg8l{4?a)%)4)3RvX<;b5mnvvl~?#ll(FwN;cF zEmW_r6Y;e?PL%f7M!Y4otyw=(9pIA2hWDZy}yraF8YZDWn(}R2dfHW&ln)lIArM z6|X>49_3>6!Qt-mheN@iTSGs|&sCpDI#=ILK0hU(dXPs6LwP zIi?>lhX&lc^a6kAy2(jT#Nk$w$MgHuIY*y_FiR#;4cB@e&70W&%+2bbd+A`%sd=@B zId!Qs+En{nCZjFlUpgD^x=jXG%>k@76*Ob>{JEA4#k2G5=^UpKkm~S!F9I5d-+u)> zG;dWV^6}uwy7KSxJk_VWYxlbb>?;ZB90`z2=D%f6lzPEPe^c7fs|(}^v=0yC$>QrN zLK129kO>PANABUGbkhE>HULQ{(4|wx`Bs(!1I}4iX{Bn{CKy{e&&BJ}gS*xH%v5BM zn&J?b$sLgRpu3q9wA6RQ8wnT9fCU9e@42m18rJ7pf9udwIuLDnqK>4-o)ZJRg^e#}pJ4Ou`!$u<>#E-hNGp2&mTr&O%-#3+^;C+A zCp_}O+7s3SlvG=nMHo$TV!=jDn81#&Tz?G%2vu^wHwkjcl_*OudQMh%Q#0kRDg9y@ ze`<5B=Skf#IPH?_w;TMFaz$mYS}AAlKjeFU0_^&et{6L07Cctt9c@=~j#sjunyGj) zLgM`&a8Gut;h!;nN~)-kuNoWIPJtRRLs_bt$psfGYS|7d2a7qOtE=#I;a66k?czIv z?;5*{axyLa6a}S9v}ovrlbf6UyWa}=_B8qP1~fn{NFxxhj9P*N^D_WC9E2kIX-dExw!5oFck&iBVN01Rm zXG6Kde_<~Cy$S8^3vFbCW!_j`MWhKkY*QTR(ZVN}IX*1Sq8&U-3S1)J3lVEuw19&~ zbn~Pc{d;yamEbnzlC!A&8g{fLjVZf?e`fU&xVNcMENO7%rc)O~M5;M4)sC^0!o$9Y-p-23DDzJnWYVq67sM{fxIdya>y|ROrAwcqbIX8ZqH!2mT-!eBtQdH7fQU{q>a% z=LRCh&=qO0ry1aSN*+ur3l<@=mm(Rbl0nmay9TXHBibrII&pe}U6kUR3Gr|XpR{Q| z_**mSOF*m623}UB;$*i&6wrDX$Rgg1*7Abs`#_-{I!bcj!ML3qH2SeVRLe>6sbE@F zn@V?GzHNqFx|vLnm3UoG@}nT)_>^egV$8Sm_!l&gFjKZ$P!Hh6p7O@O>OPVEfeg*E zd3s_$QlMrJ9AT}!dJTZ_8wFY)>Wb;_H_HSP>gJvq`;i^1f$^#wNm9V0bAZUHg_ zg5-I|S7E}vwN=>CR=&1b{r>c2)w=Qyy^7P&Oc$GMNCK7;R1R3J60ZrHu^`Hspw z#p}YCAl!4e^p`rc5$mv2pibp$u3HEU((>Mc>*>}X;2I&w8X8|+AhC}du|7CBCKl?d zZ0Q@*EuGOUdw<0BBkhLPV{UZG{xa^?o;(^m$2QwHxfJ=)5tGY^2CH#Hkn_N-Lt8~o zaO^4!`l$t@D#GAq3(SX`Wpd(#yL6rO=@Bi>nL}P6!~;b9R;ZoD&@)j&q|TGmm7AEE z&YQZw{+6}4X{NMSK3AvX{TbxuHY63ymZZMXGUtE1NSk2Fk--bu{*&mELk6!rYDX6` zEjsO!O`AfM42TH5i5t7m9x_gvoU{tH;37*npTa?Em+}4$=H2CU7QPOqO0@_mnev@C zWKt)fk`?UDK&Hp1;(n;zVT&%P9;3=llX(;L9PAJXoLQZX*Rs+4QWF+6FW7(B7h)B3 zKMIWXM^&~#9Z~)F2K=FvaIM^GGRQ1EhR$tKeR%{R-1+*>8pn>}dhl-z9)oJQB7n{s#hr?z zwFW0Jzmw9Y^lXMEhFrWhUhN=Hj`5Voy@FSK-?v+UrdXIC(PaelF+RJ@zn9>65taOz z^iWcp@{bDF&$-pNZ+DncKm-rm6yg@c-6z@QGNT?}K|^QlVM_+`QJQpfBsRsiFEk3u z-IH~#VRR0cDEZKr(TX-a8I03Hd`x-l9=zu0(i6S&e$ULX04O+Tt6w?v9PvgTH3|~% zjwW7WkP*WvzccC)Bs%Uk*!M%B@f9_ifDEXi{@x1#{r%Guc;GQMyBB52*V`PJ5-UVSe556U zPIP8@*jcE(I#ly6sH0QAlqjrf zfV#Ee$8htZMIBE{X_8x7CtYMA;C@v)kI&RAL9i#wKjl{76zZz{r1zL!+@KsUv}dIW zNA#V710y%z8SAldUwzX@MZWZDPBUbr^K9$Tk5Q@ixJ)Vnp<(zDkbn0rWfVy{jzTf{ z;+l;9?Lw)|Kg1eB8s7>AZRp8!?HjpbZZJtmWajGc=KhjC7i~os^VVaz@Lb9lClh+NjQX1{9YN_200@ z8xr)VJsr|l4$0i0)q^2XV62j8q~pzUaQ%f%?(3w)Fqmc_cA%MX*tpZiJx?61a$m+J-t_2FBXN2G&pg25Et%ut`4DIr#0 z9_6Cmxn~b7T#H@CF&xEMCDG{c5aoVAcg_pO>z%AEnrHUm@w4P|&Ew^eW7*uerNrU) znN^I}-Gx}3k=6;%9x>zLrs{iK)Bnzkg7e-hj<;oCdH6*_7C*&R_u;$8cUPI>x@TwC z?oJmx{r5As)~}={tzI|Ux|8}iH#s5!)HbrwHQDIV!mQ!t5h$q=#+kk|eMBKYT4+zDBrys-BljE{-RXQk#ToOj}34 zip8j)p$pzEhGwF$DZ-WP?~hBm1EU{vEAnBAOb=5Gq#Ro|Akb?Fuv1gcux6>5{H&t? z2-S?fpbmJmPVR+&%oYNk#ztLezmc2K`5Ec2D{YbkZRKNs-hpEJPzCBwI8M$ma_~cl+|y`|bkY2i7_HVhNK1ZU?8>y4l@ii;rk6i#ZHl13!n_3( z;&6DfpCoefNGD6AO|hW>0I|y`7Bn5MmkM-(G7@;XA2>D>K1g zB~wpdT!Z$MaEwvJ`U+Fy&<1r>!tJF<^4;I~@etSe_9NVQ@cJaSmkcrv^uEocnTrc{ z%Ztiww8Z5B@*8Fuyy<0HBGw7RVAxB(y_6(OK6^#uGuE>5JS6L*wkQ?Z^82)SI!JVx zu{9q~c^=QjS`~3pZZqt`<(^DG4M+tZ@13f;u1SBUUsdwOCa^-^AR;; z3P=Z%BMl-1*TH})mr^ax7NxEn;^uw1z<<1@TQzX&xGd3o8y+xzxJ-bw(L{m4hp}Vh zJrIW{I|5DPicepxUn&1<&|iHk_fDK4;Z*rRudo883cx~%>@>W@dhDXU^~c~z345`5 zWnJbp_DZGb69u0SF1) zhbOkjFQYgHzBVe#M`_;Vytg+YqOl2tS`|AANhdb^$zn>gUL8m*;l}<77};GP7NHWI z5->W#u+bE}(}ct4DTB#OUbA^+zv;17EJ>MTKJ4pyz31CopB|K7dZ;c6iNZ^I2^Y$} zmv!}JC=4pIu_p1{O(id_#@^DCzq`HnK91OvR_(9cV9Jb*M{~JrzXlm9dAihr@y|$0 zzzA1C1@GMuR_eWl;XSF|a#uV5ne^bz#9(Wn=M&Lb1owjqX`9{J6UXZ7@Y^y)j zok&l#Ygu>4PDa(pe-XqjIn{x5_7izjSwip64HIZ8ci^LD#jrnL4lgYf;v?_of}caN zJfBLE*bwSlM2jW_W}Bs#jgZHn`7$^Rvb)0HTu;7V17g3~V)<#eHTAT>gDY;d=WBXv z$paWOZ_8x-V9Cf4b7<~Fwjc6Di6CPw1sduN zt?tfQGuL8!LiHG8eqzBTTR0*29>`E0zaP(pfoQbX_ZCNYOAKeB#t?nK_U#T z%vzx2ET#)>+EP!Ey%WJoExw3yLbi?fo|RWr+~miBwfgY^PX= zS3$^ILLCO62KD)2{~w~tQU#;PM~4_~yg)N4G5 zq;;$b@&ko9Bfc@U0f~hd9V|OT9NiIGSn@c#q0MJsKdl$aqSOeGL2Fd|4Mt)I8^z_i!Q+= z&<*lkL}_+o>b)D0%UN6@-z-pYLOoNja*}qtmjC1O6W?8j>~TE!%4@gOl>a-9sCM$P zWIX5E`%mplqb$+#!!k$QA{`TIo&|H6EA*P;y_OSH8$A^t5_|aw zkL6DAw~e|LdKB(&EG1&f*;&OMj`%)Ar6se38`^C^e=4tV=oz5{ahUpIW)#yY^~w99 z#V|YrQ1#his*TS^L8inc8hBcq^A8Kl$D`3*#}mxmacj>ZOE2|aFkvyVg zydXJZ;xC5dlD2DGx1qfEadobj4e3*+GR~h8XhOPzJljW+qtszuG!ATF6m7@viDRiM zeHZ!x0qK;)$%4N4y0Pmd4LT&p97R;PDT1^F&#bDieilic*yc-{7)gzzyj;SKYoYIb zjPhopHns?Ial(59{e9`A`giX0bF=PCHFSy(Q6FwQ3jMNw!2CW{<~QSub~=d>W=e?S z2yGns2#)u7M&80Xb>qdlrN}&tuP2Rz#tZGxl1um%s=|-!CQgXkJ^SwA-Jin`Pt+aS zjPLTybwb2W6>irq$zx2$&!lUAOqN9yK9Xzv)(3d;SLJSO=WliFbSa=Ol(cZ@adA@&HF~o{EwM^jR%3mNLP|6L^>>D=-|pa&{u_K; z7|A6qCxC2_e!TA;$!fW~v@V!vsN&Z3ie5+0Mud*%9_NyJ?oDERRr_NjMT@!brWW(gS!_n z_^U7$tIB!3<;4B22T$^tG5$w_t76!^dnTWJp-=U~C9z}L?l58b&^2>&=|{4T)iXNY z*ZRW~jtRSjm$tKhJtSn|&tuHO0Gn;Y@yxq3m`<4}TfFeC++r?JsL_jxx#lq@IN>w4 z(#3;2KHj7LzPQ)Z)AM1aOMh9yAmv!kFjf|Kg;dFoaoy}+PmwnDJ94MiPD;!XVkdlj zOd;Kfz!>AeO2OqX3W%N9$ zsR#$wRra>s;%9xR895LEo8?es|Q|~ zG2&+mXU8-bc+wEw_6fys{_1>8`O(ovpu#<`SbSFugs32n$=Y6eSaek1mE!p8CHh>; zMrQLVUwxxyw93TXWP`)G(d3w<{?5HVZd{z#{P*G}pv6h_;9wm%jx zvamrgx-@{-P`6C;sUzg)8;EX_G&#IkAz3U)hLs^4@31Rt%_B$flYi*n;hovRd-S+PTG6mjZOum)dLlxJNqb>@wtp zl}>W%%^WK9r1A9rG)}i=eV0Gg=QXynL0LF?N7N5mVbe8K?)<^-r_tC``6Ycmn~N=P zqa$CK;W=xV`bIsQnNih^+5%>D*EbeMir%zj{j3T0ZlVtK0;BnaxVyVEGBSEy!nd@v z^x6m8201f_Bh~$}mZF!%uRdpB3F67}p_~M~Mj@u(%zEzH?!DLIFI^_}f|adB}WW@+j`od;Wwq^KhJ>G^w8 zL>BZ4Lf)Q%A?*PyaNd}~05Ldi{dCc02PWkvf^|nt+SJA!KJ-XE%0u7I@j3&``@`{0 zNP=*TCj(Xo?^qtHn#^l0NSDYue4;j6b4ihUpNzpy()>+eb^9HKXV2M6 zdo`F`$K%L`JAy0zgw)44xSip?ty|b)l~tNOK=itV%s2%G22Kb{Y2LDQE~1M=Ihoas z`7fM(Z)#H6J#+aOH`(SuaMry*Dor|#v-G&OP?!CU_PG0KF`kK0o&~GC^O|rj0u^n) z)WAgD$%^^p&LGW)?qoH;T`(b?_~c$^3eC!ktNO;Aoa7}GN1D6;)*Vv~c6~1&NwuSw zzdOZ;DDg4*{c3u*)R|6{k$!UdAJ> z<{9BM)`#+Y5{+;z@{eL4tgx$N!ddC2UO4i1Q|cHWT80Jt@Y6xo!Cuar z87o77PtD2_3xZa2`(it%rd<5qS^-qNJK4Rgw|9{>WGLXB?#z?@Gvdu(Uqa!m&aY%F z2gSBxAHHKjH05arX#}6MjftR@$k42KiTzUiH+j9E%qF$*u3ImQ_%yjd97}% zy0=bv*z>Z5%v$`qZX7f>^3Q$_Bb}>j!57YnbXtEyNhG2GPyE}5pA>eyWyL-eWu%FW zLhWr_eA;z#=JYjad5KlmgXdTF@r5P2>B0{Y4mib?L zFh?>nj#5XOARLJb^DDAk4D(H8HLK#Qnh6f{s?uX%QRTxwBT$*AxE)YI*AfH|=uWbX zOn-gLKm{;}{Iw}qrzP$hyqsqlssCaEsu*r(q)Xk%Zt1i6NLtB}0^>gRLv>>Te``)C zQf-XiJT;4{4|9c=Kqc%$F*`5d;l=c2aI>`tSounx!p~EAq@%UcAJ+ zH^ylPKHUC{)~h#o-O25<=;v`gF$pkRK+WGA%1Nx>@N1`2H+4H!A1?~N%(WIRYZtp~qu@u6 znxzLdX~N}4L}3rZj@&k|E81zH=gkQ@FOC|EzDEYoq@#$;Ct6&BG4|%>DuYBU9(AW+#x*odm7*k*FF?`H}PI%u99#Q}HQ)07qvSYR3We86b zI;)KW!a`U=c^i+%Y=~RI(K>6@Tsb^r?)Vkdm&^mk{pK3Re#7fGgQTAy0&+`byD6O; z``gagSqa}emte>Iv^3^_sIy0FjyX75#rdf2cItAQ6=R+`Emm#36oZDd-;~ou5t)Y{ z8+_33wxcS{7Pp+S+&HNpGMRwfi(@Or=$$Sy2st*y0Qa3~z({R8%W&B1{ZCT{7Qf1C zz3;L%Jbhwbf2|$>L<=_RHf5~2m2Z%Z4l{Kiudc{zR9!oYc(D}`2k+Ou^vjQih(o&P z>F-l4RZ@P8)gbvl*Sln#+0Em3R(I)j%#nIQ`~jNpM5+9HvlXmhVWtcO_GMXiGW~q6 z8B2*cYRPrwwIGmnOz|M*78Z27IHL_E3SB)9WxcS!@Aw5)8g4LNxz6DKXXK-o zz~s%3{n~G9PWk}+w7l2w+l})w3Yak83W=qpz$3`f%Q0wtA`Fgh6ZcdK+FL!7PSG^iafSQF6lxW_=GqXlw9`536MSgqq zTTDuJEqWBO5}TN$tuiO%PG zy)V}A7;8|(XsM^G2%*W0t4zY`>8mLAwNizv$2uCU4KP{J_MIm?o)X<;vxh{^oID6N~Lhbt9r+S)yp37gUw;_QxY$}vTmddL7;+|(?m4lx4$213zl*|Zn zh>MXmrzb>YdM_UqNWJw%=!eT&Eq>4b8kkJ)B#zSkt9!LR%%LFIJG}n)p91M)mSQw} zKNo|zj!`)rOF}i2Q$z)PI~{i|!Yw(^+s%<~$<6(Hv9PkPy#&r*IIb;9>mIkZJ7h9>@f%Y^zSfyx-djScH4 z-JD`bC&EoSP|ZDtw*NJA!*7~9KXOZyDXdB*vEly-3ZNT|W!QA;>U|11e;E(DmfX12 zzITOBFW4xJ8%J}%DEdwkea8FMABv+aBd>Zi6FMwssP#Bm$U9#Mk+GxnwDQY1WmkJ5 zS7qeX7c^_v$!4^kugx;uTSQ~#?c+PZ`m9qj$*(mQS=22 z9b6Y<$`vaUJs(JuJ_HYsPZRD4QRLkeB<8&cId+xP*x7k<>dVW+%sg~1XemnPWmox= zJlNk?_Li!I(vQiyX|QAF`^)t0B!iTv$60W<=Stk`FT!)gwEU9bN6T=KD@|>LmKYA= zFg4PXwO!m)_s5OY-_VNIdn=GN)7LE@&0zsSMh#EI%Oi3SWWffarlJbd#ve7}ip*1e z&2OwfM`#hmw}=VtFJsJLi(GMwywro;wVo>j6O=Cms!x{&FT8O<(VC^gz8f4f*wXED z3iQiPIx_bAVB~Jw3)4tFSvf_U~Bu`j{o{z4QId$;@2 z$NuphyN%LP{%H5hbu|FY_d@Ye>+Nuj@S{SJ4 z?dhQlN4`bQ-LMEp#LYtXO%E@8bfy0UAv1ri0odD^gLj-%vErz6MVfbyWZ0e?yeYEk zgcS5jG$8fX-LFSMjO247R~v88feaK zS+e!H*&JnPGUjCli23n1&30yymN}}w+}&oPWn==n%}z%wl?tG<7$~sxH01R#wLbk! zP3kIqnil=XrHww5X*K*#G|EkwH@KXaBuR@#v)i49Y0+kWqpovs9JF^ zYuxieMH9gqN3BmqUK=?@LR`;4Jgm{AH@x z)6jE*MuZQKTOwz!KmGYm|9$XfjYvss`oTN&tJ?wFYYSgd$o-U~g2HH90I+JK9VhL* z2j_q21wUaIqLXHYH7Dab=4664{uI9i6F{(T=`w?U@!edoeP^ET=apBk#8H}?T{USL zvyBNs5)u;F{a^g07Cw5wbzSU6Jq5Xd}{tanp9hz%->317dLFZoDTi^GxMZgYF;c2>;gzFcUtx|?S%cQ z5x@J(gIWoXzo6jB$$4JpSASOj z%E^a=JGqueWno0Ys%5~0Vpy6u4PO|5Ik@{~+D4GfrbFse9vz~Qfk37DyYl4yrOXtm zZ-O6;X^Db(HvpKS;>6~HEOSgq06YUQYJvTsPmDk97rF!l_7REZ;j!??m~0)~Uue8=j1C(@ah`MTu3kt&(0$cc?FApUuI>$|c+zwp z;+@=k=a$z|zH3@;wz4I1zOm`IU)MW!cRD4CPSUPSw@|Q4!h_JK`+>%1cU#sel1|$% z04Xf4ADw{CY+#_8+I#oBrr4({M*1Clu-?mtid3=AjoxLUudf=d$HlF2^j+u3u}@({ zOPnI5s8l)oMoXcovP&MIsA=Zf{aI>pN`!-h<7xQdu)=p{!;DkST*0IF)YFZIwki#r zCGmXHtUvQR%4yF;dS$A`?BB>)Ngf;I6ugP@3C`1p{CDH7*p`S=+RXebK5=y*GDg&`n#uY@Bv z_l&?_PG%?XH2?Qw4Rbz+;*WoA?e{Ll-R0-F1zN#uQhvMMF@1&93zO z{iBsIaYp~c`)!Bg7vh{1K9U-?uD|r;QoQli?qc+yj~G?N_8FjpUI#_Wvk}`=8)~!` z!V!a2eT8z0Nfw-a5v*crPxX0aueuswc@!uh*11=lc_nE)Sf`Ty8Zn6AyS9CtXS zy$CC<(cKwDgQZM1VBEa0X9z&GuFtrOOSNl%jg%yi_(b->740TKnYBK52D+#4Bb0* z&D$XvU#j_IoUo#;WSwl?>Z6r}|(REc1>BUI;|i(X8T zPPw)mTK9bw3;R@0s+Mb(g*fU7)aKNyvFq&w^Q{iD8LJ{mRqRPm$stqBxpSQu^Y)Y! z!E-L|UhQvKap|YVwN^2cEX4Vj4c5t;wWn1HmsxD+_y!zs*-T1N+WWRLwy0>ff+P%x ztzq~t#%SY#nDF)SX(J7cvk(Wv?u&rSv zv**t?;jqgtH)-%cKI}kFrBS2uhMVzf3M~;XrFFycdSoW-zOGsf1m{p6wQ5U5vo{JN zK56M5=fc*s5pmQ?)LhSHgW>VIJMt_8V-No=o^aiFxi%g|cw7*F+bNkVO&M_GOQm&k zG}X=Sgz9E`CdTzYLSMhO*JNqqnJ*RN<6DqqLy<2y6!{tlolEu#j{FoPz8t;?DL;Sxrr}ML?H)~V`TJ5)4Ni)ItM;tBeje!q= z0X_(E*VfFPb5g_JtEuUTiYSt@Z;7hg3!(>O4`8!;j0R z6K~~?3!sgu8NlFlW0udgwtfY|<+6n)S{xNt7p{%SAJ}S4uAQ~qyzDk^RcmUde@rjr z*2>B`YE?ZEW!Q$ArqpD?%iprbdHCvzY@GEI`z6}UHF0w$6s$}*k|etqpNLMqwfUWy za2(pgnYJ!!YP9BZ`5nRcYKX1e$%jCC)klb)28$pJA5&7E(vhAlf6j}&pF;tJiF{M) z*K}gjyNz!c!>C;x^JWBV)N*p;q4`ee#X}(sACwIr_GSVtxa2}6Iiu`zgJ=q|ezkyc zNmg`u7pOd85_M0;WI?)HUUZIRkKB))Pkm2`2Q8WkFc}Qw3K4@KhbcZ|EctQ8{E=me z5*3O&`)uNcEMGEEZj_01aL>#OSTd_Cz(;nzGU*Oi9upC#*NvD{6gzhdV9-8rl_QsW zfAyrmTfg)L=EbFkOLcdyM#VC_EOlT(-Fu>Wr%sIt)wa_g`TO9_dHOO*?7}XNhsGiK zmw7WfHbp1>k~VmFnAaSfSLz;3eQwXC9u`zB)e@S3WAFpl+%{3%~|})f;dyj z(_wG;P&jh*C<8^r7v97H^H;e(BrDI@AcDU-Oa(!{cDVh#+86>Vb>y+;eyWojcq~cp z2%a7Bq(K&5HazR$5$ec)a!s64{e()NGUsK#TY}O+Jbgx+s-Pe#fc1=VJD85&RZyJIrcm-=hshgDN}jXPPzHL9S&ZPv?!Ze3I){V)eq^2Vk$1LHts;b*?&d{NyzF< zm~E&P;3E;<-O3ci!TC0cXBy@LG%*?Qm4f79{fI2C1WD{n?Hhk*i@^fW^TN{j#0g!( zk6%c2XS)!3wSX$9NYH+!XI`re+!irDN77<5_cug|{=1)h%3k=R&I*nx7vp^(FtV*Y z5TkKB<#t9Cm9i_ z%Vr@*W+|u1?$6llF~q@L3$#(kFfprWr~L;YMuh1QYJb(bS13eToPSP#)EXWD5b(q6 zfRpw|3%e~O7a>RqNAmKI!HU2Vwva6Yc~GK004%_Vokwd|MAc>HCEIkmz%+2k*K)Z8>2-tHUK_qyxKUCYGn%hE#(HQhNg zE;(ev9NvM^?S*~?(p861;Sg=)CJPhFMG|MpqscF;r2J7wrZ%rNT7}`{vD^g<6%_DK z^m3|v06j9Q%Lf#*+fq`N^n%P4{tW%Ki@JnLd-dZ@IR%8{`|&u~>~ZNT>!`QnFmERB z>~C*kQ~&IkTdwV)ueO!S{Ou-GWIz94;C>;EW7m!A?Uzvh*yo`;<58Q#6K`3G@h+;- z7bf%ER1lh2=xN+c`jvZIYgv^>uNDuU7Zye(lAj*y@hkHU5Fm}>4NtHBO=TS1kG{ng z$`WSdI zvfvPaObGi2SwqskJoi`lb27La9>IdlsObOR;25TF8W&J=4;;)0qUlsVbouORal2Dw zbs+X2?Zt{0UJmdc5zNb*LNRdY&K2_0k0lOD-=sg@h=_Z+D9K$`yHyj2U7Q!zKxNr* z)G_tV_!QrOgJO(rFAYjQ_Go{IoBd9N!o>5A+YJ!T?LrkKsa3E6d9pYctrlqdME=OD zor`lsSx4S2}e5@g8LIRQF50r?(keUWVv-@IHN#s}G|(;PrFcU576& z{T=GN``GGM?#&eYmzgV>f0G%3kpM5Bw0pUje?ow+B`D5P@?xDmYhj&D5IeTvxqLg- z=`q?bxWh)zyJ+zP3od-z@EVCYa>27MHM90`jNY^Im2JDqNDUjULtpna#ZhfjQfJOa zzBN}rEa{$;wG#Ycc>4)yv6lYC?<>zN*`4*IOZo~pij89&wB$RRbsc6lo%YW;-JvSm zF4U%*^xc2eaQe$%`OKeyk>fYo>&Y7|Iyzc8SU)N%YCkgr4DEVWQ{NYhFU`)26&c$6 z{d7vTYp(E(jG3s?!`-{WRtXK_!A%i2sPuS%qd}(g)h4bSaDj4)AGyL@yk2wSF1^Li zo+fu#)W7E_Sle0PlL>PcrjJlg-635WhM2V8*X*>q0?h>)3EEzTdnv{JlNAg?jGuD! z$2%}n6l4eCpac};{og^-t_PX(Oc_sh6d|TNL_wT5yw#dXQDw88+sm|OddrDvi=`YT zuGKak55-ZBpuWY#07u811860ez8a9(1>RrEoOo?Kd%v;Ezz6?7O;XXO2{JhUz#yxg z!(tAga;Z30%`jfi?2LQ|WVhGa-%G*~k?hznX@TF1-so*6kSk8_2(y<^Q*kux0W>3Y z%V95mJgdm!Fn!MjJw3W*?)qosQ}Knwvkj)mfc zWT-FfM=izj#&-nqhqx<{Sq5&cB-b4Qqlj4PR^&>ChI@||==#U_Vmq!xwLX2hcV<$D0DNYBIA0*L?@p{*CiEBD1(ZnO?&3EHcwPe)E{i2pEu^`83@ijRpJjzN8HMZmM_ z*2Z*gBmd9UB!UN4H+J@u3ZR*{eQ_vmvCWw)#|=nVL2!Z&0UFrJ`|z&Fn6V6GYCkc^eK}-50>!sqj7PQI zQ&Staa!lW8`L6n!D|$UU`1>`Z{#JVVv8GFQi-7v#pmK2^;Pg|19IJhCk{0bF9FMvf zaSmg}AIyu0{IkJts1CF1vcx5c50~uQWE>aNCUvk-$*s`Aj9P8XxLkjr2QPI z+WY=#>oC85V1Cb0^#!)Dxoz`Xg1Uk%VX@g%j>lM7Slk$@QC=>*cG9Q5x1$6zt!qcs z`9otbkOzTjS15!aZHRE{%wNVsnTzppR+M#L31F_1hOt085ucJ%{H8dt|My^>w6RJ2 zS$-KZlpKU%gM~mMs>_{LUPhCbfu;!-<(>R=`Pt-1ZsA6Zf?>D zxD=TVCPLyZy>0|XE&&z?7M;1s0*=sTjg`D{Nviqx#O;f-Rc>EOI6q@l;W4ZpeiwoL z_9-Gfld4l6D9IsFNmDA^zZ-ZgNw{AOHC|DwJDcB#_YYpZA{l)5ovs)U%$1{i?3iulpRK*$hcEIRHng89uD_bTRrt2R;25{ZLr)LqOhb(rCl6Uv{ z)AvAbTzaF*De;RA;* zT{Mt+C5j(R@+``S9+CXojocWL#=ty406QN=CFN1NSjtidsB1Jm5}&k$ykcQ5vfq7U zJ)SLO@J2=FNbqTNiyy;DEoNKX5&S!Tvi7^VhG26yaDQy2pU5j(r;i$Up- zDarBYy%D|H5$Bt(p?2rb$aN1oI&0jo)6{;ZNNrxpxhtsqsv#L-y{OwhK7~$Xc%%8X zbDf2&55l0-md}ayCaFwoPTC**g*x;0=E};-6ciMe5xl7bt^%+K2Gr5rm&K+bkY3?J z!9&)tjpzMW4;q}f+eosPN>YmzzP!Br$5FHi9Rv5L7k9>q@uv7R0bdI;xU)_q54Q?Q zN(T5pFlNb9=g))iDVAoX@t{YW_z40$q#fN|r!YALC$MZtaML)BNeCKBP*2^@b#%=U z+=~sTov|k;_~*a;eN@y#-b5U%m@b#+G{W)d+fm`7t5iOM(U@&V#R$_Lfq#fpiQpv( z4J@ks*BAW?T6_xEiuD~+u_bXYdh`T41l$T^>;X?wBhyHxeRvCFz-&UDA@1tTZizhP| zt(pQ~gt$KMhK}^jIAo5U0j6+8LtF$6#%CT7MKD&xrBf5=ic-4oFqQw?HRI)Wr`+A8ta11QH&D%U_`~DG9LvW4&j49@kWNYO z0}G{6Y;>Ww?{*d(=bvA=LKn|Uw!F0>czV=nmI@{-xBmwrCEM}W`XP=zj!Pg^cql~^ zZNmTnkS)hK0szXpcmV3$+?sx&aX~BOfnF zsO3$9F#|MVDh{_vyXp?N;A;k8(}$Im#~iW5H#x;tHjwIAf*?TDfI5K8Xw>~`doB+u z*Pdm2_F}x!1j=XQ)7v%%?Zhz}ZO5#x2VAuq{fX-2ick`e_n$!dj&TRDB{-ZBM%->ZT{Da5{P6L zPC7}c>+N`z7jH@z16rpB$f~ekMJWv*zbbb&nw$U;fD~1hSQ!*UI_}VnfKYF4?lALn zDn!^00Of%3M$^TuuNGT(XYs%R?jM*0dL6$2mUIB|s}7mneiO|HR!NUyD0QAw$J|-& zBK;A?mu`n6OHF}5^^;?g(_)_WgVI!@dGYpD{vzzEJjACj-^m@k(+J-Z!6QEtoDGK; z>y#4E@fpdKpJ?}^PrT_!Saz}1eJ4ER(xZl>-qMN_i4yS)?R~6}@l>Sp z=Z$^9@_~qoGG3`D4%J@0Q)H|8>n;tJ0$F%%(!;0gio_^KvJ;N~XyhQwh%kB8?-sQ zEF<1Ar*Xguxl@>HA13GgGVE?Ir$I0nu5;BZ{iQS^CsXGMjHrrisx+6a&ff#l!X z#cS?U?v38fO~!>`uzl>wKEWAkk1;gg%ajIRveQA)AgvW6*?Snzk+8l9g&7atoToOl>zbk9l z?FX+^X%-fS;N=kP#~x=RQk(Bua4?0XiSEB8P64s0?O`^uO40hX#e`$BHvU1np8dfS z^bx0V_@R)%Z$pFyUr$i|3GbJ64*MsXI;hpK{$w>*qA=!RxVtj_wNgrF;ui7MxTXcS zZkmF%#in)vDJa}NogK@I0*8rjZ;xW~jV`i3SIWbTDpya*Tqy%Ei>|e@w&vNaR6E{6 zhk3|e!8W}+2ha<@mt8nm-6SNOvL%Rv=xsK^+N)0HhFGB$bz9mM>{ArZN5r@wSZ)Wk z@9G?k87R9Ok|j|6{ryhwBWO?%ljA}^tA?BodIl45VQCscZep7yfWDsBa(=76Pm++N z;!upohsEATM-dK?c?fQp?la1QUHZn10ua+nCl=M>`Jj?3C<5O8^Bg`sbrPo4nvz*w zViuK%2scAsBo7lRC*P|sCqG}RJTju@fHBwopE#!<-Q$Dvng31-R6#Weg8IzWpxnMG zi2R2Sp@@SohkkBBT>stJ_y6(v)bi)ipEM{U_-Q4jG2F??4vrx@j{?v!r}r~EZoXaI zt=B;`gm_B!g9wc?8A(~Q#r-+^?hE|?sU9>6;_X00!UYM--HR3Cd%r&}_|o5Ixqlir zbT+3tE^9cm12rJ~~zMVBL20dKm0F5agPZ8IFeh+}VX*I)wS8*Vt z1(1I}Mf+6a-U`!@M%DJW-B^Y*H?~rPYtPN(*4TNZaT78!j(XR^gju}ow|_fr35u7A zwGes#2U0V4v-B{9^k-^D{Rtmh7JNO1Kd4Co1mksBT|&xsjj1o%v6CpI%b!cba^Q^k z(9>@~dFt(>-}y%nKT#&KK#qR{M?t^!;^j-Q!ZTVTow_{#%VhYV)Yocg4e5&j&qfG!38y>FH^l-hcR?H%{d4n=L5yjzNm(aY_Wepgu_pz`=z{ zGx&}v#N+MAQXuBTw}>34p8r1qz)c^H`2PTrpa<>js?qNaM@3KAJ-Zz-)6Bv=={stt z$^0*V6zWY}uX#7}T1lhdpZ;kA-=k5d_~ZzhK{uuD7yt8!yLs`HI{k;py8?jIpX{iv zj*!!#ox)TouY|&O%wu(^OuhI+6ko3TaRwnoAY_n>h1}TxhnvK))}*1yR<@A(21K0l zBf@Y>%t?fjTp)T3L~kwR+hk{C34Y~iG!E{bEO6aQEO~&}6ir8zUm0>z|Nl?PRsW*} zR%9SIx?F7x1qqNLhzBn4T8pFcpR7c#QTUvHh8Er}6%VBC-Z#()SmLk1FKpg1DF|Nv zu^u1X!1f>ge1RejgJMS2rL~A)5GwEUMYFAH6)GaXZ^6WJ*ddi` zj9^YLGxL34OH4PsL~SY)2RhiBNj?S^Os9yrvHaF(x(4Y%?x?#LO}I&CV)to1nRoA& zSi%t%Xy4eBzWLU76E1ORc$k045yTg7d<8iVN>Fh>GChnn1a(o&XI88;z+=Ucf|y&K ztw7OLH-;wO`_P<_?T=ra?>VAXHEL)h+e*o;x7xB1g&(|eA`-(bAcE-Hf~O8N$IQ)I znM|4~Z`Pl3Tqm^-hAy9@zedUZ=$PQZeR{WM$B8Tl}*6EsZ2LOEgC3EPo%2& zaUN9JB-tHsAkA*u&%(41CMPQ$A8b{bo`dl5`B+`t+E)Flg0(Va0ujshIBBhQsoSKa zo!6%1^cufpg29{LcCEZZfA*+9S=&4NQQ&>(-p#l776eHzB(M3M=H%eTe+c_C@KfNH z-31e!eYgJE&C}ayxU*J6=XORoxvnrH(1X&YgN#@ z%(w=aS%nwwoS1PsfZ*Q0Fl}f%yI)Dh(n98TjPijsHPZPm*^iv?$9!A6vsg@n5cs3W z=#H%_3qNhNu|@tx){R?+gLD5k9qiZ{(l#{a1UvculcnG{fDpKH$iSxyrcvT1%9H?eL!*ZKad#0&}!Cjh4z$>Pjf4u z{!7PW{|muT&-(_D1=)+2>Jpt%$PqxYrdq>&hC!G*{J*cDRjVrwzv_S(`wf&f4(tEh z9A_^9^h2WjG~9Mv5QZnD5n55H@VaXYOht_U1=Y{VG3s6n9GN9*N`tUJK(Ub{9Gsk+ zt1AKKa+G5C!Qose{6g$^aUP>`;sJbAUVKUrW-_*G|7QN_H72lW$} zxmQ6qEjt-?9vd@4c3I@{=TIved#X}vuenLjPu)>(oH)H77k&QK{Pgg0_~MqoEtIa& zSPlk5!*d=>92a)O#9lEQ?-y}CXO@?*LAzqCy&Esw6MmESglc^3-4DzNJ1@mo8XEF- zOmE&Sso{lS#ox6u+!^I?W9V~MZ03uEt0Mmr8^p{@iBC(Y^Mht18j(?sG9!KnPEFen z-;>S(y+&@)ATw;2P)L%^uRGt|nbL(*WfBYt-^d9xu2{u;f(HJV7VT?IPhiX~zOr*S zT?qBhY^~2*So{XjY0&*5Fg1SU@o9AnX@tgXmf|0uEnEbx5RQ_>+@bf9^vK^T;g_hp z!8h$+D2ykHa?tMkIh;3JP6$vyVfJx|16qsHv+MyI0vFhiX|PodJoGpr7Nq+r7t)un ze^u`a6Ee#_OCgE|vIU>kJ2-gJ#N>cqpTeR36L+4#(;r(9G_L>(-WF-o@uJw-yy2^a3tnH$nVVz+;y&Q9`WN>om$hz3^{wd5?(llefq z%>7bl8y=2yxn=E}mR*EkAD_m-{&a9*3Ll3odszZzO30uVKW$8o_|QY^j&grp`2!O& zN9b?^>HshV?wP&d0UBJfDwo>$-AiTXw|o0m#DW)=`?VwBwoU^7qq5C0yae4wSFc^OcEm$KbI|d4 z(n>(-=kA7LM3)l;we9?is?%2U+^7$ygx>PwTM3iV(gSZt0i*CW2l@Q zgMpbTq`&n`A0W~YPxTxjqHd7LM2%a+QFQHW?EsYjoe}QAhflNKa~Lq{m)-pitYcHb zhPnFapV9xI41dKBb{?^fiBHMc%#6)Xmwc&21CtMSV(>kTEIM=x3`zBD=tfYM?fCy`d^D( zCy7b7^_jm?P5l{cU=ZcWLI>-mOAA>AXCtO=wzjnxk>P#4b9-)FakXPOu;p#nidp|I zC`yZS$ftY+8u1jqrMr?Zi)oS5o~}ybq|9u)d{W2DU$x@y!Szxko-KOVH`%#B&P~(x zPt3fL5Jf=lwz$BX`r%c9-Cn?ab58BiL-KT5%#&OE*>) zNcm5Gi3LtQb`NF}P;Vnj!(HN%bqH&n)43RS4AMEAPW%G~t=<8GTPVYg1x*o~Kkf6c zdtEDRfIBi$gceJ(Z`qA370OoG#~RtmHW)L{ zd!PCK&hMP}{LcHH_n+4}{@{6@&*y&b=YH;f@8^D)wd0IC^wppQfS>mW-5`NQP?DG` zzP0c59KDe}*xI-`f$X<$rDvvn_7JW4>Ntr?jK^=chpFwaa%H)V``dJ|fHfmSN0xaM zm@mPhAu%_xx#UYNqI(!xj?#)QjddKzM>}2kFsIoJUDwqqmkFX4kq0Bln>pVKZYN>d zI~+pnukK#lBZ%YdgbhF5Pw|agZ+L}PU zS78kpEmwpy*V1xsY2$V-L^rBFtJlYzWzf}$?h|G4yV_#DwQu;zOOy>|KIeGLZKL-v zP)IkLudsHc8+1xx1Ef};=DqdHt99cXoF7qxtFuzD-eT8rP$5lNk1KtJA$dJJ1Sp46 z_#{TKQKj5n8S&R;E}-RKALcSl6;`}Q5+dbSz`uojyKrkSr34Rx0;tB;4pHPaZOrgt zkl`4d=yUbbHH7q(y;}s!ZQBN(Us1((vB*g`4HKsG-@ZM9vs;C| zC*j;v=H2$yCS;tL(jGm99>nkhp>J2^Qy z7^4QGwSpv$)%j?TPa^&XgF4}1SUODyZYsh8E`*4hIXR^$Z+Ui~ga`~i%%Ezhh~GA| ziprY5Zm~FUFZd}a{YLCDb#uWPEWe6ZncV&KujxBiluEZW`h5}5*QZ1Tik1TRim$L# zg!LOdu6zYHYRjuvPY!ow?kENoYH>iV!K6nuA7UrMJ^! zcnF>1A!VcDVehHZd<;el;MhmT8m1@EO>(R<*76ug2Sq%9iPy4~0Ls5$!#|`w|xSu0EfEo+g5)9Z`YeZKIDCy+N}(yyG5l2^R=mB zn`aV)tq!EOEF>i+4uN8kirGo=qHne&SwWo{OqNlX0nyA7b)q1MuJqUF1?!BJ69<<5 zw24&$cMU7s!6V0l+|21KP|S^RF*O}rTtr`T>QS2<`MF6tr?`yrsF2JAIbW6qdx{3Q z^3>Kk(yh(SUl(Vj2Wyw*!;6nXF1y8z)NgAIr*gLkUt533_hf8nsB zYw?!53rxxI4E4K<*R-{{To>6)4`R3bl$A+AuGXftrmse^CgAmR>8Fg8ZoFND~tiT>PxoeLdG1 z_d{?yFvZa-!xOZ~$IB5AApNU5pkA&-b#pL|X z?{(O0i4Y$6>0sZV^;|0f*P9=^8@_P-8$!Nv?)=YAmhRLIph|^;bH;6M)4f_&`+!pL z%fB*w>~eAVk9&q|)6*WC;*2(H@{HvCM}m&N`^h#72f%S26>zMqE!f!B=J5U{X+$ha zS%QQ%YVbbfP|(LQ@@&p7w5Q0#F#S$(8s|&|&Z+LMKHO}fUQDJygV1(x89+2NIy!pI zdftb=TvbA=WOxzd#uP5kM_Ja*)Uz*r5=os>BWV`=x8n1!&tQ_2BwAuM1)c*VLqnMJ z7D#v++57XBwK{@G{7e0NeV*Q>Gdn$;icb7!2)n|NDb+i{@EJK}(Xs3{Ahq^VHaEq? zJ`uOj8ET7+^g!mq?L_3q?CEE&6Ju+4f4IboKSis%HP>|9Tpa;}IC16!J$>h}{TAd$ zs0TVz7KdPD|9(1%WQ&w{Ev)Gdr8BWU5fmH+hbX7P>`ZMH6pKpW)p^@Gdir8;_6kVo z)97XPrMk`F^^Csbx{eFku02Y?SiK(U6tpZ1_$dFjhZvgVe-q3qFh_opF`;zX z!^M3%zX~CSxbZN#XECPka1%@^L1dfKRMo8?M6qO)&FOdZwyEjPAVFa-4`0AM*6f?} z+CkZvdYBP+6AAGbDT>>?iD^9dm^)|EC;>^h||n4fS^!lo?@ zS_fYT-o!9QGJ=e%d%LHq4(M~>s>(ijfl8N(bw)+}6EswcVDLQ%iCcxq4ew%ryrGeQ zlsmKGfL1!tpiYZW%ti(bY|_ruCwTw!HO%^9oaMNL;SSk@lut@wAa2{n>oDVv#SS~%qQk(A{6&KE8--&^%U>}Ce_r)kUgY`LJ6iS~hGRlE?uu&RsC`de| zjExG%Rpf{@owfByx*;SmH_Uz8KwfXaq6WIyk)gg~|k@(@DYJXM)Zm|IU2xTek)+OiWhumPle1@A;8NOdDgZ98*!vJsAHp( zKHz%e7&N)NOhq32Vp@_@V16_kx#bUE^14WgPugsuD1({MQWgO9_Yv%SG=6jpOt8{0 zf~t7ngQbJAmmSqrv#z0~Oh|_tA6|H$)!|CL{8J3ujO6~VVf@94plk>FYQP0?2jsuC z_%QZQXa!#ZT7O5A!`@QZ(IpwyLeyQ?7t+Jjrki2ic@blEUI+1lQrDne>rU2hoI5ik z00SUp`CysbeNxVXG%paEHSFDp65TD3xD6Sa9WAGkCp|;w*t>TWNLGOt6iqt?k`Vn6 zlMZ(gwAMj?1=y2C@I12$dzho;7a}-oCXGo23!NFzm_U(z*KO3N;*4;TH@sl-r9r z0)xV)sb-&EmSZ>qCA8-SR?sDGCfKZ>0!T`T+@!|hxOX?Dw_!I4I#37Q)p^H-;GgFD z>Zs9KbXScFm$+>>^puj)ytjxjILD=-diDIp7w48LL0fL&t{H?#(KEc_s;R1ixg&Sx zy2;f6^lXdBFtN*-M=6)b8^Bx*5MIiGp=^m)4P_&#ufMRdf-+9Ds~+$JZ6JjmhI|4 zbLVeWA|q1lGBn`so0KZP4y1IV1m6u-lqa4Tg!M4@R2lRf`r7Vlc@!QRl^9E&iuTUOwNKNvvK? zshJl!S0ja)GTW84aE*;_50**quQJumT3H z*Kw2Q+zyt%_*ZLL^5S%*aL#sRU#QMGKE)KXL2_N0YN@rXj8=Ws)OsK2sR7B0X1j^$ zpxas@_;D%H-gx9imsw(766yP11FuD!>(~GKZQNN@Tx`B6YP(<%Yst>#Q+$4f~LGIoaC2LZae=c;?zJ24-znwq~zk zec#Wyte%t`t<)0b0hDp`ZxTwsF*5Ll?g^Zy|9qD1qY}!gjy!>a&EQD4)nbs9zjoKJc#3x4B^n znlg2Cb^?AD_7fyKFcaE$2H96Ag45h{cK*%W>X|g^@9(o#=b6Z;qNu*M_JfsLH9NvZ zbF3cw;)|Be;nYQjg`Bjhq}O=X zV<79e{-@rwua({1-GQ3R^0@d%(#BsQF*mlhhTL(*ULoZE&f&-fX7i-ALg(@9tlAyU zOi*|qN(ntXIj%7!J0R8A-{&hO>Vkq!hI*8r<}!rJ?j5$9^!gu8whe@tCFvtI#;jm|9l_E7CIAhlM={33A0dUVIkGve~EEaf?;dc z!SrH=DsF#$41Qqu?$V`dzXp4tb1XSfkC=fU^CJVg!mURpCYW%QfUobSw+~Ik>V?in z#vG3+w-xxaWGS?Gxr_d#bWp0rq<(M+rG2u+(lMY7|V^%-$F zEho~Yx77!aMj8-{uYGB#tv%7VOlCOMC8%-$BJVA(i^89Se^It8xhfuRGWjLSNl1N)?VzIB3&!QY*>FMDK zUm5}W&8YC2(f+y~(I7@S@!KG4)o|}?vv2Huef$&uR>>9LaD z=)hnK>*SH0Z`>GruS`}_HwIC0`!s+p0cW$K*c9D|Po zDWe1Y3AEEoQOdH$%H=nRf<`Fa*tHN8a8H;5qc= zL9-6kO;IIpgzi)`BzDy-e3$cbLK?ZNsJlS3L_M1kc09u!jYEM&mEaW=WA+Xt-JT)4 zznc-uWgOkEPswzx^=T=+I-#9Ucxtf`Zwdkmrp^2Kar+Qqn{)6~L$2Q@r@Z!cG<;pJai_ljCB8^4V z^Xlr*LOy8x4u6Y#+WVw7n8D)ODF=AS!Ho-JuT5MBm#pn-xRM)ETDc=A~To3pMq z;d4$gJYb~fiq~6gQdocEmTQO3fHb&KWB<8( zxl?fs0X>-(XeLQnUV>9_Fd{SN{vN$UEQV53NqA-9PRA)OPDHV))6aWjlCN$py24ASr`prt#+bbjw>8=9;Ln zjMILbWjH98sy$6XLj_HevM%jOJzN$!alUrIkoD)o+C z%jeN9U_sTV>1q|a8Mki~S`wHe27_6$;p|M8azjzxYA8iPltD8)rA-@{_H%=g*0uWg5?XP9UDzPy&y0>Js){;#yrU>fF=u14 zD5L`u4;+Um=Eu3If=}h(ST=8cau9A36BHJ%^Sy7*70X90o|)isx}A)f7f1{^3NtPg zf1c~P9r9<@>QBUi{J>m>+NqC${E>CCar`Td69)g4T`U8Va?lmf)uy^jEsTxV z`+VIBLD%s5^@#EY7xbdh>c78%bp+d^uCe2PK{r1TSCoJZKLHH49JP0Rz(_1=&IWaNe?CNT7p7}n0)hx(vF)QDHTF+CC z{h97oWGviY@yp!BC0YZ$GzWKSCCHl`c*==wgBgh)N_IKsTxhx5)YDUK=Yy)XZ@=5c zF7*3|)p1e)K+!tw3vp&#v0p3UioGl3U|k3dLb=lyHS{P%#;_4Ys+qgDE+s+vdx!P5 zC=q0CVL?ao^7FuR7Z|4h;8HQOt)8$AB`Te^H$kP;IXUofOdgruoUk5@A?vd41=w!5 zCpmfGyMr>erc9FL=<-p`1^pSgg)d}PWQ^C3s_`>_q@usZ;d zZ$?8=*1Ak#ZcexhQDG<71E{szZTeG!;_HIWf0|0q+{?B%cl!YL^^d=8P9-c4%NV0J z@^NHVp`l=A(LfLQZi#>&w|1t|Y;Ii!#8pC;g}IhN%NeXjK>G!?QULNvFtb$@^tD>Q zSZYm%C3KB~JF!v)1?6#qKH#saVjo@7WHCym-aO(nI7x%9e6r<+urf__#ce4Z%%!Jn zGApDE+MyM5g1J>{bT`6G%Zp%GxbA_H$z$Bb8;!l` zN|u-C!fsy>o(K8hc!Hy#dyG)FBxggHTE*SQl-X!YnSQ1mJtZ{8h2OK6e=|LkA8`*m zIE4C+p-#7ZOe-d>JLG6(-qG{-YMuoK_7vT$+ar5p&momL;uMvB$VVdgcg|4^!BOV* z4&?8xQ=)=2KN|DLEZ6)|lVnTn?EGyZR$NwmtKdr8(XmDx4$UFyDPobf?(sx`Y5EYb0t z2G&A8HA_=htFp2ZN-KPN@A2Jmb4wy?7zCsZ7or=qz;XZSIs_`O!>RfGrjxvJH)wVS z1ZHk=arC^_jvO;Z$aFiR9&|}QziR#~_1Ta}_EAKXUk=jzx7z1YM?0vGryOb@g|Zk7 zhPiZn!8IrR$b*oO^-J^Pjg1d9Oz)d7x$|*m8Xkb2Bf}?(V}Rj=?AP33=~-wAhvDED z*VpP@tApl5QkU-hB0RS{Z!V4P{}W|fp9RynT9W7140&!okoEKf zn~(*o`brDo{6z$GZA|Cmyr)E6$u2F8k>$*l-?8IEMn;jhRieiKpEN#Yw zx820yM-qx zVD?-vSHBUNMgW%q{*~Czyth6FTxIKcu+wf-%}lpr?hdyAL&UBO7TdxiWR{wJys4Y6uRG6S{ObGVl+;v{r`+I)Dzln5$X$a)U~zZoXeb#a_YbXPPVp)G z>f*zKXQ}9$r#Lq6F+|@@Occ;Ds(sPNL()0qG5)0VK$r#O3Wo7u`3!=8Kwzyf(>BcP z{5H+0Y;j%S5mmvvKRP=u>i}`)?JAsd68MOu$+!OT7Gxt);n&_wSE2+jdPB!i9N#sG zZF*>9isKJI-mNDRqzBgudZ^GvC1NfVFB{(#DC0H#vtC`o{mCZIj(GgfkH#S+{>y%? zLZ246r|KK*y{Tmlb!{L-y46&XE5hrz{PzW%?|mUHG>_6m~_9ScYE*2-7yS42Zpq1LH%4_x8xmF>) zQk!?Bqh{$15n5}H8pU%^ETUYtq@7E#LQ4|_#ac=PaW}sEm%onsU{4eCoeDMhJn%QK zcm)|s`E|tx$Ey`|_g2CD&|-Ib9|q?ib9&_iSH=*sa;(QRU&v$O8^?|B>+tfa4S`m2 z!kirODm3H%B-ig8+(?j7Xmc}b*3){Dx|bhcI&%3&W{%o*RQPwC4AJne|GUsH)&!SV zRfBcGj)>a+wz~)0x-?41hNNJf-Kmxm;pt`DaHIe|$C^h3!^5&N6x3Jv22xIj!$yQ( z?08_@0inPz#$z$^U~5Deh5z?g{^utYc=bO&{yz@;?~ngu!hb)(!|<4f_1|Io-=U>o k-~7ib|4%UW3a_juA=LCXNn4f?hEhcD*y*F`M@aYo3-mFlAOHXW literal 0 HcmV?d00001 diff --git a/OSX/iSaverRunner114.png b/OSX/iSaverRunner114.png new file mode 100644 index 0000000000000000000000000000000000000000..97da0c72cc800dd38119566e204354e09d21c316 GIT binary patch literal 3809 zcmV<74j%D|P)L{exucP!l`z;18u$krn#y95R>I&gAl-j|lK1e_+6(_N-l!pI zB?inyIa{U#5nxDU@ROvKFo+iBtylNPtGg_nP2-H&NYV{FibbjOGuZv_zhqUlle7{5{=C&ChN0)U;vWz3=1NVyd!Hp~B>?nz(Yf>) zu(2~vD$p_~=&y|rk&S$nrB*KNuvuWEfRZZbGAXrhj{}j7JguCmS*J}1Y{(d_7xc+W zDQg^vY~*PLKX8f8K)0Xb2*-!WM#WG|>*SxgxAR#OC}!$Z#|?Ga&Ji1;;|U-dXdO(_ zdLQ~HPIYe!Y4m5ciA$C7>JxtrJPHH6YbuN3n7c(QZK@8ER!^{G%38C|{VVvbJN1;U zi-mpfzv!=t@kR~s4s{yH1%K`;P!f_>Z<{6b*z=@WBp1^`3WjTscpnd4p7Hkc!Y5va z|FsQv0J)^L`i|BM=KJ1MLhh=+X5YO$!KcF7Kil=B!^xRCA4*q+CHWs@7%8SQurc6O9_rb5chnJF0U=)Dd1wXSg;w<+kF7C;HY!M_^bze&w zxTuseA!bQheZ!|c8fMuv2FKw#9hNu{(`~)2P?b512uMU@w-u@hl2+e3_G zR9_^mctds0nPPX>23$%;a+LAKRa$ZGR*d+zukE_#{#8b2HFR4@TK&RMylO97fDP3J zGnq9vP0i|f!MxS({hG>s&&7Wqsxk%(F*-?FeZ%y@uaB#`QQME=B1a3VdiZNSAHyjC z#20%QV5p6%l(LN9ohNC%4+BT@_g$~`HULlp9I4ZbFv-f?(YR1I8o@&N7m~b$TECJL#coSyyoPykNvWfktc zBrv$Wv)e(U9$z?=f|1<8Ex@qCrdV$Ov$-Lnb#QQyV^&9z z6WGE}hM(xx_Hd&1jL~h{|(gIxz?7?6i1AM4Q+%;Q` zu^6zSp*7Am*4JsXteMTjsgi(~7)hH;G#+u+VIO&1bt5n7P^Iy}D#>`J6%+tXO&xaY znpvYrCJ?Z5+FkV(Rti8yM$`eoq5*Nc+O|}|8Mm}z$D2_%ioZL9P+s|*x^=No$f3G- zp1$9u`2;-3bEh40#z}KZTY=g9Pc&%5tH(d3 zXmK_CZONU|4M~fN`Z8x_WoKuP*hHhz96WdsL6B&t)vW+-fM;T4W^UiUJ+I;{rCW>V zB!{_^wq5DWTfi@`uZP<%1U=b*+-J$_Q8;WGk``C>K+JAFSr1pl!z?_u_3PJ1y9i*1 zMIiOJ589wRx3#so9^fN0@u(z9P=PtE;kH#N=m%=nty{OviR*bNSe!X62~Yv=ewzO1 zqmNcqRgKsrJv}`Jv=#LL?$i%yWQLSgUtbTu0y`xJycG*D`-UkEek$0lxw*NI|7jC; zUU6V`R(;``NA%`$(W|e%I!;m+*7GZvoSIfMh(JR_1E?5ux34l%@t+DpZ$nQCY&ccd z;K95v$LpWA2$J`f8eYj340SexhQvIrX>=x50U_3g?z%RhA}A{>gN@~Rzrh)F*iOBA zHuu}JM~8Xw`*j028*X-_6jUH!fyV=_3NOQNZ(%~Ezf{RVX$2i96_3tZLZ`l6P0!2b z*VonT8t%iX&hR|Ynhjc^${xeCde>1)ID+yfLyjW;#EBE21F$FKxnH8+8N`o#)`S!1 z&0x8PosRuF70y;rvmLI}FIB`B78b@ft=^6m9k_#{0O}v~_8^VCOE-_|v>+xg8j?jE z8i)z#0M38~IlBE7)!k8Im{u9xhqaXU#DmR(UX03|NF+*r;rY=9EIgj7FYQqEk1AkS z(#43;q3Q1kzYY*et1rjCk(XF>MhAXC#=MI%8$`fT?tP`Grq#5178ifOqJ0GvHv9og z7_DFf{B>dORZh)K6Xa#6d_ZA?3s@-L&=&y^u=xEi^c7_)3r}4TrL_7~0C&J1sx+bj z8??fr9D&bQN|_~wA>89W35dZF!?Xs@IV%Q}imHa8S_fJ|>4FPbcsvDV!ywbmRuj&) zpiAJLg>)TS>5VH|QJMSpoNL1WnoI{;QwC=V=Cq3%ZrNmFI-cQe6ud51EgR;54c{EB zopI7Xeu#kmtg8GBatH*h@rkU_1}szu8}3Y8X-!lx@s<^+?TgiDy?Dr1D&H6xxGPI)DgR-ASc zYW$DNO?lY@2-xiG?5h(({YuAkkASWi}O_=NWo!A`iN62#*RC8 z9LiKyY|{$Ziu6#T36mz#}5fO2ETWQNAimuX^*R*^`w;oahBkb+|lHB@wqiu%^BT^sYX z0&;V6``4`qb!{3Lh{H~wVlAjZsEO0UHg_oGZwCqs3*VB7!Z4`n5Bqg0D%*L!FELgJ z2K{00$EB~>BeO;YcjOk^fgb+(~1p^^z`(CGbgu3B7H%<*Vt`^9+R1w>8~?| z;<}6w-Or94J3IoUUa!_zHT&-Usgdwt*Ki-ydqSaWI;Kxm1sfY8%f$%YU3q`vV-(6f z7B@VrghBQE=Do2r1VO5+tHaz&!o8?So~ElruMYK9z7w)XV~>IjUR3 zPR9?6R+QNgl?l~yl38RW!sGxw*Tv`h>4^hXTF>9VmtO%cP?fH5B;}lBk<(d%}ZNU%lmY)o^C)=HK z**vhfX$+Qv$?=%N2E2FJEfC{f5@Y6UT2Gg?vFZP_IpHxwa1r%k;A{{5WR@y>TX0KZ z1-T9uiV>F=8x_)et55xNlfMOvWMX=bB3_xwyf-16Ro-MMs6aZ@b}SK#U;15m04~<-(qy!)ENid^*4)P{1I%n9Ds*2fUZXg|?c;v!-e5OmUH4>p5E1L!Wr- zvxcv0M?9>t+j^upK2-WMIa4t+QgXHq}d z_|A=^Zx9uySoHSxny-C1jcai5CqyKJjmcmI-RmV?wRdYunwpwMT>o*5-czAaB+Xo+ z`O#Csx%$|km8b8XaCYnUZ|mCI!}@1j<#IWA`>sWM!WOxVaNZu!I?#C=A~Yo>C7joV zE5dadcH_7e0b&cYQ4J62xYDp)juGbDBd{=wX3!`kNLoo+Nm@yew34)vw2~kc{}W&U XGf+<;P>}HL0JY)enyV}o2K;uMHobt zb=f#McP%|L3rn&y%%AnyAR2o({QLe9!mwuNQIKNx=Hv&md0(^Hs<6Y=q_c?12{B`u z`|H;)eBl5De2h%i?A+fi6+RyQ!q3F4^N%b1i^vHx8HW4cfwDT^xih7NZn)VfsOtf_ z7cN}bxN#%l@C5=Jb{>94W_u&$E9b6S|NIXWiDVXL{`r2}{~unA0zhu~Td_4i?v*yI z1F{bsIDpk$Ea^dql@l0__l_L<5#j?E4130LO%Pi00X?C4`Q!ebn@CG%a?GqiQu8JQ zv)rF6oCptD{op;u@d?7#{>FXbuhkE}S1Z=tbh1Pi;r+x4cksA4Eh0!w1g(ef$h*=5G7`@#DY05J$P+{r2eZFRVJ{g_s{actC==pZ@>r z{PYrrrQTjO$AlSdeWf8`|#Z#aT6cD;1={20k`xY7EbKuVgmMu z$DT|}{P^k#vLG89n`(03PqRc~-HQgK?rwT@dK<8e$11C&rT@UBfE;sa*p4C_00bBS X#dj@rOBkJ~00000NkvXXu0mjf07;*g literal 0 HcmV?d00001 diff --git a/OSX/iSaverRunner29t.png b/OSX/iSaverRunner29t.png new file mode 100644 index 0000000000000000000000000000000000000000..52e24068be70dc2ccdb217063bad5d420af30673 GIT binary patch literal 906 zcmV;519kj~P)ek<18tD5Ix*sAqlcA&?$@NU5M6Qc%JWgjT63NZiq?89A55 zC`ISSba!*}cE796hTHrzCq49o!`*jwxWD`Rec$;Gz(0<9Hi*4=5r4adH6oe%lw8`i z-%5!mN|HH@;dk~;DGM);=23SG744U_8D(oZ6&p?IB!v(#3w5C!5DB3Tt&0VsF5?lA zI<2HJr%FOJJ<#M=zxx)nrjwLVVYqgb^uSL~q@5+bp7uR`Dpy(Md_ne9{u0HibLoT` z)eOx8-61@Cr=)^-$>!!}6MDMcZuszOz}%=%LY;unju2k>5zeP>s`6UMFb>|?2vn72 zn@`l47ZMS4bacGg@+D=|1HS-ps4vpBG)HKzWS-~f`q1Q+W~C zKYRj1km2$cEElk#2l^Qr&hl1GX_(7{7qk=Zwe@gotJRv6G~wwj6-wYZE&=Dz2+)_$ z$NYE2Er!oIiyOVfx=`}b3$F+IQfnC!6LQaz2>^@?gIyA9ik_Cih}aihA6t?FHTHII z`czM6!OZg>m^fXzDKGO0W7N(KJ5nPZ3T@a|JBfqMVTI{%D5eJ4|2LN3kEcf3AMk>A zB@$IpJGlhYkx#^^)V}O-}gJZHh_#f(Md^j1*wrDh;Llobbyi$T-F(a z?@x^sef9W-nyAgmfcAS#SIgFBa(%kv3x6G`!BLBM3dPW;DB|`uk-}^9F0gkx;9=*Z zy%}xxWg4`(Gold8DaB#2%{niw$_UQNdFdQV0 zQtUKoNx(s|T+d>t!;TC*JtNah$2BsA%1_(s-~~EUh-1t(vBjTd33N7P`B; gFT#JU;g0|V0HFpUxM7WqjsO4v07*qoM6N<$f+f+ZPXGV_ literal 0 HcmV?d00001 diff --git a/OSX/iSaverRunner50.png b/OSX/iSaverRunner50.png new file mode 100644 index 0000000000000000000000000000000000000000..f2fada114186c3a35011cd368f108d4abff187a3 GIT binary patch literal 1506 zcmV<81s(c{P)r=bbvvjPK1Dg1RT;F@{y?cN6JkRg zd1?Rf05nF^XCPEi;5&c%T*_p7ar&|e1k}(MtqPRRfKcf?F0A+@wh6f2Kw)&+K z_j;yRI*n^e$mI`Kz!ngi3k!tB4DWRl_T&4=FTJ0}Z#0kN45U(!j4;{Y>30!O;J!1p z)~>ood>n)!3iON{;%*jxbwhFbfny6+r!fzlb~AaA!iuwwXnH!xo@~jwL1ISE;!06= zz=P5lN@B#bC{tef$tuhWYbRH+!pKllKOGT-#EwYJd^e1^} z&&J7Yh8T09i1*)1kgrN#;sr!&O_w2K4)R^QjVmw8tU6ahYHBLkf9={e9LFhuRmkxt z&Z}oWvpp+!-45hvQ%GPwPFtl(OIG7|$Ub7|ee(o+e>qGpR=D1QiQg^7D>)C!c0$MFkG6s_$ypfI*GdaFb^HlTA*oR!eab z$<%`y+Bqz_+Io0wM`75`QYJerX@Dyf!)mpe$)_MlB@>M61AP}AGZBsf60;bvLTO*> zjQ_Q{Wh7A&`7maknqpXbk88Fdea4e|^`jAv0TQF?9i(0$YH79*>cR41uV6*w!-%XJ z>S3+T&bqlhFY4t0RAEsXcV1+SR8I36K2h_S(ZQOQIQtzk48y301rHS-uM4Z9a~s^E z7`HWk(;0vjVay^5fJ&vRsHlMF4kZbzN2Ws-gL9h#AKmnLQC(eKaA89kEU^0e`g`j* z7WZ4p!x16_3b%pmo%P$|?h|1;+BG>8Nj48njh9=7mu^=L$Tp4*%oZ~;^>$4R)lQE` zOMd=78FTuddD_cB%!tl(FTb44FMG3|pW_Jx)TrfOnv*w(e)>$yfV3PdS~=$Zrvg z#VH?LnGqx{BCI&;NEB}$_Co^&avHRGz4TIlr2L=4`dfej02j4BgU)wT>i_@%07*qo IM6N<$g53i`CTC zI61KD>(6U0m)V9jlK^W3i=QjK+IwjGB*1D(%v{44=E`b@t{od0qH zgc~f@_Jnje{_NnI{@6jZaD&B46QpK-c z2*XgV-A2taR&xq~R0s<1J(fPrYsk_1`=Nq$>9O6P%bWseVHz6yP2}vI(9Wu>0H5Go zYAQs)FoXnF;q5cKn=A1)HPd)nnSd{&-1{RgR$!%#Z_?-=R&ej&jNtVk)35*9kMq}L z#(2@B_NW!Od>82kMg|jx3K6PnbO_SI#)_ZvTGO4=c9#gbN~L&&>2DkQ-<=va&uYd` z>LSf1%ubWvv>z!ltNQ@r==HG!j4AgemY%v-qK(O;rEf5a#DQQPJh)Yb&SO%PVl0Hcy^lb!*3d{GN7Y_6KsOd0m68x zwTjF=ym!|a)NUGx$|rj%UqSITx9SPRil+gtHm8j{Pa}gxtz77{^m9$PUPw@$s5BZ4 zQCKfxT2Cdccs#Z4_#S2Ye1Bh=#bGrxG!TV#$YDQj81!84n<@MwS1v=by3&*_E* zgoj_hOrz=|7His?{I;bT!Ka~!(8{qY2=}iUWqZA5SbkYcgkCQyARH@?#|u9s@ps|7 z8U)^p29e~zZv@r_U=oQW?x|I-&MvrcEdZIqAU{%f@B8FO$SOylNeEW0R$Ek5gtyD7 z^qQ#I{$l-1s{ntpe*O9h-6Mj6wpiWmml)vs6T|A)v!4YoUf195D|d05`gMKnK>`hS zpAgu6OVwIBr1FIrP(p8NkJPgk_ny|U*+v@QS1);t-{d{_vwYb=ORYfN52X%XL5TQ> zXgczkW&BmD!S@qpF37QSq6ys3a^5Bqzm$1&P-eTc7&wN{$SEC3s6)C2pQ{;wQnns` z>6lH#X}~#FE2jSaW4+$JTyX^oCaXHdXgd2k^~&sPQSV)j?-0J!+REOiR{sQJ3;1>9 z!2Ux5D9u;)%c@SA&1S!Dj1)U_(ikg7X>nvCua(9 i(tmUQ$Lihw6<`1z&7S>2s#)9s00007pYrC}29qWot%k1cGw_~N-wOeg%tF7&HXKL+=(`~IYbr(ii zw6qnW$Wm9{EZ7Qx0P+lZk>|~84_pn8Zm z(ma*B!2A=tT4n2Qns2}Wl|!vkpL%(|0i%l&*d>RZW}Ttx^Z6Ev?seIJF{tgud%=72 z3YbH_@m?yD$D|=&JUg#|QCWh@6=^%2F~87t3=^7c;V<_UiRpX_^-q?#R8^s|?%ezV zhAvyzj9M1akW9k@@r8V%k}dqepf>)%i-tuuHF_iBjw*W5TL;P}v^!1l!3bj>W}yUI zY#0)57uV~`KAL?|J-8tU+ zoJjQ;$i1eh7uLGaTRe+g{pG{Ms%X`D=JM3YBf%_9??gJ$9hL1iEb72-&zBt08Z|o> zcQTi!MINx_`XOx5?LetA^zZ$0`ZzG&cgOQ6^!wr{tKt#5Xi2_mTcL#vc!tSoTk|QJv z9dj2=urc1(#7hEnCz*n3{GV(tt_- z@yGX!T2FQ*2x(0}+m2ldo64Z4-E07M2A@f>T>CyUfU(cL`?0Foa~YlNJlkw$kGl&* z{=ah1EkLO1bBc|va~BxUA_zZt0n`0!`>m+H%_Kj#nIy`+0`Et#&%QmHy?Ic+<^i^5JbM?UCo-`g&K-OS4+K7@yL{H)`H9E z*eP-nJxYd5afr_BngRo1Py0FqEjTSp#tLTMLs50><=d5G*(_nR-Ezxr&a}Id5vFRy z!Do_Zc*3s+1zE|=IafS(aYQY4YnE)xG8uh3lK=-+)S@1TbURV+C%}l^*+9x!%br8P zAojp4N{lmEf{gVg8se=ZuHmIg8Q8kVY4`b@4Lu^znc1;-6c}U|yr(50Gw48(v{yyt zr*pB(e_QlEo#wd8DA>rKD_rr>s0mZb%gg&;dyAy>L6d&t5Pj0;NL`9B;d3?C9!e zp9ae7QyJ{u(H|S%-%<4Gn`c%n!P5~}@U!l>zyHQdMCMou<7OSxbdiDPUi$hhY;(=h zcszZu`>7i-67%&cLmyBryoBtipd^uMVVej8=Alk7O;)zpoXRqtPPZ`cw|W=uTnrKT z;7vqi9FFFbsV7gKBnB7|j>*H~NE0<*!7VN>e)7583!<4iQVNNy{gHZK zobgMO2G6m;MO?}#=9VYY@G=b)T!Yk0mo5;UxY$gJj zPlr587SvrJ#Saxh6fw3wJ_~Ch3wF_CW(Zf^puVfC>rMlM0n8^hU>H0D{lvjt59L1N zlNJWTY?xuG9|0GSQeSpMv0mONkRe0Rh>#5#p%}DDz$FG4UcH7WV%4#f7e6trkcMKA zc7UYqZXo~|3|Dx;mQ9W38qH^GLppxqp)~hsFEM@W9sDMnIV7zAz9bZbfLIaZvGJmB z#bZWL(Ce8iLooD{da?L+0Bg2ea@TS~ zCsx68#Roq+jK}&yI;)V{E8DFwm=gvJ=1cYOw}&?%;b|=_b2Tk%_wL<9vis-%yzfk^ zJdD6j)78B!>HfFgBj%I}1cpn6LIDeD_OA=7st=O6VaP7jvTt~>@byEJOJdOFF-TyI zjg1)@6V%Dg7QHEm3o!_DHDla&+qP}Q51JFz-=xOtY<{BJtnR=&FeVZhNWQN3ZNp&D zsG#YGx4MS&H)x<*xg%Wx)k$a==|ew-9hG0en1Yx9h8n9uKG5b*SOUW+u-!7RWeiGscwgGTLi`sE56$qn#6HVzLt9agt1YU+s{l)hSuNhuwD!`AHZ(eil&^72&tQ8tgK|FO5-?iUf->` zxlIr4Jz)^9_W#L7cD#c&`!9y%+wrFz*oAAarWlQW5w65_kGQs-_QzJjiU%ef(+$nB z=lnzk(pvqku=Y~|ibtTnGW>0;vaK +# +# 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. +# +# Created: 20-Jun-2012. + +require 5; +#use diagnostics; # Fails on some MacOS 10.5 - 10.7 systems +use strict; + +my $progname = $0; $progname =~ s@.*/@@g; +my $version = q{ $Revision: 1.2 $ }; $version =~ s/^[^\d]+([\d.]+).*/$1/; + +my $verbose = 0; + +sub sanity_check() { + + my $fail = ''; + my $d1 = $ENV{SDK_DIR} || ''; + my $d2 = '/usr/include/netinet/'; + foreach my $f ('ip.h', 'in_systm.h', 'ip_icmp.h', 'ip_var.h', 'udp.h') { + $fail .= "\tsudo ln -s $d2$f $d1$d2\n" + unless (-f "$d1$d2$f"); + } + + exit (0) unless $fail; + + print STDERR "ERROR:\t" . join(' ', # "\n\t", + 'The "Sonar" module won\'t build properly unless you repair your', + 'SDK first. With some versions of Xcode, the ICMP header files', + 'are present in the iPhone Simulator SDK but are missing from', + 'the "real device" SDK. You can fix it by doing this:') . + "\n\n$fail\n"; + exit (1); +} + +if ($#ARGV >= 0) { + print STDERR "usage: $progname\n"; + exit 1; +} + +sanity_check(); diff --git a/OSX/ios_function_tables.h b/OSX/ios_function_tables.h new file mode 100644 index 00000000..58545876 --- /dev/null +++ b/OSX/ios_function_tables.h @@ -0,0 +1,396 @@ +extern struct xscreensaver_function_table + *abstractile_xscreensaver_function_table, + *anemone_xscreensaver_function_table, + *anemotaxis_xscreensaver_function_table, + *antinspect_xscreensaver_function_table, + *antmaze_xscreensaver_function_table, + *antspotlight_xscreensaver_function_table, + *apollonian_xscreensaver_function_table, + *apple2_xscreensaver_function_table, + *atlantis_xscreensaver_function_table, + *attraction_xscreensaver_function_table, + *atunnel_xscreensaver_function_table, + *barcode_xscreensaver_function_table, + *blaster_xscreensaver_function_table, + *blinkbox_xscreensaver_function_table, + *blitspin_xscreensaver_function_table, + *blocktube_xscreensaver_function_table, + *boing_xscreensaver_function_table, + *bouboule_xscreensaver_function_table, + *bouncingcow_xscreensaver_function_table, + *boxed_xscreensaver_function_table, + *boxfit_xscreensaver_function_table, + *braid_xscreensaver_function_table, + *bsod_xscreensaver_function_table, + *bubble3d_xscreensaver_function_table, + *bumps_xscreensaver_function_table, + *cage_xscreensaver_function_table, + *carousel_xscreensaver_function_table, + *ccurve_xscreensaver_function_table, + *celtic_xscreensaver_function_table, + *circuit_xscreensaver_function_table, + *cloudlife_xscreensaver_function_table, + *companioncube_xscreensaver_function_table, + *compass_xscreensaver_function_table, + *coral_xscreensaver_function_table, + *crackberg_xscreensaver_function_table, + *crystal_xscreensaver_function_table, + *cube21_xscreensaver_function_table, + *cubenetic_xscreensaver_function_table, + *cubestorm_xscreensaver_function_table, + *cubicgrid_xscreensaver_function_table, + *cwaves_xscreensaver_function_table, + *cynosure_xscreensaver_function_table, + *dangerball_xscreensaver_function_table, + *decayscreen_xscreensaver_function_table, + *deco_xscreensaver_function_table, + *deluxe_xscreensaver_function_table, + *demon_xscreensaver_function_table, + *discrete_xscreensaver_function_table, + *distort_xscreensaver_function_table, + *dnalogo_xscreensaver_function_table, + *drift_xscreensaver_function_table, + *endgame_xscreensaver_function_table, + *engine_xscreensaver_function_table, + *epicycle_xscreensaver_function_table, + *eruption_xscreensaver_function_table, + *euler2d_xscreensaver_function_table, + *fadeplot_xscreensaver_function_table, + *fiberlamp_xscreensaver_function_table, + *fireworkx_xscreensaver_function_table, + *flame_xscreensaver_function_table, + *flipflop_xscreensaver_function_table, + *flipscreen3d_xscreensaver_function_table, + *fliptext_xscreensaver_function_table, + *flow_xscreensaver_function_table, + *fluidballs_xscreensaver_function_table, + *flyingtoasters_xscreensaver_function_table, + *fontglide_xscreensaver_function_table, + *fuzzyflakes_xscreensaver_function_table, + *galaxy_xscreensaver_function_table, + *gears_xscreensaver_function_table, + *gflux_xscreensaver_function_table, + *glblur_xscreensaver_function_table, + *glcells_xscreensaver_function_table, + *gleidescope_xscreensaver_function_table, + *glhanoi_xscreensaver_function_table, + *glknots_xscreensaver_function_table, + *glmatrix_xscreensaver_function_table, + *glplanet_xscreensaver_function_table, + *glschool_xscreensaver_function_table, + *glslideshow_xscreensaver_function_table, + *glsnake_xscreensaver_function_table, + *gltext_xscreensaver_function_table, + *goop_xscreensaver_function_table, + *grav_xscreensaver_function_table, + *greynetic_xscreensaver_function_table, + *halftone_xscreensaver_function_table, + *halo_xscreensaver_function_table, + *helix_xscreensaver_function_table, + *hilbert_xscreensaver_function_table, + *hopalong_xscreensaver_function_table, + *hypertorus_xscreensaver_function_table, + *hypnowheel_xscreensaver_function_table, + *ifs_xscreensaver_function_table, + *imsmap_xscreensaver_function_table, + *interaggregate_xscreensaver_function_table, + *interference_xscreensaver_function_table, + *intermomentary_xscreensaver_function_table, + *jigglypuff_xscreensaver_function_table, + *jigsaw_xscreensaver_function_table, + *juggler3d_xscreensaver_function_table, + *julia_xscreensaver_function_table, + *kaleidescope_xscreensaver_function_table, + *klein_xscreensaver_function_table, + *kumppa_xscreensaver_function_table, + *lament_xscreensaver_function_table, + *lavalite_xscreensaver_function_table, + *loop_xscreensaver_function_table, + *m6502_xscreensaver_function_table, + *maze_xscreensaver_function_table, + *memscroller_xscreensaver_function_table, + *menger_xscreensaver_function_table, + *metaballs_xscreensaver_function_table, + *mirrorblob_xscreensaver_function_table, + *moebius_xscreensaver_function_table, + *moebiusgears_xscreensaver_function_table, + *moire_xscreensaver_function_table, + *moire2_xscreensaver_function_table, + *molecule_xscreensaver_function_table, + *morph3d_xscreensaver_function_table, + *mountain_xscreensaver_function_table, + *munch_xscreensaver_function_table, + *nerverot_xscreensaver_function_table, + *noof_xscreensaver_function_table, + *noseguy_xscreensaver_function_table, + *pacman_xscreensaver_function_table, + *pedal_xscreensaver_function_table, + *penetrate_xscreensaver_function_table, + *penrose_xscreensaver_function_table, + *petri_xscreensaver_function_table, + *phosphor_xscreensaver_function_table, + *photopile_xscreensaver_function_table, + *piecewise_xscreensaver_function_table, + *pinion_xscreensaver_function_table, + *pipes_xscreensaver_function_table, + *polyhedra_xscreensaver_function_table, + *polyominoes_xscreensaver_function_table, + *polytopes_xscreensaver_function_table, + *pong_xscreensaver_function_table, + *popsquares_xscreensaver_function_table, + *providence_xscreensaver_function_table, + *pulsar_xscreensaver_function_table, + *pyro_xscreensaver_function_table, + *qix_xscreensaver_function_table, + *queens_xscreensaver_function_table, + *rdbomb_xscreensaver_function_table, + *ripples_xscreensaver_function_table, + *rocks_xscreensaver_function_table, + *rorschach_xscreensaver_function_table, + *rotzoomer_xscreensaver_function_table, + *rubik_xscreensaver_function_table, + *rubikblocks_xscreensaver_function_table, + *sballs_xscreensaver_function_table, + *shadebobs_xscreensaver_function_table, + *sierpinski_xscreensaver_function_table, + *sierpinski3d_xscreensaver_function_table, + *skytentacles_xscreensaver_function_table, + *slidescreen_xscreensaver_function_table, + *slip_xscreensaver_function_table, + *sonar_xscreensaver_function_table, + *speedmine_xscreensaver_function_table, + *spheremonics_xscreensaver_function_table, + *spotlight_xscreensaver_function_table, + *sproingies_xscreensaver_function_table, + *squiral_xscreensaver_function_table, + *stairs_xscreensaver_function_table, + *starfish_xscreensaver_function_table, + *starwars_xscreensaver_function_table, + *stonerview_xscreensaver_function_table, + *strange_xscreensaver_function_table, + *substrate_xscreensaver_function_table, + *superquadrics_xscreensaver_function_table, + *surfaces_xscreensaver_function_table, + *swirl_xscreensaver_function_table, + *tangram_xscreensaver_function_table, + *thornbird_xscreensaver_function_table, + *timetunnel_xscreensaver_function_table, + *topblock_xscreensaver_function_table, + *triangle_xscreensaver_function_table, + *tronbit_xscreensaver_function_table, + *truchet_xscreensaver_function_table, + *twang_xscreensaver_function_table, + *vermiculate_xscreensaver_function_table, + *voronoi_xscreensaver_function_table, + *wander_xscreensaver_function_table, + *whirlwindwarp_xscreensaver_function_table, + *wormhole_xscreensaver_function_table, + *xanalogtv_xscreensaver_function_table, + *xflame_xscreensaver_function_table, + *xjack_xscreensaver_function_table, + *xlyap_xscreensaver_function_table, + *xmatrix_xscreensaver_function_table, + *xrayswarm_xscreensaver_function_table, + *xspirograph_xscreensaver_function_table, + *zoom_xscreensaver_function_table; + +static NSDictionary *make_function_tables_dict(void) +{ + return + [NSDictionary dictionaryWithObjectsAndKeys: + [NSValue valueWithPointer:&abstractile_xscreensaver_function_table], @"abstractile", + [NSValue valueWithPointer:&anemone_xscreensaver_function_table], @"anemone", + [NSValue valueWithPointer:&anemotaxis_xscreensaver_function_table], @"anemotaxis", + [NSValue valueWithPointer:&antinspect_xscreensaver_function_table], @"antinspect", + [NSValue valueWithPointer:&antmaze_xscreensaver_function_table], @"antmaze", + [NSValue valueWithPointer:&antspotlight_xscreensaver_function_table], @"antspotlight", + [NSValue valueWithPointer:&apollonian_xscreensaver_function_table], @"apollonian", + [NSValue valueWithPointer:&apple2_xscreensaver_function_table], @"apple2", + [NSValue valueWithPointer:&atlantis_xscreensaver_function_table], @"atlantis", + [NSValue valueWithPointer:&attraction_xscreensaver_function_table], @"attraction", + [NSValue valueWithPointer:&atunnel_xscreensaver_function_table], @"atunnel", + [NSValue valueWithPointer:&barcode_xscreensaver_function_table], @"barcode", + [NSValue valueWithPointer:&blaster_xscreensaver_function_table], @"blaster", + [NSValue valueWithPointer:&blinkbox_xscreensaver_function_table], @"blinkbox", + [NSValue valueWithPointer:&blitspin_xscreensaver_function_table], @"blitspin", + [NSValue valueWithPointer:&blocktube_xscreensaver_function_table], @"blocktube", + [NSValue valueWithPointer:&boing_xscreensaver_function_table], @"boing", + [NSValue valueWithPointer:&bouboule_xscreensaver_function_table], @"bouboule", + [NSValue valueWithPointer:&bouncingcow_xscreensaver_function_table], @"bouncingcow", + [NSValue valueWithPointer:&boxed_xscreensaver_function_table], @"boxed", + [NSValue valueWithPointer:&boxfit_xscreensaver_function_table], @"boxfit", + [NSValue valueWithPointer:&braid_xscreensaver_function_table], @"braid", + [NSValue valueWithPointer:&bsod_xscreensaver_function_table], @"bsod", + [NSValue valueWithPointer:&bubble3d_xscreensaver_function_table], @"bubble3d", + [NSValue valueWithPointer:&bumps_xscreensaver_function_table], @"bumps", + [NSValue valueWithPointer:&cage_xscreensaver_function_table], @"cage", + [NSValue valueWithPointer:&carousel_xscreensaver_function_table], @"carousel", + [NSValue valueWithPointer:&ccurve_xscreensaver_function_table], @"ccurve", + [NSValue valueWithPointer:&celtic_xscreensaver_function_table], @"celtic", + [NSValue valueWithPointer:&circuit_xscreensaver_function_table], @"circuit", + [NSValue valueWithPointer:&cloudlife_xscreensaver_function_table], @"cloudlife", + [NSValue valueWithPointer:&companioncube_xscreensaver_function_table], @"companioncube", + [NSValue valueWithPointer:&compass_xscreensaver_function_table], @"compass", + [NSValue valueWithPointer:&coral_xscreensaver_function_table], @"coral", + [NSValue valueWithPointer:&crackberg_xscreensaver_function_table], @"crackberg", + [NSValue valueWithPointer:&crystal_xscreensaver_function_table], @"crystal", + [NSValue valueWithPointer:&cube21_xscreensaver_function_table], @"cube21", + [NSValue valueWithPointer:&cubenetic_xscreensaver_function_table], @"cubenetic", + [NSValue valueWithPointer:&cubestorm_xscreensaver_function_table], @"cubestorm", + [NSValue valueWithPointer:&cubicgrid_xscreensaver_function_table], @"cubicgrid", + [NSValue valueWithPointer:&cwaves_xscreensaver_function_table], @"cwaves", + [NSValue valueWithPointer:&cynosure_xscreensaver_function_table], @"cynosure", + [NSValue valueWithPointer:&dangerball_xscreensaver_function_table], @"dangerball", + [NSValue valueWithPointer:&decayscreen_xscreensaver_function_table], @"decayscreen", + [NSValue valueWithPointer:&deco_xscreensaver_function_table], @"deco", + [NSValue valueWithPointer:&deluxe_xscreensaver_function_table], @"deluxe", + [NSValue valueWithPointer:&demon_xscreensaver_function_table], @"demon", + [NSValue valueWithPointer:&discrete_xscreensaver_function_table], @"discrete", + [NSValue valueWithPointer:&distort_xscreensaver_function_table], @"distort", + [NSValue valueWithPointer:&dnalogo_xscreensaver_function_table], @"dnalogo", + [NSValue valueWithPointer:&drift_xscreensaver_function_table], @"drift", + [NSValue valueWithPointer:&endgame_xscreensaver_function_table], @"endgame", + [NSValue valueWithPointer:&engine_xscreensaver_function_table], @"engine", + [NSValue valueWithPointer:&epicycle_xscreensaver_function_table], @"epicycle", + [NSValue valueWithPointer:&eruption_xscreensaver_function_table], @"eruption", + [NSValue valueWithPointer:&euler2d_xscreensaver_function_table], @"euler2d", + [NSValue valueWithPointer:&fadeplot_xscreensaver_function_table], @"fadeplot", + [NSValue valueWithPointer:&fiberlamp_xscreensaver_function_table], @"fiberlamp", + [NSValue valueWithPointer:&fireworkx_xscreensaver_function_table], @"fireworkx", + [NSValue valueWithPointer:&flame_xscreensaver_function_table], @"flame", + [NSValue valueWithPointer:&flipflop_xscreensaver_function_table], @"flipflop", + [NSValue valueWithPointer:&flipscreen3d_xscreensaver_function_table], @"flipscreen3d", + [NSValue valueWithPointer:&fliptext_xscreensaver_function_table], @"fliptext", + [NSValue valueWithPointer:&flow_xscreensaver_function_table], @"flow", + [NSValue valueWithPointer:&fluidballs_xscreensaver_function_table], @"fluidballs", + [NSValue valueWithPointer:&flyingtoasters_xscreensaver_function_table], @"flyingtoasters", + [NSValue valueWithPointer:&fontglide_xscreensaver_function_table], @"fontglide", + [NSValue valueWithPointer:&fuzzyflakes_xscreensaver_function_table], @"fuzzyflakes", + [NSValue valueWithPointer:&galaxy_xscreensaver_function_table], @"galaxy", + [NSValue valueWithPointer:&gears_xscreensaver_function_table], @"gears", + [NSValue valueWithPointer:&gflux_xscreensaver_function_table], @"gflux", + [NSValue valueWithPointer:&glblur_xscreensaver_function_table], @"glblur", + [NSValue valueWithPointer:&glcells_xscreensaver_function_table], @"glcells", + [NSValue valueWithPointer:&gleidescope_xscreensaver_function_table], @"gleidescope", + [NSValue valueWithPointer:&glhanoi_xscreensaver_function_table], @"glhanoi", + [NSValue valueWithPointer:&glknots_xscreensaver_function_table], @"glknots", + [NSValue valueWithPointer:&glmatrix_xscreensaver_function_table], @"glmatrix", + [NSValue valueWithPointer:&glplanet_xscreensaver_function_table], @"glplanet", + [NSValue valueWithPointer:&glschool_xscreensaver_function_table], @"glschool", + [NSValue valueWithPointer:&glslideshow_xscreensaver_function_table], @"glslideshow", + [NSValue valueWithPointer:&glsnake_xscreensaver_function_table], @"glsnake", + [NSValue valueWithPointer:&gltext_xscreensaver_function_table], @"gltext", + [NSValue valueWithPointer:&goop_xscreensaver_function_table], @"goop", + [NSValue valueWithPointer:&grav_xscreensaver_function_table], @"grav", + [NSValue valueWithPointer:&greynetic_xscreensaver_function_table], @"greynetic", + [NSValue valueWithPointer:&halftone_xscreensaver_function_table], @"halftone", + [NSValue valueWithPointer:&halo_xscreensaver_function_table], @"halo", + [NSValue valueWithPointer:&helix_xscreensaver_function_table], @"helix", + [NSValue valueWithPointer:&hilbert_xscreensaver_function_table], @"hilbert", + [NSValue valueWithPointer:&hopalong_xscreensaver_function_table], @"hopalong", + [NSValue valueWithPointer:&hypertorus_xscreensaver_function_table], @"hypertorus", + [NSValue valueWithPointer:&hypnowheel_xscreensaver_function_table], @"hypnowheel", + [NSValue valueWithPointer:&ifs_xscreensaver_function_table], @"ifs", + [NSValue valueWithPointer:&imsmap_xscreensaver_function_table], @"imsmap", + [NSValue valueWithPointer:&interaggregate_xscreensaver_function_table], @"interaggregate", + [NSValue valueWithPointer:&interference_xscreensaver_function_table], @"interference", + [NSValue valueWithPointer:&intermomentary_xscreensaver_function_table], @"intermomentary", + [NSValue valueWithPointer:&jigglypuff_xscreensaver_function_table], @"jigglypuff", + [NSValue valueWithPointer:&jigsaw_xscreensaver_function_table], @"jigsaw", + [NSValue valueWithPointer:&juggler3d_xscreensaver_function_table], @"juggler3d", + [NSValue valueWithPointer:&julia_xscreensaver_function_table], @"julia", + [NSValue valueWithPointer:&kaleidescope_xscreensaver_function_table], @"kaleidescope", + [NSValue valueWithPointer:&klein_xscreensaver_function_table], @"klein", + [NSValue valueWithPointer:&kumppa_xscreensaver_function_table], @"kumppa", + [NSValue valueWithPointer:&lament_xscreensaver_function_table], @"lament", + [NSValue valueWithPointer:&lavalite_xscreensaver_function_table], @"lavalite", + [NSValue valueWithPointer:&loop_xscreensaver_function_table], @"loop", + [NSValue valueWithPointer:&m6502_xscreensaver_function_table], @"m6502", + [NSValue valueWithPointer:&maze_xscreensaver_function_table], @"maze", + [NSValue valueWithPointer:&memscroller_xscreensaver_function_table], @"memscroller", + [NSValue valueWithPointer:&menger_xscreensaver_function_table], @"menger", + [NSValue valueWithPointer:&metaballs_xscreensaver_function_table], @"metaballs", + [NSValue valueWithPointer:&mirrorblob_xscreensaver_function_table], @"mirrorblob", + [NSValue valueWithPointer:&moebius_xscreensaver_function_table], @"moebius", + [NSValue valueWithPointer:&moebiusgears_xscreensaver_function_table], @"moebiusgears", + [NSValue valueWithPointer:&moire_xscreensaver_function_table], @"moire", + [NSValue valueWithPointer:&moire2_xscreensaver_function_table], @"moire2", + [NSValue valueWithPointer:&molecule_xscreensaver_function_table], @"molecule", + [NSValue valueWithPointer:&morph3d_xscreensaver_function_table], @"morph3d", + [NSValue valueWithPointer:&mountain_xscreensaver_function_table], @"mountain", + [NSValue valueWithPointer:&munch_xscreensaver_function_table], @"munch", + [NSValue valueWithPointer:&nerverot_xscreensaver_function_table], @"nerverot", + [NSValue valueWithPointer:&noof_xscreensaver_function_table], @"noof", + [NSValue valueWithPointer:&noseguy_xscreensaver_function_table], @"noseguy", + [NSValue valueWithPointer:&pacman_xscreensaver_function_table], @"pacman", + [NSValue valueWithPointer:&pedal_xscreensaver_function_table], @"pedal", + [NSValue valueWithPointer:&penetrate_xscreensaver_function_table], @"penetrate", + [NSValue valueWithPointer:&penrose_xscreensaver_function_table], @"penrose", + [NSValue valueWithPointer:&petri_xscreensaver_function_table], @"petri", + [NSValue valueWithPointer:&phosphor_xscreensaver_function_table], @"phosphor", + [NSValue valueWithPointer:&photopile_xscreensaver_function_table], @"photopile", + [NSValue valueWithPointer:&piecewise_xscreensaver_function_table], @"piecewise", + [NSValue valueWithPointer:&pinion_xscreensaver_function_table], @"pinion", + [NSValue valueWithPointer:&pipes_xscreensaver_function_table], @"pipes", + [NSValue valueWithPointer:&polyhedra_xscreensaver_function_table], @"polyhedra", + [NSValue valueWithPointer:&polyominoes_xscreensaver_function_table], @"polyominoes", + [NSValue valueWithPointer:&polytopes_xscreensaver_function_table], @"polytopes", + [NSValue valueWithPointer:&pong_xscreensaver_function_table], @"pong", + [NSValue valueWithPointer:&popsquares_xscreensaver_function_table], @"popsquares", + [NSValue valueWithPointer:&providence_xscreensaver_function_table], @"providence", + [NSValue valueWithPointer:&pulsar_xscreensaver_function_table], @"pulsar", + [NSValue valueWithPointer:&pyro_xscreensaver_function_table], @"pyro", + [NSValue valueWithPointer:&qix_xscreensaver_function_table], @"qix", + [NSValue valueWithPointer:&queens_xscreensaver_function_table], @"queens", + [NSValue valueWithPointer:&rdbomb_xscreensaver_function_table], @"rdbomb", + [NSValue valueWithPointer:&ripples_xscreensaver_function_table], @"ripples", + [NSValue valueWithPointer:&rocks_xscreensaver_function_table], @"rocks", + [NSValue valueWithPointer:&rorschach_xscreensaver_function_table], @"rorschach", + [NSValue valueWithPointer:&rotzoomer_xscreensaver_function_table], @"rotzoomer", + [NSValue valueWithPointer:&rubik_xscreensaver_function_table], @"rubik", + [NSValue valueWithPointer:&rubikblocks_xscreensaver_function_table], @"rubikblocks", + [NSValue valueWithPointer:&sballs_xscreensaver_function_table], @"sballs", + [NSValue valueWithPointer:&shadebobs_xscreensaver_function_table], @"shadebobs", + [NSValue valueWithPointer:&sierpinski_xscreensaver_function_table], @"sierpinski", + [NSValue valueWithPointer:&sierpinski3d_xscreensaver_function_table], @"sierpinski3d", + [NSValue valueWithPointer:&skytentacles_xscreensaver_function_table], @"skytentacles", + [NSValue valueWithPointer:&slidescreen_xscreensaver_function_table], @"slidescreen", + [NSValue valueWithPointer:&slip_xscreensaver_function_table], @"slip", + [NSValue valueWithPointer:&sonar_xscreensaver_function_table], @"sonar", + [NSValue valueWithPointer:&speedmine_xscreensaver_function_table], @"speedmine", + [NSValue valueWithPointer:&spheremonics_xscreensaver_function_table], @"spheremonics", + [NSValue valueWithPointer:&spotlight_xscreensaver_function_table], @"spotlight", + [NSValue valueWithPointer:&sproingies_xscreensaver_function_table], @"sproingies", + [NSValue valueWithPointer:&squiral_xscreensaver_function_table], @"squiral", + [NSValue valueWithPointer:&stairs_xscreensaver_function_table], @"stairs", + [NSValue valueWithPointer:&starfish_xscreensaver_function_table], @"starfish", + [NSValue valueWithPointer:&starwars_xscreensaver_function_table], @"starwars", + [NSValue valueWithPointer:&stonerview_xscreensaver_function_table], @"stonerview", + [NSValue valueWithPointer:&strange_xscreensaver_function_table], @"strange", + [NSValue valueWithPointer:&substrate_xscreensaver_function_table], @"substrate", + [NSValue valueWithPointer:&superquadrics_xscreensaver_function_table], @"superquadrics", + [NSValue valueWithPointer:&surfaces_xscreensaver_function_table], @"surfaces", + [NSValue valueWithPointer:&swirl_xscreensaver_function_table], @"swirl", + [NSValue valueWithPointer:&tangram_xscreensaver_function_table], @"tangram", + [NSValue valueWithPointer:þbird_xscreensaver_function_table], @"thornbird", + [NSValue valueWithPointer:&timetunnel_xscreensaver_function_table], @"timetunnel", + [NSValue valueWithPointer:&topblock_xscreensaver_function_table], @"topblock", + [NSValue valueWithPointer:&triangle_xscreensaver_function_table], @"triangle", + [NSValue valueWithPointer:&tronbit_xscreensaver_function_table], @"tronbit", + [NSValue valueWithPointer:&truchet_xscreensaver_function_table], @"truchet", + [NSValue valueWithPointer:&twang_xscreensaver_function_table], @"twang", + [NSValue valueWithPointer:&vermiculate_xscreensaver_function_table], @"vermiculate", + [NSValue valueWithPointer:&voronoi_xscreensaver_function_table], @"voronoi", + [NSValue valueWithPointer:&wander_xscreensaver_function_table], @"wander", + [NSValue valueWithPointer:&whirlwindwarp_xscreensaver_function_table], @"whirlwindwarp", + [NSValue valueWithPointer:&wormhole_xscreensaver_function_table], @"wormhole", + [NSValue valueWithPointer:&xanalogtv_xscreensaver_function_table], @"xanalogtv", + [NSValue valueWithPointer:&xflame_xscreensaver_function_table], @"xflame", + [NSValue valueWithPointer:&xjack_xscreensaver_function_table], @"xjack", + [NSValue valueWithPointer:&xlyap_xscreensaver_function_table], @"xlyap", + [NSValue valueWithPointer:&xmatrix_xscreensaver_function_table], @"xmatrix", + [NSValue valueWithPointer:&xrayswarm_xscreensaver_function_table], @"xrayswarm", + [NSValue valueWithPointer:&xspirograph_xscreensaver_function_table], @"xspirograph", + [NSValue valueWithPointer:&zoom_xscreensaver_function_table], @"zoom", + nil]; +} diff --git a/OSX/iosgrabimage.m b/OSX/iosgrabimage.m new file mode 100644 index 00000000..faf23480 --- /dev/null +++ b/OSX/iosgrabimage.m @@ -0,0 +1,125 @@ +/* xscreensaver, Copyright (c) 1992-2012 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. + */ + +/* This iOS code to choose and return a random image from the user's + * photo gallery. + * + * Much of the following written by: + * + * Created by David Oster on 6/23/12. + * Copyright (c) 2012 Google. All rights reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifdef USE_IPHONE // whole file + +#import +#import "grabscreen.h" +#import "yarandom.h" + +/* ALAssetsLibrary is an async API, so we need to fire it off and then + call a callback when it's done. Fortunately, this fits the same + interaction model already used in xscreensaver by load_image_async(), + so it works out nicely. + */ + +typedef struct { + void (*callback) (void *uiimage, const char *fn, void *closure); + void *closure; + + ALAssetsLibrary *library; + NSMutableArray *assets; + +} ios_loader_data; + + +static void +ios_random_image_done (ios_loader_data *d, BOOL ok) +{ + UIImage *img = 0; + const char *fn = 0; + int n = ok ? [d->assets count] : 0; + if (n > 0) { + ALAsset *asset = [d->assets objectAtIndex: random() % n]; + ALAssetRepresentation *rep = [asset defaultRepresentation]; + + // "fullScreenImage" returns a smaller image than "fullResolutionImage", + // but this function still takes a significant fraction of a second, + // causing a visible glitch in e.g. "glslideshow". + CGImageRef cgi = [rep fullScreenImage]; + if (cgi) { + UIImageOrientation orient = (UIImageOrientation) + [[asset valueForProperty:ALAssetPropertyOrientation] intValue]; + img = [UIImage imageWithCGImage: cgi + scale: 1 + orientation: orient]; + if (img) + fn = [[rep filename] cStringUsingEncoding:NSISOLatin1StringEncoding]; + } + } + + [d->assets release]; + [d->library release]; + + d->callback (img, fn, d->closure); + free (d); +} + + +void +ios_load_random_image (void (*callback) (void *uiimage, const char *fn, + void *closure), + void *closure) +{ + ios_loader_data *d = (ios_loader_data *) calloc (1, sizeof(*d)); + d->callback = callback; + d->closure = closure; + + d->library = [[[ALAssetsLibrary alloc] init] retain]; + d->assets = [[NSMutableArray array] retain]; + + // The closures passed in here are called later, after we have returned. + // + [d->library enumerateGroupsWithTypes: ALAssetsGroupAll + usingBlock: ^(ALAssetsGroup *group, BOOL *stop) { + NSString *name = [group valueForProperty:ALAssetsGroupPropertyName]; + if ([name length]) { + [group enumerateAssetsUsingBlock: ^(ALAsset *asset, NSUInteger index, + BOOL *stop) { + if ([[asset valueForProperty: ALAssetPropertyType] + isEqual: ALAssetTypePhoto]) { + [d->assets addObject:asset]; + } + }]; + } + + if (! group) { // done + ios_random_image_done (d, YES); + } + } failureBlock:^(NSError *error) { + // E.g., ALAssetsLibraryErrorDomain: "The user has denied the + // application access to their media." + NSLog(@"reading Photo Library: %@", error); + ios_random_image_done (d, NO); + }]; +} + +#endif // USE_IPHONE - whole file diff --git a/OSX/iostextclient.m b/OSX/iostextclient.m new file mode 100644 index 00000000..09c62985 --- /dev/null +++ b/OSX/iostextclient.m @@ -0,0 +1,575 @@ +/* xscreensaver, Copyright (c) 2012 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. + * + * Loading URLs and returning the underlying text. + * + * This is necessary because iOS doesn't have Perl installed, so we can't + * run "xscreensaver-text" to do this. + */ + +#include "utils.h" + +#ifdef USE_IPHONE /* whole file -- see utils/textclient.c */ + +#include "textclient.h" +#include "resources.h" + +#include + +extern const char *progname; + +struct text_data { + + enum { DATE, LITERAL, URL } mode; + char *literal, *url; + + int columns; + char *buf; + int buf_size; + char *fp; + +}; + + +text_data * +textclient_open (Display *dpy) +{ + text_data *d = (text_data *) calloc (1, sizeof (*d)); + +# ifdef DEBUG + fprintf (stderr, "%s: textclient: init\n", progname); +# endif + + char *s = get_string_resource (dpy, "textMode", "TextMode"); + if (!s || !*s || !strcasecmp (s, "date") || !strcmp (s, "0")) + d->mode = DATE; + else if (!strcasecmp (s, "literal") || !strcmp (s, "1")) + d->mode = LITERAL; + else if (!strcasecmp (s, "url") || !strcmp (s, "3")) + d->mode = URL; + else + d->mode = DATE; + + d->literal = get_string_resource (dpy, "textLiteral", "TextLiteral"); + d->url = get_string_resource (dpy, "textURL", "TextURL"); + + return d; +} + + +void +textclient_close (text_data *d) +{ +# ifdef DEBUG + fprintf (stderr, "%s: textclient: free\n", progname); +# endif + + if (d->buf) free (d->buf); + if (d->literal) free (d->literal); + if (d->url) free (d->url); + free (d); +} + + +static char * +date_string (void) +{ + UIDevice *dd = [UIDevice currentDevice]; + NSString *name = [dd name]; // My iPhone + NSString *model = [dd model]; // iPad + // NSString *system = [dd systemName]; // iPhone OS + NSString *vers = [dd systemVersion]; // 5.0 + NSString *date = + [NSDateFormatter + localizedStringFromDate:[NSDate date] + dateStyle: NSDateFormatterMediumStyle + timeStyle: NSDateFormatterMediumStyle]; + NSString *nl = @"\n"; + + NSString *result = name; + result = [result stringByAppendingString: nl]; + result = [result stringByAppendingString: model]; + // result = [result stringByAppendingString: nl]; + // result = [result stringByAppendingString: system]; + result = [result stringByAppendingString: @" "]; + result = [result stringByAppendingString: vers]; + result = [result stringByAppendingString: nl]; + result = [result stringByAppendingString: nl]; + result = [result stringByAppendingString: date]; + result = [result stringByAppendingString: nl]; + result = [result stringByAppendingString: nl]; + return strdup ([result cStringUsingEncoding:NSISOLatin1StringEncoding]); +} + + +static void +strip_html (char *html) +{ + int tag = 0; + int comment = 0; + int white = 0; + int nl = 0; + int entity = 0; + char *out = html; + for (char *in = html; *in; in++) { + if (comment) { + if (!strncmp (in, "-->", 3)) { + comment = 0; + } + } else if (tag) { + if (*in == '>') { + tag = 0; + entity = 0; + } + } else if (entity) { + if (*in == ';') { + entity = 0; + } + } else if (*in == '<') { + tag = 1; + entity = 0; + if (!strncmp (in, "@@gs; + $desc =~ s/^.* version \d[^\n]*\n//s; + $desc =~ s/^From the XScreenSaver.*\n//m; + $desc =~ s@^http://www\.jwz\.org/xscreensaver.*\n@@m; + $desc =~ + s/\nCopyright [^ \r\n\t]+ (\d{4})(-\d{4})? (.*)\.$/\nWritten $3; $1./s; + $desc =~ s/^\n+//s; + + error ("$filename: description contains bad characters") + if ($desc =~ m/([^\t\n -~]|[<>])/); + + error ("$filename: can't extract authors") + unless ($desc =~ m@^(.*)\nWritten by[ \t]+(.+)$@s); + $desc = $1; + my $authors = $2; + $desc =~ s/\s*$//s; + + my $year = undef; + if ($authors =~ m@^(.*?)\s*[,;]\s+(\d\d\d\d)([-\s,;]+\d\d\d\d)*[.]?$@s) { + $authors = $1; + $year = $2; + } + + error ("$filename: can't extract year") unless $year; + my $cyear = 1900 + ((localtime())[5]); + $year = "$cyear" unless $year; + if ($year && ! ($year =~ m/$cyear/)) { + $year = "$year-$cyear"; + } + + $authors =~ s/[.,;\s]+$//s; + + # List me as a co-author on all of them, since I'm the one who + # did the OSX port, packaged it up, and built the executables. + # + my $curator = "Jamie Zawinski"; + if (! ($authors =~ m/$curator/si)) { + if ($authors =~ m@^(.*?),? and (.*)$@s) { + $authors = "$1, $2, and $curator"; + } else { + $authors .= " and $curator"; + } + } + + my $desc1 = ("$name, version $vers.\n\n" . # savername.xml + $desc . "\n" . + "\n" . + "From the XScreenSaver collection: " . + "http://www.jwz.org/xscreensaver/\n" . + "Copyright \251 $year by $authors.\n"); + + my $desc2 = ("$name $vers,\n" . # Info.plist + "\302\251 $year $authors.\n" . + "From the XScreenSaver collection:\n" . + "http://www.jwz.org/xscreensaver/\n" . + "\n" . + $desc . + "\n"); + + # unwrap lines, but only when it's obviously ok: leave blank lines, + # and don't unwrap if that would compress leading whitespace on a line. + # + $desc2 =~ s/^(From |http:)/\n$1/gm; + 1 while ($desc2 =~ s/([^\s])[ \t]*\n([^\s])/$1 $2/gs); + $desc2 =~ s/\n\n(From |http:)/\n$1/gs; + + $body =~ s@(<_description>)(.*?)()@$1$desc1$3@s; + + if ($obody eq $body) { + print STDERR "$progname: $filename: unchanged\n" if ($verbose > 1); + } else { + my $file_tmp = "$filename.tmp"; + open (my $out, '>', $file_tmp) || error ("$file_tmp: $!"); + print $out $body || error ("$file_tmp: $!"); + close $out || error ("$file_tmp: $!"); + + if (!rename ("$file_tmp", "$filename")) { + unlink "$file_tmp"; + error ("mv \"$file_tmp\" \"$filename\": $!"); + } + print STDERR "$progname: wrote $filename\n" if ($verbose); + } + + return ($desc1, $desc2); +} + + + +sub set_plist_key($$$$) { + my ($filename, $body, $key, $val) = @_; + + if ($body =~ m@^(.* + \n\t$key + \n\t)([^<>]*)( + .*)$@xs) { +# print STDERR "$progname: $filename: $key was: $2\n" if ($verbose); + $body = $1 . $val . $3; + } else { + error ("$filename: unparsable") + unless ($body =~ m@^(.*)(\n\n\n)$@s); + $body = ($1 . + "\n\t$key" . + "\n\t$val" . + $2); + } + + return $body; +} + + +sub set_icon($) { + my ($app_dir) = @_; + $app_dir =~ s@/+$@@s; + + # "seticon" is from osxutils, http://osxutils.sourceforge.net/ + + my $icon = ($app_dir =~ m/\.saver$/ ? 'XScreenSaver' : 'SaverRunner'); + $icon = "$app_dir/../../../$icon.icns"; + my @cmd = ("seticon", "-d", $icon, $app_dir); + print STDERR "$progname: exec: " . join(' ', @cmd) . "\n" + if ($verbose > 1); + system (@cmd); +} + + +sub update($) { + my ($app_dir) = @_; + + error ("$app_dir: no name") + unless ($app_dir =~ m@/([^/.]+).(app|saver)/?$@x); + my $app_name = $1; + + my ($filename, $plist) = read_info_plist ($app_dir); + my $oplist = $plist; + + error ("$filename: no version number") + unless ($plist =~ m@CFBundleShortVersionString\s* + ([^<>]+)@sx); + my $vers = $1; + my ($ignore, $info_str) = update_saver_xml ($app_dir, $vers); + + if (! defined($info_str)) { + print STDERR "$progname: $filename: no XML file\n" if ($verbose > 1); + } else { + + $info_str =~ m@^([^\n]+)\n@s || + error ("$filename: unparsable copyright"); + my $copyright = "$1"; + $copyright =~ s/\b\d{4}-(\d{4})\b/$1/; + + # Lose the Wikipedia URLs. + $info_str =~ s@http:.*?\b(wikipedia|mathworld)\b[^\s]+[ \t]*\n?@@gm; + + $info_str =~ s/(\n\n)\n+/$1/gs; + $info_str =~ s/(^\s+|\s+$)//gs; + $plist = set_plist_key ($filename, $plist, + "NSHumanReadableCopyright", $copyright); + $plist = set_plist_key ($filename, $plist, + "CFBundleLongVersionString",$copyright); + $plist = set_plist_key ($filename, $plist, + "CFBundleGetInfoString", $info_str); + + if ($oplist eq $plist) { + print STDERR "$progname: $filename: unchanged\n" if ($verbose > 1); + } else { + my $file_tmp = "$filename.tmp"; + open (my $out, '>', $file_tmp) || error ("$file_tmp: $!"); + print $out $plist || error ("$file_tmp: $!"); + close $out || error ("$file_tmp: $!"); + + if (!rename ("$file_tmp", "$filename")) { + unlink "$file_tmp"; + error ("mv \"$file_tmp\" \"$filename\": $!"); + } + print STDERR "$progname: wrote $filename\n" if ($verbose); + } + } + + set_icon ($app_dir); +} + + +sub error($) { + my ($err) = @_; + print STDERR "$progname: $err\n"; + exit 1; +} + +sub usage() { + print STDERR "usage: $progname [--verbose] program.app ...\n"; + exit 1; +} + +sub main() { + + my @files = (); + while ($_ = $ARGV[0]) { + shift @ARGV; + if (m/^--?verbose$/s) { $verbose++; } + elsif (m/^-v+$/) { $verbose += length($_)-1; } + elsif (m/^--?q(uiet)?$/s) { $verbose = 0; } + elsif (m/^-/s) { usage(); } + else { push @files, $_; } + } + usage() unless ($#files >= 0); + foreach (@files) { + update ($_); + } +} + +main(); +exit 0; diff --git a/OSX/update-thumbnail.pl b/OSX/update-thumbnail.pl new file mode 100755 index 00000000..407cc8f2 --- /dev/null +++ b/OSX/update-thumbnail.pl @@ -0,0 +1,150 @@ +#!/usr/bin/perl -w +# Copyright © 2006-2012 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. +# +# Converts and installs a thumbnail image inside a .saver bundle. +# +# Created: 26-Jul-2012. + +require 5; +#use diagnostics; # Fails on some MacOS 10.5 systems +use strict; + +my $progname = $0; $progname =~ s@.*/@@g; +my $version = q{ $Revision: 1.1 $ }; $version =~ s/^[^0-9]+([0-9.]+).*$/$1/; + +my $verbose = 1; + + +sub safe_system(@) { + my @cmd = @_; + system (@cmd); + my $exit_value = $? >> 8; + my $signal_num = $? & 127; + my $dumped_core = $? & 128; + error ("$cmd[0]: core dumped!") if ($dumped_core); + error ("$cmd[0]: signal $signal_num!") if ($signal_num); + error ("$cmd[0]: exited with $exit_value!") if ($exit_value); +} + + +# Returns true if the two files differ (by running "cmp") +# +sub cmp_files($$) { + my ($file1, $file2) = @_; + + my @cmd = ("cmp", "-s", "$file1", "$file2"); + print STDERR "$progname: executing \"" . join(" ", @cmd) . "\"\n" + if ($verbose > 3); + + system (@cmd); + my $exit_value = $? >> 8; + my $signal_num = $? & 127; + my $dumped_core = $? & 128; + + error ("$cmd[0]: core dumped!") if ($dumped_core); + error ("$cmd[0]: signal $signal_num!") if ($signal_num); + return $exit_value; +} + + +sub update($$) { + my ($src_dir, $app_dir) = @_; + + # Apparently Apple wants Resources/{thumbnail.png to be 90x58, + # and Resources/thumbnail@2x.png to be 180x116. Let's just + # make the former, but make it be the latter's size. + # + my $size = '180x116'; + + error ("$app_dir does not exist") unless (-d $app_dir); + error ("$app_dir: no name") + unless ($app_dir =~ m@/([^/.]+).(saver|app)/?$@x); + my $app_name = $1; + + $app_dir =~ s@/+$@@s; + $app_dir .= "/Contents/Resources"; + + error ("$app_dir does not exist") unless (-d $app_dir); + my $target = "$app_dir/thumbnail.png"; + + $src_dir .= "/" unless ($src_dir =~ m@/$@s); + my $src_dir2 = "${src_dir}retired/"; + + $app_name =~ s/rdbomb/rd-bomb/si; # sigh + + my $img = $src_dir . lc($app_name) . ".jpg"; + my $img2 = $src_dir2 . lc($app_name) . ".jpg"; + $img = $img2 if (! -f $img && -f $img2); + error ("$img does not exist") unless (-f $img); + + my $tmp = sprintf ("%s/thumb-%08x.png", + ($ENV{TMPDIR} ? $ENV{TMPDIR} : "/tmp"), + rand(0xFFFFFFFF)); + my @cmd = ("convert", + $img, + "-resize", $size . "^", + "-gravity", "center", + "-extent", $size, + $tmp); + + print STDERR "$progname: exec: " . join(' ', @cmd) . "\n" + if ($verbose > 2); + safe_system (@cmd); + + if (! -s $tmp) { + unlink $tmp; + error ("failed: " . join(" ", @cmd)); + } + + if (! cmp_files ($tmp, $target)) { + unlink $tmp; + print STDERR "$progname: $target: unchanged\n" if ($verbose > 1); + } elsif (! rename ($tmp, $target)) { + unlink $tmp; + error ("mv $tmp $target: $!"); + } else { + print STDERR "$progname: wrote $target\n" if ($verbose); + } +} + + +sub error($) { + my ($err) = @_; + print STDERR "$progname: $err\n"; + exit 1; +} + +sub usage() { + print STDERR "usage: $progname [--verbose] image-dir program.app ...\n"; + exit 1; +} + +sub main() { + + my $src_dir; + my @files = (); + while ($_ = $ARGV[0]) { + shift @ARGV; + if (m/^--?verbose$/s) { $verbose++; } + elsif (m/^-v+$/) { $verbose += length($_)-1; } + elsif (m/^--?q(uiet)?$/s) { $verbose = 0; } + elsif (m/^-/s) { usage(); } + elsif (! $src_dir) { $src_dir = $_; } + else { push @files, $_; } + } + usage() unless ($src_dir && $#files >= 0); + foreach (@files) { + update ($src_dir, $_); + } +} + +main(); +exit 0; diff --git a/OSX/xscreensaver_Prefix.pch b/OSX/xscreensaver_Prefix.pch new file mode 100644 index 00000000..07c8c89b --- /dev/null +++ b/OSX/xscreensaver_Prefix.pch @@ -0,0 +1,33 @@ +/* Prefix header for all source files of the 'xscreensaver' project. + */ + +#include +#include +#include +#include + +#include + +#if TARGET_OS_IPHONE || TARGET_IPHONE_SIMULATOR +# undef USE_IPHONE +# define USE_IPHONE +# define HAVE_JWZGLES +#endif + +#ifdef __OBJC__ +# ifdef USE_IPHONE +# import +# import +# else +# import +# endif +#endif + +#include "jwxyz.h" + +# ifdef USE_IPHONE +# include +# include +#else +# include +#endif diff --git a/README b/README new file mode 100644 index 00000000..84c84377 --- /dev/null +++ b/README @@ -0,0 +1,1413 @@ + + XScreenSaver + + a collection of + free screen savers + for X11 and MacOS + + By Jamie Zawinski + and many others + + http://www.jwz.org/xscreensaver/ + +=============================================================================== + +This is the XScreenSaver source code distribution. It is strongly recommended +that you install a binary release rather than trying to compile it yourself. +Binaries are available for almost all platforms, including MacOS X. See the +XScreenSaver web site for details. + +To compile on a Unix system with X11: + + ./configure + make + make install + +To compile on MacOS X: + + Use the included XCode project. Requires XCode 4 and MacOS X 10.5 + or newer. + +Interested in writing a new screen saver? + + See the README.hacking file. + +=============================================================================== + +XScreenSaver has an extensive manual -- please read it! + +=============================================================================== + +Changes since 5.19: * Support for iPhone 5 screen size. + * Fixed modifier key handing in Apple2.app and + Phosphor.app on MacOS. + * Various minor bug fixes. +Changes since 5.18: * MacOS 10.8.0 compatibility. + * iOS performance improvements. +Changes since 5.17: * iOS responds to shake gestures to randomize. + * iOS can load images from your Photo Library. + * iOS has clickable Wikipedia links in Settings panels. + * Made `pipes' be ridiculously less efficient, but spin. + * Added better mouse control to `rubik', `cube21', + `crackberg', and `julia'. + * Cosmetic improvements to `queens' and `endgame'. + * `sonar' can now ping local subnet on DHCP. + * Most savers now resize/rotate properly. + * Various fixes. +Changes since 5.16: * More iOS tweaks. + * Fixed some compilation problems. + * Enlarged the texture image for `lament'. +Changes since 5.15: * Ported to iPhone and iPad. + * XInput devices now also ignore small mouse motions. + * Loading images via RSS feeds is much improved. + * Various minor fixes. +Changes since 5.14: * New hacks, `hilbert', `companioncube' and `tronbit'. + * Image-manipulating hacks can now load from RSS or Atom + feeds: `imageDirectory' may contain a URL. + * Updated `webcollage' for recent search engine changes. + * `phosphor' and `apple2' can now be run as standalone + terminal emulator applications on MacOS. + * `photopile' sped up. + * New molecule in `molecule'. + * "Upgraded" to XCode 4.0, which means that MacOS 10.4 + PPC builds are impossible, and Intel is now required. + * Turned on LC_CTYPE on Linux; maybe Japanese password + entry works now? +Changes since 5.13: * Fixed crash in Blank Only Mode when DPMS disabled. + * Added "Quick Power-off in Blank Only Mode" option. + * BSOD GLaDOS. +Changes since 5.12: * Optionally enabled full-scene OpenGL antialiasing. + Set the resource `*multiSample' to true if doing so + doesn't kill performance with your video hardware. + * New version of `glhanoi'. + * Image-loading hacks that display the file name now also + display the sub-directory (xscreensaver-getimage now + returns relative paths under imageDirectory). + * Passwords that contain UTF-8 non-Latin1 chars are now + typeable. + * Numerous minor stability fixes. +Changes since 5.11: * Big speed improvement on OSX for heavy XCopyArea + users (`xmatrix', `moire2', `phosphor', etc.) + * Plugged a bad OSX-only Pixmap leak. + * Kludged around the OSX pty bug that caused text to + be truncated in phosphor, starwars, apple2, etc. + * New molecule in `molecule'. + * `glhanoi' now supports an arbitrary number of poles. + * Turned on "New Login" button by default. + * Added support for XInput-style alternate input devices. +Changes since 5.10: * New versions of `photopile', `strange'. + * Worked around MacOS 10.6 garbage collector bug that + caused the screen saver process to become enormous. + * Fixed flicker in `pipes', `cubestorm', and `noof'. + * Fixed EXIF rotation on MacOS 10.6. + * Fixed desktop-grabbing when screen locked on MacOS. + * Minor fixes to `circuit', `polyhedra', `tangram', + `gears', `pinion', `substrate', `xanalogtv'. + * Fixed some leaks in `xanalogtv' and `apple2'. + * Better seeding of the RNG. +Changes since 5.09: * Fixed some crashes and color problems on MacOS 10.6. + * Retired `hypercube' and `hyperball', which are + redundant with `polytopes'. +Changes since 5.08: * Ported to MacOS 10.6, including various 64-bit fixes. + * New hack, `rubikblocks'. + * Fixed another potential RANDR crash. + * Use correct proxy server on MacOS. + * `molecule' now correctly displays PDB 3.2 files. + * Updates to `mirrorblob', `glhanoi', and `sonar'. + * Rewritten version of `klein' hack. + * New hack, `surfaces', incorporating objects from old + `klein' hack, plus new ones. + * Merged `juggle' and `juggler3d' hacks. + * Fixed compilation under gcc 4.4.0 (strict aliasing). + * Fixed intermittent failure in `xscreensaver-command'. +Changes since 5.07: * New hack, `photopile'. + * Rewrote `sonar' and `jigsaw' as OpenGL programs. + * Minor tweaks to `maze', `m6502', `hypnowheel', and + `timetunnel'. + * Savers that load images now obey EXIF rotation tags. + * Arrgh, more RANDR noise! Fixes this time for rotated + screens, and for systems where RANDR lies and says the + screen size is 0x0. + * When the password dialog has timed out or been + cancelled, don't pop it right back up a second time. + * Password timeouts/cancels don't count as + "failed logins". + * Retired some of the older, less interesting savers: + say goodbye to `bubbles', `critical', `flag', `forest', + `glforestfire', `lmorph', `laser', `lightning', `lisa', + `lissie', `rotor', `sphere', `spiral', `t3d', `vines', + `whirlygig', and `worm'. + * Merged `munch' and `mismunch'. + * Updated `webcollage' to use twitpic.com as well. +Changes since 5.06: * Xinerama/RANDR tweaks for old-style multi-screen. + * Added bumpy skin and cel shading to `skytentacles'. + * `flipflop' can load images onto the tiles. + * Fixed the bouncing ball in `stairs'. + * Added the missing Utah Teapotahedron to `polyhedra'. + * `blitspin' works with color images on MacOS now. + * Added transparency to `stonerview'. + * Improved layout of the preferences dialogs: they + should all now be usable even on ridiculously tiny + laptop screens. + * MacOS preferences text fields now prevent you from + entering numbers that are out of range. + * Added "Reset to Defaults" button on X11. + * Added relevant Wikipedia links to many of the screen + saver descriptions. + * All hacks support the `-fps' option, not just GL ones. + * The `-fps' option now shows CPU load. +Changes since 5.05: * Xinerama/RANDR fixes: this time for sure. It should + now work to add/remove monitors or resize screens at + any time. + * New hack, `skytentacles'. + * New version of `gleidescope'. + * Added the `-log' option to the xscreensaver daemon, + since a truly shocking number of Linux users seem to + have no idea how to redirect output to a file. + * Added `-duration' arg to most image-loading hacks, + so that they pick a new image every few minutes. + * Added an ATM crash to BSOD. +Changes since 5.04: * New hacks, `cubicgrid', `hypnowheel', and + `lcdscrub' (which isn't really a screen saver). + * Updates to `m6502' and `gears'. + * Fixed double-buffering problems in `cubestorm' and + `noof'. + * Better handling of horizontal scroll wheels. + * Attempt to work around latest Xinerama braindamage: + if the server reports overlapping screens, use the + largest non-overlapping rectangles available. + * Don't warning about receipt of bogus ClientMessages, + since Gnome's just never going to stop sending those. + * Worked around MacOS 10.5 perl bug that caused the + text-displaying hacks to fail on some systems. + * Hopefully fixed font-related System Preferences crashes + in MacOS savers. + * The recent PAM changes broke the "Caps Lock" warning + in the password dialog, the failed login warnings, and + syslogging. Fixed all that. +Changes since 5.03: * Fixed a possible crash in the unlock dialog (more + fallout from the recent PAM changes...) + * New hacks, `moebiusgears', `abstractile', and + `lockward'. + * Rewrote `gears' to use better (involute) gear models, + and to be more random. + * Minor updates to `cwaves', `voronoi', `deco', + `glcells', `rd-bomb', `fireworkx' and `webcollage'. + * `pong' can now display the current time as the score. + * `xmatrix -mode pipe' works better. + * Minor tweaks for compilation on MacOS 10.5.0. +Changes since 5.02: * New hacks, `cwaves', `glcells', `m6502', and `voronoi'. + * Minor fixes to `bsod'. + * Fixed possible crash with PAM USB-dongle auth. + * Updated `webcollage' to track recent Google Images + and Flickr changes. +Changes since 5.01: * Reworked PAM code to support fingerprint readers, etc. + * Ported 'webcollage' to MacOS. + * Added MacOS 10.2 and 10.3 kernel panics to `bsod'. + * Fixed a Xinerama crash when changing the screen count. + * New blobbier `mirrorblob'. + * Minor updates to `lisa', `bsod', `ifs', `hypertorus', + `polytopes', `circuit', `endgame', `crackberg', + `flipflop', `flipscreen3d', `fliptext', and `carousel'. + * Enabled multi-threaded OpenGL on MacOS. +Changes since 5.00: * Backed out recent locale-related changes, since they + broke far more things than they fixed. + * Fail gracefully with ridiculously small window sizes. + * `xflame' and `flag' ignore bitmap option on MacOS. + * `speedmine' prefs work on MacOS. + * Better explosions in `boxed'. + * More dynamic motion in `sproingies'. + * More options in `flipflop'. + * Minor updates to `topblock'. + * Various other minor fixes. +Changes since 4.24: * Ported to MacOS X! (10.4.0 or newer) + * API change: instead of providing a single screenhack() + function that does not return, screen savers using the + screenhack.h framework must now provide "init" and + "draw one frame" functions instead. All bundled savers + have been updated; third-party patches will need work. + * All image-loading happens asynchronously. + * xscreensaver-getimage-file caches the contents of the + image directory for a few hours, so consecutive runs + won't have to re-list the whole directory tree. + * New hacks, `topblock' and `glschool'. + * Removed `xteevee' (superceded by `xanalogtv'). + * Added variable-sized puzzle pieces to `jigsaw'. + * Changes to the defaults and command-line options of + many hacks to make the .xml files more consistent. + * Reap zombies in `glslideshow' and `carousel'. + * `sonar' works without setuid on MacOS (dgram icmp). + * `xmatrix -mode pipe' displays the text of a subprocess. + * `endgame' has higher resolution chess-piece models. + * `webcollage' takes a -directory option to get images + from a local directory. + * The RPM spec file no longer auto-restarts xscreensaver + when a new version is installed. Restart it manually. +Changes since 4.23: * New versions of `cube21', `glsnake', `celtic'. + * Backed out a DPMS-related patch that cause desktop + flickering with some X servers. + * Fixed startup crash in getgroups() when running setuid. + * Default to not displaying stderr on the saver window. + * Fixed bad free() in "Documentation" button. + * Don't try to run hacks that aren't installed. + * Minor fixes to various XML config files and man pages. +Changes since 4.22: * New hacks, `glhanoi', `cube21', `timetunnel', + `juggler3d', and `celtic'. + * New versions of `tangram', `webcollage', `hypertorus', + `polytopes', and `ripples'. + * `sonar' is now quiet about unresolvable hosts. + * Minor corrections to BASIC code in `apple2'. + * xscreensaver-demo now provides an RPM clue when none + of the hacks seem to be installed. + * Don't install `ant' by default, since there is some + Java tool of that name, which was causing confusion. + And also it's boring. + * Made screen grabbing work again on MacOS 10.4.2. + * No longer prints bogus warnings about ClientMessages + intended for the window manager. + * Ignore unprintable characters in passwd entry field. + * Fixed yet another cross-host-display image-loading + endian problem. + * `xscreensaver-command -watch' and `-time' now work + on 64-bit machines. +Changes since 4.21: * Fixed a bug in the new mouse-motion code that caused + the screen to never blank on multi-head non-Xinerama + systems. Oops. + * New hacks, `interaggregate', `antmaze', `tangram', + and `crackberg'. + * Minor tweaks to `fiberlamp', `ifs', `slidescreen', + `zoom', `sonar', `fireworkx', `whirlwindwarp', + `bubble3d', and `rd-bomb'. + * Added motion blur to `blinkbox'. + * `bsod' now includes Longhorn's "RSOD", and OS/2. + * Fixed `-wireframe' usage in most hacks and man pages. +Changes since 4.20: * New hack: `fliptext'. + * Changed default configure installation directories: + /usr/bin/ for xscreensaver, etc.; + /usr/libexec/xscreensaver/ for hacks; + /usr/share/xscreensaver/config/ for xml files. + * All the text-manipulating screen savers can have their + text source configured via `xscreensaver-demo' now. + * xscreensaver.spec now builds three RPMs: + base (no hacks); extras (2d hacks); and gl-extras. + * Added `-program' and `-front' option to `gltext'. + * Added `-shells' to `molecule'. + * Fixed text-alpha glitch in `carousel'. + * New `pacman': the ghosts can be killed now. + * Fixed a bug in screen-grabbing GL hacks where images + would be tiled instead of scaled on machines that + can't do large textures. + * `webcollage' can hit Flickr now. + * New (rewritten) implementation of `ifs'. + * The unlock dialog can be made to have a "New Login" + button that will run `gdmflexiserver'. Experimental! + * Fixed non-ASCII display bug in `starwars'. + * Configure finds a default for imageDirectory. + * "xscreensaver-command -lock" now works even if + in "screensaver disabled" mode. + * If a bad password is typed while CapsLock is on, the + unlock dialog says "CapsLock?" instead of "Sorry". + * Mouse motion only counts as activity if the mouse moved + more than 10 pixels (so the screen won't unblank every + time you bump your desk.) + * New mode option "random-same": if you have multiple + monitors, this will run the *same* randomly chosen + hack on each screen, instead of different ones on each. +Changes since 4.19: * New hacks, `fiberlamp', `boing', `boxfit', and + `carousel'. + * Rewrote `glslideshow' again: should be faster now. + * Sped up loading of images in GL programs. + * `starwars' uses texture-mapped fonts now. + * New `bsod' modes: tru64, hppa, and nvidia. + * Updates to `webcollage', `juggle', `pinion', + `fireworkx', `sonar', `extrusion', `substrate', and + `pong'. +Changes since 4.18: * New hacks, `substrate', `intermomentary', `fireworkx', + and `pinion'. + * New version of `flow'. + * Made /proc/interrupts work again on Linux 2.6. + * Made `analogtv' not hog the CPU. + * Made analogtv-based hacks work properly on PPC/ARM. + * Fixed a bad memory leak in `piecewise'. + * Minor updates to `sonar', `molecule', `glmatrix', + `galaxy', and `webcollage'. + * Removed support for GTK 1.x (everyone uses 2.x now.) +Changes since 4.17: * Oops, pay no attention to the man behind the curtain. +Changes since 4.16: * New hacks, `anemotaxis' and `memscroller'. + * Fixed a bad bug that caused `vidwhacker' to never die. + * Fixed normals and lighting in `polyhedra'. + * Don't reuse the window when changing hacks (to work + around bugs in some GL implementations.) + * Made `xscreensaver-getimage-file' skip thumbnail-sized + images. + * Fixed endian problem in `barcode' on non-x86. + * Updates to `webcollage', `apple2', `fuzzyflakes', + `atunnel', and `pacman'. + * Timing tweaks to `bubble3d', `bouncingcow', `engine', + `gltext', `lavalite', `molecule', `spotlight', + `sballs', `boxed', `blinkbox', and `circuit'. + * Configure updates for Fedora core 2 / xorg 6.7.0. + * Compile without warnings under gcc 3.3.3. + * I give up: don't blank or lock the screen if we can't + get a keyboard grab. In that case, both choices are + bad. +Changes since 4.15: * New hacks, `polyhedra', `fuzzyflakes', `antinspect', + and `providence'. + * Minor updates to `webcollage', `bsod', `endgame', + `antspotlight', `xmatrix', and `glmatrix'. + * Added support for the RANDR (Resize and Rotate) + extension to detect when the size of the desktop has + been changed while xscreensaver is already running. + * Possibly-futile attempt to work around "rdesktop" + focus/grab idiocy. + * Made `xscreensaver-getimage -file' still work even if + imageDirectory is unset. + * Convert Latin1 to ASCII in `starwars' and `phosphor' + (since the GLUT font only has ASCII glyphs.) + * Fixed randomization in `noof'. + * Added "GetViewPortIsFullOfLies" preference to work + around longstanding XFree86 bug #421. + * Made `sonar' subnet pinging work properly on bigendian + machines (e.g., PPC.) +Changes since 4.14: * New hacks, `wormhole', `mismunch', `noof', and + `pacman'. + * `phosphor' and `apple2' include vt100 emulators now: + this means you can do "phosphor -program top", or + can use either program as an xterm replacement: + "apple2 -text -fast -program 'xemacs -nw'". + * `analogtv' (and related) fill the screen better. + * The '-gradient' option works in `atlantis' now. + * Minor updates to `blinkbox', `queens', `endgame', + `glmatrix', `mirrorblob', `blocktube', and `molecule'. + * Integrated SuSE's "external passwd helper" support. + * Marginally better /tmp handling in various programs. + * Updated config defaults for xplanet 1.0.3. + * Portability fixes. +Changes since 4.13: * New hacks, `fontglide', `apple2', `xanalogtv', `pong', + `gleidescope', `mirrorblob', and `blinkbox'. + * New version of `glsnake' (with many more models.) + * Another Windows crash in `bsod'; also HVX/GCOS6/TPS6. + * New version of `endgame'. + * Screen grabbing works on MacOS X. + * Various minor fixes. +Changes since 4.12: * On Xinerama systems, xscreensaver now runs one hack on + each monitor (just like in "real" multi-head mode) + instead of running one hack stretching across all the + screens. Note that for this to work with any 3rd party + screensavers, they must update their "vroot.h" file. + * `webcollage' and `vidwhacker' display images using + `xscreensaver-getimage' now. + * Added `ljlatest' script for use with `starwars' and + `phosphor'. +Changes since 4.11: * New GL hacks, `flipflop', `antspotlight', and + `polytopes'. + * Added VMS to `bsod'. + * Compile without warnings in "gcc -pedantic". + * Updates to `webcollage' and `queens'. + * Fixed a bug that could cause PAM to hang. +Changes since 4.10: * New hacks, `hypertorus', `cubestorm', `glknots', + `blocktube', and `glmatrix'. + * Updates to `cloudlife', `engine', `xmatrix', and + `sonar'. + * Rewrote `glslideshow': it should work on somewhat + wimpier video cards now. + * Various portability tweaks. +Changes since 4.09: * New hacks, `cloudlife' and `klein'. + * Added Apple ][+, HPUX, and OS/390 sessions to BSOD. + * Added some Matrix Reloaded text to `xmatrix'. + * Updates to `webcollage', `eruption', `jigglypuff', + `metaballs', and `endgame'. + * Completely ignore the `memoryLimit' setting now, + since it was still causing people GL grief. + * Various minor fixes. +Changes since 4.08: * New hacks, `flyingtoasters', `bouncingcow', + `jigglypuff', and `glslideshow'. + * More models in `engine'. + * Rewrote `xscreensaver-getimage' to remove reliance on + external image loaders (xv, chbg, xloadimage, etc.) + and to reduce flicker when loading files. + * Made `gflux' and `flipscreen3d' be mouse-spinnable. +Changes since 4.07: * New hacks, `atunnels' and `piecewise'. + * Physics improvement in `fluidballs'. + * Various fixes for XDarwin systems (X11 on MacOS X.) + * Added -clock option to `barcode'. + * Minor fixes to `endgame', `flurry', `flipscreen3d', + and `gflux'. +Changes since 4.06: * New hacks, `flurry', `metaballs', `eruption', + `popsquares', and `barcode'. + * Minor updates to `maze' for high density mazes. + * Added double buffering to `fluidballs' and `whirlygig'. + * Bug fixes for running xscreensaver to a remote XFree86 + display (which nobody would ever do...) + * Updated `webcollage' (faster Alta Vista searching.) + * Updated `glplanet' so the sun sets in the west. + * Updated `sproingies' with smooth, unsegmented surfaces. + * Fixed Perl version-sensitivity in + `xscreensaver-getimage-file'. + * Fixed GTK2 scrolling bug in `xscreensaver-demo'. +Changes since 4.05: * New hack, `glblur' (disabled by default, since it + requires fast OpenGL texture support.) + * New hack, `halftone'. + * Updates to `endgame', `queens', `bumps', `glplanet', + `engine', and `circuit'. + * New version of `menger' that uses far fewer polygons. + * Fixed minor bug in `critical' that could cause some + bogus X servers to crash. + * Better labels in `molecule': the labels now appear to + be attached to the atoms, instead of floating in front + of the whole scene. + * Fixed bug that could rarely cause GL hacks to fail to + double-buffer (causing intermittent flickering.) + * Fixed a relative-URL-parsing bug in `webcollage'. + * Fixed a bug that (sometimes) caused the window manager + close box to kill `xscreensaver-demo' with a crash + instead of a graceful exit. + * Updated xscreensaver.pam to the Red Hat 7.3 way. + * More Gnome2-related configure crap. + * Updated to latest `config.guess' and `config.sub'. + * Fixed occasional core dump in `distort'. + * Added a Linux fsck failure and kernel panic to `bsod'. + * Added MacOS X kernel panic to `bsod'. + * Fixed a bug in `bsod' (all bsod bugs are ironic.) + * Fixed a bug that caused `xscreensaver-gl-helper' to + print a nonsense visual ID with some versions of + `printf': this could cause GL programs to display + incorrectly (e.g., flickery.) +Changes since 4.04: * More `configure' tweaks to try and get things working + on systems that both Gtk 1.x and 2.x installed. + * New hack, `endgame'. + * Minor updates to `gltext'. +Changes since 4.03: * Support for GTK 2.x / GNOME 2.x. + * The `configure' script will now use `pkg-config' if + you have it, in preference to `gtk-config', etc. + * New hacks, `lavalite', `queens', and `anemone'. + * Minor updates to `spheremonics', `gltext', `xmatrix'. + * You can use the mouse to manually spin most of the GL + hacks now (when they are displaying in a window.) + * Fixed a bug in `webcollage' (due to recent Alta Vista + url changes) that was causing it to try and load + incorrect image URLs. + * Made `xscreensaver-getimage' use gdk_pixbuf if it is + available: this means that those hacks that load images + will no longer rely on "xv", "xloadimage", etc. This + will close a race condition that could sometimes cause + your desktop background to be changed; and also makes + it possible for those programs to operate on image + files when running in windowed mode. + * `webcollage' can now be used in conjunction with + `driftnet' to display images snooped from your local + ethernet instead of obtained from search engines. + * Added man pages for all the hacks that didn't have + them. +Changes since 4.02: * New hack, `spheremonics'. + * Minor updates to `webcollage', `cage', `moebius', + `morph3d', `boxed', `circuit', and `helix'. + * `pulsar' and `extrusion' can now load texture JPEGs. + * `rubik' now does non-square cubes. + * `fluidballs' now does various sizes of balls. + * `menger' and `sierpinski3d' now also show polygon + counts in -fps mode. + * `molecule' displays real subscripts in the formulae. + * GTK internationalization/localization support. + * Better detection of the various versions of libxml. + * Upgraded to autoconf 2.53 (from 2.13.) +Changes since 4.01: * Plugged a few minor leaks in `xscreensaver' and + `xscreensaver-demo'. + * New hacks, `cubenetic' and `fluidballs'. + * Sped up `pipes'. + * Fixed sphere projection error in `glplanet'; installed + a better image of earth. + * Added Win2K and MacOS 1 crashes to `bsod'. + * Put back previous (better) version of `forest' that + was accidentially downgraded in the last release. + * New version of `bumps'. + * Made FPS computation in GL hacks more efficient: it + will influence the results less, thus resulting in + higher (but more accurate) reported frame rates. +Changes since 4.00: * New hacks: `twang', `glsnake', `boxed', `sballs', + and `glforestfire'. + * New hacks `apollonian', `euler2d', `juggle', + `polyominoes' and `thornbird', from xlockmore. + * Merged recent xlockmore changes into `ant', `braid', + `demon', `discrete', `drift', `fadeplot', `forest', + `grav', `hopalong', `ifs', `laser', `lightning', + `lisa', `lissie', `loop', `mountain', `penrose', + `rotor', `sierpinski', `slip', `sphere', `spiral', + `strange', and `vines'. + * Fixed the `gltext' bug that sometimes caused + horizontal lines to vanish again. This time for sure. + * Sped up `webcollage' by adding a C helper program to + replace the PPM pipeline. It also pastes images + semi-transparently now. + * Added support for the gdk_pixbuf library: if this lib + is available, then `blitspin', `xflame', and `flag' + can load GIF, JPEG, and PNG images in addition to XPM + and XBM. + * Fixed a rare race condition where the desktop-grabbing + hacks could sometimes leave the screen wedged, if the + user moved the mouse exactly when they were grabbing + the screen image (it would un-wedge the next time the + saver timed out or was activated.) + * Fixed incorrect colors in the screen-grabbing GL hacks + (`gflux' and `flipscreen3d'.) + * Made SIGHUP restart the daemon process (though using + `xscreensaver-command -restart' is still the preferred + way.) + * Tweaks to `xspirograph'. + * Minor configure and portability tweaks. +Changes since 3.34: * Redesigned `xscreensaver-demo' GUI: it now includes + small-preview and per-hack configuration dialogs. + * Added three new modes of operation: `One Screen Saver', + `Blank Screen', and `Don't Blank' (in addition to the + historical `Random Screen Saver'). + * Configure now defaults to installing the hacks in + /lib/xscreensaver/ instead of /bin/. + (Most distros already did it this way.) + * New GL hacks, `menger', `engine', `flipscreen3d'. + * Made `sierpinski3d' be more colorful. + * New versions of `xmatrix' and `nerverot'. + * Fixed a bug in `starwars' that made the font be drawn + with thin lines in -root mode. + * Fixed a bad colormap bug in `crystal' that could make + *subsequent* hacks malfunction! + * Made `gflux' able to grab screen images (`-mode grab'). + * Updated `webcollage' for recent search engine changes. + * Removed most command-line options to `xscreensaver': + just edit the ~/.xscreensaver file instead. + * Improved behavior on multi-screen and Xinerama systems: + the mouse now stays on the screen where the user left + it, and the password and splash dialogs always appear + on the screen that has the mouse. + * Made the splash dialog use more Gtk-like colors; + made it have only two buttons, "Settings" and "Help". + * Made `sonar' understand `.ssh/known_hosts2' format + files, and be better about stripping out illegal + addresses. +Changes since 3.33: * Turned `memoryLimit' off by default, sigh. Apparently + some versions of the GL libraries (appear to) allocate + hundreds of megs for every GL program, so `memoryLimit' + was causing GL programs to malfunction or crash on + those systems. + * Improved fading on TrueColor XFree86 4.1.x systems. + * New GL hack, `circuit'. + * Added `fuzz' mode to `decayscreen'. + * New version of `whirlygig'. + * Added links to `xplanet' and `sphereEversion'. + * Fixed rare race condition that could make `sonar' hang. + * Fixed potential crash in `speedmine'. + * Made `xscreensaver-demo' not crash when imageDirectory + was set to a non-existent directory. + * Made `xscreensaver-getimage-video' invoke XawTV's + `streamer' program better. + * Made `phosphor' and `starwars' deal with CR, LF, + or CRLF line endings. + * Changes for Cygwin compilation environments. + * Made `sonar' compile on systems that can't ping. + * Configure changes for HPUX 10.20. + * Made PAM code work on Red Had 4.2 systems. + * Made `xscreensaver-command -deactivate' work when the + saver is not active: what that does is reset the idle + timer, as if keyboard input had been detected. This + was added for the benefit of people writing DVD-playing + software: they can now prevent the screensaver from + kicking in by sending a -deactivate message once a + minute while the movie is playing and not paused. + * Various minor portability tweaks. +Changes since 3.32: * New hacks, `speedmine' and `whirlygig'. + * Sped up `pyro', made the explosions look a bit better. + * Added better stars to `glplanet' and `starwars'. + * Many internal changes to `webcollage'. + * Some new options to `attraction'. + * Minor fix to `noseguy' to avoid un-erased pixels. + * Rewrote the screen-eraser effects so that they complete + in the same amount of time regardless of how slow + your X server is (some of them were glacial on servers + with slow blitting.) + * Fixed a potential free memory reference that could + sometimes cause a crash at startup. + * Possibly fixed a problem that could cause the daemon + to crash with an X error. I was never able to + reproduce this problem, but I think I might have + figured out what caused it. + * Worked around a problem that caused PAM authentication + to fail on some Red Hat 7.x systems. + * Added a `memoryLimit' parameter that controls the + amount of memory a graphics hack may allocate: if they + try to allocate more than this, malloc() will fail + (and they will exit or (safely) crash, rather than + hogging memory.) Default is 50M. + * Made `gnome-help-browser' be the default way to display + man pages in `xscreensaver-demo', if running on a + GNOME system. +Changes since 3.31: * The image-manipulating hacks (`slidescreen', etc.) can + now operate on randomly chosen image files from disk, + or on frames captured from the system's video input, + instead of (or in addition to) manipulating images of + the desktop. + * Rewrote `vidwhacker' to use the new image-grabbing + mechanism. + * Made fading work on TrueColor XFree86 4.x systems. + * Fixed a subtle rendering bug in `atlantis' (the fish + were inside out!) + * Made `atlantis' have a texture simulating light + reflections from the surface of the ocean. + * Fixed up label placement in `molecule'. + * Better color bars in `xteevee'. + * Made `install-strip' not try to strip scripts. +Changes since 3.30: * Put in more sensible defaults for DPMS, and updated + the documentation to reflect the fact that all your + DPMS settings are now belong to xscreensaver. + * Fixed the `xscreensaver.spec' file so that `--force' + is no longer needed. + * New versions of `rotzoomer' and `nerverot'. + * Fixed an OSF/1 compilation problem in `molecule'. +Changes since 3.29: * New hacks, `molecule', `dangerball', and `rotzoomer'. + * New version of `gflux'. + * Made `gltext' able to display the current time. + * Fixed a floating-point-precision problem in `gltext' + that sometimes caused horizontal lines to vanish. + * Removed the `-window-id' option from the hacks: + it never worked right, and was unnecessary. + * Made the `starwars' hack use thicker lines, antialias + the text, and fade out at the far edge instead of just + dropping off. + * Fixed an SHM segment leak in `moire'. +Changes since 3.28: * Better rendering of the new logo. + * New hack, `gltext'. + * Added `-planetary' option to `gears', to draw a + different kind of gear system. + * Made motion and rotation be smoother in `gears', + `glplanet', `moebius', `rubik', and `sierpinski3d'. + * Improved coloration in `sierpinski3d'. + * Made the GL hacks react to window size changes. + * Made most of the GL hacks take a -fps option (like + `pulsar' did), so you can use them to benchmark your + 3D hardware. + * Fixed the previous fix to `sonar'. + * Minor fix to `nerverot'. + Made sonar able to ping hosts on DEC OSF1. + * Eliminated a bogus "didn't get enough colors" warning + in some of the hacks. +Changes since 3.27: * New logo for xscreensaver! + * New hacks, `starwars' and `stonerview'. + * Made the motion of the bouncing ball in `stairs' be a + little less jerky. + * Made newly-added screenhacks be added to .xscreensaver + automatically: if there are hacks in the app-defaults + file that are not also in ~/.xscreensaver, they will + be added to the end of the list. + * Redid the `Screensaver Options' part of the control + panel; xscreensaver now lets you configure your DPMS + settings. + * Fixed some Makefile problems with non-GL builds. + * Fixed detection of MesaGL for version 3.3. + * Better workaround to Red Hat 7.0's broken gcc. + * Added Sparc Solaris kernel panic to `bsod'. +Changes since 3.26: * New hacks: `zoom' and `whirlwindwarp'. + * Fixed a free-memory-reference bug in `sonar'. + * Better error handling when there are no suitable GL + visuals. + * Added diagnostic dialog when xscreensaver-demo is + unable to launch xscreensaver (e.g., when running as + root.) + * Fixed a bug that caused screenhack argument changes + to be ignored when xscreensaver-demo was running as + root (if "root" and "nobody" have different home + directories.) + * Made the programs default to ":0" if $DISPLAY is unset. + * Made the `-verbose' output include information about + which server extensions were supported at compile time. + * Worked around Red Hat 7.0's broken gcc 2.96. + * Updated default delays on the GL hacks to look better + on machines with super-fast 3D hardware. + * Install `screensaver-properties-capplet' to work around + the usual egregious GNOME lossage. +Changes since 3.25: * Added "enabled" checkboxes in the list of hacks in + xscreensaver-demo (Gtk version only.) + * New hacks `hyperball', `xrayswarm', and `gflux'. + * New versions of `nerverot', `galaxy', and `hypercube'. + * Small fixes to `phosphor', `shadebobs', `xflame', + and `sonar'. + * Added external helper program `xscreensaver-gl-helper' + to figure out which X visual to use for OpenGL + programs. + * Configure updates for XFree86 4.0, and for BSD. + * Made it be more tolerant of bogus /etc/group files. + * When installing the PAM config file, first try to just + copy an existing "xdm" or "login" config file, so that + xscreensaver does authentication in the same way as the + rest of the system. +Changes since 3.24: * New hack, `nerverot'. + * Added BSD kernel panic to `bsod'. + * New version of `shadebobs'. + * New version of `petri'. + * Updated `webcollage' to handle recent Altavista URL + format changes; made it search the AP photo gallery. + * Revamped command-line options of `sonar' and made it + properly handle subnets. + * The `bubbles' hack can now trickle up or down the + screen. + * The `xsublim' hack can now read its text from programs. + * Support for GLE version 3 in `extrusion'. + * Fixed compilation problems in `maze'. + * Fixed a rare crash in `flow'. + * Fixes for minor installation problems. +Changes since 3.23: * Added `-ignorant' option to `maze' hack. + * Updates to `critical', `bsod', `xflame', and `flow'. + * Added support for Kerberos 5 (via its Kerberos 4 + compatibility layer.) + * Fixed a bad leak in `xteevee'. + * Updated `webcollage' to handle recent Altavista URL + format changes. + * Removed xscreensaver-demo's `Ok' and `Cancel' buttons, + since they were confusing people: all changes are now + instantanious. + * Made xscreensaver-demo install itself into the Gnome + Control Center. +Changes since 3.22: * Fixed some misplaced text fields in the Motif version + of xscreensaver-demo; fixed a crash in the Gtk version + that would happen if the programs list was empty. + * Fixed a recently-introduced bug in `pulsar'. + * Made `sierpinski3d' use solid tetrahedrons instead of + points. + * Added `-trace' option to `xmatrix'. + * Added new hacks `xteevee' and `xspirograph'. +Changes since 3.21: * Fixed some bugs in xscreensaver-demo. + * Rewrote the Motif version of xscreensaver-demo to + match the new Gtk version. + * The Athena toolkit is no longer supported. +Changes since 3.20: * Tweaked the xscreensaver-demo UI (Gtk only.) + * Fixed a few visual selection bugs. I think the proper + GL visual should be used with nVidia systems now. + * Made the Makefiles obey $install_prefix. + * Made the `xscreensaver.spec' file able to generate both + GL and non-GL packages simultaneously. +Changes since 3.19: * Added new hacks `ripples' and `sierpinski3d'. + * Made `xscreensaver-command -exit' be silent when no + screen saver was running (instead of complaining.) + * Made `webcollage' and `vidwhacker' use `xloadimage' + when available (in addition to `xli' and `xv'.) + * Improved memory usage in `petri' and gave it a hard + cap on how much memory it can allocate. + * Added `-watch' option to `xscreensaver-command'. + * Made `xscreensaver-demo' come up with the + most-recently-run hack selected by default. + * Rewrote the Gtk version of `xscreensaver-demo'. + It's a lot easier to use now. + * Extended the format of the programs list in the + .xscreensaver file, for the benefit of the new + capabilities of `xscreensaver-demo'. + NOTE: you might want to delete your ~/.xscreensaver + file and allow it to be re-created! The old one + should still work, but xscreensaver-demo won't be as + pretty. +Changes since 3.18: * Fixed gcc dependencies in `bumps' and `ccurve'. + * New hack, `extrusion'. + * Some of the web sites that `webcollage' was using as + its sources changed formats; tweaked it to understand + the current layouts. + * Added typeahead in the password dialog: if the screen + is locked, and you unlock it by typing a character, + that key will be automatically inserted in the + password dialog (unless it is Return, Enter, Space, + or a non-printing key like Shift.) + * Made `xmatrix' take a `-small' option, since some + folks with tiny screens prefer a smaller font. +Changes since 3.17: * New versions of `shadebobs', `lmorph', and `distort'. + * Added `ccurve', `blaster', and `bumps' hacks. + * Replaced `forest' hack with a rewritten version. + * Worked around a Xinerama server bug. + * Fixed a bug I introduced in 3.10 that caused some + hacks to print out superfluous warnings about not + having gotten enough colors. + * Made `sproingies' obey the `-delay' option. + * Fixed a portability bug in `shadebobs'. + * Made `webcollage' and `vidwhacker' use `xli' in + preference to `xv', if it is available. + * Added a new source of images to `webcollage'. + * If running under KDE, xscreensaver will add itself to + KDE's list of screensavers (via xscreensaver.kss.) + * Improved detection of GL libraries. + * Made the password dialog include the date and time. +Changes since 3.16: * New version of `webcollage' -- deals better with + corrupted images, and can use an http proxy. + * New hack, `xsublim' (run it in the background, + rather than adding it to the programs list.) + * The xscreensaver daemon was leaking a file descriptor + each time you edited your .xscreensaver file. Fixed. +Changes since 3.15: * New version of `shadebobs'. + * Improved image selection in `webcollage', and sped it + up slightly. + * Made configure find the right version of perl. + * Rewrote the CGI part of `webcollage'. + * `make clean' was deleting some things it shouldn't. + * Fixed a typo in the default programs list. +Changes since 3.14: * Added `webcollage' and `shadebobs' hacks. + * Added a `-stdout' arg to `vidwhacker' so that it can + be used in a pipeline. + * Made `petri' use less memory. +Changes since 3.13: * Various improvements to the Gtk port. + * Turned off PAM by default on Solaris, since PAM seems + generally to be misconfigured out-of-the-box. + * Made the `--without-gtk' configure option work. + * Made configure check the Gtk version number, since it + requires 1.2. + * Fixed a bug in the code that attempted to prevent + changes of screen resolution while the screen is + locked. + * Fixed a race condition in `xscreensaver-demo' that + could cause an X error at startup. + * Added `-transparent' option to `deluxe'. + * Added `petri' hack. +Changes since 3.12: * Ported `xscreensaver-demo' to Gtk. + * Made it possible to build Motif, Gtk, and Athena + versions of `xscreensaver-demo' in the same directory + without reconfiguring. + * Made `xscreensaver-demo' chase symlinks before writing + the .xscreensaver file, so that if .xscreensaver is + itself a symlink, the underlying file will be replaced + instead. + * Some Makefile and configure tweaks for Solaris and + FreeBSD. + * Made it possible to set the fire color in `xflame'. + * Made transparency work in TrueColor (for `goop' and + `qix'.) + * Fixed a multi-head bug introduced by the virtual + viewports stuff. +Changes since 3.11: * Made it so that you can't scroll the screen while the + lock dialog is up (with XFree86 virtual viewports.) + * Fixed a bug in `flag' that caused bob's chin to get cut + off after a few iterations. +Changes since 3.10: * Made `xjack' be black-on-white-ish, so that it looks + less like a computer screen and more like the + typewritten paper it's supposed to be. + * New version of `pulsar'. + * Fixed Solaris compilation problem in `phosphor'. + * Made xscreensaver notice XFree86's virtual root window + hack, so that if the X server's root window is larger + than the monitor's displayable resolution, the screen + saver will limit itself to the area that actually + appears on the screen. + * Made the xscreensaver daemon do a better job of + picking the visual class that should be used for GL + programs. Less user intervention should be needed + now: you can use the logical visual name `GL' instead + of having to figure out by hand which one to use. + * Oops, the visual was defaulting to "best" instead of + "default", because the .xscreensaver file was not being + loaded quite early enough. + * Made configure figure out how to build icmp ping + support into the `sonar' hack automatically. + * Made warnings about not being able to read shadow + passwords not be printed if compiled with PAM support. + * Improved PAM startup diagnostics. + * Worked around the Solaris PAM bug that was causing + crashes there, so now PAM is turned on by default. + * Made configure detect the number of arguments that + pam_strerror() takes, since on Linux, this apparently + changed between 2.0 and 2.2, sigh. + * Made the /proc/interrupts kludge look for "PS/2 Mouse" + as well as "keyboard". + * Made xscreensaver notice when there has been a sudden + large jump in wall-clock time, and if so, lock right + away, instead of waiting for "lockTimeout" to expire + first. (Laptops need this for safer recovery from + ``hibernation.'') + * Added `-throttle' option to `xscreensaver-command'. +Changes since 3.09: * Added `phosphor', `xmatrix', and `pulsar' hacks. + * Fixed a bug in the color allocator that sometimes + caused `starfish' to fall back to monochrome. + * Reduced the amount of code that runs before root + privileges are disavowed: "normal" and "shadow" + passwords now do some initialization as root, but the + PAM and Kerberos authorization schemes will be + initialized while running as "nobody". Supposedly + this closes a potential security hole when using + Kerberos. + * Added some more sanity checking to configure. +Changes since 3.08: * Added `compass', `squiral', `xflame', `wander', + `spotlight', and `critical' hacks. + * Added some new modes to `decayscreen'. + * Made `deluxe' work in monochrome. + * Generalized usage of the Double-Buffer server extension + in several hacks (`compass', `deluxe', `interference', + `kumppa', and `moire2'.) + * Fixed another visual-depth problem in `rd-bomb'. + * The screen saver will now defer blanking if neither + the keyboard nor the mouse could be grabbed. Instead, + it will just try again in a few minutes. This fixes + a bad interaction between xscreensaver and programs + like VMware that hold the mouse and keyboard grabbed + for a long time. + * Added a new erase mode (expanding spiral.) +Changes since 3.07: * Fixed some bugs in my port of `t3d'. + * Added `penetrate' and `deluxe' hacks. + * When linking against Motif 2.x, also link against XPM. + * Added support for using /proc/interrupts for idle + detection on Linux. Now xscreensaver shouldn't kick + in when the user is active on a non-X virtual console. + * Upgraded to autoconf 2.13. +Changes since 3.06: * Configure tweaks (sometimes -lXmu wasn't getting linked + in properly; check for _Xsetlocale in -lXintl.) + * Portability fixes for sonar.c. + * Fixed a compilation problem when you have GL but don't + have XPM. + * Made configure notice when MesaGL requires -lpthread. + * Made `flame' ignore SIGFPE (not sure if this is the + right fix; it seems only to be needed on FreeBSD.) + * Kludged `rd-bomb' work on visuals that are of depth 24 + but that *do not* support pixmaps of depth 32. + * Fixed `halo' to work properly in TrueColor. + * Changed `xscreensaver.spec' to install the hacks in + /usr/X11R6/lib/xscreensaver/ by default, since that's + where recent Red Hat distributions put them. + * Added `t3d' hack. + * Updated versions of `crystal', `hopalong', and `flow' + from xlockmore. + * Imported `demon' and `loop' modes from xlockmore. +Changes since 3.05: * Oops, the "default-n" visual descriptor was broken; + it was always installing a colormap if the + `installColormap' preference was set, meaning that + `xearth', `xv' and friends were using the wrong + colors on 8-bit systems. + * Turned off HAVE_PING in `sonar', since it compiles + on some Linux systems, but not others of similar + vintage... +Changes since 3.04: * Fixed an off-by-1 in `distort'. + * Added `sonar' hack. + * New version of `glplanet' (with stars.) + * Made all hacks exit when you type `q' or `ESC' at them, + and made them obey the WM_DELETE_WINDOW ClientMessage. + * Fixed a nonfatal buffer overrun in lament (note: + lament still doesn't work with MesaGL 3.0: it dies in + lambda_textured_triangle1(), which is Mesa's bug, not + mine.) +Changes since 3.03: * Added an `xscreensaver.spec' file, to make it easier + for other folks to generate RPMs. + * Made the password code work on HPUX in the situation + where: ``enhanced security'' is available; but not + used; but the user typed a password more than 8 + characters long anyway. FTSOHPUX. +Changes since 3.02: * Made locking work when passwd aging is enabled. + * Added support for PAM (Pluggable Authentication + Modules.) It is still turned off by default, though, + since it doesn't seem to work on Solaris 2.6, and has + been behaving erratically on Red Hat 5.1. + * Made each possible authentication method be tried in + turn until one succeeds; this means that Kerberos is + being used, we will first check Kerberos, and if that + fails, will then consult the local password file. + Likewise with PAM. + * Save and restore the bits under the passwd dialog, + to avoid leaving a black rectangle behind when + unlocking is cancelled. +Changes since 3.01: * Not everyone has sys/select.h, sigh... +Changes since 3.00: * Some fixes to `reflect'. + * Configure tweaks. + * Made it log unsuccessful attempts to unlock the screen + to syslog. + * Fixed a bug where `xscreensaver-demo' could be seeing + a different programs list than `xscreensaver' did. +Changes since 2.34: * The xscreensaver daemon no longer links against Motif + or Athena: demo-mode and the preferences panel are no + longer built in to the daemon, but are now handled by + an external program, `xscreensaver-demo'. + (I decided that this, along with the recent addition + of the `.xscreensaver' config file, justified bumping + the version number to 3.00, since this is a fairly + major architectural change.) + * Lines in the `*programs' resource may now begin with + the character "-", meaning "don't run this hack." + In this way, it's possible to disable a hack without + throwing away the information about it (making it + easier to change your mind later.) Eventually the + preferences/demo mode GUI should represent this as a + checkbox or something. + * Fixed a short race condition where it was possible for + xscreensaver to die with a BadWindow error if it was + blanking the screen just as another window was being + deleted. + * Made it possible to disable specific modes in `bsod'. +Changes since 2.33: * Fixed a bug that was making `pipes' generate way too + many valves. Made the viewpoint in `pipes' be selected + randomly instead of always being -10 degrees. + * Fixed a bug in the XSHM code, in the case where the + server supports the XSHM extension but is not the same + machine as the client. + * Made `rd-bomb' default to taking up the whole screen. + * Made it not try to do fading/unfading if no PseudoColor + visuals exist. + * Initial attempt at supporting VT-locking (doesn't work + yet.) + * Eliminated the `captureStdout' resource; now + `captureStderr' controls both streams. + * Added `-capture-stderr' and `-no-capture-stderr' + command-line arguments. + * Added `glplanet' hack. + * When a hack is selected with `xscreensaver-command + -select', that hack will be used until further notice + (until the saver turns off, or another activation + command is issued.) +Changes since 2.32: * Made `xscreensaver-command' print error messages: + the xscreensaver daemon now responds to ClientMessage + events by writing a response message on a window + property, instead of just writing to its stderr. + * Made the ~/.xscreensaver file be automatically reloaded + when the file date changes. + * The password dialog and splash screen no longer depend + on Motif or Athena. This should clear up a number of + focus problems, and is the first step on the path + toward moving all of the Motif/Athena/whatever code + out of the xscreensaver daemon, and into external + processes. + * Don't complain about LessTif 0.86 any more, since the + new password dialog makes that problem go away. + * Configure tweaks for Irix 6.5, SunOS 5.something. + * New `-reflect' option to `distort'. +Changes since 2.31: * Added reading and writing of a ~/.xscreensaver file, + so that the Preferences panel can save its settings. + * New version of `rubik'. + * Added `-select N' argument to `xscreensaver-command'. + * Oops, left out some of the `bubbles3d' files... +Changes since 2.30: * The cursor was invisible in the password dialog. Fixed. + * Made configure warn against MesaGL 2.6. + * Fixed X error at startup when using non-default visual. + * New version of `crystal', `ant', and `atlantis' from + xlockmore. + * New hack, `bubble3d'. + * Added some new modes to `bsod'. +Changes since 2.29: * Changed the order in which -lSM and -lICE are linked + to be after Motif instead of before (Lesstif on Irix + needs this.) +Changes since 2.28: * Work around a bash bug in configure. + * Tweaked HPUX paths again. FTSOHPUX. + * Made configure recommend against LessTif 0.86, due + to a bug in that version that causes a security hole + in the screen locking code. LessTif 0.87 will fix it. + * Made all of the `--with' options to `configure' accept + a directory option as well (so that --with-motif=/FOO + will add -I/FOO/include -L/FOO/lib). I believe this is + the Configure Party Line of how do to such things. + * Fixed a bug where the mouse was left un-grabbed + after the first time the graphics hack was changed + (simplified all of the mouse-grabbing logic.) + * Maybe possibly perhaps made `vidwhacker' really not + leave stray xv windows around. This time for sure. + * Added a new erase mode (random dots fizzling out.) + * Added `-prefs' argument to `xscreensaver-command', + that brings up the Preferences dialog directly (it + seems that nobody ever noticed the `Preferences' button + on the Demo Mode dialog, maybe this will help.) + * Added a splash screen. Turn it off with *splash:false. +Changes since 2.27: * Better macsbug text in `bsod'. + * New version of `distort' with many new modes. + * Plugged a leak in `coral'. + * Tweaked configure for HPUX. + * Removed some compiler warnings. + * More consistent usage of stderr versus stdout. + * More diagnostics should an X error occur. + * Fixed a possible crash in SGI-specific unfading code. +Changes since 2.26: * Improved version of `distort'. + * Made `lament' compile against OpenGL 1.0 (though it + still requires 1.1 to work properly.) + * Updated my email address and home page. +Changes since 2.24: * Improved motion in `rd-bomb'. + * Added XSHM (shared memory extension) support to the + `distort', `interference', `moire', `rd-bomb', and + `swirl' hacks, which speeds them up a bit. + * Added `lament' hack. +Changes since 2.23: * Tweaked the order of the -L options again. + * Cleaned up configure's `--help' message. + * Added `kumppa' hack. + * Smarter maze-solving algorithm in `maze'. + * Took `xlyap' out of the default list of hacks, since + it's just incredibly buggy (and slow.) Maybe someday + someone will fix it... + * Added `distort' hack, but didn't add it to the default + list (yet) because it's still too slow. + * Made the Athena demo dialog look more like the Motif + version; it has a text-entry field now, too. + * Made the Athena password dialog echo asterisks, like + Motif does, instead of using a flyspeck font. + * Some random configure tweaks. + * Added a `timestamp' resource that makes the `-verbose' + messages include the time at which they were printed. +Changes since 2.22: * The fix for SGI's ``scheme'' nonsense broke things, and + let the user's "*background" resource show through. + Fixed it in a different way. +Changes since 2.21: * Added support for the DPMS server extension (Display + Power Management System.) + * Made configure advertize the `--enable-subdir' option a + little more, since that seemed to cause some people + stress. Also, made that directory be built into the + xscreensaver executable, as a hardcoded prefix to + $PATH. (Might help, shouldn't hurt.) + * Made configure prefer the two-arg gettimeofday to the + one-arg version, since AIX doesn't have any prototypes. + * Made it work with Xaw3d (the 3D Athena library.) + * Made `make install' create directories as necessary. + * New version of lmorph from Sverre. + * Added `crystal' and `discreet' hacks from xlockmore. + * Added a new mode to `bsod'. +Changes since 2.20: * Made `xscreensaver-command -time' use different words. + (It now describes the two states as "screen blanked + since..." and "screen non-blanked since..." instead of + "active since..." and "inactive since..." which a lot + of people interpreted as meaning the opposite of what + was intended.) + * Improved some error messages, in the hopes of making + the distinction between the xscreensaver and + xscreensaver-command programs more obvious. + * Rewrote (and reorganized) parts of the xscreensaver and + xscreensaver-command manual pages. + * Renamed xscreensaver's `-lock' command-line option to + be `-lock-mode', to avoid confusion with the `-lock' + option to xscreensaver-command, which does a totally + different thing. + * Removed xscreensaver's `-demo' command-line option for + a similar reason; use `xscreensaver-command -demo' + instead. + * Disabled SGI's ``scheme'' nonsense in a better way than + fully-qualifying the background colors in every single + hack. + * Fixed some other minor cosmetic problems when *sgiMode + is turned on. + * Fixed an X error in `bsod -root' (how ironic...) +Changes since 2.19: * Fixed a bug that caused the mouse to sometimes not be + grabbed properly (meaning the window manager menu could + pop up over the demo-mode display.) + * Fixed a bug that made the stderr output sometimes get + printed twice. + * Fixed a bug that made the demo-mode scrollbar move too + fast. + * Protected against a possible buffer overflow. + * Made `vidwhacker' not leave stray xv windows around. + * New version of `ant' so that Bagley doesn't calve. + * Make configure on AIX get XShm from the right library. +Changes since 2.18: * One file was missing from the tar file. Fixed. +Changes since 2.17: * Oops, atlantis wasn't being built by default. Fixed. + * Added `epicycle' hack. + * Added `interference' hack. + * Added `truchet' hack. + * Added `bsod' hack. + * Added some new modes to `vidwhacker'. +Changes since 2.16: * Added a -window-id argument to most hacks, so that they + can draw on arbitrary externally-provided windows. + * Synched with xlockmore 4.11a01. + * Added `flow' hack. + * Added `atlantis' GL hack. + * Renamed `puzzle' hack to `jigsaw', since xlock already + had a different mode called `puzzle'. + * Made it self-configure properly when Motif 2.1.0 is + being used (requires -lXp now, sigh...) +Changes since 2.15: * Made `flag' able to do XPM images. + * New look for the xscreensaver logo (`xroger'). + * Fixed compilation error on Suns with adjunct passwords. + * Got multi-architecture builds working again. + * Some configure tweaks for building on HPUX and Solaris. + * Fixed bug in decayscreen. + * Fixed typo in passwd.c. + * Made `cynosure' not die when colormap is full. +Changes since 2.14: * Added `cynosure' hack. + * Added `moire2' hack. + * Tweaked `erase.c' some more. + * Made unfading a bit smoother. + * Added `vidwhacker' hack (not installed by default.) + * Added `stairs' hack. + * Split `escher' into `cage' and `moebius', as per + xlockmore. + * Changed subprocess handling to use sigaction() instead + of signal() if it's available (this is necessary for + SCO but should work fine on other systems too.) + * Various other tweaks. +Changes since 2.13: * Better fix for the Motif drag-and-die lossage. + * Put in some kludges to work around a LessTif bug. + * XScreenSaver is known to work with LessTif 0.82 now. + * Made fading work on high-end SGI video hardware. + * Fixed another SGI-specific bug in screen grabbing; + will the madness never cease? + * Fixed another crash in `xlyap'. +Changes since 2.12: * Made `decayscreen' do directions other than down. + * Improved `puzzle'. + * Fixed a crash in `xlyap'. + * Added CDE info to the man page, removed `cde.txt'. + * Configure tweaks for Zippy. + * Turned off the signal handling in `bubbles' because + it was sometimes failing to die. + * Added `hacks/xscreensaver-sgigl.c' to make it possible + to run SGI's ElectroPaint hack (/usr/demos/bin/ep) + with xscreensaver. Finally! + * Fixed a buffer overrun in the locking code that some + wily, malicious cracker must have slipped in. + * Disabled Motif drag-and-drool in the dialog box + buttons, since it's broken in some old versions of + Motif. +Changes since 2.11: * Added `README.debugging'. + * Added `puzzle' hack. + * Added `xlyap' hack. + * Added `default-n' as a visual name, so that one can + have -install on by default, but turn it off for + certain poorly-behaved hacks (like xv.) + * Added support for grabbing frames of external video + (on SGI) to the screen-grabbing hacks (decayscreen, + slidescreen, slip, blitspin, and puzzle.) + * Improved look of tiles in `slidescreen'; fixed its + color allocation problem. +Changes since 2.10: * Tweaked `blitspin', added it to the default list. + * Added `lissie', `mountain', `triangle', `worm', + `rotor', and `ant' from xlockmore. + * Updated `sierpinski', `galaxy', and `lisa'. + * Thickened the lines in `braid' and `lmorph'. + * Updated VMS makefiles. + * Renamed `fract' to `vines'. + * Added `xjack' hack. + * Made a few more hacks use erase.c, and added a few + more wipe styles. + * Fixed compilation problem with Sun's version of OpenGL. + * Added ability to use sigaction() instead of signal() + to work around a SCO kernel bug. +Changes since 2.09: * Fixed colormap bugs in `rd-bomb'; sped up `coral'. + * Configure tweaks for *BSD. +Changes since 2.07: * New hacks `rd-bomb' and `coral'. + * New version of `maze' with some new algorithms. + * New colorized version of `rocks'. + * Fixed a bug in qix on 64-bit machines. + * Fixed a bug in the -time option. + * Fixed a bug in configure related to LessTif. +Changes since 2.06: * Minor header tweaks in windows.c and flag.c. + * Made multi-architecture ($VPATH) builds work properly. + * Merged new GL stuff from xlockmore (rubik, morph3d.) + * Fixed intermittent crashes in `imsmap' and `munch'. + * Added `fadeplot' hack from xlockmore. +Changes since 2.05: * Merged in VMS support from Patrick Moreau. +Changes since 2.04: * Fixed a MIT-SCREEN-SAVER-related crash, and tweaked + configure to detect the extra-random -Xss library. +Changes since 2.03: * HP configure tweaks. Detect and warn about LessTif. + * Fixed low-color behavior of `goop', `pyro', `starfish', + `greynetic', `flame', `halo', and `moire'. +Changes since 2.02: * Fixed flicker in `pipes'. Fixed 3d in `bouboule'. + * Added `munch' hack. + * Added basic dependencies to the Makefile.in files. +Changes since 2.01: * Fixes for compiling with the MIT saver extension. + * Made the yow/fortune program be a configure option. + * Various configure tweaks. +Changes since 2.00: * Added `goop' and `starfish' hacks. + * Added colomap cycling to `halo'. + * Made `attraction' use the new colormap allocator. + * Added better $PATH diagnostics. + * There was a bug in frand! Color selection should be + much improved now. +Changes since 1.34: * Converted to use `configure' instead of `imake'. + * ANSI C is now required. + * Added Kerberos locking support, from Nat Lanza. + * Made the stderr text use overlay planes, if possible. + * Reworked the xlockmore compatibility stuff again. + * Added `gears', `superquadrics', `escher', `pipes', + and `sproingies' hacks (depend on OpenGL.) +Changes since 1.33: * Fixed some bugs, made fading be a little smoother. +Changes since 1.32: * Made it work with multi-headed displays. + * Generalized sub-process management (Unix sucks!) + * Added interactive mouse frobbing to Julia. + * Added (untested) support for HPUX shadow passwords. + * Made normal non-shadow passwords be checked if the + shadow passwords aren't accessible for some reason. +Changes since 1.31: * Removed *colorPrograms and *monoPrograms resources: + made it possible to specify the desired visual on a + per-hack basis. + * Cleaned up / restructured the driver: no more globals. + * Made the Motif and Athena dialogs share more code. + * Probably fixed some Athena colormap-installation bugs. + * Fixed screen grabbing (cmap) on SGI 12-bit PseudoColor. + * Fixed divide-by-zero in bright random colormaps. + * Added an improved version of xlock's `flag' hack. + * Made unfading work better, and not flicker on SGIs. + * Added `sphere', `forest', `lisa' hacks from xlockmore. + * Added (untested) support for SunOS Adjunct passwords. +Changes since 1.30: * Improved colors and colormap cycling of many hacks. + * Cleaned up xlockmore compatibility layer. + * Made `blitspin' able to grab an image off the screen. + * Ported `swirl' and `bouboule' hacks from xlockmore. + * Made the driver more careful about not leaving bits on + the screen, or allowing other windows to raise + themselves: it now re-blanks the screen every so often. + * Added `-time' option to `xscreensaver-command'. + * Improved SGI screen-grabbing some more: now it can grab + TrueColor screens into PseudoColor windows and have the + colors still come out semi-reasonably. +Changes since 1.29: * Made `slidescreen' and `decayscreen' work better on + SGIs when windows of different visuals are present, by + using the XReadDisplay() extension to get a true 24-bit + image out of the frame buffer. + * Made `noseguy' be in color, if compiled with XPM. + * Ported `braid', `drift', `fract', `galaxy', `grav', + `ifs', `julia', `laser', `lightning', `penrose', + `sierpinski', `slip', `spiral', and `strange' hacks + from xlockmore. + * Merged `hopalong' hack with a more recent version. + * Added `cde.txt'. +Changes since 1.27: * Added `deco', `moire', and `kaleidescope' hacks. + * Merged in support for non-Motif locking and demo mode. + * Made `blitspin' and `bubbles' work in TrueColor. + * Fixed a stupid bug I introduced in `imsmap'. + * Added `poly' and `gravity' options to `qix'. +Changes since 1.26: * Added support for SGI SCREEN_SAVER extension. + * Made `fade' and `unfade' work on 8-bit SGIs. + * Made the dialog boxes more Motify. + * Added `bubbles' hack. +Changes since 1.25: * Added `lmorph' hack. + * Added viscosity and mouse-control to attraction. + * Fixed possible bad color choices in qix and attraction. + * Added ramp-mode to halo. + * Added a new RNG, which is faster and more portable + than using the RNG in libc. + * Made locking work on SCO. + * Various other minor tweaks that I don't remember. +Changes since 1.24: * Made it capture the stdout/stderr of its subprocesses + and present them on the screensaver window itself. + * Made demo mode work correctly with non-default visuals + and color maps, instead of always using the defaults. + * Added -visual argument to all included screenhacks. + * Support for the R6 MIT-SCREEN-SAVER server extension. + * Made the demo mode list scroll properly. + * Added `pedal' hack. +Changes since 1.23: * Fixed some private-colormap oddities in slidescreen, + decayscreen, and xroger. Fixed apparent conservation- + of-mass problem in pyro; made the shrapnel round. +Changes since 1.22: * Minor tweaks for IRIX5; fixed locking race condition. +Changes since 1.21: * Minor tweaks for X11R6. + * Fixes for non-default visuals. +Changes since 1.20: * Fixed bug in color blitspin; added default image. + * Added diagnostics to noseguy. Fixed off-by-one + error in flame. Added some missing casts. +Changes since 1.18: * Added `flame' hack. + * Fixed a minor Motif dialog text field bug. + * Fixed yet another XPointer-not-defined-in-R4 bug. +Changes since 1.17: * Added support for shadow password files. + * Fixed some Motif-related locking bugs. + * Added diagnostics when locking is disabled. + * Made blitspin able to use the XPM library. + * Added `decayscreen' hack. +Changes since 1.16: * Added `halo' hack. +Changes since 1.15: * Portability fixes. +Changes since 1.14: * Broke the driver up into more source files. + * Moved the hacks into their own directory. + * Made all `time' parameters accept the 00:00:00 syntax, + so that even the parameters which are normally read as + minutes can be specified in seconds. + * Added colormap cycling to `imsmap'. + * Made hyper work with K&R compilers. +Changes since 1.13: * Added `orbit' option to `attraction' hack. + * Added `lock-timeout' option. + * Cleaned up options of `maze' hack. +Changes since 1.8: * Added demo mode, and locking. + * Added `maze' hack. + * Added `norotate' option to `rocks' hack. +Changes since 1.4: * Works when run from XDM before anyone logs in. + * Sped up `imsmap'. + * Can use `xv' as a slideshow without using up colormap + entries while the screen is not blanked. + * Fixed a BadDrawable error in non-XIdle mode. + * Added `blitspin' and `imsmap'. +Changes since 1.0: * Current list of included hacks is now: qix, helix, + rorschach, attraction, greynetic, rocks, pyro, + hopalong, and noseguy. diff --git a/README.VMS b/README.VMS new file mode 100644 index 00000000..d1903443 --- /dev/null +++ b/README.VMS @@ -0,0 +1,57 @@ +OpenVMS port of Xscreensavser version 2.10 October 1997 +========================================== + +Xscreensaver distribution can be found in 3 subdirectories: + +[.DRIVER] The Xscreensaver and Xscreensaver-command programs. +[.HACKS] Graphic demos ,can be run either through the xscreensaver program + or standalone. +[.UTILS] A small libraries of various utilities. + +This port has been tested with VAX VMS 6.1 (compiled with DEC 5 5.0 and +Motif 1.2) and AXP VMS 6.2 (compiled with DEC C 5.0 and Motif 1.2-4). + +To rebuild, you need to rebuild [.UTILS] directory first and create the +object library (look at the end of COMPILE*.COM procedure). + +You can now build the [.HACKS] directory and the [.DRIVER] directory. + +A one-step build is now available via the MAKEVMS.COM script. + +WARNING : before building [.HACKS], you may need to correct some of the +DECwindows bitmap files. Some files are bogus !! (they have a long line of +null chars at the end). These files are under +SYS$COMMON:[DECW$INCLUDE.BITMAPS] directory: + +STIPPLE.XBM +HLINES2.XBM +LIGHT_GRAY.XBM +ROOT_WEAVES.XBM +VLINES2.XBM + +These files are all used by Greynetic demo. + +Nota: link procedure automagically select appropriate X and Motif Libraries +(X11R4/Motif 1.1 - X11R5/Motif 1.2). + +The SETUP.COM procedure gives you a definition of all DCL foreign command +symbols needed to run Xscreensaver and all the graphic hacks. You need to +modify this procedure if you install these programs in another directory tree. + +You can easily add new graphic demos without recompiling Xscreensaver. You just +need to add them in resource file XSCREENSAVER.DAT. This file (originally +present in [.DRIVER] directory ) can be installed under your SYS$LOGIN +directory for a per-user customization basis. You can also install it under +the system-wide user resource directory SYS$COMMON:[DECW$DEFAULT.USER] +(with (W:RE) protections). The new graphics hack must be run in root-window +mode to be accepted by Xscreensaver. + +The graphic demos are spawn into subprocess created by the system() call (in +the Unix version the execvp() call is used). + +The VMS passord checking programs were picked up in the Xlock distribution. + +Enjoy, + +Patrick MOREAU - CENA/Athis-Mons - FRANCE (pmoreau@cena.dgac.fr) + (moreau_p@decus.decus.fr) diff --git a/README.hacking b/README.hacking new file mode 100644 index 00000000..718cae2b --- /dev/null +++ b/README.hacking @@ -0,0 +1,180 @@ + +========================================================================== + + Writing new XScreenSaver modules + +========================================================================== + +Any program that can be made to render on an X window created by another +process can be used as a screen saver. Just get the window ID out of +$XSCREENSAVER_WINDOW, draw on that, and you're done. + +In theory, you can write a screen saver in any language you like. In +practice, however, languages other than C or C++ tend not to allow you to +draw to windows that they did not create themselves. Unfortunately, this +means that if you want to write a screen saver, you must write it in C. + +Given that you're going to be writing in C, you might as well take +advantage of the various utility functions that I have written to make +that easier. Writing a new screen saver in C using the frameworks +included with xscreensaver simplifies things enormously. + +Generally, the best way to learn how to do something is to find a similar +program, and play around with it until you understand it. Another +approach is to not worry about understanding it, but to just hack it out. +Either way, your best bet is probably to start with one of the existing +xscreensaver demos, included in the "hacks/" directory, rename the file, +and edit it until it does what you want. + +The "Greynetic" and "Deluxe" hacks are probably good ones to start with, +since they are so very simple. For OpenGL programs, "DangerBall" is a +good example. + + +========================================================================== +Requirements for inclusion with the XScreenSaver collection +========================================================================== + + If you come up with anything, send it to me! If it's good, I'd love to + include it in the xscreensaver distribution. However, there are a few + requirements for me to distribute it: + + - Write in portable ANSI C. No C++. No nonstandard libraries. + + - Write a .man page describing all command-line options. + + - Write an .xml file describing the graphical configuration dialog box. + + - Include a BSD-like copyright/license notice at the top of each source + file (preferably, just use the one from "screenhack.h", and include + your name and the current year). The GNU GPL is not compatible with + the rest of XScreenSaver. + + +========================================================================== +The XScreenSaver API +========================================================================== + + - Start with #include "screenhack.h" + + - Define 2 global variables: + + yoursavername_defaults -- Default values for the resources you use. + yoursavername_options -- The command-line options you accept. + + - Define 5 functions: + + yoursavername_init -- Return an object holding your global state. + yoursavername_draw -- Draw a single frame, quickly. + yoursavername_free -- Free everything you've allocated. + yoursavername_reshape -- Called when the window is resized. + yoursavername_event -- Called when a keyboard or mouse event happens. + + The "event" function will only be called when running in a window + (not as a screen saver). The "reshape" event will be called when the + window size changes, or (as a screen saver) when the display size + changes as a result of a RANDR event (e.g., plugging in a new monitor). + + It's ok for both the "event" and "resize" functions to do nothing. + + - All other functions should be static. + + - The last line of the file should be + XSCREENSAVER_MODULE ("YourSaverName", yoursavername) + + - Finally, edit the Makefile to add a rule for your program. + Just cut-and-paste one of the existing rules. + + Your "draw" must not run for more than a fraction of a second without + returning. This means "don't call usleep()". Everything has to be a + state machine. + + You may not store global state in global variables, or in function-local + static variables. All of your runtime state must be encapsulted in the + "state" object created by your "init" function. If you use global or + static variables, your screen saver will not work properly on MacOS. + + Do not call XSync() or XFlush(). If you think you need to do that, it + probably means that you are you are relying on the speed of the graphics + card for timing, which probably means that your "draw" function is + taking too long. + + +========================================================================== +The XLockMore API +========================================================================== + + Some of the display modes that come with xscreensaver were ported from + XLock, and so, for historical reasons, they follow a slightly different + programming convention. For newly-written Xlib programs, you'd be + better off following the pattern used in hacks like "Deluxe" than in + hacks like "Flag". The XLockMore ones are the ones that begin with + "#ifdef STANDALONE" and #include "xlockmore.h". + + But, all OpenGL screen savers have to follow the XLockMore API. + + The XLockMore API is similar to the XScreenSaver API, in that you define + (roughly) the same set of functions, but the naming conventions are + slightly different. Instead of "hackname_init", it's "init_hackname", + and it should be preceeded with the pseudo-declaration ENTRYPOINT. + + One annoying mis-feature of the XLockMore API is that it *requires* you + to make use of global variables for two things: first, for each of your + command line options; and second, for an array that holds your global + state objects. These are the only exceptions to the "never use global + variables" rule. + + +========================================================================== +Programming Tips +========================================================================== + + - Your screen saver should look reasonable at 20-30 frames per second. + That is, do not assume that your "draw" function will be called more + than 20 times a second. Even if you return a smaller requested delay + than that, you might not get it. Likewise, if your "draw" function + takes longer than 1/20th of a second to run, your screen saver may be + consuming too much CPU. + + - Don't make assumptions about the depth of the display, or whether it + is colormapped. You must allocate all your colors explicitly: do not + assume you can construct an RGB value and use that as a pixel value + directly. Use the utility routines provided by "utils/colors.h" to + simplify color allocation. + + - It is better to eliminate flicker by double-buffering to a Pixmap + than by erasing and re-drawing objects. Do not use drawing tricks + involving XOR. + + - If you use double-buffering, have a resource to turn it off. (MacOS + has double-buffering built in, so you'd be triple-buffering.) + + - Understand the differences between Pixmaps and XImages, and keep in + mind which operations are happening in client memory and which are in + server memory, and which cause latency due to server round-trips. + Sometimes using the Shared Memory extension can be helpful, but + probably not as often as you might think. + + - On modern machines, OpenGL will always run faster than Xlib. It's + also more portable. Consider writing in OpenGL whenever possible. + + +========================================================================== +The MacOS X Port +========================================================================== + + Though XScreenSaver started its life as an X11 program, it also now runs + on MacOS X. If you do your development on an X11 system, and follow the + usual XScreenSaver APIs, you shouldn't need to do anything special for + it to also work on MacOS. + + The preprocessor macro HAVE_COCOA will be defined when being compiled in + a MacOS (Cocoa/Quartz) environment, and will be undefined when compiling + against "real" Xlib. + + To compile on MacOS, use the XCode project included in the source + distribution. You shouldn't need to have X11 installed, and shouldn't + need to run "configure" first. MacOS 10.4.0 and XCode 3.1 or newer are + required. + +========================================================================== diff --git a/aclocal.m4 b/aclocal.m4 new file mode 100644 index 00000000..ef93b539 --- /dev/null +++ b/aclocal.m4 @@ -0,0 +1,443 @@ +dnl aclocal.m4 generated automatically by aclocal 1.4-p5 + +dnl Copyright (C) 1994, 1995-8, 1999, 2001 Free Software Foundation, Inc. +dnl This file is free software; the Free Software Foundation +dnl gives unlimited permission to copy and/or distribute it, +dnl with or without modifications, as long as this notice is preserved. + +dnl This program is distributed in the hope that it will be useful, +dnl but WITHOUT ANY WARRANTY, to the extent permitted by law; without +dnl even the implied warranty of MERCHANTABILITY or FITNESS FOR A +dnl PARTICULAR PURPOSE. + + +dnl AC_PROG_INTLTOOL([MINIMUM-VERSION]) +# serial 1 AC_PROG_INTLTOOL +AC_DEFUN(AC_PROG_INTLTOOL, +[ + +if test -n "$1"; then + AC_MSG_CHECKING(for intltool >= $1) + + INTLTOOL_REQUIRED_VERSION_AS_INT=`echo $1 | awk -F. '{ printf "%d", $[1] * 100 + $[2]; }'` + INTLTOOL_APPLIED_VERSION=`awk -F\" '/\\$VERSION / { printf $[2]; }' < intltool-update.in` + changequote({{,}}) + INTLTOOL_APPLIED_VERSION_AS_INT=`awk -F\" '/\\$VERSION / { split(${{2}}, VERSION, "."); printf "%d\n", VERSION[1] * 100 + VERSION[2];}' < intltool-update.in` + changequote([,]) + + if test "$INTLTOOL_APPLIED_VERSION_AS_INT" -ge "$INTLTOOL_REQUIRED_VERSION_AS_INT"; then + AC_MSG_RESULT([$INTLTOOL_APPLIED_VERSION found]) + else + AC_MSG_RESULT([$INTLTOOL_APPLIED_VERSION found. Your intltool is too old. You need intltool $1 or later.]) + exit 1 + fi +fi + + INTLTOOL_DESKTOP_RULE='%.desktop: %.desktop.in $(INTLTOOL_MERGE) $(wildcard $(top_srcdir)/po/*.po) ; $(INTLTOOL_MERGE) $(top_srcdir)/po $< [$]@ -d -u -c $(top_builddir)/po/.intltool-merge-cache' +INTLTOOL_DIRECTORY_RULE='%.directory: %.directory.in $(INTLTOOL_MERGE) $(wildcard $(top_srcdir)/po/*.po) ; $(INTLTOOL_MERGE) $(top_srcdir)/po $< [$]@ -d -u -c $(top_builddir)/po/.intltool-merge-cache' + INTLTOOL_KEYS_RULE='%.keys: %.keys.in $(INTLTOOL_MERGE) $(wildcard $(top_srcdir)/po/*.po) ; $(INTLTOOL_MERGE) $(top_srcdir)/po $< [$]@ -k -u -c $(top_builddir)/po/.intltool-merge-cache' + INTLTOOL_OAF_RULE='%.oaf: %.oaf.in $(INTLTOOL_MERGE) $(wildcard $(top_srcdir)/po/*.po) ; $(INTLTOOL_MERGE) $(top_srcdir)/po $< [$]@ -o -p' + INTLTOOL_PONG_RULE='%.pong: %.pong.in $(INTLTOOL_MERGE) $(wildcard $(top_srcdir)/po/*.po) ; $(INTLTOOL_MERGE) $(top_srcdir)/po $< [$]@ -x -u -c $(top_builddir)/po/.intltool-merge-cache' + INTLTOOL_SERVER_RULE='%.server: %.server.in $(INTLTOOL_MERGE) $(wildcard $(top_srcdir)/po/*.po) ; $(INTLTOOL_MERGE) $(top_srcdir)/po $< [$]@ -o -u -c $(top_builddir)/po/.intltool-merge-cache' + INTLTOOL_SHEET_RULE='%.sheet: %.sheet.in $(INTLTOOL_MERGE) $(wildcard $(top_srcdir)/po/*.po) ; $(INTLTOOL_MERGE) $(top_srcdir)/po $< [$]@ -x -u -c $(top_builddir)/po/.intltool-merge-cache' +INTLTOOL_SOUNDLIST_RULE='%.soundlist: %.soundlist.in $(INTLTOOL_MERGE) $(wildcard $(top_srcdir)/po/*.po) ; $(INTLTOOL_MERGE) $(top_srcdir)/po $< [$]@ -d -u -c $(top_builddir)/po/.intltool-merge-cache' + INTLTOOL_UI_RULE='%.ui: %.ui.in $(INTLTOOL_MERGE) $(wildcard $(top_srcdir)/po/*.po) ; $(INTLTOOL_MERGE) $(top_srcdir)/po $< [$]@ -x -u -c $(top_builddir)/po/.intltool-merge-cache' + INTLTOOL_XML_RULE='%.xml: %.xml.in $(INTLTOOL_MERGE) $(wildcard $(top_srcdir)/po/*.po) ; $(INTLTOOL_MERGE) $(top_srcdir)/po $< [$]@ -x -u -c $(top_builddir)/po/.intltool-merge-cache' + INTLTOOL_CAVES_RULE='%.caves: %.caves.in $(INTLTOOL_MERGE) $(wildcard $(top_srcdir)/po/*.po) ; $(INTLTOOL_MERGE) $(top_srcdir)/po $< [$]@ -d -u -c $(top_builddir)/po/.intltool-merge-cache' + +AC_SUBST(INTLTOOL_DESKTOP_RULE) +AC_SUBST(INTLTOOL_DIRECTORY_RULE) +AC_SUBST(INTLTOOL_KEYS_RULE) +AC_SUBST(INTLTOOL_OAF_RULE) +AC_SUBST(INTLTOOL_PONG_RULE) +AC_SUBST(INTLTOOL_SERVER_RULE) +AC_SUBST(INTLTOOL_SHEET_RULE) +AC_SUBST(INTLTOOL_SOUNDLIST_RULE) +AC_SUBST(INTLTOOL_UI_RULE) +AC_SUBST(INTLTOOL_XML_RULE) +AC_SUBST(INTLTOOL_CAVES_RULE) + +# Use the tools built into the package, not the ones that are installed. + +INTLTOOL_EXTRACT='$(top_builddir)/intltool-extract' +INTLTOOL_MERGE='$(top_builddir)/intltool-merge' +INTLTOOL_UPDATE='$(top_builddir)/intltool-update' + +AC_SUBST(INTLTOOL_EXTRACT) +AC_SUBST(INTLTOOL_MERGE) +AC_SUBST(INTLTOOL_UPDATE) + +AC_PATH_PROG(INTLTOOL_PERL, perl) +if test -z "$INTLTOOL_PERL"; then + AC_MSG_ERROR([perl not found; required for intltool]) +fi +if test -z "`$INTLTOOL_PERL -v | fgrep '5.' 2> /dev/null`"; then + AC_MSG_ERROR([perl 5.x required for intltool]) +fi + +# Remove file type tags (using []) from po/POTFILES. + +ifdef([AC_DIVERSION_ICMDS],[ + AC_DIVERT_PUSH(AC_DIVERSION_ICMDS) + changequote(,) + mv -f po/POTFILES po/POTFILES.tmp + sed -e 's/\[.*\] *//' < po/POTFILES.tmp > po/POTFILES + rm -f po/POTFILES.tmp + changequote([,]) + AC_DIVERT_POP() +],[ + ifdef([AC_CONFIG_COMMANDS_PRE],[ + AC_CONFIG_COMMANDS_PRE([ + changequote(,) + mv -f po/POTFILES po/POTFILES.tmp + sed -e 's/\[.*\] *//' < po/POTFILES.tmp > po/POTFILES + rm -f po/POTFILES.tmp + changequote([,]) + ]) + ]) +]) + +# Manually sed perl in so people don't have to put the intltool scripts in AC_OUTPUT. + +AC_OUTPUT_COMMANDS([ + +sed -e "s:@INTLTOOL_PERL@:${INTLTOOL_PERL}:;" < ${srcdir}/intltool-extract.in > intltool-extract.out +if cmp -s intltool-extract intltool-extract.out 2>/dev/null; then + rm -f intltool-extract.out +else + mv -f intltool-extract.out intltool-extract +fi +chmod ugo+x intltool-extract +chmod u+w intltool-extract + +sed -e "s:@INTLTOOL_PERL@:${INTLTOOL_PERL}:;" < ${srcdir}/intltool-merge.in > intltool-merge.out +if cmp -s intltool-merge intltool-merge.out 2>/dev/null; then + rm -f intltool-merge.out +else + mv -f intltool-merge.out intltool-merge +fi +chmod ugo+x intltool-merge +chmod u+w intltool-merge + +sed -e "s:@INTLTOOL_PERL@:${INTLTOOL_PERL}:;" < ${srcdir}/intltool-update.in > intltool-update.out +if cmp -s intltool-update intltool-update.out 2>/dev/null; then + rm -f intltool-update.out +else + mv -f intltool-update.out intltool-update +fi +chmod ugo+x intltool-update +chmod u+w intltool-update + +], INTLTOOL_PERL=${INTLTOOL_PERL}) + +]) + +# Macro to add for using GNU gettext. +# Ulrich Drepper , 1995. +# +# Modified to never use included libintl. +# Owen Taylor , 12/15/1998 +# +# +# This file can be copied and used freely without restrictions. It can +# be used in projects which are not available under the GNU Public License +# but which still want to provide support for the GNU gettext functionality. +# Please note that the actual code is *not* freely available. +# +# +# If you make changes to this file, you MUST update the copy in +# acinclude.m4. [ aclocal dies on duplicate macros, so if +# we run 'aclocal -I macros/' then we'll run into problems +# once we've installed glib-gettext.m4 :-( ] +# + +# serial 5 + +AC_DEFUN(AM_GLIB_WITH_NLS, + dnl NLS is obligatory + [USE_NLS=yes + AC_SUBST(USE_NLS) + + dnl Figure out what method + nls_cv_force_use_gnu_gettext="no" + + nls_cv_use_gnu_gettext="$nls_cv_force_use_gnu_gettext" + if test "$nls_cv_force_use_gnu_gettext" != "yes"; then + dnl User does not insist on using GNU NLS library. Figure out what + dnl to use. If gettext or catgets are available (in this order) we + dnl use this. Else we have to fall back to GNU NLS library. + dnl catgets is only used if permitted by option --with-catgets. + nls_cv_header_intl= + nls_cv_header_libgt= + CATOBJEXT=NONE + + AC_CHECK_HEADER(libintl.h, + [AC_CACHE_CHECK([for dgettext in libc], gt_cv_func_dgettext_libc, + [AC_TRY_LINK([#include ], [return (int) dgettext ("","")], + gt_cv_func_dgettext_libc=yes, gt_cv_func_dgettext_libc=no)]) + + if test "$gt_cv_func_dgettext_libc" != "yes"; then + AC_CHECK_LIB(intl, bindtextdomain, + [AC_CACHE_CHECK([for dgettext in libintl], + gt_cv_func_dgettext_libintl, + [AC_CHECK_LIB(intl, dgettext, + gt_cv_func_dgettext_libintl=yes, + gt_cv_func_dgettext_libintl=no)], + gt_cv_func_dgettext_libintl=no)]) + fi + + if test "$gt_cv_func_dgettext_libintl" = "yes"; then + LIBS="$LIBS -lintl"; + fi + + if test "$gt_cv_func_dgettext_libc" = "yes" \ + || test "$gt_cv_func_dgettext_libintl" = "yes"; then + AC_DEFINE(HAVE_GETTEXT,1, + [Define if the GNU gettext() function is already present or preinstalled.]) + AM_PATH_PROG_WITH_TEST(MSGFMT, msgfmt, + [test -z "`$ac_dir/$ac_word -h 2>&1 | grep 'dv '`"], no)dnl + if test "$MSGFMT" != "no"; then + AC_CHECK_FUNCS(dcgettext) + AC_PATH_PROG(GMSGFMT, gmsgfmt, $MSGFMT) + AM_PATH_PROG_WITH_TEST(XGETTEXT, xgettext, + [test -z "`$ac_dir/$ac_word -h 2>&1 | grep '(HELP)'`"], :) + AC_TRY_LINK(, [extern int _nl_msg_cat_cntr; + return _nl_msg_cat_cntr], + [CATOBJEXT=.gmo + DATADIRNAME=share], + [CATOBJEXT=.mo + DATADIRNAME=lib]) + INSTOBJEXT=.mo + fi + fi + + # Added by Martin Baulig 12/15/98 for libc5 systems + if test "$gt_cv_func_dgettext_libc" != "yes" \ + && test "$gt_cv_func_dgettext_libintl" = "yes"; then + INTLLIBS=-lintl + LIBS=`echo $LIBS | sed -e 's/-lintl//'` + fi + ]) + + if test "$CATOBJEXT" = "NONE"; then + dnl Neither gettext nor catgets in included in the C library. + dnl Fall back on GNU gettext library. + nls_cv_use_gnu_gettext=yes + fi + fi + + if test "$nls_cv_use_gnu_gettext" != "yes"; then + AC_DEFINE(ENABLE_NLS, 1, + [always defined to indicate that i18n is enabled]) + else + dnl Unset this variable since we use the non-zero value as a flag. + CATOBJEXT= + fi + + dnl Test whether we really found GNU xgettext. + if test "$XGETTEXT" != ":"; then + dnl If it is no GNU xgettext we define it as : so that the + dnl Makefiles still can work. + if $XGETTEXT --omit-header /dev/null 2> /dev/null; then + : ; + else + AC_MSG_RESULT( + [found xgettext program is not GNU xgettext; ignore it]) + XGETTEXT=":" + fi + fi + + # We need to process the po/ directory. + POSUB=po + + AC_OUTPUT_COMMANDS( + [case "$CONFIG_FILES" in *po/Makefile.in*) + rm -f po/stamp-it po/stamp-it.tmp + > po/stamp-it.tmp + sed -e "/POTFILES =/r po/POTFILES" po/Makefile.in > po/Makefile + mv po/stamp-it.tmp po/stamp-it + esac]) + + dnl These rules are solely for the distribution goal. While doing this + dnl we only have to keep exactly one list of the available catalogs + dnl in configure.in. + for lang in $ALL_LINGUAS; do + GMOFILES="$GMOFILES $lang.gmo" + POFILES="$POFILES $lang.po" + done + + dnl Make all variables we use known to autoconf. + AC_SUBST(CATALOGS) + AC_SUBST(CATOBJEXT) + AC_SUBST(DATADIRNAME) + AC_SUBST(GMOFILES) + AC_SUBST(INSTOBJEXT) + AC_SUBST(INTLDEPS) + AC_SUBST(INTLLIBS) + AC_SUBST(INTLOBJS) + AC_SUBST(POFILES) + AC_SUBST(POSUB) + ]) + +AC_DEFUN(AM_GLIB_GNU_GETTEXT, + [AC_REQUIRE([AC_PROG_MAKE_SET])dnl + AC_REQUIRE([AC_PROG_CC])dnl + AC_REQUIRE([AC_PROG_RANLIB])dnl + AC_REQUIRE([AC_HEADER_STDC])dnl + AC_REQUIRE([AC_C_CONST])dnl + AC_REQUIRE([AC_C_INLINE])dnl + AC_REQUIRE([AC_TYPE_OFF_T])dnl + AC_REQUIRE([AC_TYPE_SIZE_T])dnl + AC_REQUIRE([AC_FUNC_ALLOCA])dnl + AC_REQUIRE([AC_FUNC_MMAP])dnl + + AC_CHECK_HEADERS([argz.h limits.h locale.h nl_types.h malloc.h string.h \ +unistd.h sys/param.h]) + AC_CHECK_FUNCS([getcwd munmap putenv setenv setlocale strchr strcasecmp \ +strdup __argz_count __argz_stringify __argz_next]) + + AM_LC_MESSAGES + AM_GLIB_WITH_NLS + + if test "x$CATOBJEXT" != "x"; then + if test "x$ALL_LINGUAS" = "x"; then + LINGUAS= + else + AC_MSG_CHECKING(for catalogs to be installed) + NEW_LINGUAS= + for lang in ${LINGUAS=$ALL_LINGUAS}; do + case "$ALL_LINGUAS" in + *$lang*) NEW_LINGUAS="$NEW_LINGUAS $lang" ;; + esac + done + LINGUAS=$NEW_LINGUAS + AC_MSG_RESULT($LINGUAS) + fi + + dnl Construct list of names of catalog files to be constructed. + if test -n "$LINGUAS"; then + for lang in $LINGUAS; do CATALOGS="$CATALOGS $lang$CATOBJEXT"; done + fi + fi + + dnl Determine which catalog format we have (if any is needed) + dnl For now we know about two different formats: + dnl Linux libc-5 and the normal X/Open format + test -d po || mkdir po + if test "$CATOBJEXT" = ".cat"; then + AC_CHECK_HEADER(linux/version.h, msgformat=linux, msgformat=xopen) + + dnl Transform the SED scripts while copying because some dumb SEDs + dnl cannot handle comments. + sed -e '/^#/d' $srcdir/po/$msgformat-msg.sed > po/po2msg.sed + fi + + dnl If the AC_CONFIG_AUX_DIR macro for autoconf is used we possibly + dnl find the mkinstalldirs script in another subdir but ($top_srcdir). + dnl Try to locate is. + MKINSTALLDIRS= +# +# jwz: fuck this! it puts hardcoded pathnames into the generated Makefiles! +# +# if test -n "$ac_aux_dir"; then +# MKINSTALLDIRS="$ac_aux_dir/mkinstalldirs" +# fi + if test -z "$MKINSTALLDIRS"; then + MKINSTALLDIRS="\$(top_srcdir)/mkinstalldirs" + fi + + # jwz: you know what, screw it. Let's just use the version that I + # already computed in configure.in, instead of this version that came + # with the i18n crud, ok? + MKINSTALLDIRS="$INSTALL_DIRS" + + + AC_SUBST(MKINSTALLDIRS) + + dnl Generate list of files to be processed by xgettext which will + dnl be included in po/Makefile. + test -d po || mkdir po + if test "x$srcdir" != "x."; then + if test "x`echo $srcdir | sed 's@/.*@@'`" = "x"; then + posrcprefix="$srcdir/" + else + posrcprefix="../$srcdir/" + fi + else + posrcprefix="../" + fi + rm -f po/POTFILES + sed -e "/^#/d" -e "/^\$/d" -e "s,.*, $posrcprefix& \\\\," -e "\$s/\(.*\) \\\\/\1/" \ + < $srcdir/po/POTFILES.in > po/POTFILES + ]) + + +# Search path for a program which passes the given test. +# Ulrich Drepper , 1996. +# +# This file can be copied and used freely without restrictions. It can +# be used in projects which are not available under the GNU Public License +# but which still want to provide support for the GNU gettext functionality. +# Please note that the actual code is *not* freely available. + +# serial 1 + +dnl AM_PATH_PROG_WITH_TEST(VARIABLE, PROG-TO-CHECK-FOR, +dnl TEST-PERFORMED-ON-FOUND_PROGRAM [, VALUE-IF-NOT-FOUND [, PATH]]) +AC_DEFUN([AM_PATH_PROG_WITH_TEST], +[# Extract the first word of "$2", so it can be a program name with args. +set dummy $2; ac_word=[$]2 +AC_MSG_CHECKING([for $ac_word]) +AC_CACHE_VAL(ac_cv_path_$1, +[case "[$]$1" in + /*) + ac_cv_path_$1="[$]$1" # Let the user override the test with a path. + ;; + *) + IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS="${IFS}:" + for ac_dir in ifelse([$5], , $PATH, [$5]); do + test -z "$ac_dir" && ac_dir=. + if test -f $ac_dir/$ac_word; then + if [$3]; then + ac_cv_path_$1="$ac_dir/$ac_word" + break + fi + fi + done + IFS="$ac_save_ifs" +dnl If no 4th arg is given, leave the cache variable unset, +dnl so AC_PATH_PROGS will keep looking. +ifelse([$4], , , [ test -z "[$]ac_cv_path_$1" && ac_cv_path_$1="$4" +])dnl + ;; +esac])dnl +$1="$ac_cv_path_$1" +if test -n "[$]$1"; then + AC_MSG_RESULT([$]$1) +else + AC_MSG_RESULT(no) +fi +AC_SUBST($1)dnl +]) + +# Check whether LC_MESSAGES is available in . +# Ulrich Drepper , 1995. +# +# This file can be copied and used freely without restrictions. It can +# be used in projects which are not available under the GNU Public License +# but which still want to provide support for the GNU gettext functionality. +# Please note that the actual code is *not* freely available. + +# serial 2 + +AC_DEFUN([AM_LC_MESSAGES], + [if test $ac_cv_header_locale_h = yes; then + AC_CACHE_CHECK([for LC_MESSAGES], am_cv_val_LC_MESSAGES, + [AC_TRY_LINK([#include ], [return LC_MESSAGES], + am_cv_val_LC_MESSAGES=yes, am_cv_val_LC_MESSAGES=no)]) + if test $am_cv_val_LC_MESSAGES = yes; then + AC_DEFINE(HAVE_LC_MESSAGES, 1, + [Define if your file defines LC_MESSAGES.]) + fi + fi]) + diff --git a/config.guess b/config.guess new file mode 100755 index 00000000..951383e3 --- /dev/null +++ b/config.guess @@ -0,0 +1,1516 @@ +#! /bin/sh +# Attempt to guess a canonical system name. +# Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, +# 2000, 2001, 2002, 2003, 2004, 2005, 2006 Free Software Foundation, +# Inc. + +timestamp='2007-05-17' + +# This file is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA +# 02110-1301, USA. +# +# As a special exception to the GNU General Public License, if you +# distribute this file as part of a program that contains a +# configuration script generated by Autoconf, you may include it under +# the same distribution terms that you use for the rest of that program. + + +# Originally written by Per Bothner . +# Please send patches to . Submit a context +# diff and a properly formatted ChangeLog entry. +# +# This script attempts to guess a canonical system name similar to +# config.sub. If it succeeds, it prints the system name on stdout, and +# exits with 0. Otherwise, it exits with 1. +# +# The plan is that this can be called by configure scripts if you +# don't specify an explicit build system type. + +me=`echo "$0" | sed -e 's,.*/,,'` + +usage="\ +Usage: $0 [OPTION] + +Output the configuration name of the system \`$me' is run on. + +Operation modes: + -h, --help print this help, then exit + -t, --time-stamp print date of last modification, then exit + -v, --version print version number, then exit + +Report bugs and patches to ." + +version="\ +GNU config.guess ($timestamp) + +Originally written by Per Bothner. +Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005 +Free Software Foundation, Inc. + +This is free software; see the source for copying conditions. There is NO +warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE." + +help=" +Try \`$me --help' for more information." + +# Parse command line +while test $# -gt 0 ; do + case $1 in + --time-stamp | --time* | -t ) + echo "$timestamp" ; exit ;; + --version | -v ) + echo "$version" ; exit ;; + --help | --h* | -h ) + echo "$usage"; exit ;; + -- ) # Stop option processing + shift; break ;; + - ) # Use stdin as input. + break ;; + -* ) + echo "$me: invalid option $1$help" >&2 + exit 1 ;; + * ) + break ;; + esac +done + +if test $# != 0; then + echo "$me: too many arguments$help" >&2 + exit 1 +fi + +trap 'exit 1' 1 2 15 + +# CC_FOR_BUILD -- compiler used by this script. Note that the use of a +# compiler to aid in system detection is discouraged as it requires +# temporary files to be created and, as you can see below, it is a +# headache to deal with in a portable fashion. + +# Historically, `CC_FOR_BUILD' used to be named `HOST_CC'. We still +# use `HOST_CC' if defined, but it is deprecated. + +# Portable tmp directory creation inspired by the Autoconf team. + +set_cc_for_build=' +trap "exitcode=\$?; (rm -f \$tmpfiles 2>/dev/null; rmdir \$tmp 2>/dev/null) && exit \$exitcode" 0 ; +trap "rm -f \$tmpfiles 2>/dev/null; rmdir \$tmp 2>/dev/null; exit 1" 1 2 13 15 ; +: ${TMPDIR=/tmp} ; + { tmp=`(umask 077 && mktemp -d "$TMPDIR/cgXXXXXX") 2>/dev/null` && test -n "$tmp" && test -d "$tmp" ; } || + { test -n "$RANDOM" && tmp=$TMPDIR/cg$$-$RANDOM && (umask 077 && mkdir $tmp) ; } || + { tmp=$TMPDIR/cg-$$ && (umask 077 && mkdir $tmp) && echo "Warning: creating insecure temp directory" >&2 ; } || + { echo "$me: cannot create a temporary directory in $TMPDIR" >&2 ; exit 1 ; } ; +dummy=$tmp/dummy ; +tmpfiles="$dummy.c $dummy.o $dummy.rel $dummy" ; +case $CC_FOR_BUILD,$HOST_CC,$CC in + ,,) echo "int x;" > $dummy.c ; + for c in cc gcc c89 c99 ; do + if ($c -c -o $dummy.o $dummy.c) >/dev/null 2>&1 ; then + CC_FOR_BUILD="$c"; break ; + fi ; + done ; + if test x"$CC_FOR_BUILD" = x ; then + CC_FOR_BUILD=no_compiler_found ; + fi + ;; + ,,*) CC_FOR_BUILD=$CC ;; + ,*,*) CC_FOR_BUILD=$HOST_CC ;; +esac ; set_cc_for_build= ;' + +# This is needed to find uname on a Pyramid OSx when run in the BSD universe. +# (ghazi@noc.rutgers.edu 1994-08-24) +if (test -f /.attbin/uname) >/dev/null 2>&1 ; then + PATH=$PATH:/.attbin ; export PATH +fi + +UNAME_MACHINE=`(uname -m) 2>/dev/null` || UNAME_MACHINE=unknown +UNAME_RELEASE=`(uname -r) 2>/dev/null` || UNAME_RELEASE=unknown +UNAME_SYSTEM=`(uname -s) 2>/dev/null` || UNAME_SYSTEM=unknown +UNAME_VERSION=`(uname -v) 2>/dev/null` || UNAME_VERSION=unknown + +# Note: order is significant - the case branches are not exclusive. + +case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in + *:NetBSD:*:*) + # NetBSD (nbsd) targets should (where applicable) match one or + # more of the tupples: *-*-netbsdelf*, *-*-netbsdaout*, + # *-*-netbsdecoff* and *-*-netbsd*. For targets that recently + # switched to ELF, *-*-netbsd* would select the old + # object file format. This provides both forward + # compatibility and a consistent mechanism for selecting the + # object file format. + # + # Note: NetBSD doesn't particularly care about the vendor + # portion of the name. We always set it to "unknown". + sysctl="sysctl -n hw.machine_arch" + UNAME_MACHINE_ARCH=`(/sbin/$sysctl 2>/dev/null || \ + /usr/sbin/$sysctl 2>/dev/null || echo unknown)` + case "${UNAME_MACHINE_ARCH}" in + armeb) machine=armeb-unknown ;; + arm*) machine=arm-unknown ;; + sh3el) machine=shl-unknown ;; + sh3eb) machine=sh-unknown ;; + sh5el) machine=sh5le-unknown ;; + *) machine=${UNAME_MACHINE_ARCH}-unknown ;; + esac + # The Operating System including object format, if it has switched + # to ELF recently, or will in the future. + case "${UNAME_MACHINE_ARCH}" in + arm*|i386|m68k|ns32k|sh3*|sparc|vax) + eval $set_cc_for_build + if echo __ELF__ | $CC_FOR_BUILD -E - 2>/dev/null \ + | grep __ELF__ >/dev/null + then + # Once all utilities can be ECOFF (netbsdecoff) or a.out (netbsdaout). + # Return netbsd for either. FIX? + os=netbsd + else + os=netbsdelf + fi + ;; + *) + os=netbsd + ;; + esac + # The OS release + # Debian GNU/NetBSD machines have a different userland, and + # thus, need a distinct triplet. However, they do not need + # kernel version information, so it can be replaced with a + # suitable tag, in the style of linux-gnu. + case "${UNAME_VERSION}" in + Debian*) + release='-gnu' + ;; + *) + release=`echo ${UNAME_RELEASE}|sed -e 's/[-_].*/\./'` + ;; + esac + # Since CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM: + # contains redundant information, the shorter form: + # CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM is used. + echo "${machine}-${os}${release}" + exit ;; + *:OpenBSD:*:*) + UNAME_MACHINE_ARCH=`arch | sed 's/OpenBSD.//'` + echo ${UNAME_MACHINE_ARCH}-unknown-openbsd${UNAME_RELEASE} + exit ;; + *:ekkoBSD:*:*) + echo ${UNAME_MACHINE}-unknown-ekkobsd${UNAME_RELEASE} + exit ;; + *:SolidBSD:*:*) + echo ${UNAME_MACHINE}-unknown-solidbsd${UNAME_RELEASE} + exit ;; + macppc:MirBSD:*:*) + echo powerpc-unknown-mirbsd${UNAME_RELEASE} + exit ;; + *:MirBSD:*:*) + echo ${UNAME_MACHINE}-unknown-mirbsd${UNAME_RELEASE} + exit ;; + alpha:OSF1:*:*) + case $UNAME_RELEASE in + *4.0) + UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $3}'` + ;; + *5.*) + UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $4}'` + ;; + esac + # According to Compaq, /usr/sbin/psrinfo has been available on + # OSF/1 and Tru64 systems produced since 1995. I hope that + # covers most systems running today. This code pipes the CPU + # types through head -n 1, so we only detect the type of CPU 0. + ALPHA_CPU_TYPE=`/usr/sbin/psrinfo -v | sed -n -e 's/^ The alpha \(.*\) processor.*$/\1/p' | head -n 1` + case "$ALPHA_CPU_TYPE" in + "EV4 (21064)") + UNAME_MACHINE="alpha" ;; + "EV4.5 (21064)") + UNAME_MACHINE="alpha" ;; + "LCA4 (21066/21068)") + UNAME_MACHINE="alpha" ;; + "EV5 (21164)") + UNAME_MACHINE="alphaev5" ;; + "EV5.6 (21164A)") + UNAME_MACHINE="alphaev56" ;; + "EV5.6 (21164PC)") + UNAME_MACHINE="alphapca56" ;; + "EV5.7 (21164PC)") + UNAME_MACHINE="alphapca57" ;; + "EV6 (21264)") + UNAME_MACHINE="alphaev6" ;; + "EV6.7 (21264A)") + UNAME_MACHINE="alphaev67" ;; + "EV6.8CB (21264C)") + UNAME_MACHINE="alphaev68" ;; + "EV6.8AL (21264B)") + UNAME_MACHINE="alphaev68" ;; + "EV6.8CX (21264D)") + UNAME_MACHINE="alphaev68" ;; + "EV6.9A (21264/EV69A)") + UNAME_MACHINE="alphaev69" ;; + "EV7 (21364)") + UNAME_MACHINE="alphaev7" ;; + "EV7.9 (21364A)") + UNAME_MACHINE="alphaev79" ;; + esac + # A Pn.n version is a patched version. + # A Vn.n version is a released version. + # A Tn.n version is a released field test version. + # A Xn.n version is an unreleased experimental baselevel. + # 1.2 uses "1.2" for uname -r. + echo ${UNAME_MACHINE}-dec-osf`echo ${UNAME_RELEASE} | sed -e 's/^[PVTX]//' | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'` + exit ;; + Alpha\ *:Windows_NT*:*) + # How do we know it's Interix rather than the generic POSIX subsystem? + # Should we change UNAME_MACHINE based on the output of uname instead + # of the specific Alpha model? + echo alpha-pc-interix + exit ;; + 21064:Windows_NT:50:3) + echo alpha-dec-winnt3.5 + exit ;; + Amiga*:UNIX_System_V:4.0:*) + echo m68k-unknown-sysv4 + exit ;; + *:[Aa]miga[Oo][Ss]:*:*) + echo ${UNAME_MACHINE}-unknown-amigaos + exit ;; + *:[Mm]orph[Oo][Ss]:*:*) + echo ${UNAME_MACHINE}-unknown-morphos + exit ;; + *:OS/390:*:*) + echo i370-ibm-openedition + exit ;; + *:z/VM:*:*) + echo s390-ibm-zvmoe + exit ;; + *:OS400:*:*) + echo powerpc-ibm-os400 + exit ;; + arm:RISC*:1.[012]*:*|arm:riscix:1.[012]*:*) + echo arm-acorn-riscix${UNAME_RELEASE} + exit ;; + arm:riscos:*:*|arm:RISCOS:*:*) + echo arm-unknown-riscos + exit ;; + SR2?01:HI-UX/MPP:*:* | SR8000:HI-UX/MPP:*:*) + echo hppa1.1-hitachi-hiuxmpp + exit ;; + Pyramid*:OSx*:*:* | MIS*:OSx*:*:* | MIS*:SMP_DC-OSx*:*:*) + # akee@wpdis03.wpafb.af.mil (Earle F. Ake) contributed MIS and NILE. + if test "`(/bin/universe) 2>/dev/null`" = att ; then + echo pyramid-pyramid-sysv3 + else + echo pyramid-pyramid-bsd + fi + exit ;; + NILE*:*:*:dcosx) + echo pyramid-pyramid-svr4 + exit ;; + DRS?6000:unix:4.0:6*) + echo sparc-icl-nx6 + exit ;; + DRS?6000:UNIX_SV:4.2*:7* | DRS?6000:isis:4.2*:7*) + case `/usr/bin/uname -p` in + sparc) echo sparc-icl-nx7; exit ;; + esac ;; + sun4H:SunOS:5.*:*) + echo sparc-hal-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + exit ;; + sun4*:SunOS:5.*:* | tadpole*:SunOS:5.*:*) + echo sparc-sun-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + exit ;; + i86pc:SunOS:5.*:* | ix86xen:SunOS:5.*:*) + echo i386-pc-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + exit ;; + sun4*:SunOS:6*:*) + # According to config.sub, this is the proper way to canonicalize + # SunOS6. Hard to guess exactly what SunOS6 will be like, but + # it's likely to be more like Solaris than SunOS4. + echo sparc-sun-solaris3`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + exit ;; + sun4*:SunOS:*:*) + case "`/usr/bin/arch -k`" in + Series*|S4*) + UNAME_RELEASE=`uname -v` + ;; + esac + # Japanese Language versions have a version number like `4.1.3-JL'. + echo sparc-sun-sunos`echo ${UNAME_RELEASE}|sed -e 's/-/_/'` + exit ;; + sun3*:SunOS:*:*) + echo m68k-sun-sunos${UNAME_RELEASE} + exit ;; + sun*:*:4.2BSD:*) + UNAME_RELEASE=`(sed 1q /etc/motd | awk '{print substr($5,1,3)}') 2>/dev/null` + test "x${UNAME_RELEASE}" = "x" && UNAME_RELEASE=3 + case "`/bin/arch`" in + sun3) + echo m68k-sun-sunos${UNAME_RELEASE} + ;; + sun4) + echo sparc-sun-sunos${UNAME_RELEASE} + ;; + esac + exit ;; + aushp:SunOS:*:*) + echo sparc-auspex-sunos${UNAME_RELEASE} + exit ;; + # The situation for MiNT is a little confusing. The machine name + # can be virtually everything (everything which is not + # "atarist" or "atariste" at least should have a processor + # > m68000). The system name ranges from "MiNT" over "FreeMiNT" + # to the lowercase version "mint" (or "freemint"). Finally + # the system name "TOS" denotes a system which is actually not + # MiNT. But MiNT is downward compatible to TOS, so this should + # be no problem. + atarist[e]:*MiNT:*:* | atarist[e]:*mint:*:* | atarist[e]:*TOS:*:*) + echo m68k-atari-mint${UNAME_RELEASE} + exit ;; + atari*:*MiNT:*:* | atari*:*mint:*:* | atarist[e]:*TOS:*:*) + echo m68k-atari-mint${UNAME_RELEASE} + exit ;; + *falcon*:*MiNT:*:* | *falcon*:*mint:*:* | *falcon*:*TOS:*:*) + echo m68k-atari-mint${UNAME_RELEASE} + exit ;; + milan*:*MiNT:*:* | milan*:*mint:*:* | *milan*:*TOS:*:*) + echo m68k-milan-mint${UNAME_RELEASE} + exit ;; + hades*:*MiNT:*:* | hades*:*mint:*:* | *hades*:*TOS:*:*) + echo m68k-hades-mint${UNAME_RELEASE} + exit ;; + *:*MiNT:*:* | *:*mint:*:* | *:*TOS:*:*) + echo m68k-unknown-mint${UNAME_RELEASE} + exit ;; + m68k:machten:*:*) + echo m68k-apple-machten${UNAME_RELEASE} + exit ;; + powerpc:machten:*:*) + echo powerpc-apple-machten${UNAME_RELEASE} + exit ;; + RISC*:Mach:*:*) + echo mips-dec-mach_bsd4.3 + exit ;; + RISC*:ULTRIX:*:*) + echo mips-dec-ultrix${UNAME_RELEASE} + exit ;; + VAX*:ULTRIX*:*:*) + echo vax-dec-ultrix${UNAME_RELEASE} + exit ;; + 2020:CLIX:*:* | 2430:CLIX:*:*) + echo clipper-intergraph-clix${UNAME_RELEASE} + exit ;; + mips:*:*:UMIPS | mips:*:*:RISCos) + eval $set_cc_for_build + sed 's/^ //' << EOF >$dummy.c +#ifdef __cplusplus +#include /* for printf() prototype */ + int main (int argc, char *argv[]) { +#else + int main (argc, argv) int argc; char *argv[]; { +#endif + #if defined (host_mips) && defined (MIPSEB) + #if defined (SYSTYPE_SYSV) + printf ("mips-mips-riscos%ssysv\n", argv[1]); exit (0); + #endif + #if defined (SYSTYPE_SVR4) + printf ("mips-mips-riscos%ssvr4\n", argv[1]); exit (0); + #endif + #if defined (SYSTYPE_BSD43) || defined(SYSTYPE_BSD) + printf ("mips-mips-riscos%sbsd\n", argv[1]); exit (0); + #endif + #endif + exit (-1); + } +EOF + $CC_FOR_BUILD -o $dummy $dummy.c && + dummyarg=`echo "${UNAME_RELEASE}" | sed -n 's/\([0-9]*\).*/\1/p'` && + SYSTEM_NAME=`$dummy $dummyarg` && + { echo "$SYSTEM_NAME"; exit; } + echo mips-mips-riscos${UNAME_RELEASE} + exit ;; + Motorola:PowerMAX_OS:*:*) + echo powerpc-motorola-powermax + exit ;; + Motorola:*:4.3:PL8-*) + echo powerpc-harris-powermax + exit ;; + Night_Hawk:*:*:PowerMAX_OS | Synergy:PowerMAX_OS:*:*) + echo powerpc-harris-powermax + exit ;; + Night_Hawk:Power_UNIX:*:*) + echo powerpc-harris-powerunix + exit ;; + m88k:CX/UX:7*:*) + echo m88k-harris-cxux7 + exit ;; + m88k:*:4*:R4*) + echo m88k-motorola-sysv4 + exit ;; + m88k:*:3*:R3*) + echo m88k-motorola-sysv3 + exit ;; + AViiON:dgux:*:*) + # DG/UX returns AViiON for all architectures + UNAME_PROCESSOR=`/usr/bin/uname -p` + if [ $UNAME_PROCESSOR = mc88100 ] || [ $UNAME_PROCESSOR = mc88110 ] + then + if [ ${TARGET_BINARY_INTERFACE}x = m88kdguxelfx ] || \ + [ ${TARGET_BINARY_INTERFACE}x = x ] + then + echo m88k-dg-dgux${UNAME_RELEASE} + else + echo m88k-dg-dguxbcs${UNAME_RELEASE} + fi + else + echo i586-dg-dgux${UNAME_RELEASE} + fi + exit ;; + M88*:DolphinOS:*:*) # DolphinOS (SVR3) + echo m88k-dolphin-sysv3 + exit ;; + M88*:*:R3*:*) + # Delta 88k system running SVR3 + echo m88k-motorola-sysv3 + exit ;; + XD88*:*:*:*) # Tektronix XD88 system running UTekV (SVR3) + echo m88k-tektronix-sysv3 + exit ;; + Tek43[0-9][0-9]:UTek:*:*) # Tektronix 4300 system running UTek (BSD) + echo m68k-tektronix-bsd + exit ;; + *:IRIX*:*:*) + echo mips-sgi-irix`echo ${UNAME_RELEASE}|sed -e 's/-/_/g'` + exit ;; + ????????:AIX?:[12].1:2) # AIX 2.2.1 or AIX 2.1.1 is RT/PC AIX. + echo romp-ibm-aix # uname -m gives an 8 hex-code CPU id + exit ;; # Note that: echo "'`uname -s`'" gives 'AIX ' + i*86:AIX:*:*) + echo i386-ibm-aix + exit ;; + ia64:AIX:*:*) + if [ -x /usr/bin/oslevel ] ; then + IBM_REV=`/usr/bin/oslevel` + else + IBM_REV=${UNAME_VERSION}.${UNAME_RELEASE} + fi + echo ${UNAME_MACHINE}-ibm-aix${IBM_REV} + exit ;; + *:AIX:2:3) + if grep bos325 /usr/include/stdio.h >/dev/null 2>&1; then + eval $set_cc_for_build + sed 's/^ //' << EOF >$dummy.c + #include + + main() + { + if (!__power_pc()) + exit(1); + puts("powerpc-ibm-aix3.2.5"); + exit(0); + } +EOF + if $CC_FOR_BUILD -o $dummy $dummy.c && SYSTEM_NAME=`$dummy` + then + echo "$SYSTEM_NAME" + else + echo rs6000-ibm-aix3.2.5 + fi + elif grep bos324 /usr/include/stdio.h >/dev/null 2>&1; then + echo rs6000-ibm-aix3.2.4 + else + echo rs6000-ibm-aix3.2 + fi + exit ;; + *:AIX:*:[45]) + IBM_CPU_ID=`/usr/sbin/lsdev -C -c processor -S available | sed 1q | awk '{ print $1 }'` + if /usr/sbin/lsattr -El ${IBM_CPU_ID} | grep ' POWER' >/dev/null 2>&1; then + IBM_ARCH=rs6000 + else + IBM_ARCH=powerpc + fi + if [ -x /usr/bin/oslevel ] ; then + IBM_REV=`/usr/bin/oslevel` + else + IBM_REV=${UNAME_VERSION}.${UNAME_RELEASE} + fi + echo ${IBM_ARCH}-ibm-aix${IBM_REV} + exit ;; + *:AIX:*:*) + echo rs6000-ibm-aix + exit ;; + ibmrt:4.4BSD:*|romp-ibm:BSD:*) + echo romp-ibm-bsd4.4 + exit ;; + ibmrt:*BSD:*|romp-ibm:BSD:*) # covers RT/PC BSD and + echo romp-ibm-bsd${UNAME_RELEASE} # 4.3 with uname added to + exit ;; # report: romp-ibm BSD 4.3 + *:BOSX:*:*) + echo rs6000-bull-bosx + exit ;; + DPX/2?00:B.O.S.:*:*) + echo m68k-bull-sysv3 + exit ;; + 9000/[34]??:4.3bsd:1.*:*) + echo m68k-hp-bsd + exit ;; + hp300:4.4BSD:*:* | 9000/[34]??:4.3bsd:2.*:*) + echo m68k-hp-bsd4.4 + exit ;; + 9000/[34678]??:HP-UX:*:*) + HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'` + case "${UNAME_MACHINE}" in + 9000/31? ) HP_ARCH=m68000 ;; + 9000/[34]?? ) HP_ARCH=m68k ;; + 9000/[678][0-9][0-9]) + if [ -x /usr/bin/getconf ]; then + sc_cpu_version=`/usr/bin/getconf SC_CPU_VERSION 2>/dev/null` + sc_kernel_bits=`/usr/bin/getconf SC_KERNEL_BITS 2>/dev/null` + case "${sc_cpu_version}" in + 523) HP_ARCH="hppa1.0" ;; # CPU_PA_RISC1_0 + 528) HP_ARCH="hppa1.1" ;; # CPU_PA_RISC1_1 + 532) # CPU_PA_RISC2_0 + case "${sc_kernel_bits}" in + 32) HP_ARCH="hppa2.0n" ;; + 64) HP_ARCH="hppa2.0w" ;; + '') HP_ARCH="hppa2.0" ;; # HP-UX 10.20 + esac ;; + esac + fi + if [ "${HP_ARCH}" = "" ]; then + eval $set_cc_for_build + sed 's/^ //' << EOF >$dummy.c + + #define _HPUX_SOURCE + #include + #include + + int main () + { + #if defined(_SC_KERNEL_BITS) + long bits = sysconf(_SC_KERNEL_BITS); + #endif + long cpu = sysconf (_SC_CPU_VERSION); + + switch (cpu) + { + case CPU_PA_RISC1_0: puts ("hppa1.0"); break; + case CPU_PA_RISC1_1: puts ("hppa1.1"); break; + case CPU_PA_RISC2_0: + #if defined(_SC_KERNEL_BITS) + switch (bits) + { + case 64: puts ("hppa2.0w"); break; + case 32: puts ("hppa2.0n"); break; + default: puts ("hppa2.0"); break; + } break; + #else /* !defined(_SC_KERNEL_BITS) */ + puts ("hppa2.0"); break; + #endif + default: puts ("hppa1.0"); break; + } + exit (0); + } +EOF + (CCOPTS= $CC_FOR_BUILD -o $dummy $dummy.c 2>/dev/null) && HP_ARCH=`$dummy` + test -z "$HP_ARCH" && HP_ARCH=hppa + fi ;; + esac + if [ ${HP_ARCH} = "hppa2.0w" ] + then + eval $set_cc_for_build + + # hppa2.0w-hp-hpux* has a 64-bit kernel and a compiler generating + # 32-bit code. hppa64-hp-hpux* has the same kernel and a compiler + # generating 64-bit code. GNU and HP use different nomenclature: + # + # $ CC_FOR_BUILD=cc ./config.guess + # => hppa2.0w-hp-hpux11.23 + # $ CC_FOR_BUILD="cc +DA2.0w" ./config.guess + # => hppa64-hp-hpux11.23 + + if echo __LP64__ | (CCOPTS= $CC_FOR_BUILD -E - 2>/dev/null) | + grep __LP64__ >/dev/null + then + HP_ARCH="hppa2.0w" + else + HP_ARCH="hppa64" + fi + fi + echo ${HP_ARCH}-hp-hpux${HPUX_REV} + exit ;; + ia64:HP-UX:*:*) + HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'` + echo ia64-hp-hpux${HPUX_REV} + exit ;; + 3050*:HI-UX:*:*) + eval $set_cc_for_build + sed 's/^ //' << EOF >$dummy.c + #include + int + main () + { + long cpu = sysconf (_SC_CPU_VERSION); + /* The order matters, because CPU_IS_HP_MC68K erroneously returns + true for CPU_PA_RISC1_0. CPU_IS_PA_RISC returns correct + results, however. */ + if (CPU_IS_PA_RISC (cpu)) + { + switch (cpu) + { + case CPU_PA_RISC1_0: puts ("hppa1.0-hitachi-hiuxwe2"); break; + case CPU_PA_RISC1_1: puts ("hppa1.1-hitachi-hiuxwe2"); break; + case CPU_PA_RISC2_0: puts ("hppa2.0-hitachi-hiuxwe2"); break; + default: puts ("hppa-hitachi-hiuxwe2"); break; + } + } + else if (CPU_IS_HP_MC68K (cpu)) + puts ("m68k-hitachi-hiuxwe2"); + else puts ("unknown-hitachi-hiuxwe2"); + exit (0); + } +EOF + $CC_FOR_BUILD -o $dummy $dummy.c && SYSTEM_NAME=`$dummy` && + { echo "$SYSTEM_NAME"; exit; } + echo unknown-hitachi-hiuxwe2 + exit ;; + 9000/7??:4.3bsd:*:* | 9000/8?[79]:4.3bsd:*:* ) + echo hppa1.1-hp-bsd + exit ;; + 9000/8??:4.3bsd:*:*) + echo hppa1.0-hp-bsd + exit ;; + *9??*:MPE/iX:*:* | *3000*:MPE/iX:*:*) + echo hppa1.0-hp-mpeix + exit ;; + hp7??:OSF1:*:* | hp8?[79]:OSF1:*:* ) + echo hppa1.1-hp-osf + exit ;; + hp8??:OSF1:*:*) + echo hppa1.0-hp-osf + exit ;; + i*86:OSF1:*:*) + if [ -x /usr/sbin/sysversion ] ; then + echo ${UNAME_MACHINE}-unknown-osf1mk + else + echo ${UNAME_MACHINE}-unknown-osf1 + fi + exit ;; + parisc*:Lites*:*:*) + echo hppa1.1-hp-lites + exit ;; + C1*:ConvexOS:*:* | convex:ConvexOS:C1*:*) + echo c1-convex-bsd + exit ;; + C2*:ConvexOS:*:* | convex:ConvexOS:C2*:*) + if getsysinfo -f scalar_acc + then echo c32-convex-bsd + else echo c2-convex-bsd + fi + exit ;; + C34*:ConvexOS:*:* | convex:ConvexOS:C34*:*) + echo c34-convex-bsd + exit ;; + C38*:ConvexOS:*:* | convex:ConvexOS:C38*:*) + echo c38-convex-bsd + exit ;; + C4*:ConvexOS:*:* | convex:ConvexOS:C4*:*) + echo c4-convex-bsd + exit ;; + CRAY*Y-MP:*:*:*) + echo ymp-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' + exit ;; + CRAY*[A-Z]90:*:*:*) + echo ${UNAME_MACHINE}-cray-unicos${UNAME_RELEASE} \ + | sed -e 's/CRAY.*\([A-Z]90\)/\1/' \ + -e y/ABCDEFGHIJKLMNOPQRSTUVWXYZ/abcdefghijklmnopqrstuvwxyz/ \ + -e 's/\.[^.]*$/.X/' + exit ;; + CRAY*TS:*:*:*) + echo t90-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' + exit ;; + CRAY*T3E:*:*:*) + echo alphaev5-cray-unicosmk${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' + exit ;; + CRAY*SV1:*:*:*) + echo sv1-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' + exit ;; + *:UNICOS/mp:*:*) + echo craynv-cray-unicosmp${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' + exit ;; + F30[01]:UNIX_System_V:*:* | F700:UNIX_System_V:*:*) + FUJITSU_PROC=`uname -m | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'` + FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'` + FUJITSU_REL=`echo ${UNAME_RELEASE} | sed -e 's/ /_/'` + echo "${FUJITSU_PROC}-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}" + exit ;; + 5000:UNIX_System_V:4.*:*) + FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'` + FUJITSU_REL=`echo ${UNAME_RELEASE} | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/ /_/'` + echo "sparc-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}" + exit ;; + i*86:BSD/386:*:* | i*86:BSD/OS:*:* | *:Ascend\ Embedded/OS:*:*) + echo ${UNAME_MACHINE}-pc-bsdi${UNAME_RELEASE} + exit ;; + sparc*:BSD/OS:*:*) + echo sparc-unknown-bsdi${UNAME_RELEASE} + exit ;; + *:BSD/OS:*:*) + echo ${UNAME_MACHINE}-unknown-bsdi${UNAME_RELEASE} + exit ;; + *:FreeBSD:*:*) + case ${UNAME_MACHINE} in + pc98) + echo i386-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` ;; + amd64) + echo x86_64-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` ;; + *) + echo ${UNAME_MACHINE}-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` ;; + esac + exit ;; + i*:CYGWIN*:*) + echo ${UNAME_MACHINE}-pc-cygwin + exit ;; + *:MINGW*:*) + echo ${UNAME_MACHINE}-pc-mingw32 + exit ;; + i*:windows32*:*) + # uname -m includes "-pc" on this system. + echo ${UNAME_MACHINE}-mingw32 + exit ;; + i*:PW*:*) + echo ${UNAME_MACHINE}-pc-pw32 + exit ;; + *:Interix*:[3456]*) + case ${UNAME_MACHINE} in + x86) + echo i586-pc-interix${UNAME_RELEASE} + exit ;; + EM64T | authenticamd) + echo x86_64-unknown-interix${UNAME_RELEASE} + exit ;; + esac ;; + [345]86:Windows_95:* | [345]86:Windows_98:* | [345]86:Windows_NT:*) + echo i${UNAME_MACHINE}-pc-mks + exit ;; + i*:Windows_NT*:* | Pentium*:Windows_NT*:*) + # How do we know it's Interix rather than the generic POSIX subsystem? + # It also conflicts with pre-2.0 versions of AT&T UWIN. Should we + # UNAME_MACHINE based on the output of uname instead of i386? + echo i586-pc-interix + exit ;; + i*:UWIN*:*) + echo ${UNAME_MACHINE}-pc-uwin + exit ;; + amd64:CYGWIN*:*:* | x86_64:CYGWIN*:*:*) + echo x86_64-unknown-cygwin + exit ;; + p*:CYGWIN*:*) + echo powerpcle-unknown-cygwin + exit ;; + prep*:SunOS:5.*:*) + echo powerpcle-unknown-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + exit ;; + *:GNU:*:*) + # the GNU system + echo `echo ${UNAME_MACHINE}|sed -e 's,[-/].*$,,'`-unknown-gnu`echo ${UNAME_RELEASE}|sed -e 's,/.*$,,'` + exit ;; + *:GNU/*:*:*) + # other systems with GNU libc and userland + echo ${UNAME_MACHINE}-unknown-`echo ${UNAME_SYSTEM} | sed 's,^[^/]*/,,' | tr '[A-Z]' '[a-z]'``echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`-gnu + exit ;; + i*86:Minix:*:*) + echo ${UNAME_MACHINE}-pc-minix + exit ;; + arm*:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit ;; + avr32*:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit ;; + cris:Linux:*:*) + echo cris-axis-linux-gnu + exit ;; + crisv32:Linux:*:*) + echo crisv32-axis-linux-gnu + exit ;; + frv:Linux:*:*) + echo frv-unknown-linux-gnu + exit ;; + ia64:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit ;; + m32r*:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit ;; + m68*:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit ;; + mips:Linux:*:*) + eval $set_cc_for_build + sed 's/^ //' << EOF >$dummy.c + #undef CPU + #undef mips + #undef mipsel + #if defined(__MIPSEL__) || defined(__MIPSEL) || defined(_MIPSEL) || defined(MIPSEL) + CPU=mipsel + #else + #if defined(__MIPSEB__) || defined(__MIPSEB) || defined(_MIPSEB) || defined(MIPSEB) + CPU=mips + #else + CPU= + #endif + #endif +EOF + eval "`$CC_FOR_BUILD -E $dummy.c 2>/dev/null | sed -n ' + /^CPU/{ + s: ::g + p + }'`" + test x"${CPU}" != x && { echo "${CPU}-unknown-linux-gnu"; exit; } + ;; + mips64:Linux:*:*) + eval $set_cc_for_build + sed 's/^ //' << EOF >$dummy.c + #undef CPU + #undef mips64 + #undef mips64el + #if defined(__MIPSEL__) || defined(__MIPSEL) || defined(_MIPSEL) || defined(MIPSEL) + CPU=mips64el + #else + #if defined(__MIPSEB__) || defined(__MIPSEB) || defined(_MIPSEB) || defined(MIPSEB) + CPU=mips64 + #else + CPU= + #endif + #endif +EOF + eval "`$CC_FOR_BUILD -E $dummy.c 2>/dev/null | sed -n ' + /^CPU/{ + s: ::g + p + }'`" + test x"${CPU}" != x && { echo "${CPU}-unknown-linux-gnu"; exit; } + ;; + or32:Linux:*:*) + echo or32-unknown-linux-gnu + exit ;; + ppc:Linux:*:*) + echo powerpc-unknown-linux-gnu + exit ;; + ppc64:Linux:*:*) + echo powerpc64-unknown-linux-gnu + exit ;; + alpha:Linux:*:*) + case `sed -n '/^cpu model/s/^.*: \(.*\)/\1/p' < /proc/cpuinfo` in + EV5) UNAME_MACHINE=alphaev5 ;; + EV56) UNAME_MACHINE=alphaev56 ;; + PCA56) UNAME_MACHINE=alphapca56 ;; + PCA57) UNAME_MACHINE=alphapca56 ;; + EV6) UNAME_MACHINE=alphaev6 ;; + EV67) UNAME_MACHINE=alphaev67 ;; + EV68*) UNAME_MACHINE=alphaev68 ;; + esac + objdump --private-headers /bin/sh | grep ld.so.1 >/dev/null + if test "$?" = 0 ; then LIBC="libc1" ; else LIBC="" ; fi + echo ${UNAME_MACHINE}-unknown-linux-gnu${LIBC} + exit ;; + parisc:Linux:*:* | hppa:Linux:*:*) + # Look for CPU level + case `grep '^cpu[^a-z]*:' /proc/cpuinfo 2>/dev/null | cut -d' ' -f2` in + PA7*) echo hppa1.1-unknown-linux-gnu ;; + PA8*) echo hppa2.0-unknown-linux-gnu ;; + *) echo hppa-unknown-linux-gnu ;; + esac + exit ;; + parisc64:Linux:*:* | hppa64:Linux:*:*) + echo hppa64-unknown-linux-gnu + exit ;; + s390:Linux:*:* | s390x:Linux:*:*) + echo ${UNAME_MACHINE}-ibm-linux + exit ;; + sh64*:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit ;; + sh*:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit ;; + sparc:Linux:*:* | sparc64:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit ;; + vax:Linux:*:*) + echo ${UNAME_MACHINE}-dec-linux-gnu + exit ;; + x86_64:Linux:*:*) + echo x86_64-unknown-linux-gnu + exit ;; + xtensa:Linux:*:*) + echo xtensa-unknown-linux-gnu + exit ;; + i*86:Linux:*:*) + # The BFD linker knows what the default object file format is, so + # first see if it will tell us. cd to the root directory to prevent + # problems with other programs or directories called `ld' in the path. + # Set LC_ALL=C to ensure ld outputs messages in English. + ld_supported_targets=`cd /; LC_ALL=C ld --help 2>&1 \ + | sed -ne '/supported targets:/!d + s/[ ][ ]*/ /g + s/.*supported targets: *// + s/ .*// + p'` + case "$ld_supported_targets" in + elf32-i386) + TENTATIVE="${UNAME_MACHINE}-pc-linux-gnu" + ;; + a.out-i386-linux) + echo "${UNAME_MACHINE}-pc-linux-gnuaout" + exit ;; + coff-i386) + echo "${UNAME_MACHINE}-pc-linux-gnucoff" + exit ;; + "") + # Either a pre-BFD a.out linker (linux-gnuoldld) or + # one that does not give us useful --help. + echo "${UNAME_MACHINE}-pc-linux-gnuoldld" + exit ;; + esac + # Determine whether the default compiler is a.out or elf + eval $set_cc_for_build + sed 's/^ //' << EOF >$dummy.c + #include + #ifdef __ELF__ + # ifdef __GLIBC__ + # if __GLIBC__ >= 2 + LIBC=gnu + # else + LIBC=gnulibc1 + # endif + # else + LIBC=gnulibc1 + # endif + #else + #if defined(__INTEL_COMPILER) || defined(__PGI) || defined(__SUNPRO_C) || defined(__SUNPRO_CC) + LIBC=gnu + #else + LIBC=gnuaout + #endif + #endif + #ifdef __dietlibc__ + LIBC=dietlibc + #endif +EOF + eval "`$CC_FOR_BUILD -E $dummy.c 2>/dev/null | sed -n ' + /^LIBC/{ + s: ::g + p + }'`" + test x"${LIBC}" != x && { + echo "${UNAME_MACHINE}-pc-linux-${LIBC}" + exit + } + test x"${TENTATIVE}" != x && { echo "${TENTATIVE}"; exit; } + ;; + i*86:DYNIX/ptx:4*:*) + # ptx 4.0 does uname -s correctly, with DYNIX/ptx in there. + # earlier versions are messed up and put the nodename in both + # sysname and nodename. + echo i386-sequent-sysv4 + exit ;; + i*86:UNIX_SV:4.2MP:2.*) + # Unixware is an offshoot of SVR4, but it has its own version + # number series starting with 2... + # I am not positive that other SVR4 systems won't match this, + # I just have to hope. -- rms. + # Use sysv4.2uw... so that sysv4* matches it. + echo ${UNAME_MACHINE}-pc-sysv4.2uw${UNAME_VERSION} + exit ;; + i*86:OS/2:*:*) + # If we were able to find `uname', then EMX Unix compatibility + # is probably installed. + echo ${UNAME_MACHINE}-pc-os2-emx + exit ;; + i*86:XTS-300:*:STOP) + echo ${UNAME_MACHINE}-unknown-stop + exit ;; + i*86:atheos:*:*) + echo ${UNAME_MACHINE}-unknown-atheos + exit ;; + i*86:syllable:*:*) + echo ${UNAME_MACHINE}-pc-syllable + exit ;; + i*86:LynxOS:2.*:* | i*86:LynxOS:3.[01]*:* | i*86:LynxOS:4.0*:*) + echo i386-unknown-lynxos${UNAME_RELEASE} + exit ;; + i*86:*DOS:*:*) + echo ${UNAME_MACHINE}-pc-msdosdjgpp + exit ;; + i*86:*:4.*:* | i*86:SYSTEM_V:4.*:*) + UNAME_REL=`echo ${UNAME_RELEASE} | sed 's/\/MP$//'` + if grep Novell /usr/include/link.h >/dev/null 2>/dev/null; then + echo ${UNAME_MACHINE}-univel-sysv${UNAME_REL} + else + echo ${UNAME_MACHINE}-pc-sysv${UNAME_REL} + fi + exit ;; + i*86:*:5:[678]*) + # UnixWare 7.x, OpenUNIX and OpenServer 6. + case `/bin/uname -X | grep "^Machine"` in + *486*) UNAME_MACHINE=i486 ;; + *Pentium) UNAME_MACHINE=i586 ;; + *Pent*|*Celeron) UNAME_MACHINE=i686 ;; + esac + echo ${UNAME_MACHINE}-unknown-sysv${UNAME_RELEASE}${UNAME_SYSTEM}${UNAME_VERSION} + exit ;; + i*86:*:3.2:*) + if test -f /usr/options/cb.name; then + UNAME_REL=`sed -n 's/.*Version //p' /dev/null >/dev/null ; then + UNAME_REL=`(/bin/uname -X|grep Release|sed -e 's/.*= //')` + (/bin/uname -X|grep i80486 >/dev/null) && UNAME_MACHINE=i486 + (/bin/uname -X|grep '^Machine.*Pentium' >/dev/null) \ + && UNAME_MACHINE=i586 + (/bin/uname -X|grep '^Machine.*Pent *II' >/dev/null) \ + && UNAME_MACHINE=i686 + (/bin/uname -X|grep '^Machine.*Pentium Pro' >/dev/null) \ + && UNAME_MACHINE=i686 + echo ${UNAME_MACHINE}-pc-sco$UNAME_REL + else + echo ${UNAME_MACHINE}-pc-sysv32 + fi + exit ;; + pc:*:*:*) + # Left here for compatibility: + # uname -m prints for DJGPP always 'pc', but it prints nothing about + # the processor, so we play safe by assuming i386. + echo i386-pc-msdosdjgpp + exit ;; + Intel:Mach:3*:*) + echo i386-pc-mach3 + exit ;; + paragon:*:*:*) + echo i860-intel-osf1 + exit ;; + i860:*:4.*:*) # i860-SVR4 + if grep Stardent /usr/include/sys/uadmin.h >/dev/null 2>&1 ; then + echo i860-stardent-sysv${UNAME_RELEASE} # Stardent Vistra i860-SVR4 + else # Add other i860-SVR4 vendors below as they are discovered. + echo i860-unknown-sysv${UNAME_RELEASE} # Unknown i860-SVR4 + fi + exit ;; + mini*:CTIX:SYS*5:*) + # "miniframe" + echo m68010-convergent-sysv + exit ;; + mc68k:UNIX:SYSTEM5:3.51m) + echo m68k-convergent-sysv + exit ;; + M680?0:D-NIX:5.3:*) + echo m68k-diab-dnix + exit ;; + M68*:*:R3V[5678]*:*) + test -r /sysV68 && { echo 'm68k-motorola-sysv'; exit; } ;; + 3[345]??:*:4.0:3.0 | 3[34]??A:*:4.0:3.0 | 3[34]??,*:*:4.0:3.0 | 3[34]??/*:*:4.0:3.0 | 4400:*:4.0:3.0 | 4850:*:4.0:3.0 | SKA40:*:4.0:3.0 | SDS2:*:4.0:3.0 | SHG2:*:4.0:3.0 | S7501*:*:4.0:3.0) + OS_REL='' + test -r /etc/.relid \ + && OS_REL=.`sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' < /etc/.relid` + /bin/uname -p 2>/dev/null | grep 86 >/dev/null \ + && { echo i486-ncr-sysv4.3${OS_REL}; exit; } + /bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \ + && { echo i586-ncr-sysv4.3${OS_REL}; exit; } ;; + 3[34]??:*:4.0:* | 3[34]??,*:*:4.0:*) + /bin/uname -p 2>/dev/null | grep 86 >/dev/null \ + && { echo i486-ncr-sysv4; exit; } ;; + m68*:LynxOS:2.*:* | m68*:LynxOS:3.0*:*) + echo m68k-unknown-lynxos${UNAME_RELEASE} + exit ;; + mc68030:UNIX_System_V:4.*:*) + echo m68k-atari-sysv4 + exit ;; + TSUNAMI:LynxOS:2.*:*) + echo sparc-unknown-lynxos${UNAME_RELEASE} + exit ;; + rs6000:LynxOS:2.*:*) + echo rs6000-unknown-lynxos${UNAME_RELEASE} + exit ;; + PowerPC:LynxOS:2.*:* | PowerPC:LynxOS:3.[01]*:* | PowerPC:LynxOS:4.0*:*) + echo powerpc-unknown-lynxos${UNAME_RELEASE} + exit ;; + SM[BE]S:UNIX_SV:*:*) + echo mips-dde-sysv${UNAME_RELEASE} + exit ;; + RM*:ReliantUNIX-*:*:*) + echo mips-sni-sysv4 + exit ;; + RM*:SINIX-*:*:*) + echo mips-sni-sysv4 + exit ;; + *:SINIX-*:*:*) + if uname -p 2>/dev/null >/dev/null ; then + UNAME_MACHINE=`(uname -p) 2>/dev/null` + echo ${UNAME_MACHINE}-sni-sysv4 + else + echo ns32k-sni-sysv + fi + exit ;; + PENTIUM:*:4.0*:*) # Unisys `ClearPath HMP IX 4000' SVR4/MP effort + # says + echo i586-unisys-sysv4 + exit ;; + *:UNIX_System_V:4*:FTX*) + # From Gerald Hewes . + # How about differentiating between stratus architectures? -djm + echo hppa1.1-stratus-sysv4 + exit ;; + *:*:*:FTX*) + # From seanf@swdc.stratus.com. + echo i860-stratus-sysv4 + exit ;; + i*86:VOS:*:*) + # From Paul.Green@stratus.com. + echo ${UNAME_MACHINE}-stratus-vos + exit ;; + *:VOS:*:*) + # From Paul.Green@stratus.com. + echo hppa1.1-stratus-vos + exit ;; + mc68*:A/UX:*:*) + echo m68k-apple-aux${UNAME_RELEASE} + exit ;; + news*:NEWS-OS:6*:*) + echo mips-sony-newsos6 + exit ;; + R[34]000:*System_V*:*:* | R4000:UNIX_SYSV:*:* | R*000:UNIX_SV:*:*) + if [ -d /usr/nec ]; then + echo mips-nec-sysv${UNAME_RELEASE} + else + echo mips-unknown-sysv${UNAME_RELEASE} + fi + exit ;; + BeBox:BeOS:*:*) # BeOS running on hardware made by Be, PPC only. + echo powerpc-be-beos + exit ;; + BeMac:BeOS:*:*) # BeOS running on Mac or Mac clone, PPC only. + echo powerpc-apple-beos + exit ;; + BePC:BeOS:*:*) # BeOS running on Intel PC compatible. + echo i586-pc-beos + exit ;; + SX-4:SUPER-UX:*:*) + echo sx4-nec-superux${UNAME_RELEASE} + exit ;; + SX-5:SUPER-UX:*:*) + echo sx5-nec-superux${UNAME_RELEASE} + exit ;; + SX-6:SUPER-UX:*:*) + echo sx6-nec-superux${UNAME_RELEASE} + exit ;; + SX-7:SUPER-UX:*:*) + echo sx7-nec-superux${UNAME_RELEASE} + exit ;; + SX-8:SUPER-UX:*:*) + echo sx8-nec-superux${UNAME_RELEASE} + exit ;; + SX-8R:SUPER-UX:*:*) + echo sx8r-nec-superux${UNAME_RELEASE} + exit ;; + Power*:Rhapsody:*:*) + echo powerpc-apple-rhapsody${UNAME_RELEASE} + exit ;; + *:Rhapsody:*:*) + echo ${UNAME_MACHINE}-apple-rhapsody${UNAME_RELEASE} + exit ;; + *:Darwin:*:*) + UNAME_PROCESSOR=`uname -p` || UNAME_PROCESSOR=unknown + case $UNAME_PROCESSOR in + unknown) UNAME_PROCESSOR=powerpc ;; + esac + echo ${UNAME_PROCESSOR}-apple-darwin${UNAME_RELEASE} + exit ;; + *:procnto*:*:* | *:QNX:[0123456789]*:*) + UNAME_PROCESSOR=`uname -p` + if test "$UNAME_PROCESSOR" = "x86"; then + UNAME_PROCESSOR=i386 + UNAME_MACHINE=pc + fi + echo ${UNAME_PROCESSOR}-${UNAME_MACHINE}-nto-qnx${UNAME_RELEASE} + exit ;; + *:QNX:*:4*) + echo i386-pc-qnx + exit ;; + NSE-?:NONSTOP_KERNEL:*:*) + echo nse-tandem-nsk${UNAME_RELEASE} + exit ;; + NSR-?:NONSTOP_KERNEL:*:*) + echo nsr-tandem-nsk${UNAME_RELEASE} + exit ;; + *:NonStop-UX:*:*) + echo mips-compaq-nonstopux + exit ;; + BS2000:POSIX*:*:*) + echo bs2000-siemens-sysv + exit ;; + DS/*:UNIX_System_V:*:*) + echo ${UNAME_MACHINE}-${UNAME_SYSTEM}-${UNAME_RELEASE} + exit ;; + *:Plan9:*:*) + # "uname -m" is not consistent, so use $cputype instead. 386 + # is converted to i386 for consistency with other x86 + # operating systems. + if test "$cputype" = "386"; then + UNAME_MACHINE=i386 + else + UNAME_MACHINE="$cputype" + fi + echo ${UNAME_MACHINE}-unknown-plan9 + exit ;; + *:TOPS-10:*:*) + echo pdp10-unknown-tops10 + exit ;; + *:TENEX:*:*) + echo pdp10-unknown-tenex + exit ;; + KS10:TOPS-20:*:* | KL10:TOPS-20:*:* | TYPE4:TOPS-20:*:*) + echo pdp10-dec-tops20 + exit ;; + XKL-1:TOPS-20:*:* | TYPE5:TOPS-20:*:*) + echo pdp10-xkl-tops20 + exit ;; + *:TOPS-20:*:*) + echo pdp10-unknown-tops20 + exit ;; + *:ITS:*:*) + echo pdp10-unknown-its + exit ;; + SEI:*:*:SEIUX) + echo mips-sei-seiux${UNAME_RELEASE} + exit ;; + *:DragonFly:*:*) + echo ${UNAME_MACHINE}-unknown-dragonfly`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` + exit ;; + *:*VMS:*:*) + UNAME_MACHINE=`(uname -p) 2>/dev/null` + case "${UNAME_MACHINE}" in + A*) echo alpha-dec-vms ; exit ;; + I*) echo ia64-dec-vms ; exit ;; + V*) echo vax-dec-vms ; exit ;; + esac ;; + *:XENIX:*:SysV) + echo i386-pc-xenix + exit ;; + i*86:skyos:*:*) + echo ${UNAME_MACHINE}-pc-skyos`echo ${UNAME_RELEASE}` | sed -e 's/ .*$//' + exit ;; + i*86:rdos:*:*) + echo ${UNAME_MACHINE}-pc-rdos + exit ;; +esac + +#echo '(No uname command or uname output not recognized.)' 1>&2 +#echo "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" 1>&2 + +eval $set_cc_for_build +cat >$dummy.c < +# include +#endif +main () +{ +#if defined (sony) +#if defined (MIPSEB) + /* BFD wants "bsd" instead of "newsos". Perhaps BFD should be changed, + I don't know.... */ + printf ("mips-sony-bsd\n"); exit (0); +#else +#include + printf ("m68k-sony-newsos%s\n", +#ifdef NEWSOS4 + "4" +#else + "" +#endif + ); exit (0); +#endif +#endif + +#if defined (__arm) && defined (__acorn) && defined (__unix) + printf ("arm-acorn-riscix\n"); exit (0); +#endif + +#if defined (hp300) && !defined (hpux) + printf ("m68k-hp-bsd\n"); exit (0); +#endif + +#if defined (NeXT) +#if !defined (__ARCHITECTURE__) +#define __ARCHITECTURE__ "m68k" +#endif + int version; + version=`(hostinfo | sed -n 's/.*NeXT Mach \([0-9]*\).*/\1/p') 2>/dev/null`; + if (version < 4) + printf ("%s-next-nextstep%d\n", __ARCHITECTURE__, version); + else + printf ("%s-next-openstep%d\n", __ARCHITECTURE__, version); + exit (0); +#endif + +#if defined (MULTIMAX) || defined (n16) +#if defined (UMAXV) + printf ("ns32k-encore-sysv\n"); exit (0); +#else +#if defined (CMU) + printf ("ns32k-encore-mach\n"); exit (0); +#else + printf ("ns32k-encore-bsd\n"); exit (0); +#endif +#endif +#endif + +#if defined (__386BSD__) + printf ("i386-pc-bsd\n"); exit (0); +#endif + +#if defined (sequent) +#if defined (i386) + printf ("i386-sequent-dynix\n"); exit (0); +#endif +#if defined (ns32000) + printf ("ns32k-sequent-dynix\n"); exit (0); +#endif +#endif + +#if defined (_SEQUENT_) + struct utsname un; + + uname(&un); + + if (strncmp(un.version, "V2", 2) == 0) { + printf ("i386-sequent-ptx2\n"); exit (0); + } + if (strncmp(un.version, "V1", 2) == 0) { /* XXX is V1 correct? */ + printf ("i386-sequent-ptx1\n"); exit (0); + } + printf ("i386-sequent-ptx\n"); exit (0); + +#endif + +#if defined (vax) +# if !defined (ultrix) +# include +# if defined (BSD) +# if BSD == 43 + printf ("vax-dec-bsd4.3\n"); exit (0); +# else +# if BSD == 199006 + printf ("vax-dec-bsd4.3reno\n"); exit (0); +# else + printf ("vax-dec-bsd\n"); exit (0); +# endif +# endif +# else + printf ("vax-dec-bsd\n"); exit (0); +# endif +# else + printf ("vax-dec-ultrix\n"); exit (0); +# endif +#endif + +#if defined (alliant) && defined (i860) + printf ("i860-alliant-bsd\n"); exit (0); +#endif + + exit (1); +} +EOF + +$CC_FOR_BUILD -o $dummy $dummy.c 2>/dev/null && SYSTEM_NAME=`$dummy` && + { echo "$SYSTEM_NAME"; exit; } + +# Apollos put the system type in the environment. + +test -d /usr/apollo && { echo ${ISP}-apollo-${SYSTYPE}; exit; } + +# Convex versions that predate uname can use getsysinfo(1) + +if [ -x /usr/convex/getsysinfo ] +then + case `getsysinfo -f cpu_type` in + c1*) + echo c1-convex-bsd + exit ;; + c2*) + if getsysinfo -f scalar_acc + then echo c32-convex-bsd + else echo c2-convex-bsd + fi + exit ;; + c34*) + echo c34-convex-bsd + exit ;; + c38*) + echo c38-convex-bsd + exit ;; + c4*) + echo c4-convex-bsd + exit ;; + esac +fi + +cat >&2 < in order to provide the needed +information to handle your system. + +config.guess timestamp = $timestamp + +uname -m = `(uname -m) 2>/dev/null || echo unknown` +uname -r = `(uname -r) 2>/dev/null || echo unknown` +uname -s = `(uname -s) 2>/dev/null || echo unknown` +uname -v = `(uname -v) 2>/dev/null || echo unknown` + +/usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null` +/bin/uname -X = `(/bin/uname -X) 2>/dev/null` + +hostinfo = `(hostinfo) 2>/dev/null` +/bin/universe = `(/bin/universe) 2>/dev/null` +/usr/bin/arch -k = `(/usr/bin/arch -k) 2>/dev/null` +/bin/arch = `(/bin/arch) 2>/dev/null` +/usr/bin/oslevel = `(/usr/bin/oslevel) 2>/dev/null` +/usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null` + +UNAME_MACHINE = ${UNAME_MACHINE} +UNAME_RELEASE = ${UNAME_RELEASE} +UNAME_SYSTEM = ${UNAME_SYSTEM} +UNAME_VERSION = ${UNAME_VERSION} +EOF + +exit 1 + +# Local variables: +# eval: (add-hook 'write-file-hooks 'time-stamp) +# time-stamp-start: "timestamp='" +# time-stamp-format: "%:y-%02m-%02d" +# time-stamp-end: "'" +# End: diff --git a/config.h-vms b/config.h-vms new file mode 100644 index 00000000..7a30b196 --- /dev/null +++ b/config.h-vms @@ -0,0 +1,284 @@ +/* This is a config.h file that has been pregenerated (from config.h.in) + * with settings that are correct for VMS. + */ + + + +/* config.h.in --- xscreensaver, Copyright (c) 1998 Jamie Zawinski. + * + * The best way to set these parameters is by running the included `configure' + * script. That examines your system, and generates `config.h' from + * `config.h.in'. + * + * If something goes very wrong, you can edit `config.h' directly, but beware + * that your changes will be lost if you ever run `configure' again. + */ + + +/* ************************************************************************* + CONFIGURING SERVER EXTENSIONS + ************************************************************************* */ + +/* Define this if you have the XReadDisplay extension (I think this is an + SGI-only thing; it's in .) A few of the + screenhacks will take advantage of this if it's available. + */ +#undef HAVE_READ_DISPLAY_EXTENSION + +/* Define this if you have the Iris Video Library (dmedia/vl.h on SGI.) + A few of the screenhacks will take advantage of this if it's available. + */ +#undef HAVE_SGI_VIDEO + +/* Define this if you have the XHPDisableReset function (an HP only thing.) + */ +#undef HAVE_XHPDISABLERESET + +/* First, some background: there are three distinct server extensions which + * are useful to a screen saver program: they are XIDLE, MIT-SCREEN-SAVER, + * and SCREEN_SAVER. + * + * The XIDLE extension resides in .../contrib/extensions/xidle/ on the X11R5 + * contrib tape. This extension lets the client get accurate idle-time + * information from the X server in a potentially more reliable way than by + * simply watching for keyboard and mouse activity. However, the XIDLE + * extension has apparently not been ported to X11R6. + * + * The SCREEN_SAVER extension is found (as far as I know) only in the SGI + * X server, and it exists in all releases since (at least) Irix 5. The + * relevant header file is /usr/include/X11/extensions/XScreenSaver.h. + * + * The similarly-named MIT-SCREEN-SAVER extension came into existence long + * after the SGI SCREEN_SAVER extension was already in use, and resides in + * .../contrib/extensions/screensaver/ on the X11R6 contrib tape. It is + * also found in certain recent X servers built in to NCD X terminals. + * + * The MIT extension does basically the same thing that the XIDLE extension + * does, but there are two things wrong with it: first, because of the way + * the extension was designed, the `fade' option to XScreenSaver will be + * uglier: just before the screen fades out, there will be an unattractive + * flicker to black, because this extension blanks the screen *before* + * telling us that it is time to do so. Second, this extension is known to + * be buggy; on the systems I use, it works, but some people have reported + * X server crashes as a result of using it. XScreenSaver uses this + * extension rather conservatively, because when I tried to use any of its + * more complicated features, I could get it to crash the server at the + * drop of a hat. + * + * In short, the MIT-SCREEN-SAVER extension is a piece of junk. The older + * SGI SCREEN_SAVER extension works great, as does XIDLE. It would be nice + * If those two existed on more systems, that is, would be adopted by the + * X Consortium in favor of their inferior "not-invented-here" entry. + */ + +/* Define this if you have the XIDLE extension installed. If you have the + * XIDLE extension, this is recommended. (You have this extension if the + * file /usr/include/X11/extensions/xidle.h exists.) Turning on this flag + * lets XScreenSaver work better with servers which support this extension; + * but it will still work with servers which do not suport it, so it's a good + * idea to compile in support for it if you can. + */ +#undef HAVE_XIDLE_EXTENSION + +/* Define this if you have the MIT-SCREEN-SAVER extension installed. See the + * caveats about this extension, above. (It's available if the file + * /usr/include/X11/extensions/scrnsaver.h exists.) + */ +#undef HAVE_MIT_SAVER_EXTENSION + +/* Define this if you have the SGI SCREEN_SAVER extension. This is standard + * on Irix systems, and not available elsewhere. + */ +#undef HAVE_SGI_SAVER_EXTENSION + +/* Define this if you have the SGI-VIDEO-CONTROL extension. This is standard + * on Irix systems, and not available elsewhere. + */ +#undef HAVE_SGI_VC_EXTENSION + +/* Define this if you have the XDPMS extension. This is standard on + * sufficiently-recent XFree86 systems, and possibly elsewhere. (It's + * available if the file /usr/include/X11/extensions/dpms.h exists.) + */ +#define HAVE_DPMS_EXTENSION 1 + + +/* ************************************************************************* + CONFIGURING GRAPHICS TOOLKITS + ************************************************************************* */ + +/* Define this if you have Motif. + */ +#define HAVE_MOTIF 1 + +/* Define this if you have the XmComboBox Motif widget (Motif 2.0.) + */ +#undef HAVE_XMCOMBOBOX + +/* Define this if you have the XPM library installed. Some of the demos can + * make use of this if it is available. + */ +#define HAVE_XPM 1 + +/* Define this if you have the Xmu library. This is standard part of X, and + * if your vendor doesn't ship it, you should report that as a bug. + */ +#define HAVE_XMU 1 + +/* Define this if you have OpenGL. Some of the demos require it, so if you + * don't have it, then those particular demos won't be built. (This won't + * affect the screen saver as a whole.) + */ +#undef HAVE_GL + +/* Define this if you have OpenGL, but it's the MesaGL variant. (The + libraries have different names.) (HAVE_GL should be defined too.) + */ +#undef HAVE_MESA_GL + +/* Define this if your version of OpenGL has the glBindTexture() routine. + This is the case for OpenGL 1.1, but not for OpenGL 1.0. + */ +#undef HAVE_GLBINDTEXTURE + +/* Define this if you have the X Shared Memory Extension. + */ +#undef HAVE_XSHM_EXTENSION + + +/* ************************************************************************* + CONFIGURING PASSWORD AUTHENTICATION + ************************************************************************* */ + +/* Define this to remove the option of locking the screen at all. + */ +#undef NO_LOCKING + +/* Define this if you want to use Kerberos authentication to lock/unlock the + * screen instead of your local password. This currently uses Kerberos V4, + * but a V5 server with V4 compatibility will work. WARNING: DO NOT USE AFS + * string-to-key passwords with this option. This option currently *only* + * works with standard Kerberos des_string_to_key. If your password is an + * AFS password and not a kerberos password, it will not authenticate + * properly. See the comments in driver/kpasswd.c for more information if you + * need it. + */ +#undef HAVE_KERBEROS + + +/* Define this if your system uses `shadow' passwords, that is, the passwords + * live in /etc/shadow instead of /etc/passwd, and one reads them with + * getspnam() instead of getpwnam(). (Note that SCO systems do some random + * other thing; others might as well. See the ifdefs in driver/passwd.c if + * you're having trouble related to reading passwords.) + */ +#undef HAVE_SHADOW_PASSWD + +/* Define this if your system is Digital or SCO Unix with so-called ``Enhanced + Security'', that is, the passwords live in /tcb/files/auth// + instead of in /etc/passwd, and one reads them with getprpwnam() instead + of getpwnam(). + */ +#undef HAVE_ENHANCED_PASSWD + +/* Define this if your system is Solaris with ``adjunct'' passwords (this is + the version where one gets at the passwords with getpwanam() instead of + getpwnam().) I haven't tested this one, let me know if it works. + */ +#undef HAVE_ADJUNCT_PASSWD + +/* Define this if you are running HPUX with so-called ``Secure Passwords'' + (if you have /usr/include/hpsecurity.h, you probably have this.) I + haven't tested this one, let me know if it works. + */ +#undef HAVE_HPUX_PASSWD + +/* Define this if you are on a system that supports the VT_LOCKSWITCH and + VT_UNLOCKSWITCH ioctls. If this is defined, then when the screen is + locked, switching to another virtual terminal will also be prevented. + That is, the whole console will be locked, rather than just the VT on + which X is running. + */ +#define HAVE_VT_LOCKSWITCH 1 + + +/* ************************************************************************* + OTHER C ENVIRONMENT JUNK + ************************************************************************* */ + +/* Define this to void* if you're using X11R4 or earlier. */ +#undef XPointer + +/* Define if you have the nice function. */ +#undef HAVE_NICE + +/* Define if you have the setpriority function. */ +#undef HAVE_SETPRIORITY + +/* Define to empty if the keyword does not work. */ +#undef const + +/* Define if you have that is POSIX.1 compatible. */ +#undef HAVE_SYS_WAIT_H + +/* Define as __inline if that's what the C compiler calls it. */ +#undef inline + +/* Define to `int' if doesn't define. */ +#undef mode_t + +/* Define to `int' if doesn't define. */ +#undef pid_t + +/* Define as the return type of signal handlers (int or void). */ +#define RETSIGTYPE void + +/* Define to `unsigned' if doesn't define. */ +#undef size_t + +/* Define if you have the ANSI C header files. */ +#define STDC_HEADERS 1 + +/* Define if you can safely include both and . */ +#undef TIME_WITH_SYS_TIME + +/* Define if you have the gettimeofday function. */ +#undef HAVE_GETTIMEOFDAY + +/* Define if gettimeofday requires two arguments. */ +#undef GETTIMEOFDAY_TWO_ARGS + +/* Define if you have the putenv function. */ +#undef HAVE_PUTENV + +/* Define if you have the select function. */ +#undef HAVE_SELECT + +/* Define if you have the getcwd function. */ +#undef HAVE_GETCWD + +/* Define if you have the getcwd function. */ +#undef HAVE_GETWD + +/* Define if you have the uname function. */ +#undef HAVE_UNAME +#if (__VMS_VER >= 70000000) +# define HAVE_UNAME 1 +#endif + +/* Define if you have the fcntl function. */ +#undef HAVE_FCNTL + +/* Define if you have the sigaction function. */ +#undef HAVE_SIGACTION + +/* Define if you have the header file. */ +#undef HAVE_UNISTD_H + +/* Define if you have the header file. */ +#undef HAVE_CRYPT_H + +/* Define to use sigaction() instead of signal() for SIGCHLD-related activity. + This is necessary at least on SCO OpenServer 5, due to a Unix kernel bug. + */ +#undef USE_SIGACTION diff --git a/config.h.in b/config.h.in new file mode 100644 index 00000000..c11d0e63 --- /dev/null +++ b/config.h.in @@ -0,0 +1,489 @@ +/* config.h.in. Generated from configure.in by autoheader. */ + + +/* config.h.in --- xscreensaver, Copyright (c) 1998-2000 Jamie Zawinski. + * + * The best way to set these parameters is by running the included `configure' + * script. That examines your system, and generates `config.h' from + * `config.h.in'. + * + * If something goes very wrong, you can edit `config.h' directly, but beware + * that your changes will be lost if you ever run `configure' again. + */ + + +/* Define this to allow the root password to unlock the screen. */ +#undef ALLOW_ROOT_PASSWD + +/* Define to one of `_getb67', `GETB67', `getb67' for Cray-2 and Cray-YMP + systems. This function is required for `alloca.c' support on those systems. + */ +#undef CRAY_STACKSEG_END + +/* Define to 1 if using `alloca.c'. */ +#undef C_ALLOCA + +/* always defined to indicate that i18n is enabled */ +#undef ENABLE_NLS + +/* Some screenhacks like to run an external program to generate random pieces + of text; set this to the one you like. Note that this is just the default; + X resources can be used to override it. */ +#undef FORTUNE_PROGRAM + +/* This is the name of the gettext package to use. */ +#undef GETTEXT_PACKAGE + +/* Define this if gettimeofday() takes two arguments. */ +#undef GETTIMEOFDAY_TWO_ARGS + +/* Define this if your system is Solaris with ``adjunct'' passwords (this is + the version where one gets at the passwords with getpwanam() instead of + getpwnam().) I haven't tested this one, let me know if it works. */ +#undef HAVE_ADJUNCT_PASSWD + +/* Define to 1 if you have `alloca', as a function or macro. */ +#undef HAVE_ALLOCA + +/* Define to 1 if you have and it should be used (not on Ultrix). + */ +#undef HAVE_ALLOCA_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_ARGZ_H + +/* Define this if you have Gnome and want to build support for the + xscreensaver control panel in the Gnome Control Center (gnomecc). (This is + needed only with Gtk 1.x.) */ +#undef HAVE_CRAPPLET + +/* Define this if HAVE_CRAPPLET is defined, and the function + capplet_widget_changes_are_immediate() is available. */ +#undef HAVE_CRAPPLET_IMMEDIATE + +/* Define to 1 if you have the header file. */ +#undef HAVE_CRYPT_H + +/* Define to 1 if you have the `dcgettext' function. */ +#undef HAVE_DCGETTEXT + +/* Define to 1 if you have the header file, and it defines `DIR'. + */ +#undef HAVE_DIRENT_H + +/* Define this if you have the X Double Buffer Extension. */ +#undef HAVE_DOUBLE_BUFFER_EXTENSION + +/* Define this if you have the XDPMS extension. This is standard on + sufficiently-recent XFree86 systems, and possibly elsewhere. (It's + available if the file /usr/include/X11/extensions/dpms.h exists.) */ +#undef HAVE_DPMS_EXTENSION + +/* Define this if your system is Digital or SCO Unix with so-called ``Enhanced + Security'', that is, the passwords live in /tcb/files/auth// + instead of in /etc/passwd, and one reads them with getprpwnam() instead of + getpwnam(). */ +#undef HAVE_ENHANCED_PASSWD + +/* Define to 1 if you have the `fcntl' function. */ +#undef HAVE_FCNTL + +/* Define this if you have the 'forkpty' function: This allows 'phosphor' and + 'apple2' to run curses-based programs, or be used as terminal windows. */ +#undef HAVE_FORKPTY + +/* Define this if you have the GDK_Pixbuf library installed. Some of the demos + can make use of this if it is available. */ +#undef HAVE_GDK_PIXBUF + +/* Define this if you have the gdk_pixbuf_apply_embedded_orientation function + (gdk-pixbuf 2.12). */ +#undef HAVE_GDK_PIXBUF_APPLY_EMBEDDED_ORIENTATION + +/* Define to 1 if you have the `getcwd' function. */ +#undef HAVE_GETCWD + +/* Define this if you have the getifaddrs() function. */ +#undef HAVE_GETIFADDRS + +/* Define to 1 if you have the `getpagesize' function. */ +#undef HAVE_GETPAGESIZE + +/* Define if the GNU gettext() function is already present or preinstalled. */ +#undef HAVE_GETTEXT + +/* Define this if you have the gettimeofday function. */ +#undef HAVE_GETTIMEOFDAY + +/* Define to 1 if you have the `getwd' function. */ +#undef HAVE_GETWD + +/* Define this if you have OpenGL. Some of the demos require it, so if you + don't have it, then those particular demos won't be built. (This won't + affect the screen saver as a whole.) */ +#undef HAVE_GL + +/* Define this if your version of OpenGL has the glBindTexture() routine. This + is the case for OpenGL 1.1, but not for OpenGL 1.0. */ +#undef HAVE_GLBINDTEXTURE + +/* Define this if glBitmap exists. */ +#undef HAVE_GLBITMAP + +/* Define this if you have the -lgle and -lmatrix libraries (GL extrusion.) */ +#undef HAVE_GLE + +/* Define this if you have the -lgle from GLE version 3 */ +#undef HAVE_GLE3 + +/* Define this if you have Gtk (any version.) */ +#undef HAVE_GTK + +/* Define this if you have Gtk 2.x. */ +#undef HAVE_GTK2 + +/* Define this if you are running HPUX with so-called ``Secure Passwords'' (if + you have /usr/include/hpsecurity.h, you probably have this.) I haven't + tested this one, let me know if it works. */ +#undef HAVE_HPUX_PASSWD + +/* Define this if you do pings with a `struct icmp' and an `icmp_id' slot. */ +#undef HAVE_ICMP + +/* Define this if you do pings with a `struct icmphdr' and an `un.echo.id' + slot. */ +#undef HAVE_ICMPHDR + +/* Define to 1 if you have the header file. */ +#undef HAVE_INTTYPES_H + +/* Define this if you have the Independent JPEG Group's JPEG library + installed. Some of the demos can make use of this if it is available. */ +#undef HAVE_JPEGLIB + +/* Define this to target the OpenGL ES 1.x API instead of OpenGL 1.3. */ +#undef HAVE_JWZGLES + +/* Define this if you want to use Kerberos authentication to lock/unlock the + screen instead of your local password. This currently uses Kerberos V4, but + a V5 server with V4 compatibility will work. WARNING: DO NOT USE AFS + string-to-key passwords with this option. This option currently *only* + works with standard Kerberos des_string_to_key. If your password is an AFS + password and not a kerberos password, it will not authenticate properly. + See the comments in driver/kpasswd.c for more information if you need it. + */ +#undef HAVE_KERBEROS + +/* Define this if you have Kerberos 5, meaning we need to use the Kerberos 4 + compatibility layer. */ +#undef HAVE_KERBEROS5 + +/* Define if your file defines LC_MESSAGES. */ +#undef HAVE_LC_MESSAGES + +/* Define to 1 if you have the header file. */ +#undef HAVE_LIMITS_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_LOCALE_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_MALLOC_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_MEMORY_H + +/* Define this if you have OpenGL, but it's the MesaGL variant. (The libraries + have different names.) (HAVE_GL should be defined too.) */ +#undef HAVE_MESA_GL + +/* Define to 1 if you have a working `mmap' system call. */ +#undef HAVE_MMAP + +/* Define this if you have Motif. */ +#undef HAVE_MOTIF + +/* Define to 1 if you have the `munmap' function. */ +#undef HAVE_MUNMAP + +/* Define to 1 if you have the header file, and it defines `DIR'. */ +#undef HAVE_NDIR_H + +/* Define to 1 if you have the `nice' function. */ +#undef HAVE_NICE + +/* Define to 1 if you have the header file. */ +#undef HAVE_NL_TYPES_H + +/* Define this if you have the XML library headers in their old, + non-namespaced location (you lack the gnome-xml/libxml symlink) */ +#undef HAVE_OLD_XML_HEADERS + +/* Define this if you want to use PAM (Pluggable Authentication Modules) to + lock/unlock the screen, instead of standard /etc/passwd authentication. */ +#undef HAVE_PAM + +/* Define this if you have pam_fail_delay function. see driver/passwd-pam.c. + */ +#undef HAVE_PAM_FAIL_DELAY + +/* Define this if you have a Linux-like /proc/interrupts file which can be + examined to determine when keyboard activity has occurred. */ +#undef HAVE_PROC_INTERRUPTS + +/* Define to 1 if you have the header file. */ +#undef HAVE_PTY_H + +/* Define to 1 if you have the `putenv' function. */ +#undef HAVE_PUTENV + +/* Define this if you have the Resize and Rotate extension. This is standard + on sufficiently-recent XFree86 systems, and possibly elsewhere. (It's + available if the file /usr/include/X11/extensions/Xrandr.h exists.) */ +#undef HAVE_RANDR + +/* Define this if the RANDR library is version 1.2 or newer. */ +#undef HAVE_RANDR_12 + +/* Define this if you have the XReadDisplay extension (I think this is an + SGI-only thing; it's in .) A few of the + screenhacks will take advantage of this if it's available. */ +#undef HAVE_READ_DISPLAY_EXTENSION + +/* Define to 1 if you have the `realpath' function. */ +#undef HAVE_REALPATH + +/* Define to 1 if you have the `sbrk' function. */ +#undef HAVE_SBRK + +/* Define to 1 if you have the `select' function. */ +#undef HAVE_SELECT + +/* Define to 1 if you have the `setenv' function. */ +#undef HAVE_SETENV + +/* Define to 1 if you have the `setlocale' function. */ +#undef HAVE_SETLOCALE + +/* Define to 1 if you have the `setpriority' function. */ +#undef HAVE_SETPRIORITY + +/* Define to 1 if you have the `setrlimit' function. */ +#undef HAVE_SETRLIMIT + +/* Define this if your system uses 'shadow' passwords, that is, the passwords + live in /etc/shadow instead of /etc/passwd, and one reads them with + getspnam() instead of getpwnam(). (Note that SCO systems do some random + other thing; others might as well. See the ifdefs in driver/passwd-pwent.c + if you're having trouble related to reading passwords.) */ +#undef HAVE_SHADOW_PASSWD + +/* Define to 1 if you have the `sigaction' function. */ +#undef HAVE_SIGACTION + +/* Define to 1 if you have the `sigtimedwait' function. */ +#undef HAVE_SIGTIMEDWAIT + +/* Define to 1 if you have the header file. */ +#undef HAVE_STDINT_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_STDLIB_H + +/* Define to 1 if you have the `strcasecmp' function. */ +#undef HAVE_STRCASECMP + +/* Define to 1 if you have the `strchr' function. */ +#undef HAVE_STRCHR + +/* Define to 1 if you have the `strdup' function. */ +#undef HAVE_STRDUP + +/* Define to 1 if you have the header file. */ +#undef HAVE_STRINGS_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_STRING_H + +/* Define to 1 if you have the `syslog' function. */ +#undef HAVE_SYSLOG + +/* Define to 1 if you have the header file, and it defines `DIR'. + */ +#undef HAVE_SYS_DIR_H + +/* Define to 1 if you have the header file, and it defines `DIR'. + */ +#undef HAVE_SYS_NDIR_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_SYS_PARAM_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_SYS_SELECT_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_SYS_STAT_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_SYS_TYPES_H + +/* Define to 1 if you have that is POSIX.1 compatible. */ +#undef HAVE_SYS_WAIT_H + +/* Define to 1 if you have the `uname' function. */ +#undef HAVE_UNAME + +/* Define to 1 if you have the header file. */ +#undef HAVE_UNISTD_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_UTIL_H + +/* Define this if you have the XF86MiscSetGrabKeysState function (which allows + the Ctrl-Alt-KP_star and Ctrl-Alt-KP_slash key sequences to be temporarily + disabled. Sadly, it doesn't affect Ctrl-Alt-BS or Ctrl-Alt-F1.) */ +#undef HAVE_XF86MISCSETGRABKEYSSTATE + +/* Define this if you have the functions XF86VidModeGetModeLine() and + XF86VidModeGetViewPort(), in support of virtual desktops where the X + server's root window is bigger than the actual screen. This is an XFree86 + thing, and probably doesn't exist elsewhere. (It's available if the file + /usr/include/X11/extensions/xf86vmode.h exists.) */ +#undef HAVE_XF86VMODE + +/* Define this if you have the functions XF86VidModeGetGamma() and + XF86VidModeSetGamma(), which allow clients to change the gamma response of + the monitor. This is an XFree86 4.0.x thing, and probably doesn't exist + elsewhere. (It's available if the file + /usr/include/X11/extensions/xf86vmode.h exists and has stuff about gamma in + it.) */ +#undef HAVE_XF86VMODE_GAMMA + +/* Define this if you have the functions XF86VidModeGetGammaRamp() and + XF86VidModeSetGammaRamp(), which provide finer-grained control than + XF86VidMode[GS]etGamma(). These appeared in XFree86 4.1.0. */ +#undef HAVE_XF86VMODE_GAMMA_RAMP + +/* Define this if you have the XHPDisableReset function (an HP only thing + which allows the Ctrl-Sh-Reset key sequence to be temporarily disabled.) */ +#undef HAVE_XHPDISABLERESET + +/* Define this if you have the Xinerama extension. This is standard on + sufficiently-recent XFree86 systems, and possibly elsewhere. (It's + available if the file /usr/include/X11/extensions/Xinerama.h exists.) */ +#undef HAVE_XINERAMA + +/* Define this if you have the Xinput extension. This is standard since X11R5, + and is thus almost everywhere. (It's available if the file + /usr/include/X11/extensions/XInput.h exists.) */ +#undef HAVE_XINPUT + +/* Define this if you have the XmComboBox Motif widget (Motif 2.0.) */ +#undef HAVE_XMCOMBOBOX + +/* Define this if you have the XML library. */ +#undef HAVE_XML + +/* Define this if you have the Xmu library. This is standard part of X, and if + your vendor doesn't ship it, you should report that as a bug. */ +#undef HAVE_XMU + +/* Define this if you have the XPM library installed. Some of the demos can + make use of this if it is available. */ +#undef HAVE_XPM + +/* Define this if you have the X Shared Memory Extension. */ +#undef HAVE_XSHM_EXTENSION + +/* Define to 1 if you have the `__argz_count' function. */ +#undef HAVE___ARGZ_COUNT + +/* Define to 1 if you have the `__argz_next' function. */ +#undef HAVE___ARGZ_NEXT + +/* Define to 1 if you have the `__argz_stringify' function. */ +#undef HAVE___ARGZ_STRINGIFY + +/* Define this to remove the option of locking the screen at all. */ +#undef NO_LOCKING + +/* This is the same as GETTEXT_PACKAGE, but for the glade generated code. */ +#undef PACKAGE + +/* Define to the address where bug reports for this package should be sent. */ +#undef PACKAGE_BUGREPORT + +/* Define to the full name of this package. */ +#undef PACKAGE_NAME + +/* Define to the full name and version of this package. */ +#undef PACKAGE_STRING + +/* Define to the one symbol short name of this package. */ +#undef PACKAGE_TARNAME + +/* Define to the version of this package. */ +#undef PACKAGE_VERSION + +/* Whether PAM should check the result of account modules when authenticating. + Only do this if you have account configured properly on your system. */ +#undef PAM_CHECK_ACCOUNT_TYPE + +/* If PAM is being used, this is the name of the PAM service that xscreensaver + will authenticate as. The default is "xscreensaver", which means that the + PAM library will look for an "xscreensaver" line in /etc/pam.conf, or (on + recent Linux systems) will look for a file called /etc/pam.d/xscreensaver. + Some systems might already have a PAM installation that is configured for + xlock, so setting this to "xlock" would also work in that case. */ +#undef PAM_SERVICE_NAME + +/* Define if you have PAM and pam_strerror() requires two arguments. */ +#undef PAM_STRERROR_TWO_ARGS + +/* Set the name of the password helper program, if any */ +#undef PASSWD_HELPER_PROGRAM + +/* Define as the return type of signal handlers (`int' or `void'). */ +#undef RETSIGTYPE + +/* If using the C implementation of alloca, define if you know the + direction of stack growth for your system; otherwise it will be + automatically deduced at runtime. + STACK_DIRECTION > 0 => grows toward higher addresses + STACK_DIRECTION < 0 => grows toward lower addresses + STACK_DIRECTION = 0 => direction of growth unknown */ +#undef STACK_DIRECTION + +/* Define to 1 if you have the ANSI C header files. */ +#undef STDC_HEADERS + +/* Define to 1 if you can safely include both and . */ +#undef TIME_WITH_SYS_TIME + +/* Define this to void* if you're using X11R4 or earlier. */ +#undef XPointer + +/* Define to 1 if the X Window System is missing or not being used. */ +#undef X_DISPLAY_MISSING + +/* Define to empty if `const' does not conform to ANSI C. */ +#undef const + +/* Define to `__inline__' or `__inline' if that's what the C compiler + calls it, or to nothing if 'inline' is not supported under any name. */ +#ifndef __cplusplus +#undef inline +#endif + +/* Define to `int' if does not define. */ +#undef mode_t + +/* Define to `long int' if does not define. */ +#undef off_t + +/* Define to `int' if does not define. */ +#undef pid_t + +/* Define to `unsigned int' if does not define. */ +#undef size_t diff --git a/config.sub b/config.sub new file mode 100755 index 00000000..c060f448 --- /dev/null +++ b/config.sub @@ -0,0 +1,1626 @@ +#! /bin/sh +# Configuration validation subroutine script. +# Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, +# 2000, 2001, 2002, 2003, 2004, 2005, 2006 Free Software Foundation, +# Inc. + +timestamp='2007-04-29' + +# This file is (in principle) common to ALL GNU software. +# The presence of a machine in this file suggests that SOME GNU software +# can handle that machine. It does not imply ALL GNU software can. +# +# This file is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA +# 02110-1301, USA. +# +# As a special exception to the GNU General Public License, if you +# distribute this file as part of a program that contains a +# configuration script generated by Autoconf, you may include it under +# the same distribution terms that you use for the rest of that program. + + +# Please send patches to . Submit a context +# diff and a properly formatted ChangeLog entry. +# +# Configuration subroutine to validate and canonicalize a configuration type. +# Supply the specified configuration type as an argument. +# If it is invalid, we print an error message on stderr and exit with code 1. +# Otherwise, we print the canonical config type on stdout and succeed. + +# This file is supposed to be the same for all GNU packages +# and recognize all the CPU types, system types and aliases +# that are meaningful with *any* GNU software. +# Each package is responsible for reporting which valid configurations +# it does not support. The user should be able to distinguish +# a failure to support a valid configuration from a meaningless +# configuration. + +# The goal of this file is to map all the various variations of a given +# machine specification into a single specification in the form: +# CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM +# or in some cases, the newer four-part form: +# CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM +# It is wrong to echo any other type of specification. + +me=`echo "$0" | sed -e 's,.*/,,'` + +usage="\ +Usage: $0 [OPTION] CPU-MFR-OPSYS + $0 [OPTION] ALIAS + +Canonicalize a configuration name. + +Operation modes: + -h, --help print this help, then exit + -t, --time-stamp print date of last modification, then exit + -v, --version print version number, then exit + +Report bugs and patches to ." + +version="\ +GNU config.sub ($timestamp) + +Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005 +Free Software Foundation, Inc. + +This is free software; see the source for copying conditions. There is NO +warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE." + +help=" +Try \`$me --help' for more information." + +# Parse command line +while test $# -gt 0 ; do + case $1 in + --time-stamp | --time* | -t ) + echo "$timestamp" ; exit ;; + --version | -v ) + echo "$version" ; exit ;; + --help | --h* | -h ) + echo "$usage"; exit ;; + -- ) # Stop option processing + shift; break ;; + - ) # Use stdin as input. + break ;; + -* ) + echo "$me: invalid option $1$help" + exit 1 ;; + + *local*) + # First pass through any local machine types. + echo $1 + exit ;; + + * ) + break ;; + esac +done + +case $# in + 0) echo "$me: missing argument$help" >&2 + exit 1;; + 1) ;; + *) echo "$me: too many arguments$help" >&2 + exit 1;; +esac + +# Separate what the user gave into CPU-COMPANY and OS or KERNEL-OS (if any). +# Here we must recognize all the valid KERNEL-OS combinations. +maybe_os=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\2/'` +case $maybe_os in + nto-qnx* | linux-gnu* | linux-dietlibc | linux-newlib* | linux-uclibc* | \ + uclinux-uclibc* | uclinux-gnu* | kfreebsd*-gnu* | knetbsd*-gnu* | netbsd*-gnu* | \ + storm-chaos* | os2-emx* | rtmk-nova*) + os=-$maybe_os + basic_machine=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'` + ;; + *) + basic_machine=`echo $1 | sed 's/-[^-]*$//'` + if [ $basic_machine != $1 ] + then os=`echo $1 | sed 's/.*-/-/'` + else os=; fi + ;; +esac + +### Let's recognize common machines as not being operating systems so +### that things like config.sub decstation-3100 work. We also +### recognize some manufacturers as not being operating systems, so we +### can provide default operating systems below. +case $os in + -sun*os*) + # Prevent following clause from handling this invalid input. + ;; + -dec* | -mips* | -sequent* | -encore* | -pc532* | -sgi* | -sony* | \ + -att* | -7300* | -3300* | -delta* | -motorola* | -sun[234]* | \ + -unicom* | -ibm* | -next | -hp | -isi* | -apollo | -altos* | \ + -convergent* | -ncr* | -news | -32* | -3600* | -3100* | -hitachi* |\ + -c[123]* | -convex* | -sun | -crds | -omron* | -dg | -ultra | -tti* | \ + -harris | -dolphin | -highlevel | -gould | -cbm | -ns | -masscomp | \ + -apple | -axis | -knuth | -cray) + os= + basic_machine=$1 + ;; + -sim | -cisco | -oki | -wec | -winbond) + os= + basic_machine=$1 + ;; + -scout) + ;; + -wrs) + os=-vxworks + basic_machine=$1 + ;; + -chorusos*) + os=-chorusos + basic_machine=$1 + ;; + -chorusrdb) + os=-chorusrdb + basic_machine=$1 + ;; + -hiux*) + os=-hiuxwe2 + ;; + -sco6) + os=-sco5v6 + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -sco5) + os=-sco3.2v5 + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -sco4) + os=-sco3.2v4 + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -sco3.2.[4-9]*) + os=`echo $os | sed -e 's/sco3.2./sco3.2v/'` + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -sco3.2v[4-9]*) + # Don't forget version if it is 3.2v4 or newer. + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -sco5v6*) + # Don't forget version if it is 3.2v4 or newer. + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -sco*) + os=-sco3.2v2 + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -udk*) + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -isc) + os=-isc2.2 + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -clix*) + basic_machine=clipper-intergraph + ;; + -isc*) + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -lynx*) + os=-lynxos + ;; + -ptx*) + basic_machine=`echo $1 | sed -e 's/86-.*/86-sequent/'` + ;; + -windowsnt*) + os=`echo $os | sed -e 's/windowsnt/winnt/'` + ;; + -psos*) + os=-psos + ;; + -mint | -mint[0-9]*) + basic_machine=m68k-atari + os=-mint + ;; +esac + +# Decode aliases for certain CPU-COMPANY combinations. +case $basic_machine in + # Recognize the basic CPU types without company name. + # Some are omitted here because they have special meanings below. + 1750a | 580 \ + | a29k \ + | alpha | alphaev[4-8] | alphaev56 | alphaev6[78] | alphapca5[67] \ + | alpha64 | alpha64ev[4-8] | alpha64ev56 | alpha64ev6[78] | alpha64pca5[67] \ + | am33_2.0 \ + | arc | arm | arm[bl]e | arme[lb] | armv[2345] | armv[345][lb] | avr | avr32 \ + | bfin \ + | c4x | clipper \ + | d10v | d30v | dlx | dsp16xx \ + | fido | fr30 | frv \ + | h8300 | h8500 | hppa | hppa1.[01] | hppa2.0 | hppa2.0[nw] | hppa64 \ + | i370 | i860 | i960 | ia64 \ + | ip2k | iq2000 \ + | m32c | m32r | m32rle | m68000 | m68k | m88k \ + | maxq | mb | microblaze | mcore | mep \ + | mips | mipsbe | mipseb | mipsel | mipsle \ + | mips16 \ + | mips64 | mips64el \ + | mips64vr | mips64vrel \ + | mips64orion | mips64orionel \ + | mips64vr4100 | mips64vr4100el \ + | mips64vr4300 | mips64vr4300el \ + | mips64vr5000 | mips64vr5000el \ + | mips64vr5900 | mips64vr5900el \ + | mipsisa32 | mipsisa32el \ + | mipsisa32r2 | mipsisa32r2el \ + | mipsisa64 | mipsisa64el \ + | mipsisa64r2 | mipsisa64r2el \ + | mipsisa64sb1 | mipsisa64sb1el \ + | mipsisa64sr71k | mipsisa64sr71kel \ + | mipstx39 | mipstx39el \ + | mn10200 | mn10300 \ + | mt \ + | msp430 \ + | nios | nios2 \ + | ns16k | ns32k \ + | or32 \ + | pdp10 | pdp11 | pj | pjl \ + | powerpc | powerpc64 | powerpc64le | powerpcle | ppcbe \ + | pyramid \ + | score \ + | sh | sh[1234] | sh[24]a | sh[23]e | sh[34]eb | sheb | shbe | shle | sh[1234]le | sh3ele \ + | sh64 | sh64le \ + | sparc | sparc64 | sparc64b | sparc64v | sparc86x | sparclet | sparclite \ + | sparcv8 | sparcv9 | sparcv9b | sparcv9v \ + | spu | strongarm \ + | tahoe | thumb | tic4x | tic80 | tron \ + | v850 | v850e \ + | we32k \ + | x86 | xc16x | xscale | xscalee[bl] | xstormy16 | xtensa \ + | z8k) + basic_machine=$basic_machine-unknown + ;; + m6811 | m68hc11 | m6812 | m68hc12) + # Motorola 68HC11/12. + basic_machine=$basic_machine-unknown + os=-none + ;; + m88110 | m680[12346]0 | m683?2 | m68360 | m5200 | v70 | w65 | z8k) + ;; + ms1) + basic_machine=mt-unknown + ;; + + # We use `pc' rather than `unknown' + # because (1) that's what they normally are, and + # (2) the word "unknown" tends to confuse beginning users. + i*86 | x86_64) + basic_machine=$basic_machine-pc + ;; + # Object if more than one company name word. + *-*-*) + echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2 + exit 1 + ;; + # Recognize the basic CPU types with company name. + 580-* \ + | a29k-* \ + | alpha-* | alphaev[4-8]-* | alphaev56-* | alphaev6[78]-* \ + | alpha64-* | alpha64ev[4-8]-* | alpha64ev56-* | alpha64ev6[78]-* \ + | alphapca5[67]-* | alpha64pca5[67]-* | arc-* \ + | arm-* | armbe-* | armle-* | armeb-* | armv*-* \ + | avr-* | avr32-* \ + | bfin-* | bs2000-* \ + | c[123]* | c30-* | [cjt]90-* | c4x-* | c54x-* | c55x-* | c6x-* \ + | clipper-* | craynv-* | cydra-* \ + | d10v-* | d30v-* | dlx-* \ + | elxsi-* \ + | f30[01]-* | f700-* | fido-* | fr30-* | frv-* | fx80-* \ + | h8300-* | h8500-* \ + | hppa-* | hppa1.[01]-* | hppa2.0-* | hppa2.0[nw]-* | hppa64-* \ + | i*86-* | i860-* | i960-* | ia64-* \ + | ip2k-* | iq2000-* \ + | m32c-* | m32r-* | m32rle-* \ + | m68000-* | m680[012346]0-* | m68360-* | m683?2-* | m68k-* \ + | m88110-* | m88k-* | maxq-* | mcore-* \ + | mips-* | mipsbe-* | mipseb-* | mipsel-* | mipsle-* \ + | mips16-* \ + | mips64-* | mips64el-* \ + | mips64vr-* | mips64vrel-* \ + | mips64orion-* | mips64orionel-* \ + | mips64vr4100-* | mips64vr4100el-* \ + | mips64vr4300-* | mips64vr4300el-* \ + | mips64vr5000-* | mips64vr5000el-* \ + | mips64vr5900-* | mips64vr5900el-* \ + | mipsisa32-* | mipsisa32el-* \ + | mipsisa32r2-* | mipsisa32r2el-* \ + | mipsisa64-* | mipsisa64el-* \ + | mipsisa64r2-* | mipsisa64r2el-* \ + | mipsisa64sb1-* | mipsisa64sb1el-* \ + | mipsisa64sr71k-* | mipsisa64sr71kel-* \ + | mipstx39-* | mipstx39el-* \ + | mmix-* \ + | mt-* \ + | msp430-* \ + | nios-* | nios2-* \ + | none-* | np1-* | ns16k-* | ns32k-* \ + | orion-* \ + | pdp10-* | pdp11-* | pj-* | pjl-* | pn-* | power-* \ + | powerpc-* | powerpc64-* | powerpc64le-* | powerpcle-* | ppcbe-* \ + | pyramid-* \ + | romp-* | rs6000-* \ + | sh-* | sh[1234]-* | sh[24]a-* | sh[23]e-* | sh[34]eb-* | sheb-* | shbe-* \ + | shle-* | sh[1234]le-* | sh3ele-* | sh64-* | sh64le-* \ + | sparc-* | sparc64-* | sparc64b-* | sparc64v-* | sparc86x-* | sparclet-* \ + | sparclite-* \ + | sparcv8-* | sparcv9-* | sparcv9b-* | sparcv9v-* | strongarm-* | sv1-* | sx?-* \ + | tahoe-* | thumb-* \ + | tic30-* | tic4x-* | tic54x-* | tic55x-* | tic6x-* | tic80-* \ + | tron-* \ + | v850-* | v850e-* | vax-* \ + | we32k-* \ + | x86-* | x86_64-* | xc16x-* | xps100-* | xscale-* | xscalee[bl]-* \ + | xstormy16-* | xtensa-* \ + | ymp-* \ + | z8k-*) + ;; + # Recognize the various machine names and aliases which stand + # for a CPU type and a company and sometimes even an OS. + 386bsd) + basic_machine=i386-unknown + os=-bsd + ;; + 3b1 | 7300 | 7300-att | att-7300 | pc7300 | safari | unixpc) + basic_machine=m68000-att + ;; + 3b*) + basic_machine=we32k-att + ;; + a29khif) + basic_machine=a29k-amd + os=-udi + ;; + abacus) + basic_machine=abacus-unknown + ;; + adobe68k) + basic_machine=m68010-adobe + os=-scout + ;; + alliant | fx80) + basic_machine=fx80-alliant + ;; + altos | altos3068) + basic_machine=m68k-altos + ;; + am29k) + basic_machine=a29k-none + os=-bsd + ;; + amd64) + basic_machine=x86_64-pc + ;; + amd64-*) + basic_machine=x86_64-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + amdahl) + basic_machine=580-amdahl + os=-sysv + ;; + amiga | amiga-*) + basic_machine=m68k-unknown + ;; + amigaos | amigados) + basic_machine=m68k-unknown + os=-amigaos + ;; + amigaunix | amix) + basic_machine=m68k-unknown + os=-sysv4 + ;; + apollo68) + basic_machine=m68k-apollo + os=-sysv + ;; + apollo68bsd) + basic_machine=m68k-apollo + os=-bsd + ;; + aux) + basic_machine=m68k-apple + os=-aux + ;; + balance) + basic_machine=ns32k-sequent + os=-dynix + ;; + c90) + basic_machine=c90-cray + os=-unicos + ;; + convex-c1) + basic_machine=c1-convex + os=-bsd + ;; + convex-c2) + basic_machine=c2-convex + os=-bsd + ;; + convex-c32) + basic_machine=c32-convex + os=-bsd + ;; + convex-c34) + basic_machine=c34-convex + os=-bsd + ;; + convex-c38) + basic_machine=c38-convex + os=-bsd + ;; + cray | j90) + basic_machine=j90-cray + os=-unicos + ;; + craynv) + basic_machine=craynv-cray + os=-unicosmp + ;; + cr16c) + basic_machine=cr16c-unknown + os=-elf + ;; + crds | unos) + basic_machine=m68k-crds + ;; + crisv32 | crisv32-* | etraxfs*) + basic_machine=crisv32-axis + ;; + cris | cris-* | etrax*) + basic_machine=cris-axis + ;; + crx) + basic_machine=crx-unknown + os=-elf + ;; + da30 | da30-*) + basic_machine=m68k-da30 + ;; + decstation | decstation-3100 | pmax | pmax-* | pmin | dec3100 | decstatn) + basic_machine=mips-dec + ;; + decsystem10* | dec10*) + basic_machine=pdp10-dec + os=-tops10 + ;; + decsystem20* | dec20*) + basic_machine=pdp10-dec + os=-tops20 + ;; + delta | 3300 | motorola-3300 | motorola-delta \ + | 3300-motorola | delta-motorola) + basic_machine=m68k-motorola + ;; + delta88) + basic_machine=m88k-motorola + os=-sysv3 + ;; + djgpp) + basic_machine=i586-pc + os=-msdosdjgpp + ;; + dpx20 | dpx20-*) + basic_machine=rs6000-bull + os=-bosx + ;; + dpx2* | dpx2*-bull) + basic_machine=m68k-bull + os=-sysv3 + ;; + ebmon29k) + basic_machine=a29k-amd + os=-ebmon + ;; + elxsi) + basic_machine=elxsi-elxsi + os=-bsd + ;; + encore | umax | mmax) + basic_machine=ns32k-encore + ;; + es1800 | OSE68k | ose68k | ose | OSE) + basic_machine=m68k-ericsson + os=-ose + ;; + fx2800) + basic_machine=i860-alliant + ;; + genix) + basic_machine=ns32k-ns + ;; + gmicro) + basic_machine=tron-gmicro + os=-sysv + ;; + go32) + basic_machine=i386-pc + os=-go32 + ;; + h3050r* | hiux*) + basic_machine=hppa1.1-hitachi + os=-hiuxwe2 + ;; + h8300hms) + basic_machine=h8300-hitachi + os=-hms + ;; + h8300xray) + basic_machine=h8300-hitachi + os=-xray + ;; + h8500hms) + basic_machine=h8500-hitachi + os=-hms + ;; + harris) + basic_machine=m88k-harris + os=-sysv3 + ;; + hp300-*) + basic_machine=m68k-hp + ;; + hp300bsd) + basic_machine=m68k-hp + os=-bsd + ;; + hp300hpux) + basic_machine=m68k-hp + os=-hpux + ;; + hp3k9[0-9][0-9] | hp9[0-9][0-9]) + basic_machine=hppa1.0-hp + ;; + hp9k2[0-9][0-9] | hp9k31[0-9]) + basic_machine=m68000-hp + ;; + hp9k3[2-9][0-9]) + basic_machine=m68k-hp + ;; + hp9k6[0-9][0-9] | hp6[0-9][0-9]) + basic_machine=hppa1.0-hp + ;; + hp9k7[0-79][0-9] | hp7[0-79][0-9]) + basic_machine=hppa1.1-hp + ;; + hp9k78[0-9] | hp78[0-9]) + # FIXME: really hppa2.0-hp + basic_machine=hppa1.1-hp + ;; + hp9k8[67]1 | hp8[67]1 | hp9k80[24] | hp80[24] | hp9k8[78]9 | hp8[78]9 | hp9k893 | hp893) + # FIXME: really hppa2.0-hp + basic_machine=hppa1.1-hp + ;; + hp9k8[0-9][13679] | hp8[0-9][13679]) + basic_machine=hppa1.1-hp + ;; + hp9k8[0-9][0-9] | hp8[0-9][0-9]) + basic_machine=hppa1.0-hp + ;; + hppa-next) + os=-nextstep3 + ;; + hppaosf) + basic_machine=hppa1.1-hp + os=-osf + ;; + hppro) + basic_machine=hppa1.1-hp + os=-proelf + ;; + i370-ibm* | ibm*) + basic_machine=i370-ibm + ;; +# I'm not sure what "Sysv32" means. Should this be sysv3.2? + i*86v32) + basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` + os=-sysv32 + ;; + i*86v4*) + basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` + os=-sysv4 + ;; + i*86v) + basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` + os=-sysv + ;; + i*86sol2) + basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` + os=-solaris2 + ;; + i386mach) + basic_machine=i386-mach + os=-mach + ;; + i386-vsta | vsta) + basic_machine=i386-unknown + os=-vsta + ;; + iris | iris4d) + basic_machine=mips-sgi + case $os in + -irix*) + ;; + *) + os=-irix4 + ;; + esac + ;; + isi68 | isi) + basic_machine=m68k-isi + os=-sysv + ;; + m88k-omron*) + basic_machine=m88k-omron + ;; + magnum | m3230) + basic_machine=mips-mips + os=-sysv + ;; + merlin) + basic_machine=ns32k-utek + os=-sysv + ;; + mingw32) + basic_machine=i386-pc + os=-mingw32 + ;; + mingw32ce) + basic_machine=arm-unknown + os=-mingw32ce + ;; + miniframe) + basic_machine=m68000-convergent + ;; + *mint | -mint[0-9]* | *MiNT | *MiNT[0-9]*) + basic_machine=m68k-atari + os=-mint + ;; + mips3*-*) + basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'` + ;; + mips3*) + basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'`-unknown + ;; + monitor) + basic_machine=m68k-rom68k + os=-coff + ;; + morphos) + basic_machine=powerpc-unknown + os=-morphos + ;; + msdos) + basic_machine=i386-pc + os=-msdos + ;; + ms1-*) + basic_machine=`echo $basic_machine | sed -e 's/ms1-/mt-/'` + ;; + mvs) + basic_machine=i370-ibm + os=-mvs + ;; + ncr3000) + basic_machine=i486-ncr + os=-sysv4 + ;; + netbsd386) + basic_machine=i386-unknown + os=-netbsd + ;; + netwinder) + basic_machine=armv4l-rebel + os=-linux + ;; + news | news700 | news800 | news900) + basic_machine=m68k-sony + os=-newsos + ;; + news1000) + basic_machine=m68030-sony + os=-newsos + ;; + news-3600 | risc-news) + basic_machine=mips-sony + os=-newsos + ;; + necv70) + basic_machine=v70-nec + os=-sysv + ;; + next | m*-next ) + basic_machine=m68k-next + case $os in + -nextstep* ) + ;; + -ns2*) + os=-nextstep2 + ;; + *) + os=-nextstep3 + ;; + esac + ;; + nh3000) + basic_machine=m68k-harris + os=-cxux + ;; + nh[45]000) + basic_machine=m88k-harris + os=-cxux + ;; + nindy960) + basic_machine=i960-intel + os=-nindy + ;; + mon960) + basic_machine=i960-intel + os=-mon960 + ;; + nonstopux) + basic_machine=mips-compaq + os=-nonstopux + ;; + np1) + basic_machine=np1-gould + ;; + nsr-tandem) + basic_machine=nsr-tandem + ;; + op50n-* | op60c-*) + basic_machine=hppa1.1-oki + os=-proelf + ;; + openrisc | openrisc-*) + basic_machine=or32-unknown + ;; + os400) + basic_machine=powerpc-ibm + os=-os400 + ;; + OSE68000 | ose68000) + basic_machine=m68000-ericsson + os=-ose + ;; + os68k) + basic_machine=m68k-none + os=-os68k + ;; + pa-hitachi) + basic_machine=hppa1.1-hitachi + os=-hiuxwe2 + ;; + paragon) + basic_machine=i860-intel + os=-osf + ;; + pbd) + basic_machine=sparc-tti + ;; + pbb) + basic_machine=m68k-tti + ;; + pc532 | pc532-*) + basic_machine=ns32k-pc532 + ;; + pc98) + basic_machine=i386-pc + ;; + pc98-*) + basic_machine=i386-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + pentium | p5 | k5 | k6 | nexgen | viac3) + basic_machine=i586-pc + ;; + pentiumpro | p6 | 6x86 | athlon | athlon_*) + basic_machine=i686-pc + ;; + pentiumii | pentium2 | pentiumiii | pentium3) + basic_machine=i686-pc + ;; + pentium4) + basic_machine=i786-pc + ;; + pentium-* | p5-* | k5-* | k6-* | nexgen-* | viac3-*) + basic_machine=i586-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + pentiumpro-* | p6-* | 6x86-* | athlon-*) + basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + pentiumii-* | pentium2-* | pentiumiii-* | pentium3-*) + basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + pentium4-*) + basic_machine=i786-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + pn) + basic_machine=pn-gould + ;; + power) basic_machine=power-ibm + ;; + ppc) basic_machine=powerpc-unknown + ;; + ppc-*) basic_machine=powerpc-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + ppcle | powerpclittle | ppc-le | powerpc-little) + basic_machine=powerpcle-unknown + ;; + ppcle-* | powerpclittle-*) + basic_machine=powerpcle-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + ppc64) basic_machine=powerpc64-unknown + ;; + ppc64-*) basic_machine=powerpc64-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + ppc64le | powerpc64little | ppc64-le | powerpc64-little) + basic_machine=powerpc64le-unknown + ;; + ppc64le-* | powerpc64little-*) + basic_machine=powerpc64le-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + ps2) + basic_machine=i386-ibm + ;; + pw32) + basic_machine=i586-unknown + os=-pw32 + ;; + rdos) + basic_machine=i386-pc + os=-rdos + ;; + rom68k) + basic_machine=m68k-rom68k + os=-coff + ;; + rm[46]00) + basic_machine=mips-siemens + ;; + rtpc | rtpc-*) + basic_machine=romp-ibm + ;; + s390 | s390-*) + basic_machine=s390-ibm + ;; + s390x | s390x-*) + basic_machine=s390x-ibm + ;; + sa29200) + basic_machine=a29k-amd + os=-udi + ;; + sb1) + basic_machine=mipsisa64sb1-unknown + ;; + sb1el) + basic_machine=mipsisa64sb1el-unknown + ;; + sde) + basic_machine=mipsisa32-sde + os=-elf + ;; + sei) + basic_machine=mips-sei + os=-seiux + ;; + sequent) + basic_machine=i386-sequent + ;; + sh) + basic_machine=sh-hitachi + os=-hms + ;; + sh5el) + basic_machine=sh5le-unknown + ;; + sh64) + basic_machine=sh64-unknown + ;; + sparclite-wrs | simso-wrs) + basic_machine=sparclite-wrs + os=-vxworks + ;; + sps7) + basic_machine=m68k-bull + os=-sysv2 + ;; + spur) + basic_machine=spur-unknown + ;; + st2000) + basic_machine=m68k-tandem + ;; + stratus) + basic_machine=i860-stratus + os=-sysv4 + ;; + sun2) + basic_machine=m68000-sun + ;; + sun2os3) + basic_machine=m68000-sun + os=-sunos3 + ;; + sun2os4) + basic_machine=m68000-sun + os=-sunos4 + ;; + sun3os3) + basic_machine=m68k-sun + os=-sunos3 + ;; + sun3os4) + basic_machine=m68k-sun + os=-sunos4 + ;; + sun4os3) + basic_machine=sparc-sun + os=-sunos3 + ;; + sun4os4) + basic_machine=sparc-sun + os=-sunos4 + ;; + sun4sol2) + basic_machine=sparc-sun + os=-solaris2 + ;; + sun3 | sun3-*) + basic_machine=m68k-sun + ;; + sun4) + basic_machine=sparc-sun + ;; + sun386 | sun386i | roadrunner) + basic_machine=i386-sun + ;; + sv1) + basic_machine=sv1-cray + os=-unicos + ;; + symmetry) + basic_machine=i386-sequent + os=-dynix + ;; + t3e) + basic_machine=alphaev5-cray + os=-unicos + ;; + t90) + basic_machine=t90-cray + os=-unicos + ;; + tic54x | c54x*) + basic_machine=tic54x-unknown + os=-coff + ;; + tic55x | c55x*) + basic_machine=tic55x-unknown + os=-coff + ;; + tic6x | c6x*) + basic_machine=tic6x-unknown + os=-coff + ;; + tx39) + basic_machine=mipstx39-unknown + ;; + tx39el) + basic_machine=mipstx39el-unknown + ;; + toad1) + basic_machine=pdp10-xkl + os=-tops20 + ;; + tower | tower-32) + basic_machine=m68k-ncr + ;; + tpf) + basic_machine=s390x-ibm + os=-tpf + ;; + udi29k) + basic_machine=a29k-amd + os=-udi + ;; + ultra3) + basic_machine=a29k-nyu + os=-sym1 + ;; + v810 | necv810) + basic_machine=v810-nec + os=-none + ;; + vaxv) + basic_machine=vax-dec + os=-sysv + ;; + vms) + basic_machine=vax-dec + os=-vms + ;; + vpp*|vx|vx-*) + basic_machine=f301-fujitsu + ;; + vxworks960) + basic_machine=i960-wrs + os=-vxworks + ;; + vxworks68) + basic_machine=m68k-wrs + os=-vxworks + ;; + vxworks29k) + basic_machine=a29k-wrs + os=-vxworks + ;; + w65*) + basic_machine=w65-wdc + os=-none + ;; + w89k-*) + basic_machine=hppa1.1-winbond + os=-proelf + ;; + xbox) + basic_machine=i686-pc + os=-mingw32 + ;; + xps | xps100) + basic_machine=xps100-honeywell + ;; + ymp) + basic_machine=ymp-cray + os=-unicos + ;; + z8k-*-coff) + basic_machine=z8k-unknown + os=-sim + ;; + none) + basic_machine=none-none + os=-none + ;; + +# Here we handle the default manufacturer of certain CPU types. It is in +# some cases the only manufacturer, in others, it is the most popular. + w89k) + basic_machine=hppa1.1-winbond + ;; + op50n) + basic_machine=hppa1.1-oki + ;; + op60c) + basic_machine=hppa1.1-oki + ;; + romp) + basic_machine=romp-ibm + ;; + mmix) + basic_machine=mmix-knuth + ;; + rs6000) + basic_machine=rs6000-ibm + ;; + vax) + basic_machine=vax-dec + ;; + pdp10) + # there are many clones, so DEC is not a safe bet + basic_machine=pdp10-unknown + ;; + pdp11) + basic_machine=pdp11-dec + ;; + we32k) + basic_machine=we32k-att + ;; + sh[1234] | sh[24]a | sh[34]eb | sh[1234]le | sh[23]ele) + basic_machine=sh-unknown + ;; + sparc | sparcv8 | sparcv9 | sparcv9b | sparcv9v) + basic_machine=sparc-sun + ;; + cydra) + basic_machine=cydra-cydrome + ;; + orion) + basic_machine=orion-highlevel + ;; + orion105) + basic_machine=clipper-highlevel + ;; + mac | mpw | mac-mpw) + basic_machine=m68k-apple + ;; + pmac | pmac-mpw) + basic_machine=powerpc-apple + ;; + *-unknown) + # Make sure to match an already-canonicalized machine name. + ;; + *) + echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2 + exit 1 + ;; +esac + +# Here we canonicalize certain aliases for manufacturers. +case $basic_machine in + *-digital*) + basic_machine=`echo $basic_machine | sed 's/digital.*/dec/'` + ;; + *-commodore*) + basic_machine=`echo $basic_machine | sed 's/commodore.*/cbm/'` + ;; + *) + ;; +esac + +# Decode manufacturer-specific aliases for certain operating systems. + +if [ x"$os" != x"" ] +then +case $os in + # First match some system type aliases + # that might get confused with valid system types. + # -solaris* is a basic system type, with this one exception. + -solaris1 | -solaris1.*) + os=`echo $os | sed -e 's|solaris1|sunos4|'` + ;; + -solaris) + os=-solaris2 + ;; + -svr4*) + os=-sysv4 + ;; + -unixware*) + os=-sysv4.2uw + ;; + -gnu/linux*) + os=`echo $os | sed -e 's|gnu/linux|linux-gnu|'` + ;; + # First accept the basic system types. + # The portable systems comes first. + # Each alternative MUST END IN A *, to match a version number. + # -sysv* is not here because it comes later, after sysvr4. + -gnu* | -bsd* | -mach* | -minix* | -genix* | -ultrix* | -irix* \ + | -*vms* | -sco* | -esix* | -isc* | -aix* | -sunos | -sunos[34]*\ + | -hpux* | -unos* | -osf* | -luna* | -dgux* | -solaris* | -sym* \ + | -amigaos* | -amigados* | -msdos* | -newsos* | -unicos* | -aof* \ + | -aos* \ + | -nindy* | -vxsim* | -vxworks* | -ebmon* | -hms* | -mvs* \ + | -clix* | -riscos* | -uniplus* | -iris* | -rtu* | -xenix* \ + | -hiux* | -386bsd* | -knetbsd* | -mirbsd* | -netbsd* \ + | -openbsd* | -solidbsd* \ + | -ekkobsd* | -kfreebsd* | -freebsd* | -riscix* | -lynxos* \ + | -bosx* | -nextstep* | -cxux* | -aout* | -elf* | -oabi* \ + | -ptx* | -coff* | -ecoff* | -winnt* | -domain* | -vsta* \ + | -udi* | -eabi* | -lites* | -ieee* | -go32* | -aux* \ + | -chorusos* | -chorusrdb* \ + | -cygwin* | -pe* | -psos* | -moss* | -proelf* | -rtems* \ + | -mingw32* | -linux-gnu* | -linux-newlib* | -linux-uclibc* \ + | -uxpv* | -beos* | -mpeix* | -udk* \ + | -interix* | -uwin* | -mks* | -rhapsody* | -darwin* | -opened* \ + | -openstep* | -oskit* | -conix* | -pw32* | -nonstopux* \ + | -storm-chaos* | -tops10* | -tenex* | -tops20* | -its* \ + | -os2* | -vos* | -palmos* | -uclinux* | -nucleus* \ + | -morphos* | -superux* | -rtmk* | -rtmk-nova* | -windiss* \ + | -powermax* | -dnix* | -nx6 | -nx7 | -sei* | -dragonfly* \ + | -skyos* | -haiku* | -rdos* | -toppers* | -drops*) + # Remember, each alternative MUST END IN *, to match a version number. + ;; + -qnx*) + case $basic_machine in + x86-* | i*86-*) + ;; + *) + os=-nto$os + ;; + esac + ;; + -nto-qnx*) + ;; + -nto*) + os=`echo $os | sed -e 's|nto|nto-qnx|'` + ;; + -sim | -es1800* | -hms* | -xray | -os68k* | -none* | -v88r* \ + | -windows* | -osx | -abug | -netware* | -os9* | -beos* | -haiku* \ + | -macos* | -mpw* | -magic* | -mmixware* | -mon960* | -lnews*) + ;; + -mac*) + os=`echo $os | sed -e 's|mac|macos|'` + ;; + -linux-dietlibc) + os=-linux-dietlibc + ;; + -linux*) + os=`echo $os | sed -e 's|linux|linux-gnu|'` + ;; + -sunos5*) + os=`echo $os | sed -e 's|sunos5|solaris2|'` + ;; + -sunos6*) + os=`echo $os | sed -e 's|sunos6|solaris3|'` + ;; + -opened*) + os=-openedition + ;; + -os400*) + os=-os400 + ;; + -wince*) + os=-wince + ;; + -osfrose*) + os=-osfrose + ;; + -osf*) + os=-osf + ;; + -utek*) + os=-bsd + ;; + -dynix*) + os=-bsd + ;; + -acis*) + os=-aos + ;; + -atheos*) + os=-atheos + ;; + -syllable*) + os=-syllable + ;; + -386bsd) + os=-bsd + ;; + -ctix* | -uts*) + os=-sysv + ;; + -nova*) + os=-rtmk-nova + ;; + -ns2 ) + os=-nextstep2 + ;; + -nsk*) + os=-nsk + ;; + # Preserve the version number of sinix5. + -sinix5.*) + os=`echo $os | sed -e 's|sinix|sysv|'` + ;; + -sinix*) + os=-sysv4 + ;; + -tpf*) + os=-tpf + ;; + -triton*) + os=-sysv3 + ;; + -oss*) + os=-sysv3 + ;; + -svr4) + os=-sysv4 + ;; + -svr3) + os=-sysv3 + ;; + -sysvr4) + os=-sysv4 + ;; + # This must come after -sysvr4. + -sysv*) + ;; + -ose*) + os=-ose + ;; + -es1800*) + os=-ose + ;; + -xenix) + os=-xenix + ;; + -*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*) + os=-mint + ;; + -aros*) + os=-aros + ;; + -kaos*) + os=-kaos + ;; + -zvmoe) + os=-zvmoe + ;; + -none) + ;; + *) + # Get rid of the `-' at the beginning of $os. + os=`echo $os | sed 's/[^-]*-//'` + echo Invalid configuration \`$1\': system \`$os\' not recognized 1>&2 + exit 1 + ;; +esac +else + +# Here we handle the default operating systems that come with various machines. +# The value should be what the vendor currently ships out the door with their +# machine or put another way, the most popular os provided with the machine. + +# Note that if you're going to try to match "-MANUFACTURER" here (say, +# "-sun"), then you have to tell the case statement up towards the top +# that MANUFACTURER isn't an operating system. Otherwise, code above +# will signal an error saying that MANUFACTURER isn't an operating +# system, and we'll never get to this point. + +case $basic_machine in + score-*) + os=-elf + ;; + spu-*) + os=-elf + ;; + *-acorn) + os=-riscix1.2 + ;; + arm*-rebel) + os=-linux + ;; + arm*-semi) + os=-aout + ;; + c4x-* | tic4x-*) + os=-coff + ;; + # This must come before the *-dec entry. + pdp10-*) + os=-tops20 + ;; + pdp11-*) + os=-none + ;; + *-dec | vax-*) + os=-ultrix4.2 + ;; + m68*-apollo) + os=-domain + ;; + i386-sun) + os=-sunos4.0.2 + ;; + m68000-sun) + os=-sunos3 + # This also exists in the configure program, but was not the + # default. + # os=-sunos4 + ;; + m68*-cisco) + os=-aout + ;; + mep-*) + os=-elf + ;; + mips*-cisco) + os=-elf + ;; + mips*-*) + os=-elf + ;; + or32-*) + os=-coff + ;; + *-tti) # must be before sparc entry or we get the wrong os. + os=-sysv3 + ;; + sparc-* | *-sun) + os=-sunos4.1.1 + ;; + *-be) + os=-beos + ;; + *-haiku) + os=-haiku + ;; + *-ibm) + os=-aix + ;; + *-knuth) + os=-mmixware + ;; + *-wec) + os=-proelf + ;; + *-winbond) + os=-proelf + ;; + *-oki) + os=-proelf + ;; + *-hp) + os=-hpux + ;; + *-hitachi) + os=-hiux + ;; + i860-* | *-att | *-ncr | *-altos | *-motorola | *-convergent) + os=-sysv + ;; + *-cbm) + os=-amigaos + ;; + *-dg) + os=-dgux + ;; + *-dolphin) + os=-sysv3 + ;; + m68k-ccur) + os=-rtu + ;; + m88k-omron*) + os=-luna + ;; + *-next ) + os=-nextstep + ;; + *-sequent) + os=-ptx + ;; + *-crds) + os=-unos + ;; + *-ns) + os=-genix + ;; + i370-*) + os=-mvs + ;; + *-next) + os=-nextstep3 + ;; + *-gould) + os=-sysv + ;; + *-highlevel) + os=-bsd + ;; + *-encore) + os=-bsd + ;; + *-sgi) + os=-irix + ;; + *-siemens) + os=-sysv4 + ;; + *-masscomp) + os=-rtu + ;; + f30[01]-fujitsu | f700-fujitsu) + os=-uxpv + ;; + *-rom68k) + os=-coff + ;; + *-*bug) + os=-coff + ;; + *-apple) + os=-macos + ;; + *-atari*) + os=-mint + ;; + *) + os=-none + ;; +esac +fi + +# Here we handle the case where we know the os, and the CPU type, but not the +# manufacturer. We pick the logical manufacturer. +vendor=unknown +case $basic_machine in + *-unknown) + case $os in + -riscix*) + vendor=acorn + ;; + -sunos*) + vendor=sun + ;; + -aix*) + vendor=ibm + ;; + -beos*) + vendor=be + ;; + -hpux*) + vendor=hp + ;; + -mpeix*) + vendor=hp + ;; + -hiux*) + vendor=hitachi + ;; + -unos*) + vendor=crds + ;; + -dgux*) + vendor=dg + ;; + -luna*) + vendor=omron + ;; + -genix*) + vendor=ns + ;; + -mvs* | -opened*) + vendor=ibm + ;; + -os400*) + vendor=ibm + ;; + -ptx*) + vendor=sequent + ;; + -tpf*) + vendor=ibm + ;; + -vxsim* | -vxworks* | -windiss*) + vendor=wrs + ;; + -aux*) + vendor=apple + ;; + -hms*) + vendor=hitachi + ;; + -mpw* | -macos*) + vendor=apple + ;; + -*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*) + vendor=atari + ;; + -vos*) + vendor=stratus + ;; + esac + basic_machine=`echo $basic_machine | sed "s/unknown/$vendor/"` + ;; +esac + +echo $basic_machine$os +exit + +# Local variables: +# eval: (add-hook 'write-file-hooks 'time-stamp) +# time-stamp-start: "timestamp='" +# time-stamp-format: "%:y-%02m-%02d" +# time-stamp-end: "'" +# End: diff --git a/configure b/configure new file mode 100755 index 00000000..04b03280 --- /dev/null +++ b/configure @@ -0,0 +1,23193 @@ +#! /bin/sh +# Guess values for system-dependent variables and create Makefiles. +# Generated by GNU Autoconf 2.63. +# +# Copyright (C) 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001, +# 2002, 2003, 2004, 2005, 2006, 2007, 2008 Free Software Foundation, Inc. +# This configure script is free software; the Free Software Foundation +# gives unlimited permission to copy, distribute and modify it. +## --------------------- ## +## M4sh Initialization. ## +## --------------------- ## + +# Be more Bourne compatible +DUALCASE=1; export DUALCASE # for MKS sh +if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then + emulate sh + NULLCMD=: + # Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which + # is contrary to our usage. Disable this feature. + alias -g '${1+"$@"}'='"$@"' + setopt NO_GLOB_SUBST +else + case `(set -o) 2>/dev/null` in + *posix*) set -o posix ;; +esac + +fi + + + + +# PATH needs CR +# Avoid depending upon Character Ranges. +as_cr_letters='abcdefghijklmnopqrstuvwxyz' +as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ' +as_cr_Letters=$as_cr_letters$as_cr_LETTERS +as_cr_digits='0123456789' +as_cr_alnum=$as_cr_Letters$as_cr_digits + +as_nl=' +' +export as_nl +# Printing a long string crashes Solaris 7 /usr/bin/printf. +as_echo='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\' +as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo +as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo$as_echo +if (test "X`printf %s $as_echo`" = "X$as_echo") 2>/dev/null; then + as_echo='printf %s\n' + as_echo_n='printf %s' +else + if test "X`(/usr/ucb/echo -n -n $as_echo) 2>/dev/null`" = "X-n $as_echo"; then + as_echo_body='eval /usr/ucb/echo -n "$1$as_nl"' + as_echo_n='/usr/ucb/echo -n' + else + as_echo_body='eval expr "X$1" : "X\\(.*\\)"' + as_echo_n_body='eval + arg=$1; + case $arg in + *"$as_nl"*) + expr "X$arg" : "X\\(.*\\)$as_nl"; + arg=`expr "X$arg" : ".*$as_nl\\(.*\\)"`;; + esac; + expr "X$arg" : "X\\(.*\\)" | tr -d "$as_nl" + ' + export as_echo_n_body + as_echo_n='sh -c $as_echo_n_body as_echo' + fi + export as_echo_body + as_echo='sh -c $as_echo_body as_echo' +fi + +# The user is always right. +if test "${PATH_SEPARATOR+set}" != set; then + PATH_SEPARATOR=: + (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && { + (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 || + PATH_SEPARATOR=';' + } +fi + +# Support unset when possible. +if ( (MAIL=60; unset MAIL) || exit) >/dev/null 2>&1; then + as_unset=unset +else + as_unset=false +fi + + +# IFS +# We need space, tab and new line, in precisely that order. Quoting is +# there to prevent editors from complaining about space-tab. +# (If _AS_PATH_WALK were called with IFS unset, it would disable word +# splitting by setting IFS to empty value.) +IFS=" "" $as_nl" + +# Find who we are. Look in the path if we contain no directory separator. +case $0 in + *[\\/]* ) as_myself=$0 ;; + *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break +done +IFS=$as_save_IFS + + ;; +esac +# We did not find ourselves, most probably we were run as `sh COMMAND' +# in which case we are not to be found in the path. +if test "x$as_myself" = x; then + as_myself=$0 +fi +if test ! -f "$as_myself"; then + $as_echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2 + { (exit 1); exit 1; } +fi + +# Work around bugs in pre-3.0 UWIN ksh. +for as_var in ENV MAIL MAILPATH +do ($as_unset $as_var) >/dev/null 2>&1 && $as_unset $as_var +done +PS1='$ ' +PS2='> ' +PS4='+ ' + +# NLS nuisances. +LC_ALL=C +export LC_ALL +LANGUAGE=C +export LANGUAGE + +# Required to use basename. +if expr a : '\(a\)' >/dev/null 2>&1 && + test "X`expr 00001 : '.*\(...\)'`" = X001; then + as_expr=expr +else + as_expr=false +fi + +if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then + as_basename=basename +else + as_basename=false +fi + + +# Name of the executable. +as_me=`$as_basename -- "$0" || +$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \ + X"$0" : 'X\(//\)$' \| \ + X"$0" : 'X\(/\)' \| . 2>/dev/null || +$as_echo X/"$0" | + sed '/^.*\/\([^/][^/]*\)\/*$/{ + s//\1/ + q + } + /^X\/\(\/\/\)$/{ + s//\1/ + q + } + /^X\/\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q'` + +# CDPATH. +$as_unset CDPATH + + +if test "x$CONFIG_SHELL" = x; then + if (eval ":") 2>/dev/null; then + as_have_required=yes +else + as_have_required=no +fi + + if test $as_have_required = yes && (eval ": +(as_func_return () { + (exit \$1) +} +as_func_success () { + as_func_return 0 +} +as_func_failure () { + as_func_return 1 +} +as_func_ret_success () { + return 0 +} +as_func_ret_failure () { + return 1 +} + +exitcode=0 +if as_func_success; then + : +else + exitcode=1 + echo as_func_success failed. +fi + +if as_func_failure; then + exitcode=1 + echo as_func_failure succeeded. +fi + +if as_func_ret_success; then + : +else + exitcode=1 + echo as_func_ret_success failed. +fi + +if as_func_ret_failure; then + exitcode=1 + echo as_func_ret_failure succeeded. +fi + +if ( set x; as_func_ret_success y && test x = \"\$1\" ); then + : +else + exitcode=1 + echo positional parameters were not saved. +fi + +test \$exitcode = 0) || { (exit 1); exit 1; } + +( + as_lineno_1=\$LINENO + as_lineno_2=\$LINENO + test \"x\$as_lineno_1\" != \"x\$as_lineno_2\" && + test \"x\`expr \$as_lineno_1 + 1\`\" = \"x\$as_lineno_2\") || { (exit 1); exit 1; } +") 2> /dev/null; then + : +else + as_candidate_shells= + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in /bin$PATH_SEPARATOR/usr/bin$PATH_SEPARATOR$PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + case $as_dir in + /*) + for as_base in sh bash ksh sh5; do + as_candidate_shells="$as_candidate_shells $as_dir/$as_base" + done;; + esac +done +IFS=$as_save_IFS + + + for as_shell in $as_candidate_shells $SHELL; do + # Try only shells that exist, to save several forks. + if { test -f "$as_shell" || test -f "$as_shell.exe"; } && + { ("$as_shell") 2> /dev/null <<\_ASEOF +if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then + emulate sh + NULLCMD=: + # Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which + # is contrary to our usage. Disable this feature. + alias -g '${1+"$@"}'='"$@"' + setopt NO_GLOB_SUBST +else + case `(set -o) 2>/dev/null` in + *posix*) set -o posix ;; +esac + +fi + + +: +_ASEOF +}; then + CONFIG_SHELL=$as_shell + as_have_required=yes + if { "$as_shell" 2> /dev/null <<\_ASEOF +if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then + emulate sh + NULLCMD=: + # Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which + # is contrary to our usage. Disable this feature. + alias -g '${1+"$@"}'='"$@"' + setopt NO_GLOB_SUBST +else + case `(set -o) 2>/dev/null` in + *posix*) set -o posix ;; +esac + +fi + + +: +(as_func_return () { + (exit $1) +} +as_func_success () { + as_func_return 0 +} +as_func_failure () { + as_func_return 1 +} +as_func_ret_success () { + return 0 +} +as_func_ret_failure () { + return 1 +} + +exitcode=0 +if as_func_success; then + : +else + exitcode=1 + echo as_func_success failed. +fi + +if as_func_failure; then + exitcode=1 + echo as_func_failure succeeded. +fi + +if as_func_ret_success; then + : +else + exitcode=1 + echo as_func_ret_success failed. +fi + +if as_func_ret_failure; then + exitcode=1 + echo as_func_ret_failure succeeded. +fi + +if ( set x; as_func_ret_success y && test x = "$1" ); then + : +else + exitcode=1 + echo positional parameters were not saved. +fi + +test $exitcode = 0) || { (exit 1); exit 1; } + +( + as_lineno_1=$LINENO + as_lineno_2=$LINENO + test "x$as_lineno_1" != "x$as_lineno_2" && + test "x`expr $as_lineno_1 + 1`" = "x$as_lineno_2") || { (exit 1); exit 1; } + +_ASEOF +}; then + break +fi + +fi + + done + + if test "x$CONFIG_SHELL" != x; then + for as_var in BASH_ENV ENV + do ($as_unset $as_var) >/dev/null 2>&1 && $as_unset $as_var + done + export CONFIG_SHELL + exec "$CONFIG_SHELL" "$as_myself" ${1+"$@"} +fi + + + if test $as_have_required = no; then + echo This script requires a shell more modern than all the + echo shells that I found on your system. Please install a + echo modern shell, or manually run the script under such a + echo shell if you do have one. + { (exit 1); exit 1; } +fi + + +fi + +fi + + + +(eval "as_func_return () { + (exit \$1) +} +as_func_success () { + as_func_return 0 +} +as_func_failure () { + as_func_return 1 +} +as_func_ret_success () { + return 0 +} +as_func_ret_failure () { + return 1 +} + +exitcode=0 +if as_func_success; then + : +else + exitcode=1 + echo as_func_success failed. +fi + +if as_func_failure; then + exitcode=1 + echo as_func_failure succeeded. +fi + +if as_func_ret_success; then + : +else + exitcode=1 + echo as_func_ret_success failed. +fi + +if as_func_ret_failure; then + exitcode=1 + echo as_func_ret_failure succeeded. +fi + +if ( set x; as_func_ret_success y && test x = \"\$1\" ); then + : +else + exitcode=1 + echo positional parameters were not saved. +fi + +test \$exitcode = 0") || { + echo No shell found that supports shell functions. + echo Please tell bug-autoconf@gnu.org about your system, + echo including any error possibly output before this message. + echo This can help us improve future autoconf versions. + echo Configuration will now proceed without shell functions. +} + + + + as_lineno_1=$LINENO + as_lineno_2=$LINENO + test "x$as_lineno_1" != "x$as_lineno_2" && + test "x`expr $as_lineno_1 + 1`" = "x$as_lineno_2" || { + + # Create $as_me.lineno as a copy of $as_myself, but with $LINENO + # uniformly replaced by the line number. The first 'sed' inserts a + # line-number line after each line using $LINENO; the second 'sed' + # does the real work. The second script uses 'N' to pair each + # line-number line with the line containing $LINENO, and appends + # trailing '-' during substitution so that $LINENO is not a special + # case at line end. + # (Raja R Harinath suggested sed '=', and Paul Eggert wrote the + # scripts with optimization help from Paolo Bonzini. Blame Lee + # E. McMahon (1931-1989) for sed's syntax. :-) + sed -n ' + p + /[$]LINENO/= + ' <$as_myself | + sed ' + s/[$]LINENO.*/&-/ + t lineno + b + :lineno + N + :loop + s/[$]LINENO\([^'$as_cr_alnum'_].*\n\)\(.*\)/\2\1\2/ + t loop + s/-\n.*// + ' >$as_me.lineno && + chmod +x "$as_me.lineno" || + { $as_echo "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2 + { (exit 1); exit 1; }; } + + # Don't try to exec as it changes $[0], causing all sort of problems + # (the dirname of $[0] is not the place where we might find the + # original and so on. Autoconf is especially sensitive to this). + . "./$as_me.lineno" + # Exit status is that of the last command. + exit +} + + +if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then + as_dirname=dirname +else + as_dirname=false +fi + +ECHO_C= ECHO_N= ECHO_T= +case `echo -n x` in +-n*) + case `echo 'x\c'` in + *c*) ECHO_T=' ';; # ECHO_T is single tab character. + *) ECHO_C='\c';; + esac;; +*) + ECHO_N='-n';; +esac +if expr a : '\(a\)' >/dev/null 2>&1 && + test "X`expr 00001 : '.*\(...\)'`" = X001; then + as_expr=expr +else + as_expr=false +fi + +rm -f conf$$ conf$$.exe conf$$.file +if test -d conf$$.dir; then + rm -f conf$$.dir/conf$$.file +else + rm -f conf$$.dir + mkdir conf$$.dir 2>/dev/null +fi +if (echo >conf$$.file) 2>/dev/null; then + if ln -s conf$$.file conf$$ 2>/dev/null; then + as_ln_s='ln -s' + # ... but there are two gotchas: + # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail. + # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable. + # In both cases, we have to default to `cp -p'. + ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe || + as_ln_s='cp -p' + elif ln conf$$.file conf$$ 2>/dev/null; then + as_ln_s=ln + else + as_ln_s='cp -p' + fi +else + as_ln_s='cp -p' +fi +rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file +rmdir conf$$.dir 2>/dev/null + +if mkdir -p . 2>/dev/null; then + as_mkdir_p=: +else + test -d ./-p && rmdir ./-p + as_mkdir_p=false +fi + +if test -x / >/dev/null 2>&1; then + as_test_x='test -x' +else + if ls -dL / >/dev/null 2>&1; then + as_ls_L_option=L + else + as_ls_L_option= + fi + as_test_x=' + eval sh -c '\'' + if test -d "$1"; then + test -d "$1/."; + else + case $1 in + -*)set "./$1";; + esac; + case `ls -ld'$as_ls_L_option' "$1" 2>/dev/null` in + ???[sx]*):;;*)false;;esac;fi + '\'' sh + ' +fi +as_executable_p=$as_test_x + +# Sed expression to map a string onto a valid CPP name. +as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'" + +# Sed expression to map a string onto a valid variable name. +as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'" + + + +exec 7<&0 &1 + +# Name of the host. +# hostname on some systems (SVR3.2, Linux) returns a bogus exit status, +# so uname gets run too. +ac_hostname=`(hostname || uname -n) 2>/dev/null | sed 1q` + +# +# Initializations. +# +ac_default_prefix=/usr/local +ac_clean_files= +ac_config_libobj_dir=. +LIBOBJS= +cross_compiling=no +subdirs= +MFLAGS= +MAKEFLAGS= +SHELL=${CONFIG_SHELL-/bin/sh} + +# Identity of this package. +PACKAGE_NAME= +PACKAGE_TARNAME= +PACKAGE_VERSION= +PACKAGE_STRING= +PACKAGE_BUGREPORT= + +ac_unique_file="driver/subprocs.c" +# Factoring default headers for most tests. +ac_includes_default="\ +#include +#ifdef HAVE_SYS_TYPES_H +# include +#endif +#ifdef HAVE_SYS_STAT_H +# include +#endif +#ifdef STDC_HEADERS +# include +# include +#else +# ifdef HAVE_STDLIB_H +# include +# endif +#endif +#ifdef HAVE_STRING_H +# if !defined STDC_HEADERS && defined HAVE_MEMORY_H +# include +# endif +# include +#endif +#ifdef HAVE_STRINGS_H +# include +#endif +#ifdef HAVE_INTTYPES_H +# include +#endif +#ifdef HAVE_STDINT_H +# include +#endif +#ifdef HAVE_UNISTD_H +# include +#endif" + +ac_subst_vars='LTLIBOBJS +LIBOBJS +DEPEND_DEFINES +DEPEND_FLAGS +DEPEND +APPDEFAULTS +GTK_EXTRA_OBJS +HACK_CONF_DIR +PO_DATADIR +GTK_DATADIR +HACKDIR_FULL +HACKDIR +NOGNOME +GNOME22 +GNOME24 +GLFONT_OBJS +GLFPS_OBJS +JWZGLES_OBJS +GLE_KLUDGE +GLE_EXES +GL_KLUDGE +GL_MEN +GL_UTIL_EXES +SUID_EXES +RETIRED_GL_EXES +GL_EXES +JPEG_EXES +LOCK_OBJS +LOCK_SRCS +SAVER_GL_LIBS +SAVER_GL_OBJS +SAVER_GL_SRCS +XMU_LIBS +XMU_OBJS +XMU_SRCS +PASSWD_OBJS +PASSWD_SRCS +MEN_OSX +SCRIPTS_OSX +EXES_OSX +OBJCC +WITH_BROWSER +DEFAULT_TEXT_FILE +DEFAULT_IMAGE_DIRECTORY +DEFAULT_IMAGES_P +NEW_LOGIN_COMMAND_P +NEW_LOGIN_COMMAND +COMMENT_PAM_CHECK_ACCOUNT +HAVE_PAM_FAIL_DELAY +INSTALL_PAM +NEED_SETUID +INSTALL_DIRS +SETUID_HACKS +INSTALL_SETUID +PASSWD_LIBS +XINERAMA_LIBS +XDPMS_LIBS +GLE_LIBS +GL_LIBS +PTY_LIBS +XPM_LIBS +HACK_LIBS +JPEG_LIBS +XML_LIBS +GTK_LIBS +MOTIF_LIBS +SAVER_LIBS +ALL_DEMO_PROGRAMS +PREFERRED_DEMO_PROGRAM +INCLUDES +gnome_url_show_program +gnome_open_program +pkg_config +login_manager_tmp +MKINSTALLDIRS +POSUB +POFILES +INTLOBJS +INTLLIBS +INTLDEPS +INSTOBJEXT +GMOFILES +DATADIRNAME +CATOBJEXT +CATALOGS +XGETTEXT +GMSGFMT +MSGFMT +USE_NLS +ALLOCA +RANLIB +GETTEXT_PACKAGE +INTLTOOL_PERL +INTLTOOL_UPDATE +INTLTOOL_MERGE +INTLTOOL_EXTRACT +INTLTOOL_CAVES_RULE +INTLTOOL_XML_RULE +INTLTOOL_UI_RULE +INTLTOOL_SOUNDLIST_RULE +INTLTOOL_SHEET_RULE +INTLTOOL_SERVER_RULE +INTLTOOL_PONG_RULE +INTLTOOL_OAF_RULE +INTLTOOL_KEYS_RULE +INTLTOOL_DIRECTORY_RULE +INTLTOOL_DESKTOP_RULE +X_EXTRA_LIBS +X_LIBS +X_PRE_LIBS +X_CFLAGS +XMKMF +PERL +EGREP +GREP +SET_MAKE +INSTALL_DATA +INSTALL_SCRIPT +INSTALL_PROGRAM +CPP +OBJEXT +EXEEXT +ac_ct_CC +CPPFLAGS +LDFLAGS +CFLAGS +CC +host_os +host_vendor +host_cpu +host +build_os +build_vendor +build_cpu +build +target_alias +host_alias +build_alias +LIBS +ECHO_T +ECHO_N +ECHO_C +DEFS +mandir +localedir +libdir +psdir +pdfdir +dvidir +htmldir +infodir +docdir +oldincludedir +includedir +localstatedir +sharedstatedir +sysconfdir +datadir +datarootdir +libexecdir +sbindir +bindir +program_transform_name +prefix +exec_prefix +PACKAGE_BUGREPORT +PACKAGE_STRING +PACKAGE_VERSION +PACKAGE_TARNAME +PACKAGE_NAME +PATH_SEPARATOR +SHELL' +ac_subst_files='' +ac_user_opts=' +enable_option_checking +with_x_app_defaults +with_x +with_hackdir +enable_subdir +with_configdir +with_dpms_ext +with_xinerama_ext +with_xinput_ext +with_xf86vmode_ext +with_xf86gamma_ext +with_randr_ext +with_proc_interrupts +enable_locking +enable_root_passwd +with_pam +with_pam_service_name +enable_pam_check_account_type +with_kerberos +with_shadow +with_passwd_helper +with_login_manager +with_gtk +with_motif +with_gl +with_gle +with_gles +with_pixbuf +with_xpm +with_jpeg +with_xshm_ext +with_xdbe_ext +with_readdisplay +with_image_directory +with_text_file +with_browser +with_setuid_hacks +' + ac_precious_vars='build_alias +host_alias +target_alias +CC +CFLAGS +LDFLAGS +LIBS +CPPFLAGS +CPP +XMKMF' + + +# Initialize some variables set by options. +ac_init_help= +ac_init_version=false +ac_unrecognized_opts= +ac_unrecognized_sep= +# The variables have the same names as the options, with +# dashes changed to underlines. +cache_file=/dev/null +exec_prefix=NONE +no_create= +no_recursion= +prefix=NONE +program_prefix=NONE +program_suffix=NONE +program_transform_name=s,x,x, +silent= +site= +srcdir= +verbose= +x_includes=NONE +x_libraries=NONE + +# Installation directory options. +# These are left unexpanded so users can "make install exec_prefix=/foo" +# and all the variables that are supposed to be based on exec_prefix +# by default will actually change. +# Use braces instead of parens because sh, perl, etc. also accept them. +# (The list follows the same order as the GNU Coding Standards.) +bindir='${exec_prefix}/bin' +sbindir='${exec_prefix}/sbin' +libexecdir='${exec_prefix}/libexec' +datarootdir='${prefix}/share' +datadir='${datarootdir}' +sysconfdir='${prefix}/etc' +sharedstatedir='${prefix}/com' +localstatedir='${prefix}/var' +includedir='${prefix}/include' +oldincludedir='/usr/include' +docdir='${datarootdir}/doc/${PACKAGE}' +infodir='${datarootdir}/info' +htmldir='${docdir}' +dvidir='${docdir}' +pdfdir='${docdir}' +psdir='${docdir}' +libdir='${exec_prefix}/lib' +localedir='${datarootdir}/locale' +mandir='${datarootdir}/man' + +ac_prev= +ac_dashdash= +for ac_option +do + # If the previous option needs an argument, assign it. + if test -n "$ac_prev"; then + eval $ac_prev=\$ac_option + ac_prev= + continue + fi + + case $ac_option in + *=*) ac_optarg=`expr "X$ac_option" : '[^=]*=\(.*\)'` ;; + *) ac_optarg=yes ;; + esac + + # Accept the important Cygnus configure options, so we can diagnose typos. + + case $ac_dashdash$ac_option in + --) + ac_dashdash=yes ;; + + -bindir | --bindir | --bindi | --bind | --bin | --bi) + ac_prev=bindir ;; + -bindir=* | --bindir=* | --bindi=* | --bind=* | --bin=* | --bi=*) + bindir=$ac_optarg ;; + + -build | --build | --buil | --bui | --bu) + ac_prev=build_alias ;; + -build=* | --build=* | --buil=* | --bui=* | --bu=*) + build_alias=$ac_optarg ;; + + -cache-file | --cache-file | --cache-fil | --cache-fi \ + | --cache-f | --cache- | --cache | --cach | --cac | --ca | --c) + ac_prev=cache_file ;; + -cache-file=* | --cache-file=* | --cache-fil=* | --cache-fi=* \ + | --cache-f=* | --cache-=* | --cache=* | --cach=* | --cac=* | --ca=* | --c=*) + cache_file=$ac_optarg ;; + + --config-cache | -C) + cache_file=config.cache ;; + + -datadir | --datadir | --datadi | --datad) + ac_prev=datadir ;; + -datadir=* | --datadir=* | --datadi=* | --datad=*) + datadir=$ac_optarg ;; + + -datarootdir | --datarootdir | --datarootdi | --datarootd | --dataroot \ + | --dataroo | --dataro | --datar) + ac_prev=datarootdir ;; + -datarootdir=* | --datarootdir=* | --datarootdi=* | --datarootd=* \ + | --dataroot=* | --dataroo=* | --dataro=* | --datar=*) + datarootdir=$ac_optarg ;; + + -disable-* | --disable-*) + ac_useropt=`expr "x$ac_option" : 'x-*disable-\(.*\)'` + # Reject names that are not valid shell variable names. + expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && + { $as_echo "$as_me: error: invalid feature name: $ac_useropt" >&2 + { (exit 1); exit 1; }; } + ac_useropt_orig=$ac_useropt + ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` + case $ac_user_opts in + *" +"enable_$ac_useropt" +"*) ;; + *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--disable-$ac_useropt_orig" + ac_unrecognized_sep=', ';; + esac + eval enable_$ac_useropt=no ;; + + -docdir | --docdir | --docdi | --doc | --do) + ac_prev=docdir ;; + -docdir=* | --docdir=* | --docdi=* | --doc=* | --do=*) + docdir=$ac_optarg ;; + + -dvidir | --dvidir | --dvidi | --dvid | --dvi | --dv) + ac_prev=dvidir ;; + -dvidir=* | --dvidir=* | --dvidi=* | --dvid=* | --dvi=* | --dv=*) + dvidir=$ac_optarg ;; + + -enable-* | --enable-*) + ac_useropt=`expr "x$ac_option" : 'x-*enable-\([^=]*\)'` + # Reject names that are not valid shell variable names. + expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && + { $as_echo "$as_me: error: invalid feature name: $ac_useropt" >&2 + { (exit 1); exit 1; }; } + ac_useropt_orig=$ac_useropt + ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` + case $ac_user_opts in + *" +"enable_$ac_useropt" +"*) ;; + *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--enable-$ac_useropt_orig" + ac_unrecognized_sep=', ';; + esac + eval enable_$ac_useropt=\$ac_optarg ;; + + -exec-prefix | --exec_prefix | --exec-prefix | --exec-prefi \ + | --exec-pref | --exec-pre | --exec-pr | --exec-p | --exec- \ + | --exec | --exe | --ex) + ac_prev=exec_prefix ;; + -exec-prefix=* | --exec_prefix=* | --exec-prefix=* | --exec-prefi=* \ + | --exec-pref=* | --exec-pre=* | --exec-pr=* | --exec-p=* | --exec-=* \ + | --exec=* | --exe=* | --ex=*) + exec_prefix=$ac_optarg ;; + + -gas | --gas | --ga | --g) + # Obsolete; use --with-gas. + with_gas=yes ;; + + -help | --help | --hel | --he | -h) + ac_init_help=long ;; + -help=r* | --help=r* | --hel=r* | --he=r* | -hr*) + ac_init_help=recursive ;; + -help=s* | --help=s* | --hel=s* | --he=s* | -hs*) + ac_init_help=short ;; + + -host | --host | --hos | --ho) + ac_prev=host_alias ;; + -host=* | --host=* | --hos=* | --ho=*) + host_alias=$ac_optarg ;; + + -htmldir | --htmldir | --htmldi | --htmld | --html | --htm | --ht) + ac_prev=htmldir ;; + -htmldir=* | --htmldir=* | --htmldi=* | --htmld=* | --html=* | --htm=* \ + | --ht=*) + htmldir=$ac_optarg ;; + + -includedir | --includedir | --includedi | --included | --include \ + | --includ | --inclu | --incl | --inc) + ac_prev=includedir ;; + -includedir=* | --includedir=* | --includedi=* | --included=* | --include=* \ + | --includ=* | --inclu=* | --incl=* | --inc=*) + includedir=$ac_optarg ;; + + -infodir | --infodir | --infodi | --infod | --info | --inf) + ac_prev=infodir ;; + -infodir=* | --infodir=* | --infodi=* | --infod=* | --info=* | --inf=*) + infodir=$ac_optarg ;; + + -libdir | --libdir | --libdi | --libd) + ac_prev=libdir ;; + -libdir=* | --libdir=* | --libdi=* | --libd=*) + libdir=$ac_optarg ;; + + -libexecdir | --libexecdir | --libexecdi | --libexecd | --libexec \ + | --libexe | --libex | --libe) + ac_prev=libexecdir ;; + -libexecdir=* | --libexecdir=* | --libexecdi=* | --libexecd=* | --libexec=* \ + | --libexe=* | --libex=* | --libe=*) + libexecdir=$ac_optarg ;; + + -localedir | --localedir | --localedi | --localed | --locale) + ac_prev=localedir ;; + -localedir=* | --localedir=* | --localedi=* | --localed=* | --locale=*) + localedir=$ac_optarg ;; + + -localstatedir | --localstatedir | --localstatedi | --localstated \ + | --localstate | --localstat | --localsta | --localst | --locals) + ac_prev=localstatedir ;; + -localstatedir=* | --localstatedir=* | --localstatedi=* | --localstated=* \ + | --localstate=* | --localstat=* | --localsta=* | --localst=* | --locals=*) + localstatedir=$ac_optarg ;; + + -mandir | --mandir | --mandi | --mand | --man | --ma | --m) + ac_prev=mandir ;; + -mandir=* | --mandir=* | --mandi=* | --mand=* | --man=* | --ma=* | --m=*) + mandir=$ac_optarg ;; + + -nfp | --nfp | --nf) + # Obsolete; use --without-fp. + with_fp=no ;; + + -no-create | --no-create | --no-creat | --no-crea | --no-cre \ + | --no-cr | --no-c | -n) + no_create=yes ;; + + -no-recursion | --no-recursion | --no-recursio | --no-recursi \ + | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r) + no_recursion=yes ;; + + -oldincludedir | --oldincludedir | --oldincludedi | --oldincluded \ + | --oldinclude | --oldinclud | --oldinclu | --oldincl | --oldinc \ + | --oldin | --oldi | --old | --ol | --o) + ac_prev=oldincludedir ;; + -oldincludedir=* | --oldincludedir=* | --oldincludedi=* | --oldincluded=* \ + | --oldinclude=* | --oldinclud=* | --oldinclu=* | --oldincl=* | --oldinc=* \ + | --oldin=* | --oldi=* | --old=* | --ol=* | --o=*) + oldincludedir=$ac_optarg ;; + + -prefix | --prefix | --prefi | --pref | --pre | --pr | --p) + ac_prev=prefix ;; + -prefix=* | --prefix=* | --prefi=* | --pref=* | --pre=* | --pr=* | --p=*) + prefix=$ac_optarg ;; + + -program-prefix | --program-prefix | --program-prefi | --program-pref \ + | --program-pre | --program-pr | --program-p) + ac_prev=program_prefix ;; + -program-prefix=* | --program-prefix=* | --program-prefi=* \ + | --program-pref=* | --program-pre=* | --program-pr=* | --program-p=*) + program_prefix=$ac_optarg ;; + + -program-suffix | --program-suffix | --program-suffi | --program-suff \ + | --program-suf | --program-su | --program-s) + ac_prev=program_suffix ;; + -program-suffix=* | --program-suffix=* | --program-suffi=* \ + | --program-suff=* | --program-suf=* | --program-su=* | --program-s=*) + program_suffix=$ac_optarg ;; + + -program-transform-name | --program-transform-name \ + | --program-transform-nam | --program-transform-na \ + | --program-transform-n | --program-transform- \ + | --program-transform | --program-transfor \ + | --program-transfo | --program-transf \ + | --program-trans | --program-tran \ + | --progr-tra | --program-tr | --program-t) + ac_prev=program_transform_name ;; + -program-transform-name=* | --program-transform-name=* \ + | --program-transform-nam=* | --program-transform-na=* \ + | --program-transform-n=* | --program-transform-=* \ + | --program-transform=* | --program-transfor=* \ + | --program-transfo=* | --program-transf=* \ + | --program-trans=* | --program-tran=* \ + | --progr-tra=* | --program-tr=* | --program-t=*) + program_transform_name=$ac_optarg ;; + + -pdfdir | --pdfdir | --pdfdi | --pdfd | --pdf | --pd) + ac_prev=pdfdir ;; + -pdfdir=* | --pdfdir=* | --pdfdi=* | --pdfd=* | --pdf=* | --pd=*) + pdfdir=$ac_optarg ;; + + -psdir | --psdir | --psdi | --psd | --ps) + ac_prev=psdir ;; + -psdir=* | --psdir=* | --psdi=* | --psd=* | --ps=*) + psdir=$ac_optarg ;; + + -q | -quiet | --quiet | --quie | --qui | --qu | --q \ + | -silent | --silent | --silen | --sile | --sil) + silent=yes ;; + + -sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb) + ac_prev=sbindir ;; + -sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \ + | --sbi=* | --sb=*) + sbindir=$ac_optarg ;; + + -sharedstatedir | --sharedstatedir | --sharedstatedi \ + | --sharedstated | --sharedstate | --sharedstat | --sharedsta \ + | --sharedst | --shareds | --shared | --share | --shar \ + | --sha | --sh) + ac_prev=sharedstatedir ;; + -sharedstatedir=* | --sharedstatedir=* | --sharedstatedi=* \ + | --sharedstated=* | --sharedstate=* | --sharedstat=* | --sharedsta=* \ + | --sharedst=* | --shareds=* | --shared=* | --share=* | --shar=* \ + | --sha=* | --sh=*) + sharedstatedir=$ac_optarg ;; + + -site | --site | --sit) + ac_prev=site ;; + -site=* | --site=* | --sit=*) + site=$ac_optarg ;; + + -srcdir | --srcdir | --srcdi | --srcd | --src | --sr) + ac_prev=srcdir ;; + -srcdir=* | --srcdir=* | --srcdi=* | --srcd=* | --src=* | --sr=*) + srcdir=$ac_optarg ;; + + -sysconfdir | --sysconfdir | --sysconfdi | --sysconfd | --sysconf \ + | --syscon | --sysco | --sysc | --sys | --sy) + ac_prev=sysconfdir ;; + -sysconfdir=* | --sysconfdir=* | --sysconfdi=* | --sysconfd=* | --sysconf=* \ + | --syscon=* | --sysco=* | --sysc=* | --sys=* | --sy=*) + sysconfdir=$ac_optarg ;; + + -target | --target | --targe | --targ | --tar | --ta | --t) + ac_prev=target_alias ;; + -target=* | --target=* | --targe=* | --targ=* | --tar=* | --ta=* | --t=*) + target_alias=$ac_optarg ;; + + -v | -verbose | --verbose | --verbos | --verbo | --verb) + verbose=yes ;; + + -version | --version | --versio | --versi | --vers | -V) + ac_init_version=: ;; + + -with-* | --with-*) + ac_useropt=`expr "x$ac_option" : 'x-*with-\([^=]*\)'` + # Reject names that are not valid shell variable names. + expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && + { $as_echo "$as_me: error: invalid package name: $ac_useropt" >&2 + { (exit 1); exit 1; }; } + ac_useropt_orig=$ac_useropt + ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` + case $ac_user_opts in + *" +"with_$ac_useropt" +"*) ;; + *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--with-$ac_useropt_orig" + ac_unrecognized_sep=', ';; + esac + eval with_$ac_useropt=\$ac_optarg ;; + + -without-* | --without-*) + ac_useropt=`expr "x$ac_option" : 'x-*without-\(.*\)'` + # Reject names that are not valid shell variable names. + expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && + { $as_echo "$as_me: error: invalid package name: $ac_useropt" >&2 + { (exit 1); exit 1; }; } + ac_useropt_orig=$ac_useropt + ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` + case $ac_user_opts in + *" +"with_$ac_useropt" +"*) ;; + *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--without-$ac_useropt_orig" + ac_unrecognized_sep=', ';; + esac + eval with_$ac_useropt=no ;; + + --x) + # Obsolete; use --with-x. + with_x=yes ;; + + -x-includes | --x-includes | --x-include | --x-includ | --x-inclu \ + | --x-incl | --x-inc | --x-in | --x-i) + ac_prev=x_includes ;; + -x-includes=* | --x-includes=* | --x-include=* | --x-includ=* | --x-inclu=* \ + | --x-incl=* | --x-inc=* | --x-in=* | --x-i=*) + x_includes=$ac_optarg ;; + + -x-libraries | --x-libraries | --x-librarie | --x-librari \ + | --x-librar | --x-libra | --x-libr | --x-lib | --x-li | --x-l) + ac_prev=x_libraries ;; + -x-libraries=* | --x-libraries=* | --x-librarie=* | --x-librari=* \ + | --x-librar=* | --x-libra=* | --x-libr=* | --x-lib=* | --x-li=* | --x-l=*) + x_libraries=$ac_optarg ;; + + -*) { $as_echo "$as_me: error: unrecognized option: $ac_option +Try \`$0 --help' for more information." >&2 + { (exit 1); exit 1; }; } + ;; + + *=*) + ac_envvar=`expr "x$ac_option" : 'x\([^=]*\)='` + # Reject names that are not valid shell variable names. + expr "x$ac_envvar" : ".*[^_$as_cr_alnum]" >/dev/null && + { $as_echo "$as_me: error: invalid variable name: $ac_envvar" >&2 + { (exit 1); exit 1; }; } + eval $ac_envvar=\$ac_optarg + export $ac_envvar ;; + + *) + # FIXME: should be removed in autoconf 3.0. + $as_echo "$as_me: WARNING: you should use --build, --host, --target" >&2 + expr "x$ac_option" : ".*[^-._$as_cr_alnum]" >/dev/null && + $as_echo "$as_me: WARNING: invalid host type: $ac_option" >&2 + : ${build_alias=$ac_option} ${host_alias=$ac_option} ${target_alias=$ac_option} + ;; + + esac +done + +if test -n "$ac_prev"; then + ac_option=--`echo $ac_prev | sed 's/_/-/g'` + { $as_echo "$as_me: error: missing argument to $ac_option" >&2 + { (exit 1); exit 1; }; } +fi + +if test -n "$ac_unrecognized_opts"; then + case $enable_option_checking in + no) ;; + fatal) { $as_echo "$as_me: error: unrecognized options: $ac_unrecognized_opts" >&2 + { (exit 1); exit 1; }; } ;; + *) $as_echo "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2 ;; + esac +fi + +# Check all directory arguments for consistency. +for ac_var in exec_prefix prefix bindir sbindir libexecdir datarootdir \ + datadir sysconfdir sharedstatedir localstatedir includedir \ + oldincludedir docdir infodir htmldir dvidir pdfdir psdir \ + libdir localedir mandir +do + eval ac_val=\$$ac_var + # Remove trailing slashes. + case $ac_val in + */ ) + ac_val=`expr "X$ac_val" : 'X\(.*[^/]\)' \| "X$ac_val" : 'X\(.*\)'` + eval $ac_var=\$ac_val;; + esac + # Be sure to have absolute directory names. + case $ac_val in + [\\/$]* | ?:[\\/]* ) continue;; + NONE | '' ) case $ac_var in *prefix ) continue;; esac;; + esac + { $as_echo "$as_me: error: expected an absolute directory name for --$ac_var: $ac_val" >&2 + { (exit 1); exit 1; }; } +done + +# There might be people who depend on the old broken behavior: `$host' +# used to hold the argument of --host etc. +# FIXME: To remove some day. +build=$build_alias +host=$host_alias +target=$target_alias + +# FIXME: To remove some day. +if test "x$host_alias" != x; then + if test "x$build_alias" = x; then + cross_compiling=maybe + $as_echo "$as_me: WARNING: If you wanted to set the --build type, don't use --host. + If a cross compiler is detected then cross compile mode will be used." >&2 + elif test "x$build_alias" != "x$host_alias"; then + cross_compiling=yes + fi +fi + +ac_tool_prefix= +test -n "$host_alias" && ac_tool_prefix=$host_alias- + +test "$silent" = yes && exec 6>/dev/null + + +ac_pwd=`pwd` && test -n "$ac_pwd" && +ac_ls_di=`ls -di .` && +ac_pwd_ls_di=`cd "$ac_pwd" && ls -di .` || + { $as_echo "$as_me: error: working directory cannot be determined" >&2 + { (exit 1); exit 1; }; } +test "X$ac_ls_di" = "X$ac_pwd_ls_di" || + { $as_echo "$as_me: error: pwd does not report name of working directory" >&2 + { (exit 1); exit 1; }; } + + +# Find the source files, if location was not specified. +if test -z "$srcdir"; then + ac_srcdir_defaulted=yes + # Try the directory containing this script, then the parent directory. + ac_confdir=`$as_dirname -- "$as_myself" || +$as_expr X"$as_myself" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$as_myself" : 'X\(//\)[^/]' \| \ + X"$as_myself" : 'X\(//\)$' \| \ + X"$as_myself" : 'X\(/\)' \| . 2>/dev/null || +$as_echo X"$as_myself" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ + s//\1/ + q + } + /^X\(\/\/\)[^/].*/{ + s//\1/ + q + } + /^X\(\/\/\)$/{ + s//\1/ + q + } + /^X\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q'` + srcdir=$ac_confdir + if test ! -r "$srcdir/$ac_unique_file"; then + srcdir=.. + fi +else + ac_srcdir_defaulted=no +fi +if test ! -r "$srcdir/$ac_unique_file"; then + test "$ac_srcdir_defaulted" = yes && srcdir="$ac_confdir or .." + { $as_echo "$as_me: error: cannot find sources ($ac_unique_file) in $srcdir" >&2 + { (exit 1); exit 1; }; } +fi +ac_msg="sources are in $srcdir, but \`cd $srcdir' does not work" +ac_abs_confdir=`( + cd "$srcdir" && test -r "./$ac_unique_file" || { $as_echo "$as_me: error: $ac_msg" >&2 + { (exit 1); exit 1; }; } + pwd)` +# When building in place, set srcdir=. +if test "$ac_abs_confdir" = "$ac_pwd"; then + srcdir=. +fi +# Remove unnecessary trailing slashes from srcdir. +# Double slashes in file names in object file debugging info +# mess up M-x gdb in Emacs. +case $srcdir in +*/) srcdir=`expr "X$srcdir" : 'X\(.*[^/]\)' \| "X$srcdir" : 'X\(.*\)'`;; +esac +for ac_var in $ac_precious_vars; do + eval ac_env_${ac_var}_set=\${${ac_var}+set} + eval ac_env_${ac_var}_value=\$${ac_var} + eval ac_cv_env_${ac_var}_set=\${${ac_var}+set} + eval ac_cv_env_${ac_var}_value=\$${ac_var} +done + +# +# Report the --help message. +# +if test "$ac_init_help" = "long"; then + # Omit some internal or obsolete options to make the list less imposing. + # This message is too long to be a string in the A/UX 3.1 sh. + cat <<_ACEOF +\`configure' configures this package to adapt to many kinds of systems. + +Usage: $0 [OPTION]... [VAR=VALUE]... + +To assign environment variables (e.g., CC, CFLAGS...), specify them as +VAR=VALUE. See below for descriptions of some of the useful variables. + +Defaults for the options are specified in brackets. + + +Configuration: + + -h, --help display this help and exit + --help=short display options specific to this package + --help=recursive display the short help of all the included packages + -V, --version display version information and exit + -q, --quiet, --silent do not print \`checking...' messages + --cache-file=FILE cache test results in FILE [disabled] + -C, --config-cache alias for \`--cache-file=config.cache' + -n, --no-create do not create output files + --srcdir=DIR find the sources in DIR [configure dir or \`..'] + +Installation directories: + --prefix=PREFIX install architecture-independent files in PREFIX + [$ac_default_prefix] + --exec-prefix=EPREFIX install architecture-dependent files in EPREFIX + [PREFIX] + +By default, \`make install' will install all the files in +\`$ac_default_prefix/bin', \`$ac_default_prefix/lib' etc. You can specify +an installation prefix other than \`$ac_default_prefix' using \`--prefix', +for instance \`--prefix=\$HOME'. + +For better control, use the options below. + +Fine tuning of the installation directories: + --bindir=DIR user executables [EPREFIX/bin] + --libexecdir=DIR program executables [EPREFIX/libexec] + --libdir=DIR object code libraries [EPREFIX/lib] + --includedir=DIR C header files [PREFIX/include] + --x-includes=DIR X include files are in DIR + --x-libraries=DIR X library files are in DIR + --datarootdir=DIR read-only arch.-independent data root [PREFIX/share] + --datadir=DIR read-only architecture-independent data [DATAROOTDIR] + --localedir=DIR locale-dependent data [DATAROOTDIR/locale] + --mandir=DIR man documentation [DATAROOTDIR/man] + --docdir=DIR documentation root [DATAROOTDIR/doc/PACKAGE] + --htmldir=DIR html documentation [DOCDIR] + --dvidir=DIR dvi documentation [DOCDIR] + --pdfdir=DIR pdf documentation [DOCDIR] + --psdir=DIR ps documentation [DOCDIR] +_ACEOF + + cat <<\_ACEOF + +X features: + --x-includes=DIR X include files are in DIR + --x-libraries=DIR X library files are in DIR + +System types: + --build=BUILD configure for building on BUILD [guessed] + --host=HOST cross-compile to build programs to run on HOST [BUILD] +_ACEOF +fi + +if test -n "$ac_init_help"; then + + cat <<\_ACEOF + +Optional Features: + --disable-option-checking ignore unrecognized --enable/--with options + --disable-FEATURE do not include FEATURE (same as --enable-FEATURE=no) + --enable-FEATURE[=ARG] include FEATURE [ARG=yes] + +Screen locking options: + --enable-locking Compile in support for locking the display. + --disable-locking Do not allow locking at all. + + --enable-root-passwd Allow root passwd to unlock screen. + --disable-root-passwd Do not allow that. + --enable-pam-check-account-type + Whether PAM should check the result of account + modules when authenticating. Only do this if you + have account configured properly on your system. + +Optional Packages: + --with-PACKAGE[=ARG] use PACKAGE [ARG=yes] + --without-PACKAGE do not use PACKAGE (same as --with-PACKAGE=no) + + +Installation options: + --with-hackdir=DIR Where to install the hundreds of demo executables. + Default: `PREFIX/libexec/xscreensaver/' + --with-configdir=DIR Where to install the data files that describe each + of the display modes to the GUI. + Default: `PREFIX/share/xscreensaver/config/' + --with-x-app-defaults=DIR + Where to install xscreensaver configuration file. + + --with-dpms-ext Include support for the DPMS extension. + --with-xinerama-ext Include support for the XINERAMA extension. + --with-xinput-ext Include support for the XInput extension. + --with-xf86vmode-ext Include support for XFree86 virtual screens. + --with-xf86gamma-ext Include support for XFree86 gamma fading. + --with-randr-ext Include support for the X Resize+Rotate extension. + --with-proc-interrupts Include support for consulting the /proc/interrupts + file to notice keyboard activity. + --with-pam Include support for PAM (Pluggable Auth Modules.) + --with-pam-service-name NAME arg is the name of the PAM service that + xscreensaver will authenticate as. + --with-kerberos Include support for Kerberos authentication. + --with-shadow Include support for shadow password authentication. + --with-passwd-helper Include support for an external password + verification helper program. + --with-login-manager Put a "New Login" button on the unlock dialog that + runs a login manager like gdmflexiserver or kdmctl. + +User interface options: + + --with-gtk Use the Gtk toolkit for the user interface. + --with-motif Use the Motif toolkit for the user interface + (no longer supported.) + +Graphics options: + + --with-gl Build those demos which depend on OpenGL. + --with-gle Build those demos which depend on GLE + (the OpenGL "extrusion" library.) + --with-gles Target OpenGL ES 1.x API instead of OpenGL 1.3. + --with-pixbuf Include support for the GDK-Pixbuf library in some + demos, which will make it possible for them to read + GIF, JPEG, and PNG files as well. + --with-xpm Include support for XPM files in some demos. + (Not needed if Pixbuf is used.) + --with-jpeg Include support for the JPEG library. + --with-xshm-ext Include support for the Shared Memory extension. + --with-xdbe-ext Include support for the DOUBLE-BUFFER extension. + --with-readdisplay Include support for the XReadDisplay extension. + --with-image-directory Arg is the default directory from which some demos + will choose random images to display. + --with-text-file=FILE By default, some demos may display this file. + --with-browser=BROWSER Specify the web browser used to show the help URL. + --with-setuid-hacks Allow some demos to be installed `setuid root' + (which is needed in order to ping other hosts.) + + +Some influential environment variables: + CC C compiler command + CFLAGS C compiler flags + LDFLAGS linker flags, e.g. -L if you have libraries in a + nonstandard directory + LIBS libraries to pass to the linker, e.g. -l + CPPFLAGS C/C++/Objective C preprocessor flags, e.g. -I if + you have headers in a nonstandard directory + CPP C preprocessor + XMKMF Path to xmkmf, Makefile generator for X Window System + +Use these variables to override the choices made by `configure' or to help +it to find libraries and programs with nonstandard names/locations. + +_ACEOF +ac_status=$? +fi + +if test "$ac_init_help" = "recursive"; then + # If there are subdirs, report their specific --help. + for ac_dir in : $ac_subdirs_all; do test "x$ac_dir" = x: && continue + test -d "$ac_dir" || + { cd "$srcdir" && ac_pwd=`pwd` && srcdir=. && test -d "$ac_dir"; } || + continue + ac_builddir=. + +case "$ac_dir" in +.) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;; +*) + ac_dir_suffix=/`$as_echo "$ac_dir" | sed 's|^\.[\\/]||'` + # A ".." for each directory in $ac_dir_suffix. + ac_top_builddir_sub=`$as_echo "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'` + case $ac_top_builddir_sub in + "") ac_top_builddir_sub=. ac_top_build_prefix= ;; + *) ac_top_build_prefix=$ac_top_builddir_sub/ ;; + esac ;; +esac +ac_abs_top_builddir=$ac_pwd +ac_abs_builddir=$ac_pwd$ac_dir_suffix +# for backward compatibility: +ac_top_builddir=$ac_top_build_prefix + +case $srcdir in + .) # We are building in place. + ac_srcdir=. + ac_top_srcdir=$ac_top_builddir_sub + ac_abs_top_srcdir=$ac_pwd ;; + [\\/]* | ?:[\\/]* ) # Absolute name. + ac_srcdir=$srcdir$ac_dir_suffix; + ac_top_srcdir=$srcdir + ac_abs_top_srcdir=$srcdir ;; + *) # Relative name. + ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix + ac_top_srcdir=$ac_top_build_prefix$srcdir + ac_abs_top_srcdir=$ac_pwd/$srcdir ;; +esac +ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix + + cd "$ac_dir" || { ac_status=$?; continue; } + # Check for guested configure. + if test -f "$ac_srcdir/configure.gnu"; then + echo && + $SHELL "$ac_srcdir/configure.gnu" --help=recursive + elif test -f "$ac_srcdir/configure"; then + echo && + $SHELL "$ac_srcdir/configure" --help=recursive + else + $as_echo "$as_me: WARNING: no configuration information is in $ac_dir" >&2 + fi || ac_status=$? + cd "$ac_pwd" || { ac_status=$?; break; } + done +fi + +test -n "$ac_init_help" && exit $ac_status +if $ac_init_version; then + cat <<\_ACEOF +configure +generated by GNU Autoconf 2.63 + +Copyright (C) 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001, +2002, 2003, 2004, 2005, 2006, 2007, 2008 Free Software Foundation, Inc. +This configure script is free software; the Free Software Foundation +gives unlimited permission to copy, distribute and modify it. +_ACEOF + exit +fi +cat >config.log <<_ACEOF +This file contains any messages produced by compilers while +running configure, to aid debugging if configure makes a mistake. + +It was created by $as_me, which was +generated by GNU Autoconf 2.63. Invocation command line was + + $ $0 $@ + +_ACEOF +exec 5>>config.log +{ +cat <<_ASUNAME +## --------- ## +## Platform. ## +## --------- ## + +hostname = `(hostname || uname -n) 2>/dev/null | sed 1q` +uname -m = `(uname -m) 2>/dev/null || echo unknown` +uname -r = `(uname -r) 2>/dev/null || echo unknown` +uname -s = `(uname -s) 2>/dev/null || echo unknown` +uname -v = `(uname -v) 2>/dev/null || echo unknown` + +/usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null || echo unknown` +/bin/uname -X = `(/bin/uname -X) 2>/dev/null || echo unknown` + +/bin/arch = `(/bin/arch) 2>/dev/null || echo unknown` +/usr/bin/arch -k = `(/usr/bin/arch -k) 2>/dev/null || echo unknown` +/usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null || echo unknown` +/usr/bin/hostinfo = `(/usr/bin/hostinfo) 2>/dev/null || echo unknown` +/bin/machine = `(/bin/machine) 2>/dev/null || echo unknown` +/usr/bin/oslevel = `(/usr/bin/oslevel) 2>/dev/null || echo unknown` +/bin/universe = `(/bin/universe) 2>/dev/null || echo unknown` + +_ASUNAME + +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + $as_echo "PATH: $as_dir" +done +IFS=$as_save_IFS + +} >&5 + +cat >&5 <<_ACEOF + + +## ----------- ## +## Core tests. ## +## ----------- ## + +_ACEOF + + +# Keep a trace of the command line. +# Strip out --no-create and --no-recursion so they do not pile up. +# Strip out --silent because we don't want to record it for future runs. +# Also quote any args containing shell meta-characters. +# Make two passes to allow for proper duplicate-argument suppression. +ac_configure_args= +ac_configure_args0= +ac_configure_args1= +ac_must_keep_next=false +for ac_pass in 1 2 +do + for ac_arg + do + case $ac_arg in + -no-create | --no-c* | -n | -no-recursion | --no-r*) continue ;; + -q | -quiet | --quiet | --quie | --qui | --qu | --q \ + | -silent | --silent | --silen | --sile | --sil) + continue ;; + *\'*) + ac_arg=`$as_echo "$ac_arg" | sed "s/'/'\\\\\\\\''/g"` ;; + esac + case $ac_pass in + 1) ac_configure_args0="$ac_configure_args0 '$ac_arg'" ;; + 2) + ac_configure_args1="$ac_configure_args1 '$ac_arg'" + if test $ac_must_keep_next = true; then + ac_must_keep_next=false # Got value, back to normal. + else + case $ac_arg in + *=* | --config-cache | -C | -disable-* | --disable-* \ + | -enable-* | --enable-* | -gas | --g* | -nfp | --nf* \ + | -q | -quiet | --q* | -silent | --sil* | -v | -verb* \ + | -with-* | --with-* | -without-* | --without-* | --x) + case "$ac_configure_args0 " in + "$ac_configure_args1"*" '$ac_arg' "* ) continue ;; + esac + ;; + -* ) ac_must_keep_next=true ;; + esac + fi + ac_configure_args="$ac_configure_args '$ac_arg'" + ;; + esac + done +done +$as_unset ac_configure_args0 || test "${ac_configure_args0+set}" != set || { ac_configure_args0=; export ac_configure_args0; } +$as_unset ac_configure_args1 || test "${ac_configure_args1+set}" != set || { ac_configure_args1=; export ac_configure_args1; } + +# When interrupted or exit'd, cleanup temporary files, and complete +# config.log. We remove comments because anyway the quotes in there +# would cause problems or look ugly. +# WARNING: Use '\'' to represent an apostrophe within the trap. +# WARNING: Do not start the trap code with a newline, due to a FreeBSD 4.0 bug. +trap 'exit_status=$? + # Save into config.log some information that might help in debugging. + { + echo + + cat <<\_ASBOX +## ---------------- ## +## Cache variables. ## +## ---------------- ## +_ASBOX + echo + # The following way of writing the cache mishandles newlines in values, +( + for ac_var in `(set) 2>&1 | sed -n '\''s/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'\''`; do + eval ac_val=\$$ac_var + case $ac_val in #( + *${as_nl}*) + case $ac_var in #( + *_cv_*) { $as_echo "$as_me:$LINENO: WARNING: cache variable $ac_var contains a newline" >&5 +$as_echo "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;; + esac + case $ac_var in #( + _ | IFS | as_nl) ;; #( + BASH_ARGV | BASH_SOURCE) eval $ac_var= ;; #( + *) $as_unset $ac_var ;; + esac ;; + esac + done + (set) 2>&1 | + case $as_nl`(ac_space='\'' '\''; set) 2>&1` in #( + *${as_nl}ac_space=\ *) + sed -n \ + "s/'\''/'\''\\\\'\'''\''/g; + s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\''\\2'\''/p" + ;; #( + *) + sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p" + ;; + esac | + sort +) + echo + + cat <<\_ASBOX +## ----------------- ## +## Output variables. ## +## ----------------- ## +_ASBOX + echo + for ac_var in $ac_subst_vars + do + eval ac_val=\$$ac_var + case $ac_val in + *\'\''*) ac_val=`$as_echo "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;; + esac + $as_echo "$ac_var='\''$ac_val'\''" + done | sort + echo + + if test -n "$ac_subst_files"; then + cat <<\_ASBOX +## ------------------- ## +## File substitutions. ## +## ------------------- ## +_ASBOX + echo + for ac_var in $ac_subst_files + do + eval ac_val=\$$ac_var + case $ac_val in + *\'\''*) ac_val=`$as_echo "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;; + esac + $as_echo "$ac_var='\''$ac_val'\''" + done | sort + echo + fi + + if test -s confdefs.h; then + cat <<\_ASBOX +## ----------- ## +## confdefs.h. ## +## ----------- ## +_ASBOX + echo + cat confdefs.h + echo + fi + test "$ac_signal" != 0 && + $as_echo "$as_me: caught signal $ac_signal" + $as_echo "$as_me: exit $exit_status" + } >&5 + rm -f core *.core core.conftest.* && + rm -f -r conftest* confdefs* conf$$* $ac_clean_files && + exit $exit_status +' 0 +for ac_signal in 1 2 13 15; do + trap 'ac_signal='$ac_signal'; { (exit 1); exit 1; }' $ac_signal +done +ac_signal=0 + +# confdefs.h avoids OS command line length limits that DEFS can exceed. +rm -f -r conftest* confdefs.h + +# Predefined preprocessor variables. + +cat >>confdefs.h <<_ACEOF +#define PACKAGE_NAME "$PACKAGE_NAME" +_ACEOF + + +cat >>confdefs.h <<_ACEOF +#define PACKAGE_TARNAME "$PACKAGE_TARNAME" +_ACEOF + + +cat >>confdefs.h <<_ACEOF +#define PACKAGE_VERSION "$PACKAGE_VERSION" +_ACEOF + + +cat >>confdefs.h <<_ACEOF +#define PACKAGE_STRING "$PACKAGE_STRING" +_ACEOF + + +cat >>confdefs.h <<_ACEOF +#define PACKAGE_BUGREPORT "$PACKAGE_BUGREPORT" +_ACEOF + + +# Let the site file select an alternate cache file if it wants to. +# Prefer an explicitly selected file to automatically selected ones. +ac_site_file1=NONE +ac_site_file2=NONE +if test -n "$CONFIG_SITE"; then + ac_site_file1=$CONFIG_SITE +elif test "x$prefix" != xNONE; then + ac_site_file1=$prefix/share/config.site + ac_site_file2=$prefix/etc/config.site +else + ac_site_file1=$ac_default_prefix/share/config.site + ac_site_file2=$ac_default_prefix/etc/config.site +fi +for ac_site_file in "$ac_site_file1" "$ac_site_file2" +do + test "x$ac_site_file" = xNONE && continue + if test -r "$ac_site_file"; then + { $as_echo "$as_me:$LINENO: loading site script $ac_site_file" >&5 +$as_echo "$as_me: loading site script $ac_site_file" >&6;} + sed 's/^/| /' "$ac_site_file" >&5 + . "$ac_site_file" + fi +done + +if test -r "$cache_file"; then + # Some versions of bash will fail to source /dev/null (special + # files actually), so we avoid doing that. + if test -f "$cache_file"; then + { $as_echo "$as_me:$LINENO: loading cache $cache_file" >&5 +$as_echo "$as_me: loading cache $cache_file" >&6;} + case $cache_file in + [\\/]* | ?:[\\/]* ) . "$cache_file";; + *) . "./$cache_file";; + esac + fi +else + { $as_echo "$as_me:$LINENO: creating cache $cache_file" >&5 +$as_echo "$as_me: creating cache $cache_file" >&6;} + >$cache_file +fi + +# Check that the precious variables saved in the cache have kept the same +# value. +ac_cache_corrupted=false +for ac_var in $ac_precious_vars; do + eval ac_old_set=\$ac_cv_env_${ac_var}_set + eval ac_new_set=\$ac_env_${ac_var}_set + eval ac_old_val=\$ac_cv_env_${ac_var}_value + eval ac_new_val=\$ac_env_${ac_var}_value + case $ac_old_set,$ac_new_set in + set,) + { $as_echo "$as_me:$LINENO: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&5 +$as_echo "$as_me: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&2;} + ac_cache_corrupted=: ;; + ,set) + { $as_echo "$as_me:$LINENO: error: \`$ac_var' was not set in the previous run" >&5 +$as_echo "$as_me: error: \`$ac_var' was not set in the previous run" >&2;} + ac_cache_corrupted=: ;; + ,);; + *) + if test "x$ac_old_val" != "x$ac_new_val"; then + # differences in whitespace do not lead to failure. + ac_old_val_w=`echo x $ac_old_val` + ac_new_val_w=`echo x $ac_new_val` + if test "$ac_old_val_w" != "$ac_new_val_w"; then + { $as_echo "$as_me:$LINENO: error: \`$ac_var' has changed since the previous run:" >&5 +$as_echo "$as_me: error: \`$ac_var' has changed since the previous run:" >&2;} + ac_cache_corrupted=: + else + { $as_echo "$as_me:$LINENO: warning: ignoring whitespace changes in \`$ac_var' since the previous run:" >&5 +$as_echo "$as_me: warning: ignoring whitespace changes in \`$ac_var' since the previous run:" >&2;} + eval $ac_var=\$ac_old_val + fi + { $as_echo "$as_me:$LINENO: former value: \`$ac_old_val'" >&5 +$as_echo "$as_me: former value: \`$ac_old_val'" >&2;} + { $as_echo "$as_me:$LINENO: current value: \`$ac_new_val'" >&5 +$as_echo "$as_me: current value: \`$ac_new_val'" >&2;} + fi;; + esac + # Pass precious variables to config.status. + if test "$ac_new_set" = set; then + case $ac_new_val in + *\'*) ac_arg=$ac_var=`$as_echo "$ac_new_val" | sed "s/'/'\\\\\\\\''/g"` ;; + *) ac_arg=$ac_var=$ac_new_val ;; + esac + case " $ac_configure_args " in + *" '$ac_arg' "*) ;; # Avoid dups. Use of quotes ensures accuracy. + *) ac_configure_args="$ac_configure_args '$ac_arg'" ;; + esac + fi +done +if $ac_cache_corrupted; then + { $as_echo "$as_me:$LINENO: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} + { $as_echo "$as_me:$LINENO: error: changes in the environment can compromise the build" >&5 +$as_echo "$as_me: error: changes in the environment can compromise the build" >&2;} + { { $as_echo "$as_me:$LINENO: error: run \`make distclean' and/or \`rm $cache_file' and start over" >&5 +$as_echo "$as_me: error: run \`make distclean' and/or \`rm $cache_file' and start over" >&2;} + { (exit 1); exit 1; }; } +fi + + + + + + + + + + + + + + + + + +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + + +ac_config_headers="$ac_config_headers config.h" + + +echo "current directory: `pwd`" +echo "command line was: $0 $@" + +############################################################################### +# +# Autoheader stuff +# +############################################################################### + + + + + + + + + + +# This only ever existed in X11R4 and X11R5. +#AH_TEMPLATE([HAVE_XIDLE_EXTENSION], +# [Define this if you have the XIDLE extension installed. If you +# have the XIDLE extension, this is recommended. (You have this +# extension if the file /usr/include/X11/extensions/xidle.h +# exists.) Turning on this flag lets XScreenSaver work better with +# servers which support this extension; but it will still work +# with servers which do not suport it, so it's a good idea to +# compile in support for it if you can.]) + +# Using this extension will crash your X server and make fading not work. +#AH_TEMPLATE([HAVE_MIT_SAVER_EXTENSION], +# [Define this if you have the MIT-SCREEN-SAVER extension +# installed. See the caveats about this extension, above. +# (It's available if /usr/include/X11/extensions/scrnsaver.h +# exists.)]) + +# This only ever existed on SGI hardware. +#AH_TEMPLATE([HAVE_SGI_SAVER_EXTENSION], +# [Define this if you have the SGI SCREEN_SAVER extension. This is +# standard on Irix systems, and not available elsewhere.]) + +# This only ever existed on SGI hardware. +#AH_TEMPLATE([HAVE_SGI_VC_EXTENSION], +# [Define this if you have the SGI-VIDEO-CONTROL extension. This +# is standard on Irix systems, and not available elsewhere.]) + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +# After checking to see that --srcdir is correct (which AC_INIT does) +# check for some random other files that come later in the tar file, +# to make sure everything is here. +# +for d in driver utils hacks hacks/glx ; do + f=$srcdir/$d/Makefile.in + if test \! -r $f ; then + echo "" + echo "ERROR: The package is incomplete: $f does not exist." + echo " This probably means that your download was truncated." + echo "" + exit 1 + fi +done + +############################################################################### +# +# Function to figure out how to run the compiler. +# +############################################################################### + + + + +############################################################################### +# +# Check for availability of various gcc command-line options. +# +############################################################################### + + + + + + + +# Need to disable Objective C extensions in ANSI C on MacOS X to work +# around an Apple-specific gcc bug. +# + + +############################################################################### +# +# Function to figure out how to disable // comments in ANSI C code. +# +# (With recent gcc, this is done with "-std=c89". With older gcc, this +# is done by passing "-lang-c89" to cpp, by passing "-Wp,-lang-c89" to +# gcc. Old gcc doesn't support -std, and new gcc doesn't support -lang. +# so much for compatibility!) +# +# UPDATE: apparently there is NO WAY to tell gcc 3.2.2 to require that +# declarations preceed statements, without resorting to "-pedantic". +# This means that there is no way to get gcc3 to issue warnings that +# ensure that your code complies with the ANSI/ISO C89 standard, without +# also drowning in totally useless warnings. Thank you master may I +# have another. +# +# So, I give up, let's just use -pedantic. +# +############################################################################### + + + + + + +############################################################################### +# +# Function to figure out how to create directory trees. +# +############################################################################### + + + + +############################################################################### +# +# Function to check whether gettimeofday() exists, and how to call it. +# This may define HAVE_GETTIMEOFDAY and GETTIMEOFDAY_TWO_ARGS. +# +############################################################################### + + + + +############################################################################### +# +# Function to find perl5 (defines PERL and PERL_VERSION.) +# +############################################################################### + +# M4 sucks!! perl sucks too!! + +perl_version_cmd='print $]' + + + + + +############################################################################### +# +# Function to demand "bc". Losers. +# +############################################################################### + + + +############################################################################### +# +# Functions to check how to do ICMP PING requests. +# +############################################################################### + + + + + + +############################################################################### +# +# Functions to check for various X11 crap. +# +############################################################################### + +# Try and find the app-defaults directory. +# It sucks that autoconf doesn't do this already... +# + + +############################################################################### +# +# Handle the --with-x-app-defaults option HERE +# +############################################################################### + + +# Check whether --with-x-app-defaults was given. +if test "${with_x_app_defaults+set}" = set; then + withval=$with_x_app_defaults; ac_cv_x_app_defaults="$withval" +else + eval ac_x_app_defaults="$withval" +fi + + + + + + + + + + + +# Random special-cases for X on certain pathological OSes. +# You know who you are. +# + + + + + +############################################################################### +# +# Some utility functions to make checking for X things easier. +# +############################################################################### + +# Like AC_CHECK_HEADER, but it uses the already-computed -I directories. +# + + +# Like AC_EGREP_HEADER, but it uses the already-computed -I directories. +# + + +# Like AC_TRY_COMPILE, but it uses the already-computed -I directories. +# + + + +# Like AC_CHECK_LIB, but it uses the already-computed -I and -L directories. +# Use this sparingly; it probably doesn't work very well on X programs. +# + + +# Like AC_TRY_RUN, but it uses the already-computed -I directories. +# (But not the -L directories!) +# + + + + +# Usage: HANDLE_X_PATH_ARG([variable_name], +# [--command-line-option], +# [descriptive string]) +# +# All of the --with options take three forms: +# +# --with-foo (or --with-foo=yes) +# --without-foo (or --with-foo=no) +# --with-foo=/DIR +# +# This function, HANDLE_X_PATH_ARG, deals with the /DIR case. When it sees +# a directory (string beginning with a slash) it checks to see whether +# /DIR/include and /DIR/lib exist, and adds them to $X_CFLAGS and $X_LIBS +# as appropriate. +# + + + + +############################################################################### +############################################################################### +# +# End of function definitions. Now start actually executing stuff. +# +############################################################################### +############################################################################### + +# WTF! autoconf emits this *way* too late. Do it earlier. +test "x$prefix" = xNONE && prefix=$ac_default_prefix +test "x$exec_prefix" = xNONE && exec_prefix='${prefix}' + + +# random compiler setup +ac_aux_dir= +for ac_dir in "$srcdir" "$srcdir/.." "$srcdir/../.."; do + if test -f "$ac_dir/install-sh"; then + ac_aux_dir=$ac_dir + ac_install_sh="$ac_aux_dir/install-sh -c" + break + elif test -f "$ac_dir/install.sh"; then + ac_aux_dir=$ac_dir + ac_install_sh="$ac_aux_dir/install.sh -c" + break + elif test -f "$ac_dir/shtool"; then + ac_aux_dir=$ac_dir + ac_install_sh="$ac_aux_dir/shtool install -c" + break + fi +done +if test -z "$ac_aux_dir"; then + { { $as_echo "$as_me:$LINENO: error: cannot find install-sh or install.sh in \"$srcdir\" \"$srcdir/..\" \"$srcdir/../..\"" >&5 +$as_echo "$as_me: error: cannot find install-sh or install.sh in \"$srcdir\" \"$srcdir/..\" \"$srcdir/../..\"" >&2;} + { (exit 1); exit 1; }; } +fi + +# These three variables are undocumented and unsupported, +# and are intended to be withdrawn in a future Autoconf release. +# They can cause serious problems if a builder's source tree is in a directory +# whose full name contains unusual characters. +ac_config_guess="$SHELL $ac_aux_dir/config.guess" # Please don't use this var. +ac_config_sub="$SHELL $ac_aux_dir/config.sub" # Please don't use this var. +ac_configure="$SHELL $ac_aux_dir/configure" # Please don't use this var. + + +# Make sure we can run config.sub. +$SHELL "$ac_aux_dir/config.sub" sun4 >/dev/null 2>&1 || + { { $as_echo "$as_me:$LINENO: error: cannot run $SHELL $ac_aux_dir/config.sub" >&5 +$as_echo "$as_me: error: cannot run $SHELL $ac_aux_dir/config.sub" >&2;} + { (exit 1); exit 1; }; } + +{ $as_echo "$as_me:$LINENO: checking build system type" >&5 +$as_echo_n "checking build system type... " >&6; } +if test "${ac_cv_build+set}" = set; then + $as_echo_n "(cached) " >&6 +else + ac_build_alias=$build_alias +test "x$ac_build_alias" = x && + ac_build_alias=`$SHELL "$ac_aux_dir/config.guess"` +test "x$ac_build_alias" = x && + { { $as_echo "$as_me:$LINENO: error: cannot guess build type; you must specify one" >&5 +$as_echo "$as_me: error: cannot guess build type; you must specify one" >&2;} + { (exit 1); exit 1; }; } +ac_cv_build=`$SHELL "$ac_aux_dir/config.sub" $ac_build_alias` || + { { $as_echo "$as_me:$LINENO: error: $SHELL $ac_aux_dir/config.sub $ac_build_alias failed" >&5 +$as_echo "$as_me: error: $SHELL $ac_aux_dir/config.sub $ac_build_alias failed" >&2;} + { (exit 1); exit 1; }; } + +fi +{ $as_echo "$as_me:$LINENO: result: $ac_cv_build" >&5 +$as_echo "$ac_cv_build" >&6; } +case $ac_cv_build in +*-*-*) ;; +*) { { $as_echo "$as_me:$LINENO: error: invalid value of canonical build" >&5 +$as_echo "$as_me: error: invalid value of canonical build" >&2;} + { (exit 1); exit 1; }; };; +esac +build=$ac_cv_build +ac_save_IFS=$IFS; IFS='-' +set x $ac_cv_build +shift +build_cpu=$1 +build_vendor=$2 +shift; shift +# Remember, the first character of IFS is used to create $*, +# except with old shells: +build_os=$* +IFS=$ac_save_IFS +case $build_os in *\ *) build_os=`echo "$build_os" | sed 's/ /-/g'`;; esac + + +{ $as_echo "$as_me:$LINENO: checking host system type" >&5 +$as_echo_n "checking host system type... " >&6; } +if test "${ac_cv_host+set}" = set; then + $as_echo_n "(cached) " >&6 +else + if test "x$host_alias" = x; then + ac_cv_host=$ac_cv_build +else + ac_cv_host=`$SHELL "$ac_aux_dir/config.sub" $host_alias` || + { { $as_echo "$as_me:$LINENO: error: $SHELL $ac_aux_dir/config.sub $host_alias failed" >&5 +$as_echo "$as_me: error: $SHELL $ac_aux_dir/config.sub $host_alias failed" >&2;} + { (exit 1); exit 1; }; } +fi + +fi +{ $as_echo "$as_me:$LINENO: result: $ac_cv_host" >&5 +$as_echo "$ac_cv_host" >&6; } +case $ac_cv_host in +*-*-*) ;; +*) { { $as_echo "$as_me:$LINENO: error: invalid value of canonical host" >&5 +$as_echo "$as_me: error: invalid value of canonical host" >&2;} + { (exit 1); exit 1; }; };; +esac +host=$ac_cv_host +ac_save_IFS=$IFS; IFS='-' +set x $ac_cv_host +shift +host_cpu=$1 +host_vendor=$2 +shift; shift +# Remember, the first character of IFS is used to create $*, +# except with old shells: +host_os=$* +IFS=$ac_save_IFS +case $host_os in *\ *) host_os=`echo "$host_os" | sed 's/ /-/g'`;; esac + + + +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu +if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}gcc", so it can be a program name with args. +set dummy ${ac_tool_prefix}gcc; ac_word=$2 +{ $as_echo "$as_me:$LINENO: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if test "${ac_cv_prog_CC+set}" = set; then + $as_echo_n "(cached) " >&6 +else + if test -n "$CC"; then + ac_cv_prog_CC="$CC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_CC="${ac_tool_prefix}gcc" + $as_echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done +IFS=$as_save_IFS + +fi +fi +CC=$ac_cv_prog_CC +if test -n "$CC"; then + { $as_echo "$as_me:$LINENO: result: $CC" >&5 +$as_echo "$CC" >&6; } +else + { $as_echo "$as_me:$LINENO: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi +if test -z "$ac_cv_prog_CC"; then + ac_ct_CC=$CC + # Extract the first word of "gcc", so it can be a program name with args. +set dummy gcc; ac_word=$2 +{ $as_echo "$as_me:$LINENO: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if test "${ac_cv_prog_ac_ct_CC+set}" = set; then + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_CC"; then + ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_ac_ct_CC="gcc" + $as_echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done +IFS=$as_save_IFS + +fi +fi +ac_ct_CC=$ac_cv_prog_ac_ct_CC +if test -n "$ac_ct_CC"; then + { $as_echo "$as_me:$LINENO: result: $ac_ct_CC" >&5 +$as_echo "$ac_ct_CC" >&6; } +else + { $as_echo "$as_me:$LINENO: result: no" >&5 +$as_echo "no" >&6; } +fi + + if test "x$ac_ct_CC" = x; then + CC="" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:$LINENO: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + CC=$ac_ct_CC + fi +else + CC="$ac_cv_prog_CC" +fi + +if test -z "$CC"; then + if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}cc", so it can be a program name with args. +set dummy ${ac_tool_prefix}cc; ac_word=$2 +{ $as_echo "$as_me:$LINENO: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if test "${ac_cv_prog_CC+set}" = set; then + $as_echo_n "(cached) " >&6 +else + if test -n "$CC"; then + ac_cv_prog_CC="$CC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_CC="${ac_tool_prefix}cc" + $as_echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done +IFS=$as_save_IFS + +fi +fi +CC=$ac_cv_prog_CC +if test -n "$CC"; then + { $as_echo "$as_me:$LINENO: result: $CC" >&5 +$as_echo "$CC" >&6; } +else + { $as_echo "$as_me:$LINENO: result: no" >&5 +$as_echo "no" >&6; } +fi + + + fi +fi +if test -z "$CC"; then + # Extract the first word of "cc", so it can be a program name with args. +set dummy cc; ac_word=$2 +{ $as_echo "$as_me:$LINENO: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if test "${ac_cv_prog_CC+set}" = set; then + $as_echo_n "(cached) " >&6 +else + if test -n "$CC"; then + ac_cv_prog_CC="$CC" # Let the user override the test. +else + ac_prog_rejected=no +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + if test "$as_dir/$ac_word$ac_exec_ext" = "/usr/ucb/cc"; then + ac_prog_rejected=yes + continue + fi + ac_cv_prog_CC="cc" + $as_echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done +IFS=$as_save_IFS + +if test $ac_prog_rejected = yes; then + # We found a bogon in the path, so make sure we never use it. + set dummy $ac_cv_prog_CC + shift + if test $# != 0; then + # We chose a different compiler from the bogus one. + # However, it has the same basename, so the bogon will be chosen + # first if we set CC to just the basename; use the full file name. + shift + ac_cv_prog_CC="$as_dir/$ac_word${1+' '}$@" + fi +fi +fi +fi +CC=$ac_cv_prog_CC +if test -n "$CC"; then + { $as_echo "$as_me:$LINENO: result: $CC" >&5 +$as_echo "$CC" >&6; } +else + { $as_echo "$as_me:$LINENO: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi +if test -z "$CC"; then + if test -n "$ac_tool_prefix"; then + for ac_prog in cl.exe + do + # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args. +set dummy $ac_tool_prefix$ac_prog; ac_word=$2 +{ $as_echo "$as_me:$LINENO: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if test "${ac_cv_prog_CC+set}" = set; then + $as_echo_n "(cached) " >&6 +else + if test -n "$CC"; then + ac_cv_prog_CC="$CC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_CC="$ac_tool_prefix$ac_prog" + $as_echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done +IFS=$as_save_IFS + +fi +fi +CC=$ac_cv_prog_CC +if test -n "$CC"; then + { $as_echo "$as_me:$LINENO: result: $CC" >&5 +$as_echo "$CC" >&6; } +else + { $as_echo "$as_me:$LINENO: result: no" >&5 +$as_echo "no" >&6; } +fi + + + test -n "$CC" && break + done +fi +if test -z "$CC"; then + ac_ct_CC=$CC + for ac_prog in cl.exe +do + # Extract the first word of "$ac_prog", so it can be a program name with args. +set dummy $ac_prog; ac_word=$2 +{ $as_echo "$as_me:$LINENO: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if test "${ac_cv_prog_ac_ct_CC+set}" = set; then + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_CC"; then + ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_ac_ct_CC="$ac_prog" + $as_echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done +IFS=$as_save_IFS + +fi +fi +ac_ct_CC=$ac_cv_prog_ac_ct_CC +if test -n "$ac_ct_CC"; then + { $as_echo "$as_me:$LINENO: result: $ac_ct_CC" >&5 +$as_echo "$ac_ct_CC" >&6; } +else + { $as_echo "$as_me:$LINENO: result: no" >&5 +$as_echo "no" >&6; } +fi + + + test -n "$ac_ct_CC" && break +done + + if test "x$ac_ct_CC" = x; then + CC="" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:$LINENO: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + CC=$ac_ct_CC + fi +fi + +fi + + +test -z "$CC" && { { $as_echo "$as_me:$LINENO: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +{ { $as_echo "$as_me:$LINENO: error: no acceptable C compiler found in \$PATH +See \`config.log' for more details." >&5 +$as_echo "$as_me: error: no acceptable C compiler found in \$PATH +See \`config.log' for more details." >&2;} + { (exit 1); exit 1; }; }; } + +# Provide some information about the compiler. +$as_echo "$as_me:$LINENO: checking for C compiler version" >&5 +set X $ac_compile +ac_compiler=$2 +{ (ac_try="$ac_compiler --version >&5" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\"" +$as_echo "$ac_try_echo") >&5 + (eval "$ac_compiler --version >&5") 2>&5 + ac_status=$? + $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } +{ (ac_try="$ac_compiler -v >&5" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\"" +$as_echo "$ac_try_echo") >&5 + (eval "$ac_compiler -v >&5") 2>&5 + ac_status=$? + $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } +{ (ac_try="$ac_compiler -V >&5" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\"" +$as_echo "$ac_try_echo") >&5 + (eval "$ac_compiler -V >&5") 2>&5 + ac_status=$? + $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } + +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +ac_clean_files_save=$ac_clean_files +ac_clean_files="$ac_clean_files a.out a.out.dSYM a.exe b.out" +# Try to create an executable without -o first, disregard a.out. +# It will help us diagnose broken compilers, and finding out an intuition +# of exeext. +{ $as_echo "$as_me:$LINENO: checking for C compiler default output file name" >&5 +$as_echo_n "checking for C compiler default output file name... " >&6; } +ac_link_default=`$as_echo "$ac_link" | sed 's/ -o *conftest[^ ]*//'` + +# The possible output files: +ac_files="a.out conftest.exe conftest a.exe a_out.exe b.out conftest.*" + +ac_rmfiles= +for ac_file in $ac_files +do + case $ac_file in + *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) ;; + * ) ac_rmfiles="$ac_rmfiles $ac_file";; + esac +done +rm -f $ac_rmfiles + +if { (ac_try="$ac_link_default" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\"" +$as_echo "$ac_try_echo") >&5 + (eval "$ac_link_default") 2>&5 + ac_status=$? + $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; then + # Autoconf-2.13 could set the ac_cv_exeext variable to `no'. +# So ignore a value of `no', otherwise this would lead to `EXEEXT = no' +# in a Makefile. We should not override ac_cv_exeext if it was cached, +# so that the user can short-circuit this test for compilers unknown to +# Autoconf. +for ac_file in $ac_files '' +do + test -f "$ac_file" || continue + case $ac_file in + *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) + ;; + [ab].out ) + # We found the default executable, but exeext='' is most + # certainly right. + break;; + *.* ) + if test "${ac_cv_exeext+set}" = set && test "$ac_cv_exeext" != no; + then :; else + ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'` + fi + # We set ac_cv_exeext here because the later test for it is not + # safe: cross compilers may not add the suffix if given an `-o' + # argument, so we may need to know it at that point already. + # Even if this section looks crufty: it has the advantage of + # actually working. + break;; + * ) + break;; + esac +done +test "$ac_cv_exeext" = no && ac_cv_exeext= + +else + ac_file='' +fi + +{ $as_echo "$as_me:$LINENO: result: $ac_file" >&5 +$as_echo "$ac_file" >&6; } +if test -z "$ac_file"; then + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +{ { $as_echo "$as_me:$LINENO: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +{ { $as_echo "$as_me:$LINENO: error: C compiler cannot create executables +See \`config.log' for more details." >&5 +$as_echo "$as_me: error: C compiler cannot create executables +See \`config.log' for more details." >&2;} + { (exit 77); exit 77; }; }; } +fi + +ac_exeext=$ac_cv_exeext + +# Check that the compiler produces executables we can run. If not, either +# the compiler is broken, or we cross compile. +{ $as_echo "$as_me:$LINENO: checking whether the C compiler works" >&5 +$as_echo_n "checking whether the C compiler works... " >&6; } +# FIXME: These cross compiler hacks should be removed for Autoconf 3.0 +# If not cross compiling, check that we can run a simple program. +if test "$cross_compiling" != yes; then + if { ac_try='./$ac_file' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\"" +$as_echo "$ac_try_echo") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + cross_compiling=no + else + if test "$cross_compiling" = maybe; then + cross_compiling=yes + else + { { $as_echo "$as_me:$LINENO: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +{ { $as_echo "$as_me:$LINENO: error: cannot run C compiled programs. +If you meant to cross compile, use \`--host'. +See \`config.log' for more details." >&5 +$as_echo "$as_me: error: cannot run C compiled programs. +If you meant to cross compile, use \`--host'. +See \`config.log' for more details." >&2;} + { (exit 1); exit 1; }; }; } + fi + fi +fi +{ $as_echo "$as_me:$LINENO: result: yes" >&5 +$as_echo "yes" >&6; } + +rm -f -r a.out a.out.dSYM a.exe conftest$ac_cv_exeext b.out +ac_clean_files=$ac_clean_files_save +# Check that the compiler produces executables we can run. If not, either +# the compiler is broken, or we cross compile. +{ $as_echo "$as_me:$LINENO: checking whether we are cross compiling" >&5 +$as_echo_n "checking whether we are cross compiling... " >&6; } +{ $as_echo "$as_me:$LINENO: result: $cross_compiling" >&5 +$as_echo "$cross_compiling" >&6; } + +{ $as_echo "$as_me:$LINENO: checking for suffix of executables" >&5 +$as_echo_n "checking for suffix of executables... " >&6; } +if { (ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\"" +$as_echo "$ac_try_echo") >&5 + (eval "$ac_link") 2>&5 + ac_status=$? + $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; then + # If both `conftest.exe' and `conftest' are `present' (well, observable) +# catch `conftest.exe'. For instance with Cygwin, `ls conftest' will +# work properly (i.e., refer to `conftest.exe'), while it won't with +# `rm'. +for ac_file in conftest.exe conftest conftest.*; do + test -f "$ac_file" || continue + case $ac_file in + *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) ;; + *.* ) ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'` + break;; + * ) break;; + esac +done +else + { { $as_echo "$as_me:$LINENO: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +{ { $as_echo "$as_me:$LINENO: error: cannot compute suffix of executables: cannot compile and link +See \`config.log' for more details." >&5 +$as_echo "$as_me: error: cannot compute suffix of executables: cannot compile and link +See \`config.log' for more details." >&2;} + { (exit 1); exit 1; }; }; } +fi + +rm -rf conftest$ac_cv_exeext +{ $as_echo "$as_me:$LINENO: result: $ac_cv_exeext" >&5 +$as_echo "$ac_cv_exeext" >&6; } + +rm -rf conftest.$ac_ext +EXEEXT=$ac_cv_exeext +ac_exeext=$EXEEXT +{ $as_echo "$as_me:$LINENO: checking for suffix of object files" >&5 +$as_echo_n "checking for suffix of object files... " >&6; } +if test "${ac_cv_objext+set}" = set; then + $as_echo_n "(cached) " >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +rm -rf conftest.o conftest.obj +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\"" +$as_echo "$ac_try_echo") >&5 + (eval "$ac_compile") 2>&5 + ac_status=$? + $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; then + for ac_file in conftest.o conftest.obj conftest.*; do + test -f "$ac_file" || continue; + case $ac_file in + *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM ) ;; + *) ac_cv_objext=`expr "$ac_file" : '.*\.\(.*\)'` + break;; + esac +done +else + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +{ { $as_echo "$as_me:$LINENO: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +{ { $as_echo "$as_me:$LINENO: error: cannot compute suffix of object files: cannot compile +See \`config.log' for more details." >&5 +$as_echo "$as_me: error: cannot compute suffix of object files: cannot compile +See \`config.log' for more details." >&2;} + { (exit 1); exit 1; }; }; } +fi + +rm -rf conftest.$ac_cv_objext conftest.$ac_ext +fi +{ $as_echo "$as_me:$LINENO: result: $ac_cv_objext" >&5 +$as_echo "$ac_cv_objext" >&6; } +OBJEXT=$ac_cv_objext +ac_objext=$OBJEXT +{ $as_echo "$as_me:$LINENO: checking whether we are using the GNU C compiler" >&5 +$as_echo_n "checking whether we are using the GNU C compiler... " >&6; } +if test "${ac_cv_c_compiler_gnu+set}" = set; then + $as_echo_n "(cached) " >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +int +main () +{ +#ifndef __GNUC__ + choke me +#endif + + ; + return 0; +} +_ACEOF +rm -rf conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\"" +$as_echo "$ac_try_echo") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -rf conftest.er1 + cat conftest.err >&5 + $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest.$ac_objext; then + ac_compiler_gnu=yes +else + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_compiler_gnu=no +fi + +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +ac_cv_c_compiler_gnu=$ac_compiler_gnu + +fi +{ $as_echo "$as_me:$LINENO: result: $ac_cv_c_compiler_gnu" >&5 +$as_echo "$ac_cv_c_compiler_gnu" >&6; } +if test $ac_compiler_gnu = yes; then + GCC=yes +else + GCC= +fi +ac_test_CFLAGS=${CFLAGS+set} +ac_save_CFLAGS=$CFLAGS +{ $as_echo "$as_me:$LINENO: checking whether $CC accepts -g" >&5 +$as_echo_n "checking whether $CC accepts -g... " >&6; } +if test "${ac_cv_prog_cc_g+set}" = set; then + $as_echo_n "(cached) " >&6 +else + ac_save_c_werror_flag=$ac_c_werror_flag + ac_c_werror_flag=yes + ac_cv_prog_cc_g=no + CFLAGS="-g" + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +rm -rf conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\"" +$as_echo "$ac_try_echo") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -rf conftest.er1 + cat conftest.err >&5 + $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest.$ac_objext; then + ac_cv_prog_cc_g=yes +else + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + CFLAGS="" + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +rm -rf conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\"" +$as_echo "$ac_try_echo") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -rf conftest.er1 + cat conftest.err >&5 + $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest.$ac_objext; then + : +else + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_c_werror_flag=$ac_save_c_werror_flag + CFLAGS="-g" + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +rm -rf conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\"" +$as_echo "$ac_try_echo") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -rf conftest.er1 + cat conftest.err >&5 + $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest.$ac_objext; then + ac_cv_prog_cc_g=yes +else + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + +fi + +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi + +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi + +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + ac_c_werror_flag=$ac_save_c_werror_flag +fi +{ $as_echo "$as_me:$LINENO: result: $ac_cv_prog_cc_g" >&5 +$as_echo "$ac_cv_prog_cc_g" >&6; } +if test "$ac_test_CFLAGS" = set; then + CFLAGS=$ac_save_CFLAGS +elif test $ac_cv_prog_cc_g = yes; then + if test "$GCC" = yes; then + CFLAGS="-g -O2" + else + CFLAGS="-g" + fi +else + if test "$GCC" = yes; then + CFLAGS="-O2" + else + CFLAGS= + fi +fi +{ $as_echo "$as_me:$LINENO: checking for $CC option to accept ISO C89" >&5 +$as_echo_n "checking for $CC option to accept ISO C89... " >&6; } +if test "${ac_cv_prog_cc_c89+set}" = set; then + $as_echo_n "(cached) " >&6 +else + ac_cv_prog_cc_c89=no +ac_save_CC=$CC +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include +#include +#include +#include +/* Most of the following tests are stolen from RCS 5.7's src/conf.sh. */ +struct buf { int x; }; +FILE * (*rcsopen) (struct buf *, struct stat *, int); +static char *e (p, i) + char **p; + int i; +{ + return p[i]; +} +static char *f (char * (*g) (char **, int), char **p, ...) +{ + char *s; + va_list v; + va_start (v,p); + s = g (p, va_arg (v,int)); + va_end (v); + return s; +} + +/* OSF 4.0 Compaq cc is some sort of almost-ANSI by default. It has + function prototypes and stuff, but not '\xHH' hex character constants. + These don't provoke an error unfortunately, instead are silently treated + as 'x'. The following induces an error, until -std is added to get + proper ANSI mode. Curiously '\x00'!='x' always comes out true, for an + array size at least. It's necessary to write '\x00'==0 to get something + that's true only with -std. */ +int osf4_cc_array ['\x00' == 0 ? 1 : -1]; + +/* IBM C 6 for AIX is almost-ANSI by default, but it replaces macro parameters + inside strings and character constants. */ +#define FOO(x) 'x' +int xlc6_cc_array[FOO(a) == 'x' ? 1 : -1]; + +int test (int i, double x); +struct s1 {int (*f) (int a);}; +struct s2 {int (*f) (double a);}; +int pairnames (int, char **, FILE *(*)(struct buf *, struct stat *, int), int, int); +int argc; +char **argv; +int +main () +{ +return f (e, argv, 0) != argv[0] || f (e, argv, 1) != argv[1]; + ; + return 0; +} +_ACEOF +for ac_arg in '' -qlanglvl=extc89 -qlanglvl=ansi -std \ + -Ae "-Aa -D_HPUX_SOURCE" "-Xc -D__EXTENSIONS__" +do + CC="$ac_save_CC $ac_arg" + rm -rf conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\"" +$as_echo "$ac_try_echo") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -rf conftest.er1 + cat conftest.err >&5 + $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest.$ac_objext; then + ac_cv_prog_cc_c89=$ac_arg +else + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + +fi + +rm -f core conftest.err conftest.$ac_objext + test "x$ac_cv_prog_cc_c89" != "xno" && break +done +rm -rf conftest.$ac_ext +CC=$ac_save_CC + +fi +# AC_CACHE_VAL +case "x$ac_cv_prog_cc_c89" in + x) + { $as_echo "$as_me:$LINENO: result: none needed" >&5 +$as_echo "none needed" >&6; } ;; + xno) + { $as_echo "$as_me:$LINENO: result: unsupported" >&5 +$as_echo "unsupported" >&6; } ;; + *) + CC="$CC $ac_cv_prog_cc_c89" + { $as_echo "$as_me:$LINENO: result: $ac_cv_prog_cc_c89" >&5 +$as_echo "$ac_cv_prog_cc_c89" >&6; } ;; +esac + + +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + + + if test -z "$GCC"; then + # not using GCC + { $as_echo "$as_me:$LINENO: checking how to request ANSI compilation" >&5 +$as_echo_n "checking how to request ANSI compilation... " >&6; } + case "$host" in + *-hpux* ) + { $as_echo "$as_me:$LINENO: result: HPUX: adding -Ae" >&5 +$as_echo "HPUX: adding -Ae" >&6; } + CC="$CC -Ae" + ;; + *-aix* ) + { $as_echo "$as_me:$LINENO: result: AIX: adding -qlanglvl=ansi -qhalt=e" >&5 +$as_echo "AIX: adding -qlanglvl=ansi -qhalt=e" >&6; } + CC="$CC -qlanglvl=ansi -qhalt=e" + ;; + *-dec-* ) + { $as_echo "$as_me:$LINENO: result: DEC: adding -std1 -ieee" >&5 +$as_echo "DEC: adding -std1 -ieee" >&6; } + CC="$CC -std1" + ;; + *) + { $as_echo "$as_me:$LINENO: result: no idea" >&5 +$as_echo "no idea" >&6; } + ;; + esac + else + # using GCC + case "$host" in + *-solaris*) + { $as_echo "$as_me:$LINENO: result: Solaris: adding -D__EXTENSIONS__" >&5 +$as_echo "Solaris: adding -D__EXTENSIONS__" >&6; } + CC="$CC -D__EXTENSIONS__" + ;; + esac + fi + + OBJCC="$CC" + + { $as_echo "$as_me:$LINENO: checking whether the compiler works on ANSI C" >&5 +$as_echo_n "checking whether the compiler works on ANSI C... " >&6; } + if test "$cross_compiling" = yes; then + { { $as_echo "$as_me:$LINENO: error: Couldn't build even a trivial ANSI C program: check CC." >&5 +$as_echo "$as_me: error: Couldn't build even a trivial ANSI C program: check CC." >&2;} + { (exit 1); exit 1; }; } +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + main(int ac, char **av) { return 0; } +_ACEOF +rm -rf conftest$ac_exeext +if { (ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\"" +$as_echo "$ac_try_echo") >&5 + (eval "$ac_link") 2>&5 + ac_status=$? + $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { ac_try='./conftest$ac_exeext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\"" +$as_echo "$ac_try_echo") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + { $as_echo "$as_me:$LINENO: result: yes" >&5 +$as_echo "yes" >&6; } +else + $as_echo "$as_me: program exited with status $ac_status" >&5 +$as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +( exit $ac_status ) +{ $as_echo "$as_me:$LINENO: result: no" >&5 +$as_echo "no" >&6; } + { { $as_echo "$as_me:$LINENO: error: Couldn't build even a trivial ANSI C program: check CC." >&5 +$as_echo "$as_me: error: Couldn't build even a trivial ANSI C program: check CC." >&2;} + { (exit 1); exit 1; }; } +fi +rm -rf conftest.dSYM +rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext +fi + + + + if test -n "$GCC"; then + { $as_echo "$as_me:$LINENO: result: Turning on gcc compiler warnings." >&5 +$as_echo "Turning on gcc compiler warnings." >&6; } + CC="$CC -pedantic -Wall -Wstrict-prototypes -Wnested-externs -Wmissing-prototypes" + OBJCC="$OBJCC -Wall" + # As of gcc 3.4, we have "-Wdeclaration-after-statement" + # and so perhaps now we can do without -pedantic? + else + case "$host" in + *-irix5* |*-irix6.0-3* ) + { $as_echo "$as_me:$LINENO: result: Turning on SGI compiler warnings." >&5 +$as_echo "Turning on SGI compiler warnings." >&6; } + CC="$CC -fullwarn -use_readonly_const -rdata_shared -g3" + ;; +# *-dec-osf* ) +# if test -z "$GCC"; then +# AC_MSG_RESULT(Turning on DEC C compiler warnings.) +# CC="$CC -migrate -w0 -verbose -warnprotos" +# fi +# ;; + esac + fi + +if test -n "$GCC"; then + { $as_echo "$as_me:$LINENO: checking whether gcc accepts -Wno-overlength-strings" >&5 +$as_echo_n "checking whether gcc accepts -Wno-overlength-strings... " >&6; } +if test "${ac_cv_gcc_accepts_no_overlength+set}" = set; then + $as_echo_n "(cached) " >&6 +else + rm -rf conftest.$ac_ext + touch conftest.$ac_ext + if ( ( gcc -c -Wno-overlength-strings conftest.$ac_ext -o/dev/null >/dev/null ) 2>&1 | \ + grep unrecognized >/dev/null ); then + ac_cv_gcc_accepts_no_overlength=no + else + ac_cv_gcc_accepts_no_overlength=yes + CC="$CC -Wno-overlength-strings" + fi +fi +{ $as_echo "$as_me:$LINENO: result: $ac_cv_gcc_accepts_no_overlength" >&5 +$as_echo "$ac_cv_gcc_accepts_no_overlength" >&6; } + ac_gcc_accepts_no_overlength="$ac_cv_gcc_accepts_no_overlength" + fi + +if test -n "$GCC"; then + { $as_echo "$as_me:$LINENO: checking whether gcc accepts -Wdeclaration-after-statement" >&5 +$as_echo_n "checking whether gcc accepts -Wdeclaration-after-statement... " >&6; } +if test "${ac_cv_gcc_accepts_no_decl_after+set}" = set; then + $as_echo_n "(cached) " >&6 +else + rm -rf conftest.$ac_ext + touch conftest.$ac_ext + if ( ( gcc -c -Wdeclaration-after-statement conftest.$ac_ext -o/dev/null >/dev/null ) 2>&1 | \ + grep unrecognized >/dev/null ); then + ac_cv_gcc_accepts_no_decl_after=no + else + ac_cv_gcc_accepts_no_decl_after=yes + CC="$CC -Wdeclaration-after-statement" + fi +fi +{ $as_echo "$as_me:$LINENO: result: $ac_cv_gcc_accepts_no_decl_after" >&5 +$as_echo "$ac_cv_gcc_accepts_no_decl_after" >&6; } + ac_gcc_accepts_no_decl_after="$ac_cv_gcc_accepts_no_decl_after" + fi + +if test -n "$GCC"; then + { $as_echo "$as_me:$LINENO: checking whether gcc accepts -no-cpp-precomp" >&5 +$as_echo_n "checking whether gcc accepts -no-cpp-precomp... " >&6; } +if test "${ac_cv_gcc_accepts_no_cpp_precomp+set}" = set; then + $as_echo_n "(cached) " >&6 +else + rm -rf conftest.$ac_ext + touch conftest.$ac_ext + if ( ( gcc -c -no-cpp-precomp conftest.$ac_ext -o/dev/null >/dev/null ) 2>&1 | \ + grep unrecognized >/dev/null ); then + ac_cv_gcc_accepts_no_cpp_precomp=no + else + ac_cv_gcc_accepts_no_cpp_precomp=yes + CC="$CC -no-cpp-precomp" + fi +fi +{ $as_echo "$as_me:$LINENO: result: $ac_cv_gcc_accepts_no_cpp_precomp" >&5 +$as_echo "$ac_cv_gcc_accepts_no_cpp_precomp" >&6; } + ac_gcc_accepts_no_cpp_precomp="$ac_cv_gcc_accepts_no_cpp_precomp" + fi + +if test -n "$GCC"; then + + case "$host" in + *-darwin* ) + # Fucking Apple let // comments sneak into OpenGL headers, so + # we *must* allow // comments when compiling on Mac OS 10.6! FUCK! + ;; + *) + if test -n "$GCC"; then + { $as_echo "$as_me:$LINENO: checking whether gcc accepts -std=c89" >&5 +$as_echo_n "checking whether gcc accepts -std=c89... " >&6; } +if test "${ac_cv_gcc_accepts_std+set}" = set; then + $as_echo_n "(cached) " >&6 +else + rm -rf conftest.$ac_ext + touch conftest.$ac_ext + if ( ( gcc -c -std=c89 conftest.$ac_ext -o/dev/null >/dev/null ) 2>&1 | \ + grep unrecognized >/dev/null ); then + ac_cv_gcc_accepts_std=no + else + ac_cv_gcc_accepts_std=yes + CC="$CC -std=c89" + fi +fi +{ $as_echo "$as_me:$LINENO: result: $ac_cv_gcc_accepts_std" >&5 +$as_echo "$ac_cv_gcc_accepts_std" >&6; } + ac_gcc_accepts_std="$ac_cv_gcc_accepts_std" + fi + + ;; + esac + + { $as_echo "$as_me:$LINENO: result: Disabling C++ comments in ANSI C code." >&5 +$as_echo "Disabling C++ comments in ANSI C code." >&6; } + # + # The reason that // comments are banned from xscreensaver is that gcc is + # basically the only compiler in the world that supports them in C code. + # All other vendors support them only in their C++ compilers, not in their + # ANSI C compilers. This means that it's a portability problem: every time + # these comments have snuck into the xscreensaver source code, I've gotten + # complaints about it the next day. So we turn off support for them in gcc + # as well to prevent them from accidentially slipping in. + # + if test "$ac_gcc_accepts_std" = yes ; then + # + # -std=c89 defines __STRICT_ANSI__, which we don't want. + # (That appears to be the only additional preprocessor symbol + # it defines, in addition to the syntax changes it makes.) + # + # -std=gnu89 is no good, because // comments were a GNU extension + # before they were in the ANSI C 99 spec... (gcc 2.96 permits // + # with -std=gnu89 but not with -std=c89.) + # + # $CC already contains "-std=c89" via AC_GCC_ACCEPTS_STD + CC="$CC -U__STRICT_ANSI__" +# else +# # The old way: +# CC="$CC -Wp,-lang-c89" + fi + fi + +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu +{ $as_echo "$as_me:$LINENO: checking how to run the C preprocessor" >&5 +$as_echo_n "checking how to run the C preprocessor... " >&6; } +# On Suns, sometimes $CPP names a directory. +if test -n "$CPP" && test -d "$CPP"; then + CPP= +fi +if test -z "$CPP"; then + if test "${ac_cv_prog_CPP+set}" = set; then + $as_echo_n "(cached) " >&6 +else + # Double quotes because CPP needs to be expanded + for CPP in "$CC -E" "$CC -E -traditional-cpp" "/lib/cpp" + do + ac_preproc_ok=false +for ac_c_preproc_warn_flag in '' yes +do + # Use a header file that comes with gcc, so configuring glibc + # with a fresh cross-compiler works. + # Prefer to if __STDC__ is defined, since + # exists even on freestanding compilers. + # On the NeXT, cc -E runs the code through the compiler's parser, + # not just through cpp. "Syntax error" is here to catch this case. + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#ifdef __STDC__ +# include +#else +# include +#endif + Syntax error +_ACEOF +if { (ac_try="$ac_cpp conftest.$ac_ext" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\"" +$as_echo "$ac_try_echo") >&5 + (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -rf conftest.er1 + cat conftest.err >&5 + $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } >/dev/null && { + test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" || + test ! -s conftest.err + }; then + : +else + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + # Broken: fails on valid input. +continue +fi + +rm -rf conftest.err conftest.$ac_ext + + # OK, works on sane cases. Now check whether nonexistent headers + # can be detected and how. + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include +_ACEOF +if { (ac_try="$ac_cpp conftest.$ac_ext" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\"" +$as_echo "$ac_try_echo") >&5 + (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -rf conftest.er1 + cat conftest.err >&5 + $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } >/dev/null && { + test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" || + test ! -s conftest.err + }; then + # Broken: success on invalid input. +continue +else + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + # Passes both tests. +ac_preproc_ok=: +break +fi + +rm -rf conftest.err conftest.$ac_ext + +done +# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped. +rm -rf conftest.err conftest.$ac_ext +if $ac_preproc_ok; then + break +fi + + done + ac_cv_prog_CPP=$CPP + +fi + CPP=$ac_cv_prog_CPP +else + ac_cv_prog_CPP=$CPP +fi +{ $as_echo "$as_me:$LINENO: result: $CPP" >&5 +$as_echo "$CPP" >&6; } +ac_preproc_ok=false +for ac_c_preproc_warn_flag in '' yes +do + # Use a header file that comes with gcc, so configuring glibc + # with a fresh cross-compiler works. + # Prefer to if __STDC__ is defined, since + # exists even on freestanding compilers. + # On the NeXT, cc -E runs the code through the compiler's parser, + # not just through cpp. "Syntax error" is here to catch this case. + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#ifdef __STDC__ +# include +#else +# include +#endif + Syntax error +_ACEOF +if { (ac_try="$ac_cpp conftest.$ac_ext" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\"" +$as_echo "$ac_try_echo") >&5 + (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -rf conftest.er1 + cat conftest.err >&5 + $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } >/dev/null && { + test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" || + test ! -s conftest.err + }; then + : +else + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + # Broken: fails on valid input. +continue +fi + +rm -rf conftest.err conftest.$ac_ext + + # OK, works on sane cases. Now check whether nonexistent headers + # can be detected and how. + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include +_ACEOF +if { (ac_try="$ac_cpp conftest.$ac_ext" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\"" +$as_echo "$ac_try_echo") >&5 + (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -rf conftest.er1 + cat conftest.err >&5 + $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } >/dev/null && { + test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" || + test ! -s conftest.err + }; then + # Broken: success on invalid input. +continue +else + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + # Passes both tests. +ac_preproc_ok=: +break +fi + +rm -rf conftest.err conftest.$ac_ext + +done +# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped. +rm -rf conftest.err conftest.$ac_ext +if $ac_preproc_ok; then + : +else + { { $as_echo "$as_me:$LINENO: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +{ { $as_echo "$as_me:$LINENO: error: C preprocessor \"$CPP\" fails sanity check +See \`config.log' for more details." >&5 +$as_echo "$as_me: error: C preprocessor \"$CPP\" fails sanity check +See \`config.log' for more details." >&2;} + { (exit 1); exit 1; }; }; } +fi + +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + +{ $as_echo "$as_me:$LINENO: checking for an ANSI C-conforming const" >&5 +$as_echo_n "checking for an ANSI C-conforming const... " >&6; } +if test "${ac_cv_c_const+set}" = set; then + $as_echo_n "(cached) " >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +int +main () +{ +/* FIXME: Include the comments suggested by Paul. */ +#ifndef __cplusplus + /* Ultrix mips cc rejects this. */ + typedef int charset[2]; + const charset cs; + /* SunOS 4.1.1 cc rejects this. */ + char const *const *pcpcc; + char **ppc; + /* NEC SVR4.0.2 mips cc rejects this. */ + struct point {int x, y;}; + static struct point const zero = {0,0}; + /* AIX XL C 1.02.0.0 rejects this. + It does not let you subtract one const X* pointer from another in + an arm of an if-expression whose if-part is not a constant + expression */ + const char *g = "string"; + pcpcc = &g + (g ? g-g : 0); + /* HPUX 7.0 cc rejects these. */ + ++pcpcc; + ppc = (char**) pcpcc; + pcpcc = (char const *const *) ppc; + { /* SCO 3.2v4 cc rejects this. */ + char *t; + char const *s = 0 ? (char *) 0 : (char const *) 0; + + *t++ = 0; + if (s) return 0; + } + { /* Someone thinks the Sun supposedly-ANSI compiler will reject this. */ + int x[] = {25, 17}; + const int *foo = &x[0]; + ++foo; + } + { /* Sun SC1.0 ANSI compiler rejects this -- but not the above. */ + typedef const int *iptr; + iptr p = 0; + ++p; + } + { /* AIX XL C 1.02.0.0 rejects this saying + "k.c", line 2.27: 1506-025 (S) Operand must be a modifiable lvalue. */ + struct s { int j; const int *ap[3]; }; + struct s *b; b->j = 5; + } + { /* ULTRIX-32 V3.1 (Rev 9) vcc rejects this */ + const int foo = 10; + if (!foo) return 0; + } + return !cs[0] && !zero.x; +#endif + + ; + return 0; +} +_ACEOF +rm -rf conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\"" +$as_echo "$ac_try_echo") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -rf conftest.er1 + cat conftest.err >&5 + $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest.$ac_objext; then + ac_cv_c_const=yes +else + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_cv_c_const=no +fi + +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +{ $as_echo "$as_me:$LINENO: result: $ac_cv_c_const" >&5 +$as_echo "$ac_cv_c_const" >&6; } +if test $ac_cv_c_const = no; then + +cat >>confdefs.h <<\_ACEOF +#define const /**/ +_ACEOF + +fi + +{ $as_echo "$as_me:$LINENO: checking for inline" >&5 +$as_echo_n "checking for inline... " >&6; } +if test "${ac_cv_c_inline+set}" = set; then + $as_echo_n "(cached) " >&6 +else + ac_cv_c_inline=no +for ac_kw in inline __inline__ __inline; do + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#ifndef __cplusplus +typedef int foo_t; +static $ac_kw foo_t static_foo () {return 0; } +$ac_kw foo_t foo () {return 0; } +#endif + +_ACEOF +rm -rf conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\"" +$as_echo "$ac_try_echo") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -rf conftest.er1 + cat conftest.err >&5 + $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest.$ac_objext; then + ac_cv_c_inline=$ac_kw +else + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + +fi + +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + test "$ac_cv_c_inline" != no && break +done + +fi +{ $as_echo "$as_me:$LINENO: result: $ac_cv_c_inline" >&5 +$as_echo "$ac_cv_c_inline" >&6; } + + +case $ac_cv_c_inline in + inline | yes) ;; + *) + case $ac_cv_c_inline in + no) ac_val=;; + *) ac_val=$ac_cv_c_inline;; + esac + cat >>confdefs.h <<_ACEOF +#ifndef __cplusplus +#define inline $ac_val +#endif +_ACEOF + ;; +esac + + +ac_bc_result=`echo 6+9 | bc 2>/dev/null` + { $as_echo "$as_me:$LINENO: checking for bc" >&5 +$as_echo_n "checking for bc... " >&6; } + if test "$ac_bc_result" = "15" ; then + { $as_echo "$as_me:$LINENO: result: yes" >&5 +$as_echo "yes" >&6; } + else + { $as_echo "$as_me:$LINENO: result: no" >&5 +$as_echo "no" >&6; } + echo '' + { { $as_echo "$as_me:$LINENO: error: Your system doesn't have \"bc\", which has been a standard + part of Unix since the 1970s. Come back when your vendor + has grown a clue." >&5 +$as_echo "$as_me: error: Your system doesn't have \"bc\", which has been a standard + part of Unix since the 1970s. Come back when your vendor + has grown a clue." >&2;} + { (exit 1); exit 1; }; } + fi + + +# stuff for Makefiles +# Find a good install program. We prefer a C program (faster), +# so one script is as good as another. But avoid the broken or +# incompatible versions: +# SysV /etc/install, /usr/sbin/install +# SunOS /usr/etc/install +# IRIX /sbin/install +# AIX /bin/install +# AmigaOS /C/install, which installs bootblocks on floppy discs +# AIX 4 /usr/bin/installbsd, which doesn't work without a -g flag +# AFS /usr/afsws/bin/install, which mishandles nonexistent args +# SVR4 /usr/ucb/install, which tries to use the nonexistent group "staff" +# OS/2's system install, which has a completely different semantic +# ./install, which can be erroneously created by make from ./install.sh. +# Reject install programs that cannot install multiple files. +{ $as_echo "$as_me:$LINENO: checking for a BSD-compatible install" >&5 +$as_echo_n "checking for a BSD-compatible install... " >&6; } +if test -z "$INSTALL"; then +if test "${ac_cv_path_install+set}" = set; then + $as_echo_n "(cached) " >&6 +else + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + # Account for people who put trailing slashes in PATH elements. +case $as_dir/ in + ./ | .// | /cC/* | \ + /etc/* | /usr/sbin/* | /usr/etc/* | /sbin/* | /usr/afsws/bin/* | \ + ?:\\/os2\\/install\\/* | ?:\\/OS2\\/INSTALL\\/* | \ + /usr/ucb/* ) ;; + *) + # OSF1 and SCO ODT 3.0 have their own names for install. + # Don't use installbsd from OSF since it installs stuff as root + # by default. + for ac_prog in ginstall scoinst install; do + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_prog$ac_exec_ext" && $as_test_x "$as_dir/$ac_prog$ac_exec_ext"; }; then + if test $ac_prog = install && + grep dspmsg "$as_dir/$ac_prog$ac_exec_ext" >/dev/null 2>&1; then + # AIX install. It has an incompatible calling convention. + : + elif test $ac_prog = install && + grep pwplus "$as_dir/$ac_prog$ac_exec_ext" >/dev/null 2>&1; then + # program-specific install script used by HP pwplus--don't use. + : + else + rm -rf conftest.one conftest.two conftest.dir + echo one > conftest.one + echo two > conftest.two + mkdir conftest.dir + if "$as_dir/$ac_prog$ac_exec_ext" -c conftest.one conftest.two "`pwd`/conftest.dir" && + test -s conftest.one && test -s conftest.two && + test -s conftest.dir/conftest.one && + test -s conftest.dir/conftest.two + then + ac_cv_path_install="$as_dir/$ac_prog$ac_exec_ext -c" + break 3 + fi + fi + fi + done + done + ;; +esac + +done +IFS=$as_save_IFS + +rm -rf conftest.one conftest.two conftest.dir + +fi + if test "${ac_cv_path_install+set}" = set; then + INSTALL=$ac_cv_path_install + else + # As a last resort, use the slow shell script. Don't cache a + # value for INSTALL within a source directory, because that will + # break other packages using the cache if that directory is + # removed, or if the value is a relative name. + INSTALL=$ac_install_sh + fi +fi +{ $as_echo "$as_me:$LINENO: result: $INSTALL" >&5 +$as_echo "$INSTALL" >&6; } + +# Use test -z because SunOS4 sh mishandles braces in ${var-val}. +# It thinks the first close brace ends the variable substitution. +test -z "$INSTALL_PROGRAM" && INSTALL_PROGRAM='${INSTALL}' + +test -z "$INSTALL_SCRIPT" && INSTALL_SCRIPT='${INSTALL}' + +test -z "$INSTALL_DATA" && INSTALL_DATA='${INSTALL} -m 644' + +{ $as_echo "$as_me:$LINENO: checking whether \"\${INSTALL} -d\" creates intermediate directories" >&5 +$as_echo_n "checking whether \"\${INSTALL} -d\" creates intermediate directories... " >&6; } +if test "${ac_cv_install_d_creates_dirs+set}" = set; then + $as_echo_n "(cached) " >&6 +else + ac_cv_install_d_creates_dirs=no + rm -rf conftestdir + if mkdir conftestdir; then + cd conftestdir 2>/dev/null + ${INSTALL} -d `pwd`/dir1/dir2 >/dev/null 2>&1 + if test -d dir1/dir2/. ; then + ac_cv_install_d_creates_dirs=yes + fi + cd .. 2>/dev/null + rm -rf conftestdir + fi + +fi +{ $as_echo "$as_me:$LINENO: result: $ac_cv_install_d_creates_dirs" >&5 +$as_echo "$ac_cv_install_d_creates_dirs" >&6; } + + if test "$ac_cv_install_d_creates_dirs" = no ; then + { $as_echo "$as_me:$LINENO: checking whether \"mkdir -p\" creates intermediate directories" >&5 +$as_echo_n "checking whether \"mkdir -p\" creates intermediate directories... " >&6; } +if test "${ac_cv_mkdir_p_creates_dirs+set}" = set; then + $as_echo_n "(cached) " >&6 +else + ac_cv_mkdir_p_creates_dirs=no + rm -rf conftestdir + if mkdir conftestdir; then + cd conftestdir 2>/dev/null + mkdir -p dir1/dir2 >/dev/null 2>&1 + if test -d dir1/dir2/. ; then + ac_cv_mkdir_p_creates_dirs=yes + fi + cd .. 2>/dev/null + rm -rf conftestdir + fi + +fi +{ $as_echo "$as_me:$LINENO: result: $ac_cv_mkdir_p_creates_dirs" >&5 +$as_echo "$ac_cv_mkdir_p_creates_dirs" >&6; } + fi + + if test "$ac_cv_install_d_creates_dirs" = yes ; then + INSTALL_DIRS='${INSTALL} -d' + elif test "$ac_cv_mkdir_p_creates_dirs" = yes ; then + INSTALL_DIRS='mkdir -p' + else + # any other ideas? + INSTALL_DIRS='${INSTALL} -d' + fi + +{ $as_echo "$as_me:$LINENO: checking whether ${MAKE-make} sets \$(MAKE)" >&5 +$as_echo_n "checking whether ${MAKE-make} sets \$(MAKE)... " >&6; } +set x ${MAKE-make} +ac_make=`$as_echo "$2" | sed 's/+/p/g; s/[^a-zA-Z0-9_]/_/g'` +if { as_var=ac_cv_prog_make_${ac_make}_set; eval "test \"\${$as_var+set}\" = set"; }; then + $as_echo_n "(cached) " >&6 +else + cat >conftest.make <<\_ACEOF +SHELL = /bin/sh +all: + @echo '@@@%%%=$(MAKE)=@@@%%%' +_ACEOF +# GNU make sometimes prints "make[1]: Entering...", which would confuse us. +case `${MAKE-make} -f conftest.make 2>/dev/null` in + *@@@%%%=?*=@@@%%%*) + eval ac_cv_prog_make_${ac_make}_set=yes;; + *) + eval ac_cv_prog_make_${ac_make}_set=no;; +esac +rm -rf conftest.make +fi +if eval test \$ac_cv_prog_make_${ac_make}_set = yes; then + { $as_echo "$as_me:$LINENO: result: yes" >&5 +$as_echo "yes" >&6; } + SET_MAKE= +else + { $as_echo "$as_me:$LINENO: result: no" >&5 +$as_echo "no" >&6; } + SET_MAKE="MAKE=${MAKE-make}" +fi + + +# By default, autoconf sets INSTALL_SCRIPT to '${INSTALL_PROGRAM}'. +# That's wrong: it should be set to '${INSTALL}', so that one can +# implement the "install-strip" target properly (strip executables, +# but do not try to strip scripts.) +# +INSTALL_SCRIPT='${INSTALL}' + +# random libc stuff + +{ $as_echo "$as_me:$LINENO: checking for grep that handles long lines and -e" >&5 +$as_echo_n "checking for grep that handles long lines and -e... " >&6; } +if test "${ac_cv_path_GREP+set}" = set; then + $as_echo_n "(cached) " >&6 +else + if test -z "$GREP"; then + ac_path_GREP_found=false + # Loop through the user's path and test for each of PROGNAME-LIST + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_prog in grep ggrep; do + for ac_exec_ext in '' $ac_executable_extensions; do + ac_path_GREP="$as_dir/$ac_prog$ac_exec_ext" + { test -f "$ac_path_GREP" && $as_test_x "$ac_path_GREP"; } || continue +# Check for GNU ac_path_GREP and select it if it is found. + # Check for GNU $ac_path_GREP +case `"$ac_path_GREP" --version 2>&1` in +*GNU*) + ac_cv_path_GREP="$ac_path_GREP" ac_path_GREP_found=:;; +*) + ac_count=0 + $as_echo_n 0123456789 >"conftest.in" + while : + do + cat "conftest.in" "conftest.in" >"conftest.tmp" + mv "conftest.tmp" "conftest.in" + cp "conftest.in" "conftest.nl" + $as_echo 'GREP' >> "conftest.nl" + "$ac_path_GREP" -e 'GREP$' -e '-(cannot match)-' < "conftest.nl" >"conftest.out" 2>/dev/null || break + diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break + ac_count=`expr $ac_count + 1` + if test $ac_count -gt ${ac_path_GREP_max-0}; then + # Best one so far, save it but keep looking for a better one + ac_cv_path_GREP="$ac_path_GREP" + ac_path_GREP_max=$ac_count + fi + # 10*(2^10) chars as input seems more than enough + test $ac_count -gt 10 && break + done + rm -rf conftest.in conftest.tmp conftest.nl conftest.out;; +esac + + $ac_path_GREP_found && break 3 + done + done +done +IFS=$as_save_IFS + if test -z "$ac_cv_path_GREP"; then + { { $as_echo "$as_me:$LINENO: error: no acceptable grep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" >&5 +$as_echo "$as_me: error: no acceptable grep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" >&2;} + { (exit 1); exit 1; }; } + fi +else + ac_cv_path_GREP=$GREP +fi + +fi +{ $as_echo "$as_me:$LINENO: result: $ac_cv_path_GREP" >&5 +$as_echo "$ac_cv_path_GREP" >&6; } + GREP="$ac_cv_path_GREP" + + +{ $as_echo "$as_me:$LINENO: checking for egrep" >&5 +$as_echo_n "checking for egrep... " >&6; } +if test "${ac_cv_path_EGREP+set}" = set; then + $as_echo_n "(cached) " >&6 +else + if echo a | $GREP -E '(a|b)' >/dev/null 2>&1 + then ac_cv_path_EGREP="$GREP -E" + else + if test -z "$EGREP"; then + ac_path_EGREP_found=false + # Loop through the user's path and test for each of PROGNAME-LIST + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_prog in egrep; do + for ac_exec_ext in '' $ac_executable_extensions; do + ac_path_EGREP="$as_dir/$ac_prog$ac_exec_ext" + { test -f "$ac_path_EGREP" && $as_test_x "$ac_path_EGREP"; } || continue +# Check for GNU ac_path_EGREP and select it if it is found. + # Check for GNU $ac_path_EGREP +case `"$ac_path_EGREP" --version 2>&1` in +*GNU*) + ac_cv_path_EGREP="$ac_path_EGREP" ac_path_EGREP_found=:;; +*) + ac_count=0 + $as_echo_n 0123456789 >"conftest.in" + while : + do + cat "conftest.in" "conftest.in" >"conftest.tmp" + mv "conftest.tmp" "conftest.in" + cp "conftest.in" "conftest.nl" + $as_echo 'EGREP' >> "conftest.nl" + "$ac_path_EGREP" 'EGREP$' < "conftest.nl" >"conftest.out" 2>/dev/null || break + diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break + ac_count=`expr $ac_count + 1` + if test $ac_count -gt ${ac_path_EGREP_max-0}; then + # Best one so far, save it but keep looking for a better one + ac_cv_path_EGREP="$ac_path_EGREP" + ac_path_EGREP_max=$ac_count + fi + # 10*(2^10) chars as input seems more than enough + test $ac_count -gt 10 && break + done + rm -rf conftest.in conftest.tmp conftest.nl conftest.out;; +esac + + $ac_path_EGREP_found && break 3 + done + done +done +IFS=$as_save_IFS + if test -z "$ac_cv_path_EGREP"; then + { { $as_echo "$as_me:$LINENO: error: no acceptable egrep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" >&5 +$as_echo "$as_me: error: no acceptable egrep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" >&2;} + { (exit 1); exit 1; }; } + fi +else + ac_cv_path_EGREP=$EGREP +fi + + fi +fi +{ $as_echo "$as_me:$LINENO: result: $ac_cv_path_EGREP" >&5 +$as_echo "$ac_cv_path_EGREP" >&6; } + EGREP="$ac_cv_path_EGREP" + + +{ $as_echo "$as_me:$LINENO: checking for ANSI C header files" >&5 +$as_echo_n "checking for ANSI C header files... " >&6; } +if test "${ac_cv_header_stdc+set}" = set; then + $as_echo_n "(cached) " >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include +#include +#include +#include + +int +main () +{ + + ; + return 0; +} +_ACEOF +rm -rf conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\"" +$as_echo "$ac_try_echo") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -rf conftest.er1 + cat conftest.err >&5 + $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest.$ac_objext; then + ac_cv_header_stdc=yes +else + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_cv_header_stdc=no +fi + +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + +if test $ac_cv_header_stdc = yes; then + # SunOS 4.x string.h does not declare mem*, contrary to ANSI. + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include + +_ACEOF +if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | + $EGREP "memchr" >/dev/null 2>&1; then + : +else + ac_cv_header_stdc=no +fi +rm -rf conftest* + +fi + +if test $ac_cv_header_stdc = yes; then + # ISC 2.0.2 stdlib.h does not declare free, contrary to ANSI. + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include + +_ACEOF +if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | + $EGREP "free" >/dev/null 2>&1; then + : +else + ac_cv_header_stdc=no +fi +rm -rf conftest* + +fi + +if test $ac_cv_header_stdc = yes; then + # /bin/cc in Irix-4.0.5 gets non-ANSI ctype macros unless using -ansi. + if test "$cross_compiling" = yes; then + : +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include +#include +#if ((' ' & 0x0FF) == 0x020) +# define ISLOWER(c) ('a' <= (c) && (c) <= 'z') +# define TOUPPER(c) (ISLOWER(c) ? 'A' + ((c) - 'a') : (c)) +#else +# define ISLOWER(c) \ + (('a' <= (c) && (c) <= 'i') \ + || ('j' <= (c) && (c) <= 'r') \ + || ('s' <= (c) && (c) <= 'z')) +# define TOUPPER(c) (ISLOWER(c) ? ((c) | 0x40) : (c)) +#endif + +#define XOR(e, f) (((e) && !(f)) || (!(e) && (f))) +int +main () +{ + int i; + for (i = 0; i < 256; i++) + if (XOR (islower (i), ISLOWER (i)) + || toupper (i) != TOUPPER (i)) + return 2; + return 0; +} +_ACEOF +rm -rf conftest$ac_exeext +if { (ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\"" +$as_echo "$ac_try_echo") >&5 + (eval "$ac_link") 2>&5 + ac_status=$? + $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { ac_try='./conftest$ac_exeext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\"" +$as_echo "$ac_try_echo") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + : +else + $as_echo "$as_me: program exited with status $ac_status" >&5 +$as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +( exit $ac_status ) +ac_cv_header_stdc=no +fi +rm -rf conftest.dSYM +rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext +fi + + +fi +fi +{ $as_echo "$as_me:$LINENO: result: $ac_cv_header_stdc" >&5 +$as_echo "$ac_cv_header_stdc" >&6; } +if test $ac_cv_header_stdc = yes; then + +cat >>confdefs.h <<\_ACEOF +#define STDC_HEADERS 1 +_ACEOF + +fi + +# On IRIX 5.3, sys/types and inttypes.h are conflicting. + + + + + + + + + +for ac_header in sys/types.h sys/stat.h stdlib.h string.h memory.h strings.h \ + inttypes.h stdint.h unistd.h +do +as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh` +{ $as_echo "$as_me:$LINENO: checking for $ac_header" >&5 +$as_echo_n "checking for $ac_header... " >&6; } +if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then + $as_echo_n "(cached) " >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +$ac_includes_default + +#include <$ac_header> +_ACEOF +rm -rf conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\"" +$as_echo "$ac_try_echo") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -rf conftest.er1 + cat conftest.err >&5 + $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest.$ac_objext; then + eval "$as_ac_Header=yes" +else + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + eval "$as_ac_Header=no" +fi + +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +ac_res=`eval 'as_val=${'$as_ac_Header'} + $as_echo "$as_val"'` + { $as_echo "$as_me:$LINENO: result: $ac_res" >&5 +$as_echo "$ac_res" >&6; } +as_val=`eval 'as_val=${'$as_ac_Header'} + $as_echo "$as_val"'` + if test "x$as_val" = x""yes; then + cat >>confdefs.h <<_ACEOF +#define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1 +_ACEOF + +fi + +done + + + +for ac_header in unistd.h +do +as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh` +if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then + { $as_echo "$as_me:$LINENO: checking for $ac_header" >&5 +$as_echo_n "checking for $ac_header... " >&6; } +if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then + $as_echo_n "(cached) " >&6 +fi +ac_res=`eval 'as_val=${'$as_ac_Header'} + $as_echo "$as_val"'` + { $as_echo "$as_me:$LINENO: result: $ac_res" >&5 +$as_echo "$ac_res" >&6; } +else + # Is the header compilable? +{ $as_echo "$as_me:$LINENO: checking $ac_header usability" >&5 +$as_echo_n "checking $ac_header usability... " >&6; } +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +$ac_includes_default +#include <$ac_header> +_ACEOF +rm -rf conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\"" +$as_echo "$ac_try_echo") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -rf conftest.er1 + cat conftest.err >&5 + $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest.$ac_objext; then + ac_header_compiler=yes +else + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_header_compiler=no +fi + +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +{ $as_echo "$as_me:$LINENO: result: $ac_header_compiler" >&5 +$as_echo "$ac_header_compiler" >&6; } + +# Is the header present? +{ $as_echo "$as_me:$LINENO: checking $ac_header presence" >&5 +$as_echo_n "checking $ac_header presence... " >&6; } +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include <$ac_header> +_ACEOF +if { (ac_try="$ac_cpp conftest.$ac_ext" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\"" +$as_echo "$ac_try_echo") >&5 + (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -rf conftest.er1 + cat conftest.err >&5 + $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } >/dev/null && { + test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" || + test ! -s conftest.err + }; then + ac_header_preproc=yes +else + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_header_preproc=no +fi + +rm -rf conftest.err conftest.$ac_ext +{ $as_echo "$as_me:$LINENO: result: $ac_header_preproc" >&5 +$as_echo "$ac_header_preproc" >&6; } + +# So? What about this header? +case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in + yes:no: ) + { $as_echo "$as_me:$LINENO: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&5 +$as_echo "$as_me: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&2;} + { $as_echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the compiler's result" >&5 +$as_echo "$as_me: WARNING: $ac_header: proceeding with the compiler's result" >&2;} + ac_header_preproc=yes + ;; + no:yes:* ) + { $as_echo "$as_me:$LINENO: WARNING: $ac_header: present but cannot be compiled" >&5 +$as_echo "$as_me: WARNING: $ac_header: present but cannot be compiled" >&2;} + { $as_echo "$as_me:$LINENO: WARNING: $ac_header: check for missing prerequisite headers?" >&5 +$as_echo "$as_me: WARNING: $ac_header: check for missing prerequisite headers?" >&2;} + { $as_echo "$as_me:$LINENO: WARNING: $ac_header: see the Autoconf documentation" >&5 +$as_echo "$as_me: WARNING: $ac_header: see the Autoconf documentation" >&2;} + { $as_echo "$as_me:$LINENO: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&5 +$as_echo "$as_me: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&2;} + { $as_echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the preprocessor's result" >&5 +$as_echo "$as_me: WARNING: $ac_header: proceeding with the preprocessor's result" >&2;} + { $as_echo "$as_me:$LINENO: WARNING: $ac_header: in the future, the compiler will take precedence" >&5 +$as_echo "$as_me: WARNING: $ac_header: in the future, the compiler will take precedence" >&2;} + + ;; +esac +{ $as_echo "$as_me:$LINENO: checking for $ac_header" >&5 +$as_echo_n "checking for $ac_header... " >&6; } +if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then + $as_echo_n "(cached) " >&6 +else + eval "$as_ac_Header=\$ac_header_preproc" +fi +ac_res=`eval 'as_val=${'$as_ac_Header'} + $as_echo "$as_val"'` + { $as_echo "$as_me:$LINENO: result: $ac_res" >&5 +$as_echo "$ac_res" >&6; } + +fi +as_val=`eval 'as_val=${'$as_ac_Header'} + $as_echo "$as_val"'` + if test "x$as_val" = x""yes; then + cat >>confdefs.h <<_ACEOF +#define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1 +_ACEOF + +fi + +done + +{ $as_echo "$as_me:$LINENO: checking for mode_t" >&5 +$as_echo_n "checking for mode_t... " >&6; } +if test "${ac_cv_type_mode_t+set}" = set; then + $as_echo_n "(cached) " >&6 +else + ac_cv_type_mode_t=no +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +$ac_includes_default +int +main () +{ +if (sizeof (mode_t)) + return 0; + ; + return 0; +} +_ACEOF +rm -rf conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\"" +$as_echo "$ac_try_echo") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -rf conftest.er1 + cat conftest.err >&5 + $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest.$ac_objext; then + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +$ac_includes_default +int +main () +{ +if (sizeof ((mode_t))) + return 0; + ; + return 0; +} +_ACEOF +rm -rf conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\"" +$as_echo "$ac_try_echo") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -rf conftest.er1 + cat conftest.err >&5 + $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest.$ac_objext; then + : +else + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_cv_type_mode_t=yes +fi + +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +else + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + +fi + +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +{ $as_echo "$as_me:$LINENO: result: $ac_cv_type_mode_t" >&5 +$as_echo "$ac_cv_type_mode_t" >&6; } +if test "x$ac_cv_type_mode_t" = x""yes; then + : +else + +cat >>confdefs.h <<_ACEOF +#define mode_t int +_ACEOF + +fi + +{ $as_echo "$as_me:$LINENO: checking for pid_t" >&5 +$as_echo_n "checking for pid_t... " >&6; } +if test "${ac_cv_type_pid_t+set}" = set; then + $as_echo_n "(cached) " >&6 +else + ac_cv_type_pid_t=no +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +$ac_includes_default +int +main () +{ +if (sizeof (pid_t)) + return 0; + ; + return 0; +} +_ACEOF +rm -rf conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\"" +$as_echo "$ac_try_echo") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -rf conftest.er1 + cat conftest.err >&5 + $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest.$ac_objext; then + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +$ac_includes_default +int +main () +{ +if (sizeof ((pid_t))) + return 0; + ; + return 0; +} +_ACEOF +rm -rf conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\"" +$as_echo "$ac_try_echo") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -rf conftest.er1 + cat conftest.err >&5 + $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest.$ac_objext; then + : +else + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_cv_type_pid_t=yes +fi + +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +else + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + +fi + +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +{ $as_echo "$as_me:$LINENO: result: $ac_cv_type_pid_t" >&5 +$as_echo "$ac_cv_type_pid_t" >&6; } +if test "x$ac_cv_type_pid_t" = x""yes; then + : +else + +cat >>confdefs.h <<_ACEOF +#define pid_t int +_ACEOF + +fi + +{ $as_echo "$as_me:$LINENO: checking for size_t" >&5 +$as_echo_n "checking for size_t... " >&6; } +if test "${ac_cv_type_size_t+set}" = set; then + $as_echo_n "(cached) " >&6 +else + ac_cv_type_size_t=no +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +$ac_includes_default +int +main () +{ +if (sizeof (size_t)) + return 0; + ; + return 0; +} +_ACEOF +rm -rf conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\"" +$as_echo "$ac_try_echo") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -rf conftest.er1 + cat conftest.err >&5 + $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest.$ac_objext; then + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +$ac_includes_default +int +main () +{ +if (sizeof ((size_t))) + return 0; + ; + return 0; +} +_ACEOF +rm -rf conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\"" +$as_echo "$ac_try_echo") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -rf conftest.er1 + cat conftest.err >&5 + $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest.$ac_objext; then + : +else + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_cv_type_size_t=yes +fi + +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +else + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + +fi + +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +{ $as_echo "$as_me:$LINENO: result: $ac_cv_type_size_t" >&5 +$as_echo "$ac_cv_type_size_t" >&6; } +if test "x$ac_cv_type_size_t" = x""yes; then + : +else + +cat >>confdefs.h <<_ACEOF +#define size_t unsigned int +_ACEOF + +fi + +{ $as_echo "$as_me:$LINENO: checking return type of signal handlers" >&5 +$as_echo_n "checking return type of signal handlers... " >&6; } +if test "${ac_cv_type_signal+set}" = set; then + $as_echo_n "(cached) " >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include +#include + +int +main () +{ +return *(signal (0, 0)) (0) == 1; + ; + return 0; +} +_ACEOF +rm -rf conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\"" +$as_echo "$ac_try_echo") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -rf conftest.er1 + cat conftest.err >&5 + $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest.$ac_objext; then + ac_cv_type_signal=int +else + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_cv_type_signal=void +fi + +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +{ $as_echo "$as_me:$LINENO: result: $ac_cv_type_signal" >&5 +$as_echo "$ac_cv_type_signal" >&6; } + +cat >>confdefs.h <<_ACEOF +#define RETSIGTYPE $ac_cv_type_signal +_ACEOF + + +{ $as_echo "$as_me:$LINENO: checking whether time.h and sys/time.h may both be included" >&5 +$as_echo_n "checking whether time.h and sys/time.h may both be included... " >&6; } +if test "${ac_cv_header_time+set}" = set; then + $as_echo_n "(cached) " >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include +#include +#include + +int +main () +{ +if ((struct tm *) 0) +return 0; + ; + return 0; +} +_ACEOF +rm -rf conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\"" +$as_echo "$ac_try_echo") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -rf conftest.er1 + cat conftest.err >&5 + $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest.$ac_objext; then + ac_cv_header_time=yes +else + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_cv_header_time=no +fi + +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +{ $as_echo "$as_me:$LINENO: result: $ac_cv_header_time" >&5 +$as_echo "$ac_cv_header_time" >&6; } +if test $ac_cv_header_time = yes; then + +cat >>confdefs.h <<\_ACEOF +#define TIME_WITH_SYS_TIME 1 +_ACEOF + +fi + +{ $as_echo "$as_me:$LINENO: checking for sys/wait.h that is POSIX.1 compatible" >&5 +$as_echo_n "checking for sys/wait.h that is POSIX.1 compatible... " >&6; } +if test "${ac_cv_header_sys_wait_h+set}" = set; then + $as_echo_n "(cached) " >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include +#include +#ifndef WEXITSTATUS +# define WEXITSTATUS(stat_val) ((unsigned int) (stat_val) >> 8) +#endif +#ifndef WIFEXITED +# define WIFEXITED(stat_val) (((stat_val) & 255) == 0) +#endif + +int +main () +{ + int s; + wait (&s); + s = WIFEXITED (s) ? WEXITSTATUS (s) : 1; + ; + return 0; +} +_ACEOF +rm -rf conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\"" +$as_echo "$ac_try_echo") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -rf conftest.er1 + cat conftest.err >&5 + $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest.$ac_objext; then + ac_cv_header_sys_wait_h=yes +else + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_cv_header_sys_wait_h=no +fi + +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +{ $as_echo "$as_me:$LINENO: result: $ac_cv_header_sys_wait_h" >&5 +$as_echo "$ac_cv_header_sys_wait_h" >&6; } +if test $ac_cv_header_sys_wait_h = yes; then + +cat >>confdefs.h <<\_ACEOF +#define HAVE_SYS_WAIT_H 1 +_ACEOF + +fi + + + + + + +ac_header_dirent=no +for ac_hdr in dirent.h sys/ndir.h sys/dir.h ndir.h; do + as_ac_Header=`$as_echo "ac_cv_header_dirent_$ac_hdr" | $as_tr_sh` +{ $as_echo "$as_me:$LINENO: checking for $ac_hdr that defines DIR" >&5 +$as_echo_n "checking for $ac_hdr that defines DIR... " >&6; } +if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then + $as_echo_n "(cached) " >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include +#include <$ac_hdr> + +int +main () +{ +if ((DIR *) 0) +return 0; + ; + return 0; +} +_ACEOF +rm -rf conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\"" +$as_echo "$ac_try_echo") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -rf conftest.er1 + cat conftest.err >&5 + $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest.$ac_objext; then + eval "$as_ac_Header=yes" +else + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + eval "$as_ac_Header=no" +fi + +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +ac_res=`eval 'as_val=${'$as_ac_Header'} + $as_echo "$as_val"'` + { $as_echo "$as_me:$LINENO: result: $ac_res" >&5 +$as_echo "$ac_res" >&6; } +as_val=`eval 'as_val=${'$as_ac_Header'} + $as_echo "$as_val"'` + if test "x$as_val" = x""yes; then + cat >>confdefs.h <<_ACEOF +#define `$as_echo "HAVE_$ac_hdr" | $as_tr_cpp` 1 +_ACEOF + +ac_header_dirent=$ac_hdr; break +fi + +done +# Two versions of opendir et al. are in -ldir and -lx on SCO Xenix. +if test $ac_header_dirent = dirent.h; then + { $as_echo "$as_me:$LINENO: checking for library containing opendir" >&5 +$as_echo_n "checking for library containing opendir... " >&6; } +if test "${ac_cv_search_opendir+set}" = set; then + $as_echo_n "(cached) " >&6 +else + ac_func_search_save_LIBS=$LIBS +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char opendir (); +int +main () +{ +return opendir (); + ; + return 0; +} +_ACEOF +for ac_lib in '' dir; do + if test -z "$ac_lib"; then + ac_res="none required" + else + ac_res=-l$ac_lib + LIBS="-l$ac_lib $ac_func_search_save_LIBS" + fi + rm -rf conftest.$ac_objext conftest$ac_exeext +if { (ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\"" +$as_echo "$ac_try_echo") >&5 + (eval "$ac_link") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -rf conftest.er1 + cat conftest.err >&5 + $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest$ac_exeext && { + test "$cross_compiling" = yes || + $as_test_x conftest$ac_exeext + }; then + ac_cv_search_opendir=$ac_res +else + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + +fi + +rm -rf conftest.dSYM +rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ + conftest$ac_exeext + if test "${ac_cv_search_opendir+set}" = set; then + break +fi +done +if test "${ac_cv_search_opendir+set}" = set; then + : +else + ac_cv_search_opendir=no +fi +rm conftest.$ac_ext +LIBS=$ac_func_search_save_LIBS +fi +{ $as_echo "$as_me:$LINENO: result: $ac_cv_search_opendir" >&5 +$as_echo "$ac_cv_search_opendir" >&6; } +ac_res=$ac_cv_search_opendir +if test "$ac_res" != no; then + test "$ac_res" = "none required" || LIBS="$ac_res $LIBS" + +fi + +else + { $as_echo "$as_me:$LINENO: checking for library containing opendir" >&5 +$as_echo_n "checking for library containing opendir... " >&6; } +if test "${ac_cv_search_opendir+set}" = set; then + $as_echo_n "(cached) " >&6 +else + ac_func_search_save_LIBS=$LIBS +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char opendir (); +int +main () +{ +return opendir (); + ; + return 0; +} +_ACEOF +for ac_lib in '' x; do + if test -z "$ac_lib"; then + ac_res="none required" + else + ac_res=-l$ac_lib + LIBS="-l$ac_lib $ac_func_search_save_LIBS" + fi + rm -rf conftest.$ac_objext conftest$ac_exeext +if { (ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\"" +$as_echo "$ac_try_echo") >&5 + (eval "$ac_link") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -rf conftest.er1 + cat conftest.err >&5 + $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest$ac_exeext && { + test "$cross_compiling" = yes || + $as_test_x conftest$ac_exeext + }; then + ac_cv_search_opendir=$ac_res +else + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + +fi + +rm -rf conftest.dSYM +rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ + conftest$ac_exeext + if test "${ac_cv_search_opendir+set}" = set; then + break +fi +done +if test "${ac_cv_search_opendir+set}" = set; then + : +else + ac_cv_search_opendir=no +fi +rm conftest.$ac_ext +LIBS=$ac_func_search_save_LIBS +fi +{ $as_echo "$as_me:$LINENO: result: $ac_cv_search_opendir" >&5 +$as_echo "$ac_cv_search_opendir" >&6; } +ac_res=$ac_cv_search_opendir +if test "$ac_res" != no; then + test "$ac_res" = "none required" || LIBS="$ac_res $LIBS" + +fi + +fi + +{ $as_echo "$as_me:$LINENO: checking how to call gettimeofday" >&5 +$as_echo_n "checking how to call gettimeofday... " >&6; } + if test "${ac_cv_gettimeofday_args+set}" = set; then + $as_echo_n "(cached) " >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include + #include +int +main () +{ +struct timeval tv; struct timezone tzp; + gettimeofday(&tv, &tzp); + ; + return 0; +} +_ACEOF +rm -rf conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\"" +$as_echo "$ac_try_echo") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -rf conftest.er1 + cat conftest.err >&5 + $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest.$ac_objext; then + ac_gettimeofday_args=2 +else + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include + #include +int +main () +{ +struct timeval tv; gettimeofday(&tv); + ; + return 0; +} +_ACEOF +rm -rf conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\"" +$as_echo "$ac_try_echo") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -rf conftest.er1 + cat conftest.err >&5 + $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest.$ac_objext; then + ac_gettimeofday_args=1 +else + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_gettimeofday_args=0 +fi + +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi + +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + ac_cv_gettimeofday_args=$ac_gettimeofday_args +fi + + ac_gettimeofday_args=$ac_cv_gettimeofday_args + if test "$ac_gettimeofday_args" = 1 ; then + cat >>confdefs.h <<\_ACEOF +#define HAVE_GETTIMEOFDAY 1 +_ACEOF + + { $as_echo "$as_me:$LINENO: result: one argument" >&5 +$as_echo "one argument" >&6; } + elif test "$ac_gettimeofday_args" = 2 ; then + cat >>confdefs.h <<\_ACEOF +#define HAVE_GETTIMEOFDAY 1 +_ACEOF + + cat >>confdefs.h <<\_ACEOF +#define GETTIMEOFDAY_TWO_ARGS 1 +_ACEOF + + { $as_echo "$as_me:$LINENO: result: two arguments" >&5 +$as_echo "two arguments" >&6; } + else + { $as_echo "$as_me:$LINENO: result: unknown" >&5 +$as_echo "unknown" >&6; } + fi + + + + + + + + + + +for ac_func in select fcntl uname nice setpriority getcwd getwd putenv sbrk +do +as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh` +{ $as_echo "$as_me:$LINENO: checking for $ac_func" >&5 +$as_echo_n "checking for $ac_func... " >&6; } +if { as_var=$as_ac_var; eval "test \"\${$as_var+set}\" = set"; }; then + $as_echo_n "(cached) " >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +/* Define $ac_func to an innocuous variant, in case declares $ac_func. + For example, HP-UX 11i declares gettimeofday. */ +#define $ac_func innocuous_$ac_func + +/* System header to define __stub macros and hopefully few prototypes, + which can conflict with char $ac_func (); below. + Prefer to if __STDC__ is defined, since + exists even on freestanding compilers. */ + +#ifdef __STDC__ +# include +#else +# include +#endif + +#undef $ac_func + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char $ac_func (); +/* The GNU C library defines this for functions which it implements + to always fail with ENOSYS. Some functions are actually named + something starting with __ and the normal name is an alias. */ +#if defined __stub_$ac_func || defined __stub___$ac_func +choke me +#endif + +int +main () +{ +return $ac_func (); + ; + return 0; +} +_ACEOF +rm -rf conftest.$ac_objext conftest$ac_exeext +if { (ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\"" +$as_echo "$ac_try_echo") >&5 + (eval "$ac_link") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -rf conftest.er1 + cat conftest.err >&5 + $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest$ac_exeext && { + test "$cross_compiling" = yes || + $as_test_x conftest$ac_exeext + }; then + eval "$as_ac_var=yes" +else + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + eval "$as_ac_var=no" +fi + +rm -rf conftest.dSYM +rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ + conftest$ac_exeext conftest.$ac_ext +fi +ac_res=`eval 'as_val=${'$as_ac_var'} + $as_echo "$as_val"'` + { $as_echo "$as_me:$LINENO: result: $ac_res" >&5 +$as_echo "$ac_res" >&6; } +as_val=`eval 'as_val=${'$as_ac_var'} + $as_echo "$as_val"'` + if test "x$as_val" = x""yes; then + cat >>confdefs.h <<_ACEOF +#define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1 +_ACEOF + +fi +done + + + + + +for ac_func in sigaction syslog realpath setrlimit +do +as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh` +{ $as_echo "$as_me:$LINENO: checking for $ac_func" >&5 +$as_echo_n "checking for $ac_func... " >&6; } +if { as_var=$as_ac_var; eval "test \"\${$as_var+set}\" = set"; }; then + $as_echo_n "(cached) " >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +/* Define $ac_func to an innocuous variant, in case declares $ac_func. + For example, HP-UX 11i declares gettimeofday. */ +#define $ac_func innocuous_$ac_func + +/* System header to define __stub macros and hopefully few prototypes, + which can conflict with char $ac_func (); below. + Prefer to if __STDC__ is defined, since + exists even on freestanding compilers. */ + +#ifdef __STDC__ +# include +#else +# include +#endif + +#undef $ac_func + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char $ac_func (); +/* The GNU C library defines this for functions which it implements + to always fail with ENOSYS. Some functions are actually named + something starting with __ and the normal name is an alias. */ +#if defined __stub_$ac_func || defined __stub___$ac_func +choke me +#endif + +int +main () +{ +return $ac_func (); + ; + return 0; +} +_ACEOF +rm -rf conftest.$ac_objext conftest$ac_exeext +if { (ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\"" +$as_echo "$ac_try_echo") >&5 + (eval "$ac_link") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -rf conftest.er1 + cat conftest.err >&5 + $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest$ac_exeext && { + test "$cross_compiling" = yes || + $as_test_x conftest$ac_exeext + }; then + eval "$as_ac_var=yes" +else + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + eval "$as_ac_var=no" +fi + +rm -rf conftest.dSYM +rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ + conftest$ac_exeext conftest.$ac_ext +fi +ac_res=`eval 'as_val=${'$as_ac_var'} + $as_echo "$as_val"'` + { $as_echo "$as_me:$LINENO: result: $ac_res" >&5 +$as_echo "$ac_res" >&6; } +as_val=`eval 'as_val=${'$as_ac_var'} + $as_echo "$as_val"'` + if test "x$as_val" = x""yes; then + cat >>confdefs.h <<_ACEOF +#define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1 +_ACEOF + +fi +done + + +for ac_func in setlocale +do +as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh` +{ $as_echo "$as_me:$LINENO: checking for $ac_func" >&5 +$as_echo_n "checking for $ac_func... " >&6; } +if { as_var=$as_ac_var; eval "test \"\${$as_var+set}\" = set"; }; then + $as_echo_n "(cached) " >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +/* Define $ac_func to an innocuous variant, in case declares $ac_func. + For example, HP-UX 11i declares gettimeofday. */ +#define $ac_func innocuous_$ac_func + +/* System header to define __stub macros and hopefully few prototypes, + which can conflict with char $ac_func (); below. + Prefer to if __STDC__ is defined, since + exists even on freestanding compilers. */ + +#ifdef __STDC__ +# include +#else +# include +#endif + +#undef $ac_func + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char $ac_func (); +/* The GNU C library defines this for functions which it implements + to always fail with ENOSYS. Some functions are actually named + something starting with __ and the normal name is an alias. */ +#if defined __stub_$ac_func || defined __stub___$ac_func +choke me +#endif + +int +main () +{ +return $ac_func (); + ; + return 0; +} +_ACEOF +rm -rf conftest.$ac_objext conftest$ac_exeext +if { (ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\"" +$as_echo "$ac_try_echo") >&5 + (eval "$ac_link") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -rf conftest.er1 + cat conftest.err >&5 + $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest$ac_exeext && { + test "$cross_compiling" = yes || + $as_test_x conftest$ac_exeext + }; then + eval "$as_ac_var=yes" +else + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + eval "$as_ac_var=no" +fi + +rm -rf conftest.dSYM +rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ + conftest$ac_exeext conftest.$ac_ext +fi +ac_res=`eval 'as_val=${'$as_ac_var'} + $as_echo "$as_val"'` + { $as_echo "$as_me:$LINENO: result: $ac_res" >&5 +$as_echo "$ac_res" >&6; } +as_val=`eval 'as_val=${'$as_ac_var'} + $as_echo "$as_val"'` + if test "x$as_val" = x""yes; then + cat >>confdefs.h <<_ACEOF +#define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1 +_ACEOF + +fi +done + +{ $as_echo "$as_me:$LINENO: checking for struct icmp" >&5 +$as_echo_n "checking for struct icmp... " >&6; } +if test "${ac_cv_have_icmp+set}" = set; then + $as_echo_n "(cached) " >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include +int +main () +{ +struct icmp i; + struct sockaddr s; + struct sockaddr_in si; + struct ip ip; + i.icmp_type = ICMP_ECHO; + i.icmp_code = 0; + i.icmp_cksum = 0; + i.icmp_id = 0; + i.icmp_seq = 0; + si.sin_family = AF_INET; + #if defined(__DECC) || defined(_IP_VHL) + ip.ip_vhl = 0; + #else + ip.ip_hl = 0; + #endif + + ; + return 0; +} +_ACEOF +rm -rf conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\"" +$as_echo "$ac_try_echo") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -rf conftest.er1 + cat conftest.err >&5 + $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest.$ac_objext; then + ac_cv_have_icmp=yes +else + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_cv_have_icmp=no +fi + +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +{ $as_echo "$as_me:$LINENO: result: $ac_cv_have_icmp" >&5 +$as_echo "$ac_cv_have_icmp" >&6; } + if test "$ac_cv_have_icmp" = yes ; then + cat >>confdefs.h <<\_ACEOF +#define HAVE_ICMP 1 +_ACEOF + + fi +{ $as_echo "$as_me:$LINENO: checking for struct icmphdr" >&5 +$as_echo_n "checking for struct icmphdr... " >&6; } +if test "${ac_cv_have_icmphdr+set}" = set; then + $as_echo_n "(cached) " >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include +int +main () +{ +struct icmphdr i; + struct sockaddr s; + struct sockaddr_in si; + struct ip ip; + i.type = ICMP_ECHO; + i.code = 0; + i.checksum = 0; + i.un.echo.id = 0; + i.un.echo.sequence = 0; + si.sin_family = AF_INET; + ip.ip_hl = 0; + ; + return 0; +} +_ACEOF +rm -rf conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\"" +$as_echo "$ac_try_echo") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -rf conftest.er1 + cat conftest.err >&5 + $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest.$ac_objext; then + ac_cv_have_icmphdr=yes +else + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_cv_have_icmphdr=no +fi + +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +{ $as_echo "$as_me:$LINENO: result: $ac_cv_have_icmphdr" >&5 +$as_echo "$ac_cv_have_icmphdr" >&6; } + if test "$ac_cv_have_icmphdr" = yes ; then + cat >>confdefs.h <<\_ACEOF +#define HAVE_ICMPHDR 1 +_ACEOF + + fi +{ $as_echo "$as_me:$LINENO: checking for getifaddrs" >&5 +$as_echo_n "checking for getifaddrs... " >&6; } +if test "${ac_cv_have_getifaddrs+set}" = set; then + $as_echo_n "(cached) " >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include + #include + #include + #include +int +main () +{ +struct ifaddrs *ifa; + getifaddrs (&ifa); + ifa->ifa_next = 0; + ifa->ifa_addr->sa_family = 0; + ; + return 0; +} +_ACEOF +rm -rf conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\"" +$as_echo "$ac_try_echo") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -rf conftest.er1 + cat conftest.err >&5 + $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest.$ac_objext; then + ac_cv_have_getifaddrs=yes +else + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_cv_have_getifaddrs=no +fi + +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +{ $as_echo "$as_me:$LINENO: result: $ac_cv_have_getifaddrs" >&5 +$as_echo "$ac_cv_have_getifaddrs" >&6; } + if test "$ac_cv_have_getifaddrs" = yes ; then + cat >>confdefs.h <<\_ACEOF +#define HAVE_GETIFADDRS 1 +_ACEOF + + fi + + +for ac_header in crypt.h sys/select.h +do +as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh` +if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then + { $as_echo "$as_me:$LINENO: checking for $ac_header" >&5 +$as_echo_n "checking for $ac_header... " >&6; } +if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then + $as_echo_n "(cached) " >&6 +fi +ac_res=`eval 'as_val=${'$as_ac_Header'} + $as_echo "$as_val"'` + { $as_echo "$as_me:$LINENO: result: $ac_res" >&5 +$as_echo "$ac_res" >&6; } +else + # Is the header compilable? +{ $as_echo "$as_me:$LINENO: checking $ac_header usability" >&5 +$as_echo_n "checking $ac_header usability... " >&6; } +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +$ac_includes_default +#include <$ac_header> +_ACEOF +rm -rf conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\"" +$as_echo "$ac_try_echo") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -rf conftest.er1 + cat conftest.err >&5 + $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest.$ac_objext; then + ac_header_compiler=yes +else + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_header_compiler=no +fi + +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +{ $as_echo "$as_me:$LINENO: result: $ac_header_compiler" >&5 +$as_echo "$ac_header_compiler" >&6; } + +# Is the header present? +{ $as_echo "$as_me:$LINENO: checking $ac_header presence" >&5 +$as_echo_n "checking $ac_header presence... " >&6; } +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include <$ac_header> +_ACEOF +if { (ac_try="$ac_cpp conftest.$ac_ext" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\"" +$as_echo "$ac_try_echo") >&5 + (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -rf conftest.er1 + cat conftest.err >&5 + $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } >/dev/null && { + test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" || + test ! -s conftest.err + }; then + ac_header_preproc=yes +else + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_header_preproc=no +fi + +rm -rf conftest.err conftest.$ac_ext +{ $as_echo "$as_me:$LINENO: result: $ac_header_preproc" >&5 +$as_echo "$ac_header_preproc" >&6; } + +# So? What about this header? +case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in + yes:no: ) + { $as_echo "$as_me:$LINENO: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&5 +$as_echo "$as_me: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&2;} + { $as_echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the compiler's result" >&5 +$as_echo "$as_me: WARNING: $ac_header: proceeding with the compiler's result" >&2;} + ac_header_preproc=yes + ;; + no:yes:* ) + { $as_echo "$as_me:$LINENO: WARNING: $ac_header: present but cannot be compiled" >&5 +$as_echo "$as_me: WARNING: $ac_header: present but cannot be compiled" >&2;} + { $as_echo "$as_me:$LINENO: WARNING: $ac_header: check for missing prerequisite headers?" >&5 +$as_echo "$as_me: WARNING: $ac_header: check for missing prerequisite headers?" >&2;} + { $as_echo "$as_me:$LINENO: WARNING: $ac_header: see the Autoconf documentation" >&5 +$as_echo "$as_me: WARNING: $ac_header: see the Autoconf documentation" >&2;} + { $as_echo "$as_me:$LINENO: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&5 +$as_echo "$as_me: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&2;} + { $as_echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the preprocessor's result" >&5 +$as_echo "$as_me: WARNING: $ac_header: proceeding with the preprocessor's result" >&2;} + { $as_echo "$as_me:$LINENO: WARNING: $ac_header: in the future, the compiler will take precedence" >&5 +$as_echo "$as_me: WARNING: $ac_header: in the future, the compiler will take precedence" >&2;} + + ;; +esac +{ $as_echo "$as_me:$LINENO: checking for $ac_header" >&5 +$as_echo_n "checking for $ac_header... " >&6; } +if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then + $as_echo_n "(cached) " >&6 +else + eval "$as_ac_Header=\$ac_header_preproc" +fi +ac_res=`eval 'as_val=${'$as_ac_Header'} + $as_echo "$as_val"'` + { $as_echo "$as_me:$LINENO: result: $ac_res" >&5 +$as_echo "$ac_res" >&6; } + +fi +as_val=`eval 'as_val=${'$as_ac_Header'} + $as_echo "$as_val"'` + if test "x$as_val" = x""yes; then + cat >>confdefs.h <<_ACEOF +#define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1 +_ACEOF + +fi + +done + +for ac_prog in perl5 perl +do + # Extract the first word of "$ac_prog", so it can be a program name with args. +set dummy $ac_prog; ac_word=$2 +{ $as_echo "$as_me:$LINENO: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if test "${ac_cv_path_PERL+set}" = set; then + $as_echo_n "(cached) " >&6 +else + case $PERL in + [\\/]* | ?:[\\/]*) + ac_cv_path_PERL="$PERL" # Let the user override the test with a path. + ;; + *) + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_path_PERL="$as_dir/$ac_word$ac_exec_ext" + $as_echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done +IFS=$as_save_IFS + + ;; +esac +fi +PERL=$ac_cv_path_PERL +if test -n "$PERL"; then + { $as_echo "$as_me:$LINENO: result: $PERL" >&5 +$as_echo "$PERL" >&6; } +else + { $as_echo "$as_me:$LINENO: result: no" >&5 +$as_echo "no" >&6; } +fi + + + test -n "$PERL" && break +done + + if test -z "$PERL" ; then + PERL_VERSION=0 + else + { $as_echo "$as_me:$LINENO: checking perl version" >&5 +$as_echo_n "checking perl version... " >&6; } +if test "${ac_cv_perl_version+set}" = set; then + $as_echo_n "(cached) " >&6 +else + ac_cv_perl_version=`$PERL -e "$perl_version_cmd"` +fi +{ $as_echo "$as_me:$LINENO: result: $ac_cv_perl_version" >&5 +$as_echo "$ac_cv_perl_version" >&6; } + PERL_VERSION=$ac_cv_perl_version + fi + + +if test -z "$PERL" ; then + # don't let it be blank... + PERL=/usr/bin/perl +fi + +{ $as_echo "$as_me:$LINENO: checking for X" >&5 +$as_echo_n "checking for X... " >&6; } + + +# Check whether --with-x was given. +if test "${with_x+set}" = set; then + withval=$with_x; +fi + +# $have_x is `yes', `no', `disabled', or empty when we do not yet know. +if test "x$with_x" = xno; then + # The user explicitly disabled X. + have_x=disabled +else + case $x_includes,$x_libraries in #( + *\'*) { { $as_echo "$as_me:$LINENO: error: cannot use X directory names containing '" >&5 +$as_echo "$as_me: error: cannot use X directory names containing '" >&2;} + { (exit 1); exit 1; }; };; #( + *,NONE | NONE,*) if test "${ac_cv_have_x+set}" = set; then + $as_echo_n "(cached) " >&6 +else + # One or both of the vars are not set, and there is no cached value. +ac_x_includes=no ac_x_libraries=no +rm -f -r conftest.dir +if mkdir conftest.dir; then + cd conftest.dir + cat >Imakefile <<'_ACEOF' +incroot: + @echo incroot='${INCROOT}' +usrlibdir: + @echo usrlibdir='${USRLIBDIR}' +libdir: + @echo libdir='${LIBDIR}' +_ACEOF + if (export CC; ${XMKMF-xmkmf}) >/dev/null 2>/dev/null && test -f Makefile; then + # GNU make sometimes prints "make[1]: Entering...", which would confuse us. + for ac_var in incroot usrlibdir libdir; do + eval "ac_im_$ac_var=\`\${MAKE-make} $ac_var 2>/dev/null | sed -n 's/^$ac_var=//p'\`" + done + # Open Windows xmkmf reportedly sets LIBDIR instead of USRLIBDIR. + for ac_extension in a so sl dylib la dll; do + if test ! -f "$ac_im_usrlibdir/libX11.$ac_extension" && + test -f "$ac_im_libdir/libX11.$ac_extension"; then + ac_im_usrlibdir=$ac_im_libdir; break + fi + done + # Screen out bogus values from the imake configuration. They are + # bogus both because they are the default anyway, and because + # using them would break gcc on systems where it needs fixed includes. + case $ac_im_incroot in + /usr/include) ac_x_includes= ;; + *) test -f "$ac_im_incroot/X11/Xos.h" && ac_x_includes=$ac_im_incroot;; + esac + case $ac_im_usrlibdir in + /usr/lib | /usr/lib64 | /lib | /lib64) ;; + *) test -d "$ac_im_usrlibdir" && ac_x_libraries=$ac_im_usrlibdir ;; + esac + fi + cd .. + rm -f -r conftest.dir +fi + +# Standard set of common directories for X headers. +# Check X11 before X11Rn because it is often a symlink to the current release. +ac_x_header_dirs=' +/usr/X11/include +/usr/X11R6/include +/usr/X11R5/include +/usr/X11R4/include + +/usr/include/X11 +/usr/include/X11R6 +/usr/include/X11R5 +/usr/include/X11R4 + +/usr/local/X11/include +/usr/local/X11R6/include +/usr/local/X11R5/include +/usr/local/X11R4/include + +/usr/local/include/X11 +/usr/local/include/X11R6 +/usr/local/include/X11R5 +/usr/local/include/X11R4 + +/usr/X386/include +/usr/x386/include +/usr/XFree86/include/X11 + +/usr/include +/usr/local/include +/usr/unsupported/include +/usr/athena/include +/usr/local/x11r5/include +/usr/lpp/Xamples/include + +/usr/openwin/include +/usr/openwin/share/include' + +if test "$ac_x_includes" = no; then + # Guess where to find include files, by looking for Xlib.h. + # First, try using that file with no special directory specified. + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include +_ACEOF +if { (ac_try="$ac_cpp conftest.$ac_ext" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\"" +$as_echo "$ac_try_echo") >&5 + (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -rf conftest.er1 + cat conftest.err >&5 + $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } >/dev/null && { + test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" || + test ! -s conftest.err + }; then + # We can compile using X headers with no special include directory. +ac_x_includes= +else + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + for ac_dir in $ac_x_header_dirs; do + if test -r "$ac_dir/X11/Xlib.h"; then + ac_x_includes=$ac_dir + break + fi +done +fi + +rm -rf conftest.err conftest.$ac_ext +fi # $ac_x_includes = no + +if test "$ac_x_libraries" = no; then + # Check for the libraries. + # See if we find them without any special options. + # Don't add to $LIBS permanently. + ac_save_LIBS=$LIBS + LIBS="-lX11 $LIBS" + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include +int +main () +{ +XrmInitialize () + ; + return 0; +} +_ACEOF +rm -rf conftest.$ac_objext conftest$ac_exeext +if { (ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\"" +$as_echo "$ac_try_echo") >&5 + (eval "$ac_link") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -rf conftest.er1 + cat conftest.err >&5 + $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest$ac_exeext && { + test "$cross_compiling" = yes || + $as_test_x conftest$ac_exeext + }; then + LIBS=$ac_save_LIBS +# We can link X programs with no special library path. +ac_x_libraries= +else + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + LIBS=$ac_save_LIBS +for ac_dir in `$as_echo "$ac_x_includes $ac_x_header_dirs" | sed s/include/lib/g` +do + # Don't even attempt the hair of trying to link an X program! + for ac_extension in a so sl dylib la dll; do + if test -r "$ac_dir/libX11.$ac_extension"; then + ac_x_libraries=$ac_dir + break 2 + fi + done +done +fi + +rm -rf conftest.dSYM +rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ + conftest$ac_exeext conftest.$ac_ext +fi # $ac_x_libraries = no + +case $ac_x_includes,$ac_x_libraries in #( + no,* | *,no | *\'*) + # Didn't find X, or a directory has "'" in its name. + ac_cv_have_x="have_x=no";; #( + *) + # Record where we found X for the cache. + ac_cv_have_x="have_x=yes\ + ac_x_includes='$ac_x_includes'\ + ac_x_libraries='$ac_x_libraries'" +esac +fi +;; #( + *) have_x=yes;; + esac + eval "$ac_cv_have_x" +fi # $with_x != no + +if test "$have_x" != yes; then + { $as_echo "$as_me:$LINENO: result: $have_x" >&5 +$as_echo "$have_x" >&6; } + no_x=yes +else + # If each of the values was on the command line, it overrides each guess. + test "x$x_includes" = xNONE && x_includes=$ac_x_includes + test "x$x_libraries" = xNONE && x_libraries=$ac_x_libraries + # Update the cache value to reflect the command line values. + ac_cv_have_x="have_x=yes\ + ac_x_includes='$x_includes'\ + ac_x_libraries='$x_libraries'" + { $as_echo "$as_me:$LINENO: result: libraries $x_libraries, headers $x_includes" >&5 +$as_echo "libraries $x_libraries, headers $x_includes" >&6; } +fi + +if test "$no_x" = yes; then + # Not all programs may use this symbol, but it does not hurt to define it. + +cat >>confdefs.h <<\_ACEOF +#define X_DISPLAY_MISSING 1 +_ACEOF + + X_CFLAGS= X_PRE_LIBS= X_LIBS= X_EXTRA_LIBS= +else + if test -n "$x_includes"; then + X_CFLAGS="$X_CFLAGS -I$x_includes" + fi + + # It would also be nice to do this for all -L options, not just this one. + if test -n "$x_libraries"; then + X_LIBS="$X_LIBS -L$x_libraries" + # For Solaris; some versions of Sun CC require a space after -R and + # others require no space. Words are not sufficient . . . . + { $as_echo "$as_me:$LINENO: checking whether -R must be followed by a space" >&5 +$as_echo_n "checking whether -R must be followed by a space... " >&6; } + ac_xsave_LIBS=$LIBS; LIBS="$LIBS -R$x_libraries" + ac_xsave_c_werror_flag=$ac_c_werror_flag + ac_c_werror_flag=yes + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +rm -rf conftest.$ac_objext conftest$ac_exeext +if { (ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\"" +$as_echo "$ac_try_echo") >&5 + (eval "$ac_link") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -rf conftest.er1 + cat conftest.err >&5 + $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest$ac_exeext && { + test "$cross_compiling" = yes || + $as_test_x conftest$ac_exeext + }; then + { $as_echo "$as_me:$LINENO: result: no" >&5 +$as_echo "no" >&6; } + X_LIBS="$X_LIBS -R$x_libraries" +else + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + LIBS="$ac_xsave_LIBS -R $x_libraries" + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +rm -rf conftest.$ac_objext conftest$ac_exeext +if { (ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\"" +$as_echo "$ac_try_echo") >&5 + (eval "$ac_link") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -rf conftest.er1 + cat conftest.err >&5 + $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest$ac_exeext && { + test "$cross_compiling" = yes || + $as_test_x conftest$ac_exeext + }; then + { $as_echo "$as_me:$LINENO: result: yes" >&5 +$as_echo "yes" >&6; } + X_LIBS="$X_LIBS -R $x_libraries" +else + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + { $as_echo "$as_me:$LINENO: result: neither works" >&5 +$as_echo "neither works" >&6; } +fi + +rm -rf conftest.dSYM +rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ + conftest$ac_exeext conftest.$ac_ext +fi + +rm -rf conftest.dSYM +rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ + conftest$ac_exeext conftest.$ac_ext + ac_c_werror_flag=$ac_xsave_c_werror_flag + LIBS=$ac_xsave_LIBS + fi + + # Check for system-dependent libraries X programs must link with. + # Do this before checking for the system-independent R6 libraries + # (-lICE), since we may need -lsocket or whatever for X linking. + + if test "$ISC" = yes; then + X_EXTRA_LIBS="$X_EXTRA_LIBS -lnsl_s -linet" + else + # Martyn Johnson says this is needed for Ultrix, if the X + # libraries were built with DECnet support. And Karl Berry says + # the Alpha needs dnet_stub (dnet does not exist). + ac_xsave_LIBS="$LIBS"; LIBS="$LIBS $X_LIBS -lX11" + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char XOpenDisplay (); +int +main () +{ +return XOpenDisplay (); + ; + return 0; +} +_ACEOF +rm -rf conftest.$ac_objext conftest$ac_exeext +if { (ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\"" +$as_echo "$ac_try_echo") >&5 + (eval "$ac_link") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -rf conftest.er1 + cat conftest.err >&5 + $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest$ac_exeext && { + test "$cross_compiling" = yes || + $as_test_x conftest$ac_exeext + }; then + : +else + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + { $as_echo "$as_me:$LINENO: checking for dnet_ntoa in -ldnet" >&5 +$as_echo_n "checking for dnet_ntoa in -ldnet... " >&6; } +if test "${ac_cv_lib_dnet_dnet_ntoa+set}" = set; then + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-ldnet $LIBS" +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char dnet_ntoa (); +int +main () +{ +return dnet_ntoa (); + ; + return 0; +} +_ACEOF +rm -rf conftest.$ac_objext conftest$ac_exeext +if { (ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\"" +$as_echo "$ac_try_echo") >&5 + (eval "$ac_link") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -rf conftest.er1 + cat conftest.err >&5 + $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest$ac_exeext && { + test "$cross_compiling" = yes || + $as_test_x conftest$ac_exeext + }; then + ac_cv_lib_dnet_dnet_ntoa=yes +else + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_cv_lib_dnet_dnet_ntoa=no +fi + +rm -rf conftest.dSYM +rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:$LINENO: result: $ac_cv_lib_dnet_dnet_ntoa" >&5 +$as_echo "$ac_cv_lib_dnet_dnet_ntoa" >&6; } +if test "x$ac_cv_lib_dnet_dnet_ntoa" = x""yes; then + X_EXTRA_LIBS="$X_EXTRA_LIBS -ldnet" +fi + + if test $ac_cv_lib_dnet_dnet_ntoa = no; then + { $as_echo "$as_me:$LINENO: checking for dnet_ntoa in -ldnet_stub" >&5 +$as_echo_n "checking for dnet_ntoa in -ldnet_stub... " >&6; } +if test "${ac_cv_lib_dnet_stub_dnet_ntoa+set}" = set; then + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-ldnet_stub $LIBS" +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char dnet_ntoa (); +int +main () +{ +return dnet_ntoa (); + ; + return 0; +} +_ACEOF +rm -rf conftest.$ac_objext conftest$ac_exeext +if { (ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\"" +$as_echo "$ac_try_echo") >&5 + (eval "$ac_link") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -rf conftest.er1 + cat conftest.err >&5 + $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest$ac_exeext && { + test "$cross_compiling" = yes || + $as_test_x conftest$ac_exeext + }; then + ac_cv_lib_dnet_stub_dnet_ntoa=yes +else + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_cv_lib_dnet_stub_dnet_ntoa=no +fi + +rm -rf conftest.dSYM +rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:$LINENO: result: $ac_cv_lib_dnet_stub_dnet_ntoa" >&5 +$as_echo "$ac_cv_lib_dnet_stub_dnet_ntoa" >&6; } +if test "x$ac_cv_lib_dnet_stub_dnet_ntoa" = x""yes; then + X_EXTRA_LIBS="$X_EXTRA_LIBS -ldnet_stub" +fi + + fi +fi + +rm -rf conftest.dSYM +rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ + conftest$ac_exeext conftest.$ac_ext + LIBS="$ac_xsave_LIBS" + + # msh@cis.ufl.edu says -lnsl (and -lsocket) are needed for his 386/AT, + # to get the SysV transport functions. + # Chad R. Larson says the Pyramis MIS-ES running DC/OSx (SVR4) + # needs -lnsl. + # The nsl library prevents programs from opening the X display + # on Irix 5.2, according to T.E. Dickey. + # The functions gethostbyname, getservbyname, and inet_addr are + # in -lbsd on LynxOS 3.0.1/i386, according to Lars Hecking. + { $as_echo "$as_me:$LINENO: checking for gethostbyname" >&5 +$as_echo_n "checking for gethostbyname... " >&6; } +if test "${ac_cv_func_gethostbyname+set}" = set; then + $as_echo_n "(cached) " >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +/* Define gethostbyname to an innocuous variant, in case declares gethostbyname. + For example, HP-UX 11i declares gettimeofday. */ +#define gethostbyname innocuous_gethostbyname + +/* System header to define __stub macros and hopefully few prototypes, + which can conflict with char gethostbyname (); below. + Prefer to if __STDC__ is defined, since + exists even on freestanding compilers. */ + +#ifdef __STDC__ +# include +#else +# include +#endif + +#undef gethostbyname + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char gethostbyname (); +/* The GNU C library defines this for functions which it implements + to always fail with ENOSYS. Some functions are actually named + something starting with __ and the normal name is an alias. */ +#if defined __stub_gethostbyname || defined __stub___gethostbyname +choke me +#endif + +int +main () +{ +return gethostbyname (); + ; + return 0; +} +_ACEOF +rm -rf conftest.$ac_objext conftest$ac_exeext +if { (ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\"" +$as_echo "$ac_try_echo") >&5 + (eval "$ac_link") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -rf conftest.er1 + cat conftest.err >&5 + $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest$ac_exeext && { + test "$cross_compiling" = yes || + $as_test_x conftest$ac_exeext + }; then + ac_cv_func_gethostbyname=yes +else + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_cv_func_gethostbyname=no +fi + +rm -rf conftest.dSYM +rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ + conftest$ac_exeext conftest.$ac_ext +fi +{ $as_echo "$as_me:$LINENO: result: $ac_cv_func_gethostbyname" >&5 +$as_echo "$ac_cv_func_gethostbyname" >&6; } + + if test $ac_cv_func_gethostbyname = no; then + { $as_echo "$as_me:$LINENO: checking for gethostbyname in -lnsl" >&5 +$as_echo_n "checking for gethostbyname in -lnsl... " >&6; } +if test "${ac_cv_lib_nsl_gethostbyname+set}" = set; then + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lnsl $LIBS" +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char gethostbyname (); +int +main () +{ +return gethostbyname (); + ; + return 0; +} +_ACEOF +rm -rf conftest.$ac_objext conftest$ac_exeext +if { (ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\"" +$as_echo "$ac_try_echo") >&5 + (eval "$ac_link") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -rf conftest.er1 + cat conftest.err >&5 + $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest$ac_exeext && { + test "$cross_compiling" = yes || + $as_test_x conftest$ac_exeext + }; then + ac_cv_lib_nsl_gethostbyname=yes +else + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_cv_lib_nsl_gethostbyname=no +fi + +rm -rf conftest.dSYM +rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:$LINENO: result: $ac_cv_lib_nsl_gethostbyname" >&5 +$as_echo "$ac_cv_lib_nsl_gethostbyname" >&6; } +if test "x$ac_cv_lib_nsl_gethostbyname" = x""yes; then + X_EXTRA_LIBS="$X_EXTRA_LIBS -lnsl" +fi + + if test $ac_cv_lib_nsl_gethostbyname = no; then + { $as_echo "$as_me:$LINENO: checking for gethostbyname in -lbsd" >&5 +$as_echo_n "checking for gethostbyname in -lbsd... " >&6; } +if test "${ac_cv_lib_bsd_gethostbyname+set}" = set; then + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lbsd $LIBS" +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char gethostbyname (); +int +main () +{ +return gethostbyname (); + ; + return 0; +} +_ACEOF +rm -rf conftest.$ac_objext conftest$ac_exeext +if { (ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\"" +$as_echo "$ac_try_echo") >&5 + (eval "$ac_link") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -rf conftest.er1 + cat conftest.err >&5 + $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest$ac_exeext && { + test "$cross_compiling" = yes || + $as_test_x conftest$ac_exeext + }; then + ac_cv_lib_bsd_gethostbyname=yes +else + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_cv_lib_bsd_gethostbyname=no +fi + +rm -rf conftest.dSYM +rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:$LINENO: result: $ac_cv_lib_bsd_gethostbyname" >&5 +$as_echo "$ac_cv_lib_bsd_gethostbyname" >&6; } +if test "x$ac_cv_lib_bsd_gethostbyname" = x""yes; then + X_EXTRA_LIBS="$X_EXTRA_LIBS -lbsd" +fi + + fi + fi + + # lieder@skyler.mavd.honeywell.com says without -lsocket, + # socket/setsockopt and other routines are undefined under SCO ODT + # 2.0. But -lsocket is broken on IRIX 5.2 (and is not necessary + # on later versions), says Simon Leinen: it contains gethostby* + # variants that don't use the name server (or something). -lsocket + # must be given before -lnsl if both are needed. We assume that + # if connect needs -lnsl, so does gethostbyname. + { $as_echo "$as_me:$LINENO: checking for connect" >&5 +$as_echo_n "checking for connect... " >&6; } +if test "${ac_cv_func_connect+set}" = set; then + $as_echo_n "(cached) " >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +/* Define connect to an innocuous variant, in case declares connect. + For example, HP-UX 11i declares gettimeofday. */ +#define connect innocuous_connect + +/* System header to define __stub macros and hopefully few prototypes, + which can conflict with char connect (); below. + Prefer to if __STDC__ is defined, since + exists even on freestanding compilers. */ + +#ifdef __STDC__ +# include +#else +# include +#endif + +#undef connect + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char connect (); +/* The GNU C library defines this for functions which it implements + to always fail with ENOSYS. Some functions are actually named + something starting with __ and the normal name is an alias. */ +#if defined __stub_connect || defined __stub___connect +choke me +#endif + +int +main () +{ +return connect (); + ; + return 0; +} +_ACEOF +rm -rf conftest.$ac_objext conftest$ac_exeext +if { (ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\"" +$as_echo "$ac_try_echo") >&5 + (eval "$ac_link") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -rf conftest.er1 + cat conftest.err >&5 + $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest$ac_exeext && { + test "$cross_compiling" = yes || + $as_test_x conftest$ac_exeext + }; then + ac_cv_func_connect=yes +else + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_cv_func_connect=no +fi + +rm -rf conftest.dSYM +rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ + conftest$ac_exeext conftest.$ac_ext +fi +{ $as_echo "$as_me:$LINENO: result: $ac_cv_func_connect" >&5 +$as_echo "$ac_cv_func_connect" >&6; } + + if test $ac_cv_func_connect = no; then + { $as_echo "$as_me:$LINENO: checking for connect in -lsocket" >&5 +$as_echo_n "checking for connect in -lsocket... " >&6; } +if test "${ac_cv_lib_socket_connect+set}" = set; then + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lsocket $X_EXTRA_LIBS $LIBS" +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char connect (); +int +main () +{ +return connect (); + ; + return 0; +} +_ACEOF +rm -rf conftest.$ac_objext conftest$ac_exeext +if { (ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\"" +$as_echo "$ac_try_echo") >&5 + (eval "$ac_link") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -rf conftest.er1 + cat conftest.err >&5 + $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest$ac_exeext && { + test "$cross_compiling" = yes || + $as_test_x conftest$ac_exeext + }; then + ac_cv_lib_socket_connect=yes +else + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_cv_lib_socket_connect=no +fi + +rm -rf conftest.dSYM +rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:$LINENO: result: $ac_cv_lib_socket_connect" >&5 +$as_echo "$ac_cv_lib_socket_connect" >&6; } +if test "x$ac_cv_lib_socket_connect" = x""yes; then + X_EXTRA_LIBS="-lsocket $X_EXTRA_LIBS" +fi + + fi + + # Guillermo Gomez says -lposix is necessary on A/UX. + { $as_echo "$as_me:$LINENO: checking for remove" >&5 +$as_echo_n "checking for remove... " >&6; } +if test "${ac_cv_func_remove+set}" = set; then + $as_echo_n "(cached) " >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +/* Define remove to an innocuous variant, in case declares remove. + For example, HP-UX 11i declares gettimeofday. */ +#define remove innocuous_remove + +/* System header to define __stub macros and hopefully few prototypes, + which can conflict with char remove (); below. + Prefer to if __STDC__ is defined, since + exists even on freestanding compilers. */ + +#ifdef __STDC__ +# include +#else +# include +#endif + +#undef remove + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char remove (); +/* The GNU C library defines this for functions which it implements + to always fail with ENOSYS. Some functions are actually named + something starting with __ and the normal name is an alias. */ +#if defined __stub_remove || defined __stub___remove +choke me +#endif + +int +main () +{ +return remove (); + ; + return 0; +} +_ACEOF +rm -rf conftest.$ac_objext conftest$ac_exeext +if { (ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\"" +$as_echo "$ac_try_echo") >&5 + (eval "$ac_link") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -rf conftest.er1 + cat conftest.err >&5 + $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest$ac_exeext && { + test "$cross_compiling" = yes || + $as_test_x conftest$ac_exeext + }; then + ac_cv_func_remove=yes +else + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_cv_func_remove=no +fi + +rm -rf conftest.dSYM +rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ + conftest$ac_exeext conftest.$ac_ext +fi +{ $as_echo "$as_me:$LINENO: result: $ac_cv_func_remove" >&5 +$as_echo "$ac_cv_func_remove" >&6; } + + if test $ac_cv_func_remove = no; then + { $as_echo "$as_me:$LINENO: checking for remove in -lposix" >&5 +$as_echo_n "checking for remove in -lposix... " >&6; } +if test "${ac_cv_lib_posix_remove+set}" = set; then + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lposix $LIBS" +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char remove (); +int +main () +{ +return remove (); + ; + return 0; +} +_ACEOF +rm -rf conftest.$ac_objext conftest$ac_exeext +if { (ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\"" +$as_echo "$ac_try_echo") >&5 + (eval "$ac_link") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -rf conftest.er1 + cat conftest.err >&5 + $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest$ac_exeext && { + test "$cross_compiling" = yes || + $as_test_x conftest$ac_exeext + }; then + ac_cv_lib_posix_remove=yes +else + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_cv_lib_posix_remove=no +fi + +rm -rf conftest.dSYM +rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:$LINENO: result: $ac_cv_lib_posix_remove" >&5 +$as_echo "$ac_cv_lib_posix_remove" >&6; } +if test "x$ac_cv_lib_posix_remove" = x""yes; then + X_EXTRA_LIBS="$X_EXTRA_LIBS -lposix" +fi + + fi + + # BSDI BSD/OS 2.1 needs -lipc for XOpenDisplay. + { $as_echo "$as_me:$LINENO: checking for shmat" >&5 +$as_echo_n "checking for shmat... " >&6; } +if test "${ac_cv_func_shmat+set}" = set; then + $as_echo_n "(cached) " >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +/* Define shmat to an innocuous variant, in case declares shmat. + For example, HP-UX 11i declares gettimeofday. */ +#define shmat innocuous_shmat + +/* System header to define __stub macros and hopefully few prototypes, + which can conflict with char shmat (); below. + Prefer to if __STDC__ is defined, since + exists even on freestanding compilers. */ + +#ifdef __STDC__ +# include +#else +# include +#endif + +#undef shmat + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char shmat (); +/* The GNU C library defines this for functions which it implements + to always fail with ENOSYS. Some functions are actually named + something starting with __ and the normal name is an alias. */ +#if defined __stub_shmat || defined __stub___shmat +choke me +#endif + +int +main () +{ +return shmat (); + ; + return 0; +} +_ACEOF +rm -rf conftest.$ac_objext conftest$ac_exeext +if { (ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\"" +$as_echo "$ac_try_echo") >&5 + (eval "$ac_link") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -rf conftest.er1 + cat conftest.err >&5 + $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest$ac_exeext && { + test "$cross_compiling" = yes || + $as_test_x conftest$ac_exeext + }; then + ac_cv_func_shmat=yes +else + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_cv_func_shmat=no +fi + +rm -rf conftest.dSYM +rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ + conftest$ac_exeext conftest.$ac_ext +fi +{ $as_echo "$as_me:$LINENO: result: $ac_cv_func_shmat" >&5 +$as_echo "$ac_cv_func_shmat" >&6; } + + if test $ac_cv_func_shmat = no; then + { $as_echo "$as_me:$LINENO: checking for shmat in -lipc" >&5 +$as_echo_n "checking for shmat in -lipc... " >&6; } +if test "${ac_cv_lib_ipc_shmat+set}" = set; then + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lipc $LIBS" +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char shmat (); +int +main () +{ +return shmat (); + ; + return 0; +} +_ACEOF +rm -rf conftest.$ac_objext conftest$ac_exeext +if { (ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\"" +$as_echo "$ac_try_echo") >&5 + (eval "$ac_link") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -rf conftest.er1 + cat conftest.err >&5 + $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest$ac_exeext && { + test "$cross_compiling" = yes || + $as_test_x conftest$ac_exeext + }; then + ac_cv_lib_ipc_shmat=yes +else + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_cv_lib_ipc_shmat=no +fi + +rm -rf conftest.dSYM +rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:$LINENO: result: $ac_cv_lib_ipc_shmat" >&5 +$as_echo "$ac_cv_lib_ipc_shmat" >&6; } +if test "x$ac_cv_lib_ipc_shmat" = x""yes; then + X_EXTRA_LIBS="$X_EXTRA_LIBS -lipc" +fi + + fi + fi + + # Check for libraries that X11R6 Xt/Xaw programs need. + ac_save_LDFLAGS=$LDFLAGS + test -n "$x_libraries" && LDFLAGS="$LDFLAGS -L$x_libraries" + # SM needs ICE to (dynamically) link under SunOS 4.x (so we have to + # check for ICE first), but we must link in the order -lSM -lICE or + # we get undefined symbols. So assume we have SM if we have ICE. + # These have to be linked with before -lX11, unlike the other + # libraries we check for below, so use a different variable. + # John Interrante, Karl Berry + { $as_echo "$as_me:$LINENO: checking for IceConnectionNumber in -lICE" >&5 +$as_echo_n "checking for IceConnectionNumber in -lICE... " >&6; } +if test "${ac_cv_lib_ICE_IceConnectionNumber+set}" = set; then + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lICE $X_EXTRA_LIBS $LIBS" +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char IceConnectionNumber (); +int +main () +{ +return IceConnectionNumber (); + ; + return 0; +} +_ACEOF +rm -rf conftest.$ac_objext conftest$ac_exeext +if { (ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\"" +$as_echo "$ac_try_echo") >&5 + (eval "$ac_link") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -rf conftest.er1 + cat conftest.err >&5 + $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest$ac_exeext && { + test "$cross_compiling" = yes || + $as_test_x conftest$ac_exeext + }; then + ac_cv_lib_ICE_IceConnectionNumber=yes +else + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_cv_lib_ICE_IceConnectionNumber=no +fi + +rm -rf conftest.dSYM +rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:$LINENO: result: $ac_cv_lib_ICE_IceConnectionNumber" >&5 +$as_echo "$ac_cv_lib_ICE_IceConnectionNumber" >&6; } +if test "x$ac_cv_lib_ICE_IceConnectionNumber" = x""yes; then + X_PRE_LIBS="$X_PRE_LIBS -lSM -lICE" +fi + + LDFLAGS=$ac_save_LDFLAGS + +fi + + +if test "$have_x" != yes; then + { { $as_echo "$as_me:$LINENO: error: Couldn't find X11 headers/libs. Try \`$0 --help'." >&5 +$as_echo "$as_me: error: Couldn't find X11 headers/libs. Try \`$0 --help'." >&2;} + { (exit 1); exit 1; }; } +fi + + + { $as_echo "$as_me:$LINENO: checking for X app-defaults directory" >&5 +$as_echo_n "checking for X app-defaults directory... " >&6; } +if test "${ac_cv_x_app_defaults+set}" = set; then + $as_echo_n "(cached) " >&6 +else + + rm -fr conftestdir + if mkdir conftestdir; then + cd conftestdir 2>/dev/null + # Make sure to not put "make" in the Imakefile rules, since we grep it out. + cat > Imakefile <<'EOF' +acfindx: + @echo 'ac_x_app_defaults="${XAPPLOADDIR}"' +EOF + if (xmkmf) >/dev/null 2>&1 && test -f Makefile; then + # GNU make sometimes prints "make[1]: Entering...", which'd confuse us. + eval `${MAKE-make} acfindx 2>/dev/null | grep -v make` + fi + cd .. 2>/dev/null + rm -fr conftestdir + fi + if test x"$ac_x_app_defaults" = x; then + + # Look for the directory under a standard set of common directories. + # Check X11 before X11Rn because it's often a symlink to the current release. + for ac_dir in \ + /usr/X11/lib/app-defaults \ + /usr/X11R6/lib/app-defaults \ + /usr/X11R6/lib/X11/app-defaults \ + /usr/X11R5/lib/app-defaults \ + /usr/X11R5/lib/X11/app-defaults \ + /usr/X11R4/lib/app-defaults \ + /usr/X11R4/lib/X11/app-defaults \ + \ + /usr/lib/X11/app-defaults \ + /usr/lib/X11R6/app-defaults \ + /usr/lib/X11R5/app-defaults \ + /usr/lib/X11R4/app-defaults \ + \ + /usr/local/X11/lib/app-defaults \ + /usr/local/X11R6/lib/app-defaults \ + /usr/local/X11R5/lib/app-defaults \ + /usr/local/X11R4/lib/app-defaults \ + \ + /usr/local/lib/X11/app-defaults \ + /usr/local/lib/X11R6/app-defaults \ + /usr/local/lib/X11R6/X11/app-defaults \ + /usr/local/lib/X11R5/app-defaults \ + /usr/local/lib/X11R5/X11/app-defaults \ + /usr/local/lib/X11R4/app-defaults \ + /usr/local/lib/X11R4/X11/app-defaults \ + \ + /usr/X386/lib/X11/app-defaults \ + /usr/x386/lib/X11/app-defaults \ + /usr/XFree86/lib/X11/app-defaults \ + \ + /usr/lib/X11/app-defaults \ + /usr/local/lib/X11/app-defaults \ + /usr/unsupported/lib/X11/app-defaults \ + /usr/athena/lib/X11/app-defaults \ + /usr/local/x11r5/lib/X11/app-defaults \ + /usr/lpp/Xamples/lib/X11/app-defaults \ + /lib/usr/lib/X11/app-defaults \ + \ + /usr/openwin/lib/app-defaults \ + /usr/openwin/lib/X11/app-defaults \ + /usr/openwin/share/lib/app-defaults \ + /usr/openwin/share/lib/X11/app-defaults \ + \ + /X11R6/lib/app-defaults \ + /X11R5/lib/app-defaults \ + /X11R4/lib/app-defaults \ + ; \ + do + if test -d "$ac_dir"; then + ac_x_app_defaults=$ac_dir + break + fi + done + + fi + if test x"$ac_x_app_defaults" = x; then + ac_cv_x_app_defaults="/usr/lib/X11/app-defaults" + else + # Record where we found app-defaults for the cache. + ac_cv_x_app_defaults="$ac_x_app_defaults" + fi +fi +{ $as_echo "$as_me:$LINENO: result: $ac_cv_x_app_defaults" >&5 +$as_echo "$ac_cv_x_app_defaults" >&6; } + eval ac_x_app_defaults="$ac_cv_x_app_defaults" +case "$host" in + *-hpux*) + + # The following arcana was gleaned from conversations with + # Eric Schwartz : + # + # On HPUX 10.x, the parts of X that HP considers "standard" live in + # /usr/{include,lib}/X11R6/. The parts that HP doesn't consider + # "standard", notably, Xaw and Xmu, live in /usr/contrib/X11R6/. + # Yet /usr/contrib/X11R6/ comes preinstalled on all HPUX systems. + # Also, there are symlinks from /usr/include/ and /usr/lib/ into + # /usr/{include,lib}/X11R6/, so that (if you don't use Xmu at all) + # you don't need any -I or -L arguments. + # + # On HPUX 9.x, /usr/{include,lib}/X11R5/ and /usr/contrib/X11R5/ + # are the same division as 10.x. However, there are no symlinks to + # the X stuff from /usr/include/ and /usr/lib/, so -I and -L + # arguments are always necessary. + # + # However, X11R6 was available on HPUX 9.x as a patch: if that + # patch was installed, then all of X11R6 went in to + # /usr/contrib/X11R6/ (there was no /usr/{include,lib}/X11R6/.) + # + # HPUX 8.x was the same as 9.x, but was X11R4 instead (I don't know + # whether R5 was available as a patch; R6 undoubtedly was not.) + # + # So. We try and use the highest numbered pair of + # /usr/{include,lib}/X11R?/ and /usr/contrib/X11R?/{include,lib}/ + # that are available. We do not mix and match different versions + # of X. + # + # Question I still don't know the answer to: (do you?) + # + # * On HPUX 9.x, where /usr/include/X11R5/ was standard, and + # /usr/contrib/X11R6/ could be installed as a patch, what was in + # that contrib directory? Did it contain so-called "standard" + # X11R6, or did it include Xaw and Xmu as well? If the former, + # where did one find Xaw and Xmu on 9.x R6 systems? Would this + # be a situation where one had to reach into the R5 headers and + # libs to find Xmu? That is, must both R6 and R5 directories + # be on the -I and -L lists in that case? + # + for version in X11R6 X11R5 X11R4 ; do + # if either pair of directories exists... + if test -d /usr/include/$version || test -d /usr/contrib/$version/include + then + # if contrib exists, use it... + if test -d /usr/contrib/$version/include ; then + X_CFLAGS="$X_CFLAGS -I/usr/contrib/$version/include" + X_LIBS="$X_LIBS -L/usr/contrib/$version/lib" + fi + # if the "standard" one exists, use it. + if test -d /usr/include/$version ; then + X_CFLAGS="$X_CFLAGS -I/usr/include/$version" + X_LIBS="$X_LIBS -L/usr/lib/$version" + fi + # since at least one of the pair exists, go no farther. + break + fi + done + + # Now find Motif. Thanks for not making xmkmf find this by + # default, you losers. + # + if test -d /usr/include/Motif2.1 ; then + X_CFLAGS="$X_CFLAGS -I/usr/include/Motif2.1" + X_LIBS="$X_LIBS -L/usr/lib/Motif2.1" + elif test -d /usr/include/Motif1.2 ; then + X_CFLAGS="$X_CFLAGS -I/usr/include/Motif1.2" + X_LIBS="$X_LIBS -L/usr/lib/Motif1.2" + elif test -d /usr/include/Motif1.1 ; then + X_CFLAGS="$X_CFLAGS -I/usr/include/Motif1.1" + X_LIBS="$X_LIBS -L/usr/lib/Motif1.1" + fi + + # Now let's check for the pseudo-standard locations for OpenGL and XPM. + # + if test -d /opt/graphics/OpenGL/include ; then + # HP-UX 10.20 puts it here + X_CFLAGS="-I/opt/graphics/OpenGL/include $X_CFLAGS" + X_LIBS="-L/opt/graphics/OpenGL/lib $X_LIBS" + elif test -d /opt/Mesa/lib ; then + X_CFLAGS="-I/opt/Mesa/include $X_CFLAGS" + X_LIBS="-L/opt/Mesa/lib $X_LIBS" + fi + + + if test -d /opt/xpm/lib/X11 ; then + X_CFLAGS="-I/opt/xpm/include $X_CFLAGS" + X_LIBS="-L/opt/xpm/lib/X11 $X_LIBS" + fi + + # On HPUX, default to installing in /opt/xscreensaver/ instead of + # in /usr/local/, unless there is already an xscreensaver in + # /usr/local/bin/. This can be overridden with the --prefix arg + # to configure. I'm not sure this is the right thing to do, but + # Richard Lloyd says so... + # + if test \! -x /usr/local/bin/xscreensaver ; then + ac_default_prefix=/opt/xscreensaver + fi + + ;; + *-solaris*) + + # Thanks for not making xmkmf find this by default, pinheads. + # And thanks for moving things around again, too. Is this + # really the standard location now? What happened to the + # joke that this kind of thing went in /opt? + # cthomp says "answer: CDE (Common Disorganized Environment)" + # + if test -f /usr/dt/include/Xm/Xm.h ; then + X_CFLAGS="$X_CFLAGS -I/usr/dt/include" + MOTIF_LIBS="$MOTIF_LIBS -L/usr/dt/lib -R/usr/dt/lib" + + # Some versions of Slowlaris Motif require -lgen. But not all. Why? + { $as_echo "$as_me:$LINENO: checking for regcmp in -lgen" >&5 +$as_echo_n "checking for regcmp in -lgen... " >&6; } +if test "${ac_cv_lib_gen_regcmp+set}" = set; then + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lgen $LIBS" +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char regcmp (); +int +main () +{ +return regcmp (); + ; + return 0; +} +_ACEOF +rm -rf conftest.$ac_objext conftest$ac_exeext +if { (ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\"" +$as_echo "$ac_try_echo") >&5 + (eval "$ac_link") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -rf conftest.er1 + cat conftest.err >&5 + $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest$ac_exeext && { + test "$cross_compiling" = yes || + $as_test_x conftest$ac_exeext + }; then + ac_cv_lib_gen_regcmp=yes +else + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_cv_lib_gen_regcmp=no +fi + +rm -rf conftest.dSYM +rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:$LINENO: result: $ac_cv_lib_gen_regcmp" >&5 +$as_echo "$ac_cv_lib_gen_regcmp" >&6; } +if test "x$ac_cv_lib_gen_regcmp" = x""yes; then + MOTIF_LIBS="$MOTIF_LIBS -lgen" +fi + + fi + + ;; + *-darwin*) + + # On MacOS X (10.x with "fink"), many things are under /sw/. + # + if test -d /sw/include ; then + X_CFLAGS="-I/sw/include $X_CFLAGS" + X_LIBS="-L/sw/lib $X_LIBS" + fi + ;; + esac +{ $as_echo "$as_me:$LINENO: checking for XPointer" >&5 +$as_echo_n "checking for XPointer... " >&6; } +if test "${ac_cv_xpointer+set}" = set; then + $as_echo_n "(cached) " >&6 +else + + ac_save_CPPFLAGS="$CPPFLAGS" + if test \! -z "$includedir" ; then + CPPFLAGS="$CPPFLAGS -I$includedir" + fi + CPPFLAGS="$CPPFLAGS $X_CFLAGS" + CPPFLAGS=`eval eval eval eval eval eval eval eval eval echo $CPPFLAGS` + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include +int +main () +{ +XPointer foo = (XPointer) 0; + ; + return 0; +} +_ACEOF +rm -rf conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\"" +$as_echo "$ac_try_echo") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -rf conftest.er1 + cat conftest.err >&5 + $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest.$ac_objext; then + ac_cv_xpointer=yes +else + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_cv_xpointer=no +fi + +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + CPPFLAGS="$ac_save_CPPFLAGS" +fi +{ $as_echo "$as_me:$LINENO: result: $ac_cv_xpointer" >&5 +$as_echo "$ac_cv_xpointer" >&6; } + if test "$ac_cv_xpointer" != yes; then + cat >>confdefs.h <<\_ACEOF +#define XPointer char* +_ACEOF + + fi + +{ $as_echo "$as_me:$LINENO: checking whether this is MacOS X" >&5 +$as_echo_n "checking whether this is MacOS X... " >&6; } + ac_macosx=no + case "$host" in + *-apple-darwin* ) + ac_macosx=yes + ;; + esac +{ $as_echo "$as_me:$LINENO: result: $ac_macosx" >&5 +$as_echo "$ac_macosx" >&6; } + + +############################################################################### +# +# Gettext support +# +############################################################################### + + + +if test -n ""; then + { $as_echo "$as_me:$LINENO: checking for intltool >= " >&5 +$as_echo_n "checking for intltool >= ... " >&6; } + + INTLTOOL_REQUIRED_VERSION_AS_INT=`echo | awk -F. '{ printf "%d", $1 * 100 + $2; }'` + INTLTOOL_APPLIED_VERSION=`awk -F\" '/\\$VERSION / { printf $2; }' < intltool-update.in` + + INTLTOOL_APPLIED_VERSION_AS_INT=`awk -F\" '/\\$VERSION / { split($2, VERSION, "."); printf "%d\n", VERSION[1] * 100 + VERSION[2];}' < intltool-update.in` + + + if test "$INTLTOOL_APPLIED_VERSION_AS_INT" -ge "$INTLTOOL_REQUIRED_VERSION_AS_INT"; then + { $as_echo "$as_me:$LINENO: result: $INTLTOOL_APPLIED_VERSION found" >&5 +$as_echo "$INTLTOOL_APPLIED_VERSION found" >&6; } + else + { $as_echo "$as_me:$LINENO: result: $INTLTOOL_APPLIED_VERSION found. Your intltool is too old. You need intltool or later." >&5 +$as_echo "$INTLTOOL_APPLIED_VERSION found. Your intltool is too old. You need intltool or later." >&6; } + exit 1 + fi +fi + + INTLTOOL_DESKTOP_RULE='%.desktop: %.desktop.in $(INTLTOOL_MERGE) $(wildcard $(top_srcdir)/po/*.po) ; $(INTLTOOL_MERGE) $(top_srcdir)/po $< $@ -d -u -c $(top_builddir)/po/.intltool-merge-cache' +INTLTOOL_DIRECTORY_RULE='%.directory: %.directory.in $(INTLTOOL_MERGE) $(wildcard $(top_srcdir)/po/*.po) ; $(INTLTOOL_MERGE) $(top_srcdir)/po $< $@ -d -u -c $(top_builddir)/po/.intltool-merge-cache' + INTLTOOL_KEYS_RULE='%.keys: %.keys.in $(INTLTOOL_MERGE) $(wildcard $(top_srcdir)/po/*.po) ; $(INTLTOOL_MERGE) $(top_srcdir)/po $< $@ -k -u -c $(top_builddir)/po/.intltool-merge-cache' + INTLTOOL_OAF_RULE='%.oaf: %.oaf.in $(INTLTOOL_MERGE) $(wildcard $(top_srcdir)/po/*.po) ; $(INTLTOOL_MERGE) $(top_srcdir)/po $< $@ -o -p' + INTLTOOL_PONG_RULE='%.pong: %.pong.in $(INTLTOOL_MERGE) $(wildcard $(top_srcdir)/po/*.po) ; $(INTLTOOL_MERGE) $(top_srcdir)/po $< $@ -x -u -c $(top_builddir)/po/.intltool-merge-cache' + INTLTOOL_SERVER_RULE='%.server: %.server.in $(INTLTOOL_MERGE) $(wildcard $(top_srcdir)/po/*.po) ; $(INTLTOOL_MERGE) $(top_srcdir)/po $< $@ -o -u -c $(top_builddir)/po/.intltool-merge-cache' + INTLTOOL_SHEET_RULE='%.sheet: %.sheet.in $(INTLTOOL_MERGE) $(wildcard $(top_srcdir)/po/*.po) ; $(INTLTOOL_MERGE) $(top_srcdir)/po $< $@ -x -u -c $(top_builddir)/po/.intltool-merge-cache' +INTLTOOL_SOUNDLIST_RULE='%.soundlist: %.soundlist.in $(INTLTOOL_MERGE) $(wildcard $(top_srcdir)/po/*.po) ; $(INTLTOOL_MERGE) $(top_srcdir)/po $< $@ -d -u -c $(top_builddir)/po/.intltool-merge-cache' + INTLTOOL_UI_RULE='%.ui: %.ui.in $(INTLTOOL_MERGE) $(wildcard $(top_srcdir)/po/*.po) ; $(INTLTOOL_MERGE) $(top_srcdir)/po $< $@ -x -u -c $(top_builddir)/po/.intltool-merge-cache' + INTLTOOL_XML_RULE='%.xml: %.xml.in $(INTLTOOL_MERGE) $(wildcard $(top_srcdir)/po/*.po) ; $(INTLTOOL_MERGE) $(top_srcdir)/po $< $@ -x -u -c $(top_builddir)/po/.intltool-merge-cache' + INTLTOOL_CAVES_RULE='%.caves: %.caves.in $(INTLTOOL_MERGE) $(wildcard $(top_srcdir)/po/*.po) ; $(INTLTOOL_MERGE) $(top_srcdir)/po $< $@ -d -u -c $(top_builddir)/po/.intltool-merge-cache' + + + + + + + + + + + + + +# Use the tools built into the package, not the ones that are installed. + +INTLTOOL_EXTRACT='$(top_builddir)/intltool-extract' +INTLTOOL_MERGE='$(top_builddir)/intltool-merge' +INTLTOOL_UPDATE='$(top_builddir)/intltool-update' + + + + + +# Extract the first word of "perl", so it can be a program name with args. +set dummy perl; ac_word=$2 +{ $as_echo "$as_me:$LINENO: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if test "${ac_cv_path_INTLTOOL_PERL+set}" = set; then + $as_echo_n "(cached) " >&6 +else + case $INTLTOOL_PERL in + [\\/]* | ?:[\\/]*) + ac_cv_path_INTLTOOL_PERL="$INTLTOOL_PERL" # Let the user override the test with a path. + ;; + *) + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_path_INTLTOOL_PERL="$as_dir/$ac_word$ac_exec_ext" + $as_echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done +IFS=$as_save_IFS + + ;; +esac +fi +INTLTOOL_PERL=$ac_cv_path_INTLTOOL_PERL +if test -n "$INTLTOOL_PERL"; then + { $as_echo "$as_me:$LINENO: result: $INTLTOOL_PERL" >&5 +$as_echo "$INTLTOOL_PERL" >&6; } +else + { $as_echo "$as_me:$LINENO: result: no" >&5 +$as_echo "no" >&6; } +fi + + +if test -z "$INTLTOOL_PERL"; then + { { $as_echo "$as_me:$LINENO: error: perl not found; required for intltool" >&5 +$as_echo "$as_me: error: perl not found; required for intltool" >&2;} + { (exit 1); exit 1; }; } +fi +if test -z "`$INTLTOOL_PERL -v | fgrep '5.' 2> /dev/null`"; then + { { $as_echo "$as_me:$LINENO: error: perl 5.x required for intltool" >&5 +$as_echo "$as_me: error: perl 5.x required for intltool" >&2;} + { (exit 1); exit 1; }; } +fi + +# Remove file type tags (using []) from po/POTFILES. + + + + + + + +# Manually sed perl in so people don't have to put the intltool scripts in AC_OUTPUT. + +ac_config_commands="$ac_config_commands default-1" + + + +GETTEXT_PACKAGE=xscreensaver + +cat >>confdefs.h <<_ACEOF +#define GETTEXT_PACKAGE "$GETTEXT_PACKAGE" +_ACEOF + + +cat >>confdefs.h <<_ACEOF +#define PACKAGE "$GETTEXT_PACKAGE" +_ACEOF + + + +ALL_LINGUAS="ca da de es et fi fr hu it ja ko nb nl pl pt pt_BR ru sk sv vi wa zh_CN zh_TW" +if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}ranlib", so it can be a program name with args. +set dummy ${ac_tool_prefix}ranlib; ac_word=$2 +{ $as_echo "$as_me:$LINENO: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if test "${ac_cv_prog_RANLIB+set}" = set; then + $as_echo_n "(cached) " >&6 +else + if test -n "$RANLIB"; then + ac_cv_prog_RANLIB="$RANLIB" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_RANLIB="${ac_tool_prefix}ranlib" + $as_echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done +IFS=$as_save_IFS + +fi +fi +RANLIB=$ac_cv_prog_RANLIB +if test -n "$RANLIB"; then + { $as_echo "$as_me:$LINENO: result: $RANLIB" >&5 +$as_echo "$RANLIB" >&6; } +else + { $as_echo "$as_me:$LINENO: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi +if test -z "$ac_cv_prog_RANLIB"; then + ac_ct_RANLIB=$RANLIB + # Extract the first word of "ranlib", so it can be a program name with args. +set dummy ranlib; ac_word=$2 +{ $as_echo "$as_me:$LINENO: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if test "${ac_cv_prog_ac_ct_RANLIB+set}" = set; then + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_RANLIB"; then + ac_cv_prog_ac_ct_RANLIB="$ac_ct_RANLIB" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_ac_ct_RANLIB="ranlib" + $as_echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done +IFS=$as_save_IFS + +fi +fi +ac_ct_RANLIB=$ac_cv_prog_ac_ct_RANLIB +if test -n "$ac_ct_RANLIB"; then + { $as_echo "$as_me:$LINENO: result: $ac_ct_RANLIB" >&5 +$as_echo "$ac_ct_RANLIB" >&6; } +else + { $as_echo "$as_me:$LINENO: result: no" >&5 +$as_echo "no" >&6; } +fi + + if test "x$ac_ct_RANLIB" = x; then + RANLIB=":" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:$LINENO: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + RANLIB=$ac_ct_RANLIB + fi +else + RANLIB="$ac_cv_prog_RANLIB" +fi + +{ $as_echo "$as_me:$LINENO: checking for off_t" >&5 +$as_echo_n "checking for off_t... " >&6; } +if test "${ac_cv_type_off_t+set}" = set; then + $as_echo_n "(cached) " >&6 +else + ac_cv_type_off_t=no +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +$ac_includes_default +int +main () +{ +if (sizeof (off_t)) + return 0; + ; + return 0; +} +_ACEOF +rm -rf conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\"" +$as_echo "$ac_try_echo") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -rf conftest.er1 + cat conftest.err >&5 + $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest.$ac_objext; then + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +$ac_includes_default +int +main () +{ +if (sizeof ((off_t))) + return 0; + ; + return 0; +} +_ACEOF +rm -rf conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\"" +$as_echo "$ac_try_echo") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -rf conftest.er1 + cat conftest.err >&5 + $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest.$ac_objext; then + : +else + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_cv_type_off_t=yes +fi + +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +else + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + +fi + +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +{ $as_echo "$as_me:$LINENO: result: $ac_cv_type_off_t" >&5 +$as_echo "$ac_cv_type_off_t" >&6; } +if test "x$ac_cv_type_off_t" = x""yes; then + : +else + +cat >>confdefs.h <<_ACEOF +#define off_t long int +_ACEOF + +fi + +# The Ultrix 4.2 mips builtin alloca declared by alloca.h only works +# for constant arguments. Useless! +{ $as_echo "$as_me:$LINENO: checking for working alloca.h" >&5 +$as_echo_n "checking for working alloca.h... " >&6; } +if test "${ac_cv_working_alloca_h+set}" = set; then + $as_echo_n "(cached) " >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include +int +main () +{ +char *p = (char *) alloca (2 * sizeof (int)); + if (p) return 0; + ; + return 0; +} +_ACEOF +rm -rf conftest.$ac_objext conftest$ac_exeext +if { (ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\"" +$as_echo "$ac_try_echo") >&5 + (eval "$ac_link") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -rf conftest.er1 + cat conftest.err >&5 + $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest$ac_exeext && { + test "$cross_compiling" = yes || + $as_test_x conftest$ac_exeext + }; then + ac_cv_working_alloca_h=yes +else + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_cv_working_alloca_h=no +fi + +rm -rf conftest.dSYM +rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ + conftest$ac_exeext conftest.$ac_ext +fi +{ $as_echo "$as_me:$LINENO: result: $ac_cv_working_alloca_h" >&5 +$as_echo "$ac_cv_working_alloca_h" >&6; } +if test $ac_cv_working_alloca_h = yes; then + +cat >>confdefs.h <<\_ACEOF +#define HAVE_ALLOCA_H 1 +_ACEOF + +fi + +{ $as_echo "$as_me:$LINENO: checking for alloca" >&5 +$as_echo_n "checking for alloca... " >&6; } +if test "${ac_cv_func_alloca_works+set}" = set; then + $as_echo_n "(cached) " >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#ifdef __GNUC__ +# define alloca __builtin_alloca +#else +# ifdef _MSC_VER +# include +# define alloca _alloca +# else +# ifdef HAVE_ALLOCA_H +# include +# else +# ifdef _AIX + #pragma alloca +# else +# ifndef alloca /* predefined by HP cc +Olibcalls */ +char *alloca (); +# endif +# endif +# endif +# endif +#endif + +int +main () +{ +char *p = (char *) alloca (1); + if (p) return 0; + ; + return 0; +} +_ACEOF +rm -rf conftest.$ac_objext conftest$ac_exeext +if { (ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\"" +$as_echo "$ac_try_echo") >&5 + (eval "$ac_link") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -rf conftest.er1 + cat conftest.err >&5 + $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest$ac_exeext && { + test "$cross_compiling" = yes || + $as_test_x conftest$ac_exeext + }; then + ac_cv_func_alloca_works=yes +else + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_cv_func_alloca_works=no +fi + +rm -rf conftest.dSYM +rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ + conftest$ac_exeext conftest.$ac_ext +fi +{ $as_echo "$as_me:$LINENO: result: $ac_cv_func_alloca_works" >&5 +$as_echo "$ac_cv_func_alloca_works" >&6; } + +if test $ac_cv_func_alloca_works = yes; then + +cat >>confdefs.h <<\_ACEOF +#define HAVE_ALLOCA 1 +_ACEOF + +else + # The SVR3 libPW and SVR4 libucb both contain incompatible functions +# that cause trouble. Some versions do not even contain alloca or +# contain a buggy version. If you still want to use their alloca, +# use ar to extract alloca.o from them instead of compiling alloca.c. + +ALLOCA=\${LIBOBJDIR}alloca.$ac_objext + +cat >>confdefs.h <<\_ACEOF +#define C_ALLOCA 1 +_ACEOF + + +{ $as_echo "$as_me:$LINENO: checking whether \`alloca.c' needs Cray hooks" >&5 +$as_echo_n "checking whether \`alloca.c' needs Cray hooks... " >&6; } +if test "${ac_cv_os_cray+set}" = set; then + $as_echo_n "(cached) " >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#if defined CRAY && ! defined CRAY2 +webecray +#else +wenotbecray +#endif + +_ACEOF +if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | + $EGREP "webecray" >/dev/null 2>&1; then + ac_cv_os_cray=yes +else + ac_cv_os_cray=no +fi +rm -rf conftest* + +fi +{ $as_echo "$as_me:$LINENO: result: $ac_cv_os_cray" >&5 +$as_echo "$ac_cv_os_cray" >&6; } +if test $ac_cv_os_cray = yes; then + for ac_func in _getb67 GETB67 getb67; do + as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh` +{ $as_echo "$as_me:$LINENO: checking for $ac_func" >&5 +$as_echo_n "checking for $ac_func... " >&6; } +if { as_var=$as_ac_var; eval "test \"\${$as_var+set}\" = set"; }; then + $as_echo_n "(cached) " >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +/* Define $ac_func to an innocuous variant, in case declares $ac_func. + For example, HP-UX 11i declares gettimeofday. */ +#define $ac_func innocuous_$ac_func + +/* System header to define __stub macros and hopefully few prototypes, + which can conflict with char $ac_func (); below. + Prefer to if __STDC__ is defined, since + exists even on freestanding compilers. */ + +#ifdef __STDC__ +# include +#else +# include +#endif + +#undef $ac_func + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char $ac_func (); +/* The GNU C library defines this for functions which it implements + to always fail with ENOSYS. Some functions are actually named + something starting with __ and the normal name is an alias. */ +#if defined __stub_$ac_func || defined __stub___$ac_func +choke me +#endif + +int +main () +{ +return $ac_func (); + ; + return 0; +} +_ACEOF +rm -rf conftest.$ac_objext conftest$ac_exeext +if { (ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\"" +$as_echo "$ac_try_echo") >&5 + (eval "$ac_link") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -rf conftest.er1 + cat conftest.err >&5 + $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest$ac_exeext && { + test "$cross_compiling" = yes || + $as_test_x conftest$ac_exeext + }; then + eval "$as_ac_var=yes" +else + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + eval "$as_ac_var=no" +fi + +rm -rf conftest.dSYM +rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ + conftest$ac_exeext conftest.$ac_ext +fi +ac_res=`eval 'as_val=${'$as_ac_var'} + $as_echo "$as_val"'` + { $as_echo "$as_me:$LINENO: result: $ac_res" >&5 +$as_echo "$ac_res" >&6; } +as_val=`eval 'as_val=${'$as_ac_var'} + $as_echo "$as_val"'` + if test "x$as_val" = x""yes; then + +cat >>confdefs.h <<_ACEOF +#define CRAY_STACKSEG_END $ac_func +_ACEOF + + break +fi + + done +fi + +{ $as_echo "$as_me:$LINENO: checking stack direction for C alloca" >&5 +$as_echo_n "checking stack direction for C alloca... " >&6; } +if test "${ac_cv_c_stack_direction+set}" = set; then + $as_echo_n "(cached) " >&6 +else + if test "$cross_compiling" = yes; then + ac_cv_c_stack_direction=0 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +$ac_includes_default +int +find_stack_direction () +{ + static char *addr = 0; + auto char dummy; + if (addr == 0) + { + addr = &dummy; + return find_stack_direction (); + } + else + return (&dummy > addr) ? 1 : -1; +} + +int +main () +{ + return find_stack_direction () < 0; +} +_ACEOF +rm -rf conftest$ac_exeext +if { (ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\"" +$as_echo "$ac_try_echo") >&5 + (eval "$ac_link") 2>&5 + ac_status=$? + $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { ac_try='./conftest$ac_exeext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\"" +$as_echo "$ac_try_echo") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_c_stack_direction=1 +else + $as_echo "$as_me: program exited with status $ac_status" >&5 +$as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +( exit $ac_status ) +ac_cv_c_stack_direction=-1 +fi +rm -rf conftest.dSYM +rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext +fi + + +fi +{ $as_echo "$as_me:$LINENO: result: $ac_cv_c_stack_direction" >&5 +$as_echo "$ac_cv_c_stack_direction" >&6; } + +cat >>confdefs.h <<_ACEOF +#define STACK_DIRECTION $ac_cv_c_stack_direction +_ACEOF + + +fi + + + +for ac_header in stdlib.h unistd.h +do +as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh` +if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then + { $as_echo "$as_me:$LINENO: checking for $ac_header" >&5 +$as_echo_n "checking for $ac_header... " >&6; } +if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then + $as_echo_n "(cached) " >&6 +fi +ac_res=`eval 'as_val=${'$as_ac_Header'} + $as_echo "$as_val"'` + { $as_echo "$as_me:$LINENO: result: $ac_res" >&5 +$as_echo "$ac_res" >&6; } +else + # Is the header compilable? +{ $as_echo "$as_me:$LINENO: checking $ac_header usability" >&5 +$as_echo_n "checking $ac_header usability... " >&6; } +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +$ac_includes_default +#include <$ac_header> +_ACEOF +rm -rf conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\"" +$as_echo "$ac_try_echo") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -rf conftest.er1 + cat conftest.err >&5 + $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest.$ac_objext; then + ac_header_compiler=yes +else + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_header_compiler=no +fi + +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +{ $as_echo "$as_me:$LINENO: result: $ac_header_compiler" >&5 +$as_echo "$ac_header_compiler" >&6; } + +# Is the header present? +{ $as_echo "$as_me:$LINENO: checking $ac_header presence" >&5 +$as_echo_n "checking $ac_header presence... " >&6; } +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include <$ac_header> +_ACEOF +if { (ac_try="$ac_cpp conftest.$ac_ext" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\"" +$as_echo "$ac_try_echo") >&5 + (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -rf conftest.er1 + cat conftest.err >&5 + $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } >/dev/null && { + test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" || + test ! -s conftest.err + }; then + ac_header_preproc=yes +else + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_header_preproc=no +fi + +rm -rf conftest.err conftest.$ac_ext +{ $as_echo "$as_me:$LINENO: result: $ac_header_preproc" >&5 +$as_echo "$ac_header_preproc" >&6; } + +# So? What about this header? +case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in + yes:no: ) + { $as_echo "$as_me:$LINENO: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&5 +$as_echo "$as_me: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&2;} + { $as_echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the compiler's result" >&5 +$as_echo "$as_me: WARNING: $ac_header: proceeding with the compiler's result" >&2;} + ac_header_preproc=yes + ;; + no:yes:* ) + { $as_echo "$as_me:$LINENO: WARNING: $ac_header: present but cannot be compiled" >&5 +$as_echo "$as_me: WARNING: $ac_header: present but cannot be compiled" >&2;} + { $as_echo "$as_me:$LINENO: WARNING: $ac_header: check for missing prerequisite headers?" >&5 +$as_echo "$as_me: WARNING: $ac_header: check for missing prerequisite headers?" >&2;} + { $as_echo "$as_me:$LINENO: WARNING: $ac_header: see the Autoconf documentation" >&5 +$as_echo "$as_me: WARNING: $ac_header: see the Autoconf documentation" >&2;} + { $as_echo "$as_me:$LINENO: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&5 +$as_echo "$as_me: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&2;} + { $as_echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the preprocessor's result" >&5 +$as_echo "$as_me: WARNING: $ac_header: proceeding with the preprocessor's result" >&2;} + { $as_echo "$as_me:$LINENO: WARNING: $ac_header: in the future, the compiler will take precedence" >&5 +$as_echo "$as_me: WARNING: $ac_header: in the future, the compiler will take precedence" >&2;} + + ;; +esac +{ $as_echo "$as_me:$LINENO: checking for $ac_header" >&5 +$as_echo_n "checking for $ac_header... " >&6; } +if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then + $as_echo_n "(cached) " >&6 +else + eval "$as_ac_Header=\$ac_header_preproc" +fi +ac_res=`eval 'as_val=${'$as_ac_Header'} + $as_echo "$as_val"'` + { $as_echo "$as_me:$LINENO: result: $ac_res" >&5 +$as_echo "$ac_res" >&6; } + +fi +as_val=`eval 'as_val=${'$as_ac_Header'} + $as_echo "$as_val"'` + if test "x$as_val" = x""yes; then + cat >>confdefs.h <<_ACEOF +#define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1 +_ACEOF + +fi + +done + + +for ac_func in getpagesize +do +as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh` +{ $as_echo "$as_me:$LINENO: checking for $ac_func" >&5 +$as_echo_n "checking for $ac_func... " >&6; } +if { as_var=$as_ac_var; eval "test \"\${$as_var+set}\" = set"; }; then + $as_echo_n "(cached) " >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +/* Define $ac_func to an innocuous variant, in case declares $ac_func. + For example, HP-UX 11i declares gettimeofday. */ +#define $ac_func innocuous_$ac_func + +/* System header to define __stub macros and hopefully few prototypes, + which can conflict with char $ac_func (); below. + Prefer to if __STDC__ is defined, since + exists even on freestanding compilers. */ + +#ifdef __STDC__ +# include +#else +# include +#endif + +#undef $ac_func + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char $ac_func (); +/* The GNU C library defines this for functions which it implements + to always fail with ENOSYS. Some functions are actually named + something starting with __ and the normal name is an alias. */ +#if defined __stub_$ac_func || defined __stub___$ac_func +choke me +#endif + +int +main () +{ +return $ac_func (); + ; + return 0; +} +_ACEOF +rm -rf conftest.$ac_objext conftest$ac_exeext +if { (ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\"" +$as_echo "$ac_try_echo") >&5 + (eval "$ac_link") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -rf conftest.er1 + cat conftest.err >&5 + $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest$ac_exeext && { + test "$cross_compiling" = yes || + $as_test_x conftest$ac_exeext + }; then + eval "$as_ac_var=yes" +else + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + eval "$as_ac_var=no" +fi + +rm -rf conftest.dSYM +rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ + conftest$ac_exeext conftest.$ac_ext +fi +ac_res=`eval 'as_val=${'$as_ac_var'} + $as_echo "$as_val"'` + { $as_echo "$as_me:$LINENO: result: $ac_res" >&5 +$as_echo "$ac_res" >&6; } +as_val=`eval 'as_val=${'$as_ac_var'} + $as_echo "$as_val"'` + if test "x$as_val" = x""yes; then + cat >>confdefs.h <<_ACEOF +#define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1 +_ACEOF + +fi +done + +{ $as_echo "$as_me:$LINENO: checking for working mmap" >&5 +$as_echo_n "checking for working mmap... " >&6; } +if test "${ac_cv_func_mmap_fixed_mapped+set}" = set; then + $as_echo_n "(cached) " >&6 +else + if test "$cross_compiling" = yes; then + ac_cv_func_mmap_fixed_mapped=no +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +$ac_includes_default +/* malloc might have been renamed as rpl_malloc. */ +#undef malloc + +/* Thanks to Mike Haertel and Jim Avera for this test. + Here is a matrix of mmap possibilities: + mmap private not fixed + mmap private fixed at somewhere currently unmapped + mmap private fixed at somewhere already mapped + mmap shared not fixed + mmap shared fixed at somewhere currently unmapped + mmap shared fixed at somewhere already mapped + For private mappings, we should verify that changes cannot be read() + back from the file, nor mmap's back from the file at a different + address. (There have been systems where private was not correctly + implemented like the infamous i386 svr4.0, and systems where the + VM page cache was not coherent with the file system buffer cache + like early versions of FreeBSD and possibly contemporary NetBSD.) + For shared mappings, we should conversely verify that changes get + propagated back to all the places they're supposed to be. + + Grep wants private fixed already mapped. + The main things grep needs to know about mmap are: + * does it exist and is it safe to write into the mmap'd area + * how to use it (BSD variants) */ + +#include +#include + +#if !defined STDC_HEADERS && !defined HAVE_STDLIB_H +char *malloc (); +#endif + +/* This mess was copied from the GNU getpagesize.h. */ +#ifndef HAVE_GETPAGESIZE +/* Assume that all systems that can run configure have sys/param.h. */ +# ifndef HAVE_SYS_PARAM_H +# define HAVE_SYS_PARAM_H 1 +# endif + +# ifdef _SC_PAGESIZE +# define getpagesize() sysconf(_SC_PAGESIZE) +# else /* no _SC_PAGESIZE */ +# ifdef HAVE_SYS_PARAM_H +# include +# ifdef EXEC_PAGESIZE +# define getpagesize() EXEC_PAGESIZE +# else /* no EXEC_PAGESIZE */ +# ifdef NBPG +# define getpagesize() NBPG * CLSIZE +# ifndef CLSIZE +# define CLSIZE 1 +# endif /* no CLSIZE */ +# else /* no NBPG */ +# ifdef NBPC +# define getpagesize() NBPC +# else /* no NBPC */ +# ifdef PAGESIZE +# define getpagesize() PAGESIZE +# endif /* PAGESIZE */ +# endif /* no NBPC */ +# endif /* no NBPG */ +# endif /* no EXEC_PAGESIZE */ +# else /* no HAVE_SYS_PARAM_H */ +# define getpagesize() 8192 /* punt totally */ +# endif /* no HAVE_SYS_PARAM_H */ +# endif /* no _SC_PAGESIZE */ + +#endif /* no HAVE_GETPAGESIZE */ + +int +main () +{ + char *data, *data2, *data3; + int i, pagesize; + int fd; + + pagesize = getpagesize (); + + /* First, make a file with some known garbage in it. */ + data = (char *) malloc (pagesize); + if (!data) + return 1; + for (i = 0; i < pagesize; ++i) + *(data + i) = rand (); + umask (0); + fd = creat ("conftest.mmap", 0600); + if (fd < 0) + return 1; + if (write (fd, data, pagesize) != pagesize) + return 1; + close (fd); + + /* Next, try to mmap the file at a fixed address which already has + something else allocated at it. If we can, also make sure that + we see the same garbage. */ + fd = open ("conftest.mmap", O_RDWR); + if (fd < 0) + return 1; + data2 = (char *) malloc (2 * pagesize); + if (!data2) + return 1; + data2 += (pagesize - ((long int) data2 & (pagesize - 1))) & (pagesize - 1); + if (data2 != mmap (data2, pagesize, PROT_READ | PROT_WRITE, + MAP_PRIVATE | MAP_FIXED, fd, 0L)) + return 1; + for (i = 0; i < pagesize; ++i) + if (*(data + i) != *(data2 + i)) + return 1; + + /* Finally, make sure that changes to the mapped area do not + percolate back to the file as seen by read(). (This is a bug on + some variants of i386 svr4.0.) */ + for (i = 0; i < pagesize; ++i) + *(data2 + i) = *(data2 + i) + 1; + data3 = (char *) malloc (pagesize); + if (!data3) + return 1; + if (read (fd, data3, pagesize) != pagesize) + return 1; + for (i = 0; i < pagesize; ++i) + if (*(data + i) != *(data3 + i)) + return 1; + close (fd); + return 0; +} +_ACEOF +rm -rf conftest$ac_exeext +if { (ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\"" +$as_echo "$ac_try_echo") >&5 + (eval "$ac_link") 2>&5 + ac_status=$? + $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { ac_try='./conftest$ac_exeext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\"" +$as_echo "$ac_try_echo") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_func_mmap_fixed_mapped=yes +else + $as_echo "$as_me: program exited with status $ac_status" >&5 +$as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +( exit $ac_status ) +ac_cv_func_mmap_fixed_mapped=no +fi +rm -rf conftest.dSYM +rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext +fi + + +fi +{ $as_echo "$as_me:$LINENO: result: $ac_cv_func_mmap_fixed_mapped" >&5 +$as_echo "$ac_cv_func_mmap_fixed_mapped" >&6; } +if test $ac_cv_func_mmap_fixed_mapped = yes; then + +cat >>confdefs.h <<\_ACEOF +#define HAVE_MMAP 1 +_ACEOF + +fi +rm -rf conftest.mmap + + + + + + + + + + +for ac_header in argz.h limits.h locale.h nl_types.h malloc.h string.h \ +unistd.h sys/param.h +do +as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh` +if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then + { $as_echo "$as_me:$LINENO: checking for $ac_header" >&5 +$as_echo_n "checking for $ac_header... " >&6; } +if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then + $as_echo_n "(cached) " >&6 +fi +ac_res=`eval 'as_val=${'$as_ac_Header'} + $as_echo "$as_val"'` + { $as_echo "$as_me:$LINENO: result: $ac_res" >&5 +$as_echo "$ac_res" >&6; } +else + # Is the header compilable? +{ $as_echo "$as_me:$LINENO: checking $ac_header usability" >&5 +$as_echo_n "checking $ac_header usability... " >&6; } +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +$ac_includes_default +#include <$ac_header> +_ACEOF +rm -rf conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\"" +$as_echo "$ac_try_echo") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -rf conftest.er1 + cat conftest.err >&5 + $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest.$ac_objext; then + ac_header_compiler=yes +else + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_header_compiler=no +fi + +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +{ $as_echo "$as_me:$LINENO: result: $ac_header_compiler" >&5 +$as_echo "$ac_header_compiler" >&6; } + +# Is the header present? +{ $as_echo "$as_me:$LINENO: checking $ac_header presence" >&5 +$as_echo_n "checking $ac_header presence... " >&6; } +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include <$ac_header> +_ACEOF +if { (ac_try="$ac_cpp conftest.$ac_ext" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\"" +$as_echo "$ac_try_echo") >&5 + (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -rf conftest.er1 + cat conftest.err >&5 + $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } >/dev/null && { + test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" || + test ! -s conftest.err + }; then + ac_header_preproc=yes +else + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_header_preproc=no +fi + +rm -rf conftest.err conftest.$ac_ext +{ $as_echo "$as_me:$LINENO: result: $ac_header_preproc" >&5 +$as_echo "$ac_header_preproc" >&6; } + +# So? What about this header? +case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in + yes:no: ) + { $as_echo "$as_me:$LINENO: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&5 +$as_echo "$as_me: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&2;} + { $as_echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the compiler's result" >&5 +$as_echo "$as_me: WARNING: $ac_header: proceeding with the compiler's result" >&2;} + ac_header_preproc=yes + ;; + no:yes:* ) + { $as_echo "$as_me:$LINENO: WARNING: $ac_header: present but cannot be compiled" >&5 +$as_echo "$as_me: WARNING: $ac_header: present but cannot be compiled" >&2;} + { $as_echo "$as_me:$LINENO: WARNING: $ac_header: check for missing prerequisite headers?" >&5 +$as_echo "$as_me: WARNING: $ac_header: check for missing prerequisite headers?" >&2;} + { $as_echo "$as_me:$LINENO: WARNING: $ac_header: see the Autoconf documentation" >&5 +$as_echo "$as_me: WARNING: $ac_header: see the Autoconf documentation" >&2;} + { $as_echo "$as_me:$LINENO: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&5 +$as_echo "$as_me: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&2;} + { $as_echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the preprocessor's result" >&5 +$as_echo "$as_me: WARNING: $ac_header: proceeding with the preprocessor's result" >&2;} + { $as_echo "$as_me:$LINENO: WARNING: $ac_header: in the future, the compiler will take precedence" >&5 +$as_echo "$as_me: WARNING: $ac_header: in the future, the compiler will take precedence" >&2;} + + ;; +esac +{ $as_echo "$as_me:$LINENO: checking for $ac_header" >&5 +$as_echo_n "checking for $ac_header... " >&6; } +if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then + $as_echo_n "(cached) " >&6 +else + eval "$as_ac_Header=\$ac_header_preproc" +fi +ac_res=`eval 'as_val=${'$as_ac_Header'} + $as_echo "$as_val"'` + { $as_echo "$as_me:$LINENO: result: $ac_res" >&5 +$as_echo "$ac_res" >&6; } + +fi +as_val=`eval 'as_val=${'$as_ac_Header'} + $as_echo "$as_val"'` + if test "x$as_val" = x""yes; then + cat >>confdefs.h <<_ACEOF +#define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1 +_ACEOF + +fi + +done + + + + + + + + + + + + +for ac_func in getcwd munmap putenv setenv setlocale strchr strcasecmp \ +strdup __argz_count __argz_stringify __argz_next +do +as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh` +{ $as_echo "$as_me:$LINENO: checking for $ac_func" >&5 +$as_echo_n "checking for $ac_func... " >&6; } +if { as_var=$as_ac_var; eval "test \"\${$as_var+set}\" = set"; }; then + $as_echo_n "(cached) " >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +/* Define $ac_func to an innocuous variant, in case declares $ac_func. + For example, HP-UX 11i declares gettimeofday. */ +#define $ac_func innocuous_$ac_func + +/* System header to define __stub macros and hopefully few prototypes, + which can conflict with char $ac_func (); below. + Prefer to if __STDC__ is defined, since + exists even on freestanding compilers. */ + +#ifdef __STDC__ +# include +#else +# include +#endif + +#undef $ac_func + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char $ac_func (); +/* The GNU C library defines this for functions which it implements + to always fail with ENOSYS. Some functions are actually named + something starting with __ and the normal name is an alias. */ +#if defined __stub_$ac_func || defined __stub___$ac_func +choke me +#endif + +int +main () +{ +return $ac_func (); + ; + return 0; +} +_ACEOF +rm -rf conftest.$ac_objext conftest$ac_exeext +if { (ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\"" +$as_echo "$ac_try_echo") >&5 + (eval "$ac_link") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -rf conftest.er1 + cat conftest.err >&5 + $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest$ac_exeext && { + test "$cross_compiling" = yes || + $as_test_x conftest$ac_exeext + }; then + eval "$as_ac_var=yes" +else + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + eval "$as_ac_var=no" +fi + +rm -rf conftest.dSYM +rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ + conftest$ac_exeext conftest.$ac_ext +fi +ac_res=`eval 'as_val=${'$as_ac_var'} + $as_echo "$as_val"'` + { $as_echo "$as_me:$LINENO: result: $ac_res" >&5 +$as_echo "$ac_res" >&6; } +as_val=`eval 'as_val=${'$as_ac_var'} + $as_echo "$as_val"'` + if test "x$as_val" = x""yes; then + cat >>confdefs.h <<_ACEOF +#define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1 +_ACEOF + +fi +done + + + if test $ac_cv_header_locale_h = yes; then + { $as_echo "$as_me:$LINENO: checking for LC_MESSAGES" >&5 +$as_echo_n "checking for LC_MESSAGES... " >&6; } +if test "${am_cv_val_LC_MESSAGES+set}" = set; then + $as_echo_n "(cached) " >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include +int +main () +{ +return LC_MESSAGES + ; + return 0; +} +_ACEOF +rm -rf conftest.$ac_objext conftest$ac_exeext +if { (ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\"" +$as_echo "$ac_try_echo") >&5 + (eval "$ac_link") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -rf conftest.er1 + cat conftest.err >&5 + $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest$ac_exeext && { + test "$cross_compiling" = yes || + $as_test_x conftest$ac_exeext + }; then + am_cv_val_LC_MESSAGES=yes +else + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + am_cv_val_LC_MESSAGES=no +fi + +rm -rf conftest.dSYM +rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ + conftest$ac_exeext conftest.$ac_ext +fi +{ $as_echo "$as_me:$LINENO: result: $am_cv_val_LC_MESSAGES" >&5 +$as_echo "$am_cv_val_LC_MESSAGES" >&6; } + if test $am_cv_val_LC_MESSAGES = yes; then + +cat >>confdefs.h <<\_ACEOF +#define HAVE_LC_MESSAGES 1 +_ACEOF + + fi + fi + USE_NLS=yes + + + nls_cv_force_use_gnu_gettext="no" + + nls_cv_use_gnu_gettext="$nls_cv_force_use_gnu_gettext" + if test "$nls_cv_force_use_gnu_gettext" != "yes"; then + nls_cv_header_intl= + nls_cv_header_libgt= + CATOBJEXT=NONE + + if test "${ac_cv_header_libintl_h+set}" = set; then + { $as_echo "$as_me:$LINENO: checking for libintl.h" >&5 +$as_echo_n "checking for libintl.h... " >&6; } +if test "${ac_cv_header_libintl_h+set}" = set; then + $as_echo_n "(cached) " >&6 +fi +{ $as_echo "$as_me:$LINENO: result: $ac_cv_header_libintl_h" >&5 +$as_echo "$ac_cv_header_libintl_h" >&6; } +else + # Is the header compilable? +{ $as_echo "$as_me:$LINENO: checking libintl.h usability" >&5 +$as_echo_n "checking libintl.h usability... " >&6; } +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +$ac_includes_default +#include +_ACEOF +rm -rf conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\"" +$as_echo "$ac_try_echo") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -rf conftest.er1 + cat conftest.err >&5 + $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest.$ac_objext; then + ac_header_compiler=yes +else + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_header_compiler=no +fi + +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +{ $as_echo "$as_me:$LINENO: result: $ac_header_compiler" >&5 +$as_echo "$ac_header_compiler" >&6; } + +# Is the header present? +{ $as_echo "$as_me:$LINENO: checking libintl.h presence" >&5 +$as_echo_n "checking libintl.h presence... " >&6; } +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include +_ACEOF +if { (ac_try="$ac_cpp conftest.$ac_ext" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\"" +$as_echo "$ac_try_echo") >&5 + (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -rf conftest.er1 + cat conftest.err >&5 + $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } >/dev/null && { + test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" || + test ! -s conftest.err + }; then + ac_header_preproc=yes +else + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_header_preproc=no +fi + +rm -rf conftest.err conftest.$ac_ext +{ $as_echo "$as_me:$LINENO: result: $ac_header_preproc" >&5 +$as_echo "$ac_header_preproc" >&6; } + +# So? What about this header? +case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in + yes:no: ) + { $as_echo "$as_me:$LINENO: WARNING: libintl.h: accepted by the compiler, rejected by the preprocessor!" >&5 +$as_echo "$as_me: WARNING: libintl.h: accepted by the compiler, rejected by the preprocessor!" >&2;} + { $as_echo "$as_me:$LINENO: WARNING: libintl.h: proceeding with the compiler's result" >&5 +$as_echo "$as_me: WARNING: libintl.h: proceeding with the compiler's result" >&2;} + ac_header_preproc=yes + ;; + no:yes:* ) + { $as_echo "$as_me:$LINENO: WARNING: libintl.h: present but cannot be compiled" >&5 +$as_echo "$as_me: WARNING: libintl.h: present but cannot be compiled" >&2;} + { $as_echo "$as_me:$LINENO: WARNING: libintl.h: check for missing prerequisite headers?" >&5 +$as_echo "$as_me: WARNING: libintl.h: check for missing prerequisite headers?" >&2;} + { $as_echo "$as_me:$LINENO: WARNING: libintl.h: see the Autoconf documentation" >&5 +$as_echo "$as_me: WARNING: libintl.h: see the Autoconf documentation" >&2;} + { $as_echo "$as_me:$LINENO: WARNING: libintl.h: section \"Present But Cannot Be Compiled\"" >&5 +$as_echo "$as_me: WARNING: libintl.h: section \"Present But Cannot Be Compiled\"" >&2;} + { $as_echo "$as_me:$LINENO: WARNING: libintl.h: proceeding with the preprocessor's result" >&5 +$as_echo "$as_me: WARNING: libintl.h: proceeding with the preprocessor's result" >&2;} + { $as_echo "$as_me:$LINENO: WARNING: libintl.h: in the future, the compiler will take precedence" >&5 +$as_echo "$as_me: WARNING: libintl.h: in the future, the compiler will take precedence" >&2;} + + ;; +esac +{ $as_echo "$as_me:$LINENO: checking for libintl.h" >&5 +$as_echo_n "checking for libintl.h... " >&6; } +if test "${ac_cv_header_libintl_h+set}" = set; then + $as_echo_n "(cached) " >&6 +else + ac_cv_header_libintl_h=$ac_header_preproc +fi +{ $as_echo "$as_me:$LINENO: result: $ac_cv_header_libintl_h" >&5 +$as_echo "$ac_cv_header_libintl_h" >&6; } + +fi +if test "x$ac_cv_header_libintl_h" = x""yes; then + { $as_echo "$as_me:$LINENO: checking for dgettext in libc" >&5 +$as_echo_n "checking for dgettext in libc... " >&6; } +if test "${gt_cv_func_dgettext_libc+set}" = set; then + $as_echo_n "(cached) " >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include +int +main () +{ +return (int) dgettext ("","") + ; + return 0; +} +_ACEOF +rm -rf conftest.$ac_objext conftest$ac_exeext +if { (ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\"" +$as_echo "$ac_try_echo") >&5 + (eval "$ac_link") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -rf conftest.er1 + cat conftest.err >&5 + $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest$ac_exeext && { + test "$cross_compiling" = yes || + $as_test_x conftest$ac_exeext + }; then + gt_cv_func_dgettext_libc=yes +else + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + gt_cv_func_dgettext_libc=no +fi + +rm -rf conftest.dSYM +rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ + conftest$ac_exeext conftest.$ac_ext +fi +{ $as_echo "$as_me:$LINENO: result: $gt_cv_func_dgettext_libc" >&5 +$as_echo "$gt_cv_func_dgettext_libc" >&6; } + + if test "$gt_cv_func_dgettext_libc" != "yes"; then + { $as_echo "$as_me:$LINENO: checking for bindtextdomain in -lintl" >&5 +$as_echo_n "checking for bindtextdomain in -lintl... " >&6; } +if test "${ac_cv_lib_intl_bindtextdomain+set}" = set; then + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lintl $LIBS" +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char bindtextdomain (); +int +main () +{ +return bindtextdomain (); + ; + return 0; +} +_ACEOF +rm -rf conftest.$ac_objext conftest$ac_exeext +if { (ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\"" +$as_echo "$ac_try_echo") >&5 + (eval "$ac_link") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -rf conftest.er1 + cat conftest.err >&5 + $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest$ac_exeext && { + test "$cross_compiling" = yes || + $as_test_x conftest$ac_exeext + }; then + ac_cv_lib_intl_bindtextdomain=yes +else + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_cv_lib_intl_bindtextdomain=no +fi + +rm -rf conftest.dSYM +rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:$LINENO: result: $ac_cv_lib_intl_bindtextdomain" >&5 +$as_echo "$ac_cv_lib_intl_bindtextdomain" >&6; } +if test "x$ac_cv_lib_intl_bindtextdomain" = x""yes; then + { $as_echo "$as_me:$LINENO: checking for dgettext in libintl" >&5 +$as_echo_n "checking for dgettext in libintl... " >&6; } +if test "${gt_cv_func_dgettext_libintl+set}" = set; then + $as_echo_n "(cached) " >&6 +else + { $as_echo "$as_me:$LINENO: checking for dgettext in -lintl" >&5 +$as_echo_n "checking for dgettext in -lintl... " >&6; } +if test "${ac_cv_lib_intl_dgettext+set}" = set; then + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lintl $LIBS" +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char dgettext (); +int +main () +{ +return dgettext (); + ; + return 0; +} +_ACEOF +rm -rf conftest.$ac_objext conftest$ac_exeext +if { (ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\"" +$as_echo "$ac_try_echo") >&5 + (eval "$ac_link") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -rf conftest.er1 + cat conftest.err >&5 + $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest$ac_exeext && { + test "$cross_compiling" = yes || + $as_test_x conftest$ac_exeext + }; then + ac_cv_lib_intl_dgettext=yes +else + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_cv_lib_intl_dgettext=no +fi + +rm -rf conftest.dSYM +rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:$LINENO: result: $ac_cv_lib_intl_dgettext" >&5 +$as_echo "$ac_cv_lib_intl_dgettext" >&6; } +if test "x$ac_cv_lib_intl_dgettext" = x""yes; then + gt_cv_func_dgettext_libintl=yes +else + gt_cv_func_dgettext_libintl=no +fi + +fi +{ $as_echo "$as_me:$LINENO: result: $gt_cv_func_dgettext_libintl" >&5 +$as_echo "$gt_cv_func_dgettext_libintl" >&6; } +fi + + fi + + if test "$gt_cv_func_dgettext_libintl" = "yes"; then + LIBS="$LIBS -lintl"; + fi + + if test "$gt_cv_func_dgettext_libc" = "yes" \ + || test "$gt_cv_func_dgettext_libintl" = "yes"; then + +cat >>confdefs.h <<\_ACEOF +#define HAVE_GETTEXT 1 +_ACEOF + + # Extract the first word of "msgfmt", so it can be a program name with args. +set dummy msgfmt; ac_word=$2 +{ $as_echo "$as_me:$LINENO: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if test "${ac_cv_path_MSGFMT+set}" = set; then + $as_echo_n "(cached) " >&6 +else + case "$MSGFMT" in + /*) + ac_cv_path_MSGFMT="$MSGFMT" # Let the user override the test with a path. + ;; + *) + IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS="${IFS}:" + for ac_dir in $PATH; do + test -z "$ac_dir" && ac_dir=. + if test -f $ac_dir/$ac_word; then + if test -z "`$ac_dir/$ac_word -h 2>&1 | grep 'dv '`"; then + ac_cv_path_MSGFMT="$ac_dir/$ac_word" + break + fi + fi + done + IFS="$ac_save_ifs" + test -z "$ac_cv_path_MSGFMT" && ac_cv_path_MSGFMT="no" + ;; +esac +fi +MSGFMT="$ac_cv_path_MSGFMT" +if test -n "$MSGFMT"; then + { $as_echo "$as_me:$LINENO: result: $MSGFMT" >&5 +$as_echo "$MSGFMT" >&6; } +else + { $as_echo "$as_me:$LINENO: result: no" >&5 +$as_echo "no" >&6; } +fi + if test "$MSGFMT" != "no"; then + +for ac_func in dcgettext +do +as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh` +{ $as_echo "$as_me:$LINENO: checking for $ac_func" >&5 +$as_echo_n "checking for $ac_func... " >&6; } +if { as_var=$as_ac_var; eval "test \"\${$as_var+set}\" = set"; }; then + $as_echo_n "(cached) " >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +/* Define $ac_func to an innocuous variant, in case declares $ac_func. + For example, HP-UX 11i declares gettimeofday. */ +#define $ac_func innocuous_$ac_func + +/* System header to define __stub macros and hopefully few prototypes, + which can conflict with char $ac_func (); below. + Prefer to if __STDC__ is defined, since + exists even on freestanding compilers. */ + +#ifdef __STDC__ +# include +#else +# include +#endif + +#undef $ac_func + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char $ac_func (); +/* The GNU C library defines this for functions which it implements + to always fail with ENOSYS. Some functions are actually named + something starting with __ and the normal name is an alias. */ +#if defined __stub_$ac_func || defined __stub___$ac_func +choke me +#endif + +int +main () +{ +return $ac_func (); + ; + return 0; +} +_ACEOF +rm -rf conftest.$ac_objext conftest$ac_exeext +if { (ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\"" +$as_echo "$ac_try_echo") >&5 + (eval "$ac_link") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -rf conftest.er1 + cat conftest.err >&5 + $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest$ac_exeext && { + test "$cross_compiling" = yes || + $as_test_x conftest$ac_exeext + }; then + eval "$as_ac_var=yes" +else + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + eval "$as_ac_var=no" +fi + +rm -rf conftest.dSYM +rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ + conftest$ac_exeext conftest.$ac_ext +fi +ac_res=`eval 'as_val=${'$as_ac_var'} + $as_echo "$as_val"'` + { $as_echo "$as_me:$LINENO: result: $ac_res" >&5 +$as_echo "$ac_res" >&6; } +as_val=`eval 'as_val=${'$as_ac_var'} + $as_echo "$as_val"'` + if test "x$as_val" = x""yes; then + cat >>confdefs.h <<_ACEOF +#define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1 +_ACEOF + +fi +done + + # Extract the first word of "gmsgfmt", so it can be a program name with args. +set dummy gmsgfmt; ac_word=$2 +{ $as_echo "$as_me:$LINENO: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if test "${ac_cv_path_GMSGFMT+set}" = set; then + $as_echo_n "(cached) " >&6 +else + case $GMSGFMT in + [\\/]* | ?:[\\/]*) + ac_cv_path_GMSGFMT="$GMSGFMT" # Let the user override the test with a path. + ;; + *) + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_path_GMSGFMT="$as_dir/$ac_word$ac_exec_ext" + $as_echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done +IFS=$as_save_IFS + + test -z "$ac_cv_path_GMSGFMT" && ac_cv_path_GMSGFMT="$MSGFMT" + ;; +esac +fi +GMSGFMT=$ac_cv_path_GMSGFMT +if test -n "$GMSGFMT"; then + { $as_echo "$as_me:$LINENO: result: $GMSGFMT" >&5 +$as_echo "$GMSGFMT" >&6; } +else + { $as_echo "$as_me:$LINENO: result: no" >&5 +$as_echo "no" >&6; } +fi + + + # Extract the first word of "xgettext", so it can be a program name with args. +set dummy xgettext; ac_word=$2 +{ $as_echo "$as_me:$LINENO: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if test "${ac_cv_path_XGETTEXT+set}" = set; then + $as_echo_n "(cached) " >&6 +else + case "$XGETTEXT" in + /*) + ac_cv_path_XGETTEXT="$XGETTEXT" # Let the user override the test with a path. + ;; + *) + IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS="${IFS}:" + for ac_dir in $PATH; do + test -z "$ac_dir" && ac_dir=. + if test -f $ac_dir/$ac_word; then + if test -z "`$ac_dir/$ac_word -h 2>&1 | grep '(HELP)'`"; then + ac_cv_path_XGETTEXT="$ac_dir/$ac_word" + break + fi + fi + done + IFS="$ac_save_ifs" + test -z "$ac_cv_path_XGETTEXT" && ac_cv_path_XGETTEXT=":" + ;; +esac +fi +XGETTEXT="$ac_cv_path_XGETTEXT" +if test -n "$XGETTEXT"; then + { $as_echo "$as_me:$LINENO: result: $XGETTEXT" >&5 +$as_echo "$XGETTEXT" >&6; } +else + { $as_echo "$as_me:$LINENO: result: no" >&5 +$as_echo "no" >&6; } +fi + + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +int +main () +{ +extern int _nl_msg_cat_cntr; + return _nl_msg_cat_cntr + ; + return 0; +} +_ACEOF +rm -rf conftest.$ac_objext conftest$ac_exeext +if { (ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\"" +$as_echo "$ac_try_echo") >&5 + (eval "$ac_link") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -rf conftest.er1 + cat conftest.err >&5 + $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest$ac_exeext && { + test "$cross_compiling" = yes || + $as_test_x conftest$ac_exeext + }; then + CATOBJEXT=.gmo + DATADIRNAME=share +else + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + CATOBJEXT=.mo + DATADIRNAME=lib +fi + +rm -rf conftest.dSYM +rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ + conftest$ac_exeext conftest.$ac_ext + INSTOBJEXT=.mo + fi + fi + + # Added by Martin Baulig 12/15/98 for libc5 systems + if test "$gt_cv_func_dgettext_libc" != "yes" \ + && test "$gt_cv_func_dgettext_libintl" = "yes"; then + INTLLIBS=-lintl + LIBS=`echo $LIBS | sed -e 's/-lintl//'` + fi + +fi + + + + if test "$CATOBJEXT" = "NONE"; then + nls_cv_use_gnu_gettext=yes + fi + fi + + if test "$nls_cv_use_gnu_gettext" != "yes"; then + +cat >>confdefs.h <<\_ACEOF +#define ENABLE_NLS 1 +_ACEOF + + else + CATOBJEXT= + fi + + if test "$XGETTEXT" != ":"; then + if $XGETTEXT --omit-header /dev/null 2> /dev/null; then + : ; + else + { $as_echo "$as_me:$LINENO: result: found xgettext program is not GNU xgettext; ignore it" >&5 +$as_echo "found xgettext program is not GNU xgettext; ignore it" >&6; } + XGETTEXT=":" + fi + fi + + # We need to process the po/ directory. + POSUB=po + + ac_config_commands="$ac_config_commands default-2" + + + for lang in $ALL_LINGUAS; do + GMOFILES="$GMOFILES $lang.gmo" + POFILES="$POFILES $lang.po" + done + + + + + + + + + + + + + + if test "x$CATOBJEXT" != "x"; then + if test "x$ALL_LINGUAS" = "x"; then + LINGUAS= + else + { $as_echo "$as_me:$LINENO: checking for catalogs to be installed" >&5 +$as_echo_n "checking for catalogs to be installed... " >&6; } + NEW_LINGUAS= + for lang in ${LINGUAS=$ALL_LINGUAS}; do + case "$ALL_LINGUAS" in + *$lang*) NEW_LINGUAS="$NEW_LINGUAS $lang" ;; + esac + done + LINGUAS=$NEW_LINGUAS + { $as_echo "$as_me:$LINENO: result: $LINGUAS" >&5 +$as_echo "$LINGUAS" >&6; } + fi + + if test -n "$LINGUAS"; then + for lang in $LINGUAS; do CATALOGS="$CATALOGS $lang$CATOBJEXT"; done + fi + fi + + test -d po || mkdir po + if test "$CATOBJEXT" = ".cat"; then + if test "${ac_cv_header_linux_version_h+set}" = set; then + { $as_echo "$as_me:$LINENO: checking for linux/version.h" >&5 +$as_echo_n "checking for linux/version.h... " >&6; } +if test "${ac_cv_header_linux_version_h+set}" = set; then + $as_echo_n "(cached) " >&6 +fi +{ $as_echo "$as_me:$LINENO: result: $ac_cv_header_linux_version_h" >&5 +$as_echo "$ac_cv_header_linux_version_h" >&6; } +else + # Is the header compilable? +{ $as_echo "$as_me:$LINENO: checking linux/version.h usability" >&5 +$as_echo_n "checking linux/version.h usability... " >&6; } +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +$ac_includes_default +#include +_ACEOF +rm -rf conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\"" +$as_echo "$ac_try_echo") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -rf conftest.er1 + cat conftest.err >&5 + $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest.$ac_objext; then + ac_header_compiler=yes +else + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_header_compiler=no +fi + +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +{ $as_echo "$as_me:$LINENO: result: $ac_header_compiler" >&5 +$as_echo "$ac_header_compiler" >&6; } + +# Is the header present? +{ $as_echo "$as_me:$LINENO: checking linux/version.h presence" >&5 +$as_echo_n "checking linux/version.h presence... " >&6; } +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include +_ACEOF +if { (ac_try="$ac_cpp conftest.$ac_ext" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\"" +$as_echo "$ac_try_echo") >&5 + (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -rf conftest.er1 + cat conftest.err >&5 + $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } >/dev/null && { + test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" || + test ! -s conftest.err + }; then + ac_header_preproc=yes +else + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_header_preproc=no +fi + +rm -rf conftest.err conftest.$ac_ext +{ $as_echo "$as_me:$LINENO: result: $ac_header_preproc" >&5 +$as_echo "$ac_header_preproc" >&6; } + +# So? What about this header? +case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in + yes:no: ) + { $as_echo "$as_me:$LINENO: WARNING: linux/version.h: accepted by the compiler, rejected by the preprocessor!" >&5 +$as_echo "$as_me: WARNING: linux/version.h: accepted by the compiler, rejected by the preprocessor!" >&2;} + { $as_echo "$as_me:$LINENO: WARNING: linux/version.h: proceeding with the compiler's result" >&5 +$as_echo "$as_me: WARNING: linux/version.h: proceeding with the compiler's result" >&2;} + ac_header_preproc=yes + ;; + no:yes:* ) + { $as_echo "$as_me:$LINENO: WARNING: linux/version.h: present but cannot be compiled" >&5 +$as_echo "$as_me: WARNING: linux/version.h: present but cannot be compiled" >&2;} + { $as_echo "$as_me:$LINENO: WARNING: linux/version.h: check for missing prerequisite headers?" >&5 +$as_echo "$as_me: WARNING: linux/version.h: check for missing prerequisite headers?" >&2;} + { $as_echo "$as_me:$LINENO: WARNING: linux/version.h: see the Autoconf documentation" >&5 +$as_echo "$as_me: WARNING: linux/version.h: see the Autoconf documentation" >&2;} + { $as_echo "$as_me:$LINENO: WARNING: linux/version.h: section \"Present But Cannot Be Compiled\"" >&5 +$as_echo "$as_me: WARNING: linux/version.h: section \"Present But Cannot Be Compiled\"" >&2;} + { $as_echo "$as_me:$LINENO: WARNING: linux/version.h: proceeding with the preprocessor's result" >&5 +$as_echo "$as_me: WARNING: linux/version.h: proceeding with the preprocessor's result" >&2;} + { $as_echo "$as_me:$LINENO: WARNING: linux/version.h: in the future, the compiler will take precedence" >&5 +$as_echo "$as_me: WARNING: linux/version.h: in the future, the compiler will take precedence" >&2;} + + ;; +esac +{ $as_echo "$as_me:$LINENO: checking for linux/version.h" >&5 +$as_echo_n "checking for linux/version.h... " >&6; } +if test "${ac_cv_header_linux_version_h+set}" = set; then + $as_echo_n "(cached) " >&6 +else + ac_cv_header_linux_version_h=$ac_header_preproc +fi +{ $as_echo "$as_me:$LINENO: result: $ac_cv_header_linux_version_h" >&5 +$as_echo "$ac_cv_header_linux_version_h" >&6; } + +fi +if test "x$ac_cv_header_linux_version_h" = x""yes; then + msgformat=linux +else + msgformat=xopen +fi + + + + sed -e '/^#/d' $srcdir/po/$msgformat-msg.sed > po/po2msg.sed + fi + + MKINSTALLDIRS= +# +# jwz: fuck this! it puts hardcoded pathnames into the generated Makefiles! +# +# if test -n "$ac_aux_dir"; then +# MKINSTALLDIRS="$ac_aux_dir/mkinstalldirs" +# fi + if test -z "$MKINSTALLDIRS"; then + MKINSTALLDIRS="\$(top_srcdir)/mkinstalldirs" + fi + + # jwz: you know what, screw it. Let's just use the version that I + # already computed in configure.in, instead of this version that came + # with the i18n crud, ok? + MKINSTALLDIRS="$INSTALL_DIRS" + + + + + test -d po || mkdir po + if test "x$srcdir" != "x."; then + if test "x`echo $srcdir | sed 's@/.*@@'`" = "x"; then + posrcprefix="$srcdir/" + else + posrcprefix="../$srcdir/" + fi + else + posrcprefix="../" + fi + rm -f po/POTFILES + sed -e "/^#/d" -e "/^\$/d" -e "s,.*, $posrcprefix& \\\\," -e "\$s/\(.*\) \\\\/\1/" \ + < $srcdir/po/POTFILES.in > po/POTFILES + +MKINSTALLDIRS="$INSTALL_DIRS" + + +############################################################################### +# +# Check for -lXmu (some fucked up vendors don't ship it...) +# +############################################################################### + +have_xmu=no + + ac_save_CPPFLAGS="$CPPFLAGS" + if test \! -z "$includedir" ; then + CPPFLAGS="$CPPFLAGS -I$includedir" + fi + CPPFLAGS="$CPPFLAGS $X_CFLAGS" + CPPFLAGS=`eval eval eval eval eval eval eval eval eval echo $CPPFLAGS` + { $as_echo "$as_me:$LINENO: checking for X11/Xmu/Error.h" >&5 +$as_echo_n "checking for X11/Xmu/Error.h... " >&6; } +if test "${ac_cv_header_X11_Xmu_Error_h+set}" = set; then + $as_echo_n "(cached) " >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include + #include + #include + +#include +_ACEOF +rm -rf conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\"" +$as_echo "$ac_try_echo") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -rf conftest.er1 + cat conftest.err >&5 + $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest.$ac_objext; then + ac_cv_header_X11_Xmu_Error_h=yes +else + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_cv_header_X11_Xmu_Error_h=no +fi + +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +{ $as_echo "$as_me:$LINENO: result: $ac_cv_header_X11_Xmu_Error_h" >&5 +$as_echo "$ac_cv_header_X11_Xmu_Error_h" >&6; } +if test "x$ac_cv_header_X11_Xmu_Error_h" = x""yes; then + have_xmu=yes +fi + + + CPPFLAGS="$ac_save_CPPFLAGS" +if test "$have_xmu" = no ; then + XMU_SRCS='$(UTILS_SRC)/xmu.c' + XMU_OBJS='$(UTILS_BIN)/xmu.o' + XMU_LIBS='' +else + XMU_SRCS='' + XMU_OBJS='' + XMU_LIBS='-lXmu' + cat >>confdefs.h <<\_ACEOF +#define HAVE_XMU 1 +_ACEOF + +fi + + +############################################################################### +# +# Check for the SunOS 4.1.x _get_wmShellWidgetClass bug. +# See comp.windows.x FAQ question 124. The right fix is to +# get OpenWindows 3.0 patches 100512-02 and 100573-03. +# +############################################################################### + +if test "$have_xmu" = yes ; then + case "$host" in + *-sunos4*) + { $as_echo "$as_me:$LINENO: checking for the SunOS 4.1.x _get_wmShellWidgetClass bug" >&5 +$as_echo_n "checking for the SunOS 4.1.x _get_wmShellWidgetClass bug... " >&6; } +if test "${ac_cv_sunos_xmu_bug+set}" = set; then + $as_echo_n "(cached) " >&6 +else + ac_save_LDFLAGS="$LDFLAGS" + if test \! -z "$x_libraries" ; then + LDFLAGS="$LDFLAGS -L$x_libraries" + fi + # Note: this trick never works! (Generally.) + # We're only getting away with using AC_TRY_LINK + # with X libraries because we know it's SunOS. + LDFLAGS="$LDFLAGS -lXmu -lXt -lX11 -lXext -lm" + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +rm -rf conftest.$ac_objext conftest$ac_exeext +if { (ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\"" +$as_echo "$ac_try_echo") >&5 + (eval "$ac_link") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -rf conftest.er1 + cat conftest.err >&5 + $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest$ac_exeext && { + test "$cross_compiling" = yes || + $as_test_x conftest$ac_exeext + }; then + ac_cv_sunos_xmu_bug=no +else + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_cv_sunos_xmu_bug=yes +fi + +rm -rf conftest.dSYM +rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ + conftest$ac_exeext conftest.$ac_ext + LDFLAGS="$ac_save_LDFLAGS" +fi +{ $as_echo "$as_me:$LINENO: result: $ac_cv_sunos_xmu_bug" >&5 +$as_echo "$ac_cv_sunos_xmu_bug" >&6; } + if test "$ac_cv_sunos_xmu_bug" = yes ; then + { $as_echo "$as_me:$LINENO: checking whether the compiler understands -static" >&5 +$as_echo_n "checking whether the compiler understands -static... " >&6; } +if test "${ac_cv_ld_static+set}" = set; then + $as_echo_n "(cached) " >&6 +else + ac_save_LDFLAGS="$LDFLAGS" + LDFLAGS="$LDFLAGS -static" + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +rm -rf conftest.$ac_objext conftest$ac_exeext +if { (ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\"" +$as_echo "$ac_try_echo") >&5 + (eval "$ac_link") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -rf conftest.er1 + cat conftest.err >&5 + $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest$ac_exeext && { + test "$cross_compiling" = yes || + $as_test_x conftest$ac_exeext + }; then + ac_cv_ld_static=yes +else + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_cv_ld_static=no +fi + +rm -rf conftest.dSYM +rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ + conftest$ac_exeext conftest.$ac_ext + LDFLAGS="$ac_save_LDFLAGS" +fi +{ $as_echo "$as_me:$LINENO: result: $ac_cv_ld_static" >&5 +$as_echo "$ac_cv_ld_static" >&6; } + if test "$ac_cv_ld_static" = yes ; then + LDFLAGS="$LDFLAGS -static" + else + LDFLAGS="$LDFLAGS -Bstatic" + fi + fi + ;; + esac +fi + + +############################################################################### +# +# Handle the --with-hackdir option +# +############################################################################### + +have_hackdir=yes +with_hackdir_req=unspecified + +# Check whether --with-hackdir was given. +if test "${with_hackdir+set}" = set; then + withval=$with_hackdir; with_hackdir="$withval"; with_hackdir_req="$withval" +else + with_hackdir=yes +fi + + +if test x"$with_hackdir" = xyes; then + HACKDIR='${libexecdir}/xscreensaver' +elif test x"$with_hackdir" = xno; then + HACKDIR='${bindir}' +else + HACKDIR=$with_hackdir +fi + +# canonicalize slashes. +HACKDIR=`echo "${HACKDIR}" | sed 's@/$@@;s@//*@/@g'` + +# Expand HACKDIR as HACKDIR_FULL +HACKDIR_FULL=`eval eval eval eval eval eval eval eval eval echo $HACKDIR` + +# This option used to be called --enable-subdir; make sure that is no longer +# used, since configure brain-damagedly ignores unknown --enable options. + +obsolete_enable= +# Check whether --enable-subdir was given. +if test "${enable_subdir+set}" = set; then + enableval=$enable_subdir; obsolete_enable=yes +fi + +if test -n "$obsolete_enable"; then + echo "error: the --enable-subdir option has been replaced with" + echo " the new --with-hackdir option; see \`configure --help'" + echo " for more information." + exit 1 +fi + + +############################################################################### +# +# Handle the --with-configdir option +# Help for --with-x-app-defaults option added. +# +############################################################################### + +have_configdir=yes +with_configdir_req=unspecified + +# Check whether --with-configdir was given. +if test "${with_configdir+set}" = set; then + withval=$with_configdir; with_configdir="$withval"; with_configdir_req="$withval" +else + with_configdir=yes +fi + + +if test x"$with_configdir" = xyes; then + HACK_CONF_DIR='${datadir}/xscreensaver/config' +elif test x"$with_configdir" = xno; then + echo "error: must be yes, or a pathname: --with-configdir=$with_configdir" + exit 1 +else + # there must be a better way than this... + if test -z "`echo $with_configdir | sed 's@^/.*@@'`" ; then + # absolute path + HACK_CONF_DIR=$with_configdir + else + # relative path + HACK_CONF_DIR="\${exec_prefix}$with_configdir" + fi +fi + + + + +############################################################################### +# +# Check for the SGI SCREEN_SAVER server extension. +# +############################################################################### + +#have_sgi=no +#with_sgi_req=unspecified +#AC_ARG_WITH(sgi-ext, +#[Except where noted, all of the --with options below can also take a +#directory argument: for example, `--with-motif=/opt/Motif'. That would +#cause /opt/Motif/include/ to be added to the -I list, and /opt/Motif/lib/ +#to be added to the -L list, assuming those directories exist. +# +#By default, support for each of these options will be built in, if the +#relevant library routines exist. At run time, they will then be used +#only if the X server being used supports them. Each --with option has +#a corresponding --without option, to override building support for them +#at all. +# +#Screen blanking and idle-detection options: +# +# --with-sgi-ext Include support for the SGI SCREEN_SAVER extension.], +# [with_sgi="$withval"; with_sgi_req="$withval"],[with_sgi=yes]) +# +#HANDLE_X_PATH_ARG(with_sgi, --with-sgi-ext, SGI SCREEN_SAVER) +# +#if test "$with_sgi" = yes; then +# AC_CHECK_X_HEADER(X11/extensions/XScreenSaver.h, +# [have_sgi=yes +# AC_DEFINE(HAVE_SGI_SAVER_EXTENSION)],, +# [#include ]) +# +#elif test "$with_sgi" != no; then +# echo "error: must be yes or no: --with-sgi-ext=$with_sgi" +# exit 1 +#fi + + +############################################################################### +# +# Check for the XIDLE server extension. +# +############################################################################### + +#have_xidle=no +#with_xidle_req=unspecified +#AC_ARG_WITH(xidle-ext, +#[ --with-xidle-ext Include support for the XIDLE extension.], +# [with_xidle="$withval"; with_xidle_req="$withval"],[with_xidle=yes]) +# +#HANDLE_X_PATH_ARG(with_xidle, --with-xidle-ext, XIDLE) +# +#if test "$with_xidle" = yes; then +# AC_CHECK_X_HEADER(X11/extensions/xidle.h, +# [have_xidle=yes +# AC_DEFINE(HAVE_XIDLE_EXTENSION)],, +# [#include ]) +#elif test "$with_xidle" != no; then +# echo "error: must be yes or no: --with-xidle-ext=$with_xidle" +# exit 1 +#fi + + +############################################################################### +# +# Check for the SGI-VIDEO-CONTROL server extension. +# +############################################################################### + +#have_sgivc=no +#with_sgivc_req=unspecified +#AC_ARG_WITH(sgivc-ext, +#[ --with-sgivc-ext Include support for the SGI-VIDEO-CONTROL extension.], +# [with_sgivc="$withval"; with_sgivc_req="$withval"],[with_sgivc=yes]) +# +#HANDLE_X_PATH_ARG(with_sgivc, --with-sgivc-ext, SGI-VIDEO-CONTROL) +# +#if test "$with_sgivc" = yes; then +# +# # first check for XSGIvc.h +# AC_CHECK_X_HEADER(X11/extensions/XSGIvc.h, [have_sgivc=yes],, +# [#include ]) +# +# # if that succeeded, then check for the -lXsgivc +# if test "$have_sgivc" = yes; then +# have_sgivc=no +# AC_CHECK_X_LIB(Xsgivc, XSGIvcQueryGammaMap, +# [have_sgivc=yes; SAVER_LIBS="$SAVER_LIBS -lXsgivc"], [true], +# -lXext -lX11) +# fi +# +# # if that succeeded, then we've really got it. +# if test "$have_sgivc" = yes; then +# AC_DEFINE(HAVE_SGI_VC_EXTENSION) +# fi +# +#elif test "$with_sgivc" != no; then +# echo "error: must be yes or no: --with-sgivc-ext=$with_sgivc" +# exit 1 +#fi + + +############################################################################### +# +# Check for the DPMS server extension. +# +############################################################################### + +have_dpms=no +with_dpms_req=unspecified + +# Check whether --with-dpms-ext was given. +if test "${with_dpms_ext+set}" = set; then + withval=$with_dpms_ext; with_dpms="$withval"; with_dpms_req="$withval" +else + with_dpms=yes +fi + + + + case "$with_dpms" in + yes) ;; + no) ;; + + /*) + { $as_echo "$as_me:$LINENO: checking for DPMS headers" >&5 +$as_echo_n "checking for DPMS headers... " >&6; } + d=$with_dpms/include + if test -d $d; then + X_CFLAGS="-I$d $X_CFLAGS" + { $as_echo "$as_me:$LINENO: result: $d" >&5 +$as_echo "$d" >&6; } + else + { $as_echo "$as_me:$LINENO: result: not found ($d: no such directory)" >&5 +$as_echo "not found ($d: no such directory)" >&6; } + fi + + { $as_echo "$as_me:$LINENO: checking for DPMS libs" >&5 +$as_echo_n "checking for DPMS libs... " >&6; } + d=$with_dpms/lib + if test -d $d; then + X_LIBS="-L$d $X_LIBS" + { $as_echo "$as_me:$LINENO: result: $d" >&5 +$as_echo "$d" >&6; } + else + { $as_echo "$as_me:$LINENO: result: not found ($d: no such directory)" >&5 +$as_echo "not found ($d: no such directory)" >&6; } + fi + + # replace the directory string with "yes". + with_dpms_req="yes" + with_dpms=$with_dpms_req + ;; + + *) + echo "" + echo "error: argument to --with-dpms-ext must be \"yes\", \"no\", or a directory." + echo " If it is a directory, then \`DIR/include' will be added to" + echo " the -I list, and \`DIR/lib' will be added to the -L list." + exit 1 + ;; + esac + + +if test "$with_dpms" = yes; then + + # first check for dpms.h + + ac_save_CPPFLAGS="$CPPFLAGS" + if test \! -z "$includedir" ; then + CPPFLAGS="$CPPFLAGS -I$includedir" + fi + CPPFLAGS="$CPPFLAGS $X_CFLAGS" + CPPFLAGS=`eval eval eval eval eval eval eval eval eval echo $CPPFLAGS` + { $as_echo "$as_me:$LINENO: checking for X11/extensions/dpms.h" >&5 +$as_echo_n "checking for X11/extensions/dpms.h... " >&6; } +if test "${ac_cv_header_X11_extensions_dpms_h+set}" = set; then + $as_echo_n "(cached) " >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include + #include + +#include +_ACEOF +rm -rf conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\"" +$as_echo "$ac_try_echo") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -rf conftest.er1 + cat conftest.err >&5 + $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest.$ac_objext; then + ac_cv_header_X11_extensions_dpms_h=yes +else + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_cv_header_X11_extensions_dpms_h=no +fi + +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +{ $as_echo "$as_me:$LINENO: result: $ac_cv_header_X11_extensions_dpms_h" >&5 +$as_echo "$ac_cv_header_X11_extensions_dpms_h" >&6; } +if test "x$ac_cv_header_X11_extensions_dpms_h" = x""yes; then + have_dpms=yes +fi + + + CPPFLAGS="$ac_save_CPPFLAGS" + + # if that succeeded, then check for the DPMS code in the libraries + if test "$have_dpms" = yes; then + + # first look in -lXext (this is where it is with XFree86 4.0) + have_dpms=no + + ac_save_CPPFLAGS="$CPPFLAGS" + ac_save_LDFLAGS="$LDFLAGS" +# ac_save_LIBS="$LIBS" + + if test \! -z "$includedir" ; then + CPPFLAGS="$CPPFLAGS -I$includedir" + fi + # note: $X_CFLAGS includes $x_includes + CPPFLAGS="$CPPFLAGS $X_CFLAGS" + + if test \! -z "$libdir" ; then + LDFLAGS="$LDFLAGS -L$libdir" + fi + # note: $X_LIBS includes $x_libraries + LDFLAGS="$LDFLAGS $X_LIBS $X_EXTRA_LIBS" + + CPPFLAGS=`eval eval eval eval eval eval eval eval eval echo $CPPFLAGS` + LDFLAGS=`eval eval eval eval eval eval eval eval eval echo $LDFLAGS` + { $as_echo "$as_me:$LINENO: checking for DPMSInfo in -lXext" >&5 +$as_echo_n "checking for DPMSInfo in -lXext... " >&6; } +if test "${ac_cv_lib_Xext_DPMSInfo+set}" = set; then + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lXext -lXext -lX11 $LIBS" +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char DPMSInfo (); +int +main () +{ +return DPMSInfo (); + ; + return 0; +} +_ACEOF +rm -rf conftest.$ac_objext conftest$ac_exeext +if { (ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\"" +$as_echo "$ac_try_echo") >&5 + (eval "$ac_link") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -rf conftest.er1 + cat conftest.err >&5 + $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest$ac_exeext && { + test "$cross_compiling" = yes || + $as_test_x conftest$ac_exeext + }; then + ac_cv_lib_Xext_DPMSInfo=yes +else + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_cv_lib_Xext_DPMSInfo=no +fi + +rm -rf conftest.dSYM +rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:$LINENO: result: $ac_cv_lib_Xext_DPMSInfo" >&5 +$as_echo "$ac_cv_lib_Xext_DPMSInfo" >&6; } +if test "x$ac_cv_lib_Xext_DPMSInfo" = x""yes; then + have_dpms=yes +else + true +fi + + CPPFLAGS="$ac_save_CPPFLAGS" + LDFLAGS="$ac_save_LDFLAGS" +# LIBS="$ac_save_LIBS" + + + # if that failed, look in -lXdpms (this is where it was in XFree86 3.x) + if test "$have_dpms" = no; then + + ac_save_CPPFLAGS="$CPPFLAGS" + ac_save_LDFLAGS="$LDFLAGS" +# ac_save_LIBS="$LIBS" + + if test \! -z "$includedir" ; then + CPPFLAGS="$CPPFLAGS -I$includedir" + fi + # note: $X_CFLAGS includes $x_includes + CPPFLAGS="$CPPFLAGS $X_CFLAGS" + + if test \! -z "$libdir" ; then + LDFLAGS="$LDFLAGS -L$libdir" + fi + # note: $X_LIBS includes $x_libraries + LDFLAGS="$LDFLAGS $X_LIBS $X_EXTRA_LIBS" + + CPPFLAGS=`eval eval eval eval eval eval eval eval eval echo $CPPFLAGS` + LDFLAGS=`eval eval eval eval eval eval eval eval eval echo $LDFLAGS` + { $as_echo "$as_me:$LINENO: checking for DPMSInfo in -lXdpms" >&5 +$as_echo_n "checking for DPMSInfo in -lXdpms... " >&6; } +if test "${ac_cv_lib_Xdpms_DPMSInfo+set}" = set; then + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lXdpms -lXext -lX11 $LIBS" +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char DPMSInfo (); +int +main () +{ +return DPMSInfo (); + ; + return 0; +} +_ACEOF +rm -rf conftest.$ac_objext conftest$ac_exeext +if { (ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\"" +$as_echo "$ac_try_echo") >&5 + (eval "$ac_link") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -rf conftest.er1 + cat conftest.err >&5 + $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest$ac_exeext && { + test "$cross_compiling" = yes || + $as_test_x conftest$ac_exeext + }; then + ac_cv_lib_Xdpms_DPMSInfo=yes +else + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_cv_lib_Xdpms_DPMSInfo=no +fi + +rm -rf conftest.dSYM +rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:$LINENO: result: $ac_cv_lib_Xdpms_DPMSInfo" >&5 +$as_echo "$ac_cv_lib_Xdpms_DPMSInfo" >&6; } +if test "x$ac_cv_lib_Xdpms_DPMSInfo" = x""yes; then + have_dpms=yes; XDPMS_LIBS="-lXdpms" +else + true +fi + + CPPFLAGS="$ac_save_CPPFLAGS" + LDFLAGS="$ac_save_LDFLAGS" +# LIBS="$ac_save_LIBS" + + fi + fi + + + # if that succeeded, then we've really got it. + if test "$have_dpms" = yes; then + cat >>confdefs.h <<\_ACEOF +#define HAVE_DPMS_EXTENSION 1 +_ACEOF + + fi + +elif test "$with_dpms" != no; then + echo "error: must be yes or no: --with-dpms-ext=$with_dpms" + exit 1 +fi + + +############################################################################### +# +# Check for the XINERAMA server extension. +# +############################################################################### + +have_xinerama=no +with_xinerama_req=unspecified + +# Check whether --with-xinerama-ext was given. +if test "${with_xinerama_ext+set}" = set; then + withval=$with_xinerama_ext; with_xinerama="$withval"; with_xinerama_req="$withval" +else + with_xinerama=yes +fi + + + + case "$with_xinerama" in + yes) ;; + no) ;; + + /*) + { $as_echo "$as_me:$LINENO: checking for XINERAMA headers" >&5 +$as_echo_n "checking for XINERAMA headers... " >&6; } + d=$with_xinerama/include + if test -d $d; then + X_CFLAGS="-I$d $X_CFLAGS" + { $as_echo "$as_me:$LINENO: result: $d" >&5 +$as_echo "$d" >&6; } + else + { $as_echo "$as_me:$LINENO: result: not found ($d: no such directory)" >&5 +$as_echo "not found ($d: no such directory)" >&6; } + fi + + { $as_echo "$as_me:$LINENO: checking for XINERAMA libs" >&5 +$as_echo_n "checking for XINERAMA libs... " >&6; } + d=$with_xinerama/lib + if test -d $d; then + X_LIBS="-L$d $X_LIBS" + { $as_echo "$as_me:$LINENO: result: $d" >&5 +$as_echo "$d" >&6; } + else + { $as_echo "$as_me:$LINENO: result: not found ($d: no such directory)" >&5 +$as_echo "not found ($d: no such directory)" >&6; } + fi + + # replace the directory string with "yes". + with_xinerama_req="yes" + with_xinerama=$with_xinerama_req + ;; + + *) + echo "" + echo "error: argument to --with-xinerama-ext must be \"yes\", \"no\", or a directory." + echo " If it is a directory, then \`DIR/include' will be added to" + echo " the -I list, and \`DIR/lib' will be added to the -L list." + exit 1 + ;; + esac + + +if test "$with_xinerama" = yes; then + + # first check for Xinerama.h + + ac_save_CPPFLAGS="$CPPFLAGS" + if test \! -z "$includedir" ; then + CPPFLAGS="$CPPFLAGS -I$includedir" + fi + CPPFLAGS="$CPPFLAGS $X_CFLAGS" + CPPFLAGS=`eval eval eval eval eval eval eval eval eval echo $CPPFLAGS` + { $as_echo "$as_me:$LINENO: checking for X11/extensions/Xinerama.h" >&5 +$as_echo_n "checking for X11/extensions/Xinerama.h... " >&6; } +if test "${ac_cv_header_X11_extensions_Xinerama_h+set}" = set; then + $as_echo_n "(cached) " >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include + +#include +_ACEOF +rm -rf conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\"" +$as_echo "$ac_try_echo") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -rf conftest.er1 + cat conftest.err >&5 + $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest.$ac_objext; then + ac_cv_header_X11_extensions_Xinerama_h=yes +else + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_cv_header_X11_extensions_Xinerama_h=no +fi + +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +{ $as_echo "$as_me:$LINENO: result: $ac_cv_header_X11_extensions_Xinerama_h" >&5 +$as_echo "$ac_cv_header_X11_extensions_Xinerama_h" >&6; } +if test "x$ac_cv_header_X11_extensions_Xinerama_h" = x""yes; then + have_xinerama=yes +fi + + + CPPFLAGS="$ac_save_CPPFLAGS" + + # if that succeeded, then check for the XINERAMA code in the libraries + if test "$have_xinerama" = yes; then + + # first look in -lXext + have_xinerama=no + + ac_save_CPPFLAGS="$CPPFLAGS" + ac_save_LDFLAGS="$LDFLAGS" +# ac_save_LIBS="$LIBS" + + if test \! -z "$includedir" ; then + CPPFLAGS="$CPPFLAGS -I$includedir" + fi + # note: $X_CFLAGS includes $x_includes + CPPFLAGS="$CPPFLAGS $X_CFLAGS" + + if test \! -z "$libdir" ; then + LDFLAGS="$LDFLAGS -L$libdir" + fi + # note: $X_LIBS includes $x_libraries + LDFLAGS="$LDFLAGS $X_LIBS $X_EXTRA_LIBS" + + CPPFLAGS=`eval eval eval eval eval eval eval eval eval echo $CPPFLAGS` + LDFLAGS=`eval eval eval eval eval eval eval eval eval echo $LDFLAGS` + { $as_echo "$as_me:$LINENO: checking for XineramaQueryScreens in -lXext" >&5 +$as_echo_n "checking for XineramaQueryScreens in -lXext... " >&6; } +if test "${ac_cv_lib_Xext_XineramaQueryScreens+set}" = set; then + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lXext -lXext -lX11 $LIBS" +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char XineramaQueryScreens (); +int +main () +{ +return XineramaQueryScreens (); + ; + return 0; +} +_ACEOF +rm -rf conftest.$ac_objext conftest$ac_exeext +if { (ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\"" +$as_echo "$ac_try_echo") >&5 + (eval "$ac_link") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -rf conftest.er1 + cat conftest.err >&5 + $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest$ac_exeext && { + test "$cross_compiling" = yes || + $as_test_x conftest$ac_exeext + }; then + ac_cv_lib_Xext_XineramaQueryScreens=yes +else + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_cv_lib_Xext_XineramaQueryScreens=no +fi + +rm -rf conftest.dSYM +rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:$LINENO: result: $ac_cv_lib_Xext_XineramaQueryScreens" >&5 +$as_echo "$ac_cv_lib_Xext_XineramaQueryScreens" >&6; } +if test "x$ac_cv_lib_Xext_XineramaQueryScreens" = x""yes; then + have_xinerama=yes +else + true +fi + + CPPFLAGS="$ac_save_CPPFLAGS" + LDFLAGS="$ac_save_LDFLAGS" +# LIBS="$ac_save_LIBS" + + + # if that failed, look in -lXinerama (this is where it is in XFree86 4.1.) + if test "$have_xinerama" = no; then + + ac_save_CPPFLAGS="$CPPFLAGS" + ac_save_LDFLAGS="$LDFLAGS" +# ac_save_LIBS="$LIBS" + + if test \! -z "$includedir" ; then + CPPFLAGS="$CPPFLAGS -I$includedir" + fi + # note: $X_CFLAGS includes $x_includes + CPPFLAGS="$CPPFLAGS $X_CFLAGS" + + if test \! -z "$libdir" ; then + LDFLAGS="$LDFLAGS -L$libdir" + fi + # note: $X_LIBS includes $x_libraries + LDFLAGS="$LDFLAGS $X_LIBS $X_EXTRA_LIBS" + + CPPFLAGS=`eval eval eval eval eval eval eval eval eval echo $CPPFLAGS` + LDFLAGS=`eval eval eval eval eval eval eval eval eval echo $LDFLAGS` + { $as_echo "$as_me:$LINENO: checking for XineramaQueryScreens in -lXinerama" >&5 +$as_echo_n "checking for XineramaQueryScreens in -lXinerama... " >&6; } +if test "${ac_cv_lib_Xinerama_XineramaQueryScreens+set}" = set; then + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lXinerama -lXext -lX11 $LIBS" +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char XineramaQueryScreens (); +int +main () +{ +return XineramaQueryScreens (); + ; + return 0; +} +_ACEOF +rm -rf conftest.$ac_objext conftest$ac_exeext +if { (ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\"" +$as_echo "$ac_try_echo") >&5 + (eval "$ac_link") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -rf conftest.er1 + cat conftest.err >&5 + $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest$ac_exeext && { + test "$cross_compiling" = yes || + $as_test_x conftest$ac_exeext + }; then + ac_cv_lib_Xinerama_XineramaQueryScreens=yes +else + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_cv_lib_Xinerama_XineramaQueryScreens=no +fi + +rm -rf conftest.dSYM +rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:$LINENO: result: $ac_cv_lib_Xinerama_XineramaQueryScreens" >&5 +$as_echo "$ac_cv_lib_Xinerama_XineramaQueryScreens" >&6; } +if test "x$ac_cv_lib_Xinerama_XineramaQueryScreens" = x""yes; then + have_xinerama=yes; XINERAMA_LIBS="-lXinerama" +else + true +fi + + CPPFLAGS="$ac_save_CPPFLAGS" + LDFLAGS="$ac_save_LDFLAGS" +# LIBS="$ac_save_LIBS" + + fi + fi + + # if that succeeded, then we've really got it. + if test "$have_xinerama" = yes; then + cat >>confdefs.h <<\_ACEOF +#define HAVE_XINERAMA 1 +_ACEOF + + fi + +elif test "$with_xinerama" != no; then + echo "error: must be yes or no: --with-xinerama-ext=$with_xinerama" + exit 1 +fi + + +############################################################################### +# +# Check for the XINPUT server extension. +# +############################################################################### + +have_xinput=no +with_xinput_req=unspecified + +# Check whether --with-xinput-ext was given. +if test "${with_xinput_ext+set}" = set; then + withval=$with_xinput_ext; with_xinput="$withval"; with_xinput_req="$withval" +else + with_xinput=yes +fi + + + + case "$with_xinput" in + yes) ;; + no) ;; + + /*) + { $as_echo "$as_me:$LINENO: checking for XINPUT headers" >&5 +$as_echo_n "checking for XINPUT headers... " >&6; } + d=$with_xinput/include + if test -d $d; then + X_CFLAGS="-I$d $X_CFLAGS" + { $as_echo "$as_me:$LINENO: result: $d" >&5 +$as_echo "$d" >&6; } + else + { $as_echo "$as_me:$LINENO: result: not found ($d: no such directory)" >&5 +$as_echo "not found ($d: no such directory)" >&6; } + fi + + { $as_echo "$as_me:$LINENO: checking for XINPUT libs" >&5 +$as_echo_n "checking for XINPUT libs... " >&6; } + d=$with_xinput/lib + if test -d $d; then + X_LIBS="-L$d $X_LIBS" + { $as_echo "$as_me:$LINENO: result: $d" >&5 +$as_echo "$d" >&6; } + else + { $as_echo "$as_me:$LINENO: result: not found ($d: no such directory)" >&5 +$as_echo "not found ($d: no such directory)" >&6; } + fi + + # replace the directory string with "yes". + with_xinput_req="yes" + with_xinput=$with_xinput_req + ;; + + *) + echo "" + echo "error: argument to --with-xinput-ext must be \"yes\", \"no\", or a directory." + echo " If it is a directory, then \`DIR/include' will be added to" + echo " the -I list, and \`DIR/lib' will be added to the -L list." + exit 1 + ;; + esac + + +if test "$with_xinput" = yes; then + + # first check for Xinput.h + + ac_save_CPPFLAGS="$CPPFLAGS" + if test \! -z "$includedir" ; then + CPPFLAGS="$CPPFLAGS -I$includedir" + fi + CPPFLAGS="$CPPFLAGS $X_CFLAGS" + CPPFLAGS=`eval eval eval eval eval eval eval eval eval echo $CPPFLAGS` + { $as_echo "$as_me:$LINENO: checking for X11/extensions/XInput.h" >&5 +$as_echo_n "checking for X11/extensions/XInput.h... " >&6; } +if test "${ac_cv_header_X11_extensions_XInput_h+set}" = set; then + $as_echo_n "(cached) " >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include + +#include +_ACEOF +rm -rf conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\"" +$as_echo "$ac_try_echo") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -rf conftest.er1 + cat conftest.err >&5 + $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest.$ac_objext; then + ac_cv_header_X11_extensions_XInput_h=yes +else + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_cv_header_X11_extensions_XInput_h=no +fi + +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +{ $as_echo "$as_me:$LINENO: result: $ac_cv_header_X11_extensions_XInput_h" >&5 +$as_echo "$ac_cv_header_X11_extensions_XInput_h" >&6; } +if test "x$ac_cv_header_X11_extensions_XInput_h" = x""yes; then + have_xinput=yes +fi + + + CPPFLAGS="$ac_save_CPPFLAGS" + + # if that succeeded, then check for libXi + if test "$have_xinput" = yes; then + have_xinput=no + + ac_save_CPPFLAGS="$CPPFLAGS" + ac_save_LDFLAGS="$LDFLAGS" +# ac_save_LIBS="$LIBS" + + if test \! -z "$includedir" ; then + CPPFLAGS="$CPPFLAGS -I$includedir" + fi + # note: $X_CFLAGS includes $x_includes + CPPFLAGS="$CPPFLAGS $X_CFLAGS" + + if test \! -z "$libdir" ; then + LDFLAGS="$LDFLAGS -L$libdir" + fi + # note: $X_LIBS includes $x_libraries + LDFLAGS="$LDFLAGS $X_LIBS $X_EXTRA_LIBS" + + CPPFLAGS=`eval eval eval eval eval eval eval eval eval echo $CPPFLAGS` + LDFLAGS=`eval eval eval eval eval eval eval eval eval echo $LDFLAGS` + { $as_echo "$as_me:$LINENO: checking for XListInputDevices in -lXi" >&5 +$as_echo_n "checking for XListInputDevices in -lXi... " >&6; } +if test "${ac_cv_lib_Xi_XListInputDevices+set}" = set; then + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lXi -lXext -lX11 $LIBS" +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char XListInputDevices (); +int +main () +{ +return XListInputDevices (); + ; + return 0; +} +_ACEOF +rm -rf conftest.$ac_objext conftest$ac_exeext +if { (ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\"" +$as_echo "$ac_try_echo") >&5 + (eval "$ac_link") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -rf conftest.er1 + cat conftest.err >&5 + $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest$ac_exeext && { + test "$cross_compiling" = yes || + $as_test_x conftest$ac_exeext + }; then + ac_cv_lib_Xi_XListInputDevices=yes +else + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_cv_lib_Xi_XListInputDevices=no +fi + +rm -rf conftest.dSYM +rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:$LINENO: result: $ac_cv_lib_Xi_XListInputDevices" >&5 +$as_echo "$ac_cv_lib_Xi_XListInputDevices" >&6; } +if test "x$ac_cv_lib_Xi_XListInputDevices" = x""yes; then + have_xinput=yes; SAVER_LIBS="$SAVER_LIBS -lXi" +else + true +fi + + CPPFLAGS="$ac_save_CPPFLAGS" + LDFLAGS="$ac_save_LDFLAGS" +# LIBS="$ac_save_LIBS" + + fi + + # if that succeeded, then we've really got it. + if test "$have_xinput" = yes; then + cat >>confdefs.h <<\_ACEOF +#define HAVE_XINPUT 1 +_ACEOF + + fi + +elif test "$with_xinput" != no; then + echo "error: must be yes or no: --with-xinput-ext=$with_xinput" + exit 1 +fi + + +############################################################################### +# +# Check for the XF86VMODE server extension (for virtual screens.) +# +############################################################################### + +have_xf86vmode=no +with_xf86vmode_req=unspecified + +# Check whether --with-xf86vmode-ext was given. +if test "${with_xf86vmode_ext+set}" = set; then + withval=$with_xf86vmode_ext; with_xf86vmode="$withval"; with_xf86vmode_req="$withval" +else + with_xf86vmode=yes +fi + + + + case "$with_xf86vmode" in + yes) ;; + no) ;; + + /*) + { $as_echo "$as_me:$LINENO: checking for xf86vmode headers" >&5 +$as_echo_n "checking for xf86vmode headers... " >&6; } + d=$with_xf86vmode/include + if test -d $d; then + X_CFLAGS="-I$d $X_CFLAGS" + { $as_echo "$as_me:$LINENO: result: $d" >&5 +$as_echo "$d" >&6; } + else + { $as_echo "$as_me:$LINENO: result: not found ($d: no such directory)" >&5 +$as_echo "not found ($d: no such directory)" >&6; } + fi + + { $as_echo "$as_me:$LINENO: checking for xf86vmode libs" >&5 +$as_echo_n "checking for xf86vmode libs... " >&6; } + d=$with_xf86vmode/lib + if test -d $d; then + X_LIBS="-L$d $X_LIBS" + { $as_echo "$as_me:$LINENO: result: $d" >&5 +$as_echo "$d" >&6; } + else + { $as_echo "$as_me:$LINENO: result: not found ($d: no such directory)" >&5 +$as_echo "not found ($d: no such directory)" >&6; } + fi + + # replace the directory string with "yes". + with_xf86vmode_req="yes" + with_xf86vmode=$with_xf86vmode_req + ;; + + *) + echo "" + echo "error: argument to --with-xf86vmode-ext must be \"yes\", \"no\", or a directory." + echo " If it is a directory, then \`DIR/include' will be added to" + echo " the -I list, and \`DIR/lib' will be added to the -L list." + exit 1 + ;; + esac + + +VIDMODE_LIBS="" + +if test "$with_xf86vmode" = yes; then + + # first check for xf86vmode.h + + ac_save_CPPFLAGS="$CPPFLAGS" + if test \! -z "$includedir" ; then + CPPFLAGS="$CPPFLAGS -I$includedir" + fi + CPPFLAGS="$CPPFLAGS $X_CFLAGS" + CPPFLAGS=`eval eval eval eval eval eval eval eval eval echo $CPPFLAGS` + { $as_echo "$as_me:$LINENO: checking for X11/extensions/xf86vmode.h" >&5 +$as_echo_n "checking for X11/extensions/xf86vmode.h... " >&6; } +if test "${ac_cv_header_X11_extensions_xf86vmode_h+set}" = set; then + $as_echo_n "(cached) " >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include + +#include +_ACEOF +rm -rf conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\"" +$as_echo "$ac_try_echo") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -rf conftest.er1 + cat conftest.err >&5 + $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest.$ac_objext; then + ac_cv_header_X11_extensions_xf86vmode_h=yes +else + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_cv_header_X11_extensions_xf86vmode_h=no +fi + +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +{ $as_echo "$as_me:$LINENO: result: $ac_cv_header_X11_extensions_xf86vmode_h" >&5 +$as_echo "$ac_cv_header_X11_extensions_xf86vmode_h" >&6; } +if test "x$ac_cv_header_X11_extensions_xf86vmode_h" = x""yes; then + have_xf86vmode=yes +fi + + + CPPFLAGS="$ac_save_CPPFLAGS" + + # if that succeeded, then check for the -lXxf86vm + if test "$have_xf86vmode" = yes; then + have_xf86vmode=no + + ac_save_CPPFLAGS="$CPPFLAGS" + ac_save_LDFLAGS="$LDFLAGS" +# ac_save_LIBS="$LIBS" + + if test \! -z "$includedir" ; then + CPPFLAGS="$CPPFLAGS -I$includedir" + fi + # note: $X_CFLAGS includes $x_includes + CPPFLAGS="$CPPFLAGS $X_CFLAGS" + + if test \! -z "$libdir" ; then + LDFLAGS="$LDFLAGS -L$libdir" + fi + # note: $X_LIBS includes $x_libraries + LDFLAGS="$LDFLAGS $X_LIBS $X_EXTRA_LIBS" + + CPPFLAGS=`eval eval eval eval eval eval eval eval eval echo $CPPFLAGS` + LDFLAGS=`eval eval eval eval eval eval eval eval eval echo $LDFLAGS` + { $as_echo "$as_me:$LINENO: checking for XF86VidModeGetViewPort in -lXxf86vm" >&5 +$as_echo_n "checking for XF86VidModeGetViewPort in -lXxf86vm... " >&6; } +if test "${ac_cv_lib_Xxf86vm_XF86VidModeGetViewPort+set}" = set; then + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lXxf86vm -lXext -lX11 $LIBS" +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char XF86VidModeGetViewPort (); +int +main () +{ +return XF86VidModeGetViewPort (); + ; + return 0; +} +_ACEOF +rm -rf conftest.$ac_objext conftest$ac_exeext +if { (ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\"" +$as_echo "$ac_try_echo") >&5 + (eval "$ac_link") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -rf conftest.er1 + cat conftest.err >&5 + $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest$ac_exeext && { + test "$cross_compiling" = yes || + $as_test_x conftest$ac_exeext + }; then + ac_cv_lib_Xxf86vm_XF86VidModeGetViewPort=yes +else + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_cv_lib_Xxf86vm_XF86VidModeGetViewPort=no +fi + +rm -rf conftest.dSYM +rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:$LINENO: result: $ac_cv_lib_Xxf86vm_XF86VidModeGetViewPort" >&5 +$as_echo "$ac_cv_lib_Xxf86vm_XF86VidModeGetViewPort" >&6; } +if test "x$ac_cv_lib_Xxf86vm_XF86VidModeGetViewPort" = x""yes; then + have_xf86vmode=yes; + VIDMODE_LIBS="-lXxf86vm"; + SAVER_LIBS="$SAVER_LIBS $VIDMODE_LIBS" +else + true +fi + + CPPFLAGS="$ac_save_CPPFLAGS" + LDFLAGS="$ac_save_LDFLAGS" +# LIBS="$ac_save_LIBS" + + fi + + # if that succeeded, then we've really got it. + if test "$have_xf86vmode" = yes; then + cat >>confdefs.h <<\_ACEOF +#define HAVE_XF86VMODE 1 +_ACEOF + + fi + +elif test "$with_xf86vmode" != no; then + echo "error: must be yes or no: --with-xf86vmode-ext=$with_xf86vmode" + exit 1 +fi + + +############################################################################### +# +# Check for the XF86VMODE server extension (for gamma fading.) +# +############################################################################### + +have_xf86gamma=no +have_xf86gamma_ramp=no +with_xf86gamma_req=unspecified + +# Check whether --with-xf86gamma-ext was given. +if test "${with_xf86gamma_ext+set}" = set; then + withval=$with_xf86gamma_ext; with_xf86gamma="$withval"; with_xf86gamma_req="$withval" +else + with_xf86gamma=yes +fi + + + + case "$with_xf86gamma" in + yes) ;; + no) ;; + + /*) + { $as_echo "$as_me:$LINENO: checking for xf86gamma headers" >&5 +$as_echo_n "checking for xf86gamma headers... " >&6; } + d=$with_xf86gamma/include + if test -d $d; then + X_CFLAGS="-I$d $X_CFLAGS" + { $as_echo "$as_me:$LINENO: result: $d" >&5 +$as_echo "$d" >&6; } + else + { $as_echo "$as_me:$LINENO: result: not found ($d: no such directory)" >&5 +$as_echo "not found ($d: no such directory)" >&6; } + fi + + { $as_echo "$as_me:$LINENO: checking for xf86gamma libs" >&5 +$as_echo_n "checking for xf86gamma libs... " >&6; } + d=$with_xf86gamma/lib + if test -d $d; then + X_LIBS="-L$d $X_LIBS" + { $as_echo "$as_me:$LINENO: result: $d" >&5 +$as_echo "$d" >&6; } + else + { $as_echo "$as_me:$LINENO: result: not found ($d: no such directory)" >&5 +$as_echo "not found ($d: no such directory)" >&6; } + fi + + # replace the directory string with "yes". + with_xf86gamma_req="yes" + with_xf86gamma=$with_xf86gamma_req + ;; + + *) + echo "" + echo "error: argument to --with-xf86gamma-ext must be \"yes\", \"no\", or a directory." + echo " If it is a directory, then \`DIR/include' will be added to" + echo " the -I list, and \`DIR/lib' will be added to the -L list." + exit 1 + ;; + esac + + +if test "$with_xf86gamma" = yes; then + + # first check for xf86vmode.h, if we haven't already + if test "$have_xf86vmode" = yes; then + have_xf86gamma=yes + else + + ac_save_CPPFLAGS="$CPPFLAGS" + if test \! -z "$includedir" ; then + CPPFLAGS="$CPPFLAGS -I$includedir" + fi + CPPFLAGS="$CPPFLAGS $X_CFLAGS" + CPPFLAGS=`eval eval eval eval eval eval eval eval eval echo $CPPFLAGS` + { $as_echo "$as_me:$LINENO: checking for X11/extensions/xf86vmode.h" >&5 +$as_echo_n "checking for X11/extensions/xf86vmode.h... " >&6; } +if test "${ac_cv_header_X11_extensions_xf86vmode_h+set}" = set; then + $as_echo_n "(cached) " >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include + +#include +_ACEOF +rm -rf conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\"" +$as_echo "$ac_try_echo") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -rf conftest.er1 + cat conftest.err >&5 + $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest.$ac_objext; then + ac_cv_header_X11_extensions_xf86vmode_h=yes +else + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_cv_header_X11_extensions_xf86vmode_h=no +fi + +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +{ $as_echo "$as_me:$LINENO: result: $ac_cv_header_X11_extensions_xf86vmode_h" >&5 +$as_echo "$ac_cv_header_X11_extensions_xf86vmode_h" >&6; } +if test "x$ac_cv_header_X11_extensions_xf86vmode_h" = x""yes; then + have_xf86gamma=yes +fi + + + CPPFLAGS="$ac_save_CPPFLAGS" + fi + + # if that succeeded, then check for the -lXxf86vm + if test "$have_xf86gamma" = yes; then + have_xf86gamma=no + + ac_save_CPPFLAGS="$CPPFLAGS" + ac_save_LDFLAGS="$LDFLAGS" +# ac_save_LIBS="$LIBS" + + if test \! -z "$includedir" ; then + CPPFLAGS="$CPPFLAGS -I$includedir" + fi + # note: $X_CFLAGS includes $x_includes + CPPFLAGS="$CPPFLAGS $X_CFLAGS" + + if test \! -z "$libdir" ; then + LDFLAGS="$LDFLAGS -L$libdir" + fi + # note: $X_LIBS includes $x_libraries + LDFLAGS="$LDFLAGS $X_LIBS $X_EXTRA_LIBS" + + CPPFLAGS=`eval eval eval eval eval eval eval eval eval echo $CPPFLAGS` + LDFLAGS=`eval eval eval eval eval eval eval eval eval echo $LDFLAGS` + { $as_echo "$as_me:$LINENO: checking for XF86VidModeSetGamma in -lXxf86vm" >&5 +$as_echo_n "checking for XF86VidModeSetGamma in -lXxf86vm... " >&6; } +if test "${ac_cv_lib_Xxf86vm_XF86VidModeSetGamma+set}" = set; then + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lXxf86vm -lXext -lX11 $LIBS" +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char XF86VidModeSetGamma (); +int +main () +{ +return XF86VidModeSetGamma (); + ; + return 0; +} +_ACEOF +rm -rf conftest.$ac_objext conftest$ac_exeext +if { (ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\"" +$as_echo "$ac_try_echo") >&5 + (eval "$ac_link") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -rf conftest.er1 + cat conftest.err >&5 + $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest$ac_exeext && { + test "$cross_compiling" = yes || + $as_test_x conftest$ac_exeext + }; then + ac_cv_lib_Xxf86vm_XF86VidModeSetGamma=yes +else + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_cv_lib_Xxf86vm_XF86VidModeSetGamma=no +fi + +rm -rf conftest.dSYM +rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:$LINENO: result: $ac_cv_lib_Xxf86vm_XF86VidModeSetGamma" >&5 +$as_echo "$ac_cv_lib_Xxf86vm_XF86VidModeSetGamma" >&6; } +if test "x$ac_cv_lib_Xxf86vm_XF86VidModeSetGamma" = x""yes; then + have_xf86gamma=yes +else + true +fi + + CPPFLAGS="$ac_save_CPPFLAGS" + LDFLAGS="$ac_save_LDFLAGS" +# LIBS="$ac_save_LIBS" + + fi + + # check for the Ramp versions of the functions too. + if test "$have_xf86gamma" = yes; then + have_xf86gamma_ramp=no + + ac_save_CPPFLAGS="$CPPFLAGS" + ac_save_LDFLAGS="$LDFLAGS" +# ac_save_LIBS="$LIBS" + + if test \! -z "$includedir" ; then + CPPFLAGS="$CPPFLAGS -I$includedir" + fi + # note: $X_CFLAGS includes $x_includes + CPPFLAGS="$CPPFLAGS $X_CFLAGS" + + if test \! -z "$libdir" ; then + LDFLAGS="$LDFLAGS -L$libdir" + fi + # note: $X_LIBS includes $x_libraries + LDFLAGS="$LDFLAGS $X_LIBS $X_EXTRA_LIBS" + + CPPFLAGS=`eval eval eval eval eval eval eval eval eval echo $CPPFLAGS` + LDFLAGS=`eval eval eval eval eval eval eval eval eval echo $LDFLAGS` + { $as_echo "$as_me:$LINENO: checking for XF86VidModeSetGammaRamp in -lXxf86vm" >&5 +$as_echo_n "checking for XF86VidModeSetGammaRamp in -lXxf86vm... " >&6; } +if test "${ac_cv_lib_Xxf86vm_XF86VidModeSetGammaRamp+set}" = set; then + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lXxf86vm -lXext -lX11 $LIBS" +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char XF86VidModeSetGammaRamp (); +int +main () +{ +return XF86VidModeSetGammaRamp (); + ; + return 0; +} +_ACEOF +rm -rf conftest.$ac_objext conftest$ac_exeext +if { (ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\"" +$as_echo "$ac_try_echo") >&5 + (eval "$ac_link") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -rf conftest.er1 + cat conftest.err >&5 + $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest$ac_exeext && { + test "$cross_compiling" = yes || + $as_test_x conftest$ac_exeext + }; then + ac_cv_lib_Xxf86vm_XF86VidModeSetGammaRamp=yes +else + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_cv_lib_Xxf86vm_XF86VidModeSetGammaRamp=no +fi + +rm -rf conftest.dSYM +rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:$LINENO: result: $ac_cv_lib_Xxf86vm_XF86VidModeSetGammaRamp" >&5 +$as_echo "$ac_cv_lib_Xxf86vm_XF86VidModeSetGammaRamp" >&6; } +if test "x$ac_cv_lib_Xxf86vm_XF86VidModeSetGammaRamp" = x""yes; then + have_xf86gamma_ramp=yes +else + true +fi + + CPPFLAGS="$ac_save_CPPFLAGS" + LDFLAGS="$ac_save_LDFLAGS" +# LIBS="$ac_save_LIBS" + + fi + + # if those tests succeeded, then we've really got the functions. + if test "$have_xf86gamma" = yes; then + cat >>confdefs.h <<\_ACEOF +#define HAVE_XF86VMODE_GAMMA 1 +_ACEOF + + fi + + if test "$have_xf86gamma_ramp" = yes; then + cat >>confdefs.h <<\_ACEOF +#define HAVE_XF86VMODE_GAMMA_RAMP 1 +_ACEOF + + fi + + # pull in the lib, if we haven't already + if test "$have_xf86gamma" = yes -a "$have_xf86vmode" = no; then + SAVER_LIBS="$SAVER_LIBS -lXxf86vm" + fi + +elif test "$with_xf86gamma" != no; then + echo "error: must be yes or no: --with-xf86gamma-ext=$with_xf86vmode" + exit 1 +fi + + +############################################################################### +# +# Check for the RANDR (Resize and Rotate) server extension. +# +# We need this to detect when the resolution of the desktop +# has changed out from under us (this is a newer, different +# mechanism than the XF86VMODE virtual viewports.) +# +############################################################################### + +have_randr=no +with_randr_req=unspecified + +# Check whether --with-randr-ext was given. +if test "${with_randr_ext+set}" = set; then + withval=$with_randr_ext; with_randr="$withval"; with_randr_req="$withval" +else + with_randr=yes +fi + + + + case "$with_randr" in + yes) ;; + no) ;; + + /*) + { $as_echo "$as_me:$LINENO: checking for RANDR headers" >&5 +$as_echo_n "checking for RANDR headers... " >&6; } + d=$with_randr/include + if test -d $d; then + X_CFLAGS="-I$d $X_CFLAGS" + { $as_echo "$as_me:$LINENO: result: $d" >&5 +$as_echo "$d" >&6; } + else + { $as_echo "$as_me:$LINENO: result: not found ($d: no such directory)" >&5 +$as_echo "not found ($d: no such directory)" >&6; } + fi + + { $as_echo "$as_me:$LINENO: checking for RANDR libs" >&5 +$as_echo_n "checking for RANDR libs... " >&6; } + d=$with_randr/lib + if test -d $d; then + X_LIBS="-L$d $X_LIBS" + { $as_echo "$as_me:$LINENO: result: $d" >&5 +$as_echo "$d" >&6; } + else + { $as_echo "$as_me:$LINENO: result: not found ($d: no such directory)" >&5 +$as_echo "not found ($d: no such directory)" >&6; } + fi + + # replace the directory string with "yes". + with_randr_req="yes" + with_randr=$with_randr_req + ;; + + *) + echo "" + echo "error: argument to --with-randr-ext must be \"yes\", \"no\", or a directory." + echo " If it is a directory, then \`DIR/include' will be added to" + echo " the -I list, and \`DIR/lib' will be added to the -L list." + exit 1 + ;; + esac + + +if test "$with_randr" = yes; then + + # first check for Xrandr.h + + ac_save_CPPFLAGS="$CPPFLAGS" + if test \! -z "$includedir" ; then + CPPFLAGS="$CPPFLAGS -I$includedir" + fi + CPPFLAGS="$CPPFLAGS $X_CFLAGS" + CPPFLAGS=`eval eval eval eval eval eval eval eval eval echo $CPPFLAGS` + { $as_echo "$as_me:$LINENO: checking for X11/extensions/Xrandr.h" >&5 +$as_echo_n "checking for X11/extensions/Xrandr.h... " >&6; } +if test "${ac_cv_header_X11_extensions_Xrandr_h+set}" = set; then + $as_echo_n "(cached) " >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include + +#include +_ACEOF +rm -rf conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\"" +$as_echo "$ac_try_echo") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -rf conftest.er1 + cat conftest.err >&5 + $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest.$ac_objext; then + ac_cv_header_X11_extensions_Xrandr_h=yes +else + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_cv_header_X11_extensions_Xrandr_h=no +fi + +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +{ $as_echo "$as_me:$LINENO: result: $ac_cv_header_X11_extensions_Xrandr_h" >&5 +$as_echo "$ac_cv_header_X11_extensions_Xrandr_h" >&6; } +if test "x$ac_cv_header_X11_extensions_Xrandr_h" = x""yes; then + have_randr=yes +fi + + + CPPFLAGS="$ac_save_CPPFLAGS" + + # if that succeeded, then check for the XRR code in the libraries + if test "$have_randr" = yes; then + + # RANDR probably needs -lXrender + xrender_libs= + + ac_save_CPPFLAGS="$CPPFLAGS" + ac_save_LDFLAGS="$LDFLAGS" +# ac_save_LIBS="$LIBS" + + if test \! -z "$includedir" ; then + CPPFLAGS="$CPPFLAGS -I$includedir" + fi + # note: $X_CFLAGS includes $x_includes + CPPFLAGS="$CPPFLAGS $X_CFLAGS" + + if test \! -z "$libdir" ; then + LDFLAGS="$LDFLAGS -L$libdir" + fi + # note: $X_LIBS includes $x_libraries + LDFLAGS="$LDFLAGS $X_LIBS $X_EXTRA_LIBS" + + CPPFLAGS=`eval eval eval eval eval eval eval eval eval echo $CPPFLAGS` + LDFLAGS=`eval eval eval eval eval eval eval eval eval echo $LDFLAGS` + { $as_echo "$as_me:$LINENO: checking for XRenderSetSubpixelOrder in -lXrender" >&5 +$as_echo_n "checking for XRenderSetSubpixelOrder in -lXrender... " >&6; } +if test "${ac_cv_lib_Xrender_XRenderSetSubpixelOrder+set}" = set; then + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lXrender -lXext -lX11 $LIBS" +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char XRenderSetSubpixelOrder (); +int +main () +{ +return XRenderSetSubpixelOrder (); + ; + return 0; +} +_ACEOF +rm -rf conftest.$ac_objext conftest$ac_exeext +if { (ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\"" +$as_echo "$ac_try_echo") >&5 + (eval "$ac_link") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -rf conftest.er1 + cat conftest.err >&5 + $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest$ac_exeext && { + test "$cross_compiling" = yes || + $as_test_x conftest$ac_exeext + }; then + ac_cv_lib_Xrender_XRenderSetSubpixelOrder=yes +else + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_cv_lib_Xrender_XRenderSetSubpixelOrder=no +fi + +rm -rf conftest.dSYM +rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:$LINENO: result: $ac_cv_lib_Xrender_XRenderSetSubpixelOrder" >&5 +$as_echo "$ac_cv_lib_Xrender_XRenderSetSubpixelOrder" >&6; } +if test "x$ac_cv_lib_Xrender_XRenderSetSubpixelOrder" = x""yes; then + xrender_libs="-lXrender" +else + true +fi + + CPPFLAGS="$ac_save_CPPFLAGS" + LDFLAGS="$ac_save_LDFLAGS" +# LIBS="$ac_save_LIBS" + + + # first look for RANDR in -lXext + have_randr=no + + ac_save_CPPFLAGS="$CPPFLAGS" + ac_save_LDFLAGS="$LDFLAGS" +# ac_save_LIBS="$LIBS" + + if test \! -z "$includedir" ; then + CPPFLAGS="$CPPFLAGS -I$includedir" + fi + # note: $X_CFLAGS includes $x_includes + CPPFLAGS="$CPPFLAGS $X_CFLAGS" + + if test \! -z "$libdir" ; then + LDFLAGS="$LDFLAGS -L$libdir" + fi + # note: $X_LIBS includes $x_libraries + LDFLAGS="$LDFLAGS $X_LIBS $X_EXTRA_LIBS" + + CPPFLAGS=`eval eval eval eval eval eval eval eval eval echo $CPPFLAGS` + LDFLAGS=`eval eval eval eval eval eval eval eval eval echo $LDFLAGS` + { $as_echo "$as_me:$LINENO: checking for XRRGetScreenInfo in -lXext" >&5 +$as_echo_n "checking for XRRGetScreenInfo in -lXext... " >&6; } +if test "${ac_cv_lib_Xext_XRRGetScreenInfo+set}" = set; then + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lXext $xrender_libs -lXext -lX11 $LIBS" +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char XRRGetScreenInfo (); +int +main () +{ +return XRRGetScreenInfo (); + ; + return 0; +} +_ACEOF +rm -rf conftest.$ac_objext conftest$ac_exeext +if { (ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\"" +$as_echo "$ac_try_echo") >&5 + (eval "$ac_link") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -rf conftest.er1 + cat conftest.err >&5 + $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest$ac_exeext && { + test "$cross_compiling" = yes || + $as_test_x conftest$ac_exeext + }; then + ac_cv_lib_Xext_XRRGetScreenInfo=yes +else + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_cv_lib_Xext_XRRGetScreenInfo=no +fi + +rm -rf conftest.dSYM +rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:$LINENO: result: $ac_cv_lib_Xext_XRRGetScreenInfo" >&5 +$as_echo "$ac_cv_lib_Xext_XRRGetScreenInfo" >&6; } +if test "x$ac_cv_lib_Xext_XRRGetScreenInfo" = x""yes; then + have_randr=yes; SAVER_LIBS="$SAVER_LIBS $xrender_libs" +else + true +fi + + CPPFLAGS="$ac_save_CPPFLAGS" + LDFLAGS="$ac_save_LDFLAGS" +# LIBS="$ac_save_LIBS" + + + # if that failed, look in -lXrandr + if test "$have_randr" = no; then + + ac_save_CPPFLAGS="$CPPFLAGS" + ac_save_LDFLAGS="$LDFLAGS" +# ac_save_LIBS="$LIBS" + + if test \! -z "$includedir" ; then + CPPFLAGS="$CPPFLAGS -I$includedir" + fi + # note: $X_CFLAGS includes $x_includes + CPPFLAGS="$CPPFLAGS $X_CFLAGS" + + if test \! -z "$libdir" ; then + LDFLAGS="$LDFLAGS -L$libdir" + fi + # note: $X_LIBS includes $x_libraries + LDFLAGS="$LDFLAGS $X_LIBS $X_EXTRA_LIBS" + + CPPFLAGS=`eval eval eval eval eval eval eval eval eval echo $CPPFLAGS` + LDFLAGS=`eval eval eval eval eval eval eval eval eval echo $LDFLAGS` + { $as_echo "$as_me:$LINENO: checking for XRRGetScreenInfo in -lXrandr" >&5 +$as_echo_n "checking for XRRGetScreenInfo in -lXrandr... " >&6; } +if test "${ac_cv_lib_Xrandr_XRRGetScreenInfo+set}" = set; then + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lXrandr $xrender_libs -lXext -lX11 $LIBS" +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char XRRGetScreenInfo (); +int +main () +{ +return XRRGetScreenInfo (); + ; + return 0; +} +_ACEOF +rm -rf conftest.$ac_objext conftest$ac_exeext +if { (ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\"" +$as_echo "$ac_try_echo") >&5 + (eval "$ac_link") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -rf conftest.er1 + cat conftest.err >&5 + $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest$ac_exeext && { + test "$cross_compiling" = yes || + $as_test_x conftest$ac_exeext + }; then + ac_cv_lib_Xrandr_XRRGetScreenInfo=yes +else + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_cv_lib_Xrandr_XRRGetScreenInfo=no +fi + +rm -rf conftest.dSYM +rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:$LINENO: result: $ac_cv_lib_Xrandr_XRRGetScreenInfo" >&5 +$as_echo "$ac_cv_lib_Xrandr_XRRGetScreenInfo" >&6; } +if test "x$ac_cv_lib_Xrandr_XRRGetScreenInfo" = x""yes; then + have_randr=yes; SAVER_LIBS="$SAVER_LIBS -lXrandr $xrender_libs" +else + true +fi + + CPPFLAGS="$ac_save_CPPFLAGS" + LDFLAGS="$ac_save_LDFLAGS" +# LIBS="$ac_save_LIBS" + + fi + fi + + # if that succeeded, then we've really got it. + if test "$have_randr" = yes; then + cat >>confdefs.h <<\_ACEOF +#define HAVE_RANDR 1 +_ACEOF + + + # Now check for version 1.2 in the same libs. + # Try to compile, since on MacOS 10.5.7, headers are older than libs! + { $as_echo "$as_me:$LINENO: checking for XRRGetScreenResources" >&5 +$as_echo_n "checking for XRRGetScreenResources... " >&6; } +if test "${ac_cv_randr_12+set}" = set; then + $as_echo_n "(cached) " >&6 +else + ac_cv_randr_12=no + + ac_save_CPPFLAGS="$CPPFLAGS" + if test \! -z "$includedir" ; then + CPPFLAGS="$CPPFLAGS -I$includedir" + fi + CPPFLAGS="$CPPFLAGS $X_CFLAGS" + CPPFLAGS=`eval eval eval eval eval eval eval eval eval echo $CPPFLAGS` + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include + #include + #include +int +main () +{ +XRRScreenResources *res = + XRRGetScreenResources (0, 0); + ; + return 0; +} +_ACEOF +rm -rf conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\"" +$as_echo "$ac_try_echo") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -rf conftest.er1 + cat conftest.err >&5 + $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest.$ac_objext; then + ac_cv_randr_12=yes +else + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_cv_randr_12=no +fi + +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + CPPFLAGS="$ac_save_CPPFLAGS" +fi +{ $as_echo "$as_me:$LINENO: result: $ac_cv_randr_12" >&5 +$as_echo "$ac_cv_randr_12" >&6; } + if test "$ac_cv_randr_12" = yes ; then + cat >>confdefs.h <<\_ACEOF +#define HAVE_RANDR_12 1 +_ACEOF + + fi +# AC_CHECK_X_LIB(c, XRRGetOutputInfo, [AC_DEFINE(HAVE_RANDR_12)], +# [true], $SAVER_LIBS) + fi + + +elif test "$with_randr" != no; then + echo "error: must be yes or no: --with-randr-ext=$with_randr" + exit 1 +fi + + +############################################################################### +# +# Check for XF86MiscSetGrabKeysState (but only bother if we are already +# using other XF86 stuff.) +# +############################################################################### + +have_xf86miscsetgrabkeysstate=no +if test "$have_xf86gamma" = yes -o "$have_xf86vmode" = yes; then + + ac_save_CPPFLAGS="$CPPFLAGS" + ac_save_LDFLAGS="$LDFLAGS" +# ac_save_LIBS="$LIBS" + + if test \! -z "$includedir" ; then + CPPFLAGS="$CPPFLAGS -I$includedir" + fi + # note: $X_CFLAGS includes $x_includes + CPPFLAGS="$CPPFLAGS $X_CFLAGS" + + if test \! -z "$libdir" ; then + LDFLAGS="$LDFLAGS -L$libdir" + fi + # note: $X_LIBS includes $x_libraries + LDFLAGS="$LDFLAGS $X_LIBS $X_EXTRA_LIBS" + + CPPFLAGS=`eval eval eval eval eval eval eval eval eval echo $CPPFLAGS` + LDFLAGS=`eval eval eval eval eval eval eval eval eval echo $LDFLAGS` + { $as_echo "$as_me:$LINENO: checking for XF86MiscSetGrabKeysState in -lXxf86misc" >&5 +$as_echo_n "checking for XF86MiscSetGrabKeysState in -lXxf86misc... " >&6; } +if test "${ac_cv_lib_Xxf86misc_XF86MiscSetGrabKeysState+set}" = set; then + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lXxf86misc -lXext -lX11 $LIBS" +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char XF86MiscSetGrabKeysState (); +int +main () +{ +return XF86MiscSetGrabKeysState (); + ; + return 0; +} +_ACEOF +rm -rf conftest.$ac_objext conftest$ac_exeext +if { (ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\"" +$as_echo "$ac_try_echo") >&5 + (eval "$ac_link") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -rf conftest.er1 + cat conftest.err >&5 + $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest$ac_exeext && { + test "$cross_compiling" = yes || + $as_test_x conftest$ac_exeext + }; then + ac_cv_lib_Xxf86misc_XF86MiscSetGrabKeysState=yes +else + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_cv_lib_Xxf86misc_XF86MiscSetGrabKeysState=no +fi + +rm -rf conftest.dSYM +rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:$LINENO: result: $ac_cv_lib_Xxf86misc_XF86MiscSetGrabKeysState" >&5 +$as_echo "$ac_cv_lib_Xxf86misc_XF86MiscSetGrabKeysState" >&6; } +if test "x$ac_cv_lib_Xxf86misc_XF86MiscSetGrabKeysState" = x""yes; then + have_xf86miscsetgrabkeysstate=yes +else + true +fi + + CPPFLAGS="$ac_save_CPPFLAGS" + LDFLAGS="$ac_save_LDFLAGS" +# LIBS="$ac_save_LIBS" + + if test "$have_xf86miscsetgrabkeysstate" = yes ; then + SAVER_LIBS="$SAVER_LIBS -lXxf86misc" + cat >>confdefs.h <<\_ACEOF +#define HAVE_XF86MISCSETGRABKEYSSTATE 1 +_ACEOF + + fi +fi + + +############################################################################### +# +# Check for HP XHPDisableReset and XHPEnableReset. +# +############################################################################### + +{ $as_echo "$as_me:$LINENO: checking for XHPDisableReset in X11/XHPlib.h" >&5 +$as_echo_n "checking for XHPDisableReset in X11/XHPlib.h... " >&6; } + + ac_save_CPPFLAGS="$CPPFLAGS" + if test \! -z "$includedir" ; then + CPPFLAGS="$CPPFLAGS -I$includedir" + fi + CPPFLAGS="$CPPFLAGS $X_CFLAGS" + CPPFLAGS=`eval eval eval eval eval eval eval eval eval echo $CPPFLAGS` + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include + +_ACEOF +if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | + $EGREP "XHPDisableReset" >/dev/null 2>&1; then + cat >>confdefs.h <<\_ACEOF +#define HAVE_XHPDISABLERESET 1 +_ACEOF + + SAVER_LIBS="-lXhp11 $SAVER_LIBS" + { $as_echo "$as_me:$LINENO: result: yes" >&5 +$as_echo "yes" >&6; } +else + { $as_echo "$as_me:$LINENO: result: no" >&5 +$as_echo "no" >&6; } +fi +rm -rf conftest* + + CPPFLAGS="$ac_save_CPPFLAGS" + + +############################################################################### +# +# Check for /proc/interrupts. +# +############################################################################### + +have_proc_interrupts=no +with_proc_interrupts_req=unspecified + +# Check whether --with-proc-interrupts was given. +if test "${with_proc_interrupts+set}" = set; then + withval=$with_proc_interrupts; with_proc_interrupts="$withval"; with_proc_interrupts_req="$withval" +else + with_proc_interrupts=yes +fi + + +if test "$with_proc_interrupts" = yes; then + + # Note that we may be building in an environment (e.g. Debian buildd chroot) + # without a proper /proc filesystem. If /proc/interrupts exists, then we'll + # check that it has the bits we need, but otherwise we'll just go on faith. + # + have_proc_interrupts=yes + + if test -f /proc/interrupts; then + { $as_echo "$as_me:$LINENO: checking whether /proc/interrupts contains keyboard data" >&5 +$as_echo_n "checking whether /proc/interrupts contains keyboard data... " >&6; } +if test "${ac_cv_have_proc_interrupts+set}" = set; then + $as_echo_n "(cached) " >&6 +else + ac_cv_have_proc_interrupts=no + if grep 'keyboard\|i8042' /proc/interrupts >/dev/null 2>&1 ; then + ac_cv_have_proc_interrupts=yes + fi + +fi +{ $as_echo "$as_me:$LINENO: result: $ac_cv_have_proc_interrupts" >&5 +$as_echo "$ac_cv_have_proc_interrupts" >&6; } + have_proc_interrupts=$ac_cv_have_proc_interrupts + fi + + if test "$have_proc_interrupts" = yes; then + cat >>confdefs.h <<\_ACEOF +#define HAVE_PROC_INTERRUPTS 1 +_ACEOF + + fi + +elif test "$with_proc_interrupts" != no; then + echo "error: must be yes or no: --with-proc-interrupts=$with_proc_interrupts" + exit 1 +fi + + +############################################################################### +# +# The --enable-locking option +# +############################################################################### + +# Check whether --enable-locking was given. +if test "${enable_locking+set}" = set; then + enableval=$enable_locking; enable_locking="$enableval" +else + if test "$ac_macosx" = yes; then + # We can't lock on MacOS X, so default to not compiling in support for it. + # But allow --enable-locking to override that, so I can debug Linux locking + # under MacOS X11. + enable_locking=no + else + enable_locking=yes + fi +fi + +if test "$enable_locking" = yes; then + true +elif test "$enable_locking" = no; then + cat >>confdefs.h <<\_ACEOF +#define NO_LOCKING 1 +_ACEOF + +else + echo "error: must be yes or no: --enable-locking=$enable_locking" + exit 1 +fi + + +############################################################################### +# +# Whether to allow root password to unblank. +# +############################################################################### +# Check whether --enable-root-passwd was given. +if test "${enable_root_passwd+set}" = set; then + enableval=$enable_root_passwd; enable_root_passwd="$enableval" +else + enable_root_passwd=yes +fi + +if test "$enable_root_passwd" = yes; then + cat >>confdefs.h <<\_ACEOF +#define ALLOW_ROOT_PASSWD 1 +_ACEOF + + true +elif test "$enable_root_passwd" != no; then + echo "error: must be yes or no: --enable-root-passwd=$enable_root_passwd" + exit 1 +fi + +############################################################################### +# +# Check for PAM. +# +############################################################################### + +case "$host" in + *-solaris*) + # Solaris systems tend to come with PAM misconfigured. + # Don't build it by default, even if the headers exist. + with_pam_default=no + ;; + *) + # Default to building PAM support on all other systems, if it exists. + with_pam_default=yes + ;; +esac + +have_pam=no +with_pam_req=unspecified + + +# Check whether --with-pam was given. +if test "${with_pam+set}" = set; then + withval=$with_pam; with_pam="$withval"; with_pam_req="$withval" +else + with_pam=$with_pam_default +fi + + + +# Check whether --with-pam_service_name was given. +if test "${with_pam_service_name+set}" = set; then + withval=$with_pam_service_name; pam_service_name="$withval" +else + pam_service_name="xscreensaver" +fi + + +# Check whether --enable-pam-check-account-type was given. +if test "${enable_pam_check_account_type+set}" = set; then + enableval=$enable_pam_check_account_type; enable_pam_check_account_type="$enableval" +else + enable_pam_check_account_type=no +fi + +if test "$enable_pam_check_account_type" = yes ; then + cat >>confdefs.h <<\_ACEOF +#define PAM_CHECK_ACCOUNT_TYPE 1 +_ACEOF + + true +elif test "$enable_pam_check_account_type" != no ; then + echo "error: must be yes or no: --enable-pam-check-account-type=$enable_pam_check_account_type" + exit 1 +fi + + + case "$with_pam" in + yes) ;; + no) ;; + + /*) + { $as_echo "$as_me:$LINENO: checking for PAM headers" >&5 +$as_echo_n "checking for PAM headers... " >&6; } + d=$with_pam/include + if test -d $d; then + X_CFLAGS="-I$d $X_CFLAGS" + { $as_echo "$as_me:$LINENO: result: $d" >&5 +$as_echo "$d" >&6; } + else + { $as_echo "$as_me:$LINENO: result: not found ($d: no such directory)" >&5 +$as_echo "not found ($d: no such directory)" >&6; } + fi + + { $as_echo "$as_me:$LINENO: checking for PAM libs" >&5 +$as_echo_n "checking for PAM libs... " >&6; } + d=$with_pam/lib + if test -d $d; then + X_LIBS="-L$d $X_LIBS" + { $as_echo "$as_me:$LINENO: result: $d" >&5 +$as_echo "$d" >&6; } + else + { $as_echo "$as_me:$LINENO: result: not found ($d: no such directory)" >&5 +$as_echo "not found ($d: no such directory)" >&6; } + fi + + # replace the directory string with "yes". + with_pam_req="yes" + with_pam=$with_pam_req + ;; + + *) + echo "" + echo "error: argument to --with-pam must be \"yes\", \"no\", or a directory." + echo " If it is a directory, then \`DIR/include' will be added to" + echo " the -I list, and \`DIR/lib' will be added to the -L list." + exit 1 + ;; + esac + + +if test "$enable_locking" = yes -a "$with_pam" = yes; then + { $as_echo "$as_me:$LINENO: checking for PAM" >&5 +$as_echo_n "checking for PAM... " >&6; } +if test "${ac_cv_pam+set}" = set; then + $as_echo_n "(cached) " >&6 +else + + ac_save_CPPFLAGS="$CPPFLAGS" + if test \! -z "$includedir" ; then + CPPFLAGS="$CPPFLAGS -I$includedir" + fi + CPPFLAGS="$CPPFLAGS $X_CFLAGS" + CPPFLAGS=`eval eval eval eval eval eval eval eval eval echo $CPPFLAGS` + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include +int +main () +{ + + ; + return 0; +} +_ACEOF +rm -rf conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\"" +$as_echo "$ac_try_echo") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -rf conftest.er1 + cat conftest.err >&5 + $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest.$ac_objext; then + ac_cv_pam=yes +else + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_cv_pam=no +fi + +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + CPPFLAGS="$ac_save_CPPFLAGS" +fi +{ $as_echo "$as_me:$LINENO: result: $ac_cv_pam" >&5 +$as_echo "$ac_cv_pam" >&6; } + if test "$ac_cv_pam" = yes ; then + have_pam=yes + cat >>confdefs.h <<\_ACEOF +#define HAVE_PAM 1 +_ACEOF + + cat >>confdefs.h <<_ACEOF +#define PAM_SERVICE_NAME "$pam_service_name" +_ACEOF + + + PASSWD_LIBS="${PASSWD_LIBS} -lpam" + + # libpam typically requires dlopen and dlsym. On FreeBSD, + # those are in libc. On Linux and Solaris, they're in libdl. + { $as_echo "$as_me:$LINENO: checking for dlopen in -ldl" >&5 +$as_echo_n "checking for dlopen in -ldl... " >&6; } +if test "${ac_cv_lib_dl_dlopen+set}" = set; then + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-ldl $LIBS" +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char dlopen (); +int +main () +{ +return dlopen (); + ; + return 0; +} +_ACEOF +rm -rf conftest.$ac_objext conftest$ac_exeext +if { (ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\"" +$as_echo "$ac_try_echo") >&5 + (eval "$ac_link") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -rf conftest.er1 + cat conftest.err >&5 + $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest$ac_exeext && { + test "$cross_compiling" = yes || + $as_test_x conftest$ac_exeext + }; then + ac_cv_lib_dl_dlopen=yes +else + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_cv_lib_dl_dlopen=no +fi + +rm -rf conftest.dSYM +rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:$LINENO: result: $ac_cv_lib_dl_dlopen" >&5 +$as_echo "$ac_cv_lib_dl_dlopen" >&6; } +if test "x$ac_cv_lib_dl_dlopen" = x""yes; then + PASSWD_LIBS="${PASSWD_LIBS} -ldl" +fi + + + # On Linux, sigtimedwait() is in libc; on Solaris, it's in librt. + have_timedwait=no + { $as_echo "$as_me:$LINENO: checking for sigtimedwait in -lc" >&5 +$as_echo_n "checking for sigtimedwait in -lc... " >&6; } +if test "${ac_cv_lib_c_sigtimedwait+set}" = set; then + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lc $LIBS" +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char sigtimedwait (); +int +main () +{ +return sigtimedwait (); + ; + return 0; +} +_ACEOF +rm -rf conftest.$ac_objext conftest$ac_exeext +if { (ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\"" +$as_echo "$ac_try_echo") >&5 + (eval "$ac_link") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -rf conftest.er1 + cat conftest.err >&5 + $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest$ac_exeext && { + test "$cross_compiling" = yes || + $as_test_x conftest$ac_exeext + }; then + ac_cv_lib_c_sigtimedwait=yes +else + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_cv_lib_c_sigtimedwait=no +fi + +rm -rf conftest.dSYM +rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:$LINENO: result: $ac_cv_lib_c_sigtimedwait" >&5 +$as_echo "$ac_cv_lib_c_sigtimedwait" >&6; } +if test "x$ac_cv_lib_c_sigtimedwait" = x""yes; then + have_timedwait=yes + cat >>confdefs.h <<\_ACEOF +#define HAVE_SIGTIMEDWAIT 1 +_ACEOF + +fi + + if test "$have_timedwait" = no ; then + { $as_echo "$as_me:$LINENO: checking for sigtimedwait in -lrt" >&5 +$as_echo_n "checking for sigtimedwait in -lrt... " >&6; } +if test "${ac_cv_lib_rt_sigtimedwait+set}" = set; then + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lrt $LIBS" +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char sigtimedwait (); +int +main () +{ +return sigtimedwait (); + ; + return 0; +} +_ACEOF +rm -rf conftest.$ac_objext conftest$ac_exeext +if { (ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\"" +$as_echo "$ac_try_echo") >&5 + (eval "$ac_link") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -rf conftest.er1 + cat conftest.err >&5 + $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest$ac_exeext && { + test "$cross_compiling" = yes || + $as_test_x conftest$ac_exeext + }; then + ac_cv_lib_rt_sigtimedwait=yes +else + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_cv_lib_rt_sigtimedwait=no +fi + +rm -rf conftest.dSYM +rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:$LINENO: result: $ac_cv_lib_rt_sigtimedwait" >&5 +$as_echo "$ac_cv_lib_rt_sigtimedwait" >&6; } +if test "x$ac_cv_lib_rt_sigtimedwait" = x""yes; then + have_timedwait=yes + cat >>confdefs.h <<\_ACEOF +#define HAVE_SIGTIMEDWAIT 1 +_ACEOF + + PASSWD_LIBS="${PASSWD_LIBS} -lrt" +fi + + fi + + { $as_echo "$as_me:$LINENO: checking how to call pam_strerror" >&5 +$as_echo_n "checking how to call pam_strerror... " >&6; } + if test "${ac_cv_pam_strerror_args+set}" = set; then + $as_echo_n "(cached) " >&6 +else + + ac_save_CPPFLAGS="$CPPFLAGS" + if test \! -z "$includedir" ; then + CPPFLAGS="$CPPFLAGS -I$includedir" + fi + CPPFLAGS="$CPPFLAGS $X_CFLAGS" + CPPFLAGS=`eval eval eval eval eval eval eval eval eval echo $CPPFLAGS` + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include + #include + #include +int +main () +{ +pam_handle_t *pamh = 0; + char *s = pam_strerror(pamh, PAM_SUCCESS); + ; + return 0; +} +_ACEOF +rm -rf conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\"" +$as_echo "$ac_try_echo") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -rf conftest.er1 + cat conftest.err >&5 + $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest.$ac_objext; then + ac_pam_strerror_args=2 +else + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + + ac_save_CPPFLAGS="$CPPFLAGS" + if test \! -z "$includedir" ; then + CPPFLAGS="$CPPFLAGS -I$includedir" + fi + CPPFLAGS="$CPPFLAGS $X_CFLAGS" + CPPFLAGS=`eval eval eval eval eval eval eval eval eval echo $CPPFLAGS` + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include + #include + #include +int +main () +{ +char *s = + pam_strerror(PAM_SUCCESS); + ; + return 0; +} +_ACEOF +rm -rf conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\"" +$as_echo "$ac_try_echo") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -rf conftest.er1 + cat conftest.err >&5 + $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest.$ac_objext; then + ac_pam_strerror_args=1 +else + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_pam_strerror_args=0 +fi + +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + CPPFLAGS="$ac_save_CPPFLAGS" +fi + +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + CPPFLAGS="$ac_save_CPPFLAGS" + ac_cv_pam_strerror_args=$ac_pam_strerror_args +fi + + ac_pam_strerror_args=$ac_cv_pam_strerror_args + if test "$ac_pam_strerror_args" = 1 ; then + { $as_echo "$as_me:$LINENO: result: one argument" >&5 +$as_echo "one argument" >&6; } + elif test "$ac_pam_strerror_args" = 2 ; then + cat >>confdefs.h <<\_ACEOF +#define PAM_STRERROR_TWO_ARGS 1 +_ACEOF + + { $as_echo "$as_me:$LINENO: result: two arguments" >&5 +$as_echo "two arguments" >&6; } + else + { $as_echo "$as_me:$LINENO: result: unknown" >&5 +$as_echo "unknown" >&6; } + fi + +# Check pam_fail_delay + { $as_echo "$as_me:$LINENO: checking pam_fail_delay in -lpam" >&5 +$as_echo_n "checking pam_fail_delay in -lpam... " >&6; } + if test "${ac_cv_pam_fail_delay+set}" = set; then + $as_echo_n "(cached) " >&6 +else + ac_save_LDFLAGS="$LDFLAGS" + LDFLAGS="-lpam" + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include +int +main () +{ +pam_handle_t *pamh = 0; + unsigned int usec = 1; + int status = pam_fail_delay (pamh, usec); + ; + return 0; +} +_ACEOF +rm -rf conftest.$ac_objext conftest$ac_exeext +if { (ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\"" +$as_echo "$ac_try_echo") >&5 + (eval "$ac_link") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -rf conftest.er1 + cat conftest.err >&5 + $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest$ac_exeext && { + test "$cross_compiling" = yes || + $as_test_x conftest$ac_exeext + }; then + ac_pam_fail_delay=yes +else + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_pam_fail_delay=no +fi + +rm -rf conftest.dSYM +rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ + conftest$ac_exeext conftest.$ac_ext + ac_cv_pam_fail_delay=$ac_pam_fail_delay, + LDFLAGS=$ac_save_LDFLAGS +fi + + + if test "$ac_pam_fail_delay" = yes ; then + { $as_echo "$as_me:$LINENO: result: yes" >&5 +$as_echo "yes" >&6; } + cat >>confdefs.h <<\_ACEOF +#define HAVE_PAM_FAIL_DELAY 1 +_ACEOF + + else + { $as_echo "$as_me:$LINENO: result: no" >&5 +$as_echo "no" >&6; } + fi + + fi +fi + + +############################################################################### +# +# Check for Kerberos. +# +############################################################################### + +have_kerberos=no +have_kerberos5=no +with_kerberos_req=unspecified + + +# Check whether --with-kerberos was given. +if test "${with_kerberos+set}" = set; then + withval=$with_kerberos; with_kerberos="$withval"; with_kerberos_req="$withval" +else + with_kerberos=yes +fi + + + + case "$with_kerberos" in + yes) ;; + no) ;; + + /*) + { $as_echo "$as_me:$LINENO: checking for Kerberos headers" >&5 +$as_echo_n "checking for Kerberos headers... " >&6; } + d=$with_kerberos/include + if test -d $d; then + X_CFLAGS="-I$d $X_CFLAGS" + { $as_echo "$as_me:$LINENO: result: $d" >&5 +$as_echo "$d" >&6; } + else + { $as_echo "$as_me:$LINENO: result: not found ($d: no such directory)" >&5 +$as_echo "not found ($d: no such directory)" >&6; } + fi + + { $as_echo "$as_me:$LINENO: checking for Kerberos libs" >&5 +$as_echo_n "checking for Kerberos libs... " >&6; } + d=$with_kerberos/lib + if test -d $d; then + X_LIBS="-L$d $X_LIBS" + { $as_echo "$as_me:$LINENO: result: $d" >&5 +$as_echo "$d" >&6; } + else + { $as_echo "$as_me:$LINENO: result: not found ($d: no such directory)" >&5 +$as_echo "not found ($d: no such directory)" >&6; } + fi + + # replace the directory string with "yes". + with_kerberos_req="yes" + with_kerberos=$with_kerberos_req + ;; + + *) + echo "" + echo "error: argument to --with-kerberos must be \"yes\", \"no\", or a directory." + echo " If it is a directory, then \`DIR/include' will be added to" + echo " the -I list, and \`DIR/lib' will be added to the -L list." + exit 1 + ;; + esac + + +if test "$enable_locking" = yes -a "$with_kerberos" = yes; then + { $as_echo "$as_me:$LINENO: checking for Kerberos 4" >&5 +$as_echo_n "checking for Kerberos 4... " >&6; } +if test "${ac_cv_kerberos+set}" = set; then + $as_echo_n "(cached) " >&6 +else + + ac_save_CPPFLAGS="$CPPFLAGS" + if test \! -z "$includedir" ; then + CPPFLAGS="$CPPFLAGS -I$includedir" + fi + CPPFLAGS="$CPPFLAGS $X_CFLAGS" + CPPFLAGS=`eval eval eval eval eval eval eval eval eval echo $CPPFLAGS` + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include +int +main () +{ + + ; + return 0; +} +_ACEOF +rm -rf conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\"" +$as_echo "$ac_try_echo") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -rf conftest.er1 + cat conftest.err >&5 + $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest.$ac_objext; then + ac_cv_kerberos=yes +else + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_cv_kerberos=no +fi + +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + CPPFLAGS="$ac_save_CPPFLAGS" +fi +{ $as_echo "$as_me:$LINENO: result: $ac_cv_kerberos" >&5 +$as_echo "$ac_cv_kerberos" >&6; } + { $as_echo "$as_me:$LINENO: checking for Kerberos 5" >&5 +$as_echo_n "checking for Kerberos 5... " >&6; } +if test "${ac_cv_kerberos5+set}" = set; then + $as_echo_n "(cached) " >&6 +else + + ac_save_CPPFLAGS="$CPPFLAGS" + if test \! -z "$includedir" ; then + CPPFLAGS="$CPPFLAGS -I$includedir" + fi + CPPFLAGS="$CPPFLAGS $X_CFLAGS" + CPPFLAGS=`eval eval eval eval eval eval eval eval eval echo $CPPFLAGS` + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include +int +main () +{ + + ; + return 0; +} +_ACEOF +rm -rf conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\"" +$as_echo "$ac_try_echo") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -rf conftest.er1 + cat conftest.err >&5 + $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest.$ac_objext; then + ac_cv_kerberos5=yes +else + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_cv_kerberos5=no +fi + +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + CPPFLAGS="$ac_save_CPPFLAGS" +fi +{ $as_echo "$as_me:$LINENO: result: $ac_cv_kerberos5" >&5 +$as_echo "$ac_cv_kerberos5" >&6; } + + if test "$ac_cv_kerberos" = yes ; then + have_kerberos=yes + cat >>confdefs.h <<\_ACEOF +#define HAVE_KERBEROS 1 +_ACEOF + + fi + + if test "$ac_cv_kerberos5" = yes ; then + + # Andrew Snare wrote: + # + # You were assuming that if kerberosV (krb5) was found, then kerberosIV + # (krb4) was also available. This turns out not to be the case with + # mit-krb-1.2.7; apparently backwards-compatibility with KerberosIV + # is optional. + # + # So, disable kerberosV support if libkrb4 can't be found. + # This is not the best solution, but it makes the compile not fail. + # + + ac_save_CPPFLAGS="$CPPFLAGS" + ac_save_LDFLAGS="$LDFLAGS" +# ac_save_LIBS="$LIBS" + + if test \! -z "$includedir" ; then + CPPFLAGS="$CPPFLAGS -I$includedir" + fi + # note: $X_CFLAGS includes $x_includes + CPPFLAGS="$CPPFLAGS $X_CFLAGS" + + if test \! -z "$libdir" ; then + LDFLAGS="$LDFLAGS -L$libdir" + fi + # note: $X_LIBS includes $x_libraries + LDFLAGS="$LDFLAGS $X_LIBS $X_EXTRA_LIBS" + + CPPFLAGS=`eval eval eval eval eval eval eval eval eval echo $CPPFLAGS` + LDFLAGS=`eval eval eval eval eval eval eval eval eval echo $LDFLAGS` + { $as_echo "$as_me:$LINENO: checking for krb_get_tf_realm in -lkrb4" >&5 +$as_echo_n "checking for krb_get_tf_realm in -lkrb4... " >&6; } +if test "${ac_cv_lib_krb4_krb_get_tf_realm+set}" = set; then + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lkrb4 $LIBS" +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char krb_get_tf_realm (); +int +main () +{ +return krb_get_tf_realm (); + ; + return 0; +} +_ACEOF +rm -rf conftest.$ac_objext conftest$ac_exeext +if { (ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\"" +$as_echo "$ac_try_echo") >&5 + (eval "$ac_link") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -rf conftest.er1 + cat conftest.err >&5 + $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest$ac_exeext && { + test "$cross_compiling" = yes || + $as_test_x conftest$ac_exeext + }; then + ac_cv_lib_krb4_krb_get_tf_realm=yes +else + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_cv_lib_krb4_krb_get_tf_realm=no +fi + +rm -rf conftest.dSYM +rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:$LINENO: result: $ac_cv_lib_krb4_krb_get_tf_realm" >&5 +$as_echo "$ac_cv_lib_krb4_krb_get_tf_realm" >&6; } +if test "x$ac_cv_lib_krb4_krb_get_tf_realm" = x""yes; then + have_kerberos=yes +else + have_kerberos=no +fi + + CPPFLAGS="$ac_save_CPPFLAGS" + LDFLAGS="$ac_save_LDFLAGS" +# LIBS="$ac_save_LIBS" + + if test "$have_kerberos" = yes ; then + have_kerberos5=yes + cat >>confdefs.h <<\_ACEOF +#define HAVE_KERBEROS 1 +_ACEOF + + cat >>confdefs.h <<\_ACEOF +#define HAVE_KERBEROS5 1 +_ACEOF + + else + have_kerberos5=no + { $as_echo "$as_me:$LINENO: WARNING: Cannot find compat lib (libkrb4) needed to use Kerberos 5" >&5 +$as_echo "$as_me: WARNING: Cannot find compat lib (libkrb4) needed to use Kerberos 5" >&2;} + fi + + fi + + if test "$have_kerberos5" = yes ; then + # from Matt Knopp + # (who got it from amu@mit.edu) + + PASSWD_LIBS="$PASSWD_LIBS -lkrb4 -ldes425 -lkrb5 -lk5crypto -lcom_err" + + # jwz: MacOS X uses -lkrb5, but not -lcrypt + + ac_save_CPPFLAGS="$CPPFLAGS" + ac_save_LDFLAGS="$LDFLAGS" +# ac_save_LIBS="$LIBS" + + if test \! -z "$includedir" ; then + CPPFLAGS="$CPPFLAGS -I$includedir" + fi + # note: $X_CFLAGS includes $x_includes + CPPFLAGS="$CPPFLAGS $X_CFLAGS" + + if test \! -z "$libdir" ; then + LDFLAGS="$LDFLAGS -L$libdir" + fi + # note: $X_LIBS includes $x_libraries + LDFLAGS="$LDFLAGS $X_LIBS $X_EXTRA_LIBS" + + CPPFLAGS=`eval eval eval eval eval eval eval eval eval echo $CPPFLAGS` + LDFLAGS=`eval eval eval eval eval eval eval eval eval echo $LDFLAGS` + { $as_echo "$as_me:$LINENO: checking for crypt in -lcrypt" >&5 +$as_echo_n "checking for crypt in -lcrypt... " >&6; } +if test "${ac_cv_lib_crypt_crypt+set}" = set; then + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lcrypt $LIBS" +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char crypt (); +int +main () +{ +return crypt (); + ; + return 0; +} +_ACEOF +rm -rf conftest.$ac_objext conftest$ac_exeext +if { (ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\"" +$as_echo "$ac_try_echo") >&5 + (eval "$ac_link") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -rf conftest.er1 + cat conftest.err >&5 + $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest$ac_exeext && { + test "$cross_compiling" = yes || + $as_test_x conftest$ac_exeext + }; then + ac_cv_lib_crypt_crypt=yes +else + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_cv_lib_crypt_crypt=no +fi + +rm -rf conftest.dSYM +rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:$LINENO: result: $ac_cv_lib_crypt_crypt" >&5 +$as_echo "$ac_cv_lib_crypt_crypt" >&6; } +if test "x$ac_cv_lib_crypt_crypt" = x""yes; then + PASSWD_LIBS="$PASSWD_LIBS -lcrypt" +fi + + CPPFLAGS="$ac_save_CPPFLAGS" + LDFLAGS="$ac_save_LDFLAGS" +# LIBS="$ac_save_LIBS" + + + elif test "$have_kerberos" = yes ; then + # from Tim Showalter for FreeBSD 4.2 + PASSWD_LIBS="$PASSWD_LIBS -lkrb -ldes -lcom_err" + fi + + if test "$have_kerberos" = yes ; then + { $as_echo "$as_me:$LINENO: checking for res_search" >&5 +$as_echo_n "checking for res_search... " >&6; } +if test "${ac_cv_func_res_search+set}" = set; then + $as_echo_n "(cached) " >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +/* Define res_search to an innocuous variant, in case declares res_search. + For example, HP-UX 11i declares gettimeofday. */ +#define res_search innocuous_res_search + +/* System header to define __stub macros and hopefully few prototypes, + which can conflict with char res_search (); below. + Prefer to if __STDC__ is defined, since + exists even on freestanding compilers. */ + +#ifdef __STDC__ +# include +#else +# include +#endif + +#undef res_search + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char res_search (); +/* The GNU C library defines this for functions which it implements + to always fail with ENOSYS. Some functions are actually named + something starting with __ and the normal name is an alias. */ +#if defined __stub_res_search || defined __stub___res_search +choke me +#endif + +int +main () +{ +return res_search (); + ; + return 0; +} +_ACEOF +rm -rf conftest.$ac_objext conftest$ac_exeext +if { (ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\"" +$as_echo "$ac_try_echo") >&5 + (eval "$ac_link") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -rf conftest.er1 + cat conftest.err >&5 + $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest$ac_exeext && { + test "$cross_compiling" = yes || + $as_test_x conftest$ac_exeext + }; then + ac_cv_func_res_search=yes +else + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_cv_func_res_search=no +fi + +rm -rf conftest.dSYM +rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ + conftest$ac_exeext conftest.$ac_ext +fi +{ $as_echo "$as_me:$LINENO: result: $ac_cv_func_res_search" >&5 +$as_echo "$ac_cv_func_res_search" >&6; } +if test "x$ac_cv_func_res_search" = x""yes; then + : +else + { $as_echo "$as_me:$LINENO: checking for res_search in -lresolv" >&5 +$as_echo_n "checking for res_search in -lresolv... " >&6; } +if test "${ac_cv_lib_resolv_res_search+set}" = set; then + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lresolv $LIBS" +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char res_search (); +int +main () +{ +return res_search (); + ; + return 0; +} +_ACEOF +rm -rf conftest.$ac_objext conftest$ac_exeext +if { (ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\"" +$as_echo "$ac_try_echo") >&5 + (eval "$ac_link") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -rf conftest.er1 + cat conftest.err >&5 + $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest$ac_exeext && { + test "$cross_compiling" = yes || + $as_test_x conftest$ac_exeext + }; then + ac_cv_lib_resolv_res_search=yes +else + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_cv_lib_resolv_res_search=no +fi + +rm -rf conftest.dSYM +rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:$LINENO: result: $ac_cv_lib_resolv_res_search" >&5 +$as_echo "$ac_cv_lib_resolv_res_search" >&6; } +if test "x$ac_cv_lib_resolv_res_search" = x""yes; then + PASSWD_LIBS="${PASSWD_LIBS} -lresolv" +else + { $as_echo "$as_me:$LINENO: WARNING: Can't find DNS resolver libraries needed for Kerberos" >&5 +$as_echo "$as_me: WARNING: Can't find DNS resolver libraries needed for Kerberos" >&2;} + +fi + +fi + + fi +fi + + +############################################################################### +# +# Check for the nine billion variants of shadow passwords... +# +############################################################################### + +need_setuid=no + +have_shadow=no +with_shadow_req=unspecified + + +# Check whether --with-shadow was given. +if test "${with_shadow+set}" = set; then + withval=$with_shadow; with_shadow="$withval"; with_shadow_req="$withval" +else + with_shadow=yes +fi + + + + case "$with_shadow" in + yes) ;; + no) ;; + + /*) + { $as_echo "$as_me:$LINENO: checking for shadow password headers" >&5 +$as_echo_n "checking for shadow password headers... " >&6; } + d=$with_shadow/include + if test -d $d; then + X_CFLAGS="-I$d $X_CFLAGS" + { $as_echo "$as_me:$LINENO: result: $d" >&5 +$as_echo "$d" >&6; } + else + { $as_echo "$as_me:$LINENO: result: not found ($d: no such directory)" >&5 +$as_echo "not found ($d: no such directory)" >&6; } + fi + + { $as_echo "$as_me:$LINENO: checking for shadow password libs" >&5 +$as_echo_n "checking for shadow password libs... " >&6; } + d=$with_shadow/lib + if test -d $d; then + X_LIBS="-L$d $X_LIBS" + { $as_echo "$as_me:$LINENO: result: $d" >&5 +$as_echo "$d" >&6; } + else + { $as_echo "$as_me:$LINENO: result: not found ($d: no such directory)" >&5 +$as_echo "not found ($d: no such directory)" >&6; } + fi + + # replace the directory string with "yes". + with_shadow_req="yes" + with_shadow=$with_shadow_req + ;; + + *) + echo "" + echo "error: argument to --with-shadow must be \"yes\", \"no\", or a directory." + echo " If it is a directory, then \`DIR/include' will be added to" + echo " the -I list, and \`DIR/lib' will be added to the -L list." + exit 1 + ;; + esac + + +if test "$enable_locking" = no ; then + with_shadow_req=no + with_shadow=no +fi + + +############################################################################### +# +# Check for Sun "adjunct" passwords. +# +############################################################################### + +if test "$with_shadow" = yes ; then + { $as_echo "$as_me:$LINENO: checking for Sun-style shadow passwords" >&5 +$as_echo_n "checking for Sun-style shadow passwords... " >&6; } +if test "${ac_cv_sun_adjunct+set}" = set; then + $as_echo_n "(cached) " >&6 +else + + ac_save_CPPFLAGS="$CPPFLAGS" + if test \! -z "$includedir" ; then + CPPFLAGS="$CPPFLAGS -I$includedir" + fi + CPPFLAGS="$CPPFLAGS $X_CFLAGS" + CPPFLAGS=`eval eval eval eval eval eval eval eval eval echo $CPPFLAGS` + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include + #include + #include + #include + #include + #include +int +main () +{ +struct passwd_adjunct *p = getpwanam("nobody"); + const char *pw = p->pwa_passwd; + ; + return 0; +} +_ACEOF +rm -rf conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\"" +$as_echo "$ac_try_echo") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -rf conftest.er1 + cat conftest.err >&5 + $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest.$ac_objext; then + ac_cv_sun_adjunct=yes +else + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_cv_sun_adjunct=no +fi + +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + CPPFLAGS="$ac_save_CPPFLAGS" +fi +{ $as_echo "$as_me:$LINENO: result: $ac_cv_sun_adjunct" >&5 +$as_echo "$ac_cv_sun_adjunct" >&6; } + if test "$ac_cv_sun_adjunct" = yes; then + have_shadow_adjunct=yes + have_shadow=yes + need_setuid=yes + fi +fi + + +############################################################################### +# +# Check for DEC and SCO so-called "enhanced" security. +# +############################################################################### + +if test "$with_shadow" = yes ; then + { $as_echo "$as_me:$LINENO: checking for DEC-style shadow passwords" >&5 +$as_echo_n "checking for DEC-style shadow passwords... " >&6; } +if test "${ac_cv_enhanced_passwd+set}" = set; then + $as_echo_n "(cached) " >&6 +else + + ac_save_CPPFLAGS="$CPPFLAGS" + if test \! -z "$includedir" ; then + CPPFLAGS="$CPPFLAGS -I$includedir" + fi + CPPFLAGS="$CPPFLAGS $X_CFLAGS" + CPPFLAGS=`eval eval eval eval eval eval eval eval eval echo $CPPFLAGS` + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include + #include + #include + #include + #include + #include +int +main () +{ +struct pr_passwd *p; + const char *pw; + set_auth_parameters(0, 0); + check_auth_parameters(); + p = getprpwnam("nobody"); + pw = p->ufld.fd_encrypt; + ; + return 0; +} +_ACEOF +rm -rf conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\"" +$as_echo "$ac_try_echo") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -rf conftest.er1 + cat conftest.err >&5 + $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest.$ac_objext; then + ac_cv_enhanced_passwd=yes +else + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_cv_enhanced_passwd=no +fi + +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + CPPFLAGS="$ac_save_CPPFLAGS" +fi +{ $as_echo "$as_me:$LINENO: result: $ac_cv_enhanced_passwd" >&5 +$as_echo "$ac_cv_enhanced_passwd" >&6; } + if test $ac_cv_enhanced_passwd = yes; then + have_shadow_enhanced=yes + have_shadow=yes + need_setuid=yes + + # On SCO, getprpwnam() is in -lprot (which uses nap() from -lx) + # (I'm told it needs -lcurses too, but I don't understand why.) + # But on DEC, it's in -lsecurity. + # + { $as_echo "$as_me:$LINENO: checking for getprpwnam in -lprot" >&5 +$as_echo_n "checking for getprpwnam in -lprot... " >&6; } +if test "${ac_cv_lib_prot_getprpwnam+set}" = set; then + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lprot -lx $LIBS" +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char getprpwnam (); +int +main () +{ +return getprpwnam (); + ; + return 0; +} +_ACEOF +rm -rf conftest.$ac_objext conftest$ac_exeext +if { (ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\"" +$as_echo "$ac_try_echo") >&5 + (eval "$ac_link") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -rf conftest.er1 + cat conftest.err >&5 + $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest$ac_exeext && { + test "$cross_compiling" = yes || + $as_test_x conftest$ac_exeext + }; then + ac_cv_lib_prot_getprpwnam=yes +else + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_cv_lib_prot_getprpwnam=no +fi + +rm -rf conftest.dSYM +rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:$LINENO: result: $ac_cv_lib_prot_getprpwnam" >&5 +$as_echo "$ac_cv_lib_prot_getprpwnam" >&6; } +if test "x$ac_cv_lib_prot_getprpwnam" = x""yes; then + PASSWD_LIBS="$PASSWD_LIBS -lprot -lcurses -lx" +else + { $as_echo "$as_me:$LINENO: checking for getprpwnam in -lsecurity" >&5 +$as_echo_n "checking for getprpwnam in -lsecurity... " >&6; } +if test "${ac_cv_lib_security_getprpwnam+set}" = set; then + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lsecurity $LIBS" +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char getprpwnam (); +int +main () +{ +return getprpwnam (); + ; + return 0; +} +_ACEOF +rm -rf conftest.$ac_objext conftest$ac_exeext +if { (ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\"" +$as_echo "$ac_try_echo") >&5 + (eval "$ac_link") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -rf conftest.er1 + cat conftest.err >&5 + $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest$ac_exeext && { + test "$cross_compiling" = yes || + $as_test_x conftest$ac_exeext + }; then + ac_cv_lib_security_getprpwnam=yes +else + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_cv_lib_security_getprpwnam=no +fi + +rm -rf conftest.dSYM +rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:$LINENO: result: $ac_cv_lib_security_getprpwnam" >&5 +$as_echo "$ac_cv_lib_security_getprpwnam" >&6; } +if test "x$ac_cv_lib_security_getprpwnam" = x""yes; then + PASSWD_LIBS="$PASSWD_LIBS -lsecurity" +fi + +fi + + fi +fi + +############################################################################### +# +# Check for HP's entry in the "Not Invented Here" Sweepstakes. +# +############################################################################### + +if test "$with_shadow" = yes ; then + { $as_echo "$as_me:$LINENO: checking for HP-style shadow passwords" >&5 +$as_echo_n "checking for HP-style shadow passwords... " >&6; } +if test "${ac_cv_hpux_passwd+set}" = set; then + $as_echo_n "(cached) " >&6 +else + + ac_save_CPPFLAGS="$CPPFLAGS" + if test \! -z "$includedir" ; then + CPPFLAGS="$CPPFLAGS -I$includedir" + fi + CPPFLAGS="$CPPFLAGS $X_CFLAGS" + CPPFLAGS=`eval eval eval eval eval eval eval eval eval echo $CPPFLAGS` + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include + #include + #include + #include + #include + #include +int +main () +{ +struct s_passwd *p = getspwnam("nobody"); + const char *pw = p->pw_passwd; + ; + return 0; +} +_ACEOF +rm -rf conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\"" +$as_echo "$ac_try_echo") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -rf conftest.er1 + cat conftest.err >&5 + $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest.$ac_objext; then + ac_cv_hpux_passwd=yes +else + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_cv_hpux_passwd=no +fi + +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + CPPFLAGS="$ac_save_CPPFLAGS" +fi +{ $as_echo "$as_me:$LINENO: result: $ac_cv_hpux_passwd" >&5 +$as_echo "$ac_cv_hpux_passwd" >&6; } + if test "$ac_cv_hpux_passwd" = yes; then + have_shadow_hpux=yes + have_shadow=yes + need_setuid=yes + + # on HPUX, bigcrypt is in -lsec + { $as_echo "$as_me:$LINENO: checking for bigcrypt in -lsec" >&5 +$as_echo_n "checking for bigcrypt in -lsec... " >&6; } +if test "${ac_cv_lib_sec_bigcrypt+set}" = set; then + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lsec $LIBS" +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char bigcrypt (); +int +main () +{ +return bigcrypt (); + ; + return 0; +} +_ACEOF +rm -rf conftest.$ac_objext conftest$ac_exeext +if { (ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\"" +$as_echo "$ac_try_echo") >&5 + (eval "$ac_link") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -rf conftest.er1 + cat conftest.err >&5 + $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest$ac_exeext && { + test "$cross_compiling" = yes || + $as_test_x conftest$ac_exeext + }; then + ac_cv_lib_sec_bigcrypt=yes +else + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_cv_lib_sec_bigcrypt=no +fi + +rm -rf conftest.dSYM +rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:$LINENO: result: $ac_cv_lib_sec_bigcrypt" >&5 +$as_echo "$ac_cv_lib_sec_bigcrypt" >&6; } +if test "x$ac_cv_lib_sec_bigcrypt" = x""yes; then + PASSWD_LIBS="$PASSWD_LIBS -lsec" +fi + + fi +fi + + +############################################################################### +# +# Check for FreeBSD-style shadow passwords. +# +# On FreeBSD, getpwnam() and friends work just like on non-shadow- +# password systems -- except you only get stuff in the pw_passwd field +# if the running program is setuid. So, guess that we've got this +# lossage to contend with if /etc/master.passwd exists, and default to +# a setuid installation. +# +############################################################################### + +if test "$with_shadow" = yes ; then + { $as_echo "$as_me:$LINENO: checking for FreeBSD-style shadow passwords" >&5 +$as_echo_n "checking for FreeBSD-style shadow passwords... " >&6; } +if test "${ac_cv_master_passwd+set}" = set; then + $as_echo_n "(cached) " >&6 +else + if test -f /etc/master.passwd ; then + ac_cv_master_passwd=yes + else + ac_cv_master_passwd=no + fi +fi +{ $as_echo "$as_me:$LINENO: result: $ac_cv_master_passwd" >&5 +$as_echo "$ac_cv_master_passwd" >&6; } + if test "$ac_cv_master_passwd" = yes; then + need_setuid=yes + fi +fi + + +############################################################################### +# +# Check for traditional (ha!) shadow passwords. +# +############################################################################### + +if test "$with_shadow" = yes ; then + { $as_echo "$as_me:$LINENO: checking for generic shadow passwords" >&5 +$as_echo_n "checking for generic shadow passwords... " >&6; } +if test "${ac_cv_shadow+set}" = set; then + $as_echo_n "(cached) " >&6 +else + + ac_save_CPPFLAGS="$CPPFLAGS" + if test \! -z "$includedir" ; then + CPPFLAGS="$CPPFLAGS -I$includedir" + fi + CPPFLAGS="$CPPFLAGS $X_CFLAGS" + CPPFLAGS=`eval eval eval eval eval eval eval eval eval echo $CPPFLAGS` + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include + #include + #include + #include + #include +int +main () +{ +struct spwd *p = getspnam("nobody"); + const char *pw = p->sp_pwdp; + ; + return 0; +} +_ACEOF +rm -rf conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\"" +$as_echo "$ac_try_echo") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -rf conftest.er1 + cat conftest.err >&5 + $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest.$ac_objext; then + ac_cv_shadow=yes +else + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_cv_shadow=no +fi + +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + CPPFLAGS="$ac_save_CPPFLAGS" +fi +{ $as_echo "$as_me:$LINENO: result: $ac_cv_shadow" >&5 +$as_echo "$ac_cv_shadow" >&6; } + if test "$ac_cv_shadow" = yes; then + have_shadow=yes + need_setuid=yes + + # On some systems (UnixWare 2.1), getspnam() is in -lgen instead of -lc. + have_getspnam=no + { $as_echo "$as_me:$LINENO: checking for getspnam in -lc" >&5 +$as_echo_n "checking for getspnam in -lc... " >&6; } +if test "${ac_cv_lib_c_getspnam+set}" = set; then + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lc $LIBS" +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char getspnam (); +int +main () +{ +return getspnam (); + ; + return 0; +} +_ACEOF +rm -rf conftest.$ac_objext conftest$ac_exeext +if { (ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\"" +$as_echo "$ac_try_echo") >&5 + (eval "$ac_link") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -rf conftest.er1 + cat conftest.err >&5 + $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest$ac_exeext && { + test "$cross_compiling" = yes || + $as_test_x conftest$ac_exeext + }; then + ac_cv_lib_c_getspnam=yes +else + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_cv_lib_c_getspnam=no +fi + +rm -rf conftest.dSYM +rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:$LINENO: result: $ac_cv_lib_c_getspnam" >&5 +$as_echo "$ac_cv_lib_c_getspnam" >&6; } +if test "x$ac_cv_lib_c_getspnam" = x""yes; then + have_getspnam=yes +fi + + if test "$have_getspnam" = no ; then + { $as_echo "$as_me:$LINENO: checking for getspnam in -lgen" >&5 +$as_echo_n "checking for getspnam in -lgen... " >&6; } +if test "${ac_cv_lib_gen_getspnam+set}" = set; then + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lgen $LIBS" +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char getspnam (); +int +main () +{ +return getspnam (); + ; + return 0; +} +_ACEOF +rm -rf conftest.$ac_objext conftest$ac_exeext +if { (ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\"" +$as_echo "$ac_try_echo") >&5 + (eval "$ac_link") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -rf conftest.er1 + cat conftest.err >&5 + $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest$ac_exeext && { + test "$cross_compiling" = yes || + $as_test_x conftest$ac_exeext + }; then + ac_cv_lib_gen_getspnam=yes +else + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_cv_lib_gen_getspnam=no +fi + +rm -rf conftest.dSYM +rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:$LINENO: result: $ac_cv_lib_gen_getspnam" >&5 +$as_echo "$ac_cv_lib_gen_getspnam" >&6; } +if test "x$ac_cv_lib_gen_getspnam" = x""yes; then + have_getspnam=yes; PASSWD_LIBS="$PASSWD_LIBS -lgen" +fi + + fi + fi +fi + + +############################################################################### +# +# Check for other libraries needed for non-shadow passwords. +# +############################################################################### + +if test "$enable_locking" = yes ; then + + # On some systems (UnixWare 2.1), crypt() is in -lcrypt instead of -lc. + have_crypt=no + { $as_echo "$as_me:$LINENO: checking for crypt in -lc" >&5 +$as_echo_n "checking for crypt in -lc... " >&6; } +if test "${ac_cv_lib_c_crypt+set}" = set; then + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lc $LIBS" +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char crypt (); +int +main () +{ +return crypt (); + ; + return 0; +} +_ACEOF +rm -rf conftest.$ac_objext conftest$ac_exeext +if { (ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\"" +$as_echo "$ac_try_echo") >&5 + (eval "$ac_link") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -rf conftest.er1 + cat conftest.err >&5 + $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest$ac_exeext && { + test "$cross_compiling" = yes || + $as_test_x conftest$ac_exeext + }; then + ac_cv_lib_c_crypt=yes +else + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_cv_lib_c_crypt=no +fi + +rm -rf conftest.dSYM +rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:$LINENO: result: $ac_cv_lib_c_crypt" >&5 +$as_echo "$ac_cv_lib_c_crypt" >&6; } +if test "x$ac_cv_lib_c_crypt" = x""yes; then + have_crypt=yes +fi + + if test "$have_crypt" = no ; then + { $as_echo "$as_me:$LINENO: checking for crypt in -lcrypt" >&5 +$as_echo_n "checking for crypt in -lcrypt... " >&6; } +if test "${ac_cv_lib_crypt_crypt+set}" = set; then + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lcrypt $LIBS" +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char crypt (); +int +main () +{ +return crypt (); + ; + return 0; +} +_ACEOF +rm -rf conftest.$ac_objext conftest$ac_exeext +if { (ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\"" +$as_echo "$ac_try_echo") >&5 + (eval "$ac_link") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -rf conftest.er1 + cat conftest.err >&5 + $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest$ac_exeext && { + test "$cross_compiling" = yes || + $as_test_x conftest$ac_exeext + }; then + ac_cv_lib_crypt_crypt=yes +else + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_cv_lib_crypt_crypt=no +fi + +rm -rf conftest.dSYM +rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:$LINENO: result: $ac_cv_lib_crypt_crypt" >&5 +$as_echo "$ac_cv_lib_crypt_crypt" >&6; } +if test "x$ac_cv_lib_crypt_crypt" = x""yes; then + have_crypt=yes; PASSWD_LIBS="$PASSWD_LIBS -lcrypt" +fi + + fi +fi + + +# Most of the above shadow mechanisms will have set need_setuid to yes, +# if they were found. But, on some systems, we need setuid even when +# using plain old vanilla passwords. +# +if test "$enable_locking" = yes ; then + case "$host" in + *-hpux* | *-aix* | *-netbsd* | *-freebsd* | *-openbsd* ) + need_setuid=yes + ;; + esac +fi + + +if test "$have_shadow_adjunct" = yes ; then + cat >>confdefs.h <<\_ACEOF +#define HAVE_ADJUNCT_PASSWD 1 +_ACEOF + +elif test "$have_shadow_enhanced" = yes ; then + cat >>confdefs.h <<\_ACEOF +#define HAVE_ENHANCED_PASSWD 1 +_ACEOF + +elif test "$have_shadow_hpux" = yes ; then + cat >>confdefs.h <<\_ACEOF +#define HAVE_HPUX_PASSWD 1 +_ACEOF + +elif test "$have_shadow" = yes ; then + cat >>confdefs.h <<\_ACEOF +#define HAVE_SHADOW_PASSWD 1 +_ACEOF + +fi + + +############################################################################### +# +# Check for external password helper +# On SuSE, instead of having xscreensaver be a setuid program, they +# fork an external program that takes the password on stdin, and +# returns true if that password is a valid one. Then only that +# smaller program needs to be setuid. +# +# (Note that this external program is not a GUI: the GUI is still +# all in xscreensaver itself; the external program just does auth.) +# +############################################################################### + +have_passwd_helper=no +with_passwd_helper_req=unspecified + + +# Check whether --with-passwd-helper was given. +if test "${with_passwd_helper+set}" = set; then + withval=$with_passwd_helper; with_passwd_helper="$withval"; with_passwd_helper_req="$withval" +else + with_passwd_helper=no +fi + +# no HANDLE_X_PATH_ARG for this one + +if test "$enable_locking" = no ; then + with_passwd_helper_req=no + with_passwd_helper=no +fi + +case "$with_passwd_helper" in + ""|no) : ;; + /*) + cat >>confdefs.h <<_ACEOF +#define PASSWD_HELPER_PROGRAM "$with_passwd_helper" +_ACEOF + + have_passwd_helper=yes;; + *) + echo "error: --with-passwd-helper needs full pathname of helper (not '$with_passwd_helper')." >&2 + exit 1 +esac + + +############################################################################### +# +# Check for a login manager for a "New Login" button on the lock dialog. +# Usually this will be "/usr/bin/gdmflexiserver". +# +############################################################################### + +with_login_manager_req=unspecified +default_login_manager_1='gdmflexiserver -ls' +default_login_manager_2='kdmctl reserve' + + +# Check whether --with-login-manager was given. +if test "${with_login_manager+set}" = set; then + withval=$with_login_manager; with_login_manager="$withval"; with_login_manager_req="$withval" +else + with_login_manager=yes +fi + +# no HANDLE_X_PATH_ARG for this one + +if test "$enable_locking" = no ; then + with_login_manager_req=no + with_login_manager=no +fi + +case "$with_login_manager_req" in + no) + with_login_manager="" + ;; + + yes|unspecified) + # Try both defaults, use the one that exists. + + set dummy $default_login_manager_1 ; login_manager_tmp=$2 + unset ac_cv_path_login_manager_tmp # don't cache + # Extract the first word of "$login_manager_tmp", so it can be a program name with args. +set dummy $login_manager_tmp; ac_word=$2 +{ $as_echo "$as_me:$LINENO: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if test "${ac_cv_path_login_manager_tmp+set}" = set; then + $as_echo_n "(cached) " >&6 +else + case $login_manager_tmp in + [\\/]* | ?:[\\/]*) + ac_cv_path_login_manager_tmp="$login_manager_tmp" # Let the user override the test with a path. + ;; + *) + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_path_login_manager_tmp="$as_dir/$ac_word$ac_exec_ext" + $as_echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done +IFS=$as_save_IFS + + ;; +esac +fi +login_manager_tmp=$ac_cv_path_login_manager_tmp +if test -n "$login_manager_tmp"; then + { $as_echo "$as_me:$LINENO: result: $login_manager_tmp" >&5 +$as_echo "$login_manager_tmp" >&6; } +else + { $as_echo "$as_me:$LINENO: result: no" >&5 +$as_echo "no" >&6; } +fi + + + if test ! -z "$login_manager_tmp" ; then + with_login_manager="$default_login_manager_1" + else + set dummy $default_login_manager_2 ; login_manager_tmp=$2 + unset ac_cv_path_login_manager_tmp # don't cache + # Extract the first word of "$login_manager_tmp", so it can be a program name with args. +set dummy $login_manager_tmp; ac_word=$2 +{ $as_echo "$as_me:$LINENO: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if test "${ac_cv_path_login_manager_tmp+set}" = set; then + $as_echo_n "(cached) " >&6 +else + case $login_manager_tmp in + [\\/]* | ?:[\\/]*) + ac_cv_path_login_manager_tmp="$login_manager_tmp" # Let the user override the test with a path. + ;; + *) + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_path_login_manager_tmp="$as_dir/$ac_word$ac_exec_ext" + $as_echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done +IFS=$as_save_IFS + + ;; +esac +fi +login_manager_tmp=$ac_cv_path_login_manager_tmp +if test -n "$login_manager_tmp"; then + { $as_echo "$as_me:$LINENO: result: $login_manager_tmp" >&5 +$as_echo "$login_manager_tmp" >&6; } +else + { $as_echo "$as_me:$LINENO: result: no" >&5 +$as_echo "no" >&6; } +fi + + + if test ! -z "$login_manager_tmp" ; then + with_login_manager="$default_login_manager_2" + else + with_login_manager="" + fi + fi + ;; + + /*) + # absolute path specified on cmd line + set dummy $with_login_manager_req ; login_manager_tmp=$2 + { $as_echo "$as_me:$LINENO: checking for $login_manager_tmp" >&5 +$as_echo_n "checking for $login_manager_tmp... " >&6; } + if test -x "$login_manager_tmp" ; then + { $as_echo "$as_me:$LINENO: result: yes" >&5 +$as_echo "yes" >&6; } + else + { $as_echo "$as_me:$LINENO: result: no" >&5 +$as_echo "no" >&6; } + with_login_manager="" + fi + ;; + + *) + # relative path specified on cmd line + set dummy $with_login_manager_req ; login_manager_tmp=$2 + unset ac_cv_path_login_manager_tmp # don't cache + # Extract the first word of "$login_manager_tmp", so it can be a program name with args. +set dummy $login_manager_tmp; ac_word=$2 +{ $as_echo "$as_me:$LINENO: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if test "${ac_cv_path_login_manager_tmp+set}" = set; then + $as_echo_n "(cached) " >&6 +else + case $login_manager_tmp in + [\\/]* | ?:[\\/]*) + ac_cv_path_login_manager_tmp="$login_manager_tmp" # Let the user override the test with a path. + ;; + *) + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_path_login_manager_tmp="$as_dir/$ac_word$ac_exec_ext" + $as_echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done +IFS=$as_save_IFS + + ;; +esac +fi +login_manager_tmp=$ac_cv_path_login_manager_tmp +if test -n "$login_manager_tmp"; then + { $as_echo "$as_me:$LINENO: result: $login_manager_tmp" >&5 +$as_echo "$login_manager_tmp" >&6; } +else + { $as_echo "$as_me:$LINENO: result: no" >&5 +$as_echo "no" >&6; } +fi + + + if test -z "$login_manager_tmp" ; then + with_login_manager="" + else + with_login_manager="$login_manager_tmp" + fi + ;; +esac +ac_cv_login_manager_program="$with_login_manager" + +NEW_LOGIN_COMMAND_P='' +NEW_LOGIN_COMMAND="$ac_cv_login_manager_program" + +{ $as_echo "$as_me:$LINENO: checking for login manager" >&5 +$as_echo_n "checking for login manager... " >&6; } +if test -z "$NEW_LOGIN_COMMAND" ; then + NEW_LOGIN_COMMAND="$default_login_manager_1" + NEW_LOGIN_COMMAND_P='! ' + { $as_echo "$as_me:$LINENO: result: $NEW_LOGIN_COMMAND (disabled)" >&5 +$as_echo "$NEW_LOGIN_COMMAND (disabled)" >&6; } +else + { $as_echo "$as_me:$LINENO: result: $NEW_LOGIN_COMMAND" >&5 +$as_echo "$NEW_LOGIN_COMMAND" >&6; } +fi + + +############################################################################### +# +# Check for -lgtk (and Gnome stuff) +# +############################################################################### + +have_gtk=no +with_gtk_req=unspecified + +# Check whether --with-gtk was given. +if test "${with_gtk+set}" = set; then + withval=$with_gtk; with_gtk="$withval"; with_gtk_req="$withval" +else + with_gtk=yes +fi + + +# if --with-gtk=/directory/ was specified, remember that directory so that +# we can also look for the `gtk-config' program in that directory. +case "$with_gtk" in + /*) + gtk_dir="$with_gtk" + ;; + *) + gtk_dir="" + ;; +esac + + + case "$with_gtk" in + yes) ;; + no) ;; + + /*) + { $as_echo "$as_me:$LINENO: checking for Gtk headers" >&5 +$as_echo_n "checking for Gtk headers... " >&6; } + d=$with_gtk/include + if test -d $d; then + X_CFLAGS="-I$d $X_CFLAGS" + { $as_echo "$as_me:$LINENO: result: $d" >&5 +$as_echo "$d" >&6; } + else + { $as_echo "$as_me:$LINENO: result: not found ($d: no such directory)" >&5 +$as_echo "not found ($d: no such directory)" >&6; } + fi + + { $as_echo "$as_me:$LINENO: checking for Gtk libs" >&5 +$as_echo_n "checking for Gtk libs... " >&6; } + d=$with_gtk/lib + if test -d $d; then + X_LIBS="-L$d $X_LIBS" + { $as_echo "$as_me:$LINENO: result: $d" >&5 +$as_echo "$d" >&6; } + else + { $as_echo "$as_me:$LINENO: result: not found ($d: no such directory)" >&5 +$as_echo "not found ($d: no such directory)" >&6; } + fi + + # replace the directory string with "yes". + with_gtk_req="yes" + with_gtk=$with_gtk_req + ;; + + *) + echo "" + echo "error: argument to --with-gtk must be \"yes\", \"no\", or a directory." + echo " If it is a directory, then \`DIR/include' will be added to" + echo " the -I list, and \`DIR/lib' will be added to the -L list." + exit 1 + ;; + esac + + +if test "$with_gtk" != yes -a "$with_gtk" != no ; then + echo "error: must be yes or no: --with-gtk=$with_gtk" + exit 1 +fi + + +parse_gtk_version_string() { + # M4 sucks!! + + maj=`echo $ac_gtk_version_string | sed -n 's/\..*//p'` + min=`echo $ac_gtk_version_string | sed -n 's/[^.]*\.\([^.]*\).*/\1/p'` + + ac_gtk_version=`echo "$maj * 1000 + $min" | bc` + if test -z "$ac_gtk_version"; then + ac_gtk_version=unknown + ac_gtk_version_string=unknown + fi +} + +# Find pkg-config... (need this for both gtk and gdk_pixbuf.) +# if the user specified --with-gtk=/foo/ then look there. +# +gtk_path="$PATH" +if test ! -z "$gtk_dir"; then + # canonicalize slashes. + foo=`echo "${gtk_dir}/bin" | sed 's@//*@/@g'` + gtk_path="$foo:$gtk_path" +fi + +for ac_prog in pkg-config +do + # Extract the first word of "$ac_prog", so it can be a program name with args. +set dummy $ac_prog; ac_word=$2 +{ $as_echo "$as_me:$LINENO: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if test "${ac_cv_path_pkg_config+set}" = set; then + $as_echo_n "(cached) " >&6 +else + case $pkg_config in + [\\/]* | ?:[\\/]*) + ac_cv_path_pkg_config="$pkg_config" # Let the user override the test with a path. + ;; + *) + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $gtk_path +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_path_pkg_config="$as_dir/$ac_word$ac_exec_ext" + $as_echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done +IFS=$as_save_IFS + + ;; +esac +fi +pkg_config=$ac_cv_path_pkg_config +if test -n "$pkg_config"; then + { $as_echo "$as_me:$LINENO: result: $pkg_config" >&5 +$as_echo "$pkg_config" >&6; } +else + { $as_echo "$as_me:$LINENO: result: no" >&5 +$as_echo "no" >&6; } +fi + + + test -n "$pkg_config" && break +done + + +if test -z "$pkg_config" ; then + { $as_echo "$as_me:$LINENO: WARNING: pkg-config not found!" >&5 +$as_echo "$as_me: WARNING: pkg-config not found!" >&2;} + pkg_config="false" +fi + + +# Utility function for running pkg-config-based tests... +# +pkgs='' +pkg_check_version() { + if test "$ok" = yes ; then + req="$1" + min="$2" + { $as_echo "$as_me:$LINENO: checking for $req" >&5 +$as_echo_n "checking for $req... " >&6; } + if $pkg_config --exists "$req" ; then + vers=`$pkg_config --modversion "$req"` + if $pkg_config --exists "$req >= $min" ; then + { $as_echo "$as_me:$LINENO: result: $vers" >&5 +$as_echo "$vers" >&6; } + pkgs="$pkgs $req" + return 1 + else + { $as_echo "$as_me:$LINENO: result: $vers (wanted >= $min)" >&5 +$as_echo "$vers (wanted >= $min)" >&6; } + ok=no + return 0 + fi + else + { $as_echo "$as_me:$LINENO: result: no" >&5 +$as_echo "no" >&6; } + ok=no + return 0 + fi + fi +} + + +jurassic_gtk=no +gtk_halfassed=no + +if test "$with_gtk" = yes; then + have_gtk=no + + ok="yes" + pkg_check_version gtk+-2.0 2.0.1 ; ac_gtk_version_string="$vers" + pkg_check_version gmodule-2.0 2.0.0 + pkg_check_version libxml-2.0 2.4.6 + pkg_check_version libglade-2.0 1.99.0 + pkg_check_version gdk-pixbuf-2.0 2.0.0 + pkg_check_version gdk-pixbuf-xlib-2.0 2.0.0 + have_gtk="$ok" + + if test "$have_gtk" = no; then + if test -n "$ac_gtk_version_string" ; then + gtk_halfassed="$ac_gtk_version_string" + gtk_halfassed_lib="$req" + fi + fi + + if test "$have_gtk" = yes; then + parse_gtk_version_string + jurassic_gtk=no + fi + + if test "$have_gtk" = yes; then + { $as_echo "$as_me:$LINENO: checking for Gtk includes" >&5 +$as_echo_n "checking for Gtk includes... " >&6; } +if test "${ac_cv_gtk_config_cflags+set}" = set; then + $as_echo_n "(cached) " >&6 +else + ac_cv_gtk_config_cflags=`$pkg_config --cflags $pkgs` +fi +{ $as_echo "$as_me:$LINENO: result: $ac_cv_gtk_config_cflags" >&5 +$as_echo "$ac_cv_gtk_config_cflags" >&6; } + { $as_echo "$as_me:$LINENO: checking for Gtk libs" >&5 +$as_echo_n "checking for Gtk libs... " >&6; } +if test "${ac_cv_gtk_config_libs+set}" = set; then + $as_echo_n "(cached) " >&6 +else + ac_cv_gtk_config_libs=`$pkg_config --libs $pkgs` +fi +{ $as_echo "$as_me:$LINENO: result: $ac_cv_gtk_config_libs" >&5 +$as_echo "$ac_cv_gtk_config_libs" >&6; } + fi + + ac_gtk_config_cflags=$ac_cv_gtk_config_cflags + ac_gtk_config_libs=$ac_cv_gtk_config_libs + + GTK_EXTRA_OBJS="" + GTK_DATADIR="" + if test "$have_gtk" = yes; then + GTK_DATADIR=`$pkg_config --variable=prefix gtk+-2.0` + GTK_DATADIR="$GTK_DATADIR/share" + fi + + if test "$have_gtk" = yes; then + INCLUDES="$INCLUDES $ac_gtk_config_cflags" + GTK_LIBS="$GTK_LIBS $ac_gtk_config_libs" + cat >>confdefs.h <<\_ACEOF +#define HAVE_GTK 1 +_ACEOF + + cat >>confdefs.h <<\_ACEOF +#define HAVE_GTK2 1 +_ACEOF + + cat >>confdefs.h <<\_ACEOF +#define HAVE_XML 1 +_ACEOF + + fi + +fi + + +# Check for the various Gnome help and URL loading programs. +# +WITH_BROWSER=gnome-open +if test "$have_gtk" = yes; then + for ac_prog in gnome-open +do + # Extract the first word of "$ac_prog", so it can be a program name with args. +set dummy $ac_prog; ac_word=$2 +{ $as_echo "$as_me:$LINENO: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if test "${ac_cv_prog_gnome_open_program+set}" = set; then + $as_echo_n "(cached) " >&6 +else + if test -n "$gnome_open_program"; then + ac_cv_prog_gnome_open_program="$gnome_open_program" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_gnome_open_program="$ac_prog" + $as_echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done +IFS=$as_save_IFS + +fi +fi +gnome_open_program=$ac_cv_prog_gnome_open_program +if test -n "$gnome_open_program"; then + { $as_echo "$as_me:$LINENO: result: $gnome_open_program" >&5 +$as_echo "$gnome_open_program" >&6; } +else + { $as_echo "$as_me:$LINENO: result: no" >&5 +$as_echo "no" >&6; } +fi + + + test -n "$gnome_open_program" && break +done + + for ac_prog in gnome-url-show +do + # Extract the first word of "$ac_prog", so it can be a program name with args. +set dummy $ac_prog; ac_word=$2 +{ $as_echo "$as_me:$LINENO: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if test "${ac_cv_prog_gnome_url_show_program+set}" = set; then + $as_echo_n "(cached) " >&6 +else + if test -n "$gnome_url_show_program"; then + ac_cv_prog_gnome_url_show_program="$gnome_url_show_program" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_gnome_url_show_program="$ac_prog" + $as_echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done +IFS=$as_save_IFS + +fi +fi +gnome_url_show_program=$ac_cv_prog_gnome_url_show_program +if test -n "$gnome_url_show_program"; then + { $as_echo "$as_me:$LINENO: result: $gnome_url_show_program" >&5 +$as_echo "$gnome_url_show_program" >&6; } +else + { $as_echo "$as_me:$LINENO: result: no" >&5 +$as_echo "no" >&6; } +fi + + + test -n "$gnome_url_show_program" && break +done + +fi + + +############################################################################### +# +# Check for -lXm. +# +############################################################################### + +have_motif=no +with_motif_req=unspecified + +# Check whether --with-motif was given. +if test "${with_motif+set}" = set; then + withval=$with_motif; with_motif="$withval"; with_motif_req="$withval" +else + with_motif=no +fi + + + + case "$with_motif" in + yes) ;; + no) ;; + + /*) + { $as_echo "$as_me:$LINENO: checking for Motif headers" >&5 +$as_echo_n "checking for Motif headers... " >&6; } + d=$with_motif/include + if test -d $d; then + X_CFLAGS="-I$d $X_CFLAGS" + { $as_echo "$as_me:$LINENO: result: $d" >&5 +$as_echo "$d" >&6; } + else + { $as_echo "$as_me:$LINENO: result: not found ($d: no such directory)" >&5 +$as_echo "not found ($d: no such directory)" >&6; } + fi + + { $as_echo "$as_me:$LINENO: checking for Motif libs" >&5 +$as_echo_n "checking for Motif libs... " >&6; } + d=$with_motif/lib + if test -d $d; then + X_LIBS="-L$d $X_LIBS" + { $as_echo "$as_me:$LINENO: result: $d" >&5 +$as_echo "$d" >&6; } + else + { $as_echo "$as_me:$LINENO: result: not found ($d: no such directory)" >&5 +$as_echo "not found ($d: no such directory)" >&6; } + fi + + # replace the directory string with "yes". + with_motif_req="yes" + with_motif=$with_motif_req + ;; + + *) + echo "" + echo "error: argument to --with-motif must be \"yes\", \"no\", or a directory." + echo " If it is a directory, then \`DIR/include' will be added to" + echo " the -I list, and \`DIR/lib' will be added to the -L list." + exit 1 + ;; + esac + + +if test "$with_motif" != yes -a "$with_motif" != no ; then + echo "error: must be yes or no: --with-motif=$with_motif" + exit 1 +fi + +if test "$with_motif" = yes; then + have_motif=no + + ac_save_CPPFLAGS="$CPPFLAGS" + if test \! -z "$includedir" ; then + CPPFLAGS="$CPPFLAGS -I$includedir" + fi + CPPFLAGS="$CPPFLAGS $X_CFLAGS" + CPPFLAGS=`eval eval eval eval eval eval eval eval eval echo $CPPFLAGS` + { $as_echo "$as_me:$LINENO: checking for Xm/Xm.h" >&5 +$as_echo_n "checking for Xm/Xm.h... " >&6; } +if test "${ac_cv_header_Xm_Xm_h+set}" = set; then + $as_echo_n "(cached) " >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include + #include + #include + +#include +_ACEOF +rm -rf conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\"" +$as_echo "$ac_try_echo") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -rf conftest.er1 + cat conftest.err >&5 + $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest.$ac_objext; then + ac_cv_header_Xm_Xm_h=yes +else + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_cv_header_Xm_Xm_h=no +fi + +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +{ $as_echo "$as_me:$LINENO: result: $ac_cv_header_Xm_Xm_h" >&5 +$as_echo "$ac_cv_header_Xm_Xm_h" >&6; } +if test "x$ac_cv_header_Xm_Xm_h" = x""yes; then + have_motif=yes + cat >>confdefs.h <<\_ACEOF +#define HAVE_MOTIF 1 +_ACEOF + + MOTIF_LIBS="$MOTIF_LIBS -lXm" +fi + + + CPPFLAGS="$ac_save_CPPFLAGS" +fi + + +if test "$have_motif" = yes; then + + ac_save_CPPFLAGS="$CPPFLAGS" + if test \! -z "$includedir" ; then + CPPFLAGS="$CPPFLAGS -I$includedir" + fi + CPPFLAGS="$CPPFLAGS $X_CFLAGS" + CPPFLAGS=`eval eval eval eval eval eval eval eval eval echo $CPPFLAGS` + { $as_echo "$as_me:$LINENO: checking for Xm/ComboBox.h" >&5 +$as_echo_n "checking for Xm/ComboBox.h... " >&6; } +if test "${ac_cv_header_Xm_ComboBox_h+set}" = set; then + $as_echo_n "(cached) " >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include + #include + #include + +#include +_ACEOF +rm -rf conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\"" +$as_echo "$ac_try_echo") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -rf conftest.er1 + cat conftest.err >&5 + $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest.$ac_objext; then + ac_cv_header_Xm_ComboBox_h=yes +else + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_cv_header_Xm_ComboBox_h=no +fi + +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +{ $as_echo "$as_me:$LINENO: result: $ac_cv_header_Xm_ComboBox_h" >&5 +$as_echo "$ac_cv_header_Xm_ComboBox_h" >&6; } +if test "x$ac_cv_header_Xm_ComboBox_h" = x""yes; then + cat >>confdefs.h <<\_ACEOF +#define HAVE_XMCOMBOBOX 1 +_ACEOF + +fi + + + CPPFLAGS="$ac_save_CPPFLAGS" +fi + + +############################################################################### +# +# Checking whether Motif is really Lesstif. +# +############################################################################### + +have_lesstif=no +if test "$have_motif" = yes ; then + { $as_echo "$as_me:$LINENO: checking whether Motif is really LessTif" >&5 +$as_echo_n "checking whether Motif is really LessTif... " >&6; } +if test "${ac_cv_have_lesstif+set}" = set; then + $as_echo_n "(cached) " >&6 +else + + ac_save_CPPFLAGS="$CPPFLAGS" + if test \! -z "$includedir" ; then + CPPFLAGS="$CPPFLAGS -I$includedir" + fi + CPPFLAGS="$CPPFLAGS $X_CFLAGS" + CPPFLAGS=`eval eval eval eval eval eval eval eval eval echo $CPPFLAGS` + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include +int +main () +{ +long vers = LesstifVersion; + ; + return 0; +} +_ACEOF +rm -rf conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\"" +$as_echo "$ac_try_echo") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -rf conftest.er1 + cat conftest.err >&5 + $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest.$ac_objext; then + ac_cv_have_lesstif=yes +else + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_cv_have_lesstif=no +fi + +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + CPPFLAGS="$ac_save_CPPFLAGS" +fi +{ $as_echo "$as_me:$LINENO: result: $ac_cv_have_lesstif" >&5 +$as_echo "$ac_cv_have_lesstif" >&6; } + have_lesstif=$ac_cv_have_lesstif +fi + + +lesstif_version=unknown +lesstif_version_string=unknown + +if test "$have_lesstif" = yes ; then + ltv=unknown + echo unknown > conftest-lt + { $as_echo "$as_me:$LINENO: checking LessTif version number" >&5 +$as_echo_n "checking LessTif version number... " >&6; } +if test "${ac_cv_lesstif_version_string+set}" = set; then + $as_echo_n "(cached) " >&6 +else + + ac_save_CPPFLAGS="$CPPFLAGS" + if test \! -z "$includedir" ; then + CPPFLAGS="$CPPFLAGS -I$includedir" + fi + CPPFLAGS="$CPPFLAGS $X_CFLAGS" + CPPFLAGS=`eval eval eval eval eval eval eval eval eval echo $CPPFLAGS` + if test "$cross_compiling" = yes; then + ac_cv_lesstif_version=unknown + ac_cv_lesstif_version_string=unknown +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include + #include + int main() { + FILE *f = fopen("conftest-lt", "w"); + if (!f) exit(1); + fprintf(f, "%d %d.%d\n", LesstifVersion, + LESSTIF_VERSION, LESSTIF_REVISION); + fclose(f); + exit(0); + } +_ACEOF +rm -rf conftest$ac_exeext +if { (ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\"" +$as_echo "$ac_try_echo") >&5 + (eval "$ac_link") 2>&5 + ac_status=$? + $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { ac_try='./conftest$ac_exeext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\"" +$as_echo "$ac_try_echo") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ltv=`cat conftest-lt` + ac_cv_lesstif_version=`echo $ltv | sed 's/ .*//'` + ac_cv_lesstif_version_string=`echo $ltv | sed 's/.* //'` +else + $as_echo "$as_me: program exited with status $ac_status" >&5 +$as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +( exit $ac_status ) +ac_cv_lesstif_version=unknown + ac_cv_lesstif_version_string=unknown +fi +rm -rf conftest.dSYM +rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext +fi + + + CPPFLAGS="$ac_save_CPPFLAGS" +fi +{ $as_echo "$as_me:$LINENO: result: $ac_cv_lesstif_version_string" >&5 +$as_echo "$ac_cv_lesstif_version_string" >&6; } + rm -rf conftest-lt + lesstif_version=$ac_cv_lesstif_version + lesstif_version_string=$ac_cv_lesstif_version_string + +fi + + +if test "$have_motif" = yes ; then + mtv=unknown + echo unknown > conftest-mt + { $as_echo "$as_me:$LINENO: checking Motif version number" >&5 +$as_echo_n "checking Motif version number... " >&6; } +if test "${ac_cv_motif_version_string+set}" = set; then + $as_echo_n "(cached) " >&6 +else + + ac_save_CPPFLAGS="$CPPFLAGS" + if test \! -z "$includedir" ; then + CPPFLAGS="$CPPFLAGS -I$includedir" + fi + CPPFLAGS="$CPPFLAGS $X_CFLAGS" + CPPFLAGS=`eval eval eval eval eval eval eval eval eval echo $CPPFLAGS` + if test "$cross_compiling" = yes; then + ac_cv_motif_version=unknown + ac_cv_motif_version_string=unknown +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include + #include + int main() { + FILE *f = fopen("conftest-mt", "w"); + if (!f) exit(1); + fprintf(f, "%d %d.%d\n", XmVersion, + XmVERSION, XmREVISION); + fclose(f); + exit(0); + } +_ACEOF +rm -rf conftest$ac_exeext +if { (ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\"" +$as_echo "$ac_try_echo") >&5 + (eval "$ac_link") 2>&5 + ac_status=$? + $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { ac_try='./conftest$ac_exeext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\"" +$as_echo "$ac_try_echo") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + mtv=`cat conftest-mt` + ac_cv_motif_version=`echo $mtv | sed 's/ .*//'` + ac_cv_motif_version_string=`echo $mtv | sed 's/.* //'` +else + $as_echo "$as_me: program exited with status $ac_status" >&5 +$as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +( exit $ac_status ) +ac_cv_motif_version=unknown + ac_cv_motif_version_string=unknown +fi +rm -rf conftest.dSYM +rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext +fi + + + CPPFLAGS="$ac_save_CPPFLAGS" +fi +{ $as_echo "$as_me:$LINENO: result: $ac_cv_motif_version_string" >&5 +$as_echo "$ac_cv_motif_version_string" >&6; } + rm -rf conftest-mt + motif_version=$ac_cv_motif_version + motif_version_string=$ac_cv_motif_version_string + +fi + + +############################################################################### +# +# Checking whether Motif requires -lXpm. +# +# If this is Motif 2.x, and we have XPM, then link against XPM as well. +# The deal is, Motif 2.x requires XPM -- but it's a compilation option +# of the library whether to build the XPM code into libXm, or whether +# to rely on an external libXm. So the only way to tell whether XPM is +# a link-time requirement is to examine libXm.a, which is very +# difficult to do in an autoconf script. So... if it's Motif 2.x, we +# always link against XPM if the XPM lib exists (and this will be a +# no-op if libXm happens to already have the XPM code in it.) +# +############################################################################### + +motif_requires_xpm=no +if test "$have_motif" = yes ; then + { $as_echo "$as_me:$LINENO: checking whether Motif requires XPM" >&5 +$as_echo_n "checking whether Motif requires XPM... " >&6; } + if test "$motif_version" = "unknown" || test "$motif_version" -ge 2000 + then + motif_requires_xpm=yes + { $as_echo "$as_me:$LINENO: result: maybe" >&5 +$as_echo "maybe" >&6; } + else + { $as_echo "$as_me:$LINENO: result: no" >&5 +$as_echo "no" >&6; } + fi +fi + + +############################################################################### +# +# Checking whether Motif requires -lXp. +# +# Some versions of Motif (2.1.0, at least) require -lXp, the "X Printing +# Extension". Why this extension isn't in -lXext with all the others, +# I have no idea. +# +############################################################################### + +have_xp_ext=no +if test "$have_motif" = yes ; then + have_xp_ext=no + + ac_save_CPPFLAGS="$CPPFLAGS" + ac_save_LDFLAGS="$LDFLAGS" +# ac_save_LIBS="$LIBS" + + if test \! -z "$includedir" ; then + CPPFLAGS="$CPPFLAGS -I$includedir" + fi + # note: $X_CFLAGS includes $x_includes + CPPFLAGS="$CPPFLAGS $X_CFLAGS" + + if test \! -z "$libdir" ; then + LDFLAGS="$LDFLAGS -L$libdir" + fi + # note: $X_LIBS includes $x_libraries + LDFLAGS="$LDFLAGS $X_LIBS $X_EXTRA_LIBS" + + CPPFLAGS=`eval eval eval eval eval eval eval eval eval echo $CPPFLAGS` + LDFLAGS=`eval eval eval eval eval eval eval eval eval echo $LDFLAGS` + { $as_echo "$as_me:$LINENO: checking for XpQueryExtension in -lXp" >&5 +$as_echo_n "checking for XpQueryExtension in -lXp... " >&6; } +if test "${ac_cv_lib_Xp_XpQueryExtension+set}" = set; then + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lXp -lX11 -lXext -lm $LIBS" +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char XpQueryExtension (); +int +main () +{ +return XpQueryExtension (); + ; + return 0; +} +_ACEOF +rm -rf conftest.$ac_objext conftest$ac_exeext +if { (ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\"" +$as_echo "$ac_try_echo") >&5 + (eval "$ac_link") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -rf conftest.er1 + cat conftest.err >&5 + $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest$ac_exeext && { + test "$cross_compiling" = yes || + $as_test_x conftest$ac_exeext + }; then + ac_cv_lib_Xp_XpQueryExtension=yes +else + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_cv_lib_Xp_XpQueryExtension=no +fi + +rm -rf conftest.dSYM +rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:$LINENO: result: $ac_cv_lib_Xp_XpQueryExtension" >&5 +$as_echo "$ac_cv_lib_Xp_XpQueryExtension" >&6; } +if test "x$ac_cv_lib_Xp_XpQueryExtension" = x""yes; then + have_xp_ext=yes; MOTIF_LIBS="$MOTIF_LIBS -lXp" +else + true +fi + + CPPFLAGS="$ac_save_CPPFLAGS" + LDFLAGS="$ac_save_LDFLAGS" +# LIBS="$ac_save_LIBS" + +fi + + +############################################################################### +# +# Checking whether Motif requires -lXintl (for _Xsetlocale.) +# +############################################################################### + +have_xintl=no +if test "$have_motif" = yes ; then + + ac_save_CPPFLAGS="$CPPFLAGS" + ac_save_LDFLAGS="$LDFLAGS" +# ac_save_LIBS="$LIBS" + + if test \! -z "$includedir" ; then + CPPFLAGS="$CPPFLAGS -I$includedir" + fi + # note: $X_CFLAGS includes $x_includes + CPPFLAGS="$CPPFLAGS $X_CFLAGS" + + if test \! -z "$libdir" ; then + LDFLAGS="$LDFLAGS -L$libdir" + fi + # note: $X_LIBS includes $x_libraries + LDFLAGS="$LDFLAGS $X_LIBS $X_EXTRA_LIBS" + + CPPFLAGS=`eval eval eval eval eval eval eval eval eval echo $CPPFLAGS` + LDFLAGS=`eval eval eval eval eval eval eval eval eval echo $LDFLAGS` + { $as_echo "$as_me:$LINENO: checking for _Xsetlocale in -lXintl" >&5 +$as_echo_n "checking for _Xsetlocale in -lXintl... " >&6; } +if test "${ac_cv_lib_Xintl__Xsetlocale+set}" = set; then + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lXintl -lX11 -lXext -lm $LIBS" +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char _Xsetlocale (); +int +main () +{ +return _Xsetlocale (); + ; + return 0; +} +_ACEOF +rm -rf conftest.$ac_objext conftest$ac_exeext +if { (ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\"" +$as_echo "$ac_try_echo") >&5 + (eval "$ac_link") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -rf conftest.er1 + cat conftest.err >&5 + $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest$ac_exeext && { + test "$cross_compiling" = yes || + $as_test_x conftest$ac_exeext + }; then + ac_cv_lib_Xintl__Xsetlocale=yes +else + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_cv_lib_Xintl__Xsetlocale=no +fi + +rm -rf conftest.dSYM +rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:$LINENO: result: $ac_cv_lib_Xintl__Xsetlocale" >&5 +$as_echo "$ac_cv_lib_Xintl__Xsetlocale" >&6; } +if test "x$ac_cv_lib_Xintl__Xsetlocale" = x""yes; then + have_xintl=yes +else + have_xintl=no +fi + + CPPFLAGS="$ac_save_CPPFLAGS" + LDFLAGS="$ac_save_LDFLAGS" +# LIBS="$ac_save_LIBS" + + if test "$have_xintl" = yes; then + MOTIF_LIBS="$MOTIF_LIBS -lXintl" + fi +fi + + +############################################################################### +# +# Check for -lGL or -lMesaGL. +# +############################################################################### + +have_gl=no +ac_have_mesa_gl=no +with_gl_req=unspecified +gl_halfassed=no + +# Check whether --with-gl was given. +if test "${with_gl+set}" = set; then + withval=$with_gl; with_gl="$withval"; with_gl_req="$withval" +else + with_gl=yes +fi + + + + case "$with_gl" in + yes) ;; + no) ;; + + /*) + { $as_echo "$as_me:$LINENO: checking for GL headers" >&5 +$as_echo_n "checking for GL headers... " >&6; } + d=$with_gl/include + if test -d $d; then + X_CFLAGS="-I$d $X_CFLAGS" + { $as_echo "$as_me:$LINENO: result: $d" >&5 +$as_echo "$d" >&6; } + else + { $as_echo "$as_me:$LINENO: result: not found ($d: no such directory)" >&5 +$as_echo "not found ($d: no such directory)" >&6; } + fi + + { $as_echo "$as_me:$LINENO: checking for GL libs" >&5 +$as_echo_n "checking for GL libs... " >&6; } + d=$with_gl/lib + if test -d $d; then + X_LIBS="-L$d $X_LIBS" + { $as_echo "$as_me:$LINENO: result: $d" >&5 +$as_echo "$d" >&6; } + else + { $as_echo "$as_me:$LINENO: result: not found ($d: no such directory)" >&5 +$as_echo "not found ($d: no such directory)" >&6; } + fi + + # replace the directory string with "yes". + with_gl_req="yes" + with_gl=$with_gl_req + ;; + + *) + echo "" + echo "error: argument to --with-gl must be \"yes\", \"no\", or a directory." + echo " If it is a directory, then \`DIR/include' will be added to" + echo " the -I list, and \`DIR/lib' will be added to the -L list." + exit 1 + ;; + esac + + +ac_mesagl_version=unknown +ac_mesagl_version_string=unknown + +if test "$with_gl" = yes; then + + ac_save_CPPFLAGS="$CPPFLAGS" + if test \! -z "$includedir" ; then + CPPFLAGS="$CPPFLAGS -I$includedir" + fi + CPPFLAGS="$CPPFLAGS $X_CFLAGS" + CPPFLAGS=`eval eval eval eval eval eval eval eval eval echo $CPPFLAGS` + if test "${ac_cv_header_GL_gl_h+set}" = set; then + { $as_echo "$as_me:$LINENO: checking for GL/gl.h" >&5 +$as_echo_n "checking for GL/gl.h... " >&6; } +if test "${ac_cv_header_GL_gl_h+set}" = set; then + $as_echo_n "(cached) " >&6 +fi +{ $as_echo "$as_me:$LINENO: result: $ac_cv_header_GL_gl_h" >&5 +$as_echo "$ac_cv_header_GL_gl_h" >&6; } +else + # Is the header compilable? +{ $as_echo "$as_me:$LINENO: checking GL/gl.h usability" >&5 +$as_echo_n "checking GL/gl.h usability... " >&6; } +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +$ac_includes_default +#include +_ACEOF +rm -rf conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\"" +$as_echo "$ac_try_echo") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -rf conftest.er1 + cat conftest.err >&5 + $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest.$ac_objext; then + ac_header_compiler=yes +else + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_header_compiler=no +fi + +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +{ $as_echo "$as_me:$LINENO: result: $ac_header_compiler" >&5 +$as_echo "$ac_header_compiler" >&6; } + +# Is the header present? +{ $as_echo "$as_me:$LINENO: checking GL/gl.h presence" >&5 +$as_echo_n "checking GL/gl.h presence... " >&6; } +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include +_ACEOF +if { (ac_try="$ac_cpp conftest.$ac_ext" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\"" +$as_echo "$ac_try_echo") >&5 + (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -rf conftest.er1 + cat conftest.err >&5 + $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } >/dev/null && { + test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" || + test ! -s conftest.err + }; then + ac_header_preproc=yes +else + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_header_preproc=no +fi + +rm -rf conftest.err conftest.$ac_ext +{ $as_echo "$as_me:$LINENO: result: $ac_header_preproc" >&5 +$as_echo "$ac_header_preproc" >&6; } + +# So? What about this header? +case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in + yes:no: ) + { $as_echo "$as_me:$LINENO: WARNING: GL/gl.h: accepted by the compiler, rejected by the preprocessor!" >&5 +$as_echo "$as_me: WARNING: GL/gl.h: accepted by the compiler, rejected by the preprocessor!" >&2;} + { $as_echo "$as_me:$LINENO: WARNING: GL/gl.h: proceeding with the compiler's result" >&5 +$as_echo "$as_me: WARNING: GL/gl.h: proceeding with the compiler's result" >&2;} + ac_header_preproc=yes + ;; + no:yes:* ) + { $as_echo "$as_me:$LINENO: WARNING: GL/gl.h: present but cannot be compiled" >&5 +$as_echo "$as_me: WARNING: GL/gl.h: present but cannot be compiled" >&2;} + { $as_echo "$as_me:$LINENO: WARNING: GL/gl.h: check for missing prerequisite headers?" >&5 +$as_echo "$as_me: WARNING: GL/gl.h: check for missing prerequisite headers?" >&2;} + { $as_echo "$as_me:$LINENO: WARNING: GL/gl.h: see the Autoconf documentation" >&5 +$as_echo "$as_me: WARNING: GL/gl.h: see the Autoconf documentation" >&2;} + { $as_echo "$as_me:$LINENO: WARNING: GL/gl.h: section \"Present But Cannot Be Compiled\"" >&5 +$as_echo "$as_me: WARNING: GL/gl.h: section \"Present But Cannot Be Compiled\"" >&2;} + { $as_echo "$as_me:$LINENO: WARNING: GL/gl.h: proceeding with the preprocessor's result" >&5 +$as_echo "$as_me: WARNING: GL/gl.h: proceeding with the preprocessor's result" >&2;} + { $as_echo "$as_me:$LINENO: WARNING: GL/gl.h: in the future, the compiler will take precedence" >&5 +$as_echo "$as_me: WARNING: GL/gl.h: in the future, the compiler will take precedence" >&2;} + + ;; +esac +{ $as_echo "$as_me:$LINENO: checking for GL/gl.h" >&5 +$as_echo_n "checking for GL/gl.h... " >&6; } +if test "${ac_cv_header_GL_gl_h+set}" = set; then + $as_echo_n "(cached) " >&6 +else + ac_cv_header_GL_gl_h=$ac_header_preproc +fi +{ $as_echo "$as_me:$LINENO: result: $ac_cv_header_GL_gl_h" >&5 +$as_echo "$ac_cv_header_GL_gl_h" >&6; } + +fi +if test "x$ac_cv_header_GL_gl_h" = x""yes; then + have_gl=yes +else + have_gl=no +fi + + + CPPFLAGS="$ac_save_CPPFLAGS" + if test "$have_gl" = yes ; then + + ac_save_CPPFLAGS="$CPPFLAGS" + if test \! -z "$includedir" ; then + CPPFLAGS="$CPPFLAGS -I$includedir" + fi + CPPFLAGS="$CPPFLAGS $X_CFLAGS" + CPPFLAGS=`eval eval eval eval eval eval eval eval eval echo $CPPFLAGS` + { $as_echo "$as_me:$LINENO: checking for GL/glx.h" >&5 +$as_echo_n "checking for GL/glx.h... " >&6; } +if test "${ac_cv_header_GL_glx_h+set}" = set; then + $as_echo_n "(cached) " >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include + +#include +_ACEOF +rm -rf conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\"" +$as_echo "$ac_try_echo") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -rf conftest.er1 + cat conftest.err >&5 + $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest.$ac_objext; then + ac_cv_header_GL_glx_h=yes +else + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_cv_header_GL_glx_h=no +fi + +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +{ $as_echo "$as_me:$LINENO: result: $ac_cv_header_GL_glx_h" >&5 +$as_echo "$ac_cv_header_GL_glx_h" >&6; } +if test "x$ac_cv_header_GL_glx_h" = x""yes; then + have_gl=yes +else + have_gl=no +fi + + + CPPFLAGS="$ac_save_CPPFLAGS" + fi + + # If we have the headers, try and figure out which vendor it's from. + # + if test "$have_gl" = yes ; then + + # We need to know whether it's MesaGL so that we know which libraries + # to link against. + # + { $as_echo "$as_me:$LINENO: checking whether GL is really MesaGL" >&5 +$as_echo_n "checking whether GL is really MesaGL... " >&6; } +if test "${ac_cv_have_mesa_gl+set}" = set; then + $as_echo_n "(cached) " >&6 +else + ac_cv_have_mesa_gl=no + if test "$ac_macosx" = no; then + # WTF! MacOS 10.5.0 ships the Mesa GL headers! + # It's not really Mesa, is it? + + ac_save_CPPFLAGS="$CPPFLAGS" + if test \! -z "$includedir" ; then + CPPFLAGS="$CPPFLAGS -I$includedir" + fi + CPPFLAGS="$CPPFLAGS $X_CFLAGS" + CPPFLAGS=`eval eval eval eval eval eval eval eval eval echo $CPPFLAGS` + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include + +_ACEOF +if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | + $EGREP "Mesa|MESA" >/dev/null 2>&1; then + ac_cv_have_mesa_gl=yes +fi +rm -rf conftest* + + CPPFLAGS="$ac_save_CPPFLAGS" + fi +fi +{ $as_echo "$as_me:$LINENO: result: $ac_cv_have_mesa_gl" >&5 +$as_echo "$ac_cv_have_mesa_gl" >&6; } + ac_have_mesa_gl=$ac_cv_have_mesa_gl + + gl_lib_1="" + GL_LIBS="" + + if test "$ac_macosx" = yes; then + + # Without these, every link against libGL gets a bunch of useless + # warnings. + # + osx_crud="-bind_at_load -multiply_defined suppress" + { $as_echo "$as_me:$LINENO: result: adding \"$osx_crud\" to GL_LIBS" >&5 +$as_echo "adding \"$osx_crud\" to GL_LIBS" >&6; } + GL_LIBS="$GL_LIBS $osx_crud" + unset osx_crud + + # New lossage in 10.5.0: without this, we get: + # ld: cycle in dylib re-exports with /usr/X11/lib/libGL.dylib + # + osx_crud="/System/Library/Frameworks/OpenGL.framework/Versions/A/Libraries/libGL.dylib" + osx_crud="-Wl,-dylib_file,${osx_crud}:${osx_crud}" + + { $as_echo "$as_me:$LINENO: result: adding \"$osx_crud\" to GL_LIBS" >&5 +$as_echo "adding \"$osx_crud\" to GL_LIBS" >&6; } + GL_LIBS="$GL_LIBS $osx_crud" + unset osx_crud + + # New lossage in 10.6.8: we can't allow -L/opt/local/lib to be in the + # link line, or at runtime XQueryExtension gets a segv due to some kind + # of library version skew. Libs must come from /usr/X11/lib even if + # $prefix and/or $exec_prefix are set to /opt/local/. + # + { $as_echo "$as_me:$LINENO: result: omitting \"$libdir\" from LDFLAGS" >&5 +$as_echo "omitting \"$libdir\" from LDFLAGS" >&6; } + libdir='' + + fi + + + # Some versions of MesaGL are compiled to require -lpthread. + # So if the Mesa headers exist, and -lpthread exists, then always + # link -lpthread after the Mesa libs (be they named -lGL or -lMesaGL.) + # + if test "$ac_have_mesa_gl" = yes; then + { $as_echo "$as_me:$LINENO: checking for pthread_create in -lpthread" >&5 +$as_echo_n "checking for pthread_create in -lpthread... " >&6; } +if test "${ac_cv_lib_pthread_pthread_create+set}" = set; then + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lpthread $LIBS" +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char pthread_create (); +int +main () +{ +return pthread_create (); + ; + return 0; +} +_ACEOF +rm -rf conftest.$ac_objext conftest$ac_exeext +if { (ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\"" +$as_echo "$ac_try_echo") >&5 + (eval "$ac_link") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -rf conftest.er1 + cat conftest.err >&5 + $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest$ac_exeext && { + test "$cross_compiling" = yes || + $as_test_x conftest$ac_exeext + }; then + ac_cv_lib_pthread_pthread_create=yes +else + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_cv_lib_pthread_pthread_create=no +fi + +rm -rf conftest.dSYM +rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:$LINENO: result: $ac_cv_lib_pthread_pthread_create" >&5 +$as_echo "$ac_cv_lib_pthread_pthread_create" >&6; } +if test "x$ac_cv_lib_pthread_pthread_create" = x""yes; then + GL_LIBS="-lpthread" +fi + + fi + + + # If we have Mesa headers, check to see if we can link against -lMesaGL. + # If we don't have Mesa headers, or we don't have -lMesaGL, try -lGL. + # Else, warn that GL is busted. (We have the headers, but no libs.) + # + + if test "$ac_have_mesa_gl" = yes ; then + + ac_save_CPPFLAGS="$CPPFLAGS" + ac_save_LDFLAGS="$LDFLAGS" +# ac_save_LIBS="$LIBS" + + if test \! -z "$includedir" ; then + CPPFLAGS="$CPPFLAGS -I$includedir" + fi + # note: $X_CFLAGS includes $x_includes + CPPFLAGS="$CPPFLAGS $X_CFLAGS" + + if test \! -z "$libdir" ; then + LDFLAGS="$LDFLAGS -L$libdir" + fi + # note: $X_LIBS includes $x_libraries + LDFLAGS="$LDFLAGS $X_LIBS $X_EXTRA_LIBS" + + CPPFLAGS=`eval eval eval eval eval eval eval eval eval echo $CPPFLAGS` + LDFLAGS=`eval eval eval eval eval eval eval eval eval echo $LDFLAGS` + { $as_echo "$as_me:$LINENO: checking for glXCreateContext in -lMesaGL" >&5 +$as_echo_n "checking for glXCreateContext in -lMesaGL... " >&6; } +if test "${ac_cv_lib_MesaGL_glXCreateContext+set}" = set; then + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lMesaGL -lMesaGLU $GL_LIBS -lX11 -lXext $VIDMODE_LIBS -lm $LIBS" +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char glXCreateContext (); +int +main () +{ +return glXCreateContext (); + ; + return 0; +} +_ACEOF +rm -rf conftest.$ac_objext conftest$ac_exeext +if { (ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\"" +$as_echo "$ac_try_echo") >&5 + (eval "$ac_link") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -rf conftest.er1 + cat conftest.err >&5 + $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest$ac_exeext && { + test "$cross_compiling" = yes || + $as_test_x conftest$ac_exeext + }; then + ac_cv_lib_MesaGL_glXCreateContext=yes +else + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_cv_lib_MesaGL_glXCreateContext=no +fi + +rm -rf conftest.dSYM +rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:$LINENO: result: $ac_cv_lib_MesaGL_glXCreateContext" >&5 +$as_echo "$ac_cv_lib_MesaGL_glXCreateContext" >&6; } +if test "x$ac_cv_lib_MesaGL_glXCreateContext" = x""yes; then + gl_lib_1="MesaGL" + GL_LIBS="-lMesaGL -lMesaGLU $VIDMODE_LIBS $GL_LIBS" +fi + + CPPFLAGS="$ac_save_CPPFLAGS" + LDFLAGS="$ac_save_LDFLAGS" +# LIBS="$ac_save_LIBS" + + fi + + if test "$gl_lib_1" = "" ; then + + ac_save_CPPFLAGS="$CPPFLAGS" + ac_save_LDFLAGS="$LDFLAGS" +# ac_save_LIBS="$LIBS" + + if test \! -z "$includedir" ; then + CPPFLAGS="$CPPFLAGS -I$includedir" + fi + # note: $X_CFLAGS includes $x_includes + CPPFLAGS="$CPPFLAGS $X_CFLAGS" + + if test \! -z "$libdir" ; then + LDFLAGS="$LDFLAGS -L$libdir" + fi + # note: $X_LIBS includes $x_libraries + LDFLAGS="$LDFLAGS $X_LIBS $X_EXTRA_LIBS" + + CPPFLAGS=`eval eval eval eval eval eval eval eval eval echo $CPPFLAGS` + LDFLAGS=`eval eval eval eval eval eval eval eval eval echo $LDFLAGS` + { $as_echo "$as_me:$LINENO: checking for glXCreateContext in -lGL" >&5 +$as_echo_n "checking for glXCreateContext in -lGL... " >&6; } +if test "${ac_cv_lib_GL_glXCreateContext+set}" = set; then + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lGL -lGLU $GL_LIBS -lX11 -lXext $VIDMODE_LIBS -lm $LIBS" +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char glXCreateContext (); +int +main () +{ +return glXCreateContext (); + ; + return 0; +} +_ACEOF +rm -rf conftest.$ac_objext conftest$ac_exeext +if { (ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\"" +$as_echo "$ac_try_echo") >&5 + (eval "$ac_link") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -rf conftest.er1 + cat conftest.err >&5 + $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest$ac_exeext && { + test "$cross_compiling" = yes || + $as_test_x conftest$ac_exeext + }; then + ac_cv_lib_GL_glXCreateContext=yes +else + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_cv_lib_GL_glXCreateContext=no +fi + +rm -rf conftest.dSYM +rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:$LINENO: result: $ac_cv_lib_GL_glXCreateContext" >&5 +$as_echo "$ac_cv_lib_GL_glXCreateContext" >&6; } +if test "x$ac_cv_lib_GL_glXCreateContext" = x""yes; then + gl_lib_1="GL" + GL_LIBS="-lGL -lGLU $VIDMODE_LIBS $GL_LIBS" +fi + + CPPFLAGS="$ac_save_CPPFLAGS" + LDFLAGS="$ac_save_LDFLAGS" +# LIBS="$ac_save_LIBS" + + fi + + if test "$gl_lib_1" = "" ; then + # we have headers, but no libs -- bail. + have_gl=no + ac_have_mesa_gl=no + gl_halfassed=yes + else + # linking works -- we can build the GL hacks. + cat >>confdefs.h <<\_ACEOF +#define HAVE_GL 1 +_ACEOF + + if test "$ac_have_mesa_gl" = yes ; then + cat >>confdefs.h <<\_ACEOF +#define HAVE_MESA_GL 1 +_ACEOF + + fi + fi + fi + + + # Now that we know we have GL headers and libs, do some more GL testing. + # + + if test "$have_gl" = yes ; then + # If it's MesaGL, we'd like to issue a warning if the version number + # is less than or equal to 2.6, because that version had a security bug. + # + if test "$ac_have_mesa_gl" = yes; then + + { $as_echo "$as_me:$LINENO: checking MesaGL version number" >&5 +$as_echo_n "checking MesaGL version number... " >&6; } +if test "${ac_cv_mesagl_version_string+set}" = set; then + $as_echo_n "(cached) " >&6 +else + cat > conftest.$ac_ext < +#ifndef MESA_MAJOR_VERSION +# include +# ifdef XMESA_MAJOR_VERSION + /* Around Mesa 3.2, they took out the Mesa version number, so instead, + we have to check the XMesa version number (the number of the X protocol + support, which seems to be the same as the Mesa version number.) + */ +# define MESA_MAJOR_VERSION XMESA_MAJOR_VERSION +# define MESA_MINOR_VERSION XMESA_MINOR_VERSION +# else + /* Oh great. Some time after 3.4, they took out the xmesa.h header file, + so we have no way of telling what version of Mesa this is at all. + So, we'll guess that the osmesa version (the "offscreen protocol") + is less than or equal to the real mesa version number. Except that + if OSmesa is 3.3, assume at least Mesa 3.4, since OSmesa was 3.3 in + Mesa 3.4. And Mesa 3.3 had xmesa.h. What a complete load of shit! + */ +# include +# define MESA_MAJOR_VERSION OSMESA_MAJOR_VERSION +# define MESA_MINOR_VERSION OSMESA_MINOR_VERSION or newer, probably? +# if OSMESA_MAJOR_VERSION == 3 && OSMESA_MINOR_VERSION == 3 +# undef MESA_MINOR_VERSION +# define MESA_MINOR_VERSION 4 or newer, probably? +# endif +# endif +#endif +configure: MESA_MAJOR_VERSION MESA_MINOR_VERSION +EOF + + ac_save_CPPFLAGS="$CPPFLAGS" + if test \! -z "$includedir" ; then + CPPFLAGS="$CPPFLAGS -I$includedir" + fi + CPPFLAGS="$CPPFLAGS $X_CFLAGS" + + mglv=`(eval "$ac_cpp conftest.$ac_ext") 2>&5 | grep configure:` + + # M4 sucks!! + + mglv=`echo "$mglv" | sed -n \ + 's/^configure: *\([0-9][0-9]*\) *\([0-9].*\)$/\1.\2/p'` + + + rm -rf conftest.$ac_ext + + CPPFLAGS="$ac_save_CPPFLAGS" + + if test "$mglv" = ""; then + ac_mesagl_version=unknown + ac_mesagl_version_string=unknown + else + ac_mesagl_version_string="$mglv" + # M4 sucks!! + + maj=`echo "$mglv" | sed -n 's/^\([0-9][0-9]*\)\..*$/\1/p'` + min=`echo "$mglv" | sed -n 's/^.*\.\([0-9][0-9]*\).*$/\1/p'` + + ac_mesagl_version=`echo "$maj * 1000 + $min" | bc` + if test -z "$ac_mesagl_version"; then + ac_mesagl_version=unknown + ac_mesagl_version_string=unknown + fi + fi + ac_cv_mesagl_version=$ac_mesagl_version + ac_cv_mesagl_version_string=$ac_mesagl_version_string + +fi +{ $as_echo "$as_me:$LINENO: result: $ac_cv_mesagl_version_string" >&5 +$as_echo "$ac_cv_mesagl_version_string" >&6; } + ac_mesagl_version=$ac_cv_mesagl_version + ac_mesagl_version_string=$ac_cv_mesagl_version_string + fi + + + # Check for OpenGL 1.1 features. + # + + ac_save_CPPFLAGS="$CPPFLAGS" + ac_save_LDFLAGS="$LDFLAGS" +# ac_save_LIBS="$LIBS" + + if test \! -z "$includedir" ; then + CPPFLAGS="$CPPFLAGS -I$includedir" + fi + # note: $X_CFLAGS includes $x_includes + CPPFLAGS="$CPPFLAGS $X_CFLAGS" + + if test \! -z "$libdir" ; then + LDFLAGS="$LDFLAGS -L$libdir" + fi + # note: $X_LIBS includes $x_libraries + LDFLAGS="$LDFLAGS $X_LIBS $X_EXTRA_LIBS" + + CPPFLAGS=`eval eval eval eval eval eval eval eval eval echo $CPPFLAGS` + LDFLAGS=`eval eval eval eval eval eval eval eval eval echo $LDFLAGS` + as_ac_Lib=`$as_echo "ac_cv_lib_$gl_lib_1''_glBindTexture" | $as_tr_sh` +{ $as_echo "$as_me:$LINENO: checking for glBindTexture in -l$gl_lib_1" >&5 +$as_echo_n "checking for glBindTexture in -l$gl_lib_1... " >&6; } +if { as_var=$as_ac_Lib; eval "test \"\${$as_var+set}\" = set"; }; then + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-l$gl_lib_1 $GL_LIBS -lX11 -lXext -lm $LIBS" +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char glBindTexture (); +int +main () +{ +return glBindTexture (); + ; + return 0; +} +_ACEOF +rm -rf conftest.$ac_objext conftest$ac_exeext +if { (ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\"" +$as_echo "$ac_try_echo") >&5 + (eval "$ac_link") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -rf conftest.er1 + cat conftest.err >&5 + $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest$ac_exeext && { + test "$cross_compiling" = yes || + $as_test_x conftest$ac_exeext + }; then + eval "$as_ac_Lib=yes" +else + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + eval "$as_ac_Lib=no" +fi + +rm -rf conftest.dSYM +rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +ac_res=`eval 'as_val=${'$as_ac_Lib'} + $as_echo "$as_val"'` + { $as_echo "$as_me:$LINENO: result: $ac_res" >&5 +$as_echo "$ac_res" >&6; } +as_val=`eval 'as_val=${'$as_ac_Lib'} + $as_echo "$as_val"'` + if test "x$as_val" = x""yes; then + cat >>confdefs.h <<\_ACEOF +#define HAVE_GLBINDTEXTURE 1 +_ACEOF + +else + true +fi + + CPPFLAGS="$ac_save_CPPFLAGS" + LDFLAGS="$ac_save_LDFLAGS" +# LIBS="$ac_save_LIBS" + + fi + +elif test "$with_gl" != no; then + echo "error: must be yes or no: --with-gl=$with_gl" + exit 1 +fi + + +############################################################################### +# +# Check for -lgle. +# +############################################################################### + +have_gle=no +with_gle_req=unspecified +gle_halfassed=no + +# Check whether --with-gle was given. +if test "${with_gle+set}" = set; then + withval=$with_gle; with_gle="$withval"; with_gle_req="$withval" +else + with_gle=yes +fi + + + + case "$with_gle" in + yes) ;; + no) ;; + + /*) + { $as_echo "$as_me:$LINENO: checking for GLE headers" >&5 +$as_echo_n "checking for GLE headers... " >&6; } + d=$with_gle/include + if test -d $d; then + X_CFLAGS="-I$d $X_CFLAGS" + { $as_echo "$as_me:$LINENO: result: $d" >&5 +$as_echo "$d" >&6; } + else + { $as_echo "$as_me:$LINENO: result: not found ($d: no such directory)" >&5 +$as_echo "not found ($d: no such directory)" >&6; } + fi + + { $as_echo "$as_me:$LINENO: checking for GLE libs" >&5 +$as_echo_n "checking for GLE libs... " >&6; } + d=$with_gle/lib + if test -d $d; then + X_LIBS="-L$d $X_LIBS" + { $as_echo "$as_me:$LINENO: result: $d" >&5 +$as_echo "$d" >&6; } + else + { $as_echo "$as_me:$LINENO: result: not found ($d: no such directory)" >&5 +$as_echo "not found ($d: no such directory)" >&6; } + fi + + # replace the directory string with "yes". + with_gle_req="yes" + with_gle=$with_gle_req + ;; + + *) + echo "" + echo "error: argument to --with-gle must be \"yes\", \"no\", or a directory." + echo " If it is a directory, then \`DIR/include' will be added to" + echo " the -I list, and \`DIR/lib' will be added to the -L list." + exit 1 + ;; + esac + + +GLE_LIBS="" + +if test "$have_gl" = no ; then + true +elif test "$with_gle" = yes; then + + + ac_save_CPPFLAGS="$CPPFLAGS" + if test \! -z "$includedir" ; then + CPPFLAGS="$CPPFLAGS -I$includedir" + fi + CPPFLAGS="$CPPFLAGS $X_CFLAGS" + CPPFLAGS=`eval eval eval eval eval eval eval eval eval echo $CPPFLAGS` + { $as_echo "$as_me:$LINENO: checking for GL/gle.h" >&5 +$as_echo_n "checking for GL/gle.h... " >&6; } +if test "${ac_cv_header_GL_gle_h+set}" = set; then + $as_echo_n "(cached) " >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include + +#include +_ACEOF +rm -rf conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\"" +$as_echo "$ac_try_echo") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -rf conftest.er1 + cat conftest.err >&5 + $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest.$ac_objext; then + ac_cv_header_GL_gle_h=yes +else + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_cv_header_GL_gle_h=no +fi + +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +{ $as_echo "$as_me:$LINENO: result: $ac_cv_header_GL_gle_h" >&5 +$as_echo "$ac_cv_header_GL_gle_h" >&6; } +if test "x$ac_cv_header_GL_gle_h" = x""yes; then + have_gle3=yes +else + have_gle3=no +fi + + + CPPFLAGS="$ac_save_CPPFLAGS" + if test "$have_gle3" = yes ; then + have_gle=yes; + else + + ac_save_CPPFLAGS="$CPPFLAGS" + if test \! -z "$includedir" ; then + CPPFLAGS="$CPPFLAGS -I$includedir" + fi + CPPFLAGS="$CPPFLAGS $X_CFLAGS" + CPPFLAGS=`eval eval eval eval eval eval eval eval eval echo $CPPFLAGS` + { $as_echo "$as_me:$LINENO: checking for GL/gutil.h" >&5 +$as_echo_n "checking for GL/gutil.h... " >&6; } +if test "${ac_cv_header_GL_gutil_h+set}" = set; then + $as_echo_n "(cached) " >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include + +#include +_ACEOF +rm -rf conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\"" +$as_echo "$ac_try_echo") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -rf conftest.er1 + cat conftest.err >&5 + $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest.$ac_objext; then + ac_cv_header_GL_gutil_h=yes +else + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_cv_header_GL_gutil_h=no +fi + +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +{ $as_echo "$as_me:$LINENO: result: $ac_cv_header_GL_gutil_h" >&5 +$as_echo "$ac_cv_header_GL_gutil_h" >&6; } +if test "x$ac_cv_header_GL_gutil_h" = x""yes; then + have_gle=yes +else + have_gle=no +fi + + + CPPFLAGS="$ac_save_CPPFLAGS" + if test "$have_gle" = yes ; then + + ac_save_CPPFLAGS="$CPPFLAGS" + if test \! -z "$includedir" ; then + CPPFLAGS="$CPPFLAGS -I$includedir" + fi + CPPFLAGS="$CPPFLAGS $X_CFLAGS" + CPPFLAGS=`eval eval eval eval eval eval eval eval eval echo $CPPFLAGS` + { $as_echo "$as_me:$LINENO: checking for GL/tube.h" >&5 +$as_echo_n "checking for GL/tube.h... " >&6; } +if test "${ac_cv_header_GL_tube_h+set}" = set; then + $as_echo_n "(cached) " >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include + +#include +_ACEOF +rm -rf conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\"" +$as_echo "$ac_try_echo") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -rf conftest.er1 + cat conftest.err >&5 + $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest.$ac_objext; then + ac_cv_header_GL_tube_h=yes +else + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_cv_header_GL_tube_h=no +fi + +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +{ $as_echo "$as_me:$LINENO: result: $ac_cv_header_GL_tube_h" >&5 +$as_echo "$ac_cv_header_GL_tube_h" >&6; } +if test "x$ac_cv_header_GL_tube_h" = x""yes; then + have_gle=yes +else + have_gle=no +fi + + + CPPFLAGS="$ac_save_CPPFLAGS" + fi + fi + + if test "$have_gle" = yes ; then + have_gle=no + gle_halfassed=yes + + ac_save_CPPFLAGS="$CPPFLAGS" + ac_save_LDFLAGS="$LDFLAGS" +# ac_save_LIBS="$LIBS" + + if test \! -z "$includedir" ; then + CPPFLAGS="$CPPFLAGS -I$includedir" + fi + # note: $X_CFLAGS includes $x_includes + CPPFLAGS="$CPPFLAGS $X_CFLAGS" + + if test \! -z "$libdir" ; then + LDFLAGS="$LDFLAGS -L$libdir" + fi + # note: $X_LIBS includes $x_libraries + LDFLAGS="$LDFLAGS $X_LIBS $X_EXTRA_LIBS" + + CPPFLAGS=`eval eval eval eval eval eval eval eval eval echo $CPPFLAGS` + LDFLAGS=`eval eval eval eval eval eval eval eval eval echo $LDFLAGS` + { $as_echo "$as_me:$LINENO: checking for gleCreateGC in -lgle" >&5 +$as_echo_n "checking for gleCreateGC in -lgle... " >&6; } +if test "${ac_cv_lib_gle_gleCreateGC+set}" = set; then + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lgle $GL_LIBS -lX11 -lXext -lm $LIBS" +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char gleCreateGC (); +int +main () +{ +return gleCreateGC (); + ; + return 0; +} +_ACEOF +rm -rf conftest.$ac_objext conftest$ac_exeext +if { (ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\"" +$as_echo "$ac_try_echo") >&5 + (eval "$ac_link") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -rf conftest.er1 + cat conftest.err >&5 + $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest$ac_exeext && { + test "$cross_compiling" = yes || + $as_test_x conftest$ac_exeext + }; then + ac_cv_lib_gle_gleCreateGC=yes +else + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_cv_lib_gle_gleCreateGC=no +fi + +rm -rf conftest.dSYM +rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:$LINENO: result: $ac_cv_lib_gle_gleCreateGC" >&5 +$as_echo "$ac_cv_lib_gle_gleCreateGC" >&6; } +if test "x$ac_cv_lib_gle_gleCreateGC" = x""yes; then + have_gle=yes; gle_halfassed=no; GLE_LIBS="-lgle" +fi + + CPPFLAGS="$ac_save_CPPFLAGS" + LDFLAGS="$ac_save_LDFLAGS" +# LIBS="$ac_save_LIBS" + + fi + if test "$have_gle" = yes ; then + have_gle=no + gle_halfassed=yes + + # sometimes the libmatrix stuff is included in libgle. look there first. +# +# I don't get it. For some reason, this test passes on SGI, as if +# uview_direction_d() was in libgle -- but it's not, it's in libmatrix. +# Yet the link is succeeding. Why??? +# +# AC_CHECK_X_LIB(gle, uview_direction_d, +# [have_gle=yes; gle_halfassed=no], +# [], $GL_LIBS -lX11 -lXext -lm) + + # As of GLE 3 this is in libgle, and has changed name to uview_direction! + # *sigh* + if test "$have_gle3" = yes ; then + + ac_save_CPPFLAGS="$CPPFLAGS" + ac_save_LDFLAGS="$LDFLAGS" +# ac_save_LIBS="$LIBS" + + if test \! -z "$includedir" ; then + CPPFLAGS="$CPPFLAGS -I$includedir" + fi + # note: $X_CFLAGS includes $x_includes + CPPFLAGS="$CPPFLAGS $X_CFLAGS" + + if test \! -z "$libdir" ; then + LDFLAGS="$LDFLAGS -L$libdir" + fi + # note: $X_LIBS includes $x_libraries + LDFLAGS="$LDFLAGS $X_LIBS $X_EXTRA_LIBS" + + CPPFLAGS=`eval eval eval eval eval eval eval eval eval echo $CPPFLAGS` + LDFLAGS=`eval eval eval eval eval eval eval eval eval echo $LDFLAGS` + { $as_echo "$as_me:$LINENO: checking for uview_direction in -lgle" >&5 +$as_echo_n "checking for uview_direction in -lgle... " >&6; } +if test "${ac_cv_lib_gle_uview_direction+set}" = set; then + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lgle $GL_LIBS -lX11 -lXext -lm $LIBS" +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char uview_direction (); +int +main () +{ +return uview_direction (); + ; + return 0; +} +_ACEOF +rm -rf conftest.$ac_objext conftest$ac_exeext +if { (ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\"" +$as_echo "$ac_try_echo") >&5 + (eval "$ac_link") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -rf conftest.er1 + cat conftest.err >&5 + $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest$ac_exeext && { + test "$cross_compiling" = yes || + $as_test_x conftest$ac_exeext + }; then + ac_cv_lib_gle_uview_direction=yes +else + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_cv_lib_gle_uview_direction=no +fi + +rm -rf conftest.dSYM +rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:$LINENO: result: $ac_cv_lib_gle_uview_direction" >&5 +$as_echo "$ac_cv_lib_gle_uview_direction" >&6; } +if test "x$ac_cv_lib_gle_uview_direction" = x""yes; then + have_gle=yes; gle_halfassed=no +fi + + CPPFLAGS="$ac_save_CPPFLAGS" + LDFLAGS="$ac_save_LDFLAGS" +# LIBS="$ac_save_LIBS" + + fi + # if it wasn't in libgle, then look in libmatrix. + if test "$have_gle" = no ; then + + ac_save_CPPFLAGS="$CPPFLAGS" + ac_save_LDFLAGS="$LDFLAGS" +# ac_save_LIBS="$LIBS" + + if test \! -z "$includedir" ; then + CPPFLAGS="$CPPFLAGS -I$includedir" + fi + # note: $X_CFLAGS includes $x_includes + CPPFLAGS="$CPPFLAGS $X_CFLAGS" + + if test \! -z "$libdir" ; then + LDFLAGS="$LDFLAGS -L$libdir" + fi + # note: $X_LIBS includes $x_libraries + LDFLAGS="$LDFLAGS $X_LIBS $X_EXTRA_LIBS" + + CPPFLAGS=`eval eval eval eval eval eval eval eval eval echo $CPPFLAGS` + LDFLAGS=`eval eval eval eval eval eval eval eval eval echo $LDFLAGS` + { $as_echo "$as_me:$LINENO: checking for uview_direction_d in -lmatrix" >&5 +$as_echo_n "checking for uview_direction_d in -lmatrix... " >&6; } +if test "${ac_cv_lib_matrix_uview_direction_d+set}" = set; then + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lmatrix $GL_LIBS -lX11 -lXext -lm $LIBS" +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char uview_direction_d (); +int +main () +{ +return uview_direction_d (); + ; + return 0; +} +_ACEOF +rm -rf conftest.$ac_objext conftest$ac_exeext +if { (ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\"" +$as_echo "$ac_try_echo") >&5 + (eval "$ac_link") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -rf conftest.er1 + cat conftest.err >&5 + $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest$ac_exeext && { + test "$cross_compiling" = yes || + $as_test_x conftest$ac_exeext + }; then + ac_cv_lib_matrix_uview_direction_d=yes +else + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_cv_lib_matrix_uview_direction_d=no +fi + +rm -rf conftest.dSYM +rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:$LINENO: result: $ac_cv_lib_matrix_uview_direction_d" >&5 +$as_echo "$ac_cv_lib_matrix_uview_direction_d" >&6; } +if test "x$ac_cv_lib_matrix_uview_direction_d" = x""yes; then + have_gle=yes; gle_halfassed=no; + GLE_LIBS="$GLE_LIBS -lmatrix" +fi + + CPPFLAGS="$ac_save_CPPFLAGS" + LDFLAGS="$ac_save_LDFLAGS" +# LIBS="$ac_save_LIBS" + + fi + fi + + if test "$have_gle" = yes ; then + cat >>confdefs.h <<\_ACEOF +#define HAVE_GLE 1 +_ACEOF + + if test "$have_gle3" = yes ; then + cat >>confdefs.h <<\_ACEOF +#define HAVE_GLE3 1 +_ACEOF + + fi + fi + +elif test "$with_gle" != no; then + echo "error: must be yes or no: --with-gle=$with_gle" + exit 1 + +fi + + +############################################################################### +# +# Handle --with-gles +# +############################################################################### + +with_gles_req=unspecified + +# Check whether --with-gles was given. +if test "${with_gles+set}" = set; then + withval=$with_gles; with_gles="$withval"; with_gles_req="$withval" +else + with_gles=no +fi + + + + case "$with_gles" in + yes) ;; + no) ;; + + /*) + { $as_echo "$as_me:$LINENO: checking for JWZGLES headers" >&5 +$as_echo_n "checking for JWZGLES headers... " >&6; } + d=$with_gles/include + if test -d $d; then + X_CFLAGS="-I$d $X_CFLAGS" + { $as_echo "$as_me:$LINENO: result: $d" >&5 +$as_echo "$d" >&6; } + else + { $as_echo "$as_me:$LINENO: result: not found ($d: no such directory)" >&5 +$as_echo "not found ($d: no such directory)" >&6; } + fi + + { $as_echo "$as_me:$LINENO: checking for JWZGLES libs" >&5 +$as_echo_n "checking for JWZGLES libs... " >&6; } + d=$with_gles/lib + if test -d $d; then + X_LIBS="-L$d $X_LIBS" + { $as_echo "$as_me:$LINENO: result: $d" >&5 +$as_echo "$d" >&6; } + else + { $as_echo "$as_me:$LINENO: result: not found ($d: no such directory)" >&5 +$as_echo "not found ($d: no such directory)" >&6; } + fi + + # replace the directory string with "yes". + with_gles_req="yes" + with_gles=$with_gles_req + ;; + + *) + echo "" + echo "error: argument to --with-gles must be \"yes\", \"no\", or a directory." + echo " If it is a directory, then \`DIR/include' will be added to" + echo " the -I list, and \`DIR/lib' will be added to the -L list." + exit 1 + ;; + esac + + +if test "$with_gles" = yes; then + have_gles=yes + cat >>confdefs.h <<\_ACEOF +#define HAVE_JWZGLES 1 +_ACEOF + + JWZGLES_OBJS="jwzgles.o" + { $as_echo "$as_me:$LINENO: result: using OpenGL ES compatiblity shim" >&5 +$as_echo "using OpenGL ES compatiblity shim" >&6; } +elif test "$with_gles" != no; then + echo "error: must be yes or no: --with-gles=$with_xpm" + exit 1 +fi + +# May want to phase out glBitmap even in a non-GLES world. +# +if test "$have_gles" = yes; then + GLFPS_OBJS="fps-gl.o glxfonts.o texfont.o" + GLFONT_OBJS="" +else + cat >>confdefs.h <<\_ACEOF +#define HAVE_GLBITMAP 1 +_ACEOF + + GLFPS_OBJS="fps-gl.o glxfonts.o" + GLFONT_OBJS="texfont.o" +fi + + +############################################################################### +# +# Check for -lgdk_pixbuf. +# These tests are for gdk_pixbuf usage of the hacks, +# not xscreensaver-demo (thus we have to test again to get +# the libraries right: don't want to pull in all of GTK +# for the hacks.) +# +############################################################################### + +have_gdk_pixbuf=no +with_gdk_pixbuf_req=unspecified + +# Check whether --with-pixbuf was given. +if test "${with_pixbuf+set}" = set; then + withval=$with_pixbuf; with_gdk_pixbuf="$withval"; with_gdk_pixbuf_req="$withval" +else + with_gdk_pixbuf=yes +fi + + +# if --with-pixbuf=/directory/ was specified, remember that directory so that +# we can also look for the `gdk-pixbuf-config' program in that directory. +case "$with_gdk_pixbuf" in + /*) + gdk_pixbuf_dir="$with_gdk_pixbuf" + ;; + *) + gdk_pixbuf_dir="" + ;; +esac + + + case "$with_gdk_pixbuf" in + yes) ;; + no) ;; + + /*) + { $as_echo "$as_me:$LINENO: checking for GDK_PIXBUF headers" >&5 +$as_echo_n "checking for GDK_PIXBUF headers... " >&6; } + d=$with_gdk_pixbuf/include + if test -d $d; then + X_CFLAGS="-I$d $X_CFLAGS" + { $as_echo "$as_me:$LINENO: result: $d" >&5 +$as_echo "$d" >&6; } + else + { $as_echo "$as_me:$LINENO: result: not found ($d: no such directory)" >&5 +$as_echo "not found ($d: no such directory)" >&6; } + fi + + { $as_echo "$as_me:$LINENO: checking for GDK_PIXBUF libs" >&5 +$as_echo_n "checking for GDK_PIXBUF libs... " >&6; } + d=$with_gdk_pixbuf/lib + if test -d $d; then + X_LIBS="-L$d $X_LIBS" + { $as_echo "$as_me:$LINENO: result: $d" >&5 +$as_echo "$d" >&6; } + else + { $as_echo "$as_me:$LINENO: result: not found ($d: no such directory)" >&5 +$as_echo "not found ($d: no such directory)" >&6; } + fi + + # replace the directory string with "yes". + with_gdk_pixbuf_req="yes" + with_gdk_pixbuf=$with_gdk_pixbuf_req + ;; + + *) + echo "" + echo "error: argument to --with-pixbuf must be \"yes\", \"no\", or a directory." + echo " If it is a directory, then \`DIR/include' will be added to" + echo " the -I list, and \`DIR/lib' will be added to the -L list." + exit 1 + ;; + esac + + +if test "$with_gdk_pixbuf" != yes -a "$with_gdk_pixbuf" != no ; then + echo "error: must be yes or no: --with-pixbuf=$with_gdk_pixbuf" + exit 1 +fi + +if test "$with_gdk_pixbuf" = yes; then + have_gdk_pixbuf=no + + pkgs='' + ok="yes" + + pkg_check_version gdk-pixbuf-2.0 2.0.0 + pkg_check_version gdk-pixbuf-xlib-2.0 2.0.0 + have_gdk_pixbuf="$ok" + + if test "$have_gdk_pixbuf" = yes; then + { $as_echo "$as_me:$LINENO: checking for gdk-pixbuf includes" >&5 +$as_echo_n "checking for gdk-pixbuf includes... " >&6; } +if test "${ac_cv_gdk_pixbuf_config_cflags+set}" = set; then + $as_echo_n "(cached) " >&6 +else + ac_cv_gdk_pixbuf_config_cflags=`$pkg_config --cflags $pkgs` +fi +{ $as_echo "$as_me:$LINENO: result: $ac_cv_gdk_pixbuf_config_cflags" >&5 +$as_echo "$ac_cv_gdk_pixbuf_config_cflags" >&6; } + { $as_echo "$as_me:$LINENO: checking for gdk-pixbuf libs" >&5 +$as_echo_n "checking for gdk-pixbuf libs... " >&6; } +if test "${ac_cv_gdk_pixbuf_config_libs+set}" = set; then + $as_echo_n "(cached) " >&6 +else + ac_cv_gdk_pixbuf_config_libs=`$pkg_config --libs $pkgs` +fi +{ $as_echo "$as_me:$LINENO: result: $ac_cv_gdk_pixbuf_config_libs" >&5 +$as_echo "$ac_cv_gdk_pixbuf_config_libs" >&6; } + fi + + ac_gdk_pixbuf_config_cflags=$ac_cv_gdk_pixbuf_config_cflags + ac_gdk_pixbuf_config_libs=$ac_cv_gdk_pixbuf_config_libs + + + if test "$have_gdk_pixbuf" = yes; then + # + # we appear to have pixbuf; check for headers/libs to be sure. + # + ac_save_gdk_pixbuf_CPPFLAGS="$CPPFLAGS" + CPPFLAGS="$CPPFLAGS $ac_gdk_pixbuf_config_cflags" + + have_gdk_pixbuf=no + + # check for header A... + + ac_save_CPPFLAGS="$CPPFLAGS" + if test \! -z "$includedir" ; then + CPPFLAGS="$CPPFLAGS -I$includedir" + fi + CPPFLAGS="$CPPFLAGS $X_CFLAGS" + CPPFLAGS=`eval eval eval eval eval eval eval eval eval echo $CPPFLAGS` + if test "${ac_cv_header_gdk_pixbuf_gdk_pixbuf_h+set}" = set; then + { $as_echo "$as_me:$LINENO: checking for gdk-pixbuf/gdk-pixbuf.h" >&5 +$as_echo_n "checking for gdk-pixbuf/gdk-pixbuf.h... " >&6; } +if test "${ac_cv_header_gdk_pixbuf_gdk_pixbuf_h+set}" = set; then + $as_echo_n "(cached) " >&6 +fi +{ $as_echo "$as_me:$LINENO: result: $ac_cv_header_gdk_pixbuf_gdk_pixbuf_h" >&5 +$as_echo "$ac_cv_header_gdk_pixbuf_gdk_pixbuf_h" >&6; } +else + # Is the header compilable? +{ $as_echo "$as_me:$LINENO: checking gdk-pixbuf/gdk-pixbuf.h usability" >&5 +$as_echo_n "checking gdk-pixbuf/gdk-pixbuf.h usability... " >&6; } +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +$ac_includes_default +#include +_ACEOF +rm -rf conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\"" +$as_echo "$ac_try_echo") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -rf conftest.er1 + cat conftest.err >&5 + $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest.$ac_objext; then + ac_header_compiler=yes +else + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_header_compiler=no +fi + +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +{ $as_echo "$as_me:$LINENO: result: $ac_header_compiler" >&5 +$as_echo "$ac_header_compiler" >&6; } + +# Is the header present? +{ $as_echo "$as_me:$LINENO: checking gdk-pixbuf/gdk-pixbuf.h presence" >&5 +$as_echo_n "checking gdk-pixbuf/gdk-pixbuf.h presence... " >&6; } +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include +_ACEOF +if { (ac_try="$ac_cpp conftest.$ac_ext" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\"" +$as_echo "$ac_try_echo") >&5 + (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -rf conftest.er1 + cat conftest.err >&5 + $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } >/dev/null && { + test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" || + test ! -s conftest.err + }; then + ac_header_preproc=yes +else + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_header_preproc=no +fi + +rm -rf conftest.err conftest.$ac_ext +{ $as_echo "$as_me:$LINENO: result: $ac_header_preproc" >&5 +$as_echo "$ac_header_preproc" >&6; } + +# So? What about this header? +case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in + yes:no: ) + { $as_echo "$as_me:$LINENO: WARNING: gdk-pixbuf/gdk-pixbuf.h: accepted by the compiler, rejected by the preprocessor!" >&5 +$as_echo "$as_me: WARNING: gdk-pixbuf/gdk-pixbuf.h: accepted by the compiler, rejected by the preprocessor!" >&2;} + { $as_echo "$as_me:$LINENO: WARNING: gdk-pixbuf/gdk-pixbuf.h: proceeding with the compiler's result" >&5 +$as_echo "$as_me: WARNING: gdk-pixbuf/gdk-pixbuf.h: proceeding with the compiler's result" >&2;} + ac_header_preproc=yes + ;; + no:yes:* ) + { $as_echo "$as_me:$LINENO: WARNING: gdk-pixbuf/gdk-pixbuf.h: present but cannot be compiled" >&5 +$as_echo "$as_me: WARNING: gdk-pixbuf/gdk-pixbuf.h: present but cannot be compiled" >&2;} + { $as_echo "$as_me:$LINENO: WARNING: gdk-pixbuf/gdk-pixbuf.h: check for missing prerequisite headers?" >&5 +$as_echo "$as_me: WARNING: gdk-pixbuf/gdk-pixbuf.h: check for missing prerequisite headers?" >&2;} + { $as_echo "$as_me:$LINENO: WARNING: gdk-pixbuf/gdk-pixbuf.h: see the Autoconf documentation" >&5 +$as_echo "$as_me: WARNING: gdk-pixbuf/gdk-pixbuf.h: see the Autoconf documentation" >&2;} + { $as_echo "$as_me:$LINENO: WARNING: gdk-pixbuf/gdk-pixbuf.h: section \"Present But Cannot Be Compiled\"" >&5 +$as_echo "$as_me: WARNING: gdk-pixbuf/gdk-pixbuf.h: section \"Present But Cannot Be Compiled\"" >&2;} + { $as_echo "$as_me:$LINENO: WARNING: gdk-pixbuf/gdk-pixbuf.h: proceeding with the preprocessor's result" >&5 +$as_echo "$as_me: WARNING: gdk-pixbuf/gdk-pixbuf.h: proceeding with the preprocessor's result" >&2;} + { $as_echo "$as_me:$LINENO: WARNING: gdk-pixbuf/gdk-pixbuf.h: in the future, the compiler will take precedence" >&5 +$as_echo "$as_me: WARNING: gdk-pixbuf/gdk-pixbuf.h: in the future, the compiler will take precedence" >&2;} + + ;; +esac +{ $as_echo "$as_me:$LINENO: checking for gdk-pixbuf/gdk-pixbuf.h" >&5 +$as_echo_n "checking for gdk-pixbuf/gdk-pixbuf.h... " >&6; } +if test "${ac_cv_header_gdk_pixbuf_gdk_pixbuf_h+set}" = set; then + $as_echo_n "(cached) " >&6 +else + ac_cv_header_gdk_pixbuf_gdk_pixbuf_h=$ac_header_preproc +fi +{ $as_echo "$as_me:$LINENO: result: $ac_cv_header_gdk_pixbuf_gdk_pixbuf_h" >&5 +$as_echo "$ac_cv_header_gdk_pixbuf_gdk_pixbuf_h" >&6; } + +fi +if test "x$ac_cv_header_gdk_pixbuf_gdk_pixbuf_h" = x""yes; then + have_gdk_pixbuf=yes +fi + + + CPPFLAGS="$ac_save_CPPFLAGS" + + # if that worked, check for header B... + if test "$have_gdk_pixbuf" = yes; then + have_gdk_pixbuf=no + gdk_pixbuf_halfassed=yes + + ac_save_CPPFLAGS="$CPPFLAGS" + if test \! -z "$includedir" ; then + CPPFLAGS="$CPPFLAGS -I$includedir" + fi + CPPFLAGS="$CPPFLAGS $X_CFLAGS" + CPPFLAGS=`eval eval eval eval eval eval eval eval eval echo $CPPFLAGS` + if test "${ac_cv_header_gdk_pixbuf_gdk_pixbuf_xlib_h+set}" = set; then + { $as_echo "$as_me:$LINENO: checking for gdk-pixbuf/gdk-pixbuf-xlib.h" >&5 +$as_echo_n "checking for gdk-pixbuf/gdk-pixbuf-xlib.h... " >&6; } +if test "${ac_cv_header_gdk_pixbuf_gdk_pixbuf_xlib_h+set}" = set; then + $as_echo_n "(cached) " >&6 +fi +{ $as_echo "$as_me:$LINENO: result: $ac_cv_header_gdk_pixbuf_gdk_pixbuf_xlib_h" >&5 +$as_echo "$ac_cv_header_gdk_pixbuf_gdk_pixbuf_xlib_h" >&6; } +else + # Is the header compilable? +{ $as_echo "$as_me:$LINENO: checking gdk-pixbuf/gdk-pixbuf-xlib.h usability" >&5 +$as_echo_n "checking gdk-pixbuf/gdk-pixbuf-xlib.h usability... " >&6; } +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +$ac_includes_default +#include +_ACEOF +rm -rf conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\"" +$as_echo "$ac_try_echo") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -rf conftest.er1 + cat conftest.err >&5 + $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest.$ac_objext; then + ac_header_compiler=yes +else + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_header_compiler=no +fi + +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +{ $as_echo "$as_me:$LINENO: result: $ac_header_compiler" >&5 +$as_echo "$ac_header_compiler" >&6; } + +# Is the header present? +{ $as_echo "$as_me:$LINENO: checking gdk-pixbuf/gdk-pixbuf-xlib.h presence" >&5 +$as_echo_n "checking gdk-pixbuf/gdk-pixbuf-xlib.h presence... " >&6; } +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include +_ACEOF +if { (ac_try="$ac_cpp conftest.$ac_ext" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\"" +$as_echo "$ac_try_echo") >&5 + (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -rf conftest.er1 + cat conftest.err >&5 + $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } >/dev/null && { + test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" || + test ! -s conftest.err + }; then + ac_header_preproc=yes +else + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_header_preproc=no +fi + +rm -rf conftest.err conftest.$ac_ext +{ $as_echo "$as_me:$LINENO: result: $ac_header_preproc" >&5 +$as_echo "$ac_header_preproc" >&6; } + +# So? What about this header? +case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in + yes:no: ) + { $as_echo "$as_me:$LINENO: WARNING: gdk-pixbuf/gdk-pixbuf-xlib.h: accepted by the compiler, rejected by the preprocessor!" >&5 +$as_echo "$as_me: WARNING: gdk-pixbuf/gdk-pixbuf-xlib.h: accepted by the compiler, rejected by the preprocessor!" >&2;} + { $as_echo "$as_me:$LINENO: WARNING: gdk-pixbuf/gdk-pixbuf-xlib.h: proceeding with the compiler's result" >&5 +$as_echo "$as_me: WARNING: gdk-pixbuf/gdk-pixbuf-xlib.h: proceeding with the compiler's result" >&2;} + ac_header_preproc=yes + ;; + no:yes:* ) + { $as_echo "$as_me:$LINENO: WARNING: gdk-pixbuf/gdk-pixbuf-xlib.h: present but cannot be compiled" >&5 +$as_echo "$as_me: WARNING: gdk-pixbuf/gdk-pixbuf-xlib.h: present but cannot be compiled" >&2;} + { $as_echo "$as_me:$LINENO: WARNING: gdk-pixbuf/gdk-pixbuf-xlib.h: check for missing prerequisite headers?" >&5 +$as_echo "$as_me: WARNING: gdk-pixbuf/gdk-pixbuf-xlib.h: check for missing prerequisite headers?" >&2;} + { $as_echo "$as_me:$LINENO: WARNING: gdk-pixbuf/gdk-pixbuf-xlib.h: see the Autoconf documentation" >&5 +$as_echo "$as_me: WARNING: gdk-pixbuf/gdk-pixbuf-xlib.h: see the Autoconf documentation" >&2;} + { $as_echo "$as_me:$LINENO: WARNING: gdk-pixbuf/gdk-pixbuf-xlib.h: section \"Present But Cannot Be Compiled\"" >&5 +$as_echo "$as_me: WARNING: gdk-pixbuf/gdk-pixbuf-xlib.h: section \"Present But Cannot Be Compiled\"" >&2;} + { $as_echo "$as_me:$LINENO: WARNING: gdk-pixbuf/gdk-pixbuf-xlib.h: proceeding with the preprocessor's result" >&5 +$as_echo "$as_me: WARNING: gdk-pixbuf/gdk-pixbuf-xlib.h: proceeding with the preprocessor's result" >&2;} + { $as_echo "$as_me:$LINENO: WARNING: gdk-pixbuf/gdk-pixbuf-xlib.h: in the future, the compiler will take precedence" >&5 +$as_echo "$as_me: WARNING: gdk-pixbuf/gdk-pixbuf-xlib.h: in the future, the compiler will take precedence" >&2;} + + ;; +esac +{ $as_echo "$as_me:$LINENO: checking for gdk-pixbuf/gdk-pixbuf-xlib.h" >&5 +$as_echo_n "checking for gdk-pixbuf/gdk-pixbuf-xlib.h... " >&6; } +if test "${ac_cv_header_gdk_pixbuf_gdk_pixbuf_xlib_h+set}" = set; then + $as_echo_n "(cached) " >&6 +else + ac_cv_header_gdk_pixbuf_gdk_pixbuf_xlib_h=$ac_header_preproc +fi +{ $as_echo "$as_me:$LINENO: result: $ac_cv_header_gdk_pixbuf_gdk_pixbuf_xlib_h" >&5 +$as_echo "$ac_cv_header_gdk_pixbuf_gdk_pixbuf_xlib_h" >&6; } + +fi +if test "x$ac_cv_header_gdk_pixbuf_gdk_pixbuf_xlib_h" = x""yes; then + have_gdk_pixbuf=yes + gdk_pixbuf_halfassed=no +fi + + + CPPFLAGS="$ac_save_CPPFLAGS" + + # yay, it has a new name in Gtk 2.x... + if test "$have_gdk_pixbuf" = no; then + have_gdk_pixbuf=no + gdk_pixbuf_halfassed=yes + + ac_save_CPPFLAGS="$CPPFLAGS" + if test \! -z "$includedir" ; then + CPPFLAGS="$CPPFLAGS -I$includedir" + fi + CPPFLAGS="$CPPFLAGS $X_CFLAGS" + CPPFLAGS=`eval eval eval eval eval eval eval eval eval echo $CPPFLAGS` + if test "${ac_cv_header_gdk_pixbuf_xlib_gdk_pixbuf_xlib_h+set}" = set; then + { $as_echo "$as_me:$LINENO: checking for gdk-pixbuf-xlib/gdk-pixbuf-xlib.h" >&5 +$as_echo_n "checking for gdk-pixbuf-xlib/gdk-pixbuf-xlib.h... " >&6; } +if test "${ac_cv_header_gdk_pixbuf_xlib_gdk_pixbuf_xlib_h+set}" = set; then + $as_echo_n "(cached) " >&6 +fi +{ $as_echo "$as_me:$LINENO: result: $ac_cv_header_gdk_pixbuf_xlib_gdk_pixbuf_xlib_h" >&5 +$as_echo "$ac_cv_header_gdk_pixbuf_xlib_gdk_pixbuf_xlib_h" >&6; } +else + # Is the header compilable? +{ $as_echo "$as_me:$LINENO: checking gdk-pixbuf-xlib/gdk-pixbuf-xlib.h usability" >&5 +$as_echo_n "checking gdk-pixbuf-xlib/gdk-pixbuf-xlib.h usability... " >&6; } +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +$ac_includes_default +#include +_ACEOF +rm -rf conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\"" +$as_echo "$ac_try_echo") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -rf conftest.er1 + cat conftest.err >&5 + $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest.$ac_objext; then + ac_header_compiler=yes +else + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_header_compiler=no +fi + +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +{ $as_echo "$as_me:$LINENO: result: $ac_header_compiler" >&5 +$as_echo "$ac_header_compiler" >&6; } + +# Is the header present? +{ $as_echo "$as_me:$LINENO: checking gdk-pixbuf-xlib/gdk-pixbuf-xlib.h presence" >&5 +$as_echo_n "checking gdk-pixbuf-xlib/gdk-pixbuf-xlib.h presence... " >&6; } +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include +_ACEOF +if { (ac_try="$ac_cpp conftest.$ac_ext" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\"" +$as_echo "$ac_try_echo") >&5 + (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -rf conftest.er1 + cat conftest.err >&5 + $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } >/dev/null && { + test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" || + test ! -s conftest.err + }; then + ac_header_preproc=yes +else + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_header_preproc=no +fi + +rm -rf conftest.err conftest.$ac_ext +{ $as_echo "$as_me:$LINENO: result: $ac_header_preproc" >&5 +$as_echo "$ac_header_preproc" >&6; } + +# So? What about this header? +case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in + yes:no: ) + { $as_echo "$as_me:$LINENO: WARNING: gdk-pixbuf-xlib/gdk-pixbuf-xlib.h: accepted by the compiler, rejected by the preprocessor!" >&5 +$as_echo "$as_me: WARNING: gdk-pixbuf-xlib/gdk-pixbuf-xlib.h: accepted by the compiler, rejected by the preprocessor!" >&2;} + { $as_echo "$as_me:$LINENO: WARNING: gdk-pixbuf-xlib/gdk-pixbuf-xlib.h: proceeding with the compiler's result" >&5 +$as_echo "$as_me: WARNING: gdk-pixbuf-xlib/gdk-pixbuf-xlib.h: proceeding with the compiler's result" >&2;} + ac_header_preproc=yes + ;; + no:yes:* ) + { $as_echo "$as_me:$LINENO: WARNING: gdk-pixbuf-xlib/gdk-pixbuf-xlib.h: present but cannot be compiled" >&5 +$as_echo "$as_me: WARNING: gdk-pixbuf-xlib/gdk-pixbuf-xlib.h: present but cannot be compiled" >&2;} + { $as_echo "$as_me:$LINENO: WARNING: gdk-pixbuf-xlib/gdk-pixbuf-xlib.h: check for missing prerequisite headers?" >&5 +$as_echo "$as_me: WARNING: gdk-pixbuf-xlib/gdk-pixbuf-xlib.h: check for missing prerequisite headers?" >&2;} + { $as_echo "$as_me:$LINENO: WARNING: gdk-pixbuf-xlib/gdk-pixbuf-xlib.h: see the Autoconf documentation" >&5 +$as_echo "$as_me: WARNING: gdk-pixbuf-xlib/gdk-pixbuf-xlib.h: see the Autoconf documentation" >&2;} + { $as_echo "$as_me:$LINENO: WARNING: gdk-pixbuf-xlib/gdk-pixbuf-xlib.h: section \"Present But Cannot Be Compiled\"" >&5 +$as_echo "$as_me: WARNING: gdk-pixbuf-xlib/gdk-pixbuf-xlib.h: section \"Present But Cannot Be Compiled\"" >&2;} + { $as_echo "$as_me:$LINENO: WARNING: gdk-pixbuf-xlib/gdk-pixbuf-xlib.h: proceeding with the preprocessor's result" >&5 +$as_echo "$as_me: WARNING: gdk-pixbuf-xlib/gdk-pixbuf-xlib.h: proceeding with the preprocessor's result" >&2;} + { $as_echo "$as_me:$LINENO: WARNING: gdk-pixbuf-xlib/gdk-pixbuf-xlib.h: in the future, the compiler will take precedence" >&5 +$as_echo "$as_me: WARNING: gdk-pixbuf-xlib/gdk-pixbuf-xlib.h: in the future, the compiler will take precedence" >&2;} + + ;; +esac +{ $as_echo "$as_me:$LINENO: checking for gdk-pixbuf-xlib/gdk-pixbuf-xlib.h" >&5 +$as_echo_n "checking for gdk-pixbuf-xlib/gdk-pixbuf-xlib.h... " >&6; } +if test "${ac_cv_header_gdk_pixbuf_xlib_gdk_pixbuf_xlib_h+set}" = set; then + $as_echo_n "(cached) " >&6 +else + ac_cv_header_gdk_pixbuf_xlib_gdk_pixbuf_xlib_h=$ac_header_preproc +fi +{ $as_echo "$as_me:$LINENO: result: $ac_cv_header_gdk_pixbuf_xlib_gdk_pixbuf_xlib_h" >&5 +$as_echo "$ac_cv_header_gdk_pixbuf_xlib_gdk_pixbuf_xlib_h" >&6; } + +fi +if test "x$ac_cv_header_gdk_pixbuf_xlib_gdk_pixbuf_xlib_h" = x""yes; then + have_gdk_pixbuf=yes + gdk_pixbuf_halfassed=no +fi + + + CPPFLAGS="$ac_save_CPPFLAGS" + fi + fi + CPPFLAGS="$ac_save_gdk_pixbuf_CPPFLAGS" + fi + + if test "$have_gdk_pixbuf" = yes; then + # we have the headers, now check for the libraries + have_gdk_pixbuf=no + gdk_pixbuf_halfassed=yes + + { $as_echo "$as_me:$LINENO: result: checking for gdk_pixbuf usability..." >&5 +$as_echo "checking for gdk_pixbuf usability..." >&6; } + + # library A... + + ac_save_CPPFLAGS="$CPPFLAGS" + ac_save_LDFLAGS="$LDFLAGS" +# ac_save_LIBS="$LIBS" + + if test \! -z "$includedir" ; then + CPPFLAGS="$CPPFLAGS -I$includedir" + fi + # note: $X_CFLAGS includes $x_includes + CPPFLAGS="$CPPFLAGS $X_CFLAGS" + + if test \! -z "$libdir" ; then + LDFLAGS="$LDFLAGS -L$libdir" + fi + # note: $X_LIBS includes $x_libraries + LDFLAGS="$LDFLAGS $X_LIBS $X_EXTRA_LIBS" + + CPPFLAGS=`eval eval eval eval eval eval eval eval eval echo $CPPFLAGS` + LDFLAGS=`eval eval eval eval eval eval eval eval eval echo $LDFLAGS` + { $as_echo "$as_me:$LINENO: checking for gdk_pixbuf_new_from_file in -lc" >&5 +$as_echo_n "checking for gdk_pixbuf_new_from_file in -lc... " >&6; } +if test "${ac_cv_lib_c_gdk_pixbuf_new_from_file+set}" = set; then + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lc $ac_gdk_pixbuf_config_libs -lX11 -lXext -lm $LIBS" +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char gdk_pixbuf_new_from_file (); +int +main () +{ +return gdk_pixbuf_new_from_file (); + ; + return 0; +} +_ACEOF +rm -rf conftest.$ac_objext conftest$ac_exeext +if { (ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\"" +$as_echo "$ac_try_echo") >&5 + (eval "$ac_link") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -rf conftest.er1 + cat conftest.err >&5 + $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest$ac_exeext && { + test "$cross_compiling" = yes || + $as_test_x conftest$ac_exeext + }; then + ac_cv_lib_c_gdk_pixbuf_new_from_file=yes +else + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_cv_lib_c_gdk_pixbuf_new_from_file=no +fi + +rm -rf conftest.dSYM +rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:$LINENO: result: $ac_cv_lib_c_gdk_pixbuf_new_from_file" >&5 +$as_echo "$ac_cv_lib_c_gdk_pixbuf_new_from_file" >&6; } +if test "x$ac_cv_lib_c_gdk_pixbuf_new_from_file" = x""yes; then + have_gdk_pixbuf=yes +fi + + CPPFLAGS="$ac_save_CPPFLAGS" + LDFLAGS="$ac_save_LDFLAGS" +# LIBS="$ac_save_LIBS" + + # library B... + if test "$have_gdk_pixbuf" = yes; then + have_gdk_pixbuf=no + + ac_save_CPPFLAGS="$CPPFLAGS" + ac_save_LDFLAGS="$LDFLAGS" +# ac_save_LIBS="$LIBS" + + if test \! -z "$includedir" ; then + CPPFLAGS="$CPPFLAGS -I$includedir" + fi + # note: $X_CFLAGS includes $x_includes + CPPFLAGS="$CPPFLAGS $X_CFLAGS" + + if test \! -z "$libdir" ; then + LDFLAGS="$LDFLAGS -L$libdir" + fi + # note: $X_LIBS includes $x_libraries + LDFLAGS="$LDFLAGS $X_LIBS $X_EXTRA_LIBS" + + CPPFLAGS=`eval eval eval eval eval eval eval eval eval echo $CPPFLAGS` + LDFLAGS=`eval eval eval eval eval eval eval eval eval echo $LDFLAGS` + { $as_echo "$as_me:$LINENO: checking for gdk_pixbuf_xlib_init in -lc" >&5 +$as_echo_n "checking for gdk_pixbuf_xlib_init in -lc... " >&6; } +if test "${ac_cv_lib_c_gdk_pixbuf_xlib_init+set}" = set; then + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lc $ac_gdk_pixbuf_config_libs -lX11 -lXext -lm $LIBS" +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char gdk_pixbuf_xlib_init (); +int +main () +{ +return gdk_pixbuf_xlib_init (); + ; + return 0; +} +_ACEOF +rm -rf conftest.$ac_objext conftest$ac_exeext +if { (ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\"" +$as_echo "$ac_try_echo") >&5 + (eval "$ac_link") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -rf conftest.er1 + cat conftest.err >&5 + $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest$ac_exeext && { + test "$cross_compiling" = yes || + $as_test_x conftest$ac_exeext + }; then + ac_cv_lib_c_gdk_pixbuf_xlib_init=yes +else + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_cv_lib_c_gdk_pixbuf_xlib_init=no +fi + +rm -rf conftest.dSYM +rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:$LINENO: result: $ac_cv_lib_c_gdk_pixbuf_xlib_init" >&5 +$as_echo "$ac_cv_lib_c_gdk_pixbuf_xlib_init" >&6; } +if test "x$ac_cv_lib_c_gdk_pixbuf_xlib_init" = x""yes; then + have_gdk_pixbuf=yes + gdk_pixbuf_halfassed=no +fi + + CPPFLAGS="$ac_save_CPPFLAGS" + LDFLAGS="$ac_save_LDFLAGS" +# LIBS="$ac_save_LIBS" + + fi + fi + + if test "$have_gdk_pixbuf" = yes; then + INCLUDES="$INCLUDES $ac_gdk_pixbuf_config_cflags" + XPM_LIBS="$ac_gdk_pixbuf_config_libs" + cat >>confdefs.h <<\_ACEOF +#define HAVE_GDK_PIXBUF 1 +_ACEOF + + else + { $as_echo "$as_me:$LINENO: result: checking for gdk_pixbuf usability... no" >&5 +$as_echo "checking for gdk_pixbuf usability... no" >&6; } + fi + + if test "$have_gdk_pixbuf" = yes; then + + ac_save_CPPFLAGS="$CPPFLAGS" + ac_save_LDFLAGS="$LDFLAGS" +# ac_save_LIBS="$LIBS" + + if test \! -z "$includedir" ; then + CPPFLAGS="$CPPFLAGS -I$includedir" + fi + # note: $X_CFLAGS includes $x_includes + CPPFLAGS="$CPPFLAGS $X_CFLAGS" + + if test \! -z "$libdir" ; then + LDFLAGS="$LDFLAGS -L$libdir" + fi + # note: $X_LIBS includes $x_libraries + LDFLAGS="$LDFLAGS $X_LIBS $X_EXTRA_LIBS" + + CPPFLAGS=`eval eval eval eval eval eval eval eval eval echo $CPPFLAGS` + LDFLAGS=`eval eval eval eval eval eval eval eval eval echo $LDFLAGS` + { $as_echo "$as_me:$LINENO: checking for gdk_pixbuf_apply_embedded_orientation in -lc" >&5 +$as_echo_n "checking for gdk_pixbuf_apply_embedded_orientation in -lc... " >&6; } +if test "${ac_cv_lib_c_gdk_pixbuf_apply_embedded_orientation+set}" = set; then + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lc $ac_gdk_pixbuf_config_libs -lX11 -lXext -lm $LIBS" +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char gdk_pixbuf_apply_embedded_orientation (); +int +main () +{ +return gdk_pixbuf_apply_embedded_orientation (); + ; + return 0; +} +_ACEOF +rm -rf conftest.$ac_objext conftest$ac_exeext +if { (ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\"" +$as_echo "$ac_try_echo") >&5 + (eval "$ac_link") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -rf conftest.er1 + cat conftest.err >&5 + $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest$ac_exeext && { + test "$cross_compiling" = yes || + $as_test_x conftest$ac_exeext + }; then + ac_cv_lib_c_gdk_pixbuf_apply_embedded_orientation=yes +else + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_cv_lib_c_gdk_pixbuf_apply_embedded_orientation=no +fi + +rm -rf conftest.dSYM +rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:$LINENO: result: $ac_cv_lib_c_gdk_pixbuf_apply_embedded_orientation" >&5 +$as_echo "$ac_cv_lib_c_gdk_pixbuf_apply_embedded_orientation" >&6; } +if test "x$ac_cv_lib_c_gdk_pixbuf_apply_embedded_orientation" = x""yes; then + cat >>confdefs.h <<\_ACEOF +#define HAVE_GDK_PIXBUF_APPLY_EMBEDDED_ORIENTATION 1 +_ACEOF + +fi + + CPPFLAGS="$ac_save_CPPFLAGS" + LDFLAGS="$ac_save_LDFLAGS" +# LIBS="$ac_save_LIBS" + + fi +fi + + +############################################################################### +# +# Check for -lXpm. +# +############################################################################### + +have_xpm=no +with_xpm_req=unspecified + +# Check whether --with-xpm was given. +if test "${with_xpm+set}" = set; then + withval=$with_xpm; with_xpm="$withval"; with_xpm_req="$withval" +else + with_xpm=yes +fi + + + + case "$with_xpm" in + yes) ;; + no) ;; + + /*) + { $as_echo "$as_me:$LINENO: checking for XPM headers" >&5 +$as_echo_n "checking for XPM headers... " >&6; } + d=$with_xpm/include + if test -d $d; then + X_CFLAGS="-I$d $X_CFLAGS" + { $as_echo "$as_me:$LINENO: result: $d" >&5 +$as_echo "$d" >&6; } + else + { $as_echo "$as_me:$LINENO: result: not found ($d: no such directory)" >&5 +$as_echo "not found ($d: no such directory)" >&6; } + fi + + { $as_echo "$as_me:$LINENO: checking for XPM libs" >&5 +$as_echo_n "checking for XPM libs... " >&6; } + d=$with_xpm/lib + if test -d $d; then + X_LIBS="-L$d $X_LIBS" + { $as_echo "$as_me:$LINENO: result: $d" >&5 +$as_echo "$d" >&6; } + else + { $as_echo "$as_me:$LINENO: result: not found ($d: no such directory)" >&5 +$as_echo "not found ($d: no such directory)" >&6; } + fi + + # replace the directory string with "yes". + with_xpm_req="yes" + with_xpm=$with_xpm_req + ;; + + *) + echo "" + echo "error: argument to --with-xpm must be \"yes\", \"no\", or a directory." + echo " If it is a directory, then \`DIR/include' will be added to" + echo " the -I list, and \`DIR/lib' will be added to the -L list." + exit 1 + ;; + esac + + +if test "$with_xpm" = yes; then + + ac_save_CPPFLAGS="$CPPFLAGS" + if test \! -z "$includedir" ; then + CPPFLAGS="$CPPFLAGS -I$includedir" + fi + CPPFLAGS="$CPPFLAGS $X_CFLAGS" + CPPFLAGS=`eval eval eval eval eval eval eval eval eval echo $CPPFLAGS` + { $as_echo "$as_me:$LINENO: checking for X11/xpm.h" >&5 +$as_echo_n "checking for X11/xpm.h... " >&6; } +if test "${ac_cv_header_X11_xpm_h+set}" = set; then + $as_echo_n "(cached) " >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include + +#include +_ACEOF +rm -rf conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\"" +$as_echo "$ac_try_echo") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -rf conftest.er1 + cat conftest.err >&5 + $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest.$ac_objext; then + ac_cv_header_X11_xpm_h=yes +else + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_cv_header_X11_xpm_h=no +fi + +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +{ $as_echo "$as_me:$LINENO: result: $ac_cv_header_X11_xpm_h" >&5 +$as_echo "$ac_cv_header_X11_xpm_h" >&6; } +if test "x$ac_cv_header_X11_xpm_h" = x""yes; then + have_xpm=yes + cat >>confdefs.h <<\_ACEOF +#define HAVE_XPM 1 +_ACEOF + + XPM_LIBS="-lXpm $XPM_LIBS" +fi + + + CPPFLAGS="$ac_save_CPPFLAGS" +elif test "$with_xpm" != no; then + echo "error: must be yes or no: --with-xpm=$with_xpm" + exit 1 +fi + +# See comment near $motif_requires_xpm, above. +# Need to do this here, after both Motif and XPM have been checked for. +# +if test "$have_motif" = yes -a "$have_xpm" = yes ; then + if test "$motif_requires_xpm" = yes ; then + MOTIF_LIBS="$MOTIF_LIBS $XPM_LIBS" + fi +fi + +if test "$XPM_LIBS" = "" ; then + XPM_LIBS=$(MINIXPM) +fi + + +############################################################################### +# +# Check for -ljpeg +# +############################################################################### + +have_jpeg=no +with_jpeg_req=unspecified +jpeg_halfassed=no + +# Check whether --with-jpeg was given. +if test "${with_jpeg+set}" = set; then + withval=$with_jpeg; with_jpeg="$withval"; with_jpeg_req="$withval" +else + with_jpeg=yes +fi + + + + case "$with_jpeg" in + yes) ;; + no) ;; + + /*) + { $as_echo "$as_me:$LINENO: checking for JPEG headers" >&5 +$as_echo_n "checking for JPEG headers... " >&6; } + d=$with_jpeg/include + if test -d $d; then + X_CFLAGS="-I$d $X_CFLAGS" + { $as_echo "$as_me:$LINENO: result: $d" >&5 +$as_echo "$d" >&6; } + else + { $as_echo "$as_me:$LINENO: result: not found ($d: no such directory)" >&5 +$as_echo "not found ($d: no such directory)" >&6; } + fi + + { $as_echo "$as_me:$LINENO: checking for JPEG libs" >&5 +$as_echo_n "checking for JPEG libs... " >&6; } + d=$with_jpeg/lib + if test -d $d; then + X_LIBS="-L$d $X_LIBS" + { $as_echo "$as_me:$LINENO: result: $d" >&5 +$as_echo "$d" >&6; } + else + { $as_echo "$as_me:$LINENO: result: not found ($d: no such directory)" >&5 +$as_echo "not found ($d: no such directory)" >&6; } + fi + + # replace the directory string with "yes". + with_jpeg_req="yes" + with_jpeg=$with_jpeg_req + ;; + + *) + echo "" + echo "error: argument to --with-jpeg must be \"yes\", \"no\", or a directory." + echo " If it is a directory, then \`DIR/include' will be added to" + echo " the -I list, and \`DIR/lib' will be added to the -L list." + exit 1 + ;; + esac + + +if test "$with_jpeg" != yes -a "$with_jpeg" != no ; then + echo "error: must be yes or no: --with-jpeg=$with_jpeg" + exit 1 +fi + +if test "$with_jpeg" = yes; then + + have_jpeg=no + + ac_save_CPPFLAGS="$CPPFLAGS" + if test \! -z "$includedir" ; then + CPPFLAGS="$CPPFLAGS -I$includedir" + fi + CPPFLAGS="$CPPFLAGS $X_CFLAGS" + CPPFLAGS=`eval eval eval eval eval eval eval eval eval echo $CPPFLAGS` + if test "${ac_cv_header_jpeglib_h+set}" = set; then + { $as_echo "$as_me:$LINENO: checking for jpeglib.h" >&5 +$as_echo_n "checking for jpeglib.h... " >&6; } +if test "${ac_cv_header_jpeglib_h+set}" = set; then + $as_echo_n "(cached) " >&6 +fi +{ $as_echo "$as_me:$LINENO: result: $ac_cv_header_jpeglib_h" >&5 +$as_echo "$ac_cv_header_jpeglib_h" >&6; } +else + # Is the header compilable? +{ $as_echo "$as_me:$LINENO: checking jpeglib.h usability" >&5 +$as_echo_n "checking jpeglib.h usability... " >&6; } +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +$ac_includes_default +#include +_ACEOF +rm -rf conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\"" +$as_echo "$ac_try_echo") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -rf conftest.er1 + cat conftest.err >&5 + $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest.$ac_objext; then + ac_header_compiler=yes +else + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_header_compiler=no +fi + +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +{ $as_echo "$as_me:$LINENO: result: $ac_header_compiler" >&5 +$as_echo "$ac_header_compiler" >&6; } + +# Is the header present? +{ $as_echo "$as_me:$LINENO: checking jpeglib.h presence" >&5 +$as_echo_n "checking jpeglib.h presence... " >&6; } +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include +_ACEOF +if { (ac_try="$ac_cpp conftest.$ac_ext" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\"" +$as_echo "$ac_try_echo") >&5 + (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -rf conftest.er1 + cat conftest.err >&5 + $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } >/dev/null && { + test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" || + test ! -s conftest.err + }; then + ac_header_preproc=yes +else + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_header_preproc=no +fi + +rm -rf conftest.err conftest.$ac_ext +{ $as_echo "$as_me:$LINENO: result: $ac_header_preproc" >&5 +$as_echo "$ac_header_preproc" >&6; } + +# So? What about this header? +case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in + yes:no: ) + { $as_echo "$as_me:$LINENO: WARNING: jpeglib.h: accepted by the compiler, rejected by the preprocessor!" >&5 +$as_echo "$as_me: WARNING: jpeglib.h: accepted by the compiler, rejected by the preprocessor!" >&2;} + { $as_echo "$as_me:$LINENO: WARNING: jpeglib.h: proceeding with the compiler's result" >&5 +$as_echo "$as_me: WARNING: jpeglib.h: proceeding with the compiler's result" >&2;} + ac_header_preproc=yes + ;; + no:yes:* ) + { $as_echo "$as_me:$LINENO: WARNING: jpeglib.h: present but cannot be compiled" >&5 +$as_echo "$as_me: WARNING: jpeglib.h: present but cannot be compiled" >&2;} + { $as_echo "$as_me:$LINENO: WARNING: jpeglib.h: check for missing prerequisite headers?" >&5 +$as_echo "$as_me: WARNING: jpeglib.h: check for missing prerequisite headers?" >&2;} + { $as_echo "$as_me:$LINENO: WARNING: jpeglib.h: see the Autoconf documentation" >&5 +$as_echo "$as_me: WARNING: jpeglib.h: see the Autoconf documentation" >&2;} + { $as_echo "$as_me:$LINENO: WARNING: jpeglib.h: section \"Present But Cannot Be Compiled\"" >&5 +$as_echo "$as_me: WARNING: jpeglib.h: section \"Present But Cannot Be Compiled\"" >&2;} + { $as_echo "$as_me:$LINENO: WARNING: jpeglib.h: proceeding with the preprocessor's result" >&5 +$as_echo "$as_me: WARNING: jpeglib.h: proceeding with the preprocessor's result" >&2;} + { $as_echo "$as_me:$LINENO: WARNING: jpeglib.h: in the future, the compiler will take precedence" >&5 +$as_echo "$as_me: WARNING: jpeglib.h: in the future, the compiler will take precedence" >&2;} + + ;; +esac +{ $as_echo "$as_me:$LINENO: checking for jpeglib.h" >&5 +$as_echo_n "checking for jpeglib.h... " >&6; } +if test "${ac_cv_header_jpeglib_h+set}" = set; then + $as_echo_n "(cached) " >&6 +else + ac_cv_header_jpeglib_h=$ac_header_preproc +fi +{ $as_echo "$as_me:$LINENO: result: $ac_cv_header_jpeglib_h" >&5 +$as_echo "$ac_cv_header_jpeglib_h" >&6; } + +fi +if test "x$ac_cv_header_jpeglib_h" = x""yes; then + have_jpeg=yes +fi + + + CPPFLAGS="$ac_save_CPPFLAGS" + + if test "$have_jpeg" = yes; then + # we have the header, now check for the library + have_jpeg=no + jpeg_halfassed=yes + + ac_save_CPPFLAGS="$CPPFLAGS" + ac_save_LDFLAGS="$LDFLAGS" +# ac_save_LIBS="$LIBS" + + if test \! -z "$includedir" ; then + CPPFLAGS="$CPPFLAGS -I$includedir" + fi + # note: $X_CFLAGS includes $x_includes + CPPFLAGS="$CPPFLAGS $X_CFLAGS" + + if test \! -z "$libdir" ; then + LDFLAGS="$LDFLAGS -L$libdir" + fi + # note: $X_LIBS includes $x_libraries + LDFLAGS="$LDFLAGS $X_LIBS $X_EXTRA_LIBS" + + CPPFLAGS=`eval eval eval eval eval eval eval eval eval echo $CPPFLAGS` + LDFLAGS=`eval eval eval eval eval eval eval eval eval echo $LDFLAGS` + { $as_echo "$as_me:$LINENO: checking for jpeg_start_compress in -ljpeg" >&5 +$as_echo_n "checking for jpeg_start_compress in -ljpeg... " >&6; } +if test "${ac_cv_lib_jpeg_jpeg_start_compress+set}" = set; then + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-ljpeg $LIBS" +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char jpeg_start_compress (); +int +main () +{ +return jpeg_start_compress (); + ; + return 0; +} +_ACEOF +rm -rf conftest.$ac_objext conftest$ac_exeext +if { (ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\"" +$as_echo "$ac_try_echo") >&5 + (eval "$ac_link") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -rf conftest.er1 + cat conftest.err >&5 + $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest$ac_exeext && { + test "$cross_compiling" = yes || + $as_test_x conftest$ac_exeext + }; then + ac_cv_lib_jpeg_jpeg_start_compress=yes +else + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_cv_lib_jpeg_jpeg_start_compress=no +fi + +rm -rf conftest.dSYM +rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:$LINENO: result: $ac_cv_lib_jpeg_jpeg_start_compress" >&5 +$as_echo "$ac_cv_lib_jpeg_jpeg_start_compress" >&6; } +if test "x$ac_cv_lib_jpeg_jpeg_start_compress" = x""yes; then + have_jpeg=yes + jpeg_halfassed=no + JPEG_LIBS="-ljpeg" + cat >>confdefs.h <<\_ACEOF +#define HAVE_JPEGLIB 1 +_ACEOF + +fi + + CPPFLAGS="$ac_save_CPPFLAGS" + LDFLAGS="$ac_save_LDFLAGS" +# LIBS="$ac_save_LIBS" + + fi +fi + + +############################################################################### +# +# Check for pty support: this allows 'phosphor' and 'apple2' +# to run curses-based programs, or be used as terminal windows. +# +############################################################################### + +PTY_LIBS= + + +for ac_header in pty.h util.h +do +as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh` +if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then + { $as_echo "$as_me:$LINENO: checking for $ac_header" >&5 +$as_echo_n "checking for $ac_header... " >&6; } +if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then + $as_echo_n "(cached) " >&6 +fi +ac_res=`eval 'as_val=${'$as_ac_Header'} + $as_echo "$as_val"'` + { $as_echo "$as_me:$LINENO: result: $ac_res" >&5 +$as_echo "$ac_res" >&6; } +else + # Is the header compilable? +{ $as_echo "$as_me:$LINENO: checking $ac_header usability" >&5 +$as_echo_n "checking $ac_header usability... " >&6; } +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +$ac_includes_default +#include <$ac_header> +_ACEOF +rm -rf conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\"" +$as_echo "$ac_try_echo") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -rf conftest.er1 + cat conftest.err >&5 + $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest.$ac_objext; then + ac_header_compiler=yes +else + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_header_compiler=no +fi + +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +{ $as_echo "$as_me:$LINENO: result: $ac_header_compiler" >&5 +$as_echo "$ac_header_compiler" >&6; } + +# Is the header present? +{ $as_echo "$as_me:$LINENO: checking $ac_header presence" >&5 +$as_echo_n "checking $ac_header presence... " >&6; } +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include <$ac_header> +_ACEOF +if { (ac_try="$ac_cpp conftest.$ac_ext" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\"" +$as_echo "$ac_try_echo") >&5 + (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -rf conftest.er1 + cat conftest.err >&5 + $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } >/dev/null && { + test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" || + test ! -s conftest.err + }; then + ac_header_preproc=yes +else + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_header_preproc=no +fi + +rm -rf conftest.err conftest.$ac_ext +{ $as_echo "$as_me:$LINENO: result: $ac_header_preproc" >&5 +$as_echo "$ac_header_preproc" >&6; } + +# So? What about this header? +case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in + yes:no: ) + { $as_echo "$as_me:$LINENO: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&5 +$as_echo "$as_me: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&2;} + { $as_echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the compiler's result" >&5 +$as_echo "$as_me: WARNING: $ac_header: proceeding with the compiler's result" >&2;} + ac_header_preproc=yes + ;; + no:yes:* ) + { $as_echo "$as_me:$LINENO: WARNING: $ac_header: present but cannot be compiled" >&5 +$as_echo "$as_me: WARNING: $ac_header: present but cannot be compiled" >&2;} + { $as_echo "$as_me:$LINENO: WARNING: $ac_header: check for missing prerequisite headers?" >&5 +$as_echo "$as_me: WARNING: $ac_header: check for missing prerequisite headers?" >&2;} + { $as_echo "$as_me:$LINENO: WARNING: $ac_header: see the Autoconf documentation" >&5 +$as_echo "$as_me: WARNING: $ac_header: see the Autoconf documentation" >&2;} + { $as_echo "$as_me:$LINENO: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&5 +$as_echo "$as_me: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&2;} + { $as_echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the preprocessor's result" >&5 +$as_echo "$as_me: WARNING: $ac_header: proceeding with the preprocessor's result" >&2;} + { $as_echo "$as_me:$LINENO: WARNING: $ac_header: in the future, the compiler will take precedence" >&5 +$as_echo "$as_me: WARNING: $ac_header: in the future, the compiler will take precedence" >&2;} + + ;; +esac +{ $as_echo "$as_me:$LINENO: checking for $ac_header" >&5 +$as_echo_n "checking for $ac_header... " >&6; } +if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then + $as_echo_n "(cached) " >&6 +else + eval "$as_ac_Header=\$ac_header_preproc" +fi +ac_res=`eval 'as_val=${'$as_ac_Header'} + $as_echo "$as_val"'` + { $as_echo "$as_me:$LINENO: result: $ac_res" >&5 +$as_echo "$ac_res" >&6; } + +fi +as_val=`eval 'as_val=${'$as_ac_Header'} + $as_echo "$as_val"'` + if test "x$as_val" = x""yes; then + cat >>confdefs.h <<_ACEOF +#define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1 +_ACEOF + +fi + +done + + + ac_save_CPPFLAGS="$CPPFLAGS" + ac_save_LDFLAGS="$LDFLAGS" +# ac_save_LIBS="$LIBS" + + if test \! -z "$includedir" ; then + CPPFLAGS="$CPPFLAGS -I$includedir" + fi + # note: $X_CFLAGS includes $x_includes + CPPFLAGS="$CPPFLAGS $X_CFLAGS" + + if test \! -z "$libdir" ; then + LDFLAGS="$LDFLAGS -L$libdir" + fi + # note: $X_LIBS includes $x_libraries + LDFLAGS="$LDFLAGS $X_LIBS $X_EXTRA_LIBS" + + CPPFLAGS=`eval eval eval eval eval eval eval eval eval echo $CPPFLAGS` + LDFLAGS=`eval eval eval eval eval eval eval eval eval echo $LDFLAGS` + { $as_echo "$as_me:$LINENO: checking for forkpty in -lutil" >&5 +$as_echo_n "checking for forkpty in -lutil... " >&6; } +if test "${ac_cv_lib_util_forkpty+set}" = set; then + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lutil $LIBS" +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char forkpty (); +int +main () +{ +return forkpty (); + ; + return 0; +} +_ACEOF +rm -rf conftest.$ac_objext conftest$ac_exeext +if { (ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\"" +$as_echo "$ac_try_echo") >&5 + (eval "$ac_link") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -rf conftest.er1 + cat conftest.err >&5 + $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest$ac_exeext && { + test "$cross_compiling" = yes || + $as_test_x conftest$ac_exeext + }; then + ac_cv_lib_util_forkpty=yes +else + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_cv_lib_util_forkpty=no +fi + +rm -rf conftest.dSYM +rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:$LINENO: result: $ac_cv_lib_util_forkpty" >&5 +$as_echo "$ac_cv_lib_util_forkpty" >&6; } +if test "x$ac_cv_lib_util_forkpty" = x""yes; then + PTY_LIBS="-lutil" + ac_have_forkpty=yes + cat >>confdefs.h <<\_ACEOF +#define HAVE_FORKPTY 1 +_ACEOF + +fi + + CPPFLAGS="$ac_save_CPPFLAGS" + LDFLAGS="$ac_save_LDFLAGS" +# LIBS="$ac_save_LIBS" + + +if test "$ac_have_forkpty" != yes ; then + # we don't need (or have) -lutil on MacOS 10.4.2... + + ac_save_CPPFLAGS="$CPPFLAGS" + ac_save_LDFLAGS="$LDFLAGS" +# ac_save_LIBS="$LIBS" + + if test \! -z "$includedir" ; then + CPPFLAGS="$CPPFLAGS -I$includedir" + fi + # note: $X_CFLAGS includes $x_includes + CPPFLAGS="$CPPFLAGS $X_CFLAGS" + + if test \! -z "$libdir" ; then + LDFLAGS="$LDFLAGS -L$libdir" + fi + # note: $X_LIBS includes $x_libraries + LDFLAGS="$LDFLAGS $X_LIBS $X_EXTRA_LIBS" + + CPPFLAGS=`eval eval eval eval eval eval eval eval eval echo $CPPFLAGS` + LDFLAGS=`eval eval eval eval eval eval eval eval eval echo $LDFLAGS` + { $as_echo "$as_me:$LINENO: checking for forkpty in -lc" >&5 +$as_echo_n "checking for forkpty in -lc... " >&6; } +if test "${ac_cv_lib_c_forkpty+set}" = set; then + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lc $LIBS" +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char forkpty (); +int +main () +{ +return forkpty (); + ; + return 0; +} +_ACEOF +rm -rf conftest.$ac_objext conftest$ac_exeext +if { (ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\"" +$as_echo "$ac_try_echo") >&5 + (eval "$ac_link") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -rf conftest.er1 + cat conftest.err >&5 + $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest$ac_exeext && { + test "$cross_compiling" = yes || + $as_test_x conftest$ac_exeext + }; then + ac_cv_lib_c_forkpty=yes +else + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_cv_lib_c_forkpty=no +fi + +rm -rf conftest.dSYM +rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:$LINENO: result: $ac_cv_lib_c_forkpty" >&5 +$as_echo "$ac_cv_lib_c_forkpty" >&6; } +if test "x$ac_cv_lib_c_forkpty" = x""yes; then + PTY_LIBS="" + cat >>confdefs.h <<\_ACEOF +#define HAVE_FORKPTY 1 +_ACEOF + +fi + + CPPFLAGS="$ac_save_CPPFLAGS" + LDFLAGS="$ac_save_LDFLAGS" +# LIBS="$ac_save_LIBS" + +fi + +############################################################################### +# +# Check for the XSHM server extension. +# +############################################################################### + +have_xshm=no +with_xshm_req=unspecified + +# Check whether --with-xshm-ext was given. +if test "${with_xshm_ext+set}" = set; then + withval=$with_xshm_ext; with_xshm="$withval"; with_xshm_req="$withval" +else + with_xshm=yes +fi + + + + case "$with_xshm" in + yes) ;; + no) ;; + + /*) + { $as_echo "$as_me:$LINENO: checking for XSHM headers" >&5 +$as_echo_n "checking for XSHM headers... " >&6; } + d=$with_xshm/include + if test -d $d; then + X_CFLAGS="-I$d $X_CFLAGS" + { $as_echo "$as_me:$LINENO: result: $d" >&5 +$as_echo "$d" >&6; } + else + { $as_echo "$as_me:$LINENO: result: not found ($d: no such directory)" >&5 +$as_echo "not found ($d: no such directory)" >&6; } + fi + + { $as_echo "$as_me:$LINENO: checking for XSHM libs" >&5 +$as_echo_n "checking for XSHM libs... " >&6; } + d=$with_xshm/lib + if test -d $d; then + X_LIBS="-L$d $X_LIBS" + { $as_echo "$as_me:$LINENO: result: $d" >&5 +$as_echo "$d" >&6; } + else + { $as_echo "$as_me:$LINENO: result: not found ($d: no such directory)" >&5 +$as_echo "not found ($d: no such directory)" >&6; } + fi + + # replace the directory string with "yes". + with_xshm_req="yes" + with_xshm=$with_xshm_req + ;; + + *) + echo "" + echo "error: argument to --with-xshm-ext must be \"yes\", \"no\", or a directory." + echo " If it is a directory, then \`DIR/include' will be added to" + echo " the -I list, and \`DIR/lib' will be added to the -L list." + exit 1 + ;; + esac + + +if test "$with_xshm" = yes; then + + # first check for Xshm.h. + + ac_save_CPPFLAGS="$CPPFLAGS" + if test \! -z "$includedir" ; then + CPPFLAGS="$CPPFLAGS -I$includedir" + fi + CPPFLAGS="$CPPFLAGS $X_CFLAGS" + CPPFLAGS=`eval eval eval eval eval eval eval eval eval echo $CPPFLAGS` + { $as_echo "$as_me:$LINENO: checking for X11/extensions/XShm.h" >&5 +$as_echo_n "checking for X11/extensions/XShm.h... " >&6; } +if test "${ac_cv_header_X11_extensions_XShm_h+set}" = set; then + $as_echo_n "(cached) " >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include + +#include +_ACEOF +rm -rf conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\"" +$as_echo "$ac_try_echo") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -rf conftest.er1 + cat conftest.err >&5 + $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest.$ac_objext; then + ac_cv_header_X11_extensions_XShm_h=yes +else + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_cv_header_X11_extensions_XShm_h=no +fi + +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +{ $as_echo "$as_me:$LINENO: result: $ac_cv_header_X11_extensions_XShm_h" >&5 +$as_echo "$ac_cv_header_X11_extensions_XShm_h" >&6; } +if test "x$ac_cv_header_X11_extensions_XShm_h" = x""yes; then + have_xshm=yes +fi + + + CPPFLAGS="$ac_save_CPPFLAGS" + + # if that succeeded, then check for sys/ipc.h. + if test "$have_xshm" = yes; then + have_xshm=no + + ac_save_CPPFLAGS="$CPPFLAGS" + if test \! -z "$includedir" ; then + CPPFLAGS="$CPPFLAGS -I$includedir" + fi + CPPFLAGS="$CPPFLAGS $X_CFLAGS" + CPPFLAGS=`eval eval eval eval eval eval eval eval eval echo $CPPFLAGS` + if test "${ac_cv_header_sys_ipc_h+set}" = set; then + { $as_echo "$as_me:$LINENO: checking for sys/ipc.h" >&5 +$as_echo_n "checking for sys/ipc.h... " >&6; } +if test "${ac_cv_header_sys_ipc_h+set}" = set; then + $as_echo_n "(cached) " >&6 +fi +{ $as_echo "$as_me:$LINENO: result: $ac_cv_header_sys_ipc_h" >&5 +$as_echo "$ac_cv_header_sys_ipc_h" >&6; } +else + # Is the header compilable? +{ $as_echo "$as_me:$LINENO: checking sys/ipc.h usability" >&5 +$as_echo_n "checking sys/ipc.h usability... " >&6; } +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +$ac_includes_default +#include +_ACEOF +rm -rf conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\"" +$as_echo "$ac_try_echo") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -rf conftest.er1 + cat conftest.err >&5 + $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest.$ac_objext; then + ac_header_compiler=yes +else + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_header_compiler=no +fi + +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +{ $as_echo "$as_me:$LINENO: result: $ac_header_compiler" >&5 +$as_echo "$ac_header_compiler" >&6; } + +# Is the header present? +{ $as_echo "$as_me:$LINENO: checking sys/ipc.h presence" >&5 +$as_echo_n "checking sys/ipc.h presence... " >&6; } +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include +_ACEOF +if { (ac_try="$ac_cpp conftest.$ac_ext" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\"" +$as_echo "$ac_try_echo") >&5 + (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -rf conftest.er1 + cat conftest.err >&5 + $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } >/dev/null && { + test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" || + test ! -s conftest.err + }; then + ac_header_preproc=yes +else + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_header_preproc=no +fi + +rm -rf conftest.err conftest.$ac_ext +{ $as_echo "$as_me:$LINENO: result: $ac_header_preproc" >&5 +$as_echo "$ac_header_preproc" >&6; } + +# So? What about this header? +case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in + yes:no: ) + { $as_echo "$as_me:$LINENO: WARNING: sys/ipc.h: accepted by the compiler, rejected by the preprocessor!" >&5 +$as_echo "$as_me: WARNING: sys/ipc.h: accepted by the compiler, rejected by the preprocessor!" >&2;} + { $as_echo "$as_me:$LINENO: WARNING: sys/ipc.h: proceeding with the compiler's result" >&5 +$as_echo "$as_me: WARNING: sys/ipc.h: proceeding with the compiler's result" >&2;} + ac_header_preproc=yes + ;; + no:yes:* ) + { $as_echo "$as_me:$LINENO: WARNING: sys/ipc.h: present but cannot be compiled" >&5 +$as_echo "$as_me: WARNING: sys/ipc.h: present but cannot be compiled" >&2;} + { $as_echo "$as_me:$LINENO: WARNING: sys/ipc.h: check for missing prerequisite headers?" >&5 +$as_echo "$as_me: WARNING: sys/ipc.h: check for missing prerequisite headers?" >&2;} + { $as_echo "$as_me:$LINENO: WARNING: sys/ipc.h: see the Autoconf documentation" >&5 +$as_echo "$as_me: WARNING: sys/ipc.h: see the Autoconf documentation" >&2;} + { $as_echo "$as_me:$LINENO: WARNING: sys/ipc.h: section \"Present But Cannot Be Compiled\"" >&5 +$as_echo "$as_me: WARNING: sys/ipc.h: section \"Present But Cannot Be Compiled\"" >&2;} + { $as_echo "$as_me:$LINENO: WARNING: sys/ipc.h: proceeding with the preprocessor's result" >&5 +$as_echo "$as_me: WARNING: sys/ipc.h: proceeding with the preprocessor's result" >&2;} + { $as_echo "$as_me:$LINENO: WARNING: sys/ipc.h: in the future, the compiler will take precedence" >&5 +$as_echo "$as_me: WARNING: sys/ipc.h: in the future, the compiler will take precedence" >&2;} + + ;; +esac +{ $as_echo "$as_me:$LINENO: checking for sys/ipc.h" >&5 +$as_echo_n "checking for sys/ipc.h... " >&6; } +if test "${ac_cv_header_sys_ipc_h+set}" = set; then + $as_echo_n "(cached) " >&6 +else + ac_cv_header_sys_ipc_h=$ac_header_preproc +fi +{ $as_echo "$as_me:$LINENO: result: $ac_cv_header_sys_ipc_h" >&5 +$as_echo "$ac_cv_header_sys_ipc_h" >&6; } + +fi +if test "x$ac_cv_header_sys_ipc_h" = x""yes; then + have_xshm=yes +fi + + + CPPFLAGS="$ac_save_CPPFLAGS" + fi + + # if that succeeded, then check for sys/shm.h. + if test "$have_xshm" = yes; then + have_xshm=no + + ac_save_CPPFLAGS="$CPPFLAGS" + if test \! -z "$includedir" ; then + CPPFLAGS="$CPPFLAGS -I$includedir" + fi + CPPFLAGS="$CPPFLAGS $X_CFLAGS" + CPPFLAGS=`eval eval eval eval eval eval eval eval eval echo $CPPFLAGS` + if test "${ac_cv_header_sys_shm_h+set}" = set; then + { $as_echo "$as_me:$LINENO: checking for sys/shm.h" >&5 +$as_echo_n "checking for sys/shm.h... " >&6; } +if test "${ac_cv_header_sys_shm_h+set}" = set; then + $as_echo_n "(cached) " >&6 +fi +{ $as_echo "$as_me:$LINENO: result: $ac_cv_header_sys_shm_h" >&5 +$as_echo "$ac_cv_header_sys_shm_h" >&6; } +else + # Is the header compilable? +{ $as_echo "$as_me:$LINENO: checking sys/shm.h usability" >&5 +$as_echo_n "checking sys/shm.h usability... " >&6; } +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +$ac_includes_default +#include +_ACEOF +rm -rf conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\"" +$as_echo "$ac_try_echo") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -rf conftest.er1 + cat conftest.err >&5 + $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest.$ac_objext; then + ac_header_compiler=yes +else + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_header_compiler=no +fi + +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +{ $as_echo "$as_me:$LINENO: result: $ac_header_compiler" >&5 +$as_echo "$ac_header_compiler" >&6; } + +# Is the header present? +{ $as_echo "$as_me:$LINENO: checking sys/shm.h presence" >&5 +$as_echo_n "checking sys/shm.h presence... " >&6; } +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include +_ACEOF +if { (ac_try="$ac_cpp conftest.$ac_ext" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\"" +$as_echo "$ac_try_echo") >&5 + (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -rf conftest.er1 + cat conftest.err >&5 + $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } >/dev/null && { + test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" || + test ! -s conftest.err + }; then + ac_header_preproc=yes +else + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_header_preproc=no +fi + +rm -rf conftest.err conftest.$ac_ext +{ $as_echo "$as_me:$LINENO: result: $ac_header_preproc" >&5 +$as_echo "$ac_header_preproc" >&6; } + +# So? What about this header? +case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in + yes:no: ) + { $as_echo "$as_me:$LINENO: WARNING: sys/shm.h: accepted by the compiler, rejected by the preprocessor!" >&5 +$as_echo "$as_me: WARNING: sys/shm.h: accepted by the compiler, rejected by the preprocessor!" >&2;} + { $as_echo "$as_me:$LINENO: WARNING: sys/shm.h: proceeding with the compiler's result" >&5 +$as_echo "$as_me: WARNING: sys/shm.h: proceeding with the compiler's result" >&2;} + ac_header_preproc=yes + ;; + no:yes:* ) + { $as_echo "$as_me:$LINENO: WARNING: sys/shm.h: present but cannot be compiled" >&5 +$as_echo "$as_me: WARNING: sys/shm.h: present but cannot be compiled" >&2;} + { $as_echo "$as_me:$LINENO: WARNING: sys/shm.h: check for missing prerequisite headers?" >&5 +$as_echo "$as_me: WARNING: sys/shm.h: check for missing prerequisite headers?" >&2;} + { $as_echo "$as_me:$LINENO: WARNING: sys/shm.h: see the Autoconf documentation" >&5 +$as_echo "$as_me: WARNING: sys/shm.h: see the Autoconf documentation" >&2;} + { $as_echo "$as_me:$LINENO: WARNING: sys/shm.h: section \"Present But Cannot Be Compiled\"" >&5 +$as_echo "$as_me: WARNING: sys/shm.h: section \"Present But Cannot Be Compiled\"" >&2;} + { $as_echo "$as_me:$LINENO: WARNING: sys/shm.h: proceeding with the preprocessor's result" >&5 +$as_echo "$as_me: WARNING: sys/shm.h: proceeding with the preprocessor's result" >&2;} + { $as_echo "$as_me:$LINENO: WARNING: sys/shm.h: in the future, the compiler will take precedence" >&5 +$as_echo "$as_me: WARNING: sys/shm.h: in the future, the compiler will take precedence" >&2;} + + ;; +esac +{ $as_echo "$as_me:$LINENO: checking for sys/shm.h" >&5 +$as_echo_n "checking for sys/shm.h... " >&6; } +if test "${ac_cv_header_sys_shm_h+set}" = set; then + $as_echo_n "(cached) " >&6 +else + ac_cv_header_sys_shm_h=$ac_header_preproc +fi +{ $as_echo "$as_me:$LINENO: result: $ac_cv_header_sys_shm_h" >&5 +$as_echo "$ac_cv_header_sys_shm_h" >&6; } + +fi +if test "x$ac_cv_header_sys_shm_h" = x""yes; then + have_xshm=yes +fi + + + CPPFLAGS="$ac_save_CPPFLAGS" + fi + + # AIX is pathological, as usual: apparently it's normal for the Xshm headers + # to exist, but the library code to not exist. And even better, the library + # code is in its own library: libXextSam.a. So, if we're on AIX, and that + # lib doesn't exist, give up. (This lib gets added to X_EXTRA_LIBS, and + # that's not quite right, but close enough.) + # + case "$host" in + *-aix*) + if `uname -v` -eq 3 ; then + have_xshm=no + + ac_save_CPPFLAGS="$CPPFLAGS" + ac_save_LDFLAGS="$LDFLAGS" +# ac_save_LIBS="$LIBS" + + if test \! -z "$includedir" ; then + CPPFLAGS="$CPPFLAGS -I$includedir" + fi + # note: $X_CFLAGS includes $x_includes + CPPFLAGS="$CPPFLAGS $X_CFLAGS" + + if test \! -z "$libdir" ; then + LDFLAGS="$LDFLAGS -L$libdir" + fi + # note: $X_LIBS includes $x_libraries + LDFLAGS="$LDFLAGS $X_LIBS $X_EXTRA_LIBS" + + CPPFLAGS=`eval eval eval eval eval eval eval eval eval echo $CPPFLAGS` + LDFLAGS=`eval eval eval eval eval eval eval eval eval echo $LDFLAGS` + { $as_echo "$as_me:$LINENO: checking for XShmQueryExtension in -lXextSam" >&5 +$as_echo_n "checking for XShmQueryExtension in -lXextSam... " >&6; } +if test "${ac_cv_lib_XextSam_XShmQueryExtension+set}" = set; then + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lXextSam -lX11 -lXext -lm $LIBS" +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char XShmQueryExtension (); +int +main () +{ +return XShmQueryExtension (); + ; + return 0; +} +_ACEOF +rm -rf conftest.$ac_objext conftest$ac_exeext +if { (ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\"" +$as_echo "$ac_try_echo") >&5 + (eval "$ac_link") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -rf conftest.er1 + cat conftest.err >&5 + $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest$ac_exeext && { + test "$cross_compiling" = yes || + $as_test_x conftest$ac_exeext + }; then + ac_cv_lib_XextSam_XShmQueryExtension=yes +else + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_cv_lib_XextSam_XShmQueryExtension=no +fi + +rm -rf conftest.dSYM +rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:$LINENO: result: $ac_cv_lib_XextSam_XShmQueryExtension" >&5 +$as_echo "$ac_cv_lib_XextSam_XShmQueryExtension" >&6; } +if test "x$ac_cv_lib_XextSam_XShmQueryExtension" = x""yes; then + have_xshm=yes; X_EXTRA_LIBS="$X_EXTRA_LIBS -lXextSam" +else + true +fi + + CPPFLAGS="$ac_save_CPPFLAGS" + LDFLAGS="$ac_save_LDFLAGS" +# LIBS="$ac_save_LIBS" + + fi + ;; + esac + + # if that succeeded, then we've really got it. + if test "$have_xshm" = yes; then + cat >>confdefs.h <<\_ACEOF +#define HAVE_XSHM_EXTENSION 1 +_ACEOF + + fi + +elif test "$with_xshm" != no; then + echo "error: must be yes or no: --with-xshm-ext=$with_xshm" + exit 1 +fi + + +############################################################################### +# +# Check for the DOUBLE-BUFFER server extension. +# +############################################################################### + +have_xdbe=no +with_xdbe_req=unspecified + +# Check whether --with-xdbe-ext was given. +if test "${with_xdbe_ext+set}" = set; then + withval=$with_xdbe_ext; with_xdbe="$withval"; with_xdbe_req="$withval" +else + with_xdbe=yes +fi + + + + case "$with_xdbe" in + yes) ;; + no) ;; + + /*) + { $as_echo "$as_me:$LINENO: checking for DOUBLE-BUFFER headers" >&5 +$as_echo_n "checking for DOUBLE-BUFFER headers... " >&6; } + d=$with_xdbe/include + if test -d $d; then + X_CFLAGS="-I$d $X_CFLAGS" + { $as_echo "$as_me:$LINENO: result: $d" >&5 +$as_echo "$d" >&6; } + else + { $as_echo "$as_me:$LINENO: result: not found ($d: no such directory)" >&5 +$as_echo "not found ($d: no such directory)" >&6; } + fi + + { $as_echo "$as_me:$LINENO: checking for DOUBLE-BUFFER libs" >&5 +$as_echo_n "checking for DOUBLE-BUFFER libs... " >&6; } + d=$with_xdbe/lib + if test -d $d; then + X_LIBS="-L$d $X_LIBS" + { $as_echo "$as_me:$LINENO: result: $d" >&5 +$as_echo "$d" >&6; } + else + { $as_echo "$as_me:$LINENO: result: not found ($d: no such directory)" >&5 +$as_echo "not found ($d: no such directory)" >&6; } + fi + + # replace the directory string with "yes". + with_xdbe_req="yes" + with_xdbe=$with_xdbe_req + ;; + + *) + echo "" + echo "error: argument to --with-xdbe-ext must be \"yes\", \"no\", or a directory." + echo " If it is a directory, then \`DIR/include' will be added to" + echo " the -I list, and \`DIR/lib' will be added to the -L list." + exit 1 + ;; + esac + + +if test "$with_xdbe" = yes; then + + + ac_save_CPPFLAGS="$CPPFLAGS" + if test \! -z "$includedir" ; then + CPPFLAGS="$CPPFLAGS -I$includedir" + fi + CPPFLAGS="$CPPFLAGS $X_CFLAGS" + CPPFLAGS=`eval eval eval eval eval eval eval eval eval echo $CPPFLAGS` + { $as_echo "$as_me:$LINENO: checking for X11/extensions/Xdbe.h" >&5 +$as_echo_n "checking for X11/extensions/Xdbe.h... " >&6; } +if test "${ac_cv_header_X11_extensions_Xdbe_h+set}" = set; then + $as_echo_n "(cached) " >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include + +#include +_ACEOF +rm -rf conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\"" +$as_echo "$ac_try_echo") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -rf conftest.er1 + cat conftest.err >&5 + $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest.$ac_objext; then + ac_cv_header_X11_extensions_Xdbe_h=yes +else + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_cv_header_X11_extensions_Xdbe_h=no +fi + +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +{ $as_echo "$as_me:$LINENO: result: $ac_cv_header_X11_extensions_Xdbe_h" >&5 +$as_echo "$ac_cv_header_X11_extensions_Xdbe_h" >&6; } +if test "x$ac_cv_header_X11_extensions_Xdbe_h" = x""yes; then + have_xdbe=yes +fi + + + CPPFLAGS="$ac_save_CPPFLAGS" + if test "$have_xdbe" = yes; then + cat >>confdefs.h <<\_ACEOF +#define HAVE_DOUBLE_BUFFER_EXTENSION 1 +_ACEOF + + fi + +elif test "$with_xdbe" != no; then + echo "error: must be yes or no: --with-xdbe-ext=$with_xshm" + exit 1 +fi + + +############################################################################### +# +# Check for the SGI XReadDisplay server extension. +# +# Note: this has to be down here, rather than up with the other server +# extension tests, so that the output of `configure --help' is in the +# right order. Arrgh! +# +############################################################################### + +have_readdisplay=no +with_readdisplay_req=unspecified + +# Check whether --with-readdisplay was given. +if test "${with_readdisplay+set}" = set; then + withval=$with_readdisplay; with_readdisplay="$withval"; with_readdisplay_req="$withval" +else + with_readdisplay=yes +fi + + + + case "$with_readdisplay" in + yes) ;; + no) ;; + + /*) + { $as_echo "$as_me:$LINENO: checking for XReadDisplay headers" >&5 +$as_echo_n "checking for XReadDisplay headers... " >&6; } + d=$with_readdisplay/include + if test -d $d; then + X_CFLAGS="-I$d $X_CFLAGS" + { $as_echo "$as_me:$LINENO: result: $d" >&5 +$as_echo "$d" >&6; } + else + { $as_echo "$as_me:$LINENO: result: not found ($d: no such directory)" >&5 +$as_echo "not found ($d: no such directory)" >&6; } + fi + + { $as_echo "$as_me:$LINENO: checking for XReadDisplay libs" >&5 +$as_echo_n "checking for XReadDisplay libs... " >&6; } + d=$with_readdisplay/lib + if test -d $d; then + X_LIBS="-L$d $X_LIBS" + { $as_echo "$as_me:$LINENO: result: $d" >&5 +$as_echo "$d" >&6; } + else + { $as_echo "$as_me:$LINENO: result: not found ($d: no such directory)" >&5 +$as_echo "not found ($d: no such directory)" >&6; } + fi + + # replace the directory string with "yes". + with_readdisplay_req="yes" + with_readdisplay=$with_readdisplay_req + ;; + + *) + echo "" + echo "error: argument to --with-readdisplay must be \"yes\", \"no\", or a directory." + echo " If it is a directory, then \`DIR/include' will be added to" + echo " the -I list, and \`DIR/lib' will be added to the -L list." + exit 1 + ;; + esac + + +if test "$with_readdisplay" = yes; then + + ac_save_CPPFLAGS="$CPPFLAGS" + if test \! -z "$includedir" ; then + CPPFLAGS="$CPPFLAGS -I$includedir" + fi + CPPFLAGS="$CPPFLAGS $X_CFLAGS" + CPPFLAGS=`eval eval eval eval eval eval eval eval eval echo $CPPFLAGS` + { $as_echo "$as_me:$LINENO: checking for X11/extensions/readdisplay.h" >&5 +$as_echo_n "checking for X11/extensions/readdisplay.h... " >&6; } +if test "${ac_cv_header_X11_extensions_readdisplay_h+set}" = set; then + $as_echo_n "(cached) " >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include + +#include +_ACEOF +rm -rf conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\"" +$as_echo "$ac_try_echo") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -rf conftest.er1 + cat conftest.err >&5 + $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest.$ac_objext; then + ac_cv_header_X11_extensions_readdisplay_h=yes +else + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_cv_header_X11_extensions_readdisplay_h=no +fi + +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +{ $as_echo "$as_me:$LINENO: result: $ac_cv_header_X11_extensions_readdisplay_h" >&5 +$as_echo "$ac_cv_header_X11_extensions_readdisplay_h" >&6; } +if test "x$ac_cv_header_X11_extensions_readdisplay_h" = x""yes; then + cat >>confdefs.h <<\_ACEOF +#define HAVE_READ_DISPLAY_EXTENSION 1 +_ACEOF + +fi + + + CPPFLAGS="$ac_save_CPPFLAGS" +elif test "$with_readdisplay" != no; then + echo "error: must be yes or no: --with-readdisplay=$with_readdisplay" + exit 1 +fi + + +############################################################################### +# +# Check for a directory full of images to use as the default value +# of the "imageDirectory" preference. +# +############################################################################### + +have_imagedir=no +with_imagedir_req=unspecified + + +# Check whether --with-image-directory was given. +if test "${with_image_directory+set}" = set; then + withval=$with_image_directory; with_imagedir="$withval"; with_imagedir_req="$withval" +else + with_imagedir=yes +fi + +# no HANDLE_X_PATH_ARG for this one + +case "$with_imagedir" in + /*) + # absolute path + { $as_echo "$as_me:$LINENO: checking for image directory $with_imagedir" >&5 +$as_echo_n "checking for image directory $with_imagedir... " >&6; } + if test -d "$with_imagedir" ; then + { $as_echo "$as_me:$LINENO: result: yes" >&5 +$as_echo "yes" >&6; } + else + { $as_echo "$as_me:$LINENO: result: no" >&5 +$as_echo "no" >&6; } + with_imagedir="" + fi + ;; + yes) + with_imagedir="" + + #### Could use some more defaults here... + for dd in \ + "/usr/share/backgrounds/images/" \ + "/usr/share/wallpapers/" \ + "/Library/Desktop Pictures/" \ + ; do + if test -z "$with_imagedir"; then + { $as_echo "$as_me:$LINENO: checking for image directory $dd" >&5 +$as_echo_n "checking for image directory $dd... " >&6; } + if test -d "$dd" ; then + { $as_echo "$as_me:$LINENO: result: yes" >&5 +$as_echo "yes" >&6; } + with_imagedir="$dd" + else + { $as_echo "$as_me:$LINENO: result: no" >&5 +$as_echo "no" >&6; } + fi + fi + done + + ;; + no) + with_imagedir="" + ;; + + *) + echo "error: must be an absolute path: --with-image-directory=$with_imagedir_req" + exit 1 + ;; +esac +ac_cv_imagedir="$with_imagedir" + +DEFAULT_IMAGES_P='True' +DEFAULT_IMAGE_DIRECTORY="$ac_cv_imagedir" + +if test -z "$DEFAULT_IMAGE_DIRECTORY" ; then + DEFAULT_IMAGES_P='False' +fi + + +############################################################################### +# +# Pick a text file to use as the default of the "textFile" preference. +# Any old file will do, but preferably one that will make interesting +# shapes when displayed by "starwars" and "fontglide". +# +############################################################################### + +have_textfile=no +with_textfile_req=unspecified + + +# Check whether --with-text-file was given. +if test "${with_text_file+set}" = set; then + withval=$with_text_file; with_textfile="$withval"; with_textfile_req="$withval" +else + with_textfile=yes +fi + +# no HANDLE_X_PATH_ARG for this one + +case "$with_textfile" in + /*) + # absolute path + { $as_echo "$as_me:$LINENO: checking for text file $with_textfile" >&5 +$as_echo_n "checking for text file $with_textfile... " >&6; } + if test -f "$with_textfile" ; then + { $as_echo "$as_me:$LINENO: result: yes" >&5 +$as_echo "yes" >&6; } + else + { $as_echo "$as_me:$LINENO: result: no" >&5 +$as_echo "no" >&6; } + with_textfile="" + fi + ;; + yes) + with_textfile="" + + #### Could use some more defaults here... + for f in \ + "/usr/X11R6/lib/X11/doc/README" \ + "/usr/share/doc/xserver-common/copyright" \ + "/usr/share/doc/xserver-xorg-core/copyright" \ + "/usr/X11R6/README" \ + "/usr/share/doc/libX11*/COPYING" \ + "/usr/X11/share/X11/doc/README*" \ + "/usr/share/doc/debian/debian-manifesto" \ + ; do + if test -z "$with_textfile"; then + { $as_echo "$as_me:$LINENO: checking for text file $f" >&5 +$as_echo_n "checking for text file $f... " >&6; } + f=`/bin/ls $f 2>&- | head -1` + if test -f "$f" ; then + { $as_echo "$as_me:$LINENO: result: yes" >&5 +$as_echo "yes" >&6; } + with_textfile="$f" + else + { $as_echo "$as_me:$LINENO: result: no" >&5 +$as_echo "no" >&6; } + fi + fi + done + + ;; + no) + with_textfile="" + ;; + + *) + echo "error: must be an absolute path: --with-text-file=$with_textfile_req" + exit 1 + ;; +esac +ac_cv_textfile="$with_textfile" + +DEFAULT_TEXT_FILE="$ac_cv_textfile" + + +############################################################################### +# +# Check the browser to see help URL +# +############################################################################### + +have_browser=no +with_browser_req=unspecified + + +# Check whether --with-browser was given. +if test "${with_browser+set}" = set; then + withval=$with_browser; with_browser="$withval"; with_browser_req="$withval" +else + with_browser=no +fi + +# no HANDLE_X_PATH_ARG for this one + +case "$with_browser" in + no ) + ;; + * ) + WITH_BROWSER=$with_browser + gnome_open_program=$with_browser + { $as_echo "$as_me:$LINENO: checking for browser $with_browser" >&5 +$as_echo_n "checking for browser $with_browser... " >&6; } + with_browser_fullpath=`which $with_browser 2>/dev/null` + case $with_browser_fullpath in + /* ) + { $as_echo "$as_me:$LINENO: result: yes" >&5 +$as_echo "yes" >&6; } + have_browser=yes + ;; + * ) + { $as_echo "$as_me:$LINENO: result: no" >&5 +$as_echo "no" >&6; } +# Only warning: we don't want to install all packages for the +# dependency of the browser in building stage... + echo "WARNING: browser not found: --with-browser=$with_browser" + ;; + esac + ;; +esac +ac_cv_browser="$with_browser" + +############################################################################### +# +# Check whether it's ok to install some hacks as setuid (e.g., "sonar") +# This should be safe, but let's give people the option. +# +############################################################################### + +setuid_hacks_default=no +setuid_hacks="$setuid_hacks_default" + +# Check whether --with-setuid-hacks was given. +if test "${with_setuid_hacks+set}" = set; then + withval=$with_setuid_hacks; setuid_hacks="$withval" +else + setuid_hacks="$setuid_hacks_default" +fi + + + + case "$setuid_hacks" in + yes) ;; + no) ;; + + /*) + { $as_echo "$as_me:$LINENO: checking for setuid hacks headers" >&5 +$as_echo_n "checking for setuid hacks headers... " >&6; } + d=$setuid_hacks/include + if test -d $d; then + X_CFLAGS="-I$d $X_CFLAGS" + { $as_echo "$as_me:$LINENO: result: $d" >&5 +$as_echo "$d" >&6; } + else + { $as_echo "$as_me:$LINENO: result: not found ($d: no such directory)" >&5 +$as_echo "not found ($d: no such directory)" >&6; } + fi + + { $as_echo "$as_me:$LINENO: checking for setuid hacks libs" >&5 +$as_echo_n "checking for setuid hacks libs... " >&6; } + d=$setuid_hacks/lib + if test -d $d; then + X_LIBS="-L$d $X_LIBS" + { $as_echo "$as_me:$LINENO: result: $d" >&5 +$as_echo "$d" >&6; } + else + { $as_echo "$as_me:$LINENO: result: not found ($d: no such directory)" >&5 +$as_echo "not found ($d: no such directory)" >&6; } + fi + + # replace the directory string with "yes". + setuid_hacks_req="yes" + setuid_hacks=$setuid_hacks_req + ;; + + *) + echo "" + echo "error: argument to --with-setuid-hacks must be \"yes\", \"no\", or a directory." + echo " If it is a directory, then \`DIR/include' will be added to" + echo " the -I list, and \`DIR/lib' will be added to the -L list." + exit 1 + ;; + esac + + +if test "$setuid_hacks" = yes; then + true +elif test "$setuid_hacks" != no; then + echo "error: must be yes or no: --with-setuid-hacks=$setuid_hacks" + exit 1 +fi + + +############################################################################### +# +# Done testing. Now, set up the various -I and -L variables, +# and decide which GUI program to build by default. +# +############################################################################### + +DEPEND=makedepend +DEPEND_FLAGS= +DEPEND_DEFINES= + + +if test \! -z "$includedir" ; then + INCLUDES="$INCLUDES -I$includedir" +fi + +if test \! -z "$libdir" ; then + LDFLAGS="$LDFLAGS -L$libdir" +fi + + +PREFERRED_DEMO_PROGRAM='' +ALL_DEMO_PROGRAMS= +if test "$have_motif" = yes; then + PREFERRED_DEMO_PROGRAM=xscreensaver-demo-Xm + ALL_DEMO_PROGRAMS="$PREFERRED_DEMO_PROGRAM $ALL_DEMO_PROGRAMS" +fi +if test "$have_gtk" = yes; then + PREFERRED_DEMO_PROGRAM=xscreensaver-demo-Gtk + ALL_DEMO_PROGRAMS="$PREFERRED_DEMO_PROGRAM $ALL_DEMO_PROGRAMS" +fi + + +if test "$have_kerberos" = yes; then + PASSWD_SRCS="$PASSWD_SRCS \$(KERBEROS_SRCS)" + PASSWD_OBJS="$PASSWD_OBJS \$(KERBEROS_OBJS)" +fi +if test "$have_pam" = yes; then + PASSWD_SRCS="$PASSWD_SRCS \$(PAM_SRCS)" + PASSWD_OBJS="$PASSWD_OBJS \$(PAM_OBJS)" + INSTALL_PAM="install-pam" +fi +if test "$enable_pam_check_account_type" = yes; then + COMMENT_PAM_CHECK_ACCOUNT="" +else + COMMENT_PAM_CHECK_ACCOUNT="#" +fi +if test "$have_passwd_helper" = yes; then + PASSWD_SRCS="$PASSWD_SRCS \$(PWHELPER_SRCS)" + PASSWD_OBJS="$PASSWD_OBJS \$(PWHELPER_OBJS)" +fi + PASSWD_SRCS="$PASSWD_SRCS \$(PWENT_SRCS)" + PASSWD_OBJS="$PASSWD_OBJS \$(PWENT_OBJS)" + + +if test "$enable_locking" = yes; then + LOCK_SRCS='$(LOCK_SRCS_1) $(PASSWD_SRCS)' + LOCK_OBJS='$(LOCK_OBJS_1) $(PASSWD_OBJS)' +else + LOCK_SRCS='$(NOLOCK_SRCS_1)' + LOCK_OBJS='$(NOLOCK_OBJS_1)' +fi + +if test "$ac_macosx" = yes; then + EXES_OSX='$(EXES_OSX)' + SCRIPTS_OSX='$(SCRIPTS_OSX)' + MEN_OSX='$(MEN_OSX)' +else + EXES_OSX= + SCRIPTS_OSX= + MEN_OSX= +fi + + +INSTALL_SETUID='$(INSTALL_PROGRAM) $(SUID_FLAGS)' + +if test "$need_setuid" = yes; then + NEED_SETUID=yes +else + NEED_SETUID=no +fi + +if test "$setuid_hacks" = yes; then + SETUID_HACKS=yes +else + SETUID_HACKS=no +fi + +tab=' ' +if test "$have_gl" = yes; then + GL_EXES='$(GL_EXES)' + SUID_EXES='$(SUID_EXES)' + RETIRED_GL_EXES='$(RETIRED_GL_EXES)' + GL_UTIL_EXES='$(GL_UTIL_EXES)' + GL_MEN='$(GL_MEN)' + GL_KLUDGE=" " +else + GL_KLUDGE="-" +fi + +if test "$have_gle" = yes; then + GLE_EXES='$(GLE_EXES)' + GLE_KLUDGE=" " +else + GLE_KLUDGE="-" +fi + +if test "$have_jpeg" = yes -a "$have_gdk_pixbuf" = yes; then + JPEG_EXES='$(JPEG_EXES)' +fi + + +# Another substitution in the XScreenSaver.ad.in file: +# +if test "$gnome_open_program" != ''; then + GNOME24='' + GNOME22='! ' + NOGNOME='! ' +elif test "$gnome_url_show_program" != ''; then + GNOME24='! ' + GNOME22='' + NOGNOME='! ' +else + GNOME24='! ' + GNOME22='! ' + NOGNOME='' +fi + + +# Set PO_DATADIR to something sensible. +# +{ $as_echo "$as_me:$LINENO: checking for locale directory" >&5 +$as_echo_n "checking for locale directory... " >&6; } +if test -n "$GTK_DATADIR" ; then + PO_DATADIR="$GTK_DATADIR" +elif test "$have_gtk" = yes; then + PO_DATADIR=`$pkg_config --variable=prefix gtk+-2.0` + PO_DATADIR="$PO_DATADIR/share" +fi + +if test -z "$PO_DATADIR" ; then + # + # #### Total fucking kludge -- + # Map /build/prefix/usr/X11R6/share/ to /build/prefix/usr/share/ + # but of course we need to expand all the nested variables to do that... + # + dd=`eval eval eval eval eval eval eval eval eval eval eval echo $datadir` + PO_DATADIR=`echo $dd | sed 's@/X11R6/@/@'` +fi + +{ $as_echo "$as_me:$LINENO: result: $PO_DATADIR/locale" >&5 +$as_echo "$PO_DATADIR/locale" >&6; } + + +# canonicalize slashes. +HACK_CONF_DIR=`echo "${HACK_CONF_DIR}" | sed 's@/$@@;s@//*@/@g'` + +# gcc 3.0 likes to issue this warning for every file: +# +# cc1: warning: changing search order for system directory "/usr/local/include" +# cc1: warning: as it has already been specified as a non-system directory +# +# Yay. We can only avoid that by deleting "-I${prefix}/include" from the list. +# Which *should* be totally redundant, and thus an ok thing to delete? +# +INCLUDES=`echo "$INCLUDES" | sed 's@ -I${prefix}/include@@g;'` + + +############################################################################### +# +# Perform substitutions and write Makefiles. +# +############################################################################### + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +APPDEFAULTS=$ac_x_app_defaults + + + + + + + +ac_config_files="$ac_config_files Makefile utils/Makefile driver/Makefile driver/xscreensaver.pam hacks/Makefile hacks/glx/Makefile po/Makefile.in driver/XScreenSaver.ad" + +cat >confcache <<\_ACEOF +# This file is a shell script that caches the results of configure +# tests run on this system so they can be shared between configure +# scripts and configure runs, see configure's option --config-cache. +# It is not useful on other systems. If it contains results you don't +# want to keep, you may remove or edit it. +# +# config.status only pays attention to the cache file if you give it +# the --recheck option to rerun configure. +# +# `ac_cv_env_foo' variables (set or unset) will be overridden when +# loading this file, other *unset* `ac_cv_foo' will be assigned the +# following values. + +_ACEOF + +# The following way of writing the cache mishandles newlines in values, +# but we know of no workaround that is simple, portable, and efficient. +# So, we kill variables containing newlines. +# Ultrix sh set writes to stderr and can't be redirected directly, +# and sets the high bit in the cache file unless we assign to the vars. +( + for ac_var in `(set) 2>&1 | sed -n 's/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'`; do + eval ac_val=\$$ac_var + case $ac_val in #( + *${as_nl}*) + case $ac_var in #( + *_cv_*) { $as_echo "$as_me:$LINENO: WARNING: cache variable $ac_var contains a newline" >&5 +$as_echo "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;; + esac + case $ac_var in #( + _ | IFS | as_nl) ;; #( + BASH_ARGV | BASH_SOURCE) eval $ac_var= ;; #( + *) $as_unset $ac_var ;; + esac ;; + esac + done + + (set) 2>&1 | + case $as_nl`(ac_space=' '; set) 2>&1` in #( + *${as_nl}ac_space=\ *) + # `set' does not quote correctly, so add quotes (double-quote + # substitution turns \\\\ into \\, and sed turns \\ into \). + sed -n \ + "s/'/'\\\\''/g; + s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\\2'/p" + ;; #( + *) + # `set' quotes correctly as required by POSIX, so do not add quotes. + sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p" + ;; + esac | + sort +) | + sed ' + /^ac_cv_env_/b end + t clear + :clear + s/^\([^=]*\)=\(.*[{}].*\)$/test "${\1+set}" = set || &/ + t end + s/^\([^=]*\)=\(.*\)$/\1=${\1=\2}/ + :end' >>confcache +if diff "$cache_file" confcache >/dev/null 2>&1; then :; else + if test -w "$cache_file"; then + test "x$cache_file" != "x/dev/null" && + { $as_echo "$as_me:$LINENO: updating cache $cache_file" >&5 +$as_echo "$as_me: updating cache $cache_file" >&6;} + cat confcache >$cache_file + else + { $as_echo "$as_me:$LINENO: not updating unwritable cache $cache_file" >&5 +$as_echo "$as_me: not updating unwritable cache $cache_file" >&6;} + fi +fi +rm -f confcache + +test "x$prefix" = xNONE && prefix=$ac_default_prefix +# Let make expand exec_prefix. +test "x$exec_prefix" = xNONE && exec_prefix='${prefix}' + +DEFS=-DHAVE_CONFIG_H + +ac_libobjs= +ac_ltlibobjs= +for ac_i in : $LIBOBJS; do test "x$ac_i" = x: && continue + # 1. Remove the extension, and $U if already installed. + ac_script='s/\$U\././;s/\.o$//;s/\.obj$//' + ac_i=`$as_echo "$ac_i" | sed "$ac_script"` + # 2. Prepend LIBOBJDIR. When used with automake>=1.10 LIBOBJDIR + # will be set to the directory where LIBOBJS objects are built. + ac_libobjs="$ac_libobjs \${LIBOBJDIR}$ac_i\$U.$ac_objext" + ac_ltlibobjs="$ac_ltlibobjs \${LIBOBJDIR}$ac_i"'$U.lo' +done +LIBOBJS=$ac_libobjs + +LTLIBOBJS=$ac_ltlibobjs + + + + + mv -f po/POTFILES po/POTFILES.tmp + sed -e 's/\[.*\] *//' < po/POTFILES.tmp > po/POTFILES + rm -f po/POTFILES.tmp + + + +: ${CONFIG_STATUS=./config.status} +ac_write_fail=0 +ac_clean_files_save=$ac_clean_files +ac_clean_files="$ac_clean_files $CONFIG_STATUS" +{ $as_echo "$as_me:$LINENO: creating $CONFIG_STATUS" >&5 +$as_echo "$as_me: creating $CONFIG_STATUS" >&6;} +cat >$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 +#! $SHELL +# Generated by $as_me. +# Run this file to recreate the current configuration. +# Compiler output produced by configure, useful for debugging +# configure, is in config.log if it exists. + +debug=false +ac_cs_recheck=false +ac_cs_silent=false +SHELL=\${CONFIG_SHELL-$SHELL} +_ACEOF + +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 +## --------------------- ## +## M4sh Initialization. ## +## --------------------- ## + +# Be more Bourne compatible +DUALCASE=1; export DUALCASE # for MKS sh +if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then + emulate sh + NULLCMD=: + # Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which + # is contrary to our usage. Disable this feature. + alias -g '${1+"$@"}'='"$@"' + setopt NO_GLOB_SUBST +else + case `(set -o) 2>/dev/null` in + *posix*) set -o posix ;; +esac + +fi + + + + +# PATH needs CR +# Avoid depending upon Character Ranges. +as_cr_letters='abcdefghijklmnopqrstuvwxyz' +as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ' +as_cr_Letters=$as_cr_letters$as_cr_LETTERS +as_cr_digits='0123456789' +as_cr_alnum=$as_cr_Letters$as_cr_digits + +as_nl=' +' +export as_nl +# Printing a long string crashes Solaris 7 /usr/bin/printf. +as_echo='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\' +as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo +as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo$as_echo +if (test "X`printf %s $as_echo`" = "X$as_echo") 2>/dev/null; then + as_echo='printf %s\n' + as_echo_n='printf %s' +else + if test "X`(/usr/ucb/echo -n -n $as_echo) 2>/dev/null`" = "X-n $as_echo"; then + as_echo_body='eval /usr/ucb/echo -n "$1$as_nl"' + as_echo_n='/usr/ucb/echo -n' + else + as_echo_body='eval expr "X$1" : "X\\(.*\\)"' + as_echo_n_body='eval + arg=$1; + case $arg in + *"$as_nl"*) + expr "X$arg" : "X\\(.*\\)$as_nl"; + arg=`expr "X$arg" : ".*$as_nl\\(.*\\)"`;; + esac; + expr "X$arg" : "X\\(.*\\)" | tr -d "$as_nl" + ' + export as_echo_n_body + as_echo_n='sh -c $as_echo_n_body as_echo' + fi + export as_echo_body + as_echo='sh -c $as_echo_body as_echo' +fi + +# The user is always right. +if test "${PATH_SEPARATOR+set}" != set; then + PATH_SEPARATOR=: + (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && { + (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 || + PATH_SEPARATOR=';' + } +fi + +# Support unset when possible. +if ( (MAIL=60; unset MAIL) || exit) >/dev/null 2>&1; then + as_unset=unset +else + as_unset=false +fi + + +# IFS +# We need space, tab and new line, in precisely that order. Quoting is +# there to prevent editors from complaining about space-tab. +# (If _AS_PATH_WALK were called with IFS unset, it would disable word +# splitting by setting IFS to empty value.) +IFS=" "" $as_nl" + +# Find who we are. Look in the path if we contain no directory separator. +case $0 in + *[\\/]* ) as_myself=$0 ;; + *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break +done +IFS=$as_save_IFS + + ;; +esac +# We did not find ourselves, most probably we were run as `sh COMMAND' +# in which case we are not to be found in the path. +if test "x$as_myself" = x; then + as_myself=$0 +fi +if test ! -f "$as_myself"; then + $as_echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2 + { (exit 1); exit 1; } +fi + +# Work around bugs in pre-3.0 UWIN ksh. +for as_var in ENV MAIL MAILPATH +do ($as_unset $as_var) >/dev/null 2>&1 && $as_unset $as_var +done +PS1='$ ' +PS2='> ' +PS4='+ ' + +# NLS nuisances. +LC_ALL=C +export LC_ALL +LANGUAGE=C +export LANGUAGE + +# Required to use basename. +if expr a : '\(a\)' >/dev/null 2>&1 && + test "X`expr 00001 : '.*\(...\)'`" = X001; then + as_expr=expr +else + as_expr=false +fi + +if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then + as_basename=basename +else + as_basename=false +fi + + +# Name of the executable. +as_me=`$as_basename -- "$0" || +$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \ + X"$0" : 'X\(//\)$' \| \ + X"$0" : 'X\(/\)' \| . 2>/dev/null || +$as_echo X/"$0" | + sed '/^.*\/\([^/][^/]*\)\/*$/{ + s//\1/ + q + } + /^X\/\(\/\/\)$/{ + s//\1/ + q + } + /^X\/\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q'` + +# CDPATH. +$as_unset CDPATH + + + + as_lineno_1=$LINENO + as_lineno_2=$LINENO + test "x$as_lineno_1" != "x$as_lineno_2" && + test "x`expr $as_lineno_1 + 1`" = "x$as_lineno_2" || { + + # Create $as_me.lineno as a copy of $as_myself, but with $LINENO + # uniformly replaced by the line number. The first 'sed' inserts a + # line-number line after each line using $LINENO; the second 'sed' + # does the real work. The second script uses 'N' to pair each + # line-number line with the line containing $LINENO, and appends + # trailing '-' during substitution so that $LINENO is not a special + # case at line end. + # (Raja R Harinath suggested sed '=', and Paul Eggert wrote the + # scripts with optimization help from Paolo Bonzini. Blame Lee + # E. McMahon (1931-1989) for sed's syntax. :-) + sed -n ' + p + /[$]LINENO/= + ' <$as_myself | + sed ' + s/[$]LINENO.*/&-/ + t lineno + b + :lineno + N + :loop + s/[$]LINENO\([^'$as_cr_alnum'_].*\n\)\(.*\)/\2\1\2/ + t loop + s/-\n.*// + ' >$as_me.lineno && + chmod +x "$as_me.lineno" || + { $as_echo "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2 + { (exit 1); exit 1; }; } + + # Don't try to exec as it changes $[0], causing all sort of problems + # (the dirname of $[0] is not the place where we might find the + # original and so on. Autoconf is especially sensitive to this). + . "./$as_me.lineno" + # Exit status is that of the last command. + exit +} + + +if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then + as_dirname=dirname +else + as_dirname=false +fi + +ECHO_C= ECHO_N= ECHO_T= +case `echo -n x` in +-n*) + case `echo 'x\c'` in + *c*) ECHO_T=' ';; # ECHO_T is single tab character. + *) ECHO_C='\c';; + esac;; +*) + ECHO_N='-n';; +esac +if expr a : '\(a\)' >/dev/null 2>&1 && + test "X`expr 00001 : '.*\(...\)'`" = X001; then + as_expr=expr +else + as_expr=false +fi + +rm -f conf$$ conf$$.exe conf$$.file +if test -d conf$$.dir; then + rm -f conf$$.dir/conf$$.file +else + rm -f conf$$.dir + mkdir conf$$.dir 2>/dev/null +fi +if (echo >conf$$.file) 2>/dev/null; then + if ln -s conf$$.file conf$$ 2>/dev/null; then + as_ln_s='ln -s' + # ... but there are two gotchas: + # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail. + # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable. + # In both cases, we have to default to `cp -p'. + ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe || + as_ln_s='cp -p' + elif ln conf$$.file conf$$ 2>/dev/null; then + as_ln_s=ln + else + as_ln_s='cp -p' + fi +else + as_ln_s='cp -p' +fi +rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file +rmdir conf$$.dir 2>/dev/null + +if mkdir -p . 2>/dev/null; then + as_mkdir_p=: +else + test -d ./-p && rmdir ./-p + as_mkdir_p=false +fi + +if test -x / >/dev/null 2>&1; then + as_test_x='test -x' +else + if ls -dL / >/dev/null 2>&1; then + as_ls_L_option=L + else + as_ls_L_option= + fi + as_test_x=' + eval sh -c '\'' + if test -d "$1"; then + test -d "$1/."; + else + case $1 in + -*)set "./$1";; + esac; + case `ls -ld'$as_ls_L_option' "$1" 2>/dev/null` in + ???[sx]*):;;*)false;;esac;fi + '\'' sh + ' +fi +as_executable_p=$as_test_x + +# Sed expression to map a string onto a valid CPP name. +as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'" + +# Sed expression to map a string onto a valid variable name. +as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'" + + +exec 6>&1 + +# Save the log message, to keep $[0] and so on meaningful, and to +# report actual input values of CONFIG_FILES etc. instead of their +# values after options handling. +ac_log=" +This file was extended by $as_me, which was +generated by GNU Autoconf 2.63. Invocation command line was + + CONFIG_FILES = $CONFIG_FILES + CONFIG_HEADERS = $CONFIG_HEADERS + CONFIG_LINKS = $CONFIG_LINKS + CONFIG_COMMANDS = $CONFIG_COMMANDS + $ $0 $@ + +on `(hostname || uname -n) 2>/dev/null | sed 1q` +" + +_ACEOF + +case $ac_config_files in *" +"*) set x $ac_config_files; shift; ac_config_files=$*;; +esac + +case $ac_config_headers in *" +"*) set x $ac_config_headers; shift; ac_config_headers=$*;; +esac + + +cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 +# Files that config.status was made for. +config_files="$ac_config_files" +config_headers="$ac_config_headers" +config_commands="$ac_config_commands" + +_ACEOF + +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 +ac_cs_usage="\ +\`$as_me' instantiates files from templates according to the +current configuration. + +Usage: $0 [OPTION]... [FILE]... + + -h, --help print this help, then exit + -V, --version print version number and configuration settings, then exit + -q, --quiet, --silent + do not print progress messages + -d, --debug don't remove temporary files + --recheck update $as_me by reconfiguring in the same conditions + --file=FILE[:TEMPLATE] + instantiate the configuration file FILE + --header=FILE[:TEMPLATE] + instantiate the configuration header FILE + +Configuration files: +$config_files + +Configuration headers: +$config_headers + +Configuration commands: +$config_commands + +Report bugs to ." + +_ACEOF +cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 +ac_cs_version="\\ +config.status +configured by $0, generated by GNU Autoconf 2.63, + with options \\"`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`\\" + +Copyright (C) 2008 Free Software Foundation, Inc. +This config.status script is free software; the Free Software Foundation +gives unlimited permission to copy, distribute and modify it." + +ac_pwd='$ac_pwd' +srcdir='$srcdir' +INSTALL='$INSTALL' +test -n "\$AWK" || AWK=awk +_ACEOF + +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 +# The default lists apply if the user does not specify any file. +ac_need_defaults=: +while test $# != 0 +do + case $1 in + --*=*) + ac_option=`expr "X$1" : 'X\([^=]*\)='` + ac_optarg=`expr "X$1" : 'X[^=]*=\(.*\)'` + ac_shift=: + ;; + *) + ac_option=$1 + ac_optarg=$2 + ac_shift=shift + ;; + esac + + case $ac_option in + # Handling of the options. + -recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r) + ac_cs_recheck=: ;; + --version | --versio | --versi | --vers | --ver | --ve | --v | -V ) + $as_echo "$ac_cs_version"; exit ;; + --debug | --debu | --deb | --de | --d | -d ) + debug=: ;; + --file | --fil | --fi | --f ) + $ac_shift + case $ac_optarg in + *\'*) ac_optarg=`$as_echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"` ;; + esac + CONFIG_FILES="$CONFIG_FILES '$ac_optarg'" + ac_need_defaults=false;; + --header | --heade | --head | --hea ) + $ac_shift + case $ac_optarg in + *\'*) ac_optarg=`$as_echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"` ;; + esac + CONFIG_HEADERS="$CONFIG_HEADERS '$ac_optarg'" + ac_need_defaults=false;; + --he | --h) + # Conflict between --help and --header + { $as_echo "$as_me: error: ambiguous option: $1 +Try \`$0 --help' for more information." >&2 + { (exit 1); exit 1; }; };; + --help | --hel | -h ) + $as_echo "$ac_cs_usage"; exit ;; + -q | -quiet | --quiet | --quie | --qui | --qu | --q \ + | -silent | --silent | --silen | --sile | --sil | --si | --s) + ac_cs_silent=: ;; + + # This is an error. + -*) { $as_echo "$as_me: error: unrecognized option: $1 +Try \`$0 --help' for more information." >&2 + { (exit 1); exit 1; }; } ;; + + *) ac_config_targets="$ac_config_targets $1" + ac_need_defaults=false ;; + + esac + shift +done + +ac_configure_extra_args= + +if $ac_cs_silent; then + exec 6>/dev/null + ac_configure_extra_args="$ac_configure_extra_args --silent" +fi + +_ACEOF +cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 +if \$ac_cs_recheck; then + set X '$SHELL' '$0' $ac_configure_args \$ac_configure_extra_args --no-create --no-recursion + shift + \$as_echo "running CONFIG_SHELL=$SHELL \$*" >&6 + CONFIG_SHELL='$SHELL' + export CONFIG_SHELL + exec "\$@" +fi + +_ACEOF +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 +exec 5>>config.log +{ + echo + sed 'h;s/./-/g;s/^.../## /;s/...$/ ##/;p;x;p;x' <<_ASBOX +## Running $as_me. ## +_ASBOX + $as_echo "$ac_log" +} >&5 + +_ACEOF +cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 +# +# INIT-COMMANDS +# +INTLTOOL_PERL=${INTLTOOL_PERL} + + +_ACEOF + +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 + +# Handling of arguments. +for ac_config_target in $ac_config_targets +do + case $ac_config_target in + "config.h") CONFIG_HEADERS="$CONFIG_HEADERS config.h" ;; + "default-1") CONFIG_COMMANDS="$CONFIG_COMMANDS default-1" ;; + "default-2") CONFIG_COMMANDS="$CONFIG_COMMANDS default-2" ;; + "Makefile") CONFIG_FILES="$CONFIG_FILES Makefile" ;; + "utils/Makefile") CONFIG_FILES="$CONFIG_FILES utils/Makefile" ;; + "driver/Makefile") CONFIG_FILES="$CONFIG_FILES driver/Makefile" ;; + "driver/xscreensaver.pam") CONFIG_FILES="$CONFIG_FILES driver/xscreensaver.pam" ;; + "hacks/Makefile") CONFIG_FILES="$CONFIG_FILES hacks/Makefile" ;; + "hacks/glx/Makefile") CONFIG_FILES="$CONFIG_FILES hacks/glx/Makefile" ;; + "po/Makefile.in") CONFIG_FILES="$CONFIG_FILES po/Makefile.in" ;; + "driver/XScreenSaver.ad") CONFIG_FILES="$CONFIG_FILES driver/XScreenSaver.ad" ;; + + *) { { $as_echo "$as_me:$LINENO: error: invalid argument: $ac_config_target" >&5 +$as_echo "$as_me: error: invalid argument: $ac_config_target" >&2;} + { (exit 1); exit 1; }; };; + esac +done + + +# If the user did not use the arguments to specify the items to instantiate, +# then the envvar interface is used. Set only those that are not. +# We use the long form for the default assignment because of an extremely +# bizarre bug on SunOS 4.1.3. +if $ac_need_defaults; then + test "${CONFIG_FILES+set}" = set || CONFIG_FILES=$config_files + test "${CONFIG_HEADERS+set}" = set || CONFIG_HEADERS=$config_headers + test "${CONFIG_COMMANDS+set}" = set || CONFIG_COMMANDS=$config_commands +fi + +# Have a temporary directory for convenience. Make it in the build tree +# simply because there is no reason against having it here, and in addition, +# creating and moving files from /tmp can sometimes cause problems. +# Hook for its removal unless debugging. +# Note that there is a small window in which the directory will not be cleaned: +# after its creation but before its name has been assigned to `$tmp'. +$debug || +{ + tmp= + trap 'exit_status=$? + { test -z "$tmp" || test ! -d "$tmp" || rm -fr "$tmp"; } && exit $exit_status +' 0 + trap '{ (exit 1); exit 1; }' 1 2 13 15 +} +# Create a (secure) tmp directory for tmp files. + +{ + tmp=`(umask 077 && mktemp -d "./confXXXXXX") 2>/dev/null` && + test -n "$tmp" && test -d "$tmp" +} || +{ + tmp=./conf$$-$RANDOM + (umask 077 && mkdir "$tmp") +} || +{ + $as_echo "$as_me: cannot create a temporary directory in ." >&2 + { (exit 1); exit 1; } +} + +# Set up the scripts for CONFIG_FILES section. +# No need to generate them if there are no CONFIG_FILES. +# This happens for instance with `./config.status config.h'. +if test -n "$CONFIG_FILES"; then + + +ac_cr=' ' +ac_cs_awk_cr=`$AWK 'BEGIN { print "a\rb" }' /dev/null` +if test "$ac_cs_awk_cr" = "a${ac_cr}b"; then + ac_cs_awk_cr='\\r' +else + ac_cs_awk_cr=$ac_cr +fi + +echo 'BEGIN {' >"$tmp/subs1.awk" && +_ACEOF + + +{ + echo "cat >conf$$subs.awk <<_ACEOF" && + echo "$ac_subst_vars" | sed 's/.*/&!$&$ac_delim/' && + echo "_ACEOF" +} >conf$$subs.sh || + { { $as_echo "$as_me:$LINENO: error: could not make $CONFIG_STATUS" >&5 +$as_echo "$as_me: error: could not make $CONFIG_STATUS" >&2;} + { (exit 1); exit 1; }; } +ac_delim_num=`echo "$ac_subst_vars" | grep -c '$'` +ac_delim='%!_!# ' +for ac_last_try in false false false false false :; do + . ./conf$$subs.sh || + { { $as_echo "$as_me:$LINENO: error: could not make $CONFIG_STATUS" >&5 +$as_echo "$as_me: error: could not make $CONFIG_STATUS" >&2;} + { (exit 1); exit 1; }; } + + ac_delim_n=`sed -n "s/.*$ac_delim\$/X/p" conf$$subs.awk | grep -c X` + if test $ac_delim_n = $ac_delim_num; then + break + elif $ac_last_try; then + { { $as_echo "$as_me:$LINENO: error: could not make $CONFIG_STATUS" >&5 +$as_echo "$as_me: error: could not make $CONFIG_STATUS" >&2;} + { (exit 1); exit 1; }; } + else + ac_delim="$ac_delim!$ac_delim _$ac_delim!! " + fi +done +rm -f conf$$subs.sh + +cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 +cat >>"\$tmp/subs1.awk" <<\\_ACAWK && +_ACEOF +sed -n ' +h +s/^/S["/; s/!.*/"]=/ +p +g +s/^[^!]*!// +:repl +t repl +s/'"$ac_delim"'$// +t delim +:nl +h +s/\(.\{148\}\).*/\1/ +t more1 +s/["\\]/\\&/g; s/^/"/; s/$/\\n"\\/ +p +n +b repl +:more1 +s/["\\]/\\&/g; s/^/"/; s/$/"\\/ +p +g +s/.\{148\}// +t nl +:delim +h +s/\(.\{148\}\).*/\1/ +t more2 +s/["\\]/\\&/g; s/^/"/; s/$/"/ +p +b +:more2 +s/["\\]/\\&/g; s/^/"/; s/$/"\\/ +p +g +s/.\{148\}// +t delim +' >$CONFIG_STATUS || ac_write_fail=1 +rm -f conf$$subs.awk +cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 +_ACAWK +cat >>"\$tmp/subs1.awk" <<_ACAWK && + for (key in S) S_is_set[key] = 1 + FS = "" + +} +{ + line = $ 0 + nfields = split(line, field, "@") + substed = 0 + len = length(field[1]) + for (i = 2; i < nfields; i++) { + key = field[i] + keylen = length(key) + if (S_is_set[key]) { + value = S[key] + line = substr(line, 1, len) "" value "" substr(line, len + keylen + 3) + len += length(value) + length(field[++i]) + substed = 1 + } else + len += 1 + keylen + } + + print line +} + +_ACAWK +_ACEOF +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 +if sed "s/$ac_cr//" < /dev/null > /dev/null 2>&1; then + sed "s/$ac_cr\$//; s/$ac_cr/$ac_cs_awk_cr/g" +else + cat +fi < "$tmp/subs1.awk" > "$tmp/subs.awk" \ + || { { $as_echo "$as_me:$LINENO: error: could not setup config files machinery" >&5 +$as_echo "$as_me: error: could not setup config files machinery" >&2;} + { (exit 1); exit 1; }; } +_ACEOF + +# VPATH may cause trouble with some makes, so we remove $(srcdir), +# ${srcdir} and @srcdir@ from VPATH if srcdir is ".", strip leading and +# trailing colons and then remove the whole line if VPATH becomes empty +# (actually we leave an empty line to preserve line numbers). +if test "x$srcdir" = x.; then + ac_vpsub='/^[ ]*VPATH[ ]*=/{ +s/:*\$(srcdir):*/:/ +s/:*\${srcdir}:*/:/ +s/:*@srcdir@:*/:/ +s/^\([^=]*=[ ]*\):*/\1/ +s/:*$// +s/^[^=]*=[ ]*$// +}' +fi + +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 +fi # test -n "$CONFIG_FILES" + +# Set up the scripts for CONFIG_HEADERS section. +# No need to generate them if there are no CONFIG_HEADERS. +# This happens for instance with `./config.status Makefile'. +if test -n "$CONFIG_HEADERS"; then +cat >"$tmp/defines.awk" <<\_ACAWK || +BEGIN { +_ACEOF + +# Transform confdefs.h into an awk script `defines.awk', embedded as +# here-document in config.status, that substitutes the proper values into +# config.h.in to produce config.h. + +# Create a delimiter string that does not exist in confdefs.h, to ease +# handling of long lines. +ac_delim='%!_!# ' +for ac_last_try in false false :; do + ac_t=`sed -n "/$ac_delim/p" confdefs.h` + if test -z "$ac_t"; then + break + elif $ac_last_try; then + { { $as_echo "$as_me:$LINENO: error: could not make $CONFIG_HEADERS" >&5 +$as_echo "$as_me: error: could not make $CONFIG_HEADERS" >&2;} + { (exit 1); exit 1; }; } + else + ac_delim="$ac_delim!$ac_delim _$ac_delim!! " + fi +done + +# For the awk script, D is an array of macro values keyed by name, +# likewise P contains macro parameters if any. Preserve backslash +# newline sequences. + +ac_word_re=[_$as_cr_Letters][_$as_cr_alnum]* +sed -n ' +s/.\{148\}/&'"$ac_delim"'/g +t rset +:rset +s/^[ ]*#[ ]*define[ ][ ]*/ / +t def +d +:def +s/\\$// +t bsnl +s/["\\]/\\&/g +s/^ \('"$ac_word_re"'\)\(([^()]*)\)[ ]*\(.*\)/P["\1"]="\2"\ +D["\1"]=" \3"/p +s/^ \('"$ac_word_re"'\)[ ]*\(.*\)/D["\1"]=" \2"/p +d +:bsnl +s/["\\]/\\&/g +s/^ \('"$ac_word_re"'\)\(([^()]*)\)[ ]*\(.*\)/P["\1"]="\2"\ +D["\1"]=" \3\\\\\\n"\\/p +t cont +s/^ \('"$ac_word_re"'\)[ ]*\(.*\)/D["\1"]=" \2\\\\\\n"\\/p +t cont +d +:cont +n +s/.\{148\}/&'"$ac_delim"'/g +t clear +:clear +s/\\$// +t bsnlc +s/["\\]/\\&/g; s/^/"/; s/$/"/p +d +:bsnlc +s/["\\]/\\&/g; s/^/"/; s/$/\\\\\\n"\\/p +b cont +' >$CONFIG_STATUS || ac_write_fail=1 + +cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 + for (key in D) D_is_set[key] = 1 + FS = "" +} +/^[\t ]*#[\t ]*(define|undef)[\t ]+$ac_word_re([\t (]|\$)/ { + line = \$ 0 + split(line, arg, " ") + if (arg[1] == "#") { + defundef = arg[2] + mac1 = arg[3] + } else { + defundef = substr(arg[1], 2) + mac1 = arg[2] + } + split(mac1, mac2, "(") #) + macro = mac2[1] + prefix = substr(line, 1, index(line, defundef) - 1) + if (D_is_set[macro]) { + # Preserve the white space surrounding the "#". + print prefix "define", macro P[macro] D[macro] + next + } else { + # Replace #undef with comments. This is necessary, for example, + # in the case of _POSIX_SOURCE, which is predefined and required + # on some systems where configure will not decide to define it. + if (defundef == "undef") { + print "/*", prefix defundef, macro, "*/" + next + } + } +} +{ print } +_ACAWK +_ACEOF +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 + { { $as_echo "$as_me:$LINENO: error: could not setup config headers machinery" >&5 +$as_echo "$as_me: error: could not setup config headers machinery" >&2;} + { (exit 1); exit 1; }; } +fi # test -n "$CONFIG_HEADERS" + + +eval set X " :F $CONFIG_FILES :H $CONFIG_HEADERS :C $CONFIG_COMMANDS" +shift +for ac_tag +do + case $ac_tag in + :[FHLC]) ac_mode=$ac_tag; continue;; + esac + case $ac_mode$ac_tag in + :[FHL]*:*);; + :L* | :C*:*) { { $as_echo "$as_me:$LINENO: error: invalid tag $ac_tag" >&5 +$as_echo "$as_me: error: invalid tag $ac_tag" >&2;} + { (exit 1); exit 1; }; };; + :[FH]-) ac_tag=-:-;; + :[FH]*) ac_tag=$ac_tag:$ac_tag.in;; + esac + ac_save_IFS=$IFS + IFS=: + set x $ac_tag + IFS=$ac_save_IFS + shift + ac_file=$1 + shift + + case $ac_mode in + :L) ac_source=$1;; + :[FH]) + ac_file_inputs= + for ac_f + do + case $ac_f in + -) ac_f="$tmp/stdin";; + *) # Look for the file first in the build tree, then in the source tree + # (if the path is not absolute). The absolute path cannot be DOS-style, + # because $ac_f cannot contain `:'. + test -f "$ac_f" || + case $ac_f in + [\\/$]*) false;; + *) test -f "$srcdir/$ac_f" && ac_f="$srcdir/$ac_f";; + esac || + { { $as_echo "$as_me:$LINENO: error: cannot find input file: $ac_f" >&5 +$as_echo "$as_me: error: cannot find input file: $ac_f" >&2;} + { (exit 1); exit 1; }; };; + esac + case $ac_f in *\'*) ac_f=`$as_echo "$ac_f" | sed "s/'/'\\\\\\\\''/g"`;; esac + ac_file_inputs="$ac_file_inputs '$ac_f'" + done + + # Let's still pretend it is `configure' which instantiates (i.e., don't + # use $as_me), people would be surprised to read: + # /* config.h. Generated by config.status. */ + configure_input='Generated from '` + $as_echo "$*" | sed 's|^[^:]*/||;s|:[^:]*/|, |g' + `' by configure.' + if test x"$ac_file" != x-; then + configure_input="$ac_file. $configure_input" + { $as_echo "$as_me:$LINENO: creating $ac_file" >&5 +$as_echo "$as_me: creating $ac_file" >&6;} + fi + # Neutralize special characters interpreted by sed in replacement strings. + case $configure_input in #( + *\&* | *\|* | *\\* ) + ac_sed_conf_input=`$as_echo "$configure_input" | + sed 's/[\\\\&|]/\\\\&/g'`;; #( + *) ac_sed_conf_input=$configure_input;; + esac + + case $ac_tag in + *:-:* | *:-) cat >"$tmp/stdin" \ + || { { $as_echo "$as_me:$LINENO: error: could not create $ac_file" >&5 +$as_echo "$as_me: error: could not create $ac_file" >&2;} + { (exit 1); exit 1; }; } ;; + esac + ;; + esac + + ac_dir=`$as_dirname -- "$ac_file" || +$as_expr X"$ac_file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$ac_file" : 'X\(//\)[^/]' \| \ + X"$ac_file" : 'X\(//\)$' \| \ + X"$ac_file" : 'X\(/\)' \| . 2>/dev/null || +$as_echo X"$ac_file" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ + s//\1/ + q + } + /^X\(\/\/\)[^/].*/{ + s//\1/ + q + } + /^X\(\/\/\)$/{ + s//\1/ + q + } + /^X\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q'` + { as_dir="$ac_dir" + case $as_dir in #( + -*) as_dir=./$as_dir;; + esac + test -d "$as_dir" || { $as_mkdir_p && mkdir -p "$as_dir"; } || { + as_dirs= + while :; do + case $as_dir in #( + *\'*) as_qdir=`$as_echo "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #'( + *) as_qdir=$as_dir;; + esac + as_dirs="'$as_qdir' $as_dirs" + as_dir=`$as_dirname -- "$as_dir" || +$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$as_dir" : 'X\(//\)[^/]' \| \ + X"$as_dir" : 'X\(//\)$' \| \ + X"$as_dir" : 'X\(/\)' \| . 2>/dev/null || +$as_echo X"$as_dir" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ + s//\1/ + q + } + /^X\(\/\/\)[^/].*/{ + s//\1/ + q + } + /^X\(\/\/\)$/{ + s//\1/ + q + } + /^X\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q'` + test -d "$as_dir" && break + done + test -z "$as_dirs" || eval "mkdir $as_dirs" + } || test -d "$as_dir" || { { $as_echo "$as_me:$LINENO: error: cannot create directory $as_dir" >&5 +$as_echo "$as_me: error: cannot create directory $as_dir" >&2;} + { (exit 1); exit 1; }; }; } + ac_builddir=. + +case "$ac_dir" in +.) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;; +*) + ac_dir_suffix=/`$as_echo "$ac_dir" | sed 's|^\.[\\/]||'` + # A ".." for each directory in $ac_dir_suffix. + ac_top_builddir_sub=`$as_echo "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'` + case $ac_top_builddir_sub in + "") ac_top_builddir_sub=. ac_top_build_prefix= ;; + *) ac_top_build_prefix=$ac_top_builddir_sub/ ;; + esac ;; +esac +ac_abs_top_builddir=$ac_pwd +ac_abs_builddir=$ac_pwd$ac_dir_suffix +# for backward compatibility: +ac_top_builddir=$ac_top_build_prefix + +case $srcdir in + .) # We are building in place. + ac_srcdir=. + ac_top_srcdir=$ac_top_builddir_sub + ac_abs_top_srcdir=$ac_pwd ;; + [\\/]* | ?:[\\/]* ) # Absolute name. + ac_srcdir=$srcdir$ac_dir_suffix; + ac_top_srcdir=$srcdir + ac_abs_top_srcdir=$srcdir ;; + *) # Relative name. + ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix + ac_top_srcdir=$ac_top_build_prefix$srcdir + ac_abs_top_srcdir=$ac_pwd/$srcdir ;; +esac +ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix + + + case $ac_mode in + :F) + # + # CONFIG_FILE + # + + case $INSTALL in + [\\/$]* | ?:[\\/]* ) ac_INSTALL=$INSTALL ;; + *) ac_INSTALL=$ac_top_build_prefix$INSTALL ;; + esac +_ACEOF + +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 +# If the template does not know about datarootdir, expand it. +# FIXME: This hack should be removed a few years after 2.60. +ac_datarootdir_hack=; ac_datarootdir_seen= + +ac_sed_dataroot=' +/datarootdir/ { + p + q +} +/@datadir@/p +/@docdir@/p +/@infodir@/p +/@localedir@/p +/@mandir@/p +' +case `eval "sed -n \"\$ac_sed_dataroot\" $ac_file_inputs"` in +*datarootdir*) ac_datarootdir_seen=yes;; +*@datadir@*|*@docdir@*|*@infodir@*|*@localedir@*|*@mandir@*) + { $as_echo "$as_me:$LINENO: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&5 +$as_echo "$as_me: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&2;} +_ACEOF +cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 + ac_datarootdir_hack=' + s&@datadir@&$datadir&g + s&@docdir@&$docdir&g + s&@infodir@&$infodir&g + s&@localedir@&$localedir&g + s&@mandir@&$mandir&g + s&\\\${datarootdir}&$datarootdir&g' ;; +esac +_ACEOF + +# Neutralize VPATH when `$srcdir' = `.'. +# Shell code in configure.ac might set extrasub. +# FIXME: do we really want to maintain this feature? +cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 +ac_sed_extra="$ac_vpsub +$extrasub +_ACEOF +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 +:t +/@[a-zA-Z_][a-zA-Z_0-9]*@/!b +s|@configure_input@|$ac_sed_conf_input|;t t +s&@top_builddir@&$ac_top_builddir_sub&;t t +s&@top_build_prefix@&$ac_top_build_prefix&;t t +s&@srcdir@&$ac_srcdir&;t t +s&@abs_srcdir@&$ac_abs_srcdir&;t t +s&@top_srcdir@&$ac_top_srcdir&;t t +s&@abs_top_srcdir@&$ac_abs_top_srcdir&;t t +s&@builddir@&$ac_builddir&;t t +s&@abs_builddir@&$ac_abs_builddir&;t t +s&@abs_top_builddir@&$ac_abs_top_builddir&;t t +s&@INSTALL@&$ac_INSTALL&;t t +$ac_datarootdir_hack +" +eval sed \"\$ac_sed_extra\" "$ac_file_inputs" | $AWK -f "$tmp/subs.awk" >$tmp/out \ + || { { $as_echo "$as_me:$LINENO: error: could not create $ac_file" >&5 +$as_echo "$as_me: error: could not create $ac_file" >&2;} + { (exit 1); exit 1; }; } + +test -z "$ac_datarootdir_hack$ac_datarootdir_seen" && + { ac_out=`sed -n '/\${datarootdir}/p' "$tmp/out"`; test -n "$ac_out"; } && + { ac_out=`sed -n '/^[ ]*datarootdir[ ]*:*=/p' "$tmp/out"`; test -z "$ac_out"; } && + { $as_echo "$as_me:$LINENO: WARNING: $ac_file contains a reference to the variable \`datarootdir' +which seems to be undefined. Please make sure it is defined." >&5 +$as_echo "$as_me: WARNING: $ac_file contains a reference to the variable \`datarootdir' +which seems to be undefined. Please make sure it is defined." >&2;} + + rm -f "$tmp/stdin" + case $ac_file in + -) cat "$tmp/out" && rm -f "$tmp/out";; + *) rm -f "$ac_file" && mv "$tmp/out" "$ac_file";; + esac \ + || { { $as_echo "$as_me:$LINENO: error: could not create $ac_file" >&5 +$as_echo "$as_me: error: could not create $ac_file" >&2;} + { (exit 1); exit 1; }; } + ;; + :H) + # + # CONFIG_HEADER + # + if test x"$ac_file" != x-; then + { + $as_echo "/* $configure_input */" \ + && eval '$AWK -f "$tmp/defines.awk"' "$ac_file_inputs" + } >"$tmp/config.h" \ + || { { $as_echo "$as_me:$LINENO: error: could not create $ac_file" >&5 +$as_echo "$as_me: error: could not create $ac_file" >&2;} + { (exit 1); exit 1; }; } + if diff "$ac_file" "$tmp/config.h" >/dev/null 2>&1; then + { $as_echo "$as_me:$LINENO: $ac_file is unchanged" >&5 +$as_echo "$as_me: $ac_file is unchanged" >&6;} + else + rm -f "$ac_file" + mv "$tmp/config.h" "$ac_file" \ + || { { $as_echo "$as_me:$LINENO: error: could not create $ac_file" >&5 +$as_echo "$as_me: error: could not create $ac_file" >&2;} + { (exit 1); exit 1; }; } + fi + else + $as_echo "/* $configure_input */" \ + && eval '$AWK -f "$tmp/defines.awk"' "$ac_file_inputs" \ + || { { $as_echo "$as_me:$LINENO: error: could not create -" >&5 +$as_echo "$as_me: error: could not create -" >&2;} + { (exit 1); exit 1; }; } + fi + ;; + + :C) { $as_echo "$as_me:$LINENO: executing $ac_file commands" >&5 +$as_echo "$as_me: executing $ac_file commands" >&6;} + ;; + esac + + + case $ac_file$ac_mode in + "default-1":C) + +sed -e "s:@INTLTOOL_PERL@:${INTLTOOL_PERL}:;" < ${srcdir}/intltool-extract.in > intltool-extract.out +if cmp -s intltool-extract intltool-extract.out 2>/dev/null; then + rm -f intltool-extract.out +else + mv -f intltool-extract.out intltool-extract +fi +chmod ugo+x intltool-extract +chmod u+w intltool-extract + +sed -e "s:@INTLTOOL_PERL@:${INTLTOOL_PERL}:;" < ${srcdir}/intltool-merge.in > intltool-merge.out +if cmp -s intltool-merge intltool-merge.out 2>/dev/null; then + rm -f intltool-merge.out +else + mv -f intltool-merge.out intltool-merge +fi +chmod ugo+x intltool-merge +chmod u+w intltool-merge + +sed -e "s:@INTLTOOL_PERL@:${INTLTOOL_PERL}:;" < ${srcdir}/intltool-update.in > intltool-update.out +if cmp -s intltool-update intltool-update.out 2>/dev/null; then + rm -f intltool-update.out +else + mv -f intltool-update.out intltool-update +fi +chmod ugo+x intltool-update +chmod u+w intltool-update + + ;; + "default-2":C) case "$CONFIG_FILES" in *po/Makefile.in*) + rm -f po/stamp-it po/stamp-it.tmp + > po/stamp-it.tmp + sed -e "/POTFILES =/r po/POTFILES" po/Makefile.in > po/Makefile + mv po/stamp-it.tmp po/stamp-it + esac ;; + + esac +done # for ac_tag + + +{ (exit 0); exit 0; } +_ACEOF +chmod +x $CONFIG_STATUS +ac_clean_files=$ac_clean_files_save + +test $ac_write_fail = 0 || + { { $as_echo "$as_me:$LINENO: error: write failure creating $CONFIG_STATUS" >&5 +$as_echo "$as_me: error: write failure creating $CONFIG_STATUS" >&2;} + { (exit 1); exit 1; }; } + + +# configure is writing to config.log, and then calls config.status. +# config.status does its own redirection, appending to config.log. +# Unfortunately, on DOS this fails, as config.log is still kept open +# by configure, so config.status won't be able to write to it; its +# output is simply discarded. So we exec the FD to /dev/null, +# effectively closing config.log, so it can be properly (re)opened and +# appended to by config.status. When coming back to configure, we +# need to make the FD available again. +if test "$no_create" != yes; then + ac_cs_success=: + ac_config_status_args= + test "$silent" = yes && + ac_config_status_args="$ac_config_status_args --quiet" + exec 5>/dev/null + $SHELL $CONFIG_STATUS $ac_config_status_args || ac_cs_success=false + exec 5>>config.log + # Use ||, not &&, to avoid exiting from the if with $? = 1, which + # would make configure fail if this is the last instruction. + $ac_cs_success || { (exit 1); exit 1; } +fi +if test -n "$ac_unrecognized_opts" && test "$enable_option_checking" != no; then + { $as_echo "$as_me:$LINENO: WARNING: unrecognized options: $ac_unrecognized_opts" >&5 +$as_echo "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2;} +fi + + +############################################################################### +# +# Print some warnings at the end. +# +############################################################################### + +warn_prefix_1=" Warning:" +warn_prefix_2=" Note:" +warn_prefix="$warn_prefix_1" + +warning=no +warnsep=' #################################################################' + +warnpre() { + if test "$warning" = no ; then + echo '' ; echo "$warnsep" ; echo '' + warning=yes + fi +} + +warn() { + warnpre + if test "$warning" = long ; then echo '' ; fi + warning=yes + rest="$@" + echo "$warn_prefix $rest" +} + +warnL() { + was=$warning + warnpre + warning=yes + if test "$was" != no ; then echo '' ; fi + rest="$@" + echo "$warn_prefix $rest" +} + +warn2() { + rest="$@" + echo " $rest" + warning=long +} + +note() { + warn_prefix="$warn_prefix_2" + warn $@ + warn_prefix="$warn_prefix_1" +} + +noteL() { + warn_prefix="$warn_prefix_2" + warnL $@ + warn_prefix="$warn_prefix_1" +} + + +if test "$with_sgi_req" = yes -a "$have_sgi" = no ; then + warn 'The SGI saver extension was requested, but was not found.' +fi + +if test "$with_xidle_req" = yes -a "$have_xidle" = no ; then + warn 'The XIdle extension was requested, but was not found.' +fi + +if test "$with_xshm_req" = yes -a "$have_xshm" = no ; then + warn 'The XSHM extension was requested, but was not found.' +fi + +if test "$with_xdbe_req" = yes -a "$have_xdbe" = no ; then + warn 'The DOUBLE-BUFFER extension was requested, but was not found.' +fi + +if test "$with_sgivc_req" = yes -a "$have_sgivc" = no ; then + warn 'The SGI-VIDEO-CONTROL extension was requested, but was not found.' +fi + +if test "$with_dpms_req" = yes -a "$have_dpms" = no ; then + warn 'The DPMS extension was requested, but was not found.' +fi + +if test "$with_xinerama_req" = yes -a "$have_xinerama" = no ; then + warn 'The Xinerama extension was requested, but was not found.' +fi + +if test "$with_xf86vmode_req" = yes -a "$have_xf86vmode" = no ; then + warn 'The XF86VMODE extension was requested, but was not found.' +fi + +if test "$with_randr_req" = yes -a "$have_randr" = no ; then + warn 'The RANDR extension was requested, but was not found.' +fi + +if test "$with_proc_interrupts_req" = yes -a "$have_proc_interrupts" = no; then + warn "Checking of /proc/interrupts was requested, but it's bogus." +fi + +if test "$pkg_config" = false ; then + warnL 'The "pkg-config" program was not found. Without that,' + warn2 "detection of the various GTK libraries won't work." +else + pkgerr=`$pkg_config --list-all 2>&1 >/dev/null` + if test "x$pkgerr" != "x" ; then + warnL 'The "pkg-config" program produces errors. This often causes' + warn2 "detection of the various GTK libraries to malfunction." + warn2 "The errors are:" + echo '' + echo "$pkgerr" | sed 's/^/ > /g' + fi +fi + +if test "$gtk_halfassed" != no ; then + warnL "GTK version $gtk_halfassed was found, but at least one supporting" + warn2 "library ($gtk_halfassed_lib) was not, so GTK can't be used." + warn2 "Perhaps some of the development packages are not installed?" + if test "$have_gtk" = yes ; then + v="$ac_gtk_version_string" + warn2 "GTK $v is also installed, so it will be used instead." + warn2 "Please read the above output and the \`config.log' file" + warn2 "for more details." + fi +fi + +motif_warn2() { + warn2 'Though the Motif front-end to xscreensaver is still' + warn2 'maintained, it is no longer being updated with new' + warn2 'features: all new development on the xscreensaver-demo' + warn2 'program is happening in the GTK version, and not in the' + warn2 'Motif version. It is recommended that you build against' + warn2 'GTK instead of Motif. See .' +} + +if test "$have_motif" = no -a "$have_gtk" = no; then + + if test "$with_motif" = yes; then + warnL "Neither the GTK nor Motif libraries were found; the" + warn2 "\`xscreensaver-demo' program requires one of these." + echo '' + motif_warn2 + else + warnL "The GTK libraries do not seem to be available; the" + warn2 "\`xscreensaver-demo' program requires them." +# echo '' +# warn2 'You can use Motif or Lesstif instead of GTK (use the' +# warn2 "\`--with-motif' option) but that is NOT recommended." +# motif_warn2 + fi + +elif test "$with_motif_req" = yes -a "$have_motif" = no ; then + warnL "Use of Motif was requested, but it wasn't found;" + warn2 "Gtk will be used instead." + +elif test "$jurassic_gtk" = yes ; then + + pref_gtk=2.0 + + v="$ac_gtk_version_string" + if test "$with_gtk_req" = yes -a "$ac_gtk_version" = "unknown" ; then + warnL "Use of Gtk was requested, but its version number is unknown;" + elif test "$with_gtk_req" = yes ; then + warnL "Use of Gtk was requested, but it is version $v;" + else + warnL "Gtk was found on this system, but it is version $v;" + fi + + warn2 "Gtk $pref_gtk or newer is required." + +elif test "$with_gtk_req" = yes -a "$have_gtk" = no ; then + warnL "Use of Gtk was requested, but it wasn't found." +fi + + +if test "$have_gtk" = yes -a "$have_gdk_pixbuf" = no ; then + warn "GTK is being used, but the GDK-Pixbuf library and/or" + warn2 "headers were not found. That can't be good. Please" + warn2 "install the GDK-Pixbuf development kit and re-configure." +fi + +if test "$have_motif" = yes -a "$have_lesstif" = yes ; then + + preferred_lesstif=0.92 + + if test "$lesstif_version" = unknown; then + warnL "Unable to determine the LessTif version number!" + warn2 "Make sure you are using version $preferred_lesstif or newer." + warn2 "See ." + + elif test \! $lesstif_version -gt 82; then + warnL "LessTif version $lesstif_version_string is being used." + warn2 "LessTif versions 0.82 and earlier are too buggy to" + warn2 "use with XScreenSaver; it is strongly recommended" + warn2 "that you upgrade to at least version $preferred_lesstif!" + warn2 "See ." + fi +fi + + +if test "$have_motif" = yes -a "$have_gtk" = no ; then + warn 'Motif is being used, and GTK is not.' + echo '' + motif_warn2 +fi + + +if test "$with_xpm_req" = yes -a "$have_xpm" = no; then + warnL 'Use of XPM was requested, but it was not found.' +fi + +if test "$with_gdk_pixbuf_req" = yes -a "$have_gdk_pixbuf" = no; then + warnL 'Use of GDK-Pixbuf was requested, but it was not found.' +fi + +if test "$have_gdk_pixbuf" = no -o "$gdk_pixbuf_halfassed" = yes || \ + test "$have_gdk_pixbuf" = no -a "$have_xpm" = no ; then + + if test "$with_gdk_pixbuf_req" = yes ; then + true + elif test "$with_gdk_pixbuf_req" = no ; then + warnL 'The GDK-Pixbuf library is not being used.' + else + warnL 'The GDK-Pixbuf library was not found.' + fi + + if test "$with_xpm_req" = yes -o "$have_xpm" = yes ; then + true + elif test "$with_xpm_req" = no ; then + warnL 'The XPM library is not being used.' + else + warnL 'The XPM library was not found.' + fi + + if test "$have_gdk_pixbuf" = no -a "$have_xpm" = yes ; then + warn2 'The XPM library is being used instead.' + fi + + if test "$gdk_pixbuf_halfassed" = yes ; then + echo '' + warn2 'More specifically, we found the headers, but not the' + warn2 'libraries; so either GDK-Pixbuf is half-installed on this' + warn2 "system, or something else went wrong. The \`config.log'" + warn2 'file might contain some clues.' + fi + + echo '' + warn2 'Some of the demos will not use images as much as they could.' + warn2 'You should consider installing GDK-Pixbuf and re-running' + warn2 'configure. (GDK-Pixbuf is recommended over XPM, as it' + warn2 'provides support for more image formats.)' +fi + + +if test "$have_jpeg" = no ; then + if test "$with_jpeg_req" = yes ; then + warnL 'Use of libjpeg was requested, but it was not found.' + elif test "$with_jpeg_req" = no ; then + noteL 'The JPEG library is not being used.' + else + noteL 'The JPEG library was not found.' + fi + + if test "$jpeg_halfassed" = yes ; then + echo '' + warn2 'More specifically, we found the headers, but not the' + warn2 'library; so either JPEG is half-installed on this' + warn2 "system, or something else went wrong. The \`config.log'" + warn2 'file might contain some clues.' + echo '' + fi + + if test "$have_gdk_pixbuf" = no ; then + warn2 "This means that it won't be possible for the image-manipulating" + warn2 "display modes to load files from disk; and it also means that" + warn2 "the \`webcollage' program will be much slower." + else + warn2 "This means the \`webcollage' program will be much slower." + fi +fi + + +if test "$have_gl" = yes -a "$ac_have_mesa_gl" = yes ; then + preferred_mesagl=3.4 + mgv="$ac_mesagl_version_string" + pgl="$preferred_mesagl" + + if test "$ac_mesagl_version" = unknown; then + true + # warnL "Unable to determine the MesaGL version number!" + # warn2 "Make sure you are using version $preferred_mesagl or newer." + + elif test \! "$ac_mesagl_version" -gt 2006; then + warnL "MesaGL version number is $mgv --" + warn2 "MesaGL 2.6 and earlier have a security bug. It is strongly" + warn2 "recommended that you upgrade to at least version $preferred_mesagl." + + elif test \! "$ac_mesagl_version" -gt 3003; then + warnL "MesaGL version number is $mgv --" + warn2 "MesaGL 3.3 and earlier have some bugs; it is recommended" + warn2 "that you upgrade to $pgl or newer." + fi +fi + +if test "$have_gl" = no ; then + if test "$with_gl_req" = yes ; then + warnL 'Use of GL was requested, but it was not found.' + elif test "$with_gl_req" = no ; then + noteL 'The OpenGL 3D library is not being used.' + else + noteL 'The OpenGL 3D library was not found.' + fi + + if test "$gl_halfassed" = yes ; then + echo '' + warn2 'More specifically, we found the headers, but not the' + warn2 'libraries; so either GL is half-installed on this' + warn2 "system, or something else went wrong. The \`config.log'" + warn2 'file might contain some clues.' + fi + + echo '' + warn2 'Those demos which use 3D will not be built or installed.' + warn2 'You might want to consider installing OpenGL and' + warn2 "re-running configure. If your vendor doesn't ship" + warn2 'their own implementation of OpenGL, you can get a free' + warn2 'version at . For general OpenGL' + warn2 'info, see .' + +fi + + +if test "$have_gl" = yes -a "$have_gle" = no ; then + + # nobody cares about this; don't print the warning unless it was + # requested and not found, or halfway-found. + if test "$with_gle_req" = yes -o "$gle_halfassed" = yes ; then + + if test "$with_gle_req" = yes ; then + noteL 'Use of the GLE (GL Extrusion) library was requested, but' + warn2 'it was not found (though the OpenGL library was found, and' + warn2 'is being used.)' + elif test "$with_gle_req" = no ; then + noteL 'The OpenGL Library is being used, but the GLE (GL Extrusion)' + warn2 'library is not.' + else + noteL 'The OpenGL Library was found, but the GLE (GL Extrusion)' + warn2 'was not.' + fi + + if test "$gle_halfassed" = yes ; then + echo '' + warn2 'More specifically, we found the headers, but not the' + warn2 'libraries; so either GLE is half-installed on this' + warn2 "system, or something else went wrong. The \`config.log'" + warn2 'file might contain some clues.' + fi + + echo '' + warn2 'Some of the OpenGL (3D) demos (those that depend on GLE)' + warn2 'will not be built or installed. You might want to consider' + warn2 'installing GLE and re-running configure. You can find the' + warn2 'GLE library at . For general' + warn2 'OpenGL info, see .' + + fi +fi + + +if test "$with_readdisplay_req" = yes -a "$have_readdisplay" = no ; then + warn 'Use of XReadDisplay was requested, but it was not found.' +fi + +if test "$with_kerberos_req" = yes -a "$have_kerberos" = no ; then + warn 'Use of Kerberos was requested, but it was not found.' +fi + +if test "$with_pam_req" = yes -a "$have_pam" = no ; then + warn 'Use of PAM was requested, but it was not found.' +fi + +if test "$with_shadow_req" = yes -a "$have_shadow" = no ; then + warn 'Use of shadow passwords was requested, but they were not found.' +fi + +if test "$ac_macosx" = yes ; then + if test "$enable_locking" = yes ; then + warn "You have specified --enable-locking on MacOS X." + warn2 "THIS DOES NOT WORK! Don't do this!" + fi +fi + + +# You are in a twisty maze of namespaces and syntaxes, all alike. +# Fuck the skull of Unix. +# +bindir=`eval eval eval eval eval eval eval echo $bindir` +HACKDIR=`eval eval eval eval eval eval eval echo $HACKDIR` +HACK_CONF_DIR=`eval eval eval eval eval eval eval echo $HACK_CONF_DIR` + +# canonicalize slashes. +bindir=`echo "${bindir}" | sed 's@/$@@;s@//*@/@g'` +HACKDIR=`echo "${HACKDIR}" | sed 's@/$@@;s@//*@/@g'` +HACK_CONF_DIR=`echo "${HACK_CONF_DIR}" | sed 's@/$@@;s@//*@/@g'` + + +# Sanity check the hackdir +for bad_choice in xscreensaver xscreensaver-demo xscreensaver-command ; do + if test "${HACKDIR}" = "${bindir}/${bad_choice}" ; then + echo "" + { { $as_echo "$as_me:$LINENO: error: \"--with-hackdir=${bindir}/${bad_choice}\" won't work. + There will be an executable installed with that name, so + that can't be the name of a directory as well. Please + re-configure with a different directory name." >&5 +$as_echo "$as_me: error: \"--with-hackdir=${bindir}/${bad_choice}\" won't work. + There will be an executable installed with that name, so + that can't be the name of a directory as well. Please + re-configure with a different directory name." >&2;} + { (exit 1); exit 1; }; } + fi +done + + +do_dir_warning=no + +# Now let's warn if there's a previous RPM version already installed. +# But don't bother with this test if we are currently *building* an RPM. + +if test -z "$RPM_PACKAGE_VERSION" ; then + + rpmnames="xscreensaver xscreensaver-base xscreensaver-extras" + + # M4 sucks!! + + rpmv=`(rpm -qv $rpmnames) 2>/dev/null | \ + sed -n 's/^[-a-z]*-\([0-9][0-9]*[.][0-9][0-9a-z]*\)-.*$/\1/p' | \ + head -1` + + + if test \! -z "$rpmv" ; then + rpmbdir=`rpm -ql $rpmnames | sed -n 's@^\(.*\)/xscreensaver-demo$@\1@p'` + rpmhdir=`rpm -ql $rpmnames | sed -n 's@^\(.*\)/popsquares$@\1@p'` + + warning=no + warnL "There is already an installed RPM of xscreensaver $rpmv" + warn2 'on this system. You might want to remove it ("rpm -ve")' + warn2 'before running "make install" in this directory.' + echo "" + warn2 "Alternately, you could build this version of xscreensaver" + warn2 'as an RPM, and then install that. An "xscreensaver.spec"' + warn2 'file is included. Try "rpmbuild -v -ba xscreensaver.spec".' + warn2 "See the RPM documentation for more info." + echo "" + + if test "$rpmbdir" = "$rpmhdir" ; then + warn2 "The RPM version was installed in $rpmbdir/." + do_dir_warning=yes + else + warn2 "The RPM version was installed in $rpmbdir/," + warn2 "with demos in $rpmhdir/." + fi + fi +fi + +# Also warn if there's a Debian package installed. +# +debnames="xscreensaver xscreensaver-data xscreensaver-data-extra" +debv='' +for dpkg in $debnames ; do + if test -z "$debv"; then + debv=`dpkg -s $dpkg 2>/dev/null | sed -n 's/^Version: \(.*\)$/\1/p'` + fi +done + +if test \! -z "$debv" ; then + debbdir=`dpkg -L $debnames 2>/dev/null | \ + sed -n 's@^\(.*/bin/\)xscreensaver$@\1@p'` + debhdir=`dpkg -L $debnames 2>/dev/null | \ + sed -n 's@^\(.*/\)popsquares$@\1@p'` + if test -z "$debbdir" ; then debbdir='???'; fi + if test -z "$debhdir" ; then debhdir='???'; fi + + warning=no + warnL "There is already an installed dpkg of xscreensaver" + warn2 "version \"$debv\" on this system." + echo "" + warn2 "The dpkg was installed in $debbdir," + warn2 "with demos in $debhdir." +fi + + +if test "${bindir}" = "${HACKDIR}" ; then + do_dir_warning=yes +fi + +if test "$do_dir_warning" = yes; then + echo "" + echo "$warnsep" + echo "" + echo ' When you run "make install", the "xscreensaver",' + echo ' "xscreensaver-demo", and "xscreensaver-command" executables' + echo " will be installed in ${bindir}/." + echo "" + echo " The various graphics demos (190+ different executables) will" + echo " be installed in ${HACKDIR}/." + echo "" + echo " If you would prefer the demos to be installed elsewhere," + echo " you should re-run configure with the --with-hackdir=DIR" + echo " option. For more information, run \`./configure --help'." + warning=yes +fi + +if test "$warning" != no; then + echo '' ; echo "$warnsep" ; echo '' +fi + +if test "$do_dir_warning" = no; then + if test "$warning" = no; then + echo '' + fi + echo "User programs will be installed in ${bindir}/" + echo "Screen savers will be installed in ${HACKDIR}/" + echo "Configuration dialogs will be installed in ${HACK_CONF_DIR}/" + echo "System-wide default settings will be installed in ${APPDEFAULTS}/" + echo '' +fi diff --git a/configure.in b/configure.in new file mode 100644 index 00000000..11ba5c19 --- /dev/null +++ b/configure.in @@ -0,0 +1,4464 @@ +# configure.in --- xscreensaver, Copyright (c) 1997-2005 Jamie Zawinski. +# + +AC_PREREQ(2.52) +AC_INIT(driver/subprocs.c) +AC_CONFIG_HEADER(config.h) + +echo "current directory: `pwd`" +echo "command line was: $0 $@" + +############################################################################### +# +# Autoheader stuff +# +############################################################################### + +AH_TOP([ +/* config.h.in --- xscreensaver, Copyright (c) 1998-2000 Jamie Zawinski. + * + * The best way to set these parameters is by running the included `configure' + * script. That examines your system, and generates `config.h' from + * `config.h.in'. + * + * If something goes very wrong, you can edit `config.h' directly, but beware + * that your changes will be lost if you ever run `configure' again. + */ +]) + +AH_TEMPLATE([HAVE_READ_DISPLAY_EXTENSION], + [Define this if you have the XReadDisplay extension (I think + this is an SGI-only thing; it's in + .) A few of the screenhacks will + take advantage of this if it's available.]) + +AH_TEMPLATE([HAVE_XHPDISABLERESET], + [Define this if you have the XHPDisableReset function (an HP only + thing which allows the Ctrl-Sh-Reset key sequence to be + temporarily disabled.)]) + +# This only ever existed in X11R4 and X11R5. +#AH_TEMPLATE([HAVE_XIDLE_EXTENSION], +# [Define this if you have the XIDLE extension installed. If you +# have the XIDLE extension, this is recommended. (You have this +# extension if the file /usr/include/X11/extensions/xidle.h +# exists.) Turning on this flag lets XScreenSaver work better with +# servers which support this extension; but it will still work +# with servers which do not suport it, so it's a good idea to +# compile in support for it if you can.]) + +# Using this extension will crash your X server and make fading not work. +#AH_TEMPLATE([HAVE_MIT_SAVER_EXTENSION], +# [Define this if you have the MIT-SCREEN-SAVER extension +# installed. See the caveats about this extension, above. +# (It's available if /usr/include/X11/extensions/scrnsaver.h +# exists.)]) + +# This only ever existed on SGI hardware. +#AH_TEMPLATE([HAVE_SGI_SAVER_EXTENSION], +# [Define this if you have the SGI SCREEN_SAVER extension. This is +# standard on Irix systems, and not available elsewhere.]) + +# This only ever existed on SGI hardware. +#AH_TEMPLATE([HAVE_SGI_VC_EXTENSION], +# [Define this if you have the SGI-VIDEO-CONTROL extension. This +# is standard on Irix systems, and not available elsewhere.]) + +AH_TEMPLATE([HAVE_DPMS_EXTENSION], + [Define this if you have the XDPMS extension. This is standard + on sufficiently-recent XFree86 systems, and possibly elsewhere. + (It's available if the file /usr/include/X11/extensions/dpms.h + exists.)]) + +AH_TEMPLATE([HAVE_XF86VMODE], + [Define this if you have the functions XF86VidModeGetModeLine() + and XF86VidModeGetViewPort(), in support of virtual desktops + where the X server's root window is bigger than the actual + screen. This is an XFree86 thing, and probably doesn't exist + elsewhere. (It's available if the file + /usr/include/X11/extensions/xf86vmode.h exists.)]) + +AH_TEMPLATE([HAVE_XF86VMODE_GAMMA], + [Define this if you have the functions XF86VidModeGetGamma() and + XF86VidModeSetGamma(), which allow clients to change the gamma + response of the monitor. This is an XFree86 4.0.x thing, and + probably doesn't exist elsewhere. (It's available if the file + /usr/include/X11/extensions/xf86vmode.h exists and has stuff about + gamma in it.)]) + +AH_TEMPLATE([HAVE_XF86VMODE_GAMMA_RAMP], + [Define this if you have the functions XF86VidModeGetGammaRamp() + and XF86VidModeSetGammaRamp(), which provide finer-grained + control than XF86VidMode[GS]etGamma(). These appeared in + XFree86 4.1.0.]) + +AH_TEMPLATE([HAVE_XINERAMA], + [Define this if you have the Xinerama extension. This is + standard on sufficiently-recent XFree86 systems, and possibly + elsewhere. (It's available if the file + /usr/include/X11/extensions/Xinerama.h exists.)]) + +AH_TEMPLATE([HAVE_XINPUT], + [Define this if you have the Xinput extension. This is + standard since X11R5, and is thus almost everywhere. + (It's available if the file /usr/include/X11/extensions/XInput.h + exists.)]) + +AH_TEMPLATE([HAVE_XF86MISCSETGRABKEYSSTATE], + [Define this if you have the XF86MiscSetGrabKeysState function + (which allows the Ctrl-Alt-KP_star and Ctrl-Alt-KP_slash key + sequences to be temporarily disabled. Sadly, it doesn't affect + Ctrl-Alt-BS or Ctrl-Alt-F1.)]) + +AH_TEMPLATE([HAVE_RANDR], + [Define this if you have the Resize and Rotate extension. + This is standard on sufficiently-recent XFree86 systems, and + possibly elsewhere. (It's available if the file + /usr/include/X11/extensions/Xrandr.h exists.)]) + +AH_TEMPLATE([HAVE_RANDR_12], + [Define this if the RANDR library is version 1.2 or newer.]) + +AH_TEMPLATE([HAVE_PROC_INTERRUPTS], + [Define this if you have a Linux-like /proc/interrupts file which + can be examined to determine when keyboard activity has + occurred.]) + +AH_TEMPLATE([HAVE_MOTIF],[Define this if you have Motif.]) + +AH_TEMPLATE([HAVE_XMCOMBOBOX], + [Define this if you have the XmComboBox Motif widget (Motif 2.0.)]) + +AH_TEMPLATE([HAVE_GTK],[Define this if you have Gtk (any version.)]) +AH_TEMPLATE([HAVE_GTK2],[Define this if you have Gtk 2.x.]) + +AH_TEMPLATE([HAVE_CRAPPLET], + [Define this if you have Gnome and want to build support for the + xscreensaver control panel in the Gnome Control Center + (gnomecc). (This is needed only with Gtk 1.x.)]) + +AH_TEMPLATE([HAVE_CRAPPLET_IMMEDIATE], + [Define this if HAVE_CRAPPLET is defined, and the function + capplet_widget_changes_are_immediate() is available.]) + +AH_TEMPLATE([HAVE_XML],[Define this if you have the XML library.]) + +AH_TEMPLATE([HAVE_OLD_XML_HEADERS], + [Define this if you have the XML library headers in their old, + non-namespaced location (you lack the gnome-xml/libxml symlink)]) + +AH_TEMPLATE([HAVE_XPM], + [Define this if you have the XPM library installed. Some of the + demos can make use of this if it is available.]) + +AH_TEMPLATE([HAVE_GDK_PIXBUF], + [Define this if you have the GDK_Pixbuf library installed. Some + of the demos can make use of this if it is available.]) + +AH_TEMPLATE([HAVE_GDK_PIXBUF_APPLY_EMBEDDED_ORIENTATION], + [Define this if you have the gdk_pixbuf_apply_embedded_orientation + function (gdk-pixbuf 2.12).]) + +AH_TEMPLATE([HAVE_JPEGLIB], + [Define this if you have the Independent JPEG Group's JPEG + library installed. Some of the demos can make use of this if it + is available.]) + +AH_TEMPLATE([HAVE_XMU], + [Define this if you have the Xmu library. This is standard part + of X, and if your vendor doesn't ship it, you should report that + as a bug.]) + +AH_TEMPLATE([HAVE_GL], + [Define this if you have OpenGL. Some of the demos require it, + so if you don't have it, then those particular demos won't be + built. (This won't affect the screen saver as a whole.)]) + +AH_TEMPLATE([HAVE_MESA_GL], + [Define this if you have OpenGL, but it's the MesaGL variant. + (The libraries have different names.) (HAVE_GL should be defined + too.)]) + +AH_TEMPLATE([HAVE_GLBINDTEXTURE], + [Define this if your version of OpenGL has the glBindTexture() + routine. This is the case for OpenGL 1.1, but not for OpenGL + 1.0.]) + +AH_TEMPLATE([HAVE_GLE], + [Define this if you have the -lgle and -lmatrix libraries (GL + extrusion.)]) + +AH_TEMPLATE([HAVE_GLE3],[Define this if you have the -lgle from GLE version 3]) + +AH_TEMPLATE([HAVE_JWZGLES],[Define this to target the OpenGL ES 1.x API + instead of OpenGL 1.3.]) + +AH_TEMPLATE([HAVE_GLBITMAP],[Define this if glBitmap exists.]) + +AH_TEMPLATE([HAVE_XSHM_EXTENSION], + [Define this if you have the X Shared Memory Extension.]) + +AH_TEMPLATE([HAVE_DOUBLE_BUFFER_EXTENSION], + [Define this if you have the X Double Buffer Extension.]) + +AH_TEMPLATE([FORTUNE_PROGRAM], + [Some screenhacks like to run an external program to generate + random pieces of text; set this to the one you like. Note that + this is just the default; X resources can be used to override + it.]) + +AH_TEMPLATE([PASSWD_HELPER_PROGRAM], + [Set the name of the password helper program, if any]) + +AH_TEMPLATE([NO_LOCKING], + [Define this to remove the option of locking the screen at all.]) + +AH_TEMPLATE([ALLOW_ROOT_PASSWD], + [Define this to allow the root password to unlock the screen.]) + +AH_TEMPLATE([HAVE_KERBEROS], + [Define this if you want to use Kerberos authentication to + lock/unlock the screen instead of your local password. This + currently uses Kerberos V4, but a V5 server with V4 + compatibility will work. WARNING: DO NOT USE AFS string-to-key + passwords with this option. This option currently *only* works + with standard Kerberos des_string_to_key. If your password is + an AFS password and not a kerberos password, it will not + authenticate properly. See the comments in driver/kpasswd.c for + more information if you need it.]) + +AH_TEMPLATE([HAVE_KERBEROS5], + [Define this if you have Kerberos 5, meaning we need to use the + Kerberos 4 compatibility layer.]) + +AH_TEMPLATE([HAVE_PAM], + [Define this if you want to use PAM (Pluggable Authentication + Modules) to lock/unlock the screen, instead of standard + /etc/passwd authentication.]) + +AH_TEMPLATE([PAM_SERVICE_NAME], + [If PAM is being used, this is the name of the PAM service that + xscreensaver will authenticate as. The default is + "xscreensaver", which means that the PAM library will look for + an "xscreensaver" line in /etc/pam.conf, or (on recent Linux + systems) will look for a file called /etc/pam.d/xscreensaver. + Some systems might already have a PAM installation that is + configured for xlock, so setting this to "xlock" would also work + in that case.]) + +AH_TEMPLATE([HAVE_PAM_FAIL_DELAY], + [Define this if you have pam_fail_delay function. + see driver/passwd-pam.c.]) + +AH_TEMPLATE([PAM_CHECK_ACCOUNT_TYPE], + [Whether PAM should check the result of account modules + when authenticating. Only do this if you have account + configured properly on your system.]) + +AH_TEMPLATE([PAM_STRERROR_TWO_ARGS], + [Define if you have PAM and pam_strerror() requires two + arguments.]) + +AH_TEMPLATE([HAVE_SIGTIMEDWAIT], + [Define to 1 if you have the `sigtimedwait' function.]) + +AH_TEMPLATE([HAVE_SHADOW_PASSWD], + [Define this if your system uses 'shadow' passwords, that is, the + passwords live in /etc/shadow instead of /etc/passwd, and one + reads them with getspnam() instead of getpwnam(). (Note that + SCO systems do some random other thing; others might as well. + See the ifdefs in driver/passwd-pwent.c if you're having trouble + related to reading passwords.)]) + +AH_TEMPLATE([HAVE_ENHANCED_PASSWD], + [Define this if your system is Digital or SCO Unix with so-called + ``Enhanced Security'', that is, the passwords live in + /tcb/files/auth// instead of in /etc/passwd, and one + reads them with getprpwnam() instead of getpwnam().]) + +AH_TEMPLATE([HAVE_ADJUNCT_PASSWD], + [Define this if your system is Solaris with ``adjunct'' passwords + (this is the version where one gets at the passwords with + getpwanam() instead of getpwnam().) I haven't tested this one, + let me know if it works.]) + +AH_TEMPLATE([HAVE_HPUX_PASSWD], + [Define this if you are running HPUX with so-called ``Secure + Passwords'' (if you have /usr/include/hpsecurity.h, you probably + have this.) I haven't tested this one, let me know if it works.]) + +AH_TEMPLATE([HAVE_SYSLOG], + [Define this if you the openlog(), syslog(), and closelog() + functions. This is used for logging failed login attempts.]) + +AH_TEMPLATE([HAVE_ICMP], + [Define this if you do pings with a `struct icmp' and an + `icmp_id' slot.]) + +AH_TEMPLATE([HAVE_ICMPHDR], + [Define this if you do pings with a `struct icmphdr' and an + `un.echo.id' slot.]) + +AH_TEMPLATE([HAVE_GETIFADDRS], + [Define this if you have the getifaddrs() function.]) + +AH_TEMPLATE([HAVE_FORKPTY], + [Define this if you have the 'forkpty' function: + This allows 'phosphor' and 'apple2' to run curses-based + programs, or be used as terminal windows.]) + +AH_TEMPLATE([HAVE_GETTIMEOFDAY], + [Define this if you have the gettimeofday function.]) + +AH_TEMPLATE([GETTIMEOFDAY_TWO_ARGS], + [Define this if gettimeofday() takes two arguments.]) + +AH_TEMPLATE([XPointer], + [Define this to void* if you're using X11R4 or earlier.]) + +# After checking to see that --srcdir is correct (which AC_INIT does) +# check for some random other files that come later in the tar file, +# to make sure everything is here. +# +for d in driver utils hacks hacks/glx ; do + f=$srcdir/$d/Makefile.in + if test \! -r $f ; then + echo "" + echo "ERROR: The package is incomplete: $f does not exist." + echo " This probably means that your download was truncated." + echo "" + exit 1 + fi +done + +############################################################################### +# +# Function to figure out how to run the compiler. +# +############################################################################### + +AC_DEFUN(AC_PROG_CC_ANSI, + [AC_PROG_CC + + if test -z "$GCC"; then + # not using GCC + AC_MSG_CHECKING(how to request ANSI compilation) + case "$host" in + *-hpux* ) + AC_MSG_RESULT(HPUX: adding -Ae) + CC="$CC -Ae" + ;; + *-aix* ) + AC_MSG_RESULT(AIX: adding -qlanglvl=ansi -qhalt=e) + CC="$CC -qlanglvl=ansi -qhalt=e" + ;; + *-dec-* ) + AC_MSG_RESULT(DEC: adding -std1 -ieee) + CC="$CC -std1" + ;; + *) + AC_MSG_RESULT(no idea) + ;; + esac + else + # using GCC + case "$host" in + *-solaris*) + AC_MSG_RESULT(Solaris: adding -D__EXTENSIONS__) + CC="$CC -D__EXTENSIONS__" + ;; + esac + fi + + OBJCC="$CC" + + AC_MSG_CHECKING([whether the compiler works on ANSI C]) + AC_TRY_RUN([ main(int ac, char **av) { return 0; } ], + AC_MSG_RESULT(yes), + AC_MSG_RESULT(no) + AC_MSG_ERROR(Couldn't build even a trivial ANSI C program: check CC.), + AC_MSG_ERROR(Couldn't build even a trivial ANSI C program: check CC.)) + + if test -n "$GCC"; then + AC_MSG_RESULT(Turning on gcc compiler warnings.) + CC="$CC -pedantic -Wall -Wstrict-prototypes -Wnested-externs -Wmissing-prototypes" + OBJCC="$OBJCC -Wall" + # As of gcc 3.4, we have "-Wdeclaration-after-statement" + # and so perhaps now we can do without -pedantic? + else + case "$host" in + *-irix5* |*-irix6.[0-3]* ) + AC_MSG_RESULT(Turning on SGI compiler warnings.) + CC="$CC -fullwarn -use_readonly_const -rdata_shared -g3" + ;; +# *-dec-osf* ) +# if test -z "$GCC"; then +# AC_MSG_RESULT(Turning on DEC C compiler warnings.) +# CC="$CC -migrate -w0 -verbose -warnprotos" +# fi +# ;; + esac + fi +]) + + +############################################################################### +# +# Check for availability of various gcc command-line options. +# +############################################################################### + +AC_DEFUN(AC_CHECK_GCC_ARG, + [if test -n "$GCC"; then + AC_CACHE_CHECK([whether gcc accepts [$2]], + ac_cv_gcc_accepts_[$1], + [rm -rf conftest.$ac_ext + touch conftest.$ac_ext + if ( ( gcc -c [$2] conftest.$ac_ext -o/dev/null >/dev/null ) 2>&1 | \ + grep unrecognized >/dev/null ); then + ac_cv_gcc_accepts_[$1]=no + else + ac_cv_gcc_accepts_[$1]=yes + CC="$CC [$2]" + fi]) + ac_gcc_accepts_[$1]="$ac_cv_gcc_accepts_[$1]" + fi +]) + +AC_DEFUN(AC_NO_LONG_STRING_WARNINGS, + [AC_CHECK_GCC_ARG(no_overlength, -Wno-overlength-strings)]) + +AC_DEFUN(AC_NO_MISPLACED_DECLARATIONS, + [AC_CHECK_GCC_ARG(no_decl_after, -Wdeclaration-after-statement)]) + +# Need to disable Objective C extensions in ANSI C on MacOS X to work +# around an Apple-specific gcc bug. +# +AC_DEFUN(AC_NO_OBJECTIVE_C, + [AC_CHECK_GCC_ARG(no_cpp_precomp, -no-cpp-precomp)]) + +############################################################################### +# +# Function to figure out how to disable // comments in ANSI C code. +# +# (With recent gcc, this is done with "-std=c89". With older gcc, this +# is done by passing "-lang-c89" to cpp, by passing "-Wp,-lang-c89" to +# gcc. Old gcc doesn't support -std, and new gcc doesn't support -lang. +# so much for compatibility!) +# +# UPDATE: apparently there is NO WAY to tell gcc 3.2.2 to require that +# declarations preceed statements, without resorting to "-pedantic". +# This means that there is no way to get gcc3 to issue warnings that +# ensure that your code complies with the ANSI/ISO C89 standard, without +# also drowning in totally useless warnings. Thank you master may I +# have another. +# +# So, I give up, let's just use -pedantic. +# +############################################################################### + +AC_DEFUN(AC_GCC_ACCEPTS_STD, [ + case "$host" in + *-darwin* ) + # Fucking Apple let // comments sneak into OpenGL headers, so + # we *must* allow // comments when compiling on Mac OS 10.6! FUCK! + ;; + *) + AC_CHECK_GCC_ARG(std, -std=c89) + ;; + esac +]) + +AC_DEFUN(AC_NO_CPLUSPLUS_COMMENTS_IN_C_CODE, + [if test -n "$GCC"; then + AC_GCC_ACCEPTS_STD + AC_MSG_RESULT(Disabling C++ comments in ANSI C code.) + # + # The reason that // comments are banned from xscreensaver is that gcc is + # basically the only compiler in the world that supports them in C code. + # All other vendors support them only in their C++ compilers, not in their + # ANSI C compilers. This means that it's a portability problem: every time + # these comments have snuck into the xscreensaver source code, I've gotten + # complaints about it the next day. So we turn off support for them in gcc + # as well to prevent them from accidentially slipping in. + # + if test "$ac_gcc_accepts_std" = yes ; then + # + # -std=c89 defines __STRICT_ANSI__, which we don't want. + # (That appears to be the only additional preprocessor symbol + # it defines, in addition to the syntax changes it makes.) + # + # -std=gnu89 is no good, because // comments were a GNU extension + # before they were in the ANSI C 99 spec... (gcc 2.96 permits // + # with -std=gnu89 but not with -std=c89.) + # + # $CC already contains "-std=c89" via AC_GCC_ACCEPTS_STD + CC="$CC -U__STRICT_ANSI__" +# else +# # The old way: +# CC="$CC -Wp,-lang-c89" + fi + fi +]) + + +############################################################################### +# +# Function to figure out how to create directory trees. +# +############################################################################### + +AC_DEFUN(AC_PROG_INSTALL_DIRS, + [AC_CACHE_CHECK([whether "\${INSTALL} -d" creates intermediate directories], + ac_cv_install_d_creates_dirs, + [ac_cv_install_d_creates_dirs=no + rm -rf conftestdir + if mkdir conftestdir; then + cd conftestdir 2>/dev/null + ${INSTALL} -d `pwd`/dir1/dir2 >/dev/null 2>&1 + if test -d dir1/dir2/. ; then + ac_cv_install_d_creates_dirs=yes + fi + cd .. 2>/dev/null + rm -rf conftestdir + fi + ]) + + if test "$ac_cv_install_d_creates_dirs" = no ; then + AC_CACHE_CHECK([whether "mkdir -p" creates intermediate directories], + ac_cv_mkdir_p_creates_dirs, + [ac_cv_mkdir_p_creates_dirs=no + rm -rf conftestdir + if mkdir conftestdir; then + cd conftestdir 2>/dev/null + mkdir -p dir1/dir2 >/dev/null 2>&1 + if test -d dir1/dir2/. ; then + ac_cv_mkdir_p_creates_dirs=yes + fi + cd .. 2>/dev/null + rm -rf conftestdir + fi + ]) + fi + + if test "$ac_cv_install_d_creates_dirs" = yes ; then + INSTALL_DIRS='${INSTALL} -d' + elif test "$ac_cv_mkdir_p_creates_dirs" = yes ; then + INSTALL_DIRS='mkdir -p' + else + # any other ideas? + INSTALL_DIRS='${INSTALL} -d' + fi +]) + + +############################################################################### +# +# Function to check whether gettimeofday() exists, and how to call it. +# This may define HAVE_GETTIMEOFDAY and GETTIMEOFDAY_TWO_ARGS. +# +############################################################################### + +AC_DEFUN(AC_GETTIMEOFDAY_ARGS, + [AC_MSG_CHECKING(how to call gettimeofday) + AC_CACHE_VAL(ac_cv_gettimeofday_args, + [AC_TRY_COMPILE([#include + #include ], + [struct timeval tv; struct timezone tzp; + gettimeofday(&tv, &tzp);], + [ac_gettimeofday_args=2], + [AC_TRY_COMPILE([#include + #include ], + [struct timeval tv; gettimeofday(&tv);], + [ac_gettimeofday_args=1], + [ac_gettimeofday_args=0])]) + ac_cv_gettimeofday_args=$ac_gettimeofday_args]) + ac_gettimeofday_args=$ac_cv_gettimeofday_args + if test "$ac_gettimeofday_args" = 1 ; then + AC_DEFINE(HAVE_GETTIMEOFDAY) + AC_MSG_RESULT(one argument) + elif test "$ac_gettimeofday_args" = 2 ; then + AC_DEFINE(HAVE_GETTIMEOFDAY) + AC_DEFINE(GETTIMEOFDAY_TWO_ARGS) + AC_MSG_RESULT(two arguments) + else + AC_MSG_RESULT(unknown) + fi +]) + + +############################################################################### +# +# Function to find perl5 (defines PERL and PERL_VERSION.) +# +############################################################################### + +# M4 sucks!! perl sucks too!! +changequote(X,Y) +perl_version_cmd='print $]' +changequote([,]) + +AC_DEFUN(AC_PROG_PERL, + [AC_PATH_PROGS(PERL, [perl5 perl],,) + if test -z "$PERL" ; then + PERL_VERSION=0 + else + AC_CACHE_CHECK([perl version], ac_cv_perl_version, + [ac_cv_perl_version=`$PERL -e "$perl_version_cmd"`]) + PERL_VERSION=$ac_cv_perl_version + fi + ]) + + +############################################################################### +# +# Function to demand "bc". Losers. +# +############################################################################### + +AC_DEFUN(AC_DEMAND_BC, + [ac_bc_result=`echo 6+9 | bc 2>/dev/null` + AC_MSG_CHECKING([for bc]) + if test "$ac_bc_result" = "15" ; then + AC_MSG_RESULT(yes) + else + AC_MSG_RESULT(no) + echo '' + AC_MSG_ERROR([Your system doesn't have \"bc\", which has been a standard + part of Unix since the 1970s. Come back when your vendor + has grown a clue.]) + fi + ]) + +############################################################################### +# +# Functions to check how to do ICMP PING requests. +# +############################################################################### + +AC_DEFUN(AC_CHECK_ICMP, + [AC_CACHE_CHECK([for struct icmp], ac_cv_have_icmp, + [AC_TRY_COMPILE([#include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include ], + [struct icmp i; + struct sockaddr s; + struct sockaddr_in si; + struct ip ip; + i.icmp_type = ICMP_ECHO; + i.icmp_code = 0; + i.icmp_cksum = 0; + i.icmp_id = 0; + i.icmp_seq = 0; + si.sin_family = AF_INET; + #if defined(__DECC) || defined(_IP_VHL) + ip.ip_vhl = 0; + #else + ip.ip_hl = 0; + #endif + ], + [ac_cv_have_icmp=yes], + [ac_cv_have_icmp=no])]) + if test "$ac_cv_have_icmp" = yes ; then + AC_DEFINE(HAVE_ICMP) + fi]) + +AC_DEFUN(AC_CHECK_ICMPHDR, + [AC_CACHE_CHECK([for struct icmphdr], ac_cv_have_icmphdr, + [AC_TRY_COMPILE([#include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include ], + [struct icmphdr i; + struct sockaddr s; + struct sockaddr_in si; + struct ip ip; + i.type = ICMP_ECHO; + i.code = 0; + i.checksum = 0; + i.un.echo.id = 0; + i.un.echo.sequence = 0; + si.sin_family = AF_INET; + ip.ip_hl = 0;], + [ac_cv_have_icmphdr=yes], + [ac_cv_have_icmphdr=no])]) + if test "$ac_cv_have_icmphdr" = yes ; then + AC_DEFINE(HAVE_ICMPHDR) + fi]) + + +############################################################################### +# +# Functions to check for various X11 crap. +# +############################################################################### + +# Try and find the app-defaults directory. +# It sucks that autoconf doesn't do this already... +# +AC_DEFUN(AC_PATH_X_APP_DEFAULTS_XMKMF,[ + rm -fr conftestdir + if mkdir conftestdir; then + cd conftestdir 2>/dev/null + # Make sure to not put "make" in the Imakefile rules, since we grep it out. + cat > Imakefile <<'EOF' +acfindx: + @echo 'ac_x_app_defaults="${XAPPLOADDIR}"' +EOF + if (xmkmf) >/dev/null 2>&1 && test -f Makefile; then + # GNU make sometimes prints "make[1]: Entering...", which'd confuse us. + eval `${MAKE-make} acfindx 2>/dev/null | grep -v make` + fi + cd .. 2>/dev/null + rm -fr conftestdir + fi]) + +############################################################################### +# +# Handle the --with-x-app-defaults option HERE +# +############################################################################### + +AC_ARG_WITH(x-app-defaults,[], + [ac_cv_x_app_defaults="$withval"], + [eval ac_x_app_defaults="$withval"]) + + +AC_DEFUN(AC_PATH_X_APP_DEFAULTS_DIRECT,[ + # Look for the directory under a standard set of common directories. + # Check X11 before X11Rn because it's often a symlink to the current release. + for ac_dir in \ + /usr/X11/lib/app-defaults \ + /usr/X11R6/lib/app-defaults \ + /usr/X11R6/lib/X11/app-defaults \ + /usr/X11R5/lib/app-defaults \ + /usr/X11R5/lib/X11/app-defaults \ + /usr/X11R4/lib/app-defaults \ + /usr/X11R4/lib/X11/app-defaults \ + \ + /usr/lib/X11/app-defaults \ + /usr/lib/X11R6/app-defaults \ + /usr/lib/X11R5/app-defaults \ + /usr/lib/X11R4/app-defaults \ + \ + /usr/local/X11/lib/app-defaults \ + /usr/local/X11R6/lib/app-defaults \ + /usr/local/X11R5/lib/app-defaults \ + /usr/local/X11R4/lib/app-defaults \ + \ + /usr/local/lib/X11/app-defaults \ + /usr/local/lib/X11R6/app-defaults \ + /usr/local/lib/X11R6/X11/app-defaults \ + /usr/local/lib/X11R5/app-defaults \ + /usr/local/lib/X11R5/X11/app-defaults \ + /usr/local/lib/X11R4/app-defaults \ + /usr/local/lib/X11R4/X11/app-defaults \ + \ + /usr/X386/lib/X11/app-defaults \ + /usr/x386/lib/X11/app-defaults \ + /usr/XFree86/lib/X11/app-defaults \ + \ + /usr/lib/X11/app-defaults \ + /usr/local/lib/X11/app-defaults \ + /usr/unsupported/lib/X11/app-defaults \ + /usr/athena/lib/X11/app-defaults \ + /usr/local/x11r5/lib/X11/app-defaults \ + /usr/lpp/Xamples/lib/X11/app-defaults \ + /lib/usr/lib/X11/app-defaults \ + \ + /usr/openwin/lib/app-defaults \ + /usr/openwin/lib/X11/app-defaults \ + /usr/openwin/share/lib/app-defaults \ + /usr/openwin/share/lib/X11/app-defaults \ + \ + /X11R6/lib/app-defaults \ + /X11R5/lib/app-defaults \ + /X11R4/lib/app-defaults \ + ; \ + do + if test -d "$ac_dir"; then + ac_x_app_defaults=$ac_dir + break + fi + done +]) + +AC_DEFUN(AC_PATH_X_APP_DEFAULTS, + [AC_REQUIRE_CPP() + AC_CACHE_CHECK([for X app-defaults directory], ac_cv_x_app_defaults, + [AC_PATH_X_APP_DEFAULTS_XMKMF + if test x"$ac_x_app_defaults" = x; then + AC_PATH_X_APP_DEFAULTS_DIRECT + fi + if test x"$ac_x_app_defaults" = x; then + ac_cv_x_app_defaults="/usr/lib/X11/app-defaults" + else + # Record where we found app-defaults for the cache. + ac_cv_x_app_defaults="$ac_x_app_defaults" + fi]) + eval ac_x_app_defaults="$ac_cv_x_app_defaults"]) + + +AC_DEFUN(AC_XPOINTER, + [AC_CACHE_CHECK([for XPointer], ac_cv_xpointer, + [AC_TRY_X_COMPILE([#include ], + [XPointer foo = (XPointer) 0;], + [ac_cv_xpointer=yes], + [ac_cv_xpointer=no])]) + if test "$ac_cv_xpointer" != yes; then + AC_DEFINE(XPointer,[char*]) + fi]) + + +# Random special-cases for X on certain pathological OSes. +# You know who you are. +# +AC_DEFUN(AC_X_RANDOM_PATHS, + [case "$host" in + *-hpux*) + + # The following arcana was gleaned from conversations with + # Eric Schwartz : + # + # On HPUX 10.x, the parts of X that HP considers "standard" live in + # /usr/{include,lib}/X11R6/. The parts that HP doesn't consider + # "standard", notably, Xaw and Xmu, live in /usr/contrib/X11R6/. + # Yet /usr/contrib/X11R6/ comes preinstalled on all HPUX systems. + # Also, there are symlinks from /usr/include/ and /usr/lib/ into + # /usr/{include,lib}/X11R6/, so that (if you don't use Xmu at all) + # you don't need any -I or -L arguments. + # + # On HPUX 9.x, /usr/{include,lib}/X11R5/ and /usr/contrib/X11R5/ + # are the same division as 10.x. However, there are no symlinks to + # the X stuff from /usr/include/ and /usr/lib/, so -I and -L + # arguments are always necessary. + # + # However, X11R6 was available on HPUX 9.x as a patch: if that + # patch was installed, then all of X11R6 went in to + # /usr/contrib/X11R6/ (there was no /usr/{include,lib}/X11R6/.) + # + # HPUX 8.x was the same as 9.x, but was X11R4 instead (I don't know + # whether R5 was available as a patch; R6 undoubtedly was not.) + # + # So. We try and use the highest numbered pair of + # /usr/{include,lib}/X11R?/ and /usr/contrib/X11R?/{include,lib}/ + # that are available. We do not mix and match different versions + # of X. + # + # Question I still don't know the answer to: (do you?) + # + # * On HPUX 9.x, where /usr/include/X11R5/ was standard, and + # /usr/contrib/X11R6/ could be installed as a patch, what was in + # that contrib directory? Did it contain so-called "standard" + # X11R6, or did it include Xaw and Xmu as well? If the former, + # where did one find Xaw and Xmu on 9.x R6 systems? Would this + # be a situation where one had to reach into the R5 headers and + # libs to find Xmu? That is, must both R6 and R5 directories + # be on the -I and -L lists in that case? + # + for version in X11R6 X11R5 X11R4 ; do + # if either pair of directories exists... + if test -d /usr/include/$version || test -d /usr/contrib/$version/include + then + # if contrib exists, use it... + if test -d /usr/contrib/$version/include ; then + X_CFLAGS="$X_CFLAGS -I/usr/contrib/$version/include" + X_LIBS="$X_LIBS -L/usr/contrib/$version/lib" + fi + # if the "standard" one exists, use it. + if test -d /usr/include/$version ; then + X_CFLAGS="$X_CFLAGS -I/usr/include/$version" + X_LIBS="$X_LIBS -L/usr/lib/$version" + fi + # since at least one of the pair exists, go no farther. + break + fi + done + + # Now find Motif. Thanks for not making xmkmf find this by + # default, you losers. + # + if test -d /usr/include/Motif2.1 ; then + X_CFLAGS="$X_CFLAGS -I/usr/include/Motif2.1" + X_LIBS="$X_LIBS -L/usr/lib/Motif2.1" + elif test -d /usr/include/Motif1.2 ; then + X_CFLAGS="$X_CFLAGS -I/usr/include/Motif1.2" + X_LIBS="$X_LIBS -L/usr/lib/Motif1.2" + elif test -d /usr/include/Motif1.1 ; then + X_CFLAGS="$X_CFLAGS -I/usr/include/Motif1.1" + X_LIBS="$X_LIBS -L/usr/lib/Motif1.1" + fi + + # Now let's check for the pseudo-standard locations for OpenGL and XPM. + # + if test -d /opt/graphics/OpenGL/include ; then + # HP-UX 10.20 puts it here + X_CFLAGS="-I/opt/graphics/OpenGL/include $X_CFLAGS" + X_LIBS="-L/opt/graphics/OpenGL/lib $X_LIBS" + elif test -d /opt/Mesa/lib ; then + X_CFLAGS="-I/opt/Mesa/include $X_CFLAGS" + X_LIBS="-L/opt/Mesa/lib $X_LIBS" + fi + + + if test -d /opt/xpm/lib/X11 ; then + X_CFLAGS="-I/opt/xpm/include $X_CFLAGS" + X_LIBS="-L/opt/xpm/lib/X11 $X_LIBS" + fi + + # On HPUX, default to installing in /opt/xscreensaver/ instead of + # in /usr/local/, unless there is already an xscreensaver in + # /usr/local/bin/. This can be overridden with the --prefix arg + # to configure. I'm not sure this is the right thing to do, but + # Richard Lloyd says so... + # + if test \! -x /usr/local/bin/xscreensaver ; then + ac_default_prefix=/opt/xscreensaver + fi + + ;; + *-solaris*) + + # Thanks for not making xmkmf find this by default, pinheads. + # And thanks for moving things around again, too. Is this + # really the standard location now? What happened to the + # joke that this kind of thing went in /opt? + # cthomp says "answer: CDE (Common Disorganized Environment)" + # + if test -f /usr/dt/include/Xm/Xm.h ; then + X_CFLAGS="$X_CFLAGS -I/usr/dt/include" + MOTIF_LIBS="$MOTIF_LIBS -L/usr/dt/lib -R/usr/dt/lib" + + # Some versions of Slowlaris Motif require -lgen. But not all. Why? + AC_CHECK_LIB(gen, regcmp, [MOTIF_LIBS="$MOTIF_LIBS -lgen"]) + fi + + ;; + *-darwin*) + + # On MacOS X (10.x with "fink"), many things are under /sw/. + # + if test -d /sw/include ; then + X_CFLAGS="-I/sw/include $X_CFLAGS" + X_LIBS="-L/sw/lib $X_LIBS" + fi + ;; + esac]) + +AC_DEFUN(AC_CHECK_GETIFADDRS, + [AC_CACHE_CHECK([for getifaddrs], ac_cv_have_getifaddrs, + [AC_TRY_COMPILE([#include + #include + #include + #include ], + [struct ifaddrs *ifa; + getifaddrs (&ifa); + ifa->ifa_next = 0; + ifa->ifa_addr->sa_family = 0;], + [ac_cv_have_getifaddrs=yes], + [ac_cv_have_getifaddrs=no])]) + if test "$ac_cv_have_getifaddrs" = yes ; then + AC_DEFINE(HAVE_GETIFADDRS) + fi]) + + +############################################################################### +# +# Some utility functions to make checking for X things easier. +# +############################################################################### + +# Like AC_CHECK_HEADER, but it uses the already-computed -I directories. +# +AC_DEFUN(AC_CHECK_X_HEADER, [ + ac_save_CPPFLAGS="$CPPFLAGS" + if test \! -z "$includedir" ; then + CPPFLAGS="$CPPFLAGS -I$includedir" + fi + CPPFLAGS="$CPPFLAGS $X_CFLAGS" + CPPFLAGS=`eval eval eval eval eval eval eval eval eval echo $CPPFLAGS` + AC_CHECK_HEADER([$1],[$2],[$3],[$4]) + CPPFLAGS="$ac_save_CPPFLAGS"]) + +# Like AC_EGREP_HEADER, but it uses the already-computed -I directories. +# +AC_DEFUN(AC_EGREP_X_HEADER, [ + ac_save_CPPFLAGS="$CPPFLAGS" + if test \! -z "$includedir" ; then + CPPFLAGS="$CPPFLAGS -I$includedir" + fi + CPPFLAGS="$CPPFLAGS $X_CFLAGS" + CPPFLAGS=`eval eval eval eval eval eval eval eval eval echo $CPPFLAGS` + AC_EGREP_HEADER([$1], [$2], [$3], [$4]) + CPPFLAGS="$ac_save_CPPFLAGS"]) + +# Like AC_TRY_COMPILE, but it uses the already-computed -I directories. +# +AC_DEFUN(AC_TRY_X_COMPILE, [ + ac_save_CPPFLAGS="$CPPFLAGS" + if test \! -z "$includedir" ; then + CPPFLAGS="$CPPFLAGS -I$includedir" + fi + CPPFLAGS="$CPPFLAGS $X_CFLAGS" + CPPFLAGS=`eval eval eval eval eval eval eval eval eval echo $CPPFLAGS` + AC_TRY_COMPILE([$1], [$2], [$3], [$4]) + CPPFLAGS="$ac_save_CPPFLAGS"]) + + +# Like AC_CHECK_LIB, but it uses the already-computed -I and -L directories. +# Use this sparingly; it probably doesn't work very well on X programs. +# +AC_DEFUN(AC_CHECK_X_LIB, [ + ac_save_CPPFLAGS="$CPPFLAGS" + ac_save_LDFLAGS="$LDFLAGS" +# ac_save_LIBS="$LIBS" + + if test \! -z "$includedir" ; then + CPPFLAGS="$CPPFLAGS -I$includedir" + fi + # note: $X_CFLAGS includes $x_includes + CPPFLAGS="$CPPFLAGS $X_CFLAGS" + + if test \! -z "$libdir" ; then + LDFLAGS="$LDFLAGS -L$libdir" + fi + # note: $X_LIBS includes $x_libraries + LDFLAGS="$LDFLAGS $X_LIBS $X_EXTRA_LIBS" + + CPPFLAGS=`eval eval eval eval eval eval eval eval eval echo $CPPFLAGS` + LDFLAGS=`eval eval eval eval eval eval eval eval eval echo $LDFLAGS` + AC_CHECK_LIB([$1], [$2], [$3], [$4], [$5]) + CPPFLAGS="$ac_save_CPPFLAGS" + LDFLAGS="$ac_save_LDFLAGS" +# LIBS="$ac_save_LIBS" + ]) + +# Like AC_TRY_RUN, but it uses the already-computed -I directories. +# (But not the -L directories!) +# +AC_DEFUN(AC_TRY_X_RUN, [ + ac_save_CPPFLAGS="$CPPFLAGS" + if test \! -z "$includedir" ; then + CPPFLAGS="$CPPFLAGS -I$includedir" + fi + CPPFLAGS="$CPPFLAGS $X_CFLAGS" + CPPFLAGS=`eval eval eval eval eval eval eval eval eval echo $CPPFLAGS` + AC_TRY_RUN([$1], [$2], [$3], [$4]) + CPPFLAGS="$ac_save_CPPFLAGS"]) + + + +# Usage: HANDLE_X_PATH_ARG([variable_name], +# [--command-line-option], +# [descriptive string]) +# +# All of the --with options take three forms: +# +# --with-foo (or --with-foo=yes) +# --without-foo (or --with-foo=no) +# --with-foo=/DIR +# +# This function, HANDLE_X_PATH_ARG, deals with the /DIR case. When it sees +# a directory (string beginning with a slash) it checks to see whether +# /DIR/include and /DIR/lib exist, and adds them to $X_CFLAGS and $X_LIBS +# as appropriate. +# +AC_DEFUN(HANDLE_X_PATH_ARG, [ + case "$[$1]" in + yes) ;; + no) ;; + + /*) + AC_MSG_CHECKING([for [$3] headers]) + d=$[$1]/include + if test -d $d; then + X_CFLAGS="-I$d $X_CFLAGS" + AC_MSG_RESULT($d) + else + AC_MSG_RESULT(not found ($d: no such directory)) + fi + + AC_MSG_CHECKING([for [$3] libs]) + d=$[$1]/lib + if test -d $d; then + X_LIBS="-L$d $X_LIBS" + AC_MSG_RESULT($d) + else + AC_MSG_RESULT(not found ($d: no such directory)) + fi + + # replace the directory string with "yes". + [$1]_req="yes" + [$1]=$[$1]_req + ;; + + *) + echo "" + echo "error: argument to [$2] must be \"yes\", \"no\", or a directory." + echo " If it is a directory, then \`DIR/include' will be added to" + echo " the -I list, and \`DIR/lib' will be added to the -L list." + exit 1 + ;; + esac + ]) + + + +############################################################################### +############################################################################### +# +# End of function definitions. Now start actually executing stuff. +# +############################################################################### +############################################################################### + +# WTF! autoconf emits this *way* too late. Do it earlier. +test "x$prefix" = xNONE && prefix=$ac_default_prefix +test "x$exec_prefix" = xNONE && exec_prefix='${prefix}' + + +# random compiler setup +AC_CANONICAL_HOST +AC_PROG_CC_ANSI +AC_NO_LONG_STRING_WARNINGS +AC_NO_MISPLACED_DECLARATIONS +AC_NO_OBJECTIVE_C +AC_NO_CPLUSPLUS_COMMENTS_IN_C_CODE +AC_PROG_CPP +AC_C_CONST +AC_C_INLINE +AC_EXEEXT +AC_DEMAND_BC + +# stuff for Makefiles +AC_PROG_INSTALL +AC_PROG_INSTALL_DIRS +AC_PROG_MAKE_SET + +# By default, autoconf sets INSTALL_SCRIPT to '${INSTALL_PROGRAM}'. +# That's wrong: it should be set to '${INSTALL}', so that one can +# implement the "install-strip" target properly (strip executables, +# but do not try to strip scripts.) +# +INSTALL_SCRIPT='${INSTALL}' + +# random libc stuff +AC_HEADER_STDC +AC_CHECK_HEADERS(unistd.h) +AC_TYPE_MODE_T +AC_TYPE_PID_T +AC_TYPE_SIZE_T +AC_TYPE_SIGNAL +AC_HEADER_TIME +AC_HEADER_SYS_WAIT +AC_HEADER_DIRENT +AC_GETTIMEOFDAY_ARGS +AC_CHECK_FUNCS(select fcntl uname nice setpriority getcwd getwd putenv sbrk) +AC_CHECK_FUNCS(sigaction syslog realpath setrlimit) +AC_CHECK_FUNCS(setlocale) +AC_CHECK_ICMP +AC_CHECK_ICMPHDR +AC_CHECK_GETIFADDRS +AC_CHECK_HEADERS(crypt.h sys/select.h) +AC_PROG_PERL + +if test -z "$PERL" ; then + # don't let it be blank... + PERL=/usr/bin/perl +fi + +AC_PATH_XTRA + +if test "$have_x" != yes; then + AC_MSG_ERROR(Couldn't find X11 headers/libs. Try `$0 --help'.) +fi + +AC_PATH_X_APP_DEFAULTS +AC_X_RANDOM_PATHS +AC_XPOINTER + +AC_MSG_CHECKING(whether this is MacOS X) + ac_macosx=no + case "$host" in + *-apple-darwin* ) + ac_macosx=yes + ;; + esac +AC_MSG_RESULT($ac_macosx) + + +############################################################################### +# +# Gettext support +# +############################################################################### + +AC_PROG_INTLTOOL +GETTEXT_PACKAGE=xscreensaver +AC_DEFINE_UNQUOTED(GETTEXT_PACKAGE, "$GETTEXT_PACKAGE", + [This is the name of the gettext package to use.]) +AC_DEFINE_UNQUOTED(PACKAGE, "$GETTEXT_PACKAGE", + [This is the same as GETTEXT_PACKAGE, but for the glade + generated code.]) +AC_SUBST(GETTEXT_PACKAGE) + +ALL_LINGUAS="ca da de es et fi fr hu it ja ko nb nl pl pt pt_BR ru sk sv vi wa zh_CN zh_TW" +AM_GLIB_GNU_GETTEXT +MKINSTALLDIRS="$INSTALL_DIRS" + + +############################################################################### +# +# Check for -lXmu (some fucked up vendors don't ship it...) +# +############################################################################### + +have_xmu=no +AC_CHECK_X_HEADER(X11/Xmu/Error.h, [have_xmu=yes],, + [#include + #include + #include ]) +if test "$have_xmu" = no ; then + XMU_SRCS='$(UTILS_SRC)/xmu.c' + XMU_OBJS='$(UTILS_BIN)/xmu.o' + XMU_LIBS='' +else + XMU_SRCS='' + XMU_OBJS='' + XMU_LIBS='-lXmu' + AC_DEFINE(HAVE_XMU) +fi + + +############################################################################### +# +# Check for the SunOS 4.1.x _get_wmShellWidgetClass bug. +# See comp.windows.x FAQ question 124. The right fix is to +# get OpenWindows 3.0 patches 100512-02 and 100573-03. +# +############################################################################### + +if test "$have_xmu" = yes ; then + case "$host" in + *-sunos4*) + AC_CACHE_CHECK([for the SunOS 4.1.x _get_wmShellWidgetClass bug], + ac_cv_sunos_xmu_bug, + [ac_save_LDFLAGS="$LDFLAGS" + if test \! -z "$x_libraries" ; then + LDFLAGS="$LDFLAGS -L$x_libraries" + fi + # Note: this trick never works! (Generally.) + # We're only getting away with using AC_TRY_LINK + # with X libraries because we know it's SunOS. + LDFLAGS="$LDFLAGS -lXmu -lXt -lX11 -lXext -lm" + AC_TRY_LINK(,, + [ac_cv_sunos_xmu_bug=no], + [ac_cv_sunos_xmu_bug=yes]) + LDFLAGS="$ac_save_LDFLAGS"]) + if test "$ac_cv_sunos_xmu_bug" = yes ; then + AC_CACHE_CHECK([whether the compiler understands -static], + ac_cv_ld_static, + [ac_save_LDFLAGS="$LDFLAGS" + LDFLAGS="$LDFLAGS -static" + AC_TRY_LINK(,,[ac_cv_ld_static=yes],[ac_cv_ld_static=no]) + LDFLAGS="$ac_save_LDFLAGS"]) + if test "$ac_cv_ld_static" = yes ; then + LDFLAGS="$LDFLAGS -static" + else + LDFLAGS="$LDFLAGS -Bstatic" + fi + fi + ;; + esac +fi + + +############################################################################### +# +# Handle the --with-hackdir option +# +############################################################################### + +have_hackdir=yes +with_hackdir_req=unspecified +AC_ARG_WITH(hackdir,[ + +Installation options: + --with-hackdir=DIR Where to install the hundreds of demo executables. + Default: `PREFIX/libexec/xscreensaver/'], + [with_hackdir="$withval"; with_hackdir_req="$withval"],[with_hackdir=yes]) + +if test x"$with_hackdir" = xyes; then + HACKDIR='${libexecdir}/xscreensaver' +elif test x"$with_hackdir" = xno; then + HACKDIR='${bindir}' +else + HACKDIR=$with_hackdir +fi + +# canonicalize slashes. +HACKDIR=`echo "${HACKDIR}" | sed 's@/$@@;s@//*@/@g'` + +# Expand HACKDIR as HACKDIR_FULL +HACKDIR_FULL=`eval eval eval eval eval eval eval eval eval echo $HACKDIR` + +# This option used to be called --enable-subdir; make sure that is no longer +# used, since configure brain-damagedly ignores unknown --enable options. + +obsolete_enable= +AC_ARG_ENABLE(subdir,,[obsolete_enable=yes]) +if test -n "$obsolete_enable"; then + echo "error: the --enable-subdir option has been replaced with" + echo " the new --with-hackdir option; see \`configure --help'" + echo " for more information." + exit 1 +fi + + +############################################################################### +# +# Handle the --with-configdir option +# Help for --with-x-app-defaults option added. +# +############################################################################### + +have_configdir=yes +with_configdir_req=unspecified +AC_ARG_WITH(configdir, +[ --with-configdir=DIR Where to install the data files that describe each + of the display modes to the GUI. + Default: `PREFIX/share/xscreensaver/config/' + --with-x-app-defaults=DIR + Where to install xscreensaver configuration file. +], + [with_configdir="$withval"; with_configdir_req="$withval"], + [with_configdir=yes]) + +if test x"$with_configdir" = xyes; then + HACK_CONF_DIR='${datadir}/xscreensaver/config' +elif test x"$with_configdir" = xno; then + echo "error: must be yes, or a pathname: --with-configdir=$with_configdir" + exit 1 +else + # there must be a better way than this... + if test -z "`echo $with_configdir | sed 's@^/.*@@'`" ; then + # absolute path + HACK_CONF_DIR=$with_configdir + else + # relative path + HACK_CONF_DIR="\${exec_prefix}$with_configdir" + fi +fi + + + + +############################################################################### +# +# Check for the SGI SCREEN_SAVER server extension. +# +############################################################################### + +#have_sgi=no +#with_sgi_req=unspecified +#AC_ARG_WITH(sgi-ext, +#[Except where noted, all of the --with options below can also take a +#directory argument: for example, `--with-motif=/opt/Motif'. That would +#cause /opt/Motif/include/ to be added to the -I list, and /opt/Motif/lib/ +#to be added to the -L list, assuming those directories exist. +# +#By default, support for each of these options will be built in, if the +#relevant library routines exist. At run time, they will then be used +#only if the X server being used supports them. Each --with option has +#a corresponding --without option, to override building support for them +#at all. +# +#Screen blanking and idle-detection options: +# +# --with-sgi-ext Include support for the SGI SCREEN_SAVER extension.], +# [with_sgi="$withval"; with_sgi_req="$withval"],[with_sgi=yes]) +# +#HANDLE_X_PATH_ARG(with_sgi, --with-sgi-ext, SGI SCREEN_SAVER) +# +#if test "$with_sgi" = yes; then +# AC_CHECK_X_HEADER(X11/extensions/XScreenSaver.h, +# [have_sgi=yes +# AC_DEFINE(HAVE_SGI_SAVER_EXTENSION)],, +# [#include ]) +# +#elif test "$with_sgi" != no; then +# echo "error: must be yes or no: --with-sgi-ext=$with_sgi" +# exit 1 +#fi + + +############################################################################### +# +# Check for the XIDLE server extension. +# +############################################################################### + +#have_xidle=no +#with_xidle_req=unspecified +#AC_ARG_WITH(xidle-ext, +#[ --with-xidle-ext Include support for the XIDLE extension.], +# [with_xidle="$withval"; with_xidle_req="$withval"],[with_xidle=yes]) +# +#HANDLE_X_PATH_ARG(with_xidle, --with-xidle-ext, XIDLE) +# +#if test "$with_xidle" = yes; then +# AC_CHECK_X_HEADER(X11/extensions/xidle.h, +# [have_xidle=yes +# AC_DEFINE(HAVE_XIDLE_EXTENSION)],, +# [#include ]) +#elif test "$with_xidle" != no; then +# echo "error: must be yes or no: --with-xidle-ext=$with_xidle" +# exit 1 +#fi + + +############################################################################### +# +# Check for the SGI-VIDEO-CONTROL server extension. +# +############################################################################### + +#have_sgivc=no +#with_sgivc_req=unspecified +#AC_ARG_WITH(sgivc-ext, +#[ --with-sgivc-ext Include support for the SGI-VIDEO-CONTROL extension.], +# [with_sgivc="$withval"; with_sgivc_req="$withval"],[with_sgivc=yes]) +# +#HANDLE_X_PATH_ARG(with_sgivc, --with-sgivc-ext, SGI-VIDEO-CONTROL) +# +#if test "$with_sgivc" = yes; then +# +# # first check for XSGIvc.h +# AC_CHECK_X_HEADER(X11/extensions/XSGIvc.h, [have_sgivc=yes],, +# [#include ]) +# +# # if that succeeded, then check for the -lXsgivc +# if test "$have_sgivc" = yes; then +# have_sgivc=no +# AC_CHECK_X_LIB(Xsgivc, XSGIvcQueryGammaMap, +# [have_sgivc=yes; SAVER_LIBS="$SAVER_LIBS -lXsgivc"], [true], +# -lXext -lX11) +# fi +# +# # if that succeeded, then we've really got it. +# if test "$have_sgivc" = yes; then +# AC_DEFINE(HAVE_SGI_VC_EXTENSION) +# fi +# +#elif test "$with_sgivc" != no; then +# echo "error: must be yes or no: --with-sgivc-ext=$with_sgivc" +# exit 1 +#fi + + +############################################################################### +# +# Check for the DPMS server extension. +# +############################################################################### + +have_dpms=no +with_dpms_req=unspecified +AC_ARG_WITH(dpms-ext, +[ --with-dpms-ext Include support for the DPMS extension.], + [with_dpms="$withval"; with_dpms_req="$withval"],[with_dpms=yes]) + +HANDLE_X_PATH_ARG(with_dpms, --with-dpms-ext, DPMS) + +if test "$with_dpms" = yes; then + + # first check for dpms.h + AC_CHECK_X_HEADER(X11/extensions/dpms.h, [have_dpms=yes],, + [#include + #include ]) + + # if that succeeded, then check for the DPMS code in the libraries + if test "$have_dpms" = yes; then + + # first look in -lXext (this is where it is with XFree86 4.0) + have_dpms=no + AC_CHECK_X_LIB(Xext, DPMSInfo, [have_dpms=yes], [true], -lXext -lX11) + + # if that failed, look in -lXdpms (this is where it was in XFree86 3.x) + if test "$have_dpms" = no; then + AC_CHECK_X_LIB(Xdpms, DPMSInfo, + [have_dpms=yes; XDPMS_LIBS="-lXdpms"], [true], + -lXext -lX11) + fi + fi + + + # if that succeeded, then we've really got it. + if test "$have_dpms" = yes; then + AC_DEFINE(HAVE_DPMS_EXTENSION) + fi + +elif test "$with_dpms" != no; then + echo "error: must be yes or no: --with-dpms-ext=$with_dpms" + exit 1 +fi + + +############################################################################### +# +# Check for the XINERAMA server extension. +# +############################################################################### + +have_xinerama=no +with_xinerama_req=unspecified +AC_ARG_WITH(xinerama-ext, +[ --with-xinerama-ext Include support for the XINERAMA extension.], + [with_xinerama="$withval"; with_xinerama_req="$withval"],[with_xinerama=yes]) + +HANDLE_X_PATH_ARG(with_xinerama, --with-xinerama-ext, XINERAMA) + +if test "$with_xinerama" = yes; then + + # first check for Xinerama.h + AC_CHECK_X_HEADER(X11/extensions/Xinerama.h, [have_xinerama=yes],, + [#include ]) + + # if that succeeded, then check for the XINERAMA code in the libraries + if test "$have_xinerama" = yes; then + + # first look in -lXext + have_xinerama=no + AC_CHECK_X_LIB(Xext, XineramaQueryScreens, [have_xinerama=yes], [true], + -lXext -lX11) + + # if that failed, look in -lXinerama (this is where it is in XFree86 4.1.) + if test "$have_xinerama" = no; then + AC_CHECK_X_LIB(Xinerama, XineramaQueryScreens, + [have_xinerama=yes; XINERAMA_LIBS="-lXinerama"], + [true], -lXext -lX11) + fi + fi + + # if that succeeded, then we've really got it. + if test "$have_xinerama" = yes; then + AC_DEFINE(HAVE_XINERAMA) + fi + +elif test "$with_xinerama" != no; then + echo "error: must be yes or no: --with-xinerama-ext=$with_xinerama" + exit 1 +fi + + +############################################################################### +# +# Check for the XINPUT server extension. +# +############################################################################### + +have_xinput=no +with_xinput_req=unspecified +AC_ARG_WITH(xinput-ext, +[ --with-xinput-ext Include support for the XInput extension.], + [with_xinput="$withval"; with_xinput_req="$withval"], [with_xinput=yes]) + +HANDLE_X_PATH_ARG(with_xinput, --with-xinput-ext, XINPUT) + +if test "$with_xinput" = yes; then + + # first check for Xinput.h + AC_CHECK_X_HEADER(X11/extensions/XInput.h, [have_xinput=yes],, + [#include ]) + + # if that succeeded, then check for libXi + if test "$have_xinput" = yes; then + have_xinput=no + AC_CHECK_X_LIB(Xi, XListInputDevices, + [have_xinput=yes; SAVER_LIBS="$SAVER_LIBS -lXi"], + [true], -lXext -lX11) + fi + + # if that succeeded, then we've really got it. + if test "$have_xinput" = yes; then + AC_DEFINE(HAVE_XINPUT) + fi + +elif test "$with_xinput" != no; then + echo "error: must be yes or no: --with-xinput-ext=$with_xinput" + exit 1 +fi + + +############################################################################### +# +# Check for the XF86VMODE server extension (for virtual screens.) +# +############################################################################### + +have_xf86vmode=no +with_xf86vmode_req=unspecified +AC_ARG_WITH(xf86vmode-ext, +[ --with-xf86vmode-ext Include support for XFree86 virtual screens.], + [with_xf86vmode="$withval"; with_xf86vmode_req="$withval"], + [with_xf86vmode=yes]) + +HANDLE_X_PATH_ARG(with_xf86vmode, --with-xf86vmode-ext, xf86vmode) + +VIDMODE_LIBS="" + +if test "$with_xf86vmode" = yes; then + + # first check for xf86vmode.h + AC_CHECK_X_HEADER(X11/extensions/xf86vmode.h, [have_xf86vmode=yes],, + [#include ]) + + # if that succeeded, then check for the -lXxf86vm + if test "$have_xf86vmode" = yes; then + have_xf86vmode=no + AC_CHECK_X_LIB(Xxf86vm, XF86VidModeGetViewPort, + [have_xf86vmode=yes; + VIDMODE_LIBS="-lXxf86vm"; + SAVER_LIBS="$SAVER_LIBS $VIDMODE_LIBS"], + [true], -lXext -lX11) + fi + + # if that succeeded, then we've really got it. + if test "$have_xf86vmode" = yes; then + AC_DEFINE(HAVE_XF86VMODE) + fi + +elif test "$with_xf86vmode" != no; then + echo "error: must be yes or no: --with-xf86vmode-ext=$with_xf86vmode" + exit 1 +fi + + +############################################################################### +# +# Check for the XF86VMODE server extension (for gamma fading.) +# +############################################################################### + +have_xf86gamma=no +have_xf86gamma_ramp=no +with_xf86gamma_req=unspecified +AC_ARG_WITH(xf86gamma-ext, +[ --with-xf86gamma-ext Include support for XFree86 gamma fading.], + [with_xf86gamma="$withval"; with_xf86gamma_req="$withval"], + [with_xf86gamma=yes]) + +HANDLE_X_PATH_ARG(with_xf86gamma, --with-xf86gamma-ext, xf86gamma) + +if test "$with_xf86gamma" = yes; then + + # first check for xf86vmode.h, if we haven't already + if test "$have_xf86vmode" = yes; then + have_xf86gamma=yes + else + AC_CHECK_X_HEADER(X11/extensions/xf86vmode.h, [have_xf86gamma=yes],, + [#include ]) + fi + + # if that succeeded, then check for the -lXxf86vm + if test "$have_xf86gamma" = yes; then + have_xf86gamma=no + AC_CHECK_X_LIB(Xxf86vm, XF86VidModeSetGamma, + [have_xf86gamma=yes], + [true], -lXext -lX11) + fi + + # check for the Ramp versions of the functions too. + if test "$have_xf86gamma" = yes; then + have_xf86gamma_ramp=no + AC_CHECK_X_LIB(Xxf86vm, XF86VidModeSetGammaRamp, + [have_xf86gamma_ramp=yes], + [true], -lXext -lX11) + fi + + # if those tests succeeded, then we've really got the functions. + if test "$have_xf86gamma" = yes; then + AC_DEFINE(HAVE_XF86VMODE_GAMMA) + fi + + if test "$have_xf86gamma_ramp" = yes; then + AC_DEFINE(HAVE_XF86VMODE_GAMMA_RAMP) + fi + + # pull in the lib, if we haven't already + if test "$have_xf86gamma" = yes -a "$have_xf86vmode" = no; then + SAVER_LIBS="$SAVER_LIBS -lXxf86vm" + fi + +elif test "$with_xf86gamma" != no; then + echo "error: must be yes or no: --with-xf86gamma-ext=$with_xf86vmode" + exit 1 +fi + + +############################################################################### +# +# Check for the RANDR (Resize and Rotate) server extension. +# +# We need this to detect when the resolution of the desktop +# has changed out from under us (this is a newer, different +# mechanism than the XF86VMODE virtual viewports.) +# +############################################################################### + +have_randr=no +with_randr_req=unspecified +AC_ARG_WITH(randr-ext, +[ --with-randr-ext Include support for the X Resize+Rotate extension.], + [with_randr="$withval"; with_randr_req="$withval"],[with_randr=yes]) + +HANDLE_X_PATH_ARG(with_randr, --with-randr-ext, RANDR) + +if test "$with_randr" = yes; then + + # first check for Xrandr.h + AC_CHECK_X_HEADER(X11/extensions/Xrandr.h, [have_randr=yes],, + [#include ]) + + # if that succeeded, then check for the XRR code in the libraries + if test "$have_randr" = yes; then + + # RANDR probably needs -lXrender + xrender_libs= + AC_CHECK_X_LIB(Xrender, XRenderSetSubpixelOrder, + [xrender_libs="-lXrender"], [true], -lXext -lX11) + + # first look for RANDR in -lXext + have_randr=no + AC_CHECK_X_LIB(Xext, XRRGetScreenInfo, + [have_randr=yes; SAVER_LIBS="$SAVER_LIBS $xrender_libs"], + [true], $xrender_libs -lXext -lX11) + + # if that failed, look in -lXrandr + if test "$have_randr" = no; then + AC_CHECK_X_LIB(Xrandr, XRRGetScreenInfo, + [have_randr=yes; SAVER_LIBS="$SAVER_LIBS -lXrandr $xrender_libs"], + [true], $xrender_libs -lXext -lX11) + fi + fi + + # if that succeeded, then we've really got it. + if test "$have_randr" = yes; then + AC_DEFINE(HAVE_RANDR) + + # Now check for version 1.2 in the same libs. + # Try to compile, since on MacOS 10.5.7, headers are older than libs! + AC_CACHE_CHECK([for XRRGetScreenResources], ac_cv_randr_12, + [ac_cv_randr_12=no + AC_TRY_X_COMPILE([#include + #include + #include ], + [XRRScreenResources *res = + XRRGetScreenResources (0, 0);], + [ac_cv_randr_12=yes], + [ac_cv_randr_12=no])]) + if test "$ac_cv_randr_12" = yes ; then + AC_DEFINE(HAVE_RANDR_12) + fi +# AC_CHECK_X_LIB(c, XRRGetOutputInfo, [AC_DEFINE(HAVE_RANDR_12)], +# [true], $SAVER_LIBS) + fi + + +elif test "$with_randr" != no; then + echo "error: must be yes or no: --with-randr-ext=$with_randr" + exit 1 +fi + + +############################################################################### +# +# Check for XF86MiscSetGrabKeysState (but only bother if we are already +# using other XF86 stuff.) +# +############################################################################### + +have_xf86miscsetgrabkeysstate=no +if test "$have_xf86gamma" = yes -o "$have_xf86vmode" = yes; then + AC_CHECK_X_LIB(Xxf86misc, XF86MiscSetGrabKeysState, + [have_xf86miscsetgrabkeysstate=yes], + [true], -lXext -lX11) + if test "$have_xf86miscsetgrabkeysstate" = yes ; then + SAVER_LIBS="$SAVER_LIBS -lXxf86misc" + AC_DEFINE(HAVE_XF86MISCSETGRABKEYSSTATE) + fi +fi + + +############################################################################### +# +# Check for HP XHPDisableReset and XHPEnableReset. +# +############################################################################### + +AC_MSG_CHECKING([for XHPDisableReset in X11/XHPlib.h]) +AC_EGREP_X_HEADER(XHPDisableReset, X11/XHPlib.h, + [AC_DEFINE(HAVE_XHPDISABLERESET) + SAVER_LIBS="-lXhp11 $SAVER_LIBS" + AC_MSG_RESULT(yes)], + [AC_MSG_RESULT(no)]) + + +############################################################################### +# +# Check for /proc/interrupts. +# +############################################################################### + +have_proc_interrupts=no +with_proc_interrupts_req=unspecified +AC_ARG_WITH(proc-interrupts, +[ --with-proc-interrupts Include support for consulting the /proc/interrupts + file to notice keyboard activity.], + [with_proc_interrupts="$withval"; with_proc_interrupts_req="$withval"], + [with_proc_interrupts=yes]) + +if test "$with_proc_interrupts" = yes; then + + # Note that we may be building in an environment (e.g. Debian buildd chroot) + # without a proper /proc filesystem. If /proc/interrupts exists, then we'll + # check that it has the bits we need, but otherwise we'll just go on faith. + # + have_proc_interrupts=yes + + if test -f /proc/interrupts; then + AC_CACHE_CHECK([whether /proc/interrupts contains keyboard data], + ac_cv_have_proc_interrupts, + [ac_cv_have_proc_interrupts=no + if grep 'keyboard\|i8042' /proc/interrupts >/dev/null 2>&1 ; then + ac_cv_have_proc_interrupts=yes + fi + ]) + have_proc_interrupts=$ac_cv_have_proc_interrupts + fi + + if test "$have_proc_interrupts" = yes; then + AC_DEFINE(HAVE_PROC_INTERRUPTS) + fi + +elif test "$with_proc_interrupts" != no; then + echo "error: must be yes or no: --with-proc-interrupts=$with_proc_interrupts" + exit 1 +fi + + +############################################################################### +# +# The --enable-locking option +# +############################################################################### + +AC_ARG_ENABLE(locking,[Screen locking options: + --enable-locking Compile in support for locking the display. + --disable-locking Do not allow locking at all.], + [enable_locking="$enableval"], + [if test "$ac_macosx" = yes; then + # We can't lock on MacOS X, so default to not compiling in support for it. + # But allow --enable-locking to override that, so I can debug Linux locking + # under MacOS X11. + enable_locking=no + else + enable_locking=yes + fi]) +if test "$enable_locking" = yes; then + true +elif test "$enable_locking" = no; then + AC_DEFINE(NO_LOCKING) +else + echo "error: must be yes or no: --enable-locking=$enable_locking" + exit 1 +fi + + +############################################################################### +# +# Whether to allow root password to unblank. +# +############################################################################### +AC_ARG_ENABLE(root-passwd, [ + --enable-root-passwd Allow root passwd to unlock screen. + --disable-root-passwd Do not allow that.], + [enable_root_passwd="$enableval"],[enable_root_passwd=yes]) +if test "$enable_root_passwd" = yes; then + AC_DEFINE(ALLOW_ROOT_PASSWD) + true +elif test "$enable_root_passwd" != no; then + echo "error: must be yes or no: --enable-root-passwd=$enable_root_passwd" + exit 1 +fi + +############################################################################### +# +# Check for PAM. +# +############################################################################### + +case "$host" in + *-solaris*) + # Solaris systems tend to come with PAM misconfigured. + # Don't build it by default, even if the headers exist. + with_pam_default=no + ;; + *) + # Default to building PAM support on all other systems, if it exists. + with_pam_default=yes + ;; +esac + +have_pam=no +with_pam_req=unspecified + +AC_ARG_WITH(pam, +[ --with-pam Include support for PAM (Pluggable Auth Modules.)], + [with_pam="$withval"; with_pam_req="$withval"],[with_pam=$with_pam_default]) + +AC_ARG_WITH([pam_service_name], + AC_HELP_STRING([--with-pam-service-name], + [NAME arg is the name of the PAM service that + xscreensaver will authenticate as.]), + [pam_service_name="$withval"],[pam_service_name="xscreensaver"]) + +AC_ARG_ENABLE(pam-check-account-type, + [AC_HELP_STRING([--enable-pam-check-account-type], + [Whether PAM should check the result of account + modules when authenticating. Only do this if you + have account configured properly on your system.])], + [enable_pam_check_account_type="$enableval"],[enable_pam_check_account_type=no]) +if test "$enable_pam_check_account_type" = yes ; then + AC_DEFINE(PAM_CHECK_ACCOUNT_TYPE) + true +elif test "$enable_pam_check_account_type" != no ; then + echo "error: must be yes or no: --enable-pam-check-account-type=$enable_pam_check_account_type" + exit 1 +fi + +HANDLE_X_PATH_ARG(with_pam, --with-pam, PAM) + +if test "$enable_locking" = yes -a "$with_pam" = yes; then + AC_CACHE_CHECK([for PAM], ac_cv_pam, + [AC_TRY_X_COMPILE([#include ],, + [ac_cv_pam=yes], + [ac_cv_pam=no])]) + if test "$ac_cv_pam" = yes ; then + have_pam=yes + AC_DEFINE(HAVE_PAM) + AC_DEFINE_UNQUOTED(PAM_SERVICE_NAME,"$pam_service_name") + + PASSWD_LIBS="${PASSWD_LIBS} -lpam" + + # libpam typically requires dlopen and dlsym. On FreeBSD, + # those are in libc. On Linux and Solaris, they're in libdl. + AC_CHECK_LIB(dl, dlopen, [PASSWD_LIBS="${PASSWD_LIBS} -ldl"]) + + # On Linux, sigtimedwait() is in libc; on Solaris, it's in librt. + have_timedwait=no + AC_CHECK_LIB(c, sigtimedwait, + [have_timedwait=yes + AC_DEFINE(HAVE_SIGTIMEDWAIT)]) + if test "$have_timedwait" = no ; then + AC_CHECK_LIB(rt, sigtimedwait, [have_timedwait=yes + AC_DEFINE(HAVE_SIGTIMEDWAIT) + PASSWD_LIBS="${PASSWD_LIBS} -lrt"]) + fi + + AC_MSG_CHECKING(how to call pam_strerror) + AC_CACHE_VAL(ac_cv_pam_strerror_args, + [AC_TRY_X_COMPILE([#include + #include + #include ], + [pam_handle_t *pamh = 0; + char *s = pam_strerror(pamh, PAM_SUCCESS);], + [ac_pam_strerror_args=2], + [AC_TRY_X_COMPILE([#include + #include + #include ], + [char *s = + pam_strerror(PAM_SUCCESS);], + [ac_pam_strerror_args=1], + [ac_pam_strerror_args=0])]) + ac_cv_pam_strerror_args=$ac_pam_strerror_args]) + ac_pam_strerror_args=$ac_cv_pam_strerror_args + if test "$ac_pam_strerror_args" = 1 ; then + AC_MSG_RESULT(one argument) + elif test "$ac_pam_strerror_args" = 2 ; then + AC_DEFINE(PAM_STRERROR_TWO_ARGS) + AC_MSG_RESULT(two arguments) + else + AC_MSG_RESULT(unknown) + fi + +# Check pam_fail_delay + AC_MSG_CHECKING(pam_fail_delay in -lpam) + AC_CACHE_VAL(ac_cv_pam_fail_delay, + [ac_save_LDFLAGS="$LDFLAGS" + LDFLAGS="-lpam" + AC_TRY_LINK([#include ], + [pam_handle_t *pamh = 0; + unsigned int usec = 1; + int status = pam_fail_delay (pamh, usec);], + [ac_pam_fail_delay=yes], + [ac_pam_fail_delay=no]) + ac_cv_pam_fail_delay=$ac_pam_fail_delay, + LDFLAGS=$ac_save_LDFLAGS]) + + if test "$ac_pam_fail_delay" = yes ; then + AC_MSG_RESULT(yes) + AC_DEFINE(HAVE_PAM_FAIL_DELAY) + else + AC_MSG_RESULT(no) + fi + + fi +fi + + +############################################################################### +# +# Check for Kerberos. +# +############################################################################### + +have_kerberos=no +have_kerberos5=no +with_kerberos_req=unspecified + +AC_ARG_WITH(kerberos, +[ --with-kerberos Include support for Kerberos authentication.], + [with_kerberos="$withval"; with_kerberos_req="$withval"],[with_kerberos=yes]) + +HANDLE_X_PATH_ARG(with_kerberos, --with-kerberos, Kerberos) + +if test "$enable_locking" = yes -a "$with_kerberos" = yes; then + AC_CACHE_CHECK([for Kerberos 4], ac_cv_kerberos, + [AC_TRY_X_COMPILE([#include ],, + [ac_cv_kerberos=yes], + [ac_cv_kerberos=no])]) + AC_CACHE_CHECK([for Kerberos 5], ac_cv_kerberos5, + [AC_TRY_X_COMPILE([#include ],, + [ac_cv_kerberos5=yes], + [ac_cv_kerberos5=no])]) + + if test "$ac_cv_kerberos" = yes ; then + have_kerberos=yes + AC_DEFINE(HAVE_KERBEROS) + fi + + if test "$ac_cv_kerberos5" = yes ; then + + # Andrew Snare wrote: + # + # You were assuming that if kerberosV (krb5) was found, then kerberosIV + # (krb4) was also available. This turns out not to be the case with + # mit-krb-1.2.7; apparently backwards-compatibility with KerberosIV + # is optional. + # + # So, disable kerberosV support if libkrb4 can't be found. + # This is not the best solution, but it makes the compile not fail. + # + AC_CHECK_X_LIB(krb4, krb_get_tf_realm, + [have_kerberos=yes], + [have_kerberos=no]) + if test "$have_kerberos" = yes ; then + have_kerberos5=yes + AC_DEFINE(HAVE_KERBEROS) + AC_DEFINE(HAVE_KERBEROS5) + else + have_kerberos5=no + AC_MSG_WARN([Cannot find compat lib (libkrb4) needed to use Kerberos 5]) + fi + + fi + + if test "$have_kerberos5" = yes ; then + # from Matt Knopp + # (who got it from amu@mit.edu) + + PASSWD_LIBS="$PASSWD_LIBS -lkrb4 -ldes425 -lkrb5 -lk5crypto -lcom_err" + + # jwz: MacOS X uses -lkrb5, but not -lcrypt + AC_CHECK_X_LIB(crypt, crypt, [PASSWD_LIBS="$PASSWD_LIBS -lcrypt"]) + + elif test "$have_kerberos" = yes ; then + # from Tim Showalter for FreeBSD 4.2 + PASSWD_LIBS="$PASSWD_LIBS -lkrb -ldes -lcom_err" + fi + + if test "$have_kerberos" = yes ; then + AC_CHECK_FUNC(res_search,, + AC_CHECK_LIB(resolv,res_search,PASSWD_LIBS="${PASSWD_LIBS} -lresolv", + AC_MSG_WARN([Can't find DNS resolver libraries needed for Kerberos]) + )) + fi +fi + + +############################################################################### +# +# Check for the nine billion variants of shadow passwords... +# +############################################################################### + +need_setuid=no + +have_shadow=no +with_shadow_req=unspecified + +AC_ARG_WITH(shadow, +[ --with-shadow Include support for shadow password authentication.], + [with_shadow="$withval"; with_shadow_req="$withval"],[with_shadow=yes]) + +HANDLE_X_PATH_ARG(with_shadow, --with-shadow, shadow password) + +if test "$enable_locking" = no ; then + with_shadow_req=no + with_shadow=no +fi + + +############################################################################### +# +# Check for Sun "adjunct" passwords. +# +############################################################################### + +if test "$with_shadow" = yes ; then + AC_CACHE_CHECK([for Sun-style shadow passwords], ac_cv_sun_adjunct, + [AC_TRY_X_COMPILE([#include + #include + #include + #include + #include + #include ], + [struct passwd_adjunct *p = getpwanam("nobody"); + const char *pw = p->pwa_passwd;], + [ac_cv_sun_adjunct=yes], + [ac_cv_sun_adjunct=no])]) + if test "$ac_cv_sun_adjunct" = yes; then + have_shadow_adjunct=yes + have_shadow=yes + need_setuid=yes + fi +fi + + +############################################################################### +# +# Check for DEC and SCO so-called "enhanced" security. +# +############################################################################### + +if test "$with_shadow" = yes ; then + AC_CACHE_CHECK([for DEC-style shadow passwords], ac_cv_enhanced_passwd, + [AC_TRY_X_COMPILE([#include + #include + #include + #include + #include + #include ], + [struct pr_passwd *p; + const char *pw; + set_auth_parameters(0, 0); + check_auth_parameters(); + p = getprpwnam("nobody"); + pw = p->ufld.fd_encrypt;], + [ac_cv_enhanced_passwd=yes], + [ac_cv_enhanced_passwd=no])]) + if test $ac_cv_enhanced_passwd = yes; then + have_shadow_enhanced=yes + have_shadow=yes + need_setuid=yes + + # On SCO, getprpwnam() is in -lprot (which uses nap() from -lx) + # (I'm told it needs -lcurses too, but I don't understand why.) + # But on DEC, it's in -lsecurity. + # + AC_CHECK_LIB(prot, getprpwnam, + [PASSWD_LIBS="$PASSWD_LIBS -lprot -lcurses -lx"], + [AC_CHECK_LIB(security, getprpwnam, + [PASSWD_LIBS="$PASSWD_LIBS -lsecurity"])], + [-lx]) + fi +fi + +############################################################################### +# +# Check for HP's entry in the "Not Invented Here" Sweepstakes. +# +############################################################################### + +if test "$with_shadow" = yes ; then + AC_CACHE_CHECK([for HP-style shadow passwords], ac_cv_hpux_passwd, + [AC_TRY_X_COMPILE([#include + #include + #include + #include + #include + #include ], + [struct s_passwd *p = getspwnam("nobody"); + const char *pw = p->pw_passwd;], + [ac_cv_hpux_passwd=yes], + [ac_cv_hpux_passwd=no])]) + if test "$ac_cv_hpux_passwd" = yes; then + have_shadow_hpux=yes + have_shadow=yes + need_setuid=yes + + # on HPUX, bigcrypt is in -lsec + AC_CHECK_LIB(sec, bigcrypt, [PASSWD_LIBS="$PASSWD_LIBS -lsec"]) + fi +fi + + +############################################################################### +# +# Check for FreeBSD-style shadow passwords. +# +# On FreeBSD, getpwnam() and friends work just like on non-shadow- +# password systems -- except you only get stuff in the pw_passwd field +# if the running program is setuid. So, guess that we've got this +# lossage to contend with if /etc/master.passwd exists, and default to +# a setuid installation. +# +############################################################################### + +if test "$with_shadow" = yes ; then + AC_CACHE_CHECK([for FreeBSD-style shadow passwords], ac_cv_master_passwd, + [if test -f /etc/master.passwd ; then + ac_cv_master_passwd=yes + else + ac_cv_master_passwd=no + fi]) + if test "$ac_cv_master_passwd" = yes; then + need_setuid=yes + fi +fi + + +############################################################################### +# +# Check for traditional (ha!) shadow passwords. +# +############################################################################### + +if test "$with_shadow" = yes ; then + AC_CACHE_CHECK([for generic shadow passwords], ac_cv_shadow, + [AC_TRY_X_COMPILE([#include + #include + #include + #include + #include ], + [struct spwd *p = getspnam("nobody"); + const char *pw = p->sp_pwdp;], + [ac_cv_shadow=yes], + [ac_cv_shadow=no])]) + if test "$ac_cv_shadow" = yes; then + have_shadow=yes + need_setuid=yes + + # On some systems (UnixWare 2.1), getspnam() is in -lgen instead of -lc. + have_getspnam=no + AC_CHECK_LIB(c, getspnam, [have_getspnam=yes]) + if test "$have_getspnam" = no ; then + AC_CHECK_LIB(gen, getspnam, + [have_getspnam=yes; PASSWD_LIBS="$PASSWD_LIBS -lgen"]) + fi + fi +fi + + +############################################################################### +# +# Check for other libraries needed for non-shadow passwords. +# +############################################################################### + +if test "$enable_locking" = yes ; then + + # On some systems (UnixWare 2.1), crypt() is in -lcrypt instead of -lc. + have_crypt=no + AC_CHECK_LIB(c, crypt, [have_crypt=yes]) + if test "$have_crypt" = no ; then + AC_CHECK_LIB(crypt, crypt, + [have_crypt=yes; PASSWD_LIBS="$PASSWD_LIBS -lcrypt"]) + fi +fi + + +# Most of the above shadow mechanisms will have set need_setuid to yes, +# if they were found. But, on some systems, we need setuid even when +# using plain old vanilla passwords. +# +if test "$enable_locking" = yes ; then + case "$host" in + *-hpux* | *-aix* | *-netbsd* | *-freebsd* | *-openbsd* ) + need_setuid=yes + ;; + esac +fi + + +if test "$have_shadow_adjunct" = yes ; then + AC_DEFINE(HAVE_ADJUNCT_PASSWD) +elif test "$have_shadow_enhanced" = yes ; then + AC_DEFINE(HAVE_ENHANCED_PASSWD) +elif test "$have_shadow_hpux" = yes ; then + AC_DEFINE(HAVE_HPUX_PASSWD) +elif test "$have_shadow" = yes ; then + AC_DEFINE(HAVE_SHADOW_PASSWD) +fi + + +############################################################################### +# +# Check for external password helper +# On SuSE, instead of having xscreensaver be a setuid program, they +# fork an external program that takes the password on stdin, and +# returns true if that password is a valid one. Then only that +# smaller program needs to be setuid. +# +# (Note that this external program is not a GUI: the GUI is still +# all in xscreensaver itself; the external program just does auth.) +# +############################################################################### + +have_passwd_helper=no +with_passwd_helper_req=unspecified + +AC_ARG_WITH(passwd-helper, +[ --with-passwd-helper Include support for an external password + verification helper program.], + [with_passwd_helper="$withval"; with_passwd_helper_req="$withval"],[with_passwd_helper=no]) +# no HANDLE_X_PATH_ARG for this one + +if test "$enable_locking" = no ; then + with_passwd_helper_req=no + with_passwd_helper=no +fi + +case "$with_passwd_helper" in + ""|no) : ;; + /*) + AC_DEFINE_UNQUOTED(PASSWD_HELPER_PROGRAM, "$with_passwd_helper") + have_passwd_helper=yes;; + *) + echo "error: --with-passwd-helper needs full pathname of helper (not '$with_passwd_helper')." >&2 + exit 1 +esac + + +############################################################################### +# +# Check for a login manager for a "New Login" button on the lock dialog. +# Usually this will be "/usr/bin/gdmflexiserver". +# +############################################################################### + +with_login_manager_req=unspecified +default_login_manager_1='gdmflexiserver -ls' +default_login_manager_2='kdmctl reserve' + +AC_ARG_WITH(login-manager, +[ --with-login-manager Put a "New Login" button on the unlock dialog that + runs a login manager like gdmflexiserver or kdmctl.], + [with_login_manager="$withval"; with_login_manager_req="$withval"], + [with_login_manager=yes]) +# no HANDLE_X_PATH_ARG for this one + +if test "$enable_locking" = no ; then + with_login_manager_req=no + with_login_manager=no +fi + +case "$with_login_manager_req" in + no) + with_login_manager="" + ;; + + yes|unspecified) + # Try both defaults, use the one that exists. + + set dummy $default_login_manager_1 ; login_manager_tmp=$2 + unset ac_cv_path_login_manager_tmp # don't cache + AC_PATH_PROG(login_manager_tmp, $login_manager_tmp, []) + if test ! -z "$login_manager_tmp" ; then + with_login_manager="$default_login_manager_1" + else + set dummy $default_login_manager_2 ; login_manager_tmp=$2 + unset ac_cv_path_login_manager_tmp # don't cache + AC_PATH_PROG(login_manager_tmp, $login_manager_tmp, []) + if test ! -z "$login_manager_tmp" ; then + with_login_manager="$default_login_manager_2" + else + with_login_manager="" + fi + fi + ;; + + /*) + # absolute path specified on cmd line + set dummy $with_login_manager_req ; login_manager_tmp=$2 + AC_MSG_CHECKING([for $login_manager_tmp]) + if test -x "$login_manager_tmp" ; then + AC_MSG_RESULT(yes) + else + AC_MSG_RESULT(no) + with_login_manager="" + fi + ;; + + *) + # relative path specified on cmd line + set dummy $with_login_manager_req ; login_manager_tmp=$2 + unset ac_cv_path_login_manager_tmp # don't cache + AC_PATH_PROG(login_manager_tmp, $login_manager_tmp, []) + if test -z "$login_manager_tmp" ; then + with_login_manager="" + else + with_login_manager="$login_manager_tmp" + fi + ;; +esac +ac_cv_login_manager_program="$with_login_manager" + +NEW_LOGIN_COMMAND_P='' +NEW_LOGIN_COMMAND="$ac_cv_login_manager_program" + +AC_MSG_CHECKING(for login manager) +if test -z "$NEW_LOGIN_COMMAND" ; then + NEW_LOGIN_COMMAND="$default_login_manager_1" + NEW_LOGIN_COMMAND_P='! ' + AC_MSG_RESULT($NEW_LOGIN_COMMAND (disabled)) +else + AC_MSG_RESULT($NEW_LOGIN_COMMAND) +fi + + +############################################################################### +# +# Check for -lgtk (and Gnome stuff) +# +############################################################################### + +have_gtk=no +with_gtk_req=unspecified +AC_ARG_WITH(gtk,[ +User interface options: + + --with-gtk Use the Gtk toolkit for the user interface.], + [with_gtk="$withval"; with_gtk_req="$withval"],[with_gtk=yes]) + +# if --with-gtk=/directory/ was specified, remember that directory so that +# we can also look for the `gtk-config' program in that directory. +case "$with_gtk" in + /*) + gtk_dir="$with_gtk" + ;; + *) + gtk_dir="" + ;; +esac + +HANDLE_X_PATH_ARG(with_gtk, --with-gtk, Gtk) + +if test "$with_gtk" != yes -a "$with_gtk" != no ; then + echo "error: must be yes or no: --with-gtk=$with_gtk" + exit 1 +fi + + +parse_gtk_version_string() { + # M4 sucks!! + changequote(X,Y) + maj=`echo $ac_gtk_version_string | sed -n 's/\..*//p'` + min=`echo $ac_gtk_version_string | sed -n 's/[^.]*\.\([^.]*\).*/\1/p'` + changequote([,]) + ac_gtk_version=`echo "$maj * 1000 + $min" | bc` + if test -z "$ac_gtk_version"; then + ac_gtk_version=unknown + ac_gtk_version_string=unknown + fi +} + +# Find pkg-config... (need this for both gtk and gdk_pixbuf.) +# if the user specified --with-gtk=/foo/ then look there. +# +gtk_path="$PATH" +if test ! -z "$gtk_dir"; then + # canonicalize slashes. + foo=`echo "${gtk_dir}/bin" | sed 's@//*@/@g'` + gtk_path="$foo:$gtk_path" +fi + +AC_PATH_PROGS(pkg_config, pkg-config,, $gtk_path) + +if test -z "$pkg_config" ; then + AC_MSG_WARN([pkg-config not found!]) + pkg_config="false" +fi + + +# Utility function for running pkg-config-based tests... +# +pkgs='' +pkg_check_version() { + if test "$ok" = yes ; then + req="$1" + min="$2" + AC_MSG_CHECKING(for $req) + if $pkg_config --exists "$req" ; then + vers=`$pkg_config --modversion "$req"` + if $pkg_config --exists "$req >= $min" ; then + AC_MSG_RESULT($vers) + pkgs="$pkgs $req" + return 1 + else + AC_MSG_RESULT($vers (wanted >= $min)) + ok=no + return 0 + fi + else + AC_MSG_RESULT(no) + ok=no + return 0 + fi + fi +} + + +jurassic_gtk=no +gtk_halfassed=no + +if test "$with_gtk" = yes; then + have_gtk=no + + ok="yes" + pkg_check_version gtk+-2.0 2.0.1 ; ac_gtk_version_string="$vers" + pkg_check_version gmodule-2.0 2.0.0 + pkg_check_version libxml-2.0 2.4.6 + pkg_check_version libglade-2.0 1.99.0 + pkg_check_version gdk-pixbuf-2.0 2.0.0 + pkg_check_version gdk-pixbuf-xlib-2.0 2.0.0 + have_gtk="$ok" + + if test "$have_gtk" = no; then + if test -n "$ac_gtk_version_string" ; then + gtk_halfassed="$ac_gtk_version_string" + gtk_halfassed_lib="$req" + fi + fi + + if test "$have_gtk" = yes; then + parse_gtk_version_string + jurassic_gtk=no + fi + + if test "$have_gtk" = yes; then + AC_CACHE_CHECK([for Gtk includes], ac_cv_gtk_config_cflags, + [ac_cv_gtk_config_cflags=`$pkg_config --cflags $pkgs`]) + AC_CACHE_CHECK([for Gtk libs], ac_cv_gtk_config_libs, + [ac_cv_gtk_config_libs=`$pkg_config --libs $pkgs`]) + fi + + ac_gtk_config_cflags=$ac_cv_gtk_config_cflags + ac_gtk_config_libs=$ac_cv_gtk_config_libs + + GTK_EXTRA_OBJS="" + GTK_DATADIR="" + if test "$have_gtk" = yes; then + GTK_DATADIR=`$pkg_config --variable=prefix gtk+-2.0` + GTK_DATADIR="$GTK_DATADIR/share" + fi + + if test "$have_gtk" = yes; then + INCLUDES="$INCLUDES $ac_gtk_config_cflags" + GTK_LIBS="$GTK_LIBS $ac_gtk_config_libs" + AC_DEFINE(HAVE_GTK) + AC_DEFINE(HAVE_GTK2) + AC_DEFINE(HAVE_XML) + fi + +fi + + +# Check for the various Gnome help and URL loading programs. +# +WITH_BROWSER=gnome-open +if test "$have_gtk" = yes; then + AC_CHECK_PROGS(gnome_open_program, gnome-open) + AC_CHECK_PROGS(gnome_url_show_program, gnome-url-show) +fi + + +############################################################################### +# +# Check for -lXm. +# +############################################################################### + +have_motif=no +with_motif_req=unspecified +AC_ARG_WITH(motif,[ --with-motif Use the Motif toolkit for the user interface + (no longer supported.)], + [with_motif="$withval"; with_motif_req="$withval"],[with_motif=no]) + +HANDLE_X_PATH_ARG(with_motif, --with-motif, Motif) + +if test "$with_motif" != yes -a "$with_motif" != no ; then + echo "error: must be yes or no: --with-motif=$with_motif" + exit 1 +fi + +if test "$with_motif" = yes; then + have_motif=no + AC_CHECK_X_HEADER(Xm/Xm.h, + [have_motif=yes + AC_DEFINE(HAVE_MOTIF) + MOTIF_LIBS="$MOTIF_LIBS -lXm"],, + [#include + #include + #include ]) +fi + + +if test "$have_motif" = yes; then + AC_CHECK_X_HEADER(Xm/ComboBox.h, [AC_DEFINE(HAVE_XMCOMBOBOX)],, + [#include + #include + #include ]) +fi + + +############################################################################### +# +# Checking whether Motif is really Lesstif. +# +############################################################################### + +have_lesstif=no +if test "$have_motif" = yes ; then + AC_CACHE_CHECK([whether Motif is really LessTif], + ac_cv_have_lesstif, + [AC_TRY_X_COMPILE([#include ], + [long vers = LesstifVersion;], + [ac_cv_have_lesstif=yes], + [ac_cv_have_lesstif=no])]) + have_lesstif=$ac_cv_have_lesstif +fi + + +lesstif_version=unknown +lesstif_version_string=unknown + +if test "$have_lesstif" = yes ; then + ltv=unknown + echo unknown > conftest-lt + AC_CACHE_CHECK([LessTif version number], + ac_cv_lesstif_version_string, + [AC_TRY_X_RUN([#include + #include + int main() { + FILE *f = fopen("conftest-lt", "w"); + if (!f) exit(1); + fprintf(f, "%d %d.%d\n", LesstifVersion, + LESSTIF_VERSION, LESSTIF_REVISION); + fclose(f); + exit(0); + }], + [ltv=`cat conftest-lt` + ac_cv_lesstif_version=`echo $ltv | sed 's/ .*//'` + ac_cv_lesstif_version_string=`echo $ltv | sed 's/.* //'`], + [ac_cv_lesstif_version=unknown + ac_cv_lesstif_version_string=unknown], + [ac_cv_lesstif_version=unknown + ac_cv_lesstif_version_string=unknown])]) + rm -f conftest-lt + lesstif_version=$ac_cv_lesstif_version + lesstif_version_string=$ac_cv_lesstif_version_string + +fi + + +if test "$have_motif" = yes ; then + mtv=unknown + echo unknown > conftest-mt + AC_CACHE_CHECK([Motif version number], + ac_cv_motif_version_string, + [AC_TRY_X_RUN([#include + #include + int main() { + FILE *f = fopen("conftest-mt", "w"); + if (!f) exit(1); + fprintf(f, "%d %d.%d\n", XmVersion, + XmVERSION, XmREVISION); + fclose(f); + exit(0); + }], + [mtv=`cat conftest-mt` + ac_cv_motif_version=`echo $mtv | sed 's/ .*//'` + ac_cv_motif_version_string=`echo $mtv | sed 's/.* //'`], + [ac_cv_motif_version=unknown + ac_cv_motif_version_string=unknown], + [ac_cv_motif_version=unknown + ac_cv_motif_version_string=unknown])]) + rm -f conftest-mt + motif_version=$ac_cv_motif_version + motif_version_string=$ac_cv_motif_version_string + +fi + + +############################################################################### +# +# Checking whether Motif requires -lXpm. +# +# If this is Motif 2.x, and we have XPM, then link against XPM as well. +# The deal is, Motif 2.x requires XPM -- but it's a compilation option +# of the library whether to build the XPM code into libXm, or whether +# to rely on an external libXm. So the only way to tell whether XPM is +# a link-time requirement is to examine libXm.a, which is very +# difficult to do in an autoconf script. So... if it's Motif 2.x, we +# always link against XPM if the XPM lib exists (and this will be a +# no-op if libXm happens to already have the XPM code in it.) +# +############################################################################### + +motif_requires_xpm=no +if test "$have_motif" = yes ; then + AC_MSG_CHECKING(whether Motif requires XPM) + if test "$motif_version" = "unknown" || test "$motif_version" -ge 2000 + then + motif_requires_xpm=yes + AC_MSG_RESULT(maybe) + else + AC_MSG_RESULT(no) + fi +fi + + +############################################################################### +# +# Checking whether Motif requires -lXp. +# +# Some versions of Motif (2.1.0, at least) require -lXp, the "X Printing +# Extension". Why this extension isn't in -lXext with all the others, +# I have no idea. +# +############################################################################### + +have_xp_ext=no +if test "$have_motif" = yes ; then + have_xp_ext=no + AC_CHECK_X_LIB(Xp, XpQueryExtension, + [have_xp_ext=yes; MOTIF_LIBS="$MOTIF_LIBS -lXp"], + [true], -lX11 -lXext -lm) +fi + + +############################################################################### +# +# Checking whether Motif requires -lXintl (for _Xsetlocale.) +# +############################################################################### + +have_xintl=no +if test "$have_motif" = yes ; then + AC_CHECK_X_LIB(Xintl, _Xsetlocale, [have_xintl=yes], [have_xintl=no], + -lX11 -lXext -lm) + if test "$have_xintl" = yes; then + MOTIF_LIBS="$MOTIF_LIBS -lXintl" + fi +fi + + +############################################################################### +# +# Check for -lGL or -lMesaGL. +# +############################################################################### + +have_gl=no +ac_have_mesa_gl=no +with_gl_req=unspecified +gl_halfassed=no +AC_ARG_WITH(gl,[ +Graphics options: + + --with-gl Build those demos which depend on OpenGL.], + [with_gl="$withval"; with_gl_req="$withval"],[with_gl=yes]) + +HANDLE_X_PATH_ARG(with_gl, --with-gl, GL) + +ac_mesagl_version=unknown +ac_mesagl_version_string=unknown + +if test "$with_gl" = yes; then + AC_CHECK_X_HEADER(GL/gl.h, have_gl=yes, have_gl=no) + if test "$have_gl" = yes ; then + AC_CHECK_X_HEADER(GL/glx.h, have_gl=yes, have_gl=no, + [#include ]) + fi + + # If we have the headers, try and figure out which vendor it's from. + # + if test "$have_gl" = yes ; then + + # We need to know whether it's MesaGL so that we know which libraries + # to link against. + # + AC_CACHE_CHECK([whether GL is really MesaGL], ac_cv_have_mesa_gl, + [ac_cv_have_mesa_gl=no + if test "$ac_macosx" = no; then + # WTF! MacOS 10.5.0 ships the Mesa GL headers! + # It's not really Mesa, is it? + AC_EGREP_X_HEADER(Mesa|MESA, GL/glx.h, [ac_cv_have_mesa_gl=yes]) + fi]) + ac_have_mesa_gl=$ac_cv_have_mesa_gl + + gl_lib_1="" + GL_LIBS="" + + if test "$ac_macosx" = yes; then + + # Without these, every link against libGL gets a bunch of useless + # warnings. + # + osx_crud="-bind_at_load -multiply_defined suppress" + AC_MSG_RESULT(adding "$osx_crud" to GL_LIBS) + GL_LIBS="$GL_LIBS $osx_crud" + unset osx_crud + + # New lossage in 10.5.0: without this, we get: + # ld: cycle in dylib re-exports with /usr/X11/lib/libGL.dylib + # + osx_crud="/System/Library/Frameworks/OpenGL.framework/Versions/A/Libraries/libGL.dylib" + osx_crud="-Wl,-dylib_file,${osx_crud}:${osx_crud}" + + AC_MSG_RESULT(adding "$osx_crud" to GL_LIBS) + GL_LIBS="$GL_LIBS $osx_crud" + unset osx_crud + + # New lossage in 10.6.8: we can't allow -L/opt/local/lib to be in the + # link line, or at runtime XQueryExtension gets a segv due to some kind + # of library version skew. Libs must come from /usr/X11/lib even if + # $prefix and/or $exec_prefix are set to /opt/local/. + # + AC_MSG_RESULT(omitting "$libdir" from LDFLAGS) + libdir='' + + fi + + + # Some versions of MesaGL are compiled to require -lpthread. + # So if the Mesa headers exist, and -lpthread exists, then always + # link -lpthread after the Mesa libs (be they named -lGL or -lMesaGL.) + # + if test "$ac_have_mesa_gl" = yes; then + AC_CHECK_LIB(pthread, pthread_create, [GL_LIBS="-lpthread"], [],) + fi + + + # If we have Mesa headers, check to see if we can link against -lMesaGL. + # If we don't have Mesa headers, or we don't have -lMesaGL, try -lGL. + # Else, warn that GL is busted. (We have the headers, but no libs.) + # + + if test "$ac_have_mesa_gl" = yes ; then + AC_CHECK_X_LIB(MesaGL, glXCreateContext, + [gl_lib_1="MesaGL" + GL_LIBS="-lMesaGL -lMesaGLU $VIDMODE_LIBS $GL_LIBS"], + [], -lMesaGLU $GL_LIBS -lX11 -lXext $VIDMODE_LIBS -lm) + fi + + if test "$gl_lib_1" = "" ; then + AC_CHECK_X_LIB(GL, glXCreateContext, + [gl_lib_1="GL" + GL_LIBS="-lGL -lGLU $VIDMODE_LIBS $GL_LIBS"], + [], -lGLU $GL_LIBS -lX11 -lXext $VIDMODE_LIBS -lm) + fi + + if test "$gl_lib_1" = "" ; then + # we have headers, but no libs -- bail. + have_gl=no + ac_have_mesa_gl=no + gl_halfassed=yes + else + # linking works -- we can build the GL hacks. + AC_DEFINE(HAVE_GL) + if test "$ac_have_mesa_gl" = yes ; then + AC_DEFINE(HAVE_MESA_GL) + fi + fi + fi + + + # Now that we know we have GL headers and libs, do some more GL testing. + # + + if test "$have_gl" = yes ; then + # If it's MesaGL, we'd like to issue a warning if the version number + # is less than or equal to 2.6, because that version had a security bug. + # + if test "$ac_have_mesa_gl" = yes; then + + AC_CACHE_CHECK([MesaGL version number], ac_cv_mesagl_version_string, + [cat > conftest.$ac_ext < +#ifndef MESA_MAJOR_VERSION +# include +# ifdef XMESA_MAJOR_VERSION + /* Around Mesa 3.2, they took out the Mesa version number, so instead, + we have to check the XMesa version number (the number of the X protocol + support, which seems to be the same as the Mesa version number.) + */ +# define MESA_MAJOR_VERSION XMESA_MAJOR_VERSION +# define MESA_MINOR_VERSION XMESA_MINOR_VERSION +# else + /* Oh great. Some time after 3.4, they took out the xmesa.h header file, + so we have no way of telling what version of Mesa this is at all. + So, we'll guess that the osmesa version (the "offscreen protocol") + is less than or equal to the real mesa version number. Except that + if OSmesa is 3.3, assume at least Mesa 3.4, since OSmesa was 3.3 in + Mesa 3.4. And Mesa 3.3 had xmesa.h. What a complete load of shit! + */ +# include +# define MESA_MAJOR_VERSION OSMESA_MAJOR_VERSION +# define MESA_MINOR_VERSION OSMESA_MINOR_VERSION or newer, probably? +# if OSMESA_MAJOR_VERSION == 3 && OSMESA_MINOR_VERSION == 3 +# undef MESA_MINOR_VERSION +# define MESA_MINOR_VERSION 4 or newer, probably? +# endif +# endif +#endif +configure: MESA_MAJOR_VERSION MESA_MINOR_VERSION +EOF + + ac_save_CPPFLAGS="$CPPFLAGS" + if test \! -z "$includedir" ; then + CPPFLAGS="$CPPFLAGS -I$includedir" + fi + CPPFLAGS="$CPPFLAGS $X_CFLAGS" + + mglv=`(eval "$ac_cpp conftest.$ac_ext") 2>&AC_FD_CC | grep configure:` + + # M4 sucks!! + changequote(X,Y) + mglv=`echo "$mglv" | sed -n \ + 's/^configure: *\([0-9][0-9]*\) *\([0-9].*\)$/\1.\2/p'` + changequote([,]) + + rm -f conftest.$ac_ext + + CPPFLAGS="$ac_save_CPPFLAGS" + + if test "$mglv" = ""; then + ac_mesagl_version=unknown + ac_mesagl_version_string=unknown + else + ac_mesagl_version_string="$mglv" + # M4 sucks!! + changequote(X,Y) + maj=`echo "$mglv" | sed -n 's/^\([0-9][0-9]*\)\..*$/\1/p'` + min=`echo "$mglv" | sed -n 's/^.*\.\([0-9][0-9]*\).*$/\1/p'` + changequote([,]) + ac_mesagl_version=`echo "$maj * 1000 + $min" | bc` + if test -z "$ac_mesagl_version"; then + ac_mesagl_version=unknown + ac_mesagl_version_string=unknown + fi + fi + ac_cv_mesagl_version=$ac_mesagl_version + ac_cv_mesagl_version_string=$ac_mesagl_version_string + ]) + ac_mesagl_version=$ac_cv_mesagl_version + ac_mesagl_version_string=$ac_cv_mesagl_version_string + fi + + + # Check for OpenGL 1.1 features. + # + AC_CHECK_X_LIB($gl_lib_1, glBindTexture, [AC_DEFINE(HAVE_GLBINDTEXTURE)], + [true], $GL_LIBS -lX11 -lXext -lm) + fi + +elif test "$with_gl" != no; then + echo "error: must be yes or no: --with-gl=$with_gl" + exit 1 +fi + + +############################################################################### +# +# Check for -lgle. +# +############################################################################### + +have_gle=no +with_gle_req=unspecified +gle_halfassed=no +AC_ARG_WITH(gle, +[ --with-gle Build those demos which depend on GLE + (the OpenGL "extrusion" library.)], + [with_gle="$withval"; with_gle_req="$withval"],[with_gle=yes]) + +HANDLE_X_PATH_ARG(with_gle, --with-gle, GLE) + +GLE_LIBS="" + +if test "$have_gl" = no ; then + true +elif test "$with_gle" = yes; then + + AC_CHECK_X_HEADER(GL/gle.h, have_gle3=yes, have_gle3=no, + [#include ]) + if test "$have_gle3" = yes ; then + have_gle=yes; + else + AC_CHECK_X_HEADER(GL/gutil.h, have_gle=yes, have_gle=no, + [#include ]) + if test "$have_gle" = yes ; then + AC_CHECK_X_HEADER(GL/tube.h, have_gle=yes, have_gle=no, + [#include ]) + fi + fi + + if test "$have_gle" = yes ; then + have_gle=no + gle_halfassed=yes + AC_CHECK_X_LIB(gle, gleCreateGC, + [have_gle=yes; gle_halfassed=no; GLE_LIBS="-lgle"], + [], $GL_LIBS -lX11 -lXext -lm) + fi + if test "$have_gle" = yes ; then + have_gle=no + gle_halfassed=yes + + # sometimes the libmatrix stuff is included in libgle. look there first. +# +# I don't get it. For some reason, this test passes on SGI, as if +# uview_direction_d() was in libgle -- but it's not, it's in libmatrix. +# Yet the link is succeeding. Why??? +# +# AC_CHECK_X_LIB(gle, uview_direction_d, +# [have_gle=yes; gle_halfassed=no], +# [], $GL_LIBS -lX11 -lXext -lm) + + # As of GLE 3 this is in libgle, and has changed name to uview_direction! + # *sigh* + if test "$have_gle3" = yes ; then + AC_CHECK_X_LIB(gle, uview_direction, + [have_gle=yes; gle_halfassed=no], + [], $GL_LIBS -lX11 -lXext -lm) + fi + # if it wasn't in libgle, then look in libmatrix. + if test "$have_gle" = no ; then + AC_CHECK_X_LIB(matrix, uview_direction_d, + [have_gle=yes; gle_halfassed=no; + GLE_LIBS="$GLE_LIBS -lmatrix"], + [], $GL_LIBS -lX11 -lXext -lm) + fi + fi + + if test "$have_gle" = yes ; then + AC_DEFINE(HAVE_GLE) + if test "$have_gle3" = yes ; then + AC_DEFINE(HAVE_GLE3) + fi + fi + +elif test "$with_gle" != no; then + echo "error: must be yes or no: --with-gle=$with_gle" + exit 1 + +fi + + +############################################################################### +# +# Handle --with-gles +# +############################################################################### + +with_gles_req=unspecified +AC_ARG_WITH(gles, +[ --with-gles Target OpenGL ES 1.x API instead of OpenGL 1.3.], + [with_gles="$withval"; with_gles_req="$withval"],[with_gles=no]) + +HANDLE_X_PATH_ARG(with_gles, --with-gles, JWZGLES) + +if test "$with_gles" = yes; then + have_gles=yes + AC_DEFINE(HAVE_JWZGLES) + JWZGLES_OBJS="jwzgles.o" + AC_MSG_RESULT(using OpenGL ES compatiblity shim) +elif test "$with_gles" != no; then + echo "error: must be yes or no: --with-gles=$with_xpm" + exit 1 +fi + +# May want to phase out glBitmap even in a non-GLES world. +# +if test "$have_gles" = yes; then + GLFPS_OBJS="fps-gl.o glxfonts.o texfont.o" + GLFONT_OBJS="" +else + AC_DEFINE(HAVE_GLBITMAP) + GLFPS_OBJS="fps-gl.o glxfonts.o" + GLFONT_OBJS="texfont.o" +fi + + +############################################################################### +# +# Check for -lgdk_pixbuf. +# These tests are for gdk_pixbuf usage of the hacks, +# not xscreensaver-demo (thus we have to test again to get +# the libraries right: don't want to pull in all of GTK +# for the hacks.) +# +############################################################################### + +have_gdk_pixbuf=no +with_gdk_pixbuf_req=unspecified +AC_ARG_WITH(pixbuf, +[ --with-pixbuf Include support for the GDK-Pixbuf library in some + demos, which will make it possible for them to read + GIF, JPEG, and PNG files as well.], + [with_gdk_pixbuf="$withval"; with_gdk_pixbuf_req="$withval"], + [with_gdk_pixbuf=yes]) + +# if --with-pixbuf=/directory/ was specified, remember that directory so that +# we can also look for the `gdk-pixbuf-config' program in that directory. +case "$with_gdk_pixbuf" in + /*) + gdk_pixbuf_dir="$with_gdk_pixbuf" + ;; + *) + gdk_pixbuf_dir="" + ;; +esac + +HANDLE_X_PATH_ARG(with_gdk_pixbuf, --with-pixbuf, GDK_PIXBUF) + +if test "$with_gdk_pixbuf" != yes -a "$with_gdk_pixbuf" != no ; then + echo "error: must be yes or no: --with-pixbuf=$with_gdk_pixbuf" + exit 1 +fi + +if test "$with_gdk_pixbuf" = yes; then + have_gdk_pixbuf=no + + pkgs='' + ok="yes" + + pkg_check_version gdk-pixbuf-2.0 2.0.0 + pkg_check_version gdk-pixbuf-xlib-2.0 2.0.0 + have_gdk_pixbuf="$ok" + + if test "$have_gdk_pixbuf" = yes; then + AC_CACHE_CHECK([for gdk-pixbuf includes], ac_cv_gdk_pixbuf_config_cflags, + [ac_cv_gdk_pixbuf_config_cflags=`$pkg_config --cflags $pkgs`]) + AC_CACHE_CHECK([for gdk-pixbuf libs], ac_cv_gdk_pixbuf_config_libs, + [ac_cv_gdk_pixbuf_config_libs=`$pkg_config --libs $pkgs`]) + fi + + ac_gdk_pixbuf_config_cflags=$ac_cv_gdk_pixbuf_config_cflags + ac_gdk_pixbuf_config_libs=$ac_cv_gdk_pixbuf_config_libs + + + if test "$have_gdk_pixbuf" = yes; then + # + # we appear to have pixbuf; check for headers/libs to be sure. + # + ac_save_gdk_pixbuf_CPPFLAGS="$CPPFLAGS" + CPPFLAGS="$CPPFLAGS $ac_gdk_pixbuf_config_cflags" + + have_gdk_pixbuf=no + + # check for header A... + AC_CHECK_X_HEADER(gdk-pixbuf/gdk-pixbuf.h, [have_gdk_pixbuf=yes]) + + # if that worked, check for header B... + if test "$have_gdk_pixbuf" = yes; then + have_gdk_pixbuf=no + gdk_pixbuf_halfassed=yes + AC_CHECK_X_HEADER(gdk-pixbuf/gdk-pixbuf-xlib.h, + [have_gdk_pixbuf=yes + gdk_pixbuf_halfassed=no]) + + # yay, it has a new name in Gtk 2.x... + if test "$have_gdk_pixbuf" = no; then + have_gdk_pixbuf=no + gdk_pixbuf_halfassed=yes + AC_CHECK_X_HEADER(gdk-pixbuf-xlib/gdk-pixbuf-xlib.h, + [have_gdk_pixbuf=yes + gdk_pixbuf_halfassed=no]) + fi + fi + CPPFLAGS="$ac_save_gdk_pixbuf_CPPFLAGS" + fi + + if test "$have_gdk_pixbuf" = yes; then + # we have the headers, now check for the libraries + have_gdk_pixbuf=no + gdk_pixbuf_halfassed=yes + + AC_MSG_RESULT(checking for gdk_pixbuf usability...) + + # library A... + AC_CHECK_X_LIB(c, gdk_pixbuf_new_from_file, [have_gdk_pixbuf=yes],, + $ac_gdk_pixbuf_config_libs -lX11 -lXext -lm) + # library B... + if test "$have_gdk_pixbuf" = yes; then + have_gdk_pixbuf=no + AC_CHECK_X_LIB(c, gdk_pixbuf_xlib_init, + [have_gdk_pixbuf=yes + gdk_pixbuf_halfassed=no],, + $ac_gdk_pixbuf_config_libs -lX11 -lXext -lm) + fi + fi + + if test "$have_gdk_pixbuf" = yes; then + INCLUDES="$INCLUDES $ac_gdk_pixbuf_config_cflags" + XPM_LIBS="$ac_gdk_pixbuf_config_libs" + AC_DEFINE(HAVE_GDK_PIXBUF) + else + AC_MSG_RESULT(checking for gdk_pixbuf usability... no) + fi + + if test "$have_gdk_pixbuf" = yes; then + AC_CHECK_X_LIB(c, gdk_pixbuf_apply_embedded_orientation, + [AC_DEFINE(HAVE_GDK_PIXBUF_APPLY_EMBEDDED_ORIENTATION)],, + $ac_gdk_pixbuf_config_libs -lX11 -lXext -lm) + fi +fi + + +############################################################################### +# +# Check for -lXpm. +# +############################################################################### + +have_xpm=no +with_xpm_req=unspecified +AC_ARG_WITH(xpm, +[ --with-xpm Include support for XPM files in some demos. + (Not needed if Pixbuf is used.)], + [with_xpm="$withval"; with_xpm_req="$withval"],[with_xpm=yes]) + +HANDLE_X_PATH_ARG(with_xpm, --with-xpm, XPM) + +if test "$with_xpm" = yes; then + AC_CHECK_X_HEADER(X11/xpm.h, + [have_xpm=yes + AC_DEFINE(HAVE_XPM) + XPM_LIBS="-lXpm $XPM_LIBS"],, + [#include ]) +elif test "$with_xpm" != no; then + echo "error: must be yes or no: --with-xpm=$with_xpm" + exit 1 +fi + +# See comment near $motif_requires_xpm, above. +# Need to do this here, after both Motif and XPM have been checked for. +# +if test "$have_motif" = yes -a "$have_xpm" = yes ; then + if test "$motif_requires_xpm" = yes ; then + MOTIF_LIBS="$MOTIF_LIBS $XPM_LIBS" + fi +fi + +if test "$XPM_LIBS" = "" ; then + XPM_LIBS=$(MINIXPM) +fi + + +############################################################################### +# +# Check for -ljpeg +# +############################################################################### + +have_jpeg=no +with_jpeg_req=unspecified +jpeg_halfassed=no +AC_ARG_WITH(jpeg, +[ --with-jpeg Include support for the JPEG library.], + [with_jpeg="$withval"; with_jpeg_req="$withval"], + [with_jpeg=yes]) + +HANDLE_X_PATH_ARG(with_jpeg, --with-jpeg, JPEG) + +if test "$with_jpeg" != yes -a "$with_jpeg" != no ; then + echo "error: must be yes or no: --with-jpeg=$with_jpeg" + exit 1 +fi + +if test "$with_jpeg" = yes; then + + have_jpeg=no + AC_CHECK_X_HEADER(jpeglib.h, [have_jpeg=yes]) + + if test "$have_jpeg" = yes; then + # we have the header, now check for the library + have_jpeg=no + jpeg_halfassed=yes + AC_CHECK_X_LIB(jpeg, jpeg_start_compress, + [have_jpeg=yes + jpeg_halfassed=no + JPEG_LIBS="-ljpeg" + AC_DEFINE(HAVE_JPEGLIB)]) + fi +fi + + +############################################################################### +# +# Check for pty support: this allows 'phosphor' and 'apple2' +# to run curses-based programs, or be used as terminal windows. +# +############################################################################### + +PTY_LIBS= +AC_CHECK_HEADERS(pty.h util.h) +AC_CHECK_X_LIB(util, forkpty, + [PTY_LIBS="-lutil" + ac_have_forkpty=yes + AC_DEFINE(HAVE_FORKPTY)]) + +if test "$ac_have_forkpty" != yes ; then + # we don't need (or have) -lutil on MacOS 10.4.2... + AC_CHECK_X_LIB(c, forkpty, + [PTY_LIBS="" + AC_DEFINE(HAVE_FORKPTY)]) +fi + +############################################################################### +# +# Check for the XSHM server extension. +# +############################################################################### + +have_xshm=no +with_xshm_req=unspecified +AC_ARG_WITH(xshm-ext, +[ --with-xshm-ext Include support for the Shared Memory extension.], + [with_xshm="$withval"; with_xshm_req="$withval"],[with_xshm=yes]) + +HANDLE_X_PATH_ARG(with_xshm, --with-xshm-ext, XSHM) + +if test "$with_xshm" = yes; then + + # first check for Xshm.h. + AC_CHECK_X_HEADER(X11/extensions/XShm.h, [have_xshm=yes],, + [#include ]) + + # if that succeeded, then check for sys/ipc.h. + if test "$have_xshm" = yes; then + have_xshm=no + AC_CHECK_X_HEADER(sys/ipc.h, [have_xshm=yes]) + fi + + # if that succeeded, then check for sys/shm.h. + if test "$have_xshm" = yes; then + have_xshm=no + AC_CHECK_X_HEADER(sys/shm.h, [have_xshm=yes]) + fi + + # AIX is pathological, as usual: apparently it's normal for the Xshm headers + # to exist, but the library code to not exist. And even better, the library + # code is in its own library: libXextSam.a. So, if we're on AIX, and that + # lib doesn't exist, give up. (This lib gets added to X_EXTRA_LIBS, and + # that's not quite right, but close enough.) + # + case "$host" in + *-aix*) + if [ `uname -v` -eq 3 ]; then + have_xshm=no + AC_CHECK_X_LIB(XextSam, XShmQueryExtension, + [have_xshm=yes; X_EXTRA_LIBS="$X_EXTRA_LIBS -lXextSam"], + [true], -lX11 -lXext -lm) + fi + ;; + esac + + # if that succeeded, then we've really got it. + if test "$have_xshm" = yes; then + AC_DEFINE(HAVE_XSHM_EXTENSION) + fi + +elif test "$with_xshm" != no; then + echo "error: must be yes or no: --with-xshm-ext=$with_xshm" + exit 1 +fi + + +############################################################################### +# +# Check for the DOUBLE-BUFFER server extension. +# +############################################################################### + +have_xdbe=no +with_xdbe_req=unspecified +AC_ARG_WITH(xdbe-ext, +[ --with-xdbe-ext Include support for the DOUBLE-BUFFER extension.], + [with_xdbe="$withval"; with_xdbe_req="$withval"],[with_xdbe=yes]) + +HANDLE_X_PATH_ARG(with_xdbe, --with-xdbe-ext, DOUBLE-BUFFER) + +if test "$with_xdbe" = yes; then + + AC_CHECK_X_HEADER(X11/extensions/Xdbe.h, [have_xdbe=yes],, + [#include ]) + if test "$have_xdbe" = yes; then + AC_DEFINE(HAVE_DOUBLE_BUFFER_EXTENSION) + fi + +elif test "$with_xdbe" != no; then + echo "error: must be yes or no: --with-xdbe-ext=$with_xshm" + exit 1 +fi + + +############################################################################### +# +# Check for the SGI XReadDisplay server extension. +# +# Note: this has to be down here, rather than up with the other server +# extension tests, so that the output of `configure --help' is in the +# right order. Arrgh! +# +############################################################################### + +have_readdisplay=no +with_readdisplay_req=unspecified +AC_ARG_WITH(readdisplay, +[ --with-readdisplay Include support for the XReadDisplay extension.], + [with_readdisplay="$withval"; with_readdisplay_req="$withval"], + [with_readdisplay=yes]) + +HANDLE_X_PATH_ARG(with_readdisplay, --with-readdisplay, XReadDisplay) + +if test "$with_readdisplay" = yes; then + AC_CHECK_X_HEADER(X11/extensions/readdisplay.h, + AC_DEFINE(HAVE_READ_DISPLAY_EXTENSION),, + [#include ]) +elif test "$with_readdisplay" != no; then + echo "error: must be yes or no: --with-readdisplay=$with_readdisplay" + exit 1 +fi + + +############################################################################### +# +# Check for a directory full of images to use as the default value +# of the "imageDirectory" preference. +# +############################################################################### + +have_imagedir=no +with_imagedir_req=unspecified + +AC_ARG_WITH(image-directory, +[ --with-image-directory Arg is the default directory from which some demos + will choose random images to display.], + [with_imagedir="$withval"; with_imagedir_req="$withval"], + [with_imagedir=yes]) +# no HANDLE_X_PATH_ARG for this one + +case "$with_imagedir" in + /*) + # absolute path + AC_MSG_CHECKING([for image directory $with_imagedir]) + if test -d "$with_imagedir" ; then + AC_MSG_RESULT(yes) + else + AC_MSG_RESULT(no) + with_imagedir="" + fi + ;; + yes) + with_imagedir="" + + #### Could use some more defaults here... + for dd in \ + "/usr/share/backgrounds/images/" \ + "/usr/share/wallpapers/" \ + "/Library/Desktop Pictures/" \ + ; do + if test -z "$with_imagedir"; then + AC_MSG_CHECKING([for image directory $dd]) + if test -d "$dd" ; then + AC_MSG_RESULT(yes) + with_imagedir="$dd" + else + AC_MSG_RESULT(no) + fi + fi + done + + ;; + no) + with_imagedir="" + ;; + + *) + echo "error: must be an absolute path: --with-image-directory=$with_imagedir_req" + exit 1 + ;; +esac +ac_cv_imagedir="$with_imagedir" + +DEFAULT_IMAGES_P='True' +DEFAULT_IMAGE_DIRECTORY="$ac_cv_imagedir" + +if test -z "$DEFAULT_IMAGE_DIRECTORY" ; then + DEFAULT_IMAGES_P='False' +fi + + +############################################################################### +# +# Pick a text file to use as the default of the "textFile" preference. +# Any old file will do, but preferably one that will make interesting +# shapes when displayed by "starwars" and "fontglide". +# +############################################################################### + +have_textfile=no +with_textfile_req=unspecified + +AC_ARG_WITH(text-file, +[ --with-text-file=FILE By default, some demos may display this file.], + [with_textfile="$withval"; with_textfile_req="$withval"], + [with_textfile=yes]) +# no HANDLE_X_PATH_ARG for this one + +case "$with_textfile" in + /*) + # absolute path + AC_MSG_CHECKING([for text file $with_textfile]) + if test -f "$with_textfile" ; then + AC_MSG_RESULT(yes) + else + AC_MSG_RESULT(no) + with_textfile="" + fi + ;; + yes) + with_textfile="" + + #### Could use some more defaults here... + for f in \ + "/usr/X11R6/lib/X11/doc/README" \ + "/usr/share/doc/xserver-common/copyright" \ + "/usr/share/doc/xserver-xorg-core/copyright" \ + "/usr/X11R6/README" \ + "/usr/share/doc/libX11*/COPYING" \ + "/usr/X11/share/X11/doc/README*" \ + "/usr/share/doc/debian/debian-manifesto" \ + ; do + if test -z "$with_textfile"; then + AC_MSG_CHECKING([for text file $f]) + f=`/bin/ls $f 2>&- | head -1` + if test -f "$f" ; then + AC_MSG_RESULT(yes) + with_textfile="$f" + else + AC_MSG_RESULT(no) + fi + fi + done + + ;; + no) + with_textfile="" + ;; + + *) + echo "error: must be an absolute path: --with-text-file=$with_textfile_req" + exit 1 + ;; +esac +ac_cv_textfile="$with_textfile" + +DEFAULT_TEXT_FILE="$ac_cv_textfile" + + +############################################################################### +# +# Check the browser to see help URL +# +############################################################################### + +have_browser=no +with_browser_req=unspecified + +AC_ARG_WITH(browser, +[ --with-browser=BROWSER Specify the web browser used to show the help URL.], + [with_browser="$withval"; with_browser_req="$withval"], + [with_browser=no ]) +# no HANDLE_X_PATH_ARG for this one + +case "$with_browser" in + no ) + ;; + * ) + WITH_BROWSER=$with_browser + gnome_open_program=$with_browser + AC_MSG_CHECKING([for browser $with_browser]) + with_browser_fullpath=`which $with_browser 2>/dev/null` + case $with_browser_fullpath in + /* ) + AC_MSG_RESULT(yes) + have_browser=yes + ;; + * ) + AC_MSG_RESULT(no) +# Only warning: we don't want to install all packages for the +# dependency of the browser in building stage... + echo "WARNING: browser not found: --with-browser=$with_browser" + ;; + esac + ;; +esac +ac_cv_browser="$with_browser" + +############################################################################### +# +# Check whether it's ok to install some hacks as setuid (e.g., "sonar") +# This should be safe, but let's give people the option. +# +############################################################################### + +setuid_hacks_default=no +setuid_hacks="$setuid_hacks_default" +AC_ARG_WITH(setuid-hacks, +[ --with-setuid-hacks Allow some demos to be installed `setuid root' + (which is needed in order to ping other hosts.) +], + [setuid_hacks="$withval"], [setuid_hacks="$setuid_hacks_default"]) + +HANDLE_X_PATH_ARG(setuid_hacks, --with-setuid-hacks, setuid hacks) + +if test "$setuid_hacks" = yes; then + true +elif test "$setuid_hacks" != no; then + echo "error: must be yes or no: --with-setuid-hacks=$setuid_hacks" + exit 1 +fi + + +############################################################################### +# +# Done testing. Now, set up the various -I and -L variables, +# and decide which GUI program to build by default. +# +############################################################################### + +DEPEND=makedepend +DEPEND_FLAGS= +DEPEND_DEFINES= + + +if test \! -z "$includedir" ; then + INCLUDES="$INCLUDES -I$includedir" +fi + +if test \! -z "$libdir" ; then + LDFLAGS="$LDFLAGS -L$libdir" +fi + + +PREFERRED_DEMO_PROGRAM='' +ALL_DEMO_PROGRAMS= +if test "$have_motif" = yes; then + PREFERRED_DEMO_PROGRAM=xscreensaver-demo-Xm + ALL_DEMO_PROGRAMS="$PREFERRED_DEMO_PROGRAM $ALL_DEMO_PROGRAMS" +fi +if test "$have_gtk" = yes; then + PREFERRED_DEMO_PROGRAM=xscreensaver-demo-Gtk + ALL_DEMO_PROGRAMS="$PREFERRED_DEMO_PROGRAM $ALL_DEMO_PROGRAMS" +fi + + +if test "$have_kerberos" = yes; then + PASSWD_SRCS="$PASSWD_SRCS \$(KERBEROS_SRCS)" + PASSWD_OBJS="$PASSWD_OBJS \$(KERBEROS_OBJS)" +fi +if test "$have_pam" = yes; then + PASSWD_SRCS="$PASSWD_SRCS \$(PAM_SRCS)" + PASSWD_OBJS="$PASSWD_OBJS \$(PAM_OBJS)" + INSTALL_PAM="install-pam" +fi +if test "$enable_pam_check_account_type" = yes; then + COMMENT_PAM_CHECK_ACCOUNT="" +else + COMMENT_PAM_CHECK_ACCOUNT="#" +fi +if test "$have_passwd_helper" = yes; then + PASSWD_SRCS="$PASSWD_SRCS \$(PWHELPER_SRCS)" + PASSWD_OBJS="$PASSWD_OBJS \$(PWHELPER_OBJS)" +fi + PASSWD_SRCS="$PASSWD_SRCS \$(PWENT_SRCS)" + PASSWD_OBJS="$PASSWD_OBJS \$(PWENT_OBJS)" + + +if test "$enable_locking" = yes; then + LOCK_SRCS='$(LOCK_SRCS_1) $(PASSWD_SRCS)' + LOCK_OBJS='$(LOCK_OBJS_1) $(PASSWD_OBJS)' +else + LOCK_SRCS='$(NOLOCK_SRCS_1)' + LOCK_OBJS='$(NOLOCK_OBJS_1)' +fi + +if test "$ac_macosx" = yes; then + EXES_OSX='$(EXES_OSX)' + SCRIPTS_OSX='$(SCRIPTS_OSX)' + MEN_OSX='$(MEN_OSX)' +else + EXES_OSX= + SCRIPTS_OSX= + MEN_OSX= +fi + + +INSTALL_SETUID='$(INSTALL_PROGRAM) $(SUID_FLAGS)' + +if test "$need_setuid" = yes; then + NEED_SETUID=yes +else + NEED_SETUID=no +fi + +if test "$setuid_hacks" = yes; then + SETUID_HACKS=yes +else + SETUID_HACKS=no +fi + +tab=' ' +if test "$have_gl" = yes; then + GL_EXES='$(GL_EXES)' + SUID_EXES='$(SUID_EXES)' + RETIRED_GL_EXES='$(RETIRED_GL_EXES)' + GL_UTIL_EXES='$(GL_UTIL_EXES)' + GL_MEN='$(GL_MEN)' + GL_KLUDGE=" " +else + GL_KLUDGE="-" +fi + +if test "$have_gle" = yes; then + GLE_EXES='$(GLE_EXES)' + GLE_KLUDGE=" " +else + GLE_KLUDGE="-" +fi + +if test "$have_jpeg" = yes -a "$have_gdk_pixbuf" = yes; then + JPEG_EXES='$(JPEG_EXES)' +fi + + +# Another substitution in the XScreenSaver.ad.in file: +# +if test "$gnome_open_program" != ''; then + GNOME24='' + GNOME22='! ' + NOGNOME='! ' +elif test "$gnome_url_show_program" != ''; then + GNOME24='! ' + GNOME22='' + NOGNOME='! ' +else + GNOME24='! ' + GNOME22='! ' + NOGNOME='' +fi + + +# Set PO_DATADIR to something sensible. +# +AC_MSG_CHECKING([for locale directory]) +if test -n "$GTK_DATADIR" ; then + PO_DATADIR="$GTK_DATADIR" +elif test "$have_gtk" = yes; then + PO_DATADIR=`$pkg_config --variable=prefix gtk+-2.0` + PO_DATADIR="$PO_DATADIR/share" +fi + +if test -z "$PO_DATADIR" ; then + # + # #### Total fucking kludge -- + # Map /build/prefix/usr/X11R6/share/ to /build/prefix/usr/share/ + # but of course we need to expand all the nested variables to do that... + # + dd=`eval eval eval eval eval eval eval eval eval eval eval echo $datadir` + PO_DATADIR=`echo $dd | sed 's@/X11R6/@/@'` +fi + +AC_MSG_RESULT($PO_DATADIR/locale) + + +# canonicalize slashes. +HACK_CONF_DIR=`echo "${HACK_CONF_DIR}" | sed 's@/$@@;s@//*@/@g'` + +# gcc 3.0 likes to issue this warning for every file: +# +# cc1: warning: changing search order for system directory "/usr/local/include" +# cc1: warning: as it has already been specified as a non-system directory +# +# Yay. We can only avoid that by deleting "-I${prefix}/include" from the list. +# Which *should* be totally redundant, and thus an ok thing to delete? +# +INCLUDES=`echo "$INCLUDES" | sed 's@ -I${prefix}/include@@g;'` + + +############################################################################### +# +# Perform substitutions and write Makefiles. +# +############################################################################### + +AC_SUBST(INCLUDES) + +AC_SUBST(PREFERRED_DEMO_PROGRAM) +AC_SUBST(ALL_DEMO_PROGRAMS) +AC_SUBST(SAVER_LIBS) +AC_SUBST(MOTIF_LIBS) +AC_SUBST(GTK_LIBS) +AC_SUBST(XML_LIBS) +AC_SUBST(JPEG_LIBS) +AC_SUBST(HACK_LIBS) +AC_SUBST(XPM_LIBS) +AC_SUBST(PTY_LIBS) +AC_SUBST(GL_LIBS) +AC_SUBST(GLE_LIBS) +AC_SUBST(XDPMS_LIBS) +AC_SUBST(XINERAMA_LIBS) +AC_SUBST(PASSWD_LIBS) +AC_SUBST(INSTALL_SETUID) +AC_SUBST(SETUID_HACKS) +AC_SUBST(INSTALL_DIRS) +AC_SUBST(NEED_SETUID) +AC_SUBST(INSTALL_PAM) +AC_SUBST(HAVE_PAM_FAIL_DELAY) +AC_SUBST(COMMENT_PAM_CHECK_ACCOUNT) +AC_SUBST(NEW_LOGIN_COMMAND) +AC_SUBST(NEW_LOGIN_COMMAND_P) +AC_SUBST(DEFAULT_IMAGES_P) +AC_SUBST(DEFAULT_IMAGE_DIRECTORY) +AC_SUBST(DEFAULT_TEXT_FILE) +AC_SUBST(WITH_BROWSER) + +AC_SUBST(OBJCC) +AC_SUBST(EXES_OSX) +AC_SUBST(SCRIPTS_OSX) +AC_SUBST(MEN_OSX) + +AC_SUBST(PASSWD_SRCS) +AC_SUBST(PASSWD_OBJS) +AC_SUBST(XMU_SRCS) +AC_SUBST(XMU_OBJS) +AC_SUBST(XMU_LIBS) +AC_SUBST(SAVER_GL_SRCS) +AC_SUBST(SAVER_GL_OBJS) +AC_SUBST(SAVER_GL_LIBS) +AC_SUBST(LOCK_SRCS) +AC_SUBST(LOCK_OBJS) +AC_SUBST(JPEG_EXES) +AC_SUBST(GL_EXES) +AC_SUBST(RETIRED_GL_EXES) +AC_SUBST(SUID_EXES) +AC_SUBST(GL_UTIL_EXES) +AC_SUBST(GL_MEN) +AC_SUBST(GL_KLUDGE) +AC_SUBST(GLE_EXES) +AC_SUBST(GLE_KLUDGE) +AC_SUBST(JWZGLES_OBJS) +AC_SUBST(GLFPS_OBJS) +AC_SUBST(GLFONT_OBJS) +AC_SUBST(GNOME24) +AC_SUBST(GNOME22) +AC_SUBST(NOGNOME) +AC_SUBST(HACKDIR) +AC_SUBST(HACKDIR_FULL) +AC_SUBST(GTK_DATADIR) +AC_SUBST(PO_DATADIR) +AC_SUBST(HACK_CONF_DIR) +AC_SUBST(GTK_EXTRA_OBJS) + +APPDEFAULTS=$ac_x_app_defaults +AC_SUBST(APPDEFAULTS) + +AC_SUBST(DEPEND) +AC_SUBST(DEPEND_FLAGS) +AC_SUBST(DEPEND_DEFINES) +AC_SUBST(PERL) + +AC_OUTPUT(Makefile + utils/Makefile + driver/Makefile + driver/xscreensaver.pam + hacks/Makefile + hacks/glx/Makefile + po/Makefile.in + driver/XScreenSaver.ad) + +############################################################################### +# +# Print some warnings at the end. +# +############################################################################### + +warn_prefix_1=" Warning:" +warn_prefix_2=" Note:" +warn_prefix="$warn_prefix_1" + +warning=no +warnsep=' #################################################################' + +warnpre() { + if test "$warning" = no ; then + echo '' ; echo "$warnsep" ; echo '' + warning=yes + fi +} + +warn() { + warnpre + if test "$warning" = long ; then echo '' ; fi + warning=yes + rest="$@" + echo "$warn_prefix $rest" +} + +warnL() { + was=$warning + warnpre + warning=yes + if test "$was" != no ; then echo '' ; fi + rest="$@" + echo "$warn_prefix $rest" +} + +warn2() { + rest="$@" + echo " $rest" + warning=long +} + +note() { + warn_prefix="$warn_prefix_2" + warn $@ + warn_prefix="$warn_prefix_1" +} + +noteL() { + warn_prefix="$warn_prefix_2" + warnL $@ + warn_prefix="$warn_prefix_1" +} + + +if test "$with_sgi_req" = yes -a "$have_sgi" = no ; then + warn 'The SGI saver extension was requested, but was not found.' +fi + +if test "$with_xidle_req" = yes -a "$have_xidle" = no ; then + warn 'The XIdle extension was requested, but was not found.' +fi + +if test "$with_xshm_req" = yes -a "$have_xshm" = no ; then + warn 'The XSHM extension was requested, but was not found.' +fi + +if test "$with_xdbe_req" = yes -a "$have_xdbe" = no ; then + warn 'The DOUBLE-BUFFER extension was requested, but was not found.' +fi + +if test "$with_sgivc_req" = yes -a "$have_sgivc" = no ; then + warn 'The SGI-VIDEO-CONTROL extension was requested, but was not found.' +fi + +if test "$with_dpms_req" = yes -a "$have_dpms" = no ; then + warn 'The DPMS extension was requested, but was not found.' +fi + +if test "$with_xinerama_req" = yes -a "$have_xinerama" = no ; then + warn 'The Xinerama extension was requested, but was not found.' +fi + +if test "$with_xf86vmode_req" = yes -a "$have_xf86vmode" = no ; then + warn 'The XF86VMODE extension was requested, but was not found.' +fi + +if test "$with_randr_req" = yes -a "$have_randr" = no ; then + warn 'The RANDR extension was requested, but was not found.' +fi + +if test "$with_proc_interrupts_req" = yes -a "$have_proc_interrupts" = no; then + warn "Checking of /proc/interrupts was requested, but it's bogus." +fi + +if test "$pkg_config" = false ; then + warnL 'The "pkg-config" program was not found. Without that,' + warn2 "detection of the various GTK libraries won't work." +else + pkgerr=`$pkg_config --list-all 2>&1 >/dev/null` + if test "x$pkgerr" != "x" ; then + warnL 'The "pkg-config" program produces errors. This often causes' + warn2 "detection of the various GTK libraries to malfunction." + warn2 "The errors are:" + echo '' + echo "$pkgerr" | sed 's/^/ > /g' + fi +fi + +if test "$gtk_halfassed" != no ; then + warnL "GTK version $gtk_halfassed was found, but at least one supporting" + warn2 "library ($gtk_halfassed_lib) was not, so GTK can't be used." + warn2 "Perhaps some of the development packages are not installed?" + if test "$have_gtk" = yes ; then + v="$ac_gtk_version_string" + warn2 "GTK $v is also installed, so it will be used instead." + warn2 "Please read the above output and the \`config.log' file" + warn2 "for more details." + fi +fi + +motif_warn2() { + warn2 'Though the Motif front-end to xscreensaver is still' + warn2 'maintained, it is no longer being updated with new' + warn2 'features: all new development on the xscreensaver-demo' + warn2 'program is happening in the GTK version, and not in the' + warn2 'Motif version. It is recommended that you build against' + warn2 'GTK instead of Motif. See .' +} + +if test "$have_motif" = no -a "$have_gtk" = no; then + + if test "$with_motif" = yes; then + warnL "Neither the GTK nor Motif libraries were found; the" + warn2 "\`xscreensaver-demo' program requires one of these." + echo '' + motif_warn2 + else + warnL "The GTK libraries do not seem to be available; the" + warn2 "\`xscreensaver-demo' program requires them." +# echo '' +# warn2 'You can use Motif or Lesstif instead of GTK (use the' +# warn2 "\`--with-motif' option) but that is NOT recommended." +# motif_warn2 + fi + +elif test "$with_motif_req" = yes -a "$have_motif" = no ; then + warnL "Use of Motif was requested, but it wasn't found;" + warn2 "Gtk will be used instead." + +elif test "$jurassic_gtk" = yes ; then + + pref_gtk=2.0 + + v="$ac_gtk_version_string" + if test "$with_gtk_req" = yes -a "$ac_gtk_version" = "unknown" ; then + warnL "Use of Gtk was requested, but its version number is unknown;" + elif test "$with_gtk_req" = yes ; then + warnL "Use of Gtk was requested, but it is version $v;" + else + warnL "Gtk was found on this system, but it is version $v;" + fi + + warn2 "Gtk $pref_gtk or newer is required." + +elif test "$with_gtk_req" = yes -a "$have_gtk" = no ; then + warnL "Use of Gtk was requested, but it wasn't found." +fi + + +if test "$have_gtk" = yes -a "$have_gdk_pixbuf" = no ; then + warn "GTK is being used, but the GDK-Pixbuf library and/or" + warn2 "headers were not found. That can't be good. Please" + warn2 "install the GDK-Pixbuf development kit and re-configure." +fi + +if test "$have_motif" = yes -a "$have_lesstif" = yes ; then + + preferred_lesstif=0.92 + + if test "$lesstif_version" = unknown; then + warnL "Unable to determine the LessTif version number!" + warn2 "Make sure you are using version $preferred_lesstif or newer." + warn2 "See ." + + elif test \! $lesstif_version -gt 82; then + warnL "LessTif version $lesstif_version_string is being used." + warn2 "LessTif versions 0.82 and earlier are too buggy to" + warn2 "use with XScreenSaver; it is strongly recommended" + warn2 "that you upgrade to at least version $preferred_lesstif!" + warn2 "See ." + fi +fi + + +if test "$have_motif" = yes -a "$have_gtk" = no ; then + warn 'Motif is being used, and GTK is not.' + echo '' + motif_warn2 +fi + + +if test "$with_xpm_req" = yes -a "$have_xpm" = no; then + warnL 'Use of XPM was requested, but it was not found.' +fi + +if test "$with_gdk_pixbuf_req" = yes -a "$have_gdk_pixbuf" = no; then + warnL 'Use of GDK-Pixbuf was requested, but it was not found.' +fi + +if test "$have_gdk_pixbuf" = no -o "$gdk_pixbuf_halfassed" = yes || \ + test "$have_gdk_pixbuf" = no -a "$have_xpm" = no ; then + + if test "$with_gdk_pixbuf_req" = yes ; then + true + elif test "$with_gdk_pixbuf_req" = no ; then + warnL 'The GDK-Pixbuf library is not being used.' + else + warnL 'The GDK-Pixbuf library was not found.' + fi + + if test "$with_xpm_req" = yes -o "$have_xpm" = yes ; then + true + elif test "$with_xpm_req" = no ; then + warnL 'The XPM library is not being used.' + else + warnL 'The XPM library was not found.' + fi + + if test "$have_gdk_pixbuf" = no -a "$have_xpm" = yes ; then + warn2 'The XPM library is being used instead.' + fi + + if test "$gdk_pixbuf_halfassed" = yes ; then + echo '' + warn2 'More specifically, we found the headers, but not the' + warn2 'libraries; so either GDK-Pixbuf is half-installed on this' + warn2 "system, or something else went wrong. The \`config.log'" + warn2 'file might contain some clues.' + fi + + echo '' + warn2 'Some of the demos will not use images as much as they could.' + warn2 'You should consider installing GDK-Pixbuf and re-running' + warn2 'configure. (GDK-Pixbuf is recommended over XPM, as it' + warn2 'provides support for more image formats.)' +fi + + +if test "$have_jpeg" = no ; then + if test "$with_jpeg_req" = yes ; then + warnL 'Use of libjpeg was requested, but it was not found.' + elif test "$with_jpeg_req" = no ; then + noteL 'The JPEG library is not being used.' + else + noteL 'The JPEG library was not found.' + fi + + if test "$jpeg_halfassed" = yes ; then + echo '' + warn2 'More specifically, we found the headers, but not the' + warn2 'library; so either JPEG is half-installed on this' + warn2 "system, or something else went wrong. The \`config.log'" + warn2 'file might contain some clues.' + echo '' + fi + + if test "$have_gdk_pixbuf" = no ; then + warn2 "This means that it won't be possible for the image-manipulating" + warn2 "display modes to load files from disk; and it also means that" + warn2 "the \`webcollage' program will be much slower." + else + warn2 "This means the \`webcollage' program will be much slower." + fi +fi + + +if test "$have_gl" = yes -a "$ac_have_mesa_gl" = yes ; then + preferred_mesagl=3.4 + mgv="$ac_mesagl_version_string" + pgl="$preferred_mesagl" + + if test "$ac_mesagl_version" = unknown; then + true + # warnL "Unable to determine the MesaGL version number!" + # warn2 "Make sure you are using version $preferred_mesagl or newer." + + elif test \! "$ac_mesagl_version" -gt 2006; then + warnL "MesaGL version number is $mgv --" + warn2 "MesaGL 2.6 and earlier have a security bug. It is strongly" + warn2 "recommended that you upgrade to at least version $preferred_mesagl." + + elif test \! "$ac_mesagl_version" -gt 3003; then + warnL "MesaGL version number is $mgv --" + warn2 "MesaGL 3.3 and earlier have some bugs; it is recommended" + warn2 "that you upgrade to $pgl or newer." + fi +fi + +if test "$have_gl" = no ; then + if test "$with_gl_req" = yes ; then + warnL 'Use of GL was requested, but it was not found.' + elif test "$with_gl_req" = no ; then + noteL 'The OpenGL 3D library is not being used.' + else + noteL 'The OpenGL 3D library was not found.' + fi + + if test "$gl_halfassed" = yes ; then + echo '' + warn2 'More specifically, we found the headers, but not the' + warn2 'libraries; so either GL is half-installed on this' + warn2 "system, or something else went wrong. The \`config.log'" + warn2 'file might contain some clues.' + fi + + echo '' + warn2 'Those demos which use 3D will not be built or installed.' + warn2 'You might want to consider installing OpenGL and' + warn2 "re-running configure. If your vendor doesn't ship" + warn2 'their own implementation of OpenGL, you can get a free' + warn2 'version at . For general OpenGL' + warn2 'info, see .' + +fi + + +if test "$have_gl" = yes -a "$have_gle" = no ; then + + # nobody cares about this; don't print the warning unless it was + # requested and not found, or halfway-found. + if test "$with_gle_req" = yes -o "$gle_halfassed" = yes ; then + + if test "$with_gle_req" = yes ; then + noteL 'Use of the GLE (GL Extrusion) library was requested, but' + warn2 'it was not found (though the OpenGL library was found, and' + warn2 'is being used.)' + elif test "$with_gle_req" = no ; then + noteL 'The OpenGL Library is being used, but the GLE (GL Extrusion)' + warn2 'library is not.' + else + noteL 'The OpenGL Library was found, but the GLE (GL Extrusion)' + warn2 'was not.' + fi + + if test "$gle_halfassed" = yes ; then + echo '' + warn2 'More specifically, we found the headers, but not the' + warn2 'libraries; so either GLE is half-installed on this' + warn2 "system, or something else went wrong. The \`config.log'" + warn2 'file might contain some clues.' + fi + + echo '' + warn2 'Some of the OpenGL (3D) demos (those that depend on GLE)' + warn2 'will not be built or installed. You might want to consider' + warn2 'installing GLE and re-running configure. You can find the' + warn2 'GLE library at . For general' + warn2 'OpenGL info, see .' + + fi +fi + + +if test "$with_readdisplay_req" = yes -a "$have_readdisplay" = no ; then + warn 'Use of XReadDisplay was requested, but it was not found.' +fi + +if test "$with_kerberos_req" = yes -a "$have_kerberos" = no ; then + warn 'Use of Kerberos was requested, but it was not found.' +fi + +if test "$with_pam_req" = yes -a "$have_pam" = no ; then + warn 'Use of PAM was requested, but it was not found.' +fi + +if test "$with_shadow_req" = yes -a "$have_shadow" = no ; then + warn 'Use of shadow passwords was requested, but they were not found.' +fi + +if test "$ac_macosx" = yes ; then + if test "$enable_locking" = yes ; then + warn "You have specified --enable-locking on MacOS X." + warn2 "THIS DOES NOT WORK! Don't do this!" + fi +fi + + +# You are in a twisty maze of namespaces and syntaxes, all alike. +# Fuck the skull of Unix. +# +bindir=`eval eval eval eval eval eval eval echo $bindir` +HACKDIR=`eval eval eval eval eval eval eval echo $HACKDIR` +HACK_CONF_DIR=`eval eval eval eval eval eval eval echo $HACK_CONF_DIR` + +# canonicalize slashes. +bindir=`echo "${bindir}" | sed 's@/$@@;s@//*@/@g'` +HACKDIR=`echo "${HACKDIR}" | sed 's@/$@@;s@//*@/@g'` +HACK_CONF_DIR=`echo "${HACK_CONF_DIR}" | sed 's@/$@@;s@//*@/@g'` + + +# Sanity check the hackdir +for bad_choice in xscreensaver xscreensaver-demo xscreensaver-command ; do + if test "${HACKDIR}" = "${bindir}/${bad_choice}" ; then + echo "" + AC_MSG_ERROR([\"--with-hackdir=${bindir}/${bad_choice}\" won't work. + There will be an executable installed with that name, so + that can't be the name of a directory as well. Please + re-configure with a different directory name.]) + fi +done + + +do_dir_warning=no + +# Now let's warn if there's a previous RPM version already installed. +# But don't bother with this test if we are currently *building* an RPM. + +if test -z "$RPM_PACKAGE_VERSION" ; then + + rpmnames="xscreensaver xscreensaver-base xscreensaver-extras" + + # M4 sucks!! + changequote(X,Y) + rpmv=`(rpm -qv $rpmnames) 2>/dev/null | \ + sed -n 's/^[-a-z]*-\([0-9][0-9]*[.][0-9][0-9a-z]*\)-.*$/\1/p' | \ + head -1` + changequote([,]) + + if test \! -z "$rpmv" ; then + rpmbdir=`rpm -ql $rpmnames | sed -n 's@^\(.*\)/xscreensaver-demo$@\1@p'` + rpmhdir=`rpm -ql $rpmnames | sed -n 's@^\(.*\)/popsquares$@\1@p'` + + warning=no + warnL "There is already an installed RPM of xscreensaver $rpmv" + warn2 'on this system. You might want to remove it ("rpm -ve")' + warn2 'before running "make install" in this directory.' + echo "" + warn2 "Alternately, you could build this version of xscreensaver" + warn2 'as an RPM, and then install that. An "xscreensaver.spec"' + warn2 'file is included. Try "rpmbuild -v -ba xscreensaver.spec".' + warn2 "See the RPM documentation for more info." + echo "" + + if test "$rpmbdir" = "$rpmhdir" ; then + warn2 "The RPM version was installed in $rpmbdir/." + do_dir_warning=yes + else + warn2 "The RPM version was installed in $rpmbdir/," + warn2 "with demos in $rpmhdir/." + fi + fi +fi + +# Also warn if there's a Debian package installed. +# +debnames="xscreensaver xscreensaver-data xscreensaver-data-extra" +debv='' +for dpkg in $debnames ; do + if test -z "$debv"; then + debv=`dpkg -s $dpkg 2>/dev/null | sed -n 's/^Version: \(.*\)$/\1/p'` + fi +done + +if test \! -z "$debv" ; then + debbdir=`dpkg -L $debnames 2>/dev/null | \ + sed -n 's@^\(.*/bin/\)xscreensaver$@\1@p'` + debhdir=`dpkg -L $debnames 2>/dev/null | \ + sed -n 's@^\(.*/\)popsquares$@\1@p'` + if test -z "$debbdir" ; then debbdir='???'; fi + if test -z "$debhdir" ; then debhdir='???'; fi + + warning=no + warnL "There is already an installed dpkg of xscreensaver" + warn2 "version \"$debv\" on this system." + echo "" + warn2 "The dpkg was installed in $debbdir," + warn2 "with demos in $debhdir." +fi + + +if test "${bindir}" = "${HACKDIR}" ; then + do_dir_warning=yes +fi + +if test "$do_dir_warning" = yes; then + echo "" + echo "$warnsep" + echo "" + echo ' When you run "make install", the "xscreensaver",' + echo ' "xscreensaver-demo", and "xscreensaver-command" executables' + echo " will be installed in ${bindir}/." + echo "" + echo " The various graphics demos (190+ different executables) will" + echo " be installed in ${HACKDIR}/." + echo "" + echo " If you would prefer the demos to be installed elsewhere," + echo " you should re-run configure with the --with-hackdir=DIR" + echo " option. For more information, run \`./configure --help'." + warning=yes +fi + +if test "$warning" != no; then + echo '' ; echo "$warnsep" ; echo '' +fi + +if test "$do_dir_warning" = no; then + if test "$warning" = no; then + echo '' + fi + echo "User programs will be installed in ${bindir}/" + echo "Screen savers will be installed in ${HACKDIR}/" + echo "Configuration dialogs will be installed in ${HACK_CONF_DIR}/" + echo "System-wide default settings will be installed in ${APPDEFAULTS}/" + echo '' +fi diff --git a/driver/.gdbinit b/driver/.gdbinit new file mode 100644 index 00000000..a585259f --- /dev/null +++ b/driver/.gdbinit @@ -0,0 +1,27 @@ +# If you're debugging xscreensaver and you are running a virtual root window +# manager, you'd better let the process handle these signals: it remaps the +# virtual root window when they arrive. If you don't do this, your window +# manager will be hosed. +# +# Also, gdb copes badly with breakpoints in functions that are called on the +# other side of a fork(). The Trace/BPT traps cause the spawned process to +# die. +# +#handle 1 pass nostop +#handle 3 pass nostop +#handle 4 pass nostop +#handle 6 pass nostop +#handle 7 pass nostop +#handle 8 pass nostop +#handle 9 pass nostop +#handle 10 pass nostop +#handle 11 pass nostop +#handle 12 pass nostop +#handle 13 pass nostop +#handle 15 pass nostop +#handle 19 pass nostop +set env MallocGuardEdges 1 +set env MallocPreScribble 1 +set env MallocScribble 1 +b exit +set args -debug diff --git a/driver/Makefile.in b/driver/Makefile.in new file mode 100644 index 00000000..0d5865cb --- /dev/null +++ b/driver/Makefile.in @@ -0,0 +1,1011 @@ +# driver/Makefile.in --- xscreensaver, Copyright (c) 1997-2010 Jamie Zawinski. +# the `../configure' script generates `driver/Makefile' from this file. + +@SET_MAKE@ +.SUFFIXES: +.SUFFIXES: .c .m .o + +srcdir = @srcdir@ +VPATH = @srcdir@ +top_srcdir = @top_srcdir@ +top_builddir = .. + +install_prefix = +prefix = @prefix@ +exec_prefix = @exec_prefix@ +bindir = @bindir@ +datarootdir = @datarootdir@ +datadir = @datadir@ +localedir = $(datadir)/locale +mandir = @mandir@ +libexecdir = @libexecdir@ +mansuffix = 1 +manNdir = $(mandir)/man$(mansuffix) + +INTLTOOL_MERGE = @INTLTOOL_MERGE@ + +GTK_DATADIR = @GTK_DATADIR@ +GTK_APPDIR = $(GTK_DATADIR)/applications +GTK_ICONDIR = $(GTK_DATADIR)/pixmaps +GTK_GLADEDIR = $(GTK_DATADIR)/xscreensaver/glade +HACK_CONF_DIR = @HACK_CONF_DIR@ + +CC = @CC@ +OBJCC = @OBJCC@ +CFLAGS = @CFLAGS@ +LDFLAGS = @LDFLAGS@ +DEFS = @DEFS@ +INTL_DEFS = -DLOCALEDIR=\"$(localedir)\" +SUBP_DEFS = $(DEFS) -DDEFAULT_PATH_PREFIX='"@HACKDIR@"' +GTK_DEFS = $(DEFS) -DDEFAULT_ICONDIR='"$(GTK_GLADEDIR)"' +CONF_DEFS = -DHACK_CONFIGURATION_PATH='"$(HACK_CONF_DIR)"' + +LIBS = @LIBS@ +INTL_LIBS = @INTLLIBS@ +JPEG_LIBS = @JPEG_LIBS@ +PERL = @PERL@ + +DEPEND = @DEPEND@ +DEPEND_FLAGS = @DEPEND_FLAGS@ +DEPEND_DEFINES = @DEPEND_DEFINES@ + +SHELL = /bin/sh +INSTALL = @INSTALL@ +SUID_FLAGS = -o root -m 4755 +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_SETUID = @INSTALL_SETUID@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_DIRS = @INSTALL_DIRS@ + +X_CFLAGS = @X_CFLAGS@ +X_LIBS = @X_LIBS@ +X_PRE_LIBS = @X_PRE_LIBS@ +X_EXTRA_LIBS = @X_EXTRA_LIBS@ +XMU_LIBS = @XMU_LIBS@ +XPM_LIBS = @XPM_LIBS@ + +# Note: +# +# X_LIBS would more properly be called X_LDFLAGS (it contains the -L args.) +# X_PRE_LIBS contains extra libraries you have to link against on some systems, +# and that must come before -lX11. (e.g., -lSM and -lICE.) +# X_EXTRA_LIBS contains extra libraries needed by X that aren't a part of X. +# (e.g., -lsocket, -lnsl, etc.) +# +# I think (but am not totally sure) that LIBS is also really "LDFLAGS". +# +# SAVER_LIBS is the link line for "xscreensaver", and +# CMD_LIBS is the link line for "xscreensaver-command". +# GETIMG_LIBS is the link line for "xscreensaver-getimage". + + +AD_DIR = @APPDEFAULTS@ +PAM_DIR = /etc/pam.d +PAM_CONF = /etc/pam.conf + +UTILS_SRC = $(srcdir)/../utils +UTILS_BIN = ../utils + +INCLUDES_1 = -I. -I$(srcdir) -I$(UTILS_SRC) -I.. +INCLUDES = $(INCLUDES_1) @INCLUDES@ + +MOTIF_SRCS = demo-Xm.c demo-Xm-widgets.c +MOTIF_OBJS = demo-Xm.o demo-Xm-widgets.o + +GTK_SRCS = demo-Gtk.c demo-Gtk-conf.c \ + demo-Gtk-widgets.c demo-Gtk-support.c +GTK_EXTRA_OBJS = demo-Gtk-widgets.o demo-Gtk-support.o +GTK_OBJS = demo-Gtk.o demo-Gtk-conf.o @GTK_EXTRA_OBJS@ + +PWENT_SRCS = passwd-pwent.c +PWENT_OBJS = passwd-pwent.o + +KERBEROS_SRCS = passwd-kerberos.c +KERBEROS_OBJS = passwd-kerberos.o + +PAM_SRCS = passwd-pam.c +PAM_OBJS = passwd-pam.o + +PWHELPER_SRCS = passwd-helper.c +PWHELPER_OBJS = passwd-helper.o + +LOCK_SRCS_1 = lock.c passwd.c +LOCK_OBJS_1 = lock.o passwd.o +NOLOCK_SRCS_1 = lock.c +NOLOCK_OBJS_1 = lock.o + +TEST_SRCS = test-passwd.c test-uid.c test-xdpms.c test-grab.c \ + test-apm.c test-fade.c test-xinerama.c test-vp.c \ + test-randr.c xdpyinfo.c test-mlstring.c test-screens.c +TEST_EXES = test-passwd test-uid test-xdpms test-grab \ + test-apm test-fade test-xinerama test-vp \ + test-randr xdpyinfo test-mlstring test-screens + +MOTIF_LIBS = @MOTIF_LIBS@ @XPM_LIBS@ $(XMU_LIBS) +GTK_LIBS = @GTK_LIBS@ $(XMU_LIBS) +XML_LIBS = @XML_LIBS@ + +XDPMS_LIBS = @XDPMS_LIBS@ +XINERAMA_LIBS = @XINERAMA_LIBS@ +XINPUT_LIBS = @XINPUT_LIBS@ + +PASSWD_SRCS = @PASSWD_SRCS@ +PASSWD_OBJS = @PASSWD_OBJS@ +PASSWD_LIBS = @PASSWD_LIBS@ + +LOCK_SRCS = @LOCK_SRCS@ +LOCK_OBJS = @LOCK_OBJS@ + +XMU_SRCS = @XMU_SRCS@ +XMU_OBJS = @XMU_OBJS@ + +GL_SRCS = @SAVER_GL_SRCS@ +GL_OBJS = @SAVER_GL_OBJS@ +GL_LIBS = @SAVER_GL_LIBS@ + +ICON_SRC = $(UTILS_SRC)/images +LOGO = $(ICON_SRC)/logo-50.xpm +GTK_ICONS = $(ICON_SRC)/screensaver-*.png + +DEMO_UTIL_SRCS = $(UTILS_SRC)/resources.c $(UTILS_SRC)/usleep.c \ + $(UTILS_SRC)/visual.c $(XMU_SRCS) +DEMO_UTIL_OBJS = $(UTILS_BIN)/resources.o $(UTILS_BIN)/usleep.o \ + $(UTILS_BIN)/visual.o $(XMU_OBJS) + +SAVER_UTIL_SRCS = $(UTILS_SRC)/fade.c $(UTILS_SRC)/overlay.c \ + $(UTILS_SRC)/logo.c $(UTILS_SRC)/yarandom.c \ + $(UTILS_SRC)/minixpm.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 \ + $(DEMO_UTIL_OBJS) + +GETIMG_SRCS_1 = xscreensaver-getimage.c +GETIMG_OBJS_1 = xscreensaver-getimage.o + +GETIMG_SRCS = $(GETIMG_SRCS_1) \ + $(UTILS_BIN)/colorbars.o $(UTILS_BIN)/resources.o \ + $(UTILS_BIN)/yarandom.o $(UTILS_BIN)/visual.o \ + $(UTILS_BIN)/usleep.o $(UTILS_BIN)/hsv.o \ + $(UTILS_BIN)/colors.o $(UTILS_BIN)/grabscreen.o \ + $(UTILS_BIN)/logo.o $(UTILS_BIN)/minixpm.o prefs.o \ + $(XMU_SRCS) + +GETIMG_OBJS = $(GETIMG_OBJS_1) \ + $(UTILS_BIN)/colorbars.o $(UTILS_BIN)/resources.o \ + $(UTILS_BIN)/yarandom.o $(UTILS_BIN)/visual.o \ + $(UTILS_BIN)/usleep.o $(UTILS_BIN)/hsv.o \ + $(UTILS_BIN)/colors.o $(UTILS_BIN)/grabscreen.o \ + $(UTILS_BIN)/logo.o $(UTILS_BIN)/minixpm.o prefs.o \ + $(XMU_OBJS) + +SAVER_SRCS_1 = xscreensaver.c windows.c screens.c timers.c subprocs.c \ + exec.c xset.c splash.c setuid.c stderr.c mlstring.c +SAVER_OBJS_1 = xscreensaver.o windows.o screens.o timers.o subprocs.o \ + exec.o xset.o splash.o setuid.o stderr.o mlstring.o + +SAVER_SRCS = $(SAVER_SRCS_1) prefs.c dpms.c $(LOCK_SRCS) \ + $(SAVER_UTIL_SRCS) $(GL_SRCS) +SAVER_OBJS = $(SAVER_OBJS_1) prefs.o dpms.o $(LOCK_OBJS) \ + $(SAVER_UTIL_OBJS) $(GL_OBJS) + +CMD_SRCS = remote.c xscreensaver-command.c +CMD_OBJS = remote.o xscreensaver-command.o + +DEMO_SRCS_1 = prefs.c dpms.c +DEMO_OBJS_1 = prefs.o dpms.o + +DEMO_SRCS = $(DEMO_SRCS_1) remote.c exec.c $(DEMO_UTIL_SRCS) +DEMO_OBJS = $(DEMO_OBJS_1) remote.o exec.o $(DEMO_UTIL_OBJS) + +PDF2JPEG_SRCS = pdf2jpeg.m +PDF2JPEG_OBJS = pdf2jpeg.o +PDF2JPEG_LIBS = -framework Cocoa + +SAVER_LIBS = $(LIBS) $(X_LIBS) $(XMU_LIBS) @SAVER_LIBS@ \ + $(XDPMS_LIBS) $(XINERAMA_LIBS) $(GL_LIBS) $(X_PRE_LIBS) \ + -lXt -lX11 -lXext $(X_EXTRA_LIBS) \ + $(PASSWD_LIBS) + +CMD_LIBS = $(LIBS) $(X_LIBS) \ + $(X_PRE_LIBS) -lX11 -lXext $(X_EXTRA_LIBS) + +GETIMG_LIBS = $(LIBS) $(X_LIBS) $(XPM_LIBS) $(JPEG_LIBS) \ + $(X_PRE_LIBS) -lXt -lX11 $(XMU_LIBS) -lXext $(X_EXTRA_LIBS) + +EXES = xscreensaver xscreensaver-command xscreensaver-demo \ + xscreensaver-getimage @EXES_OSX@ +EXES2 = @ALL_DEMO_PROGRAMS@ +EXES_OSX = pdf2jpeg + +SCRIPTS_1 = xscreensaver-getimage-file xscreensaver-getimage-video \ + xscreensaver-text +SCRIPTS_OSX = xscreensaver-getimage-desktop +SCRIPTS = $(SCRIPTS_1) @SCRIPTS_OSX@ + +HDRS = XScreenSaver_ad.h XScreenSaver_Xm_ad.h \ + xscreensaver.h prefs.h remote.h exec.h \ + demo-Gtk-widgets.h demo-Gtk-stubs.h demo-Gtk-support.h \ + demo-Gtk-conf.h auth.h mlstring.h types.h +MEN_1 = xscreensaver.man xscreensaver-demo.man \ + xscreensaver-command.man \ + xscreensaver-text.man \ + xscreensaver-getimage.man \ + xscreensaver-getimage-file.man \ + xscreensaver-getimage-video.man +MEN_OSX = xscreensaver-getimage-desktop.man pdf2jpeg.man +MEN = $(MEN_1) @MEN_OSX@ + +EXTRAS = README Makefile.in \ + XScreenSaver.ad.in XScreenSaver-Xm.ad xscreensaver.pam.in \ + xscreensaver-demo.glade2 xscreensaver-demo.glade2p \ + screensaver-properties.desktop.in \ + .gdbinit +VMSFILES = compile_axp.com compile_decc.com link_axp.com link_decc.com \ + vms-getpwnam.c vms-pwd.h vms-hpwd.c vms-validate.c \ + vms_axp.opt vms_axp_12.opt vms_decc.opt vms_decc_12.opt + +TARFILES = $(EXTRAS) $(VMSFILES) $(SAVER_SRCS_1) \ + $(MOTIF_SRCS) $(GTK_SRCS) $(PWENT_SRCS) $(PWHELPER_SRCS) \ + $(KERBEROS_SRCS) $(PAM_SRCS) $(LOCK_SRCS_1) $(DEMO_SRCS_1) \ + $(CMD_SRCS) $(GETIMG_SRCS_1) $(PDF2JPEG_SRCS) $(HDRS) \ + $(SCRIPTS_1) $(SCRIPTS_OSX) $(MEN_1) $(MEN_OSX) \ + $(TEST_SRCS) + + +default: $(EXES) +all: $(EXES) $(EXES2) +tests: $(TEST_EXES) + +install: install-program install-ad install-scripts \ + install-gnome install-man install-xml install-pam +uninstall: uninstall-program uninstall-ad \ + uninstall-gnome uninstall-man uninstall-xml + +install-strip: + $(MAKE) INSTALL_PROGRAM='$(INSTALL_PROGRAM) -s' \ + install + +install-program: $(EXES) + @if [ ! -d $(install_prefix)$(bindir) ]; then \ + $(INSTALL_DIRS) $(install_prefix)$(bindir) ; \ + fi + @inst="$(INSTALL_PROGRAM)" ; \ + if [ @NEED_SETUID@ = yes ]; then \ + me=`PATH="$$PATH:/usr/ucb" whoami` ; \ + if [ "$$me" = root ]; then \ + inst="$(INSTALL_SETUID)" ; \ + else \ + e=echo ; \ + $$e "" ;\ + $$e " ####################################################################";\ + $$e " Warning: xscreensaver has been compiled with support for shadow" ;\ + $$e " passwords. If your system actually uses shadow passwords," ;\ + $$e " then xscreensaver must be installed as a setuid root" ;\ + $$e " program in order for locking to work. To do this, you" ;\ + $$e " must run 'make install' as 'root', not as '$$me'." ;\ + $$e "" ;\ + $$e " For now, xscreensaver will be installed non-setuid, which" ;\ + $$e " means that locking might not work. (Try it and see.)" ;\ + $$e " ####################################################################";\ + $$e "" ;\ + fi ; \ + fi ; \ + echo $$inst xscreensaver $(install_prefix)$(bindir)/xscreensaver ; \ + $$inst xscreensaver $(install_prefix)$(bindir)/xscreensaver + @for exe in xscreensaver-command xscreensaver-demo \ + xscreensaver-getimage @EXES_OSX@ ; do \ + echo $(INSTALL_PROGRAM) $$exe $(install_prefix)$(bindir)/$$exe ; \ + $(INSTALL_PROGRAM) $$exe $(install_prefix)$(bindir)/$$exe ; \ + done + +install-ad: XScreenSaver.ad + @if [ ! -d $(install_prefix)$(AD_DIR) ]; then \ + $(INSTALL_DIRS) $(install_prefix)$(AD_DIR) ; \ + fi + @-echo $(INSTALL_DATA) XScreenSaver.ad \ + $(install_prefix)$(AD_DIR)/XScreenSaver ; \ + if $(INSTALL_DATA) XScreenSaver.ad \ + $(install_prefix)$(AD_DIR)/XScreenSaver ; then \ + true ; \ + else \ + e=echo ; \ + if [ -f $(install_prefix)$(AD_DIR)/XScreenSaver ]; then \ + $$e "" ;\ + $$e " ####################################################################";\ + $$e " Warning: unable to install $(install_prefix)$(AD_DIR)/XScreenSaver" ;\ + $$e " That file exists, and is unwritable. It is probably from" ;\ + $$e " an older version of xscreensaver, and could cause things" ;\ + $$e " to malfunction. Please delete it!" ;\ + $$e " ####################################################################";\ + $$e "" ;\ + exit 1 ; \ + else \ + $$e "" ;\ + $$e " ####################################################################";\ + $$e " Warning: unable to install $(install_prefix)$(AD_DIR)/XScreenSaver" ;\ + $$e " The directory is unwritable. This is probably ok;" ;\ + $$e " xscreensaver should work without that file." ;\ + $$e " ####################################################################";\ + $$e "" ;\ + exit 0 ; \ + fi \ + fi + +install-scripts: $(SCRIPTS) munge-scripts + @for program in $(SCRIPTS); do \ + if [ -r $$program ] ; then \ + p=$$program ; \ + else \ + p=$(srcdir)/$$program ; \ + fi ; \ + echo $(INSTALL_SCRIPT) $$p \ + $(install_prefix)$(bindir)/$$program ; \ + $(INSTALL_SCRIPT) $$p \ + $(install_prefix)$(bindir)/$$program ; \ + done + +munge-scripts: $(SCRIPTS) + @tmp=/tmp/mf.$$$$ ; \ + perl="${PERL}" ; \ + rm -f $$tmp ; \ + for program in $(SCRIPTS); do \ + sed "s@^\(#!\)\(/[^ ]*/perl[^ ]*\)\(.*\)\$$@\1$$perl\3@" \ + < $(srcdir)/$$program > $$tmp ; \ + if cmp -s $(srcdir)/$$program $$tmp ; then \ + true ; \ + else \ + echo "$$program: setting interpreter to $$perl" >&2 ; \ + cat $$tmp > ./$$program ; \ + fi ; \ + done ; \ + rm -f $$tmp + +# When installing man pages, we install "foo.man" as "foo.N" and update +# the .TH line in the installed file with one like +# +# .TH XScreenSaver N "V.VV (DD-MMM-YYYY)" "X Version 11" +# +# where N is the manual section suffix. +# +install-man: $(MEN) + @men="$(MEN)" ; \ + U=$(UTILS_SRC)/version.h ; \ + V=`sed -n 's/.*xscreensaver \([0-9]\.[^)]*)\).*/\1/p' < $$U` ; \ + T=/tmp/xs$$$$.$(mansuffix) ; \ + TH=".TH XScreenSaver $(mansuffix) \"$$V\" \"X Version 11\"" ; \ + echo "installing man pages: $$TH" ; \ + \ + if [ ! -d $(install_prefix)$(manNdir) ]; then \ + $(INSTALL_DIRS) $(install_prefix)$(manNdir) ; \ + fi ; \ + \ + for man in $$men; do \ + instname=`echo $$man | sed 's/\.man$$/\.$(mansuffix)/'` ; \ + manbase=`echo $$man | sed 's/\.man$$//'` ; \ + TH=".TH $$manbase $(mansuffix) \"$$V\" \"X Version 11\" \"XScreenSaver manual\"" ; \ + sed -e "s/^\.TH.*/$$TH/" \ + -e 's/^\(\.BR xscr.*(\)[^()]\(.*\)/\1$(mansuffix)\2/' \ + -e 's@(MANSUFFIX)@($(mansuffix))@g' \ + < $(srcdir)/$$man > $$T ; \ + echo $(INSTALL_DATA) $(srcdir)/$$man \ + $(install_prefix)$(manNdir)/$$instname ; \ + $(INSTALL_DATA) $$T \ + $(install_prefix)$(manNdir)/$$instname ; \ + done ; \ + rm -f $$T + +uninstall-program: + @for program in $(EXES) $(SCRIPTS); do \ + echo rm -f $(install_prefix)$(bindir)/$$program ; \ + rm -f $(install_prefix)$(bindir)/$$program ; \ + done + +uninstall-ad: + rm -f $(install_prefix)$(AD_DIR)/XScreenSaver + +uninstall-man: + @men="$(MEN)" ; \ + for man in $$men; do \ + instname=`echo $$man | sed 's/\.man$$/\.$(mansuffix)/'` ; \ + echo rm -f $(install_prefix)$(manNdir)/$$instname* ; \ + rm -f $(install_prefix)$(manNdir)/$$instname* ; \ + done + +install-pam: xscreensaver.pam + @src="xscreensaver.pam" ; \ + dest=`sed -n 's/.*PAM_SERVICE_NAME[ ]*"\([^"]*\)".*$$/\1/p' \ + < ../config.h` ; \ + dir="$(install_prefix)$(PAM_DIR)" ; \ + conf="$(PAM_CONF)" ; \ + \ + if [ -d $$dir ] ; then \ + \ + if [ -f $$dir/xdm ]; then \ + src2=$$dir/xdm ; \ + elif [ -f $$dir/login ]; then \ + src2=$$dir/login ; \ + fi ; \ + \ + if [ -z "$$src2" ]; then \ + echo $(INSTALL_DATA) $$src $$dir/$$dest ; \ + $(INSTALL_DATA) $$src $$dir/$$dest ; \ + else \ + src="xscreensaver.pam.$$$$" ; \ + echo "grep '^#%\|^auth\|^@include' $$src2 > $$src" ; \ + grep '^#%\|^auth\|^@include' $$src2 > $$src ; \ + echo $(INSTALL_DATA) $$src $$dir/$$dest ; \ + $(INSTALL_DATA) $$src $$dir/$$dest ; \ + echo rm -f $$src ; \ + rm -f $$src ; \ + fi ; \ + \ + if [ ! -f $$dir/$$dest ]; then \ + e=echo ; \ + $$e "" ;\ + $$e " ####################################################################";\ + $$e " Warning: xscreensaver has been compiled with support for Pluggable" ;\ + $$e " Authentication Modules (PAM). However, we were unable to" ;\ + $$e " install the file $$dir/$$dest. PAM is unlikely" ;\ + $$e " to work without this file (and old-style password" ;\ + $$e " authentication will be used instead, which may or may not" ;\ + $$e " work.)" ;\ + $$e " ####################################################################";\ + $$e "" ;\ + fi ; \ + elif [ -f $$conf -a "x$$dest" != "x" ]; then \ + if ( grep $$dest $$conf >/dev/null ); then \ + echo "$$conf unchanged: already has an entry for $$dest" ; \ + else \ + src="pam.conf.$$$$" ; \ + echo "grep -v $$dest $$conf > $$src" ; \ + grep -v $$dest $$conf > $$src ; \ + extras=`sed -n "s/^login\(.*auth.*\)$$/$$dest\1/p" $$conf`; \ + echo "$$extras" >> $$src ; \ + if [ "x$$extras" = "x" ]; then \ + echo "Error: no login rules in $$conf?" >&2 ; \ + else \ + echo "adding $$dest rules to $$src:" ; \ + echo "$$extras" | sed 's/^/ /' ; \ + fi ; \ + echo $(INSTALL_DATA) $$src $$conf ; \ + $(INSTALL_DATA) $$src $$conf ; \ + echo rm -f $$src ; \ + rm -f $$src ; \ + fi ; \ + if ( grep $$dest $$conf >/dev/null ); then \ + echo ; \ + else \ + e=echo ; \ + $$e "" ;\ + $$e " ####################################################################";\ + $$e " Warning: xscreensaver has been compiled with support for Pluggable" ;\ + $$e " Authentication Modules (PAM). However, we were unable to" ;\ + $$e " install xscreensaver rules in the file $$conf." ;\ + $$e " PAM is unlikely to work without this (and old-style" ;\ + $$e " password authentication will be used instead, which may" ;\ + $$e " or may not work.)" ;\ + $$e " ####################################################################";\ + $$e "" ;\ + fi ; \ + fi + +# screensaver-properties.desktop +# into /usr/share/applications/ +install-gnome:: screensaver-properties.desktop + @if [ "$(GTK_DATADIR)" != "" ]; then \ + if [ ! -d "$(install_prefix)$(GTK_APPDIR)" ]; then \ + echo $(INSTALL_DIRS) "$(install_prefix)$(GTK_APPDIR)" ;\ + $(INSTALL_DIRS) "$(install_prefix)$(GTK_APPDIR)" ;\ + fi ;\ + name2=xscreensaver-properties.desktop ;\ + echo $(INSTALL_DATA) screensaver-properties.desktop \ + $(install_prefix)$(GTK_APPDIR)/$$name2 ;\ + $(INSTALL_DATA) screensaver-properties.desktop \ + $(install_prefix)$(GTK_APPDIR)/$$name2 ;\ + fi + + +# xscreensaver.xpm +# into /usr/share/pixmaps/ +install-gnome:: $(LOGO) + @if [ "$(GTK_DATADIR)" != "" ]; then \ + if [ ! -d "$(install_prefix)$(GTK_ICONDIR)" ]; then \ + echo $(INSTALL_DIRS) "$(install_prefix)$(GTK_ICONDIR)" ;\ + $(INSTALL_DIRS) "$(install_prefix)$(GTK_ICONDIR)" ;\ + fi ;\ + target=xscreensaver.xpm ;\ + echo $(INSTALL_DATA) $(LOGO) \ + $(install_prefix)$(GTK_ICONDIR)/$$target ;\ + $(INSTALL_DATA) $(LOGO) \ + $(install_prefix)$(GTK_ICONDIR)/$$target ;\ + fi + +# ../utils/images/screensaver-*.png +# into /usr/share/xscreensaver/glade/ +install-gnome:: + @if [ "$(GTK_DATADIR)" != "" ]; then \ + if [ ! -d "$(install_prefix)$(GTK_GLADEDIR)" ]; then \ + echo $(INSTALL_DIRS) "$(install_prefix)$(GTK_GLADEDIR)" ;\ + $(INSTALL_DIRS) "$(install_prefix)$(GTK_GLADEDIR)" ;\ + fi ;\ + for target in $(GTK_ICONS) ; do \ + dest=`echo $$target | sed 's@^.*/@@'` ;\ + echo $(INSTALL_DATA) $$target \ + $(install_prefix)$(GTK_GLADEDIR)/$$dest ;\ + $(INSTALL_DATA) $$target \ + $(install_prefix)$(GTK_GLADEDIR)/$$dest ;\ + done ;\ + fi + +# xscreensaver-demo.glade2 +# into /usr/share/xscreensaver/glade/ +install-gnome:: xscreensaver-demo.glade2 + @if [ "$(GTK_DATADIR)" != "" ]; then \ + if [ ! -d "$(install_prefix)$(GTK_GLADEDIR)" ]; then \ + echo $(INSTALL_DIRS) "$(install_prefix)$(GTK_GLADEDIR)" ;\ + $(INSTALL_DIRS) "$(install_prefix)$(GTK_GLADEDIR)" ;\ + fi ;\ + target=xscreensaver-demo.glade2 ;\ + echo $(INSTALL_DATA) $(srcdir)/$$target \ + $(install_prefix)$(GTK_GLADEDIR)/$$target ;\ + if $(INSTALL_DATA) $(srcdir)/$$target \ + $(install_prefix)$(GTK_GLADEDIR)/$$target ;\ + then true ;\ + else \ + e=echo ; \ + $$e "" ;\ + $$e " ####################################################################";\ + $$e " Warning: unable to install $$target into" ;\ + $$e " $(install_prefix)$(GTK_GLADEDIR)/." ;\ + $$e " Without this file, xscreensaver-demo will not" ;\ + $$e " be able to run properly." ;\ + $$e " ####################################################################";\ + $$e "" ;\ + exit 1 ; \ + fi ; \ + fi + + +# screensaver-properties.desktop +# into /usr/share/applications/ +uninstall-gnome:: + @if [ "$(GTK_DATADIR)" != "" ]; then \ + f=xscreensaver-properties.desktop ;\ + echo rm -f $(install_prefix)$(GTK_APPDIR)/$$f ;\ + rm -f $(install_prefix)$(GTK_APPDIR)/$$f ;\ + fi + +# xscreensaver.xpm +# into /usr/share/pixmaps/ +uninstall-gnome:: + @if [ "$(GTK_ICONDIR)" != "" ]; then \ + target=xscreensaver.xpm ;\ + echo rm -f $(install_prefix)$(GTK_ICONDIR)/$$target ;\ + rm -f $(install_prefix)$(GTK_ICONDIR)/$$target ;\ + fi + +# ../utils/images/screensaver-*.png +# into /usr/share/xscreensaver/glade/ +uninstall-gnome:: + @if [ "$(GTK_DATADIR)" != "" ]; then \ + for target in $(GTK_ICONS) ; do \ + dest=`echo $$target | sed 's@^.*/@@'` ;\ + echo rm -f $(install_prefix)$(GTK_GLADEDIR)/$$dest ;\ + rm -f $(install_prefix)$(GTK_GLADEDIR)/$$dest ;\ + done ;\ + fi + +# xscreensaver-demo.glade2 +# into /usr/share/xscreensaver/glade/ +uninstall-gnome:: xscreensaver-demo.glade2 + @if [ "$(GTK_DATADIR)" != "" ]; then \ + target=xscreensaver-demo.glade2 ;\ + echo rm -f $(install_prefix)$(GTK_GLADEDIR)/$$target ;\ + rm -f $(install_prefix)$(GTK_GLADEDIR)/$$target ;\ + fi + +# /usr/share/xscreensaver/config/README +install-xml: + @dest=$(install_prefix)$(HACK_CONF_DIR) ; \ + if [ ! -d $$dest ]; then \ + $(INSTALL_DIRS) $$dest ; \ + fi ; \ + src=$(srcdir)/../hacks/config ; \ + echo $(INSTALL_DATA) $$src/README $$dest/README ; \ + $(INSTALL_DATA) $$src/README $$dest/README + + +# /usr/share/xscreensaver/config/README +uninstall-xml: + rm -f $(install_prefix)$(HACK_CONF_DIR)/README + +clean: + -rm -f *.o a.out core $(EXES) $(EXES2) $(TEST_EXES) \ + XScreenSaver_ad.h XScreenSaver_Xm_ad.h + +distclean: clean + -rm -f Makefile XScreenSaver.ad \ + TAGS *~ "#"* screensaver-properties.desktop + +# Adds all current dependencies to Makefile +depend: XScreenSaver_ad.h XScreenSaver_Xm_ad.h + $(DEPEND) -s '# DO NOT DELETE: updated by make depend' \ + $(DEPEND_FLAGS) -- \ + $(INCLUDES_1) $(DEFS) $(DEPEND_DEFINES) $(CFLAGS) $(X_CFLAGS) -- \ + $(SAVER_SRCS) $(CMD_SRCS) $(GETIMG_SRCS_1) + +# Adds some dependencies to Makefile.in -- not totally accurate, but pretty +# close. This excludes dependencies on files in /usr/include, etc. It tries +# to include only dependencies on files which are themselves a part of this +# package. +distdepend: check_men update_ad_version XScreenSaver_ad.h XScreenSaver_Xm_ad.h + @echo updating dependencies in `pwd`/Makefile.in... ; \ + $(DEPEND) -w 0 -f - \ + -s '# DO NOT DELETE: updated by make distdepend' $(DEPEND_FLAGS) -- \ + $(INCLUDES_1) $(DEFS) $(DEPEND_DEFINES) $(CFLAGS) $(X_CFLAGS) -- \ + $(SAVER_SRCS_1) $(MOTIF_SRCS) $(GTK_SRCS) $(GETIMG_SRCS_1) \ + $(PWENT_SRCS) $(LOCK_SRCS_1) $(DEMO_SRCS_1) $(CMD_SRCS) \ + $(TEST_SRCS) 2>/dev/null | \ + sort -d | \ + ( \ + awk '/^# .*Makefile.in ---/,/^# DO .*distdepend/' < Makefile.in ; \ + sed -e '/^#.*/d' \ + -e 's@ \./@ @g;s@ /[^ ]*@@g;/^.*:$$/d' \ + -e 's@\.\./utils@$$(UTILS_SRC)@g' \ + -e 's@ \([^$$]\)@ $$(srcdir)/\1@g' \ + -e 's@$$.*\(XScreenSaver_ad\)@\1@g' \ + -e 's@$$.*\(XScreenSaver_Xm_ad\)@\1@g' \ + -e 's@ $$(srcdir)/\(.*config\.h\)@ \1@g' ; \ + echo '' \ + ) > /tmp/distdepend.$$$$ && \ + mv Makefile.in Makefile.in.bak && \ + mv /tmp/distdepend.$$$$ Makefile.in + +# Updates the version number in the app-defaults file to be in sync with +# the version number in version.h. This is so people can tell when they +# have a version skew between the app-defaults file and the executable. +# Also update hacks/config/README in the same way. +update_ad_version:: + @ \ + files="XScreenSaver.ad.in ../hacks/config/README ../OSX/bindist.rtf" ; \ + U=$(UTILS_SRC)/version.h ; \ + V=`sed -n 's/[^0-9]*\([0-9]\.[0-9][^. ]*\).*/\1/p' < $$U` ; \ + Y=`date '+%Y'` ; \ + D=`date '+%d-%b-%Y'` ; \ + for S in $$files ; do \ + T=/tmp/xs.$$$$ ; \ + sed -e "s/\(.*version \)[0-9][0-9]*\.[0-9]*[ab]*[0-9]*\(.*\)/\1$$V\2/" \ + -e "s/\([0-9][0-9]-[A-Z][a-z][a-z]-[0-9][0-9][0-9]*\)/$$D/" \ + -e "s/\( [0-9][0-9][0-9][0-9]-\)[0-9][0-9][0-9][0-9] /\1$$Y /" \ + < $$S > $$T ; \ + if cmp -s $$S $$T ; then \ + true ; \ + else \ + cat $$T > $$S ; \ + echo "updated $$S to $$V $$D" ; \ + fi ; \ + done ; \ + rm $$T + +TAGS: tags +tags: + find $(srcdir) -name '*.[chly]' -print | xargs etags -a + +echo_tarfiles: + @$(MAKE) XScreenSaver_ad.h XScreenSaver_Xm_ad.h 2>&1 >/dev/null + @echo $(TARFILES) + +check_men: + @badmen="" ; \ + for exe in $(EXES); do \ + if ! [ -f $(srcdir)/$$exe.man ]; then \ + badmen="$$badmen $$exe" ; \ + fi ; \ + done ; \ + if [ -n "$$badmen" ]; then \ + echo "" ; \ + echo "Warning: The following programs have no manuals:" ; \ + echo "" ; \ + for m in $$badmen ; do \ + echo " $$m" ; \ + done ; \ + echo "" ; \ + fi + + +# Rules for noticing when the objects from the utils directory are out of +# date with respect to their sources, and going and building them according +# to the rules in their own Makefile... +# +$(UTILS_BIN)/fade.o: $(UTILS_SRC)/fade.c +$(UTILS_BIN)/overlay.o: $(UTILS_SRC)/overlay.c +$(UTILS_BIN)/resources.o: $(UTILS_SRC)/resources.c +$(UTILS_BIN)/usleep.o: $(UTILS_SRC)/usleep.c +$(UTILS_BIN)/visual.o: $(UTILS_SRC)/visual.c +$(UTILS_BIN)/xmu.o: $(UTILS_SRC)/xmu.c +$(UTILS_BIN)/logo.o: $(UTILS_SRC)/logo.c +$(UTILS_BIN)/minixpm.o: $(UTILS_SRC)/minixpm.c +$(UTILS_BIN)/yarandom.o: $(UTILS_SRC)/yarandom.c +$(UTILS_BIN)/colorbars.o: $(UTILS_SRC)/colorbars.c + +$(SAVER_UTIL_OBJS): + cd $(UTILS_BIN) ; \ + $(MAKE) $(@F) CC="$(CC)" CFLAGS="$(CFLAGS)" LDFLAGS="$(LDFLAGS)" + +# How we build object files in this directory. +.c.o: + $(CC) -c $(INCLUDES) $(DEFS) $(CFLAGS) $(X_CFLAGS) $< + +.m.o: + $(OBJCC) -c $(INCLUDES) $(DEFS) $(CFLAGS) $(X_CFLAGS) $< + +# subprocs takes an extra -D option. +subprocs.o: subprocs.c + $(CC) -c $(INCLUDES) $(SUBP_DEFS) $(CFLAGS) $(X_CFLAGS) \ + $(srcdir)/subprocs.c + +# xscreensaver takes an extra -D option. +xscreensaver.o: xscreensaver.c + $(CC) -c $(INCLUDES) $(DEFS) $(INTL_DEFS) $(CFLAGS) $(X_CFLAGS) \ + $(srcdir)/xscreensaver.c + +# demo-Gtk takes extra -D options, and an extra -I option. +demo-Gtk.o: demo-Gtk.c + $(CC) -c $(INCLUDES) $(SUBP_DEFS) -I$(ICON_SRC) \ + $(GTK_DEFS) $(INTL_DEFS) $(CFLAGS) $(X_CFLAGS) \ + $(srcdir)/demo-Gtk.c + +# demo-Gtk-conf takes an extra -D option. +demo-Gtk-conf.o: demo-Gtk-conf.c + $(CC) -c $(INCLUDES) $(CONF_DEFS) $(GTK_DEFS) $(CFLAGS) $(X_CFLAGS) \ + $(srcdir)/demo-Gtk-conf.c + + +# How we build the default app-defaults file into the program. +# +XScreenSaver_ad.h: XScreenSaver.ad + $(SHELL) $(UTILS_SRC)/ad2c XScreenSaver.ad > XScreenSaver_ad.h + +XScreenSaver_Xm_ad.h: XScreenSaver-Xm.ad + $(SHELL) $(UTILS_SRC)/ad2c XScreenSaver-Xm.ad > XScreenSaver_Xm_ad.h + +@INTLTOOL_DESKTOP_RULE@ + +# The executables linked in this directory. +# +xscreensaver: $(SAVER_OBJS) + $(CC) $(LDFLAGS) -o $@ $(SAVER_OBJS) $(SAVER_LIBS) + +xscreensaver-command: $(CMD_OBJS) + $(CC) $(LDFLAGS) -o $@ $(CMD_OBJS) $(CMD_LIBS) + + +xscreensaver-demo: @PREFERRED_DEMO_PROGRAM@ + @if [ "@PREFERRED_DEMO_PROGRAM@" = "" ]; then \ + echo "WARNING: neither GTK nor Motif are available," \ + "therefore no xscreensaver-demo!" ; \ + rm -f $@@EXEEXT@ ; \ + else \ + echo cp -p @PREFERRED_DEMO_PROGRAM@@EXEEXT@ $@@EXEEXT@ ; \ + cp -p @PREFERRED_DEMO_PROGRAM@@EXEEXT@ $@@EXEEXT@ ; \ + fi + +xscreensaver-demo-Xm: $(DEMO_OBJS) $(MOTIF_OBJS) + $(CC) $(LDFLAGS) -o $@ $(DEMO_OBJS) $(MOTIF_OBJS) $(LIBS) $(X_LIBS) \ + $(MOTIF_LIBS) $(INTL_LIBS) $(X_PRE_LIBS) -lXt -lX11 \ + $(XDPMS_LIBS) $(XINERAMA_LIBS) -lXext $(X_EXTRA_LIBS) + +xscreensaver-demo-Gtk: $(DEMO_OBJS) $(GTK_OBJS) + $(CC) $(LDFLAGS) -o $@ $(DEMO_OBJS) $(GTK_OBJS) $(LIBS) $(X_LIBS) \ + $(GTK_LIBS) $(XPM_LIBS) $(XML_LIBS) $(INTL_LIBS) $(X_PRE_LIBS) \ + -lXt -lX11 $(XDPMS_LIBS) $(XINERAMA_LIBS) -lXext $(X_EXTRA_LIBS) + +demo-Gtk.o: XScreenSaver_ad.h +demo-Xm.o: XScreenSaver_Xm_ad.h +xscreensaver.o: XScreenSaver_ad.h +xscreensaver-getimage.o: XScreenSaver_ad.h + +xscreensaver-getimage: $(GETIMG_OBJS) + $(CC) $(LDFLAGS) -o $@ $(GETIMG_OBJS) $(GETIMG_LIBS) -lm + +pdf2jpeg: $(PDF2JPEG_OBJS) + $(OBJCC) $(LDFLAGS) -o $@ $(PDF2JPEG_OBJS) $(PDF2JPEG_LIBS) -lm + + +TEST_PASSWD_OBJS = test-passwd.o $(LOCK_OBJS_1) $(PASSWD_OBJS) \ + subprocs.o setuid.o splash.o prefs.o mlstring.o exec.o \ + $(SAVER_UTIL_OBJS) +test-passwd.o: XScreenSaver_ad.h + +test-passwd: $(TEST_PASSWD_OBJS) XScreenSaver_ad.h + $(CC) $(LDFLAGS) -o $@ $(TEST_PASSWD_OBJS) $(SAVER_LIBS) + +test-uid: test-uid.o + $(CC) $(LDFLAGS) -o $@ test-uid.o + +test-xdpms: test-xdpms.o + $(CC) $(LDFLAGS) -o $@ test-xdpms.o $(LIBS) $(X_LIBS) $(XDPMS_LIBS) \ + $(X_PRE_LIBS) -lXt -lX11 -lXext $(X_EXTRA_LIBS) + +test-xinerama: test-xinerama.o + $(CC) $(LDFLAGS) -o $@ test-xinerama.o $(LIBS) $(X_LIBS) $(SAVER_LIBS) \ + $(X_PRE_LIBS) $(XINERAMA_LIBS) -lXt -lX11 -lXext $(X_EXTRA_LIBS) + +test-vp: test-vp.o + $(CC) $(LDFLAGS) -o $@ test-vp.o $(LIBS) $(X_LIBS) $(SAVER_LIBS) \ + $(X_PRE_LIBS) -lXt -lX11 -lXext $(X_EXTRA_LIBS) + +test-randr: test-randr.o + $(CC) $(LDFLAGS) -o $@ test-randr.o $(LIBS) $(X_LIBS) $(SAVER_LIBS) \ + $(X_PRE_LIBS) -lXt -lX11 -lXext $(X_EXTRA_LIBS) + +test-grab: test-grab.o + $(CC) $(LDFLAGS) -o $@ test-grab.o $(SAVER_LIBS) + +test-apm: test-apm.o + $(CC) $(LDFLAGS) -o $@ test-apm.o $(SAVER_LIBS) -lapm + +test-mlstring.o: mlstring.c +test-mlstring: test-mlstring.o + $(CC) -DTEST $(LDFLAGS) -o $@ test-mlstring.o $(SAVER_LIBS) + +TEST_FADE_OBJS = test-fade.o $(UTILS_SRC)/fade.o $(DEMO_UTIL_OBJS) +test-fade: test-fade.o $(UTILS_BIN)/fade.o + $(CC) $(LDFLAGS) -o $@ $(TEST_FADE_OBJS) $(SAVER_LIBS) + +TEST_SCREENS_OBJS = test-screens.o $(DEMO_UTIL_OBJS) +test-screens.o: screens.c +test-screens: test-screens.o + $(CC) $(LDFLAGS) -o $@ $(TEST_SCREENS_OBJS) $(SAVER_LIBS) + + +xdpyinfo.o: xdpyinfo.c + $(CC) -c $(INCLUDES) -DHAVE_GLX $(CFLAGS) $(X_CFLAGS) \ + $(srcdir)/xdpyinfo.c + +xdpyinfo: xdpyinfo.o + $(CC) $(LDFLAGS) -o $@ xdpyinfo.o \ + $(LIBS) $(X_LIBS) @GL_LIBS@ \ + $(X_PRE_LIBS) -lX11 -lXext $(X_EXTRA_LIBS) -lm + + +############################################################################## +# +# DO NOT DELETE: updated by make distdepend + +demo-Gtk-conf.o: ../config.h +demo-Gtk.o: ../config.h +demo-Gtk-support.o: ../config.h +demo-Gtk-support.o: $(srcdir)/demo-Gtk-support.h +demo-Gtk-widgets.o: ../config.h +demo-Gtk-widgets.o: $(srcdir)/demo-Gtk-stubs.h +demo-Gtk-widgets.o: $(srcdir)/demo-Gtk-support.h +demo-Gtk-widgets.o: $(srcdir)/demo-Gtk-widgets.h +demo-Xm.o: ../config.h +demo-Xm-widgets.o: ../config.h +dpms.o: ../config.h +dpms.o: $(srcdir)/prefs.h +dpms.o: $(srcdir)/types.h +dpms.o: $(srcdir)/xscreensaver.h +exec.o: ../config.h +exec.o: $(srcdir)/exec.h +lock.o: $(srcdir)/auth.h +lock.o: ../config.h +lock.o: $(srcdir)/mlstring.h +lock.o: $(srcdir)/prefs.h +lock.o: $(srcdir)/types.h +lock.o: $(UTILS_SRC)/resources.h +lock.o: $(srcdir)/xscreensaver.h +mlstring.o: $(srcdir)/mlstring.h +passwd.o: $(srcdir)/auth.h +passwd.o: ../config.h +passwd.o: $(srcdir)/prefs.h +passwd.o: $(srcdir)/types.h +passwd.o: $(srcdir)/xscreensaver.h +passwd-pwent.o: ../config.h +prefs.o: ../config.h +prefs.o: $(srcdir)/prefs.h +prefs.o: $(srcdir)/types.h +prefs.o: $(UTILS_SRC)/resources.h +remote.o: ../config.h +remote.o: $(srcdir)/remote.h +screens.o: ../config.h +screens.o: $(srcdir)/prefs.h +screens.o: $(srcdir)/types.h +screens.o: $(UTILS_SRC)/visual.h +screens.o: $(srcdir)/xscreensaver.h +setuid.o: ../config.h +setuid.o: $(srcdir)/prefs.h +setuid.o: $(srcdir)/types.h +setuid.o: $(srcdir)/xscreensaver.h +splash.o: ../config.h +splash.o: $(srcdir)/prefs.h +splash.o: $(srcdir)/types.h +splash.o: $(UTILS_SRC)/resources.h +splash.o: $(srcdir)/xscreensaver.h +stderr.o: ../config.h +stderr.o: $(srcdir)/prefs.h +stderr.o: $(srcdir)/types.h +stderr.o: $(UTILS_SRC)/resources.h +stderr.o: $(UTILS_SRC)/visual.h +stderr.o: $(srcdir)/xscreensaver.h +subprocs.o: ../config.h +subprocs.o: $(srcdir)/exec.h +subprocs.o: $(srcdir)/prefs.h +subprocs.o: $(srcdir)/types.h +subprocs.o: $(UTILS_SRC)/visual.h +subprocs.o: $(UTILS_SRC)/yarandom.h +subprocs.o: $(srcdir)/xscreensaver.h +test-apm.o: ../config.h +test-fade.o: ../config.h +test-fade.o: $(srcdir)/prefs.h +test-fade.o: $(srcdir)/types.h +test-fade.o: $(UTILS_SRC)/fade.h +test-fade.o: $(srcdir)/xscreensaver.h +test-grab.o: ../config.h +test-mlstring.o: $(srcdir)/mlstring.c +test-mlstring.o: $(srcdir)/mlstring.h +test-passwd.o: XScreenSaver_ad.h +test-passwd.o: $(srcdir)/auth.h +test-passwd.o: ../config.h +test-passwd.o: $(srcdir)/prefs.h +test-passwd.o: $(srcdir)/types.h +test-passwd.o: $(UTILS_SRC)/resources.h +test-passwd.o: $(UTILS_SRC)/version.h +test-passwd.o: $(UTILS_SRC)/visual.h +test-passwd.o: $(srcdir)/xscreensaver.h +test-randr.o: ../config.h +test-screens.o: ../config.h +test-screens.o: $(srcdir)/prefs.h +test-screens.o: $(srcdir)/screens.c +test-screens.o: $(srcdir)/types.h +test-screens.o: $(UTILS_SRC)/visual.h +test-screens.o: $(srcdir)/xscreensaver.h +test-uid.o: ../config.h +test-vp.o: ../config.h +test-xdpms.o: ../config.h +test-xinerama.o: ../config.h +timers.o: ../config.h +timers.o: $(srcdir)/prefs.h +timers.o: $(srcdir)/types.h +timers.o: $(srcdir)/xscreensaver.h +windows.o: ../config.h +windows.o: $(srcdir)/prefs.h +windows.o: $(srcdir)/types.h +windows.o: $(UTILS_SRC)/fade.h +windows.o: $(UTILS_SRC)/visual.h +windows.o: $(srcdir)/xscreensaver.h +xscreensaver-command.o: ../config.h +xscreensaver-command.o: $(srcdir)/remote.h +xscreensaver-command.o: $(UTILS_SRC)/version.h +xscreensaver-getimage.o: ../config.h +xscreensaver-getimage.o: XScreenSaver_ad.h +xscreensaver-getimage.o: $(srcdir)/prefs.h +xscreensaver-getimage.o: $(srcdir)/types.h +xscreensaver-getimage.o: $(UTILS_SRC)/colorbars.h +xscreensaver-getimage.o: $(UTILS_SRC)/grabscreen.h +xscreensaver-getimage.o: $(UTILS_SRC)/resources.h +xscreensaver-getimage.o: $(UTILS_SRC)/utils.h +xscreensaver-getimage.o: $(UTILS_SRC)/version.h +xscreensaver-getimage.o: $(UTILS_SRC)/visual.h +xscreensaver-getimage.o: $(UTILS_SRC)/vroot.h +xscreensaver-getimage.o: $(UTILS_SRC)/yarandom.h +xscreensaver.o: XScreenSaver_ad.h +xscreensaver.o: $(srcdir)/auth.h +xscreensaver.o: ../config.h +xscreensaver.o: $(srcdir)/prefs.h +xscreensaver.o: $(srcdir)/types.h +xscreensaver.o: $(UTILS_SRC)/resources.h +xscreensaver.o: $(UTILS_SRC)/usleep.h +xscreensaver.o: $(UTILS_SRC)/version.h +xscreensaver.o: $(UTILS_SRC)/visual.h +xscreensaver.o: $(UTILS_SRC)/yarandom.h +xscreensaver.o: $(srcdir)/xscreensaver.h +xset.o: ../config.h +xset.o: $(srcdir)/prefs.h +xset.o: $(srcdir)/types.h +xset.o: $(srcdir)/xscreensaver.h + diff --git a/driver/README b/driver/README new file mode 100644 index 00000000..df64793b --- /dev/null +++ b/driver/README @@ -0,0 +1,6 @@ + +This directory contains the source for xscreensaver and xscreensaver-command, +the screensaver driver, and the program for externally controlling it. Some +stuff from the ../utils/ directory is used here as well. + +If you have compilation problems, check the parameters in ../config.h. diff --git a/driver/XScreenSaver-Xm.ad b/driver/XScreenSaver-Xm.ad new file mode 100644 index 00000000..6b04ae97 --- /dev/null +++ b/driver/XScreenSaver-Xm.ad @@ -0,0 +1,126 @@ +! Resources for the Motif dialog boxes of the "xscreensaver-demo" program. +! +*fontList: *-helvetica-medium-r-*-*-*-120-*-*-*-iso8859-1 +*demoDialog*label1.fontList: *-helvetica-medium-r-*-*-*-140-*-*-*-iso8859-1 +*cmdText.fontList: *-courier-medium-r-*-*-*-120-*-*-*-iso8859-1 +*label0.fontList: *-helvetica-bold-r-*-*-*-140-*-*-*-iso8859-1 +XScreenSaver*doc.fontList: *-helvetica-medium-r-*-*-*-100-*-*-*-iso8859-1 +! above must be fully qualified to get around *sgiMode. + +*foreground: #000000 +*background: #C0C0C0 +*XmTextField.foreground: #000000 +*XmTextField.background: #FFFFFF +*list.foreground: #000000 +*list.background: #FFFFFF + +*ApplicationShell.title: XScreenSaver +*warning.title: XScreenSaver +*warning_popup.title: XScreenSaver +*allowShellResize: True +*autoUnmanage: False + +*menubar*file.labelString: File +*menubar*file.mnemonic: F +*file.blank.labelString: Blank Screen Now +*file.blank.mnemonic: B +*file.lock.labelString: Lock Screen Now +*file.lock.mnemonic: L +*file.kill.labelString: Kill Daemon +*file.kill.mnemonic: K +*file.restart.labelString: Restart Daemon +*file.restart.mnemonic: R +*file.exit.labelString: Exit +*file.exit.mnemonic: E + +*menubar*edit.labelString: Edit +*menubar*edit.mnemonic: E +*edit.cut.labelString: Cut +*edit.cut.mnemonic: u +*edit.copy.labelString: Copy +*edit.copy.mnemonic: C +*edit.paste.labelString: Paste +*edit.paste.mnemonic: P + +*menubar*help.labelString: Help +*menubar*help.mnemonic: H +*help.about.labelString: About... +*help.about.mnemonic: A +*help.docMenu.labelString: Documentation... +*help.docMenu.mnemonic: D + +*demoTab.marginWidth: 10 +*optionsTab.marginWidth: 10 + +*XmScrolledWindow.topOffset: 10 +*XmScrolledWindow.leftOffset: 10 +*demoTab.topOffset: 4 +*form1.bottomOffset: 10 +*form3.leftOffset: 10 +*form3.rightOffset: 10 +*frame.topOffset: 10 +*frame.bottomOffset: 10 +*enabled.topOffset: 10 +*visLabel.topOffset: 10 +*combo.topOffset: 10 +*form4.bottomOffset: 4 +*hr.bottomOffset: 4 +*XmComboBox.marginWidth: 0 +*XmComboBox.marginHeight: 0 + +*demo.marginWidth: 30 +*demo.marginHeight: 4 +*man.marginWidth: 10 +*man.marginHeight: 4 +*down.leftOffset: 40 +*down.marginWidth: 4 +*down.marginHeight: 4 +*up.marginWidth: 4 +*up.marginHeight: 4 +*frame.traversalOn: False + +*list.automaticSelection: True +*list.visibleItemCount: 20 +*doc.columns: 60 +*combo.columns: 11 + +*demoTab.labelString: Graphics Demos +*optionsTab.labelString: Screensaver Options +*down.labelString: \\/ +*up.labelString: /\\ +*frameLabel.labelString: +*cmdLabel.labelString: Command Line: +*cmdLabel.alignment: ALIGNMENT_BEGINNING +*enabled.labelString: Enabled +*visLabel.labelString: Visual: +*visLabel.alignment: ALIGNMENT_END +*visLabel.leftOffset: 20 +*demo.labelString: Demo +*man.labelString: Documentation... +*done.labelString: Quit + +*preferencesLabel.labelString: XScreenSaver Parameters + +*timeoutLabel.labelString: Saver Timeout +*cycleLabel.labelString: Cycle Timeout +*fadeSecondsLabel.labelString: Fade Duration +*fadeTicksLabel.labelString: Fade Ticks +*lockLabel.labelString: Lock Timeout +*passwdLabel.labelString: Password Timeout +*preferencesForm*XmTextField.columns: 8 + +*verboseToggle.labelString: Verbose +*cmapToggle.labelString: Install Colormap +*fadeToggle.labelString: Fade Colormap +*unfadeToggle.labelString: Unfade Colormap +*lockToggle.labelString: Require Password + + +*OK.marginWidth: 30 +*OK.marginHeight: 4 +*OK.leftOffset: 10 +*OK.bottomOffset: 10 +*Cancel.marginWidth: 30 +*Cancel.marginHeight: 4 +*Cancel.rightOffset: 10 +*Cancel.bottomOffset: 10 diff --git a/driver/XScreenSaver.ad.in b/driver/XScreenSaver.ad.in new file mode 100644 index 00000000..020b1ec0 --- /dev/null +++ b/driver/XScreenSaver.ad.in @@ -0,0 +1,503 @@ +! +! XScreenSaver +! +! a screen saver and locker for the X window system +! by Jamie Zawinski +! +! version 5.20 +! 06-Oct-2012 +! +! See "man xscreensaver" for more info. The latest version is always +! available at http://www.jwz.org/xscreensaver/ + + +! These resources, when placed in the system-wide app-defaults directory +! (e.g., /usr/lib/X11/app-defaults/XScreenSaver) will provide the default +! settings for new users. However, if you have a ".xscreensaver" file in +! your home directory, the settings in that file take precedence. + + +! Don't hand this file to "xrdb" -- that isn't how app-defaults files work. +! Though app-defaults files have (mostly) the same syntax as your ~/.Xdefaults +! file, they are used differently, and if you run this file through xrdb, +! you will probably mess things up. + +#error Do not run app-defaults files through xrdb! +#error That does not do what you might expect. +#error Put this file in /usr/lib/X11/app-defaults/XScreenSaver instead. + +! /* (xrdb prevention kludge: whole file) + +*mode: random +*timeout: 0:10:00 +*cycle: 0:10:00 +*lockTimeout: 0:00:00 +*passwdTimeout: 0:00:30 +*dpmsEnabled: False +*dpmsQuickoffEnabled: False +*dpmsStandby: 2:00:00 +*dpmsSuspend: 2:00:00 +*dpmsOff: 4:00:00 +*grabDesktopImages: True +*grabVideoFrames: False +*chooseRandomImages: @DEFAULT_IMAGES_P@ +! This can be a local directory name, or the URL of an RSS or Atom feed. +*imageDirectory: @DEFAULT_IMAGE_DIRECTORY@ +*nice: 10 +*memoryLimit: 0 +*lock: False +*verbose: False +*timestamp: True +*fade: True +*unfade: False +*fadeSeconds: 0:00:03 +*fadeTicks: 20 +*splash: True +*splashDuration: 0:00:05 +*visualID: default +*captureStderr: True +*ignoreUninstalledPrograms: False + +*textMode: file +*textLiteral: XScreenSaver +*textFile: @DEFAULT_TEXT_FILE@ +*textProgram: fortune +*textURL: http://twitter.com/statuses/public_timeline.atom +!*textURL: http://www.livejournal.com/stats/latest-rss.bml + +*overlayTextForeground: #FFFF00 +*overlayTextBackground: #000000 +*overlayStderr: True +*font: *-medium-r-*-140-*-m-* + +! The default is to use these extensions if available (as noted.) +*sgiSaverExtension: True +*xidleExtension: True +*procInterrupts: True + +! Turning this on makes pointerHysteresis not work. +*xinputExtensionDev: False + +! Set this to True if you are experiencing longstanding XFree86 bug #421 +! (xscreensaver not covering the whole screen) +GetViewPortIsFullOfLies: False + +! This is what the "Demo" button on the splash screen runs (/bin/sh syntax.) +*demoCommand: xscreensaver-demo + +! This is what the "Prefs" button on the splash screen runs (/bin/sh syntax.) +*prefsCommand: xscreensaver-demo -prefs + +! This is the URL loaded by the "Help" button on the splash screen, +! and by the "Documentation" menu item in xscreensaver-demo. +*helpURL: http://www.jwz.org/xscreensaver/man.html + +! loadURL -- how the "Help" buttons load the helpURL (/bin/sh syntax.) +! manualCommand -- how the "Documentation" buttons display man pages. +! +! And there are so very many options to choose from! +! +! Gnome 2.4, 2.6: (yelp can't display man pages, as of 2.6.3) +! +@GNOME24@*loadURL: @WITH_BROWSER@ '%s' +@GNOME24@*manualCommand: gnome-terminal --title '%s manual' \ +@GNOME24@ --command '/bin/sh -c "man %s; read foo"' +! +! Gnome 2.2: +! +@GNOME22@*loadURL: gnome-url-show '%s' +@GNOME22@*manualCommand: gnome-terminal --title '%s manual' \ +@GNOME22@ --command '/bin/sh -c "man %s; read foo"' +! +! Gnome 1.4: +! +! *loadURL: gnome-moz-remote --newwin '%s' +! *manualCommand: gnome-help-browser 'man:%s' +! +! non-Gnome systems: +! +@NOGNOME@*loadURL: firefox '%s' || mozilla '%s' || netscape '%s' +@NOGNOME@*manualCommand: xterm -sb -fg black -bg gray75 -T '%s manual' \ +@NOGNOME@ -e /bin/sh -c 'man "%s" ; read foo' + + +! The format used for printing the date and time in the password dialog box +! (see the strftime(3) manual page for details.) +*dateFormat: %d-%b-%y (%a); %I:%M %p +! To show the time only: +! *dateFormat: %I:%M %p +! For 24 hour time: +! *dateFormat: %H:%M + + +! This command is executed by the "New Login" button on the lock dialog. +! (That button does not appear on the dialog if this program does not exist.) +! For Gnome: probably "gdmflexiserver -ls". KDE, probably "kdmctl reserve". +! Or maybe yet another wheel-reinvention, "lxdm -c USER_SWITCH". +! +@NEW_LOGIN_COMMAND_P@*newLoginCommand: @NEW_LOGIN_COMMAND@ + + +! Turning on "installColormap" on 8-bit systems interacts erratically with +! certain jurassic window managers. If your screen turns some color other +! than black, the window manager is buggy, and you need to set this resource +! to false. Or switch WMs. Or join the 21st century and get a 24-bit +! graphics card. +! +*installColormap: True + + +! This is the list of installed screen saver modes. See "man xscreensaver" +! for the syntax used here. +! +! If you want to disable a screensaver, DO NOT remove it from this list: +! instead, mark it as inactive by placing a "-" at the beginning of the line. +! +! You can use the `xscreensaver-demo' program to edit the current list of +! screen savers interactively. +! +*programs: \ + maze -root \n\ +@GL_KLUDGE@ GL: superquadrics -root \n\ + attraction -root \n\ + blitspin -root \n\ + greynetic -root \n\ + helix -root \n\ + hopalong -root \n\ + imsmap -root \n\ +- noseguy -root \n\ +- pyro -root \n\ + qix -root \n\ +- rocks -root \n\ + rorschach -root \n\ + decayscreen -root \n\ + flame -root \n\ + halo -root \n\ + slidescreen -root \n\ + pedal -root \n\ + bouboule -root \n\ +- braid -root \n\ + coral -root \n\ + deco -root \n\ + drift -root \n\ +- fadeplot -root \n\ + galaxy -root \n\ + goop -root \n\ + grav -root \n\ + ifs -root \n\ +@GL_KLUDGE@ GL: jigsaw -root \n\ + julia -root \n\ +- kaleidescope -root \n\ +@GL_KLUDGE@ GL: moebius -root \n\ + moire -root \n\ +@GL_KLUDGE@ GL: morph3d -root \n\ + mountain -root \n\ + munch -root \n\ + penrose -root \n\ +@GL_KLUDGE@ GL: pipes -root \n\ + rd-bomb -root \n\ +@GL_KLUDGE@ GL: rubik -root \n\ +- sierpinski -root \n\ + slip -root \n\ +@GL_KLUDGE@ GL: sproingies -root \n\ + starfish -root \n\ + strange -root \n\ + swirl -root \n\ + triangle -root \n\ + xjack -root \n\ + xlyap -root \n\ +@GL_KLUDGE@ GL: atlantis -root \n\ + bsod -root \n\ +@GL_KLUDGE@ GL: bubble3d -root \n\ +@GL_KLUDGE@ GL: cage -root \n\ +- crystal -root \n\ + cynosure -root \n\ + discrete -root \n\ + distort -root \n\ + epicycle -root \n\ + flow -root \n\ +- GL: glplanet -root \n\ + interference -root \n\ + kumppa -root \n\ +@GL_KLUDGE@ GL: lament -root \n\ + moire2 -root \n\ +@GL_KLUDGE@ GL: sonar -root \n\ +@GL_KLUDGE@ GL: stairs -root \n\ + truchet -root \n\ +- vidwhacker -root \n\ + blaster -root \n\ + bumps -root \n\ + ccurve -root \n\ + compass -root \n\ + deluxe -root \n\ +- demon -root \n\ +@GLE_KLUDGE@ GL: extrusion -root \n\ +- loop -root \n\ + penetrate -root \n\ + petri -root \n\ + phosphor -root \n\ +@GL_KLUDGE@ GL: pulsar -root \n\ + ripples -root \n\ + shadebobs -root \n\ +@GL_KLUDGE@ GL: sierpinski3d -root \n\ + spotlight -root \n\ + squiral -root \n\ + wander -root \n\ +- webcollage -root \n\ + xflame -root \n\ + xmatrix -root \n\ +@GL_KLUDGE@ GL: gflux -root \n\ +- nerverot -root \n\ + xrayswarm -root \n\ + xspirograph -root \n\ +@GL_KLUDGE@ GL: circuit -root \n\ +@GL_KLUDGE@ GL: dangerball -root \n\ +- GL: dnalogo -root \n\ +@GL_KLUDGE@ GL: engine -root \n\ +@GL_KLUDGE@ GL: flipscreen3d -root \n\ +@GL_KLUDGE@ GL: gltext -root \n\ +@GL_KLUDGE@ GL: menger -root \n\ +@GL_KLUDGE@ GL: molecule -root \n\ + rotzoomer -root \n\ + speedmine -root \n\ +@GL_KLUDGE@ GL: starwars -root \n\ +@GL_KLUDGE@ GL: stonerview -root \n\ + vermiculate -root \n\ + whirlwindwarp -root \n\ + zoom -root \n\ + anemone -root \n\ + apollonian -root \n\ +@GL_KLUDGE@ GL: boxed -root \n\ +@GL_KLUDGE@ GL: cubenetic -root \n\ +@GL_KLUDGE@ GL: endgame -root \n\ + euler2d -root \n\ + fluidballs -root \n\ +@GL_KLUDGE@ GL: flurry -root \n\ +- GL: glblur -root \n\ +@GL_KLUDGE@ GL: glsnake -root \n\ + halftone -root \n\ +@GL_KLUDGE@ GL: juggler3d -root \n\ +@GL_KLUDGE@ GL: lavalite -root \n\ +- polyominoes -root \n\ +@GL_KLUDGE@ GL: queens -root \n\ +- GL: sballs -root \n\ +@GL_KLUDGE@ GL: spheremonics -root \n\ +- thornbird -root \n\ + twang -root \n\ +- GL: antspotlight -root \n\ + apple2 -root \n\ +@GL_KLUDGE@ GL: atunnel -root \n\ + barcode -root \n\ +@GL_KLUDGE@ GL: blinkbox -root \n\ +@GL_KLUDGE@ GL: blocktube -root \n\ +@GL_KLUDGE@ GL: bouncingcow -root \n\ + cloudlife -root \n\ +@GL_KLUDGE@ GL: cubestorm -root \n\ + eruption -root \n\ +@GL_KLUDGE@ GL: flipflop -root \n\ +@GL_KLUDGE@ GL: flyingtoasters -root \n\ + fontglide -root \n\ +@GL_KLUDGE@ GL: gleidescope -root \n\ +@GL_KLUDGE@ GL: glknots -root \n\ +@GL_KLUDGE@ GL: glmatrix -root \n\ +- GL: glslideshow -root \n\ +@GL_KLUDGE@ GL: hypertorus -root \n\ +- GL: jigglypuff -root \n\ + metaballs -root \n\ +@GL_KLUDGE@ GL: mirrorblob -root \n\ + piecewise -root \n\ +@GL_KLUDGE@ GL: polytopes -root \n\ + pong -root \n\ + popsquares -root \n\ +@GL_KLUDGE@ GL: surfaces -root \n\ + xanalogtv -root \n\ +- abstractile -root \n\ + anemotaxis -root \n\ +- GL: antinspect -root \n\ + fireworkx -root \n\ + fuzzyflakes -root \n\ + interaggregate -root \n\ + intermomentary -root \n\ + memscroller -root \n\ +@GL_KLUDGE@ GL: noof -root \n\ + pacman -root \n\ +@GL_KLUDGE@ GL: pinion -root \n\ +@GL_KLUDGE@ GL: polyhedra -root \n\ +- GL: providence -root \n\ + substrate -root \n\ + wormhole -root \n\ +- GL: antmaze -root \n\ +@GL_KLUDGE@ GL: boing -root \n\ + boxfit -root \n\ +@GL_KLUDGE@ GL: carousel -root \n\ + celtic -root \n\ +@GL_KLUDGE@ GL: crackberg -root \n\ +@GL_KLUDGE@ GL: cube21 -root \n\ + fiberlamp -root \n\ +@GL_KLUDGE@ GL: fliptext -root \n\ +@GL_KLUDGE@ GL: glhanoi -root \n\ +@GL_KLUDGE@ GL: tangram -root \n\ +@GL_KLUDGE@ GL: timetunnel -root \n\ +@GL_KLUDGE@ GL: glschool -root \n\ +@GL_KLUDGE@ GL: topblock -root \n\ +@GL_KLUDGE@ GL: cubicgrid -root \n\ + cwaves -root \n\ +@GL_KLUDGE@ GL: gears -root \n\ +@GL_KLUDGE@ GL: glcells -root \n\ +@GL_KLUDGE@ GL: lockward -root \n\ + m6502 -root \n\ +@GL_KLUDGE@ GL: moebiusgears -root \n\ +@GL_KLUDGE@ GL: voronoi -root \n\ +@GL_KLUDGE@ GL: hypnowheel -root \n\ +@GL_KLUDGE@ GL: klein -root \n\ +- lcdscrub -root \n\ +@GL_KLUDGE@ GL: photopile -root \n\ +@GL_KLUDGE@ GL: skytentacles -root \n\ +@GL_KLUDGE@ GL: rubikblocks -root \n\ +@GL_KLUDGE@ GL: companioncube -root \n\ +@GL_KLUDGE@ GL: hilbert -root \n\ +@GL_KLUDGE@ GL: tronbit -root \n + + + +!============================================================================= +! +! You probably don't want to change anything after this point. +! +!============================================================================= + + +XScreenSaver.pointerPollTime: 0:00:05 +XScreenSaver.pointerHysteresis: 10 +XScreenSaver.initialDelay: 0:00:00 +XScreenSaver.windowCreationTimeout: 0:00:30 +XScreenSaver.bourneShell: /bin/sh + + +! Resources for the password and splash-screen dialog boxes of +! the "xscreensaver" daemon. +! +*Dialog.headingFont: *-helvetica-bold-r-*-*-*-180-*-*-*-iso8859-1 +*Dialog.bodyFont: *-helvetica-bold-r-*-*-*-140-*-*-*-iso8859-1 +*Dialog.labelFont: *-helvetica-bold-r-*-*-*-140-*-*-*-iso8859-1 +*Dialog.unameFont: *-helvetica-bold-r-*-*-*-120-*-*-*-iso8859-1 +*Dialog.buttonFont: *-helvetica-bold-r-*-*-*-140-*-*-*-iso8859-1 +*Dialog.dateFont: *-helvetica-medium-r-*-*-*-80-*-*-*-iso8859-1 +! Helvetica asterisks look terrible. +!*passwd.passwdFont: *-helvetica-medium-r-*-*-*-140-*-*-*-iso8859-1 +*passwd.passwdFont: *-courier-medium-r-*-*-*-140-*-*-*-iso8859-1 + +*Dialog.foreground: #000000 +*Dialog.background: #E6E6E6 +*Dialog.Button.foreground: #000000 +*Dialog.Button.background: #F5F5F5 +!*Dialog.Button.pointBackground: #EAEAEA +!*Dialog.Button.clickBackground: #C3C3C3 +*Dialog.text.foreground: #000000 +*Dialog.text.background: #FFFFFF +*passwd.thermometer.foreground: #4464AC +*passwd.thermometer.background: #FFFFFF +*Dialog.topShadowColor: #FFFFFF +*Dialog.bottomShadowColor: #CECECE +*Dialog.logo.width: 210 +*Dialog.logo.height: 210 +*Dialog.internalBorderWidth: 24 +*Dialog.borderWidth: 1 +*Dialog.shadowThickness: 2 + +*passwd.heading.label: XScreenSaver %s +*passwd.body.label: This screen is locked. +*passwd.unlock.label: OK +*passwd.login.label: New Login +*passwd.user.label: Username: +*passwd.thermometer.width: 8 +*passwd.asterisks: True +*passwd.uname: True + +*splash.heading.label: XScreenSaver %s +*splash.body.label: Copyright © 1991-2012 by +*splash.body2.label: Jamie Zawinski +*splash.demo.label: Settings +*splash.help.label: Help + + +!============================================================================= +! +! Pretty names for the hacks that have unusual capitalization. +! +!============================================================================= + +*hacks.antinspect.name: AntInspect +*hacks.antmaze.name: AntMaze +*hacks.antspotlight.name: AntSpotlight +*hacks.blinkbox.name: BlinkBox +*hacks.blitspin.name: BlitSpin +*hacks.blocktube.name: BlockTube +*hacks.bouncingcow.name: BouncingCow +*hacks.boxfit.name: BoxFit +*hacks.bsod.name: BSOD +*hacks.bubble3d.name: Bubble3D +*hacks.ccurve.name: CCurve +*hacks.cloudlife.name: CloudLife +*hacks.companioncube.name: CompanionCube +*hacks.cubestorm.name: CubeStorm +*hacks.cubicgrid.name: CubicGrid +*hacks.cwaves.name: CWaves +*hacks.dangerball.name: DangerBall +*hacks.decayscreen.name: DecayScreen +*hacks.dnalogo.name: DNA Logo +*hacks.euler2d.name: Euler2D +*hacks.fadeplot.name: FadePlot +*hacks.flipflop.name: FlipFlop +*hacks.flipscreen3d.name: FlipScreen3D +*hacks.fliptext.name: FlipText +*hacks.fluidballs.name: FluidBalls +*hacks.flyingtoasters.name: FlyingToasters +*hacks.fontglide.name: FontGlide +*hacks.fuzzyflakes.name: FuzzyFlakes +*hacks.gflux.name: GFlux +*hacks.gleidescope.name: Gleidescope +*hacks.glforestfire.name: GLForestFire +*hacks.hyperball.name: HyperBall +*hacks.hypercube.name: HyperCube +*hacks.ifs.name: IFS +*hacks.imsmap.name: IMSMap +*hacks.jigglypuff.name: JigglyPuff +*hacks.juggler3d.name: Juggler3D +*hacks.lcdscrub.name: LCDscrub +*hacks.lmorph.name: LMorph +*hacks.m6502.name: m6502 +*hacks.memscroller.name: MemScroller +*hacks.metaballs.name: MetaBalls +*hacks.mirrorblob.name: MirrorBlob +*hacks.moebiusgears.name: MoebiusGears +*hacks.morph3d.name: Morph3D +*hacks.nerverot.name: NerveRot +*hacks.noseguy.name: NoseGuy +*hacks.popsquares.name: PopSquares +*hacks.rd-bomb.name: RDbomb +*hacks.rdbomb.name: RDbomb +*hacks.rotzoomer.name: RotZoomer +*hacks.rubikblocks.name: RubikBlocks +*hacks.sballs.name: SBalls +*hacks.shadebobs.name: ShadeBobs +*hacks.sierpinski3d.name: Sierpinski3D +*hacks.skytentacles.name: SkyTentacles +*hacks.slidescreen.name: SlideScreen +*hacks.speedmine.name: SpeedMine +*hacks.starwars.name: StarWars +*hacks.stonerview.name: StonerView +*hacks.t3d.name: T3D +*hacks.timetunnel.name: TimeTunnel +*hacks.topblock.name: TopBlock +*hacks.tronbit.name: TronBit +*hacks.vidwhacker.name: VidWhacker +*hacks.webcollage.name: WebCollage +*hacks.whirlwindwarp.name: WhirlWindWarp +*hacks.xanalogtv.name: XAnalogTV +*hacks.xrayswarm.name: XRaySwarm + +! obsolete, but still used by xscreensaver-demo-Xm. +*hacks.documentation.isInstalled: True + +! (xrdb prevention kludge: whole file) */ diff --git a/driver/XScreenSaver_Xm_ad.h b/driver/XScreenSaver_Xm_ad.h new file mode 100644 index 00000000..371e0a29 --- /dev/null +++ b/driver/XScreenSaver_Xm_ad.h @@ -0,0 +1,108 @@ +"*fontList: *-helvetica-medium-r-*-*-*-120-*-*-*-iso8859-1", +"*demoDialog*label1.fontList: *-helvetica-medium-r-*-*-*-140-*-*-*-iso8859-1", +"*cmdText.fontList: *-courier-medium-r-*-*-*-120-*-*-*-iso8859-1", +"*label0.fontList: *-helvetica-bold-r-*-*-*-140-*-*-*-iso8859-1", +"XScreenSaver*doc.fontList: *-helvetica-medium-r-*-*-*-100-*-*-*-iso8859-1", +"*foreground: #000000", +"*background: #C0C0C0", +"*XmTextField.foreground: #000000", +"*XmTextField.background: #FFFFFF", +"*list.foreground: #000000", +"*list.background: #FFFFFF", +"*ApplicationShell.title: XScreenSaver", +"*warning.title: XScreenSaver", +"*warning_popup.title: XScreenSaver", +"*allowShellResize: True", +"*autoUnmanage: False", +"*menubar*file.labelString: File", +"*menubar*file.mnemonic: F", +"*file.blank.labelString: Blank Screen Now", +"*file.blank.mnemonic: B", +"*file.lock.labelString: Lock Screen Now", +"*file.lock.mnemonic: L", +"*file.kill.labelString: Kill Daemon", +"*file.kill.mnemonic: K", +"*file.restart.labelString: Restart Daemon", +"*file.restart.mnemonic: R", +"*file.exit.labelString: Exit", +"*file.exit.mnemonic: E", +"*menubar*edit.labelString: Edit", +"*menubar*edit.mnemonic: E", +"*edit.cut.labelString: Cut", +"*edit.cut.mnemonic: u", +"*edit.copy.labelString: Copy", +"*edit.copy.mnemonic: C", +"*edit.paste.labelString: Paste", +"*edit.paste.mnemonic: P", +"*menubar*help.labelString: Help", +"*menubar*help.mnemonic: H", +"*help.about.labelString: About...", +"*help.about.mnemonic: A", +"*help.docMenu.labelString: Documentation...", +"*help.docMenu.mnemonic: D", +"*demoTab.marginWidth: 10", +"*optionsTab.marginWidth: 10", +"*XmScrolledWindow.topOffset: 10", +"*XmScrolledWindow.leftOffset: 10", +"*demoTab.topOffset: 4", +"*form1.bottomOffset: 10", +"*form3.leftOffset: 10", +"*form3.rightOffset: 10", +"*frame.topOffset: 10", +"*frame.bottomOffset: 10", +"*enabled.topOffset: 10", +"*visLabel.topOffset: 10", +"*combo.topOffset: 10", +"*form4.bottomOffset: 4", +"*hr.bottomOffset: 4", +"*XmComboBox.marginWidth: 0", +"*XmComboBox.marginHeight: 0", +"*demo.marginWidth: 30", +"*demo.marginHeight: 4", +"*man.marginWidth: 10", +"*man.marginHeight: 4", +"*down.leftOffset: 40", +"*down.marginWidth: 4", +"*down.marginHeight: 4", +"*up.marginWidth: 4", +"*up.marginHeight: 4", +"*frame.traversalOn: False", +"*list.automaticSelection: True", +"*list.visibleItemCount: 20", +"*doc.columns: 60", +"*combo.columns: 11", +"*demoTab.labelString: Graphics Demos", +"*optionsTab.labelString: Screensaver Options", +"*down.labelString: \\\\/ ", +"*up.labelString: /\\\\ ", +"*frameLabel.labelString: ", +"*cmdLabel.labelString: Command Line:", +"*cmdLabel.alignment: ALIGNMENT_BEGINNING", +"*enabled.labelString: Enabled", +"*visLabel.labelString: Visual:", +"*visLabel.alignment: ALIGNMENT_END", +"*visLabel.leftOffset: 20", +"*demo.labelString: Demo", +"*man.labelString: Documentation...", +"*done.labelString: Quit", +"*preferencesLabel.labelString: XScreenSaver Parameters", +"*timeoutLabel.labelString: Saver Timeout", +"*cycleLabel.labelString: Cycle Timeout", +"*fadeSecondsLabel.labelString: Fade Duration", +"*fadeTicksLabel.labelString: Fade Ticks", +"*lockLabel.labelString: Lock Timeout", +"*passwdLabel.labelString: Password Timeout", +"*preferencesForm*XmTextField.columns: 8", +"*verboseToggle.labelString: Verbose", +"*cmapToggle.labelString: Install Colormap", +"*fadeToggle.labelString: Fade Colormap", +"*unfadeToggle.labelString: Unfade Colormap", +"*lockToggle.labelString: Require Password", +"*OK.marginWidth: 30", +"*OK.marginHeight: 4", +"*OK.leftOffset: 10", +"*OK.bottomOffset: 10", +"*Cancel.marginWidth: 30", +"*Cancel.marginHeight: 4", +"*Cancel.rightOffset: 10", +"*Cancel.bottomOffset: 10", diff --git a/driver/XScreenSaver_ad.h b/driver/XScreenSaver_ad.h new file mode 100644 index 00000000..88edae9d --- /dev/null +++ b/driver/XScreenSaver_ad.h @@ -0,0 +1,364 @@ +"#error Do not run app-defaults files through xrdb!", +"#error That does not do what you might expect.", +"#error Put this file in /usr/lib/X11/app-defaults/XScreenSaver instead.", +"*mode: random", +"*timeout: 0:10:00", +"*cycle: 0:10:00", +"*lockTimeout: 0:00:00", +"*passwdTimeout: 0:00:30", +"*dpmsEnabled: False", +"*dpmsQuickoffEnabled: False", +"*dpmsStandby: 2:00:00", +"*dpmsSuspend: 2:00:00", +"*dpmsOff: 4:00:00", +"*grabDesktopImages: True", +"*grabVideoFrames: False", +"*chooseRandomImages: True", +"*imageDirectory: /Library/Desktop Pictures/", +"*nice: 10", +"*memoryLimit: 0", +"*lock: False", +"*verbose: False", +"*timestamp: True", +"*fade: True", +"*unfade: False", +"*fadeSeconds: 0:00:03", +"*fadeTicks: 20", +"*splash: True", +"*splashDuration: 0:00:05", +"*visualID: default", +"*captureStderr: True", +"*ignoreUninstalledPrograms: False", +"*textMode: file", +"*textLiteral: XScreenSaver", +"*textFile: ", +"*textProgram: fortune", +"*textURL: http://twitter.com/statuses/public_timeline.atom", +"*overlayTextForeground: #FFFF00", +"*overlayTextBackground: #000000", +"*overlayStderr: True", +"*font: *-medium-r-*-140-*-m-*", +"*sgiSaverExtension: True", +"*xidleExtension: True", +"*procInterrupts: True", +"*xinputExtensionDev: False", +"GetViewPortIsFullOfLies: False", +"*demoCommand: xscreensaver-demo", +"*prefsCommand: xscreensaver-demo -prefs", +"*helpURL: http://www.jwz.org/xscreensaver/man.html", +"*loadURL: firefox '%s' || mozilla '%s' || netscape '%s'", +"*manualCommand: xterm -sb -fg black -bg gray75 -T '%s manual' \ + -e /bin/sh -c 'man \"%s\" ; read foo'", +"*dateFormat: %d-%b-%y (%a); %I:%M %p", +"*installColormap: True", +"*programs: \ + maze -root \\n\ + GL: superquadrics -root \\n\ + attraction -root \\n\ + blitspin -root \\n\ + greynetic -root \\n\ + helix -root \\n\ + hopalong -root \\n\ + imsmap -root \\n\ +- noseguy -root \\n\ +- pyro -root \\n\ + qix -root \\n\ +- rocks -root \\n\ + rorschach -root \\n\ + decayscreen -root \\n\ + flame -root \\n\ + halo -root \\n\ + slidescreen -root \\n\ + pedal -root \\n\ + bouboule -root \\n\ +- braid -root \\n\ + coral -root \\n\ + deco -root \\n\ + drift -root \\n\ +- fadeplot -root \\n\ + galaxy -root \\n\ + goop -root \\n\ + grav -root \\n\ + ifs -root \\n\ + GL: jigsaw -root \\n\ + julia -root \\n\ +- kaleidescope -root \\n\ + GL: moebius -root \\n\ + moire -root \\n\ + GL: morph3d -root \\n\ + mountain -root \\n\ + munch -root \\n\ + penrose -root \\n\ + GL: pipes -root \\n\ + rd-bomb -root \\n\ + GL: rubik -root \\n\ +- sierpinski -root \\n\ + slip -root \\n\ + GL: sproingies -root \\n\ + starfish -root \\n\ + strange -root \\n\ + swirl -root \\n\ + triangle -root \\n\ + xjack -root \\n\ + xlyap -root \\n\ + GL: atlantis -root \\n\ + bsod -root \\n\ + GL: bubble3d -root \\n\ + GL: cage -root \\n\ +- crystal -root \\n\ + cynosure -root \\n\ + discrete -root \\n\ + distort -root \\n\ + epicycle -root \\n\ + flow -root \\n\ +- GL: glplanet -root \\n\ + interference -root \\n\ + kumppa -root \\n\ + GL: lament -root \\n\ + moire2 -root \\n\ + GL: sonar -root \\n\ + GL: stairs -root \\n\ + truchet -root \\n\ +- vidwhacker -root \\n\ + blaster -root \\n\ + bumps -root \\n\ + ccurve -root \\n\ + compass -root \\n\ + deluxe -root \\n\ +- demon -root \\n\ +- GL: extrusion -root \\n\ +- loop -root \\n\ + penetrate -root \\n\ + petri -root \\n\ + phosphor -root \\n\ + GL: pulsar -root \\n\ + ripples -root \\n\ + shadebobs -root \\n\ + GL: sierpinski3d -root \\n\ + spotlight -root \\n\ + squiral -root \\n\ + wander -root \\n\ +- webcollage -root \\n\ + xflame -root \\n\ + xmatrix -root \\n\ + GL: gflux -root \\n\ +- nerverot -root \\n\ + xrayswarm -root \\n\ + xspirograph -root \\n\ + GL: circuit -root \\n\ + GL: dangerball -root \\n\ +- GL: dnalogo -root \\n\ + GL: engine -root \\n\ + GL: flipscreen3d -root \\n\ + GL: gltext -root \\n\ + GL: menger -root \\n\ + GL: molecule -root \\n\ + rotzoomer -root \\n\ + speedmine -root \\n\ + GL: starwars -root \\n\ + GL: stonerview -root \\n\ + vermiculate -root \\n\ + whirlwindwarp -root \\n\ + zoom -root \\n\ + anemone -root \\n\ + apollonian -root \\n\ + GL: boxed -root \\n\ + GL: cubenetic -root \\n\ + GL: endgame -root \\n\ + euler2d -root \\n\ + fluidballs -root \\n\ + GL: flurry -root \\n\ +- GL: glblur -root \\n\ + GL: glsnake -root \\n\ + halftone -root \\n\ + GL: juggler3d -root \\n\ + GL: lavalite -root \\n\ +- polyominoes -root \\n\ + GL: queens -root \\n\ +- GL: sballs -root \\n\ + GL: spheremonics -root \\n\ +- thornbird -root \\n\ + twang -root \\n\ +- GL: antspotlight -root \\n\ + apple2 -root \\n\ + GL: atunnel -root \\n\ + barcode -root \\n\ + GL: blinkbox -root \\n\ + GL: blocktube -root \\n\ + GL: bouncingcow -root \\n\ + cloudlife -root \\n\ + GL: cubestorm -root \\n\ + eruption -root \\n\ + GL: flipflop -root \\n\ + GL: flyingtoasters -root \\n\ + fontglide -root \\n\ + GL: gleidescope -root \\n\ + GL: glknots -root \\n\ + GL: glmatrix -root \\n\ +- GL: glslideshow -root \\n\ + GL: hypertorus -root \\n\ +- GL: jigglypuff -root \\n\ + metaballs -root \\n\ + GL: mirrorblob -root \\n\ + piecewise -root \\n\ + GL: polytopes -root \\n\ + pong -root \\n\ + popsquares -root \\n\ + GL: surfaces -root \\n\ + xanalogtv -root \\n\ +- abstractile -root \\n\ + anemotaxis -root \\n\ +- GL: antinspect -root \\n\ + fireworkx -root \\n\ + fuzzyflakes -root \\n\ + interaggregate -root \\n\ + intermomentary -root \\n\ + memscroller -root \\n\ + GL: noof -root \\n\ + pacman -root \\n\ + GL: pinion -root \\n\ + GL: polyhedra -root \\n\ +- GL: providence -root \\n\ + substrate -root \\n\ + wormhole -root \\n\ +- GL: antmaze -root \\n\ + GL: boing -root \\n\ + boxfit -root \\n\ + GL: carousel -root \\n\ + celtic -root \\n\ + GL: crackberg -root \\n\ + GL: cube21 -root \\n\ + fiberlamp -root \\n\ + GL: fliptext -root \\n\ + GL: glhanoi -root \\n\ + GL: tangram -root \\n\ + GL: timetunnel -root \\n\ + GL: glschool -root \\n\ + GL: topblock -root \\n\ + GL: cubicgrid -root \\n\ + cwaves -root \\n\ + GL: gears -root \\n\ + GL: glcells -root \\n\ + GL: lockward -root \\n\ + m6502 -root \\n\ + GL: moebiusgears -root \\n\ + GL: voronoi -root \\n\ + GL: hypnowheel -root \\n\ + GL: klein -root \\n\ +- lcdscrub -root \\n\ + GL: photopile -root \\n\ + GL: skytentacles -root \\n\ + GL: rubikblocks -root \\n\ + GL: companioncube -root \\n\ + GL: hilbert -root \\n\ + GL: tronbit -root \\n", +"XScreenSaver.pointerPollTime: 0:00:05", +"XScreenSaver.pointerHysteresis: 10", +"XScreenSaver.initialDelay: 0:00:00", +"XScreenSaver.windowCreationTimeout: 0:00:30", +"XScreenSaver.bourneShell: /bin/sh", +"*Dialog.headingFont: *-helvetica-bold-r-*-*-*-180-*-*-*-iso8859-1", +"*Dialog.bodyFont: *-helvetica-bold-r-*-*-*-140-*-*-*-iso8859-1", +"*Dialog.labelFont: *-helvetica-bold-r-*-*-*-140-*-*-*-iso8859-1", +"*Dialog.unameFont: *-helvetica-bold-r-*-*-*-120-*-*-*-iso8859-1", +"*Dialog.buttonFont: *-helvetica-bold-r-*-*-*-140-*-*-*-iso8859-1", +"*Dialog.dateFont: *-helvetica-medium-r-*-*-*-80-*-*-*-iso8859-1", +"*passwd.passwdFont: *-courier-medium-r-*-*-*-140-*-*-*-iso8859-1", +"*Dialog.foreground: #000000", +"*Dialog.background: #E6E6E6", +"*Dialog.Button.foreground: #000000", +"*Dialog.Button.background: #F5F5F5", +"*Dialog.text.foreground: #000000", +"*Dialog.text.background: #FFFFFF", +"*passwd.thermometer.foreground: #4464AC", +"*passwd.thermometer.background: #FFFFFF", +"*Dialog.topShadowColor: #FFFFFF", +"*Dialog.bottomShadowColor: #CECECE", +"*Dialog.logo.width: 210", +"*Dialog.logo.height: 210", +"*Dialog.internalBorderWidth: 24", +"*Dialog.borderWidth: 1", +"*Dialog.shadowThickness: 2", +"*passwd.heading.label: XScreenSaver %s", +"*passwd.body.label: This screen is locked.", +"*passwd.unlock.label: OK", +"*passwd.login.label: New Login", +"*passwd.user.label: Username:", +"*passwd.thermometer.width: 8", +"*passwd.asterisks: True", +"*passwd.uname: True", +"*splash.heading.label: XScreenSaver %s", +"*splash.body.label: Copyright © 1991-2012 by", +"*splash.body2.label: Jamie Zawinski ", +"*splash.demo.label: Settings", +"*splash.help.label: Help", +"*hacks.antinspect.name: AntInspect", +"*hacks.antmaze.name: AntMaze", +"*hacks.antspotlight.name: AntSpotlight", +"*hacks.blinkbox.name: BlinkBox", +"*hacks.blitspin.name: BlitSpin", +"*hacks.blocktube.name: BlockTube", +"*hacks.bouncingcow.name: BouncingCow", +"*hacks.boxfit.name: BoxFit", +"*hacks.bsod.name: BSOD", +"*hacks.bubble3d.name: Bubble3D", +"*hacks.ccurve.name: CCurve", +"*hacks.cloudlife.name: CloudLife", +"*hacks.companioncube.name: CompanionCube", +"*hacks.cubestorm.name: CubeStorm", +"*hacks.cubicgrid.name: CubicGrid", +"*hacks.cwaves.name: CWaves", +"*hacks.dangerball.name: DangerBall", +"*hacks.decayscreen.name: DecayScreen", +"*hacks.dnalogo.name: DNA Logo", +"*hacks.euler2d.name: Euler2D", +"*hacks.fadeplot.name: FadePlot", +"*hacks.flipflop.name: FlipFlop", +"*hacks.flipscreen3d.name: FlipScreen3D", +"*hacks.fliptext.name: FlipText", +"*hacks.fluidballs.name: FluidBalls", +"*hacks.flyingtoasters.name: FlyingToasters", +"*hacks.fontglide.name: FontGlide", +"*hacks.fuzzyflakes.name: FuzzyFlakes", +"*hacks.gflux.name: GFlux", +"*hacks.gleidescope.name: Gleidescope", +"*hacks.glforestfire.name: GLForestFire", +"*hacks.hyperball.name: HyperBall", +"*hacks.hypercube.name: HyperCube", +"*hacks.ifs.name: IFS", +"*hacks.imsmap.name: IMSMap", +"*hacks.jigglypuff.name: JigglyPuff", +"*hacks.juggler3d.name: Juggler3D", +"*hacks.lcdscrub.name: LCDscrub", +"*hacks.lmorph.name: LMorph", +"*hacks.m6502.name: m6502", +"*hacks.memscroller.name: MemScroller", +"*hacks.metaballs.name: MetaBalls", +"*hacks.mirrorblob.name: MirrorBlob", +"*hacks.moebiusgears.name: MoebiusGears", +"*hacks.morph3d.name: Morph3D", +"*hacks.nerverot.name: NerveRot", +"*hacks.noseguy.name: NoseGuy", +"*hacks.popsquares.name: PopSquares", +"*hacks.rd-bomb.name: RDbomb", +"*hacks.rdbomb.name: RDbomb", +"*hacks.rotzoomer.name: RotZoomer", +"*hacks.rubikblocks.name: RubikBlocks", +"*hacks.sballs.name: SBalls", +"*hacks.shadebobs.name: ShadeBobs", +"*hacks.sierpinski3d.name: Sierpinski3D", +"*hacks.skytentacles.name: SkyTentacles", +"*hacks.slidescreen.name: SlideScreen", +"*hacks.speedmine.name: SpeedMine", +"*hacks.starwars.name: StarWars", +"*hacks.stonerview.name: StonerView", +"*hacks.t3d.name: T3D", +"*hacks.timetunnel.name: TimeTunnel", +"*hacks.topblock.name: TopBlock", +"*hacks.tronbit.name: TronBit", +"*hacks.vidwhacker.name: VidWhacker", +"*hacks.webcollage.name: WebCollage", +"*hacks.whirlwindwarp.name: WhirlWindWarp", +"*hacks.xanalogtv.name: XAnalogTV", +"*hacks.xrayswarm.name: XRaySwarm", +"*hacks.documentation.isInstalled: True", diff --git a/driver/auth.h b/driver/auth.h new file mode 100644 index 00000000..65e00f33 --- /dev/null +++ b/driver/auth.h @@ -0,0 +1,54 @@ +/* auth.h --- Providing authentication mechanisms. + * + * (c) 2007, Quest Software, Inc. All rights reserved. + * + * This file is part of XScreenSaver, + * Copyright (c) 1993-2004 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. + */ +#ifndef XSS_AUTH_H +#define XSS_AUTH_H + +#include "types.h" + +#undef Bool +#undef True +#undef False +#define Bool int +#define True 1 +#define False 0 + +struct auth_message { + enum { + AUTH_MSGTYPE_INFO, + AUTH_MSGTYPE_ERROR, + AUTH_MSGTYPE_PROMPT_NOECHO, + AUTH_MSGTYPE_PROMPT_ECHO + } type; + const char *msg; +}; + +struct auth_response { + char *response; +}; + +int +gui_auth_conv(int num_msg, + const struct auth_message auth_msgs[], + struct auth_response **resp, + saver_info *si); + +void +xss_authenticate(saver_info *si, Bool verbose_p); + +void +auth_finished_cb (saver_info *si); + +#endif diff --git a/driver/compile_axp.com b/driver/compile_axp.com new file mode 100644 index 00000000..d6ed0e8a --- /dev/null +++ b/driver/compile_axp.com @@ -0,0 +1,15 @@ +$ CC/DECC/PREFIX=ALL/DEFINE=(VMS,HAVE_CONFIG_H)/INCL=([],[-],[-.UTILS]) DEMO.C +$ CC/DECC/PREFIX=ALL/DEFINE=(VMS,HAVE_CONFIG_H)/INCL=([],[-],[-.UTILS]) DIALOGS-XM.C +$ CC/DECC/PREFIX=ALL/DEFINE=(VMS,HAVE_CONFIG_H)/INCL=([],[-],[-.UTILS]) LOCK.C +$ CC/DECC/PREFIX=ALL/DEFINE=(VMS,HAVE_CONFIG_H)/INCL=([],[-],[-.UTILS]) PASSWD.C +$ CC/DECC/PREFIX=ALL/DEFINE=(VMS,HAVE_CONFIG_H)/INCL=([],[-],[-.UTILS]) STDERR.C +$ CC/DECC/PREFIX=ALL/DEFINE=(VMS,HAVE_CONFIG_H,NO_SETUID)/INCL=([],[-],[-.UTILS]) SUBPROCS.C +$ CC/DECC/PREFIX=ALL/DEFINE=(VMS,HAVE_CONFIG_H)/INCL=([],[-],[-.UTILS]) TIMERS.C +$ CC/DECC/PREFIX=ALL/DEFINE=(VMS,HAVE_CONFIG_H)/INCL=([],[-],[-.UTILS]) WINDOWS.C +$ CC/DECC/PREFIX=ALL/DEFINE=(VMS,HAVE_CONFIG_H)/INCL=([],[-],[-.UTILS]) XSCREENSAVER-COMMAND.C +$ CC/DECC/PREFIX=ALL/DEFINE=(VMS,HAVE_CONFIG_H,NO_SETUID)/INCL=([],[-],[-.UTILS]) XSCREENSAVER.C +$ CC/DECC/PREFIX=ALL/DEFINE=(VMS,HAVE_CONFIG_H)/INCL=([],[-],[-.UTILS]) XSET.C +$ CC/DECC/PREFIX=ALL/DEFINE=(VMS,HAVE_CONFIG_H)/INCL=([],[-],[-.UTILS]) VMS-GETPWNAM.C +$!!! CC/DECC/PREFIX=ALL/DEFINE=(VMS,HAVE_CONFIG_H)/INCL=([],[-],[-.UTILS]) GETPWUID.C +$ CC/DECC/PREFIX=ALL/DEFINE=(VMS,HAVE_CONFIG_H)/INCL=([],[-],[-.UTILS]) VMS-HPWD.C +$ CC/DECC/PREFIX=ALL/DEFINE=(VMS,HAVE_CONFIG_H)/INCL=([],[-],[-.UTILS]) VMS-VALIDATE.C diff --git a/driver/compile_decc.com b/driver/compile_decc.com new file mode 100644 index 00000000..d6ed0e8a --- /dev/null +++ b/driver/compile_decc.com @@ -0,0 +1,15 @@ +$ CC/DECC/PREFIX=ALL/DEFINE=(VMS,HAVE_CONFIG_H)/INCL=([],[-],[-.UTILS]) DEMO.C +$ CC/DECC/PREFIX=ALL/DEFINE=(VMS,HAVE_CONFIG_H)/INCL=([],[-],[-.UTILS]) DIALOGS-XM.C +$ CC/DECC/PREFIX=ALL/DEFINE=(VMS,HAVE_CONFIG_H)/INCL=([],[-],[-.UTILS]) LOCK.C +$ CC/DECC/PREFIX=ALL/DEFINE=(VMS,HAVE_CONFIG_H)/INCL=([],[-],[-.UTILS]) PASSWD.C +$ CC/DECC/PREFIX=ALL/DEFINE=(VMS,HAVE_CONFIG_H)/INCL=([],[-],[-.UTILS]) STDERR.C +$ CC/DECC/PREFIX=ALL/DEFINE=(VMS,HAVE_CONFIG_H,NO_SETUID)/INCL=([],[-],[-.UTILS]) SUBPROCS.C +$ CC/DECC/PREFIX=ALL/DEFINE=(VMS,HAVE_CONFIG_H)/INCL=([],[-],[-.UTILS]) TIMERS.C +$ CC/DECC/PREFIX=ALL/DEFINE=(VMS,HAVE_CONFIG_H)/INCL=([],[-],[-.UTILS]) WINDOWS.C +$ CC/DECC/PREFIX=ALL/DEFINE=(VMS,HAVE_CONFIG_H)/INCL=([],[-],[-.UTILS]) XSCREENSAVER-COMMAND.C +$ CC/DECC/PREFIX=ALL/DEFINE=(VMS,HAVE_CONFIG_H,NO_SETUID)/INCL=([],[-],[-.UTILS]) XSCREENSAVER.C +$ CC/DECC/PREFIX=ALL/DEFINE=(VMS,HAVE_CONFIG_H)/INCL=([],[-],[-.UTILS]) XSET.C +$ CC/DECC/PREFIX=ALL/DEFINE=(VMS,HAVE_CONFIG_H)/INCL=([],[-],[-.UTILS]) VMS-GETPWNAM.C +$!!! CC/DECC/PREFIX=ALL/DEFINE=(VMS,HAVE_CONFIG_H)/INCL=([],[-],[-.UTILS]) GETPWUID.C +$ CC/DECC/PREFIX=ALL/DEFINE=(VMS,HAVE_CONFIG_H)/INCL=([],[-],[-.UTILS]) VMS-HPWD.C +$ CC/DECC/PREFIX=ALL/DEFINE=(VMS,HAVE_CONFIG_H)/INCL=([],[-],[-.UTILS]) VMS-VALIDATE.C diff --git a/driver/demo-Gtk-conf.c b/driver/demo-Gtk-conf.c new file mode 100644 index 00000000..b9c9479c --- /dev/null +++ b/driver/demo-Gtk-conf.c @@ -0,0 +1,1996 @@ +/* demo-Gtk-conf.c --- implements the dynamic configuration dialogs. + * xscreensaver, Copyright (c) 2001-2008 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. + */ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#if defined(HAVE_GTK) && defined(HAVE_XML) /* whole file */ + +#include + +#include + +#ifdef HAVE_UNISTD_H +# include +#endif + +#include +#include +#include + +/* + * Both of these workarounds can be removed when support for ancient + * libxml versions is dropped. versions 1.8.11 and 2.3.4 provide the + * correct fixes. + */ + +/* + * Older libxml polluted the global headerspace, while libxml2 fixed + * this. To support both old and recent libxmls, we have this + * workaround. + */ +#ifdef HAVE_OLD_XML_HEADERS +# include +#else /* ! HAVE_OLD_XML_HEADERS */ +# include +#endif /* HAVE_OLD_XML_HEADERS */ + +/* + * handle non-native spelling mistakes in earlier versions and provide + * the source-compat fix for this that may not be in older versions. + */ +#ifndef xmlChildrenNode +# if LIBXML_VERSION >= 20000 +# define xmlChildrenNode children +# define xmlRootNode children +# else +# define xmlChildrenNode childs +# define xmlRootNode root +# endif /* LIBXML_VERSION */ +#endif /* xmlChildrenNode */ + +#include + +#include "demo-Gtk-conf.h" + +/* Deal with deprecation of direct access to struct fields on the way to GTK3 + See http://live.gnome.org/GnomeGoals/UseGseal + */ +#if GTK_CHECK_VERSION(2,14,0) +# define GET_PARENT(w) gtk_widget_get_parent (w) +# define GET_ADJ_VALUE(a) gtk_adjustment_get_value (a) +# define GET_ADJ_UPPER(a) gtk_adjustment_get_upper (a) +# define GET_ADJ_LOWER(a) gtk_adjustment_get_lower (a) +#else +# define GET_PARENT(w) ((w)->parent) +# define GET_ADJ_VALUE(a) ((a)->value) +# define GET_ADJ_UPPER(a) ((a)->upper) +# define GET_ADJ_LOWER(a) ((a)->lower) +#endif + + +extern const char *blurb (void); + + +const char *hack_configuration_path = HACK_CONFIGURATION_PATH; + +static gboolean debug_p = FALSE; + + +#define MIN_SLIDER_WIDTH 150 +#define MIN_SPINBUTTON_WIDTH 48 +#define MIN_LABEL_WIDTH 70 + + +typedef enum { + COMMAND, + FAKE, + DESCRIPTION, + FAKEPREVIEW, + STRING, + FILENAME, + SLIDER, + SPINBUTTON, + BOOLEAN, + SELECT, + SELECT_OPTION +} parameter_type; + + +typedef struct { + + parameter_type type; + + xmlChar *id; /* widget name */ + xmlChar *label; /* heading label, or null */ + + /* command, fake, description, fakepreview, string, file + */ + xmlChar *string; /* file name, description, whatever. */ + + /* slider, spinbutton + */ + xmlChar *low_label; /* label for the left side */ + xmlChar *high_label; /* label for the right side */ + float low; /* minimum value */ + float high; /* maximum value */ + float value; /* default value */ + gboolean integer_p; /* whether the range is integral, or real */ + xmlChar *arg; /* command-line option to set (substitute "%") */ + gboolean invert_p; /* whether to flip the value and pretend the + range goes from hi-low instead of low-hi. */ + + /* boolean, select-option + */ + xmlChar *arg_set; /* command-line option to set for "yes", or null */ + xmlChar *arg_unset; /* command-line option to set for "no", or null */ + + /* select + */ + GList *options; + + /* select_option + */ + GtkWidget *widget; + +} parameter; + + +static parameter *make_select_option (const char *file, xmlNodePtr); +static void make_parameter_widget (const char *filename, + parameter *, GtkWidget *); +static void browse_button_cb (GtkButton *button, gpointer user_data); + + +/* Frees the parameter object and all strings and sub-parameters. + Does not destroy the widget, if any. + */ +static void +free_parameter (parameter *p) +{ + GList *rest; + if (p->id) free (p->id); + if (p->label) free (p->label); + if (p->string) free (p->string); + if (p->low_label) free (p->low_label); + if (p->high_label) free (p->high_label); + if (p->arg) free (p->arg); + if (p->arg_set) free (p->arg_set); + if (p->arg_unset) free (p->arg_unset); + + for (rest = p->options; rest; rest = rest->next) + if (rest->data) + free_parameter ((parameter *) rest->data); + + memset (p, ~0, sizeof(*p)); + free (p); +} + + +/* Debugging: dumps out a `parameter' structure. + */ +#if 0 +void +describe_parameter (FILE *out, parameter *p) +{ + fprintf (out, "<"); + switch (p->type) + { + case COMMAND: fprintf (out, "command"); break; + case FAKE: fprintf (out, "fake"); break; + case DESCRIPTION: fprintf (out, "_description"); break; + case FAKEPREVIEW: fprintf (out, "fakepreview"); break; + case STRING: fprintf (out, "string"); break; + case FILENAME: fprintf (out, "filename"); break; + case SLIDER: fprintf (out, "number type=\"slider\""); break; + case SPINBUTTON: fprintf (out, "number type=\"spinbutton\""); break; + case BOOLEAN: fprintf (out, "boolean"); break; + case SELECT: fprintf (out, "select"); break; + default: abort(); break; + } + if (p->id) fprintf (out, " id=\"%s\"", p->id); + if (p->label) fprintf (out, " _label=\"%s\"", p->label); + if (p->string && p->type != DESCRIPTION) + fprintf (out, " string=\"%s\"", p->string); + if (p->low_label) fprintf (out, " _low-label=\"%s\"", p->low_label); + if (p->high_label) fprintf (out, " _high-label=\"%s\"", p->high_label); + if (p->low) fprintf (out, " low=\"%.2f\"", p->low); + if (p->high) fprintf (out, " high=\"%.2f\"", p->high); + if (p->value) fprintf (out, " default=\"%.2f\"", p->value); + if (p->arg) fprintf (out, " arg=\"%s\"", p->arg); + if (p->invert_p) fprintf (out, " convert=\"invert\""); + if (p->arg_set) fprintf (out, " arg-set=\"%s\"", p->arg_set); + if (p->arg_unset) fprintf (out, " arg-unset=\"%s\"", p->arg_unset); + fprintf (out, ">\n"); + + if (p->type == SELECT) + { + GList *opt; + for (opt = p->options; opt; opt = opt->next) + { + parameter *o = (parameter *) opt->data; + if (o->type != SELECT_OPTION) abort(); + fprintf (out, " id) fprintf (out, " id=\"%s\"", o->id); + if (o->label) fprintf (out, " _label=\"%s\"", o->label); + if (o->arg_set) fprintf (out, " arg-set=\"%s\"", o->arg_set); + if (o->arg_unset) fprintf (out, " arg-unset=\"%s\"", o->arg_unset); + fprintf (out, ">\n"); + } + fprintf (out, "\n"); + } + else if (p->type == DESCRIPTION) + { + if (p->string) + fprintf (out, " %s\n", p->string); + fprintf (out, "\n"); + } +} +#endif /* 0 */ + + +/* Like xmlGetProp() but parses a float out of the string. + If the number was expressed as a float and not an integer + (that is, the string contained a decimal point) then + `floatp' is set to TRUE. Otherwise, it is unchanged. + */ +static float +xml_get_float (xmlNodePtr node, const xmlChar *name, gboolean *floatpP) +{ + const char *s = (char *) xmlGetProp (node, name); + float f; + char c; + if (!s || 1 != sscanf (s, "%f %c", &f, &c)) + return 0; + else + { + if (strchr (s, '.')) *floatpP = TRUE; + return f; + } +} + + +static void sanity_check_parameter (const char *filename, + const xmlChar *node_name, + parameter *p); +static void sanity_check_text_node (const char *filename, + const xmlNodePtr node); +static void sanity_check_menu_options (const char *filename, + const xmlChar *node_name, + parameter *p); + +/* Allocates and returns a new `parameter' object based on the + properties in the given XML node. Returns 0 if there's nothing + to create (comment, or unknown tag.) + */ +static parameter * +make_parameter (const char *filename, xmlNodePtr node) +{ + parameter *p; + const char *name = (char *) node->name; + const char *convert; + gboolean floatp = FALSE; + + if (node->type == XML_COMMENT_NODE) + return 0; + + p = calloc (1, sizeof(*p)); + + if (!name) abort(); + else if (!strcmp (name, "command")) p->type = COMMAND; + else if (!strcmp (name, "fullcommand")) p->type = COMMAND; + else if (!strcmp (name, "_description")) p->type = DESCRIPTION; + else if (!strcmp (name, "fakepreview")) p->type = FAKEPREVIEW; + else if (!strcmp (name, "fake")) p->type = FAKE; + else if (!strcmp (name, "boolean")) p->type = BOOLEAN; + else if (!strcmp (name, "string")) p->type = STRING; + else if (!strcmp (name, "file")) p->type = FILENAME; + else if (!strcmp (name, "number")) p->type = SPINBUTTON; + else if (!strcmp (name, "select")) p->type = SELECT; + + else if (!strcmp (name, "xscreensaver-text") || /* these are ignored in X11 */ + !strcmp (name, "xscreensaver-image")) /* (they are used in Cocoa) */ + { + free (p); + return 0; + } + else if (node->type == XML_TEXT_NODE) + { + sanity_check_text_node (filename, node); + free (p); + return 0; + } + else + { + if (debug_p) + fprintf (stderr, "%s: WARNING: %s: unknown tag: \"%s\"\n", + blurb(), filename, name); + free (p); + return 0; + } + + if (p->type == SPINBUTTON) + { + const char *type = (char *) xmlGetProp (node, (xmlChar *) "type"); + if (!type || !strcmp (type, "spinbutton")) p->type = SPINBUTTON; + else if (!strcmp (type, "slider")) p->type = SLIDER; + else + { + if (debug_p) + fprintf (stderr, "%s: WARNING: %s: unknown %s type: \"%s\"\n", + blurb(), filename, name, type); + free (p); + return 0; + } + } + else if (p->type == DESCRIPTION) + { + if (node->xmlChildrenNode && + node->xmlChildrenNode->type == XML_TEXT_NODE && + !node->xmlChildrenNode->next) + p->string = (xmlChar *) + strdup ((char *) node->xmlChildrenNode->content); + } + + p->id = xmlGetProp (node, (xmlChar *) "id"); + p->label = xmlGetProp (node, (xmlChar *) "_label"); + p->low_label = xmlGetProp (node, (xmlChar *) "_low-label"); + p->high_label = xmlGetProp (node, (xmlChar *) "_high-label"); + p->low = xml_get_float (node, (xmlChar *) "low", &floatp); + p->high = xml_get_float (node, (xmlChar *) "high", &floatp); + p->value = xml_get_float (node, (xmlChar *) "default", &floatp); + p->integer_p = !floatp; + convert = (char *) xmlGetProp (node, (xmlChar *) "convert"); + p->invert_p = (convert && !strcmp (convert, "invert")); + p->arg = xmlGetProp (node, (xmlChar *) "arg"); + p->arg_set = xmlGetProp (node, (xmlChar *) "arg-set"); + p->arg_unset = xmlGetProp (node, (xmlChar *) "arg-unset"); + + /* Check for missing decimal point */ + if (debug_p && + p->integer_p && + (p->high != p->low) && + (p->high - p->low) <= 1) + fprintf (stderr, + "%s: WARNING: %s: %s: range [%.1f, %.1f] shouldn't be integral!\n", + blurb(), filename, p->id, + p->low, p->high); + + if (p->type == SELECT) + { + xmlNodePtr kids; + for (kids = node->xmlChildrenNode; kids; kids = kids->next) + { + parameter *s = make_select_option (filename, kids); + if (s) + p->options = g_list_append (p->options, s); + } + } + + sanity_check_parameter (filename, (const xmlChar *) name, p); + + return p; +} + + +/* Allocates and returns a new SELECT_OPTION `parameter' object based + on the properties in the given XML node. Returns 0 if there's nothing + to create (comment, or unknown tag.) + */ +static parameter * +make_select_option (const char *filename, xmlNodePtr node) +{ + if (node->type == XML_COMMENT_NODE) + return 0; + else if (node->type == XML_TEXT_NODE) + { + sanity_check_text_node (filename, node); + return 0; + } + else if (node->type != XML_ELEMENT_NODE) + { + if (debug_p) + fprintf (stderr, + "%s: WARNING: %s: %s: unexpected child tag type %d\n", + blurb(), filename, node->name, (int)node->type); + return 0; + } + else if (strcmp ((char *) node->name, "option")) + { + if (debug_p) + fprintf (stderr, + "%s: WARNING: %s: %s: child not an option tag: \"%s\"\n", + blurb(), filename, node->name, node->name); + return 0; + } + else + { + parameter *s = calloc (1, sizeof(*s)); + + s->type = SELECT_OPTION; + s->id = xmlGetProp (node, (xmlChar *) "id"); + s->label = xmlGetProp (node, (xmlChar *) "_label"); + s->arg_set = xmlGetProp (node, (xmlChar *) "arg-set"); + s->arg_unset = xmlGetProp (node, (xmlChar *) "arg-unset"); + + sanity_check_parameter (filename, node->name, s); + return s; + } +} + + +/* Rudimentary check to make sure someone hasn't typed "arg-set=" + when they should have typed "arg=", etc. + */ +static void +sanity_check_parameter (const char *filename, const xmlChar *node_name, + parameter *p) +{ + struct { + gboolean id; + gboolean label; + gboolean string; + gboolean low_label; + gboolean high_label; + gboolean low; + gboolean high; + gboolean value; + gboolean arg; + gboolean invert_p; + gboolean arg_set; + gboolean arg_unset; + } allowed, require; + + memset (&allowed, 0, sizeof (allowed)); + memset (&require, 0, sizeof (require)); + + switch (p->type) + { + case COMMAND: + allowed.arg = TRUE; + require.arg = TRUE; + break; + case FAKE: + break; + case DESCRIPTION: + allowed.string = TRUE; + break; + case FAKEPREVIEW: + break; + case STRING: + allowed.id = TRUE; + require.id = TRUE; + allowed.label = TRUE; + require.label = TRUE; + allowed.arg = TRUE; + require.arg = TRUE; + break; + case FILENAME: + allowed.id = TRUE; + require.id = TRUE; + allowed.label = TRUE; + allowed.arg = TRUE; + require.arg = TRUE; + break; + case SLIDER: + allowed.id = TRUE; + require.id = TRUE; + allowed.label = TRUE; + allowed.low_label = TRUE; + allowed.high_label = TRUE; + allowed.arg = TRUE; + require.arg = TRUE; + allowed.low = TRUE; + /* require.low = TRUE; -- may be 0 */ + allowed.high = TRUE; + /* require.high = TRUE; -- may be 0 */ + allowed.value = TRUE; + /* require.value = TRUE; -- may be 0 */ + allowed.invert_p = TRUE; + break; + case SPINBUTTON: + allowed.id = TRUE; + require.id = TRUE; + allowed.label = TRUE; + allowed.arg = TRUE; + require.arg = TRUE; + allowed.low = TRUE; + /* require.low = TRUE; -- may be 0 */ + allowed.high = TRUE; + /* require.high = TRUE; -- may be 0 */ + allowed.value = TRUE; + /* require.value = TRUE; -- may be 0 */ + allowed.invert_p = TRUE; + break; + case BOOLEAN: + allowed.id = TRUE; + require.id = TRUE; + allowed.label = TRUE; + allowed.arg_set = TRUE; + allowed.arg_unset = TRUE; + break; + case SELECT: + allowed.id = TRUE; + require.id = TRUE; + break; + case SELECT_OPTION: + allowed.id = TRUE; + allowed.label = TRUE; + require.label = TRUE; + allowed.arg_set = TRUE; + break; + default: + abort(); + break; + } + +# define WARN(STR) \ + fprintf (stderr, "%s: %s: " STR " in <%s%s id=\"%s\">\n", \ + blurb(), filename, node_name, \ + (!strcmp((char *) node_name, "number") \ + ? (p->type == SPINBUTTON ? " type=spinbutton" : " type=slider")\ + : ""), \ + (p->id ? (char *) p->id : "")) +# define CHECK(SLOT,NAME) \ + if (p->SLOT && !allowed.SLOT) \ + WARN ("\"" NAME "\" is not a valid option"); \ + if (!p->SLOT && require.SLOT) \ + WARN ("\"" NAME "\" is required") + + CHECK (id, "id"); + CHECK (label, "_label"); + CHECK (string, "(body text)"); + CHECK (low_label, "_low-label"); + CHECK (high_label, "_high-label"); + CHECK (low, "low"); + CHECK (high, "high"); + CHECK (value, "default"); + CHECK (arg, "arg"); + CHECK (invert_p, "convert"); + CHECK (arg_set, "arg-set"); + CHECK (arg_unset, "arg-unset"); +# undef CHECK +# undef WARN + + if (p->type == SELECT) + sanity_check_menu_options (filename, node_name, p); +} + + +static void +sanity_check_menu_options (const char *filename, const xmlChar *node_name, + parameter *p) +{ + GList *opts; + int noptions = 0; + int nulls = 0; + char *prefix = 0; + +/* fprintf (stderr, "\n## %s\n", p->id);*/ + for (opts = p->options; opts; opts = opts->next) + { + parameter *s = (parameter *) opts->data; + if (!s->arg_set) nulls++; + noptions++; + + if (s->arg_set) + { + char *a = strdup ((char *) s->arg_set); + char *spc = strchr (a, ' '); + if (spc) *spc = 0; + if (prefix) + { + if (strcmp (a, prefix)) + fprintf (stderr, + "%s: %s: both \"%s\" and \"%s\" used in \n", + blurb(), filename, p->id); +} + + +/* "text" nodes show up for all the non-tag text in the file, including + all the newlines between tags. Warn if there is text there that + is not whitespace. + */ +static void +sanity_check_text_node (const char *filename, const xmlNodePtr node) +{ + const char *body = (const char *) node->content; + if (node->type != XML_TEXT_NODE) abort(); + while (isspace (*body)) body++; + if (*body) + fprintf (stderr, "%s: WARNING: %s: random text present: \"%s\"\n", + blurb(), filename, body); +} + + +/* Returns a list of strings, every switch mentioned in the parameters. + The strings must be freed. + */ +static GList * +get_all_switches (const char *filename, GList *parms) +{ + GList *switches = 0; + GList *p; + for (p = parms; p; p = p->next) + { + parameter *pp = (parameter *) p->data; + + if (pp->type == SELECT) + { + GList *list2 = get_all_switches (filename, pp->options); + switches = g_list_concat (switches, list2); + } + if (pp->arg && *pp->arg) + switches = g_list_append (switches, strdup ((char *) pp->arg)); + if (pp->arg_set && *pp->arg_set) + switches = g_list_append (switches, strdup ((char *) pp->arg_set)); + if (pp->arg_unset && *pp->arg_unset) + switches = g_list_append (switches, strdup ((char *) pp->arg_unset)); + } + return switches; +} + + +/* Ensures that no switch is mentioned more than once. + */ +static void +sanity_check_parameters (const char *filename, GList *parms) +{ + GList *list = get_all_switches (filename, parms); + GList *p; + for (p = list; p; p = p->next) + { + char *sw = (char *) p->data; + GList *p2; + + if (*sw != '-' && *sw != '+') + fprintf (stderr, "%s: %s: switch does not begin with hyphen \"%s\"\n", + blurb(), filename, sw); + + for (p2 = p->next; p2; p2 = p2->next) + { + const char *sw2 = (const char *) p2->data; + if (!strcmp (sw, sw2)) + fprintf (stderr, "%s: %s: duplicate switch \"%s\"\n", + blurb(), filename, sw); + } + + free (sw); + } + g_list_free (list); +} + + +/* Helper for make_parameters() + */ +static GList * +make_parameters_1 (const char *filename, xmlNodePtr node, GtkWidget *parent) +{ + GList *list = 0; + + for (; node; node = node->next) + { + const char *name = (char *) node->name; + if (!strcmp (name, "hgroup") || + !strcmp (name, "vgroup")) + { + GtkWidget *box = (*name == 'h' + ? gtk_hbox_new (FALSE, 0) + : gtk_vbox_new (FALSE, 0)); + GList *list2; + gtk_widget_show (box); + gtk_box_pack_start (GTK_BOX (parent), box, FALSE, FALSE, 0); + + list2 = make_parameters_1 (filename, node->xmlChildrenNode, box); + if (list2) + list = g_list_concat (list, list2); + } + else + { + parameter *p = make_parameter (filename, node); + if (p) + { + list = g_list_append (list, p); + make_parameter_widget (filename, p, parent); + } + } + } + return list; +} + + +/* Calls make_parameter() and make_parameter_widget() on each relevant + tag in the XML tree. Also handles the "hgroup" and "vgroup" flags. + Returns a GList of `parameter' objects. + */ +static GList * +make_parameters (const char *filename, xmlNodePtr node, GtkWidget *parent) +{ + for (; node; node = node->next) + { + if (node->type == XML_ELEMENT_NODE && + !strcmp ((char *) node->name, "screensaver")) + return make_parameters_1 (filename, node->xmlChildrenNode, parent); + } + return 0; +} + + +static gfloat +invert_range (gfloat low, gfloat high, gfloat value) +{ + gfloat range = high-low; + gfloat off = value-low; + return (low + (range - off)); +} + + +static GtkAdjustment * +make_adjustment (const char *filename, parameter *p) +{ + float range = (p->high - p->low); + float value = (p->invert_p + ? invert_range (p->low, p->high, p->value) + : p->value); + gfloat si = (p->high - p->low) / 100; + gfloat pi = (p->high - p->low) / 10; + gfloat page_size = ((p->type == SLIDER) ? 1 : 0); + + if (p->value < p->low || p->value > p->high) + { + if (debug_p && p->integer_p) + fprintf (stderr, "%s: WARNING: %s: %d is not in range [%d, %d]\n", + blurb(), filename, + (int) p->value, (int) p->low, (int) p->high); + else if (debug_p) + fprintf (stderr, + "%s: WARNING: %s: %.2f is not in range [%.2f, %.2f]\n", + blurb(), filename, p->value, p->low, p->high); + value = (value < p->low ? p->low : p->high); + } +#if 0 + else if (debug_p && p->value < 1000 && p->high >= 10000) + { + if (p->integer_p) + fprintf (stderr, + "%s: WARNING: %s: %d is suspicious for range [%d, %d]\n", + blurb(), filename, + (int) p->value, (int) p->low, (int) p->high); + else + fprintf (stderr, + "%s: WARNING: %s: %.2f is suspicious for range [%.2f, %.2f]\n", + blurb(), filename, p->value, p->low, p->high); + } +#endif /* 0 */ + + si = (int) (si + 0.5); + pi = (int) (pi + 0.5); + if (si < 1) si = 1; + if (pi < 1) pi = 1; + + if (range <= 500) si = 1; + + return GTK_ADJUSTMENT (gtk_adjustment_new (value, + p->low, + p->high + page_size, + si, pi, page_size)); +} + + + +static void +set_widget_min_width (GtkWidget *w, int width) +{ + GtkRequisition req; + gtk_widget_size_request (GTK_WIDGET (w), &req); + if (req.width < width) + gtk_widget_set_size_request (GTK_WIDGET (w), width, -1); +} + + +/* If we're inside a vbox, we need to put an hbox in it, or labels appear + on top instead of to the left, and things stretch to the full width of + the window. + */ +static GtkWidget * +insert_fake_hbox (GtkWidget *parent) +{ + if (GTK_IS_VBOX (parent)) + { + GtkWidget *hbox = gtk_hbox_new (FALSE, 0); + gtk_box_pack_start (GTK_BOX (parent), hbox, FALSE, FALSE, 4); + gtk_widget_show (hbox); + return hbox; + } + return parent; +} + + +static void +link_atk_label_to_widget(GtkWidget *label, GtkWidget *widget) +{ + AtkObject *atk_label = gtk_widget_get_accessible (label); + AtkObject *atk_widget = gtk_widget_get_accessible (widget); + + atk_object_add_relationship (atk_label, ATK_RELATION_LABEL_FOR, + atk_widget); + atk_object_add_relationship (atk_widget, ATK_RELATION_LABELLED_BY, + atk_label); +} + +/* Given a `parameter' struct, allocates an appropriate GtkWidget for it, + and stores it in `p->widget'. + `parent' must be a GtkBox. + */ +static void +make_parameter_widget (const char *filename, parameter *p, GtkWidget *parent) +{ + const char *label = (char *) p->label; + if (p->widget) return; + + switch (p->type) + { + case STRING: + { + GtkWidget *entry = gtk_entry_new (); + parent = insert_fake_hbox (parent); + if (label) + { + GtkWidget *w = gtk_label_new (_(label)); + link_atk_label_to_widget (w, entry); + gtk_label_set_justify (GTK_LABEL (w), GTK_JUSTIFY_RIGHT); + gtk_misc_set_alignment (GTK_MISC (w), 1.0, 0.5); + set_widget_min_width (GTK_WIDGET (w), MIN_LABEL_WIDTH); + gtk_widget_show (w); + gtk_box_pack_start (GTK_BOX (parent), w, FALSE, FALSE, 4); + } + + p->widget = entry; + if (p->string) + gtk_entry_set_text (GTK_ENTRY (p->widget), (char *) p->string); + gtk_box_pack_start (GTK_BOX (parent), p->widget, FALSE, FALSE, 4); + break; + } + case FILENAME: + { + GtkWidget *L = gtk_label_new (label ? _(label) : ""); + GtkWidget *entry = gtk_entry_new (); + GtkWidget *button = gtk_button_new_with_label (_("Browse...")); + link_atk_label_to_widget (L, entry); + gtk_widget_show (entry); + gtk_widget_show (button); + p->widget = entry; + + gtk_signal_connect (GTK_OBJECT (button), + "clicked", GTK_SIGNAL_FUNC (browse_button_cb), + (gpointer) entry); + + gtk_label_set_justify (GTK_LABEL (L), GTK_JUSTIFY_RIGHT); + gtk_misc_set_alignment (GTK_MISC (L), 1.0, 0.5); + set_widget_min_width (GTK_WIDGET (L), MIN_LABEL_WIDTH); + gtk_widget_show (L); + + if (p->string) + gtk_entry_set_text (GTK_ENTRY (entry), (char *) p->string); + + parent = insert_fake_hbox (parent); + gtk_box_pack_start (GTK_BOX (parent), L, FALSE, FALSE, 4); + gtk_box_pack_start (GTK_BOX (parent), entry, TRUE, TRUE, 4); + gtk_box_pack_start (GTK_BOX (parent), button, FALSE, FALSE, 4); + break; + } + case SLIDER: + { + GtkAdjustment *adj = make_adjustment (filename, p); + GtkWidget *scale = gtk_hscale_new (adj); + GtkWidget *labelw = 0; + + if (label) + { + labelw = gtk_label_new (_(label)); + link_atk_label_to_widget (labelw, scale); + gtk_label_set_justify (GTK_LABEL (labelw), GTK_JUSTIFY_LEFT); + gtk_misc_set_alignment (GTK_MISC (labelw), 0.0, 0.5); + set_widget_min_width (GTK_WIDGET (labelw), MIN_LABEL_WIDTH); + gtk_widget_show (labelw); + gtk_box_pack_start (GTK_BOX (parent), labelw, FALSE, FALSE, 2); + } + + /* Do this after 'labelw' so that it appears above, not to left. */ + parent = insert_fake_hbox (parent); + + if (p->low_label) + { + GtkWidget *w = gtk_label_new (_((char *) p->low_label)); + link_atk_label_to_widget (w, scale); + gtk_label_set_justify (GTK_LABEL (w), GTK_JUSTIFY_RIGHT); + gtk_misc_set_alignment (GTK_MISC (w), 1.0, 0.5); + set_widget_min_width (GTK_WIDGET (w), MIN_LABEL_WIDTH); + gtk_widget_show (w); + gtk_box_pack_start (GTK_BOX (parent), w, FALSE, FALSE, 4); + } + + gtk_scale_set_value_pos (GTK_SCALE (scale), GTK_POS_BOTTOM); + gtk_scale_set_draw_value (GTK_SCALE (scale), debug_p); + gtk_scale_set_digits (GTK_SCALE (scale), (p->integer_p ? 0 : 2)); + set_widget_min_width (GTK_WIDGET (scale), MIN_SLIDER_WIDTH); + + gtk_box_pack_start (GTK_BOX (parent), scale, FALSE, FALSE, 4); + + gtk_widget_show (scale); + + if (p->high_label) + { + GtkWidget *w = gtk_label_new (_((char *) p->high_label)); + link_atk_label_to_widget (w, scale); + gtk_label_set_justify (GTK_LABEL (w), GTK_JUSTIFY_LEFT); + gtk_misc_set_alignment (GTK_MISC (w), 0.0, 0.5); + set_widget_min_width (GTK_WIDGET (w), MIN_LABEL_WIDTH); + gtk_widget_show (w); + gtk_box_pack_start (GTK_BOX (parent), w, FALSE, FALSE, 4); + } + + p->widget = scale; + break; + } + case SPINBUTTON: + { + GtkAdjustment *adj = make_adjustment (filename, p); + GtkWidget *spin = gtk_spin_button_new (adj, 15, 0); + gtk_spin_button_set_numeric (GTK_SPIN_BUTTON (spin), TRUE); + gtk_spin_button_set_snap_to_ticks (GTK_SPIN_BUTTON (spin), TRUE); + gtk_spin_button_set_value (GTK_SPIN_BUTTON (spin), GET_ADJ_VALUE(adj)); + set_widget_min_width (GTK_WIDGET (spin), MIN_SPINBUTTON_WIDTH); + + if (label) + { + GtkWidget *w = gtk_label_new (_(label)); + link_atk_label_to_widget (w, spin); + gtk_label_set_justify (GTK_LABEL (w), GTK_JUSTIFY_RIGHT); + gtk_misc_set_alignment (GTK_MISC (w), 1.0, 0.5); + set_widget_min_width (GTK_WIDGET (w), MIN_LABEL_WIDTH); + gtk_widget_show (w); + parent = insert_fake_hbox (parent); + gtk_box_pack_start (GTK_BOX (parent), w, FALSE, FALSE, 4); + } + + gtk_widget_show (spin); + gtk_box_pack_start (GTK_BOX (parent), spin, FALSE, FALSE, 4); + + p->widget = spin; + break; + } + case BOOLEAN: + { + p->widget = gtk_check_button_new_with_label (_(label)); + /* Let these stretch -- doesn't hurt. + parent = insert_fake_hbox (parent); + */ + gtk_box_pack_start (GTK_BOX (parent), p->widget, FALSE, FALSE, 4); + break; + } + case SELECT: + { + GtkWidget *opt = gtk_option_menu_new (); + GtkWidget *menu = gtk_menu_new (); + GList *opts; + + for (opts = p->options; opts; opts = opts->next) + { + parameter *s = (parameter *) opts->data; + GtkWidget *i = gtk_menu_item_new_with_label (_((char *) s->label)); + gtk_widget_show (i); + gtk_menu_append (GTK_MENU (menu), i); + } + + gtk_option_menu_set_menu (GTK_OPTION_MENU (opt), menu); + p->widget = opt; + parent = insert_fake_hbox (parent); + gtk_box_pack_start (GTK_BOX (parent), p->widget, FALSE, FALSE, 4); + break; + } + + case COMMAND: + case FAKE: + case DESCRIPTION: + case FAKEPREVIEW: + break; + default: + abort(); + } + + if (p->widget) + { + gtk_widget_set_name (p->widget, (char *) p->id); + gtk_widget_show (p->widget); + } +} + + +/* File selection. + Absurdly, there is no GTK file entry widget, only a GNOME one, + so in order to avoid depending on GNOME in this code, we have + to do it ourselves. + */ + +/* cancel button on GtkFileSelection: user_data unused */ +static void +file_sel_cancel (GtkWidget *button, gpointer user_data) +{ + GtkWidget *dialog = button; + while (GET_PARENT (dialog)) + dialog = GET_PARENT (dialog); + gtk_widget_destroy (dialog); +} + +/* ok button on GtkFileSelection: user_data is the corresponding GtkEntry */ +static void +file_sel_ok (GtkWidget *button, gpointer user_data) +{ + GtkWidget *entry = GTK_WIDGET (user_data); + GtkWidget *dialog = button; + const char *path; + + while (GET_PARENT (dialog)) + dialog = GET_PARENT (dialog); + gtk_widget_hide (dialog); + + path = gtk_file_selection_get_filename (GTK_FILE_SELECTION (dialog)); + /* apparently one doesn't free `path' */ + + gtk_entry_set_text (GTK_ENTRY (entry), path); + gtk_entry_set_position (GTK_ENTRY (entry), strlen (path)); + + gtk_widget_destroy (dialog); +} + +/* WM close on GtkFileSelection: user_data unused */ +static void +file_sel_close (GtkWidget *widget, GdkEvent *event, gpointer user_data) +{ + file_sel_cancel (widget, user_data); +} + +/* "Browse" button: user_data is the corresponding GtkEntry */ +static void +browse_button_cb (GtkButton *button, gpointer user_data) +{ + GtkWidget *entry = GTK_WIDGET (user_data); + const char *text = gtk_entry_get_text (GTK_ENTRY (entry)); + GtkFileSelection *selector = + GTK_FILE_SELECTION (gtk_file_selection_new (_("Select file."))); + + gtk_file_selection_set_filename (selector, text); + gtk_signal_connect (GTK_OBJECT (selector->ok_button), + "clicked", GTK_SIGNAL_FUNC (file_sel_ok), + (gpointer) entry); + gtk_signal_connect (GTK_OBJECT (selector->cancel_button), + "clicked", GTK_SIGNAL_FUNC (file_sel_cancel), + (gpointer) entry); + gtk_signal_connect (GTK_OBJECT (selector), "delete_event", + GTK_SIGNAL_FUNC (file_sel_close), + (gpointer) entry); + + gtk_window_set_modal (GTK_WINDOW (selector), TRUE); + gtk_widget_show (GTK_WIDGET (selector)); +} + + +/* Converting to and from command-lines + */ + + +/* Returns a copy of string that has been quoted according to shell rules: + it may have been wrapped in "" and had some characters backslashed; or + it may be unchanged. + */ +static char * +shell_quotify (const char *string) +{ + char *string2 = (char *) malloc ((strlen (string) * 2) + 10); + const char *in; + char *out; + int need_quotes = 0; + int in_length = 0; + + out = string2; + *out++ = '"'; + for (in = string; *in; in++) + { + in_length++; + if (*in == '!' || + *in == '"' || + *in == '$') + { + need_quotes = 1; + *out++ = '\\'; + *out++ = *in; + } + else if (*in <= ' ' || + *in >= 127 || + *in == '\'' || + *in == '#' || + *in == '%' || + *in == '&' || + *in == '(' || + *in == ')' || + *in == '*') + { + need_quotes = 1; + *out++ = *in; + } + else + *out++ = *in; + } + *out++ = '"'; + *out = 0; + + if (in_length == 0) + need_quotes = 1; + + if (need_quotes) + return (string2); + + free (string2); + return strdup (string); +} + +/* Modify the string in place to remove wrapping double-quotes + and interior backslashes. + */ +static void +de_stringify (char *s) +{ + char q = s[0]; + if (q != '\'' && q != '\"' && q != '`') + abort(); + memmove (s, s+1, strlen (s)+1); + while (*s && *s != q) + { + if (*s == '\\') + memmove (s, s+1, strlen (s)+1); + s++; + } + if (*s != q) abort(); + *s = 0; +} + + +/* Substitutes a shell-quotified version of `value' into `p->arg' at + the place where the `%' character appeared. + */ +static char * +format_switch (parameter *p, const char *value) +{ + char *fmt = (char *) p->arg; + char *v2; + char *result, *s; + if (!fmt || !value) return 0; + v2 = shell_quotify (value); + result = (char *) malloc (strlen (fmt) + strlen (v2) + 10); + s = result; + for (; *fmt; fmt++) + if (*fmt != '%') + *s++ = *fmt; + else + { + strcpy (s, v2); + s += strlen (s); + } + *s = 0; + + free (v2); + return result; +} + + +/* Maps a `parameter' to a command-line switch. + Returns 0 if it can't, or if the parameter has the default value. + */ +static char * +parameter_to_switch (parameter *p) +{ + switch (p->type) + { + case COMMAND: + if (p->arg) + return strdup ((char *) p->arg); + else + return 0; + break; + case STRING: + case FILENAME: + if (!p->widget) return 0; + { + const char *s = gtk_entry_get_text (GTK_ENTRY (p->widget)); + char *v; + if (!strcmp ((s ? s : ""), + (p->string ? (char *) p->string : ""))) + v = 0; /* same as default */ + else + v = format_switch (p, s); + + /* don't free `s' */ + return v; + } + case SLIDER: + case SPINBUTTON: + if (!p->widget) return 0; + { + GtkAdjustment *adj = + (p->type == SLIDER + ? gtk_range_get_adjustment (GTK_RANGE (p->widget)) + : gtk_spin_button_get_adjustment (GTK_SPIN_BUTTON (p->widget))); + char buf[255]; + char *s1; + float value = (p->invert_p + ? invert_range (GET_ADJ_LOWER(adj), GET_ADJ_UPPER(adj), + GET_ADJ_VALUE(adj)) - 1 + : GET_ADJ_VALUE(adj)); + + if (value == p->value) /* same as default */ + return 0; + + if (p->integer_p) + sprintf (buf, "%d", (int) (value + (value > 0 ? 0.5 : -0.5))); + else + sprintf (buf, "%.4f", value); + + s1 = strchr (buf, '.'); + if (s1) + { + char *s2 = s1 + strlen(s1) - 1; + while (s2 > s1 && *s2 == '0') /* lose trailing zeroes */ + *s2-- = 0; + if (s2 >= s1 && *s2 == '.') /* lose trailing decimal */ + *s2-- = 0; + } + return format_switch (p, buf); + } + case BOOLEAN: + if (!p->widget) return 0; + { + GtkToggleButton *b = GTK_TOGGLE_BUTTON (p->widget); + const char *s = (gtk_toggle_button_get_active (b) + ? (char *) p->arg_set + : (char *) p->arg_unset); + if (s) + return strdup (s); + else + return 0; + } + case SELECT: + if (!p->widget) return 0; + { + GtkOptionMenu *opt = GTK_OPTION_MENU (p->widget); + GtkMenu *menu = GTK_MENU (gtk_option_menu_get_menu (opt)); + GtkWidget *selected = gtk_menu_get_active (menu); + GList *kids = gtk_container_children (GTK_CONTAINER (menu)); + int menu_elt = g_list_index (kids, (gpointer) selected); + GList *ol = g_list_nth (p->options, menu_elt); + parameter *o = (ol ? (parameter *) ol->data : 0); + const char *s; + if (!o) abort(); + if (o->type != SELECT_OPTION) abort(); + s = (char *) o->arg_set; + if (s) + return strdup (s); + else + return 0; + } + default: + if (p->widget) + abort(); + else + return 0; + } +} + +/* Maps a GList of `parameter' objects to a complete command-line string. + All arguments will be properly quoted. + */ +static char * +parameters_to_cmd_line (GList *parms, gboolean default_p) +{ + int L = g_list_length (parms); + int LL = 0; + char **strs = (char **) calloc (sizeof (*parms), L); + char *result; + char *out; + int i, j; + + for (i = 0, j = 0; parms; parms = parms->next, i++) + { + parameter *p = (parameter *) parms->data; + if (!default_p || p->type == COMMAND) + { + char *s = parameter_to_switch (p); + strs[j++] = s; + LL += (s ? strlen(s) : 0) + 1; + } + } + + result = (char *) malloc (LL + 10); + out = result; + for (i = 0; i < j; i++) + if (strs[i]) + { + strcpy (out, strs[i]); + out += strlen (out); + *out++ = ' '; + free (strs[i]); + } + *out = 0; + while (out > result && out[-1] == ' ') /* strip trailing spaces */ + *(--out) = 0; + free (strs); + + return result; +} + + +/* Returns a GList of the tokens the string, using shell syntax; + Quoted strings are handled as a single token. + */ +static GList * +tokenize_command_line (const char *cmd) +{ + GList *result = 0; + const char *s = cmd; + while (*s) + { + const char *start; + char *ss; + for (; isspace(*s); s++); /* skip whitespace */ + + start = s; + if (*s == '\'' || *s == '\"' || *s == '`') + { + char q = *s; + s++; + while (*s && *s != q) /* skip to matching quote */ + { + if (*s == '\\' && s[1]) /* allowing backslash quoting */ + s++; + s++; + } + s++; + } + else + { + while (*s && + (! (isspace(*s) || + *s == '\'' || + *s == '\"' || + *s == '`'))) + s++; + } + + if (s > start) + { + ss = (char *) malloc ((s - start) + 1); + strncpy (ss, start, s-start); + ss[s-start] = 0; + if (*ss == '\'' || *ss == '\"' || *ss == '`') + de_stringify (ss); + result = g_list_append (result, ss); + } + } + + return result; +} + +static void parameter_set_switch (parameter *, gpointer value); +static gboolean parse_command_line_into_parameters_1 (const char *filename, + GList *parms, + const char *option, + const char *value, + parameter *parent); + + +/* Parses the command line, and flushes those options down into + the `parameter' structs in the list. + */ +static void +parse_command_line_into_parameters (const char *filename, + const char *cmd, GList *parms) +{ + GList *tokens = tokenize_command_line (cmd); + GList *rest; + for (rest = tokens; rest; rest = rest->next) + { + char *option = rest->data; + rest->data = 0; + + if (option[0] != '-' && option[0] != '+') + { + if (debug_p) + fprintf (stderr, "%s: WARNING: %s: not a switch: \"%s\"\n", + blurb(), filename, option); + } + else + { + char *value = 0; + + if (rest->next) /* pop off the arg to this option */ + { + char *s = (char *) rest->next->data; + /* the next token is the next switch iff it matches "-[a-z]". + (To avoid losing on "-x -3.1".) + */ + if (s && (s[0] != '-' || !isalpha(s[1]))) + { + value = s; + rest->next->data = 0; + rest = rest->next; + } + } + + parse_command_line_into_parameters_1 (filename, parms, + option, value, 0); + if (value) free (value); + free (option); + } + } + g_list_free (tokens); +} + + +static gboolean +compare_opts (const char *option, const char *value, + const char *template) +{ + int ol = strlen (option); + char *c; + + if (strncmp (option, template, ol)) + return FALSE; + + if (template[ol] != (value ? ' ' : 0)) + return FALSE; + + /* At this point, we have a match against "option". + If template contains a %, we're done. + Else, compare against "value" too. + */ + c = strchr (template, '%'); + if (c) + return TRUE; + + if (!value) + return (template[ol] == 0); + if (strcmp (template + ol + 1, value)) + return FALSE; + + return TRUE; +} + + +static gboolean +parse_command_line_into_parameters_1 (const char *filename, + GList *parms, + const char *option, + const char *value, + parameter *parent) +{ + GList *p; + parameter *match = 0; + gint which = -1; + gint index = 0; + + for (p = parms; p; p = p->next) + { + parameter *pp = (parameter *) p->data; + which = -99; + + if (pp->type == SELECT) + { + if (parse_command_line_into_parameters_1 (filename, + pp->options, + option, value, + pp)) + { + which = -2; + match = pp; + } + } + else if (pp->arg) + { + if (compare_opts (option, value, (char *) pp->arg)) + { + which = -1; + match = pp; + } + } + else if (pp->arg_set) + { + if (compare_opts (option, value, (char *) pp->arg_set)) + { + which = 1; + match = pp; + } + } + else if (pp->arg_unset) + { + if (compare_opts (option, value, (char *) pp->arg_unset)) + { + which = 0; + match = pp; + } + } + + if (match) + break; + + index++; + } + + if (!match) + { + if (debug_p && !parent) + fprintf (stderr, "%s: WARNING: %s: no match for %s %s\n", + blurb(), filename, option, (value ? value : "")); + return FALSE; + } + + switch (match->type) + { + case STRING: + case FILENAME: + case SLIDER: + case SPINBUTTON: + if (which != -1) abort(); + parameter_set_switch (match, (gpointer) value); + break; + case BOOLEAN: + if (which != 0 && which != 1) abort(); + parameter_set_switch (match, GINT_TO_POINTER(which)); + break; + case SELECT_OPTION: + if (which != 1) abort(); + parameter_set_switch (parent, GINT_TO_POINTER(index)); + break; + default: + break; + } + return TRUE; +} + + +/* Set the parameter's value. + For STRING, FILENAME, SLIDER, and SPINBUTTON, `value' is a char*. + For BOOLEAN and SELECT, `value' is an int. + */ +static void +parameter_set_switch (parameter *p, gpointer value) +{ + if (p->type == SELECT_OPTION) abort(); + if (!p->widget) return; + switch (p->type) + { + case STRING: + case FILENAME: + { + gtk_entry_set_text (GTK_ENTRY (p->widget), (char *) value); + break; + } + case SLIDER: + case SPINBUTTON: + { + GtkAdjustment *adj = + (p->type == SLIDER + ? gtk_range_get_adjustment (GTK_RANGE (p->widget)) + : gtk_spin_button_get_adjustment (GTK_SPIN_BUTTON (p->widget))); + float f; + char c; + + if (1 == sscanf ((char *) value, "%f %c", &f, &c)) + { + if (p->invert_p) + f = invert_range (GET_ADJ_LOWER(adj), GET_ADJ_UPPER(adj), f) - 1; + gtk_adjustment_set_value (adj, f); + } + break; + } + case BOOLEAN: + { + GtkToggleButton *b = GTK_TOGGLE_BUTTON (p->widget); + gtk_toggle_button_set_active (b, GPOINTER_TO_INT(value)); + break; + } + case SELECT: + { + gtk_option_menu_set_history (GTK_OPTION_MENU (p->widget), + GPOINTER_TO_INT(value)); + break; + } + default: + abort(); + } +} + + +static void +restore_defaults (const char *progname, GList *parms) +{ + for (; parms; parms = parms->next) + { + parameter *p = (parameter *) parms->data; + if (!p->widget) continue; + switch (p->type) + { + case STRING: + case FILENAME: + { + gtk_entry_set_text (GTK_ENTRY (p->widget), + (p->string ? (char *) p->string : "")); + break; + } + case SLIDER: + case SPINBUTTON: + { + GtkAdjustment *adj = + (p->type == SLIDER + ? gtk_range_get_adjustment (GTK_RANGE (p->widget)) + : gtk_spin_button_get_adjustment (GTK_SPIN_BUTTON (p->widget))); + float value = (p->invert_p + ? invert_range (p->low, p->high, p->value) + : p->value); + gtk_adjustment_set_value (adj, value); + break; + } + case BOOLEAN: + { + /* A toggle button should be on by default if it inserts + nothing into the command line when on. E.g., it should + be on if `arg_set' is null. + */ + gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (p->widget), + (!p->arg_set || !*p->arg_set)); + break; + } + case SELECT: + { + GtkOptionMenu *opt = GTK_OPTION_MENU (p->widget); + GList *opts; + int selected = 0; + int index; + + for (opts = p->options, index = 0; opts; + opts = opts->next, index++) + { + parameter *s = (parameter *) opts->data; + /* The default menu item is the first one with + no `arg_set' field. */ + if (!s->arg_set) + { + selected = index; + break; + } + } + + gtk_option_menu_set_history (GTK_OPTION_MENU (opt), selected); + break; + } + default: + abort(); + } + } +} + + + +/* Documentation strings + */ + +static char * +get_description (GList *parms, gboolean verbose_p) +{ + parameter *doc = 0; + for (; parms; parms = parms->next) + { + parameter *p = (parameter *) parms->data; + if (p->type == DESCRIPTION) + { + doc = p; + break; + } + } + + if (!doc || !doc->string) + return 0; + else + { + char *d = strdup ((char *) doc->string); + char *s; + char *p; + for (s = d; *s; s++) + if (s[0] == '\n') + { + if (s[1] == '\n') /* blank line: leave it */ + s++; + else if (s[1] == ' ' || s[1] == '\t') + s++; /* next line is indented: leave newline */ + else if (!strncmp(s+1, "http:", 5)) + s++; /* next line begins a URL: leave newline */ + else + s[0] = ' '; /* delete newline to un-fold this line */ + } + + /* strip off leading whitespace on first line only */ + for (s = d; *s && (*s == ' ' || *s == '\t'); s++) + ; + while (*s == '\n') /* strip leading newlines */ + s++; + if (s != d) + memmove (d, s, strlen(s)+1); + + /* strip off trailing whitespace and newlines */ + { + int L = strlen(d); + while (L && isspace(d[L-1])) + d[--L] = 0; + } + + /* strip off duplicated whitespaces */ + for (s = d; *s; s++) + if (s[0] == ' ') + { + p = s+1; + while (*s == ' ') + s++; + if (*p && (s != p)) + memmove (p, s, strlen(s)+1); + } + +#if 0 + if (verbose_p) + { + fprintf (stderr, "%s: text read is \"%s\"\n", blurb(),doc->string); + fprintf (stderr, "%s: description is \"%s\"\n", blurb(), d); + fprintf (stderr, "%s: translation is \"%s\"\n", blurb(), _(d)); + } +#endif /* 0 */ + + return (d); + } +} + + +/* External interface. + */ + +static conf_data * +load_configurator_1 (const char *program, const char *arguments, + gboolean verbose_p) +{ + const char *dir = hack_configuration_path; + char *base_program; + int L = strlen (dir); + char *file; + char *s; + FILE *f; + conf_data *data; + + if (L == 0) return 0; + + base_program = strrchr(program, '/'); + if (base_program) base_program++; + if (!base_program) base_program = (char *) program; + + file = (char *) malloc (L + strlen (base_program) + 10); + data = (conf_data *) calloc (1, sizeof(*data)); + + strcpy (file, dir); + if (file[L-1] != '/') + file[L++] = '/'; + strcpy (file+L, base_program); + + for (s = file+L; *s; s++) + if (*s == '/' || *s == ' ') + *s = '_'; + else if (isupper (*s)) + *s = tolower (*s); + + strcat (file+L, ".xml"); + + f = fopen (file, "r"); + if (f) + { + int res, size = 1024; + char chars[1024]; + xmlParserCtxtPtr ctxt; + xmlDocPtr doc = 0; + GtkWidget *vbox0; + GList *parms; + + if (verbose_p) + fprintf (stderr, "%s: reading %s...\n", blurb(), file); + + res = fread (chars, 1, 4, f); + if (res <= 0) + { + free (data); + data = 0; + goto DONE; + } + + ctxt = xmlCreatePushParserCtxt(NULL, NULL, chars, res, file); + while ((res = fread(chars, 1, size, f)) > 0) + xmlParseChunk (ctxt, chars, res, 0); + xmlParseChunk (ctxt, chars, 0, 1); + doc = ctxt->myDoc; + xmlFreeParserCtxt (ctxt); + fclose (f); + + /* Parsed the XML file. Now make some widgets. */ + + vbox0 = gtk_vbox_new (FALSE, 0); + gtk_widget_show (vbox0); + + parms = make_parameters (file, doc->xmlRootNode, vbox0); + sanity_check_parameters (file, parms); + + xmlFreeDoc (doc); + + restore_defaults (program, parms); + if (arguments && *arguments) + parse_command_line_into_parameters (program, arguments, parms); + + data->widget = vbox0; + data->parameters = parms; + data->description = get_description (parms, verbose_p); + } + else + { + parameter *p; + + if (verbose_p) + fprintf (stderr, "%s: %s does not exist.\n", blurb(), file); + + p = calloc (1, sizeof(*p)); + p->type = COMMAND; + p->arg = (xmlChar *) strdup (arguments); + + data->parameters = g_list_append (0, (gpointer) p); + } + + data->progname = strdup (program); + + DONE: + free (file); + return data; +} + +static void +split_command_line (const char *full_command_line, + char **prog_ret, char **args_ret) +{ + char *line = strdup (full_command_line); + char *prog; + char *args; + char *s; + + prog = line; + s = line; + while (*s) + { + if (isspace (*s)) + { + *s = 0; + s++; + while (isspace (*s)) s++; + break; + } + else if (*s == '=') /* if the leading word contains an "=", skip it. */ + { + while (*s && !isspace (*s)) s++; + while (isspace (*s)) s++; + prog = s; + } + s++; + } + args = s; + + *prog_ret = strdup (prog); + *args_ret = strdup (args); + free (line); +} + + +conf_data * +load_configurator (const char *full_command_line, gboolean verbose_p) +{ + char *prog; + char *args; + conf_data *cd; + debug_p = verbose_p; + split_command_line (full_command_line, &prog, &args); + cd = load_configurator_1 (prog, args, verbose_p); + free (prog); + free (args); + return cd; +} + + + +char * +get_configurator_command_line (conf_data *data, gboolean default_p) +{ + char *args = parameters_to_cmd_line (data->parameters, default_p); + char *result = (char *) malloc (strlen (data->progname) + + strlen (args) + 2); + strcpy (result, data->progname); + strcat (result, " "); + strcat (result, args); + free (args); + return result; +} + + +void +set_configurator_command_line (conf_data *data, const char *full_command_line) +{ + char *prog; + char *args; + split_command_line (full_command_line, &prog, &args); + if (data->progname) free (data->progname); + data->progname = prog; + restore_defaults (prog, data->parameters); + parse_command_line_into_parameters (prog, args, data->parameters); + free (args); +} + +void +free_conf_data (conf_data *data) +{ + if (data->parameters) + { + GList *rest; + for (rest = data->parameters; rest; rest = rest->next) + { + free_parameter ((parameter *) rest->data); + rest->data = 0; + } + g_list_free (data->parameters); + data->parameters = 0; + } + + if (data->widget) + gtk_widget_destroy (data->widget); + + if (data->progname) + free (data->progname); + if (data->description) + free (data->description); + + memset (data, ~0, sizeof(*data)); + free (data); +} + + +#endif /* HAVE_GTK && HAVE_XML -- whole file */ diff --git a/driver/demo-Gtk-conf.h b/driver/demo-Gtk-conf.h new file mode 100644 index 00000000..f462152c --- /dev/null +++ b/driver/demo-Gtk-conf.h @@ -0,0 +1,31 @@ +/* demo-Gtk-conf.c --- implements the dynamic configuration dialogs. + * xscreensaver, Copyright (c) 2001-2008 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. + */ + +#ifndef _DEMO_GTK_CONF_H_ +#define _DEMO_GTK_CONF_H_ + +typedef struct { + GtkWidget *widget; /* the container widget with the sliders and stuff. */ + GList *parameters; /* internal data -- hands off */ + char *progname; + char *progclass; + char *description; +} conf_data; + +extern conf_data *load_configurator (const char *cmd_line, gboolean verbose_p); +extern char *get_configurator_command_line (conf_data *, gboolean default_p); +extern void set_configurator_command_line (conf_data *, const char *cmd_line); +extern void free_conf_data (conf_data *); + +extern const char *hack_configuration_path; + +#endif /* _DEMO_GTK_CONF_H_ */ diff --git a/driver/demo-Gtk-stubs.h b/driver/demo-Gtk-stubs.h new file mode 100644 index 00000000..c897d3ed --- /dev/null +++ b/driver/demo-Gtk-stubs.h @@ -0,0 +1,90 @@ +#include + + +void +activate_menu_cb (GtkMenuItem *menuitem, + gpointer user_data); + +void +lock_menu_cb (GtkMenuItem *menuitem, + gpointer user_data); + +void +kill_menu_cb (GtkMenuItem *menuitem, + gpointer user_data); + +void +restart_menu_cb (GtkMenuItem *menuitem, + gpointer user_data); + +void +exit_menu_cb (GtkMenuItem *menuitem, + gpointer user_data); + +void +about_menu_cb (GtkMenuItem *menuitem, + gpointer user_data); + +void +doc_menu_cb (GtkMenuItem *menuitem, + gpointer user_data); + +void +switch_page_cb (GtkNotebook *notebook, + GtkNotebookPage *page, + gint page_num, + gpointer user_data); + +void +pref_changed_cb (GtkToggleButton *togglebutton, + gpointer user_data); + +void +run_this_cb (GtkButton *button, + gpointer user_data); + +void +settings_cb (GtkButton *button, + gpointer user_data); + +void +run_next_cb (GtkButton *button, + gpointer user_data); + +void +run_prev_cb (GtkButton *button, + gpointer user_data); + +void +browse_image_dir_cb (GtkButton *button, + gpointer user_data); + +void +settings_switch_page_cb (GtkNotebook *notebook, + GtkNotebookPage *page, + gint page_num, + gpointer user_data); + +void +manual_cb (GtkButton *button, + gpointer user_data); + +void +settings_adv_cb (GtkButton *button, + gpointer user_data); + +void +settings_std_cb (GtkButton *button, + gpointer user_data); + +void +settings_reset_cb (GtkButton *button, + gpointer user_data); + +void +settings_ok_cb (GtkButton *button, + gpointer user_data); + +void +settings_cancel_cb (GtkButton *button, + gpointer user_data); diff --git a/driver/demo-Gtk-support.c b/driver/demo-Gtk-support.c new file mode 100644 index 00000000..881129c4 --- /dev/null +++ b/driver/demo-Gtk-support.c @@ -0,0 +1,219 @@ +/* + * DO NOT EDIT THIS FILE - it is generated by Glade. + WARNING: I did edit this file! Be careful! -jwz + */ + +#ifdef HAVE_CONFIG_H +# include +#endif + +#include +#include +#include +#include + +#include + +#include "demo-Gtk-support.h" + +/* jwz -- dumbass Glade1 doesn't emit code that can read PNGs. this does. */ +#ifdef HAVE_GDK_PIXBUF +# ifdef HAVE_GTK2 +# include +# else /* !HAVE_GTK2 */ +# include +# endif /* !HAVE_GTK2 */ +#endif /* HAVE_GDK_PIXBUF */ + + +/* This is an internally used function to check if a pixmap file exists. */ +static gchar* check_file_exists (const gchar *directory, + const gchar *filename); + +/* This is an internally used function to create pixmaps. */ +static GtkWidget* create_dummy_pixmap (GtkWidget *widget); + +GtkWidget* +lookup_widget (GtkWidget *widget, + const gchar *widget_name) +{ + GtkWidget *parent, *found_widget; + + for (;;) + { + if (GTK_IS_MENU (widget)) + parent = gtk_menu_get_attach_widget (GTK_MENU (widget)); + else + parent = widget->parent; + if (parent == NULL) + break; + widget = parent; + } + + found_widget = (GtkWidget*) gtk_object_get_data (GTK_OBJECT (widget), + widget_name); + if (!found_widget) + g_warning ("Widget not found: %s", widget_name); + return found_widget; +} + +/* This is a dummy pixmap we use when a pixmap can't be found. */ +static char *dummy_pixmap_xpm[] = { +/* columns rows colors chars-per-pixel */ +"1 1 1 1", +" c None", +/* pixels */ +" " +}; + +/* This is an internally used function to create pixmaps. */ +static GtkWidget* +create_dummy_pixmap (GtkWidget *widget) +{ + GdkColormap *colormap; + GdkPixmap *gdkpixmap; + GdkBitmap *mask; + GtkWidget *pixmap; + + colormap = gtk_widget_get_colormap (widget); + gdkpixmap = gdk_pixmap_colormap_create_from_xpm_d (NULL, colormap, &mask, + NULL, dummy_pixmap_xpm); + if (gdkpixmap == NULL) + g_error ("Couldn't create replacement pixmap."); + pixmap = gtk_pixmap_new (gdkpixmap, mask); + gdk_pixmap_unref (gdkpixmap); + gdk_bitmap_unref (mask); + return pixmap; +} + +static GList *pixmaps_directories = NULL; + +/* Use this function to set the directory containing installed pixmaps. */ +void +add_pixmap_directory (const gchar *directory) +{ + pixmaps_directories = g_list_prepend (pixmaps_directories, + g_strdup (directory)); +} + +/* This is an internally used function to create pixmaps. */ +/* #### Warning: this version of this function hacked by jwz to + support PNGs. Don't let Glade1 overwrite this! + */ +GtkWidget* +create_pixmap (GtkWidget *widget, + const gchar *filename) +{ + gchar *found_filename = NULL; + GdkColormap *colormap = 0; + GdkPixmap *gdkpixmap = 0; + GdkBitmap *mask = 0; + GtkWidget *pixmap = 0; + GList *elem = 0; + + if (!filename || !filename[0]) + return create_dummy_pixmap (widget); + + /* We first try any pixmaps directories set by the application. */ + elem = pixmaps_directories; + while (elem) + { + found_filename = check_file_exists ((gchar*)elem->data, filename); + if (found_filename) + break; + elem = elem->next; + } + + /* If we haven't found the pixmap, try the source directory. */ + if (!found_filename) + { + found_filename = check_file_exists ("../utils/images", filename); + } + + if (!found_filename) + { + g_warning (_("Couldn't find pixmap file: %s"), filename); + return create_dummy_pixmap (widget); + } + + colormap = gtk_widget_get_colormap (widget); + +# ifndef HAVE_GDK_PIXBUF + + gdkpixmap = gdk_pixmap_colormap_create_from_xpm (NULL, colormap, &mask, + NULL, found_filename); + if (gdkpixmap == NULL) + { + g_warning (_("Error loading pixmap file: %s"), found_filename); + g_free (found_filename); + return create_dummy_pixmap (widget); + } + +# else /* HAVE_GDK_PIXBUF */ + + /* jwz -- dumbass Glade1 doesn't emit code that can read PNGs. + This code does... */ + + /* #### Danger: we aren't using `colormap'... */ + + { + GdkPixbuf *pb; +# ifdef HAVE_GTK2 + GError *gerr = 0; +# endif /* HAVE_GTK2 */ + + pb = gdk_pixbuf_new_from_file (found_filename +# ifdef HAVE_GTK2 + , &gerr +# endif /* HAVE_GTK2 */ + ); + + if (pb) + { + gdkpixmap = 0; + mask = 0; + gdk_pixbuf_render_pixmap_and_mask (pb, &gdkpixmap, &mask, 128); + } + else + { + g_warning (_("Error loading pixmap file: %s"), found_filename); +# ifdef HAVE_GTK2 + if (gerr && gerr->message && *gerr->message) + g_warning (_("reason: %s\n"), gerr->message); +# endif /* HAVE_GTK2 */ + + return create_dummy_pixmap (widget); + } + } +# endif /* HAVE_GDK_PIXBUF */ + + g_free (found_filename); + pixmap = gtk_pixmap_new (gdkpixmap, mask); + gdk_pixmap_unref (gdkpixmap); + gdk_bitmap_unref (mask); + + return pixmap; +} + +/* This is an internally used function to check if a pixmap file exists. */ +static gchar* +check_file_exists (const gchar *directory, + const gchar *filename) +{ + gchar *full_filename; + struct stat s; + gint status; + + full_filename = (gchar*) g_malloc (strlen (directory) + 1 + + strlen (filename) + 1); + strcpy (full_filename, directory); + strcat (full_filename, G_DIR_SEPARATOR_S); + strcat (full_filename, filename); + + status = stat (full_filename, &s); + if (status == 0 && S_ISREG (s.st_mode)) + return full_filename; + g_free (full_filename); + return NULL; +} + diff --git a/driver/demo-Gtk-support.h b/driver/demo-Gtk-support.h new file mode 100644 index 00000000..931bc5ad --- /dev/null +++ b/driver/demo-Gtk-support.h @@ -0,0 +1,61 @@ +/* + * DO NOT EDIT THIS FILE - it is generated by Glade. + */ + +#ifdef HAVE_CONFIG_H +# include +#endif + +#include + +/* + * Standard gettext macros. + */ +#ifdef ENABLE_NLS +# include +# undef _ +# define _(String) dgettext (PACKAGE, String) +# ifdef gettext_noop +# define N_(String) gettext_noop (String) +# else +# define N_(String) (String) +# endif +#else +# define textdomain(String) (String) +# define gettext(String) (String) +# define dgettext(Domain,Message) (Message) +# define dcgettext(Domain,Message,Type) (Message) +# define bindtextdomain(Domain,Directory) (Domain) +# define _(String) (String) +# define N_(String) (String) +#endif + + +/* + * Public Functions. + */ + +/* + * This function returns a widget in a component created by Glade. + * Call it with the toplevel widget in the component (i.e. a window/dialog), + * or alternatively any widget in the component, and the name of the widget + * you want returned. + */ +GtkWidget* lookup_widget (GtkWidget *widget, + const gchar *widget_name); + +/* get_widget() is deprecated. Use lookup_widget instead. */ +#define get_widget lookup_widget + +/* Use this function to set the directory containing installed pixmaps. */ +void add_pixmap_directory (const gchar *directory); + + +/* + * Private Functions. + */ + +/* This is used to create the pixmaps in the interface. */ +GtkWidget* create_pixmap (GtkWidget *widget, + const gchar *filename); + diff --git a/driver/demo-Gtk-widgets.c b/driver/demo-Gtk-widgets.c new file mode 100644 index 00000000..4e853c99 --- /dev/null +++ b/driver/demo-Gtk-widgets.c @@ -0,0 +1,1764 @@ +/* + * DO NOT EDIT THIS FILE - it is generated by Glade. + */ + +#ifdef HAVE_CONFIG_H +# include +#endif + +#include +#include +#include +#include + +#include +#include + +#include "demo-Gtk-stubs.h" +#include "demo-Gtk-widgets.h" +#include "demo-Gtk-support.h" + +# ifdef __GNUC__ +# define STFU __extension__ /* ignore gcc -pendantic warnings in next sexp */ +# else +# define STFU /* */ +# endif + +GtkWidget* +create_xscreensaver_demo (void) +{ + GtkWidget *xscreensaver_demo; + GtkWidget *outer_vbox; + GtkWidget *menubar; + guint tmp_key; + GtkWidget *file; + GtkWidget *file_menu; + GtkAccelGroup *file_menu_accels; + GtkWidget *activate_menu; + GtkWidget *lock_menu; + GtkWidget *kill_menu; + GtkWidget *restart; + GtkWidget *separator1; + GtkWidget *exit_menu; + GtkWidget *help; + GtkWidget *help_menu; + GtkAccelGroup *help_menu_accels; + GtkWidget *about_menu; + GtkWidget *doc_menu; + GtkWidget *notebook; + GtkWidget *demos_table; + GtkWidget *blanking_table; + GtkWidget *cycle_label; + GtkWidget *lock_button_eventbox; + GtkWidget *lock_button; + GtkWidget *timeout_label; + GtkObject *timeout_spinbutton_adj; + GtkWidget *timeout_spinbutton; + GtkWidget *timeout_mlabel; + GtkWidget *cycle_mlabel; + GtkWidget *lock_mlabel; + GtkObject *lock_spinbutton_adj; + GtkWidget *lock_spinbutton; + GtkObject *cycle_spinbutton_adj; + GtkWidget *cycle_spinbutton; + GtkWidget *demo_manual_hbbox; + GtkWidget *demo; + GtkWidget *settings; + GtkWidget *list_vbox; + GtkWidget *mode_hbox; + GtkWidget *mode_label; + GtkWidget *mode_menu; + GtkWidget *mode_menu_menu; + GtkWidget *glade_menuitem; + GtkWidget *col_head_hbox; + GtkWidget *use_col_frame; + GtkWidget *use_label; + GtkWidget *saver_col_frame; + GtkWidget *saver_label; + GtkWidget *scroller; + GtkWidget *viewport; + GtkWidget *list; + GtkWidget *centering_hbox; + GtkWidget *next_prev_hbox; + GtkWidget *next; + GtkWidget *prev; + GtkWidget *preview_frame; + GtkWidget *preview_aspectframe; + GtkWidget *preview; + GtkWidget *demo_tab; + GtkWidget *options_table; + GtkWidget *diag_frame; + GtkWidget *diag_hbox; + GtkWidget *diag_logo; + GtkWidget *diag_vbox; + GtkWidget *verbose_button_eventbox; + GtkWidget *verbose_button; + GtkWidget *capture_button_eventbox; + GtkWidget *capture_button; + GtkWidget *splash_button_eventbox; + GtkWidget *splash_button; + GtkWidget *cmap_frame; + GtkWidget *cmap_hbox; + GtkWidget *cmap_logo; + GtkWidget *cmap_vbox; + GtkWidget *install_button_eventbox; + GtkWidget *install_button; + GtkWidget *cmap_hr; + GtkWidget *fade_button_eventbox; + GtkWidget *fade_button; + GtkWidget *unfade_button_eventbox; + GtkWidget *unfade_button; + GtkWidget *fade_hbox; + GtkWidget *fade_dummy; + GtkWidget *fade_label; + GtkObject *fade_spinbutton_adj; + GtkWidget *fade_spinbutton; + GtkWidget *fade_sec_label; + GtkWidget *dpms_frame; + GtkWidget *dpms_hbox; + GtkWidget *dpms_logo; + GtkWidget *dpms_vbox; + GtkWidget *dpms_button_eventbox; + GtkWidget *dpms_button; + GtkWidget *dpms_table; + GtkObject *dpms_standby_spinbutton_adj; + GtkWidget *dpms_standby_spinbutton; + GtkWidget *dpms_standby_mlabel; + GtkWidget *dpms_suspend_mlabel; + GtkWidget *dpms_off_mlabel; + GtkWidget *dpms_off_label; + GtkWidget *dpms_suspend_label; + GtkWidget *dpms_standby_label; + GtkObject *dpms_suspend_spinbutton_adj; + GtkWidget *dpms_suspend_spinbutton; + GtkObject *dpms_off_spinbutton_adj; + GtkWidget *dpms_off_spinbutton; + GtkWidget *grab_frame; + GtkWidget *grab_hbox; + GtkWidget *img_logo; + GtkWidget *grab_vbox; + GtkWidget *grab_desk_eventbox; + GtkWidget *grab_desk_button; + GtkWidget *grab_video_eventbox; + GtkWidget *grab_video_button; + GtkWidget *grab_image_eventbox; + GtkWidget *grab_image_button; + GtkWidget *image_hbox; + GtkWidget *grab_dummy; + GtkWidget *image_text; + GtkWidget *image_browse_button; + GtkWidget *options_tab; + GtkAccelGroup *accel_group; + GtkTooltips *tooltips; + + tooltips = gtk_tooltips_new (); + + accel_group = gtk_accel_group_new (); + + xscreensaver_demo = gtk_window_new (GTK_WINDOW_TOPLEVEL); + gtk_widget_set_name (xscreensaver_demo, "xscreensaver_demo"); + gtk_object_set_data (GTK_OBJECT (xscreensaver_demo), "xscreensaver_demo", xscreensaver_demo); + gtk_window_set_title (GTK_WINDOW (xscreensaver_demo), _("XScreenSaver")); + gtk_window_set_wmclass (GTK_WINDOW (xscreensaver_demo), "xscreensaver", "XScreenSaver"); + + outer_vbox = gtk_vbox_new (FALSE, 5); + gtk_widget_set_name (outer_vbox, "outer_vbox"); + gtk_widget_ref (outer_vbox); + gtk_object_set_data_full (GTK_OBJECT (xscreensaver_demo), "outer_vbox", outer_vbox, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (outer_vbox); + gtk_container_add (GTK_CONTAINER (xscreensaver_demo), outer_vbox); + + menubar = gtk_menu_bar_new (); + gtk_widget_set_name (menubar, "menubar"); + gtk_widget_ref (menubar); + gtk_object_set_data_full (GTK_OBJECT (xscreensaver_demo), "menubar", menubar, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (menubar); + gtk_box_pack_start (GTK_BOX (outer_vbox), menubar, FALSE, FALSE, 0); + + file = gtk_menu_item_new_with_label (""); + tmp_key = gtk_label_parse_uline (GTK_LABEL (GTK_BIN (file)->child), + _("_File")); + gtk_widget_add_accelerator (file, "activate_item", accel_group, + tmp_key, GDK_MOD1_MASK, (GtkAccelFlags) 0); + gtk_widget_set_name (file, "file"); + gtk_widget_ref (file); + gtk_object_set_data_full (GTK_OBJECT (xscreensaver_demo), "file", file, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (file); + gtk_container_add (GTK_CONTAINER (menubar), file); + + file_menu = gtk_menu_new (); + gtk_widget_set_name (file_menu, "file_menu"); + gtk_widget_ref (file_menu); + gtk_object_set_data_full (GTK_OBJECT (xscreensaver_demo), "file_menu", file_menu, + (GtkDestroyNotify) gtk_widget_unref); + gtk_menu_item_set_submenu (GTK_MENU_ITEM (file), file_menu); + file_menu_accels = gtk_menu_ensure_uline_accel_group (GTK_MENU (file_menu)); + + activate_menu = gtk_menu_item_new_with_label (""); + tmp_key = gtk_label_parse_uline (GTK_LABEL (GTK_BIN (activate_menu)->child), + _("_Blank Screen Now")); + gtk_widget_add_accelerator (activate_menu, "activate_item", file_menu_accels, + tmp_key, 0, 0); + gtk_widget_set_name (activate_menu, "activate_menu"); + gtk_widget_ref (activate_menu); + gtk_object_set_data_full (GTK_OBJECT (xscreensaver_demo), "activate_menu", activate_menu, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (activate_menu); + gtk_container_add (GTK_CONTAINER (file_menu), activate_menu); + gtk_tooltips_set_tip (tooltips, activate_menu, _("Activate the XScreenSaver daemon now (locking the screen if so configured.)"), NULL); + + lock_menu = gtk_menu_item_new_with_label (""); + tmp_key = gtk_label_parse_uline (GTK_LABEL (GTK_BIN (lock_menu)->child), + _("_Lock Screen Now")); + gtk_widget_add_accelerator (lock_menu, "activate_item", file_menu_accels, + tmp_key, 0, 0); + gtk_widget_set_name (lock_menu, "lock_menu"); + gtk_widget_ref (lock_menu); + gtk_object_set_data_full (GTK_OBJECT (xscreensaver_demo), "lock_menu", lock_menu, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (lock_menu); + gtk_container_add (GTK_CONTAINER (file_menu), lock_menu); + gtk_tooltips_set_tip (tooltips, lock_menu, _("Lock the screen now (even if \"Lock Screen\" is unchecked.)"), NULL); + + kill_menu = gtk_menu_item_new_with_label (""); + tmp_key = gtk_label_parse_uline (GTK_LABEL (GTK_BIN (kill_menu)->child), + _("_Kill Daemon")); + gtk_widget_add_accelerator (kill_menu, "activate_item", file_menu_accels, + tmp_key, 0, 0); + gtk_widget_set_name (kill_menu, "kill_menu"); + gtk_widget_ref (kill_menu); + gtk_object_set_data_full (GTK_OBJECT (xscreensaver_demo), "kill_menu", kill_menu, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (kill_menu); + gtk_container_add (GTK_CONTAINER (file_menu), kill_menu); + gtk_tooltips_set_tip (tooltips, kill_menu, _("Tell the running XScreenSaver daemon to exit."), NULL); + + restart = gtk_menu_item_new_with_label (""); + tmp_key = gtk_label_parse_uline (GTK_LABEL (GTK_BIN (restart)->child), + _("_Restart Daemon")); + gtk_widget_add_accelerator (restart, "activate_item", file_menu_accels, + tmp_key, 0, 0); + gtk_widget_set_name (restart, "restart"); + gtk_widget_ref (restart); + gtk_object_set_data_full (GTK_OBJECT (xscreensaver_demo), "restart", restart, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (restart); + gtk_container_add (GTK_CONTAINER (file_menu), restart); + gtk_tooltips_set_tip (tooltips, restart, _("Kill and re-launch the XScreenSaver daemon."), NULL); + + separator1 = gtk_menu_item_new (); + gtk_widget_set_name (separator1, "separator1"); + gtk_widget_ref (separator1); + gtk_object_set_data_full (GTK_OBJECT (xscreensaver_demo), "separator1", separator1, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (separator1); + gtk_container_add (GTK_CONTAINER (file_menu), separator1); + gtk_widget_set_sensitive (separator1, FALSE); + + exit_menu = gtk_menu_item_new_with_label (""); + tmp_key = gtk_label_parse_uline (GTK_LABEL (GTK_BIN (exit_menu)->child), + _("_Exit")); + gtk_widget_add_accelerator (exit_menu, "activate_item", file_menu_accels, + tmp_key, 0, 0); + gtk_widget_set_name (exit_menu, "exit_menu"); + gtk_widget_ref (exit_menu); + gtk_object_set_data_full (GTK_OBJECT (xscreensaver_demo), "exit_menu", exit_menu, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (exit_menu); + gtk_container_add (GTK_CONTAINER (file_menu), exit_menu); + gtk_tooltips_set_tip (tooltips, exit_menu, _("Exit the xscreensaver-demo program (but leave the XScreenSaver daemon running in the background.)"), NULL); + + help = gtk_menu_item_new_with_label (""); + tmp_key = gtk_label_parse_uline (GTK_LABEL (GTK_BIN (help)->child), + _("_Help")); + gtk_widget_add_accelerator (help, "activate_item", accel_group, + tmp_key, GDK_MOD1_MASK, (GtkAccelFlags) 0); + gtk_widget_set_name (help, "help"); + gtk_widget_ref (help); + gtk_object_set_data_full (GTK_OBJECT (xscreensaver_demo), "help", help, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (help); + gtk_container_add (GTK_CONTAINER (menubar), help); + + help_menu = gtk_menu_new (); + gtk_widget_set_name (help_menu, "help_menu"); + gtk_widget_ref (help_menu); + gtk_object_set_data_full (GTK_OBJECT (xscreensaver_demo), "help_menu", help_menu, + (GtkDestroyNotify) gtk_widget_unref); + gtk_menu_item_set_submenu (GTK_MENU_ITEM (help), help_menu); + help_menu_accels = gtk_menu_ensure_uline_accel_group (GTK_MENU (help_menu)); + + about_menu = gtk_menu_item_new_with_label (""); + tmp_key = gtk_label_parse_uline (GTK_LABEL (GTK_BIN (about_menu)->child), + _("_About...")); + gtk_widget_add_accelerator (about_menu, "activate_item", help_menu_accels, + tmp_key, 0, 0); + gtk_widget_set_name (about_menu, "about_menu"); + gtk_widget_ref (about_menu); + gtk_object_set_data_full (GTK_OBJECT (xscreensaver_demo), "about_menu", about_menu, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (about_menu); + gtk_container_add (GTK_CONTAINER (help_menu), about_menu); + gtk_tooltips_set_tip (tooltips, about_menu, _("Display version information."), NULL); + + doc_menu = gtk_menu_item_new_with_label (""); + tmp_key = gtk_label_parse_uline (GTK_LABEL (GTK_BIN (doc_menu)->child), + _("_Documentation...")); + gtk_widget_add_accelerator (doc_menu, "activate_item", help_menu_accels, + tmp_key, 0, 0); + gtk_widget_set_name (doc_menu, "doc_menu"); + gtk_widget_ref (doc_menu); + gtk_object_set_data_full (GTK_OBJECT (xscreensaver_demo), "doc_menu", doc_menu, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (doc_menu); + gtk_container_add (GTK_CONTAINER (help_menu), doc_menu); + gtk_tooltips_set_tip (tooltips, doc_menu, _("Go to the documentation on the XScreenSaver web page."), NULL); + + notebook = gtk_notebook_new (); + gtk_widget_set_name (notebook, "notebook"); + gtk_widget_ref (notebook); + gtk_object_set_data_full (GTK_OBJECT (xscreensaver_demo), "notebook", notebook, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (notebook); + gtk_box_pack_start (GTK_BOX (outer_vbox), notebook, TRUE, TRUE, 0); + + demos_table = gtk_table_new (2, 2, FALSE); + gtk_widget_set_name (demos_table, "demos_table"); + gtk_widget_ref (demos_table); + gtk_object_set_data_full (GTK_OBJECT (xscreensaver_demo), "demos_table", demos_table, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (demos_table); + gtk_container_add (GTK_CONTAINER (notebook), demos_table); + gtk_container_set_border_width (GTK_CONTAINER (demos_table), 10); + + blanking_table = gtk_table_new (3, 4, FALSE); + gtk_widget_set_name (blanking_table, "blanking_table"); + gtk_widget_ref (blanking_table); + gtk_object_set_data_full (GTK_OBJECT (xscreensaver_demo), "blanking_table", blanking_table, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (blanking_table); + gtk_table_attach (GTK_TABLE (demos_table), blanking_table, 0, 1, 1, 2, + (GtkAttachOptions) (GTK_FILL), + (GtkAttachOptions) (GTK_FILL), 0, 0); + gtk_table_set_row_spacings (GTK_TABLE (blanking_table), 2); + + cycle_label = gtk_label_new (_("Cycle After")); + gtk_widget_set_name (cycle_label, "cycle_label"); + gtk_widget_ref (cycle_label); + gtk_object_set_data_full (GTK_OBJECT (xscreensaver_demo), "cycle_label", cycle_label, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (cycle_label); + gtk_table_attach (GTK_TABLE (blanking_table), cycle_label, 1, 2, 1, 2, + (GtkAttachOptions) (GTK_FILL), + (GtkAttachOptions) (0), 0, 0); + gtk_label_set_justify (GTK_LABEL (cycle_label), GTK_JUSTIFY_RIGHT); + gtk_misc_set_alignment (GTK_MISC (cycle_label), 1, 0.5); + gtk_misc_set_padding (GTK_MISC (cycle_label), 8, 0); + + lock_button_eventbox = gtk_event_box_new (); + gtk_widget_set_name (lock_button_eventbox, "lock_button_eventbox"); + gtk_widget_ref (lock_button_eventbox); + gtk_object_set_data_full (GTK_OBJECT (xscreensaver_demo), "lock_button_eventbox", lock_button_eventbox, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (lock_button_eventbox); + gtk_table_attach (GTK_TABLE (blanking_table), lock_button_eventbox, 0, 2, 2, 3, + (GtkAttachOptions) (GTK_FILL), + (GtkAttachOptions) (0), 0, 0); + gtk_tooltips_set_tip (tooltips, lock_button_eventbox, _("Whether a password should be required to un-blank the screen."), NULL); + + lock_button = gtk_check_button_new_with_label (_("Lock Screen After")); + gtk_widget_set_name (lock_button, "lock_button"); + gtk_widget_ref (lock_button); + gtk_object_set_data_full (GTK_OBJECT (xscreensaver_demo), "lock_button", lock_button, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (lock_button); + gtk_container_add (GTK_CONTAINER (lock_button_eventbox), lock_button); + + timeout_label = gtk_label_new (_("Blank After")); + gtk_widget_set_name (timeout_label, "timeout_label"); + gtk_widget_ref (timeout_label); + gtk_object_set_data_full (GTK_OBJECT (xscreensaver_demo), "timeout_label", timeout_label, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (timeout_label); + gtk_table_attach (GTK_TABLE (blanking_table), timeout_label, 1, 2, 0, 1, + (GtkAttachOptions) (GTK_FILL), + (GtkAttachOptions) (0), 0, 0); + gtk_label_set_justify (GTK_LABEL (timeout_label), GTK_JUSTIFY_RIGHT); + gtk_misc_set_alignment (GTK_MISC (timeout_label), 1, 0.5); + gtk_misc_set_padding (GTK_MISC (timeout_label), 8, 0); + + timeout_spinbutton_adj = gtk_adjustment_new (0, 1, 720, 1, 30, 30); + timeout_spinbutton = gtk_spin_button_new (GTK_ADJUSTMENT (timeout_spinbutton_adj), 15, 0); + gtk_widget_set_name (timeout_spinbutton, "timeout_spinbutton"); + gtk_widget_ref (timeout_spinbutton); + gtk_object_set_data_full (GTK_OBJECT (xscreensaver_demo), "timeout_spinbutton", timeout_spinbutton, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (timeout_spinbutton); + gtk_table_attach (GTK_TABLE (blanking_table), timeout_spinbutton, 2, 3, 0, 1, + (GtkAttachOptions) (GTK_FILL), + (GtkAttachOptions) (0), 0, 0); + gtk_tooltips_set_tip (tooltips, timeout_spinbutton, _("How long before the monitor goes completely black."), NULL); + gtk_spin_button_set_numeric (GTK_SPIN_BUTTON (timeout_spinbutton), TRUE); + gtk_spin_button_set_snap_to_ticks (GTK_SPIN_BUTTON (timeout_spinbutton), TRUE); + + timeout_mlabel = gtk_label_new (_("minutes")); + gtk_widget_set_name (timeout_mlabel, "timeout_mlabel"); + gtk_widget_ref (timeout_mlabel); + gtk_object_set_data_full (GTK_OBJECT (xscreensaver_demo), "timeout_mlabel", timeout_mlabel, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (timeout_mlabel); + gtk_table_attach (GTK_TABLE (blanking_table), timeout_mlabel, 3, 4, 0, 1, + (GtkAttachOptions) (GTK_EXPAND | GTK_FILL), + (GtkAttachOptions) (0), 0, 0); + gtk_label_set_justify (GTK_LABEL (timeout_mlabel), GTK_JUSTIFY_LEFT); + gtk_misc_set_alignment (GTK_MISC (timeout_mlabel), 0, 0.5); + + cycle_mlabel = gtk_label_new (_("minutes")); + gtk_widget_set_name (cycle_mlabel, "cycle_mlabel"); + gtk_widget_ref (cycle_mlabel); + gtk_object_set_data_full (GTK_OBJECT (xscreensaver_demo), "cycle_mlabel", cycle_mlabel, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (cycle_mlabel); + gtk_table_attach (GTK_TABLE (blanking_table), cycle_mlabel, 3, 4, 1, 2, + (GtkAttachOptions) (GTK_EXPAND | GTK_FILL), + (GtkAttachOptions) (0), 0, 0); + gtk_label_set_justify (GTK_LABEL (cycle_mlabel), GTK_JUSTIFY_LEFT); + gtk_misc_set_alignment (GTK_MISC (cycle_mlabel), 0, 0.5); + + lock_mlabel = gtk_label_new (_("minutes")); + gtk_widget_set_name (lock_mlabel, "lock_mlabel"); + gtk_widget_ref (lock_mlabel); + gtk_object_set_data_full (GTK_OBJECT (xscreensaver_demo), "lock_mlabel", lock_mlabel, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (lock_mlabel); + gtk_table_attach (GTK_TABLE (blanking_table), lock_mlabel, 3, 4, 2, 3, + (GtkAttachOptions) (GTK_EXPAND | GTK_FILL), + (GtkAttachOptions) (0), 0, 0); + gtk_label_set_justify (GTK_LABEL (lock_mlabel), GTK_JUSTIFY_LEFT); + gtk_misc_set_alignment (GTK_MISC (lock_mlabel), 0, 0.5); + + lock_spinbutton_adj = gtk_adjustment_new (0, 0, 720, 1, 30, 30); + lock_spinbutton = gtk_spin_button_new (GTK_ADJUSTMENT (lock_spinbutton_adj), 15, 0); + gtk_widget_set_name (lock_spinbutton, "lock_spinbutton"); + gtk_widget_ref (lock_spinbutton); + gtk_object_set_data_full (GTK_OBJECT (xscreensaver_demo), "lock_spinbutton", lock_spinbutton, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (lock_spinbutton); + gtk_table_attach (GTK_TABLE (blanking_table), lock_spinbutton, 2, 3, 2, 3, + (GtkAttachOptions) (GTK_FILL), + (GtkAttachOptions) (0), 0, 10); + gtk_tooltips_set_tip (tooltips, lock_spinbutton, _("How long before the monitor goes completely black."), NULL); + gtk_spin_button_set_numeric (GTK_SPIN_BUTTON (lock_spinbutton), TRUE); + gtk_spin_button_set_snap_to_ticks (GTK_SPIN_BUTTON (lock_spinbutton), TRUE); + + cycle_spinbutton_adj = gtk_adjustment_new (0, 1, 720, 1, 30, 30); + cycle_spinbutton = gtk_spin_button_new (GTK_ADJUSTMENT (cycle_spinbutton_adj), 15, 0); + gtk_widget_set_name (cycle_spinbutton, "cycle_spinbutton"); + gtk_widget_ref (cycle_spinbutton); + gtk_object_set_data_full (GTK_OBJECT (xscreensaver_demo), "cycle_spinbutton", cycle_spinbutton, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (cycle_spinbutton); + gtk_table_attach (GTK_TABLE (blanking_table), cycle_spinbutton, 2, 3, 1, 2, + (GtkAttachOptions) (GTK_FILL), + (GtkAttachOptions) (0), 0, 0); + gtk_tooltips_set_tip (tooltips, cycle_spinbutton, _("How long before the monitor goes completely black."), NULL); + gtk_spin_button_set_numeric (GTK_SPIN_BUTTON (cycle_spinbutton), TRUE); + gtk_spin_button_set_snap_to_ticks (GTK_SPIN_BUTTON (cycle_spinbutton), TRUE); + + demo_manual_hbbox = gtk_hbutton_box_new (); + gtk_widget_set_name (demo_manual_hbbox, "demo_manual_hbbox"); + gtk_widget_ref (demo_manual_hbbox); + gtk_object_set_data_full (GTK_OBJECT (xscreensaver_demo), "demo_manual_hbbox", demo_manual_hbbox, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (demo_manual_hbbox); + gtk_table_attach (GTK_TABLE (demos_table), demo_manual_hbbox, 1, 2, 1, 2, + (GtkAttachOptions) (GTK_FILL), + (GtkAttachOptions) (GTK_FILL), 0, 0); + gtk_button_box_set_layout (GTK_BUTTON_BOX (demo_manual_hbbox), GTK_BUTTONBOX_SPREAD); + + demo = gtk_button_new_with_label (_("Preview")); + gtk_widget_set_name (demo, "demo"); + gtk_widget_ref (demo); + gtk_object_set_data_full (GTK_OBJECT (xscreensaver_demo), "demo", demo, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (demo); + gtk_container_add (GTK_CONTAINER (demo_manual_hbbox), demo); + STFU GTK_WIDGET_SET_FLAGS (demo, GTK_CAN_DEFAULT); + gtk_tooltips_set_tip (tooltips, demo, _("Demo the selected screen saver in full-screen mode (click the mouse to return.)"), NULL); + + settings = gtk_button_new_with_label (_("Settings...")); + gtk_widget_set_name (settings, "settings"); + gtk_widget_ref (settings); + gtk_object_set_data_full (GTK_OBJECT (xscreensaver_demo), "settings", settings, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (settings); + gtk_container_add (GTK_CONTAINER (demo_manual_hbbox), settings); + STFU GTK_WIDGET_SET_FLAGS (settings, GTK_CAN_DEFAULT); + gtk_tooltips_set_tip (tooltips, settings, _("Customization and explanation of the selected screen saver."), NULL); + + list_vbox = gtk_vbox_new (FALSE, 0); + gtk_widget_set_name (list_vbox, "list_vbox"); + gtk_widget_ref (list_vbox); + gtk_object_set_data_full (GTK_OBJECT (xscreensaver_demo), "list_vbox", list_vbox, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (list_vbox); + gtk_table_attach (GTK_TABLE (demos_table), list_vbox, 0, 1, 0, 1, + (GtkAttachOptions) (GTK_FILL), + (GtkAttachOptions) (GTK_EXPAND | GTK_FILL), 0, 0); + gtk_container_set_border_width (GTK_CONTAINER (list_vbox), 10); + + mode_hbox = gtk_hbox_new (FALSE, 0); + gtk_widget_set_name (mode_hbox, "mode_hbox"); + gtk_widget_ref (mode_hbox); + gtk_object_set_data_full (GTK_OBJECT (xscreensaver_demo), "mode_hbox", mode_hbox, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (mode_hbox); + gtk_box_pack_start (GTK_BOX (list_vbox), mode_hbox, FALSE, TRUE, 10); + + mode_label = gtk_label_new (_("Mode:")); + gtk_widget_set_name (mode_label, "mode_label"); + gtk_widget_ref (mode_label); + gtk_object_set_data_full (GTK_OBJECT (xscreensaver_demo), "mode_label", mode_label, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (mode_label); + gtk_box_pack_start (GTK_BOX (mode_hbox), mode_label, FALSE, FALSE, 0); + gtk_label_set_justify (GTK_LABEL (mode_label), GTK_JUSTIFY_LEFT); + gtk_misc_set_alignment (GTK_MISC (mode_label), 0, 0.5); + + mode_menu = gtk_option_menu_new (); + gtk_widget_set_name (mode_menu, "mode_menu"); + gtk_widget_ref (mode_menu); + gtk_object_set_data_full (GTK_OBJECT (xscreensaver_demo), "mode_menu", mode_menu, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (mode_menu); + gtk_box_pack_start (GTK_BOX (mode_hbox), mode_menu, FALSE, FALSE, 4); + mode_menu_menu = gtk_menu_new (); + glade_menuitem = gtk_menu_item_new_with_label (_("Disable Screen Saver")); + gtk_widget_show (glade_menuitem); + gtk_menu_append (GTK_MENU (mode_menu_menu), glade_menuitem); + glade_menuitem = gtk_menu_item_new_with_label (_("Blank Screen Only")); + gtk_widget_show (glade_menuitem); + gtk_menu_append (GTK_MENU (mode_menu_menu), glade_menuitem); + glade_menuitem = gtk_menu_item_new_with_label (_("Only One Screen Saver")); + gtk_widget_show (glade_menuitem); + gtk_menu_append (GTK_MENU (mode_menu_menu), glade_menuitem); + glade_menuitem = gtk_menu_item_new_with_label (_("Random Screen Saver")); + gtk_widget_show (glade_menuitem); + gtk_menu_append (GTK_MENU (mode_menu_menu), glade_menuitem); + gtk_option_menu_set_menu (GTK_OPTION_MENU (mode_menu), mode_menu_menu); + gtk_option_menu_set_history (GTK_OPTION_MENU (mode_menu), 3); + + col_head_hbox = gtk_hbox_new (FALSE, 0); + gtk_widget_set_name (col_head_hbox, "col_head_hbox"); + gtk_widget_ref (col_head_hbox); + gtk_object_set_data_full (GTK_OBJECT (xscreensaver_demo), "col_head_hbox", col_head_hbox, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (col_head_hbox); + gtk_box_pack_start (GTK_BOX (list_vbox), col_head_hbox, FALSE, TRUE, 0); + + use_col_frame = gtk_frame_new (NULL); + gtk_widget_set_name (use_col_frame, "use_col_frame"); + gtk_widget_ref (use_col_frame); + gtk_object_set_data_full (GTK_OBJECT (xscreensaver_demo), "use_col_frame", use_col_frame, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (use_col_frame); + gtk_box_pack_start (GTK_BOX (col_head_hbox), use_col_frame, FALSE, FALSE, 0); + gtk_frame_set_shadow_type (GTK_FRAME (use_col_frame), GTK_SHADOW_OUT); + + use_label = gtk_label_new (_("Use")); + gtk_widget_set_name (use_label, "use_label"); + gtk_widget_ref (use_label); + gtk_object_set_data_full (GTK_OBJECT (xscreensaver_demo), "use_label", use_label, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (use_label); + gtk_container_add (GTK_CONTAINER (use_col_frame), use_label); + gtk_label_set_justify (GTK_LABEL (use_label), GTK_JUSTIFY_LEFT); + gtk_misc_set_alignment (GTK_MISC (use_label), 0, 0.5); + gtk_misc_set_padding (GTK_MISC (use_label), 3, 0); + + saver_col_frame = gtk_frame_new (NULL); + gtk_widget_set_name (saver_col_frame, "saver_col_frame"); + gtk_widget_ref (saver_col_frame); + gtk_object_set_data_full (GTK_OBJECT (xscreensaver_demo), "saver_col_frame", saver_col_frame, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (saver_col_frame); + gtk_box_pack_start (GTK_BOX (col_head_hbox), saver_col_frame, TRUE, TRUE, 0); + gtk_frame_set_shadow_type (GTK_FRAME (saver_col_frame), GTK_SHADOW_OUT); + + saver_label = gtk_label_new (_("Screen Saver")); + gtk_widget_set_name (saver_label, "saver_label"); + gtk_widget_ref (saver_label); + gtk_object_set_data_full (GTK_OBJECT (xscreensaver_demo), "saver_label", saver_label, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (saver_label); + gtk_container_add (GTK_CONTAINER (saver_col_frame), saver_label); + gtk_label_set_justify (GTK_LABEL (saver_label), GTK_JUSTIFY_LEFT); + gtk_misc_set_alignment (GTK_MISC (saver_label), 0, 0.5); + gtk_misc_set_padding (GTK_MISC (saver_label), 6, 0); + + scroller = gtk_scrolled_window_new (NULL, NULL); + gtk_widget_set_name (scroller, "scroller"); + gtk_widget_ref (scroller); + gtk_object_set_data_full (GTK_OBJECT (xscreensaver_demo), "scroller", scroller, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (scroller); + gtk_box_pack_start (GTK_BOX (list_vbox), scroller, TRUE, TRUE, 0); + gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scroller), GTK_POLICY_NEVER, GTK_POLICY_ALWAYS); + + viewport = gtk_viewport_new (NULL, NULL); + gtk_widget_set_name (viewport, "viewport"); + gtk_widget_ref (viewport); + gtk_object_set_data_full (GTK_OBJECT (xscreensaver_demo), "viewport", viewport, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (viewport); + gtk_container_add (GTK_CONTAINER (scroller), viewport); + gtk_container_set_border_width (GTK_CONTAINER (viewport), 1); + + list = gtk_list_new (); + gtk_widget_set_name (list, "list"); + gtk_widget_ref (list); + gtk_object_set_data_full (GTK_OBJECT (xscreensaver_demo), "list", list, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (list); + gtk_container_add (GTK_CONTAINER (viewport), list); + + centering_hbox = gtk_hbox_new (TRUE, 0); + gtk_widget_set_name (centering_hbox, "centering_hbox"); + gtk_widget_ref (centering_hbox); + gtk_object_set_data_full (GTK_OBJECT (xscreensaver_demo), "centering_hbox", centering_hbox, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (centering_hbox); + gtk_box_pack_end (GTK_BOX (list_vbox), centering_hbox, FALSE, TRUE, 0); + + next_prev_hbox = gtk_hbox_new (FALSE, 0); + gtk_widget_set_name (next_prev_hbox, "next_prev_hbox"); + gtk_widget_ref (next_prev_hbox); + gtk_object_set_data_full (GTK_OBJECT (xscreensaver_demo), "next_prev_hbox", next_prev_hbox, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (next_prev_hbox); + gtk_box_pack_start (GTK_BOX (centering_hbox), next_prev_hbox, FALSE, FALSE, 0); + + next = gtk_button_new_with_label (_("\\/")); + gtk_widget_set_name (next, "next"); + gtk_widget_ref (next); + gtk_object_set_data_full (GTK_OBJECT (xscreensaver_demo), "next", next, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (next); + gtk_box_pack_start (GTK_BOX (next_prev_hbox), next, FALSE, FALSE, 0); + STFU GTK_WIDGET_SET_FLAGS (next, GTK_CAN_DEFAULT); + gtk_tooltips_set_tip (tooltips, next, _("Run the next screen saver in the list in full-screen mode (click the mouse to return.)"), NULL); + + prev = gtk_button_new_with_label (_("/\\")); + gtk_widget_set_name (prev, "prev"); + gtk_widget_ref (prev); + gtk_object_set_data_full (GTK_OBJECT (xscreensaver_demo), "prev", prev, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (prev); + gtk_box_pack_start (GTK_BOX (next_prev_hbox), prev, FALSE, FALSE, 0); + STFU GTK_WIDGET_SET_FLAGS (prev, GTK_CAN_DEFAULT); + gtk_tooltips_set_tip (tooltips, prev, _("Run the previous screen saver in the list in full-screen mode (click the mouse to return.)"), NULL); + + preview_frame = gtk_frame_new (_("Description")); + gtk_widget_set_name (preview_frame, "preview_frame"); + gtk_widget_ref (preview_frame); + gtk_object_set_data_full (GTK_OBJECT (xscreensaver_demo), "preview_frame", preview_frame, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (preview_frame); + gtk_table_attach (GTK_TABLE (demos_table), preview_frame, 1, 2, 0, 1, + (GtkAttachOptions) (GTK_EXPAND | GTK_SHRINK | GTK_FILL), + (GtkAttachOptions) (GTK_EXPAND | GTK_SHRINK | GTK_FILL), 0, 6); + + preview_aspectframe = gtk_aspect_frame_new (NULL, 0.5, 0.5, 1.33, FALSE); + gtk_widget_set_name (preview_aspectframe, "preview_aspectframe"); + gtk_widget_ref (preview_aspectframe); + gtk_object_set_data_full (GTK_OBJECT (xscreensaver_demo), "preview_aspectframe", preview_aspectframe, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (preview_aspectframe); + gtk_container_add (GTK_CONTAINER (preview_frame), preview_aspectframe); + gtk_container_set_border_width (GTK_CONTAINER (preview_aspectframe), 8); + + preview = gtk_drawing_area_new (); + gtk_widget_set_name (preview, "preview"); + gtk_widget_ref (preview); + gtk_object_set_data_full (GTK_OBJECT (xscreensaver_demo), "preview", preview, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (preview); + gtk_container_add (GTK_CONTAINER (preview_aspectframe), preview); + + demo_tab = gtk_label_new (_("Display Modes")); + gtk_widget_set_name (demo_tab, "demo_tab"); + gtk_widget_ref (demo_tab); + gtk_object_set_data_full (GTK_OBJECT (xscreensaver_demo), "demo_tab", demo_tab, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (demo_tab); + gtk_notebook_set_tab_label (GTK_NOTEBOOK (notebook), gtk_notebook_get_nth_page (GTK_NOTEBOOK (notebook), 0), demo_tab); + + options_table = gtk_table_new (2, 2, TRUE); + gtk_widget_set_name (options_table, "options_table"); + gtk_widget_ref (options_table); + gtk_object_set_data_full (GTK_OBJECT (xscreensaver_demo), "options_table", options_table, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (options_table); + gtk_container_add (GTK_CONTAINER (notebook), options_table); + + diag_frame = gtk_frame_new (_("Diagnostics")); + gtk_widget_set_name (diag_frame, "diag_frame"); + gtk_widget_ref (diag_frame); + gtk_object_set_data_full (GTK_OBJECT (xscreensaver_demo), "diag_frame", diag_frame, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (diag_frame); + gtk_table_attach (GTK_TABLE (options_table), diag_frame, 0, 1, 1, 2, + (GtkAttachOptions) (GTK_EXPAND | GTK_FILL), + (GtkAttachOptions) (GTK_EXPAND | GTK_FILL), 0, 0); + gtk_container_set_border_width (GTK_CONTAINER (diag_frame), 10); + + diag_hbox = gtk_hbox_new (FALSE, 8); + gtk_widget_set_name (diag_hbox, "diag_hbox"); + gtk_widget_ref (diag_hbox); + gtk_object_set_data_full (GTK_OBJECT (xscreensaver_demo), "diag_hbox", diag_hbox, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (diag_hbox); + gtk_container_add (GTK_CONTAINER (diag_frame), diag_hbox); + gtk_container_set_border_width (GTK_CONTAINER (diag_hbox), 8); + + diag_logo = create_pixmap (xscreensaver_demo, "screensaver-diagnostic.png"); + gtk_widget_set_name (diag_logo, "diag_logo"); + gtk_widget_ref (diag_logo); + gtk_object_set_data_full (GTK_OBJECT (xscreensaver_demo), "diag_logo", diag_logo, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (diag_logo); + gtk_box_pack_start (GTK_BOX (diag_hbox), diag_logo, FALSE, FALSE, 0); + gtk_misc_set_alignment (GTK_MISC (diag_logo), 0.5, 0); + + diag_vbox = gtk_vbox_new (FALSE, 0); + gtk_widget_set_name (diag_vbox, "diag_vbox"); + gtk_widget_ref (diag_vbox); + gtk_object_set_data_full (GTK_OBJECT (xscreensaver_demo), "diag_vbox", diag_vbox, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (diag_vbox); + gtk_box_pack_start (GTK_BOX (diag_hbox), diag_vbox, TRUE, TRUE, 0); + + verbose_button_eventbox = gtk_event_box_new (); + gtk_widget_set_name (verbose_button_eventbox, "verbose_button_eventbox"); + gtk_widget_ref (verbose_button_eventbox); + gtk_object_set_data_full (GTK_OBJECT (xscreensaver_demo), "verbose_button_eventbox", verbose_button_eventbox, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (verbose_button_eventbox); + gtk_box_pack_start (GTK_BOX (diag_vbox), verbose_button_eventbox, FALSE, FALSE, 0); + gtk_tooltips_set_tip (tooltips, verbose_button_eventbox, _("Whether the daemon should print lots of debugging information."), NULL); + + verbose_button = gtk_check_button_new_with_label (_("Verbose Diagnostics")); + gtk_widget_set_name (verbose_button, "verbose_button"); + gtk_widget_ref (verbose_button); + gtk_object_set_data_full (GTK_OBJECT (xscreensaver_demo), "verbose_button", verbose_button, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (verbose_button); + gtk_container_add (GTK_CONTAINER (verbose_button_eventbox), verbose_button); + + capture_button_eventbox = gtk_event_box_new (); + gtk_widget_set_name (capture_button_eventbox, "capture_button_eventbox"); + gtk_widget_ref (capture_button_eventbox); + gtk_object_set_data_full (GTK_OBJECT (xscreensaver_demo), "capture_button_eventbox", capture_button_eventbox, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (capture_button_eventbox); + gtk_box_pack_start (GTK_BOX (diag_vbox), capture_button_eventbox, FALSE, FALSE, 0); + gtk_tooltips_set_tip (tooltips, capture_button_eventbox, _("Whether any error output of the display modes should be redirected to the screen."), NULL); + + capture_button = gtk_check_button_new_with_label (_("Display Subprocess Errors")); + gtk_widget_set_name (capture_button, "capture_button"); + gtk_widget_ref (capture_button); + gtk_object_set_data_full (GTK_OBJECT (xscreensaver_demo), "capture_button", capture_button, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (capture_button); + gtk_container_add (GTK_CONTAINER (capture_button_eventbox), capture_button); + + splash_button_eventbox = gtk_event_box_new (); + gtk_widget_set_name (splash_button_eventbox, "splash_button_eventbox"); + gtk_widget_ref (splash_button_eventbox); + gtk_object_set_data_full (GTK_OBJECT (xscreensaver_demo), "splash_button_eventbox", splash_button_eventbox, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (splash_button_eventbox); + gtk_box_pack_start (GTK_BOX (diag_vbox), splash_button_eventbox, FALSE, FALSE, 0); + gtk_tooltips_set_tip (tooltips, splash_button_eventbox, _("Whether the splash screen (with the version number and `Help' button) should be momentarily displayed when the daemon first starts up."), NULL); + + splash_button = gtk_check_button_new_with_label (_("Display Splash Screen at Startup")); + gtk_widget_set_name (splash_button, "splash_button"); + gtk_widget_ref (splash_button); + gtk_object_set_data_full (GTK_OBJECT (xscreensaver_demo), "splash_button", splash_button, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (splash_button); + gtk_container_add (GTK_CONTAINER (splash_button_eventbox), splash_button); + gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (splash_button), TRUE); + + cmap_frame = gtk_frame_new (_("Colormaps")); + gtk_widget_set_name (cmap_frame, "cmap_frame"); + gtk_widget_ref (cmap_frame); + gtk_object_set_data_full (GTK_OBJECT (xscreensaver_demo), "cmap_frame", cmap_frame, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (cmap_frame); + gtk_table_attach (GTK_TABLE (options_table), cmap_frame, 1, 2, 1, 2, + (GtkAttachOptions) (GTK_EXPAND | GTK_FILL), + (GtkAttachOptions) (GTK_FILL), 0, 0); + gtk_container_set_border_width (GTK_CONTAINER (cmap_frame), 10); + + cmap_hbox = gtk_hbox_new (FALSE, 8); + gtk_widget_set_name (cmap_hbox, "cmap_hbox"); + gtk_widget_ref (cmap_hbox); + gtk_object_set_data_full (GTK_OBJECT (xscreensaver_demo), "cmap_hbox", cmap_hbox, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (cmap_hbox); + gtk_container_add (GTK_CONTAINER (cmap_frame), cmap_hbox); + gtk_container_set_border_width (GTK_CONTAINER (cmap_hbox), 8); + + cmap_logo = create_pixmap (xscreensaver_demo, "screensaver-colorselector.png"); + gtk_widget_set_name (cmap_logo, "cmap_logo"); + gtk_widget_ref (cmap_logo); + gtk_object_set_data_full (GTK_OBJECT (xscreensaver_demo), "cmap_logo", cmap_logo, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (cmap_logo); + gtk_box_pack_start (GTK_BOX (cmap_hbox), cmap_logo, FALSE, FALSE, 0); + gtk_misc_set_alignment (GTK_MISC (cmap_logo), 0.5, 0); + + cmap_vbox = gtk_vbox_new (FALSE, 0); + gtk_widget_set_name (cmap_vbox, "cmap_vbox"); + gtk_widget_ref (cmap_vbox); + gtk_object_set_data_full (GTK_OBJECT (xscreensaver_demo), "cmap_vbox", cmap_vbox, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (cmap_vbox); + gtk_box_pack_start (GTK_BOX (cmap_hbox), cmap_vbox, TRUE, TRUE, 0); + + install_button_eventbox = gtk_event_box_new (); + gtk_widget_set_name (install_button_eventbox, "install_button_eventbox"); + gtk_widget_ref (install_button_eventbox); + gtk_object_set_data_full (GTK_OBJECT (xscreensaver_demo), "install_button_eventbox", install_button_eventbox, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (install_button_eventbox); + gtk_box_pack_start (GTK_BOX (cmap_vbox), install_button_eventbox, FALSE, FALSE, 0); + gtk_tooltips_set_tip (tooltips, install_button_eventbox, _("Whether to install a private colormap when running in 8-bit mode on the default Visual."), NULL); + + install_button = gtk_check_button_new_with_label (_("Install Colormap")); + gtk_widget_set_name (install_button, "install_button"); + gtk_widget_ref (install_button); + gtk_object_set_data_full (GTK_OBJECT (xscreensaver_demo), "install_button", install_button, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (install_button); + gtk_container_add (GTK_CONTAINER (install_button_eventbox), install_button); + + cmap_hr = gtk_hseparator_new (); + gtk_widget_set_name (cmap_hr, "cmap_hr"); + gtk_widget_ref (cmap_hr); + gtk_object_set_data_full (GTK_OBJECT (xscreensaver_demo), "cmap_hr", cmap_hr, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (cmap_hr); + gtk_box_pack_start (GTK_BOX (cmap_vbox), cmap_hr, FALSE, FALSE, 4); + + fade_button_eventbox = gtk_event_box_new (); + gtk_widget_set_name (fade_button_eventbox, "fade_button_eventbox"); + gtk_widget_ref (fade_button_eventbox); + gtk_object_set_data_full (GTK_OBJECT (xscreensaver_demo), "fade_button_eventbox", fade_button_eventbox, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (fade_button_eventbox); + gtk_box_pack_start (GTK_BOX (cmap_vbox), fade_button_eventbox, FALSE, FALSE, 0); + gtk_tooltips_set_tip (tooltips, fade_button_eventbox, _("Whether the screen should slowly fade to black when the screen saver activates."), NULL); + + fade_button = gtk_check_button_new_with_label (_("Fade To Black When Blanking")); + gtk_widget_set_name (fade_button, "fade_button"); + gtk_widget_ref (fade_button); + gtk_object_set_data_full (GTK_OBJECT (xscreensaver_demo), "fade_button", fade_button, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (fade_button); + gtk_container_add (GTK_CONTAINER (fade_button_eventbox), fade_button); + + unfade_button_eventbox = gtk_event_box_new (); + gtk_widget_set_name (unfade_button_eventbox, "unfade_button_eventbox"); + gtk_widget_ref (unfade_button_eventbox); + gtk_object_set_data_full (GTK_OBJECT (xscreensaver_demo), "unfade_button_eventbox", unfade_button_eventbox, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (unfade_button_eventbox); + gtk_box_pack_start (GTK_BOX (cmap_vbox), unfade_button_eventbox, FALSE, FALSE, 0); + gtk_tooltips_set_tip (tooltips, unfade_button_eventbox, _("Whether the screen should slowly fade in from black when the screen saver deactivates."), NULL); + + unfade_button = gtk_check_button_new_with_label (_("Fade From Black When Unblanking")); + gtk_widget_set_name (unfade_button, "unfade_button"); + gtk_widget_ref (unfade_button); + gtk_object_set_data_full (GTK_OBJECT (xscreensaver_demo), "unfade_button", unfade_button, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (unfade_button); + gtk_container_add (GTK_CONTAINER (unfade_button_eventbox), unfade_button); + + fade_hbox = gtk_hbox_new (FALSE, 0); + gtk_widget_set_name (fade_hbox, "fade_hbox"); + gtk_widget_ref (fade_hbox); + gtk_object_set_data_full (GTK_OBJECT (xscreensaver_demo), "fade_hbox", fade_hbox, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (fade_hbox); + gtk_box_pack_start (GTK_BOX (cmap_vbox), fade_hbox, FALSE, FALSE, 0); + + fade_dummy = gtk_label_new (""); + gtk_widget_set_name (fade_dummy, "fade_dummy"); + gtk_widget_ref (fade_dummy); + gtk_object_set_data_full (GTK_OBJECT (xscreensaver_demo), "fade_dummy", fade_dummy, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (fade_dummy); + gtk_box_pack_start (GTK_BOX (fade_hbox), fade_dummy, FALSE, FALSE, 0); + gtk_label_set_justify (GTK_LABEL (fade_dummy), GTK_JUSTIFY_LEFT); + gtk_misc_set_padding (GTK_MISC (fade_dummy), 3, 0); + + fade_label = gtk_label_new (_("Fade Duration")); + gtk_widget_set_name (fade_label, "fade_label"); + gtk_widget_ref (fade_label); + gtk_object_set_data_full (GTK_OBJECT (xscreensaver_demo), "fade_label", fade_label, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (fade_label); + gtk_box_pack_start (GTK_BOX (fade_hbox), fade_label, FALSE, FALSE, 10); + gtk_label_set_justify (GTK_LABEL (fade_label), GTK_JUSTIFY_LEFT); + gtk_misc_set_alignment (GTK_MISC (fade_label), 0, 0.5); + + fade_spinbutton_adj = gtk_adjustment_new (0, 0, 10, 1, 1, 1); + fade_spinbutton = gtk_spin_button_new (GTK_ADJUSTMENT (fade_spinbutton_adj), 1, 0); + gtk_widget_set_name (fade_spinbutton, "fade_spinbutton"); + gtk_widget_ref (fade_spinbutton); + gtk_object_set_data_full (GTK_OBJECT (xscreensaver_demo), "fade_spinbutton", fade_spinbutton, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (fade_spinbutton); + gtk_box_pack_start (GTK_BOX (fade_hbox), fade_spinbutton, FALSE, FALSE, 0); + gtk_tooltips_set_tip (tooltips, fade_spinbutton, _("How long it should take for the screen to fade in and out."), NULL); + gtk_spin_button_set_numeric (GTK_SPIN_BUTTON (fade_spinbutton), TRUE); + gtk_spin_button_set_snap_to_ticks (GTK_SPIN_BUTTON (fade_spinbutton), TRUE); + + fade_sec_label = gtk_label_new (_("seconds")); + gtk_widget_set_name (fade_sec_label, "fade_sec_label"); + gtk_widget_ref (fade_sec_label); + gtk_object_set_data_full (GTK_OBJECT (xscreensaver_demo), "fade_sec_label", fade_sec_label, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (fade_sec_label); + gtk_box_pack_start (GTK_BOX (fade_hbox), fade_sec_label, FALSE, FALSE, 0); + gtk_label_set_justify (GTK_LABEL (fade_sec_label), GTK_JUSTIFY_LEFT); + gtk_misc_set_alignment (GTK_MISC (fade_sec_label), 0, 0.5); + + dpms_frame = gtk_frame_new (_("Display Power Management")); + gtk_widget_set_name (dpms_frame, "dpms_frame"); + gtk_widget_ref (dpms_frame); + gtk_object_set_data_full (GTK_OBJECT (xscreensaver_demo), "dpms_frame", dpms_frame, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (dpms_frame); + gtk_table_attach (GTK_TABLE (options_table), dpms_frame, 1, 2, 0, 1, + (GtkAttachOptions) (GTK_EXPAND | GTK_FILL), + (GtkAttachOptions) (GTK_FILL), 0, 0); + gtk_container_set_border_width (GTK_CONTAINER (dpms_frame), 10); + + dpms_hbox = gtk_hbox_new (FALSE, 8); + gtk_widget_set_name (dpms_hbox, "dpms_hbox"); + gtk_widget_ref (dpms_hbox); + gtk_object_set_data_full (GTK_OBJECT (xscreensaver_demo), "dpms_hbox", dpms_hbox, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (dpms_hbox); + gtk_container_add (GTK_CONTAINER (dpms_frame), dpms_hbox); + gtk_container_set_border_width (GTK_CONTAINER (dpms_hbox), 8); + + dpms_logo = create_pixmap (xscreensaver_demo, "screensaver-power.png"); + gtk_widget_set_name (dpms_logo, "dpms_logo"); + gtk_widget_ref (dpms_logo); + gtk_object_set_data_full (GTK_OBJECT (xscreensaver_demo), "dpms_logo", dpms_logo, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (dpms_logo); + gtk_box_pack_start (GTK_BOX (dpms_hbox), dpms_logo, FALSE, FALSE, 0); + gtk_misc_set_alignment (GTK_MISC (dpms_logo), 0.5, 0); + + dpms_vbox = gtk_vbox_new (FALSE, 0); + gtk_widget_set_name (dpms_vbox, "dpms_vbox"); + gtk_widget_ref (dpms_vbox); + gtk_object_set_data_full (GTK_OBJECT (xscreensaver_demo), "dpms_vbox", dpms_vbox, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (dpms_vbox); + gtk_box_pack_start (GTK_BOX (dpms_hbox), dpms_vbox, FALSE, FALSE, 0); + + dpms_button_eventbox = gtk_event_box_new (); + gtk_widget_set_name (dpms_button_eventbox, "dpms_button_eventbox"); + gtk_widget_ref (dpms_button_eventbox); + gtk_object_set_data_full (GTK_OBJECT (xscreensaver_demo), "dpms_button_eventbox", dpms_button_eventbox, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (dpms_button_eventbox); + gtk_box_pack_start (GTK_BOX (dpms_vbox), dpms_button_eventbox, FALSE, FALSE, 0); + gtk_tooltips_set_tip (tooltips, dpms_button_eventbox, _("Whether the monitor should be powered down after a while."), NULL); + + dpms_button = gtk_check_button_new_with_label (_("Power Management Enabled")); + gtk_widget_set_name (dpms_button, "dpms_button"); + gtk_widget_ref (dpms_button); + gtk_object_set_data_full (GTK_OBJECT (xscreensaver_demo), "dpms_button", dpms_button, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (dpms_button); + gtk_container_add (GTK_CONTAINER (dpms_button_eventbox), dpms_button); + gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (dpms_button), TRUE); + + dpms_table = gtk_table_new (3, 3, FALSE); + gtk_widget_set_name (dpms_table, "dpms_table"); + gtk_widget_ref (dpms_table); + gtk_object_set_data_full (GTK_OBJECT (xscreensaver_demo), "dpms_table", dpms_table, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (dpms_table); + gtk_box_pack_start (GTK_BOX (dpms_vbox), dpms_table, FALSE, FALSE, 0); + gtk_table_set_row_spacings (GTK_TABLE (dpms_table), 2); + + dpms_standby_spinbutton_adj = gtk_adjustment_new (0, 0, 1440, 1, 30, 30); + dpms_standby_spinbutton = gtk_spin_button_new (GTK_ADJUSTMENT (dpms_standby_spinbutton_adj), 15, 0); + gtk_widget_set_name (dpms_standby_spinbutton, "dpms_standby_spinbutton"); + gtk_widget_ref (dpms_standby_spinbutton); + gtk_object_set_data_full (GTK_OBJECT (xscreensaver_demo), "dpms_standby_spinbutton", dpms_standby_spinbutton, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (dpms_standby_spinbutton); + gtk_table_attach (GTK_TABLE (dpms_table), dpms_standby_spinbutton, 1, 2, 0, 1, + (GtkAttachOptions) (GTK_FILL), + (GtkAttachOptions) (0), 0, 0); + gtk_tooltips_set_tip (tooltips, dpms_standby_spinbutton, _("How long before the monitor goes completely black."), NULL); + gtk_spin_button_set_numeric (GTK_SPIN_BUTTON (dpms_standby_spinbutton), TRUE); + gtk_spin_button_set_snap_to_ticks (GTK_SPIN_BUTTON (dpms_standby_spinbutton), TRUE); + + dpms_standby_mlabel = gtk_label_new (_("minutes")); + gtk_widget_set_name (dpms_standby_mlabel, "dpms_standby_mlabel"); + gtk_widget_ref (dpms_standby_mlabel); + gtk_object_set_data_full (GTK_OBJECT (xscreensaver_demo), "dpms_standby_mlabel", dpms_standby_mlabel, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (dpms_standby_mlabel); + gtk_table_attach (GTK_TABLE (dpms_table), dpms_standby_mlabel, 2, 3, 0, 1, + (GtkAttachOptions) (GTK_EXPAND | GTK_FILL), + (GtkAttachOptions) (0), 0, 0); + gtk_label_set_justify (GTK_LABEL (dpms_standby_mlabel), GTK_JUSTIFY_LEFT); + gtk_misc_set_alignment (GTK_MISC (dpms_standby_mlabel), 0, 0.5); + + dpms_suspend_mlabel = gtk_label_new (_("minutes")); + gtk_widget_set_name (dpms_suspend_mlabel, "dpms_suspend_mlabel"); + gtk_widget_ref (dpms_suspend_mlabel); + gtk_object_set_data_full (GTK_OBJECT (xscreensaver_demo), "dpms_suspend_mlabel", dpms_suspend_mlabel, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (dpms_suspend_mlabel); + gtk_table_attach (GTK_TABLE (dpms_table), dpms_suspend_mlabel, 2, 3, 1, 2, + (GtkAttachOptions) (GTK_EXPAND | GTK_FILL), + (GtkAttachOptions) (0), 0, 0); + gtk_label_set_justify (GTK_LABEL (dpms_suspend_mlabel), GTK_JUSTIFY_LEFT); + gtk_misc_set_alignment (GTK_MISC (dpms_suspend_mlabel), 0, 0.5); + + dpms_off_mlabel = gtk_label_new (_("minutes")); + gtk_widget_set_name (dpms_off_mlabel, "dpms_off_mlabel"); + gtk_widget_ref (dpms_off_mlabel); + gtk_object_set_data_full (GTK_OBJECT (xscreensaver_demo), "dpms_off_mlabel", dpms_off_mlabel, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (dpms_off_mlabel); + gtk_table_attach (GTK_TABLE (dpms_table), dpms_off_mlabel, 2, 3, 2, 3, + (GtkAttachOptions) (GTK_EXPAND | GTK_FILL), + (GtkAttachOptions) (0), 0, 0); + gtk_label_set_justify (GTK_LABEL (dpms_off_mlabel), GTK_JUSTIFY_LEFT); + gtk_misc_set_alignment (GTK_MISC (dpms_off_mlabel), 0, 0.5); + + dpms_off_label = gtk_label_new (_("Off After")); + gtk_widget_set_name (dpms_off_label, "dpms_off_label"); + gtk_widget_ref (dpms_off_label); + gtk_object_set_data_full (GTK_OBJECT (xscreensaver_demo), "dpms_off_label", dpms_off_label, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (dpms_off_label); + gtk_table_attach (GTK_TABLE (dpms_table), dpms_off_label, 0, 1, 2, 3, + (GtkAttachOptions) (GTK_FILL), + (GtkAttachOptions) (0), 0, 0); + gtk_label_set_justify (GTK_LABEL (dpms_off_label), GTK_JUSTIFY_RIGHT); + gtk_misc_set_alignment (GTK_MISC (dpms_off_label), 1, 0.5); + gtk_misc_set_padding (GTK_MISC (dpms_off_label), 10, 0); + + dpms_suspend_label = gtk_label_new (_("Suspend After")); + gtk_widget_set_name (dpms_suspend_label, "dpms_suspend_label"); + gtk_widget_ref (dpms_suspend_label); + gtk_object_set_data_full (GTK_OBJECT (xscreensaver_demo), "dpms_suspend_label", dpms_suspend_label, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (dpms_suspend_label); + gtk_table_attach (GTK_TABLE (dpms_table), dpms_suspend_label, 0, 1, 1, 2, + (GtkAttachOptions) (GTK_FILL), + (GtkAttachOptions) (0), 0, 0); + gtk_label_set_justify (GTK_LABEL (dpms_suspend_label), GTK_JUSTIFY_RIGHT); + gtk_misc_set_alignment (GTK_MISC (dpms_suspend_label), 1, 0.5); + gtk_misc_set_padding (GTK_MISC (dpms_suspend_label), 10, 0); + + dpms_standby_label = gtk_label_new (_("Standby After")); + gtk_widget_set_name (dpms_standby_label, "dpms_standby_label"); + gtk_widget_ref (dpms_standby_label); + gtk_object_set_data_full (GTK_OBJECT (xscreensaver_demo), "dpms_standby_label", dpms_standby_label, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (dpms_standby_label); + gtk_table_attach (GTK_TABLE (dpms_table), dpms_standby_label, 0, 1, 0, 1, + (GtkAttachOptions) (GTK_FILL), + (GtkAttachOptions) (0), 0, 0); + gtk_label_set_justify (GTK_LABEL (dpms_standby_label), GTK_JUSTIFY_RIGHT); + gtk_misc_set_alignment (GTK_MISC (dpms_standby_label), 1, 0.5); + gtk_misc_set_padding (GTK_MISC (dpms_standby_label), 10, 0); + + dpms_suspend_spinbutton_adj = gtk_adjustment_new (0, 0, 1440, 1, 30, 30); + dpms_suspend_spinbutton = gtk_spin_button_new (GTK_ADJUSTMENT (dpms_suspend_spinbutton_adj), 15, 0); + gtk_widget_set_name (dpms_suspend_spinbutton, "dpms_suspend_spinbutton"); + gtk_widget_ref (dpms_suspend_spinbutton); + gtk_object_set_data_full (GTK_OBJECT (xscreensaver_demo), "dpms_suspend_spinbutton", dpms_suspend_spinbutton, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (dpms_suspend_spinbutton); + gtk_table_attach (GTK_TABLE (dpms_table), dpms_suspend_spinbutton, 1, 2, 1, 2, + (GtkAttachOptions) (GTK_EXPAND | GTK_FILL), + (GtkAttachOptions) (0), 0, 0); + gtk_tooltips_set_tip (tooltips, dpms_suspend_spinbutton, _("How long until the monitor goes into power-saving mode."), NULL); + gtk_spin_button_set_numeric (GTK_SPIN_BUTTON (dpms_suspend_spinbutton), TRUE); + gtk_spin_button_set_snap_to_ticks (GTK_SPIN_BUTTON (dpms_suspend_spinbutton), TRUE); + + dpms_off_spinbutton_adj = gtk_adjustment_new (0, 0, 1440, 1, 30, 30); + dpms_off_spinbutton = gtk_spin_button_new (GTK_ADJUSTMENT (dpms_off_spinbutton_adj), 15, 0); + gtk_widget_set_name (dpms_off_spinbutton, "dpms_off_spinbutton"); + gtk_widget_ref (dpms_off_spinbutton); + gtk_object_set_data_full (GTK_OBJECT (xscreensaver_demo), "dpms_off_spinbutton", dpms_off_spinbutton, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (dpms_off_spinbutton); + gtk_table_attach (GTK_TABLE (dpms_table), dpms_off_spinbutton, 1, 2, 2, 3, + (GtkAttachOptions) (GTK_EXPAND | GTK_FILL), + (GtkAttachOptions) (0), 0, 0); + gtk_tooltips_set_tip (tooltips, dpms_off_spinbutton, _("How long until the monitor powers down."), NULL); + gtk_spin_button_set_numeric (GTK_SPIN_BUTTON (dpms_off_spinbutton), TRUE); + gtk_spin_button_set_snap_to_ticks (GTK_SPIN_BUTTON (dpms_off_spinbutton), TRUE); + + grab_frame = gtk_frame_new (_("Image Manipulation")); + gtk_widget_set_name (grab_frame, "grab_frame"); + gtk_widget_ref (grab_frame); + gtk_object_set_data_full (GTK_OBJECT (xscreensaver_demo), "grab_frame", grab_frame, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (grab_frame); + gtk_table_attach (GTK_TABLE (options_table), grab_frame, 0, 1, 0, 1, + (GtkAttachOptions) (GTK_EXPAND | GTK_FILL), + (GtkAttachOptions) (GTK_FILL), 0, 0); + gtk_container_set_border_width (GTK_CONTAINER (grab_frame), 10); + + grab_hbox = gtk_hbox_new (FALSE, 8); + gtk_widget_set_name (grab_hbox, "grab_hbox"); + gtk_widget_ref (grab_hbox); + gtk_object_set_data_full (GTK_OBJECT (xscreensaver_demo), "grab_hbox", grab_hbox, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (grab_hbox); + gtk_container_add (GTK_CONTAINER (grab_frame), grab_hbox); + gtk_container_set_border_width (GTK_CONTAINER (grab_hbox), 8); + + img_logo = create_pixmap (xscreensaver_demo, "screensaver-snap.png"); + gtk_widget_set_name (img_logo, "img_logo"); + gtk_widget_ref (img_logo); + gtk_object_set_data_full (GTK_OBJECT (xscreensaver_demo), "img_logo", img_logo, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (img_logo); + gtk_box_pack_start (GTK_BOX (grab_hbox), img_logo, FALSE, FALSE, 0); + gtk_misc_set_alignment (GTK_MISC (img_logo), 0.5, 0); + + grab_vbox = gtk_vbox_new (FALSE, 0); + gtk_widget_set_name (grab_vbox, "grab_vbox"); + gtk_widget_ref (grab_vbox); + gtk_object_set_data_full (GTK_OBJECT (xscreensaver_demo), "grab_vbox", grab_vbox, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (grab_vbox); + gtk_box_pack_start (GTK_BOX (grab_hbox), grab_vbox, TRUE, TRUE, 0); + + grab_desk_eventbox = gtk_event_box_new (); + gtk_widget_set_name (grab_desk_eventbox, "grab_desk_eventbox"); + gtk_widget_ref (grab_desk_eventbox); + gtk_object_set_data_full (GTK_OBJECT (xscreensaver_demo), "grab_desk_eventbox", grab_desk_eventbox, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (grab_desk_eventbox); + gtk_box_pack_start (GTK_BOX (grab_vbox), grab_desk_eventbox, FALSE, FALSE, 0); + gtk_tooltips_set_tip (tooltips, grab_desk_eventbox, _("Whether the image-manipulating modes should be allowed to operate on an image of your desktop."), NULL); + + grab_desk_button = gtk_check_button_new_with_label (_("Grab Desktop Images")); + gtk_widget_set_name (grab_desk_button, "grab_desk_button"); + gtk_widget_ref (grab_desk_button); + gtk_object_set_data_full (GTK_OBJECT (xscreensaver_demo), "grab_desk_button", grab_desk_button, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (grab_desk_button); + gtk_container_add (GTK_CONTAINER (grab_desk_eventbox), grab_desk_button); + + grab_video_eventbox = gtk_event_box_new (); + gtk_widget_set_name (grab_video_eventbox, "grab_video_eventbox"); + gtk_widget_ref (grab_video_eventbox); + gtk_object_set_data_full (GTK_OBJECT (xscreensaver_demo), "grab_video_eventbox", grab_video_eventbox, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (grab_video_eventbox); + gtk_box_pack_start (GTK_BOX (grab_vbox), grab_video_eventbox, FALSE, FALSE, 0); + gtk_tooltips_set_tip (tooltips, grab_video_eventbox, _("Whether the image-manipulating modes should operate on images captured from the system's video input (if there is one)."), NULL); + + grab_video_button = gtk_check_button_new_with_label (_("Grab Video Frames")); + gtk_widget_set_name (grab_video_button, "grab_video_button"); + gtk_widget_ref (grab_video_button); + gtk_object_set_data_full (GTK_OBJECT (xscreensaver_demo), "grab_video_button", grab_video_button, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (grab_video_button); + gtk_container_add (GTK_CONTAINER (grab_video_eventbox), grab_video_button); + + grab_image_eventbox = gtk_event_box_new (); + gtk_widget_set_name (grab_image_eventbox, "grab_image_eventbox"); + gtk_widget_ref (grab_image_eventbox); + gtk_object_set_data_full (GTK_OBJECT (xscreensaver_demo), "grab_image_eventbox", grab_image_eventbox, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (grab_image_eventbox); + gtk_box_pack_start (GTK_BOX (grab_vbox), grab_image_eventbox, FALSE, FALSE, 0); + gtk_tooltips_set_tip (tooltips, grab_image_eventbox, _("Whether the image-manipulating modes should load image files."), NULL); + + grab_image_button = gtk_check_button_new_with_label (_("Choose Random Image:")); + gtk_widget_set_name (grab_image_button, "grab_image_button"); + gtk_widget_ref (grab_image_button); + gtk_object_set_data_full (GTK_OBJECT (xscreensaver_demo), "grab_image_button", grab_image_button, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (grab_image_button); + gtk_container_add (GTK_CONTAINER (grab_image_eventbox), grab_image_button); + + image_hbox = gtk_hbox_new (FALSE, 0); + gtk_widget_set_name (image_hbox, "image_hbox"); + gtk_widget_ref (image_hbox); + gtk_object_set_data_full (GTK_OBJECT (xscreensaver_demo), "image_hbox", image_hbox, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (image_hbox); + gtk_box_pack_start (GTK_BOX (grab_vbox), image_hbox, FALSE, FALSE, 0); + + grab_dummy = gtk_label_new (""); + gtk_widget_set_name (grab_dummy, "grab_dummy"); + gtk_widget_ref (grab_dummy); + gtk_object_set_data_full (GTK_OBJECT (xscreensaver_demo), "grab_dummy", grab_dummy, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (grab_dummy); + gtk_box_pack_start (GTK_BOX (image_hbox), grab_dummy, FALSE, FALSE, 0); + gtk_label_set_justify (GTK_LABEL (grab_dummy), GTK_JUSTIFY_LEFT); + gtk_misc_set_padding (GTK_MISC (grab_dummy), 8, 0); + + image_text = gtk_entry_new (); + gtk_widget_set_name (image_text, "image_text"); + gtk_widget_ref (image_text); + gtk_object_set_data_full (GTK_OBJECT (xscreensaver_demo), "image_text", image_text, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (image_text); + gtk_box_pack_start (GTK_BOX (image_hbox), image_text, TRUE, TRUE, 0); + gtk_tooltips_set_tip (tooltips, image_text, _("The local directory, RSS feed or Atom feed from which images will be randomly chosen."), NULL); + + image_browse_button = gtk_button_new_with_label (_("Browse")); + gtk_widget_set_name (image_browse_button, "image_browse_button"); + gtk_widget_ref (image_browse_button); + gtk_object_set_data_full (GTK_OBJECT (xscreensaver_demo), "image_browse_button", image_browse_button, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (image_browse_button); + gtk_box_pack_start (GTK_BOX (image_hbox), image_browse_button, FALSE, FALSE, 4); + + options_tab = gtk_label_new (_("Advanced")); + gtk_widget_set_name (options_tab, "options_tab"); + gtk_widget_ref (options_tab); + gtk_object_set_data_full (GTK_OBJECT (xscreensaver_demo), "options_tab", options_tab, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (options_tab); + gtk_notebook_set_tab_label (GTK_NOTEBOOK (notebook), gtk_notebook_get_nth_page (GTK_NOTEBOOK (notebook), 1), options_tab); + + gtk_signal_connect (GTK_OBJECT (activate_menu), "activate", + GTK_SIGNAL_FUNC (activate_menu_cb), + NULL); + gtk_signal_connect (GTK_OBJECT (lock_menu), "activate", + GTK_SIGNAL_FUNC (lock_menu_cb), + NULL); + gtk_signal_connect (GTK_OBJECT (kill_menu), "activate", + GTK_SIGNAL_FUNC (kill_menu_cb), + NULL); + gtk_signal_connect (GTK_OBJECT (restart), "activate", + GTK_SIGNAL_FUNC (restart_menu_cb), + NULL); + gtk_signal_connect (GTK_OBJECT (exit_menu), "activate", + GTK_SIGNAL_FUNC (exit_menu_cb), + NULL); + gtk_signal_connect (GTK_OBJECT (about_menu), "activate", + GTK_SIGNAL_FUNC (about_menu_cb), + NULL); + gtk_signal_connect (GTK_OBJECT (doc_menu), "activate", + GTK_SIGNAL_FUNC (doc_menu_cb), + NULL); + gtk_signal_connect (GTK_OBJECT (notebook), "switch_page", + GTK_SIGNAL_FUNC (switch_page_cb), + NULL); + gtk_signal_connect (GTK_OBJECT (lock_button), "toggled", + GTK_SIGNAL_FUNC (pref_changed_cb), + NULL); + gtk_signal_connect (GTK_OBJECT (timeout_spinbutton), "activate", + GTK_SIGNAL_FUNC (pref_changed_cb), + NULL); + gtk_signal_connect (GTK_OBJECT (timeout_spinbutton), "focus_out_event", + GTK_SIGNAL_FUNC (pref_changed_cb), + NULL); + gtk_signal_connect (GTK_OBJECT (timeout_spinbutton), "changed", + GTK_SIGNAL_FUNC (pref_changed_cb), + NULL); + gtk_signal_connect (GTK_OBJECT (lock_spinbutton), "activate", + GTK_SIGNAL_FUNC (pref_changed_cb), + NULL); + gtk_signal_connect (GTK_OBJECT (lock_spinbutton), "focus_out_event", + GTK_SIGNAL_FUNC (pref_changed_cb), + NULL); + gtk_signal_connect (GTK_OBJECT (lock_spinbutton), "changed", + GTK_SIGNAL_FUNC (pref_changed_cb), + NULL); + gtk_signal_connect (GTK_OBJECT (cycle_spinbutton), "activate", + GTK_SIGNAL_FUNC (pref_changed_cb), + NULL); + gtk_signal_connect (GTK_OBJECT (cycle_spinbutton), "focus_out_event", + GTK_SIGNAL_FUNC (pref_changed_cb), + NULL); + gtk_signal_connect (GTK_OBJECT (cycle_spinbutton), "changed", + GTK_SIGNAL_FUNC (pref_changed_cb), + NULL); + gtk_signal_connect (GTK_OBJECT (demo), "clicked", + GTK_SIGNAL_FUNC (run_this_cb), + NULL); + gtk_signal_connect (GTK_OBJECT (settings), "clicked", + GTK_SIGNAL_FUNC (settings_cb), + NULL); + gtk_signal_connect (GTK_OBJECT (next), "clicked", + GTK_SIGNAL_FUNC (run_next_cb), + NULL); + gtk_signal_connect (GTK_OBJECT (prev), "clicked", + GTK_SIGNAL_FUNC (run_prev_cb), + NULL); + gtk_signal_connect (GTK_OBJECT (verbose_button), "toggled", + GTK_SIGNAL_FUNC (pref_changed_cb), + NULL); + gtk_signal_connect (GTK_OBJECT (capture_button), "toggled", + GTK_SIGNAL_FUNC (pref_changed_cb), + NULL); + gtk_signal_connect (GTK_OBJECT (splash_button), "toggled", + GTK_SIGNAL_FUNC (pref_changed_cb), + NULL); + gtk_signal_connect (GTK_OBJECT (install_button), "toggled", + GTK_SIGNAL_FUNC (pref_changed_cb), + NULL); + gtk_signal_connect (GTK_OBJECT (fade_button), "toggled", + GTK_SIGNAL_FUNC (pref_changed_cb), + NULL); + gtk_signal_connect (GTK_OBJECT (unfade_button), "toggled", + GTK_SIGNAL_FUNC (pref_changed_cb), + NULL); + gtk_signal_connect (GTK_OBJECT (fade_spinbutton), "activate", + GTK_SIGNAL_FUNC (pref_changed_cb), + NULL); + gtk_signal_connect (GTK_OBJECT (fade_spinbutton), "focus_out_event", + GTK_SIGNAL_FUNC (pref_changed_cb), + NULL); + gtk_signal_connect (GTK_OBJECT (fade_spinbutton), "changed", + GTK_SIGNAL_FUNC (pref_changed_cb), + NULL); + gtk_signal_connect (GTK_OBJECT (dpms_button), "toggled", + GTK_SIGNAL_FUNC (pref_changed_cb), + NULL); + gtk_signal_connect (GTK_OBJECT (dpms_standby_spinbutton), "activate", + GTK_SIGNAL_FUNC (pref_changed_cb), + NULL); + gtk_signal_connect (GTK_OBJECT (dpms_standby_spinbutton), "focus_out_event", + GTK_SIGNAL_FUNC (pref_changed_cb), + NULL); + gtk_signal_connect (GTK_OBJECT (dpms_standby_spinbutton), "changed", + GTK_SIGNAL_FUNC (pref_changed_cb), + NULL); + gtk_signal_connect (GTK_OBJECT (dpms_suspend_spinbutton), "activate", + GTK_SIGNAL_FUNC (pref_changed_cb), + NULL); + gtk_signal_connect (GTK_OBJECT (dpms_suspend_spinbutton), "focus_out_event", + GTK_SIGNAL_FUNC (pref_changed_cb), + NULL); + gtk_signal_connect (GTK_OBJECT (dpms_suspend_spinbutton), "changed", + GTK_SIGNAL_FUNC (pref_changed_cb), + NULL); + gtk_signal_connect (GTK_OBJECT (dpms_off_spinbutton), "activate", + GTK_SIGNAL_FUNC (pref_changed_cb), + NULL); + gtk_signal_connect (GTK_OBJECT (dpms_off_spinbutton), "focus_out_event", + GTK_SIGNAL_FUNC (pref_changed_cb), + NULL); + gtk_signal_connect (GTK_OBJECT (dpms_off_spinbutton), "changed", + GTK_SIGNAL_FUNC (pref_changed_cb), + NULL); + gtk_signal_connect (GTK_OBJECT (grab_desk_button), "toggled", + GTK_SIGNAL_FUNC (pref_changed_cb), + NULL); + gtk_signal_connect (GTK_OBJECT (grab_video_button), "toggled", + GTK_SIGNAL_FUNC (pref_changed_cb), + NULL); + gtk_signal_connect (GTK_OBJECT (grab_image_button), "toggled", + GTK_SIGNAL_FUNC (pref_changed_cb), + NULL); + gtk_signal_connect (GTK_OBJECT (image_text), "activate", + GTK_SIGNAL_FUNC (pref_changed_cb), + NULL); + gtk_signal_connect (GTK_OBJECT (image_text), "focus_out_event", + GTK_SIGNAL_FUNC (pref_changed_cb), + NULL); + gtk_signal_connect (GTK_OBJECT (image_browse_button), "clicked", + GTK_SIGNAL_FUNC (browse_image_dir_cb), + NULL); + + gtk_widget_grab_default (next); + gtk_object_set_data (GTK_OBJECT (xscreensaver_demo), "tooltips", tooltips); + + gtk_window_add_accel_group (GTK_WINDOW (xscreensaver_demo), accel_group); + + return xscreensaver_demo; +} + +GtkWidget* +create_xscreensaver_settings_dialog (void) +{ + GtkWidget *xscreensaver_settings_dialog; + GtkWidget *dialog_vbox; + GtkWidget *dialog_top_table; + GtkWidget *opt_frame; + GtkWidget *opt_notebook; + GtkWidget *settings_vbox; + GtkWidget *std_label; + GtkWidget *opt_table; + GtkWidget *cmd_logo; + GtkWidget *visual_hbox; + GtkWidget *visual; + GtkWidget *visual_combo; + GList *visual_combo_items = NULL; + GtkWidget *combo_entry1; + GtkWidget *cmd_label; + GtkWidget *cmd_text; + GtkWidget *adv_label; + GtkWidget *doc_frame; + GtkWidget *doc_vbox; + GtkWidget *doc; + GtkWidget *doc_hbuttonbox; + GtkWidget *manual; + GtkWidget *dialog_action_area; + GtkWidget *actionarea_hbox; + GtkWidget *dialog_hbuttonbox; + GtkWidget *adv_button; + GtkWidget *std_button; + GtkWidget *reset_button; + GtkWidget *ok_cancel_hbuttonbox; + GtkWidget *ok_button; + GtkWidget *cancel_button; + GtkTooltips *tooltips; + + tooltips = gtk_tooltips_new (); + + xscreensaver_settings_dialog = gtk_dialog_new (); + gtk_widget_set_name (xscreensaver_settings_dialog, "xscreensaver_settings_dialog"); + gtk_object_set_data (GTK_OBJECT (xscreensaver_settings_dialog), "xscreensaver_settings_dialog", xscreensaver_settings_dialog); + gtk_window_set_title (GTK_WINDOW (xscreensaver_settings_dialog), _("XScreenSaver: Mode-Specific Settings")); + GTK_WINDOW (xscreensaver_settings_dialog)->type = GTK_WINDOW_DIALOG; + gtk_window_set_modal (GTK_WINDOW (xscreensaver_settings_dialog), TRUE); + gtk_window_set_policy (GTK_WINDOW (xscreensaver_settings_dialog), TRUE, TRUE, FALSE); + gtk_window_set_wmclass (GTK_WINDOW (xscreensaver_settings_dialog), "settings", "XScreenSaver"); + + dialog_vbox = GTK_DIALOG (xscreensaver_settings_dialog)->vbox; + gtk_widget_set_name (dialog_vbox, "dialog_vbox"); + gtk_object_set_data (GTK_OBJECT (xscreensaver_settings_dialog), "dialog_vbox", dialog_vbox); + gtk_widget_show (dialog_vbox); + + dialog_top_table = gtk_table_new (1, 2, FALSE); + gtk_widget_set_name (dialog_top_table, "dialog_top_table"); + gtk_widget_ref (dialog_top_table); + gtk_object_set_data_full (GTK_OBJECT (xscreensaver_settings_dialog), "dialog_top_table", dialog_top_table, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (dialog_top_table); + gtk_box_pack_start (GTK_BOX (dialog_vbox), dialog_top_table, TRUE, TRUE, 0); + gtk_container_set_border_width (GTK_CONTAINER (dialog_top_table), 8); + gtk_table_set_row_spacings (GTK_TABLE (dialog_top_table), 8); + gtk_table_set_col_spacings (GTK_TABLE (dialog_top_table), 8); + + opt_frame = gtk_frame_new (_("Settings")); + gtk_widget_set_name (opt_frame, "opt_frame"); + gtk_widget_ref (opt_frame); + gtk_object_set_data_full (GTK_OBJECT (xscreensaver_settings_dialog), "opt_frame", opt_frame, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (opt_frame); + gtk_table_attach (GTK_TABLE (dialog_top_table), opt_frame, 0, 1, 0, 1, + (GtkAttachOptions) (GTK_EXPAND | GTK_FILL), + (GtkAttachOptions) (GTK_EXPAND | GTK_FILL), 4, 8); + + opt_notebook = gtk_notebook_new (); + gtk_widget_set_name (opt_notebook, "opt_notebook"); + gtk_widget_ref (opt_notebook); + gtk_object_set_data_full (GTK_OBJECT (xscreensaver_settings_dialog), "opt_notebook", opt_notebook, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (opt_notebook); + gtk_container_add (GTK_CONTAINER (opt_frame), opt_notebook); + gtk_container_set_border_width (GTK_CONTAINER (opt_notebook), 12); + gtk_notebook_set_show_border (GTK_NOTEBOOK (opt_notebook), FALSE); + gtk_notebook_set_tab_pos (GTK_NOTEBOOK (opt_notebook), GTK_POS_BOTTOM); + + settings_vbox = gtk_vbox_new (FALSE, 0); + gtk_widget_set_name (settings_vbox, "settings_vbox"); + gtk_widget_ref (settings_vbox); + gtk_object_set_data_full (GTK_OBJECT (xscreensaver_settings_dialog), "settings_vbox", settings_vbox, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (settings_vbox); + gtk_container_add (GTK_CONTAINER (opt_notebook), settings_vbox); + + std_label = gtk_label_new (_("Standard")); + gtk_widget_set_name (std_label, "std_label"); + gtk_widget_ref (std_label); + gtk_object_set_data_full (GTK_OBJECT (xscreensaver_settings_dialog), "std_label", std_label, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (std_label); + gtk_notebook_set_tab_label (GTK_NOTEBOOK (opt_notebook), gtk_notebook_get_nth_page (GTK_NOTEBOOK (opt_notebook), 0), std_label); + + opt_table = gtk_table_new (4, 2, FALSE); + gtk_widget_set_name (opt_table, "opt_table"); + gtk_widget_ref (opt_table); + gtk_object_set_data_full (GTK_OBJECT (xscreensaver_settings_dialog), "opt_table", opt_table, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (opt_table); + gtk_container_add (GTK_CONTAINER (opt_notebook), opt_table); + + cmd_logo = create_pixmap (xscreensaver_settings_dialog, "screensaver-cmndln.png"); + gtk_widget_set_name (cmd_logo, "cmd_logo"); + gtk_widget_ref (cmd_logo); + gtk_object_set_data_full (GTK_OBJECT (xscreensaver_settings_dialog), "cmd_logo", cmd_logo, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (cmd_logo); + gtk_table_attach (GTK_TABLE (opt_table), cmd_logo, 0, 1, 0, 1, + (GtkAttachOptions) (GTK_FILL), + (GtkAttachOptions) (GTK_FILL), 0, 0); + gtk_misc_set_padding (GTK_MISC (cmd_logo), 4, 8); + + visual_hbox = gtk_hbox_new (FALSE, 0); + gtk_widget_set_name (visual_hbox, "visual_hbox"); + gtk_widget_ref (visual_hbox); + gtk_object_set_data_full (GTK_OBJECT (xscreensaver_settings_dialog), "visual_hbox", visual_hbox, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (visual_hbox); + gtk_table_attach (GTK_TABLE (opt_table), visual_hbox, 1, 2, 3, 4, + (GtkAttachOptions) (GTK_FILL), + (GtkAttachOptions) (GTK_FILL), 0, 0); + + visual = gtk_label_new (_("Visual:")); + gtk_widget_set_name (visual, "visual"); + gtk_widget_ref (visual); + gtk_object_set_data_full (GTK_OBJECT (xscreensaver_settings_dialog), "visual", visual, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (visual); + gtk_box_pack_start (GTK_BOX (visual_hbox), visual, FALSE, FALSE, 0); + gtk_label_set_justify (GTK_LABEL (visual), GTK_JUSTIFY_RIGHT); + gtk_misc_set_alignment (GTK_MISC (visual), 1, 0.5); + gtk_misc_set_padding (GTK_MISC (visual), 4, 0); + + visual_combo = gtk_combo_new (); + gtk_widget_set_name (visual_combo, "visual_combo"); + gtk_widget_ref (visual_combo); + gtk_object_set_data_full (GTK_OBJECT (xscreensaver_settings_dialog), "visual_combo", visual_combo, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (visual_combo); + gtk_box_pack_start (GTK_BOX (visual_hbox), visual_combo, FALSE, FALSE, 0); + visual_combo_items = g_list_append (visual_combo_items, (gpointer) _("Any")); + visual_combo_items = g_list_append (visual_combo_items, (gpointer) _("Best")); + visual_combo_items = g_list_append (visual_combo_items, (gpointer) _("Default")); + visual_combo_items = g_list_append (visual_combo_items, (gpointer) _("Default-N")); + visual_combo_items = g_list_append (visual_combo_items, (gpointer) _("GL")); + visual_combo_items = g_list_append (visual_combo_items, (gpointer) _("TrueColor")); + visual_combo_items = g_list_append (visual_combo_items, (gpointer) _("PseudoColor")); + visual_combo_items = g_list_append (visual_combo_items, (gpointer) _("StaticGray")); + visual_combo_items = g_list_append (visual_combo_items, (gpointer) _("GrayScale")); + visual_combo_items = g_list_append (visual_combo_items, (gpointer) _("DirectColor")); + visual_combo_items = g_list_append (visual_combo_items, (gpointer) _("Color")); + visual_combo_items = g_list_append (visual_combo_items, (gpointer) _("Gray")); + visual_combo_items = g_list_append (visual_combo_items, (gpointer) _("Mono")); + gtk_combo_set_popdown_strings (GTK_COMBO (visual_combo), visual_combo_items); + g_list_free (visual_combo_items); + + combo_entry1 = GTK_COMBO (visual_combo)->entry; + gtk_widget_set_name (combo_entry1, "combo_entry1"); + gtk_widget_ref (combo_entry1); + gtk_object_set_data_full (GTK_OBJECT (xscreensaver_settings_dialog), "combo_entry1", combo_entry1, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (combo_entry1); + gtk_tooltips_set_tip (tooltips, combo_entry1, _("The X visual type that this demo will require. If that visual is available it will be used, otherwise, this demo will not be run."), NULL); + gtk_entry_set_text (GTK_ENTRY (combo_entry1), _("Any")); + + cmd_label = gtk_label_new (_("Command Line:")); + gtk_widget_set_name (cmd_label, "cmd_label"); + gtk_widget_ref (cmd_label); + gtk_object_set_data_full (GTK_OBJECT (xscreensaver_settings_dialog), "cmd_label", cmd_label, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (cmd_label); + gtk_table_attach (GTK_TABLE (opt_table), cmd_label, 1, 2, 1, 2, + (GtkAttachOptions) (GTK_EXPAND | GTK_FILL), + (GtkAttachOptions) (0), 0, 0); + gtk_label_set_justify (GTK_LABEL (cmd_label), GTK_JUSTIFY_LEFT); + gtk_misc_set_alignment (GTK_MISC (cmd_label), 0, 1); + gtk_misc_set_padding (GTK_MISC (cmd_label), 0, 2); + + cmd_text = gtk_entry_new (); + gtk_widget_set_name (cmd_text, "cmd_text"); + gtk_widget_ref (cmd_text); + gtk_object_set_data_full (GTK_OBJECT (xscreensaver_settings_dialog), "cmd_text", cmd_text, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (cmd_text); + gtk_table_attach (GTK_TABLE (opt_table), cmd_text, 1, 2, 2, 3, + (GtkAttachOptions) (GTK_EXPAND | GTK_FILL), + (GtkAttachOptions) (0), 0, 0); + gtk_widget_set_usize (cmd_text, 80, -2); + + adv_label = gtk_label_new (_("Advanced")); + gtk_widget_set_name (adv_label, "adv_label"); + gtk_widget_ref (adv_label); + gtk_object_set_data_full (GTK_OBJECT (xscreensaver_settings_dialog), "adv_label", adv_label, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (adv_label); + gtk_notebook_set_tab_label (GTK_NOTEBOOK (opt_notebook), gtk_notebook_get_nth_page (GTK_NOTEBOOK (opt_notebook), 1), adv_label); + + doc_frame = gtk_frame_new (_("Description")); + gtk_widget_set_name (doc_frame, "doc_frame"); + gtk_widget_ref (doc_frame); + gtk_object_set_data_full (GTK_OBJECT (xscreensaver_settings_dialog), "doc_frame", doc_frame, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (doc_frame); + gtk_table_attach (GTK_TABLE (dialog_top_table), doc_frame, 1, 2, 0, 1, + (GtkAttachOptions) (GTK_EXPAND | GTK_SHRINK | GTK_FILL), + (GtkAttachOptions) (GTK_EXPAND | GTK_SHRINK | GTK_FILL), 4, 8); + + doc_vbox = gtk_vbox_new (FALSE, 0); + gtk_widget_set_name (doc_vbox, "doc_vbox"); + gtk_widget_ref (doc_vbox); + gtk_object_set_data_full (GTK_OBJECT (xscreensaver_settings_dialog), "doc_vbox", doc_vbox, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (doc_vbox); + gtk_container_add (GTK_CONTAINER (doc_frame), doc_vbox); + + doc = gtk_label_new (""); + gtk_widget_set_name (doc, "doc"); + gtk_widget_ref (doc); + gtk_object_set_data_full (GTK_OBJECT (xscreensaver_settings_dialog), "doc", doc, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (doc); + gtk_box_pack_start (GTK_BOX (doc_vbox), doc, TRUE, TRUE, 0); + gtk_label_set_justify (GTK_LABEL (doc), GTK_JUSTIFY_LEFT); + gtk_label_set_line_wrap (GTK_LABEL (doc), TRUE); + gtk_misc_set_alignment (GTK_MISC (doc), 0, 0); + gtk_misc_set_padding (GTK_MISC (doc), 10, 10); + + doc_hbuttonbox = gtk_hbutton_box_new (); + gtk_widget_set_name (doc_hbuttonbox, "doc_hbuttonbox"); + gtk_widget_ref (doc_hbuttonbox); + gtk_object_set_data_full (GTK_OBJECT (xscreensaver_settings_dialog), "doc_hbuttonbox", doc_hbuttonbox, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (doc_hbuttonbox); + gtk_box_pack_end (GTK_BOX (doc_vbox), doc_hbuttonbox, FALSE, FALSE, 0); + gtk_container_set_border_width (GTK_CONTAINER (doc_hbuttonbox), 4); + gtk_button_box_set_layout (GTK_BUTTON_BOX (doc_hbuttonbox), GTK_BUTTONBOX_END); + + manual = gtk_button_new_with_label (_("Documentation...")); + gtk_widget_set_name (manual, "manual"); + gtk_widget_ref (manual); + gtk_object_set_data_full (GTK_OBJECT (xscreensaver_settings_dialog), "manual", manual, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (manual); + gtk_container_add (GTK_CONTAINER (doc_hbuttonbox), manual); + STFU GTK_WIDGET_SET_FLAGS (manual, GTK_CAN_DEFAULT); + gtk_tooltips_set_tip (tooltips, manual, _("Click here to read the manual for this display mode, if it has one."), NULL); + + dialog_action_area = GTK_DIALOG (xscreensaver_settings_dialog)->action_area; + gtk_widget_set_name (dialog_action_area, "dialog_action_area"); + gtk_object_set_data (GTK_OBJECT (xscreensaver_settings_dialog), "dialog_action_area", dialog_action_area); + gtk_widget_show (dialog_action_area); + gtk_container_set_border_width (GTK_CONTAINER (dialog_action_area), 10); + + actionarea_hbox = gtk_hbox_new (FALSE, 0); + gtk_widget_set_name (actionarea_hbox, "actionarea_hbox"); + gtk_widget_ref (actionarea_hbox); + gtk_object_set_data_full (GTK_OBJECT (xscreensaver_settings_dialog), "actionarea_hbox", actionarea_hbox, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (actionarea_hbox); + gtk_box_pack_start (GTK_BOX (dialog_action_area), actionarea_hbox, TRUE, TRUE, 0); + + dialog_hbuttonbox = gtk_hbutton_box_new (); + gtk_widget_set_name (dialog_hbuttonbox, "dialog_hbuttonbox"); + gtk_widget_ref (dialog_hbuttonbox); + gtk_object_set_data_full (GTK_OBJECT (xscreensaver_settings_dialog), "dialog_hbuttonbox", dialog_hbuttonbox, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (dialog_hbuttonbox); + gtk_box_pack_start (GTK_BOX (actionarea_hbox), dialog_hbuttonbox, TRUE, TRUE, 0); + gtk_button_box_set_layout (GTK_BUTTON_BOX (dialog_hbuttonbox), GTK_BUTTONBOX_SPREAD); + + adv_button = gtk_button_new_with_label (_("Advanced >>")); + gtk_widget_set_name (adv_button, "adv_button"); + gtk_widget_ref (adv_button); + gtk_object_set_data_full (GTK_OBJECT (xscreensaver_settings_dialog), "adv_button", adv_button, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (adv_button); + gtk_container_add (GTK_CONTAINER (dialog_hbuttonbox), adv_button); + STFU GTK_WIDGET_SET_FLAGS (adv_button, GTK_CAN_DEFAULT); + gtk_tooltips_set_tip (tooltips, adv_button, _("Edit the command line directly."), NULL); + + std_button = gtk_button_new_with_label (_("Standard <<")); + gtk_widget_set_name (std_button, "std_button"); + gtk_widget_ref (std_button); + gtk_object_set_data_full (GTK_OBJECT (xscreensaver_settings_dialog), "std_button", std_button, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (std_button); + gtk_container_add (GTK_CONTAINER (dialog_hbuttonbox), std_button); + STFU GTK_WIDGET_SET_FLAGS (std_button, GTK_CAN_DEFAULT); + gtk_tooltips_set_tip (tooltips, std_button, _("Back to the graphical configuration options."), NULL); + + reset_button = gtk_button_new_with_label (_("Reset to Defaults")); + gtk_widget_set_name (reset_button, "reset_button"); + gtk_widget_ref (reset_button); + gtk_object_set_data_full (GTK_OBJECT (xscreensaver_settings_dialog), "reset_button", reset_button, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (reset_button); + gtk_container_add (GTK_CONTAINER (dialog_hbuttonbox), reset_button); + STFU GTK_WIDGET_SET_FLAGS (reset_button, GTK_CAN_DEFAULT); + gtk_tooltips_set_tip (tooltips, reset_button, _("Reset this screen saver to the default settings."), NULL); + + ok_cancel_hbuttonbox = gtk_hbutton_box_new (); + gtk_widget_set_name (ok_cancel_hbuttonbox, "ok_cancel_hbuttonbox"); + gtk_widget_ref (ok_cancel_hbuttonbox); + gtk_object_set_data_full (GTK_OBJECT (xscreensaver_settings_dialog), "ok_cancel_hbuttonbox", ok_cancel_hbuttonbox, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (ok_cancel_hbuttonbox); + gtk_box_pack_start (GTK_BOX (actionarea_hbox), ok_cancel_hbuttonbox, TRUE, TRUE, 0); + gtk_button_box_set_layout (GTK_BUTTON_BOX (ok_cancel_hbuttonbox), GTK_BUTTONBOX_END); + + ok_button = gtk_button_new_with_label (_("OK")); + gtk_widget_set_name (ok_button, "ok_button"); + gtk_widget_ref (ok_button); + gtk_object_set_data_full (GTK_OBJECT (xscreensaver_settings_dialog), "ok_button", ok_button, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (ok_button); + gtk_container_add (GTK_CONTAINER (ok_cancel_hbuttonbox), ok_button); + STFU GTK_WIDGET_SET_FLAGS (ok_button, GTK_CAN_DEFAULT); + + cancel_button = gtk_button_new_with_label (_("Cancel")); + gtk_widget_set_name (cancel_button, "cancel_button"); + gtk_widget_ref (cancel_button); + gtk_object_set_data_full (GTK_OBJECT (xscreensaver_settings_dialog), "cancel_button", cancel_button, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (cancel_button); + gtk_container_add (GTK_CONTAINER (ok_cancel_hbuttonbox), cancel_button); + STFU GTK_WIDGET_SET_FLAGS (cancel_button, GTK_CAN_DEFAULT); + + gtk_signal_connect (GTK_OBJECT (opt_notebook), "switch_page", + GTK_SIGNAL_FUNC (settings_switch_page_cb), + NULL); + gtk_signal_connect (GTK_OBJECT (manual), "clicked", + GTK_SIGNAL_FUNC (manual_cb), + NULL); + gtk_signal_connect (GTK_OBJECT (adv_button), "clicked", + GTK_SIGNAL_FUNC (settings_adv_cb), + NULL); + gtk_signal_connect (GTK_OBJECT (std_button), "clicked", + GTK_SIGNAL_FUNC (settings_std_cb), + NULL); + gtk_signal_connect (GTK_OBJECT (reset_button), "clicked", + GTK_SIGNAL_FUNC (settings_reset_cb), + NULL); + gtk_signal_connect (GTK_OBJECT (ok_button), "clicked", + GTK_SIGNAL_FUNC (settings_ok_cb), + NULL); + gtk_signal_connect (GTK_OBJECT (cancel_button), "clicked", + GTK_SIGNAL_FUNC (settings_cancel_cb), + NULL); + + gtk_object_set_data (GTK_OBJECT (xscreensaver_settings_dialog), "tooltips", tooltips); + + return xscreensaver_settings_dialog; +} + diff --git a/driver/demo-Gtk-widgets.h b/driver/demo-Gtk-widgets.h new file mode 100644 index 00000000..298c5171 --- /dev/null +++ b/driver/demo-Gtk-widgets.h @@ -0,0 +1,6 @@ +/* + * DO NOT EDIT THIS FILE - it is generated by Glade. + */ + +GtkWidget* create_xscreensaver_demo (void); +GtkWidget* create_xscreensaver_settings_dialog (void); diff --git a/driver/demo-Gtk.c b/driver/demo-Gtk.c new file mode 100644 index 00000000..93e5fb3c --- /dev/null +++ b/driver/demo-Gtk.c @@ -0,0 +1,5334 @@ +/* demo-Gtk.c --- implements the interactive demo-mode and options dialogs. + * xscreensaver, Copyright (c) 1993-2012 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. + */ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#ifdef HAVE_GTK /* whole file */ + +#include + +#include + +#ifdef HAVE_UNISTD_H +# include +#endif + +# ifdef __GNUC__ +# define STFU __extension__ /* ignore gcc -pendantic warnings in next sexp */ +# else +# define STFU /* */ +# endif + + +#ifdef ENABLE_NLS +# include +#endif /* ENABLE_NLS */ + +#ifndef VMS +# include /* for getpwuid() */ +#else /* VMS */ +# include "vms-pwd.h" +#endif /* VMS */ + +#ifdef HAVE_UNAME +# include /* for uname() */ +#endif /* HAVE_UNAME */ + +#include +#include +#include +#include + + +#include +#include +#ifdef HAVE_SYS_WAIT_H +# include /* for waitpid() and associated macros */ +#endif + + +#include /* for CARD32 */ +#include /* for XA_INTEGER */ +#include +#include + +/* We don't actually use any widget internals, but these are included + so that gdb will have debug info for the widgets... */ +#include +#include + +#ifdef HAVE_XMU +# ifndef VMS +# include +# else /* VMS */ +# include +# endif +#else +# include "xmu.h" +#endif + +#ifdef HAVE_XINERAMA +# include +#endif /* HAVE_XINERAMA */ + +#include + +#ifdef HAVE_CRAPPLET +# include +# include +#endif + +#include + +#ifdef HAVE_GTK2 +# include +# include +#else /* !HAVE_GTK2 */ +# define G_MODULE_EXPORT /**/ +#endif /* !HAVE_GTK2 */ + +#if defined(DEFAULT_ICONDIR) && !defined(GLADE_DIR) +# define GLADE_DIR DEFAULT_ICONDIR +#endif +#if !defined(DEFAULT_ICONDIR) && defined(GLADE_DIR) +# define DEFAULT_ICONDIR GLADE_DIR +#endif + +#ifndef HAVE_XML + /* Kludge: this is defined in demo-Gtk-conf.c when HAVE_XML. + It is unused otherwise, so in that case, stub it out. */ + static const char *hack_configuration_path = 0; +#endif + + + +#include "version.h" +#include "prefs.h" +#include "resources.h" /* for parse_time() */ +#include "visual.h" /* for has_writable_cells() */ +#include "remote.h" /* for xscreensaver_command() */ +#include "usleep.h" + +#include "logo-50.xpm" +#include "logo-180.xpm" + +#undef dgettext /* else these are defined twice... */ +#undef dcgettext + +#include "demo-Gtk-widgets.h" +#include "demo-Gtk-support.h" +#include "demo-Gtk-conf.h" + +#include +#include +#include + +#ifdef HAVE_GTK2 +enum { + COL_ENABLED, + COL_NAME, + COL_LAST +}; +#endif /* HAVE_GTK2 */ + +/* Deal with deprecation of direct access to struct fields on the way to GTK3 + See http://live.gnome.org/GnomeGoals/UseGseal + */ +#if GTK_CHECK_VERSION(2,14,0) +# define GET_PARENT(w) gtk_widget_get_parent (w) +# define GET_WINDOW(w) gtk_widget_get_window (w) +# define GET_ACTION_AREA(d) gtk_dialog_get_action_area (d) +# define GET_CONTENT_AREA(d) gtk_dialog_get_content_area (d) +# define GET_ADJ_VALUE(a) gtk_adjustment_get_value (a) +# define SET_ADJ_VALUE(a,v) gtk_adjustment_set_value (a, v) +# define SET_ADJ_UPPER(a,v) gtk_adjustment_set_upper (a, v) +#else +# define GET_PARENT(w) ((w)->parent) +# define GET_WINDOW(w) ((w)->window) +# define GET_ACTION_AREA(d) ((d)->action_area) +# define GET_CONTENT_AREA(d) ((d)->vbox) +# define GET_ADJ_VALUE(a) ((a)->value) +# define SET_ADJ_VALUE(a,v) (a)->value = v +# define SET_ADJ_UPPER(a,v) (a)->upper = v +#endif + +#if GTK_CHECK_VERSION(2,18,0) +# define SET_CAN_DEFAULT(w) gtk_widget_set_can_default ((w), TRUE) +# define GET_SENSITIVE(w) gtk_widget_get_sensitive (w) +#else +# define SET_CAN_DEFAULT(w) GTK_WIDGET_SET_FLAGS ((w), GTK_CAN_DEFAULT) +# define GET_SENSITIVE(w) GTK_WIDGET_IS_SENSITIVE (w) +#endif + +#if GTK_CHECK_VERSION(2,20,0) +# define GET_REALIZED(w) gtk_widget_get_realized (w) +#else +# define GET_REALIZED(w) GTK_WIDGET_REALIZED (w) +#endif + +/* from exec.c */ +extern void exec_command (const char *shell, const char *command, int nice); +extern int on_path_p (const char *program); + +static void hack_subproc_environment (Window preview_window_id, Bool debug_p); + +#undef countof +#define countof(x) (sizeof((x))/sizeof((*x))) + + +/* You might think that to read an array of 32-bit quantities out of a + server-side property, you would pass an array of 32-bit data quantities + into XGetWindowProperty(). You would be wrong. You have to use an array + of longs, even if long is 64 bits (using 32 of each 64.) + */ +typedef long PROP32; + +char *progname = 0; +char *progclass = "XScreenSaver"; +XrmDatabase db; + +/* The order of the items in the mode menu. */ +static int mode_menu_order[] = { + DONT_BLANK, BLANK_ONLY, ONE_HACK, RANDOM_HACKS, RANDOM_HACKS_SAME }; + + +typedef struct { + + char *short_version; /* version number of this xscreensaver build */ + + GtkWidget *toplevel_widget; /* the main window */ + GtkWidget *base_widget; /* root of our hierarchy (for name lookups) */ + GtkWidget *popup_widget; /* the "Settings" dialog */ + conf_data *cdata; /* private data for per-hack configuration */ + +#ifdef HAVE_GTK2 + GladeXML *glade_ui; /* Glade UI file */ +#endif /* HAVE_GTK2 */ + + Bool debug_p; /* whether to print diagnostics */ + Bool initializing_p; /* flag for breaking recursion loops */ + Bool saving_p; /* flag for breaking recursion loops */ + + char *desired_preview_cmd; /* subprocess we intend to run */ + char *running_preview_cmd; /* subprocess we are currently running */ + pid_t running_preview_pid; /* pid of forked subproc (might be dead) */ + Bool running_preview_error_p; /* whether the pid died abnormally */ + + Bool preview_suppressed_p; /* flag meaning "don't launch subproc" */ + int subproc_timer_id; /* timer to delay subproc launch */ + int subproc_check_timer_id; /* timer to check whether it started up */ + int subproc_check_countdown; /* how many more checks left */ + + int *list_elt_to_hack_number; /* table for sorting the hack list */ + int *hack_number_to_list_elt; /* the inverse table */ + Bool *hacks_available_p; /* whether hacks are on $PATH */ + int total_available; /* how many are on $PATH */ + int list_count; /* how many items are in the list: this may be + less than p->screenhacks_count, if some are + suppressed. */ + + int _selected_list_element; /* don't use this: call + selected_list_element() instead */ + + int nscreens; /* How many X or Xinerama screens there are */ + + saver_preferences prefs; + +} state; + + +/* Total fucking evilness due to the fact that it's rocket science to get + a closure object of our own down into the various widget callbacks. */ +static state *global_state_kludge; + +Atom XA_VROOT; +Atom XA_SCREENSAVER, XA_SCREENSAVER_RESPONSE, XA_SCREENSAVER_VERSION; +Atom XA_SCREENSAVER_ID, XA_SCREENSAVER_STATUS, XA_SELECT, XA_DEMO; +Atom XA_ACTIVATE, XA_BLANK, XA_LOCK, XA_RESTART, XA_EXIT; + + +static void populate_demo_window (state *, int list_elt); +static void populate_prefs_page (state *); +static void populate_popup_window (state *); + +static Bool flush_dialog_changes_and_save (state *); +static Bool flush_popup_changes_and_save (state *); + +static int maybe_reload_init_file (state *); +static void await_xscreensaver (state *); +static Bool xscreensaver_running_p (state *); +static void sensitize_menu_items (state *s, Bool force_p); +static void force_dialog_repaint (state *s); + +static void schedule_preview (state *, const char *cmd); +static void kill_preview_subproc (state *, Bool reset_p); +static void schedule_preview_check (state *); + + +/* Prototypes of functions used by the Glade-generated code, + to avoid warnings. + */ +void exit_menu_cb (GtkMenuItem *, gpointer user_data); +void about_menu_cb (GtkMenuItem *, gpointer user_data); +void doc_menu_cb (GtkMenuItem *, gpointer user_data); +void file_menu_cb (GtkMenuItem *, gpointer user_data); +void activate_menu_cb (GtkMenuItem *, gpointer user_data); +void lock_menu_cb (GtkMenuItem *, gpointer user_data); +void kill_menu_cb (GtkMenuItem *, gpointer user_data); +void restart_menu_cb (GtkWidget *, gpointer user_data); +void run_this_cb (GtkButton *, gpointer user_data); +void manual_cb (GtkButton *, gpointer user_data); +void run_next_cb (GtkButton *, gpointer user_data); +void run_prev_cb (GtkButton *, gpointer user_data); +void pref_changed_cb (GtkWidget *, gpointer user_data); +gboolean pref_changed_event_cb (GtkWidget *, GdkEvent *, gpointer user_data); +void mode_menu_item_cb (GtkWidget *, gpointer user_data); +void switch_page_cb (GtkNotebook *, GtkNotebookPage *, + gint page_num, gpointer user_data); +void browse_image_dir_cb (GtkButton *, gpointer user_data); +void browse_text_file_cb (GtkButton *, gpointer user_data); +void browse_text_program_cb (GtkButton *, gpointer user_data); +void settings_cb (GtkButton *, gpointer user_data); +void settings_adv_cb (GtkButton *, gpointer user_data); +void settings_std_cb (GtkButton *, gpointer user_data); +void settings_reset_cb (GtkButton *, gpointer user_data); +void settings_switch_page_cb (GtkNotebook *, GtkNotebookPage *, + gint page_num, gpointer user_data); +void settings_cancel_cb (GtkButton *, gpointer user_data); +void settings_ok_cb (GtkButton *, gpointer user_data); + +static void kill_gnome_screensaver (void); +static void kill_kde_screensaver (void); + + +/* Some random utility functions + */ + +const char *blurb (void); + +const char * +blurb (void) +{ + time_t now = time ((time_t *) 0); + char *ct = (char *) ctime (&now); + static char buf[255]; + int n = strlen(progname); + if (n > 100) n = 99; + strncpy(buf, progname, n); + buf[n++] = ':'; + buf[n++] = ' '; + strncpy(buf+n, ct+11, 8); + strcpy(buf+n+9, ": "); + return buf; +} + + +static GtkWidget * +name_to_widget (state *s, const char *name) +{ + GtkWidget *w; + if (!s) abort(); + if (!name) abort(); + if (!*name) abort(); + +#ifdef HAVE_GTK2 + if (!s->glade_ui) + { + /* First try to load the Glade file from the current directory; + if there isn't one there, check the installed directory. + */ +# define GLADE_FILE_NAME "xscreensaver-demo.glade2" + const char * const files[] = { GLADE_FILE_NAME, + GLADE_DIR "/" GLADE_FILE_NAME }; + int i; + for (i = 0; i < countof (files); i++) + { + struct stat st; + if (!stat (files[i], &st)) + { + s->glade_ui = glade_xml_new (files[i], NULL, NULL); + break; + } + } + if (!s->glade_ui) + { + fprintf (stderr, + "%s: could not load \"" GLADE_FILE_NAME "\"\n" + "\tfrom " GLADE_DIR "/ or current directory.\n", + blurb()); + exit (-1); + } +# undef GLADE_FILE_NAME + + glade_xml_signal_autoconnect (s->glade_ui); + } + + w = glade_xml_get_widget (s->glade_ui, name); + +#else /* !HAVE_GTK2 */ + + w = (GtkWidget *) gtk_object_get_data (GTK_OBJECT (s->base_widget), + name); + if (w) return w; + w = (GtkWidget *) gtk_object_get_data (GTK_OBJECT (s->popup_widget), + name); +#endif /* HAVE_GTK2 */ + if (w) return w; + + fprintf (stderr, "%s: no widget \"%s\" (wrong Glade file?)\n", + blurb(), name); + abort(); +} + + +/* Why this behavior isn't automatic in *either* toolkit, I'll never know. + Takes a scroller, viewport, or list as an argument. + */ +static void +ensure_selected_item_visible (GtkWidget *widget) +{ +#ifdef HAVE_GTK2 + GtkTreePath *path; + GtkTreeSelection *selection; + GtkTreeIter iter; + GtkTreeModel *model; + + selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (widget)); + if (!gtk_tree_selection_get_selected (selection, &model, &iter)) + path = gtk_tree_path_new_first (); + else + path = gtk_tree_model_get_path (model, &iter); + + gtk_tree_view_set_cursor (GTK_TREE_VIEW (widget), path, NULL, FALSE); + + gtk_tree_path_free (path); + +#else /* !HAVE_GTK2 */ + + GtkScrolledWindow *scroller = 0; + GtkViewport *vp = 0; + GtkList *list_widget = 0; + GList *slist; + GList *kids; + int nkids = 0; + GtkWidget *selected = 0; + int list_elt = -1; + GtkAdjustment *adj; + gint parent_h, child_y, child_h, children_h, ignore; + double ratio_t, ratio_b; + + if (GTK_IS_SCROLLED_WINDOW (widget)) + { + scroller = GTK_SCROLLED_WINDOW (widget); + vp = GTK_VIEWPORT (GTK_BIN (scroller)->child); + list_widget = GTK_LIST (GTK_BIN(vp)->child); + } + else if (GTK_IS_VIEWPORT (widget)) + { + vp = GTK_VIEWPORT (widget); + scroller = GTK_SCROLLED_WINDOW (GTK_WIDGET (vp)->parent); + list_widget = GTK_LIST (GTK_BIN(vp)->child); + } + else if (GTK_IS_LIST (widget)) + { + list_widget = GTK_LIST (widget); + vp = GTK_VIEWPORT (GTK_WIDGET (list_widget)->parent); + scroller = GTK_SCROLLED_WINDOW (GTK_WIDGET (vp)->parent); + } + else + abort(); + + slist = list_widget->selection; + selected = (slist ? GTK_WIDGET (slist->data) : 0); + if (!selected) + return; + + list_elt = gtk_list_child_position (list_widget, GTK_WIDGET (selected)); + + for (kids = gtk_container_children (GTK_CONTAINER (list_widget)); + kids; kids = kids->next) + nkids++; + + adj = gtk_scrolled_window_get_vadjustment (scroller); + + gdk_window_get_geometry (GET_WINDOW (GTK_WIDGET (vp)), + &ignore, &ignore, &ignore, &parent_h, &ignore); + gdk_window_get_geometry (GET_WINDOW (GTK_WIDGET (selected)), + &ignore, &child_y, &ignore, &child_h, &ignore); + children_h = nkids * child_h; + + ratio_t = ((double) child_y) / ((double) children_h); + ratio_b = ((double) child_y + child_h) / ((double) children_h); + + if (adj->upper == 0.0) /* no items in list */ + return; + + if (ratio_t < (adj->value / adj->upper) || + ratio_b > ((adj->value + adj->page_size) / adj->upper)) + { + double target; + int slop = parent_h * 0.75; /* how much to overshoot by */ + + if (ratio_t < (adj->value / adj->upper)) + { + double ratio_w = ((double) parent_h) / ((double) children_h); + double ratio_l = (ratio_b - ratio_t); + target = ((ratio_t - ratio_w + ratio_l) * adj->upper); + target += slop; + } + else /* if (ratio_b > ((adj->value + adj->page_size) / adj->upper))*/ + { + target = ratio_t * adj->upper; + target -= slop; + } + + if (target > adj->upper - adj->page_size) + target = adj->upper - adj->page_size; + if (target < 0) + target = 0; + + gtk_adjustment_set_value (adj, target); + } +#endif /* !HAVE_GTK2 */ +} + +static void +warning_dialog_dismiss_cb (GtkWidget *widget, gpointer user_data) +{ + GtkWidget *shell = GTK_WIDGET (user_data); + while (GET_PARENT (shell)) + shell = GET_PARENT (shell); + gtk_widget_destroy (GTK_WIDGET (shell)); +} + + +void restart_menu_cb (GtkWidget *widget, gpointer user_data); + +static void warning_dialog_restart_cb (GtkWidget *widget, gpointer user_data) +{ + restart_menu_cb (widget, user_data); + warning_dialog_dismiss_cb (widget, user_data); +} + +static void warning_dialog_killg_cb (GtkWidget *widget, gpointer user_data) +{ + kill_gnome_screensaver (); + warning_dialog_dismiss_cb (widget, user_data); +} + +static void warning_dialog_killk_cb (GtkWidget *widget, gpointer user_data) +{ + kill_kde_screensaver (); + warning_dialog_dismiss_cb (widget, user_data); +} + +typedef enum { D_NONE, D_LAUNCH, D_GNOME, D_KDE } dialog_button; + +static Bool +warning_dialog (GtkWidget *parent, const char *message, + dialog_button button_type, int center) +{ + char *msg = strdup (message); + char *head; + + GtkWidget *dialog = gtk_dialog_new (); + GtkWidget *label = 0; + GtkWidget *ok = 0; + GtkWidget *cancel = 0; + int i = 0; + + while (parent && !GET_WINDOW (parent)) + parent = GET_PARENT (parent); + + if (!parent || + !GET_WINDOW (parent)) /* too early to pop up transient dialogs */ + { + fprintf (stderr, "%s: too early for dialog?\n", progname); + return False; + } + + head = msg; + while (head) + { + char name[20]; + char *s = strchr (head, '\n'); + if (s) *s = 0; + + sprintf (name, "label%d", i++); + + { + label = gtk_label_new (head); +#ifdef HAVE_GTK2 + gtk_label_set_selectable (GTK_LABEL (label), TRUE); +#endif /* HAVE_GTK2 */ + +#ifndef HAVE_GTK2 + if (i == 1) + { + GTK_WIDGET (label)->style = + gtk_style_copy (GTK_WIDGET (label)->style); + GTK_WIDGET (label)->style->font = + gdk_font_load (get_string_resource("warning_dialog.headingFont", + "Dialog.Font")); + gtk_widget_set_style (GTK_WIDGET (label), + GTK_WIDGET (label)->style); + } +#endif /* !HAVE_GTK2 */ + if (center <= 0) + gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5); + gtk_box_pack_start (GTK_BOX (GET_CONTENT_AREA (GTK_DIALOG (dialog))), + label, TRUE, TRUE, 0); + gtk_widget_show (label); + } + + if (s) + head = s+1; + else + head = 0; + + center--; + } + + label = gtk_label_new (""); + gtk_box_pack_start (GTK_BOX (GET_CONTENT_AREA (GTK_DIALOG (dialog))), + label, TRUE, TRUE, 0); + gtk_widget_show (label); + + label = gtk_hbutton_box_new (); + gtk_box_pack_start (GTK_BOX (GET_ACTION_AREA (GTK_DIALOG (dialog))), + label, TRUE, TRUE, 0); + +#ifdef HAVE_GTK2 + if (button_type != D_NONE) + { + cancel = gtk_button_new_from_stock (GTK_STOCK_CANCEL); + gtk_container_add (GTK_CONTAINER (label), cancel); + } + + ok = gtk_button_new_from_stock (GTK_STOCK_OK); + gtk_container_add (GTK_CONTAINER (label), ok); + +#else /* !HAVE_GTK2 */ + + ok = gtk_button_new_with_label ("OK"); + gtk_container_add (GTK_CONTAINER (label), ok); + + if (button_type != D_NONE) + { + cancel = gtk_button_new_with_label ("Cancel"); + gtk_container_add (GTK_CONTAINER (label), cancel); + } + +#endif /* !HAVE_GTK2 */ + + gtk_window_set_position (GTK_WINDOW (dialog), GTK_WIN_POS_CENTER); + gtk_container_set_border_width (GTK_CONTAINER (dialog), 10); + gtk_window_set_title (GTK_WINDOW (dialog), progclass); + SET_CAN_DEFAULT (ok); + gtk_widget_show (ok); + gtk_widget_grab_focus (ok); + + if (cancel) + { + SET_CAN_DEFAULT (cancel); + gtk_widget_show (cancel); + } + gtk_widget_show (label); + gtk_widget_show (dialog); + + if (button_type != D_NONE) + { + GtkSignalFunc fn; + switch (button_type) { + case D_LAUNCH: fn = GTK_SIGNAL_FUNC (warning_dialog_restart_cb); break; + case D_GNOME: fn = GTK_SIGNAL_FUNC (warning_dialog_killg_cb); break; + case D_KDE: fn = GTK_SIGNAL_FUNC (warning_dialog_killk_cb); break; + default: abort(); break; + } + gtk_signal_connect_object (GTK_OBJECT (ok), "clicked", fn, + (gpointer) dialog); + gtk_signal_connect_object (GTK_OBJECT (cancel), "clicked", + GTK_SIGNAL_FUNC (warning_dialog_dismiss_cb), + (gpointer) dialog); + } + else + { + gtk_signal_connect_object (GTK_OBJECT (ok), "clicked", + GTK_SIGNAL_FUNC (warning_dialog_dismiss_cb), + (gpointer) dialog); + } + + gdk_window_set_transient_for (GET_WINDOW (GTK_WIDGET (dialog)), + GET_WINDOW (GTK_WIDGET (parent))); + +#ifdef HAVE_GTK2 + gtk_window_present (GTK_WINDOW (dialog)); +#else /* !HAVE_GTK2 */ + gdk_window_show (GTK_WIDGET (dialog)->window); + gdk_window_raise (GTK_WIDGET (dialog)->window); +#endif /* !HAVE_GTK2 */ + + free (msg); + return True; +} + + +static void +run_cmd (state *s, Atom command, int arg) +{ + char *err = 0; + int status; + + flush_dialog_changes_and_save (s); + status = xscreensaver_command (GDK_DISPLAY(), command, arg, False, &err); + + /* Kludge: ignore the spurious "window unexpectedly deleted" errors... */ + if (status < 0 && err && strstr (err, "unexpectedly deleted")) + status = 0; + + if (status < 0) + { + char buf [255]; + if (err) + sprintf (buf, "Error:\n\n%s", err); + else + strcpy (buf, "Unknown error!"); + warning_dialog (s->toplevel_widget, buf, D_NONE, 100); + } + if (err) free (err); + + sensitize_menu_items (s, True); + force_dialog_repaint (s); +} + + +static void +run_hack (state *s, int list_elt, Bool report_errors_p) +{ + int hack_number; + char *err = 0; + int status; + + if (list_elt < 0) return; + hack_number = s->list_elt_to_hack_number[list_elt]; + + flush_dialog_changes_and_save (s); + schedule_preview (s, 0); + + status = xscreensaver_command (GDK_DISPLAY(), XA_DEMO, hack_number + 1, + False, &err); + + if (status < 0 && report_errors_p) + { + if (xscreensaver_running_p (s)) + { + /* Kludge: ignore the spurious "window unexpectedly deleted" + errors... */ + if (err && strstr (err, "unexpectedly deleted")) + status = 0; + + if (status < 0) + { + char buf [255]; + if (err) + sprintf (buf, "Error:\n\n%s", err); + else + strcpy (buf, "Unknown error!"); + warning_dialog (s->toplevel_widget, buf, D_NONE, 100); + } + } + else + { + /* The error is that the daemon isn't running; + offer to restart it. + */ + const char *d = DisplayString (GDK_DISPLAY()); + char msg [1024]; + sprintf (msg, + _("Warning:\n\n" + "The XScreenSaver daemon doesn't seem to be running\n" + "on display \"%s\". Launch it now?"), + d); + warning_dialog (s->toplevel_widget, msg, D_LAUNCH, 1); + } + } + + if (err) free (err); + + sensitize_menu_items (s, False); +} + + + +/* Button callbacks + + According to Eric Lassauge, this G_MODULE_EXPORT crud is needed to make + libglade work on Cygwin; apparently all Glade callbacks need this magic + extra declaration. I do not pretend to understand. + */ + +G_MODULE_EXPORT void +exit_menu_cb (GtkMenuItem *menuitem, gpointer user_data) +{ + state *s = global_state_kludge; /* I hate C so much... */ + flush_dialog_changes_and_save (s); + kill_preview_subproc (s, False); + gtk_main_quit (); +} + +static gboolean +wm_toplevel_close_cb (GtkWidget *widget, GdkEvent *event, gpointer data) +{ + state *s = (state *) data; + flush_dialog_changes_and_save (s); + gtk_main_quit (); + return TRUE; +} + + +G_MODULE_EXPORT void +about_menu_cb (GtkMenuItem *menuitem, gpointer user_data) +{ + char msg [2048]; + char *vers = strdup (screensaver_id + 4); + char *s; + char copy[1024]; + char *desc = _("For updates, check http://www.jwz.org/xscreensaver/"); + + s = strchr (vers, ','); + *s = 0; + s += 2; + + /* Ole Laursen says "don't use _() here because + non-ASCII characters aren't allowed in localizable string keys." + (I don't want to just use (c) instead of © because that doesn't + look as good in the plain-old default Latin1 "C" locale.) + */ +#ifdef HAVE_GTK2 + sprintf(copy, ("Copyright \xC2\xA9 1991-2008 %s"), s); +#else /* !HAVE_GTK2 */ + sprintf(copy, ("Copyright \251 1991-2008 %s"), s); +#endif /* !HAVE_GTK2 */ + + sprintf (msg, "%s\n\n%s", copy, desc); + + /* I can't make gnome_about_new() work here -- it starts dying in + gdk_imlib_get_visual() under gnome_about_new(). If this worked, + then this might be the thing to do: + + #ifdef HAVE_CRAPPLET + { + const gchar *auth[] = { 0 }; + GtkWidget *about = gnome_about_new (progclass, vers, "", auth, desc, + "xscreensaver.xpm"); + gtk_widget_show (about); + } + #else / * GTK but not GNOME * / + ... + */ + { + GdkColormap *colormap; + GdkPixmap *gdkpixmap; + GdkBitmap *mask; + + GtkWidget *dialog = gtk_dialog_new (); + GtkWidget *hbox, *icon, *vbox, *label1, *label2, *hb, *ok; + GtkWidget *parent = GTK_WIDGET (menuitem); + while (GET_PARENT (parent)) + parent = GET_PARENT (parent); + + hbox = gtk_hbox_new (FALSE, 20); + gtk_box_pack_start (GTK_BOX (GET_CONTENT_AREA (GTK_DIALOG (dialog))), + hbox, TRUE, TRUE, 0); + + colormap = gtk_widget_get_colormap (parent); + gdkpixmap = + gdk_pixmap_colormap_create_from_xpm_d (NULL, colormap, &mask, NULL, + (gchar **) logo_180_xpm); + icon = gtk_pixmap_new (gdkpixmap, mask); + gtk_misc_set_padding (GTK_MISC (icon), 10, 10); + + gtk_box_pack_start (GTK_BOX (hbox), icon, FALSE, FALSE, 0); + + vbox = gtk_vbox_new (FALSE, 0); + gtk_box_pack_start (GTK_BOX (hbox), vbox, TRUE, TRUE, 0); + + label1 = gtk_label_new (vers); + gtk_box_pack_start (GTK_BOX (vbox), label1, TRUE, TRUE, 0); + gtk_label_set_justify (GTK_LABEL (label1), GTK_JUSTIFY_LEFT); + gtk_misc_set_alignment (GTK_MISC (label1), 0.0, 0.75); + +#ifndef HAVE_GTK2 + GTK_WIDGET (label1)->style = gtk_style_copy (GTK_WIDGET (label1)->style); + GTK_WIDGET (label1)->style->font = + gdk_font_load (get_string_resource ("about.headingFont","Dialog.Font")); + gtk_widget_set_style (GTK_WIDGET (label1), GTK_WIDGET (label1)->style); +#endif /* HAVE_GTK2 */ + + label2 = gtk_label_new (msg); + gtk_box_pack_start (GTK_BOX (vbox), label2, TRUE, TRUE, 0); + gtk_label_set_justify (GTK_LABEL (label2), GTK_JUSTIFY_LEFT); + gtk_misc_set_alignment (GTK_MISC (label2), 0.0, 0.25); + +#ifndef HAVE_GTK2 + GTK_WIDGET (label2)->style = gtk_style_copy (GTK_WIDGET (label2)->style); + GTK_WIDGET (label2)->style->font = + gdk_font_load (get_string_resource ("about.bodyFont","Dialog.Font")); + gtk_widget_set_style (GTK_WIDGET (label2), GTK_WIDGET (label2)->style); +#endif /* HAVE_GTK2 */ + + hb = gtk_hbutton_box_new (); + + gtk_box_pack_start (GTK_BOX (GET_ACTION_AREA (GTK_DIALOG (dialog))), + hb, TRUE, TRUE, 0); + +#ifdef HAVE_GTK2 + ok = gtk_button_new_from_stock (GTK_STOCK_OK); +#else /* !HAVE_GTK2 */ + ok = gtk_button_new_with_label (_("OK")); +#endif /* !HAVE_GTK2 */ + gtk_container_add (GTK_CONTAINER (hb), ok); + + gtk_window_set_position (GTK_WINDOW (dialog), GTK_WIN_POS_CENTER); + gtk_container_set_border_width (GTK_CONTAINER (dialog), 10); + gtk_window_set_title (GTK_WINDOW (dialog), progclass); + + gtk_widget_show (hbox); + gtk_widget_show (icon); + gtk_widget_show (vbox); + gtk_widget_show (label1); + gtk_widget_show (label2); + gtk_widget_show (hb); + gtk_widget_show (ok); + gtk_widget_show (dialog); + + gtk_signal_connect_object (GTK_OBJECT (ok), "clicked", + GTK_SIGNAL_FUNC (warning_dialog_dismiss_cb), + (gpointer) dialog); + gdk_window_set_transient_for (GET_WINDOW (GTK_WIDGET (dialog)), + GET_WINDOW (GTK_WIDGET (parent))); + gdk_window_show (GET_WINDOW (GTK_WIDGET (dialog))); + gdk_window_raise (GET_WINDOW (GTK_WIDGET (dialog))); + } +} + + +G_MODULE_EXPORT void +doc_menu_cb (GtkMenuItem *menuitem, gpointer user_data) +{ + state *s = global_state_kludge; /* I hate C so much... */ + saver_preferences *p = &s->prefs; + char *help_command; + + if (!p->help_url || !*p->help_url) + { + warning_dialog (s->toplevel_widget, + _("Error:\n\n" + "No Help URL has been specified.\n"), D_NONE, 100); + return; + } + + help_command = (char *) malloc (strlen (p->load_url_command) + + (strlen (p->help_url) * 4) + 20); + strcpy (help_command, "( "); + sprintf (help_command + strlen(help_command), + p->load_url_command, + p->help_url, p->help_url, p->help_url, p->help_url); + strcat (help_command, " ) &"); + if (system (help_command) < 0) + fprintf (stderr, "%s: fork error\n", blurb()); + free (help_command); +} + + +G_MODULE_EXPORT void +file_menu_cb (GtkMenuItem *menuitem, gpointer user_data) +{ + state *s = global_state_kludge; /* I hate C so much... */ + sensitize_menu_items (s, False); +} + + +G_MODULE_EXPORT void +activate_menu_cb (GtkMenuItem *menuitem, gpointer user_data) +{ + state *s = global_state_kludge; /* I hate C so much... */ + run_cmd (s, XA_ACTIVATE, 0); +} + + +G_MODULE_EXPORT void +lock_menu_cb (GtkMenuItem *menuitem, gpointer user_data) +{ + state *s = global_state_kludge; /* I hate C so much... */ + run_cmd (s, XA_LOCK, 0); +} + + +G_MODULE_EXPORT void +kill_menu_cb (GtkMenuItem *menuitem, gpointer user_data) +{ + state *s = global_state_kludge; /* I hate C so much... */ + run_cmd (s, XA_EXIT, 0); +} + + +G_MODULE_EXPORT void +restart_menu_cb (GtkWidget *widget, gpointer user_data) +{ + state *s = global_state_kludge; /* I hate C so much... */ + flush_dialog_changes_and_save (s); + xscreensaver_command (GDK_DISPLAY(), XA_EXIT, 0, False, NULL); + sleep (1); + if (system ("xscreensaver -nosplash &") < 0) + fprintf (stderr, "%s: fork error\n", blurb()); + + await_xscreensaver (s); +} + +static Bool +xscreensaver_running_p (state *s) +{ + Display *dpy = GDK_DISPLAY(); + char *rversion = 0; + server_xscreensaver_version (dpy, &rversion, 0, 0); + if (!rversion) + return False; + free (rversion); + return True; +} + +static void +await_xscreensaver (state *s) +{ + int countdown = 5; + Bool ok = False; + + while (!ok && (--countdown > 0)) + if (xscreensaver_running_p (s)) + ok = True; + else + sleep (1); /* If it's not there yet, wait a second... */ + + sensitize_menu_items (s, True); + + if (! ok) + { + /* Timed out, no screensaver running. */ + + char buf [1024]; + Bool root_p = (geteuid () == 0); + + strcpy (buf, + _("Error:\n\n" + "The xscreensaver daemon did not start up properly.\n" + "\n")); + + if (root_p) + +# ifdef __GNUC__ + __extension__ /* don't warn about "string length is greater than + the length ISO C89 compilers are required to + support" in the following expression... */ +# endif + strcat (buf, STFU + _("You are running as root. This usually means that xscreensaver\n" + "was unable to contact your X server because access control is\n" + "turned on. Try running this command:\n" + "\n" + " xhost +localhost\n" + "\n" + "and then selecting `File / Restart Daemon'.\n" + "\n" + "Note that turning off access control will allow anyone logged\n" + "on to this machine to access your screen, which might be\n" + "considered a security problem. Please read the xscreensaver\n" + "manual and FAQ for more information.\n" + "\n" + "You shouldn't run X as root. Instead, you should log in as a\n" + "normal user, and `su' as necessary.")); + else + strcat (buf, _("Please check your $PATH and permissions.")); + + warning_dialog (s->toplevel_widget, buf, D_NONE, 1); + } + + force_dialog_repaint (s); +} + + +static int +selected_list_element (state *s) +{ + return s->_selected_list_element; +} + + +static int +demo_write_init_file (state *s, saver_preferences *p) +{ + Display *dpy = GDK_DISPLAY(); + +#if 0 + /* #### try to figure out why shit keeps getting reordered... */ + if (strcmp (s->prefs.screenhacks[0]->name, "DNA Lounge Slideshow")) + abort(); +#endif + + if (!write_init_file (dpy, p, s->short_version, False)) + { + if (s->debug_p) + fprintf (stderr, "%s: wrote %s\n", blurb(), init_file_name()); + return 0; + } + else + { + const char *f = init_file_name(); + if (!f || !*f) + warning_dialog (s->toplevel_widget, + _("Error:\n\nCouldn't determine init file name!\n"), + D_NONE, 100); + else + { + char *b = (char *) malloc (strlen(f) + 1024); + sprintf (b, _("Error:\n\nCouldn't write %s\n"), f); + warning_dialog (s->toplevel_widget, b, D_NONE, 100); + free (b); + } + return -1; + } +} + + +G_MODULE_EXPORT void +run_this_cb (GtkButton *button, gpointer user_data) +{ + state *s = global_state_kludge; /* I hate C so much... */ + int list_elt = selected_list_element (s); + if (list_elt < 0) return; + if (!flush_dialog_changes_and_save (s)) + run_hack (s, list_elt, True); +} + + +G_MODULE_EXPORT void +manual_cb (GtkButton *button, gpointer user_data) +{ + Display *dpy = GDK_DISPLAY(); + state *s = global_state_kludge; /* I hate C so much... */ + saver_preferences *p = &s->prefs; + GtkWidget *list_widget = name_to_widget (s, "list"); + int list_elt = selected_list_element (s); + int hack_number; + char *name, *name2, *cmd, *str; + char *oname = 0; + if (list_elt < 0) return; + hack_number = s->list_elt_to_hack_number[list_elt]; + + flush_dialog_changes_and_save (s); + ensure_selected_item_visible (list_widget); + + name = strdup (p->screenhacks[hack_number]->command); + name2 = name; + oname = name; + while (isspace (*name2)) name2++; + str = name2; + while (*str && !isspace (*str)) str++; + *str = 0; + str = strrchr (name2, '/'); + if (str) name2 = str+1; + + cmd = get_string_resource (dpy, "manualCommand", "ManualCommand"); + if (cmd) + { + char *cmd2 = (char *) malloc (strlen (cmd) + (strlen (name2) * 4) + 100); + strcpy (cmd2, "( "); + sprintf (cmd2 + strlen (cmd2), + cmd, + name2, name2, name2, name2); + strcat (cmd2, " ) &"); + if (system (cmd2) < 0) + fprintf (stderr, "%s: fork error\n", blurb()); + free (cmd2); + } + else + { + warning_dialog (GTK_WIDGET (button), + _("Error:\n\nno `manualCommand' resource set."), + D_NONE, 100); + } + + free (oname); +} + + +static void +force_list_select_item (state *s, GtkWidget *list, int list_elt, Bool scroll_p) +{ + GtkWidget *parent = name_to_widget (s, "scroller"); + gboolean was = GET_SENSITIVE (parent); +#ifdef HAVE_GTK2 + GtkTreeIter iter; + GtkTreeModel *model; + GtkTreeSelection *selection; +#endif /* HAVE_GTK2 */ + + if (!was) gtk_widget_set_sensitive (parent, True); +#ifdef HAVE_GTK2 + model = gtk_tree_view_get_model (GTK_TREE_VIEW (list)); + g_assert (model); + if (gtk_tree_model_iter_nth_child (model, &iter, NULL, list_elt)) + { + selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (list)); + gtk_tree_selection_select_iter (selection, &iter); + } +#else /* !HAVE_GTK2 */ + gtk_list_select_item (GTK_LIST (list), list_elt); +#endif /* !HAVE_GTK2 */ + if (scroll_p) ensure_selected_item_visible (GTK_WIDGET (list)); + if (!was) gtk_widget_set_sensitive (parent, False); +} + + +G_MODULE_EXPORT void +run_next_cb (GtkButton *button, gpointer user_data) +{ + state *s = global_state_kludge; /* I hate C so much... */ + /* saver_preferences *p = &s->prefs; */ + Bool ops = s->preview_suppressed_p; + + GtkWidget *list_widget = name_to_widget (s, "list"); + int list_elt = selected_list_element (s); + + if (list_elt < 0) + list_elt = 0; + else + list_elt++; + + if (list_elt >= s->list_count) + list_elt = 0; + + s->preview_suppressed_p = True; + + flush_dialog_changes_and_save (s); + force_list_select_item (s, list_widget, list_elt, True); + populate_demo_window (s, list_elt); + run_hack (s, list_elt, False); + + s->preview_suppressed_p = ops; +} + + +G_MODULE_EXPORT void +run_prev_cb (GtkButton *button, gpointer user_data) +{ + state *s = global_state_kludge; /* I hate C so much... */ + /* saver_preferences *p = &s->prefs; */ + Bool ops = s->preview_suppressed_p; + + GtkWidget *list_widget = name_to_widget (s, "list"); + int list_elt = selected_list_element (s); + + if (list_elt < 0) + list_elt = s->list_count - 1; + else + list_elt--; + + if (list_elt < 0) + list_elt = s->list_count - 1; + + s->preview_suppressed_p = True; + + flush_dialog_changes_and_save (s); + force_list_select_item (s, list_widget, list_elt, True); + populate_demo_window (s, list_elt); + run_hack (s, list_elt, False); + + s->preview_suppressed_p = ops; +} + + +/* Writes the given settings into prefs. + Returns true if there was a change, False otherwise. + command and/or visual may be 0, or enabled_p may be -1, meaning "no change". + */ +static Bool +flush_changes (state *s, + int list_elt, + int enabled_p, + const char *command, + const char *visual) +{ + saver_preferences *p = &s->prefs; + Bool changed = False; + screenhack *hack; + int hack_number; + if (list_elt < 0 || list_elt >= s->list_count) + abort(); + + hack_number = s->list_elt_to_hack_number[list_elt]; + hack = p->screenhacks[hack_number]; + + if (enabled_p != -1 && + enabled_p != hack->enabled_p) + { + hack->enabled_p = enabled_p; + changed = True; + if (s->debug_p) + fprintf (stderr, "%s: \"%s\": enabled => %d\n", + blurb(), hack->name, enabled_p); + } + + if (command) + { + if (!hack->command || !!strcmp (command, hack->command)) + { + if (hack->command) free (hack->command); + hack->command = strdup (command); + changed = True; + if (s->debug_p) + fprintf (stderr, "%s: \"%s\": command => \"%s\"\n", + blurb(), hack->name, command); + } + } + + if (visual) + { + const char *ov = hack->visual; + if (!ov || !*ov) ov = "any"; + if (!*visual) visual = "any"; + if (!!strcasecmp (visual, ov)) + { + if (hack->visual) free (hack->visual); + hack->visual = strdup (visual); + changed = True; + if (s->debug_p) + fprintf (stderr, "%s: \"%s\": visual => \"%s\"\n", + blurb(), hack->name, visual); + } + } + + return changed; +} + + +/* Helper for the text fields that contain time specifications: + this parses the text, and does error checking. + */ +static void +hack_time_text (state *s, const char *line, Time *store, Bool sec_p) +{ + if (*line) + { + int value; + if (!sec_p || strchr (line, ':')) + value = parse_time ((char *) line, sec_p, True); + else + { + char c; + if (sscanf (line, "%d%c", &value, &c) != 1) + value = -1; + if (!sec_p) + value *= 60; + } + + value *= 1000; /* Time measures in microseconds */ + if (value < 0) + { + char b[255]; + sprintf (b, + _("Error:\n\n" + "Unparsable time format: \"%s\"\n"), + line); + warning_dialog (s->toplevel_widget, b, D_NONE, 100); + } + else + *store = value; + } +} + + +static Bool +directory_p (const char *path) +{ + struct stat st; + if (!path || !*path) + return False; + else if (stat (path, &st)) + return False; + else if (!S_ISDIR (st.st_mode)) + return False; + else + return True; +} + +static Bool +file_p (const char *path) +{ + struct stat st; + if (!path || !*path) + return False; + else if (stat (path, &st)) + return False; + else if (S_ISDIR (st.st_mode)) + return False; + else + return True; +} + +static char * +normalize_directory (const char *path) +{ + int L; + char *p2, *s; + if (!path || !*path) return 0; + L = strlen (path); + p2 = (char *) malloc (L + 2); + strcpy (p2, path); + if (p2[L-1] == '/') /* remove trailing slash */ + p2[--L] = 0; + + for (s = p2; s && *s; s++) + { + if (*s == '/' && + (!strncmp (s, "/../", 4) || /* delete "XYZ/../" */ + !strncmp (s, "/..\000", 4))) /* delete "XYZ/..$" */ + { + char *s0 = s; + while (s0 > p2 && s0[-1] != '/') + s0--; + if (s0 > p2) + { + s0--; + s += 3; + /* strcpy (s0, s); */ + memmove(s0, s, strlen(s) + 1); + s = s0-1; + } + } + else if (*s == '/' && !strncmp (s, "/./", 3)) { /* delete "/./" */ + /* strcpy (s, s+2), s--; */ + memmove(s, s+2, strlen(s+2) + 1); + s--; + } + else if (*s == '/' && !strncmp (s, "/.\000", 3)) /* delete "/.$" */ + *s = 0, s--; + } + + /* + Normalize consecutive slashes. + Ignore doubled slashes after ":" to avoid mangling URLs. + */ + + for (s = p2; s && *s; s++){ + if (*s == ':') continue; + if (!s[1] || !s[2]) continue; + while (s[1] == '/' && s[2] == '/') + /* strcpy (s+1, s+2); */ + memmove (s+1, s+2, strlen(s+2) + 1); + } + + /* and strip trailing whitespace for good measure. */ + L = strlen(p2); + while (isspace(p2[L-1])) + p2[--L] = 0; + + return p2; +} + + +#ifdef HAVE_GTK2 + +typedef struct { + state *s; + int i; + Bool *changed; +} FlushForeachClosure; + +static gboolean +flush_checkbox (GtkTreeModel *model, + GtkTreePath *path, + GtkTreeIter *iter, + gpointer data) +{ + FlushForeachClosure *closure = data; + gboolean checked; + + gtk_tree_model_get (model, iter, + COL_ENABLED, &checked, + -1); + + if (flush_changes (closure->s, closure->i, + checked, 0, 0)) + *closure->changed = True; + + closure->i++; + + /* don't remove row */ + return FALSE; +} + +#endif /* HAVE_GTK2 */ + +/* Flush out any changes made in the main dialog window (where changes + take place immediately: clicking on a checkbox causes the init file + to be written right away.) + */ +static Bool +flush_dialog_changes_and_save (state *s) +{ + saver_preferences *p = &s->prefs; + saver_preferences P2, *p2 = &P2; +#ifdef HAVE_GTK2 + GtkTreeView *list_widget = GTK_TREE_VIEW (name_to_widget (s, "list")); + GtkTreeModel *model = gtk_tree_view_get_model (list_widget); + FlushForeachClosure closure; +#else /* !HAVE_GTK2 */ + GtkList *list_widget = GTK_LIST (name_to_widget (s, "list")); + GList *kids = gtk_container_children (GTK_CONTAINER (list_widget)); + int i; +#endif /* !HAVE_GTK2 */ + static Bool already_warned_about_missing_image_directory = False; /* very long name... */ + + Bool changed = False; + GtkWidget *w; + + if (s->saving_p) return False; + s->saving_p = True; + + *p2 = *p; + + /* Flush any checkbox changes in the list down into the prefs struct. + */ +#ifdef HAVE_GTK2 + closure.s = s; + closure.changed = &changed; + closure.i = 0; + gtk_tree_model_foreach (model, flush_checkbox, &closure); + +#else /* !HAVE_GTK2 */ + + for (i = 0; kids; kids = kids->next, i++) + { + GtkWidget *line = GTK_WIDGET (kids->data); + GtkWidget *line_hbox = GTK_WIDGET (GTK_BIN (line)->child); + GtkWidget *line_check = + GTK_WIDGET (gtk_container_children (GTK_CONTAINER (line_hbox))->data); + Bool checked = + gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (line_check)); + + if (flush_changes (s, i, (checked ? 1 : 0), 0, 0)) + changed = True; + } +#endif /* ~HAVE_GTK2 */ + + /* Flush the non-hack-specific settings down into the prefs struct. + */ + +# define SECONDS(FIELD,NAME) \ + w = name_to_widget (s, (NAME)); \ + hack_time_text (s, gtk_entry_get_text (GTK_ENTRY (w)), (FIELD), True) + +# define MINUTES(FIELD,NAME) \ + w = name_to_widget (s, (NAME)); \ + hack_time_text (s, gtk_entry_get_text (GTK_ENTRY (w)), (FIELD), False) + +# define CHECKBOX(FIELD,NAME) \ + w = name_to_widget (s, (NAME)); \ + (FIELD) = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (w)) + +# define PATHNAME(FIELD,NAME) \ + w = name_to_widget (s, (NAME)); \ + (FIELD) = normalize_directory (gtk_entry_get_text (GTK_ENTRY (w))) + +# define TEXT(FIELD,NAME) \ + w = name_to_widget (s, (NAME)); \ + (FIELD) = (char *) gtk_entry_get_text (GTK_ENTRY (w)) + + MINUTES (&p2->timeout, "timeout_spinbutton"); + MINUTES (&p2->cycle, "cycle_spinbutton"); + CHECKBOX (p2->lock_p, "lock_button"); + MINUTES (&p2->lock_timeout, "lock_spinbutton"); + + CHECKBOX (p2->dpms_enabled_p, "dpms_button"); + CHECKBOX (p2->dpms_quickoff_p, "dpms_quickoff_button"); + MINUTES (&p2->dpms_standby, "dpms_standby_spinbutton"); + MINUTES (&p2->dpms_suspend, "dpms_suspend_spinbutton"); + MINUTES (&p2->dpms_off, "dpms_off_spinbutton"); + + CHECKBOX (p2->grab_desktop_p, "grab_desk_button"); + CHECKBOX (p2->grab_video_p, "grab_video_button"); + CHECKBOX (p2->random_image_p, "grab_image_button"); + PATHNAME (p2->image_directory, "image_text"); + +#if 0 + CHECKBOX (p2->verbose_p, "verbose_button"); + CHECKBOX (p2->capture_stderr_p, "capture_button"); + CHECKBOX (p2->splash_p, "splash_button"); +#endif + + { + Bool v = False; + CHECKBOX (v, "text_host_radio"); if (v) p2->tmode = TEXT_DATE; + CHECKBOX (v, "text_radio"); if (v) p2->tmode = TEXT_LITERAL; + CHECKBOX (v, "text_file_radio"); if (v) p2->tmode = TEXT_FILE; + CHECKBOX (v, "text_program_radio"); if (v) p2->tmode = TEXT_PROGRAM; + CHECKBOX (v, "text_url_radio"); if (v) p2->tmode = TEXT_URL; + TEXT (p2->text_literal, "text_entry"); + PATHNAME (p2->text_file, "text_file_entry"); + PATHNAME (p2->text_program, "text_program_entry"); + PATHNAME (p2->text_program, "text_program_entry"); + TEXT (p2->text_url, "text_url_entry"); + } + + CHECKBOX (p2->install_cmap_p, "install_button"); + CHECKBOX (p2->fade_p, "fade_button"); + CHECKBOX (p2->unfade_p, "unfade_button"); + SECONDS (&p2->fade_seconds, "fade_spinbutton"); + +# undef SECONDS +# undef MINUTES +# undef CHECKBOX +# undef PATHNAME +# undef TEXT + + /* Warn if the image directory doesn't exist, when: + - not being warned before + - image directory is changed and the directory doesn't exist + - image directory does not begin with http:// + */ + if (p2->image_directory && + *p2->image_directory && + !directory_p (p2->image_directory) && + strncmp(p2->image_directory, "http://", 6) && + ( !already_warned_about_missing_image_directory || + ( p->image_directory && + *p->image_directory && + strcmp(p->image_directory, p2->image_directory) + ) + ) + ) + { + char b[255]; + sprintf (b, "Warning:\n\n" "Directory does not exist: \"%s\"\n", + p2->image_directory); + if (warning_dialog (s->toplevel_widget, b, D_NONE, 100)) + already_warned_about_missing_image_directory = True; + } + + + /* Map the mode menu to `saver_mode' enum values. */ + { + GtkOptionMenu *opt = GTK_OPTION_MENU (name_to_widget (s, "mode_menu")); + GtkMenu *menu = GTK_MENU (gtk_option_menu_get_menu (opt)); + GtkWidget *selected = gtk_menu_get_active (menu); + GList *kids = gtk_container_children (GTK_CONTAINER (menu)); + int menu_elt = g_list_index (kids, (gpointer) selected); + if (menu_elt < 0 || menu_elt >= countof(mode_menu_order)) abort(); + p2->mode = mode_menu_order[menu_elt]; + } + + if (p2->mode == ONE_HACK) + { + int list_elt = selected_list_element (s); + p2->selected_hack = (list_elt >= 0 + ? s->list_elt_to_hack_number[list_elt] + : -1); + } + +# define COPY(field, name) \ + if (p->field != p2->field) { \ + changed = True; \ + if (s->debug_p) \ + fprintf (stderr, "%s: %s => %d\n", blurb(), name, (int) p2->field); \ + } \ + p->field = p2->field + + COPY(mode, "mode"); + COPY(selected_hack, "selected_hack"); + + COPY(timeout, "timeout"); + COPY(cycle, "cycle"); + COPY(lock_p, "lock_p"); + COPY(lock_timeout, "lock_timeout"); + + COPY(dpms_enabled_p, "dpms_enabled_p"); + COPY(dpms_quickoff_p, "dpms_quickoff_enabled_p"); + COPY(dpms_standby, "dpms_standby"); + COPY(dpms_suspend, "dpms_suspend"); + COPY(dpms_off, "dpms_off"); + +#if 0 + COPY(verbose_p, "verbose_p"); + COPY(capture_stderr_p, "capture_stderr_p"); + COPY(splash_p, "splash_p"); +#endif + + COPY(tmode, "tmode"); + + COPY(install_cmap_p, "install_cmap_p"); + COPY(fade_p, "fade_p"); + COPY(unfade_p, "unfade_p"); + COPY(fade_seconds, "fade_seconds"); + + COPY(grab_desktop_p, "grab_desktop_p"); + COPY(grab_video_p, "grab_video_p"); + COPY(random_image_p, "random_image_p"); + +# undef COPY + +# define COPYSTR(FIELD,NAME) \ + if (!p->FIELD || \ + !p2->FIELD || \ + strcmp(p->FIELD, p2->FIELD)) \ + { \ + changed = True; \ + if (s->debug_p) \ + fprintf (stderr, "%s: %s => \"%s\"\n", blurb(), NAME, p2->FIELD); \ + } \ + if (p->FIELD && p->FIELD != p2->FIELD) \ + free (p->FIELD); \ + p->FIELD = p2->FIELD; \ + p2->FIELD = 0 + + COPYSTR(image_directory, "image_directory"); + COPYSTR(text_literal, "text_literal"); + COPYSTR(text_file, "text_file"); + COPYSTR(text_program, "text_program"); + COPYSTR(text_url, "text_url"); +# undef COPYSTR + + populate_prefs_page (s); + + if (changed) + { + Display *dpy = GDK_DISPLAY(); + Bool enabled_p = (p->dpms_enabled_p && p->mode != DONT_BLANK); + sync_server_dpms_settings (dpy, enabled_p, + p->dpms_standby / 1000, + p->dpms_suspend / 1000, + p->dpms_off / 1000, + False); + + changed = demo_write_init_file (s, p); + } + + s->saving_p = False; + return changed; +} + + +/* Flush out any changes made in the popup dialog box (where changes + take place only when the OK button is clicked.) + */ +static Bool +flush_popup_changes_and_save (state *s) +{ + Bool changed = False; + saver_preferences *p = &s->prefs; + int list_elt = selected_list_element (s); + + GtkEntry *cmd = GTK_ENTRY (name_to_widget (s, "cmd_text")); + GtkCombo *vis = GTK_COMBO (name_to_widget (s, "visual_combo")); + + const char *visual = gtk_entry_get_text (GTK_ENTRY (GTK_COMBO (vis)->entry)); + const char *command = gtk_entry_get_text (cmd); + + char c; + unsigned long id; + + if (s->saving_p) return False; + s->saving_p = True; + + if (list_elt < 0) + goto DONE; + + if (maybe_reload_init_file (s) != 0) + { + changed = True; + goto DONE; + } + + /* Sanity-check and canonicalize whatever the user typed into the combo box. + */ + if (!strcasecmp (visual, "")) visual = ""; + else if (!strcasecmp (visual, "any")) visual = ""; + else if (!strcasecmp (visual, "default")) visual = "Default"; + else if (!strcasecmp (visual, "default-n")) visual = "Default-N"; + else if (!strcasecmp (visual, "default-i")) visual = "Default-I"; + else if (!strcasecmp (visual, "best")) visual = "Best"; + else if (!strcasecmp (visual, "mono")) visual = "Mono"; + else if (!strcasecmp (visual, "monochrome")) visual = "Mono"; + else if (!strcasecmp (visual, "gray")) visual = "Gray"; + else if (!strcasecmp (visual, "grey")) visual = "Gray"; + else if (!strcasecmp (visual, "color")) visual = "Color"; + else if (!strcasecmp (visual, "gl")) visual = "GL"; + else if (!strcasecmp (visual, "staticgray")) visual = "StaticGray"; + else if (!strcasecmp (visual, "staticcolor")) visual = "StaticColor"; + else if (!strcasecmp (visual, "truecolor")) visual = "TrueColor"; + else if (!strcasecmp (visual, "grayscale")) visual = "GrayScale"; + else if (!strcasecmp (visual, "greyscale")) visual = "GrayScale"; + else if (!strcasecmp (visual, "pseudocolor")) visual = "PseudoColor"; + else if (!strcasecmp (visual, "directcolor")) visual = "DirectColor"; + else if (1 == sscanf (visual, " %lu %c", &id, &c)) ; + else if (1 == sscanf (visual, " 0x%lx %c", &id, &c)) ; + else + { + gdk_beep (); /* unparsable */ + visual = ""; + gtk_entry_set_text (GTK_ENTRY (GTK_COMBO (vis)->entry), _("Any")); + } + + changed = flush_changes (s, list_elt, -1, command, visual); + if (changed) + { + changed = demo_write_init_file (s, p); + + /* Do this to re-launch the hack if (and only if) the command line + has changed. */ + populate_demo_window (s, selected_list_element (s)); + } + + DONE: + s->saving_p = False; + return changed; +} + + +G_MODULE_EXPORT void +pref_changed_cb (GtkWidget *widget, gpointer user_data) +{ + state *s = global_state_kludge; /* I hate C so much... */ + if (! s->initializing_p) + { + s->initializing_p = True; + flush_dialog_changes_and_save (s); + s->initializing_p = False; + } +} + +G_MODULE_EXPORT gboolean +pref_changed_event_cb (GtkWidget *widget, GdkEvent *event, gpointer user_data) +{ + pref_changed_cb (widget, user_data); + return FALSE; +} + +/* Callback on menu items in the "mode" options menu. + */ +G_MODULE_EXPORT void +mode_menu_item_cb (GtkWidget *widget, gpointer user_data) +{ + state *s = (state *) user_data; + saver_preferences *p = &s->prefs; + GtkWidget *list = name_to_widget (s, "list"); + int list_elt; + + GList *menu_items = + gtk_container_children (GTK_CONTAINER (GET_PARENT (widget))); + int menu_index = 0; + saver_mode new_mode; + + while (menu_items) + { + if (menu_items->data == widget) + break; + menu_index++; + menu_items = menu_items->next; + } + if (!menu_items) abort(); + + new_mode = mode_menu_order[menu_index]; + + /* Keep the same list element displayed as before; except if we're + switching *to* "one screensaver" mode from any other mode, set + "the one" to be that which is currently selected. + */ + list_elt = selected_list_element (s); + if (new_mode == ONE_HACK) + p->selected_hack = s->list_elt_to_hack_number[list_elt]; + + { + saver_mode old_mode = p->mode; + p->mode = new_mode; + populate_demo_window (s, list_elt); + force_list_select_item (s, list, list_elt, True); + p->mode = old_mode; /* put it back, so the init file gets written */ + } + + pref_changed_cb (widget, user_data); +} + + +G_MODULE_EXPORT void +switch_page_cb (GtkNotebook *notebook, GtkNotebookPage *page, + gint page_num, gpointer user_data) +{ + state *s = global_state_kludge; /* I hate C so much... */ + pref_changed_cb (GTK_WIDGET (notebook), user_data); + + /* If we're switching to page 0, schedule the current hack to be run. + Otherwise, schedule it to stop. */ + if (page_num == 0) + populate_demo_window (s, selected_list_element (s)); + else + schedule_preview (s, 0); +} + +#ifdef HAVE_GTK2 +static void +list_activated_cb (GtkTreeView *list, + GtkTreePath *path, + GtkTreeViewColumn *column, + gpointer data) +{ + state *s = data; + char *str; + int list_elt; + + g_return_if_fail (!gdk_pointer_is_grabbed ()); + + str = gtk_tree_path_to_string (path); + list_elt = strtol (str, NULL, 10); + g_free (str); + + if (list_elt >= 0) + run_hack (s, list_elt, True); +} + +static void +list_select_changed_cb (GtkTreeSelection *selection, gpointer data) +{ + state *s = (state *)data; + GtkTreeModel *model; + GtkTreeIter iter; + GtkTreePath *path; + char *str; + int list_elt; + + if (!gtk_tree_selection_get_selected (selection, &model, &iter)) + return; + + path = gtk_tree_model_get_path (model, &iter); + str = gtk_tree_path_to_string (path); + list_elt = strtol (str, NULL, 10); + + gtk_tree_path_free (path); + g_free (str); + + populate_demo_window (s, list_elt); + flush_dialog_changes_and_save (s); + + /* Re-populate the Settings window any time a new item is selected + in the list, in case both windows are currently visible. + */ + populate_popup_window (s); +} + +#else /* !HAVE_GTK2 */ + +static time_t last_doubleclick_time = 0; /* FMH! This is to suppress the + list_select_cb that comes in + *after* we've double-clicked. + */ + +static gint +list_doubleclick_cb (GtkWidget *button, GdkEventButton *event, + gpointer data) +{ + state *s = (state *) data; + if (event->type == GDK_2BUTTON_PRESS) + { + GtkList *list = GTK_LIST (name_to_widget (s, "list")); + int list_elt = gtk_list_child_position (list, GTK_WIDGET (button)); + + last_doubleclick_time = time ((time_t *) 0); + + if (list_elt >= 0) + run_hack (s, list_elt, True); + } + + return FALSE; +} + + +static void +list_select_cb (GtkList *list, GtkWidget *child, gpointer data) +{ + state *s = (state *) data; + time_t now = time ((time_t *) 0); + + if (now >= last_doubleclick_time + 2) + { + int list_elt = gtk_list_child_position (list, GTK_WIDGET (child)); + populate_demo_window (s, list_elt); + flush_dialog_changes_and_save (s); + } +} + +static void +list_unselect_cb (GtkList *list, GtkWidget *child, gpointer data) +{ + state *s = (state *) data; + populate_demo_window (s, -1); + flush_dialog_changes_and_save (s); +} + +#endif /* !HAVE_GTK2 */ + + +/* Called when the checkboxes that are in the left column of the + scrolling list are clicked. This both populates the right pane + (just as clicking on the label (really, listitem) does) and + also syncs this checkbox with the right pane Enabled checkbox. + */ +static void +list_checkbox_cb ( +#ifdef HAVE_GTK2 + GtkCellRendererToggle *toggle, + gchar *path_string, +#else /* !HAVE_GTK2 */ + GtkWidget *cb, +#endif /* !HAVE_GTK2 */ + gpointer data) +{ + state *s = (state *) data; + +#ifdef HAVE_GTK2 + GtkScrolledWindow *scroller = + GTK_SCROLLED_WINDOW (name_to_widget (s, "scroller")); + GtkTreeView *list = GTK_TREE_VIEW (name_to_widget (s, "list")); + GtkTreeModel *model = gtk_tree_view_get_model (list); + GtkTreePath *path = gtk_tree_path_new_from_string (path_string); + GtkTreeIter iter; + gboolean active; +#else /* !HAVE_GTK2 */ + GtkWidget *line_hbox = GTK_WIDGET (cb)->parent; + GtkWidget *line = GTK_WIDGET (line_hbox)->parent; + + GtkList *list = GTK_LIST (GTK_WIDGET (line)->parent); + GtkViewport *vp = GTK_VIEWPORT (GTK_WIDGET (list)->parent); + GtkScrolledWindow *scroller = GTK_SCROLLED_WINDOW (GTK_WIDGET (vp)->parent); +#endif /* !HAVE_GTK2 */ + GtkAdjustment *adj; + double scroll_top; + + int list_elt; + +#ifdef HAVE_GTK2 + if (!gtk_tree_model_get_iter (model, &iter, path)) + { + g_warning ("bad path: %s", path_string); + return; + } + gtk_tree_path_free (path); + + gtk_tree_model_get (model, &iter, + COL_ENABLED, &active, + -1); + + gtk_list_store_set (GTK_LIST_STORE (model), &iter, + COL_ENABLED, !active, + -1); + + list_elt = strtol (path_string, NULL, 10); +#else /* !HAVE_GTK2 */ + list_elt = gtk_list_child_position (list, line); +#endif /* !HAVE_GTK2 */ + + /* remember previous scroll position of the top of the list */ + adj = gtk_scrolled_window_get_vadjustment (scroller); + scroll_top = GET_ADJ_VALUE (adj); + + flush_dialog_changes_and_save (s); + force_list_select_item (s, GTK_WIDGET (list), list_elt, False); + populate_demo_window (s, list_elt); + + /* restore the previous scroll position of the top of the list. + this is weak, but I don't really know why it's moving... */ + gtk_adjustment_set_value (adj, scroll_top); +} + + +typedef struct { + state *state; + GtkFileSelection *widget; +} file_selection_data; + + + +static void +store_image_directory (GtkWidget *button, gpointer user_data) +{ + file_selection_data *fsd = (file_selection_data *) user_data; + state *s = fsd->state; + GtkFileSelection *selector = fsd->widget; + GtkWidget *top = s->toplevel_widget; + saver_preferences *p = &s->prefs; + const char *path = gtk_file_selection_get_filename (selector); + + if (p->image_directory && !strcmp(p->image_directory, path)) + return; /* no change */ + + /* No warning for URLs. */ + if ((!directory_p (path)) && strncmp(path, "http://", 6)) + { + char b[255]; + sprintf (b, _("Error:\n\n" "Directory does not exist: \"%s\"\n"), path); + warning_dialog (GTK_WIDGET (top), b, D_NONE, 100); + return; + } + + if (p->image_directory) free (p->image_directory); + p->image_directory = normalize_directory (path); + + gtk_entry_set_text (GTK_ENTRY (name_to_widget (s, "image_text")), + (p->image_directory ? p->image_directory : "")); + demo_write_init_file (s, p); +} + + +static void +store_text_file (GtkWidget *button, gpointer user_data) +{ + file_selection_data *fsd = (file_selection_data *) user_data; + state *s = fsd->state; + GtkFileSelection *selector = fsd->widget; + GtkWidget *top = s->toplevel_widget; + saver_preferences *p = &s->prefs; + const char *path = gtk_file_selection_get_filename (selector); + + if (p->text_file && !strcmp(p->text_file, path)) + return; /* no change */ + + if (!file_p (path)) + { + char b[255]; + sprintf (b, _("Error:\n\n" "File does not exist: \"%s\"\n"), path); + warning_dialog (GTK_WIDGET (top), b, D_NONE, 100); + return; + } + + if (p->text_file) free (p->text_file); + p->text_file = normalize_directory (path); + + gtk_entry_set_text (GTK_ENTRY (name_to_widget (s, "text_file_entry")), + (p->text_file ? p->text_file : "")); + demo_write_init_file (s, p); +} + + +static void +store_text_program (GtkWidget *button, gpointer user_data) +{ + file_selection_data *fsd = (file_selection_data *) user_data; + state *s = fsd->state; + GtkFileSelection *selector = fsd->widget; + /*GtkWidget *top = s->toplevel_widget;*/ + saver_preferences *p = &s->prefs; + const char *path = gtk_file_selection_get_filename (selector); + + if (p->text_program && !strcmp(p->text_program, path)) + return; /* no change */ + +# if 0 + if (!file_p (path)) + { + char b[255]; + sprintf (b, _("Error:\n\n" "File does not exist: \"%s\"\n"), path); + warning_dialog (GTK_WIDGET (top), b, D_NONE, 100); + return; + } +# endif + + if (p->text_program) free (p->text_program); + p->text_program = normalize_directory (path); + + gtk_entry_set_text (GTK_ENTRY (name_to_widget (s, "text_program_entry")), + (p->text_program ? p->text_program : "")); + demo_write_init_file (s, p); +} + + + +static void +browse_image_dir_cancel (GtkWidget *button, gpointer user_data) +{ + file_selection_data *fsd = (file_selection_data *) user_data; + gtk_widget_hide (GTK_WIDGET (fsd->widget)); +} + +static void +browse_image_dir_ok (GtkWidget *button, gpointer user_data) +{ + browse_image_dir_cancel (button, user_data); + store_image_directory (button, user_data); +} + +static void +browse_text_file_ok (GtkWidget *button, gpointer user_data) +{ + browse_image_dir_cancel (button, user_data); + store_text_file (button, user_data); +} + +static void +browse_text_program_ok (GtkWidget *button, gpointer user_data) +{ + browse_image_dir_cancel (button, user_data); + store_text_program (button, user_data); +} + +static void +browse_image_dir_close (GtkWidget *widget, GdkEvent *event, gpointer user_data) +{ + browse_image_dir_cancel (widget, user_data); +} + + +G_MODULE_EXPORT void +browse_image_dir_cb (GtkButton *button, gpointer user_data) +{ + state *s = global_state_kludge; /* I hate C so much... */ + saver_preferences *p = &s->prefs; + static file_selection_data *fsd = 0; + + GtkFileSelection *selector = GTK_FILE_SELECTION( + gtk_file_selection_new ("Please select the image directory.")); + + if (!fsd) + fsd = (file_selection_data *) malloc (sizeof (*fsd)); + + fsd->widget = selector; + fsd->state = s; + + if (p->image_directory && *p->image_directory) + gtk_file_selection_set_filename (selector, p->image_directory); + + gtk_signal_connect (GTK_OBJECT (selector->ok_button), + "clicked", GTK_SIGNAL_FUNC (browse_image_dir_ok), + (gpointer *) fsd); + gtk_signal_connect (GTK_OBJECT (selector->cancel_button), + "clicked", GTK_SIGNAL_FUNC (browse_image_dir_cancel), + (gpointer *) fsd); + gtk_signal_connect (GTK_OBJECT (selector), "delete_event", + GTK_SIGNAL_FUNC (browse_image_dir_close), + (gpointer *) fsd); + + gtk_widget_set_sensitive (GTK_WIDGET (selector->file_list), False); + + gtk_window_set_modal (GTK_WINDOW (selector), True); + gtk_widget_show (GTK_WIDGET (selector)); +} + + +G_MODULE_EXPORT void +browse_text_file_cb (GtkButton *button, gpointer user_data) +{ + state *s = global_state_kludge; /* I hate C so much... */ + saver_preferences *p = &s->prefs; + static file_selection_data *fsd = 0; + + GtkFileSelection *selector = GTK_FILE_SELECTION( + gtk_file_selection_new ("Please select a text file.")); + + if (!fsd) + fsd = (file_selection_data *) malloc (sizeof (*fsd)); + + fsd->widget = selector; + fsd->state = s; + + if (p->text_file && *p->text_file) + gtk_file_selection_set_filename (selector, p->text_file); + + gtk_signal_connect (GTK_OBJECT (selector->ok_button), + "clicked", GTK_SIGNAL_FUNC (browse_text_file_ok), + (gpointer *) fsd); + gtk_signal_connect (GTK_OBJECT (selector->cancel_button), + "clicked", GTK_SIGNAL_FUNC (browse_image_dir_cancel), + (gpointer *) fsd); + gtk_signal_connect (GTK_OBJECT (selector), "delete_event", + GTK_SIGNAL_FUNC (browse_image_dir_close), + (gpointer *) fsd); + + gtk_window_set_modal (GTK_WINDOW (selector), True); + gtk_widget_show (GTK_WIDGET (selector)); +} + + +G_MODULE_EXPORT void +browse_text_program_cb (GtkButton *button, gpointer user_data) +{ + state *s = global_state_kludge; /* I hate C so much... */ + saver_preferences *p = &s->prefs; + static file_selection_data *fsd = 0; + + GtkFileSelection *selector = GTK_FILE_SELECTION( + gtk_file_selection_new ("Please select a text-generating program.")); + + if (!fsd) + fsd = (file_selection_data *) malloc (sizeof (*fsd)); + + fsd->widget = selector; + fsd->state = s; + + if (p->text_program && *p->text_program) + gtk_file_selection_set_filename (selector, p->text_program); + + gtk_signal_connect (GTK_OBJECT (selector->ok_button), + "clicked", GTK_SIGNAL_FUNC (browse_text_program_ok), + (gpointer *) fsd); + gtk_signal_connect (GTK_OBJECT (selector->cancel_button), + "clicked", GTK_SIGNAL_FUNC (browse_image_dir_cancel), + (gpointer *) fsd); + gtk_signal_connect (GTK_OBJECT (selector), "delete_event", + GTK_SIGNAL_FUNC (browse_image_dir_close), + (gpointer *) fsd); + + gtk_window_set_modal (GTK_WINDOW (selector), True); + gtk_widget_show (GTK_WIDGET (selector)); +} + + + + + +G_MODULE_EXPORT void +settings_cb (GtkButton *button, gpointer user_data) +{ + state *s = global_state_kludge; /* I hate C so much... */ + int list_elt = selected_list_element (s); + + populate_demo_window (s, list_elt); /* reset the widget */ + populate_popup_window (s); /* create UI on popup window */ + gtk_widget_show (s->popup_widget); +} + +static void +settings_sync_cmd_text (state *s) +{ +# ifdef HAVE_XML + GtkWidget *cmd = GTK_WIDGET (name_to_widget (s, "cmd_text")); + char *cmd_line = get_configurator_command_line (s->cdata, False); + gtk_entry_set_text (GTK_ENTRY (cmd), cmd_line); + gtk_entry_set_position (GTK_ENTRY (cmd), strlen (cmd_line)); + free (cmd_line); +# endif /* HAVE_XML */ +} + +G_MODULE_EXPORT void +settings_adv_cb (GtkButton *button, gpointer user_data) +{ + state *s = global_state_kludge; /* I hate C so much... */ + GtkNotebook *notebook = + GTK_NOTEBOOK (name_to_widget (s, "opt_notebook")); + + settings_sync_cmd_text (s); + gtk_notebook_set_page (notebook, 1); +} + +G_MODULE_EXPORT void +settings_std_cb (GtkButton *button, gpointer user_data) +{ + state *s = global_state_kludge; /* I hate C so much... */ + GtkNotebook *notebook = + GTK_NOTEBOOK (name_to_widget (s, "opt_notebook")); + + /* Re-create UI to reflect the in-progress command-line settings. */ + populate_popup_window (s); + + gtk_notebook_set_page (notebook, 0); +} + +G_MODULE_EXPORT void +settings_reset_cb (GtkButton *button, gpointer user_data) +{ +# ifdef HAVE_XML + state *s = global_state_kludge; /* I hate C so much... */ + GtkWidget *cmd = GTK_WIDGET (name_to_widget (s, "cmd_text")); + char *cmd_line = get_configurator_command_line (s->cdata, True); + gtk_entry_set_text (GTK_ENTRY (cmd), cmd_line); + gtk_entry_set_position (GTK_ENTRY (cmd), strlen (cmd_line)); + free (cmd_line); + populate_popup_window (s); +# endif /* HAVE_XML */ +} + +G_MODULE_EXPORT void +settings_switch_page_cb (GtkNotebook *notebook, GtkNotebookPage *page, + gint page_num, gpointer user_data) +{ + state *s = global_state_kludge; /* I hate C so much... */ + GtkWidget *adv = name_to_widget (s, "adv_button"); + GtkWidget *std = name_to_widget (s, "std_button"); + + if (page_num == 0) + { + gtk_widget_show (adv); + gtk_widget_hide (std); + } + else if (page_num == 1) + { + gtk_widget_hide (adv); + gtk_widget_show (std); + } + else + abort(); +} + + + +G_MODULE_EXPORT void +settings_cancel_cb (GtkButton *button, gpointer user_data) +{ + state *s = global_state_kludge; /* I hate C so much... */ + gtk_widget_hide (s->popup_widget); +} + +G_MODULE_EXPORT void +settings_ok_cb (GtkButton *button, gpointer user_data) +{ + state *s = global_state_kludge; /* I hate C so much... */ + GtkNotebook *notebook = GTK_NOTEBOOK (name_to_widget (s, "opt_notebook")); + int page = gtk_notebook_get_current_page (notebook); + + if (page == 0) + /* Regenerate the command-line from the widget contents before saving. + But don't do this if we're looking at the command-line page already, + or we will blow away what they typed... */ + settings_sync_cmd_text (s); + + flush_popup_changes_and_save (s); + gtk_widget_hide (s->popup_widget); +} + +static gboolean +wm_popup_close_cb (GtkWidget *widget, GdkEvent *event, gpointer data) +{ + state *s = (state *) data; + settings_cancel_cb (0, (gpointer) s); + return TRUE; +} + + + +/* Populating the various widgets + */ + + +/* Returns the number of the last hack run by the server. + */ +static int +server_current_hack (void) +{ + Atom type; + int format; + unsigned long nitems, bytesafter; + unsigned char *dataP = 0; + Display *dpy = GDK_DISPLAY(); + int hack_number = -1; + + if (XGetWindowProperty (dpy, RootWindow (dpy, 0), /* always screen #0 */ + XA_SCREENSAVER_STATUS, + 0, 3, False, XA_INTEGER, + &type, &format, &nitems, &bytesafter, + &dataP) + == Success + && type == XA_INTEGER + && nitems >= 3 + && dataP) + { + PROP32 *data = (PROP32 *) dataP; + hack_number = (int) data[2] - 1; + } + + if (dataP) XFree (dataP); + + return hack_number; +} + + +/* Finds the number of the last hack that was run, and makes that item be + selected by default. + */ +static void +scroll_to_current_hack (state *s) +{ + saver_preferences *p = &s->prefs; + int hack_number = -1; + + if (p->mode == ONE_HACK) /* in "one" mode, use the one */ + hack_number = p->selected_hack; + if (hack_number < 0) /* otherwise, use the last-run */ + hack_number = server_current_hack (); + if (hack_number < 0) /* failing that, last "one mode" */ + hack_number = p->selected_hack; + if (hack_number < 0) /* failing that, newest hack. */ + { + /* We should only get here if the user does not have a .xscreensaver + file, and the screen has not been blanked with a hack since X + started up: in other words, this is probably a fresh install. + + Instead of just defaulting to hack #0 (in either "programs" or + "alphabetical" order) let's try to default to the last runnable + hack in the "programs" list: this is probably the hack that was + most recently added to the xscreensaver distribution (and so + it's probably the currently-coolest one!) + */ + hack_number = p->screenhacks_count-1; + while (hack_number > 0 && + ! (s->hacks_available_p[hack_number] && + p->screenhacks[hack_number]->enabled_p)) + hack_number--; + } + + if (hack_number >= 0 && hack_number < p->screenhacks_count) + { + int list_elt = s->hack_number_to_list_elt[hack_number]; + GtkWidget *list = name_to_widget (s, "list"); + force_list_select_item (s, list, list_elt, True); + populate_demo_window (s, list_elt); + } +} + + +static void +populate_hack_list (state *s) +{ + Display *dpy = GDK_DISPLAY(); +#ifdef HAVE_GTK2 + saver_preferences *p = &s->prefs; + GtkTreeView *list = GTK_TREE_VIEW (name_to_widget (s, "list")); + GtkListStore *model; + GtkTreeSelection *selection; + GtkCellRenderer *ren; + GtkTreeIter iter; + int i; + + g_object_get (G_OBJECT (list), + "model", &model, + NULL); + if (!model) + { + model = gtk_list_store_new (COL_LAST, G_TYPE_BOOLEAN, G_TYPE_STRING); + g_object_set (G_OBJECT (list), "model", model, NULL); + g_object_unref (model); + + ren = gtk_cell_renderer_toggle_new (); + gtk_tree_view_insert_column_with_attributes (list, COL_ENABLED, + _("Use"), ren, + "active", COL_ENABLED, + NULL); + + g_signal_connect (ren, "toggled", + G_CALLBACK (list_checkbox_cb), + s); + + ren = gtk_cell_renderer_text_new (); + gtk_tree_view_insert_column_with_attributes (list, COL_NAME, + _("Screen Saver"), ren, + "markup", COL_NAME, + NULL); + + g_signal_connect_after (list, "row_activated", + G_CALLBACK (list_activated_cb), + s); + + selection = gtk_tree_view_get_selection (list); + g_signal_connect (selection, "changed", + G_CALLBACK (list_select_changed_cb), + s); + + } + + for (i = 0; i < s->list_count; i++) + { + int hack_number = s->list_elt_to_hack_number[i]; + screenhack *hack = (hack_number < 0 ? 0 : p->screenhacks[hack_number]); + char *pretty_name; + Bool available_p = (hack && s->hacks_available_p [hack_number]); + + if (!hack) continue; + + /* If we're to suppress uninstalled hacks, check $PATH now. */ + if (p->ignore_uninstalled_p && !available_p) + continue; + + pretty_name = (hack->name + ? strdup (hack->name) + : make_hack_name (dpy, hack->command)); + + if (!available_p) + { + /* Make the text foreground be the color of insensitive widgets + (but don't actually make it be insensitive, since we still + want to be able to click on it.) + */ + GtkStyle *style = gtk_widget_get_style (GTK_WIDGET (list)); + GdkColor *fg = &style->fg[GTK_STATE_INSENSITIVE]; + /* GdkColor *bg = &style->bg[GTK_STATE_INSENSITIVE]; */ + char *buf = (char *) malloc (strlen (pretty_name) + 100); + + sprintf (buf, "%s", + fg->red >> 8, fg->green >> 8, fg->blue >> 8, + /* bg->red >> 8, bg->green >> 8, bg->blue >> 8, */ + pretty_name); + free (pretty_name); + pretty_name = buf; + } + + gtk_list_store_append (model, &iter); + gtk_list_store_set (model, &iter, + COL_ENABLED, hack->enabled_p, + COL_NAME, pretty_name, + -1); + free (pretty_name); + } + +#else /* !HAVE_GTK2 */ + + saver_preferences *p = &s->prefs; + GtkList *list = GTK_LIST (name_to_widget (s, "list")); + int i; + for (i = 0; i < s->list_count; i++) + { + int hack_number = s->list_elt_to_hack_number[i]; + screenhack *hack = (hack_number < 0 ? 0 : p->screenhacks[hack_number]); + + /* A GtkList must contain only GtkListItems, but those can contain + an arbitrary widget. We add an Hbox, and inside that, a Checkbox + and a Label. We handle single and double click events on the + line itself, for clicking on the text, but the interior checkbox + also handles its own events. + */ + GtkWidget *line; + GtkWidget *line_hbox; + GtkWidget *line_check; + GtkWidget *line_label; + char *pretty_name; + Bool available_p = (hack && s->hacks_available_p [hack_number]); + + if (!hack) continue; + + /* If we're to suppress uninstalled hacks, check $PATH now. */ + if (p->ignore_uninstalled_p && !available_p) + continue; + + pretty_name = (hack->name + ? strdup (hack->name) + : make_hack_name (hack->command)); + + line = gtk_list_item_new (); + line_hbox = gtk_hbox_new (FALSE, 0); + line_check = gtk_check_button_new (); + line_label = gtk_label_new (pretty_name); + + gtk_container_add (GTK_CONTAINER (line), line_hbox); + gtk_box_pack_start (GTK_BOX (line_hbox), line_check, FALSE, FALSE, 0); + gtk_box_pack_start (GTK_BOX (line_hbox), line_label, FALSE, FALSE, 0); + + gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (line_check), + hack->enabled_p); + gtk_label_set_justify (GTK_LABEL (line_label), GTK_JUSTIFY_LEFT); + + gtk_widget_show (line_check); + gtk_widget_show (line_label); + gtk_widget_show (line_hbox); + gtk_widget_show (line); + + free (pretty_name); + + gtk_container_add (GTK_CONTAINER (list), line); + gtk_signal_connect (GTK_OBJECT (line), "button_press_event", + GTK_SIGNAL_FUNC (list_doubleclick_cb), + (gpointer) s); + + gtk_signal_connect (GTK_OBJECT (line_check), "toggled", + GTK_SIGNAL_FUNC (list_checkbox_cb), + (gpointer) s); + + gtk_widget_show (line); + + if (!available_p) + { + /* Make the widget be colored like insensitive widgets + (but don't actually make it be insensitive, since we + still want to be able to click on it.) + */ + GtkRcStyle *rc_style; + GdkColor fg, bg; + + gtk_widget_realize (GTK_WIDGET (line_label)); + + fg = GTK_WIDGET (line_label)->style->fg[GTK_STATE_INSENSITIVE]; + bg = GTK_WIDGET (line_label)->style->bg[GTK_STATE_INSENSITIVE]; + + rc_style = gtk_rc_style_new (); + rc_style->fg[GTK_STATE_NORMAL] = fg; + rc_style->bg[GTK_STATE_NORMAL] = bg; + rc_style->color_flags[GTK_STATE_NORMAL] |= GTK_RC_FG|GTK_RC_BG; + + gtk_widget_modify_style (GTK_WIDGET (line_label), rc_style); + gtk_rc_style_unref (rc_style); + } + } + + gtk_signal_connect (GTK_OBJECT (list), "select_child", + GTK_SIGNAL_FUNC (list_select_cb), + (gpointer) s); + gtk_signal_connect (GTK_OBJECT (list), "unselect_child", + GTK_SIGNAL_FUNC (list_unselect_cb), + (gpointer) s); +#endif /* !HAVE_GTK2 */ +} + +static void +update_list_sensitivity (state *s) +{ + saver_preferences *p = &s->prefs; + Bool sensitive = (p->mode == RANDOM_HACKS || + p->mode == RANDOM_HACKS_SAME || + p->mode == ONE_HACK); + Bool checkable = (p->mode == RANDOM_HACKS || + p->mode == RANDOM_HACKS_SAME); + Bool blankable = (p->mode != DONT_BLANK); + +#ifndef HAVE_GTK2 + GtkWidget *head = name_to_widget (s, "col_head_hbox"); + GtkWidget *use = name_to_widget (s, "use_col_frame"); +#endif /* HAVE_GTK2 */ + GtkWidget *scroller = name_to_widget (s, "scroller"); + GtkWidget *buttons = name_to_widget (s, "next_prev_hbox"); + GtkWidget *blanker = name_to_widget (s, "blanking_table"); + +#ifdef HAVE_GTK2 + GtkTreeView *list = GTK_TREE_VIEW (name_to_widget (s, "list")); + GtkTreeViewColumn *use = gtk_tree_view_get_column (list, COL_ENABLED); +#else /* !HAVE_GTK2 */ + GtkList *list = GTK_LIST (name_to_widget (s, "list")); + GList *kids = gtk_container_children (GTK_CONTAINER (list)); + + gtk_widget_set_sensitive (GTK_WIDGET (head), sensitive); +#endif /* !HAVE_GTK2 */ + gtk_widget_set_sensitive (GTK_WIDGET (scroller), sensitive); + gtk_widget_set_sensitive (GTK_WIDGET (buttons), sensitive); + + gtk_widget_set_sensitive (GTK_WIDGET (blanker), blankable); + +#ifdef HAVE_GTK2 + gtk_tree_view_column_set_visible (use, checkable); +#else /* !HAVE_GTK2 */ + if (checkable) + gtk_widget_show (use); /* the "Use" column header */ + else + gtk_widget_hide (use); + + while (kids) + { + GtkBin *line = GTK_BIN (kids->data); + GtkContainer *line_hbox = GTK_CONTAINER (line->child); + GtkWidget *line_check = + GTK_WIDGET (gtk_container_children (line_hbox)->data); + + if (checkable) + gtk_widget_show (line_check); + else + gtk_widget_hide (line_check); + + kids = kids->next; + } +#endif /* !HAVE_GTK2 */ +} + + +static void +populate_prefs_page (state *s) +{ + saver_preferences *p = &s->prefs; + + Bool can_lock_p = True; + + /* Disable all the "lock" controls if locking support was not provided + at compile-time, or if running on MacOS. */ +# if defined(NO_LOCKING) || defined(__APPLE__) + can_lock_p = False; +# endif + + + /* If there is only one screen, the mode menu contains + "random" but not "random-same". + */ + if (s->nscreens <= 1 && p->mode == RANDOM_HACKS_SAME) + p->mode = RANDOM_HACKS; + + + /* The file supports timeouts of less than a minute, but the GUI does + not, so throttle the values to be at least one minute (since "0" is + a bad rounding choice...) + */ +# define THROTTLE(NAME) if (p->NAME != 0 && p->NAME < 60000) p->NAME = 60000 + THROTTLE (timeout); + THROTTLE (cycle); + /* THROTTLE (passwd_timeout); */ /* GUI doesn't set this; leave it alone */ +# undef THROTTLE + +# define FMT_MINUTES(NAME,N) \ + gtk_spin_button_set_value (GTK_SPIN_BUTTON (name_to_widget (s, (NAME))), (double)((N) + 59) / (60 * 1000)) + +# define FMT_SECONDS(NAME,N) \ + gtk_spin_button_set_value (GTK_SPIN_BUTTON (name_to_widget (s, (NAME))), (double)((N) / 1000)) + + FMT_MINUTES ("timeout_spinbutton", p->timeout); + FMT_MINUTES ("cycle_spinbutton", p->cycle); + FMT_MINUTES ("lock_spinbutton", p->lock_timeout); + FMT_MINUTES ("dpms_standby_spinbutton", p->dpms_standby); + FMT_MINUTES ("dpms_suspend_spinbutton", p->dpms_suspend); + FMT_MINUTES ("dpms_off_spinbutton", p->dpms_off); + FMT_SECONDS ("fade_spinbutton", p->fade_seconds); + +# undef FMT_MINUTES +# undef FMT_SECONDS + +# define TOGGLE_ACTIVE(NAME,ACTIVEP) \ + gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (name_to_widget (s,(NAME))),\ + (ACTIVEP)) + + TOGGLE_ACTIVE ("lock_button", p->lock_p); +#if 0 + TOGGLE_ACTIVE ("verbose_button", p->verbose_p); + TOGGLE_ACTIVE ("capture_button", p->capture_stderr_p); + TOGGLE_ACTIVE ("splash_button", p->splash_p); +#endif + TOGGLE_ACTIVE ("dpms_button", p->dpms_enabled_p); + TOGGLE_ACTIVE ("dpms_quickoff_button", p->dpms_quickoff_p); + TOGGLE_ACTIVE ("grab_desk_button", p->grab_desktop_p); + TOGGLE_ACTIVE ("grab_video_button", p->grab_video_p); + TOGGLE_ACTIVE ("grab_image_button", p->random_image_p); + TOGGLE_ACTIVE ("install_button", p->install_cmap_p); + TOGGLE_ACTIVE ("fade_button", p->fade_p); + TOGGLE_ACTIVE ("unfade_button", p->unfade_p); + + switch (p->tmode) + { + case TEXT_LITERAL: TOGGLE_ACTIVE ("text_radio", True); break; + case TEXT_FILE: TOGGLE_ACTIVE ("text_file_radio", True); break; + case TEXT_PROGRAM: TOGGLE_ACTIVE ("text_program_radio", True); break; + case TEXT_URL: TOGGLE_ACTIVE ("text_url_radio", True); break; + default: TOGGLE_ACTIVE ("text_host_radio", True); break; + } + +# undef TOGGLE_ACTIVE + + gtk_entry_set_text (GTK_ENTRY (name_to_widget (s, "image_text")), + (p->image_directory ? p->image_directory : "")); + gtk_widget_set_sensitive (name_to_widget (s, "image_text"), + p->random_image_p); + gtk_widget_set_sensitive (name_to_widget (s, "image_browse_button"), + p->random_image_p); + + gtk_entry_set_text (GTK_ENTRY (name_to_widget (s, "text_entry")), + (p->text_literal ? p->text_literal : "")); + gtk_entry_set_text (GTK_ENTRY (name_to_widget (s, "text_file_entry")), + (p->text_file ? p->text_file : "")); + gtk_entry_set_text (GTK_ENTRY (name_to_widget (s, "text_program_entry")), + (p->text_program ? p->text_program : "")); + gtk_entry_set_text (GTK_ENTRY (name_to_widget (s, "text_url_entry")), + (p->text_url ? p->text_url : "")); + + gtk_widget_set_sensitive (name_to_widget (s, "text_entry"), + p->tmode == TEXT_LITERAL); + gtk_widget_set_sensitive (name_to_widget (s, "text_file_entry"), + p->tmode == TEXT_FILE); + gtk_widget_set_sensitive (name_to_widget (s, "text_file_browse"), + p->tmode == TEXT_FILE); + gtk_widget_set_sensitive (name_to_widget (s, "text_program_entry"), + p->tmode == TEXT_PROGRAM); + gtk_widget_set_sensitive (name_to_widget (s, "text_program_browse"), + p->tmode == TEXT_PROGRAM); + gtk_widget_set_sensitive (name_to_widget (s, "text_url_entry"), + p->tmode == TEXT_URL); + + + /* Map the `saver_mode' enum to mode menu to values. */ + { + GtkOptionMenu *opt = GTK_OPTION_MENU (name_to_widget (s, "mode_menu")); + + int i; + for (i = 0; i < countof(mode_menu_order); i++) + if (mode_menu_order[i] == p->mode) + break; + gtk_option_menu_set_history (opt, i); + update_list_sensitivity (s); + } + + { + Bool found_any_writable_cells = False; + Bool fading_possible = False; + Bool dpms_supported = False; + + Display *dpy = GDK_DISPLAY(); + int nscreens = ScreenCount(dpy); /* real screens, not Xinerama */ + int i; + for (i = 0; i < nscreens; i++) + { + Screen *s = ScreenOfDisplay (dpy, i); + if (has_writable_cells (s, DefaultVisualOfScreen (s))) + { + found_any_writable_cells = True; + break; + } + } + + fading_possible = found_any_writable_cells; +#ifdef HAVE_XF86VMODE_GAMMA + fading_possible = True; +#endif + +#ifdef HAVE_DPMS_EXTENSION + { + int op = 0, event = 0, error = 0; + if (XQueryExtension (dpy, "DPMS", &op, &event, &error)) + dpms_supported = True; + } +#endif /* HAVE_DPMS_EXTENSION */ + + +# define SENSITIZE(NAME,SENSITIVEP) \ + gtk_widget_set_sensitive (name_to_widget (s, (NAME)), (SENSITIVEP)) + + /* Blanking and Locking + */ + SENSITIZE ("lock_button", can_lock_p); + SENSITIZE ("lock_spinbutton", can_lock_p && p->lock_p); + SENSITIZE ("lock_mlabel", can_lock_p && p->lock_p); + + /* DPMS + */ +dpms_supported=1; + SENSITIZE ("dpms_frame", dpms_supported); + SENSITIZE ("dpms_button", dpms_supported); + SENSITIZE ("dpms_quickoff_button", dpms_supported); + + SENSITIZE ("dpms_standby_label", dpms_supported && p->dpms_enabled_p); + SENSITIZE ("dpms_standby_mlabel", dpms_supported && p->dpms_enabled_p); + SENSITIZE ("dpms_standby_spinbutton", dpms_supported && p->dpms_enabled_p); + SENSITIZE ("dpms_suspend_label", dpms_supported && p->dpms_enabled_p); + SENSITIZE ("dpms_suspend_mlabel", dpms_supported && p->dpms_enabled_p); + SENSITIZE ("dpms_suspend_spinbutton", dpms_supported && p->dpms_enabled_p); + SENSITIZE ("dpms_off_label", dpms_supported && p->dpms_enabled_p); + SENSITIZE ("dpms_off_mlabel", dpms_supported && p->dpms_enabled_p); + SENSITIZE ("dpms_off_spinbutton", dpms_supported && p->dpms_enabled_p); + + /* Colormaps + */ + SENSITIZE ("cmap_frame", found_any_writable_cells || fading_possible); + SENSITIZE ("install_button", found_any_writable_cells); + SENSITIZE ("fade_button", fading_possible); + SENSITIZE ("unfade_button", fading_possible); + + SENSITIZE ("fade_label", (fading_possible && + (p->fade_p || p->unfade_p))); + SENSITIZE ("fade_spinbutton", (fading_possible && + (p->fade_p || p->unfade_p))); + +# undef SENSITIZE + } +} + + +static void +populate_popup_window (state *s) +{ + GtkLabel *doc = GTK_LABEL (name_to_widget (s, "doc")); + char *doc_string = 0; + + /* #### not in Gtk 1.2 + gtk_label_set_selectable (doc); + */ + +# ifdef HAVE_XML + if (s->cdata) + { + free_conf_data (s->cdata); + s->cdata = 0; + } + + { + saver_preferences *p = &s->prefs; + int list_elt = selected_list_element (s); + int hack_number = (list_elt >= 0 && list_elt < s->list_count + ? s->list_elt_to_hack_number[list_elt] + : -1); + screenhack *hack = (hack_number >= 0 ? p->screenhacks[hack_number] : 0); + if (hack) + { + GtkWidget *parent = name_to_widget (s, "settings_vbox"); + GtkWidget *cmd = GTK_WIDGET (name_to_widget (s, "cmd_text")); + const char *cmd_line = gtk_entry_get_text (GTK_ENTRY (cmd)); + s->cdata = load_configurator (cmd_line, s->debug_p); + if (s->cdata && s->cdata->widget) + gtk_box_pack_start (GTK_BOX (parent), s->cdata->widget, + TRUE, TRUE, 0); + } + } + + doc_string = (s->cdata + ? s->cdata->description + : 0); +# else /* !HAVE_XML */ + doc_string = _("Descriptions not available: no XML support compiled in."); +# endif /* !HAVE_XML */ + + gtk_label_set_text (doc, (doc_string + ? _(doc_string) + : _("No description available."))); +} + + +static void +sensitize_demo_widgets (state *s, Bool sensitive_p) +{ + const char *names[] = { "demo", "settings", + "cmd_label", "cmd_text", "manual", + "visual", "visual_combo" }; + int i; + for (i = 0; i < countof(names); i++) + { + GtkWidget *w = name_to_widget (s, names[i]); + gtk_widget_set_sensitive (GTK_WIDGET(w), sensitive_p); + } +} + + +static void +sensitize_menu_items (state *s, Bool force_p) +{ + static Bool running_p = False; + static time_t last_checked = 0; + time_t now = time ((time_t *) 0); + const char *names[] = { "activate_menu", "lock_menu", "kill_menu", + /* "demo" */ }; + int i; + + if (force_p || now > last_checked + 10) /* check every 10 seconds */ + { + running_p = xscreensaver_running_p (s); + last_checked = time ((time_t *) 0); + } + + for (i = 0; i < countof(names); i++) + { + GtkWidget *w = name_to_widget (s, names[i]); + gtk_widget_set_sensitive (GTK_WIDGET(w), running_p); + } +} + + +/* When the File menu is de-posted after a "Restart Daemon" command, + the window underneath doesn't repaint for some reason. I guess this + is a bug in exposure handling in GTK or GDK. This works around it. + */ +static void +force_dialog_repaint (state *s) +{ +#if 1 + /* Tell GDK to invalidate and repaint the whole window. + */ + GdkWindow *w = GET_WINDOW (s->toplevel_widget); + GdkRegion *region = gdk_region_new (); + GdkRectangle rect; + rect.x = rect.y = 0; + rect.width = rect.height = 32767; + gdk_region_union_with_rect (region, &rect); + gdk_window_invalidate_region (w, region, True); + gdk_region_destroy (region); + gdk_window_process_updates (w, True); +#else + /* Force the server to send an exposure event by creating and then + destroying a window as a child of the top level shell. + */ + Display *dpy = GDK_DISPLAY(); + Window parent = GDK_WINDOW_XWINDOW (s->toplevel_widget->window); + Window w; + XWindowAttributes xgwa; + XGetWindowAttributes (dpy, parent, &xgwa); + w = XCreateSimpleWindow (dpy, parent, 0, 0, xgwa.width, xgwa.height, 0,0,0); + XMapRaised (dpy, w); + XDestroyWindow (dpy, w); + XSync (dpy, False); +#endif +} + + +/* Even though we've given these text fields a maximum number of characters, + their default size is still about 30 characters wide -- so measure out + a string in their font, and resize them to just fit that. + */ +static void +fix_text_entry_sizes (state *s) +{ + GtkWidget *w; + +# if 0 /* appears no longer necessary with Gtk 1.2.10 */ + const char * const spinbuttons[] = { + "timeout_spinbutton", "cycle_spinbutton", "lock_spinbutton", + "dpms_standby_spinbutton", "dpms_suspend_spinbutton", + "dpms_off_spinbutton", + "-fade_spinbutton" }; + int i; + int width = 0; + + for (i = 0; i < countof(spinbuttons); i++) + { + const char *n = spinbuttons[i]; + int cols = 4; + while (*n == '-') n++, cols--; + w = GTK_WIDGET (name_to_widget (s, n)); + width = gdk_text_width (w->style->font, "MMMMMMMM", cols); + gtk_widget_set_usize (w, width, -2); + } + + /* Now fix the width of the combo box. + */ + w = GTK_WIDGET (name_to_widget (s, "visual_combo")); + w = GTK_COMBO (w)->entry; + width = gdk_string_width (w->style->font, "PseudoColor___"); + gtk_widget_set_usize (w, width, -2); + + /* Now fix the width of the file entry text. + */ + w = GTK_WIDGET (name_to_widget (s, "image_text")); + width = gdk_string_width (w->style->font, "mmmmmmmmmmmmmm"); + gtk_widget_set_usize (w, width, -2); + + /* Now fix the width of the command line text. + */ + w = GTK_WIDGET (name_to_widget (s, "cmd_text")); + width = gdk_string_width (w->style->font, "mmmmmmmmmmmmmmmmmmmm"); + gtk_widget_set_usize (w, width, -2); + +# endif /* 0 */ + + /* Now fix the height of the list widget: + make it default to being around 10 text-lines high instead of 4. + */ + w = GTK_WIDGET (name_to_widget (s, "list")); + { + int lines = 10; + int height; + int leading = 3; /* approximate is ok... */ + int border = 2; + +#ifdef HAVE_GTK2 + PangoFontMetrics *pain = + pango_context_get_metrics (gtk_widget_get_pango_context (w), + gtk_widget_get_style (w)->font_desc, + gtk_get_default_language ()); + height = PANGO_PIXELS (pango_font_metrics_get_ascent (pain) + + pango_font_metrics_get_descent (pain)); +#else /* !HAVE_GTK2 */ + height = w->style->font->ascent + w->style->font->descent; +#endif /* !HAVE_GTK2 */ + + height += leading; + height *= lines; + height += border * 2; + w = GTK_WIDGET (name_to_widget (s, "scroller")); + gtk_widget_set_usize (w, -2, height); + } +} + + +#ifndef HAVE_GTK2 + +/* Pixmaps for the up and down arrow buttons (yeah, this is sleazy...) + */ + +static char *up_arrow_xpm[] = { + "15 15 4 1", + " c None", + "- c #FFFFFF", + "+ c #D6D6D6", + "@ c #000000", + + " @ ", + " @ ", + " -+@ ", + " -+@ ", + " -+++@ ", + " -+++@ ", + " -+++++@ ", + " -+++++@ ", + " -+++++++@ ", + " -+++++++@ ", + " -+++++++++@ ", + " -+++++++++@ ", + " -+++++++++++@ ", + " @@@@@@@@@@@@@ ", + " ", + + /* Need these here because gdk_pixmap_create_from_xpm_d() walks off + the end of the array (Gtk 1.2.5.) */ + "\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000", + "\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000" +}; + +static char *down_arrow_xpm[] = { + "15 15 4 1", + " c None", + "- c #FFFFFF", + "+ c #D6D6D6", + "@ c #000000", + + " ", + " ------------- ", + " -+++++++++++@ ", + " -+++++++++@ ", + " -+++++++++@ ", + " -+++++++@ ", + " -+++++++@ ", + " -+++++@ ", + " -+++++@ ", + " -+++@ ", + " -+++@ ", + " -+@ ", + " -+@ ", + " @ ", + " @ ", + + /* Need these here because gdk_pixmap_create_from_xpm_d() walks off + the end of the array (Gtk 1.2.5.) */ + "\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000", + "\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000" +}; + +static void +pixmapify_button (state *s, int down_p) +{ + GdkPixmap *pixmap; + GdkBitmap *mask; + GtkWidget *pixmapwid; + GtkStyle *style; + GtkWidget *w; + + w = GTK_WIDGET (name_to_widget (s, (down_p ? "next" : "prev"))); + style = gtk_widget_get_style (w); + mask = 0; + pixmap = gdk_pixmap_create_from_xpm_d (w->window, &mask, + &style->bg[GTK_STATE_NORMAL], + (down_p + ? (gchar **) down_arrow_xpm + : (gchar **) up_arrow_xpm)); + pixmapwid = gtk_pixmap_new (pixmap, mask); + gtk_widget_show (pixmapwid); + gtk_container_remove (GTK_CONTAINER (w), GTK_BIN (w)->child); + gtk_container_add (GTK_CONTAINER (w), pixmapwid); +} + +static void +map_next_button_cb (GtkWidget *w, gpointer user_data) +{ + state *s = (state *) user_data; + pixmapify_button (s, 1); +} + +static void +map_prev_button_cb (GtkWidget *w, gpointer user_data) +{ + state *s = (state *) user_data; + pixmapify_button (s, 0); +} +#endif /* !HAVE_GTK2 */ + + +#ifndef HAVE_GTK2 +/* Work around a Gtk bug that causes label widgets to wrap text too early. + */ + +static void +you_are_not_a_unique_or_beautiful_snowflake (GtkWidget *label, + GtkAllocation *allocation, + void *foo) +{ + GtkRequisition req; + GtkWidgetAuxInfo *aux_info; + + aux_info = gtk_object_get_data (GTK_OBJECT (label), "gtk-aux-info"); + + aux_info->width = allocation->width; + aux_info->height = -2; + aux_info->x = -1; + aux_info->y = -1; + + gtk_widget_size_request (label, &req); +} + +/* Feel the love. Thanks to Nat Friedman for finding this workaround. + */ +static void +eschew_gtk_lossage (GtkLabel *label) +{ + GtkWidgetAuxInfo *aux_info = g_new0 (GtkWidgetAuxInfo, 1); + aux_info->width = GTK_WIDGET (label)->allocation.width; + aux_info->height = -2; + aux_info->x = -1; + aux_info->y = -1; + + gtk_object_set_data (GTK_OBJECT (label), "gtk-aux-info", aux_info); + + gtk_signal_connect (GTK_OBJECT (label), "size_allocate", + GTK_SIGNAL_FUNC (you_are_not_a_unique_or_beautiful_snowflake), + 0); + + gtk_widget_set_usize (GTK_WIDGET (label), -2, -2); + + gtk_widget_queue_resize (GTK_WIDGET (label)); +} +#endif /* !HAVE_GTK2 */ + + +static void +populate_demo_window (state *s, int list_elt) +{ + Display *dpy = GDK_DISPLAY(); + saver_preferences *p = &s->prefs; + screenhack *hack; + char *pretty_name; + GtkFrame *frame1 = GTK_FRAME (name_to_widget (s, "preview_frame")); + GtkFrame *frame2 = GTK_FRAME (name_to_widget (s, "opt_frame")); + GtkEntry *cmd = GTK_ENTRY (name_to_widget (s, "cmd_text")); + GtkCombo *vis = GTK_COMBO (name_to_widget (s, "visual_combo")); + GtkWidget *list = GTK_WIDGET (name_to_widget (s, "list")); + + if (p->mode == BLANK_ONLY) + { + hack = 0; + pretty_name = strdup (_("Blank Screen")); + schedule_preview (s, 0); + } + else if (p->mode == DONT_BLANK) + { + hack = 0; + pretty_name = strdup (_("Screen Saver Disabled")); + schedule_preview (s, 0); + } + else + { + int hack_number = (list_elt >= 0 && list_elt < s->list_count + ? s->list_elt_to_hack_number[list_elt] + : -1); + hack = (hack_number >= 0 ? p->screenhacks[hack_number] : 0); + + pretty_name = (hack + ? (hack->name + ? strdup (hack->name) + : make_hack_name (dpy, hack->command)) + : 0); + + if (hack) + schedule_preview (s, hack->command); + else + schedule_preview (s, 0); + } + + if (!pretty_name) + pretty_name = strdup (_("Preview")); + + gtk_frame_set_label (frame1, _(pretty_name)); + gtk_frame_set_label (frame2, _(pretty_name)); + + gtk_entry_set_text (cmd, (hack ? hack->command : "")); + gtk_entry_set_position (cmd, 0); + + { + char title[255]; + sprintf (title, _("%s: %.100s Settings"), + progclass, (pretty_name ? pretty_name : "???")); + gtk_window_set_title (GTK_WINDOW (s->popup_widget), title); + } + + gtk_entry_set_text (GTK_ENTRY (GTK_COMBO (vis)->entry), + (hack + ? (hack->visual && *hack->visual + ? hack->visual + : _("Any")) + : "")); + + sensitize_demo_widgets (s, (hack ? True : False)); + + if (pretty_name) free (pretty_name); + + ensure_selected_item_visible (list); + + s->_selected_list_element = list_elt; +} + + +static void +widget_deleter (GtkWidget *widget, gpointer data) +{ + /* #### Well, I want to destroy these widgets, but if I do that, they get + referenced again, and eventually I get a SEGV. So instead of + destroying them, I'll just hide them, and leak a bunch of memory + every time the disk file changes. Go go go Gtk! + + #### Ok, that's a lie, I get a crash even if I just hide the widget + and don't ever delete it. Fuck! + */ +#if 0 + gtk_widget_destroy (widget); +#else + gtk_widget_hide (widget); +#endif +} + + +static char **sort_hack_cmp_names_kludge; +static int +sort_hack_cmp (const void *a, const void *b) +{ + if (a == b) + return 0; + else + { + int aa = *(int *) a; + int bb = *(int *) b; + const char last[] = "\377\377\377\377\377\377\377\377\377\377\377"; + return strcmp ((aa < 0 ? last : sort_hack_cmp_names_kludge[aa]), + (bb < 0 ? last : sort_hack_cmp_names_kludge[bb])); + } +} + + +static void +initialize_sort_map (state *s) +{ + Display *dpy = GDK_DISPLAY(); + saver_preferences *p = &s->prefs; + int i, j; + + if (s->list_elt_to_hack_number) free (s->list_elt_to_hack_number); + if (s->hack_number_to_list_elt) free (s->hack_number_to_list_elt); + if (s->hacks_available_p) free (s->hacks_available_p); + + s->list_elt_to_hack_number = (int *) + calloc (sizeof(int), p->screenhacks_count + 1); + s->hack_number_to_list_elt = (int *) + calloc (sizeof(int), p->screenhacks_count + 1); + s->hacks_available_p = (Bool *) + calloc (sizeof(Bool), p->screenhacks_count + 1); + s->total_available = 0; + + /* Check which hacks actually exist on $PATH + */ + for (i = 0; i < p->screenhacks_count; i++) + { + screenhack *hack = p->screenhacks[i]; + int on = on_path_p (hack->command) ? 1 : 0; + s->hacks_available_p[i] = on; + s->total_available += on; + } + + /* Initialize list->hack table to unsorted mapping, omitting nonexistent + hacks, if desired. + */ + j = 0; + for (i = 0; i < p->screenhacks_count; i++) + { + if (!p->ignore_uninstalled_p || + s->hacks_available_p[i]) + s->list_elt_to_hack_number[j++] = i; + } + s->list_count = j; + + for (; j < p->screenhacks_count; j++) + s->list_elt_to_hack_number[j] = -1; + + + /* Generate list of sortable names (once) + */ + sort_hack_cmp_names_kludge = (char **) + calloc (sizeof(char *), p->screenhacks_count); + for (i = 0; i < p->screenhacks_count; i++) + { + screenhack *hack = p->screenhacks[i]; + char *name = (hack->name && *hack->name + ? strdup (hack->name) + : make_hack_name (dpy, hack->command)); + char *str; + for (str = name; *str; str++) + *str = tolower(*str); + sort_hack_cmp_names_kludge[i] = name; + } + + /* Sort list->hack map alphabetically + */ + qsort (s->list_elt_to_hack_number, + p->screenhacks_count, + sizeof(*s->list_elt_to_hack_number), + sort_hack_cmp); + + /* Free names + */ + for (i = 0; i < p->screenhacks_count; i++) + free (sort_hack_cmp_names_kludge[i]); + free (sort_hack_cmp_names_kludge); + sort_hack_cmp_names_kludge = 0; + + /* Build inverse table */ + for (i = 0; i < p->screenhacks_count; i++) + { + int n = s->list_elt_to_hack_number[i]; + if (n != -1) + s->hack_number_to_list_elt[n] = i; + } +} + + +static int +maybe_reload_init_file (state *s) +{ + Display *dpy = GDK_DISPLAY(); + saver_preferences *p = &s->prefs; + int status = 0; + + static Bool reentrant_lock = False; + if (reentrant_lock) return 0; + reentrant_lock = True; + + if (init_file_changed_p (p)) + { + const char *f = init_file_name(); + char *b; + int list_elt; + GtkWidget *list; + + if (!f || !*f) return 0; + b = (char *) malloc (strlen(f) + 1024); + sprintf (b, + _("Warning:\n\n" + "file \"%s\" has changed, reloading.\n"), + f); + warning_dialog (s->toplevel_widget, b, D_NONE, 100); + free (b); + + load_init_file (dpy, p); + initialize_sort_map (s); + + list_elt = selected_list_element (s); + list = name_to_widget (s, "list"); + gtk_container_foreach (GTK_CONTAINER (list), widget_deleter, NULL); + populate_hack_list (s); + force_list_select_item (s, list, list_elt, True); + populate_prefs_page (s); + populate_demo_window (s, list_elt); + ensure_selected_item_visible (list); + + status = 1; + } + + reentrant_lock = False; + return status; +} + + + +/* Making the preview window have the right X visual (so that GL works.) + */ + +static Visual *get_best_gl_visual (state *); + +static GdkVisual * +x_visual_to_gdk_visual (Visual *xv) +{ + GList *gvs = gdk_list_visuals(); + if (!xv) return gdk_visual_get_system(); + for (; gvs; gvs = gvs->next) + { + GdkVisual *gv = (GdkVisual *) gvs->data; + if (xv == GDK_VISUAL_XVISUAL (gv)) + return gv; + } + fprintf (stderr, "%s: couldn't convert X Visual 0x%lx to a GdkVisual\n", + blurb(), (unsigned long) xv->visualid); + abort(); +} + +static void +clear_preview_window (state *s) +{ + GtkWidget *p; + GdkWindow *window; + GtkStyle *style; + + if (!s->toplevel_widget) return; /* very early */ + p = name_to_widget (s, "preview"); + window = GET_WINDOW (p); + + if (!window) return; + + /* Flush the widget background down into the window, in case a subproc + has changed it. */ + style = gtk_widget_get_style (p); + gdk_window_set_background (window, &style->bg[GTK_STATE_NORMAL]); + gdk_window_clear (window); + + { + int list_elt = selected_list_element (s); + int hack_number = (list_elt >= 0 + ? s->list_elt_to_hack_number[list_elt] + : -1); + Bool available_p = (hack_number >= 0 + ? s->hacks_available_p [hack_number] + : True); + Bool nothing_p = (s->total_available < 5); + +#ifdef HAVE_GTK2 + GtkWidget *notebook = name_to_widget (s, "preview_notebook"); + gtk_notebook_set_page (GTK_NOTEBOOK (notebook), + (s->running_preview_error_p + ? (available_p ? 1 : + nothing_p ? 3 : 2) + : 0)); +#else /* !HAVE_GTK2 */ + if (s->running_preview_error_p) + { + const char * const lines1[] = { N_("No Preview"), N_("Available") }; + const char * const lines2[] = { N_("Not"), N_("Installed") }; + int nlines = countof(lines1); + int lh = p->style->font->ascent + p->style->font->descent; + int y, i; + gint w, h; + + const char * const *lines = (available_p ? lines1 : lines2); + + gdk_window_get_size (window, &w, &h); + y = (h - (lh * nlines)) / 2; + y += p->style->font->ascent; + for (i = 0; i < nlines; i++) + { + int sw = gdk_string_width (p->style->font, _(lines[i])); + int x = (w - sw) / 2; + gdk_draw_string (window, p->style->font, + p->style->fg_gc[GTK_STATE_NORMAL], + x, y, _(lines[i])); + y += lh; + } + } +#endif /* !HAVE_GTK2 */ + } + + gdk_flush (); +} + + +static void +reset_preview_window (state *s) +{ + /* On some systems (most recently, MacOS X) OpenGL programs get confused + when you kill one and re-start another on the same window. So maybe + it's best to just always destroy and recreate the preview window + when changing hacks, instead of always trying to reuse the same one? + */ + GtkWidget *pr = name_to_widget (s, "preview"); + if (GET_REALIZED (pr)) + { + GdkWindow *window = GET_WINDOW (pr); + Window oid = (window ? GDK_WINDOW_XWINDOW (window) : 0); + Window id; + gtk_widget_hide (pr); + gtk_widget_unrealize (pr); + gtk_widget_realize (pr); + gtk_widget_show (pr); + id = (window ? GDK_WINDOW_XWINDOW (window) : 0); + if (s->debug_p) + fprintf (stderr, "%s: window id 0x%X -> 0x%X\n", blurb(), + (unsigned int) oid, + (unsigned int) id); + } +} + + +static void +fix_preview_visual (state *s) +{ + GtkWidget *widget = name_to_widget (s, "preview"); + Visual *xvisual = get_best_gl_visual (s); + GdkVisual *visual = x_visual_to_gdk_visual (xvisual); + GdkVisual *dvisual = gdk_visual_get_system(); + GdkColormap *cmap = (visual == dvisual + ? gdk_colormap_get_system () + : gdk_colormap_new (visual, False)); + + if (s->debug_p) + fprintf (stderr, "%s: using %s visual 0x%lx\n", blurb(), + (visual == dvisual ? "default" : "non-default"), + (xvisual ? (unsigned long) xvisual->visualid : 0L)); + + if (!GET_REALIZED (widget) || + gtk_widget_get_visual (widget) != visual) + { + gtk_widget_unrealize (widget); + gtk_widget_set_visual (widget, visual); + gtk_widget_set_colormap (widget, cmap); + gtk_widget_realize (widget); + } + + /* Set the Widget colors to be white-on-black. */ + { + GdkWindow *window = GET_WINDOW (widget); + GtkStyle *style = gtk_style_copy (gtk_widget_get_style (widget)); + GdkColormap *cmap = gtk_widget_get_colormap (widget); + GdkColor *fg = &style->fg[GTK_STATE_NORMAL]; + GdkColor *bg = &style->bg[GTK_STATE_NORMAL]; + GdkGC *fgc = gdk_gc_new(window); + GdkGC *bgc = gdk_gc_new(window); + if (!gdk_color_white (cmap, fg)) abort(); + if (!gdk_color_black (cmap, bg)) abort(); + gdk_gc_set_foreground (fgc, fg); + gdk_gc_set_background (fgc, bg); + gdk_gc_set_foreground (bgc, bg); + gdk_gc_set_background (bgc, fg); + style->fg_gc[GTK_STATE_NORMAL] = fgc; + style->bg_gc[GTK_STATE_NORMAL] = fgc; + gtk_widget_set_style (widget, style); + + /* For debugging purposes, put a title on the window (so that + it can be easily found in the output of "xwininfo -tree".) + */ + gdk_window_set_title (window, "Preview"); + } + + gtk_widget_show (widget); +} + + +/* Subprocesses + */ + +static char * +subproc_pretty_name (state *s) +{ + if (s->running_preview_cmd) + { + char *ps = strdup (s->running_preview_cmd); + char *ss = strchr (ps, ' '); + if (ss) *ss = 0; + ss = strrchr (ps, '/'); + if (!ss) + ss = ps; + else + { + ss = strdup (ss+1); + free (ps); + } + return ss; + } + else + return strdup ("???"); +} + + +static void +reap_zombies (state *s) +{ + int wait_status = 0; + pid_t pid; + while ((pid = waitpid (-1, &wait_status, WNOHANG|WUNTRACED)) > 0) + { + if (s->debug_p) + { + if (pid == s->running_preview_pid) + { + char *ss = subproc_pretty_name (s); + fprintf (stderr, "%s: pid %lu (%s) died\n", blurb(), + (unsigned long) pid, ss); + free (ss); + } + else + fprintf (stderr, "%s: pid %lu died\n", blurb(), + (unsigned long) pid); + } + } +} + + +/* Mostly lifted from driver/subprocs.c */ +static Visual * +get_best_gl_visual (state *s) +{ + Display *dpy = GDK_DISPLAY(); + pid_t forked; + int fds [2]; + int in, out; + char buf[1024]; + + char *av[10]; + int ac = 0; + + av[ac++] = "xscreensaver-gl-helper"; + av[ac] = 0; + + if (pipe (fds)) + { + perror ("error creating pipe:"); + return 0; + } + + in = fds [0]; + out = fds [1]; + + switch ((int) (forked = fork ())) + { + case -1: + { + sprintf (buf, "%s: couldn't fork", blurb()); + perror (buf); + exit (1); + } + case 0: + { + int stdout_fd = 1; + + close (in); /* don't need this one */ + close (ConnectionNumber (dpy)); /* close display fd */ + + if (dup2 (out, stdout_fd) < 0) /* pipe stdout */ + { + perror ("could not dup() a new stdout:"); + return 0; + } + + execvp (av[0], av); /* shouldn't return. */ + + if (errno != ENOENT) + { + /* Ignore "no such file or directory" errors, unless verbose. + Issue all other exec errors, though. */ + sprintf (buf, "%s: running %s", blurb(), av[0]); + perror (buf); + } + + /* Note that one must use _exit() instead of exit() in procs forked + off of Gtk programs -- Gtk installs an atexit handler that has a + copy of the X connection (which we've already closed, for safety.) + If one uses exit() instead of _exit(), then one sometimes gets a + spurious "Gdk-ERROR: Fatal IO error on X server" error message. + */ + _exit (1); /* exits fork */ + break; + } + default: + { + int result = 0; + int wait_status = 0; + + FILE *f = fdopen (in, "r"); + unsigned int v = 0; + char c; + + close (out); /* don't need this one */ + + *buf = 0; + if (!fgets (buf, sizeof(buf)-1, f)) + *buf = 0; + fclose (f); + + /* Wait for the child to die. */ + waitpid (-1, &wait_status, 0); + + if (1 == sscanf (buf, "0x%x %c", &v, &c)) + result = (int) v; + + if (result == 0) + { + if (s->debug_p) + fprintf (stderr, "%s: %s did not report a GL visual!\n", + blurb(), av[0]); + return 0; + } + else + { + Visual *v = id_to_visual (DefaultScreenOfDisplay (dpy), result); + if (s->debug_p) + fprintf (stderr, "%s: %s says the GL visual is 0x%X.\n", + blurb(), av[0], result); + if (!v) abort(); + return v; + } + } + } + + abort(); +} + + +static void +kill_preview_subproc (state *s, Bool reset_p) +{ + s->running_preview_error_p = False; + + reap_zombies (s); + clear_preview_window (s); + + if (s->subproc_check_timer_id) + { + gtk_timeout_remove (s->subproc_check_timer_id); + s->subproc_check_timer_id = 0; + s->subproc_check_countdown = 0; + } + + if (s->running_preview_pid) + { + int status = kill (s->running_preview_pid, SIGTERM); + char *ss = subproc_pretty_name (s); + + if (status < 0) + { + if (errno == ESRCH) + { + if (s->debug_p) + fprintf (stderr, "%s: pid %lu (%s) was already dead.\n", + blurb(), (unsigned long) s->running_preview_pid, ss); + } + else + { + char buf [1024]; + sprintf (buf, "%s: couldn't kill pid %lu (%s)", + blurb(), (unsigned long) s->running_preview_pid, ss); + perror (buf); + } + } + else { + int endstatus; + waitpid(s->running_preview_pid, &endstatus, 0); + if (s->debug_p) + fprintf (stderr, "%s: killed pid %lu (%s)\n", blurb(), + (unsigned long) s->running_preview_pid, ss); + } + + free (ss); + s->running_preview_pid = 0; + if (s->running_preview_cmd) free (s->running_preview_cmd); + s->running_preview_cmd = 0; + } + + reap_zombies (s); + + if (reset_p) + { + reset_preview_window (s); + clear_preview_window (s); + } +} + + +/* Immediately and unconditionally launches the given process, + after appending the -window-id option; sets running_preview_pid. + */ +static void +launch_preview_subproc (state *s) +{ + saver_preferences *p = &s->prefs; + Window id; + char *new_cmd = 0; + pid_t forked; + const char *cmd = s->desired_preview_cmd; + + GtkWidget *pr = name_to_widget (s, "preview"); + GdkWindow *window; + + reset_preview_window (s); + + window = GET_WINDOW (pr); + + s->running_preview_error_p = False; + + if (s->preview_suppressed_p) + { + kill_preview_subproc (s, False); + goto DONE; + } + + new_cmd = malloc (strlen (cmd) + 40); + + id = (window ? GDK_WINDOW_XWINDOW (window) : 0); + if (id == 0) + { + /* No window id? No command to run. */ + free (new_cmd); + new_cmd = 0; + } + else + { + strcpy (new_cmd, cmd); + sprintf (new_cmd + strlen (new_cmd), " -window-id 0x%X", + (unsigned int) id); + } + + kill_preview_subproc (s, False); + if (! new_cmd) + { + s->running_preview_error_p = True; + clear_preview_window (s); + goto DONE; + } + + switch ((int) (forked = fork ())) + { + case -1: + { + char buf[255]; + sprintf (buf, "%s: couldn't fork", blurb()); + perror (buf); + s->running_preview_error_p = True; + goto DONE; + break; + } + case 0: + { + close (ConnectionNumber (GDK_DISPLAY())); + + hack_subproc_environment (id, s->debug_p); + + usleep (250000); /* pause for 1/4th second before launching, to give + the previous program time to die and flush its X + buffer, so we don't get leftover turds on the + window. */ + + exec_command (p->shell, new_cmd, p->nice_inferior); + /* Don't bother printing an error message when we are unable to + exec subprocesses; we handle that by polling the pid later. + + Note that one must use _exit() instead of exit() in procs forked + off of Gtk programs -- Gtk installs an atexit handler that has a + copy of the X connection (which we've already closed, for safety.) + If one uses exit() instead of _exit(), then one sometimes gets a + spurious "Gdk-ERROR: Fatal IO error on X server" error message. + */ + _exit (1); /* exits child fork */ + break; + + default: + + if (s->running_preview_cmd) free (s->running_preview_cmd); + s->running_preview_cmd = strdup (s->desired_preview_cmd); + s->running_preview_pid = forked; + + if (s->debug_p) + { + char *ss = subproc_pretty_name (s); + fprintf (stderr, "%s: forked %lu (%s)\n", blurb(), + (unsigned long) forked, ss); + free (ss); + } + break; + } + } + + schedule_preview_check (s); + + DONE: + if (new_cmd) free (new_cmd); + new_cmd = 0; +} + + +/* Modify $DISPLAY and $PATH for the benefit of subprocesses. + */ +static void +hack_environment (state *s) +{ + static const char *def_path = +# ifdef DEFAULT_PATH_PREFIX + DEFAULT_PATH_PREFIX; +# else + ""; +# endif + + Display *dpy = GDK_DISPLAY(); + const char *odpy = DisplayString (dpy); + char *ndpy = (char *) malloc(strlen(odpy) + 20); + strcpy (ndpy, "DISPLAY="); + strcat (ndpy, odpy); + if (putenv (ndpy)) + abort (); + + if (s->debug_p) + fprintf (stderr, "%s: %s\n", blurb(), ndpy); + + /* don't free(ndpy) -- some implementations of putenv (BSD 4.4, glibc + 2.0) copy the argument, but some (libc4,5, glibc 2.1.2) do not. + So we must leak it (and/or the previous setting). Yay. + */ + + if (def_path && *def_path) + { + const char *opath = getenv("PATH"); + char *npath = (char *) malloc(strlen(def_path) + strlen(opath) + 20); + strcpy (npath, "PATH="); + strcat (npath, def_path); + strcat (npath, ":"); + strcat (npath, opath); + + if (putenv (npath)) + abort (); + /* do not free(npath) -- see above */ + + if (s->debug_p) + fprintf (stderr, "%s: added \"%s\" to $PATH\n", blurb(), def_path); + } +} + + +static void +hack_subproc_environment (Window preview_window_id, Bool debug_p) +{ + /* Store a window ID in $XSCREENSAVER_WINDOW -- this isn't strictly + necessary yet, but it will make programs work if we had invoked + them with "-root" and not with "-window-id" -- which, of course, + doesn't happen. + */ + char *nssw = (char *) malloc (40); + sprintf (nssw, "XSCREENSAVER_WINDOW=0x%X", (unsigned int) preview_window_id); + + /* Allegedly, BSD 4.3 didn't have putenv(), but nobody runs such systems + any more, right? It's not Posix, but everyone seems to have it. */ + if (putenv (nssw)) + abort (); + + if (debug_p) + fprintf (stderr, "%s: %s\n", blurb(), nssw); + + /* do not free(nssw) -- see above */ +} + + +/* Called from a timer: + Launches the currently-chosen subprocess, if it's not already running. + If there's a different process running, kills it. + */ +static int +update_subproc_timer (gpointer data) +{ + state *s = (state *) data; + if (! s->desired_preview_cmd) + kill_preview_subproc (s, True); + else if (!s->running_preview_cmd || + !!strcmp (s->desired_preview_cmd, s->running_preview_cmd)) + launch_preview_subproc (s); + + s->subproc_timer_id = 0; + return FALSE; /* do not re-execute timer */ +} + +static int +settings_timer (gpointer data) +{ + settings_cb (0, 0); + return FALSE; +} + + +/* Call this when you think you might want a preview process running. + It will set a timer that will actually launch that program a second + from now, if you haven't changed your mind (to avoid double-click + spazzing, etc.) `cmd' may be null meaning "no process". + */ +static void +schedule_preview (state *s, const char *cmd) +{ + int delay = 1000 * 0.5; /* 1/2 second hysteresis */ + + if (s->debug_p) + { + if (cmd) + fprintf (stderr, "%s: scheduling preview \"%s\"\n", blurb(), cmd); + else + fprintf (stderr, "%s: scheduling preview death\n", blurb()); + } + + if (s->desired_preview_cmd) free (s->desired_preview_cmd); + s->desired_preview_cmd = (cmd ? strdup (cmd) : 0); + + if (s->subproc_timer_id) + gtk_timeout_remove (s->subproc_timer_id); + s->subproc_timer_id = gtk_timeout_add (delay, update_subproc_timer, s); +} + + +/* Called from a timer: + Checks to see if the subproc that should be running, actually is. + */ +static int +check_subproc_timer (gpointer data) +{ + state *s = (state *) data; + Bool again_p = True; + + if (s->running_preview_error_p || /* already dead */ + s->running_preview_pid <= 0) + { + again_p = False; + } + else + { + int status; + reap_zombies (s); + status = kill (s->running_preview_pid, 0); + if (status < 0 && errno == ESRCH) + s->running_preview_error_p = True; + + if (s->debug_p) + { + char *ss = subproc_pretty_name (s); + fprintf (stderr, "%s: timer: pid %lu (%s) is %s\n", blurb(), + (unsigned long) s->running_preview_pid, ss, + (s->running_preview_error_p ? "dead" : "alive")); + free (ss); + } + + if (s->running_preview_error_p) + { + clear_preview_window (s); + again_p = False; + } + } + + /* Otherwise, it's currently alive. We might be checking again, or we + might be satisfied. */ + + if (--s->subproc_check_countdown <= 0) + again_p = False; + + if (again_p) + return TRUE; /* re-execute timer */ + else + { + s->subproc_check_timer_id = 0; + s->subproc_check_countdown = 0; + return FALSE; /* do not re-execute timer */ + } +} + + +/* Call this just after launching a subprocess. + This sets a timer that will, five times a second for two seconds, + check whether the program is still running. The assumption here + is that if the process didn't stay up for more than a couple of + seconds, then either the program doesn't exist, or it doesn't + take a -window-id argument. + */ +static void +schedule_preview_check (state *s) +{ + int seconds = 2; + int ticks = 5; + + if (s->debug_p) + fprintf (stderr, "%s: scheduling check\n", blurb()); + + if (s->subproc_check_timer_id) + gtk_timeout_remove (s->subproc_check_timer_id); + s->subproc_check_timer_id = + gtk_timeout_add (1000 / ticks, + check_subproc_timer, (gpointer) s); + s->subproc_check_countdown = ticks * seconds; +} + + +static Bool +screen_blanked_p (void) +{ + Atom type; + int format; + unsigned long nitems, bytesafter; + unsigned char *dataP = 0; + Display *dpy = GDK_DISPLAY(); + Bool blanked_p = False; + + if (XGetWindowProperty (dpy, RootWindow (dpy, 0), /* always screen #0 */ + XA_SCREENSAVER_STATUS, + 0, 3, False, XA_INTEGER, + &type, &format, &nitems, &bytesafter, + &dataP) + == Success + && type == XA_INTEGER + && nitems >= 3 + && dataP) + { + Atom *data = (Atom *) dataP; + blanked_p = (data[0] == XA_BLANK || data[0] == XA_LOCK); + } + + if (dataP) XFree (dataP); + + return blanked_p; +} + +/* Wake up every now and then and see if the screen is blanked. + If it is, kill off the small-window demo -- no point in wasting + cycles by running two screensavers at once... + */ +static int +check_blanked_timer (gpointer data) +{ + state *s = (state *) data; + Bool blanked_p = screen_blanked_p (); + if (blanked_p && s->running_preview_pid) + { + if (s->debug_p) + fprintf (stderr, "%s: screen is blanked: killing preview\n", blurb()); + kill_preview_subproc (s, True); + } + + return True; /* re-execute timer */ +} + + +/* How many screens are there (including Xinerama.) + */ +static int +screen_count (Display *dpy) +{ + int nscreens = ScreenCount(dpy); +# ifdef HAVE_XINERAMA + if (nscreens <= 1) + { + int event_number, error_number; + if (XineramaQueryExtension (dpy, &event_number, &error_number) && + XineramaIsActive (dpy)) + { + XineramaScreenInfo *xsi = XineramaQueryScreens (dpy, &nscreens); + if (xsi) XFree (xsi); + } + } +# endif /* HAVE_XINERAMA */ + + return nscreens; +} + + +/* Setting window manager icon + */ + +static void +init_icon (GdkWindow *window) +{ + GdkBitmap *mask = 0; + GdkColor transp; + GdkPixmap *pixmap = + gdk_pixmap_create_from_xpm_d (window, &mask, &transp, + (gchar **) logo_50_xpm); + if (pixmap) + gdk_window_set_icon (window, 0, pixmap, mask); +} + + +/* The main demo-mode command loop. + */ + +#if 0 +static Bool +mapper (XrmDatabase *db, XrmBindingList bindings, XrmQuarkList quarks, + XrmRepresentation *type, XrmValue *value, XPointer closure) +{ + int i; + for (i = 0; quarks[i]; i++) + { + if (bindings[i] == XrmBindTightly) + fprintf (stderr, (i == 0 ? "" : ".")); + else if (bindings[i] == XrmBindLoosely) + fprintf (stderr, "*"); + else + fprintf (stderr, " ??? "); + fprintf(stderr, "%s", XrmQuarkToString (quarks[i])); + } + + fprintf (stderr, ": %s\n", (char *) value->addr); + + return False; +} +#endif + + +static Window +gnome_screensaver_window (Screen *screen) +{ + Display *dpy = DisplayOfScreen (screen); + Window root = RootWindowOfScreen (screen); + Window parent, *kids; + unsigned int nkids; + Window gnome_window = 0; + int i; + + if (! XQueryTree (dpy, root, &root, &parent, &kids, &nkids)) + abort (); + for (i = 0; i < nkids; i++) + { + Atom type; + int format; + unsigned long nitems, bytesafter; + unsigned char *name; + if (XGetWindowProperty (dpy, kids[i], XA_WM_COMMAND, 0, 128, + False, XA_STRING, &type, &format, &nitems, + &bytesafter, &name) + == Success + && type != None + && !strcmp ((char *) name, "gnome-screensaver")) + { + gnome_window = kids[i]; + break; + } + } + + if (kids) XFree ((char *) kids); + return gnome_window; +} + +static Bool +gnome_screensaver_active_p (void) +{ + Display *dpy = GDK_DISPLAY(); + Window w = gnome_screensaver_window (DefaultScreenOfDisplay (dpy)); + return (w ? True : False); +} + +static void +kill_gnome_screensaver (void) +{ + Display *dpy = GDK_DISPLAY(); + Window w = gnome_screensaver_window (DefaultScreenOfDisplay (dpy)); + if (w) XKillClient (dpy, (XID) w); +} + +static Bool +kde_screensaver_active_p (void) +{ + FILE *p = popen ("dcop kdesktop KScreensaverIface isEnabled 2>/dev/null", + "r"); + char buf[255]; + fgets (buf, sizeof(buf)-1, p); + pclose (p); + if (!strcmp (buf, "true\n")) + return True; + else + return False; +} + +static void +kill_kde_screensaver (void) +{ + system ("dcop kdesktop KScreensaverIface enable false"); +} + + +static void +the_network_is_not_the_computer (state *s) +{ + Display *dpy = GDK_DISPLAY(); + char *rversion = 0, *ruser = 0, *rhost = 0; + char *luser, *lhost; + char *msg = 0; + struct passwd *p = getpwuid (getuid ()); + const char *d = DisplayString (dpy); + +# if defined(HAVE_UNAME) + struct utsname uts; + if (uname (&uts) < 0) + lhost = ""; + else + lhost = uts.nodename; +# elif defined(VMS) + strcpy (lhost, getenv("SYS$NODE")); +# else /* !HAVE_UNAME && !VMS */ + strcat (lhost, ""); +# endif /* !HAVE_UNAME && !VMS */ + + if (p && p->pw_name) + luser = p->pw_name; + else + luser = "???"; + + server_xscreensaver_version (dpy, &rversion, &ruser, &rhost); + + /* Make a buffer that's big enough for a number of copies of all the + strings, plus some. */ + msg = (char *) malloc (10 * ((rversion ? strlen(rversion) : 0) + + (ruser ? strlen(ruser) : 0) + + (rhost ? strlen(rhost) : 0) + + strlen(lhost) + + strlen(luser) + + strlen(d) + + 1024)); + *msg = 0; + + if (!rversion || !*rversion) + { + sprintf (msg, + _("Warning:\n\n" + "The XScreenSaver daemon doesn't seem to be running\n" + "on display \"%s\". Launch it now?"), + d); + } + else if (p && ruser && *ruser && !!strcmp (ruser, p->pw_name)) + { + /* Warn that the two processes are running as different users. + */ + sprintf(msg, + _("Warning:\n\n" + "%s is running as user \"%s\" on host \"%s\".\n" + "But the xscreensaver managing display \"%s\"\n" + "is running as user \"%s\" on host \"%s\".\n" + "\n" + "Since they are different users, they won't be reading/writing\n" + "the same ~/.xscreensaver file, so %s isn't\n" + "going to work right.\n" + "\n" + "You should either re-run %s as \"%s\", or re-run\n" + "xscreensaver as \"%s\".\n" + "\n" + "Restart the xscreensaver daemon now?\n"), + progname, luser, lhost, + d, + (ruser ? ruser : "???"), (rhost ? rhost : "???"), + progname, + progname, (ruser ? ruser : "???"), + luser); + } + else if (rhost && *rhost && !!strcmp (rhost, lhost)) + { + /* Warn that the two processes are running on different hosts. + */ + sprintf (msg, + _("Warning:\n\n" + "%s is running as user \"%s\" on host \"%s\".\n" + "But the xscreensaver managing display \"%s\"\n" + "is running as user \"%s\" on host \"%s\".\n" + "\n" + "If those two machines don't share a file system (that is,\n" + "if they don't see the same ~%s/.xscreensaver file) then\n" + "%s won't work right.\n" + "\n" + "Restart the daemon on \"%s\" as \"%s\" now?\n"), + progname, luser, lhost, + d, + (ruser ? ruser : "???"), (rhost ? rhost : "???"), + luser, + progname, + lhost, luser); + } + else if (!!strcmp (rversion, s->short_version)) + { + /* Warn that the version numbers don't match. + */ + sprintf (msg, + _("Warning:\n\n" + "This is %s version %s.\n" + "But the xscreensaver managing display \"%s\"\n" + "is version %s. This could cause problems.\n" + "\n" + "Restart the xscreensaver daemon now?\n"), + progname, s->short_version, + d, + rversion); + } + + + if (*msg) + warning_dialog (s->toplevel_widget, msg, D_LAUNCH, 1); + + if (rversion) free (rversion); + if (ruser) free (ruser); + if (rhost) free (rhost); + free (msg); + msg = 0; + + /* Note: since these dialogs are not modal, they will stack up. + So we do this check *after* popping up the "xscreensaver is not + running" dialog so that these are on top. Good enough. + */ + + if (gnome_screensaver_active_p ()) + warning_dialog (s->toplevel_widget, + _("Warning:\n\n" + "The GNOME screensaver daemon appears to be running.\n" + "It must be stopped for XScreenSaver to work properly.\n" + "\n" + "Stop the GNOME screen saver daemon now?\n"), + D_GNOME, 1); + + if (kde_screensaver_active_p ()) + warning_dialog (s->toplevel_widget, + _("Warning:\n\n" + "The KDE screen saver daemon appears to be running.\n" + "It must be stopped for XScreenSaver to work properly.\n" + "\n" + "Stop the KDE screen saver daemon now?\n"), + D_KDE, 1); +} + + +/* We use this error handler so that X errors are preceeded by the name + of the program that generated them. + */ +static int +demo_ehandler (Display *dpy, XErrorEvent *error) +{ + state *s = global_state_kludge; /* I hate C so much... */ + fprintf (stderr, "\nX error in %s:\n", blurb()); + XmuPrintDefaultErrorMessage (dpy, error, stderr); + kill_preview_subproc (s, False); + exit (-1); + return 0; +} + + +/* We use this error handler so that Gtk/Gdk errors are preceeded by the name + of the program that generated them; and also that we can ignore one + particular bogus error message that Gdk madly spews. + */ +static void +g_log_handler (const gchar *log_domain, GLogLevelFlags log_level, + const gchar *message, gpointer user_data) +{ + /* Ignore the message "Got event for unknown window: 0x...". + Apparently some events are coming in for the xscreensaver window + (presumably reply events related to the ClientMessage) and Gdk + feels the need to complain about them. So, just suppress any + messages that look like that one. + */ + if (strstr (message, "unknown window")) + return; + + fprintf (stderr, "%s: %s-%s: %s%s", blurb(), + (log_domain ? log_domain : progclass), + (log_level == G_LOG_LEVEL_ERROR ? "error" : + log_level == G_LOG_LEVEL_CRITICAL ? "critical" : + log_level == G_LOG_LEVEL_WARNING ? "warning" : + log_level == G_LOG_LEVEL_MESSAGE ? "message" : + log_level == G_LOG_LEVEL_INFO ? "info" : + log_level == G_LOG_LEVEL_DEBUG ? "debug" : "???"), + message, + ((!*message || message[strlen(message)-1] != '\n') + ? "\n" : "")); +} + + +#ifdef __GNUC__ + __extension__ /* shut up about "string length is greater than the length + ISO C89 compilers are required to support" when including + the .ad file... */ +#endif + +STFU +static char *defaults[] = { +#include "XScreenSaver_ad.h" + 0 +}; + +#if 0 +#ifdef HAVE_CRAPPLET +static struct poptOption crapplet_options[] = { + {NULL, '\0', 0, NULL, 0} +}; +#endif /* HAVE_CRAPPLET */ +#endif /* 0 */ + +const char *usage = "[--display dpy] [--prefs | --settings]" +# ifdef HAVE_CRAPPLET + " [--crapplet]" +# endif + "\n\t\t [--debug] [--sync] [--no-xshm] [--configdir dir]"; + +static void +map_popup_window_cb (GtkWidget *w, gpointer user_data) +{ + state *s = (state *) user_data; + Boolean oi = s->initializing_p; +#ifndef HAVE_GTK2 + GtkLabel *label = GTK_LABEL (name_to_widget (s, "doc")); +#endif + s->initializing_p = True; +#ifndef HAVE_GTK2 + eschew_gtk_lossage (label); +#endif + s->initializing_p = oi; +} + + +#if 0 +static void +print_widget_tree (GtkWidget *w, int depth) +{ + int i; + for (i = 0; i < depth; i++) + fprintf (stderr, " "); + fprintf (stderr, "%s\n", gtk_widget_get_name (w)); + + if (GTK_IS_LIST (w)) + { + for (i = 0; i < depth+1; i++) + fprintf (stderr, " "); + fprintf (stderr, "...list kids...\n"); + } + else if (GTK_IS_CONTAINER (w)) + { + GList *kids = gtk_container_children (GTK_CONTAINER (w)); + while (kids) + { + print_widget_tree (GTK_WIDGET (kids->data), depth+1); + kids = kids->next; + } + } +} +#endif /* 0 */ + +static int +delayed_scroll_kludge (gpointer data) +{ + state *s = (state *) data; + GtkWidget *w = GTK_WIDGET (name_to_widget (s, "list")); + ensure_selected_item_visible (w); + + /* Oh, this is just fucking lovely, too. */ + w = GTK_WIDGET (name_to_widget (s, "preview")); + gtk_widget_hide (w); + gtk_widget_show (w); + + return FALSE; /* do not re-execute timer */ +} + +#ifdef HAVE_GTK2 + +GtkWidget * +create_xscreensaver_demo (void) +{ + GtkWidget *nb; + + nb = name_to_widget (global_state_kludge, "preview_notebook"); + gtk_notebook_set_show_tabs (GTK_NOTEBOOK (nb), FALSE); + + return name_to_widget (global_state_kludge, "xscreensaver_demo"); +} + +GtkWidget * +create_xscreensaver_settings_dialog (void) +{ + GtkWidget *w, *box; + + box = name_to_widget (global_state_kludge, "dialog_action_area"); + + w = name_to_widget (global_state_kludge, "adv_button"); + gtk_button_box_set_child_secondary (GTK_BUTTON_BOX (box), w, TRUE); + + w = name_to_widget (global_state_kludge, "std_button"); + gtk_button_box_set_child_secondary (GTK_BUTTON_BOX (box), w, TRUE); + + return name_to_widget (global_state_kludge, "xscreensaver_settings_dialog"); +} + +#endif /* HAVE_GTK2 */ + +int +main (int argc, char **argv) +{ + XtAppContext app; + state S, *s; + saver_preferences *p; + Bool prefs_p = False; + Bool settings_p = False; + int i; + Display *dpy; + Widget toplevel_shell; + char *real_progname = argv[0]; + char *window_title; + char *geom = 0; + Bool crapplet_p = False; + char *str; + +#ifdef ENABLE_NLS + bindtextdomain (GETTEXT_PACKAGE, LOCALEDIR); + textdomain (GETTEXT_PACKAGE); + +# ifdef HAVE_GTK2 + bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8"); +# else /* !HAVE_GTK2 */ + if (!setlocale (LC_ALL, "")) + fprintf (stderr, "%s: locale not supported by C library\n", real_progname); +# endif /* !HAVE_GTK2 */ + +#endif /* ENABLE_NLS */ + + str = strrchr (real_progname, '/'); + if (str) real_progname = str+1; + + s = &S; + memset (s, 0, sizeof(*s)); + s->initializing_p = True; + p = &s->prefs; + + global_state_kludge = s; /* I hate C so much... */ + + progname = real_progname; + + s->short_version = (char *) malloc (5); + memcpy (s->short_version, screensaver_id + 17, 4); + s->short_version [4] = 0; + + + /* Register our error message logger for every ``log domain'' known. + There's no way to do this globally, so I grepped the Gtk/Gdk sources + for all of the domains that seem to be in use. + */ + { + const char * const domains[] = { 0, + "Gtk", "Gdk", "GLib", "GModule", + "GThread", "Gnome", "GnomeUI" }; + for (i = 0; i < countof(domains); i++) + g_log_set_handler (domains[i], G_LOG_LEVEL_MASK, g_log_handler, 0); + } + +#ifdef DEFAULT_ICONDIR /* from -D on compile line */ +# ifndef HAVE_GTK2 + { + const char *dir = DEFAULT_ICONDIR; + if (*dir) add_pixmap_directory (dir); + } +# endif /* !HAVE_GTK2 */ +#endif /* DEFAULT_ICONDIR */ + + /* This is gross, but Gtk understands --display and not -display... + */ + for (i = 1; i < argc; i++) + if (argv[i][0] && argv[i][1] && + !strncmp(argv[i], "-display", strlen(argv[i]))) + argv[i] = "--display"; + + + /* We need to parse this arg really early... Sigh. */ + for (i = 1; i < argc; i++) + { + if (argv[i] && + (!strcmp(argv[i], "--crapplet") || + !strcmp(argv[i], "--capplet"))) + { +# if defined(HAVE_CRAPPLET) || defined(HAVE_GTK2) + int j; + crapplet_p = True; + for (j = i; j < argc; j++) /* remove it from the list */ + argv[j] = argv[j+1]; + argc--; +# else /* !HAVE_CRAPPLET && !HAVE_GTK2 */ + fprintf (stderr, "%s: not compiled with --crapplet support\n", + real_progname); + fprintf (stderr, "%s: %s\n", real_progname, usage); + exit (1); +# endif /* !HAVE_CRAPPLET && !HAVE_GTK2 */ + } + else if (argv[i] && + (!strcmp(argv[i], "--debug") || + !strcmp(argv[i], "-debug") || + !strcmp(argv[i], "-d"))) + { + int j; + s->debug_p = True; + for (j = i; j < argc; j++) /* remove it from the list */ + argv[j] = argv[j+1]; + argc--; + i--; + } + else if (argv[i] && + argc > i+1 && + *argv[i+1] && + (!strcmp(argv[i], "-geometry") || + !strcmp(argv[i], "-geom") || + !strcmp(argv[i], "-geo") || + !strcmp(argv[i], "-g"))) + { + int j; + geom = argv[i+1]; + for (j = i; j < argc; j++) /* remove them from the list */ + argv[j] = argv[j+2]; + argc -= 2; + i -= 2; + } + else if (argv[i] && + argc > i+1 && + *argv[i+1] && + (!strcmp(argv[i], "--configdir"))) + { + int j; + struct stat st; + hack_configuration_path = argv[i+1]; + for (j = i; j < argc; j++) /* remove them from the list */ + argv[j] = argv[j+2]; + argc -= 2; + i -= 2; + + if (0 != stat (hack_configuration_path, &st)) + { + char buf[255]; + sprintf (buf, "%s: %.200s", blurb(), hack_configuration_path); + perror (buf); + exit (1); + } + else if (!S_ISDIR (st.st_mode)) + { + fprintf (stderr, "%s: not a directory: %s\n", + blurb(), hack_configuration_path); + exit (1); + } + } + } + + + if (s->debug_p) + fprintf (stderr, "%s: using config directory \"%s\"\n", + progname, hack_configuration_path); + + + /* Let Gtk open the X connection, then initialize Xt to use that + same connection. Doctor Frankenstein would be proud. + */ +# ifdef HAVE_CRAPPLET + if (crapplet_p) + { + GnomeClient *client; + GnomeClientFlags flags = 0; + + int init_results = gnome_capplet_init ("screensaver-properties", + s->short_version, + argc, argv, NULL, 0, NULL); + /* init_results is: + 0 upon successful initialization; + 1 if --init-session-settings was passed on the cmdline; + 2 if --ignore was passed on the cmdline; + -1 on error. + + So the 1 signifies just to init the settings, and quit, basically. + (Meaning launch the xscreensaver daemon.) + */ + + if (init_results < 0) + { +# if 0 + g_error ("An initialization error occurred while " + "starting xscreensaver-capplet.\n"); +# else /* !0 */ + fprintf (stderr, "%s: gnome_capplet_init failed: %d\n", + real_progname, init_results); + exit (1); +# endif /* !0 */ + } + + client = gnome_master_client (); + + if (client) + flags = gnome_client_get_flags (client); + + if (flags & GNOME_CLIENT_IS_CONNECTED) + { + int token = + gnome_startup_acquire_token ("GNOME_SCREENSAVER_PROPERTIES", + gnome_client_get_id (client)); + if (token) + { + char *session_args[20]; + int i = 0; + session_args[i++] = real_progname; + session_args[i++] = "--capplet"; + session_args[i++] = "--init-session-settings"; + session_args[i] = 0; + gnome_client_set_priority (client, 20); + gnome_client_set_restart_style (client, GNOME_RESTART_ANYWAY); + gnome_client_set_restart_command (client, i, session_args); + } + else + { + gnome_client_set_restart_style (client, GNOME_RESTART_NEVER); + } + + gnome_client_flush (client); + } + + if (init_results == 1) + { + system ("xscreensaver -nosplash &"); + return 0; + } + + } + else +# endif /* HAVE_CRAPPLET */ + { + gtk_init (&argc, &argv); + } + + + /* We must read exactly the same resources as xscreensaver. + That means we must have both the same progclass *and* progname, + at least as far as the resource database is concerned. So, + put "xscreensaver" in argv[0] while initializing Xt. + */ + argv[0] = "xscreensaver"; + progname = argv[0]; + + + /* Teach Xt to use the Display that Gtk/Gdk have already opened. + */ + XtToolkitInitialize (); + app = XtCreateApplicationContext (); + dpy = GDK_DISPLAY(); + XtAppSetFallbackResources (app, defaults); + XtDisplayInitialize (app, dpy, progname, progclass, 0, 0, &argc, argv); + toplevel_shell = XtAppCreateShell (progname, progclass, + applicationShellWidgetClass, + dpy, 0, 0); + + dpy = XtDisplay (toplevel_shell); + db = XtDatabase (dpy); + XtGetApplicationNameAndClass (dpy, &progname, &progclass); + XSetErrorHandler (demo_ehandler); + + /* Let's just ignore these. They seem to confuse Irix Gtk... */ + signal (SIGPIPE, SIG_IGN); + + /* After doing Xt-style command-line processing, complain about any + unrecognized command-line arguments. + */ + for (i = 1; i < argc; i++) + { + char *str = argv[i]; + if (str[0] == '-' && str[1] == '-') + str++; + if (!strcmp (str, "-prefs")) + prefs_p = True; + else if (!strcmp (str, "-settings")) + settings_p = True; + else if (crapplet_p) + /* There are lots of random args that we don't care about when we're + started as a crapplet, so just ignore unknown args in that case. */ + ; + else + { + fprintf (stderr, _("%s: unknown option: %s\n"), real_progname, + argv[i]); + fprintf (stderr, "%s: %s\n", real_progname, usage); + exit (1); + } + } + + /* Load the init file, which may end up consulting the X resource database + and the site-wide app-defaults file. Note that at this point, it's + important that `progname' be "xscreensaver", rather than whatever + was in argv[0]. + */ + p->db = db; + s->nscreens = screen_count (dpy); + + hack_environment (s); /* must be before initialize_sort_map() */ + + load_init_file (dpy, p); + initialize_sort_map (s); + + /* Now that Xt has been initialized, and the resources have been read, + we can set our `progname' variable to something more in line with + reality. + */ + progname = real_progname; + + +#if 0 + /* Print out all the resources we read. */ + { + XrmName name = { 0 }; + XrmClass class = { 0 }; + int count = 0; + XrmEnumerateDatabase (db, &name, &class, XrmEnumAllLevels, mapper, + (POINTER) &count); + } +#endif + + + /* Intern the atoms that xscreensaver_command() needs. + */ + XA_VROOT = XInternAtom (dpy, "__SWM_VROOT", False); + XA_SCREENSAVER = XInternAtom (dpy, "SCREENSAVER", False); + XA_SCREENSAVER_VERSION = XInternAtom (dpy, "_SCREENSAVER_VERSION",False); + XA_SCREENSAVER_STATUS = XInternAtom (dpy, "_SCREENSAVER_STATUS", False); + XA_SCREENSAVER_ID = XInternAtom (dpy, "_SCREENSAVER_ID", False); + XA_SCREENSAVER_RESPONSE = XInternAtom (dpy, "_SCREENSAVER_RESPONSE", False); + XA_SELECT = XInternAtom (dpy, "SELECT", False); + XA_DEMO = XInternAtom (dpy, "DEMO", False); + XA_ACTIVATE = XInternAtom (dpy, "ACTIVATE", False); + XA_BLANK = XInternAtom (dpy, "BLANK", False); + XA_LOCK = XInternAtom (dpy, "LOCK", False); + XA_EXIT = XInternAtom (dpy, "EXIT", False); + XA_RESTART = XInternAtom (dpy, "RESTART", False); + + + /* Create the window and all its widgets. + */ + s->base_widget = create_xscreensaver_demo (); + s->popup_widget = create_xscreensaver_settings_dialog (); + s->toplevel_widget = s->base_widget; + + + /* Set the main window's title. */ + { + char *base_title = _("Screensaver Preferences"); + char *v = (char *) strdup(strchr(screensaver_id, ' ')); + char *s1, *s2, *s3, *s4; + s1 = (char *) strchr(v, ' '); s1++; + s2 = (char *) strchr(s1, ' '); + s3 = (char *) strchr(v, '('); s3++; + s4 = (char *) strchr(s3, ')'); + *s2 = 0; + *s4 = 0; + + window_title = (char *) malloc (strlen (base_title) + + strlen (progclass) + + strlen (s1) + strlen (s3) + + 100); + sprintf (window_title, "%s (%s %s, %s)", base_title, progclass, s1, s3); + gtk_window_set_title (GTK_WINDOW (s->toplevel_widget), window_title); + gtk_window_set_title (GTK_WINDOW (s->popup_widget), window_title); + free (v); + } + + /* Adjust the (invisible) notebooks on the popup dialog... */ + { + GtkNotebook *notebook = + GTK_NOTEBOOK (name_to_widget (s, "opt_notebook")); + GtkWidget *std = GTK_WIDGET (name_to_widget (s, "std_button")); + int page = 0; + +# ifdef HAVE_XML + gtk_widget_hide (std); +# else /* !HAVE_XML */ + /* Make the advanced page be the only one available. */ + gtk_widget_set_sensitive (std, False); + std = GTK_WIDGET (name_to_widget (s, "adv_button")); + gtk_widget_hide (std); + std = GTK_WIDGET (name_to_widget (s, "reset_button")); + gtk_widget_hide (std); + page = 1; +# endif /* !HAVE_XML */ + + gtk_notebook_set_page (notebook, page); + gtk_notebook_set_show_tabs (notebook, False); + } + + /* Various other widget initializations... + */ + gtk_signal_connect (GTK_OBJECT (s->toplevel_widget), "delete_event", + GTK_SIGNAL_FUNC (wm_toplevel_close_cb), + (gpointer) s); + gtk_signal_connect (GTK_OBJECT (s->popup_widget), "delete_event", + GTK_SIGNAL_FUNC (wm_popup_close_cb), + (gpointer) s); + + populate_hack_list (s); + populate_prefs_page (s); + sensitize_demo_widgets (s, False); + fix_text_entry_sizes (s); + scroll_to_current_hack (s); + + gtk_signal_connect (GTK_OBJECT (name_to_widget (s, "cancel_button")), + "map", GTK_SIGNAL_FUNC(map_popup_window_cb), + (gpointer) s); + +#ifndef HAVE_GTK2 + gtk_signal_connect (GTK_OBJECT (name_to_widget (s, "prev")), + "map", GTK_SIGNAL_FUNC(map_prev_button_cb), + (gpointer) s); + gtk_signal_connect (GTK_OBJECT (name_to_widget (s, "next")), + "map", GTK_SIGNAL_FUNC(map_next_button_cb), + (gpointer) s); +#endif /* !HAVE_GTK2 */ + + /* Hook up callbacks to the items on the mode menu. */ + { + GtkOptionMenu *opt = GTK_OPTION_MENU (name_to_widget (s, "mode_menu")); + GtkMenu *menu = GTK_MENU (gtk_option_menu_get_menu (opt)); + GList *kids = gtk_container_children (GTK_CONTAINER (menu)); + int i; + for (i = 0; kids; kids = kids->next, i++) + { + gtk_signal_connect (GTK_OBJECT (kids->data), "activate", + GTK_SIGNAL_FUNC (mode_menu_item_cb), + (gpointer) s); + + /* The "random-same" mode menu item does not appear unless + there are multple screens. + */ + if (s->nscreens <= 1 && + mode_menu_order[i] == RANDOM_HACKS_SAME) + gtk_widget_hide (GTK_WIDGET (kids->data)); + } + + if (s->nscreens <= 1) /* recompute option-menu size */ + { + gtk_widget_unrealize (GTK_WIDGET (menu)); + gtk_widget_realize (GTK_WIDGET (menu)); + } + } + + + /* Handle the -prefs command-line argument. */ + if (prefs_p) + { + GtkNotebook *notebook = + GTK_NOTEBOOK (name_to_widget (s, "notebook")); + gtk_notebook_set_page (notebook, 1); + } + +# ifdef HAVE_CRAPPLET + if (crapplet_p) + { + GtkWidget *capplet; + GtkWidget *outer_vbox; + + gtk_widget_hide (s->toplevel_widget); + + capplet = capplet_widget_new (); + + /* Make there be a "Close" button instead of "OK" and "Cancel" */ +# ifdef HAVE_CRAPPLET_IMMEDIATE + capplet_widget_changes_are_immediate (CAPPLET_WIDGET (capplet)); +# endif /* HAVE_CRAPPLET_IMMEDIATE */ + /* In crapplet-mode, take off the menubar. */ + gtk_widget_hide (name_to_widget (s, "menubar")); + + /* Reparent our top-level container to be a child of the capplet + window. + */ + outer_vbox = GTK_BIN (s->toplevel_widget)->child; + gtk_widget_ref (outer_vbox); + gtk_container_remove (GTK_CONTAINER (s->toplevel_widget), + outer_vbox); + STFU GTK_OBJECT_SET_FLAGS (outer_vbox, GTK_FLOATING); + gtk_container_add (GTK_CONTAINER (capplet), outer_vbox); + + /* Find the window above us, and set the title and close handler. */ + { + GtkWidget *window = capplet; + while (window && !GTK_IS_WINDOW (window)) + window = GET_PARENT (window); + if (window) + { + gtk_window_set_title (GTK_WINDOW (window), window_title); + gtk_signal_connect (GTK_OBJECT (window), "delete_event", + GTK_SIGNAL_FUNC (wm_toplevel_close_cb), + (gpointer) s); + } + } + + s->toplevel_widget = capplet; + } +# endif /* HAVE_CRAPPLET */ + + + /* The Gnome folks hate the menubar. I think it's important to have access + to the commands on the File menu (Restart Daemon, etc.) and to the + About and Documentation commands on the Help menu. + */ +#if 0 +#ifdef HAVE_GTK2 + gtk_widget_hide (name_to_widget (s, "menubar")); +#endif +#endif + + free (window_title); + window_title = 0; + +#ifdef HAVE_GTK2 + /* After picking the default size, allow -geometry to override it. */ + if (geom) + gtk_window_parse_geometry (GTK_WINDOW (s->toplevel_widget), geom); +#endif + + gtk_widget_show (s->toplevel_widget); + init_icon (GET_WINDOW (GTK_WIDGET (s->toplevel_widget))); /* after `show' */ + fix_preview_visual (s); + + /* Realize page zero, so that we can diddle the scrollbar when the + user tabs back to it -- otherwise, the current hack isn't scrolled + to the first time they tab back there, when started with "-prefs". + (Though it is if they then tab away, and back again.) + + #### Bah! This doesn't work. Gtk eats my ass! Someone who + #### understands this crap, explain to me how to make this work. + */ + gtk_widget_realize (name_to_widget (s, "demos_table")); + + + gtk_timeout_add (60 * 1000, check_blanked_timer, s); + + + /* Handle the --settings command-line argument. */ + if (settings_p) + gtk_timeout_add (500, settings_timer, 0); + + + /* Issue any warnings about the running xscreensaver daemon. */ + if (! s->debug_p) + the_network_is_not_the_computer (s); + + + /* Run the Gtk event loop, and not the Xt event loop. This means that + if there were Xt timers or fds registered, they would never get serviced, + and if there were any Xt widgets, they would never have events delivered. + Fortunately, we're using Gtk for all of the UI, and only initialized + Xt so that we could process the command line and use the X resource + manager. + */ + s->initializing_p = False; + + /* This totally sucks -- set a timer that whacks the scrollbar 0.5 seconds + after we start up. Otherwise, it always appears scrolled to the top + when in crapplet-mode. */ + gtk_timeout_add (500, delayed_scroll_kludge, s); + + +#if 1 + /* Load every configurator in turn, to scan them for errors all at once. */ + if (s->debug_p) + { + int i; + for (i = 0; i < p->screenhacks_count; i++) + { + screenhack *hack = p->screenhacks[i]; + conf_data *d = load_configurator (hack->command, s->debug_p); + if (d) free_conf_data (d); + } + } +#endif + + +# ifdef HAVE_CRAPPLET + if (crapplet_p) + capplet_gtk_main (); + else +# endif /* HAVE_CRAPPLET */ + gtk_main (); + + kill_preview_subproc (s, False); + exit (0); +} + +#endif /* HAVE_GTK -- whole file */ diff --git a/driver/demo-Xm-widgets.c b/driver/demo-Xm-widgets.c new file mode 100644 index 00000000..cbe33934 --- /dev/null +++ b/driver/demo-Xm-widgets.c @@ -0,0 +1,907 @@ +/* demo-Xm.c --- implements the interactive demo-mode and options dialogs. + * xscreensaver, Copyright (c) 1999, 2003 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. + */ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include +#include + +#include /* just for debug info */ +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef HAVE_XMCOMBOBOX /* a Motif 2.0 widget */ +# include +# ifndef XmNtextField /* Lesstif 0.89.4 bug */ +# undef HAVE_XMCOMBOBOX +# endif +#endif /* HAVE_XMCOMBOBOX */ + +#include +#include + + + +const char *visual_menu[] = { + "Any", "Best", "Default", "Default-N", "GL", "TrueColor", "PseudoColor", + "StaticGray", "GrayScale", "DirectColor", "Color", "Gray", "Mono", 0 +}; + + + +static Widget create_demos_page (Widget parent); +static Widget create_options_page (Widget parent); + +static void +tab_cb (Widget button, XtPointer client_data, XtPointer ignored) +{ + Widget parent = XtParent(button); + Widget tabber = XtNameToWidget (parent, "*folder"); + Widget this_tab = (Widget) client_data; + Widget *kids = 0; + Cardinal nkids = 0; + if (!tabber) abort(); + + XtVaGetValues (tabber, XmNnumChildren, &nkids, XmNchildren, &kids, NULL); + if (!kids) abort(); + if (nkids > 0) + XtUnmanageChildren (kids, nkids); + + XtManageChild (this_tab); +} + + +Widget +create_xscreensaver_demo (Widget parent) +{ + /* MainWindow + Form + Menubar + DemoTab + OptionsTab + HR + Tabber + (demo page) + (options page) + */ + + Widget mainw, form, menubar; + Widget demo_tab, options_tab, hr, tabber, demos, options; + Arg av[100]; + int ac = 0; + + mainw = XmCreateMainWindow (parent, "demoForm", av, ac); + form = XmCreateForm (mainw, "form", av, ac); + menubar = XmCreateSimpleMenuBar (form, "menubar", av, ac); + XtVaSetValues (menubar, + XmNtopAttachment, XmATTACH_FORM, + XmNleftAttachment, XmATTACH_FORM, + XmNrightAttachment, XmATTACH_FORM, + NULL); + + { + Widget menu = 0, item = 0; + char *menus[] = { + "*file", "blank", "lock", "kill", "restart", "-", "exit", + "*edit", "cut", "copy", "paste", + "*help", "about", "docMenu" }; + int i; + for (i = 0; i < sizeof(menus)/sizeof(*menus); i++) + { + ac = 0; + if (menus[i][0] == '-') + item = XmCreateSeparatorGadget (menu, "separator", av, ac); + else if (menus[i][0] != '*') + item = XmCreatePushButtonGadget (menu, menus[i], av, ac); + else + { + menu = XmCreatePulldownMenu (parent, menus[i]+1, av, ac); + XtSetArg (av [ac], XmNsubMenuId, menu); ac++; + item = XmCreateCascadeButtonGadget (menubar, menus[i]+1, av, ac); + + if (!strcmp (menus[i]+1, "help")) + XtVaSetValues(menubar, XmNmenuHelpWidget, item, NULL); + } + XtManageChild (item); + } + ac = 0; + } + + demo_tab = XmCreatePushButtonGadget (form, "demoTab", av, ac); + XtVaSetValues (demo_tab, + XmNleftAttachment, XmATTACH_FORM, + XmNtopAttachment, XmATTACH_WIDGET, + XmNtopWidget, menubar, + NULL); + + options_tab = XmCreatePushButtonGadget (form, "optionsTab", av, ac); + XtVaSetValues (options_tab, + XmNleftAttachment, XmATTACH_WIDGET, + XmNleftWidget, demo_tab, + XmNtopAttachment, XmATTACH_OPPOSITE_WIDGET, + XmNtopWidget, demo_tab, + XmNbottomAttachment, XmATTACH_OPPOSITE_WIDGET, + XmNbottomWidget, demo_tab, + NULL); + + hr = XmCreateSeparatorGadget (form, "hr", av, ac); + XtVaSetValues (hr, + XmNleftAttachment, XmATTACH_FORM, + XmNrightAttachment, XmATTACH_FORM, + XmNtopAttachment, XmATTACH_WIDGET, + XmNtopWidget, demo_tab, + NULL); + + tabber = XmCreateForm (form, "folder", av, ac); + XtVaSetValues (tabber, + XmNtopAttachment, XmATTACH_WIDGET, + XmNtopWidget, hr, + XmNleftAttachment, XmATTACH_FORM, + XmNrightAttachment, XmATTACH_FORM, + XmNbottomAttachment, XmATTACH_FORM, + NULL); + + demos = create_demos_page (tabber); + options = create_options_page (tabber); + + XtAddCallback (demo_tab, XmNactivateCallback, tab_cb, demos); + XtAddCallback (options_tab, XmNactivateCallback, tab_cb, options); + + XtManageChild (demos); + XtManageChild (options); + + XtManageChild (demo_tab); + XtManageChild (options_tab); + XtManageChild (hr); + XtManageChild (menubar); + XtManageChild (tabber); + XtManageChild (form); + +#if 1 + XtUnmanageChild (options); + XtManageChild (demos); +#endif + + return mainw; +} + + +static Widget +create_demos_page (Widget parent) +{ + /* Form1 (horizontal) + Form2 (vertical) + Scroller + List + ButtonBox1 (vertical) + Button ("Down") + Button ("Up") + Form3 (vertical) + Frame + Label + TextArea (doc) + Label + Text ("Command Line") + Form4 (horizontal) + Checkbox ("Enabled") + Label ("Visual") + ComboBox + HR + ButtonBox2 (vertical) + Button ("Demo") + Button ("Documentation") + */ + Widget form1, form2, form3, form4; + Widget scroller, list, buttonbox1, down, up; + Widget frame, frame_label, doc, cmd_label, cmd_text, enabled, vis_label; + Widget combo; + Widget hr, buttonbox2, demo, man; + Arg av[100]; + int ac = 0; + int i; + + form1 = XmCreateForm (parent, "form1", av, ac); + form2 = XmCreateForm (form1, "form2", av, ac); + XtVaSetValues (form2, + XmNtopAttachment, XmATTACH_FORM, + XmNleftAttachment, XmATTACH_FORM, + XmNbottomAttachment, XmATTACH_FORM, + NULL); + + scroller = XmCreateScrolledWindow (form2, "scroller", av, ac); + XtVaSetValues (scroller, + XmNtopAttachment, XmATTACH_FORM, + XmNleftAttachment, XmATTACH_FORM, + XmNrightAttachment, XmATTACH_FORM, + XmNbottomAttachment, XmATTACH_WIDGET, + NULL); + list = XmCreateList (scroller, "list", av, ac); + + buttonbox1 = XmCreateForm (form2, "buttonbox1", av, ac); + XtVaSetValues (buttonbox1, + XmNleftAttachment, XmATTACH_FORM, + XmNrightAttachment, XmATTACH_FORM, + XmNbottomAttachment, XmATTACH_FORM, + NULL); + XtVaSetValues (scroller, XmNbottomWidget, buttonbox1, NULL); + + down = XmCreatePushButton (buttonbox1, "down", av, ac); + XtVaSetValues (down, + XmNleftAttachment, XmATTACH_FORM, + XmNtopAttachment, XmATTACH_FORM, + XmNbottomAttachment, XmATTACH_FORM, + NULL); + up = XmCreatePushButton (buttonbox1, "up", av, ac); + XtVaSetValues (up, + XmNleftAttachment, XmATTACH_WIDGET, + XmNleftWidget, down, + XmNtopAttachment, XmATTACH_FORM, + XmNbottomAttachment, XmATTACH_FORM, + NULL); + + form3 = XmCreateForm (form1, "form3", av, ac); + XtVaSetValues (form3, + XmNtopAttachment, XmATTACH_FORM, + XmNleftAttachment, XmATTACH_WIDGET, + XmNleftWidget, form2, + XmNrightAttachment, XmATTACH_FORM, + XmNbottomAttachment, XmATTACH_FORM, + NULL); + frame = XmCreateFrame (form3, "frame", av, ac); + + ac = 0; + XtSetArg (av [ac], XmNchildType, XmFRAME_TITLE_CHILD); ac++; + frame_label = XmCreateLabelGadget (frame, "frameLabel", av, ac); + + ac = 0; + XtVaSetValues (frame, + XmNtopAttachment, XmATTACH_FORM, + XmNleftAttachment, XmATTACH_FORM, + XmNrightAttachment, XmATTACH_FORM, + XmNbottomAttachment, XmATTACH_WIDGET, + NULL); + + ac = 0; + XtSetArg (av [ac], XmNchildType, XmFRAME_WORKAREA_CHILD); ac++; + doc = XmCreateText (frame, "doc", av, ac); + + ac = 0; + XtVaSetValues (doc, + XmNeditable, FALSE, + XmNcursorPositionVisible, FALSE, + XmNwordWrap, TRUE, + XmNeditMode, XmMULTI_LINE_EDIT, + XmNshadowThickness, 0, + NULL); + + cmd_label = XmCreateLabelGadget (form3, "cmdLabel", av, ac); + XtVaSetValues (cmd_label, + XmNleftAttachment, XmATTACH_FORM, + XmNrightAttachment, XmATTACH_FORM, + XmNbottomAttachment, XmATTACH_WIDGET, + NULL); + XtVaSetValues (frame, XmNbottomWidget, cmd_label, NULL); + + cmd_text = XmCreateTextField (form3, "cmdText", av, ac); + XtVaSetValues (cmd_text, + XmNleftAttachment, XmATTACH_FORM, + XmNrightAttachment, XmATTACH_FORM, + XmNbottomAttachment, XmATTACH_WIDGET, + NULL); + XtVaSetValues (cmd_label, XmNbottomWidget, cmd_text, NULL); + + form4 = XmCreateForm (form3, "form4", av, ac); + XtVaSetValues (form4, + XmNleftAttachment, XmATTACH_FORM, + XmNrightAttachment, XmATTACH_FORM, + XmNbottomAttachment, XmATTACH_WIDGET, + NULL); + XtVaSetValues (cmd_text, XmNbottomWidget, form4, NULL); + + enabled = XmCreateToggleButtonGadget (form4, "enabled", av, ac); + XtVaSetValues (enabled, + XmNtopAttachment, XmATTACH_FORM, + XmNleftAttachment, XmATTACH_FORM, + XmNbottomAttachment, XmATTACH_FORM, + NULL); + vis_label = XmCreateLabelGadget (form4, "visLabel", av, ac); + XtVaSetValues (vis_label, + XmNtopAttachment, XmATTACH_FORM, + XmNleftAttachment, XmATTACH_WIDGET, + XmNleftWidget, enabled, + XmNbottomAttachment, XmATTACH_FORM, + NULL); +#ifdef HAVE_XMCOMBOBOX + { + Widget list; + ac = 0; + XtSetArg (av [ac], XmNcomboBoxType, XmDROP_DOWN_COMBO_BOX); ac++; + combo = XmCreateComboBox (form4, "combo", av, ac); + for (i = 0; visual_menu[i]; i++) + { + XmString xs = XmStringCreate ((char *) visual_menu[i], + XmSTRING_DEFAULT_CHARSET); + XmComboBoxAddItem (combo, xs, 0, False); + XmStringFree (xs); + } + XtVaGetValues (combo, XmNlist, &list, NULL); + XtVaSetValues (list, XmNvisibleItemCount, i, NULL); + } +#else /* !HAVE_XMCOMBOBOX */ + { + Widget popup_menu = XmCreatePulldownMenu (parent, "menu", av, ac); + Widget kids[100]; + for (i = 0; visual_menu[i]; i++) + { + XmString xs = XmStringCreate ((char *) visual_menu[i], + XmSTRING_DEFAULT_CHARSET); + ac = 0; + XtSetArg (av [ac], XmNlabelString, xs); ac++; + kids[i] = XmCreatePushButtonGadget (popup_menu, "button", av, ac); + /* XtAddCallback (combo, XmNactivateCallback, visual_popup_cb, + combo); */ + XmStringFree (xs); + } + XtManageChildren (kids, i); + + ac = 0; + XtSetArg (av [ac], XmNsubMenuId, popup_menu); ac++; + combo = XmCreateOptionMenu (form4, "combo", av, ac); + ac = 0; + } +#endif /* !HAVE_XMCOMBOBOX */ + + XtVaSetValues (combo, + XmNtopAttachment, XmATTACH_FORM, + XmNleftAttachment, XmATTACH_WIDGET, + XmNleftWidget, vis_label, + XmNbottomAttachment, XmATTACH_FORM, + NULL); + + hr = XmCreateSeparatorGadget (form3, "hr", av, ac); + XtVaSetValues (hr, + XmNleftAttachment, XmATTACH_FORM, + XmNrightAttachment, XmATTACH_FORM, + XmNbottomAttachment, XmATTACH_WIDGET, + NULL); + XtVaSetValues (form4, XmNbottomWidget, hr, NULL); + + buttonbox2 = XmCreateForm (form3, "buttonbox2", av, ac); + XtVaSetValues (buttonbox2, + XmNleftAttachment, XmATTACH_FORM, + XmNrightAttachment, XmATTACH_FORM, + XmNbottomAttachment, XmATTACH_FORM, + NULL); + XtVaSetValues (hr, XmNbottomWidget, buttonbox2, NULL); + + demo = XmCreatePushButtonGadget (buttonbox2, "demo", av, ac); + XtVaSetValues (demo, + XmNleftAttachment, XmATTACH_FORM, + XmNtopAttachment, XmATTACH_FORM, + XmNbottomAttachment, XmATTACH_FORM, + NULL); + man = XmCreatePushButtonGadget (buttonbox2, "man", av, ac); + XtVaSetValues (man, + XmNrightAttachment, XmATTACH_FORM, + XmNtopAttachment, XmATTACH_FORM, + XmNbottomAttachment, XmATTACH_FORM, + NULL); + + XtManageChild (demo); + XtManageChild (man); + XtManageChild (buttonbox2); + XtManageChild (hr); + + XtManageChild (combo); + XtManageChild (vis_label); + XtManageChild (enabled); + XtManageChild (form4); + + XtManageChild (cmd_text); + XtManageChild (cmd_label); + + XtManageChild (doc); + XtManageChild (frame_label); + XtManageChild (frame); + XtManageChild (form3); + + XtManageChild (up); + XtManageChild (down); + XtManageChild (buttonbox1); + + XtManageChild (list); + XtManageChild (scroller); + XtManageChild (form2); + + XtManageChild (form1); + + XtVaSetValues (form1, + XmNleftAttachment, XmATTACH_FORM, + XmNrightAttachment, XmATTACH_FORM, + XmNtopAttachment, XmATTACH_FORM, + XmNbottomAttachment, XmATTACH_FORM, + NULL); + + return form1; +} + + + +static Widget +create_options_page (Widget parent) +{ + /* This is what the layout is today: + + Form (horizontal) + Label ("Saver Timeout") + Label ("Cycle Timeout") + Label ("Fade Duration") + Label ("Fade Ticks") + Label ("Lock Timeout") + Label ("Password Timeout") + + Text (timeout) + Text (cycle) + Text (fade seconds) + Text (fade ticks) + Text (lock) + Text (passwd) + + Toggle ("Verbose") + Toggle ("Install Colormap") + Toggle ("Fade Colormap") + Toggle ("Unfade Colormap") + Toggle ("Require Password") + + HR + Button ("OK") + Button ("Cancel") + */ + + /* This is what it should be: + + Form (horizontal) + Form (vertical) ("column1") + Frame + Label ("Blanking and Locking") + Form + Label ("Blank After") + Label ("Cycle After") + Text ("Blank After") + Text ("Cycle After") + HR + Checkbox ("Require Password") + Label ("Lock After") + Text ("Lock After") + Frame + Label ("Image Manipulation") + Form + Checkbox ("Grab Desktop Images") + Checkbox ("Grab Video Frames") + Checkbox ("Choose Random Image") + Text (pathname) + Button ("Browse") + Frame + Label ("Diagnostics") + Form + Checkbox ("Verbose Diagnostics") + Checkbox ("Display Subprocess Errors") + Checkbox ("Display Splash Screen at Startup") + Form (vertical) ("column2") + Frame + Label ("Display Power Management") + Form + Checkbox ("Power Management Enabled") + Label ("Standby After") + Label ("Suspend After") + Label ("Off After") + Text ("Standby After") + Text ("Suspend After") + Text ("Off After") + Frame + Label ("Colormaps") + Form + Checkbox ("Install Colormap") + HR + Checkbox ("Fade To Black When Blanking") + Checkbox ("Fade From Black When Unblanking") + Label ("Fade Duration") + Text ("Fade Duration") + + timeoutLabel + cycleLabel + fadeSecondsLabel + fadeTicksLabel + lockLabel + passwdLabel + + timeoutText + cycleText + fadeSecondsText + fadeTicksText + lockText + passwdText + + verboseToggle + cmapToggle + fadeToggle + unfadeToggle + lockToggle + + separator + OK + Cancel + */ + + + + Arg av[64]; + int ac = 0; + Widget children[100]; + Widget timeout_label, cycle_label, fade_seconds_label, fade_ticks_label; + Widget lock_label, passwd_label, hr; + Widget preferences_form; + + Widget timeout_text, cycle_text, fade_text, fade_ticks_text; + Widget lock_timeout_text, passwd_timeout_text, verbose_toggle; + Widget install_cmap_toggle, fade_toggle, unfade_toggle; + Widget lock_toggle, prefs_done, prefs_cancel; + + ac = 0; + XtSetArg (av [ac], XmNdialogType, XmDIALOG_PROMPT); ac++; + + ac = 0; + XtSetArg (av [ac], XmNtopAttachment, XmATTACH_FORM); ac++; + XtSetArg (av [ac], XmNbottomAttachment, XmATTACH_FORM); ac++; + XtSetArg (av [ac], XmNleftAttachment, XmATTACH_FORM); ac++; + XtSetArg (av [ac], XmNrightAttachment, XmATTACH_FORM); ac++; + preferences_form = XmCreateForm (parent, "preferencesForm", av, ac); + XtManageChild (preferences_form); + + ac = 0; + + XtSetArg(av[ac], XmNalignment, XmALIGNMENT_END); ac++; + timeout_label = XmCreateLabelGadget (preferences_form, "timeoutLabel", + av, ac); + ac = 0; + XtSetArg(av[ac], XmNalignment, XmALIGNMENT_END); ac++; + cycle_label = XmCreateLabelGadget (preferences_form, "cycleLabel", + av, ac); + ac = 0; + XtSetArg(av[ac], XmNalignment, XmALIGNMENT_END); ac++; + fade_seconds_label = XmCreateLabelGadget (preferences_form, + "fadeSecondsLabel", av, ac); + ac = 0; + XtSetArg(av[ac], XmNalignment, XmALIGNMENT_END); ac++; + fade_ticks_label = XmCreateLabelGadget (preferences_form, "fadeTicksLabel", + av, ac); + ac = 0; + XtSetArg(av[ac], XmNalignment, XmALIGNMENT_END); ac++; + lock_label = XmCreateLabelGadget (preferences_form, "lockLabel", av, ac); + ac = 0; + XtSetArg(av[ac], XmNalignment, XmALIGNMENT_END); ac++; + passwd_label = XmCreateLabelGadget (preferences_form, "passwdLabel", av, ac); + ac = 0; + timeout_text = XmCreateTextField (preferences_form, "timeoutText", av, ac); + cycle_text = XmCreateTextField (preferences_form, "cycleText", av, ac); + fade_text = XmCreateTextField (preferences_form, "fadeSecondsText", av, ac); + fade_ticks_text = XmCreateTextField (preferences_form, "fadeTicksText", + av, ac); + lock_timeout_text = XmCreateTextField (preferences_form, "lockText", + av, ac); + passwd_timeout_text = XmCreateTextField (preferences_form, "passwdText", + av, ac); + XtSetArg(av[ac], XmNalignment, XmALIGNMENT_BEGINNING); ac++; + verbose_toggle = XmCreateToggleButtonGadget (preferences_form, + "verboseToggle", av, ac); + ac = 0; + XtSetArg(av[ac], XmNalignment, XmALIGNMENT_BEGINNING); ac++; + install_cmap_toggle = XmCreateToggleButtonGadget (preferences_form, + "cmapToggle", av, ac); + ac = 0; + XtSetArg(av[ac], XmNalignment, XmALIGNMENT_BEGINNING); ac++; + fade_toggle = XmCreateToggleButtonGadget (preferences_form, "fadeToggle", + av, ac); + ac = 0; + XtSetArg(av[ac], XmNalignment, XmALIGNMENT_BEGINNING); ac++; + unfade_toggle = XmCreateToggleButtonGadget (preferences_form, "unfadeToggle", + av,ac); + ac = 0; + XtSetArg(av[ac], XmNalignment, XmALIGNMENT_BEGINNING); ac++; + lock_toggle = XmCreateToggleButtonGadget (preferences_form, "lockToggle", + av, ac); + ac = 0; + hr = XmCreateSeparatorGadget (preferences_form, "separator", av, ac); + + prefs_done = XmCreatePushButtonGadget (preferences_form, "OK", av, ac); + prefs_cancel = XmCreatePushButtonGadget (preferences_form, "Cancel", av, ac); + + XtVaSetValues (timeout_label, + XmNtopAttachment, XmATTACH_FORM, + XmNtopOffset, 4, + XmNbottomAttachment, XmATTACH_OPPOSITE_WIDGET, + XmNbottomWidget, timeout_text, + XmNleftAttachment, XmATTACH_FORM, + XmNleftOffset, 20, + XmNrightAttachment, XmATTACH_WIDGET, + XmNrightOffset, 4, + XmNrightWidget, timeout_text, + NULL); + + XtVaSetValues (cycle_label, + XmNtopAttachment, XmATTACH_OPPOSITE_WIDGET, + XmNtopOffset, 0, + XmNtopWidget, cycle_text, + XmNbottomAttachment, XmATTACH_OPPOSITE_WIDGET, + XmNbottomOffset, 0, + XmNbottomWidget, cycle_text, + XmNleftAttachment, XmATTACH_FORM, + XmNleftOffset, 20, + XmNrightAttachment, XmATTACH_WIDGET, + XmNrightOffset, 4, + XmNrightWidget, cycle_text, + NULL); + + XtVaSetValues (fade_seconds_label, + XmNtopAttachment, XmATTACH_OPPOSITE_WIDGET, + XmNtopOffset, 0, + XmNtopWidget, fade_text, + XmNbottomAttachment, XmATTACH_OPPOSITE_WIDGET, + XmNbottomOffset, 0, + XmNbottomWidget, fade_text, + XmNleftAttachment, XmATTACH_FORM, + XmNleftOffset, 20, + XmNrightAttachment, XmATTACH_WIDGET, + XmNrightOffset, 4, + XmNrightWidget, fade_text, + NULL); + + XtVaSetValues (fade_ticks_label, + XmNtopAttachment, XmATTACH_OPPOSITE_WIDGET, + XmNtopOffset, 0, + XmNtopWidget, fade_ticks_text, + XmNbottomAttachment, XmATTACH_OPPOSITE_WIDGET, + XmNbottomOffset, 0, + XmNbottomWidget, fade_ticks_text, + XmNleftAttachment, XmATTACH_FORM, + XmNleftOffset, 20, + XmNrightAttachment, XmATTACH_WIDGET, + XmNrightOffset, 4, + XmNrightWidget, fade_ticks_text, + NULL); + + XtVaSetValues (lock_label, + XmNtopAttachment, XmATTACH_OPPOSITE_WIDGET, + XmNtopOffset, 0, + XmNtopWidget, lock_timeout_text, + XmNbottomAttachment, XmATTACH_OPPOSITE_WIDGET, + XmNbottomOffset, 0, + XmNbottomWidget, lock_timeout_text, + XmNleftAttachment, XmATTACH_FORM, + XmNleftOffset, 19, + XmNrightAttachment, XmATTACH_WIDGET, + XmNrightOffset, 4, + XmNrightWidget, lock_timeout_text, + NULL); + + XtVaSetValues (passwd_label, + XmNtopAttachment, XmATTACH_OPPOSITE_WIDGET, + XmNtopOffset, 0, + XmNtopWidget, passwd_timeout_text, + XmNbottomAttachment, XmATTACH_OPPOSITE_WIDGET, + XmNbottomOffset, 0, + XmNbottomWidget, passwd_timeout_text, + XmNleftAttachment, XmATTACH_FORM, + XmNleftOffset, 14, + XmNrightAttachment, XmATTACH_WIDGET, + XmNrightOffset, 4, + XmNrightWidget, passwd_timeout_text, + NULL); + + XtVaSetValues (timeout_text, + XmNtopAttachment, XmATTACH_FORM, + XmNtopOffset, 4, + XmNleftAttachment, XmATTACH_FORM, + XmNleftOffset, 141, + NULL); + + XtVaSetValues (cycle_text, + XmNtopAttachment, XmATTACH_WIDGET, + XmNtopOffset, 2, + XmNtopWidget, timeout_text, + XmNleftAttachment, XmATTACH_OPPOSITE_WIDGET, + XmNleftOffset, 0, + XmNleftWidget, timeout_text, + NULL); + + XtVaSetValues (fade_text, + XmNtopAttachment, XmATTACH_WIDGET, + XmNtopOffset, 2, + XmNtopWidget, cycle_text, + XmNleftAttachment, XmATTACH_OPPOSITE_WIDGET, + XmNleftOffset, 0, + XmNleftWidget, cycle_text, + NULL); + + XtVaSetValues (fade_ticks_text, + XmNtopAttachment, XmATTACH_WIDGET, + XmNtopOffset, 2, + XmNtopWidget, fade_text, + XmNleftAttachment, XmATTACH_OPPOSITE_WIDGET, + XmNleftOffset, 0, + XmNleftWidget, fade_text, + NULL); + + XtVaSetValues (lock_timeout_text, + XmNtopAttachment, XmATTACH_WIDGET, + XmNtopOffset, 2, + XmNtopWidget, fade_ticks_text, + XmNleftAttachment, XmATTACH_OPPOSITE_WIDGET, + XmNleftOffset, 0, + XmNleftWidget, fade_ticks_text, + NULL); + + XtVaSetValues (passwd_timeout_text, + XmNtopAttachment, XmATTACH_WIDGET, + XmNtopOffset, 4, + XmNtopWidget, lock_timeout_text, + XmNleftAttachment, XmATTACH_OPPOSITE_WIDGET, + XmNleftOffset, 0, + XmNleftWidget, lock_timeout_text, + NULL); + + XtVaSetValues (verbose_toggle, + XmNtopAttachment, XmATTACH_FORM, + XmNtopOffset, 4, + XmNbottomAttachment, XmATTACH_OPPOSITE_WIDGET, + XmNbottomOffset, 0, + XmNbottomWidget, timeout_text, + XmNleftAttachment, XmATTACH_WIDGET, + XmNleftOffset, 20, + XmNleftWidget, timeout_text, + XmNrightAttachment, XmATTACH_FORM, + XmNrightOffset, 20, + NULL); + + XtVaSetValues (install_cmap_toggle, + XmNtopAttachment, XmATTACH_OPPOSITE_WIDGET, + XmNtopOffset, 0, + XmNtopWidget, cycle_text, + XmNbottomAttachment, XmATTACH_OPPOSITE_WIDGET, + XmNbottomOffset, 0, + XmNbottomWidget, cycle_text, + XmNleftAttachment, XmATTACH_OPPOSITE_WIDGET, + XmNleftOffset, 0, + XmNleftWidget, verbose_toggle, + XmNrightAttachment, XmATTACH_FORM, + XmNrightOffset, 20, + NULL); + + XtVaSetValues (fade_toggle, + XmNtopAttachment, XmATTACH_OPPOSITE_WIDGET, + XmNtopOffset, 0, + XmNtopWidget, fade_text, + XmNbottomAttachment, XmATTACH_OPPOSITE_WIDGET, + XmNbottomOffset, 0, + XmNbottomWidget, fade_text, + XmNleftAttachment, XmATTACH_OPPOSITE_WIDGET, + XmNleftOffset, 0, + XmNleftWidget, install_cmap_toggle, + XmNrightAttachment, XmATTACH_FORM, + XmNrightOffset, 20, + NULL); + + XtVaSetValues (unfade_toggle, + XmNtopAttachment, XmATTACH_OPPOSITE_WIDGET, + XmNtopOffset, 0, + XmNtopWidget, fade_ticks_text, + XmNbottomAttachment, XmATTACH_OPPOSITE_WIDGET, + XmNbottomOffset, 0, + XmNbottomWidget, fade_ticks_text, + XmNleftAttachment, XmATTACH_OPPOSITE_WIDGET, + XmNleftOffset, 0, + XmNleftWidget, fade_toggle, + XmNrightAttachment, XmATTACH_FORM, + XmNrightOffset, 20, + NULL); + + XtVaSetValues (lock_toggle, + XmNtopAttachment, XmATTACH_OPPOSITE_WIDGET, + XmNtopOffset, 0, + XmNtopWidget, lock_timeout_text, + XmNbottomAttachment, XmATTACH_OPPOSITE_WIDGET, + XmNbottomOffset, 0, + XmNbottomWidget, lock_timeout_text, + XmNleftAttachment, XmATTACH_OPPOSITE_WIDGET, + XmNleftOffset, 0, + XmNleftWidget, unfade_toggle, + XmNrightAttachment, XmATTACH_FORM, + XmNrightOffset, 20, + NULL); + + XtVaSetValues (hr, + XmNtopWidget, passwd_timeout_text, + XmNbottomAttachment, XmATTACH_FORM, + XmNbottomOffset, 4, + XmNleftAttachment, XmATTACH_FORM, + XmNrightAttachment, XmATTACH_FORM, + NULL); + + XtVaSetValues (prefs_done, + XmNleftAttachment, XmATTACH_FORM, + XmNbottomAttachment, XmATTACH_FORM, + NULL); + XtVaSetValues (prefs_cancel, + XmNrightAttachment, XmATTACH_FORM, + XmNbottomAttachment, XmATTACH_FORM, + NULL); + XtVaSetValues (hr, + XmNbottomAttachment, XmATTACH_WIDGET, + XmNbottomWidget, prefs_done, + NULL); + + ac = 0; + children[ac++] = timeout_label; + children[ac++] = cycle_label; + children[ac++] = fade_seconds_label; + children[ac++] = fade_ticks_label; + children[ac++] = lock_label; + children[ac++] = passwd_label; + children[ac++] = timeout_text; + children[ac++] = cycle_text; + children[ac++] = fade_text; + children[ac++] = fade_ticks_text; + children[ac++] = lock_timeout_text; + children[ac++] = passwd_timeout_text; + children[ac++] = verbose_toggle; + children[ac++] = install_cmap_toggle; + children[ac++] = fade_toggle; + children[ac++] = unfade_toggle; + children[ac++] = lock_toggle; + children[ac++] = hr; + + XtManageChildren(children, ac); + ac = 0; + + XtManageChild (prefs_done); + XtManageChild (prefs_cancel); + + XtManageChild (preferences_form); + + XtVaSetValues (preferences_form, + XmNleftAttachment, XmATTACH_FORM, + XmNrightAttachment, XmATTACH_FORM, + XmNtopAttachment, XmATTACH_FORM, + XmNbottomAttachment, XmATTACH_FORM, + NULL); + + return preferences_form; +} diff --git a/driver/demo-Xm.c b/driver/demo-Xm.c new file mode 100644 index 00000000..56d1aac5 --- /dev/null +++ b/driver/demo-Xm.c @@ -0,0 +1,1875 @@ +/* demo-Xm.c --- implements the interactive demo-mode and options dialogs. + * xscreensaver, Copyright (c) 1993-2003, 2005 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. + */ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#ifdef HAVE_MOTIF /* whole file */ + +#include + +#ifdef HAVE_UNISTD_H +# include +#endif + +#ifndef VMS +# include /* for getpwuid() */ +#else /* VMS */ +# include "vms-pwd.h" +#endif /* VMS */ + +#ifdef HAVE_UNAME +# include /* for uname() */ +#endif /* HAVE_UNAME */ + +#include + +#include /* for CARD32 */ +#include /* for XA_INTEGER */ +#include +#include + +/* We don't actually use any widget internals, but these are included + so that gdb will have debug info for the widgets... */ +#include +#include + +#ifdef HAVE_XPM +# include +#endif /* HAVE_XPM */ + +#ifdef HAVE_XMU +# ifndef VMS +# include +# else /* VMS */ +# include +# endif +#else +# include "xmu.h" +#endif + + + +#include +#include +#include +#include +#include +#include + +#ifdef HAVE_XMCOMBOBOX /* a Motif 2.0 widget */ +# include +# ifndef XmNtextField /* Lesstif 0.89.4 bug */ +# undef HAVE_XMCOMBOBOX +# endif +# if (XmVersion < 2001) /* Lesstif has two personalities these days */ +# undef HAVE_XMCOMBOBOX +# endif +#endif /* HAVE_XMCOMBOBOX */ + +#include "version.h" +#include "prefs.h" +#include "resources.h" /* for parse_time() */ +#include "visual.h" /* for has_writable_cells() */ +#include "remote.h" /* for xscreensaver_command() */ +#include "usleep.h" + +#include +#include +#include + +#undef countof +#define countof(x) (sizeof((x))/sizeof((*x))) + + +char *progname = 0; +char *progclass = "XScreenSaver"; +XrmDatabase db; + +typedef struct { + saver_preferences *a, *b; +} prefs_pair; + +static void *global_prefs_pair; /* I hate C so much... */ + +char *blurb (void) { return progname; } + +extern Widget create_xscreensaver_demo (Widget parent); +extern const char *visual_menu[]; + + +static char *short_version = 0; + +Atom XA_VROOT; +Atom XA_SCREENSAVER, XA_SCREENSAVER_RESPONSE, XA_SCREENSAVER_VERSION; +Atom XA_SCREENSAVER_ID, XA_SCREENSAVER_STATUS, XA_SELECT, XA_DEMO; +Atom XA_ACTIVATE, XA_BLANK, XA_LOCK, XA_RESTART, XA_EXIT; + + +static void populate_demo_window (Widget toplevel, + int which, prefs_pair *pair); +static void populate_prefs_page (Widget top, prefs_pair *pair); +static int apply_changes_and_save (Widget widget); +static int maybe_reload_init_file (Widget widget, prefs_pair *pair); +static void await_xscreensaver (Widget widget); + + +/* Some random utility functions + */ + +static Widget +name_to_widget (Widget widget, const char *name) +{ + Widget parent; + char name2[255]; + name2[0] = '*'; + strcpy (name2+1, name); + + while ((parent = XtParent (widget))) + widget = parent; + return XtNameToWidget (widget, name2); +} + + + +/* Why this behavior isn't automatic in *either* toolkit, I'll never know. + Takes a scroller, viewport, or list as an argument. + */ +static void +ensure_selected_item_visible (Widget list) +{ + int *pos_list = 0; + int pos_count = 0; + if (XmListGetSelectedPos (list, &pos_list, &pos_count) && pos_count > 0) + { + int top = -2; + int visible = 0; + XtVaGetValues (list, + XmNtopItemPosition, &top, + XmNvisibleItemCount, &visible, + NULL); + if (pos_list[0] >= top + visible) + { + int pos = pos_list[0] - visible + 1; + if (pos < 0) pos = 0; + XmListSetPos (list, pos); + } + else if (pos_list[0] < top) + { + XmListSetPos (list, pos_list[0]); + } + } + if (pos_list) + XtFree ((char *) pos_list); +} + + +static void +warning_dialog_dismiss_cb (Widget button, XtPointer client_data, + XtPointer user_data) +{ + Widget shell = (Widget) client_data; + XtDestroyWidget (shell); +} + + +static void +warning_dialog (Widget parent, const char *message, int center) +{ + char *msg = strdup (message); + char *head; + + Widget dialog = 0; + Widget label = 0; + Widget ok = 0; + int i = 0; + + Widget w; + Widget container; + XmString xmstr; + Arg av[10]; + int ac = 0; + + ac = 0; + dialog = XmCreateWarningDialog (parent, "warning", av, ac); + + w = XmMessageBoxGetChild (dialog, XmDIALOG_MESSAGE_LABEL); + if (w) XtUnmanageChild (w); + w = XmMessageBoxGetChild (dialog, XmDIALOG_CANCEL_BUTTON); + if (w) XtUnmanageChild (w); + w = XmMessageBoxGetChild (dialog, XmDIALOG_HELP_BUTTON); + if (w) XtUnmanageChild (w); + + ok = XmMessageBoxGetChild (dialog, XmDIALOG_OK_BUTTON); + + ac = 0; + XtSetArg (av[ac], XmNnumColumns, 1); ac++; + XtSetArg (av[ac], XmNorientation, XmVERTICAL); ac++; + XtSetArg (av[ac], XmNpacking, XmPACK_COLUMN); ac++; + XtSetArg (av[ac], XmNrowColumnType, XmWORK_AREA); ac++; + XtSetArg (av[ac], XmNspacing, 0); ac++; + container = XmCreateRowColumn (dialog, "container", av, ac); + + head = msg; + while (head) + { + char name[20]; + char *s = strchr (head, '\n'); + if (s) *s = 0; + + sprintf (name, "label%d", i++); + + xmstr = XmStringCreate (head, XmSTRING_DEFAULT_CHARSET); + ac = 0; + XtSetArg (av[ac], XmNlabelString, xmstr); ac++; + XtSetArg (av[ac], XmNmarginHeight, 0); ac++; + label = XmCreateLabelGadget (container, name, av, ac); + XtManageChild (label); + XmStringFree (xmstr); + + if (s) + head = s+1; + else + head = 0; + + center--; + } + + XtManageChild (container); + XtRealizeWidget (dialog); + XtManageChild (dialog); + + XtAddCallback (ok, XmNactivateCallback, warning_dialog_dismiss_cb, dialog); + + free (msg); +} + + +static void +run_cmd (Widget widget, Atom command, int arg) +{ + char *err = 0; + int status; + + apply_changes_and_save (widget); + status = xscreensaver_command (XtDisplay (widget), + command, arg, False, &err); + if (status < 0) + { + char buf [255]; + if (err) + sprintf (buf, "Error:\n\n%s", err); + else + strcpy (buf, "Unknown error!"); + warning_dialog (widget, buf, 100); + } + if (err) free (err); +} + + +static void +run_hack (Widget widget, int which, Bool report_errors_p) +{ + if (which < 0) return; + apply_changes_and_save (widget); + if (report_errors_p) + run_cmd (widget, XA_DEMO, which + 1); + else + { + char *s = 0; + xscreensaver_command (XtDisplay (widget), XA_DEMO, which + 1, False, &s); + if (s) free (s); + } +} + + + +/* Button callbacks + */ + +void +exit_menu_cb (Widget button, XtPointer client_data, XtPointer ignored) +{ + apply_changes_and_save (XtParent (button)); + exit (0); +} + +#if 0 +static void +wm_close_cb (Widget widget, GdkEvent *event, XtPointer data) +{ + apply_changes_and_save (XtParent (button)); + exit (0); +} +#endif + +void +cut_menu_cb (Widget button, XtPointer client_data, XtPointer ignored) +{ + /* #### */ + warning_dialog (XtParent (button), + "Error:\n\n" + "cut unimplemented\n", 1); +} + + +void +copy_menu_cb (Widget button, XtPointer client_data, XtPointer ignored) +{ + /* #### */ + warning_dialog (XtParent (button), + "Error:\n\n" + "copy unimplemented\n", 1); +} + + +void +paste_menu_cb (Widget button, XtPointer client_data, XtPointer ignored) +{ + /* #### */ + warning_dialog (XtParent (button), + "Error:\n\n" + "paste unimplemented\n", 1); +} + + +void +about_menu_cb (Widget button, XtPointer client_data, XtPointer ignored) +{ + char buf [2048]; + char *s = strdup (screensaver_id + 4); + char *s2; + + s2 = strchr (s, ','); + *s2 = 0; + s2 += 2; + + sprintf (buf, "%s\n%s\n" + "\n" + "This is the Motif version of \"xscreensaver-demo\". The Motif\n" + "version is no longer maintained. Please use the GTK version\n" + "instead, which has many more features.\n" + "\n" + "For xscreensaver updates, check http://www.jwz.org/xscreensaver/", + s, s2); + free (s); + + warning_dialog (XtParent (button), buf, 100); +} + + +void +doc_menu_cb (Widget button, XtPointer client_data, XtPointer ignored) +{ + prefs_pair *pair = (prefs_pair *) client_data; + + saver_preferences *p = pair->a; + char *help_command; + + if (!p->help_url || !*p->help_url) + { + warning_dialog (XtParent (button), + "Error:\n\n" + "No Help URL has been specified.\n", 100); + return; + } + + help_command = (char *) malloc (strlen (p->load_url_command) + + (strlen (p->help_url) * 4) + 20); + strcpy (help_command, "( "); + sprintf (help_command + strlen(help_command), + p->load_url_command, + p->help_url, p->help_url, p->help_url, p->help_url); + strcat (help_command, " ) &"); + system (help_command); + free (help_command); +} + + +void +activate_menu_cb (Widget button, XtPointer client_data, XtPointer ignored) +{ + run_cmd (XtParent (button), XA_ACTIVATE, 0); +} + + +void +lock_menu_cb (Widget button, XtPointer client_data, XtPointer ignored) +{ + run_cmd (XtParent (button), XA_LOCK, 0); +} + + +void +kill_menu_cb (Widget button, XtPointer client_data, XtPointer ignored) +{ + run_cmd (XtParent (button), XA_EXIT, 0); +} + + +void +restart_menu_cb (Widget button, XtPointer client_data, XtPointer ignored) +{ +#if 0 + run_cmd (XtParent (button), XA_RESTART, 0); +#else + button = XtParent (button); + apply_changes_and_save (button); + xscreensaver_command (XtDisplay (button), XA_EXIT, 0, False, NULL); + sleep (1); + system ("xscreensaver -nosplash &"); +#endif + + await_xscreensaver (button); +} + +static void +await_xscreensaver (Widget widget) +{ + int countdown = 5; + + Display *dpy = XtDisplay (widget); + char *rversion = 0; + + while (!rversion && (--countdown > 0)) + { + /* Check for the version of the running xscreensaver... */ + server_xscreensaver_version (dpy, &rversion, 0, 0); + + /* If it's not there yet, wait a second... */ + sleep (1); + } + + if (rversion) + { + /* Got it. */ + free (rversion); + } + else + { + /* Timed out, no screensaver running. */ + + char buf [1024]; + Bool root_p = (geteuid () == 0); + + strcpy (buf, + "Error:\n\n" + "The xscreensaver daemon did not start up properly.\n" + "\n"); + + if (root_p) +# ifdef __GNUC__ + __extension__ /* don't warn about "string length is greater than + the length ISO C89 compilers are required to + support" in the following expression... */ +# endif + strcat (buf, + "You are running as root. This usually means that xscreensaver\n" + "was unable to contact your X server because access control is\n" + "turned on. Try running this command:\n" + "\n" + " xhost +localhost\n" + "\n" + "and then selecting `File / Restart Daemon'.\n" + "\n" + "Note that turning off access control will allow anyone logged\n" + "on to this machine to access your screen, which might be\n" + "considered a security problem. Please read the xscreensaver\n" + "manual and FAQ for more information.\n" + "\n" + "You shouldn't run X as root. Instead, you should log in as a\n" + "normal user, and `su' as necessary."); + else + strcat (buf, "Please check your $PATH and permissions."); + + warning_dialog (XtParent (widget), buf, 1); + } +} + + +static int _selected_hack_number = -1; + +static int +selected_hack_number (Widget toplevel) +{ + return _selected_hack_number; +} + + +static int +demo_write_init_file (Widget widget, saver_preferences *p) +{ + if (!write_init_file (XtDisplay (widget), p, short_version, False)) + return 0; + else + { + const char *f = init_file_name(); + if (!f || !*f) + warning_dialog (widget, + "Error:\n\nCouldn't determine init file name!\n", + 100); + else + { + char *b = (char *) malloc (strlen(f) + 1024); + sprintf (b, "Error:\n\nCouldn't write %s\n", f); + warning_dialog (widget, b, 100); + free (b); + } + return -1; + } +} + + +static int +apply_changes_and_save (Widget widget) +{ + prefs_pair *pair = global_prefs_pair; + saver_preferences *p = pair->a; + Widget list_widget = name_to_widget (widget, "list"); + int which = selected_hack_number (widget); + + Widget cmd = name_to_widget (widget, "cmdText"); + Widget enabled = name_to_widget (widget, "enabled"); + + Widget vis = name_to_widget (widget, "combo"); +# ifdef HAVE_XMCOMBOBOX + Widget text = 0; +# else /* !HAVE_XMCOMBOBOX */ + Widget menu = 0, *kids = 0, selected_item = 0; + Cardinal nkids = 0; + int i = 0; +# endif /* !HAVE_XMCOMBOBOX */ + + Bool enabled_p = False; + const char *visual = 0; + const char *command = 0; + + char c; + unsigned long id; + + if (which < 0) return -1; + +# ifdef HAVE_XMCOMBOBOX + XtVaGetValues (vis, XmNtextField, &text, NULL); + if (!text) + /* If we can't get at the text field of this combo box, we're screwed. */ + abort(); + XtVaGetValues (text, XmNvalue, &visual, NULL); + +# else /* !HAVE_XMCOMBOBOX */ + XtVaGetValues (vis, XmNsubMenuId, &menu, NULL); + XtVaGetValues (menu, XmNnumChildren, &nkids, XmNchildren, &kids, NULL); + XtVaGetValues (menu, XmNmenuHistory, &selected_item, NULL); + if (selected_item) + for (i = 0; i < nkids; i++) + if (kids[i] == selected_item) + break; + + visual = visual_menu[i]; +# endif /* !HAVE_XMCOMBOBOX */ + + XtVaGetValues (enabled, XmNset, &enabled_p, NULL); + XtVaGetValues (cmd, XtNvalue, &command, NULL); + + if (maybe_reload_init_file (widget, pair) != 0) + return 1; + + /* Sanity-check and canonicalize whatever the user typed into the combo box. + */ + if (!strcasecmp (visual, "")) visual = ""; + else if (!strcasecmp (visual, "any")) visual = ""; + else if (!strcasecmp (visual, "default")) visual = "Default"; + else if (!strcasecmp (visual, "default-n")) visual = "Default-N"; + else if (!strcasecmp (visual, "default-i")) visual = "Default-I"; + else if (!strcasecmp (visual, "best")) visual = "Best"; + else if (!strcasecmp (visual, "mono")) visual = "Mono"; + else if (!strcasecmp (visual, "monochrome")) visual = "Mono"; + else if (!strcasecmp (visual, "gray")) visual = "Gray"; + else if (!strcasecmp (visual, "grey")) visual = "Gray"; + else if (!strcasecmp (visual, "color")) visual = "Color"; + else if (!strcasecmp (visual, "gl")) visual = "GL"; + else if (!strcasecmp (visual, "staticgray")) visual = "StaticGray"; + else if (!strcasecmp (visual, "staticcolor")) visual = "StaticColor"; + else if (!strcasecmp (visual, "truecolor")) visual = "TrueColor"; + else if (!strcasecmp (visual, "grayscale")) visual = "GrayScale"; + else if (!strcasecmp (visual, "greyscale")) visual = "GrayScale"; + else if (!strcasecmp (visual, "pseudocolor")) visual = "PseudoColor"; + else if (!strcasecmp (visual, "directcolor")) visual = "DirectColor"; + else if (1 == sscanf (visual, " %lu %c", &id, &c)) ; + else if (1 == sscanf (visual, " 0x%lx %c", &id, &c)) ; + else + { + XBell (XtDisplay (widget), 0); /* unparsable */ + visual = ""; + /* #### gtk_entry_set_text (GTK_ENTRY (GTK_COMBO (vis)->entry), "Any");*/ + } + + ensure_selected_item_visible (list_widget); + + if (!p->screenhacks[which]->visual) + p->screenhacks[which]->visual = strdup (""); + if (!p->screenhacks[which]->command) + p->screenhacks[which]->command = strdup (""); + + if (p->screenhacks[which]->enabled_p != enabled_p || + !!strcasecmp (p->screenhacks[which]->visual, visual) || + !!strcasecmp (p->screenhacks[which]->command, command)) + { + /* Something was changed -- store results into the struct, + and write the file. + */ + free (p->screenhacks[which]->visual); + free (p->screenhacks[which]->command); + p->screenhacks[which]->visual = strdup (visual); + p->screenhacks[which]->command = strdup (command); + p->screenhacks[which]->enabled_p = enabled_p; + + return demo_write_init_file (widget, p); + } + + /* No changes made */ + return 0; +} + +void +run_this_cb (Widget button, XtPointer client_data, XtPointer ignored) +{ + int which = selected_hack_number (XtParent (button)); + if (which < 0) return; + if (0 == apply_changes_and_save (XtParent (button))) + run_hack (XtParent (button), which, True); +} + + +void +manual_cb (Widget button, XtPointer client_data, XtPointer ignored) +{ + prefs_pair *pair = (prefs_pair *) client_data; + saver_preferences *p = pair->a; + Widget list_widget = name_to_widget (button, "list"); + int which = selected_hack_number (button); + char *name, *name2, *cmd, *s; + if (which < 0) return; + apply_changes_and_save (button); + ensure_selected_item_visible (list_widget); + + name = strdup (p->screenhacks[which]->command); + name2 = name; + while (isspace (*name2)) name2++; + s = name2; + while (*s && !isspace (*s)) s++; + *s = 0; + s = strrchr (name2, '/'); + if (s) name = s+1; + + cmd = get_string_resource (XtDisplay (button), "manualCommand", "ManualCommand"); + if (cmd) + { + char *cmd2 = (char *) malloc (strlen (cmd) + (strlen (name2) * 4) + 100); + strcpy (cmd2, "( "); + sprintf (cmd2 + strlen (cmd2), + cmd, + name2, name2, name2, name2); + strcat (cmd2, " ) &"); + system (cmd2); + free (cmd2); + } + else + { + warning_dialog (XtParent (button), + "Error:\n\nno `manualCommand' resource set.", + 100); + } + + free (name); +} + + +void +run_next_cb (Widget button, XtPointer client_data, XtPointer ignored) +{ + prefs_pair *pair = (prefs_pair *) client_data; + saver_preferences *p = pair->a; + + Widget list_widget = name_to_widget (button, "list"); + int which = selected_hack_number (button); + + button = XtParent (button); + + if (which < 0) + which = 0; + else + which++; + + if (which >= p->screenhacks_count) + which = 0; + + apply_changes_and_save (button); + + XmListDeselectAllItems (list_widget); /* LessTif lossage */ + XmListSelectPos (list_widget, which+1, True); + + ensure_selected_item_visible (list_widget); + populate_demo_window (button, which, pair); + run_hack (button, which, False); +} + + +void +run_prev_cb (Widget button, XtPointer client_data, XtPointer ignored) +{ + prefs_pair *pair = (prefs_pair *) client_data; + saver_preferences *p = pair->a; + + Widget list_widget = name_to_widget (button, "list"); + int which = selected_hack_number (button); + + button = XtParent (button); + + if (which < 0) + which = p->screenhacks_count - 1; + else + which--; + + if (which < 0) + which = p->screenhacks_count - 1; + + apply_changes_and_save (button); + + XmListDeselectAllItems (list_widget); /* LessTif lossage */ + XmListSelectPos (list_widget, which+1, True); + + ensure_selected_item_visible (list_widget); + populate_demo_window (button, which, pair); + run_hack (button, which, False); +} + + +/* Helper for the text fields that contain time specifications: + this parses the text, and does error checking. + */ +static void +hack_time_text (Widget button, const char *line, Time *store, Bool sec_p) +{ + if (*line) + { + int value; + value = parse_time ((char *) line, sec_p, True); + value *= 1000; /* Time measures in microseconds */ + if (value < 0) + { + char b[255]; + sprintf (b, + "Error:\n\n" + "Unparsable time format: \"%s\"\n", + line); + warning_dialog (XtParent (button), b, 100); + } + else + *store = value; + } +} + + +void +prefs_ok_cb (Widget button, XtPointer client_data, XtPointer ignored) +{ + prefs_pair *pair = (prefs_pair *) client_data; + + saver_preferences *p = pair->a; + saver_preferences *p2 = pair->b; + Bool changed = False; + char *v = 0; + + button = XtParent (button); + +# define SECONDS(field, name) \ + v = 0; \ + XtVaGetValues (name_to_widget (button, (name)), XtNvalue, &v, NULL); \ + hack_time_text (button, v, (field), True) + +# define MINUTES(field, name) \ + v = 0; \ + XtVaGetValues (name_to_widget (button, (name)), XtNvalue, &v, NULL); \ + hack_time_text (button, v, (field), False) + +# define INTEGER(field, name) do { \ + unsigned int value; \ + char c; \ + XtVaGetValues (name_to_widget (button, (name)), XtNvalue, &v, NULL); \ + if (! *v) \ + ; \ + else if (sscanf (v, "%u%c", &value, &c) != 1) \ + { \ + char b[255]; \ + sprintf (b, "Error:\n\n" "Not an integer: \"%s\"\n", v); \ + warning_dialog (XtParent (button), b, 100); \ + } \ + else \ + *(field) = value; \ + } while(0) + +# define CHECKBOX(field, name) \ + XtVaGetValues (name_to_widget (button, (name)), XmNset, &field, NULL) + + MINUTES (&p2->timeout, "timeoutText"); + MINUTES (&p2->cycle, "cycleText"); + SECONDS (&p2->fade_seconds, "fadeSecondsText"); + INTEGER (&p2->fade_ticks, "fadeTicksText"); + MINUTES (&p2->lock_timeout, "lockText"); + SECONDS (&p2->passwd_timeout, "passwdText"); + CHECKBOX (p2->verbose_p, "verboseToggle"); + CHECKBOX (p2->install_cmap_p, "cmapToggle"); + CHECKBOX (p2->fade_p, "fadeToggle"); + CHECKBOX (p2->unfade_p, "unfadeToggle"); + CHECKBOX (p2->lock_p, "lockToggle"); + +# undef SECONDS +# undef MINUTES +# undef INTEGER +# undef CHECKBOX + +# define COPY(field) \ + if (p->field != p2->field) changed = True; \ + p->field = p2->field + + COPY(timeout); + COPY(cycle); + COPY(lock_timeout); + COPY(passwd_timeout); + COPY(fade_seconds); + COPY(fade_ticks); + COPY(verbose_p); + COPY(install_cmap_p); + COPY(fade_p); + COPY(unfade_p); + COPY(lock_p); +# undef COPY + + populate_prefs_page (button, pair); + + if (changed) + demo_write_init_file (button, p); +} + + +void +prefs_cancel_cb (Widget button, XtPointer client_data, XtPointer ignored) +{ + prefs_pair *pair = (prefs_pair *) client_data; + + *pair->b = *pair->a; + populate_prefs_page (XtParent (button), pair); +} + + +static void +list_select_cb (Widget list, XtPointer client_data, XtPointer call_data) +{ + prefs_pair *pair = (prefs_pair *) client_data; + + XmListCallbackStruct *lcb = (XmListCallbackStruct *) call_data; + int which = lcb->item_position - 1; + + apply_changes_and_save (list); + populate_demo_window (list, which, pair); + + if (lcb->reason == XmCR_DEFAULT_ACTION && which >= 0) + run_hack (list, which, True); +} + + +/* Populating the various widgets + */ + + +/* Formats a `Time' into "H:MM:SS". (Time is microseconds.) + */ +static void +format_time (char *buf, Time time) +{ + int s = time / 1000; + unsigned int h = 0, m = 0; + if (s >= 60) + { + m += (s / 60); + s %= 60; + } + if (m >= 60) + { + h += (m / 60); + m %= 60; + } + sprintf (buf, "%u:%02u:%02u", h, m, s); +} + + +/* Finds the number of the last hack to run, and makes that item be + selected by default. + */ +static void +scroll_to_current_hack (Widget toplevel, prefs_pair *pair) +{ + Atom type; + int format; + unsigned long nitems, bytesafter; + unsigned char *data = 0; + Display *dpy = XtDisplay (toplevel); + int which = 0; + Widget list; + + if (XGetWindowProperty (dpy, RootWindow (dpy, 0), /* always screen #0 */ + XA_SCREENSAVER_STATUS, + 0, 3, False, XA_INTEGER, + &type, &format, &nitems, &bytesafter, + &data) + == Success + && type == XA_INTEGER + && nitems >= 3 + && data) + which = (int) data[2] - 1; + + if (data) free (data); + + if (which < 0) + return; + + list = name_to_widget (toplevel, "list"); + apply_changes_and_save (toplevel); + + XmListDeselectAllItems (list); /* LessTif lossage */ + XmListSelectPos (list, which+1, True); + + ensure_selected_item_visible (list); + populate_demo_window (toplevel, which, pair); +} + + + +static void +populate_hack_list (Widget toplevel, prefs_pair *pair) +{ + saver_preferences *p = pair->a; + Widget list = name_to_widget (toplevel, "list"); + screenhack **hacks = p->screenhacks; + screenhack **h; + + for (h = hacks; *h; h++) + { + char *pretty_name = (h[0]->name + ? strdup (h[0]->name) + : make_hack_name (XtDisplay (toplevel), h[0]->command)); + + XmString xmstr = XmStringCreate (pretty_name, XmSTRING_DEFAULT_CHARSET); + XmListAddItem (list, xmstr, 0); + XmStringFree (xmstr); + } + + XtAddCallback (list, XmNbrowseSelectionCallback, list_select_cb, pair); + XtAddCallback (list, XmNdefaultActionCallback, list_select_cb, pair); +} + + +static void +populate_prefs_page (Widget top, prefs_pair *pair) +{ + saver_preferences *p = pair->a; + char s[100]; + + format_time (s, p->timeout); + XtVaSetValues (name_to_widget (top, "timeoutText"), XmNvalue, s, NULL); + format_time (s, p->cycle); + XtVaSetValues (name_to_widget (top, "cycleText"), XmNvalue, s, NULL); + format_time (s, p->lock_timeout); + XtVaSetValues (name_to_widget (top, "lockText"), XmNvalue, s, NULL); + format_time (s, p->passwd_timeout); + XtVaSetValues (name_to_widget (top, "passwdText"), XmNvalue, s, NULL); + format_time (s, p->fade_seconds); + XtVaSetValues (name_to_widget (top, "fadeSecondsText"), XmNvalue, s, NULL); + sprintf (s, "%u", p->fade_ticks); + XtVaSetValues (name_to_widget (top, "fadeTicksText"), XmNvalue, s, NULL); + + XtVaSetValues (name_to_widget (top, "verboseToggle"), + XmNset, p->verbose_p, NULL); + XtVaSetValues (name_to_widget (top, "cmapToggle"), + XmNset, p->install_cmap_p, NULL); + XtVaSetValues (name_to_widget (top, "fadeToggle"), + XmNset, p->fade_p, NULL); + XtVaSetValues (name_to_widget (top, "unfadeToggle"), + XmNset, p->unfade_p, NULL); + XtVaSetValues (name_to_widget (top, "lockToggle"), + XmNset, p->lock_p, NULL); + + + { + Bool found_any_writable_cells = False; + Display *dpy = XtDisplay (top); + int nscreens = ScreenCount(dpy); + int i; + for (i = 0; i < nscreens; i++) + { + Screen *s = ScreenOfDisplay (dpy, i); + if (has_writable_cells (s, DefaultVisualOfScreen (s))) + { + found_any_writable_cells = True; + break; + } + } + +#ifdef HAVE_XF86VMODE_GAMMA + found_any_writable_cells = True; /* if we can gamma fade, go for it */ +#endif + + XtVaSetValues (name_to_widget (top, "fadeSecondsLabel"), XtNsensitive, + found_any_writable_cells, NULL); + XtVaSetValues (name_to_widget (top, "fadeTicksLabel"), XtNsensitive, + found_any_writable_cells, NULL); + XtVaSetValues (name_to_widget (top, "fadeSecondsText"), XtNsensitive, + found_any_writable_cells, NULL); + XtVaSetValues (name_to_widget (top, "fadeTicksText"), XtNsensitive, + found_any_writable_cells, NULL); + XtVaSetValues (name_to_widget (top, "cmapToggle"), XtNsensitive, + found_any_writable_cells, NULL); + XtVaSetValues (name_to_widget (top, "fadeToggle"), XtNsensitive, + found_any_writable_cells, NULL); + XtVaSetValues (name_to_widget (top, "unfadeToggle"), XtNsensitive, + found_any_writable_cells, NULL); + } +} + + +static void +sensitize_demo_widgets (Widget toplevel, Bool sensitive_p) +{ + const char *names[] = { "cmdLabel", "cmdText", "enabled", + "visLabel", "combo", "demo", "man" }; + int i; + for (i = 0; i < sizeof(names)/countof(*names); i++) + { + Widget w = name_to_widget (toplevel, names[i]); + XtVaSetValues (w, XtNsensitive, sensitive_p, NULL); + } + + /* I don't know how to handle these yet... */ + { + const char *names2[] = { "cut", "copy", "paste" }; + for (i = 0; i < sizeof(names2)/countof(*names2); i++) + { + Widget w = name_to_widget (toplevel, names2[i]); + XtVaSetValues (w, XtNsensitive, FALSE, NULL); + } + } +} + + + +/* Pixmaps for the up and down arrow buttons (yeah, this is sleazy...) + */ + +#ifdef HAVE_XPM + +static char *up_arrow_xpm[] = { + "15 15 4 1", + " c None s background", + "- c #FFFFFF", + "+ c #D6D6D6", + "@ c #000000", + + " @ ", + " @ ", + " -+@ ", + " -+@ ", + " -+++@ ", + " -+++@ ", + " -+++++@ ", + " -+++++@ ", + " -+++++++@ ", + " -+++++++@ ", + " -+++++++++@ ", + " -+++++++++@ ", + " -+++++++++++@ ", + " @@@@@@@@@@@@@ ", + " " +}; + +static char *down_arrow_xpm[] = { + "15 15 4 1", + " c None s background", + "- c #FFFFFF", + "+ c #D6D6D6", + "@ c #000000", + + " ", + " ------------- ", + " -+++++++++++@ ", + " -+++++++++@ ", + " -+++++++++@ ", + " -+++++++@ ", + " -+++++++@ ", + " -+++++@ ", + " -+++++@ ", + " -+++@ ", + " -+++@ ", + " -+@ ", + " -+@ ", + " @ ", + " @ " +}; + +#endif /* HAVE_XPM */ + + +static void +pixmapify_buttons (Widget toplevel) +{ +#ifdef HAVE_XPM + + Display *dpy = XtDisplay (toplevel); + Window window = XtWindow (toplevel); + XWindowAttributes xgwa; + XpmAttributes xpmattrs; + Pixmap up_pixmap = 0, down_pixmap = 0; + int result; + Widget up = name_to_widget (toplevel, "up"); + Widget dn = name_to_widget (toplevel, "down"); +# ifdef XpmColorSymbols + XColor xc; + XpmColorSymbol symbols[2]; + char color[20]; +# endif + + XGetWindowAttributes (dpy, window, &xgwa); + + xpmattrs.valuemask = 0; + +# ifdef XpmColorSymbols + symbols[0].name = "background"; + symbols[0].pixel = 0; + symbols[1].name = 0; + XtVaGetValues (up, XmNbackground, &xc, NULL); + XQueryColor (dpy, xgwa.colormap, &xc); + sprintf (color, "#%04X%04X%04X", xc.red, xc.green, xc.blue); + symbols[0].value = color; + symbols[0].pixel = xc.pixel; + + xpmattrs.valuemask |= XpmColorSymbols; + xpmattrs.colorsymbols = symbols; + xpmattrs.numsymbols = 1; +# endif + +# ifdef XpmCloseness + xpmattrs.valuemask |= XpmCloseness; + xpmattrs.closeness = 40000; +# endif +# ifdef XpmVisual + xpmattrs.valuemask |= XpmVisual; + xpmattrs.visual = xgwa.visual; +# endif +# ifdef XpmDepth + xpmattrs.valuemask |= XpmDepth; + xpmattrs.depth = xgwa.depth; +# endif +# ifdef XpmColormap + xpmattrs.valuemask |= XpmColormap; + xpmattrs.colormap = xgwa.colormap; +# endif + + result = XpmCreatePixmapFromData(dpy, window, up_arrow_xpm, + &up_pixmap, 0 /* mask */, &xpmattrs); + if (!up_pixmap || (result != XpmSuccess && result != XpmColorError)) + { + fprintf (stderr, "%s: Can't load pixmaps\n", progname); + return; + } + + result = XpmCreatePixmapFromData(dpy, window, down_arrow_xpm, + &down_pixmap, 0 /* mask */, &xpmattrs); + if (!down_pixmap || (result != XpmSuccess && result != XpmColorError)) + { + fprintf (stderr, "%s: Can't load pixmaps\n", progname); + return; + } + + XtVaSetValues (up, XmNlabelType, XmPIXMAP, XmNlabelPixmap, up_pixmap, NULL); + XtVaSetValues (dn, XmNlabelType, XmPIXMAP, XmNlabelPixmap, down_pixmap,NULL); + +#endif /* HAVE_XPM */ +} + + + +char * +get_hack_blurb (Display *dpy, screenhack *hack) +{ + char *doc_string; + char *prog_name = strdup (hack->command); + char *pretty_name = (hack->name + ? strdup (hack->name) + : make_hack_name (dpy, hack->command)); + char doc_name[255], doc_class[255]; + char *s, *s2; + + for (s = prog_name; *s && !isspace(*s); s++) + ; + *s = 0; + s = strrchr (prog_name, '/'); + if (s) strcpy (prog_name, s+1); + + sprintf (doc_name, "hacks.%s.documentation", pretty_name); + sprintf (doc_class, "hacks.%s.documentation", prog_name); + free (prog_name); + free (pretty_name); + + doc_string = get_string_resource (dpy, doc_name, doc_class); + if (doc_string) + { + for (s = doc_string; *s; s++) + { + if (*s == '\n') + { + /* skip over whitespace at beginning of line */ + s++; + while (*s && (*s == ' ' || *s == '\t')) + s++; + } + else if (*s == ' ' || *s == '\t') + { + /* compress all other horizontal whitespace. */ + *s = ' '; + s++; + for (s2 = s; *s2 && (*s2 == ' ' || *s2 == '\t'); s2++) + ; + if (s2 > s) strcpy (s, s2); + s--; + } + } + + while (*s && isspace (*s)) /* Strip trailing whitespace */ + *(--s) = 0; + + /* Delete whitespace at end of each line. */ + for (; s > doc_string; s--) + if (*s == '\n' && (s[-1] == ' ' || s[-1] == '\t')) + { + for (s2 = s-1; + s2 > doc_string && (*s2 == ' ' || *s2 == '\t'); + s2--) + ; + s2++; + if (s2 < s) strcpy (s2, s); + s = s2; + } + + /* Delete leading blank lines. */ + for (s = doc_string; *s == '\n'; s++) + ; + if (s > doc_string) strcpy (doc_string, s); + } + else + { +# if 0 + static int doc_installed = 0; + if (doc_installed == 0) + { + if (get_boolean_resource ("hacks.documentation.isInstalled", + "hacks.documentation.isInstalled")) + doc_installed = 1; + else + doc_installed = -1; + } + + if (doc_installed < 0) + doc_string = + strdup ("Error:\n\n" + "The documentation strings do not appear to be " + "installed. This is probably because there is " + "an \"XScreenSaver\" app-defaults file installed " + "that is from an older version of the program. " + "To fix this problem, delete that file, or " + "install a current version (either will work.)"); + else +# endif /* 0 */ + doc_string = strdup ( + "\n" + "This is the Motif version of \"xscreensaver-demo\". The Motif " + "version is no longer maintained. Please use the GTK version " + "instead, which has many more features." + "\n\n" + "If you were running the GTK version, there would be a preview " + "of this screen saver mode displayed here, along with graphical " + "configuration options."); + } + + return doc_string; +} + + +static void +populate_demo_window (Widget toplevel, int which, prefs_pair *pair) +{ + saver_preferences *p = pair->a; + screenhack *hack = (which >= 0 ? p->screenhacks[which] : 0); + Widget frameL = name_to_widget (toplevel, "frameLabel"); + Widget doc = name_to_widget (toplevel, "doc"); + Widget cmd = name_to_widget (toplevel, "cmdText"); + Widget enabled = name_to_widget (toplevel, "enabled"); + Widget vis = name_to_widget (toplevel, "combo"); + int i = 0; + + char *pretty_name = (hack + ? (hack->name + ? strdup (hack->name) + : make_hack_name (XtDisplay (toplevel), hack->command)) + : 0); + char *doc_string = hack ? get_hack_blurb (XtDisplay (toplevel), hack) : 0; + + XmString xmstr; + + xmstr = XmStringCreate (pretty_name, XmSTRING_DEFAULT_CHARSET); + XtVaSetValues (frameL, XmNlabelString, xmstr, NULL); + XmStringFree (xmstr); + + XtVaSetValues (doc, XmNvalue, doc_string, NULL); + XtVaSetValues (cmd, XmNvalue, (hack ? hack->command : ""), NULL); + + XtVaSetValues (enabled, XmNset, (hack ? hack->enabled_p : False), NULL); + + i = 0; + if (hack && hack->visual && *hack->visual) + for (i = 0; visual_menu[i]; i++) + if (!strcasecmp (hack->visual, visual_menu[i])) + break; + if (!visual_menu[i]) i = -1; + + { +# ifdef HAVE_XMCOMBOBOX + Widget text = 0; + XtVaGetValues (vis, XmNtextField, &text, NULL); + XtVaSetValues (vis, XmNselectedPosition, i, NULL); + if (i < 0) + XtVaSetValues (text, XmNvalue, hack->visual, NULL); +# else /* !HAVE_XMCOMBOBOX */ + Cardinal nkids; + Widget *kids; + Widget menu; + + XtVaGetValues (vis, XmNsubMenuId, &menu, NULL); + if (!menu) abort (); + XtVaGetValues (menu, XmNnumChildren, &nkids, XmNchildren, &kids, NULL); + if (!kids) abort(); + if (i < nkids) + XtVaSetValues (vis, XmNmenuHistory, kids[i], NULL); +# endif /* !HAVE_XMCOMBOBOX */ + } + + sensitize_demo_widgets (toplevel, (hack ? True : False)); + + if (pretty_name) free (pretty_name); + if (doc_string) free (doc_string); + + _selected_hack_number = which; +} + + + +static int +maybe_reload_init_file (Widget widget, prefs_pair *pair) +{ + int status = 0; + saver_preferences *p = pair->a; + + static Bool reentrant_lock = False; + if (reentrant_lock) return 0; + reentrant_lock = True; + + if (init_file_changed_p (p)) + { + const char *f = init_file_name(); + char *b; + int which; + Widget list; + + if (!f || !*f) return 0; + b = (char *) malloc (strlen(f) + 1024); + sprintf (b, + "Warning:\n\n" + "file \"%s\" has changed, reloading.\n", + f); + warning_dialog (widget, b, 100); + free (b); + + load_init_file (XtDisplay (widget), p); + + which = selected_hack_number (widget); + list = name_to_widget (widget, "list"); + + XtVaSetValues (list, XmNitemCount, 0, NULL); + + populate_hack_list (widget, pair); + + XmListDeselectAllItems (list); /* LessTif lossage */ + XmListSelectPos (list, which+1, True); + + populate_prefs_page (widget, pair); + populate_demo_window (widget, which, pair); + ensure_selected_item_visible (list); + + status = 1; + } + + reentrant_lock = False; + return status; +} + + + +/* Attach all callback functions to widgets + */ + +static void +add_callbacks (Widget toplevel, prefs_pair *pair) +{ + Widget w; + +# define CB(NAME,FN) \ + w = name_to_widget (toplevel, (NAME)); \ + XtAddCallback (w, XmNactivateCallback, (FN), pair) + + CB ("blank", activate_menu_cb); + CB ("lock", lock_menu_cb); + CB ("kill", kill_menu_cb); + CB ("restart", restart_menu_cb); + CB ("exit", exit_menu_cb); + + CB ("cut", cut_menu_cb); + CB ("copy", copy_menu_cb); + CB ("paste", paste_menu_cb); + + CB ("about", about_menu_cb); + CB ("docMenu", doc_menu_cb); + + CB ("down", run_next_cb); + CB ("up", run_prev_cb); + CB ("demo", run_this_cb); + CB ("man", manual_cb); + + CB ("preferencesForm.Cancel", prefs_cancel_cb); + CB ("preferencesForm.OK", prefs_ok_cb); + +# undef CB +} + + +static void +sanity_check_resources (Widget toplevel) +{ + const char *names[] = { "demoTab", "optionsTab", "cmdLabel", "visLabel", + "enabled", "demo", "man", "timeoutLabel", + "cycleLabel", "fadeSecondsLabel", "fadeTicksLabel", + "lockLabel", "passwdLabel" }; + int i; + for (i = 0; i < sizeof(names)/countof(*names); i++) + { + Widget w = name_to_widget (toplevel, names[i]); + const char *name = XtName(w); + XmString xm = 0; + char *label = 0; + XtVaGetValues (w, XmNlabelString, &xm, NULL); + if (xm) XmStringGetLtoR (xm, XmSTRING_DEFAULT_CHARSET, &label); + if (w && (!label || !strcmp (name, label))) + { + xm = XmStringCreate ("ERROR", XmSTRING_DEFAULT_CHARSET); + XtVaSetValues (w, XmNlabelString, xm, NULL); + } + } +} + +/* Set certain buttons to be the same size (the max of the set.) + */ +static void +hack_button_sizes (Widget toplevel) +{ + Widget demo = name_to_widget (toplevel, "demo"); + Widget man = name_to_widget (toplevel, "man"); + Widget ok = name_to_widget (toplevel, "OK"); + Widget can = name_to_widget (toplevel, "Cancel"); + Widget up = name_to_widget (toplevel, "up"); + Widget down = name_to_widget (toplevel, "down"); + Dimension w1, w2; + + XtVaGetValues (demo, XmNwidth, &w1, NULL); + XtVaGetValues (man, XmNwidth, &w2, NULL); + XtVaSetValues ((w1 > w2 ? man : demo), XmNwidth, (w1 > w2 ? w1 : w2), NULL); + + XtVaGetValues (ok, XmNwidth, &w1, NULL); + XtVaGetValues (can, XmNwidth, &w2, NULL); + XtVaSetValues ((w1 > w2 ? can : ok), XmNwidth, (w1 > w2 ? w1 : w2), NULL); + + XtVaGetValues (up, XmNwidth, &w1, NULL); + XtVaGetValues (down, XmNwidth, &w2, NULL); + XtVaSetValues ((w1 > w2 ? down : up), XmNwidth, (w1 > w2 ? w1 : w2), NULL); +} + + + + +/* The main demo-mode command loop. + */ + +#if 0 +static Bool +mapper (XrmDatabase *db, XrmBindingList bindings, XrmQuarkList quarks, + XrmRepresentation *type, XrmValue *value, XPointer closure) +{ + int i; + for (i = 0; quarks[i]; i++) + { + if (bindings[i] == XrmBindTightly) + fprintf (stderr, (i == 0 ? "" : ".")); + else if (bindings[i] == XrmBindLoosely) + fprintf (stderr, "*"); + else + fprintf (stderr, " ??? "); + fprintf(stderr, "%s", XrmQuarkToString (quarks[i])); + } + + fprintf (stderr, ": %s\n", (char *) value->addr); + + return False; +} +#endif + + +static void +the_network_is_not_the_computer (Widget parent) +{ + Display *dpy = XtDisplay (parent); + char *rversion, *ruser, *rhost; + char *luser, *lhost; + char *msg = 0; + struct passwd *p = getpwuid (getuid ()); + const char *d = DisplayString (dpy); + +# if defined(HAVE_UNAME) + struct utsname uts; + if (uname (&uts) < 0) + lhost = ""; + else + lhost = uts.nodename; +# elif defined(VMS) + strcpy (lhost, getenv("SYS$NODE")); +# else /* !HAVE_UNAME && !VMS */ + strcat (lhost, ""); +# endif /* !HAVE_UNAME && !VMS */ + + if (p && p->pw_name) + luser = p->pw_name; + else + luser = "???"; + + server_xscreensaver_version (dpy, &rversion, &ruser, &rhost); + + /* Make a buffer that's big enough for a number of copies of all the + strings, plus some. */ + msg = (char *) malloc (10 * ((rversion ? strlen(rversion) : 0) + + (ruser ? strlen(ruser) : 0) + + (rhost ? strlen(rhost) : 0) + + strlen(lhost) + + strlen(luser) + + strlen(d) + + 1024)); + *msg = 0; + + if (!rversion || !*rversion) + { + sprintf (msg, + "Warning:\n\n" + "The XScreenSaver daemon doesn't seem to be running\n" + "on display \"%s\". You can launch it by selecting\n" + "`Restart Daemon' from the File menu, or by typing\n" + "\"xscreensaver &\" in a shell.", + d); + } + else if (p && ruser && *ruser && !!strcmp (ruser, p->pw_name)) + { + /* Warn that the two processes are running as different users. + */ + sprintf(msg, + "Warning:\n\n" + "%s is running as user \"%s\" on host \"%s\".\n" + "But the xscreensaver managing display \"%s\"\n" + "is running as user \"%s\" on host \"%s\".\n" + "\n" + "Since they are different users, they won't be reading/writing\n" + "the same ~/.xscreensaver file, so %s isn't\n" + "going to work right.\n" + "\n" + "Either re-run %s as \"%s\", or re-run\n" + "xscreensaver as \"%s\" (which you can do by\n" + "selecting `Restart Daemon' from the File menu.)\n", + progname, luser, lhost, + d, + (ruser ? ruser : "???"), (rhost ? rhost : "???"), + progname, + progname, (ruser ? ruser : "???"), + luser); + } + else if (rhost && *rhost && !!strcmp (rhost, lhost)) + { + /* Warn that the two processes are running on different hosts. + */ + sprintf (msg, + "Warning:\n\n" + "%s is running as user \"%s\" on host \"%s\".\n" + "But the xscreensaver managing display \"%s\"\n" + "is running as user \"%s\" on host \"%s\".\n" + "\n" + "If those two machines don't share a file system (that is,\n" + "if they don't see the same ~%s/.xscreensaver file) then\n" + "%s won't work right.\n" + "\n" + "You can restart the daemon on \"%s\" as \"%s\" by\n" + "selecting `Restart Daemon' from the File menu.)", + progname, luser, lhost, + d, + (ruser ? ruser : "???"), (rhost ? rhost : "???"), + luser, + progname, + lhost, luser); + } + else if (!!strcmp (rversion, short_version)) + { + /* Warn that the version numbers don't match. + */ + sprintf (msg, + "Warning:\n\n" + "This is %s version %s.\n" + "But the xscreensaver managing display \"%s\"\n" + "is version %s. This could cause problems.", + progname, short_version, + d, + rversion); + } + + + if (*msg) + warning_dialog (parent, msg, 1); + + free (msg); +} + + +/* We use this error handler so that X errors are preceeded by the name + of the program that generated them. + */ +static int +demo_ehandler (Display *dpy, XErrorEvent *error) +{ + fprintf (stderr, "\nX error in %s:\n", progname); + XmuPrintDefaultErrorMessage (dpy, error, stderr); + exit (-1); + return 0; +} + + + +#ifdef __GNUC__ + __extension__ /* shut up about "string length is greater than the length + ISO C89 compilers are required to support" when including + the .ad file... */ +#endif + +static char *defaults[] = { +#include "XScreenSaver_ad.h" +#include "XScreenSaver_Xm_ad.h" + 0 +}; + + +int +main (int argc, char **argv) +{ + XtAppContext app; + prefs_pair Pair, *pair; + saver_preferences P, P2, *p, *p2; + Bool prefs = False; + int i; + Display *dpy; + Widget toplevel_shell, dialog; + char *real_progname = argv[0]; + char *s; + + s = strrchr (real_progname, '/'); + if (s) real_progname = s+1; + + p = &P; + p2 = &P2; + pair = &Pair; + pair->a = p; + pair->b = p2; + memset (p, 0, sizeof (*p)); + memset (p2, 0, sizeof (*p2)); + + global_prefs_pair = pair; + + progname = real_progname; + + /* We must read exactly the same resources as xscreensaver. + That means we must have both the same progclass *and* progname, + at least as far as the resource database is concerned. So, + put "xscreensaver" in argv[0] while initializing Xt. + */ + argv[0] = "xscreensaver"; + progname = argv[0]; + + + toplevel_shell = XtAppInitialize (&app, progclass, 0, 0, &argc, argv, + defaults, 0, 0); + + dpy = XtDisplay (toplevel_shell); + db = XtDatabase (dpy); + XtGetApplicationNameAndClass (dpy, &progname, &progclass); + XSetErrorHandler (demo_ehandler); + + /* Complain about unrecognized command-line arguments. + */ + for (i = 1; i < argc; i++) + { + char *s = argv[i]; + if (s[0] == '-' && s[1] == '-') + s++; + if (!strcmp (s, "-prefs")) + prefs = True; + else + { + fprintf (stderr, "usage: %s [ -display dpy-string ] [ -prefs ]\n", + real_progname); + exit (1); + } + } + + short_version = (char *) malloc (5); + memcpy (short_version, screensaver_id + 17, 4); + short_version [4] = 0; + + /* Load the init file, which may end up consulting the X resource database + and the site-wide app-defaults file. Note that at this point, it's + important that `progname' be "xscreensaver", rather than whatever + was in argv[0]. + */ + p->db = db; + load_init_file (dpy, p); + *p2 = *p; + + /* Now that Xt has been initialized, and the resources have been read, + we can set our `progname' variable to something more in line with + reality. + */ + progname = real_progname; + + +#if 0 + { + XrmName name = { 0 }; + XrmClass class = { 0 }; + int count = 0; + XrmEnumerateDatabase (db, &name, &class, XrmEnumAllLevels, mapper, + (POINTER) &count); + } +#endif + + + /* Intern the atoms that xscreensaver_command() needs. + */ + XA_VROOT = XInternAtom (dpy, "__SWM_VROOT", False); + XA_SCREENSAVER = XInternAtom (dpy, "SCREENSAVER", False); + XA_SCREENSAVER_VERSION = XInternAtom (dpy, "_SCREENSAVER_VERSION",False); + XA_SCREENSAVER_STATUS = XInternAtom (dpy, "_SCREENSAVER_STATUS", False); + XA_SCREENSAVER_ID = XInternAtom (dpy, "_SCREENSAVER_ID", False); + XA_SCREENSAVER_RESPONSE = XInternAtom (dpy, "_SCREENSAVER_RESPONSE", False); + XA_SELECT = XInternAtom (dpy, "SELECT", False); + XA_DEMO = XInternAtom (dpy, "DEMO", False); + XA_ACTIVATE = XInternAtom (dpy, "ACTIVATE", False); + XA_BLANK = XInternAtom (dpy, "BLANK", False); + XA_LOCK = XInternAtom (dpy, "LOCK", False); + XA_EXIT = XInternAtom (dpy, "EXIT", False); + XA_RESTART = XInternAtom (dpy, "RESTART", False); + + /* Create the window and all its widgets. + */ + dialog = create_xscreensaver_demo (toplevel_shell); + + /* Set the window's title. */ + { + char title[255]; + char *v = (char *) strdup(strchr(screensaver_id, ' ')); + char *s1, *s2, *s3, *s4; + s1 = (char *) strchr(v, ' '); s1++; + s2 = (char *) strchr(s1, ' '); + s3 = (char *) strchr(v, '('); s3++; + s4 = (char *) strchr(s3, ')'); + *s2 = 0; + *s4 = 0; + sprintf (title, "%.50s %.50s, %.50s", progclass, s1, s3); + XtVaSetValues (toplevel_shell, XtNtitle, title, NULL); + free (v); + } + + sanity_check_resources (toplevel_shell); + add_callbacks (toplevel_shell, pair); + populate_hack_list (toplevel_shell, pair); + populate_prefs_page (toplevel_shell, pair); + sensitize_demo_widgets (toplevel_shell, False); + scroll_to_current_hack (toplevel_shell, pair); + + XtManageChild (dialog); + XtRealizeWidget(toplevel_shell); + + /* The next few calls must come after XtRealizeWidget(). */ + pixmapify_buttons (toplevel_shell); + hack_button_sizes (toplevel_shell); + ensure_selected_item_visible (name_to_widget (toplevel_shell, "list")); + + XSync (dpy, False); + XtVaSetValues (toplevel_shell, XmNallowShellResize, False, NULL); + + + /* Handle the -prefs command-line argument. */ + if (prefs) + { + Widget tabber = name_to_widget (toplevel_shell, "folder"); + Widget this_tab = name_to_widget (toplevel_shell, "optionsTab"); + Widget this_page = name_to_widget (toplevel_shell, "preferencesForm"); + Widget *kids = 0; + Cardinal nkids = 0; + if (!tabber) abort(); + + XtVaGetValues (tabber, XmNnumChildren, &nkids, XmNchildren, &kids, NULL); + if (!kids) abort(); + if (nkids > 0) + XtUnmanageChildren (kids, nkids); + + XtManageChild (this_page); + + XmProcessTraversal (this_tab, XmTRAVERSE_CURRENT); + } + + /* Issue any warnings about the running xscreensaver daemon. */ + the_network_is_not_the_computer (toplevel_shell); + + + XtAppMainLoop (app); + exit (0); +} + +#endif /* HAVE_MOTIF -- whole file */ diff --git a/driver/dpms.c b/driver/dpms.c new file mode 100644 index 00000000..d88737ee --- /dev/null +++ b/driver/dpms.c @@ -0,0 +1,296 @@ +/* dpms.c --- syncing the X Display Power Management values + * xscreensaver, Copyright (c) 2001-2011 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. + */ + +/* Display Power Management System (DPMS.) + + On XFree86 systems, "man xset" reports: + + -dpms The -dpms option disables DPMS (Energy Star) features. + +dpms The +dpms option enables DPMS (Energy Star) features. + + dpms flags... + The dpms option allows the DPMS (Energy Star) + parameters to be set. The option can take up to three + numerical values, or the `force' flag followed by a + DPMS state. The `force' flags forces the server to + immediately switch to the DPMS state specified. The + DPMS state can be one of `standby', `suspend', or + `off'. When numerical values are given, they set the + inactivity period before the three modes are activated. + The first value given is for the `standby' mode, the + second is for the `suspend' mode, and the third is for + the `off' mode. Setting these values implicitly + enables the DPMS features. A value of zero disables a + particular mode. + + However, note that the implementation is more than a little bogus, + in that there is code in /usr/X11R6/lib/libXdpms.a to implement all + the usual server-extension-querying utilities -- but there are no + prototypes in any header file! Thus, the prototypes here. (The + stuff in X11/extensions/dpms.h and X11/extensions/dpmsstr.h define + the raw X protcol, they don't define the API to libXdpms.a.) + + Some documentation: + Library: ftp://ftp.x.org/pub/R6.4/xc/doc/specs/Xext/DPMSLib.ms + Protocol: ftp://ftp.x.org/pub/R6.4/xc/doc/specs/Xext/DPMS.ms + */ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include +#include + +#ifdef HAVE_DPMS_EXTENSION /* almost the whole file */ + +# include +# include +/*# include */ + + /* Why this crap is not in a header file somewhere, I have no idea. Losers! + */ + extern Bool DPMSQueryExtension (Display *, int *event_ret, int *err_ret); + extern Status DPMSGetVersion (Display *, int *major_ret, int *minor_ret); + extern Bool DPMSCapable (Display *); + extern Status DPMSInfo (Display *, CARD16 *power_level, BOOL *state); + extern Status DPMSEnable (Display *dpy); + extern Status DPMSDisable (Display *dpy); + extern Status DPMSForceLevel (Display *, CARD16 level); + extern Status DPMSSetTimeouts (Display *, CARD16 standby, CARD16 suspend, + CARD16 off); + extern Bool DPMSGetTimeouts (Display *, CARD16 *standby, + CARD16 *suspend, CARD16 *off); + +#endif /* HAVE_DPMS_EXTENSION */ + + +/* This file doesn't need the Xt headers, so stub these types out... */ +#undef XtPointer +#define XtAppContext void* +#define XrmDatabase void* +#define XtIntervalId void* +#define XtPointer void* +#define Widget void* + +#include "xscreensaver.h" + +#ifdef HAVE_DPMS_EXTENSION + +static Bool error_handler_hit_p = False; + +static int +ignore_all_errors_ehandler (Display *dpy, XErrorEvent *error) +{ + error_handler_hit_p = True; + return 0; +} + + +void +sync_server_dpms_settings (Display *dpy, Bool enabled_p, + int standby_secs, int suspend_secs, int off_secs, + Bool verbose_p) +{ + int event = 0, error = 0; + BOOL o_enabled = False; + CARD16 o_power = 0; + CARD16 o_standby = 0, o_suspend = 0, o_off = 0; + Bool bogus_p = False; + + if (standby_secs == 0 && suspend_secs == 0 && off_secs == 0) + /* all zero implies "DPMS disabled" */ + enabled_p = False; + + else if ((standby_secs != 0 && standby_secs < 10) || + (suspend_secs != 0 && suspend_secs < 10) || + (off_secs != 0 && off_secs < 10)) + /* any negative, or any positive-and-less-than-10-seconds, is crazy. */ + bogus_p = True; + + if (bogus_p) enabled_p = False; + + /* X protocol sends these values in a CARD16, so truncate them to 16 bits. + This means that the maximum timeout is 18:12:15. + */ + if (standby_secs > 0xFFFF) standby_secs = 0xFFFF; + if (suspend_secs > 0xFFFF) suspend_secs = 0xFFFF; + if (off_secs > 0xFFFF) off_secs = 0xFFFF; + + if (! DPMSQueryExtension (dpy, &event, &error)) + { + if (verbose_p) + fprintf (stderr, "%s: XDPMS extension not supported.\n", blurb()); + return; + } + + if (! DPMSCapable (dpy)) + { + if (verbose_p) + fprintf (stderr, "%s: DPMS not supported.\n", blurb()); + return; + } + + if (! DPMSInfo (dpy, &o_power, &o_enabled)) + { + if (verbose_p) + fprintf (stderr, "%s: unable to get DPMS state.\n", blurb()); + return; + } + + if (o_enabled != enabled_p) + { + if (! (enabled_p ? DPMSEnable (dpy) : DPMSDisable (dpy))) + { + if (verbose_p) + fprintf (stderr, "%s: unable to set DPMS state.\n", blurb()); + return; + } + else if (verbose_p) + fprintf (stderr, "%s: turned DPMS %s.\n", blurb(), + enabled_p ? "on" : "off"); + } + + if (bogus_p) + { + if (verbose_p) + fprintf (stderr, "%s: not setting bogus DPMS timeouts: %d %d %d.\n", + blurb(), standby_secs, suspend_secs, off_secs); + return; + } + + if (!DPMSGetTimeouts (dpy, &o_standby, &o_suspend, &o_off)) + { + if (verbose_p) + fprintf (stderr, "%s: unable to get DPMS timeouts.\n", blurb()); + return; + } + + if (o_standby != standby_secs || + o_suspend != suspend_secs || + o_off != off_secs) + { + if (!DPMSSetTimeouts (dpy, standby_secs, suspend_secs, off_secs)) + { + if (verbose_p) + fprintf (stderr, "%s: unable to set DPMS timeouts.\n", blurb()); + return; + } + else if (verbose_p) + fprintf (stderr, "%s: set DPMS timeouts: %d %d %d.\n", blurb(), + standby_secs, suspend_secs, off_secs); + } +} + +Bool +monitor_powered_on_p (saver_info *si) +{ + Bool result; + int event_number, error_number; + BOOL onoff = False; + CARD16 state; + + if (!DPMSQueryExtension(si->dpy, &event_number, &error_number)) + /* Server doesn't know -- assume the monitor is on. */ + result = True; + + else if (!DPMSCapable(si->dpy)) + /* Server says the monitor doesn't do power management -- so it's on. */ + result = True; + + else + { + DPMSInfo(si->dpy, &state, &onoff); + if (!onoff) + /* Server says DPMS is disabled -- so the monitor is on. */ + result = True; + else + switch (state) { + case DPMSModeOn: result = True; break; /* really on */ + case DPMSModeStandby: result = False; break; /* kinda off */ + case DPMSModeSuspend: result = False; break; /* pretty off */ + case DPMSModeOff: result = False; break; /* really off */ + default: result = True; break; /* protocol error? */ + } + } + + return result; +} + +void +monitor_power_on (saver_info *si, Bool on_p) +{ + if ((!!on_p) != monitor_powered_on_p (si)) + { + XErrorHandler old_handler; + int event_number, error_number; + if (!DPMSQueryExtension(si->dpy, &event_number, &error_number) || + !DPMSCapable(si->dpy)) + { + if (si->prefs.verbose_p) + fprintf (stderr, + "%s: unable to power %s monitor: no DPMS extension.\n", + blurb(), (on_p ? "on" : "off")); + return; + } + + /* The manual for DPMSForceLevel() says that it throws BadMatch if + "DPMS is disabled on the specified display." + + The manual for DPMSCapable() says that it "returns True if the X + server is capable of DPMS." + + Apparently they consider "capable of DPMS" and "DPMS is enabled" + to be different things, and so even if DPMSCapable() returns + True, DPMSForceLevel() *might* throw an X Error. Isn't that + just fucking special. + */ + XSync (si->dpy, False); + error_handler_hit_p = False; + old_handler = XSetErrorHandler (ignore_all_errors_ehandler); + XSync (si->dpy, False); + DPMSForceLevel(si->dpy, (on_p ? DPMSModeOn : DPMSModeOff)); + XSync (si->dpy, False); + /* Ignore error_handler_hit_p, just probe monitor instead */ + + if ((!!on_p) != monitor_powered_on_p (si)) /* double-check */ + fprintf (stderr, + "%s: DPMSForceLevel(dpy, %s) did not change monitor power state.\n", + blurb(), + (on_p ? "DPMSModeOn" : "DPMSModeOff")); + } +} + +#else /* !HAVE_DPMS_EXTENSION */ + +void +sync_server_dpms_settings (Display *dpy, Bool enabled_p, + int standby_secs, int suspend_secs, int off_secs, + Bool verbose_p) +{ + if (verbose_p) + fprintf (stderr, "%s: DPMS support not compiled in.\n", blurb()); +} + +Bool +monitor_powered_on_p (saver_info *si) +{ + return True; +} + +void +monitor_power_on (saver_info *si, Bool on_p) +{ + return; +} + +#endif /* !HAVE_DPMS_EXTENSION */ diff --git a/driver/exec.c b/driver/exec.c new file mode 100644 index 00000000..5da53a01 --- /dev/null +++ b/driver/exec.c @@ -0,0 +1,299 @@ +/* exec.c --- executes a program in *this* pid, without an intervening process. + * xscreensaver, Copyright (c) 1991-2008 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. + */ + + +/* I don't believe what a sorry excuse for an operating system UNIX is! + + - I want to spawn a process. + - I want to know it's pid so that I can kill it. + - I would like to receive a message when it dies of natural causes. + - I want the spawned process to have user-specified arguments. + + If shell metacharacters are present (wildcards, backquotes, etc), the + only way to parse those arguments is to run a shell to do the parsing + for you. + + And the only way to know the pid of the process is to fork() and exec() + it in the spawned side of the fork. + + But if you're running a shell to parse your arguments, this gives you + the pid of the *shell*, not the pid of the *process* that you're + actually interested in, which is an *inferior* of the shell. This also + means that the SIGCHLD you get applies to the shell, not its inferior. + (Why isn't that sufficient? I don't remember any more, but it turns + out that it isn't.) + + So, the only solution, when metacharacters are present, is to force the + shell to exec() its inferior. What a fucking hack! We prepend "exec " + to the command string, and hope it doesn't contain unquoted semicolons + or ampersands (we don't search for them, because we don't want to + prohibit their use in quoted strings (messages, for example) and parsing + out the various quote characters is too much of a pain.) + + (Actually, Clint Wong points out that process groups + might be used to take care of this problem; this may be worth considering + some day, except that, 1: this code works now, so why fix it, and 2: from + what I've seen in Emacs, dealing with process groups isn't especially + portable.) + */ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include +#ifdef HAVE_UNISTD_H +# include +#endif + +#include +#include +#include +#include + +#ifndef ESRCH +# include +#endif + +#if defined(HAVE_SETPRIORITY) && defined(PRIO_PROCESS) +# include /* for setpriority() and PRIO_PROCESS */ + /* and also setrlimit() and RLIMIT_AS */ +#endif + +#ifdef VMS +# include +# include /* for close */ +# include /* for getpid */ +# define pid_t int +# define fork vfork +#endif /* VMS */ + +#include "exec.h" + +extern const char *blurb (void); + +static void nice_process (int nice_level); + + +#ifndef VMS + +static void +exec_simple_command (const char *command) +{ + char *av[1024]; + int ac = 0; + char *token = strtok (strdup(command), " \t"); + while (token) + { + av[ac++] = token; + token = strtok(0, " \t"); + } + av[ac] = 0; + + execvp (av[0], av); /* shouldn't return. */ +} + + +static void +exec_complex_command (const char *shell, const char *command) +{ + char *av[5]; + int ac = 0; + char *command2 = (char *) malloc (strlen (command) + 10); + const char *s; + int got_eq = 0; + const char *after_vars; + + /* Skip leading whitespace. + */ + while (*command == ' ' || *command == '\t') + command++; + + /* If the string has a series of tokens with "=" in them at them, set + `after_vars' to point into the string after those tokens and any + trailing whitespace. Otherwise, after_vars == command. + */ + after_vars = command; + for (s = command; *s; s++) + { + if (*s == '=') got_eq = 1; + else if (*s == ' ') + { + if (got_eq) + { + while (*s == ' ' || *s == '\t') + s++; + after_vars = s; + got_eq = 0; + } + else + break; + } + } + + *command2 = 0; + strncat (command2, command, after_vars - command); + strcat (command2, "exec "); + strcat (command2, after_vars); + + /* We have now done these transformations: + "foo -x -y" ==> "exec foo -x -y" + "BLAT=foop foo -x" ==> "BLAT=foop exec foo -x" + "BLAT=foop A=b foo -x" ==> "BLAT=foop A=b exec foo -x" + */ + + + /* Invoke the shell as "/bin/sh -c 'exec prog -arg -arg ...'" */ + av [ac++] = (char *) shell; + av [ac++] = "-c"; + av [ac++] = command2; + av [ac] = 0; + + execvp (av[0], av); /* shouldn't return. */ +} + +#else /* VMS */ + +static void +exec_vms_command (const char *command) +{ + system (command); + fflush (stderr); + fflush (stdout); + exit (1); /* Note that this only exits a child fork. */ +} + +#endif /* !VMS */ + + +void +exec_command (const char *shell, const char *command, int nice_level) +{ + int hairy_p; + +#ifndef VMS + nice_process (nice_level); + + hairy_p = !!strpbrk (command, "*?$&!<>[];`'\\\"="); + /* note: = is in the above because of the sh syntax "FOO=bar cmd". */ + + if (getuid() == (uid_t) 0 || geteuid() == (uid_t) 0) + { + /* If you're thinking of commenting this out, think again. + If you do so, you will open a security hole. Mail jwz + so that he may enlighten you as to the error of your ways. + */ + fprintf (stderr, "%s: we're still running as root! Disaster!\n", + blurb()); + exit (-1); + } + + if (hairy_p) + /* If it contains any shell metacharacters, do it the hard way, + and fork a shell to parse the arguments for us. */ + exec_complex_command (shell, command); + else + /* Otherwise, we can just exec the program directly. */ + exec_simple_command (command); + +#else /* VMS */ + exec_vms_command (command); +#endif /* VMS */ +} + + +/* Setting process priority + */ + +static void +nice_process (int nice_level) +{ + if (nice_level == 0) + return; + +#if defined(HAVE_NICE) + { + int old_nice = nice (0); + int n = nice_level - old_nice; + errno = 0; + if (nice (n) == -1 && errno != 0) + { + char buf [512]; + sprintf (buf, "%s: nice(%d) failed", blurb(), n); + perror (buf); + } + } +#elif defined(HAVE_SETPRIORITY) && defined(PRIO_PROCESS) + if (setpriority (PRIO_PROCESS, getpid(), nice_level) != 0) + { + char buf [512]; + sprintf (buf, "%s: setpriority(PRIO_PROCESS, %lu, %d) failed", + blurb(), (unsigned long) getpid(), nice_level); + perror (buf); + } +#else + fprintf (stderr, + "%s: don't know how to change process priority on this system.\n", + blurb()); + +#endif +} + + +/* Whether the given command exists on $PATH. + (Anything before the first space is considered to be the program name.) + */ +int +on_path_p (const char *program) +{ + int result = 0; + struct stat st; + char *cmd = strdup (program); + char *token = strchr (cmd, ' '); + char *path = 0; + int L; + + if (token) *token = 0; + token = 0; + + if (strchr (cmd, '/')) + { + result = (0 == stat (cmd, &st)); + goto DONE; + } + + path = getenv("PATH"); + if (!path || !*path) + goto DONE; + + L = strlen (cmd); + path = strdup (path); + token = strtok (path, ":"); + + while (token) + { + char *p2 = (char *) malloc (strlen (token) + L + 3); + strcpy (p2, token); + strcat (p2, "/"); + strcat (p2, cmd); + result = (0 == stat (p2, &st)); + if (result) + goto DONE; + token = strtok (0, ":"); + } + + DONE: + free (cmd); + if (path) free (path); + return result; +} + diff --git a/driver/exec.h b/driver/exec.h new file mode 100644 index 00000000..318410b8 --- /dev/null +++ b/driver/exec.h @@ -0,0 +1,21 @@ +/* exec.c --- executes a program in *this* pid, without an intervening process. + * xscreensaver, Copyright (c) 1991-2006 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. + */ + +#ifndef __XSCREENSAVER_EXEC_H__ +#define __XSCREENSAVER_EXEC_H__ + +extern void exec_command (const char *shell, const char *command, + int nice_level); + +extern int on_path_p (const char *program); + +#endif /* __XSCREENSAVER_EXEC_H__ */ diff --git a/driver/link_axp.com b/driver/link_axp.com new file mode 100644 index 00000000..a1418927 --- /dev/null +++ b/driver/link_axp.com @@ -0,0 +1,15 @@ +$! We fisrt test the version of DECW/Motif ; if 1.2 we need to link with new +$! X11R5 libraries +$@sys$update:decw$get_image_version sys$share:decw$xlibshr.exe decw$version +$ if f$extract(4,3,decw$version).eqs."1.2" +$ then +$! DECW/Motif 1.2 : link with X11R5 libraries +$ link xscreensaver-command,vms_axp_12.opt/opt +$ link xscreensaver,demo,dialogs-xm,lock,passwd,stderr,subprocs,timers, - + windows,xset,vms-getpwnam,vms-hpwd,vms-validate,vms_axp_12.opt/opt +$ else +$! Else, link with X11R4 libraries +$ link xscreensaver-command,vms_axp.opt/opt +$ link xscreensaver,demo,dialogs-xm,lock,passwd,stderr,subprocs,timers, - + windows,xset,vms-getpwnam,vms-hpwd,vms-validate,vms_axp.opt/opt +$ endif diff --git a/driver/link_decc.com b/driver/link_decc.com new file mode 100644 index 00000000..d1de0d0a --- /dev/null +++ b/driver/link_decc.com @@ -0,0 +1,15 @@ +$! We fisrt test the version of DECW/Motif ; if 1.2 we need to link with new +$! X11R5 libraries +$@sys$update:decw$get_image_version sys$share:decw$xlibshr.exe decw$version +$ if f$extract(4,3,decw$version).eqs."1.2" +$ then +$! DECW/Motif 1.2 : link with X11R5 libraries +$ link xscreensaver-command,vms_decc_12.opt/opt +$ link xscreensaver,demo,dialogs-xm,lock,passwd,stderr,subprocs,timers, - + windows,xset,vms-getpwnam,vms-hpwd,vms-validate,vms_decc_12.opt/opt +$ else +$! Else, link with X11R4 libraries +$ link xscreensaver-command,vms_decc.opt/opt +$ link xscreensaver,demo,dialogs-xm,lock,passwd,stderr,subprocs,timers, - + windows,xset,vms-getpwnam,vms-hpwd,vms-validate,vms_decc.opt/opt +$ endif diff --git a/driver/lock.c b/driver/lock.c new file mode 100644 index 00000000..296bcd02 --- /dev/null +++ b/driver/lock.c @@ -0,0 +1,2263 @@ +/* lock.c --- handling the password dialog for locking-mode. + * xscreensaver, Copyright (c) 1993-2011 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. + */ + +/* Athena locking code contributed by Jon A. Christopher */ +/* Copyright 1997, with the same permissions as above. */ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include +#include +#include +#include /* for time() */ +#include +#include +#include "xscreensaver.h" +#include "resources.h" +#include "mlstring.h" +#include "auth.h" + +#ifndef NO_LOCKING /* (mostly) whole file */ + +#ifdef HAVE_XHPDISABLERESET +# include + static void hp_lock_reset (saver_info *si, Bool lock_p); +#endif /* HAVE_XHPDISABLERESET */ + +#ifdef HAVE_XF86VMODE +# include + static void xfree_lock_mode_switch (saver_info *si, Bool lock_p); +#endif /* HAVE_XF86VMODE */ + +#ifdef HAVE_XF86MISCSETGRABKEYSSTATE +# include + static void xfree_lock_grab_smasher (saver_info *si, Bool lock_p); +#endif /* HAVE_XF86MISCSETGRABKEYSSTATE */ + +#ifdef HAVE_RANDR +# include +#endif /* HAVE_RANDR */ + +#ifdef _VROOT_H_ +ERROR! You must not include vroot.h in this file. +#endif + +#ifdef HAVE_UNAME +# include /* for hostname info */ +#endif /* HAVE_UNAME */ +#include + +#ifndef VMS +# include +#else /* VMS */ + +extern char *getenv(const char *name); +extern int validate_user(char *name, char *password); + +static Bool +vms_passwd_valid_p(char *pw, Bool verbose_p) +{ + return (validate_user (getenv("USER"), typed_passwd) == 1); +} +# undef passwd_valid_p +# define passwd_valid_p vms_passwd_valid_p + +#endif /* VMS */ + +#define SAMPLE_INPUT "MMMMMMMMMMMM" + + +#undef MAX +#define MAX(a,b) ((a)>(b)?(a):(b)) + +typedef struct info_dialog_data info_dialog_data; + + +#define MAX_BYTES_PER_CHAR 8 /* UTF-8 uses no more than 3, I think */ +#define MAX_PASSWD_CHARS 128 /* Longest possible passphrase */ + +struct passwd_dialog_data { + + saver_screen_info *prompt_screen; + int previous_mouse_x, previous_mouse_y; + + /* "Characters" in the password may be a variable number of bytes long. + typed_passwd contains the raw bytes. + typed_passwd_char_size indicates the size in bytes of each character, + so that we can make backspace work. + */ + char typed_passwd [MAX_PASSWD_CHARS * MAX_BYTES_PER_CHAR]; + char typed_passwd_char_size [MAX_PASSWD_CHARS]; + + XtIntervalId timer; + int i_beam; + + float ratio; + Position x, y; + Dimension width; + Dimension height; + Dimension border_width; + + Bool echo_input; + Bool show_stars_p; /* "I regret that I have but one asterisk for my country." + -- Nathan Hale, 1776. */ + + char *heading_label; + char *body_label; + char *user_label; + mlstring *info_label; + /* The entry field shall only be displayed if prompt_label is not NULL */ + mlstring *prompt_label; + char *date_label; + char *passwd_string; + Bool passwd_changed_p; /* Whether the user entry field needs redrawing */ + Bool caps_p; /* Whether we saw a keypress with caps-lock on */ + char *unlock_label; + char *login_label; + char *uname_label; + + Bool show_uname_p; + + XFontStruct *heading_font; + XFontStruct *body_font; + XFontStruct *label_font; + XFontStruct *passwd_font; + XFontStruct *date_font; + XFontStruct *button_font; + XFontStruct *uname_font; + + Pixel foreground; + Pixel background; + Pixel border; + Pixel passwd_foreground; + Pixel passwd_background; + Pixel thermo_foreground; + Pixel thermo_background; + Pixel shadow_top; + Pixel shadow_bottom; + Pixel button_foreground; + Pixel button_background; + + Dimension preferred_logo_width, logo_width; + Dimension preferred_logo_height, logo_height; + Dimension thermo_width; + Dimension internal_border; + Dimension shadow_width; + + Dimension passwd_field_x, passwd_field_y; + Dimension passwd_field_width, passwd_field_height; + + Dimension unlock_button_x, unlock_button_y; + Dimension unlock_button_width, unlock_button_height; + + Dimension login_button_x, login_button_y; + Dimension login_button_width, login_button_height; + + Dimension thermo_field_x, thermo_field_y; + Dimension thermo_field_height; + + Pixmap logo_pixmap; + Pixmap logo_clipmask; + int logo_npixels; + unsigned long *logo_pixels; + + Cursor passwd_cursor; + Bool unlock_button_down_p; + Bool login_button_down_p; + Bool login_button_p; + Bool login_button_enabled_p; + Bool button_state_changed_p; /* Refers to both buttons */ + + Pixmap save_under; + Pixmap user_entry_pixmap; +}; + +static void draw_passwd_window (saver_info *si); +static void update_passwd_window (saver_info *si, const char *printed_passwd, + float ratio); +static void destroy_passwd_window (saver_info *si); +static void undo_vp_motion (saver_info *si); +static void finished_typing_passwd (saver_info *si, passwd_dialog_data *pw); +static void cleanup_passwd_window (saver_info *si); +static void restore_background (saver_info *si); + +extern void xss_authenticate(saver_info *si, Bool verbose_p); + +static int +new_passwd_window (saver_info *si) +{ + passwd_dialog_data *pw; + Screen *screen; + Colormap cmap; + char *f; + saver_screen_info *ssi = &si->screens [mouse_screen (si)]; + + pw = (passwd_dialog_data *) calloc (1, sizeof(*pw)); + if (!pw) + return -1; + + /* Display the button only if the "newLoginCommand" pref is non-null. + */ + pw->login_button_p = (si->prefs.new_login_command && + *si->prefs.new_login_command); + + pw->passwd_cursor = XCreateFontCursor (si->dpy, XC_top_left_arrow); + + pw->prompt_screen = ssi; + + screen = pw->prompt_screen->screen; + cmap = DefaultColormapOfScreen (screen); + + pw->show_stars_p = get_boolean_resource(si->dpy, "passwd.asterisks", + "Boolean"); + + pw->heading_label = get_string_resource (si->dpy, "passwd.heading.label", + "Dialog.Label.Label"); + pw->body_label = get_string_resource (si->dpy, "passwd.body.label", + "Dialog.Label.Label"); + pw->user_label = get_string_resource (si->dpy, "passwd.user.label", + "Dialog.Label.Label"); + pw->unlock_label = get_string_resource (si->dpy, "passwd.unlock.label", + "Dialog.Button.Label"); + pw->login_label = get_string_resource (si->dpy, "passwd.login.label", + "Dialog.Button.Label"); + + pw->date_label = get_string_resource (si->dpy, "dateFormat", "DateFormat"); + + if (!pw->heading_label) + pw->heading_label = strdup("ERROR: RESOURCES NOT INSTALLED CORRECTLY"); + if (!pw->body_label) + pw->body_label = strdup("ERROR: RESOURCES NOT INSTALLED CORRECTLY"); + if (!pw->user_label) pw->user_label = strdup("ERROR"); + if (!pw->date_label) pw->date_label = strdup("ERROR"); + if (!pw->unlock_label) pw->unlock_label = strdup("ERROR (UNLOCK)"); + if (!pw->login_label) pw->login_label = strdup ("ERROR (LOGIN)") ; + + /* Put the version number in the label. */ + { + char *s = (char *) malloc (strlen(pw->heading_label) + 20); + sprintf(s, pw->heading_label, si->version); + free (pw->heading_label); + pw->heading_label = s; + } + + /* Get hostname info */ + pw->uname_label = strdup(""); /* Initialy, write nothing */ + +# ifdef HAVE_UNAME + { + struct utsname uts; + + if (uname (&uts) == 0) + { +#if 0 /* Get the full hostname */ + { + char *s; + if ((s = strchr(uts.nodename, '.'))) + *s = 0; + } +#endif + char *s = strdup (uts.nodename); + free (pw->uname_label); + pw->uname_label = s; + } + } +# endif + + pw->passwd_string = strdup(""); + + f = get_string_resource (si->dpy, "passwd.headingFont", "Dialog.Font"); + pw->heading_font = XLoadQueryFont (si->dpy, (f ? f : "fixed")); + if (!pw->heading_font) pw->heading_font = XLoadQueryFont (si->dpy, "fixed"); + if (f) free (f); + + f = get_string_resource (si->dpy, "passwd.buttonFont", "Dialog.Font"); + pw->button_font = XLoadQueryFont (si->dpy, (f ? f : "fixed")); + if (!pw->button_font) pw->button_font = XLoadQueryFont (si->dpy, "fixed"); + if (f) free (f); + + f = get_string_resource(si->dpy, "passwd.bodyFont", "Dialog.Font"); + pw->body_font = XLoadQueryFont (si->dpy, (f ? f : "fixed")); + if (!pw->body_font) pw->body_font = XLoadQueryFont (si->dpy, "fixed"); + if (f) free (f); + + f = get_string_resource(si->dpy, "passwd.labelFont", "Dialog.Font"); + pw->label_font = XLoadQueryFont (si->dpy, (f ? f : "fixed")); + if (!pw->label_font) pw->label_font = XLoadQueryFont (si->dpy, "fixed"); + if (f) free (f); + + f = get_string_resource(si->dpy, "passwd.passwdFont", "Dialog.Font"); + pw->passwd_font = XLoadQueryFont (si->dpy, (f ? f : "fixed")); + if (!pw->passwd_font) pw->passwd_font = XLoadQueryFont (si->dpy, "fixed"); + if (f) free (f); + + f = get_string_resource(si->dpy, "passwd.dateFont", "Dialog.Font"); + pw->date_font = XLoadQueryFont (si->dpy, (f ? f : "fixed")); + if (!pw->date_font) pw->date_font = XLoadQueryFont (si->dpy, "fixed"); + if (f) free (f); + + f = get_string_resource(si->dpy, "passwd.unameFont", "Dialog.Font"); + pw->uname_font = XLoadQueryFont (si->dpy, (f ? f : "fixed")); + if (!pw->uname_font) pw->uname_font = XLoadQueryFont (si->dpy, "fixed"); + if (f) free (f); + + pw->show_uname_p = get_boolean_resource(si->dpy, "passwd.uname", "Boolean"); + + pw->foreground = get_pixel_resource (si->dpy, cmap, + "passwd.foreground", + "Dialog.Foreground" ); + pw->background = get_pixel_resource (si->dpy, cmap, + "passwd.background", + "Dialog.Background" ); + pw->border = get_pixel_resource (si->dpy, cmap, + "passwd.borderColor", + "Dialog.borderColor"); + + if (pw->foreground == pw->background) + { + /* Make sure the error messages show up. */ + pw->foreground = BlackPixelOfScreen (screen); + pw->background = WhitePixelOfScreen (screen); + } + + pw->passwd_foreground = get_pixel_resource (si->dpy, cmap, + "passwd.text.foreground", + "Dialog.Text.Foreground" ); + pw->passwd_background = get_pixel_resource (si->dpy, cmap, + "passwd.text.background", + "Dialog.Text.Background" ); + pw->button_foreground = get_pixel_resource (si->dpy, cmap, + "splash.Button.foreground", + "Dialog.Button.Foreground" ); + pw->button_background = get_pixel_resource (si->dpy, cmap, + "splash.Button.background", + "Dialog.Button.Background" ); + pw->thermo_foreground = get_pixel_resource (si->dpy, cmap, + "passwd.thermometer.foreground", + "Dialog.Thermometer.Foreground"); + pw->thermo_background = get_pixel_resource ( si->dpy, cmap, + "passwd.thermometer.background", + "Dialog.Thermometer.Background"); + pw->shadow_top = get_pixel_resource ( si->dpy, cmap, + "passwd.topShadowColor", + "Dialog.Foreground" ); + pw->shadow_bottom = get_pixel_resource (si->dpy, cmap, + "passwd.bottomShadowColor", + "Dialog.Background" ); + + pw->preferred_logo_width = get_integer_resource (si->dpy, + "passwd.logo.width", + "Dialog.Logo.Width"); + pw->preferred_logo_height = get_integer_resource (si->dpy, + "passwd.logo.height", + "Dialog.Logo.Height"); + pw->thermo_width = get_integer_resource (si->dpy, "passwd.thermometer.width", + "Dialog.Thermometer.Width"); + pw->internal_border = get_integer_resource (si->dpy, + "passwd.internalBorderWidth", + "Dialog.InternalBorderWidth"); + pw->shadow_width = get_integer_resource (si->dpy, "passwd.shadowThickness", + "Dialog.ShadowThickness"); + + if (pw->preferred_logo_width == 0) pw->preferred_logo_width = 150; + if (pw->preferred_logo_height == 0) pw->preferred_logo_height = 150; + if (pw->internal_border == 0) pw->internal_border = 15; + if (pw->shadow_width == 0) pw->shadow_width = 4; + if (pw->thermo_width == 0) pw->thermo_width = pw->shadow_width; + + + /* We need to remember the mouse position and restore it afterward, or + sometimes (perhaps only with Xinerama?) the mouse gets warped to + inside the bounds of the lock dialog window. + */ + { + Window pointer_root, pointer_child; + int root_x, root_y, win_x, win_y; + unsigned int mask; + pw->previous_mouse_x = 0; + pw->previous_mouse_y = 0; + if (XQueryPointer (si->dpy, RootWindowOfScreen (pw->prompt_screen->screen), + &pointer_root, &pointer_child, + &root_x, &root_y, &win_x, &win_y, &mask)) + { + pw->previous_mouse_x = root_x; + pw->previous_mouse_y = root_y; + if (si->prefs.verbose_p) + fprintf (stderr, "%s: %d: mouse is at %d,%d.\n", + blurb(), pw->prompt_screen->number, + pw->previous_mouse_x, pw->previous_mouse_y); + } + else if (si->prefs.verbose_p) + fprintf (stderr, "%s: %d: unable to determine mouse position?\n", + blurb(), pw->prompt_screen->number); + } + + /* Before mapping the window, save a pixmap of the current screen. + When we lower the window, we restore these bits. This works, + because the running screenhack has already been sent SIGSTOP, so + we know nothing else is drawing right now! */ + { + XGCValues gcv; + GC gc; + pw->save_under = XCreatePixmap (si->dpy, + pw->prompt_screen->screensaver_window, + pw->prompt_screen->width, + pw->prompt_screen->height, + pw->prompt_screen->current_depth); + gcv.function = GXcopy; + gc = XCreateGC (si->dpy, pw->save_under, GCFunction, &gcv); + XCopyArea (si->dpy, pw->prompt_screen->screensaver_window, + pw->save_under, gc, + 0, 0, + pw->prompt_screen->width, pw->prompt_screen->height, + 0, 0); + XFreeGC (si->dpy, gc); + } + + si->pw_data = pw; + return 0; +} + + +Bool debug_passwd_window_p = False; /* used only by test-passwd.c */ + + +/** + * info_msg and prompt may be NULL. + */ +static int +make_passwd_window (saver_info *si, + const char *info_msg, + const char *prompt, + Bool echo) +{ + XSetWindowAttributes attrs; + unsigned long attrmask = 0; + passwd_dialog_data *pw; + Screen *screen; + Colormap cmap; + Dimension max_string_width_px; + saver_screen_info *ssi = &si->screens [mouse_screen (si)]; + + cleanup_passwd_window (si); + + if (! ssi) /* WTF? Trying to prompt while no screens connected? */ + return -1; + + if (!si->pw_data) + if (new_passwd_window (si) < 0) + return -1; + + if (!(pw = si->pw_data)) + return -1; + + pw->ratio = 1.0; + + pw->prompt_screen = ssi; + if (si->prefs.verbose_p) + fprintf (stderr, "%s: %d: creating password dialog (\"%s\")\n", + blurb(), pw->prompt_screen->number, + info_msg ? info_msg : ""); + + screen = pw->prompt_screen->screen; + cmap = DefaultColormapOfScreen (screen); + + pw->echo_input = echo; + + max_string_width_px = ssi->width + - pw->shadow_width * 4 + - pw->border_width * 2 + - pw->thermo_width + - pw->preferred_logo_width + - pw->internal_border * 2; + /* As the string wraps it makes the window taller which makes the logo wider + * which leaves less room for the text which makes the string wrap. Uh-oh, a + * loop. By wrapping at a bit less than the available width, there's some + * room for the dialog to grow without going off the edge of the screen. */ + max_string_width_px *= 0.75; + + pw->info_label = mlstring_new(info_msg ? info_msg : pw->body_label, + pw->label_font, max_string_width_px); + + { + int direction, ascent, descent; + XCharStruct overall; + + pw->width = 0; + pw->height = 0; + + /* Measure the heading_label. */ + XTextExtents (pw->heading_font, + pw->heading_label, strlen(pw->heading_label), + &direction, &ascent, &descent, &overall); + if (overall.width > pw->width) pw->width = overall.width; + pw->height += ascent + descent; + + /* Measure the uname_label. */ + if ((strlen(pw->uname_label)) && pw->show_uname_p) + { + XTextExtents (pw->uname_font, + pw->uname_label, strlen(pw->uname_label), + &direction, &ascent, &descent, &overall); + if (overall.width > pw->width) pw->width = overall.width; + pw->height += ascent + descent; + } + + { + Dimension w2 = 0, w3 = 0, button_w = 0; + Dimension h2 = 0, h3 = 0, button_h = 0; + const char *passwd_string = SAMPLE_INPUT; + + /* Measure the user_label. */ + XTextExtents (pw->label_font, + pw->user_label, strlen(pw->user_label), + &direction, &ascent, &descent, &overall); + if (overall.width > w2) w2 = overall.width; + h2 += ascent + descent; + + /* Measure the info_label. */ + if (pw->info_label->overall_width > pw->width) + pw->width = pw->info_label->overall_width; + h2 += pw->info_label->overall_height; + + /* Measure the user string. */ + XTextExtents (pw->passwd_font, + si->user, strlen(si->user), + &direction, &ascent, &descent, &overall); + overall.width += (pw->shadow_width * 4); + ascent += (pw->shadow_width * 4); + if (overall.width > w3) w3 = overall.width; + h3 += ascent + descent; + + /* Measure the (dummy) passwd_string. */ + if (prompt) + { + XTextExtents (pw->passwd_font, + passwd_string, strlen(passwd_string), + &direction, &ascent, &descent, &overall); + overall.width += (pw->shadow_width * 4); + ascent += (pw->shadow_width * 4); + if (overall.width > w3) w3 = overall.width; + h3 += ascent + descent; + + /* Measure the prompt_label. */ + max_string_width_px -= w3; + pw->prompt_label = mlstring_new (prompt, pw->label_font, + max_string_width_px); + + if (pw->prompt_label->overall_width > w2) + w2 = pw->prompt_label->overall_width; + + h2 += pw->prompt_label->overall_height; + + w2 = w2 + w3 + (pw->shadow_width * 2); + h2 = MAX (h2, h3); + } + + /* The "Unlock" button. */ + XTextExtents (pw->label_font, + pw->unlock_label, strlen(pw->unlock_label), + &direction, &ascent, &descent, &overall); + button_w = overall.width; + button_h = ascent + descent; + + /* Add some horizontal padding inside the button. */ + button_w += ascent; + + button_w += ((ascent + descent) / 2) + (pw->shadow_width * 2); + button_h += ((ascent + descent) / 2) + (pw->shadow_width * 2); + + pw->unlock_button_width = button_w; + pw->unlock_button_height = button_h; + + w2 = MAX (w2, button_w); + h2 += button_h * 1.5; + + /* The "New Login" button */ + pw->login_button_width = 0; + pw->login_button_height = 0; + + if (pw->login_button_p) + { + pw->login_button_enabled_p = True; + + /* Measure the "New Login" button */ + XTextExtents (pw->button_font, pw->login_label, + strlen (pw->login_label), + &direction, &ascent, &descent, &overall); + button_w = overall.width; + button_h = ascent + descent; + + /* Add some horizontal padding inside the buttons. */ + button_w += ascent; + + button_w += ((ascent + descent) / 2) + (pw->shadow_width * 2); + button_h += ((ascent + descent) / 2) + (pw->shadow_width * 2); + + pw->login_button_width = button_w; + pw->login_button_height = button_h; + + if (button_h > pw->unlock_button_height) + h2 += (button_h * 1.5 - pw->unlock_button_height * 1.5); + + /* Use (2 * shadow_width) spacing between the buttons. Another + (2 * shadow_width) is required to account for button shadows. */ + w2 = MAX (w2, + button_w + pw->unlock_button_width + + (pw->shadow_width * 4)); + } + + if (w2 > pw->width) pw->width = w2; + pw->height += h2; + } + + pw->width += (pw->internal_border * 2); + pw->height += (pw->internal_border * 4); + + pw->width += pw->thermo_width + (pw->shadow_width * 3); + + if (pw->preferred_logo_height > pw->height) + pw->height = pw->logo_height = pw->preferred_logo_height; + else if (pw->height > pw->preferred_logo_height) + pw->logo_height = pw->height; + + pw->logo_width = pw->logo_height; + + pw->width += pw->logo_width; + } + + attrmask |= CWOverrideRedirect; attrs.override_redirect = True; + + if (debug_passwd_window_p) + attrs.override_redirect = False; /* kludge for test-passwd.c */ + + attrmask |= CWEventMask; + attrs.event_mask = (ExposureMask | KeyPressMask | + ButtonPressMask | ButtonReleaseMask); + + /* Figure out where on the desktop to place the window so that it will + actually be visible; this takes into account virtual viewports as + well as Xinerama. */ + { + saver_screen_info *ssi = &si->screens [mouse_screen (si)]; + int x = ssi->x; + int y = ssi->y; + int w = ssi->width; + int h = ssi->height; + if (si->prefs.debug_p) w /= 2; + pw->x = x + ((w + pw->width) / 2) - pw->width; + pw->y = y + ((h + pw->height) / 2) - pw->height; + if (pw->x < x) pw->x = x; + if (pw->y < y) pw->y = y; + } + + pw->border_width = get_integer_resource (si->dpy, "passwd.borderWidth", + "Dialog.BorderWidth"); + + /* Only create the window the first time around */ + if (!si->passwd_dialog) + { + si->passwd_dialog = + XCreateWindow (si->dpy, + RootWindowOfScreen(screen), + pw->x, pw->y, pw->width, pw->height, pw->border_width, + DefaultDepthOfScreen (screen), InputOutput, + DefaultVisualOfScreen(screen), + attrmask, &attrs); + XSetWindowBackground (si->dpy, si->passwd_dialog, pw->background); + XSetWindowBorder (si->dpy, si->passwd_dialog, pw->border); + + /* We use the default visual, not ssi->visual, so that the logo pixmap's + visual matches that of the si->passwd_dialog window. */ + pw->logo_pixmap = xscreensaver_logo (ssi->screen, + /* ssi->current_visual, */ + DefaultVisualOfScreen(screen), + si->passwd_dialog, cmap, + pw->background, + &pw->logo_pixels, &pw->logo_npixels, + &pw->logo_clipmask, True); + } + else /* On successive prompts, just resize the window */ + { + XWindowChanges wc; + unsigned int mask = CWX | CWY | CWWidth | CWHeight; + + wc.x = pw->x; + wc.y = pw->y; + wc.width = pw->width; + wc.height = pw->height; + + XConfigureWindow (si->dpy, si->passwd_dialog, mask, &wc); + } + + restore_background(si); + + XMapRaised (si->dpy, si->passwd_dialog); + XSync (si->dpy, False); + + move_mouse_grab (si, si->passwd_dialog, + pw->passwd_cursor, + pw->prompt_screen->number); + undo_vp_motion (si); + + si->pw_data = pw; + + if (cmap) + XInstallColormap (si->dpy, cmap); + draw_passwd_window (si); + + return 0; +} + + +static void +draw_passwd_window (saver_info *si) +{ + passwd_dialog_data *pw = si->pw_data; + XGCValues gcv; + GC gc1, gc2; + int spacing, height; + int x1, x2, x3, y1, y2; + int sw; + int tb_height; + + /* Force redraw */ + pw->passwd_changed_p = True; + pw->button_state_changed_p = True; + + /* This height is the height of all the elements, not to be confused with + * the overall window height which is pw->height. It is used to compute + * the amount of spacing (padding) between elements. */ + height = (pw->heading_font->ascent + pw->heading_font->descent + + pw->info_label->overall_height + + MAX (((pw->label_font->ascent + pw->label_font->descent) + + (pw->prompt_label ? pw->prompt_label->overall_height : 0)), + ((pw->passwd_font->ascent + pw->passwd_font->descent) + + (pw->shadow_width * 2)) * (pw->prompt_label ? 2 : 1)) + + pw->date_font->ascent + pw->date_font->descent); + + if ((strlen(pw->uname_label)) && pw->show_uname_p) + height += (pw->uname_font->ascent + pw->uname_font->descent); + + height += ((pw->button_font->ascent + pw->button_font->descent) * 2 + + 2 * pw->shadow_width); + + spacing = ((pw->height - 2 * pw->shadow_width + - pw->internal_border - height) + / 10); + + if (spacing < 0) spacing = 0; + + gcv.foreground = pw->foreground; + gc1 = XCreateGC (si->dpy, si->passwd_dialog, GCForeground, &gcv); + gc2 = XCreateGC (si->dpy, si->passwd_dialog, GCForeground, &gcv); + x1 = pw->logo_width + pw->thermo_width + (pw->shadow_width * 3); + x3 = pw->width - (pw->shadow_width * 2); + y1 = (pw->shadow_width * 2) + spacing + spacing; + + /* top heading + */ + XSetFont (si->dpy, gc1, pw->heading_font->fid); + sw = string_width (pw->heading_font, pw->heading_label); + x2 = (x1 + ((x3 - x1 - sw) / 2)); + y1 += spacing + pw->heading_font->ascent + pw->heading_font->descent; + XDrawString (si->dpy, si->passwd_dialog, gc1, x2, y1, + pw->heading_label, strlen(pw->heading_label)); + + /* uname below top heading + */ + if ((strlen(pw->uname_label)) && pw->show_uname_p) + { + XSetFont (si->dpy, gc1, pw->uname_font->fid); + y1 += spacing + pw->uname_font->ascent + pw->uname_font->descent; + sw = string_width (pw->uname_font, pw->uname_label); + x2 = (x1 + ((x3 - x1 - sw) / 2)); + XDrawString (si->dpy, si->passwd_dialog, gc1, x2, y1, + pw->uname_label, strlen(pw->uname_label)); + } + + /* the info_label (below uname) + */ + x2 = (x1 + ((x3 - x1 - pw->info_label->overall_width) / 2)); + y1 += spacing + pw->info_label->font_height / 2; + mlstring_draw(si->dpy, si->passwd_dialog, gc1, pw->info_label, + x2, y1); + y1 += pw->info_label->overall_height; + + + tb_height = (pw->passwd_font->ascent + pw->passwd_font->descent + + (pw->shadow_width * 4)); + + /* the "User:" prompt + */ + y2 = y1; + XSetForeground (si->dpy, gc1, pw->foreground); + XSetFont (si->dpy, gc1, pw->label_font->fid); + y1 += (spacing + tb_height + pw->shadow_width); + x2 = (x1 + pw->internal_border + + MAX(string_width (pw->label_font, pw->user_label), + pw->prompt_label ? pw->prompt_label->overall_width : 0)); + XDrawString (si->dpy, si->passwd_dialog, gc1, + x2 - string_width (pw->label_font, pw->user_label), + y1 - pw->passwd_font->descent, + pw->user_label, strlen(pw->user_label)); + + /* the prompt_label prompt + */ + if (pw->prompt_label) + { + y1 += tb_height - pw->label_font->ascent + pw->shadow_width; + mlstring_draw(si->dpy, si->passwd_dialog, gc1, pw->prompt_label, + x2 - pw->prompt_label->overall_width, y1); + } + + /* the "user name" text field + */ + y1 = y2; + XSetForeground (si->dpy, gc1, pw->passwd_foreground); + XSetForeground (si->dpy, gc2, pw->passwd_background); + XSetFont (si->dpy, gc1, pw->passwd_font->fid); + y1 += (spacing + tb_height); + x2 += (pw->shadow_width * 4); + + pw->passwd_field_width = x3 - x2 - pw->internal_border; + pw->passwd_field_height = (pw->passwd_font->ascent + + pw->passwd_font->descent + + pw->shadow_width); + + XFillRectangle (si->dpy, si->passwd_dialog, gc2, + x2 - pw->shadow_width, + y1 - (pw->passwd_font->ascent + pw->passwd_font->descent), + pw->passwd_field_width, pw->passwd_field_height); + XDrawString (si->dpy, si->passwd_dialog, gc1, + x2, + y1 - pw->passwd_font->descent, + si->user, strlen(si->user)); + + /* the password/prompt text field + */ + if (pw->prompt_label) + { + y1 += (spacing + pw->prompt_label->overall_height + pw->shadow_width*2); + + pw->passwd_field_x = x2 - pw->shadow_width; + pw->passwd_field_y = y1 - (pw->passwd_font->ascent + + pw->passwd_font->descent); + } + + /* The shadow around the text fields + */ + y1 = y2; + y1 += (spacing + (pw->shadow_width * 3)); + x1 = x2 - (pw->shadow_width * 2); + x2 = pw->passwd_field_width + (pw->shadow_width * 2); + y2 = pw->passwd_field_height + (pw->shadow_width * 2); + + draw_shaded_rectangle (si->dpy, si->passwd_dialog, + x1, y1, x2, y2, + pw->shadow_width, + pw->shadow_bottom, pw->shadow_top); + + if (pw->prompt_label) + { + y1 += (spacing + pw->prompt_label->overall_height + pw->shadow_width*2); + draw_shaded_rectangle (si->dpy, si->passwd_dialog, + x1, y1, x2, y2, + pw->shadow_width, + pw->shadow_bottom, pw->shadow_top); + } + + + /* The date, below the text fields + */ + { + char buf[100]; + time_t now = time ((time_t *) 0); + struct tm *tm = localtime (&now); + memset (buf, 0, sizeof(buf)); + strftime (buf, sizeof(buf)-1, pw->date_label, tm); + + XSetFont (si->dpy, gc1, pw->date_font->fid); + y1 += pw->shadow_width; + y1 += (spacing + tb_height); + y1 += spacing/2; + sw = string_width (pw->date_font, buf); + x2 = x1 + x2 - sw; + XDrawString (si->dpy, si->passwd_dialog, gc1, x2, y1, buf, strlen(buf)); + } + + /* Set up the GCs for the "New Login" and "Unlock" buttons. + */ + XSetForeground(si->dpy, gc1, pw->button_foreground); + XSetForeground(si->dpy, gc2, pw->button_background); + XSetFont(si->dpy, gc1, pw->button_font->fid); + + /* The "Unlock" button */ + x2 = pw->width - pw->internal_border - (pw->shadow_width * 2); + + /* right aligned button */ + x1 = x2 - pw->unlock_button_width; + + /* Add half the difference between y1 and the internal edge. + * It actually looks better if the internal border is ignored. */ + y1 += ((pw->height - MAX (pw->unlock_button_height, pw->login_button_height) + - spacing - y1) + / 2); + + pw->unlock_button_x = x1; + pw->unlock_button_y = y1; + + /* The "New Login" button + */ + if (pw->login_button_p) + { + /* Using the same GC as for the Unlock button */ + + sw = string_width (pw->button_font, pw->login_label); + + /* left aligned button */ + x1 = (pw->logo_width + pw->thermo_width + (pw->shadow_width * 3) + + pw->internal_border); + + pw->login_button_x = x1; + pw->login_button_y = y1; + } + + /* The logo + */ + x1 = pw->shadow_width * 6; + y1 = pw->shadow_width * 6; + x2 = pw->logo_width - (pw->shadow_width * 12); + y2 = pw->logo_height - (pw->shadow_width * 12); + + if (pw->logo_pixmap) + { + Window root; + int x, y; + unsigned int w, h, bw, d; + XGetGeometry (si->dpy, pw->logo_pixmap, &root, &x, &y, &w, &h, &bw, &d); + XSetForeground (si->dpy, gc1, pw->foreground); + XSetBackground (si->dpy, gc1, pw->background); + XSetClipMask (si->dpy, gc1, pw->logo_clipmask); + XSetClipOrigin (si->dpy, gc1, + x1 + ((x2 - (int)w) / 2), + y1 + ((y2 - (int)h) / 2)); + if (d == 1) + XCopyPlane (si->dpy, pw->logo_pixmap, si->passwd_dialog, gc1, + 0, 0, w, h, + x1 + ((x2 - (int)w) / 2), + y1 + ((y2 - (int)h) / 2), + 1); + else + XCopyArea (si->dpy, pw->logo_pixmap, si->passwd_dialog, gc1, + 0, 0, w, h, + x1 + ((x2 - (int)w) / 2), + y1 + ((y2 - (int)h) / 2)); + } + + /* The thermometer + */ + XSetForeground (si->dpy, gc1, pw->thermo_foreground); + XSetForeground (si->dpy, gc2, pw->thermo_background); + + pw->thermo_field_x = pw->logo_width + pw->shadow_width; + pw->thermo_field_y = pw->shadow_width * 5; + pw->thermo_field_height = pw->height - (pw->shadow_width * 10); + +#if 0 + /* Solid border inside the logo box. */ + XSetForeground (si->dpy, gc1, pw->foreground); + XDrawRectangle (si->dpy, si->passwd_dialog, gc1, x1, y1, x2-1, y2-1); +#endif + + /* The shadow around the logo + */ + draw_shaded_rectangle (si->dpy, si->passwd_dialog, + pw->shadow_width * 4, + pw->shadow_width * 4, + pw->logo_width - (pw->shadow_width * 8), + pw->logo_height - (pw->shadow_width * 8), + pw->shadow_width, + pw->shadow_bottom, pw->shadow_top); + + /* The shadow around the thermometer + */ + draw_shaded_rectangle (si->dpy, si->passwd_dialog, + pw->logo_width, + pw->shadow_width * 4, + pw->thermo_width + (pw->shadow_width * 2), + pw->height - (pw->shadow_width * 8), + pw->shadow_width, + pw->shadow_bottom, pw->shadow_top); + +#if 1 + /* Solid border inside the thermometer. */ + XSetForeground (si->dpy, gc1, pw->foreground); + XDrawRectangle (si->dpy, si->passwd_dialog, gc1, + pw->thermo_field_x, pw->thermo_field_y, + pw->thermo_width - 1, pw->thermo_field_height - 1); +#endif + + /* The shadow around the whole window + */ + draw_shaded_rectangle (si->dpy, si->passwd_dialog, + 0, 0, pw->width, pw->height, pw->shadow_width, + pw->shadow_top, pw->shadow_bottom); + + XFreeGC (si->dpy, gc1); + XFreeGC (si->dpy, gc2); + + update_passwd_window (si, pw->passwd_string, pw->ratio); +} + +static void +draw_button(Display *dpy, + Drawable dialog, + XFontStruct *font, + unsigned long foreground, unsigned long background, + char *label, + int x, int y, + int width, int height, + int shadow_width, + Pixel shadow_light, Pixel shadow_dark, + Bool button_down) +{ + XGCValues gcv; + GC gc1, gc2; + int sw; + int label_x, label_y; + + gcv.foreground = foreground; + gcv.font = font->fid; + gc1 = XCreateGC(dpy, dialog, GCForeground|GCFont, &gcv); + gcv.foreground = background; + gc2 = XCreateGC(dpy, dialog, GCForeground, &gcv); + + XFillRectangle(dpy, dialog, gc2, + x, y, width, height); + + sw = string_width(font, label); + + label_x = x + ((width - sw) / 2); + label_y = (y + (height - (font->ascent + font->descent)) / 2 + font->ascent); + + if (button_down) + { + label_x += 2; + label_y += 2; + } + + XDrawString(dpy, dialog, gc1, label_x, label_y, label, strlen(label)); + + XFreeGC(dpy, gc1); + XFreeGC(dpy, gc2); + + draw_shaded_rectangle(dpy, dialog, x, y, width, height, + shadow_width, shadow_light, shadow_dark); +} + +static void +update_passwd_window (saver_info *si, const char *printed_passwd, float ratio) +{ + passwd_dialog_data *pw = si->pw_data; + XGCValues gcv; + GC gc1, gc2; + int x, y; + XRectangle rects[1]; + + pw->ratio = ratio; + gcv.foreground = pw->passwd_foreground; + gcv.font = pw->passwd_font->fid; + gc1 = XCreateGC (si->dpy, si->passwd_dialog, GCForeground|GCFont, &gcv); + gcv.foreground = pw->passwd_background; + gc2 = XCreateGC (si->dpy, si->passwd_dialog, GCForeground, &gcv); + + if (printed_passwd) + { + char *s = strdup (printed_passwd); + if (pw->passwd_string) free (pw->passwd_string); + pw->passwd_string = s; + } + + if (pw->prompt_label) + { + + /* the "password" text field + */ + rects[0].x = pw->passwd_field_x; + rects[0].y = pw->passwd_field_y; + rects[0].width = pw->passwd_field_width; + rects[0].height = pw->passwd_field_height; + + /* The user entry (password) field is double buffered. + * This avoids flickering, particularly in synchronous mode. */ + + if (pw->passwd_changed_p) + { + pw->passwd_changed_p = False; + + if (pw->user_entry_pixmap) + { + XFreePixmap(si->dpy, pw->user_entry_pixmap); + pw->user_entry_pixmap = 0; + } + + pw->user_entry_pixmap = + XCreatePixmap (si->dpy, si->passwd_dialog, + rects[0].width, rects[0].height, + DefaultDepthOfScreen (pw->prompt_screen->screen)); + + XFillRectangle (si->dpy, pw->user_entry_pixmap, gc2, + 0, 0, rects[0].width, rects[0].height); + + XDrawString (si->dpy, pw->user_entry_pixmap, gc1, + pw->shadow_width, + pw->passwd_font->ascent, + pw->passwd_string, strlen(pw->passwd_string)); + + /* Ensure the new pixmap gets copied to the window */ + pw->i_beam = 0; + + } + + /* The I-beam + */ + if (pw->i_beam == 0) + { + /* Make the I-beam disappear */ + XCopyArea(si->dpy, pw->user_entry_pixmap, si->passwd_dialog, gc2, + 0, 0, rects[0].width, rects[0].height, + rects[0].x, rects[0].y); + } + else if (pw->i_beam == 1) + { + /* Make the I-beam appear */ + x = (rects[0].x + pw->shadow_width + + string_width (pw->passwd_font, pw->passwd_string)); + y = rects[0].y + pw->shadow_width; + + if (x > rects[0].x + rects[0].width - 1) + x = rects[0].x + rects[0].width - 1; + XDrawLine (si->dpy, si->passwd_dialog, gc1, + x, y, + x, y + pw->passwd_font->ascent + + pw->passwd_font->descent-1); + } + + pw->i_beam = (pw->i_beam + 1) % 4; + + } + + /* the thermometer + */ + y = (pw->thermo_field_height - 2) * (1.0 - pw->ratio); + if (y > 0) + { + XFillRectangle (si->dpy, si->passwd_dialog, gc2, + pw->thermo_field_x + 1, + pw->thermo_field_y + 1, + pw->thermo_width-2, + y); + XSetForeground (si->dpy, gc1, pw->thermo_foreground); + XFillRectangle (si->dpy, si->passwd_dialog, gc1, + pw->thermo_field_x + 1, + pw->thermo_field_y + 1 + y, + pw->thermo_width-2, + MAX (0, pw->thermo_field_height - y - 2)); + } + + if (pw->button_state_changed_p) + { + pw->button_state_changed_p = False; + + /* The "Unlock" button + */ + draw_button(si->dpy, si->passwd_dialog, pw->button_font, + pw->button_foreground, pw->button_background, + pw->unlock_label, + pw->unlock_button_x, pw->unlock_button_y, + pw->unlock_button_width, pw->unlock_button_height, + pw->shadow_width, + (pw->unlock_button_down_p ? pw->shadow_bottom : + pw->shadow_top), + (pw->unlock_button_down_p ? pw->shadow_top : + pw->shadow_bottom), + pw->unlock_button_down_p); + + /* The "New Login" button + */ + if (pw->login_button_p) + { + draw_button(si->dpy, si->passwd_dialog, pw->button_font, + (pw->login_button_enabled_p + ? pw->passwd_foreground + : pw->shadow_bottom), + pw->button_background, + pw->login_label, + pw->login_button_x, pw->login_button_y, + pw->login_button_width, pw->login_button_height, + pw->shadow_width, + (pw->login_button_down_p + ? pw->shadow_bottom + : pw->shadow_top), + (pw->login_button_down_p + ? pw->shadow_top + : pw->shadow_bottom), + pw->login_button_down_p); + } + } + + XFreeGC (si->dpy, gc1); + XFreeGC (si->dpy, gc2); + XSync (si->dpy, False); +} + + +void +restore_background (saver_info *si) +{ + passwd_dialog_data *pw = si->pw_data; + saver_screen_info *ssi = pw->prompt_screen; + XGCValues gcv; + GC gc; + + gcv.function = GXcopy; + + gc = XCreateGC (si->dpy, ssi->screensaver_window, GCFunction, &gcv); + + XCopyArea (si->dpy, pw->save_under, + ssi->screensaver_window, gc, + 0, 0, + ssi->width, ssi->height, + 0, 0); + + XFreeGC (si->dpy, gc); +} + + +/* Frees anything created by make_passwd_window */ +static void +cleanup_passwd_window (saver_info *si) +{ + passwd_dialog_data *pw; + + if (!(pw = si->pw_data)) + return; + + if (pw->info_label) + { + mlstring_free(pw->info_label); + pw->info_label = 0; + } + + if (pw->prompt_label) + { + mlstring_free(pw->prompt_label); + pw->prompt_label = 0; + } + + memset (pw->typed_passwd, 0, sizeof(pw->typed_passwd)); + memset (pw->typed_passwd_char_size, 0, sizeof(pw->typed_passwd_char_size)); + memset (pw->passwd_string, 0, strlen(pw->passwd_string)); + + if (pw->timer) + { + XtRemoveTimeOut (pw->timer); + pw->timer = 0; + } + + if (pw->user_entry_pixmap) + { + XFreePixmap(si->dpy, pw->user_entry_pixmap); + pw->user_entry_pixmap = 0; + } +} + + +static void +destroy_passwd_window (saver_info *si) +{ + saver_preferences *p = &si->prefs; + passwd_dialog_data *pw = si->pw_data; + saver_screen_info *ssi = pw->prompt_screen; + Colormap cmap = DefaultColormapOfScreen (ssi->screen); + Pixel black = BlackPixelOfScreen (ssi->screen); + Pixel white = WhitePixelOfScreen (ssi->screen); + XEvent event; + + cleanup_passwd_window (si); + + if (si->cached_passwd) + { + char *wipe = si->cached_passwd; + + while (*wipe) + *wipe++ = '\0'; + + free(si->cached_passwd); + si->cached_passwd = NULL; + } + + move_mouse_grab (si, RootWindowOfScreen (ssi->screen), + ssi->cursor, ssi->number); + + if (pw->passwd_cursor) + XFreeCursor (si->dpy, pw->passwd_cursor); + + if (p->verbose_p) + fprintf (stderr, "%s: %d: moving mouse back to %d,%d.\n", + blurb(), ssi->number, + pw->previous_mouse_x, pw->previous_mouse_y); + + XWarpPointer (si->dpy, None, RootWindowOfScreen (ssi->screen), + 0, 0, 0, 0, + pw->previous_mouse_x, pw->previous_mouse_y); + XSync (si->dpy, False); + + while (XCheckMaskEvent (si->dpy, PointerMotionMask, &event)) + if (p->verbose_p) + fprintf (stderr, "%s: discarding MotionNotify event.\n", blurb()); + +#ifdef HAVE_XINPUT + if (si->using_xinput_extension && si->xinput_DeviceMotionNotify) + while (XCheckTypedEvent (si->dpy, si->xinput_DeviceMotionNotify, &event)) + if (p->verbose_p) + fprintf (stderr, "%s: discarding DeviceMotionNotify event.\n", + blurb()); +#endif + + if (si->passwd_dialog) + { + if (si->prefs.verbose_p) + fprintf (stderr, "%s: %d: destroying password dialog.\n", + blurb(), pw->prompt_screen->number); + + XDestroyWindow (si->dpy, si->passwd_dialog); + si->passwd_dialog = 0; + } + + if (pw->save_under) + { + restore_background(si); + XFreePixmap (si->dpy, pw->save_under); + pw->save_under = 0; + } + + if (pw->heading_label) free (pw->heading_label); + if (pw->body_label) free (pw->body_label); + if (pw->user_label) free (pw->user_label); + if (pw->date_label) free (pw->date_label); + if (pw->login_label) free (pw->login_label); + if (pw->unlock_label) free (pw->unlock_label); + if (pw->passwd_string) free (pw->passwd_string); + if (pw->uname_label) free (pw->uname_label); + + if (pw->heading_font) XFreeFont (si->dpy, pw->heading_font); + if (pw->body_font) XFreeFont (si->dpy, pw->body_font); + if (pw->label_font) XFreeFont (si->dpy, pw->label_font); + if (pw->passwd_font) XFreeFont (si->dpy, pw->passwd_font); + if (pw->date_font) XFreeFont (si->dpy, pw->date_font); + if (pw->button_font) XFreeFont (si->dpy, pw->button_font); + if (pw->uname_font) XFreeFont (si->dpy, pw->uname_font); + + if (pw->foreground != black && pw->foreground != white) + XFreeColors (si->dpy, cmap, &pw->foreground, 1, 0L); + if (pw->background != black && pw->background != white) + XFreeColors (si->dpy, cmap, &pw->background, 1, 0L); + if (!(pw->button_foreground == black || pw->button_foreground == white)) + XFreeColors (si->dpy, cmap, &pw->button_foreground, 1, 0L); + if (!(pw->button_background == black || pw->button_background == white)) + XFreeColors (si->dpy, cmap, &pw->button_background, 1, 0L); + if (pw->passwd_foreground != black && pw->passwd_foreground != white) + XFreeColors (si->dpy, cmap, &pw->passwd_foreground, 1, 0L); + if (pw->passwd_background != black && pw->passwd_background != white) + XFreeColors (si->dpy, cmap, &pw->passwd_background, 1, 0L); + if (pw->thermo_foreground != black && pw->thermo_foreground != white) + XFreeColors (si->dpy, cmap, &pw->thermo_foreground, 1, 0L); + if (pw->thermo_background != black && pw->thermo_background != white) + XFreeColors (si->dpy, cmap, &pw->thermo_background, 1, 0L); + if (pw->shadow_top != black && pw->shadow_top != white) + XFreeColors (si->dpy, cmap, &pw->shadow_top, 1, 0L); + if (pw->shadow_bottom != black && pw->shadow_bottom != white) + XFreeColors (si->dpy, cmap, &pw->shadow_bottom, 1, 0L); + + if (pw->logo_pixmap) + XFreePixmap (si->dpy, pw->logo_pixmap); + if (pw-> logo_clipmask) + XFreePixmap (si->dpy, pw->logo_clipmask); + if (pw->logo_pixels) + { + if (pw->logo_npixels) + XFreeColors (si->dpy, cmap, pw->logo_pixels, pw->logo_npixels, 0L); + free (pw->logo_pixels); + pw->logo_pixels = 0; + pw->logo_npixels = 0; + } + + if (pw->save_under) + XFreePixmap (si->dpy, pw->save_under); + + if (cmap) + XInstallColormap (si->dpy, cmap); + + memset (pw, 0, sizeof(*pw)); + free (pw); + si->pw_data = 0; +} + + +static Bool error_handler_hit_p = False; + +static int +ignore_all_errors_ehandler (Display *dpy, XErrorEvent *error) +{ + error_handler_hit_p = True; + return 0; +} + + +#ifdef HAVE_XHPDISABLERESET +/* This function enables and disables the C-Sh-Reset hot-key, which + normally resets the X server (logging out the logged-in user.) + We don't want random people to be able to do that while the + screen is locked. + */ +static void +hp_lock_reset (saver_info *si, Bool lock_p) +{ + static Bool hp_locked_p = False; + + /* Calls to XHPDisableReset and XHPEnableReset must be balanced, + or BadAccess errors occur. (It's ok for this to be global, + since it affects the whole machine, not just the current screen.) + */ + if (hp_locked_p == lock_p) + return; + + if (lock_p) + XHPDisableReset (si->dpy); + else + XHPEnableReset (si->dpy); + hp_locked_p = lock_p; +} +#endif /* HAVE_XHPDISABLERESET */ + + +#ifdef HAVE_XF86MISCSETGRABKEYSSTATE + +/* This function enables and disables the Ctrl-Alt-KP_star and + Ctrl-Alt-KP_slash hot-keys, which (in XFree86 4.2) break any + grabs and/or kill the grabbing client. That would effectively + unlock the screen, so we don't like that. + + The Ctrl-Alt-KP_star and Ctrl-Alt-KP_slash hot-keys only exist + if AllowDeactivateGrabs and/or AllowClosedownGrabs are turned on + in XF86Config. I believe they are disabled by default. + + This does not affect any other keys (specifically Ctrl-Alt-BS or + Ctrl-Alt-F1) but I wish it did. Maybe it will someday. + */ +static void +xfree_lock_grab_smasher (saver_info *si, Bool lock_p) +{ + saver_preferences *p = &si->prefs; + int status; + int event, error; + XErrorHandler old_handler; + + if (!XF86MiscQueryExtension(si->dpy, &event, &error)) + return; + + XSync (si->dpy, False); + error_handler_hit_p = False; + old_handler = XSetErrorHandler (ignore_all_errors_ehandler); + XSync (si->dpy, False); + status = XF86MiscSetGrabKeysState (si->dpy, !lock_p); + XSync (si->dpy, False); + if (error_handler_hit_p) status = 666; + + if (!lock_p && status == MiscExtGrabStateAlready) + status = MiscExtGrabStateSuccess; /* shut up, consider this success */ + + if (p->verbose_p && status != MiscExtGrabStateSuccess) + fprintf (stderr, "%s: error: XF86MiscSetGrabKeysState(%d) returned %s\n", + blurb(), !lock_p, + (status == MiscExtGrabStateSuccess ? "MiscExtGrabStateSuccess" : + status == MiscExtGrabStateLocked ? "MiscExtGrabStateLocked" : + status == MiscExtGrabStateAlready ? "MiscExtGrabStateAlready" : + status == 666 ? "an X error" : + "unknown value")); + + XSync (si->dpy, False); + XSetErrorHandler (old_handler); + XSync (si->dpy, False); +} +#endif /* HAVE_XF86MISCSETGRABKEYSSTATE */ + + + +/* This function enables and disables the C-Alt-Plus and C-Alt-Minus + hot-keys, which normally change the resolution of the X server. + We don't want people to be able to switch the server resolution + while the screen is locked, because if they switch to a higher + resolution, it could cause part of the underlying desktop to become + exposed. + */ +#ifdef HAVE_XF86VMODE + +static void +xfree_lock_mode_switch (saver_info *si, Bool lock_p) +{ + static Bool any_mode_locked_p = False; + saver_preferences *p = &si->prefs; + int screen; + int real_nscreens = ScreenCount (si->dpy); + int event, error; + Bool status; + XErrorHandler old_handler; + + if (any_mode_locked_p == lock_p) + return; + if (!XF86VidModeQueryExtension (si->dpy, &event, &error)) + return; + + for (screen = 0; screen < real_nscreens; screen++) + { + XSync (si->dpy, False); + old_handler = XSetErrorHandler (ignore_all_errors_ehandler); + error_handler_hit_p = False; + status = XF86VidModeLockModeSwitch (si->dpy, screen, lock_p); + XSync (si->dpy, False); + XSetErrorHandler (old_handler); + if (error_handler_hit_p) status = False; + + if (status) + any_mode_locked_p = lock_p; + + if (!status && (p->verbose_p || !lock_p)) + /* Only print this when verbose, or when we locked but can't unlock. + I tried printing this message whenever it comes up, but + mode-locking always fails if DontZoom is set in XF86Config. */ + fprintf (stderr, "%s: %d: unable to %s mode switching!\n", + blurb(), screen, (lock_p ? "lock" : "unlock")); + else if (p->verbose_p) + fprintf (stderr, "%s: %d: %s mode switching.\n", + blurb(), screen, (lock_p ? "locked" : "unlocked")); + } +} +#endif /* HAVE_XF86VMODE */ + + +/* If the viewport has been scrolled since the screen was blanked, + then scroll it back to where it belongs. This function only exists + to patch over a very brief race condition. + */ +static void +undo_vp_motion (saver_info *si) +{ +#ifdef HAVE_XF86VMODE + saver_preferences *p = &si->prefs; + int screen; + int real_nscreens = ScreenCount (si->dpy); + int event, error; + + if (!XF86VidModeQueryExtension (si->dpy, &event, &error)) + return; + + for (screen = 0; screen < real_nscreens; screen++) + { + saver_screen_info *ssi = &si->screens[screen]; + int x, y; + Bool status; + + if (ssi->blank_vp_x == -1 && ssi->blank_vp_y == -1) + break; + if (!XF86VidModeGetViewPort (si->dpy, screen, &x, &y)) + return; + if (ssi->blank_vp_x == x && ssi->blank_vp_y == y) + return; + + /* We're going to move the viewport. The mouse has just been grabbed on + (and constrained to, thus warped to) the password window, so it is no + longer near the edge of the screen. However, wait a bit anyway, just + to make sure the server drains its last motion event, so that the + screen doesn't continue to scroll after we've reset the viewport. + */ + XSync (si->dpy, False); + usleep (250000); /* 1/4 second */ + XSync (si->dpy, False); + + status = XF86VidModeSetViewPort (si->dpy, screen, + ssi->blank_vp_x, ssi->blank_vp_y); + + if (!status) + fprintf (stderr, + "%s: %d: unable to move vp from (%d,%d) back to (%d,%d)!\n", + blurb(), screen, x, y, ssi->blank_vp_x, ssi->blank_vp_y); + else if (p->verbose_p) + fprintf (stderr, + "%s: %d: vp moved to (%d,%d); moved it back to (%d,%d).\n", + blurb(), screen, x, y, ssi->blank_vp_x, ssi->blank_vp_y); + } +#endif /* HAVE_XF86VMODE */ +} + + + +/* Interactions + */ + +static void +passwd_animate_timer (XtPointer closure, XtIntervalId *id) +{ + saver_info *si = (saver_info *) closure; + int tick = 166; + passwd_dialog_data *pw = si->pw_data; + + if (!pw) return; + + pw->ratio -= (1.0 / ((double) si->prefs.passwd_timeout / (double) tick)); + if (pw->ratio < 0) + { + pw->ratio = 0; + if (si->unlock_state == ul_read) + si->unlock_state = ul_time; + } + + update_passwd_window (si, 0, pw->ratio); + + if (si->unlock_state == ul_read) + pw->timer = XtAppAddTimeOut (si->app, tick, passwd_animate_timer, + (XtPointer) si); + else + pw->timer = 0; + + idle_timer ((XtPointer) si, 0); +} + + +static XComposeStatus *compose_status; + +static void +handle_login_button (saver_info *si, XEvent *event) +{ + saver_preferences *p = &si->prefs; + Bool mouse_in_box = False; + Bool hit_p = False; + passwd_dialog_data *pw = si->pw_data; + saver_screen_info *ssi = pw->prompt_screen; + + if (! pw->login_button_enabled_p) + return; + + mouse_in_box = + (event->xbutton.x >= pw->login_button_x && + event->xbutton.x <= pw->login_button_x + pw->login_button_width && + event->xbutton.y >= pw->login_button_y && + event->xbutton.y <= pw->login_button_y + pw->login_button_height); + + if (ButtonRelease == event->xany.type && + pw->login_button_down_p && + mouse_in_box) + { + /* Only allow them to press the button once: don't want to + accidentally launch a dozen gdm choosers if the machine + is being slow. + */ + hit_p = True; + pw->login_button_enabled_p = False; + } + + pw->login_button_down_p = (mouse_in_box && + ButtonRelease != event->xany.type); + + update_passwd_window (si, 0, pw->ratio); + + if (hit_p) + fork_and_exec (ssi, p->new_login_command); +} + + +static void +handle_unlock_button (saver_info *si, XEvent *event) +{ + Bool mouse_in_box = False; + passwd_dialog_data *pw = si->pw_data; + + mouse_in_box = + (event->xbutton.x >= pw->unlock_button_x && + event->xbutton.x <= pw->unlock_button_x + pw->unlock_button_width && + event->xbutton.y >= pw->unlock_button_y && + event->xbutton.y <= pw->unlock_button_y + pw->unlock_button_height); + + if (ButtonRelease == event->xany.type && + pw->unlock_button_down_p && + mouse_in_box) + finished_typing_passwd (si, pw); + + pw->unlock_button_down_p = (mouse_in_box && + ButtonRelease != event->xany.type); +} + + +static void +finished_typing_passwd (saver_info *si, passwd_dialog_data *pw) +{ + if (si->unlock_state == ul_read) + { + update_passwd_window (si, "Checking...", pw->ratio); + XSync (si->dpy, False); + + si->unlock_state = ul_finished; + update_passwd_window (si, "", pw->ratio); + } +} + +static void +handle_passwd_key (saver_info *si, XKeyEvent *event) +{ + passwd_dialog_data *pw = si->pw_data; + unsigned char decoded [MAX_BYTES_PER_CHAR * 10]; /* leave some slack */ + KeySym keysym = 0; + + /* XLookupString may return more than one character via XRebindKeysym; + and on some systems it returns multi-byte UTF-8 characters (contrary + to its documentation, which says it returns only Latin1.) + + It seems to only do so, however, if setlocale() has been called. + See the code inside ENABLE_NLS in xscreensaver.c. + */ + int decoded_size = XLookupString (event, (char *)decoded, sizeof(decoded), + &keysym, compose_status); + +#if 0 + { + const char *ks = XKeysymToString (keysym); + int i; + fprintf(stderr, "## %-12s\t=> %d\t", (ks ? ks : "(null)"), decoded_size); + for (i = 0; i < decoded_size; i++) + fprintf(stderr, "%c", decoded[i]); + fprintf(stderr, "\t"); + for (i = 0; i < decoded_size; i++) + fprintf(stderr, "\\%03o", ((unsigned char *)decoded)[i]); + fprintf(stderr, "\n"); + } +#endif + + if (decoded_size > MAX_BYTES_PER_CHAR) + { + /* The multi-byte character returned is too large. */ + XBell (si->dpy, 0); + return; + } + + decoded[decoded_size] = 0; + pw->passwd_changed_p = True; + + /* Add 10% to the time remaining every time a key is pressed. */ + pw->ratio += 0.1; + if (pw->ratio > 1) pw->ratio = 1; + + if (decoded_size == 1) /* Handle single-char commands */ + { + switch (*decoded) + { + case '\010': case '\177': /* Backspace */ + { + /* kludgey way to get the number of "logical" characters. */ + int nchars = strlen (pw->typed_passwd_char_size); + int nbytes = strlen (pw->typed_passwd); + if (nbytes <= 0) + XBell (si->dpy, 0); + else + { + int i; + for (i = pw->typed_passwd_char_size[nchars-1]; i >= 0; i--) + { + if (nbytes < 0) abort(); + pw->typed_passwd[nbytes--] = 0; + } + pw->typed_passwd_char_size[nchars-1] = 0; + } + } + break; + + case '\012': case '\015': /* Enter */ + finished_typing_passwd (si, pw); + break; + + case '\033': /* Escape */ + si->unlock_state = ul_cancel; + break; + + case '\025': case '\030': /* Erase line */ + memset (pw->typed_passwd, 0, sizeof (pw->typed_passwd)); + memset (pw->typed_passwd_char_size, 0, + sizeof (pw->typed_passwd_char_size)); + break; + + default: + if (*decoded < ' ' && *decoded != '\t') /* Other ctrl char */ + XBell (si->dpy, 0); + else + goto SELF_INSERT; + break; + } + } + else + { + int nbytes, nchars; + SELF_INSERT: + nbytes = strlen (pw->typed_passwd); + nchars = strlen (pw->typed_passwd_char_size); + if (nchars + 1 >= sizeof (pw->typed_passwd_char_size)-1 || + nbytes + decoded_size >= sizeof (pw->typed_passwd)-1) /* overflow */ + XBell (si->dpy, 0); + else + { + pw->typed_passwd_char_size[nchars] = decoded_size; + pw->typed_passwd_char_size[nchars+1] = 0; + memcpy (pw->typed_passwd + nbytes, decoded, decoded_size); + pw->typed_passwd[nbytes + decoded_size] = 0; + } + } + + if (pw->echo_input) + { + /* If the input is wider than the text box, only show the last portion, + to simulate a horizontally-scrolling text field. */ + int chars_in_pwfield = (pw->passwd_field_width / + pw->passwd_font->max_bounds.width); + const char *output = pw->typed_passwd; + if (strlen(output) > chars_in_pwfield) + output += (strlen(output) - chars_in_pwfield); + update_passwd_window (si, output, pw->ratio); + } + else if (pw->show_stars_p) + { + int nchars = strlen (pw->typed_passwd_char_size); + char *stars = 0; + stars = (char *) malloc(nchars + 1); + memset (stars, '*', nchars); + stars[nchars] = 0; + update_passwd_window (si, stars, pw->ratio); + free (stars); + } + else + { + update_passwd_window (si, "", pw->ratio); + } +} + + +static void +passwd_event_loop (saver_info *si) +{ + saver_preferences *p = &si->prefs; + char *msg = 0; + + /* We have to go through this union bullshit because gcc-4.4.0 has + stricter struct-aliasing rules. Without this, the optimizer + can fuck things up. + */ + union { + XEvent x_event; +# ifdef HAVE_RANDR + XRRScreenChangeNotifyEvent xrr_event; +# endif /* HAVE_RANDR */ + } event; + + passwd_animate_timer ((XtPointer) si, 0); + + while (si->unlock_state == ul_read) + { + XtAppNextEvent (si->app, &event.x_event); + +#ifdef HAVE_RANDR + if (si->using_randr_extension && + (event.x_event.type == + (si->randr_event_number + RRScreenChangeNotify))) + { + /* The Resize and Rotate extension sends an event when the + size, rotation, or refresh rate of any screen has changed. */ + + if (p->verbose_p) + { + /* XRRRootToScreen is in Xrandr.h 1.4, 2001/06/07 */ + int screen = XRRRootToScreen(si->dpy, event.xrr_event.window); + fprintf (stderr, "%s: %d: screen change event received\n", + blurb(), screen); + } + +#ifdef RRScreenChangeNotifyMask + /* Inform Xlib that it's ok to update its data structures. */ + XRRUpdateConfiguration(&event.x_event); /* Xrandr.h 1.9, 2002/09/29*/ +#endif /* RRScreenChangeNotifyMask */ + + /* Resize the existing xscreensaver windows and cached ssi data. */ + if (update_screen_layout (si)) + { + if (p->verbose_p) + { + fprintf (stderr, "%s: new layout:\n", blurb()); + describe_monitor_layout (si); + } + resize_screensaver_window (si); + } + } + else +#endif /* HAVE_RANDR */ + + if (event.x_event.xany.window == si->passwd_dialog && + event.x_event.xany.type == Expose) + draw_passwd_window (si); + else if (event.x_event.xany.type == KeyPress) + { + handle_passwd_key (si, &event.x_event.xkey); + si->pw_data->caps_p = (event.x_event.xkey.state & LockMask); + } + else if (event.x_event.xany.type == ButtonPress || + event.x_event.xany.type == ButtonRelease) + { + si->pw_data->button_state_changed_p = True; + handle_unlock_button (si, &event.x_event); + if (si->pw_data->login_button_p) + handle_login_button (si, &event.x_event); + } + else + XtDispatchEvent (&event.x_event); + } + + switch (si->unlock_state) + { + case ul_cancel: msg = ""; break; + case ul_time: msg = "Timed out!"; break; + case ul_finished: msg = "Checking..."; break; + default: msg = 0; break; + } + + if (p->verbose_p) + switch (si->unlock_state) { + case ul_cancel: + fprintf (stderr, "%s: input cancelled.\n", blurb()); break; + case ul_time: + fprintf (stderr, "%s: input timed out.\n", blurb()); break; + case ul_finished: + fprintf (stderr, "%s: input finished.\n", blurb()); break; + default: break; + } + + if (msg) + { + si->pw_data->i_beam = 0; + update_passwd_window (si, msg, 0.0); + XSync (si->dpy, False); + + /* Swallow all pending KeyPress/KeyRelease events. */ + { + XEvent e; + while (XCheckMaskEvent (si->dpy, KeyPressMask|KeyReleaseMask, &e)) + ; + } + } +} + + +static void +handle_typeahead (saver_info *si) +{ + passwd_dialog_data *pw = si->pw_data; + int i; + if (!si->unlock_typeahead) + return; + + pw->passwd_changed_p = True; + + i = strlen (si->unlock_typeahead); + if (i >= sizeof(pw->typed_passwd) - 1) + i = sizeof(pw->typed_passwd) - 1; + + memcpy (pw->typed_passwd, si->unlock_typeahead, i); + pw->typed_passwd [i] = 0; + { + int j; + char *c = pw->typed_passwd_char_size; + for (j = 0; j < i; j++) + *c++ = 1; + *c = 0; + } + + memset (si->unlock_typeahead, '*', strlen(si->unlock_typeahead)); + si->unlock_typeahead[i] = 0; + update_passwd_window (si, si->unlock_typeahead, pw->ratio); + + free (si->unlock_typeahead); + si->unlock_typeahead = 0; +} + + +/** + * Returns a copy of the input string with trailing whitespace removed. + * Whitespace is anything considered so by isspace(). + * It is safe to call this with NULL, in which case NULL will be returned. + * The returned string (if not NULL) should be freed by the caller with free(). + */ +static char * +remove_trailing_whitespace(const char *str) +{ + size_t len; + char *newstr, *chr; + + if (!str) + return NULL; + + len = strlen(str); + + newstr = malloc(len + 1); + if (!newstr) + return NULL; + + (void) strcpy(newstr, str); + chr = newstr + len; + while (isspace(*--chr) && chr >= newstr) + *chr = '\0'; + + return newstr; +} + + +/* + * The authentication conversation function. + * Like a PAM conversation function, this accepts multiple messages in a single + * round. It then splits them into individual messages for display on the + * passwd dialog. A message sequence of info or error followed by a prompt will + * be reduced into a single dialog window. + * + * Returns 0 on success or -1 if some problem occurred (cancelled, OOM, etc.) + */ +int +gui_auth_conv(int num_msg, + const struct auth_message auth_msgs[], + struct auth_response **resp, + saver_info *si) +{ + int i; + const char *info_msg, *prompt; + struct auth_response *responses; + + if (si->unlock_state == ul_cancel || + si->unlock_state == ul_time) + /* If we've already cancelled or timed out in this PAM conversation, + don't prompt again even if PAM asks us to! */ + return -1; + + if (!(responses = calloc(num_msg, sizeof(struct auth_response)))) + goto fail; + + for (i = 0; i < num_msg; ++i) + { + info_msg = prompt = NULL; + + /* See if there is a following message that can be shown at the same + * time */ + if (auth_msgs[i].type == AUTH_MSGTYPE_INFO + && i+1 < num_msg + && ( auth_msgs[i+1].type == AUTH_MSGTYPE_PROMPT_NOECHO + || auth_msgs[i+1].type == AUTH_MSGTYPE_PROMPT_ECHO) + ) + { + info_msg = auth_msgs[i].msg; + prompt = auth_msgs[++i].msg; + } + else + { + if ( auth_msgs[i].type == AUTH_MSGTYPE_INFO + || auth_msgs[i].type == AUTH_MSGTYPE_ERROR) + info_msg = auth_msgs[i].msg; + else + prompt = auth_msgs[i].msg; + } + + { + char *info_msg_trimmed, *prompt_trimmed; + + /* Trailing whitespace looks bad in a GUI */ + info_msg_trimmed = remove_trailing_whitespace(info_msg); + prompt_trimmed = remove_trailing_whitespace(prompt); + + if (make_passwd_window(si, info_msg_trimmed, prompt_trimmed, + auth_msgs[i].type == AUTH_MSGTYPE_PROMPT_ECHO + ? True : False) + < 0) + goto fail; + + if (info_msg_trimmed) + free(info_msg_trimmed); + + if (prompt_trimmed) + free(prompt_trimmed); + } + + compose_status = calloc (1, sizeof (*compose_status)); + if (!compose_status) + goto fail; + + si->unlock_state = ul_read; + + handle_typeahead (si); + passwd_event_loop (si); + + if (si->unlock_state == ul_cancel) + goto fail; + + responses[i].response = strdup(si->pw_data->typed_passwd); + + /* Cache the first response to a PROMPT_NOECHO to save prompting for + * each auth mechanism. */ + if (si->cached_passwd == NULL && + auth_msgs[i].type == AUTH_MSGTYPE_PROMPT_NOECHO) + si->cached_passwd = strdup(responses[i].response); + + free (compose_status); + compose_status = 0; + } + + *resp = responses; + + return (si->unlock_state == ul_finished) ? 0 : -1; + +fail: + if (compose_status) + free (compose_status); + compose_status = 0; + + if (responses) + { + for (i = 0; i < num_msg; ++i) + if (responses[i].response) + free (responses[i].response); + free (responses); + } + + return -1; +} + + +void +auth_finished_cb (saver_info *si) +{ + char buf[1024]; + const char *s; + + /* If we have something to say, put the dialog back up for a few seconds + to display it. Otherwise, don't bother. + */ + + if (si->unlock_state == ul_fail && /* failed with caps lock on */ + si->pw_data && si->pw_data->caps_p) + s = "Authentication failed (Caps Lock?)"; + else if (si->unlock_state == ul_fail) /* failed without caps lock */ + s = "Authentication failed!"; + else if (si->unlock_state == ul_success && /* good, but report failures */ + si->unlock_failures > 0) + { + if (si->unlock_failures == 1) + s = "There has been\n1 failed login attempt."; + else + { + sprintf (buf, "There have been\n%d failed login attempts.", + si->unlock_failures); + s = buf; + } + si->unlock_failures = 0; + } + else /* good, with no failures, */ + goto END; /* or timeout, or cancel. */ + + make_passwd_window (si, s, NULL, True); + XSync (si->dpy, False); + + { + int secs = 4; + time_t start = time ((time_t *) 0); + XEvent event; + while (time ((time_t *) 0) < start + secs) + if (XPending (si->dpy)) + { + XNextEvent (si->dpy, &event); + if (event.xany.window == si->passwd_dialog && + event.xany.type == Expose) + draw_passwd_window (si); + else if (event.xany.type == ButtonPress || + event.xany.type == KeyPress) + break; + XSync (si->dpy, False); + } + else + usleep (250000); /* 1/4 second */ + } + + END: + if (si->pw_data) + destroy_passwd_window (si); +} + + +Bool +unlock_p (saver_info *si) +{ + saver_preferences *p = &si->prefs; + + if (!si->unlock_cb) + { + fprintf(stderr, "%s: Error: no unlock function specified!\n", blurb()); + return False; + } + + raise_window (si, True, True, True); + + xss_authenticate(si, p->verbose_p); + + return (si->unlock_state == ul_success); +} + + +void +set_locked_p (saver_info *si, Bool locked_p) +{ + si->locked_p = locked_p; + +#ifdef HAVE_XHPDISABLERESET + hp_lock_reset (si, locked_p); /* turn off/on C-Sh-Reset */ +#endif +#ifdef HAVE_XF86VMODE + xfree_lock_mode_switch (si, locked_p); /* turn off/on C-Alt-Plus */ +#endif +#ifdef HAVE_XF86MISCSETGRABKEYSSTATE + xfree_lock_grab_smasher (si, locked_p); /* turn off/on C-Alt-KP-*,/ */ +#endif + + store_saver_status (si); /* store locked-p */ +} + + +#else /* NO_LOCKING -- whole file */ + +void +set_locked_p (saver_info *si, Bool locked_p) +{ + if (locked_p) abort(); +} + +#endif /* !NO_LOCKING */ diff --git a/driver/mlstring.c b/driver/mlstring.c new file mode 100644 index 00000000..fdba1ee5 --- /dev/null +++ b/driver/mlstring.c @@ -0,0 +1,229 @@ +/* + * (c) 2007, Quest Software, Inc. All rights reserved. + * + * This file is part of XScreenSaver, + * Copyright (c) 1993-2009 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. + */ + +#include +#include + +#include + +#include "mlstring.h" + +#define LINE_SPACING 1.2 + +static mlstring * +mlstring_allocate(const char *msg); + +static void +mlstring_calculate(mlstring *str, XFontStruct *font); + +mlstring* +mlstring_new(const char *msg, XFontStruct *font, Dimension wrap_width) +{ + mlstring *newstr; + + if (!(newstr = mlstring_allocate(msg))) + return NULL; + + newstr->font_id = font->fid; + + mlstring_wrap(newstr, font, wrap_width); + + return newstr; +} + +mlstring * +mlstring_allocate(const char *msg) +{ + const char *s; + mlstring *ml; + struct mlstr_line *cur, *prev = NULL; + size_t linelength; + int the_end = 0; + + if (!msg) + return NULL; + + ml = calloc(1, sizeof(mlstring)); + + if (!ml) + return NULL; + + for (s = msg; !the_end; msg = ++s) + { + /* New string struct */ + cur = calloc(1, sizeof(struct mlstr_line)); + if (!cur) + goto fail; + + if (!ml->lines) + ml->lines = cur; + + /* Find the \n or end of string */ + while (*s != '\n') + { + if (*s == '\0') + { + the_end = 1; + break; + } + + ++s; + } + + linelength = s - msg; + + /* Duplicate the string */ + cur->line = malloc(linelength + 1); + if (!cur->line) + goto fail; + + strncpy(cur->line, msg, linelength); + cur->line[linelength] = '\0'; + + if (prev) + prev->next_line = cur; + prev = cur; + } + + return ml; + +fail: + + if (ml) + mlstring_free(ml); + + return NULL; +} + + +/* + * Frees an mlstring. + * This function does not have any unit tests. + */ +void +mlstring_free(mlstring *str) { + struct mlstr_line *cur, *next; + + for (cur = str->lines; cur; cur = next) { + next = cur->next_line; + free(cur->line); + free(cur); + } + + free(str); +} + + +void +mlstring_wrap(mlstring *mstring, XFontStruct *font, Dimension width) +{ + short char_width = font->max_bounds.width; + int line_length, wrap_at; + struct mlstr_line *mstr, *newml; + + /* An alternative implementation of this function would be to keep trying + * XTextWidth() on space-delimited substrings until the longest one less + * than 'width' is found, however there shouldn't be much difference + * between that, and this implementation. + */ + + for (mstr = mstring->lines; mstr; mstr = mstr->next_line) + { + if (XTextWidth(font, mstr->line, strlen(mstr->line)) > width) + { + /* Wrap it */ + line_length = width / char_width; + if (line_length == 0) + line_length = 1; + + /* First try to soft wrap by finding a space */ + for (wrap_at = line_length; wrap_at >= 0 && !isspace(mstr->line[wrap_at]); --wrap_at); + + if (wrap_at == -1) /* No space found, hard wrap */ + wrap_at = line_length; + else + wrap_at++; /* Leave the space at the end of the line. */ + + newml = calloc(1, sizeof(*newml)); + if (!newml) /* OOM, don't bother trying to wrap */ + break; + + if (NULL == (newml->line = strdup(mstr->line + wrap_at))) + { + /* OOM, jump ship */ + free(newml); + break; + } + + /* Terminate the existing string at its end */ + mstr->line[wrap_at] = '\0'; + + newml->next_line = mstr->next_line; + mstr->next_line = newml; + } + } + + mlstring_calculate(mstring, font); +} + +#undef MAX +#define MAX(x, y) ((x) > (y) ? (x) : (y)) + +/* + * Calculates the overall extents (width + height of the multi-line string). + * This function is called as part of mlstring_new(). + * It does not have any unit testing. + */ +void +mlstring_calculate(mlstring *str, XFontStruct *font) { + struct mlstr_line *line; + + str->font_height = font->ascent + font->descent; + str->overall_height = 0; + str->overall_width = 0; + + /* XXX: Should there be some baseline calculations to help XDrawString later on? */ + str->font_ascent = font->ascent; + + for (line = str->lines; line; line = line->next_line) + { + line->line_width = XTextWidth(font, line->line, strlen(line->line)); + str->overall_width = MAX(str->overall_width, line->line_width); + /* Don't add line spacing for the first line */ + str->overall_height += (font->ascent + font->descent) * + (line == str->lines ? 1 : LINE_SPACING); + } +} + +void +mlstring_draw(Display *dpy, Drawable dialog, GC gc, mlstring *string, int x, int y) { + struct mlstr_line *line; + + if (!string) + return; + + y += string->font_ascent; + + XSetFont(dpy, gc, string->font_id); + + for (line = string->lines; line; line = line->next_line) + { + XDrawString(dpy, dialog, gc, x, y, line->line, strlen(line->line)); + y += string->font_height * LINE_SPACING; + } +} + +/* vim:ts=8:sw=2:noet + */ diff --git a/driver/mlstring.h b/driver/mlstring.h new file mode 100644 index 00000000..ce362056 --- /dev/null +++ b/driver/mlstring.h @@ -0,0 +1,57 @@ +/* mlstring.h --- Multi-line strings for use with Xlib + * + * (c) 2007, Quest Software, Inc. All rights reserved. + * + * This file is part of XScreenSaver, + * Copyright (c) 1993-2004 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. + */ +#ifndef MLSTRING_H +#define MLSTRING_H + +#include + +/* mlstring means multi-line string */ + +struct mlstr_line; + +typedef struct mlstring mlstring; +struct mlstring { + struct mlstr_line *lines; /* linked list */ + Dimension overall_height; + Dimension overall_width; + /* XXX: Perhaps it is simpler to keep a reference to the XFontStruct */ + int font_ascent; + int font_height; + Font font_id; +}; + +struct mlstr_line { + char *line; + Dimension line_width; + struct mlstr_line *next_line; +}; + +mlstring * +mlstring_new(const char *str, XFontStruct *font, Dimension wrap_width); + +/* Does not have to be called manually */ +void +mlstring_wrap(mlstring *mstr, XFontStruct *font, Dimension width); + +void +mlstring_free(mlstring *str); + +void +mlstring_draw(Display *dpy, Drawable dialog, GC gc, mlstring *string, int x, int y); + +#endif +/* vim:ts=8:sw=2:noet + */ diff --git a/driver/passwd-helper.c b/driver/passwd-helper.c new file mode 100644 index 00000000..a3a6b924 --- /dev/null +++ b/driver/passwd-helper.c @@ -0,0 +1,162 @@ +/* passwd-helper.c --- verifying typed passwords with external helper program + * written by Olaf Kirch + * xscreensaver, Copyright (c) 1993-2005 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. + */ + +/* The idea here is to be able to run xscreensaver without any setuid bits. + * Password verification happens through an external program that you feed + * your password to on stdin. The external command is invoked with a user + * name argument. + * + * The external helper does whatever authentication is necessary. Currently, + * SuSE uses "unix2_chkpwd", which is a variation of "unix_chkpwd" from the + * PAM distribution. + * + * Normally, the password helper should just authenticate the calling user + * (i.e. based on the caller's real uid). This is in order to prevent + * brute-forcing passwords in a shadow environment. A less restrictive + * approach would be to allow verifying other passwords as well, but always + * with a 2 second delay or so. (Not sure what SuSE's "unix2_chkpwd" + * currently does.) + * -- Olaf Kirch , 16-Dec-2003 + */ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#ifndef NO_LOCKING /* whole file */ + +#include /* not used for much... */ + +/* This file doesn't need the Xt headers, so stub these types out... */ +#undef XtPointer +#define XtAppContext void* +#define XrmDatabase void* +#define XtIntervalId void* +#define XtPointer void* +#define Widget void* + +#include "xscreensaver.h" + +#include +#ifdef HAVE_UNISTD_H +# include +#endif + +#include +#include +#include +#include +#include + +#include + +static int +ext_run (const char *user, const char *typed_passwd, int verbose_p) +{ + int pfd[2], status; + pid_t pid; + + if (pipe(pfd) < 0) + return 0; + + if (verbose_p) + fprintf (stderr, "%s: ext_run (%s, %s)\n", + blurb(), PASSWD_HELPER_PROGRAM, user); + + block_sigchld(); + + if ((pid = fork()) < 0) { + close(pfd[0]); + close(pfd[1]); + return 0; + } + + if (pid == 0) { + close(pfd[1]); + if (pfd[0] != 0) + dup2(pfd[0], 0); + + /* Helper is invoked as helper service-name [user] */ + execlp(PASSWD_HELPER_PROGRAM, PASSWD_HELPER_PROGRAM, "xscreensaver", user, NULL); + if (verbose_p) + fprintf(stderr, "%s: %s\n", PASSWD_HELPER_PROGRAM, + strerror(errno)); + exit(1); + } + + close(pfd[0]); + + /* Write out password to helper process */ + if (!typed_passwd) + typed_passwd = ""; + write(pfd[1], typed_passwd, strlen(typed_passwd)); + close(pfd[1]); + + while (waitpid(pid, &status, 0) < 0) { + if (errno == EINTR) + continue; + if (verbose_p) + fprintf(stderr, "%s: ext_run: waitpid failed: %s\n", + blurb(), strerror(errno)); + unblock_sigchld(); + return 0; + } + + unblock_sigchld(); + + if (!WIFEXITED(status) || WEXITSTATUS(status) != 0) + return 0; + return 1; +} + + + +/* This can be called at any time, and says whether the typed password + belongs to either the logged in user (real uid, not effective); or + to root. + */ +int +ext_passwd_valid_p (const char *typed_passwd, int verbose_p) +{ + struct passwd *pw; + int res = 0; + + if ((pw = getpwuid(getuid())) != NULL) + res = ext_run (pw->pw_name, typed_passwd, verbose_p); + endpwent(); + +#ifdef ALLOW_ROOT_PASSWD + if (!res) + res = ext_run ("root", typed_passwd, verbose_p); +#endif /* ALLOW_ROOT_PASSWD */ + + return res; +} + + +int +ext_priv_init (int argc, char **argv, int verbose_p) +{ + /* Make sure the passwd helper exists */ + if (access(PASSWD_HELPER_PROGRAM, X_OK) < 0) { + fprintf(stderr, + "%s: warning: %s does not exist.\n" + "%s: password authentication via " + "external helper will not work.\n", + blurb(), PASSWD_HELPER_PROGRAM, blurb()); + return 0; + } + return 1; +} + +#endif /* NO_LOCKING -- whole file */ diff --git a/driver/passwd-kerberos.c b/driver/passwd-kerberos.c new file mode 100644 index 00000000..202e0eb1 --- /dev/null +++ b/driver/passwd-kerberos.c @@ -0,0 +1,251 @@ +/* kpasswd.c --- verify kerberos passwords. + * written by Nat Lanza (magus@cs.cmu.edu) for + * xscreensaver, Copyright (c) 1993-2004 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. + */ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#ifndef NO_LOCKING /* whole file */ + +#include +#ifdef HAVE_UNISTD_H +# include +#endif + +#include +#include +#include +#include + +/* I'm not sure if this is exactly the right test... + Might __APPLE__ be defined if this is apple hardware, but not + an Apple OS? + + Thanks to Alexei Kosut for the MacOS X code. + */ +#ifdef __APPLE__ +# define HAVE_DARWIN +#endif + + +#if defined(HAVE_DARWIN) +# include +#elif defined(HAVE_KERBEROS5) +# include +# include +#else /* !HAVE_KERBEROS5 (meaning Kerberos 4) */ +# include +# include +#endif /* !HAVE_KERBEROS5 */ + +#if !defined(VMS) && !defined(HAVE_ADJUNCT_PASSWD) +# include +#endif + + +#ifdef __bsdi__ +# include +# if _BSDI_VERSION >= 199608 +# define BSD_AUTH +# endif +#endif /* __bsdi__ */ + +/* blargh */ +#undef Bool +#undef True +#undef False +#define Bool int +#define True 1 +#define False 0 + +/* The user information we need to store */ +#ifdef HAVE_DARWIN + static KLPrincipal princ; +#else /* !HAVE_DARWIN */ + static char realm[REALM_SZ]; + static char name[ANAME_SZ]; + static char inst[INST_SZ]; + static const char *tk_file; +#endif /* !HAVE_DARWIN */ + +/* warning suppression: duplicated in passwd.c */ +extern Bool kerberos_lock_init (int argc, char **argv, Bool verbose_p); +extern Bool kerberos_passwd_valid_p (const char *typed_passwd, Bool verbose_p); + + +/* Called at startup to grab user, instance, and realm information + from the user's ticketfile (remember, name.inst@realm). Since we're + using tf_get_pname(), this should work even if your kerberos username + isn't the same as your local username. We grab the ticket at startup + time so that even if your ticketfile dies while the screen's locked + we'll still have the information to unlock it. + + Problems: the password dialog currently displays local username, so if + you have some non-standard name/instance when you run xscreensaver, + you'll need to remember what it was when unlocking, or else you lose. + + Also, we use des_string_to_key(), so if you have an AFS password + (encrypted with ka_StringToKey()), you'll lose. Get a kerberos password; + it isn't that hard. + + Like the original lock_init, we return false if something went wrong. + We don't use the arguments we're given, though. + */ +Bool +kerberos_lock_init (int argc, char **argv, Bool verbose_p) +{ +# ifdef HAVE_DARWIN + + KLBoolean found; + return ((klNoErr == (KLCacheHasValidTickets (NULL, kerberosVersion_Any, + &found, &princ, NULL))) + && found); + +# else /* !HAVE_DARWIN */ + + /* Perhaps we should be doing it the Mac way (above) all the time? + The following code assumes Unix-style file-based Kerberos credentials + cache, which Mac OS X doesn't use. But is there any real reason to + do it this way at all, even on other Unixen? + */ + int k_errno; + + memset(name, 0, sizeof(name)); + memset(inst, 0, sizeof(inst)); + + /* find out where the user's keeping his tickets. + squirrel it away for later use. */ + tk_file = tkt_string(); + + /* open ticket file or die trying. */ + if ((k_errno = tf_init(tk_file, R_TKT_FIL))) { + return False; + } + + /* same with principal and instance names */ + if ((k_errno = tf_get_pname(name)) || + (k_errno = tf_get_pinst(inst))) { + return False; + } + + /* close the ticketfile to release the lock on it. */ + tf_close(); + + /* figure out what realm we're authenticated to. this ought + to be the local realm, but it pays to be sure. */ + if ((k_errno = krb_get_tf_realm(tk_file, realm))) { + return False; + } + + /* last-minute sanity check on what we got. */ + if ((strlen(name)+strlen(inst)+strlen(realm)+3) > + (REALM_SZ + ANAME_SZ + INST_SZ + 3)) { + return False; + } + + /* success */ + return True; + +# endif /* !HAVE_DARWIN */ +} + + +/* des_string_to_key() wants this. If C didn't suck, we could have an + anonymous function do this. Even a local one. But it does, so here + we are. Calling it ive_got_your_local_function_right_here_buddy() + would have been rude. + */ +#ifndef HAVE_DARWIN +static int +key_to_key(char *user, char *instance, char *realm, char *passwd, C_Block key) +{ + memcpy(key, passwd, sizeof(des_cblock)); + return (0); +} +#endif /* !HAVE_DARWIN */ + +/* Called to see if the user's typed password is valid. We do this by asking + the kerberos server for a ticket and checking to see if it gave us one. + We need to move the ticketfile first, or otherwise we end up updating the + user's tkfile with new tickets. This would break services like zephyr that + like to stay authenticated, and it would screw with AFS authentication at + some sites. So, we do a quick, painful hack with a tmpfile. + */ +Bool +kerberos_passwd_valid_p (const char *typed_passwd, Bool verbose_p) +{ +# ifdef HAVE_DARWIN + return (klNoErr == + KLAcquireNewInitialTicketsWithPassword (princ, NULL, + typed_passwd, NULL)); +# else /* !HAVE_DARWIN */ + + /* See comments in kerberos_lock_init -- should we do it the Mac Way + on all systems? + */ + C_Block mitkey; + Bool success; + char *newtkfile; + int fh = -1; + + /* temporarily switch to a new ticketfile. + I'm not using tmpnam() because it isn't entirely portable. + this could probably be fixed with autoconf. */ + newtkfile = malloc(80 * sizeof(char)); + memset(newtkfile, 0, sizeof(newtkfile)); + + sprintf(newtkfile, "/tmp/xscrn-%i.XXXXXX", getpid()); + + if( (fh = mkstemp(newtkfile)) < 0) + { + free(newtkfile); + return(False); + } + if( fchmod(fh, 0600) < 0) + { + free(newtkfile); + return(False); + } + + + krb_set_tkt_string(newtkfile); + + /* encrypt the typed password. if you have an AFS password instead + of a kerberos one, you lose *right here*. If you want to use AFS + passwords, you can use ka_StringToKey() instead. As always, ymmv. */ + des_string_to_key(typed_passwd, mitkey); + + if (krb_get_in_tkt(name, inst, realm, "krbtgt", realm, DEFAULT_TKT_LIFE, + key_to_key, NULL, (char *) mitkey) != 0) { + success = False; + } else { + success = True; + } + + /* quickly block out the tempfile and password to prevent snooping, + then restore the old ticketfile and cleean up a bit. */ + + dest_tkt(); + krb_set_tkt_string(tk_file); + free(newtkfile); + memset(mitkey, 0, sizeof(mitkey)); + close(fh); /* #### tom: should the file be removed? */ + + + /* Did we verify successfully? */ + return success; + +# endif /* !HAVE_DARWIN */ +} + +#endif /* NO_LOCKING -- whole file */ diff --git a/driver/passwd-pam.c b/driver/passwd-pam.c new file mode 100644 index 00000000..0c60d508 --- /dev/null +++ b/driver/passwd-pam.c @@ -0,0 +1,514 @@ +/* passwd-pam.c --- verifying typed passwords with PAM + * (Pluggable Authentication Modules.) + * written by Bill Nottingham (and jwz) for + * xscreensaver, Copyright (c) 1993-2012 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. + * + * Some PAM resources: + * + * PAM home page: + * http://www.us.kernel.org/pub/linux/libs/pam/ + * + * PAM FAQ: + * http://www.us.kernel.org/pub/linux/libs/pam/FAQ + * + * PAM Application Developers' Guide: + * http://www.us.kernel.org/pub/linux/libs/pam/Linux-PAM-html/Linux-PAM_ADG.html + * + * PAM Mailing list archives: + * http://www.linuxhq.com/lnxlists/linux-pam/ + * + * Compatibility notes, especially between Linux and Solaris: + * http://www.contrib.andrew.cmu.edu/u/shadow/pam.html + * + * The Open Group's PAM API documentation: + * http://www.opengroup.org/onlinepubs/8329799/pam_start.htm + */ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#ifndef NO_LOCKING /* whole file */ + +#include +#ifdef HAVE_UNISTD_H +# include +#endif + +extern char *blurb(void); + + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include "auth.h" + +extern sigset_t block_sigchld (void); +extern void unblock_sigchld (void); + +/* blargh */ +#undef Bool +#undef True +#undef False +#define Bool int +#define True 1 +#define False 0 + +#undef countof +#define countof(x) (sizeof((x))/sizeof(*(x))) + +/* Some time between Red Hat 4.2 and 7.0, the words were transposed + in the various PAM_x_CRED macro names. Yay! + */ +#ifndef PAM_REFRESH_CRED +# define PAM_REFRESH_CRED PAM_CRED_REFRESH +#endif + +static int pam_conversation (int nmsgs, + const struct pam_message **msg, + struct pam_response **resp, + void *closure); + +void pam_try_unlock(saver_info *si, Bool verbose_p, + Bool (*valid_p)(const char *typed_passwd, Bool verbose_p)); + +Bool pam_priv_init (int argc, char **argv, Bool verbose_p); + +#ifdef HAVE_PAM_FAIL_DELAY + /* We handle delays ourself.*/ + /* Don't set this to 0 (Linux bug workaround.) */ +# define PAM_NO_DELAY(pamh) pam_fail_delay ((pamh), 1) +#else /* !HAVE_PAM_FAIL_DELAY */ +# define PAM_NO_DELAY(pamh) /* */ +#endif /* !HAVE_PAM_FAIL_DELAY */ + + +/* On SunOS 5.6, and on Linux with PAM 0.64, pam_strerror() takes two args. + On some other Linux systems with some other version of PAM (e.g., + whichever Debian release comes with a 2.2.5 kernel) it takes one arg. + I can't tell which is more "recent" or "correct" behavior, so configure + figures out which is in use for us. Shoot me! + */ +#ifdef PAM_STRERROR_TWO_ARGS +# define PAM_STRERROR(pamh, status) pam_strerror((pamh), (status)) +#else /* !PAM_STRERROR_TWO_ARGS */ +# define PAM_STRERROR(pamh, status) pam_strerror((status)) +#endif /* !PAM_STRERROR_TWO_ARGS */ + + +/* PAM sucks in that there is no way to tell whether a particular service + is configured at all. That is, there is no way to tell the difference + between "authentication of the FOO service is not allowed" and "the + user typed the wrong password." + + On RedHat 5.1 systems, if a service name is not known, it defaults to + being not allowed (because the fallback service, /etc/pam.d/other, is + set to `pam_deny'.) + + On Solaris 2.6 systems, unknown services default to authenticating normally. + + So, we could simply require that the person who installs xscreensaver + set up an "xscreensaver" PAM service. However, if we went that route, + it would have a really awful failure mode: the failure mode would be that + xscreensaver was willing to *lock* the screen, but would be unwilling to + *unlock* the screen. (With the non-PAM password code, the analagous + situation -- security not being configured properly, for example do to the + executable not being installed as setuid root -- the failure mode is much + more palettable, in that xscreensaver will refuse to *lock* the screen, + because it can know up front that there is no password that will work.) + + Another route would be to have the service name to consult be computed at + compile-time (perhaps with a configure option.) However, that doesn't + really solve the problem, because it means that the same executable might + work fine on one machine, but refuse to unlock when run on another + machine. + + Another alternative would be to look in /etc/pam.conf or /etc/pam.d/ at + runtime to see what services actually exist. But I think that's no good, + because who is to say that the PAM info is actually specified in those + files? Opening and reading those files is not a part of the PAM client + API, so it's not guarenteed to work on any given system. + + An alternative I tried was to specify a list of services to try, and to + try them all in turn ("xscreensaver", "xlock", "xdm", and "login"). + This worked, but it was slow (and I also had to do some contortions to + work around bugs in Linux PAM 0.64-3.) + + So what we do today is, try PAM once, and if that fails, try the usual + getpwent() method. So if PAM doesn't work, it will at least make an + attempt at looking up passwords in /etc/passwd or /etc/shadow instead. + + This all kind of blows. I'm not sure what else to do. + */ + + +/* On SunOS 5.6, the `pam_conv.appdata_ptr' slot seems to be ignored, and + the `closure' argument to pc.conv always comes in as random garbage. + So we get around this by using a global variable instead. Shoot me! + + (I've been told this is bug 4092227, and is fixed in Solaris 7.) + (I've also been told that it's fixed in Solaris 2.6 by patch 106257-05.) + */ +static void *suns_pam_implementation_blows = 0; + + +/** + * This function is the PAM conversation driver. It conducts a full + * authentication round by invoking the GUI with various prompts. + */ +void +pam_try_unlock(saver_info *si, Bool verbose_p, + Bool (*valid_p)(const char *typed_passwd, Bool verbose_p)) +{ + const char *service = PAM_SERVICE_NAME; + pam_handle_t *pamh = 0; + int status = -1; + struct pam_conv pc; + sigset_t set; + struct timespec timeout; + + pc.conv = &pam_conversation; + pc.appdata_ptr = (void *) si; + + /* On SunOS 5.6, the `appdata_ptr' slot seems to be ignored, and the + `closure' argument to pc.conv always comes in as random garbage. */ + suns_pam_implementation_blows = (void *) si; + + + /* Initialize PAM. + */ + status = pam_start (service, si->user, &pc, &pamh); + if (verbose_p) + fprintf (stderr, "%s: pam_start (\"%s\", \"%s\", ...) ==> %d (%s)\n", + blurb(), service, si->user, + status, PAM_STRERROR (pamh, status)); + if (status != PAM_SUCCESS) goto DONE; + + /* #### We should set PAM_TTY to the display we're using, but we + don't have that handy from here. So set it to :0.0, which is a + good guess (and has the bonus of counting as a "secure tty" as + far as PAM is concerned...) + */ + { + char *tty = strdup (":0.0"); + status = pam_set_item (pamh, PAM_TTY, tty); + if (verbose_p) + fprintf (stderr, "%s: pam_set_item (p, PAM_TTY, \"%s\") ==> %d (%s)\n", + blurb(), tty, status, PAM_STRERROR(pamh, status)); + free (tty); + } + + /* Try to authenticate as the current user. + We must turn off our SIGCHLD handler for the duration of the call to + pam_authenticate(), because in some cases, the underlying PAM code + will do this: + + 1: fork a setuid subprocess to do some dirty work; + 2: read a response from that subprocess; + 3: waitpid(pid, ...) on that subprocess. + + If we (the ignorant parent process) have a SIGCHLD handler, then there's + a race condition between steps 2 and 3: if the subprocess exits before + waitpid() was called, then our SIGCHLD handler fires, and gets notified + of the subprocess death; then PAM's call to waitpid() fails, because the + process has already been reaped. + + I consider this a bug in PAM, since the caller should be able to have + whatever signal handlers it wants -- the PAM documentation doesn't say + "oh by the way, if you use PAM, you can't use SIGCHLD." + */ + + PAM_NO_DELAY(pamh); + + if (verbose_p) + fprintf (stderr, "%s: pam_authenticate (...) ...\n", blurb()); + + timeout.tv_sec = 0; + timeout.tv_nsec = 1; + set = block_sigchld(); + status = pam_authenticate (pamh, 0); +# ifdef HAVE_SIGTIMEDWAIT + sigtimedwait (&set, NULL, &timeout); + /* #### What is the portable thing to do if we don't have it? */ +# endif /* HAVE_SIGTIMEDWAIT */ + unblock_sigchld(); + + if (verbose_p) + fprintf (stderr, "%s: pam_authenticate (...) ==> %d (%s)\n", + blurb(), status, PAM_STRERROR(pamh, status)); + + if (status == PAM_SUCCESS) /* Win! */ + { + int status2; + + /* On most systems, it doesn't matter whether the account modules + are run, or whether they fail or succeed. + + On some systems, the account modules fail, because they were + never configured properly, but it's necessary to run them anyway + because certain PAM modules depend on side effects of the account + modules having been run. + + And on still other systems, the account modules are actually + used, and failures in them should be considered to be true! + + So: + - We run the account modules on all systems. + - Whether we ignore them is a configure option. + + It's all kind of a mess. + */ + status2 = pam_acct_mgmt (pamh, 0); + + if (verbose_p) + fprintf (stderr, "%s: pam_acct_mgmt (...) ==> %d (%s)\n", + blurb(), status2, PAM_STRERROR(pamh, status2)); + + /* HPUX for some reason likes to make PAM defines different from + * everyone else's. */ +#ifdef PAM_AUTHTOKEN_REQD + if (status2 == PAM_AUTHTOKEN_REQD) +#else + if (status2 == PAM_NEW_AUTHTOK_REQD) +#endif + { + status2 = pam_chauthtok (pamh, PAM_CHANGE_EXPIRED_AUTHTOK); + if (verbose_p) + fprintf (stderr, "%s: pam_chauthtok (...) ==> %d (%s)\n", + blurb(), status2, PAM_STRERROR(pamh, status2)); + } + + /* If 'configure' requested that we believe the results of PAM + account module failures, then obey that status code. + Otherwise ignore it. + */ +#ifdef PAM_CHECK_ACCOUNT_TYPE + status = status2; +#endif + + /* Each time we successfully authenticate, refresh credentials, + for Kerberos/AFS/DCE/etc. If this fails, just ignore that + failure and blunder along; it shouldn't matter. + + Note: this used to be PAM_REFRESH_CRED instead of + PAM_REINITIALIZE_CRED, but Jason Heiss + says that the Linux PAM library ignores that one, and only refreshes + credentials when using PAM_REINITIALIZE_CRED. + */ + status2 = pam_setcred (pamh, PAM_REINITIALIZE_CRED); + if (verbose_p) + fprintf (stderr, "%s: pam_setcred (...) ==> %d (%s)\n", + blurb(), status2, PAM_STRERROR(pamh, status2)); + } + + DONE: + if (pamh) + { + int status2 = pam_end (pamh, status); + pamh = 0; + if (verbose_p) + fprintf (stderr, "%s: pam_end (...) ==> %d (%s)\n", + blurb(), status2, + (status2 == PAM_SUCCESS ? "Success" : "Failure")); + } + + if (status == PAM_SUCCESS) + si->unlock_state = ul_success; /* yay */ + else if (si->unlock_state == ul_cancel || + si->unlock_state == ul_time) + ; /* more specific failures ok */ + else + si->unlock_state = ul_fail; /* generic failure */ +} + + +Bool +pam_priv_init (int argc, char **argv, Bool verbose_p) +{ + /* We have nothing to do at init-time. + However, we might as well do some error checking. + If "/etc/pam.d" exists and is a directory, but "/etc/pam.d/xlock" + does not exist, warn that PAM probably isn't going to work. + + This is a priv-init instead of a non-priv init in case the directory + is unreadable or something (don't know if that actually happens.) + */ + const char dir[] = "/etc/pam.d"; + const char file[] = "/etc/pam.d/" PAM_SERVICE_NAME; + const char file2[] = "/etc/pam.conf"; + struct stat st; + +# ifndef S_ISDIR +# define S_ISDIR(mode) (((mode) & S_IFMT) == S_IFDIR) +# endif + + if (stat (dir, &st) == 0 && S_ISDIR(st.st_mode)) + { + if (stat (file, &st) != 0) + fprintf (stderr, + "%s: warning: %s does not exist.\n" + "%s: password authentication via PAM is unlikely to work.\n", + blurb(), file, blurb()); + } + else if (stat (file2, &st) == 0) + { + FILE *f = fopen (file2, "r"); + if (f) + { + Bool ok = False; + char buf[255]; + while (fgets (buf, sizeof(buf), f)) + if (strstr (buf, PAM_SERVICE_NAME)) + { + ok = True; + break; + } + fclose (f); + if (!ok) + { + fprintf (stderr, + "%s: warning: %s does not list the `%s' service.\n" + "%s: password authentication via PAM is unlikely to work.\n", + blurb(), file2, PAM_SERVICE_NAME, blurb()); + } + } + /* else warn about file2 existing but being unreadable? */ + } + else + { + fprintf (stderr, + "%s: warning: neither %s nor %s exist.\n" + "%s: password authentication via PAM is unlikely to work.\n", + blurb(), file2, file, blurb()); + } + + /* Return true anyway, just in case. */ + return True; +} + + +static int +pam_conversation (int nmsgs, + const struct pam_message **msg, + struct pam_response **resp, + void *vsaver_info) +{ + int i, ret = -1; + struct auth_message *messages = 0; + struct auth_response *authresp = 0; + struct pam_response *pam_responses; + saver_info *si = (saver_info *) vsaver_info; + Bool verbose_p; + + /* On SunOS 5.6, the `closure' argument always comes in as random garbage. */ + si = (saver_info *) suns_pam_implementation_blows; + + verbose_p = si->prefs.verbose_p; + + /* Converting the PAM prompts into the XScreenSaver native format. + * It was a design goal to collapse (INFO,PROMPT) pairs from PAM + * into a single call to the unlock_cb function. The unlock_cb function + * does that, but only if it is passed several prompts at a time. Most PAM + * modules only send a single prompt at a time, but because there is no way + * of telling whether there will be more prompts to follow, we can only ever + * pass along whatever was passed in here. + */ + + messages = calloc(nmsgs, sizeof(struct auth_message)); + pam_responses = calloc(nmsgs, sizeof(*pam_responses)); + + if (!pam_responses || !messages) + goto end; + + if (verbose_p) + fprintf (stderr, "%s: pam_conversation (", blurb()); + + for (i = 0; i < nmsgs; ++i) + { + if (verbose_p && i > 0) fprintf (stderr, ", "); + + messages[i].msg = msg[i]->msg; + + switch (msg[i]->msg_style) { + case PAM_PROMPT_ECHO_OFF: messages[i].type = AUTH_MSGTYPE_PROMPT_NOECHO; + if (verbose_p) fprintf (stderr, "ECHO_OFF"); + break; + case PAM_PROMPT_ECHO_ON: messages[i].type = AUTH_MSGTYPE_PROMPT_ECHO; + if (verbose_p) fprintf (stderr, "ECHO_ON"); + break; + case PAM_ERROR_MSG: messages[i].type = AUTH_MSGTYPE_ERROR; + if (verbose_p) fprintf (stderr, "ERROR_MSG"); + break; + case PAM_TEXT_INFO: messages[i].type = AUTH_MSGTYPE_INFO; + if (verbose_p) fprintf (stderr, "TEXT_INFO"); + break; + default: messages[i].type = AUTH_MSGTYPE_PROMPT_ECHO; + if (verbose_p) fprintf (stderr, "PROMPT_ECHO"); + break; + } + + if (verbose_p) + fprintf (stderr, "=\"%s\"", msg[i]->msg ? msg[i]->msg : "(null)"); + } + + if (verbose_p) + fprintf (stderr, ") ...\n"); + + ret = si->unlock_cb(nmsgs, messages, &authresp, si); + + /* #### If the user times out, or hits ESC or Cancel, we return PAM_CONV_ERR, + and PAM logs this as an authentication failure. It would be nice if + there was some way to indicate that this was a "cancel" rather than + a "fail", so that it wouldn't show up in syslog, but I think the + only options are PAM_SUCCESS and PAM_CONV_ERR. (I think that + PAM_ABORT means "internal error", not "cancel".) Bleh. + */ + + if (ret == 0) + { + for (i = 0; i < nmsgs; ++i) + pam_responses[i].resp = authresp[i].response; + } + +end: + if (messages) + free(messages); + + if (authresp) + free(authresp); + + if (verbose_p) + fprintf (stderr, "%s: pam_conversation (...) ==> %s\n", blurb(), + (ret == 0 ? "PAM_SUCCESS" : "PAM_CONV_ERR")); + + if (ret == 0) + { + *resp = pam_responses; + return PAM_SUCCESS; + } + + /* Failure only */ + if (pam_responses) + free(pam_responses); + + return PAM_CONV_ERR; +} + +#endif /* NO_LOCKING -- whole file */ diff --git a/driver/passwd-pwent.c b/driver/passwd-pwent.c new file mode 100644 index 00000000..bb0edfc2 --- /dev/null +++ b/driver/passwd-pwent.c @@ -0,0 +1,312 @@ +/* passwd-pwent.c --- verifying typed passwords with the OS. + * xscreensaver, Copyright (c) 1993-1998 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. + */ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#ifndef NO_LOCKING /* whole file */ + +#include +#ifdef HAVE_UNISTD_H +# include +#endif + +#ifdef HAVE_CRYPT_H +# include +#endif + +#include +#include +#include +#ifndef VMS +# include +# include +#else /* VMS */ +# include "vms-pwd.h" +#endif /* VMS */ + + +#ifdef __bsdi__ +# include +# if _BSDI_VERSION >= 199608 +# define BSD_AUTH +# endif +#endif /* __bsdi__ */ + + +#if defined(HAVE_SHADOW_PASSWD) /* passwds live in /etc/shadow */ + +# include +# define PWTYPE struct spwd * +# define PWPSLOT sp_pwdp +# define GETPW getspnam + +#elif defined(HAVE_ENHANCED_PASSWD) /* passwds live in /tcb/files/auth/ */ + /* M.Matsumoto */ +# include +# include + +# define PWTYPE struct pr_passwd * +# define PWPSLOT ufld.fd_encrypt +# define GETPW getprpwnam + +#elif defined(HAVE_ADJUNCT_PASSWD) + +# include +# include +# include + +# define PWTYPE struct passwd_adjunct * +# define PWPSLOT pwa_passwd +# define GETPW getpwanam + +#elif defined(HAVE_HPUX_PASSWD) + +# include +# include + +# define PWTYPE struct s_passwd * +# define PWPSLOT pw_passwd +# define GETPW getspwnam + +# define HAVE_BIGCRYPT + +#endif + + +/* blargh */ +#undef Bool +#undef True +#undef False +#define Bool int +#define True 1 +#define False 0 + + +extern const char *blurb(void); + +static char *encrypted_root_passwd = 0; +static char *encrypted_user_passwd = 0; + +#ifdef VMS +# define ROOT "SYSTEM" +#else +# define ROOT "root" +#endif + +#ifndef VMS +Bool pwent_priv_init (int argc, char **argv, Bool verbose_p); +Bool pwent_lock_init (int argc, char **argv, Bool verbose_p); +Bool pwent_passwd_valid_p (const char *typed_passwd, Bool verbose_p); +#endif + + +#ifndef VMS + +static char * +user_name (void) +{ + /* I think that just checking $USER here is not the best idea. */ + + const char *u = 0; + + /* It has been reported that getlogin() returns the wrong user id on some + very old SGI systems... And I've seen it return the string "rlogin" + sometimes! Screw it, using getpwuid() should be enough... + */ +/* u = (char *) getlogin (); + */ + + /* getlogin() fails if not attached to a terminal; in that case, use + getpwuid(). (Note that in this case, we're not doing shadow stuff, since + all we're interested in is the name, not the password. So that should + still work. Right?) */ + if (!u || !*u) + { + struct passwd *p = getpwuid (getuid ()); + u = (p ? p->pw_name : 0); + } + + return (u ? strdup(u) : 0); +} + +#else /* VMS */ + +static char * +user_name (void) +{ + char *u = getenv("USER"); + return (u ? strdup(u) : 0); +} + +#endif /* VMS */ + + +static Bool +passwd_known_p (const char *pw) +{ + return (pw && + pw[0] != '*' && /* This would be sensible... */ + strlen(pw) > 4); /* ...but this is what Solaris does. */ +} + + +static char * +get_encrypted_passwd(const char *user) +{ + char *result = 0; + +#ifdef PWTYPE + if (user && *user && !result) + { /* First check the shadow passwords. */ + PWTYPE p = GETPW((char *) user); + if (p && passwd_known_p (p->PWPSLOT)) + result = strdup(p->PWPSLOT); + } +#endif /* PWTYPE */ + + if (user && *user && !result) + { /* Check non-shadow passwords too. */ + struct passwd *p = getpwnam(user); + if (p && passwd_known_p (p->pw_passwd)) + result = strdup(p->pw_passwd); + } + + /* The manual for passwd(4) on HPUX 10.10 says: + + Password aging is put in effect for a particular user if his + encrypted password in the password file is followed by a comma and + a nonnull string of characters from the above alphabet. This + string defines the "age" needed to implement password aging. + + So this means that passwd->pw_passwd isn't simply a string of cyphertext, + it might have trailing junk. So, if there is a comma in the string, and + that comma is beyond position 13, terminate the string before the comma. + */ + if (result && strlen(result) > 13) + { + char *s = strchr (result+13, ','); + if (s) + *s = 0; + } + +#ifndef HAVE_PAM + /* We only issue this warning if not compiled with support for PAM. + If we're using PAM, it's not unheard of that normal pwent passwords + would be unavailable. */ + + if (!result) + fprintf (stderr, "%s: couldn't get password of \"%s\"\n", + blurb(), (user ? user : "(null)")); +#endif /* !HAVE_PAM */ + + return result; +} + + + +/* This has to be called before we've changed our effective user ID, + because it might need privileges to get at the encrypted passwords. + Returns false if we weren't able to get any passwords, and therefore, + locking isn't possible. (It will also have written to stderr.) + */ + +#ifndef VMS + +Bool +pwent_priv_init (int argc, char **argv, Bool verbose_p) +{ + char *u; + +#ifdef HAVE_ENHANCED_PASSWD + set_auth_parameters(argc, argv); + check_auth_parameters(); +#endif /* HAVE_DEC_ENHANCED */ + + u = user_name(); + encrypted_user_passwd = get_encrypted_passwd(u); + encrypted_root_passwd = get_encrypted_passwd(ROOT); + if (u) free (u); + + if (encrypted_user_passwd) + return True; + else + return False; +} + + +Bool +pwent_lock_init (int argc, char **argv, Bool verbose_p) +{ + if (encrypted_user_passwd) + return True; + else + return False; +} + + + +static Bool +passwds_match_p (const char *cleartext, const char *ciphertext) +{ + char *s = 0; /* note that on some systems, crypt() may return null */ + + s = (char *) crypt (cleartext, ciphertext); + if (s && !strcmp (s, ciphertext)) + return True; + +#ifdef HAVE_BIGCRYPT + /* There seems to be no way to tell at runtime if an HP machine is in + "trusted" mode, and thereby, which of crypt() or bigcrypt() we should + be calling to compare passwords. So call them both, and see which + one works. */ + + s = (char *) bigcrypt (cleartext, ciphertext); + if (s && !strcmp (s, ciphertext)) + return True; + +#endif /* HAVE_BIGCRYPT */ + + return False; +} + + + +/* This can be called at any time, and says whether the typed password + belongs to either the logged in user (real uid, not effective); or + to root. + */ +Bool +pwent_passwd_valid_p (const char *typed_passwd, Bool verbose_p) +{ + if (encrypted_user_passwd && + passwds_match_p (typed_passwd, encrypted_user_passwd)) + return True; + +#ifdef ALLOW_ROOT_PASSWD + /* do not allow root to have a null password. */ + else if (typed_passwd[0] && + encrypted_root_passwd && + passwds_match_p (typed_passwd, encrypted_root_passwd)) + return True; +#endif /* ALLOW_ROOT_PASSWD */ + + else + return False; +} + +#else /* VMS */ +Bool pwent_lock_init (int argc, char **argv, Bool verbose_p) { return True; } +#endif /* VMS */ + +#endif /* NO_LOCKING -- whole file */ diff --git a/driver/passwd.c b/driver/passwd.c new file mode 100644 index 00000000..fd42c552 --- /dev/null +++ b/driver/passwd.c @@ -0,0 +1,334 @@ +/* passwd.c --- verifying typed passwords with the OS. + * xscreensaver, Copyright (c) 1993-2004 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. + */ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#ifndef NO_LOCKING /* whole file */ + +#include +#include +#include +#ifdef HAVE_UNISTD_H +# include +#endif + +#ifndef VMS +# include /* for getpwuid() */ +#else /* VMS */ +# include "vms-pwd.h" +#endif /* VMS */ + +#ifdef HAVE_SYSLOG +# include +#endif /* HAVE_SYSLOG */ + +#include + +#include "xscreensaver.h" +#include "auth.h" + +extern const char *blurb(void); +extern void check_for_leaks (const char *where); + + +/* blargh */ +#undef Bool +#undef True +#undef False +#define Bool int +#define True 1 +#define False 0 + +#undef countof +#define countof(x) (sizeof((x))/sizeof(*(x))) + +struct auth_methods { + const char *name; + Bool (*init) (int argc, char **argv, Bool verbose_p); + Bool (*priv_init) (int argc, char **argv, Bool verbose_p); + Bool (*valid_p) (const char *typed_passwd, Bool verbose_p); + void (*try_unlock) (saver_info *si, Bool verbose_p, + Bool (*valid_p)(const char *typed_passwd, Bool verbose_p)); + Bool initted_p; + Bool priv_initted_p; +}; + + +#ifdef HAVE_KERBEROS +extern Bool kerberos_lock_init (int argc, char **argv, Bool verbose_p); +extern Bool kerberos_passwd_valid_p (const char *typed_passwd, Bool verbose_p); +#endif +#ifdef HAVE_PAM +extern Bool pam_priv_init (int argc, char **argv, Bool verbose_p); +extern void pam_try_unlock (saver_info *si, Bool verbose_p, + Bool (*valid_p)(const char *typed_passwd, Bool verbose_p)); +#endif +#ifdef PASSWD_HELPER_PROGRAM +extern Bool ext_priv_init (int argc, char **argv, Bool verbose_p); +extern Bool ext_passwd_valid_p (const char *typed_passwd, Bool verbose_p); +#endif +extern Bool pwent_lock_init (int argc, char **argv, Bool verbose_p); +extern Bool pwent_priv_init (int argc, char **argv, Bool verbose_p); +extern Bool pwent_passwd_valid_p (const char *typed_passwd, Bool verbose_p); + +Bool lock_priv_init (int argc, char **argv, Bool verbose_p); +Bool lock_init (int argc, char **argv, Bool verbose_p); +Bool passwd_valid_p (const char *typed_passwd, Bool verbose_p); + +/* The authorization methods to try, in order. + Note that the last one (the pwent version) is actually two auth methods, + since that code tries shadow passwords, and then non-shadow passwords. + (It's all in the same file since the APIs are randomly nearly-identical.) + */ +struct auth_methods methods[] = { +# ifdef HAVE_PAM + { "PAM", 0, pam_priv_init, 0, pam_try_unlock, + False, False }, +# endif +# ifdef HAVE_KERBEROS + { "Kerberos", kerberos_lock_init, 0, kerberos_passwd_valid_p, 0, + False, False }, +# endif +# ifdef PASSWD_HELPER_PROGRAM + { "external", 0, ext_priv_init, ext_passwd_valid_p, 0, + False, False }, +# endif + { "normal", pwent_lock_init, pwent_priv_init, pwent_passwd_valid_p, 0, + False, False } +}; + + +Bool +lock_priv_init (int argc, char **argv, Bool verbose_p) +{ + int i; + Bool any_ok = False; + for (i = 0; i < countof(methods); i++) + { + if (!methods[i].priv_init) + methods[i].priv_initted_p = True; + else + methods[i].priv_initted_p = methods[i].priv_init (argc, argv, + verbose_p); + + if (methods[i].priv_initted_p) + any_ok = True; + else if (verbose_p) + fprintf (stderr, "%s: initialization of %s passwords failed.\n", + blurb(), methods[i].name); + } + return any_ok; +} + + +Bool +lock_init (int argc, char **argv, Bool verbose_p) +{ + int i; + Bool any_ok = False; + for (i = 0; i < countof(methods); i++) + { + if (!methods[i].priv_initted_p) /* Bail if lock_priv_init failed. */ + continue; + + if (!methods[i].init) + methods[i].initted_p = True; + else + methods[i].initted_p = methods[i].init (argc, argv, verbose_p); + + if (methods[i].initted_p) + any_ok = True; + else if (verbose_p) + fprintf (stderr, "%s: initialization of %s passwords failed.\n", + blurb(), methods[i].name); + } + return any_ok; +} + + +/* A basic auth driver that simply prompts for a password then runs it through + * valid_p to determine whether the password is correct. + */ +static void +try_unlock_password(saver_info *si, + Bool verbose_p, + Bool (*valid_p)(const char *typed_passwd, Bool verbose_p)) +{ + struct auth_message message; + struct auth_response *response = NULL; + + memset(&message, 0, sizeof(message)); + + if (verbose_p) + fprintf(stderr, "%s: non-PAM password auth.\n", blurb()); + + /* Call the auth_conv function with "Password:", then feed + * the result into valid_p() + */ + message.type = AUTH_MSGTYPE_PROMPT_NOECHO; + message.msg = "Password:"; + + si->unlock_cb(1, &message, &response, si); + + if (!response) + return; + + if (valid_p (response->response, verbose_p)) + si->unlock_state = ul_success; /* yay */ + else if (si->unlock_state == ul_cancel || + si->unlock_state == ul_time) + ; /* more specific failures ok */ + else + si->unlock_state = ul_fail; /* generic failure */ + + if (response->response) + free(response->response); + free(response); +} + + +/* Write a password failure to the system log. + */ +static void +do_syslog (saver_info *si, Bool verbose_p) +{ +# ifdef HAVE_SYSLOG + struct passwd *pw = getpwuid (getuid ()); + char *d = DisplayString (si->dpy); + char *u = (pw && pw->pw_name ? pw->pw_name : "???"); + int opt = 0; + int fac = 0; + +# ifdef LOG_PID + opt = LOG_PID; +# endif + +# if defined(LOG_AUTHPRIV) + fac = LOG_AUTHPRIV; +# elif defined(LOG_AUTH) + fac = LOG_AUTH; +# else + fac = LOG_DAEMON; +# endif + + if (!d) d = ""; + +# undef FMT +# define FMT "FAILED LOGIN %d ON DISPLAY \"%s\", FOR \"%s\"" + + if (verbose_p) + fprintf (stderr, "%s: syslog: " FMT "\n", blurb(), + si->unlock_failures, d, u); + + openlog (progname, opt, fac); + syslog (LOG_NOTICE, FMT, si->unlock_failures, d, u); + closelog (); + +# endif /* HAVE_SYSLOG */ +} + + + +/** + * Runs through each authentication driver calling its try_unlock function. + * Called xss_authenticate() because AIX beat us to the name authenticate(). + */ +void +xss_authenticate(saver_info *si, Bool verbose_p) +{ + int i, j; + + si->unlock_state = ul_read; + + for (i = 0; i < countof(methods); i++) + { + if (!methods[i].initted_p) + continue; + + if (si->cached_passwd != NULL && methods[i].valid_p) + si->unlock_state = (methods[i].valid_p(si->cached_passwd, verbose_p) == True) + ? ul_success : ul_fail; + else if (methods[i].try_unlock != NULL) + methods[i].try_unlock(si, verbose_p, methods[i].valid_p); + else if (methods[i].valid_p) + try_unlock_password(si, verbose_p, methods[i].valid_p); + else /* Ze goggles, zey do nozing! */ + fprintf(stderr, "%s: authentication method %s does nothing.\n", + blurb(), methods[i].name); + + check_for_leaks (methods[i].name); + + /* If password authentication failed, but the password was NULL + (meaning the user just hit RET) then treat that as "cancel". + This means that if the password is literally NULL, it will + work; but if not, then NULL passwords are treated as cancel. + */ + if (si->unlock_state == ul_fail && + si->cached_passwd && + !*si->cached_passwd) + { + fprintf (stderr, "%s: assuming null password means cancel.\n", + blurb()); + si->unlock_state = ul_cancel; + } + + if (si->unlock_state == ul_success) + { + /* If we successfully authenticated by method N, but attempting + to authenticate by method N-1 failed, mention that (since if + an earlier authentication method fails and a later one succeeds, + something screwy is probably going on.) + */ + if (verbose_p && i > 0) + { + for (j = 0; j < i; j++) + if (methods[j].initted_p) + fprintf (stderr, + "%s: authentication via %s failed.\n", + blurb(), methods[j].name); + fprintf (stderr, + "%s: authentication via %s succeeded.\n", + blurb(), methods[i].name); + } + goto DONE; /* Successfully authenticated! */ + } + else if (si->unlock_state == ul_cancel || + si->unlock_state == ul_time) + { + /* If any auth method gets a cancel or timeout, don't try the + next auth method! We're done! */ + fprintf (stderr, + "%s: authentication via %s %s.\n", + blurb(), methods[i].name, + (si->unlock_state == ul_cancel + ? "cancelled" : "timed out")); + goto DONE; + } + } + + if (verbose_p) + fprintf(stderr, "%s: All authentication mechanisms failed.\n", blurb()); + + if (si->unlock_state == ul_fail) + { + si->unlock_failures++; + do_syslog (si, verbose_p); + } + +DONE: + if (si->auth_finished_cb) + si->auth_finished_cb (si); +} + +#endif /* NO_LOCKING -- whole file */ diff --git a/driver/pdf2jpeg.m b/driver/pdf2jpeg.m new file mode 100644 index 00000000..d681b4a5 --- /dev/null +++ b/driver/pdf2jpeg.m @@ -0,0 +1,152 @@ +/* pdf2jpeg -- converts a PDF file to a JPEG file, using Cocoa + * + * Copyright (c) 2003, 2008 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. + * + * Inspired by clues provided by Jan Kujawa and Jonathan Hendry. + */ + +#import +#include +#include + +int +main (int argc, char** argv) +{ + const char *progname = argv[0]; + const char *infile = 0, *outfile = 0; + double compression = 0.85; + double scale = 1.0; + int verbose = 0; + int i; + + for (i = 1; i < argc; i++) + { + char c; + if (argv[i][0] == '-' && argv[i][1] == '-') + argv[i]++; + if (!strcmp (argv[i], "-q") || + !strcmp (argv[i], "-qual") || + !strcmp (argv[i], "-quality")) + { + int q; + if (1 != sscanf (argv[++i], " %d %c", &q, &c) || + q < 5 || q > 100) + { + fprintf (stderr, "%s: quality must be 5 - 100 (%d)\n", + progname, q); + goto USAGE; + } + compression = q / 100.0; + } + else if (!strcmp (argv[i], "-scale")) + { + float s; + if (1 != sscanf (argv[++i], " %f %c", &s, &c) || + s <= 0 || s > 50) + { + fprintf (stderr, "%s: scale must be 0.0 - 50.0 (%f)\n", + progname, s); + goto USAGE; + } + scale = s; + } + else if (!strcmp (argv[i], "-verbose")) + verbose++; + else if (!strcmp (argv[i], "-v") || + !strcmp (argv[i], "-vv") || + !strcmp (argv[i], "-vvv")) + verbose += strlen(argv[i])-1; + else if (argv[i][0] == '-') + { + fprintf (stderr, "%s: unknown option %s\n", progname, argv[i]); + goto USAGE; + } + else if (!infile) + infile = argv[i]; + else if (!outfile) + outfile = argv[i]; + else + { + USAGE: + fprintf (stderr, + "usage: %s [-verbose] [-scale N] [-quality NN] " + "infile.pdf outfile.jpg\n", + progname); + exit (1); + } + } + + if (!infile || !outfile) + goto USAGE; + + + // Much of Cocoa needs one of these to be available. + NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; + + //Need an NSApp instance to make [NSImage TIFFRepresentation] work + NSApp = [NSApplication sharedApplication]; + [NSApp autorelease]; + + if (verbose) + fprintf (stderr, "%s: reading %s...\n", progname, infile); + + // Load the PDF file into an NSData object: + NSData *pdf_data = [NSData dataWithContentsOfFile: + [NSString stringWithCString:infile + encoding:NSUTF8StringEncoding]]; + + // Create an NSPDFImageRep from the data: + NSPDFImageRep *pdf_rep = [NSPDFImageRep imageRepWithData:pdf_data]; + + // Create an NSImage instance + NSRect rect; + rect.size = [pdf_rep size]; + rect.size.width *= scale; + rect.size.height *= scale; + rect.origin.x = rect.origin.y = 0; + NSImage *image = [[NSImage alloc] initWithSize:rect.size]; + + // Draw the PDFImageRep in the NSImage + [image lockFocus]; + [pdf_rep drawInRect:rect]; + [image unlockFocus]; + + // Load the NSImage's contents into an NSBitmapImageRep: + NSBitmapImageRep *bit_rep = [NSBitmapImageRep + imageRepWithData:[image TIFFRepresentation]]; + + // Write the bitmapImageRep to a JPEG file: + if (bit_rep == nil) + { + fprintf (stderr, "%s: error converting image?\n", argv[0]); + exit (1); + } + + if (verbose) + fprintf (stderr, "%s: writing %s (%d%% quality)...\n", + progname, outfile, (int) (compression * 100)); + + NSDictionary *props = [NSDictionary + dictionaryWithObject: + [NSNumber numberWithFloat:compression] + forKey:NSImageCompressionFactor]; + NSData *jpeg_data = [bit_rep representationUsingType:NSJPEGFileType + properties:props]; + + [jpeg_data writeToFile: + [NSString stringWithCString:outfile + encoding:NSUTF8StringEncoding] + atomically:YES]; + [image release]; + + [pool release]; + exit (0); +} diff --git a/driver/pdf2jpeg.man b/driver/pdf2jpeg.man new file mode 100644 index 00000000..9d80dd76 --- /dev/null +++ b/driver/pdf2jpeg.man @@ -0,0 +1,43 @@ +.TH XScreenSaver 1 "07-Sep-2003 (4.13)" "X Version 11" +.SH NAME +pdf2jpeg - converts a PDF file to a JPEG file using Cocoa +.SH SYNOPSIS +.B pdf2jpeg +[\--verbose] [\--quality \fINN\fP] infile.pdf outfile.jpg +.SH DESCRIPTION +This reads a PDF file (for example, as written by the +.BR screencapture (1) +program) and writes a JPEG file. +.SH OPTIONS +.I pdf2jpeg +accepts the following options: +.TP 4 +.B --verbose +Print diagnostics. +.TP 4 +.B --quality \fINN\fP +JPEG compression factor. Default 85%. +.SH BUGS +The input and output files must be files: pipes don't work. + +This program is Cocoa-specific, so it won't work on non-MacOS systems. + +This shouldn't need to be a part of the XScreenSaver distribution at +all, but Apple is COMPLETELY INSANE and made +.BR screencapture (1) +only write PDFs, with no simple way to convert that to something +less crazy. +.SH SEE ALSO +.BR screencapture (1), +.BR xscreensaver\-getimage\-desktop (1) +.SH COPYRIGHT +Copyright \(co 2003 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 , 20-Oct-03. diff --git a/driver/prefs.c b/driver/prefs.c new file mode 100644 index 00000000..f01f1147 --- /dev/null +++ b/driver/prefs.c @@ -0,0 +1,1650 @@ +/* dotfile.c --- management of the ~/.xscreensaver file. + * xscreensaver, Copyright (c) 1998-2011 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. + */ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include + +#ifdef HAVE_UNISTD_H +# include +#endif + +#include +#include +#include +#include +#include +#include +#include /* for PATH_MAX */ + +#include +#include + +#ifndef VMS +# include +#else /* VMS */ +# include "vms-pwd.h" +#endif /* VMS */ + + +/* This file doesn't need the Xt headers, so stub these types out... */ +#undef XtPointer +#define XtAppContext void* +#define XtIntervalId void* +#define XtPointer void* +#define Widget void* + + +/* Just in case there's something pathological about stat.h... */ +#ifndef S_IRUSR +# define S_IRUSR 00400 +#endif +#ifndef S_IWUSR +# define S_IWUSR 00200 +#endif +#ifndef S_IXUSR +# define S_IXUSR 00100 +#endif +#ifndef S_IXGRP +# define S_IXGRP 00010 +#endif +#ifndef S_IXOTH +# define S_IXOTH 00001 +#endif + + +#include "prefs.h" +#include "resources.h" + +/* don't use realpath() on fedora system */ +#ifdef _FORTIFY_SOURCE +#undef HAVE_REALPATH +#endif + + +extern char *progname; +extern char *progclass; +extern const char *blurb (void); + + + +static void get_screenhacks (Display *, saver_preferences *); +static char *format_command (const char *cmd, Bool wrap_p); +static void merge_system_screenhacks (Display *, saver_preferences *, + screenhack **system_list, int count); +static void stop_the_insanity (saver_preferences *p); + + +static char * +chase_symlinks (const char *file) +{ +# ifdef HAVE_REALPATH + if (file) + { +# ifndef PATH_MAX +# ifdef MAXPATHLEN +# define PATH_MAX MAXPATHLEN +# else +# define PATH_MAX 2048 +# endif +# endif + char buf[PATH_MAX]; + if (realpath (file, buf)) + return strdup (buf); + +/* sprintf (buf, "%.100s: realpath %.200s", blurb(), file); + perror(buf);*/ + } +# endif /* HAVE_REALPATH */ + return 0; +} + + +static Bool +i_am_a_nobody (uid_t uid) +{ + struct passwd *p; + + p = getpwnam ("nobody"); + if (! p) p = getpwnam ("noaccess"); + if (! p) p = getpwnam ("daemon"); + + if (! p) /* There is no nobody? */ + return False; + + return (uid == p->pw_uid); +} + + +const char * +init_file_name (void) +{ + static char *file = 0; + + if (!file) + { + uid_t uid = getuid (); + struct passwd *p = getpwuid (uid); + + if (i_am_a_nobody (uid)) + /* If we're running as nobody, then use root's .xscreensaver file + (since ~root/.xscreensaver and ~nobody/.xscreensaver are likely + to be different -- if we didn't do this, then xscreensaver-demo + would appear to have no effect when the luser is running as root.) + */ + uid = 0; + + p = getpwuid (uid); + + if (!p || !p->pw_name || !*p->pw_name) + { + fprintf (stderr, "%s: couldn't get user info of uid %d\n", + blurb(), getuid ()); + file = ""; + } + else if (!p->pw_dir || !*p->pw_dir) + { + fprintf (stderr, "%s: couldn't get home directory of \"%s\"\n", + blurb(), (p->pw_name ? p->pw_name : "???")); + file = ""; + } + else + { + const char *home = p->pw_dir; + const char *name = ".xscreensaver"; + file = (char *) malloc(strlen(home) + strlen(name) + 2); + strcpy(file, home); + if (!*home || home[strlen(home)-1] != '/') + strcat(file, "/"); + strcat(file, name); + } + } + + if (file && *file) + return file; + else + return 0; +} + + +static const char * +init_file_tmp_name (void) +{ + static char *file = 0; + if (!file) + { + const char *name = init_file_name(); + const char *suffix = ".tmp"; + + char *n2 = chase_symlinks (name); + if (n2) name = n2; + + if (!name || !*name) + file = ""; + else + { + file = (char *) malloc(strlen(name) + strlen(suffix) + 2); + strcpy(file, name); + strcat(file, suffix); + } + + if (n2) free (n2); + } + + if (file && *file) + return file; + else + return 0; +} + +static int +get_byte_resource (Display *dpy, char *name, char *class) +{ + char *s = get_string_resource (dpy, name, class); + char *s2 = s; + int n = 0; + if (!s) return 0; + + while (isspace(*s2)) s2++; + while (*s2 >= '0' && *s2 <= '9') + { + n = (n * 10) + (*s2 - '0'); + s2++; + } + while (isspace(*s2)) s2++; + if (*s2 == 'k' || *s2 == 'K') n <<= 10; + else if (*s2 == 'm' || *s2 == 'M') n <<= 20; + else if (*s2 == 'g' || *s2 == 'G') n <<= 30; + else if (*s2) + { + LOSE: + fprintf (stderr, "%s: %s must be a number of bytes, not \"%s\".\n", + progname, name, s); + free (s); + return 0; + } + s2++; + if (*s2 == 'b' || *s2 == 'B') s2++; + while (isspace(*s2)) s2++; + if (*s2) goto LOSE; + + free (s); + return n; +} + + +static const char * const prefs[] = { + "timeout", + "cycle", + "lock", + "lockVTs", /* not saved */ + "lockTimeout", + "passwdTimeout", + "visualID", + "installColormap", + "verbose", + "timestamp", + "splash", + "splashDuration", + "quad", + "demoCommand", + "prefsCommand", + "newLoginCommand", + "helpURL", /* not saved */ + "loadURL", /* not saved */ + "newLoginCommand", /* not saved */ + "nice", + "memoryLimit", + "fade", + "unfade", + "fadeSeconds", + "fadeTicks", + "captureStderr", + "captureStdout", /* not saved -- obsolete */ + "logFile", /* not saved */ + "ignoreUninstalledPrograms", + "font", + "dpmsEnabled", + "dpmsQuickOff", + "dpmsStandby", + "dpmsSuspend", + "dpmsOff", + "grabDesktopImages", + "grabVideoFrames", + "chooseRandomImages", + "imageDirectory", + "mode", + "selected", + "textMode", + "textLiteral", + "textFile", + "textProgram", + "textURL", + "", + "programs", + "", + "pointerPollTime", + "pointerHysteresis", + "windowCreationTimeout", + "initialDelay", + "sgiSaverExtension", /* not saved -- obsolete */ + "mitSaverExtension", /* not saved -- obsolete */ + "xidleExtension", /* not saved -- obsolete */ + "GetViewPortIsFullOfLies", + "procInterrupts", + "xinputExtensionDev", + "overlayStderr", + "overlayTextBackground", /* not saved -- X resources only */ + "overlayTextForeground", /* not saved -- X resources only */ + "bourneShell", /* not saved -- X resources only */ + 0 +}; + +static char * +strip (char *s) +{ + char *s2; + while (*s == '\t' || *s == ' ' || *s == '\r' || *s == '\n') + s++; + for (s2 = s; *s2; s2++) + ; + for (s2--; s2 >= s; s2--) + if (*s2 == '\t' || *s2 == ' ' || *s2 == '\r' || *s2 =='\n') + *s2 = 0; + else + break; + return s; +} + + +/* Reading + */ + +static int +handle_entry (XrmDatabase *db, const char *key, const char *value, + const char *filename, int line) +{ + int i; + for (i = 0; prefs[i]; i++) + if (*prefs[i] && !strcasecmp(key, prefs[i])) + { + char *val = strdup(value); + char *spec = (char *) malloc(strlen(progclass) + strlen(prefs[i]) +10); + strcpy(spec, progclass); + strcat(spec, "."); + strcat(spec, prefs[i]); + + XrmPutStringResource (db, spec, val); + + free(spec); + free(val); + return 0; + } + + fprintf(stderr, "%s: %s:%d: unknown option \"%s\"\n", + blurb(), filename, line, key); + return 1; +} + + +static int +parse_init_file (saver_preferences *p) +{ + time_t write_date = 0; + const char *name = init_file_name(); + int line = 0; + struct stat st; + FILE *in; + int buf_size = 1024; + char *buf; + + if (!name) return 0; + + if (stat(name, &st) != 0) + { + p->init_file_date = 0; + return 0; + } + + in = fopen(name, "r"); + if (!in) + { + char *buf = (char *) malloc(1024 + strlen(name)); + sprintf(buf, "%s: error reading \"%s\"", blurb(), name); + perror(buf); + free(buf); + return -1; + } + + if (fstat (fileno(in), &st) == 0) + { + write_date = st.st_mtime; + } + else + { + char *buf = (char *) malloc(1024 + strlen(name)); + sprintf(buf, "%s: couldn't re-stat \"%s\"", blurb(), name); + perror(buf); + free(buf); + return -1; + } + + buf = (char *) malloc(buf_size); + + while (fgets (buf, buf_size-1, in)) + { + char *key, *value; + int L = strlen(buf); + + line++; + while (L > 2 && + (buf[L-1] != '\n' || /* whole line didn't fit in buffer */ + buf[L-2] == '\\')) /* or line ended with backslash */ + { + if (buf[L-2] == '\\') /* backslash-newline gets swallowed */ + { + buf[L-2] = 0; + L -= 2; + } + buf_size += 1024; + buf = (char *) realloc(buf, buf_size); + if (!buf) exit(1); + + line++; + if (!fgets (buf + L, buf_size-L-1, in)) + break; + L = strlen(buf); + } + + /* Now handle other backslash escapes. */ + { + int i, j; + for (i = 0; buf[i]; i++) + if (buf[i] == '\\') + { + switch (buf[i+1]) + { + case 'n': buf[i] = '\n'; break; + case 'r': buf[i] = '\r'; break; + case 't': buf[i] = '\t'; break; + default: buf[i] = buf[i+1]; break; + } + for (j = i+2; buf[j]; j++) + buf[j-1] = buf[j]; + buf[j-1] = 0; + } + } + + key = strip(buf); + + if (*key == '#' || *key == '!' || *key == ';' || + *key == '\n' || *key == 0) + continue; + + value = strchr (key, ':'); + if (!value) + { + fprintf(stderr, "%s: %s:%d: unparsable line: %s\n", blurb(), + name, line, key); + continue; + } + else + { + *value++ = 0; + value = strip(value); + } + + if (!p->db) abort(); + handle_entry (&p->db, key, value, name, line); + } + fclose (in); + free(buf); + + p->init_file_date = write_date; + return 0; +} + + +Bool +init_file_changed_p (saver_preferences *p) +{ + const char *name = init_file_name(); + struct stat st; + + if (!name) return False; + + if (stat(name, &st) != 0) + return False; + + if (p->init_file_date == st.st_mtime) + return False; + + return True; +} + + +/* Writing + */ + +static int +tab_to (FILE *out, int from, int to) +{ + int tab_width = 8; + int to_mod = (to / tab_width) * tab_width; + while (from < to_mod) + { + fprintf(out, "\t"); + from = (((from / tab_width) + 1) * tab_width); + } + while (from < to) + { + fprintf(out, " "); + from++; + } + return from; +} + +static char * +stab_to (char *out, int from, int to) +{ + int tab_width = 8; + int to_mod = (to / tab_width) * tab_width; + while (from < to_mod) + { + *out++ = '\t'; + from = (((from / tab_width) + 1) * tab_width); + } + while (from < to) + { + *out++ = ' '; + from++; + } + return out; +} + +static int +string_columns (const char *string, int length, int start) +{ + int tab_width = 8; + int col = start; + const char *end = string + length; + while (string < end) + { + if (*string == '\n') + col = 0; + else if (*string == '\t') + col = (((col / tab_width) + 1) * tab_width); + else + col++; + string++; + } + return col; +} + + +static void +write_entry (FILE *out, const char *key, const char *value) +{ + char *v = strdup(value ? value : ""); + char *v2 = v; + char *nl = 0; + int col; + Bool programs_p = (!strcmp(key, "programs")); + int tab = (programs_p ? 32 : 16); + Bool first = True; + + fprintf(out, "%s:", key); + col = strlen(key) + 1; + + if (strlen(key) > 14) + col = tab_to (out, col, 20); + + while (1) + { + if (!programs_p) + v2 = strip(v2); + nl = strchr(v2, '\n'); + if (nl) + *nl = 0; + + if (first && programs_p) + { + col = tab_to (out, col, 77); + fprintf (out, " \\\n"); + col = 0; + } + + if (first) + first = False; + else + { + col = tab_to (out, col, 75); + fprintf (out, " \\n\\\n"); + col = 0; + } + + if (!programs_p) + col = tab_to (out, col, tab); + + if (programs_p && + string_columns(v2, strlen (v2), col) + col > 75) + { + int L = strlen (v2); + int start = 0; + int end = start; + while (start < L) + { + while (v2[end] == ' ' || v2[end] == '\t') + end++; + while (v2[end] != ' ' && v2[end] != '\t' && + v2[end] != '\n' && v2[end] != 0) + end++; + if (string_columns (v2 + start, (end - start), col) >= 74) + { + col = tab_to (out, col, 75); + fprintf(out, " \\\n"); + col = tab_to (out, 0, tab + 2); + while (v2[start] == ' ' || v2[start] == '\t') + start++; + } + + col = string_columns (v2 + start, (end - start), col); + while (start < end) + fputc(v2[start++], out); + } + } + else + { + fprintf (out, "%s", v2); + col += string_columns(v2, strlen (v2), col); + } + + if (nl) + v2 = nl + 1; + else + break; + } + + fprintf(out, "\n"); + free(v); +} + +int +write_init_file (Display *dpy, + saver_preferences *p, const char *version_string, + Bool verbose_p) +{ + int status = -1; + const char *name = init_file_name(); + const char *tmp_name = init_file_tmp_name(); + char *n2 = chase_symlinks (name); + struct stat st; + int i, j; + + /* Kludge, since these aren't in the saver_preferences struct as strings... + */ + char *visual_name; + char *programs; + Bool overlay_stderr_p; + char *stderr_font; + FILE *out; + + if (!name) goto END; + + if (n2) name = n2; + + /* Throttle the various timeouts to reasonable values before writing + the file to disk. */ + stop_the_insanity (p); + + + if (verbose_p) + fprintf (stderr, "%s: writing \"%s\".\n", blurb(), name); + + unlink (tmp_name); + out = fopen(tmp_name, "w"); + if (!out) + { + char *buf = (char *) malloc(1024 + strlen(name)); + sprintf(buf, "%s: error writing \"%s\"", blurb(), name); + perror(buf); + free(buf); + goto END; + } + + /* Give the new .xscreensaver file the same permissions as the old one; + except ensure that it is readable and writable by owner, and not + executable. Extra hack: if we're running as root, make the file + be world-readable (so that the daemon, running as "nobody", will + still be able to read it.) + */ + if (stat(name, &st) == 0) + { + mode_t mode = st.st_mode; + mode |= S_IRUSR | S_IWUSR; /* read/write by user */ + mode &= ~(S_IXUSR | S_IXGRP | S_IXOTH); /* executable by none */ + + if (getuid() == (uid_t) 0) /* read by group/other */ + mode |= S_IRGRP | S_IROTH; + + if (fchmod (fileno(out), mode) != 0) + { + char *buf = (char *) malloc(1024 + strlen(name)); + sprintf (buf, "%s: error fchmodding \"%s\" to 0%o", blurb(), + tmp_name, (unsigned int) mode); + perror(buf); + free(buf); + goto END; + } + } + + /* Kludge, since these aren't in the saver_preferences struct... */ + visual_name = get_string_resource (dpy, "visualID", "VisualID"); + programs = 0; + overlay_stderr_p = get_boolean_resource (dpy, "overlayStderr", "Boolean"); + stderr_font = get_string_resource (dpy, "font", "Font"); + + i = 0; + { + char *ss; + char **hack_strings = (char **) + calloc (p->screenhacks_count, sizeof(char *)); + + for (j = 0; j < p->screenhacks_count; j++) + { + hack_strings[j] = format_hack (dpy, p->screenhacks[j], True); + i += strlen (hack_strings[j]); + i += 2; + } + + ss = programs = (char *) malloc(i + 10); + *ss = 0; + for (j = 0; j < p->screenhacks_count; j++) + { + strcat (ss, hack_strings[j]); + free (hack_strings[j]); + ss += strlen(ss); + *ss++ = '\n'; + *ss = 0; + } + free (hack_strings); + } + + { + struct passwd *pw = getpwuid (getuid ()); + char *whoami = (pw && pw->pw_name && *pw->pw_name + ? pw->pw_name + : ""); + time_t now = time ((time_t *) 0); + char *timestr = (char *) ctime (&now); + char *nl = (char *) strchr (timestr, '\n'); + if (nl) *nl = 0; + fprintf (out, + "# %s Preferences File\n" + "# Written by %s %s for %s on %s.\n" + "# http://www.jwz.org/xscreensaver/\n" + "\n", + progclass, progname, version_string, whoami, timestr); + } + + for (j = 0; prefs[j]; j++) + { + char buf[255]; + const char *pr = prefs[j]; + enum pref_type { pref_str, pref_int, pref_bool, pref_byte, pref_time + } type = pref_str; + const char *s = 0; + int i = 0; + Bool b = False; + Time t = 0; + + if (pr && !*pr) + { + fprintf(out, "\n"); + continue; + } + +# undef CHECK +# define CHECK(X) else if (!strcmp(pr, X)) + if (!pr || !*pr) ; + CHECK("timeout") type = pref_time, t = p->timeout; + CHECK("cycle") type = pref_time, t = p->cycle; + CHECK("lock") type = pref_bool, b = p->lock_p; + CHECK("lockVTs") continue; /* don't save, unused */ + CHECK("lockTimeout") type = pref_time, t = p->lock_timeout; + CHECK("passwdTimeout") type = pref_time, t = p->passwd_timeout; + CHECK("visualID") type = pref_str, s = visual_name; + CHECK("installColormap") type = pref_bool, b = p->install_cmap_p; + CHECK("verbose") type = pref_bool, b = p->verbose_p; + CHECK("timestamp") type = pref_bool, b = p->timestamp_p; + CHECK("splash") type = pref_bool, b = p->splash_p; + CHECK("splashDuration") type = pref_time, t = p->splash_duration; +# ifdef QUAD_MODE + CHECK("quad") type = pref_bool, b = p->quad_p; +# else /* !QUAD_MODE */ + CHECK("quad") continue; /* don't save */ +# endif /* !QUAD_MODE */ + CHECK("demoCommand") type = pref_str, s = p->demo_command; + CHECK("prefsCommand") type = pref_str, s = p->prefs_command; +/* CHECK("helpURL") type = pref_str, s = p->help_url; */ + CHECK("helpURL") continue; /* don't save */ +/* CHECK("loadURL") type = pref_str, s = p->load_url_command; */ + CHECK("loadURL") continue; /* don't save */ +/* CHECK("newLoginCommand") type = pref_str, s = p->new_login_command; */ + CHECK("newLoginCommand") continue; /* don't save */ + CHECK("nice") type = pref_int, i = p->nice_inferior; + CHECK("memoryLimit") type = pref_byte, i = p->inferior_memory_limit; + CHECK("fade") type = pref_bool, b = p->fade_p; + CHECK("unfade") type = pref_bool, b = p->unfade_p; + CHECK("fadeSeconds") type = pref_time, t = p->fade_seconds; + CHECK("fadeTicks") type = pref_int, i = p->fade_ticks; + CHECK("captureStderr") type = pref_bool, b = p->capture_stderr_p; + CHECK("captureStdout") continue; /* don't save */ + CHECK("logFile") continue; /* don't save */ + CHECK("ignoreUninstalledPrograms") + type = pref_bool, b = p->ignore_uninstalled_p; + + CHECK("font") type = pref_str, s = stderr_font; + + CHECK("dpmsEnabled") type = pref_bool, b = p->dpms_enabled_p; + CHECK("dpmsQuickOff") type = pref_bool, b = p->dpms_quickoff_p; + CHECK("dpmsStandby") type = pref_time, t = p->dpms_standby; + CHECK("dpmsSuspend") type = pref_time, t = p->dpms_suspend; + CHECK("dpmsOff") type = pref_time, t = p->dpms_off; + + CHECK("grabDesktopImages") type =pref_bool, b = p->grab_desktop_p; + CHECK("grabVideoFrames") type =pref_bool, b = p->grab_video_p; + CHECK("chooseRandomImages")type =pref_bool, b = p->random_image_p; + CHECK("imageDirectory") type =pref_str, s = p->image_directory; + + CHECK("mode") type = pref_str, + s = (p->mode == ONE_HACK ? "one" : + p->mode == BLANK_ONLY ? "blank" : + p->mode == DONT_BLANK ? "off" : + p->mode == RANDOM_HACKS_SAME + ? "random-same" + : "random"); + CHECK("selected") type = pref_int, i = p->selected_hack; + + CHECK("textMode") type = pref_str, + s = (p->tmode == TEXT_URL ? "url" : + p->tmode == TEXT_LITERAL ? "literal" : + p->tmode == TEXT_FILE ? "file" : + p->tmode == TEXT_PROGRAM ? "program" : + "date"); + CHECK("textLiteral") type = pref_str, s = p->text_literal; + CHECK("textFile") type = pref_str, s = p->text_file; + CHECK("textProgram") type = pref_str, s = p->text_program; + CHECK("textURL") type = pref_str, s = p->text_url; + + CHECK("programs") type = pref_str, s = programs; + CHECK("pointerPollTime") type = pref_time, t = p->pointer_timeout; + CHECK("pointerHysteresis")type = pref_int, i = p->pointer_hysteresis; + CHECK("windowCreationTimeout")type=pref_time,t= p->notice_events_timeout; + CHECK("initialDelay") type = pref_time, t = p->initial_delay; + CHECK("sgiSaverExtension") continue; /* don't save */ + CHECK("mitSaverExtension") continue; /* don't save */ + CHECK("xidleExtension") continue; /* don't save */ + CHECK("procInterrupts") type = pref_bool, b = p->use_proc_interrupts; + CHECK("xinputExtensionDev") type = pref_bool, b = p->use_xinput_extension; + CHECK("GetViewPortIsFullOfLies") type = pref_bool, + b = p->getviewport_full_of_lies_p; + CHECK("overlayStderr") type = pref_bool, b = overlay_stderr_p; + CHECK("overlayTextBackground") continue; /* don't save */ + CHECK("overlayTextForeground") continue; /* don't save */ + CHECK("bourneShell") continue; /* don't save */ + else abort(); +# undef CHECK + + switch (type) + { + case pref_str: + break; + case pref_int: + sprintf(buf, "%d", i); + s = buf; + break; + case pref_bool: + s = b ? "True" : "False"; + break; + case pref_time: + { + unsigned int hour = 0, min = 0, sec = (unsigned int) (t/1000); + if (sec >= 60) + { + min += (sec / 60); + sec %= 60; + } + if (min >= 60) + { + hour += (min / 60); + min %= 60; + } + sprintf (buf, "%u:%02u:%02u", hour, min, sec); + s = buf; + } + break; + case pref_byte: + { + if (i >= (1<<30) && i == ((i >> 30) << 30)) + sprintf(buf, "%dG", i >> 30); + else if (i >= (1<<20) && i == ((i >> 20) << 20)) + sprintf(buf, "%dM", i >> 20); + else if (i >= (1<<10) && i == ((i >> 10) << 10)) + sprintf(buf, "%dK", i >> 10); + else + sprintf(buf, "%d", i); + s = buf; + } + break; + default: + abort(); + break; + } + + if (pr && (!strcmp(pr, "mode") || !strcmp(pr, "textMode"))) + fprintf(out, "\n"); + + write_entry (out, pr, s); + } + + fprintf(out, "\n"); + + if (visual_name) free(visual_name); + if (stderr_font) free(stderr_font); + if (programs) free(programs); + + if (fclose(out) == 0) + { + time_t write_date = 0; + + if (stat(tmp_name, &st) == 0) + { + write_date = st.st_mtime; + } + else + { + char *buf = (char *) malloc(1024 + strlen(tmp_name) + strlen(name)); + sprintf(buf, "%s: couldn't stat \"%s\"", blurb(), tmp_name); + perror(buf); + unlink (tmp_name); + free(buf); + goto END; + } + + if (rename (tmp_name, name) != 0) + { + char *buf = (char *) malloc(1024 + strlen(tmp_name) + strlen(name)); + sprintf(buf, "%s: error renaming \"%s\" to \"%s\"", + blurb(), tmp_name, name); + perror(buf); + unlink (tmp_name); + free(buf); + goto END; + } + else + { + p->init_file_date = write_date; + + /* Since the .xscreensaver file is used for IPC, let's try and make + sure that the bits actually land on the disk right away. */ + sync (); + + status = 0; /* wrote and renamed successfully! */ + } + } + else + { + char *buf = (char *) malloc(1024 + strlen(name)); + sprintf(buf, "%s: error closing \"%s\"", blurb(), name); + perror(buf); + free(buf); + unlink (tmp_name); + goto END; + } + + END: + if (n2) free (n2); + return status; +} + + +/* Parsing the resource database + */ + +void +free_screenhack (screenhack *hack) +{ + if (hack->visual) free (hack->visual); + if (hack->name) free (hack->name); + free (hack->command); + memset (hack, 0, sizeof(*hack)); + free (hack); +} + +static void +free_screenhack_list (screenhack **list, int count) +{ + int i; + if (!list) return; + for (i = 0; i < count; i++) + if (list[i]) + free_screenhack (list[i]); + free (list); +} + + + +/* Populate `saver_preferences' with the contents of the resource database. + Note that this may be called multiple times -- it is re-run each time + the ~/.xscreensaver file is reloaded. + + This function can be very noisy, since it issues resource syntax errors + and so on. + */ +void +load_init_file (Display *dpy, saver_preferences *p) +{ + static Bool first_time = True; + + screenhack **system_default_screenhacks = 0; + int system_default_screenhack_count = 0; + + if (first_time) + { + /* Get the programs resource before the .xscreensaver file has been + parsed and merged into the resource database for the first time: + this is the value of *programs from the app-defaults file. + Then clear it out so that it will be parsed again later, after + the init file has been read. + */ + get_screenhacks (dpy, p); + system_default_screenhacks = p->screenhacks; + system_default_screenhack_count = p->screenhacks_count; + p->screenhacks = 0; + p->screenhacks_count = 0; + } + + if (parse_init_file (p) != 0) /* file might have gone away */ + if (!first_time) return; + + first_time = False; + + p->xsync_p = get_boolean_resource (dpy, "synchronous", "Synchronous"); + p->verbose_p = get_boolean_resource (dpy, "verbose", "Boolean"); + p->timestamp_p = get_boolean_resource (dpy, "timestamp", "Boolean"); + p->lock_p = get_boolean_resource (dpy, "lock", "Boolean"); + p->fade_p = get_boolean_resource (dpy, "fade", "Boolean"); + p->unfade_p = get_boolean_resource (dpy, "unfade", "Boolean"); + p->fade_seconds = 1000 * get_seconds_resource (dpy, "fadeSeconds", "Time"); + p->fade_ticks = get_integer_resource (dpy, "fadeTicks", "Integer"); + p->install_cmap_p = get_boolean_resource (dpy, "installColormap", "Boolean"); + p->nice_inferior = get_integer_resource (dpy, "nice", "Nice"); + p->inferior_memory_limit = get_byte_resource (dpy, "memoryLimit", + "MemoryLimit"); + p->splash_p = get_boolean_resource (dpy, "splash", "Boolean"); +# ifdef QUAD_MODE + p->quad_p = get_boolean_resource (dpy, "quad", "Boolean"); +# endif + p->capture_stderr_p = get_boolean_resource (dpy, "captureStderr", "Boolean"); + p->ignore_uninstalled_p = get_boolean_resource (dpy, + "ignoreUninstalledPrograms", + "Boolean"); + + p->initial_delay = 1000 * get_seconds_resource (dpy, "initialDelay", "Time"); + p->splash_duration = 1000 * get_seconds_resource (dpy, "splashDuration", "Time"); + p->timeout = 1000 * get_minutes_resource (dpy, "timeout", "Time"); + p->lock_timeout = 1000 * get_minutes_resource (dpy, "lockTimeout", "Time"); + p->cycle = 1000 * get_minutes_resource (dpy, "cycle", "Time"); + p->passwd_timeout = 1000 * get_seconds_resource (dpy, "passwdTimeout", "Time"); + p->pointer_timeout = 1000 * get_seconds_resource (dpy, "pointerPollTime", "Time"); + p->pointer_hysteresis = get_integer_resource (dpy, "pointerHysteresis","Integer"); + p->notice_events_timeout = 1000*get_seconds_resource(dpy, + "windowCreationTimeout", + "Time"); + + p->dpms_enabled_p = get_boolean_resource (dpy, "dpmsEnabled", "Boolean"); + p->dpms_quickoff_p = get_boolean_resource (dpy, "dpmsQuickOff", "Boolean"); + p->dpms_standby = 1000 * get_minutes_resource (dpy, "dpmsStandby", "Time"); + p->dpms_suspend = 1000 * get_minutes_resource (dpy, "dpmsSuspend", "Time"); + p->dpms_off = 1000 * get_minutes_resource (dpy, "dpmsOff", "Time"); + + p->grab_desktop_p = get_boolean_resource (dpy, "grabDesktopImages", "Boolean"); + p->grab_video_p = get_boolean_resource (dpy, "grabVideoFrames", "Boolean"); + p->random_image_p = get_boolean_resource (dpy, "chooseRandomImages", "Boolean"); + p->image_directory = get_string_resource (dpy, + "imageDirectory", + "ImageDirectory"); + + p->text_literal = get_string_resource (dpy, "textLiteral", "TextLiteral"); + p->text_file = get_string_resource (dpy, "textFile", "TextFile"); + p->text_program = get_string_resource (dpy, "textProgram", "TextProgram"); + p->text_url = get_string_resource (dpy, "textURL", "TextURL"); + + p->shell = get_string_resource (dpy, "bourneShell", "BourneShell"); + + p->demo_command = get_string_resource(dpy, "demoCommand", "URL"); + p->prefs_command = get_string_resource(dpy, "prefsCommand", "URL"); + p->help_url = get_string_resource(dpy, "helpURL", "URL"); + p->load_url_command = get_string_resource(dpy, "loadURL", "LoadURL"); + p->new_login_command = get_string_resource(dpy, + "newLoginCommand", + "NewLoginCommand"); + + /* If "*splash" is unset, default to true. */ + { + char *s = get_string_resource (dpy, "splash", "Boolean"); + if (s) + free (s); + else + p->splash_p = True; + } + + /* If "*grabDesktopImages" is unset, default to true. */ + { + char *s = get_string_resource (dpy, "grabDesktopImages", "Boolean"); + if (s) + free (s); + else + p->grab_desktop_p = True; + } + + p->use_xidle_extension = get_boolean_resource (dpy, "xidleExtension","Boolean"); +#if 0 /* obsolete. */ + p->use_sgi_saver_extension = get_boolean_resource (dpy, + "sgiSaverExtension", + "Boolean"); +#endif +#ifdef HAVE_XINPUT + p->use_xinput_extension = get_boolean_resource (dpy, "xinputExtensionDev", + "Boolean"); +#endif +#if 0 /* broken and evil. */ + p->use_mit_saver_extension = get_boolean_resource (dpy, + "mitSaverExtension", + "Boolean"); +#endif + + p->use_proc_interrupts = get_boolean_resource (dpy, + "procInterrupts", "Boolean"); + + p->getviewport_full_of_lies_p = + get_boolean_resource (dpy, "GetViewPortIsFullOfLies", "Boolean"); + + get_screenhacks (dpy, p); /* Parse the "programs" resource. */ + + { + char *s = get_string_resource (dpy, "selected", "Integer"); + if (!s || !*s) + p->selected_hack = -1; + else + p->selected_hack = get_integer_resource (dpy, "selected", "Integer"); + if (s) free (s); + if (p->selected_hack < 0 || p->selected_hack >= p->screenhacks_count) + p->selected_hack = -1; + } + + { + char *s = get_string_resource (dpy, "mode", "Mode"); + if (s && !strcasecmp (s, "one")) p->mode = ONE_HACK; + else if (s && !strcasecmp (s, "blank")) p->mode = BLANK_ONLY; + else if (s && !strcasecmp (s, "off")) p->mode = DONT_BLANK; + else if (s && !strcasecmp (s, "random-same")) p->mode = RANDOM_HACKS_SAME; + else p->mode = RANDOM_HACKS; + if (s) free (s); + } + + { + char *s = get_string_resource (dpy, "textMode", "TextMode"); + if (s && !strcasecmp (s, "url")) p->tmode = TEXT_URL; + else if (s && !strcasecmp (s, "literal")) p->tmode = TEXT_LITERAL; + else if (s && !strcasecmp (s, "file")) p->tmode = TEXT_FILE; + else if (s && !strcasecmp (s, "program")) p->tmode = TEXT_PROGRAM; + else p->tmode = TEXT_DATE; + if (s) free (s); + } + + if (system_default_screenhack_count) /* note: first_time is also true */ + { + merge_system_screenhacks (dpy, p, system_default_screenhacks, + system_default_screenhack_count); + free_screenhack_list (system_default_screenhacks, + system_default_screenhack_count); + system_default_screenhacks = 0; + system_default_screenhack_count = 0; + } + + if (p->debug_p) + { + p->xsync_p = True; + p->verbose_p = True; + p->timestamp_p = True; + p->initial_delay = 0; + } + + /* Throttle the various timeouts to reasonable values after reading the + disk file. */ + stop_the_insanity (p); +} + + +/* If there are any hacks in the system-wide defaults that are not in + the ~/.xscreensaver file, add the new ones to the end of the list. + This does *not* actually save the file. + */ +static void +merge_system_screenhacks (Display *dpy, saver_preferences *p, + screenhack **system_list, int system_count) +{ + /* Yeah yeah, this is an N^2 operation, but I don't have hashtables handy, + so fuck it. */ + + int made_space = 0; + int i; + for (i = 0; i < system_count; i++) + { + int j; + Bool matched_p = False; + + for (j = 0; j < p->screenhacks_count; j++) + { + char *name; + if (!system_list[i]->name) + system_list[i]->name = make_hack_name (dpy, + system_list[i]->command); + + name = p->screenhacks[j]->name; + if (!name) + name = make_hack_name (dpy, p->screenhacks[j]->command); + + matched_p = !strcasecmp (name, system_list[i]->name); + + if (name != p->screenhacks[j]->name) + free (name); + + if (matched_p) + break; + } + + if (!matched_p) + { + /* We have an entry in the system-wide list that is not in the + user's .xscreensaver file. Add it to the end. + Note that p->screenhacks is a single malloc block, not a + linked list, so we have to realloc it. + */ + screenhack *oh = system_list[i]; + screenhack *nh = (screenhack *) malloc (sizeof(screenhack)); + + if (made_space == 0) + { + made_space = 10; + p->screenhacks = (screenhack **) + realloc (p->screenhacks, + (p->screenhacks_count + made_space + 1) + * sizeof(screenhack)); + if (!p->screenhacks) abort(); + } + + nh->enabled_p = oh->enabled_p; + nh->visual = oh->visual ? strdup(oh->visual) : 0; + nh->name = oh->name ? strdup(oh->name) : 0; + nh->command = oh->command ? strdup(oh->command) : 0; + + p->screenhacks[p->screenhacks_count++] = nh; + p->screenhacks[p->screenhacks_count] = 0; + made_space--; + +#if 0 + fprintf (stderr, "%s: noticed new hack: %s\n", blurb(), + (nh->name ? nh->name : make_hack_name (dpy, nh->command))); +#endif + } + } +} + + + +/* Parsing the programs resource. + */ + +screenhack * +parse_screenhack (const char *line) +{ + screenhack *h = (screenhack *) calloc (1, sizeof(*h)); + const char *s; + + h->enabled_p = True; + + while (isspace(*line)) line++; /* skip whitespace */ + if (*line == '-') /* handle "-" */ + { + h->enabled_p = False; + line++; + while (isspace(*line)) line++; /* skip whitespace */ + } + + s = line; /* handle "visual:" */ + while (*line && *line != ':' && *line != '"' && !isspace(*line)) + line++; + if (*line != ':') + line = s; + else + { + h->visual = (char *) malloc (line-s+1); + strncpy (h->visual, s, line-s); + h->visual[line-s] = 0; + if (*line == ':') line++; /* skip ":" */ + while (isspace(*line)) line++; /* skip whitespace */ + } + + if (*line == '"') /* handle "name" */ + { + line++; + s = line; + while (*line && *line != '"') + line++; + h->name = (char *) malloc (line-s+1); + strncpy (h->name, s, line-s); + h->name[line-s] = 0; + if (*line == '"') line++; /* skip "\"" */ + while (isspace(*line)) line++; /* skip whitespace */ + } + + h->command = format_command (line, False); /* handle command */ + return h; +} + + +static char * +format_command (const char *cmd, Bool wrap_p) +{ + int tab = 30; + int col = tab; + char *cmd2 = (char *) calloc (1, 2 * (strlen (cmd) + 1)); + const char *in = cmd; + char *out = cmd2; + while (*in) + { + /* shrink all whitespace to one space, for the benefit of the "demo" + mode display. We only do this when we can easily tell that the + whitespace is not significant (no shell metachars). + */ + switch (*in) + { + case '\'': case '"': case '`': case '\\': + /* Metachars are scary. Copy the rest of the line unchanged. */ + while (*in) + *out++ = *in++, col++; + break; + + case ' ': case '\t': + /* Squeeze all other whitespace down to one space. */ + while (*in == ' ' || *in == '\t') + in++; + *out++ = ' ', col++; + break; + + default: + /* Copy other chars unchanged. */ + *out++ = *in++, col++; + break; + } + } + + *out = 0; + + /* Strip trailing whitespace */ + while (out > cmd2 && isspace (out[-1])) + *(--out) = 0; + + return cmd2; +} + + +/* Returns a new string describing the shell command. + This may be just the name of the program, capitalized. + It also may be something from the resource database (gotten + by looking for "hacks.XYZ.name", where XYZ is the program.) + */ +char * +make_hack_name (Display *dpy, const char *shell_command) +{ + char *s = strdup (shell_command); + char *s2; + char res_name[255]; + + for (s2 = s; *s2; s2++) /* truncate at first whitespace */ + if (isspace (*s2)) + { + *s2 = 0; + break; + } + + s2 = strrchr (s, '/'); /* if pathname, take last component */ + if (s2) + { + s2 = strdup (s2+1); + free (s); + s = s2; + } + + if (strlen (s) > 50) /* 51 is hereby defined as "unreasonable" */ + s[50] = 0; + + sprintf (res_name, "hacks.%s.name", s); /* resource? */ + s2 = get_string_resource (dpy, res_name, res_name); + if (s2) + { + free (s); + return s2; + } + + for (s2 = s; *s2; s2++) /* if it has any capitals, return it */ + if (*s2 >= 'A' && *s2 <= 'Z') + return s; + + if (s[0] >= 'a' && s[0] <= 'z') /* else cap it */ + s[0] -= 'a'-'A'; + if (s[0] == 'X' && s[1] >= 'a' && s[1] <= 'z') /* (magic leading X) */ + s[1] -= 'a'-'A'; + if (s[0] == 'G' && s[1] == 'l' && + s[2] >= 'a' && s[2] <= 'z') /* (magic leading GL) */ + s[1] -= 'a'-'A', + s[2] -= 'a'-'A'; + return s; +} + + +char * +format_hack (Display *dpy, screenhack *hack, Bool wrap_p) +{ + int tab = 32; + int size; + char *h2, *out, *s; + int col = 0; + + char *def_name = make_hack_name (dpy, hack->command); + + /* Don't ever write out a name for a hack if it's the same as the default. + */ + if (hack->name && !strcmp (hack->name, def_name)) + { + free (hack->name); + hack->name = 0; + } + free (def_name); + + size = (2 * (strlen(hack->command) + + (hack->visual ? strlen(hack->visual) : 0) + + (hack->name ? strlen(hack->name) : 0) + + tab)); + h2 = (char *) malloc (size); + out = h2; + + if (!hack->enabled_p) *out++ = '-'; /* write disabled flag */ + + if (hack->visual && *hack->visual) /* write visual name */ + { + if (hack->enabled_p) *out++ = ' '; + *out++ = ' '; + strcpy (out, hack->visual); + out += strlen (hack->visual); + *out++ = ':'; + *out++ = ' '; + } + + *out = 0; + col = string_columns (h2, strlen (h2), 0); + + if (hack->name && *hack->name) /* write pretty name */ + { + int L = (strlen (hack->name) + 2); + if (L + col < tab) + out = stab_to (out, col, tab - L - 2); + else + *out++ = ' '; + *out++ = '"'; + strcpy (out, hack->name); + out += strlen (hack->name); + *out++ = '"'; + *out = 0; + + col = string_columns (h2, strlen (h2), 0); + if (wrap_p && col >= tab) + out = stab_to (out, col, 77); + else + *out++ = ' '; + + if (out >= h2+size) abort(); + } + + *out = 0; + col = string_columns (h2, strlen (h2), 0); + out = stab_to (out, col, tab); /* indent */ + + if (out >= h2+size) abort(); + s = format_command (hack->command, wrap_p); + strcpy (out, s); + out += strlen (s); + free (s); + *out = 0; + + return h2; +} + + +static void +get_screenhacks (Display *dpy, saver_preferences *p) +{ + int i, j; + int start = 0; + int end = 0; + int size; + char *d; + + d = get_string_resource (dpy, "monoPrograms", "MonoPrograms"); + if (d && !*d) { free(d); d = 0; } + if (!d) + d = get_string_resource (dpy, "colorPrograms", "ColorPrograms"); + if (d && !*d) { free(d); d = 0; } + + if (d) + { + fprintf (stderr, + "%s: the `monoPrograms' and `colorPrograms' resources are obsolete;\n\ + see the manual for details.\n", blurb()); + free(d); + } + + d = get_string_resource (dpy, "programs", "Programs"); + + free_screenhack_list (p->screenhacks, p->screenhacks_count); + p->screenhacks = 0; + p->screenhacks_count = 0; + + if (!d || !*d) + return; + + size = strlen (d); + + + /* Count up the number of newlines (which will be equal to or larger than + one less than the number of hacks.) + */ + for (i = j = 0; d[i]; i++) + if (d[i] == '\n') + j++; + j++; + + p->screenhacks = (screenhack **) calloc (j + 1, sizeof (screenhack *)); + + /* Iterate over the lines in `d' (the string with newlines) + and make new strings to stuff into the `screenhacks' array. + */ + p->screenhacks_count = 0; + while (start < size) + { + /* skip forward over whitespace. */ + while (d[start] == ' ' || d[start] == '\t' || d[start] == '\n') + start++; + + /* skip forward to newline or end of string. */ + end = start; + while (d[end] != 0 && d[end] != '\n') + end++; + + /* null terminate. */ + d[end] = 0; + + p->screenhacks[p->screenhacks_count++] = parse_screenhack (d + start); + if (p->screenhacks_count >= i) + abort(); + + start = end+1; + } + + free (d); + + if (p->screenhacks_count == 0) + { + free (p->screenhacks); + p->screenhacks = 0; + } +} + + +/* Make sure all the values in the preferences struct are sane. + */ +static void +stop_the_insanity (saver_preferences *p) +{ + if (p->passwd_timeout <= 0) p->passwd_timeout = 30000; /* 30 secs */ + if (p->timeout < 15000) p->timeout = 15000; /* 15 secs */ + if (p->cycle != 0 && p->cycle < 2000) p->cycle = 2000; /* 2 secs */ + if (p->pointer_timeout <= 0) p->pointer_timeout = 5000; /* 5 secs */ + if (p->notice_events_timeout <= 0) + p->notice_events_timeout = 10000; /* 10 secs */ + if (p->fade_seconds <= 0 || p->fade_ticks <= 0) + p->fade_p = False; + if (! p->fade_p) p->unfade_p = False; + + /* The DPMS settings may have the value 0. + But if they are negative, or are a range less than 10 seconds, + reset them to sensible defaults. (Since that must be a mistake.) + */ + if (p->dpms_standby != 0 && + p->dpms_standby < 10 * 1000) + p->dpms_standby = 2 * 60 * 60 * 1000; /* 2 hours */ + if (p->dpms_suspend != 0 && + p->dpms_suspend < 10 * 1000) + p->dpms_suspend = 2 * 60 * 60 * 1000; /* 2 hours */ + if (p->dpms_off != 0 && + p->dpms_off < 10 * 1000) + p->dpms_off = 4 * 60 * 60 * 1000; /* 4 hours */ + + /* suspend may not be greater than off, unless off is 0. + standby may not be greater than suspend, unless suspend is 0. + */ + if (p->dpms_off != 0 && + p->dpms_suspend > p->dpms_off) + p->dpms_suspend = p->dpms_off; + if (p->dpms_suspend != 0 && + p->dpms_standby > p->dpms_suspend) + p->dpms_standby = p->dpms_suspend; + + /* These fixes above ignores the case + suspend = 0 and standby > off ... + */ + if (p->dpms_off != 0 && + p->dpms_standby > p->dpms_off) + p->dpms_standby = p->dpms_off; + + + if (p->dpms_standby == 0 && /* if *all* are 0, then DPMS is disabled */ + p->dpms_suspend == 0 && + p->dpms_off == 0) + p->dpms_enabled_p = False; + + + /* Set watchdog timeout to about half of the cycle timeout, but + don't let it be faster than 1/2 minute or slower than 1 minute. + */ + p->watchdog_timeout = p->cycle * 0.6; + if (p->watchdog_timeout < 27000) p->watchdog_timeout = 27000; /* 27 secs */ + if (p->watchdog_timeout > 57000) p->watchdog_timeout = 57000; /* 57 secs */ + + if (p->pointer_hysteresis < 0) p->pointer_hysteresis = 0; + if (p->pointer_hysteresis > 100) p->pointer_hysteresis = 100; +} diff --git a/driver/prefs.h b/driver/prefs.h new file mode 100644 index 00000000..eeb272ef --- /dev/null +++ b/driver/prefs.h @@ -0,0 +1,35 @@ +/* xscreensaver, Copyright (c) 1993-2006 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. + */ + +#ifndef __XSCREENSAVER_PREFS_H__ +#define __XSCREENSAVER_PREFS_H__ + +#include "types.h" + +extern void load_init_file (Display *, saver_preferences *); +extern Bool init_file_changed_p (saver_preferences *); +extern int write_init_file (Display *, + saver_preferences *, const char *version_string, + Bool verbose_p); +const char *init_file_name (void); + +extern screenhack *parse_screenhack (const char *line); +extern void free_screenhack (screenhack *); +extern char *format_hack (Display *, screenhack *, Bool wrap_p); +char *make_hack_name (Display *, const char *shell_command); + +/* From dpms.c */ +extern void sync_server_dpms_settings (Display *, Bool enabled_p, + int standby_secs, int suspend_secs, + int off_secs, + Bool verbose_p); + +#endif /* __XSCREENSAVER_PREFS_H__ */ diff --git a/driver/remote.c b/driver/remote.c new file mode 100644 index 00000000..775036ac --- /dev/null +++ b/driver/remote.c @@ -0,0 +1,595 @@ +/* xscreensaver-command, Copyright (c) 1991-2009 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. + */ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include +#include +#include +#include +#include + +#ifdef HAVE_SYS_SELECT_H +# include +#endif /* HAVE_SYS_SELECT_H */ + +#ifdef HAVE_UNISTD_H +# include +#endif + +#include /* for CARD32 */ +#include +#include +#include /* for XGetClassHint() */ +#include + +#include "remote.h" + +#ifdef _VROOT_H_ +ERROR! you must not include vroot.h in this file +#endif + +extern char *progname; +extern Atom XA_SCREENSAVER, XA_SCREENSAVER_VERSION, XA_SCREENSAVER_RESPONSE; +extern Atom XA_SCREENSAVER_ID, XA_SCREENSAVER_STATUS, XA_EXIT; +extern Atom XA_VROOT, XA_SELECT, XA_DEMO, XA_BLANK, XA_LOCK; + + +static XErrorHandler old_handler = 0; +static Bool got_badwindow = False; +static int +BadWindow_ehandler (Display *dpy, XErrorEvent *error) +{ + if (error->error_code == BadWindow) + { + got_badwindow = True; + return 0; + } + else + { + fprintf (stderr, "%s: ", progname); + if (!old_handler) abort(); + return (*old_handler) (dpy, error); + } +} + + + +static Window +find_screensaver_window (Display *dpy, char **version) +{ + int i; + Window root = RootWindowOfScreen (DefaultScreenOfDisplay (dpy)); + Window root2, parent, *kids; + unsigned int nkids; + + if (version) *version = 0; + + if (! XQueryTree (dpy, root, &root2, &parent, &kids, &nkids)) + abort (); + if (root != root2) + abort (); + if (parent) + abort (); + if (! (kids && nkids)) + return 0; + for (i = 0; i < nkids; i++) + { + Atom type; + int format; + unsigned long nitems, bytesafter; + unsigned char *v; + int status; + + /* We're walking the list of root-level windows and trying to find + the one that has a particular property on it. We need to trap + BadWindows errors while doing this, because it's possible that + some random window might get deleted in the meantime. (That + window won't have been the one we're looking for.) + */ + XSync (dpy, False); + if (old_handler) abort(); + got_badwindow = False; + old_handler = XSetErrorHandler (BadWindow_ehandler); + status = XGetWindowProperty (dpy, kids[i], + XA_SCREENSAVER_VERSION, + 0, 200, False, XA_STRING, + &type, &format, &nitems, &bytesafter, + &v); + XSync (dpy, False); + XSetErrorHandler (old_handler); + old_handler = 0; + + if (got_badwindow) + { + status = BadWindow; + got_badwindow = False; + } + + if (status == Success && type != None) + { + Window ret = kids[i]; + if (version) + *version = (char *) v; + XFree (kids); + return ret; + } + } + + if (kids) XFree (kids); + return 0; +} + + +static int +send_xscreensaver_command (Display *dpy, Atom command, long arg, + Window *window_ret, char **error_ret) +{ + int status = -1; + char *v = 0; + Window window = find_screensaver_window (dpy, &v); + XWindowAttributes xgwa; + char err[2048]; + + if (window_ret) + *window_ret = window; + + if (!window) + { + sprintf (err, "no screensaver is running on display %s", + DisplayString (dpy)); + + if (error_ret) + { + *error_ret = strdup (err); + status = -1; + goto DONE; + } + + if (command == XA_EXIT) + { + /* Don't print an error if xscreensaver is already dead. */ + status = 1; + goto DONE; + } + + fprintf (stderr, "%s: %s\n", progname, err); + status = -1; + goto DONE; + } + + /* Select for property change events, so that we can read the response. */ + XGetWindowAttributes (dpy, window, &xgwa); + XSelectInput (dpy, window, xgwa.your_event_mask | PropertyChangeMask); + + if (command == XA_SCREENSAVER_STATUS || + command == XA_SCREENSAVER_VERSION) + { + XClassHint hint; + memset (&hint, 0, sizeof(hint)); + if (!v || !*v) + { + sprintf (err, "version property not set on window 0x%x?", + (unsigned int) window); + if (error_ret) + *error_ret = strdup (err); + else + fprintf (stderr, "%s: %s\n", progname, err); + + status = -1; + goto DONE; + } + + XGetClassHint(dpy, window, &hint); + if (!hint.res_class) + { + sprintf (err, "class hints not set on window 0x%x?", + (unsigned int) window); + if (error_ret) + *error_ret = strdup (err); + else + fprintf (stderr, "%s: %s\n", progname, err); + + status = -1; + goto DONE; + } + + fprintf (stdout, "%s %s", hint.res_class, v); + + if (command != XA_SCREENSAVER_STATUS) + { + fprintf (stdout, "\n"); + } + else + { + Atom type; + int format; + unsigned long nitems, bytesafter; + unsigned char *dataP = 0; + + if (XGetWindowProperty (dpy, + RootWindow (dpy, 0), + XA_SCREENSAVER_STATUS, + 0, 999, False, XA_INTEGER, + &type, &format, &nitems, &bytesafter, + &dataP) + == Success + && type + && dataP) + { + Atom blanked; + time_t tt; + char *s; + Atom *data = (Atom *) dataP; + + if (type != XA_INTEGER || nitems < 3) + { + STATUS_LOSE: + if (data) free (data); + fprintf (stdout, "\n"); + fflush (stdout); + fprintf (stderr, "bad status format on root window.\n"); + status = -1; + goto DONE; + } + + blanked = (Atom) data[0]; + tt = (time_t) data[1]; + + if (tt <= (time_t) 666000000L) /* early 1991 */ + goto STATUS_LOSE; + + if (blanked == XA_BLANK) + fputs (": screen blanked since ", stdout); + else if (blanked == XA_LOCK) + fputs (": screen locked since ", stdout); + else if (blanked == 0) + /* suggestions for a better way to phrase this are welcome. */ + fputs (": screen non-blanked since ", stdout); + else + /* `blanked' has an unknown value - fail. */ + goto STATUS_LOSE; + + s = ctime(&tt); + if (s[strlen(s)-1] == '\n') + s[strlen(s)-1] = 0; + fputs (s, stdout); + + { + int nhacks = nitems - 2; + Bool any = False; + int i; + for (i = 0; i < nhacks; i++) + if (data[i + 2] > 0) + { + any = True; + break; + } + + if (any && nhacks == 1) + fprintf (stdout, " (hack #%d)\n", (int) data[2]); + else if (any) + { + fprintf (stdout, " (hacks: "); + for (i = 0; i < nhacks; i++) + { + fprintf (stdout, "#%d", (int) data[2 + i]); + if (i != nhacks-1) + fputs (", ", stdout); + } + fputs (")\n", stdout); + } + else + fputs ("\n", stdout); + } + + if (data) free (data); + } + else + { + if (dataP) XFree (dataP); + fprintf (stdout, "\n"); + fflush (stdout); + fprintf (stderr, "no saver status on root window.\n"); + status = -1; + goto DONE; + } + } + + /* No need to read a response for these commands. */ + status = 1; + goto DONE; + } + else + { + XEvent event; + long arg1 = arg; + long arg2 = 0; + + if (arg < 0) + abort(); + else if (arg == 0 && command == XA_SELECT) + abort(); + else if (arg != 0 && command == XA_DEMO) + { + arg1 = 5000; /* version number of the XA_DEMO protocol, */ + arg2 = arg; /* since it didn't use to take an argument. */ + } + + event.xany.type = ClientMessage; + event.xclient.display = dpy; + event.xclient.window = window; + event.xclient.message_type = XA_SCREENSAVER; + event.xclient.format = 32; + memset (&event.xclient.data, 0, sizeof(event.xclient.data)); + event.xclient.data.l[0] = (long) command; + event.xclient.data.l[1] = arg1; + event.xclient.data.l[2] = arg2; + if (! XSendEvent (dpy, window, False, 0L, &event)) + { + sprintf (err, "XSendEvent(dpy, 0x%x ...) failed.\n", + (unsigned int) window); + if (error_ret) + *error_ret = strdup (err); + else + fprintf (stderr, "%s: %s\n", progname, err); + status = -1; + goto DONE; + } + } + + status = 0; + + DONE: + if (v) free (v); + XSync (dpy, 0); + return status; +} + + +static Bool +xscreensaver_command_event_p (Display *dpy, XEvent *event, XPointer arg) +{ + return (event->xany.type == PropertyNotify && + event->xproperty.state == PropertyNewValue && + event->xproperty.atom == XA_SCREENSAVER_RESPONSE); +} + + +static int +xscreensaver_command_response (Display *dpy, Window window, + Bool verbose_p, Bool exiting_p, + char **error_ret) +{ + int sleep_count = 0; + char err[2048]; + XEvent event; + Bool got_event = False; + + while (!(got_event = XCheckIfEvent(dpy, &event, + &xscreensaver_command_event_p, 0)) && + sleep_count++ < 10) + { +# if defined(HAVE_SELECT) + /* Wait for an event, but don't wait longer than 1 sec. Note that we + might do this multiple times if an event comes in, but it wasn't + the event we're waiting for. + */ + int fd = XConnectionNumber(dpy); + fd_set rset; + struct timeval tv; + tv.tv_sec = 1; + tv.tv_usec = 0; + FD_ZERO (&rset); + FD_SET (fd, &rset); + select (fd+1, &rset, 0, 0, &tv); +# else /* !HAVE_SELECT */ + sleep(1); +# endif /* !HAVE_SELECT */ + } + + if (!got_event) + { + sprintf (err, "no response to command."); + if (error_ret) + *error_ret = strdup (err); + else + fprintf (stderr, "%s: %s\n", progname, err); + + return -1; + } + else + { + Status st2; + Atom type; + int format; + unsigned long nitems, bytesafter; + unsigned char *msg = 0; + + XSync (dpy, False); + if (old_handler) abort(); + old_handler = XSetErrorHandler (BadWindow_ehandler); + st2 = XGetWindowProperty (dpy, window, + XA_SCREENSAVER_RESPONSE, + 0, 1024, True, + AnyPropertyType, + &type, &format, &nitems, &bytesafter, + &msg); + XSync (dpy, False); + XSetErrorHandler (old_handler); + old_handler = 0; + + if (got_badwindow) + { + if (exiting_p) + return 0; + + sprintf (err, "xscreensaver window unexpectedly deleted."); + + if (error_ret) + *error_ret = strdup (err); + else + fprintf (stderr, "%s: %s\n", progname, err); + + return -1; + } + + if (st2 == Success && type != None) + { + if (type != XA_STRING || format != 8) + { + sprintf (err, "unrecognized response property."); + + if (error_ret) + *error_ret = strdup (err); + else + fprintf (stderr, "%s: %s\n", progname, err); + + if (msg) XFree (msg); + return -1; + } + else if (!msg || (msg[0] != '+' && msg[0] != '-')) + { + sprintf (err, "unrecognized response message."); + + if (error_ret) + *error_ret = strdup (err); + else + fprintf (stderr, "%s: %s\n", progname, err); + + if (msg) XFree (msg); + return -1; + } + else + { + int ret = (msg[0] == '+' ? 0 : -1); + sprintf (err, "%s: %s\n", progname, (char *) msg+1); + + if (error_ret) + *error_ret = strdup (err); + else if (verbose_p || ret != 0) + fprintf ((ret < 0 ? stderr : stdout), "%s\n", err); + + XFree (msg); + return ret; + } + } + } + + return -1; /* warning suppression: not actually reached */ +} + + +int +xscreensaver_command (Display *dpy, Atom command, long arg, Bool verbose_p, + char **error_ret) +{ + Window w = 0; + int status = send_xscreensaver_command (dpy, command, arg, &w, error_ret); + if (status == 0) + status = xscreensaver_command_response (dpy, w, verbose_p, + (command == XA_EXIT), + error_ret); + + fflush (stdout); + fflush (stderr); + return (status < 0 ? status : 0); +} + + +void +server_xscreensaver_version (Display *dpy, + char **version_ret, + char **user_ret, + char **host_ret) +{ + Window window = find_screensaver_window (dpy, 0); + + Atom type; + int format; + unsigned long nitems, bytesafter; + + if (version_ret) + *version_ret = 0; + if (user_ret) + *user_ret = 0; + if (host_ret) + *host_ret = 0; + + if (!window) + return; + + if (version_ret) + { + unsigned char *v = 0; + XGetWindowProperty (dpy, window, XA_SCREENSAVER_VERSION, 0, 1, + False, XA_STRING, &type, &format, &nitems, + &bytesafter, &v); + if (v) + { + *version_ret = strdup ((char *) v); + XFree (v); + } + } + + if (user_ret || host_ret) + { + unsigned char *id = 0; + const char *user = 0; + const char *host = 0; + + XGetWindowProperty (dpy, window, XA_SCREENSAVER_ID, 0, 512, + False, XA_STRING, &type, &format, &nitems, + &bytesafter, &id); + if (id && *id) + { + const char *old_tag = " on host "; + const char *s = strstr ((char *) id, old_tag); + if (s) + { + /* found ID of the form "1234 on host xyz". */ + user = 0; + host = s + strlen (old_tag); + } + else + { + char *o = 0, *p = 0, *c = 0; + o = strchr ((char *) id, '('); + if (o) p = strchr (o, '@'); + if (p) c = strchr (p, ')'); + if (c) + { + /* found ID of the form "1234 (user@host)". */ + user = o+1; + host = p+1; + *p = 0; + *c = 0; + } + } + + } + + if (user && *user && *user != '?') + *user_ret = strdup (user); + else + *user_ret = 0; + + if (host && *host && *host != '?') + *host_ret = strdup (host); + else + *host_ret = 0; + + if (id) + XFree (id); + } +} diff --git a/driver/remote.h b/driver/remote.h new file mode 100644 index 00000000..e1db3517 --- /dev/null +++ b/driver/remote.h @@ -0,0 +1,24 @@ +/* xscreensaver-command, Copyright (c) 1991-1998 + * 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. + */ + +#ifndef _XSCREENSAVER_REMOTE_H_ +#define _XSCREENSAVER_REMOTE_H_ + +extern int xscreensaver_command (Display *dpy, Atom command, long arg, + Bool verbose_p, char **error_ret); + +extern void server_xscreensaver_version (Display *dpy, + char **version_ret, + char **user_ret, + char **host_ret); + +#endif /* _XSCREENSAVER_REMOTE_H_ */ diff --git a/driver/screens.c b/driver/screens.c new file mode 100644 index 00000000..52320d65 --- /dev/null +++ b/driver/screens.c @@ -0,0 +1,1077 @@ +/* screens.c --- dealing with RANDR, Xinerama, and VidMode Viewports. + * xscreensaver, Copyright (c) 1991-2008 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. + */ + +/* There are a bunch of different mechanisms for multiple monitors + * available in X. XScreenSaver needs to care about this for two + * reasons: first, to ensure that all visible areas go black; and + * second, so that the windows of screen savers exactly fill the + * glass of each monitor (instead of one saver spanning multiple + * monitors, or a monitor displaying only a sub-rectangle of the + * screen saver.) + * + * 1) Multi-screen: + * + * This is the original way. Each monitor gets its own display + * number. :0.0 is the first one, :0.1 is the next, etc. The + * value of $DISPLAY determines which screen windows open on by + * default. A single app can open windows on multiple screens + * with the same display connection, but windows cannot be moved + * from one screen to another. The mouse can be moved from one + * screen to another, though. Screens may be different depths + * (e.g., one can be TrueColor and one can be PseudoColor.) + * Screens cannot be resized or moved without restarting X. + * + * Everyone hates this way of doing things because of the + * inability to move a window from one screen to another without + * restarting the application. + * + * 2) Xinerama: + * + * There is a single giant root window that spans all the + * monitors. All monitors are the same depth, and windows can be + * moved around. Applications can learn which rectangles are + * actually visible on monitors by querying the Xinerama server + * extension. (If you don't do that, you end up with dialog + * boxes that try to appear in the middle of the screen actually + * spanning the gap between two monitors.) + * + * Xinerama doesn't work with DRI, which means that if you use + * it, you lose hardware acceleration on OpenGL programs. Also, + * screens can't be resized or moved without restarting X. + * + * 3) Vidmode Viewports: + * + * With this extension, the root window can be bigger than the + * monitor. Moving the mouse near the edges of the screen + * scrolls around, like a pan-and-scan movie. There can also be + * a hot key for changing the monitor's resolution (zooming + * in/out). + * + * Trying to combine this with Xinerama crashes the server, so + * you can only use this if you have only a single screen, or are + * in old-multi-screen mode. + * + * Also, half the time it doesn't work at all: it tends to lie + * about the size of the rectangle in use. + * + * 4) RANDR 1.0: + * + * The first version of the "Resize and Rotate" extension let you + * change the resolution of a screen on the fly. The root window + * would actually resize. However, it was also incompatible with + * Xinerama (did it crash, or just do nothing? I can't remember) + * so you needed to be in single-screen or old multi-screen mode. + * I believe RANDR could co-exist with Vidmode Viewports, but I'm + * not sure. + * + * 5) RANDR 1.2: + * + * Finally, RANDR added the functionality of Xinerama, plus some. + * Each X screen (in the sense of #1, "multi-screen") can have a + * number of sub-rectangles that are displayed on monitors, and + * each of those sub-rectangles can be displayed on more than one + * monitor. So it's possible (I think) to have a hybrid of + * multi-screen and Xinerama (e.g., to have two monitors running + * in one depth, and three monitors running in another?) + * Typically though, there will be a single X screen, with + * Xinerama-like division of that large root window onto multiple + * monitors. Also everything's dynamic: monitors can be added, + * removed, and resized at runtime. + * + * I believe that as of RANDR 1.2, the Xinerama extension still + * exists but only as a compatiblity layer: it's actually + * returning data from the RANDR extension. + * + * Though RANDR 1.2 allows the same image to be cloned onto more + * than one monitor, and also allows one monitor to show a + * subsection of something on another monitor (e.g., the + * rectangles can be enclosed or overlap). Since there's no way + * to put seperate savers on those duplicated-or-overlapping + * monitors, xscreensaver just ignores them (which allows them to + * display duplicates or overlaps). + * + * 5a) Nvidia fucks it up: + * + * Nvidia drivers as of Aug 2008 running in "TwinView" mode + * apparently report correct screen geometry via Xinerama, but + * report one giant screen via RANDR. The response from the + * nvidia developers is, "we don't support RANDR, use Xinerama + * instead." Which is a seriously lame answer. So, xscreensaver + * has to query *both* extensions, and make a guess as to which + * is to be believed. + * + * 5b) Also sometimes RANDR says stupid shit like, "You have one + * screen, and it has no available orientations or sizes." + * + */ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include + +#ifdef HAVE_RANDR +# include +#endif /* HAVE_RANDR */ + +#ifdef HAVE_XINERAMA +# include +#endif /* HAVE_XINERAMA */ + +#ifdef HAVE_XF86VMODE +# include +#endif /* HAVE_XF86VMODE */ + +/* This file doesn't need the Xt headers, so stub these types out... */ +#undef XtPointer +#define XtAppContext void* +#define XrmDatabase void* +#define XtIntervalId void* +#define XtPointer void* +#define Widget void* + +#include "xscreensaver.h" +#include "visual.h" + + +typedef enum { S_SANE, S_ENCLOSED, S_DUPLICATE, S_OVERLAP, + S_OFFSCREEN, S_DISABLED } monitor_sanity; + +/* 'typedef monitor' is in types.h */ +struct _monitor { + int id; + char *desc; + Screen *screen; + int x, y, width, height; + monitor_sanity sanity; /* I'm not crazy you're the one who's crazy */ + int enemy; /* which monitor it overlaps or duplicates */ + char *err; /* msg to print at appropriate later time; + exists only on monitor #0. */ +}; + +static Bool layouts_differ_p (monitor **a, monitor **b); + + +static void +free_monitors (monitor **monitors) +{ + monitor **m2 = monitors; + if (! monitors) return; + while (*m2) + { + if ((*m2)->desc) free ((*m2)->desc); + if ((*m2)->err) free ((*m2)->err); + free (*m2); + m2++; + } + free (monitors); +} + + +static char * +append (char *s1, const char *s2) +{ + char *s = (char *) malloc ((s1 ? strlen(s1) : 0) + + (s2 ? strlen(s2) : 0) + 3); + *s = 0; + if (s1) strcat (s, s1); + if (s1 && s2) strcat (s, "\n"); + if (s2) strcat (s, s2); + if (s1) free (s1); + return s; +} + + +#ifdef HAVE_XINERAMA + +static monitor ** +xinerama_scan_monitors (Display *dpy, char **errP) +{ + Screen *screen = DefaultScreenOfDisplay (dpy); + int event, error, nscreens, i; + XineramaScreenInfo *xsi; + monitor **monitors; + + if (! XineramaQueryExtension (dpy, &event, &error)) + return 0; + + if (! XineramaIsActive (dpy)) + return 0; + + xsi = XineramaQueryScreens (dpy, &nscreens); + if (!xsi) return 0; + + monitors = (monitor **) calloc (nscreens + 1, sizeof(*monitors)); + if (!monitors) return 0; + + for (i = 0; i < nscreens; i++) + { + monitor *m = (monitor *) calloc (1, sizeof (monitor)); + monitors[i] = m; + m->id = i; + m->screen = screen; + m->x = xsi[i].x_org; + m->y = xsi[i].y_org; + m->width = xsi[i].width; + m->height = xsi[i].height; + } + return monitors; +} + +#endif /* HAVE_XINERAMA */ + + +#ifdef HAVE_XF86VMODE + +static monitor ** +vidmode_scan_monitors (Display *dpy, char **errP) +{ + int event, error, nscreens, i; + monitor **monitors; + + /* Note that XF86VidModeGetViewPort() tends to be full of lies on laptops + that have a docking station or external monitor that runs in a different + resolution than the laptop's screen: + + http://bugzilla.redhat.com/bugzilla/show_bug.cgi?id=81593 + http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=208417 + http://bugs.xfree86.org/show_bug.cgi?id=421 + + Presumably this is fixed by using RANDR instead of VidMode. + */ + +# ifdef HAVE_XINERAMA + /* Attempts to use the VidMode extension when the Xinerama extension is + active can result in a server crash! Yay! */ + if (XQueryExtension (dpy, "XINERAMA", &error, &event, &error)) + return 0; +# endif /* !HAVE_XINERAMA */ + + if (! XF86VidModeQueryExtension (dpy, &event, &error)) + return 0; + + nscreens = ScreenCount (dpy); + monitors = (monitor **) calloc (nscreens + 1, sizeof(*monitors)); + if (!monitors) return 0; + + for (i = 0; i < nscreens; i++) + { + monitor *m = (monitor *) calloc (1, sizeof (monitor)); + XF86VidModeModeLine ml; + int dot; + Screen *screen = ScreenOfDisplay (dpy, i); + + monitors[i] = m; + m->id = i; + m->screen = screen; + + if (! safe_XF86VidModeGetViewPort (dpy, i, &m->x, &m->y)) + m->x = m->y = -1; + + if (XF86VidModeGetModeLine (dpy, i, &dot, &ml)) + { + m->width = ml.hdisplay; + m->height = ml.vdisplay; + } + + /* Apparently, though the server stores the X position in increments of + 1 pixel, it will only make changes to the *display* in some other + increment. With XF86_SVGA on a Thinkpad, the display only updates + in multiples of 8 pixels when in 8-bit mode, and in multiples of 4 + pixels in 16-bit mode. I don't know what it does in 24- and 32-bit + mode, because I don't have enough video memory to find out. + + I consider it a bug that XF86VidModeGetViewPort() is telling me the + server's *target* scroll position rather than the server's *actual* + scroll position. David Dawes agrees, and says they may fix this in + XFree86 4.0, but it's notrivial. + + He also confirms that this behavior is server-dependent, so the + actual scroll position cannot be reliably determined by the client. + So... that means the only solution is to provide a ``sandbox'' + around the blackout window -- we make the window be up to N pixels + larger than the viewport on both the left and right sides. That + means some part of the outer edges of each hack might not be + visible, but screw it. + + I'm going to guess that 16 pixels is enough, and that the Y dimension + doesn't have this problem. + + The drawback of doing this, of course, is that some of the screenhacks + will still look pretty stupid -- for example, "slidescreen" will cut + off the left and right edges of the grid, etc. + */ +# define FUDGE 16 + if (m->x > 0 && m->x < m->width - ml.hdisplay) + { + /* Not at left edge or right edge: + Round X position down to next lower multiple of FUDGE. + Increase width by 2*FUDGE in case some server rounds up. + */ + m->x = ((m->x - 1) / FUDGE) * FUDGE; + m->width += (FUDGE * 2); + } +# undef FUDGE + } + + return monitors; +} + +#endif /* HAVE_XF86VMODE */ + + +#ifdef HAVE_RANDR + +static monitor ** +randr_scan_monitors (Display *dpy, char **errP) +{ + int event, error, major, minor, nscreens, i, j; + monitor **monitors; + Bool new_randr_p = False; + + if (! XRRQueryExtension (dpy, &event, &error)) + return 0; + + if (! XRRQueryVersion (dpy, &major, &minor)) + return 0; + + if (major <= 0) /* Protocol was still in flux back then -- fuck it. */ + return 0; + +# ifdef HAVE_RANDR_12 + new_randr_p = (major > 1 || (major == 1 && minor >= 2)); +# endif + + if (! new_randr_p) + /* RANDR 1.0 -- no Xinerama-like virtual screens. */ + nscreens = ScreenCount (dpy); + else /* RANDR 1.2 or newer -- built-in Xinerama */ + { +# ifdef HAVE_RANDR_12 + int xsc = ScreenCount (dpy); + nscreens = 0; + /* Add up the virtual screens on each X screen. */ + for (i = 0; i < xsc; i++) + { + XRRScreenResources *res = + XRRGetScreenResources (dpy, RootWindow (dpy, i)); + nscreens += res->noutput; + XRRFreeScreenResources (res); + } +# endif /* HAVE_RANDR_12 */ + } + + if (nscreens <= 0) + { + *errP = append (*errP, + "WARNING: RANDR reported no screens! Ignoring it."); + return 0; + } + + monitors = (monitor **) calloc (nscreens + 1, sizeof(*monitors)); + if (!monitors) return 0; + + for (i = 0, j = 0; i < ScreenCount (dpy); i++) + { + Screen *screen = ScreenOfDisplay (dpy, i); + + if (! new_randr_p) /* RANDR 1.0 */ + { + XRRScreenConfiguration *rrc; + monitor *m = (monitor *) calloc (1, sizeof (monitor)); + monitors[i] = m; + m->screen = screen; + m->id = i; + + rrc = XRRGetScreenInfo (dpy, RootWindowOfScreen (screen)); + if (rrc) + { + SizeID size = -1; + Rotation rot = ~0; + XRRScreenSize *rrsizes; + int nsizes = 0; + + size = XRRConfigCurrentConfiguration (rrc, &rot); + rrsizes = XRRConfigSizes (rrc, &nsizes); + + if (nsizes <= 0) /* WTF? Shouldn't happen but does. */ + { + m->width = DisplayWidth (dpy, i); + m->height = DisplayHeight (dpy, i); + } + else if (rot & (RR_Rotate_90|RR_Rotate_270)) + { + m->width = rrsizes[size].height; + m->height = rrsizes[size].width; + } + else + { + m->width = rrsizes[size].width; + m->height = rrsizes[size].height; + } + + /* don't free 'rrsizes' */ + XRRFreeScreenConfigInfo (rrc); + } + } + else /* RANDR 1.2 or newer */ + { +# ifdef HAVE_RANDR_12 + int k; + XRRScreenResources *res = + XRRGetScreenResources (dpy, RootWindowOfScreen (screen)); + for (k = 0; k < res->noutput; k++, j++) + { + monitor *m = (monitor *) calloc (1, sizeof (monitor)); + XRROutputInfo *rroi = XRRGetOutputInfo (dpy, res, + res->outputs[k]); + RRCrtc crtc = (rroi->crtc ? rroi->crtc : + rroi->ncrtc ? rroi->crtcs[0] : 0); + XRRCrtcInfo *crtci = (crtc ? XRRGetCrtcInfo(dpy, res, crtc) : 0); + + monitors[j] = m; + m->screen = screen; + m->id = (i * 1000) + j; + m->desc = (rroi->name ? strdup (rroi->name) : 0); + + if (crtci) + { + /* Note: if the screen is rotated, XRRConfigSizes contains + the unrotated WxH, but XRRCrtcInfo contains rotated HxW. + */ + m->x = crtci->x; + m->y = crtci->y; + m->width = crtci->width; + m->height = crtci->height; + } + + if (rroi->connection == RR_Disconnected) + m->sanity = S_DISABLED; + /* #### do the same for RR_UnknownConnection? */ + + if (crtci) + XRRFreeCrtcInfo (crtci); + XRRFreeOutputInfo (rroi); + } + XRRFreeScreenResources (res); +# endif /* HAVE_RANDR_12 */ + } + } + + /* Work around more fucking brain damage. */ + { + int ok = 0; + int i = 0; + while (monitors[i]) + { + if (monitors[i]->width != 0 && monitors[i]->height != 0) + ok++; + i++; + } + if (! ok) + { + *errP = append (*errP, + "WARNING: RANDR says all screens are 0x0! Ignoring it."); + free_monitors (monitors); + monitors = 0; + } + } + + return monitors; +} + +#endif /* HAVE_RANDR */ + + +static monitor ** +basic_scan_monitors (Display *dpy, char **errP) +{ + int nscreens = ScreenCount (dpy); + int i; + monitor **monitors = (monitor **) calloc (nscreens + 1, sizeof(*monitors)); + if (!monitors) return 0; + + for (i = 0; i < nscreens; i++) + { + Screen *screen = ScreenOfDisplay (dpy, i); + monitor *m = (monitor *) calloc (1, sizeof (monitor)); + monitors[i] = m; + m->id = i; + m->screen = screen; + m->x = 0; + m->y = 0; + m->width = WidthOfScreen (screen); + m->height = HeightOfScreen (screen); + } + return monitors; +} + + +#if defined(HAVE_RANDR) && defined(HAVE_XINERAMA) + +/* From: Aaron Plattner + Date: August 7, 2008 10:21:25 AM PDT + To: linux-bugs@nvidia.com + + The NVIDIA X driver does not yet support RandR 1.2. The X server has + a compatibility layer in it that allows RandR 1.2 clients to talk to + RandR 1.1 drivers through an RandR 1.2 pseudo-output called "default". + This reports the total combined resolution of the TwinView display, + since it doesn't have any visibility into TwinView metamodes. There + is no way for the driver to prevent the server from turning on this + compatibility layer. + + The intention is for X client applications to continue to use the + Xinerama extension to query the screen geometry. RandR 1.2 reports + its own Xinerama info for this purpose. I would recommend against + modifying xscreensaver to try to get this information from RandR. + */ +static monitor ** +randr_versus_xinerama_fight (Display *dpy, monitor **randr_monitors, + char **errP) +{ + monitor **xinerama_monitors; + + if (!randr_monitors) + return 0; + + xinerama_monitors = xinerama_scan_monitors (dpy, errP); + if (!xinerama_monitors) + return randr_monitors; + + if (! layouts_differ_p (randr_monitors, xinerama_monitors)) + { + free_monitors (xinerama_monitors); + return randr_monitors; + } + else if ( randr_monitors[0] && !randr_monitors[1] && /* 1 monitor */ + xinerama_monitors[0] && xinerama_monitors[1]) /* >1 monitor */ + { + *errP = append (*errP, + "WARNING: RANDR reports 1 screen but Xinerama\n" + "\t\treports multiple. Believing Xinerama."); + free_monitors (randr_monitors); + return xinerama_monitors; + } + else + { + *errP = append (*errP, + "WARNING: RANDR and Xinerama report different\n" + "\t\tscreen layouts! Believing RANDR."); + free_monitors (xinerama_monitors); + return randr_monitors; + } +} + +#endif /* HAVE_RANDR && HAVE_XINERAMA */ + + +#ifdef DEBUG_MULTISCREEN + +/* If DEBUG_MULTISCREEN is defined, then in "-debug" mode, xscreensaver + will pretend that it is changing the number of connected monitors + every few seconds, using the geometries in the following list, + for stress-testing purposes. + */ +static monitor ** +debug_scan_monitors (Display *dpy, char **errP) +{ + static const char * const geoms[] = { + "1600x1028+0+22", + "1024x768+0+22", + "800x600+0+22", + "800x600+0+22,800x600+800+22", + "800x600+0+22,800x600+800+22,800x600+300+622", + "800x600+0+22,800x600+800+22,800x600+0+622,800x600+800+622", + "640x480+0+22,640x480+640+22,640x480+0+502,640x480+640+502", + "640x480+240+22,640x480+0+502,640x480+640+502", + "640x480+0+200,640x480+640+200", + "800x600+400+22", + "320x200+0+22,320x200+320+22,320x200+640+22,320x200+960+22,320x200+0+222,320x200+320+222,320x200+640+222,320x200+960+222,320x200+0+422,320x200+320+422,320x200+640+422,320x200+960+422,320x200+0+622,320x200+320+622,320x200+640+622,320x200+960+622,320x200+0+822,320x200+320+822,320x200+640+822,320x200+960+822" + }; + static int index = 0; + monitor **monitors = (monitor **) calloc (100, sizeof(*monitors)); + int nscreens = 0; + Screen *screen = DefaultScreenOfDisplay (dpy); + + char *s = strdup (geoms[index]); + char *token = strtok (s, ","); + while (token) + { + monitor *m = calloc (1, sizeof (monitor)); + char c; + m->id = nscreens; + m->screen = screen; + if (4 != sscanf (token, "%dx%d+%d+%d%c", + &m->width, &m->height, &m->x, &m->y, &c)) + abort(); + m->width -= 2; + m->height -= 2; + monitors[nscreens++] = m; + token = strtok (0, ","); + } + free (s); + + index = (index+1) % countof(geoms); + return monitors; +} + +#endif /* DEBUG_MULTISCREEN */ + + +#ifdef QUAD_MODE +static monitor ** +quadruple (monitor **monitors, Bool debug_p, char **errP) +{ + int i, j, count = 0; + monitor **monitors2; + while (monitors[count]) + count++; + monitors2 = (monitor **) calloc (count * 4 + 1, sizeof(*monitors)); + if (!monitors2) abort(); + + for (i = 0, j = 0; i < count; i++) + { + int k; + for (k = 0; k < 4; k++) + { + monitors2[j+k] = (monitor *) calloc (1, sizeof (monitor)); + *monitors2[j+k] = *monitors[i]; + monitors2[j+k]->width /= (debug_p ? 4 : 2); + monitors2[j+k]->height /= 2; + monitors2[j+k]->id = (monitors[i]->id * 4) + k; + monitors2[j+k]->name = (monitors[i]->name + ? strdup (monitors[i]->name) : 0); + } + monitors2[j+1]->x += monitors2[j]->width; + monitors2[j+2]->y += monitors2[j]->height; + monitors2[j+3]->x += monitors2[j]->width; + monitors2[j+3]->y += monitors2[j]->height; + j += 4; + } + + free_monitors (monitors); + return monitors2; +} +#endif /* QUAD_MODE */ + + +static monitor ** +scan_monitors (saver_info *si) +{ + saver_preferences *p = &si->prefs; + monitor **monitors = 0; + char *err = 0; + +# ifdef DEBUG_MULTISCREEN + if (! monitors) monitors = debug_scan_monitors (si->dpy, &err); +# endif + +# ifdef HAVE_RANDR + if (! p->getviewport_full_of_lies_p) + if (! monitors) monitors = randr_scan_monitors (si->dpy, &err); + +# ifdef HAVE_XINERAMA + monitors = randr_versus_xinerama_fight (si->dpy, monitors, &err); +# endif +# endif /* HAVE_RANDR */ + +# ifdef HAVE_XF86VMODE + if (! monitors) monitors = vidmode_scan_monitors (si->dpy, &err); +# endif + +# ifdef HAVE_XINERAMA + if (! monitors) monitors = xinerama_scan_monitors (si->dpy, &err); +# endif + + if (! monitors) monitors = basic_scan_monitors (si->dpy, &err); + +# ifdef QUAD_MODE + if (p->quad_p) + monitors = quadruple (monitors, p->debug_p, &err); +# endif + + if (monitors && err) monitors[0]->err = err; + + return monitors; +} + + +static Bool +monitors_overlap_p (monitor *a, monitor *b) +{ + /* Two rectangles overlap if the max of the tops is less than the + min of the bottoms and the max of the lefts is less than the min + of the rights. + */ +# undef MAX +# undef MIN +# define MAX(A,B) ((A)>(B)?(A):(B)) +# define MIN(A,B) ((A)<(B)?(A):(B)) + + int maxleft = MAX(a->x, b->x); + int maxtop = MAX(a->y, b->y); + int minright = MIN(a->x + a->width - 1, b->x + b->width); + int minbot = MIN(a->y + a->height - 1, b->y + b->height); + return (maxtop < minbot && maxleft < minright); +} + + +static Bool +plausible_aspect_ratio_p (monitor **monitors) +{ + /* Modern wide-screen monitors come in the following aspect ratios: + + One monitor: If you tack a 640x480 monitor + onto the right, the ratio is: + 16 x 9 --> 1.78 + 852 x 480 --> 1.77 852+640 x 480 --> 3.11 "SD 480p" + 1280 x 720 --> 1.78 1280+640 x 720 --> 2.67 "HD 720p" + 1280 x 920 --> 1.39 1280+640 x 920 --> 2.09 + 1366 x 768 --> 1.78 1366+640 x 768 --> 2.61 "HD 768p" + 1440 x 900 --> 1.60 1440+640 x 900 --> 2.31 + 1680 x 1050 --> 1.60 1680+640 x 1050 --> 2.21 + 1690 x 1050 --> 1.61 1690+640 x 1050 --> 2.22 + 1920 x 1080 --> 1.78 1920+640 x 1080 --> 2.37 "HD 1080p" + 1920 x 1200 --> 1.60 1920+640 x 1200 --> 2.13 + 2560 x 1600 --> 1.60 2560+640 x 1600 --> 2.00 + + So that implies that if we ever see an aspect ratio >= 2.0, + we can be pretty sure that the X server is lying to us, and + that's actually two monitors, not one. + */ + if (monitors[0] && !monitors[1] && /* exactly 1 monitor */ + monitors[0]->height && + monitors[0]->width / (double) monitors[0]->height >= 1.9) + return False; + else + return True; +} + + +/* Mark the ones that overlap, etc. + */ +static void +check_monitor_sanity (monitor **monitors) +{ + int i, j, count = 0; + + while (monitors[count]) + count++; + +# define X1 monitors[i]->x +# define X2 monitors[j]->x +# define Y1 monitors[i]->y +# define Y2 monitors[j]->y +# define W1 monitors[i]->width +# define W2 monitors[j]->width +# define H1 monitors[i]->height +# define H2 monitors[j]->height + + /* If a monitor is enclosed by any other monitor, that's insane. + */ + for (i = 0; i < count; i++) + for (j = 0; j < count; j++) + if (i != j && + monitors[i]->sanity == S_SANE && + monitors[j]->sanity == S_SANE && + monitors[i]->screen == monitors[j]->screen && + X2 >= X1 && + Y2 >= Y1 && + (X2+W2) <= (X1+W1) && + (Y2+H2) <= (Y1+H1)) + { + if (X1 == X2 && + Y1 == Y2 && + W1 == W2 && + H1 == H2) + monitors[j]->sanity = S_DUPLICATE; + else + monitors[j]->sanity = S_ENCLOSED; + monitors[j]->enemy = i; + } + + /* After checking for enclosure, check for other lossage against earlier + monitors. We do enclosure first so that we make sure to pick the + larger one. + */ + for (i = 0; i < count; i++) + for (j = 0; j < i; j++) + { + if (monitors[i]->sanity != S_SANE) continue; /* already marked */ + if (monitors[j]->sanity != S_SANE) continue; + if (monitors[i]->screen != monitors[j]->screen) continue; + + if (monitors_overlap_p (monitors[i], monitors[j])) + { + monitors[i]->sanity = S_OVERLAP; + monitors[i]->enemy = j; + } + } + + /* Finally, make sure all monitors have sane positions and sizes. + Xinerama sometimes reports 1024x768 VPs at -1936862040, -1953705044. + */ + for (i = 0; i < count; i++) + { + if (monitors[i]->sanity != S_SANE) continue; /* already marked */ + if (X1 < 0 || Y1 < 0 || + W1 <= 0 || H1 <= 0 || + X1+W1 >= 0x7FFF || Y1+H1 >= 0x7FFF) + { + monitors[i]->sanity = S_OFFSCREEN; + monitors[i]->enemy = 0; + } + } + +# undef X1 +# undef X2 +# undef Y1 +# undef Y2 +# undef W1 +# undef W2 +# undef H1 +# undef H2 +} + + +static Bool +layouts_differ_p (monitor **a, monitor **b) +{ + if (!a || !b) return True; + while (1) + { + if (!*a) break; + if (!*b) break; + if ((*a)->screen != (*b)->screen || + (*a)->x != (*b)->x || + (*a)->y != (*b)->y || + (*a)->width != (*b)->width || + (*a)->height != (*b)->height) + return True; + a++; + b++; + } + if (*a) return True; + if (*b) return True; + + return False; +} + + +void +describe_monitor_layout (saver_info *si) +{ + monitor **monitors = si->monitor_layout; + int count = 0; + int good_count = 0; + int bad_count = 0; + int implausible_p = !plausible_aspect_ratio_p (monitors); + + while (monitors[count]) + { + if (monitors[count]->sanity == S_SANE) + good_count++; + else + bad_count++; + count++; + } + + if (monitors[0]->err) /* deferred error msg */ + { + char *token = strtok (monitors[0]->err, "\n"); + while (token) + { + fprintf (stderr, "%s: %s\n", blurb(), token); + token = strtok (0, "\n"); + } + free (monitors[0]->err); + monitors[0]->err = 0; + } + + if (count == 0) + fprintf (stderr, "%s: no screens!\n", blurb()); + else + { + int i; + fprintf (stderr, "%s: screens in use: %d\n", blurb(), good_count); + for (i = 0; i < count; i++) + { + monitor *m = monitors[i]; + if (m->sanity != S_SANE) continue; + fprintf (stderr, "%s: %3d/%d: %dx%d+%d+%d", + blurb(), m->id, screen_number (m->screen), + m->width, m->height, m->x, m->y); + if (m->desc && *m->desc) fprintf (stderr, " (%s)", m->desc); + fprintf (stderr, "\n"); + } + if (bad_count > 0) + { + fprintf (stderr, "%s: rejected screens: %d\n", blurb(), bad_count); + for (i = 0; i < count; i++) + { + monitor *m = monitors[i]; + monitor *e = monitors[m->enemy]; + if (m->sanity == S_SANE) continue; + fprintf (stderr, "%s: %3d/%d: %dx%d+%d+%d", + blurb(), m->id, screen_number (m->screen), + m->width, m->height, m->x, m->y); + if (m->desc && *m->desc) fprintf (stderr, " (%s)", m->desc); + fprintf (stderr, " -- "); + switch (m->sanity) + { + case S_SANE: abort(); break; + case S_ENCLOSED: + fprintf (stderr, "enclosed by %d (%dx%d+%d+%d)\n", + e->id, e->width, e->height, e->x, e->y); + break; + case S_DUPLICATE: + fprintf (stderr, "duplicate of %d\n", e->id); + break; + case S_OVERLAP: + fprintf (stderr, "overlaps %d (%dx%d+%d+%d)\n", + e->id, e->width, e->height, e->x, e->y); + break; + case S_OFFSCREEN: + fprintf (stderr, "off screen (%dx%d)\n", + WidthOfScreen (e->screen), + HeightOfScreen (e->screen)); + break; + case S_DISABLED: + fprintf (stderr, "output disabled\n"); + break; + } + } + } + + if (implausible_p) + fprintf (stderr, + "%s: WARNING: single screen aspect ratio is %dx%d = %.2f\n" + "%s: probable X server bug in Xinerama/RANDR!\n", + blurb(), monitors[0]->width, monitors[0]->height, + monitors[0]->width / (double) monitors[0]->height, + blurb()); + } +} + + +/* Synchronize the contents of si->ssi to the current state of the monitors. + Doesn't change anything if nothing has changed; otherwise, alters and + reuses existing saver_screen_info structs as much as possible. + Returns True if anything changed. + */ +Bool +update_screen_layout (saver_info *si) +{ + monitor **monitors = scan_monitors (si); + int count = 0; + int good_count = 0; + int i, j; + int seen_screens[100] = { 0, }; + + if (! layouts_differ_p (monitors, si->monitor_layout)) + { + free_monitors (monitors); + return False; + } + + free_monitors (si->monitor_layout); + si->monitor_layout = monitors; + check_monitor_sanity (si->monitor_layout); + + while (monitors[count]) + { + if (monitors[count]->sanity == S_SANE) + good_count++; + count++; + } + + if (si->ssi_count == 0) + { + si->ssi_count = 10; + si->screens = (saver_screen_info *) + calloc (sizeof(*si->screens), si->ssi_count); + } + + if (si->ssi_count <= good_count) + { + si->ssi_count = good_count + 10; + si->screens = (saver_screen_info *) + realloc (si->screens, sizeof(*si->screens) * si->ssi_count); + memset (si->screens + si->nscreens, 0, + sizeof(*si->screens) * (si->ssi_count - si->nscreens)); + } + + if (! si->screens) abort(); + + si->nscreens = good_count; + + /* Regenerate the list of GL visuals as needed. */ + if (si->best_gl_visuals) + free (si->best_gl_visuals); + si->best_gl_visuals = 0; + + for (i = 0, j = 0; i < count; i++) + { + monitor *m = monitors[i]; + saver_screen_info *ssi = &si->screens[j]; + Screen *old_screen = ssi->screen; + int sn; + if (monitors[i]->sanity != S_SANE) continue; + + ssi->global = si; + ssi->number = j; + + sn = screen_number (m->screen); + ssi->screen = m->screen; + ssi->real_screen_number = sn; + ssi->real_screen_p = (seen_screens[sn] == 0); + seen_screens[sn]++; + + ssi->default_visual = + get_visual_resource (ssi->screen, "visualID", "VisualID", False); + ssi->current_visual = ssi->default_visual; + ssi->current_depth = visual_depth (ssi->screen, ssi->current_visual); + + /* If the screen changed (or if this is the first time) we need + a new toplevel shell for this screen's depth. + */ + if (ssi->screen != old_screen) + initialize_screen_root_widget (ssi); + + ssi->last_poll_mouse.root_x = -1; + ssi->last_poll_mouse.root_y = -1; + + ssi->x = m->x; + ssi->y = m->y; + ssi->width = m->width; + ssi->height = m->height; + +# ifndef DEBUG_MULTISCREEN + { + saver_preferences *p = &si->prefs; + if (p->debug_p +# ifdef QUAD_MODE + && !p->quad_p +# endif + ) + ssi->width /= 2; + } +# endif + + j++; + } + + si->default_screen = &si->screens[0]; + return True; +} diff --git a/driver/screensaver-properties.desktop.in b/driver/screensaver-properties.desktop.in new file mode 100644 index 00000000..de425279 --- /dev/null +++ b/driver/screensaver-properties.desktop.in @@ -0,0 +1,8 @@ +[Desktop Entry] +Exec=xscreensaver-demo +Icon=xscreensaver +Terminal=false +_Name=Screensaver +_Comment=Change screensaver properties +Type=Application +Categories=Settings;DesktopSettings;Security;X-XFCE; diff --git a/driver/setuid.c b/driver/setuid.c new file mode 100644 index 00000000..3ac78e4f --- /dev/null +++ b/driver/setuid.c @@ -0,0 +1,361 @@ +/* setuid.c --- management of runtime privileges. + * xscreensaver, Copyright (c) 1993-1998, 2005 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. + */ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include /* not used for much... */ + +/* This file doesn't need the Xt headers, so stub these types out... */ +#undef XtPointer +#define XtAppContext void* +#define XrmDatabase void* +#define XtIntervalId void* +#define XtPointer void* +#define Widget void* + +#include "xscreensaver.h" + +#ifndef EPERM +#include +#endif + +#include /* for getpwnam() and struct passwd */ +#include /* for getgrgid() and struct group */ + +static const char * +uid_gid_string (uid_t uid, gid_t gid) +{ + static char buf[255]; + struct passwd *p = 0; + struct group *g = 0; + p = getpwuid (uid); + g = getgrgid (gid); + sprintf (buf, "%.100s/%.100s (%ld/%ld)", + (p && p->pw_name ? p->pw_name : "???"), + (g && g->gr_name ? g->gr_name : "???"), + (long) uid, (long) gid); + return buf; +} + + +void +describe_uids (saver_info *si, FILE *out) +{ + uid_t uid = getuid(); + gid_t gid = getgid(); + uid_t euid = geteuid(); + gid_t egid = getegid(); + char *s1 = strdup (uid_gid_string (uid, gid)); + char *s2 = strdup (uid_gid_string (euid, egid)); + + if (si->orig_uid && *si->orig_uid && + (!!strcmp (si->orig_uid, s1) || + !!strcmp (si->orig_uid, s2))) + fprintf (out, "%s: initial effective uid/gid was %s\n", blurb(), + si->orig_uid); + + fprintf (out, "%s: running as %s", blurb(), s1); + if (uid != euid || gid != egid) + fprintf (out, "; effectively %s", s2); + fprintf(out, "\n"); + free(s1); + free(s2); +} + + +/* Returns true if we need to call setgroups(). + + Without calling setgroups(), the process will retain any supplementary + gids associated with the uid, e.g.: + + % groups root + root : root bin daemon sys adm disk wheel + + However, setgroups() can only be called by root, and returns EPERM + for other users even if the call would be a no-op (e.g., setting the + group list to the current list.) So, to avoid that spurious error, + before calling setgroups() we first check whether the current list + of groups contains only one element, our target group. If so, we + don't need to call setgroups(). + */ +static int +setgroups_needed_p (uid_t target_group) +{ + gid_t groups[1024]; + int n, size; + size = sizeof(groups) / sizeof(gid_t); + n = getgroups (size - 1, groups); + if (n < 0) + { + char buf [1024]; + sprintf (buf, "%s: getgroups(%ld, ...)", blurb(), (long int)(size - 1)); + perror (buf); + return 1; + } + else if (n == 0) /* an empty list means only egid is in effect. */ + return 0; + else if (n == 1 && groups[0] == target_group) /* one element, the target */ + return 0; + else /* more than one, or the wrong one. */ + return 1; +} + + +static int +set_ids_by_number (uid_t uid, gid_t gid, char **message_ret) +{ + int uid_errno = 0; + int gid_errno = 0; + int sgs_errno = 0; + struct passwd *p = getpwuid (uid); + struct group *g = getgrgid (gid); + + if (message_ret) + *message_ret = 0; + + /* Rumor has it that some implementations of of setuid() do nothing + when called with -1; therefore, if the "nobody" user has a uid of + -1, then that would be Really Bad. Rumor further has it that such + systems really ought to be using -2 for "nobody", since that works. + So, if we get a uid (or gid, for good measure) of -1, switch to -2 + instead. Note that this must be done after we've looked up the + user/group names with getpwuid(-1) and/or getgrgid(-1). + */ + if (gid == (gid_t) -1) gid = (gid_t) -2; + if (uid == (uid_t) -1) uid = (uid_t) -2; + + errno = 0; + if (setgroups_needed_p (gid) && + setgroups (1, &gid) < 0) + sgs_errno = errno ? errno : -1; + + errno = 0; + if (setgid (gid) != 0) + gid_errno = errno ? errno : -1; + + errno = 0; + if (setuid (uid) != 0) + uid_errno = errno ? errno : -1; + + if (uid_errno == 0 && gid_errno == 0 && sgs_errno == 0) + { + static char buf [1024]; + sprintf (buf, "changed uid/gid to %.100s/%.100s (%ld/%ld).", + (p && p->pw_name ? p->pw_name : "???"), + (g && g->gr_name ? g->gr_name : "???"), + (long) uid, (long) gid); + if (message_ret) + *message_ret = buf; + return 0; + } + else + { + char buf [1024]; + gid_t groups[1024]; + int n, size; + + if (sgs_errno) + { + sprintf (buf, "%s: couldn't setgroups to %.100s (%ld)", + blurb(), + (g && g->gr_name ? g->gr_name : "???"), + (long) gid); + if (sgs_errno == -1) + fprintf(stderr, "%s: unknown error\n", buf); + else + { + errno = sgs_errno; + perror(buf); + } + + fprintf (stderr, "%s: effective group list: ", blurb()); + size = sizeof(groups) / sizeof(gid_t); + n = getgroups (size - 1, groups); + if (n < 0) + fprintf (stderr, "unknown!\n"); + else + { + int i; + fprintf (stderr, "["); + for (i = 0; i < n; i++) + { + g = getgrgid (groups[i]); + if (i > 0) fprintf (stderr, ", "); + if (g && g->gr_name) fprintf (stderr, "%s", g->gr_name); + else fprintf (stderr, "%ld", (long) groups[i]); + } + fprintf (stderr, "]\n"); + } + } + + if (gid_errno) + { + sprintf (buf, "%s: couldn't set gid to %.100s (%ld)", + blurb(), + (g && g->gr_name ? g->gr_name : "???"), + (long) gid); + if (gid_errno == -1) + fprintf(stderr, "%s: unknown error\n", buf); + else + { + errno = gid_errno; + perror(buf); + } + } + + if (uid_errno) + { + sprintf (buf, "%s: couldn't set uid to %.100s (%ld)", + blurb(), + (p && p->pw_name ? p->pw_name : "???"), + (long) uid); + if (uid_errno == -1) + fprintf(stderr, "%s: unknown error\n", buf); + else + { + errno = uid_errno; + perror(buf); + } + } + + return -1; + } +} + + +/* If we've been run as setuid or setgid to someone else (most likely root) + turn off the extra permissions so that random user-specified programs + don't get special privileges. (On some systems it is necessary to install + this program as setuid root in order to read the passwd file to implement + lock-mode.) + + *** WARNING: DO NOT DISABLE ANY OF THE FOLLOWING CODE! + If you do so, you will open a security hole. See the sections + of the xscreensaver manual titled "LOCKING AND ROOT LOGINS", + and "USING XDM". + */ +void +hack_uid (saver_info *si) +{ + + /* Discard privileges, and set the effective user/group ids to the + real user/group ids. That is, give up our "chmod +s" rights. + */ + { + uid_t euid = geteuid(); + gid_t egid = getegid(); + uid_t uid = getuid(); + gid_t gid = getgid(); + + si->orig_uid = strdup (uid_gid_string (euid, egid)); + + if (uid != euid || gid != egid) + if (set_ids_by_number (uid, gid, &si->uid_message) != 0) + saver_exit (si, 1, 0); + } + + + /* Locking can't work when running as root, because we have no way of + knowing what the user id of the logged in user is (so we don't know + whose password to prompt for.) + + *** WARNING: DO NOT DISABLE THIS CODE! + If you do so, you will open a security hole. See the sections + of the xscreensaver manual titled "LOCKING AND ROOT LOGINS", + and "USING XDM". + */ + if (getuid() == (uid_t) 0) + { + si->locking_disabled_p = True; + si->nolock_reason = "running as root"; + } + + + /* If we're running as root, switch to a safer user. This is above and + beyond the fact that we've disabling locking, above -- the theory is + that running graphics demos as root is just always a stupid thing + to do, since they have probably never been security reviewed and are + more likely to be buggy than just about any other kind of program. + (And that assumes non-malicious code. There are also attacks here.) + + *** WARNING: DO NOT DISABLE THIS CODE! + If you do so, you will open a security hole. See the sections + of the xscreensaver manual titled "LOCKING AND ROOT LOGINS", + and "USING XDM". + */ + if (getuid() == (uid_t) 0) + { + struct passwd *p; + + p = getpwnam ("nobody"); + if (! p) p = getpwnam ("noaccess"); + if (! p) p = getpwnam ("daemon"); + if (! p) + { + fprintf (stderr, + "%s: running as root, and couldn't find a safer uid.\n", + blurb()); + saver_exit(si, 1, 0); + } + + if (set_ids_by_number (p->pw_uid, p->pw_gid, &si->uid_message) != 0) + saver_exit (si, -1, 0); + } + + + /* If there's anything even remotely funny looking about the passwd struct, + or if we're running as some other user from the list below (a + non-comprehensive selection of users known to be privileged in some way, + and not normal end-users) then disable locking. If it was possible, + switching to "nobody" would be the thing to do, but only root itself has + the privs to do that. + + *** WARNING: DO NOT DISABLE THIS CODE! + If you do so, you will open a security hole. See the sections + of the xscreensaver manual titled "LOCKING AND ROOT LOGINS", + and "USING XDM". + */ + { + uid_t uid = getuid (); /* get it again */ + struct passwd *p = getpwuid (uid); /* get it again */ + + if (!p || + uid == (uid_t) 0 || + uid == (uid_t) -1 || + uid == (uid_t) -2 || + p->pw_uid == (uid_t) 0 || + p->pw_uid == (uid_t) -1 || + p->pw_uid == (uid_t) -2 || + !p->pw_name || + !*p->pw_name || + !strcmp (p->pw_name, "root") || + !strcmp (p->pw_name, "nobody") || + !strcmp (p->pw_name, "noaccess") || + !strcmp (p->pw_name, "operator") || + !strcmp (p->pw_name, "daemon") || + !strcmp (p->pw_name, "bin") || + !strcmp (p->pw_name, "adm") || + !strcmp (p->pw_name, "sys") || + !strcmp (p->pw_name, "games")) + { + static char buf [1024]; + sprintf (buf, "running as %.100s", + (p && p->pw_name && *p->pw_name + ? p->pw_name : "")); + si->nolock_reason = buf; + si->locking_disabled_p = True; + si->dangerous_uid_p = True; + } + } +} diff --git a/driver/splash.c b/driver/splash.c new file mode 100644 index 00000000..02844b58 --- /dev/null +++ b/driver/splash.c @@ -0,0 +1,866 @@ +/* xscreensaver, Copyright (c) 1991-2008 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. + */ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include + +#include "xscreensaver.h" +#include "resources.h" + +#undef MAX +#define MAX(a,b) ((a)>(b)?(a):(b)) + +void +draw_shaded_rectangle (Display *dpy, Window window, + int x, int y, + int width, int height, + int thickness, + unsigned long top_color, + unsigned long bottom_color) +{ + XPoint points[4]; + XGCValues gcv; + GC gc1, gc2; + if (thickness == 0) return; + + gcv.foreground = top_color; + gc1 = XCreateGC (dpy, window, GCForeground, &gcv); + gcv.foreground = bottom_color; + gc2 = XCreateGC (dpy, window, GCForeground, &gcv); + + points [0].x = x; + points [0].y = y; + points [1].x = x + width; + points [1].y = y; + points [2].x = x + width - thickness; + points [2].y = y + thickness; + points [3].x = x; + points [3].y = y + thickness; + XFillPolygon (dpy, window, gc1, points, 4, Convex, CoordModeOrigin); + + points [0].x = x; + points [0].y = y + thickness; + points [1].x = x; + points [1].y = y + height; + points [2].x = x + thickness; + points [2].y = y + height - thickness; + points [3].x = x + thickness; + points [3].y = y + thickness; + XFillPolygon (dpy, window, gc1, points, 4, Convex, CoordModeOrigin); + + points [0].x = x + width; + points [0].y = y; + points [1].x = x + width - thickness; + points [1].y = y + thickness; + points [2].x = x + width - thickness; + points [2].y = y + height - thickness; + points [3].x = x + width; + points [3].y = y + height - thickness; + XFillPolygon (dpy, window, gc2, points, 4, Convex, CoordModeOrigin); + + points [0].x = x; + points [0].y = y + height; + points [1].x = x + width; + points [1].y = y + height; + points [2].x = x + width; + points [2].y = y + height - thickness; + points [3].x = x + thickness; + points [3].y = y + height - thickness; + XFillPolygon (dpy, window, gc2, points, 4, Convex, CoordModeOrigin); + + XFreeGC (dpy, gc1); + XFreeGC (dpy, gc2); +} + + +int +string_width (XFontStruct *font, char *s) +{ + return XTextWidth(font, s, strlen(s)); +} + + +static void update_splash_window (saver_info *si); +static void draw_splash_window (saver_info *si); +static void destroy_splash_window (saver_info *si); +static void unsplash_timer (XtPointer closure, XtIntervalId *id); + +static void do_demo (saver_screen_info *ssi); +#ifdef PREFS_BUTTON +static void do_prefs (saver_screen_info *ssi); +#endif /* PREFS_BUTTON */ +static void do_help (saver_screen_info *ssi); + + +struct splash_dialog_data { + + saver_screen_info *prompt_screen; + XtIntervalId timer; + + Dimension width; + Dimension height; + + char *heading_label; + char *body_label; + char *body2_label; + char *demo_label; +#ifdef PREFS_BUTTON + char *prefs_label; +#endif /* PREFS_BUTTON */ + char *help_label; + + XFontStruct *heading_font; + XFontStruct *body_font; + XFontStruct *button_font; + + Pixel foreground; + Pixel background; + Pixel border; + Pixel button_foreground; + Pixel button_background; + Pixel shadow_top; + Pixel shadow_bottom; + + Dimension logo_width; + Dimension logo_height; + Dimension internal_border; + Dimension shadow_width; + + Dimension button_width, button_height; + Dimension demo_button_x, demo_button_y; +#ifdef PREFS_BUTTON + Dimension prefs_button_x, prefs_button_y; +#endif /* PREFS_BUTTON */ + Dimension help_button_x, help_button_y; + + Pixmap logo_pixmap; + Pixmap logo_clipmask; + int logo_npixels; + unsigned long *logo_pixels; + + int pressed; +}; + + +void +make_splash_dialog (saver_info *si) +{ + int x, y, bw; + XSetWindowAttributes attrs; + unsigned long attrmask = 0; + splash_dialog_data *sp; + saver_screen_info *ssi; + Colormap cmap; + char *f; + + if (si->sp_data) + return; + if (!si->prefs.splash_p || + si->prefs.splash_duration <= 0) + return; + + ssi = &si->screens[mouse_screen (si)]; + + if (!ssi || !ssi->screen) + return; /* WTF? Trying to splash while no screens connected? */ + + cmap = DefaultColormapOfScreen (ssi->screen); + + sp = (splash_dialog_data *) calloc (1, sizeof(*sp)); + sp->prompt_screen = ssi; + + sp->heading_label = get_string_resource (si->dpy, + "splash.heading.label", + "Dialog.Label.Label"); + sp->body_label = get_string_resource (si->dpy, + "splash.body.label", + "Dialog.Label.Label"); + sp->body2_label = get_string_resource (si->dpy, + "splash.body2.label", + "Dialog.Label.Label"); + sp->demo_label = get_string_resource (si->dpy, + "splash.demo.label", + "Dialog.Button.Label"); +#ifdef PREFS_BUTTON + sp->prefs_label = get_string_resource (si->dpy, + "splash.prefs.label", + "Dialog.Button.Label"); +#endif /* PREFS_BUTTON */ + sp->help_label = get_string_resource (si->dpy, + "splash.help.label", + "Dialog.Button.Label"); + + if (!sp->heading_label) + sp->heading_label = strdup("ERROR: REESOURCES NOT INSTALLED CORRECTLY"); + if (!sp->body_label) + sp->body_label = strdup("ERROR: REESOURCES NOT INSTALLED CORRECTLY"); + if (!sp->body2_label) + sp->body2_label = strdup("ERROR: REESOURCES NOT INSTALLED CORRECTLY"); + if (!sp->demo_label) sp->demo_label = strdup("ERROR"); +#ifdef PREFS_BUTTON + if (!sp->prefs_label) sp->prefs_label = strdup("ERROR"); +#endif /* PREFS_BUTTON */ + if (!sp->help_label) sp->help_label = strdup("ERROR"); + + /* Put the version number in the label. */ + { + char *s = (char *) malloc (strlen(sp->heading_label) + 20); + sprintf(s, sp->heading_label, si->version); + free (sp->heading_label); + sp->heading_label = s; + } + + f = get_string_resource (si->dpy, "splash.headingFont", "Dialog.Font"); + sp->heading_font = XLoadQueryFont (si->dpy, (f ? f : "fixed")); + if (!sp->heading_font) sp->heading_font = XLoadQueryFont (si->dpy, "fixed"); + if (f) free (f); + + f = get_string_resource(si->dpy, "splash.bodyFont", "Dialog.Font"); + sp->body_font = XLoadQueryFont (si->dpy, (f ? f : "fixed")); + if (!sp->body_font) sp->body_font = XLoadQueryFont (si->dpy, "fixed"); + if (f) free (f); + + f = get_string_resource(si->dpy, "splash.buttonFont", "Dialog.Font"); + sp->button_font = XLoadQueryFont (si->dpy, (f ? f : "fixed")); + if (!sp->button_font) sp->button_font = XLoadQueryFont (si->dpy, "fixed"); + if (f) free (f); + + sp->foreground = get_pixel_resource (si->dpy, cmap, + "splash.foreground", + "Dialog.Foreground"); + sp->background = get_pixel_resource (si->dpy, cmap, + "splash.background", + "Dialog.Background"); + sp->border = get_pixel_resource (si->dpy, cmap, + "splash.borderColor", + "Dialog.borderColor"); + + if (sp->foreground == sp->background) + { + /* Make sure the error messages show up. */ + sp->foreground = BlackPixelOfScreen (ssi->screen); + sp->background = WhitePixelOfScreen (ssi->screen); + } + + sp->button_foreground = get_pixel_resource (si->dpy, cmap, + "splash.Button.foreground", + "Dialog.Button.Foreground"); + sp->button_background = get_pixel_resource (si->dpy, cmap, + "splash.Button.background", + "Dialog.Button.Background"); + sp->shadow_top = get_pixel_resource (si->dpy, cmap, + "splash.topShadowColor", + "Dialog.Foreground"); + sp->shadow_bottom = get_pixel_resource (si->dpy, cmap, + "splash.bottomShadowColor", + "Dialog.Background"); + + sp->logo_width = get_integer_resource (si->dpy, + "splash.logo.width", + "Dialog.Logo.Width"); + sp->logo_height = get_integer_resource (si->dpy, + "splash.logo.height", + "Dialog.Logo.Height"); + sp->internal_border = get_integer_resource (si->dpy, + "splash.internalBorderWidth", + "Dialog.InternalBorderWidth"); + sp->shadow_width = get_integer_resource (si->dpy, + "splash.shadowThickness", + "Dialog.ShadowThickness"); + + if (sp->logo_width == 0) sp->logo_width = 150; + if (sp->logo_height == 0) sp->logo_height = 150; + if (sp->internal_border == 0) sp->internal_border = 15; + if (sp->shadow_width == 0) sp->shadow_width = 4; + + { + int direction, ascent, descent; + XCharStruct overall; + + sp->width = 0; + sp->height = 0; + + /* Measure the heading_label. */ + XTextExtents (sp->heading_font, + sp->heading_label, strlen(sp->heading_label), + &direction, &ascent, &descent, &overall); + if (overall.width > sp->width) sp->width = overall.width; + sp->height += ascent + descent; + + /* Measure the body_label. */ + XTextExtents (sp->body_font, + sp->body_label, strlen(sp->body_label), + &direction, &ascent, &descent, &overall); + if (overall.width > sp->width) sp->width = overall.width; + sp->height += ascent + descent; + + /* Measure the body2_label. */ + XTextExtents (sp->body_font, + sp->body2_label, strlen(sp->body2_label), + &direction, &ascent, &descent, &overall); + if (overall.width > sp->width) sp->width = overall.width; + sp->height += ascent + descent; + + { + Dimension w2 = 0, w3 = 0, w4 = 0; + Dimension h2 = 0, h3 = 0, h4 = 0; + + /* Measure the Demo button. */ + XTextExtents (sp->button_font, + sp->demo_label, strlen(sp->demo_label), + &direction, &ascent, &descent, &overall); + w2 = overall.width; + h2 = ascent + descent; + +#ifdef PREFS_BUTTON + /* Measure the Prefs button. */ + XTextExtents (sp->button_font, + sp->prefs_label, strlen(sp->prefs_label), + &direction, &ascent, &descent, &overall); + w3 = overall.width; + h3 = ascent + descent; +#else /* !PREFS_BUTTON */ + w3 = 0; + h3 = 0; +#endif /* !PREFS_BUTTON */ + + /* Measure the Help button. */ + XTextExtents (sp->button_font, + sp->help_label, strlen(sp->help_label), + &direction, &ascent, &descent, &overall); + w4 = overall.width; + h4 = ascent + descent; + + w2 = MAX(w2, w3); w2 = MAX(w2, w4); + h2 = MAX(h2, h3); h2 = MAX(h2, h4); + + /* Add some horizontal padding inside the buttons. */ + w2 += ascent; + + w2 += ((ascent + descent) / 2) + (sp->shadow_width * 2); + h2 += ((ascent + descent) / 2) + (sp->shadow_width * 2); + + sp->button_width = w2; + sp->button_height = h2; + +#ifdef PREFS_BUTTON + w2 *= 3; +#else /* !PREFS_BUTTON */ + w2 *= 2; +#endif /* !PREFS_BUTTON */ + + w2 += ((ascent + descent) * 2); /* for space between buttons */ + + if (w2 > sp->width) sp->width = w2; + sp->height += h2; + } + + sp->width += (sp->internal_border * 2); + sp->height += (sp->internal_border * 3); + + if (sp->logo_height > sp->height) + sp->height = sp->logo_height; + else if (sp->height > sp->logo_height) + sp->logo_height = sp->height; + + sp->logo_width = sp->logo_height; + + sp->width += sp->logo_width; + } + + attrmask |= CWOverrideRedirect; attrs.override_redirect = True; + attrmask |= CWEventMask; + attrs.event_mask = (ExposureMask | ButtonPressMask | ButtonReleaseMask); + + { + int sx = 0, sy = 0, w, h; + int mouse_x = 0, mouse_y = 0; + + { + Window pointer_root, pointer_child; + int root_x, root_y, win_x, win_y; + unsigned int mask; + if (XQueryPointer (si->dpy, + RootWindowOfScreen (ssi->screen), + &pointer_root, &pointer_child, + &root_x, &root_y, &win_x, &win_y, &mask)) + { + mouse_x = root_x; + mouse_y = root_y; + } + } + + x = ssi->x; + y = ssi->y; + w = ssi->width; + h = ssi->height; + if (si->prefs.debug_p) w /= 2; + x = sx + (((w + sp->width) / 2) - sp->width); + y = sy + (((h + sp->height) / 2) - sp->height); + if (x < sx) x = sx; + if (y < sy) y = sy; + } + + bw = get_integer_resource (si->dpy, + "splash.borderWidth", + "Dialog.BorderWidth"); + + si->splash_dialog = + XCreateWindow (si->dpy, + RootWindowOfScreen(ssi->screen), + x, y, sp->width, sp->height, bw, + DefaultDepthOfScreen (ssi->screen), InputOutput, + DefaultVisualOfScreen(ssi->screen), + attrmask, &attrs); + XSetWindowBackground (si->dpy, si->splash_dialog, sp->background); + XSetWindowBorder (si->dpy, si->splash_dialog, sp->border); + + + sp->logo_pixmap = xscreensaver_logo (ssi->screen, + /* same visual as si->splash_dialog */ + DefaultVisualOfScreen (ssi->screen), + si->splash_dialog, cmap, + sp->background, + &sp->logo_pixels, &sp->logo_npixels, + &sp->logo_clipmask, True); + + XMapRaised (si->dpy, si->splash_dialog); + XSync (si->dpy, False); + + si->sp_data = sp; + + sp->timer = XtAppAddTimeOut (si->app, si->prefs.splash_duration, + unsplash_timer, (XtPointer) si); + + draw_splash_window (si); + XSync (si->dpy, False); +} + + +static void +draw_splash_window (saver_info *si) +{ + splash_dialog_data *sp = si->sp_data; + XGCValues gcv; + GC gc1, gc2; + int hspacing, vspacing, height; + int x1, x2, x3, y1, y2; + int sw; + +#ifdef PREFS_BUTTON + int nbuttons = 3; +#else /* !PREFS_BUTTON */ + int nbuttons = 2; +#endif /* !PREFS_BUTTON */ + + height = (sp->heading_font->ascent + sp->heading_font->descent + + sp->body_font->ascent + sp->body_font->descent + + sp->body_font->ascent + sp->body_font->descent + + sp->button_font->ascent + sp->button_font->descent); + vspacing = ((sp->height + - (4 * sp->shadow_width) + - (2 * sp->internal_border) + - height) / 5); + if (vspacing < 0) vspacing = 0; + if (vspacing > (sp->heading_font->ascent * 2)) + vspacing = (sp->heading_font->ascent * 2); + + gcv.foreground = sp->foreground; + gc1 = XCreateGC (si->dpy, si->splash_dialog, GCForeground, &gcv); + gc2 = XCreateGC (si->dpy, si->splash_dialog, GCForeground, &gcv); + x1 = sp->logo_width; + x3 = sp->width - (sp->shadow_width * 2); + y1 = sp->internal_border; + + /* top heading + */ + XSetFont (si->dpy, gc1, sp->heading_font->fid); + sw = string_width (sp->heading_font, sp->heading_label); + x2 = (x1 + ((x3 - x1 - sw) / 2)); + y1 += sp->heading_font->ascent; + XDrawString (si->dpy, si->splash_dialog, gc1, x2, y1, + sp->heading_label, strlen(sp->heading_label)); + y1 += sp->heading_font->descent; + + /* text below top heading + */ + XSetFont (si->dpy, gc1, sp->body_font->fid); + y1 += vspacing + sp->body_font->ascent; + sw = string_width (sp->body_font, sp->body_label); + x2 = (x1 + ((x3 - x1 - sw) / 2)); + XDrawString (si->dpy, si->splash_dialog, gc1, x2, y1, + sp->body_label, strlen(sp->body_label)); + y1 += sp->body_font->descent; + + y1 += sp->body_font->ascent; + sw = string_width (sp->body_font, sp->body2_label); + x2 = (x1 + ((x3 - x1 - sw) / 2)); + XDrawString (si->dpy, si->splash_dialog, gc1, x2, y1, + sp->body2_label, strlen(sp->body2_label)); + y1 += sp->body_font->descent; + + /* The buttons + */ + XSetForeground (si->dpy, gc1, sp->button_foreground); + XSetForeground (si->dpy, gc2, sp->button_background); + +/* y1 += (vspacing * 2);*/ + y1 = sp->height - sp->internal_border - sp->button_height; + + x1 += sp->internal_border; + y2 = (y1 + ((sp->button_height - + (sp->button_font->ascent + sp->button_font->descent)) + / 2) + + sp->button_font->ascent); + hspacing = ((sp->width - x1 - (sp->shadow_width * 2) - + sp->internal_border - (sp->button_width * nbuttons)) + / 2); + + x2 = x1 + ((sp->button_width - string_width(sp->button_font, sp->demo_label)) + / 2); + XFillRectangle (si->dpy, si->splash_dialog, gc2, x1, y1, + sp->button_width, sp->button_height); + XDrawString (si->dpy, si->splash_dialog, gc1, x2, y2, + sp->demo_label, strlen(sp->demo_label)); + sp->demo_button_x = x1; + sp->demo_button_y = y1; + +#ifdef PREFS_BUTTON + x1 += hspacing + sp->button_width; + x2 = x1 + ((sp->button_width - string_width(sp->button_font,sp->prefs_label)) + / 2); + XFillRectangle (si->dpy, si->splash_dialog, gc2, x1, y1, + sp->button_width, sp->button_height); + XDrawString (si->dpy, si->splash_dialog, gc1, x2, y2, + sp->prefs_label, strlen(sp->prefs_label)); + sp->prefs_button_x = x1; + sp->prefs_button_y = y1; +#endif /* PREFS_BUTTON */ + +#ifdef PREFS_BUTTON + x1 += hspacing + sp->button_width; +#else /* !PREFS_BUTTON */ + x1 = (sp->width - sp->button_width - + sp->internal_border - (sp->shadow_width * 2)); +#endif /* !PREFS_BUTTON */ + + x2 = x1 + ((sp->button_width - string_width(sp->button_font,sp->help_label)) + / 2); + XFillRectangle (si->dpy, si->splash_dialog, gc2, x1, y1, + sp->button_width, sp->button_height); + XDrawString (si->dpy, si->splash_dialog, gc1, x2, y2, + sp->help_label, strlen(sp->help_label)); + sp->help_button_x = x1; + sp->help_button_y = y1; + + + /* The logo + */ + x1 = sp->shadow_width * 6; + y1 = sp->shadow_width * 6; + x2 = sp->logo_width - (sp->shadow_width * 12); + y2 = sp->logo_height - (sp->shadow_width * 12); + + if (sp->logo_pixmap) + { + Window root; + int x, y; + unsigned int w, h, bw, d; + XGetGeometry (si->dpy, sp->logo_pixmap, &root, &x, &y, &w, &h, &bw, &d); + XSetForeground (si->dpy, gc1, sp->foreground); + XSetBackground (si->dpy, gc1, sp->background); + XSetClipMask (si->dpy, gc1, sp->logo_clipmask); + XSetClipOrigin (si->dpy, gc1, x1 + ((x2 - (int)w) /2), y1 + ((y2 - (int)h) / 2)); + if (d == 1) + XCopyPlane (si->dpy, sp->logo_pixmap, si->splash_dialog, gc1, + 0, 0, w, h, + x1 + ((x2 - (int)w) / 2), + y1 + ((y2 - (int)h) / 2), + 1); + else + XCopyArea (si->dpy, sp->logo_pixmap, si->splash_dialog, gc1, + 0, 0, w, h, + x1 + ((x2 - (int)w) / 2), + y1 + ((y2 - (int)h) / 2)); + } + + /* Solid border inside the logo box. */ +#if 0 + XSetForeground (si->dpy, gc1, sp->foreground); + XDrawRectangle (si->dpy, si->splash_dialog, gc1, x1, y1, x2-1, y2-1); +#endif + + /* The shadow around the logo + */ + draw_shaded_rectangle (si->dpy, si->splash_dialog, + sp->shadow_width * 4, + sp->shadow_width * 4, + sp->logo_width - (sp->shadow_width * 8), + sp->logo_height - (sp->shadow_width * 8), + sp->shadow_width, + sp->shadow_bottom, sp->shadow_top); + + /* The shadow around the whole window + */ + draw_shaded_rectangle (si->dpy, si->splash_dialog, + 0, 0, sp->width, sp->height, sp->shadow_width, + sp->shadow_top, sp->shadow_bottom); + + XFreeGC (si->dpy, gc1); + XFreeGC (si->dpy, gc2); + + update_splash_window (si); +} + + +static void +update_splash_window (saver_info *si) +{ + splash_dialog_data *sp = si->sp_data; + int pressed; + if (!sp) return; + pressed = sp->pressed; + + /* The shadows around the buttons + */ + draw_shaded_rectangle (si->dpy, si->splash_dialog, + sp->demo_button_x, sp->demo_button_y, + sp->button_width, sp->button_height, sp->shadow_width, + (pressed == 1 ? sp->shadow_bottom : sp->shadow_top), + (pressed == 1 ? sp->shadow_top : sp->shadow_bottom)); +#ifdef PREFS_BUTTON + draw_shaded_rectangle (si->dpy, si->splash_dialog, + sp->prefs_button_x, sp->prefs_button_y, + sp->button_width, sp->button_height, sp->shadow_width, + (pressed == 2 ? sp->shadow_bottom : sp->shadow_top), + (pressed == 2 ? sp->shadow_top : sp->shadow_bottom)); +#endif /* PREFS_BUTTON */ + draw_shaded_rectangle (si->dpy, si->splash_dialog, + sp->help_button_x, sp->help_button_y, + sp->button_width, sp->button_height, sp->shadow_width, + (pressed == 3 ? sp->shadow_bottom : sp->shadow_top), + (pressed == 3 ? sp->shadow_top : sp->shadow_bottom)); +} + +static void +destroy_splash_window (saver_info *si) +{ + splash_dialog_data *sp = si->sp_data; + saver_screen_info *ssi = sp->prompt_screen; + Colormap cmap = DefaultColormapOfScreen (ssi->screen); + Pixel black = BlackPixelOfScreen (ssi->screen); + Pixel white = WhitePixelOfScreen (ssi->screen); + + if (sp->timer) + XtRemoveTimeOut (sp->timer); + + if (si->splash_dialog) + { + XDestroyWindow (si->dpy, si->splash_dialog); + si->splash_dialog = 0; + } + + if (sp->heading_label) free (sp->heading_label); + if (sp->body_label) free (sp->body_label); + if (sp->body2_label) free (sp->body2_label); + if (sp->demo_label) free (sp->demo_label); +#ifdef PREFS_BUTTON + if (sp->prefs_label) free (sp->prefs_label); +#endif /* PREFS_BUTTON */ + if (sp->help_label) free (sp->help_label); + + if (sp->heading_font) XFreeFont (si->dpy, sp->heading_font); + if (sp->body_font) XFreeFont (si->dpy, sp->body_font); + if (sp->button_font) XFreeFont (si->dpy, sp->button_font); + + if (sp->foreground != black && sp->foreground != white) + XFreeColors (si->dpy, cmap, &sp->foreground, 1, 0L); + if (sp->background != black && sp->background != white) + XFreeColors (si->dpy, cmap, &sp->background, 1, 0L); + if (sp->button_foreground != black && sp->button_foreground != white) + XFreeColors (si->dpy, cmap, &sp->button_foreground, 1, 0L); + if (sp->button_background != black && sp->button_background != white) + XFreeColors (si->dpy, cmap, &sp->button_background, 1, 0L); + if (sp->shadow_top != black && sp->shadow_top != white) + XFreeColors (si->dpy, cmap, &sp->shadow_top, 1, 0L); + if (sp->shadow_bottom != black && sp->shadow_bottom != white) + XFreeColors (si->dpy, cmap, &sp->shadow_bottom, 1, 0L); + + if (sp->logo_pixmap) + XFreePixmap (si->dpy, sp->logo_pixmap); + if (sp->logo_clipmask) + XFreePixmap (si->dpy, sp->logo_clipmask); + if (sp->logo_pixels) + { + if (sp->logo_npixels) + XFreeColors (si->dpy, cmap, sp->logo_pixels, sp->logo_npixels, 0L); + free (sp->logo_pixels); + sp->logo_pixels = 0; + sp->logo_npixels = 0; + } + + memset (sp, 0, sizeof(*sp)); + free (sp); + si->sp_data = 0; +} + +void +handle_splash_event (saver_info *si, XEvent *event) +{ + splash_dialog_data *sp = si->sp_data; + saver_screen_info *ssi = sp->prompt_screen; + int which = 0; + if (!sp) return; + + switch (event->xany.type) + { + case Expose: + draw_splash_window (si); + break; + + case ButtonPress: case ButtonRelease: + + if (event->xbutton.x >= sp->demo_button_x && + event->xbutton.x < sp->demo_button_x + sp->button_width && + event->xbutton.y >= sp->demo_button_y && + event->xbutton.y < sp->demo_button_y + sp->button_height) + which = 1; + +#ifdef PREFS_BUTTON + else if (event->xbutton.x >= sp->prefs_button_x && + event->xbutton.x < sp->prefs_button_x + sp->button_width && + event->xbutton.y >= sp->prefs_button_y && + event->xbutton.y < sp->prefs_button_y + sp->button_height) + which = 2; +#endif /* PREFS_BUTTON */ + + else if (event->xbutton.x >= sp->help_button_x && + event->xbutton.x < sp->help_button_x + sp->button_width && + event->xbutton.y >= sp->help_button_y && + event->xbutton.y < sp->help_button_y + sp->button_height) + which = 3; + + if (event->xany.type == ButtonPress) + { + sp->pressed = which; + update_splash_window (si); + if (which == 0) + XBell (si->dpy, False); + } + else if (event->xany.type == ButtonRelease) + { + if (which && sp->pressed == which) + { + destroy_splash_window (si); + sp = si->sp_data; + switch (which) + { + case 1: do_demo (ssi); break; +#ifdef PREFS_BUTTON + case 2: do_prefs (ssi); break; +#endif /* PREFS_BUTTON */ + case 3: do_help (ssi); break; + default: abort(); + } + } + else if (which == 0 && sp->pressed == 0) + { + /* click and release on the window but not in a button: + treat that as "dismiss the splash dialog." */ + destroy_splash_window (si); + sp = si->sp_data; + } + if (sp) sp->pressed = 0; + update_splash_window (si); + } + break; + + default: + break; + } +} + +static void +unsplash_timer (XtPointer closure, XtIntervalId *id) +{ + saver_info *si = (saver_info *) closure; + if (si && si->sp_data) + destroy_splash_window (si); +} + + +/* Button callbacks */ + +#ifdef VMS +# define pid_t int +# define fork vfork +#endif /* VMS */ + + +static void +do_demo (saver_screen_info *ssi) +{ + saver_info *si = ssi->global; + saver_preferences *p = &si->prefs; + const char *cmd = p->demo_command; + + if (cmd && *cmd) + fork_and_exec (ssi, cmd); + else + fprintf (stderr, "%s: no demo-mode command has been specified.\n", + blurb()); +} + +#ifdef PREFS_BUTTON +static void +do_prefs (saver_screen_info *ssi) +{ + saver_info *si = ssi->global; + saver_preferences *p = &si->prefs; + const char *cmd = p->prefs_command; + + if (command && *command) + fork_and_exec (ssi, cmd); + else + fprintf (stderr, "%s: no preferences command has been specified.\n", + blurb()); +} +#endif /* PREFS_BUTTON */ + +static void +do_help (saver_screen_info *ssi) +{ + saver_info *si = ssi->global; + saver_preferences *p = &si->prefs; + char *help_command = 0; + + if (!p->load_url_command || !*p->load_url_command) + { + fprintf (stderr, "%s: no URL command has been specified.\n", blurb()); + return; + } + if (!p->help_url || !*p->help_url) + { + fprintf (stderr, "%s: no Help URL has been specified.\n", blurb()); + return; + } + + help_command = (char *) malloc (strlen (p->load_url_command) + + (strlen (p->help_url) * 4) + 10); + sprintf (help_command, p->load_url_command, + p->help_url, p->help_url, p->help_url, p->help_url); + + fork_and_exec (ssi, help_command); + free (help_command); +} diff --git a/driver/stderr.c b/driver/stderr.c new file mode 100644 index 00000000..7def5d92 --- /dev/null +++ b/driver/stderr.c @@ -0,0 +1,560 @@ +/* stderr.c --- capturing stdout/stderr output onto the screensaver window. + * xscreensaver, Copyright (c) 1991-2012 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. + */ + +/* stderr hackery - Why Unix Sucks, reason number 32767. + */ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include + +#include +#include + +#ifdef HAVE_UNISTD_H +# include +#endif + +#ifdef HAVE_FCNTL +# include +#endif + +#include + +#include "xscreensaver.h" +#include "resources.h" +#include "visual.h" + +FILE *real_stderr = 0; +FILE *real_stdout = 0; + + +/* It's ok for these to be global, since they refer to the one and only + stderr stream, not to a particular screen or window or visual. + */ +static char stderr_buffer [4096]; +static char *stderr_tail = 0; +static time_t stderr_last_read = 0; + +static int stderr_stdout_read_fd = -1; + +static void make_stderr_overlay_window (saver_screen_info *); + + +/* Recreates the stderr window or GCs: do this when the xscreensaver window + on a screen has been re-created. + */ +void +reset_stderr (saver_screen_info *ssi) +{ + saver_info *si = ssi->global; + + if (si->prefs.debug_p) + fprintf ((real_stderr ? real_stderr : stderr), + "%s: resetting stderr\n", blurb()); + + ssi->stderr_text_x = 0; + ssi->stderr_text_y = 0; + + if (ssi->stderr_gc) + XFreeGC (si->dpy, ssi->stderr_gc); + ssi->stderr_gc = 0; + + if (ssi->stderr_overlay_window) + XDestroyWindow(si->dpy, ssi->stderr_overlay_window); + ssi->stderr_overlay_window = 0; + + if (ssi->stderr_cmap) + XFreeColormap(si->dpy, ssi->stderr_cmap); + ssi->stderr_cmap = 0; +} + +/* Erases any stderr text overlaying the screen (if possible) and resets + the stderr output cursor to the upper left. Do this when the xscreensaver + window is cleared. + */ +void +clear_stderr (saver_screen_info *ssi) +{ + saver_info *si = ssi->global; + ssi->stderr_text_x = 0; + ssi->stderr_text_y = 0; + if (ssi->stderr_overlay_window) + XClearWindow (si->dpy, ssi->stderr_overlay_window); +} + + +/* Draws the string on the screen's window. + */ +static void +print_stderr_1 (saver_screen_info *ssi, char *string) +{ + saver_info *si = ssi->global; + Display *dpy = si->dpy; + Screen *screen = ssi->screen; + Window window = (ssi->stderr_overlay_window ? + ssi->stderr_overlay_window : + ssi->screensaver_window); + int h_border = 20; + int v_border = 20; + char *head = string; + char *tail; + + if (! ssi->stderr_font) + { + char *font_name = get_string_resource (dpy, "font", "Font"); + if (!font_name) font_name = strdup ("fixed"); + ssi->stderr_font = XLoadQueryFont (dpy, font_name); + if (! ssi->stderr_font) ssi->stderr_font = XLoadQueryFont (dpy, "fixed"); + ssi->stderr_line_height = (ssi->stderr_font->ascent + + ssi->stderr_font->descent); + free (font_name); + } + + if (! ssi->stderr_gc) + { + XGCValues gcv; + Pixel fg, bg; + Colormap cmap = ssi->cmap; + + if (!ssi->stderr_overlay_window && + get_boolean_resource(dpy, "overlayStderr", "Boolean")) + { + make_stderr_overlay_window (ssi); + if (ssi->stderr_overlay_window) + window = ssi->stderr_overlay_window; + if (ssi->stderr_cmap) + cmap = ssi->stderr_cmap; + } + + fg = get_pixel_resource (dpy,cmap,"overlayTextForeground","Foreground"); + bg = get_pixel_resource (dpy,cmap,"overlayTextBackground","Background"); + gcv.font = ssi->stderr_font->fid; + gcv.foreground = fg; + gcv.background = bg; + ssi->stderr_gc = XCreateGC (dpy, window, + (GCFont | GCForeground | GCBackground), + &gcv); + } + + + if (ssi->stderr_cmap) + XInstallColormap(si->dpy, ssi->stderr_cmap); + + for (tail = string; *tail; tail++) + { + if (*tail == '\n' || *tail == '\r') + { + int maxy = HeightOfScreen (screen) - v_border - v_border; + if (tail != head) + XDrawImageString (dpy, window, ssi->stderr_gc, + ssi->stderr_text_x + h_border, + ssi->stderr_text_y + v_border + + ssi->stderr_font->ascent, + head, tail - head); + ssi->stderr_text_x = 0; + ssi->stderr_text_y += ssi->stderr_line_height; + head = tail + 1; + if (*tail == '\r' && *head == '\n') + head++, tail++; + + if (ssi->stderr_text_y > maxy - ssi->stderr_line_height) + { +#if 0 + ssi->stderr_text_y = 0; +#else + int offset = ssi->stderr_line_height * 5; + XWindowAttributes xgwa; + XGetWindowAttributes (dpy, window, &xgwa); + + XCopyArea (dpy, window, window, ssi->stderr_gc, + 0, v_border + offset, + xgwa.width, + (xgwa.height - v_border - v_border - offset), + 0, v_border); + XClearArea (dpy, window, + 0, xgwa.height - v_border - offset, + xgwa.width, offset, False); + ssi->stderr_text_y -= offset; +#endif + } + } + } + if (tail != head) + { + int direction, ascent, descent; + XCharStruct overall; + XDrawImageString (dpy, window, ssi->stderr_gc, + ssi->stderr_text_x + h_border, + ssi->stderr_text_y + v_border + + ssi->stderr_font->ascent, + head, tail - head); + XTextExtents (ssi->stderr_font, tail, tail - head, + &direction, &ascent, &descent, &overall); + ssi->stderr_text_x += overall.width; + } +} + +static void +make_stderr_overlay_window (saver_screen_info *ssi) +{ + saver_info *si = ssi->global; + unsigned long transparent_pixel = 0; + Visual *visual = get_overlay_visual (ssi->screen, &transparent_pixel); + if (visual) + { + int depth = visual_depth (ssi->screen, visual); + XSetWindowAttributes attrs; + XWindowAttributes xgwa; + unsigned long attrmask; + XGetWindowAttributes (si->dpy, ssi->screensaver_window, &xgwa); + + if (si->prefs.debug_p) + fprintf(real_stderr, + "%s: using overlay visual 0x%0x for stderr text layer.\n", + blurb(), (int) XVisualIDFromVisual (visual)); + + ssi->stderr_cmap = XCreateColormap(si->dpy, + RootWindowOfScreen(ssi->screen), + visual, AllocNone); + + attrmask = (CWColormap | CWBackPixel | CWBackingPixel | CWBorderPixel | + CWBackingStore | CWSaveUnder); + attrs.colormap = ssi->stderr_cmap; + attrs.background_pixel = transparent_pixel; + attrs.backing_pixel = transparent_pixel; + attrs.border_pixel = transparent_pixel; + attrs.backing_store = NotUseful; + attrs.save_under = False; + + ssi->stderr_overlay_window = + XCreateWindow(si->dpy, ssi->screensaver_window, 0, 0, + xgwa.width, xgwa.height, + 0, depth, InputOutput, visual, attrmask, &attrs); + XMapRaised(si->dpy, ssi->stderr_overlay_window); + } +} + + +/* Draws the string on each screen's window as error text. + */ +static void +print_stderr (saver_info *si, char *string) +{ + saver_preferences *p = &si->prefs; + int i; + + /* In verbose mode, copy it to stderr as well. */ + if (p->verbose_p) + fprintf (real_stderr, "%s", string); + + for (i = 0; i < si->nscreens; i++) + print_stderr_1 (&si->screens[i], string); +} + + +/* Polls the stderr buffer every few seconds and if it finds any text, + writes it on all screens. + */ +static void +stderr_popup_timer_fn (XtPointer closure, XtIntervalId *id) +{ + saver_info *si = (saver_info *) closure; + char *s = stderr_buffer; + if (*s) + { + /* If too much data was printed, then something has gone haywire, + so truncate it. */ + char *trailer = "\n\n<< stderr diagnostics have been truncated >>\n\n"; + int max = sizeof (stderr_buffer) - strlen (trailer) - 5; + if (strlen (s) > max) + strcpy (s + max, trailer); + /* Now show the user. */ + print_stderr (si, s); + } + + stderr_tail = stderr_buffer; + si->stderr_popup_timer = 0; +} + + +/* Called when data becomes available on the stderr pipe. Copies it into + stderr_buffer where stderr_popup_timer_fn() can find it later. + */ +static void +stderr_callback (XtPointer closure, int *fd, XtIntervalId *id) +{ + saver_info *si = (saver_info *) closure; + char *s; + int left; + int size; + int read_this_time = 0; + + if (!fd || *fd < 0 || *fd != stderr_stdout_read_fd) + abort(); + + if (stderr_tail == 0) + stderr_tail = stderr_buffer; + + left = ((sizeof (stderr_buffer) - 2) - (stderr_tail - stderr_buffer)); + + s = stderr_tail; + *s = 0; + + /* Read as much data from the fd as we can, up to our buffer size. */ + if (left > 0) + { + while ((size = read (*fd, (void *) s, left)) > 0) + { + left -= size; + s += size; + read_this_time += size; + } + *s = 0; + } + else + { + char buf2 [1024]; + /* The buffer is full; flush the rest of it. */ + while (read (*fd, (void *) buf2, sizeof (buf2)) > 0) + ; + } + + stderr_tail = s; + stderr_last_read = time ((time_t *) 0); + + /* Now we have read some data that we would like to put up in a dialog + box. But more data may still be coming in - so don't pop up the + dialog right now, but instead, start a timer that will pop it up + a second from now. Should more data come in in the meantime, we + will be called again, and will reset that timer again. So the + dialog will only pop up when a second has elapsed with no new data + being written to stderr. + + However, if the buffer is full (meaning lots of data has been written) + then we don't reset the timer. + */ + if (read_this_time > 0) + { + if (si->stderr_popup_timer) + XtRemoveTimeOut (si->stderr_popup_timer); + + si->stderr_popup_timer = + XtAppAddTimeOut (si->app, 1 * 1000, stderr_popup_timer_fn, + (XtPointer) si); + } +} + +/* If stderr capturing is desired, this replaces `stdout' and `stderr' + with a pipe, so that any output written to them will show up on the + screen as well as on the original value of those streams. + */ +void +initialize_stderr (saver_info *si) +{ + static Boolean done = False; + int fds [2]; + int in, out; + int new_stdout, new_stderr; + int stdout_fd = 1; + int stderr_fd = 2; + int flags = 0; + Boolean stderr_dialog_p; + + if (done) return; + done = True; + + real_stderr = stderr; + real_stdout = stdout; + + stderr_dialog_p = get_boolean_resource (si->dpy, "captureStderr", "Boolean"); + + if (!stderr_dialog_p) + return; + + if (pipe (fds)) + { + perror ("error creating pipe:"); + return; + } + + in = fds [0]; + out = fds [1]; + +# ifdef HAVE_FCNTL + +# if defined(O_NONBLOCK) + flags = O_NONBLOCK; +# elif defined(O_NDELAY) + flags = O_NDELAY; +# else + ERROR!! neither O_NONBLOCK nor O_NDELAY are defined. +# endif + + /* Set both sides of the pipe to nonblocking - this is so that + our reads (in stderr_callback) will terminate, and so that + out writes (in the client programs) will silently fail when + the pipe is full, instead of hosing the program. */ + if (fcntl (in, F_SETFL, flags) != 0) + { + perror ("fcntl:"); + return; + } + if (fcntl (out, F_SETFL, flags) != 0) + { + perror ("fcntl:"); + return; + } + +# endif /* !HAVE_FCNTL */ + + if (stderr_dialog_p) + { + FILE *new_stderr_file; + FILE *new_stdout_file; + + new_stderr = dup (stderr_fd); + if (new_stderr < 0) + { + perror ("could not dup() a stderr:"); + return; + } + if (! (new_stderr_file = fdopen (new_stderr, "w"))) + { + perror ("could not fdopen() the new stderr:"); + return; + } + real_stderr = new_stderr_file; + + close (stderr_fd); + if (dup2 (out, stderr_fd) < 0) + { + perror ("could not dup() a new stderr:"); + return; + } + + + new_stdout = dup (stdout_fd); + if (new_stdout < 0) + { + perror ("could not dup() a stdout:"); + return; + } + if (! (new_stdout_file = fdopen (new_stdout, "w"))) + { + perror ("could not fdopen() the new stdout:"); + return; + } + real_stdout = new_stdout_file; + + close (stdout_fd); + if (dup2 (out, stdout_fd) < 0) + { + perror ("could not dup() a new stdout:"); + return; + } + close (out); + } + + stderr_stdout_read_fd = in; + XtAppAddInput (si->app, in, (XtPointer) XtInputReadMask, stderr_callback, + (XtPointer) si); +} + + +/* If the "-log file" command-line option has been specified, + open the file for append, and redirect stdout/stderr there. + This is called very early, before initialize_stderr(). + */ +void +stderr_log_file (saver_info *si) +{ + int stdout_fd = 1; + int stderr_fd = 2; + const char *filename = get_string_resource (si->dpy, "logFile", "LogFile"); + int fd; + + if (!filename || !*filename) return; + + fd = open (filename, O_WRONLY | O_APPEND | O_CREAT, 0666); + + if (fd < 0) + { + char buf[255]; + FAIL: + sprintf (buf, "%.100s: %.100s", blurb(), filename); + perror (buf); + fflush (stderr); + fflush (stdout); + exit (1); + } + + fprintf (stderr, "%s: logging to file %s\n", blurb(), filename); + + if (dup2 (fd, stdout_fd) < 0) goto FAIL; + if (dup2 (fd, stderr_fd) < 0) goto FAIL; + + fprintf (stderr, "\n\n" + "##########################################################################\n" + "%s: logging to \"%s\" at %s\n" + "##########################################################################\n" + "\n", + blurb(), filename, timestring()); +} + + +/* If there is anything in the stderr buffer, flush it to the real stderr. + This does no X operations. Call this when exiting to make sure any + last words actually show up. + */ +void +shutdown_stderr (saver_info *si) +{ + fflush (stdout); + fflush (stderr); + + if (!real_stderr || stderr_stdout_read_fd < 0) + return; + + stderr_callback ((XtPointer) si, &stderr_stdout_read_fd, 0); + + if (stderr_tail && + stderr_buffer < stderr_tail) + { + *stderr_tail = 0; + fprintf (real_stderr, "%s", stderr_buffer); + stderr_tail = stderr_buffer; + } + + if (real_stdout) fflush (real_stdout); + if (real_stderr) fflush (real_stderr); + + if (stdout != real_stdout) + { + dup2 (fileno(real_stdout), fileno(stdout)); + fclose (real_stdout); + real_stdout = stdout; + } + if (stderr != real_stderr) + { + dup2 (fileno(real_stderr), fileno(stderr)); + fclose (real_stderr); + real_stderr = stderr; + } + if (stderr_stdout_read_fd != -1) + { + close (stderr_stdout_read_fd); + stderr_stdout_read_fd = -1; + } +} diff --git a/driver/subprocs.c b/driver/subprocs.c new file mode 100644 index 00000000..2a8f163e --- /dev/null +++ b/driver/subprocs.c @@ -0,0 +1,1375 @@ +/* subprocs.c --- choosing, spawning, and killing screenhacks. + * xscreensaver, Copyright (c) 1991-2012 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. + */ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include +#include +#include + +#include /* not used for much... */ + +#ifndef ESRCH +# include +#endif + +#include /* sys/resource.h needs this for timeval */ +#include /* for PATH_MAX */ + +#ifdef HAVE_SYS_WAIT_H +# include /* for waitpid() and associated macros */ +#endif + +#ifdef HAVE_SETRLIMIT +# include /* for setrlimit() and RLIMIT_AS */ +#endif + +#ifdef VMS +# include +# include /* for close */ +# include /* for getpid */ +# define pid_t int +# define fork vfork +#endif /* VMS */ + +#include /* for the signal names */ + +#if !defined(SIGCHLD) && defined(SIGCLD) +# define SIGCHLD SIGCLD +#endif + +#if 0 /* putenv() is declared in stdlib.h on modern linux systems. */ +#ifdef HAVE_PUTENV +extern int putenv (/* const char * */); /* getenv() is in stdlib.h... */ +#endif +#endif + +extern int kill (pid_t, int); /* signal() is in sys/signal.h... */ + +/* This file doesn't need the Xt headers, so stub these types out... */ +#undef XtPointer +#define XtAppContext void* +#define XrmDatabase void* +#define XtIntervalId void* +#define XtPointer void* +#define Widget void* + +#include "xscreensaver.h" +#include "exec.h" +#include "yarandom.h" +#include "visual.h" /* for id_to_visual() */ + +extern saver_info *global_si_kludge; /* I hate C so much... */ + + +/* Used when printing error/debugging messages from signal handlers. + */ +static const char * +no_malloc_number_to_string (long num) +{ + static char string[128] = ""; + int num_digits; + Bool negative_p = False; + + num_digits = 0; + + if (num == 0) + return "0"; + + if (num < 0) + { + negative_p = True; + num = -num; + } + + while ((num > 0) && (num_digits < sizeof(string) - 1)) + { + int digit; + digit = (int) num % 10; + num_digits++; + string[sizeof(string) - 1 - num_digits] = digit + '0'; + num /= 10; + } + + if (negative_p) + { + num_digits++; + string[sizeof(string) - 1 - num_digits] = '-'; + } + + return string + sizeof(string) - 1 - num_digits; +} + +/* Like write(), but runs strlen() on the arg to get the length. */ +static int +write_string (int fd, const char *str) +{ + return write (fd, str, strlen (str)); +} + +static int +write_long (int fd, long n) +{ + const char *str = no_malloc_number_to_string (n); + return write_string (fd, str); +} + + +/* RLIMIT_AS (called RLIMIT_VMEM on some systems) controls the maximum size + of a process's address space, i.e., the maximal brk(2) and mmap(2) values. + Setting this lets you put a cap on how much memory a process can allocate. + + Except the "and mmap()" part kinda makes this useless, since many GL + implementations end up using mmap() to pull the whole frame buffer into + memory (or something along those lines) making it appear processes are + using hundreds of megabytes when in fact they're using very little, and + we end up capping their mallocs prematurely. YAY! + */ +#if defined(RLIMIT_VMEM) && !defined(RLIMIT_AS) +# define RLIMIT_AS RLIMIT_VMEM +#endif + +static void +limit_subproc_memory (int address_space_limit, Bool verbose_p) +{ + +/* This has caused way more problems than it has solved... + Let's just completely ignore the "memoryLimit" option now. + */ +#undef HAVE_SETRLIMIT + +#if defined(HAVE_SETRLIMIT) && defined(RLIMIT_AS) + struct rlimit r; + + if (address_space_limit < 10 * 1024) /* let's not be crazy */ + return; + + if (getrlimit (RLIMIT_AS, &r) != 0) + { + char buf [512]; + sprintf (buf, "%s: getrlimit(RLIMIT_AS) failed", blurb()); + perror (buf); + return; + } + + r.rlim_cur = address_space_limit; + + if (setrlimit (RLIMIT_AS, &r) != 0) + { + char buf [512]; + sprintf (buf, "%s: setrlimit(RLIMIT_AS, {%lu, %lu}) failed", + blurb(), r.rlim_cur, r.rlim_max); + perror (buf); + return; + } + + if (verbose_p) + { + int i = address_space_limit; + char buf[100]; + if (i >= (1<<30) && i == ((i >> 30) << 30)) + sprintf(buf, "%dG", i >> 30); + else if (i >= (1<<20) && i == ((i >> 20) << 20)) + sprintf(buf, "%dM", i >> 20); + else if (i >= (1<<10) && i == ((i >> 10) << 10)) + sprintf(buf, "%dK", i >> 10); + else + sprintf(buf, "%d bytes", i); + + fprintf (stderr, "%s: limited pid %lu address space to %s.\n", + blurb(), (unsigned long) getpid (), buf); + } + +#endif /* HAVE_SETRLIMIT && RLIMIT_AS */ +} + + +/* Management of child processes, and de-zombification. + */ + +enum job_status { + job_running, /* the process is still alive */ + job_stopped, /* we have sent it a STOP signal */ + job_killed, /* we have sent it a TERM signal */ + job_dead /* we have wait()ed for it, and it's dead -- this state only + occurs so that we can avoid calling free() from a signal + handler. Shortly after going into this state, the list + element will be removed. */ +}; + +struct screenhack_job { + char *name; + pid_t pid; + int screen; + enum job_status status; + struct screenhack_job *next; +}; + +static struct screenhack_job *jobs = 0; + +/* for debugging -- nothing calls this, but it's useful to invoke from gdb. + */ +void show_job_list (void); + +void +show_job_list (void) +{ + struct screenhack_job *job; + fprintf(stderr, "%s: job list:\n", blurb()); + for (job = jobs; job; job = job->next) + fprintf (stderr, " %5ld: %2d: (%s) %s\n", + (long) job->pid, + job->screen, + (job->status == job_running ? "running" : + job->status == job_stopped ? "stopped" : + job->status == job_killed ? " killed" : + job->status == job_dead ? " dead" : " ???"), + job->name); + fprintf (stderr, "\n"); +} + + +static void clean_job_list (void); + +static struct screenhack_job * +make_job (pid_t pid, int screen, const char *cmd) +{ + struct screenhack_job *job = (struct screenhack_job *) malloc (sizeof(*job)); + + static char name [1024]; + const char *in = cmd; + char *out = name; + int got_eq = 0; + int first = 1; + + clean_job_list(); + + AGAIN: + while (isspace(*in)) in++; /* skip whitespace */ + while (!isspace(*in) && *in != ':') { + if (*in == '=') got_eq = 1; + *out++ = *in++; /* snarf first token */ + } + + if (got_eq) /* if the first token was FOO=bar */ + { /* then get the next token instead. */ + got_eq = 0; + out = name; + first = 0; + goto AGAIN; + } + + while (isspace(*in)) in++; /* skip whitespace */ + *out = 0; + + job->name = strdup(name); + job->pid = pid; + job->screen = screen; + job->status = job_running; + job->next = jobs; + jobs = job; + + return jobs; +} + + +static void +free_job (struct screenhack_job *job) +{ + if (!job) + return; + else if (job == jobs) + jobs = jobs->next; + else + { + struct screenhack_job *job2, *prev; + for (prev = 0, job2 = jobs; + job2; + prev = job2, job2 = job2->next) + if (job2 == job) + { + prev->next = job->next; + break; + } + } + free(job->name); + free(job); +} + + +/* Cleans out dead jobs from the jobs list -- this must only be called + from the main thread, not from a signal handler. + */ +static void +clean_job_list (void) +{ + struct screenhack_job *job, *prev, *next; + for (prev = 0, job = jobs, next = (job ? job->next : 0); + job; + prev = job, job = next, next = (job ? job->next : 0)) + { + if (job->status == job_dead) + { + if (prev) + prev->next = next; + free_job (job); + job = prev; + } + } +} + + +static struct screenhack_job * +find_job (pid_t pid) +{ + struct screenhack_job *job; + for (job = jobs; job; job = job->next) + if (job->pid == pid) + return job; + return 0; +} + +static void await_dying_children (saver_info *si); +#ifndef VMS +static void describe_dead_child (saver_info *, pid_t, int wait_status); +#endif + + +/* Semaphore to temporarily turn the SIGCHLD handler into a no-op. + Don't alter this directly -- use block_sigchld() / unblock_sigchld(). + */ +static int block_sigchld_handler = 0; + + +#ifdef HAVE_SIGACTION + sigset_t +#else /* !HAVE_SIGACTION */ + int +#endif /* !HAVE_SIGACTION */ +block_sigchld (void) +{ +#ifdef HAVE_SIGACTION + struct sigaction sa; + sigset_t child_set; + + memset (&sa, 0, sizeof (sa)); + sa.sa_handler = SIG_IGN; + sigaction (SIGPIPE, &sa, NULL); + + sigemptyset (&child_set); + sigaddset (&child_set, SIGCHLD); + sigprocmask (SIG_BLOCK, &child_set, 0); + +#else /* !HAVE_SIGACTION */ + signal (SIGPIPE, SIG_IGN); +#endif /* !HAVE_SIGACTION */ + + block_sigchld_handler++; + +#ifdef HAVE_SIGACTION + return child_set; +#else /* !HAVE_SIGACTION */ + return 0; +#endif /* !HAVE_SIGACTION */ +} + +void +unblock_sigchld (void) +{ +#ifdef HAVE_SIGACTION + struct sigaction sa; + sigset_t child_set; + + memset(&sa, 0, sizeof (sa)); + sa.sa_handler = SIG_DFL; + sigaction(SIGPIPE, &sa, NULL); + + sigemptyset(&child_set); + sigaddset(&child_set, SIGCHLD); + sigprocmask(SIG_UNBLOCK, &child_set, 0); + +#else /* !HAVE_SIGACTION */ + signal(SIGPIPE, SIG_DFL); +#endif /* !HAVE_SIGACTION */ + + block_sigchld_handler--; +} + +static int +kill_job (saver_info *si, pid_t pid, int signal) +{ + saver_preferences *p = &si->prefs; + struct screenhack_job *job; + int status = -1; + + clean_job_list(); + + if (block_sigchld_handler) + /* This function should not be called from the signal handler. */ + abort(); + + block_sigchld(); /* we control the horizontal... */ + + job = find_job (pid); + if (!job || + !job->pid || + job->status == job_killed) + { + if (p->verbose_p) + fprintf (stderr, "%s: no child %ld to signal!\n", + blurb(), (long) pid); + goto DONE; + } + + switch (signal) { + case SIGTERM: job->status = job_killed; break; +#ifdef SIGSTOP + /* #### there must be a way to do this on VMS... */ + case SIGSTOP: job->status = job_stopped; break; + case SIGCONT: job->status = job_running; break; +#endif /* SIGSTOP */ + default: abort(); + } + + if (p->verbose_p) + fprintf (stderr, "%s: %d: %s pid %lu (%s)\n", + blurb(), job->screen, + (job->status == job_killed ? "killing" : + job->status == job_stopped ? "suspending" : "resuming"), + (unsigned long) job->pid, + job->name); + + status = kill (job->pid, signal); + + if (p->verbose_p && status < 0) + { + if (errno == ESRCH) + fprintf (stderr, + "%s: %d: child process %lu (%s) was already dead.\n", + blurb(), job->screen, (unsigned long) job->pid, job->name); + else + { + char buf [1024]; + sprintf (buf, "%s: %d: couldn't kill child process %lu (%s)", + blurb(), job->screen, (unsigned long) job->pid, job->name); + perror (buf); + } + } + + await_dying_children (si); + + DONE: + unblock_sigchld(); + if (block_sigchld_handler < 0) + abort(); + + clean_job_list(); + return status; +} + + +#ifdef SIGCHLD +static RETSIGTYPE +sigchld_handler (int sig) +{ + saver_info *si = global_si_kludge; /* I hate C so much... */ + in_signal_handler_p++; + + if (si->prefs.debug_p) + { + /* Don't call fprintf() from signal handlers, as it might malloc. + fprintf(stderr, "%s: got SIGCHLD%s\n", blurb(), + (block_sigchld_handler ? " (blocked)" : "")); + */ + write_string (STDERR_FILENO, blurb()); + write_string (STDERR_FILENO, ": got SIGCHLD"); + + if (block_sigchld_handler) + write_string (STDERR_FILENO, " (blocked)\n"); + else + write_string (STDERR_FILENO, "\n"); + } + + if (block_sigchld_handler < 0) + abort(); + else if (block_sigchld_handler == 0) + { + block_sigchld(); + await_dying_children (si); + unblock_sigchld(); + } + + init_sigchld(); + in_signal_handler_p--; +} +#endif /* SIGCHLD */ + + +#ifndef VMS + +static void +await_dying_children (saver_info *si) +{ + while (1) + { + int wait_status = 0; + pid_t kid; + + errno = 0; + kid = waitpid (-1, &wait_status, WNOHANG|WUNTRACED); + + if (si->prefs.debug_p) + { + if (kid < 0 && errno) + { + /* Don't call fprintf() from signal handlers, as it might malloc. + fprintf (stderr, "%s: waitpid(-1) ==> %ld (%d)\n", blurb(), + (long) kid, errno); + */ + write_string (STDERR_FILENO, blurb()); + write_string (STDERR_FILENO, ": waitpid(-1) ==> "); + write_long (STDERR_FILENO, (long) kid); + write_string (STDERR_FILENO, " ("); + write_long (STDERR_FILENO, (long) errno); + write_string (STDERR_FILENO, ")\n"); + } + else + { + /* Don't call fprintf() from signal handlers, as it might malloc. + fprintf (stderr, "%s: waitpid(-1) ==> %ld\n", blurb(), + (long) kid); + */ + write_string (STDERR_FILENO, blurb()); + write_string (STDERR_FILENO, ": waitpid(-1) ==> "); + write_long (STDERR_FILENO, (long) kid); + write_string (STDERR_FILENO, "\n"); + } + } + + /* 0 means no more children to reap. + -1 means error -- except "interrupted system call" isn't a "real" + error, so if we get that, we should just try again. */ + if (kid == 0 || + (kid < 0 && errno != EINTR)) + break; + + describe_dead_child (si, kid, wait_status); + } +} + + +static void +describe_dead_child (saver_info *si, pid_t kid, int wait_status) +{ + int i; + saver_preferences *p = &si->prefs; + struct screenhack_job *job = find_job (kid); + const char *name = job ? job->name : ""; + int screen_no = job ? job->screen : 0; + + if (WIFEXITED (wait_status)) + { + int exit_status = WEXITSTATUS (wait_status); + + /* Treat exit code as a signed 8-bit quantity. */ + if (exit_status & 0x80) exit_status |= ~0xFF; + + /* One might assume that exiting with non-0 means something went wrong. + But that loser xswarm exits with the code that it was killed with, so + it *always* exits abnormally. Treat abnormal exits as "normal" (don't + mention them) if we've just killed the subprocess. But mention them + if they happen on their own. + */ + if (!job || + (exit_status != 0 && + (p->verbose_p || job->status != job_killed))) + { + /* Don't call fprintf() from signal handlers, as it might malloc. + fprintf (stderr, + "%s: %d: child pid %lu (%s) exited abnormally (code %d).\n", + blurb(), screen_no, (unsigned long) kid, name, exit_status); + */ + write_string (STDERR_FILENO, blurb()); + write_string (STDERR_FILENO, ": "); + write_long (STDERR_FILENO, (long) screen_no); + write_string (STDERR_FILENO, ": child pid "); + write_long (STDERR_FILENO, (long) kid); + write_string (STDERR_FILENO, " ("); + write_string (STDERR_FILENO, name); + write_string (STDERR_FILENO, ") exited abnormally (code "); + write_long (STDERR_FILENO, (long) exit_status); + write_string (STDERR_FILENO, ").\n"); + } + else if (p->verbose_p) + { + /* Don't call fprintf() from signal handlers, as it might malloc. + fprintf (stderr, "%s: %d: child pid %lu (%s) exited normally.\n", + blurb(), screen_no, (unsigned long) kid, name); + */ + write_string (STDERR_FILENO, blurb()); + write_string (STDERR_FILENO, ": "); + write_long (STDERR_FILENO, (long) screen_no); + write_string (STDERR_FILENO, ": child pid "); + write_long (STDERR_FILENO, (long) kid); + write_string (STDERR_FILENO, " ("); + write_string (STDERR_FILENO, name); + write_string (STDERR_FILENO, ") exited normally.\n"); + } + + if (job) + job->status = job_dead; + } + else if (WIFSIGNALED (wait_status)) + { + if (p->verbose_p || + !job || + job->status != job_killed || + WTERMSIG (wait_status) != SIGTERM) + { + /* Don't call fprintf() from signal handlers, as it might malloc. + fprintf (stderr, "%s: %d: child pid %lu (%s) terminated with %s.\n", + blurb(), screen_no, (unsigned long) kid, name, + signal_name (WTERMSIG(wait_status))); + */ + write_string (STDERR_FILENO, blurb()); + write_string (STDERR_FILENO, ": "); + write_long (STDERR_FILENO, (long) screen_no); + write_string (STDERR_FILENO, ": child pid "); + write_long (STDERR_FILENO, (long) kid); + write_string (STDERR_FILENO, " ("); + write_string (STDERR_FILENO, name); + write_string (STDERR_FILENO, ") terminated with signal "); + write_long (STDERR_FILENO, WTERMSIG(wait_status)); + write_string (STDERR_FILENO, ".\n"); + } + + if (job) + job->status = job_dead; + } + else if (WIFSTOPPED (wait_status)) + { + if (p->verbose_p) + { + /* Don't call fprintf() from signal handlers, as it might malloc. + fprintf (stderr, "%s: child pid %lu (%s) stopped with %s.\n", + blurb(), (unsigned long) kid, name, + signal_name (WSTOPSIG (wait_status))); + */ + write_string (STDERR_FILENO, blurb()); + write_string (STDERR_FILENO, ": "); + write_long (STDERR_FILENO, (long) screen_no); + write_string (STDERR_FILENO, ": child pid "); + write_long (STDERR_FILENO, (long) kid); + write_string (STDERR_FILENO, " ("); + write_string (STDERR_FILENO, name); + write_string (STDERR_FILENO, ") stopped with signal "); + write_long (STDERR_FILENO, WSTOPSIG(wait_status)); + write_string (STDERR_FILENO, ".\n"); + } + + if (job) + job->status = job_stopped; + } + else + { + /* Don't call fprintf() from signal handlers, as it might malloc. + fprintf (stderr, "%s: child pid %lu (%s) died in a mysterious way!", + blurb(), (unsigned long) kid, name); + */ + write_string (STDERR_FILENO, blurb()); + write_string (STDERR_FILENO, ": "); + write_long (STDERR_FILENO, (long) screen_no); + write_string (STDERR_FILENO, ": child pid "); + write_long (STDERR_FILENO, (long) kid); + write_string (STDERR_FILENO, " ("); + write_string (STDERR_FILENO, name); + write_string (STDERR_FILENO, ") died in a mysterious way!"); + if (job) + job->status = job_dead; + } + + /* Clear out the pid so that screenhack_running_p() knows it's dead. + */ + if (!job || job->status == job_dead) + for (i = 0; i < si->nscreens; i++) + { + saver_screen_info *ssi = &si->screens[i]; + if (kid == ssi->pid) + ssi->pid = 0; + } +} + +#else /* VMS */ +static void await_dying_children (saver_info *si) { return; } +#endif /* VMS */ + + +void +init_sigchld (void) +{ +#ifdef SIGCHLD + +# ifdef HAVE_SIGACTION /* Thanks to Tom Kelly */ + + static Bool sigchld_initialized_p = 0; + if (!sigchld_initialized_p) + { + struct sigaction action, old; + + action.sa_handler = sigchld_handler; + sigemptyset(&action.sa_mask); + action.sa_flags = 0; + + if (sigaction(SIGCHLD, &action, &old) < 0) + { + char buf [255]; + sprintf (buf, "%s: couldn't catch SIGCHLD", blurb()); + perror (buf); + } + sigchld_initialized_p = True; + } + +# else /* !HAVE_SIGACTION */ + + if (((long) signal (SIGCHLD, sigchld_handler)) == -1L) + { + char buf [255]; + sprintf (buf, "%s: couldn't catch SIGCHLD", blurb()); + perror (buf); + } +# endif /* !HAVE_SIGACTION */ +#endif /* SIGCHLD */ +} + + + + + +static Bool +select_visual_of_hack (saver_screen_info *ssi, screenhack *hack) +{ + saver_info *si = ssi->global; + saver_preferences *p = &si->prefs; + Bool selected; + + if (hack->visual && *hack->visual) + selected = select_visual(ssi, hack->visual); + else + selected = select_visual(ssi, 0); + + if (!selected && (p->verbose_p || si->demoing_p)) + fprintf (stderr, + (si->demoing_p + ? "%s: warning, no \"%s\" visual for \"%s\".\n" + : "%s: no \"%s\" visual; skipping \"%s\".\n"), + blurb(), + (hack->visual && *hack->visual ? hack->visual : "???"), + hack->command); + + return selected; +} + + +static void +print_path_error (const char *program) +{ + char buf [512]; + char *cmd = strdup (program); + char *token = strchr (cmd, ' '); + + if (token) *token = 0; + sprintf (buf, "%s: could not execute \"%.100s\"", blurb(), cmd); + free (cmd); + perror (buf); + + if (errno == ENOENT && + (token = getenv("PATH"))) + { +# ifndef PATH_MAX +# ifdef MAXPATHLEN +# define PATH_MAX MAXPATHLEN +# else +# define PATH_MAX 2048 +# endif +# endif + char path[PATH_MAX]; + fprintf (stderr, "\n"); + *path = 0; +# if defined(HAVE_GETCWD) + if (! getcwd (path, sizeof(path))) + *path = 0; +# elif defined(HAVE_GETWD) + getwd (path); +# endif + if (*path) + fprintf (stderr, " Current directory is: %s\n", path); + fprintf (stderr, " PATH is:\n"); + token = strtok (strdup(token), ":"); + while (token) + { + fprintf (stderr, " %s\n", token); + token = strtok(0, ":"); + } + fprintf (stderr, "\n"); + } +} + + +/* Executes the command in another process. + Command may be any single command acceptable to /bin/sh. + It may include wildcards, but no semicolons. + If successful, the pid of the other process is returned. + Otherwise, -1 is returned and an error may have been + printed to stderr. + */ +pid_t +fork_and_exec (saver_screen_info *ssi, const char *command) +{ + saver_info *si = ssi->global; + saver_preferences *p = &si->prefs; + pid_t forked; + + switch ((int) (forked = fork ())) + { + case -1: + { + char buf [255]; + sprintf (buf, "%s: couldn't fork", blurb()); + perror (buf); + break; + } + + case 0: + close (ConnectionNumber (si->dpy)); /* close display fd */ + limit_subproc_memory (p->inferior_memory_limit, p->verbose_p); + hack_subproc_environment (ssi->screen, ssi->screensaver_window); + + if (p->verbose_p) + fprintf (stderr, "%s: %d: spawning \"%s\" in pid %lu.\n", + blurb(), ssi->number, command, + (unsigned long) getpid ()); + + exec_command (p->shell, command, p->nice_inferior); + + /* If that returned, we were unable to exec the subprocess. + Print an error message, if desired. + */ + if (! p->ignore_uninstalled_p) + print_path_error (command); + + exit (1); /* exits child fork */ + break; + + default: /* parent */ + (void) make_job (forked, ssi->number, command); + break; + } + + return forked; +} + + +void +spawn_screenhack (saver_screen_info *ssi) +{ + saver_info *si = ssi->global; + saver_preferences *p = &si->prefs; + XFlush (si->dpy); + + if (!monitor_powered_on_p (si)) + { + if (si->prefs.verbose_p) + fprintf (stderr, + "%s: %d: X says monitor has powered down; " + "not launching a hack.\n", blurb(), ssi->number); + return; + } + + if (p->screenhacks_count) + { + screenhack *hack; + pid_t forked; + char buf [255]; + int new_hack = -1; + int retry_count = 0; + Bool force = False; + + AGAIN: + + if (p->screenhacks_count < 1) + { + /* No hacks at all */ + new_hack = -1; + } + else if (p->screenhacks_count == 1) + { + /* Exactly one hack in the list */ + new_hack = 0; + } + else if (si->selection_mode == -1) + { + /* Select the next hack, wrapping. */ + new_hack = (ssi->current_hack + 1) % p->screenhacks_count; + } + else if (si->selection_mode == -2) + { + /* Select the previous hack, wrapping. */ + if (ssi->current_hack < 0) + new_hack = p->screenhacks_count - 1; + else + new_hack = ((ssi->current_hack + p->screenhacks_count - 1) + % p->screenhacks_count); + } + else if (si->selection_mode > 0) + { + /* Select a specific hack, by number (via the ACTIVATE command.) */ + new_hack = ((si->selection_mode - 1) % p->screenhacks_count); + force = True; + } + else if (p->mode == ONE_HACK && + p->selected_hack >= 0) + { + /* Select a specific hack, by number (via "One Saver" mode.) */ + new_hack = p->selected_hack; + force = True; + } + else if (p->mode == BLANK_ONLY || p->mode == DONT_BLANK) + { + new_hack = -1; + } + else if (p->mode == RANDOM_HACKS_SAME && + ssi->number != 0) + { + /* Use the same hack that's running on screen 0. + (Assumes this function was called on screen 0 first.) + */ + new_hack = si->screens[0].current_hack; + } + else /* (p->mode == RANDOM_HACKS) */ + { + /* Select a random hack (but not the one we just ran.) */ + while ((new_hack = random () % p->screenhacks_count) + == ssi->current_hack) + ; + } + + if (new_hack < 0) /* don't run a hack */ + { + ssi->current_hack = -1; + if (si->selection_mode < 0) + si->selection_mode = 0; + return; + } + + ssi->current_hack = new_hack; + hack = p->screenhacks[ssi->current_hack]; + + /* If the hack is disabled, or there is no visual for this hack, + then try again (move forward, or backward, or re-randomize.) + Unless this hack was specified explicitly, in which case, + use it regardless. + */ + if (force) + select_visual_of_hack (ssi, hack); + + if (!force && + (!hack->enabled_p || + !on_path_p (hack->command) || + !select_visual_of_hack (ssi, hack))) + { + if (++retry_count > (p->screenhacks_count*4)) + { + /* Uh, oops. Odds are, there are no suitable visuals, + and we're looping. Give up. (This is totally lame, + what we should do is make a list of suitable hacks at + the beginning, then only loop over them.) + */ + if (p->verbose_p) + fprintf(stderr, + "%s: %d: no programs enabled, or no suitable visuals.\n", + blurb(), ssi->number); + return; + } + else + goto AGAIN; + } + + /* Turn off "next" and "prev" modes now, but "demo" mode is only + turned off by explicit action. + */ + if (si->selection_mode < 0) + si->selection_mode = 0; + + forked = fork_and_exec (ssi, hack->command); + switch ((int) forked) + { + case -1: /* fork failed */ + case 0: /* child fork (can't happen) */ + sprintf (buf, "%s: couldn't fork", blurb()); + perror (buf); + restore_real_vroot (si); + saver_exit (si, 1, "couldn't fork"); + break; + + default: + ssi->pid = forked; + break; + } + } + + store_saver_status (si); /* store current hack number */ +} + + +void +kill_screenhack (saver_screen_info *ssi) +{ + saver_info *si = ssi->global; + if (ssi->pid) + kill_job (si, ssi->pid, SIGTERM); + ssi->pid = 0; +} + + +void +suspend_screenhack (saver_screen_info *ssi, Bool suspend_p) +{ +#ifdef SIGSTOP /* older VMS doesn't have it... */ + saver_info *si = ssi->global; + if (ssi->pid) + kill_job (si, ssi->pid, (suspend_p ? SIGSTOP : SIGCONT)); +#endif /* SIGSTOP */ +} + + +/* Called when we're exiting abnormally, to kill off the subproc. */ +void +emergency_kill_subproc (saver_info *si) +{ + int i; +#ifdef SIGCHLD + signal (SIGCHLD, SIG_IGN); +#endif /* SIGCHLD */ + + for (i = 0; i < si->nscreens; i++) + { + saver_screen_info *ssi = &si->screens[i]; + if (ssi->pid) + { + kill_job (si, ssi->pid, SIGTERM); + ssi->pid = 0; + } + } +} + +Bool +screenhack_running_p (saver_info *si) +{ + Bool any_running_p = False; + int i; + for (i = 0; i < si->nscreens; i++) + { + saver_screen_info *ssi = &si->screens[i]; + if (ssi->pid) any_running_p = True; + } + return any_running_p; +} + + +/* Environment variables. */ + + +/* Modifies $PATH in the current environment, so that if DEFAULT_PATH_PREFIX + is defined, the xscreensaver daemon will search that directory for hacks. + */ +void +hack_environment (saver_info *si) +{ +#if defined(HAVE_PUTENV) && defined(DEFAULT_PATH_PREFIX) + static const char *def_path = DEFAULT_PATH_PREFIX; + if (def_path && *def_path) + { + const char *opath = getenv("PATH"); + char *npath = (char *) malloc(strlen(def_path) + strlen(opath) + 20); + strcpy (npath, "PATH="); + strcat (npath, def_path); + strcat (npath, ":"); + strcat (npath, opath); + + if (putenv (npath)) + abort (); + + /* don't free (npath) -- some implementations of putenv (BSD 4.4, + glibc 2.0) copy the argument, but some (libc4,5, glibc 2.1.2) + do not. So we must leak it (and/or the previous setting). Yay. + */ + } +#endif /* HAVE_PUTENV && DEFAULT_PATH_PREFIX */ +} + + +void +hack_subproc_environment (Screen *screen, Window saver_window) +{ + /* Store $DISPLAY into the environment, so that the $DISPLAY variable that + the spawned processes inherit is correct. First, it must be on the same + host and display as the value of -display passed in on our command line + (which is not necessarily the same as what our $DISPLAY variable is.) + Second, the screen number in the $DISPLAY passed to the subprocess should + be the screen on which this particular hack is running -- not the display + specification which the driver itself is using, since the driver ignores + its screen number and manages all existing screens. + + Likewise, store a window ID in $XSCREENSAVER_WINDOW -- this will allow + us to (eventually) run multiple hacks in Xinerama mode, where each hack + has the same $DISPLAY but a different piece of glass. + */ + Display *dpy = DisplayOfScreen (screen); + const char *odpy = DisplayString (dpy); + char *ndpy = (char *) malloc (strlen(odpy) + 20); + char *nssw = (char *) malloc (40); + char *s, *c; + + strcpy (ndpy, "DISPLAY="); + s = ndpy + strlen(ndpy); + strcpy (s, odpy); + + /* We have to find the last colon since it is the boundary between + hostname & screen - IPv6 numeric format addresses may have many + colons before that point, and DECnet addresses always have two colons */ + c = strrchr(s,':'); /* skip to last colon */ + if (c != NULL) s = c+1; + while (isdigit(*s)) s++; /* skip over dpy number */ + while (*s == '.') s++; /* skip over dot */ + if (s[-1] != '.') *s++ = '.'; /* put on a dot */ + sprintf(s, "%d", screen_number (screen)); /* put on screen number */ + + sprintf (nssw, "XSCREENSAVER_WINDOW=0x%lX", (unsigned long) saver_window); + + /* Allegedly, BSD 4.3 didn't have putenv(), but nobody runs such systems + any more, right? It's not Posix, but everyone seems to have it. */ +#ifdef HAVE_PUTENV + if (putenv (ndpy)) + abort (); + if (putenv (nssw)) + abort (); + + /* don't free ndpy/nssw -- some implementations of putenv (BSD 4.4, + glibc 2.0) copy the argument, but some (libc4,5, glibc 2.1.2) + do not. So we must leak it (and/or the previous setting). Yay. + */ +#endif /* HAVE_PUTENV */ +} + + +/* GL crap */ + +Visual * +get_best_gl_visual (saver_info *si, Screen *screen) +{ + pid_t forked; + int fds [2]; + int in, out; + int errfds[2]; + int errin = -1, errout = -1; + char buf[1024]; + + char *av[10]; + int ac = 0; + + av[ac++] = "xscreensaver-gl-helper"; + av[ac] = 0; + + if (pipe (fds)) + { + perror ("error creating pipe:"); + return 0; + } + + in = fds [0]; + out = fds [1]; + + if (!si->prefs.verbose_p) + { + if (pipe (errfds)) + { + perror ("error creating pipe:"); + return 0; + } + + errin = errfds [0]; + errout = errfds [1]; + } + + block_sigchld(); /* This blocks it in the parent and child, to avoid + racing. It is never unblocked in the child before + the child exits, but that doesn't matter. + */ + + switch ((int) (forked = fork ())) + { + case -1: + { + sprintf (buf, "%s: couldn't fork", blurb()); + perror (buf); + saver_exit (si, 1, 0); + } + case 0: + { + close (in); /* don't need this one */ + close (ConnectionNumber (si->dpy)); /* close display fd */ + + if (dup2 (out, STDOUT_FILENO) < 0) /* pipe stdout */ + { + perror ("could not dup() a new stdout:"); + return 0; + } + + if (! si->prefs.verbose_p) + { + close(errin); + if (dup2 (errout, STDERR_FILENO) < 0) + { + perror ("could not dup() a new stderr:"); + return 0; + } + } + + hack_subproc_environment (screen, 0); /* set $DISPLAY */ + + execvp (av[0], av); /* shouldn't return. */ + + if (errno != ENOENT /* || si->prefs.verbose_p */ ) + { + /* Ignore "no such file or directory" errors. + Issue all other exec errors, though. */ + sprintf (buf, "%s: running %s", blurb(), av[0]); + perror (buf); + } + exit (1); /* exits fork */ + break; + } + default: + { + int result = 0; + int wait_status = 0; + + FILE *f = fdopen (in, "r"); + unsigned long v = 0; + char c; + + close (out); /* don't need this one */ + + *buf = 0; + if (! fgets (buf, sizeof(buf)-1, f)) + *buf = 0; + fclose (f); + + if (! si->prefs.verbose_p) + { + close (errout); + close (errin); + } + + /* Wait for the child to die. */ + waitpid (-1, &wait_status, 0); + + unblock_sigchld(); /* child is dead and waited, unblock now. */ + + if (1 == sscanf (buf, "0x%lx %c", &v, &c)) + result = (int) v; + + if (result == 0) + { + if (si->prefs.verbose_p) + { + int L = strlen(buf); + fprintf (stderr, "%s: %s did not report a GL visual!\n", + blurb(), av[0]); + + if (L && buf[L-1] == '\n') + buf[--L] = 0; + if (*buf) + fprintf (stderr, "%s: %s said: \"%s\"\n", + blurb(), av[0], buf); + } + return 0; + } + else + { + Visual *v = id_to_visual (screen, result); + if (si->prefs.verbose_p) + fprintf (stderr, "%s: %d: %s: GL visual is 0x%X%s.\n", + blurb(), screen_number (screen), + av[0], result, + (v == DefaultVisualOfScreen (screen) + ? " (default)" : "")); + return v; + } + } + } + + abort(); +} + + + +/* Restarting the xscreensaver process from scratch. */ + +static char **saved_argv; + +void +save_argv (int argc, char **argv) +{ + saved_argv = (char **) calloc (argc+2, sizeof (char *)); + saved_argv [argc] = 0; + while (argc--) + { + int i = strlen (argv [argc]) + 1; + saved_argv [argc] = (char *) malloc (i); + memcpy (saved_argv [argc], argv [argc], i); + } +} + + +/* Re-execs the process with the arguments in saved_argv. Does not return. + */ +void +restart_process (saver_info *si) +{ + fflush (stdout); + fflush (stderr); + shutdown_stderr (si); + if (si->prefs.verbose_p) + { + int i; + fprintf (stderr, "%s: re-executing", blurb()); + for (i = 0; saved_argv[i]; i++) + fprintf (stderr, " %s", saved_argv[i]); + fprintf (stderr, "\n"); + } + describe_uids (si, stderr); + fprintf (stderr, "\n"); + + fflush (stdout); + fflush (stderr); + execvp (saved_argv [0], saved_argv); /* shouldn't return */ + { + char buf [512]; + sprintf (buf, "%s: could not restart process", blurb()); + perror(buf); + fflush(stderr); + abort(); + } +} diff --git a/driver/test-apm.c b/driver/test-apm.c new file mode 100644 index 00000000..6b87c7e7 --- /dev/null +++ b/driver/test-apm.c @@ -0,0 +1,101 @@ +/* test-apm.c --- playing with the APM library. + * xscreensaver, Copyright (c) 1999 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. + */ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include +#ifdef HAVE_UNISTD_H +# include +#endif + +#include +#include +#include + +#include +#include + +#include + +#define countof(x) (sizeof((x))/sizeof(*(x))) + + +char *progname = 0; +char *progclass = "XScreenSaver"; + +static const char * +blurb (void) +{ + static char buf[255]; + time_t now = time ((time_t *) 0); + char *ct = (char *) ctime (&now); + int n = strlen(progname); + if (n > 100) n = 99; + strncpy(buf, progname, n); + buf[n++] = ':'; + buf[n++] = ' '; + strncpy(buf+n, ct+11, 8); + strcpy(buf+n+9, ": "); + return buf; +} + +static void +apm_cb (XtPointer closure, int *fd, XtInputId *id) +{ + apm_event_t events[100]; + int n, i; + while ((n = apm_get_events (*fd, 0, events, countof(events))) + > 0) + for (i = 0; i < n; i++) + { + fprintf (stderr, "%s: APM event 0x%x: %s.\n", blurb(), + events[i], apm_event_name (events[i])); +#if 0 + switch (events[i]) + { + case APM_SYS_STANDBY: + case APM_USER_STANDBY: + case APM_SYS_SUSPEND: + case APM_USER_SUSPEND: + case APM_CRITICAL_SUSPEND: + break; + } +#endif + } +} + +int +main (int argc, char **argv) +{ + XtAppContext app; + Widget toplevel_shell = XtAppInitialize (&app, progclass, 0, 0, + &argc, argv, 0, 0, 0); + Display *dpy = XtDisplay (toplevel_shell); + int fd; + XtInputId id; + XtGetApplicationNameAndClass (dpy, &progname, &progclass); + + fd = apm_open (); + if (fd <= 0) + { + fprintf (stderr, "%s: couldn't initialize APM.\n", blurb()); + exit (1); + } + + id = XtAppAddInput(app, fd, + (XtPointer) (XtInputReadMask | XtInputWriteMask), + apm_cb, 0); + XtAppMainLoop (app); + exit (0); +} diff --git a/driver/test-fade.c b/driver/test-fade.c new file mode 100644 index 00000000..9db773d0 --- /dev/null +++ b/driver/test-fade.c @@ -0,0 +1,123 @@ +/* test-fade.c --- playing with colormap and/or gamma fading. + * xscreensaver, Copyright (c) 2001, 2004 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. + */ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include +#ifdef HAVE_UNISTD_H +# include +#endif + +#include + +#include +#include "xscreensaver.h" +#include "fade.h" + +#ifdef HAVE_SGI_VC_EXTENSION +# include +#endif +#ifdef HAVE_XF86VMODE_GAMMA +# include +#endif + +XrmDatabase db = 0; +char *progname = 0; +char *progclass = "XScreenSaver"; + +#define SGI_VC_NAME "SGI-VIDEO-CONTROL" +#define XF86_VIDMODE_NAME "XFree86-VidModeExtension" + +int +main (int argc, char **argv) +{ + int seconds = 3; + int ticks = 20; + int delay = 1; + + int op, event, error, major, minor; + + XtAppContext app; + Widget toplevel_shell = XtAppInitialize (&app, progclass, 0, 0, + &argc, argv, 0, 0, 0); + Display *dpy = XtDisplay (toplevel_shell); + Colormap *current_maps; + int i; + + XtGetApplicationNameAndClass (dpy, &progname, &progclass); + db = XtDatabase (dpy); + + current_maps = (Colormap *) calloc(sizeof(Colormap), ScreenCount(dpy)); + for (i = 0; i < ScreenCount(dpy); i++) + current_maps[i] = DefaultColormap (dpy, i); + + if (!XQueryExtension (dpy, SGI_VC_NAME, &op, &event, &error)) + fprintf(stderr, "%s: no " SGI_VC_NAME " extension\n", progname); + else + { +# ifdef HAVE_SGI_VC_EXTENSION + if (!XSGIvcQueryVersion (dpy, &major, &minor)) + fprintf(stderr, "%s: unable to get " SGI_VC_NAME " version\n", + progname); + else + fprintf(stderr, "%s: " SGI_VC_NAME " version %d.%d\n", + progname, major, minor); +# else /* !HAVE_SGI_VC_EXTENSION */ + fprintf(stderr, "%s: no support for display's " SGI_VC_NAME + " extension\n", progname); +# endif /* !HAVE_SGI_VC_EXTENSION */ + } + + + if (!XQueryExtension (dpy, XF86_VIDMODE_NAME, &op, &event, &error)) + fprintf(stderr, "%s: no " XF86_VIDMODE_NAME " extension\n", progname); + else + { +# ifdef HAVE_XF86VMODE_GAMMA + if (!XF86VidModeQueryVersion (dpy, &major, &minor)) + fprintf(stderr, "%s: unable to get " XF86_VIDMODE_NAME " version\n", + progname); + else + fprintf(stderr, "%s: " XF86_VIDMODE_NAME " version %d.%d\n", + progname, major, minor); +# else /* !HAVE_XF86VMODE_GAMMA */ + fprintf(stderr, "%s: no support for display's " XF86_VIDMODE_NAME + " extension\n", progname); +# endif /* !HAVE_XF86VMODE_GAMMA */ + } + + fprintf (stderr, "%s: fading %d screen%s\n", + progname, ScreenCount(dpy), ScreenCount(dpy) == 1 ? "" : "s"); + + while (1) + { + XSync (dpy, False); + + fprintf(stderr, "%s: out...", progname); + fflush(stderr); + fade_screens (dpy, current_maps, 0, 0, seconds, ticks, True, False); + fprintf(stderr, "done.\n"); + fflush(stderr); + + if (delay) sleep (delay); + + fprintf(stderr,"%s: in...", progname); + fflush(stderr); + fade_screens (dpy, current_maps, 0, 0, seconds, ticks, False, False); + fprintf(stderr, "done.\n"); + fflush(stderr); + + if (delay) sleep (delay); + } +} diff --git a/driver/test-grab.c b/driver/test-grab.c new file mode 100644 index 00000000..03018eb5 --- /dev/null +++ b/driver/test-grab.c @@ -0,0 +1,89 @@ +/* test-uid.c --- playing with grabs. + * xscreensaver, Copyright (c) 1999, 2004 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. + */ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include +#ifdef HAVE_UNISTD_H +# include +#endif + +#include +#include + +#include +#include + +char *progname = 0; +char *progclass = "XScreenSaver"; + +#define ALL_POINTER_EVENTS \ + (ButtonPressMask | ButtonReleaseMask | EnterWindowMask | \ + LeaveWindowMask | PointerMotionMask | PointerMotionHintMask | \ + Button1MotionMask | Button2MotionMask | Button3MotionMask | \ + Button4MotionMask | Button5MotionMask | ButtonMotionMask) + +int +main (int argc, char **argv) +{ + XtAppContext app; + int kstatus, mstatus; + Cursor cursor = 0; + int delay = 60 * 15; + Widget toplevel_shell = XtAppInitialize (&app, progclass, 0, 0, + &argc, argv, 0, 0, 0); + Display *dpy = XtDisplay (toplevel_shell); + Window w = RootWindow (dpy, DefaultScreen(dpy)); + XtGetApplicationNameAndClass (dpy, &progname, &progclass); + + kstatus = XGrabKeyboard (dpy, w, True, + GrabModeSync, GrabModeAsync, + CurrentTime); + fprintf (stderr, "%s: grabbing keyboard on 0x%lx... %s.\n", + progname, (unsigned long) w, + (kstatus == GrabSuccess ? "GrabSuccess" : + kstatus == AlreadyGrabbed ? "AlreadyGrabbed" : + kstatus == GrabInvalidTime ? "GrabInvalidTime" : + kstatus == GrabNotViewable ? "GrabNotViewable" : + kstatus == GrabFrozen ? "GrabFrozen" : + "???")); + + mstatus = XGrabPointer (dpy, w, True, ALL_POINTER_EVENTS, + GrabModeAsync, GrabModeAsync, None, + cursor, CurrentTime); + fprintf (stderr, "%s: grabbing mouse on 0x%lx... %s.\n", + progname, (unsigned long) w, + (mstatus == GrabSuccess ? "GrabSuccess" : + mstatus == AlreadyGrabbed ? "AlreadyGrabbed" : + mstatus == GrabInvalidTime ? "GrabInvalidTime" : + mstatus == GrabNotViewable ? "GrabNotViewable" : + mstatus == GrabFrozen ? "GrabFrozen" : + "???")); + + XSync(dpy, False); + + if (kstatus == GrabSuccess || mstatus == GrabSuccess) + { + fprintf (stderr, "%s: sleeping for %d:%02d:%02d...\n", + progname, + delay / (60 * 60), + (delay % (60 * 60)) / 60, + delay % 60); + fflush(stderr); + sleep (delay); + XSync(dpy, False); + } + + exit (0); +} diff --git a/driver/test-mlstring.c b/driver/test-mlstring.c new file mode 100644 index 00000000..e269a004 --- /dev/null +++ b/driver/test-mlstring.c @@ -0,0 +1,312 @@ +/* + * (c) 2007, Quest Software, Inc. All rights reserved. + * + * This file is part of XScreenSaver, + * Copyright (c) 1993-2004 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. + */ + +#include +#include +#include + +#include "mlstring.c" /* hokey, but whatever */ + +#define WRAP_WIDTH_PX 100 + +#undef Bool +#undef True +#undef False +typedef int Bool; +#define True 1 +#define False 0 + +#define SKIPPED -1 +#define SUCCESS 0 +#define FAILURE 1 + +#define FAIL(msg, ...) \ + do { \ + ++failcount; \ + fprintf(stderr, "[FAIL] "); \ + fprintf(stderr, msg, __VA_ARGS__); \ + putc('\n', stderr); \ + return FAILURE; \ + } while (0) + +#define SUCCEED(testname) \ + do { \ + fprintf(stderr, "[SUCCESS] %s\n", (testname)); \ + } while (0) + +#define SKIP(testname) \ + do { \ + fprintf(stderr, "[SKIPPED] %s\n", (testname)); \ + } while (0) + +extern mlstring* mlstring_allocate(const char *msg); +extern void mlstring_wrap(mlstring *mstr, XFontStruct *font, Dimension width); + +static int failcount = 0; + +static char *mlstring_to_cstr(const mlstring *mlstr) { + char *cstr; + size_t cstrlen = 0, alloclen = 1024; + const struct mlstr_line *line; + + cstr = malloc(alloclen); + if (!cstr) + return NULL; + cstr[0] = '\0'; + + for (line = mlstr->lines; line; line = line->next_line) { + /* Extend the buffer if necessary. */ + if (cstrlen + strlen(line->line) + 1 > alloclen) { + cstr = realloc(cstr, alloclen *= 2); + if (!cstr) + return NULL; + } + + /* If this is not the first line */ + if (line != mlstr->lines) { + /* Append a newline character */ + cstr[cstrlen] = '\n'; + ++cstrlen; + cstr[cstrlen] = '\0'; + } + + strcat(cstr, line->line); + cstrlen += strlen(line->line); + } + return cstr; +} + +/* Pass -1 for expect_min or expect_exact to not check that value. + * expect_empty_p means an empty line is expected at some point in the string. + * Also ensures that the string was not too wide after wrapping. */ +static int mlstring_expect_lines(const mlstring *mlstr, int expect_min, int expect_exact, Bool expect_empty_p) +{ + int count; + Bool got_empty_line = False; + const struct mlstr_line *line = mlstr->lines; + + for (count = 0; line; line = line->next_line) { + if (line->line[0] == '\0') { + if (!expect_empty_p) + FAIL("Not expecting empty lines, but got one on line %d of [%s]", count + 1, mlstring_to_cstr(mlstr)); + got_empty_line = True; + } + ++count; + } + + if (expect_empty_p && !got_empty_line) + FAIL("Expecting an empty line, but none found in [%s]", mlstring_to_cstr(mlstr)); + + if (expect_exact != -1 && expect_exact != count) + FAIL("Expected %d lines, got %d", expect_exact, count); + + if (expect_min != -1 && count < expect_min) + FAIL("Expected at least %d lines, got %d", expect_min, count); + + return SUCCESS; +} + +static int mlstring_expect(const char *msg, int expect_lines, const mlstring *mlstr, Bool expect_empty_p) +{ + char *str, *str_top; + const struct mlstr_line *cur; + int linecount = 0; + + /* Duplicate msg so we can chop it up */ + str_top = strdup(msg); + if (!str_top) + return SKIPPED; + + /* Replace all newlines with NUL */ + str = str_top; + while ((str = strchr(str, '\n'))) + *str++ = '\0'; + + /* str is now used to point to the expected string */ + str = str_top; + + for (cur = mlstr->lines; cur; cur = cur->next_line) + { + ++linecount; + if (strcmp(cur->line, str)) + FAIL("lines didn't match; expected [%s], got [%s]", str, cur->line); + + str += strlen(str) + 1; /* Point to the next expected string */ + } + + free(str_top); + + return mlstring_expect_lines(mlstr, -1, expect_lines, expect_empty_p); +} + +/* Ensures that the width has been set properly after wrapping */ +static int check_width(const char *msg, const mlstring *mlstr) { + if (mlstr->overall_width == 0) + FAIL("Overall width was zero for string [%s]", msg); + + if (mlstr->overall_width > WRAP_WIDTH_PX) + FAIL("Overall width was %hu but the maximum wrap width was %d", mlstr->overall_width, WRAP_WIDTH_PX); + + return SUCCESS; +} + +/* FAIL() actually returns the wrong return codes in main, but it + * prints a message which is what we want. */ + +#define TRY_NEW(str, numl, expect_empty) \ + do { \ + mlstr = mlstring_allocate((str)); \ + if (!mlstr) \ + FAIL("%s", #str); \ + if (SUCCESS == mlstring_expect((str), (numl), mlstr, (expect_empty))) \ + SUCCEED(#str); \ + free(mlstr); \ + } while (0) + +/* Expects an XFontStruct* font, and tries to wrap to 100px */ +#define TRY_WRAP(str, minl, expect_empty) \ + do { \ + mltest = mlstring_allocate((str)); \ + if (!mltest) \ + SKIP(#str); \ + else { \ + mlstring_wrap(mltest, font, WRAP_WIDTH_PX); \ + check_width((str), mltest); \ + if (SUCCESS == mlstring_expect_lines(mltest, (minl), -1, (expect_empty))) \ + SUCCEED(#str); \ + free(mltest); \ + mltest = NULL; \ + } \ + } while (0) + + +/* Ideally this function would use stub functions rather than real Xlib. + * Then it would be possible to test for exact line counts, which would be + * more reliable. + * It also doesn't handle Xlib errors. + * + * Don't print anything based on the return value of this function, it only + * returns a value so that I can use the FAIL() macro without warning. + * + * Anyone who understands this function wins a cookie ;) + */ +static int test_wrapping(void) +{ + Display *dpy = NULL; + XFontStruct *font = NULL; + mlstring *mltest = NULL; + int ok = 0; + int chars_per_line, chars_first_word, i; + + const char *test_short = "a"; + const char *test_hardwrap = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" + "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" + "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"; + const char *test_withnewlines = "a\nb"; + char *test_softwrap = NULL; + + dpy = XOpenDisplay(NULL); + if (!dpy) + goto end; + + font = XLoadQueryFont(dpy, "fixed"); + if (!font) + goto end; + + TRY_WRAP(test_short, 1, False); + TRY_WRAP(test_hardwrap, 2, False); + TRY_WRAP(test_withnewlines, 2, False); + + /* See if wrapping splits on word boundaries like it should */ + chars_per_line = WRAP_WIDTH_PX / font->max_bounds.width; + if (chars_per_line < 3) + goto end; + + /* Allocate for 2 lines + \0 */ + test_softwrap = malloc(chars_per_line * 2 + 1); + if (!test_softwrap) + goto end; + + /* 2 = strlen(' a'); that is, the minimum space required to start a new word + * on the same line. */ + chars_first_word = chars_per_line - 2; + + for (i = 0; i < chars_first_word; ++i) { + test_softwrap[i] = 'a'; /* first word */ + test_softwrap[i + chars_per_line] = 'b'; /* second word */ + } + /* space between first & second words */ + test_softwrap[chars_first_word] = ' '; + /* first char of second word (last char of first line) */ + test_softwrap[chars_first_word + 1] = 'b'; + /* after second word */ + test_softwrap[chars_per_line * 2] = '\0'; + + mltest = mlstring_allocate(test_softwrap); + mlstring_wrap(mltest, font, WRAP_WIDTH_PX); + + /* reusing 'i' for a moment here to make freeing mltest easier */ + i = strlen(mltest->lines->line); + free(mltest); + + if (i != chars_first_word) + FAIL("Soft wrap failed, expected the first line to be %d chars, but it was %d.", chars_first_word, i); + SUCCEED("Soft wrap"); + + ok = 1; + +end: + if (test_softwrap) + free(test_softwrap); + + if (font) + XFreeFont(dpy, font); + + if (dpy) + XCloseDisplay(dpy); + + if (!ok) + SKIP("wrapping"); + + return ok ? SUCCESS : SKIPPED; /* Unused, actually */ +} + + +int main(int argc, char *argv[]) +{ + const char *oneline = "1Foo"; + const char *twolines = "2Foo\nBar"; + const char *threelines = "3Foo\nBar\nWhippet"; + const char *trailnewline = "4Foo\n"; + const char *trailnewlines = "5Foo\n\n"; + const char *embeddednewlines = "6Foo\n\nBar"; + mlstring *mlstr; + + TRY_NEW(oneline, 1, False); + TRY_NEW(twolines, 2, False); + TRY_NEW(threelines, 3, False); + TRY_NEW(trailnewline, 2, True); + TRY_NEW(trailnewlines, 3, True); + TRY_NEW(embeddednewlines, 3, True); + + (void) test_wrapping(); + + fprintf(stdout, "%d test failures.\n", failcount); + + return !!failcount; +} + +/* vim:ts=8:sw=2:noet + */ diff --git a/driver/test-passwd.c b/driver/test-passwd.c new file mode 100644 index 00000000..6563bd8d --- /dev/null +++ b/driver/test-passwd.c @@ -0,0 +1,303 @@ +/* xscreensaver, Copyright (c) 1998-2011 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. + */ + +/* This is a kludgy test harness for debugging the password dialog box. + It's somewhat easier to debug it here than in the xscreensaver executable + itself. + */ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#include "xscreensaver.h" +#include "resources.h" +#include "version.h" +#include "visual.h" +#include "auth.h" + +char *progname = 0; +char *progclass = 0; +XrmDatabase db = 0; +saver_info *global_si_kludge; + +FILE *real_stderr, *real_stdout; + +void monitor_power_on (saver_info *si, Bool on_p) {} +Bool monitor_powered_on_p (saver_info *si) { return True; } +void initialize_screensaver_window (saver_info *si) {} +void raise_window (saver_info *si, Bool i, Bool b, Bool d) {} +Bool blank_screen (saver_info *si) {return False;} +void unblank_screen (saver_info *si) {} +Bool select_visual (saver_screen_info *ssi, const char *v) { return False; } +Bool window_exists_p (Display *dpy, Window window) {return True;} +void start_notice_events_timer (saver_info *si, Window w, Bool b) {} +Bool handle_clientmessage (saver_info *si, XEvent *e, Bool u) { return False; } +int BadWindow_ehandler (Display *dpy, XErrorEvent *error) { exit(1); } +const char *signal_name(int signal) { return "???"; } +Bool restore_real_vroot (saver_info *si) { return False; } +void store_saver_status (saver_info *si) {} +void saver_exit (saver_info *si, int status, const char *core) { exit(status);} +int move_mouse_grab (saver_info *si, Window to, Cursor c, int ts) { return 0; } +int mouse_screen (saver_info *si) { return 0; } +void check_for_leaks (const char *where) { } +void shutdown_stderr (saver_info *si) { } +void resize_screensaver_window (saver_info *si) { } +void describe_monitor_layout (saver_info *si) { } +Bool update_screen_layout (saver_info *si) { return 0; } + +const char *blurb(void) { return progname; } +Atom XA_SCREENSAVER, XA_DEMO, XA_PREFS; + +void +idle_timer (XtPointer closure, XtIntervalId *id) +{ + saver_info *si = (saver_info *) closure; + XEvent fake_event; + fake_event.type = 0; /* XAnyEvent type, ignored. */ + fake_event.xany.display = si->dpy; + fake_event.xany.window = 0; + XPutBackEvent (si->dpy, &fake_event); +} + + +static int +text_auth_conv ( + int num_msg, + const struct auth_message *auth_msgs, + struct auth_response **resp, + saver_info *si) +{ + char *input; + char buf[255]; + struct auth_response *responses; + int i; + + responses = calloc(num_msg, sizeof(struct auth_response)); + if (!responses) + return -1; + + /* The unlock state won't actually be used until this function returns and + * the auth module processes the response, but set it anyway for consistency + */ + si->unlock_state = ul_read; + + for (i = 0; i < num_msg; ++i) + { + printf ("\n%s: %s", progname, auth_msgs[i].msg); + if ( auth_msgs[i].type == AUTH_MSGTYPE_PROMPT_NOECHO + || auth_msgs[i].type == AUTH_MSGTYPE_PROMPT_ECHO) + { + input = fgets (buf, sizeof(buf)-1, stdin); + if (!input || !*input) + exit (0); + if (input[strlen(input)-1] == '\n') + input[strlen(input)-1] = 0; + + responses[i].response = strdup(input); + } + } + + *resp = responses; + + si->unlock_state = ul_finished; + + return 0; +} + + +#ifdef __GNUC__ + __extension__ /* shut up about "string length is greater than the length + ISO C89 compilers are required to support" when including + the .ad file... */ +#endif + +static char *fallback[] = { +#include "XScreenSaver_ad.h" + 0 +}; + +extern Bool debug_passwd_window_p; /* lock.c kludge */ + +int +main (int argc, char **argv) +{ + enum { PASS, SPLASH, TTY } which; + Widget toplevel_shell = 0; + saver_screen_info ssip; + saver_info sip; + saver_info *si = &sip; + saver_preferences *p = &si->prefs; + struct passwd *pw; + + memset(&sip, 0, sizeof(sip)); + memset(&ssip, 0, sizeof(ssip)); + + si->nscreens = 1; + si->screens = si->default_screen = &ssip; + ssip.global = si; + + global_si_kludge = si; + real_stderr = stderr; + real_stdout = stdout; + + si->version = (char *) malloc (5); + memcpy (si->version, screensaver_id + 17, 4); + progname = argv[0]; + { + char *s = strrchr(progname, '/'); + if (*s) strcpy (progname, s+1); + } + + if (argc != 2) goto USAGE; + else if (!strcmp (argv[1], "pass")) which = PASS; + else if (!strcmp (argv[1], "splash")) which = SPLASH; + else if (!strcmp (argv[1], "tty")) which = TTY; + else + { + USAGE: + fprintf (stderr, "usage: %s [ pass | splash | tty ]\n", progname); + exit (1); + } + +#ifdef NO_LOCKING + if (which == PASS || which == TTY) + { + fprintf (stderr, "%s: compiled with NO_LOCKING\n", progname); + exit (1); + } +#endif + +#ifndef NO_LOCKING + /* before hack_uid() for proper permissions */ + lock_priv_init (argc, argv, True); + + hack_uid (si); + + if (! lock_init (argc, argv, True)) + { + si->locking_disabled_p = True; + si->nolock_reason = "error getting password"; + } +#endif + + progclass = "XScreenSaver"; + + if (!setlocale (LC_CTYPE, "")) + fprintf (stderr, "%s: warning: could not set default locale\n", + progname); + + + if (which != TTY) + { + toplevel_shell = XtAppInitialize (&si->app, progclass, 0, 0, + &argc, argv, fallback, + 0, 0); + + si->dpy = XtDisplay (toplevel_shell); + p->db = XtDatabase (si->dpy); + si->default_screen->toplevel_shell = toplevel_shell; + si->default_screen->screen = XtScreen(toplevel_shell); + si->default_screen->default_visual = + si->default_screen->current_visual = + DefaultVisualOfScreen(si->default_screen->screen); + si->default_screen->screensaver_window = + RootWindowOfScreen(si->default_screen->screen); + si->default_screen->current_depth = + visual_depth(si->default_screen->screen, + si->default_screen->current_visual); + + ssip.width = WidthOfScreen(ssip.screen); + ssip.height = HeightOfScreen(ssip.screen); + + db = p->db; + XtGetApplicationNameAndClass (si->dpy, &progname, &progclass); + + load_init_file (si->dpy, &si->prefs); + } + + p->verbose_p = True; + + pw = getpwuid (getuid ()); + si->user = strdup (pw->pw_name); + +/* si->nscreens = 0; + si->screens = si->default_screen = 0; */ + + while (1) + { +#ifndef NO_LOCKING + if (which == PASS) + { + si->unlock_cb = gui_auth_conv; + si->auth_finished_cb = auth_finished_cb; + + debug_passwd_window_p = True; + xss_authenticate(si, True); + + if (si->unlock_state == ul_success) + fprintf (stderr, "%s: authentication succeeded\n", progname); + else + fprintf (stderr, "%s: authentication FAILED!\n", progname); + + XSync(si->dpy, False); + fprintf (stderr, "\n######################################\n\n"); + sleep (3); + } + else +#endif + if (which == SPLASH) + { + XEvent event; + make_splash_dialog (si); + XtAppAddTimeOut (si->app, p->splash_duration + 1000, + idle_timer, (XtPointer) si); + while (si->splash_dialog) + { + XtAppNextEvent (si->app, &event); + if (event.xany.window == si->splash_dialog) + handle_splash_event (si, &event); + XtDispatchEvent (&event); + } + XSync (si->dpy, False); + sleep (1); + } +#ifndef NO_LOCKING + else if (which == TTY) + { + si->unlock_cb = text_auth_conv; + + printf ("%s: Authenticating user %s\n", progname, si->user); + xss_authenticate(si, True); + + if (si->unlock_state == ul_success) + printf ("%s: Ok!\n", progname); + else + printf ("%s: Wrong!\n", progname); + } +#endif + else + abort(); + } + + free(si->user); +} diff --git a/driver/test-randr.c b/driver/test-randr.c new file mode 100644 index 00000000..74ead37f --- /dev/null +++ b/driver/test-randr.c @@ -0,0 +1,339 @@ +/* test-randr.c --- playing with the Resize And Rotate extension. + * xscreensaver, Copyright (c) 2004-2008 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. + */ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include +#ifdef HAVE_UNISTD_H +# include +#endif + +#include +#include +#include + +#include +#include +#include + +#include +#include + +char *progname = 0; +char *progclass = "XScreenSaver"; + +static const char * +blurb (void) +{ + static char buf[255]; + time_t now = time ((time_t *) 0); + char *ct = (char *) ctime (&now); + int n = strlen(progname); + if (n > 100) n = 99; + strncpy(buf, progname, n); + buf[n++] = ':'; + buf[n++] = ' '; + strncpy(buf+n, ct+11, 8); + strcpy(buf+n+9, ": "); + return buf; +} + + +static Bool error_handler_hit_p = False; + +static int +ignore_all_errors_ehandler (Display *dpy, XErrorEvent *error) +{ + error_handler_hit_p = True; + return 0; +} + + +int +main (int argc, char **argv) +{ + int event_number = -1, error_number = -1; + int major = -1, minor = -1; + int nscreens = 0; + int i; + + XtAppContext app; + Widget toplevel_shell = XtAppInitialize (&app, progclass, 0, 0, + &argc, argv, 0, 0, 0); + Display *dpy = XtDisplay (toplevel_shell); + XtGetApplicationNameAndClass (dpy, &progname, &progclass); + + nscreens = ScreenCount(dpy); + + if (!XRRQueryExtension(dpy, &event_number, &error_number)) + { + fprintf(stderr, "%s: XRRQueryExtension(dpy, ...) ==> False\n", + blurb()); + fprintf(stderr, "%s: server does not support the RANDR extension.\n", + blurb()); + major = -1; + } + else + { + fprintf(stderr, "%s: XRRQueryExtension(dpy, ...) ==> %d, %d\n", + blurb(), event_number, error_number); + + if (!XRRQueryVersion(dpy, &major, &minor)) + { + fprintf(stderr, "%s: XRRQueryVersion(dpy, ...) ==> False\n", + blurb()); + fprintf(stderr, "%s: server didn't report RANDR version numbers?\n", + blurb()); + } + else + fprintf(stderr, "%s: XRRQueryVersion(dpy, ...) ==> %d, %d\n", blurb(), + major, minor); + } + + for (i = 0; i < nscreens; i++) + { + XRRScreenConfiguration *rrc; + XErrorHandler old_handler; + + XSync (dpy, False); + error_handler_hit_p = False; + old_handler = XSetErrorHandler (ignore_all_errors_ehandler); + + rrc = (major >= 0 ? XRRGetScreenInfo (dpy, RootWindow (dpy, i)) : 0); + + XSync (dpy, False); + XSetErrorHandler (old_handler); + XSync (dpy, False); + + if (error_handler_hit_p) + { + fprintf(stderr, "%s: XRRGetScreenInfo(dpy, %d) ==> X error:\n", + blurb(), i); + /* do it again without the error handler to print the error */ + rrc = XRRGetScreenInfo (dpy, RootWindow (dpy, i)); + } + else if (rrc) + { + SizeID current_size = -1; + Rotation current_rotation = ~0; + + fprintf (stderr, "\n%s: Screen %d\n", blurb(), i); + + current_size = + XRRConfigCurrentConfiguration (rrc, ¤t_rotation); + + /* Times */ +# if 0 /* #### This is wrong -- I don't understand what these two + timestamp numbers represent, or how they correlate + to the wall clock or to each other. */ + { + Time server_time, config_time; + server_time = XRRConfigTimes (rrc, &config_time); + if (config_time == 0 || server_time == 0) + fprintf (stderr, "%s: config has never been changed\n", + blurb()); + else + fprintf (stderr, "%s: config changed %lu seconds ago\n", + blurb(), (unsigned long) (server_time - config_time)); + } +# endif + + /* Rotations */ + { + Rotation available, current; + available = XRRConfigRotations (rrc, ¤t); + + fprintf (stderr, "%s: Available Rotations:\t", blurb()); + if (available & RR_Rotate_0) fprintf (stderr, " 0"); + if (available & RR_Rotate_90) fprintf (stderr, " 90"); + if (available & RR_Rotate_180) fprintf (stderr, " 180"); + if (available & RR_Rotate_270) fprintf (stderr, " 270"); + if (! (available & (RR_Rotate_0 | RR_Rotate_90 | + RR_Rotate_180 | RR_Rotate_270))) + fprintf (stderr, " none"); + fprintf (stderr, "\n"); + + if (current_rotation != current) + fprintf (stderr, + "%s: WARNING: rotation inconsistency: 0x%X vs 0x%X\n", + blurb(), current_rotation, current); + + fprintf (stderr, "%s: Current Rotation:\t", blurb()); + if (current & RR_Rotate_0) fprintf (stderr, " 0"); + if (current & RR_Rotate_90) fprintf (stderr, " 90"); + if (current & RR_Rotate_180) fprintf (stderr, " 180"); + if (current & RR_Rotate_270) fprintf (stderr, " 270"); + if (! (current & (RR_Rotate_0 | RR_Rotate_90 | + RR_Rotate_180 | RR_Rotate_270))) + fprintf (stderr, " none"); + fprintf (stderr, "\n"); + + fprintf (stderr, "%s: Available Reflections:\t", blurb()); + if (available & RR_Reflect_X) fprintf (stderr, " X"); + if (available & RR_Reflect_Y) fprintf (stderr, " Y"); + if (! (available & (RR_Reflect_X | RR_Reflect_Y))) + fprintf (stderr, " none"); + fprintf (stderr, "\n"); + + fprintf (stderr, "%s: Current Reflections:\t", blurb()); + if (current & RR_Reflect_X) fprintf (stderr, " X"); + if (current & RR_Reflect_Y) fprintf (stderr, " Y"); + if (! (current & (RR_Reflect_X | RR_Reflect_Y))) + fprintf (stderr, " none"); + fprintf (stderr, "\n"); + } + + /* Sizes */ + { + int nsizes, j; + XRRScreenSize *rrsizes; + + rrsizes = XRRConfigSizes (rrc, &nsizes); + if (nsizes <= 0) + fprintf (stderr, "%s: sizes:\t none\n", blurb()); + else + for (j = 0; j < nsizes; j++) + { + short *rates; + int nrates, k; + fprintf (stderr, + "%s: %c size %d: %d x %d\t rates:", + blurb(), + (j == current_size ? '+' : ' '), + j, + rrsizes[j].width, rrsizes[j].height); + + rates = XRRConfigRates (rrc, j, &nrates); + if (nrates == 0) + fprintf (stderr, " none?"); + else + for (k = 0; k < nrates; k++) + fprintf (stderr, " %d", rates[k]); + fprintf (stderr, "\n"); + /* don't free 'rates' */ + } + /* don't free 'rrsizes' */ + } + + XRRFreeScreenConfigInfo (rrc); + } + else if (major >= 0) + { + fprintf(stderr, "%s: XRRGetScreenInfo(dpy, %d) ==> NULL\n", + blurb(), i); + } + + +# ifdef HAVE_RANDR_12 + if (major > 1 || (major == 1 && minor >= 2)) + { + int j; + XRRScreenResources *res = + XRRGetScreenResources (dpy, RootWindow (dpy, i)); + fprintf (stderr, "\n"); + for (j = 0; j < res->noutput; j++) + { + int k; + XRROutputInfo *rroi = + XRRGetOutputInfo (dpy, res, res->outputs[j]); + fprintf (stderr, "%s: Output %d: %s: %s (%d)\n", blurb(), j, + rroi->name, + (rroi->connection == RR_Disconnected ? "disconnected" : + rroi->connection == RR_UnknownConnection ? "unknown" : + "connected"), + (int) rroi->crtc); + for (k = 0; k < rroi->ncrtc; k++) + { + XRRCrtcInfo *crtci = XRRGetCrtcInfo (dpy, res, + rroi->crtcs[k]); + fprintf(stderr, "%s: %c CRTC %d (%d): %dx%d+%d+%d\n", + blurb(), + (rroi->crtc == rroi->crtcs[k] ? '+' : ' '), + k, (int) rroi->crtcs[k], + crtci->width, crtci->height, crtci->x, crtci->y); + XRRFreeCrtcInfo (crtci); + } + XRRFreeOutputInfo (rroi); + fprintf (stderr, "\n"); + } + XRRFreeScreenResources (res); + } +# endif /* HAVE_RANDR_12 */ + } + + if (major > 0) + { + Window w[20]; + XWindowAttributes xgwa[20]; + + for (i = 0; i < nscreens; i++) + { + XRRSelectInput (dpy, RootWindow (dpy, i), RRScreenChangeNotifyMask); + w[i] = RootWindow (dpy, i); + XGetWindowAttributes (dpy, w[i], &xgwa[i]); + } + + XSync (dpy, False); + + fprintf (stderr, "\n%s: awaiting events...\n\n" + "\t(If you resize the screen or add/remove monitors, this should\n" + "\tnotice that and print stuff. Otherwise, hit ^C.)\n\n", + progname); + while (1) + { + XEvent event; + XNextEvent (dpy, &event); + + if (event.type == event_number + RRScreenChangeNotify) + { + XRRScreenChangeNotifyEvent *xrr_event = + (XRRScreenChangeNotifyEvent *) &event; + int screen = XRRRootToScreen (dpy, xrr_event->window); + + fprintf (stderr, "%s: screen %d: RRScreenChangeNotify event\n", + progname, screen); + + fprintf (stderr, "%s: screen %d: old size: \t%d x %d\n", + progname, screen, + DisplayWidth (dpy, screen), + DisplayHeight (dpy, screen)); + fprintf (stderr, "%s: screen %d: old root 0x%lx:\t%d x %d\n", + progname, screen, (unsigned long) w[screen], + xgwa[screen].width, xgwa[screen].height); + + XRRUpdateConfiguration (&event); + XSync (dpy, False); + + fprintf (stderr, "%s: screen %d: new size: \t%d x %d\n", + progname, screen, + DisplayWidth (dpy, screen), + DisplayHeight (dpy, screen)); + + w[screen] = RootWindow (dpy, screen); + XGetWindowAttributes (dpy, w[screen], &xgwa[screen]); + fprintf (stderr, "%s: screen %d: new root 0x%lx:\t%d x %d\n", + progname, screen, (unsigned long) w[screen], + xgwa[screen].width, xgwa[screen].height); + fprintf (stderr, "\n"); + } + else + { + fprintf (stderr, "%s: event %d\n", progname, event.type); + } + } + } + + XSync (dpy, False); + exit (0); +} diff --git a/driver/test-screens.c b/driver/test-screens.c new file mode 100644 index 00000000..2fb3e35d --- /dev/null +++ b/driver/test-screens.c @@ -0,0 +1,208 @@ +/* test-screens.c --- some test cases for the "monitor sanity" checks. + * xscreensaver, Copyright (c) 2008 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. + */ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include + +/* This file doesn't need the Xt headers, so stub these types out... */ +#undef XtPointer +#define XtAppContext void* +#define XrmDatabase void* +#define XtIntervalId void* +#define XtPointer void* +#define Widget void* + +#include "xscreensaver.h" +#include "visual.h" + +#undef WidthOfScreen +#undef HeightOfScreen +#define WidthOfScreen(s) 10240 +#define HeightOfScreen(s) 10240 + +#undef screen_number +#define screen_number(s) ((int) s) + +#include "screens.c" /* to get at static void check_monitor_sanity() */ + +char *progname = 0; +char *progclass = "XScreenSaver"; + +const char *blurb(void) { return progname; } + +Bool safe_XF86VidModeGetViewPort(Display *d, int i, int *x, int *y) { abort(); } +void initialize_screen_root_widget(saver_screen_info *ssi) { abort(); } +Visual *get_best_gl_visual (saver_info *si, Screen *sc) { abort(); } + + +static const char * +failstr (monitor_sanity san) +{ + switch (san) { + case S_SANE: return "OK"; + case S_ENCLOSED: return "ENC"; + case S_DUPLICATE: return "DUP"; + case S_OVERLAP: return "OVR"; + case S_OFFSCREEN: return "OFF"; + case S_DISABLED: return "DIS"; + default: abort(); break; + } +} + + +static void +test (int testnum, const char *screens, const char *desired) +{ + monitor *monitors[100]; + char result[2048]; + char *out = result; + int i, nscreens = 0; + char *token = strtok (strdup(screens), ","); + while (token) + { + monitor *m = calloc (1, sizeof (monitor)); + char c; + m->id = (testnum * 1000) + nscreens; + if (5 == sscanf (token, "%dx%d+%d+%d@%d%c", + &m->width, &m->height, &m->x, &m->y, + (int *) &m->screen, &c)) + ; + else if (4 != sscanf (token, "%dx%d+%d+%d%c", + &m->width, &m->height, &m->x, &m->y, &c)) + { + fprintf (stderr, "%s: unparsable geometry: %s\n", blurb(), token); + exit (1); + } + monitors[nscreens] = m; + nscreens++; + token = strtok (0, ","); + } + monitors[nscreens] = 0; + + check_monitor_sanity (monitors); + + *out = 0; + for (i = 0; i < nscreens; i++) + { + monitor *m = monitors[i]; + if (out != result) *out++ = ','; + if (m->sanity == S_SANE) + { + sprintf (out, "%dx%d+%d+%d", m->width, m->height, m->x, m->y); + if (m->screen) + sprintf (out + strlen(out), "@%d", (int) m->screen); + } + else + strcpy (out, failstr (m->sanity)); + out += strlen(out); + } + *out = 0; + + if (!strcmp (result, desired)) + fprintf (stderr, "%s: test %2d OK\n", blurb(), testnum); + else + fprintf (stderr, "%s: test %2d FAILED:\n" + "%s: given: %s\n" + "%s: wanted: %s\n" + "%s: got: %s\n", + blurb(), testnum, + blurb(), screens, + blurb(), desired, + blurb(), result); + +# if 0 + { + saver_info SI; + SI.monitor_layout = monitors; + describe_monitor_layout (&SI); + } +# endif + +} + +static void +run_tests(void) +{ + int i = 1; +# define A(a) test (i++, a, a); +# define B(a,b) test (i++, a, b) + + A(""); + A("1024x768+0+0"); + A("1024x768+0+0,1024x768+1024+0"); + A("1024x768+0+0,1024x768+0+768"); + A("1024x768+0+0,1024x768+0+768,1024x768+1024+0"); + A("800x600+0+0,800x600+0+0@1,800x600+10+0@2"); + + B("1024x768+999999+0", + "OFF"); + B("1024x768+-999999+-999999", + "OFF"); + B("1024x768+0+0,1024x768+0+0", + "1024x768+0+0,DUP"); + B("1024x768+0+0,1024x768+0+0,1024x768+0+0", + "1024x768+0+0,DUP,DUP"); + B("1024x768+0+0,1024x768+1024+0,1024x768+0+0", + "1024x768+0+0,1024x768+1024+0,DUP"); + B("1280x1024+0+0,1024x768+0+64,800x600+0+0,640x480+0+0,720x400+0+0", + "1280x1024+0+0,ENC,ENC,ENC,ENC"); + B("1024x768+0+64,1280x1024+0+0,800x600+0+0,640x480+0+0,800x600+0+0,720x400+0+0", + "ENC,1280x1024+0+0,ENC,ENC,ENC,ENC"); + B("1024x768+0+64,1280x1024+0+0,800x600+0+0,640x480+0+0,1280x1024+0+0,720x400+0+0", + "ENC,1280x1024+0+0,ENC,ENC,DUP,ENC"); + B("720x400+0+0,640x480+0+0,800x600+0+0,1024x768+0+64,1280x1024+0+0", + "ENC,ENC,ENC,ENC,1280x1024+0+0"); + B("1280x1024+0+0,800x600+1280+0,800x600+1300+0", + "1280x1024+0+0,800x600+1280+0,OVR"); + B("1280x1024+0+0,800x600+1280+0,800x600+1300+0,1280x1024+0+0,800x600+1280+0", + "1280x1024+0+0,800x600+1280+0,OVR,DUP,DUP"); + + /* +-------------+----+ +------+---+ 1: 1440x900, widescreen display + | : | | 3+4 : | 2: 1280x1024, conventional display + | 1+2 : 1 | +......+ | 3: 1024x768, laptop + | : | | 3 | 4: 800x600, external projector + +.............+----+ +----------+ + | 2 | + | | + +-------------+ + */ + B("1440x900+0+0,1280x1024+0+0,1024x768+1440+0,800x600+1440+0", + "1440x900+0+0,OVR,1024x768+1440+0,ENC"); + B("800x600+0+0,800x600+0+0,800x600+800+0", + "800x600+0+0,DUP,800x600+800+0"); + B("1600x1200+0+0,1360x768+0+0", + "1600x1200+0+0,ENC"); + B("1600x1200+0+0,1360x768+0+0,1600x1200+0+0@1,1360x768+0+0@1", + "1600x1200+0+0,ENC,1600x1200+0+0@1,ENC"); +} + + +int +main (int argc, char **argv) +{ + char *s; + progname = argv[0]; + s = strrchr(progname, '/'); + if (s) progname = s+1; + if (argc != 1) + { + fprintf (stderr, "usage: %s\n", argv[0]); + exit (1); + } + + run_tests(); + + exit (0); +} diff --git a/driver/test-uid.c b/driver/test-uid.c new file mode 100644 index 00000000..6a1f9cc1 --- /dev/null +++ b/driver/test-uid.c @@ -0,0 +1,209 @@ +/* test-uid.c --- playing with setuid. + * xscreensaver, Copyright (c) 1998, 2005 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. + */ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include +#ifdef HAVE_UNISTD_H +# include +#endif + +#include +#include +#include +#include +#include +#include +#include + +static void +print(void) +{ + int uid = getuid(); + int gid = getgid(); + int euid = geteuid(); + int egid = getegid(); + struct passwd *p = 0; + struct group *g = 0; + gid_t groups[1024]; + int n, size; + + p = getpwuid (uid); + g = getgrgid (gid); + fprintf(stderr, "real user/group: %ld/%ld (%s/%s)\n", (long) uid, (long) gid, + (p && p->pw_name ? p->pw_name : "???"), + (g && g->gr_name ? g->gr_name : "???")); + + p = getpwuid (euid); + g = getgrgid (egid); + fprintf(stderr, "eff. user/group: %ld/%ld (%s/%s)\n", (long)euid, (long)egid, + (p && p->pw_name ? p->pw_name : "???"), + (g && g->gr_name ? g->gr_name : "???")); + + size = sizeof(groups) / sizeof(gid_t); + n = getgroups(size - 1, groups); + if (n < 0) + perror("getgroups failed"); + else + { + int i; + fprintf (stderr, "eff. group list: ["); + for (i = 0; i < n; i++) + { + g = getgrgid (groups[i]); + fprintf(stderr, "%s%s=%ld", (i == 0 ? "" : ", "), + (g->gr_name ? g->gr_name : "???"), + (long) groups[i]); + } + fprintf (stderr, "]\n"); + } +} + +int +main (int argc, char **argv) +{ + int i; + struct passwd *p = 0; + struct group *g = 0; + + if (argc <= 1) + { + fprintf(stderr, + "usage: %s [ user/group ... ]\n" + "\tEach argument may be a user name, or user/group.\n" + "\tThis program will attempt to setuid/setgid to each\n" + "\tin turn, and report the results. The user and group\n" + "\tnames may be strings, or numeric.\n", + argv[0]); + exit(1); + } + + print(); + for (i = 1; i < argc; i++) + { + char *user = argv[i]; + char *group = strchr(user, '/'); + if (!group) + group = strchr(user, '.'); + if (group) + *group++ = 0; + + if (group && *group) + { + long gid = 0; + int was_numeric = 0; + + g = 0; + if (*group == '-' || (*group >= '0' && *group <= '9')) + if (1 == sscanf(group, "%ld", &gid)) + { + g = getgrgid (gid); + was_numeric = 1; + } + + if (!g) + g = getgrnam(group); + + if (g) + { + gid = g->gr_gid; + group = g->gr_name; + } + else + { + if (was_numeric) + { + fprintf(stderr, "no group numbered %s.\n", group); + group = ""; + } + else + { + fprintf(stderr, "no group named %s.\n", group); + goto NOGROUP; + } + } + + fprintf(stderr, "setgroups(1, [%ld]) \"%s\"", gid, group); + { + gid_t g2 = gid; + if (setgroups(1, &g2) == 0) + fprintf(stderr, " succeeded.\n"); + else + perror(" failed"); + } + + fprintf(stderr, "setgid(%ld) \"%s\"", gid, group); + if (setgid(gid) == 0) + fprintf(stderr, " succeeded.\n"); + else + perror(" failed"); + + NOGROUP: ; + } + + if (user && *user) + { + long uid = 0; + int was_numeric = 0; + + p = 0; + if (*user == '-' || (*user >= '0' && *user <= '9')) + if (1 == sscanf(user, "%ld", &uid)) + { + p = getpwuid (uid); + was_numeric = 1; + } + + if (!p) + p = getpwnam(user); + + if (p) + { + uid = p->pw_uid; + user = p->pw_name; + } + else + { + if (was_numeric) + { + fprintf(stderr, "no user numbered \"%s\".\n", user); + user = ""; + } + else + { + fprintf(stderr, "no user named %s.\n", user); + goto NOUSER; + } + } + + fprintf(stderr, "setuid(%ld) \"%s\"", uid, user); + if (setuid(uid) == 0) + fprintf(stderr, " succeeded.\n"); + else + perror(" failed"); + NOUSER: ; + } + print(); + } + + fprintf(stderr, + "running \"whoami\" and \"groups\" in a sub-process reports:\n"); + fflush(stdout); + fflush(stderr); + system ("/bin/sh -c 'echo \"`whoami` / `groups`\"'"); + + fflush(stdout); + fflush(stderr); + exit(0); +} diff --git a/driver/test-vp.c b/driver/test-vp.c new file mode 100644 index 00000000..bf1a0b18 --- /dev/null +++ b/driver/test-vp.c @@ -0,0 +1,213 @@ +/* test-xinerama.c --- playing with XF86VidModeGetViewPort + * xscreensaver, Copyright (c) 2004 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. + */ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include +#ifdef HAVE_UNISTD_H +# include +#endif + +#include +#include +#include + +#include +#include +#include + +#include +#include +#include + +char *progname = 0; +char *progclass = "XScreenSaver"; + +static const char * +blurb (void) +{ + static char buf[255]; + time_t now = time ((time_t *) 0); + char *ct = (char *) ctime (&now); + int n = strlen(progname); + if (n > 100) n = 99; + strncpy(buf, progname, n); + buf[n++] = ':'; + buf[n++] = ' '; + strncpy(buf+n, ct+11, 8); + strcpy(buf+n+9, ": "); + return buf; +} + + +static Bool error_handler_hit_p = False; + +static int +ignore_all_errors_ehandler (Display *dpy, XErrorEvent *error) +{ + error_handler_hit_p = True; + return 0; +} + + +static int +screen_count (Display *dpy) +{ + int n = ScreenCount(dpy); + int xn = 0; + int event_number, error_number; + + if (!XineramaQueryExtension (dpy, &event_number, &error_number)) + { + fprintf(stderr, "%s: XineramaQueryExtension(dpy, ...) ==> False\n", + blurb()); + goto DONE; + } + else + fprintf(stderr, "%s: XineramaQueryExtension(dpy, ...) ==> %d, %d\n", + blurb(), event_number, error_number); + + if (!XineramaIsActive(dpy)) + { + fprintf(stderr, "%s: XineramaIsActive(dpy) ==> False\n", + blurb()); + goto DONE; + } + else + { + int major, minor; + XineramaScreenInfo *xsi; + fprintf(stderr, "%s: XineramaIsActive(dpy) ==> True\n", + blurb()); + if (!XineramaQueryVersion(dpy, &major, &minor)) + { + fprintf(stderr, + "%s: XineramaQueryVersion(dpy, ...) ==> False\n", + blurb()); + goto DONE; + } + else + fprintf(stderr, + "%s: XineramaQueryVersion(dpy, ...) ==> %d, %d\n", + blurb(), major, minor); + + xsi = XineramaQueryScreens (dpy, &xn); + if (xsi) XFree (xsi); + } + + DONE: + fprintf (stderr, "\n"); + fprintf (stderr, "%s: X client screens: %d\n", blurb(), n); + fprintf (stderr, "%s: Xinerama screens: %d\n", blurb(), xn); + fprintf (stderr, "\n"); + + if (xn > n) return xn; + else return n; +} + + +int +main (int argc, char **argv) +{ + int event_number, error_number; + int major, minor; + int nscreens = 0; + int i; + + XtAppContext app; + Widget toplevel_shell = XtAppInitialize (&app, progclass, 0, 0, + &argc, argv, 0, 0, 0); + Display *dpy = XtDisplay (toplevel_shell); + XtGetApplicationNameAndClass (dpy, &progname, &progclass); + + if (!XF86VidModeQueryExtension(dpy, &event_number, &error_number)) + { + fprintf(stderr, "%s: XF86VidModeQueryExtension(dpy, ...) ==> False\n", + blurb()); + fprintf(stderr, + "%s: server does not support the XF86VidMode extension.\n", + blurb()); + exit(1); + } + else + fprintf(stderr, "%s: XF86VidModeQueryExtension(dpy, ...) ==> %d, %d\n", + blurb(), event_number, error_number); + + if (!XF86VidModeQueryVersion(dpy, &major, &minor)) + { + fprintf(stderr, "%s: XF86VidModeQueryVersion(dpy, ...) ==> False\n", + blurb()); + fprintf(stderr, + "%s: server didn't report XF86VidMode version numbers?\n", + blurb()); + } + else + fprintf(stderr, "%s: XF86VidModeQueryVersion(dpy, ...) ==> %d, %d\n", + blurb(), major, minor); + + nscreens = screen_count (dpy); + + for (i = 0; i < nscreens; i++) + { + int result = 0; + int x = 0, y = 0, dot = 0; + XF86VidModeModeLine ml = { 0, }; + XErrorHandler old_handler; + + XSync (dpy, False); + error_handler_hit_p = False; + old_handler = XSetErrorHandler (ignore_all_errors_ehandler); + + result = XF86VidModeGetViewPort (dpy, i, &x, &y); + + XSync (dpy, False); + XSetErrorHandler (old_handler); + XSync (dpy, False); + + if (error_handler_hit_p) + { + fprintf(stderr, + "%s: XF86VidModeGetViewPort(dpy, %d, ...) ==> X error\n", + blurb(), i); + continue; + } + + if (! result) + fprintf(stderr, "%s: XF86VidModeGetViewPort(dpy, %d, ...) ==> %d\n", + blurb(), i, result); + + result = XF86VidModeGetModeLine (dpy, i, &dot, &ml); + if (! result) + fprintf(stderr, "%s: XF86VidModeGetModeLine(dpy, %d, ...) ==> %d\n", + blurb(), i, result); + + fprintf (stderr, "%s: screen %d: %dx%d; viewport: %dx%d+%d+%d\n", + blurb(), i, + DisplayWidth (dpy, i), DisplayHeight (dpy, i), + ml.hdisplay, ml.vdisplay, x, y + ); + + fprintf (stderr, + "%s: hsync start %d; end %d; total %d; skew %d;\n", + blurb(), + ml.hsyncstart, ml.hsyncend, ml.htotal, ml.hskew); + fprintf (stderr, + "%s: vsync start %d; end %d; total %d; flags 0x%04x;\n", + blurb(), + ml.vsyncstart, ml.vsyncend, ml.vtotal, ml.flags); + fprintf (stderr, "\n"); + } + XSync (dpy, False); + exit (0); +} diff --git a/driver/test-xdpms.c b/driver/test-xdpms.c new file mode 100644 index 00000000..b86aed3a --- /dev/null +++ b/driver/test-xdpms.c @@ -0,0 +1,179 @@ +/* test-xdpms.c --- playing with the XDPMS extension. + * xscreensaver, Copyright (c) 1998-2011 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. + */ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include +#ifdef HAVE_UNISTD_H +# include +#endif + +#include +#include +#include + +#include +#include +#include + +#include +#include +#include + +extern Bool DPMSQueryExtension (Display *dpy, int *event_ret, int *error_ret); +extern Bool DPMSCapable (Display *dpy); +extern Status DPMSForceLevel (Display *dpy, CARD16 level); +extern Status DPMSInfo (Display *dpy, CARD16 *power_level, BOOL *state); + +extern Status DPMSGetVersion (Display *dpy, int *major_ret, int *minor_ret); +extern Status DPMSSetTimeouts (Display *dpy, + CARD16 standby, CARD16 suspend, CARD16 off); +extern Bool DPMSGetTimeouts (Display *dpy, + CARD16 *standby, CARD16 *suspend, CARD16 *off); +extern Status DPMSEnable (Display *dpy); +extern Status DPMSDisable (Display *dpy); + + +char *progname = 0; +char *progclass = "XScreenSaver"; + +static const char * +blurb (void) +{ + static char buf[255]; + time_t now = time ((time_t *) 0); + char *ct = (char *) ctime (&now); + int n = strlen(progname); + if (n > 100) n = 99; + strncpy(buf, progname, n); + buf[n++] = ':'; + buf[n++] = ' '; + strncpy(buf+n, ct+11, 8); + strcpy(buf+n+9, ": "); + return buf; +} + + +static Bool error_handler_hit_p = False; + +static int +ignore_all_errors_ehandler (Display *dpy, XErrorEvent *error) +{ + error_handler_hit_p = True; + return 0; +} + + +int +main (int argc, char **argv) +{ + int delay = 10; + + int event_number, error_number; + int major, minor; + CARD16 standby, suspend, off; + CARD16 state; + BOOL onoff; + + XtAppContext app; + Widget toplevel_shell = XtAppInitialize (&app, progclass, 0, 0, + &argc, argv, 0, 0, 0); + Display *dpy = XtDisplay (toplevel_shell); + XtGetApplicationNameAndClass (dpy, &progname, &progclass); + + if (!DPMSQueryExtension(dpy, &event_number, &error_number)) + { + fprintf(stderr, "%s: DPMSQueryExtension(dpy, ...) ==> False\n", + blurb()); + fprintf(stderr, "%s: server does not support the XDPMS extension.\n", + blurb()); + exit(1); + } + else + fprintf(stderr, "%s: DPMSQueryExtension(dpy, ...) ==> %d, %d\n", blurb(), + event_number, error_number); + + if (!DPMSCapable(dpy)) + { + fprintf(stderr, "%s: DPMSCapable(dpy) ==> False\n", blurb()); + fprintf(stderr, "%s: server says hardware doesn't support DPMS.\n", + blurb()); + exit(1); + } + else + fprintf(stderr, "%s: DPMSCapable(dpy) ==> True\n", blurb()); + + if (!DPMSGetVersion(dpy, &major, &minor)) + { + fprintf(stderr, "%s: DPMSGetVersion(dpy, ...) ==> False\n", blurb()); + fprintf(stderr, "%s: server didn't report XDPMS version numbers?\n", + blurb()); + } + else + fprintf(stderr, "%s: DPMSGetVersion(dpy, ...) ==> %d, %d\n", blurb(), + major, minor); + + if (!DPMSGetTimeouts(dpy, &standby, &suspend, &off)) + { + fprintf(stderr, "%s: DPMSGetTimeouts(dpy, ...) ==> False\n", blurb()); + fprintf(stderr, "%s: server didn't report DPMS timeouts?\n", blurb()); + } + else + fprintf(stderr, + "%s: DPMSGetTimeouts(dpy, ...)\n" + "\t ==> standby = %d, suspend = %d, off = %d\n", + blurb(), standby, suspend, off); + + while (1) + { + if (!DPMSInfo(dpy, &state, &onoff)) + { + fprintf(stderr, "%s: DPMSInfo(dpy, ...) ==> False\n", blurb()); + fprintf(stderr, "%s: couldn't read DPMS state?\n", blurb()); + onoff = 0; + state = -1; + } + else + { + fprintf(stderr, "%s: DPMSInfo(dpy, ...) ==> %s, %s\n", blurb(), + (state == DPMSModeOn ? "DPMSModeOn" : + state == DPMSModeStandby ? "DPMSModeStandby" : + state == DPMSModeSuspend ? "DPMSModeSuspend" : + state == DPMSModeOff ? "DPMSModeOff" : "???"), + (onoff == 1 ? "On" : onoff == 0 ? "Off" : "???")); + } + + if (state == DPMSModeStandby || + state == DPMSModeSuspend || + state == DPMSModeOff) + { + XErrorHandler old_handler; + int st; + fprintf(stderr, "%s: monitor is off; turning it on.\n", blurb()); + + XSync (dpy, False); + error_handler_hit_p = False; + old_handler = XSetErrorHandler (ignore_all_errors_ehandler); + XSync (dpy, False); + st = DPMSForceLevel (dpy, DPMSModeOn); + XSync (dpy, False); + if (error_handler_hit_p) st = -666; + + fprintf (stderr, "%s: DPMSForceLevel (dpy, DPMSModeOn) ==> %s\n", + blurb(), (st == -666 ? "X Error" : st ? "Ok" : "Error")); + } + + sleep (delay); + } +} diff --git a/driver/test-xinerama.c b/driver/test-xinerama.c new file mode 100644 index 00000000..8bafbb07 --- /dev/null +++ b/driver/test-xinerama.c @@ -0,0 +1,112 @@ +/* test-xinerama.c --- playing with the Xinerama extension. + * xscreensaver, Copyright (c) 2003 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. + */ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include +#ifdef HAVE_UNISTD_H +# include +#endif + +#include +#include +#include + +#include +#include +#include + +#include +#include + +char *progname = 0; +char *progclass = "XScreenSaver"; + +static const char * +blurb (void) +{ + static char buf[255]; + time_t now = time ((time_t *) 0); + char *ct = (char *) ctime (&now); + int n = strlen(progname); + if (n > 100) n = 99; + strncpy(buf, progname, n); + buf[n++] = ':'; + buf[n++] = ' '; + strncpy(buf+n, ct+11, 8); + strcpy(buf+n+9, ": "); + return buf; +} + + +int +main (int argc, char **argv) +{ + int event_number, error_number; + int major, minor; + int nscreens = 0; + XineramaScreenInfo *xsi; + int i; + + XtAppContext app; + Widget toplevel_shell = XtAppInitialize (&app, progclass, 0, 0, + &argc, argv, 0, 0, 0); + Display *dpy = XtDisplay (toplevel_shell); + XtGetApplicationNameAndClass (dpy, &progname, &progclass); + + if (!XineramaQueryExtension(dpy, &event_number, &error_number)) + { + fprintf(stderr, "%s: XineramaQueryExtension(dpy, ...) ==> False\n", + blurb()); + fprintf(stderr, "%s: server does not support the Xinerama extension.\n", + blurb()); + exit(1); + } + else + fprintf(stderr, "%s: XineramaQueryExtension(dpy, ...) ==> %d, %d\n", + blurb(), event_number, error_number); + + if (!XineramaIsActive(dpy)) + { + fprintf(stderr, "%s: XineramaIsActive(dpy) ==> False\n", blurb()); + fprintf(stderr, "%s: server says Xinerama is turned off.\n", blurb()); + exit(1); + } + else + fprintf(stderr, "%s: XineramaIsActive(dpy) ==> True\n", blurb()); + + if (!XineramaQueryVersion(dpy, &major, &minor)) + { + fprintf(stderr, "%s: XineramaQueryVersion(dpy, ...) ==> False\n", + blurb()); + fprintf(stderr, "%s: server didn't report Xinerama version numbers?\n", + blurb()); + } + else + fprintf(stderr, "%s: XineramaQueryVersion(dpy, ...) ==> %d, %d\n", blurb(), + major, minor); + + xsi = XineramaQueryScreens (dpy, &nscreens); + fprintf(stderr, "%s: %d Xinerama screens\n", blurb(), nscreens); + + for (i = 0; i < nscreens; i++) + fprintf (stderr, "%s: screen %d: %dx%d+%d+%d\n", + blurb(), + xsi[i].screen_number, + xsi[i].width, xsi[i].height, + xsi[i].x_org, xsi[i].y_org); + XFree (xsi); + XSync (dpy, False); + exit (0); +} diff --git a/driver/timers.c b/driver/timers.c new file mode 100644 index 00000000..87b3fb98 --- /dev/null +++ b/driver/timers.c @@ -0,0 +1,1669 @@ +/* timers.c --- detecting when the user is idle, and other timer-related tasks. + * xscreensaver, Copyright (c) 1991-2012 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. + */ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include +#include +#include +#include +#include +#include +#ifdef HAVE_XMU +# ifndef VMS +# include +# else /* VMS */ +# include +# endif /* VMS */ +# else /* !HAVE_XMU */ +# include "xmu.h" +#endif /* !HAVE_XMU */ + +#ifdef HAVE_XIDLE_EXTENSION +#include +#endif /* HAVE_XIDLE_EXTENSION */ + +#ifdef HAVE_MIT_SAVER_EXTENSION +#include +#endif /* HAVE_MIT_SAVER_EXTENSION */ + +#ifdef HAVE_SGI_SAVER_EXTENSION +#include +#endif /* HAVE_SGI_SAVER_EXTENSION */ + +#ifdef HAVE_RANDR +#include +#endif /* HAVE_RANDR */ + +#include "xscreensaver.h" + +#undef ABS +#define ABS(x)((x)<0?-(x):(x)) + +#undef MAX +#define MAX(x,y)((x)>(y)?(x):(y)) + + +#ifdef HAVE_PROC_INTERRUPTS +static Bool proc_interrupts_activity_p (saver_info *si); +#endif /* HAVE_PROC_INTERRUPTS */ + +static void check_for_clock_skew (saver_info *si); + + +void +idle_timer (XtPointer closure, XtIntervalId *id) +{ + saver_info *si = (saver_info *) closure; + + /* What an amazingly shitty design. Not only does Xt execute timeout + events from XtAppNextEvent() instead of from XtDispatchEvent(), but + there is no way to tell Xt to block until there is an X event OR a + timeout happens. Once your timeout proc is called, XtAppNextEvent() + still won't return until a "real" X event comes in. + + So this function pushes a stupid, gratuitous, unnecessary event back + on the event queue to force XtAppNextEvent to return Right Fucking Now. + When the code in sleep_until_idle() sees an event of type XAnyEvent, + which the server never generates, it knows that a timeout has occurred. + */ + XEvent fake_event; + fake_event.type = 0; /* XAnyEvent type, ignored. */ + fake_event.xany.display = si->dpy; + fake_event.xany.window = 0; + XPutBackEvent (si->dpy, &fake_event); + + /* If we are the timer that just went off, clear the pointer to the id. */ + if (id) + { + if (si->timer_id && *id != si->timer_id) + abort(); /* oops, scheduled timer twice?? */ + si->timer_id = 0; + } +} + + +void +schedule_wakeup_event (saver_info *si, Time when, Bool verbose_p) +{ + if (si->timer_id) + { + if (verbose_p) + fprintf (stderr, "%s: idle_timer already running\n", blurb()); + return; + } + + /* Wake up periodically to ask the server if we are idle. */ + si->timer_id = XtAppAddTimeOut (si->app, when, idle_timer, + (XtPointer) si); + + if (verbose_p) + fprintf (stderr, "%s: starting idle_timer (%ld, %ld)\n", + blurb(), when, si->timer_id); +} + + +static void +notice_events (saver_info *si, Window window, Bool top_p) +{ + saver_preferences *p = &si->prefs; + XWindowAttributes attrs; + unsigned long events; + Window root, parent, *kids; + unsigned int nkids; + int screen_no; + + if (XtWindowToWidget (si->dpy, window)) + /* If it's one of ours, don't mess up its event mask. */ + return; + + if (!XQueryTree (si->dpy, window, &root, &parent, &kids, &nkids)) + return; + if (window == root) + top_p = False; + + /* Figure out which screen this window is on, for the diagnostics. */ + for (screen_no = 0; screen_no < si->nscreens; screen_no++) + if (root == RootWindowOfScreen (si->screens[screen_no].screen)) + break; + + XGetWindowAttributes (si->dpy, window, &attrs); + events = ((attrs.all_event_masks | attrs.do_not_propagate_mask) + & KeyPressMask); + + /* Select for SubstructureNotify on all windows. + Select for KeyPress on all windows that already have it selected. + + Note that we can't select for ButtonPress, because of X braindamage: + only one client at a time may select for ButtonPress on a given + window, though any number can select for KeyPress. Someone explain + *that* to me. + + So, if the user spends a while clicking the mouse without ever moving + the mouse or touching the keyboard, we won't know that they've been + active, and the screensaver will come on. That sucks, but I don't + know how to get around it. + + Since X presents mouse wheels as clicks, this applies to those, too: + scrolling through a document using only the mouse wheel doesn't + count as activity... Fortunately, /proc/interrupts helps, on + systems that have it. Oh, if it's a PS/2 mouse, not serial or USB. + This sucks! + */ + XSelectInput (si->dpy, window, SubstructureNotifyMask | events); + + if (top_p && p->debug_p && (events & KeyPressMask)) + { + /* Only mention one window per tree (hack hack). */ + fprintf (stderr, "%s: %d: selected KeyPress on 0x%lX\n", + blurb(), screen_no, (unsigned long) window); + top_p = False; + } + + if (kids) + { + while (nkids) + notice_events (si, kids [--nkids], top_p); + XFree ((char *) kids); + } +} + + +int +BadWindow_ehandler (Display *dpy, XErrorEvent *error) +{ + /* When we notice a window being created, we spawn a timer that waits + 30 seconds or so, and then selects events on that window. This error + handler is used so that we can cope with the fact that the window + may have been destroyed <30 seconds after it was created. + */ + if (error->error_code == BadWindow || + error->error_code == BadMatch || + error->error_code == BadDrawable) + return 0; + else + return saver_ehandler (dpy, error); +} + + +struct notice_events_timer_arg { + saver_info *si; + Window w; +}; + +static void +notice_events_timer (XtPointer closure, XtIntervalId *id) +{ + struct notice_events_timer_arg *arg = + (struct notice_events_timer_arg *) closure; + + XErrorHandler old_handler = XSetErrorHandler (BadWindow_ehandler); + + saver_info *si = arg->si; + Window window = arg->w; + + free(arg); + notice_events (si, window, True); + XSync (si->dpy, False); + XSetErrorHandler (old_handler); +} + +void +start_notice_events_timer (saver_info *si, Window w, Bool verbose_p) +{ + saver_preferences *p = &si->prefs; + struct notice_events_timer_arg *arg = + (struct notice_events_timer_arg *) malloc(sizeof(*arg)); + arg->si = si; + arg->w = w; + XtAppAddTimeOut (si->app, p->notice_events_timeout, notice_events_timer, + (XtPointer) arg); + + if (verbose_p) + fprintf (stderr, "%s: starting notice_events_timer for 0x%X (%lu)\n", + blurb(), (unsigned int) w, p->notice_events_timeout); +} + + +/* When the screensaver is active, this timer will periodically change + the running program. + */ +void +cycle_timer (XtPointer closure, XtIntervalId *id) +{ + saver_info *si = (saver_info *) closure; + saver_preferences *p = &si->prefs; + Time how_long = p->cycle; + + if (si->selection_mode > 0 && + screenhack_running_p (si)) + /* If we're in "SELECT n" mode, the cycle timer going off will just + restart this same hack again. There's not much point in doing this + every 5 or 10 minutes, but on the other hand, leaving one hack running + for days is probably not a great idea, since they tend to leak and/or + crash. So, restart the thing once an hour. */ + how_long = 1000 * 60 * 60; + + if (si->dbox_up_p) + { + if (p->verbose_p) + fprintf (stderr, "%s: dialog box up; delaying hack change.\n", + blurb()); + how_long = 30000; /* 30 secs */ + } + else + { + int i; + maybe_reload_init_file (si); + for (i = 0; i < si->nscreens; i++) + kill_screenhack (&si->screens[i]); + + raise_window (si, True, True, False); + + if (!si->throttled_p) + for (i = 0; i < si->nscreens; i++) + spawn_screenhack (&si->screens[i]); + else + { + if (p->verbose_p) + fprintf (stderr, "%s: not launching new hack (throttled.)\n", + blurb()); + } + } + + if (how_long > 0) + { + si->cycle_id = XtAppAddTimeOut (si->app, how_long, cycle_timer, + (XtPointer) si); + + if (p->debug_p) + fprintf (stderr, "%s: starting cycle_timer (%ld, %ld)\n", + blurb(), how_long, si->cycle_id); + } + else + { + if (p->debug_p) + fprintf (stderr, "%s: not starting cycle_timer: how_long == %ld\n", + blurb(), (unsigned long) how_long); + } +} + + +void +activate_lock_timer (XtPointer closure, XtIntervalId *id) +{ + saver_info *si = (saver_info *) closure; + saver_preferences *p = &si->prefs; + + if (p->verbose_p) + fprintf (stderr, "%s: timed out; activating lock.\n", blurb()); + set_locked_p (si, True); +} + + +/* Call this when user activity (or "simulated" activity) has been noticed. + */ +void +reset_timers (saver_info *si) +{ + saver_preferences *p = &si->prefs; + if (si->using_mit_saver_extension || si->using_sgi_saver_extension) + return; + + if (si->timer_id) + { + if (p->debug_p) + fprintf (stderr, "%s: killing idle_timer (%ld, %ld)\n", + blurb(), p->timeout, si->timer_id); + XtRemoveTimeOut (si->timer_id); + si->timer_id = 0; + } + + schedule_wakeup_event (si, p->timeout, p->debug_p); /* sets si->timer_id */ + + if (si->cycle_id) abort (); /* no cycle timer when inactive */ + + si->last_activity_time = time ((time_t *) 0); + + /* This will (hopefully, supposedly) tell the server to re-set its + DPMS timer. Without this, the -deactivate clientmessage would + prevent xscreensaver from blanking, but would not prevent the + monitor from powering down. */ +#if 0 + /* #### With some servers, this causes the screen to flicker every + time a key is pressed! Ok, I surrender. I give up on ever + having DPMS work properly. + */ + XForceScreenSaver (si->dpy, ScreenSaverReset); + + /* And if the monitor is already powered off, turn it on. + You'd think the above would do that, but apparently not? */ + monitor_power_on (si, True); +#endif + +} + + +/* Returns true if a mouse has moved since the last time we checked. + Small motions (of less than "hysteresis" pixels/second) are ignored. + */ +static Bool +device_pointer_moved_p (saver_info *si, poll_mouse_data *last_poll_mouse, + poll_mouse_data *this_poll_mouse, Bool mods_p, + const char *debug_type, int debug_id) +{ + saver_preferences *p = &si->prefs; + + unsigned int distance, dps; + unsigned long seconds = 0; + Bool moved_p = False; + + distance = MAX (ABS (last_poll_mouse->root_x - this_poll_mouse->root_x), + ABS (last_poll_mouse->root_y - this_poll_mouse->root_y)); + seconds = (this_poll_mouse->time - last_poll_mouse->time); + + + /* When the screen is blanked, we get MotionNotify events, but when not + blanked, we poll only every 5 seconds, and that's not enough resolution + to do hysteresis based on a 1 second interval. So, assume that any + motion we've seen during the 5 seconds when our eyes were closed happened + in the last 1 second instead. + */ + if (seconds > 1) seconds = 1; + + dps = (seconds <= 0 ? distance : (distance / seconds)); + + /* Motion only counts if the rate is more than N pixels per second. + */ + if (dps >= p->pointer_hysteresis && + distance > 0) + moved_p = True; + + /* If the mouse is not on this screen but used to be, that's motion. + If the mouse was not on this screen, but is now, that's motion. + */ + { + Bool on_screen_p = (this_poll_mouse->root_x != -1 && + this_poll_mouse->root_y != -1); + Bool was_on_screen_p = (last_poll_mouse->root_x != -1 && + last_poll_mouse->root_y != -1); + + if (on_screen_p != was_on_screen_p) + moved_p = True; + } + + if (p->debug_p && (distance != 0 || moved_p)) + { + fprintf (stderr, "%s: %s %d: pointer %s", blurb(), debug_type, debug_id, + (moved_p ? "moved: " : "ignored:")); + if (last_poll_mouse->root_x == -1) + fprintf (stderr, "off screen"); + else + fprintf (stderr, "%d,%d", + last_poll_mouse->root_x, + last_poll_mouse->root_y); + fprintf (stderr, " -> "); + if (this_poll_mouse->root_x == -1) + fprintf (stderr, "off screen"); + else + fprintf (stderr, "%d,%d", this_poll_mouse->root_x, + this_poll_mouse->root_y); + if (last_poll_mouse->root_x != -1 && this_poll_mouse->root_x != -1) + fprintf (stderr, " (%d,%d; %d/%lu=%d)", + ABS(last_poll_mouse->root_x - this_poll_mouse->root_x), + ABS(last_poll_mouse->root_y - this_poll_mouse->root_y), + distance, seconds, dps); + + fprintf (stderr, ".\n"); + } + + if (!moved_p && + mods_p && + this_poll_mouse->mask != last_poll_mouse->mask) + { + moved_p = True; + + if (p->debug_p) + fprintf (stderr, "%s: %s %d: modifiers changed: 0x%04x -> 0x%04x.\n", + blurb(), debug_type, debug_id, + last_poll_mouse->mask, this_poll_mouse->mask); + } + + last_poll_mouse->child = this_poll_mouse->child; + last_poll_mouse->mask = this_poll_mouse->mask; + + if (moved_p || seconds > 0) + { + last_poll_mouse->time = this_poll_mouse->time; + last_poll_mouse->root_x = this_poll_mouse->root_x; + last_poll_mouse->root_y = this_poll_mouse->root_y; + } + + return moved_p; +} + +/* Returns true if core mouse pointer has moved since the last time we checked. + */ +static Bool +pointer_moved_p (saver_screen_info *ssi, Bool mods_p) +{ + saver_info *si = ssi->global; + + Window root; + poll_mouse_data this_poll_mouse; + int x, y; + + /* don't check xinerama pseudo-screens. */ + if (!ssi->real_screen_p) return False; + + this_poll_mouse.time = time ((time_t *) 0); + + if (!XQueryPointer (si->dpy, ssi->screensaver_window, &root, + &this_poll_mouse.child, + &this_poll_mouse.root_x, &this_poll_mouse.root_y, + &x, &y, &this_poll_mouse.mask)) + { + /* If XQueryPointer() returns false, the mouse is not on this screen. + */ + this_poll_mouse.root_x = -1; + this_poll_mouse.root_y = -1; + this_poll_mouse.child = 0; + this_poll_mouse.mask = 0; + } + else + si->last_activity_screen = ssi; + + return device_pointer_moved_p(si, &(ssi->last_poll_mouse), &this_poll_mouse, + mods_p, "screen", ssi->number); +} + + +/* When we aren't using a server extension, this timer is used to periodically + wake up and poll the mouse position, which is possibly more reliable than + selecting motion events on every window. + */ +static void +check_pointer_timer (XtPointer closure, XtIntervalId *id) +{ + int i; + saver_info *si = (saver_info *) closure; + saver_preferences *p = &si->prefs; + Bool active_p = False; + + if (!si->using_proc_interrupts && + (si->using_xidle_extension || + si->using_mit_saver_extension || + si->using_sgi_saver_extension)) + /* If an extension is in use, we should not be polling the mouse. + Unless we're also checking /proc/interrupts, in which case, we should. + */ + abort (); + + if (id && *id == si->check_pointer_timer_id) /* this is us - it's expired */ + si->check_pointer_timer_id = 0; + + if (si->check_pointer_timer_id) /* only queue one at a time */ + XtRemoveTimeOut (si->check_pointer_timer_id); + + si->check_pointer_timer_id = /* now re-queue */ + XtAppAddTimeOut (si->app, p->pointer_timeout, check_pointer_timer, + (XtPointer) si); + + for (i = 0; i < si->nscreens; i++) + { + saver_screen_info *ssi = &si->screens[i]; + if (pointer_moved_p (ssi, True)) + active_p = True; + } + +#ifdef HAVE_PROC_INTERRUPTS + if (!active_p && + si->using_proc_interrupts && + proc_interrupts_activity_p (si)) + { + active_p = True; + } +#endif /* HAVE_PROC_INTERRUPTS */ + + if (active_p) + reset_timers (si); + + check_for_clock_skew (si); +} + + +/* An unfortunate situation is this: the saver is not active, because the + user has been typing. The machine is a laptop. The user closes the lid + and suspends it. The CPU halts. Some hours later, the user opens the + lid. At this point, Xt's timers will fire, and xscreensaver will blank + the screen. + + So far so good -- well, not really, but it's the best that we can do, + since the OS doesn't send us a signal *before* shutdown -- but if the + user had delayed locking (lockTimeout > 0) then we should start off + in the locked state, rather than only locking N minutes from when the + lid was opened. Also, eschewing fading is probably a good idea, to + clamp down as soon as possible. + + We only do this when we'd be polling the mouse position anyway. + This amounts to an assumption that machines with APM support also + have /proc/interrupts. + */ +static void +check_for_clock_skew (saver_info *si) +{ + saver_preferences *p = &si->prefs; + time_t now = time ((time_t *) 0); + long shift = now - si->last_wall_clock_time; + + if (p->debug_p) + { + int i = (si->last_wall_clock_time == 0 ? 0 : shift); + fprintf (stderr, + "%s: checking wall clock for hibernation (%d:%02d:%02d).\n", + blurb(), + (i / (60 * 60)), ((i / 60) % 60), (i % 60)); + } + + if (si->last_wall_clock_time != 0 && + shift > (p->timeout / 1000)) + { + if (p->verbose_p) + fprintf (stderr, "%s: wall clock has jumped by %ld:%02ld:%02ld!\n", + blurb(), + (shift / (60 * 60)), ((shift / 60) % 60), (shift % 60)); + + si->emergency_lock_p = True; + idle_timer ((XtPointer) si, 0); + } + + si->last_wall_clock_time = now; +} + + + +static void +dispatch_event (saver_info *si, XEvent *event) +{ + /* If this is for the splash dialog, pass it along. + Note that the password dialog is handled with its own event loop, + so events for that window will never come through here. + */ + if (si->splash_dialog && event->xany.window == si->splash_dialog) + handle_splash_event (si, event); + + XtDispatchEvent (event); +} + + +static void +swallow_unlock_typeahead_events (saver_info *si, XEvent *e) +{ + XEvent event; + char buf [100]; + int i = 0; + + memset (buf, 0, sizeof(buf)); + + event = *e; + + do + { + if (event.xany.type == KeyPress) + { + char s[2]; + int size = XLookupString ((XKeyEvent *) &event, s, 1, 0, 0); + if (size != 1) continue; + switch (*s) + { + case '\010': case '\177': /* Backspace */ + if (i > 0) i--; + break; + case '\025': case '\030': /* Erase line */ + case '\012': case '\015': /* Enter */ + case '\033': /* ESC */ + i = 0; + break; + case '\040': /* Space */ + if (i == 0) + break; /* ignore space at beginning of line */ + /* else, fall through */ + default: + buf [i++] = *s; + break; + } + } + + } while (i < sizeof(buf)-1 && + XCheckMaskEvent (si->dpy, KeyPressMask, &event)); + + buf[i] = 0; + + if (si->unlock_typeahead) + { + memset (si->unlock_typeahead, 0, strlen(si->unlock_typeahead)); + free (si->unlock_typeahead); + } + + if (i > 0) + si->unlock_typeahead = strdup (buf); + else + si->unlock_typeahead = 0; + + memset (buf, 0, sizeof(buf)); +} + + +/* methods of detecting idleness: + + explicitly informed by SGI SCREEN_SAVER server event; + explicitly informed by MIT-SCREEN-SAVER server event; + poll server idle time with XIDLE extension; + select events on all windows, and note absence of recent events; + note that /proc/interrupts has not changed in a while; + activated by clientmessage. + + methods of detecting non-idleness: + + read events on the xscreensaver window; + explicitly informed by SGI SCREEN_SAVER server event; + explicitly informed by MIT-SCREEN-SAVER server event; + select events on all windows, and note events on any of them; + note that /proc/interrupts has changed; + deactivated by clientmessage. + + I trust that explains why this function is a big hairy mess. + */ +void +sleep_until_idle (saver_info *si, Bool until_idle_p) +{ + saver_preferences *p = &si->prefs; + + /* We have to go through this union bullshit because gcc-4.4.0 has + stricter struct-aliasing rules. Without this, the optimizer + can fuck things up. + */ + union { + XEvent x_event; +# ifdef HAVE_RANDR + XRRScreenChangeNotifyEvent xrr_event; +# endif /* HAVE_RANDR */ +# ifdef HAVE_MIT_SAVER_EXTENSION + XScreenSaverNotifyEvent sevent; +# endif /* HAVE_MIT_SAVER_EXTENSION */ + } event; + + /* We need to select events on all windows if we're not using any extensions. + Otherwise, we don't need to. */ + Bool scanning_all_windows = !(si->using_xidle_extension || + si->using_mit_saver_extension || + si->using_sgi_saver_extension); + + /* We need to periodically wake up and check for idleness if we're not using + any extensions, or if we're using the XIDLE extension. The other two + extensions explicitly deliver events when we go idle/non-idle, so we + don't need to poll. */ + Bool polling_for_idleness = !(si->using_mit_saver_extension || + si->using_sgi_saver_extension); + + /* Whether we need to periodically wake up and check to see if the mouse has + moved. We only need to do this when not using any extensions. The reason + this isn't the same as `polling_for_idleness' is that the "idleness" poll + can happen (for example) 5 minutes from now, whereas the mouse-position + poll should happen with low periodicity. We don't need to poll the mouse + position with the XIDLE extension, but we do need to periodically wake up + and query the server with that extension. For our purposes, polling + /proc/interrupts is just like polling the mouse position. It has to + happen on the same kind of schedule. */ + Bool polling_mouse_position = (si->using_proc_interrupts || + !(si->using_xidle_extension || + si->using_mit_saver_extension || + si->using_sgi_saver_extension) || + si->using_xinput_extension); + + const char *why = 0; /* What caused the idle-state to change? */ + + if (until_idle_p) + { + if (polling_for_idleness) + /* This causes a no-op event to be delivered to us in a while, so that + we come back around through the event loop again. */ + schedule_wakeup_event (si, p->timeout, p->debug_p); + + if (polling_mouse_position) + /* Check to see if the mouse has moved, and set up a repeating timer + to do so periodically (typically, every 5 seconds.) */ + check_pointer_timer ((XtPointer) si, 0); + } + + while (1) + { + XtAppNextEvent (si->app, &event.x_event); + + switch (event.x_event.xany.type) { + case 0: /* our synthetic "timeout" event has been signalled */ + if (until_idle_p) + { + Time idle; + + /* We may be idle; check one last time to see if the mouse has + moved, just in case the idle-timer went off within the 5 second + window between mouse polling. If the mouse has moved, then + check_pointer_timer() will reset last_activity_time. + */ + if (polling_mouse_position) + check_pointer_timer ((XtPointer) si, 0); + +#ifdef HAVE_XIDLE_EXTENSION + if (si->using_xidle_extension) + { + /* The XIDLE extension uses the synthetic event to prod us into + re-asking the server how long the user has been idle. */ + if (! XGetIdleTime (si->dpy, &idle)) + { + fprintf (stderr, "%s: XGetIdleTime() failed.\n", blurb()); + saver_exit (si, 1, 0); + } + } + else +#endif /* HAVE_XIDLE_EXTENSION */ +#ifdef HAVE_MIT_SAVER_EXTENSION + if (si->using_mit_saver_extension) + { + /* We don't need to do anything in this case - the synthetic + event isn't necessary, as we get sent specific events + to wake us up. In fact, this event generally shouldn't + be being delivered when the MIT extension is in use. */ + idle = 0; + } + else +#endif /* HAVE_MIT_SAVER_EXTENSION */ +#ifdef HAVE_SGI_SAVER_EXTENSION + if (si->using_sgi_saver_extension) + { + /* We don't need to do anything in this case - the synthetic + event isn't necessary, as we get sent specific events + to wake us up. In fact, this event generally shouldn't + be being delivered when the SGI extension is in use. */ + idle = 0; + } + else +#endif /* HAVE_SGI_SAVER_EXTENSION */ + { + /* Otherwise, no server extension is in use. The synthetic + event was to tell us to wake up and see if the user is now + idle. Compute the amount of idle time by comparing the + `last_activity_time' to the wall clock. The l_a_t was set + by calling `reset_timers()', which is called only in only + two situations: when polling the mouse position has revealed + the the mouse has moved (user activity) or when we have read + an event (again, user activity.) + */ + idle = 1000 * (si->last_activity_time - time ((time_t *) 0)); + } + + if (idle >= p->timeout) + { + /* Look, we've been idle long enough. We're done. */ + why = "timeout"; + goto DONE; + } + else if (si->emergency_lock_p) + { + /* Oops, the wall clock has jumped far into the future, so + we need to lock down in a hurry! */ + why = "large wall clock change"; + goto DONE; + } + else + { + /* The event went off, but it turns out that the user has not + yet been idle for long enough. So re-signal the event. + Be economical: if we should blank after 5 minutes, and the + user has been idle for 2 minutes, then set this timer to + go off in 3 minutes. + */ + if (polling_for_idleness) + schedule_wakeup_event (si, p->timeout - idle, p->debug_p); + } + } + break; + + case ClientMessage: + if (handle_clientmessage (si, &event.x_event, until_idle_p)) + { + why = "ClientMessage"; + goto DONE; + } + break; + + case CreateNotify: + /* A window has been created on the screen somewhere. If we're + supposed to scan all windows for events, prepare this window. */ + if (scanning_all_windows) + { + Window w = event.x_event.xcreatewindow.window; + start_notice_events_timer (si, w, p->debug_p); + } + break; + + case KeyPress: + case ButtonPress: + /* Ignore release events so that hitting ESC at the password dialog + doesn't result in the password dialog coming right back again when + the fucking release key is seen! */ + /* case KeyRelease:*/ + /* case ButtonRelease:*/ + case MotionNotify: + + if (p->debug_p) + { + Window root=0, window=0; + int x=-1, y=-1; + const char *type = 0; + if (event.x_event.xany.type == MotionNotify) + { + /*type = "MotionNotify";*/ + root = event.x_event.xmotion.root; + window = event.x_event.xmotion.window; + x = event.x_event.xmotion.x_root; + y = event.x_event.xmotion.y_root; + } + else if (event.x_event.xany.type == KeyPress) + { + type = "KeyPress"; + root = event.x_event.xkey.root; + window = event.x_event.xkey.window; + x = y = -1; + } + else if (event.x_event.xany.type == ButtonPress) + { + type = "ButtonPress"; + root = event.x_event.xkey.root; + window = event.x_event.xkey.window; + x = event.x_event.xmotion.x_root; + y = event.x_event.xmotion.y_root; + } + + if (type) + { + int i; + for (i = 0; i < si->nscreens; i++) + if (root == RootWindowOfScreen (si->screens[i].screen)) + break; + fprintf (stderr,"%s: %d: %s on 0x%lx", + blurb(), i, type, (unsigned long) window); + + /* Be careful never to do this unless in -debug mode, as + this could expose characters from the unlock password. */ + if (p->debug_p && event.x_event.xany.type == KeyPress) + { + KeySym keysym; + char c = 0; + XLookupString (&event.x_event.xkey, &c, 1, &keysym, 0); + fprintf (stderr, " (%s%s)", + (event.x_event.xkey.send_event ? "synthetic " : ""), + XKeysymToString (keysym)); + } + + if (x == -1) + fprintf (stderr, "\n"); + else + fprintf (stderr, " at %d,%d.\n", x, y); + } + } + + /* If any widgets want to handle this event, let them. */ + dispatch_event (si, &event.x_event); + + + /* If we got a MotionNotify event, figure out what screen it + was on and poll the mouse there: if the mouse hasn't moved + far enough to count as "real" motion, then ignore this + event. + */ + if (event.x_event.xany.type == MotionNotify) + { + int i; + for (i = 0; i < si->nscreens; i++) + if (event.x_event.xmotion.root == + RootWindowOfScreen (si->screens[i].screen)) + break; + if (i < si->nscreens) + { + if (!pointer_moved_p (&si->screens[i], False)) + continue; + } + } + + + /* We got a user event. + If we're waiting for the user to become active, this is it. + If we're waiting until the user becomes idle, reset the timers + (since now we have longer to wait.) + */ + if (!until_idle_p) + { + if (si->demoing_p && + (event.x_event.xany.type == MotionNotify || + event.x_event.xany.type == KeyRelease)) + /* When we're demoing a single hack, mouse motion doesn't + cause deactivation. Only clicks and keypresses do. */ + ; + else + { + /* If we're not demoing, then any activity causes deactivation. + */ + why = (event.x_event.xany.type == MotionNotify ?"mouse motion": + event.x_event.xany.type == KeyPress?"keyboard activity": + event.x_event.xany.type == ButtonPress ? "mouse click" : + "unknown user activity"); + goto DONE; + } + } + else + reset_timers (si); + + break; + + default: + +#ifdef HAVE_MIT_SAVER_EXTENSION + if (event.x_event.type == si->mit_saver_ext_event_number) + { + /* This event's number is that of the MIT-SCREEN-SAVER server + extension. This extension has one event number, and the event + itself contains sub-codes that say what kind of event it was + (an "idle" or "not-idle" event.) + */ + if (event.sevent.state == ScreenSaverOn) + { + int i = 0; + if (p->verbose_p) + fprintf (stderr, "%s: MIT ScreenSaverOn event received.\n", + blurb()); + + /* Get the "real" server window(s) out of the way as soon + as possible. */ + for (i = 0; i < si->nscreens; i++) + { + saver_screen_info *ssi = &si->screens[i]; + if (ssi->server_mit_saver_window && + window_exists_p (si->dpy, + ssi->server_mit_saver_window)) + XUnmapWindow (si->dpy, ssi->server_mit_saver_window); + } + + if (event.sevent.kind != ScreenSaverExternal) + { + fprintf (stderr, + "%s: ScreenSaverOn event wasn't of type External!\n", + blurb()); + } + + if (until_idle_p) + { + why = "MIT ScreenSaverOn"; + goto DONE; + } + } + else if (event.sevent.state == ScreenSaverOff) + { + if (p->verbose_p) + fprintf (stderr, "%s: MIT ScreenSaverOff event received.\n", + blurb()); + if (!until_idle_p) + { + why = "MIT ScreenSaverOff"; + goto DONE; + } + } + else + fprintf (stderr, + "%s: unknown MIT-SCREEN-SAVER event %d received!\n", + blurb(), event.sevent.state); + } + else + +#endif /* HAVE_MIT_SAVER_EXTENSION */ + + +#ifdef HAVE_SGI_SAVER_EXTENSION + if (event.x_event.type == (si->sgi_saver_ext_event_number + ScreenSaverStart)) + { + /* The SGI SCREEN_SAVER server extension has two event numbers, + and this event matches the "idle" event. */ + if (p->verbose_p) + fprintf (stderr, "%s: SGI ScreenSaverStart event received.\n", + blurb()); + + if (until_idle_p) + { + why = "SGI ScreenSaverStart"; + goto DONE; + } + } + else if (event.x_event.type == (si->sgi_saver_ext_event_number + + ScreenSaverEnd)) + { + /* The SGI SCREEN_SAVER server extension has two event numbers, + and this event matches the "idle" event. */ + if (p->verbose_p) + fprintf (stderr, "%s: SGI ScreenSaverEnd event received.\n", + blurb()); + if (!until_idle_p) + { + why = "SGI ScreenSaverEnd"; + goto DONE; + } + } + else +#endif /* HAVE_SGI_SAVER_EXTENSION */ + +#ifdef HAVE_XINPUT + /* If we got a MotionNotify event, check to see if the mouse has + moved far enough to count as "real" motion, if not, then ignore + this event. + */ + if ((si->num_xinput_devices > 0) && + (event.x_event.type == si->xinput_DeviceMotionNotify)) + { + XDeviceMotionEvent *dme = (XDeviceMotionEvent *) &event; + poll_mouse_data *last_poll_mouse = NULL; + int d; + + for (d = 0; d < si->num_xinput_devices; d++) + { + if (si->xinput_devices[d].device->device_id == dme->deviceid) + { + last_poll_mouse = &(si->xinput_devices[d].last_poll_mouse); + break; + } + } + + if (last_poll_mouse) + { + poll_mouse_data this_poll_mouse; + this_poll_mouse.root_x = dme->x_root; + this_poll_mouse.root_y = dme->y_root; + this_poll_mouse.child = dme->subwindow; + this_poll_mouse.mask = dme->device_state; + this_poll_mouse.time = dme->time / 1000; /* milliseconds */ + + if (!device_pointer_moved_p (si, last_poll_mouse, + &this_poll_mouse, False, + "device", dme->deviceid)) + continue; + } + else if (p->debug_p) + fprintf (stderr, + "%s: received MotionNotify from unknown device %d\n", + blurb(), (int) dme->deviceid); + } + + if ((!until_idle_p) && + (si->num_xinput_devices > 0) && + (event.x_event.type == si->xinput_DeviceMotionNotify || + event.x_event.type == si->xinput_DeviceButtonPress)) + /* Ignore DeviceButtonRelease, see ButtonRelease comment above. */ + { + + dispatch_event (si, &event.x_event); + if (si->demoing_p && + event.x_event.type == si->xinput_DeviceMotionNotify) + /* When we're demoing a single hack, mouse motion doesn't + cause deactivation. Only clicks and keypresses do. */ + ; + else + /* If we're not demoing, then any activity causes deactivation. + */ + { + why = (event.x_event.type == si->xinput_DeviceMotionNotify + ? "XI mouse motion" : + event.x_event.type == si->xinput_DeviceButtonPress + ? "XI mouse click" : "unknown XINPUT event"); + goto DONE; + } + } + else +#endif /* HAVE_XINPUT */ + +#ifdef HAVE_RANDR + if (si->using_randr_extension && + (event.x_event.type == + (si->randr_event_number + RRScreenChangeNotify))) + { + /* The Resize and Rotate extension sends an event when the + size, rotation, or refresh rate of any screen has changed. + */ + if (p->verbose_p) + { + /* XRRRootToScreen is in Xrandr.h 1.4, 2001/06/07 */ + int screen = XRRRootToScreen (si->dpy, event.xrr_event.window); + fprintf (stderr, "%s: %d: screen change event received\n", + blurb(), screen); + } + +# ifdef RRScreenChangeNotifyMask + /* Inform Xlib that it's ok to update its data structures. */ + XRRUpdateConfiguration (&event.x_event); /* Xrandr.h 1.9, 2002/09/29 */ +# endif /* RRScreenChangeNotifyMask */ + + /* Resize the existing xscreensaver windows and cached ssi data. */ + if (update_screen_layout (si)) + { + if (p->verbose_p) + { + fprintf (stderr, "%s: new layout:\n", blurb()); + describe_monitor_layout (si); + } + resize_screensaver_window (si); + } + } + else +#endif /* HAVE_RANDR */ + + /* Just some random event. Let the Widgets handle it, if desired. */ + dispatch_event (si, &event.x_event); + } + } + DONE: + + if (p->verbose_p) + { + if (! why) why = "unknown reason"; + fprintf (stderr, "%s: %s (%s)\n", blurb(), + (until_idle_p ? "user is idle" : "user is active"), + why); + } + + /* If there's a user event on the queue, swallow it. + If we're using a server extension, and the user becomes active, we + get the extension event before the user event -- so the keypress or + motion or whatever is still on the queue. This makes "unfade" not + work, because it sees that event, and bugs out. (This problem + doesn't exhibit itself without an extension, because in that case, + there's only one event generated by user activity, not two.) + */ + if (!until_idle_p && si->locked_p) + swallow_unlock_typeahead_events (si, &event.x_event); + else + while (XCheckMaskEvent (si->dpy, + (KeyPressMask|ButtonPressMask|PointerMotionMask), + &event.x_event)) + ; + + + if (si->check_pointer_timer_id) + { + XtRemoveTimeOut (si->check_pointer_timer_id); + si->check_pointer_timer_id = 0; + } + if (si->timer_id) + { + XtRemoveTimeOut (si->timer_id); + si->timer_id = 0; + } + + if (until_idle_p && si->cycle_id) /* no cycle timer when inactive */ + abort (); +} + + + +/* Some crap for dealing with /proc/interrupts. + + On Linux systems, it's possible to see the hardware interrupt count + associated with the keyboard. We can therefore use that as another method + of detecting idleness. + + Why is it a good idea to do this? Because it lets us detect keyboard + activity that is not associated with X events. For example, if the user + has switched to another virtual console, it's good for xscreensaver to not + be running graphics hacks on the (non-visible) X display. The common + complaint that checking /proc/interrupts addresses is that the user is + playing Quake on a non-X console, and the GL hacks are perceptibly slowing + the game... + + This is tricky for a number of reasons. + + * First, we must be sure to only do this when running on an X server that + is on the local machine (because otherwise, we'd be reacting to the + wrong keyboard.) The way we do this is by noting that the $DISPLAY is + pointing to display 0 on the local machine. It *could* be that display + 1 is also on the local machine (e.g., two X servers, each on a different + virtual-terminal) but it's also possible that screen 1 is an X terminal, + using this machine as the host. So we can't take that chance. + + * Second, one can only access these interrupt numbers in a completely + and utterly brain-damaged way. You would think that one would use an + ioctl for this. But no. The ONLY way to get this information is to + open the pseudo-file /proc/interrupts AS A FILE, and read the numbers + out of it TEXTUALLY. Because this is Unix, and all the world's a file, + and the only real data type is the short-line sequence of ASCII bytes. + + Now it's all well and good that the /proc/interrupts pseudo-file + exists; that's a clever idea, and a useful API for things that are + already textually oriented, like shell scripts, and users doing + interactive debugging sessions. But to make a *C PROGRAM* open a file + and parse the textual representation of integers out of it is just + insane. + + * Third, you can't just hold the file open, and fseek() back to the + beginning to get updated data! If you do that, the data never changes. + And I don't want to call open() every five seconds, because I don't want + to risk going to disk for any inodes. It turns out that if you dup() + it early, then each copy gets fresh data, so we can get around that in + this way (but for how many releases, one might wonder?) + + * Fourth, the format of the output of the /proc/interrupts file is + undocumented, and has changed several times already! In Linux 2.0.33, + even on a multiprocessor machine, it looks like this: + + 0: 309453991 timer + 1: 4771729 keyboard + + but in Linux 2.2 and 2.4 kernels with MP machines, it looks like this: + + CPU0 CPU1 + 0: 1671450 1672618 IO-APIC-edge timer + 1: 13037 13495 IO-APIC-edge keyboard + + and in Linux 2.6, it's gotten even goofier: now there are two lines + labelled "i8042". One of them is the keyboard, and one of them is + the PS/2 mouse -- and of course, you can't tell them apart, except + by wiggling the mouse and noting which one changes: + + CPU0 CPU1 + 1: 32051 30864 IO-APIC-edge i8042 + 12: 476577 479913 IO-APIC-edge i8042 + + Joy! So how are we expected to parse that? Well, this code doesn't + parse it: it saves the first line with the string "keyboard" (or + "i8042") in it, and does a string-comparison to note when it has + changed. If there are two "i8042" lines, we assume the first is + the keyboard and the second is the mouse (doesn't matter which is + which, really, as long as we don't compare them against each other.) + + Thanks to Nat Friedman for figuring out most of this crap. + + Note that if you have a serial or USB mouse, or a USB keyboard, it won't + detect it. That's because there's no way to tell the difference between a + serial mouse and a general serial port, and all USB devices look the same + from here. It would be somewhat unfortunate to have the screensaver turn + off when the modem on COM1 burped, or when a USB disk was accessed. + */ + + +#ifdef HAVE_PROC_INTERRUPTS + +#define PROC_INTERRUPTS "/proc/interrupts" + +Bool +query_proc_interrupts_available (saver_info *si, const char **why) +{ + /* We can use /proc/interrupts if $DISPLAY points to :0, and if the + "/proc/interrupts" file exists and is readable. + */ + FILE *f; + if (why) *why = 0; + + if (!display_is_on_console_p (si)) + { + if (why) *why = "not on primary console"; + return False; + } + + f = fopen (PROC_INTERRUPTS, "r"); + if (!f) + { + if (why) *why = "does not exist"; + return False; + } + + fclose (f); + return True; +} + + +static Bool +proc_interrupts_activity_p (saver_info *si) +{ + static FILE *f0 = 0; + FILE *f1 = 0; + int fd; + static char last_kbd_line[255] = { 0, }; + static char last_ptr_line[255] = { 0, }; + char new_line[sizeof(last_kbd_line)]; + Bool checked_kbd = False, kbd_changed = False; + Bool checked_ptr = False, ptr_changed = False; + int i8042_count = 0; + + if (!f0) + { + /* First time -- open the file. */ + f0 = fopen (PROC_INTERRUPTS, "r"); + if (!f0) + { + char buf[255]; + sprintf(buf, "%s: error opening %s", blurb(), PROC_INTERRUPTS); + perror (buf); + goto FAIL; + } + +# if defined(HAVE_FCNTL) && defined(FD_CLOEXEC) + /* Close this fd upon exec instead of inheriting / leaking it. */ + if (fcntl (fileno (f0), F_SETFD, FD_CLOEXEC) != 0) + perror ("fcntl: CLOEXEC:"); +# endif + } + + if (f0 == (FILE *) -1) /* means we got an error initializing. */ + return False; + + fd = dup (fileno (f0)); + if (fd < 0) + { + char buf[255]; + sprintf(buf, "%s: could not dup() the %s fd", blurb(), PROC_INTERRUPTS); + perror (buf); + goto FAIL; + } + + f1 = fdopen (fd, "r"); + if (!f1) + { + char buf[255]; + sprintf(buf, "%s: could not fdopen() the %s fd", blurb(), + PROC_INTERRUPTS); + perror (buf); + goto FAIL; + } + + /* Actually, I'm unclear on why this fseek() is necessary, given the timing + of the dup() above, but it is. */ + if (fseek (f1, 0, SEEK_SET) != 0) + { + char buf[255]; + sprintf(buf, "%s: error rewinding %s", blurb(), PROC_INTERRUPTS); + perror (buf); + goto FAIL; + } + + /* Now read through the pseudo-file until we find the "keyboard", + "PS/2 mouse", or "i8042" lines. */ + + while (fgets (new_line, sizeof(new_line)-1, f1)) + { + Bool i8042_p = !!strstr (new_line, "i8042"); + if (i8042_p) i8042_count++; + + if (strchr (new_line, ',')) + { + /* Ignore any line that has a comma on it: this is because + a setup like this: + + 12: 930935 XT-PIC usb-uhci, PS/2 Mouse + + is really bad news. It *looks* like we can note mouse + activity from that line, but really, that interrupt gets + fired any time any USB device has activity! So we have + to ignore any shared IRQs. + */ + } + else if (!checked_kbd && + (strstr (new_line, "keyboard") || + (i8042_p && i8042_count == 1))) + { + /* Assume the keyboard interrupt is the line that says "keyboard", + or the *first* line that says "i8042". + */ + kbd_changed = (*last_kbd_line && !!strcmp (new_line, last_kbd_line)); + strcpy (last_kbd_line, new_line); + checked_kbd = True; + } + else if (!checked_ptr && + (strstr (new_line, "PS/2 Mouse") || + (i8042_p && i8042_count == 2))) + { + /* Assume the mouse interrupt is the line that says "PS/2 mouse", + or the *second* line that says "i8042". + */ + ptr_changed = (*last_ptr_line && !!strcmp (new_line, last_ptr_line)); + strcpy (last_ptr_line, new_line); + checked_ptr = True; + } + + if (checked_kbd && checked_ptr) + break; + } + + if (checked_kbd || checked_ptr) + { + fclose (f1); + + if (si->prefs.debug_p && (kbd_changed || ptr_changed)) + fprintf (stderr, "%s: /proc/interrupts activity: %s\n", + blurb(), + ((kbd_changed && ptr_changed) ? "mouse and kbd" : + kbd_changed ? "kbd" : + ptr_changed ? "mouse" : "ERR")); + + return (kbd_changed || ptr_changed); + } + + + /* If we got here, we didn't find either a "keyboard" or a "PS/2 Mouse" + line in the file at all. */ + fprintf (stderr, "%s: no keyboard or mouse data in %s?\n", + blurb(), PROC_INTERRUPTS); + + FAIL: + if (f1) + fclose (f1); + + if (f0 && f0 != (FILE *) -1) + fclose (f0); + + f0 = (FILE *) -1; + return False; +} + +#endif /* HAVE_PROC_INTERRUPTS */ + + +/* This timer goes off every few minutes, whether the user is idle or not, + to try and clean up anything that has gone wrong. + + It calls disable_builtin_screensaver() so that if xset has been used, + or some other program (like xlock) has messed with the XSetScreenSaver() + settings, they will be set back to sensible values (if a server extension + is in use, messing with xlock can cause xscreensaver to never get a wakeup + event, and could cause monitor power-saving to occur, and all manner of + heinousness.) + + If the screen is currently blanked, it raises the window, in case some + other window has been mapped on top of it. + + If the screen is currently blanked, and there is no hack running, it + clears the window, in case there is an error message printed on it (we + don't want the error message to burn in.) + */ + +static void +watchdog_timer (XtPointer closure, XtIntervalId *id) +{ + saver_info *si = (saver_info *) closure; + saver_preferences *p = &si->prefs; + + disable_builtin_screensaver (si, False); + + /* If the DPMS settings on the server have changed, change them back to + what ~/.xscreensaver says they should be. */ + sync_server_dpms_settings (si->dpy, + (p->dpms_enabled_p && + p->mode != DONT_BLANK), + p->dpms_standby / 1000, + p->dpms_suspend / 1000, + p->dpms_off / 1000, + False); + + if (si->screen_blanked_p) + { + Bool running_p = screenhack_running_p (si); + + if (si->dbox_up_p) + { + if (si->prefs.debug_p) + fprintf (stderr, "%s: dialog box is up: not raising screen.\n", + blurb()); + } + else + { + if (si->prefs.debug_p) + fprintf (stderr, "%s: watchdog timer raising %sscreen.\n", + blurb(), (running_p ? "" : "and clearing ")); + + raise_window (si, True, True, running_p); + } + + if (screenhack_running_p (si) && + !monitor_powered_on_p (si)) + { + int i; + if (si->prefs.verbose_p) + fprintf (stderr, + "%s: X says monitor has powered down; " + "killing running hacks.\n", blurb()); + for (i = 0; i < si->nscreens; i++) + kill_screenhack (&si->screens[i]); + } + + /* Re-schedule this timer. The watchdog timer defaults to a bit less + than the hack cycle period, but is never longer than one hour. + */ + si->watchdog_id = 0; + reset_watchdog_timer (si, True); + } +} + + +void +reset_watchdog_timer (saver_info *si, Bool on_p) +{ + saver_preferences *p = &si->prefs; + + if (si->watchdog_id) + { + XtRemoveTimeOut (si->watchdog_id); + si->watchdog_id = 0; + } + + if (on_p && p->watchdog_timeout) + { + si->watchdog_id = XtAppAddTimeOut (si->app, p->watchdog_timeout, + watchdog_timer, (XtPointer) si); + + if (p->debug_p) + fprintf (stderr, "%s: restarting watchdog_timer (%ld, %ld)\n", + blurb(), p->watchdog_timeout, si->watchdog_id); + } +} + + +/* It's possible that a race condition could have led to the saver + window being unexpectedly still mapped. This can happen like so: + + - screen is blanked + - hack is launched + - that hack tries to grab a screen image (it does this by + first unmapping the saver window, then remapping it.) + - hack unmaps window + - hack waits + - user becomes active + - hack re-maps window (*) + - driver kills subprocess + - driver unmaps window (**) + + The race is that (*) might have been sent to the server before + the client process was killed, but, due to scheduling randomness, + might not have been received by the server until after (**). + In other words, (*) and (**) might happen out of order, meaning + the driver will unmap the window, and then after that, the + recently-dead client will re-map it. This leaves the user + locked out (it looks like a desktop, but it's not!) + + To avoid this: after un-blanking the screen, we launch a timer + that wakes up once a second for ten seconds, and makes damned + sure that the window is still unmapped. + */ + +void +de_race_timer (XtPointer closure, XtIntervalId *id) +{ + saver_info *si = (saver_info *) closure; + saver_preferences *p = &si->prefs; + int secs = 1; + + if (id == 0) /* if id is 0, this is the initialization call. */ + { + si->de_race_ticks = 10; + if (p->verbose_p) + fprintf (stderr, "%s: starting de-race timer (%d seconds.)\n", + blurb(), si->de_race_ticks); + } + else + { + int i; + XSync (si->dpy, False); + for (i = 0; i < si->nscreens; i++) + { + saver_screen_info *ssi = &si->screens[i]; + Window w = ssi->screensaver_window; + XWindowAttributes xgwa; + XGetWindowAttributes (si->dpy, w, &xgwa); + if (xgwa.map_state != IsUnmapped) + { + if (p->verbose_p) + fprintf (stderr, + "%s: %d: client race! emergency unmap 0x%lx.\n", + blurb(), i, (unsigned long) w); + XUnmapWindow (si->dpy, w); + } + else if (p->debug_p) + fprintf (stderr, "%s: %d: (de-race of 0x%lx is cool.)\n", + blurb(), i, (unsigned long) w); + } + XSync (si->dpy, False); + + si->de_race_ticks--; + } + + if (id && *id == si->de_race_id) + si->de_race_id = 0; + + if (si->de_race_id) abort(); + + if (si->de_race_ticks <= 0) + { + si->de_race_id = 0; + if (p->verbose_p) + fprintf (stderr, "%s: de-race completed.\n", blurb()); + } + else + { + si->de_race_id = XtAppAddTimeOut (si->app, secs * 1000, + de_race_timer, closure); + } +} diff --git a/driver/types.h b/driver/types.h new file mode 100644 index 00000000..3ab8506c --- /dev/null +++ b/driver/types.h @@ -0,0 +1,437 @@ +/* xscreensaver, Copyright (c) 1993-2011 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. + */ + +#ifndef __XSCREENSAVER_TYPES_H__ +#define __XSCREENSAVER_TYPES_H__ + +typedef struct saver_info saver_info; + +typedef enum { + ul_read, /* reading input or ready to do so */ + ul_success, /* auth success, unlock */ + ul_fail, /* auth fail */ + ul_cancel, /* user cancelled auth (pw_cancel or pw_null) */ + ul_time, /* timed out */ + ul_finished /* user pressed enter */ +} unlock_state; + +typedef struct screenhack screenhack; +struct screenhack { + Bool enabled_p; + char *visual; + char *name; + char *command; +}; + +typedef enum { + RANDOM_HACKS, ONE_HACK, BLANK_ONLY, DONT_BLANK, RANDOM_HACKS_SAME +} saver_mode; + +typedef enum { + TEXT_DATE, TEXT_LITERAL, TEXT_FILE, TEXT_PROGRAM, TEXT_URL +} text_mode; + +struct auth_message; +struct auth_response; + +typedef int (*auth_conv_cb_t) ( + int num_msg, + const struct auth_message *msg, + struct auth_response **resp, + saver_info *si); + +typedef struct saver_preferences saver_preferences; +typedef struct saver_screen_info saver_screen_info; +typedef struct passwd_dialog_data passwd_dialog_data; +typedef struct splash_dialog_data splash_dialog_data; +typedef struct _monitor monitor; + +typedef struct poll_mouse_data poll_mouse_data; +struct poll_mouse_data { + int root_x; + int root_y; + Window child; + unsigned int mask; + time_t time; +}; + +#ifdef HAVE_XINPUT +/* XInputExtension device support */ +#include + +typedef struct xinput_dev_info xinput_dev_info; +struct xinput_dev_info { + XDevice *device; + XEventClass press, release, valuator; + poll_mouse_data last_poll_mouse; +}; +#endif + +/* This structure holds all the user-specified parameters, read from the + command line, the resource database, or entered through a dialog box. + */ +struct saver_preferences { + + XrmDatabase db; /* The resource database into which the + init file is merged, and out of which the + preferences are parsed. */ + + time_t init_file_date; /* The date (from stat()) of the .xscreensaver + file the last time this process read or + wrote it. */ + + Bool verbose_p; /* whether to print out lots of status info */ + Bool timestamp_p; /* whether to mark messages with a timestamp */ + Bool capture_stderr_p; /* whether to redirect stdout/stderr */ + Bool ignore_uninstalled_p; /* whether to avoid displaying or complaining + about hacks that are not on $PATH */ + Bool debug_p; /* pay no mind to the man behind the curtain */ + Bool xsync_p; /* whether XSynchronize has been called */ + + Bool lock_p; /* whether to lock as well as save */ + + Bool fade_p; /* whether to fade to black, if possible */ + Bool unfade_p; /* whether to fade from black, if possible */ + Time fade_seconds; /* how long that should take */ + int fade_ticks; /* how many ticks should be used */ + Bool splash_p; /* whether to do a splash screen at startup */ + + Bool install_cmap_p; /* whether we should use our own colormap + when using the screen's default visual. */ + +# ifdef QUAD_MODE + Bool quad_p; /* whether to run four savers per monitor */ +# endif + + screenhack **screenhacks; /* the programs to run */ + int screenhacks_count; + + saver_mode mode; /* hack-selection mode */ + int selected_hack; /* in one_hack mode, this is the one */ + + int nice_inferior; /* nice value for subprocs */ + int inferior_memory_limit; /* setrlimit(LIMIT_AS) value for subprocs */ + + Time initial_delay; /* how long to sleep after launch */ + Time splash_duration; /* how long the splash screen stays up */ + Time timeout; /* how much idle time before activation */ + Time lock_timeout; /* how long after activation locking starts */ + Time cycle; /* how long each hack should run */ + Time passwd_timeout; /* how much time before pw dialog goes down */ + Time pointer_timeout; /* how often to check mouse position */ + Time notice_events_timeout; /* how long after window creation to select */ + Time watchdog_timeout; /* how often to re-raise and re-blank screen */ + int pointer_hysteresis; /* mouse motions less than N/sec are ignored */ + + Bool dpms_enabled_p; /* Whether to power down the monitor */ + Bool dpms_quickoff_p; /* Whether to power down monitor immediately + in "Blank Only" mode */ + Time dpms_standby; /* how long until monitor goes black */ + Time dpms_suspend; /* how long until monitor power-saves */ + Time dpms_off; /* how long until monitor powers down */ + + Bool grab_desktop_p; /* These are not used by "xscreensaver" */ + Bool grab_video_p; /* itself: they are used by the external */ + Bool random_image_p; /* "xscreensaver-getimage" program, and set */ + char *image_directory; /* by the "xscreensaver-demo" configurator. */ + + text_mode tmode; /* How we generate text to display. */ + char *text_literal; /* used when tmode is TEXT_LITERAL. */ + char *text_file; /* used when tmode is TEXT_FILE. */ + char *text_program; /* used when tmode is TEXT_PROGRAM. */ + char *text_url; /* used when tmode is TEXT_URL. */ + + Bool use_xidle_extension; /* which extension to use, if possible */ + Bool use_mit_saver_extension; + Bool use_sgi_saver_extension; + Bool use_proc_interrupts; + Bool use_xinput_extension; + + Bool getviewport_full_of_lies_p; /* XFree86 bug #421 */ + + char *shell; /* where to find /bin/sh */ + + char *demo_command; /* How to enter demo mode. */ + char *prefs_command; /* How to edit preferences. */ + char *help_url; /* Where the help document resides. */ + char *load_url_command; /* How one loads URLs. */ + char *new_login_command; /* Command for the "New Login" button. */ +}; + +/* This structure holds all the data that applies to the program as a whole, + or to the non-screen-specific parts of the display connection. + + The saver_preferences structure (prefs.h) holds all the user-specified + parameters, read from the command line, the resource database, or entered + through a dialog box. + */ +struct saver_info { + char *version; + saver_preferences prefs; + + int nscreens; + int ssi_count; + saver_screen_info *screens; + saver_screen_info *default_screen; /* ...on which dialogs will appear. */ + monitor **monitor_layout; /* private to screens.c */ + Visual **best_gl_visuals; /* visuals for GL hacks on screen N */ + + /* ======================================================================= + global connection info + ======================================================================= */ + + XtAppContext app; + Display *dpy; + + /* ======================================================================= + server extension info + ======================================================================= */ + + Bool using_xidle_extension; /* which extension is being used. */ + Bool using_mit_saver_extension; /* Note that `p->use_*' is the *request*, */ + Bool using_sgi_saver_extension; /* and `si->using_*' is the *reality*. */ + Bool using_proc_interrupts; + +# ifdef HAVE_MIT_SAVER_EXTENSION + int mit_saver_ext_event_number; + int mit_saver_ext_error_number; +# endif +# ifdef HAVE_SGI_SAVER_EXTENSION + int sgi_saver_ext_event_number; + int sgi_saver_ext_error_number; +# endif +# ifdef HAVE_RANDR + int randr_event_number; + int randr_error_number; + Bool using_randr_extension; +# endif + + Bool using_xinput_extension; /* Note that `p->use_*' is the *request*, */ + /* and `si->using_*' is the *reality*. */ +#ifdef HAVE_XINPUT + int xinput_ext_event_number; /* may not be used */ + int xinput_ext_error_number; + int xinput_DeviceButtonPress; /* Extension device event codes. */ + int xinput_DeviceButtonRelease; /* Assigned by server at runtime */ + int xinput_DeviceMotionNotify; + xinput_dev_info *xinput_devices; + int num_xinput_devices; +# endif + + /* ======================================================================= + blanking + ======================================================================= */ + + Bool screen_blanked_p; /* Whether the saver is currently active. */ + Window mouse_grab_window; /* Window holding our mouse grab */ + Window keyboard_grab_window; /* Window holding our keyboard grab */ + int mouse_grab_screen; /* The screen number the mouse grab is on */ + int keyboard_grab_screen; /* The screen number the keyboard grab is on */ + Bool fading_possible_p; /* Whether fading to/from black is possible. */ + Bool throttled_p; /* Whether we should temporarily just blank + the screen, not run hacks. (Deprecated: + users should use "xset dpms force off" + instead.) */ + time_t blank_time; /* The time at which the screen was blanked + (if currently blanked) or unblanked (if + not blanked.) */ + + + /* ======================================================================= + locking and runtime privileges + ======================================================================= */ + + Bool locked_p; /* Whether the screen is currently locked. */ + Bool dbox_up_p; /* Whether the demo-mode or passwd dialogs + are currently visible */ + + Bool locking_disabled_p; /* Sometimes locking is impossible. */ + char *nolock_reason; /* This is why. */ + + char *orig_uid; /* What uid/gid we had at startup, before + discarding privileges. */ + char *uid_message; /* Any diagnostics from our attempt to + discard privileges (printed only in + -verbose mode.) */ + Bool dangerous_uid_p; /* Set to true if we're running as a user id + which is known to not be a normal, non- + privileged user. */ + + Window passwd_dialog; /* The password dialog, if it's up. */ + passwd_dialog_data *pw_data; /* Other info necessary to draw it. */ + + int unlock_failures; /* Counts failed login attempts while the + screen is locked. */ + + char *unlock_typeahead; /* If the screen is locked, and the user types + a character, we assume that it is the first + character of the password. It's stored here + for the password dialog to use to populate + itself. */ + + char *user; /* The user whose session is locked. */ + char *cached_passwd; /* Cached password, used to avoid multiple + prompts for password-only auth mechanisms.*/ + unlock_state unlock_state; + + auth_conv_cb_t unlock_cb; /* The function used to prompt for creds. */ + void (*auth_finished_cb) (saver_info *si); + /* Called when authentication has finished, + regardless of success or failure. + May be NULL. */ + + + /* ======================================================================= + demoing + ======================================================================= */ + + Bool demoing_p; /* Whether we are demoing a single hack + (without UI.) */ + + Window splash_dialog; /* The splash dialog, if its up. */ + splash_dialog_data *sp_data; /* Other info necessary to draw it. */ + + + /* ======================================================================= + timers + ======================================================================= */ + + XtIntervalId lock_id; /* Timer to implement `prefs.lock_timeout' */ + XtIntervalId cycle_id; /* Timer to implement `prefs.cycle' */ + XtIntervalId timer_id; /* Timer to implement `prefs.timeout' */ + XtIntervalId watchdog_id; /* Timer to implement `prefs.watchdog */ + XtIntervalId check_pointer_timer_id; /* `prefs.pointer_timeout' */ + + XtIntervalId de_race_id; /* Timer to make sure screen un-blanks */ + int de_race_ticks; + + time_t last_activity_time; /* Used only when no server exts. */ + time_t last_wall_clock_time; /* Used to detect laptop suspend. */ + saver_screen_info *last_activity_screen; + + Bool emergency_lock_p; /* Set when the wall clock has jumped + (presumably due to laptop suspend) and we + need to lock down right away instead of + waiting for the lock timer to go off. */ + + + /* ======================================================================= + remote control + ======================================================================= */ + + int selection_mode; /* Set to -1 if the NEXT ClientMessage has just + been received; set to -2 if PREV has just + been received; set to N if SELECT or DEMO N + has been received. (This is kind of nasty.) + */ + + /* ======================================================================= + subprocs + ======================================================================= */ + + XtIntervalId stderr_popup_timer; + +}; + +/* This structure holds all the data that applies to the screen-specific parts + of the display connection; if the display has multiple screens, there will + be one of these for each screen. + */ +struct saver_screen_info { + saver_info *global; + + int number; /* The internal ordinal of this screen, + counting Xinerama rectangles as separate + screens. */ + int real_screen_number; /* The number of the underlying X screen on + which this rectangle lies. */ + Screen *screen; /* The X screen in question. */ + + int x, y, width, height; /* The size and position of this rectangle + on its underlying X screen. */ + + Bool real_screen_p; /* This will be true of exactly one ssi per + X screen. */ + + Widget toplevel_shell; + + /* ======================================================================= + blanking + ======================================================================= */ + + Window screensaver_window; /* The window that will impersonate the root, + when the screensaver activates. Note that + the window stored here may change, as we + destroy and recreate it on different + visuals. */ + Colormap cmap; /* The colormap that goes with the window. */ + Bool install_cmap_p; /* Whether this screen should have its own + colormap installed, for whichever of several + reasons. This is definitive (even a false + value here overrides prefs->install_cmap_p.) + */ + Visual *current_visual; /* The visual of the window. */ + int current_depth; /* How deep the visual (and the window) are. */ + + Visual *default_visual; /* visual to use when none other specified */ + + Window real_vroot; /* The original virtual-root window. */ + Window real_vroot_value; /* What was in the __SWM_VROOT property. */ + + Cursor cursor; /* A blank cursor that goes with the + real root window. */ + unsigned long black_pixel; /* Black, allocated from `cmap'. */ + + int blank_vp_x, blank_vp_y; /* Where the virtual-scrolling viewport was + when the screen went blank. We need to + prevent the X server from letting the mouse + bump the edges to scroll while the screen + is locked, so we reset to this when it has + moved, and the lock dialog is up... */ + +# ifdef HAVE_MIT_SAVER_EXTENSION + Window server_mit_saver_window; +# endif + + + /* ======================================================================= + demoing + ======================================================================= */ + + Colormap demo_cmap; /* The colormap that goes with the dialogs: + this might be the same as `cmap' so care + must be taken not to free it while it's + still in use. */ + + /* ======================================================================= + timers + ======================================================================= */ + + poll_mouse_data last_poll_mouse; /* Used only when no server exts. */ + + /* ======================================================================= + subprocs + ======================================================================= */ + + int current_hack; /* Index into `prefs.screenhacks' */ + pid_t pid; + + int stderr_text_x; + int stderr_text_y; + int stderr_line_height; + XFontStruct *stderr_font; + GC stderr_gc; + Window stderr_overlay_window; /* Used if the server has overlay planes */ + Colormap stderr_cmap; +}; + + +#endif /* __XSCREENSAVER_TYPES_H__ */ diff --git a/driver/vms-getpwnam.c b/driver/vms-getpwnam.c new file mode 100644 index 00000000..ec0650c9 --- /dev/null +++ b/driver/vms-getpwnam.c @@ -0,0 +1,129 @@ +/* + * getpwnam(name) - retrieves a UAF entry + * + * Author: Patrick L. Mahan + * Location: TGV, Inc + * Date: 15-Nov-1991 + * + * Purpose: Provides emulation for the UNIX getpwname routine. + * + * Modification History + * + * Date | Who | Version | Reason + * ------------+-----------+---------------+--------------------------- + * 15-Nov-1991 | PLM | 1.0 | First Write + */ + +#define PASSWDROUTINES + +#include +#include +#include +#include +#include +#include +#include "vms-pwd.h" + +struct uic { + unsigned short uid; + unsigned short gid; +}; + +#define TEST(ptr, str) { if (ptr == NULL) { \ + fprintf(stderr, "getpwnam: memory allocation failure for \"%s\"\n", \ + str); \ + return ((struct passwd *)(NULL)); \ + } } + +struct passwd *getpwnam(name) +char *name; +{ + int istatus; + int UserNameLen; + int UserOwnerLen; + int UserDeviceLen; + int UserDirLen; + static char UserName[13]; + static char UserOwner[32]; + static char UserDevice[32]; + static char UserDir[64]; + char *cptr, *sptr; + unsigned long int UserPwd[2]; + unsigned short int UserSalt; + unsigned long int UserEncrypt; + struct uic UicValue; + struct passwd *entry; + + struct dsc$descriptor_s VMSNAME = + {strlen(name), DSC$K_DTYPE_T, DSC$K_CLASS_S, name}; + + struct itmlist3 { + unsigned short int length; + unsigned short int item; + unsigned long int addr; + unsigned long int retaddr; + } ItemList[] = { + {12, UAI$_USERNAME, (unsigned long)&UserName, (unsigned long)&UserNameLen}, + {8, UAI$_PWD, (unsigned long)&UserPwd, 0}, + {4, UAI$_UIC, (unsigned long)&UicValue, 0}, + {32, UAI$_OWNER, (unsigned long)&UserOwner, (unsigned long)&UserOwnerLen}, + {32, UAI$_DEFDEV, (unsigned long)&UserDevice, (unsigned long)&UserDeviceLen}, + {64, UAI$_DEFDIR, (unsigned long)&UserDir, (unsigned long)&UserDirLen}, + {2, UAI$_SALT, (unsigned long)&UserSalt, 0}, + {4, UAI$_ENCRYPT, (unsigned long)&UserEncrypt, 0}, + {0, 0, 0, 0} + }; + + UserNameLen = 0; + istatus = sys$getuai (0, 0, &VMSNAME, &ItemList, 0, 0, 0); + + if (!(istatus & 1)) { + fprintf (stderr, "getpwnam: unable to retrieve passwd entry for %s\n", + name); + fprintf (stderr, "getpwnam: vms error number is 0x%x\n", istatus); + return ((struct passwd *)NULL); + } + + entry = (struct passwd *) calloc (1, sizeof(struct passwd)); + TEST(entry, "PASSWD_ENTRY"); + + entry->pw_uid = UicValue.uid; + entry->pw_gid = UicValue.gid; + entry->pw_salt = UserSalt; + entry->pw_encrypt = UserEncrypt; + + sptr = UserName; + cptr = calloc (UserNameLen+1, sizeof(char)); + TEST(cptr, "USERNAME"); + strncpy (cptr, sptr, UserNameLen); + cptr[UserNameLen] = '\0'; + entry->pw_name = cptr; + + cptr = calloc(8, sizeof(char)); + TEST(cptr, "PASSWORD"); + memcpy(cptr, UserPwd, 8); + entry->pw_passwd = cptr; + + sptr = UserOwner; sptr++; + cptr = calloc ((int)UserOwner[0]+1, sizeof(char)); + TEST(cptr, "FULLNAME"); + strncpy (cptr, sptr, (int)UserOwner[0]); + cptr[(int)UserOwner[0]] = '\0'; + entry->pw_gecos = cptr; + + cptr = calloc ((int)UserDevice[0]+(int)UserDir[0]+1, sizeof(char)); + TEST(cptr, "HOME"); + sptr = UserDevice; sptr++; + strncpy (cptr, sptr, (int)UserDevice[0]); + sptr = UserDir; sptr++; + strncat (cptr, sptr, (int)UserDir[0]); + cptr[(int)UserDevice[0]+(int)UserDir[0]] = '\0'; + entry->pw_dir = cptr; + + cptr = calloc (strlen("SYS$SYSTEM:LOGINOUT.EXE")+1, sizeof(char)); + TEST(cptr,"SHELL"); + strcpy (cptr, "SYS$SYSTEM:LOGINOUT.EXE"); + entry->pw_shell = cptr; + + return (entry); +} diff --git a/driver/vms-hpwd.c b/driver/vms-hpwd.c new file mode 100644 index 00000000..707e3ea5 --- /dev/null +++ b/driver/vms-hpwd.c @@ -0,0 +1,75 @@ +/* + * VAX/VMS Password hashing routines: + * + * uses the System Service SYS$HASH_PASSWORD + * + * 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. + * + */ + +#include +#include +#include +#include +/* + * Hashing routine + */ +hash_vms_password(output_buf,input_buf,input_length,username,encryption_type,salt) +char *output_buf; +char *input_buf; +int input_length; +char *username; +int encryption_type; +unsigned short salt; +{ + struct dsc$descriptor_s password; + struct dsc$descriptor_s user; + + /* + * Check the VMS Version. If this is V5.4 or later, then + * we can use the new system service SYS$HASH_PASSWORD. Else + * fail and return garbage. + */ + + static char VMS_Version[32]; + struct { + unsigned short int Size; + unsigned short int Code; + char *Buffer; + unsigned short int *Resultant_Size; + } Item_List[2]={32, SYI$_VERSION, VMS_Version, 0, 0, 0}; + struct {int Size; char *Ptr;} Descr1; + + /* + * Get the information + */ + sys$getsyiw(0,0,0,Item_List,0,0,0); + /* + * Call the old routine if this isn't V5.4 or later... + */ +#ifndef __DECC + if ((VMS_Version[1] < '5') || + ((VMS_Version[1] == '5') && (VMS_Version[3] < '4'))) { + printf("Unsupported OS version\n"); + return(1); + } +#endif /* !__DECC */ + /* + * Call the SYS$HASH_PASSWORD system service... + */ + password.dsc$b_dtype = DSC$K_DTYPE_T; + password.dsc$b_class = DSC$K_CLASS_S; + password.dsc$w_length = input_length; + password.dsc$a_pointer = input_buf; + user.dsc$b_dtype = DSC$K_DTYPE_T; + user.dsc$b_class = DSC$K_CLASS_S; + user.dsc$w_length = strlen(username); + user.dsc$a_pointer = username; + sys$hash_password (&password, encryption_type, salt, &user, output_buf); +} diff --git a/driver/vms-pwd.h b/driver/vms-pwd.h new file mode 100644 index 00000000..6cb73d3e --- /dev/null +++ b/driver/vms-pwd.h @@ -0,0 +1,48 @@ +/* @(#)pwd.h 1.7 89/08/24 SMI; from S5R2 1.1 */ + +#ifndef __pwd_h +#define __pwd_h + +#ifdef vax11c +#include +#else +#include +#endif /* vax11c */ + +#ifdef PASSWDROUTINES +#define EXTERN +#else +#define EXTERN extern +#endif /* PASSWDROUTINES */ + +struct passwd { + char *pw_name; + char *pw_passwd; + int pw_uid; + int pw_gid; + short pw_salt; + int pw_encrypt; + char *pw_age; + char *pw_comment; + char *pw_gecos; + char *pw_dir; + char *pw_shell; +}; + + +#ifndef _POSIX_SOURCE +extern struct passwd *getpwent(); + +struct comment { + char *c_dept; + char *c_name; + char *c_acct; + char *c_bin; +}; + +#endif + +EXTERN struct passwd *getpwuid(/* uid_t uid */); +EXTERN struct passwd *getpwnam(/* char *name */); + +#endif /* !__pwd_h */ diff --git a/driver/vms-validate.c b/driver/vms-validate.c new file mode 100644 index 00000000..8f7141d6 --- /dev/null +++ b/driver/vms-validate.c @@ -0,0 +1,75 @@ +/* + * validate a password for a user + * + * 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. + */ + +/* + * Includes + */ +#include +#include +#include + +#include "vms-pwd.h" +int hash_vms_password(char *output_buf,char *input_buf,int input_length, + char *username,int encryption_type,unsigned short salt); + +/* + * + * Validate a VMS UserName/Password pair. + * + */ + +int validate_user(name,password) +char *name; +char *password; +{ + char password_buf[64]; + char username_buf[31]; + char encrypt_buf[8]; + register int i; + register char *cp,*cp1; + struct passwd *user_entry; + + /* + * Get the users UAF entry + */ + user_entry = getpwnam(name); + + /* + * If user_entry == NULL then we got a bad error + * return -1 to indicate a bad error + */ + if (user_entry == NULL) return (-1); + + /* + * Uppercase the password + */ + cp = password; + cp1 = password_buf; + while (*cp) + if (islower(*cp)) + *cp1++ = toupper(*cp++); + else + *cp1++ = *cp++; + /* + * Get the length of the password + */ + i = strlen(password); + /* + * Encrypt the password + */ + hash_vms_password(encrypt_buf,password_buf,i,user_entry->pw_name, + user_entry->pw_encrypt, user_entry->pw_salt); + if (memcmp(encrypt_buf,user_entry->pw_passwd,8) == 0) + return(1); + else return(0); +} + diff --git a/driver/vms_axp.opt b/driver/vms_axp.opt new file mode 100644 index 00000000..04d465df --- /dev/null +++ b/driver/vms_axp.opt @@ -0,0 +1,5 @@ +[-.UTILS]UTILS.OLB_AXP/LIB +SYS$SHARE:DECW$XMLIBSHR.EXE/SHARE +SYS$SHARE:DECW$XMULIBSHR.EXE/SHARE +SYS$SHARE:DECW$XTSHR.EXE/SHARE +SYS$SHARE:DECW$XLIBSHR.EXE/SHARE diff --git a/driver/vms_axp_12.opt b/driver/vms_axp_12.opt new file mode 100644 index 00000000..25dd1f18 --- /dev/null +++ b/driver/vms_axp_12.opt @@ -0,0 +1,5 @@ +[-.UTILS]UTILS.OLB_AXP/LIB +SYS$SHARE:DECW$XMLIBSHR12.EXE/SHARE +SYS$SHARE:DECW$XMULIBSHRR5.EXE/SHARE +SYS$SHARE:DECW$XTLIBSHRR5.EXE/SHARE +SYS$SHARE:DECW$XLIBSHR.EXE/SHARE diff --git a/driver/vms_decc.opt b/driver/vms_decc.opt new file mode 100644 index 00000000..65bec033 --- /dev/null +++ b/driver/vms_decc.opt @@ -0,0 +1,5 @@ +[-.UTILS]UTILS.OLB_DECC/LIB +SYS$SHARE:DECW$XMLIBSHR.EXE/SHARE +SYS$SHARE:DECW$XMULIBSHR.EXE/SHARE +SYS$SHARE:DECW$XTSHR.EXE/SHARE +SYS$SHARE:DECW$XLIBSHR.EXE/SHARE diff --git a/driver/vms_decc_12.opt b/driver/vms_decc_12.opt new file mode 100644 index 00000000..fdd9a802 --- /dev/null +++ b/driver/vms_decc_12.opt @@ -0,0 +1,5 @@ +[-.UTILS]UTILS.OLB_DECC/LIB +SYS$SHARE:DECW$XMLIBSHR12.EXE/SHARE +SYS$SHARE:DECW$XMULIBSHRR5.EXE/SHARE +SYS$SHARE:DECW$XTLIBSHRR5.EXE/SHARE +SYS$SHARE:DECW$XLIBSHR.EXE/SHARE diff --git a/driver/windows.c b/driver/windows.c new file mode 100644 index 00000000..2bdc146c --- /dev/null +++ b/driver/windows.c @@ -0,0 +1,2001 @@ +/* windows.c --- turning the screen black; dealing with visuals, virtual roots. + * xscreensaver, Copyright (c) 1991-2011 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. + */ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#ifdef VMS +# include /* for getpid() */ +# include "vms-gtod.h" /* for gettimeofday() */ +#endif /* VMS */ + +#ifndef VMS +# include /* for getpwuid() */ +#else /* VMS */ +# include "vms-pwd.h" +#endif /* VMS */ + +#ifdef HAVE_UNAME +# include /* for uname() */ +#endif /* HAVE_UNAME */ + +#include +/* #include / * for CARD32 */ +#include +#include /* for XSetClassHint() */ +#include +#include /* for time() */ +#include /* for the signal names */ +#include +#include + +/* You might think that to store an array of 32-bit quantities onto a + server-side property, you would pass an array of 32-bit data quantities + into XChangeProperty(). You would be wrong. You have to use an array + of longs, even if long is 64 bits (using 32 of each 64.) + */ +typedef long PROP32; + +#ifdef HAVE_MIT_SAVER_EXTENSION +# include +#endif /* HAVE_MIT_SAVER_EXTENSION */ + +#ifdef HAVE_XF86VMODE +# include +#endif /* HAVE_XF86VMODE */ + +#ifdef HAVE_XINERAMA +# include +#endif /* HAVE_XINERAMA */ + +/* This file doesn't need the Xt headers, so stub these types out... */ +#undef XtPointer +#define XtAppContext void* +#define XrmDatabase void* +#define XtIntervalId void* +#define XtPointer void* +#define Widget void* + +#include "xscreensaver.h" +#include "visual.h" +#include "fade.h" + + +extern int kill (pid_t, int); /* signal() is in sys/signal.h... */ + +Atom XA_VROOT, XA_XSETROOT_ID, XA_ESETROOT_PMAP_ID, XA_XROOTPMAP_ID; +Atom XA_SCREENSAVER, XA_SCREENSAVER_VERSION, XA_SCREENSAVER_ID; +Atom XA_SCREENSAVER_STATUS; + + +extern saver_info *global_si_kludge; /* I hate C so much... */ + +static void maybe_transfer_grabs (saver_screen_info *ssi, + Window old_w, Window new_w, int new_screen); + +#define ALL_POINTER_EVENTS \ + (ButtonPressMask | ButtonReleaseMask | EnterWindowMask | \ + LeaveWindowMask | PointerMotionMask | PointerMotionHintMask | \ + Button1MotionMask | Button2MotionMask | Button3MotionMask | \ + Button4MotionMask | Button5MotionMask | ButtonMotionMask) + + +static const char * +grab_string(int status) +{ + switch (status) + { + case GrabSuccess: return "GrabSuccess"; + case AlreadyGrabbed: return "AlreadyGrabbed"; + case GrabInvalidTime: return "GrabInvalidTime"; + case GrabNotViewable: return "GrabNotViewable"; + case GrabFrozen: return "GrabFrozen"; + default: + { + static char foo[255]; + sprintf(foo, "unknown status: %d", status); + return foo; + } + } +} + +static int +grab_kbd(saver_info *si, Window w, int screen_no) +{ + saver_preferences *p = &si->prefs; + int status = XGrabKeyboard (si->dpy, w, True, + /* I don't really understand Sync vs Async, + but these seem to work... */ + GrabModeSync, GrabModeAsync, + CurrentTime); + if (status == GrabSuccess) + { + si->keyboard_grab_window = w; + si->keyboard_grab_screen = screen_no; + } + + if (p->verbose_p) + fprintf(stderr, "%s: %d: grabbing keyboard on 0x%lx... %s.\n", + blurb(), screen_no, (unsigned long) w, grab_string(status)); + return status; +} + + +static int +grab_mouse (saver_info *si, Window w, Cursor cursor, int screen_no) +{ + saver_preferences *p = &si->prefs; + int status = XGrabPointer (si->dpy, w, True, ALL_POINTER_EVENTS, + GrabModeAsync, GrabModeAsync, w, + cursor, CurrentTime); + if (status == GrabSuccess) + { + si->mouse_grab_window = w; + si->mouse_grab_screen = screen_no; + } + + if (p->verbose_p) + fprintf(stderr, "%s: %d: grabbing mouse on 0x%lx... %s.\n", + blurb(), screen_no, (unsigned long) w, grab_string(status)); + return status; +} + + +static void +ungrab_kbd(saver_info *si) +{ + saver_preferences *p = &si->prefs; + XUngrabKeyboard(si->dpy, CurrentTime); + if (p->verbose_p) + fprintf(stderr, "%s: %d: ungrabbing keyboard (was 0x%lx).\n", + blurb(), si->keyboard_grab_screen, + (unsigned long) si->keyboard_grab_window); + si->keyboard_grab_window = 0; +} + + +static void +ungrab_mouse(saver_info *si) +{ + saver_preferences *p = &si->prefs; + XUngrabPointer(si->dpy, CurrentTime); + if (p->verbose_p) + fprintf(stderr, "%s: %d: ungrabbing mouse (was 0x%lx).\n", + blurb(), si->mouse_grab_screen, + (unsigned long) si->mouse_grab_window); + si->mouse_grab_window = 0; +} + + +/* Apparently there is this program called "rdesktop" which is a windows + terminal server client for Unix. It would seem that this program holds + the keyboard GRABBED the whole time it has focus! This is, of course, + completely idiotic: the whole point of grabbing is to get events when + you do *not* have focus, so grabbing *only when* you have focus is + completely redundant -- unless your goal is to make xscreensaver not + able to ever lock the screen when your program is running. + + If xscreensaver blanks while rdesktop still has a keyboard grab, then + when we try to prompt for the password, we won't get the characters: + they'll be typed into rdesktop. + + Perhaps rdesktop will release its keyboard grab if it loses focus? + What the hell, let's give it a try. If we fail to grab the keyboard + four times in a row, we forcibly set focus to "None" and try four + more times. (We don't touch focus unless we're already having a hard + time getting a grab.) + */ +static void +nuke_focus (saver_info *si, int screen_no) +{ + saver_preferences *p = &si->prefs; + Window focus = 0; + int rev = 0; + + XGetInputFocus (si->dpy, &focus, &rev); + + if (p->verbose_p) + { + char w[255], r[255]; + + if (focus == PointerRoot) strcpy (w, "PointerRoot"); + else if (focus == None) strcpy (w, "None"); + else sprintf (w, "0x%lx", (unsigned long) focus); + + if (rev == RevertToParent) strcpy (r, "RevertToParent"); + else if (rev == RevertToPointerRoot) strcpy (r, "RevertToPointerRoot"); + else if (rev == RevertToNone) strcpy (r, "RevertToNone"); + else sprintf (r, "0x%x", rev); + + fprintf (stderr, "%s: %d: removing focus from %s / %s.\n", + blurb(), screen_no, w, r); + } + + XSetInputFocus (si->dpy, None, RevertToNone, CurrentTime); + XSync (si->dpy, False); +} + + +static void +ungrab_keyboard_and_mouse (saver_info *si) +{ + ungrab_mouse (si); + ungrab_kbd (si); +} + + +static Bool +grab_keyboard_and_mouse (saver_info *si, Window window, Cursor cursor, + int screen_no) +{ + Status mstatus = 0, kstatus = 0; + int i; + int retries = 4; + Bool focus_fuckus = False; + + AGAIN: + + for (i = 0; i < retries; i++) + { + XSync (si->dpy, False); + kstatus = grab_kbd (si, window, screen_no); + if (kstatus == GrabSuccess) + break; + + /* else, wait a second and try to grab again. */ + sleep (1); + } + + if (kstatus != GrabSuccess) + { + fprintf (stderr, "%s: couldn't grab keyboard! (%s)\n", + blurb(), grab_string(kstatus)); + + if (! focus_fuckus) + { + focus_fuckus = True; + nuke_focus (si, screen_no); + goto AGAIN; + } + } + + for (i = 0; i < retries; i++) + { + XSync (si->dpy, False); + mstatus = grab_mouse (si, window, cursor, screen_no); + if (mstatus == GrabSuccess) + break; + + /* else, wait a second and try to grab again. */ + sleep (1); + } + + if (mstatus != GrabSuccess) + fprintf (stderr, "%s: couldn't grab pointer! (%s)\n", + blurb(), grab_string(mstatus)); + + + /* When should we allow blanking to proceed? The current theory + is that a keyboard grab is mandatory; a mouse grab is optional. + + - If we don't have a keyboard grab, then we won't be able to + read a password to unlock, so the kbd grab is mandatory. + (We can't conditionalize this on locked_p, because someone + might run "xscreensaver-command -lock" at any time.) + + - If we don't have a mouse grab, then we might not see mouse + clicks as a signal to unblank -- but we will still see kbd + activity, so that's not a disaster. + + It has been suggested that we should allow blanking if locking + is disabled, and we have a mouse grab but no keyboard grab + (that is: kstatus != GrabSuccess && + mstatus == GrabSuccess && + si->locking_disabled_p) + That would allow screen blanking (but not locking) while the gdm + login screen had the keyboard grabbed, but one would have to use + the mouse to unblank. Keyboard characters would go to the gdm + login field without unblanking. I have not made this change + because I'm not completely convinced it is a safe thing to do. + */ + + if (kstatus != GrabSuccess) /* Do not blank without a kbd grab. */ + { + /* If we didn't get both grabs, release the one we did get. */ + ungrab_keyboard_and_mouse (si); + return False; + } + + return True; /* Grab is good, go ahead and blank. */ +} + + +int +move_mouse_grab (saver_info *si, Window to, Cursor cursor, int to_screen_no) +{ + Window old = si->mouse_grab_window; + + if (old == 0) + return grab_mouse (si, to, cursor, to_screen_no); + else + { + saver_preferences *p = &si->prefs; + int status; + + XSync (si->dpy, False); + XGrabServer (si->dpy); /* ############ DANGER! */ + XSync (si->dpy, False); + + if (p->verbose_p) + fprintf(stderr, "%s: grabbing server...\n", blurb()); + + ungrab_mouse (si); + status = grab_mouse (si, to, cursor, to_screen_no); + + if (status != GrabSuccess) /* Augh! */ + { + sleep (1); /* Note dramatic evil of sleeping + with server grabbed. */ + XSync (si->dpy, False); + status = grab_mouse (si, to, cursor, to_screen_no); + } + + if (status != GrabSuccess) /* Augh! Try to get the old one back... */ + grab_mouse (si, old, cursor, to_screen_no); + + XUngrabServer (si->dpy); + XSync (si->dpy, False); /* ###### (danger over) */ + + if (p->verbose_p) + fprintf(stderr, "%s: ungrabbing server.\n", blurb()); + + return status; + } +} + + +/* Prints an error message to stderr and returns True if there is another + xscreensaver running already. Silently returns False otherwise. */ +Bool +ensure_no_screensaver_running (Display *dpy, Screen *screen) +{ + Bool status = 0; + int i; + Window root = RootWindowOfScreen (screen); + Window root2, parent, *kids; + unsigned int nkids; + XErrorHandler old_handler = XSetErrorHandler (BadWindow_ehandler); + + if (! XQueryTree (dpy, root, &root2, &parent, &kids, &nkids)) + abort (); + if (root != root2) + abort (); + if (parent) + abort (); + for (i = 0; i < nkids; i++) + { + Atom type; + int format; + unsigned long nitems, bytesafter; + unsigned char *version; + + if (XGetWindowProperty (dpy, kids[i], XA_SCREENSAVER_VERSION, 0, 1, + False, XA_STRING, &type, &format, &nitems, + &bytesafter, &version) + == Success + && type != None) + { + unsigned char *id; + if (!XGetWindowProperty (dpy, kids[i], XA_SCREENSAVER_ID, 0, 512, + False, XA_STRING, &type, &format, &nitems, + &bytesafter, &id) + == Success + || type == None) + id = (unsigned char *) "???"; + + fprintf (stderr, + "%s: already running on display %s (window 0x%x)\n from process %s.\n", + blurb(), DisplayString (dpy), (int) kids [i], + (char *) id); + status = True; + } + + else if (XGetWindowProperty (dpy, kids[i], XA_WM_COMMAND, 0, 128, + False, XA_STRING, &type, &format, &nitems, + &bytesafter, &version) + == Success + && type != None + && !strcmp ((char *) version, "gnome-screensaver")) + { + fprintf (stderr, + "%s: \"%s\" is already running on display %s (window 0x%x)\n", + blurb(), (char *) version, + DisplayString (dpy), (int) kids [i]); + status = True; + break; + } + } + + if (kids) XFree ((char *) kids); + XSync (dpy, False); + XSetErrorHandler (old_handler); + return status; +} + + + +/* Virtual-root hackery */ + +#ifdef _VROOT_H_ +ERROR! You must not include vroot.h in this file. +#endif + +static void +store_vroot_property (Display *dpy, Window win, Window value) +{ +#if 0 + if (p->verbose_p) + fprintf (stderr, + "%s: storing XA_VROOT = 0x%x (%s) = 0x%x (%s)\n", blurb(), + win, + (win == screensaver_window ? "ScreenSaver" : + (win == real_vroot ? "VRoot" : + (win == real_vroot_value ? "Vroot_value" : "???"))), + value, + (value == screensaver_window ? "ScreenSaver" : + (value == real_vroot ? "VRoot" : + (value == real_vroot_value ? "Vroot_value" : "???")))); +#endif + XChangeProperty (dpy, win, XA_VROOT, XA_WINDOW, 32, PropModeReplace, + (unsigned char *) &value, 1); +} + +static void +remove_vroot_property (Display *dpy, Window win) +{ +#if 0 + if (p->verbose_p) + fprintf (stderr, "%s: removing XA_VROOT from 0x%x (%s)\n", blurb(), win, + (win == screensaver_window ? "ScreenSaver" : + (win == real_vroot ? "VRoot" : + (win == real_vroot_value ? "Vroot_value" : "???")))); +#endif + XDeleteProperty (dpy, win, XA_VROOT); +} + + +static Bool safe_XKillClient (Display *dpy, XID id); + +static void +kill_xsetroot_data_1 (Display *dpy, Window window, + Atom prop, const char *atom_name, + Bool verbose_p) +{ + Atom type; + int format; + unsigned long nitems, bytesafter; + unsigned char *dataP = 0; + + /* If the user has been using xv or xsetroot as a screensaver (to display + an image on the screensaver window, as a kind of slideshow) then the + pixmap and its associated color cells have been put in RetainPermanent + CloseDown mode. Since we're not destroying the xscreensaver window, + but merely unmapping it, we need to free these resources or those + colormap cells will stay allocated while the screensaver is off. (We + could just delete the screensaver window and recreate it later, but + that could cause other problems.) This code does an atomic read-and- + delete of the _XSETROOT_ID property, and if it held a pixmap, then we + cause the RetainPermanent resources of the client which created it + (and which no longer exists) to be freed. + + Update: it seems that Gnome and KDE do this same trick, but with the + properties "ESETROOT_PMAP_ID" and/or "_XROOTPMAP_ID" instead of + "_XSETROOT_ID". So, we'll kill those too. + */ + if (XGetWindowProperty (dpy, window, prop, 0, 1, + True, AnyPropertyType, &type, &format, &nitems, + &bytesafter, &dataP) + == Success + && type != None) + { + Pixmap *pixP = (Pixmap *) dataP; + if (pixP && *pixP && type == XA_PIXMAP && format == 32 && + nitems == 1 && bytesafter == 0) + { + if (verbose_p) + fprintf (stderr, "%s: destroying %s data (0x%lX).\n", + blurb(), atom_name, *pixP); + safe_XKillClient (dpy, *pixP); + } + else + fprintf (stderr, + "%s: deleted unrecognised %s property: \n" + "\t%lu, %lu; type: %lu, format: %d, " + "nitems: %lu, bytesafter %ld\n", + blurb(), atom_name, + (unsigned long) pixP, (pixP ? *pixP : 0), type, + format, nitems, bytesafter); + } +} + + +static void +kill_xsetroot_data (Display *dpy, Window w, Bool verbose_p) +{ + kill_xsetroot_data_1 (dpy, w, XA_XSETROOT_ID, "_XSETROOT_ID", verbose_p); + kill_xsetroot_data_1 (dpy, w, XA_ESETROOT_PMAP_ID, "ESETROOT_PMAP_ID", + verbose_p); + kill_xsetroot_data_1 (dpy, w, XA_XROOTPMAP_ID, "_XROOTPMAP_ID", verbose_p); +} + + +static void +save_real_vroot (saver_screen_info *ssi) +{ + saver_info *si = ssi->global; + Display *dpy = si->dpy; + Screen *screen = ssi->screen; + int i; + Window root = RootWindowOfScreen (screen); + Window root2, parent, *kids; + unsigned int nkids; + XErrorHandler old_handler; + + /* It's possible that a window might be deleted between our call to + XQueryTree() and our call to XGetWindowProperty(). Don't die if + that happens (but just ignore that window, it's not the one we're + interested in anyway.) + */ + XSync (dpy, False); + old_handler = XSetErrorHandler (BadWindow_ehandler); + XSync (dpy, False); + + ssi->real_vroot = 0; + ssi->real_vroot_value = 0; + if (! XQueryTree (dpy, root, &root2, &parent, &kids, &nkids)) + abort (); + if (root != root2) + abort (); + if (parent) + abort (); + for (i = 0; i < nkids; i++) + { + Atom type; + int format; + unsigned long nitems, bytesafter; + unsigned char *dataP = 0; + Window *vrootP; + int j; + + /* Skip this window if it is the xscreensaver window of any other + screen (this can happen in the Xinerama case.) + */ + for (j = 0; j < si->nscreens; j++) + { + saver_screen_info *ssi2 = &si->screens[j]; + if (kids[i] == ssi2->screensaver_window) + goto SKIP; + } + + if (XGetWindowProperty (dpy, kids[i], XA_VROOT, 0, 1, False, XA_WINDOW, + &type, &format, &nitems, &bytesafter, + &dataP) + != Success) + continue; + if (! dataP) + continue; + + vrootP = (Window *) dataP; + if (ssi->real_vroot) + { + if (*vrootP == ssi->screensaver_window) abort (); + fprintf (stderr, + "%s: more than one virtual root window found (0x%x and 0x%x).\n", + blurb(), (int) ssi->real_vroot, (int) kids [i]); + exit (1); + } + ssi->real_vroot = kids [i]; + ssi->real_vroot_value = *vrootP; + SKIP: + ; + } + + XSync (dpy, False); + XSetErrorHandler (old_handler); + XSync (dpy, False); + + if (ssi->real_vroot) + { + remove_vroot_property (si->dpy, ssi->real_vroot); + XSync (dpy, False); + } + + XFree ((char *) kids); +} + + +static Bool +restore_real_vroot_1 (saver_screen_info *ssi) +{ + saver_info *si = ssi->global; + saver_preferences *p = &si->prefs; + if (p->verbose_p && ssi->real_vroot) + fprintf (stderr, + "%s: restoring __SWM_VROOT property on the real vroot (0x%lx).\n", + blurb(), (unsigned long) ssi->real_vroot); + if (ssi->screensaver_window) + remove_vroot_property (si->dpy, ssi->screensaver_window); + if (ssi->real_vroot) + { + store_vroot_property (si->dpy, ssi->real_vroot, ssi->real_vroot_value); + ssi->real_vroot = 0; + ssi->real_vroot_value = 0; + /* make sure the property change gets there before this process + terminates! We might be doing this because we have intercepted + SIGTERM or something. */ + XSync (si->dpy, False); + return True; + } + return False; +} + +Bool +restore_real_vroot (saver_info *si) +{ + int i; + Bool did_any = False; + for (i = 0; i < si->nscreens; i++) + { + saver_screen_info *ssi = &si->screens[i]; + if (restore_real_vroot_1 (ssi)) + did_any = True; + } + return did_any; +} + + +/* Signal hackery to ensure that the vroot doesn't get left in an + inconsistent state + */ + +const char * +signal_name(int signal) +{ + switch (signal) { + case SIGHUP: return "SIGHUP"; + case SIGINT: return "SIGINT"; + case SIGQUIT: return "SIGQUIT"; + case SIGILL: return "SIGILL"; + case SIGTRAP: return "SIGTRAP"; +#ifdef SIGABRT + case SIGABRT: return "SIGABRT"; +#endif + case SIGFPE: return "SIGFPE"; + case SIGKILL: return "SIGKILL"; + case SIGBUS: return "SIGBUS"; + case SIGSEGV: return "SIGSEGV"; + case SIGPIPE: return "SIGPIPE"; + case SIGALRM: return "SIGALRM"; + case SIGTERM: return "SIGTERM"; +#ifdef SIGSTOP + case SIGSTOP: return "SIGSTOP"; +#endif +#ifdef SIGCONT + case SIGCONT: return "SIGCONT"; +#endif +#ifdef SIGUSR1 + case SIGUSR1: return "SIGUSR1"; +#endif +#ifdef SIGUSR2 + case SIGUSR2: return "SIGUSR2"; +#endif +#ifdef SIGEMT + case SIGEMT: return "SIGEMT"; +#endif +#ifdef SIGSYS + case SIGSYS: return "SIGSYS"; +#endif +#ifdef SIGCHLD + case SIGCHLD: return "SIGCHLD"; +#endif +#ifdef SIGPWR + case SIGPWR: return "SIGPWR"; +#endif +#ifdef SIGWINCH + case SIGWINCH: return "SIGWINCH"; +#endif +#ifdef SIGURG + case SIGURG: return "SIGURG"; +#endif +#ifdef SIGIO + case SIGIO: return "SIGIO"; +#endif +#ifdef SIGVTALRM + case SIGVTALRM: return "SIGVTALRM"; +#endif +#ifdef SIGXCPU + case SIGXCPU: return "SIGXCPU"; +#endif +#ifdef SIGXFSZ + case SIGXFSZ: return "SIGXFSZ"; +#endif +#ifdef SIGDANGER + case SIGDANGER: return "SIGDANGER"; +#endif + default: + { + static char buf[50]; + sprintf(buf, "signal %d\n", signal); + return buf; + } + } +} + + + +static RETSIGTYPE +restore_real_vroot_handler (int sig) +{ + saver_info *si = global_si_kludge; /* I hate C so much... */ + + signal (sig, SIG_DFL); + if (restore_real_vroot (si)) + fprintf (real_stderr, "\n%s: %s intercepted, vroot restored.\n", + blurb(), signal_name(sig)); + kill (getpid (), sig); +} + +static void +catch_signal (saver_info *si, int sig, RETSIGTYPE (*handler) (int)) +{ +# ifdef HAVE_SIGACTION + + struct sigaction a; + a.sa_handler = handler; + sigemptyset (&a.sa_mask); + a.sa_flags = 0; + + /* On Linux 2.4.9 (at least) we need to tell the kernel to not mask delivery + of this signal from inside its handler, or else when we execvp() the + process again, it starts up with SIGHUP blocked, meaning that killing + it with -HUP only works *once*. You'd think that execvp() would reset + all the signal masks, but it doesn't. + */ +# if defined(SA_NOMASK) + a.sa_flags |= SA_NOMASK; +# elif defined(SA_NODEFER) + a.sa_flags |= SA_NODEFER; +# endif + + if (sigaction (sig, &a, 0) < 0) +# else /* !HAVE_SIGACTION */ + if (((long) signal (sig, handler)) == -1L) +# endif /* !HAVE_SIGACTION */ + { + char buf [255]; + sprintf (buf, "%s: couldn't catch %s", blurb(), signal_name(sig)); + perror (buf); + saver_exit (si, 1, 0); + } +} + +static RETSIGTYPE saver_sighup_handler (int sig); + +void +handle_signals (saver_info *si) +{ + catch_signal (si, SIGHUP, saver_sighup_handler); + + catch_signal (si, SIGINT, restore_real_vroot_handler); + catch_signal (si, SIGQUIT, restore_real_vroot_handler); + catch_signal (si, SIGILL, restore_real_vroot_handler); + catch_signal (si, SIGTRAP, restore_real_vroot_handler); +#ifdef SIGIOT + catch_signal (si, SIGIOT, restore_real_vroot_handler); +#endif + catch_signal (si, SIGABRT, restore_real_vroot_handler); +#ifdef SIGEMT + catch_signal (si, SIGEMT, restore_real_vroot_handler); +#endif + catch_signal (si, SIGFPE, restore_real_vroot_handler); + catch_signal (si, SIGBUS, restore_real_vroot_handler); + catch_signal (si, SIGSEGV, restore_real_vroot_handler); +#ifdef SIGSYS + catch_signal (si, SIGSYS, restore_real_vroot_handler); +#endif + catch_signal (si, SIGTERM, restore_real_vroot_handler); +#ifdef SIGXCPU + catch_signal (si, SIGXCPU, restore_real_vroot_handler); +#endif +#ifdef SIGXFSZ + catch_signal (si, SIGXFSZ, restore_real_vroot_handler); +#endif +#ifdef SIGDANGER + catch_signal (si, SIGDANGER, restore_real_vroot_handler); +#endif +} + + +static RETSIGTYPE +saver_sighup_handler (int sig) +{ + saver_info *si = global_si_kludge; /* I hate C so much... */ + + /* Re-establish SIGHUP handler */ + catch_signal (si, SIGHUP, saver_sighup_handler); + + fprintf (stderr, "%s: %s received: restarting...\n", + blurb(), signal_name(sig)); + + if (si->screen_blanked_p) + { + int i; + for (i = 0; i < si->nscreens; i++) + kill_screenhack (&si->screens[i]); + unblank_screen (si); + XSync (si->dpy, False); + } + + restart_process (si); /* Does not return */ + abort (); +} + + + +void +saver_exit (saver_info *si, int status, const char *dump_core_reason) +{ + saver_preferences *p = &si->prefs; + static Bool exiting = False; + Bool bugp; + Bool vrs; + + if (exiting) + exit(status); + + exiting = True; + + vrs = restore_real_vroot (si); + emergency_kill_subproc (si); + shutdown_stderr (si); + + if (p->verbose_p && vrs) + fprintf (real_stderr, "%s: old vroot restored.\n", blurb()); + + fflush(real_stdout); + +#ifdef VMS /* on VMS, 1 is the "normal" exit code instead of 0. */ + if (status == 0) status = 1; + else if (status == 1) status = -1; +#endif + + bugp = !!dump_core_reason; + + if (si->prefs.debug_p && !dump_core_reason) + dump_core_reason = "because of -debug"; + + if (dump_core_reason) + { + /* Note that the Linux man page for setuid() says If uid is + different from the old effective uid, the process will be + forbidden from leaving core dumps. + */ + char cwd[4096]; /* should really be PATH_MAX, but who cares. */ + cwd[0] = 0; + fprintf(real_stderr, "%s: dumping core (%s)\n", blurb(), + dump_core_reason); + + if (bugp) + fprintf(real_stderr, + "%s: see http://www.jwz.org/xscreensaver/bugs.html\n" + "\t\t\tfor bug reporting information.\n\n", + blurb()); + +# if defined(HAVE_GETCWD) + if (!getcwd (cwd, sizeof(cwd))) +# elif defined(HAVE_GETWD) + if (!getwd (cwd)) +# endif + strcpy(cwd, "unknown."); + + fprintf (real_stderr, "%s: current directory is %s\n", blurb(), cwd); + describe_uids (si, real_stderr); + + /* Do this to drop a core file, so that we can get a stack trace. */ + abort(); + } + + exit (status); +} + + +/* Managing the actual screensaver window */ + +Bool +window_exists_p (Display *dpy, Window window) +{ + XErrorHandler old_handler; + XWindowAttributes xgwa; + xgwa.screen = 0; + old_handler = XSetErrorHandler (BadWindow_ehandler); + XGetWindowAttributes (dpy, window, &xgwa); + XSync (dpy, False); + XSetErrorHandler (old_handler); + return (xgwa.screen != 0); +} + +static void +store_saver_id (saver_screen_info *ssi) +{ + XClassHint class_hints; + saver_info *si = ssi->global; + unsigned long pid = (unsigned long) getpid (); + char buf[20]; + struct passwd *p = getpwuid (getuid ()); + const char *name, *host; + char *id; + + /* First store the name and class on the window. + */ + class_hints.res_name = progname; + class_hints.res_class = progclass; + XSetClassHint (si->dpy, ssi->screensaver_window, &class_hints); + XStoreName (si->dpy, ssi->screensaver_window, "screensaver"); + + /* Then store the xscreensaver version number. + */ + XChangeProperty (si->dpy, ssi->screensaver_window, + XA_SCREENSAVER_VERSION, + XA_STRING, 8, PropModeReplace, + (unsigned char *) si->version, + strlen (si->version)); + + /* Now store the XSCREENSAVER_ID property, that says what user and host + xscreensaver is running as. + */ + + if (p && p->pw_name && *p->pw_name) + name = p->pw_name; + else if (p) + { + sprintf (buf, "%lu", (unsigned long) p->pw_uid); + name = buf; + } + else + name = "???"; + +# if defined(HAVE_UNAME) + { + struct utsname uts; + if (uname (&uts) < 0) + host = "???"; + else + host = uts.nodename; + } +# elif defined(VMS) + host = getenv("SYS$NODE"); +# else /* !HAVE_UNAME && !VMS */ + host = "???"; +# endif /* !HAVE_UNAME && !VMS */ + + id = (char *) malloc (strlen(name) + strlen(host) + 50); + sprintf (id, "%lu (%s@%s)", pid, name, host); + + XChangeProperty (si->dpy, ssi->screensaver_window, + XA_SCREENSAVER_ID, XA_STRING, + 8, PropModeReplace, + (unsigned char *) id, strlen (id)); + free (id); +} + + +void +store_saver_status (saver_info *si) +{ + PROP32 *status; + int size = si->nscreens + 2; + int i; + + status = (PROP32 *) calloc (size, sizeof(PROP32)); + + status[0] = (PROP32) (si->screen_blanked_p + ? (si->locked_p ? XA_LOCK : XA_BLANK) + : 0); + status[1] = (PROP32) si->blank_time; + + for (i = 0; i < si->nscreens; i++) + { + saver_screen_info *ssi = &si->screens[i]; + status [2 + i] = ssi->current_hack + 1; + } + + XChangeProperty (si->dpy, + RootWindow (si->dpy, 0), /* always screen #0 */ + XA_SCREENSAVER_STATUS, + XA_INTEGER, 32, PropModeReplace, + (unsigned char *) status, size); + free (status); +} + + +static Bool error_handler_hit_p = False; + +static int +ignore_all_errors_ehandler (Display *dpy, XErrorEvent *error) +{ + error_handler_hit_p = True; + return 0; +} + + +/* Returns True if successful, False if an X error occurred. + We need this because other programs might have done things to + our window that will cause XChangeWindowAttributes() to fail: + if that happens, we give up, destroy the window, and re-create + it. + */ +static Bool +safe_XChangeWindowAttributes (Display *dpy, Window window, + unsigned long mask, + XSetWindowAttributes *attrs) +{ + XErrorHandler old_handler; + XSync (dpy, False); + error_handler_hit_p = False; + old_handler = XSetErrorHandler (ignore_all_errors_ehandler); + + XChangeWindowAttributes (dpy, window, mask, attrs); + + XSync (dpy, False); + XSetErrorHandler (old_handler); + XSync (dpy, False); + + return (!error_handler_hit_p); +} + + +/* This might not be necessary, but just in case. */ +static Bool +safe_XConfigureWindow (Display *dpy, Window window, + unsigned long mask, XWindowChanges *changes) +{ + XErrorHandler old_handler; + XSync (dpy, False); + error_handler_hit_p = False; + old_handler = XSetErrorHandler (ignore_all_errors_ehandler); + + XConfigureWindow (dpy, window, mask, changes); + + XSync (dpy, False); + XSetErrorHandler (old_handler); + XSync (dpy, False); + + return (!error_handler_hit_p); +} + +/* This might not be necessary, but just in case. */ +static Bool +safe_XDestroyWindow (Display *dpy, Window window) +{ + XErrorHandler old_handler; + XSync (dpy, False); + error_handler_hit_p = False; + old_handler = XSetErrorHandler (ignore_all_errors_ehandler); + + XDestroyWindow (dpy, window); + + XSync (dpy, False); + XSetErrorHandler (old_handler); + XSync (dpy, False); + + return (!error_handler_hit_p); +} + + +static Bool +safe_XKillClient (Display *dpy, XID id) +{ + XErrorHandler old_handler; + XSync (dpy, False); + error_handler_hit_p = False; + old_handler = XSetErrorHandler (ignore_all_errors_ehandler); + + XKillClient (dpy, id); + + XSync (dpy, False); + XSetErrorHandler (old_handler); + XSync (dpy, False); + + return (!error_handler_hit_p); +} + + +#ifdef HAVE_XF86VMODE +Bool +safe_XF86VidModeGetViewPort (Display *dpy, int screen, int *xP, int *yP) +{ + Bool result; + XErrorHandler old_handler; + XSync (dpy, False); + error_handler_hit_p = False; + old_handler = XSetErrorHandler (ignore_all_errors_ehandler); + + result = XF86VidModeGetViewPort (dpy, screen, xP, yP); + + XSync (dpy, False); + XSetErrorHandler (old_handler); + XSync (dpy, False); + + return (error_handler_hit_p + ? False + : result); +} + +/* There is no "safe_XF86VidModeGetModeLine" because it fails with an + untrappable I/O error instead of an X error -- so one must call + safe_XF86VidModeGetViewPort first, and assume that both have the + same error condition. Thank you XFree, may I have another. + */ + +#endif /* HAVE_XF86VMODE */ + + +static void +initialize_screensaver_window_1 (saver_screen_info *ssi) +{ + saver_info *si = ssi->global; + saver_preferences *p = &si->prefs; + Bool install_cmap_p = ssi->install_cmap_p; /* not p->install_cmap_p */ + + /* This resets the screensaver window as fully as possible, since there's + no way of knowing what some random client may have done to us in the + meantime. We could just destroy and recreate the window, but that has + its own set of problems... + */ + XColor black; + XSetWindowAttributes attrs; + unsigned long attrmask; + static Bool printed_visual_info = False; /* only print the message once. */ + Window horked_window = 0; + + black.red = black.green = black.blue = 0; + + if (ssi->cmap == DefaultColormapOfScreen (ssi->screen)) + ssi->cmap = 0; + + if (ssi->current_visual != DefaultVisualOfScreen (ssi->screen)) + /* It's not the default visual, so we have no choice but to install. */ + install_cmap_p = True; + + if (install_cmap_p) + { + if (! ssi->cmap) + { + ssi->cmap = XCreateColormap (si->dpy, + RootWindowOfScreen (ssi->screen), + ssi->current_visual, AllocNone); + if (! XAllocColor (si->dpy, ssi->cmap, &black)) abort (); + ssi->black_pixel = black.pixel; + } + } + else + { + Colormap def_cmap = DefaultColormapOfScreen (ssi->screen); + if (ssi->cmap) + { + XFreeColors (si->dpy, ssi->cmap, &ssi->black_pixel, 1, 0); + if (ssi->cmap != ssi->demo_cmap && + ssi->cmap != def_cmap) + XFreeColormap (si->dpy, ssi->cmap); + } + ssi->cmap = def_cmap; + ssi->black_pixel = BlackPixelOfScreen (ssi->screen); + } + + attrmask = (CWOverrideRedirect | CWEventMask | CWBackingStore | CWColormap | + CWBackPixel | CWBackingPixel | CWBorderPixel); + attrs.override_redirect = True; + + /* When use_mit_saver_extension or use_sgi_saver_extension is true, we won't + actually be reading these events during normal operation; but we still + need to see Button events for demo-mode to work properly. + */ + attrs.event_mask = (KeyPressMask | KeyReleaseMask | + ButtonPressMask | ButtonReleaseMask | + PointerMotionMask); + + attrs.backing_store = NotUseful; + attrs.colormap = ssi->cmap; + attrs.background_pixel = ssi->black_pixel; + attrs.backing_pixel = ssi->black_pixel; + attrs.border_pixel = ssi->black_pixel; + + if (!p->verbose_p || printed_visual_info) + ; + else if (ssi->current_visual == DefaultVisualOfScreen (ssi->screen)) + { + fprintf (stderr, "%s: %d: visual ", blurb(), ssi->number); + describe_visual (stderr, ssi->screen, ssi->current_visual, + install_cmap_p); + } + else + { + fprintf (stderr, "%s: using visual: ", blurb()); + describe_visual (stderr, ssi->screen, ssi->current_visual, + install_cmap_p); + fprintf (stderr, "%s: default visual: ", blurb()); + describe_visual (stderr, ssi->screen, + DefaultVisualOfScreen (ssi->screen), + ssi->install_cmap_p); + } + printed_visual_info = True; + +#ifdef HAVE_MIT_SAVER_EXTENSION + if (si->using_mit_saver_extension) + { + XScreenSaverInfo *info; + Window root = RootWindowOfScreen (ssi->screen); + +#if 0 + /* This call sets the server screensaver timeouts to what we think + they should be (based on the resources and args xscreensaver was + started with.) It's important that we do this to sync back up + with the server - if we have turned on prematurely, as by an + ACTIVATE ClientMessage, then the server may decide to activate + the screensaver while it's already active. That's ok for us, + since we would know to ignore that ScreenSaverActivate event, + but a side effect of this would be that the server would map its + saver window (which we then hide again right away) meaning that + the bits currently on the screen get blown away. Ugly. */ + + /* #### Ok, that doesn't work - when we tell the server that the + screensaver is "off" it sends us a Deactivate event, which is + sensible... but causes the saver to never come on. Hmm. */ + disable_builtin_screensaver (si, True); +#endif /* 0 */ + +#if 0 + /* #### The MIT-SCREEN-SAVER extension gives us access to the + window that the server itself uses for saving the screen. + However, using this window in any way, in particular, calling + XScreenSaverSetAttributes() as below, tends to make the X server + crash. So fuck it, let's try and get along without using it... + + It's also inconvenient to use this window because it doesn't + always exist (though the ID is constant.) So to use this + window, we'd have to reimplement the ACTIVATE ClientMessage to + tell the *server* to tell *us* to turn on, to cause the window + to get created at the right time. Gag. */ + XScreenSaverSetAttributes (si->dpy, root, + 0, 0, width, height, 0, + current_depth, InputOutput, visual, + attrmask, &attrs); + XSync (si->dpy, False); +#endif /* 0 */ + + info = XScreenSaverAllocInfo (); + XScreenSaverQueryInfo (si->dpy, root, info); + ssi->server_mit_saver_window = info->window; + if (! ssi->server_mit_saver_window) abort (); + XFree (info); + } +#endif /* HAVE_MIT_SAVER_EXTENSION */ + + if (ssi->screensaver_window) + { + XWindowChanges changes; + unsigned int changesmask = CWX|CWY|CWWidth|CWHeight|CWBorderWidth; + changes.x = ssi->x; + changes.y = ssi->y; + changes.width = ssi->width; + changes.height = ssi->height; + changes.border_width = 0; + + if (! (safe_XConfigureWindow (si->dpy, ssi->screensaver_window, + changesmask, &changes) && + safe_XChangeWindowAttributes (si->dpy, ssi->screensaver_window, + attrmask, &attrs))) + { + horked_window = ssi->screensaver_window; + ssi->screensaver_window = 0; + } + } + + if (!ssi->screensaver_window) + { + ssi->screensaver_window = + XCreateWindow (si->dpy, RootWindowOfScreen (ssi->screen), + ssi->x, ssi->y, ssi->width, ssi->height, + 0, ssi->current_depth, InputOutput, + ssi->current_visual, attrmask, &attrs); + reset_stderr (ssi); + + if (horked_window) + { + fprintf (stderr, + "%s: someone horked our saver window (0x%lx)! Recreating it...\n", + blurb(), (unsigned long) horked_window); + maybe_transfer_grabs (ssi, horked_window, ssi->screensaver_window, + ssi->number); + safe_XDestroyWindow (si->dpy, horked_window); + horked_window = 0; + } + + if (p->verbose_p) + fprintf (stderr, "%s: %d: saver window is 0x%lx.\n", + blurb(), ssi->number, + (unsigned long) ssi->screensaver_window); + } + + store_saver_id (ssi); /* store window name and IDs */ + + if (!ssi->cursor) + { + Pixmap bit; + bit = XCreatePixmapFromBitmapData (si->dpy, ssi->screensaver_window, + "\000", 1, 1, + BlackPixelOfScreen (ssi->screen), + BlackPixelOfScreen (ssi->screen), + 1); + ssi->cursor = XCreatePixmapCursor (si->dpy, bit, bit, &black, &black, + 0, 0); + XFreePixmap (si->dpy, bit); + } + + XSetWindowBackground (si->dpy, ssi->screensaver_window, ssi->black_pixel); + + if (si->demoing_p) + XUndefineCursor (si->dpy, ssi->screensaver_window); + else + XDefineCursor (si->dpy, ssi->screensaver_window, ssi->cursor); +} + +void +initialize_screensaver_window (saver_info *si) +{ + int i; + for (i = 0; i < si->nscreens; i++) + initialize_screensaver_window_1 (&si->screens[i]); +} + + +/* Called when the RANDR (Resize and Rotate) extension tells us that + the size of the screen has changed while the screen was blanked. + Call update_screen_layout() first, then call this to synchronize + the size of the saver windows to the new sizes of the screens. + */ +void +resize_screensaver_window (saver_info *si) +{ + saver_preferences *p = &si->prefs; + int i; + + for (i = 0; i < si->nscreens; i++) + { + saver_screen_info *ssi = &si->screens[i]; + XWindowAttributes xgwa; + + /* Make sure a window exists -- it might not if a monitor was just + added for the first time. + */ + if (! ssi->screensaver_window) + { + initialize_screensaver_window_1 (ssi); + if (p->verbose_p) + fprintf (stderr, + "%s: %d: newly added window 0x%lx %dx%d+%d+%d\n", + blurb(), i, (unsigned long) ssi->screensaver_window, + ssi->width, ssi->height, ssi->x, ssi->y); + } + + /* Make sure the window is the right size -- it might not be if + the monitor changed resolution, or if a badly-behaved hack + screwed with it. + */ + XGetWindowAttributes (si->dpy, ssi->screensaver_window, &xgwa); + if (xgwa.x != ssi->x || + xgwa.y != ssi->y || + xgwa.width != ssi->width || + xgwa.height != ssi->height) + { + XWindowChanges changes; + unsigned int changesmask = CWX|CWY|CWWidth|CWHeight|CWBorderWidth; + changes.x = ssi->x; + changes.y = ssi->y; + changes.width = ssi->width; + changes.height = ssi->height; + changes.border_width = 0; + + if (p->verbose_p) + fprintf (stderr, + "%s: %d: resize 0x%lx from %dx%d+%d+%d to %dx%d+%d+%d\n", + blurb(), i, (unsigned long) ssi->screensaver_window, + xgwa.width, xgwa.height, xgwa.x, xgwa.y, + ssi->width, ssi->height, ssi->x, ssi->y); + + if (! safe_XConfigureWindow (si->dpy, ssi->screensaver_window, + changesmask, &changes)) + fprintf (stderr, "%s: %d: someone horked our saver window" + " (0x%lx)! Unable to resize it!\n", + blurb(), i, (unsigned long) ssi->screensaver_window); + } + + /* Now (if blanked) make sure that it's mapped and running a hack -- + it might not be if we just added it. (We also might be re-using + an old window that existed for a previous monitor that was + removed and re-added.) + + Note that spawn_screenhack() calls select_visual() which may destroy + and re-create the window via initialize_screensaver_window_1(). + */ + if (si->screen_blanked_p) + { + if (ssi->cmap) + XInstallColormap (si->dpy, ssi->cmap); + XMapRaised (si->dpy, ssi->screensaver_window); + if (! ssi->pid) + spawn_screenhack (ssi); + + /* Make sure the act of adding a screen doesn't present as + pointer motion (and thus cause an unblank). */ + { + Window root, child; + int x, y; + unsigned int mask; + XQueryPointer (si->dpy, ssi->screensaver_window, &root, &child, + &ssi->last_poll_mouse.root_x, + &ssi->last_poll_mouse.root_y, + &x, &y, &mask); + } + } + } + + /* Kill off any savers running on no-longer-extant monitors. + */ + for (; i < si->ssi_count; i++) + { + saver_screen_info *ssi = &si->screens[i]; + if (ssi->pid) + kill_screenhack (ssi); + if (ssi->screensaver_window) + { + XUnmapWindow (si->dpy, ssi->screensaver_window); + restore_real_vroot_1 (ssi); + } + } +} + + +void +raise_window (saver_info *si, + Bool inhibit_fade, Bool between_hacks_p, Bool dont_clear) +{ + saver_preferences *p = &si->prefs; + int i; + + if (si->demoing_p) + inhibit_fade = True; + + if (si->emergency_lock_p) + inhibit_fade = True; + + if (!dont_clear) + initialize_screensaver_window (si); + + reset_watchdog_timer (si, True); + + if (p->fade_p && si->fading_possible_p && !inhibit_fade) + { + Window *current_windows = (Window *) + calloc(sizeof(Window), si->nscreens); + Colormap *current_maps = (Colormap *) + calloc(sizeof(Colormap), si->nscreens); + + for (i = 0; i < si->nscreens; i++) + { + saver_screen_info *ssi = &si->screens[i]; + current_windows[i] = ssi->screensaver_window; + current_maps[i] = (between_hacks_p + ? ssi->cmap + : DefaultColormapOfScreen (ssi->screen)); + /* Ensure that the default background of the window is really black, + not a pixmap or something. (This does not clear the window.) */ + XSetWindowBackground (si->dpy, ssi->screensaver_window, + ssi->black_pixel); + } + + if (p->verbose_p) fprintf (stderr, "%s: fading...\n", blurb()); + + XGrabServer (si->dpy); /* ############ DANGER! */ + + /* Clear the stderr layer on each screen. + */ + if (!dont_clear) + for (i = 0; i < si->nscreens; i++) + { + saver_screen_info *ssi = &si->screens[i]; + if (ssi->stderr_overlay_window) + /* Do this before the fade, since the stderr cmap won't fade + even if we uninstall it (beats me...) */ + clear_stderr (ssi); + } + + /* Note! The server is grabbed, and this will take several seconds + to complete! */ + fade_screens (si->dpy, current_maps, + current_windows, si->nscreens, + p->fade_seconds/1000, p->fade_ticks, True, !dont_clear); + + free(current_maps); + free(current_windows); + current_maps = 0; + current_windows = 0; + + if (p->verbose_p) fprintf (stderr, "%s: fading done.\n", blurb()); + +#ifdef HAVE_MIT_SAVER_EXTENSION + for (i = 0; i < si->nscreens; i++) + { + saver_screen_info *ssi = &si->screens[i]; + if (ssi->server_mit_saver_window && + window_exists_p (si->dpy, ssi->server_mit_saver_window)) + XUnmapWindow (si->dpy, ssi->server_mit_saver_window); + } +#endif /* HAVE_MIT_SAVER_EXTENSION */ + + XUngrabServer (si->dpy); + XSync (si->dpy, False); /* ###### (danger over) */ + } + else + { + for (i = 0; i < si->nscreens; i++) + { + saver_screen_info *ssi = &si->screens[i]; + if (!dont_clear) + XClearWindow (si->dpy, ssi->screensaver_window); + if (!dont_clear || ssi->stderr_overlay_window) + clear_stderr (ssi); + XMapRaised (si->dpy, ssi->screensaver_window); +#ifdef HAVE_MIT_SAVER_EXTENSION + if (ssi->server_mit_saver_window && + window_exists_p (si->dpy, ssi->server_mit_saver_window)) + XUnmapWindow (si->dpy, ssi->server_mit_saver_window); +#endif /* HAVE_MIT_SAVER_EXTENSION */ + } + } + + for (i = 0; i < si->nscreens; i++) + { + saver_screen_info *ssi = &si->screens[i]; + if (ssi->cmap) + XInstallColormap (si->dpy, ssi->cmap); + } +} + + +int +mouse_screen (saver_info *si) +{ + saver_preferences *p = &si->prefs; + Window pointer_root, pointer_child; + int root_x, root_y, win_x, win_y; + unsigned int mask; + int i; + + if (si->nscreens == 1) + return 0; + + for (i = 0; i < si->nscreens; i++) + { + saver_screen_info *ssi = &si->screens[i]; + if (XQueryPointer (si->dpy, RootWindowOfScreen (ssi->screen), + &pointer_root, &pointer_child, + &root_x, &root_y, &win_x, &win_y, &mask) && + root_x >= ssi->x && + root_y >= ssi->y && + root_x < ssi->x + ssi->width && + root_y < ssi->y + ssi->height) + { + if (p->verbose_p) + fprintf (stderr, "%s: mouse is on screen %d of %d\n", + blurb(), i, si->nscreens); + return i; + } + } + + /* couldn't figure out where the mouse is? Oh well. */ + return 0; +} + + +Bool +blank_screen (saver_info *si) +{ + int i; + Bool ok; + Window w; + int mscreen; + + /* Note: we do our grabs on the root window, not on the screensaver window. + If we grabbed on the saver window, then the demo mode and lock dialog + boxes wouldn't get any events. + + By "the root window", we mean "the root window that contains the mouse." + We use to always grab the mouse on screen 0, but that has the effect of + moving the mouse to screen 0 from whichever screen it was on, on + multi-head systems. + */ + mscreen = mouse_screen (si); + w = RootWindowOfScreen(si->screens[mscreen].screen); + ok = grab_keyboard_and_mouse (si, w, + (si->demoing_p ? 0 : si->screens[0].cursor), + mscreen); + + +# if 0 + if (si->using_mit_saver_extension || si->using_sgi_saver_extension) + /* If we're using a server extension, then failure to get a grab is + not a big deal -- even without the grab, we will still be able + to un-blank when there is user activity, since the server will + tell us. */ + /* #### No, that's not true: if we don't have a keyboard grab, + then we can't read passwords to unlock. + */ + ok = True; +# endif /* 0 */ + + if (!ok) + return False; + + for (i = 0; i < si->nscreens; i++) + { + saver_screen_info *ssi = &si->screens[i]; + if (ssi->real_screen_p) + save_real_vroot (ssi); + store_vroot_property (si->dpy, + ssi->screensaver_window, + ssi->screensaver_window); + +#ifdef HAVE_XF86VMODE + { + int ev, er; + if (!XF86VidModeQueryExtension (si->dpy, &ev, &er) || + !safe_XF86VidModeGetViewPort (si->dpy, i, + &ssi->blank_vp_x, + &ssi->blank_vp_y)) + ssi->blank_vp_x = ssi->blank_vp_y = -1; + } +#endif /* HAVE_XF86VMODE */ + } + + raise_window (si, False, False, False); + + si->screen_blanked_p = True; + si->blank_time = time ((time_t) 0); + si->last_wall_clock_time = 0; + + store_saver_status (si); /* store blank time */ + + return True; +} + + +void +unblank_screen (saver_info *si) +{ + saver_preferences *p = &si->prefs; + Bool unfade_p = (si->fading_possible_p && p->unfade_p); + int i; + + monitor_power_on (si, True); + reset_watchdog_timer (si, False); + + if (si->demoing_p) + unfade_p = False; + + if (unfade_p) + { + Window *current_windows = (Window *) + calloc(sizeof(Window), si->nscreens); + + for (i = 0; i < si->nscreens; i++) + { + saver_screen_info *ssi = &si->screens[i]; + current_windows[i] = ssi->screensaver_window; + /* Ensure that the default background of the window is really black, + not a pixmap or something. (This does not clear the window.) */ + XSetWindowBackground (si->dpy, ssi->screensaver_window, + ssi->black_pixel); + } + + if (p->verbose_p) fprintf (stderr, "%s: unfading...\n", blurb()); + + + XSync (si->dpy, False); + XGrabServer (si->dpy); /* ############ DANGER! */ + XSync (si->dpy, False); + + /* Clear the stderr layer on each screen. + */ + for (i = 0; i < si->nscreens; i++) + { + saver_screen_info *ssi = &si->screens[i]; + clear_stderr (ssi); + } + + XUngrabServer (si->dpy); + XSync (si->dpy, False); /* ###### (danger over) */ + + fade_screens (si->dpy, 0, + current_windows, si->nscreens, + p->fade_seconds/1000, p->fade_ticks, + False, False); + + free(current_windows); + current_windows = 0; + + if (p->verbose_p) fprintf (stderr, "%s: unfading done.\n", blurb()); + } + else + { + for (i = 0; i < si->nscreens; i++) + { + saver_screen_info *ssi = &si->screens[i]; + if (ssi->cmap) + { + Colormap c = DefaultColormapOfScreen (ssi->screen); + /* avoid technicolor */ + XClearWindow (si->dpy, ssi->screensaver_window); + if (c) XInstallColormap (si->dpy, c); + } + XUnmapWindow (si->dpy, ssi->screensaver_window); + } + } + + + /* If the focus window does has a non-default colormap, then install + that colormap as well. (On SGIs, this will cause both the root map + and the focus map to be installed simultaneously. It'd be nice to + pick up the other colormaps that had been installed, too; perhaps + XListInstalledColormaps could be used for that?) + */ + { + Window focus = 0; + int revert_to; + XGetInputFocus (si->dpy, &focus, &revert_to); + if (focus && focus != PointerRoot && focus != None) + { + XWindowAttributes xgwa; + xgwa.colormap = 0; + XGetWindowAttributes (si->dpy, focus, &xgwa); + if (xgwa.colormap && + xgwa.colormap != DefaultColormapOfScreen (xgwa.screen)) + XInstallColormap (si->dpy, xgwa.colormap); + } + } + + + for (i = 0; i < si->nscreens; i++) + { + saver_screen_info *ssi = &si->screens[i]; + kill_xsetroot_data (si->dpy, ssi->screensaver_window, p->verbose_p); + } + + store_saver_status (si); /* store unblank time */ + ungrab_keyboard_and_mouse (si); + restore_real_vroot (si); + + /* Unmap the windows a second time, dammit -- just to avoid a race + with the screen-grabbing hacks. (I'm not sure if this is really + necessary; I'm stabbing in the dark now.) + */ + for (i = 0; i < si->nscreens; i++) + XUnmapWindow (si->dpy, si->screens[i].screensaver_window); + + si->screen_blanked_p = False; + si->blank_time = time ((time_t) 0); + si->last_wall_clock_time = 0; + + store_saver_status (si); /* store unblank time */ +} + + +/* Transfer any grabs from the old window to the new. + Actually I think none of this is necessary, since we always + hold our grabs on the root window, but I wrote this before + re-discovering that... + */ +static void +maybe_transfer_grabs (saver_screen_info *ssi, + Window old_w, Window new_w, + int new_screen_no) +{ + saver_info *si = ssi->global; + + /* If the old window held our mouse grab, transfer the grab to the new + window. (Grab the server while so doing, to avoid a race condition.) + */ + if (old_w == si->mouse_grab_window) + { + XGrabServer (si->dpy); /* ############ DANGER! */ + ungrab_mouse (si); + grab_mouse (si, ssi->screensaver_window, + (si->demoing_p ? 0 : ssi->cursor), + new_screen_no); + XUngrabServer (si->dpy); + XSync (si->dpy, False); /* ###### (danger over) */ + } + + /* If the old window held our keyboard grab, transfer the grab to the new + window. (Grab the server while so doing, to avoid a race condition.) + */ + if (old_w == si->keyboard_grab_window) + { + XGrabServer (si->dpy); /* ############ DANGER! */ + ungrab_kbd(si); + grab_kbd(si, ssi->screensaver_window, ssi->number); + XUngrabServer (si->dpy); + XSync (si->dpy, False); /* ###### (danger over) */ + } +} + + +static Visual * +get_screen_gl_visual (saver_info *si, int real_screen_number) +{ + int i; + int nscreens = ScreenCount (si->dpy); + + if (! si->best_gl_visuals) + si->best_gl_visuals = (Visual **) + calloc (nscreens + 1, sizeof (*si->best_gl_visuals)); + + for (i = 0; i < nscreens; i++) + if (! si->best_gl_visuals[i]) + si->best_gl_visuals[i] = + get_best_gl_visual (si, ScreenOfDisplay (si->dpy, i)); + + if (real_screen_number < 0 || real_screen_number >= nscreens) abort(); + return si->best_gl_visuals[real_screen_number]; +} + + +Bool +select_visual (saver_screen_info *ssi, const char *visual_name) +{ + XWindowAttributes xgwa; + saver_info *si = ssi->global; + saver_preferences *p = &si->prefs; + Bool install_cmap_p = p->install_cmap_p; + Bool was_installed_p = (ssi->cmap != DefaultColormapOfScreen(ssi->screen)); + Visual *new_v = 0; + Bool got_it; + + /* On some systems (most recently, MacOS X) OpenGL programs get confused + when you kill one and re-start another on the same window. So maybe + it's best to just always destroy and recreate the xscreensaver window + when changing hacks, instead of trying to reuse the old one? + */ + Bool always_recreate_window_p = True; + + get_screen_gl_visual (si, 0); /* let's probe all the GL visuals early */ + + /* We make sure the existing window is actually on ssi->screen before + trying to use it, in case things moved around radically when monitors + were added or deleted. If we don't do this we could get a BadMatch + even though the depths match. I think. + */ + memset (&xgwa, 0, sizeof(xgwa)); + if (ssi->screensaver_window) + XGetWindowAttributes (si->dpy, ssi->screensaver_window, &xgwa); + + if (visual_name && *visual_name) + { + if (!strcmp(visual_name, "default-i") || + !strcmp(visual_name, "Default-i") || + !strcmp(visual_name, "Default-I") + ) + { + visual_name = "default"; + install_cmap_p = True; + } + else if (!strcmp(visual_name, "default-n") || + !strcmp(visual_name, "Default-n") || + !strcmp(visual_name, "Default-N")) + { + visual_name = "default"; + install_cmap_p = False; + } + else if (!strcmp(visual_name, "gl") || + !strcmp(visual_name, "Gl") || + !strcmp(visual_name, "GL")) + { + new_v = get_screen_gl_visual (si, ssi->real_screen_number); + if (!new_v && p->verbose_p) + fprintf (stderr, "%s: no GL visuals.\n", progname); + } + + if (!new_v) + new_v = get_visual (ssi->screen, visual_name, True, False); + } + else + { + new_v = ssi->default_visual; + } + + got_it = !!new_v; + + if (new_v && new_v != DefaultVisualOfScreen(ssi->screen)) + /* It's not the default visual, so we have no choice but to install. */ + install_cmap_p = True; + + ssi->install_cmap_p = install_cmap_p; + + if ((ssi->screen != xgwa.screen) || + (new_v && + (always_recreate_window_p || + (ssi->current_visual != new_v) || + (install_cmap_p != was_installed_p)))) + { + Colormap old_c = ssi->cmap; + Window old_w = ssi->screensaver_window; + if (! new_v) + new_v = ssi->current_visual; + + if (p->verbose_p) + { + fprintf (stderr, "%s: %d: visual ", blurb(), ssi->number); + describe_visual (stderr, ssi->screen, new_v, install_cmap_p); +#if 0 + fprintf (stderr, "%s: from ", blurb()); + describe_visual (stderr, ssi->screen, ssi->current_visual, + was_installed_p); +#endif + } + + reset_stderr (ssi); + ssi->current_visual = new_v; + ssi->current_depth = visual_depth(ssi->screen, new_v); + ssi->cmap = 0; + ssi->screensaver_window = 0; + + initialize_screensaver_window_1 (ssi); + + /* stderr_overlay_window is a child of screensaver_window, so we need + to destroy that as well (actually, we just need to invalidate and + drop our pointers to it, but this will destroy it, which is ok so + long as it happens before old_w itself is destroyed.) */ + reset_stderr (ssi); + + raise_window (si, True, True, False); + store_vroot_property (si->dpy, + ssi->screensaver_window, ssi->screensaver_window); + + /* Transfer any grabs from the old window to the new. */ + maybe_transfer_grabs (ssi, old_w, ssi->screensaver_window, ssi->number); + + /* Now we can destroy the old window without horking our grabs. */ + XDestroyWindow (si->dpy, old_w); + + if (p->verbose_p) + fprintf (stderr, "%s: %d: destroyed old saver window 0x%lx.\n", + blurb(), ssi->number, (unsigned long) old_w); + + if (old_c && + old_c != DefaultColormapOfScreen (ssi->screen) && + old_c != ssi->demo_cmap) + XFreeColormap (si->dpy, old_c); + } + + return got_it; +} diff --git a/driver/xdpyinfo.c b/driver/xdpyinfo.c new file mode 100644 index 00000000..9f679665 --- /dev/null +++ b/driver/xdpyinfo.c @@ -0,0 +1,1098 @@ +/* + * $ TOG: xdpyinfo.c /main/35 1998/02/09 13:57:05 kaleb $ + * + * xdpyinfo - print information about X display connecton + * + * +Copyright 1988, 1998 The Open Group + +All Rights Reserved. + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from The Open Group. + * + * Author: Jim Fulton, MIT X Consortium + * + * GLX and Overlay support added by Jamie Zawinski , 11-Nov-99 + * + * To compile: + * cc -DHAVE_GLX xdpyinfo.c -o xdpyinfo -lGL -lX11 -lXext [-lXtst] -lm + * + * Other defines to consider: + * -DMITSHM -DHAVE_XDBE -DHAVE_XIE -DHAVE_XTEST -DHAVE_SYNC + * -DHAVE_XRECORD + */ + +#include +#include +#include /* for CARD32 */ +#include +#ifdef HAVE_XIE +#include +#endif /* HAVE_XIE */ +#ifdef HAVE_XTEST +#include +#endif /* HAVE_XTEST */ +#ifdef HAVE_XSYNC +#include +#endif /* HAVE_XSYNC */ +#ifdef HAVE_XDBE +#include +#endif /* HAVE_XDBE */ +#ifdef HAVE_XRECORD +#include +#endif /* HAVE_XRECORD */ +#ifdef MITSHM +#include +#endif +#include +#include + +#ifdef HAVE_GLX +# include +# include +#endif /* HAVE_GLX */ + +#define HAVE_OVERLAY /* jwz: no compile-time deps, so do this all the time */ + +char *ProgramName; +Bool queryExtensions = False; + +static int StrCmp(a, b) + char **a, **b; +{ + return strcmp(*a, *b); +} + + +#ifdef HAVE_GLX /* Added by jwz, 11-Nov-99 */ + +static void +print_glx_versions (dpy) + Display *dpy; +{ + /* Note: with Mesa 3.0, this lies: it prints the info from the + client's GL library, rather than the info from the GLX server. + + Note also that we can't protect these calls by only doing + them when the GLX extension is present, because with Mesa, + the server doesn't have that extension (but the GL library + works anyway.) + */ + int scr = DefaultScreen (dpy); + const char *vend, *vers; + vend = glXQueryServerString (dpy, scr, GLX_VENDOR); + if (!vend) return; + vers = glXQueryServerString (dpy, scr, GLX_VERSION); + printf ("GLX vendor: %s (%s)\n", + vend, (vers ? vers : "unknown version")); +} + +static void +print_glx_visual_info (dpy, vip) + Display *dpy; + XVisualInfo *vip; +{ + int status, value = False; + + status = glXGetConfig (dpy, vip, GLX_USE_GL, &value); + if (status == GLX_NO_EXTENSION) + /* dpy does not support the GLX extension. */ + return; + + if (status == GLX_BAD_VISUAL || value == False) + { + printf (" GLX supported: no\n"); + return; + } + else + { + printf (" GLX supported: yes\n"); + } + + if (!glXGetConfig (dpy, vip, GLX_LEVEL, &value) && + value != 0) + printf (" GLX level: %d\n", value); + + if (!glXGetConfig (dpy, vip, GLX_RGBA, &value) && value) + { + int r=0, g=0, b=0, a=0; + glXGetConfig (dpy, vip, GLX_RED_SIZE, &r); + glXGetConfig (dpy, vip, GLX_GREEN_SIZE, &g); + glXGetConfig (dpy, vip, GLX_BLUE_SIZE, &b); + glXGetConfig (dpy, vip, GLX_ALPHA_SIZE, &a); + printf (" GLX type: RGBA (%2d, %2d, %2d, %2d)\n", + r, g, b, a); + + r=0, g=0, b=0, a=0; + glXGetConfig (dpy, vip, GLX_ACCUM_RED_SIZE, &r); + glXGetConfig (dpy, vip, GLX_ACCUM_GREEN_SIZE, &g); + glXGetConfig (dpy, vip, GLX_ACCUM_BLUE_SIZE, &b); + glXGetConfig (dpy, vip, GLX_ACCUM_ALPHA_SIZE, &a); + printf (" GLX accum: RGBA (%2d, %2d, %2d, %2d)\n", + r, g, b, a); + } + else + { + value = 0; + glXGetConfig (dpy, vip, GLX_BUFFER_SIZE, &value); + printf (" GLX type: indexed (%d)\n", value); + } + +# if 0 /* redundant */ + if (!glXGetConfig (dpy, vip, GLX_X_VISUAL_TYPE_EXT, &value)) + printf (" GLX class: %s\n", + (value == GLX_TRUE_COLOR_EXT ? "TrueColor" : + value == GLX_DIRECT_COLOR_EXT ? "DirectColor" : + value == GLX_PSEUDO_COLOR_EXT ? "PseudoColor" : + value == GLX_STATIC_COLOR_EXT ? "StaticColor" : + value == GLX_GRAY_SCALE_EXT ? "Grayscale" : + value == GLX_STATIC_GRAY_EXT ? "StaticGray" : "???")); +# endif + +# ifdef GLX_VISUAL_CAVEAT_EXT + if (!glXGetConfig (dpy, vip, GLX_VISUAL_CAVEAT_EXT, &value) && + value != GLX_NONE_EXT) + printf (" GLX rating: %s\n", + (value == GLX_NONE_EXT ? "none" : + value == GLX_SLOW_VISUAL_EXT ? "slow" : +# ifdef GLX_NON_CONFORMANT_EXT + value == GLX_NON_CONFORMANT_EXT ? "non-conformant" : +# endif + "???")); +# endif + + if (!glXGetConfig (dpy, vip, GLX_DOUBLEBUFFER, &value)) + printf (" GLX double-buffer: %s\n", (value ? "yes" : "no")); + + if (!glXGetConfig (dpy, vip, GLX_STEREO, &value) && + value) + printf (" GLX stereo: %s\n", (value ? "yes" : "no")); + + if (!glXGetConfig (dpy, vip, GLX_AUX_BUFFERS, &value) && + value != 0) + printf (" GLX aux buffers: %d\n", value); + + if (!glXGetConfig (dpy, vip, GLX_DEPTH_SIZE, &value)) + printf (" GLX depth size: %d\n", value); + + if (!glXGetConfig (dpy, vip, GLX_STENCIL_SIZE, &value) && + value != 0) + printf (" GLX stencil size: %d\n", value); + +# if defined(GL_SAMPLE_BUFFERS) +# define SB GL_SAMPLE_BUFFERS +# define SM GL_SAMPLES +# elif defined(GLX_SAMPLE_BUFFERS) +# define SB GLX_SAMPLE_BUFFERS +# define SM GLX_SAMPLES +# elif defined(GLX_SAMPLE_BUFFERS_ARB) +# define SB GLX_SAMPLE_BUFFERS_ARB +# define SM GLX_SAMPLES_ARB +# elif defined(GLX_SAMPLE_BUFFERS_SGIS) +# define SB GLX_SAMPLE_BUFFERS_SGIS +# define SM GLX_SAMPLES_SGIS +# endif + +# ifdef SB + if (!glXGetConfig (dpy, vip, SB, &value) && value != 0) + { + int bufs = value; + if (!glXGetConfig (dpy, vip, SM, &value)) + printf (" GLX multisample: %d, %d\n", bufs, value); + } +# endif /* SB */ + + if (!glXGetConfig (dpy, vip, GLX_TRANSPARENT_TYPE_EXT, &value) && + value != GLX_NONE_EXT) + { + if (value == GLX_NONE_EXT) + printf (" GLX transparency: none\n"); + else if (value == GLX_TRANSPARENT_INDEX_EXT) + { + if (!glXGetConfig (dpy, vip, GLX_TRANSPARENT_INDEX_VALUE_EXT,&value)) + printf (" GLX transparency: indexed (%d)\n", value); + } + else if (value == GLX_TRANSPARENT_RGB_EXT) + { + int r=0, g=0, b=0, a=0; + glXGetConfig (dpy, vip, GLX_TRANSPARENT_RED_VALUE_EXT, &r); + glXGetConfig (dpy, vip, GLX_TRANSPARENT_GREEN_VALUE_EXT, &g); + glXGetConfig (dpy, vip, GLX_TRANSPARENT_BLUE_VALUE_EXT, &b); + glXGetConfig (dpy, vip, GLX_TRANSPARENT_ALPHA_VALUE_EXT, &a); + printf (" GLX transparency: RGBA (%2d, %2d, %2d, %2d)\n", + r, g, b, a); + } + } +} +#endif /* HAVE_GLX */ + + +#ifdef HAVE_OVERLAY /* Added by jwz, 11-Nov-99 */ + + /* If the server's root window contains a SERVER_OVERLAY_VISUALS property, + then that identifies the visuals which correspond to the video hardware's + overlay planes. Windows created in these kinds of visuals may have + transparent pixels that let other layers shine through. + + This might not be an X Consortium standard, but it turns out that + SGI, HP, DEC, and IBM all use this same mechanism. So that's close + enough for me. + + Documentation on the SERVER_OVERLAY_VISUALS property can be found at: + http://www.hp.com/xwindow/sharedInfo/Whitepapers/Visuals/server_overlay_visuals.html + */ + +struct overlay +{ + CARD32 visual_id; + CARD32 transparency; /* 0: none; 1: pixel; 2: mask */ + CARD32 value; /* the transparent pixel */ + CARD32 layer; /* -1: underlay; 0: normal; 1: popup; 2: overlay */ +}; + +struct overlay_list +{ + int count; + struct overlay *list; +}; + +static struct overlay_list *overlays = 0; + +static void +find_overlay_info (dpy) + Display *dpy; +{ + int screen; + Atom OVERLAY = XInternAtom (dpy, "SERVER_OVERLAY_VISUALS", False); + + overlays = (struct overlay_list *) calloc (sizeof (struct overlay_list), + ScreenCount (dpy)); + + for (screen = 0; screen < ScreenCount (dpy); screen++) + { + Window window = RootWindow (dpy, screen); + Atom actual_type; + int actual_format; + unsigned long nitems, bytes_after; + struct overlay *data = 0; + int result = XGetWindowProperty (dpy, window, OVERLAY, + 0, (65536 / sizeof (long)), False, + OVERLAY, &actual_type, &actual_format, + &nitems, &bytes_after, + (unsigned char **) &data); + if (result == Success && + actual_type == OVERLAY && + actual_format == 32 && + nitems > 0) + { + overlays[screen].count = (nitems / + (sizeof(struct overlay) / sizeof(CARD32))); + overlays[screen].list = data; + } + else if (data) + XFree((char *) data); + } +} + +static void +print_overlay_visual_info (vip) + XVisualInfo *vip; +{ + int i; + int vis = vip->visualid; + int scr = vip->screen; + if (!overlays) return; + for (i = 0; i < overlays[scr].count; i++) + if (vis == overlays[scr].list[i].visual_id) + { + struct overlay *ov = &overlays[scr].list[i]; + printf (" Overlay info: layer %ld (%s), ", + (long) ov->layer, + (ov->layer == -1 ? "underlay" : + ov->layer == 0 ? "normal" : + ov->layer == 1 ? "popup" : + ov->layer == 2 ? "overlay" : "???")); + if (ov->transparency == 1) + printf ("transparent pixel %lu\n", (unsigned long) ov->value); + else if (ov->transparency == 2) + printf ("transparent mask 0x%x\n", (unsigned long) ov->value); + else + printf ("opaque\n"); + } +} +#endif /* HAVE_OVERLAY */ + + +void +print_extension_info (dpy) + Display *dpy; +{ + int n = 0; + char **extlist = XListExtensions (dpy, &n); + + printf ("number of extensions: %d\n", n); + + if (extlist) { + register int i; + int opcode, event, error; + + qsort(extlist, n, sizeof(char *), StrCmp); + for (i = 0; i < n; i++) { + if (!queryExtensions) { + printf (" %s\n", extlist[i]); + continue; + } + XQueryExtension(dpy, extlist[i], &opcode, &event, &error); + printf (" %s (opcode: %d", extlist[i], opcode); + if (event) + printf (", base event: %d", event); + if (error) + printf (", base error: %d", error); + printf(")\n"); + } + /* do not free, Xlib can depend on contents being unaltered */ + /* XFreeExtensionList (extlist); */ + } +} + +void +print_display_info (dpy) + Display *dpy; +{ + char dummybuf[40]; + char *cp; + int minkeycode, maxkeycode; + int i, n; + long req_size; + XPixmapFormatValues *pmf; + Window focuswin; + int focusrevert; + + printf ("name of display: %s\n", DisplayString (dpy)); + printf ("version number: %d.%d\n", + ProtocolVersion (dpy), ProtocolRevision (dpy)); + printf ("vendor string: %s\n", ServerVendor (dpy)); + printf ("vendor release number: %d\n", VendorRelease (dpy)); + +#ifdef HAVE_GLX + print_glx_versions (dpy); +#endif /* HAVE_GLX */ + + req_size = XExtendedMaxRequestSize (dpy); + if (!req_size) req_size = XMaxRequestSize (dpy); + printf ("maximum request size: %ld bytes\n", req_size * 4); + printf ("motion buffer size: %d\n", XDisplayMotionBufferSize (dpy)); + + switch (BitmapBitOrder (dpy)) { + case LSBFirst: cp = "LSBFirst"; break; + case MSBFirst: cp = "MSBFirst"; break; + default: + sprintf (dummybuf, "unknown order %d", BitmapBitOrder (dpy)); + cp = dummybuf; + break; + } + printf ("bitmap unit, bit order, padding: %d, %s, %d\n", + BitmapUnit (dpy), cp, BitmapPad (dpy)); + + switch (ImageByteOrder (dpy)) { + case LSBFirst: cp = "LSBFirst"; break; + case MSBFirst: cp = "MSBFirst"; break; + default: + sprintf (dummybuf, "unknown order %d", ImageByteOrder (dpy)); + cp = dummybuf; + break; + } + printf ("image byte order: %s\n", cp); + + pmf = XListPixmapFormats (dpy, &n); + printf ("number of supported pixmap formats: %d\n", n); + if (pmf) { + printf ("supported pixmap formats:\n"); + for (i = 0; i < n; i++) { + printf (" depth %d, bits_per_pixel %d, scanline_pad %d\n", + pmf[i].depth, pmf[i].bits_per_pixel, pmf[i].scanline_pad); + } + XFree ((char *) pmf); + } + + + /* + * when we get interfaces to the PixmapFormat stuff, insert code here + */ + + XDisplayKeycodes (dpy, &minkeycode, &maxkeycode); + printf ("keycode range: minimum %d, maximum %d\n", + minkeycode, maxkeycode); + + XGetInputFocus (dpy, &focuswin, &focusrevert); + printf ("focus: "); + switch (focuswin) { + case PointerRoot: + printf ("PointerRoot\n"); + break; + case None: + printf ("None\n"); + break; + default: + printf("window 0x%lx, revert to ", focuswin); + switch (focusrevert) { + case RevertToParent: + printf ("Parent\n"); + break; + case RevertToNone: + printf ("None\n"); + break; + case RevertToPointerRoot: + printf ("PointerRoot\n"); + break; + default: /* should not happen */ + printf ("%d\n", focusrevert); + break; + } + break; + } + + print_extension_info (dpy); + + printf ("default screen number: %d\n", DefaultScreen (dpy)); + printf ("number of screens: %d\n", ScreenCount (dpy)); +} + +void +print_visual_info (vip) + XVisualInfo *vip; +{ + char errorbuf[40]; /* for sprintfing into */ + char *class = NULL; /* for printing */ + + switch (vip->class) { + case StaticGray: class = "StaticGray"; break; + case GrayScale: class = "GrayScale"; break; + case StaticColor: class = "StaticColor"; break; + case PseudoColor: class = "PseudoColor"; break; + case TrueColor: class = "TrueColor"; break; + case DirectColor: class = "DirectColor"; break; + default: + sprintf (errorbuf, "unknown class %d", vip->class); + class = errorbuf; + break; + } + + printf (" visual:\n"); + printf (" visual id: 0x%lx\n", vip->visualid); + printf (" class: %s\n", class); + printf (" depth: %d plane%s\n", vip->depth, + vip->depth == 1 ? "" : "s"); + if (vip->class == TrueColor || vip->class == DirectColor) + printf (" available colormap entries: %d per subfield\n", + vip->colormap_size); + else + printf (" available colormap entries: %d\n", + vip->colormap_size); + printf (" red, green, blue masks: 0x%lx, 0x%lx, 0x%lx\n", + vip->red_mask, vip->green_mask, vip->blue_mask); + printf (" significant bits in color specification: %d bits\n", + vip->bits_per_rgb); +} + +void +print_screen_info (dpy, scr) + Display *dpy; + int scr; +{ + Screen *s = ScreenOfDisplay (dpy, scr); /* opaque structure */ + XVisualInfo viproto; /* fill in for getting info */ + XVisualInfo *vip; /* retured info */ + int nvi; /* number of elements returned */ + int i; /* temp variable: iterator */ + char eventbuf[80]; /* want 79 chars per line + nul */ + static char *yes = "YES", *no = "NO", *when = "WHEN MAPPED"; + double xres, yres; + int ndepths = 0, *depths = NULL; + unsigned int width, height; + + + /* + * there are 2.54 centimeters to an inch; so there are 25.4 millimeters. + * + * dpi = N pixels / (M millimeters / (25.4 millimeters / 1 inch)) + * = N pixels / (M inch / 25.4) + * = N * 25.4 pixels / M inch + */ + + xres = ((((double) DisplayWidth(dpy,scr)) * 25.4) / + ((double) DisplayWidthMM(dpy,scr))); + yres = ((((double) DisplayHeight(dpy,scr)) * 25.4) / + ((double) DisplayHeightMM(dpy,scr))); + + printf ("\n"); + printf ("screen #%d:\n", scr); + printf (" dimensions: %dx%d pixels (%dx%d millimeters)\n", + DisplayWidth (dpy, scr), DisplayHeight (dpy, scr), + DisplayWidthMM(dpy, scr), DisplayHeightMM (dpy, scr)); + printf (" resolution: %dx%d dots per inch\n", + (int) (xres + 0.5), (int) (yres + 0.5)); + depths = XListDepths (dpy, scr, &ndepths); + if (!depths) ndepths = 0; + printf (" depths (%d): ", ndepths); + for (i = 0; i < ndepths; i++) { + printf ("%d", depths[i]); + if (i < ndepths - 1) { + putchar (','); + putchar (' '); + } + } + putchar ('\n'); + if (depths) XFree ((char *) depths); + printf (" root window id: 0x%lx\n", RootWindow (dpy, scr)); + printf (" depth of root window: %d plane%s\n", + DisplayPlanes (dpy, scr), + DisplayPlanes (dpy, scr) == 1 ? "" : "s"); + printf (" number of colormaps: minimum %d, maximum %d\n", + MinCmapsOfScreen(s), MaxCmapsOfScreen(s)); + printf (" default colormap: 0x%lx\n", DefaultColormap (dpy, scr)); + printf (" default number of colormap cells: %d\n", + DisplayCells (dpy, scr)); + printf (" preallocated pixels: black %d, white %d\n", + BlackPixel (dpy, scr), WhitePixel (dpy, scr)); + printf (" options: backing-store %s, save-unders %s\n", + (DoesBackingStore (s) == NotUseful) ? no : + ((DoesBackingStore (s) == Always) ? yes : when), + DoesSaveUnders (s) ? yes : no); + XQueryBestSize (dpy, CursorShape, RootWindow (dpy, scr), 65535, 65535, + &width, &height); + if (width == 65535 && height == 65535) + printf (" largest cursor: unlimited\n"); + else + printf (" largest cursor: %dx%d\n", width, height); + printf (" current input event mask: 0x%lx\n", EventMaskOfScreen (s)); + (void) print_event_mask (eventbuf, 79, 4, EventMaskOfScreen (s)); + + + nvi = 0; + viproto.screen = scr; + vip = XGetVisualInfo (dpy, VisualScreenMask, &viproto, &nvi); + printf (" number of visuals: %d\n", nvi); + printf (" default visual id: 0x%lx\n", + XVisualIDFromVisual (DefaultVisual (dpy, scr))); + for (i = 0; i < nvi; i++) { + print_visual_info (vip+i); +#ifdef HAVE_OVERLAY + print_overlay_visual_info (vip+i); +#endif /* HAVE_OVERLAY */ +#ifdef HAVE_GLX + print_glx_visual_info (dpy, vip+i); +#endif /* HAVE_GLX */ + } + if (vip) XFree ((char *) vip); +} + +/* + * The following routine prints out an event mask, wrapping events at nice + * boundaries. + */ + +#define MASK_NAME_WIDTH 25 + +static struct _event_table { + char *name; + long value; +} event_table[] = { + { "KeyPressMask ", KeyPressMask }, + { "KeyReleaseMask ", KeyReleaseMask }, + { "ButtonPressMask ", ButtonPressMask }, + { "ButtonReleaseMask ", ButtonReleaseMask }, + { "EnterWindowMask ", EnterWindowMask }, + { "LeaveWindowMask ", LeaveWindowMask }, + { "PointerMotionMask ", PointerMotionMask }, + { "PointerMotionHintMask ", PointerMotionHintMask }, + { "Button1MotionMask ", Button1MotionMask }, + { "Button2MotionMask ", Button2MotionMask }, + { "Button3MotionMask ", Button3MotionMask }, + { "Button4MotionMask ", Button4MotionMask }, + { "Button5MotionMask ", Button5MotionMask }, + { "ButtonMotionMask ", ButtonMotionMask }, + { "KeymapStateMask ", KeymapStateMask }, + { "ExposureMask ", ExposureMask }, + { "VisibilityChangeMask ", VisibilityChangeMask }, + { "StructureNotifyMask ", StructureNotifyMask }, + { "ResizeRedirectMask ", ResizeRedirectMask }, + { "SubstructureNotifyMask ", SubstructureNotifyMask }, + { "SubstructureRedirectMask ", SubstructureRedirectMask }, + { "FocusChangeMask ", FocusChangeMask }, + { "PropertyChangeMask ", PropertyChangeMask }, + { "ColormapChangeMask ", ColormapChangeMask }, + { "OwnerGrabButtonMask ", OwnerGrabButtonMask }, + { NULL, 0 }}; + +int print_event_mask (buf, lastcol, indent, mask) + char *buf; /* string to write into */ + int lastcol; /* strlen(buf)+1 */ + int indent; /* amount by which to indent */ + long mask; /* event mask */ +{ + struct _event_table *etp; + int len; + int bitsfound = 0; + + buf[0] = buf[lastcol] = '\0'; /* just in case */ + +#define INDENT() { register int i; len = indent; \ + for (i = 0; i < indent; i++) buf[i] = ' '; } + + INDENT (); + + for (etp = event_table; etp->name; etp++) { + if (mask & etp->value) { + if (len + MASK_NAME_WIDTH > lastcol) { + puts (buf); + INDENT (); + } + strcpy (buf+len, etp->name); + len += MASK_NAME_WIDTH; + bitsfound++; + } + } + + if (bitsfound) puts (buf); + +#undef INDENT + + return (bitsfound); +} + +void +print_standard_extension_info(dpy, extname, majorrev, minorrev) + Display *dpy; + char *extname; + int majorrev, minorrev; +{ + int opcode, event, error; + + printf("%s version %d.%d ", extname, majorrev, minorrev); + + XQueryExtension(dpy, extname, &opcode, &event, &error); + printf ("opcode: %d", opcode); + if (event) + printf (", base event: %d", event); + if (error) + printf (", base error: %d", error); + printf("\n"); +} + +int +print_multibuf_info(dpy, extname) + Display *dpy; + char *extname; +{ + int i, j; /* temp variable: iterator */ + int nmono, nstereo; /* count */ + XmbufBufferInfo *mono_info = NULL, *stereo_info = NULL; /* arrays */ + static char *fmt = + " visual id, max buffers, depth: 0x%lx, %d, %d\n"; + int scr = 0; + int majorrev, minorrev; + + if (!XmbufGetVersion(dpy, &majorrev, &minorrev)) + return 0; + + print_standard_extension_info(dpy, extname, majorrev, minorrev); + + for (i = 0; i < ScreenCount (dpy); i++) + { + if (!XmbufGetScreenInfo (dpy, RootWindow(dpy, scr), &nmono, &mono_info, + &nstereo, &stereo_info)) { + fprintf (stderr, + "%s: unable to get multibuffer info for screen %d\n", + ProgramName, scr); + } else { + printf (" screen %d number of mono multibuffer types: %d\n", i, nmono); + for (j = 0; j < nmono; j++) { + printf (fmt, mono_info[j].visualid, mono_info[j].max_buffers, + mono_info[j].depth); + } + printf (" number of stereo multibuffer types: %d\n", nstereo); + for (j = 0; j < nstereo; j++) { + printf (fmt, stereo_info[j].visualid, + stereo_info[j].max_buffers, stereo_info[j].depth); + } + if (mono_info) XFree ((char *) mono_info); + if (stereo_info) XFree ((char *) stereo_info); + } + } + return 1; +} /* end print_multibuf_info */ + + +/* XIE stuff */ + +#ifdef HAVE_XIE + +char *subset_names[] = { NULL, "FULL", "DIS" }; +char *align_names[] = { NULL, "Alignable", "Arbitrary" }; +char *group_names[] = { /* 0 */ "Default", + /* 2 */ "ColorAlloc", + /* 4 */ "Constrain", + /* 6 */ "ConvertFromRGB", + /* 8 */ "ConvertToRGB", + /* 10 */ "Convolve", + /* 12 */ "Decode", + /* 14 */ "Dither", + /* 16 */ "Encode", + /* 18 */ "Gamut", + /* 20 */ "Geometry", + /* 22 */ "Histogram", + /* 24 */ "WhiteAdjust" + }; + +int +print_xie_info(dpy, extname) + Display *dpy; + char *extname; +{ + XieExtensionInfo *xieInfo; + int i; + int ntechs; + XieTechnique *techs; + XieTechniqueGroup prevGroup; + + if (!XieInitialize(dpy, &xieInfo )) + return 0; + + print_standard_extension_info(dpy, extname, + xieInfo->server_major_rev, xieInfo->server_minor_rev); + + printf(" service class: %s\n", subset_names[xieInfo->service_class]); + printf(" alignment: %s\n", align_names[xieInfo->alignment]); + printf(" uncnst_mantissa: %d\n", xieInfo->uncnst_mantissa); + printf(" uncnst_min_exp: %d\n", xieInfo->uncnst_min_exp); + printf(" uncnst_max_exp: %d\n", xieInfo->uncnst_max_exp); + printf(" cnst_levels:"); + for (i = 0; i < xieInfo->n_cnst_levels; i++) + printf(" %d", xieInfo->cnst_levels[i]); + printf("\n"); + + if (!XieQueryTechniques(dpy, xieValAll, &ntechs, &techs)) + return 1; + + prevGroup = -1; + + for (i = 0; i < ntechs; i++) + { + if (techs[i].group != prevGroup) + { + printf(" technique group: %s\n", group_names[techs[i].group >> 1]); + prevGroup = techs[i].group; + } + printf(" %s\tspeed: %d needs_param: %s number: %d\n", + techs[i].name, + techs[i].speed, (techs[i].needs_param ? "True " : "False"), + techs[i].number); + } + return 1; +} /* end print_xie_info */ + +#endif /* HAVE_XIE */ + + +#ifdef HAVE_XTEST +int +print_xtest_info(dpy, extname) + Display *dpy; + char *extname; +{ + int majorrev, minorrev, foo; + + if (!XTestQueryExtension(dpy, &foo, &foo, &majorrev, &minorrev)) + return 0; + print_standard_extension_info(dpy, extname, majorrev, minorrev); + return 1; +} +#endif /* HAVE_XTEST */ + +#ifdef HAVE_XSYNC +int +print_sync_info(dpy, extname) + Display *dpy; + char *extname; +{ + int majorrev, minorrev; + XSyncSystemCounter *syscounters; + int ncounters, i; + + if (!XSyncInitialize(dpy, &majorrev, &minorrev)) + return 0; + print_standard_extension_info(dpy, extname, majorrev, minorrev); + + syscounters = XSyncListSystemCounters(dpy, &ncounters); + printf(" system counters: %d\n", ncounters); + for (i = 0; i < ncounters; i++) + { + printf(" %s id: 0x%08x resolution_lo: %d resolution_hi: %d\n", + syscounters[i].name, syscounters[i].counter, + XSyncValueLow32(syscounters[i].resolution), + XSyncValueHigh32(syscounters[i].resolution)); + } + XSyncFreeSystemCounterList(syscounters); + return 1; +} +#endif /* HAVE_XSYNC */ + +int +print_shape_info(dpy, extname) + Display *dpy; + char *extname; +{ + int majorrev, minorrev; + + if (!XShapeQueryVersion(dpy, &majorrev, &minorrev)) + return 0; + print_standard_extension_info(dpy, extname, majorrev, minorrev); + return 1; +} + +#ifdef MITSHM +int +print_mitshm_info(dpy, extname) + Display *dpy; + char *extname; +{ + int majorrev, minorrev; + Bool sharedPixmaps; + + if (!XShmQueryVersion(dpy, &majorrev, &minorrev, &sharedPixmaps)) + return 0; + print_standard_extension_info(dpy, extname, majorrev, minorrev); + printf(" shared pixmaps: "); + if (sharedPixmaps) + { + int format = XShmPixmapFormat(dpy); + printf("yes, format: %d\n", format); + } + else + { + printf("no\n"); + } + return 1; +} +#endif /* MITSHM */ + +#ifdef HAVE_XDBE +int +print_dbe_info(dpy, extname) + Display *dpy; + char *extname; +{ + int majorrev, minorrev; + XdbeScreenVisualInfo *svi; + int numscreens = 0; + int iscrn, ivis; + + if (!XdbeQueryExtension(dpy, &majorrev, &minorrev)) + return 0; + + print_standard_extension_info(dpy, extname, majorrev, minorrev); + svi = XdbeGetVisualInfo(dpy, (Drawable *)NULL, &numscreens); + for (iscrn = 0; iscrn < numscreens; iscrn++) + { + printf(" Double-buffered visuals on screen %d\n", iscrn); + for (ivis = 0; ivis < svi[iscrn].count; ivis++) + { + printf(" visual id 0x%lx depth %d perflevel %d\n", + svi[iscrn].visinfo[ivis].visual, + svi[iscrn].visinfo[ivis].depth, + svi[iscrn].visinfo[ivis].perflevel); + } + } + XdbeFreeVisualInfo(svi); + return 1; +} +#endif /* HAVE_XDBE */ + +#ifdef HAVE_XRECORD +int +print_record_info(dpy, extname) + Display *dpy; + char *extname; +{ + int majorrev, minorrev; + + if (!XRecordQueryVersion(dpy, &majorrev, &minorrev)) + return 0; + print_standard_extension_info(dpy, extname, majorrev, minorrev); + return 1; +} +#endif /* HAVE_XRECORD */ + +/* utilities to manage the list of recognized extensions */ + + +typedef int (*ExtensionPrintFunc)( +#if NeedFunctionPrototypes + Display *, char * +#endif +); + +typedef struct { + char *extname; + ExtensionPrintFunc printfunc; + Bool printit; +} ExtensionPrintInfo; + +ExtensionPrintInfo known_extensions[] = +{ +#ifdef MITSHM + {"MIT-SHM", print_mitshm_info, False}, +#endif /* MITSHM */ + {MULTIBUFFER_PROTOCOL_NAME, print_multibuf_info, False}, + {"SHAPE", print_shape_info, False}, +#ifdef HAVE_XSYNC + {SYNC_NAME, print_sync_info, False}, +#endif /* HAVE_XSYNC */ +#ifdef HAVE_XIE + {xieExtName, print_xie_info, False}, +#endif /* HAVE_XIE */ +#ifdef HAVE_XTEST + {XTestExtensionName, print_xtest_info, False}, +#endif /* HAVE_XTEST */ +#ifdef HAVE_XDBE + {"DOUBLE-BUFFER", print_dbe_info, False}, +#endif /* HAVE_XDBE */ +#ifdef HAVE_XRECORD + {"RECORD", print_record_info, False} +#endif /* HAVE_XRECORD */ + /* add new extensions here */ + /* wish list: PEX XKB LBX */ +}; + +int num_known_extensions = sizeof known_extensions / sizeof known_extensions[0]; + +void +print_known_extensions(f) + FILE *f; +{ + int i; + for (i = 0; i < num_known_extensions; i++) + { + fprintf(f, "%s ", known_extensions[i].extname); + } +} + +void +mark_extension_for_printing(extname) + char *extname; +{ + int i; + + if (strcmp(extname, "all") == 0) + { + for (i = 0; i < num_known_extensions; i++) + known_extensions[i].printit = True; + } + else + { + for (i = 0; i < num_known_extensions; i++) + { + if (strcmp(extname, known_extensions[i].extname) == 0) + { + known_extensions[i].printit = True; + return; + } + } + printf("%s extension not supported by %s\n", extname, ProgramName); + } +} + +void +print_marked_extensions(dpy) + Display *dpy; +{ + int i; + for (i = 0; i < num_known_extensions; i++) + { + if (known_extensions[i].printit) + { + printf("\n"); + if (! (*known_extensions[i].printfunc)(dpy, + known_extensions[i].extname)) + { + printf("%s extension not supported by server\n", + known_extensions[i].extname); + } + } + } +} + +static void usage () +{ + fprintf (stderr, "usage: %s [options]\n", ProgramName); + fprintf (stderr, "-display displayname\tserver to query\n"); + fprintf (stderr, "-queryExtensions\tprint info returned by XQueryExtension\n"); + fprintf (stderr, "-ext all\t\tprint detailed info for all supported extensions\n"); + fprintf (stderr, "-ext extension-name\tprint detailed info for extension-name if one of:\n "); + print_known_extensions(stderr); + fprintf (stderr, "\n"); + exit (1); +} + +int main (argc, argv) + int argc; + char *argv[]; +{ + Display *dpy; /* X connection */ + char *displayname = NULL; /* server to contact */ + int i; /* temp variable: iterator */ + Bool multibuf = False; + int mbuf_event_base, mbuf_error_base; + + ProgramName = argv[0]; + + for (i = 1; i < argc; i++) { + char *arg = argv[i]; + int len = strlen(arg); + + if (!strncmp("-display", arg, len)) { + if (++i >= argc) usage (); + displayname = argv[i]; + } else if (!strncmp("-queryExtensions", arg, len)) { + queryExtensions = True; + } else if (!strncmp("-ext", arg, len)) { + if (++i >= argc) usage (); + mark_extension_for_printing(argv[i]); + } else + usage (); + } + + dpy = XOpenDisplay (displayname); + if (!dpy) { + fprintf (stderr, "%s: unable to open display \"%s\".\n", + ProgramName, XDisplayName (displayname)); + exit (1); + } + +#ifdef HAVE_OVERLAY + find_overlay_info (dpy); +#endif /* HAVE_OVERLAY */ + + print_display_info (dpy); + for (i = 0; i < ScreenCount (dpy); i++) { + print_screen_info (dpy, i); + } + + print_marked_extensions(dpy); + + XCloseDisplay (dpy); + exit (0); +} diff --git a/driver/xscreensaver-command.c b/driver/xscreensaver-command.c new file mode 100644 index 00000000..5ec74417 --- /dev/null +++ b/driver/xscreensaver-command.c @@ -0,0 +1,439 @@ +/* xscreensaver-command, Copyright (c) 1991-2008 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. + */ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include +#include +#include +#include +#include + +#ifdef HAVE_UNISTD_H +# include +#endif + +/* #include / * for CARD32 */ +#include +#include +#include /* for XGetClassHint() */ +#include + +#include /* only needed to get through xscreensaver.h */ + + +/* You might think that to read an array of 32-bit quantities out of a + server-side property, you would pass an array of 32-bit data quantities + into XGetWindowProperty(). You would be wrong. You have to use an array + of longs, even if long is 64 bits (using 32 of each 64.) + */ +typedef long PROP32; + +#include "remote.h" +#include "version.h" + +#ifdef _VROOT_H_ +ERROR! you must not include vroot.h in this file +#endif + +char *progname; + +Atom XA_VROOT; +Atom XA_SCREENSAVER, XA_SCREENSAVER_VERSION, XA_SCREENSAVER_RESPONSE; +Atom XA_SCREENSAVER_ID, XA_SCREENSAVER_STATUS, XA_SELECT, XA_DEMO, XA_EXIT; +Atom XA_BLANK, XA_LOCK; +static Atom XA_ACTIVATE, XA_DEACTIVATE, XA_CYCLE, XA_NEXT, XA_PREV; +static Atom XA_RESTART, XA_PREFS, XA_THROTTLE, XA_UNTHROTTLE; + +static char *screensaver_version; +# ifdef __GNUC__ + __extension__ /* don't warn about "string length is greater than the + length ISO C89 compilers are required to support" in the + usage string... */ +# endif +static char *usage = "\n\ +usage: %s -
+ [ ... s ... ] + [ ... s ... ] + [ ... s ... ] + [ ... s ... ] + [ ... s ... ] + [ ...
s ... ] + + + A vertical group of widgets/groups. No more than 10 widgets + or groups should be used in a column. + + Since the default alignment of widgets is a column, the + element is only of use inside an
element. + +----------------------------------------------------------------------- + + <_description> + FREE TEXT + + + This is the description of the hack that appears in the right + part of the window. Lines are wrapped; paragraphs are separated + by blank lines. Lines that begin with whitespace will not be + wrapped (see "munch.xml" for an example of why.) + + Make sure you use "<" instead of "<", etc. Character + entities are allowed; HTML (and other markup) is not. + +----------------------------------------------------------------------- + +If you are DTD-minded, you may also find the included files "xss.dtd" +and "xss.xsd" useful. + +----------------------------------------------------------------------- diff --git a/hacks/config/abstractile.xml b/hacks/config/abstractile.xml new file mode 100644 index 00000000..879da91c --- /dev/null +++ b/hacks/config/abstractile.xml @@ -0,0 +1,32 @@ + + + + + + + + + + + + + + + <_description> +Generates mosaic patterns of interlocking tiles. + +Written by Steve Sundstrom; 2004. + + diff --git a/hacks/config/anemone.xml b/hacks/config/anemone.xml new file mode 100644 index 00000000..d951149e --- /dev/null +++ b/hacks/config/anemone.xml @@ -0,0 +1,50 @@ + + + + + + + + + + + + + + + + + + + + + + + + + <_description> +Wiggling tentacles. + +Written by Gabriel Finch; 2002. + + diff --git a/hacks/config/anemotaxis.xml b/hacks/config/anemotaxis.xml new file mode 100644 index 00000000..a89862f7 --- /dev/null +++ b/hacks/config/anemotaxis.xml @@ -0,0 +1,36 @@ + + + + + + + + + + + + + + + + + <_description> +This demonstrates a search algorithm designed for locating a source of +odor in turbulent atmosphere. The searcher is able to sense the odor +and determine local instantaneous wind direction. The goal is to find +the source in the shortest mean time. + +http://en.wikipedia.org/wiki/Anemotaxis + +Written by Eugene Balkovsky; 2004. + + diff --git a/hacks/config/ant.xml b/hacks/config/ant.xml new file mode 100644 index 00000000..76fc4475 --- /dev/null +++ b/hacks/config/ant.xml @@ -0,0 +1,63 @@ + + + + + + + + + + +
+ + + +
+ +
+ + +
+ + + + + + + + <_description> +This screen saver was removed from the XScreenSaver distribution as of +version 4.22. + +A cellular automaton that is really a two-dimensional Turing machine: +as the heads ("ants") walk along the screen, they change pixel +values in their path. Then, as they pass over changed pixels, their +behavior is influenced. + +http://en.wikipedia.org/wiki/Langton%27s_ant +http://en.wikipedia.org/wiki/Turing_machine + +Written by David Bagley; 1997. + +
diff --git a/hacks/config/antinspect.xml b/hacks/config/antinspect.xml new file mode 100644 index 00000000..3558d653 --- /dev/null +++ b/hacks/config/antinspect.xml @@ -0,0 +1,21 @@ + + + + + + + + + + + + + <_description> +Draws a trio of ants moving their spheres around a circle. + +Written by Blair Tennessy; 2004. + + diff --git a/hacks/config/antmaze.xml b/hacks/config/antmaze.xml new file mode 100644 index 00000000..feadfe32 --- /dev/null +++ b/hacks/config/antmaze.xml @@ -0,0 +1,19 @@ + + + + + + + + + + + <_description> +Draws a few views of a few ants walking around in a simple maze. + +Written by Blair Tennessy; 2005. + + diff --git a/hacks/config/antspotlight.xml b/hacks/config/antspotlight.xml new file mode 100644 index 00000000..368d24a1 --- /dev/null +++ b/hacks/config/antspotlight.xml @@ -0,0 +1,21 @@ + + + + + + + + + + + + + <_description> +Draws an ant (with a headlight) who walks around on top of a loaded image. + +Written by Blair Tennessy; 2003. + + diff --git a/hacks/config/apollonian.xml b/hacks/config/apollonian.xml new file mode 100644 index 00000000..a563fcd5 --- /dev/null +++ b/hacks/config/apollonian.xml @@ -0,0 +1,38 @@ + + + + + + + + + + + + + + + + + + + + + <_description> +Draws an Apollonian gasket: a fractal packing of circles with +smaller circles, demonstrating Descartes's theorem. + +http://en.wikipedia.org/wiki/Apollonian_gasket +http://en.wikipedia.org/wiki/Descartes%27_theorem + +Written by Allan R. Wilks and David Bagley; 2002. + + diff --git a/hacks/config/apple2.xml b/hacks/config/apple2.xml new file mode 100644 index 00000000..b4fd4dda --- /dev/null +++ b/hacks/config/apple2.xml @@ -0,0 +1,62 @@ + + + + + + + + +
+ + + + + + + +
+ +
+ + + + + + + + +
+ + <_description> +Simulates an original Apple ][ Plus computer in all its 1979 glory. It +also reproduces the appearance of display on a color television set of +the period. + +In "Basic Programming Mode", a simulated user types in a BASIC program +and runs it. In "Text Mode", it displays the output of a program, or +the contents of a file or URL. In "Slideshow Mode", it chooses random +images and displays them within the limitations of the Apple ][ +display hardware. (Six available colors in hi-res mode!) + +On MacOS and Linux, this program is also a fully-functional VT100 +emulator! Run it as an application instead of as a screen saver and +you can use it as a terminal. + +http://en.wikipedia.org/wiki/Apple_II_series + +Written by Trevor Blackwell; 2003. + +
diff --git a/hacks/config/atlantis.xml b/hacks/config/atlantis.xml new file mode 100644 index 00000000..fffa06af --- /dev/null +++ b/hacks/config/atlantis.xml @@ -0,0 +1,46 @@ + + + + + + + + + + + + + + +
+ + + +
+ +
+ + +
+ + <_description> +A 3D animation of a number of sharks, dolphins, and whales. + +Written by Mark Kilgard; 1998. + +
diff --git a/hacks/config/attraction.xml b/hacks/config/attraction.xml new file mode 100644 index 00000000..c4646eef --- /dev/null +++ b/hacks/config/attraction.xml @@ -0,0 +1,83 @@ + + + + + + +
+ + + + +
+ +
+ + + + + + + + + + + +
+ +
+ + + +
+ + + + + + + + + + + <_description> + +Points attract each other up to a certain distance, and then begin to +repel each other. The attraction/repulsion is proportional to the +distance between any two particles, similar to the strong and weak +nuclear forces. + +Written by Jamie Zawinski and John Pezaris; 1992. + +
diff --git a/hacks/config/atunnel.xml b/hacks/config/atunnel.xml new file mode 100644 index 00000000..7e1e2826 --- /dev/null +++ b/hacks/config/atunnel.xml @@ -0,0 +1,22 @@ + + + + + + + + + + + + + + <_description> +Zooming through a textured tunnel. + +Written by Eric Lassauge and Roman Podobedov; 2003. + + diff --git a/hacks/config/barcode.xml b/hacks/config/barcode.xml new file mode 100644 index 00000000..13564ce6 --- /dev/null +++ b/hacks/config/barcode.xml @@ -0,0 +1,32 @@ + + + + + + + + + + + + + <_description> +Draws a random sequence of colorful barcodes scrolling across your +screen. CONSUME! + +The barcodes follow the UPC-A, UPC-E, EAN-8 or EAN-13 standards. + +http://en.wikipedia.org/wiki/Universal_Product_Code +http://en.wikipedia.org/wiki/European_Article_Number + +Written by Dan Bornstein; 2003. + + diff --git a/hacks/config/blaster.xml b/hacks/config/blaster.xml new file mode 100644 index 00000000..c03c135c --- /dev/null +++ b/hacks/config/blaster.xml @@ -0,0 +1,59 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + <_description> +Draws a simulation of flying space-combat robots (cleverly disguised +as colored circles) doing battle in front of a moving star field. + +Written by Jonathan Lin; 1999. + + diff --git a/hacks/config/blinkbox.xml b/hacks/config/blinkbox.xml new file mode 100644 index 00000000..e04da27d --- /dev/null +++ b/hacks/config/blinkbox.xml @@ -0,0 +1,31 @@ + + + + + + + + + + +
+ + + + +
+ + + + <_description> +A motion-blurred ball bounces inside a box whose tiles only become +visible upon impact. + +Written by Jeremy English; 2003. + +
diff --git a/hacks/config/blitspin.xml b/hacks/config/blitspin.xml new file mode 100644 index 00000000..00cfaccc --- /dev/null +++ b/hacks/config/blitspin.xml @@ -0,0 +1,38 @@ + + + + + + + + + + + + + + + + + + + <_description> + +Repeatedly rotates a bitmap by 90 degrees by using logical operations: +the bitmap is divided into quadrants, and the quadrants are shifted +clockwise. Then the same thing is done again with progressively +smaller quadrants, except that all sub-quadrants of a given size are +rotated in parallel. As you watch it, the image appears to dissolve +into static and then reconstitute itself, but rotated. + +Written by Jamie Zawinski; 1992. + + diff --git a/hacks/config/blocktube.xml b/hacks/config/blocktube.xml new file mode 100644 index 00000000..9a9743c8 --- /dev/null +++ b/hacks/config/blocktube.xml @@ -0,0 +1,30 @@ + + + + + + + + + + + + + + + + + <_description> +Draws a swirling, falling tunnel of reflective slabs. They fade from +hue to hue. + +Written by Lars R. Damerow; 2003. + + diff --git a/hacks/config/boing.xml b/hacks/config/boing.xml new file mode 100644 index 00000000..1d877aa7 --- /dev/null +++ b/hacks/config/boing.xml @@ -0,0 +1,47 @@ + + + + + + + + + + + +
+ + +
+
+ + + +
+
+ + +
+
+ + <_description> + +This bouncing ball is a clone of the first graphics demo for the Amiga +1000, which was written by Dale Luck and RJ Mical during a break at +the 1984 Consumer Electronics Show (or so the legend goes.) + +This looks like the original Amiga demo if you turn off "smoothing" +and "lighting" and turn on "scanlines", and is somewhat more modern +otherwise. + +http://en.wikipedia.org/wiki/Amiga#Boing_Ball + +Written by Jamie Zawinski; 2005. + +
diff --git a/hacks/config/bouboule.xml b/hacks/config/bouboule.xml new file mode 100644 index 00000000..237646a3 --- /dev/null +++ b/hacks/config/bouboule.xml @@ -0,0 +1,30 @@ + + + + + + + + + + + + + + + + + <_description> +This draws what looks like a spinning, deforming balloon with +varying-sized spots painted on its invisible surface. + +Written by Jeremie Petit; 1997. + + diff --git a/hacks/config/bouncingcow.xml b/hacks/config/bouncingcow.xml new file mode 100644 index 00000000..1bb9f97b --- /dev/null +++ b/hacks/config/bouncingcow.xml @@ -0,0 +1,28 @@ + + + + + + + + + + + + + + + + <_description> +A Cow. A Trampoline. Together, they fight crime. + +Written by Jamie Zawinski; 2003. + + diff --git a/hacks/config/boxed.xml b/hacks/config/boxed.xml new file mode 100644 index 00000000..e00c974b --- /dev/null +++ b/hacks/config/boxed.xml @@ -0,0 +1,54 @@ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + +
+ + + <_description> +Draws a box full of 3D bouncing balls that explode. + +Written by Sander van Grieken; 2002. + +
diff --git a/hacks/config/boxfit.xml b/hacks/config/boxfit.xml new file mode 100644 index 00000000..a7d35bf9 --- /dev/null +++ b/hacks/config/boxfit.xml @@ -0,0 +1,55 @@ + + + + + + + + +
+ + + +
+ +
+ + + +
+ +
+ + + +
+ + + + + + + + <_description> +Packs the screen with growing squares or circles, colored according to +a horizontal or vertical gradient, or according to the colors of a +loaded image. The objects grow until they touch, then stop. When the +screen is full, they shrink away and the process restarts. + +Written by Jamie Zawinski; 2005. + +
diff --git a/hacks/config/braid.xml b/hacks/config/braid.xml new file mode 100644 index 00000000..f9cfa54d --- /dev/null +++ b/hacks/config/braid.xml @@ -0,0 +1,35 @@ + + + + + + + + + + + + +
+ + + +
+ + + + <_description> +Draws random color-cycling inter-braided concentric circles. + +Written by John Neil; 1997. + +
diff --git a/hacks/config/bsod.xml b/hacks/config/bsod.xml new file mode 100644 index 00000000..016479ac --- /dev/null +++ b/hacks/config/bsod.xml @@ -0,0 +1,88 @@ + + + + + + +
+ + +
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + <_description> +BSOD stands for "Blue Screen of Death". The finest in personal +computer emulation, BSOD simulates popular screen savers from a +number of less robust operating systems. + +http://en.wikipedia.org/wiki/Blue_Screen_of_Death +http://en.wikipedia.org/wiki/Screen_of_death +http://en.wikipedia.org/wiki/Guru_Meditation +http://en.wikipedia.org/wiki/Row_of_Bombs +http://en.wikipedia.org/wiki/Bomb_%28symbol%29 + +Written by Jamie Zawinski; 1998. + +
diff --git a/hacks/config/bubble3d.xml b/hacks/config/bubble3d.xml new file mode 100644 index 00000000..573763a6 --- /dev/null +++ b/hacks/config/bubble3d.xml @@ -0,0 +1,21 @@ + + + + + + + + + + + + <_description> +Draws a stream of rising, undulating 3D bubbles, rising toward the +top of the screen, with transparency and specular reflections. + +Written by Richard Jones; 1998. + + diff --git a/hacks/config/bubbles.xml b/hacks/config/bubbles.xml new file mode 100644 index 00000000..bf675546 --- /dev/null +++ b/hacks/config/bubbles.xml @@ -0,0 +1,38 @@ + + + + + + + + + + + + + + + + + + + <_description> +This screen saver was removed from the XScreenSaver distribution as of +version 5.08. + +This simulates the kind of bubble formation that happens when water +boils: small bubbles appear, and as they get closer to each other, +they combine to form larger bubbles, which eventually pop. + +Written by James Macnicol; 1996. + + diff --git a/hacks/config/bumps.xml b/hacks/config/bumps.xml new file mode 100644 index 00000000..5c49021c --- /dev/null +++ b/hacks/config/bumps.xml @@ -0,0 +1,32 @@ + + + + + + + + + + + + + + + + + + + + + + <_description> +A spotlight roams across an embossed version of a loaded image. + +Written by Shane Smit; 1999. + + diff --git a/hacks/config/cage.xml b/hacks/config/cage.xml new file mode 100644 index 00000000..03b89467 --- /dev/null +++ b/hacks/config/cage.xml @@ -0,0 +1,23 @@ + + + + + + + + + + + + <_description> +This draws Escher's "Impossible Cage", a 3d analog of a moebius +strip, and rotates it in three dimensions. + +http://en.wikipedia.org/wiki/Maurits_Cornelis_Escher + +Written by Marcelo Vianna; 1998. + + diff --git a/hacks/config/carousel.xml b/hacks/config/carousel.xml new file mode 100644 index 00000000..87e8fdac --- /dev/null +++ b/hacks/config/carousel.xml @@ -0,0 +1,53 @@ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + +
+ + + + <_description> +Loads several random images, and displays them flying in a circular +formation. The formation changes speed and direction randomly, and +images periodically drop out to be replaced by new ones. + +Written by Jamie Zawinski; 2005. + +
diff --git a/hacks/config/ccurve.xml b/hacks/config/ccurve.xml new file mode 100644 index 00000000..203e6746 --- /dev/null +++ b/hacks/config/ccurve.xml @@ -0,0 +1,28 @@ + + + + + + + + + + + + + + + <_description> +Generates self-similar linear fractals, including the classic "C Curve". + +http://en.wikipedia.org/wiki/Levy_C_curve + +Written by Rick Campbell; 1999. + + diff --git a/hacks/config/celtic.xml b/hacks/config/celtic.xml new file mode 100644 index 00000000..b38040ab --- /dev/null +++ b/hacks/config/celtic.xml @@ -0,0 +1,28 @@ + + + + + + + + + + + + + + + <_description> +Repeatedly draws random Celtic cross-stitch patterns. + +http://en.wikipedia.org/wiki/Celtic_knot +http://en.wikipedia.org/wiki/Knots_and_graphs + +Written by Max Froumentin; 2005. + + diff --git a/hacks/config/circuit.xml b/hacks/config/circuit.xml new file mode 100644 index 00000000..25d6a2ea --- /dev/null +++ b/hacks/config/circuit.xml @@ -0,0 +1,33 @@ + + + + + + + + + + + + + + + + + + <_description> +Animates a number of 3D electronic components. + +Written by Ben Buxton; 2001. + + diff --git a/hacks/config/cloudlife.xml b/hacks/config/cloudlife.xml new file mode 100644 index 00000000..859d15f3 --- /dev/null +++ b/hacks/config/cloudlife.xml @@ -0,0 +1,37 @@ + + + + + + + + + + + + + + + + + <_description> + +Generates cloud-like formations based on a variant of Conway's Life. The +difference is that cells have a maximum age, after which they count as +3 for populating the next generation. This makes long-lived formations +explode instead of just sitting there. + +http://en.wikipedia.org/wiki/Conway%27s_Game_of_Life + +Written by Don Marti; 2003. + + diff --git a/hacks/config/companioncube.xml b/hacks/config/companioncube.xml new file mode 100644 index 00000000..e16256eb --- /dev/null +++ b/hacks/config/companioncube.xml @@ -0,0 +1,52 @@ + + + + + + +
+ + + + + + + + + + + +
+ + + + + + + + +
+ +
+
+ + <_description> +The symptoms most commonly produced by Enrichment Center testing are +superstition, perceiving inanimate objects as alive, and hallucinations. +The Enrichment Center reminds you that the weighted companion cube will +never threaten to stab you and, in fact, cannot speak. In the event that +the Weighted Companion Cube does speak, the Enrichment Center urges you to +disregard its advice. + +http://en.wikipedia.org/wiki/Portal_%28video_game%29 + +Written by Jamie Zawinski; 2011. + +
diff --git a/hacks/config/compass.xml b/hacks/config/compass.xml new file mode 100644 index 00000000..4e903f0a --- /dev/null +++ b/hacks/config/compass.xml @@ -0,0 +1,20 @@ + + + + + + + + + + + <_description> +This draws a compass, with all elements spinning about randomly, for +that "lost and nauseous" feeling. + +Written by Jamie Zawinski; 1999. + + diff --git a/hacks/config/coral.xml b/hacks/config/coral.xml new file mode 100644 index 00000000..e9182702 --- /dev/null +++ b/hacks/config/coral.xml @@ -0,0 +1,32 @@ + + + + + + + + + + + + + + + + + <_description> +Simulates coral growth, albeit somewhat slowly. + +Written by Frederick Roeber; 1997. + + diff --git a/hacks/config/crackberg.xml b/hacks/config/crackberg.xml new file mode 100644 index 00000000..4abb2018 --- /dev/null +++ b/hacks/config/crackberg.xml @@ -0,0 +1,48 @@ + + + + + + + + + + + +
+ + + + + + + + + + + + +
+ + + + <_description> +Flies through height maps, optionally animating the creation and +destruction of generated tiles; tiles `grow' into place. + +Written by Matus Telgarsky; 2005. + +
diff --git a/hacks/config/critical.xml b/hacks/config/critical.xml new file mode 100644 index 00000000..ceef8326 --- /dev/null +++ b/hacks/config/critical.xml @@ -0,0 +1,27 @@ + + + + + + + + + + + + + <_description> +This screen saver was removed from the XScreenSaver distribution as of +version 5.08. + +Draws a system of self-organizing lines. It starts out as random +squiggles, but after a few iterations, order begins to appear. + +Written by Martin Pool; 1999. + + diff --git a/hacks/config/crystal.xml b/hacks/config/crystal.xml new file mode 100644 index 00000000..2f2d972f --- /dev/null +++ b/hacks/config/crystal.xml @@ -0,0 +1,44 @@ + + + + + + + + + + + + + + + + + + + +
+ + + +
+ + + + <_description> +Moving polygons, similar to a kaleidoscope. See also the +"Kaleidescope" and "GLeidescope" screen savers. + +http://en.wikipedia.org/wiki/Kaleidoscope + +Written by Jouk Jansen; 1998. + +
diff --git a/hacks/config/cube21.xml b/hacks/config/cube21.xml new file mode 100644 index 00000000..23e37675 --- /dev/null +++ b/hacks/config/cube21.xml @@ -0,0 +1,73 @@ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + +
+ + + +
+
+ + +
+ +
+
+ + <_description> +Animates a Rubik-like puzzle known as Cube 21 or Square-1. +The rotations are chosen randomly. See also the "Rubik", +"RubikBlocks" and "GLSnake" screen savers. + +http://en.wikipedia.org/wiki/Square_One_%28puzzle%29 + +Written by Vasek Potocek; 2005. + +
diff --git a/hacks/config/cubenetic.xml b/hacks/config/cubenetic.xml new file mode 100644 index 00000000..aadbfc37 --- /dev/null +++ b/hacks/config/cubenetic.xml @@ -0,0 +1,57 @@ + + + + + + + + + + +
+ + + +
+ + + + + + + +
+ + + +
+ + <_description> +Draws a pulsating set of overlapping boxes with ever-chaning blobby +patterns undulating across their surfaces. It's sort of a cubist Lavalite. + +Written by Jamie Zawinski; 2002. + +
diff --git a/hacks/config/cubestorm.xml b/hacks/config/cubestorm.xml new file mode 100644 index 00000000..077aa660 --- /dev/null +++ b/hacks/config/cubestorm.xml @@ -0,0 +1,38 @@ + + + + + + + + + + + + + + +
+ + + +
+ + + + <_description> +Draws a series of rotating 3D boxes that intersect each other and +eventually fill space. + +Written by Jamie Zawinski; 2003. + +
diff --git a/hacks/config/cubicgrid.xml b/hacks/config/cubicgrid.xml new file mode 100644 index 00000000..962299b9 --- /dev/null +++ b/hacks/config/cubicgrid.xml @@ -0,0 +1,28 @@ + + + + + + + + + + + + + + + + <_description> +Draws the view of an observer located inside a rotating 3D lattice of colored +points. + +Written by Vasek Potocek; 2007. + + diff --git a/hacks/config/cwaves.xml b/hacks/config/cwaves.xml new file mode 100644 index 00000000..215d9fe8 --- /dev/null +++ b/hacks/config/cwaves.xml @@ -0,0 +1,27 @@ + + + + + + + + + + + + + + + <_description> +This generates a languidly-scrolling vertical field of sinusoidal colors. + +Written by Jamie Zawinski; 2007. + + diff --git a/hacks/config/cynosure.xml b/hacks/config/cynosure.xml new file mode 100644 index 00000000..ac1350e6 --- /dev/null +++ b/hacks/config/cynosure.xml @@ -0,0 +1,28 @@ + + + + + + + + + + + + + + + + <_description> +Random dropshadowed rectangles pop onto the screen in lockstep. + +Written by Ozymandias G. Desiderata, Jamie Zawinski, and Stephen Linhart; 1998. + + diff --git a/hacks/config/dangerball.xml b/hacks/config/dangerball.xml new file mode 100644 index 00000000..41450430 --- /dev/null +++ b/hacks/config/dangerball.xml @@ -0,0 +1,33 @@ + + + + + + + + + + + + +
+ + + +
+ + + + <_description> +Draws a ball that periodically extrudes many random spikes. Ouch! + +Written by Jamie Zawinski; 2001. + +
diff --git a/hacks/config/decayscreen.xml b/hacks/config/decayscreen.xml new file mode 100644 index 00000000..b3245fa6 --- /dev/null +++ b/hacks/config/decayscreen.xml @@ -0,0 +1,45 @@ + + + + + + + + + + + + + + + + + <_description> +This takes an image and makes it melt, toward a randomly chosen point +or direction. Warning, if the effect continues after the screen saver +is off, seek medical attention. + +Written by David Wald, Vivek Khera, Jamie Zawinski, and Vince Levey; 1993. + + diff --git a/hacks/config/deco.xml b/hacks/config/deco.xml new file mode 100644 index 00000000..e2ff33bc --- /dev/null +++ b/hacks/config/deco.xml @@ -0,0 +1,41 @@ + + + + + + + + + + +
+ + + + + + + + + + + + + +
+ + <_description> +Subdivides and colors rectangles randomly, for a Mondrian-esque effect. + +http://en.wikipedia.org/wiki/Piet_Mondrian#Paris_1919.E2.80.931938 + +Written by Jamie Zawinski and Michael Bayne; 1997. + +
diff --git a/hacks/config/deluxe.xml b/hacks/config/deluxe.xml new file mode 100644 index 00000000..de3b4955 --- /dev/null +++ b/hacks/config/deluxe.xml @@ -0,0 +1,35 @@ + + + + + + + + + + + + + + + + + + + + + <_description> +Draws a pulsing sequence of transparent stars, circles, and lines. + +Written by Jamie Zawinski; 1999. + + diff --git a/hacks/config/demon.xml b/hacks/config/demon.xml new file mode 100644 index 00000000..c99799cf --- /dev/null +++ b/hacks/config/demon.xml @@ -0,0 +1,37 @@ + + + + + + + + + + + + + + + + + + + <_description> +A cellular automaton that starts with a random field, and organizes +it into stripes and spirals. + +http://en.wikipedia.org/wiki/Maxwell%27s_demon + +Written by David Bagley; 1999. + + diff --git a/hacks/config/discrete.xml b/hacks/config/discrete.xml new file mode 100644 index 00000000..153f331a --- /dev/null +++ b/hacks/config/discrete.xml @@ -0,0 +1,28 @@ + + + + + + + + + + + + + + + <_description> +Discrete map fractal systems, including variants of Hopalong, Julia, +and others. + +Written by Tim Auckland; 1998. + + diff --git a/hacks/config/distort.xml b/hacks/config/distort.xml new file mode 100644 index 00000000..b78998dc --- /dev/null +++ b/hacks/config/distort.xml @@ -0,0 +1,49 @@ + + + + + + + + + + + + + + + +
+ + + +
+ +
+ + + + + +
+ + + + <_description> +Wandering lenses distort the screen image in various ways. + +Written by Jonas Munsin; 1998. + +
diff --git a/hacks/config/dnalogo.xml b/hacks/config/dnalogo.xml new file mode 100644 index 00000000..9942905e --- /dev/null +++ b/hacks/config/dnalogo.xml @@ -0,0 +1,36 @@ + + + + + + + + + +
+ + +
+ + <_description> +DNA Lounge + + Restaurant -- Bar -- Nightclub -- Cafe -- Est. 1985. + + 375 Eleventh Street + San Francisco, CA + 94103 + + http://www.dnalounge.com/ + http://www.dnapizza.com/ + +Written by Jamie Zawinski; 2001. + +
diff --git a/hacks/config/drift.xml b/hacks/config/drift.xml new file mode 100644 index 00000000..aacfe0d2 --- /dev/null +++ b/hacks/config/drift.xml @@ -0,0 +1,27 @@ + + + + + + + + + + + + + + + <_description> +Drifting recursive fractal cosmic flames. + +Written by Scott Draves; 1997. + + diff --git a/hacks/config/endgame.xml b/hacks/config/endgame.xml new file mode 100644 index 00000000..a2fa7f3c --- /dev/null +++ b/hacks/config/endgame.xml @@ -0,0 +1,25 @@ + + + + + + + + + + + + <_description> +Black slips out of three mating nets, but the fourth one holds him tight! +A brilliant composition! + +See also the "Queens" screen saver. + +http://en.wikipedia.org/wiki/Chess_endgame + +Written by Blair Tennessy; 2002. + + diff --git a/hacks/config/engine.xml b/hacks/config/engine.xml new file mode 100644 index 00000000..ccae48f0 --- /dev/null +++ b/hacks/config/engine.xml @@ -0,0 +1,40 @@ + + + + + + + + + + + +
+ + +
+ + + <_description> +Draws a simple model of an engine that floats around the screen. + +http://en.wikipedia.org/wiki/Internal_combustion_engine#Operation + +Written by Ben Buxton and Ed Beroset; 2001. + +
diff --git a/hacks/config/epicycle.xml b/hacks/config/epicycle.xml new file mode 100644 index 00000000..0d5aecb2 --- /dev/null +++ b/hacks/config/epicycle.xml @@ -0,0 +1,52 @@ + + + + + + + + + + + + +
+ + + +
+ + + + + + + + + + + + + + + + <_description> +This draws the path traced out by a point on the edge of a +circle. That circle rotates around a point on the rim of another +circle, and so on, several times. These were the basis for the +pre-heliocentric model of planetary motion. + +http://en.wikipedia.org/wiki/Deferent_and_epicycle + +Written by James Youngman; 1998. + +
diff --git a/hacks/config/eruption.xml b/hacks/config/eruption.xml new file mode 100644 index 00000000..86af1667 --- /dev/null +++ b/hacks/config/eruption.xml @@ -0,0 +1,49 @@ + + + + + + +
+ + + + + + + + + + + + + + + + + + +
+ + <_description> +Exploding fireworks. See also the "Fireworkx", "XFlame" and "Pyro" +screen savers. + +Written by W.P. van Paassen; 2003. + +
diff --git a/hacks/config/euler2d.xml b/hacks/config/euler2d.xml new file mode 100644 index 00000000..f69b24a9 --- /dev/null +++ b/hacks/config/euler2d.xml @@ -0,0 +1,44 @@ + + + + + + + + + + + + + + + + + + + + + <_description> +Simulates two dimensional incompressible inviscid fluid flow. + +http://en.wikipedia.org/wiki/Euler_equations_%28fluid_dynamics%29 +http://en.wikipedia.org/wiki/Inviscid_flow + +Written by Stephen Montgomery-Smith; 2002. + + diff --git a/hacks/config/extrusion.xml b/hacks/config/extrusion.xml new file mode 100644 index 00000000..48d42368 --- /dev/null +++ b/hacks/config/extrusion.xml @@ -0,0 +1,41 @@ + + + + + + + + + + + + + + + + + + + + <_description> +Draws various rotating extruded shapes that twist around, lengthen, +and turn inside out. + +Written by Linas Vepstas, David Konerding, and Jamie Zawinski; 1999. + + diff --git a/hacks/config/fadeplot.xml b/hacks/config/fadeplot.xml new file mode 100644 index 00000000..368224fd --- /dev/null +++ b/hacks/config/fadeplot.xml @@ -0,0 +1,31 @@ + + + + + + + + + + + + + + + + + <_description> +Draws what looks like a waving ribbon following a sinusoidal path. + +Written by Bas van Gaalen and Charles Vidal; 1997. + + diff --git a/hacks/config/fiberlamp.xml b/hacks/config/fiberlamp.xml new file mode 100644 index 00000000..9357730f --- /dev/null +++ b/hacks/config/fiberlamp.xml @@ -0,0 +1,27 @@ + + + + + + + + + + + + + + + <_description> +Draws a groovy rotating fiber optic lamp. + +Written by Tim Auckland; 2005. + + diff --git a/hacks/config/fireworkx.xml b/hacks/config/fireworkx.xml new file mode 100644 index 00000000..2a8f675d --- /dev/null +++ b/hacks/config/fireworkx.xml @@ -0,0 +1,28 @@ + + + + + + + + + + + + + + + + + <_description> +Exploding fireworks. See also the "Eruption", "XFlame" and "Pyro" +screen savers. + +Written by Rony B Chandran; 2004. + + diff --git a/hacks/config/flag.xml b/hacks/config/flag.xml new file mode 100644 index 00000000..93155fb2 --- /dev/null +++ b/hacks/config/flag.xml @@ -0,0 +1,37 @@ + + + + + + + + + + + + + + + + + + + <_description> +This screen saver was removed from the XScreenSaver distribution as of +version 5.08. + +This draws a waving colored flag, that undulates its way around the +screen. The flag can contain arbitrary text and images. By default, +it displays either the current system name and OS type, or a picture +of "Bob". + +Written by Charles Vidal and Jamie Zawinski; 1997. + + diff --git a/hacks/config/flame.xml b/hacks/config/flame.xml new file mode 100644 index 00000000..8fce71c2 --- /dev/null +++ b/hacks/config/flame.xml @@ -0,0 +1,35 @@ + + + + + + + + + + + + + + + + + + + <_description> +Iterative fractals. + +Written by Scott Draves; 1993. + + diff --git a/hacks/config/flipflop.xml b/hacks/config/flipflop.xml new file mode 100644 index 00000000..3a7828fe --- /dev/null +++ b/hacks/config/flipflop.xml @@ -0,0 +1,48 @@ + + + + + + +
+ + + + + + + + + + + + +
+ +
+ + + + + + + + +
+ + <_description> +Draws a grid of 3D colored tiles that change positions with each other. + +Written by Kevin Ogden and Sergio Gutierrez; 2003. + +
diff --git a/hacks/config/flipscreen3d.xml b/hacks/config/flipscreen3d.xml new file mode 100644 index 00000000..662f8ff2 --- /dev/null +++ b/hacks/config/flipscreen3d.xml @@ -0,0 +1,23 @@ + + + + + + + + + + + + + + + <_description> +Spins and deforms an image. + +Written by Ben Buxton and Jamie Zawinski; 2001. + + diff --git a/hacks/config/fliptext.xml b/hacks/config/fliptext.xml new file mode 100644 index 00000000..270ee242 --- /dev/null +++ b/hacks/config/fliptext.xml @@ -0,0 +1,47 @@ + + + + + + + + + + +
+ + + + + + + + + + + + + + +
+ + <_description> +Draws successive pages of text. The lines flip in and out in +a soothing 3D pattern. + +Written by Jamie Zawinski; 2005. + +
diff --git a/hacks/config/flow.xml b/hacks/config/flow.xml new file mode 100644 index 00000000..76d1bf4c --- /dev/null +++ b/hacks/config/flow.xml @@ -0,0 +1,56 @@ + + + + + + +
+ + + + + + + + + + + + +
+ +
+ + + + + + + + + + +
+ + <_description> +Strange attractors formed of flows in a 3D differential equation phase +space. Features the popular attractors described by Lorentz, +Roessler, Birkhoff and Duffing, and can discover entirely new +attractors by itself. + +http://en.wikipedia.org/wiki/Attractor#Strange_attractor + +Written by Tim Auckland; 1998. + +
diff --git a/hacks/config/fluidballs.xml b/hacks/config/fluidballs.xml new file mode 100644 index 00000000..10b342f2 --- /dev/null +++ b/hacks/config/fluidballs.xml @@ -0,0 +1,49 @@ + + + + + + +
+ + + + + + + + + + + + + + +
+ + + + + + <_description> +Models the physics of bouncing balls, or of particles in a gas or +fluid, depending on the settings. If "Shake Box" is selected, then +every now and then, the box will be rotated, changing which direction +is down (in order to keep the settled balls in motion.) + +Written by Peter Birtles and Jamie Zawinski; 2002. + +
diff --git a/hacks/config/flurry.xml b/hacks/config/flurry.xml new file mode 100644 index 00000000..0c689c16 --- /dev/null +++ b/hacks/config/flurry.xml @@ -0,0 +1,28 @@ + + + + + + + + + + + <_description> +This X11 port of the OSX screensaver of the same name draws a colourful +star(fish)like flurry of particles. + +Original Mac version: http://homepage.mac.com/calumr + +Written by Calum Robinson and Tobias Sargeant; 2002. + + diff --git a/hacks/config/flyingtoasters.xml b/hacks/config/flyingtoasters.xml new file mode 100644 index 00000000..45721bfe --- /dev/null +++ b/hacks/config/flyingtoasters.xml @@ -0,0 +1,38 @@ + + + + + + + + + + + + + + +
+ + + +
+ + <_description> +A fleet of 3d space-age jet-powered flying toasters (and toast!) +Inspired by the ancient Berkeley Systems After Dark flying toasters. + +http://en.wikipedia.org/wiki/After_Dark_%28software%29#Flying_Toasters + +Written by Jamie Zawinski and Devon Dossett; 2003. + +
diff --git a/hacks/config/fontglide.xml b/hacks/config/fontglide.xml new file mode 100644 index 00000000..58dadcbf --- /dev/null +++ b/hacks/config/fontglide.xml @@ -0,0 +1,44 @@ + + + + + + +
+ + + + + + + + + + + + + +
+ + + + <_description> +Puts text on the screen using large characters that glide in from the +edges, assemble, then disperse. Alternately, it can simply scroll whole +sentences from right to left. + +Written by Jamie Zawinski; 2003. + +
diff --git a/hacks/config/forest.xml b/hacks/config/forest.xml new file mode 100644 index 00000000..2b8d64e9 --- /dev/null +++ b/hacks/config/forest.xml @@ -0,0 +1,26 @@ + + + + + + + + + + + + + <_description> +This screen saver was removed from the XScreenSaver distribution as of +version 5.08. + +Fractal trees. + +Written by Peter Baumung; 1997. + + diff --git a/hacks/config/fuzzyflakes.xml b/hacks/config/fuzzyflakes.xml new file mode 100644 index 00000000..4a94f685 --- /dev/null +++ b/hacks/config/fuzzyflakes.xml @@ -0,0 +1,62 @@ + + + + + + +
+ + + + + + + +
+ + +
+ + + +
+ + + + + + + +
+ + <_description> +Falling colored snowflake/flower shapes. + +http://en.wikipedia.org/wiki/Snowflake + +Written by Barry Dmytro; 2004. + +
diff --git a/hacks/config/galaxy.xml b/hacks/config/galaxy.xml new file mode 100644 index 00000000..bc116cd5 --- /dev/null +++ b/hacks/config/galaxy.xml @@ -0,0 +1,33 @@ + + + + + + + + + + + + + + + + + + + <_description> +This draws spinning galaxies, which then collide and scatter their +stars to the, uh, four winds or something. + +Written by Uli Siegmund, Harald Backert, and Hubert Feyrer; 1997. + + diff --git a/hacks/config/gears.xml b/hacks/config/gears.xml new file mode 100644 index 00000000..16b8cf31 --- /dev/null +++ b/hacks/config/gears.xml @@ -0,0 +1,36 @@ + + + + + + + + + + + + +
+ + + + +
+ + <_description> +This draws sets of turning, interlocking gears, rotating in three +dimensions. See also the "Pinion" and "MoebiusGears" screen savers. + +http://en.wikipedia.org/wiki/Involute_gear +http://en.wikipedia.org/wiki/Epicyclic_gearing + +Written by Jamie Zawinski; 2007. + +
diff --git a/hacks/config/gflux.xml b/hacks/config/gflux.xml new file mode 100644 index 00000000..0b3c17d4 --- /dev/null +++ b/hacks/config/gflux.xml @@ -0,0 +1,57 @@ + + + + + + +
+ + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + <_description> +Draws undulating waves on a rotating grid. + +Written by Josiah Pease; 2000. + +
diff --git a/hacks/config/glblur.xml b/hacks/config/glblur.xml new file mode 100644 index 00000000..19a80d32 --- /dev/null +++ b/hacks/config/glblur.xml @@ -0,0 +1,43 @@ + + + + + + + + + + + + + + + + + <_description> +Generates flowing field effects from the vapor trails around a moving +object. + +This is done by rendering the scene into a small texture, then +repeatedly rendering increasingly-enlarged and increasingly-transparent +versions of that texture onto the frame buffer. As such, it's quite +GPU-intensive: if you don't have a very good graphics card, it +will hurt your machine bad. + +Written by Jamie Zawinski; 2002. + + diff --git a/hacks/config/glcells.xml b/hacks/config/glcells.xml new file mode 100644 index 00000000..7f38d48b --- /dev/null +++ b/hacks/config/glcells.xml @@ -0,0 +1,60 @@ + + + + + + +
+ + + + + + + + + + + + + + +
+ +
+ + + +
+ + <_description> +Cells growing, dividing and dying on your screen. Microscopic pathos. + +Written by Matthias Toussaint; 2007. + +
diff --git a/hacks/config/gleidescope.xml b/hacks/config/gleidescope.xml new file mode 100644 index 00000000..025fec88 --- /dev/null +++ b/hacks/config/gleidescope.xml @@ -0,0 +1,37 @@ + + + + + + + + + + + + +
+ + + + +
+ + + + <_description> +A kaleidoscope that operates on a loaded image. + +http://en.wikipedia.org/wiki/Kaleidoscope + +Written by Andrew Dean; 2003. + +
diff --git a/hacks/config/glforestfire.xml b/hacks/config/glforestfire.xml new file mode 100644 index 00000000..feec5da5 --- /dev/null +++ b/hacks/config/glforestfire.xml @@ -0,0 +1,42 @@ + + + + + + + + + + + + +
+ + + + + + + + + + +
+ + <_description> +This screen saver was removed from the XScreenSaver distribution as of +version 5.08. + +Draws an animation of sprinkling fire-like 3D triangles in a landscape +filled with trees. + +Written by Eric Lassauge; 2002. + +
diff --git a/hacks/config/glhanoi.xml b/hacks/config/glhanoi.xml new file mode 100644 index 00000000..81f35d57 --- /dev/null +++ b/hacks/config/glhanoi.xml @@ -0,0 +1,44 @@ + + + + + + + + + + + + + + + + + + + + + + + + + <_description> +Solves the Towers of Hanoi puzzle. Move N disks from one pole to +another, one disk at a time, with no disk ever resting on a disk +smaller than itself. + +http://en.wikipedia.org/wiki/Tower_of_Hanoi + +Written by Dave Atkinson; 2005. + + diff --git a/hacks/config/glknots.xml b/hacks/config/glknots.xml new file mode 100644 index 00000000..e6dd137c --- /dev/null +++ b/hacks/config/glknots.xml @@ -0,0 +1,59 @@ + + + + + + +
+ + + + + + + + + + + + + + +
+ + +
+ +
+ +
+ +
+
+ + <_description> +Generates some twisting 3d knot patterns. Spins 'em around. + +http://en.wikipedia.org/wiki/Knot_theory + +Written by Jamie Zawinski; 2003. + +
diff --git a/hacks/config/glmatrix.xml b/hacks/config/glmatrix.xml new file mode 100644 index 00000000..2b8ea5a3 --- /dev/null +++ b/hacks/config/glmatrix.xml @@ -0,0 +1,50 @@ + + + + + + + + + + + + + + +
+ + + +
+ +
+ + + +
+ + <_description> +Draws the 3D "digital rain" effect, as seen in the title sequence +of "The Matrix". + +See also "xmatrix" for a 2D rendering of the similar effect that +appeared on the computer monitors actually *in* the movie. + +http://en.wikipedia.org/wiki/Matrix_digital_rain + +Written by Jamie Zawinski; 2003. + +
diff --git a/hacks/config/glplanet.xml b/hacks/config/glplanet.xml new file mode 100644 index 00000000..c7d27179 --- /dev/null +++ b/hacks/config/glplanet.xml @@ -0,0 +1,38 @@ + + + + + + + + + + + + + +
+ + + + +
+ +
+ + + +
+ + <_description> +Draws the Earth bouncing around in space. + +If you would like it to display a different planet, the texture maps +that come with "ssystem" work well. + +Written by David Konerding; 1998. + +
diff --git a/hacks/config/glschool.xml b/hacks/config/glschool.xml new file mode 100644 index 00000000..8ca0211d --- /dev/null +++ b/hacks/config/glschool.xml @@ -0,0 +1,41 @@ + + + + + + +
+ + + + + + + + + + + + +
+ +
+ + + + + +
+ + <_description> +Uses Craig Reynolds' classic "Boids" algorithm to simulate a school of fish. + +http://en.wikipedia.org/wiki/Boids + +Written by David C. Lambert; 2006. + +
diff --git a/hacks/config/glslideshow.xml b/hacks/config/glslideshow.xml new file mode 100644 index 00000000..7e30eb9c --- /dev/null +++ b/hacks/config/glslideshow.xml @@ -0,0 +1,56 @@ + + + + + + +
+ + + + + + + + + + + + + + +
+ +
+ + + + + + + + +
+ + <_description> +Loads a random sequence of images and smoothly scans and zooms around +in each, fading from pan to pan. + +Written by Jamie Zawinski and Mike Oliphant; 2003. + +
diff --git a/hacks/config/glsnake.xml b/hacks/config/glsnake.xml new file mode 100644 index 00000000..3efc7f49 --- /dev/null +++ b/hacks/config/glsnake.xml @@ -0,0 +1,53 @@ + + + + + + +
+ + + + + + + + + + + + + + + +
+ + +
+ + + +
+ + <_description> +Draws a simulation of the Rubik's Snake puzzle. See also the "Rubik" +and "Cube21" screen savers. + +http://en.wikipedia.org/wiki/Rubik%27s_Snake + +Written by Jamie Wilkinson, Andrew Bennetts, and Peter Aylett; 2002. + +
diff --git a/hacks/config/gltext.xml b/hacks/config/gltext.xml new file mode 100644 index 00000000..8a1eb591 --- /dev/null +++ b/hacks/config/gltext.xml @@ -0,0 +1,47 @@ + + + + + + + + + + +
+ + +
+ + + + + + + <_description> +Displays a few lines of text spinning around in a solid 3D font. +The text can use strftime() escape codes to display the current +date and time. + +Written by Jamie Zawinski; 2001. + +
diff --git a/hacks/config/goop.xml b/hacks/config/goop.xml new file mode 100644 index 00000000..f8b1ab48 --- /dev/null +++ b/hacks/config/goop.xml @@ -0,0 +1,61 @@ + + + + + + +
+ + + + + + + + + + + + + + + + +
+ +
+ + + +
+ + <_description> +This draws set of animating, transparent, amoeba-like blobs. The blobs +change shape as they wander around the screen, and they are translucent, +so you can see the lower blobs through the higher ones, and when one +passes over another, their colors merge. I got the idea for this from +a mouse pad I had once, which achieved the same kind of effect in real +life by having several layers of plastic with colored oil between them. + +Written by Jamie Zawinski; 1997. + +
diff --git a/hacks/config/grav.xml b/hacks/config/grav.xml new file mode 100644 index 00000000..915e00a2 --- /dev/null +++ b/hacks/config/grav.xml @@ -0,0 +1,32 @@ + + + + + + + + + + + + +
+ + + +
+ + <_description> +This draws a simple orbital simulation. With trails enabled, +it looks kind of like a cloud-chamber photograph. + +Written by Greg Bowering; 1997. + +
diff --git a/hacks/config/greynetic.xml b/hacks/config/greynetic.xml new file mode 100644 index 00000000..3604dba7 --- /dev/null +++ b/hacks/config/greynetic.xml @@ -0,0 +1,21 @@ + + + + + + + + + + + + + <_description> +Draws random colored, stippled and transparent rectangles. + +Written by Jamie Zawinski; 1992. + + diff --git a/hacks/config/halftone.xml b/hacks/config/halftone.xml new file mode 100644 index 00000000..4eaef74b --- /dev/null +++ b/hacks/config/halftone.xml @@ -0,0 +1,55 @@ + + + + + + +
+ + + + + + + + + + + + + + + + + + +
+ + + + <_description> +Draws the gravity force in each point on the screen seen through a +halftone dot pattern. The gravity force is calculated from a set of +moving mass points. View it from a distance for best effect. + +http://en.wikipedia.org/wiki/Halftone + +Written by Peter Jaric; 2002. + +
diff --git a/hacks/config/halo.xml b/hacks/config/halo.xml new file mode 100644 index 00000000..dfbaaf0e --- /dev/null +++ b/hacks/config/halo.xml @@ -0,0 +1,38 @@ + + + + + + + + + + + + + + +
+ + +
+ + <_description> +Draws circular interference patterns that hurt to look at. + +http://en.wikipedia.org/wiki/Moire_pattern + +Written by Jamie Zawinski; 1993. + +
diff --git a/hacks/config/helix.xml b/hacks/config/helix.xml new file mode 100644 index 00000000..b2eb11d2 --- /dev/null +++ b/hacks/config/helix.xml @@ -0,0 +1,23 @@ + + + + + + + + + + + + + <_description> +Spirally string-art-ish patterns. + +Written by Jamie Zawinski; 1992. + + diff --git a/hacks/config/hilbert.xml b/hacks/config/hilbert.xml new file mode 100644 index 00000000..e58a8c6c --- /dev/null +++ b/hacks/config/hilbert.xml @@ -0,0 +1,73 @@ + + + + + + +
+ + +
+ + + +
+ +
+ + + + + + + + + + + +
+ +
+ + + + +
+ +
+
+ + <_description> +This draws the recursive Hilbert space-filling curve, in both 2D and +3D variants. It incrementally animates the growth and recursion to +the maximum depth, then unwinds it back. + +The Hilbert path is a single contiguous line that can fill a volume +without crossing itself. As a data structure, Hilbert paths are +useful because ordering along the curve preserves locality: points +that are close together along the curve are also close together in space. +The converse is often, but not always, true. The coloration +reflects this. + +http://en.wikipedia.org/wiki/Hilbert_curve + +Written by Jamie Zawinski; 2011. + +
diff --git a/hacks/config/hopalong.xml b/hacks/config/hopalong.xml new file mode 100644 index 00000000..4c91dbba --- /dev/null +++ b/hacks/config/hopalong.xml @@ -0,0 +1,55 @@ + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + +
+ + <_description> +This draws lacy fractal patterns based on iteration in the imaginary +plane, from a 1986 Scientific American article. See also the +"Discrete" screen saver. + +Written by Patrick Naughton; 1992. + +
diff --git a/hacks/config/hyperball.xml b/hacks/config/hyperball.xml new file mode 100644 index 00000000..5d80bd91 --- /dev/null +++ b/hacks/config/hyperball.xml @@ -0,0 +1,61 @@ + + + + + + + + + + +
+ + + + + + + + + + +
+ + + + <_description> +This screen saver was removed from the XScreenSaver distribution as of +version 5.10. It has been replaced by the more general "Polytopes" +screen saver, which can display this object as well as others. The +Polytopes "120-cell" object corresponds to this one. + +Hyperball is to hypercube as dodecahedron is to cube: this displays +a 2D projection of the sequence of 3D objects which are the projections +of the 4D analog to the dodecahedron. Technically, it is a "120 cell +polytope". + +http://en.wikipedia.org/wiki/Hypercube +http://en.wikipedia.org/wiki/Regular_polytope + +Written by Joe Keane; 2000. + +
diff --git a/hacks/config/hypercube.xml b/hacks/config/hypercube.xml new file mode 100644 index 00000000..472430e2 --- /dev/null +++ b/hacks/config/hypercube.xml @@ -0,0 +1,71 @@ + + + + + + +
+ + + + + + + + + + + + + + +
+ + + + + + + + + + + + + <_description> +This screen saver was removed from the XScreenSaver distribution as of +version 5.10. It has been replaced by the more general "Polytopes" +screen saver, which can display this object as well as others. + +This displays 2D projections of the sequence of 3D objects which are +the projections of the 4D analog to the cube: as a square is composed +of four lines, each touching two others; and a cube is composed of +six squares, each touching four others; a hypercube is composed of +eight cubes, each touching six others. To make it easier to +visualize the rotation, it uses a different color for the edges of +each face. Don't think about it too long, or your brain will melt. + +http://en.wikipedia.org/wiki/Hypercube +http://en.wikipedia.org/wiki/Tesseract +http://en.wikipedia.org/wiki/Regular_polytope + +Written by Joe Keane, Fritz Mueller, and Jamie Zawinski; 1992. + +
diff --git a/hacks/config/hypertorus.xml b/hacks/config/hypertorus.xml new file mode 100644 index 00000000..2d061959 --- /dev/null +++ b/hacks/config/hypertorus.xml @@ -0,0 +1,114 @@ + + + + + + +
+ + +
+ +
+ + + +
+ +
+ + + + + +
+ +
+ + + + + + + + + + + + + + + + + + + + + +
+ + <_description> +This shows a rotating Clifford Torus: a torus lying on the +"surface" of a 4D hypersphere. Inspired by Thomas Banchoff's book +"Beyond the Third Dimension: Geometry, Computer Graphics, and Higher +Dimensions", Scientific American Library, 1990. + +http://en.wikipedia.org/wiki/N-sphere +http://en.wikipedia.org/wiki/Clifford_torus +http://en.wikipedia.org/wiki/Regular_polytope + +Written by Carsten Steger; 2003. + +
diff --git a/hacks/config/hypnowheel.xml b/hacks/config/hypnowheel.xml new file mode 100644 index 00000000..68d9a9a1 --- /dev/null +++ b/hacks/config/hypnowheel.xml @@ -0,0 +1,50 @@ + + + + + + +
+ + + + + +
+ + +
+ + + +
+ + + + + + + + +
+ + <_description> +Draws a series of overlapping, translucent spiral patterns. +The tightness of their spirals fluctuates in and out. + +http://en.wikipedia.org/wiki/Moire_pattern + +Written by Jamie Zawinski; 2008. + +
diff --git a/hacks/config/ifs.xml b/hacks/config/ifs.xml new file mode 100644 index 00000000..fda3119c --- /dev/null +++ b/hacks/config/ifs.xml @@ -0,0 +1,61 @@ + + + + + + + + + + + + + + + + +
+ + + + +
+ + <_description> + +Clouds of iterated function systems spin and collide. + +Note that the "Detail" parameter is exponential. Number of points +drawn is functions^detail. + +http://en.wikipedia.org/wiki/Iterated_function_system + +Written by Chris Le Sueur and Robby Griffin; 1997. + +
diff --git a/hacks/config/imsmap.xml b/hacks/config/imsmap.xml new file mode 100644 index 00000000..51adcfe7 --- /dev/null +++ b/hacks/config/imsmap.xml @@ -0,0 +1,42 @@ + + + + + + + + + + + + + + + + + + + <_description> +This generates random cloud-like patterns. The idea is to take four +points on the edge of the image, and assign each a random "elevation". +Then find the point between them, and give it a value which is the +average of the other four, plus some small random offset. +Coloration is done based on elevation. + +Written by Juergen Nickelsen and Jamie Zawinski; 1992. + + diff --git a/hacks/config/interaggregate.xml b/hacks/config/interaggregate.xml new file mode 100644 index 00000000..7335d750 --- /dev/null +++ b/hacks/config/interaggregate.xml @@ -0,0 +1,29 @@ + + + + + + + + + + + + + <_description> +Pale pencil-like scribbles slowly fill the screen. + +A surface is filled with a hundred medium to small sized circles. +Each circle has a different size and direction, but moves at the same +slow rate. Displays the instantaneous intersections of the circles as +well as the aggregate intersections of the circles. + +Though actually it doesn't look like circles at all! + +Written by Casey Reas, William Ngan, Robert Hodgin, and Jamie Zawinski; 2004. + + diff --git a/hacks/config/interference.xml b/hacks/config/interference.xml new file mode 100644 index 00000000..eed84c44 --- /dev/null +++ b/hacks/config/interference.xml @@ -0,0 +1,53 @@ + + + + + + +
+ + + + + + + + + + + + + + + + + + + +
+ + + + <_description> +Color field based on computing decaying sinusoidal waves. + +Written by Hannu Mallat; 1998. + +
diff --git a/hacks/config/intermomentary.xml b/hacks/config/intermomentary.xml new file mode 100644 index 00000000..d5a43714 --- /dev/null +++ b/hacks/config/intermomentary.xml @@ -0,0 +1,33 @@ + + + + + + + + + + + + + <_description> +Blinking dots interact with each other circularly. + +A surface is filled with a hundred medium to small sized circles. +Each circle has a different size and direction, but moves at the same +slow rate. Displays the instantaneous intersections of the circles as +well as the aggregate intersections of the circles. + +The circles begin with a radius of 1 pixel and slowly increase to some +arbitrary size. Circles are drawn with small moving points along the +perimeter. The intersections are rendered as glowing orbs. Glowing +orbs are rendered only when a perimeter point moves past the +intersection point. + +Written by Casey Reas, William Ngan, Robert Hodgin, and Jamie Zawinski; 2004. + + diff --git a/hacks/config/jigglypuff.xml b/hacks/config/jigglypuff.xml new file mode 100644 index 00000000..219fb497 --- /dev/null +++ b/hacks/config/jigglypuff.xml @@ -0,0 +1,88 @@ + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + + + +
+ + <_description> +This does bad things with quasi-spherical objects. + +You have a tetrahedron with tesselated faces. The vertices on these +faces have forces on them: one proportional to the distance from the +surface of a sphere; and one proportional to the distance from the +neighbors. They also have inertia. The resulting effect can range +from a shape that does nothing, to a frenetic polygon storm. +Somewhere in between there it usually manifests as a blob that jiggles +in a kind of disturbing manner. + +Written by Keith Macleod; 2003. + + +
+ + + + + + + + diff --git a/hacks/config/jigsaw.xml b/hacks/config/jigsaw.xml new file mode 100644 index 00000000..6e665499 --- /dev/null +++ b/hacks/config/jigsaw.xml @@ -0,0 +1,47 @@ + + + + + + +
+ + + + + + + + + + +
+ +
+ + + + + + + +
+ + <_description> +This carves an image up into a jigsaw puzzle, shuffles it, and solves it. + +http://en.wikipedia.org/wiki/Jigsaw_puzzle +http://en.wikipedia.org/wiki/Tessellation + +Written by Jamie Zawinski; 1997. + +
diff --git a/hacks/config/juggle.xml b/hacks/config/juggle.xml new file mode 100644 index 00000000..ade836e7 --- /dev/null +++ b/hacks/config/juggle.xml @@ -0,0 +1,56 @@ + + + + + + +
+ + + + + + + + + + +
+ +
+ + + + + + + + + + + + +
+ + + + + + + <_description> +This screen saver was removed from the XScreenSaver distribution as of +version 5.09. It has been replaced by the "Juggler3D" screen saver. + +Written by Tim Auckland; 2002. + +
diff --git a/hacks/config/juggler3d.xml b/hacks/config/juggler3d.xml new file mode 100644 index 00000000..9247cc40 --- /dev/null +++ b/hacks/config/juggler3d.xml @@ -0,0 +1,51 @@ + + + + + +
+ + + + + + + + + + +
+ +
+ + + + + + +
+ + + + + + + <_description> +Draws a 3D juggling stick-man, with Cambridge juggling pattern +notation used to describe the patterns he juggles. + +http://en.wikipedia.org/wiki/Siteswap + +Written by Tim Auckland and Jamie Zawinski; 2002. + +
diff --git a/hacks/config/julia.xml b/hacks/config/julia.xml new file mode 100644 index 00000000..7213412e --- /dev/null +++ b/hacks/config/julia.xml @@ -0,0 +1,35 @@ + + + + + + + + + + + + + + + + + <_description> +Animates the Julia set (a close relative of the Mandelbrot set). The +small moving dot indicates the control point from which the rest of +the image was generated. See also the "Discrete" screen saver. + +http://en.wikipedia.org/wiki/Julia_set + +Written by Sean McCullough; 1997. + + diff --git a/hacks/config/kaleidescope.xml b/hacks/config/kaleidescope.xml new file mode 100644 index 00000000..25df7fda --- /dev/null +++ b/hacks/config/kaleidescope.xml @@ -0,0 +1,38 @@ + + + + + + + + + + + + + + + + + + + + + <_description> +A simple kaleidoscope made of line segments. See "GLeidescope" +for a more sophisticated take. + +http://en.wikipedia.org/wiki/Kaleidoscope + +Written by Ron Tapia; 1997. + + diff --git a/hacks/config/klein.xml b/hacks/config/klein.xml new file mode 100644 index 00000000..64d7301a --- /dev/null +++ b/hacks/config/klein.xml @@ -0,0 +1,127 @@ + + + + + + +
+ + +
+ +
+ + + + + +
+ +
+ + + +
+ +
+ + + + + +
+ +
+ + + + + + + + + + + + + + + + + + + +
+ + <_description> +This animates a Klein bottle, the 4D analog of a moebius strip. + +You can walk on the surface of the bottle or rotate it in 4D or walk +on it while it rotates in 4D. Inspired by Thomas Banchoff's book +"Beyond the Third Dimension: Geometry, Computer Graphics, and Higher +Dimensions", Scientific American Library, 1990. + +http://en.wikipedia.org/wiki/Klein_bottle + +Written by Carsten Steger; 2008. + +
diff --git a/hacks/config/kumppa.xml b/hacks/config/kumppa.xml new file mode 100644 index 00000000..192b4266 --- /dev/null +++ b/hacks/config/kumppa.xml @@ -0,0 +1,28 @@ + + + + + + + + + + + + + + + + + <_description> +Spiraling, spinning, and very, very fast splashes of color rush +toward the screen. + +Written by Teemu Suutari; 1998. + + diff --git a/hacks/config/lament.xml b/hacks/config/lament.xml new file mode 100644 index 00000000..50107447 --- /dev/null +++ b/hacks/config/lament.xml @@ -0,0 +1,26 @@ + + + + + + + + + + + + + <_description> +Animates a simulation of Lemarchand's Box, the Lament Configuration, +repeatedly solving itself. + +Warning: occasionally opens doors. + +http://en.wikipedia.org/wiki/Lemarchand%27s_box + +Written by Jamie Zawinski; 1998. + + diff --git a/hacks/config/laser.xml b/hacks/config/laser.xml new file mode 100644 index 00000000..5ef6eecd --- /dev/null +++ b/hacks/config/laser.xml @@ -0,0 +1,34 @@ + + + + + + + + + + + + + + + + + <_description> +This screen saver was removed from the XScreenSaver distribution as of +version 5.08. + +Moving radiating lines, that look vaguely like scanning laser beams. +(Frankie say relax.) + +Written by Pascal Pensa; 1997. + + diff --git a/hacks/config/lavalite.xml b/hacks/config/lavalite.xml new file mode 100644 index 00000000..c6e4d488 --- /dev/null +++ b/hacks/config/lavalite.xml @@ -0,0 +1,86 @@ + + + + + + +
+ + + + + + + + + + +
+ +
+ + +
+ + + +
+ +
+ + +
+ +
+ + + + + + + +
+ + <_description> +Draws a 3D Simulation a Lava Lite(r). Odd-shaped blobs of a mysterious +substance are heated, slowly rise to the top of the bottle, and then +drop back down as they cool. This simulation requires a fairly fast +machine (both CPU and 3D performance.) + +"LAVA LITE(r) and the configuration of the LAVA(r) brand motion lamp are +registered trademarks of Haggerty Enterprises, Inc. The configuration +of the globe and base of the motion lamp are registered trademarks of +Haggerty Enterprises, Inc. in the U.S.A. and in other countries around +the world." + +http://en.wikipedia.org/wiki/Lava_lamp +http://en.wikipedia.org/wiki/Metaballs +http://en.wikipedia.org/wiki/Lavarand + +Written by Jamie Zawinski; 2002. + +
diff --git a/hacks/config/lcdscrub.xml b/hacks/config/lcdscrub.xml new file mode 100644 index 00000000..09206b6c --- /dev/null +++ b/hacks/config/lcdscrub.xml @@ -0,0 +1,51 @@ + + + + + + + + +
+ + + + + + + + + + + + + + + + + +
+ + <_description> +This screen saver is not meant to look pretty, but rather, to +repair burn-in on LCD monitors. + +Believe it or not, screen burn is not a thing of the past. +It can happen to LCD screens pretty easily, even in this modern age. +However, leaving the screen on and displaying high contrast images +can often repair the damage. That's what this screen saver does. + +See also: +http://docs.info.apple.com/article.html?artnum=88343 +http://toastycode.com/blog/2008/02/05/lcd-scrub/ + +Inspired by the like-named program by Daniel Sandler. + +Written by Jamie Zawinski; 2008. + +
diff --git a/hacks/config/lightning.xml b/hacks/config/lightning.xml new file mode 100644 index 00000000..9633a617 --- /dev/null +++ b/hacks/config/lightning.xml @@ -0,0 +1,26 @@ + + + + + + + + + + + + + <_description> +This screen saver was removed from the XScreenSaver distribution as of +version 5.08. + +Crackling fractal lightning bolts. + +Written by Keith Romberg; 1997. + + diff --git a/hacks/config/lisa.xml b/hacks/config/lisa.xml new file mode 100644 index 00000000..8d3d35f1 --- /dev/null +++ b/hacks/config/lisa.xml @@ -0,0 +1,40 @@ + + + + + + + + + + + + + + + + + + + <_description> +This screen saver was removed from the XScreenSaver distribution as of +version 5.08. + +Lissajous loops. + +http://en.wikipedia.org/wiki/Lissajous_curve + +Written by Caleb Cullen; 1997. + + diff --git a/hacks/config/lissie.xml b/hacks/config/lissie.xml new file mode 100644 index 00000000..18ad4d22 --- /dev/null +++ b/hacks/config/lissie.xml @@ -0,0 +1,39 @@ + + + + + + + + + + + + + + + + + + + <_description> +This screen saver was removed from the XScreenSaver distribution as of +version 5.08. + +Lissajous loops. This one draws the progress of circular shapes along a path. + +http://en.wikipedia.org/wiki/Lissajous_curve + +Written by Alexander Jolk; 1997. + + diff --git a/hacks/config/lmorph.xml b/hacks/config/lmorph.xml new file mode 100644 index 00000000..1fa654de --- /dev/null +++ b/hacks/config/lmorph.xml @@ -0,0 +1,41 @@ + + + + + + + + + + + + + + + + + + + <_description> +This screen saver was removed from the XScreenSaver distribution as of +version 5.08. + +This generates random spline-ish line drawings and morphs between +them. + +Written by Sverre H. Huseby and Glenn T. Lines; 1995. + + diff --git a/hacks/config/lockward.xml b/hacks/config/lockward.xml new file mode 100644 index 00000000..55ff54c7 --- /dev/null +++ b/hacks/config/lockward.xml @@ -0,0 +1,63 @@ + + + + + + + + +
+ + + + + + + +
+ + +
+ +
+ + + + + + + + +
+ + <_description> +A translucent spinning, blinking thing. Sort of a cross between the wards +in an old combination lock and those old backlit information displays that +animated and changed color via polarized light. + +Written by Leo L. Schwab; 2007. + +
diff --git a/hacks/config/loop.xml b/hacks/config/loop.xml new file mode 100644 index 00000000..01d658ee --- /dev/null +++ b/hacks/config/loop.xml @@ -0,0 +1,33 @@ + + + + + + + + + + + + + + + + + <_description> +A cellular automaton that generates loop-shaped colonies that spawn, +age, and eventually die. + +http://en.wikipedia.org/wiki/Langton%27s_loops + +Written by David Bagley; 1999. + + diff --git a/hacks/config/m6502.xml b/hacks/config/m6502.xml new file mode 100644 index 00000000..6340824b --- /dev/null +++ b/hacks/config/m6502.xml @@ -0,0 +1,49 @@ + + + + + + + + + + + + +
+ + + + + + + + +
+ + <_description> +This emulates a 6502 microprocessor, and runs some example programs on +it. + +The family of 6502 chips were used throughout the 70's and 80's in +machines such as the Atari 2600, Commodore PET, VIC20 and C64, Apple +][, and the NES. Some example programs are included, and it can also +read in an assembly file as input. + +Original JavaScript Version by Stian Soreng: http://www.6502asm.com/. +Ported to XScreenSaver by Jeremy English. + +Written by Stian Soreng and Jeremy English; 2007. + +
diff --git a/hacks/config/maze.xml b/hacks/config/maze.xml new file mode 100644 index 00000000..0de676af --- /dev/null +++ b/hacks/config/maze.xml @@ -0,0 +1,56 @@ + + + + + + + + + + + + + + + + +
+ + + +
+ + <_description> +This generates random mazes, with three different algorithms: Kruskal, +Prim, and a depth-first recursive backtracker. It also solves them. +Backtracking and look-ahead paths are displayed in different colors. + +http://en.wikipedia.org/wiki/Maze_generation_algorithm +http://en.wikipedia.org/wiki/Maze_solving_algorithm + +Written by Martin Weiss, Dave Lemke, Jim Randell, Jamie Zawinski, +Johannes Keukelaar, and Zack Weinberg; 1985. + +
diff --git a/hacks/config/memscroller.xml b/hacks/config/memscroller.xml new file mode 100644 index 00000000..bf56694c --- /dev/null +++ b/hacks/config/memscroller.xml @@ -0,0 +1,30 @@ + + + + + + + + + + + + + + + <_description> +This draws a dump of its own process memory scrolling across the screen +in three windows at three different rates. + +Written by Jamie Zawinski; 2004. + + diff --git a/hacks/config/menger.xml b/hacks/config/menger.xml new file mode 100644 index 00000000..a39d49a2 --- /dev/null +++ b/hacks/config/menger.xml @@ -0,0 +1,47 @@ + + + + + + + + + + + + + + + + + + + + + + <_description> +This draws the recursive Menger Gasket, a cube-based fractal object +analagous to the Sierpinski Tetrahedron. + +http://en.wikipedia.org/wiki/Menger_sponge +http://en.wikipedia.org/wiki/Sierpinski_carpet + +Written by Jamie Zawinski; 2001. + + diff --git a/hacks/config/metaballs.xml b/hacks/config/metaballs.xml new file mode 100644 index 00000000..899272af --- /dev/null +++ b/hacks/config/metaballs.xml @@ -0,0 +1,51 @@ + + + + + + + + +
+ + + + + + + + + + + + + + + + + +
+ + + + <_description> + +Draws two dimensional metaballs: overlapping and merging balls with +fuzzy edges. + +http://en.wikipedia.org/wiki/Metaballs + +Written by W.P. van Paassen; 2003. + +
diff --git a/hacks/config/mirrorblob.xml b/hacks/config/mirrorblob.xml new file mode 100644 index 00000000..3521a42a --- /dev/null +++ b/hacks/config/mirrorblob.xml @@ -0,0 +1,70 @@ + + + + + + +
+ + + + + + + + + + + + + + + + +
+ +
+ + + + + + + + + + + + + + + +
+ + <_description> +Draws a wobbly blob that distorts the image behind it. + +Written by Jon Dowdall; 2003. + +
diff --git a/hacks/config/mismunch.xml b/hacks/config/mismunch.xml new file mode 100644 index 00000000..dd47c0fe --- /dev/null +++ b/hacks/config/mismunch.xml @@ -0,0 +1,40 @@ + + + + + + + + + + + + + + + + + <_description> +This screen saver was removed from the XScreenSaver distribution as of +version 5.08. It was merged with the "Munch" screen saver. + +Munching errors! This is a creatively broken misimplementation of the +classic munching squares graphics hack. See the "Munch" screen saver +for the original. + +http://en.wikipedia.org/wiki/HAKMEM +http://en.wikipedia.org/wiki/Munching_square + +Written by Steven Hazel; 2004. + + diff --git a/hacks/config/moebius.xml b/hacks/config/moebius.xml new file mode 100644 index 00000000..804395a1 --- /dev/null +++ b/hacks/config/moebius.xml @@ -0,0 +1,25 @@ + + + + + + + + + + + + + <_description> +This animates a 3D rendition M.C. Escher's "Moebius Strip II", +an image of ants walking along the surface of a moebius strip. + +http://en.wikipedia.org/wiki/Moebius_strip +http://en.wikipedia.org/wiki/Maurits_Cornelis_Escher + +Written by Marcelo F. Vianna; 1997. + + diff --git a/hacks/config/moebiusgears.xml b/hacks/config/moebiusgears.xml new file mode 100644 index 00000000..bd6f0d70 --- /dev/null +++ b/hacks/config/moebiusgears.xml @@ -0,0 +1,43 @@ + + + + + + + + + + +
+ + + +
+ +
+ + + + +
+ + + + <_description> +Draws a closed, interlinked chain of rotating gears. The layout of +the gears follows the path of a moebius strip. See also the "Pinion" +and "Gears" screen savers. + +http://en.wikipedia.org/wiki/Involute_gear +http://en.wikipedia.org/wiki/Moebius_strip + +Written by Jamie Zawinski; 2007. + +
diff --git a/hacks/config/moire.xml b/hacks/config/moire.xml new file mode 100644 index 00000000..6e4c9b9d --- /dev/null +++ b/hacks/config/moire.xml @@ -0,0 +1,34 @@ + + + + + + + + + + + + + + + + + + + <_description> + When the lines on the screen + Make more lines in between, + That's a moire'! + +http://en.wikipedia.org/wiki/Moire_pattern + +Written by Jamie Zawinski and Michael Bayne; 1997. + + diff --git a/hacks/config/moire2.xml b/hacks/config/moire2.xml new file mode 100644 index 00000000..1c5d7f14 --- /dev/null +++ b/hacks/config/moire2.xml @@ -0,0 +1,30 @@ + + + + + + + + + + + + + + + <_description> +Generates fields of concentric circles or ovals, and combines the +planes with various operations. The planes are moving independently +of one another, causing the interference lines to spray. + +http://en.wikipedia.org/wiki/Moire_pattern + +Written by Jamie Zawinski; 1998. + + diff --git a/hacks/config/molecule.xml b/hacks/config/molecule.xml new file mode 100644 index 00000000..9195353e --- /dev/null +++ b/hacks/config/molecule.xml @@ -0,0 +1,57 @@ + + + + + + + + + + +
+ + + + + + + + + + + + +
+ +
+ + + +
+ + + + <_description> +Draws several different representations of molecules. Some common +molecules are built in, and it can also read PDB (Protein Data Bank) +files as input. + +http://en.wikipedia.org/wiki/Protein_Data_Bank_%28file_format%29 + +Written by Jamie Zawinski; 2001. + +
diff --git a/hacks/config/morph3d.xml b/hacks/config/morph3d.xml new file mode 100644 index 00000000..58b2b00d --- /dev/null +++ b/hacks/config/morph3d.xml @@ -0,0 +1,30 @@ + + + + + + + + + + + + + <_description> +Platonic solids that turn inside out and get spikey. + +http://en.wikipedia.org/wiki/Platonic_solid + +Written by Marcelo Vianna; 1997. + + diff --git a/hacks/config/mountain.xml b/hacks/config/mountain.xml new file mode 100644 index 00000000..252a28d5 --- /dev/null +++ b/hacks/config/mountain.xml @@ -0,0 +1,27 @@ + + + + + + + + + + + + + + + <_description> +Generates random 3D plots that look vaguely mountainous. + +Written by Pascal Pensa; 1997. + + diff --git a/hacks/config/munch.xml b/hacks/config/munch.xml new file mode 100644 index 00000000..df7f92ee --- /dev/null +++ b/hacks/config/munch.xml @@ -0,0 +1,58 @@ + + + + + + +
+ + + + + + + + + + + + + + +
+ + <_description> + DATAI 2 + ADDB 1,2 + ROTC 2,-22 + XOR 1,2 + JRST .-4 + +As reported by HAKMEM (MIT AI Memo 239, 1972), Jackson Wright wrote +the above PDP-1 code in 1962. That code still lives on here, some 46 +years later. + +In "mismunch" mode, it displays a creatively broken misimplementation +of the classic munching squares algorithm instead. + +http://en.wikipedia.org/wiki/HAKMEM +http://en.wikipedia.org/wiki/Munching_square + +Written by Jackson Wright, Tim Showalter, Jamie Zawinski and +Steven Hazel; 1997. + +
diff --git a/hacks/config/nerverot.xml b/hacks/config/nerverot.xml new file mode 100644 index 00000000..2b97b689 --- /dev/null +++ b/hacks/config/nerverot.xml @@ -0,0 +1,59 @@ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + <_description> +Draws different shapes composed of nervously vibrating squiggles, +as if seen through a camera operated by a monkey on crack. + +Written by Dan Bornstein; 2000. + +
diff --git a/hacks/config/noof.xml b/hacks/config/noof.xml new file mode 100644 index 00000000..04bed8c8 --- /dev/null +++ b/hacks/config/noof.xml @@ -0,0 +1,19 @@ + + + + + + + + + + + <_description> +Draws some flowery, rotatey patterns. + +Written by Bill Torzewski; 2004. + + diff --git a/hacks/config/noseguy.xml b/hacks/config/noseguy.xml new file mode 100644 index 00000000..4ef79577 --- /dev/null +++ b/hacks/config/noseguy.xml @@ -0,0 +1,15 @@ + + + + + + + + + + <_description> +A little man with a big nose wanders around your screen saying things. + +Written by Dan Heller and Jamie Zawinski; 1992. + + diff --git a/hacks/config/pacman.xml b/hacks/config/pacman.xml new file mode 100644 index 00000000..c43daf96 --- /dev/null +++ b/hacks/config/pacman.xml @@ -0,0 +1,24 @@ + + + + + + + + + + + + + <_description> +Simulates a game of Pac-Man on a randomly-created level. + +http://en.wikipedia.org/wiki/Pac-Man + +Written by Edwin de Jong; 2004. + + diff --git a/hacks/config/pedal.xml b/hacks/config/pedal.xml new file mode 100644 index 00000000..6f084720 --- /dev/null +++ b/hacks/config/pedal.xml @@ -0,0 +1,29 @@ + + + + + + + + + + + + + + + + + <_description> +A demonstration of the even-odd winding rule. + +http://en.wikipedia.org/wiki/Even-odd_rule +http://en.wikipedia.org/wiki/Nonzero-rule + +Written by Dale Moore; 1995. + + diff --git a/hacks/config/penetrate.xml b/hacks/config/penetrate.xml new file mode 100644 index 00000000..23b545d2 --- /dev/null +++ b/hacks/config/penetrate.xml @@ -0,0 +1,30 @@ + + + + + + + + + + + + + + + <_description> +Simulates (something like) the classic arcade game Missile Command. + +http://en.wikipedia.org/wiki/Missile_Command + +Written by Adam Miller; 1999. + + diff --git a/hacks/config/penrose.xml b/hacks/config/penrose.xml new file mode 100644 index 00000000..c298dd5e --- /dev/null +++ b/hacks/config/penrose.xml @@ -0,0 +1,52 @@ + + + + + + +
+ + + + + + + + + + + +
+ + + <_description> +Draws quasiperiodic tilings; think of the implications on modern +formica technology. + +In April 1997, Sir Roger Penrose, a British math professor who has +worked with Stephen Hawking on such topics as relativity, black +holes, and whether time has a beginning, filed a +copyright-infringement lawsuit against the Kimberly-Clark +Corporation, which Penrose said copied a pattern he created (a +pattern demonstrating that "a nonrepeating pattern could exist in +nature") for its Kleenex quilted toilet paper. Penrose said he +doesn't like litigation but, "When it comes to the population of +Great Britain being invited by a multinational to wipe their bottoms +on what appears to be the work of a Knight of the Realm, then a last +stand must be taken." + +As reported by News of the Weird #491, 4-Jul-1997. + +http://en.wikipedia.org/wiki/Penrose_tiling +http://en.wikipedia.org/wiki/Tessellation + +Written by Timo Korvola; 1997. + +
diff --git a/hacks/config/petri.xml b/hacks/config/petri.xml new file mode 100644 index 00000000..a51b6c34 --- /dev/null +++ b/hacks/config/petri.xml @@ -0,0 +1,83 @@ + + + + + + + +
+ + +
+
+ +
+ + + +
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + <_description> +This simulates colonies of mold growing in a petri dish. Growing +colored circles overlap and leave spiral interference in their wake. + +Written by Dan Bornstein; 1999. + +
diff --git a/hacks/config/phosphor.xml b/hacks/config/phosphor.xml new file mode 100644 index 00000000..3bc86190 --- /dev/null +++ b/hacks/config/phosphor.xml @@ -0,0 +1,39 @@ + + + + + + +
+ + + + + + + + + + + + +
+ + <_description> +Draws a simulation of an old terminal, with large pixels and +long-sustain phosphor. + +On MacOS and Linux, this program is also a fully-functional VT100 +emulator! Run it as an application instead of as a screen saver and +you can use it as a terminal. + +Written by Jamie Zawinski; 1999. + +
diff --git a/hacks/config/photopile.xml b/hacks/config/photopile.xml new file mode 100644 index 00000000..bd9c5bf5 --- /dev/null +++ b/hacks/config/photopile.xml @@ -0,0 +1,62 @@ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + <_description> +Loads several random images, and displays them as if lying in a random pile. +The pile is periodically reshuffled, with new images coming in and old ones +being thrown out. + +Written by Jens Kilian; 2008. + +
diff --git a/hacks/config/piecewise.xml b/hacks/config/piecewise.xml new file mode 100644 index 00000000..3cf47829 --- /dev/null +++ b/hacks/config/piecewise.xml @@ -0,0 +1,42 @@ + + + + + + +
+ + + + + + + + + + + + + +
+ + + + <_description> +This draws a bunch of moving circles which switch from visibility to +invisibility at intersection points. + +Written by Geoffrey Irving; 2003. + +
diff --git a/hacks/config/pinion.xml b/hacks/config/pinion.xml new file mode 100644 index 00000000..229a722a --- /dev/null +++ b/hacks/config/pinion.xml @@ -0,0 +1,45 @@ + + + + + + +
+ + + + + + + + + + + + + + + + +
+ + <_description> +Draws an interconnected set of gears moving across the screen. +See also the "Gears" and "MoebiusGears" screen savers. + +http://en.wikipedia.org/wiki/Involute_gear + +Written by Jamie Zawinski; 2004. + +
diff --git a/hacks/config/pipes.xml b/hacks/config/pipes.xml new file mode 100644 index 00000000..2fa82e23 --- /dev/null +++ b/hacks/config/pipes.xml @@ -0,0 +1,45 @@ + + + + + + + + + + + + + + +
+ + + +
+ +
+ + +
+ + <_description> +A growing plumbing system, with bolts and valves. + +Written by Marcelo Vianna; 1997. + +
diff --git a/hacks/config/polyhedra.xml b/hacks/config/polyhedra.xml new file mode 100644 index 00000000..c443a105 --- /dev/null +++ b/hacks/config/polyhedra.xml @@ -0,0 +1,195 @@ + + + + + + + + + + + + + + +
+ + + +
+
+ + +
+ + <_description> +Displays the 75 uniform polyhedra and their duals, plus 5 prisms +and antiprisms, and some information about each. + +http://en.wikipedia.org/wiki/Uniform_polyhedra +http://en.wikipedia.org/wiki/Stellation + +Written by Dr. Zvi Har'El and Jamie Zawinski; 2004. + +
diff --git a/hacks/config/polyominoes.xml b/hacks/config/polyominoes.xml new file mode 100644 index 00000000..6601a218 --- /dev/null +++ b/hacks/config/polyominoes.xml @@ -0,0 +1,32 @@ + + + + + + + + + + + + + + + + + <_description> +Repeatedly attempts to completely fill a rectangle with +irregularly-shaped puzzle pieces. + +http://en.wikipedia.org/wiki/Polyomino + +Written by Stephen Montgomery-Smith; 2002. + + diff --git a/hacks/config/polytopes.xml b/hacks/config/polytopes.xml new file mode 100644 index 00000000..204e1b96 --- /dev/null +++ b/hacks/config/polytopes.xml @@ -0,0 +1,109 @@ + + + + + + +
+ + + +
+ +
+ + + + + +
+ +
+ + + + + + + + + + + + + + + + + + +
+ + <_description> + +This shows one of the six regular 4D polytopes rotating in 4D. + +Inspired by H.S.M Coxeter's book "Regular Polytopes", 3rd Edition, +Dover Publications, Inc., 1973, and Thomas Banchoff's book "Beyond the +Third Dimension: Geometry, Computer Graphics, and Higher Dimensions", +Scientific American Library, 1990. + +http://en.wikipedia.org/wiki/Hypercube +http://en.wikipedia.org/wiki/Tesseract +http://en.wikipedia.org/wiki/Regular_polytope + +Written by Carsten Steger; 2003. + +
diff --git a/hacks/config/pong.xml b/hacks/config/pong.xml new file mode 100644 index 00000000..a8c33295 --- /dev/null +++ b/hacks/config/pong.xml @@ -0,0 +1,36 @@ + + + + + + + + + + + + + + + + + + <_description> +This simulates the 1971 Pong home video game, as well as +various artifacts from displaying it on a color TV set. + +In clock mode, the score keeps track of the current time. + +http://en.wikipedia.org/wiki/Pong + +Written by Jeremy English and Trevor Blackwell; 2003. + + diff --git a/hacks/config/popsquares.xml b/hacks/config/popsquares.xml new file mode 100644 index 00000000..514a1808 --- /dev/null +++ b/hacks/config/popsquares.xml @@ -0,0 +1,52 @@ + + + + + + + + + + + + + + +
+ + + +
+ + + + + + <_description> +This draws a pop-art-ish looking grid of pulsing colors. + +Written by Levi Burton; 2003. + +
diff --git a/hacks/config/providence.xml b/hacks/config/providence.xml new file mode 100644 index 00000000..5cc40628 --- /dev/null +++ b/hacks/config/providence.xml @@ -0,0 +1,25 @@ + + + + + + + + + + + + + + <_description> +"A pyramid unfinished. In the zenith an eye in a triangle, surrounded +by a glory, proper." + +http://en.wikipedia.org/wiki/Eye_of_Providence + +Written by Blair Tennessy; 2004. + + diff --git a/hacks/config/pulsar.xml b/hacks/config/pulsar.xml new file mode 100644 index 00000000..6c3acbe5 --- /dev/null +++ b/hacks/config/pulsar.xml @@ -0,0 +1,39 @@ + + + + + + + + + + +
+ + + + + + + + + + + + +
+ + + + <_description> +Draws some intersecting planes, making use of alpha blending, fog, +textures, and mipmaps. + +Written by David Konerding; 1999. + +
diff --git a/hacks/config/pyro.xml b/hacks/config/pyro.xml new file mode 100644 index 00000000..96983a43 --- /dev/null +++ b/hacks/config/pyro.xml @@ -0,0 +1,33 @@ + + + + + + + + + + + + + + + + + <_description> +Exploding fireworks. See also the "Fireworkx", "Eruption", and +"XFlame" screen savers. + +Written by Jamie Zawinski; 1992. + + diff --git a/hacks/config/qix.xml b/hacks/config/qix.xml new file mode 100644 index 00000000..4a3ad75c --- /dev/null +++ b/hacks/config/qix.xml @@ -0,0 +1,70 @@ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + +
+ + <_description> +Bounces a series of line segments around the screen, and uses +variations on this basic motion pattern to produce all sorts of +different presentations: line segments, filled polygons, and +overlapping translucent areas. + +http://en.wikipedia.org/wiki/Qix + +Written by Jamie Zawinski; 1992. + +
diff --git a/hacks/config/queens.xml b/hacks/config/queens.xml new file mode 100644 index 00000000..80061edf --- /dev/null +++ b/hacks/config/queens.xml @@ -0,0 +1,27 @@ + + + + + + + + +
+ + +
+ + <_description> +The N-Queens problem: how to place N queens on an NxN chessboard +such that no queen can attack a sister? + +See also the "Endgame" screen saver. + +http://en.wikipedia.org/wiki/Eight_queens_puzzle + +Written by Blair Tennessy; 2002. + +
diff --git a/hacks/config/rd-bomb.xml b/hacks/config/rd-bomb.xml new file mode 100644 index 00000000..d33a8278 --- /dev/null +++ b/hacks/config/rd-bomb.xml @@ -0,0 +1,62 @@ + + + + + + +
+ + + + + + + + + + + + +
+ +
+ + + + + + + + + + + + + + + +
+ + <_description> +Reaction-diffusion: draws a grid of growing square-like shapes that, +once they overtake each other, react in unpredictable ways. + +Written by Scott Draves; 1997. + +
diff --git a/hacks/config/rdbomb.xml b/hacks/config/rdbomb.xml new file mode 100644 index 00000000..d33a8278 --- /dev/null +++ b/hacks/config/rdbomb.xml @@ -0,0 +1,62 @@ + + + + + + +
+ + + + + + + + + + + + +
+ +
+ + + + + + + + + + + + + + + +
+ + <_description> +Reaction-diffusion: draws a grid of growing square-like shapes that, +once they overtake each other, react in unpredictable ways. + +Written by Scott Draves; 1997. + +
diff --git a/hacks/config/ripples.xml b/hacks/config/ripples.xml new file mode 100644 index 00000000..9d750f3d --- /dev/null +++ b/hacks/config/ripples.xml @@ -0,0 +1,51 @@ + + + + + + +
+ + + + + + + + + + + +
+ + + +
+ + + + + + +
+
+ + <_description> +Rippling interference patterns reminiscent of splashing water +distort a loaded image. + +Written by Tom Hammersley; 1999. + +
diff --git a/hacks/config/rocks.xml b/hacks/config/rocks.xml new file mode 100644 index 00000000..3a253ae6 --- /dev/null +++ b/hacks/config/rocks.xml @@ -0,0 +1,42 @@ + + + + + + + + + + + + +
+ + + +
+ + + + + + + + + + <_description> +This draws an animation of flight through an asteroid field, with +changes in rotation and direction. + +Written by Jamie Zawinski; 1992. + +
diff --git a/hacks/config/rorschach.xml b/hacks/config/rorschach.xml new file mode 100644 index 00000000..ad7051a8 --- /dev/null +++ b/hacks/config/rorschach.xml @@ -0,0 +1,34 @@ + + + + + + + + + + + + + + + + + + <_description> +This generates random inkblot patterns via a reflected random walk. +Any deep-seated neurotic tendencies which this program reveals +are your own problem. + +http://en.wikipedia.org/wiki/Rorschach_inkblot_test +http://en.wikipedia.org/wiki/Random_walk + +Written by Jamie Zawinski; 1992. + + diff --git a/hacks/config/rotor.xml b/hacks/config/rotor.xml new file mode 100644 index 00000000..b3c3e5d3 --- /dev/null +++ b/hacks/config/rotor.xml @@ -0,0 +1,36 @@ + + + + + + + + + + + + + + + + + + + <_description> +This screen saver was removed from the XScreenSaver distribution as of +version 5.08. + +Draws a line segment moving along a complex spiraling curve. + +Written by Tom Lawrence; 1997. + + diff --git a/hacks/config/rotzoomer.xml b/hacks/config/rotzoomer.xml new file mode 100644 index 00000000..c2d5d8c5 --- /dev/null +++ b/hacks/config/rotzoomer.xml @@ -0,0 +1,37 @@ + + + + + + + + + + + + + + + + + + + + + + + <_description> +Distorts an image by rotating and scaling random sections of it. + +Written by Claudio Matsuoka; 2001. + + diff --git a/hacks/config/rubik.xml b/hacks/config/rubik.xml new file mode 100644 index 00000000..029afded --- /dev/null +++ b/hacks/config/rubik.xml @@ -0,0 +1,36 @@ + + + + + + + + + + + + + + + + + + + <_description> +Draws a Rubik's Cube that rotates in three dimensions and repeatedly +shuffles and solves itself. See also the "GLSnake" and "Cube21" +screen savers. + +http://en.wikipedia.org/wiki/Rubik%27s_Cube + +Written by Marcelo Vianna; 1997. + + diff --git a/hacks/config/rubikblocks.xml b/hacks/config/rubikblocks.xml new file mode 100644 index 00000000..e728d9cf --- /dev/null +++ b/hacks/config/rubikblocks.xml @@ -0,0 +1,63 @@ + + + + + + +
+ + + + + + + + + + + + + + + + + + + +
+ + + +
+
+ + +
+ +
+
+ + <_description> +Animates the Rubik's Mirror Blocks puzzle. +See also the "Rubik", "Cube21", and "GLSnake" screen savers. + +http://en.wikipedia.org/wiki/Combination_puzzles#Irregular_cuboids + +Written by Vasek Potocek; 2009. + +
diff --git a/hacks/config/sballs.xml b/hacks/config/sballs.xml new file mode 100644 index 00000000..892851cf --- /dev/null +++ b/hacks/config/sballs.xml @@ -0,0 +1,33 @@ + + + + + + + + + + + + + + + <_description> +Draws an animation of textured balls spinning like crazy. + +Written by Eric Lassauge; 2002. + + diff --git a/hacks/config/shadebobs.xml b/hacks/config/shadebobs.xml new file mode 100644 index 00000000..9ed9ec11 --- /dev/null +++ b/hacks/config/shadebobs.xml @@ -0,0 +1,35 @@ + + + + + + + + + + + + + + + + + + + + <_description> +This draws smoothly-shaded oscillating oval patterns that look +something like vapor trails or neon tubes. + +Written by Shane Smit; 1999. + + diff --git a/hacks/config/sierpinski.xml b/hacks/config/sierpinski.xml new file mode 100644 index 00000000..2d243180 --- /dev/null +++ b/hacks/config/sierpinski.xml @@ -0,0 +1,34 @@ + + + + + + + + + + + + + + + + + <_description> +This draws the two-dimensional variant of the recursive Sierpinski +triangle fractal. See also the "Sierpinski3D" screen saver. + +http://en.wikipedia.org/wiki/Sierpinski_triangle + +Written by Desmond Daignault; 1997. + + diff --git a/hacks/config/sierpinski3d.xml b/hacks/config/sierpinski3d.xml new file mode 100644 index 00000000..cf2c50f0 --- /dev/null +++ b/hacks/config/sierpinski3d.xml @@ -0,0 +1,30 @@ + + + + + + + + + + + + + + + + <_description> +The recursive Sierpinski tetrahedron fractal. + +http://en.wikipedia.org/wiki/Sierpinski_triangle#Analogs_in_higher_dimension + +Written by Jamie Zawinski and Tim Robinson; 1999. + + diff --git a/hacks/config/skytentacles.xml b/hacks/config/skytentacles.xml new file mode 100644 index 00000000..4dd12e90 --- /dev/null +++ b/hacks/config/skytentacles.xml @@ -0,0 +1,67 @@ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + +
+ + + +
+
+ + +
+ +
+
+ + + <_description> +There is a tentacled abomination in the sky. From above you it devours. + +Written by Jamie Zawinski; 2008. + +
diff --git a/hacks/config/slidescreen.xml b/hacks/config/slidescreen.xml new file mode 100644 index 00000000..efa1091b --- /dev/null +++ b/hacks/config/slidescreen.xml @@ -0,0 +1,50 @@ + + + + + + +
+ + + + + + + + + + + + + + + + + + +
+ + + + <_description> +A variant on a "fifteen puzzle", operating on the screen or an image. +It divides the image into a grid and randomly shuffles the squares. + +http://en.wikipedia.org/wiki/Fifteen_puzzle + +Written by Jamie Zawinski; 1994. + +
diff --git a/hacks/config/slip.xml b/hacks/config/slip.xml new file mode 100644 index 00000000..4eb704f2 --- /dev/null +++ b/hacks/config/slip.xml @@ -0,0 +1,43 @@ + + + + + + +
+ + + + + + + + + + + +
+ + + + + + <_description> +This throws some random bits on the screen, then sucks them +through a jet engine and spews them out the other side. To avoid +turning the image completely to mush, every now and then it will it +interject some splashes of color into the scene, or go into a spin +cycle, or stretch the image like taffy. + +Written by Scott Draves and Jamie Zawinski; 1997. + +
diff --git a/hacks/config/sonar.xml b/hacks/config/sonar.xml new file mode 100644 index 00000000..21fcc28f --- /dev/null +++ b/hacks/config/sonar.xml @@ -0,0 +1,84 @@ + + + + + + +
+ + + + + + + + + + + + + +
+ + +
+ + +
+ +
+ + +
+ +
+ + + + +
+ + <_description> +This draws a sonar screen that pings (get it?) the hosts on +your local network, and plots their distance (response time) from you. +The three rings represent ping times of approximately 2.5, 70 and 2,000 +milliseconds respectively. + +Alternately, it can run a simulation that doesn't involve hosts. + +(If pinging doesn't work on Linux, you may need to make the executable +be setuid.) + +http://en.wikipedia.org/wiki/Ping#History + +Written by Jamie Zawinski and Stephen Martin; 1998. + +
diff --git a/hacks/config/speedmine.xml b/hacks/config/speedmine.xml new file mode 100644 index 00000000..5da9e14e --- /dev/null +++ b/hacks/config/speedmine.xml @@ -0,0 +1,58 @@ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + <_description> +Simulates speeding down a rocky mineshaft, or a funky dancing worm. + +Written by Conrad Parker; 2001. + +
diff --git a/hacks/config/sphere.xml b/hacks/config/sphere.xml new file mode 100644 index 00000000..a48ca2fb --- /dev/null +++ b/hacks/config/sphere.xml @@ -0,0 +1,26 @@ + + + + + + + + + + + + + <_description> +This screen saver was removed from the XScreenSaver distribution as of +version 5.08. + +Draws shaded spheres in multiple colors. + +Written by Tom Duff and Jamie Zawinski; 1982, 1997. + + diff --git a/hacks/config/spheremonics.xml b/hacks/config/spheremonics.xml new file mode 100644 index 00000000..10b67c9f --- /dev/null +++ b/hacks/config/spheremonics.xml @@ -0,0 +1,56 @@ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + +
+ + <_description> +These closed objects are commonly called spherical harmonics, +although they are only remotely related to the mathematical +definition found in the solution to certain wave functions, most +notably the eigenfunctions of angular momentum operators. + +http://en.wikipedia.org/wiki/Spherical_harmonics#Visualization_of_the_spherical_harmonics + +Written by Paul Bourke and Jamie Zawinski; 2002. + +
diff --git a/hacks/config/spiral.xml b/hacks/config/spiral.xml new file mode 100644 index 00000000..f43a6ead --- /dev/null +++ b/hacks/config/spiral.xml @@ -0,0 +1,34 @@ + + + + + + + + + + + + + + + + + <_description> +This screen saver was removed from the XScreenSaver distribution as of +version 5.08. + +Moving circular moire patterns. + +Written by Peter Schmitzberger; 1997. + + diff --git a/hacks/config/spotlight.xml b/hacks/config/spotlight.xml new file mode 100644 index 00000000..8c283a39 --- /dev/null +++ b/hacks/config/spotlight.xml @@ -0,0 +1,30 @@ + + + + + + + + + + + + + + + + + <_description> +A spotlight scanning across a black screen, illuminating a loaded +image when it passes. + +Written by Rick Schultz and Jamie Zawinski; 1999. + + diff --git a/hacks/config/sproingies.xml b/hacks/config/sproingies.xml new file mode 100644 index 00000000..c7b5b51d --- /dev/null +++ b/hacks/config/sproingies.xml @@ -0,0 +1,32 @@ + + + + + + + + + + +
+ + + +
+ + <_description> +Slinky-like creatures walk down an infinite staircase and +occasionally explode! + +http://en.wikipedia.org/wiki/Slinky +http://en.wikipedia.org/wiki/Q%2Abert +http://en.wikipedia.org/wiki/Marble_Madness + +Written by Ed Mackey; 1997. + +
diff --git a/hacks/config/squiral.xml b/hacks/config/squiral.xml new file mode 100644 index 00000000..b302dada --- /dev/null +++ b/hacks/config/squiral.xml @@ -0,0 +1,47 @@ + + + + + + +
+ + + + + + + + + + + + + + + +
+ + + + + + <_description> +Draws a set of interacting, square-spiral-producing automata. The +spirals grow outward until they hit something, then they go around it. + +Written by Jeff Epler; 1999. + +
diff --git a/hacks/config/stairs.xml b/hacks/config/stairs.xml new file mode 100644 index 00000000..15f0150d --- /dev/null +++ b/hacks/config/stairs.xml @@ -0,0 +1,21 @@ + + + + + + + + + + + <_description> +Escher's infinite staircase. + +http://en.wikipedia.org/wiki/Maurits_Cornelis_Escher + +Written by Marcelo Vianna; 1998. + + diff --git a/hacks/config/starfish.xml b/hacks/config/starfish.xml new file mode 100644 index 00000000..522f859e --- /dev/null +++ b/hacks/config/starfish.xml @@ -0,0 +1,39 @@ + + + + + + + + + + + + + + + + + + + <_description> +Undulating, throbbing, star-like patterns pulsate, rotate, and turn +inside out. Another display mode uses these shapes to lay down a +field of colors, which are then cycled. The motion is very organic. + +Written by Jamie Zawinski; 1997. + + diff --git a/hacks/config/starwars.xml b/hacks/config/starwars.xml new file mode 100644 index 00000000..6a15c00f --- /dev/null +++ b/hacks/config/starwars.xml @@ -0,0 +1,59 @@ + + + + + + +
+ + + + + + + + + + + + + + +
+ + +
+ + + + + + +
+
+ + <_description> +Draws a stream of text slowly scrolling into the distance at an +angle, over a star field, like at the beginning of the movie of the +same name. + +http://en.wikipedia.org/wiki/Star_Wars_opening_crawl + +Written by Jamie Zawinski and Claudio Matauoka; 2001. + +
diff --git a/hacks/config/stonerview.xml b/hacks/config/stonerview.xml new file mode 100644 index 00000000..89fe9067 --- /dev/null +++ b/hacks/config/stonerview.xml @@ -0,0 +1,23 @@ + + + + + + + + + + + + + <_description> +Chains of colorful squares dance around each other in complex spiral +patterns. Inspired by David Tristram's `electropaint' screen saver, +originally written for SGI computers in the late 1980s or early 1990s. + +Written by Andrew Plotkin; 2001. + + diff --git a/hacks/config/strange.xml b/hacks/config/strange.xml new file mode 100644 index 00000000..43e23865 --- /dev/null +++ b/hacks/config/strange.xml @@ -0,0 +1,30 @@ + + + + + + + + + + + + + + + <_description> +This draws iterations to strange attractors: it's a colorful, +unpredictably-animating swarm of dots that swoops and twists around. + +http://en.wikipedia.org/wiki/Attractor#Strange_attractor + +Written by Massimino Pascal; 1997. + + diff --git a/hacks/config/substrate.xml b/hacks/config/substrate.xml new file mode 100644 index 00000000..7c9ac57a --- /dev/null +++ b/hacks/config/substrate.xml @@ -0,0 +1,41 @@ + + + + + + +
+ + + + + + + + + + + + + + + + +
+ + <_description> +Crystalline lines grow on a computational substrate. A simple +perpendicular growth rule creates intricate city-like structures. + +Written by J. Tarbell and Mike Kershaw; 2004. + +
diff --git a/hacks/config/superquadrics.xml b/hacks/config/superquadrics.xml new file mode 100644 index 00000000..265e0005 --- /dev/null +++ b/hacks/config/superquadrics.xml @@ -0,0 +1,32 @@ + + + + + + + + + + + + + + + + + + <_description> +Morphing 3D shapes. + +Written by Ed Mackey; 1987, 1997. + + diff --git a/hacks/config/surfaces.xml b/hacks/config/surfaces.xml new file mode 100644 index 00000000..d7922242 --- /dev/null +++ b/hacks/config/surfaces.xml @@ -0,0 +1,67 @@ + + + + + + + + + + +
+ + + +
+ +
+ + + +
+ + <_description> +This draws a visualization of several interesting parametric surfaces. + +http://mathworld.wolfram.com/DinisSurface.html +http://en.wikipedia.org/wiki/Enneper_surface +http://mathworld.wolfram.com/EnnepersMinimalSurface.html +http://mathworld.wolfram.com/KuenSurface.html +http://en.wikipedia.org/wiki/Moebius_strip +http://mathworld.wolfram.com/Seashell.html +http://mathworld.wolfram.com/SwallowtailCatastrophe.html +http://mathworld.wolfram.com/BohemianDome.html +http://en.wikipedia.org/wiki/Whitney_umbrella +http://mathworld.wolfram.com/PlueckersConoid.html +http://mathworld.wolfram.com/HennebergsMinimalSurface.html +http://mathworld.wolfram.com/CatalansSurface.html +http://mathworld.wolfram.com/CorkscrewSurface.html + +Written by Andrey Mirtchovski and Carsten Steger; 2003. + +
diff --git a/hacks/config/swirl.xml b/hacks/config/swirl.xml new file mode 100644 index 00000000..ec69fb52 --- /dev/null +++ b/hacks/config/swirl.xml @@ -0,0 +1,29 @@ + + + + + + + + + + + + + + + + + <_description> +Flowing, swirly patterns. + +Written by M. Dobie and R. Taylor; 1997. + + diff --git a/hacks/config/t3d.xml b/hacks/config/t3d.xml new file mode 100644 index 00000000..abf85343 --- /dev/null +++ b/hacks/config/t3d.xml @@ -0,0 +1,49 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + <_description> +This screen saver was removed from the XScreenSaver distribution as of +version 5.08. + +Draws a working analog clock composed of floating, throbbing bubbles. + +Written by Bernd Paysan; 1999. + + diff --git a/hacks/config/tangram.xml b/hacks/config/tangram.xml new file mode 100644 index 00000000..18b161fa --- /dev/null +++ b/hacks/config/tangram.xml @@ -0,0 +1,41 @@ + + + + + + + + + + + + + + + + +
+ + + + +
+ + <_description> +Solves tangram puzzles. + +http://en.wikipedia.org/wiki/Tangram + +Written by Jeremy English; 2005. + +
diff --git a/hacks/config/thornbird.xml b/hacks/config/thornbird.xml new file mode 100644 index 00000000..e3922874 --- /dev/null +++ b/hacks/config/thornbird.xml @@ -0,0 +1,33 @@ + + + + + + + + + + + + + + + + + <_description> +Displays a view of the "Bird in a Thornbush" fractal. + +Written by Tim Auckland; 2002. + + diff --git a/hacks/config/timetunnel.xml b/hacks/config/timetunnel.xml new file mode 100644 index 00000000..7ec87939 --- /dev/null +++ b/hacks/config/timetunnel.xml @@ -0,0 +1,39 @@ + + + + + + + + + + +
+ + + + + +
+ + <_description> +Draws an animation similar to the opening and closing effects on the +Dr. Who TV show. + +Written by Sean P. Brennan; 2005. + +
diff --git a/hacks/config/topblock.xml b/hacks/config/topblock.xml new file mode 100644 index 00000000..06d8f924 --- /dev/null +++ b/hacks/config/topblock.xml @@ -0,0 +1,60 @@ + + + + + + +
+ + + + + + + + + + + + + + + + + +
+ +
+ + + + + +
+
+ + + +
+ + <_description> +Creates a 3D world with dropping blocks that build up and up. +Written by rednuht; 2006. + +
diff --git a/hacks/config/triangle.xml b/hacks/config/triangle.xml new file mode 100644 index 00000000..8e6ac967 --- /dev/null +++ b/hacks/config/triangle.xml @@ -0,0 +1,24 @@ + + + + + + + + + + + + + <_description> +Generates random mountain ranges using iterative subdivision of +triangles. + +Written by Tobias Gloth; 1997. + + diff --git a/hacks/config/tronbit.xml b/hacks/config/tronbit.xml new file mode 100644 index 00000000..fc60f840 --- /dev/null +++ b/hacks/config/tronbit.xml @@ -0,0 +1,37 @@ + + + + + + + + + + +
+ + + + +
+ + <_description> +Draws an animation of the character "Bit" from the film, "Tron". + +The "yes" state is a tetrahedron; the "no" state is the second +stellation of an icosahedron; and the idle state oscillates between +a small triambic icosahedron and the compound of an icosahedron and +a dodecahedron. + +http://en.wikipedia.org/wiki/List_of_Tron_characters#Bit +http://en.wikipedia.org/wiki/Uniform_polyhedra +http://en.wikipedia.org/wiki/Stellation + +Written by Jamie Zawinski; 2011. + +
diff --git a/hacks/config/truchet.xml b/hacks/config/truchet.xml new file mode 100644 index 00000000..af2e8814 --- /dev/null +++ b/hacks/config/truchet.xml @@ -0,0 +1,37 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + <_description> +This draws line- and arc-based truchet patterns that tile the screen. + +http://en.wikipedia.org/wiki/Tessellation + +Written by Adrian Likins; 1998. + + diff --git a/hacks/config/twang.xml b/hacks/config/twang.xml new file mode 100644 index 00000000..9beced7c --- /dev/null +++ b/hacks/config/twang.xml @@ -0,0 +1,57 @@ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + <_description> +Divides the screen into a grid, and plucks them. + +Written by Dan Bornstein; 2002. + +
diff --git a/hacks/config/vermiculate.xml b/hacks/config/vermiculate.xml new file mode 100644 index 00000000..a3c692f0 --- /dev/null +++ b/hacks/config/vermiculate.xml @@ -0,0 +1,18 @@ + + + + + + + + + + + <_description> +Draws squiggly worm-like paths. + +Written by Tyler Pierce; 2001. + + diff --git a/hacks/config/vidwhacker.xml b/hacks/config/vidwhacker.xml new file mode 100644 index 00000000..da36b834 --- /dev/null +++ b/hacks/config/vidwhacker.xml @@ -0,0 +1,26 @@ + + + + + + + + + + + + + <_description> +This is a shell script that grabs a frame of video from the system's +video input, and then uses some PBM filters (chosen at random) to +manipulate and recombine the video frame in various ways (edge +detection, subtracting the image from a rotated version of itself, +etc.) Then it displays that image for a few seconds, and does it +again. This works really well if you just feed broadcast television +into it. + +Written by Jamie Zawinski; 1998. + + diff --git a/hacks/config/vines.xml b/hacks/config/vines.xml new file mode 100644 index 00000000..6e1605d2 --- /dev/null +++ b/hacks/config/vines.xml @@ -0,0 +1,26 @@ + + + + + + + + + + + + + <_description> +This screen saver was removed from the XScreenSaver distribution as of +version 5.08. + +Generates a continuous sequence of small, curvy geometric patterns. + +Written by Tracy Camp and David Hansen; 1997. + + diff --git a/hacks/config/voronoi.xml b/hacks/config/voronoi.xml new file mode 100644 index 00000000..2cd4fee1 --- /dev/null +++ b/hacks/config/voronoi.xml @@ -0,0 +1,59 @@ + + + + + + +
+ + + + + + + + + + + + + + + + + + + +
+ + <_description> +Draws a randomly-colored Voronoi tessellation, and periodically zooms +in and adds new points. The existing points also wander around. + +There are a set of control points on the plane, each at the center of +a colored cell. Every pixel within that cell is closer to that cell's +control point than to any other control point. That is what +determines the cell's shapes. + +http://en.wikipedia.org/wiki/Voronoi_diagram +http://en.wikipedia.org/wiki/Tessellation + +Written by Jamie Zawinski; 2007. + +
diff --git a/hacks/config/wander.xml b/hacks/config/wander.xml new file mode 100644 index 00000000..80a770dd --- /dev/null +++ b/hacks/config/wander.xml @@ -0,0 +1,45 @@ + + + + + + + + + + + + + + +
+ + + +
+ + + + + + <_description> +Draws a colorful random-walk, in various forms. + +http://en.wikipedia.org/wiki/Random_walk + +Written by Rick Campbell; 1999. + +
diff --git a/hacks/config/webcollage.xml b/hacks/config/webcollage.xml new file mode 100644 index 00000000..c6f84b5e --- /dev/null +++ b/hacks/config/webcollage.xml @@ -0,0 +1,52 @@ + + + + + + +
+ + + + + + + + + + + +
+ + + + <_description> +This is what the Internet looks like. + +This creates collages out of random images from the World Wide Web. +It finds the images by feeding random words into various search +engines, and pulling images (or sections of images) out of the pages +returned. + +WARNING: THE INTERNET SOMETIMES CONTAINS PORNOGRAPHY. + +The Internet being what it is, absolutely anything might show up in the +collage including -- quite possibly -- pornography, or even nudity. +Please act accordingly. + +See also http://www.jwz.org/webcollage/ + +Written by Jamie Zawinski; 1999. + +
diff --git a/hacks/config/whirlwindwarp.xml b/hacks/config/whirlwindwarp.xml new file mode 100644 index 00000000..6c5aec6b --- /dev/null +++ b/hacks/config/whirlwindwarp.xml @@ -0,0 +1,24 @@ + + + + + + + + + + + + + <_description> +Floating stars are acted upon by a mixture of simple 2D +force fields. The strength of each force field changes +continuously, and it is also switched on and off at random. + +Written by Paul 'Joey' Clark; 2001. + + diff --git a/hacks/config/whirlygig.xml b/hacks/config/whirlygig.xml new file mode 100644 index 00000000..3ca0dce2 --- /dev/null +++ b/hacks/config/whirlygig.xml @@ -0,0 +1,86 @@ + + + + + + +
+ + + +
+ +
+ + + + + + + + + +
+ + + + +
+ + + +
+ + + + + + + + +
+ + + + +
+ + <_description> +This screen saver was removed from the XScreenSaver distribution as of +version 5.08. + +Draws zooming chains of sinusoidal spots. + +Written by Ashton Trey Belew; 2001. + +
diff --git a/hacks/config/worm.xml b/hacks/config/worm.xml new file mode 100644 index 00000000..6cf221b6 --- /dev/null +++ b/hacks/config/worm.xml @@ -0,0 +1,35 @@ + + + + + + + + + + + + + + + + + + + + <_description> +This screen saver was removed from the XScreenSaver distribution as of +version 5.08. + +Draws multicolored worms that crawl around the screen. + +Written by Brad Taylor, Dave Lemke, Boris Putanec, and Henrik Theiling; 1991. + + diff --git a/hacks/config/wormhole.xml b/hacks/config/wormhole.xml new file mode 100644 index 00000000..c137a0fd --- /dev/null +++ b/hacks/config/wormhole.xml @@ -0,0 +1,27 @@ + + + + + + + + + + + + + + + <_description> +Flying through a colored wormhole in space. + +Written by Jon Rafkind; 2004. + + diff --git a/hacks/config/xanalogtv.xml b/hacks/config/xanalogtv.xml new file mode 100644 index 00000000..42188010 --- /dev/null +++ b/hacks/config/xanalogtv.xml @@ -0,0 +1,39 @@ + + + + + + + + + + +
+ + + + + + + + +
+ + <_description> + +a detailed simulation of an old TV set, including artifacts like snow, +bloom, distortion, ghosting, and hash noise. It also simulates the TV +warming up. It will cycle through 12 channels, some with images you +give it, and some with color bars or nothing but static. + +Written by Trevor Blackwell; 2003. + +
diff --git a/hacks/config/xflame.xml b/hacks/config/xflame.xml new file mode 100644 index 00000000..e9a4686f --- /dev/null +++ b/hacks/config/xflame.xml @@ -0,0 +1,31 @@ + + + + + + + + + + + + + + + + + + + + + + <_description> +Draws a simulation of pulsing fire. It can also take an arbitrary +image and set it on fire too. + +Written by Carsten Haitzler and many others; 1999. + + diff --git a/hacks/config/xjack.xml b/hacks/config/xjack.xml new file mode 100644 index 00000000..8d6f9c07 --- /dev/null +++ b/hacks/config/xjack.xml @@ -0,0 +1,21 @@ + + + + + + + + + + + + + <_description> +This behaves schizophrenically and makes a lot of typos. + +Written by Jamie Zawinski; 1997. + + diff --git a/hacks/config/xlyap.xml b/hacks/config/xlyap.xml new file mode 100644 index 00000000..1f473520 --- /dev/null +++ b/hacks/config/xlyap.xml @@ -0,0 +1,48 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + <_description> +The Lyapunov exponent makes pretty fractal pictures. + +http://en.wikipedia.org/wiki/Lyapunov_exponent + +Written by Ron Record; 1997. + + diff --git a/hacks/config/xmatrix.xml b/hacks/config/xmatrix.xml new file mode 100644 index 00000000..e011f4a0 --- /dev/null +++ b/hacks/config/xmatrix.xml @@ -0,0 +1,63 @@ + + + + + + +
+ + + + + +
+ +
+ + + +
+ +
+ + + + + + + + + + +
+ + <_description> +Draws the "digital rain" effect, as seen on the computer monitors in +"The Matrix". + +See also "GLMatrix" for a 3D rendering of the similar effect that +appeared in the movie's title sequence. + +http://en.wikipedia.org/wiki/Matrix_digital_rain + +Written by Jamie Zawinski; 1999. + +
diff --git a/hacks/config/xrayswarm.xml b/hacks/config/xrayswarm.xml new file mode 100644 index 00000000..49fe4559 --- /dev/null +++ b/hacks/config/xrayswarm.xml @@ -0,0 +1,19 @@ + + + + + + + + + + + <_description> +Worm-like swarms of particles with vapor trails. + +Written by Chris Leger; 2000. + + diff --git a/hacks/config/xspirograph.xml b/hacks/config/xspirograph.xml new file mode 100644 index 00000000..ab297adc --- /dev/null +++ b/hacks/config/xspirograph.xml @@ -0,0 +1,28 @@ + + + + + + + + + + + + + + + <_description> +Simulates that pen-in-nested-plastic-gears toy from your childhood. + +http://en.wikipedia.org/wiki/Spirograph + +Written by Rohit Singh; 2000. + + diff --git a/hacks/config/xss.dtd b/hacks/config/xss.dtd new file mode 100644 index 00000000..212d53db --- /dev/null +++ b/hacks/config/xss.dtd @@ -0,0 +1,109 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/hacks/config/xss.xsd b/hacks/config/xss.xsd new file mode 100644 index 00000000..fac1fe33 --- /dev/null +++ b/hacks/config/xss.xsd @@ -0,0 +1,375 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/hacks/config/zoom.xml b/hacks/config/zoom.xml new file mode 100644 index 00000000..4375f5db --- /dev/null +++ b/hacks/config/zoom.xml @@ -0,0 +1,50 @@ + + + + + + + + + + +
+ + + + + + + + + + + + + + + + +
+ + + + <_description> +Fatbits! Zooms in on a part of the screen and then moves around. +With the "Lenses" option, the result is like looking through many +overlapping lenses rather than just a simple zoom. + +Written by James Macnicol; 2001. + +
diff --git a/hacks/coral.c b/hacks/coral.c new file mode 100644 index 00000000..62df14cd --- /dev/null +++ b/hacks/coral.c @@ -0,0 +1,303 @@ +/* coral, by "Frederick G.M. Roeber" , 15-jul-97. + * + * 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. + */ + +#include "screenhack.h" +#include "colors.h" +#include "erase.h" + +#define NCOLORSMAX 200 + +struct state { + Display *dpy; + Window window; + + GC draw_gc, erase_gc; + unsigned int default_fg_pixel; + XColor colors[NCOLORSMAX]; + int ncolors; + int colorindex; + int colorsloth; + + XPoint *walkers; + int nwalkers; + int width, widthb; + int height; + int delay, delay2; + int max_points; + XPoint *pointbuf; + + unsigned int *board; + + int done, reset; + int npoints; + eraser_state *eraser; +}; + + +#define getdot(x,y) (st->board[(y*st->widthb)+(x>>5)] & (1<<(x & 31))) +#define setdot(x,y) (st->board[(y*st->widthb)+(x>>5)] |= (1<<(x & 31))) + + +static void +init_coral(struct state *st) +{ + XGCValues gcv; + Colormap cmap; + XWindowAttributes xgwa; + Bool writeable = False; + int seeds; + int density; + int i; + + XClearWindow(st->dpy, st->window); + XGetWindowAttributes(st->dpy, st->window, &xgwa); + st->width = xgwa.width; + st->widthb = ((xgwa.width + 31) >> 5); + st->height = xgwa.height; + if (st->board) free(st->board); + st->board = (unsigned int *)calloc(st->widthb * xgwa.height, sizeof(unsigned int)); + if(!st->board) exit(1); + cmap = xgwa.colormap; + if( st->ncolors ) { + free_colors(st->dpy, cmap, st->colors, st->ncolors); + st->ncolors = 0; + } + gcv.foreground = st->default_fg_pixel = get_pixel_resource(st->dpy, cmap, "foreground", "Foreground"); + st->draw_gc = XCreateGC(st->dpy, st->window, GCForeground, &gcv); + gcv.foreground = get_pixel_resource (st->dpy, cmap, "background", "Background"); + st->erase_gc = XCreateGC (st->dpy, st->window, GCForeground, &gcv); + st->ncolors = NCOLORSMAX; + make_uniform_colormap(st->dpy, xgwa.visual, cmap, st->colors, &st->ncolors, True, &writeable, False); + if (st->ncolors <= 0) { + st->ncolors = 2; + st->colors[0].red = st->colors[0].green = st->colors[0].blue = 0; + st->colors[1].red = st->colors[1].green = st->colors[1].blue = 0xFFFF; + XAllocColor(st->dpy, cmap, &st->colors[0]); + XAllocColor(st->dpy, cmap, &st->colors[1]); + } + st->colorindex = random()%st->ncolors; + + density = get_integer_resource(st->dpy, "density", "Integer"); + if( density < 1 ) density = 1; + if( density > 100 ) density = 90; /* more like mold than coral */ + st->nwalkers = (st->width*st->height*density)/100; + if (st->walkers) free(st->walkers); + st->walkers = (XPoint *)calloc(st->nwalkers, sizeof(XPoint)); + if( (XPoint *)0 == st->walkers ) exit(1); + + seeds = get_integer_resource(st->dpy, "seeds", "Integer"); + if( seeds < 1 ) seeds = 1; + if( seeds > 1000 ) seeds = 1000; + + st->colorsloth = st->nwalkers*2/st->ncolors; + XSetForeground(st->dpy, st->draw_gc, st->colors[st->colorindex].pixel); + + if ((st->width <= 2) || (st->height <= 2)) return; + + for( i = 0; i < seeds; i++ ) { + int x, y; + int max_repeat = 10; + do { + x = 1 + random() % (st->width - 2); + y = 1 + random() % (st->height - 2); + } while( getdot(x, y) && max_repeat--); + + setdot((x-1), (y-1)); setdot(x, (y-1)); setdot((x+1), (y-1)); + setdot((x-1), y ); setdot(x, y ); setdot((x+1), y ); + setdot((x-1), (y+1)); setdot(x, (y+1)); setdot((x+1), (y+1)); + XDrawPoint(st->dpy, st->window, st->draw_gc, x, y); + } + + for( i = 0; i < st->nwalkers; i++ ) { + st->walkers[i].x = (random() % (st->width-2)) + 1; + st->walkers[i].y = (random() % (st->height-2)) + 1; + } +} + + +/* returns 2 bits of randomness (conserving calls to random()). + This speeds things up a little, but not a lot (5-10% or so.) + */ +static int +rand_2(void) +{ + static int i = 0; + static int r = 0; + if (i != 0) { + i--; + } else { + i = 15; + r = random(); + } + + { + register int j = (r & 3); + r = r >> 2; + return j; + } +} + + +static int +coral(struct state *st) +{ + int i = 0; + + for( i = 0; i < st->nwalkers; i++ ) { + int x = st->walkers[i].x; + int y = st->walkers[i].y; + + if( getdot(x, y) ) { + + Bool flush = False; + Bool color = False; + + /* XDrawPoint(dpy, window, draw_gc, x, y); */ + st->pointbuf[st->npoints].x = x; + st->pointbuf[st->npoints].y = y; + st->npoints++; + + /* Mark the surrounding area as "sticky" */ + setdot((x-1), (y-1)); setdot(x, (y-1)); setdot((x+1), (y-1)); + setdot((x-1), y ); setdot((x+1), y ); + setdot((x-1), (y+1)); setdot(x, (y+1)); setdot((x+1), (y+1)); + st->nwalkers--; + st->walkers[i].x = st->walkers[st->nwalkers].x; + st->walkers[i].y = st->walkers[st->nwalkers].y; + if( 0 == + ((st->colorsloth ? st->nwalkers%st->colorsloth : 0)) ) { + color = True; + } + + if (flush || color || 0 == st->nwalkers || st->npoints >= st->max_points) { + XDrawPoints(st->dpy, st->window, st->draw_gc, st->pointbuf, st->npoints, + CoordModeOrigin); + st->npoints = 0; + } + + if (color) { + st->colorindex++; + if( st->colorindex == st->ncolors ) + st->colorindex = 0; + XSetForeground(st->dpy, st->draw_gc, st->colors[st->colorindex].pixel); + } + } else { + /* move it a notch */ + do { + switch(rand_2()) { + case 0: + if( 1 == x ) continue; + st->walkers[i].x--; + break; + case 1: + if( st->width-2 == x ) continue; + st->walkers[i].x++; + break; + case 2: + if( 1 == y ) continue; + st->walkers[i].y--; + break; + default: /* case 3: */ + if( st->height-2 == y ) continue; + st->walkers[i].y++; + break; + /* default: + abort(); */ + } + } while(0); + } + } + + return (0 == st->nwalkers); +} + +static void * +coral_init (Display *dpy, Window window) +{ + struct state *st = (struct state *) calloc (1, sizeof(*st)); + st->dpy = dpy; + st->window = window; + st->max_points = 200; + st->pointbuf = (XPoint *) calloc(sizeof(XPoint), st->max_points+2); + if (!st->pointbuf) exit(-1); + + st->delay = get_integer_resource (st->dpy, "delay", "Integer"); + st->delay2 = get_integer_resource (st->dpy, "delay2", "Integer"); + st->reset = 1; + return st; +} + + +static unsigned long +coral_draw (Display *dpy, Window window, void *closure) +{ + struct state *st = (struct state *) closure; + + if (st->eraser || st->done) + { + st->done = 0; + st->eraser = erase_window (st->dpy, st->window, st->eraser); + return st->delay2; + } + + if (st->reset) + init_coral(st); + st->reset = st->done = coral(st); + + return (st->reset + ? (st->delay * 1000000) + : st->delay2); +} + +static void +coral_reshape (Display *dpy, Window window, void *closure, + unsigned int w, unsigned int h) +{ + struct state *st = (struct state *) closure; + init_coral(st); +} + +static Bool +coral_event (Display *dpy, Window window, void *closure, XEvent *event) +{ + return False; +} + +static void +coral_free (Display *dpy, Window window, void *closure) +{ + struct state *st = (struct state *) closure; + free (st->pointbuf); + if (st->walkers) free (st->walkers); + if (st->board) free (st->board); + free (st); +} + +static const char *coral_defaults[] = { + ".background: black", + ".foreground: white", + "*fpsSolid: true", + "*density: 25", + "*seeds: 20", /* too many for 640x480, too few for 1280x1024 */ + "*delay: 5", + "*delay2: 20000", + 0 +}; + +static XrmOptionDescRec coral_options[] = { + { "-density", ".density", XrmoptionSepArg, 0 }, + { "-seeds", ".seeds", XrmoptionSepArg, 0 }, + { "-delay", ".delay", XrmoptionSepArg, 0 }, + { "-delay2", ".delay2", XrmoptionSepArg, 0 }, + { 0, 0, 0, 0 } +}; + +XSCREENSAVER_MODULE ("Coral", coral) diff --git a/hacks/coral.man b/hacks/coral.man new file mode 100644 index 00000000..aaa497ee --- /dev/null +++ b/hacks/coral.man @@ -0,0 +1,64 @@ +.TH XScreenSaver 1 "" "X Version 11" +.SH NAME +coral - simulates coral growth, albeit somewhat slowly. +.SH SYNOPSIS +.B coral +[\-display \fIhost:display.screen\fP] +[\-visual \fIvisual\fP] +[\-window] +[\-root] +[\-delay2 \fInumber\fP] +[\-delay \fInumber\fP] +[\-density \fInumber\fP] +[\-seeds \fInumber\fP] +[\-fps] +.SH DESCRIPTION +Simulates coral growth, albeit somewhat slowly. +.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 \-delay2 \fInumber\fP +Per-frame delay, in microseconds. Default: 1000 (0.001 seconds.). +.TP 8 +.B \-delay \fInumber\fP +Duration. 1 - 60. Default: 5. +.TP 8 +.B \-density \fInumber\fP +Density. 1 - 90. Default: 25. +.TP 8 +.B \-seeds \fInumber\fP +Seeds. 1 - 100. Default: 20. +.TP 8 +.B \-fps +Display the current frame rate and CPU load. +.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 2002 by Frederick Roeber. 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 +Frederick Roeber. diff --git a/hacks/critical.c b/hacks/critical.c new file mode 100644 index 00000000..6f9fa760 --- /dev/null +++ b/hacks/critical.c @@ -0,0 +1,452 @@ +/* critical -- Self-organizing-criticality display hack for XScreenSaver + * Copyright (C) 1998, 1999, 2000 Martin Pool + * + * 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. + * + * See `critical.man' for more information. + * + * Revision history: + * 13 Nov 1998: Initial version, Martin Pool + * 08 Feb 2000: Change to keeping and erasing a trail, + * + * It would be nice to draw curvy shapes rather than just straight + * lines, but X11 doesn't have spline primitives (?) so we'd have to + * do all the work ourselves */ + +#include "screenhack.h" +#include "erase.h" + +#include +#include +#include + + +typedef struct { + int width, height; /* in cells */ + unsigned short *cells; +} CriticalModel; + +typedef struct { + int trail; /* length of trail */ + int cell_size; +} CriticalSettings; + + +/* Number of screens that should be drawn before reinitializing the + model, and count of the number of screens done so far. */ + +struct state { + Display *dpy; + Window window; + + int n_restart, i_restart; + XWindowAttributes wattr; + CriticalModel *model; + int batchcount; + XPoint *history; /* in cell coords */ + long delay_usecs; + GC fgc, bgc; + XGCValues gcv; + CriticalSettings settings; + + int d_n_colors; + XColor *d_colors; + int lines_per_color; + int d_i_color; + int d_pos; + int d_wrapped; + + int d_i_batch; + eraser_state *eraser; + +}; + + +static CriticalModel * model_allocate (int w, int h); +static void model_initialize (CriticalModel *); + + +static int +clip (int low, int val, int high) +{ + if (val < low) + return low; + else if (val > high) + return high; + else + return val; +} + + +/* Allocate an return a new simulation model datastructure. + */ + +static CriticalModel * +model_allocate (int model_w, int model_h) +{ + CriticalModel *mm; + + mm = malloc (sizeof (CriticalModel)); + if (!mm) + return 0; + + mm->width = model_w; + mm->height = model_h; + + mm->cells = malloc (sizeof (unsigned short) * model_w * model_h); + if (!mm->cells) + return 0; + + return mm; +} + + + +/* Initialize the data model underlying the hack. + + For the self-organizing criticality hack, this consists of a 2d + array full of random integers. + + I've considered storing the data as (say) a binary tree within a 2d + array, to make finding the highest value faster at the expense of + storage space: searching the whole array on each iteration seems a + little inefficient. However, the screensaver doesn't seem to take + up many cycles as it is: presumably the search is pretty quick + compared to the sleeps. The current version uses less than 1% of + the CPU time of an AMD K6-233. Many machines running X11 at this + point in time seem to be memory-limited, not CPU-limited. + + The root of all evil, and all that. +*/ + + +static void +model_initialize (CriticalModel *mm) +{ + int i; + + for (i = mm->width * mm->height - 1; i >= 0; i--) + { + mm->cells[i] = (unsigned short) random (); + } +} + + +/* Move one step forward in the criticality simulation. + + This function locates and returns in (TOP_X, TOP_Y) the location of + the highest-valued cell in the model. It also replaces that cell + and it's eight nearest neighbours with new random values. + Neighbours that fall off the edge of the model are simply + ignored. */ +static void +model_step (CriticalModel *mm, XPoint *ptop) +{ + int x, y, i; + int dx, dy; + unsigned short top_value = 0; + int top_x = 0, top_y = 0; + + /* Find the top cell */ + top_value = 0; + i = 0; + for (y = 0; y < mm->height; y++) + for (x = 0; x < mm->width; x++) + { + if (mm->cells[i] >= top_value) + { + top_value = mm->cells[i]; + top_x = x; + top_y = y; + } + i++; + } + + /* Replace it and its neighbours with new random values */ + for (dy = -1; dy <= 1; dy++) + { + int yy = top_y + dy; + if (yy < 0 || yy >= mm->height) + continue; + + for (dx = -1; dx <= 1; dx++) + { + int xx = top_x + dx; + if (xx < 0 || xx >= mm->width) + continue; + + mm->cells[yy * mm->width + xx] = (unsigned short) random(); + } + } + + ptop->x = top_x; + ptop->y = top_y; +} + + +/* Construct and return in COLORS and N_COLORS a new set of colors, + depending on the resource settings. */ +static void +setup_colormap (struct state *st, XColor **colors, int *n_colors) +{ + Bool writable; + char const * color_scheme; + + /* Make a colormap */ + *n_colors = get_integer_resource (st->dpy, "ncolors", "Integer"); + if (*n_colors < 3) + *n_colors = 3; + + *colors = (XColor *) calloc (sizeof(XColor), *n_colors); + if (!*colors) + { + fprintf (stderr, "%s:%d: can't allocate memory for colors\n", + __FILE__, __LINE__); + return; + } + + writable = False; + color_scheme = get_string_resource (st->dpy, "colorscheme", "ColorScheme"); + + if (!strcmp (color_scheme, "random")) + { + make_random_colormap (st->dpy, st->wattr.visual, + st->wattr.colormap, + *colors, n_colors, + True, True, &writable, True); + } + else if (!strcmp (color_scheme, "smooth")) + { + make_smooth_colormap (st->dpy, st->wattr.visual, + st->wattr.colormap, + *colors, n_colors, + True, &writable, True); + } + else + { + make_uniform_colormap (st->dpy, st->wattr.visual, + st->wattr.colormap, + *colors, n_colors, True, + &writable, True); + } +} + + +/* Free allocated colormap created by setup_colormap. */ +static void +free_colormap (struct state *st, XColor **colors, int n_colors) +{ + free_colors (st->dpy, st->wattr.colormap, *colors, n_colors); + free (*colors); +} + + + +/* Draw one step of the hack. Positions are cell coordinates. */ +static void +draw_step (struct state *st, GC gc, int pos) +{ + int cell_size = st->settings.cell_size; + int half = cell_size/2; + int old_pos = (pos + st->settings.trail - 1) % st->settings.trail; + + pos = pos % st->settings.trail; + + XDrawLine (st->dpy, st->window, gc, + st->history[pos].x * cell_size + half, + st->history[pos].y * cell_size + half, + st->history[old_pos].x * cell_size + half, + st->history[old_pos].y * cell_size + half); +} + + + +static void * +critical_init (Display *dpy, Window window) +{ + struct state *st = (struct state *) calloc (1, sizeof(*st)); + int model_w, model_h; + st->dpy = dpy; + st->window = window; + + /* Find window attributes */ + XGetWindowAttributes (st->dpy, st->window, &st->wattr); + + st->batchcount = get_integer_resource (st->dpy, "batchcount", "Integer"); + if (st->batchcount < 5) + st->batchcount = 5; + + st->lines_per_color = 10; + + /* For the moment the model size is just fixed -- making it vary + with the screen size just makes the hack boring on large + screens. */ + model_w = 80; + st->settings.cell_size = st->wattr.width / model_w; + model_h = st->settings.cell_size ? + st->wattr.height / st->settings.cell_size : 0; + + /* Construct the initial model state. */ + + st->settings.trail = clip(2, get_integer_resource (st->dpy, "trail", "Integer"), 1000); + + st->history = calloc (st->settings.trail, sizeof (st->history[0])); + if (!st->history) + { + fprintf (stderr, "critical: " + "couldn't allocate trail history of %d cells\n", + st->settings.trail); + abort(); + } + + st->model = model_allocate (model_w, model_h); + if (!st->model) + { + fprintf (stderr, "critical: error preparing the model\n"); + abort(); + } + + /* make a black gc for the background */ + st->gcv.foreground = get_pixel_resource (st->dpy, st->wattr.colormap, + "background", "Background"); + st->bgc = XCreateGC (st->dpy, st->window, GCForeground, &st->gcv); + + st->fgc = XCreateGC (st->dpy, st->window, 0, &st->gcv); + +#ifdef HAVE_COCOA + jwxyz_XSetAntiAliasing (dpy, st->fgc, False); + jwxyz_XSetAntiAliasing (dpy, st->bgc, False); +#endif + + st->delay_usecs = get_integer_resource (st->dpy, "delay", "Integer"); + st->n_restart = get_integer_resource (st->dpy, "restart", "Integer"); + + setup_colormap (st, &st->d_colors, &st->d_n_colors); + model_initialize (st->model); + model_step (st->model, &st->history[0]); + st->d_pos = 1; + st->d_wrapped = 0; + st->i_restart = 0; + st->d_i_batch = st->batchcount; + + return st; +} + +static unsigned long +critical_draw (Display *dpy, Window window, void *closure) +{ + struct state *st = (struct state *) closure; + + if (st->eraser) { + st->eraser = erase_window (st->dpy, st->window, st->eraser); + return st->delay_usecs; + } + + /* for (d_i_batch = batchcount; d_i_batch; d_i_batch--) */ + { + /* Set color */ + if ((st->d_i_batch % st->lines_per_color) == 0) + { + st->d_i_color = (st->d_i_color + 1) % st->d_n_colors; + st->gcv.foreground = st->d_colors[st->d_i_color].pixel; + XChangeGC (st->dpy, st->fgc, GCForeground, &st->gcv); + } + + assert(st->d_pos >= 0 && st->d_pos < st->settings.trail); + model_step (st->model, &st->history[st->d_pos]); + + draw_step (st, st->fgc, st->d_pos); + + /* we use the history as a ring buffer, but don't start erasing until + we've d_wrapped around once. */ + if (++st->d_pos >= st->settings.trail) + { + st->d_pos -= st->settings.trail; + st->d_wrapped = 1; + } + + if (st->d_wrapped) + { + draw_step (st, st->bgc, st->d_pos+1); + } + + } + + st->d_i_batch--; + if (st->d_i_batch < 0) + st->d_i_batch = st->batchcount; + else + return st->delay_usecs; + + st->i_restart = (st->i_restart + 1) % st->n_restart; + + if (st->i_restart == 0) + { + /* Time to start a new simulation, this one has probably got + to be a bit boring. */ + free_colormap (st, &st->d_colors, st->d_n_colors); + setup_colormap (st, &st->d_colors, &st->d_n_colors); + st->eraser = erase_window (st->dpy, st->window, st->eraser); + model_initialize (st->model); + model_step (st->model, &st->history[0]); + st->d_pos = 1; + st->d_wrapped = 0; + st->d_i_batch = st->batchcount; + } + + return st->delay_usecs; +} + +static void +critical_reshape (Display *dpy, Window window, void *closure, + unsigned int w, unsigned int h) +{ +} + +static Bool +critical_event (Display *dpy, Window window, void *closure, XEvent *event) +{ + return False; +} + +static void +critical_free (Display *dpy, Window window, void *closure) +{ + struct state *st = (struct state *) closure; + free (st); +} + + +/* Options this module understands. */ +static XrmOptionDescRec critical_options[] = { + { "-ncolors", ".ncolors", XrmoptionSepArg, 0 }, + { "-delay", ".delay", XrmoptionSepArg, 0 }, + { "-colorscheme", ".colorscheme", XrmoptionSepArg, 0 }, + { "-restart", ".restart", XrmoptionSepArg, 0 }, + { "-batchcount", ".batchcount", XrmoptionSepArg, 0 }, + { "-trail", ".trail", XrmoptionSepArg, 0 }, + { 0, 0, 0, 0 } /* end */ +}; + + +/* Default xrm resources. */ +static const char *critical_defaults[] = { + ".background: black", + "*fpsSolid: true", + "*colorscheme: smooth", + "*delay: 10000", + "*ncolors: 64", + "*restart: 8", + "*batchcount: 1500", + "*trail: 50", + 0 /* end */ +}; + + +XSCREENSAVER_MODULE ("Critical", critical) diff --git a/hacks/critical.man b/hacks/critical.man new file mode 100644 index 00000000..324c1164 --- /dev/null +++ b/hacks/critical.man @@ -0,0 +1,94 @@ +.TH XScreenSaver 1 "08 Feb 2000" "X Version 11" +.SH NAME +critical - Draw a system showing self-organizing criticality +.SH SYNOPSIS +.B critical +[\-display \fIhost:display.screen\fP] [\-foreground \fIcolor\fP] [\-background \fIcolor\fP] [\-window] [\-root] [\-mono] [\-install] [\-visual \fIvisual\fP] [\-delay \fIseconds\fP] [\-random \fIboolean\fP] [\-ncolors \fIint\fP] [\-offset \fIint\fP] +[\-fps] +.SH DESCRIPTION +The \fIcritical\fP program displays a self-organizing critical system +that gradually emerges from chaos. + +\fIcritical\fP performs a simulation on a two-dimensional array of +integers. The array is initialized to random values. On each +iteration, it draws a line to the array position with the greatest +value. It then replaces that location and the eight neighboring +locations with randomly-selected values. + +The lines are initially random, but over time a chaotic +self-organizing system evolves: areas of the screen which happen to +have lower values are less likely to be updated to new values, and so +the line tends to avoid those areas. Eventually, the histogram of +changes approaches the power-law curve typical of such systems. + +The simplest documented self-organizing system is the one-dimensional +equivalent of \fIcritical\fP. + +I heard about this algorithm second-hand: apparently there was an +article in \fIScientific American\fP describing it sometime in 1997. +.SH OPTIONS +.I critical +accepts the following options: +.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 \-mono +If on a color display, pretend we're on a monochrome display. +.TP 8 +.B \-install +Install a private colormap for the window. +.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 \-delay \fIusecs\fP +Number of microseconds to wait after drawing each line. +.TP 8 +.B \-random \fIboolean\fP +Whether to use randomly selected colours rather than a cycle around +the colour wheel. +.TP 8 +.B \-offset \fIinteger\fP +The maximum random radius increment to use. +.TP 8 +.B \-ncolors \fIinteger\fP +How many colors should be allocated in the color ramp (note that this +value interacts with \fIoffset\fP.) +.TP 8 +.B \-trail \fIinteger\fP +Length of the trail: between 5 and 100 is nice. +.TP 8 +.B \-fps +Display the current frame rate and CPU load. +.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) +.BR xscreensaver-command (1) +.BR xscreensaver-demo (1) +.SH COPYRIGHT +Copyright \(co 1998 by Martin Pool. + +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 +Martin Pool , 1998-2000. Based in part on the +XScreenSaver code by Jamie Zawinski . diff --git a/hacks/crystal.c b/hacks/crystal.c new file mode 100644 index 00000000..a1c501d8 --- /dev/null +++ b/hacks/crystal.c @@ -0,0 +1,1279 @@ +/* -*- Mode: C; tab-width: 4 -*- */ +/* crystal --- polygons moving according to plane group rules */ + +#if 0 +static const char sccsid[] = "@(#)crystal.c 4.12 98/09/10 xlockmore"; +#endif + +/*- + * Copyright (c) 1997 by Jouk Jansen + * + * Permission to use, copy, modify, and distribute this software and its + * documentation for any purpose and without fee is hereby granted, + * provided that the above copyright notice appear in all copies and that + * both that copyright notice and this permission notice appear in + * supporting documentation. + * + * This file is provided AS IS with no warranties of any kind. The author + * shall have no liability with respect to the infringement of copyrights, + * trade secrets or any patents by this file or any part thereof. In no + * event will the author be liable for any lost revenue or profits or + * other special, indirect and consequential damages. + * + * The author should like to be notified if changes have been made to the + * routine. Response will only be guaranteed when a VMS version of the + * program is available. + * + * A moving polygon-mode. The polygons obey 2D-planegroup symmetry. + * + * The groupings of the cells fall in 3 categories: + * oblique groups 1 and 2 where the angle gamma ranges from 60 to 120 degrees + * square groups 3 through 11 where the angle gamma is 90 degrees + * hexagonal groups 12 through 17 where the angle gamma is 120 degrees + * + * Revision History: + * 03-Dec-98: Random inversion of y-axis included to simulate hexagonal groups + * with an angle of 60 degrees. + * 10-Sep-98: new colour scheme + * 24-Feb-98: added option centre which turns on/off forcing the centre of + * the screen to be used + * added option maxsize which forces the dimensions to be chasen + * in such ua way that the largest possible part of the screen is + * used + * When only one unit cell is drawn, it is chosen at random + * 18-Feb-98: added support for negative numbers with -nx and -ny meaning + * "random" choice with given maximum + * added +/-grid option. If -cell is specified this option + * determines if one or all unit cells are drawn. + * -batchcount is now a parameter for all the objects on the screen + * instead of the number of "unique" objects + * The maximum size of the objects now scales with the part + * of the screen used. + * fixed "size" problem. Now very small non-vissable objects + * are not allowed + * 13-Feb-98: randomized the unit cell size + * runtime options -/+cell (turn on/off unit cell drawing) + * -nx num (number of translational symmetries in x-direction + * -ny num (idem y-direction but ignored for square and + * hexagonal space groups + * i.e. try xlock -mode crystal -nx 3 -ny 2 + * Fullrandom overrules the -/+cell option. + * 05-Feb-98: Revision + bug repairs + * shows unit cell + * use part of the screen for unit cell + * in hexagonal and square groups a&b axis forced to be equal + * cell angle for oblique groups randomly chosen between 60 and 120 + * bugs solved: planegroups with cell angles <> 90.0 now work properly + * 19-Sep-97: Added remaining hexagonal groups + * 12-Jun-97: Created + */ + +#ifdef STANDALONE +# define DEFAULTS "*delay: 60000 \n" \ + "*count: -500 \n" \ + "*cycles: 200 \n" \ + "*size: -15 \n" \ + "*ncolors: 100 \n" \ + "*fpsSolid: true \n" \ + +# define crystal_handle_event 0 +# include "xlockmore.h" /* in xscreensaver distribution */ +#else /* STANDALONE */ +# include "xlock.h" /* in xlockmore distribution */ +# include "color.h" +#endif /* STANDALONE */ + +#define DEF_CELL "True" /* Draw unit cell */ +#define DEF_GRID "False" /* Draw unit all cell if DEF_CELL is True */ +#define DEF_NX "-3" /* number of unit cells in x-direction */ +#define DEF_NX1 1 /* number of unit cells in x-direction */ +#define DEF_NY "-3" /* number of unit cells in y-direction */ +#define DEF_NY1 1 /* number of unit cells in y-direction */ +#define DEF_CENTRE "False" +#define DEF_MAXSIZE "False" +#define DEF_CYCLE "True" + +#undef NRAND +#define NRAND(n) ( (n) ? (int) (LRAND() % (n)) : 0) + +#define min(a,b) ((a) <= (b) ? (a) : (b)) + +static int nx, ny; + +static Bool unit_cell, grid_cell, centre, maxsize, cycle_p; + +static XrmOptionDescRec opts[] = +{ + {"-nx", "crystal.nx", XrmoptionSepArg, 0}, + {"-ny", "crystal.ny", XrmoptionSepArg, 0}, + {"-centre", ".crystal.centre", XrmoptionNoArg, "on"}, + {"+centre", ".crystal.centre", XrmoptionNoArg, "off"}, + {"-maxsize", ".crystal.maxsize", XrmoptionNoArg, "on"}, + {"+maxsize", ".crystal.maxsize", XrmoptionNoArg, "off"}, + {"-cell", ".crystal.cell", XrmoptionNoArg, "on"}, + {"+cell", ".crystal.cell", XrmoptionNoArg, "off"}, + {"-grid", ".crystal.grid", XrmoptionNoArg, "on"}, + {"+grid", ".crystal.grid", XrmoptionNoArg, "off"}, + {"-shift", ".crystal.shift", XrmoptionNoArg, "on"}, + {"+shift", ".crystal.shift", XrmoptionNoArg, "off"} +}; + +static argtype vars[] = +{ + {&nx, "nx", "nx", DEF_NX, t_Int}, + {&ny, "ny", "ny", DEF_NY, t_Int}, + {¢re, "centre", "Centre", DEF_CENTRE, t_Bool}, + {&maxsize, "maxsize", "Maxsize", DEF_MAXSIZE, t_Bool}, + {&unit_cell, "cell", "Cell", DEF_CELL, t_Bool}, + {&grid_cell, "grid", "Grid", DEF_GRID, t_Bool}, + {&cycle_p, "shift", "Shift", DEF_CYCLE, t_Bool} +}; +static OptionStruct desc[] = +{ + {"-nx num", "Number of unit cells in x-direction"}, + {"-ny num", "Number of unit cells in y-direction"}, + {"-/+centre", "turn on/off centering on screen"}, + {"-/+maxsize", "turn on/off use of maximum part of screen"}, + {"-/+cell", "turn on/off drawing of unit cell"}, + {"-/+grid", "turn on/off drawing of grid of unit cells (if -cell is on)"}, + {"-/+shift", "turn on/off colour cycling"} +}; + +ENTRYPOINT ModeSpecOpt crystal_opts = +{sizeof opts / sizeof opts[0], opts, sizeof vars / sizeof vars[0], vars, desc}; + +#ifdef USE_MODULES +ModStruct crystal_description = +{"crystal", "init_crystal", "draw_crystal", "release_crystal", + "refresh_crystal", "init_crystal", NULL, &crystal_opts, + 60000, -40, 200, -15, 64, 1.0, "", + "Shows polygons in 2D plane groups", 0, NULL}; + +#endif + +#define DEF_NUM_ATOM 10 + +#define DEF_SIZ_ATOM 10 + +#define PI_RAD (M_PI / 180.0) + +static Bool centro[17] = +{ + False, + True, + False, + False, + False, + True, + True, + True, + True, + True, + True, + True, + False, + False, + False, + True, + True +}; + +static Bool primitive[17] = +{ + True, + True, + True, + True, + False, + True, + True, + True, + False, + True, + True, + True, + True, + True, + True, + True, + True +}; + +static short numops[34] = +{ + 1, 0, + 1, 0, + 9, 7, + 2, 0, + 9, 7, + 9, 7, + 4, 2, + 5, 3, + 9, 7, + 8, 6, + 10, 6, + 8, 4, + 16, 13, + 19, 13, + 16, 10, + 19, 13, + 19, 13 +}; + +static short operation[114] = +{ + 1, 0, 0, 1, 0, 0, + -1, 0, 0, 1, 0, 1, + -1, 0, 0, 1, 1, 0, + 1, 0, 0, 1, 0, 0, + -1, 0, 0, 1, 1, 1, + 1, 0, 0, 1, 1, 1, + 0, -1, 1, 0, 0, 0, + 1, 0, 0, 1, 0, 0, + -1, 0, 0, 1, 0, 0, + 0, 1, 1, 0, 0, 0, + -1, 0, -1, 1, 0, 0, + 1, -1, 0, -1, 0, 0, + 0, 1, 1, 0, 0, 0, + 0, -1, 1, -1, 0, 0, + -1, 1, -1, 0, 0, 0, + 1, 0, 0, 1, 0, 0, + 0, -1, -1, 0, 0, 0, + -1, 1, 0, 1, 0, 0, + 1, 0, 1, -1, 0, 0 +}; + +typedef struct { + unsigned long colour; + int x0, y0, velocity[2]; + float angle, velocity_a; + int num_point, at_type, size_at; + XPoint xy[5]; +} crystalatom; + +typedef struct { + Bool painted; + int win_width, win_height, num_atom; + int planegroup, a, b, offset_w, offset_h, nx, ny; + float gamma; + crystalatom *atom; + GC gc; + Bool unit_cell, grid_cell; + Colormap cmap; + XColor *colors; + int ncolors; + Bool cycle_p, mono_p, no_colors; + unsigned long blackpixel, whitepixel, fg, bg; + int direction, invert; +} crystalstruct; + +static crystalstruct *crystals = NULL; + +static void +trans_coor(XPoint * xyp, XPoint * new_xyp, int num_points, + float gamma) +{ + int i; + + for (i = 0; i <= num_points; i++) { + new_xyp[i].x = xyp[i].x + + (int) (xyp[i].y * sin((gamma - 90.0) * PI_RAD)); + new_xyp[i].y = (int) (xyp[i].y / cos((gamma - 90.0) * PI_RAD)); + } +} + +static void +trans_coor_back(XPoint * xyp, XPoint * new_xyp, + int num_points, float gamma, int offset_w, int offset_h , + int winheight , int invert ) +{ + int i; + + for (i = 0; i <= num_points; i++) { + new_xyp[i].y = (int) (xyp[i].y * cos((gamma - 90) * PI_RAD)) + + offset_h; + new_xyp[i].x = xyp[i].x - (int) (xyp[i].y * sin((gamma - 90.0) + * PI_RAD)) + offset_w; + if ( invert ) new_xyp[i].y = winheight - new_xyp[i].y; + } +} + +static void +crystal_setupatom(crystalatom * atom0, float gamma) +{ + XPoint xy[5]; + int x0, y0; + + y0 = (int) (atom0->y0 * cos((gamma - 90) * PI_RAD)); + x0 = atom0->x0 - (int) (atom0->y0 * sin((gamma - 90.0) * PI_RAD)); + switch (atom0->at_type) { + case 0: /* rectangles */ + xy[0].x = x0 + (int) (2 * atom0->size_at * + cos(atom0->angle)) + + (int) (atom0->size_at * sin(atom0->angle)); + xy[0].y = y0 + (int) (atom0->size_at * + cos(atom0->angle)) - + (int) (2 * atom0->size_at * sin(atom0->angle)); + xy[1].x = x0 + (int) (2 * atom0->size_at * + cos(atom0->angle)) - + (int) (atom0->size_at * sin(atom0->angle)); + xy[1].y = y0 - (int) (atom0->size_at * + cos(atom0->angle)) - + (int) (2 * atom0->size_at * sin(atom0->angle)); + xy[2].x = x0 - (int) (2 * atom0->size_at * + cos(atom0->angle)) - + (int) (atom0->size_at * sin(atom0->angle)); + xy[2].y = y0 - (int) (atom0->size_at * + cos(atom0->angle)) + + (int) (2 * atom0->size_at * sin(atom0->angle)); + xy[3].x = x0 - (int) (2 * atom0->size_at * + cos(atom0->angle)) + + (int) (atom0->size_at * sin(atom0->angle)); + xy[3].y = y0 + (int) (atom0->size_at * + cos(atom0->angle)) + + (int) (2 * atom0->size_at * + sin(atom0->angle)); + xy[4].x = xy[0].x; + xy[4].y = xy[0].y; + trans_coor(xy, atom0->xy, 4, gamma); + return; + case 1: /* squares */ + xy[0].x = x0 + (int) (1.5 * atom0->size_at * + cos(atom0->angle)) + + (int) (1.5 * atom0->size_at * + sin(atom0->angle)); + xy[0].y = y0 + (int) (1.5 * atom0->size_at * + cos(atom0->angle)) - + (int) (1.5 * atom0->size_at * + sin(atom0->angle)); + xy[1].x = x0 + (int) (1.5 * atom0->size_at * + cos(atom0->angle)) - + (int) (1.5 * atom0->size_at * + sin(atom0->angle)); + xy[1].y = y0 - (int) (1.5 * atom0->size_at * + cos(atom0->angle)) - + (int) (1.5 * atom0->size_at * + sin(atom0->angle)); + xy[2].x = x0 - (int) (1.5 * atom0->size_at * + cos(atom0->angle)) - + (int) (1.5 * atom0->size_at * + sin(atom0->angle)); + xy[2].y = y0 - (int) (1.5 * atom0->size_at * + cos(atom0->angle)) + + (int) (1.5 * atom0->size_at * + sin(atom0->angle)); + xy[3].x = x0 - (int) (1.5 * atom0->size_at * + cos(atom0->angle)) + + (int) (1.5 * atom0->size_at * + sin(atom0->angle)); + xy[3].y = y0 + (int) (1.5 * atom0->size_at * + cos(atom0->angle)) + + (int) (1.5 * atom0->size_at * + sin(atom0->angle)); + xy[4].x = xy[0].x; + xy[4].y = xy[0].y; + trans_coor(xy, atom0->xy, 4, gamma); + return; + case 2: /* triangles */ + xy[0].x = x0 + (int) (1.5 * atom0->size_at * + sin(atom0->angle)); + xy[0].y = y0 + (int) (1.5 * atom0->size_at * + cos(atom0->angle)); + xy[1].x = x0 + (int) (1.5 * atom0->size_at * + cos(atom0->angle)) - + (int) (1.5 * atom0->size_at * + sin(atom0->angle)); + xy[1].y = y0 - (int) (1.5 * atom0->size_at * + cos(atom0->angle)) - + (int) (1.5 * atom0->size_at * + sin(atom0->angle)); + xy[2].x = x0 - (int) (1.5 * atom0->size_at * + cos(atom0->angle)) - + (int) (1.5 * atom0->size_at * + sin(atom0->angle)); + xy[2].y = y0 - (int) (1.5 * atom0->size_at * + cos(atom0->angle)) + + (int) (1.5 * atom0->size_at * + sin(atom0->angle)); + xy[3].x = xy[0].x; + xy[3].y = xy[0].y; + trans_coor(xy, atom0->xy, 3, gamma); + return; + } +} + +static void +crystal_drawatom(ModeInfo * mi, crystalatom * atom0) +{ + crystalstruct *cryst; + Display *display = MI_DISPLAY(mi); + Window window = MI_WINDOW(mi); + int j, k, l, m; + + cryst = &crystals[MI_SCREEN(mi)]; + for (j = numops[2 * cryst->planegroup + 1]; + j < numops[2 * cryst->planegroup]; j++) { + XPoint xy[5], new_xy[5]; + XPoint xy_1[5]; + int xtrans, ytrans; + + xtrans = operation[j * 6] * atom0->x0 + operation[j * 6 + 1] * + atom0->y0 + (int) (operation[j * 6 + 4] * cryst->a / + 2.0); + ytrans = operation[j * 6 + 2] * atom0->x0 + operation[j * 6 + + 3] * atom0->y0 + (int) (operation[j * 6 + 5] * + cryst->b / 2.0); + if (xtrans < 0) { + if (xtrans < -cryst->a) + xtrans = 2 * cryst->a; + else + xtrans = cryst->a; + } else if (xtrans >= cryst->a) + xtrans = -cryst->a; + else + xtrans = 0; + if (ytrans < 0) + ytrans = cryst->b; + else if (ytrans >= cryst->b) + ytrans = -cryst->b; + else + ytrans = 0; + for (k = 0; k < atom0->num_point; k++) { + xy[k].x = operation[j * 6] * atom0->xy[k].x + + operation[j * 6 + 1] * + atom0->xy[k].y + (int) (operation[j * 6 + 4] * + cryst->a / 2.0) + + xtrans; + xy[k].y = operation[j * 6 + 2] * atom0->xy[k].x + + operation[j * 6 + 3] * + atom0->xy[k].y + (int) (operation[j * 6 + 5] * + cryst->b / 2.0) + + ytrans; + } + xy[atom0->num_point].x = xy[0].x; + xy[atom0->num_point].y = xy[0].y; + for (l = 0; l < cryst->nx; l++) { + for (m = 0; m < cryst->ny; m++) { + + for (k = 0; k <= atom0->num_point; k++) { + xy_1[k].x = xy[k].x + l * cryst->a; + xy_1[k].y = xy[k].y + m * cryst->b; + } + trans_coor_back(xy_1, new_xy, atom0->num_point, + cryst->gamma, cryst->offset_w, + cryst->offset_h , + cryst->win_height, + cryst->invert); + XFillPolygon(display, window, cryst->gc, new_xy, + atom0->num_point, Convex, CoordModeOrigin); + } + } + if (centro[cryst->planegroup] == True) { + for (k = 0; k <= atom0->num_point; k++) { + xy[k].x = cryst->a - xy[k].x; + xy[k].y = cryst->b - xy[k].y; + } + for (l = 0; l < cryst->nx; l++) { + for (m = 0; m < cryst->ny; m++) { + + for (k = 0; k <= atom0->num_point; k++) { + xy_1[k].x = xy[k].x + l * cryst->a; + xy_1[k].y = xy[k].y + m * cryst->b; + } + trans_coor_back(xy_1, new_xy, atom0->num_point, + cryst->gamma, + cryst->offset_w, + cryst->offset_h , + cryst->win_height , + cryst->invert); + XFillPolygon(display, window, cryst->gc, + new_xy, + atom0->num_point, Convex, + CoordModeOrigin); + } + } + } + if (primitive[cryst->planegroup] == False) { + if (xy[atom0->num_point].x >= (int) (cryst->a / 2.0)) + xtrans = (int) (-cryst->a / 2.0); + else + xtrans = (int) (cryst->a / 2.0); + if (xy[atom0->num_point].y >= (int) (cryst->b / 2.0)) + ytrans = (int) (-cryst->b / 2.0); + else + ytrans = (int) (cryst->b / 2.0); + for (k = 0; k <= atom0->num_point; k++) { + xy[k].x = xy[k].x + xtrans; + xy[k].y = xy[k].y + ytrans; + } + for (l = 0; l < cryst->nx; l++) { + for (m = 0; m < cryst->ny; m++) { + + for (k = 0; k <= atom0->num_point; k++) { + xy_1[k].x = xy[k].x + l * cryst->a; + xy_1[k].y = xy[k].y + m * cryst->b; + } + trans_coor_back(xy_1, new_xy, atom0->num_point, + cryst->gamma, + cryst->offset_w, + cryst->offset_h , + cryst->win_height, + cryst->invert); + XFillPolygon(display, window, cryst->gc, + new_xy, + atom0->num_point, Convex, + CoordModeOrigin); + } + } + if (centro[cryst->planegroup] == True) { + XPoint xy1[5]; + + for (k = 0; k <= atom0->num_point; k++) { + xy1[k].x = cryst->a - xy[k].x; + xy1[k].y = cryst->b - xy[k].y; + } + for (l = 0; l < cryst->nx; l++) { + for (m = 0; m < cryst->ny; m++) { + + for (k = 0; k <= atom0->num_point; k++) { + xy_1[k].x = xy1[k].x + l * cryst->a; + xy_1[k].y = xy1[k].y + m * cryst->b; + } + trans_coor_back(xy_1, new_xy, atom0->num_point, + cryst->gamma, + cryst->offset_w, + cryst->offset_h , + cryst->win_height, + cryst->invert); + XFillPolygon(display, window, + cryst->gc, + new_xy, atom0->num_point, + Convex, CoordModeOrigin); + } + } + } + } + } +} + +ENTRYPOINT void init_crystal(ModeInfo * mi); +ENTRYPOINT void release_crystal(ModeInfo * mi); + + +ENTRYPOINT void +draw_crystal(ModeInfo * mi) +{ + Display *display = MI_DISPLAY(mi); + crystalstruct *cryst = &crystals[MI_SCREEN(mi)]; + int i; + +#ifdef HAVE_COCOA /* Don't second-guess Quartz's double-buffering */ + XClearWindow(MI_DISPLAY(mi), MI_WINDOW(mi)); +#endif + + if (cryst->no_colors) { + release_crystal(mi); + init_crystal(mi); + return; + } + cryst->painted = True; + MI_IS_DRAWN(mi) = True; + XSetFunction(display, cryst->gc, GXxor); + +/* Rotate colours */ + if (cryst->cycle_p) { + rotate_colors(display, cryst->cmap, cryst->colors, cryst->ncolors, + cryst->direction); + if (!(LRAND() % 1000)) + cryst->direction = -cryst->direction; + } + for (i = 0; i < cryst->num_atom; i++) { + crystalatom *atom0; + + atom0 = &cryst->atom[i]; + + if (MI_IS_INSTALL(mi) && MI_NPIXELS(mi) > 2) { + XSetForeground(display, cryst->gc, cryst->colors[atom0->colour].pixel); + } else { + XSetForeground(display, cryst->gc, atom0->colour); + } + crystal_drawatom(mi, atom0); + atom0->velocity[0] += NRAND(3) - 1; + atom0->velocity[0] = MAX(-20, MIN(20, atom0->velocity[0])); + atom0->velocity[1] += NRAND(3) - 1; + atom0->velocity[1] = MAX(-20, MIN(20, atom0->velocity[1])); + atom0->x0 += atom0->velocity[0]; + /*if (cryst->gamma == 90.0) { */ + if (atom0->x0 < 0) + atom0->x0 += cryst->a; + else if (atom0->x0 >= cryst->a) + atom0->x0 -= cryst->a; + atom0->y0 += atom0->velocity[1]; + if (atom0->y0 < 0) + atom0->y0 += cryst->b; + else if (atom0->y0 >= cryst->b) + atom0->y0 -= cryst->b; + /*} */ + atom0->velocity_a += ((float) NRAND(1001) - 500.0) / 2000.0; + atom0->angle += atom0->velocity_a; + crystal_setupatom(atom0, cryst->gamma); + crystal_drawatom(mi, atom0); + } + XSetFunction(display, cryst->gc, GXcopy); +} + +ENTRYPOINT void +refresh_crystal(ModeInfo * mi) +{ + Display *display = MI_DISPLAY(mi); + Window window = MI_WINDOW(mi); + crystalstruct *cryst = &crystals[MI_SCREEN(mi)]; + int i; + + if (!cryst->painted) + return; + MI_CLEARWINDOW(mi); + XSetFunction(display, cryst->gc, GXxor); + + if (cryst->unit_cell) { + int y_coor1 , y_coor2; + + if (MI_NPIXELS(mi) > 2) + XSetForeground(display, cryst->gc, MI_PIXEL(mi, NRAND(MI_NPIXELS(mi)))); + else + XSetForeground(display, cryst->gc, MI_WHITE_PIXEL(mi)); + if (cryst->grid_cell) { + int inx, iny; + + if ( cryst->invert ) + y_coor1 = y_coor2 = cryst->win_height - cryst->offset_h; + else + y_coor1 = y_coor2 = cryst->offset_h; + XDrawLine(display, window, cryst->gc, cryst->offset_w, + y_coor1, cryst->offset_w + cryst->nx * cryst->a, + y_coor2); + if ( cryst->invert ) + { + y_coor1 = cryst->win_height - cryst->offset_h; + y_coor2 = cryst->win_height - (int) (cryst->ny * + cryst->b * + cos((cryst->gamma - 90) * PI_RAD)) - + cryst->offset_h; + } + else + { + y_coor1 = cryst->offset_h; + y_coor2 = (int) (cryst->ny * cryst->b * + cos((cryst->gamma - 90) * PI_RAD)) + + cryst->offset_h; + } + XDrawLine(display, window, cryst->gc, cryst->offset_w, + y_coor1, (int) (cryst->offset_w - cryst->ny * cryst->b * + sin((cryst->gamma - 90) * PI_RAD)), + y_coor2); + inx = cryst->nx; + for (iny = 1; iny <= cryst->ny; iny++) { + if ( cryst->invert ) + { + y_coor1 = cryst->win_height - + (int) (iny * cryst->b * cos((cryst->gamma - 90) * + PI_RAD)) - cryst->offset_h; + y_coor2 = cryst->win_height - + (int) (iny * cryst->b * cos((cryst->gamma - 90) * + PI_RAD)) - + cryst->offset_h; + } + else + { + y_coor1 = (int) (iny * cryst->b * cos((cryst->gamma - 90) * + PI_RAD)) + cryst->offset_h; + y_coor2 = (int) (iny * cryst->b * cos((cryst->gamma - 90) * PI_RAD)) + + cryst->offset_h; + } + XDrawLine(display, window, cryst->gc, + (int) (cryst->offset_w + + inx * cryst->a - (int) (iny * cryst->b * + sin((cryst->gamma - 90) * PI_RAD))), + y_coor1, + (int) (cryst->offset_w - iny * cryst->b * + sin((cryst->gamma - 90) * PI_RAD)), + y_coor2); + } + iny = cryst->ny; + for (inx = 1; inx <= cryst->nx; inx++) { + if ( cryst->invert ) + { + y_coor1 =cryst->win_height - + (int) (iny * cryst->b * + cos((cryst->gamma - 90) * + PI_RAD)) - cryst->offset_h; + y_coor2 =cryst->win_height - cryst->offset_h; + } + else + { + y_coor1 =(int) (iny * cryst->b * + cos((cryst->gamma - 90) * + PI_RAD)) + cryst->offset_h; + y_coor2 =cryst->offset_h; + } + XDrawLine(display, window, cryst->gc, + (int) (cryst->offset_w + + inx * cryst->a - (int) (iny * cryst->b * + sin((cryst->gamma - 90) * PI_RAD))), + y_coor1, + cryst->offset_w + inx * cryst->a, + y_coor2); + } + } else { + int inx, iny; + + inx = NRAND(cryst->nx); + iny = NRAND(cryst->ny); + if ( cryst->invert ) + { + y_coor1 =cryst->win_height - + (int) (iny * cryst->b * + cos((cryst->gamma - 90) * + PI_RAD)) - + cryst->offset_h; + y_coor2 =cryst->win_height - + (int) ( ( iny + 1 ) * cryst->b * + cos((cryst->gamma - 90) * + PI_RAD)) - + cryst->offset_h; + } + else + { + y_coor1 =(int) (iny * cryst->b * + cos((cryst->gamma - 90) * + PI_RAD)) + + cryst->offset_h; + y_coor2 =(int) (( iny + 1 ) * cryst->b * + cos((cryst->gamma - 90) * + PI_RAD)) + + cryst->offset_h; + } + XDrawLine(display, window, cryst->gc, + cryst->offset_w + inx * cryst->a - (int) (iny * cryst->b * sin((cryst->gamma - 90) * PI_RAD)), + y_coor1, + cryst->offset_w + (inx + 1) * cryst->a - (int) (iny * cryst->b * sin((cryst->gamma - 90) * PI_RAD)), + y_coor1); + XDrawLine(display, window, cryst->gc, + cryst->offset_w + inx * cryst->a - (int) (iny * cryst->b * sin((cryst->gamma - 90) * PI_RAD)), + y_coor1, + cryst->offset_w + inx * cryst->a - (int) ((iny + 1) * cryst->b * sin((cryst->gamma - 90) * PI_RAD)), + y_coor2); + XDrawLine(display, window, cryst->gc, + cryst->offset_w + (inx + 1) * cryst->a - (int) (iny * cryst->b * sin((cryst->gamma - 90) * PI_RAD)), + y_coor1, + cryst->offset_w + (inx + 1) * cryst->a - (int) ((iny + 1) * cryst->b * sin((cryst->gamma - 90) * PI_RAD)), + y_coor2); + XDrawLine(display, window, cryst->gc, + cryst->offset_w + inx * cryst->a - (int) ((iny + 1) * cryst->b * sin((cryst->gamma - 90) * PI_RAD)), + y_coor2, + cryst->offset_w + (inx + 1) * cryst->a - (int) ((iny + 1) * cryst->b * sin((cryst->gamma - 90) * PI_RAD)), + y_coor2); + } + } + for (i = 0; i < cryst->num_atom; i++) { + crystalatom *atom0; + + atom0 = &cryst->atom[i]; + if (MI_IS_INSTALL(mi) && MI_NPIXELS(mi) > 2) { + XSetForeground(display, cryst->gc, cryst->colors[atom0->colour].pixel); + } else { + XSetForeground(display, cryst->gc, atom0->colour); + } + crystal_drawatom(mi, atom0); + } + XSetFunction(display, cryst->gc, GXcopy); +} + +ENTRYPOINT void +release_crystal(ModeInfo * mi) +{ + Display *display = MI_DISPLAY(mi); + + if (crystals != NULL) { + int screen; + + for (screen = 0; screen < MI_NUM_SCREENS(mi); screen++) { + crystalstruct *cryst = &crystals[screen]; + + if (MI_IS_INSTALL(mi) && MI_NPIXELS(mi) > 2) { + MI_WHITE_PIXEL(mi) = cryst->whitepixel; + MI_BLACK_PIXEL(mi) = cryst->blackpixel; +#ifndef STANDALONE + MI_FG_PIXEL(mi) = cryst->fg; + MI_BG_PIXEL(mi) = cryst->bg; +#endif + if (cryst->colors && cryst->ncolors && !cryst->no_colors) + free_colors(display, cryst->cmap, cryst->colors, cryst->ncolors); + if (cryst->colors) + (void) free((void *) cryst->colors); +#if 0 /* #### wrong! -jwz */ + XFreeColormap(display, cryst->cmap); +#endif + } + if (cryst->gc != NULL) + XFreeGC(display, cryst->gc); + if (cryst->atom != NULL) + (void) free((void *) cryst->atom); + } + (void) free((void *) crystals); + crystals = NULL; + } +} + +ENTRYPOINT void +init_crystal(ModeInfo * mi) +{ + Display *display = MI_DISPLAY(mi); + Window window = MI_WINDOW(mi); + crystalstruct *cryst; + int i, max_atoms, size_atom, neqv; + int cell_min; + +#define MIN_CELL 200 + +/* initialize */ + if (crystals == NULL) { + if ((crystals = (crystalstruct *) calloc(MI_NUM_SCREENS(mi), + sizeof (crystalstruct))) == NULL) + return; + } + cryst = &crystals[MI_SCREEN(mi)]; + + if (!cryst->gc) { + if (MI_IS_INSTALL(mi) && MI_NPIXELS(mi) > 2) { + XColor color; + +#ifndef STANDALONE + extern char *background; + extern char *foreground; + + cryst->fg = MI_FG_PIXEL(mi); + cryst->bg = MI_BG_PIXEL(mi); +#endif + cryst->blackpixel = MI_BLACK_PIXEL(mi); + cryst->whitepixel = MI_WHITE_PIXEL(mi); +#if 0 /* #### wrong! -jwz */ + cryst->cmap = XCreateColormap(display, window, + MI_VISUAL(mi), AllocNone); + XSetWindowColormap(display, window, cryst->cmap); +#else + cryst->cmap = mi->xgwa.colormap; +#endif + (void) XParseColor(display, cryst->cmap, "black", &color); + (void) XAllocColor(display, cryst->cmap, &color); + MI_BLACK_PIXEL(mi) = color.pixel; + (void) XParseColor(display, cryst->cmap, "white", &color); + (void) XAllocColor(display, cryst->cmap, &color); + MI_WHITE_PIXEL(mi) = color.pixel; +#ifndef STANDALONE + (void) XParseColor(display, cryst->cmap, background, &color); + (void) XAllocColor(display, cryst->cmap, &color); + MI_BG_PIXEL(mi) = color.pixel; + (void) XParseColor(display, cryst->cmap, foreground, &color); + (void) XAllocColor(display, cryst->cmap, &color); + MI_FG_PIXEL(mi) = color.pixel; +#endif + cryst->colors = 0; + cryst->ncolors = 0; + } + if ((cryst->gc = XCreateGC(display, MI_WINDOW(mi), + (unsigned long) 0, (XGCValues *) NULL)) == None) + return; + } +/* Clear Display */ + MI_CLEARWINDOW(mi); + cryst->painted = False; + XSetFunction(display, cryst->gc, GXxor); + + +/*Set up crystal data */ + cryst->direction = (LRAND() & 1) ? 1 : -1; + if (MI_IS_FULLRANDOM(mi)) { + if (LRAND() & 1) + cryst->unit_cell = True; + else + cryst->unit_cell = False; + } else + cryst->unit_cell = unit_cell; + if (cryst->unit_cell) { + if (MI_IS_FULLRANDOM(mi)) { + if (LRAND() & 1) + cryst->grid_cell = True; + else + cryst->grid_cell = False; + } else + cryst->grid_cell = grid_cell; + } + cryst->win_width = MI_WIDTH(mi); + cryst->win_height = MI_HEIGHT(mi); + cell_min = min(cryst->win_width / 2 + 1, MIN_CELL); + cell_min = min(cell_min, cryst->win_height / 2 + 1); + cryst->planegroup = NRAND(17); + cryst->invert = NRAND(2); + if (MI_IS_VERBOSE(mi)) + (void) fprintf(stdout, "Selected plane group no %d\n", + cryst->planegroup + 1); + if (cryst->planegroup > 11) + cryst->gamma = 120.0; + else if (cryst->planegroup < 2) + cryst->gamma = 60.0 + NRAND(60); + else + cryst->gamma = 90.0; + neqv = numops[2 * cryst->planegroup] - numops[2 * cryst->planegroup + 1]; + if (centro[cryst->planegroup] == True) + neqv = 2 * neqv; + if (primitive[cryst->planegroup] == False) + neqv = 2 * neqv; + + + if (nx > 0) + cryst->nx = nx; + else if (nx < 0) + cryst->nx = NRAND(-nx) + 1; + else + cryst->nx = DEF_NX1; + if (cryst->planegroup > 8) + cryst->ny = cryst->nx; + else if (ny > 0) + cryst->ny = ny; + else if (ny < 0) + cryst->ny = NRAND(-ny) + 1; + else + cryst->ny = DEF_NY1; + neqv = neqv * cryst->nx * cryst->ny; + + cryst->num_atom = MI_COUNT(mi); + max_atoms = MI_COUNT(mi); + if (cryst->num_atom == 0) { + cryst->num_atom = DEF_NUM_ATOM; + max_atoms = DEF_NUM_ATOM; + } else if (cryst->num_atom < 0) { + max_atoms = -cryst->num_atom; + cryst->num_atom = NRAND(-cryst->num_atom) + 1; + } + if (neqv > 1) + cryst->num_atom = cryst->num_atom / neqv + 1; + + if (cryst->atom == NULL) + cryst->atom = (crystalatom *) calloc(max_atoms, sizeof ( + crystalatom)); + + if (maxsize) { + if (cryst->planegroup < 13) { + cryst->gamma = 90.0; + cryst->offset_w = 0; + cryst->offset_h = 0; + if (cryst->planegroup < 10) { + cryst->b = cryst->win_height; + cryst->a = cryst->win_width; + } else { + cryst->b = min(cryst->win_height, cryst->win_width); + cryst->a = cryst->b; + } + } else { + cryst->gamma = 120.0; + cryst->a = (int) (cryst->win_width * 2.0 / 3.0); + cryst->b = cryst->a; + cryst->offset_h = (int) (cryst->b * 0.25 * + cos((cryst->gamma - 90) * PI_RAD)); + cryst->offset_w = (int) (cryst->b * 0.5); + } + } else { + int max_repeat = 10; + cryst->offset_w = -1; + while (max_repeat-- && + (cryst->offset_w < 4 || (int) (cryst->offset_w - cryst->b * + sin((cryst->gamma - 90) * PI_RAD)) < 4) + ) { + cryst->b = NRAND((int) (cryst->win_height / (cos((cryst->gamma - 90) * + PI_RAD))) - cell_min) + cell_min; + if (cryst->planegroup > 8) + cryst->a = cryst->b; + else + cryst->a = NRAND(cryst->win_width - cell_min) + cell_min; + cryst->offset_w = (int) ((cryst->win_width - (cryst->a - cryst->b * + sin((cryst->gamma - 90) * + PI_RAD))) / 2.0); + } + cryst->offset_h = (int) ((cryst->win_height - cryst->b * cos(( + cryst->gamma - 90) * PI_RAD)) / 2.0); + if (!centre) { + if (cryst->offset_h > 0) + cryst->offset_h = NRAND(2 * cryst->offset_h); + cryst->offset_w = (int) (cryst->win_width - cryst->a - + cryst->b * + fabs(sin((cryst->gamma - 90) * PI_RAD))); + if (cryst->gamma > 90.0) { + if (cryst->offset_w > 0) + cryst->offset_w = NRAND(cryst->offset_w) + + (int) (cryst->b * sin((cryst->gamma - 90) * PI_RAD)); + else + cryst->offset_w = (int) (cryst->b * sin((cryst->gamma - 90) * + PI_RAD)); + } else if (cryst->offset_w > 0) + cryst->offset_w = NRAND(cryst->offset_w); + else + cryst->offset_w = 0; + } + } + + size_atom = min((int) ((float) (cryst->a) / 40.) + 1, + (int) ((float) (cryst->b) / 40.) + 1); + if (MI_SIZE(mi) < size_atom) { + if (MI_SIZE(mi) < -size_atom) + size_atom = -size_atom; + else + size_atom = MI_SIZE(mi); + } + cryst->a = cryst->a / cryst->nx; + cryst->b = cryst->b / cryst->ny; + if (cryst->unit_cell) { + int y_coor1 , y_coor2; + + if (MI_NPIXELS(mi) > 2) + XSetForeground(display, cryst->gc, MI_PIXEL(mi, NRAND(MI_NPIXELS(mi)))); + else + XSetForeground(display, cryst->gc, MI_WHITE_PIXEL(mi)); + if (cryst->grid_cell) { + int inx, iny; + + if ( cryst->invert ) + y_coor1 = y_coor2 = cryst->win_height - cryst->offset_h; + else + y_coor1 = y_coor2 = cryst->offset_h; + XDrawLine(display, window, cryst->gc, cryst->offset_w, + y_coor1, cryst->offset_w + cryst->nx * cryst->a, + y_coor2); + if ( cryst->invert ) + { + y_coor1 = cryst->win_height - cryst->offset_h; + y_coor2 = cryst->win_height - (int) (cryst->ny * + cryst->b * + cos((cryst->gamma - 90) * PI_RAD)) - + cryst->offset_h; + } + else + { + y_coor1 = cryst->offset_h; + y_coor2 = (int) (cryst->ny * cryst->b * + cos((cryst->gamma - 90) * PI_RAD)) + + cryst->offset_h; + } + XDrawLine(display, window, cryst->gc, cryst->offset_w, + y_coor1, (int) (cryst->offset_w - cryst->ny * cryst->b * + sin((cryst->gamma - 90) * PI_RAD)), + y_coor2); + inx = cryst->nx; + for (iny = 1; iny <= cryst->ny; iny++) { + if ( cryst->invert ) + { + y_coor1 = cryst->win_height - + (int) (iny * cryst->b * cos((cryst->gamma - 90) * + PI_RAD)) - cryst->offset_h; + y_coor2 = cryst->win_height - + (int) (iny * cryst->b * cos((cryst->gamma - 90) * + PI_RAD)) - + cryst->offset_h; + } + else + { + y_coor1 = (int) (iny * cryst->b * cos((cryst->gamma - 90) * + PI_RAD)) + cryst->offset_h; + y_coor2 = (int) (iny * cryst->b * cos((cryst->gamma - 90) * PI_RAD)) + + cryst->offset_h; + } + XDrawLine(display, window, cryst->gc, + (int) (cryst->offset_w + + inx * cryst->a - (int) (iny * cryst->b * + sin((cryst->gamma - 90) * PI_RAD))), + y_coor1, + (int) (cryst->offset_w - iny * cryst->b * + sin((cryst->gamma - 90) * PI_RAD)), + y_coor2); + } + iny = cryst->ny; + for (inx = 1; inx <= cryst->nx; inx++) { + if ( cryst->invert ) + { + y_coor1 =cryst->win_height - + (int) (iny * cryst->b * + cos((cryst->gamma - 90) * + PI_RAD)) - cryst->offset_h; + y_coor2 =cryst->win_height - cryst->offset_h; + } + else + { + y_coor1 =(int) (iny * cryst->b * + cos((cryst->gamma - 90) * + PI_RAD)) + cryst->offset_h; + y_coor2 =cryst->offset_h; + } + XDrawLine(display, window, cryst->gc, + (int) (cryst->offset_w + + inx * cryst->a - (int) (iny * cryst->b * + sin((cryst->gamma - 90) * PI_RAD))), + y_coor1, + cryst->offset_w + inx * cryst->a, + y_coor2); + } + } else { + int inx, iny; + + inx = NRAND(cryst->nx); + iny = NRAND(cryst->ny); + if ( cryst->invert ) + { + y_coor1 =cryst->win_height - + (int) (iny * cryst->b * + cos((cryst->gamma - 90) * + PI_RAD)) - + cryst->offset_h; + y_coor2 =cryst->win_height - + (int) ( ( iny + 1 ) * cryst->b * + cos((cryst->gamma - 90) * + PI_RAD)) - + cryst->offset_h; + } + else + { + y_coor1 =(int) (iny * cryst->b * + cos((cryst->gamma - 90) * + PI_RAD)) + + cryst->offset_h; + y_coor2 =(int) (( iny + 1 ) * cryst->b * + cos((cryst->gamma - 90) * + PI_RAD)) + + cryst->offset_h; + } + XDrawLine(display, window, cryst->gc, + cryst->offset_w + inx * cryst->a - (int) (iny * cryst->b * sin((cryst->gamma - 90) * PI_RAD)), + y_coor1, + cryst->offset_w + (inx + 1) * cryst->a - (int) (iny * cryst->b * sin((cryst->gamma - 90) * PI_RAD)), + y_coor1); + XDrawLine(display, window, cryst->gc, + cryst->offset_w + inx * cryst->a - (int) (iny * cryst->b * sin((cryst->gamma - 90) * PI_RAD)), + y_coor1, + cryst->offset_w + inx * cryst->a - (int) ((iny + 1) * cryst->b * sin((cryst->gamma - 90) * PI_RAD)), + y_coor2); + XDrawLine(display, window, cryst->gc, + cryst->offset_w + (inx + 1) * cryst->a - (int) (iny * cryst->b * sin((cryst->gamma - 90) * PI_RAD)), + y_coor1, + cryst->offset_w + (inx + 1) * cryst->a - (int) ((iny + 1) * cryst->b * sin((cryst->gamma - 90) * PI_RAD)), + y_coor2); + XDrawLine(display, window, cryst->gc, + cryst->offset_w + inx * cryst->a - (int) ((iny + 1) * cryst->b * sin((cryst->gamma - 90) * PI_RAD)), + y_coor2, + cryst->offset_w + (inx + 1) * cryst->a - (int) ((iny + 1) * cryst->b * sin((cryst->gamma - 90) * PI_RAD)), + y_coor2); + } + } + if (MI_IS_INSTALL(mi) && MI_NPIXELS(mi) > 2) { +/* Set up colour map */ + if (cryst->colors && cryst->ncolors && !cryst->no_colors) + free_colors(display, cryst->cmap, cryst->colors, cryst->ncolors); + if (cryst->colors) + (void) free((void *) cryst->colors); + cryst->colors = 0; + cryst->ncolors = MI_NCOLORS(mi); + if (cryst->ncolors < 2) + cryst->ncolors = 2; + if (cryst->ncolors <= 2) + cryst->mono_p = True; + else + cryst->mono_p = False; + + if (cryst->mono_p) + cryst->colors = 0; + else + cryst->colors = (XColor *) malloc(sizeof (*cryst->colors) * (cryst->ncolors + 1)); + cryst->cycle_p = has_writable_cells(mi->xgwa.screen, MI_VISUAL(mi)); + if (cryst->cycle_p) { + if (MI_IS_FULLRANDOM(mi)) { + if (!NRAND(8)) + cryst->cycle_p = False; + else + cryst->cycle_p = True; + } else { + cryst->cycle_p = cycle_p; + } + } + if (!cryst->mono_p) { + if (!(LRAND() % 10)) + make_random_colormap(MI_DISPLAY(mi), MI_VISUAL(mi), cryst->cmap, cryst->colors, &cryst->ncolors, + True, True, &cryst->cycle_p, True); + else if (!(LRAND() % 2)) + make_uniform_colormap(MI_DISPLAY(mi), MI_VISUAL(mi), cryst->cmap, cryst->colors, &cryst->ncolors, + True, &cryst->cycle_p, True); + else + make_smooth_colormap(MI_DISPLAY(mi), MI_VISUAL(mi), cryst->cmap, cryst->colors, &cryst->ncolors, + True, &cryst->cycle_p, True); + } +#if 0 /* #### wrong! -jwz */ + XInstallColormap(display, cryst->cmap); +#endif + if (cryst->ncolors < 2) { + cryst->ncolors = 2; + cryst->no_colors = True; + } else + cryst->no_colors = False; + if (cryst->ncolors <= 2) + cryst->mono_p = True; + + if (cryst->mono_p) + cryst->cycle_p = False; + + } + for (i = 0; i < cryst->num_atom; i++) { + crystalatom *atom0; + + atom0 = &cryst->atom[i]; + if (MI_IS_INSTALL(mi) && MI_NPIXELS(mi) > 2) { + if (cryst->ncolors > 2) + atom0->colour = NRAND(cryst->ncolors - 2) + 2; + else + atom0->colour = 1; /* Just in case */ + XSetForeground(display, cryst->gc, cryst->colors[atom0->colour].pixel); + } else { + if (MI_NPIXELS(mi) > 2) + atom0->colour = MI_PIXEL(mi, NRAND(MI_NPIXELS(mi))); + else + atom0->colour = 1; /*Xor'red so WHITE may not be appropriate */ + XSetForeground(display, cryst->gc, atom0->colour); + } + atom0->x0 = NRAND(cryst->a); + atom0->y0 = NRAND(cryst->b); + atom0->velocity[0] = NRAND(7) - 3; + atom0->velocity[1] = NRAND(7) - 3; + atom0->velocity_a = (NRAND(7) - 3) * PI_RAD; + atom0->angle = NRAND(90) * PI_RAD; + atom0->at_type = NRAND(3); + if (size_atom == 0) + atom0->size_at = DEF_SIZ_ATOM; + else if (size_atom > 0) + atom0->size_at = size_atom; + else + atom0->size_at = NRAND(-size_atom) + 1; + atom0->size_at++; + if (atom0->at_type == 2) + atom0->num_point = 3; + else + atom0->num_point = 4; + crystal_setupatom(atom0, cryst->gamma); + crystal_drawatom(mi, atom0); + } + XSetFunction(display, cryst->gc, GXcopy); +} + +ENTRYPOINT void +reshape_crystal(ModeInfo * mi, int width, int height) +{ + release_crystal(mi); + init_crystal(mi); +} + +XSCREENSAVER_MODULE ("Crystal", crystal) diff --git a/hacks/crystal.man b/hacks/crystal.man new file mode 100644 index 00000000..06bf6546 --- /dev/null +++ b/hacks/crystal.man @@ -0,0 +1,81 @@ +.TH XScreenSaver 1 "" "X Version 11" +.SH NAME +crystal - kaleidescope. +.SH SYNOPSIS +.B crystal +[\-display \fIhost:display.screen\fP] +[\-visual \fIvisual\fP] +[\-window] +[\-root] +[\-grid] +[\-no-cell] +[\-centre] +[\-nx \fInumber\fP] +[\-ny \fInumber\fP] +[\-count \fInumber\fP] +[\-delay \fInumber\fP] +[\-ncolors \fInumber\fP] +[\-fps] +.SH DESCRIPTION +Moving polygons, similar to a kaleidescope (more like a kaleidescope than +the hack called `kaleid,' actually.) +.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 \-grid | \-no-grid +Whether to draw grid. +.TP 8 +.B \-cell | \-no-cell +Whether to draw the cell. +.TP 8 +.B \-centre | \-no-centre +Whether to center on screen +.TP 8 +.B \-nx \fInumber\fP +Horizontal Symmetries. -10 - 10. Default: -3. +.TP 8 +.B \-ny \fInumber\fP +Vertical Symmetries. -10 - 10. Default: -3. +.TP 8 +.B \-count \fInumber\fP +Count. -5000 - 5000. Default: -500. +.TP 8 +.B \-delay \fInumber\fP +Per-frame delay, in microseconds. Default: 60000 (0.06 seconds.). +.TP 8 +.B \-ncolors \fInumber\fP +Number of Colors. Default: 100. +.TP 8 +.B \-fps +Display the current frame rate and CPU load. +.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 2002 by Jouk Jansen. 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 +Jouk Jansen. diff --git a/hacks/cwaves.c b/hacks/cwaves.c new file mode 100644 index 00000000..912ccc70 --- /dev/null +++ b/hacks/cwaves.c @@ -0,0 +1,208 @@ +/* xscreensaver, Copyright (c) 2007 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. + * + * cwaves -- languid sinusoidal colors. + */ + +#include "screenhack.h" +#include +#include "xpm-pixmap.h" + +#define BELLRAND(n) ((frand((n)) + frand((n)) + frand((n))) / 3) + +typedef struct { + double scale; + double offset; + double delta; +} wave; + +typedef struct { + Display *dpy; + Window window; + XWindowAttributes xgwa; + GC gc; + int delay; + int scale; + int ncolors; + XColor *colors; + + int nwaves; + wave *waves; + int debug_p; + +} state; + + +static void * +cwaves_init (Display *dpy, Window window) +{ + int i; + XGCValues gcv; + state *st = (state *) calloc (1, sizeof (*st)); + + st->dpy = dpy; + st->window = window; + XGetWindowAttributes (st->dpy, st->window, &st->xgwa); + + st->debug_p = get_boolean_resource (dpy, "debug", "Boolean"); + st->scale = get_integer_resource (dpy, "scale", "Integer"); + if (st->scale <= 0) st->scale = 1; + st->ncolors = get_integer_resource (dpy, "ncolors", "Integer"); + if (st->ncolors < 4) st->ncolors = 4; + st->colors = (XColor *) malloc (sizeof(*st->colors) * (st->ncolors+1)); + make_smooth_colormap (st->dpy, st->xgwa.visual, st->xgwa.colormap, + st->colors, &st->ncolors, + True, 0, False); + + st->gc = XCreateGC (st->dpy, st->window, 0, &gcv); + st->delay = get_integer_resource (dpy, "delay", "Integer"); + + st->nwaves = get_integer_resource (dpy, "nwaves", "Integer"); + st->waves = (wave *) calloc (st->nwaves, sizeof(*st->waves)); + + for (i = 0; i < st->nwaves; i++) + { + st->waves[i].scale = frand(0.03) + 0.005; + st->waves[i].offset = frand(M_PI); + st->waves[i].delta = (BELLRAND(2)-1) / 15.0; + } + + return st; +} + + +static unsigned long +cwaves_draw (Display *dpy, Window window, void *closure) +{ + state *st = (state *) closure; + int i, x; + + for (i = 0; i < st->nwaves; i++) + st->waves[i].offset += st->waves[i].delta; + + for (x = 0; x < st->xgwa.width; x += st->scale) + { + double v = 0; + int j; + for (i = 0; i < st->nwaves; i++) + v += cos ((x * st->waves[i].scale) - st->waves[i].offset); + v /= st->nwaves; + + j = st->ncolors * (v/2 + 0.5); + if (j < 0 || j >= st->ncolors) abort(); + XSetForeground (st->dpy, st->gc, st->colors[j].pixel); + XFillRectangle (st->dpy, st->window, st->gc, + x, 0, st->scale, st->xgwa.height); + } + + if (st->debug_p) + { + int wh = (st->xgwa.height / (st->nwaves + 1)) * 0.9; + int i; + XSetLineAttributes (st->dpy, st->gc, 2, LineSolid, CapRound, JoinRound); + XSetForeground (st->dpy, st->gc, BlackPixelOfScreen (st->xgwa.screen)); + for (i = 0; i < st->nwaves; i++) + { + int y = st->xgwa.height * i / (st->nwaves + 1); + int ox = -1, oy = -1; + + for (x = 0; x < st->xgwa.width; x += st->scale) + { + int yy; + double v = 0; + v = cos ((x * st->waves[i].scale) - st->waves[i].offset); + v /= 2; + + yy = y + wh/2 + (wh * v); + if (ox == -1) + ox = x, oy = yy; + XDrawLine (st->dpy, st->window, st->gc, ox, oy, x, yy); + ox = x; + oy = yy; + } + } + + { + int y = st->xgwa.height * i / (st->nwaves + 1); + int ox = -1, oy = -1; + + for (x = 0; x < st->xgwa.width; x += st->scale) + { + int yy; + double v = 0; + for (i = 0; i < st->nwaves; i++) + v += cos ((x * st->waves[i].scale) - st->waves[i].offset); + v /= st->nwaves; + v /= 2; + + yy = y + wh/2 + (wh * v); + if (ox == -1) + ox = x, oy = yy; + XDrawLine (st->dpy, st->window, st->gc, ox, oy, x, yy); + ox = x; + oy = yy; + } + } + } + + return st->delay; +} + + +static void +cwaves_reshape (Display *dpy, Window window, void *closure, + unsigned int w, unsigned int h) +{ + state *st = (state *) closure; + XGetWindowAttributes (st->dpy, st->window, &st->xgwa); +} + +static Bool +cwaves_event (Display *dpy, Window window, void *closure, XEvent *event) +{ + state *st = (state *) closure; + if (event->type == ButtonPress) + { + make_smooth_colormap (st->dpy, st->xgwa.visual, st->xgwa.colormap, + st->colors, &st->ncolors, + True, 0, False); + return True; + } + return False; +} + +static void +cwaves_free (Display *dpy, Window window, void *closure) +{ +} + + +static const char *cwaves_defaults [] = { + ".background: black", + ".foreground: white", + "*ncolors: 600", + "*nwaves: 15", + "*scale: 2", + "*debug: False", + "*delay: 20000", + 0 +}; + +static XrmOptionDescRec cwaves_options [] = { + { "-delay", ".delay", XrmoptionSepArg, 0 }, + { "-waves", ".nwaves", XrmoptionSepArg, 0 }, + { "-colors", ".ncolors", XrmoptionSepArg, 0 }, + { "-scale", ".scale", XrmoptionSepArg, 0 }, + { "-debug", ".debug", XrmoptionNoArg, "True" }, + { 0, 0, 0, 0 } +}; + + +XSCREENSAVER_MODULE ("CWaves", cwaves) diff --git a/hacks/cwaves.man b/hacks/cwaves.man new file mode 100644 index 00000000..57f3978d --- /dev/null +++ b/hacks/cwaves.man @@ -0,0 +1,76 @@ +.TH XScreenSaver 1 "14-Jun-97" "X Version 11" +.SH NAME +cwaves - languid sinusoidal colors +.SH SYNOPSIS +.B cwaves +[\-display \fIhost:display.screen\fP] +[\-foreground \fIcolor\fP] +[\-background \fIcolor\fP] +[\-window] +[\-root] +[\-mono] +[\-install] +[\-visual \fIvisual\fP] +[\-delay \fIusecs\fP] +[\-waves \fIint\fP] +[\-colors \fIint\fP] +[\-fps] +.SH DESCRIPTION +The \fIcwaves\fP program draws a languidly-scrolling vertical field +of sinusoidal colors. +.SH OPTIONS +.I cwaves +accepts the following options: +.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 \-mono +If on a color display, pretend we're on a monochrome display. +.TP 8 +.B \-install +Install a private colormap for the window. +.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 \-delay \fImicroseconds\fP +How much of a delay should be introduced between steps of the animation. +Default 20000, or about 1/50th second. +.TP 8 +.B \-waves \fIint\fP +How many cosines to add together. The more waves, the more complex +the apparent motion. +.TP 8 +.B \-colors \fIint\fP +How many colors to use. Default 800. The more colors, the smoother the +blending will be. +.TP 8 +.B \-fps +Display the current frame rate and CPU load. +.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 2007 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 , 2-Jul-2007. diff --git a/hacks/cynosure.c b/hacks/cynosure.c new file mode 100644 index 00000000..baf3be43 --- /dev/null +++ b/hacks/cynosure.c @@ -0,0 +1,432 @@ +/* cynosure --- draw some rectangles + * + * 01-aug-96: written in Java by ozymandias G desiderata + * 25-dec-97: ported to C and XScreenSaver by Jamie Zawinski + * + * Original version: + * http://www.organic.com/staff/ogd/java/cynosure.html + * http://www.organic.com/staff/ogd/java/source/cynosure/Cynosure-java.txt + * + * Original comments and copyright: + * + * Cynosure.java + * A Java implementation of Stephen Linhart's Cynosure screen-saver as a + * drop-in class. + * + * Header: /home/ogd/lib/cvs/aoaioxxysz/graphics/Cynosure.java,v 1.2 1996/08/02 02:41:21 ogd Exp + * + * ozymandias G desiderata + * Thu Aug 1 1996 + * + * COPYRIGHT NOTICE + * + * Copyright 1996 ozymandias G desiderata. Title, ownership rights, and + * intellectual property rights in and to this software remain with + * ozymandias G desiderata. This software may be copied, modified, + * or used as long as this copyright is retained. Use this code at your + * own risk. + * + * Revision: 1.2 + * + * Log: Cynosure.java,v + * Revision 1.2 1996/08/02 02:41:21 ogd + * Added a few more comments, fixed messed-up header. + * + * Revision 1.1.1.1 1996/08/02 02:30:45 ogd + * First version + */ + +#include "screenhack.h" + +/* #define DO_STIPPLE */ + +struct state { + Display *dpy; + Window window; + + XColor *colors; + int ncolors; + +#ifndef DO_STIPPLE + XColor *colors2; + int ncolors2; +#endif + + int fg_pixel, bg_pixel; + GC fg_gc, bg_gc, shadow_gc; + + int curColor; + int curBase; /* color progression */ + int shadowWidth; + int elevation; /* offset of dropshadow */ + int sway; /* time until base color changed */ + int timeLeft; /* until base color used */ + int tweak; /* amount of color variance */ + int gridSize; + int iterations, i, delay; + XWindowAttributes xgwa; +}; + + +/** + * The smallest size for an individual cell. + **/ +#define MINCELLSIZE 16 + +/** + * The narrowest a rectangle can be. + **/ +#define MINRECTSIZE 6 + +/** + * Every so often genNewColor() generates a completely random + * color. This variable sets how frequently that happens. It's + * currently set to happen 1% of the time. + * + * @see #genNewColor + **/ +#define THRESHOLD 100 /*0.01*/ + +static void paint(struct state *st); +static int genNewColor(struct state *st); +static int genConstrainedColor(struct state *st, int base, int tweak); +static int c_tweak(struct state *st, int base, int tweak); + + +static void * +cynosure_init (Display *d, Window w) +{ + struct state *st = (struct state *) calloc (1, sizeof(*st)); + XGCValues gcv; + + st->dpy = d; + st->window = w; + + st->curColor = 0; + st->curBase = st->curColor; + st->shadowWidth = get_integer_resource (st->dpy, "shadowWidth", "Integer"); + st->elevation = get_integer_resource (st->dpy, "elevation", "Integer"); + st->sway = get_integer_resource (st->dpy, "sway", "Integer"); + st->tweak = get_integer_resource (st->dpy, "tweak", "Integer"); + st->gridSize = get_integer_resource (st->dpy, "gridSize", "Integer"); + st->timeLeft = 0; + + XGetWindowAttributes (st->dpy, st->window, &st->xgwa); + + st->ncolors = get_integer_resource (st->dpy, "colors", "Colors"); + if (st->ncolors < 2) st->ncolors = 2; + if (st->ncolors <= 2) mono_p = True; + + if (mono_p) + st->colors = 0; + else + st->colors = (XColor *) malloc(sizeof(*st->colors) * (st->ncolors+1)); + + if (mono_p) + ; + else { + make_smooth_colormap (st->dpy, st->xgwa.visual, st->xgwa.colormap, st->colors, &st->ncolors, + True, 0, True); + if (st->ncolors <= 2) { + mono_p = True; + st->ncolors = 2; + if (st->colors) free(st->colors); + st->colors = 0; + } + } + + st->bg_pixel = get_pixel_resource(st->dpy, + st->xgwa.colormap, "background", "Background"); + st->fg_pixel = get_pixel_resource(st->dpy, + st->xgwa.colormap, "foreground", "Foreground"); + + gcv.foreground = st->fg_pixel; + st->fg_gc = XCreateGC(st->dpy, st->window, GCForeground, &gcv); + gcv.foreground = st->bg_pixel; + st->bg_gc = XCreateGC(st->dpy, st->window, GCForeground, &gcv); + +#ifdef DO_STIPPLE + gcv.fill_style = FillStippled; + gcv.stipple = XCreateBitmapFromData(st->dpy, st->window, "\125\252", 8, 2); + st->shadow_gc = XCreateGC(st->dpy, st->window, GCForeground|GCFillStyle|GCStipple, &gcv); + XFreePixmap(st->dpy, gcv.stipple); + +#else /* !DO_STIPPLE */ + st->shadow_gc = XCreateGC(st->dpy, st->window, GCForeground, &gcv); + +# ifdef HAVE_COCOA /* allow non-opaque alpha components in pixel values */ + jwxyz_XSetAlphaAllowed (st->dpy, st->shadow_gc, True); +# endif + + if (st->colors) + { + int i; + st->ncolors2 = st->ncolors; + st->colors2 = (XColor *) malloc(sizeof(*st->colors2) * (st->ncolors2+1)); + + for (i = 0; i < st->ncolors2; i++) + { +# ifdef HAVE_COCOA + /* give a non-opaque alpha to the shadow colors */ + unsigned long pixel = st->colors[i].pixel; + unsigned long amask = BlackPixelOfScreen (st->xgwa.screen); + unsigned long a = (0x77777777 & amask); + pixel = (pixel & (~amask)) | a; + st->colors2[i].pixel = pixel; +# else /* !HAVE_COCOA */ + int h; + double s, v; + rgb_to_hsv (st->colors[i].red, + st->colors[i].green, + st->colors[i].blue, + &h, &s, &v); + v *= 0.4; + hsv_to_rgb (h, s, v, + &st->colors2[i].red, + &st->colors2[i].green, + &st->colors2[i].blue); + st->colors2[i].pixel = st->colors[i].pixel; + XAllocColor (st->dpy, st->xgwa.colormap, &st->colors2[i]); +# endif /* !HAVE_COCOA */ + } + } +# endif /* !DO_STIPPLE */ + + st->delay = get_integer_resource (st->dpy, "delay", "Delay"); + st->iterations = get_integer_resource (st->dpy, "iterations", "Iterations"); + + return st; +} + +static unsigned long +cynosure_draw (Display *dpy, Window window, void *closure) +{ + struct state *st = (struct state *) closure; + if (st->iterations > 0 && ++st->i >= st->iterations) + { + st->i = 0; + if (!mono_p) + XSetWindowBackground(st->dpy, st->window, + st->colors[random() % st->ncolors].pixel); + XClearWindow(st->dpy, st->window); + } + paint(st); + + return st->delay; +} + + +/** + * paint adds a new layer of multicolored rectangles within a grid of + * randomly generated size. Each row of rectangles is the same color, + * but colors vary slightly from row to row. Each rectangle is placed + * within a regularly-sized cell, but each rectangle is sized and + * placed randomly within that cell. + * + * @param g the Graphics coordinate in which to draw + * @see #genNewColor + **/ +static void paint(struct state *st) +{ + int i; + int cellsWide, cellsHigh, cellWidth, cellHeight; + int width = st->xgwa.width; + int height = st->xgwa.height; + + /* How many cells wide the grid is (equal to gridSize +/- (gridSize / 2)) + */ + cellsWide = c_tweak(st, st->gridSize, st->gridSize / 2); + /* How many cells high the grid is (equal to gridSize +/- (gridSize / 2)) + */ + cellsHigh = c_tweak(st, st->gridSize, st->gridSize / 2); + /* How wide each cell in the grid is */ + cellWidth = width / cellsWide; + /* How tall each cell in the grid is */ + cellHeight = height / cellsHigh; + + /* Ensure that each cell is above a certain minimum size */ + + if (cellWidth < MINCELLSIZE) { + cellWidth = MINCELLSIZE; + cellsWide = width / cellWidth; + } + + if (cellHeight < MINCELLSIZE) { + cellHeight = MINCELLSIZE; + cellsHigh = width / cellWidth; + } + + /* fill the grid with randomly-generated cells */ + for(i = 0; i < cellsHigh; i++) { + int j; + + /* Each row is a different color, randomly generated (but constrained) */ + if (!mono_p) + { + int c = genNewColor(st); + XSetForeground(st->dpy, st->fg_gc, st->colors[c].pixel); +# ifndef DO_STIPPLE + if (st->colors2) + XSetForeground(st->dpy, st->shadow_gc, st->colors2[c].pixel); +# endif + } + + for(j = 0; j < cellsWide; j++) { + int curWidth, curHeight, curX, curY; + + /* Generate a random height for a rectangle and make sure that */ + /* it's above a certain minimum size */ + curHeight = random() % (cellHeight - st->shadowWidth); + if (curHeight < MINRECTSIZE) + curHeight = MINRECTSIZE; + /* Generate a random width for a rectangle and make sure that + it's above a certain minimum size */ + curWidth = random() % (cellWidth - st->shadowWidth); + if (curWidth < MINRECTSIZE) + curWidth = MINRECTSIZE; + /* Figure out a random place to locate the rectangle within the + cell */ + curY = (i * cellHeight) + (random() % ((cellHeight - curHeight) - + st->shadowWidth)); + curX = (j * cellWidth) + (random() % ((cellWidth - curWidth) - + st->shadowWidth)); + + /* Draw the shadow */ + if (st->elevation > 0) + XFillRectangle(st->dpy, st->window, st->shadow_gc, + curX + st->elevation, curY + st->elevation, + curWidth, curHeight); + + /* Draw the edge */ + if (st->shadowWidth > 0) + XFillRectangle(st->dpy, st->window, st->bg_gc, + curX + st->shadowWidth, curY + st->shadowWidth, + curWidth, curHeight); + + XFillRectangle(st->dpy, st->window, st->fg_gc, curX, curY, curWidth, curHeight); + + /* Draw a 1-pixel black border around the rectangle */ + XDrawRectangle(st->dpy, st->window, st->bg_gc, curX, curY, curWidth, curHeight); + } + + } +} + + +/** + * genNewColor returns a new color, gradually mutating the colors and + * occasionally returning a totally random color, just for variety. + * + * @return the new color + **/ +static int genNewColor(struct state *st) +{ + /* These lines handle "sway", or the gradual random changing of */ + /* colors. After genNewColor() has been called a given number of */ + /* times (specified by a random permutation of the tweak variable), */ + /* take whatever color has been most recently randomly generated and */ + /* make it the new base color. */ + if (st->timeLeft == 0) { + st->timeLeft = c_tweak(st, st->sway, st->sway / 3); + st->curColor = st->curBase; + } else { + st->timeLeft--; + } + + /* If a randomly generated number is less than the threshold value, + produce a "sport" color value that is completely unrelated to the + current palette. */ + if (0 == (random() % THRESHOLD)) { + return (random() % st->ncolors); + } else { + st->curBase = genConstrainedColor(st, st->curColor, st->tweak); + return st->curBase; + } + +} + +/** + * genConstrainedColor creates a random new color within a certain + * range of an existing color. Right now this works with RGB color + * values, but a future version of the program will most likely use HSV + * colors, which should generate a more pleasing progression of values. + * + * @param base the color on which the new color will be based + * @param tweak the amount that the new color can be tweaked + * @return a new constrained color + * @see #genNewColor + **/ +static int genConstrainedColor(struct state *st, int base, int tweak) +{ + int i = 1 + (random() % st->tweak); + if (random() & 1) + i = -i; + i = (base + i) % st->ncolors; + while (i < 0) + i += st->ncolors; + return i; +} + +/** + * Utility function to generate a tweaked color value + * + * @param base the byte value on which the color is based + * @param tweak the amount the value will be skewed + * @see #tweak + * @return the tweaked byte + **/ +static int c_tweak(struct state *st, int base, int tweak) +{ + int ranTweak = (random() % (2 * tweak)); + int n = (base + (ranTweak - tweak)); + if (n < 0) n = -n; + return (n < 255 ? n : 255); +} + +static void +cynosure_reshape (Display *dpy, Window window, void *closure, + unsigned int w, unsigned int h) +{ + struct state *st = (struct state *) closure; + st->xgwa.width = w; + st->xgwa.height = h; +} + +static Bool +cynosure_event (Display *dpy, Window window, void *closure, XEvent *event) +{ + return False; +} + +static void +cynosure_free (Display *dpy, Window window, void *closure) +{ + struct state *st = (struct state *) closure; + free (st); +} + + +static const char *cynosure_defaults [] = { + ".background: black", + ".foreground: white", + "*fpsSolid: true", + "*delay: 500000", + "*colors: 128", + "*iterations: 100", + "*shadowWidth: 2", + "*elevation: 5", + "*sway: 30", + "*tweak: 20", + "*gridSize: 12", + 0 +}; + +static XrmOptionDescRec cynosure_options [] = { + { "-delay", ".delay", XrmoptionSepArg, 0 }, + { "-ncolors", ".colors", XrmoptionSepArg, 0 }, + { "-iterations", ".iterations", XrmoptionSepArg, 0 }, + { 0, 0, 0, 0 } +}; + + +XSCREENSAVER_MODULE ("Cynosure", cynosure) diff --git a/hacks/cynosure.man b/hacks/cynosure.man new file mode 100644 index 00000000..b89eb810 --- /dev/null +++ b/hacks/cynosure.man @@ -0,0 +1,64 @@ +.TH XScreenSaver 1 "" "X Version 11" +.SH NAME +cynosure - gentle overlapping squares screen saver. +.SH SYNOPSIS +.B cynosure +[\-display \fIhost:display.screen\fP] +[\-visual \fIvisual\fP] +[\-window] +[\-root] +[\-delay \fInumber\fP] +[\-ncolors \fInumber\fP] +[\-iterations \fInumber\fP] +[\-fps] +.SH DESCRIPTION +A hack similar to `greynetic', but less frenetic. The first implementation +was by Stephen Linhart; then Ozymandias G. Desiderata wrote a Java applet +clone. That clone was discovered by Jamie Zawinski, and ported to C for +inclusion here. +.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: 500000 (0.50 seconds.). +.TP 8 +.B \-ncolors \fInumber\fP +Number of Colors. Default: 128. +.TP 8 +.B \-iterations \fInumber\fP +Duration. 2 - 200. Default: 100. +.TP 8 +.B \-fps +Display the current frame rate and CPU load. +.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 2002 by Stephen Linhart, Ozymandias G. Desiderata, 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 +Stephen Linhart, Ozymandias G. Desiderata, and Jamie Zawinski. diff --git a/hacks/decayscreen.c b/hacks/decayscreen.c new file mode 100644 index 00000000..42f8149a --- /dev/null +++ b/hacks/decayscreen.c @@ -0,0 +1,380 @@ +/* xscreensaver, Copyright (c) 1992-2008 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. + */ + +/* decayscreen + * + * Based on slidescreen program from the xscreensaver application and the + * decay program for Sun framebuffers. This is the comment from the decay.c + * file: + + * decay.c + * find the screen bitmap for the console and make it "decay" by + * randomly shifting random rectangles by one pixelwidth at a time. + * + * by David Wald, 1988 + * rewritten by Natuerlich! + * based on a similar "utility" on the Apollo ring at Yale. + + * X version by + * + * Vivek Khera + * 5-AUG-1993 + * + * Hacked by jwz, 28-Nov-97 (sped up and added new motion directions) + + * R. Schultz + * Added "melt" & "stretch" modes 28-Mar-1999 + * + */ + +#include "screenhack.h" + +struct state { + Display *dpy; + Window window; + XWindowAttributes xgwa; + Pixmap saved; + int saved_w, saved_h; + + int sizex, sizey; + int delay; + int duration; + GC gc; + int mode; + int random_p; + time_t start_time; + + int fuzz_toggle; + const int *current_bias; + + async_load_state *img_loader; +}; + + +#define SHUFFLE 0 +#define UP 1 +#define LEFT 2 +#define RIGHT 3 +#define DOWN 4 +#define UPLEFT 5 +#define DOWNLEFT 6 +#define UPRIGHT 7 +#define DOWNRIGHT 8 +#define IN 9 +#define OUT 10 +#define MELT 11 +#define STRETCH 12 +#define FUZZ 13 + +static void +decayscreen_load_image (struct state *st) +{ + XWindowAttributes xgwa; + XGetWindowAttributes (st->dpy, st->window, &xgwa); + st->sizex = xgwa.width; + st->sizey = xgwa.height; + if (st->img_loader) abort(); + + st->img_loader = load_image_async_simple (0, xgwa.screen, st->window, + st->window, 0, 0); +} + +static void * +decayscreen_init (Display *dpy, Window window) +{ + struct state *st = (struct state *) calloc (1, sizeof(*st)); + XGCValues gcv; + long gcflags; + unsigned long bg; + char *s; + + st->dpy = dpy; + st->window = window; + st->random_p = 0; + + s = get_string_resource(st->dpy, "mode", "Mode"); + if (s && !strcmp(s, "shuffle")) st->mode = SHUFFLE; + else if (s && !strcmp(s, "up")) st->mode = UP; + else if (s && !strcmp(s, "left")) st->mode = LEFT; + else if (s && !strcmp(s, "right")) st->mode = RIGHT; + else if (s && !strcmp(s, "down")) st->mode = DOWN; + else if (s && !strcmp(s, "upleft")) st->mode = UPLEFT; + else if (s && !strcmp(s, "downleft")) st->mode = DOWNLEFT; + else if (s && !strcmp(s, "upright")) st->mode = UPRIGHT; + else if (s && !strcmp(s, "downright")) st->mode = DOWNRIGHT; + else if (s && !strcmp(s, "in")) st->mode = IN; + else if (s && !strcmp(s, "out")) st->mode = OUT; + else if (s && !strcmp(s, "melt")) st->mode = MELT; + else if (s && !strcmp(s, "stretch")) st->mode = STRETCH; + else if (s && !strcmp(s, "fuzz")) st->mode = FUZZ; + else { + if (s && *s && !!strcmp(s, "random")) + fprintf(stderr, "%s: unknown mode %s\n", progname, s); + st->random_p = 1; + st->mode = random() % (FUZZ+1); + } + + st->delay = get_integer_resource (st->dpy, "delay", "Integer"); + if (st->delay < 0) st->delay = 0; + + st->duration = get_integer_resource (st->dpy, "duration", "Seconds"); + if (st->duration < 1) st->duration = 1; + + XGetWindowAttributes (st->dpy, st->window, &st->xgwa); + + gcv.function = GXcopy; + gcv.subwindow_mode = IncludeInferiors; + bg = get_pixel_resource (st->dpy, st->xgwa.colormap, "background", "Background"); + gcv.foreground = bg; + + gcflags = GCForeground | GCFunction; + if (use_subwindow_mode_p(st->xgwa.screen, st->window)) /* see grabscreen.c */ + gcflags |= GCSubwindowMode; + st->gc = XCreateGC (st->dpy, st->window, gcflags, &gcv); + + st->start_time = time ((time_t) 0); + decayscreen_load_image (st); + + return st; +} + + +/* + * perform one iteration of decay + */ +static unsigned long +decayscreen_draw (Display *dpy, Window window, void *closure) +{ + struct state *st = (struct state *) closure; + int left, top, width, height, toleft, totop; + +#define L 101 +#define R 102 +#define U 103 +#define D 104 + static const int no_bias[] = { L,L,L,L, R,R,R,R, U,U,U,U, D,D,D,D }; + static const int up_bias[] = { L,L,L,L, R,R,R,R, U,U,U,U, U,U,D,D }; + static const int down_bias[] = { L,L,L,L, R,R,R,R, U,U,D,D, D,D,D,D }; + static const int left_bias[] = { L,L,L,L, L,L,R,R, U,U,U,U, D,D,D,D }; + static const int right_bias[] = { L,L,R,R, R,R,R,R, U,U,U,U, D,D,D,D }; + + static const int upleft_bias[] = { L,L,L,L, L,R,R,R, U,U,U,U, U,D,D,D }; + static const int downleft_bias[] = { L,L,L,L, L,R,R,R, U,U,U,D, D,D,D,D }; + static const int upright_bias[] = { L,L,L,R, R,R,R,R, U,U,U,U, U,D,D,D }; + static const int downright_bias[] = { L,L,L,R, R,R,R,R, U,U,U,D, D,D,D,D }; + + if (st->img_loader) /* still loading */ + { + st->img_loader = load_image_async_simple (st->img_loader, + 0, 0, 0, 0, 0); + if (! st->img_loader) { /* just finished */ + + st->start_time = time ((time_t) 0); + if (st->random_p) + st->mode = random() % (FUZZ+1); + + if (st->mode == MELT || st->mode == STRETCH) + /* make sure screen eventually turns background color */ + XDrawLine (st->dpy, st->window, st->gc, 0, 0, st->sizex, 0); + + if (!st->saved) { + st->saved = XCreatePixmap (st->dpy, st->window, + st->sizex, st->sizey, + st->xgwa.depth); + st->saved_w = st->sizex; + st->saved_h = st->sizey; + } + XCopyArea (st->dpy, st->window, st->saved, st->gc, 0, 0, + st->sizex, st->sizey, 0, 0); + } + return st->delay; + } + + if (!st->img_loader && + st->start_time + st->duration < time ((time_t) 0)) { + decayscreen_load_image (st); + } + + switch (st->mode) { + case SHUFFLE: st->current_bias = no_bias; break; + case UP: st->current_bias = up_bias; break; + case LEFT: st->current_bias = left_bias; break; + case RIGHT: st->current_bias = right_bias; break; + case DOWN: st->current_bias = down_bias; break; + case UPLEFT: st->current_bias = upleft_bias; break; + case DOWNLEFT: st->current_bias = downleft_bias; break; + case UPRIGHT: st->current_bias = upright_bias; break; + case DOWNRIGHT: st->current_bias = downright_bias; break; + case IN: st->current_bias = no_bias; break; + case OUT: st->current_bias = no_bias; break; + case MELT: st->current_bias = no_bias; break; + case STRETCH: st->current_bias = no_bias; break; + case FUZZ: st->current_bias = no_bias; break; + default: abort(); + } + +#define nrnd(x) ((x) ? random() % (x) : x) + + if (st->mode == MELT || st->mode == STRETCH) { + left = nrnd(st->sizex/2); + top = nrnd(st->sizey); + width = nrnd( st->sizex/2 ) + st->sizex/2 - left; + height = nrnd(st->sizey - top); + toleft = left; + totop = top+1; + + } else if (st->mode == FUZZ) { /* By Vince Levey ; + inspired by the "melt" mode of the + "scrhack" IrisGL program by Paul Haeberli + circa 1991. */ + left = nrnd(st->sizex - 1); + top = nrnd(st->sizey - 1); + st->fuzz_toggle = !st->fuzz_toggle; + if (st->fuzz_toggle) + { + totop = top; + height = 1; + toleft = nrnd(st->sizex - 1); + if (toleft > left) + { + width = toleft-left; + toleft = left; + left++; + } + else + { + width = left-toleft; + left = toleft; + toleft++; + } + } + else + { + toleft = left; + width = 1; + totop = nrnd(st->sizey - 1); + if (totop > top) + { + height = totop-top; + totop = top; + top++; + } + else + { + height = top-totop; + top = totop; + totop++; + } + } + + } else { + + left = nrnd(st->sizex - 1); + top = nrnd(st->sizey); + width = nrnd(st->sizex - left); + height = nrnd(st->sizey - top); + + toleft = left; + totop = top; + if (st->mode == IN || st->mode == OUT) { + int x = left+(width/2); + int y = top+(height/2); + int cx = st->sizex/2; + int cy = st->sizey/2; + if (st->mode == IN) { + if (x > cx && y > cy) st->current_bias = upleft_bias; + else if (x < cx && y > cy) st->current_bias = upright_bias; + else if (x < cx && y < cy) st->current_bias = downright_bias; + else /* (x > cx && y < cy)*/ st->current_bias = downleft_bias; + } else { + if (x > cx && y > cy) st->current_bias = downright_bias; + else if (x < cx && y > cy) st->current_bias = downleft_bias; + else if (x < cx && y < cy) st->current_bias = upleft_bias; + else /* (x > cx && y < cy)*/ st->current_bias = upright_bias; + } + } + + switch (st->current_bias[random() % (sizeof(no_bias)/sizeof(*no_bias))]) { + case L: toleft = left-1; break; + case R: toleft = left+1; break; + case U: totop = top-1; break; + case D: totop = top+1; break; + default: abort(); break; + } + } + + if (st->mode == STRETCH) { + XCopyArea (st->dpy, st->window, st->window, st->gc, 0, st->sizey-top-2, st->sizex, top+1, + 0, st->sizey-top-1); + } else { + XCopyArea (st->dpy, st->window, st->window, st->gc, left, top, width, height, + toleft, totop); + } + +#undef nrnd + + return st->delay; +} + +static void +decayscreen_reshape (Display *dpy, Window window, void *closure, + unsigned int w, unsigned int h) +{ + struct state *st = (struct state *) closure; + XClearWindow (st->dpy, st->window); + XCopyArea (st->dpy, st->saved, st->window, st->gc, + 0, 0, st->saved_w, st->saved_h, + (w - st->saved_w) / 2, + (h - st->saved_h) / 2); + st->sizex = w; + st->sizey = h; +} + +static Bool +decayscreen_event (Display *dpy, Window window, void *closure, XEvent *event) +{ + return False; +} + +static void +decayscreen_free (Display *dpy, Window window, void *closure) +{ + struct state *st = (struct state *) closure; + free (st); +} + + + +static const char *decayscreen_defaults [] = { + ".background: Black", + ".foreground: Yellow", + "*dontClearRoot: True", + "*fpsSolid: True", + +#ifdef __sgi /* really, HAVE_READ_DISPLAY_EXTENSION */ + "*visualID: Best", +#endif + + "*delay: 10000", + "*mode: random", + "*duration: 120", + 0 +}; + +static XrmOptionDescRec decayscreen_options [] = { + { "-delay", ".delay", XrmoptionSepArg, 0 }, + { "-mode", ".mode", XrmoptionSepArg, 0 }, + { "-duration", ".duration", XrmoptionSepArg, 0 }, + { 0, 0, 0, 0 } +}; + + +XSCREENSAVER_MODULE ("DecayScreen", decayscreen) diff --git a/hacks/decayscreen.man b/hacks/decayscreen.man new file mode 100644 index 00000000..7b0f8161 --- /dev/null +++ b/hacks/decayscreen.man @@ -0,0 +1,92 @@ +.TH XScreenSaver 1 "05-Apr-1999" "X Version 11" +.SH NAME +decayscreen - make a screen meltdown. +.SH SYNOPSIS +.B decayscreen +[\-display \fIhost:display.screen\fP] +[\-window] +[\-root] +[\-mono] +[\-install] +[\-visual \fIvisual\fP] +[\-delay \fIusecs\fP] +[\-duration \fIsecs\fP] +[\-mode \fImode\fP] +[\-fps] +.SH DESCRIPTION +The \fIdecayscreen\fP program creates a melting effect by randomly +shifting rectangles around the screen. + +The image that it manipulates will be grabbed from the portion of +the screen underlying the window, or from the system's video input, +or from a random file on disk, as indicated by +the \fIgrabDesktopImages\fP, \fIgrabVideoFrames\fP, +and \fIchooseRandomImages\fP options in the \fI~/.xscreensaver\fP +file; see +.BR xscreensaver-demo (1) +for more details. +.SH OPTIONS +.I decayscreen +accepts the following options: +.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 \-mono +If on a color display, pretend we're on a monochrome display. +.TP 8 +.B \-install +Install a private colormap for the window. +.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 \-delay \fImicroseconds\fP +Slow it down. +.TP 8 +.B \-duration \fIseconds\fP +How long to run before loading a new image. Default 120 seconds. +.TP 8 +.B \-mode \fImode\fP +The direction in which the image should tend to slide. Legal values are +\fIrandom\fP (meaning pick one), \fIup\fP, \fIleft\fP, \fIright\fP, +\fIdown\fP, \fIupleft\fP, \fIdownleft\fP, \fIupright\fP, \fIdownright\fP, +\fIshuffle\fP (meaning prefer no particular direction), \fIin\fP (meaning +move things toward the center), \fIout\fP (meaning move things away +from the center), \fImelt\fP (meaning melt straight +downward), \fIstretch\fP (meaning stretch the screen downward), +and \fIfuzz\fP (meaning go blurry instead of melty). +.TP 8 +.B \-fps +Display the current frame rate and CPU load. +.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), +.BR xscreensaver\-demo (1), +.BR xscreensaver\-getimage (1) +.SH COPYRIGHT +Copyright 1992 by Vivek Khera. 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 +Vivek Khera , 05-Aug-93; based on code by David Wald, 1988. +Modified by jwz, 28-Nov-1997. +Modified by Rick Schultz 05-Apr-1999. +Modified by Vince Levey 25-Oct-2001. diff --git a/hacks/deco.c b/hacks/deco.c new file mode 100644 index 00000000..69085525 --- /dev/null +++ b/hacks/deco.c @@ -0,0 +1,333 @@ +/* xscreensaver, Copyright (c) 1997, 1998, 2002, 2006 + * 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. + * + * Concept snarfed from Michael D. Bayne in + * http://www.go2net.com/internet/deep/1997/04/16/body.html + * + * Changes by Lars Huttar, http://www.huttar.net: + * - allow use of golden ratio for dividing rectangles instead of 1/2. + * - allow smooth colors instead of random + * - added line thickness setting + * - added "Mondrian" mode + * Other ideas: + * - allow recomputing the colormap on each new frame (especially useful + * when ncolors is low) + */ + +#include "screenhack.h" +#include + +struct state { + XColor colors[255]; + int ncolors; + int max_depth; + int min_height; + int min_width; + int line_width; + int old_line_width; + Bool goldenRatio; + Bool mondrian; + Bool smoothColors; + + int delay; + XWindowAttributes xgwa; + GC fgc, bgc; + int current_color; +}; + +/* Golden Ratio + * Suppose you're dividing a rectangle of length A+B + * into two parts, of length A and B respectively. You want the ratio of + * A to B to be the same as the ratio of the whole (A+B) to A. The golden + * ratio (phi) is that ratio. Supposed to be visually pleasing. */ +#define PHI 1.61803 +#define PHI1 (1.0/PHI) +#define PHI2 (1.0 - PHI1) + +/* copied from make_random_colormap in colors.c */ +static void +make_mondrian_colormap (Display *dpy, Visual *visual, Colormap cmap, + XColor *colors, int *ncolorsP, + Bool allocate_p, + Bool *writable_pP, + Bool verbose_p) +{ + Bool wanted_writable = (allocate_p && writable_pP && *writable_pP); + int ncolors = 8; + int i; + Screen *screen = (dpy ? DefaultScreenOfDisplay(dpy) : 0); /* #### WRONG! */ + + if (*ncolorsP <= 0) return; + + /* If this visual doesn't support writable cells, don't bother trying. */ + if (wanted_writable && !has_writable_cells(screen, visual)) + *writable_pP = False; + + for (i = 0; i < ncolors; i++) + { + colors[i].flags = DoRed|DoGreen|DoBlue; + colors[i].red = 0; + colors[i].green = 0; + colors[i].blue = 0; + + switch(i) { + case 0: case 1: case 2: case 3: case 7: /* white */ + colors[i].red = 0xE800; + colors[i].green = 0xE800; + colors[i].blue = 0xE800; + break; + case 4: + colors[i].red = 0xCFFF; break; /* red */ + case 5: + colors[i].red = 0x2000; + colors[i].blue = 0xCFFF; break; /* blue */ + case 6: + colors[i].red = 0xDFFF; /* yellow */ + colors[i].green = 0xCFFF; break; + } + } + + if (!allocate_p) + return; + + RETRY_NON_WRITABLE: + if (writable_pP && *writable_pP) + { + unsigned long *pixels = (unsigned long *) + malloc(sizeof(*pixels) * (ncolors + 1)); + + allocate_writable_colors (dpy, cmap, pixels, &ncolors); + if (ncolors > 0) + for (i = 0; i < ncolors; i++) + colors[i].pixel = pixels[i]; + free (pixels); + if (ncolors > 0) + XStoreColors (dpy, cmap, colors, ncolors); + } + else + { + for (i = 0; i < ncolors; i++) + { + XColor color; + color = colors[i]; + if (!XAllocColor (dpy, cmap, &color)) + break; + colors[i].pixel = color.pixel; + } + ncolors = i; + } + + /* If we tried for writable cells and got none, try for non-writable. */ + if (allocate_p && ncolors == 0 && writable_pP && *writable_pP) + { + ncolors = *ncolorsP; + *writable_pP = False; + goto RETRY_NON_WRITABLE; + } + +#if 0 + /* I don't think we need to bother copying or linking to the complain + function. */ + if (verbose_p) + complain(*ncolorsP, ncolors, wanted_writable, + wanted_writable && *writable_pP); +#endif + + *ncolorsP = ncolors; +} + +static void +mondrian_set_sizes (struct state *st, int w, int h) +{ + if (w > h) { + st->line_width = w/50; + st->min_height = st->min_width = w/8; + } else { + st->line_width = h/50; + st->min_height = st->min_width = h/8; + } +} + +static void +deco (Display *dpy, Window window, struct state *st, + int x, int y, int w, int h, int depth) +{ + if (((random() % st->max_depth) < depth) || (w < st->min_width) || (h < st->min_height)) + { + if (!mono_p) + { + if (++st->current_color >= st->ncolors) + st->current_color = 0; + XSetForeground(dpy, st->bgc, st->colors[st->current_color].pixel); + } + XFillRectangle (dpy, window, st->bgc, x, y, w, h); + XDrawRectangle (dpy, window, st->fgc, x, y, w, h); + } + else + { + if ((st->goldenRatio || st->mondrian) ? (w > h) : (random() & 1)) + { /* Divide the rectangle side-by-side */ + int wnew = (st->goldenRatio ? (w * (random() & 1 ? PHI1 : PHI2)) : w/2); + deco (dpy, window, st, x, y, wnew, h, depth+1); + deco (dpy, window, st, x+wnew, y, w-wnew, h, depth+1); + } + else + { /* Divide the rectangle top-to-bottom */ + int hnew = (st->goldenRatio ? (h * (random() & 1 ? PHI1 : PHI2)) : h/2); + deco (dpy, window, st, x, y, w, hnew, depth+1); + deco (dpy, window, st, x, y+hnew, w, h-hnew, depth+1); + } + } +} + +static void * +deco_init (Display *dpy, Window window) +{ + struct state *st = (struct state *) calloc (1, sizeof(*st)); + XGCValues gcv; + + st->delay = get_integer_resource (dpy, "delay", "Integer"); + + st->smoothColors = get_boolean_resource(dpy, "smoothColors", "Boolean"); + st->old_line_width = 1; + + st->goldenRatio = get_boolean_resource (dpy, "goldenRatio", "Boolean"); + + st->max_depth = get_integer_resource (dpy, "maxDepth", "Integer"); + if (st->max_depth < 1) st->max_depth = 1; + else if (st->max_depth > 1000) st->max_depth = 1000; + + st->min_width = get_integer_resource (dpy, "minWidth", "Integer"); + if (st->min_width < 2) st->min_width = 2; + st->min_height = get_integer_resource (dpy, "minHeight", "Integer"); + if (st->min_height < 2) st->min_height = 2; + + st->line_width = get_integer_resource (dpy, "lineWidth", "Integer"); + + XGetWindowAttributes (dpy, window, &st->xgwa); + + st->ncolors = get_integer_resource (dpy, "ncolors", "Integer"); + + gcv.foreground = get_pixel_resource(dpy, st->xgwa.colormap, + "foreground", "Foreground"); + st->fgc = XCreateGC (dpy, window, GCForeground, &gcv); + + gcv.foreground = get_pixel_resource(dpy, st->xgwa.colormap, + "background", "Background"); + st->bgc = XCreateGC (dpy, window, GCForeground, &gcv); + + if (st->ncolors <= 2) + mono_p = True; + + if (!mono_p) + { + GC tmp = st->fgc; + st->fgc = st->bgc; + st->bgc = tmp; + } + + st->mondrian = get_boolean_resource(dpy, "mondrian", "Boolean"); + if (st->mondrian) { + /* Mondrian, if true, overrides several other options. */ + mondrian_set_sizes(st, st->xgwa.width, st->xgwa.height); + + /** set up red-yellow-blue-black-white colormap and fgc **/ + make_mondrian_colormap(dpy, st->xgwa.visual, st->xgwa.colormap, + st->colors, &st->ncolors, True, 0, True); + + /** put white in several cells **/ + /** set min-height and min-width to about 10% of total w/h **/ + } + else if (st->smoothColors) + make_smooth_colormap (dpy, st->xgwa.visual, st->xgwa.colormap, + st->colors, &st->ncolors, True, 0, True); + else + make_random_colormap (dpy, st->xgwa.visual, st->xgwa.colormap, + st->colors, &st->ncolors, False, True, 0, True); + + gcv.line_width = st->old_line_width = st->line_width; + XChangeGC(dpy, st->fgc, GCLineWidth, &gcv); + + return st; +} + +static unsigned long +deco_draw (Display *dpy, Window window, void *closure) +{ + struct state *st = (struct state *) closure; + XFillRectangle (dpy, window, st->bgc, 0, 0, st->xgwa.width, st->xgwa.height); + if (st->mondrian) { + mondrian_set_sizes(st, st->xgwa.width, st->xgwa.height); + if (st->line_width != st->old_line_width) { + XSetLineAttributes(dpy, st->fgc, st->line_width, + LineSolid, CapButt, JoinBevel); + st->old_line_width = st->line_width; + } + } + deco (dpy, window, st, 0, 0, st->xgwa.width, st->xgwa.height, 0); + return 1000000 * st->delay; +} + +static void +deco_reshape (Display *dpy, Window window, void *closure, + unsigned int w, unsigned int h) +{ + struct state *st = (struct state *) closure; + st->xgwa.width = w; + st->xgwa.height = h; +} + +static Bool +deco_event (Display *dpy, Window window, void *closure, XEvent *event) +{ + return False; +} + +static void +deco_free (Display *dpy, Window window, void *closure) +{ + struct state *st = (struct state *) closure; + free (st); +} + + +static const char *deco_defaults [] = { + ".background: black", + ".foreground: white", + "*maxDepth: 12", + "*minWidth: 20", + "*minHeight: 20", + "*lineWidth: 1", + "*delay: 5", + "*ncolors: 64", + "*goldenRatio: False", + "*smoothColors: False", + "*mondrian: False", + 0 +}; + +static XrmOptionDescRec deco_options [] = { + { "-max-depth", ".maxDepth", XrmoptionSepArg, 0 }, + { "-min-width", ".minWidth", XrmoptionSepArg, 0 }, + { "-min-height", ".minHeight", XrmoptionSepArg, 0 }, + { "-line-width", ".lineWidth", XrmoptionSepArg, 0 }, + { "-delay", ".delay", XrmoptionSepArg, 0 }, + { "-ncolors", ".ncolors", XrmoptionSepArg, 0 }, + { "-golden-ratio", ".goldenRatio", XrmoptionNoArg, "True" }, + { "-no-golden-ratio", ".goldenRatio", XrmoptionNoArg, "False" }, + { "-smooth-colors", ".smoothColors",XrmoptionNoArg, "True" }, + { "-no-smooth-colors",".smoothColors",XrmoptionNoArg, "False" }, + { "-mondrian", ".mondrian", XrmoptionNoArg, "True" }, + { "-no-mondrian", ".mondrian", XrmoptionNoArg, "False" }, + { 0, 0, 0, 0 } +}; + +XSCREENSAVER_MODULE ("Deco", deco) diff --git a/hacks/deco.man b/hacks/deco.man new file mode 100644 index 00000000..e62190c9 --- /dev/null +++ b/hacks/deco.man @@ -0,0 +1,105 @@ +.TH XScreenSaver 1 "27-Apr-97" "X Version 11" +.SH NAME +deco - draw tacky 70s basement wall panelling +.SH SYNOPSIS +.B deco +[\-display \fIhost:display.screen\fP] +[\-foreground \fIcolor\fP] +[\-background \fIcolor\fP] +[\-window] +[\-root] +[\-mono] +[\-install] +[\-visual \fIvisual\fP] +[\-delay \fIseconds\fP] +[\-max\-depth \fIint\fP] +[\-min\-width \fIint\fP] +[\-min\-height \fIint\fP] +[\-line-width \yIint\fP] +[\-smooth\-colors] +[\-golden\-ratio] +[\-mondrian] +[\-fps] +.SH DESCRIPTION +The \fIdeco\fP program subdivides and colors rectangles randomly. +It looks kind of like Brady-Bunch-era rec-room wall paneling. +(Raven says: "This screensaver is ugly enough to peel paint.") +Can also produce more aesthetically pleasing displays via options. +.SH OPTIONS +.I deco +accepts the following options: +.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 \-mono +If on a color display, pretend we're on a monochrome display. +.TP 8 +.B \-install +Install a private colormap for the window. +.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 \-delay \fIseconds\fP +How long to wait before starting over. Default 5 seconds. +.TP 8 +.B \-max\-depth \fIinteger\fP +How deep to subdivide. Default 12. +.TP 8 +.B \-min\-width \fIinteger\fP +.TP 8 +.B \-min\-height \fIinteger\fP +The size of the smallest rectangle to draw. Default 20x20. +.TP 8 +.B \-line\-width \fIinteger\fP +Width of lines drawn between rectangles. Default zero (minimal width). +.TP 8 +.B \-smooth\-colors +.TP 8 +.B \-no\-smooth\-colors +Whether to use a smooth color palette instead of a random one. +Less jarring. Default False. +.TP 8 +.B \-golden\-ratio +.TP 8 +.B \-no\-golden\-ratio +Whether to subdivide rectangles using the golden ratio instead of 1/2. +This ratio is supposed to be more aesthetically pleasing. Default false. +.TP 8 +.B \-mondrian +.TP 8 +.B \-no\-mondrian +Whether to imitiate style of some famous paintings by Piet Mondrian. +Overrides line-width and colormap options. Default false. +.TP 8 +.B \-fps +Display the current frame rate and CPU load. +.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 1997 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 , 26-Apr-97, based on code by +Michael D. Bayne . Golden ratio and +Mondrian settings by Lars Huttar. diff --git a/hacks/deluxe.c b/hacks/deluxe.c new file mode 100644 index 00000000..27ba0484 --- /dev/null +++ b/hacks/deluxe.c @@ -0,0 +1,453 @@ +/* xscreensaver, Copyright (c) 1999-2012 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. + */ + +#include +#include "screenhack.h" +#include "alpha.h" + +#ifdef HAVE_DOUBLE_BUFFER_EXTENSION +# include "xdbe.h" +#endif /* HAVE_DOUBLE_BUFFER_EXTENSION */ + +#define countof(x) (sizeof(x)/sizeof(*(x))) +#define ABS(x) ((x)<0?-(x):(x)) + +struct state { + Display *dpy; + Window window; + + Bool transparent_p; + int nplanes; + unsigned long base_pixel, *plane_masks; + + int count; + int delay; + int ncolors; + Bool dbuf; + XColor *colors; + GC erase_gc; + struct throbber **throbbers; + XWindowAttributes xgwa; + Pixmap b, ba, bb; /* double-buffer to reduce flicker */ + +# ifdef HAVE_DOUBLE_BUFFER_EXTENSION + Bool dbeclear_p; + XdbeBackBuffer backb; +# endif /* HAVE_DOUBLE_BUFFER_EXTENSION */ +}; + +struct throbber { + int x, y; + int size; + int max_size; + int thickness; + int speed; + int fuse; + GC gc; + void (*draw) (struct state *, Drawable, struct throbber *); +}; + + +static void +draw_star (struct state *st, Drawable w, struct throbber *t) +{ + XPoint points[11]; + int x = t->x; + int y = t->y; + int s = t->size / 0.383; /* trial and error, I forget how to derive this */ + int s2 = t->size; + double c = M_PI * 2; + double o = -M_PI / 2; + + points[0].x = x + s * cos(o + 0.0*c); points[0].y = y + s * sin(o + 0.0*c); + points[1].x = x + s2 * cos(o + 0.1*c); points[1].y = y + s2 * sin(o + 0.1*c); + points[2].x = x + s * cos(o + 0.2*c); points[2].y = y + s * sin(o + 0.2*c); + points[3].x = x + s2 * cos(o + 0.3*c); points[3].y = y + s2 * sin(o + 0.3*c); + points[4].x = x + s * cos(o + 0.4*c); points[4].y = y + s * sin(o + 0.4*c); + points[5].x = x + s2 * cos(o + 0.5*c); points[5].y = y + s2 * sin(o + 0.5*c); + points[6].x = x + s * cos(o + 0.6*c); points[6].y = y + s * sin(o + 0.6*c); + points[7].x = x + s2 * cos(o + 0.7*c); points[7].y = y + s2 * sin(o + 0.7*c); + points[8].x = x + s * cos(o + 0.8*c); points[8].y = y + s * sin(o + 0.8*c); + points[9].x = x + s2 * cos(o + 0.9*c); points[9].y = y + s2 * sin(o + 0.9*c); + points[10] = points[0]; + + XDrawLines (st->dpy, w, t->gc, points, countof(points), CoordModeOrigin); +} + +static void +draw_circle (struct state *st, Drawable w, struct throbber *t) +{ + XDrawArc (st->dpy, w, t->gc, + t->x - t->size / 2, + t->y - t->size / 2, + t->size, t->size, + 0, 360*64); +} + +static void +draw_hlines (struct state *st, Drawable w, struct throbber *t) +{ + XDrawLine (st->dpy, w, t->gc, 0, + t->y - t->size, t->max_size, + t->y - t->size); + XDrawLine (st->dpy, w, t->gc, 0, + t->y + t->size, t->max_size, + t->y + t->size); +} + +static void +draw_vlines (struct state *st, Drawable w, struct throbber *t) +{ + XDrawLine (st->dpy, w, t->gc, + t->x - t->size, 0, + t->x - t->size, t->max_size); + XDrawLine (st->dpy, w, t->gc, + t->x + t->size, 0, + t->x + t->size, t->max_size); +} + +static void +draw_corners (struct state *st, Drawable w, struct throbber *t) +{ + int s = (t->size + t->thickness) / 2; + XPoint points[3]; + + if (t->y > s) + { + points[0].x = 0; points[0].y = t->y - s; + points[1].x = t->x - s; points[1].y = t->y - s; + points[2].x = t->x - s; points[2].y = 0; + XDrawLines (st->dpy, w, t->gc, points, countof(points), CoordModeOrigin); + + points[0].x = t->x + s; points[0].y = 0; + points[1].x = t->x + s; points[1].y = t->y - s; + points[2].x = t->max_size; points[2].y = t->y - s; + XDrawLines (st->dpy, w, t->gc, points, countof(points), CoordModeOrigin); + } + + if (t->x > s) + { + points[0].x = 0; points[0].y = t->y + s; + points[1].x = t->x - s; points[1].y = t->y + s; + points[2].x = t->x - s; points[2].y = t->max_size; + XDrawLines (st->dpy, w, t->gc, points, countof(points), CoordModeOrigin); + + points[0].x = t->x + s; points[0].y = t->max_size; + points[1].x = t->x + s; points[1].y = t->y + s; + points[2].x = t->max_size; points[2].y = t->y + s; + XDrawLines (st->dpy, w, t->gc, points, countof(points), CoordModeOrigin); + } +} + + +static struct throbber * +make_throbber (struct state *st, Drawable d, int w, int h, unsigned long pixel) +{ + XGCValues gcv; + unsigned long flags; + struct throbber *t = (struct throbber *) malloc (sizeof (*t)); + t->x = w / 2; + t->y = h / 2; + t->max_size = (w > h ? w : h); + t->speed = get_integer_resource (st->dpy, "speed", "Speed"); + t->fuse = 1 + (random() % 4); + t->thickness = get_integer_resource (st->dpy, "thickness", "Thickness"); + + if (t->speed < 0) t->speed = -t->speed; + t->speed += (((random() % t->speed) / 2) - (t->speed / 2)); + if (t->speed > 0) t->speed = -t->speed; + + flags = GCForeground; +# ifndef HAVE_COCOA + if (st->transparent_p) + { + gcv.foreground = ~0L; + gcv.plane_mask = st->base_pixel | st->plane_masks[random() % st->nplanes]; + flags |= GCPlaneMask; + } + else +# endif /* !HAVE_COCOA */ + { + gcv.foreground = pixel; + } + + gcv.line_width = t->thickness; + gcv.cap_style = CapProjecting; + gcv.join_style = JoinMiter; + + flags |= (GCLineWidth | GCCapStyle | GCJoinStyle); + t->gc = XCreateGC (st->dpy, d, flags, &gcv); + +# ifdef HAVE_COCOA + if (st->transparent_p) + { + /* give a non-opaque alpha to the color */ + unsigned long pixel = gcv.foreground; + unsigned long amask = BlackPixelOfScreen (st->xgwa.screen); + unsigned long a = (0xCCCCCCCC & amask); + pixel = (pixel & (~amask)) | a; + + jwxyz_XSetAlphaAllowed (st->dpy, t->gc, True); + XSetForeground (st->dpy, t->gc, pixel); + } +# endif /* HAVE_COCOA */ + + switch (random() % 11) { + case 0: case 1: case 2: case 3: t->draw = draw_star; break; + case 4: case 5: case 6: case 7: t->draw = draw_circle; break; + case 8: t->draw = draw_hlines; break; + case 9: t->draw = draw_vlines; break; + case 10: t->draw = draw_corners; break; + default: abort(); break; + } + + if (t->draw == draw_circle) + t->max_size *= 1.5; + + if (random() % 4) + t->size = t->max_size; + else + t->size = t->thickness, t->speed = -t->speed; + + return t; +} + +static int +throb (struct state *st, Drawable window, struct throbber *t) +{ + t->size += t->speed; + if (t->size <= (t->thickness / 2)) + { + t->speed = -t->speed; + t->size += (t->speed * 2); + } + else if (t->size > t->max_size) + { + t->speed = -t->speed; + t->size += (t->speed * 2); + t->fuse--; + } + + if (t->fuse <= 0) + { + XFreeGC (st->dpy, t->gc); + memset (t, 0, sizeof(*t)); + free (t); + return -1; + } + else + { + t->draw (st, window, t); + return 0; + } +} + + +static void * +deluxe_init (Display *dpy, Window window) +{ + struct state *st = (struct state *) calloc (1, sizeof(*st)); + XGCValues gcv; + int i; + st->dpy = dpy; + st->window = window; + st->count = get_integer_resource (st->dpy, "count", "Integer"); + st->delay = get_integer_resource (st->dpy, "delay", "Integer"); + st->ncolors = get_integer_resource (st->dpy, "ncolors", "Integer"); + st->dbuf = get_boolean_resource (st->dpy, "doubleBuffer", "Boolean"); + +# ifdef HAVE_DOUBLE_BUFFER_EXTENSION + st->dbeclear_p = get_boolean_resource (st->dpy, "useDBEClear", "Boolean"); +#endif + +# ifdef HAVE_COCOA /* Don't second-guess Quartz's double-buffering */ + st->dbuf = False; +# endif + + XGetWindowAttributes (st->dpy, st->window, &st->xgwa); + + st->transparent_p = get_boolean_resource(st->dpy, "transparent", "Transparent"); + + st->colors = (XColor *) calloc (sizeof(*st->colors), st->ncolors); + + if (get_boolean_resource(st->dpy, "mono", "Boolean")) + { + MONO: + st->ncolors = 1; + st->colors[0].pixel = get_pixel_resource(st->dpy, st->xgwa.colormap, + "foreground", "Foreground"); + } +#ifndef HAVE_COCOA + else if (st->transparent_p) + { + st->nplanes = get_integer_resource (st->dpy, "planes", "Planes"); + if (st->nplanes <= 0) + st->nplanes = (random() % (st->xgwa.depth-2)) + 2; + + allocate_alpha_colors (st->xgwa.screen, st->xgwa.visual, st->xgwa.colormap, + &st->nplanes, True, &st->plane_masks, + &st->base_pixel); + if (st->nplanes <= 1) + { +# if 0 + fprintf (stderr, + "%s: couldn't allocate any color planes; turning transparency off.\n", + progname); +# endif + st->transparent_p = False; + goto COLOR; + } + } +#endif /* !HAVE_COCOA */ + else + { +#ifndef HAVE_COCOA + COLOR: +#endif + make_random_colormap (st->dpy, st->xgwa.visual, st->xgwa.colormap, + st->colors, &st->ncolors, True, True, 0, True); + if (st->ncolors < 2) + goto MONO; + } + + if (st->dbuf) + { +#ifdef HAVE_DOUBLE_BUFFER_EXTENSION + if (st->dbeclear_p) + st->b = xdbe_get_backbuffer (st->dpy, st->window, XdbeBackground); + else + st->b = xdbe_get_backbuffer (st->dpy, st->window, XdbeUndefined); + st->backb = st->b; +#endif /* HAVE_DOUBLE_BUFFER_EXTENSION */ + + if (!st->b) + { + st->ba = XCreatePixmap (st->dpy, st->window, st->xgwa.width, st->xgwa.height,st->xgwa.depth); + st->bb = XCreatePixmap (st->dpy, st->window, st->xgwa.width, st->xgwa.height,st->xgwa.depth); + st->b = st->ba; + } + } + else + { + st->b = st->window; + } + + st->throbbers = (struct throbber **) calloc (st->count, sizeof(struct throbber *)); + for (i = 0; i < st->count; i++) + st->throbbers[i] = make_throbber (st, st->b, st->xgwa.width, st->xgwa.height, + st->colors[random() % st->ncolors].pixel); + + gcv.foreground = get_pixel_resource (st->dpy, st->xgwa.colormap, + "background", "Background"); + st->erase_gc = XCreateGC (st->dpy, st->b, GCForeground, &gcv); + + if (st->ba) XFillRectangle (st->dpy, st->ba, st->erase_gc, 0, 0, st->xgwa.width, st->xgwa.height); + if (st->bb) XFillRectangle (st->dpy, st->bb, st->erase_gc, 0, 0, st->xgwa.width, st->xgwa.height); + + return st; +} + +static unsigned long +deluxe_draw (Display *dpy, Window window, void *closure) +{ + struct state *st = (struct state *) closure; + int i; +#ifdef HAVE_DOUBLE_BUFFER_EXTENSION + if (!st->dbeclear_p || !st->backb) +#endif /* HAVE_DOUBLE_BUFFER_EXTENSION */ + XFillRectangle (st->dpy, st->b, st->erase_gc, 0, 0, st->xgwa.width, st->xgwa.height); + + for (i = 0; i < st->count; i++) + if (throb (st, st->b, st->throbbers[i]) < 0) + st->throbbers[i] = make_throbber (st, st->b, st->xgwa.width, st->xgwa.height, + st->colors[random() % st->ncolors].pixel); + +#ifdef HAVE_DOUBLE_BUFFER_EXTENSION + if (st->backb) + { + XdbeSwapInfo info[1]; + info[0].swap_window = st->window; + info[0].swap_action = (st->dbeclear_p ? XdbeBackground : XdbeUndefined); + XdbeSwapBuffers (st->dpy, info, 1); + } + else +#endif /* HAVE_DOUBLE_BUFFER_EXTENSION */ + if (st->dbuf) + { + XCopyArea (st->dpy, st->b, st->window, st->erase_gc, 0, 0, + st->xgwa.width, st->xgwa.height, 0, 0); + st->b = (st->b == st->ba ? st->bb : st->ba); + } + + return st->delay; +} + +static void +deluxe_reshape (Display *dpy, Window window, void *closure, + unsigned int w, unsigned int h) +{ + struct state *st = (struct state *) closure; + if (! st->dbuf) { /* #### more complicated if we have a back buffer... */ + int i; + XGetWindowAttributes (st->dpy, st->window, &st->xgwa); + XClearWindow (dpy, window); + for (i = 0; i < st->count; i++) + if (st->throbbers[i]) + st->throbbers[i]->fuse = 0; + } +} + +static Bool +deluxe_event (Display *dpy, Window window, void *closure, XEvent *event) +{ + return False; +} + +static void +deluxe_free (Display *dpy, Window window, void *closure) +{ +} + + +static const char *deluxe_defaults [] = { + ".background: black", + ".foreground: white", + "*delay: 10000", + "*count: 5", + "*thickness: 50", + "*speed: 15", + "*ncolors: 20", + "*transparent: True", + "*doubleBuffer: True", +#ifdef HAVE_DOUBLE_BUFFER_EXTENSION + "*useDBE: True", + "*useDBEClear: True", +#endif /* HAVE_DOUBLE_BUFFER_EXTENSION */ + 0 +}; + +static XrmOptionDescRec deluxe_options [] = { + { "-delay", ".delay", XrmoptionSepArg, 0 }, + { "-thickness", ".thickness", XrmoptionSepArg, 0 }, + { "-count", ".count", XrmoptionSepArg, 0 }, + { "-ncolors", ".ncolors", XrmoptionSepArg, 0 }, + { "-speed", ".speed", XrmoptionSepArg, 0 }, + { "-transparent", ".transparent", XrmoptionNoArg, "True" }, + { "-no-transparent", ".transparent", XrmoptionNoArg, "False" }, + { "-opaque", ".transparent", XrmoptionNoArg, "False" }, + { "-no-opaque", ".transparent", XrmoptionNoArg, "True" }, + { "-db", ".doubleBuffer", XrmoptionNoArg, "True" }, + { "-no-db", ".doubleBuffer", XrmoptionNoArg, "False" }, + { 0, 0, 0, 0 } +}; + + +XSCREENSAVER_MODULE ("Deluxe", deluxe) diff --git a/hacks/deluxe.man b/hacks/deluxe.man new file mode 100644 index 00000000..380e7e5a --- /dev/null +++ b/hacks/deluxe.man @@ -0,0 +1,72 @@ +.TH XScreenSaver 1 "" "X Version 11" +.SH NAME +deluxe - pulsing sequence of stars, circles, and lines. +.SH SYNOPSIS +.B deluxe +[\-display \fIhost:display.screen\fP] +[\-visual \fIvisual\fP] +[\-window] +[\-root] +[\-delay \fInumber\fP] +[\-thickness \fInumber\fP] +[\-count \fInumber\fP] +[\-ncolors \fInumber\fP] +[\-transparent] +[\-no-db] +[\-fps] +.SH DESCRIPTION +This draws a pulsing sequence of stars, circles, and lines. +.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: 5000 (0.01 seconds.). +.TP 8 +.B \-thickness \fInumber\fP +Thickness of lines. Default: 50. +.TP 8 +.B \-count \fInumber\fP +Number of objects. Default: 5. +.TP 8 +.B \-ncolors \fInumber\fP +Number of colors. Default: 20. +.TP 8 +.B \-transparent | \-no-transparent +Whether to use transparency. +.TP 8 +.B \-db | \-no-db +Whether to double buffer. +.TP 8 +.B \-fps +Display the current frame rate and CPU load. +.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 2002 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/demon.c b/hacks/demon.c new file mode 100644 index 00000000..c9a15e25 --- /dev/null +++ b/hacks/demon.c @@ -0,0 +1,988 @@ +/* -*- Mode: C; tab-width: 4 -*- */ +/* demon --- David Griffeath's cellular automata */ + +#if 0 +static const char sccsid[] = "@(#)demon.c 5.00 2000/11/01 xlockmore"; +#endif + +/*- + * Copyright (c) 1995 by David Bagley. + * + * Permission to use, copy, modify, and distribute this software and its + * documentation for any purpose and without fee is hereby granted, + * provided that the above copyright notice appear in all copies and that + * both that copyright notice and this permission notice appear in + * supporting documentation. + * + * This file is provided AS IS with no warranties of any kind. The author + * shall have no liability with respect to the infringement of copyrights, + * trade secrets or any patents by this file or any part thereof. In no + * event will the author be liable for any lost revenue or profits or + * other special, indirect and consequential damages. + * + * Revision History: + * 01-Nov-2000: Allocation checks + * 10-May-1997: Compatible with xscreensaver + * 16-Apr-1997: -neighbors 3, 9 (not sound mathematically), 12, and 8 added + * 30-May-1996: Ron Hitchens + * Fixed memory management that caused leaks + * 14-Apr-1996: -neighbors 6 runtime-time option added + * 21-Aug-1995: Coded from A.K. Dewdney's "Computer Recreations", Scientific + * American Magazine" Aug 1989 pp 102-105. Also very similar + * to hodgepodge machine described in A.K. Dewdney's "Computer + * Recreations", Scientific American Magazine" Aug 1988 + * pp 104-107. Also used life.c as a guide. + */ + +/*- + * A cellular universe of 4 phases debris, droplets, defects, and demons. + */ + +/*- + Grid Number of Neighbors + ---- ------------------ + Square 4 or 8 + Hexagon 6 + Triangle 3, 9, or 12 +*/ + +#ifndef HAVE_COCOA +# define DO_STIPPLE +#endif + +#ifdef STANDALONE +# define MODE_demon +# define DEFAULTS "*delay: 50000 \n" \ + "*count: 0 \n" \ + "*cycles: 1000 \n" \ + "*size: -7 \n" \ + "*ncolors: 64 \n" \ + "*fpsSolid: true \n" \ + +# define demon_handle_event 0 +# define UNIFORM_COLORS +# include "xlockmore.h" /* in xscreensaver distribution */ +#else /* STANDALONE */ +# include "xlock.h" /* in xlockmore distribution */ +#endif /* STANDALONE */ +#include "automata.h" + +#ifdef MODE_demon + +/*- + * neighbors of 0 randomizes it between 3, 4, 6, 8, 9, and 12. + */ +#define DEF_NEIGHBORS "0" /* choose random value */ + +static int neighbors; + +static XrmOptionDescRec opts[] = +{ + {"-neighbors", ".demon.neighbors", XrmoptionSepArg, 0} +}; + +static argtype vars[] = +{ + {&neighbors, "neighbors", "Neighbors", DEF_NEIGHBORS, t_Int} +}; +static OptionStruct desc[] = +{ + {"-neighbors num", "squares 4 or 8, hexagons 6, triangles 3, 9 or 12"} +}; + +ENTRYPOINT ModeSpecOpt demon_opts = +{sizeof opts / sizeof opts[0], opts, sizeof vars / sizeof vars[0], vars, desc}; + +#ifdef USE_MODULES +ModStruct demon_description = +{"demon", "init_demon", "draw_demon", "release_demon", + "refresh_demon", "init_demon", (char *) NULL, &demon_opts, + 50000, 0, 1000, -7, 64, 1.0, "", + "Shows Griffeath's cellular automata", 0, NULL}; + +#endif + +#define DEMONBITS(n,w,h)\ + if ((dp->pixmaps[dp->init_bits]=\ + XCreatePixmapFromBitmapData(display,window,(char *)n,w,h,1,0,1))==None){\ + free_demon(display,dp); return;} else {dp->init_bits++;} + +#define REDRAWSTEP 2000 /* How many cells to draw per cycle */ +#define MINSTATES 2 +#define MINGRIDSIZE 24 +#define MINSIZE 4 +#define NEIGHBORKINDS 6 + +/* Singly linked list */ +typedef struct _CellList { + XPoint pt; + struct _CellList *next; +} CellList; + +typedef struct { + int generation; + int xs, ys; + int xb, yb; + int nrows, ncols; + int width, height; + int states; + int state; + int redrawing, redrawpos; + int *ncells; + CellList **cellList; + unsigned char *oldcell, *newcell; + int neighbors; + int init_bits; + GC stippledGC; + Pixmap pixmaps[NUMSTIPPLES - 1]; + union { + XPoint hexagon[6]; + XPoint triangle[2][3]; + } shape; +} demonstruct; + +static char plots[2][NEIGHBORKINDS] = +{ + {3, 4, 6, 8, 9, 12}, /* Neighborhoods */ + {12, 16, 18, 20, 22, 24} /* Number of states */ +}; + +static demonstruct *demons = (demonstruct *) NULL; + +static void +drawcell(ModeInfo * mi, int col, int row, unsigned char state) +{ + demonstruct *dp = &demons[MI_SCREEN(mi)]; + GC gc; + + if (!state) { + XSetForeground(MI_DISPLAY(mi), MI_GC(mi), MI_BLACK_PIXEL(mi)); + gc = MI_GC(mi); + } else if (MI_NPIXELS(mi) >= NUMSTIPPLES) { + XSetForeground(MI_DISPLAY(mi), MI_GC(mi), + MI_PIXEL(mi, (((int) state - 1) * MI_NPIXELS(mi) / + (dp->states - 1)) % MI_NPIXELS(mi))); + gc = MI_GC(mi); + } else { + XGCValues gcv; +#ifdef DO_STIPPLE + gcv.stipple = dp->pixmaps[(state - 1) % (NUMSTIPPLES - 1)]; +#endif /* DO_STIPPLE */ + gcv.foreground = MI_WHITE_PIXEL(mi); + gcv.background = MI_BLACK_PIXEL(mi); + XChangeGC(MI_DISPLAY(mi), dp->stippledGC, + GCStipple | GCForeground | GCBackground, &gcv); + gc = dp->stippledGC; + } + if (dp->neighbors == 6) { + int ccol = 2 * col + !(row & 1), crow = 2 * row; + + dp->shape.hexagon[0].x = dp->xb + ccol * dp->xs; + dp->shape.hexagon[0].y = dp->yb + crow * dp->ys; + if (dp->xs == 1 && dp->ys == 1) + XDrawPoint(MI_DISPLAY(mi), MI_WINDOW(mi), + gc, dp->shape.hexagon[0].x, dp->shape.hexagon[0].y); + else + XFillPolygon(MI_DISPLAY(mi), MI_WINDOW(mi), gc, + dp->shape.hexagon, 6, Convex, CoordModePrevious); + } else if (dp->neighbors == 4 || dp->neighbors == 8) { + XFillRectangle(MI_DISPLAY(mi), MI_WINDOW(mi), gc, + dp->xb + dp->xs * col, dp->yb + dp->ys * row, + dp->xs - (dp->xs > 3), dp->ys - (dp->ys > 3)); + } else { /* TRI */ + int orient = (col + row) % 2; /* O left 1 right */ + + dp->shape.triangle[orient][0].x = dp->xb + col * dp->xs; + dp->shape.triangle[orient][0].y = dp->yb + row * dp->ys; + if (dp->xs <= 3 || dp->ys <= 3) + XDrawPoint(MI_DISPLAY(mi), MI_WINDOW(mi), gc, + ((orient) ? -1 : 1) + dp->shape.triangle[orient][0].x, + dp->shape.triangle[orient][0].y); + else { + if (orient) + dp->shape.triangle[orient][0].x += (dp->xs / 2 - 1); + else + dp->shape.triangle[orient][0].x -= (dp->xs / 2 - 1); + XFillPolygon(MI_DISPLAY(mi), MI_WINDOW(mi), gc, + dp->shape.triangle[orient], 3, Convex, CoordModePrevious); + + } + } +} + +static Bool +addtolist(ModeInfo * mi, int col, int row, unsigned char state) +{ + demonstruct *dp = &demons[MI_SCREEN(mi)]; + CellList *current; + + current = dp->cellList[state]; + if ((dp->cellList[state] = (CellList *) + malloc(sizeof (CellList))) == NULL) { + return False; + } + dp->cellList[state]->pt.x = col; + dp->cellList[state]->pt.y = row; + dp->cellList[state]->next = current; + dp->ncells[state]++; + return True; +} + +#ifdef DEBUG +static void +print_state(ModeInfo * mi, int state) +{ + demonstruct *dp = &demons[MI_SCREEN(mi)]; + CellList *locallist; + int i = 0; + + locallist = dp->cellList[state]; + (void) printf("state %d\n", state); + while (locallist) { + (void) printf("%d x %d, y %d\n", i, + locallist->pt.x, locallist->pt.y); + locallist = locallist->next; + i++; + } +} + +#endif + +static void +free_state(demonstruct * dp, int state) +{ + CellList *current; + + while (dp->cellList[state]) { + current = dp->cellList[state]; + dp->cellList[state] = dp->cellList[state]->next; + (void) free((void *) current); + } + dp->cellList[state] = (CellList *) NULL; + if (dp->ncells != NULL) + dp->ncells[state] = 0; +} + + +static void +free_list(demonstruct * dp) +{ + int state; + + for (state = 0; state < dp->states; state++) + free_state(dp, state); + (void) free((void *) dp->cellList); + dp->cellList = (CellList **) NULL; +} + +static void +free_struct(demonstruct * dp) +{ + if (dp->cellList != NULL) { + free_list(dp); + } + if (dp->ncells != NULL) { + (void) free((void *) dp->ncells); + dp->ncells = (int *) NULL; + } + if (dp->oldcell != NULL) { + (void) free((void *) dp->oldcell); + dp->oldcell = (unsigned char *) NULL; + } + if (dp->newcell != NULL) { + (void) free((void *) dp->newcell); + dp->newcell = (unsigned char *) NULL; + } +} + +static void +free_demon(Display *display, demonstruct *dp) +{ + int shade; + + if (dp->stippledGC != None) { + XFreeGC(display, dp->stippledGC); + dp->stippledGC = None; + } + for (shade = 0; shade < dp->init_bits; shade++) { + XFreePixmap(display, dp->pixmaps[shade]); + } + dp->init_bits = 0; + free_struct(dp); +} + +static Bool +draw_state(ModeInfo * mi, int state) +{ + demonstruct *dp = &demons[MI_SCREEN(mi)]; + GC gc; + XRectangle *rects; + CellList *current; + + if (!state) { + XSetForeground(MI_DISPLAY(mi), MI_GC(mi), MI_BLACK_PIXEL(mi)); + gc = MI_GC(mi); + } else if (MI_NPIXELS(mi) >= NUMSTIPPLES) { + XSetForeground(MI_DISPLAY(mi), MI_GC(mi), + MI_PIXEL(mi, (((int) state - 1) * MI_NPIXELS(mi) / + (dp->states - 1)) % MI_NPIXELS(mi))); + gc = MI_GC(mi); + } else { + XGCValues gcv; + +#ifdef DO_STIPPLE + gcv.stipple = dp->pixmaps[(state - 1) % (NUMSTIPPLES - 1)]; +#endif /* DO_STIPPLE */ + gcv.foreground = MI_WHITE_PIXEL(mi); + gcv.background = MI_BLACK_PIXEL(mi); + XChangeGC(MI_DISPLAY(mi), dp->stippledGC, + GCStipple | GCForeground | GCBackground, &gcv); + gc = dp->stippledGC; + } + if (dp->neighbors == 6) { /* Draw right away, slow */ + current = dp->cellList[state]; + while (current) { + int col, row, ccol, crow; + + col = current->pt.x; + row = current->pt.y; + ccol = 2 * col + !(row & 1), crow = 2 * row; + dp->shape.hexagon[0].x = dp->xb + ccol * dp->xs; + dp->shape.hexagon[0].y = dp->yb + crow * dp->ys; + if (dp->xs == 1 && dp->ys == 1) + XDrawPoint(MI_DISPLAY(mi), MI_WINDOW(mi), + gc, dp->shape.hexagon[0].x, dp->shape.hexagon[0].y); + else + XFillPolygon(MI_DISPLAY(mi), MI_WINDOW(mi), gc, + dp->shape.hexagon, 6, Convex, CoordModePrevious); + current = current->next; + } + } else if (dp->neighbors == 4 || dp->neighbors == 8) { + /* Take advantage of XDrawRectangles */ + int ncells = 0; + + /* Create Rectangle list from part of the cellList */ + if ((rects = (XRectangle *) malloc(dp->ncells[state] * + sizeof (XRectangle))) == NULL) { + return False; + } + current = dp->cellList[state]; + while (current) { + rects[ncells].x = dp->xb + current->pt.x * dp->xs; + rects[ncells].y = dp->yb + current->pt.y * dp->ys; + rects[ncells].width = dp->xs - (dp->xs > 3); + rects[ncells].height = dp->ys - (dp->ys > 3); + current = current->next; + ncells++; + } + /* Finally get to draw */ + XFillRectangles(MI_DISPLAY(mi), MI_WINDOW(mi), gc, rects, ncells); + /* Free up rects list and the appropriate part of the cellList */ + (void) free((void *) rects); + } else { /* TRI */ + current = dp->cellList[state]; + while (current) { + int col, row, orient; + + col = current->pt.x; + row = current->pt.y; + orient = (col + row) % 2; /* O left 1 right */ + dp->shape.triangle[orient][0].x = dp->xb + col * dp->xs; + dp->shape.triangle[orient][0].y = dp->yb + row * dp->ys; + if (dp->xs <= 3 || dp->ys <= 3) + XDrawPoint(MI_DISPLAY(mi), MI_WINDOW(mi), gc, + ((orient) ? -1 : 1) + dp->shape.triangle[orient][0].x, + dp->shape.triangle[orient][0].y); + else { + if (orient) + dp->shape.triangle[orient][0].x += (dp->xs / 2 - 1); + else + dp->shape.triangle[orient][0].x -= (dp->xs / 2 - 1); + XFillPolygon(MI_DISPLAY(mi), MI_WINDOW(mi), gc, + dp->shape.triangle[orient], 3, Convex, CoordModePrevious); + } + current = current->next; + } + } + free_state(dp, state); + return True; +} + +static void +RandomSoup(ModeInfo * mi) +{ + demonstruct *dp = &demons[MI_SCREEN(mi)]; + int row, col, mrow = 0; + + for (row = 0; row < dp->nrows; ++row) { + for (col = 0; col < dp->ncols; ++col) { + dp->oldcell[col + mrow] = + (unsigned char) LRAND() % ((unsigned char) dp->states); + if (!addtolist(mi, col, row, dp->oldcell[col + mrow])) + return; /* sparse soup */ + } + mrow += dp->ncols; + } +} + +ENTRYPOINT void +init_demon (ModeInfo * mi) +{ + Display *display = MI_DISPLAY(mi); + int size = MI_SIZE(mi), nk; + demonstruct *dp; + + if (demons == NULL) { + if ((demons = (demonstruct *) calloc(MI_NUM_SCREENS(mi), + sizeof (demonstruct))) == NULL) + return; + } + dp = &demons[MI_SCREEN(mi)]; + + dp->generation = 0; + dp->redrawing = 0; +#ifdef DO_STIPPLE + if (MI_NPIXELS(mi) < NUMSTIPPLES) { + Window window = MI_WINDOW(mi); + if (dp->stippledGC == None) { + XGCValues gcv; + + gcv.fill_style = FillOpaqueStippled; + if ((dp->stippledGC = XCreateGC(display, window, + GCFillStyle, &gcv)) == None) { + free_demon(display, dp); + return; + } + } + if (dp->init_bits == 0) { + int i; + + for (i = 1; i < NUMSTIPPLES; i++) { + DEMONBITS(stipples[i], STIPPLESIZE, STIPPLESIZE); + } + } + } +#endif /* DO_STIPPLE */ + free_struct(dp); + +#ifdef HAVE_COCOA + jwxyz_XSetAntiAliasing (MI_DISPLAY(mi), MI_GC(mi), False); +#endif + + for (nk = 0; nk < NEIGHBORKINDS; nk++) { + if (neighbors == plots[0][nk]) { + dp->neighbors = plots[0][nk]; + break; + } + if (nk == NEIGHBORKINDS - 1) { + nk = NRAND(NEIGHBORKINDS); + dp->neighbors = plots[0][nk]; + break; + } + } + + dp->states = MI_COUNT(mi); + if (dp->states < -MINSTATES) + dp->states = NRAND(-dp->states - MINSTATES + 1) + MINSTATES; + else if (dp->states < MINSTATES) + dp->states = plots[1][nk]; + if ((dp->cellList = (CellList **) calloc(dp->states, + sizeof (CellList *))) == NULL) { + free_demon(display, dp); + return; + } + if ((dp->ncells = (int *) calloc(dp->states, sizeof (int))) == NULL) { + free_demon(display, dp); + return; + } + + dp->state = 0; + + dp->width = MI_WIDTH(mi); + dp->height = MI_HEIGHT(mi); + + if (dp->neighbors == 6) { + int nccols, ncrows, i; + + if (dp->width < 8) + dp->width = 8; + if (dp->height < 8) + dp->height = 8; + if (size < -MINSIZE) + dp->ys = NRAND(MIN(-size, MAX(MINSIZE, MIN(dp->width, dp->height) / + MINGRIDSIZE)) - MINSIZE + 1) + MINSIZE; + else if (size < MINSIZE) { + if (!size) + dp->ys = MAX(MINSIZE, MIN(dp->width, dp->height) / MINGRIDSIZE); + else + dp->ys = MINSIZE; + } else + dp->ys = MIN(size, MAX(MINSIZE, MIN(dp->width, dp->height) / + MINGRIDSIZE)); + dp->xs = dp->ys; + nccols = MAX(dp->width / dp->xs - 2, 2); + ncrows = MAX(dp->height / dp->ys - 1, 4); + dp->ncols = nccols / 2; + dp->nrows = 2 * (ncrows / 4); + dp->xb = (dp->width - dp->xs * nccols) / 2 + dp->xs / 2; + dp->yb = (dp->height - dp->ys * (ncrows / 2) * 2) / 2 + dp->ys - 2; + for (i = 0; i < 6; i++) { + dp->shape.hexagon[i].x = (dp->xs - 1) * hexagonUnit[i].x; + dp->shape.hexagon[i].y = ((dp->ys - 1) * hexagonUnit[i].y / 2) * 4 / 3; + } + } else if (dp->neighbors == 4 || dp->neighbors == 8) { + if (size < -MINSIZE) + dp->ys = NRAND(MIN(-size, MAX(MINSIZE, MIN(dp->width, dp->height) / + MINGRIDSIZE)) - MINSIZE + 1) + MINSIZE; + else if (size < MINSIZE) { + if (!size) + dp->ys = MAX(MINSIZE, MIN(dp->width, dp->height) / MINGRIDSIZE); + else + dp->ys = MINSIZE; + } else + dp->ys = MIN(size, MAX(MINSIZE, MIN(dp->width, dp->height) / + MINGRIDSIZE)); + dp->xs = dp->ys; + dp->ncols = MAX(dp->width / dp->xs, 2); + dp->nrows = MAX(dp->height / dp->ys, 2); + dp->xb = (dp->width - dp->xs * dp->ncols) / 2; + dp->yb = (dp->height - dp->ys * dp->nrows) / 2; + } else { /* TRI */ + int orient, i; + + if (dp->width < 2) + dp->width = 2; + if (dp->height < 2) + dp->height = 2; + if (size < -MINSIZE) + dp->ys = NRAND(MIN(-size, MAX(MINSIZE, MIN(dp->width, dp->height) / + MINGRIDSIZE)) - MINSIZE + 1) + MINSIZE; + else if (size < MINSIZE) { + if (!size) + dp->ys = MAX(MINSIZE, MIN(dp->width, dp->height) / MINGRIDSIZE); + else + dp->ys = MINSIZE; + } else + dp->ys = MIN(size, MAX(MINSIZE, MIN(dp->width, dp->height) / + MINGRIDSIZE)); + dp->xs = (int) (1.52 * dp->ys); + dp->ncols = (MAX(dp->width / dp->xs - 1, 2) / 2) * 2; + dp->nrows = (MAX(dp->height / dp->ys - 1, 2) / 2) * 2; + dp->xb = (dp->width - dp->xs * dp->ncols) / 2 + dp->xs / 2; + dp->yb = (dp->height - dp->ys * dp->nrows) / 2 + dp->ys / 2; + for (orient = 0; orient < 2; orient++) { + for (i = 0; i < 3; i++) { + dp->shape.triangle[orient][i].x = + (dp->xs - 2) * triangleUnit[orient][i].x; + dp->shape.triangle[orient][i].y = + (dp->ys - 2) * triangleUnit[orient][i].y; + } + } + } + + MI_CLEARWINDOW(mi); + + if ((dp->oldcell = (unsigned char *) + malloc(dp->ncols * dp->nrows * sizeof (unsigned char))) == NULL) { + free_demon(display, dp); + return; + } + + if ((dp->newcell = (unsigned char *) + malloc(dp->ncols * dp->nrows * sizeof (unsigned char))) == NULL) { + free_demon(display, dp); + return; + } + + RandomSoup(mi); +} + +ENTRYPOINT void +draw_demon (ModeInfo * mi) +{ + int i, j, k, l, mj = 0, ml; + demonstruct *dp; + + if (demons == NULL) + return; + dp = &demons[MI_SCREEN(mi)]; + if (dp->cellList == NULL) + return; + + MI_IS_DRAWN(mi) = True; + if (dp->state >= dp->states) { + (void) memcpy((char *) dp->newcell, (char *) dp->oldcell, + dp->ncols * dp->nrows * sizeof (unsigned char)); + + if (dp->neighbors == 6) { + for (j = 0; j < dp->nrows; j++) { + for (i = 0; i < dp->ncols; i++) { + /* NE */ + if (!(j & 1)) + k = (i + 1 == dp->ncols) ? 0 : i + 1; + else + k = i; + l = (!j) ? dp->nrows - 1 : j - 1; + ml = l * dp->ncols; + if (dp->oldcell[k + ml] == + (int) (dp->oldcell[i + mj] + 1) % dp->states) + dp->newcell[i + mj] = dp->oldcell[k + ml]; + /* E */ + k = (i + 1 == dp->ncols) ? 0 : i + 1; + ml = mj; + if (dp->oldcell[k + ml] == + (int) (dp->oldcell[i + mj] + 1) % dp->states) + dp->newcell[i + mj] = dp->oldcell[k + ml]; + /* SE */ + if (!(j & 1)) + k = (i + 1 == dp->ncols) ? 0 : i + 1; + else + k = i; + l = (j + 1 == dp->nrows) ? 0 : j + 1; + ml = l * dp->ncols; + if (dp->oldcell[k + ml] == + (int) (dp->oldcell[i + mj] + 1) % dp->states) + dp->newcell[i + mj] = dp->oldcell[k + ml]; + /* SW */ + if (j & 1) + k = (!i) ? dp->ncols - 1 : i - 1; + else + k = i; + l = (j + 1 == dp->nrows) ? 0 : j + 1; + ml = l * dp->ncols; + if (dp->oldcell[k + ml] == + (int) (dp->oldcell[i + mj] + 1) % dp->states) + dp->newcell[i + mj] = dp->oldcell[k + ml]; + /* W */ + k = (!i) ? dp->ncols - 1 : i - 1; + ml = mj; + if (dp->oldcell[k + ml] == + (int) (dp->oldcell[i + mj] + 1) % dp->states) + dp->newcell[i + mj] = dp->oldcell[k + ml]; + /* NW */ + if (j & 1) + k = (!i) ? dp->ncols - 1 : i - 1; + else + k = i; + l = (!j) ? dp->nrows - 1 : j - 1; + ml = l * dp->ncols; + if (dp->oldcell[k + ml] == + (int) (dp->oldcell[i + mj] + 1) % dp->states) + dp->newcell[i + mj] = dp->oldcell[k + ml]; + } + mj += dp->ncols; + } + } else if (dp->neighbors == 4 || dp->neighbors == 8) { + for (j = 0; j < dp->nrows; j++) { + for (i = 0; i < dp->ncols; i++) { + /* N */ + k = i; + l = (!j) ? dp->nrows - 1 : j - 1; + ml = l * dp->ncols; + if (dp->oldcell[k + ml] == + (int) (dp->oldcell[i + mj] + 1) % dp->states) + dp->newcell[i + mj] = dp->oldcell[k + ml]; + /* E */ + k = (i + 1 == dp->ncols) ? 0 : i + 1; + ml = mj; + if (dp->oldcell[k + ml] == + (int) (dp->oldcell[i + mj] + 1) % dp->states) + dp->newcell[i + mj] = dp->oldcell[k + ml]; + /* S */ + k = i; + l = (j + 1 == dp->nrows) ? 0 : j + 1; + ml = l * dp->ncols; + if (dp->oldcell[k + ml] == + (int) (dp->oldcell[i + mj] + 1) % dp->states) + dp->newcell[i + mj] = dp->oldcell[k + ml]; + /* W */ + k = (!i) ? dp->ncols - 1 : i - 1; + /*l = j;*/ + ml = mj; + if (dp->oldcell[k + ml] == + (int) (dp->oldcell[i + mj] + 1) % dp->states) + dp->newcell[i + mj] = dp->oldcell[k + ml]; + } + mj += dp->ncols; + } + if (dp->neighbors == 8) { + mj = 0; + for (j = 0; j < dp->nrows; j++) { + for (i = 0; i < dp->ncols; i++) { + /* NE */ + k = (i + 1 == dp->ncols) ? 0 : i + 1; + l = (!j) ? dp->nrows - 1 : j - 1; + ml = l * dp->ncols; + if (dp->oldcell[k + ml] == + (int) (dp->oldcell[i + mj] + 1) % dp->states) + dp->newcell[i + mj] = dp->oldcell[k + ml]; + /* SE */ + k = (i + 1 == dp->ncols) ? 0 : i + 1; + l = (j + 1 == dp->nrows) ? 0 : j + 1; + ml = l * dp->ncols; + if (dp->oldcell[k + ml] == + (int) (dp->oldcell[i + mj] + 1) % dp->states) + dp->newcell[i + mj] = dp->oldcell[k + ml]; + /* SW */ + k = (!i) ? dp->ncols - 1 : i - 1; + l = (j + 1 == dp->nrows) ? 0 : j + 1; + ml = l * dp->ncols; + if (dp->oldcell[k + ml] == + (int) (dp->oldcell[i + mj] + 1) % dp->states) + dp->newcell[i + mj] = dp->oldcell[k + ml]; + /* NW */ + k = (!i) ? dp->ncols - 1 : i - 1; + l = (!j) ? dp->nrows - 1 : j - 1; + ml = l * dp->ncols; + if (dp->oldcell[k + ml] == + (int) (dp->oldcell[i + mj] + 1) % dp->states) + dp->newcell[i + mj] = dp->oldcell[k + ml]; + } + mj += dp->ncols; + } + } + } else if (dp->neighbors == 3 || dp->neighbors == 9 || + dp->neighbors == 12) { + for (j = 0; j < dp->nrows; j++) { + for (i = 0; i < dp->ncols; i++) { + if ((i + j) % 2) { /* right */ + /* W */ + k = (!i) ? dp->ncols - 1 : i - 1; + ml = mj; + if (dp->oldcell[k + ml] == + (int) (dp->oldcell[i + mj] + 1) % dp->states) + dp->newcell[i + mj] = dp->oldcell[k + ml]; + } else { /* left */ + /* E */ + k = (i + 1 == dp->ncols) ? 0 : i + 1; + ml = mj; + if (dp->oldcell[k + ml] == + (int) (dp->oldcell[i + mj] + 1) % dp->states) + dp->newcell[i + mj] = dp->oldcell[k + ml]; + } + /* N */ + k = i; + l = (!j) ? dp->nrows - 1 : j - 1; + ml = l * dp->ncols; + if (dp->oldcell[k + ml] == + (int) (dp->oldcell[i + mj] + 1) % dp->states) + dp->newcell[i + mj] = dp->oldcell[k + ml]; + /* S */ + k = i; + l = (j + 1 == dp->nrows) ? 0 : j + 1; + ml = l * dp->ncols; + if (dp->oldcell[k + ml] == + (int) (dp->oldcell[i + mj] + 1) % dp->states) + dp->newcell[i + mj] = dp->oldcell[k + ml]; + } + mj += dp->ncols; + } + if (dp->neighbors == 9 || dp->neighbors == 12) { + mj = 0; + for (j = 0; j < dp->nrows; j++) { + for (i = 0; i < dp->ncols; i++) { + /* NN */ + k = i; + if (!j) + l = dp->nrows - 2; + else if (!(j - 1)) + l = dp->nrows - 1; + else + l = j - 2; + ml = l * dp->ncols; + if (dp->oldcell[k + ml] == + (int) (dp->oldcell[i + mj] + 1) % dp->states) + dp->newcell[i + mj] = dp->oldcell[k + ml]; + /* SS */ + k = i; + if (j + 1 == dp->nrows) + l = 1; + else if (j + 2 == dp->nrows) + l = 0; + else + l = j + 2; + ml = l * dp->ncols; + if (dp->oldcell[k + ml] == + (int) (dp->oldcell[i + mj] + 1) % dp->states) + dp->newcell[i + mj] = dp->oldcell[k + ml]; + /* NW */ + k = (!i) ? dp->ncols - 1 : i - 1; + l = (!j) ? dp->nrows - 1 : j - 1; + ml = l * dp->ncols; + if (dp->oldcell[k + ml] == + (int) (dp->oldcell[i + mj] + 1) % dp->states) + dp->newcell[i + mj] = dp->oldcell[k + ml]; + /* NE */ + k = (i + 1 == dp->ncols) ? 0 : i + 1; + l = (!j) ? dp->nrows - 1 : j - 1; + ml = l * dp->ncols; + if (dp->oldcell[k + ml] == + (int) (dp->oldcell[i + mj] + 1) % dp->states) + dp->newcell[i + mj] = dp->oldcell[k + ml]; + /* SW */ + k = (!i) ? dp->ncols - 1 : i - 1; + l = (j + 1 == dp->nrows) ? 0 : j + 1; + ml = l * dp->ncols; + if (dp->oldcell[k + ml] == + (int) (dp->oldcell[i + mj] + 1) % dp->states) + dp->newcell[i + mj] = dp->oldcell[k + ml]; + /* SE */ + k = (i + 1 == dp->ncols) ? 0 : i + 1; + l = (j + 1 == dp->nrows) ? 0 : j + 1; + ml = l * dp->ncols; + if (dp->oldcell[k + ml] == + (int) (dp->oldcell[i + mj] + 1) % dp->states) + dp->newcell[i + mj] = dp->oldcell[k + ml]; + } + mj += dp->ncols; + } + if (dp->neighbors == 12) { + mj = 0; + for (j = 0; j < dp->nrows; j++) { + for (i = 0; i < dp->ncols; i++) { + if ((i + j) % 2) { /* right */ + /* NNW */ + k = (!i) ? dp->ncols - 1 : i - 1; + if (!j) + l = dp->nrows - 2; + else if (!(j - 1)) + l = dp->nrows - 1; + else + l = j - 2; + ml = l * dp->ncols; + if (dp->oldcell[k + ml] == + (int) (dp->oldcell[i + mj] + 1) % dp->states) + dp->newcell[i + mj] = dp->oldcell[k + ml]; + /* SSW */ + k = (!i) ? dp->ncols - 1 : i - 1; + if (j + 1 == dp->nrows) + l = 1; + else if (j + 2 == dp->nrows) + l = 0; + else + l = j + 2; + ml = l * dp->ncols; + if (dp->oldcell[k + ml] == + (int) (dp->oldcell[i + mj] + 1) % dp->states) + dp->newcell[i + mj] = dp->oldcell[k + ml]; + /* EE */ + k = (i + 1 == dp->ncols) ? 0 : i + 1; + /*l = j;*/ + ml = mj; + if (dp->oldcell[k + ml] == + (int) (dp->oldcell[i + mj] + 1) % dp->states) + dp->newcell[i + mj] = dp->oldcell[k + ml]; + } else { /* left */ + /* NNE */ + k = (i + 1 == dp->ncols) ? 0 : i + 1; + if (!j) + l = dp->nrows - 2; + else if (!(j - 1)) + l = dp->nrows - 1; + else + l = j - 2; + ml = l * dp->ncols; + if (dp->oldcell[k + ml] == + (int) (dp->oldcell[i + mj] + 1) % dp->states) + dp->newcell[i + mj] = dp->oldcell[k + ml]; + /* SSE */ + k = (i + 1 == dp->ncols) ? 0 : i + 1; + if (j + 1 == dp->nrows) + l = 1; + else if (j + 2 == dp->nrows) + l = 0; + else + l = j + 2; + ml = l * dp->ncols; + if (dp->oldcell[k + ml] == + (int) (dp->oldcell[i + mj] + 1) % dp->states) + dp->newcell[i + mj] = dp->oldcell[k + ml]; + /* WW */ + k = (!i) ? dp->ncols - 1 : i - 1; + /*l = j;*/ + ml = mj; + if (dp->oldcell[k + ml] == + (int) (dp->oldcell[i + mj] + 1) % dp->states) + dp->newcell[i + mj] = dp->oldcell[k + ml]; + } + } + mj += dp->ncols; + } + } + } + } + mj = 0; + for (j = 0; j < dp->nrows; j++) { + for (i = 0; i < dp->ncols; i++) + if (dp->oldcell[i + mj] != dp->newcell[i + mj]) { + dp->oldcell[i + mj] = dp->newcell[i + mj]; + if (!addtolist(mi, i, j, dp->oldcell[i + mj])) { + free_demon(MI_DISPLAY(mi), dp); + return; + } + } + mj += dp->ncols; + } + if (++dp->generation > MI_CYCLES(mi)) + init_demon(mi); + dp->state = 0; + } else { + if (dp->ncells[dp->state]) + if (!draw_state(mi, dp->state)) { + free_demon(MI_DISPLAY(mi), dp); + return; + } + dp->state++; + } + if (dp->redrawing) { + for (i = 0; i < REDRAWSTEP; i++) { + if (dp->oldcell[dp->redrawpos]) { + drawcell(mi, dp->redrawpos % dp->ncols, dp->redrawpos / dp->ncols, + dp->oldcell[dp->redrawpos]); + } + if (++(dp->redrawpos) >= dp->ncols * dp->nrows) { + dp->redrawing = 0; + break; + } + } + } +} + + +ENTRYPOINT void +reshape_demon(ModeInfo * mi, int width, int height) +{ + XClearWindow (MI_DISPLAY (mi), MI_WINDOW(mi)); + init_demon (mi); +} + + +ENTRYPOINT void +release_demon (ModeInfo * mi) +{ + if (demons != NULL) { + int screen; + + for (screen = 0; screen < MI_NUM_SCREENS(mi); screen++) + free_demon(MI_DISPLAY(mi), &demons[screen]); + (void) free((void *) demons); + demons = (demonstruct *) NULL; + } +} + +ENTRYPOINT void +refresh_demon (ModeInfo * mi) +{ + demonstruct *dp; + + if (demons == NULL) + return; + dp = &demons[MI_SCREEN(mi)]; + + dp->redrawing = 1; + dp->redrawpos = 0; +} + +XSCREENSAVER_MODULE ("Demon", demon) + +#endif /* MODE_demon */ diff --git a/hacks/demon.man b/hacks/demon.man new file mode 100644 index 00000000..43481bc8 --- /dev/null +++ b/hacks/demon.man @@ -0,0 +1,69 @@ +.TH XScreenSaver 1 "" "X Version 11" +.SH NAME +demon - cellular automaton. +.SH SYNOPSIS +.B demon +[\-display \fIhost:display.screen\fP] +[\-visual \fIvisual\fP] +[\-window] +[\-root] +[\-count \fInumber\fP] +[\-cycles \fInumber\fP] +[\-delay \fInumber\fP] +[\-ncolors \fInumber\fP] +[\-size \fInumber\fP] +[\-fps] +.SH DESCRIPTION +A cellular automaton that starts with a random field, and organizes it into +stripes and spirals. +.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 \-count \fInumber\fP +States. 0 - 20. Default: 0. +.TP 8 +.B \-cycles \fInumber\fP +Timeout. 0 - 800000. Default: 1000. +.TP 8 +.B \-delay \fInumber\fP +Per-frame delay, in microseconds. Default: 50000 (0.05 seconds.). +.TP 8 +.B \-ncolors \fInumber\fP +Number of Colors. Default: 64. +.TP 8 +.B \-size \fInumber\fP +Cell Size. -20 - 20. Default: -7. +.TP 8 +.B \-fps +Display the current frame rate and CPU load. +.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 2002 by David Bagley. 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 Bagley. diff --git a/hacks/discrete.c b/hacks/discrete.c new file mode 100644 index 00000000..1746f726 --- /dev/null +++ b/hacks/discrete.c @@ -0,0 +1,461 @@ +/* -*- Mode: C; tab-width: 4 -*- */ +/* discrete --- chaotic mappings */ + +#if 0 +static const char sccsid[] = "@(#)discrete.c 5.00 2000/11/01 xlockmore"; +#endif + +/*- + * Copyright (c) 1996 by Tim Auckland + * + * Permission to use, copy, modify, and distribute this software and its + * documentation for any purpose and without fee is hereby granted, + * provided that the above copyright notice appear in all copies and that + * both that copyright notice and this permission notice appear in + * supporting documentation. + * + * This file is provided AS IS with no warranties of any kind. The author + * shall have no liability with respect to the infringement of copyrights, + * trade secrets or any patents by this file or any part thereof. In no + * event will the author be liable for any lost revenue or profits or + * other special, indirect and consequential damages. + * + * "discrete" shows a number of fractals based on the "discrete map" + * type of dynamical systems. They include a different way of looking + * at the HOPALONG system, an inverse julia-set iteration, the "Standard + * Map" and the "Bird in a Thornbush" fractal. + * + * Revision History: + * 01-Nov-2000: Allocation checks + * 31-Jul-1997: Ported to xlockmore-4 + * 08-Aug-1996: Adapted from hop.c Copyright (c) 1991 by Patrick J. Naughton. + */ + +#ifdef STANDALONE +# define MODE_discrete +#define DEFAULTS "*delay: 20000 \n" \ + "*count: 4096 \n" \ + "*cycles: 2500 \n" \ + "*ncolors: 100 \n" \ + "*fpsSolid: true \n" \ + +# define SMOOTH_COLORS +# define discrete_handle_event 0 +# include "xlockmore.h" /* in xscreensaver distribution */ +# include "erase.h" +#else /* STANDALONE */ +# include "xlock.h" /* in xlockmore distribution */ +#endif /* STANDALONE */ + +#ifdef MODE_discrete + +ENTRYPOINT ModeSpecOpt discrete_opts = +{0, (XrmOptionDescRec *) NULL, 0, (argtype *) NULL, (OptionStruct *) NULL}; + +#ifdef USE_MODULES +ModStruct discrete_description = +{"discrete", "init_discrete", "draw_discrete", "release_discrete", + "refresh_discrete", "init_discrete", (char *) NULL, &discrete_opts, + 1000, 4096, 2500, 1, 64, 1.0, "", + "Shows various discrete maps", 0, NULL}; + +#endif + +enum ftypes { + SQRT, BIRDIE, STANDARD, TRIG, CUBIC, HENON, AILUJ, HSHOE, DELOG +}; + +/*#define TEST STANDARD */ + +#define BIASES 18 +static enum ftypes bias[BIASES] = +{ + STANDARD, STANDARD, STANDARD, STANDARD, + SQRT, SQRT, SQRT, SQRT, + BIRDIE, BIRDIE, BIRDIE, + AILUJ, AILUJ, AILUJ, + TRIG, TRIG, + CUBIC, + HENON, +}; + +typedef struct { + int maxx; + int maxy; /* max of the screen */ + double a; + double b; + double c; + double d; + double e; + double i; + double j; /* discrete parameters */ + double ic; + double jc; + double is; + double js; + int inc; + int pix; + enum ftypes op; + int count; + XPoint *pointBuffer; /* pointer for XDrawPoints */ + + int sqrt_sign, std_sign; + +#ifdef STANDALONE + eraser_state *eraser; +#endif + +} discretestruct; + +static discretestruct *discretes = (discretestruct *) NULL; + +ENTRYPOINT void +init_discrete (ModeInfo * mi) +{ + double range; + discretestruct *hp; + + if (discretes == NULL) { + if ((discretes = + (discretestruct *) calloc(MI_NUM_SCREENS(mi), + sizeof (discretestruct))) == NULL) + return; + } + hp = &discretes[MI_SCREEN(mi)]; + + hp->maxx = MI_WIDTH(mi); + hp->maxy = MI_HEIGHT(mi); +#ifdef TEST + hp->op = TEST; +#else + hp->op = bias[LRAND() % BIASES]; +#endif + switch (hp->op) { + case HSHOE: + hp->ic = 0; + hp->jc = 0; + hp->is = hp->maxx / (4); + hp->js = hp->maxy / (4); + hp->a = 0.5; + hp->b = 0.5; + hp->c = 0.2; + hp->d = -1.25; + hp->e = 1; + hp->i = hp->j = 0.0; + break; + case DELOG: + hp->ic = 0.5; + hp->jc = 0.3; + hp->is = hp->maxx / 1.5; + hp->js = hp->maxy / 1.5; + hp->a = 2.176399; + hp->i = hp->j = 0.01; + break; + case HENON: + hp->jc = ((LRAND() / MAXRAND) * 2.0 - 1.0) * 0.4; + hp->ic = 1.3 * (1 - (hp->jc * hp->jc) / (0.4 * 0.4)); + hp->is = hp->maxx; + hp->js = hp->maxy * 1.5; + hp->a = 1; + hp->b = 1.4; + hp->c = 0.3; + hp->i = hp->j = 0; + break; + case SQRT: + hp->ic = 0; + hp->jc = 0; + hp->is = 1; + hp->js = 1; + range = sqrt((double) hp->maxx * 2 * hp->maxx * 2 + + (double) hp->maxy * 2 * hp->maxy * 2) / + (10.0 + LRAND() % 10); + + hp->a = (LRAND() / MAXRAND) * range - range / 2.0; + hp->b = (LRAND() / MAXRAND) * range - range / 2.0; + hp->c = (LRAND() / MAXRAND) * range - range / 2.0; + if (!(LRAND() % 2)) + hp->c = 0.0; + hp->i = hp->j = 0.0; + break; + case STANDARD: + hp->ic = M_PI; + hp->jc = M_PI; + hp->is = hp->maxx / (M_PI * 2); + hp->js = hp->maxy / (M_PI * 2); + hp->a = 0; /* decay */ + hp->b = (LRAND() / MAXRAND) * 2.0; + hp->c = 0; + hp->i = M_PI; + hp->j = M_PI; + break; + case BIRDIE: + hp->ic = 0; + hp->jc = 0; + hp->is = hp->maxx / 2; + hp->js = hp->maxy / 2; + hp->a = 1.99 + ((LRAND() / MAXRAND) * 2.0 - 1.0) * 0.2; + hp->b = 0; + hp->c = 0.8 + ((LRAND() / MAXRAND) * 2.0 - 1.0) * 0.1; + hp->i = hp->j = 0; + break; + case TRIG: + hp->a = 5; + hp->b = 0.5 + ((LRAND() / MAXRAND) * 2.0 - 1.0) * 0.3; + hp->ic = hp->a; + hp->jc = 0; + hp->is = hp->maxx / (hp->b * 20); + hp->js = hp->maxy / (hp->b * 20); + hp->i = hp->j = 0; + break; + case CUBIC: + hp->a = 2.77; + hp->b = 0.1 + ((LRAND() / MAXRAND) * 2.0 - 1.0) * 0.1; + hp->ic = 0; + hp->jc = 0; + hp->is = hp->maxx / 4; + hp->js = hp->maxy / 4; + hp->i = hp->j = 0.1; + break; + case AILUJ: + { + int i; + double x, y, xn, yn; + + hp->ic = 0; + hp->jc = 0; + hp->is = hp->maxx / 4; + hp->js = hp->maxx / 4; + do { + hp->a = ((LRAND() / MAXRAND) * 2.0 - 1.0) * 1.5 - 0.5; + hp->b = ((LRAND() / MAXRAND) * 2.0 - 1.0) * 1.5; + x = y = 0; +#define MAXITER 10 + for (i = 0; i < MAXITER && x * x + y * y < 13; i++) { /* 'Brot calc */ + xn = x * x - y * y + hp->a; + yn = 2 * x * y + hp->b; + x = xn; + y = yn; + } + } while (i < MAXITER); /* wait for a connected set */ + hp->i = hp->j = 0.1; + break; + } + } + hp->pix = 0; + hp->inc = 0; + + if (hp->pointBuffer == NULL) { + hp->pointBuffer = (XPoint *) malloc(sizeof (XPoint) * MI_COUNT(mi)); + /* if fails will check later */ + } + +#ifndef STANDALONE + /* Clear the background. */ + MI_CLEARWINDOW(mi); +#endif + + XSetForeground(MI_DISPLAY(mi), MI_GC(mi), MI_WHITE_PIXEL(mi)); + hp->count = 0; + hp->sqrt_sign = 1; + hp->std_sign = 1; +} + + +static void +draw_discrete_1 (ModeInfo * mi) +{ + Display *dsp = MI_DISPLAY(mi); + Window win = MI_WINDOW(mi); + double oldj, oldi; + int count = MI_COUNT(mi); + int cycles = MI_CYCLES(mi); + int k; + XPoint *xp; + GC gc = MI_GC(mi); + discretestruct *hp; + + if (discretes == NULL) + return; + hp = &discretes[MI_SCREEN(mi)]; + if (hp->pointBuffer == NULL) + return; + + k = count; + xp = hp->pointBuffer; + + hp->inc++; + + MI_IS_DRAWN(mi) = True; + + if (MI_NPIXELS(mi) > 2) { + XSetForeground(dsp, gc, MI_PIXEL(mi, hp->pix)); + if (++hp->pix >= MI_NPIXELS(mi)) + hp->pix = 0; + } + while (k--) { + oldj = hp->j; + oldi = hp->i; + switch (hp->op) { + case HSHOE: + { + int i; + +#if 0 + if (!k) { + XSetForeground(dsp, gc, MI_BLACK_PIXEL(mi)); + XFillRectangle(dsp, win, gc, 0, 0, hp->maxx, hp->maxy); + XSetForeground(dsp, gc, MI_PIXEL(mi, hp->pix)); + } else +#endif +#define HD +#ifdef HD + if (k < count / 4) { + hp->i = ((double) k / count) * 8 - 1; + hp->j = 1; + } else if (k < count / 2) { + hp->i = 1; + hp->j = 3 - ((double) k / count) * 8; + } else if (k < 3 * count / 4) { + hp->i = 5 - ((double) k / count) * 8; + hp->j = -1; + } else { + hp->i = -1; + hp->j = ((double) k / count) * 8 - 7; + } + for (i = 1; i < (hp->inc % 15); i++) { + oldj = hp->j; + oldi = hp->i; +#endif + hp->i = (hp->a * oldi + hp->b) * oldj; + hp->j = (hp->e - hp->d + hp->c * oldi) * oldj * oldj - hp->c * oldi + hp->d; +#ifdef HD + } +#endif + break; + } + case DELOG: + hp->j = oldi; + hp->i = hp->a * oldi * (1 - oldj); + break; + case HENON: + hp->i = oldj + hp->a - hp->b * oldi * oldi; + hp->j = hp->c * oldi; + break; + case SQRT: + if (k) { + hp->j = hp->a + hp->i; + hp->i = -oldj + (hp->i < 0 + ? sqrt(fabs(hp->b * (hp->i - hp->c))) + : -sqrt(fabs(hp->b * (hp->i - hp->c)))); + } else { + hp->i = (hp->sqrt_sign ? 1 : -1) * hp->inc * hp->maxx / cycles / 2; + hp->j = hp->a + hp->i; + hp->sqrt_sign = !hp->sqrt_sign; + } + break; + case STANDARD: + if (k) { + hp->j = (1 - hp->a) * oldj + hp->b * sin(oldi) + hp->a * hp->c; + hp->j = fmod(hp->j + 2 * M_PI, 2 * M_PI); + hp->i = oldi + hp->j; + hp->i = fmod(hp->i + 2 * M_PI, 2 * M_PI); + } else { + hp->j = M_PI + fmod((hp->std_sign ? 1 : -1) * hp->inc * 2 * M_PI / (cycles - 0.5), M_PI); + hp->i = M_PI; + hp->std_sign = !hp->std_sign; + } + break; + case BIRDIE: + hp->j = oldi; + hp->i = (1 - hp->c) * cos(M_PI * hp->a * oldj) + hp->c * hp->b; + hp->b = oldj; + break; + case TRIG: + { + double r2 = oldi * oldi + oldj * oldj; + + hp->i = hp->a + hp->b * (oldi * cos(r2) - oldj * sin(r2)); + hp->j = hp->b * (oldj * cos(r2) + oldi * sin(r2)); + } + break; + case CUBIC: + hp->i = oldj; + hp->j = hp->a * oldj - oldj * oldj * oldj - hp->b * oldi; + break; + case AILUJ: + hp->i = ((LRAND() < MAXRAND / 2) ? -1 : 1) * + sqrt(((oldi - hp->a) + + sqrt((oldi - hp->a) * (oldi - hp->a) + (oldj - hp->b) * (oldj - hp->b))) / 2); + if (hp->i < 0.00000001 && hp->i > -0.00000001) + hp->i = (hp->i > 0.0) ? 0.00000001 : -0.00000001; + hp->j = (oldj - hp->b) / (2 * hp->i); + break; + } + xp->x = hp->maxx / 2 + (int) ((hp->i - hp->ic) * hp->is); + xp->y = hp->maxy / 2 - (int) ((hp->j - hp->jc) * hp->js); + xp++; + } + XDrawPoints(dsp, win, gc, hp->pointBuffer, count, CoordModeOrigin); +} + +ENTRYPOINT void +draw_discrete (ModeInfo * mi) +{ + discretestruct *hp = &discretes[MI_SCREEN(mi)]; + int cycles = MI_CYCLES(mi); + int i; + + if (hp->eraser) { + hp->eraser = erase_window (MI_DISPLAY(mi), MI_WINDOW(mi), hp->eraser); + return; + } + + for (i = 0; i < 10; i++) { + draw_discrete_1 (mi); + hp->count++; + } + + if (hp->count > cycles) { + hp->eraser = erase_window (MI_DISPLAY(mi), MI_WINDOW(mi), hp->eraser); + init_discrete(mi); + } +} + + +ENTRYPOINT void +reshape_discrete(ModeInfo * mi, int width, int height) +{ + discretestruct *hp = &discretes[MI_SCREEN(mi)]; + hp->maxx = width; + hp->maxy = height; + XClearWindow (MI_DISPLAY (mi), MI_WINDOW(mi)); +} + +ENTRYPOINT void +release_discrete(ModeInfo * mi) +{ + if (discretes != NULL) { + int screen; + + for (screen = 0; screen < MI_NUM_SCREENS(mi); screen++) { + discretestruct *hp = &discretes[screen]; + + if (hp->pointBuffer != NULL) { + (void) free((void *) hp->pointBuffer); + /* hp->pointBuffer = NULL; */ + } + } + (void) free((void *) discretes); + discretes = (discretestruct *) NULL; + } +} + +ENTRYPOINT void +refresh_discrete(ModeInfo * mi) +{ + MI_CLEARWINDOW(mi); +} + +XSCREENSAVER_MODULE ("Discrete", discrete) + +#endif /* MODE_discrete */ diff --git a/hacks/discrete.man b/hacks/discrete.man new file mode 100644 index 00000000..63e1787c --- /dev/null +++ b/hacks/discrete.man @@ -0,0 +1,61 @@ +.TH XScreenSaver 1 "" "X Version 11" +.SH NAME +discrete - discrete map iterative function fractal systems. +.SH SYNOPSIS +.B discrete +[\-display \fIhost:display.screen\fP] +[\-visual \fIvisual\fP] +[\-window] +[\-root] +[\-cycles \fInumber\fP] +[\-delay \fInumber\fP] +[\-ncolors \fInumber\fP] +[\-fps] +.SH DESCRIPTION +More ``discrete map'' systems, including new variants of Hopalong and +Julia, and a few others. +.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 \-cycles \fInumber\fP +Timeout. 100 - 10000. Default: 2500. +.TP 8 +.B \-delay \fInumber\fP +Per-frame delay, in microseconds. Default: 1000 (0.001 seconds.). +.TP 8 +.B \-ncolors \fInumber\fP +Number of Colors. Default: 100. +.TP 8 +.B \-fps +Display the current frame rate and CPU load. +.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 2002 by Tim Auckland. 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 +Tim Auckland. diff --git a/hacks/distort.c b/hacks/distort.c new file mode 100644 index 00000000..92cc0de3 --- /dev/null +++ b/hacks/distort.c @@ -0,0 +1,862 @@ +/* -*- mode: C; tab-width: 4 -*- + * xscreensaver, Copyright (c) 1992-2008 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. + */ + +/* distort + * by Jonas Munsin (jmunsin@iki.fi) and Jamie Zawinski + * TODO: + * -check the allocations in init_round_lense again, maybe make it possible again + * to use swamp without pre-allocating/calculating (although that + * makes it slower) - -swamp is memory hungry + * -more distortion matrices (fortunately, I'm out of ideas :) + * Stuff that would be cool but probably too much of a resource hog: + * -some kind of interpolation to avoid jaggies + * -large speed values leaves the image distorted + * program idea borrowed from a screensaver on a non-*NIX OS, + * + * 28 Sep 1999 Jonas Munsin (jmunsin@iki.fi) + * Added about 10x faster algortim for 8, 16 and 32 bpp (modifies pixels + * directly avoiding costly XPutPixle(XGetPixel()) calls, inspired by + * xwhirl made by horvai@clipper.ens.fr (Peter Horvai) and the XFree86 + * Xlib sources. + * This piece of code is really horrible, but it works, and at the moment + * I don't have time or inspiration to fix something that works (knock + * on wood). + * 08 Oct 1999 Jonas Munsin (jmunsin@iki.fi) + * Corrected several bugs causing references beyond allocated memory. + */ + +#include +#include "screenhack.h" +/*#include */ + +#ifdef HAVE_XSHM_EXTENSION +# include "xshm.h" +#endif /* HAVE_XSHM_EXTENSION */ + +#define CARD32 unsigned int +#define CARD16 unsigned short +#define CARD8 unsigned char + + +struct coo { + int x; + int y; + int r, r_change; + int xmove, ymove; +}; + +struct state { + Display *dpy; + Window window; + + struct coo xy_coo[10]; + + int delay, radius, speed, number, blackhole, vortex, magnify, reflect, slow; + int duration; + time_t start_time; + + XWindowAttributes xgwa; + GC gc; + unsigned long black_pixel; + + XImage *orig_map, *buffer_map; + unsigned long *buffer_map_cache; + + int ***from; + int ****from_array; + int *fast_from; + + int bpp_size; + +#ifdef HAVE_XSHM_EXTENSION + Bool use_shm; + XShmSegmentInfo shm_info; +#endif /* HAVE_XSHM_EXTENSION */ + + void (*effect) (struct state *, int); + void (*draw) (struct state *, int); + void (*draw_routine) (struct state *st, XImage *, XImage *, int, int, int *); + + async_load_state *img_loader; +}; + + +static void move_lense(struct state *, int); +static void swamp_thing(struct state *, int); +static void new_rnd_coo(struct state *, int); +static void init_round_lense(struct state *st); +static void reflect_draw(struct state *, int); +static void plain_draw(struct state *, int); + +static void fast_draw_8 (struct state *st, XImage *, XImage *, int, int, int *); +static void fast_draw_16(struct state *st, XImage *, XImage *, int, int, int *); +static void fast_draw_32(struct state *st, XImage *, XImage *, int, int, int *); +static void generic_draw(struct state *st, XImage *, XImage *, int, int, int *); + + +static void distort_finish_loading (struct state *); + +static void * +distort_init (Display *dpy, Window window) +{ + struct state *st = (struct state *) calloc (1, sizeof(*st)); + XGCValues gcv; + long gcflags; + int i; + char *s; + + st->dpy = dpy; + st->window = window; + + st->delay = get_integer_resource(st->dpy, "delay", "Integer"); + st->duration = get_integer_resource (st->dpy, "duration", "Seconds"); + st->radius = get_integer_resource(st->dpy, "radius", "Integer"); + st->speed = get_integer_resource(st->dpy, "speed", "Integer"); + st->number = get_integer_resource(st->dpy, "number", "Integer"); + + if (st->delay < 0) st->delay = 0; + if (st->duration < 1) st->duration = 1; + +#ifdef HAVE_XSHM_EXTENSION + st->use_shm = get_boolean_resource(st->dpy, "useSHM", "Boolean"); +#endif /* HAVE_XSHM_EXTENSION */ + + st->blackhole = get_boolean_resource(st->dpy, "blackhole", "Boolean"); + st->vortex = get_boolean_resource(st->dpy, "vortex", "Boolean"); + st->magnify = get_boolean_resource(st->dpy, "magnify", "Boolean"); + st->reflect = get_boolean_resource(st->dpy, "reflect", "Boolean"); + st->slow = get_boolean_resource(st->dpy, "slow", "Boolean"); + + st->effect = NULL; + s = get_string_resource(st->dpy, "effect", "String"); + if (s && !strcasecmp(s,"swamp")) + st->effect = &swamp_thing; + else if (s && !strcasecmp(s,"bounce")) + st->effect = &move_lense; + else if (s && !strcasecmp(s,"none")) + ; + else if (s && *s) + fprintf(stderr,"%s: bogus effect: %s\n", progname, s); + + XGetWindowAttributes (st->dpy, st->window, &st->xgwa); + + if (st->effect == NULL && st->radius == 0 && st->speed == 0 && st->number == 0 + && !st->blackhole && !st->vortex && !st->magnify && !st->reflect) { +/* if no cmdline options are given, randomly choose one of: + * -radius 50 -number 4 -speed 1 -bounce + * -radius 50 -number 4 -speed 1 -blackhole + * -radius 50 -number 4 -speed 1 -vortex + * -radius 50 -number 4 -speed 1 -vortex -magnify + * -radius 50 -number 4 -speed 1 -vortex -magnify -blackhole + * -radius 100 -number 1 -speed 2 -bounce + * -radius 100 -number 1 -speed 2 -blackhole + * -radius 100 -number 1 -speed 2 -vortex + * -radius 100 -number 1 -speed 2 -vortex -magnify + * -radius 100 -number 1 -speed 2 -vortex -magnify -blackhole + * -radius 80 -number 1 -speed 2 -reflect + * -radius 50 -number 3 -speed 2 -reflect + * jwz: not these + * -radius 50 -number 4 -speed 2 -swamp + * -radius 50 -number 4 -speed 2 -swamp -blackhole + * -radius 50 -number 4 -speed 2 -swamp -vortex + * -radius 50 -number 4 -speed 2 -swamp -vortex -magnify + * -radius 50 -number 4 -speed 2 -swamp -vortex -magnify -blackhole + */ + + i = (random() % 12 /* 17 */); + + st->draw = &plain_draw; + + switch (i) { + case 0: + st->radius=50;st->number=4;st->speed=1; + st->effect=&move_lense;break; + case 1: + st->radius=50;st->number=4;st->speed=1;st->blackhole=1; + st->effect=&move_lense;break; + case 2: + st->radius=50;st->number=4;st->speed=1;st->vortex=1; + st->effect=&move_lense;break; + case 3: + st->radius=50;st->number=4;st->speed=1;st->vortex=1;st->magnify=1; + st->effect=&move_lense;break; + case 4: + st->radius=50;st->number=4;st->speed=1;st->vortex=1;st->magnify=1;st->blackhole=1; + st->effect=&move_lense;break; + case 5: + st->radius=100;st->number=1;st->speed=2; + st->effect=&move_lense;break; + case 6: + st->radius=100;st->number=1;st->speed=2;st->blackhole=1; + st->effect=&move_lense;break; + case 7: + st->radius=100;st->number=1;st->speed=2;st->vortex=1; + st->effect=&move_lense;break; + case 8: + st->radius=100;st->number=1;st->speed=2;st->vortex=1;st->magnify=1; + st->effect=&move_lense;break; + case 9: + st->radius=100;st->number=1;st->speed=2;st->vortex=1;st->magnify=1;st->blackhole=1; + st->effect=&move_lense;break; + + case 10: + st->radius=80;st->number=1;st->speed=2;st->reflect=1; + st->draw = &reflect_draw;st->effect = &move_lense;break; + case 11: + st->radius=50;st->number=4;st->speed=2;st->reflect=1; + st->draw = &reflect_draw;st->effect = &move_lense;break; + +#if 0 /* jwz: not these */ + case 12: + st->radius=50;st->number=4;st->speed=2; + effect=&swamp_thing;break; + case 13: + st->radius=50;st->number=4;st->speed=2;st->blackhole=1; + effect=&swamp_thing;break; + case 14: + st->radius=50;st->number=4;st->speed=2;st->vortex=1; + effect=&swamp_thing;break; + case 15: + st->radius=50;st->number=4;st->speed=2;st->vortex=1;st->magnify=1; + effect=&swamp_thing;break; + case 16: + st->radius=50;st->number=4;st->speed=2;st->vortex=1;st->magnify=1;st->blackhole=1; + effect=&swamp_thing;break; +#endif + + default: + abort(); break; + } + + /* but if the window is small, reduce default radius */ + if (st->xgwa.width < st->radius * 8) + st->radius = st->xgwa.width/8; + } + + /* never allow the radius to be too close to the min window dimension + */ + if (st->radius >= st->xgwa.width * 0.45) st->radius = st->xgwa.width * 0.45; + if (st->radius >= st->xgwa.height * 0.45) st->radius = st->xgwa.height * 0.45; + + + /* -swamp mode consumes vast amounts of memory, proportional to radius -- + so throttle radius to a small-ish value (60 => ~30MB.) + */ + if (st->effect == &swamp_thing && st->radius > 60) + st->radius = 60; + + if (st->delay < 0) + st->delay = 0; + if (st->radius <= 0) + st->radius = 60; + if (st->speed <= 0) + st->speed = 2; + if (st->number <= 0) + st->number=1; + if (st->number >= 10) + st->number=1; + if (st->effect == NULL) + st->effect = &move_lense; + if (st->reflect) { + st->draw = &reflect_draw; + st->effect = &move_lense; + } + if (st->draw == NULL) + st->draw = &plain_draw; + + st->black_pixel = BlackPixelOfScreen( st->xgwa.screen ); + + gcv.function = GXcopy; + gcv.subwindow_mode = IncludeInferiors; + gcflags = GCFunction; + if (use_subwindow_mode_p(st->xgwa.screen, st->window)) /* see grabscreen.c */ + gcflags |= GCSubwindowMode; + st->gc = XCreateGC (st->dpy, st->window, gcflags, &gcv); + + st->img_loader = load_image_async_simple (0, st->xgwa.screen, st->window, + st->window, 0, 0); + st->start_time = time ((time_t) 0); + return st; +} + +static void +distort_finish_loading (struct state *st) +{ + int i; + + st->start_time = time ((time_t) 0); + + st->buffer_map = 0; + st->orig_map = XGetImage(st->dpy, st->window, 0, 0, st->xgwa.width, st->xgwa.height, + ~0L, ZPixmap); + st->buffer_map_cache = malloc(sizeof(unsigned long)*(2*st->radius+st->speed+2)*(2*st->radius+st->speed+2)); + + if (st->buffer_map_cache == NULL) { + perror("distort"); + exit(EXIT_FAILURE); + } + +# ifdef HAVE_XSHM_EXTENSION + + if (st->use_shm) + { + st->buffer_map = create_xshm_image(st->dpy, st->xgwa.visual, st->orig_map->depth, + ZPixmap, 0, &st->shm_info, + 2*st->radius + st->speed + 2, + 2*st->radius + st->speed + 2); + if (!st->buffer_map) + st->use_shm = False; + } +# endif /* HAVE_XSHM_EXTENSION */ + + if (!st->buffer_map) + { + st->buffer_map = XCreateImage(st->dpy, st->xgwa.visual, + st->orig_map->depth, ZPixmap, 0, 0, + 2*st->radius + st->speed + 2, 2*st->radius + st->speed + 2, + 8, 0); + st->buffer_map->data = (char *) + calloc(st->buffer_map->height, st->buffer_map->bytes_per_line); + } + + if ((st->buffer_map->byte_order == st->orig_map->byte_order) + && (st->buffer_map->depth == st->orig_map->depth) + && (st->buffer_map->format == ZPixmap) + && (st->orig_map->format == ZPixmap) + && !st->slow) { + switch (st->orig_map->bits_per_pixel) { + case 32: + st->draw_routine = &fast_draw_32; + st->bpp_size = sizeof(CARD32); + break; + case 16: + st->draw_routine = &fast_draw_16; + st->bpp_size = sizeof(CARD16); + break; + case 8: + st->draw_routine = &fast_draw_8; + st->bpp_size = sizeof(CARD8); + break; + default: + st->draw_routine = &generic_draw; + break; + } + } else { + st->draw_routine = &generic_draw; + } + init_round_lense(st); + + for (i = 0; i < st->number; i++) { + new_rnd_coo(st,i); + if (st->number != 1) + st->xy_coo[i].r = (i*st->radius)/(st->number-1); /* "randomize" initial */ + else + st->xy_coo[i].r = 0; + st->xy_coo[i].r_change = st->speed + (i%2)*2*(-st->speed); /* values a bit */ + st->xy_coo[i].xmove = st->speed + (i%2)*2*(-st->speed); + st->xy_coo[i].ymove = st->speed + (i%2)*2*(-st->speed); + } +} + +/* example: initializes a "see-trough" matrix */ +/* static void make_null_lense(struct state *st) +{ + int i, j; + for (i = 0; i < 2*radius+speed+2; i++) { + for (j = 0 ; j < 2*radius+speed+2 ; j++) { + from[i][j][0]=i; + from[i][j][1]=j; + } + } +} +*/ +static void convert(struct state *st) +{ + int *p; + int i, j; + st->fast_from = calloc(1, sizeof(int)*((st->buffer_map->bytes_per_line/st->bpp_size)*(2*st->radius+st->speed+2) + 2*st->radius+st->speed+2)); + if (st->fast_from == NULL) { + perror("distort"); + exit(EXIT_FAILURE); + } + p = st->fast_from; + for (i = 0; i < 2*st->radius+st->speed+2; i++) { + for (j = 0; j < 2*st->radius+st->speed+2; j++) { + *(p + i + j*st->buffer_map->bytes_per_line/st->bpp_size) + = st->from[i][j][0] + st->xgwa.width*st->from[i][j][1]; + if (*(p + i + j*st->buffer_map->bytes_per_line/st->bpp_size) < 0 + || *(p + i + j*st->buffer_map->bytes_per_line/st->bpp_size) >= st->orig_map->height*st->orig_map->width) { + *(p + i + j*st->buffer_map->bytes_per_line/st->bpp_size) = 0; + } + } + } +} + +/* makes a lense with the Radius=loop and centred in + * the point (radius, radius) + */ +static void make_round_lense(struct state *st, int radius, int loop) +{ + int i, j; + + for (i = 0; i < 2*radius+st->speed+2; i++) { + for(j = 0; j < ((0 == st->bpp_size) ? (2*radius+st->speed+2) : (st->buffer_map->bytes_per_line/st->bpp_size)); j++) { + double r, d; + r = sqrt ((i-radius)*(i-radius)+(j-radius)*(j-radius)); + if (loop == 0) + d=0.0; + else + d=r/loop; + + if (r < loop-1) { + + if (st->vortex) { /* vortex-twist effect */ + double angle; + /* this one-line formula for getting a nice rotation angle is borrowed + * (with permission) from the whirl plugin for gimp, + * Copyright (C) 1996 Federico Mena Quintero + */ + /* 5 is just a constant used because it looks good :) */ + angle = 5*(1-d)*(1-d); + + /* Avoid atan2: DOMAIN error message */ + if ((radius-j) == 0.0 && (radius-i) == 0.0) { + st->from[i][j][0] = radius + cos(angle)*r; + st->from[i][j][1] = radius + sin(angle)*r; + } else { + st->from[i][j][0] = radius + + cos(angle - atan2(radius-j, -(radius-i)))*r; + st->from[i][j][1] = radius + + sin(angle - atan2(radius-j, -(radius-i)))*r; + } + if (st->magnify) { + r = sin(d*M_PI_2); + if (st->blackhole && r != 0) /* blackhole effect */ + r = 1/r; + st->from[i][j][0] = radius + (st->from[i][j][0]-radius)*r; + st->from[i][j][1] = radius + (st->from[i][j][1]-radius)*r; + } + } else { /* default is to magnify */ + r = sin(d*M_PI_2); + + /* raising r to different power here gives different amounts of + * distortion, a negative value sucks everything into a black hole + */ + /* r = r*r; */ + if (st->blackhole && r != 0) /* blackhole effect */ + r = 1/r; + /* bubble effect (and blackhole) */ + st->from[i][j][0] = radius + (i-radius)*r; + st->from[i][j][1] = radius + (j-radius)*r; + } + } else { /* not inside loop */ + st->from[i][j][0] = i; + st->from[i][j][1] = j; + } + } + } + + /* this is really just a quick hack to keep both the compability mode with all depths and still + * allow the custom optimized draw routines with the minimum amount of work */ + if (0 != st->bpp_size) { + convert(st); + } +} + +#ifndef EXIT_FAILURE +# define EXIT_FAILURE -1 +#endif + +static void allocate_lense(struct state *st) +{ + int i, j; + int s = ((0 != st->bpp_size) ? (st->buffer_map->bytes_per_line/st->bpp_size) : (2*st->radius+st->speed+2)); + /* maybe this should be redone so that from[][][] is in one block; + * then pointers could be used instead of arrays in some places (and + * maybe give a speedup - maybe also consume less memory) + */ + st->from = (int ***)malloc(s*sizeof(int **)); + if (st->from == NULL) { + perror("distort"); + exit(EXIT_FAILURE); + } + for (i = 0; i < s; i++) { + st->from[i] = (int **)malloc((2*st->radius+st->speed+2) * sizeof(int *)); + if (st->from[i] == NULL) { + perror("distort"); + exit(EXIT_FAILURE); + } + for (j = 0; j < s; j++) { + st->from[i][j] = (int *)malloc(2 * sizeof(int)); + if (st->from[i][j] == NULL) { + perror("distort"); + exit(EXIT_FAILURE); + } + } + } +} + +/* from_array in an array containing precalculated from matrices, + * this is a double faced mem vs speed trade, it's faster, but eats + * _a lot_ of mem for large radius (is there a bug here? I can't see it) + */ +static void init_round_lense(struct state *st) +{ + int k; + + if (st->effect == &swamp_thing) { + st->from_array = (int ****)malloc((st->radius+1)*sizeof(int ***)); + for (k=0; k <= st->radius; k++) { + allocate_lense(st); + make_round_lense(st, st->radius, k); + st->from_array[k] = st->from; + } + } else { /* just allocate one from[][][] */ + allocate_lense(st); + make_round_lense(st, st->radius,st->radius); + } +} + +/* If fast_draw_8, fast_draw_16 or fast_draw_32 are to be used, the following properties + * of the src and dest XImages must hold (otherwise the generic, slooow, method provided + * by X is to be used): + * src->byte_order == dest->byte_order + * src->format == ZPixmap && dest->format == ZPixmap + * src->depth == dest->depth == the depth the function in question asumes + * x and y is the coordinates in src from where to cut out the image from, + * distort_matrix is a precalculated array of how to distort the matrix + */ + +static void fast_draw_8(struct state *st, XImage *src, XImage *dest, int x, int y, int *distort_matrix) +{ + CARD8 *u = (CARD8 *)dest->data; + CARD8 *t = (CARD8 *)src->data + x + y*src->bytes_per_line/sizeof(CARD8); + + while (u < (CARD8 *)(dest->data + sizeof(CARD8)*dest->height + *dest->bytes_per_line/sizeof(CARD8))) { + *u++ = t[*distort_matrix++]; + } +} + +static void fast_draw_16(struct state *st, XImage *src, XImage *dest, int x, int y, int *distort_matrix) +{ + CARD16 *u = (CARD16 *)dest->data; + CARD16 *t = (CARD16 *)src->data + x + y*src->bytes_per_line/sizeof(CARD16); + + while (u < (CARD16 *)(dest->data + sizeof(CARD16)*dest->height + *dest->bytes_per_line/sizeof(CARD16))) { + *u++ = t[*distort_matrix++]; + } +} + +static void fast_draw_32(struct state *st, XImage *src, XImage *dest, int x, int y, int *distort_matrix) +{ + CARD32 *u = (CARD32 *)dest->data; + CARD32 *t = (CARD32 *)src->data + x + y*src->bytes_per_line/sizeof(CARD32); + + while (u < (CARD32 *)(dest->data + sizeof(CARD32)*dest->height + *dest->bytes_per_line/sizeof(CARD32))) { + *u++ = t[*distort_matrix++]; + } +} + +static void generic_draw(struct state *st, XImage *src, XImage *dest, int x, int y, int *distort_matrix) +{ + int i, j; + for (i = 0; i < dest->width; i++) + for (j = 0; j < dest->height; j++) + if (st->from[i][j][0] + x >= 0 && + st->from[i][j][0] + x < src->width && + st->from[i][j][1] + y >= 0 && + st->from[i][j][1] + y < src->height) + XPutPixel(dest, i, j, + XGetPixel(src, + st->from[i][j][0] + x, + st->from[i][j][1] + y)); +} + +/* generate an XImage of from[][][] and draw it on the screen */ +static void plain_draw(struct state *st, int k) +{ + if (st->xy_coo[k].x+2*st->radius+st->speed+2 > st->orig_map->width || + st->xy_coo[k].y+2*st->radius+st->speed+2 > st->orig_map->height) + return; + + st->draw_routine(st, st->orig_map, st->buffer_map, st->xy_coo[k].x, st->xy_coo[k].y, st->fast_from); + +# ifdef HAVE_XSHM_EXTENSION + if (st->use_shm) + XShmPutImage(st->dpy, st->window, st->gc, st->buffer_map, 0, 0, st->xy_coo[k].x, st->xy_coo[k].y, + 2*st->radius+st->speed+2, 2*st->radius+st->speed+2, False); + else + + if (!st->use_shm) +# endif + XPutImage(st->dpy, st->window, st->gc, st->buffer_map, 0, 0, st->xy_coo[k].x, st->xy_coo[k].y, + 2*st->radius+st->speed+2, 2*st->radius+st->speed+2); + +} + + +/* generate an XImage from the reflect algoritm submitted by + * Randy Zack + * draw really got too big and ugly so I split it up + * it should be possible to use the from[][] to speed it up + * (once I figure out the algorithm used :) + */ +static void reflect_draw(struct state *st, int k) +{ + int i, j; + int cx, cy; + int ly, lysq, lx, ny, dist, rsq = st->radius * st->radius; + + cx = cy = st->radius; + if (st->xy_coo[k].ymove > 0) + cy += st->speed; + if (st->xy_coo[k].xmove > 0) + cx += st->speed; + + for(i = 0 ; i < 2*st->radius+st->speed+2; i++) { + ly = i - cy; + lysq = ly * ly; + ny = st->xy_coo[k].y + i; + if (ny >= st->orig_map->height) ny = st->orig_map->height-1; + for(j = 0 ; j < 2*st->radius+st->speed+2 ; j++) { + lx = j - cx; + dist = lx * lx + lysq; + if (dist > rsq || + ly < -st->radius || ly > st->radius || + lx < -st->radius || lx > st->radius) + XPutPixel( st->buffer_map, j, i, + XGetPixel( st->orig_map, st->xy_coo[k].x + j, ny )); + else if (dist == 0) + XPutPixel( st->buffer_map, j, i, st->black_pixel ); + else { + int x = st->xy_coo[k].x + cx + (lx * rsq / dist); + int y = st->xy_coo[k].y + cy + (ly * rsq / dist); + if (x < 0 || x >= st->xgwa.width || + y < 0 || y >= st->xgwa.height) + XPutPixel( st->buffer_map, j, i, st->black_pixel ); + else + XPutPixel( st->buffer_map, j, i, + XGetPixel( st->orig_map, x, y )); + } + } + } + + XPutImage(st->dpy, st->window, st->gc, st->buffer_map, 0, 0, st->xy_coo[k].x, st->xy_coo[k].y, + 2*st->radius+st->speed+2, 2*st->radius+st->speed+2); +} + +/* create a new, random coordinate, that won't interfer with any other + * coordinates, as the drawing routines would be significantly slowed + * down if they were to handle serveral layers of distortions + */ +static void new_rnd_coo(struct state *st, int k) +{ + int i; + + st->xy_coo[k].x = (random() % (st->xgwa.width-2*st->radius)); + st->xy_coo[k].y = (random() % (st->xgwa.height-2*st->radius)); + + for (i = 0; i < st->number; i++) { + if (i != k) { + if ((abs(st->xy_coo[k].x - st->xy_coo[i].x) <= 2*st->radius+st->speed+2) + && (abs(st->xy_coo[k].y - st->xy_coo[i].y) <= 2*st->radius+st->speed+2)) { + st->xy_coo[k].x = (random() % (st->xgwa.width-2*st->radius)); + st->xy_coo[k].y = (random() % (st->xgwa.height-2*st->radius)); + i=-1; /* ugly */ + } + } + } +} + +/* move lens and handle bounces with walls and other lenses */ +static void move_lense(struct state *st, int k) +{ + int i; + + if (st->xy_coo[k].x + 2*st->radius + st->speed + 2 >= st->xgwa.width) + st->xy_coo[k].xmove = -abs(st->xy_coo[k].xmove); + if (st->xy_coo[k].x <= st->speed) + st->xy_coo[k].xmove = abs(st->xy_coo[k].xmove); + if (st->xy_coo[k].y + 2*st->radius + st->speed + 2 >= st->xgwa.height) + st->xy_coo[k].ymove = -abs(st->xy_coo[k].ymove); + if (st->xy_coo[k].y <= st->speed) + st->xy_coo[k].ymove = abs(st->xy_coo[k].ymove); + + st->xy_coo[k].x = st->xy_coo[k].x + st->xy_coo[k].xmove; + st->xy_coo[k].y = st->xy_coo[k].y + st->xy_coo[k].ymove; + + /* bounce against othe lenses */ + for (i = 0; i < st->number; i++) { + if ((i != k) + +/* This commented test is for rectangular lenses (not currently used) and + * the one used is for circular ones + && (abs(xy_coo[k].x - xy_coo[i].x) <= 2*radius) + && (abs(xy_coo[k].y - xy_coo[i].y) <= 2*radius)) { */ + + && ((st->xy_coo[k].x - st->xy_coo[i].x)*(st->xy_coo[k].x - st->xy_coo[i].x) + + (st->xy_coo[k].y - st->xy_coo[i].y)*(st->xy_coo[k].y - st->xy_coo[i].y) + <= 2*st->radius*2*st->radius)) { + + int x, y; + x = st->xy_coo[k].xmove; + y = st->xy_coo[k].ymove; + st->xy_coo[k].xmove = st->xy_coo[i].xmove; + st->xy_coo[k].ymove = st->xy_coo[i].ymove; + st->xy_coo[i].xmove = x; + st->xy_coo[i].ymove = y; + } + } + +} + +/* make xy_coo[k] grow/shrink */ +static void swamp_thing(struct state *st, int k) +{ + if (st->xy_coo[k].r >= st->radius) + st->xy_coo[k].r_change = -abs(st->xy_coo[k].r_change); + + if (st->xy_coo[k].r <= 0) { + st->from = st->from_array[0]; + st->draw(st,k); + st->xy_coo[k].r_change = abs(st->xy_coo[k].r_change); + new_rnd_coo(st,k); + st->xy_coo[k].r=st->xy_coo[k].r_change; + return; + } + + st->xy_coo[k].r = st->xy_coo[k].r + st->xy_coo[k].r_change; + + if (st->xy_coo[k].r >= st->radius) + st->xy_coo[k].r = st->radius; + if (st->xy_coo[k].r <= 0) + st->xy_coo[k].r=0; + + st->from = st->from_array[st->xy_coo[k].r]; +} + + +static unsigned long +distort_draw (Display *dpy, Window window, void *closure) +{ + struct state *st = (struct state *) closure; + int k; + + if (st->img_loader) /* still loading */ + { + st->img_loader = load_image_async_simple (st->img_loader, 0, 0, 0, 0, 0); + if (! st->img_loader) { /* just finished */ + distort_finish_loading (st); + } + return st->delay; + } + + if (!st->img_loader && + st->start_time + st->duration < time ((time_t) 0)) { + st->img_loader = load_image_async_simple (0, st->xgwa.screen, st->window, + st->window, 0, 0); + return st->delay; + } + + for (k = 0; k < st->number; k++) { + st->effect(st,k); + st->draw(st,k); + } + return st->delay; +} + +static void +distort_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); + /* XClearWindow (dpy, window); */ + /* Why doesn't this work? */ + XPutImage (st->dpy, st->window, st->gc, st->orig_map, + 0, 0, st->orig_map->width, st->orig_map->height, 0, 0); +} + +static Bool +distort_event (Display *dpy, Window window, void *closure, XEvent *event) +{ + return False; +} + +static void +distort_free (Display *dpy, Window window, void *closure) +{ + struct state *st = (struct state *) closure; + XFreeGC (st->dpy, st->gc); + if (st->orig_map) XDestroyImage (st->orig_map); + if (st->buffer_map) XDestroyImage (st->buffer_map); + if (st->from) free (st->from); + if (st->fast_from) free (st->fast_from); + if (st->from_array) free (st->from_array); + free (st); +} + + + + +static const char *distort_defaults [] = { + "*dontClearRoot: True", + "*background: Black", + "*fpsSolid: true", +#ifdef __sgi /* really, HAVE_READ_DISPLAY_EXTENSION */ + "*visualID: Best", +#endif + + "*delay: 20000", + "*duration: 120", + "*radius: 0", + "*speed: 0", + "*number: 0", + "*slow: False", + "*vortex: False", + "*magnify: False", + "*reflect: False", + "*blackhole: False", + "*effect: none", +#ifdef HAVE_XSHM_EXTENSION + "*useSHM: False", /* xshm turns out not to help. */ +#endif /* HAVE_XSHM_EXTENSION */ + 0 +}; + +static XrmOptionDescRec distort_options [] = { + { "-delay", ".delay", XrmoptionSepArg, 0 }, + { "-duration", ".duration", XrmoptionSepArg, 0 }, + { "-radius", ".radius", XrmoptionSepArg, 0 }, + { "-speed", ".speed", XrmoptionSepArg, 0 }, + { "-number", ".number", XrmoptionSepArg, 0 }, + + { "-effect", ".effect", XrmoptionSepArg, 0 }, + { "-swamp", ".effect", XrmoptionNoArg, "swamp" }, + { "-bounce", ".effect", XrmoptionNoArg, "bounce" }, + + { "-reflect", ".reflect", XrmoptionNoArg, "True" }, + { "-vortex", ".vortex", XrmoptionNoArg, "True" }, + { "-magnify", ".magnify", XrmoptionNoArg, "True" }, + { "-blackhole", ".blackhole", XrmoptionNoArg, "True" }, + { "-slow", ".slow", XrmoptionNoArg, "True" }, +#ifdef HAVE_XSHM_EXTENSION + { "-shm", ".useSHM", XrmoptionNoArg, "True" }, + { "-no-shm", ".useSHM", XrmoptionNoArg, "False" }, +#endif /* HAVE_XSHM_EXTENSION */ + { 0, 0, 0, 0 } +}; + +XSCREENSAVER_MODULE ("Distort", distort) diff --git a/hacks/distort.man b/hacks/distort.man new file mode 100644 index 00000000..eedb924e --- /dev/null +++ b/hacks/distort.man @@ -0,0 +1,137 @@ +.TH XScreenSaver 1 "17-Oct-99" "X Version 11" +.SH NAME +distort \- distort the content of the screen in interesting ways +.SH SYNOPSIS +.B distort +[\-root] [\-window] [\-mono] [\-install] [\-noinstall] [\-visual \fIvisual\fP] +[\-window\-id \fIwindow\-id\fP] +[\-delay \fIusecs\fP] +[\-duration \fIsecs\fP] +[\-radius \fIpixels\fP] +[\-speed \fIint\fP] +[\-number \fIint\fP] +[\-swamp] +[\-bounce] +[\-reflect] +[\-vortex] +[\-magnify] +[\-blackhole] +[\-slow] +[\-shm] [\-no\-shm] +[\-fps] +.SH DESCRIPTION +The \fIdistort\fP program takes an image and lets circular zones of +distortion wander randomly around it, distorting what is under them. +The mode of distortion and the overall behaviour of the zones can be +influenced in various ways. + +The image that it manipulates will be grabbed from the portion of +the screen underlying the window, or from the system's video input, +or from a random file on disk, as indicated by +the \fIgrabDesktopImages\fP, \fIgrabVideoFrames\fP, +and \fIchooseRandomImages\fP options in the \fI~/.xscreensaver\fP +file; see +.BR xscreensaver-demo (1) +for more details. +.SH OPTIONS +.I distort +accepts the following options: +.TP 8 +.B \-root +Draw on the root window. +.TP 8 +.B \-window +Draw on a newly-created window. This is the default. +.TP 8 +.B \-mono +If on a color display, pretend we're on a monochrome display. +.TP 8 +.B \-install +Install a private colormap for the window. +.TP 8 +.B \-noinstall +Don't install a private colormap for the window. +.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\-id \fIwindow\-id\fP +Specify which window id to use. +.TP 8 +.B \-delay \fIusecs\fP +Specify the delay between subsequent animation frames in microseconds. +.TP 8 +.B \-duration \fIseconds\fP +How long to run before loading a new image. Default 120 seconds. +.TP 8 +.B \-radius \fIpixels\fP +Specify the radius of the distortion zone in pixels. +.TP 8 +.B \-speed \fIint\fP +Specify the speed at which the distortion zone moves, where 0 is slow, +higher numbers are faster (10 is pretty fast.) +.TP 8 +.B \-number \fIint\fP +Specify the number of distortion zones. +.TP 8 +.B \-swamp +Instead of letting zones wander around, let small zones pop up like +bubbles in a swamp and leave permanent distortion. \fBWARNING:\fP +this option uses a \fIcolossal\fP amount of memory: keep the \fI\-radius\fP +small when using \fI\-swamp\fP. +.TP 8 +.B \-bounce +Let zones wander around and bounce off the window border. This is the +default. +.TP 8 +.B \-reflect +Mode of distortion that resembles reflection by a cylindrical mirror. +.TP 8 +.B \-vortex +Whirlpool-shaped distortion. Way cool. +.TP 8 +.B \-magnify +This mode of distortion looks like a magnifying glass. +.TP 8 +.B \-blackhole +Suck your pixels beyond the event horizon. Favourite mode of Dr +Stephen Hawking. +.TP 8 +.B \-slow +Make the zone wander slower. +.TP 8 +.B \-shm +Use shared memory extension. +.TP 8 +.B \-no\-shm +Don't use shared memory extension. +.TP 8 +.B \-fps +Display the current frame rate and CPU load. +.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), +.BR xscreensaver\-demo (1), +.BR xscreensaver\-getimage (1) +.SH COPYRIGHT +Copyright \(co 1998 by Jonas Munsin 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 AUTHORS +Jonas Munsin and Jamie Zawinski . +This manual page by Matthias Warkus , 17-Oct-1999. diff --git a/hacks/drift.c b/hacks/drift.c new file mode 100644 index 00000000..711bc09e --- /dev/null +++ b/hacks/drift.c @@ -0,0 +1,701 @@ +/* -*- Mode: C; tab-width: 4 -*- */ +/* drift --- drifting recursive fractal cosmic flames */ + +#if 0 +static const char sccsid[] = "@(#)drift.c 5.00 2000/11/01 xlockmore"; +#endif + +/*- + * Copyright (c) 1991 by Patrick J. Naughton. + * + * Permission to use, copy, modify, and distribute this software and its + * documentation for any purpose and without fee is hereby granted, + * provided that the above copyright notice appear in all copies and that + * both that copyright notice and this permission notice appear in + * supporting documentation. + * + * This file is provided AS IS with no warranties of any kind. The author + * shall have no liability with respect to the infringement of copyrights, + * trade secrets or any patents by this file or any part thereof. In no + * event will the author be liable for any lost revenue or profits or + * other special, indirect and consequential damages. + * + * Revision History: + * 01-Nov-2000: Allocation checks + * 10-May-1997: Jamie Zawinski compatible with xscreensaver + * 01-Jan-1997: Moved new flame to drift. Compile time options now run time. + * 01-Jun-1995: Updated by Scott Draves. + * 27-Jun-1991: vary number of functions used. + * 24-Jun-1991: fixed portability problem with integer mod (%). + * 06-Jun-1991: Written, received from Scott Draves + */ + +#ifdef STANDALONE +# define MODE_drift +# define DEFAULTS "*delay: 10000 \n" \ + "*count: 30 \n" \ + "*ncolors: 200 \n" \ + "*fpsSolid: true \n" \ + +# define SMOOTH_COLORS +# define drift_handle_event 0 +# include "xlockmore.h" /* in xscreensaver distribution */ +# include "erase.h" +#else /* STANDALONE */ +# define ENTRYPOINT /**/ +# include "xlock.h" /* in xlockmore distribution */ +#endif /* STANDALONE */ + +#ifdef MODE_drift + +#define DEF_GROW "False" /* Grow fractals instead of animating one at a time, + would then be like flame */ +#define DEF_LISS "False" /* if this is defined then instead of a point + bouncing around in a high dimensional sphere, we + use lissojous figures. Only makes sense if + grow is false. */ + +static Bool grow; +static Bool liss; + +static XrmOptionDescRec opts[] = +{ + {"-grow", ".drift.grow", XrmoptionNoArg, "on"}, + {"+grow", ".drift.grow", XrmoptionNoArg, "off"}, + {"-liss", ".drift.trail", XrmoptionNoArg, "on"}, + {"+liss", ".drift.trail", XrmoptionNoArg, "off"} +}; +static argtype vars[] = +{ + {&grow, "grow", "Grow", DEF_GROW, t_Bool}, + {&liss, "trail", "Trail", DEF_LISS, t_Bool} +}; +static OptionStruct desc[] = +{ + {"-/+grow", "turn on/off growing fractals, else they are animated"}, + {"-/+liss", "turn on/off using lissojous figures to get points"} +}; + +ENTRYPOINT ModeSpecOpt drift_opts = +{sizeof opts / sizeof opts[0], opts, sizeof vars / sizeof vars[0], vars, desc}; + +#ifdef USE_MODULES +ModStruct drift_description = +{"drift", "init_drift", "draw_drift", "release_drift", + "refresh_drift", "init_drift", (char *) NULL, &drift_opts, + 10000, 30, 1, 1, 64, 1.0, "", + "Shows cosmic drifting flame fractals", 0, NULL}; + +#endif + +#define MAXBATCH1 200 /* mono */ +#define MAXBATCH2 20 /* color */ +#define FUSE 10 /* discard this many initial iterations */ +#define NMAJORVARS 7 +#define MAXLEV 10 + +typedef struct { + /* shape of current flame */ + int nxforms; + double f[2][3][MAXLEV]; /* a bunch of non-homogeneous xforms */ + int variation[10]; /* for each xform */ + + /* Animation */ + double df[2][3][MAXLEV]; + + /* high-level control */ + int mode; /* 0->slow/single 1->fast/many */ + int nfractals; /* draw this many fractals */ + int major_variation; + int fractal_len; /* pts/fractal */ + int color; + int rainbow; /* more than one color per fractal + 1-> computed by adding dimension to fractal */ + + int width, height; /* of window */ + int timer; + + /* draw info about current flame */ + int fuse; /* iterate this many before drawing */ + int total_points; /* draw this many pts before fractal ends */ + int npoints; /* how many we've computed but not drawn */ + XPoint pts[MAXBATCH1]; /* here they are */ + unsigned long pixcol; + /* when drawing in color, we have a buffer per color */ + int *ncpoints; + XPoint *cpts; + + double x, y, c; + int liss_time; + Bool grow, liss; + + short lasthalf; + long saved_random_bits; + int nbits; + +#ifdef STANDALONE + int erase_countdown; + eraser_state *eraser; +#endif +} driftstruct; + +static driftstruct *drifts = (driftstruct *) NULL; + +static short +halfrandom(driftstruct * dp, int mv) +{ + unsigned long r; + + if (dp->lasthalf) { + r = dp->lasthalf; + dp->lasthalf = 0; + } else { + r = LRAND(); + dp->lasthalf = (short) (r >> 16); + } + r = r % mv; + return r; +} + +static int +frandom(driftstruct * dp, int n) +{ + int result; + + if (3 > dp->nbits) { + dp->saved_random_bits = LRAND(); + dp->nbits = 31; + } + switch (n) { + case 2: + result = (int) (dp->saved_random_bits & 1); + dp->saved_random_bits >>= 1; + dp->nbits -= 1; + return result; + + case 3: + result = (int) (dp->saved_random_bits & 3); + dp->saved_random_bits >>= 2; + dp->nbits -= 2; + if (3 == result) + return frandom(dp, 3); + return result; + + case 4: + result = (int) (dp->saved_random_bits & 3); + dp->saved_random_bits >>= 2; + dp->nbits -= 2; + return result; + + case 5: + result = (int) (dp->saved_random_bits & 7); + dp->saved_random_bits >>= 3; + dp->nbits -= 3; + if (4 < result) + return frandom(dp, 5); + return result; + default: + (void) fprintf(stderr, "bad arg to frandom\n"); + } + return 0; +} + +#define DISTRIB_A (halfrandom(dp, 7000) + 9000) +#define DISTRIB_B ((frandom(dp, 3) + 1) * (frandom(dp, 3) + 1) * 120000) +#define LEN(x) (sizeof(x)/sizeof((x)[0])) + +static void +initmode(ModeInfo * mi, int mode) +{ + driftstruct *dp = &drifts[MI_SCREEN(mi)]; + +#define VARIATION_LEN 14 + + dp->mode = mode; + + dp->major_variation = halfrandom(dp, VARIATION_LEN); + /* 0, 0, 1, 1, 2, 2, 3, 4, 4, 5, 5, 6, 6, 6 */ + dp->major_variation = ((dp->major_variation >= VARIATION_LEN >> 1) && + (dp->major_variation < VARIATION_LEN - 1)) ? + (dp->major_variation + 1) >> 1 : dp->major_variation >> 1; + + if (dp->grow) { + dp->rainbow = 0; + if (mode) { + if (!dp->color || halfrandom(dp, 8)) { + dp->nfractals = halfrandom(dp, 30) + 5; + dp->fractal_len = DISTRIB_A; + } else { + dp->nfractals = halfrandom(dp, 5) + 5; + dp->fractal_len = DISTRIB_B; + } + } else { + dp->rainbow = dp->color; + dp->nfractals = 1; + dp->fractal_len = DISTRIB_B; + } + } else { + dp->nfractals = 1; + dp->rainbow = dp->color; + dp->fractal_len = 2000000; + } + dp->fractal_len = (dp->fractal_len * MI_COUNT(mi)) / 20; + +#ifndef STANDALONE + MI_CLEARWINDOW(mi); +#endif +} + +static void +pick_df_coefs(ModeInfo * mi) +{ + driftstruct *dp = &drifts[MI_SCREEN(mi)]; + int i, j, k; + double r; + + for (i = 0; i < dp->nxforms; i++) { + + r = 1e-6; + for (j = 0; j < 2; j++) + for (k = 0; k < 3; k++) { + dp->df[j][k][i] = ((double) halfrandom(dp, 1000) / 500.0 - 1.0); + r += dp->df[j][k][i] * dp->df[j][k][i]; + } + r = (3 + halfrandom(dp, 5)) * 0.01 / sqrt(r); + for (j = 0; j < 2; j++) + for (k = 0; k < 3; k++) + dp->df[j][k][i] *= r; + } +} + +static void +free_drift(driftstruct *dp) +{ + if (dp->ncpoints != NULL) { + (void) free((void *) dp->ncpoints); + dp->ncpoints = (int *) NULL; + } + if (dp->cpts != NULL) { + (void) free((void *) dp->cpts); + dp->cpts = (XPoint *) NULL; + } +} + +static void +initfractal(ModeInfo * mi) +{ + driftstruct *dp = &drifts[MI_SCREEN(mi)]; + int i, j, k; + +#define XFORM_LEN 9 + + dp->fuse = FUSE; + dp->total_points = 0; + + if (!dp->ncpoints) { + if ((dp->ncpoints = (int *) malloc(sizeof (int) * MI_NCOLORS(mi))) == + NULL) { + free_drift(dp); + return; + } + } + if (!dp->cpts) { + if ((dp->cpts = (XPoint *) malloc(MAXBATCH2 * sizeof (XPoint) * + MI_NCOLORS(mi))) == NULL) { + free_drift(dp); + return; + } + } + + if (dp->rainbow) + for (i = 0; i < MI_NPIXELS(mi); i++) + dp->ncpoints[i] = 0; + else + dp->npoints = 0; + dp->nxforms = halfrandom(dp, XFORM_LEN); + /* 2, 2, 2, 3, 3, 3, 4, 4, 5 */ + dp->nxforms = (dp->nxforms >= XFORM_LEN - 1) + dp->nxforms / 3 + 2; + + dp->c = dp->x = dp->y = 0.0; + if (dp->liss && !halfrandom(dp, 10)) { + dp->liss_time = 0; + } + if (!dp->grow) + pick_df_coefs(mi); + for (i = 0; i < dp->nxforms; i++) { + if (NMAJORVARS == dp->major_variation) + dp->variation[i] = halfrandom(dp, NMAJORVARS); + else + dp->variation[i] = dp->major_variation; + for (j = 0; j < 2; j++) + for (k = 0; k < 3; k++) { + if (dp->liss) + dp->f[j][k][i] = sin(dp->liss_time * dp->df[j][k][i]); + else + dp->f[j][k][i] = ((double) halfrandom(dp, 1000) / 500.0 - 1.0); + } + } + if (dp->color) + dp->pixcol = MI_PIXEL(mi, halfrandom(dp, MI_NPIXELS(mi))); + else + dp->pixcol = MI_WHITE_PIXEL(mi); + +} + + +ENTRYPOINT void +init_drift(ModeInfo * mi) +{ + driftstruct *dp; + + if (drifts == NULL) { + if ((drifts = (driftstruct *) calloc(MI_NUM_SCREENS(mi), + sizeof (driftstruct))) == NULL) + return; + } + dp = &drifts[MI_SCREEN(mi)]; + + dp->width = MI_WIDTH(mi); + dp->height = MI_HEIGHT(mi); + dp->color = MI_NPIXELS(mi) > 2; + + if (MI_IS_FULLRANDOM(mi)) { + if (NRAND(3) == 0) + dp->grow = True; + else { + dp->grow = False; + dp->liss = (Bool) (LRAND() & 1); + } + } else { + dp->grow = grow; + if (dp->grow) + dp->liss = False; + else + dp->liss = liss; + } + initmode(mi, 1); + initfractal(mi); +} + +static void +iter(driftstruct * dp) +{ + int i = frandom(dp, dp->nxforms); + double nx, ny, nc; + + + if (i) + nc = (dp->c + 1.0) / 2.0; + else + nc = dp->c / 2.0; + + nx = dp->f[0][0][i] * dp->x + dp->f[0][1][i] * dp->y + dp->f[0][2][i]; + ny = dp->f[1][0][i] * dp->x + dp->f[1][1][i] * dp->y + dp->f[1][2][i]; + + + switch (dp->variation[i]) { + case 1: + /* sinusoidal */ + nx = sin(nx); + ny = sin(ny); + break; + case 2: + { + /* complex */ + double r2 = nx * nx + ny * ny + 1e-6; + + nx = nx / r2; + ny = ny / r2; + break; + } + case 3: + /* bent */ + if (nx < 0.0) + nx = nx * 2.0; + if (ny < 0.0) + ny = ny / 2.0; + break; + case 4: + { + /* swirl */ + + double r = (nx * nx + ny * ny); /* times k here is fun */ + double c1 = sin(r); + double c2 = cos(r); + double t = nx; + + if (nx > 1e4 || nx < -1e4 || ny > 1e4 || ny < -1e4) + ny = 1e4; + else + ny = c2 * t + c1 * ny; + nx = c1 * nx - c2 * ny; + break; + } + case 5: + { + /* horseshoe */ + double r, c1, c2, t; + + /* Avoid atan2: DOMAIN error message */ + if (nx == 0.0 && ny == 0.0) + r = 0.0; + else + r = atan2(nx, ny); /* times k here is fun */ + c1 = sin(r); + c2 = cos(r); + t = nx; + + nx = c1 * nx - c2 * ny; + ny = c2 * t + c1 * ny; + break; + } + case 6: + { + /* drape */ + double t; + + /* Avoid atan2: DOMAIN error message */ + if (nx == 0.0 && ny == 0.0) + t = 0.0; + else + t = atan2(nx, ny) / M_PI; + + if (nx > 1e4 || nx < -1e4 || ny > 1e4 || ny < -1e4) + ny = 1e4; + else + ny = sqrt(nx * nx + ny * ny) - 1.0; + nx = t; + break; + } + } + +#if 0 + /* here are some others */ + { + /* broken */ + if (nx > 1.0) + nx = nx - 1.0; + if (nx < -1.0) + nx = nx + 1.0; + if (ny > 1.0) + ny = ny - 1.0; + if (ny < -1.0) + ny = ny + 1.0; + break; + } + { + /* complex sine */ + double u = nx, v = ny; + double ev = exp(v); + double emv = exp(-v); + + nx = (ev + emv) * sin(u) / 2.0; + ny = (ev - emv) * cos(u) / 2.0; + } + { + + /* polynomial */ + if (nx < 0) + nx = -nx * nx; + else + nx = nx * nx; + + if (ny < 0) + ny = -ny * ny; + else + ny = ny * ny; + } + { + /* spherical */ + double r = 0.5 + sqrt(nx * nx + ny * ny + 1e-6); + + nx = nx / r; + ny = ny / r; + } + { + nx = atan(nx) / M_PI_2 + ny = atan(ny) / M_PI_2 + } +#endif + + /* how to check nan too? some machines don't have finite(). + don't need to check ny, it'll propogate */ + if (nx > 1e4 || nx < -1e4) { + nx = halfrandom(dp, 1000) / 500.0 - 1.0; + ny = halfrandom(dp, 1000) / 500.0 - 1.0; + dp->fuse = FUSE; + } + dp->x = nx; + dp->y = ny; + dp->c = nc; + +} + +static void +draw(ModeInfo * mi, driftstruct * dp, Drawable d) +{ + Display *display = MI_DISPLAY(mi); + GC gc = MI_GC(mi); + double x = dp->x; + double y = dp->y; + int fixed_x, fixed_y, npix, c, n; + + if (dp->fuse) { + dp->fuse--; + return; + } + if (!(x > -1.0 && x < 1.0 && y > -1.0 && y < 1.0)) + return; + + fixed_x = (int) ((dp->width / 2) * (x + 1.0)); + fixed_y = (int) ((dp->height / 2) * (y + 1.0)); + + if (!dp->rainbow) { + + dp->pts[dp->npoints].x = fixed_x; + dp->pts[dp->npoints].y = fixed_y; + dp->npoints++; + if (dp->npoints == MAXBATCH1) { + XSetForeground(display, gc, dp->pixcol); + XDrawPoints(display, d, gc, dp->pts, dp->npoints, CoordModeOrigin); + dp->npoints = 0; + } + } else { + + npix = MI_NPIXELS(mi); + c = (int) (dp->c * npix); + + if (c < 0) + c = 0; + if (c >= npix) + c = npix - 1; + n = dp->ncpoints[c]; + dp->cpts[c * MAXBATCH2 + n].x = fixed_x; + dp->cpts[c * MAXBATCH2 + n].y = fixed_y; + if (++dp->ncpoints[c] == MAXBATCH2) { + XSetForeground(display, gc, MI_PIXEL(mi, c)); + XDrawPoints(display, d, gc, &(dp->cpts[c * MAXBATCH2]), + dp->ncpoints[c], CoordModeOrigin); + dp->ncpoints[c] = 0; + } + } +} + +static void +draw_flush(ModeInfo * mi, driftstruct * dp, Drawable d) +{ + Display *display = MI_DISPLAY(mi); + GC gc = MI_GC(mi); + + if (dp->rainbow) { + int npix = MI_NPIXELS(mi); + int i; + + for (i = 0; i < npix; i++) { + if (dp->ncpoints[i]) { + XSetForeground(display, gc, MI_PIXEL(mi, i)); + XDrawPoints(display, d, gc, &(dp->cpts[i * MAXBATCH2]), + dp->ncpoints[i], CoordModeOrigin); + dp->ncpoints[i] = 0; + } + } + } else { + if (dp->npoints) + XSetForeground(display, gc, dp->pixcol); + XDrawPoints(display, d, gc, dp->pts, + dp->npoints, CoordModeOrigin); + dp->npoints = 0; + } +} + + +ENTRYPOINT void +draw_drift(ModeInfo * mi) +{ + Window window = MI_WINDOW(mi); + driftstruct *dp; + + if (drifts == NULL) + return; + dp = &drifts[MI_SCREEN(mi)]; + if (dp->ncpoints == NULL) + return; + + if (dp->erase_countdown) { + if (!--dp->erase_countdown) { + dp->eraser = erase_window (MI_DISPLAY(mi), MI_WINDOW(mi), dp->eraser); + } + return; + } + if (dp->eraser) { + dp->eraser = erase_window (MI_DISPLAY(mi), MI_WINDOW(mi), dp->eraser); + return; + } + + MI_IS_DRAWN(mi) = True; + dp->timer = 3000; + while (dp->timer) { + iter(dp); + draw(mi, dp, window); + if (dp->total_points++ > dp->fractal_len) { + draw_flush(mi, dp, window); + if (0 == --dp->nfractals) { +#ifdef STANDALONE + dp->erase_countdown = 4 * 1000000 / MI_PAUSE(mi); +#endif /* STANDALONE */ + initmode(mi, frandom(dp, 2)); + } + initfractal(mi); + } + dp->timer--; + } + if (!dp->grow) { + int i, j, k; + + draw_flush(mi, dp, window); + if (dp->liss) + dp->liss_time++; + for (i = 0; i < dp->nxforms; i++) + for (j = 0; j < 2; j++) + for (k = 0; k < 3; k++) { + if (dp->liss) + dp->f[j][k][i] = sin(dp->liss_time * dp->df[j][k][i]); + else { + double t = dp->f[j][k][i] += dp->df[j][k][i]; + + if (t < -1.0 || 1.0 < t) + dp->df[j][k][i] *= -1.0; + } + } + } +} + +ENTRYPOINT void +release_drift(ModeInfo * mi) +{ + if (drifts != NULL) { + int screen; + + for (screen = 0; screen < MI_NUM_SCREENS(mi); screen++) + free_drift(&drifts[screen]); + (void) free((void *) drifts); + drifts = (driftstruct *) NULL; + } +} + +ENTRYPOINT void +reshape_drift(ModeInfo * mi, int width, int height) +{ + MI_CLEARWINDOW(mi); + init_drift (mi); +} + +ENTRYPOINT void +refresh_drift(ModeInfo * mi) +{ + MI_CLEARWINDOW(mi); +} + +XSCREENSAVER_MODULE ("Drift", drift) + +#endif /* MODE_drift */ diff --git a/hacks/drift.man b/hacks/drift.man new file mode 100644 index 00000000..f0a9be88 --- /dev/null +++ b/hacks/drift.man @@ -0,0 +1,79 @@ +.TH XScreenSaver 1 "10-May-97" "X Version 11" +.SH NAME +drift - draws drifting recursive fractal cosmic flames +.SH SYNOPSIS +.B drift +[\-display \fIhost:display.screen\fP] [\-foreground \fIcolor\fP] [\-background \fIcolor\fP] [\-window] [\-root] [\-mono] [\-install] [\-visual \fIvisual\fP] [\-ncolors \fIinteger\fP] [\-delay \fImicroseconds\fP] [\-count \fIinteger\fP] [\-grow] [\-no\-grow] [\-liss] [\-no\-liss] + +[\-fps] +.SH DESCRIPTION +The \fIdrift\fP program draws drifting recursive fractal cosmic flames +.SH OPTIONS +.I drift +accepts the following options: +.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 \-mono +If on a color display, pretend we're on a monochrome display. +.TP 8 +.B \-install +Install a private colormap for the window. +.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 \-ncolors \fIinteger\fP +How many colors should be used (if possible). Default 200. +The colors used cycle through the hue, making N stops around +the color wheel. +.TP 8 +.B \-count \fIinteger\fP + +.TP 8 +.B \-grow +.TP 8 +.B \-no\-grow +Whether fractals should grow; otherwise, they are animated. + +.TP 8 +.B \-liss +.TP 8 +.B \-no\-liss +Whether we should use lissajous figures to get points. + +.TP 8 +.B \-fps +Display the current frame rate and CPU load. +.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 flame (MANSUFFIX), +.BR X (1), +.BR xscreensaver (1), +.BR xlock (1) +.SH COPYRIGHT +Copyright \(co 1991, 1995 by Scott Draves. + +Permission to use, copy, modify, and distribute this software and its +documentation for any purpose and without fee is hereby granted, +provided that the above copyright notice appear in all copies and that +both that copyright notice and this permission notice appear in +supporting documentation. +.SH AUTHOR +Scott Draves , 06-Jun-91, 01-Jun-95. + +Ability to run standalone or with \fIxscreensaver\fP added by +Jamie Zawinski , 10-May-97. diff --git a/hacks/epicycle.c b/hacks/epicycle.c new file mode 100644 index 00000000..004c0ea5 --- /dev/null +++ b/hacks/epicycle.c @@ -0,0 +1,779 @@ +/* epicycle --- The motion of a body with epicycles, as in the pre-Copernican + * cosmologies. + * + * Copyright (c) 1998 James Youngman + * + * 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. + */ + +/* Standard C headers; screenhack.h assumes that these have already + * been included if required -- for example, it defines M_PI if not + * already defined. + */ +#include +#include + + +#include "screenhack.h" +#include "erase.h" + +/* MIT-SHM headers omitted; this screenhack doesn't use it */ + + + +/*********************************************************/ +/******************** MAGIC CONSTANTS ********************/ +/*********************************************************/ +#define MIN_RADIUS (5) /* smallest allowable circle radius */ +#define FILL_PROPORTION (0.9) /* proportion of screen to fill by scaling. */ +/*********************************************************/ +/***************** END OF MAGIC CONSTANTS ****************/ +/*********************************************************/ + + + +#define FULLCIRCLE (2.0 * M_PI) /* radians in a circle. */ + + +/* Some of these resource values here are hand-tuned to give a + * pleasing variety of interesting shapes. These are not the only + * good settings, but you may find you need to change some as a group + * to get pleasing figures. + */ +static const char *epicycle_defaults [] = { + ".background: black", + ".foreground: white", + "*fpsSolid: true", + "*colors: 100", + "*color0: red", + "*delay: 20000", + "*holdtime: 2", + "*lineWidth: 4", + "*minCircles: 2", + "*maxCircles: 10", + "*minSpeed: 0.003", + "*maxSpeed: 0.005", + "*harmonics: 8", + "*timestep: 1.0", + "*timestepCoarseFactor: 1.0", /* no option for this resource. */ + "*divisorPoisson: 0.4", + "*sizeFactorMin: 1.05", + "*sizeFactorMax: 2.05", + 0 +}; + +/* options passed to this program */ +static XrmOptionDescRec epicycle_options [] = { + { "-color0", ".color0", XrmoptionSepArg, 0 }, + { "-colors", ".colors", XrmoptionSepArg, 0 }, + { "-colours", ".colors", XrmoptionSepArg, 0 }, + { "-foreground", ".foreground", XrmoptionSepArg, 0 }, + { "-delay", ".delay", XrmoptionSepArg, 0 }, + { "-holdtime", ".holdtime", XrmoptionSepArg, 0 }, + { "-linewidth", ".lineWidth", XrmoptionSepArg, 0 }, + { "-min_circles", ".minCircles", XrmoptionSepArg, 0 }, + { "-max_circles", ".maxCircles", XrmoptionSepArg, 0 }, + { "-min_speed", ".minSpeed", XrmoptionSepArg, 0 }, + { "-max_speed", ".maxSpeed", XrmoptionSepArg, 0 }, + { "-harmonics", ".harmonics", XrmoptionSepArg, 0 }, + { "-timestep", ".timestep", XrmoptionSepArg, 0 }, + { "-divisor_poisson",".divisorPoisson",XrmoptionSepArg, 0 }, + { "-size_factor_min", ".sizeFactorMin", XrmoptionSepArg, 0 }, + { "-size_factor_max", ".sizeFactorMax", XrmoptionSepArg, 0 }, + { 0, 0, 0, 0 } +}; + + +/* Each circle is centred on a point on the rim of another circle. + */ +struct tagCircle +{ + long radius; /* in pixels */ + double w; /* position (radians ccw from x-axis) */ + double initial_w; /* starting position */ + double wdot; /* rotation rate (change in w per iteration) */ + int divisor; + + struct tagCircle *pchild; +}; +typedef struct tagCircle Circle; + + +struct tagBody /* a body that moves on a system of circles. */ +{ + int x_origin, y_origin; + int x, y; + int old_x, old_y; + int current_color; /* pixel index into colors[] */ + Circle *epicycles; /* system of circles on which it moves. */ + struct tagBody *next; /* next in list. */ +}; +typedef struct tagBody Body; + + +struct state { + Display *dpy; + Window window; + GC color0; + int width, height; + int x_offset, y_offset; + int unit_pixels; + unsigned long bg; + Colormap cmap; + int restart; + double wdot_max; + XColor *colors; + int ncolors; + int color_shift_pos; /* how far we are towards that. */ + double colour_cycle_rate; + int harmonics; + double divisorPoisson; + double sizeFactorMin; + double sizeFactorMax; + int minCircles; + int maxCircles; + + Bool done; + + long L; + double T, timestep, circle, timestep_coarse; + int delay; + int uncleared; + int holdtime; + int xmax, xmin, ymax, ymin; + Body *pb0; + double xtime; + eraser_state *eraser; +}; + + + +/* Determine the GCD of two numbers using Euclid's method. The other + * possible algorighm is Stein's method, but it's probably only going + * to be much faster on machines with no divide instruction, like the + * ARM and the Z80. The former is very fast anyway and the latter + * probably won't run X clients; in any case, this calculation is not + * the bulk of the computational expense of the program. I originally + * tried using Stein's method, but I wanted to remove the gotos. Not + * wanting to introduce possible bugs, I plumped for Euclid's method + * instead. Lastly, Euclid's algorithm is preferred to the + * generalisation for N inputs. + * + * See Knuth, section 4.5.2. + */ +static int +gcd(int u, int v) /* Euclid's Method */ +{ + /* If either operand of % is negative, the sign of the result is + * implementation-defined. See section 6.3.5 "Multiplicative + * Operators" of the ANSI C Standard (page 46 [LEFT HAND PAGE!] of + * "Annotated C Standard", Osborne, ISBN 0-07-881952-0). + */ + if (u < 0) u = -u; + if (v < 0) v = -v; + + while (0 != v) + { + int r; + r = u % v; + u = v; + v = r; + } + return u; +} + +/* Determine the Lowest Common Multiple of two integers, using + * Euclid's Proposition 34, as explained in Knuth's The Art of + * Computer Programming, Vol 2, section 4.5.2. + */ +static int +lcm(int u, int v) +{ + return u / gcd(u,v) * v; +} + +static long +random_radius(struct state *st, double scale) +{ + long r; + + r = frand(scale) * st->unit_pixels/2; /* for frand() see utils/yarandom.h */ + if (r < MIN_RADIUS) + r = MIN_RADIUS; + return r; +} + + +static long +random_divisor(struct state *st) +{ + int divisor = 1; + int sign; + + while (frand(1.0) < st->divisorPoisson && divisor <= st->harmonics) + { + ++divisor; + } + sign = (frand(1.0) < 0.5) ? +1 : -1; + return sign * divisor; +} + + +/* Construct a circle or die. + */ +static Circle * +new_circle(struct state *st, double scale) +{ + Circle *p = malloc(sizeof(Circle)); + + p->radius = random_radius(st, scale); + p->w = p->initial_w = 0.0; + p->divisor = random_divisor(st); + p->wdot = st->wdot_max / p->divisor; + p->pchild = NULL; + + return p; +} + +static void delete_circle(Circle *p) +{ + free(p); +} + +static void +delete_circle_chain(Circle *p) +{ + while (p) + { + Circle *q = p->pchild; + delete_circle(p); + p = q; + } +} + +static Circle * +new_circle_chain(struct state *st) +{ + Circle *head; + double scale = 1.0, factor; + int n; + + /* Parent circles are larger than their children by a factor of at + * least FACTOR_MIN and at most FACTOR_MAX. + */ + factor = st->sizeFactorMin + frand(st->sizeFactorMax - st->sizeFactorMin); + + /* There are between minCircles and maxCircles in each figure. + */ + if (st->maxCircles == st->minCircles) + n = st->minCircles; /* Avoid division by zero. */ + else + n = st->minCircles + random() % (st->maxCircles - st->minCircles); + + head = NULL; + while (n--) + { + Circle *p = new_circle(st, scale); + p->pchild = head; + head = p; + + scale /= factor; + } + return head; +} + +static void +assign_random_common_w(Circle *p) +{ + double w_common = frand(FULLCIRCLE); /* anywhere on the circle */ + while (p) + { + p->initial_w = w_common; + p = p->pchild; + } +} + +static Body * +new_body(struct state *st) +{ + Body *p = malloc(sizeof(Body)); + if (!p) abort(); + p->epicycles = new_circle_chain(st); + p->current_color = 0; /* ?? start them all on different colors? */ + p->next = NULL; + p->x = p->y = 0; + p->old_x = p->old_y = 0; + p->x_origin = p->y_origin = 0; + + /* Start all the epicycles at the same w value to make it easier to + * figure out at what T value the cycle is closed. We don't just fix + * the initial W value because that makes all the patterns tend to + * be symmetrical about the X axis. + */ + assign_random_common_w(p->epicycles); + return p; +} + +static void +delete_body(Body *p) +{ + delete_circle_chain(p->epicycles); + free(p); +} + + +static void +draw_body(struct state *st, Body *pb, GC gc) +{ + XDrawLine(st->dpy, st->window, gc, pb->old_x, pb->old_y, pb->x, pb->y); +} + +static long +compute_divisor_lcm(Circle *p) +{ + long l = 1; + + while (p) + { + l = lcm(l, p->divisor); + p = p->pchild; + } + return l; +} + + +/* move_body() + * + * Calculate the position for the body at time T. We work in double + * rather than int to avoid the cumulative errors that would be caused + * by the rounding implicit in an assignment to int. + */ +static void +move_body(Body *pb, double t) +{ + Circle *p; + double x, y; + + pb->old_x = pb->x; + pb->old_y = pb->y; + + x = pb->x_origin; + y = pb->y_origin; + + for (p=pb->epicycles; NULL != p; p=p->pchild) + { + /* angular pos = initial_pos + time * angular speed */ + /* but this is an angular position, so modulo FULLCIRCLE. */ + p->w = fmod(p->initial_w + (t * p->wdot), FULLCIRCLE); + + x += (p->radius * cos(p->w)); + y += (p->radius * sin(p->w)); + } + + pb->x = (int)x; + pb->y = (int)y; +} + +static int +colour_init(struct state *st, XWindowAttributes *pxgwa) +{ + XGCValues gcv; + +#if 0 + int H = random() % 360; /* colour choice from attraction.c. */ + double S1 = 0.25; + double S2 = 1.00; + double V = frand(0.25) + 0.75; + int line_width = 0; +#endif + + int retval = 1; + unsigned long valuemask = 0L; + unsigned long fg; + + /* Free any already allocated colors... + */ + if (st->colors) + { + free_colors(st->dpy, st->cmap, st->colors, st->ncolors); + st->colors = 0; + st->ncolors = 0; + } + + st->ncolors = get_integer_resource (st->dpy, "colors", "Colors"); + if (0 == st->ncolors) /* English spelling? */ + st->ncolors = get_integer_resource (st->dpy, "colours", "Colors"); + + if (st->ncolors < 2) + st->ncolors = 2; + if (st->ncolors <= 2) + mono_p = True; + st->colors = 0; + + if (!mono_p) + { + st->colors = (XColor *) malloc(sizeof(*st->colors) * (st->ncolors+1)); + if (!st->colors) abort(); + + make_smooth_colormap (st->dpy, pxgwa->visual, st->cmap, st->colors, &st->ncolors, + True, /* allocate */ + False, /* not writable */ + True); /* verbose (complain about failure) */ + if (st->ncolors <= 2) + { + if (st->colors) + free (st->colors); + st->colors = 0; + mono_p = True; + } + } + + + st->bg = get_pixel_resource (st->dpy, st->cmap, "background", "Background"); + + /* Set the line width + */ + gcv.line_width = get_integer_resource (st->dpy, "lineWidth", "Integer"); + if (gcv.line_width) + { + valuemask |= GCLineWidth; + + gcv.join_style = JoinRound; + gcv.cap_style = CapRound; + + valuemask |= (GCCapStyle | GCJoinStyle); + } + + + /* Set the drawing function. + */ + gcv.function = GXcopy; + valuemask |= GCFunction; + + /* Set the foreground. + */ +/* if (mono_p)*/ + fg = get_pixel_resource (st->dpy, st->cmap, "foreground", "Foreground"); +/* WTF? +else + fg = st->bg ^ get_pixel_resource (st->dpy, st->cmap, ("color0"), "Foreground"); +*/ + gcv.foreground = fg; + valuemask |= GCForeground; + + /* Actually create the GC. + */ + st->color0 = XCreateGC (st->dpy, st->window, valuemask, &gcv); + + return retval; +} + + + + +static void +setup(struct state *st) +{ + XWindowAttributes xgwa; + + XGetWindowAttributes (st->dpy, st->window, &xgwa); + st->cmap = xgwa.colormap; + + st->width = xgwa.width; + st->height = xgwa.height; + st->x_offset = st->width / 2; + st->y_offset = st->height / 2; + st->unit_pixels = st->width < st->height ? st->width : st->height; + + { + if (!st->done) + { + colour_init(st, &xgwa); + st->done = True; + } + } +} + + +static void +color_step(struct state *st, Body *pb, double frac) +{ + if (!mono_p) + { + int newshift = st->ncolors * fmod(frac * st->colour_cycle_rate, 1.0); + if (newshift != st->color_shift_pos) + { + pb->current_color = newshift; + XSetForeground (st->dpy, st->color0, st->colors[pb->current_color].pixel); + st->color_shift_pos = newshift; + } + } +} + + +#if 0 +static long +distance(long x1, long y1, long x2, long y2) +{ + long dx, dy; + + dx = x2 - x1; + dy = y2 - y1; + return dx*dx + dy*dy; +} + +static int poisson_irand(double p) +{ + int r = 1; + while (fabs(frand(1.0)) < p) + ++r; + return r < 1 ? 1 : r; +} +#endif + +static void +precalculate_figure(Body *pb, + double this_xtime, double step, + int *x_max, int *y_max, + int *x_min, int *y_min) +{ + double t; + + move_body(pb, 0.0); /* move once to avoid initial line from origin */ + *x_min = *x_max = pb->x; + *y_min = *y_max = pb->y; + + for (t=0.0; tx > *x_max) + *x_max = pb->x; + if (pb->x < *x_min) + *x_min = pb->x; + if (pb->y > *y_max) + *y_max = pb->y; + if (pb->y < *y_min) + *y_min = pb->y; + } +} + +static int i_max(int a, int b) +{ + return (a>b) ? a : b; +} + +static void rescale_circles(struct state *st, Body *pb, + int x_max, int y_max, + int x_min, int y_min) +{ + double xscale, yscale, scale; + double xm, ym; + + x_max -= st->x_offset; + x_min -= st->x_offset; + y_max -= st->y_offset; + y_min -= st->y_offset; + + x_max = i_max(x_max, -x_min); + y_max = i_max(y_max, -y_min); + + + xm = st->width / 2.0; + ym = st->height / 2.0; + if (x_max > xm) + xscale = xm / x_max; + else + xscale = 1.0; + if (y_max > ym) + yscale = ym / y_max; + else + yscale = 1.0; + + if (xscale < yscale) /* wider than tall */ + scale = xscale; /* ensure width fits onscreen */ + else + scale = yscale; /* ensure height fits onscreen */ + + + scale *= FILL_PROPORTION; /* only fill FILL_PROPORTION of screen */ + if (scale < 1.0) /* only reduce, don't enlarge. */ + { + Circle *p; + for (p=pb->epicycles; p; p=p->pchild) + { + p->radius *= scale; + } + } + else + { + printf("enlarge by x%.2f skipped...\n", scale); + } +} + + +/* angular speeds of the circles are harmonics of a fundamental + * value. That should please the Pythagoreans among you... :-) + */ +static double +random_wdot_max(struct state *st) +{ + /* Maximum and minimum values for the choice of wdot_max. Possible + * epicycle speeds vary from wdot_max to (wdot_max * harmonics). + */ + double minspeed, maxspeed; + minspeed = get_float_resource(st->dpy, "minSpeed", "Double"); + maxspeed = get_float_resource(st->dpy, "maxSpeed", "Double"); + return st->harmonics * (minspeed + FULLCIRCLE * frand(maxspeed-minspeed)); +} + + +static void * +epicycle_init (Display *disp, Window win) +{ + struct state *st = (struct state *) calloc (1, sizeof(*st)); + st->dpy = disp; + st->window = win; + + st->holdtime = get_integer_resource (st->dpy, "holdtime", "Integer"); + + st->circle = FULLCIRCLE; + + XClearWindow(st->dpy, st->window); + st->uncleared = 0; + st->restart = 1; + + st->delay = get_integer_resource (st->dpy, "delay", "Integer"); + st->harmonics = get_integer_resource(st->dpy, "harmonics", "Integer"); + st->divisorPoisson = get_float_resource(st->dpy, "divisorPoisson", "Double"); + + st->timestep = get_float_resource(st->dpy, "timestep", "Double"); + st->timestep_coarse = st->timestep * + get_float_resource(st->dpy, "timestepCoarseFactor", "Double"); + + st->sizeFactorMin = get_float_resource(st->dpy, "sizeFactorMin", "Double"); + st->sizeFactorMax = get_float_resource(st->dpy, "sizeFactorMax", "Double"); + + st->minCircles = get_integer_resource (st->dpy, "minCircles", "Integer"); + st->maxCircles = get_integer_resource (st->dpy, "maxCircles", "Integer"); + + st->xtime = 0; /* is this right? */ + + return st; +} + +static unsigned long +epicycle_draw (Display *dpy, Window window, void *closure) +{ + struct state *st = (struct state *) closure; + int this_delay = st->delay; + + if (st->eraser) { + st->eraser = erase_window (st->dpy, st->window, st->eraser); + return 10000; + } + + if (st->restart) + { + setup(st); + st->restart = 0; + + /* Flush any outstanding events; this has the side effect of + * reducing the number of "false restarts"; resdtarts caused by + * one event (e.g. ConfigureNotify) followed by another + * (e.g. Expose). + */ + + st->wdot_max = random_wdot_max(st); + + if (st->pb0) + { + delete_body(st->pb0); + st->pb0 = NULL; + } + st->pb0 = new_body(st); + st->pb0->x_origin = st->pb0->x = st->x_offset; + st->pb0->y_origin = st->pb0->y = st->y_offset; + + if (st->uncleared) + { + st->eraser = erase_window (st->dpy, st->window, st->eraser); + st->uncleared = 0; + } + + precalculate_figure(st->pb0, st->xtime, st->timestep_coarse, + &st->xmax, &st->ymax, &st->xmin, &st->ymin); + + rescale_circles(st, st->pb0, st->xmax, st->ymax, st->xmin, st->ymin); + + move_body(st->pb0, 0.0); /* move once to avoid initial line from origin */ + move_body(st->pb0, 0.0); /* move once to avoid initial line from origin */ + + + st->T = 0.0; /* start at time zero. */ + + st->L = compute_divisor_lcm(st->pb0->epicycles); + + st->colour_cycle_rate = fabs(st->L); + + st->xtime = fabs(st->L * st->circle / st->wdot_max); + + if (st->colors) /* (colors==NULL) if mono_p */ + XSetForeground (st->dpy, st->color0, st->colors[st->pb0->current_color].pixel); + } + + + color_step(st, st->pb0, st->T/st->xtime ); + draw_body(st, st->pb0, st->color0); + st->uncleared = 1; + + + /* Check if the figure is complete...*/ + if (st->T > st->xtime) + { + this_delay = st->holdtime * 1000000; + st->restart = 1; /* begin new figure. */ + } + + + + st->T += st->timestep; + move_body(st->pb0, st->T); + + return this_delay; +} + +static void +epicycle_reshape (Display *dpy, Window window, void *closure, + unsigned int w, unsigned int h) +{ + struct state *st = (struct state *) closure; + st->restart = 1; +} + +static Bool +epicycle_event (Display *dpy, Window window, void *closure, XEvent *e) +{ + struct state *st = (struct state *) closure; + if (e->type == ButtonPress) + { + st->restart = 1; + return True; + } + + return False; +} + +static void +epicycle_free (Display *dpy, Window window, void *closure) +{ + struct state *st = (struct state *) closure; + free (st); +} + +XSCREENSAVER_MODULE ("Epicycle", epicycle) diff --git a/hacks/epicycle.man b/hacks/epicycle.man new file mode 100644 index 00000000..290884f8 --- /dev/null +++ b/hacks/epicycle.man @@ -0,0 +1,204 @@ +.de EX \"Begin example +.ne 5 +.if n .sp 1 +.if t .sp .5 +.nf +.in +.5i +.. +.de EE +.fi +.in -.5i +.if n .sp 1 +.if t .sp .5 +.. +.TH XScreenSaver 1 "27-Apr-97" "X Version 11" +.SH NAME +epicycle - draws a point moving around a circle which moves around a cicle which... +.SH SYNOPSIS +.B epicycle +[\-display \fIhost:display.screen\fP] [\-root] [\-window] [\-mono] [\-install] [\-noinstall] [\-visual \fIviz\fP] [\-colors \fIN\fP] [\-foreground \fIname\fP] [\-color\-shift \fIN\fP] [\-delay \fImicroseconds\fP] [\-holdtime \fIseconds\fP] [\-linewidth \fIN\fP] [\-min_circles \fIN\fP] [\-max_circles \fIN\fP] [\-min_speed \fInumber\fP] [\-max_speed \fInumber\fP] [\-harmonics \fIN\fP] [\-timestep \fInumber\fP] [\-divisor_poisson \fIprobability\fP] [\-size_factor_min \fInumber\fP] [\-size_factor_max \fInumber\fP] +[\-fps] +.SH DESCRIPTION +The epicycle program draws the path traced out by a point on the edge +of a circle. That circle rotates around a point on the rim of another +circle, and so on, several times. The random curves produced can be +simple or complex, convex or concave, but they are always closed +curves (they never go in indefinitely). + +You can configure both the way the curves are drawn and the way in +which the random sequence of circles is generated, either with +command-line options or X resources. +.SH OPTIONS +.TP 8 +.B \-display \fIhost:display.screen\fP +Specifies which X display we should use (see the section DISPLAY NAMES in +.BR X (1) +for more information about this option). +.TP 8 +.B \-root +Draw on the root window. +.TP 8 +.B \-window +Draw on a newly-created window. This is the default. +.TP 8 +.B \-mono +If on a color display, pretend we're on a monochrome display. +If we're on a mono display, we have no choice. +.TP 8 +.B \-install +Install a private colormap for the window. +.TP 8 +.B \-noinstall +Don't install a private colormap for the window. +.TP 8 +.B \-visual \fIviz\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. +Possible choices include + +.RS +default, best, mono, monochrome, gray, grey, color, staticgray, staticcolor, +truecolor, grayscale, greyscale, pseudocolor, directcolor, \fInumber\fP + +If a decimal or hexadecimal number is used, +.BR XGetVisualInfo (3X) +is consulted to obtain the required visual. +.RE +.TP 8 +.B \-colors \fIN\fP +How many colors should be used (if possible). The colors are chosen +randomly. +.TP 8 +.B \-foreground \fIname\fP +With +.BR \-mono , +this option selects the foreground colour. +.TP 8 +.B \-delay \fImicroseconds\fP +Specifies the delay between drawing successive line segments of the +path. If you do not specify +.BR -sync , +some X servers may batch up several drawing operations together, +producing a less smooth effect. This is more likely to happen +in monochrome mode (on monochrome servers or when +.B \-mono +is specified). +.TP 8 +.B \-holdtime \fIseconds\fP +When the figure is complete, +.I epicycle +pauses this number of seconds. +.TP 8 +.B \-linewidth \fIN\fP +Width in pixels of the body's track. Specifying values greater than +one may cause slower drawing. The fastest value is usually zero, +meaning one pixel. +.TP 8 +.B \-min_circles \fIN\fP +Smallest number of epicycles in the figure. +.TP 8 +.B \-max_circles \fIN\fP +Largest number of epicycles in the figure. +.TP 8 +.B \-min_speed \fInumber\fP +Smallest possible value for the base speed of revolution of the +epicycles. The actual speeds of the epicycles vary from this down +to +.IB "min_speed / harmonics" . +.TP 8 +.B \-max_speed \fInumber\fP +Smallest possible value for the base speed of revolution of the +epicycles. +.TP 8 +.B \-harmonics \fIN\fP +Number of possible harmonics; the larger this value is, the greater +the possible variety of possible speeds of epicycle. +.TP 8 +.B \-timestep \fInumber\fP +Decreasing this value will reduce the distance the body moves for +each line segment, possibly producing a smoother figure. Increasing +it may produce faster results. +.TP 8 +.B \-divisor_poisson \fIprobability\fP +Each epicycle rotates at a rate which is a factor of the base speed. +The speed of each epicycle is the base speed divided by some integer +between 1 and the value of the +.B \-harmonics +option. This integer is decided by starting at 1 and tossing +a biased coin. For each consecutive head, the value is incremented by +one. The integer will not be incremented above the value of the +.B \-harmonics +option. The argument of this option decides the bias of the coin; it +is the probability that that coin will produce a head at any given toss. +.TP 8 +.B \-size_factor_min \fInumber\fP +Epicycles are always at least this factor smaller than their +parents. +.TP 8 +.B \-size_factor_max \fInumber\fP +Epicycles are never more than this factor smaller than their parents. +.TP 8 +.B \-fps +Display the current frame rate and CPU load. +.SH RESOURCES +.EX +Option Resource Default Value +------ -------- ------------- +-colors .colors 100 +-delay .delay 1000 +-holdtime .holdtime 2 +-linewidth .lineWidth 4 +-min_circles .minCircles 2 +-max_circles .maxCircles 10 +-min_speed .minSpeed 0.003 +-max_speed .maxSpeed 0.005 +-harmonics .harmonics 8 +-timestep .timestep 1.0 +-divisor_poisson .divisorPoisson 0.4 +-size_factor_min .sizeFactorMin 1.05 +-size_factor_max .sizeFactorMax 2.05 + .timestepCoarseFactor 1.0 +.EE +Before the drawing of the figure is begun, a preliminary calculation +of the path is done in order to scale the radii of the epicycles so +as to fit the figure on the screen or window. For the sake of speed, +This calculation is done with a larger timestep than the actual +drawing. The time-step used is the value of the +.B \-timestep +option multiplied by the timestepCoarseFactor resource. The default +value of 1 will almost always work fast enough and so this resource +is not available as a command-line option. +.SH USER INTERFACE +The program runs mostly without user interaction. When running on the +root window, no input is accepted. When running in its own window, +the program will exit if mouse button 3 is pressed. If any other +mouse button is pressed, the current figure will be abandoned and +another will be started. +.SH HISTORY +The geometry of epicycles was perfected by Hipparchus of Rhodes at +some time around 125 B.C., 185 years after the birth of Aristarchus of +Samos, the inventor of the heliocentric universe model. Hipparchus +applied epicycles to the Sun and the Moon. Ptolemy of Alexandria went +on to apply them to what was then the known universe, at around 150 +A.D. Copernicus went on to apply them to the heliocentric model at +the beginning of the sixteenth century. Johannes Kepler discovered +that the planets actually move in elliptical orbits in about 1602. +The inverse-square law of gravity was suggested by Boulliau in 1645. +Isaac Newton's +.I Principia Mathematica +was published in 1687, and proved that Kepler's laws derived from +Newtonian gravitation. +.SH BUGS +The colour selection is re-done for every figure. This may +generate too much network traffic for this program to work well +over slow or long links. +.SH COPYRIGHT +Copyright \(co 1998, James Youngman. 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 +James Youngman , April 1998. diff --git a/hacks/eruption.c b/hacks/eruption.c new file mode 100644 index 00000000..5749aa6d --- /dev/null +++ b/hacks/eruption.c @@ -0,0 +1,520 @@ +/* Eruption, Copyright (c) 2002-2003 W.P. van Paassen + * + * 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. + * + * Module - "eruption.c" + * + * [02-2003] - W.P. van Paassen: Improvements, added some code of jwz from the pyro hack for a spherical distribution of the particles + * [01-2003] - W.P. van Paassen: Port to X for use with XScreenSaver, the shadebob hack by Shane Smit was used as a template + * [04-2002] - W.P. van Paassen: Creation for the Demo Effects Collection (http://demo-effects.sourceforge.net) + */ + +#include +#include "screenhack.h" + +/*#define VERBOSE*/ + +/* Slightly whacked, for better explosions + */ +#define PI_2000 6284 +#define SPREAD 15 + +/*particle structure*/ +typedef struct +{ + short xpos, ypos, xdir, ydir; + unsigned char colorindex; + unsigned char dead; +} PARTICLE; + +struct state { + Display *dpy; + Window window; + + int sin_cache[PI_2000]; + int cos_cache[PI_2000]; + + PARTICLE *particles; + unsigned short iWinWidth, iWinHeight; + unsigned char **fire; + unsigned short nParticleCount; + unsigned char xdelta, ydelta, decay; + signed char gravity; + signed short heat; + + int cycles, delay; + GC gc; + signed short iColorCount; + unsigned long *aiColorVals; + XImage *pImage; + + int draw_i; +}; + +static void +cache(struct state *st) /* jwz */ +{ /*needs to be run once. Could easily be */ + int i; /*reimplemented to run and cache at compile-time,*/ + double dA; + for (i=0; icos_cache[i]=-abs((int) (cos(((double)i)/1000.0)*dA*st->ydelta)); + st->sin_cache[i]=(int) (sin(((double)i)/1000.0)*dA*st->xdelta); + } +} + +static void init_particle(struct state *st, PARTICLE* particle, unsigned short xcenter, unsigned short ycenter) +{ + int v = random() % PI_2000; + particle->xpos = xcenter - SPREAD + (random() % (SPREAD * 2)); + particle->ypos = ycenter - SPREAD + (random() % (SPREAD * 2));; + particle->xdir = st->sin_cache[v]; + particle->ydir = st->cos_cache[v]; + particle->colorindex = st->iColorCount-1; + particle->dead = 0; +} + +static void Execute( struct state *st ) +{ + int i, j; + unsigned int temp; + + /* move and draw particles into st->fire array */ + + for (i = 0; i < st->nParticleCount; i++) + { + if (!st->particles[i].dead) + { + st->particles[i].xpos += st->particles[i].xdir; + st->particles[i].ypos += st->particles[i].ydir; + + /* is particle dead? */ + + if (st->particles[i].colorindex == 0) + { + st->particles[i].dead = 1; + continue; + } + + if (st->particles[i].xpos < 1) + { + st->particles[i].xpos = 1; + st->particles[i].xdir = -st->particles[i].xdir - 4; + st->particles[i].colorindex = st->iColorCount; + } + else if (st->particles[i].xpos >= st->iWinWidth - 2) + { + st->particles[i].xpos = st->iWinWidth - 2; + if (st->particles[i].xpos < 1) st->particles[i].xpos = 1; + st->particles[i].xdir = -st->particles[i].xdir + 4; + st->particles[i].colorindex = st->iColorCount; + } + + if (st->particles[i].ypos < 1) + { + st->particles[i].ypos = 1; + st->particles[i].ydir = -st->particles[i].ydir; + st->particles[i].colorindex = st->iColorCount; + } + else if (st->particles[i].ypos >= st->iWinHeight - 3) + { + st->particles[i].ypos = st->iWinHeight- 3; + if (st->particles[i].ypos < 1) st->particles[i].ypos = 1; + st->particles[i].ydir = (-st->particles[i].ydir >> 2) - (random() % 2); + st->particles[i].colorindex = st->iColorCount; + } + + + /* st->gravity kicks in */ + st->particles[i].ydir += st->gravity; + + /* particle cools off */ + st->particles[i].colorindex--; + + /* draw particle */ + if (st->iWinHeight <= 2 || st->iWinWidth <= 2) continue; + st->fire[st->particles[i].ypos][st->particles[i].xpos] = st->particles[i].colorindex; + st->fire[st->particles[i].ypos][st->particles[i].xpos - 1] = st->particles[i].colorindex; + st->fire[st->particles[i].ypos + 1][st->particles[i].xpos] = st->particles[i].colorindex; + st->fire[st->particles[i].ypos - 1][st->particles[i].xpos] = st->particles[i].colorindex; + st->fire[st->particles[i].ypos][st->particles[i].xpos + 1] = st->particles[i].colorindex; + } + } + + /* create st->fire effect */ + for (i = 0; i < st->iWinHeight; i++) + { + for (j = 0; j < st->iWinWidth; j++) + { + if (j + 1 >= st->iWinWidth) + temp = 0; + else + temp = st->fire[i][j + 1]; + + if (j - 1 >= 0) + temp += st->fire[i][j - 1]; + + if (i - 1 >= 0) + { + temp += st->fire[i - 1][j]; + if (j - 1 >= 0) + temp += st->fire[i - 1][j - 1]; + if (j + 1 < st->iWinWidth) + temp += st->fire[i - 1][j + 1]; + } + + if (i + 1 < st->iWinHeight) + { + temp += st->fire[i + 1][j]; + if (j + 1 < st->iWinWidth) + temp += st->fire[i + 1][j + 1]; + if (j - 1 >= 0) + temp += st->fire[i + 1][j - 1]; + } + + temp >>= 3; + + if (temp > st->decay) + { + temp -= st->decay; + } + else + temp = 0; + + st->fire[i][j] = temp; + } + } + + memset( st->pImage->data, 0, st->pImage->bytes_per_line * st->pImage->height ); + + /* draw st->fire array to screen */ + for (i = 0; i < st->iWinHeight; ++i) + { + for (j = 0; j < st->iWinWidth; ++j) + { + if (st->fire[i][j] > 0) + XPutPixel( st->pImage, j, i, st->aiColorVals[ st->fire[i][j] ] ); + } + } + XPutImage( st->dpy, st->window, st->gc, st->pImage, + 0,0,0,0, st->iWinWidth, st->iWinHeight ); +} + +static unsigned long * SetPalette(struct state *st) +{ + XWindowAttributes XWinAttribs; + XColor Color, *aColors; + signed short iColor; + + XGetWindowAttributes( st->dpy, st->window, &XWinAttribs ); + + st->iColorCount = get_integer_resource(st->dpy, "ncolors", "Integer" ); + if( st->iColorCount < 16 ) st->iColorCount = 16; + if( st->iColorCount > 255 ) st->iColorCount = 256; + + aColors = calloc( st->iColorCount, sizeof(XColor) ); + st->aiColorVals = calloc( st->iColorCount, sizeof(unsigned long) ); + + Color.red = Color.green = Color.blue = 65535 / st->iColorCount; + + /* create st->fire palette */ + for( iColor=0; iColor < st->iColorCount; iColor++ ) + { + if (iColor < st->iColorCount >> 3) + { + /* black to blue */ + aColors[iColor].red = 0; + aColors[iColor].green = 0; + aColors[iColor].blue = Color.blue * (iColor << 1); + } + else if (iColor < st->iColorCount >> 2) + { + /* blue to red */ + signed short temp = (iColor - (st->iColorCount >> 3)); + aColors[iColor].red = Color.red * (temp << 3); + aColors[iColor].green = 0; + aColors[iColor].blue = 16383 - Color.blue * (temp << 1); + } + else if (iColor < (st->iColorCount >> 2) + (st->iColorCount >> 3)) + { + /* red to yellow */ + signed short temp = (iColor - (st->iColorCount >> 2)) << 3; + aColors[iColor].red = 65535; + aColors[iColor].green = Color.green * temp; + aColors[iColor].blue = 0; + } + else if (iColor < st->iColorCount >> 1) + { + /* yellow to white */ + signed int temp = (iColor - ((st->iColorCount >> 2) + (st->iColorCount >> 3))) << 3; + aColors[iColor].red = 65535; + aColors[iColor].green = 65535; + aColors[iColor].blue = Color.blue * temp; + } + else + { + /* white */ + aColors[iColor].red = aColors[iColor].green = aColors[iColor].blue = 65535; + } + + if( !XAllocColor( st->dpy, XWinAttribs.colormap, &aColors[ iColor ] ) ) + { + /* start all over with less colors */ + XFreeColors( st->dpy, XWinAttribs.colormap, st->aiColorVals, iColor, 0 ); + free( aColors ); + free( st->aiColorVals ); + (st->iColorCount)--; + aColors = calloc( st->iColorCount, sizeof(XColor) ); + st->aiColorVals = calloc( st->iColorCount, sizeof(unsigned long) ); + iColor = -1; + } + else + st->aiColorVals[ iColor ] = aColors[ iColor ].pixel; + } + + if (st->heat < st->iColorCount) + st->iColorCount = st->heat; + + free( aColors ); + + XSetWindowBackground( st->dpy, st->window, st->aiColorVals[ 0 ] ); + + return st->aiColorVals; +} + + +static void Initialize( struct state *st ) +{ + XGCValues gcValues; + XWindowAttributes XWinAttribs; + int /*iBitsPerPixel,*/ i; + + /* Create the Image for drawing */ + XGetWindowAttributes( st->dpy, st->window, &XWinAttribs ); + + /* Find the preferred bits-per-pixel. (jwz) */ + { + int pfvc = 0; + XPixmapFormatValues *pfv = XListPixmapFormats( st->dpy, &pfvc ); + for( i=0; igc = XCreateGC( st->dpy, st->window, 0, &gcValues ); + + st->pImage = XCreateImage( st->dpy, XWinAttribs.visual, XWinAttribs.depth, ZPixmap, 0, NULL, + XWinAttribs.width, XWinAttribs.height, BitmapPad( st->dpy ), 0 ); + (st->pImage)->data = calloc((st->pImage)->bytes_per_line, (st->pImage)->height); + + st->iWinWidth = XWinAttribs.width; + st->iWinHeight = XWinAttribs.height; + + /* create st->fire array */ + st->fire = calloc( st->iWinHeight, sizeof(unsigned char*)); + for (i = 0; i < st->iWinHeight; ++i) + st->fire[i] = calloc( st->iWinWidth, sizeof(unsigned char)); + + /*create st->particles */ + st->particles = malloc (st->nParticleCount * sizeof(PARTICLE)); +} + +static void * +eruption_init (Display *dpy, Window window) +{ + struct state *st = (struct state *) calloc (1, sizeof(*st)); + XWindowAttributes XWinAttribs; + unsigned short sum = 0; +#ifdef VERBOSE + time_t nTime = time( NULL ); + unsigned short iFrame = 0; +#endif /* VERBOSE */ + + st->dpy = dpy; + st->window = window; + + st->nParticleCount = get_integer_resource(st->dpy, "particles", "Integer" ); + if (st->nParticleCount < 100) + st->nParticleCount = 100; + if (st->nParticleCount > 2000) + st->nParticleCount = 2000; + + st->decay = get_integer_resource(st->dpy, "cooloff", "Integer" ); + if (st->decay <= 0) + st->decay = 0; + if (st->decay > 10) + st->decay = 10; + + st->gravity = get_integer_resource(st->dpy, "gravity", "Integer" ); + if (st->gravity < -5) + st->gravity = -5; + if (st->gravity > 5) + st->gravity = 5; + + st->heat = get_integer_resource(st->dpy, "heat", "Integer" ); + if (st->heat < 64) + st->heat = 64; + if (st->heat > 256) + st->heat = 256; + +#ifdef VERBOSE + printf( "%s: Allocated %d st->particles\n", progclass, st->nParticleCount ); +#endif /* VERBOSE */ + + Initialize( st ); + + st->ydelta = 0; + while (sum < (st->iWinHeight >> 1) - SPREAD) + { + st->ydelta++; + sum += st->ydelta; + } + + sum = 0; + while (sum < (st->iWinWidth >> 3)) + { + st->xdelta++; + sum += st->xdelta; + } + + st->delay = get_integer_resource(st->dpy, "delay", "Integer" ); + st->cycles = get_integer_resource(st->dpy, "cycles", "Integer" ); + + cache(st); + + XGetWindowAttributes( st->dpy, st->window, &XWinAttribs ); + XFreeColors( st->dpy, XWinAttribs.colormap, st->aiColorVals, st->iColorCount, 0 ); + free( st->aiColorVals ); + st->aiColorVals = SetPalette( st ); + XClearWindow( st->dpy, st->window ); + memset( st->pImage->data, 0, st->pImage->bytes_per_line * st->pImage->height ); + + st->draw_i = -1; + + return st; +} + + +static unsigned long +eruption_draw (Display *dpy, Window window, void *closure) +{ + struct state *st = (struct state *) closure; + + if( st->draw_i < 0 || st->draw_i++ >= st->cycles ) + { + /* compute random center */ + unsigned short xcenter, ycenter; + xcenter = random() % st->iWinWidth; + ycenter = random() % st->iWinHeight; + + for (st->draw_i = 0; st->draw_i < st->nParticleCount; st->draw_i++) + init_particle(st, st->particles + st->draw_i, xcenter, ycenter); + st->draw_i = 0; + } + + Execute( st ); + +#ifdef VERBOSE + iFrame++; + if( nTime - time( NULL ) ) + { + printf( "%s: %d FPS\n", progclass, iFrame ); + nTime = time( NULL ); + iFrame = 0; + } +#endif /* VERBOSE */ + + return st->delay; +} + + +static void +eruption_reshape (Display *dpy, Window window, void *closure, + unsigned int w, unsigned int h) +{ +#if 0 + struct state *st = (struct state *) closure; + int i; + for (i = 0; i < st->iWinHeight; ++i) + free (st->fire[i]); + + st->iWinWidth = w; + st->iWinHeight = h; + + free (st->fire); + st->fire = calloc( st->iWinHeight, sizeof(unsigned char*)); + for (i = 0; i < st->iWinHeight; ++i) + st->fire[i] = calloc( st->iWinWidth, sizeof(unsigned char)); + st->draw_i = -1; +#endif +} + +static Bool +eruption_event (Display *dpy, Window window, void *closure, XEvent *event) +{ + return False; +} + +static void +eruption_free (Display *dpy, Window window, void *closure) +{ +#if 0 + struct state *st = (struct state *) closure; + free( st->pImage->data ); + XDestroyImage( st->pImage ); + free( st->aiColorVals ); + for (i = 0; i < st->iWinHeight; ++i) + free( st->fire[i] ); + free( st->fire ); + free( st->particles ); +#endif +} + + +static const char *eruption_defaults [] = { + ".background: black", + ".foreground: white", + "*fpsTop: true", + "*cycles: 80", + "*ncolors: 256", + "*delay: 10000", + "*particles: 300", + "*cooloff: 2", + "*gravity: 1", + "*heat: 256", + 0 +}; + +static XrmOptionDescRec eruption_options [] = { + { "-ncolors", ".ncolors", XrmoptionSepArg, 0 }, + { "-delay", ".delay", XrmoptionSepArg, 0 }, + { "-cycles", ".cycles", XrmoptionSepArg, 0 }, + { "-particles", ".particles", XrmoptionSepArg, 0 }, + { "-cooloff", ".cooloff", XrmoptionSepArg, 0 }, + { "-gravity", ".gravity", XrmoptionSepArg, 0 }, + { "-heat", ".heat", XrmoptionSepArg, 0 }, + { 0, 0, 0, 0 } +}; + + +XSCREENSAVER_MODULE ("Eruption", eruption) + +/* End of Module - "eruption.c" */ + diff --git a/hacks/eruption.man b/hacks/eruption.man new file mode 100644 index 00000000..032b3bd7 --- /dev/null +++ b/hacks/eruption.man @@ -0,0 +1,77 @@ +.TH XScreenSaver 1 "" "X Version 11" +.SH NAME +Eruption \- eruption of pieces of hot volcanic rock +.SH SYNOPSIS +.B Eruption +[\-display \fIhost:display.screen\fP] +[\-visual \fIvisual\fP] +[\-window] +[\-root] +[\-ncolors \fInumber\fP] +[\-nParticles \fInumber\fP] +[\-Heat \fInumber\fP] +[\-Cooling \fInumber\fP] +[\-Gravity \fInumber\fP] +[\-delay \fInumber\fP] +[\-cycles \fInumber\fP] +[\-fps] +.SH DESCRIPTION +This hack creates an eruption of pieces of hot volcanic rock. +Ported from the demo effects collection (http://demo-effects.sourceforge.net) +.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 \-ncolors \fInumber\fP +Number of Colors. Default: 256. +.TP 8 +.B \-particles \fInumber\fP +Number of Particles. Default: 300. +.TP 8 +.B \-cooloff \fInumber\fP +Eruption Cooloff. Default: 2. +.TP 8 +.B \-heat \fInumber\fP +Heat of Eruption. Default: 256. +.TP 8 +.B \-gravity \fInumber\fP +Gravity. Default: 1. +.TP 8 +.B \-delay \fInumber\fP +Per-frame delay, in microseconds. Default: 5000 (0.01 seconds.). +.TP 8 +.B \-cycles \fInumber\fP +Duration. 10 - 3000. Default: 80. +.TP 8 +.B \-fps +Display the current frame rate and CPU load. +.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 2002-2003 by W.P. van Paassen. 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 +W.P. van Paassen diff --git a/hacks/euler2d.c b/hacks/euler2d.c new file mode 100644 index 00000000..2a3700bf --- /dev/null +++ b/hacks/euler2d.c @@ -0,0 +1,887 @@ +/* -*- Mode: C; tab-width: 4 -*- */ +/* euler2d --- 2 Dimensional Incompressible Inviscid Fluid Flow */ + +#if 0 +static const char sccsid[] = "@(#)euler2d.c 5.00 2000/11/01 xlockmore"; +#endif + +/* + * Copyright (c) 2000 by Stephen Montgomery-Smith + * + * Permission to use, copy, modify, and distribute this software and its + * documentation for any purpose and without fee is hereby granted, + * provided that the above copyright notice appear in all copies and that + * both that copyright notice and this permission notice appear in + * supporting documentation. + * + * This file is provided AS IS with no warranties of any kind. The author + * shall have no liability with respect to the infringement of copyrights, + * trade secrets or any patents by this file or any part thereof. In no + * event will the author be liable for any lost revenue or profits or + * other special, indirect and consequential damages. + * + * Revision History: + * 04-Nov-2000: Added an option eulerpower. This allows for example the + * quasi-geostrophic equation by setting eulerpower to 2. + * 01-Nov-2000: Allocation checks. + * 10-Sep-2000: Added optimizations, and removed subtle_perturb, by stephen. + * 03-Sep-2000: Changed method of solving ode to Adams-Bashforth of order 2. + * Previously used a rather compilcated method of order 4. + * This doubles the speed of the program. Also it seems + * to have improved numerical stability. Done by stephen. + * 27-Aug-2000: Added rotation of region to maximize screen fill by stephen. + * 05-Jun-2000: Adapted from flow.c Copyright (c) 1996 by Tim Auckland + * 18-Jul-1996: Adapted from swarm.c Copyright (c) 1991 by Patrick J. Naughton. + * 31-Aug-1990: Adapted from xswarm by Jeff Butterworth. (butterwo@ncsc.org) + */ + +/* + * The mathematical aspects of this program are discussed in the file + * euler2d.tex. + */ + +#ifdef STANDALONE +# define MODE_euler2d +# define DEFAULTS "*delay: 10000 \n" \ + "*count: 1024 \n" \ + "*cycles: 3000 \n" \ + "*ncolors: 64 \n" \ + "*fpsSolid: true \n" \ + +# define euler2d_handle_event 0 +# define SMOOTH_COLORS +# include "xlockmore.h" /* in xscreensaver distribution */ +#else /* STANDALONE */ +# include "xlock.h" /* in xlockmore distribution */ +#endif /* STANDALONE */ + +#ifdef MODE_euler2d + +#define DEF_EULERTAIL "10" + +#define DEBUG_POINTED_REGION 0 + +static int tail_len; +static int variable_boundary = 1; +static float power = 1; + +static XrmOptionDescRec opts[] = +{ + {"-eulertail", ".euler2d.eulertail", XrmoptionSepArg, NULL}, + {"-eulerpower", ".euler2d.eulerpower", XrmoptionSepArg, NULL}, +}; +static argtype vars[] = +{ + {&tail_len, "eulertail", + "EulerTail", (char *) DEF_EULERTAIL, t_Int}, + {&power, "eulerpower", + "EulerPower", "1", t_Float}, +}; +static OptionStruct desc[] = +{ + {"-eulertail len", "Length of Euler2d tails"}, + {"-eulerpower power", "power of interaction law for points for Euler2d"}, +}; + +ENTRYPOINT ModeSpecOpt euler2d_opts = +{sizeof opts / sizeof opts[0], opts, + sizeof vars / sizeof vars[0], vars, desc}; + +#ifdef USE_MODULES +ModStruct euler2d_description = { + "euler2d", "init_euler2d", "draw_euler2d", "release_euler2d", + "refresh_euler2d", "init_euler2d", (char *) NULL, &euler2d_opts, + 1000, 1024, 3000, 1, 64, 1.0, "", + "Simulates 2D incompressible invisid fluid.", 0, NULL +}; + +#endif + +#define balance_rand(v) ((LRAND()/MAXRAND*(v))-((v)/2)) /* random around 0 */ +#define positive_rand(v) (LRAND()/MAXRAND*(v)) /* positive random */ + +#define number_of_vortex_points 20 + +#define n_bound_p 500 +#define deg_p 6 + +static double delta_t; + +typedef struct { + int width; + int height; + int count; + double xshift,yshift,scale; + double radius; + + int N; + int Nvortex; + +/* x[2i+0] = x coord for nth point + x[2i+1] = y coord for nth point + w[i] = vorticity at nth point +*/ + double *x; + double *w; + + double *diffx; + double *olddiffx; + double *tempx; + double *tempdiffx; +/* (xs[2i+0],xs[2i+1]) is reflection of (x[2i+0],x[2i+1]) about unit circle + xs[2i+0] = x[2i+0]/nx + xs[2i+1] = x[2i+1]/nx + where + nx = x[2i+0]*x[2i+0] + x[2i+1]*x[2i+1] + + x_is_zero[i] = (nx < 1e-10) +*/ + double *xs; + short *x_is_zero; + +/* (p[2i+0],p[2i+1]) is image of (x[2i+0],x[2i+1]) under polynomial p. + mod_dp2 is |p'(z)|^2 when z = (x[2i+0],x[2i+1]). +*/ + double *p; + double *mod_dp2; + +/* Sometimes in our calculations we get overflow or numbers that are too big. + If that happens with the point x[2*i+0], x[2*i+1], we set dead[i]. +*/ + short *dead; + + XSegment *csegs; + int cnsegs; + XSegment *old_segs; + int *nold_segs; + int c_old_seg; + int boundary_color; + int hide_vortex; + short *lastx; + + double p_coef[2*(deg_p-1)]; + XSegment *boundary; + +} euler2dstruct; + +static euler2dstruct *euler2ds = (euler2dstruct *) NULL; + +/* + If variable_boundary == 1, then we make a variable boundary. + The way this is done is to map the unit disk under a + polynomial p, where + p(z) = z + c_2 z^2 + ... + c_n z^n + where n = deg_p. sp->p_coef contains the complex numbers + c_2, c_3, ... c_n. +*/ + +#define add(a1,a2,b1,b2) (a1)+=(b1);(a2)+=(b2) +#define mult(a1,a2,b1,b2) temp=(a1)*(b1)-(a2)*(b2); \ + (a2)=(a1)*(b2)+(a2)*(b1);(a1)=temp + +static void +calc_p(double *p1, double *p2, double z1, double z2, double p_coef[]) +{ + int i; + double temp; + + *p1=0; + *p2=0; + for(i=deg_p;i>=2;i--) + { + add(*p1,*p2,p_coef[(i-2)*2],p_coef[(i-2)*2+1]); + mult(*p1,*p2,z1,z2); + } + add(*p1,*p2,1,0); + mult(*p1,*p2,z1,z2); +} + +/* Calculate |p'(z)|^2 */ +static double +calc_mod_dp2(double z1, double z2, double p_coef[]) +{ + int i; + double temp,mp1,mp2; + + mp1=0; + mp2=0; + for(i=deg_p;i>=2;i--) + { + add(mp1,mp2,i*p_coef[(i-2)*2],i*p_coef[(i-2)*2+1]); + mult(mp1,mp2,z1,z2); + } + add(mp1,mp2,1,0); + return mp1*mp1+mp2*mp2; +} + +static void +calc_all_p(euler2dstruct *sp) +{ + int i,j; + double temp,p1,p2,z1,z2; + for(j=(sp->hide_vortex?sp->Nvortex:0);jN;j++) if(!sp->dead[j]) + { + p1=0; + p2=0; + z1=sp->x[2*j+0]; + z2=sp->x[2*j+1]; + for(i=deg_p;i>=2;i--) + { + add(p1,p2,sp->p_coef[(i-2)*2],sp->p_coef[(i-2)*2+1]); + mult(p1,p2,z1,z2); + } + add(p1,p2,1,0); + mult(p1,p2,z1,z2); + sp->p[2*j+0] = p1; + sp->p[2*j+1] = p2; + } +} + +static void +calc_all_mod_dp2(double *x, euler2dstruct *sp) +{ + int i,j; + double temp,mp1,mp2,z1,z2; + for(j=0;jN;j++) if(!sp->dead[j]) + { + mp1=0; + mp2=0; + z1=x[2*j+0]; + z2=x[2*j+1]; + for(i=deg_p;i>=2;i--) + { + add(mp1,mp2,i*sp->p_coef[(i-2)*2],i*sp->p_coef[(i-2)*2+1]); + mult(mp1,mp2,z1,z2); + } + add(mp1,mp2,1,0); + sp->mod_dp2[j] = mp1*mp1+mp2*mp2; + } +} + +static void +derivs(double *x, euler2dstruct *sp) +{ + int i,j; + double u1,u2,x1,x2,xij1,xij2,nxij; + double nx; + + if (variable_boundary) + calc_all_mod_dp2(sp->x,sp); + + for (j=0;jNvortex;j++) if (!sp->dead[j]) + { + nx = x[2*j+0]*x[2*j+0] + x[2*j+1]*x[2*j+1]; + if (nx < 1e-10) + sp->x_is_zero[j] = 1; + else { + sp->x_is_zero[j] = 0; + sp->xs[2*j+0] = x[2*j+0]/nx; + sp->xs[2*j+1] = x[2*j+1]/nx; + } + } + + (void) memset(sp->diffx,0,sizeof(double)*2*sp->N); + + for (i=0;iN;i++) if (!sp->dead[i]) + { + x1 = x[2*i+0]; + x2 = x[2*i+1]; + for (j=0;jNvortex;j++) if (!sp->dead[j]) + { +/* + Calculate the Biot-Savart kernel, that is, effect of a + vortex point at a = (x[2*j+0],x[2*j+1]) at the point + x = (x1,x2), returning the vector field in (u1,u2). + + In the plane, this is given by the formula + + u = (x-a)/|x-a|^2 or zero if x=a. + + However, in the unit disk we have to subtract from the + above: + + (x-as)/|x-as|^2 + + where as = a/|a|^2 is the reflection of a about the unit circle. + + If however power != 1, then + + u = (x-a)/|x-a|^(power+1) - |a|^(1-power) (x-as)/|x-as|^(power+1) + +*/ + + xij1 = x1 - x[2*j+0]; + xij2 = x2 - x[2*j+1]; + nxij = (power==1.0) ? xij1*xij1+xij2*xij2 : pow(xij1*xij1+xij2*xij2,(power+1)/2.0); + + if(nxij >= 1e-4) { + u1 = xij2/nxij; + u2 = -xij1/nxij; + } + else + u1 = u2 = 0.0; + + if (!sp->x_is_zero[j]) + { + xij1 = x1 - sp->xs[2*j+0]; + xij2 = x2 - sp->xs[2*j+1]; + nxij = (power==1.0) ? xij1*xij1+xij2*xij2 : pow(xij1*xij1+xij2*xij2,(power+1)/2.0); + + if (nxij < 1e-5) + { + sp->dead[i] = 1; + u1 = u2 = 0.0; + } + else + { + u1 -= xij2/nxij; + u2 += xij1/nxij; + } + } + + if (!sp->dead[i]) + { + sp->diffx[2*i+0] += u1*sp->w[j]; + sp->diffx[2*i+1] += u2*sp->w[j]; + } + } + + if (!sp->dead[i] && variable_boundary) + { + if (sp->mod_dp2[i] < 1e-5) + sp->dead[i] = 1; + else + { + sp->diffx[2*i+0] /= sp->mod_dp2[i]; + sp->diffx[2*i+1] /= sp->mod_dp2[i]; + } + } + } +} + +/* + What perturb does is effectively + ret = x + k, + where k should be of order delta_t. + + We have the option to do this more subtly by mapping points x + in the unit disk to points y in the plane, where y = f(|x|) x, + with f(t) = -log(1-t)/t. + + This might reduce (but does not remove) problems where particles near + the edge of the boundary bounce around. + + But it seems to be not that effective, so for now switch it off. +*/ + +#define SUBTLE_PERTURB 0 + +static void +perturb(double ret[], double x[], double k[], euler2dstruct *sp) +{ + int i; + double x1,x2,k1,k2; + +#if SUBTLE_PERTURB + double d1,d2,t1,t2,mag,mag2,mlog1mmag,memmagdmag,xdotk; + for (i=0;iN;i++) if (!sp->dead[i]) + { + x1 = x[2*i+0]; + x2 = x[2*i+1]; + k1 = k[2*i+0]; + k2 = k[2*i+1]; + mag2 = x1*x1 + x2*x2; + if (mag2 < 1e-10) + { + ret[2*i+0] = x1+k1; + ret[2*i+1] = x2+k2; + } + else if (mag2 > 1-1e-5) + sp->dead[i] = 1; + else + { + mag = sqrt(mag2); + mlog1mmag = -log(1-mag); + xdotk = x1*k1 + x2*k2; + t1 = (x1 + k1)*mlog1mmag/mag + x1*xdotk*(1.0/(1-mag)-mlog1mmag/mag)/mag/mag; + t2 = (x2 + k2)*mlog1mmag/mag + x2*xdotk*(1.0/(1-mag)-mlog1mmag/mag)/mag/mag; + mag = sqrt(t1*t1+t2*t2); + if (mag > 11.5 /* log(1e5) */) + sp->dead[i] = 1; + else + { + memmagdmag = (mag>1e-5) ? ((1.0-exp(-mag))/mag) : (1-mag/2.0); + ret[2*i+0] = t1*memmagdmag; + ret[2*i+1] = t2*memmagdmag; + } + } + if (!sp->dead[i]) + { + d1 = ret[2*i+0]-x1; + d2 = ret[2*i+1]-x2; + if (d1*d1+d2*d2 > 0.1) + sp->dead[i] = 1; + } + } + +#else + + for (i=0;iN;i++) if (!sp->dead[i]) + { + x1 = x[2*i+0]; + x2 = x[2*i+1]; + k1 = k[2*i+0]; + k2 = k[2*i+1]; + if (k1*k1+k2*k2 > 0.1 || x1*x1+x2*x2 > 1-1e-5) + sp->dead[i] = 1; + else + { + ret[2*i+0] = x1+k1; + ret[2*i+1] = x2+k2; + } + } +#endif +} + +static void +ode_solve(euler2dstruct *sp) +{ + int i; + double *temp; + + if (sp->count < 1) { + /* midpoint method */ + derivs(sp->x,sp); + (void) memcpy(sp->olddiffx,sp->diffx,sizeof(double)*2*sp->N); + for (i=0;iN;i++) if (!sp->dead[i]) { + sp->tempdiffx[2*i+0] = 0.5*delta_t*sp->diffx[2*i+0]; + sp->tempdiffx[2*i+1] = 0.5*delta_t*sp->diffx[2*i+1]; + } + perturb(sp->tempx,sp->x,sp->tempdiffx,sp); + derivs(sp->tempx,sp); + for (i=0;iN;i++) if (!sp->dead[i]) { + sp->tempdiffx[2*i+0] = delta_t*sp->diffx[2*i+0]; + sp->tempdiffx[2*i+1] = delta_t*sp->diffx[2*i+1]; + } + perturb(sp->x,sp->x,sp->tempdiffx,sp); + } else { + /* Adams Basforth */ + derivs(sp->x,sp); + for (i=0;iN;i++) if (!sp->dead[i]) { + sp->tempdiffx[2*i+0] = delta_t*(1.5*sp->diffx[2*i+0] - 0.5*sp->olddiffx[2*i+0]); + sp->tempdiffx[2*i+1] = delta_t*(1.5*sp->diffx[2*i+1] - 0.5*sp->olddiffx[2*i+1]); + } + perturb(sp->x,sp->x,sp->tempdiffx,sp); + temp = sp->olddiffx; + sp->olddiffx = sp->diffx; + sp->diffx = temp; + } +} + +#define deallocate(p,t) if (p!=NULL) {(void) free((void *) p); p=(t*)NULL; } +#define allocate(p,t,s) if ((p=(t*)malloc(sizeof(t)*s))==NULL)\ +{free_euler2d(sp);return;} + +static void +free_euler2d(euler2dstruct *sp) +{ + deallocate(sp->csegs, XSegment); + deallocate(sp->old_segs, XSegment); + deallocate(sp->nold_segs, int); + deallocate(sp->lastx, short); + deallocate(sp->x, double); + deallocate(sp->diffx, double); + deallocate(sp->w, double); + deallocate(sp->olddiffx, double); + deallocate(sp->tempdiffx, double); + deallocate(sp->tempx, double); + deallocate(sp->dead, short); + deallocate(sp->boundary, XSegment); + deallocate(sp->xs, double); + deallocate(sp->x_is_zero, short); + deallocate(sp->p, double); + deallocate(sp->mod_dp2, double); +} + +ENTRYPOINT void +init_euler2d (ModeInfo * mi) +{ +#define nr_rotates 18 /* how many rotations to try to fill as much of screen as possible - must be even number */ + euler2dstruct *sp; + int i,k,n,np; + double r,theta,x,y,w; + double mag,xscale,yscale,p1,p2; + double low[nr_rotates],high[nr_rotates],pp1,pp2,pn1,pn2,angle1,angle2,tempangle,dist,scale,bestscale,temp; + int besti = 0; + + if (power<0.5) power = 0.5; + if (power>3.0) power = 3.0; + variable_boundary &= power == 1.0; + delta_t = 0.001; + if (power>1.0) delta_t *= pow(0.1,power-1); + + if (euler2ds == NULL) { + if ((euler2ds = (euler2dstruct *) calloc(MI_NUM_SCREENS(mi), + sizeof (euler2dstruct))) == NULL) + return; + } + sp = &euler2ds[MI_SCREEN(mi)]; + +#ifdef HAVE_COCOA + jwxyz_XSetAntiAliasing (MI_DISPLAY(mi), MI_GC(mi), False); +#endif + + sp->boundary_color = NRAND(MI_NPIXELS(mi)); + sp->hide_vortex = NRAND(4) != 0; + + sp->count = 0; + + sp->width = MI_WIDTH(mi); + sp->height = MI_HEIGHT(mi); + + sp->N = MI_COUNT(mi)+number_of_vortex_points; + sp->Nvortex = number_of_vortex_points; + + if (tail_len < 1) { /* minimum tail */ + tail_len = 1; + } + if (tail_len > MI_CYCLES(mi)) { /* maximum tail */ + tail_len = MI_CYCLES(mi); + } + + /* Clear the background. */ + MI_CLEARWINDOW(mi); + + free_euler2d(sp); + + /* Allocate memory. */ + + if (sp->csegs == NULL) { + allocate(sp->csegs, XSegment, sp->N); + allocate(sp->old_segs, XSegment, sp->N * tail_len); + allocate(sp->nold_segs, int, tail_len); + allocate(sp->lastx, short, sp->N * 2); + allocate(sp->x, double, sp->N * 2); + allocate(sp->diffx, double, sp->N * 2); + allocate(sp->w, double, sp->Nvortex); + allocate(sp->olddiffx, double, sp->N * 2); + allocate(sp->tempdiffx, double, sp->N * 2); + allocate(sp->tempx, double, sp->N * 2); + allocate(sp->dead, short, sp->N); + allocate(sp->boundary, XSegment, n_bound_p); + allocate(sp->xs, double, sp->Nvortex * 2); + allocate(sp->x_is_zero, short, sp->Nvortex); + allocate(sp->p, double, sp->N * 2); + allocate(sp->mod_dp2, double, sp->N); + } + for (i=0;inold_segs[i] = 0; + } + sp->c_old_seg = 0; + (void) memset(sp->dead,0,sp->N*sizeof(short)); + + if (variable_boundary) + { + /* Initialize polynomial p */ +/* + The polynomial p(z) = z + c_2 z^2 + ... c_n z^n needs to be + a bijection of the unit disk onto its image. This is achieved + by insisting that sum_{k=2}^n k |c_k| <= 1. Actually we set + the inequality to be equality (to get more interesting shapes). +*/ + mag = 0; + for(k=2;k<=deg_p;k++) + { + r = positive_rand(1.0/k); + theta = balance_rand(2*M_PI); + sp->p_coef[2*(k-2)+0]=r*cos(theta); + sp->p_coef[2*(k-2)+1]=r*sin(theta); + mag += k*r; + } + if (mag > 0.0001) for(k=2;k<=deg_p;k++) + { + sp->p_coef[2*(k-2)+0] /= mag; + sp->p_coef[2*(k-2)+1] /= mag; + } + +#if DEBUG_POINTED_REGION + for(k=2;k<=deg_p;k++){ + sp->p_coef[2*(k-2)+0]=0; + sp->p_coef[2*(k-2)+1]=0; + } + sp->p_coef[2*(6-2)+0] = 1.0/6.0; +#endif + + +/* Here we figure out the best rotation of the domain so that it fills as + much of the screen as possible. The number of angles we look at is determined + by nr_rotates (we look every 180/nr_rotates degrees). + While we figure out the best angle to rotate, we also figure out the correct scaling factors. +*/ + + for(k=0;kp_coef); + calc_p(&pp1,&pp2,cos((double)(k-1)/(n_bound_p)*2*M_PI),sin((double)(k-1)/(n_bound_p)*2*M_PI),sp->p_coef); + calc_p(&pn1,&pn2,cos((double)(k+1)/(n_bound_p)*2*M_PI),sin((double)(k+1)/(n_bound_p)*2*M_PI),sp->p_coef); + angle1 = nr_rotates/M_PI*atan2(p2-pp2,p1-pp1)-nr_rotates/2; + angle2 = nr_rotates/M_PI*atan2(pn2-p2,pn1-p1)-nr_rotates/2; + while (angle1<0) angle1+=nr_rotates*2; + while (angle2<0) angle2+=nr_rotates*2; + if (angle1>nr_rotates*1.75 && angle2nr_rotates*1.75) angle1+=nr_rotates*2; + if (angle2high[i%nr_rotates]) high[i%nr_rotates] = dist; + if (disthigh[i%nr_rotates]) high[i%nr_rotates] = -dist; + if (-distwidth-5.0)/(high[i]-low[i]); + yscale = (sp->height-5.0)/(high[(i+nr_rotates/2)%nr_rotates]-low[(i+nr_rotates/2)%nr_rotates]); + scale = (xscale>yscale) ? yscale : xscale; + if (scale>bestscale) { + bestscale = scale; + besti = i; + } + } +/* Here we do the rotation. The way we do this is to replace the + polynomial p(z) by a^{-1} p(a z) where a = exp(i best_angle). +*/ + p1 = 1; + p2 = 0; + for(k=2;k<=deg_p;k++) + { + mult(p1,p2,cos((double)besti*M_PI/nr_rotates),sin((double)besti*M_PI/nr_rotates)); + mult(sp->p_coef[2*(k-2)+0],sp->p_coef[2*(k-2)+1],p1,p2); + } + + sp->scale = bestscale; + sp->xshift = -(low[besti]+high[besti])/2.0*sp->scale+sp->width/2; + if (bestiyshift = -(low[besti+nr_rotates/2]+high[besti+nr_rotates/2])/2.0*sp->scale+sp->height/2; + else + sp->yshift = (low[besti-nr_rotates/2]+high[besti-nr_rotates/2])/2.0*sp->scale+sp->height/2; + + +/* Initialize boundary */ + + for(k=0;kp_coef); + sp->boundary[k].x1 = (short)(p1*sp->scale+sp->xshift); + sp->boundary[k].y1 = (short)(p2*sp->scale+sp->yshift); + } + for(k=1;kboundary[k].x2 = sp->boundary[k-1].x1; + sp->boundary[k].y2 = sp->boundary[k-1].y1; + } + sp->boundary[0].x2 = sp->boundary[n_bound_p-1].x1; + sp->boundary[0].y2 = sp->boundary[n_bound_p-1].y1; + } + else + { + if (sp->width>sp->height) + sp->radius = sp->height/2.0-5.0; + else + sp->radius = sp->width/2.0-5.0; + } + + /* Initialize point positions */ + + for (i=sp->Nvortex;iN;i++) { + do { + r = sqrt(positive_rand(1.0)); + theta = balance_rand(2*M_PI); + sp->x[2*i+0]=r*cos(theta); + sp->x[2*i+1]=r*sin(theta); + /* This is to make sure the initial distribution of points is uniform */ + } while (variable_boundary && + calc_mod_dp2(sp->x[2*i+0],sp->x[2*i+1],sp->p_coef) + < positive_rand(4)); + } + + n = NRAND(4)+2; + /* number of vortex points with negative vorticity */ + if (n%2) { + np = NRAND(n+1); + } + else { + /* if n is even make sure that np==n/2 is twice as likely + as the other possibilities. */ + np = NRAND(n+2); + if (np==n+1) np=n/2; + } + for(k=0;kNvortex; + for (i=sp->Nvortex*k/n;iNvortex*(k+1)/n;i++) { + theta = balance_rand(2*M_PI); + sp->x[2*i+0]=x + r*cos(theta); + sp->x[2*i+1]=y + r*sin(theta); + sp->w[i]=w; + } + } +} + +ENTRYPOINT void +draw_euler2d (ModeInfo * mi) +{ + Display *display = MI_DISPLAY(mi); + Window window = MI_WINDOW(mi); + GC gc = MI_GC(mi); + int b, col, n_non_vortex_segs; + euler2dstruct *sp; + + MI_IS_DRAWN(mi) = True; + + if (euler2ds == NULL) + return; + sp = &euler2ds[MI_SCREEN(mi)]; + if (sp->csegs == NULL) + return; + + ode_solve(sp); + if (variable_boundary) + calc_all_p(sp); + + sp->cnsegs = 0; + for(b=sp->Nvortex;bN;b++) if(!sp->dead[b]) + { + sp->csegs[sp->cnsegs].x1 = sp->lastx[2*b+0]; + sp->csegs[sp->cnsegs].y1 = sp->lastx[2*b+1]; + if (variable_boundary) + { + sp->csegs[sp->cnsegs].x2 = (short)(sp->p[2*b+0]*sp->scale+sp->xshift); + sp->csegs[sp->cnsegs].y2 = (short)(sp->p[2*b+1]*sp->scale+sp->yshift); + } + else + { + sp->csegs[sp->cnsegs].x2 = (short)(sp->x[2*b+0]*sp->radius+sp->width/2); + sp->csegs[sp->cnsegs].y2 = (short)(sp->x[2*b+1]*sp->radius+sp->height/2); + } + sp->lastx[2*b+0] = sp->csegs[sp->cnsegs].x2; + sp->lastx[2*b+1] = sp->csegs[sp->cnsegs].y2; + sp->cnsegs++; + } + n_non_vortex_segs = sp->cnsegs; + + if (!sp->hide_vortex) for(b=0;bNvortex;b++) if(!sp->dead[b]) + { + sp->csegs[sp->cnsegs].x1 = sp->lastx[2*b+0]; + sp->csegs[sp->cnsegs].y1 = sp->lastx[2*b+1]; + if (variable_boundary) + { + sp->csegs[sp->cnsegs].x2 = (short)(sp->p[2*b+0]*sp->scale+sp->xshift); + sp->csegs[sp->cnsegs].y2 = (short)(sp->p[2*b+1]*sp->scale+sp->yshift); + } + else + { + sp->csegs[sp->cnsegs].x2 = (short)(sp->x[2*b+0]*sp->radius+sp->width/2); + sp->csegs[sp->cnsegs].y2 = (short)(sp->x[2*b+1]*sp->radius+sp->height/2); + } + sp->lastx[2*b+0] = sp->csegs[sp->cnsegs].x2; + sp->lastx[2*b+1] = sp->csegs[sp->cnsegs].y2; + sp->cnsegs++; + } + + if (sp->count) { + XSetForeground(display, gc, MI_BLACK_PIXEL(mi)); + + XDrawSegments(display, window, gc, sp->old_segs+sp->c_old_seg*sp->N, sp->nold_segs[sp->c_old_seg]); + + if (MI_NPIXELS(mi) > 2){ /* render colour */ + for (col = 0; col < MI_NPIXELS(mi); col++) { + int start = col*n_non_vortex_segs/MI_NPIXELS(mi); + int finish = (col+1)*n_non_vortex_segs/MI_NPIXELS(mi); + XSetForeground(display, gc, MI_PIXEL(mi, col)); + XDrawSegments(display, window, gc,sp->csegs+start, finish-start); + } + if (!sp->hide_vortex) { + XSetForeground(display, gc, MI_WHITE_PIXEL(mi)); + XDrawSegments(display, window, gc,sp->csegs+n_non_vortex_segs, sp->cnsegs-n_non_vortex_segs); + } + + } else { /* render mono */ + XSetForeground(display, gc, MI_WHITE_PIXEL(mi)); + XDrawSegments(display, window, gc, + sp->csegs, sp->cnsegs); + } + + if (MI_NPIXELS(mi) > 2) /* render colour */ + XSetForeground(display, gc, MI_PIXEL(mi, sp->boundary_color)); + else + XSetForeground(MI_DISPLAY(mi), MI_GC(mi), MI_WHITE_PIXEL(mi)); + if (variable_boundary) + XDrawSegments(display, window, gc, + sp->boundary, n_bound_p); + else + XDrawArc(MI_DISPLAY(mi), MI_WINDOW(mi), MI_GC(mi), + sp->width/2 - (int) sp->radius - 1, sp->height/2 - (int) sp->radius -1, + (int) (2*sp->radius) + 2, (int) (2* sp->radius) + 2, 0, 64*360); + + /* Copy to erase-list */ + (void) memcpy(sp->old_segs+sp->c_old_seg*sp->N, sp->csegs, sp->cnsegs*sizeof(XSegment)); + sp->nold_segs[sp->c_old_seg] = sp->cnsegs; + sp->c_old_seg++; + if (sp->c_old_seg >= tail_len) + sp->c_old_seg = 0; + } + + if (++sp->count > MI_CYCLES(mi)) /* pick a new flow */ + init_euler2d(mi); + +} + +ENTRYPOINT void +reshape_euler2d(ModeInfo * mi, int width, int height) +{ + XClearWindow (MI_DISPLAY (mi), MI_WINDOW(mi)); + init_euler2d (mi); +} + +ENTRYPOINT void +release_euler2d (ModeInfo * mi) +{ + if (euler2ds != NULL) { + int screen; + + for (screen = 0; screen < MI_NUM_SCREENS(mi); screen++) + free_euler2d(&euler2ds[screen]); + (void) free((void *) euler2ds); + euler2ds = (euler2dstruct *) NULL; + } +} + +ENTRYPOINT void +refresh_euler2d (ModeInfo * mi) +{ + MI_CLEARWINDOW(mi); +} + +XSCREENSAVER_MODULE ("Euler2D", euler2d) + +#endif /* MODE_euler2d */ diff --git a/hacks/euler2d.man b/hacks/euler2d.man new file mode 100644 index 00000000..ddfd6192 --- /dev/null +++ b/hacks/euler2d.man @@ -0,0 +1,69 @@ +.TH XScreenSaver 1 "" "X Version 11" +.SH NAME +euler2d - two dimensional incompressible inviscid fluid flow. +.SH SYNOPSIS +.B euler2d +[\-display \fIhost:display.screen\fP] +[\-visual \fIvisual\fP] +[\-window] +[\-root] +[\-count \fInumber\fP] +[\-eulertail \fInumber\fP] +[\-cycles \fInumber\fP] +[\-ncolors \fInumber\fP] +[\-delay \fInumber\fP] +[\-fps] +.SH DESCRIPTION +Simulates two dimensional incompressible inviscid fluid flow. +.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 \-count \fInumber\fP +Particles. 2 - 5000. Default: 1024. +.TP 8 +.B \-eulertail \fInumber\fP +Trail Length. 2 - 500. Default: 10. +.TP 8 +.B \-cycles \fInumber\fP +Duration. 100 - 5000. Default: 3000. +.TP 8 +.B \-ncolors \fInumber\fP +Number of Colors. Default: 64. +.TP 8 +.B \-delay \fInumber\fP +Per-frame delay, in microseconds. Default: 10000 (0.01 seconds.). +.TP 8 +.B \-fps +Display the current frame rate and CPU load. +.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 2002 by Stephen Montgomery-Smith. 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 +Stephen Montgomery-Smith. diff --git a/hacks/euler2d.tex b/hacks/euler2d.tex new file mode 100644 index 00000000..700ad317 --- /dev/null +++ b/hacks/euler2d.tex @@ -0,0 +1,337 @@ +\documentclass[12pt]{article} + +%\usepackage{fullpage} +\usepackage{amsmath,amssymb} + +\begin{document} + +\title{Two Dimensional Euler Simulation} + +\author{ +S.J. Montgomery-Smith\\ +Department of Mathematics\\ +University of Missouri\\ +Columbia, MO 65211, U.S.A.\\ +stephen@math.missouri.edu\\ +http://www.math.missouri.edu/\~{}stephen} + +\date{September 10, 2000} + +\maketitle + +This document describes a program I wrote to simulate the +two dimensional Euler Equation --- a program that is part +of the {\tt xlock} screensaver as the {\tt euler2d} +mode. A similar explanation may also be found in the +book by Chorin \cite{C}. + +\section{The Euler Equation} + +The Euler Equation describes the motion of an incompressible +fluid that has no viscosity. If the fluid is contained +in a domain $\Omega$ with boundary $\partial \Omega$, then +the equation is in the vector field $u$ (the velocity) +and the +scalar field $p$ (the pressure): +\begin{eqnarray*} +\frac{\partial}{\partial t} u &=& -u \cdot \nabla u + \nabla p \\ +\nabla \cdot u &=& 0 \\ +u \cdot n &=& 0 \quad \text{on $\partial \Omega$} +\end{eqnarray*} +where $n$ is the unit normal to $\partial \Omega$. + +\section{Vorticity} + +It turns out that it can be easier write these equations +in terms of the vorticity. In two dimensions the vorticity +is the scalar $w = \partial u_2/\partial x - \partial u_1/\partial y$. +The equation for vorticity becomes +\[ \frac{\partial}{\partial t} w = -u \cdot \nabla w .\] +A solution to this equation can be written as follows. The velocity +$u$ causes a flow, that is, a function $\varphi(t,x)$ that tells where +the particle initially at $x$ ends up at time $t$, that is +\[ +\frac\partial{\partial t} \varphi(t,x) += u(t,\varphi(t,x)) .\] +Then the equation +for $w$ tells us that the vorticity is ``pushed'' around by the flow, +that is, $w(t,\varphi(t,x)) = w(0,x)$. + +\section{The Biot-Savart Kernel} + +Now, once we have the vorticity, we can recover the velocity $u$ by +solving the equation +\begin{eqnarray*} +\partial u_2/\partial x - \partial u_1/\partial y &=& w \\ +\nabla \cdot u &=& 0 \\ +u \cdot n &=& 0 \quad \text{on $\partial \Omega$}. +\end{eqnarray*} +This equation is solved by using a Biot-Savart kernel $K(x,y)$: +$$ u(x) = \int_\Omega K(x,y) w(y) \, dy .$$ +The function $K$ depends upon the choice of domain. First let us consider +the case when $\Omega$ is the whole plane (in which case the boundary +condition $u \cdot n = 0$ is replaced by saying that $u$ decays at infinity). +Then +\begin{equation*} +K(x,y) = K_1(x,y) = c \frac{(x-y)^\perp}{|x-y|^2} . +\end{equation*} +Here $x^\perp = (-x_2,x_1)$, and $c$ is a constant, probably something +like $1/2\pi$. In any case we will set it to be one, which in effect +is rescaling the time variable, so we don't need to worry about it. + +We can use this as a basis to find $K$ on the unit disk +$\Omega = \Delta = \{x:|x|<1\}$. It turns out to be +\begin{equation*} +K_2(x,y) = K_1(x,y) - K_1(x,y^*) , +\end{equation*} +where $y^* = y/|y|^2$ is called the reflection of $y$ about the +boundary of the unit disk. + +Another example is if we have a bijective analytic function +$p:\Delta \to {\mathbb C}$, and we let $\Omega = p(\Delta)$. +(Here we think of $\Delta$ as a subset of $\mathbb C$, that is, +we are identifying the plane with the set of complex numbers.) +In that case we get +\[ K_p(p(x),p(y)) = K_2(x,y)/|p'(x)|^2 .\] +Our simulation considers the last case. Examples of such +analytic functions include series +$p(x) = x + \sum_{n=2}^\infty c_n x^n$, where +$\sum_{n=2}^\infty n |c_n| \le 1$. +(Thanks to David Ullrich for pointing this out to me.) + +\section{The Simulation} + +Now let's get to decribing the simulation. We assume a rather +unusual initial distribution for the vorticity --- that the +vorticity is a finite sum of dirac delta masses. +\[ w(0,x) = \sum_{k=1}^N w_k \delta(x-x_k(0)) .\] +Here $x_k(0)$ is the initial place where the points +of vorticity are concentrated, with values $w_k$. +Then at time $t$, the vorticity becomes +\[ w(t,x) = \sum_{k=1}^N w_k \delta(x-x_k(t)) .\] +The points of fluid $x_k(t)$ are pushed by the +flow, that is, $x_k(t) = \varphi(t,x_k(0))$, or +\[ \frac{\partial}{\partial t} x_k(t) = u(t,x_k(t)) .\] +Putting this all together, we finally obtain the equations +\[ \frac{\partial}{\partial t} x_k = \alpha_k \] +where +\[ \alpha_k = \sum_{l=1}^N w_l K(x_k,x_l) .\] +This is the equation that our simulation solves. + +In fact, in our case, where the domain is $p(\Delta)$, +the points are described by points +$\tilde x_k$, where $x_k = p(\tilde x_k)$. Then +the equations become +\begin{eqnarray} +\label{tildex-p1} +\frac{\partial}{\partial t} \tilde x_k &=& \tilde\alpha_k \\ +\label{tildex-p2} +\tilde\alpha_k &=& \frac1{|p'(\tilde x_k)|^2} + \sum_{l=1}^N w_l K_2(\tilde x_k,\tilde x_l) . +\end{eqnarray} + +We solve this $2N$ system of equations using standard +numerical methods, in our case, using the second order midpoint method +for the first step, and thereafter using the second order Adams-Bashforth +method. (See for example the book +by Burden and Faires \cite{BF}). + +\section{The Program - Data Structures} + +The computer program solves equation (\ref{tildex-p1}), and displays +the results on the screen, with a boundary. All the information +for solving the equation and displaying the output is countained +in the structure {\tt euler2dstruct}. Let us describe some of +the fields in {\tt euler2dstruct}. +The points $\tilde x_k$ are contained +in {\tt double *x}: with the coordinates of +$\tilde x_k$ being the two numbers +{\tt x[2*k+0]}, {\tt x[2*k+1]}. The values $w_k$ are contained +in {\tt double *w}. The total number of points is +{\tt int N}. (But only the first {\tt int Nvortex} points +have $w_k \ne 0$.) The coefficients of the analytic function +(in our case a polynomial) $p$ +are contained in {\tt double p\_coef[2*(deg\_p-1)]} --- here +{\tt deg\_p} is the degree of $p$, and the real and imaginary +parts of the coefficient +$c_n$ is contained in {\tt p\_coef[2*(n-2)+0]} and {\tt p\_coef[2*(n-2)+1]}. + +\section{Data Initialization} + +The program starts in the function {\tt init\_euler2d}. After allocating +the memory for the data, and initialising some of the temporary variables +required for the numerical solving program, it randomly assigns the +coefficients of $p$, making sure that $\sum_{n=2}^{\tt deg\_p} n |c_n| = 1$. +Then the program figures out how to draw the boundary, and what rescaling +of the data is required to draw it on the screen. (This uses the +function {\tt calc\_p} which calculates $p(x)$.) + +Next, it randomly assigns the initial values of $\tilde x_k$. We want +to do this in such a way so that the points are uniformly spread over the +domain. Let us first consider the case when the domain is the unit circle +$\Delta$. In that case the proportion of points that we would expect +inside the circle of radius $r$ would be proportional to $r^2$. So +we do it as follows: +\[ r = \sqrt{R_{0,1}},\quad \theta = R_{-\pi,\pi}, \quad + \tilde x_k = r (\cos \theta, \sin \theta) .\] +Here, and in the rest of this discussion, $R_{a,b}$ is a function +that returns a random variable uniformly distributed over the interval +$[a,b]$. + +This works fine for $\Delta$, but for $p(\Delta)$, the points +$p(\tilde x_k)$ are not uniformly distributed over $p(\Delta)$, +but are distributed with a density proportional to +$1/|p'(\tilde x_k)|^2$. So to restore the uniform density we need +to reject this value of $\tilde x_k$ with probability proportional +to $|p'(\tilde x_k)|^2$. Noticing that the condition +$\sum_{n=2}^{\tt deg\_p} n |c_n| = 1$ implies that +$|p'(\tilde x_k)| \le 2$, we +do this by rejecting if $|p'(\tilde x_k)|^2 < R_{0,4}$. +(This makes use of the function {\tt calc\_mod\_dp2} which calculates +$|p'(x)|^2$.) + +\section{Solving the Equation} + +The main loop of the program is in the function {\tt draw\_euler2d}. +Most of the drawing operations are contained in this function, and +the numerical aspects are sent to the function {\tt ode\_solve}. +But there is an aspect of this that I would like +to discuss in the next section, and so we will look at a simple method for +numerically solving differential equations. + +The Euler Method +(nothing to do with the Euler Equation), is as +follows. Pick a small number $h$ --- the time step (in +the program call {\tt delta\_t}). Then we approximate +the solution of the equation: +\begin{equation} +\label{method-simple} +\tilde x_k(t+h) = \tilde x_k(t) + h \tilde\alpha_k(t) . +\end{equation} +The more sophisticated methods we use are variations of +the Euler Method, and so the discussion in the following section +still applies. + +In the program, the quantities $\tilde\alpha_k$, given by +equations (\ref{tildex-p2}) are calculated by the function +{\tt derivs} +(which in turns calls {\tt calc\_all\_mod\_dp2} to +calculate $|p'(\tilde x_k)|^2$ at all the points). + + +\section{Subtle Perturbation} + +Added later: the scheme described here seems to not be that effective, +so now it is not used. + +One problem using a numerical scheme such as the Euler Method occurs +when the points $\tilde x_k$ get close to the boundary +of $\Delta$. In that case, it is possible that the new +points will be pushed outside of the boundary. Even if they +are not pushed out of the boundary, they may be much closer +or farther from the boundary than they should be. +Our system of equations is very sensitive to how close points +are to the boundary --- points with non-zero vorticity +(``vortex points'') that are close to the boundary travel +at great speed alongside the boundary, with speed that is +inversely proportional to the distance from the boundary. + +A way to try to mitigate this problem is something that I call +``subtle perturbation.'' +We map the points in +the unit disk to points in the plane using the map +\begin{equation*} +F(x) = f(|x|) \frac x{|x|} , +\end{equation*} +where $f:[0,1]\to[0,\infty]$ is an increasing continuous +bijection. It turns out that a good choice is +\begin{equation*} +f(t) = -\log(1-t) . +\end{equation*} +(The reason for this is that points close to each other +that are a distance +about $r$ from the boundary will be pushed around so that +their distance from each other is about multiplied by the +derivative of $\log r$, that is, $1/r$.) +Note that the inverse of this function is given by +\begin{equation*} +F^{-1}(x) = f^{-1}(|x|) \frac x{|x|} , +\end{equation*} +where +\begin{equation*} +f^{-1}(t) = 1-e^{-t} . +\end{equation*} + +So what we could do is the following: instead of working with +the points $\tilde x_k$, we could work instead with the points +$y_k = F(\tilde x_k)$. In effect this is what we do. +Instead of performing the computation (\ref{method-simple}), +we do the calculation +\begin{equation*} +y_k = F(\tilde x_k(t)) + h {\cal A}(\tilde x_k) \tilde\alpha_k(t) +\end{equation*} +where +${\cal A}(x)$ is the matrix of partial derivatives of $F$: +\begin{equation*} +{\cal A}(x) = +\frac{f(|x|)}{|x|} +\left[ +\begin{matrix} +1 & 0\\ +0 & 1 +\end{matrix} +\right] ++ \frac1{|x|} + \left(\frac{f'(|x|)}{|x|} - \frac{f(|x|)}{|x|^2}\right) +\left[ +\begin{matrix} +x_{1}^2 & x_{1} x_{2}\\ +x_{1} x_{2} & x_{2}^2 +\end{matrix} +\right], +\end{equation*} +and then compute +\begin{equation*} +\tilde x_k(t+h) = F^{-1}(y_k). +\end{equation*} +These calculations are done in the function {\tt perturb}, if +the quantity {\tt SUBTLE\_PERTURB} is set. + +\section{Drawing the Points} + +As we stated earlier, most of the drawing functions are contained +in the function {\tt draw\_euler2d}. If the variable +{\tt hide\_vortex} is set (and the function {\tt init\_euler2d} +will set this with probability $3/4$), then we only display +the points $\tilde x_k$ for ${\tt Nvortex} < k \le N$. If +{\tt hide\_vortex} is not set, then the ``vortex points'' +$\tilde x_k$ ($1 \le k \le {\tt Nvortex}$) are displayed in white. +In fact the points $p(\tilde x_k)$ are what are put onto the screen, +and for this we make use of the function {\tt calc\_all\_p}. + +\section{Addition to Program: Changing the Power Law} + +A later addition to the program adds an option {\tt eulerpower}, +which allows one to change the power law that describes how +the vortex points influence other points. In effect, if this +option is set with the value $m$, then the Biot-Savart Kernel +is replace by +$$ K_1(x,y) = \frac{(x-y)^\perp}{|x-y|^{m+1}}, $$ +and +$$ K_2(x,y) = K_1(x,y) - |y|^{1-m} K_1(x,y) .$$ +So for example, setting $m=2$ corresponds to the +quasi-geostrophic equation. (I haven't yet figured out +what $K_p$ should be, so if $m \ne 1$ we use the unit circle +as the boundary.) + +\begin{thebibliography}{9} + +\bibitem{BF} Richard L. Burden, J. Douglas Faires, Numerical Analysis, +sixth edition, Brooks/Cole, 1996. + +\bibitem{C} Alexandre J. Chorin, Vorticity and Turbulence, +Applied Mathematical Sciences, Vol 103, Springer Verlag, 1994. + +\end{thebibliography} + +\end{document} diff --git a/hacks/fadeplot.c b/hacks/fadeplot.c new file mode 100644 index 00000000..9fa65f8f --- /dev/null +++ b/hacks/fadeplot.c @@ -0,0 +1,245 @@ +/* -*- Mode: C; tab-width: 4 -*- */ +/* fadeplot --- a fading plot of sine squared */ + +#if 0 +static const char sccsid[] = "@(#)fadeplot.c 5.00 2000/11/01 xlockmore"; +#endif + +/*- + * Some easy plotting stuff, by Bas van Gaalen, Holland, PD + * + * Copyright (c) 1996 by Charles Vidal + * + * Permission to use, copy, modify, and distribute this software and its + * documentation for any purpose and without fee is hereby granted, + * provided that the above copyright notice appear in all copies and that + * both that copyright notice and this permission notice appear in + * supporting documentation. + * + * This file is provided AS IS with no warranties of any kind. The author + * shall have no liability with respect to the infringement of copyrights, + * trade secrets or any patents by this file or any part thereof. In no + * event will the author be liable for any lost revenue or profits or + * other special, indirect and consequential damages. + * + * Revision History: + * 01-Nov-2000: Allocation checks + * 10-May-1997: Compatible with screensaver + * 1996: Written by Charles Vidal based on work by Bas van Gaalen + */ + +#ifdef STANDALONE +# define MODE_fadeplot +# define DEFAULTS "*delay: 30000 \n" \ + "*count: 10 \n" \ + "*cycles: 1500 \n" \ + "*ncolors: 64 \n" \ + "*fpsSolid: true \n" \ + +# define BRIGHT_COLORS +# define UNIFORM_COLORS +# define fadeplot_handle_event 0 +# include "xlockmore.h" /* in xscreensaver distribution */ +#else /* STANDALONE */ +# include "xlock.h" /* in xlockmore distribution */ +#endif /* STANDALONE */ + +#ifdef MODE_fadeplot + +ENTRYPOINT ModeSpecOpt fadeplot_opts = +{0, (XrmOptionDescRec *) NULL, 0, (argtype *) NULL, (OptionStruct *) NULL}; + +#ifdef USE_MODULES +ModStruct fadeplot_description = +{"fadeplot", "init_fadeplot", "draw_fadeplot", "release_fadeplot", + "refresh_fadeplot", "init_fadeplot", (char *) NULL, &fadeplot_opts, + 30000, 10, 1500, 1, 64, 0.6, "", + "Shows a fading plot of sine squared", 0, NULL}; + +#endif + +#define MINSTEPS 1 + +typedef struct { + XPoint speed, step, factor, st; + int temps, maxpts, nbstep; + int min; + int width, height; + int pix; + int angles; + int *stab; + XPoint *pts; +} fadeplotstruct; + +static fadeplotstruct *fadeplots = (fadeplotstruct *) NULL; + +static void +free_fadeplot(fadeplotstruct *fp) +{ + if (fp->pts != NULL) { + (void) free((void *) fp->pts); + fp->pts = (XPoint *) NULL; + } + if (fp->stab != NULL) { + (void) free((void *) fp->stab); + fp->stab = (int *) NULL; + } +} + +static Bool +initSintab(ModeInfo * mi) +{ + fadeplotstruct *fp = &fadeplots[MI_SCREEN(mi)]; + int i; + float x; + + fp->angles = NRAND(950) + 250; + if ((fp->stab = (int *) malloc(fp->angles * sizeof (int))) == NULL) { + free_fadeplot(fp); + return False; + } + for (i = 0; i < fp->angles; i++) { + x = SINF(2.0 * M_PI * i / fp->angles); + fp->stab[i] = (int) (x * ABS(x) * fp->min) + fp->min; + } + return True; +} + +ENTRYPOINT void +init_fadeplot (ModeInfo * mi) +{ + fadeplotstruct *fp; + + if (fadeplots == NULL) { + if ((fadeplots = (fadeplotstruct *) calloc(MI_NUM_SCREENS(mi), + sizeof (fadeplotstruct))) == NULL) + return; + } + fp = &fadeplots[MI_SCREEN(mi)]; + + fp->width = MI_WIDTH(mi); + fp->height = MI_HEIGHT(mi); + fp->min = MAX(MIN(fp->width, fp->height) / 2, 1); + + fp->speed.x = 8; + fp->speed.y = 10; + fp->step.x = 1; + fp->step.y = 1; + fp->temps = 0; + fp->factor.x = MAX(fp->width / (2 * fp->min), 1); + fp->factor.y = MAX(fp->height / (2 * fp->min), 1); + + fp->nbstep = MI_COUNT(mi); + if (fp->nbstep < -MINSTEPS) { + fp->nbstep = NRAND(-fp->nbstep - MINSTEPS + 1) + MINSTEPS; + } else if (fp->nbstep < MINSTEPS) + fp->nbstep = MINSTEPS; + + fp->maxpts = MI_CYCLES(mi); + if (fp->maxpts < 1) + fp->maxpts = 1; + + if (fp->pts == NULL) { + if ((fp->pts = (XPoint *) calloc(fp->maxpts, sizeof (XPoint))) == + NULL) { + free_fadeplot(fp); + return; + } + } + if (MI_NPIXELS(mi) > 2) + fp->pix = NRAND(MI_NPIXELS(mi)); + + if (fp->stab != NULL) + (void) free((void *) fp->stab); + if (!initSintab(mi)) + return; + MI_CLEARWINDOW(mi); +} + +ENTRYPOINT void +draw_fadeplot (ModeInfo * mi) +{ + Display *display = MI_DISPLAY(mi); + Window window = MI_WINDOW(mi); + GC gc = MI_GC(mi); + int i, j, temp; + fadeplotstruct *fp; + + if (fadeplots == NULL) + return; + fp = &fadeplots[MI_SCREEN(mi)]; + if (fp->stab == NULL) + return; + + MI_IS_DRAWN(mi) = True; + XSetForeground(display, gc, MI_BLACK_PIXEL(mi)); + XDrawPoints(display, window, gc, fp->pts, fp->maxpts, CoordModeOrigin); + + if (MI_NPIXELS(mi) > 2) { + XSetForeground(display, gc, MI_PIXEL(mi, fp->pix)); + if (++fp->pix >= MI_NPIXELS(mi)) + fp->pix = 0; + } else + XSetForeground(display, gc, MI_WHITE_PIXEL(mi)); + + temp = 0; + for (j = 0; j < fp->nbstep; j++) { + for (i = 0; i < fp->maxpts / fp->nbstep; i++) { + fp->pts[temp].x = + fp->stab[(fp->st.x + fp->speed.x * j + i * fp->step.x) % fp->angles] * + fp->factor.x + fp->width / 2 - fp->min; + fp->pts[temp].y = + fp->stab[(fp->st.y + fp->speed.y * j + i * fp->step.y) % fp->angles] * + fp->factor.y + fp->height / 2 - fp->min; + temp++; + } + } + XDrawPoints(display, window, gc, fp->pts, temp, CoordModeOrigin); + fp->st.x = (fp->st.x + fp->speed.x) % fp->angles; + fp->st.y = (fp->st.y + fp->speed.y) % fp->angles; + fp->temps++; + if ((fp->temps % (fp->angles / 2)) == 0) { + fp->temps = fp->temps % fp->angles * 5; + if ((fp->temps % (fp->angles)) == 0) + fp->speed.y = (fp->speed.y + 1) % 30 + 1; + if ((fp->temps % (fp->angles * 2)) == 0) + fp->speed.x = (fp->speed.x) % 20; + if ((fp->temps % (fp->angles * 3)) == 0) + fp->step.y = (fp->step.y + 1) % 2 + 1; + + MI_CLEARWINDOW(mi); + } +} + +ENTRYPOINT void +reshape_fadeplot(ModeInfo * mi, int width, int height) +{ + fadeplotstruct *fp = &fadeplots[MI_SCREEN(mi)]; + fp->width = width; + fp->height = height; + fp->min = MAX(MIN(fp->width, fp->height) / 2, 1); + fp->factor.x = MAX(fp->width / (2 * fp->min), 1); + fp->factor.y = MAX(fp->height / (2 * fp->min), 1); +} + +ENTRYPOINT void +refresh_fadeplot (ModeInfo * mi) +{ +} + +ENTRYPOINT void +release_fadeplot (ModeInfo * mi) +{ + if (fadeplots != NULL) { + int screen; + + for (screen = 0; screen < MI_NUM_SCREENS(mi); screen++) + free_fadeplot(&fadeplots[screen]); + (void) free((void *) fadeplots); + fadeplots = (fadeplotstruct *) NULL; + } +} + +XSCREENSAVER_MODULE ("FadePlot", fadeplot) + +#endif /* MODE_fadeplot */ diff --git a/hacks/fadeplot.man b/hacks/fadeplot.man new file mode 100644 index 00000000..d525afdb --- /dev/null +++ b/hacks/fadeplot.man @@ -0,0 +1,65 @@ +.TH XScreenSaver 1 "" "X Version 11" +.SH NAME +fadeplot - draws a waving ribbon following a sinusoidal path. +.SH SYNOPSIS +.B fadeplot +[\-display \fIhost:display.screen\fP] +[\-visual \fIvisual\fP] +[\-window] +[\-root] +[\-count \fInumber\fP] +[\-cycles \fInumber\fP] +[\-delay \fInumber\fP] +[\-ncolors \fInumber\fP] +[\-fps] +.SH DESCRIPTION +Draws what looks like a waving ribbon following a sinusoidal path. +.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 \-count \fInumber\fP +Count. 0 - 20. Default: 10. +.TP 8 +.B \-cycles \fInumber\fP +How many frames until the shape changes. Default: 1500. +.TP 8 +.B \-delay \fInumber\fP +Per-frame delay, in microseconds. Default: 30000 (0.03 seconds.). +.TP 8 +.B \-ncolors \fInumber\fP +Number of colors. Default: 64. +.TP 8 +.B \-fps +Display the current frame rate and CPU load. +.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 2002 by Bas van Gaalen and Charles Vidal. 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 +Bas van Gaalen and Charles Vidal. diff --git a/hacks/fiberlamp.c b/hacks/fiberlamp.c new file mode 100644 index 00000000..062f62ff --- /dev/null +++ b/hacks/fiberlamp.c @@ -0,0 +1,473 @@ +/* -*- Mode: C; tab-width: 4 -*- */ +/* fiberlamp --- A Fiber Optic Lamp */ + +#if !defined( lint ) && !defined( SABER ) +static const char sccsid[] = "@(#)fiberlamp.c 5.00 2000/11/01 xlockmore"; + +#endif + +/*- + * Copyright (c) 2005 by Tim Auckland + * + * Permission to use, copy, modify, and distribute this software and its + * documentation for any purpose and without fee is hereby granted, + * provided that the above copyright notice appear in all copies and that + * both that copyright notice and this permission notice appear in + * supporting documentation. + * + * This file is provided AS IS with no warranties of any kind. The author + * shall have no liability with respect to the infringement of copyrights, + * trade secrets or any patents by this file or any part thereof. In no + * event will the author be liable for any lost revenue or profits or + * other special, indirect and consequential damages. + * + * "fiberlamp" shows Fiber Optic Lamp. Since there is no closed-form + * solution to the large-amplitude cantilever equation, the flexible + * fiber is modeled as a set of descrete nodes. + * + * Revision History: + * 13-Jan-2005: Initial development. + */ + +#ifdef STANDALONE +#define MODE_fiberlamp +#define DEFAULTS "*delay: 10000 \n" \ + "*count: 500 \n" \ + "*cycles: 10000 \n" \ + "*ncolors: 64 \n" \ + "*fpsTop: true \n" \ + +# define UNIFORM_COLORS +# define fiberlamp_handle_event 0 +# include "xlockmore.h" /* in xscreensaver distribution */ +#else /* STANDALONE */ +# include "xlock.h" /* in xlockmore distribution */ +#endif /* STANDALONE */ + +#ifdef MODE_fiberlamp + +ENTRYPOINT ModeSpecOpt fiberlamp_opts = +{0, (XrmOptionDescRec *) NULL, 0, (argtype *) NULL, (OptionStruct *) NULL}; + +#ifdef USE_MODULES +ModStruct fiberlamp_description = +{"fiberlamp", "init_fiberlamp", "draw_fiberlamp", "release_fiberlamp", + "draw_fiberlamp", "change_fiberlamp", (char *) NULL, &fiberlamp_opts, + 1000, 500, 10000, 0, 64, 1.0, "", "Shows a Fiber Optic Lamp", 0, NULL}; + +#endif + +#define SPREAD (30.0) /* Angular spread at the base */ +#define SCALE (MI_WIDTH(mi)/2) /* Screen size */ +#define NODES (20) /* Number of nodes in a fiber. Variable with range + 10 .. 30, if desired. High values have + stability problems unless you use small DT */ + +/* Physics parameters. Tune carefully to keep realism and avoid instability*/ +#define DT (0.5) /* Time increment: Low is slow, High is less stable. */ +#define PY (0.12) /* Rigidity: Low droops, High is stiff. */ +#define DAMPING (0.055) /* Damping: Low allows oscillations, High is boring. */ + +#undef PLAN /* Plan view (for debugging) */ +#undef CHECKCOLORWHEEL /* Plan view with no spread */ + +#define DRAND(v) (LRAND()/MAXRAND*(v)) /* double random 0 - v */ + +/* Length of nodes. Uniform except for shorter notes at the tips for + colour highlights. Sum from 0..NODES-1 should exactly 1.0 */ +#define LEN(A) ((Acx = (DRAND(SCALE/4)-SCALE/8)/SCALE; /* Knock the lamp */ + fl->count = 0; /* Reset counter */ + if (fl->dbufp) { + XSetForeground(MI_DISPLAY(mi), MI_GC(mi), MI_BLACK_PIXEL(mi)); + XFillRectangle(MI_DISPLAY(mi), fl->buffer, MI_GC(mi), 0, 0, + MI_WIDTH(mi), MI_HEIGHT(mi)); + } +} + +static void +free_fiber(fiberlampstruct *fl) +{ + if (fl->fiber) { + int f; + + for (f = 0; f < fl->nfibers; f++) { + fiberstruct *fs = fl->fiber + f; + + if (fs->node) + free(fs->node); + if (fs->draw) + free(fs->draw); + } + free(fl->fiber); + fl->fiber = NULL; + } +} + +static void +free_fiberlamp(ModeInfo *mi, fiberlampstruct *fl) +{ + if (fl->buffer != None && fl->dbufp) { + XFreePixmap(MI_DISPLAY(mi), fl->buffer); + fl->buffer = None; + } + free_fiber(fl); +} + +ENTRYPOINT void +init_fiberlamp(ModeInfo * mi) +{ + fiberlampstruct *fl; + + if (fiberlamps == NULL) { + if ((fiberlamps = + (fiberlampstruct *) calloc(MI_NUM_SCREENS(mi), + sizeof (fiberlampstruct))) == NULL) + return; + } + fl = &fiberlamps[MI_SCREEN(mi)]; + + /* Create or Resize double buffer */ +#ifdef HAVE_COCOA /* Don't second-guess Quartz's double-buffering */ + fl->dbufp = False; +#else + fl->dbufp = True; +#endif + + if(fl->buffer != None && fl->buffer != MI_WINDOW(mi) && fl->dbufp) + XFreePixmap(MI_DISPLAY(mi), fl->buffer); + + if(fl->dbufp) { + fl->buffer = XCreatePixmap(MI_DISPLAY(mi), MI_WINDOW(mi), + MI_WIDTH(mi), MI_HEIGHT(mi), MI_DEPTH(mi)); + if (fl->buffer == None) { + free_fiberlamp(mi, fl); + return; + } + } else { + fl->buffer = MI_WINDOW(mi); + } + + XSetForeground(MI_DISPLAY(mi), MI_GC(mi), MI_BLACK_PIXEL(mi)); + XFillRectangle(MI_DISPLAY(mi), fl->buffer, MI_GC(mi), 0, 0, + MI_WIDTH(mi), MI_HEIGHT(mi)); + + if(fl->init) /* Nothing else to do (probably a resize) */ + return; + + fl->init = True; + fl->nfibers = MI_COUNT(mi); + /* Allocate fibers */ + if((fl->fiber = + (fiberstruct*) calloc(fl->nfibers, sizeof (fiberstruct))) == NULL) { + free_fiberlamp(mi, fl); + return; + } else { + int f; + for(f = 0; f < fl->nfibers; f++) { + fiberstruct *fs = fl->fiber + f; + if((fs->node = + (nodestruct*) calloc(NODES, sizeof (nodestruct))) == NULL + ||(fs->draw = + (XPoint*) calloc(NODES, sizeof (XPoint))) == NULL) { + free_fiberlamp(mi, fl); + return; + } + } + } + + { + int f, i; + for(f = 0; f < fl->nfibers; f++) { + double phi = M_PI/180 * DRAND(SPREAD); + double eta = DRAND(2*M_PI) - M_PI; + for(i = 0; i < NODES; i++) { + nodestruct *n = &fl->fiber[f].node[i]; + n->phi = phi; + n->phidash = 0; + n->eta = eta; + n->etadash = 0; + } + fl->fiber[f].node[0].etadash = 0.002/DT; + fl->fiber[f].node[0].y = 0; + fl->fiber[f].node[0].z = 0; + } + + } + + /* Set up rotation */ + fl->psi = DRAND(2*M_PI); + fl->dpsi = 0.01; + + /* no "NoExpose" events from XCopyArea wanted */ + XSetGraphicsExposures(MI_DISPLAY(mi), MI_GC(mi), False); + + /* Make sure we're using 'thin' lines */ + XSetLineAttributes(MI_DISPLAY(mi), MI_GC(mi), 0, LineSolid, CapNotLast, + JoinMiter); +#ifdef CHECKCOLORWHEEL + /* Only interested in tips, leave the rest black */ + fl->bright = fl->medium = fl->dim = MI_BLACK_PIXEL(mi); +#else + if(MI_NPIXELS(mi) > 2) { + /* Set up colours for the fiber bodies. Tips handled seperately */ + XColor c, t; + if(XAllocNamedColor(MI_DISPLAY(mi), MI_COLORMAP(mi), "#E0E0C0", &c, &t)){ + fl->bright = c.pixel; + } else { + fl->bright = MI_WHITE_PIXEL(mi); + } + if(XAllocNamedColor(MI_DISPLAY(mi), MI_COLORMAP(mi), "#808070", &c, &t)){ + fl->medium = c.pixel; + } else { + fl->medium = MI_WHITE_PIXEL(mi); + } + if(XAllocNamedColor(MI_DISPLAY(mi), MI_COLORMAP(mi), "#404020", &c, &t)){ + fl->dim = c.pixel; + } else { + fl->dim = MI_BLACK_PIXEL(mi); + } + } else { + fl->bright = MI_WHITE_PIXEL(mi); + fl->medium = MI_WHITE_PIXEL(mi); + fl->dim = MI_BLACK_PIXEL(mi); + } +#endif + + /* Clear the background. */ + MI_CLEARWINDOW(mi); + change_fiberlamp(mi); +} + +/* Used by xscreensaver. xlock just uses init_fiberlamp */ +ENTRYPOINT void +reshape_fiberlamp(ModeInfo * mi, int width, int height) +{ + init_fiberlamp(mi); +} + +/* sort fibers so they get drawn back-to-front, one bubble pass is + enough as the order only changes slowly */ +static void +sort_fibers(fiberlampstruct *fl) +{ + int i; + + for(i = 1; i < fl->nfibers; i++) { + if (fl->fiber[i - 1].node[NODES - 1].z > fl->fiber[i].node[NODES - 1].z) { + fiberstruct tmp = fl->fiber[i - 1]; + fl->fiber[i - 1] = fl->fiber[i]; + fl->fiber[i] = tmp; + } + } +} + +ENTRYPOINT void +draw_fiberlamp (ModeInfo * mi) +{ + fiberlampstruct *fl; + int f, i; + int x, y; + Window unused; + + short cx = MI_WIDTH(mi)/2; +#if defined PLAN || defined CHECKCOLORWHEEL + short cy = MI_HEIGHT(mi)/2; +#else + short cy = MI_HEIGHT(mi); +#endif + + if (fiberlamps == NULL) + return; + fl = &fiberlamps[MI_SCREEN(mi)]; + + fl->psi += fl->dpsi; /* turn colorwheel */ + + XTranslateCoordinates(MI_DISPLAY(mi), MI_WINDOW(mi), + RootWindow(MI_DISPLAY(mi),0/*#### MI_SCREEN(mi)*/), + cx, cy, &x, &y, &unused); + sort_fibers(fl); + + for(f = 0; f < fl->nfibers; f++) { + fiberstruct *fs = fl->fiber + f; + + fs->node[0].eta += DT*fs->node[0].etadash; + fs->node[0].x = fl->cx; /* Handle center movement */ + /* Handle window move. NOTE, only x is deflected, since y doesn't + directly affect the physics */ + fs->node[NODES-2].x *= 0.1*(fl->ry - y); + fs->node[NODES-2].x += 0.05*(fl->rx - x); + + /* 2nd order diff equation */ + for(i = 1; i < NODES; i++) { + nodestruct *n = fs->node+i; + nodestruct *p = fs->node+i-1; + double pload = 0; + double eload = 0; + double pstress = (n->phi - p->phi)*PY; + double estress = (n->eta - p->eta)*PY; + double dxi = n->x - p->x; + double dzi = n->z - p->z; + double li = sqrt(dxi*dxi + dzi*dzi)/LEN(i); + double drag = DAMPING*LEN(i)*LEN(i)*NODES*NODES; + + if(li > 0) { + int j; + for(j = i+1; j < NODES; j++) { + nodestruct *nn = fs->node+j; + double dxj = nn->x - n->x; + double dzj = nn->z - n->z; + + pload += LEN(j)*(dxi*dxj + dzi*dzj)/li; /* Radial load */ + eload += LEN(j)*(dxi*dzj - dzi*dxj)/li; /* Transverse load */ + /* Not a perfect simulation: in reality the transverse load + is only indirectly coupled to the eta deflection, but of + all the approaches I've tried this produces the most + stable model and looks the most realistic. */ + } + } + +#ifndef CHECKCOLORWHEEL + n->phidash += DT*(pload - pstress - drag*n->phidash)/LEN(i); + n->phi += DT*n->phidash; +#endif + + n->etadash += DT*(eload - estress - drag*n->etadash)/LEN(i); + n->eta += DT*n->etadash; + + { + double sp = sin(p->phi); + double cp = cos(p->phi); + double se = sin(p->eta); + double ce = cos(p->eta); + + n->x = p->x + LEN(i-1) * ce * sp; + n->y = p->y - LEN(i-1) * cp; + n->z = p->z + LEN(i-1) * se * sp; + } + + fs->draw[i-1].x = cx + MI_WIDTH(mi)/2*n->x; +#if defined PLAN || defined CHECKCOLORWHEEL /* Plan */ + fs->draw[i-1].y = cy + MI_WIDTH(mi)/2*n->z; +#else /* Elevation */ + fs->draw[i-1].y = cy + MI_WIDTH(mi)/2*n->y; +#endif + } + MI_IS_DRAWN(mi) = True; + + /* Erase: this may only be erasing an off-screen buffer, but on a + slow system it may still be faster than XFillRectangle() */ + /* That's unpossible. -jwz */ + } + + XSetForeground(MI_DISPLAY(mi), MI_GC(mi), MI_BLACK_PIXEL(mi)); + XFillRectangle(MI_DISPLAY(mi), fl->buffer, MI_GC(mi), + 0, 0, MI_WIDTH(mi), MI_HEIGHT(mi)); + + for(f = 0; f < fl->nfibers; f++) { + fiberstruct *fs = fl->fiber + f; + + { + double x = fs->node[1].x - fl->cx + 0.025; + double y = fs->node[1].z + 0.02; + double angle = atan2(y, x) + fl->psi; + int tipcolor = (int)(MI_NPIXELS(mi)*angle/(2*M_PI)) % MI_NPIXELS(mi); + int fibercolor; + int tiplen; + + if (tipcolor < 0) tipcolor += MI_NPIXELS(mi); + tipcolor = MI_PIXEL(mi, tipcolor); + + if(fs->node[1].z < 0.0) { /* Back */ + tiplen = 2; + fibercolor = fl->dim; + }else if(fs->node[NODES-1].z < 0.7) { /* Middle */ + tiplen = 3; + fibercolor = fl->medium; + } else { /* Front */ + tiplen = 3; + fibercolor = fl->bright; + } + + XSetForeground(MI_DISPLAY(mi), MI_GC(mi), fibercolor); + XDrawLines(MI_DISPLAY(mi), fl->buffer, MI_GC(mi), + fs->draw, NODES-tiplen, CoordModeOrigin); + + XSetForeground(MI_DISPLAY(mi), MI_GC(mi), tipcolor); + XDrawLines(MI_DISPLAY(mi), fl->buffer, MI_GC(mi), + fs->draw+NODES-1-tiplen, tiplen, CoordModeOrigin); + } + } + + /* Update the screen from the double-buffer */ + if (fl->dbufp) + XCopyArea(MI_DISPLAY(mi), fl->buffer, MI_WINDOW(mi), MI_GC(mi), 0, 0, + MI_WIDTH(mi), MI_HEIGHT(mi), 0, 0); + + fl->rx = x; + fl->ry = y; + + if(fl->count++ > MI_CYCLES(mi)) { + change_fiberlamp(mi); + } +} + +ENTRYPOINT void +release_fiberlamp(ModeInfo * mi) +{ + if (fiberlamps != NULL) { + int screen; + + for (screen = 0; screen < MI_NUM_SCREENS(mi); screen++) + free_fiberlamp(mi, &fiberlamps[screen]); + free(fiberlamps); + fiberlamps = (fiberlampstruct *) NULL; + } +} + +ENTRYPOINT void +refresh_fiberlamp(ModeInfo * mi) +{ + MI_CLEARWINDOW(mi); +} + +XSCREENSAVER_MODULE ("Fiberlamp", fiberlamp) + +#endif /* MODE_fiberlamp */ diff --git a/hacks/fiberlamp.man b/hacks/fiberlamp.man new file mode 100644 index 00000000..da0d4f4e --- /dev/null +++ b/hacks/fiberlamp.man @@ -0,0 +1,65 @@ +.TH XScreenSaver 1 "" "X Version 11" +.SH NAME +fiberlamp - Fiber Optic Lamp +.SH SYNOPSIS +.B fiberlamp +[\-display \fIhost:display.screen\fP] +[\-visual \fIvisual\fP] +[\-window] +[\-root] +[\-count \fInumber\fP] +[\-cycles \fInumber\fP] +[\-delay \fInumber\fP] +[\-ncolors \fInumber\fP] +[\-fps] +.SH DESCRIPTION +Displays a Fiber Optic Lamp. +.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 \-count \fInumber\fP +Number of Fibers. 10 - 500. Default: 500. +.TP 8 +.B \-cycles \fInumber\fP +Number of cycles before the lamp is knocked sideways. 100 - 10000. +Default: 10000. +.TP 8 +.B \-delay \fInumber\fP +Per-frame delay, in microseconds. Default: 10000 (0.01 seconds.). +.TP 8 +.B \-ncolors \fInumber\fP +Number of Colors. Default: 64. +.TP 8 +.B \-fps +Display the current frame rate and CPU load. +.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 2005 by Tim Auckland. 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 +Tim Auckland. diff --git a/hacks/fireworkx.c b/hacks/fireworkx.c new file mode 100644 index 00000000..e0cfeee0 --- /dev/null +++ b/hacks/fireworkx.c @@ -0,0 +1,499 @@ +/* + * Fireworkx 1.6 - pyrotechnics simulation program (XScreensaver version) + * Copyright (c) 1999-2007 Rony B Chandran + * + * From Kerala, INDIA + * + * url: http://www.ronybc.8k.com + * + * 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. + * + * Additional programming: + * ------------------------ + * Support for different dpy color modes: + * Jean-Pierre Demailly + * + * Fixed array access problems by beating on it with a large hammer. + * Nicholas Miell + * + * Freed 'free'ing up of memory by adding the forgotten 'XSync's + * Renuka S + * + */ + +#include +#include "screenhack.h" + +#define FWXVERSION "1.6" + +#define SHELLCOUNT 3 /* 3 ; see light() before changing this value */ +#define PIXCOUNT 500 /* 500 */ +#define POWER 5 /* 5 */ +#define FTWEAK 12 /* 12 */ + +#if HAVE_X86_MMX +void mmx_blur(char *a, int b, int c, int d); +void mmx_glow(char *a, int b, int c, int d, char *e); +#endif + +#define rnd(x) ((x) ? (int)(random() % (x)) : 0) + +typedef struct { + unsigned int burn; + float x; + float y; + float xv; + float yv;}firepix; + +typedef struct { + unsigned int cx,cy; + unsigned int life; + unsigned int color; + unsigned int special; + unsigned int cshift; + unsigned int vgn,shy; + float air,flash; + firepix *fpix; }fireshell; + +struct state { + Display *dpy; + Window window; + + fireshell *fshell, *ffshell; + GC gc; + + int depth; + int bigendian; + Bool flash_on; + Bool glow_on; + Bool verbose; + Bool shoot; + int width; + int height; + int rndlife; + int minlife; + int delay; + float flash_fade; + unsigned char *palaka1; + unsigned char *palaka2; + XImage *xim; + XColor *colors; + int ncolors; +}; + +static int explode(struct state *st, fireshell *fs) +{ + float air,adg = 0.001; /* gravity */ + unsigned int n,c; + unsigned int h = st->height; + unsigned int w = st->width; + unsigned int *prgb; + unsigned char *palaka = st->palaka1; + firepix *fp = fs->fpix; + if(fs->vgn){ + if(--fs->cy == fs->shy){ + fs->vgn = 0; + fs->flash = rnd(30000)+25000; + fs->flash = fs->flash*fs->flash; } + else{ + fs->flash = 200000+(fs->cy - fs->shy)*(fs->cy - fs->shy)*8; + prgb=(unsigned int *)(palaka + (fs->cy * w + fs->cx + rnd(5)-2)*4); + *prgb=(rnd(8)+8)*0x000f0f10; + return(1);}} + if(fs->cshift) --fs->cshift; + if((fs->cshift+1)%50==0) fs->color = ~fs->color; + c = fs->color; + air = fs->air; + fs->flash *= st->flash_fade; + for(n=PIXCOUNT;n;n--){ + if(fp->burn){ --fp->burn; + if(fs->special){ + fp->x += fp->xv = fp->xv * air + (float)(rnd(200)-100)/2000; + fp->y += fp->yv = fp->yv * air + (float)(rnd(200)-100)/2000+ adg;} + else{ + fp->x += fp->xv = fp->xv * air + (float)(rnd(200)-100)/20000; + fp->y += fp->yv = fp->yv * air + (float)(rnd(200)-100)/40000+ adg; } + if(fp->y > h){ + if(rnd(5)==3) {fp->yv *= -0.24; fp->y = h;} + else fp->burn=0;} /* touch muddy ground :) */ + if(fp->x < w && fp->x > 0 && fp->y < h && fp->y > 0){ + prgb = (unsigned int *)(palaka + ((int)fp->y * w + (int)fp->x)*4); + *prgb = c; } + } fp++; + } return(--fs->life); } + +static void recycle(struct state *st, fireshell *fs,int x,int y) +{ + unsigned int n,pixlife; + firepix *fp = fs->fpix; + fs->vgn = st->shoot; + fs->shy = y; + fs->cx = x; + fs->cy = st->shoot ? st->height : y ; + fs->color = (rnd(155)+100) <<16 | + (rnd(155)+100) <<8 | + rnd(255); + fs->life = rnd(st->rndlife)+st->minlife; + fs->air = 1-(float)(rnd(200))/10000; + fs->flash = rnd(30000)+25000; /* million jouls... */ + fs->flash = fs->flash*fs->flash; + fs->cshift = !rnd(5) ? 120:0; + fs->special = !rnd(10) ? 1:0; + if(st->verbose) + printf("recycle(): color = %x air = %f life = %d \n",fs->color,fs->air,fs->life); + pixlife = rnd(fs->life)+fs->life/10+1; /* ! */ + for(n=0;nburn = rnd(pixlife)+32; + fp->xv = POWER*(float)(rnd(20000)-10000)/10000; + fp->yv = sqrt(POWER*POWER - fp->xv * fp->xv) * + (float)(rnd(20000)-10000)/10000; + fp->x = x; + fp->y = y; + fp++; }} + +static void glow(struct state *st) +{ + unsigned int n,q; + unsigned int w = st->width; + unsigned int h = st->height; + unsigned char *pa, *pb, *pm, *po; + if (!st->xim) return; + pm = st->palaka1; + po = st->palaka2; + for(n=0;n8 ? 8:q; + pm[n] = q>>4; + q = q>>3; + po[n] = q>255 ? 255 : q;} + pm+=n; po+=n; + for(n=0;nwidth; + unsigned int h = st->height; + unsigned char *pa, *pb, *pm; + pm = st->palaka1; + pm += w*4; h-=2; /* line 0&h */ + pa = pm-(w*4); + pb = pm+(w*4); + for(n=4;n8 ? 8:q; + pm[n] = q>>4;} + pm += n-4; /* last line */ + for(n=0;npalaka1; /* first line */ + for(n=0;nwidth; + int h = st->height; + unsigned char *dim = st->palaka2; + unsigned char *sim = st->palaka1; + int nl = w*4; + fireshell *f; + if(st->glow_on) sim=dim; + for(y=0;yflash/(1+(f->cx - x)*(f->cx - x)+(f->cy - y)*(f->cy - y));} */ + + s = f->flash/(1+(f->cx - x)*(f->cx - x)+(f->cy - y)*(f->cy - y)); + f++; + s += f->flash/(1+(f->cx - x)*(f->cx - x)+(f->cy - y)*(f->cy - y)); + f++; + s += f->flash/(1+(f->cx - x)*(f->cx - x)+(f->cy - y)*(f->cy - y)); + + l = sqrtf(s); + + t = l + sim[0]; + dim[0] = (t > 255 ? 255 : t); + t = l + sim[1]; + dim[1] = (t > 255 ? 255 : t); + t = l + sim[2]; + dim[2] = (t > 255 ? 255 : t); + + t = l + sim[4]; + dim[4] = (t > 255 ? 255 : t); + t = l + sim[5]; + dim[5] = (t > 255 ? 255 : t); + t = l + sim[6]; + dim[6] = (t > 255 ? 255 : t); + + t = l + sim[nl+0]; + dim[nl+0] = (t > 255 ? 255 : t); + t = l + sim[nl+1]; + dim[nl+1] = (t > 255 ? 255 : t); + t = l + sim[nl+2]; + dim[nl+2] = (t > 255 ? 255 : t); + + t = l + sim[nl+4]; + dim[nl+4] = (t > 255 ? 255 : t); + t = l + sim[nl+5]; + dim[nl+5] = (t > 255 ? 255 : t); + t = l + sim[nl+6]; + dim[nl+6] = (t > 255 ? 255 : t); + + sim += 8; dim += 8; } sim += nl; dim += nl;}} + +static void resize(struct state *st) +{ + XWindowAttributes xwa; + XGetWindowAttributes (st->dpy, st->window, &xwa); + xwa.width -= xwa.width % 2; + xwa.height -= xwa.height % 2; + if(xwa.height != st->height || xwa.width != st->width) { + st->width = xwa.width; + st->height = xwa.height; + if (st->verbose) + printf("sky size: %dx%d ------------------------------\n",st->width,st->height); + if (st->xim) { + if (st->xim->data==(char *)st->palaka2) st->xim->data=NULL; + XDestroyImage(st->xim); + if (st->palaka2!=st->palaka1) free(st->palaka2 - 8); + free(st->palaka1 - 8); + } + st->palaka1 = NULL; + st->palaka2 = NULL; + st->xim = XCreateImage(st->dpy, xwa.visual, xwa.depth, ZPixmap, 0, 0, + st->width, st->height, 8, 0); + if (!st->xim) return; + st->palaka1 = (unsigned char *) calloc(st->xim->height+1,st->xim->width*4) + 8; + if(st->flash_on|st->glow_on) + st->palaka2 = (unsigned char *) calloc(st->xim->height+1,st->xim->width*4) + 8; + else + st->palaka2 = st->palaka1; + if (st->depth>=24) + st->xim->data = (char *)st->palaka2; + else + st->xim->data = calloc(st->xim->height,st->xim->bytes_per_line); }} + +static void put_image(struct state *st) +{ + int x,y,i,j; + unsigned char r, g, b; + if (!st->xim) return; + i = 0; + j = 0; + if (st->depth==16) { + if(st->bigendian) + for (y=0;yxim->height; y++) + for (x=0;xxim->width; x++) { + r = st->palaka2[j++]; + g = st->palaka2[j++]; + b = st->palaka2[j++]; + j++; + st->xim->data[i++] = (g&224)>>5 | (r&248); + st->xim->data[i++] = (b&248)>>3 | (g&28)<<3; + } + else + for (y=0;yxim->height; y++) + for (x=0;xxim->width; x++) { + r = st->palaka2[j++]; + g = st->palaka2[j++]; + b = st->palaka2[j++]; + j++; + st->xim->data[i++] = (b&248)>>3 | (g&28)<<3; + st->xim->data[i++] = (g&224)>>5 | (r&248); + } + } + if (st->depth==15) { + if(st->bigendian) + for (y=0;yxim->height; y++) + for (x=0;xxim->width; x++) { + r = st->palaka2[j++]; + g = st->palaka2[j++]; + b = st->palaka2[j++]; + j++; + st->xim->data[i++] = (g&192)>>6 | (r&248)>>1; + st->xim->data[i++] = (b&248)>>3 | (g&56)<<2; + } + else + for (y=0;yxim->height; y++) + for (x=0;xxim->width; x++) { + r = st->palaka2[j++]; + g = st->palaka2[j++]; + b = st->palaka2[j++]; + j++; + st->xim->data[i++] = (b&248)>>3 | (g&56)<<2; + st->xim->data[i++] = (g&192)>>6 | (r&248)>>1; + } + } + if (st->depth==8) { + for (y=0;yxim->height; y++) + for (x=0;xxim->width; x++) { + r = st->palaka2[j++]; + g = st->palaka2[j++]; + b = st->palaka2[j++]; + j++; + st->xim->data[i++] = (((7*g)/256)*36)+(((6*r)/256)*6)+((6*b)/256); + } + } + XPutImage(st->dpy,st->window,st->gc,st->xim,0,0,0,0,st->xim->width,st->xim->height); } + + +static void * +fireworkx_init (Display *dpy, Window win) +{ + struct state *st = (struct state *) calloc (1, sizeof(*st)); + unsigned int n; + Visual *vi; + Colormap cmap; + Bool writable; + XWindowAttributes xwa; + XGCValues gcv; + firepix *fpix, *ffpix; + + st->dpy = dpy; + st->window = win; + + st->glow_on = get_boolean_resource(st->dpy, "glow" , "Boolean"); + st->flash_on = get_boolean_resource(st->dpy, "flash" , "Boolean"); + st->shoot = get_boolean_resource(st->dpy, "shoot" , "Boolean"); + st->verbose = get_boolean_resource(st->dpy, "verbose" , "Boolean"); + st->rndlife = get_integer_resource(st->dpy, "maxlife" , "Integer"); + st->delay = get_integer_resource(st->dpy, "delay" , "Integer"); + st->minlife = st->rndlife/4; + st->flash_fade=0.98; + if(st->rndlife < 1000) st->flash_fade=0.96; + if(st->rndlife < 500) st->flash_fade=0.94; + if(st->verbose){ + printf("Fireworkx %s - pyrotechnics simulation program \n", FWXVERSION); + printf("Copyright (c) 1999-2007 Rony B Chandran \n\n"); + printf("url: http://www.ronybc.8k.com \n\n");} + + XGetWindowAttributes(st->dpy,win,&xwa); + st->depth = xwa.depth; + vi = xwa.visual; + cmap = xwa.colormap; + st->bigendian = (ImageByteOrder(st->dpy) == MSBFirst); + + if(st->depth==8){ + if(st->verbose){ + printf("Pseudocolor color: use '-no-flash' for better results.\n");} + st->colors = (XColor *) calloc(sizeof(XColor),st->ncolors+1); + writable = False; + make_smooth_colormap(st->dpy, vi, cmap, st->colors, &st->ncolors, + False, &writable, True); + } + st->gc = XCreateGC(st->dpy, win, 0, &gcv); + + resize(st); /* initialize palakas */ + + ffpix = malloc(sizeof(firepix) * PIXCOUNT * SHELLCOUNT); + st->ffshell = malloc(sizeof(fireshell) * SHELLCOUNT); + st->fshell = st->ffshell; + fpix = ffpix; + for (n=0;nfshell->fpix = fpix; + recycle (st, st->fshell,rnd(st->width),rnd(st->height)); + st->fshell++; + fpix += PIXCOUNT; } + + return st; +} + + +static unsigned long +fireworkx_draw (Display *dpy, Window win, void *closure) +{ + struct state *st = (struct state *) closure; + int q,n; + for(q=FTWEAK;q;q--){ + st->fshell=st->ffshell; + for(n=SHELLCOUNT;n;n--){ + if (!explode(st, st->fshell)){ + recycle(st, st->fshell,rnd(st->width),rnd(st->height)); } + st->fshell++; }} +#if HAVE_X86_MMX + if(st->glow_on) mmx_glow(st->palaka1,st->width,st->height,8,st->palaka2); +#else + if(st->glow_on) glow(st); +#endif + if(st->flash_on) light_2x2(st, st->ffshell); + put_image(st); +#if HAVE_X86_MMX + if(!st->glow_on) mmx_blur(st->palaka1,st->width,st->height,8); +#else + if(!st->glow_on) blur(st); +#endif + + return st->delay; +} + + +static void +fireworkx_reshape (Display *dpy, Window window, void *closure, + unsigned int w, unsigned int h) +{ + struct state *st = (struct state *) closure; + resize(st); +} + +static Bool +fireworkx_event (Display *dpy, Window window, void *closure, XEvent *event) +{ + struct state *st = (struct state *) closure; + if (event->type == ButtonPress) { + recycle(st, st->ffshell, event->xbutton.x, event->xbutton.y); + return True; + } + return False; +} + +static void +fireworkx_free (Display *dpy, Window window, void *closure) +{ +} + + +static const char *fireworkx_defaults [] = { + ".background: black", + ".foreground: white", + "*delay: 20000", /* never default to zero! */ + "*maxlife: 2000", + "*flash: True", + "*glow: True", + "*shoot: False", + "*verbose: False", + 0 +}; + +static XrmOptionDescRec fireworkx_options [] = { + { "-delay", ".delay", XrmoptionSepArg, 0 }, + { "-maxlife", ".maxlife", XrmoptionSepArg, 0 }, + { "-no-flash", ".flash", XrmoptionNoArg, "False" }, + { "-no-glow", ".glow", XrmoptionNoArg, "False" }, + { "-shoot", ".shoot", XrmoptionNoArg, "True" }, + { "-verbose", ".verbose", XrmoptionNoArg, "True" }, + { 0, 0, 0, 0 } +}; + +XSCREENSAVER_MODULE ("Fireworkx", fireworkx) diff --git a/hacks/fireworkx.man b/hacks/fireworkx.man new file mode 100644 index 00000000..ece881a8 --- /dev/null +++ b/hacks/fireworkx.man @@ -0,0 +1,90 @@ +.TH XScreenSaver 1 "" "X Version 11" +.SH NAME +fireworkx - pyrotechnics simulation eye-candy. +.SH SYNOPSIS +.B fireworkx +[\-display \fIhost:display.screen\fP] +[\-visual \fIvisual\fP] +[\-window] +[\-root] +[\-verbose] +[\-noflash] +[\-noglow] +[\-shoot] +[\-delay \fInumber\fP] +[\-maxlife \fInumber\fP] +[\-fps] +.SH DESCRIPTION +Simulates fireworks (pyrotechnics); explodes better on faster machines. +.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 \-noflash +Turn off light effect (runs faster) +.TP 8 +.B \-noglow +Turn off self glow (dull blasts..!) +.TP 8 +.B \-shoot +Shoot the shells. +.TP 8 +.B \-delay \fInumber\fP +Delay between frames. In microseconds. (Default: 1000) +.TP 8 +.B \-maxlife \fInumber\fP +Maximum decay period for an explosion. (Default: 2000) +.TP 8 +.B \-verbose +for scientific purposes..! +.TP 8 +.B \-fps +Display the current frame rate and CPU load. +.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 1999-2005 by Rony B Chandran. 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 + +.br +Written by Rony B Chandran +.br + +.br +Additional programming: +.br +------------------------ +.br +Renuka S +.br +Jean-Pierre Demailly +.br +Nicholas Miell + +.SH URL +http://www.ronybc.8k.com + diff --git a/hacks/fireworkx_mmx.S b/hacks/fireworkx_mmx.S new file mode 100644 index 00000000..039b60ad --- /dev/null +++ b/hacks/fireworkx_mmx.S @@ -0,0 +1,226 @@ +/* + * Fast MMX blur code for Fireworkx + * Copyright (c) 1999-2005 Rony B Chandran + * + * From Kerala, INDIA + * + * url: http://www.ronybc.8k.com + * + * 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. + * + */ + +.data + +.text + +.align 8 + +.global mmx_blur +.global mmx_glow + +mmx_blur: /* void mmx_blur( int *palaka, + int width, + int height) + int fade_lvl) */ + pushl %ebp + pushl %edi + pushl %esi + pushl %ebx + + movl 32(%esp),%eax + imull $0x00010001,%eax + movd %eax,%mm0 + movq %mm0,%mm1 + psllq $32,%mm0 + por %mm0,%mm1 + movq %mm1,40(%esp) + + movl 20(%esp), %eax + movl 24(%esp), %edx + shll $2, %edx + addl %eax, %edx + pxor %mm0,%mm0 +.fline: + movq %mm0,(%eax) + addl $8,%eax + cmp %edx,%eax + jbe .fline + + movl 24(%esp),%eax + shll $2,%eax + movl %eax,%edi + movl 28(%esp),%edi + subl $2,%edi + imull %eax,%edi + + movl 20(%esp),%ecx + movl %ecx,%ebx + addl %eax,%ebx + addl %ebx,%eax + xorl %esi,%esi +.align 32 +.renuKa: + pxor %mm7,%mm7 + movq %mm0,%mm6 + movq %mm1,%mm0 + paddw %mm1,%mm6 + movd 8(%esi,%ecx),%mm1 + punpcklbw %mm7,%mm1 + paddw %mm1,%mm6 + + paddw %mm2,%mm6 + movq %mm3,%mm2 + movd 8(%esi,%ebx),%mm3 + punpcklbw %mm7,%mm3 + paddw %mm3,%mm6 + + paddw %mm4,%mm6 + movq %mm5,%mm4 + paddw %mm5,%mm6 + movd 8(%esi,%eax),%mm5 + punpcklbw %mm7,%mm5 + paddw %mm5,%mm6 + + psllw $3,%mm2 + paddw %mm2,%mm6 + psrlw $3,%mm2 + movq 40(%esp),%mm7 + psubusw %mm7,%mm6 + psrlw $4,%mm6 + + packuswb %mm6,%mm6 + movd %mm6, 4(%esi,%ebx) + addl $4,%esi + cmp %edi,%esi + jbe .renuKa + + addl %esi,%eax + addl %esi,%ebx + xorl %ecx,%ecx +.lline: + movl %ecx,(%ebx) + addl $4,%ebx + cmpl %eax,%ebx + jbe .lline + + emms + popl %ebx + popl %esi + popl %edi + popl %ebp + ret + +/* Add Glycerine to + Potassium permanganite... (DANGER-FIRE) */ + +mmx_glow: /* void mmx_glow( int *palaka1, + int width, + int height, + int fade_lvl, + int *palaka2) */ + pushl %ebp + pushl %edi + pushl %esi + pushl %ebx + + movl 32(%esp),%eax + imull $0x00010001,%eax + movd %eax,%mm0 + movq %mm0,%mm1 + psllq $32,%mm0 + por %mm0,%mm1 + movq %mm1,40(%esp) + + movl 20(%esp), %eax + movl 36(%esp), %ebx + movl 24(%esp), %edx + shll $2,%edx + add %eax, %edx + pxor %mm7,%mm7 +.flineGlow: + movq %mm7,(%eax) + movq %mm7,(%ebx) + addl $8,%eax + addl $8,%ebx + cmp %edx,%eax + jbe .flineGlow + + movl 24(%esp),%eax + shll $2,%eax + movl %eax,%edi + movl 28(%esp),%edi + subl $2,%edi + imull %eax,%edi + + movl 20(%esp),%ecx + movl 36(%esp),%edx + movl %ecx,%ebx + addl %eax,%edx + addl %eax,%ebx + addl %ebx,%eax + xorl %esi,%esi +.align 32 +.renuGa: + pxor %mm7,%mm7 + movq %mm0,%mm6 + movq %mm1,%mm0 + paddw %mm1,%mm6 + movd 8(%esi,%ecx),%mm1 + punpcklbw %mm7,%mm1 + paddw %mm1,%mm6 + + paddw %mm2,%mm6 + movq %mm3,%mm2 + movd 8(%esi,%ebx),%mm3 + punpcklbw %mm7,%mm3 + paddw %mm3,%mm6 + + paddw %mm4,%mm6 + movq %mm5,%mm4 + paddw %mm5,%mm6 + movd 8(%esi,%eax),%mm5 + punpcklbw %mm7,%mm5 + paddw %mm5,%mm6 + + psllw $3,%mm2 + paddw %mm2,%mm6 + psrlw $3,%mm2 + movq 40(%esp),%mm7 + psubusw %mm7,%mm6 + movq %mm6,%mm7 + psrlw $4,%mm6 + psrlw $3,%mm7 + + packuswb %mm7,%mm7 + movd %mm7, 4(%esi,%edx) + packuswb %mm6,%mm6 + movd %mm6, 4(%esi,%ebx) + addl $4,%esi + cmp %edi,%esi + jbe .renuGa + + addl %esi,%eax + addl %esi,%ebx + addl %esi,%edx + xorl %ecx,%ecx +.llineGlow: + movl %ecx,(%ebx) + movl %ecx,(%edx) + addl $4,%ebx + addl $4,%edx + cmpl %eax,%ebx + jbe .llineGlow + + emms + popl %ebx + popl %esi + popl %edi + popl %ebp + ret diff --git a/hacks/flag.c b/hacks/flag.c new file mode 100644 index 00000000..351ca000 --- /dev/null +++ b/hacks/flag.c @@ -0,0 +1,568 @@ +/* -*- Mode: C; tab-width: 4 -*- + * flag --- a waving flag + */ +#if 0 +static const char sccsid[] = "@(#)flag.c 4.02 97/04/01 xlockmore"; +#endif + +/* Copyright (c) 1996 Charles Vidal . + * PEtite demo X11 de charles vidal 15 05 96 + * tourne sous Linux et SOLARIS + * thank's to Bas van Gaalen, Holland, PD, for his sources + * in pascal vous devez rajouter une ligne dans mode.c + * + * Permission to use, copy, modify, and distribute this software and its + * documentation for any purpose and without fee is hereby granted, + * provided that the above copyright notice appear in all copies and that + * both that copyright notice and this permission notice appear in + * supporting documentation. + * + * This file is provided AS IS with no warranties of any kind. The author + * shall have no liability with respect to the infringement of copyrights, + * trade secrets or any patents by this file or any part thereof. In no + * event will the author be liable for any lost revenue or profits or + * other special, indirect and consequential damages. + * + * Revision History: + * 22-Jan-98: jwz: made the flag wigglier; added xpm support. + * (I tried to do this by re-porting from xlockmore, but the + * current xlockmore version is completely inscrutable.) + * 13-May-97: jwz@jwz.org: turned into a standalone program. + * Made it able to animate arbitrary (runtime) text or bitmaps. + * 01-May-96: written. + */ + +#ifdef HAVE_COCOA +# define DEF_FONT "Monaco 15" +#else +# define DEF_FONT "fixed" +#endif + +#ifdef STANDALONE +# define DEFAULTS "*delay: 50000 \n" \ + "*cycles: 1000 \n" \ + "*size: -7 \n" \ + "*ncolors: 200 \n" \ + "*bitmap: \n" \ + "*font: " DEF_FONT "\n" \ + "*text: \n" \ + "*fpsSolid: true \n" \ + +# define BRIGHT_COLORS +# define UNIFORM_COLORS +# define reshape_flag 0 +# define flag_handle_event 0 +# include "xlockmore.h" /* from the xscreensaver distribution */ + +#include "xpm-pixmap.h" +#include "images/bob.xbm" + +#else /* !STANDALONE */ +# include "xlock.h" /* from the xlockmore distribution */ +# include "flag.h" +#endif /* !STANDALONE */ + + +#ifdef HAVE_UNAME +# include +#endif /* HAVE_UNAME */ + +#ifdef STANDALONE +static XrmOptionDescRec opts[] = +{ + { "-bitmap", ".flag.bitmap", XrmoptionSepArg, 0 }, + { "-text", ".flag.text", XrmoptionSepArg, 0 } +}; + +#endif /* STANDALONE */ + +ENTRYPOINT ModeSpecOpt flag_opts = { +#ifdef STANDALONE + 2, opts, 0, NULL, NULL +#else /* !STANDALONE */ + 0, NULL, 0, NULL, NULL +#endif /* STANDALONE */ +}; + +#define MINSIZE 1 +#define MAXSCALE 8 +#define MINSCALE 2 +#define MAXINITSIZE 6 +#define MININITSIZE 2 +#define MINAMP 5 +#define MAXAMP 20 +#define MAXW(fp) (MAXSCALE * (fp)->image->width + 2 * MAXAMP + (fp)->pointsize) +#define MAXH(fp) (MAXSCALE * (fp)->image->height+ 2 * MAXAMP + (fp)->pointsize) +#define MINW(fp) (MINSCALE * (fp)->image->width + 2 * MINAMP + (fp)->pointsize) +#define MINH(fp) (MINSCALE * (fp)->image->height+ 2 * MINAMP + (fp)->pointsize) +#define ANGLES 360 + +typedef struct { + int samp; + int sofs; + int sidx; + int x_flag, y_flag; + int timer; + int initialized; + int stab[ANGLES]; + Bool dbufp; + Pixmap cache; + int width, height; + int pointsize; + float size; + float inctaille; + int startcolor; + XImage *image; +} flagstruct; + +static flagstruct *flags = NULL; + +static int +random_num(int n) +{ + return ((int) (((float) LRAND() / MAXRAND) * (n + 1.0))); +} + +static void +initSintab(ModeInfo * mi) +{ + flagstruct *fp = &flags[MI_SCREEN(mi)]; + int i; + + /*- + * change the periodicity of the sin formula : the maximum of the + * periocity seem to be 16 ( 2^4 ), after the drawing isn't good looking + */ + int periodicity = random_num(4); + int puissance = 1; + + /* for (i=0;istab[i] = (int) (SINF(i * puissance * M_PI / ANGLES) * fp->samp) + + fp->sofs; +} + +static void +affiche(ModeInfo * mi) +{ + Display *display = MI_DISPLAY(mi); + int x, y, xp, yp; + flagstruct *fp = &flags[MI_SCREEN(mi)]; + + for (x = 0; x < fp->image->width; x++) + for (y = fp->image->height-1; y >= 0; y--) { + xp = (int) (fp->size * (float) x) + + fp->stab[(fp->sidx + x + y) % ANGLES]; + yp = (int) (fp->size * (float) y) + + fp->stab[(fp->sidx + 4 * x + y + y) % ANGLES]; + + if (fp->image->depth > 1) + XSetForeground(display, MI_GC(mi), + XGetPixel(fp->image, x, y)); + else if (XGetPixel(fp->image, x, y)) + XSetForeground(display, MI_GC(mi), MI_WIN_BLACK_PIXEL(mi)); + else if (MI_NPIXELS(mi) <= 2) + XSetForeground(display, MI_GC(mi), MI_WIN_WHITE_PIXEL(mi)); + else + XSetForeground(display, MI_GC(mi), + MI_PIXEL(mi, (y + x + fp->sidx + fp->startcolor) % MI_NPIXELS(mi))); + + if (fp->cache == MI_WINDOW(mi)) { /* not double-buffering */ + xp += fp->x_flag; + yp += fp->y_flag; + } + + if (fp->pointsize <= 1) + XDrawPoint(display, fp->cache, MI_GC(mi), xp, yp); + else if (fp->pointsize < 6) + XFillRectangle(display, fp->cache, MI_GC(mi), xp, yp, + fp->pointsize, fp->pointsize); + else + XFillArc(display, fp->cache, MI_GC(mi), xp, yp, + fp->pointsize, fp->pointsize, 0, 360*64); + } +} + +#ifdef STANDALONE + +static void +make_flag_bits(ModeInfo *mi) +{ + Display *dpy = MI_DISPLAY(mi); + flagstruct *fp = &flags[MI_SCREEN(mi)]; + char *bitmap_name = get_string_resource (dpy, "bitmap", "Bitmap"); + char *text = get_string_resource (dpy, "text", "Text"); + +#ifdef HAVE_COCOA + bitmap_name = 0; /* #### always use default */ +#endif + + /* If neither a bitmap nor text are specified, randomly select either + the builtin bitmap or builtin text. */ + if ((!bitmap_name || !*bitmap_name) && (!text || !*text)) + { + if (random() & 1) + { + free(bitmap_name); + bitmap_name = strdup("(default)"); + } + else + { + free(text); + text = strdup("(default)"); + } + } + + if (bitmap_name && + *bitmap_name && + !!strcmp(bitmap_name, "(default)")) + { + Pixmap bitmap = 0; + int width = 0; + int height = 0; + + bitmap = xpm_file_to_pixmap (dpy, MI_WINDOW (mi), bitmap_name, + &width, &height, 0); + if (bitmap) + { + fp->image = XGetImage(dpy, bitmap, 0, 0, width, height, ~0L, + ZPixmap); + XFreePixmap(dpy, bitmap); + } + } + else if (text && *text) + { + char *text2; + char *fn = get_string_resource (dpy, "font", "Font"); + char *def_fn = "fixed"; + char *line, *token; + int width, height; + int lines; + int margin = 2; + int fg = 1; + int bg = 0; + Pixmap bitmap; + XFontStruct *font; + XCharStruct overall; + XGCValues gcv; + GC gc; + + if (!strcmp(text, "(default)")) + { +# ifdef HAVE_UNAME + struct utsname uts; + if (uname (&uts) < 0) + { + text = strdup("uname() failed"); + } + else + { + char *s; + if ((s = strchr(uts.nodename, '.'))) + *s = 0; + text = (char *) malloc(strlen(uts.nodename) + + strlen(uts.sysname) + + strlen(uts.version) + + strlen(uts.release) + 10); +# if defined(_AIX) + sprintf(text, "%s\n%s %s.%s", + uts.nodename, uts.sysname, uts.version, uts.release); +# elif defined(__APPLE__) && !defined(USE_IPHONE) /* MacOS X + XDarwin */ + { + const char *file = + "/System/Library/CoreServices/SystemVersion.plist"; + FILE *f = fopen (file, "r"); + char *pbv = 0, *pn = 0, *puvv = 0; + if (f) { + char *s, buf[255]; + + while (fgets (buf, sizeof(buf)-1, f)) { +# define GRAB(S,V) \ + if (strstr(buf, S)) { \ + fgets (buf, sizeof(buf)-1, f); \ + if ((s = strchr (buf, '>'))) V = strdup(s+1); \ + if ((s = strchr (V, '<'))) *s = 0; \ + } + GRAB ("ProductName", pn) + GRAB ("ProductBuildVersion", pbv) + GRAB ("ProductUserVisibleVersion", puvv) +# undef GRAB + } + } + if (pbv) + sprintf (text, "%s\n%s\n%s", + uts.nodename, pn, puvv /*, uts.machine*/); + else + sprintf(text, "%s\n%s %s", + uts.nodename, uts.sysname, uts.release); + } +# else + sprintf(text, "%s\n%s %s", + uts.nodename, uts.sysname, uts.release); +# endif /* special system types */ + } +#else /* !HAVE_UNAME */ +# ifdef VMS + text = strdup(getenv("SYS$NODE")); +# else + text = strdup("X\nScreen\nSaver"); +# endif +#endif /* !HAVE_UNAME */ + } + + while (*text && + (text[strlen(text)-1] == '\r' || + text[strlen(text)-1] == '\n')) + text[strlen(text)-1] = 0; + + text2 = strdup(text); + + if (!fn) fn = def_fn; + font = XLoadQueryFont (dpy, fn); + if (! font) + { + fprintf(stderr, "%s: unable to load font %s; using %s\n", + progname, fn, def_fn); + font = XLoadQueryFont (dpy, def_fn); + } + + memset(&overall, 0, sizeof(overall)); + token = text; + lines = 0; + while ((line = strtok(token, "\r\n"))) + { + XCharStruct o2; + int ascent, descent, direction; + token = 0; + XTextExtents(font, line, strlen(line), + &direction, &ascent, &descent, &o2); + overall.lbearing = MAX(overall.lbearing, o2.lbearing); + overall.rbearing = MAX(overall.rbearing, o2.rbearing); + lines++; + } + + width = overall.lbearing + overall.rbearing + margin + margin + 1; + height = ((font->ascent + font->descent) * lines) + margin + margin; + + bitmap = XCreatePixmap(dpy, MI_WINDOW(mi), width, height, 1); + + gcv.font = font->fid; + gcv.foreground = bg; + gc = XCreateGC (dpy, bitmap, (GCFont | GCForeground), &gcv); + XFillRectangle(dpy, bitmap, gc, 0, 0, width, height); + XSetForeground(dpy, gc, fg); + + token = text2; + lines = 0; + while ((line = strtok(token, "\r\n"))) + { + XCharStruct o2; + int ascent, descent, direction, xoff; + token = 0; + + XTextExtents(font, line, strlen(line), + &direction, &ascent, &descent, &o2); + xoff = ((overall.lbearing + overall.rbearing) - + (o2.lbearing + o2.rbearing)) / 2; + + XDrawString(dpy, bitmap, gc, + overall.lbearing + margin + xoff, + ((font->ascent * (lines + 1)) + + (font->descent * lines) + + margin), + line, strlen(line)); + lines++; + } + free(text2); + XUnloadFont(dpy, font->fid); + XFree((XPointer) font); + XFreeGC(dpy, gc); + + fp->image = XGetImage(dpy, bitmap, 0, 0, width, height, 1L, XYPixmap); + XFreePixmap(dpy, bitmap); + } + + + if (! fp->image) + { + char *bits = (char *) malloc (sizeof(bob_bits)); + memcpy (bits, bob_bits, sizeof(bob_bits)); + fp->image = XCreateImage (dpy, MI_VISUAL(mi), 1, XYBitmap, 0, + bits, bob_width, bob_height, + 8, 0); + fp->image->byte_order = LSBFirst; + fp->image->bitmap_bit_order = LSBFirst; + } + + if (bitmap_name) + free (bitmap_name); + if (text) + free (text); +} + +#else /* !STANDALONE */ + +static void +make_flag_bits(ModeInfo *mi) +{ + flagstruct *fp = &flags[MI_SCREEN(mi)]; + int x, y; + int w = flag_width; + int h = flag_height; + int i = 0; + fp->image = + XCreateImage(MI_DISPLAY(mi), MI_VISUAL(mi), + 1, XYBitmap, 0, /* dpth, fmt, offset */ + (char *) calloc ((w+8) / 8, h), /* data */ + w, h, 8, 0); /* w, h, pad, bpl */ + /* Geez, what kinda goofy bit order is this?? */ + for (x = 0; x < w; x++) + for (y = h-1; y >= 0; y--) + XPutPixel (fp->image, x, y, flag_bits[i++]); +} + +#endif /* !STANDALONE */ + + +ENTRYPOINT void +init_flag(ModeInfo * mi) +{ + Display *display = MI_DISPLAY(mi); + int size = MI_SIZE(mi); + flagstruct *fp; + + if (flags == NULL) { + if ((flags = (flagstruct *) calloc(MI_NUM_SCREENS(mi), + sizeof (flagstruct))) == NULL) + return; + } + fp = &flags[MI_SCREEN(mi)]; + + make_flag_bits(mi); + if (!fp->image) abort(); + + fp->width = MI_WIN_WIDTH(mi); + fp->height = MI_WIN_HEIGHT(mi); + + fp->samp = MAXAMP; /* Amplitude */ + fp->sofs = 20; /* ???????? */ + fp->pointsize = size; + if (size < -MINSIZE) + fp->pointsize = NRAND(-size - MINSIZE + 1) + MINSIZE; + if (fp->pointsize < MINSIZE || + fp->width <= MAXW(fp) || fp->height <= MAXH(fp)) + fp->pointsize = MINSIZE; + fp->size = MAXINITSIZE; /* Initial distance between pts */ + fp->inctaille = 0.05; + fp->timer = 0; + fp->sidx = fp->x_flag = fp->y_flag = 0; + + if (!fp->initialized) { + fp->dbufp = True; +# ifdef HAVE_COCOA /* Don't second-guess Quartz's double-buffering */ + fp->dbufp = False; +#endif + fp->initialized = True; + if (!fp->dbufp) + fp->cache = MI_WINDOW(mi); /* not double-buffering */ + else + if (!(fp->cache = XCreatePixmap(display, MI_WINDOW(mi), + MAXW(fp), MAXH(fp), + MI_WIN_DEPTH(mi)))) +#ifdef STANDALONE + exit(-1); +#else /* !STANDALONE */ + error("%s: catastrophe memoire\n"); +#endif /* !STANDALONE */ + } + XSetForeground(display, MI_GC(mi), MI_WIN_BLACK_PIXEL(mi)); + XFillRectangle(display, fp->cache, MI_GC(mi), + 0, 0, MAXW(fp), MAXH(fp)); + /* don't want any exposure events from XCopyArea */ + XSetGraphicsExposures(display, MI_GC(mi), False); + if (MI_NPIXELS(mi) > 2) + fp->startcolor = NRAND(MI_NPIXELS(mi)); + if (fp->width <= MAXW(fp) || fp->height <= MAXH(fp)) { + fp->samp = MINAMP; + fp->sofs = 0; + fp->x_flag = random_num(fp->width - MINW(fp)); + fp->y_flag = random_num(fp->height - MINH(fp)); + } else { + fp->samp = MAXAMP; + fp->sofs = 20; + fp->x_flag = random_num(fp->width - MAXW(fp)); + fp->y_flag = random_num(fp->height - MAXH(fp)); + } + + initSintab(mi); + + XClearWindow(display, MI_WINDOW(mi)); +} + +ENTRYPOINT void release_flag(ModeInfo * mi); + + +ENTRYPOINT void +draw_flag(ModeInfo * mi) +{ + Display *display = MI_DISPLAY(mi); + Window window = MI_WINDOW(mi); + flagstruct *fp = &flags[MI_SCREEN(mi)]; + + if (!fp->image) abort(); + if (fp->cache == window) { /* not double-buffering */ + XClearWindow (display, window); + } else if (fp->width <= MAXW(fp) || fp->height <= MAXH(fp)) { + fp->size = MININITSIZE; + /* fp->pointsize = MINPOINTSIZE; */ + XCopyArea(display, fp->cache, window, MI_GC(mi), + 0, 0, MINW(fp), MINH(fp), fp->x_flag, fp->y_flag); + } else { + if ((fp->size + fp->inctaille) > MAXSCALE) + fp->inctaille = -fp->inctaille; + if ((fp->size + fp->inctaille) < MINSCALE) + fp->inctaille = -fp->inctaille; + fp->size += fp->inctaille; + XCopyArea(display, fp->cache, window, MI_GC(mi), + 0, 0, MAXW(fp), MAXH(fp), fp->x_flag, fp->y_flag); + } + XSetForeground(MI_DISPLAY(mi), MI_GC(mi), MI_WIN_BLACK_PIXEL(mi)); + XFillRectangle(display, fp->cache, MI_GC(mi), + 0, 0, MAXW(fp), MAXH(fp)); + affiche(mi); + fp->sidx += 2; + fp->sidx %= (ANGLES * MI_NPIXELS(mi)); + fp->timer++; + if ((MI_CYCLES(mi) > 0) && (fp->timer >= MI_CYCLES(mi))) + { + release_flag(mi); + init_flag(mi); + } +} + +ENTRYPOINT void +release_flag(ModeInfo * mi) +{ + if (flags != NULL) { + int screen; + + for (screen = 0; screen < MI_NUM_SCREENS(mi); screen++) + { + if (flags[screen].cache && flags[screen].dbufp) + XFreePixmap(MI_DISPLAY(mi), flags[screen].cache); + if (flags[screen].image) + XDestroyImage(flags[screen].image); + } + (void) free((void *) flags); + flags = NULL; + } +} + +ENTRYPOINT void +refresh_flag(ModeInfo * mi) +{ + /* Do nothing, it will refresh by itself */ +} + +XSCREENSAVER_MODULE ("Flag", flag) diff --git a/hacks/flag.man b/hacks/flag.man new file mode 100644 index 00000000..dcf93f76 --- /dev/null +++ b/hacks/flag.man @@ -0,0 +1,92 @@ +.TH XScreenSaver 1 "24-May-97" "X Version 11" +.SH NAME +flag - draws a waving flag, containing text or an image +.SH SYNOPSIS +.B flag +[\-display \fIhost:display.screen\fP] [\-foreground \fIcolor\fP] [\-background \fIcolor\fP] [\-window] [\-root] [\-mono] [\-install] [\-visual \fIvisual\fP] [\-ncolors \fIinteger\fP] [\-delay \fImicroseconds\fP] [\-cycles \fIinteger\fP] [\-size \fIinteger\fP] [\-text \fIstring\fP] [\-font \fIfont\fP] [\-bitmap \fIxbm-file\fP] + +[\-fps] +.SH DESCRIPTION +The \fIflag\fP program draws a waving flag that contains text or a bitmap. +.SH OPTIONS +.I flag +accepts the following options: +.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 \-mono +If on a color display, pretend we're on a monochrome display. +.TP 8 +.B \-install +Install a private colormap for the window. +.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 \-ncolors \fIinteger\fP +How many colors should be used (if possible). Default 200. +.TP 8 +.B \-cycles \fIinteger\fP + +.TP 8 +.B \-count \fIinteger\fP + +.TP 8 +.B \-size \fIinteger\fP +How large the pixels in the flag should be, from 1 to 8. +If this is a negative number, the pixel size is chosen randomly +from the range 1 to -size. Default -7. +.TP 8 +.B \-text \fItext\fP +The text to display in the flag. Multiple lines of text are allowed; +the lines will be displayed centered atop one another. Default: none. +If the text is the magic string \fI"(default)"\fP, then the text used +will be the local machine name; a newline; and the local OS version. +.TP 8 +.B \-bitmap \fIxbm-file\fP +The bitmap to display in the flag; this must be an XBM file (color XPMs +are not allowed.) Default: none. If the bitmap is the magic +string \fI"(default)"\fP, then the bitmap used will be a charming +little picture of J. R. "Bob" Dobbs. + +If neither \fI\-text\fP nor \fI\-bitmap\fP are specified, then either +the builtin text or the builtin bitmap will be chosen randomly. +.TP 8 +.B \-font \fIfont\fP +The font in which to draw the text; the default is +"-*-helvetica-bold-r-*-240-*". +.TP 8 +.B \-fps +Display the current frame rate and CPU load. +.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), +.BR xlock (1) +.SH COPYRIGHT +Copyright \(co 1996 Charles Vidal. + +Permission to use, copy, modify, and distribute this software and its +documentation for any purpose and without fee is hereby granted, +provided that the above copyright notice appear in all copies and that +both that copyright notice and this permission notice appear in +supporting documentation. + +.SH AUTHOR +Charles Vidal , 1996. + +Ability to run standalone or with \fIxscreensaver\fP, and the \-text +and \-bitmap options, added by Jamie Zawinski , 24-May-97. diff --git a/hacks/flame.c b/hacks/flame.c new file mode 100644 index 00000000..eed6287c --- /dev/null +++ b/hacks/flame.c @@ -0,0 +1,456 @@ +/* xscreensaver, Copyright (c) 1993-2008 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. + */ + +/* This file was ported from xlock for use in xscreensaver (and standalone) + * by jwz on 18-Oct-93. (And again, 11-May-97.) Original copyright reads: + * + * static char sccsid[] = "@(#)flame.c 1.4 91/09/27 XLOCK"; + * + * flame.c - recursive fractal cosmic flames. + * + * Copyright (c) 1991 by Patrick J. Naughton. + * + * Permission to use, copy, modify, and distribute this software and its + * documentation for any purpose and without fee is hereby granted, + * provided that the above copyright notice appear in all copies and that + * both that copyright notice and this permission notice appear in + * supporting documentation. + * + * This file is provided AS IS with no warranties of any kind. The author + * shall have no liability with respect to the infringement of copyrights, + * trade secrets or any patents by this file or any part thereof. In no + * event will the author be liable for any lost revenue or profits or + * other special, indirect and consequential damages. + * + * Comments and additions should be sent to the author: + * + * naughton@eng.sun.com + * + * Patrick J. Naughton + * MS 21-14 + * Sun Laboritories, Inc. + * 2550 Garcia Ave + * Mountain View, CA 94043 + * + * Revision History: + * 01-Jun-95: This should look more like the original with some updates by + * Scott Draves. + * 27-Jun-91: vary number of functions used. + * 24-Jun-91: fixed portability problem with integer mod (%). + * 06-Jun-91: Written. (received from Scott Draves, spot@cs.cmu.edu). + */ + +#include +#include "screenhack.h" + +#include /* so we can ignore SIGFPE */ + +#define POINT_BUFFER_SIZE 10 +#define MAXLEV 4 +#define MAXKINDS 10 + +struct state { + Display *dpy; + Window window; + + double f[2][3][MAXLEV]; /* three non-homogeneous transforms */ + int max_total; + int max_levels; + int max_points; + int cur_level; + int variation; + int snum; + int anum; + int num_points; + int total_points; + int pixcol; + int ncolors; + XColor *colors; + XPoint points [POINT_BUFFER_SIZE]; + GC gc; + + int delay, delay2; + int width, height; + + short lasthalf; + + int flame_alt; + int do_reset; +}; + + +static short +halfrandom (struct state *st, int mv) +{ + unsigned long r; + + if (st->lasthalf) + { + r = st->lasthalf; + st->lasthalf = 0; + } + else + { + r = random (); + st->lasthalf = r >> 16; + } + return (r % mv); +} + +static void * +flame_init (Display *dpy, Window window) +{ + struct state *st = (struct state *) calloc (1, sizeof(*st)); + XGCValues gcv; + XWindowAttributes xgwa; + Colormap cmap; + + st->dpy = dpy; + st->window = window; + +#if defined(SIGFPE) && defined(SIG_IGN) + /* No doubt a better fix would be to track down where the NaN is coming + from, and code around that; but this should do. Apparently most systems + (Linux, Solaris, Irix, ...) ignore FPE by default -- but FreeBSD dumps + core by default. */ + signal (SIGFPE, SIG_IGN); +#endif + + XGetWindowAttributes (st->dpy, st->window, &xgwa); + st->width = xgwa.width; + st->height = xgwa.height; + cmap = xgwa.colormap; + + st->max_points = get_integer_resource (st->dpy, "iterations", "Integer"); + if (st->max_points <= 0) st->max_points = 100; + + st->max_levels = st->max_points; + + st->max_total = get_integer_resource (st->dpy, "points", "Integer"); + if (st->max_total <= 0) st->max_total = 10000; + + st->delay = get_integer_resource (st->dpy, "delay", "Integer"); + if (st->delay < 0) st->delay = 0; + st->delay2 = get_integer_resource (st->dpy, "delay2", "Integer"); + if (st->delay2 < 0) st->delay2 = 0; + + st->variation = random() % MAXKINDS; + + if (mono_p) + st->ncolors = 0; + else + { + st->ncolors = get_integer_resource (st->dpy, "colors", "Integer"); + if (st->ncolors <= 0) st->ncolors = 128; + st->colors = (XColor *) malloc ((st->ncolors+1) * sizeof (*st->colors)); + make_smooth_colormap (st->dpy, xgwa.visual, xgwa.colormap, st->colors, &st->ncolors, + True, 0, True); + if (st->ncolors <= 2) + mono_p = True, st->ncolors = 0; + } + + gcv.foreground = get_pixel_resource (st->dpy, cmap, "foreground", "Foreground"); + gcv.background = get_pixel_resource (st->dpy, cmap, "background", "Background"); + + if (! mono_p) + { + st->pixcol = halfrandom (st, st->ncolors); + gcv.foreground = (st->colors [st->pixcol].pixel); + } + + st->gc = XCreateGC (st->dpy, st->window, GCForeground | GCBackground, &gcv); + return st; +} + +static int +recurse (struct state *st, double x, double y, int l, Display *dpy, Window win) +{ + int i; + double nx, ny; + + if (l == st->max_levels) + { + st->total_points++; + if (st->total_points > st->max_total) /* how long each fractal runs */ + return 0; + + if (x > -1.0 && x < 1.0 && y > -1.0 && y < 1.0) + { + st->points[st->num_points].x = (int) ((st->width / 2) * (x + 1.0)); + st->points[st->num_points].y = (int) ((st->height / 2) * (y + 1.0)); + st->num_points++; + if (st->num_points >= POINT_BUFFER_SIZE) + { + XDrawPoints (st->dpy, win, st->gc, st->points, st->num_points, CoordModeOrigin); + st->num_points = 0; + } + } + } + else + { + for (i = 0; i < st->snum; i++) + { + + /* Scale back when values get very large. Spot sez: + "I think this happens on HPUX. I think it's non-IEEE + to generate an exception instead of a silent NaN." + */ + if ((abs(x) > 1.0E5) || (abs(y) > 1.0E5)) + x = x / y; + + nx = st->f[0][0][i] * x + st->f[0][1][i] * y + st->f[0][2][i]; + ny = st->f[1][0][i] * x + st->f[1][1][i] * y + st->f[1][2][i]; + if (i < st->anum) + { + switch (st->variation) + { + case 0: /* sinusoidal */ + nx = sin(nx); + ny = sin(ny); + break; + case 1: /* complex */ + { + double r2 = nx * nx + ny * ny + 1e-6; + nx = nx / r2; + ny = ny / r2; + } + break; + case 2: /* bent */ + if (nx < 0.0) + nx = nx * 2.0; + if (ny < 0.0) + ny = ny / 2.0; + break; + case 3: /* swirl */ + { + double r = (nx * nx + ny * ny); /* times k here is fun */ + double c1 = sin(r); + double c2 = cos(r); + double t = nx; + + if (nx > 1e4 || nx < -1e4 || ny > 1e4 || ny < -1e4) + ny = 1e4; + else + ny = c2 * t + c1 * ny; + nx = c1 * nx - c2 * ny; + } + break; + case 4: /* horseshoe */ + { + double r, c1, c2, t; + + /* Avoid atan2: DOMAIN error message */ + if (nx == 0.0 && ny == 0.0) + r = 0.0; + else + r = atan2(nx, ny); /* times k here is fun */ + c1 = sin(r); + c2 = cos(r); + t = nx; + + nx = c1 * nx - c2 * ny; + ny = c2 * t + c1 * ny; + } + break; + case 5: /* drape */ + { + double t; + + /* Avoid atan2: DOMAIN error message */ + if (nx == 0.0 && ny == 0.0) + t = 0.0; + else + t = atan2(nx, ny) / M_PI; + + if (nx > 1e4 || nx < -1e4 || ny > 1e4 || ny < -1e4) + ny = 1e4; + else + ny = sqrt(nx * nx + ny * ny) - 1.0; + nx = t; + } + break; + case 6: /* broken */ + if (nx > 1.0) + nx = nx - 1.0; + if (nx < -1.0) + nx = nx + 1.0; + if (ny > 1.0) + ny = ny - 1.0; + if (ny < -1.0) + ny = ny + 1.0; + break; + case 7: /* spherical */ + { + double r = 0.5 + sqrt(nx * nx + ny * ny + 1e-6); + + nx = nx / r; + ny = ny / r; + } + break; + case 8: /* */ + nx = atan(nx) / M_PI_2; + ny = atan(ny) / M_PI_2; + break; +/* #if 0 */ /* core dumps on some machines, why not all? */ + case 9: /* complex sine */ + { + double u = nx; + double v = ny; + double ev = exp(v); + double emv = exp(-v); + + nx = (ev + emv) * sin(u) / 2.0; + ny = (ev - emv) * cos(u) / 2.0; + } + break; + case 10: /* polynomial */ + if (nx < 0) + nx = -nx * nx; + else + nx = nx * nx; + if (ny < 0) + ny = -ny * ny; + else + ny = ny * ny; + break; +/* #endif */ + default: + nx = sin(nx); + ny = sin(ny); + } + } + if (!recurse (st, nx, ny, l + 1, st->dpy, win)) + return 0; + } + } + return 1; +} + +static unsigned long +flame_draw (Display *dpy, Window window, void *closure) +{ + struct state *st = (struct state *) closure; + int i, j, k; + unsigned long this_delay = st->delay; + + if (st->do_reset) + { + st->do_reset = 0; + XClearWindow (st->dpy, st->window); + } + + if (!(st->cur_level++ % st->max_levels)) + { + st->do_reset = 1; + this_delay = st->delay2; + st->flame_alt = !st->flame_alt; + st->variation = random() % MAXKINDS; + } + else + { + if (st->ncolors > 2) + { + XSetForeground (st->dpy, st->gc, st->colors [st->pixcol].pixel); + if (--st->pixcol < 0) + st->pixcol = st->ncolors - 1; + } + } + + /* number of functions */ + st->snum = 2 + (st->cur_level % (MAXLEV - 1)); + + /* how many of them are of alternate form */ + if (st->flame_alt) + st->anum = 0; + else + st->anum = halfrandom (st, st->snum) + 2; + + /* 6 coefs per function */ + for (k = 0; k < st->snum; k++) + { + for (i = 0; i < 2; i++) + for (j = 0; j < 3; j++) + st->f[i][j][k] = ((double) (random() & 1023) / 512.0 - 1.0); + } + st->num_points = 0; + st->total_points = 0; + recurse (st, 0.0, 0.0, 0, st->dpy, st->window); + XDrawPoints (st->dpy, st->window, st->gc, st->points, st->num_points, CoordModeOrigin); + + return this_delay; +} + + +#if defined(__hpux) && defined(PLOSS) +/* I don't understand why this is necessary, but I'm told that this program + does nothing at all on HP-sUX without it. + + I'm further told that HPUX 11.0 doesn't define PLOSS, and works ok without + this section. Go figure. + */ +#undef random +#undef srandom +#include +int matherr(x) + register struct exception *x; +{ + if (x->type == PLOSS) return 1; + else return 0; +} +#endif /* __hpux */ + + + +static const char *flame_defaults [] = { + ".background: black", + ".foreground: white", + "*fpsSolid: true", + "*colors: 64", + "*iterations: 25", + "*delay: 50000", + "*delay2: 2000000", + "*points: 10000", + 0 +}; + +static XrmOptionDescRec flame_options [] = { + { "-colors", ".colors", XrmoptionSepArg, 0 }, + { "-iterations", ".iterations", XrmoptionSepArg, 0 }, + { "-delay", ".delay", XrmoptionSepArg, 0 }, + { "-delay2", ".delay2", XrmoptionSepArg, 0 }, + { "-points", ".points", XrmoptionSepArg, 0 }, + { 0, 0, 0, 0 } +}; + +static void +flame_reshape (Display *dpy, Window window, void *closure, + unsigned int w, unsigned int h) +{ + struct state *st = (struct state *) closure; + st->width = w; + st->height = h; +} + +static Bool +flame_event (Display *dpy, Window window, void *closure, XEvent *event) +{ + return False; +} + +static void +flame_free (Display *dpy, Window window, void *closure) +{ + struct state *st = (struct state *) closure; + free (st); +} + +XSCREENSAVER_MODULE ("Flame", flame) + diff --git a/hacks/flame.man b/hacks/flame.man new file mode 100644 index 00000000..dae4d1b0 --- /dev/null +++ b/hacks/flame.man @@ -0,0 +1,74 @@ +.TH XScreenSaver 1 "13-aug-92" "X Version 11" +.SH NAME +flame - draw weird cosmic fractals +.SH SYNOPSIS +.B flame +[\-display \fIhost:display.screen\fP] [\-foreground \fIcolor\fP] [\-background \fIcolor\fP] [\-window] [\-root] [\-mono] [\-install] [\-visual \fIvisual\fP] [\-colors \fIinteger\fP] [\-iterations \fIinteger\fP] [\-points \fIinteger\fP] [\-delay \fImicroseconds\fP] [\-delay2 \fImicroseconds\fP] +[\-fps] +.SH DESCRIPTION +The \fIflame\fP program generates colorful fractal displays. +.SH OPTIONS +.I flame +accepts the following options: +.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 \-mono +If on a color display, pretend we're on a monochrome display. +.TP 8 +.B \-install +Install a private colormap for the window. +.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 \-colors \fIinteger\fP +How many colors should be used (if possible). Default 64. +.TP 8 +.B \-iterations \fIinteger\fP +How many fractals to generate. Default 25. +.TP 8 +.B \-points \fIinteger\fP +How many pixels to draw for each fractal. Default 10000. +.TP 8 +.B \-delay \fImicroseconds\fP +How long we should wait between drawing each fractal. Default 50000, +or about 1/20th second. +.TP 8 +.B \-delay2 \fImicroseconds\fP +How long we should wait before clearing the screen when each run ends. +Default 2000000, or two seconds. +.TP 8 +.B \-fps +Display the current frame rate and CPU load. +.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), +.BR xlock (1) +.SH COPYRIGHT +Copyright \(co 1991 by Patrick J. Naughton + +Permission to use, copy, modify, and distribute this software and its +documentation for any purpose and without fee is hereby granted, +provided that the above copyright notice appear in all copies and that +both that copyright notice and this permission notice appear in +supporting documentation. +.SH AUTHOR +Scott Graves , 06-Jun-91.n + +Ability to run standalone or with \fIxscreensaver\fP added by +Jamie Zawinski , 18-Oct-93. diff --git a/hacks/flow.c b/hacks/flow.c new file mode 100644 index 00000000..794776f1 --- /dev/null +++ b/hacks/flow.c @@ -0,0 +1,1231 @@ +/* -*- Mode: C; tab-width: 4; c-basic-offset: 4 -*- */ +/* flow --- flow of strange bees */ + +#if 0 +#if !defined( lint ) && !defined( SABER ) +static const char sccsid[] = "@(#)flow.c 5.00 2000/11/01 xlockmore"; +#endif +#endif + +/*- + * Copyright (c) 1996 by Tim Auckland + * Incorporating some code from Stephen Davies Copyright (c) 2000 + * + * Search code based on techniques described in "Strange Attractors: + * Creating Patterns in Chaos" by Julien C. Sprott + * + * Permission to use, copy, modify, and distribute this software and its + * documentation for any purpose and without fee is hereby granted, + * provided that the above copyright notice appear in all copies and that + * both that copyright notice and this permission notice appear in + * supporting documentation. + * + * This file is provided AS IS with no warranties of any kind. The author + * shall have no liability with respect to the infringement of copyrights, + * trade secrets or any patents by this file or any part thereof. In no + * event will the author be liable for any lost revenue or profits or + * other special, indirect and consequential damages. + * + * "flow" shows a variety of continuous phase-space flows around strange + * attractors. It includes the well-known Lorentz mask (the "Butterfly" + * of chaos fame), two forms of Rossler's "Folded Band" and Poincare' + * sections of the "Birkhoff Bagel" and Duffing's forced occilator. "flow" + * can now discover new attractors. + * + * Revision History: + * + * 29-Oct-2004: [TDA] Discover Attractors unknown to science. + * Replace 2D rendering of Periodic Attractors with a 3D + * 'interrupted' rendering. Replace "-/+allow2d" with "-/+periodic" + * Replace all ODE formulae with completely generic forms. + * Add '-search' option to perform background high-speed discovery + * for completely new attractors without impacting rendering + * performance. + * Use gaussian distribution for initial point positions and for + * parameter search. + * Add "+dbuf" option to allow Double-Buffering to be turned off on + * slow X servers. + * Remove redundant '-zoom' option. Now automatically zooms if both + * rotation and riding are permitted. + * Replace dynamic bounding box with static one pre-calculated + * during discovery phase. + * Simplify and fix bounding box clipping code. Should now be safe + * to run without double buffer on all XFree86 servers if desired. + * 12-Oct-2004: [TDA] Merge Xscreensaver and Xlockmore branches + * Added Chalky's orbital camera, but made the zooming work by + * flying the camera rather than interpolating the view transforms. + * Added Chalky's Bounding Box, but time-averaged the boundaries to + * let the lost bees escape. + * Added Chalky's 'view-frustrum' clipping, but only applying it to + * the Bounding Box. Trails make clipping less useful. + * Added Chalky's "-slow" and "-freeze" options for compatibility, + * but haven't implemented the features, since the results are ugly + * and make no mathematical contribution. + * Added Double-Buffering as a work-around for a persistent XFree86 + * bug that left debris on the screen. + * 21-Mar-2003: [TDA] Trails added (XLockmore branch) + * 01-Nov-2000: [TDA] Allocation checks (XLockmore branch) + * 21-Feb-2000: [Chalky] Major hackage (Stephen Davies, chalky@null.net) + * (Xscreensaver branch) + * Forced perspective mode, added 3d box around attractor which + * involved coding 3d-planar-clipping against the view-frustrum + * thingy. Also made view alternate between piggybacking on a 'bee' + * to zooming around outside the attractor. Most bees slow down and + * stop, to make the structure of the attractor more obvious. +* 28-Jan-1999: [TDA] Catch 'lost' bees in flow.c and disable them. + * (XLockmore branch) + * I chose to disable them rather than reinitialise them because + * reinitialising can produce fake attractors. + * This has allowed me to relax some of the parameters and initial + * conditions slightly to catch some of the more extreme cases. As a + * result you may see some bees fly away at the start - these are the ones + * that 'missed' the attractor. If the bee with the camera should fly + * away the mode will restart :-) + * 31-Nov-1998: [TDA] Added Duffing (what a strange day that was :) DAB) + * Duffing's forced oscillator has been added to the formula list and + * the parameters section has been updated to display it in Poincare' + * section. + * 30-Nov-1998: [TDA] Added travelling perspective option + * A more exciting point-of-view has been added to all autonomous flows. + * This views the flow as seen by a particle moving with the flow. In the + * metaphor of the original code, I've attached a camera to one of the + * trained bees! + * 30-Nov-1998: [TDA] Much code cleanup. + * 09-Apr-1997: [TDA] Ported to xlockmore-4 + * 18-Jul-1996: Adapted from swarm.c Copyright (c) 1991 by Patrick J. Naughton. + * 31-Aug-1990: Adapted from xswarm by Jeff Butterworth. (butterwo@ncsc.org). + */ + +#ifdef STANDALONE +# define MODE_flow +# define DEFAULTS "*delay: 10000 \n" \ + "*count: 3000 \n" \ + "*size: -10 \n" \ + "*cycles: 10000 \n" \ + "*ncolors: 200 \n" + +# define flow_handle_event 0 +# include "xlockmore.h" /* in xscreensaver distribution */ +#else /* STANDALONE */ +# include "xlock.h" /* in xlockmore distribution */ +#endif /* STANDALONE */ + +#ifdef MODE_flow + +#define DEF_ROTATE "TRUE" +#define DEF_RIDE "TRUE" +#define DEF_BOX "TRUE" +#define DEF_PERIODIC "TRUE" +#define DEF_SEARCH "TRUE" +#define DEF_DBUF "TRUE" + +static Bool rotatep; +static Bool ridep; +static Bool boxp; +static Bool periodicp; +static Bool searchp; +static Bool dbufp; + +static XrmOptionDescRec opts[] = { + {"-rotate", ".flow.rotate", XrmoptionNoArg, "on"}, + {"+rotate", ".flow.rotate", XrmoptionNoArg, "off"}, + {"-ride", ".flow.ride", XrmoptionNoArg, "on"}, + {"+ride", ".flow.ride", XrmoptionNoArg, "off"}, + {"-box", ".flow.box", XrmoptionNoArg, "on"}, + {"+box", ".flow.box", XrmoptionNoArg, "off"}, + {"-periodic", ".flow.periodic", XrmoptionNoArg, "on"}, + {"+periodic", ".flow.periodic", XrmoptionNoArg, "off"}, + {"-search", ".flow.search", XrmoptionNoArg, "on"}, + {"+search", ".flow.search", XrmoptionNoArg, "off"}, + {"-dbuf", ".flow.dbuf", XrmoptionNoArg, "on"}, + {"+dbuf", ".flow.dbuf", XrmoptionNoArg, "off"}, +}; + +static argtype vars[] = { + {&rotatep, "rotate", "Rotate", DEF_ROTATE, t_Bool}, + {&ridep, "ride", "Ride", DEF_RIDE, t_Bool}, + {&boxp, "box", "Box", DEF_BOX, t_Bool}, + {&periodicp, "periodic", "Periodic", DEF_PERIODIC, t_Bool}, + {&searchp, "search", "Search", DEF_SEARCH, t_Bool}, + {&dbufp, "dbuf", "Dbuf", DEF_DBUF, t_Bool}, +}; + +static OptionStruct desc[] = { + {"-/+rotate", "turn on/off rotating around attractor."}, + {"-/+ride", "turn on/off ride in the flow."}, + {"-/+box", "turn on/off bounding box."}, + {"-/+periodic", "turn on/off periodic attractors."}, + {"-/+search", "turn on/off search for new attractors."}, + {"-/+dbuf", "turn on/off double buffering."}, +}; + +ENTRYPOINT ModeSpecOpt flow_opts = +{sizeof opts / sizeof opts[0], opts, + sizeof vars / sizeof vars[0], vars, desc}; + +#ifdef USE_MODULES +ModStruct flow_description = { + "flow", "init_flow", "draw_flow", "release_flow", + "refresh_flow", "init_flow", NULL, &flow_opts, + 1000, 1024, 10000, -10, 200, 1.0, "", + "Shows dynamic strange attractors", 0, NULL +}; + +#endif + +typedef struct { double x, y, z; } dvector; + +#define N_PARS 20 /* Enough for Full Cubic or Periodic Cubic */ +typedef dvector Par[N_PARS]; +enum { /* Name the parameter indices to make it easier to write + standard examples */ + C, + X,XX,XXX,XXY,XXZ,XY,XYY,XYZ,XZ,XZZ, + Y,YY,YYY,YYZ,YZ,YZZ, + Z,ZZ,ZZZ, + SINY = XY /* OK to overlap in this case */ +}; + +/* Camera target [TDA] */ +typedef enum { + ORBIT = 0, + BEE = 1 +} Chaseto; + +/* Macros */ +#define IX(C) ((C) * segindex + sp->cnsegs[(C)]) +#define B(t,b) (sp->p + (t) + (b) * sp->taillen) +#define X(t,b) (B((t),(b))->x) +#define Y(t,b) (B((t),(b))->y) +#define Z(t,b) (B((t),(b))->z) +#define balance_rand(v) ((LRAND()/MAXRAND*(v))-((v)/2)) /* random around 0 */ +#define LOST_IN_SPACE 2000.0 +#define INITIALSTEP 0.04 +#define EYEHEIGHT 0.005 +#define MINTRAIL 2 +#define BOX_L 36 + +/* Points that make up the box (normalized coordinates) */ +static const double box[][3] = { + {1,1,1}, /* 0 */ + {1,1,-1}, /* 1 */ + {1,-1,-1}, /* 2 */ + {1,-1,1}, /* 3 */ + {-1,1,1}, /* 4 */ + {-1,1,-1}, /* 5 */ + {-1,-1,-1},/* 6 */ + {-1,-1,1}, /* 7 */ + {1, .8, .8}, + {1, .8,-.8}, + {1,-.8,-.8}, + {1,-.8, .8}, + { .8,1, .8}, + { .8,1,-.8}, + {-.8,1,-.8}, + {-.8,1, .8}, + { .8, .8,1}, + { .8,-.8,1}, + {-.8,-.8,1}, + {-.8, .8,1}, + {-1, .8, .8}, + {-1, .8,-.8}, + {-1,-.8,-.8}, + {-1,-.8, .8}, + { .8,-1, .8}, + { .8,-1,-.8}, + {-.8,-1,-.8}, + {-.8,-1, .8}, + { .8, .8,-1}, + { .8,-.8,-1}, + {-.8,-.8,-1}, + {-.8, .8,-1} +}; + +/* Lines connecting the box dots */ +static const double lines[][2] = { + {0,1}, {1,2}, {2,3}, {3,0}, /* box */ + {4,5}, {5,6}, {6,7}, {7,4}, + {0,4}, {1,5}, {2,6}, {3,7}, + {4+4,5+4}, {5+4,6+4}, {6+4,7+4}, {7+4,4+4}, + {4+8,5+8}, {5+8,6+8}, {6+8,7+8}, {7+8,4+8}, + {4+12,5+12}, {5+12,6+12}, {6+12,7+12}, {7+12,4+12}, + {4+16,5+16}, {5+16,6+16}, {6+16,7+16}, {7+16,4+16}, + {4+20,5+20}, {5+20,6+20}, {6+20,7+20}, {7+20,4+20}, + {4+24,5+24}, {5+24,6+24}, {6+24,7+24}, {7+24,4+24}, +}; + +typedef struct { + /* Variables used in rendering */ + dvector cam[3]; /* camera flight path */ + int chasetime; + Chaseto chaseto; + Pixmap buffer; /* Double Buffer */ + dvector circle[2]; /* POV that circles around the scene */ + dvector centre; /* centre */ + int beecount; /* number of bees */ + XSegment *csegs; /* bee lines */ + int *cnsegs; + XSegment *old_segs; /* old bee lines */ + int nold_segs; + int taillen; + + /* Variables common to iterators */ + dvector (*ODE) (Par par, double x, double y, double z); + dvector range; /* Initial conditions */ + double yperiod; /* ODE's where Y is periodic. */ + + /* Variables used in iterating main flow */ + Par par; + dvector *p; /* bee positions x[time][bee#] */ + int count; + double lyap; + double size; + dvector mid; /* Effective bounding box */ + double step; + + /* second set of variables, used for parallel search */ + Par par2; + dvector p2[2]; + int count2; + double lyap2; + double size2; + dvector mid2; + double step2; + +} flowstruct; + +static flowstruct *flows = (flowstruct *) NULL; + +/* + * Private functions + */ + + +/* ODE functions */ + +/* Generic 3D Cubic Polynomial. Includes all the Quadratics (Lorentz, + Rossler) and much more! */ + +/* I considered offering a seperate 'Quadratic' option, since Cubic is + clearly overkill for the standard examples, but the performance + difference is too small to measure. The compute time is entirely + dominated by the XDrawSegments calls anyway. [TDA] */ +static dvector +Cubic(Par a, double x, double y, double z) +{ + dvector d; + d.x = a[C].x + a[X].x*x + a[XX].x*x*x + a[XXX].x*x*x*x + a[XXY].x*x*x*y + + a[XXZ].x*x*x*z + a[XY].x*x*y + a[XYY].x*x*y*y + a[XYZ].x*x*y*z + + a[XZ].x*x*z + a[XZZ].x*x*z*z + a[Y].x*y + a[YY].x*y*y + + a[YYY].x*y*y*y + a[YYZ].x*y*y*z + a[YZ].x*y*z + a[YZZ].x*y*z*z + + a[Z].x*z + a[ZZ].x*z*z + a[ZZZ].x*z*z*z; + + d.y = a[C].y + a[X].y*x + a[XX].y*x*x + a[XXX].y*x*x*x + a[XXY].y*x*x*y + + a[XXZ].y*x*x*z + a[XY].y*x*y + a[XYY].y*x*y*y + a[XYZ].y*x*y*z + + a[XZ].y*x*z + a[XZZ].y*x*z*z + a[Y].y*y + a[YY].y*y*y + + a[YYY].y*y*y*y + a[YYZ].y*y*y*z + a[YZ].y*y*z + a[YZZ].y*y*z*z + + a[Z].y*z + a[ZZ].y*z*z + a[ZZZ].y*z*z*z; + + d.z = a[C].z + a[X].z*x + a[XX].z*x*x + a[XXX].z*x*x*x + a[XXY].z*x*x*y + + a[XXZ].z*x*x*z + a[XY].z*x*y + a[XYY].z*x*y*y + a[XYZ].z*x*y*z + + a[XZ].z*x*z + a[XZZ].z*x*z*z + a[Y].z*y + a[YY].z*y*y + + a[YYY].z*y*y*y + a[YYZ].z*y*y*z + a[YZ].z*y*z + a[YZZ].z*y*z*z + + a[Z].z*z + a[ZZ].z*z*z + a[ZZZ].z*z*z*z; + + return d; +} + +/* 3D Cubic in (x,z) with periodic sinusoidal forcing term in x. y is + the independent periodic (time) axis. This includes Birkhoff's + Bagel and Duffing's Attractor */ +static dvector +Periodic(Par a, double x, double y, double z) +{ + dvector d; + + d.x = a[C].x + a[X].x*x + a[XX].x*x*x + a[XXX].x*x*x*x + + a[XXZ].x*x*x*z + a[XZ].x*x*z + a[XZZ].x*x*z*z + a[Z].x*z + + a[ZZ].x*z*z + a[ZZZ].x*z*z*z + a[SINY].x*sin(y); + + d.y = a[C].y; + + d.z = a[C].z + a[X].z*x + a[XX].z*x*x + a[XXX].z*x*x*x + + a[XXZ].z*x*x*z + a[XZ].z*x*z + a[XZZ].z*x*z*z + a[Z].z*z + + a[ZZ].z*z*z + a[ZZZ].z*z*z*z; + + return d; +} + +/* Numerical integration of the ODE using 2nd order Runge Kutta. + Returns length^2 of the update, so that we can detect if the step + size needs reducing. */ +static double +Iterate(dvector *p, dvector(*ODE)(Par par, double x, double y, double z), + Par par, double step) +{ + dvector k1, k2, k3; + + k1 = ODE(par, p->x, p->y, p->z); + k1.x *= step; + k1.y *= step; + k1.z *= step; + k2 = ODE(par, p->x + k1.x, p->y + k1.y, p->z + k1.z); + k2.x *= step; + k2.y *= step; + k2.z *= step; + k3.x = (k1.x + k2.x) / 2.0; + k3.y = (k1.y + k2.y) / 2.0; + k3.z = (k1.z + k2.z) / 2.0; + + p->x += k3.x; + p->y += k3.y; + p->z += k3.z; + + return k3.x*k3.x + k3.y*k3.y + k3.z*k3.z; +} + +/* Memory functions */ + +#define deallocate(p,t) if (p!=NULL) {free(p); p=(t*)NULL; } +#define allocate(p,t,s) if ((p=(t*)malloc(sizeof(t)*s))==NULL)\ +{free_flow(sp);return;} + +static void +free_flow(flowstruct *sp) +{ + deallocate(sp->csegs, XSegment); + deallocate(sp->cnsegs, int); + deallocate(sp->old_segs, XSegment); + deallocate(sp->p, dvector); +} + +/* Generate Gaussian random number: mean 0, "amplitude" A (actually + A is 3*standard deviation). */ + +/* Note this generates a pair of gaussian variables, so it saves one + to give out next time it's called */ +static double +Gauss_Rand(double A) +{ + static double d; + static Bool ready = 0; + if(ready) { + ready = 0; + return A/3 * d; + } else { + double x, y, w; + do { + x = 2.0 * (double)LRAND() / MAXRAND - 1.0; + y = 2.0 * (double)LRAND() / MAXRAND - 1.0; + w = x*x + y*y; + } while(w >= 1.0); + + w = sqrt((-2 * log(w))/w); + ready = 1; + d = x * w; + return A/3 * y * w; + } +} + +/* Attempt to discover new atractors by sending a pair of bees on a + fast trip through the new flow and computing their Lyapunov + exponent. Returns False if the bees fly away. + + If the bees stay bounded, the new bounds and the Lyapunov exponent + are stored in sp and the function returns True. + + Repeat invocations continue the flow and improve the accuracy of + the bounds and the Lyapunov exponent. Set sp->count2 to zero to + start a new test. + + Acts on alternate variable set, so that it can be run in parallel + with the main flow */ + +static Bool +discover(ModeInfo * mi) +{ + flowstruct *sp; + double l = 0; + dvector dl; + dvector max, min; + double dl2, df, rs, lsum = 0, s, maxv2 = 0, v2; + + int N, i, nl = 0; + + if (flows == NULL) + return 0; + sp = &flows[MI_SCREEN(mi)]; + + if(sp->count2 == 0) { + /* initial conditions */ + sp->p2[0].x = Gauss_Rand(sp->range.x); + sp->p2[0].y = (sp->yperiod > 0)? + balance_rand(sp->range.y) : Gauss_Rand(sp->range.y); + sp->p2[0].z = Gauss_Rand(sp->range.z); + + /* 1000 steps to find an attractor */ + /* Most cases explode out here */ + for(N=0; N < 1000; N++){ + Iterate(sp->p2, sp->ODE, sp->par2, sp->step2); + if(sp->yperiod > 0 && sp->p2[0].y > sp->yperiod) + sp->p2[0].y -= sp->yperiod; + if(fabs(sp->p2[0].x) > LOST_IN_SPACE || + fabs(sp->p2[0].y) > LOST_IN_SPACE || + fabs(sp->p2[0].z) > LOST_IN_SPACE) { + return 0; + } + sp->count2++; + } + /* Small perturbation */ + sp->p2[1].x = sp->p2[0].x + 0.000001; + sp->p2[1].y = sp->p2[0].y; + sp->p2[1].z = sp->p2[0].z; + } + + /* Reset bounding box */ + max.x = min.x = sp->p2[0].x; + max.y = min.y = sp->p2[0].y; + max.z = min.z = sp->p2[0].z; + + /* Compute Lyapunov Exponent */ + + /* (Technically, we're only estimating the largest Lyapunov + Exponent, but that's all we need to know to determine if we + have a strange attractor.) [TDA] */ + + /* Fly two bees close together */ + for(N=0; N < 5000; N++){ + for(i=0; i< 2; i++) { + v2 = Iterate(sp->p2+i, sp->ODE, sp->par2, sp->step2); + if(sp->yperiod > 0 && sp->p2[i].y > sp->yperiod) + sp->p2[i].y -= sp->yperiod; + + if(fabs(sp->p2[i].x) > LOST_IN_SPACE || + fabs(sp->p2[i].y) > LOST_IN_SPACE || + fabs(sp->p2[i].z) > LOST_IN_SPACE) { + return 0; + } + if(v2 > maxv2) maxv2 = v2; /* Track max v^2 */ + } + + /* find bounding box */ + if ( sp->p2[0].x < min.x ) min.x = sp->p2[0].x; + else if ( sp->p2[0].x > max.x ) max.x = sp->p2[0].x; + if ( sp->p2[0].y < min.y ) min.y = sp->p2[0].y; + else if ( sp->p2[0].y > max.y ) max.y = sp->p2[0].y; + if ( sp->p2[0].z < min.z ) min.z = sp->p2[0].z; + else if ( sp->p2[0].z > max.z ) max.z = sp->p2[0].z; + + /* Measure how much we have to pull the two bees to prevent + them diverging. */ + dl.x = sp->p2[1].x - sp->p2[0].x; + dl.y = sp->p2[1].y - sp->p2[0].y; + dl.z = sp->p2[1].z - sp->p2[0].z; + + dl2 = dl.x*dl.x + dl.y*dl.y + dl.z*dl.z; + if(dl2 > 0) { + df = 1e12 * dl2; + rs = 1/sqrt(df); + sp->p2[1].x = sp->p2[0].x + rs * dl.x; + sp->p2[1].y = sp->p2[0].y + rs * dl.y; + sp->p2[1].z = sp->p2[0].z + rs * dl.z; + lsum = lsum + log(df); + nl = nl + 1; + l = M_LOG2E / 2 * lsum / nl / sp->step2; + } + sp->count2++; + } + /* Anything that didn't explode has a finite attractor */ + /* If Lyapunov is negative then it probably hit a fixed point or a + * limit cycle. Positive Lyapunov indicates a strange attractor. */ + + sp->lyap2 = l; + + sp->size2 = max.x - min.x; + s = max.y - min.y; + if(s > sp->size2) sp->size2 = s; + s = max.z - min.z; + if(s > sp->size2) sp->size2 = s; + + sp->mid2.x = (max.x + min.x) / 2; + sp->mid2.y = (max.y + min.y) / 2; + sp->mid2.z = (max.z + min.z) / 2; + + if(sqrt(maxv2) > sp->size2 * 0.2) { + /* Flowing too fast, reduce step size. This + helps to eliminate high-speed limit cycles, + which can show +ve Lyapunov due to integration + inaccuracy. */ + sp->step2 /= 2; + } + return 1; +} + +/* Sets up initial conditions for a flow without all the extra baggage + that goes with init_flow */ +static void +restart_flow(ModeInfo * mi) +{ + flowstruct *sp; + int b; + + if (flows == NULL) + return; + sp = &flows[MI_SCREEN(mi)]; + sp->count = 0; + + /* Re-Initialize point positions, velocities, etc. */ + for (b = 0; b < sp->beecount; b++) { + X(0, b) = Gauss_Rand(sp->range.x); + Y(0, b) = (sp->yperiod > 0)? + balance_rand(sp->range.y) : Gauss_Rand(sp->range.y); + Z(0, b) = Gauss_Rand(sp->range.z); + } +} + +/* Returns true if line was behind a clip plane, or it clips the line */ +/* nx,ny,nz is the normal to the plane. d is the distance from the origin */ +/* s and e are the end points of the line to be clipped */ +static int +clip(double nx, double ny, double nz, double d, dvector *s, dvector *e) +{ + int front1, front2; + dvector w, p; + double t; + + front1 = (nx*s->x + ny*s->y + nz*s->z >= -d); + front2 = (nx*e->x + ny*e->y + nz*e->z >= -d); + if (!front1 && !front2) return 1; + if (front1 && front2) return 0; + w.x = e->x - s->x; + w.y = e->y - s->y; + w.z = e->z - s->z; + + /* Find t in line equation */ + t = ( -d - nx*s->x - ny*s->y - nz*s->z) / ( nx*w.x + ny*w.y + nz*w.z); + + p.x = s->x + w.x * t; + p.y = s->y + w.y * t; + p.z = s->z + w.z * t; + + /* Move clipped point to the intersection */ + if (front2) { + *s = p; + } else { + *e = p; + } + return 0; +} + +/* + * Public functions + */ + +ENTRYPOINT void +init_flow (ModeInfo * mi) +{ + flowstruct *sp; + char *name; + + if (flows == NULL) { + if ((flows = (flowstruct *) calloc(MI_NUM_SCREENS(mi), + sizeof (flowstruct))) == NULL) + return; + } + sp = &flows[MI_SCREEN(mi)]; + + sp->count2 = 0; + + sp->taillen = MI_SIZE(mi); + if (sp->taillen < -MINTRAIL) { + /* Change by sqrt so it seems more variable */ + sp->taillen = NRAND((int)sqrt((double) (-sp->taillen - MINTRAIL + 1))); + sp->taillen = sp->taillen * sp->taillen + MINTRAIL; + } else if (sp->taillen < MINTRAIL) { + sp->taillen = MINTRAIL; + } + + if(!rotatep && !ridep) rotatep = True; /* We need at least one viewpoint */ + + /* Start camera at Orbit or Bee */ + if(rotatep) { + sp->chaseto = ORBIT; + } else { + sp->chaseto = BEE; + } + sp->chasetime = 1; /* Go directly to target */ + + sp->lyap = 0; + sp->yperiod = 0; + sp->step2 = INITIALSTEP; + + /* Zero parameter set */ + memset(sp->par2, 0, N_PARS * sizeof(dvector)); + + /* Set up standard examples */ + switch (NRAND((periodicp) ? 5 : 3)) { + case 0: + /* + x' = a(y - x) + y' = x(b - z) - y + z' = xy - cz + */ + name = "Lorentz"; + sp->par2[Y].x = 10 + balance_rand(5*0); /* a */ + sp->par2[X].x = - sp->par2[Y].x; /* -a */ + sp->par2[X].y = 28 + balance_rand(5*0); /* b */ + sp->par2[XZ].y = -1; + sp->par2[Y].y = -1; + sp->par2[XY].z = 1; + sp->par2[Z].z = - 2 + balance_rand(1*0); /* -c */ + break; + case 1: + /* + x' = -(y + az) + y' = x + by + z' = c + z(x - 5.7) + */ + name = "Rossler"; + sp->par2[Y].x = -1; + sp->par2[Z].x = -2 + balance_rand(1); /* a */ + sp->par2[X].y = 1; + sp->par2[Y].y = 0.2 + balance_rand(0.1); /* b */ + sp->par2[C].z = 0.2 + balance_rand(0.1); /* c */ + sp->par2[XZ].z = 1; + sp->par2[Z].z = -5.7; + break; + case 2: + /* + x' = -(y + az) + y' = x + by - cz^2 + z' = 0.2 + z(x - 5.7) + */ + name = "RosslerCone"; + sp->par2[Y].x = -1; + sp->par2[Z].x = -2; /* a */ + sp->par2[X].y = 1; + sp->par2[Y].y = 0.2; /* b */ + sp->par2[ZZ].y = -0.331 + balance_rand(0.01); /* c */ + sp->par2[C].z = 0.2; + sp->par2[XZ].z = 1; + sp->par2[Z].z = -5.7; + break; + case 3: + /* + x' = -z + b sin(y) + y' = c + z' = 0.7x + az(0.1 - x^2) + */ + name = "Birkhoff"; + sp->par2[Z].x = -1; + sp->par2[SINY].x = 0.35 + balance_rand(0.25); /* b */ + sp->par2[C].y = 1.57; /* c */ + sp->par2[X].z = 0.7; + sp->par2[Z].z = 1 + balance_rand(0.5); /* a/10 */ + sp->par2[XXZ].z = -10 * sp->par2[Z].z; /* -a */ + sp->yperiod = 2 * M_PI; + break; + default: + /* + x' = -ax - z/2 - z^3/8 + b sin(y) + y' = c + z' = 2x + */ + name = "Duffing"; + sp->par2[X].x = -0.2 + balance_rand(0.1); /* a */ + sp->par2[Z].x = -0.5; + sp->par2[ZZZ].x = -0.125; + sp->par2[SINY].x = 27.0 + balance_rand(3.0); /* b */ + sp->par2[C].y = 1.33; /* c */ + sp->par2[X].z = 2; + sp->yperiod = 2 * M_PI; + break; + + } + + sp->range.x = 5; + sp->range.z = 5; + + if(sp->yperiod > 0) { + sp->ODE = Periodic; + /* periodic flows show either uniform distribution or a + snapshot on the 'time' axis */ + sp->range.y = NRAND(2)? sp->yperiod : 0; + } else { + sp->range.y = 5; + sp->ODE = Cubic; + } + + /* Run discoverer to set up bounding box, etc. Lyapunov will + probably be innaccurate, since we're only running it once, but + we're using known strange attractors so it should be ok. */ + discover(mi); + if(MI_IS_VERBOSE(mi)) + fprintf(stdout, + "flow: Lyapunov exponent: %g, step: %g, size: %g (%s)\n", + sp->lyap2, sp->step2, sp->size2, name); + /* Install new params */ + sp->lyap = sp->lyap2; + sp->size = sp->size2; + sp->mid = sp->mid2; + sp->step = sp->step2; + memcpy(sp->par, sp->par2, sizeof(sp->par2)); + + sp->count2 = 0; /* Reset search */ + + free_flow(sp); + sp->beecount = MI_COUNT(mi); + if (sp->beecount < 0) { /* random variations */ + sp->beecount = NRAND(-sp->beecount) + 1; /* Minimum 1 */ + } + +# ifdef HAVE_COCOA /* Don't second-guess Quartz's double-buffering */ + dbufp = False; +# endif + + if(dbufp) { /* Set up double buffer */ + if (sp->buffer != None) + XFreePixmap(MI_DISPLAY(mi), sp->buffer); + sp->buffer = XCreatePixmap(MI_DISPLAY(mi), MI_WINDOW(mi), + MI_WIDTH(mi), MI_HEIGHT(mi), MI_DEPTH(mi)); + } else { + sp->buffer = MI_WINDOW(mi); + } + /* no "NoExpose" events from XCopyArea wanted */ + XSetGraphicsExposures(MI_DISPLAY(mi), MI_GC(mi), False); + + /* Make sure we're using 'thin' lines */ + XSetLineAttributes(MI_DISPLAY(mi), MI_GC(mi), 0, LineSolid, CapNotLast, + JoinMiter); + + /* Clear the background (may be slow depending on user prefs). */ + MI_CLEARWINDOW(mi); + + /* Allocate memory. */ + if (sp->csegs == NULL) { + allocate(sp->csegs, XSegment, + (sp->beecount + BOX_L) * MI_NPIXELS(mi) * sp->taillen); + allocate(sp->cnsegs, int, MI_NPIXELS(mi)); + allocate(sp->old_segs, XSegment, sp->beecount * sp->taillen); + allocate(sp->p, dvector, sp->beecount * sp->taillen); + } + + /* Initialize point positions, velocities, etc. */ + restart_flow(mi); + + /* Set up camera tail */ + X(1, 0) = sp->cam[1].x = 0; + Y(1, 0) = sp->cam[1].y = 0; + Z(1, 0) = sp->cam[1].z = 0; +} + +ENTRYPOINT void +draw_flow (ModeInfo * mi) +{ + int b, i; + int col, begin, end; + double M[3][3]; /* transformation matrix */ + flowstruct *sp = NULL; + int swarm = 0; + int segindex; + + if (flows == NULL) + return; + sp = &flows[MI_SCREEN(mi)]; + if (sp->csegs == NULL) + return; + +#ifdef HAVE_COCOA /* Don't second-guess Quartz's double-buffering */ + XClearWindow (MI_DISPLAY(mi), MI_WINDOW(mi)); +#endif + + /* multiplier for indexing segment arrays. Used in IX macro, etc. */ + segindex = (sp->beecount + BOX_L) * sp->taillen; + + if(searchp){ + if(sp->count2 == 0) { /* start new search */ + sp->step2 = INITIALSTEP; + /* Pick random parameters. Actual range is irrelevant + since parameter scale determines flow speed but not + structure. */ + for(i=0; i< N_PARS; i++) { + sp->par2[i].x = Gauss_Rand(1.0); + sp->par2[i].y = Gauss_Rand(1.0); + sp->par2[i].z = Gauss_Rand(1.0); + } + } + if(!discover(mi)) { /* Flow exploded, reset. */ + sp->count2 = 0; + } else { + if(sp->lyap2 < 0) { + sp->count2 = 0; /* Attractor found, but it's not strange */ + }else if(sp->count2 > 1000000) { /* This one will do */ + sp->count2 = 0; /* Reset search */ + if(MI_IS_VERBOSE(mi)) + fprintf(stdout, + "flow: Lyapunov exponent: %g, step: %g, size: %g (unnamed)\n", + sp->lyap2, sp->step2, sp->size2); + /* Install new params */ + sp->lyap = sp->lyap2; + sp->size = sp->size2; + sp->mid = sp->mid2; + sp->step = sp->step2; + memcpy(sp->par, sp->par2, sizeof(sp->par2)); + + /* If we're allowed to zoom out, do so now, so that we + get a look at the new attractor. */ + if(sp->chaseto == BEE && rotatep) { + sp->chaseto = ORBIT; + sp->chasetime = 100; + } + /* Reset initial conditions, so we don't get + misleading artifacts in the particle density. */ + restart_flow(mi); + } + } + } + + /* Reset segment buffers */ + for (col = 0; col < MI_NPIXELS(mi); col++) + sp->cnsegs[col] = 0; + + MI_IS_DRAWN(mi) = True; + + /* Calculate circling POV [Chalky]*/ + sp->circle[1] = sp->circle[0]; + sp->circle[0].x = sp->size * 2 * sin(sp->count / 100.0) * + (-0.6 + 0.4 *cos(sp->count / 500.0)) + sp->mid.x; + sp->circle[0].y = sp->size * 2 * cos(sp->count / 100.0) * + (0.6 + 0.4 *cos(sp->count / 500.0)) + sp->mid.y; + sp->circle[0].z = sp->size * 2 * sin(sp->count / 421.0) + sp->mid.z; + + /* Timed chase instead of Chalkie's Bistable oscillator [TDA] */ + if(rotatep && ridep) { + if(sp->chaseto == BEE && NRAND(1000) == 0){ + sp->chaseto = ORBIT; + sp->chasetime = 100; + }else if(NRAND(4000) == 0){ + sp->chaseto = BEE; + sp->chasetime = 100; + } + } + + /* Set up orientation matrix */ + { + double x[3], p[3], x2=0, xp=0; + int j; + + /* Chasetime is here to guarantee the camera makes it all the + way to the target in a finite number of steps. */ + if(sp->chasetime > 1) + sp->chasetime--; + + if(sp->chaseto == BEE){ + /* Camera Head targets bee 0 */ + sp->cam[0].x += (X(0, 0) - sp->cam[0].x)/sp->chasetime; + sp->cam[0].y += (Y(0, 0) - sp->cam[0].y)/sp->chasetime; + sp->cam[0].z += (Z(0, 0) - sp->cam[0].z)/sp->chasetime; + + /* Camera Tail targets previous position of bee 0 */ + sp->cam[1].x += (X(1, 0) - sp->cam[1].x)/sp->chasetime; + sp->cam[1].y += (Y(1, 0) - sp->cam[1].y)/sp->chasetime; + sp->cam[1].z += (Z(1, 0) - sp->cam[1].z)/sp->chasetime; + + /* Camera Wing targets bee 1 */ + sp->cam[2].x += (X(0, 1) - sp->cam[2].x)/sp->chasetime; + sp->cam[2].y += (Y(0, 1) - sp->cam[2].y)/sp->chasetime; + sp->cam[2].z += (Z(0, 1) - sp->cam[2].z)/sp->chasetime; + } else { + /* Camera Head targets Orbiter */ + sp->cam[0].x += (sp->circle[0].x - sp->cam[0].x)/sp->chasetime; + sp->cam[0].y += (sp->circle[0].y - sp->cam[0].y)/sp->chasetime; + sp->cam[0].z += (sp->circle[0].z - sp->cam[0].z)/sp->chasetime; + + /* Camera Tail targets diametrically opposite the middle + of the bounding box from the Orbiter */ + sp->cam[1].x += + (2*sp->circle[0].x - sp->mid.x - sp->cam[1].x)/sp->chasetime; + sp->cam[1].y += + (2*sp->circle[0].y - sp->mid.y - sp->cam[1].y)/sp->chasetime; + sp->cam[1].z += + (2*sp->circle[0].z - sp->mid.z - sp->cam[1].z)/sp->chasetime; + /* Camera Wing targets previous position of Orbiter */ + sp->cam[2].x += (sp->circle[1].x - sp->cam[2].x)/sp->chasetime; + sp->cam[2].y += (sp->circle[1].y - sp->cam[2].y)/sp->chasetime; + sp->cam[2].z += (sp->circle[1].z - sp->cam[2].z)/sp->chasetime; + } + + /* Viewpoint from Tail of camera */ + sp->centre.x=sp->cam[1].x; + sp->centre.y=sp->cam[1].y; + sp->centre.z=sp->cam[1].z; + + /* forward vector */ + x[0] = sp->cam[0].x - sp->cam[1].x; + x[1] = sp->cam[0].y - sp->cam[1].y; + x[2] = sp->cam[0].z - sp->cam[1].z; + + /* side */ + p[0] = sp->cam[2].x - sp->cam[1].x; + p[1] = sp->cam[2].y - sp->cam[1].y; + p[2] = sp->cam[2].z - sp->cam[1].z; + + + /* So long as X and P don't collide, these can be used to form + three mutually othogonal axes: X, (X x P) x X and X x P. + After being normalised to unit length, these form the + Orientation Matrix. */ + + for(i=0; i<3; i++){ + x2+= x[i]*x[i]; /* X . X */ + xp+= x[i]*p[i]; /* X . P */ + M[0][i] = x[i]; /* X */ + } + + for(i=0; i<3; i++) /* (X x P) x X */ + M[1][i] = x2*p[i] - xp*x[i]; /* == (X . X) P - (X . P) X */ + + M[2][0] = x[1]*p[2] - x[2]*p[1]; /* X x P */ + M[2][1] = -x[0]*p[2] + x[2]*p[0]; + M[2][2] = x[0]*p[1] - x[1]*p[0]; + + /* normalise axes */ + for(j=0; j<3; j++){ + double A=0; + for(i=0; i<3; i++) A+=M[j][i]*M[j][i]; /* sum squares */ + A=sqrt(A); + if(A>0) + for(i=0; i<3; i++) M[j][i]/=A; + } + + if(sp->chaseto == BEE) { + X(0, 1)=X(0, 0)+M[1][0]*sp->step; /* adjust neighbour */ + Y(0, 1)=Y(0, 0)+M[1][1]*sp->step; + Z(0, 1)=Z(0, 0)+M[1][2]*sp->step; + } + } + + /* <=- Bounding Box -=> */ + if(boxp) { + for (b = 0; b < BOX_L; b++) { + + /* Chalky's clipping code, Only used for the box */ + /* clipping trails is slow and of little benefit. [TDA] */ + int p1 = lines[b][0]; + int p2 = lines[b][1]; + dvector A1, A2; + double x1=box[p1][0]* sp->size/2 + sp->mid.x - sp->centre.x; + double y1=box[p1][1]* sp->size/2 + sp->mid.y - sp->centre.y; + double z1=box[p1][2]* sp->size/2 + sp->mid.z - sp->centre.z; + double x2=box[p2][0]* sp->size/2 + sp->mid.x - sp->centre.x; + double y2=box[p2][1]* sp->size/2 + sp->mid.y - sp->centre.y; + double z2=box[p2][2]* sp->size/2 + sp->mid.z - sp->centre.z; + + A1.x=M[0][0]*x1 + M[0][1]*y1 + M[0][2]*z1; + A1.y=M[1][0]*x1 + M[1][1]*y1 + M[1][2]*z1; + A1.z=M[2][0]*x1 + M[2][1]*y1 + M[2][2]*z1 + EYEHEIGHT * sp->size; + A2.x=M[0][0]*x2 + M[0][1]*y2 + M[0][2]*z2; + A2.y=M[1][0]*x2 + M[1][1]*y2 + M[1][2]*z2; + A2.z=M[2][0]*x2 + M[2][1]*y2 + M[2][2]*z2 + EYEHEIGHT * sp->size; + + /* Clip in 3D before projecting down to 2D. A 2D clip + after projection wouldn't be able to handle lines that + cross x=0 */ + if (clip(1, 0, 0,-1, &A1, &A2) || /* Screen */ + clip(1, 2, 0, 0, &A1, &A2) || /* Left */ + clip(1,-2, 0, 0, &A1, &A2) || /* Right */ + clip(1,0, 2.0*MI_WIDTH(mi)/MI_HEIGHT(mi), 0, &A1, &A2)||/*UP*/ + clip(1,0,-2.0*MI_WIDTH(mi)/MI_HEIGHT(mi), 0, &A1, &A2))/*Down*/ + continue; + + /* Colour according to bee */ + col = b % (MI_NPIXELS(mi) - 1); + + sp->csegs[IX(col)].x1 = MI_WIDTH(mi)/2 + MI_WIDTH(mi) * A1.y/A1.x; + sp->csegs[IX(col)].y1 = MI_HEIGHT(mi)/2 + MI_WIDTH(mi) * A1.z/A1.x; + sp->csegs[IX(col)].x2 = MI_WIDTH(mi)/2 + MI_WIDTH(mi) * A2.y/A2.x; + sp->csegs[IX(col)].y2 = MI_HEIGHT(mi)/2 + MI_WIDTH(mi) * A2.z/A2.x; + sp->cnsegs[col]++; + } + } + + /* <=- Bees -=> */ + for (b = 0; b < sp->beecount; b++) { + if(fabs(X(0, b)) > LOST_IN_SPACE || + fabs(Y(0, b)) > LOST_IN_SPACE || + fabs(Z(0, b)) > LOST_IN_SPACE){ + if(sp->chaseto == BEE && b == 0){ + /* Lost camera bee. Need to replace it since + rerunning init_flow could lose us a hard-won new + attractor. Try moving it very close to a random + other bee. This way we have a good chance of being + close to the attractor and not forming a false + artifact. If we've lost many bees this may need to + be repeated. */ + /* Don't worry about camera wingbee. It stays close + to the main camera bee no matter what happens. */ + int newb = 1 + NRAND(sp->beecount - 1); + X(0, 0) = X(0, newb) + 0.001; + Y(0, 0) = Y(0, newb); + Z(0, 0) = Z(0, newb); + if(MI_IS_VERBOSE(mi)) + fprintf(stdout, + "flow: resetting lost camera near bee %d\n", + newb); + } + continue; + } + + /* Age the tail. It's critical this be fast since + beecount*taillen can be large. */ + memmove(B(1, b), B(0, b), (sp->taillen - 1) * sizeof(dvector)); + + Iterate(B(0,b), sp->ODE, sp->par, sp->step); + + /* Don't show wingbee since he's not quite in the flow. */ + if(sp->chaseto == BEE && b == 1) continue; + + /* Colour according to bee */ + col = b % (MI_NPIXELS(mi) - 1); + + /* Fill the segment lists. */ + + begin = 0; /* begin new trail */ + end = MIN(sp->taillen, sp->count); /* short trails at first */ + for(i=0; i < end; i++){ + double x = X(i,b)-sp->centre.x; + double y = Y(i,b)*(sp->yperiod < 0? (sp->size/sp->yperiod) :1) + -sp->centre.y; + double z = Z(i,b)-sp->centre.z; + double XM=M[0][0]*x + M[0][1]*y + M[0][2]*z; + double YM=M[1][0]*x + M[1][1]*y + M[1][2]*z; + double ZM=M[2][0]*x + M[2][1]*y + M[2][2]*z + EYEHEIGHT * sp->size; + short absx, absy; + + swarm++; /* count the remaining bees */ + if(sp->yperiod > 0 && Y(i,b) > sp->yperiod){ + int j; + Y(i,b) -= sp->yperiod; + /* hide tail to prevent streaks in Y. Streaks in X,Z + are ok, they help to outline the Poincare' + slice. */ + for(j = i; j < end; j++) Y(j,b) = Y(i,b); + /*begin = i + 1;*/ + break; + } + + if(XM <= 0){ /* off screen - new trail */ + begin = i + 1; + continue; + } + absx = MI_WIDTH(mi)/2 + MI_WIDTH(mi) * YM/XM; + absy = MI_HEIGHT(mi)/2 + MI_WIDTH(mi) * ZM/XM; + /* Performance bottleneck */ + if(absx <= 0 || absx >= MI_WIDTH(mi) || + absy <= 0 || absy >= MI_HEIGHT(mi)) { + /* off screen - new trail */ + begin = i + 1; + continue; + } + if(i > begin) { /* complete previous segment */ + sp->csegs[IX(col)].x2 = absx; + sp->csegs[IX(col)].y2 = absy; + sp->cnsegs[col]++; + } + + if(i < end -1){ /* start new segment */ + sp->csegs[IX(col)].x1 = absx; + sp->csegs[IX(col)].y1 = absy; + } + } + } + + /* Erase */ + XSetForeground(MI_DISPLAY(mi), MI_GC(mi), MI_BLACK_PIXEL(mi)); + if (dbufp) { /* In Double Buffer case, prepare off-screen copy */ + /* For slow systems, this can be the single biggest bottleneck + in the program. These systems may be better of not using + the double buffer. */ + XFillRectangle(MI_DISPLAY(mi), sp->buffer, MI_GC(mi), 0, 0, + MI_WIDTH(mi), MI_HEIGHT(mi)); + } else { /* Otherwise, erase previous segment list directly */ + XDrawSegments(MI_DISPLAY(mi), sp->buffer, MI_GC(mi), + sp->old_segs, sp->nold_segs); + } + + /* Render */ + if (MI_NPIXELS(mi) > 2){ /* colour */ + int mn = 0; + for (col = 0; col < MI_NPIXELS(mi) - 1; col++) + if (sp->cnsegs[col] > 0) { + if(sp->cnsegs[col] > mn) mn = sp->cnsegs[col]; + XSetForeground(MI_DISPLAY(mi), MI_GC(mi), MI_PIXEL(mi, col+1)); + /* This is usually the biggest bottleneck on most + systems. The maths load is insignificant compared + to this. */ + XDrawSegments(MI_DISPLAY(mi), sp->buffer, MI_GC(mi), + sp->csegs + col * segindex, sp->cnsegs[col]); + } + } else { /* mono handled seperately since xlockmore uses '1' for + mono white! */ + XSetForeground(MI_DISPLAY(mi), MI_GC(mi), MI_WHITE_PIXEL(mi)); + XDrawSegments(MI_DISPLAY(mi), sp->buffer, MI_GC(mi), + sp->csegs, sp->cnsegs[0]); + } + if (dbufp) { /* In Double Buffer case, this updates the screen */ + XCopyArea(MI_DISPLAY(mi), sp->buffer, MI_WINDOW(mi), MI_GC(mi), 0, 0, + MI_WIDTH(mi), MI_HEIGHT(mi), 0, 0); + } else { /* Otherwise, screen is already updated. Copy segments + to erase-list to be erased directly next time. */ + int c = 0; + for (col = 0; col < MI_NPIXELS(mi) - 1; col++) { + memcpy(sp->old_segs + c, sp->csegs + col * segindex, + sp->cnsegs[col] * sizeof(XSegment)); + c += sp->cnsegs[col]; + } + sp->nold_segs = c; + } + + if(sp->count > 1 && swarm == 0) { /* all gone */ + if(MI_IS_VERBOSE(mi)) + fprintf(stdout, "flow: all gone at %d\n", sp->count); + init_flow(mi); + } + + if(sp->count++ > MI_CYCLES(mi)){ /* Time's up. If we haven't + found anything new by now we + should pick a new standard + flow */ + init_flow(mi); + } +} + +ENTRYPOINT void +reshape_flow(ModeInfo * mi, int width, int height) +{ + init_flow (mi); +} + + +ENTRYPOINT void +release_flow (ModeInfo * mi) +{ + if (flows != NULL) { + int screen; + + for (screen = 0; screen < MI_NUM_SCREENS(mi); screen++) + free_flow(&flows[screen]); + free(flows); + flows = (flowstruct *) NULL; + } +} + +ENTRYPOINT void +refresh_flow (ModeInfo * mi) +{ + if(!dbufp) MI_CLEARWINDOW(mi); +} + +XSCREENSAVER_MODULE ("Flow", flow) + +#endif /* MODE_flow */ diff --git a/hacks/flow.man b/hacks/flow.man new file mode 100644 index 00000000..ea3a2956 --- /dev/null +++ b/hacks/flow.man @@ -0,0 +1,137 @@ +.TH XScreenSaver 1 "" "X Version 11" +.SH NAME +flow - strange attractors. +.SH SYNOPSIS +.B flow +[\-display \fIhost:display.screen\fP] +[\-visual \fIvisual\fP] +[\-window] +[\-root] +[\-count \fInumber\fP] +[\-cycles \fInumber\fP] +[\-periodic|\-no\-periodic] +[\-search|\-no\-search] +[\-rotate|\-no\-rotate] +[\-ride|\-no\-ride] +[\-box|\-no\-box] +[\-dbuf|\-no\-dbuf] +[\-ncolors \fInumber\fP] +[\-delay \fInumber\fP] +[\-fps] +.SH DESCRIPTION +Strange attractors formed of flows in a 3D differential equation phase +space. Features the popular attractors described by \fBLorentz\fP, +\fBRoessler\fP, \fBBirkhoff\fP and \fBDuffing\fP, and can discover +entirely new attractors by itself. +.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 \-count \fInumber\fP +Number of particles in the flow. Default: 3000 +.TP 8 +.B \-size \fInumber\fP +Length of particle trails. Negative values indicate +randomness. The computational load of a given flow depends on +(particle count) * (trail length). Default: -10 +.TP 8 +.B \-cycles \fInumber\fP +Timeout before changing objects. 0 - 800000. Default: 10000. +.TP 8 +.B \-periodic +.TP 8 +.B \-no\-periodic +turn on/off periodic attractors. These are flows in 2 dependent +variables, with a periodic dependence on a third independent variable +(eg time). Flow will sometimes choose to start all the particles in +the same phase to illustrate the flow's cross-section. Default: +on +.TP 8 +.B \-search +.TP 8 +.B \-no\-search +turn on/off search for new attractors. If this is enabled, a fraction +of the computing cycles is directed to searching a 60-dimensional +parameter space for new strange attractors. If periodic flows are +enabled, these can be searched too. Watch carefully - you are quite +likely to see mathematical objects that have never been seen before, +and since the parameters are not recorded, you'll probably never see +them again! Default: on +.TP 8 +.B \-rotate +.TP 8 +.B \-no\-rotate +turn on/off rotating around attractor. Default: on +.TP 8 +.B \-ride +.TP 8 +.B \-no\-ride +turn on/off ride in the flow. Default: on + +If both -rotate and -ride are enabled the viewpoint will occasionally +fly between the two views. +.TP 8 +.B \-box +.TP 8 +.B \-no\-box +turn on/off bounding box. Default: on +.TP 8 +.B \-dbuf +.TP 8 +.B \-no\-dbuf +turn on/off double buffering. If Flow runs slowly in full screen, but +fast in a smaller window (eg on old graphics cards with too little +memory), try turning this option off. Default: on +.TP 8 +.B \-ncolors \fInumber\fP +Number of Colors. Default: 200. +.TP 8 +.B \-delay \fInumber\fP +Per-frame delay, in microseconds. Default: 10000 (0.01 seconds.). +.TP 8 +.B \-fps +Display the current frame rate and CPU load. +.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 (c) 1996 by Tim Auckland +Incorporating some code from Stephen Davies Copyright (c) 2000 + +Search code based on techniques described in "Strange Attractors: +Creating Patterns in Chaos" by Julien C. Sprott + +Permission to use, copy, modify, and distribute this software and its +documentation for any purpose and without fee is hereby granted, +provided that the above copyright notice appear in all copies and that +both that copyright notice and this permission notice appear in +supporting documentation. + +This file is provided AS IS with no warranties of any kind. The author +shall have no liability with respect to the infringement of copyrights, +trade secrets or any patents by this file or any part thereof. In no +event will the author be liable for any lost revenue or profits or +other special, indirect and consequential damages. + +Adapted from swarm.c Copyright (c) 1991 by Patrick J. Naughton. + +Adapted from xswarm by Jeff Butterworth. (butterwo@ncsc.org). +.SH AUTHOR +Tim Auckland diff --git a/hacks/fluidballs.c b/hacks/fluidballs.c new file mode 100644 index 00000000..958f7bc1 --- /dev/null +++ b/hacks/fluidballs.c @@ -0,0 +1,805 @@ +/* fluidballs, Copyright (c) 2000 by Peter Birtles + * + * 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. + * + * Ported to X11 and xscreensaver by jwz, 27-Feb-2002. + * + * http://astronomy.swin.edu.au/~pbourke/modelling/fluid/ + * + * Some physics improvements by Steven Barker + */ + +/* Future ideas: + * Specifying a distribution in the ball sizes (with a gamma curve, possibly). + * Brownian motion, for that extra touch of realism. + * + * It would be nice to detect when there are more balls than fit in + * the window, and scale the number of balls back. Useful for the + * xscreensaver-demo preview, which is often too tight by default. + */ + +#include +#include "screenhack.h" +#include + +#ifdef HAVE_DOUBLE_BUFFER_EXTENSION +#include "xdbe.h" +#endif /* HAVE_DOUBLE_BUFFER_EXTENSION */ + +typedef struct { + Display *dpy; + Window window; + XWindowAttributes xgwa; + int delay; + + Pixmap b, ba; /* double-buffer to reduce flicker */ +#ifdef HAVE_DOUBLE_BUFFER_EXTENSION + XdbeBackBuffer backb; + Bool dbeclear_p; +#endif /* HAVE_DOUBLE_BUFFER_EXTENSION */ + + GC draw_gc; /* most of the balls */ + GC draw_gc2; /* the ball being dragged with the mouse */ + GC erase_gc; + XColor fg; + XColor fg2; + + int count; /* number of balls */ + float xmin, ymin; /* rectangle of window, relative to root */ + float xmax, ymax; + + int mouse_ball; /* index of ball being dragged, or 0 if none. */ + + float tc; /* time constant (time-warp multiplier) */ + float accx; /* horizontal acceleration (wind) */ + float accy; /* vertical acceleration (gravity) */ + + float *vx, *vy; /* current ball velocities */ + float *px, *py; /* current ball positions */ + float *opx, *opy; /* previous ball positions */ + float *r; /* ball radiuses */ + + float *m; /* ball mass, precalculated */ + float e; /* coeficient of elasticity */ + float max_radius; /* largest radius of any ball */ + + Bool random_sizes_p; /* Whether balls should be various sizes up to max. */ + Bool shake_p; /* Whether to mess with gravity when things settle. */ + Bool dbuf; /* Whether we're using double buffering. */ + float shake_threshold; + int time_since_shake; + + Bool fps_p; /* Whether to draw some text at the bottom. */ + GC font_gc; + int font_height; + int font_baseline; + int frame_count; + int collision_count; + char fps_str[1024]; + + int time_tick; + struct timeval last_time; + +} b_state; + + +/* Draws the frames per second string */ +static void +draw_fps_string (b_state *state) +{ + XFillRectangle (state->dpy, state->b, state->erase_gc, + 0, state->xgwa.height - state->font_height*3 - 20, + state->xgwa.width, state->font_height*3 + 20); + XDrawImageString (state->dpy, state->b, state->font_gc, + 10, state->xgwa.height - state->font_height*2 - + state->font_baseline - 10, + state->fps_str, strlen(state->fps_str)); +} + +/* Finds the origin of the window relative to the root window, by + walking up the window tree until it reaches the top. + */ +static void +window_origin (Display *dpy, Window window, int *x, int *y) +{ + XTranslateCoordinates (dpy, window, RootWindow (dpy, DefaultScreen (dpy)), + 0, 0, x, y, &window); +} + + +/* Queries the window position to see if the window has moved or resized. + We poll this instead of waiting for ConfigureNotify events, because + when the window manager moves the window, only one ConfigureNotify + comes in: at the end of the motion. If we poll, we can react to the + new position while the window is still being moved. (Assuming the WM + does OpaqueMove, of course.) + */ +static void +check_window_moved (b_state *state) +{ + float oxmin = state->xmin; + float oxmax = state->xmax; + float oymin = state->ymin; + float oymax = state->ymax; + int wx, wy; + XGetWindowAttributes (state->dpy, state->window, &state->xgwa); + window_origin (state->dpy, state->window, &wx, &wy); + state->xmin = wx; + state->ymin = wy; + state->xmax = state->xmin + state->xgwa.width; + state->ymax = state->ymin + state->xgwa.height - (state->font_height*3) - + (state->font_height ? 22 : 0); + + if (state->dbuf && (state->ba)) + { + if (oxmax != state->xmax || oymax != state->ymax) + { + XFreePixmap (state->dpy, state->ba); + state->ba = XCreatePixmap (state->dpy, state->window, + state->xgwa.width, state->xgwa.height, + state->xgwa.depth); + XFillRectangle (state->dpy, state->ba, state->erase_gc, 0, 0, + state->xgwa.width, state->xgwa.height); + state->b = state->ba; + } + } + else + { + /* Only need to erase the window if the origin moved */ + if (oxmin != state->xmin || oymin != state->ymin) + XClearWindow (state->dpy, state->window); + else if (state->fps_p && oymax != state->ymax) + XFillRectangle (state->dpy, state->b, state->erase_gc, + 0, state->xgwa.height - state->font_height*3, + state->xgwa.width, state->font_height*3); + } +} + + +/* Returns the position of the mouse relative to the root window. + */ +static void +query_mouse (b_state *state, int *x, int *y) +{ + Window root1, child1; + int mouse_x, mouse_y, root_x, root_y; + unsigned int mask; + if (XQueryPointer (state->dpy, state->window, &root1, &child1, + &root_x, &root_y, &mouse_x, &mouse_y, &mask)) + { + *x = root_x; + *y = root_y; + } + else + { + *x = -9999; + *y = -9999; + } +} + +/* Re-pick the colors of the balls, and the mouse-ball. + */ +static void +recolor (b_state *state) +{ + if (state->fg.flags) + XFreeColors (state->dpy, state->xgwa.colormap, &state->fg.pixel, 1, 0); + if (state->fg2.flags) + XFreeColors (state->dpy, state->xgwa.colormap, &state->fg2.pixel, 1, 0); + + state->fg.flags = DoRed|DoGreen|DoBlue; + state->fg.red = 0x8888 + (random() % 0x8888); + state->fg.green = 0x8888 + (random() % 0x8888); + state->fg.blue = 0x8888 + (random() % 0x8888); + + state->fg2.flags = DoRed|DoGreen|DoBlue; + state->fg2.red = 0x8888 + (random() % 0x8888); + state->fg2.green = 0x8888 + (random() % 0x8888); + state->fg2.blue = 0x8888 + (random() % 0x8888); + + if (XAllocColor (state->dpy, state->xgwa.colormap, &state->fg)) + XSetForeground (state->dpy, state->draw_gc, state->fg.pixel); + + if (XAllocColor (state->dpy, state->xgwa.colormap, &state->fg2)) + XSetForeground (state->dpy, state->draw_gc2, state->fg2.pixel); +} + +/* Initialize the state structure and various X data. + */ +static void * +fluidballs_init (Display *dpy, Window window) +{ + int i; + float extx, exty; + b_state *state = (b_state *) calloc (1, sizeof(*state)); + XGCValues gcv; + + state->dpy = dpy; + state->window = window; + state->delay = get_integer_resource (dpy, "delay", "Integer"); + + check_window_moved (state); + + state->dbuf = get_boolean_resource (dpy, "doubleBuffer", "Boolean"); + +# ifdef HAVE_COCOA /* Don't second-guess Quartz's double-buffering */ + state->dbuf = False; +# endif + + if (state->dbuf) + { +#ifdef HAVE_DOUBLE_BUFFER_EXTENSION + state->dbeclear_p = get_boolean_resource (dpy, "useDBEClear", "Boolean"); + if (state->dbeclear_p) + state->b = xdbe_get_backbuffer (dpy, window, XdbeBackground); + else + state->b = xdbe_get_backbuffer (dpy, window, XdbeUndefined); + state->backb = state->b; +#endif /* HAVE_DOUBLE_BUFFER_EXTENSION */ + + if (!state->b) + { + state->ba = XCreatePixmap (state->dpy, state->window, + state->xgwa.width, state->xgwa.height, + state->xgwa.depth); + state->b = state->ba; + } + } + else + { + state->b = state->window; + } + + /* Select ButtonRelease events on the external window, if no other app has + already selected it (only one app can select it at a time: BadAccess. */ +#if 0 + if (! (state->xgwa.all_event_masks & ButtonReleaseMask)) + XSelectInput (state->dpy, state->window, + state->xgwa.your_event_mask | ButtonReleaseMask); +#endif + + gcv.foreground = get_pixel_resource(state->dpy, state->xgwa.colormap, + "foreground", "Foreground"); + gcv.background = get_pixel_resource(state->dpy, state->xgwa.colormap, + "background", "Background"); + state->draw_gc = XCreateGC (state->dpy, state->b, + GCForeground|GCBackground, &gcv); + + gcv.foreground = get_pixel_resource(state->dpy, state->xgwa.colormap, + "mouseForeground", "MouseForeground"); + state->draw_gc2 = XCreateGC (state->dpy, state->b, + GCForeground|GCBackground, &gcv); + + gcv.foreground = gcv.background; + state->erase_gc = XCreateGC (state->dpy, state->b, + GCForeground|GCBackground, &gcv); + + + if (state->ba) + XFillRectangle (state->dpy, state->ba, state->erase_gc, 0, 0, + state->xgwa.width, state->xgwa.height); + + recolor (state); + + extx = state->xmax - state->xmin; + exty = state->ymax - state->ymin; + + state->count = get_integer_resource (dpy, "count", "Count"); + if (state->count < 1) state->count = 20; + + state->max_radius = get_float_resource (dpy, "size", "Size") / 2; + if (state->max_radius < 1.0) state->max_radius = 1.0; + + state->random_sizes_p = get_boolean_resource (dpy, "random", "Random"); + + /* If the initial window size is too small to hold all these balls, + make fewer of them... + */ + { + float r = (state->random_sizes_p + ? state->max_radius * 0.7 + : state->max_radius); + float ball_area = M_PI * r * r; + float balls_area = state->count * ball_area; + float window_area = state->xgwa.width * state->xgwa.height; + window_area *= 0.75; /* don't pack it completely full */ + if (balls_area > window_area) + state->count = window_area / ball_area; + } + + state->accx = get_float_resource (dpy, "wind", "Wind"); + if (state->accx < -1.0 || state->accx > 1.0) state->accx = 0; + + state->accy = get_float_resource (dpy, "gravity", "Gravity"); + if (state->accy < -1.0 || state->accy > 1.0) state->accy = 0.01; + + state->e = get_float_resource (dpy, "elasticity", "Elacitcity"); + if (state->e < 0.2 || state->e > 1.0) state->e = 0.97; + + state->tc = get_float_resource (dpy, "timeScale", "TimeScale"); + if (state->tc <= 0 || state->tc > 10) state->tc = 1.0; + + state->shake_p = get_boolean_resource (dpy, "shake", "Shake"); + state->shake_threshold = get_float_resource (dpy, "shakeThreshold", + "ShakeThreshold"); + + state->fps_p = get_boolean_resource (dpy, "doFPS", "DoFPS"); + if (state->fps_p) + { + XFontStruct *font; + char *fontname = get_string_resource (dpy, "fpsFont", "Font"); + if (!fontname) fontname = "-*-courier-bold-r-normal-*-180-*"; + font = XLoadQueryFont (dpy, fontname); + if (!font) font = XLoadQueryFont (dpy, "fixed"); + if (!font) exit(-1); + gcv.font = font->fid; + gcv.foreground = get_pixel_resource(state->dpy, state->xgwa.colormap, + "textColor", "Foreground"); + state->font_gc = XCreateGC(dpy, state->b, + GCFont|GCForeground|GCBackground, &gcv); + state->font_height = font->ascent + font->descent; + state->font_baseline = font->descent; + } + + state->m = (float *) malloc (sizeof (*state->m) * (state->count + 1)); + state->r = (float *) malloc (sizeof (*state->r) * (state->count + 1)); + state->vx = (float *) malloc (sizeof (*state->vx) * (state->count + 1)); + state->vy = (float *) malloc (sizeof (*state->vy) * (state->count + 1)); + state->px = (float *) malloc (sizeof (*state->px) * (state->count + 1)); + state->py = (float *) malloc (sizeof (*state->py) * (state->count + 1)); + state->opx = (float *) malloc (sizeof (*state->opx) * (state->count + 1)); + state->opy = (float *) malloc (sizeof (*state->opy) * (state->count + 1)); + + for (i=1; i<=state->count; i++) + { + state->px[i] = frand(extx) + state->xmin; + state->py[i] = frand(exty) + state->ymin; + state->vx[i] = frand(0.2) - 0.1; + state->vy[i] = frand(0.2) - 0.1; + + state->r[i] = (state->random_sizes_p + ? ((0.2 + frand(0.8)) * state->max_radius) + : state->max_radius); + /*state->r[i] = pow(frand(1.0), state->sizegamma) * state->max_radius;*/ + + /* state->m[i] = pow(state->r[i],2) * M_PI; */ + state->m[i] = pow(state->r[i],3) * M_PI * 1.3333; + } + + memcpy (state->opx, state->px, sizeof (*state->opx) * (state->count + 1)); + memcpy (state->opy, state->py, sizeof (*state->opx) * (state->count + 1)); + + return state; +} + + +/* Messes with gravity: permute "down" to be in a random direction. + */ +static void +shake (b_state *state) +{ + float a = state->accx; + float b = state->accy; + int i = random() % 4; + + switch (i) + { + case 0: + state->accx = a; + state->accy = b; + break; + case 1: + state->accx = -a; + state->accy = -b; + break; + case 2: + state->accx = b; + state->accy = a; + break; + case 3: + state->accx = -b; + state->accy = -a; + break; + default: + abort(); + break; + } + + state->time_since_shake = 0; + recolor (state); +} + + +/* Look at the current time, and update state->time_since_shake. + Draw the FPS display if desired. + */ +static void +check_wall_clock (b_state *state, float max_d) +{ + state->frame_count++; + + if (state->time_tick++ > 20) /* don't call gettimeofday() too often -- it's slow. */ + { + struct timeval now; +# ifdef GETTIMEOFDAY_TWO_ARGS + struct timezone tzp; + gettimeofday(&now, &tzp); +# else + gettimeofday(&now); +# endif + + if (state->last_time.tv_sec == 0) + state->last_time = now; + + state->time_tick = 0; + if (now.tv_sec == state->last_time.tv_sec) + return; + + state->time_since_shake += (now.tv_sec - state->last_time.tv_sec); + + if (state->fps_p) + { + float elapsed = ((now.tv_sec + (now.tv_usec / 1000000.0)) - + (state->last_time.tv_sec + (state->last_time.tv_usec / 1000000.0))); + float fps = state->frame_count / elapsed; + float cps = state->collision_count / elapsed; + + sprintf (state->fps_str, "Collisions: %.3f/frame Max motion: %.3f", + cps/fps, max_d); + + draw_fps_string(state); + } + + state->frame_count = 0; + state->collision_count = 0; + state->last_time = now; + } +} + +/* Erases the balls at their previous positions, and draws the new ones. + */ +static void +repaint_balls (b_state *state) +{ + int a; + int x1a, x2a, y1a, y2a; + int x1b, x2b, y1b, y2b; + float max_d = 0; + +#ifdef HAVE_COCOA /* Don't second-guess Quartz's double-buffering */ + XClearWindow (state->dpy, state->b); +#endif + + for (a=1; a <= state->count; a++) + { + GC gc; + x1a = (state->opx[a] - state->r[a] - state->xmin); + y1a = (state->opy[a] - state->r[a] - state->ymin); + x2a = (state->opx[a] + state->r[a] - state->xmin); + y2a = (state->opy[a] + state->r[a] - state->ymin); + + x1b = (state->px[a] - state->r[a] - state->xmin); + y1b = (state->py[a] - state->r[a] - state->ymin); + x2b = (state->px[a] + state->r[a] - state->xmin); + y2b = (state->py[a] + state->r[a] - state->ymin); + +#ifndef HAVE_COCOA /* Don't second-guess Quartz's double-buffering */ +#ifdef HAVE_DOUBLE_BUFFER_EXTENSION + if (!state->dbeclear_p || !state->backb) +#endif /* HAVE_DOUBLE_BUFFER_EXTENSION */ + { +/* if (x1a != x1b || y1a != y1b) -- leaves turds if we optimize this */ + { + gc = state->erase_gc; + XFillArc (state->dpy, state->b, gc, + x1a, y1a, x2a-x1a, y2a-y1a, + 0, 360*64); + } + } +#endif /* !HAVE_COCOA */ + + if (state->mouse_ball == a) + gc = state->draw_gc2; + else + gc = state->draw_gc; + + XFillArc (state->dpy, state->b, gc, + x1b, y1b, x2b-x1b, y2b-y1b, + 0, 360*64); + + if (state->shake_p) + { + /* distance this ball moved this frame */ + float d = ((state->px[a] - state->opx[a]) * + (state->px[a] - state->opx[a]) + + (state->py[a] - state->opy[a]) * + (state->py[a] - state->opy[a])); + if (d > max_d) max_d = d; + } + + state->opx[a] = state->px[a]; + state->opy[a] = state->py[a]; + } + + if (state->fps_p +#ifdef HAVE_DOUBLE_BUFFER_EXTENSION + && (state->backb ? state->dbeclear_p : 1) +#endif /* HAVE_DOUBLE_BUFFER_EXTENSION */ + ) + draw_fps_string(state); + +#ifdef HAVE_DOUBLE_BUFFER_EXTENSION + if (state->backb) + { + XdbeSwapInfo info[1]; + info[0].swap_window = state->window; + info[0].swap_action = (state->dbeclear_p ? XdbeBackground : XdbeUndefined); + XdbeSwapBuffers (state->dpy, info, 1); + } + else +#endif /* HAVE_DOUBLE_BUFFER_EXTENSION */ + if (state->dbuf) + { + XCopyArea (state->dpy, state->b, state->window, state->erase_gc, + 0, 0, state->xgwa.width, state->xgwa.height, 0, 0); + } + + if (state->shake_p && state->time_since_shake > 5) + { + max_d /= state->max_radius; + if (max_d < state->shake_threshold || /* when its stable */ + state->time_since_shake > 30) /* or when 30 secs has passed */ + { + shake (state); + } + } + + check_wall_clock (state, max_d); +} + + +/* Implements the laws of physics: move balls to their new positions. + */ +static void +update_balls (b_state *state) +{ + int a, b; + float d, vxa, vya, vxb, vyb, dd, cdx, cdy; + float ma, mb, vca, vcb, dva, dvb; + float dee2; + + check_window_moved (state); + + /* If we're currently tracking the mouse, update that ball first. + */ + if (state->mouse_ball != 0) + { + int mouse_x, mouse_y; + query_mouse (state, &mouse_x, &mouse_y); + state->px[state->mouse_ball] = mouse_x; + state->py[state->mouse_ball] = mouse_y; + state->vx[state->mouse_ball] = + (0.1 * + (state->px[state->mouse_ball] - state->opx[state->mouse_ball]) * + state->tc); + state->vy[state->mouse_ball] = + (0.1 * + (state->py[state->mouse_ball] - state->opy[state->mouse_ball]) * + state->tc); + } + + /* For each ball, compute the influence of every other ball. */ + for (a=1; a <= state->count - 1; a++) + for (b=a + 1; b <= state->count; b++) + { + d = ((state->px[a] - state->px[b]) * + (state->px[a] - state->px[b]) + + (state->py[a] - state->py[b]) * + (state->py[a] - state->py[b])); + dee2 = (state->r[a] + state->r[b]) * + (state->r[a] + state->r[b]); + if (d < dee2) + { + state->collision_count++; + d = sqrt(d); + dd = state->r[a] + state->r[b] - d; + + cdx = (state->px[b] - state->px[a]) / d; + cdy = (state->py[b] - state->py[a]) / d; + + /* Move each ball apart from the other by half the + * 'collision' distance. + */ + state->px[a] -= 0.5 * dd * cdx; + state->py[a] -= 0.5 * dd * cdy; + state->px[b] += 0.5 * dd * cdx; + state->py[b] += 0.5 * dd * cdy; + + ma = state->m[a]; + mb = state->m[b]; + + vxa = state->vx[a]; + vya = state->vy[a]; + vxb = state->vx[b]; + vyb = state->vy[b]; + + vca = vxa * cdx + vya * cdy; /* the component of each velocity */ + vcb = vxb * cdx + vyb * cdy; /* along the axis of the collision */ + + /* elastic collison */ + dva = (vca * (ma - mb) + vcb * 2 * mb) / (ma + mb) - vca; + dvb = (vcb * (mb - ma) + vca * 2 * ma) / (ma + mb) - vcb; + + dva *= state->e; /* some energy lost to inelasticity */ + dvb *= state->e; + +#if 0 + dva += (frand (50) - 25) / ma; /* q: why are elves so chaotic? */ + dvb += (frand (50) - 25) / mb; /* a: brownian motion. */ +#endif + + vxa += dva * cdx; + vya += dva * cdy; + vxb += dvb * cdx; + vyb += dvb * cdy; + + state->vx[a] = vxa; + state->vy[a] = vya; + state->vx[b] = vxb; + state->vy[b] = vyb; + } + } + + /* Force all balls to be on screen. + */ + for (a=1; a <= state->count; a++) + { + if (state->px[a] <= (state->xmin + state->r[a])) + { + state->px[a] = state->xmin + state->r[a]; + state->vx[a] = -state->vx[a] * state->e; + } + if (state->px[a] >= (state->xmax - state->r[a])) + { + state->px[a] = state->xmax - state->r[a]; + state->vx[a] = -state->vx[a] * state->e; + } + if (state->py[a] <= (state->ymin + state->r[a])) + { + state->py[a] = state->ymin + state->r[a]; + state->vy[a] = -state->vy[a] * state->e; + } + if (state->py[a] >= (state->ymax - state->r[a])) + { + state->py[a] = state->ymax - state->r[a]; + state->vy[a] = -state->vy[a] * state->e; + } + } + + /* Apply gravity to all balls. + */ + for (a=1; a <= state->count; a++) + if (a != state->mouse_ball) + { + state->vx[a] += state->accx * state->tc; + state->vy[a] += state->accy * state->tc; + state->px[a] += state->vx[a] * state->tc; + state->py[a] += state->vy[a] * state->tc; + } +} + + +/* Handle X events, specifically, allow a ball to be picked up with the mouse. + */ +static Bool +fluidballs_event (Display *dpy, Window window, void *closure, XEvent *event) +{ + b_state *state = (b_state *) closure; + + if (event->xany.type == ButtonPress) + { + int i, rx, ry; + XTranslateCoordinates (dpy, window, RootWindow (dpy, DefaultScreen(dpy)), + event->xbutton.x, event->xbutton.y, &rx, &ry, + &window); + + if (state->mouse_ball != 0) /* second down-click? drop the ball. */ + { + state->mouse_ball = 0; + return True; + } + else + for (i=1; i <= state->count; i++) + { + float d = ((state->px[i] - rx) * (state->px[i] - rx) + + (state->py[i] - ry) * (state->py[i] - ry)); + float r = state->r[i]; + if (d < r*r) + { + state->mouse_ball = i; + return True; + } + } + return True; + } + else if (event->xany.type == ButtonRelease) /* drop the ball */ + { + state->mouse_ball = 0; + return True; + } + + return False; +} + +static unsigned long +fluidballs_draw (Display *dpy, Window window, void *closure) +{ + b_state *state = (b_state *) closure; + repaint_balls(state); + update_balls(state); + return state->delay; +} + +static void +fluidballs_reshape (Display *dpy, Window window, void *closure, + unsigned int w, unsigned int h) +{ +} + +static void +fluidballs_free (Display *dpy, Window window, void *closure) +{ + b_state *state = (b_state *) closure; + free (state); +} + + +static const char *fluidballs_defaults [] = { + ".background: black", + ".foreground: yellow", + ".textColor: white", + "*mouseForeground: white", + "*delay: 10000", + "*count: 300", + "*size: 25", + "*random: True", + "*gravity: 0.01", + "*wind: 0.00", + "*elasticity: 0.97", + "*timeScale: 1.0", + "*shake: True", + "*shakeThreshold: 0.015", + "*doubleBuffer: True", +#ifdef HAVE_DOUBLE_BUFFER_EXTENSION + "*useDBE: True", + "*useDBEClear: True", +#endif /* HAVE_DOUBLE_BUFFER_EXTENSION */ + 0 +}; + +static XrmOptionDescRec fluidballs_options [] = { + { "-delay", ".delay", XrmoptionSepArg, 0 }, + { "-count", ".count", XrmoptionSepArg, 0 }, + { "-size", ".size", XrmoptionSepArg, 0 }, + { "-count", ".count", XrmoptionSepArg, 0 }, + { "-gravity", ".gravity", XrmoptionSepArg, 0 }, + { "-wind", ".wind", XrmoptionSepArg, 0 }, + { "-elasticity", ".elasticity", XrmoptionSepArg, 0 }, + { "-shake", ".shake", XrmoptionNoArg, "True" }, + { "-no-shake", ".shake", XrmoptionNoArg, "False" }, + { "-random", ".random", XrmoptionNoArg, "True" }, + { "-no-random", ".random", XrmoptionNoArg, "False" }, + { "-nonrandom", ".random", XrmoptionNoArg, "False" }, + { "-db", ".doubleBuffer", XrmoptionNoArg, "True" }, + { "-no-db", ".doubleBuffer", XrmoptionNoArg, "False" }, + { 0, 0, 0, 0 } +}; + + +XSCREENSAVER_MODULE ("FluidBalls", fluidballs) diff --git a/hacks/fluidballs.man b/hacks/fluidballs.man new file mode 100644 index 00000000..650fe63c --- /dev/null +++ b/hacks/fluidballs.man @@ -0,0 +1,90 @@ +.TH XScreenSaver 1 "" "X Version 11" +.SH NAME +fluidballs - the physics of bouncing balls. +.SH SYNOPSIS +.B fluidballs +[\-display \fIhost:display.screen\fP] +[\-visual \fIvisual\fP] +[\-window] +[\-root] +[\-count \fInumber\fP] +[\-size \fInumber\fP] +[\-gravity \fInumber\fP] +[\-wind \fInumber\fP] +[\-elasticity \fInumber\fP] +[\-delay \fInumber\fP] +[\-nonrandom] +[\-no-shake] +[\-fps] +.SH DESCRIPTION +Models the physics of bouncing balls, or of particles in a gas or fluid, +depending on the settings. If "Shake Box" is selected, then every now and +then, the box will be rotated, changing which direction is down (in order +to keep the settled balls in motion.) +.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 \-count \fInumber\fP +How many balls to display. Default: 300. +.TP 8 +.B \-size \fInumber\fP +Maximum size of each ball. Default: 25. +.TP 8 +.B \-gravity \fInumber\fP +Coefficient of gravity. Useful values are < 0.1. Default: 0.01. +.TP 8 +.B \-wind \fInumber\fP +Wind. Useful values are < 0.1. Default: 0.00. +.TP 8 +.B \-elasticity \fInumber\fP +Coefficient of elasticity. Useful values are 0.2 to 1.0. Default: 0.97. +Lower numbers make less bouncy balls. +.TP 8 +.B \-delay \fInumber\fP +Per-frame delay, in microseconds. Default: 10000 (0.01 seconds.). +.TP 8 +.B \-nonrandom +Make all balls be the same size. +.TP 8 +.B \-no-nonrandom +Make the balls be random sizes. Default. +.TP 8 +.B \-shake | \-no-shake +Whether to shake the box if the system seems to have settled down. +"Shake" means "change the direction of Down." +.TP 8 +.B \-fps +Display the current frame rate and CPU load. +.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 2002 by Peter Birtles 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 +Peter Birtles, Jamie Zawinski, and Steven Barker. + diff --git a/hacks/fontglide.c b/hacks/fontglide.c new file mode 100644 index 00000000..4ed76d4d --- /dev/null +++ b/hacks/fontglide.c @@ -0,0 +1,1681 @@ +/* xscreensaver, Copyright (c) 2003, 2005, 2006 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. + * + * fontglide -- reads text from a subprocess and puts it on the screen using + * large characters that glide in from the edges, assemble, then disperse. + * Requires a system with scalable fonts. (X's font handing sucks. A lot.) + */ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif /* HAVE_CONFIG_H */ + +#include + +#ifndef HAVE_COCOA +# include +#endif + +#ifdef HAVE_UNISTD_H +# include +#endif + +#include "screenhack.h" +#include "textclient.h" + +#ifdef HAVE_DOUBLE_BUFFER_EXTENSION +#include "xdbe.h" +#endif /* HAVE_DOUBLE_BUFFER_EXTENSION */ + +typedef struct { + char *text; + int x, y, width, height; + int ascent, lbearing, rbearing; + + int nticks, tick; + int start_x, start_y; + int target_x, target_y; + Pixmap pixmap, mask; +} word; + + +typedef struct { + int id; + XColor fg; + XColor bg; + Bool dark_p; + Bool move_chars_p; + int width; + + char *font_name; + XFontStruct *font; + + GC fg_gc; + + int nwords; + word **words; + + enum { IN, PAUSE, OUT } anim_state; + enum { LEFT, CENTER, RIGHT } alignment; + int pause_tick; + +} sentence; + + +typedef struct { + Display *dpy; + Window window; + XWindowAttributes xgwa; + + Pixmap b, ba; /* double-buffer to reduce flicker */ + GC bg_gc; + +#ifdef HAVE_DOUBLE_BUFFER_EXTENSION + XdbeBackBuffer backb; + Bool dbeclear_p; +#endif /* HAVE_DOUBLE_BUFFER_EXTENSION */ + + Bool dbuf; /* Whether we're using double buffering. */ + + int border_width; /* size of the font outline */ + char *charset; /* registry and encoding for font lookups */ + double speed; /* frame rate multiplier */ + double linger; /* multiplier for how long to leave words on screen */ + Bool trails_p; + Bool debug_p; + int debug_metrics_p; + enum { PAGE, SCROLL } mode; + + char *font_override; /* if -font was specified on the cmd line */ + + char buf [40]; /* this only needs to be as big as one "word". */ + int buf_tail; + + int nsentences; + sentence **sentences; + Bool spawn_p; /* whether it is time to create a new sentence */ + int latest_sentence; + unsigned long frame_delay; + int id_tick; + text_data *tc; + +} state; + + +static void drain_input (state *s); + + +static int +pick_font_size (state *s) +{ + double scale = s->xgwa.height / 1024.0; /* shrink for small windows */ + int min, max, r, pixel; + + min = scale * 24; + max = scale * 260; + + if (min < 10) min = 10; + if (max < 30) max = 30; + + r = ((max-min)/3)+1; + + pixel = min + ((random() % r) + (random() % r) + (random() % r)); + + if (s->mode == SCROLL) /* scroll mode likes bigger fonts */ + pixel *= 1.5; + + return pixel; +} + + +/* Finds the set of scalable fonts on the system; picks one; + and loads that font in a random pixel size. + Returns False if something went wrong. + */ +static Bool +pick_font_1 (state *s, sentence *se) +{ + Bool ok = False; + char pattern[1024]; + +# ifndef HAVE_COCOA /* real Xlib */ + char **names = 0; + char **names2 = 0; + XFontStruct *info = 0; + int count = 0, count2 = 0; + int i; + + if (se->font) + { + XFreeFont (s->dpy, se->font); + free (se->font_name); + se->font = 0; + se->font_name = 0; + } + + if (s->font_override) + sprintf (pattern, "%.200s", s->font_override); + else + sprintf (pattern, "-%s-%s-%s-%s-%s-%s-%s-%s-%s-%s-%s-%s-%s", + "*", /* foundry */ + "*", /* family */ + "*", /* weight */ + "*", /* slant */ + "*", /* swidth */ + "*", /* adstyle */ + "0", /* pixel size */ + "0", /* point size */ + "0", /* resolution x */ + "0", /* resolution y */ + "p", /* spacing */ + "0", /* avg width */ + s->charset); /* registry + encoding */ + + names = XListFonts (s->dpy, pattern, 1000, &count); + + if (count <= 0) + { + if (s->font_override) + fprintf (stderr, "%s: -font option bogus: %s\n", progname, pattern); + else + fprintf (stderr, "%s: no scalable fonts found! (pattern: %s)\n", + progname, pattern); + exit (1); + } + + i = random() % count; + + names2 = XListFontsWithInfo (s->dpy, names[i], 1000, &count2, &info); + if (count2 <= 0) + { + fprintf (stderr, "%s: pattern %s\n" + " gave unusable %s\n\n", + progname, pattern, names[i]); + goto FAIL; + } + + { + XFontStruct *font = &info[0]; + unsigned long value = 0; + char *foundry=0, *family=0, *weight=0, *slant=0, *setwidth=0, *add_style=0; + unsigned long pixel=0, point=0, res_x=0, res_y=0; + char *spacing=0; + unsigned long avg_width=0; + char *registry=0, *encoding=0; + Atom a; + char *bogus = "\"?\""; + +# define STR(ATOM,VAR) \ + bogus = (ATOM); \ + a = XInternAtom (s->dpy, (ATOM), False); \ + if (XGetFontProperty (font, a, &value)) \ + VAR = XGetAtomName (s->dpy, value); \ + else \ + goto FAIL2 + +# define INT(ATOM,VAR) \ + bogus = (ATOM); \ + a = XInternAtom (s->dpy, (ATOM), False); \ + if (!XGetFontProperty (font, a, &VAR) || \ + VAR > 9999) \ + goto FAIL2 + + STR ("FOUNDRY", foundry); + STR ("FAMILY_NAME", family); + STR ("WEIGHT_NAME", weight); + STR ("SLANT", slant); + STR ("SETWIDTH_NAME", setwidth); + STR ("ADD_STYLE_NAME", add_style); + INT ("PIXEL_SIZE", pixel); + INT ("POINT_SIZE", point); + INT ("RESOLUTION_X", res_x); + INT ("RESOLUTION_Y", res_y); + STR ("SPACING", spacing); + INT ("AVERAGE_WIDTH", avg_width); + STR ("CHARSET_REGISTRY", registry); + STR ("CHARSET_ENCODING", encoding); + +#undef INT +#undef STR + + pixel = pick_font_size (s); + +#if 0 + /* Occasionally change the aspect ratio of the font, by increasing + either the X or Y resolution (while leaving the other alone.) + + #### Looks like this trick doesn't really work that well: the + metrics of the individual characters are ok, but the + overall font ascent comes out wrong (unscaled.) + */ + if (! (random() % 8)) + { + double n = 2.5 / 3; + double scale = 1 + (frand(n) + frand(n) + frand(n)); + if (random() % 2) + res_x *= scale; + else + res_y *= scale; + } +# endif + + sprintf (pattern, + "-%s-%s-%s-%s-%s-%s-%ld-%s-%ld-%ld-%s-%s-%s-%s", + foundry, family, weight, slant, setwidth, add_style, + pixel, "*", /* point, */ + res_x, res_y, spacing, + "*", /* avg_width */ + registry, encoding); + ok = True; + + FAIL2: + if (!ok) + fprintf (stderr, "%s: font has bogus %s property: %s\n", + progname, bogus, names[i]); + + if (foundry) XFree (foundry); + if (family) XFree (family); + if (weight) XFree (weight); + if (slant) XFree (slant); + if (setwidth) XFree (setwidth); + if (add_style) XFree (add_style); + if (spacing) XFree (spacing); + if (registry) XFree (registry); + if (encoding) XFree (encoding); + } + + FAIL: + + XFreeFontInfo (names2, info, count2); + XFreeFontNames (names); + +# else /* HAVE_COCOA */ + + if (s->font_override) + sprintf (pattern, "%.200s", s->font_override); + else + { + const char *family = "random"; + const char *weight = ((random() % 2) ? "normal" : "bold"); + const char *slant = ((random() % 2) ? "o" : "r"); + int size = 10 * pick_font_size (s); + sprintf (pattern, "*-%s-%s-%s-*-%d-*", family, weight, slant, size); + } + ok = True; +# endif /* HAVE_COCOA */ + + if (! ok) return False; + + se->font = XLoadQueryFont (s->dpy, pattern); + if (! se->font) + { + if (s->debug_p) + fprintf (stderr, "%s: unable to load font %s\n", + progname, pattern); + return False; + } + + if (se->font->min_bounds.width == se->font->max_bounds.width && + !s->font_override) + { + /* This is to weed out + "-urw-nimbus mono l-medium-o-normal--*-*-*-*-p-*-iso8859-1" and + "-urw-courier-medium-r-normal--*-*-*-*-p-*-iso8859-1". + We asked for only proportional fonts, but this fixed-width font + shows up anyway -- but it has goofy metrics (see below) so it + looks terrible anyway. + */ + if (s->debug_p) + fprintf (stderr, + "%s: skipping bogus monospace non-charcell font: %s\n", + progname, pattern); + return False; + } + + if (s->debug_p) + fprintf(stderr, "%s: %s\n", progname, pattern); + + se->font_name = strdup (pattern); + XSetFont (s->dpy, se->fg_gc, se->font->fid); + return True; +} + + +/* Finds the set of scalable fonts on the system; picks one; + and loads that font in a random pixel size. + */ +static void +pick_font (state *s, sentence *se) +{ + int i; + for (i = 0; i < 20; i++) + if (pick_font_1 (s, se)) + return; + fprintf (stderr, "%s: too many font-loading failures: giving up!\n", progname); + exit (1); +} + + +static char *unread_word_text = 0; + +/* Returns a newly-allocated string with one word in it, or NULL if there + is no complete word available. + */ +static char * +get_word_text (state *s) +{ + char *start = s->buf; + char *end; + char *result = 0; + int lfs = 0; + + drain_input (s); + + if (unread_word_text) + { + start = unread_word_text; + unread_word_text = 0; + return start; + } + + /* Skip over whitespace at the beginning of the buffer, + and count up how many linebreaks we see while doing so. + */ + while (*start && + (*start == ' ' || + *start == '\t' || + *start == '\r' || + *start == '\n')) + { + if (*start == '\n' || (*start == '\r' && start[1] != '\n')) + lfs++; + start++; + } + + end = start; + + /* If we saw a blank line, then return NULL (treat it as a temporary "eof", + to trigger a sentence break here.) */ + if (lfs >= 2) + goto DONE; + + /* Skip forward to the end of this word (find next whitespace.) */ + while (*end && + (! (*end == ' ' || + *end == '\t' || + *end == '\r' || + *end == '\n'))) + end++; + + /* If we have a word, allocate a string for it */ + if (end > start) + { + result = malloc ((end - start) + 1); + strncpy (result, start, (end-start)); + result [end-start] = 0; + } + + DONE: + + /* Make room in the buffer by compressing out any bytes we've processed. + */ + if (end > s->buf) + { + int n = end - s->buf; + memmove (s->buf, end, sizeof(s->buf) - n); + s->buf_tail -= n; + } + + return result; +} + + +/* Gets some random text, and creates a "word" object from it. + */ +static word * +new_word (state *s, sentence *se, char *txt, Bool alloc_p) +{ + word *w; + XCharStruct overall; + int dir, ascent, descent; + int bw = s->border_width; + + if (!txt) + return 0; + + w = (word *) calloc (1, sizeof(*w)); + XTextExtents (se->font, txt, strlen(txt), &dir, &ascent, &descent, &overall); + + /* Leave a little more slack */ + overall.lbearing -= (bw * 2); + overall.rbearing += (bw * 2); + overall.ascent += (bw * 2); + overall.descent += (bw * 2); + + w->width = overall.rbearing - overall.lbearing + bw + bw; + w->height = overall.ascent + overall.descent + bw + bw; + w->ascent = overall.ascent + bw; + w->lbearing = overall.lbearing - bw; + w->rbearing = overall.width + bw; + +# if 0 + /* The metrics on some fonts are strange -- e.g., + "-urw-nimbus mono l-medium-o-normal--*-*-*-*-p-*-iso8859-1" and + "-urw-courier-medium-r-normal--*-*-*-*-p-*-iso8859-1" both have + an rbearing so wide that it looks like there are two spaces after + each letter. If this character says it has an rbearing that is to + the right of its ink, ignore that. + + #### Of course, this hack only helps when we're in `move_chars_p' mode + and drawing a char at a time -- when we draw the whole word at once, + XDrawString believes the bogus metrics and spaces the font out + crazily anyway. + + Sigh, this causes some text to mis-render in, e.g., + "-adobe-utopia-medium-i-normal--114-*-100-100-p-*-iso8859-1" + (in "ux", we need the rbearing on "r" or we get too much overlap.) + */ + if (w->rbearing > w->width) + w->rbearing = w->width; +# endif /* 0 */ + + if (s->mode == SCROLL && !alloc_p) abort(); + + if (alloc_p) + { + int i, j; + XGCValues gcv; + GC gc0, gc1; + + w->pixmap = XCreatePixmap (s->dpy, s->b, w->width, w->height, 1L); + w->mask = XCreatePixmap (s->dpy, s->b, w->width, w->height, 1L); + + gcv.font = se->font->fid; + gcv.foreground = 0L; + gcv.background = 1L; + gc0 = XCreateGC (s->dpy, w->pixmap, GCFont|GCForeground|GCBackground, + &gcv); + gcv.foreground = 1L; + gcv.background = 0L; + gc1 = XCreateGC (s->dpy, w->pixmap, GCFont|GCForeground|GCBackground, + &gcv); + + XFillRectangle (s->dpy, w->mask, gc0, 0, 0, w->width, w->height); + XFillRectangle (s->dpy, w->pixmap, gc0, 0, 0, w->width, w->height); + + if (s->debug_p) + { + /* bounding box (behind the characters) */ + XDrawRectangle (s->dpy, w->pixmap, (se->dark_p ? gc0 : gc1), + 0, 0, w->width-1, w->height-1); + XDrawRectangle (s->dpy, w->mask, gc1, + 0, 0, w->width-1, w->height-1); + } + + if (s->debug_p > 1) + { + /* bounding box (behind *each* character) */ + char *ss; + int x = 0; + for (ss = txt; *ss; ss++) + { + XTextExtents (se->font, ss, 1, &dir, &ascent, &descent, &overall); + XDrawRectangle (s->dpy, w->pixmap, (se->dark_p ? gc0 : gc1), + x, w->ascent - overall.ascent, + overall.width, + overall.ascent + overall.descent); + XDrawRectangle (s->dpy, w->mask, gc1, + x, w->ascent - overall.ascent, + overall.width, + overall.ascent + overall.descent); + + XDrawRectangle (s->dpy, w->pixmap, (se->dark_p ? gc0 : gc1), + x - overall.lbearing, w->ascent - overall.ascent, + overall.rbearing, + overall.ascent + overall.descent); + XDrawRectangle (s->dpy, w->mask, gc1, + x - overall.lbearing, w->ascent - overall.ascent, + overall.rbearing, + overall.ascent + overall.descent); + + + x += overall.width; + } + } + + /* Draw foreground text */ + XDrawString (s->dpy, w->pixmap, gc1, -w->lbearing, w->ascent, + txt, strlen(txt)); + + /* Cheesy hack to draw a border */ + /* (I should be able to do this in i*2 time instead of i*i time, + but I can't get it right, so fuck it.) */ + XSetFunction (s->dpy, gc1, GXor); + for (i = -bw; i <= bw; i++) + for (j = -bw; j <= bw; j++) + XCopyArea (s->dpy, w->pixmap, w->mask, gc1, + 0, 0, w->width, w->height, + i, j); + + if (s->debug_p) + { + XSetFunction (s->dpy, gc1, GXcopy); + if (w->ascent != w->height) + { + /* baseline (on top of the characters) */ + XDrawLine (s->dpy, w->pixmap, (se->dark_p ? gc0 : gc1), + 0, w->ascent, w->width-1, w->ascent); + XDrawLine (s->dpy, w->mask, gc1, + 0, w->ascent, w->width-1, w->ascent); + } + + if (w->lbearing != 0) + { + /* left edge of charcell */ + XDrawLine (s->dpy, w->pixmap, (se->dark_p ? gc0 : gc1), + w->lbearing, 0, w->lbearing, w->height-1); + XDrawLine (s->dpy, w->mask, gc1, + w->lbearing, 0, w->lbearing, w->height-1); + } + + if (w->rbearing != w->width) + { + /* right edge of charcell */ + XDrawLine (s->dpy, w->pixmap, (se->dark_p ? gc0 : gc1), + w->rbearing, 0, w->rbearing, w->height-1); + XDrawLine (s->dpy, w->mask, gc1, + w->rbearing, 0, w->rbearing, w->height-1); + } + } + + XFreeGC (s->dpy, gc0); + XFreeGC (s->dpy, gc1); + } + + w->text = txt; + return w; +} + + +static void +free_word (state *s, word *w) +{ + if (w->text) free (w->text); + if (w->pixmap) XFreePixmap (s->dpy, w->pixmap); + if (w->mask) XFreePixmap (s->dpy, w->mask); +} + + +static sentence * +new_sentence (state *st, state *s) +{ + XGCValues gcv; + sentence *se = (sentence *) calloc (1, sizeof (*se)); + se->fg_gc = XCreateGC (s->dpy, s->b, 0, &gcv); + se->anim_state = IN; + se->id = ++st->id_tick; + return se; +} + + +static void +free_sentence (state *s, sentence *se) +{ + int i; + for (i = 0; i < se->nwords; i++) + free_word (s, se->words[i]); + if (se->words) free (se->words); + + if (se->fg.flags) + XFreeColors (s->dpy, s->xgwa.colormap, &se->fg.pixel, 1, 0); + if (se->bg.flags) + XFreeColors (s->dpy, s->xgwa.colormap, &se->bg.pixel, 1, 0); + + if (se->font_name) free (se->font_name); + if (se->font) XFreeFont (s->dpy, se->font); + if (se->fg_gc) XFreeGC (s->dpy, se->fg_gc); + + free (se); +} + + +/* free the word, and put its text back at the front of the input queue, + to be read next time. */ +static void +unread_word (state *s, word *w) +{ + if (unread_word_text) + abort(); + unread_word_text = w->text; + w->text = 0; + free_word (s, w); +} + + +/* Divide each of the words in the sentence into one character words, + without changing the positions of those characters. + */ +static void +split_words (state *s, sentence *se) +{ + word **words2; + int nwords2 = 0; + int i, j; + for (i = 0; i < se->nwords; i++) + nwords2 += strlen (se->words[i]->text); + + words2 = (word **) calloc (nwords2, sizeof(*words2)); + + for (i = 0, j = 0; i < se->nwords; i++) + { + word *ow = se->words[i]; + int L = strlen (ow->text); + int k; + + int x = ow->x; + int y = ow->y; + int sx = ow->start_x; + int sy = ow->start_y; + int tx = ow->target_x; + int ty = ow->target_y; + + for (k = 0; k < L; k++) + { + char *t2 = malloc (2); + word *w2; + int xoff, yoff; + + t2[0] = ow->text[k]; + t2[1] = 0; + w2 = new_word (s, se, t2, True); + words2[j++] = w2; + + xoff = (w2->lbearing - ow->lbearing); + yoff = (ow->ascent - w2->ascent); + + w2->x = x + xoff; + w2->y = y + yoff; + w2->start_x = sx + xoff; + w2->start_y = sy + yoff; + w2->target_x = tx + xoff; + w2->target_y = ty + yoff; + + x += w2->rbearing; + sx += w2->rbearing; + tx += w2->rbearing; + } + + free_word (s, ow); + se->words[i] = 0; + } + free (se->words); + + se->words = words2; + se->nwords = nwords2; +} + + +/* Set the source or destination position of the words to be somewhere + off screen. + */ +static void +scatter_sentence (state *s, sentence *se) +{ + int i = 0; + int off = 100; + + int flock_p = ((random() % 4) == 0); + int mode = (flock_p ? (random() % 12) : 0); + + for (i = 0; i < se->nwords; i++) + { + word *w = se->words[i]; + int x, y; + int r = (flock_p ? mode : (random() % 4)); + switch (r) + { + /* random positions on the edges */ + + case 0: + x = -off - w->width; + y = random() % s->xgwa.height; + break; + case 1: + x = off + s->xgwa.width; + y = random() % s->xgwa.height; + break; + case 2: + x = random() % s->xgwa.width; + y = -off - w->height; + break; + case 3: + x = random() % s->xgwa.width; + y = off + s->xgwa.height; + break; + + /* straight towards the edges */ + + case 4: + x = -off - w->width; + y = w->target_y; + break; + case 5: + x = off + s->xgwa.width; + y = w->target_y; + break; + case 6: + x = w->target_x; + y = -off - w->height; + break; + case 7: + x = w->target_x; + y = off + s->xgwa.height; + break; + + /* corners */ + + case 8: + x = -off - w->width; + y = -off - w->height; + break; + case 9: + x = -off - w->width; + y = off + s->xgwa.height; + break; + case 10: + x = off + s->xgwa.width; + y = off + s->xgwa.height; + break; + case 11: + x = off + s->xgwa.width; + y = -off - w->height; + break; + + default: + abort(); + break; + } + + if (se->anim_state == IN) + { + w->start_x = x; + w->start_y = y; + } + else + { + w->start_x = w->x; + w->start_y = w->y; + w->target_x = x; + w->target_y = y; + } + + w->nticks = ((100 + ((random() % 140) + + (random() % 140) + + (random() % 140))) + / s->speed); + if (w->nticks < 2) + w->nticks = 2; + w->tick = 0; + } +} + + +/* Set the source position of the words to be off the right side, + and the destination to be off the left side. + */ +static void +aim_sentence (state *s, sentence *se) +{ + int i = 0; + int nticks; + int yoff = 0; + + if (se->nwords <= 0) abort(); + + /* Have the sentence shift up or down a little bit; not too far, and + never let it fall off the top or bottom of the screen before its + last character has reached the left edge. + */ + for (i = 0; i < 10; i++) + { + int ty = random() % (s->xgwa.height - se->words[0]->ascent); + yoff = ty - se->words[0]->target_y; + if (yoff < s->xgwa.height/3) /* this one is ok */ + break; + } + + for (i = 0; i < se->nwords; i++) + { + word *w = se->words[i]; + w->start_x = w->target_x + s->xgwa.width; + w->target_x -= se->width; + w->start_y = w->target_y; + w->target_y += yoff; + } + + nticks = ((se->words[0]->start_x - se->words[0]->target_x) + / (s->speed * 10)); + nticks *= (frand(0.9) + frand(0.9) + frand(0.9)); + + if (nticks < 2) + nticks = 2; + + for (i = 0; i < se->nwords; i++) + { + word *w = se->words[i]; + w->nticks = nticks; + w->tick = 0; + } +} + + +/* Randomize the order of the words in the list (since that changes + which ones are "on top".) + */ +static void +shuffle_words (state *s, sentence *se) +{ + int i; + for (i = 0; i < se->nwords-1; i++) + { + int j = i + (random() % (se->nwords - i)); + word *swap = se->words[i]; + se->words[i] = se->words[j]; + se->words[j] = swap; + } +} + + +/* qsort comparitor */ +static int +cmp_sentences (const void *aa, const void *bb) +{ + const sentence *a = *(sentence **) aa; + const sentence *b = *(sentence **) bb; + return ((a ? a->id : 999999) - (b ? b->id : 999999)); +} + + +/* Sort the sentences by id, so that sentences added later are on top. + */ +static void +sort_sentences (state *s) +{ + qsort (s->sentences, s->nsentences, sizeof(*s->sentences), cmp_sentences); +} + + +/* Re-pick the colors of the text and border + */ +static void +recolor (state *s, sentence *se) +{ + if (se->fg.flags) + XFreeColors (s->dpy, s->xgwa.colormap, &se->fg.pixel, 1, 0); + if (se->bg.flags) + XFreeColors (s->dpy, s->xgwa.colormap, &se->bg.pixel, 1, 0); + + se->fg.flags = DoRed|DoGreen|DoBlue; + se->bg.flags = DoRed|DoGreen|DoBlue; + + switch (random() % 2) + { + case 0: /* bright fg, dim bg */ + se->fg.red = (random() % 0x8888) + 0x8888; + se->fg.green = (random() % 0x8888) + 0x8888; + se->fg.blue = (random() % 0x8888) + 0x8888; + se->bg.red = (random() % 0x5555); + se->bg.green = (random() % 0x5555); + se->bg.blue = (random() % 0x5555); + break; + + case 1: /* bright bg, dim fg */ + se->fg.red = (random() % 0x4444); + se->fg.green = (random() % 0x4444); + se->fg.blue = (random() % 0x4444); + se->bg.red = (random() % 0x4444) + 0xCCCC; + se->bg.green = (random() % 0x4444) + 0xCCCC; + se->bg.blue = (random() % 0x4444) + 0xCCCC; + break; + + default: + abort(); + break; + } + + if (s->debug_p) + se->dark_p = (se->fg.red*2 + se->fg.green*3 + se->fg.blue < + se->bg.red*2 + se->bg.green*3 + se->bg.blue); + + if (XAllocColor (s->dpy, s->xgwa.colormap, &se->fg)) + XSetForeground (s->dpy, se->fg_gc, se->fg.pixel); + if (XAllocColor (s->dpy, s->xgwa.colormap, &se->bg)) + XSetBackground (s->dpy, se->fg_gc, se->bg.pixel); +} + + +static void +align_line (state *s, sentence *se, int line_start, int x, int right) +{ + int off, j; + switch (se->alignment) + { + case LEFT: off = 0; break; + case CENTER: off = (right - x) / 2; break; + case RIGHT: off = (right - x); break; + default: abort(); break; + } + + if (off != 0) + for (j = line_start; j < se->nwords; j++) + se->words[j]->target_x += off; +} + + +/* Fill the sentence with new words: in "page" mode, fills the page + with text; in "scroll" mode, just makes one long horizontal sentence. + The sentence might have *no* words in it, if no text is currently + available. + */ +static void +populate_sentence (state *s, sentence *se) +{ + int i = 0; + int left, right, top, x, y; + int space = 0; + int line_start = 0; + Bool done = False; + + int array_size = 100; + + se->move_chars_p = (s->mode == SCROLL ? False : + (random() % 3) ? False : True); + se->alignment = (random() % 3); + + recolor (s, se); + + if (se->words) + { + for (i = 0; i < se->nwords; i++) + free_word (s, se->words[i]); + free (se->words); + } + + se->words = (word **) calloc (array_size, sizeof(*se->words)); + se->nwords = 0; + + switch (s->mode) + { + case PAGE: + left = random() % (s->xgwa.width / 3); + right = s->xgwa.width - (random() % (s->xgwa.width / 3)); + top = random() % (s->xgwa.height * 2 / 3); + break; + case SCROLL: + left = 0; + right = s->xgwa.width; + top = random() % s->xgwa.height; + break; + default: + abort(); + break; + } + + x = left; + y = top; + + while (!done) + { + char *txt = get_word_text (s); + word *w; + if (!txt) + { + if (se->nwords == 0) + return; /* If the stream is empty, bail. */ + else + break; /* If EOF after some words, end of sentence. */ + } + + if (! se->font) /* Got a word: need a font now */ + { + pick_font (s, se); + if (y < se->font->ascent) + y += se->font->ascent; + space = XTextWidth (se->font, " ", 1); + } + + w = new_word (s, se, txt, !se->move_chars_p); + + /* If we have a few words, let punctuation terminate the sentence: + stop gathering more words if the last word ends in a period, etc. */ + if (se->nwords >= 4) + { + char c = w->text[strlen(w->text)-1]; + if (c == '.' || c == '?' || c == '!') + done = True; + } + + /* If the sentence is kind of long already, terminate at commas, etc. */ + if (se->nwords >= 12) + { + char c = w->text[strlen(w->text)-1]; + if (c == ',' || c == ';' || c == ':' || c == '-' || + c == ')' || c == ']' || c == '}') + done = True; + } + + if (se->nwords >= 25) /* ok that's just about enough out of you */ + done = True; + + if (s->mode == PAGE && + x + w->rbearing > right) /* wrap line */ + { + align_line (s, se, line_start, x, right); + line_start = se->nwords; + + x = left; + y += se->font->ascent; + + /* If we're close to the bottom of the screen, stop, and + unread the current word. (But not if this is the first + word, otherwise we might just get stuck on it.) + */ + if (se->nwords > 0 && + y + se->font->ascent > s->xgwa.height) + { + unread_word (s, w); + /* done = True; */ + break; + } + } + + w->target_x = x + w->lbearing; + w->target_y = y - w->ascent; + + x += w->rbearing + space; + se->width = x; + + if (se->nwords >= (array_size - 1)) + { + array_size += 100; + se->words = (word **) realloc (se->words, + array_size * sizeof(*se->words)); + if (!se->words) + { + fprintf (stderr, "%s: out of memory (%d words)\n", + progname, array_size); + exit (1); + } + } + + se->words[se->nwords++] = w; + } + + se->width -= space; + + switch (s->mode) + { + case PAGE: + align_line (s, se, line_start, x, right); + if (se->move_chars_p) + split_words (s, se); + scatter_sentence (s, se); + shuffle_words (s, se); + break; + case SCROLL: + aim_sentence (s, se); + break; + default: + abort(); + break; + } + +# ifdef DEBUG + if (s->debug_p) + { + fprintf (stderr, "%s: sentence %d:", progname, se->id); + for (i = 0; i < se->nwords; i++) + fprintf (stderr, " %s", se->words[i]->text); + fprintf (stderr, "\n"); + } +# endif +} + + +/* Render a single word object to the screen. + */ +static void +draw_word (state *s, sentence *se, word *w) +{ + if (! w->pixmap) return; + + if (w->x + w->width < 0 || + w->y + w->height < 0 || + w->x > s->xgwa.width || + w->y > s->xgwa.height) + return; + + XSetClipMask (s->dpy, se->fg_gc, w->mask); + XSetClipOrigin (s->dpy, se->fg_gc, w->x, w->y); + XCopyPlane (s->dpy, w->pixmap, s->b, se->fg_gc, + 0, 0, w->width, w->height, + w->x, w->y, + 1L); +} + + +/* If there is room for more sentences, add one. + */ +static void +more_sentences (state *s) +{ + int i; + Bool any = False; + for (i = 0; i < s->nsentences; i++) + { + sentence *se = s->sentences[i]; + if (! se) + { + se = new_sentence (s, s); + populate_sentence (s, se); + if (se->nwords > 0) + s->spawn_p = False, any = True; + else + { + free_sentence (s, se); + se = 0; + } + s->sentences[i] = se; + if (se) + s->latest_sentence = se->id; + break; + } + } + + if (any) sort_sentences (s); +} + + +/* Render all the words to the screen, and run the animation one step. + */ +static void +draw_sentence (state *s, sentence *se) +{ + int i; + Bool moved = False; + + if (! se) return; + + for (i = 0; i < se->nwords; i++) + { + word *w = se->words[i]; + + switch (s->mode) + { + case PAGE: + if (se->anim_state != PAUSE && + w->tick <= w->nticks) + { + int dx = w->target_x - w->start_x; + int dy = w->target_y - w->start_y; + double r = sin (w->tick * M_PI / (2 * w->nticks)); + w->x = w->start_x + (dx * r); + w->y = w->start_y + (dy * r); + + w->tick++; + if (se->anim_state == OUT && s->mode == PAGE) + w->tick++; /* go out faster */ + moved = True; + } + break; + case SCROLL: + { + int dx = w->target_x - w->start_x; + int dy = w->target_y - w->start_y; + double r = (double) w->tick / w->nticks; + w->x = w->start_x + (dx * r); + w->y = w->start_y + (dy * r); + w->tick++; + moved = (w->tick <= w->nticks); + + /* Launch a new sentence when: + - the front of this sentence is almost off the left edge; + - the end of this sentence is almost on screen. + - or, randomly + */ + if (se->anim_state != OUT && + i == 0 && + se->id == s->latest_sentence) + { + Bool new_p = (w->x < (s->xgwa.width * 0.4) && + w->x + se->width < (s->xgwa.width * 2.1)); + Bool rand_p = (new_p ? 0 : !(random() % 2000)); + + if (new_p || rand_p) + { + se->anim_state = OUT; + s->spawn_p = True; +# ifdef DEBUG + if (s->debug_p) + fprintf (stderr, "%s: OUT %d (x2 = %d%s)\n", + progname, se->id, + se->words[0]->x + se->width, + rand_p ? " randomly" : ""); +# endif + } + } + } + break; + default: + abort(); + break; + } + + draw_word (s, se, w); + } + + if (moved && se->anim_state == PAUSE) + abort(); + + if (! moved) + { + switch (se->anim_state) + { + case IN: + se->anim_state = PAUSE; + se->pause_tick = (se->nwords * 7 * s->linger); + if (se->move_chars_p) + se->pause_tick /= 5; + scatter_sentence (s, se); + shuffle_words (s, se); +# ifdef DEBUG + if (s->debug_p) + fprintf (stderr, "%s: PAUSE %d\n", progname, se->id); +# endif + break; + case PAUSE: + if (--se->pause_tick <= 0) + { + se->anim_state = OUT; + s->spawn_p = True; +# ifdef DEBUG + if (s->debug_p) + fprintf (stderr, "%s: OUT %d\n", progname, se->id); +# endif + } + break; + case OUT: +# ifdef DEBUG + if (s->debug_p) + fprintf (stderr, "%s: DEAD %d\n", progname, se->id); +# endif + { + int j; + for (j = 0; j < s->nsentences; j++) + if (s->sentences[j] == se) + s->sentences[j] = 0; + free_sentence (s, se); + } + break; + default: + abort(); + break; + } + } +} + + +static unsigned long +fontglide_draw_metrics (state *s) +{ + char txt[2]; + char *fn = (s->font_override ? s->font_override : "fixed"); + XFontStruct *font = XLoadQueryFont (s->dpy, fn); + XCharStruct c, overall; + int dir, ascent, descent; + int x, y; + GC gc; + unsigned long red = 0xFFFF0000; /* so shoot me */ + unsigned long green = 0xFF00FF00; + unsigned long blue = 0xFF6666FF; + int i; + + txt[0] = s->debug_metrics_p; + txt[1] = 0; + + gc = XCreateGC (s->dpy, s->window, 0, 0); + XSetFont (s->dpy, gc, font->fid); + +#ifdef HAVE_COCOA + jwxyz_XSetAntiAliasing (s->dpy, gc, False); +#endif + + XTextExtents (font, txt, strlen(txt), + &dir, &ascent, &descent, &overall); + c = font->per_char[((unsigned char *) txt)[0] - font->min_char_or_byte2]; + + XClearWindow (s->dpy, s->window); + + x = (s->xgwa.width - overall.width) / 2; + y = (s->xgwa.height - (2 * (ascent + descent))) / 2; + + for (i = 0; i < 2; i++) + { + XCharStruct cc = (i == 0 ? c : overall); + int x1 = 20; + int x2 = s->xgwa.width - 40; + int x3 = s->xgwa.width; + + XSetForeground (s->dpy, gc, red); + XDrawLine (s->dpy, s->window, gc, 0, y - ascent, x3, y - ascent); + XDrawLine (s->dpy, s->window, gc, 0, y + descent, x3, y + descent); + + XSetForeground (s->dpy, gc, green); + /* ascent, baseline, descent */ + XDrawLine (s->dpy, s->window, gc, x1, y - cc.ascent, x2, y - cc.ascent); + XDrawLine (s->dpy, s->window, gc, x1, y, x2, y); + XDrawLine (s->dpy, s->window, gc, x1, y + cc.descent, x2, y + cc.descent); + + /* origin, width */ + XSetForeground (s->dpy, gc, blue); + XDrawLine (s->dpy, s->window, gc, + x, y - ascent - 10, + x, y + descent + 10); + XDrawLine (s->dpy, s->window, gc, + x + cc.width, y - ascent - 10, + x + cc.width, y + descent + 10); + + /* lbearing, rbearing */ + XSetForeground (s->dpy, gc, green); + XDrawLine (s->dpy, s->window, gc, + x + cc.lbearing, y - ascent, + x + cc.lbearing, y + descent); + XDrawLine (s->dpy, s->window, gc, + x + cc.rbearing, y - ascent, + x + cc.rbearing, y + descent); + + XSetForeground (s->dpy, gc, WhitePixelOfScreen (s->xgwa.screen)); + XDrawString (s->dpy, s->window, gc, x, y, txt, strlen(txt)); + + y += (ascent + descent) * 2; + } + + XFreeGC (s->dpy, gc); + XFreeFont (s->dpy, font); + return s->frame_delay; +} + + +/* Render all the words to the screen, and run the animation one step. + Clear screen first, swap buffers after. + */ +static unsigned long +fontglide_draw (Display *dpy, Window window, void *closure) +{ + state *s = (state *) closure; + int i; + + if (s->debug_metrics_p) + return fontglide_draw_metrics (closure); + + if (s->spawn_p) + more_sentences (s); + + if (!s->trails_p) + XFillRectangle (s->dpy, s->b, s->bg_gc, + 0, 0, s->xgwa.width, s->xgwa.height); + + for (i = 0; i < s->nsentences; i++) + draw_sentence (s, s->sentences[i]); + +#ifdef HAVE_DOUBLE_BUFFER_EXTENSION + if (s->backb) + { + XdbeSwapInfo info[1]; + info[0].swap_window = s->window; + info[0].swap_action = (s->dbeclear_p ? XdbeBackground : XdbeUndefined); + XdbeSwapBuffers (s->dpy, info, 1); + } + else +#endif /* HAVE_DOUBLE_BUFFER_EXTENSION */ + if (s->dbuf) + { + XCopyArea (s->dpy, s->b, s->window, s->bg_gc, + 0, 0, s->xgwa.width, s->xgwa.height, 0, 0); + } + + return s->frame_delay; +} + + + +/* When the subprocess has generated some output, this reads as much as it + can into s->buf at s->buf_tail. + */ +static void +drain_input (state *s) +{ + while (s->buf_tail < sizeof(s->buf) - 2) + { + char c = textclient_getc (s->tc); + if (c > 0) + s->buf[s->buf_tail++] = c; + else + break; + } +} + + +/* Window setup and resource loading */ + +static void * +fontglide_init (Display *dpy, Window window) +{ + XGCValues gcv; + state *s = (state *) calloc (1, sizeof(*s)); + s->dpy = dpy; + s->window = window; + s->frame_delay = get_integer_resource (dpy, "delay", "Integer"); + + XGetWindowAttributes (s->dpy, s->window, &s->xgwa); + + s->font_override = get_string_resource (dpy, "font", "Font"); + if (s->font_override && (!*s->font_override || *s->font_override == '(')) + s->font_override = 0; + + s->charset = get_string_resource (dpy, "fontCharset", "FontCharset"); + s->border_width = get_integer_resource (dpy, "fontBorderWidth", "Integer"); + if (s->border_width < 0 || s->border_width > 20) + s->border_width = 1; + + s->speed = get_float_resource (dpy, "speed", "Float"); + if (s->speed <= 0 || s->speed > 200) + s->speed = 1; + + s->linger = get_float_resource (dpy, "linger", "Float"); + if (s->linger <= 0 || s->linger > 200) + s->linger = 1; + + s->trails_p = get_boolean_resource (dpy, "trails", "Trails"); + s->debug_p = get_boolean_resource (dpy, "debug", "Debug"); + s->debug_metrics_p = (get_boolean_resource (dpy, "debugMetrics", "Debug") + ? 'y' : 0); + + s->dbuf = get_boolean_resource (dpy, "doubleBuffer", "Boolean"); + +# ifdef HAVE_COCOA /* Don't second-guess Quartz's double-buffering */ + s->dbuf = False; +# endif + + if (s->trails_p) s->dbuf = False; /* don't need it in this case */ + + { + char *ss = get_string_resource (dpy, "mode", "Mode"); + if (!ss || !*ss || !strcasecmp (ss, "random")) + s->mode = ((random() % 2) ? SCROLL : PAGE); + else if (!strcasecmp (ss, "scroll")) + s->mode = SCROLL; + else if (!strcasecmp (ss, "page")) + s->mode = PAGE; + else + { + fprintf (stderr, + "%s: `mode' must be `scroll', `page', or `random', not `%s'\n", + progname, ss); + } + } + + if (s->dbuf) + { +#ifdef HAVE_DOUBLE_BUFFER_EXTENSION + s->dbeclear_p = get_boolean_resource (dpy, "useDBEClear", "Boolean"); + if (s->dbeclear_p) + s->b = xdbe_get_backbuffer (dpy, window, XdbeBackground); + else + s->b = xdbe_get_backbuffer (dpy, window, XdbeUndefined); + s->backb = s->b; +#endif /* HAVE_DOUBLE_BUFFER_EXTENSION */ + + if (!s->b) + { + s->ba = XCreatePixmap (s->dpy, s->window, + s->xgwa.width, s->xgwa.height, + s->xgwa.depth); + s->b = s->ba; + } + } + else + { + s->b = s->window; + } + + gcv.foreground = get_pixel_resource (s->dpy, s->xgwa.colormap, + "background", "Background"); + s->bg_gc = XCreateGC (s->dpy, s->b, GCForeground, &gcv); + + s->nsentences = 5; /* #### */ + s->sentences = (sentence **) calloc (s->nsentences, sizeof (sentence *)); + s->spawn_p = True; + + s->tc = textclient_open (dpy); + + return s; +} + + +static Bool +fontglide_event (Display *dpy, Window window, void *closure, XEvent *event) +{ + state *s = (state *) closure; + + if (! s->debug_metrics_p) + return False; + else if (event->xany.type == ButtonPress) + { + s->debug_metrics_p++; + if (s->debug_metrics_p > 255) + s->debug_metrics_p = ' '; + else if (s->debug_metrics_p > 127 && + s->debug_metrics_p < 159) + s->debug_metrics_p = 160; + return True; + } + else if (event->xany.type == KeyPress) + { + KeySym keysym; + char c = 0; + XLookupString (&event->xkey, &c, 1, &keysym, 0); + if (c) + s->debug_metrics_p = (unsigned char) c; + return !!c; + } + else + return False; +} + + +static void +fontglide_reshape (Display *dpy, Window window, void *closure, + unsigned int w, unsigned int h) +{ + state *s = (state *) closure; + XGetWindowAttributes (s->dpy, s->window, &s->xgwa); + + if (s->dbuf && (s->ba)) + { + XFreePixmap (s->dpy, s->ba); + s->ba = XCreatePixmap (s->dpy, s->window, + s->xgwa.width, s->xgwa.height, + s->xgwa.depth); + XFillRectangle (s->dpy, s->ba, s->bg_gc, 0, 0, + s->xgwa.width, s->xgwa.height); + s->b = s->ba; + } +} + +static void +fontglide_free (Display *dpy, Window window, void *closure) +{ + state *s = (state *) closure; + textclient_close (s->tc); + + /* #### there's more to free here */ + + free (s); +} + + +static const char *fontglide_defaults [] = { + ".background: #000000", + ".foreground: #DDDDDD", + ".borderColor: #555555", + "*delay: 10000", + "*program: xscreensaver-text", + "*usePty: false", + "*mode: random", + ".font: (default)", + "*fontCharset: iso8859-1", + "*fontBorderWidth: 2", + "*speed: 1.0", + "*linger: 1.0", + "*trails: False", + "*debug: False", + "*debugMetrics: False", + "*doubleBuffer: True", +#ifdef HAVE_DOUBLE_BUFFER_EXTENSION + "*useDBE: True", + "*useDBEClear: True", +#endif /* HAVE_DOUBLE_BUFFER_EXTENSION */ + 0 +}; + +static XrmOptionDescRec fontglide_options [] = { + { "-mode", ".mode", XrmoptionSepArg, 0 }, + { "-scroll", ".mode", XrmoptionNoArg, "scroll" }, + { "-page", ".mode", XrmoptionNoArg, "page" }, + { "-random", ".mode", XrmoptionNoArg, "random" }, + { "-delay", ".delay", XrmoptionSepArg, 0 }, + { "-speed", ".speed", XrmoptionSepArg, 0 }, + { "-linger", ".linger", XrmoptionSepArg, 0 }, + { "-program", ".program", XrmoptionSepArg, 0 }, + { "-font", ".font", XrmoptionSepArg, 0 }, + { "-fn", ".font", XrmoptionSepArg, 0 }, + { "-bw", ".fontBorderWidth", XrmoptionSepArg, 0 }, + { "-trails", ".trails", XrmoptionNoArg, "True" }, + { "-no-trails", ".trails", XrmoptionNoArg, "False" }, + { "-db", ".doubleBuffer", XrmoptionNoArg, "True" }, + { "-no-db", ".doubleBuffer", XrmoptionNoArg, "False" }, + { "-debug", ".debug", XrmoptionNoArg, "True" }, + { "-debug-metrics", ".debugMetrics", XrmoptionNoArg, "True" }, + { 0, 0, 0, 0 } +}; + + +XSCREENSAVER_MODULE ("FontGlide", fontglide) diff --git a/hacks/fontglide.man b/hacks/fontglide.man new file mode 100644 index 00000000..f60d20d1 --- /dev/null +++ b/hacks/fontglide.man @@ -0,0 +1,124 @@ +.TH XScreenSaver 1 "30-Oct-99" "X Version 11" +.SH NAME +fontglide - characters float onto the screen to form words +.SH SYNOPSIS +.B fontglide +[\-display \fIhost:display.screen\fP] [\-window] [\-root] [\-install] +[\-visual \fIvisual\fP] +[\-delay \fIusecs\fP] +[\-scroll\fP] +[\-page\fP] +[\-random\fP] +[\-speed \fIfloat\fP] +[\-linger \fIfloat\fP] +[\-program \fIsh-command\fP] +[\-font \fIfont-name\fP] +[\-bw \fIint\fP] +[\-trails] +[\-db] +[\-debug] +[\-fps] +.SH DESCRIPTION +The \fIfontglide\fP program reads text from a subprocess and puts it on +the screen using large characters that glide in from the edges, +assemble, then disperse. Alternately, it can simply scroll whole +sentences from right to left. +.SH OPTIONS +.I fontglide +accepts the following options: +.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 \-install +Install a private colormap for the window. +.TP 8 +.B \-visual \fIvisual\fP\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 \-delay \fIusecs\fP +The delay between steps of the animation, in microseconds: default 10000. +.TP 8 +.B \-page +With this option, a page full of text will glide in, and disperse. +.TP 8 +.B \-scroll +With this option, sentences will scroll by from right to left. +.TP 8 +.B \-random +The default is to pick randomly between \fI\-page\fP and \fI\-scroll\fP. +.TP 8 +.B \-speed \fIfloat\fP +How fast to animate; 2 means twice as fast, 0.5 means half as fast. +Default 1.0. +.TP 8 +.B \-linger \fIfloat\fP +How long to leave the assembled text on the screen in \fI\-page\fP mode; +2 means twice as long, 0.5 means half as long. Default 1.0. (The more +words there are on the screen, the longer it lingers.) +.TP 8 +.B \-program \fIsh-command\fP +The command to run to generate the text to display. This option may be +any string acceptable to /bin/sh. The program will be run at the end of +a pipe, and any words that it prints to \fIstdout\fP will end up on +the window. (Whitespace and line breaks are ignored.) If the program +exits, it will be launched again after we have processed all the text +it produced. Default: +.BR xscreensaver-text (1). +.TP 8 +.B \-font\fP \fIstring\fP +The base font pattern to use when loading fonts. The default is to search +for any Latin1 scalable proportional fonts on the system. Once a base font +is selected, it will be loaded in a random size. +.TP 8 +.B \-bw \fIint\fP +How thick an outline to draw around the characters. Default 2 pixels. +.TP 8 +.B \-trails\fP +Leave "vapor trails" behind the moving text. Default off. +.TP 8 +.B \-no-db\fP +Turn off double-buffering. It may be faster, but will flicker. +.TP 8 +.B \-debug\fP +Draw some boxes showing character metrics, and print the name of the +current font to stderr. +.TP 8 +.B \-fps +Display the current frame rate and CPU load. +.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 xscreensaver (1), +.BR xscreensaver-text (1), +.BR fortune (1), +.BR phosphor (MANSUFFIX), +.BR apple2 (MANSUFFIX), +.BR starwars (MANSUFFIX), +.BR ljlatest (MANSUFFIX), +.BR dadadodo (1), +.BR webcollage (MANSUFFIX), +.BR driftnet (1) +.BR EtherPEG , +.BR EtherPeek +.SH COPYRIGHT +Copyright \(co 2003 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 , 15-Sep-2003. diff --git a/hacks/forest.c b/hacks/forest.c new file mode 100644 index 00000000..23392c74 --- /dev/null +++ b/hacks/forest.c @@ -0,0 +1,260 @@ +/* forest.c (aka xtree.c), Copyright (c) 1999 + * Peter Baumung + * + * Most code taken from + * xscreensaver, Copyright (c) 1992, 1995, 1997 + * 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. + */ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +/* ****************************** NOTE ****************************** + + This is not the xlockmore version of forest, but a much better + looking rewrite. Be careful not to delete it in a merging frenzy... + + ********************************************************************** + */ + +#ifdef STANDALONE +# define DEFAULTS "*delay: 500000 \n" \ + "*ncolors: 20 \n" \ + "*fpsSolid: true \n" \ + +# include "xlockmore.h" /* from the xscreensaver distribution */ +# define refresh_trees 0 +# define reshape_trees 0 +# define trees_handle_event 0 +#else /* !STANDALONE */ +# include "xlock.h" /* from the xlockmore distribution */ +#endif /* !STANDALONE */ + +ENTRYPOINT ModeSpecOpt trees_opts = {0, NULL, 0, NULL, NULL}; + +typedef struct { + int x; + int y; + int thick; + double size; + long color; + int toDo; + int pause; + int season; +} treestruct; + +static treestruct *trees = NULL; + +static XColor colors[20]; +static int color; + +static long colorM[12] = {0xff0000, 0xff8000, 0xffff00, 0x80ff00, + 0x00ff00, 0x00ff80, 0x00ffff, 0x0080ff, + 0x0000ff, 0x8000ff, 0xff00ff, 0xff0080}; + +static long colorV[12] = {0x0a0000, 0x0a0500, 0x0a0a00, 0x050a00, + 0x000a00, 0x000a05, 0x000a0a, 0x00050a, + 0x00000a, 0x05000a, 0x0a000a, 0x0a0005}; + +ENTRYPOINT void +init_trees(ModeInfo * mi) +{ + unsigned long pixels[20]; + treestruct *tree; + Display *display = MI_DISPLAY(mi); + GC gc = MI_GC(mi); + int i; + + if (trees == NULL) { + trees = (treestruct *) calloc(MI_NUM_SCREENS(mi), sizeof (treestruct)); + if (trees == NULL) { + return; + } + + if (mi->npixels > 20) { + printf("%d colors selected. Setting limit to 20...\n", mi->npixels); + mi->npixels = 20; + } + + if (mi->npixels < 4) { + for (i = 0; i < mi->npixels; i++) { + colors[i].red = 65535 * (i & 1); + colors[i].green = 65535 * (i & 1); + colors[i].blue = 65535 * (i & 1); + colors[i].flags = DoRed | DoGreen | DoBlue; + } + } else { + if (mi->npixels < 8) { + for (i = 0; i < mi->npixels; i++) { + colors[i].red = 32768 + 4096 * (i % 4); + colors[i].green = 32768 + 4096 * (i % 4); + colors[i].blue = 32768 + 4096 * (i % 4); + colors[i].flags = DoRed | DoGreen | DoBlue; + } + } else { + for (i = 0; i < mi->npixels; i++) { + colors[i].red = 24576 + 4096 * (i % 4); + colors[i].green = 10240 + 2048 * (i % 4); + colors[i].blue = 0; + colors[i].flags = DoRed | DoGreen | DoBlue; + } + } + } + + for (i = 0; i < mi->npixels; i++) + if (!XAllocColor(display, mi->xgwa.colormap, &colors[i])) break; + color = i; + + XSetForeground(display, gc, colors[1].pixel); + } + + XClearWindow(display, MI_WINDOW(mi)); + XSetLineAttributes(display, gc, 2, LineSolid, CapButt, JoinMiter); + tree = &trees[MI_SCREEN(mi)]; + tree->toDo = 25; + tree->season = NRAND(12); + + for (i = 4; i < mi->npixels; i++) { + int sIndex = (tree->season + (i-4) / 4) % 12; + long color = colorM[sIndex] - 2 * colorV[sIndex] * (i % 4); + colors[i].red = (color & 0xff0000) / 256; + colors[i].green = (color & 0x00ff00); + colors[i].blue = (color & 0x0000ff) * 256; + colors[i].flags = DoRed | DoGreen | DoBlue; + } + + for (i = 0; i < color; i++) + pixels[i] = colors[i].pixel; + + XFreeColors(display, mi->xgwa.colormap, pixels, mi->npixels, 0L); + + for (i = 0; i < mi->npixels; i++) + if (!XAllocColor(display, mi->xgwa.colormap, &colors[i])) break; + + color = i; +} + +static double rRand(double a, double b) +{ + return (a+(b-a)*NRAND(10001)/10000.0); +} + +static void draw_line(ModeInfo * mi, + int x1, int y1, int x2, int y2, + double angle, int widths, int widthe) +{ + + Display *display = MI_DISPLAY(mi); + GC gc = MI_GC(mi); + double sns = 0.5*widths*sin(angle + M_PI_2); + double css = 0.5*widths*cos(angle + M_PI_2); + double sne = 0.5*widthe*sin(angle + M_PI_2); + double cse = 0.5*widthe*cos(angle + M_PI_2); + + int xs1 = (int) (x1-sns); + int xs2 = (int) (x1+sns); + int ys1 = (int) (y1-css); + int ys2 = (int) (y1+css); + int xe1 = (int) (x2-sne); + int xe2 = (int) (x2+sne); + int ye1 = (int) (y2-cse); + int ye2 = (int) (y2+cse); + int i; + + for (i = 0; i < widths; i++) { + if (color >= 4) + XSetForeground(display, gc, colors[i*4/widths].pixel); + XDrawLine(display, MI_WINDOW(mi), gc, + xs1+(xs2-xs1)*i/widths, ys1+(ys2-ys1)*i/widths, + xe1+(xe2-xe1)*i/widths, ye1+(ye2-ye1)*i/widths); + } +} + +static void draw_tree_rec(ModeInfo * mi, double thick, int x, int y, double angle) +{ + treestruct *tree = &trees[MI_SCREEN(mi)]; + Display *display = MI_DISPLAY(mi); + GC gc = MI_GC(mi); + int length = (24+NRAND(12))*tree->size; + int a = (int) (x - length*sin(angle)); + int b = (int) (y - length*cos(angle)); + int i; + + draw_line(mi, x, y, a, b, angle, thick*tree->size, 0.68*thick*tree->size); + + if (thick > 2) { + draw_tree_rec(mi, 0.68*thick, a, b, 0.8*angle+rRand(-0.2, 0.2)); + if (thick < tree->thick-1) { + draw_tree_rec(mi, 0.68*thick, a, b, angle+rRand(0.2, 0.9)); + draw_tree_rec(mi, 0.68*thick, (a+x)/2, (b+y)/2, angle-rRand(0.2, 0.9)); + } + } + + if (thick < 0.5*tree->thick) { + int nleaf = 12 + NRAND(4); + XArc leaf[16]; + for (i = 0; i < nleaf; i++) { + leaf[i].x = a + (int) (tree->size * rRand(-12, 12)); + leaf[i].y = b + (int) (tree->size * rRand(-12, 12)); + leaf[i].width = (int) (tree->size * rRand(2, 6)); + leaf[i].height = leaf[i].width; + leaf[i].angle1 = 0; + leaf[i].angle2 = 360 * 64; + } + if (mi->npixels >= 4) + XSetForeground(display, gc, colors[tree->color+NRAND(4)].pixel); + XFillArcs(display, MI_WINDOW(mi), gc, leaf, nleaf); + } +} + +ENTRYPOINT void +draw_trees(ModeInfo * mi) +{ + treestruct *tree = &trees[MI_SCREEN(mi)]; + int width = MI_WIN_WIDTH(mi); + int height = MI_WIN_HEIGHT(mi); + + if (tree->pause == 1) { + tree->pause--; + init_trees(mi); + } else if (tree->pause > 1) { + tree->pause--; + return; + } else if (--(tree->toDo) == 0) { + tree->pause = 6; + return; + } + + tree->x = NRAND(width); + tree->y = (int) (1.25 * height * (1 - tree->toDo / 23.0)); + tree->thick = rRand(7, 12); + tree->size = height / 480.0; + if (color < 8) { + tree->color = 0; + } else { + tree->color = 4 * (1 + NRAND(color / 4 - 1)); + } + + draw_tree_rec(mi, tree->thick, tree->x, tree->y, rRand(-0.1, 0.1)); +} + + +ENTRYPOINT void +release_trees(ModeInfo * mi) +{ + if (trees != NULL) { + (void) free((void *) trees); + trees = NULL; + } +} + +XSCREENSAVER_MODULE_2 ("Forest", forest, trees) diff --git a/hacks/forest.man b/hacks/forest.man new file mode 100644 index 00000000..44472215 --- /dev/null +++ b/hacks/forest.man @@ -0,0 +1,62 @@ +.TH XScreenSaver 1 "27-May-97" "X Version 11" +.SH NAME +forest - draws a fractal forest +.SH SYNOPSIS +.B forest +[\-display \fIhost:display.screen\fP] [\-foreground \fIcolor\fP] [\-background \fIcolor\fP] [\-window] [\-root] [\-mono] [\-install] [\-visual \fIvisual\fP] [\-ncolors \fIinteger\fP] [\-delay \fImicroseconds\fP] + +[\-fps] +.SH DESCRIPTION +The \fIforest\fP program draws a fractal forest. +.SH OPTIONS +.I forest +accepts the following options: +.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 \-mono +If on a color display, pretend we're on a monochrome display. +.TP 8 +.B \-install +Install a private colormap for the window. +.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 \-ncolors \fIinteger\fP +How many colors should be used (if possible). Default 20. + +.TP 8 +.B \-fps +Display the current frame rate and CPU load. +.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), +.BR xlock (1) +.SH COPYRIGHT +Copyright \(co 1995 by Pascal Pensa. + +Permission to use, copy, modify, and distribute this software and its +documentation for any purpose and without fee is hereby granted, +provided that the above copyright notice appear in all copies and that +both that copyright notice and this permission notice appear in +supporting documentation. +.SH AUTHOR +Pascal Pensa , 1995. + +Ability to run standalone or with \fIxscreensaver\fP added by +Jamie Zawinski , 27-May-97. diff --git a/hacks/fps.c b/hacks/fps.c new file mode 100644 index 00000000..1cd39271 --- /dev/null +++ b/hacks/fps.c @@ -0,0 +1,251 @@ +/* fps, Copyright (c) 2001-2011 Jamie Zawinski + * Draw a frames-per-second display (Xlib and OpenGL). + * + * 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. + */ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif /* HAVE_CONFIG_H */ + +#include "screenhackI.h" +#include "fpsI.h" + +fps_state * +fps_init (Display *dpy, Window window) +{ + fps_state *st; + const char *font; + XFontStruct *f; + + if (! get_boolean_resource (dpy, "doFPS", "DoFPS")) + return 0; + + st = (fps_state *) calloc (1, sizeof(*st)); + + st->dpy = dpy; + st->window = window; + st->clear_p = get_boolean_resource (dpy, "fpsSolid", "FPSSolid"); + + font = get_string_resource (dpy, "fpsFont", "Font"); + + if (!font) font = "-*-courier-bold-r-normal-*-180-*"; + f = XLoadQueryFont (dpy, font); + if (!f) f = XLoadQueryFont (dpy, "fixed"); + + { + XWindowAttributes xgwa; + XGCValues gcv; + XGetWindowAttributes (dpy, window, &xgwa); + gcv.font = f->fid; + gcv.foreground = + get_pixel_resource (st->dpy, xgwa.colormap, "foreground", "Foreground"); + st->draw_gc = XCreateGC (dpy, window, GCFont|GCForeground, &gcv); + gcv.foreground = + get_pixel_resource (st->dpy, xgwa.colormap, "background", "Background"); + st->erase_gc = XCreateGC (dpy, window, GCFont|GCForeground, &gcv); + } + + st->font = f; + st->x = 10; + st->y = 10; + if (get_boolean_resource (dpy, "fpsTop", "FPSTop")) + /* don't leave a blank line in GL top-fps. */ + st->y = - (/*st->font->ascent +*/ st->font->descent + 10); + + strcpy (st->string, "FPS: ... "); + + return st; +} + +void +fps_free (fps_state *st) +{ + if (st->draw_gc) XFreeGC (st->dpy, st->draw_gc); + if (st->erase_gc) XFreeGC (st->dpy, st->erase_gc); + if (st->font) XFreeFont (st->dpy, st->font); + free (st); +} + + +void +fps_slept (fps_state *st, unsigned long usecs) +{ + st->slept += usecs; +} + + +double +fps_compute (fps_state *st, unsigned long polys, double depth) +{ + if (! st) return 0; /* too early? */ + + /* Every N frames (where N is approximately one second's worth of frames) + check the wall clock. We do this because checking the wall clock is + a slow operation. + */ + if (st->frame_count++ >= st->last_ifps) + { +# ifdef GETTIMEOFDAY_TWO_ARGS + struct timezone tzp; + gettimeofday(&st->this_frame_end, &tzp); +# else + gettimeofday(&st->this_frame_end); +# endif + + if (st->prev_frame_end.tv_sec == 0) + st->prev_frame_end = st->this_frame_end; + } + + /* If we've probed the wall-clock time, regenerate the string. + */ + if (st->this_frame_end.tv_sec != st->prev_frame_end.tv_sec) + { + double uprev_frame_end = (st->prev_frame_end.tv_sec + + ((double) st->prev_frame_end.tv_usec + * 0.000001)); + double uthis_frame_end = (st->this_frame_end.tv_sec + + ((double) st->this_frame_end.tv_usec + * 0.000001)); + double fps = st->frame_count / (uthis_frame_end - uprev_frame_end); + double idle = (((double) st->slept * 0.000001) / + (uthis_frame_end - uprev_frame_end)); + double load = 100 * (1 - idle); + + if (load < 0) load = 0; /* well that's obviously nonsense... */ + + st->prev_frame_end = st->this_frame_end; + st->frame_count = 0; + st->slept = 0; + st->last_ifps = fps; + st->last_fps = fps; + + sprintf (st->string, (polys + ? "FPS: %.1f \nLoad: %.1f%% " + : "FPS: %.1f \nLoad: %.1f%% "), + fps, load); + + if (polys > 0) + { + const char *s = ""; +# if 0 + if (polys >= (1024 * 1024)) polys >>= 20, s = "M"; + else if (polys >= 2048) polys >>= 10, s = "K"; +# endif + + strcat (st->string, "\nPolys: "); + if (polys >= 1000000) + sprintf (st->string + strlen(st->string), "%lu,%03lu,%03lu%s ", + (polys / 1000000), ((polys / 1000) % 1000), + (polys % 1000), s); + else if (polys >= 1000) + sprintf (st->string + strlen(st->string), "%lu,%03lu%s ", + (polys / 1000), (polys % 1000), s); + else + sprintf (st->string + strlen(st->string), "%lu%s ", polys, s); + } + + if (depth >= 0.0) + { + int L = strlen (st->string); + char *s = st->string + L; + strcat (s, "\nDepth: "); + sprintf (s + strlen(s), "%.1f", depth); + L = strlen (s); + /* Remove trailing ".0" in case depth is not a fraction. */ + if (s[L-2] == '.' && s[L-1] == '0') + s[L-2] = 0; + } + } + + return st->last_fps; +} + + + +/* Width (and optionally height) of the string in pixels. + */ +static int +string_width (XFontStruct *f, const char *c, int *height_ret) +{ + int x = 0; + int max_w = 0; + int h = f->ascent + f->descent; + while (*c) + { + int cc = *((unsigned char *) c); + if (*c == '\n') + { + if (x > max_w) max_w = x; + x = 0; + h += f->ascent + f->descent; + } + else + x += (f->per_char + ? f->per_char[cc-f->min_char_or_byte2].width + : f->min_bounds.rbearing); + c++; + } + if (x > max_w) max_w = x; + if (height_ret) *height_ret = h; + + return max_w; +} + + +/* This function is used only in Xlib mode. For GL mode, see glx/fps-gl.c. + */ +void +fps_draw (fps_state *st) +{ + XWindowAttributes xgwa; + const char *string = st->string; + const char *s; + int x = st->x; + int y = st->y; + int lines = 1; + int lh = st->font->ascent + st->font->descent; + + XGetWindowAttributes (st->dpy, st->window, &xgwa); + + for (s = string; *s; s++) + if (*s == '\n') lines++; + + if (y < 0) + y = -y + (lines-1) * lh; + else + y = xgwa.height - y; + + y -= lh * (lines-1) + st->font->descent; + + /* clear the background */ + if (st->clear_p) + { + int w, h; + w = string_width (st->font, string, &h); + XFillRectangle (st->dpy, st->window, st->erase_gc, + x - st->font->descent, + y - lh, + w + 2*st->font->descent, + h + 2*st->font->descent); + } + + /* draw the text */ + while (lines) + { + s = strchr (string, '\n'); + if (! s) s = string + strlen(string); + XDrawString (st->dpy, st->window, st->draw_gc, + x, y, string, s - string); + string = s; + string++; + lines--; + y += lh; + } +} diff --git a/hacks/fps.h b/hacks/fps.h new file mode 100644 index 00000000..d99ab84b --- /dev/null +++ b/hacks/fps.h @@ -0,0 +1,35 @@ +/* fps, Copyright (c) 2001-2011 Jamie Zawinski + * Draw a frames-per-second display (Xlib and OpenGL). + * + * 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. + */ + +#ifndef __XSCREENSAVER_FPS_H__ +# define __XSCREENSAVER_FPS_H__ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif /* HAVE_CONFIG_H */ + +typedef struct fps_state fps_state; + +extern fps_state *fps_init (Display *, Window); +extern void fps_free (fps_state *); +extern void fps_slept (fps_state *, unsigned long usecs); +extern double fps_compute (fps_state *, unsigned long polys, double depth); +extern void fps_draw (fps_state *); + +/* Doesn't really belong here, but close enough. */ +#ifdef USE_IPHONE + extern double current_device_rotation (void); +#else +# define current_device_rotation() (0) +#endif + +#endif /* __XSCREENSAVER_FPS_H__ */ diff --git a/hacks/fpsI.h b/hacks/fpsI.h new file mode 100644 index 00000000..decd6849 --- /dev/null +++ b/hacks/fpsI.h @@ -0,0 +1,42 @@ +/* fps, Copyright (c) 2001-2012 Jamie Zawinski + * Draw a frames-per-second display (Xlib and OpenGL). + * + * 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. + */ + +#ifndef __XSCREENSAVER_FPSI_H__ +# define __XSCREENSAVER_FPSI_H__ + +#include "fps.h" + +struct fps_state { + Display *dpy; + Window window; + int x, y; + XFontStruct *font; + Bool clear_p; + char string[1024]; + + /* for glx/fps-gl.c */ +# ifdef HAVE_GLBITMAP + unsigned long font_dlist; +# else + void *gl_fps_data; +# endif + + GC draw_gc, erase_gc; + + int last_ifps; + double last_fps; + int frame_count; + unsigned long slept; + struct timeval prev_frame_end, this_frame_end; +}; + +#endif /* __XSCREENSAVER_FPSI_H__ */ diff --git a/hacks/fuzzyflakes.c b/hacks/fuzzyflakes.c new file mode 100644 index 00000000..91762eac --- /dev/null +++ b/hacks/fuzzyflakes.c @@ -0,0 +1,639 @@ +/* fuzzyflakes, Copyright (c) 2004 + * Barry Dmytro + * + * ! 2004.06.10 21:05 + * ! - Added support for resizing + * ! - Added a color scheme generation algorithm + * ! Thanks to from #vegans@irc.blitzed.org + * ! - Added random color generation + * ! - Fixed errors in the xml config file + * ! - Cleaned up a few inconsistencies in the code + * ! - Changed the default color to #EFBEA5 + * + * ! 2004.05.?? ??:?? + * ! -original creation + * + * 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. + */ + +#include +#include "screenhack.h" + +/* I have need of 1/3 and 2/3 constants later on */ +#define N1_3 0.3333333333 +#define N2_3 0.6666666666 + +typedef struct _flake_var +{ + double Ticks; + double XPos, YPos; + double TrueX; + double XOffset; + double Angle; +} FlakeVariable; + +/* Struct containing the atrributes to our flakes */ +typedef struct _flake +{ + Display *dpy; + Window window; + + int Arms; + int Thickness; + int BorderThickness; + int Radius; + unsigned long BordColor; + unsigned long ForeColor; + unsigned long BackColor; + Bool RandomColors; + int Layers; + int Density; + int Delay; + int FallingSpeed; + struct _colors + { + char *Fore; + char *Bord; + char *Back; + } Colors; +/* a dynamic array containing positions of all the flakes */ + FlakeVariable ***Flakes; + XGCValues GCValues; + unsigned long GCFlags; + GC GCVar; + XWindowAttributes XGWA; + struct _dbevar + { + Bool dbuf; + Pixmap b, ba, bb; + } DB; +} Flake; + +/* + *This gets the pixel resource for a color: #ffffff + */ +static unsigned int +FuzzyFlakesColorResource(Flake *flake, char *Color) +{ + XColor color; + + if (!XParseColor(flake->dpy, flake->XGWA.colormap, Color, &color)) + { + fprintf(stderr, "%s: can't parse color %s", progname, Color); + return 0; + } + if (!XAllocColor(flake->dpy, flake->XGWA.colormap, &color)) + { + fprintf(stderr, "%s: can't allocate color %s", progname, Color); + return 0; + } + return color.pixel; +} + +/* + * This is a great color matching algorithm that I got from + * a friend of mine on #vegans@irc.blitzed.org + * She wrote it in PHP and I ported it over to C + * her site is http://beautifulfreak.net/ + */ +static int +FuzzyFlakesColorHelper(Flake *flake) +{ + unsigned int iR, iG, iB; + unsigned int iR0, iG0, iB0; + unsigned int iR1, iG1, iB1; + float fR, fG, fB; + float Max = 0, Min = 0, Lig, Sat; + float Hue, Hue0, Hue1; + float f1, f2; + float fR0, fG0, fB0; + float fR1, fG1, fB1; + float nR0, nG0, nB0; + float nR1, nG1, nB1; + XColor color; + + /* First convert from hex to dec */ + /* while splitting up the RGB values */ + if (!XParseColor(flake->dpy, flake->XGWA.colormap, + flake->Colors.Back, &color)) + { + fprintf(stderr, "%s: can't parse color %s", progname, + flake->Colors.Back); + return 1; + } + iR = color.red >> 8; + iG = color.green >> 8; + iB = color.blue >> 8; + + /* Convert from int to float */ + fR = iR; + fG = iG; + fB = iB; + + /* convert from 0-255 to 0-1 */ + fR = fR / 255; + fG = fG / 255; + fB = fB / 255; + + /* work out the lightness */ + if (fR >= fG && fR >= fB) + Max = fR; + if (fG >= fR && fG >= fB) + Max = fG; + if (fB >= fR && fB >= fG) + Max = fB; + + if (fR <= fG && fR <= fB) + Min = fR; + if (fG <= fR && fG <= fB) + Min = fG; + if (fB <= fR && fB <= fG) + Min = fB; + + Lig = (Max + Min) / 2; + + /* work out the saturation */ + if (Max == Min) + Sat = 0; + else + { + if (Lig < 0.5) + Sat = (Max - Min) / (Max + Min); + else + Sat = (Max - Min) / (2 - Max - Min); + } + + /* + * if our satration is too low we won't be + * able to see any objects + */ + if (Sat < 0.03) + { + return 1; + } + + /* work out the hue */ + if (fR == Max) + Hue = (fG - fB) / (Max - Min); + else if (fG == Max) + Hue = 2 + (fB - fR) / (Max - Min); + else + Hue = 4 + (fR - fG) / (Max - Min); + + Hue = Hue / 6; + + /* fine two equidistant hues */ + Hue0 = Hue + N1_3; + if (Hue0 > 1) + Hue0 = Hue0 - 1; + Hue1 = Hue0 + N1_3; + if (Hue1 > 1) + Hue1 = Hue1 - 1; + + /* convert the colors into hex codes */ + if (Lig < 0.5) + f2 = Lig * (1 + Sat); + else + f2 = (Lig + Sat) - (Lig * Sat); + + f1 = (2 * Lig) - f2; + + fR0 = (Hue0 + 1) / 3; + fR1 = (Hue1 + 1) / 3; + fG0 = Hue0; + fG1 = Hue1; + fB0 = (Hue0 - 1) / 3; + fB1 = (Hue1 - 1) / 3; + + if (fR0 < 0) + fR0 = fR0 + 1; + if (fR0 > 1) + fR0 = fR0 - 1; + if (fG0 < 0) + fG0 = fG0 + 1; + if (fG0 > 1) + fG0 = fG0 - 1; + if (fB0 < 0) + fB0 = fB0 + 1; + if (fB0 > 1) + fB0 = fB0 - 1; + + if (fR1 < 0) + fR1 = fR1 + 1; + if (fR1 > 1) + fR1 = fR1 - 1; + if (fG1 < 0) + fG1 = fG1 + 1; + if (fG1 > 1) + fG1 = fG1 - 1; + if (fB1 < 0) + fB1 = fB1 + 1; + if (fB1 > 1) + fB1 = fB1 - 1; + + if (6 * fR0 < 1) + nR0 = f1 + (f2 - f1) * 6 * fR0; + else if (2 * fR0 < 1) + nR0 = f2; + else if (3 * fR0 < 2) + nR0 = f1 + (f2 - f1) * (N2_3 - fR0) * 6; + else + nR0 = f1; + + if (6 * fG0 < 1) + nG0 = f1 + (f2 - f1) * 6 * fG0; + else if (2 * fG0 < 1) + nG0 = f2; + else if (3 * fG0 < 2) + nG0 = f1 + (f2 - f1) * (N2_3 - fG0) * 6; + else + nG0 = f1; + + if (6 * fB0 < 1) + nB0 = f1 + (f2 - f1) * 6 * fB0; + else if (2 * fB0 < 1) + nB0 = f2; + else if (3 * fB0 < 2) + nB0 = f1 + (f2 - f1) * (N2_3 - fB0) * 6; + else + nB0 = f1; + + if (6 * fR1 < 1) + nR1 = f1 + (f2 - f1) * 6 * fR1; + else if (2 * fR1 < 1) + nR1 = f2; + else if (3 * fR1 < 2) + nR1 = f1 + (f2 - f1) * (N2_3 - fR1) * 6; + else + nR1 = f1; + + if (6 * fG1 < 1) + nG1 = f1 + (f2 - f1) * 6 * fG1; + else if (2 * fG1 < 1) + nG1 = f2; + else if (3 * fG1 < 2) + nG1 = f1 + (f2 - f1) * (N2_3 - fG1) * 6; + else + nG1 = f1; + + if (6 * fB1 < 1) + nB1 = f1 + (f2 - f1) * 6 * fB1; + else if (2 * fB1 < 1) + nB1 = f2; + else if (3 * fB1 < 2) + nB1 = f1 + (f2 - f1) * (N2_3 - fB1) * 6; + else + nB1 = f1; + + /* at last convert them to a hex string */ + iR0 = nR0 * 255; + iG0 = nG0 * 255; + iB0 = nB0 * 255; + + iR1 = nR1 * 255; + iG1 = nG1 * 255; + iB1 = nB1 * 255; + + flake->Colors.Fore = malloc(sizeof(unsigned char) * 8); + flake->Colors.Bord = malloc(sizeof(unsigned char) * 8); + + sprintf(flake->Colors.Fore, "#%02X%02X%02X", iR0, iG0, iB0); + sprintf(flake->Colors.Bord, "#%02X%02X%02X", iR1, iG1, iB1); + + return 0; +} + +static void +FuzzyFlakesInit(Flake *flake) +{ + int i, j; + XWindowAttributes xgwa; + + XGetWindowAttributes(flake->dpy, flake->window, &xgwa); + flake->XGWA = xgwa; + flake->DB.b = flake->DB.ba = flake->DB.bb = 0; + flake->DB.dbuf = get_boolean_resource(flake->dpy, "doubleBuffer", "Boolean"); + +# ifdef HAVE_COCOA /* Don't second-guess Quartz's double-buffering */ + flake->DB.dbuf = False; +# endif + + if (flake->DB.dbuf) + { + flake->DB.ba = + XCreatePixmap(flake->dpy, flake->window, xgwa.width, xgwa.height, xgwa.depth); + flake->DB.bb = + XCreatePixmap(flake->dpy, flake->window, xgwa.width, xgwa.height, xgwa.depth); + flake->DB.b = flake->DB.ba; + } + else + { + flake->DB.b = flake->window; + } + + flake->Arms = get_integer_resource(flake->dpy, "arms", "Integer"); + flake->Thickness = get_integer_resource(flake->dpy, "thickness", "Integer"); + flake->BorderThickness = get_integer_resource(flake->dpy, "bthickness", "Integer"); + flake->Radius = get_integer_resource(flake->dpy, "radius", "Integer"); + + flake->Density = get_integer_resource(flake->dpy, "density", "Integer"); + flake->Layers = get_integer_resource(flake->dpy, "layers", "Integer"); + flake->FallingSpeed = get_integer_resource(flake->dpy, "fallingspeed", "Integer"); + flake->Delay = get_integer_resource(flake->dpy, "delay", "Integer"); + if (flake->RandomColors == True) + flake->RandomColors = get_boolean_resource(flake->dpy, "randomColors", "Boolean"); + + if (flake->Delay < 0) + flake->Delay = 0; + + if (!flake->Colors.Back) + { + flake->Colors.Back = get_string_resource(flake->dpy, "color", "Color"); + if (!FuzzyFlakesColorResource(flake, flake->Colors.Back)) + { + fprintf(stderr, " reverting to random\n"); + flake->RandomColors = True; + } + + if (flake->RandomColors) + { + if (flake->Colors.Back) + free(flake->Colors.Back); + flake->Colors.Back = malloc(sizeof(unsigned char) * 8); + sprintf(flake->Colors.Back, "#%X%X%X%X%X%X", random() % 16, + random() % 16, random() % 16, random() % 16, random() % 16, + random() % 16); + } + + /* + * Here we establish our colormap based on what is in + * flake->Colors.Back + */ + if (FuzzyFlakesColorHelper(flake)) + { + fprintf(stderr, " reverting to random\n"); + if (flake->Colors.Back) + free(flake->Colors.Back); + flake->Colors.Back = malloc(sizeof(unsigned char) * 8); + sprintf(flake->Colors.Back, "#%X%X%X%X%X%X", random() % 16, + random() % 16, random() % 16, random() % 16, random() % 16, + random() % 16); + FuzzyFlakesColorHelper(flake); + } + + flake->ForeColor = FuzzyFlakesColorResource(flake, flake->Colors.Fore); + flake->BackColor = FuzzyFlakesColorResource(flake, flake->Colors.Back); + flake->BordColor = FuzzyFlakesColorResource(flake, flake->Colors.Bord); + + flake->GCValues.foreground = flake->ForeColor; + flake->GCValues.background = flake->BackColor; + flake->RandomColors = False; + } + + flake->GCValues.line_width = flake->Thickness; + flake->GCValues.cap_style = CapProjecting; + flake->GCValues.join_style = JoinMiter; + flake->GCFlags |= (GCLineWidth | GCCapStyle | GCJoinStyle); + + flake->GCVar = + XCreateGC(flake->dpy, flake->window, flake->GCFlags, + &flake->GCValues); + + flake->Density = flake->XGWA.width / 200 * flake->Density; + flake->Flakes = malloc(sizeof(FlakeVariable **) * flake->Layers); + for (i = 1; i <= flake->Layers; i++) + { + flake->Flakes[i - 1] = malloc(sizeof(FlakeVariable *) * flake->Density); + for (j = 0; j < flake->Density; j++) + { + flake->Flakes[i - 1][j] = malloc(sizeof(FlakeVariable)); + flake->Flakes[i - 1][j]->XPos = random() % flake->XGWA.width; + flake->Flakes[i - 1][j]->YPos = random() % flake->XGWA.height; + flake->Flakes[i - 1][j]->Angle = random() % 360 * (M_PI / 180); + flake->Flakes[i - 1][j]->Ticks = random() % 360; + flake->Flakes[i - 1][j]->XOffset = random() % flake->XGWA.height; + } + } +} + +static void +FuzzyFlakesFreeFlake(Flake *flake) +{ + int i, j; + + for (i = 1; i <= flake->Layers; i++) + { + for (j = 0; j < flake->Density; j++) + { + free(flake->Flakes[i - 1][j]); + } + free(flake->Flakes[i - 1]); + } + + if (flake->DB.bb) XFreePixmap(flake->dpy, flake->DB.bb); + if (flake->DB.ba) XFreePixmap(flake->dpy, flake->DB.ba); +} + +static void +FuzzyFlakesMove(Flake *flake) +{ + int i, j; + + for (i = 1; i <= flake->Layers; i++) + { + for (j = 0; j < flake->Density; j++) + { + FlakeVariable *FlakeVar; + + FlakeVar = flake->Flakes[i - 1][j]; + FlakeVar->Ticks++; + FlakeVar->YPos = + FlakeVar->YPos + ((double)flake->FallingSpeed) / 10 / i; + FlakeVar->TrueX = + (sin + (FlakeVar->XOffset + + FlakeVar->Ticks * (M_PI / 180) * ((double)flake->FallingSpeed / + 10))) * 10 + FlakeVar->XPos; + FlakeVar->Angle = + FlakeVar->Angle + 0.005 * ((double)flake->FallingSpeed / 10); + if (FlakeVar->YPos - flake->Radius > flake->XGWA.height) + { + FlakeVar->Ticks = 0; + FlakeVar->YPos = 0 - flake->Radius; + } + } + } +} + +static void +FuzzyFlakesDrawFlake(Flake *flake, int XPos, int YPos, double AngleOffset, int Layer) +{ + int i; + double x, y, Angle, Radius; + + /* calculate the shrink factor debending on which layer we are drawing atm */ + Radius = (double)(flake->Radius - Layer * 5); + /* draw the flake one arm at a time */ + for (i = 1; i <= flake->Arms; i++) + { + int Diameter; + + Diameter = (flake->BorderThickness * 2 + flake->Thickness) / Layer; + /* compute the angle of this arm of the flake */ + Angle = ((2 * M_PI) / flake->Arms) * i + AngleOffset; + /* calculate the x and y dispositions for this arm */ + y = (int)(sin(Angle) * Radius); + x = (int)(cos(Angle) * Radius); + /* draw the base for the arm */ + flake->GCValues.line_width = Diameter; + XFreeGC(flake->dpy, flake->GCVar); + flake->GCVar = + XCreateGC(flake->dpy, flake->DB.b, flake->GCFlags, + &flake->GCValues); + XSetForeground(flake->dpy, flake->GCVar, flake->BordColor); + XDrawLine(flake->dpy, flake->DB.b, flake->GCVar, XPos, YPos, + XPos + x, YPos + y); + } + /* draw the flake one arm at a time */ + for (i = 1; i <= flake->Arms; i++) + { + /* compute the angle of this arm of the flake */ + Angle = ((2 * M_PI) / flake->Arms) * i + AngleOffset; + /* calculate the x and y dispositions for this arm */ + y = (int)(sin(Angle) * Radius); + x = (int)(cos(Angle) * Radius); + /* draw the inside of the arm */ + flake->GCValues.line_width = flake->Thickness / Layer; + XFreeGC(flake->dpy, flake->GCVar); + flake->GCVar = + XCreateGC(flake->dpy, flake->DB.b, flake->GCFlags, + &flake->GCValues); + XSetForeground(flake->dpy, flake->GCVar, flake->ForeColor); + XDrawLine(flake->dpy, flake->DB.b, flake->GCVar, XPos, YPos, + XPos + x, YPos + y); + } +} + +static void +FuzzyFlakes(Flake *flake) +{ + int i, j; + + FuzzyFlakesMove(flake); + XSetForeground(flake->dpy, flake->GCVar, flake->BackColor); + XFillRectangle(flake->dpy, flake->DB.b, flake->GCVar, 0, 0, + flake->XGWA.width, flake->XGWA.height); + for (i = flake->Layers; i >= 1; i--) + { + for (j = 0; j < flake->Density; j++) + { + FuzzyFlakesDrawFlake(flake, + flake->Flakes[i - 1][j]->TrueX, + flake->Flakes[i - 1][j]->YPos, + flake->Flakes[i - 1][j]->Angle, i); + } + } + +} + +static void * +fuzzyflakes_init (Display *dpy, Window window) +{ + Flake *flake = (Flake *) calloc (1, sizeof(*flake)); + flake->dpy = dpy; + flake->window = window; + + /* This is needed even if it is going to be set to false */ + flake->RandomColors = True; + + /* set up our colors amoung many other things */ + FuzzyFlakesInit(flake); + + return flake; +} + +static unsigned long +fuzzyflakes_draw (Display *dpy, Window window, void *closure) +{ + Flake *flake = (Flake *) closure; + + FuzzyFlakes(flake); + if (flake->DB.dbuf) + { + XCopyArea(flake->dpy, flake->DB.b, flake->window, + flake->GCVar, 0, 0, flake->XGWA.width, flake->XGWA.height, + 0, 0); + flake->DB.b = + (flake->DB.b == flake->DB.ba ? flake->DB.bb : flake->DB.ba); + } + + return flake->Delay; +} + +static void +fuzzyflakes_reshape (Display *dpy, Window window, void *closure, + unsigned int w, unsigned int h) +{ + Flake *flake = (Flake *) closure; + + if (flake->XGWA.width != w || flake->XGWA.height != h) + { + FuzzyFlakesFreeFlake(flake); + FuzzyFlakesInit(flake); + } +} + +static Bool +fuzzyflakes_event (Display *dpy, Window window, void *closure, XEvent *event) +{ + return False; +} + +static void +fuzzyflakes_free (Display *dpy, Window window, void *closure) +{ + Flake *flake = (Flake *) closure; + FuzzyFlakesFreeFlake(flake); + free(flake); +} + + +static const char *fuzzyflakes_defaults[] = { + "*color: #efbea5", + "*arms: 5", + "*thickness: 10", + "*bthickness: 3", + "*radius: 20", + "*layers: 3", + "*density: 5", + "*fallingspeed: 10", + "*delay: 10000", + "*doubleBuffer: True", + "*randomColors: False", + 0 +}; + +static XrmOptionDescRec fuzzyflakes_options[] = { + { "-color", ".color", XrmoptionSepArg, 0}, + { "-arms", ".arms", XrmoptionSepArg, 0}, + { "-thickness", ".thickness", XrmoptionSepArg, 0}, + { "-bthickness", ".bthickness", XrmoptionSepArg, 0}, + { "-radius", ".radius", XrmoptionSepArg, 0}, + { "-layers", ".layers", XrmoptionSepArg, 0}, + { "-density", ".density", XrmoptionSepArg, 0}, + { "-speed", ".fallingspeed", XrmoptionSepArg, 0}, + { "-delay", ".delay", XrmoptionSepArg, 0}, + { "-db", ".doubleBuffer", XrmoptionNoArg, "True"}, + { "-no-db", ".doubleBuffer", XrmoptionNoArg, "False"}, + { "-random-colors", ".randomColors", XrmoptionNoArg, "True"}, + { 0, 0, 0, 0} +}; + + +XSCREENSAVER_MODULE ("FuzzyFlakes", fuzzyflakes) diff --git a/hacks/fuzzyflakes.man b/hacks/fuzzyflakes.man new file mode 100644 index 00000000..a85cf0e8 --- /dev/null +++ b/hacks/fuzzyflakes.man @@ -0,0 +1,112 @@ +.TH XScreenSaver 1 "12-May-04" "X Version 11" +.SH NAME +fuzzyflakes - falling snowflakes/flower shapes +.SH SYNOPSIS +.B fuzzyflakes +[\-display \fIhost:display.screen\fP] [\-foreground \fIcolor\fP] +[\-background \fIcolor\fP] [\-window] [\-root] [\-mono] [\-install] +[\-visual \fIvisual\fP] +[\-delay \fIusecs\fP] +[\-speed \fIint\fP] +[\-arms \fIint\fP] +[\-thickness \fIint\fP] +[\-bthickness \fIint\fP] +[\-radius \fIint\fP] +[\-layers \fIint\fP] +[\-density \fIint\fP] +[\-no-db] +(\-color \fIstring\fP) +(\-random-colors) +[\-fps] +.SH DESCRIPTION +The +.I fuzzyflakes +program draws falling pastel colored snowflake/flower shapes. +Inspired by the credits of the anime "Azumanga Daioh". +.SH OPTIONS +.I fuzzyflakes +accepts the following options: +.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 \-mono +If on a color display, pretend we're on a monochrome display. +.TP 8 +.B \-install +Install a private colormap for the window. +.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 \-delay \fIusecs\fP +The delay between steps of the animation, in microseconds. Default: 250000. +.TP 8 +.B \-speed \fIint\fP +How fast, 1-50. Default 10. +.TP 8 +.B \-arms \fIint\fP +How many arms on the flakes; default 5. +.TP 8 +.B \-thickness \fIint\fP +How thick to make the lines; default 10 pixels. +.TP 8 +.B \-bthickness \fIint\fP +How thick to make the borders; default 3 pixels. +.TP 8 +.B \-radius \fIint\fP +Radius of the objects; default 20 pixels. +.TP 8 +.B \-layers \fIint\fP +How many layers of objects; default 3. +.TP 8 +.B \-density \fIint\fP +Default 5. +.TP 8 +.B \-no-db +Disable double-buffering. +.TP 8 +.B \-color \fIstring\fP +The base color for the color scheme. Typed as a hexadecimal triplet +with or with out the leading #. ie. fa4563 & #43cd12 are both acceptable. +If the saturation of you color is too low (<0.03) the random color +generator will kick in. +The default color is #efbea5 +.TP 8 +.B \-random-colors +This enables the random color generation. It is disabled by default. +It overrides anything from -color +.TP 8 +.B \-fps +Display the current frame rate and CPU load. +.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 2004 Barry Dmytro. 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 +Barry Dmytro +.SH CREDITS +The color generation algorithm was borrowed from a friend +from #vegans@irc.blitzed.org. Her site is http://beautifulfreak.net/. +To see her original code in action visit her site. diff --git a/hacks/galaxy.c b/hacks/galaxy.c new file mode 100644 index 00000000..43a0b5bf --- /dev/null +++ b/hacks/galaxy.c @@ -0,0 +1,468 @@ +/* -*- Mode: C; tab-width: 4 -*- */ +/* galaxy --- spinning galaxies */ +/* #include*/ +#if 0 +static const char sccsid[] = "@(#)galaxy.c 4.04 97/07/28 xlockmore"; +#endif + +/* Originally done by Uli Siegmund on Amiga + * for EGS in Cluster + * Port from Cluster/EGS to C/Intuition by Harald Backert + * Port to X11 and incorporation into xlockmore by Hubert Feyrer + * + * + * Permission to use, copy, modify, and distribute this software and its + * documentation for any purpose and without fee is hereby granted, + * provided that the above copyright notice appear in all copies and that + * both that copyright notice and this permission notice appear in + * supporting documentation. + * + * This file is provided AS IS with no warranties of any kind. The author + * shall have no liability with respect to the infringement of copyrights, + * trade secrets or any patents by this file or any part thereof. In no + * event will the author be liable for any lost revenue or profits or + * other special, indirect and consequential damages. + * + * Revision History: + * 26-Aug-00: robert.nagtegaal@phil.uu.nl and roland@tschai.demon.nl: + * various improvements + * 10-May-97: jwz@jwz.org: turned into a standalone program. + * 18-Apr-97: Memory leak fixed by Tom Schmidt + * 07-Apr-97: Modified by Dave Mitchell + * 23-Oct-94: Modified by David Bagley + * random star sizes + * colors change depending on velocity + * 10-Oct-94: Add colors by Hubert Feyer + * 30-Sep-94: Initial port by Hubert Feyer + * 09-Mar-94: VMS can generate a random number 0.0 which results in a + * division by zero, corrected by Jouk Jansen + * + */ + +#ifdef STANDALONE +# define DEFAULTS "*delay: 20000 \n" \ + "*count: -5 \n" \ + "*cycles: 250 \n" \ + "*ncolors: 64 \n" \ + "*fpsSolid: true \n" \ + +# define UNIFORM_COLORS +# define galaxy_handle_event 0 +# include "xlockmore.h" /* from the xscreensaver distribution */ +#else /* !STANDALONE */ +# include "xlock.h" /* from the xlockmore distribution */ +#endif /* !STANDALONE */ + +static Bool tracks; +static Bool spin; +static Bool dbufp; + +#define DEF_TRACKS "True" +#define DEF_SPIN "True" +#define DEF_DBUF "True" + +static XrmOptionDescRec opts[] = +{ + {"-tracks", ".galaxy.tracks", XrmoptionNoArg, "on"}, + {"+tracks", ".galaxy.tracks", XrmoptionNoArg, "off"}, + {"-spin", ".galaxy.spin", XrmoptionNoArg, "on"}, + {"+spin", ".galaxy.spin", XrmoptionNoArg, "off"}, + {"-dbuf", ".galaxy.dbuf", XrmoptionNoArg, "on"}, + {"+dbuf", ".galaxy.dbuf", XrmoptionNoArg, "off"}, +}; + +static argtype vars[] = +{ + {&tracks, "tracks", "Tracks", DEF_TRACKS, t_Bool}, + {&spin, "spin", "Spin", DEF_SPIN, t_Bool}, + {&dbufp, "dbuf", "Dbuf", DEF_DBUF, t_Bool}, +}; + +static OptionStruct desc[] = +{ + {"-/+tracks", "turn on/off star tracks"}, + {"-/+spin", "do/don't spin viewpoint"}, + {"-/+dbuf", "turn on/off double buffering."}, +}; + +ENTRYPOINT ModeSpecOpt galaxy_opts = +{sizeof opts / sizeof opts[0], opts, + sizeof vars / sizeof vars[0], vars, desc}; + + +#define FLOATRAND ((double) LRAND() / ((double) MAXRAND)) + +#if 0 +#define WRAP 1 /* Warp around edges */ +#define BOUNCE 1 /* Bounce from borders */ +#endif + +#define MINSIZE 1 +#define MINGALAXIES 2 +#define MAX_STARS 3000 +#define MAX_IDELTAT 50 +/* These come originally from the Cluster-version */ +#define DEFAULT_GALAXIES 3 +#define DEFAULT_STARS 1000 +#define DEFAULT_HITITERATIONS 7500 +#define DEFAULT_IDELTAT 200 /* 0.02 */ +#define EPSILON 0.00000001 + +#define sqrt_EPSILON 0.0001 + +#define DELTAT (MAX_IDELTAT * 0.0001) + +#define GALAXYRANGESIZE 0.1 +#define GALAXYMINSIZE 0.15 +#define QCONS 0.001 + + +#define COLORBASE 16 +/* colors per galaxy */ +/* #define COLORSTEP (NUMCOLORS/COLORBASE) */ +# define COLORSTEP (MI_NCOLORS(mi)/COLORBASE) + + +typedef struct { + double pos[3], vel[3]; +} Star; + + +typedef struct { + int mass; + int nstars; + Star *stars; + XPoint *oldpoints; + XPoint *newpoints; + double pos[3], vel[3]; + int galcol; +} Galaxy; + +typedef struct { + double mat[3][3]; /* Movement of stars(?) */ + double scale; /* Scale */ + int midx; /* Middle of screen, x */ + int midy; /* Middle of screen, y */ + double size; /* */ + double diff[3]; /* */ + Galaxy *galaxies; /* the Whole Universe */ + int ngalaxies; /* # galaxies */ + int f_hititerations; /* # iterations before restart */ + int step; /* */ + double rot_y; /* rotation of eye around center of universe, around +y-axis*/ + double rot_x; /* rotation of eye around center of universe, around +x-axis */ +} unistruct; + +static unistruct *universes = NULL; + +static void +free_galaxies(unistruct * gp) +{ + if (gp->galaxies != NULL) { + int i; + + for (i = 0; i < gp->ngalaxies; i++) { + Galaxy *gt = &gp->galaxies[i]; + + if (gt->stars != NULL) + (void) free((void *) gt->stars); + if (gt->oldpoints != NULL) + (void) free((void *) gt->oldpoints); + if (gt->newpoints != NULL) + (void) free((void *) gt->newpoints); + } + (void) free((void *) gp->galaxies); + gp->galaxies = NULL; + } +} + +static void +startover(ModeInfo * mi) +{ + unistruct *gp = &universes[MI_SCREEN(mi)]; + int i, j; /* more tmp */ + double w1, w2; /* more tmp */ + double d, v, w, h; /* yet more tmp */ + + gp->step = 0; + gp->rot_y = 0; + gp->rot_x = 0; + + if (MI_BATCHCOUNT(mi) < -MINGALAXIES) + free_galaxies(gp); + gp->ngalaxies = MI_BATCHCOUNT(mi); + if (gp->ngalaxies < -MINGALAXIES) + gp->ngalaxies = NRAND(-gp->ngalaxies - MINGALAXIES + 1) + MINGALAXIES; + + else if (gp->ngalaxies < MINGALAXIES) + gp->ngalaxies = MINGALAXIES; + if (gp->galaxies == NULL) + gp->galaxies = (Galaxy *) calloc(gp->ngalaxies, sizeof (Galaxy)); + + for (i = 0; i < gp->ngalaxies; ++i) { + Galaxy *gt = &gp->galaxies[i]; + double sinw1, sinw2, cosw1, cosw2; + + gt->galcol = NRAND(COLORBASE - 2); + if (gt->galcol > 1) + gt->galcol += 2; /* Mult 8; 16..31 no green stars */ + /* Galaxies still may have some green stars but are not all green. */ + + if (gt->stars != NULL) { + (void) free((void *) gt->stars); + gt->stars = NULL; + } + gt->nstars = (NRAND(MAX_STARS / 2)) + MAX_STARS / 2; + gt->stars = (Star *) malloc(gt->nstars * sizeof (Star)); + gt->oldpoints = (XPoint *) malloc(gt->nstars * sizeof (XPoint)); + gt->newpoints = (XPoint *) malloc(gt->nstars * sizeof (XPoint)); + + w1 = 2.0 * M_PI * FLOATRAND; + w2 = 2.0 * M_PI * FLOATRAND; + sinw1 = SINF(w1); + sinw2 = SINF(w2); + cosw1 = COSF(w1); + cosw2 = COSF(w2); + + gp->mat[0][0] = cosw2; + gp->mat[0][1] = -sinw1 * sinw2; + gp->mat[0][2] = cosw1 * sinw2; + gp->mat[1][0] = 0.0; + gp->mat[1][1] = cosw1; + gp->mat[1][2] = sinw1; + gp->mat[2][0] = -sinw2; + gp->mat[2][1] = -sinw1 * cosw2; + gp->mat[2][2] = cosw1 * cosw2; + + gt->vel[0] = FLOATRAND * 2.0 - 1.0; + gt->vel[1] = FLOATRAND * 2.0 - 1.0; + gt->vel[2] = FLOATRAND * 2.0 - 1.0; + gt->pos[0] = -gt->vel[0] * DELTAT * gp->f_hititerations + FLOATRAND - +0.5; + gt->pos[1] = -gt->vel[1] * DELTAT * gp->f_hititerations + FLOATRAND - +0.5; + gt->pos[2] = -gt->vel[2] * DELTAT * gp->f_hititerations + FLOATRAND - +0.5; + + gt->mass = (int) (FLOATRAND * 1000.0) + 1; + + gp->size = GALAXYRANGESIZE * FLOATRAND + GALAXYMINSIZE; + + for (j = 0; j < gt->nstars; ++j) { + Star *st = >->stars[j]; + XPoint *oldp = >->oldpoints[j]; + XPoint *newp = >->newpoints[j]; + + double sinw, cosw; + + w = 2.0 * M_PI * FLOATRAND; + sinw = SINF(w); + cosw = COSF(w); + d = FLOATRAND * gp->size; + h = FLOATRAND * exp(-2.0 * (d / gp->size)) / 5.0 * gp->size; + if (FLOATRAND < 0.5) + h = -h; + st->pos[0] = gp->mat[0][0] * d * cosw + gp->mat[1][0] * d * sinw + +gp->mat[2][0] * h + gt->pos[0]; + st->pos[1] = gp->mat[0][1] * d * cosw + gp->mat[1][1] * d * sinw + +gp->mat[2][1] * h + gt->pos[1]; + st->pos[2] = gp->mat[0][2] * d * cosw + gp->mat[1][2] * d * sinw + +gp->mat[2][2] * h + gt->pos[2]; + + v = sqrt(gt->mass * QCONS / sqrt(d * d + h * h)); + st->vel[0] = -gp->mat[0][0] * v * sinw + gp->mat[1][0] * v * cosw + +gt->vel[0]; + st->vel[1] = -gp->mat[0][1] * v * sinw + gp->mat[1][1] * v * cosw + +gt->vel[1]; + st->vel[2] = -gp->mat[0][2] * v * sinw + gp->mat[1][2] * v * cosw + +gt->vel[2]; + + st->vel[0] *= DELTAT; + st->vel[1] *= DELTAT; + st->vel[2] *= DELTAT; + + oldp->x = 0; + oldp->y = 0; + newp->x = 0; + newp->y = 0; + } + + } + + XClearWindow(MI_DISPLAY(mi), MI_WINDOW(mi)); + +#if 0 + (void) printf("ngalaxies=%d, f_hititerations=%d\n", gp->ngalaxies, +gp->f_hititerations); + (void) printf("f_deltat=%g\n", DELTAT); + (void) printf("Screen: "); +#endif /*0 */ +} + +ENTRYPOINT void +init_galaxy(ModeInfo * mi) +{ + unistruct *gp; + + if (universes == NULL) { + if ((universes = (unistruct *) calloc(MI_NUM_SCREENS(mi), + sizeof (unistruct))) == NULL) + return; + } + gp = &universes[MI_SCREEN(mi)]; + +# ifdef HAVE_COCOA /* Don't second-guess Quartz's double-buffering */ + dbufp = False; +# endif + + gp->f_hititerations = MI_CYCLES(mi); + + gp->scale = (double) (MI_WIN_WIDTH(mi) + MI_WIN_HEIGHT(mi)) / 8.0; + gp->midx = MI_WIN_WIDTH(mi) / 2; + gp->midy = MI_WIN_HEIGHT(mi) / 2; + startover(mi); +} + +ENTRYPOINT void +draw_galaxy(ModeInfo * mi) +{ + Display *display = MI_DISPLAY(mi); + Window window = MI_WINDOW(mi); + GC gc = MI_GC(mi); + unistruct *gp = &universes[MI_SCREEN(mi)]; + double d, eps, cox, six, cor, sir; /* tmp */ + int i, j, k; /* more tmp */ + XPoint *dummy = NULL; + + if (! dbufp) + XClearWindow(MI_DISPLAY(mi), MI_WINDOW(mi)); + + if(spin){ + gp->rot_y += 0.01; + gp->rot_x += 0.004; + } + + cox = COSF(gp->rot_y); + six = SINF(gp->rot_y); + cor = COSF(gp->rot_x); + sir = SINF(gp->rot_x); + + eps = 1/(EPSILON * sqrt_EPSILON * DELTAT * DELTAT * QCONS); + + for (i = 0; i < gp->ngalaxies; ++i) { + Galaxy *gt = &gp->galaxies[i]; + + for (j = 0; j < gp->galaxies[i].nstars; ++j) { + Star *st = >->stars[j]; + XPoint *newp = >->newpoints[j]; + double v0 = st->vel[0]; + double v1 = st->vel[1]; + double v2 = st->vel[2]; + + for (k = 0; k < gp->ngalaxies; ++k) { + Galaxy *gtk = &gp->galaxies[k]; + double d0 = gtk->pos[0] - st->pos[0]; + double d1 = gtk->pos[1] - st->pos[1]; + double d2 = gtk->pos[2] - st->pos[2]; + + d = d0 * d0 + d1 * d1 + d2 * d2; + if (d > EPSILON) + d = gtk->mass / (d * sqrt(d)) * DELTAT * DELTAT * QCONS; + else + d = gtk->mass / (eps * sqrt(eps)); + v0 += d0 * d; + v1 += d1 * d; + v2 += d2 * d; + } + + st->vel[0] = v0; + st->vel[1] = v1; + st->vel[2] = v2; + + st->pos[0] += v0; + st->pos[1] += v1; + st->pos[2] += v2; + + newp->x = (short) (((cox * st->pos[0]) - (six * st->pos[2])) * + gp->scale) + gp->midx; + newp->y = (short) (((cor * st->pos[1]) - (sir * ((six * st->pos[0]) + + (cox * st->pos[2])))) + * gp->scale) + gp->midy; + + } + + for (k = i + 1; k < gp->ngalaxies; ++k) { + Galaxy *gtk = &gp->galaxies[k]; + double d0 = gtk->pos[0] - gt->pos[0]; + double d1 = gtk->pos[1] - gt->pos[1]; + double d2 = gtk->pos[2] - gt->pos[2]; + + d = d0 * d0 + d1 * d1 + d2 * d2; + if (d > EPSILON) + d = 1 / (d * sqrt(d)) * DELTAT * QCONS; + else + d = 1 / (EPSILON * sqrt_EPSILON) * DELTAT * QCONS; + + d0 *= d; + d1 *= d; + d2 *= d; + gt->vel[0] += d0 * gtk->mass; + gt->vel[1] += d1 * gtk->mass; + gt->vel[2] += d2 * gtk->mass; + gtk->vel[0] -= d0 * gt->mass; + gtk->vel[1] -= d1 * gt->mass; + gtk->vel[2] -= d2 * gt->mass; + } + + gt->pos[0] += gt->vel[0] * DELTAT; + gt->pos[1] += gt->vel[1] * DELTAT; + gt->pos[2] += gt->vel[2] * DELTAT; + + if (dbufp) { + XSetForeground(display, gc, MI_WIN_BLACK_PIXEL(mi)); + XDrawPoints(display, window, gc, gt->oldpoints, gt->nstars, + CoordModeOrigin); + } + XSetForeground(display, gc, MI_PIXEL(mi, COLORSTEP * gt->galcol)); + XDrawPoints(display, window, gc, gt->newpoints, gt->nstars, + CoordModeOrigin); + + dummy = gt->oldpoints; + gt->oldpoints = gt->newpoints; + gt->newpoints = dummy; + } + + gp->step++; + if (gp->step > gp->f_hititerations * 4) + startover(mi); +} + +ENTRYPOINT void +reshape_galaxy(ModeInfo * mi, int width, int height) +{ + XClearWindow (MI_DISPLAY (mi), MI_WINDOW(mi)); + init_galaxy (mi); +} + +ENTRYPOINT void +release_galaxy(ModeInfo * mi) +{ + if (universes != NULL) { + int screen; + + for (screen = 0; screen < MI_NUM_SCREENS(mi); screen++) + free_galaxies(&universes[screen]); + (void) free((void *) universes); + universes = NULL; + } +} + +ENTRYPOINT void +refresh_galaxy(ModeInfo * mi) +{ + /* Do nothing, it will refresh by itself */ +} + +XSCREENSAVER_MODULE ("Galaxy", galaxy) diff --git a/hacks/galaxy.man b/hacks/galaxy.man new file mode 100644 index 00000000..1a2a79da --- /dev/null +++ b/hacks/galaxy.man @@ -0,0 +1,87 @@ +.TH XScreenSaver 1 "10-May-97" "X Version 11" +.SH NAME +galaxy - draws spinning galaxies +.SH SYNOPSIS +.B galaxy +[\-display \fIhost:display.screen\fP] [\-foreground \fIcolor\fP] [\-background \fIcolor\fP] [\-window] [\-root] [\-mono] [\-install] [\-visual \fIvisual\fP] [\-ncolors \fIinteger\fP] [\-delay \fImicroseconds\fP] [\-cycles \fIinteger\fP] [\-count \fIinteger\fP] [\-size \fIinteger\fP] [\-tracks] [\-no\-tracks] [\-spin] [\-no\-spin] + +[\-fps] +.SH DESCRIPTION +The \fIgalaxy\fP program draws spinning galaxies. +.SH OPTIONS +.I galaxy +accepts the following options: +.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 \-mono +If on a color display, pretend we're on a monochrome display. +.TP 8 +.B \-install +Install a private colormap for the window. +.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 \-ncolors \fIinteger\fP +How many colors should be used (if possible). Default 64. +The colors used cycle through the hue, making N stops around +the color wheel. +.TP 8 +.B \-cycles \fIinteger\fP +.TP 8 +.B \-count \fIinteger\fP +.TP 8 +.B \-size \fIinteger\fP +.TP 8 +.B \-tracks +.TP 8 +.B \-no\-tracks +.TP 8 +.B \-spin +.TP 8 +.B \-no\-spin +.TP 8 +.B \-fps +Display the current frame rate and CPU load. +.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), +.BR xlock (1) +.SH COPYRIGHT +Copyright \(co 1994 by Hubert Feyrer. + +Permission to use, copy, modify, and distribute this software and its +documentation for any purpose and without fee is hereby granted, +provided that the above copyright notice appear in all copies and that +both that copyright notice and this permission notice appear in +supporting documentation. +.SH AUTHOR +Original Amiga version by Uli Siegmund + for EGS in Cluster. + +Ported from Cluster/EGS to C/Intuition by Harald Backert. + +Ported to X11 and xlockmore by +Hubert Feyrer , 30-Sep-94. + +Modified by David Bagley , 23-Oct-94. + +Modified by Dave Mitchell , 7-Apr-97. + +Ability to run standalone or with \fIxscreensaver\fP added by +Jamie Zawinski , 10-May-97. diff --git a/hacks/glx/Makefile.in b/hacks/glx/Makefile.in new file mode 100644 index 00000000..9f256641 --- /dev/null +++ b/hacks/glx/Makefile.in @@ -0,0 +1,2893 @@ +# hacks/glx/Makefile.in --- xscreensaver, Copyright (c) 1999-2010 +# by Jamie Zawinski. +# the `../../configure' script generates `hacks/glx/Makefile' from this file. + +@SET_MAKE@ +.SUFFIXES: +.SUFFIXES: .c .o + +srcdir = @srcdir@ +VPATH = @srcdir@ +top_srcdir = @top_srcdir@ +top_builddir = .. + +install_prefix = +prefix = @prefix@ +exec_prefix = @exec_prefix@ +bindir = @bindir@ +datarootdir = @datarootdir@ +datadir = @datadir@ +mandir = @mandir@ +libexecdir = @libexecdir@ +mansuffix = 6 +manNdir = $(mandir)/man$(mansuffix) + +HACKDIR = @HACKDIR@ +HACK_CONF_DIR = @HACK_CONF_DIR@ + +CC = @CC@ +CFLAGS = @CFLAGS@ +LDFLAGS = @LDFLAGS@ +DEFS = -DSTANDALONE -DUSE_GL @DEFS@ +LIBS = @LIBS@ + +DEPEND = @DEPEND@ +DEPEND_FLAGS = @DEPEND_FLAGS@ +DEPEND_DEFINES = @DEPEND_DEFINES@ + +SHELL = /bin/sh +INSTALL = @INSTALL@ +SUID_FLAGS = -o root -m 4755 +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SETUID = @INSTALL_SETUID@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_DIRS = @INSTALL_DIRS@ + +X_CFLAGS = @X_CFLAGS@ +X_LIBS = @X_LIBS@ +X_PRE_LIBS = @X_PRE_LIBS@ +X_EXTRA_LIBS = @X_EXTRA_LIBS@ +XMU_LIBS = @XMU_LIBS@ + +# Note: see comment in ../../driver/Makefile.in for explanation of X_LIBS, etc. +# +HACK_PRE = $(LIBS) $(X_LIBS) +HACK_POST = $(X_PRE_LIBS) -lXt -lX11 $(XMU_LIBS) -lXext $(X_EXTRA_LIBS) -lm +HACK_POST2 = @GL_LIBS@ @HACK_LIBS@ $(HACK_POST) +HACK_LIBS = $(HACK_PRE) $(HACK_POST2) +XPM_LIBS = $(HACK_PRE) @XPM_LIBS@ $(HACK_POST2) +GLE_LIBS = $(HACK_PRE) @GLE_LIBS@ @XPM_LIBS@ $(HACK_POST2) +TEXT_LIBS = @PTY_LIBS@ +MINIXPM = $(UTILS_BIN)/minixpm.o + +HACK_SRC = $(srcdir)/.. +HACK_BIN = .. +UTILS_SRC = $(HACK_SRC)/../utils +UTILS_BIN = $(HACK_BIN)/../utils + +INCLUDES_1 = -I. -I$(srcdir) -I$(UTILS_SRC) -I$(HACK_SRC) -I../.. +INCLUDES = $(INCLUDES_1) @INCLUDES@ + +UTIL_SRCS = $(UTILS_SRC)/colors.c $(UTILS_SRC)/hsv.c \ + $(UTILS_SRC)/resources.c $(UTILS_SRC)/usleep.c \ + $(UTILS_SRC)/visual.c $(UTILS_SRC)/visual-gl.c \ + $(UTILS_SRC)/yarandom.c $(UTILS_SRC)/xshm.c \ + $(UTILS_SRC)/textclient.c +UTIL_OBJS = $(UTILS_SRC)/colors.o $(UTILS_SRC)/hsv.o \ + $(UTILS_SRC)/resources.o $(UTILS_SRC)/usleep.o \ + $(UTILS_SRC)/visual.o $(UTILS_SRC)/visual-gl.o \ + $(UTILS_SRC)/yarandom.o $(UTILS_SRC)/xshm.o \ + $(UTILS_SRC)/textclient.o + +SRCS = xscreensaver-gl-helper.c normals.c glxfonts.c fps-gl.c \ + atlantis.c b_draw.c b_lockglue.c b_sphere.c bubble3d.c \ + buildlwo.c cage.c dolphin.c gears.c lament.c moebius.c \ + morph3d.c pipeobjs.c pipes.c rubik.c s1_1.c s1_2.c s1_3.c \ + s1_4.c s1_5.c s1_6.c s1_b.c shark.c sproingies.c \ + sproingiewrap.c stairs.c superquadrics.c swim.c whale.c \ + xlock-gl-utils.c xpm-ximage.c glplanet.c pulsar.c \ + extrusion.c extrusion-helix2.c extrusion-helix3.c \ + extrusion-helix4.c extrusion-joinoffset.c extrusion-screw.c \ + extrusion-taper.c extrusion-twistoid.c sierpinski3d.c \ + gflux.c stonerview.c stonerview-move.c stonerview-osc.c \ + stonerview-view.c starwars.c glut_stroke.c glut_swidth.c \ + gltext.c molecule.c dangerball.c sphere.c tube.c circuit.c \ + menger.c engine.c flipscreen3d.c font-ximage.c dnalogo.c \ + grab-ximage.c glsnake.c boxed.c glforestfire.c sballs.c \ + cubenetic.c spheremonics.c marching.c lavalite.c rotator.c \ + trackball.c gltrackball.c queens.c endgame.c chessmodels.c \ + glblur.c gllist.c flurry.c flurry-smoke.c flurry-spark.c \ + flurry-star.c flurry-texture.c atunnel.c tunnel_draw.c \ + flyingtoasters.c toaster.c toaster_base.c toaster_handle.c \ + toaster_handle2.c toaster_jet.c toaster_knob.c \ + toaster_slots.c toaster_wing.c toast.c toast2.c \ + bouncingcow.c cow_face.c cow_hide.c cow_hoofs.c cow_horns.c \ + cow_tail.c cow_udder.c glslideshow.c jigglypuff.c klein.c \ + hypertorus.c glmatrix.c cubestorm.c glknots.c blocktube.c \ + flipflop.c antspotlight.c polytopes.c gleidescope.c \ + mirrorblob.c blinkbox.c noof.c polyhedra.c polyhedra-gl.c \ + antinspect.c providence.c pinion.c involute.c boing.c \ + texfont.c carousel.c fliptext.c antmaze.c tangram.c \ + tangram_shapes.c crackberg.c glhanoi.c cube21.c \ + timetunnel.c juggler3d.c topblock.c glschool.c \ + glschool_gl.c glschool_alg.c glcells.c voronoi.c \ + moebiusgears.c lockward.c cubicgrid.c hypnowheel.c \ + skytentacles.c teapot.c sonar.c sonar-sim.c sonar-icmp.c \ + jigsaw.c photopile.c dropshadow.c rubikblocks.c surfaces.c \ + hilbert.c companion.c companion_quad.c companion_disc.c \ + companion_heart.c tronbit.c tronbit_idle1.c tronbit_idle2.c \ + tronbit_no.c tronbit_yes.c jwzgles.c + +OBJS = xscreensaver-gl-helper.o normals.o glxfonts.o fps-gl.o \ + atlantis.o b_draw.o b_lockglue.o b_sphere.o bubble3d.o \ + buildlwo.o cage.o dolphin.o gears.o lament.o moebius.o \ + morph3d.o pipeobjs.o pipes.o rubik.o s1_1.o s1_2.o s1_3.o \ + s1_4.o s1_5.o s1_6.o s1_b.o shark.o sproingies.o \ + sproingiewrap.o stairs.o superquadrics.o swim.o whale.o \ + xlock-gl-utils.o xpm-ximage.o glplanet.o pulsar.o \ + extrusion.o extrusion-helix2.o extrusion-helix3.o \ + extrusion-helix4.o extrusion-joinoffset.o extrusion-screw.o \ + extrusion-taper.o extrusion-twistoid.o sierpinski3d.o \ + gflux.o stonerview.o stonerview-move.o stonerview-osc.o \ + stonerview-view.o starwars.o glut_stroke.o glut_swidth.o \ + gltext.o molecule.o dangerball.o sphere.o tube.o circuit.o \ + menger.o engine.o flipscreen3d.o font-ximage.o dnalogo.o \ + grab-ximage.o glsnake.o boxed.o glforestfire.o sballs.o \ + cubenetic.o spheremonics.o marching.o lavalite.o rotator.o \ + trackball.o gltrackball.o queens.o endgame.o chessmodels.o \ + glblur.o gllist.o flurry.o flurry-smoke.o flurry-spark.o \ + flurry-star.o flurry-texture.o atunnel.o tunnel_draw.o \ + flyingtoasters.o toaster.o toaster_base.o toaster_handle.o \ + toaster_handle2.o toaster_jet.o toaster_knob.o \ + toaster_slots.o toaster_wing.o toast.o toast2.o \ + bouncingcow.o cow_face.o cow_hide.o cow_hoofs.o cow_horns.o \ + cow_tail.o cow_udder.o glslideshow.o jigglypuff.o klein.o \ + hypertorus.o glmatrix.o cubestorm.o glknots.o blocktube.o \ + flipflop.o antspotlight.o polytopes.o gleidescope.o \ + mirrorblob.o blinkbox.o noof.o polyhedra.o polyhedra-gl.o \ + antinspect.o providence.o pinion.o involute.o boing.o \ + texfont.o carousel.o fliptext.o antmaze.o tangram.o \ + tangram_shapes.o crackberg.o glhanoi.o cube21.o \ + timetunnel.o juggler3d.o topblock.o glschool.o \ + glschool_gl.o glschool_alg.o glcells.o voronoi.o \ + moebiusgears.o lockward.o cubicgrid.o hypnowheel.o \ + skytentacles.o teapot.o sonar.o sonar-sim.o sonar-icmp.o \ + jigsaw.o photopile.o dropshadow.o rubikblocks.o surfaces.o \ + hilbert.o companion.o companion_quad.o companion_disc.o \ + companion_heart.o tronbit.o tronbit_idle1.o tronbit_idle2.o \ + tronbit_no.o tronbit_yes.o jwzgles.o + +GL_EXES = cage gears moebius pipes sproingies stairs superquadrics \ + morph3d rubik atlantis lament bubble3d glplanet pulsar \ + sierpinski3d gflux stonerview starwars gltext molecule \ + dangerball circuit menger engine flipscreen3d glsnake boxed \ + sballs cubenetic spheremonics lavalite queens \ + endgame glblur flurry atunnel flyingtoasters bouncingcow \ + glslideshow jigglypuff klein hypertorus glmatrix cubestorm \ + glknots blocktube flipflop antspotlight polytopes \ + gleidescope mirrorblob blinkbox noof polyhedra \ + antinspect providence pinion boing carousel fliptext \ + antmaze tangram crackberg glhanoi cube21 timetunnel \ + juggler3d topblock glschool glcells voronoi moebiusgears \ + lockward cubicgrid hypnowheel skytentacles jigsaw photopile \ + rubikblocks surfaces hilbert companioncube tronbit +GLE_EXES = extrusion +SUID_EXES = sonar +GL_UTIL_EXES = xscreensaver-gl-helper +JWZGLES_OBJS = @JWZGLES_OBJS@ +HACK_EXES_1 = @GL_EXES@ @GLE_EXES@ +HACK_EXES = $(HACK_EXES_1) @SUID_EXES@ +XSHM_OBJS = $(UTILS_BIN)/xshm.o +GRAB_OBJS = $(UTILS_BIN)/grabclient.o grab-ximage.o $(XSHM_OBJS) +EXES = @GL_UTIL_EXES@ $(HACK_EXES) + +RETIRED_EXES = @RETIRED_GL_EXES@ +RETIRED_GL_EXES = glforestfire + +FPS_OBJS = @GLFPS_OBJS@ $(HACK_BIN)/fps.o +FONT_OBJS = @GLFONT_OBJS@ + +HACK_OBJS = $(JWZGLES_OBJS) $(HACK_BIN)/screenhack.o \ + xlockmore-gl.o xlock-gl-utils.o ${FPS_OBJS} \ + $(UTILS_BIN)/resources.o $(UTILS_BIN)/visual.o \ + $(UTILS_BIN)/visual-gl.o $(UTILS_BIN)/usleep.o \ + $(UTILS_BIN)/yarandom.o $(UTILS_BIN)/hsv.o \ + $(UTILS_BIN)/colors.o + +HDRS = atlantis.h bubble3d.h buildlwo.h e_textures.h xpm-ximage.h \ + grab-ximage.h font-ximage.h tube.h sphere.h boxed.h \ + stonerview.h stonerview-move.h stonerview-osc.h \ + glutstroke.h glut_roman.h marching.h rotator.h trackball.h \ + gltrackball.h chessmodels.h chessgames.h gllist.h flurry.h \ + tunnel_draw.h ants.h polyhedra.h normals.h glxfonts.h \ + texfont.h tangram_shapes.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 \ + jwzgles.h jwzglesI.h teapot2.h dnapizza.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 \ + glplanet.man glsnake.man gltext.man lament.man lavalite.man \ + menger.man moebius.man molecule.man morph3d.man pipes.man \ + pulsar.man queens.man rubik.man sballs.man sierpinski3d.man \ + spheremonics.man sproingies.man stairs.man starwars.man \ + stonerview.man superquadrics.man xscreensaver-gl-helper.man \ + endgame.man flurry.man glblur.man atunnel.man \ + flyingtoasters.man bouncingcow.man glslideshow.man \ + jigglypuff.man klein.man hypertorus.man glmatrix.man \ + cubestorm.man glknots.man blocktube.man flipflop.man \ + antspotlight.man polytopes.man gleidescope.man \ + mirrorblob.man blinkbox.man noof.man polyhedra.man \ + antinspect.man providence.man pinion.man boing.man \ + carousel.man fliptext.man antmaze.man tangram.man \ + crackberg.man glhanoi.man cube21.man timetunnel.man \ + juggler3d.man topblock.man glschool.man glcells.man \ + voronoi.man moebiusgears.man lockward.man cubicgrid.man \ + hypnowheel.man skytentacles.man sonar.man jigsaw.man \ + photopile.man rubikblocks.man surfaces.man hilbert.man \ + companioncube.man tronbit.man +MEN = @GL_MEN@ +RETIRED_MEN = glforestfire.man +EXTRAS = README Makefile.in dxf2gl.pl vrml2gl.pl wfront2gl.pl \ + molecules.sh starwars.txt + +TARFILES = $(SRCS) $(HDRS) $(MEN) $(RETIRED_MEN) $(EXTRAS) + + +default: all +all: $(EXES) $(RETIRED_EXES) + +install: install-program install-xml install-man +uninstall: uninstall-program uninstall-xml uninstall-man + +install-strip: + $(MAKE) INSTALL_PROGRAM='$(INSTALL_PROGRAM) -s' install + +# the hacks, in $HACKDIR +install-program:: $(EXES) + @exes="$(HACK_EXES_1)" ; \ + idir="$(install_prefix)$(HACKDIR)" ; \ + if [ "$$exes" != "" ]; then \ + if [ ! -d $$idir ]; then \ + $(INSTALL_DIRS) $$idir ; \ + fi ; \ + for program in $$exes; do \ + echo $(INSTALL_PROGRAM) $$program $$idir/$$program ; \ + $(INSTALL_PROGRAM) $$program $$idir/$$program ; \ + done ; \ + \ + exes="$(SUID_EXES)" ; \ + if [ @SETUID_HACKS@ = yes ]; then \ + sinst="$(INSTALL_SETUID)" ; \ + else \ + sinst="$(INSTALL_PROGRAM)" ; \ + fi ; \ + for program in $$exes; do \ + echo $$sinst $$program $$idir/$$program ; \ + if $$sinst $$program $$idir/$$program ; then \ + true ; \ + elif [ @SETUID_HACKS@ = yes ]; then \ + echo $(INSTALL_PROGRAM) $$program $$idir/$$program ; \ + if $(INSTALL_PROGRAM) $$program $$idir/$$program ; then\ + echo "" ; \ + echo "WARNING: unable to install $$program setuid:" \ + "installed non-setuid instead." ; \ + echo "" ; \ + else \ + exit 1 ; \ + fi ; \ + else \ + exit 1 ; \ + fi ; \ + done ; \ + fi + + +# the xscreensaver-gl-helper program, in $bindir +install-program:: $(EXES) + @exes="@GL_UTIL_EXES@" ; \ + idir="$(install_prefix)$(bindir)" ; \ + if [ "$$exes" != "" ]; then \ + if [ ! -d $$idir ]; then \ + $(INSTALL_DIRS) $$idir ; \ + fi ; \ + for program in $$exes; do \ + echo $(INSTALL_PROGRAM) $$program $$idir/$$program ; \ + $(INSTALL_PROGRAM) $$program $$idir/$$program ; \ + done ; \ + fi + +# When installing man pages, we install "foo.man" as "foo.N" and update +# the .TH line in the installed file with one like +# +# .TH XScreenSaver N "V.VV (DD-MMM-YYYY)" "X Version 11" +# +# where N is the manual section suffix. +# +install-man: $(MEN) + @men="$(MEN)" ; \ + U=$(UTILS_SRC)/version.h ; \ + V=`sed -n 's/.*xscreensaver \([0-9]\.[^)]*)\).*/\1/p' < $$U` ; \ + T=/tmp/xs$$$$.$(mansuffix) ; \ + TH=".TH XScreenSaver $(mansuffix) \"$$V\" \"X Version 11\"" ; \ + echo "installing man pages: $$TH" ; \ + \ + if [ ! -d $(install_prefix)$(manNdir) ]; then \ + $(INSTALL_DIRS) $(install_prefix)$(manNdir) ; \ + fi ; \ + \ + for man in $$men; do \ + instname=`echo $$man | sed 's/\.man$$/\.$(mansuffix)/'` ; \ + manbase=`echo $$man | sed 's/\.man$$//'` ; \ + TH=".TH $$manbase $(mansuffix) \"$$V\" \"X Version 11\" \"XScreenSaver manual\"" ; \ + sed -e "s/^\.TH.*/$$TH/" \ + -e 's@(MANSUFFIX)@($(mansuffix))@g' \ + < $(srcdir)/$$man > $$T ; \ + echo $(INSTALL_DATA) $(srcdir)/$$man \ + $(install_prefix)$(manNdir)/$$instname ; \ + $(INSTALL_DATA) $$T \ + $(install_prefix)$(manNdir)/$$instname ; \ + done ; \ + rm -f $$T + +install-xml: + @dest=$(install_prefix)$(HACK_CONF_DIR) ; \ + if [ ! -d $$dest ]; then \ + $(INSTALL_DIRS) $$dest ; \ + fi ; \ + src=$(srcdir)/../config ; \ + for file in $(EXES) $(SCRIPTS) ; do \ + if [ -f $$src/$$file.xml ]; then \ + echo $(INSTALL_DATA) $$src/$$file.xml $$dest/$$file.xml ; \ + $(INSTALL_DATA) $$src/$$file.xml $$dest/$$file.xml ; \ + fi ; \ + done + +# the hacks, in $HACKDIR +uninstall-program:: + @exes="$(HACK_EXES) $(RETIRED_EXES)" ; \ + idir="$(install_prefix)$(HACKDIR)" ; \ + for program in $$exes; do \ + echo rm -f $$idir/$$program ; \ + rm -f $$idir/$$program ; \ + done + +# the xscreensaver-gl-helper program, in $bindir +uninstall-program:: + @exes="$(GL_UTIL_EXES)" ; \ + idir="$(install_prefix)$(bindir)" ; \ + for program in $$exes; do \ + echo rm -f $$idir/$$program ; \ + rm -f $$idir/$$program ; \ + done + +uninstall-man: + @men="$(MEN) $(RETIRED_MEN)" ; \ + for man in $$men; do \ + instname=`echo $$man | sed 's/\.man$$/\.$(mansuffix)/'` ; \ + echo rm -f $(install_prefix)$(manNdir)/$$instname* ; \ + rm -f $(install_prefix)$(manNdir)/$$instname* ; \ + done + +uninstall-xml: + @dest=$(install_prefix)$(HACK_CONF_DIR) ; \ + for file in $(EXES) $(RETIRED_EXES) $(SCRIPTS) ; do \ + echo rm -f $$dest/$$file.xml ; \ + rm -f $$dest/$$file.xml ; \ + done + +clean: + -rm -f *.o a.out core $(EXES) $(RETIRED_EXES) molecules.h + +distclean: clean + -rm -f Makefile TAGS *~ "#"* + +# Adds all current dependencies to Makefile +depend: + $(DEPEND) -s '# DO NOT DELETE: updated by make depend' \ + $(DEPEND_FLAGS) -- \ + $(INCLUDES) $(DEFS) $(DEPEND_DEFINES) $(CFLAGS) $(X_CFLAGS) -- \ + $(SRCS) + +# Adds some dependencies to Makefile.in -- not totally accurate, but pretty +# close. This excludes dependencies on files in /usr/include, etc. It tries +# to include only dependencies on files which are themselves a part of this +# package. +distdepend:: molecules.h + @echo updating dependencies in `pwd`/Makefile.in... ; \ + $(DEPEND) -w 0 -f - \ + -s '# DO NOT DELETE: updated by make distdepend' $(DEPEND_FLAGS) -- \ + $(INCLUDES_1) $(DEFS) $(DEPEND_DEFINES) $(CFLAGS) $(X_CFLAGS) -- \ + $(SRCS) 2>/dev/null | \ + sort -d | \ + ( \ + awk '/^# .*Makefile.in ---/,/^# DO .*distdepend/' < Makefile.in ; \ + sed -e '/^#.*/d' \ + -e 's@ \./@ @g;s@ /[^ ]*@@g;/^.*:$$/d' \ + -e 's@\.\./\.\./utils@$$(UTILS_SRC)@g' \ + -e 's@\.\./glx/@@g' \ + -e 's@ \.\./@ $$(HACK_SRC)/@g' \ + -e 's@ \([^$$]\)@ $$(srcdir)/\1@g' \ + -e 's@ $$(srcdir)/\(.*config.h\)@ \1@g' \ + -e 's@ $$(HACK_SRC)/\(.*config.h\)@ ../\1@g' \ + -e 's@ $$(srcdir)/\(.*molecules.h\)@ \1@g' ; \ + echo '' \ + ) > /tmp/distdepend.$$$$ && \ + mv Makefile.in Makefile.in.bak && \ + mv /tmp/distdepend.$$$$ Makefile.in + + +TAGS: tags +tags: + find $(srcdir) -name '*.[chly]' -print | xargs etags -a + +echo_tarfiles: + @echo $(TARFILES) + +check_men: + @badmen="" ; \ + for exe in $(EXES); do \ + if ! [ -f $(srcdir)/$$exe.man ]; then \ + badmen="$$badmen $$exe" ; \ + fi ; \ + done ; \ + if [ -n "$$badmen" ]; then \ + echo "" ; \ + echo "Warning: The following programs have no manuals:" ; \ + echo "" ; \ + for m in $$badmen ; do \ + echo " $$m" ; \ + done ; \ + fi + +validate_xml: + @echo "Validating XML..." ; \ + cd $(HACK_SRC) ; ./check-configs.pl $(EXES) + +distdepend:: check_men validate_xml + + + +# Rules for noticing when the objects from the utils directory are out of +# date with respect to their sources, and going and building them according +# to the rules in their own Makefile... +# +$(UTILS_BIN)/colors.o: $(UTILS_SRC)/colors.c +$(UTILS_BIN)/grabclient.o: $(UTILS_SRC)/grabclient.c +$(UTILS_BIN)/hsv.o: $(UTILS_SRC)/hsv.c +$(UTILS_BIN)/resources.o: $(UTILS_SRC)/resources.c +$(UTILS_BIN)/usleep.o: $(UTILS_SRC)/usleep.c +$(UTILS_BIN)/visual.o: $(UTILS_SRC)/visual.c +$(UTILS_BIN)/visual-gl.o: $(UTILS_SRC)/visual-gl.c +$(UTILS_BIN)/yarandom.o: $(UTILS_SRC)/yarandom.c +$(UTILS_BIN)/xshm.o: $(UTILS_SRC)/xshm.c +$(UTILS_BIN)/textclient.o: $(UTILS_SRC)/textclient.c + +$(UTIL_OBJS): + cd $(UTILS_BIN) ; \ + $(MAKE) $(@F) CC="$(CC)" CFLAGS="$(CFLAGS)" LDFLAGS="$(LDFLAGS)" + +$(HACK_BIN)/xlockmore.o: $(HACK_SRC)/xlockmore.c + cd $(HACK_BIN) ; $(MAKE) $(@F) CC="$(CC)" CFLAGS="$(CFLAGS)" + + +# How we build object files in this directory. +.c.o: + $(CC) -c $(INCLUDES) $(DEFS) $(CFLAGS) $(X_CFLAGS) $< + + +# How to build the "xscreensaver-gl-helper" program, that lets the daemon +# know which visual is the right one for GL programs. +# +HELPER_OBJS = xscreensaver-gl-helper.o $(UTILS_BIN)/visual-gl.o \ + $(UTILS_BIN)/visual.o $(UTILS_BIN)/resources.o +xscreensaver-gl-helper: $(HELPER_OBJS) + $(CC) $(LDFLAGS) -o $@ $(HELPER_OBJS) $(LIBS) $(X_LIBS) $(HACK_POST2) + + +# These hacks use a slightly-differently-compiled variant of xlockmore.c. +# This is how to make the the other .o file from it. +# +XLM_CFLAGS=-DUSE_GL $(INCLUDES) $(DEFS) $(CFLAGS) $(X_CFLAGS) +xlockmore-gl.o: $(HACK_SRC)/xlockmore.c + $(CC) -o $@ -c $(XLM_CFLAGS) $(HACK_SRC)/xlockmore.c + +CC_HACK = $(CC) $(LDFLAGS) + +TRACK_OBJS=rotator.o trackball.o gltrackball.o +HACK_TRACK_OBJS=$(HACK_OBJS) $(TRACK_OBJS) +HACK_GRAB_OBJS=$(HACK_OBJS) $(GRAB_OBJS) +HACK_TRACK_GRAB_OBJS=$(HACK_TRACK_OBJS) $(GRAB_OBJS) +TEXT=$(UTILS_BIN)/textclient.o + +ATLANTIS_OBJS = $(HACK_OBJS) dolphin.o shark.o swim.o whale.o xpm-ximage.o +atlantis: atlantis.o $(ATLANTIS_OBJS) + $(CC_HACK) -o $@ $@.o $(ATLANTIS_OBJS) $(XPM_LIBS) + +ATUNNEL_OBJS = $(HACK_OBJS) tunnel_draw.o xpm-ximage.o +atunnel: atunnel.o $(ATUNNEL_OBJS) + $(CC_HACK) -o $@ $@.o $(ATUNNEL_OBJS) $(XPM_LIBS) + +cage: cage.o xpm-ximage.o $(HACK_OBJS) + $(CC_HACK) -o $@ $@.o xpm-ximage.o $(HACK_OBJS) $(XPM_LIBS) + +FLURRY_OBJS_1 = flurry-smoke.o flurry-spark.o flurry-star.o flurry-texture.o +FLURRY_OBJS = $(FLURRY_OBJS_1) $(HACK_OBJS) + +flurry: flurry.o $(FLURRY_OBJS) + $(CC_HACK) -o $@ $@.o $(FLURRY_OBJS) $(HACK_LIBS) -lm + +GEARS_OBJS=normals.o involute.o $(HACK_TRACK_OBJS) +gears: gears.o tube.o $(GEARS_OBJS) + $(CC_HACK) -o $@ $@.o tube.o $(GEARS_OBJS) $(HACK_LIBS) + +MOEBIUS_OBJS=sphere.o tube.o xpm-ximage.o $(HACK_TRACK_OBJS) +moebius: moebius.o $(MOEBIUS_OBJS) + $(CC_HACK) -o $@ $@.o $(MOEBIUS_OBJS) $(HACK_LIBS) $(XPM_LIBS) + +PIPE_OBJS=pipeobjs.o buildlwo.o sphere.o teapot.o normals.o +pipes: pipes.o $(PIPE_OBJS) $(HACK_TRACK_OBJS) + $(CC_HACK) -o $@ $@.o $(PIPE_OBJS) $(HACK_TRACK_OBJS) $(HACK_LIBS) + +superquadrics: superquadrics.o $(HACK_OBJS) + $(CC_HACK) -o $@ $@.o $(HACK_OBJS) $(HACK_LIBS) + +morph3d: morph3d.o $(HACK_OBJS) + $(CC_HACK) -o $@ $@.o $(HACK_OBJS) $(HACK_LIBS) + +rubik: rubik.o $(HACK_TRACK_OBJS) + $(CC_HACK) -o $@ $@.o $(HACK_TRACK_OBJS) $(HACK_LIBS) + +stairs: stairs.o sphere.o xpm-ximage.o $(HACK_TRACK_OBJS) + $(CC_HACK) -o $@ $@.o sphere.o xpm-ximage.o $(HACK_TRACK_OBJS) \ + $(HACK_LIBS) $(XPM_LIBS) + +SPROINGIES = sproingiewrap.o gllist.o \ + s1_1.o s1_2.o s1_3.o s1_4.o s1_5.o s1_6.o s1_b.o +sproingies: sproingies.o $(HACK_OBJS) $(SPROINGIES) + $(CC_HACK) -o $@ $@.o $(HACK_OBJS) $(SPROINGIES) $(HACK_LIBS) + +LAMENTOBJS = $(HACK_TRACK_OBJS) xpm-ximage.o normals.o +lament: lament.o $(LAMENTOBJS) + $(CC_HACK) -o $@ $@.o $(LAMENTOBJS) $(XPM_LIBS) + +B3D_OBJS = b_sphere.o b_draw.o b_lockglue.o $(HACK_OBJS) +bubble3d: bubble3d.o $(B3D_OBJS) + $(CC_HACK) -o $@ $@.o $(B3D_OBJS) $(HACK_LIBS) + +PLANET_OBJS=sphere.o xpm-ximage.o $(HACK_TRACK_OBJS) +glplanet: glplanet.o $(PLANET_OBJS) + $(CC_HACK) -o $@ $@.o $(PLANET_OBJS) $(XPM_LIBS) + +pulsar: pulsar.o $(HACK_OBJS) xpm-ximage.o + $(CC_HACK) -o $@ $@.o $(HACK_OBJS) xpm-ximage.o $(XPM_LIBS) + +EXTRUSION_OBJS=extrusion.o extrusion-helix2.o extrusion-helix3.o \ + extrusion-helix4.o extrusion-joinoffset.o extrusion-screw.o \ + extrusion-taper.o extrusion-twistoid.o xpm-ximage.o \ + $(HACK_TRACK_OBJS) +extrusion: $(EXTRUSION_OBJS) + $(CC_HACK) -o $@ $(EXTRUSION_OBJS) $(XPM_LIBS) $(GLE_LIBS) + +sierpinski3d: sierpinski3d.o $(HACK_TRACK_OBJS) + $(CC_HACK) -o $@ $@.o $(HACK_TRACK_OBJS) $(HACK_LIBS) + +gflux: gflux.o $(HACK_TRACK_GRAB_OBJS) + $(CC_HACK) -o $@ $@.o $(HACK_TRACK_GRAB_OBJS) $(HACK_LIBS) + +SW_OBJS=starwars.o glut_stroke.o glut_swidth.o \ + $(TEXT) ${FONT_OBJS} $(HACK_OBJS) +starwars: $(SW_OBJS) + $(CC_HACK) -o $@ $(SW_OBJS) $(HACK_LIBS) $(TEXT_LIBS) + +GLT_OBJS=gltext.o glut_stroke.o glut_swidth.o tube.o sphere.o \ + $(TEXT) $(HACK_TRACK_OBJS) +gltext: $(GLT_OBJS) + $(CC_HACK) -o $@ $(GLT_OBJS) $(HACK_LIBS) $(TEXT_LIBS) + +DB_OBJS=sphere.o tube.o $(HACK_TRACK_OBJS) +dangerball: dangerball.o $(DB_OBJS) + $(CC_HACK) -o $@ $@.o $(DB_OBJS) $(HACK_LIBS) + +circuit: circuit.o font-ximage.o $(HACK_OBJS) + $(CC_HACK) -o $@ $@.o font-ximage.o $(HACK_OBJS) $(HACK_LIBS) + +menger: menger.o $(HACK_TRACK_OBJS) + $(CC_HACK) -o $@ $@.o $(HACK_TRACK_OBJS) $(HACK_LIBS) + +engine: engine.o $(HACK_TRACK_OBJS) + $(CC_HACK) -o $@ $@.o $(HACK_TRACK_OBJS) $(HACK_LIBS) + +flipscreen3d: flipscreen3d.o $(HACK_TRACK_GRAB_OBJS) + $(CC_HACK) -o $@ $@.o $(HACK_TRACK_GRAB_OBJS) $(HACK_LIBS) + +glsnake: glsnake.o $(HACK_OBJS) + $(CC_HACK) -o $@ $@.o $(HACK_OBJS) $(HACK_LIBS) + +boxed: boxed.o $(HACK_OBJS) + $(CC_HACK) -o $@ $@.o $(HACK_OBJS) $(HACK_LIBS) + +glforestfire: glforestfire.o xpm-ximage.o $(HACK_TRACK_OBJS) + $(CC_HACK) -o $@ $@.o xpm-ximage.o $(HACK_TRACK_OBJS) $(XPM_LIBS) + +sballs: sballs.o xpm-ximage.o $(HACK_TRACK_OBJS) + $(CC_HACK) -o $@ $@.o xpm-ximage.o $(HACK_TRACK_OBJS) $(XPM_LIBS) + +cubenetic: cubenetic.o $(HACK_TRACK_OBJS) + $(CC_HACK) -o $@ $@.o $(HACK_TRACK_OBJS) $(HACK_LIBS) + +spheremonics: spheremonics.o normals.o $(HACK_TRACK_OBJS) + $(CC_HACK) -o $@ $@.o normals.o $(HACK_TRACK_OBJS) $(HACK_LIBS) + +LL_OBJS=marching.o xpm-ximage.o normals.o $(HACK_TRACK_OBJS) +lavalite: lavalite.o $(LL_OBJS) + $(CC_HACK) -o $@ $@.o $(LL_OBJS) $(XPM_LIBS) + +queens: queens.o chessmodels.o $(HACK_TRACK_OBJS) + $(CC_HACK) -o $@ $@.o chessmodels.o $(HACK_TRACK_OBJS) $(HACK_LIBS) + +endgame: endgame.o chessmodels.o $(HACK_TRACK_OBJS) + $(CC_HACK) -o $@ $@.o chessmodels.o $(HACK_TRACK_OBJS) $(HACK_LIBS) + +glblur: glblur.o $(HACK_TRACK_OBJS) + $(CC_HACK) -o $@ $@.o $(HACK_TRACK_OBJS) $(HACK_LIBS) + +TOAST_OBJS=\ + toaster.o toaster_base.o toaster_handle.o toaster_handle2.o \ + toaster_jet.o toaster_knob.o toaster_slots.o toaster_wing.o \ + toast.o toast2.o \ + flyingtoasters.o gllist.o xpm-ximage.o $(HACK_TRACK_OBJS) +flyingtoasters: $(TOAST_OBJS) + $(CC_HACK) -o $@ $(TOAST_OBJS) $(XPM_LIBS) + +COW_OBJS=\ + cow_face.o cow_hide.o cow_hoofs.o cow_horns.o cow_tail.o cow_udder.o \ + bouncingcow.o gllist.o xpm-ximage.o $(HACK_TRACK_OBJS) +bouncingcow: $(COW_OBJS) + $(CC_HACK) -o $@ $(COW_OBJS) $(XPM_LIBS) + +glslideshow: glslideshow.o $(HACK_GRAB_OBJS) + $(CC_HACK) -o $@ $@.o $(HACK_GRAB_OBJS) $(HACK_LIBS) + +jigglypuff: jigglypuff.o xpm-ximage.o $(HACK_TRACK_OBJS) + $(CC_HACK) -o $@ $@.o xpm-ximage.o $(HACK_TRACK_OBJS) $(XPM_LIBS) + +klein: klein.o $(HACK_TRACK_OBJS) + $(CC_HACK) -o $@ $@.o $(HACK_TRACK_OBJS) $(HACK_LIBS) + +surfaces: surfaces.o $(HACK_TRACK_OBJS) + $(CC_HACK) -o $@ $@.o $(HACK_TRACK_OBJS) $(HACK_LIBS) + +hypertorus: hypertorus.o $(HACK_TRACK_OBJS) + $(CC_HACK) -o $@ $@.o $(HACK_TRACK_OBJS) $(HACK_LIBS) + +glmatrix: glmatrix.o xpm-ximage.o $(HACK_OBJS) + $(CC_HACK) -o $@ $@.o xpm-ximage.o $(HACK_OBJS) $(XPM_LIBS) + +cubestorm: cubestorm.o $(HACK_TRACK_OBJS) + $(CC_HACK) -o $@ $@.o $(HACK_TRACK_OBJS) $(HACK_LIBS) + +glknots: glknots.o tube.o $(HACK_TRACK_OBJS) + $(CC_HACK) -o $@ $@.o tube.o $(HACK_TRACK_OBJS) $(HACK_LIBS) + +blocktube: blocktube.o xpm-ximage.o $(HACK_OBJS) + $(CC_HACK) -o $@ $@.o xpm-ximage.o $(HACK_OBJS) $(XPM_LIBS) + +flipflop: flipflop.o $(HACK_TRACK_GRAB_OBJS) + $(CC_HACK) -o $@ $@.o $(HACK_TRACK_GRAB_OBJS) $(HACK_LIBS) + +antspotlight: antspotlight.o sphere.o $(HACK_TRACK_GRAB_OBJS) + $(CC_HACK) -o $@ $@.o sphere.o $(HACK_TRACK_GRAB_OBJS) $(HACK_LIBS) + +polytopes: polytopes.o $(HACK_TRACK_OBJS) + $(CC_HACK) -o $@ $@.o $(HACK_TRACK_OBJS) $(HACK_LIBS) + +STONER_OBJS=stonerview-move.o stonerview-osc.o stonerview-view.o +stonerview: stonerview.o $(STONER_OBJS) $(HACK_TRACK_OBJS) + $(CC_HACK) -o $@ $@.o $(STONER_OBJS) $(HACK_TRACK_OBJS) $(HACK_LIBS) + + +molecules.h: + @echo "building molecules.h from $(HACK_SRC)/images/molecules/*.pdb"; \ + UTILS_SRC="$(UTILS_SRC)" \ + $(srcdir)/molecules.sh molecules.h $(HACK_SRC)/images/molecules/*.pdb + +MOLECULE_OBJS=sphere.o tube.o $(HACK_TRACK_OBJS) +molecule.o: molecules.h +molecule: molecule.o $(MOLECULE_OBJS) + $(CC_HACK) -o $@ $@.o $(MOLECULE_OBJS) $(HACK_LIBS) + +gleidescope: gleidescope.o xpm-ximage.o $(HACK_GRAB_OBJS) + $(CC_HACK) -o $@ $@.o xpm-ximage.o $(HACK_GRAB_OBJS) $(XPM_LIBS) + +mirrorblob: mirrorblob.o $(HACK_TRACK_GRAB_OBJS) + $(CC_HACK) -o $@ $@.o $(HACK_TRACK_GRAB_OBJS) $(XPM_LIBS) + +blinkbox: blinkbox.o sphere.o $(HACK_OBJS) + $(CC_HACK) -o $@ $@.o sphere.o $(HACK_OBJS) $(HACK_LIBS) + +noof: noof.o $(HACK_OBJS) + $(CC_HACK) -o $@ $@.o $(HACK_OBJS) $(HACK_LIBS) + +PH_OBJS=polyhedra-gl.o normals.o teapot.o $(HACK_TRACK_OBJS) +polyhedra: polyhedra.o $(PH_OBJS) + $(CC_HACK) -o $@ $@.o $(PH_OBJS) $(HACK_LIBS) + +antinspect: antinspect.o sphere.o $(HACK_TRACK_OBJS) + $(CC_HACK) -o $@ $@.o sphere.o $(HACK_TRACK_OBJS) $(HACK_LIBS) + +providence: providence.o $(HACK_TRACK_OBJS) + $(CC_HACK) -o $@ $@.o $(HACK_TRACK_OBJS) $(HACK_LIBS) + +pinion: pinion.o $(GEARS_OBJS) + $(CC_HACK) -o $@ $@.o $(GEARS_OBJS) $(HACK_LIBS) + +moebiusgears: moebiusgears.o $(GEARS_OBJS) + $(CC_HACK) -o $@ $@.o $(GEARS_OBJS) $(HACK_LIBS) + +boing: boing.o normals.o $(HACK_TRACK_OBJS) + $(CC_HACK) -o $@ $@.o normals.o $(HACK_TRACK_OBJS) $(HACK_LIBS) + +carousel: carousel.o ${FONT_OBJS} $(HACK_TRACK_GRAB_OBJS) + $(CC_HACK) -o $@ $@.o ${FONT_OBJS} $(HACK_TRACK_GRAB_OBJS) $(HACK_LIBS) + +fliptext: fliptext.o $(TEXT) ${FONT_OBJS} $(HACK_OBJS) + $(CC_HACK) -o $@ $@.o $(TEXT) ${FONT_OBJS} $(HACK_OBJS) $(HACK_LIBS) $(TEXT_LIBS) + +antmaze: antmaze.o sphere.o tube.o $(HACK_TRACK_OBJS) + $(CC_HACK) -o $@ $@.o sphere.o tube.o $(HACK_TRACK_OBJS) $(HACK_LIBS) + +TANGRAM_OBJS=tangram_shapes.o $(HACK_OBJS) +tangram: tangram.o $(TANGRAM_OBJS) + $(CC_HACK) -o $@ $@.o $(TANGRAM_OBJS) $(HACK_LIBS) + +crackberg: crackberg.o $(HACK_OBJS) + $(CC_HACK) -o $@ $@.o $(HACK_OBJS) $(HACK_LIBS) + +glhanoi: glhanoi.o $(HACK_TRACK_OBJS) + $(CC_HACK) -o $@ $@.o $(HACK_TRACK_OBJS) $(HACK_LIBS) + +cube21: cube21.o $(HACK_TRACK_OBJS) + $(CC_HACK) -o $@ $@.o $(HACK_TRACK_OBJS) $(HACK_LIBS) + +TIMETUNNEL_OBJS = xpm-ximage.o $(HACK_TRACK_OBJS) +timetunnel: timetunnel.o $(TIMETUNNEL_OBJS) + $(CC_HACK) -o $@ $@.o $(TIMETUNNEL_OBJS) $(XPM_LIBS) + +JUGG_OBJS=sphere.o tube.o $(HACK_TRACK_OBJS) +juggler3d: juggler3d.o $(JUGG_OBJS) + $(CC_HACK) -o $@ $@.o $(JUGG_OBJS) $(HACK_LIBS) + +dnalogo: dnalogo.o tube.o normals.o $(HACK_TRACK_OBJS) + $(CC_HACK) -o $@ $@.o tube.o normals.o $(HACK_TRACK_OBJS) $(HACK_LIBS) + +topblock: topblock.o sphere.o tube.o $(HACK_TRACK_OBJS) + $(CC_HACK) -o $@ $@.o sphere.o tube.o $(HACK_TRACK_OBJS) $(HACK_LIBS) + +SCHOOL_OBJS=glschool.o glschool_alg.o glschool_gl.o \ + sphere.o tube.o normals.o $(HACK_OBJS) +glschool: $(SCHOOL_OBJS) + $(CC_HACK) -o $@ $(SCHOOL_OBJS) $(HACK_LIBS) + +glcells: glcells.o $(HACK_OBJS) + $(CC_HACK) -o $@ $@.o $(HACK_OBJS) $(HACK_LIBS) + +voronoi: voronoi.o $(HACK_OBJS) + $(CC_HACK) -o $@ $@.o $(HACK_OBJS) $(HACK_LIBS) + +lockward: lockward.o $(HACK_OBJS) + $(CC_HACK) -o $@ $@.o $(HACK_OBJS) $(HACK_LIBS) + +cubicgrid: cubicgrid.o $(HACK_TRACK_OBJS) + $(CC_HACK) -o $@ $@.o $(HACK_TRACK_OBJS) $(HACK_LIBS) + +hypnowheel: hypnowheel.o $(HACK_TRACK_OBJS) + $(CC_HACK) -o $@ $@.o $(HACK_TRACK_OBJS) $(HACK_LIBS) + +TENTACLE_OBJS=normals.o xpm-ximage.o $(HACK_TRACK_OBJS) +skytentacles: skytentacles.o $(TENTACLE_OBJS) + $(CC_HACK) -o $@ $@.o $(TENTACLE_OBJS) $(XPM_LIBS) + +SONAR_OBJS=sonar-sim.o sonar-icmp.o ${FONT_OBJS} $(HACK_TRACK_OBJS) +sonar: sonar.o $(SONAR_OBJS) + $(CC_HACK) -o $@ $@.o $(SONAR_OBJS) $(HACK_LIBS) + +JIGSAW_OBJS=normals.o $(UTILS_BIN)/spline.o \ + ${FONT_OBJS} $(HACK_TRACK_GRAB_OBJS) +jigsaw: jigsaw.o $(JIGSAW_OBJS) + $(CC_HACK) -o $@ $@.o $(JIGSAW_OBJS) $(HACK_LIBS) + +PHOTOPILE_OBJS=${FONT_OBJS} dropshadow.o $(HACK_GRAB_OBJS) +photopile: photopile.o $(PHOTOPILE_OBJS) + $(CC_HACK) -o $@ $@.o $(PHOTOPILE_OBJS) $(HACK_LIBS) + +rubikblocks: rubikblocks.o $(HACK_TRACK_OBJS) + $(CC_HACK) -o $@ $@.o $(HACK_TRACK_OBJS) $(HACK_LIBS) + +HILB_OBJS=sphere.o tube.o $(HACK_TRACK_OBJS) +hilbert: hilbert.o $(HILB_OBJS) + $(CC_HACK) -o $@ $@.o $(HILB_OBJS) $(HACK_LIBS) + +CCUBE_OBJS=companion.o companion_quad.o companion_disc.o companion_heart.o \ + gllist.o $(HACK_TRACK_OBJS) +companioncube: $(CCUBE_OBJS) + $(CC_HACK) -o $@ $(CCUBE_OBJS) $(HACK_LIBS) + +TBIT_OBJS=tronbit.o tronbit_idle1.o tronbit_idle2.o tronbit_no.o tronbit_yes.o\ + gllist.o $(HACK_TRACK_OBJS) +tronbit: $(TBIT_OBJS) + $(CC_HACK) -o $@ $(TBIT_OBJS) $(HACK_LIBS) + +############################################################################## +# +# DO NOT DELETE: updated by make distdepend + +antinspect.o: ../../config.h +antinspect.o: $(HACK_SRC)/fps.h +antinspect.o: $(srcdir)/gltrackball.h +antinspect.o: $(srcdir)/jwzglesI.h +antinspect.o: $(srcdir)/jwzgles.h +antinspect.o: $(HACK_SRC)/screenhackI.h +antinspect.o: $(srcdir)/sphere.h +antinspect.o: $(UTILS_SRC)/colors.h +antinspect.o: $(UTILS_SRC)/grabscreen.h +antinspect.o: $(UTILS_SRC)/hsv.h +antinspect.o: $(UTILS_SRC)/resources.h +antinspect.o: $(UTILS_SRC)/usleep.h +antinspect.o: $(UTILS_SRC)/visual.h +antinspect.o: $(UTILS_SRC)/xshm.h +antinspect.o: $(UTILS_SRC)/yarandom.h +antinspect.o: $(HACK_SRC)/xlockmoreI.h +antinspect.o: $(HACK_SRC)/xlockmore.h +antmaze.o: $(srcdir)/ants.h +antmaze.o: ../../config.h +antmaze.o: $(HACK_SRC)/fps.h +antmaze.o: $(srcdir)/gltrackball.h +antmaze.o: $(srcdir)/jwzglesI.h +antmaze.o: $(srcdir)/jwzgles.h +antmaze.o: $(srcdir)/rotator.h +antmaze.o: $(HACK_SRC)/screenhackI.h +antmaze.o: $(srcdir)/sphere.h +antmaze.o: $(srcdir)/tube.h +antmaze.o: $(UTILS_SRC)/colors.h +antmaze.o: $(UTILS_SRC)/grabscreen.h +antmaze.o: $(UTILS_SRC)/hsv.h +antmaze.o: $(UTILS_SRC)/resources.h +antmaze.o: $(UTILS_SRC)/usleep.h +antmaze.o: $(UTILS_SRC)/visual.h +antmaze.o: $(UTILS_SRC)/xshm.h +antmaze.o: $(UTILS_SRC)/yarandom.h +antmaze.o: $(HACK_SRC)/xlockmoreI.h +antmaze.o: $(HACK_SRC)/xlockmore.h +antspotlight.o: $(srcdir)/ants.h +antspotlight.o: ../../config.h +antspotlight.o: $(HACK_SRC)/fps.h +antspotlight.o: $(srcdir)/gltrackball.h +antspotlight.o: $(srcdir)/grab-ximage.h +antspotlight.o: $(srcdir)/jwzglesI.h +antspotlight.o: $(srcdir)/jwzgles.h +antspotlight.o: $(srcdir)/rotator.h +antspotlight.o: $(HACK_SRC)/screenhackI.h +antspotlight.o: $(srcdir)/sphere.h +antspotlight.o: $(srcdir)/tube.h +antspotlight.o: $(UTILS_SRC)/colors.h +antspotlight.o: $(UTILS_SRC)/grabscreen.h +antspotlight.o: $(UTILS_SRC)/hsv.h +antspotlight.o: $(UTILS_SRC)/resources.h +antspotlight.o: $(UTILS_SRC)/usleep.h +antspotlight.o: $(UTILS_SRC)/visual.h +antspotlight.o: $(UTILS_SRC)/xshm.h +antspotlight.o: $(UTILS_SRC)/yarandom.h +antspotlight.o: $(HACK_SRC)/xlockmoreI.h +antspotlight.o: $(HACK_SRC)/xlockmore.h +atlantis.o: $(srcdir)/atlantis.h +atlantis.o: ../../config.h +atlantis.o: $(HACK_SRC)/fps.h +atlantis.o: $(HACK_SRC)/images/sea-texture.xpm +atlantis.o: $(srcdir)/jwzglesI.h +atlantis.o: $(srcdir)/jwzgles.h +atlantis.o: $(HACK_SRC)/screenhackI.h +atlantis.o: $(UTILS_SRC)/colors.h +atlantis.o: $(UTILS_SRC)/grabscreen.h +atlantis.o: $(UTILS_SRC)/hsv.h +atlantis.o: $(UTILS_SRC)/resources.h +atlantis.o: $(UTILS_SRC)/usleep.h +atlantis.o: $(UTILS_SRC)/visual.h +atlantis.o: $(UTILS_SRC)/xshm.h +atlantis.o: $(UTILS_SRC)/yarandom.h +atlantis.o: $(HACK_SRC)/xlockmoreI.h +atlantis.o: $(HACK_SRC)/xlockmore.h +atlantis.o: $(srcdir)/xpm-ximage.h +atunnel.o: ../../config.h +atunnel.o: $(HACK_SRC)/fps.h +atunnel.o: $(HACK_SRC)/images/tunnel0.xpm +atunnel.o: $(HACK_SRC)/images/tunnel1.xpm +atunnel.o: $(HACK_SRC)/images/tunnel2.xpm +atunnel.o: $(HACK_SRC)/images/tunnel3.xpm +atunnel.o: $(HACK_SRC)/images/tunnel4.xpm +atunnel.o: $(HACK_SRC)/images/tunnel5.xpm +atunnel.o: $(srcdir)/jwzglesI.h +atunnel.o: $(srcdir)/jwzgles.h +atunnel.o: $(HACK_SRC)/screenhackI.h +atunnel.o: $(srcdir)/tunnel_draw.h +atunnel.o: $(UTILS_SRC)/colors.h +atunnel.o: $(UTILS_SRC)/grabscreen.h +atunnel.o: $(UTILS_SRC)/hsv.h +atunnel.o: $(UTILS_SRC)/resources.h +atunnel.o: $(UTILS_SRC)/usleep.h +atunnel.o: $(UTILS_SRC)/visual.h +atunnel.o: $(UTILS_SRC)/xshm.h +atunnel.o: $(UTILS_SRC)/yarandom.h +atunnel.o: $(HACK_SRC)/xlockmoreI.h +atunnel.o: $(HACK_SRC)/xlockmore.h +atunnel.o: $(srcdir)/xpm-ximage.h +b_draw.o: $(srcdir)/bubble3d.h +b_draw.o: ../../config.h +b_draw.o: $(HACK_SRC)/fps.h +b_draw.o: $(srcdir)/jwzglesI.h +b_draw.o: $(srcdir)/jwzgles.h +b_draw.o: $(HACK_SRC)/screenhackI.h +b_draw.o: $(UTILS_SRC)/colors.h +b_draw.o: $(UTILS_SRC)/grabscreen.h +b_draw.o: $(UTILS_SRC)/hsv.h +b_draw.o: $(UTILS_SRC)/resources.h +b_draw.o: $(UTILS_SRC)/usleep.h +b_draw.o: $(UTILS_SRC)/visual.h +b_draw.o: $(UTILS_SRC)/xshm.h +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: $(srcdir)/jwzglesI.h +blinkbox.o: $(srcdir)/jwzgles.h +blinkbox.o: $(HACK_SRC)/screenhackI.h +blinkbox.o: $(srcdir)/sphere.h +blinkbox.o: $(UTILS_SRC)/colors.h +blinkbox.o: $(UTILS_SRC)/grabscreen.h +blinkbox.o: $(UTILS_SRC)/hsv.h +blinkbox.o: $(UTILS_SRC)/resources.h +blinkbox.o: $(UTILS_SRC)/usleep.h +blinkbox.o: $(UTILS_SRC)/visual.h +blinkbox.o: $(UTILS_SRC)/xshm.h +blinkbox.o: $(UTILS_SRC)/yarandom.h +blinkbox.o: $(HACK_SRC)/xlockmoreI.h +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: $(srcdir)/jwzglesI.h +b_lockglue.o: $(srcdir)/jwzgles.h +b_lockglue.o: $(HACK_SRC)/screenhackI.h +b_lockglue.o: $(UTILS_SRC)/colors.h +b_lockglue.o: $(UTILS_SRC)/grabscreen.h +b_lockglue.o: $(UTILS_SRC)/hsv.h +b_lockglue.o: $(UTILS_SRC)/resources.h +b_lockglue.o: $(UTILS_SRC)/usleep.h +b_lockglue.o: $(UTILS_SRC)/visual.h +b_lockglue.o: $(UTILS_SRC)/xshm.h +b_lockglue.o: $(UTILS_SRC)/yarandom.h +b_lockglue.o: $(HACK_SRC)/xlockmoreI.h +b_lockglue.o: $(HACK_SRC)/xlockmore.h +blocktube.o: ../../config.h +blocktube.o: $(HACK_SRC)/fps.h +blocktube.o: $(HACK_SRC)/images/blocktube.xpm +blocktube.o: $(srcdir)/jwzglesI.h +blocktube.o: $(srcdir)/jwzgles.h +blocktube.o: $(HACK_SRC)/screenhackI.h +blocktube.o: $(UTILS_SRC)/colors.h +blocktube.o: $(UTILS_SRC)/grabscreen.h +blocktube.o: $(UTILS_SRC)/hsv.h +blocktube.o: $(UTILS_SRC)/resources.h +blocktube.o: $(UTILS_SRC)/usleep.h +blocktube.o: $(UTILS_SRC)/visual.h +blocktube.o: $(UTILS_SRC)/xshm.h +blocktube.o: $(UTILS_SRC)/yarandom.h +blocktube.o: $(HACK_SRC)/xlockmoreI.h +blocktube.o: $(HACK_SRC)/xlockmore.h +blocktube.o: $(srcdir)/xpm-ximage.h +boing.o: ../../config.h +boing.o: $(HACK_SRC)/fps.h +boing.o: $(srcdir)/gltrackball.h +boing.o: $(srcdir)/jwzglesI.h +boing.o: $(srcdir)/jwzgles.h +boing.o: $(HACK_SRC)/screenhackI.h +boing.o: $(UTILS_SRC)/colors.h +boing.o: $(UTILS_SRC)/grabscreen.h +boing.o: $(UTILS_SRC)/hsv.h +boing.o: $(UTILS_SRC)/resources.h +boing.o: $(UTILS_SRC)/usleep.h +boing.o: $(UTILS_SRC)/visual.h +boing.o: $(UTILS_SRC)/xshm.h +boing.o: $(UTILS_SRC)/yarandom.h +boing.o: $(HACK_SRC)/xlockmoreI.h +boing.o: $(HACK_SRC)/xlockmore.h +bouncingcow.o: ../../config.h +bouncingcow.o: $(HACK_SRC)/fps.h +bouncingcow.o: $(srcdir)/gllist.h +bouncingcow.o: $(srcdir)/gltrackball.h +bouncingcow.o: $(srcdir)/jwzglesI.h +bouncingcow.o: $(srcdir)/jwzgles.h +bouncingcow.o: $(srcdir)/rotator.h +bouncingcow.o: $(HACK_SRC)/screenhackI.h +bouncingcow.o: $(UTILS_SRC)/colors.h +bouncingcow.o: $(UTILS_SRC)/grabscreen.h +bouncingcow.o: $(UTILS_SRC)/hsv.h +bouncingcow.o: $(UTILS_SRC)/resources.h +bouncingcow.o: $(UTILS_SRC)/usleep.h +bouncingcow.o: $(UTILS_SRC)/visual.h +bouncingcow.o: $(UTILS_SRC)/xshm.h +bouncingcow.o: $(UTILS_SRC)/yarandom.h +bouncingcow.o: $(HACK_SRC)/xlockmoreI.h +bouncingcow.o: $(HACK_SRC)/xlockmore.h +bouncingcow.o: $(srcdir)/xpm-ximage.h +boxed.o: $(srcdir)/boxed.h +boxed.o: ../../config.h +boxed.o: $(HACK_SRC)/fps.h +boxed.o: $(srcdir)/jwzglesI.h +boxed.o: $(srcdir)/jwzgles.h +boxed.o: $(HACK_SRC)/screenhackI.h +boxed.o: $(UTILS_SRC)/colors.h +boxed.o: $(UTILS_SRC)/grabscreen.h +boxed.o: $(UTILS_SRC)/hsv.h +boxed.o: $(UTILS_SRC)/resources.h +boxed.o: $(UTILS_SRC)/usleep.h +boxed.o: $(UTILS_SRC)/visual.h +boxed.o: $(UTILS_SRC)/xshm.h +boxed.o: $(UTILS_SRC)/yarandom.h +boxed.o: $(HACK_SRC)/xlockmoreI.h +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: $(srcdir)/jwzglesI.h +b_sphere.o: $(srcdir)/jwzgles.h +b_sphere.o: $(HACK_SRC)/screenhackI.h +b_sphere.o: $(UTILS_SRC)/colors.h +b_sphere.o: $(UTILS_SRC)/grabscreen.h +b_sphere.o: $(UTILS_SRC)/hsv.h +b_sphere.o: $(UTILS_SRC)/resources.h +b_sphere.o: $(UTILS_SRC)/usleep.h +b_sphere.o: $(UTILS_SRC)/visual.h +b_sphere.o: $(UTILS_SRC)/xshm.h +b_sphere.o: $(UTILS_SRC)/yarandom.h +b_sphere.o: $(HACK_SRC)/xlockmoreI.h +bubble3d.o: $(srcdir)/bubble3d.h +bubble3d.o: ../../config.h +bubble3d.o: $(HACK_SRC)/fps.h +bubble3d.o: $(srcdir)/jwzglesI.h +bubble3d.o: $(srcdir)/jwzgles.h +bubble3d.o: $(HACK_SRC)/screenhackI.h +bubble3d.o: $(UTILS_SRC)/colors.h +bubble3d.o: $(UTILS_SRC)/grabscreen.h +bubble3d.o: $(UTILS_SRC)/hsv.h +bubble3d.o: $(UTILS_SRC)/resources.h +bubble3d.o: $(UTILS_SRC)/usleep.h +bubble3d.o: $(UTILS_SRC)/visual.h +bubble3d.o: $(UTILS_SRC)/xshm.h +bubble3d.o: $(UTILS_SRC)/yarandom.h +bubble3d.o: $(HACK_SRC)/xlockmoreI.h +buildlwo.o: $(srcdir)/buildlwo.h +buildlwo.o: ../../config.h +buildlwo.o: $(srcdir)/jwzglesI.h +buildlwo.o: $(srcdir)/jwzgles.h +cage.o: ../../config.h +cage.o: $(HACK_SRC)/fps.h +cage.o: $(HACK_SRC)/images/wood.xpm +cage.o: $(srcdir)/jwzglesI.h +cage.o: $(srcdir)/jwzgles.h +cage.o: $(HACK_SRC)/screenhackI.h +cage.o: $(UTILS_SRC)/colors.h +cage.o: $(UTILS_SRC)/grabscreen.h +cage.o: $(UTILS_SRC)/hsv.h +cage.o: $(UTILS_SRC)/resources.h +cage.o: $(UTILS_SRC)/usleep.h +cage.o: $(UTILS_SRC)/visual.h +cage.o: $(UTILS_SRC)/xshm.h +cage.o: $(UTILS_SRC)/yarandom.h +cage.o: $(HACK_SRC)/xlockmoreI.h +cage.o: $(HACK_SRC)/xlockmore.h +cage.o: $(srcdir)/xpm-ximage.h +carousel.o: ../../config.h +carousel.o: $(HACK_SRC)/fps.h +carousel.o: $(srcdir)/gltrackball.h +carousel.o: $(srcdir)/grab-ximage.h +carousel.o: $(srcdir)/jwzglesI.h +carousel.o: $(srcdir)/jwzgles.h +carousel.o: $(srcdir)/rotator.h +carousel.o: $(HACK_SRC)/screenhackI.h +carousel.o: $(srcdir)/texfont.h +carousel.o: $(UTILS_SRC)/colors.h +carousel.o: $(UTILS_SRC)/grabscreen.h +carousel.o: $(UTILS_SRC)/hsv.h +carousel.o: $(UTILS_SRC)/resources.h +carousel.o: $(UTILS_SRC)/usleep.h +carousel.o: $(UTILS_SRC)/visual.h +carousel.o: $(UTILS_SRC)/xshm.h +carousel.o: $(UTILS_SRC)/yarandom.h +carousel.o: $(HACK_SRC)/xlockmoreI.h +carousel.o: $(HACK_SRC)/xlockmore.h +chessmodels.o: $(srcdir)/chessmodels.h +chessmodels.o: ../../config.h +chessmodels.o: $(srcdir)/jwzglesI.h +chessmodels.o: $(srcdir)/jwzgles.h +circuit.o: ../../config.h +circuit.o: $(srcdir)/font-ximage.h +circuit.o: $(HACK_SRC)/fps.h +circuit.o: $(srcdir)/jwzglesI.h +circuit.o: $(srcdir)/jwzgles.h +circuit.o: $(HACK_SRC)/screenhackI.h +circuit.o: $(UTILS_SRC)/colors.h +circuit.o: $(UTILS_SRC)/grabscreen.h +circuit.o: $(UTILS_SRC)/hsv.h +circuit.o: $(UTILS_SRC)/resources.h +circuit.o: $(UTILS_SRC)/usleep.h +circuit.o: $(UTILS_SRC)/visual.h +circuit.o: $(UTILS_SRC)/xshm.h +circuit.o: $(UTILS_SRC)/yarandom.h +circuit.o: $(HACK_SRC)/xlockmoreI.h +circuit.o: $(HACK_SRC)/xlockmore.h +companion_disc.o: ../../config.h +companion_disc.o: $(srcdir)/gllist.h +companion_disc.o: $(srcdir)/jwzglesI.h +companion_disc.o: $(srcdir)/jwzgles.h +companion_heart.o: ../../config.h +companion_heart.o: $(srcdir)/gllist.h +companion_heart.o: $(srcdir)/jwzglesI.h +companion_heart.o: $(srcdir)/jwzgles.h +companion.o: ../../config.h +companion.o: $(HACK_SRC)/fps.h +companion.o: $(srcdir)/gllist.h +companion.o: $(srcdir)/gltrackball.h +companion.o: $(srcdir)/jwzglesI.h +companion.o: $(srcdir)/jwzgles.h +companion.o: $(srcdir)/rotator.h +companion.o: $(HACK_SRC)/screenhackI.h +companion.o: $(UTILS_SRC)/colors.h +companion.o: $(UTILS_SRC)/grabscreen.h +companion.o: $(UTILS_SRC)/hsv.h +companion.o: $(UTILS_SRC)/resources.h +companion.o: $(UTILS_SRC)/usleep.h +companion.o: $(UTILS_SRC)/visual.h +companion.o: $(UTILS_SRC)/xshm.h +companion.o: $(UTILS_SRC)/yarandom.h +companion.o: $(HACK_SRC)/xlockmoreI.h +companion.o: $(HACK_SRC)/xlockmore.h +companion.o: $(srcdir)/xpm-ximage.h +companion_quad.o: ../../config.h +companion_quad.o: $(srcdir)/gllist.h +companion_quad.o: $(srcdir)/jwzglesI.h +companion_quad.o: $(srcdir)/jwzgles.h +cow_face.o: ../../config.h +cow_face.o: $(srcdir)/gllist.h +cow_face.o: $(srcdir)/jwzglesI.h +cow_face.o: $(srcdir)/jwzgles.h +cow_hide.o: ../../config.h +cow_hide.o: $(srcdir)/gllist.h +cow_hide.o: $(srcdir)/jwzglesI.h +cow_hide.o: $(srcdir)/jwzgles.h +cow_hoofs.o: ../../config.h +cow_hoofs.o: $(srcdir)/gllist.h +cow_hoofs.o: $(srcdir)/jwzglesI.h +cow_hoofs.o: $(srcdir)/jwzgles.h +cow_horns.o: ../../config.h +cow_horns.o: $(srcdir)/gllist.h +cow_horns.o: $(srcdir)/jwzglesI.h +cow_horns.o: $(srcdir)/jwzgles.h +cow_tail.o: ../../config.h +cow_tail.o: $(srcdir)/gllist.h +cow_tail.o: $(srcdir)/jwzglesI.h +cow_tail.o: $(srcdir)/jwzgles.h +cow_udder.o: ../../config.h +cow_udder.o: $(srcdir)/gllist.h +cow_udder.o: $(srcdir)/jwzglesI.h +cow_udder.o: $(srcdir)/jwzgles.h +crackberg.o: ../../config.h +crackberg.o: $(HACK_SRC)/fps.h +crackberg.o: $(srcdir)/jwzglesI.h +crackberg.o: $(srcdir)/jwzgles.h +crackberg.o: $(HACK_SRC)/screenhackI.h +crackberg.o: $(UTILS_SRC)/colors.h +crackberg.o: $(UTILS_SRC)/grabscreen.h +crackberg.o: $(UTILS_SRC)/hsv.h +crackberg.o: $(UTILS_SRC)/resources.h +crackberg.o: $(UTILS_SRC)/usleep.h +crackberg.o: $(UTILS_SRC)/visual.h +crackberg.o: $(UTILS_SRC)/xshm.h +crackberg.o: $(UTILS_SRC)/yarandom.h +crackberg.o: $(HACK_SRC)/xlockmoreI.h +crackberg.o: $(HACK_SRC)/xlockmore.h +cube21.o: ../../config.h +cube21.o: $(HACK_SRC)/fps.h +cube21.o: $(srcdir)/gltrackball.h +cube21.o: $(srcdir)/jwzglesI.h +cube21.o: $(srcdir)/jwzgles.h +cube21.o: $(HACK_SRC)/screenhackI.h +cube21.o: $(UTILS_SRC)/colors.h +cube21.o: $(UTILS_SRC)/grabscreen.h +cube21.o: $(UTILS_SRC)/hsv.h +cube21.o: $(UTILS_SRC)/resources.h +cube21.o: $(UTILS_SRC)/usleep.h +cube21.o: $(UTILS_SRC)/visual.h +cube21.o: $(UTILS_SRC)/xshm.h +cube21.o: $(UTILS_SRC)/yarandom.h +cube21.o: $(HACK_SRC)/xlockmoreI.h +cube21.o: $(HACK_SRC)/xlockmore.h +cubenetic.o: ../../config.h +cubenetic.o: $(HACK_SRC)/fps.h +cubenetic.o: $(srcdir)/gltrackball.h +cubenetic.o: $(srcdir)/jwzglesI.h +cubenetic.o: $(srcdir)/jwzgles.h +cubenetic.o: $(srcdir)/rotator.h +cubenetic.o: $(HACK_SRC)/screenhackI.h +cubenetic.o: $(UTILS_SRC)/colors.h +cubenetic.o: $(UTILS_SRC)/grabscreen.h +cubenetic.o: $(UTILS_SRC)/hsv.h +cubenetic.o: $(UTILS_SRC)/resources.h +cubenetic.o: $(UTILS_SRC)/usleep.h +cubenetic.o: $(UTILS_SRC)/visual.h +cubenetic.o: $(UTILS_SRC)/xshm.h +cubenetic.o: $(UTILS_SRC)/yarandom.h +cubenetic.o: $(HACK_SRC)/xlockmoreI.h +cubenetic.o: $(HACK_SRC)/xlockmore.h +cubestorm.o: ../../config.h +cubestorm.o: $(HACK_SRC)/fps.h +cubestorm.o: $(srcdir)/gltrackball.h +cubestorm.o: $(srcdir)/jwzglesI.h +cubestorm.o: $(srcdir)/jwzgles.h +cubestorm.o: $(srcdir)/rotator.h +cubestorm.o: $(HACK_SRC)/screenhackI.h +cubestorm.o: $(UTILS_SRC)/colors.h +cubestorm.o: $(UTILS_SRC)/grabscreen.h +cubestorm.o: $(UTILS_SRC)/hsv.h +cubestorm.o: $(UTILS_SRC)/resources.h +cubestorm.o: $(UTILS_SRC)/usleep.h +cubestorm.o: $(UTILS_SRC)/visual.h +cubestorm.o: $(UTILS_SRC)/xshm.h +cubestorm.o: $(UTILS_SRC)/yarandom.h +cubestorm.o: $(HACK_SRC)/xlockmoreI.h +cubestorm.o: $(HACK_SRC)/xlockmore.h +cubicgrid.o: ../../config.h +cubicgrid.o: $(HACK_SRC)/fps.h +cubicgrid.o: $(srcdir)/gltrackball.h +cubicgrid.o: $(srcdir)/jwzglesI.h +cubicgrid.o: $(srcdir)/jwzgles.h +cubicgrid.o: $(srcdir)/rotator.h +cubicgrid.o: $(HACK_SRC)/screenhackI.h +cubicgrid.o: $(UTILS_SRC)/colors.h +cubicgrid.o: $(UTILS_SRC)/grabscreen.h +cubicgrid.o: $(UTILS_SRC)/hsv.h +cubicgrid.o: $(UTILS_SRC)/resources.h +cubicgrid.o: $(UTILS_SRC)/usleep.h +cubicgrid.o: $(UTILS_SRC)/visual.h +cubicgrid.o: $(UTILS_SRC)/xshm.h +cubicgrid.o: $(UTILS_SRC)/yarandom.h +cubicgrid.o: $(HACK_SRC)/xlockmoreI.h +cubicgrid.o: $(HACK_SRC)/xlockmore.h +dangerball.o: ../../config.h +dangerball.o: $(HACK_SRC)/fps.h +dangerball.o: $(srcdir)/gltrackball.h +dangerball.o: $(srcdir)/jwzglesI.h +dangerball.o: $(srcdir)/jwzgles.h +dangerball.o: $(srcdir)/rotator.h +dangerball.o: $(HACK_SRC)/screenhackI.h +dangerball.o: $(srcdir)/sphere.h +dangerball.o: $(srcdir)/tube.h +dangerball.o: $(UTILS_SRC)/colors.h +dangerball.o: $(UTILS_SRC)/grabscreen.h +dangerball.o: $(UTILS_SRC)/hsv.h +dangerball.o: $(UTILS_SRC)/resources.h +dangerball.o: $(UTILS_SRC)/usleep.h +dangerball.o: $(UTILS_SRC)/visual.h +dangerball.o: $(UTILS_SRC)/xshm.h +dangerball.o: $(UTILS_SRC)/yarandom.h +dangerball.o: $(HACK_SRC)/xlockmoreI.h +dangerball.o: $(HACK_SRC)/xlockmore.h +dnalogo.o: ../../config.h +dnalogo.o: $(srcdir)/dnapizza.h +dnalogo.o: $(HACK_SRC)/fps.h +dnalogo.o: $(srcdir)/gltrackball.h +dnalogo.o: $(srcdir)/jwzglesI.h +dnalogo.o: $(srcdir)/jwzgles.h +dnalogo.o: $(srcdir)/normals.h +dnalogo.o: $(srcdir)/rotator.h +dnalogo.o: $(HACK_SRC)/screenhackI.h +dnalogo.o: $(srcdir)/tube.h +dnalogo.o: $(UTILS_SRC)/colors.h +dnalogo.o: $(UTILS_SRC)/grabscreen.h +dnalogo.o: $(UTILS_SRC)/hsv.h +dnalogo.o: $(UTILS_SRC)/resources.h +dnalogo.o: $(UTILS_SRC)/usleep.h +dnalogo.o: $(UTILS_SRC)/visual.h +dnalogo.o: $(UTILS_SRC)/xshm.h +dnalogo.o: $(UTILS_SRC)/yarandom.h +dnalogo.o: $(HACK_SRC)/xlockmoreI.h +dnalogo.o: $(HACK_SRC)/xlockmore.h +dolphin.o: $(srcdir)/atlantis.h +dolphin.o: ../../config.h +dolphin.o: $(HACK_SRC)/fps.h +dolphin.o: $(srcdir)/jwzglesI.h +dolphin.o: $(srcdir)/jwzgles.h +dolphin.o: $(HACK_SRC)/screenhackI.h +dolphin.o: $(UTILS_SRC)/colors.h +dolphin.o: $(UTILS_SRC)/grabscreen.h +dolphin.o: $(UTILS_SRC)/hsv.h +dolphin.o: $(UTILS_SRC)/resources.h +dolphin.o: $(UTILS_SRC)/usleep.h +dolphin.o: $(UTILS_SRC)/visual.h +dolphin.o: $(UTILS_SRC)/yarandom.h +dropshadow.o: ../../config.h +dropshadow.o: $(srcdir)/dropshadow.h +dropshadow.o: $(srcdir)/jwzglesI.h +dropshadow.o: $(srcdir)/jwzgles.h +endgame.o: $(srcdir)/chessgames.h +endgame.o: $(srcdir)/chessmodels.h +endgame.o: ../../config.h +endgame.o: $(HACK_SRC)/fps.h +endgame.o: $(srcdir)/gltrackball.h +endgame.o: $(srcdir)/jwzglesI.h +endgame.o: $(srcdir)/jwzgles.h +endgame.o: $(HACK_SRC)/screenhackI.h +endgame.o: $(UTILS_SRC)/colors.h +endgame.o: $(UTILS_SRC)/grabscreen.h +endgame.o: $(UTILS_SRC)/hsv.h +endgame.o: $(UTILS_SRC)/resources.h +endgame.o: $(UTILS_SRC)/usleep.h +endgame.o: $(UTILS_SRC)/visual.h +endgame.o: $(UTILS_SRC)/xshm.h +endgame.o: $(UTILS_SRC)/yarandom.h +endgame.o: $(HACK_SRC)/xlockmoreI.h +endgame.o: $(HACK_SRC)/xlockmore.h +engine.o: ../../config.h +engine.o: $(HACK_SRC)/fps.h +engine.o: $(srcdir)/gltrackball.h +engine.o: $(srcdir)/glxfonts.h +engine.o: $(srcdir)/jwzglesI.h +engine.o: $(srcdir)/jwzgles.h +engine.o: $(srcdir)/rotator.h +engine.o: $(HACK_SRC)/screenhackI.h +engine.o: $(srcdir)/texfont.h +engine.o: $(UTILS_SRC)/colors.h +engine.o: $(UTILS_SRC)/grabscreen.h +engine.o: $(UTILS_SRC)/hsv.h +engine.o: $(UTILS_SRC)/resources.h +engine.o: $(UTILS_SRC)/usleep.h +engine.o: $(UTILS_SRC)/visual.h +engine.o: $(UTILS_SRC)/xshm.h +engine.o: $(UTILS_SRC)/yarandom.h +engine.o: $(HACK_SRC)/xlockmoreI.h +engine.o: $(HACK_SRC)/xlockmore.h +extrusion-helix2.o: ../../config.h +extrusion-helix2.o: $(srcdir)/extrusion.h +extrusion-helix2.o: $(srcdir)/jwzglesI.h +extrusion-helix2.o: $(srcdir)/jwzgles.h +extrusion-helix3.o: ../../config.h +extrusion-helix3.o: $(srcdir)/extrusion.h +extrusion-helix3.o: $(srcdir)/jwzglesI.h +extrusion-helix3.o: $(srcdir)/jwzgles.h +extrusion-helix4.o: ../../config.h +extrusion-helix4.o: $(srcdir)/extrusion.h +extrusion-helix4.o: $(srcdir)/jwzglesI.h +extrusion-helix4.o: $(srcdir)/jwzgles.h +extrusion-joinoffset.o: ../../config.h +extrusion-joinoffset.o: $(srcdir)/extrusion.h +extrusion-joinoffset.o: $(srcdir)/jwzglesI.h +extrusion-joinoffset.o: $(srcdir)/jwzgles.h +extrusion.o: ../../config.h +extrusion.o: $(srcdir)/extrusion.h +extrusion.o: $(HACK_SRC)/fps.h +extrusion.o: $(srcdir)/gltrackball.h +extrusion.o: $(srcdir)/jwzglesI.h +extrusion.o: $(srcdir)/jwzgles.h +extrusion.o: $(srcdir)/rotator.h +extrusion.o: $(HACK_SRC)/screenhackI.h +extrusion.o: $(UTILS_SRC)/colors.h +extrusion.o: $(UTILS_SRC)/grabscreen.h +extrusion.o: $(UTILS_SRC)/hsv.h +extrusion.o: $(UTILS_SRC)/resources.h +extrusion.o: $(UTILS_SRC)/usleep.h +extrusion.o: $(UTILS_SRC)/visual.h +extrusion.o: $(UTILS_SRC)/xshm.h +extrusion.o: $(UTILS_SRC)/yarandom.h +extrusion.o: $(HACK_SRC)/xlockmoreI.h +extrusion.o: $(HACK_SRC)/xlockmore.h +extrusion.o: $(srcdir)/xpm-ximage.h +extrusion-screw.o: ../../config.h +extrusion-screw.o: $(srcdir)/extrusion.h +extrusion-screw.o: $(srcdir)/jwzglesI.h +extrusion-screw.o: $(srcdir)/jwzgles.h +extrusion-taper.o: ../../config.h +extrusion-taper.o: $(srcdir)/extrusion.h +extrusion-taper.o: $(srcdir)/jwzglesI.h +extrusion-taper.o: $(srcdir)/jwzgles.h +extrusion-twistoid.o: ../../config.h +extrusion-twistoid.o: $(srcdir)/extrusion.h +extrusion-twistoid.o: $(srcdir)/jwzglesI.h +extrusion-twistoid.o: $(srcdir)/jwzgles.h +flipflop.o: ../../config.h +flipflop.o: $(HACK_SRC)/fps.h +flipflop.o: $(srcdir)/gltrackball.h +flipflop.o: $(srcdir)/grab-ximage.h +flipflop.o: $(srcdir)/jwzglesI.h +flipflop.o: $(srcdir)/jwzgles.h +flipflop.o: $(HACK_SRC)/screenhackI.h +flipflop.o: $(UTILS_SRC)/colors.h +flipflop.o: $(UTILS_SRC)/grabscreen.h +flipflop.o: $(UTILS_SRC)/hsv.h +flipflop.o: $(UTILS_SRC)/resources.h +flipflop.o: $(UTILS_SRC)/usleep.h +flipflop.o: $(UTILS_SRC)/visual.h +flipflop.o: $(UTILS_SRC)/xshm.h +flipflop.o: $(UTILS_SRC)/yarandom.h +flipflop.o: $(HACK_SRC)/xlockmoreI.h +flipflop.o: $(HACK_SRC)/xlockmore.h +flipscreen3d.o: ../../config.h +flipscreen3d.o: $(HACK_SRC)/fps.h +flipscreen3d.o: $(srcdir)/gltrackball.h +flipscreen3d.o: $(srcdir)/grab-ximage.h +flipscreen3d.o: $(srcdir)/jwzglesI.h +flipscreen3d.o: $(srcdir)/jwzgles.h +flipscreen3d.o: $(HACK_SRC)/screenhackI.h +flipscreen3d.o: $(UTILS_SRC)/colors.h +flipscreen3d.o: $(UTILS_SRC)/grabscreen.h +flipscreen3d.o: $(UTILS_SRC)/hsv.h +flipscreen3d.o: $(UTILS_SRC)/resources.h +flipscreen3d.o: $(UTILS_SRC)/usleep.h +flipscreen3d.o: $(UTILS_SRC)/visual.h +flipscreen3d.o: $(UTILS_SRC)/xshm.h +flipscreen3d.o: $(UTILS_SRC)/yarandom.h +flipscreen3d.o: $(HACK_SRC)/xlockmoreI.h +flipscreen3d.o: $(HACK_SRC)/xlockmore.h +fliptext.o: ../../config.h +fliptext.o: $(HACK_SRC)/fps.h +fliptext.o: $(srcdir)/jwzglesI.h +fliptext.o: $(srcdir)/jwzgles.h +fliptext.o: $(HACK_SRC)/screenhackI.h +fliptext.o: $(srcdir)/texfont.h +fliptext.o: $(UTILS_SRC)/colors.h +fliptext.o: $(UTILS_SRC)/grabscreen.h +fliptext.o: $(UTILS_SRC)/hsv.h +fliptext.o: $(UTILS_SRC)/resources.h +fliptext.o: $(UTILS_SRC)/textclient.h +fliptext.o: $(UTILS_SRC)/usleep.h +fliptext.o: $(UTILS_SRC)/visual.h +fliptext.o: $(UTILS_SRC)/xshm.h +fliptext.o: $(UTILS_SRC)/yarandom.h +fliptext.o: $(HACK_SRC)/xlockmoreI.h +fliptext.o: $(HACK_SRC)/xlockmore.h +flurry.o: ../../config.h +flurry.o: $(srcdir)/flurry.h +flurry.o: $(HACK_SRC)/fps.h +flurry.o: $(srcdir)/gltrackball.h +flurry.o: $(srcdir)/jwzglesI.h +flurry.o: $(srcdir)/jwzgles.h +flurry.o: $(srcdir)/rotator.h +flurry.o: $(HACK_SRC)/screenhackI.h +flurry.o: $(UTILS_SRC)/colors.h +flurry.o: $(UTILS_SRC)/grabscreen.h +flurry.o: $(UTILS_SRC)/hsv.h +flurry.o: $(UTILS_SRC)/resources.h +flurry.o: $(UTILS_SRC)/usleep.h +flurry.o: $(UTILS_SRC)/visual.h +flurry.o: $(UTILS_SRC)/xshm.h +flurry.o: $(UTILS_SRC)/yarandom.h +flurry.o: $(HACK_SRC)/xlockmoreI.h +flurry.o: $(HACK_SRC)/xlockmore.h +flurry-smoke.o: ../../config.h +flurry-smoke.o: $(srcdir)/flurry.h +flurry-smoke.o: $(srcdir)/gltrackball.h +flurry-smoke.o: $(srcdir)/jwzglesI.h +flurry-smoke.o: $(srcdir)/jwzgles.h +flurry-smoke.o: $(srcdir)/rotator.h +flurry-smoke.o: $(UTILS_SRC)/yarandom.h +flurry-spark.o: ../../config.h +flurry-spark.o: $(srcdir)/flurry.h +flurry-spark.o: $(srcdir)/gltrackball.h +flurry-spark.o: $(srcdir)/jwzglesI.h +flurry-spark.o: $(srcdir)/jwzgles.h +flurry-spark.o: $(srcdir)/rotator.h +flurry-spark.o: $(UTILS_SRC)/yarandom.h +flurry-star.o: ../../config.h +flurry-star.o: $(srcdir)/flurry.h +flurry-star.o: $(srcdir)/gltrackball.h +flurry-star.o: $(srcdir)/jwzglesI.h +flurry-star.o: $(srcdir)/jwzgles.h +flurry-star.o: $(srcdir)/rotator.h +flurry-star.o: $(UTILS_SRC)/yarandom.h +flurry-texture.o: ../../config.h +flurry-texture.o: $(srcdir)/flurry.h +flurry-texture.o: $(srcdir)/gltrackball.h +flurry-texture.o: $(srcdir)/jwzglesI.h +flurry-texture.o: $(srcdir)/jwzgles.h +flurry-texture.o: $(srcdir)/rotator.h +flurry-texture.o: $(UTILS_SRC)/yarandom.h +flyingtoasters.o: ../../config.h +flyingtoasters.o: $(HACK_SRC)/fps.h +flyingtoasters.o: $(srcdir)/gllist.h +flyingtoasters.o: $(srcdir)/gltrackball.h +flyingtoasters.o: $(HACK_SRC)/images/chromesphere.xpm +flyingtoasters.o: $(HACK_SRC)/images/toast.xpm +flyingtoasters.o: $(srcdir)/jwzglesI.h +flyingtoasters.o: $(srcdir)/jwzgles.h +flyingtoasters.o: $(HACK_SRC)/screenhackI.h +flyingtoasters.o: $(UTILS_SRC)/colors.h +flyingtoasters.o: $(UTILS_SRC)/grabscreen.h +flyingtoasters.o: $(UTILS_SRC)/hsv.h +flyingtoasters.o: $(UTILS_SRC)/resources.h +flyingtoasters.o: $(UTILS_SRC)/usleep.h +flyingtoasters.o: $(UTILS_SRC)/visual.h +flyingtoasters.o: $(UTILS_SRC)/xshm.h +flyingtoasters.o: $(UTILS_SRC)/yarandom.h +flyingtoasters.o: $(HACK_SRC)/xlockmoreI.h +flyingtoasters.o: $(HACK_SRC)/xlockmore.h +flyingtoasters.o: $(srcdir)/xpm-ximage.h +font-ximage.o: ../../config.h +font-ximage.o: $(srcdir)/font-ximage.h +font-ximage.o: $(srcdir)/jwzglesI.h +font-ximage.o: $(srcdir)/jwzgles.h +fps-gl.o: ../../config.h +fps-gl.o: $(HACK_SRC)/fpsI.h +fps-gl.o: $(HACK_SRC)/fps.h +fps-gl.o: $(srcdir)/glxfonts.h +fps-gl.o: $(srcdir)/jwzglesI.h +fps-gl.o: $(srcdir)/jwzgles.h +fps-gl.o: $(HACK_SRC)/screenhackI.h +fps-gl.o: $(srcdir)/texfont.h +fps-gl.o: $(UTILS_SRC)/colors.h +fps-gl.o: $(UTILS_SRC)/grabscreen.h +fps-gl.o: $(UTILS_SRC)/hsv.h +fps-gl.o: $(UTILS_SRC)/resources.h +fps-gl.o: $(UTILS_SRC)/usleep.h +fps-gl.o: $(UTILS_SRC)/visual.h +fps-gl.o: $(UTILS_SRC)/xshm.h +fps-gl.o: $(UTILS_SRC)/yarandom.h +fps-gl.o: $(HACK_SRC)/xlockmoreI.h +gears.o: ../../config.h +gears.o: $(HACK_SRC)/fps.h +gears.o: $(srcdir)/gltrackball.h +gears.o: $(srcdir)/involute.h +gears.o: $(srcdir)/jwzglesI.h +gears.o: $(srcdir)/jwzgles.h +gears.o: $(srcdir)/normals.h +gears.o: $(srcdir)/rotator.h +gears.o: $(HACK_SRC)/screenhackI.h +gears.o: $(srcdir)/tube.h +gears.o: $(UTILS_SRC)/colors.h +gears.o: $(UTILS_SRC)/grabscreen.h +gears.o: $(UTILS_SRC)/hsv.h +gears.o: $(UTILS_SRC)/resources.h +gears.o: $(UTILS_SRC)/usleep.h +gears.o: $(UTILS_SRC)/visual.h +gears.o: $(UTILS_SRC)/xshm.h +gears.o: $(UTILS_SRC)/yarandom.h +gears.o: $(HACK_SRC)/xlockmoreI.h +gears.o: $(HACK_SRC)/xlockmore.h +gflux.o: ../../config.h +gflux.o: $(HACK_SRC)/fps.h +gflux.o: $(srcdir)/gltrackball.h +gflux.o: $(srcdir)/grab-ximage.h +gflux.o: $(srcdir)/jwzglesI.h +gflux.o: $(srcdir)/jwzgles.h +gflux.o: $(HACK_SRC)/screenhackI.h +gflux.o: $(UTILS_SRC)/colors.h +gflux.o: $(UTILS_SRC)/grabscreen.h +gflux.o: $(UTILS_SRC)/hsv.h +gflux.o: $(UTILS_SRC)/resources.h +gflux.o: $(UTILS_SRC)/usleep.h +gflux.o: $(UTILS_SRC)/visual.h +gflux.o: $(UTILS_SRC)/xshm.h +gflux.o: $(UTILS_SRC)/yarandom.h +gflux.o: $(HACK_SRC)/xlockmoreI.h +gflux.o: $(HACK_SRC)/xlockmore.h +glblur.o: ../../config.h +glblur.o: $(HACK_SRC)/fps.h +glblur.o: $(srcdir)/gltrackball.h +glblur.o: $(srcdir)/jwzglesI.h +glblur.o: $(srcdir)/jwzgles.h +glblur.o: $(srcdir)/rotator.h +glblur.o: $(HACK_SRC)/screenhackI.h +glblur.o: $(UTILS_SRC)/colors.h +glblur.o: $(UTILS_SRC)/grabscreen.h +glblur.o: $(UTILS_SRC)/hsv.h +glblur.o: $(UTILS_SRC)/resources.h +glblur.o: $(UTILS_SRC)/usleep.h +glblur.o: $(UTILS_SRC)/visual.h +glblur.o: $(UTILS_SRC)/xshm.h +glblur.o: $(UTILS_SRC)/yarandom.h +glblur.o: $(HACK_SRC)/xlockmoreI.h +glblur.o: $(HACK_SRC)/xlockmore.h +glcells.o: ../../config.h +glcells.o: $(HACK_SRC)/fps.h +glcells.o: $(srcdir)/jwzglesI.h +glcells.o: $(srcdir)/jwzgles.h +glcells.o: $(HACK_SRC)/screenhackI.h +glcells.o: $(UTILS_SRC)/colors.h +glcells.o: $(UTILS_SRC)/grabscreen.h +glcells.o: $(UTILS_SRC)/hsv.h +glcells.o: $(UTILS_SRC)/resources.h +glcells.o: $(UTILS_SRC)/usleep.h +glcells.o: $(UTILS_SRC)/visual.h +glcells.o: $(UTILS_SRC)/xshm.h +glcells.o: $(UTILS_SRC)/yarandom.h +glcells.o: $(HACK_SRC)/xlockmoreI.h +glcells.o: $(HACK_SRC)/xlockmore.h +gleidescope.o: ../../config.h +gleidescope.o: $(HACK_SRC)/fps.h +gleidescope.o: $(srcdir)/grab-ximage.h +gleidescope.o: $(srcdir)/jwzglesI.h +gleidescope.o: $(srcdir)/jwzgles.h +gleidescope.o: $(HACK_SRC)/screenhackI.h +gleidescope.o: $(UTILS_SRC)/colors.h +gleidescope.o: $(UTILS_SRC)/grabscreen.h +gleidescope.o: $(UTILS_SRC)/hsv.h +gleidescope.o: $(UTILS_SRC)/resources.h +gleidescope.o: $(UTILS_SRC)/usleep.h +gleidescope.o: $(UTILS_SRC)/visual.h +gleidescope.o: $(UTILS_SRC)/xshm.h +gleidescope.o: $(UTILS_SRC)/yarandom.h +gleidescope.o: $(HACK_SRC)/xlockmoreI.h +gleidescope.o: $(HACK_SRC)/xlockmore.h +gleidescope.o: $(srcdir)/xpm-ximage.h +glforestfire.o: ../../config.h +glforestfire.o: $(HACK_SRC)/fps.h +glforestfire.o: $(srcdir)/gltrackball.h +glforestfire.o: $(HACK_SRC)/images/ground.xpm +glforestfire.o: $(HACK_SRC)/images/tree.xpm +glforestfire.o: $(srcdir)/jwzglesI.h +glforestfire.o: $(srcdir)/jwzgles.h +glforestfire.o: $(HACK_SRC)/screenhackI.h +glforestfire.o: $(UTILS_SRC)/colors.h +glforestfire.o: $(UTILS_SRC)/grabscreen.h +glforestfire.o: $(UTILS_SRC)/hsv.h +glforestfire.o: $(UTILS_SRC)/resources.h +glforestfire.o: $(UTILS_SRC)/usleep.h +glforestfire.o: $(UTILS_SRC)/visual.h +glforestfire.o: $(UTILS_SRC)/xshm.h +glforestfire.o: $(UTILS_SRC)/yarandom.h +glforestfire.o: $(HACK_SRC)/xlockmoreI.h +glforestfire.o: $(HACK_SRC)/xlockmore.h +glforestfire.o: $(srcdir)/xpm-ximage.h +glhanoi.o: ../../config.h +glhanoi.o: $(HACK_SRC)/fps.h +glhanoi.o: $(srcdir)/jwzglesI.h +glhanoi.o: $(srcdir)/jwzgles.h +glhanoi.o: $(srcdir)/rotator.h +glhanoi.o: $(HACK_SRC)/screenhackI.h +glhanoi.o: $(UTILS_SRC)/colors.h +glhanoi.o: $(UTILS_SRC)/grabscreen.h +glhanoi.o: $(UTILS_SRC)/hsv.h +glhanoi.o: $(UTILS_SRC)/resources.h +glhanoi.o: $(UTILS_SRC)/usleep.h +glhanoi.o: $(UTILS_SRC)/visual.h +glhanoi.o: $(UTILS_SRC)/xshm.h +glhanoi.o: $(UTILS_SRC)/yarandom.h +glhanoi.o: $(HACK_SRC)/xlockmoreI.h +glhanoi.o: $(HACK_SRC)/xlockmore.h +glknots.o: ../../config.h +glknots.o: $(HACK_SRC)/fps.h +glknots.o: $(srcdir)/gltrackball.h +glknots.o: $(srcdir)/jwzglesI.h +glknots.o: $(srcdir)/jwzgles.h +glknots.o: $(srcdir)/rotator.h +glknots.o: $(HACK_SRC)/screenhackI.h +glknots.o: $(srcdir)/tube.h +glknots.o: $(UTILS_SRC)/colors.h +glknots.o: $(UTILS_SRC)/grabscreen.h +glknots.o: $(UTILS_SRC)/hsv.h +glknots.o: $(UTILS_SRC)/resources.h +glknots.o: $(UTILS_SRC)/usleep.h +glknots.o: $(UTILS_SRC)/visual.h +glknots.o: $(UTILS_SRC)/xshm.h +glknots.o: $(UTILS_SRC)/yarandom.h +glknots.o: $(HACK_SRC)/xlockmoreI.h +glknots.o: $(HACK_SRC)/xlockmore.h +gllist.o: ../../config.h +gllist.o: $(srcdir)/gllist.h +gllist.o: $(srcdir)/jwzglesI.h +gllist.o: $(srcdir)/jwzgles.h +glmatrix.o: ../../config.h +glmatrix.o: $(HACK_SRC)/fps.h +glmatrix.o: $(HACK_SRC)/images/matrix3.xpm +glmatrix.o: $(srcdir)/jwzglesI.h +glmatrix.o: $(srcdir)/jwzgles.h +glmatrix.o: $(HACK_SRC)/screenhackI.h +glmatrix.o: $(UTILS_SRC)/colors.h +glmatrix.o: $(UTILS_SRC)/grabscreen.h +glmatrix.o: $(UTILS_SRC)/hsv.h +glmatrix.o: $(UTILS_SRC)/resources.h +glmatrix.o: $(UTILS_SRC)/usleep.h +glmatrix.o: $(UTILS_SRC)/visual.h +glmatrix.o: $(UTILS_SRC)/xshm.h +glmatrix.o: $(UTILS_SRC)/yarandom.h +glmatrix.o: $(HACK_SRC)/xlockmoreI.h +glmatrix.o: $(HACK_SRC)/xlockmore.h +glmatrix.o: $(srcdir)/xpm-ximage.h +glplanet.o: ../../config.h +glplanet.o: $(HACK_SRC)/fps.h +glplanet.o: $(srcdir)/gltrackball.h +glplanet.o: $(HACK_SRC)/images/earth.xpm +glplanet.o: $(srcdir)/jwzglesI.h +glplanet.o: $(srcdir)/jwzgles.h +glplanet.o: $(srcdir)/rotator.h +glplanet.o: $(HACK_SRC)/screenhackI.h +glplanet.o: $(srcdir)/sphere.h +glplanet.o: $(UTILS_SRC)/colors.h +glplanet.o: $(UTILS_SRC)/grabscreen.h +glplanet.o: $(UTILS_SRC)/hsv.h +glplanet.o: $(UTILS_SRC)/resources.h +glplanet.o: $(UTILS_SRC)/usleep.h +glplanet.o: $(UTILS_SRC)/visual.h +glplanet.o: $(UTILS_SRC)/xshm.h +glplanet.o: $(UTILS_SRC)/yarandom.h +glplanet.o: $(HACK_SRC)/xlockmoreI.h +glplanet.o: $(HACK_SRC)/xlockmore.h +glplanet.o: $(srcdir)/xpm-ximage.h +glschool_alg.o: ../../config.h +glschool_alg.o: $(srcdir)/glschool_alg.h +glschool_alg.o: $(UTILS_SRC)/yarandom.h +glschool_gl.o: ../../config.h +glschool_gl.o: $(srcdir)/glschool_alg.h +glschool_gl.o: $(srcdir)/glschool_gl.h +glschool_gl.o: $(srcdir)/jwzglesI.h +glschool_gl.o: $(srcdir)/jwzgles.h +glschool_gl.o: $(srcdir)/sphere.h +glschool_gl.o: $(srcdir)/tube.h +glschool.o: ../../config.h +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: $(srcdir)/jwzglesI.h +glschool.o: $(srcdir)/jwzgles.h +glschool.o: $(HACK_SRC)/screenhackI.h +glschool.o: $(UTILS_SRC)/colors.h +glschool.o: $(UTILS_SRC)/grabscreen.h +glschool.o: $(UTILS_SRC)/hsv.h +glschool.o: $(UTILS_SRC)/resources.h +glschool.o: $(UTILS_SRC)/usleep.h +glschool.o: $(UTILS_SRC)/visual.h +glschool.o: $(UTILS_SRC)/xshm.h +glschool.o: $(UTILS_SRC)/yarandom.h +glschool.o: $(HACK_SRC)/xlockmoreI.h +glschool.o: $(HACK_SRC)/xlockmore.h +glslideshow.o: ../../config.h +glslideshow.o: $(HACK_SRC)/fps.h +glslideshow.o: $(srcdir)/glxfonts.h +glslideshow.o: $(srcdir)/grab-ximage.h +glslideshow.o: $(srcdir)/jwzglesI.h +glslideshow.o: $(srcdir)/jwzgles.h +glslideshow.o: $(HACK_SRC)/screenhackI.h +glslideshow.o: $(srcdir)/texfont.h +glslideshow.o: $(UTILS_SRC)/colors.h +glslideshow.o: $(UTILS_SRC)/grabscreen.h +glslideshow.o: $(UTILS_SRC)/hsv.h +glslideshow.o: $(UTILS_SRC)/resources.h +glslideshow.o: $(UTILS_SRC)/usleep.h +glslideshow.o: $(UTILS_SRC)/visual.h +glslideshow.o: $(UTILS_SRC)/xshm.h +glslideshow.o: $(UTILS_SRC)/yarandom.h +glslideshow.o: $(HACK_SRC)/xlockmoreI.h +glslideshow.o: $(HACK_SRC)/xlockmore.h +glsnake.o: ../../config.h +glsnake.o: $(HACK_SRC)/fps.h +glsnake.o: $(srcdir)/glxfonts.h +glsnake.o: $(srcdir)/jwzglesI.h +glsnake.o: $(srcdir)/jwzgles.h +glsnake.o: $(HACK_SRC)/screenhackI.h +glsnake.o: $(srcdir)/texfont.h +glsnake.o: $(UTILS_SRC)/colors.h +glsnake.o: $(UTILS_SRC)/grabscreen.h +glsnake.o: $(UTILS_SRC)/hsv.h +glsnake.o: $(UTILS_SRC)/resources.h +glsnake.o: $(UTILS_SRC)/usleep.h +glsnake.o: $(UTILS_SRC)/visual.h +glsnake.o: $(UTILS_SRC)/xshm.h +glsnake.o: $(UTILS_SRC)/yarandom.h +glsnake.o: $(HACK_SRC)/xlockmoreI.h +glsnake.o: $(HACK_SRC)/xlockmore.h +gltext.o: ../../config.h +gltext.o: $(HACK_SRC)/fps.h +gltext.o: $(srcdir)/gltrackball.h +gltext.o: $(srcdir)/glut_roman.h +gltext.o: $(srcdir)/glutstroke.h +gltext.o: $(srcdir)/jwzglesI.h +gltext.o: $(srcdir)/jwzgles.h +gltext.o: $(srcdir)/rotator.h +gltext.o: $(HACK_SRC)/screenhackI.h +gltext.o: $(srcdir)/sphere.h +gltext.o: $(srcdir)/tube.h +gltext.o: $(UTILS_SRC)/colors.h +gltext.o: $(UTILS_SRC)/grabscreen.h +gltext.o: $(UTILS_SRC)/hsv.h +gltext.o: $(UTILS_SRC)/resources.h +gltext.o: $(UTILS_SRC)/textclient.h +gltext.o: $(UTILS_SRC)/usleep.h +gltext.o: $(UTILS_SRC)/visual.h +gltext.o: $(UTILS_SRC)/xshm.h +gltext.o: $(UTILS_SRC)/yarandom.h +gltext.o: $(HACK_SRC)/xlockmoreI.h +gltext.o: $(HACK_SRC)/xlockmore.h +gltrackball.o: ../../config.h +gltrackball.o: $(srcdir)/gltrackball.h +gltrackball.o: $(srcdir)/jwzglesI.h +gltrackball.o: $(srcdir)/jwzgles.h +gltrackball.o: $(srcdir)/trackball.h +glut_stroke.o: ../../config.h +glut_stroke.o: $(srcdir)/glutstroke.h +glut_stroke.o: $(srcdir)/jwzglesI.h +glut_stroke.o: $(srcdir)/jwzgles.h +glut_swidth.o: ../../config.h +glut_swidth.o: $(srcdir)/glutstroke.h +glut_swidth.o: $(srcdir)/jwzglesI.h +glut_swidth.o: $(srcdir)/jwzgles.h +glxfonts.o: ../../config.h +glxfonts.o: $(HACK_SRC)/fps.h +glxfonts.o: $(srcdir)/glxfonts.h +glxfonts.o: $(srcdir)/jwzglesI.h +glxfonts.o: $(srcdir)/jwzgles.h +glxfonts.o: $(srcdir)/texfont.h +glxfonts.o: $(UTILS_SRC)/resources.h +grab-ximage.o: ../../config.h +grab-ximage.o: $(srcdir)/grab-ximage.h +grab-ximage.o: $(srcdir)/jwzglesI.h +grab-ximage.o: $(srcdir)/jwzgles.h +grab-ximage.o: $(UTILS_SRC)/grabscreen.h +grab-ximage.o: $(UTILS_SRC)/resources.h +grab-ximage.o: $(UTILS_SRC)/visual.h +grab-ximage.o: $(UTILS_SRC)/xshm.h +hilbert.o: ../../config.h +hilbert.o: $(HACK_SRC)/fps.h +hilbert.o: $(srcdir)/gltrackball.h +hilbert.o: $(srcdir)/jwzglesI.h +hilbert.o: $(srcdir)/jwzgles.h +hilbert.o: $(srcdir)/rotator.h +hilbert.o: $(HACK_SRC)/screenhackI.h +hilbert.o: $(srcdir)/sphere.h +hilbert.o: $(srcdir)/tube.h +hilbert.o: $(UTILS_SRC)/colors.h +hilbert.o: $(UTILS_SRC)/grabscreen.h +hilbert.o: $(UTILS_SRC)/hsv.h +hilbert.o: $(UTILS_SRC)/resources.h +hilbert.o: $(UTILS_SRC)/usleep.h +hilbert.o: $(UTILS_SRC)/visual.h +hilbert.o: $(UTILS_SRC)/xshm.h +hilbert.o: $(UTILS_SRC)/yarandom.h +hilbert.o: $(HACK_SRC)/xlockmoreI.h +hilbert.o: $(HACK_SRC)/xlockmore.h +hypertorus.o: ../../config.h +hypertorus.o: $(HACK_SRC)/fps.h +hypertorus.o: $(srcdir)/gltrackball.h +hypertorus.o: $(srcdir)/jwzglesI.h +hypertorus.o: $(srcdir)/jwzgles.h +hypertorus.o: $(HACK_SRC)/screenhackI.h +hypertorus.o: $(UTILS_SRC)/colors.h +hypertorus.o: $(UTILS_SRC)/grabscreen.h +hypertorus.o: $(UTILS_SRC)/hsv.h +hypertorus.o: $(UTILS_SRC)/resources.h +hypertorus.o: $(UTILS_SRC)/usleep.h +hypertorus.o: $(UTILS_SRC)/visual.h +hypertorus.o: $(UTILS_SRC)/xshm.h +hypertorus.o: $(UTILS_SRC)/yarandom.h +hypertorus.o: $(HACK_SRC)/xlockmoreI.h +hypertorus.o: $(HACK_SRC)/xlockmore.h +hypnowheel.o: ../../config.h +hypnowheel.o: $(HACK_SRC)/fps.h +hypnowheel.o: $(srcdir)/jwzglesI.h +hypnowheel.o: $(srcdir)/jwzgles.h +hypnowheel.o: $(srcdir)/rotator.h +hypnowheel.o: $(HACK_SRC)/screenhackI.h +hypnowheel.o: $(UTILS_SRC)/colors.h +hypnowheel.o: $(UTILS_SRC)/grabscreen.h +hypnowheel.o: $(UTILS_SRC)/hsv.h +hypnowheel.o: $(UTILS_SRC)/resources.h +hypnowheel.o: $(UTILS_SRC)/usleep.h +hypnowheel.o: $(UTILS_SRC)/visual.h +hypnowheel.o: $(UTILS_SRC)/xshm.h +hypnowheel.o: $(UTILS_SRC)/yarandom.h +hypnowheel.o: $(HACK_SRC)/xlockmoreI.h +hypnowheel.o: $(HACK_SRC)/xlockmore.h +involute.o: ../../config.h +involute.o: $(HACK_SRC)/fps.h +involute.o: $(srcdir)/involute.h +involute.o: $(srcdir)/jwzglesI.h +involute.o: $(srcdir)/jwzgles.h +involute.o: $(srcdir)/normals.h +involute.o: $(HACK_SRC)/screenhackI.h +involute.o: $(UTILS_SRC)/colors.h +involute.o: $(UTILS_SRC)/grabscreen.h +involute.o: $(UTILS_SRC)/hsv.h +involute.o: $(UTILS_SRC)/resources.h +involute.o: $(UTILS_SRC)/usleep.h +involute.o: $(UTILS_SRC)/visual.h +involute.o: $(UTILS_SRC)/yarandom.h +jigglypuff.o: ../../config.h +jigglypuff.o: $(HACK_SRC)/fps.h +jigglypuff.o: $(srcdir)/gltrackball.h +jigglypuff.o: $(HACK_SRC)/images/jigglymap.xpm +jigglypuff.o: $(srcdir)/jwzglesI.h +jigglypuff.o: $(srcdir)/jwzgles.h +jigglypuff.o: $(HACK_SRC)/screenhackI.h +jigglypuff.o: $(UTILS_SRC)/colors.h +jigglypuff.o: $(UTILS_SRC)/grabscreen.h +jigglypuff.o: $(UTILS_SRC)/hsv.h +jigglypuff.o: $(UTILS_SRC)/resources.h +jigglypuff.o: $(UTILS_SRC)/usleep.h +jigglypuff.o: $(UTILS_SRC)/visual.h +jigglypuff.o: $(UTILS_SRC)/xshm.h +jigglypuff.o: $(UTILS_SRC)/yarandom.h +jigglypuff.o: $(HACK_SRC)/xlockmoreI.h +jigglypuff.o: $(HACK_SRC)/xlockmore.h +jigglypuff.o: $(srcdir)/xpm-ximage.h +jigsaw.o: ../../config.h +jigsaw.o: $(HACK_SRC)/fps.h +jigsaw.o: $(srcdir)/gltrackball.h +jigsaw.o: $(srcdir)/grab-ximage.h +jigsaw.o: $(srcdir)/jwzglesI.h +jigsaw.o: $(srcdir)/jwzgles.h +jigsaw.o: $(srcdir)/normals.h +jigsaw.o: $(srcdir)/rotator.h +jigsaw.o: $(HACK_SRC)/screenhackI.h +jigsaw.o: $(srcdir)/texfont.h +jigsaw.o: $(UTILS_SRC)/colors.h +jigsaw.o: $(UTILS_SRC)/grabscreen.h +jigsaw.o: $(UTILS_SRC)/hsv.h +jigsaw.o: $(UTILS_SRC)/resources.h +jigsaw.o: $(UTILS_SRC)/spline.h +jigsaw.o: $(UTILS_SRC)/usleep.h +jigsaw.o: $(UTILS_SRC)/visual.h +jigsaw.o: $(UTILS_SRC)/xshm.h +jigsaw.o: $(UTILS_SRC)/yarandom.h +jigsaw.o: $(HACK_SRC)/xlockmoreI.h +jigsaw.o: $(HACK_SRC)/xlockmore.h +juggler3d.o: ../../config.h +juggler3d.o: $(HACK_SRC)/fps.h +juggler3d.o: $(srcdir)/gltrackball.h +juggler3d.o: $(srcdir)/glxfonts.h +juggler3d.o: $(srcdir)/jwzglesI.h +juggler3d.o: $(srcdir)/jwzgles.h +juggler3d.o: $(srcdir)/rotator.h +juggler3d.o: $(HACK_SRC)/screenhackI.h +juggler3d.o: $(srcdir)/sphere.h +juggler3d.o: $(srcdir)/texfont.h +juggler3d.o: $(srcdir)/tube.h +juggler3d.o: $(UTILS_SRC)/colors.h +juggler3d.o: $(UTILS_SRC)/grabscreen.h +juggler3d.o: $(UTILS_SRC)/hsv.h +juggler3d.o: $(UTILS_SRC)/resources.h +juggler3d.o: $(UTILS_SRC)/usleep.h +juggler3d.o: $(UTILS_SRC)/visual.h +juggler3d.o: $(UTILS_SRC)/xshm.h +juggler3d.o: $(UTILS_SRC)/yarandom.h +juggler3d.o: $(HACK_SRC)/xlockmoreI.h +juggler3d.o: $(HACK_SRC)/xlockmore.h +jwzgles.o: ../../config.h +jwzgles.o: $(srcdir)/jwzglesI.h +klein.o: ../../config.h +klein.o: $(HACK_SRC)/fps.h +klein.o: $(srcdir)/gltrackball.h +klein.o: $(srcdir)/jwzglesI.h +klein.o: $(srcdir)/jwzgles.h +klein.o: $(HACK_SRC)/screenhackI.h +klein.o: $(UTILS_SRC)/colors.h +klein.o: $(UTILS_SRC)/grabscreen.h +klein.o: $(UTILS_SRC)/hsv.h +klein.o: $(UTILS_SRC)/resources.h +klein.o: $(UTILS_SRC)/usleep.h +klein.o: $(UTILS_SRC)/visual.h +klein.o: $(UTILS_SRC)/xshm.h +klein.o: $(UTILS_SRC)/yarandom.h +klein.o: $(HACK_SRC)/xlockmoreI.h +klein.o: $(HACK_SRC)/xlockmore.h +lament.o: ../../config.h +lament.o: $(HACK_SRC)/fps.h +lament.o: $(srcdir)/gltrackball.h +lament.o: $(HACK_SRC)/images/lament512.xpm +lament.o: $(srcdir)/jwzglesI.h +lament.o: $(srcdir)/jwzgles.h +lament.o: $(srcdir)/normals.h +lament.o: $(srcdir)/rotator.h +lament.o: $(HACK_SRC)/screenhackI.h +lament.o: $(UTILS_SRC)/colors.h +lament.o: $(UTILS_SRC)/grabscreen.h +lament.o: $(UTILS_SRC)/hsv.h +lament.o: $(UTILS_SRC)/resources.h +lament.o: $(UTILS_SRC)/usleep.h +lament.o: $(UTILS_SRC)/visual.h +lament.o: $(UTILS_SRC)/xshm.h +lament.o: $(UTILS_SRC)/yarandom.h +lament.o: $(HACK_SRC)/xlockmoreI.h +lament.o: $(HACK_SRC)/xlockmore.h +lament.o: $(srcdir)/xpm-ximage.h +lavalite.o: ../../config.h +lavalite.o: $(HACK_SRC)/fps.h +lavalite.o: $(srcdir)/gltrackball.h +lavalite.o: $(srcdir)/jwzglesI.h +lavalite.o: $(srcdir)/jwzgles.h +lavalite.o: $(srcdir)/marching.h +lavalite.o: $(srcdir)/rotator.h +lavalite.o: $(HACK_SRC)/screenhackI.h +lavalite.o: $(UTILS_SRC)/colors.h +lavalite.o: $(UTILS_SRC)/grabscreen.h +lavalite.o: $(UTILS_SRC)/hsv.h +lavalite.o: $(UTILS_SRC)/resources.h +lavalite.o: $(UTILS_SRC)/usleep.h +lavalite.o: $(UTILS_SRC)/visual.h +lavalite.o: $(UTILS_SRC)/xshm.h +lavalite.o: $(UTILS_SRC)/yarandom.h +lavalite.o: $(HACK_SRC)/xlockmoreI.h +lavalite.o: $(HACK_SRC)/xlockmore.h +lavalite.o: $(srcdir)/xpm-ximage.h +lockward.o: ../../config.h +lockward.o: $(HACK_SRC)/fps.h +lockward.o: $(srcdir)/jwzglesI.h +lockward.o: $(srcdir)/jwzgles.h +lockward.o: $(HACK_SRC)/screenhackI.h +lockward.o: $(UTILS_SRC)/colors.h +lockward.o: $(UTILS_SRC)/grabscreen.h +lockward.o: $(UTILS_SRC)/hsv.h +lockward.o: $(UTILS_SRC)/resources.h +lockward.o: $(UTILS_SRC)/usleep.h +lockward.o: $(UTILS_SRC)/visual.h +lockward.o: $(UTILS_SRC)/xshm.h +lockward.o: $(UTILS_SRC)/yarandom.h +lockward.o: $(HACK_SRC)/xlockmoreI.h +lockward.o: $(HACK_SRC)/xlockmore.h +marching.o: ../../config.h +marching.o: $(srcdir)/jwzglesI.h +marching.o: $(srcdir)/jwzgles.h +marching.o: $(srcdir)/marching.h +marching.o: $(srcdir)/normals.h +menger.o: ../../config.h +menger.o: $(HACK_SRC)/fps.h +menger.o: $(srcdir)/gltrackball.h +menger.o: $(srcdir)/jwzglesI.h +menger.o: $(srcdir)/jwzgles.h +menger.o: $(srcdir)/rotator.h +menger.o: $(HACK_SRC)/screenhackI.h +menger.o: $(UTILS_SRC)/colors.h +menger.o: $(UTILS_SRC)/grabscreen.h +menger.o: $(UTILS_SRC)/hsv.h +menger.o: $(UTILS_SRC)/resources.h +menger.o: $(UTILS_SRC)/usleep.h +menger.o: $(UTILS_SRC)/visual.h +menger.o: $(UTILS_SRC)/xshm.h +menger.o: $(UTILS_SRC)/yarandom.h +menger.o: $(HACK_SRC)/xlockmoreI.h +menger.o: $(HACK_SRC)/xlockmore.h +mirrorblob.o: ../../config.h +mirrorblob.o: $(HACK_SRC)/fps.h +mirrorblob.o: $(srcdir)/gltrackball.h +mirrorblob.o: $(srcdir)/grab-ximage.h +mirrorblob.o: $(srcdir)/jwzglesI.h +mirrorblob.o: $(srcdir)/jwzgles.h +mirrorblob.o: $(HACK_SRC)/screenhackI.h +mirrorblob.o: $(UTILS_SRC)/colors.h +mirrorblob.o: $(UTILS_SRC)/grabscreen.h +mirrorblob.o: $(UTILS_SRC)/hsv.h +mirrorblob.o: $(UTILS_SRC)/resources.h +mirrorblob.o: $(UTILS_SRC)/usleep.h +mirrorblob.o: $(UTILS_SRC)/visual.h +mirrorblob.o: $(UTILS_SRC)/xshm.h +mirrorblob.o: $(UTILS_SRC)/yarandom.h +mirrorblob.o: $(HACK_SRC)/xlockmoreI.h +mirrorblob.o: $(HACK_SRC)/xlockmore.h +moebiusgears.o: ../../config.h +moebiusgears.o: $(HACK_SRC)/fps.h +moebiusgears.o: $(srcdir)/gltrackball.h +moebiusgears.o: $(srcdir)/involute.h +moebiusgears.o: $(srcdir)/jwzglesI.h +moebiusgears.o: $(srcdir)/jwzgles.h +moebiusgears.o: $(srcdir)/normals.h +moebiusgears.o: $(srcdir)/rotator.h +moebiusgears.o: $(HACK_SRC)/screenhackI.h +moebiusgears.o: $(UTILS_SRC)/colors.h +moebiusgears.o: $(UTILS_SRC)/grabscreen.h +moebiusgears.o: $(UTILS_SRC)/hsv.h +moebiusgears.o: $(UTILS_SRC)/resources.h +moebiusgears.o: $(UTILS_SRC)/usleep.h +moebiusgears.o: $(UTILS_SRC)/visual.h +moebiusgears.o: $(UTILS_SRC)/xshm.h +moebiusgears.o: $(UTILS_SRC)/yarandom.h +moebiusgears.o: $(HACK_SRC)/xlockmoreI.h +moebiusgears.o: $(HACK_SRC)/xlockmore.h +moebius.o: ../../config.h +moebius.o: $(HACK_SRC)/fps.h +moebius.o: $(srcdir)/gltrackball.h +moebius.o: $(srcdir)/jwzglesI.h +moebius.o: $(srcdir)/jwzgles.h +moebius.o: $(srcdir)/rotator.h +moebius.o: $(HACK_SRC)/screenhackI.h +moebius.o: $(srcdir)/sphere.h +moebius.o: $(srcdir)/tube.h +moebius.o: $(UTILS_SRC)/colors.h +moebius.o: $(UTILS_SRC)/grabscreen.h +moebius.o: $(UTILS_SRC)/hsv.h +moebius.o: $(UTILS_SRC)/resources.h +moebius.o: $(UTILS_SRC)/usleep.h +moebius.o: $(UTILS_SRC)/visual.h +moebius.o: $(UTILS_SRC)/xshm.h +moebius.o: $(UTILS_SRC)/yarandom.h +moebius.o: $(HACK_SRC)/xlockmoreI.h +moebius.o: $(HACK_SRC)/xlockmore.h +molecule.o: ../../config.h +molecule.o: $(HACK_SRC)/fps.h +molecule.o: $(srcdir)/gltrackball.h +molecule.o: $(srcdir)/glxfonts.h +molecule.o: $(srcdir)/jwzglesI.h +molecule.o: $(srcdir)/jwzgles.h +molecule.o: molecules.h +molecule.o: $(srcdir)/rotator.h +molecule.o: $(HACK_SRC)/screenhackI.h +molecule.o: $(srcdir)/sphere.h +molecule.o: $(srcdir)/texfont.h +molecule.o: $(srcdir)/tube.h +molecule.o: $(UTILS_SRC)/colors.h +molecule.o: $(UTILS_SRC)/grabscreen.h +molecule.o: $(UTILS_SRC)/hsv.h +molecule.o: $(UTILS_SRC)/resources.h +molecule.o: $(UTILS_SRC)/usleep.h +molecule.o: $(UTILS_SRC)/visual.h +molecule.o: $(UTILS_SRC)/xshm.h +molecule.o: $(UTILS_SRC)/yarandom.h +molecule.o: $(HACK_SRC)/xlockmoreI.h +molecule.o: $(HACK_SRC)/xlockmore.h +morph3d.o: ../../config.h +morph3d.o: $(HACK_SRC)/fps.h +morph3d.o: $(srcdir)/jwzglesI.h +morph3d.o: $(srcdir)/jwzgles.h +morph3d.o: $(HACK_SRC)/screenhackI.h +morph3d.o: $(UTILS_SRC)/colors.h +morph3d.o: $(UTILS_SRC)/grabscreen.h +morph3d.o: $(UTILS_SRC)/hsv.h +morph3d.o: $(UTILS_SRC)/resources.h +morph3d.o: $(UTILS_SRC)/usleep.h +morph3d.o: $(UTILS_SRC)/visual.h +morph3d.o: $(UTILS_SRC)/xshm.h +morph3d.o: $(UTILS_SRC)/yarandom.h +morph3d.o: $(HACK_SRC)/xlockmoreI.h +morph3d.o: $(HACK_SRC)/xlockmore.h +noof.o: ../../config.h +noof.o: $(HACK_SRC)/fps.h +noof.o: $(srcdir)/jwzglesI.h +noof.o: $(srcdir)/jwzgles.h +noof.o: $(HACK_SRC)/screenhackI.h +noof.o: $(UTILS_SRC)/colors.h +noof.o: $(UTILS_SRC)/grabscreen.h +noof.o: $(UTILS_SRC)/hsv.h +noof.o: $(UTILS_SRC)/resources.h +noof.o: $(UTILS_SRC)/usleep.h +noof.o: $(UTILS_SRC)/visual.h +noof.o: $(UTILS_SRC)/xshm.h +noof.o: $(UTILS_SRC)/yarandom.h +noof.o: $(HACK_SRC)/xlockmoreI.h +noof.o: $(HACK_SRC)/xlockmore.h +normals.o: ../../config.h +normals.o: $(srcdir)/jwzglesI.h +normals.o: $(srcdir)/jwzgles.h +normals.o: $(srcdir)/normals.h +photopile.o: ../../config.h +photopile.o: $(srcdir)/dropshadow.h +photopile.o: $(HACK_SRC)/fps.h +photopile.o: $(srcdir)/grab-ximage.h +photopile.o: $(srcdir)/jwzglesI.h +photopile.o: $(srcdir)/jwzgles.h +photopile.o: $(HACK_SRC)/screenhackI.h +photopile.o: $(srcdir)/texfont.h +photopile.o: $(UTILS_SRC)/colors.h +photopile.o: $(UTILS_SRC)/grabscreen.h +photopile.o: $(UTILS_SRC)/hsv.h +photopile.o: $(UTILS_SRC)/resources.h +photopile.o: $(UTILS_SRC)/usleep.h +photopile.o: $(UTILS_SRC)/visual.h +photopile.o: $(UTILS_SRC)/xshm.h +photopile.o: $(UTILS_SRC)/yarandom.h +photopile.o: $(HACK_SRC)/xlockmoreI.h +photopile.o: $(HACK_SRC)/xlockmore.h +pinion.o: ../../config.h +pinion.o: $(HACK_SRC)/fps.h +pinion.o: $(srcdir)/gltrackball.h +pinion.o: $(srcdir)/glxfonts.h +pinion.o: $(srcdir)/involute.h +pinion.o: $(srcdir)/jwzglesI.h +pinion.o: $(srcdir)/jwzgles.h +pinion.o: $(srcdir)/normals.h +pinion.o: $(HACK_SRC)/screenhackI.h +pinion.o: $(srcdir)/texfont.h +pinion.o: $(UTILS_SRC)/colors.h +pinion.o: $(UTILS_SRC)/grabscreen.h +pinion.o: $(UTILS_SRC)/hsv.h +pinion.o: $(UTILS_SRC)/resources.h +pinion.o: $(UTILS_SRC)/usleep.h +pinion.o: $(UTILS_SRC)/visual.h +pinion.o: $(UTILS_SRC)/xshm.h +pinion.o: $(UTILS_SRC)/yarandom.h +pinion.o: $(HACK_SRC)/xlockmoreI.h +pinion.o: $(HACK_SRC)/xlockmore.h +pipeobjs.o: $(srcdir)/buildlwo.h +pipeobjs.o: ../../config.h +pipeobjs.o: $(srcdir)/jwzglesI.h +pipeobjs.o: $(srcdir)/jwzgles.h +pipes.o: $(srcdir)/buildlwo.h +pipes.o: ../../config.h +pipes.o: $(HACK_SRC)/fps.h +pipes.o: $(srcdir)/gltrackball.h +pipes.o: $(srcdir)/jwzglesI.h +pipes.o: $(srcdir)/jwzgles.h +pipes.o: $(HACK_SRC)/screenhackI.h +pipes.o: $(srcdir)/sphere.h +pipes.o: $(srcdir)/teapot.h +pipes.o: $(UTILS_SRC)/colors.h +pipes.o: $(UTILS_SRC)/grabscreen.h +pipes.o: $(UTILS_SRC)/hsv.h +pipes.o: $(UTILS_SRC)/resources.h +pipes.o: $(UTILS_SRC)/usleep.h +pipes.o: $(UTILS_SRC)/visual.h +pipes.o: $(UTILS_SRC)/xshm.h +pipes.o: $(UTILS_SRC)/yarandom.h +pipes.o: $(HACK_SRC)/xlockmoreI.h +pipes.o: $(HACK_SRC)/xlockmore.h +polyhedra-gl.o: ../../config.h +polyhedra-gl.o: $(HACK_SRC)/fps.h +polyhedra-gl.o: $(srcdir)/gltrackball.h +polyhedra-gl.o: $(srcdir)/glxfonts.h +polyhedra-gl.o: $(srcdir)/jwzglesI.h +polyhedra-gl.o: $(srcdir)/jwzgles.h +polyhedra-gl.o: $(srcdir)/normals.h +polyhedra-gl.o: $(srcdir)/polyhedra.h +polyhedra-gl.o: $(srcdir)/rotator.h +polyhedra-gl.o: $(HACK_SRC)/screenhackI.h +polyhedra-gl.o: $(srcdir)/teapot.h +polyhedra-gl.o: $(srcdir)/texfont.h +polyhedra-gl.o: $(UTILS_SRC)/colors.h +polyhedra-gl.o: $(UTILS_SRC)/grabscreen.h +polyhedra-gl.o: $(UTILS_SRC)/hsv.h +polyhedra-gl.o: $(UTILS_SRC)/resources.h +polyhedra-gl.o: $(UTILS_SRC)/usleep.h +polyhedra-gl.o: $(UTILS_SRC)/visual.h +polyhedra-gl.o: $(UTILS_SRC)/xshm.h +polyhedra-gl.o: $(UTILS_SRC)/yarandom.h +polyhedra-gl.o: $(HACK_SRC)/xlockmoreI.h +polyhedra-gl.o: $(HACK_SRC)/xlockmore.h +polyhedra.o: ../../config.h +polyhedra.o: $(srcdir)/polyhedra.h +polytopes.o: ../../config.h +polytopes.o: $(HACK_SRC)/fps.h +polytopes.o: $(srcdir)/gltrackball.h +polytopes.o: $(srcdir)/jwzglesI.h +polytopes.o: $(srcdir)/jwzgles.h +polytopes.o: $(HACK_SRC)/screenhackI.h +polytopes.o: $(UTILS_SRC)/colors.h +polytopes.o: $(UTILS_SRC)/grabscreen.h +polytopes.o: $(UTILS_SRC)/hsv.h +polytopes.o: $(UTILS_SRC)/resources.h +polytopes.o: $(UTILS_SRC)/usleep.h +polytopes.o: $(UTILS_SRC)/visual.h +polytopes.o: $(UTILS_SRC)/xshm.h +polytopes.o: $(UTILS_SRC)/yarandom.h +polytopes.o: $(HACK_SRC)/xlockmoreI.h +polytopes.o: $(HACK_SRC)/xlockmore.h +providence.o: ../../config.h +providence.o: $(HACK_SRC)/fps.h +providence.o: $(srcdir)/gltrackball.h +providence.o: $(srcdir)/jwzglesI.h +providence.o: $(srcdir)/jwzgles.h +providence.o: $(HACK_SRC)/screenhackI.h +providence.o: $(UTILS_SRC)/colors.h +providence.o: $(UTILS_SRC)/grabscreen.h +providence.o: $(UTILS_SRC)/hsv.h +providence.o: $(UTILS_SRC)/resources.h +providence.o: $(UTILS_SRC)/usleep.h +providence.o: $(UTILS_SRC)/visual.h +providence.o: $(UTILS_SRC)/xshm.h +providence.o: $(UTILS_SRC)/yarandom.h +providence.o: $(HACK_SRC)/xlockmoreI.h +providence.o: $(HACK_SRC)/xlockmore.h +pulsar.o: ../../config.h +pulsar.o: $(HACK_SRC)/fps.h +pulsar.o: $(srcdir)/jwzglesI.h +pulsar.o: $(srcdir)/jwzgles.h +pulsar.o: $(HACK_SRC)/screenhackI.h +pulsar.o: $(UTILS_SRC)/colors.h +pulsar.o: $(UTILS_SRC)/grabscreen.h +pulsar.o: $(UTILS_SRC)/hsv.h +pulsar.o: $(UTILS_SRC)/resources.h +pulsar.o: $(UTILS_SRC)/usleep.h +pulsar.o: $(UTILS_SRC)/visual.h +pulsar.o: $(UTILS_SRC)/xshm.h +pulsar.o: $(UTILS_SRC)/yarandom.h +pulsar.o: $(HACK_SRC)/xlockmoreI.h +pulsar.o: $(HACK_SRC)/xlockmore.h +pulsar.o: $(srcdir)/xpm-ximage.h +queens.o: $(srcdir)/chessmodels.h +queens.o: ../../config.h +queens.o: $(HACK_SRC)/fps.h +queens.o: $(srcdir)/gltrackball.h +queens.o: $(srcdir)/jwzglesI.h +queens.o: $(srcdir)/jwzgles.h +queens.o: $(HACK_SRC)/screenhackI.h +queens.o: $(UTILS_SRC)/colors.h +queens.o: $(UTILS_SRC)/grabscreen.h +queens.o: $(UTILS_SRC)/hsv.h +queens.o: $(UTILS_SRC)/resources.h +queens.o: $(UTILS_SRC)/usleep.h +queens.o: $(UTILS_SRC)/visual.h +queens.o: $(UTILS_SRC)/xshm.h +queens.o: $(UTILS_SRC)/yarandom.h +queens.o: $(HACK_SRC)/xlockmoreI.h +queens.o: $(HACK_SRC)/xlockmore.h +rotator.o: ../../config.h +rotator.o: $(srcdir)/rotator.h +rotator.o: $(UTILS_SRC)/yarandom.h +rubikblocks.o: ../../config.h +rubikblocks.o: $(HACK_SRC)/fps.h +rubikblocks.o: $(srcdir)/gltrackball.h +rubikblocks.o: $(srcdir)/jwzglesI.h +rubikblocks.o: $(srcdir)/jwzgles.h +rubikblocks.o: $(srcdir)/rotator.h +rubikblocks.o: $(HACK_SRC)/screenhackI.h +rubikblocks.o: $(UTILS_SRC)/colors.h +rubikblocks.o: $(UTILS_SRC)/grabscreen.h +rubikblocks.o: $(UTILS_SRC)/hsv.h +rubikblocks.o: $(UTILS_SRC)/resources.h +rubikblocks.o: $(UTILS_SRC)/usleep.h +rubikblocks.o: $(UTILS_SRC)/visual.h +rubikblocks.o: $(UTILS_SRC)/xshm.h +rubikblocks.o: $(UTILS_SRC)/yarandom.h +rubikblocks.o: $(HACK_SRC)/xlockmoreI.h +rubikblocks.o: $(HACK_SRC)/xlockmore.h +rubik.o: ../../config.h +rubik.o: $(HACK_SRC)/fps.h +rubik.o: $(srcdir)/gltrackball.h +rubik.o: $(srcdir)/jwzglesI.h +rubik.o: $(srcdir)/jwzgles.h +rubik.o: $(HACK_SRC)/screenhackI.h +rubik.o: $(UTILS_SRC)/colors.h +rubik.o: $(UTILS_SRC)/grabscreen.h +rubik.o: $(UTILS_SRC)/hsv.h +rubik.o: $(UTILS_SRC)/resources.h +rubik.o: $(UTILS_SRC)/usleep.h +rubik.o: $(UTILS_SRC)/visual.h +rubik.o: $(UTILS_SRC)/xshm.h +rubik.o: $(UTILS_SRC)/yarandom.h +rubik.o: $(HACK_SRC)/xlockmoreI.h +rubik.o: $(HACK_SRC)/xlockmore.h +s1_1.o: ../../config.h +s1_1.o: $(srcdir)/gllist.h +s1_1.o: $(srcdir)/jwzglesI.h +s1_1.o: $(srcdir)/jwzgles.h +s1_2.o: ../../config.h +s1_2.o: $(srcdir)/gllist.h +s1_2.o: $(srcdir)/jwzglesI.h +s1_2.o: $(srcdir)/jwzgles.h +s1_3.o: ../../config.h +s1_3.o: $(srcdir)/gllist.h +s1_3.o: $(srcdir)/jwzglesI.h +s1_3.o: $(srcdir)/jwzgles.h +s1_4.o: ../../config.h +s1_4.o: $(srcdir)/gllist.h +s1_4.o: $(srcdir)/jwzglesI.h +s1_4.o: $(srcdir)/jwzgles.h +s1_5.o: ../../config.h +s1_5.o: $(srcdir)/gllist.h +s1_5.o: $(srcdir)/jwzglesI.h +s1_5.o: $(srcdir)/jwzgles.h +s1_6.o: ../../config.h +s1_6.o: $(srcdir)/gllist.h +s1_6.o: $(srcdir)/jwzglesI.h +s1_6.o: $(srcdir)/jwzgles.h +s1_b.o: ../../config.h +s1_b.o: $(srcdir)/gllist.h +s1_b.o: $(srcdir)/jwzglesI.h +s1_b.o: $(srcdir)/jwzgles.h +sballs.o: ../../config.h +sballs.o: $(HACK_SRC)/fps.h +sballs.o: $(srcdir)/gltrackball.h +sballs.o: $(HACK_SRC)/images/sball-bg.xpm +sballs.o: $(HACK_SRC)/images/sball.xpm +sballs.o: $(srcdir)/jwzglesI.h +sballs.o: $(srcdir)/jwzgles.h +sballs.o: $(HACK_SRC)/screenhackI.h +sballs.o: $(UTILS_SRC)/colors.h +sballs.o: $(UTILS_SRC)/grabscreen.h +sballs.o: $(UTILS_SRC)/hsv.h +sballs.o: $(UTILS_SRC)/resources.h +sballs.o: $(UTILS_SRC)/usleep.h +sballs.o: $(UTILS_SRC)/visual.h +sballs.o: $(UTILS_SRC)/xshm.h +sballs.o: $(UTILS_SRC)/yarandom.h +sballs.o: $(HACK_SRC)/xlockmoreI.h +sballs.o: $(HACK_SRC)/xlockmore.h +sballs.o: $(srcdir)/xpm-ximage.h +shark.o: $(srcdir)/atlantis.h +shark.o: ../../config.h +shark.o: $(HACK_SRC)/fps.h +shark.o: $(srcdir)/jwzglesI.h +shark.o: $(srcdir)/jwzgles.h +shark.o: $(HACK_SRC)/screenhackI.h +shark.o: $(UTILS_SRC)/colors.h +shark.o: $(UTILS_SRC)/grabscreen.h +shark.o: $(UTILS_SRC)/hsv.h +shark.o: $(UTILS_SRC)/resources.h +shark.o: $(UTILS_SRC)/usleep.h +shark.o: $(UTILS_SRC)/visual.h +shark.o: $(UTILS_SRC)/yarandom.h +sierpinski3d.o: ../../config.h +sierpinski3d.o: $(HACK_SRC)/fps.h +sierpinski3d.o: $(srcdir)/gltrackball.h +sierpinski3d.o: $(srcdir)/jwzglesI.h +sierpinski3d.o: $(srcdir)/jwzgles.h +sierpinski3d.o: $(srcdir)/rotator.h +sierpinski3d.o: $(HACK_SRC)/screenhackI.h +sierpinski3d.o: $(UTILS_SRC)/colors.h +sierpinski3d.o: $(UTILS_SRC)/grabscreen.h +sierpinski3d.o: $(UTILS_SRC)/hsv.h +sierpinski3d.o: $(UTILS_SRC)/resources.h +sierpinski3d.o: $(UTILS_SRC)/usleep.h +sierpinski3d.o: $(UTILS_SRC)/visual.h +sierpinski3d.o: $(UTILS_SRC)/xshm.h +sierpinski3d.o: $(UTILS_SRC)/yarandom.h +sierpinski3d.o: $(HACK_SRC)/xlockmoreI.h +sierpinski3d.o: $(HACK_SRC)/xlockmore.h +skytentacles.o: ../../config.h +skytentacles.o: $(HACK_SRC)/fps.h +skytentacles.o: $(srcdir)/gltrackball.h +skytentacles.o: $(HACK_SRC)/images/scales.xpm +skytentacles.o: $(srcdir)/jwzglesI.h +skytentacles.o: $(srcdir)/jwzgles.h +skytentacles.o: $(srcdir)/normals.h +skytentacles.o: $(srcdir)/rotator.h +skytentacles.o: $(HACK_SRC)/screenhackI.h +skytentacles.o: $(UTILS_SRC)/colors.h +skytentacles.o: $(UTILS_SRC)/grabscreen.h +skytentacles.o: $(UTILS_SRC)/hsv.h +skytentacles.o: $(UTILS_SRC)/resources.h +skytentacles.o: $(UTILS_SRC)/usleep.h +skytentacles.o: $(UTILS_SRC)/visual.h +skytentacles.o: $(UTILS_SRC)/xshm.h +skytentacles.o: $(UTILS_SRC)/yarandom.h +skytentacles.o: $(HACK_SRC)/xlockmoreI.h +skytentacles.o: $(HACK_SRC)/xlockmore.h +skytentacles.o: $(srcdir)/xpm-ximage.h +sonar-icmp.o: ../../config.h +sonar-icmp.o: $(HACK_SRC)/fps.h +sonar-icmp.o: $(HACK_SRC)/screenhackI.h +sonar-icmp.o: $(srcdir)/sonar.h +sonar-icmp.o: $(UTILS_SRC)/colors.h +sonar-icmp.o: $(UTILS_SRC)/grabscreen.h +sonar-icmp.o: $(UTILS_SRC)/hsv.h +sonar-icmp.o: $(UTILS_SRC)/resources.h +sonar-icmp.o: $(UTILS_SRC)/usleep.h +sonar-icmp.o: $(UTILS_SRC)/version.h +sonar-icmp.o: $(UTILS_SRC)/visual.h +sonar-icmp.o: $(UTILS_SRC)/yarandom.h +sonar.o: ../../config.h +sonar.o: $(HACK_SRC)/fps.h +sonar.o: $(srcdir)/gltrackball.h +sonar.o: $(srcdir)/jwzglesI.h +sonar.o: $(srcdir)/jwzgles.h +sonar.o: $(srcdir)/rotator.h +sonar.o: $(HACK_SRC)/screenhackI.h +sonar.o: $(srcdir)/sonar.h +sonar.o: $(srcdir)/texfont.h +sonar.o: $(UTILS_SRC)/colors.h +sonar.o: $(UTILS_SRC)/grabscreen.h +sonar.o: $(UTILS_SRC)/hsv.h +sonar.o: $(UTILS_SRC)/resources.h +sonar.o: $(UTILS_SRC)/usleep.h +sonar.o: $(UTILS_SRC)/visual.h +sonar.o: $(UTILS_SRC)/xshm.h +sonar.o: $(UTILS_SRC)/yarandom.h +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)/screenhackI.h +sonar-sim.o: $(srcdir)/sonar.h +sonar-sim.o: $(UTILS_SRC)/colors.h +sonar-sim.o: $(UTILS_SRC)/grabscreen.h +sonar-sim.o: $(UTILS_SRC)/hsv.h +sonar-sim.o: $(UTILS_SRC)/resources.h +sonar-sim.o: $(UTILS_SRC)/usleep.h +sonar-sim.o: $(UTILS_SRC)/visual.h +sonar-sim.o: $(UTILS_SRC)/yarandom.h +spheremonics.o: ../../config.h +spheremonics.o: $(HACK_SRC)/fps.h +spheremonics.o: $(srcdir)/gltrackball.h +spheremonics.o: $(srcdir)/glxfonts.h +spheremonics.o: $(srcdir)/jwzglesI.h +spheremonics.o: $(srcdir)/jwzgles.h +spheremonics.o: $(srcdir)/normals.h +spheremonics.o: $(srcdir)/rotator.h +spheremonics.o: $(HACK_SRC)/screenhackI.h +spheremonics.o: $(srcdir)/texfont.h +spheremonics.o: $(UTILS_SRC)/colors.h +spheremonics.o: $(UTILS_SRC)/grabscreen.h +spheremonics.o: $(UTILS_SRC)/hsv.h +spheremonics.o: $(UTILS_SRC)/resources.h +spheremonics.o: $(UTILS_SRC)/usleep.h +spheremonics.o: $(UTILS_SRC)/visual.h +spheremonics.o: $(UTILS_SRC)/xshm.h +spheremonics.o: $(UTILS_SRC)/yarandom.h +spheremonics.o: $(HACK_SRC)/xlockmoreI.h +spheremonics.o: $(HACK_SRC)/xlockmore.h +sphere.o: ../../config.h +sphere.o: $(srcdir)/jwzglesI.h +sphere.o: $(srcdir)/jwzgles.h +sphere.o: $(srcdir)/sphere.h +sproingies.o: ../../config.h +sproingies.o: $(HACK_SRC)/fps.h +sproingies.o: $(srcdir)/gllist.h +sproingies.o: $(srcdir)/jwzglesI.h +sproingies.o: $(srcdir)/jwzgles.h +sproingies.o: $(HACK_SRC)/screenhackI.h +sproingies.o: $(srcdir)/sproingies.h +sproingies.o: $(UTILS_SRC)/colors.h +sproingies.o: $(UTILS_SRC)/grabscreen.h +sproingies.o: $(UTILS_SRC)/hsv.h +sproingies.o: $(UTILS_SRC)/resources.h +sproingies.o: $(UTILS_SRC)/usleep.h +sproingies.o: $(UTILS_SRC)/visual.h +sproingies.o: $(UTILS_SRC)/xshm.h +sproingies.o: $(UTILS_SRC)/yarandom.h +sproingies.o: $(HACK_SRC)/xlockmoreI.h +sproingiewrap.o: ../../config.h +sproingiewrap.o: $(HACK_SRC)/fps.h +sproingiewrap.o: $(srcdir)/jwzglesI.h +sproingiewrap.o: $(srcdir)/jwzgles.h +sproingiewrap.o: $(HACK_SRC)/screenhackI.h +sproingiewrap.o: $(srcdir)/sproingies.h +sproingiewrap.o: $(UTILS_SRC)/colors.h +sproingiewrap.o: $(UTILS_SRC)/grabscreen.h +sproingiewrap.o: $(UTILS_SRC)/hsv.h +sproingiewrap.o: $(UTILS_SRC)/resources.h +sproingiewrap.o: $(UTILS_SRC)/usleep.h +sproingiewrap.o: $(UTILS_SRC)/visual.h +sproingiewrap.o: $(UTILS_SRC)/xshm.h +sproingiewrap.o: $(UTILS_SRC)/yarandom.h +sproingiewrap.o: $(HACK_SRC)/xlockmoreI.h +sproingiewrap.o: $(HACK_SRC)/xlockmore.h +stairs.o: ../../config.h +stairs.o: $(HACK_SRC)/fps.h +stairs.o: $(srcdir)/gltrackball.h +stairs.o: $(HACK_SRC)/images/wood.xpm +stairs.o: $(srcdir)/jwzglesI.h +stairs.o: $(srcdir)/jwzgles.h +stairs.o: $(HACK_SRC)/screenhackI.h +stairs.o: $(srcdir)/sphere.h +stairs.o: $(UTILS_SRC)/colors.h +stairs.o: $(UTILS_SRC)/grabscreen.h +stairs.o: $(UTILS_SRC)/hsv.h +stairs.o: $(UTILS_SRC)/resources.h +stairs.o: $(UTILS_SRC)/usleep.h +stairs.o: $(UTILS_SRC)/visual.h +stairs.o: $(UTILS_SRC)/xshm.h +stairs.o: $(UTILS_SRC)/yarandom.h +stairs.o: $(HACK_SRC)/xlockmoreI.h +stairs.o: $(HACK_SRC)/xlockmore.h +stairs.o: $(srcdir)/xpm-ximage.h +starwars.o: ../../config.h +starwars.o: $(HACK_SRC)/fps.h +starwars.o: $(srcdir)/glut_roman.h +starwars.o: $(srcdir)/glutstroke.h +starwars.o: $(srcdir)/jwzglesI.h +starwars.o: $(srcdir)/jwzgles.h +starwars.o: $(HACK_SRC)/screenhackI.h +starwars.o: $(srcdir)/starwars.h +starwars.o: $(srcdir)/texfont.h +starwars.o: $(UTILS_SRC)/colors.h +starwars.o: $(UTILS_SRC)/grabscreen.h +starwars.o: $(UTILS_SRC)/hsv.h +starwars.o: $(UTILS_SRC)/resources.h +starwars.o: $(UTILS_SRC)/textclient.h +starwars.o: $(UTILS_SRC)/usleep.h +starwars.o: $(UTILS_SRC)/visual.h +starwars.o: $(UTILS_SRC)/xshm.h +starwars.o: $(UTILS_SRC)/yarandom.h +starwars.o: $(HACK_SRC)/xlockmoreI.h +starwars.o: $(HACK_SRC)/xlockmore.h +stonerview-move.o: ../../config.h +stonerview-move.o: $(srcdir)/jwzglesI.h +stonerview-move.o: $(srcdir)/jwzgles.h +stonerview-move.o: $(srcdir)/stonerview.h +stonerview-move.o: $(srcdir)/stonerview-move.h +stonerview-move.o: $(srcdir)/stonerview-osc.h +stonerview-move.o: $(UTILS_SRC)/yarandom.h +stonerview.o: ../../config.h +stonerview.o: $(HACK_SRC)/fps.h +stonerview.o: $(srcdir)/gltrackball.h +stonerview.o: $(srcdir)/jwzglesI.h +stonerview.o: $(srcdir)/jwzgles.h +stonerview.o: $(HACK_SRC)/screenhackI.h +stonerview.o: $(srcdir)/stonerview.h +stonerview.o: $(srcdir)/stonerview-move.h +stonerview.o: $(srcdir)/stonerview-osc.h +stonerview.o: $(UTILS_SRC)/colors.h +stonerview.o: $(UTILS_SRC)/grabscreen.h +stonerview.o: $(UTILS_SRC)/hsv.h +stonerview.o: $(UTILS_SRC)/resources.h +stonerview.o: $(UTILS_SRC)/usleep.h +stonerview.o: $(UTILS_SRC)/visual.h +stonerview.o: $(UTILS_SRC)/xshm.h +stonerview.o: $(UTILS_SRC)/yarandom.h +stonerview.o: $(HACK_SRC)/xlockmoreI.h +stonerview.o: $(HACK_SRC)/xlockmore.h +stonerview-osc.o: ../../config.h +stonerview-osc.o: $(srcdir)/jwzglesI.h +stonerview-osc.o: $(srcdir)/jwzgles.h +stonerview-osc.o: $(srcdir)/stonerview.h +stonerview-osc.o: $(srcdir)/stonerview-move.h +stonerview-osc.o: $(srcdir)/stonerview-osc.h +stonerview-osc.o: $(UTILS_SRC)/yarandom.h +stonerview-view.o: ../../config.h +stonerview-view.o: $(srcdir)/jwzglesI.h +stonerview-view.o: $(srcdir)/jwzgles.h +stonerview-view.o: $(srcdir)/stonerview.h +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: $(srcdir)/jwzglesI.h +superquadrics.o: $(srcdir)/jwzgles.h +superquadrics.o: $(HACK_SRC)/screenhackI.h +superquadrics.o: $(UTILS_SRC)/colors.h +superquadrics.o: $(UTILS_SRC)/grabscreen.h +superquadrics.o: $(UTILS_SRC)/hsv.h +superquadrics.o: $(UTILS_SRC)/resources.h +superquadrics.o: $(UTILS_SRC)/usleep.h +superquadrics.o: $(UTILS_SRC)/visual.h +superquadrics.o: $(UTILS_SRC)/xshm.h +superquadrics.o: $(UTILS_SRC)/yarandom.h +superquadrics.o: $(HACK_SRC)/xlockmoreI.h +superquadrics.o: $(HACK_SRC)/xlockmore.h +surfaces.o: ../../config.h +surfaces.o: $(HACK_SRC)/fps.h +surfaces.o: $(srcdir)/gltrackball.h +surfaces.o: $(srcdir)/jwzglesI.h +surfaces.o: $(srcdir)/jwzgles.h +surfaces.o: $(srcdir)/rotator.h +surfaces.o: $(HACK_SRC)/screenhackI.h +surfaces.o: $(UTILS_SRC)/colors.h +surfaces.o: $(UTILS_SRC)/grabscreen.h +surfaces.o: $(UTILS_SRC)/hsv.h +surfaces.o: $(UTILS_SRC)/resources.h +surfaces.o: $(UTILS_SRC)/usleep.h +surfaces.o: $(UTILS_SRC)/visual.h +surfaces.o: $(UTILS_SRC)/xshm.h +surfaces.o: $(UTILS_SRC)/yarandom.h +surfaces.o: $(HACK_SRC)/xlockmoreI.h +surfaces.o: $(HACK_SRC)/xlockmore.h +swim.o: $(srcdir)/atlantis.h +swim.o: ../../config.h +swim.o: $(HACK_SRC)/fps.h +swim.o: $(srcdir)/jwzglesI.h +swim.o: $(srcdir)/jwzgles.h +swim.o: $(HACK_SRC)/screenhackI.h +swim.o: $(UTILS_SRC)/colors.h +swim.o: $(UTILS_SRC)/grabscreen.h +swim.o: $(UTILS_SRC)/hsv.h +swim.o: $(UTILS_SRC)/resources.h +swim.o: $(UTILS_SRC)/usleep.h +swim.o: $(UTILS_SRC)/visual.h +swim.o: $(UTILS_SRC)/xshm.h +swim.o: $(UTILS_SRC)/yarandom.h +swim.o: $(HACK_SRC)/xlockmoreI.h +tangram.o: ../../config.h +tangram.o: $(HACK_SRC)/fps.h +tangram.o: $(srcdir)/glxfonts.h +tangram.o: $(srcdir)/jwzglesI.h +tangram.o: $(srcdir)/jwzgles.h +tangram.o: $(HACK_SRC)/screenhackI.h +tangram.o: $(srcdir)/tangram_shapes.h +tangram.o: $(srcdir)/texfont.h +tangram.o: $(UTILS_SRC)/colors.h +tangram.o: $(UTILS_SRC)/grabscreen.h +tangram.o: $(UTILS_SRC)/hsv.h +tangram.o: $(UTILS_SRC)/resources.h +tangram.o: $(UTILS_SRC)/usleep.h +tangram.o: $(UTILS_SRC)/visual.h +tangram.o: $(UTILS_SRC)/xshm.h +tangram.o: $(UTILS_SRC)/yarandom.h +tangram.o: $(HACK_SRC)/xlockmoreI.h +tangram.o: $(HACK_SRC)/xlockmore.h +tangram_shapes.o: ../../config.h +tangram_shapes.o: $(srcdir)/jwzglesI.h +tangram_shapes.o: $(srcdir)/jwzgles.h +tangram_shapes.o: $(srcdir)/tangram_shapes.h +teapot.o: ../../config.h +teapot.o: $(srcdir)/jwzglesI.h +teapot.o: $(srcdir)/jwzgles.h +teapot.o: $(srcdir)/normals.h +teapot.o: $(srcdir)/teapot2.h +teapot.o: $(srcdir)/teapot.h +texfont.o: ../../config.h +texfont.o: $(srcdir)/jwzglesI.h +texfont.o: $(srcdir)/jwzgles.h +texfont.o: $(srcdir)/texfont.h +texfont.o: $(UTILS_SRC)/resources.h +timetunnel.o: ../../config.h +timetunnel.o: $(HACK_SRC)/fps.h +timetunnel.o: $(srcdir)/gltrackball.h +timetunnel.o: $(HACK_SRC)/images/timetunnel0.xpm +timetunnel.o: $(HACK_SRC)/images/timetunnel1.xpm +timetunnel.o: $(HACK_SRC)/images/timetunnel2.xpm +timetunnel.o: $(HACK_SRC)/images/tunnelstar.xpm +timetunnel.o: $(srcdir)/jwzglesI.h +timetunnel.o: $(srcdir)/jwzgles.h +timetunnel.o: $(srcdir)/rotator.h +timetunnel.o: $(HACK_SRC)/screenhackI.h +timetunnel.o: $(UTILS_SRC)/colors.h +timetunnel.o: $(UTILS_SRC)/grabscreen.h +timetunnel.o: $(UTILS_SRC)/hsv.h +timetunnel.o: $(UTILS_SRC)/images/logo-180.xpm +timetunnel.o: $(UTILS_SRC)/resources.h +timetunnel.o: $(UTILS_SRC)/usleep.h +timetunnel.o: $(UTILS_SRC)/visual.h +timetunnel.o: $(UTILS_SRC)/xshm.h +timetunnel.o: $(UTILS_SRC)/yarandom.h +timetunnel.o: $(HACK_SRC)/xlockmoreI.h +timetunnel.o: $(HACK_SRC)/xlockmore.h +timetunnel.o: $(srcdir)/xpm-ximage.h +toast2.o: ../../config.h +toast2.o: $(srcdir)/gllist.h +toast2.o: $(srcdir)/jwzglesI.h +toast2.o: $(srcdir)/jwzgles.h +toaster_base.o: ../../config.h +toaster_base.o: $(srcdir)/gllist.h +toaster_base.o: $(srcdir)/jwzglesI.h +toaster_base.o: $(srcdir)/jwzgles.h +toaster_handle2.o: ../../config.h +toaster_handle2.o: $(srcdir)/gllist.h +toaster_handle2.o: $(srcdir)/jwzglesI.h +toaster_handle2.o: $(srcdir)/jwzgles.h +toaster_handle.o: ../../config.h +toaster_handle.o: $(srcdir)/gllist.h +toaster_handle.o: $(srcdir)/jwzglesI.h +toaster_handle.o: $(srcdir)/jwzgles.h +toaster_jet.o: ../../config.h +toaster_jet.o: $(srcdir)/gllist.h +toaster_jet.o: $(srcdir)/jwzglesI.h +toaster_jet.o: $(srcdir)/jwzgles.h +toaster_knob.o: ../../config.h +toaster_knob.o: $(srcdir)/gllist.h +toaster_knob.o: $(srcdir)/jwzglesI.h +toaster_knob.o: $(srcdir)/jwzgles.h +toaster.o: ../../config.h +toaster.o: $(srcdir)/gllist.h +toaster.o: $(srcdir)/jwzglesI.h +toaster.o: $(srcdir)/jwzgles.h +toaster_slots.o: ../../config.h +toaster_slots.o: $(srcdir)/gllist.h +toaster_slots.o: $(srcdir)/jwzglesI.h +toaster_slots.o: $(srcdir)/jwzgles.h +toaster_wing.o: ../../config.h +toaster_wing.o: $(srcdir)/gllist.h +toaster_wing.o: $(srcdir)/jwzglesI.h +toaster_wing.o: $(srcdir)/jwzgles.h +toast.o: ../../config.h +toast.o: $(srcdir)/gllist.h +toast.o: $(srcdir)/jwzglesI.h +toast.o: $(srcdir)/jwzgles.h +topblock.o: ../../config.h +topblock.o: $(HACK_SRC)/fps.h +topblock.o: $(srcdir)/gltrackball.h +topblock.o: $(srcdir)/jwzglesI.h +topblock.o: $(srcdir)/jwzgles.h +topblock.o: $(HACK_SRC)/screenhackI.h +topblock.o: $(srcdir)/sphere.h +topblock.o: $(srcdir)/topblock.h +topblock.o: $(srcdir)/tube.h +topblock.o: $(UTILS_SRC)/colors.h +topblock.o: $(UTILS_SRC)/grabscreen.h +topblock.o: $(UTILS_SRC)/hsv.h +topblock.o: $(UTILS_SRC)/resources.h +topblock.o: $(UTILS_SRC)/usleep.h +topblock.o: $(UTILS_SRC)/visual.h +topblock.o: $(UTILS_SRC)/xshm.h +topblock.o: $(UTILS_SRC)/yarandom.h +topblock.o: $(HACK_SRC)/xlockmoreI.h +topblock.o: $(HACK_SRC)/xlockmore.h +trackball.o: ../../config.h +trackball.o: $(srcdir)/trackball.h +tronbit_idle1.o: ../../config.h +tronbit_idle1.o: $(srcdir)/gllist.h +tronbit_idle1.o: $(srcdir)/jwzglesI.h +tronbit_idle1.o: $(srcdir)/jwzgles.h +tronbit_idle2.o: ../../config.h +tronbit_idle2.o: $(srcdir)/gllist.h +tronbit_idle2.o: $(srcdir)/jwzglesI.h +tronbit_idle2.o: $(srcdir)/jwzgles.h +tronbit_no.o: ../../config.h +tronbit_no.o: $(srcdir)/gllist.h +tronbit_no.o: $(srcdir)/jwzglesI.h +tronbit_no.o: $(srcdir)/jwzgles.h +tronbit.o: ../../config.h +tronbit.o: $(HACK_SRC)/fps.h +tronbit.o: $(srcdir)/gllist.h +tronbit.o: $(srcdir)/gltrackball.h +tronbit.o: $(srcdir)/jwzglesI.h +tronbit.o: $(srcdir)/jwzgles.h +tronbit.o: $(srcdir)/rotator.h +tronbit.o: $(HACK_SRC)/screenhackI.h +tronbit.o: $(srcdir)/sphere.h +tronbit.o: $(UTILS_SRC)/colors.h +tronbit.o: $(UTILS_SRC)/grabscreen.h +tronbit.o: $(UTILS_SRC)/hsv.h +tronbit.o: $(UTILS_SRC)/resources.h +tronbit.o: $(UTILS_SRC)/usleep.h +tronbit.o: $(UTILS_SRC)/visual.h +tronbit.o: $(UTILS_SRC)/xshm.h +tronbit.o: $(UTILS_SRC)/yarandom.h +tronbit.o: $(HACK_SRC)/xlockmoreI.h +tronbit.o: $(HACK_SRC)/xlockmore.h +tronbit_yes.o: ../../config.h +tronbit_yes.o: $(srcdir)/gllist.h +tronbit_yes.o: $(srcdir)/jwzglesI.h +tronbit_yes.o: $(srcdir)/jwzgles.h +tube.o: ../../config.h +tube.o: $(srcdir)/jwzglesI.h +tube.o: $(srcdir)/jwzgles.h +tube.o: $(srcdir)/tube.h +tunnel_draw.o: ../../config.h +tunnel_draw.o: $(HACK_SRC)/fps.h +tunnel_draw.o: $(srcdir)/jwzglesI.h +tunnel_draw.o: $(srcdir)/jwzgles.h +tunnel_draw.o: $(HACK_SRC)/screenhackI.h +tunnel_draw.o: $(srcdir)/tunnel_draw.h +tunnel_draw.o: $(UTILS_SRC)/colors.h +tunnel_draw.o: $(UTILS_SRC)/grabscreen.h +tunnel_draw.o: $(UTILS_SRC)/hsv.h +tunnel_draw.o: $(UTILS_SRC)/resources.h +tunnel_draw.o: $(UTILS_SRC)/usleep.h +tunnel_draw.o: $(UTILS_SRC)/visual.h +tunnel_draw.o: $(UTILS_SRC)/xshm.h +tunnel_draw.o: $(UTILS_SRC)/yarandom.h +tunnel_draw.o: $(HACK_SRC)/xlockmoreI.h +voronoi.o: ../../config.h +voronoi.o: $(HACK_SRC)/fps.h +voronoi.o: $(srcdir)/jwzglesI.h +voronoi.o: $(srcdir)/jwzgles.h +voronoi.o: $(HACK_SRC)/screenhackI.h +voronoi.o: $(UTILS_SRC)/colors.h +voronoi.o: $(UTILS_SRC)/grabscreen.h +voronoi.o: $(UTILS_SRC)/hsv.h +voronoi.o: $(UTILS_SRC)/resources.h +voronoi.o: $(UTILS_SRC)/usleep.h +voronoi.o: $(UTILS_SRC)/visual.h +voronoi.o: $(UTILS_SRC)/xshm.h +voronoi.o: $(UTILS_SRC)/yarandom.h +voronoi.o: $(HACK_SRC)/xlockmoreI.h +voronoi.o: $(HACK_SRC)/xlockmore.h +whale.o: $(srcdir)/atlantis.h +whale.o: ../../config.h +whale.o: $(HACK_SRC)/fps.h +whale.o: $(srcdir)/jwzglesI.h +whale.o: $(srcdir)/jwzgles.h +whale.o: $(HACK_SRC)/screenhackI.h +whale.o: $(UTILS_SRC)/colors.h +whale.o: $(UTILS_SRC)/grabscreen.h +whale.o: $(UTILS_SRC)/hsv.h +whale.o: $(UTILS_SRC)/resources.h +whale.o: $(UTILS_SRC)/usleep.h +whale.o: $(UTILS_SRC)/visual.h +whale.o: $(UTILS_SRC)/yarandom.h +xlock-gl-utils.o: ../../config.h +xlock-gl-utils.o: $(HACK_SRC)/fps.h +xlock-gl-utils.o: $(srcdir)/glxfonts.h +xlock-gl-utils.o: $(srcdir)/jwzglesI.h +xlock-gl-utils.o: $(srcdir)/jwzgles.h +xlock-gl-utils.o: $(HACK_SRC)/screenhackI.h +xlock-gl-utils.o: $(srcdir)/texfont.h +xlock-gl-utils.o: $(UTILS_SRC)/colors.h +xlock-gl-utils.o: $(UTILS_SRC)/grabscreen.h +xlock-gl-utils.o: $(UTILS_SRC)/hsv.h +xlock-gl-utils.o: $(UTILS_SRC)/resources.h +xlock-gl-utils.o: $(UTILS_SRC)/usleep.h +xlock-gl-utils.o: $(UTILS_SRC)/visual.h +xlock-gl-utils.o: $(UTILS_SRC)/xshm.h +xlock-gl-utils.o: $(UTILS_SRC)/yarandom.h +xlock-gl-utils.o: $(HACK_SRC)/xlockmoreI.h +xpm-ximage.o: ../../config.h +xpm-ximage.o: $(srcdir)/xpm-ximage.h +xscreensaver-gl-helper.o: ../../config.h +xscreensaver-gl-helper.o: $(UTILS_SRC)/utils.h +xscreensaver-gl-helper.o: $(UTILS_SRC)/visual.h + diff --git a/hacks/glx/README b/hacks/glx/README new file mode 100644 index 00000000..51425032 --- /dev/null +++ b/hacks/glx/README @@ -0,0 +1,10 @@ + +This directory contains various graphics hacks that requre OpenGL. These are +independent from the xscreensaver program (in the ../../driver/ directory) +but some of them use the utility functions found in the ../../utils/ directory. + +If you have compilation problems, check the parameters in ../../config.h. + +If you're looking for a free implementation of the OpenGL library, +check out . For general OpenGL info, see +. diff --git a/hacks/glx/antinspect.c b/hacks/glx/antinspect.c new file mode 100644 index 00000000..179c44f4 --- /dev/null +++ b/hacks/glx/antinspect.c @@ -0,0 +1,723 @@ +/* + * Permission to use, copy, modify, and distribute this software and its + * documentation for any purpose and without fee is hereby granted, + * provided that the above copyright notice appear in all copies and that + * both that copyright notice and this permission notice appear in + * supporting documentation. + * + * This file is provided AS IS with no warranties of any kind. The author + * shall have no liability with respect to the infringement of copyrights, + * trade secrets or any patents by this file or any part thereof. In no + * event will the author be liable for any lost revenue or profits or + * other special, indirect and consequential damages. + * + * Copyright 2004 Blair Tennessy + * tennessy@cs.ubc.ca + */ + +#ifdef STANDALONE +#define DEFAULTS "*delay: 20000 \n" \ + "*showFPS: False \n" + +# define refresh_antinspect 0 +#include "xlockmore.h" +#else +#include "xlock.h" +#endif + +#ifdef HAVE_COCOA +# include "jwxyz.h" +#else +# include +# include +# include +#endif + +#ifdef HAVE_JWZGLES +# include "jwzgles.h" +#endif /* HAVE_JWZGLES */ + +#include "sphere.h" +#include "gltrackball.h" + +#define DEF_SHADOWS "True" + +static int shadows; + +static XrmOptionDescRec opts[] = { + {"-shadows", ".antinspect.shadows", XrmoptionNoArg, "on"}, + {"+shadows", ".antinspect.shadows", XrmoptionNoArg, "off"} +}; + +static argtype vars[] = { + {&shadows, "shadows", "Shadows", DEF_SHADOWS, t_Bool} +}; + +static OptionStruct desc[] = { + {"-/+shadows", "turn on/off ant shadows"} +}; + +ENTRYPOINT ModeSpecOpt antinspect_opts = {sizeof opts / sizeof opts[0], + opts, + sizeof vars / sizeof vars[0], + vars, + desc}; + +#ifdef USE_MODULES +ModStruct antinspect_description = + {"antinspect", "init_antinspect", "draw_antinspect", "release_antinspect", + "draw_antinspect", "change_antinspect", (char *) NULL, &antinspect_opts, + 1000, 1, 1, 1, 4, 1.0, "", + "draws some ants", 0, NULL}; +#endif + +#define Scale4Window 0.3 +#define Scale4Iconic 0.4 + +#define sqr(A) ((A)*(A)) + +#ifndef Pi +#define Pi M_PI +#endif + +#define ObjAntinspectStrip 0 +#define ObjAntBody 1 +#define MaxObj 2 + +/*************************************************************************/ + +typedef struct { + GLint WindH, WindW; + GLfloat step; + GLfloat ant_position; + GLXContext *glx_context; + trackball_state *trackball; + Bool button_down_p; + int linewidth; + float ant_step; + +} antinspectstruct; + +static const float front_shininess[] = {60.0}; +static const float front_specular[] = {0.7, 0.7, 0.7, 1.0}; +static const float ambient[] = {0.0, 0.0, 0.0, 1.0}; +static const float diffuse[] = {1.0, 1.0, 1.0, 1.0}; +static float position0[] = {0.0, 3.0, 0.0, 1.0}; +static const float position1[] = {-1.0, -3.0, 1.0, 0.0}; +static const float lmodel_ambient[] = {0.5, 0.5, 0.5, 1.0}; +static const float lmodel_twoside[] = {GL_TRUE}; + +static const float MaterialRed[] = {0.6, 0.0, 0.0, 1.0}; +static const float MaterialOrange[] = {1.0, 0.69, 0.00, 1.0}; +static const float MaterialGray[] = {0.2, 0.2, 0.2, 1.0}; +static const float MaterialBlack[] = {0.1, 0.1, 0.1, 0.4}; +static const float MaterialShadow[] = {0.3, 0.3, 0.3, 0.3}; +static const float MaterialGray5[] = {0.5, 0.5, 0.5, 0.3}; +static const float MaterialGray6[] = {0.6, 0.6, 0.6, 1.0}; + +static antinspectstruct *antinspect = (antinspectstruct *) NULL; + +#define NUM_SCENES 2 + +enum {X, Y, Z, W}; +enum {A, B, C, D}; + +/* create a matrix that will project the desired shadow */ +static void shadowmatrix(GLfloat shadowMat[4][4], + const GLfloat groundplane[4], + const GLfloat lightpos[4]) +{ + GLfloat dot; + + /* find dot product between light position vector and ground plane normal */ + dot = groundplane[X] * lightpos[X] + + groundplane[Y] * lightpos[Y] + + groundplane[Z] * lightpos[Z] + + groundplane[W] * lightpos[W]; + + shadowMat[0][0] = dot - lightpos[X] * groundplane[X]; + shadowMat[1][0] = 0.f - lightpos[X] * groundplane[Y]; + shadowMat[2][0] = 0.f - lightpos[X] * groundplane[Z]; + shadowMat[3][0] = 0.f - lightpos[X] * groundplane[W]; + + shadowMat[X][1] = 0.f - lightpos[Y] * groundplane[X]; + shadowMat[1][1] = dot - lightpos[Y] * groundplane[Y]; + shadowMat[2][1] = 0.f - lightpos[Y] * groundplane[Z]; + shadowMat[3][1] = 0.f - lightpos[Y] * groundplane[W]; + + shadowMat[X][2] = 0.f - lightpos[Z] * groundplane[X]; + shadowMat[1][2] = 0.f - lightpos[Z] * groundplane[Y]; + shadowMat[2][2] = dot - lightpos[Z] * groundplane[Z]; + shadowMat[3][2] = 0.f - lightpos[Z] * groundplane[W]; + + shadowMat[X][3] = 0.f - lightpos[W] * groundplane[X]; + shadowMat[1][3] = 0.f - lightpos[W] * groundplane[Y]; + shadowMat[2][3] = 0.f - lightpos[W] * groundplane[Z]; + shadowMat[3][3] = dot - lightpos[W] * groundplane[W]; +} + +static const GLfloat ground[4] = {0.0, 1.0, 0.0, -0.00001}; + +/* simple filled sphere */ +static Bool mySphere(float radius) +{ +#if 0 + GLUquadricObj *quadObj; + + if((quadObj = gluNewQuadric()) == 0) + return False; + gluQuadricDrawStyle(quadObj, (GLenum) GLU_FILL); + gluSphere(quadObj, radius, 16, 16); + gluDeleteQuadric(quadObj); +#else + glPushMatrix(); + glScalef (radius, radius, radius); + glRotatef (90, 1, 0, 0); + unit_sphere (16, 16, False); + glPopMatrix(); +#endif + return True; +} + +/* caged sphere */ +static Bool mySphere2(float radius) +{ +#if 0 + GLUquadricObj *quadObj; + + if((quadObj = gluNewQuadric()) == 0) + return False; + gluQuadricDrawStyle(quadObj, (GLenum) GLU_LINE);/*GLU_SILHOUETTE);*/ + gluSphere(quadObj, radius, 16, 8); + gluDeleteQuadric(quadObj); +#else + glPushMatrix(); + glScalef (radius, radius, radius); + glRotatef (90, 1, 0, 0); + unit_sphere (16, 8, True); + glPopMatrix(); +#endif + + return True; +} + +/* null cone */ +static Bool myCone2(float radius) +{ + return True; +} + +/* draw an ant */ +static Bool draw_antinspect_ant(ModeInfo *mi, antinspectstruct * mp, + const float *Material, int mono, + Bool (*sphere)(float), Bool (*cone)(float)) +{ + float cos1 = cos(mp->ant_step); + float cos2 = cos(mp->ant_step + 2 * Pi / 3); + float cos3 = cos(mp->ant_step + 4 * Pi / 3); + float sin1 = sin(mp->ant_step); + float sin2 = sin(mp->ant_step + 2 * Pi / 3); + float sin3 = sin(mp->ant_step + 4 * Pi / 3); + + if (mono) + glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, MaterialGray5); + else + glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, Material); + glEnable(GL_CULL_FACE); + glPushMatrix(); + glScalef(1, 1.3, 1); + if (!((*sphere)(0.18))) + return False; + glScalef(1, 1 / 1.3, 1); + glTranslatef(0.00, 0.30, 0.00); + if (!((*sphere)(0.2))) + return False; + + glTranslatef(-0.05, 0.17, 0.05); + glRotatef(-90, 1, 0, 0); + glRotatef(-25, 0, 1, 0); + if (!((*cone)(0.05))) + return False; + glTranslatef(0.00, 0.10, 0.00); + if (!((*cone)(0.05))) + return False; + glRotatef(25, 0, 1, 0); + glRotatef(90, 1, 0, 0); + + glScalef(1, 1.3, 1); + glTranslatef(0.15, -0.65, 0.05); + if (!((*sphere)(0.25))) + return False; + glScalef(1, 1 / 1.3, 1); + glPopMatrix(); + glDisable(GL_CULL_FACE); + + glDisable(GL_LIGHTING); + + /* ANTENNAS */ + glBegin(GL_LINES); + if (mono) + glColor3fv(MaterialGray5); + else + glColor3fv(Material); + glVertex3f(0.00, 0.30, 0.00); + glColor3fv(MaterialGray); + glVertex3f(0.40, 0.70, 0.40); + mi->polygon_count++; + if (mono) + glColor3fv(MaterialGray5); + else + glColor3fv(Material); + glVertex3f(0.00, 0.30, 0.00); + glColor3fv(MaterialGray); + glVertex3f(0.40, 0.70, -0.40); + mi->polygon_count++; + glEnd(); + glBegin(GL_POINTS); + if (mono) + glColor3fv(MaterialGray6); + else + glColor3fv(Material); + glVertex3f(0.40, 0.70, 0.40); + mi->polygon_count++; + glVertex3f(0.40, 0.70, -0.40); + mi->polygon_count++; + glEnd(); + + /* LEFT-FRONT ARM */ + glBegin(GL_LINE_STRIP); + if (mono) + glColor3fv(MaterialGray5); + else + glColor3fv(Material); + glVertex3f(0.00, 0.05, 0.18); + glVertex3f(0.35 + 0.05 * cos1, 0.15, 0.25); + mi->polygon_count++; + glColor3fv(MaterialGray); + glVertex3f(-0.20 + 0.05 * cos1, 0.25 + 0.1 * sin1, 0.45); + mi->polygon_count++; + glEnd(); + + /* LEFT-CENTER ARM */ + glBegin(GL_LINE_STRIP); + if (mono) + glColor3fv(MaterialGray5); + else + glColor3fv(Material); + glVertex3f(0.00, 0.00, 0.18); + glVertex3f(0.35 + 0.05 * cos2, 0.00, 0.25); + mi->polygon_count++; + glColor3fv(MaterialGray); + glVertex3f(-0.20 + 0.05 * cos2, 0.00 + 0.1 * sin2, 0.45); + mi->polygon_count++; + glEnd(); + mi->polygon_count++; + + /* LEFT-BACK ARM */ + glBegin(GL_LINE_STRIP); + if (mono) + glColor3fv(MaterialGray5); + else + glColor3fv(Material); + glVertex3f(0.00, -0.05, 0.18); + glVertex3f(0.35 + 0.05 * cos3, -0.15, 0.25); + mi->polygon_count++; + glColor3fv(MaterialGray); + glVertex3f(-0.20 + 0.05 * cos3, -0.25 + 0.1 * sin3, 0.45); + mi->polygon_count++; + glEnd(); + + /* RIGHT-FRONT ARM */ + glBegin(GL_LINE_STRIP); + if (mono) + glColor3fv(MaterialGray5); + else + glColor3fv(Material); + glVertex3f(0.00, 0.05, -0.18); + glVertex3f(0.35 - 0.05 * sin1, 0.15, -0.25); + mi->polygon_count++; + glColor3fv(MaterialGray); + glVertex3f(-0.20 - 0.05 * sin1, 0.25 + 0.1 * cos1, -0.45); + mi->polygon_count++; + glEnd(); + + /* RIGHT-CENTER ARM */ + glBegin(GL_LINE_STRIP); + if (mono) + glColor3fv(MaterialGray5); + else + glColor3fv(Material); + glVertex3f(0.00, 0.00, -0.18); + glVertex3f(0.35 - 0.05 * sin2, 0.00, -0.25); + mi->polygon_count++; + glColor3fv(MaterialGray); + glVertex3f(-0.20 - 0.05 * sin2, 0.00 + 0.1 * cos2, -0.45); + mi->polygon_count++; + glEnd(); + + /* RIGHT-BACK ARM */ + glBegin(GL_LINE_STRIP); + if (mono) + glColor3fv(MaterialGray5); + else + glColor3fv(Material); + glVertex3f(0.00, -0.05, -0.18); + glVertex3f(0.35 - 0.05 * sin3, -0.15, -0.25); + mi->polygon_count++; + glColor3fv(MaterialGray); + glVertex3f(-0.20 - 0.05 * sin3, -0.25 + 0.1 * cos3, -0.45); + mi->polygon_count++; + glEnd(); + + glEnable(GL_LIGHTING); + + return True; +} + +/* only works with 3 right now */ +#define ANTCOUNT 3 + +static const float MaterialBen[4] = {0.25, 0.30, 0.46, 1.0}; + +static const float* antmaterial[ANTCOUNT] = + {MaterialRed, MaterialBen, MaterialOrange}; +static double antposition[ANTCOUNT] = {0.0, 120.0, 240.0}; +static const double antvelocity[ANTCOUNT] = {0.3, 0.3, 0.3}; +static const double antsphere[ANTCOUNT] = {1.2, 1.2, 1.2}; + +/* permutations */ +static const double antorder[6][ANTCOUNT] = {{0, 1, 2}, + {0, 2, 1}, + {2, 0, 1}, + {2, 1, 0}, + {1, 2, 0}, + {1, 0, 2}}; + +/* draw the scene */ +static Bool draw_antinspect_strip(ModeInfo * mi) +{ + antinspectstruct *mp = &antinspect[MI_SCREEN(mi)]; + int i, j; + int mono = MI_IS_MONO(mi); + + int ro = (((int)antposition[1])/(360/(2*ANTCOUNT))) % (2*ANTCOUNT); + + glEnable(GL_TEXTURE_2D); + position0[1] = 9.6; + glLightfv(GL_LIGHT0, GL_POSITION, position0); + + glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, MaterialGray5); + glRotatef(-30.0, 0.0, 1.0, 0.0); + + glDisable(GL_TEXTURE_2D); + glDisable(GL_BLEND); + + /* render ground plane */ + glBegin(GL_TRIANGLES); + glColor4fv(MaterialShadow); + glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, MaterialBlack); + glNormal3f(0.0, 1.0, 0.0); + + /* middle tri */ + glVertex3f(0.0, 0.0, -1.0); + glVertex3f(-sqrt(3.0)/2.0, 0.0, 0.5); + glVertex3f(sqrt(3.0)/2.0, 0.0, 0.5); + mi->polygon_count++; + glEnd(); + + /* rotate */ + for(i = 0; i < 3; ++i) { + glRotatef(120.0, 0.0, 1.0, 0.0); + glBegin(GL_TRIANGLES); + glVertex3f(0.0, 0.0, 1.0 + 3.0); + glVertex3f(sqrt(3.0)/2.0, 0.0, -0.5 + 3.0); + glVertex3f(-sqrt(3.0)/2.0, 0.0, -0.5 + 3.0); + mi->polygon_count++; + glEnd(); + } + + /* first render shadows -- no depth required */ + if(shadows) { + GLfloat m[4][4]; + shadowmatrix(m, ground, position0); + + glColor4fv(MaterialShadow); + glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, MaterialShadow); + + glDisable(GL_BLEND); + glDisable(GL_LIGHTING); + + /* display ant shadow */ + glPushMatrix(); + glTranslatef(0.0, 0.001, 0.0); + glMultMatrixf(m[0]); + + for(i = 0; i < ANTCOUNT; ++i) { + + /* draw ant */ + glPushMatrix(); + + /* center */ + glRotatef(antposition[i], 0.0, 1.0, 0.0); + glTranslatef(2.4, 0.0, 0.0); + glTranslatef(0.0, antsphere[i], 0.0); + glRotatef(90.0, 0.0, 1.0, 0.0); + + /* orient ant */ + glRotatef(10.0, 0.0, 1.0, 0.0); + glRotatef(40.0, 0.0, 0.0, 1.0); + glTranslatef(0.0, -0.8, 0.0); + glRotatef(180.0, 0.0, 1.0, 0.0); + glRotatef(90.0, 0.0, 0.0, 1.0); + + /* set colour */ + glColor4fv(MaterialShadow); + glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, MaterialShadow); + + if(antposition[i] > 360.0) + antposition[i] = 0.0; + draw_antinspect_ant(mi, mp, MaterialShadow, mono, mySphere2, myCone2); + + glDisable(GL_BLEND); + glDisable(GL_LIGHTING); + + /* draw sphere */ + glRotatef(-20.0, 1.0, 0.0, 0.0); + glRotatef(-mp->ant_step*2, 0.0, 0.0, 1.0); + glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, MaterialShadow); + mySphere2(1.2); + + glPopMatrix(); + } + + glPopMatrix(); + } + + glEnable(GL_LIGHTING); + + /* truants */ + for(j = 0; j < ANTCOUNT; ++j) { + /* determine rendering order */ + i = antorder[ro][j]; + + glPushMatrix(); + + /* center */ + glRotatef(antposition[i], 0.0, 1.0, 0.0); + glTranslatef(2.4, 0.0, 0.0); + glTranslatef(0.0, antsphere[i], 0.0); + glRotatef(90.0, 0.0, 1.0, 0.0); + + /* draw ant */ + glPushMatrix(); + glRotatef(10.0, 0.0, 1.0, 0.0); + glRotatef(40.0, 0.0, 0.0, 1.0); + glTranslatef(0.0, -0.8, 0.0); + glRotatef(180.0, 0.0, 1.0, 0.0); + glRotatef(90.0, 0.0, 0.0, 1.0); + if(antposition[i] > 360.0) + antposition[i] = 0.0; + glEnable(GL_BLEND); + draw_antinspect_ant(mi, mp, antmaterial[i], mono, mySphere2, myCone2); + glDisable(GL_BLEND); + glPopMatrix(); + + /* draw sphere */ + glRotatef(-20.0, 1.0, 0.0, 0.0); + glRotatef(-mp->ant_step*2, 0.0, 0.0, 1.0); + glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, mono ? MaterialGray5 : antmaterial[i]); + mySphere2(1.2); + glEnable(GL_BLEND); + glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, MaterialBlack); + mySphere(1.16); + glDisable(GL_BLEND); + + glPopMatrix(); + + /* finally, evolve */ + antposition[i] += antvelocity[i]; + } + + /* but the step size is the same! */ + mp->ant_step += 0.2; + + mp->ant_position += 1; + return True; +} + +ENTRYPOINT void reshape_antinspect(ModeInfo * mi, int width, int height) +{ + double h = (GLfloat) height / (GLfloat) width; + antinspectstruct *mp = &antinspect[MI_SCREEN(mi)]; + mp->linewidth = (width / 512) + 1; + + glViewport(0, 0, mp->WindW = (GLint) width, mp->WindH = (GLint) height); + glMatrixMode(GL_PROJECTION); + glLoadIdentity(); + + gluPerspective(45, 1/h, 7.0, 20.0); + + glMatrixMode(GL_MODELVIEW); + glLineWidth(mp->linewidth); + glPointSize(mp->linewidth); +} + +static void pinit(void) +{ + glClearDepth(1.0); + glLightfv(GL_LIGHT0, GL_AMBIENT, ambient); + glLightfv(GL_LIGHT0, GL_DIFFUSE, diffuse); + glLightfv(GL_LIGHT0, GL_POSITION, position0); + glLightfv(GL_LIGHT1, GL_AMBIENT, ambient); + glLightfv(GL_LIGHT1, GL_DIFFUSE, diffuse); + glLightfv(GL_LIGHT1, GL_POSITION, position1); + glLightModelfv(GL_LIGHT_MODEL_AMBIENT, lmodel_ambient); + glLightModelfv(GL_LIGHT_MODEL_TWO_SIDE, lmodel_twoside); + glEnable(GL_LIGHTING); + glEnable(GL_LIGHT0); + glEnable(GL_LIGHT1); + glEnable(GL_NORMALIZE); + glFrontFace(GL_CCW); + + /* antinspect */ + glShadeModel(GL_SMOOTH); + glEnable(GL_DEPTH_TEST); + glDisable(GL_TEXTURE_2D); + + glMaterialfv(GL_FRONT_AND_BACK, GL_SHININESS, front_shininess); + glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, front_specular); +} + +ENTRYPOINT void release_antinspect(ModeInfo * mi) +{ + if(antinspect) { + free((void *) antinspect); + antinspect = (antinspectstruct *) NULL; + } + FreeAllGL(mi); +} + +ENTRYPOINT Bool antinspect_handle_event (ModeInfo *mi, XEvent *event) +{ + antinspectstruct *mp = &antinspect[MI_SCREEN(mi)]; + + if(event->xany.type == ButtonPress && event->xbutton.button == Button1) { + mp->button_down_p = True; + gltrackball_start(mp->trackball, + event->xbutton.x, event->xbutton.y, + MI_WIDTH (mi), MI_HEIGHT (mi)); + return True; + } + else if(event->xany.type == ButtonRelease && + event->xbutton.button == Button1) { + mp->button_down_p = False; + return True; + } + else if (event->xany.type == ButtonPress && + (event->xbutton.button == Button4 || + event->xbutton.button == Button5 || + event->xbutton.button == Button6 || + event->xbutton.button == Button7)) + { + gltrackball_mousewheel (mp->trackball, event->xbutton.button, 5, + !event->xbutton.state); + return True; + } + else if(event->xany.type == MotionNotify && mp->button_down_p) { + gltrackball_track (mp->trackball, + event->xmotion.x, event->xmotion.y, + MI_WIDTH (mi), MI_HEIGHT (mi)); + return True; + } + + return False; +} + +ENTRYPOINT void init_antinspect(ModeInfo * mi) +{ + antinspectstruct *mp; + + if(antinspect == NULL) { + if((antinspect = (antinspectstruct *) calloc(MI_NUM_SCREENS(mi), + sizeof (antinspectstruct))) == NULL) + return; + } + mp = &antinspect[MI_SCREEN(mi)]; + mp->step = NRAND(90); + mp->ant_position = NRAND(90); + mp->trackball = gltrackball_init (); + + if ((mp->glx_context = init_GL(mi)) != NULL) { + reshape_antinspect(mi, MI_WIDTH(mi), MI_HEIGHT(mi)); + glDrawBuffer(GL_BACK); + pinit(); + } + else + MI_CLEARWINDOW(mi); + + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); +} + +ENTRYPOINT void draw_antinspect(ModeInfo * mi) +{ + antinspectstruct *mp; + + Display *display = MI_DISPLAY(mi); + Window window = MI_WINDOW(mi); + + if(!antinspect) + return; + mp = &antinspect[MI_SCREEN(mi)]; + + MI_IS_DRAWN(mi) = True; + + if(!mp->glx_context) + return; + + glXMakeCurrent(display, window, *(mp->glx_context)); + + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + + glPushMatrix(); + glRotatef(current_device_rotation(), 0, 0, 1); + + mi->polygon_count = 0; + + /* position camera --- this works well, we can peer inside + the antbubble */ + glTranslatef(0.0, 0.0, -10.0); + gltrackball_rotate(mp->trackball); + glRotatef((15.0/2.0 + 15.0*sin(mp->ant_step/100.0)), 1.0, 0.0, 0.0); + glRotatef(30.0, 1.0, 0.0, 0.0); + glRotatef(180.0, 0.0, 1.0, 0.0); + + if (!draw_antinspect_strip(mi)) { + release_antinspect(mi); + return; + } + + glPopMatrix(); + + if (MI_IS_FPS(mi)) do_fps (mi); + glFlush(); + + glXSwapBuffers(display, window); + + mp->step += 0.025; +} + +#ifndef STANDALONE +ENTRYPOINT void change_antinspect(ModeInfo * mi) +{ + antinspectstruct *mp = &antinspect[MI_SCREEN(mi)]; + + if (!mp->glx_context) + return; + + glXMakeCurrent(MI_DISPLAY(mi), MI_WINDOW(mi), *(mp->glx_context)); + pinit(); +} +#endif /* !STANDALONE */ + + +XSCREENSAVER_MODULE ("AntInspect", antinspect) diff --git a/hacks/glx/antinspect.man b/hacks/glx/antinspect.man new file mode 100644 index 00000000..804d7a4e --- /dev/null +++ b/hacks/glx/antinspect.man @@ -0,0 +1,56 @@ +.TH XScreenSaver 1 "March 2004" +.SH NAME +antinspect \- ant model inspection screenhack +.SH SYNOPSIS +.B antinspect +[\-display \fIhost:display.screen\fP] [\-window] [\-root] [\-install] +[\-visual \fIvisual\fP] [\-delay \fImicroseconds\fP] [\-fps] +.SH DESCRIPTION +The \fIantinspect\fP code displays three ant-powered balls churning in a +circle. +.SH OPTIONS +.I antinspect +accepts the following options: +.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 \-install +Install a private colormap for the window. +.TP 8 +.B \-shadows +Draw shadows on ground +.TP 8 +.B \-visual \fIvisual\fP\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. +.B \-fps +Display the current frame rate, CPU load, and polygon count. +.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) +.BR xscreensaver\-demo (1), +.BR xscreensaver\-getimage (1) +.SH COPYRIGHT +Copyright \(co 2004 by Blair Tennessy. 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 +Blair Tennessy , 15-March-2004. + diff --git a/hacks/glx/antmaze.c b/hacks/glx/antmaze.c new file mode 100644 index 00000000..0ca7f05f --- /dev/null +++ b/hacks/glx/antmaze.c @@ -0,0 +1,1648 @@ +/* + * Permission to use, copy, modify, and distribute this software and its + * documentation for any purpose and without fee is hereby granted, + * provided that the above copyright notice appear in all copies and that + * both that copyright notice and this permission notice appear in + * supporting documentation. + * + * This file is provided AS IS with no warranties of any kind. The author + * shall have no liability with respect to the infringement of copyrights, + * trade secrets or any patents by this file or any part thereof. In no + * event will the author be liable for any lost revenue or profits or + * other special, indirect and consequential damages. + * + * Copyright 2004 Blair Tennessy + * tennessy@cs.ubc.ca + */ + +#if !defined( lint ) && !defined( SABER ) +static const char sccsid[] = "@(#)antmaze.c 5.01 2001/03/01 xlockmore"; +#endif + +#ifdef STANDALONE +# define MODE_antmaze +# define DEFAULTS "*delay: 20000 \n" \ + "*showFPS: False \n" \ + "*fpsSolid: True \n" + +# define refresh_antmaze 0 +# include "xlockmore.h" /* from the xscreensaver distribution */ +#else /* !STANDALONE */ +# include "xlock.h" /* from the xlockmore distribution */ +#endif /* !STANDALONE */ + +#ifdef HAVE_COCOA +# include "jwxyz.h" +#else +# include +# include +# include +#endif + +#ifdef HAVE_JWZGLES +# include "jwzgles.h" +#endif /* HAVE_JWZGLES */ + +#ifdef MODE_antmaze + + +#include "sphere.h" +#include "tube.h" +#include "rotator.h" +#include "gltrackball.h" + +#define DEF_SOLIDANTMAZE "False" +#define DEF_NOANTS "False" + +static int solidantmaze; +static int noants; + +static XrmOptionDescRec opts[] = +{ + {"-solidantmaze", ".antmaze.solidantmaze", XrmoptionNoArg, "on"}, + {"+solidantmaze", ".antmaze.solidantmaze", XrmoptionNoArg, "off"}, + {"-noants", ".antmaze.noants", XrmoptionNoArg, "on"}, + {"+noants", ".antmaze.noants", XrmoptionNoArg, "off"} +}; +static argtype vars[] = +{ + {&solidantmaze, "solidantmaze", "Solidantmaze", DEF_SOLIDANTMAZE, t_Bool}, + {&noants, "noants", "Noants", DEF_NOANTS, t_Bool} +}; + +static OptionStruct desc[] = +{ + {"-/+solidantmaze", "select between a SOLID or a NET Antmaze Strip"}, + {"-/+noants", "turn on/off walking ants"} +}; + +ENTRYPOINT ModeSpecOpt antmaze_opts = +{sizeof opts / sizeof opts[0], opts, sizeof vars / sizeof vars[0], vars, desc}; + +#ifdef USE_MODULES +ModStruct antmaze_description = +{"antmaze", "init_antmaze", "draw_antmaze", "release_antmaze", + "draw_antmaze", "change_antmaze", NULL, &antmaze_opts, + 1000, 1, 1, 1, 4, 1.0, "", + "draws some ants", 0, NULL}; + +#endif + +#define Scale4Window 0.3 +#define Scale4Iconic 0.4 + +#define sqr(A) ((A)*(A)) + +#ifndef Pi +#define Pi M_PI +#endif + +#define ObjAntmazeStrip 0 +#define ObjAntBody 1 +#define MaxObj 2 + +/*************************************************************************/ + +#include "ants.h" + +#define ANTCOUNT 5 +#define PI 3.14157 + +#define EPSILON 0.01 +#define BOARDSIZE 10 +#define BOARDCOUNT 2 +#define PARTS 20 + +#define checkImageWidth 64 +#define checkImageHeight 64 + +typedef struct { + GLint WindH, WindW; + GLfloat step; + GLfloat ant_position; + GLXContext *glx_context; + rotator *rot; + trackball_state *trackball; + Bool button_down_p; + + int focus; + int currentboard; + + double antdirection[ANTCOUNT]; + double antposition[ANTCOUNT][3]; + int anton[ANTCOUNT]; + + double antvelocity[ANTCOUNT]; + double antsize[ANTCOUNT]; + int bposition[ANTCOUNT][2]; + int board[BOARDCOUNT][10][10]; + + int part[ANTCOUNT]; + double antpath[ANTCOUNT][PARTS][2]; + int antpathlength[ANTCOUNT]; + + GLubyte checkers[checkImageWidth][checkImageHeight][3]; + + GLuint checktexture, brushedtexture; + double elevator; + + double ant_step; + double first_ant_step; + int started; + int introduced; + int entroducing; + + double fadeout; + double fadeoutspeed; + + int mag; + +} antmazestruct; + +static antmazestruct *antmaze = (antmazestruct *) NULL; + + +static const GLfloat MaterialRed[] = {0.6, 0.0, 0.0, 1.0}; +/*static const GLfloat MaterialMagenta[] = {0.6, 0.2, 0.5, 1.0};*/ +static const GLfloat MaterialGray8[] = {0.8, 0.8, 0.8, 1.0}; +static const GLfloat MaterialGray35[] = {0.30, 0.30, 0.30, 1.0}; +static const GLfloat MaterialGray4[] = {0.40, 0.40, 0.40, 1.0}; +static const GLfloat MaterialOrange[] = {1.0, 0.69, 0.00, 1.0}; +static const GLfloat MaterialGreen[] = {0.1, 0.4, 0.2, 1.0}; + +/* lighting variables */ +static const GLfloat front_shininess[] = {60.0}; +static const GLfloat front_specular[] = {0.8, 0.8, 0.8, 1.0}; +static const GLfloat ambient[] = {0.1, 0.1, 0.1, 1.0}; +/*static const GLfloat ambient2[] = {0.0, 0.0, 0.0, 0.0};*/ +static const GLfloat diffuse[] = {0.8, 0.8, 0.8, 1.0}; +static const GLfloat position0[] = {1.0, 5.0, 1.0, 1.0}; +static const GLfloat position1[] = {-1.0, -5.0, 1.0, 1.0}; +/*static const GLfloat lmodel_ambient[] = {0.8, 0.8, 0.8, 1.0};*/ +/*static const GLfloat lmodel_twoside[] = {GL_TRUE};*/ +/*static const GLfloat spotlight_ambient[] = { 0.0, 0.0, 0.0, 1.0 };*/ +/*static const GLfloat spotlight_diffuse[] = { 1.0, 1.0, 1.0, 1.0 };*/ + +#define NUM_SCENES 2 + +/* filled sphere */ +static Bool mySphere(float radius) +{ +#if 0 + GLUquadricObj *quadObj; + + if((quadObj = gluNewQuadric()) == 0) + return False; + gluQuadricDrawStyle(quadObj, (GLenum) GLU_FILL); + gluSphere(quadObj, radius, 16, 16); + gluDeleteQuadric(quadObj); +#else + glPushMatrix(); + glScalef (radius, radius, radius); + glRotatef (90, 1, 0, 0); + unit_sphere (16, 16, False); + glPopMatrix(); +#endif + return True; +} + +#if 0 +/* silhouette sphere */ +static Bool mySphere2(float radius) +{ + GLUquadricObj *quadObj; + + if((quadObj = gluNewQuadric()) == 0) + return False; + gluQuadricDrawStyle(quadObj, (GLenum) GLU_SILHOUETTE); + gluSphere(quadObj, radius, 16, 8); + gluDeleteQuadric(quadObj); + + return True; +} +#endif + +/* textured sphere */ +static Bool mySphereTex(float radius) +{ +#if 0 + GLUquadricObj *quadObj; + + if((quadObj = gluNewQuadric()) == 0) + return False; + gluQuadricDrawStyle(quadObj, (GLenum) GLU_FILL); + gluQuadricTexture(quadObj, GL_TRUE); + gluQuadricNormals(quadObj, GLU_SMOOTH); + gluSphere(quadObj, radius, 32, 16); + gluDeleteQuadric(quadObj); +#else + glPushMatrix(); + glScalef (radius, radius, radius); + glRotatef (90, 1, 0, 0); + unit_sphere (32, 16, False); + glPopMatrix(); +#endif + + return True; +} + +/* filled cone */ +static Bool myCone(float radius) +{ +#if 0 + GLUquadricObj *quadObj; + + if ((quadObj = gluNewQuadric()) == 0) + return False; + gluQuadricDrawStyle(quadObj, (GLenum) GLU_FILL); + gluCylinder(quadObj, radius, 0, radius * 2, 8, 1); + gluDeleteQuadric(quadObj); +#else + cone (0, 0, 0, + 0, 0, radius * 2, + radius, 0, + 8, True, True, False); +#endif + return True; +} + +/* no cone */ +static Bool myCone2(float radius) { return True; } + +#define MATERIALS 4 +static const float *antmaterial[ANTCOUNT] = + {MaterialRed, MaterialGray35, MaterialGray4, MaterialOrange, MaterialGreen}; + +static const float *materials[MATERIALS] = + {MaterialRed, MaterialGray35, MaterialGray4, MaterialOrange}; + + +static void makeCheckImage(antmazestruct *mp) +{ + int i, j; + + for (i = 0; i < checkImageWidth; i++) { + for (j = 0; j < checkImageHeight; j++) { + if(((((i&0x8)==0)^((j&0x8)))==0)) { + int c = 102 + random()%32; + mp->checkers[i][j][0] = c; + mp->checkers[i][j][1] = c; + mp->checkers[i][j][2] = c; + } + else { + int c = 153 + random()%32; + mp->checkers[i][j][0] = c;/*153;*/ + mp->checkers[i][j][1] = c;/*c;*//*0;*/ + mp->checkers[i][j][2] = c;/*c;*//*0;*/ + } + } + } + + glGenTextures(1, &mp->checktexture); + glBindTexture(GL_TEXTURE_2D, mp->checktexture); + + glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_S,GL_REPEAT); + glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_T,GL_REPEAT); + glTexImage2D(GL_TEXTURE_2D, 0, 3, checkImageWidth, + checkImageHeight, 0, GL_RGB, GL_UNSIGNED_BYTE, + &mp->checkers[0][0]); + glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); +} + +static void makeBrushedImage(antmazestruct *mp) +{ + int i, j, c; + + for(i = 0; i < checkImageWidth; ++i) + for(j = 0; j < checkImageHeight; ++j) { + + c = 102+102*fabs(sin(2.0*i / Pi)*sin(2.0*j/Pi)) + random()%51; + +/* c = (i+j)%8==0 || (i+j+5)%8==0 ? 153 : 102; */ + + mp->checkers[i][j][0] = c; + mp->checkers[i][j][1] = c; + mp->checkers[i][j][2] = c; + } + +/* for (i = 0; i < checkImageWidth; i++) { */ +/* for (j = 0; j < checkImageHeight; j++) { */ +/* int c = 102 + pow((random()%1000)/1000.0, 4)*103; */ +/* checkers[i][j][0] = c; */ +/* checkers[i][j][1] = c; */ +/* checkers[i][j][2] = c; */ +/* } */ +/* } */ + +/* /\* smooth *\/ */ +/* for (i = 0; i < checkImageWidth; i++) { */ +/* for (j = 0; j < checkImageHeight; j++) { */ +/* int a = checkers[(i+checkImageWidth+1)%checkImageWidth][j][0] + */ +/* 4*checkers[i][j][0] + checkers[(i+1)%checkImageWidth][j][0]; */ +/* a /= 6; */ +/* checkers[i][j][0] = a; */ +/* checkers[i][j][1] = a; */ +/* checkers[i][j][2] = a; */ +/* } */ +/* } */ + + glGenTextures(1, &mp->brushedtexture); + glBindTexture(GL_TEXTURE_2D, mp->brushedtexture); + + glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_S,GL_REPEAT); + glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_T,GL_REPEAT); + glTexImage2D(GL_TEXTURE_2D, 0, 3, checkImageWidth, + checkImageHeight, 0, GL_RGB, GL_UNSIGNED_BYTE, + &mp->checkers[0][0]); + glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); +} + +#if 0 +static void draw_wall(ModeInfo *mi, double x1, double z1, double x2, double z2) +{ + float x = fabs(x2 - x1)/2.0; + + glBegin(GL_QUADS); + + /* draw top */ + glNormal3f(0.0, 1.0, 0.0); + glTexCoord2f(0.0, 0.0); + glVertex3f(x1, 1.0, z1+0.25); + glTexCoord2f(x, 0.0); + glVertex3f(x2, 1.0, z2+0.25); + glTexCoord2f(x, 0.25); + glVertex3f(x2, 1.0, z2-0.25); + glTexCoord2f(0.0, 0.25); + glVertex3f(x1, 1.0, z1-0.25); + mi->polygon_count++; + + /* draw sides */ + glNormal3f(0.0, 0.0, 1.0); + glTexCoord2f(0.0, 0.0); + glVertex3f(x1, 0.0, z1+0.25); + glTexCoord2f(x, 0.0); + glVertex3f(x2, 0.0, z2+0.25); + glTexCoord2f(x, 0.5); + glVertex3f(x2, 1.0, z2+0.25); + glTexCoord2f(0.0, 0.5); + glVertex3f(x1, 1.0, z1+0.25); + mi->polygon_count++; + + glNormal3f(0.0, 0.0, -1.0); + glTexCoord2f(0.0, 0.0); + glVertex3f(x1, 0.0, z1-0.25); + glTexCoord2f(x, 0.0); + glVertex3f(x2, 0.0, z2-0.25); + glTexCoord2f(x, 0.5); + glVertex3f(x2, 1.0, z2-0.25); + glTexCoord2f(0.0, 0.5); + glVertex3f(x1, 1.0, z1-0.25); + mi->polygon_count++; + + /* draw ends */ + glNormal3f(1.0, 0.0, 0.0); + glTexCoord2f(0.0, 0.0); + glVertex3f(x2, 0.0, z2+0.25); + glTexCoord2f(0.25, 0.0); + glVertex3f(x2, 0.0, z2-0.25); + glTexCoord2f(0.25, 0.5); + glVertex3f(x2, 1.0, z2-0.25); + glTexCoord2f(0.0, 0.5); + glVertex3f(x2, 1.0, z2+0.25); + mi->polygon_count++; + + glNormal3f(-1.0, 0.0, 0.0); + glTexCoord2f(0.0, 0.0); + glVertex3f(x1, 0.0, z1-0.25); + glTexCoord2f(0.25, 0.0); + glVertex3f(x1, 0.0, z1+0.25); + glTexCoord2f(0.25, 0.5); + glVertex3f(x1, 1.0, z1+0.25); + glTexCoord2f(0.0, 0.5); + glVertex3f(x1, 1.0, z1-0.25); + mi->polygon_count++; + + glEnd(); +} +#endif + +static void draw_board(ModeInfo *mi, antmazestruct *mp) +{ + + int i, j; + double h = 0.5; + double stf = 0.0625; + + glBindTexture(GL_TEXTURE_2D, mp->checktexture); + + glBegin(GL_QUADS); + + for(i = 0; i < BOARDSIZE; ++i) + for(j = 0; j < BOARDSIZE; ++j) { + if(mp->board[mp->currentboard][j][i]) { + +/* /\* draw top *\/ */ +/* glNormal3f(0.0, 1.0, 0.0); */ +/* glTexCoord2f(0.0 + stf, 0.0 + stf); */ +/* glVertex3f(i-0.5, h, j+0.5); */ +/* glTexCoord2f(1.0 + stf, 0.0 + stf); */ +/* glVertex3f(i+0.5, h, j+0.5); */ +/* glTexCoord2f(1.0 + stf, 1.0 + stf); */ +/* glVertex3f(i+0.5, h, j-0.5); */ +/* glTexCoord2f(0.0 + stf, 1.0 + stf); */ +/* glVertex3f(i-0.5, h, j-0.5); */ + + /* draw top */ + glNormal3f(0.0, 1.0, 0.0); + glTexCoord2f(0.0 + stf, 0.0 + stf); + glVertex3f(i-0.5, h, j+0.5); + glTexCoord2f(1.0 + stf, 0.0 + stf); + glVertex3f(i+0.5, h, j+0.5); + glTexCoord2f(1.0 + stf, 1.0 + stf); + glVertex3f(i+0.5, h, j-0.5); + glTexCoord2f(0.0 + stf, 1.0 + stf); + glVertex3f(i-0.5, h, j-0.5); + mi->polygon_count++; + + /* draw south face */ + if(j == 9 || !mp->board[mp->currentboard][j+1][i]) { + glNormal3f(0.0, 0.0, 1.0); + glTexCoord2f(0.0 + stf, 0.0 + stf); + glVertex3f(i-0.5, 0.0, j+0.5); + glTexCoord2f(1.0 + stf, 0.0 + stf); + glVertex3f(i+0.5, 0.0, j+0.5); + glTexCoord2f(1.0 + stf, h + stf); + glVertex3f(i+0.5, h, j+0.5); + glTexCoord2f(0.0 + stf, h + stf); + glVertex3f(i-0.5, h, j+0.5); + mi->polygon_count++; + } + + /* draw north face */ + if(j == 0 || !mp->board[mp->currentboard][j-1][i]) { + glNormal3f(0.0, 0.0, -1.0); + glTexCoord2f(0.0 + stf, 0.0 + stf); + glVertex3f(i+0.5, 0.0, j-0.5); + glTexCoord2f(1.0 + stf, 0.0 + stf); + glVertex3f(i-0.5, 0.0, j-0.5); + glTexCoord2f(1.0 + stf, h + stf); + glVertex3f(i-0.5, h, j-0.5); + glTexCoord2f(0.0 + stf, h + stf); + glVertex3f(i+0.5, h, j-0.5); + mi->polygon_count++; + } + + /* draw east face */ + if(i == 9 || !mp->board[mp->currentboard][j][i+1]) { + glNormal3f(1.0, 0.0, 0.0); + glTexCoord2f(0.0 + stf, 0.0 + stf); + glVertex3f(i+0.5, 0.0, j+0.5); + glTexCoord2f(1.0 + stf, 0.0 + stf); + glVertex3f(i+0.5, 0.0, j-0.5); + glTexCoord2f(1.0 + stf, h + stf); + glVertex3f(i+0.5, h, j-0.5); + glTexCoord2f(0.0 + stf, h + stf); + glVertex3f(i+0.5, h, j+0.5); + mi->polygon_count++; + } + + /* draw west face */ + if(i == 0 || !mp->board[mp->currentboard][j][i-1]) { + glNormal3f(-1.0, 0.0, 0.0); + glTexCoord2f(0.0 + stf, 0.0 + stf); + glVertex3f(i-0.5, 0.0, j-0.5); + glTexCoord2f(1.0 + stf, 0.0 + stf); + glVertex3f(i-0.5, 0.0, j+0.5); + glTexCoord2f(1.0 + stf, h + stf); + glVertex3f(i-0.5, h, j+0.5); + glTexCoord2f(0.0 + stf, h + stf); + glVertex3f(i-0.5, h, j-0.5); + mi->polygon_count++; + } + } + else { + double tx = 2.0; + glNormal3f(0.0, 1.0, 0.0); + glTexCoord2f(0.0, 0.0); + glVertex3f(i-0.5, 0.0, j+0.5); + glTexCoord2f(tx, 0.0); + glVertex3f(i+0.5, 0.0, j+0.5); + glTexCoord2f(tx, tx); + glVertex3f(i+0.5, 0.0, j-0.5); + glTexCoord2f(0.0, tx); + glVertex3f(i-0.5, 0.0, j-0.5); + mi->polygon_count++; + } + } + glEnd(); + +/* /\* draw elevator *\/ */ +/* glBindTexture(GL_TEXTURE_2D, brushedtexture); */ + +/* glBegin(GL_QUADS); */ + +/* glNormal3f(0.0, 1.0, 0.0); */ + +/* if(pastfirst) { */ +/* /\* source *\/ */ +/* glTexCoord2f(0.0, 0.0); */ +/* glVertex3f(0.5, 0.0, BOARDSIZE - 0.5 + 0.2); */ +/* glTexCoord2f(1.0, 0.0); */ +/* glVertex3f(1.5, 0.0, BOARDSIZE - 0.5 + 0.2); */ +/* glTexCoord2f(1.0, 1.5); */ +/* glVertex3f(1.5, 0.0, BOARDSIZE + 1.0 + 0.2); */ +/* glTexCoord2f(0.0, 1.5); */ +/* glVertex3f(0.5, 0.0, BOARDSIZE + 1.0 + 0.2); */ +/* mi->polygon_count++; */ +/* } */ + +/* /\* destination *\/ */ +/* glTexCoord2f(0.0, 0.0); */ +/* glVertex3f(BOARDSIZE - 2.5, elevator, -2.0 - 0.2); */ +/* glTexCoord2f(1.0, 0.0); */ +/* glVertex3f(BOARDSIZE - 1.5, elevator, -2.0 - 0.2); */ +/* glTexCoord2f(1.0, 1.5); */ +/* glVertex3f(BOARDSIZE - 1.5, elevator, -0.5 - 0.2); */ +/* glTexCoord2f(0.0, 1.5); */ +/* glVertex3f(BOARDSIZE - 2.5, elevator, -0.5 - 0.2); */ +/* mi->polygon_count++; */ + +/* glEnd(); */ + +/* for(i = 0; i < BOARDSIZE; ++i) */ +/* for(j = 0; j < BOARDSIZE; ++j) { */ +/* if(board[j][i]) { */ + +/* /\* draw brushed boxtop *\/ */ +/* glNormal3f(0.0, 1.0, 0.0); */ +/* glTexCoord2f(0.0 + stf, 0.0 + stf); */ +/* glVertex3f(i-0.5 + stf, h+0.001, j+0.5 - stf); */ +/* glTexCoord2f(1.0 + stf, 0.0 + stf); */ +/* glVertex3f(i+0.5 - stf, h+0.001, j+0.5 - stf); */ +/* glTexCoord2f(1.0 + stf, 1.0 + stf); */ +/* glVertex3f(i+0.5 - stf, h+0.001, j-0.5 + stf); */ +/* glTexCoord2f(0.0 + stf, 1.0 + stf); */ +/* glVertex3f(i-0.5 + stf, h+0.001, j-0.5 + stf); */ +/* mi->polygon_count++; */ +/* } */ +/* } */ + +/* glEnd(); */ +} + +static void build_board(antmazestruct *mp, int b) +{ + int i, j; + + for(i = 0; i < BOARDSIZE; ++i) + for(j = 0; j < BOARDSIZE; ++j) + mp->board[b][i][j] = 1; + +/* for(i = 0; i < BOARDSIZE; ++i) { */ +/* board[0][i] = 1; */ +/* board[i][0] = 1; */ +/* board[BOARDSIZE-1][BOARDSIZE-i] = 1; */ +/* board[BOARDSIZE-i][BOARDSIZE-1] = 1; */ +/* } */ + +/* board[0][BOARDSIZE-2] = 0; */ +/* board[BOARDSIZE-1][1] = 0; */ + + + mp->board[b][BOARDSIZE-1][1] = 0; + mp->board[b][0][BOARDSIZE-2] = 0; + + /* build the ant paths */ + if(mp->currentboard == b) { + for(i = 0; i < ANTCOUNT; ++i) { + int sx = BOARDSIZE-2; + int sy = 1; + + for(j = 0; ; ++j) { + mp->board[b][sx][sy] = 0; + mp->antpath[i][j][0] = sy - 5.0; + mp->antpath[i][j][1] = sx - 5.0; + + if(random()%2) { + if(sx > 1) + sx -= 1; + else if(sy < BOARDSIZE-2) + sy += 1; + else + break; + } + else { + if(sy < BOARDSIZE-2) + sy += 1; + else if(sx > 1) + sx -= 1; + else + break; + } + } + + ++j; + mp->antpath[i][j][0] = BOARDSIZE-7.0; + mp->antpath[i][j][1] = -7.0; + mp->antpathlength[i] = j; + } + } + +/* for(i = 0; i < 20; ++i) { */ +/* int x = 1 + random()%(BOARDSIZE-2); */ +/* int y = 1 + random()%(BOARDSIZE-2); */ +/* board[x][y] = 1; */ +/* } */ +} + +/* compute nearness */ +static int near(double a[2], double b[2]) +{ + return fabs(a[0] - b[0]) < 0.5 && fabs(a[1] - b[1]) < 0.5; +} + +static double sign(double d) +{ + return d < 0.0 ? -1.0 : 1.0; +} + +static double min(double a, double b) +{ + return a < b ? a : b; +} + +/* draw method for ant */ +static Bool draw_ant(ModeInfo *mi, antmazestruct *mp, + const float *Material, int mono, int shadow, + float ant_step, Bool (*sphere)(float), Bool (*cone)(float)) +{ + + float cos1 = cos(mp->ant_step); + float cos2 = cos(mp->ant_step + 2 * Pi / 3); + float cos3 = cos(mp->ant_step + 4 * Pi / 3); + float sin1 = sin(mp->ant_step); + float sin2 = sin(mp->ant_step + 2 * Pi / 3); + float sin3 = sin(mp->ant_step + 4 * Pi / 3); + + glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, mono ? MaterialGray5 : Material); + +/* glEnable(GL_CULL_FACE); */ + + glPushMatrix(); + glScalef(1, 1.3, 1); + if(!((*sphere)(0.18))) + return False; + glScalef(1, 1 / 1.3, 1); + glTranslatef(0.00, 0.30, 0.00); + if(!((*sphere)(0.2))) + return False; + + glTranslatef(-0.05, 0.17, 0.05); + glRotatef(-90, 1, 0, 0); + glRotatef(-25, 0, 1, 0); + if(!((*cone)(0.05))) + return False; + glTranslatef(0.00, 0.10, 0.00); + if(!((*cone)(0.05))) + return False; + glRotatef(25, 0, 1, 0); + glRotatef(90, 1, 0, 0); + + glScalef(1, 1.3, 1); + glTranslatef(0.15, -0.65, 0.05); + if(!((*sphere)(0.25))) + return False; + glScalef(1, 1 / 1.3, 1); + glPopMatrix(); + +/* glDisable(GL_CULL_FACE); */ + + glDisable(GL_LIGHTING); + + /* ANTENNAS */ + glBegin(GL_LINES); + glColor3fv(mono ? MaterialGray5 : Material); + glVertex3f(0.00, 0.30, 0.00); + glColor3fv(MaterialGray); + glVertex3f(0.40, 0.70, 0.40); + mi->polygon_count++; + glColor3fv(mono ? MaterialGray5 : Material); + glVertex3f(0.00, 0.30, 0.00); + glColor3fv(MaterialGray); + glVertex3f(0.40, 0.70, -0.40); + mi->polygon_count++; + glEnd(); + + if(!shadow) { + glBegin(GL_POINTS); + glColor3fv(mono ? MaterialGray6 : MaterialRed); + glVertex3f(0.40, 0.70, 0.40); + mi->polygon_count++; + glVertex3f(0.40, 0.70, -0.40); + mi->polygon_count++; + glEnd(); + } + + /* LEFT-FRONT ARM */ + glBegin(GL_LINE_STRIP); + glColor3fv(mono ? MaterialGray5 : Material); + glVertex3f(0.00, 0.05, 0.18); + glVertex3f(0.35 + 0.05 * cos1, 0.15, 0.25); + mi->polygon_count++; + glColor3fv(MaterialGray); + glVertex3f(-0.20 + 0.05 * cos1, 0.25 + 0.1 * sin1, 0.45); + mi->polygon_count++; + glEnd(); + + /* LEFT-CENTER ARM */ + glBegin(GL_LINE_STRIP); + glColor3fv(mono ? MaterialGray5 : Material); + glVertex3f(0.00, 0.00, 0.18); + glVertex3f(0.35 + 0.05 * cos2, 0.00, 0.25); + mi->polygon_count++; + glColor3fv(MaterialGray); + glVertex3f(-0.20 + 0.05 * cos2, 0.00 + 0.1 * sin2, 0.45); + mi->polygon_count++; + glEnd(); + + /* LEFT-BACK ARM */ + glBegin(GL_LINE_STRIP); + glColor3fv(mono ? MaterialGray5 : Material); + glVertex3f(0.00, -0.05, 0.18); + glVertex3f(0.35 + 0.05 * cos3, -0.15, 0.25); + mi->polygon_count++; + glColor3fv(MaterialGray); + glVertex3f(-0.20 + 0.05 * cos3, -0.25 + 0.1 * sin3, 0.45); + mi->polygon_count++; + glEnd(); + + /* RIGHT-FRONT ARM */ + glBegin(GL_LINE_STRIP); + glColor3fv(mono ? MaterialGray5 : Material); + glVertex3f(0.00, 0.05, -0.18); + glVertex3f(0.35 - 0.05 * sin1, 0.15, -0.25); + mi->polygon_count++; + glColor3fv(MaterialGray); + glVertex3f(-0.20 - 0.05 * sin1, 0.25 + 0.1 * cos1, -0.45); + mi->polygon_count++; + glEnd(); + + /* RIGHT-CENTER ARM */ + glBegin(GL_LINE_STRIP); + glColor3fv(mono ? MaterialGray5 : Material); + glVertex3f(0.00, 0.00, -0.18); + glVertex3f(0.35 - 0.05 * sin2, 0.00, -0.25); + mi->polygon_count++; + glColor3fv(MaterialGray); + glVertex3f(-0.20 - 0.05 * sin2, 0.00 + 0.1 * cos2, -0.45); + mi->polygon_count++; + glEnd(); + + /* RIGHT-BACK ARM */ + glBegin(GL_LINE_STRIP); + glColor3fv(mono ? MaterialGray5 : Material); + glVertex3f(0.00, -0.05, -0.18); + glVertex3f(0.35 - 0.05 * sin3, -0.15, -0.25); + mi->polygon_count++; + glColor3fv(MaterialGray); + glVertex3f(-0.20 - 0.05 * sin3, -0.25 + 0.1 * cos3, -0.45); + mi->polygon_count++; + glEnd(); + + if(!shadow) { + glBegin(GL_POINTS); + glColor3fv(mono ? MaterialGray8 : MaterialGray35); + glVertex3f(-0.20 + 0.05 * cos1, 0.25 + 0.1 * sin1, 0.45); + glVertex3f(-0.20 + 0.05 * cos2, 0.00 + 0.1 * sin2, 0.45); + glVertex3f(-0.20 + 0.05 * cos3, -0.25 + 0.1 * sin3, 0.45); + glVertex3f(-0.20 - 0.05 * sin1, 0.25 + 0.1 * cos1, -0.45); + glVertex3f(-0.20 - 0.05 * sin2, 0.00 + 0.1 * cos2, -0.45); + glVertex3f(-0.20 - 0.05 * sin3, -0.25 + 0.1 * cos3, -0.45); + mi->polygon_count += 6; + glEnd(); + } + + glEnable(GL_LIGHTING); + + return True; +} + +static Bool draw_antmaze_strip(ModeInfo * mi) +{ + antmazestruct *mp = &antmaze[MI_SCREEN(mi)]; + int i; + int mono = MI_IS_MONO(mi); + +/* glMatrixMode(GL_MODELVIEW); */ +/* glLoadIdentity(); */ +/* glPushMatrix(); */ + + glEnable(GL_LIGHTING); +/* glDisable(GL_BLEND); */ + glEnable(GL_LIGHT0); + glEnable(GL_LIGHT1); + + /* set light */ +/* double l1 = 1.0 - (elevator < 1.0 ? elevator : 2.0 - elevator); */ +/* GLfloat df[4] = {0.8*l1, 0.8*l1, 0.8*l1, 1.0}; */ +/* glLightfv(GL_LIGHT0, GL_DIFFUSE, df); */ +/* glLightfv(GL_LIGHT1, GL_DIFFUSE, df); */ + + /* draw board */ + if(mp->elevator < 1.0) { + glEnable(GL_TEXTURE_2D); + glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, MaterialGray6); + glTranslatef(-(BOARDSIZE-1)/2.0, 0.0, -(BOARDSIZE-1)/2.0); + draw_board(mi, mp); + glTranslatef(BOARDSIZE/2.0, 0.0, BOARDSIZE/2.0); + glDisable(GL_TEXTURE_2D); + } + + mp->introduced--; + + glTranslatef(0.0, -0.1, 0.0); + + for(i = 0; i < ANTCOUNT; ++i) { + +/* glLightfv(GL_LIGHT0, GL_DIFFUSE, df); */ +/* glLightfv(GL_LIGHT1, GL_DIFFUSE, df); */ + + if(!mp->anton[i]) { continue; } + + /* determine location, move to goal */ + glPushMatrix(); + glTranslatef(0.0, 0.01, 0.0); + glTranslatef(mp->antposition[i][0], mp->antposition[i][2], mp->antposition[i][1]); +/* glScalef(1.0, 0.01, 1.0); */ + glScalef(0.6, 0.01, 0.6); + glRotatef(180.0 + mp->antdirection[i]*180.0/PI, 0.0, 1.0, 0.0); + glRotatef(90.0, 0.0, 0.0, 1.0); + glDisable(GL_LIGHTING); + glEnable(GL_BLEND); + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + glColor4fv(MaterialGrayB); + + glScalef(mp->antsize[i], mp->antsize[i], mp->antsize[i]); + + /* slow down first ant */ + if(i == 0 && mp->part[i] == mp->antpathlength[i]) + draw_ant(mi, mp, MaterialGrayB, mono, 1, mp->first_ant_step, mySphere, myCone); + else + draw_ant(mi, mp, MaterialGrayB, mono, 1, mp->ant_step, mySphere, myCone); + + glPopMatrix(); + + glDisable(GL_BLEND); + glEnable(GL_LIGHTING); + + glPushMatrix(); +/* glTranslatef(0.0, 0.18, 0.0); */ + glTranslatef(0.0, 0.12, 0.0); + glTranslatef(mp->antposition[i][0], mp->antposition[i][2], mp->antposition[i][1]); + glRotatef(180.0 + mp->antdirection[i]*180.0/PI, 0.0, 1.0, 0.0); + glRotatef(90.0, 0.0, 0.0, 1.0); + glScalef(0.6, 0.6, 0.6); + + glScalef(mp->antsize[i], mp->antsize[i], mp->antsize[i]); + +/* glEnable(GL_TEXTURE_2D); */ +/* glBindTexture(GL_TEXTURE_2D, brushedtexture); */ + +/* glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, MaterialRed); */ + + /* slow down first ant */ + if(i == 0 && mp->part[i] == mp->antpathlength[i] && mp->elevator > 0.0) { + glLightfv(GL_LIGHT0, GL_DIFFUSE, diffuse); + glLightfv(GL_LIGHT1, GL_DIFFUSE, diffuse); + draw_ant(mi, mp, antmaterial[i], mono, 1, mp->first_ant_step, mySphere, myCone); + } + else { +/* glLightfv(GL_LIGHT0, GL_DIFFUSE, df); */ +/* glLightfv(GL_LIGHT1, GL_DIFFUSE, df); */ + + glEnable(GL_TEXTURE_2D); + glBindTexture(GL_TEXTURE_2D, mp->brushedtexture); + draw_ant(mi, mp, antmaterial[i], mono, 1, mp->ant_step, mySphereTex, myCone); + glDisable(GL_TEXTURE_2D); + } + + +/* draw_ant(mi, antmaterial[i], mono, 0, ant_step, mySphereTex, myCone); */ +/* glDisable(GL_TEXTURE_2D); */ + glPopMatrix(); + } + +/* glPopMatrix(); */ + +/* /\* now draw overlay *\/ */ +/* glDisable(GL_LIGHTING); */ +/* glDisable(GL_BLEND); */ + +/* /\* go to ortho mode *\/ */ +/* glMatrixMode(GL_PROJECTION); */ +/* glPushMatrix(); */ +/* glLoadIdentity(); */ +/* glOrtho(-4.0, 4.0, -3.0, 3.0, -100.0, 100.0); */ + +/* /\* translate to corner *\/ */ +/* glTranslatef(4.0-1.2, 3.0-1.2, 0.0); */ + +/* glDisable(GL_LIGHTING); */ +/* glEnable(GL_BLEND); */ + +/* /\* draw the 2d board *\/ */ +/* glBegin(GL_QUADS); */ +/* { */ +/* int i, j; */ +/* double sz = 1.0; */ +/* for(i = 0; i < BOARDSIZE; ++i) */ +/* for(j = 0; j < BOARDSIZE; ++j) { */ +/* int par = board[i][j]; */ +/* glColor4f(par ? 0.4 : 0.6, */ +/* par ? 0.4 : 0.6, */ +/* par ? 0.4 : 0.6, */ +/* 0.5); */ +/* glNormal3f(0.0, 0.0, 1.0); */ +/* glVertex3f((sz*(i+1))/BOARDSIZE, (sz*(j+1))/BOARDSIZE, 0.0); */ +/* glVertex3f((sz*i)/BOARDSIZE, (sz*(j+1))/BOARDSIZE, 0.0); */ +/* glVertex3f((sz*i)/BOARDSIZE, (sz*j)/BOARDSIZE, 0.0); */ +/* glVertex3f((sz*(i+1))/BOARDSIZE, (sz*j)/BOARDSIZE, 0.0); */ +/* mi->polygon_count++; */ +/* } */ +/* } */ +/* glEnd(); */ + +/* glPopMatrix(); */ + + + /* but the step size is the same! */ + mp->ant_step += 0.18; +/* if(ant_step > 2*Pi) { */ +/* ant_step = 0.0; */ +/* } */ + + if(mp->ant_step > 5*Pi) + mp->started = 1; + + mp->ant_position += 1; + return True; +} +#undef AntmazeDivisions +#undef AntmazeTransversals + +ENTRYPOINT void reshape_antmaze(ModeInfo * mi, int width, int height) +{ + double h = (GLfloat) height / (GLfloat) width; + int size = (width / 512) + 1; + antmazestruct *mp = &antmaze[MI_SCREEN(mi)]; + + glViewport(0, 0, mp->WindW = (GLint) width, mp->WindH = (GLint) height); + glMatrixMode(GL_PROJECTION); + glLoadIdentity(); + + gluPerspective(45, 1/h, 1, 25.0); + + glMatrixMode(GL_MODELVIEW); +/* glLineWidth(3.0); */ + glLineWidth(size); + glPointSize(size); +} + +static void update_ants(antmazestruct *mp) +{ + int i; + GLfloat df[4]; + df[0] = df[1] = df[2] = 0.8*mp->fadeout; + df[3] = 1.0; + + /* fade out */ + if(mp->fadeoutspeed < -0.00001) { + + if(mp->fadeout <= 0.0) { + /* switch boards: rebuild old board, increment current */ + mp->currentboard = (mp->currentboard+1)%BOARDCOUNT; + build_board(mp, mp->currentboard); + mp->fadeoutspeed = 0.02; + } + + mp->fadeout += mp->fadeoutspeed; + + glLightfv(GL_LIGHT0, GL_DIFFUSE, df); + glLightfv(GL_LIGHT1, GL_DIFFUSE, df); + } + + /* fade in */ + if(mp->fadeoutspeed > 0.0001) { + mp->fadeout += mp->fadeoutspeed; + if(mp->fadeout >= 1.0) { + mp->fadeout = 1.0; + mp->fadeoutspeed = 0.0; + mp->entroducing = 12; + } + glLightfv(GL_LIGHT0, GL_DIFFUSE, df); + glLightfv(GL_LIGHT1, GL_DIFFUSE, df); + } + + for(i = 0; i < ANTCOUNT; ++i) { + + if(!mp->anton[i] && mp->elevator < 1.0) { + + /* turn on ant */ + if(mp->entroducing > 0 && mp->introduced <= 0 && random()%100 == 0) { + mp->anton[i] = 1; + mp->part[i] = 0; + mp->antsize[i] = 0.0; + mp->antposition[i][0] = -4.0; + mp->antposition[i][1] = 5.0; + mp->antdirection[i] = PI/2.0; + mp->bposition[i][0] = 0; + mp->bposition[i][1] = 8; + mp->introduced = 300; + mp->entroducing--; + } + + continue; + } + + if(mp->part[i] == 0 && mp->antsize[i] < 1.0) { + mp->antsize[i] += 0.02; + continue; + } + + if(mp->part[i] > mp->antpathlength[i] && mp->antsize[i] > 0.0) { + mp->antsize[i] -= 0.02; + if(mp->antvelocity[i] > 0.0) { + mp->antvelocity[i] -= 0.02; + } + else { mp->antvelocity[i] = 0.0; } + + continue; + } + + if(mp->part[i] > mp->antpathlength[i] && mp->antsize[i] <= 0.0) { + mp->antvelocity[i] = 0.02; + + /* if(i != 0) { */ + antmaterial[i] = materials[random()%MATERIALS]; + /* } */ + + mp->antdirection[i] = PI/2.0; + mp->bposition[i][0] = 0; + mp->bposition[i][1] = 8; + mp->part[i] = 0; + + mp->antsize[i] = 0.0; + + mp->anton[i] = 0; + + mp->antposition[i][0] = -4.0; + mp->antposition[i][1] = 5.0; + + /* /\* reset camera *\/ */ + /* if(i == focus) { */ + /* started = 0; */ + /* ant_step = 0.0; */ + /* } */ + + /* check for the end */ + if(mp->entroducing <= 0) { + int ao = 0, z = 0; + for(z = 0; z < ANTCOUNT; ++z) { + if(mp->anton[z]) { ao = 1; break; } + } + + if(ao == 0) { + mp->fadeoutspeed = -0.02; + } + } + + } + + /* near goal, bend path towards next step */ + if(near(mp->antposition[i], mp->antpath[i][mp->part[i]])) { + + ++mp->part[i]; + +/* /\* special first ant *\/ */ +/* if(i == 0 && part[i] > antpathlength[i]) { */ +/* if(fir) */ +/* first_ant_step = ant_step; */ + +/* antvelocity[i] = 0.0; */ +/* /\* antposition[i][2] += 0.025; *\/ */ +/* elevator += 0.025; */ + +/* /\* set light *\/ */ +/* double l1 = 1.0 - (elevator < 1.0 ? elevator : 2.0 - elevator); */ +/* GLfloat df[4] = {0.8*l1, 0.8*l1, 0.8*l1, 1.0}; */ +/* glLightfv(GL_LIGHT0, GL_DIFFUSE, df); */ +/* glLightfv(GL_LIGHT1, GL_DIFFUSE, df); */ + +/* /\* draw next board *\/ */ +/* if(elevator > 1.0) { */ + +/* if(makenew == 1) { */ +/* int re; */ + +/* /\* switch boards: rebuild old board, increment current *\/ */ +/* currentboard = (currentboard+1)%BOARDCOUNT; */ +/* build_board(currentboard); */ + +/* for(re = 1; re < ANTCOUNT; ++re) { */ +/* anton[re] = 0; */ +/* antmaterial[re] = materials[random()%MATERIALS]; */ +/* } */ + +/* makenew = 0; */ + +/* } */ + +/* /\* draw the other board *\/ */ +/* glEnable(GL_TEXTURE_2D); */ +/* glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, MaterialGray6); */ + +/* glPushMatrix(); */ +/* glTranslatef(-(-(BOARDSIZE-3.5)+(BOARDSIZE-1)/2.0), 0.0, */ +/* -(2.4+BOARDSIZE+(BOARDSIZE-1)/2.0)); */ +/* draw_board(mi, mp); */ +/* glPopMatrix(); */ +/* glDisable(GL_TEXTURE_2D); */ +/* } */ +/* /\* reset *\/ */ +/* if(elevator > 2.0) { */ +/* antposition[i][0] = -4.0;/\*-= -(-(BOARDSIZE-3.5)+(BOARDSIZE-1)/2.0);*\//\*= -4.0;*\/ */ +/* antposition[i][1] = 5.5;/\*-(2.4+BOARDSIZE+(BOARDSIZE-1)/2.0);*\/ */ +/* /\* antposition[i][2] = 0.15; *\/ */ +/* antdirection[i] = PI/2.0; */ +/* bposition[i][0] = 0; */ +/* bposition[i][1] = 8; */ +/* part[i] = 0; */ +/* antvelocity[i] = 0.02; */ +/* fir = 0; */ +/* antmaterial[i] = MaterialRed; */ + +/* makenew = 1; */ + +/* elevator = 0.0; */ +/* introduced = 200; */ +/* } */ +/* else { */ +/* part[i]--; */ +/* } */ +/* } */ + + } + + /* move toward goal, correct ant direction if required */ + else { + + /* difference */ + double dx = mp->antpath[i][mp->part[i]][0] - mp->antposition[i][0]; + double dz = - mp->antpath[i][mp->part[i]][1] + mp->antposition[i][1]; + double theta, ideal; + + if(dz > EPSILON) + theta = atan(dz/dx); + else + theta = dx > EPSILON ? 0.0 : PI; + + ideal = theta - mp->antdirection[i]; + if(ideal < -Pi/2.0) + ideal += Pi; + + /* compute correction */ + { + double dt = sign(ideal) * min(fabs(ideal), PI/90.0); + mp->antdirection[i] += dt; + if(mp->antdirection[i] > 2.0*PI) + mp->antdirection[i] = 0.0; + } + } + + mp->antposition[i][0] += mp->antvelocity[i] * cos(mp->antdirection[i]); + mp->antposition[i][1] += mp->antvelocity[i] * sin(-mp->antdirection[i]); + } +} + +static void pinit(antmazestruct *mp) +{ + glClearDepth(1.0); + glLightfv(GL_LIGHT0, GL_AMBIENT, ambient); + glLightfv(GL_LIGHT0, GL_DIFFUSE, diffuse); + glLightfv(GL_LIGHT0, GL_POSITION, position0); + glLightfv(GL_LIGHT1, GL_AMBIENT, ambient); + glLightfv(GL_LIGHT1, GL_DIFFUSE, diffuse); + glLightfv(GL_LIGHT1, GL_POSITION, position1); + + glLightf(GL_LIGHT0, GL_LINEAR_ATTENUATION, 0.05); + glLightf(GL_LIGHT0, GL_QUADRATIC_ATTENUATION, 0.001); + glLightf(GL_LIGHT0, GL_CONSTANT_ATTENUATION, 0.1); + + glLightf(GL_LIGHT1, GL_LINEAR_ATTENUATION, 0.05); + glLightf(GL_LIGHT1, GL_QUADRATIC_ATTENUATION, 0.001); + glLightf(GL_LIGHT1, GL_CONSTANT_ATTENUATION, 0.1); + + +/* glLightModelfv(GL_LIGHT_MODEL_AMBIENT, lmodel_ambient); */ +/* glLightModelfv(GL_LIGHT_MODEL_TWO_SIDE, lmodel_twoside); */ + glEnable(GL_LIGHTING); + glEnable(GL_LIGHT0); + glEnable(GL_LIGHT1); + glEnable(GL_NORMALIZE); + glFrontFace(GL_CCW); + glCullFace(GL_BACK); + + /* antmaze */ + glMaterialfv(GL_FRONT_AND_BACK, GL_SHININESS, front_shininess); + glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, front_specular); + + glShadeModel(GL_SMOOTH); + glEnable(GL_DEPTH_TEST); + glDisable(GL_TEXTURE_2D); + + /* setup textures */ + makeCheckImage(mp); + makeBrushedImage(mp); + + build_board(mp, 0); + build_board(mp, 1); + +/* makeCheckImage(); */ +/* glPixelStorei(GL_UNPACK_ALIGNMENT, 1); */ +/* glTexImage2D(GL_TEXTURE_2D, 0, 3, checkImageWidth, */ +/* checkImageHeight, 0, GL_RGB, GL_UNSIGNED_BYTE, checkers); */ +/* 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_NEAREST); */ +/* glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); */ +/* glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); */ + glEnable(GL_TEXTURE_2D); + +/* glMaterialfv(GL_FRONT_AND_BACK, GL_SHININESS, front_shininess); */ +/* glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, front_specular); */ +} + +ENTRYPOINT void release_antmaze(ModeInfo * mi) +{ + if(antmaze) { + free((void *) antmaze); + antmaze = (antmazestruct *) NULL; + } + FreeAllGL(mi); +} + +#define MAX_MAGNIFICATION 10 +#define max(a, b) a < b ? b : a +#define min(a, b) a < b ? a : b + +ENTRYPOINT Bool antmaze_handle_event (ModeInfo *mi, XEvent *event) +{ + antmazestruct *mp = &antmaze[MI_SCREEN(mi)]; + + switch(event->xany.type) { + case ButtonPress: + + switch(event->xbutton.button) { + + case Button1: + mp->button_down_p = True; + gltrackball_start(mp->trackball, + event->xbutton.x, event->xbutton.y, + MI_WIDTH (mi), MI_HEIGHT (mi)); + break; + + case Button3: + mp->focus = (mp->focus + 1) % ANTCOUNT; + break; + + case Button4: + mp->mag = max(mp->mag-1, 1); + break; + + case Button5: + mp->mag = min(mp->mag+1, MAX_MAGNIFICATION); + break; + } + + break; + + case ButtonRelease: + + switch(event->xbutton.button) { + case Button1: + mp->button_down_p = False; + break; + } + + break; + + case MotionNotify: + if(mp->button_down_p) + gltrackball_track(mp->trackball, + event->xmotion.x, event->xmotion.y, + MI_WIDTH (mi), MI_HEIGHT (mi)); + break; + + default: + return False; + } + + return True; +} + +ENTRYPOINT void init_antmaze(ModeInfo * mi) +{ + double rot_speed = 0.3; + int i; + + antmazestruct *mp; + + if (antmaze == NULL) { + if ((antmaze = (antmazestruct *) calloc(MI_NUM_SCREENS(mi), + sizeof (antmazestruct))) == NULL) + return; + } + mp = &antmaze[MI_SCREEN(mi)]; + mp->step = NRAND(90); + mp->ant_position = NRAND(90); + + + mp->antdirection[0] = PI/2.0; + mp->antdirection[1] = PI/2.0; + mp->antdirection[2] = 0; + mp->antdirection[3] = PI/2.0; + mp->antdirection[4] = PI/2.0; + + mp->antposition[0][0] = -4.0; + mp->antposition[0][1] = 5.0; + mp->antposition[0][1] = 0.15; + + mp->antposition[1][0] = -4.0; + mp->antposition[1][1] = 3.0; + mp->antposition[1][1] = 0.15; + + mp->antposition[2][0] = -1.0; + mp->antposition[2][1] = -2.0; + mp->antposition[2][1] = 0.15; + + mp->antposition[3][0] = -3.9; + mp->antposition[3][1] = 6.0; + mp->antposition[3][1] = 0.15; + + mp->antposition[4][0] = 2.0; + mp->antposition[4][1] = -2.0; + mp->antposition[4][1] = 0.15; + + + + for (i = 0; i < ANTCOUNT; i++) { + mp->antvelocity[i] = 0.02; + mp->antsize[i] = 1.0; + mp->anton[i] = 0; + } + + mp->bposition[0][0] = 0; + mp->bposition[0][1] = 8; + + mp->bposition[1][0] = 9; + mp->bposition[1][1] = 1; + + mp->bposition[2][0] = 1; + mp->bposition[2][1] = 1; + + mp->bposition[3][0] = 4; + mp->bposition[3][1] = 8; + + mp->bposition[4][0] = 2; + mp->bposition[4][1] = 1; + + mp->part[0] = 0; + mp->part[1] = 1; + mp->part[2] = 5; + mp->part[3] = 1; + mp->part[4] = 3; + + mp->introduced = 0; + mp->entroducing = 12; + mp->fadeout = 1.0; + mp->mag = 4.0; + + mp->rot = make_rotator (rot_speed, rot_speed, rot_speed, 1, 0, True); + mp->trackball = gltrackball_init (); + + if ((mp->glx_context = init_GL(mi)) != NULL) { + reshape_antmaze(mi, MI_WIDTH(mi), MI_HEIGHT(mi)); + glDrawBuffer(GL_BACK); + pinit(mp); + } + else + MI_CLEARWINDOW(mi); +} + +static void +device_rotate(ModeInfo *mi) +{ + GLfloat rot = current_device_rotation(); + glRotatef(rot, 0, 0, 1); + if ((rot > 45 && rot < 135) || + (rot < -45 && rot > -135)) + { + GLfloat s = MI_HEIGHT(mi) / (GLfloat) MI_WIDTH(mi); + glScalef (1/s, s, 1); + } +} + + +ENTRYPOINT void draw_antmaze(ModeInfo * mi) +{ + double h = (GLfloat) MI_HEIGHT(mi) / (GLfloat) MI_WIDTH(mi); + + antmazestruct *mp; + + Display *display = MI_DISPLAY(mi); + Window window = MI_WINDOW(mi); + + if(!antmaze) + return; + mp = &antmaze[MI_SCREEN(mi)]; + + MI_IS_DRAWN(mi) = True; + + if(!mp->glx_context) + return; + + mi->polygon_count = 0; + glXMakeCurrent(display, window, *(mp->glx_context)); + + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + + /* first panel */ + glPushMatrix(); +/* h = ((GLfloat) MI_HEIGHT(mi)/2) / (3*(GLfloat)MI_WIDTH(mi)/4); */ + glViewport(MI_WIDTH(mi)/32, MI_HEIGHT(mi)/8, (9*MI_WIDTH(mi))/16, 3*MI_HEIGHT(mi)/4); + glMatrixMode(GL_PROJECTION); + glLoadIdentity(); + +/* h = (3*MI_HEIGHT(mi)/4) / (3*MI_WIDTH(mi)/4); */ + gluPerspective(45, 1/h, 1, 25.0); + + glMatrixMode(GL_MODELVIEW); + glLoadIdentity(); + device_rotate(mi); + + glPushMatrix(); + + /* follow focused ant */ + glTranslatef(0.0, 0.0, -mp->mag - 5.0); + glRotatef(20.0+5.0*sin(mp->ant_step/40.0), 1.0, 0.0, 0.0); +/* glTranslatef(0.0, */ +/* started ? -mag : -8.0 + 4.0*fabs(sin(ant_step/10.0)), */ +/* started ? -mag : -8.0 + 4.0*fabs(sin(ant_step/10.0))); */ + + gltrackball_rotate(mp->trackball); + + glRotatef(mp->ant_step*0.6, 0.0, 1.0, 0.0); + +/* glRotatef(90.0, 0.0, 0.0, 1.0); */ + +/* glTranslatef(-antposition[0][0]-0.5, 0.0, -antposition[focus][1]); */ + /*-elevator*/ + + /* sync */ + if(!draw_antmaze_strip(mi)) { + release_antmaze(mi); + return; + } + + glPopMatrix(); + glPopMatrix(); + + h = (GLfloat) (3*MI_HEIGHT(mi)/8) / (GLfloat) (MI_WIDTH(mi)/2); + + /* draw overhead */ + glPushMatrix(); + glViewport((17*MI_WIDTH(mi))/32, MI_HEIGHT(mi)/2, MI_WIDTH(mi)/2, 3*MI_HEIGHT(mi)/8); + glMatrixMode(GL_PROJECTION); + glLoadIdentity(); + device_rotate(mi); + gluPerspective(45, 1/h, 1, 25.0); + glMatrixMode(GL_MODELVIEW); + + /* twist scene */ + glTranslatef(0.0, 0.0, -16.0); + glRotatef(60.0, 1.0, 0.0, 0.0); + glRotatef(-15.0 + mp->ant_step/10.0, 0.0, 1.0, 0.0); + gltrackball_rotate(mp->trackball); + + /* sync */ + if(!draw_antmaze_strip(mi)) { + release_antmaze(mi); + return; + } + + glPopMatrix(); + + /* draw ant display */ + glPushMatrix(); + glViewport((5*MI_WIDTH(mi))/8, MI_HEIGHT(mi)/8, (11*MI_WIDTH(mi))/32, 3*MI_HEIGHT(mi)/8); + glMatrixMode(GL_PROJECTION); + glLoadIdentity(); + device_rotate(mi); + gluPerspective(45, 1/h, 1, 25.0); + glMatrixMode(GL_MODELVIEW); + + /* twist scene */ + glTranslatef(0.0, 0.0, -1.6); + glRotatef(30.0, 1.0, 0.0, 0.0); + glRotatef(mp->ant_step, 0.0, 1.0, 0.0); + glRotatef(90.0, 0.0, 0.0, 1.0); + +/* /\* draw ant shadow *\/ */ +/* glPushMatrix(); */ +/* glScalef(1.0, 0.01, 1.0); */ +/* glRotatef(90.0, 0.0, 0.0, 1.0); */ +/* glRotatef(90.0, 0.0, 1.0, 0.0); */ +/* glDisable(GL_LIGHTING); */ +/* glColor4fv(MaterialGray6); */ + +/* /\* slow down first ant *\/ */ +/* draw_ant(MaterialGrayB, 0, 1, first_ant_step, mySphere, myCone); */ +/* glPopMatrix(); */ + + /* draw ant body */ + glEnable(GL_TEXTURE_2D); + glLightfv(GL_LIGHT0, GL_DIFFUSE, diffuse); + glLightfv(GL_LIGHT1, GL_DIFFUSE, diffuse); + glBindTexture(GL_TEXTURE_2D, mp->brushedtexture); + draw_ant(mi, mp, MaterialGray35, 0, 1, mp->ant_step/2.0, mySphereTex, myCone2); + glDisable(GL_TEXTURE_2D); + + glPopMatrix(); + +/* /\* draw overlay *\/ */ +/* glPushMatrix(); */ + +/* /\* go to ortho mode *\/ */ +/* glViewport(MI_WIDTH(mi)/2, MI_HEIGHT(mi)/8, MI_WIDTH(mi)/2, 3*MI_HEIGHT(mi)/8); */ + +/* glMatrixMode(GL_PROJECTION); */ +/* glLoadIdentity(); */ + +/* glPushMatrix (); */ +/* glOrtho(-4.0, 4.0, -3.0, 3.0, -100.0, 100.0); */ + +/* glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, MaterialGrayB); */ +/* glColor4fv(MaterialGrayB); */ + +/* glDisable(GL_LIGHTING); */ +/* glEnable(GL_BLEND); */ + +/* glBegin(GL_QUADS); */ +/* glNormal3f(0.0, 0.0, 1.0); */ +/* glVertex3f(4.0, 3.0, 0.0); */ +/* glVertex3f(2.0, 3.0, 0.0); */ +/* glVertex3f(2.0, -3.0, 0.0); */ +/* glVertex3f(4.0, -3.0, 0.0); */ +/* mi->polygon_count++; */ +/* glEnd(); */ + +/* glEnable(GL_LIGHTING); */ +/* glDisable(GL_BLEND); */ + +/* glPopMatrix(); */ +/* glPopMatrix(); */ + + if (MI_IS_FPS(mi)) { + glViewport(0, 0, MI_WIDTH(mi), MI_HEIGHT(mi)); + do_fps (mi); + } + glFlush(); + + glXSwapBuffers(display, window); + + update_ants(mp); + + mp->step += 0.025; +} + +#ifndef STANDALONE +ENTRYPOINT void change_antmaze(ModeInfo * mi) +{ + antmazestruct *mp = &antmaze[MI_SCREEN(mi)]; + + if (!mp->glx_context) + return; + + glXMakeCurrent(MI_DISPLAY(mi), MI_WINDOW(mi), *(mp->glx_context)); + pinit(); +} +#endif /* !STANDALONE */ + +XSCREENSAVER_MODULE ("AntMaze", antmaze) + +#endif diff --git a/hacks/glx/antmaze.man b/hacks/glx/antmaze.man new file mode 100644 index 00000000..4c4bec8c --- /dev/null +++ b/hacks/glx/antmaze.man @@ -0,0 +1,52 @@ +.TH XScreenSaver 1 "May 2005" +.SH NAME +antmaze \- ant maze walker +.SH SYNOPSIS +.B antmaze +[\-display \fIhost:display.screen\fP] [\-window] [\-root] [\-install] +[\-visual \fIvisual\fP] [\-delay \fImicroseconds\fP] [\-fps] +.SH DESCRIPTION +The \fIantmaze\fP code displays ants finding their way through a maze. +.SH OPTIONS +.I antmaze +accepts the following options: +.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 \-install +Install a private colormap for the window. +.TP 8 +.B \-visual \fIvisual\fP\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. +.B \-fps +Display the current frame rate, CPU load, and polygon count. +.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) +.BR xscreensaver\-demo (1), +.BR xscreensaver\-getimage (1) +.SH COPYRIGHT +Copyright \(co 2005 by Blair Tennessy. 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 +Blair Tennessy , 8-May-2005. + diff --git a/hacks/glx/ants.h b/hacks/glx/ants.h new file mode 100644 index 00000000..d0bef7e1 --- /dev/null +++ b/hacks/glx/ants.h @@ -0,0 +1,45 @@ +/* ants.h -- header file containing common ant parameters + * + * Permission to use, copy, modify, and distribute this software and its + * documentation for any purpose and without fee is hereby granted, + * provided that the above copyright notice appear in all copies and that + * both that copyright notice and this permission notice appear in + * supporting documentation. + * + * This file is provided AS IS with no warranties of any kind. The author + * shall have no liability with respect to the infringement of copyrights, + * trade secrets or any patents by this file or any part thereof. In no + * event will the author be liable for any lost revenue or profits or + * other special, indirect and consequential damages. + * + * Copyright 2003 Blair Tennessy +*/ + +/* static const GLfloat MaterialRed[] = {0.6, 0.0, 0.0, 1.0}; */ +/*static const GLfloat MaterialPurple[] = {0.6, 0.2, 0.5, 1.0};*/ +/*static const GLfloat MaterialOrange[] = {1.0, 0.69, 0.00, 1.0};*/ +/*static const GLfloat MaterialGreen[] = {0.1, 0.5, 0.2, 0.2};*/ +/*static const GLfloat MaterialBlue[] = {0.4, 0.4, 0.8, 1.0};*/ +/*static const GLfloat MaterialCyan[] = {0.2, 0.5, 0.7, 1.0};*/ +/*static const GLfloat MaterialYellow[] = {0.7, 0.7, 0.0, 1.0};*/ +/* static const GLfloat MaterialMagenta[] = {0.6, 0.2, 0.5, 1.0}; */ +/*static const GLfloat MaterialWhite[] = {0.7, 0.7, 0.7, 1.0};*/ +static const GLfloat MaterialGray[] = {0.2, 0.2, 0.2, 1.0}; +static const GLfloat MaterialGrayB[] = {0.1, 0.1, 0.1, 0.5}; +/*static const GLfloat MaterialGray35[] = {0.30, 0.30, 0.30, 1.0};*/ + +static const GLfloat MaterialGray5[] = {0.5, 0.5, 0.5, 1.0}; +static const GLfloat MaterialGray6[] = {0.6, 0.6, 0.6, 1.0}; +/* static const GLfloat MaterialGray8[] = {0.8, 0.8, 0.8, 1.0};*/ + +typedef struct { + + double position[3]; + double goal[3]; + double velocity; + double direction; + double step; + + const GLfloat *material; + +} Ant; diff --git a/hacks/glx/antspotlight.c b/hacks/glx/antspotlight.c new file mode 100644 index 00000000..cec2676d --- /dev/null +++ b/hacks/glx/antspotlight.c @@ -0,0 +1,824 @@ +/* + * Permission to use, copy, modify, and distribute this software and its + * documentation for any purpose and without fee is hereby granted, + * provided that the above copyright notice appear in all copies and that + * both that copyright notice and this permission notice appear in + * supporting documentation. + * + * This file is provided AS IS with no warranties of any kind. The author + * shall have no liability with respect to the infringement of copyrights, + * trade secrets or any patents by this file or any part thereof. In no + * event will the author be liable for any lost revenue or profits or + * other special, indirect and consequential damages. + * + * Copyright 2003 Blair Tennessy + */ + +#ifdef STANDALONE +#define DEFAULTS "*delay: 20000 \n" \ + "*showFPS: False \n" \ + "*useSHM: True \n" + +# define refresh_antspotlight 0 +#include "xlockmore.h" +#else +#include "xlock.h" +#endif + +#ifdef HAVE_COCOA +# include "jwxyz.h" +#else +# include +# include +# include +#endif + +#ifdef HAVE_JWZGLES +# include "jwzgles.h" +#endif /* HAVE_JWZGLES */ + +#include "sphere.h" +#include "tube.h" +#include "rotator.h" +#include "gltrackball.h" + +ENTRYPOINT ModeSpecOpt antspotlight_opts = { + 0, NULL, 0, NULL, NULL +}; + +#ifdef USE_MODULES +ModStruct antspotlight_description = { + "antspotlight", "init_antspotlight", "draw_antspotlight", + "release_antspotlight", "draw_antspotlight", "change_antspotlight", + (char *) NULL, &antspotlight_opts, 1000, 1, 1, 1, 4, 1.0, "", + "draws an ant scoping the screen", 0, NULL +}; +#endif + +#define Scale4Window 0.3 +#define Scale4Iconic 0.4 + +#define sqr(A) ((A)*(A)) + +#ifndef Pi +#define Pi M_PI +#endif + +#include "ants.h" +#include "grab-ximage.h" + +typedef struct { + GLXContext *glx_context; + rotator *rot; + trackball_state *trackball; + Bool button_down_p; + + GLfloat max_tx, max_ty; + int mono, wire, ticks; + GLuint screentexture; + + Ant *ant; + double boardsize; + GLfloat spot_direction[3]; + int mag; + + Bool mipmap_p; + Bool waiting_for_image_p; + +} antspotlightstruct; + +static antspotlightstruct *antspotlight = (antspotlightstruct *) NULL; + +#define NUM_SCENES 2 + +/* draw method for ant */ +static Bool draw_ant(ModeInfo *mi, antspotlightstruct *mp, + const GLfloat *Material, int mono, int shadow, + float ant_step, Bool (*sphere)(float), Bool (*cone)(float)) +{ + + float cos1 = cos(ant_step); + float cos2 = cos(ant_step + 2 * Pi / 3); + float cos3 = cos(ant_step + 4 * Pi / 3); + float sin1 = sin(ant_step); + float sin2 = sin(ant_step + 2 * Pi / 3); + float sin3 = sin(ant_step + 4 * Pi / 3); + +/* Apparently this is a performance killer on many systems... + glEnable(GL_POLYGON_SMOOTH); + */ + glEnable(GL_BLEND); + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + + glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, mp->mono ? MaterialGray5 : Material); + glEnable(GL_CULL_FACE); + glPushMatrix(); + glScalef(1, 1.3, 1); + if(!((*sphere)(0.18))) + return False; + glScalef(1, 1 / 1.3, 1); + glTranslatef(0.00, 0.30, 0.00); + if(!((*sphere)(0.2))) + return False; + + glTranslatef(-0.05, 0.17, 0.05); + glRotatef(-90, 1, 0, 0); + glRotatef(-25, 0, 1, 0); + if(!((*cone)(0.05))) + return False; + glTranslatef(0.00, 0.10, 0.00); + if(!((*cone)(0.05))) + return False; + glRotatef(25, 0, 1, 0); + glRotatef(90, 1, 0, 0); + + glScalef(1, 1.3, 1); + glTranslatef(0.15, -0.65, 0.05); + if(!((*sphere)(0.25))) + return False; + glScalef(1, 1 / 1.3, 1); + glPopMatrix(); + glDisable(GL_CULL_FACE); + + glDisable(GL_LIGHTING); + + /* ANTENNAS */ + glEnable(GL_LINE_SMOOTH); + glEnable(GL_BLEND); + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + + glBegin(GL_LINES); + glColor3fv(mp->mono ? MaterialGray5 : Material); + glVertex3f(0.00, 0.30, 0.00); + glColor3fv(MaterialGray); + glVertex3f(0.40, 0.70, 0.40); + mi->polygon_count++; + glColor3fv(mp->mono ? MaterialGray5 : Material); + glVertex3f(0.00, 0.30, 0.00); + glColor3fv(MaterialGray); + glVertex3f(0.40, 0.70, -0.40); + mi->polygon_count++; + glEnd(); + + if(!shadow) { + glBegin(GL_POINTS); + glColor3fv(mp->mono ? MaterialGray6 : MaterialGray5); + glVertex3f(0.40, 0.70, 0.40); + mi->polygon_count++; + glVertex3f(0.40, 0.70, -0.40); + mi->polygon_count++; + glEnd(); + } + + /* LEFT-FRONT ARM */ + glBegin(GL_LINE_STRIP); + glColor3fv(mp->mono ? MaterialGray5 : Material); + glVertex3f(0.00, 0.05, 0.18); + glVertex3f(0.35 + 0.05 * cos1, 0.15, 0.25); + mi->polygon_count++; + glColor3fv(MaterialGray); + glVertex3f(-0.20 + 0.05 * cos1, 0.25 + 0.1 * sin1, 0.45); + mi->polygon_count++; + glEnd(); + + /* LEFT-CENTER ARM */ + glBegin(GL_LINE_STRIP); + glColor3fv(mp->mono ? MaterialGray5 : Material); + glVertex3f(0.00, 0.00, 0.18); + glVertex3f(0.35 + 0.05 * cos2, 0.00, 0.25); + mi->polygon_count++; + glColor3fv(MaterialGray); + glVertex3f(-0.20 + 0.05 * cos2, 0.00 + 0.1 * sin2, 0.45); + mi->polygon_count++; + glEnd(); + + /* LEFT-BACK ARM */ + glBegin(GL_LINE_STRIP); + glColor3fv(mp->mono ? MaterialGray5 : Material); + glVertex3f(0.00, -0.05, 0.18); + glVertex3f(0.35 + 0.05 * cos3, -0.15, 0.25); + mi->polygon_count++; + glColor3fv(MaterialGray); + glVertex3f(-0.20 + 0.05 * cos3, -0.25 + 0.1 * sin3, 0.45); + mi->polygon_count++; + glEnd(); + + /* RIGHT-FRONT ARM */ + glBegin(GL_LINE_STRIP); + glColor3fv(mp->mono ? MaterialGray5 : Material); + glVertex3f(0.00, 0.05, -0.18); + glVertex3f(0.35 - 0.05 * sin1, 0.15, -0.25); + mi->polygon_count++; + glColor3fv(MaterialGray); + glVertex3f(-0.20 - 0.05 * sin1, 0.25 + 0.1 * cos1, -0.45); + mi->polygon_count++; + glEnd(); + + /* RIGHT-CENTER ARM */ + glBegin(GL_LINE_STRIP); + glColor3fv(mp->mono ? MaterialGray5 : Material); + glVertex3f(0.00, 0.00, -0.18); + glVertex3f(0.35 - 0.05 * sin2, 0.00, -0.25); + mi->polygon_count++; + glColor3fv(MaterialGray); + glVertex3f(-0.20 - 0.05 * sin2, 0.00 + 0.1 * cos2, -0.45); + mi->polygon_count++; + glEnd(); + + /* RIGHT-BACK ARM */ + glBegin(GL_LINE_STRIP); + glColor3fv(mp->mono ? MaterialGray5 : Material); + glVertex3f(0.00, -0.05, -0.18); + glVertex3f(0.35 - 0.05 * sin3, -0.15, -0.25); + mi->polygon_count++; + glColor3fv(MaterialGray); + glVertex3f(-0.20 - 0.05 * sin3, -0.25 + 0.1 * cos3, -0.45); + mi->polygon_count++; + glEnd(); + + if(!shadow) { + glBegin(GL_POINTS); + glColor3fv(MaterialGray5); + glVertex3f(-0.20 + 0.05 * cos1, 0.25 + 0.1 * sin1, 0.45); + glVertex3f(-0.20 + 0.05 * cos2, 0.00 + 0.1 * sin2, 0.45); + glVertex3f(-0.20 + 0.05 * cos3, -0.25 + 0.1 * sin3, 0.45); + glVertex3f(-0.20 - 0.05 * sin1, 0.25 + 0.1 * cos1, -0.45); + glVertex3f(-0.20 - 0.05 * sin2, 0.00 + 0.1 * cos2, -0.45); + glVertex3f(-0.20 - 0.05 * sin3, -0.25 + 0.1 * cos3, -0.45); + mi->polygon_count += 6; + glEnd(); + } + + glEnable(GL_LIGHTING); + + return True; +} + +/* filled sphere */ +static Bool mySphere(float radius) +{ +#if 0 + GLUquadricObj *quadObj; + + if((quadObj = gluNewQuadric()) == 0) + return False; + + gluQuadricDrawStyle(quadObj, (GLenum) GLU_FILL); + gluSphere(quadObj, radius, 16, 16); + gluDeleteQuadric(quadObj); +#else + glPushMatrix(); + glScalef (radius, radius, radius); + glRotatef (90, 1, 0, 0); + unit_sphere (16, 16, False); + glPopMatrix(); +#endif + return True; +} + +/* silhouette sphere */ +static Bool mySphere2(float radius) +{ +#if 0 + GLUquadricObj *quadObj; + + if((quadObj = gluNewQuadric()) == 0) + return False; + gluQuadricDrawStyle(quadObj, (GLenum) GLU_LINE); + gluSphere(quadObj, radius, 16, 8); + gluDeleteQuadric(quadObj); +#else + /* #### no GLU_LINE */ + glPushMatrix(); + glScalef (radius, radius, radius); + glRotatef (90, 1, 0, 0); + unit_sphere (16, 16, True); + glPopMatrix(); +#endif + return True; +} + +/* no cone */ +static Bool myCone2(float radius) { return True; } + +static void draw_board(ModeInfo *mi, antspotlightstruct *mp) +{ + int i, j; + double cutoff = Pi/3.0; + double center[3]; + double centertex[2]; + + glEnable(GL_TEXTURE_2D); + glBindTexture(GL_TEXTURE_2D, mp->screentexture); + glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, MaterialGray6); + + /* draw mesh */ + + /* center is roughly spotlight position */ + center[0] = mp->ant->position[0];/* + cos(ant->direction); */ + center[1] = 0.0; + center[2] = mp->ant->position[2];/* - 0.7*sin(ant->direction);*/ + + centertex[0] = (mp->boardsize/2.0+center[0]) * mp->max_tx / mp->boardsize; + centertex[1] = mp->max_ty - ((mp->boardsize/2.0+center[2]) * mp->max_ty / mp->boardsize); + +/* glPolygonMode(GL_FRONT, GL_LINE); */ +/* glDisable(GL_TEXTURE_2D); */ + + /* + the vertices determined here should correspond to the illuminated + board. ideally the code adapts vertex distribution to the + intensity and shape of the light. + + i should be finding the intersection of the cone of light and + the board-plane. + */ + for(i = -12; i < 12; ++i) { + + double theta1, theta2; + + glBegin(GL_TRIANGLE_STRIP); + glNormal3f(0.0, 1.0, 0.0); + + glTexCoord2f(centertex[0], centertex[1]); + glVertex3f(center[0], 0.01, center[2]); + + /* watch those constants */ + theta1 = mp->ant->direction + i*(cutoff/8); + theta2 = mp->ant->direction + (i+1)*(cutoff/8); + + for(j = 1; j <= 64; ++j) { + double point[3], tex[2]; + /* double fj = pow(1.05, j) - 1.0;*/ + double fj = j / 6.0; + point[0] = center[0] + fj*cos(theta1); + point[1] = 0.0; + point[2] = center[2] - fj*sin(theta1); + + tex[0] = (mp->boardsize/2.0+point[0]) * mp->max_tx / mp->boardsize; + tex[1] = (mp->boardsize/2.0+point[2]) * mp->max_ty / mp->boardsize; + + glTexCoord2f(tex[0], tex[1]); + glVertex3f(point[0], point[1], point[2]); + + point[0] = center[0] + fj*cos(theta2); + point[1] = 0.0; + point[2] = center[2] - fj*sin(theta2); + + tex[0] = (mp->boardsize/2.0+point[0]) * mp->max_tx / mp->boardsize; + tex[1] = (mp->boardsize/2.0+point[2]) * mp->max_ty / mp->boardsize; + + glTexCoord2f(tex[0], tex[1]); + glVertex3f(point[0], point[1], point[2]); + mi->polygon_count++; + } + + glEnd(); + } + + glDisable(GL_TEXTURE_2D); +} + +/* return euclidean distance between two points */ +static double distance(double x[3], double y[3]) +{ + double dx = x[0] - y[0]; + double dz = x[2] - y[2]; + return sqrt(dx*dx + dz*dz); +} + +/* determine a new goal */ +static void find_goal(antspotlightstruct *mp) +{ + do { + mp->ant->goal[0] = random()%((int)(mp->boardsize+0.5)-2) - mp->boardsize/2.0 + 1.0; + mp->ant->goal[1] = 0.0; + mp->ant->goal[2] = random()%((int)(mp->boardsize+0.5)-2) - mp->boardsize/2.0 + 1.0; + } + while(distance(mp->ant->position, mp->ant->goal) < 2.0); +} + +/* construct our ant */ +static void build_ant(antspotlightstruct *mp) +{ + mp->ant = (Ant *) malloc(sizeof (Ant)); + mp->ant->position[0] = 0.0; + mp->ant->position[1] = 0.0; + mp->ant->position[2] = 0.0; + mp->ant->direction = 0.0; + mp->ant->velocity = 0.02; + mp->ant->material = MaterialGray5; + mp->ant->step = 0; + find_goal(mp); +} + +#define EPSILON 0.01 + +static double sign(double d) +{ + return d < 0.0 ? -1.0 : 1.0; +} + +static double min(double a, double b) +{ + return a < b ? a : b; +} + +/* +static double max(double a, double b) +{ + return a > b ? a : b; +} +*/ + +/* find a new goal and reset steps */ +static void reset_ant(antspotlightstruct *mp) +{ + find_goal(mp); +} + +/* draw ant composed of skeleton and glass */ +static void show_ant(ModeInfo *mi, antspotlightstruct *mp) +{ + + glPushMatrix(); + + /* move into position */ + glTranslatef(mp->ant->position[0], 0.33, mp->ant->position[2]); + glRotatef(180.0 + mp->ant->direction*180.0/Pi, 0.0, 1.0, 0.0); + glRotatef(90.0, 0.0, 0.0, 1.0); + + /* draw skeleton */ + draw_ant(mi, mp, mp->ant->material, mp->mono, 0, mp->ant->step, mySphere2, myCone2); + + /* draw glass */ + if(!mp->wire && !mp->mono) { + glEnable(GL_BLEND); + glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, MaterialGrayB); + glColor4fv(MaterialGrayB); + draw_ant(mi, mp, MaterialGrayB, mp->mono, 0, mp->ant->step, mySphere, myCone2); + glDisable(GL_BLEND); + } + + glPopMatrix(); +} + +static void draw_antspotlight_strip(ModeInfo *mi) +{ + antspotlightstruct *mp = &antspotlight[MI_SCREEN(mi)]; + + /* compute spotlight position and direction */ + GLfloat light1_position[4]; + + light1_position[0] = mp->ant->position[0] + 0.7*cos(mp->ant->direction); + light1_position[1] = 0.5; + light1_position[2] = mp->ant->position[2] - 0.7*sin(mp->ant->direction); + light1_position[3] = 1.0; + + mp->spot_direction[0] = cos(mp->ant->direction); + mp->spot_direction[1] = -0.5; + mp->spot_direction[2] = -sin(mp->ant->direction); + + glLightfv(GL_LIGHT2, GL_POSITION, light1_position); + glLightfv(GL_LIGHT2, GL_SPOT_DIRECTION, mp->spot_direction); + + glEnable(GL_LIGHT2); + glDisable(GL_LIGHT0); + glDisable(GL_LIGHT1); + + /* draw board */ + if(mp->wire) + ; + else + draw_board(mi, mp); + + glDisable(GL_LIGHT2); + glEnable(GL_LIGHT0); + glEnable(GL_LIGHT1); + + /* now modify ant */ + show_ant(mi, mp); + + /* near goal, bend path towards next step */ + if(distance(mp->ant->position, mp->ant->goal) < 0.2) { + reset_ant(mp); + } + + if(random()%100 == 0) { + reset_ant(mp); + } + + + /* move toward goal, correct ant direction if required */ + else { + + /* difference */ + double dx = mp->ant->goal[0] - mp->ant->position[0]; + double dz = -(mp->ant->goal[2] - mp->ant->position[2]); + double theta, ideal, dt; + + if(fabs(dx) > EPSILON) { + theta = atan(dz/dx); + if(dx < 0.0) + theta += Pi; + } + else + theta = dz > 0.0 ? (1.0/2.0)*Pi : (3.0/2.0)*Pi; + + if(theta < 0.0) + theta += 2*Pi; + + ideal = theta - mp->ant->direction; + if(ideal > Pi) + ideal -= 2*Pi; + + /* compute correction */ + dt = sign(ideal) * min(fabs(ideal), Pi/100.0); + mp->ant->direction += dt; + while(mp->ant->direction < 0.0) + mp->ant->direction += 2*Pi; + while(mp->ant->direction > 2*Pi) + mp->ant->direction -= 2*Pi; + } + + mp->ant->position[0] += mp->ant->velocity * cos(mp->ant->direction); + mp->ant->position[2] += mp->ant->velocity * sin(-mp->ant->direction); + mp->ant->step += 10*mp->ant->velocity; + while(mp->ant->step > 2*Pi) + mp->ant->step -= 2*Pi; +} + +ENTRYPOINT void reshape_antspotlight(ModeInfo * mi, int width, int height) +{ + double h = (GLfloat) height / (GLfloat) width; + int size = 2; + glViewport(0, 0, width, height); + glMatrixMode(GL_PROJECTION); + glLoadIdentity(); + + gluPerspective(45, 1/h, 1.0, 25.0); + + glMatrixMode(GL_MODELVIEW); + glLineWidth(size); + glPointSize(size); +} + +/* lighting variables */ +static const GLfloat front_shininess[] = {60.0}; +static const GLfloat front_specular[] = {0.8, 0.8, 0.8, 1.0}; +static const GLfloat ambient[] = {0.4, 0.4, 0.4, 1.0}; +/*static const GLfloat ambient2[] = {0.0, 0.0, 0.0, 0.0};*/ +static const GLfloat diffuse[] = {1.0, 1.0, 1.0, 1.0}; +static const GLfloat position0[] = {1.0, 5.0, 1.0, 0.0}; +static const GLfloat position1[] = {-1.0, -5.0, 1.0, 0.0}; +/*static const GLfloat lmodel_ambient[] = {0.8, 0.8, 0.8, 1.0};*/ +static const GLfloat lmodel_twoside[] = {GL_TRUE}; +static const GLfloat spotlight_ambient[] = { 0.0, 0.0, 0.0, 1.0 }; +static const GLfloat spotlight_diffuse[] = { 1.0, 1.0, 1.0, 1.0 }; + +static void pinit(void) +{ + glClearDepth(1.0); + + /* setup twoside lighting */ + glLightfv(GL_LIGHT0, GL_AMBIENT, ambient); + glLightfv(GL_LIGHT0, GL_DIFFUSE, diffuse); + glLightfv(GL_LIGHT0, GL_POSITION, position0); + glLightfv(GL_LIGHT1, GL_AMBIENT, ambient); + glLightfv(GL_LIGHT1, GL_DIFFUSE, diffuse); + glLightfv(GL_LIGHT1, GL_POSITION, position1); + + glLightModelfv(GL_LIGHT_MODEL_AMBIENT, spotlight_ambient); + glLightModelfv(GL_LIGHT_MODEL_TWO_SIDE, lmodel_twoside); + glEnable(GL_LIGHTING); + glEnable(GL_LIGHT0); + glEnable(GL_LIGHT1); + + /* setup spotlight */ + glLightfv(GL_LIGHT2, GL_AMBIENT, spotlight_ambient); + glLightfv(GL_LIGHT2, GL_DIFFUSE, spotlight_diffuse); + glLightf(GL_LIGHT2, GL_CONSTANT_ATTENUATION, 0.1); + glLightf(GL_LIGHT2, GL_LINEAR_ATTENUATION, 0.05); + glLightf(GL_LIGHT2, GL_QUADRATIC_ATTENUATION, 0.0); + glLightf(GL_LIGHT2, GL_SPOT_CUTOFF, 60.0); + glLightf(GL_LIGHT2, GL_SPOT_EXPONENT, 3.0); + + glEnable(GL_NORMALIZE); + glFrontFace(GL_CCW); + glCullFace(GL_BACK); + + /* setup material properties */ + glMaterialfv(GL_FRONT_AND_BACK, GL_SHININESS, front_shininess); + glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, front_specular); + + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + glShadeModel(GL_SMOOTH); +/* glShadeModel(GL_FLAT); */ + glEnable(GL_DEPTH_TEST); +} + +/* cleanup routine */ +ENTRYPOINT void release_antspotlight(ModeInfo * mi) +{ + + if(antspotlight) { + free((void *) antspotlight); + antspotlight = (antspotlightstruct *) NULL; + } + + FreeAllGL(mi); +} + +#define MAX_MAGNIFICATION 10 +#define max(a, b) a < b ? b : a +#define min(a, b) a < b ? a : b + +/* event handling */ +ENTRYPOINT Bool antspotlight_handle_event(ModeInfo *mi, XEvent *event) +{ + antspotlightstruct *mp = &antspotlight[MI_SCREEN(mi)]; + + switch(event->xany.type) { + case ButtonPress: + + switch(event->xbutton.button) { + + case Button1: + mp->button_down_p = True; + gltrackball_start(mp->trackball, + event->xbutton.x, event->xbutton.y, + MI_WIDTH (mi), MI_HEIGHT (mi)); + break; + + case Button4: + mp->mag = max(mp->mag-1, 1); + break; + + case Button5: + mp->mag = min(mp->mag+1, MAX_MAGNIFICATION); + break; + } + + break; + + case ButtonRelease: + + switch(event->xbutton.button) { + case Button1: + mp->button_down_p = False; + break; + } + + break; + + case MotionNotify: + if(mp->button_down_p) + gltrackball_track(mp->trackball, + event->xmotion.x, event->xmotion.y, + MI_WIDTH (mi), MI_HEIGHT (mi)); + break; + + default: + return False; + } + + return True; +} + +static void +image_loaded_cb (const char *filename, XRectangle *geometry, + int image_width, int image_height, + int texture_width, int texture_height, + void *closure) +{ + antspotlightstruct *mp = (antspotlightstruct *) closure; + + mp->max_tx = (GLfloat) image_width / texture_width; + mp->max_ty = (GLfloat) image_height / texture_height; + + glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, + (mp->mipmap_p ? GL_LINEAR_MIPMAP_LINEAR : GL_LINEAR)); + + mp->waiting_for_image_p = False; +} + + +/* get screenshot */ +static void get_snapshot(ModeInfo *modeinfo) +{ + antspotlightstruct *mp = &antspotlight[MI_SCREEN(modeinfo)]; + + if (MI_IS_WIREFRAME(modeinfo)) + return; + + mp->waiting_for_image_p = True; + mp->mipmap_p = True; + load_texture_async (modeinfo->xgwa.screen, modeinfo->window, + *mp->glx_context, 0, 0, mp->mipmap_p, + mp->screentexture, image_loaded_cb, mp); +} + + +ENTRYPOINT void init_antspotlight(ModeInfo *mi) +{ + double rot_speed = 0.3; + + antspotlightstruct *mp; + + if(!antspotlight) { + if((antspotlight = (antspotlightstruct *) + calloc(MI_NUM_SCREENS(mi), sizeof (antspotlightstruct))) == NULL) + return; + } + mp = &antspotlight[MI_SCREEN(mi)]; + mp->rot = make_rotator (rot_speed, rot_speed, rot_speed, 1, 0, True); + mp->trackball = gltrackball_init (); + + if((mp->glx_context = init_GL(mi)) != NULL) { + reshape_antspotlight(mi, MI_WIDTH(mi), MI_HEIGHT(mi)); + glDrawBuffer(GL_BACK); + pinit(); + } + else + MI_CLEARWINDOW(mi); + + glGenTextures(1, &mp->screentexture); + glBindTexture(GL_TEXTURE_2D, mp->screentexture); + get_snapshot(mi); + + build_ant(mp); + mp->mono = MI_IS_MONO(mi); + mp->wire = MI_IS_WIREFRAME(mi); + mp->boardsize = 8.0; + mp->mag = 1; +} + +ENTRYPOINT void draw_antspotlight(ModeInfo * mi) +{ + antspotlightstruct *mp; + + Display *display = MI_DISPLAY(mi); + Window window = MI_WINDOW(mi); + + if(!antspotlight) + return; + mp = &antspotlight[MI_SCREEN(mi)]; + + MI_IS_DRAWN(mi) = True; + + if(!mp->glx_context) + return; + + mi->polygon_count = 0; + + /* Just keep running before the texture has come in. */ + /* if (mp->waiting_for_image_p) return; */ + + glXMakeCurrent(display, window, *(mp->glx_context)); + + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + + glPushMatrix(); + glRotatef(current_device_rotation(), 0, 0, 1); + + /* position camera */ + + /* follow focused ant */ + glTranslatef(0.0, 0.0, -6.0 - mp->mag); + glRotatef(35.0, 1.0, 0.0, 0.0); + gltrackball_rotate(mp->trackball); + glTranslatef(-mp->ant->position[0], mp->ant->position[1], -mp->ant->position[2]); + + /* stable position */ +/* glTranslatef(0.0, 0.0, -10.0 - mag); */ +/* gltrackball_rotate(mp->trackball); */ +/* glRotatef(40.0, 1.0, 0.0, 0.0); */ +/* glRotatef(20.0, 0.0, 1.0, 0.0); */ + + draw_antspotlight_strip(mi); + + ++mp->ticks; + + glPopMatrix(); + + if (MI_IS_FPS(mi)) do_fps (mi); + glFlush(); + + glXSwapBuffers(display, window); +} + +#ifndef STANDALONE +ENTRYPOINT void change_antspotlight(ModeInfo * mi) +{ + antspotlightstruct *mp = &antspotlight[MI_SCREEN(mi)]; + + if (!mp->glx_context) + return; + + glXMakeCurrent(MI_DISPLAY(mi), MI_WINDOW(mi), *(mp->glx_context)); + pinit(); +} +#endif /* !STANDALONE */ + +XSCREENSAVER_MODULE ("AntSpotlight", antspotlight) diff --git a/hacks/glx/antspotlight.man b/hacks/glx/antspotlight.man new file mode 100644 index 00000000..c5f8ed7c --- /dev/null +++ b/hacks/glx/antspotlight.man @@ -0,0 +1,56 @@ +.TH XScreenSaver 1 "July 2003" +.SH NAME +antspotlight \- ant spotlight screenhack +.SH SYNOPSIS +.B antspotlight +[\-display \fIhost:display.screen\fP] [\-window] [\-root] [\-install] +[\-visual \fIvisual\fP] [\-delay \fImicroseconds\fP] [\-fps] +.SH DESCRIPTION +The \fIantspotlight\fP code displays a single ant spotting out a screenshot. +.SH OPTIONS +.I antspotlight +accepts the following options: +.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 \-install +Install a private colormap for the window. +.TP 8 +.B \-visual \fIvisual\fP\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 \-fps +Display the current frame rate, CPU load, and polygon count. +.TP 8 +.B \-delay \fImicroseconds\fP +Per-frame delay. +.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) +.BR xscreensaver\-demo (1), +.BR xscreensaver\-getimage (1) +.SH COPYRIGHT +Copyright \(co 2003 by Blair Tennessy. 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 +Blair Tennessy , 20-July-2003. + diff --git a/hacks/glx/atlantis.c b/hacks/glx/atlantis.c new file mode 100644 index 00000000..85bd4a59 --- /dev/null +++ b/hacks/glx/atlantis.c @@ -0,0 +1,579 @@ +/* atlantis --- Shows moving 3D sea animals */ + +#if 0 +static const char sccsid[] = "@(#)atlantis.c 5.08 2003/04/09 xlockmore"; +#endif + +/* Copyright (c) E. Lassauge, 1998. */ + +/* + * Permission to use, copy, modify, and distribute this software and its + * documentation for any purpose and without fee is hereby granted, + * provided that the above copyright notice appear in all copies and that + * both that copyright notice and this permission notice appear in + * supporting documentation. + * + * This file is provided AS IS with no warranties of any kind. The author + * shall have no liability with respect to the infringement of copyrights, + * trade secrets or any patents by this file or any part thereof. In no + * event will the author be liable for any lost revenue or profits or + * other special, indirect and consequential damages. + * + * The original code for this mode was written by Mark J. Kilgard + * as a demo for openGL programming. + * + * Porting it to xlock was possible by comparing the original Mesa's morph3d + * demo with it's ported version to xlock, so thanks for Marcelo F. Vianna + * (look at morph3d.c) for his indirect help. + * + * Thanks goes also to Brian Paul for making it possible and inexpensive + * to use OpenGL at home. + * + * My e-mail address is lassauge@users.sourceforge.net + * + * Eric Lassauge (May-13-1998) + * + * REVISION HISTORY: + * + * Jamie Zawinski, 2-Apr-01: - The fishies were inside out! The back faces + * were being drawn, not the front faces. + * - Added a texture to simulate light from the + * surface, like in the SGI version. + * + * David A. Bagley - 98/06/17 : Add whalespeed option. Global options to + * initialize local variables are now: + * XLock.atlantis.cycles: 100 ! SharkSpeed + * XLock.atlantis.batchcount: 4 ! SharkNum + * XLock.atlantis.whalespeed: 250 ! WhaleSpeed + * XLock.atlantis.size: 6000 ! SharkSize + * Add random direction for whales/dolphins + * + * E.Lassauge - 98/06/16: Use the following global options to initialize + * local variables : + * XLock.atlantis.delay: 100 ! SharkSpeed + * XLock.atlantis.batchcount: 4 ! SharkNum + * XLock.atlantis.cycles: 250 ! WhaleSpeed + * XLock.atlantis.size: 6000 ! SharkSize + * Add support for -/+ wireframe (t'was so easy to do!) + * + * TODO : + * - better handling of sizes and speeds + * - test standalone and module modes + * - purify it (!) + */ + +/* Copyright (c) Mark J. Kilgard, 1994. */ + +/** + * (c) Copyright 1993, 1994, Silicon Graphics, Inc. + * ALL RIGHTS RESERVED + * Permission to use, copy, modify, and distribute this software for + * any purpose and without fee is hereby granted, provided that the above + * copyright notice appear in all copies and that both the copyright notice + * and this permission notice appear in supporting documentation, and that + * the name of Silicon Graphics, Inc. not be used in advertising + * or publicity pertaining to distribution of the software without specific, + * written prior permission. + * + * THE MATERIAL EMBODIED ON THIS SOFTWARE IS PROVIDED TO YOU "AS-IS" + * AND WITHOUT WARRANTY OF ANY KIND, EXPRESS, IMPLIED OR OTHERWISE, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTY OF MERCHANTABILITY OR + * FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL SILICON + * GRAPHICS, INC. BE LIABLE TO YOU OR ANYONE ELSE FOR ANY DIRECT, + * SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY + * KIND, OR ANY DAMAGES WHATSOEVER, INCLUDING WITHOUT LIMITATION, + * LOSS OF PROFIT, LOSS OF USE, SAVINGS OR REVENUE, OR THE CLAIMS OF + * THIRD PARTIES, WHETHER OR NOT SILICON GRAPHICS, INC. HAS BEEN + * ADVISED OF THE POSSIBILITY OF SUCH LOSS, HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE + * POSSESSION, USE OR PERFORMANCE OF THIS SOFTWARE. + * + * US Government Users Restricted Rights + * Use, duplication, or disclosure by the Government is subject to + * restrictions set forth in FAR 52.227.19(c)(2) or subparagraph + * (c)(1)(ii) of the Rights in Technical Data and Computer Software + * clause at DFARS 252.227-7013 and/or in similar or successor + * clauses in the FAR or the DOD or NASA FAR Supplement. + * Unpublished-- rights reserved under the copyright laws of the + * United States. Contractor/manufacturer is Silicon Graphics, + * Inc., 2011 N. Shoreline Blvd., Mountain View, CA 94039-7311. + * + * OpenGL(TM) is a trademark of Silicon Graphics, Inc. + */ + +#define DEF_TEXTURE "True" +#define DEF_GRADIENT "True" +#define DEF_WHALESPEED "250" + +#ifdef STANDALONE +# define DEFAULTS "*delay: 25000 \n" \ + "*count: 4 \n" \ + "*showFPS: False \n" \ + "*cycles: 100 \n" \ + "*size: 6000 \n" \ + "*wireframe: False \n" +# define atlantis_handle_event 0 +# include "xlockmore.h" /* from the xscreensaver distribution */ +#else /* !STANDALONE */ +# include "xlock.h" /* from the xlockmore distribution */ +# include "vis.h" +#endif /* !STANDALONE */ + +#ifdef USE_GL + +#include "atlantis.h" + + +static int whalespeed; +static int do_texture; +static int do_gradient; +static XrmOptionDescRec opts[] = +{ + {"-whalespeed", ".atlantis.whalespeed", XrmoptionSepArg, 0}, + {"-texture", ".atlantis.texture", XrmoptionNoArg, "true"}, + {"+texture", ".atlantis.texture", XrmoptionNoArg, "false"}, + {"-gradient", ".atlantis.gradient", XrmoptionNoArg, "true"}, + {"+gradient", ".atlantis.gradient", XrmoptionNoArg, "false"}, +}; + +static argtype vars[] = +{ + {&whalespeed, "whalespeed", "WhaleSpeed", DEF_WHALESPEED, t_Int}, + {&do_texture, "texture", "Texture", DEF_TEXTURE, t_Bool}, + {&do_gradient, "gradient", "Gradient", DEF_GRADIENT, t_Bool}, +}; + +static OptionStruct desc[] = +{ + {"-whalespeed num", "speed of whales and the dolphin"}, + {"-texture", "whether to introduce water-like distortion"}, + {"-gradient", "whether to introduce gradient-filled background"}, +}; + +ENTRYPOINT ModeSpecOpt atlantis_opts = +{sizeof opts / sizeof opts[0], opts, sizeof vars / sizeof vars[0], vars, desc}; + +#ifdef USE_MODULES +ModStruct atlantis_description = +{"atlantis", "init_atlantis", "draw_atlantis", "release_atlantis", + "refresh_atlantis", "change_atlantis", NULL, &atlantis_opts, + 1000, NUM_SHARKS, SHARKSPEED, SHARKSIZE, 64, 1.0, "", + "Shows moving sharks/whales/dolphin", 0, NULL}; + +#endif + +static atlantisstruct *atlantis = NULL; + +#include "xpm-ximage.h" + +#include "../images/sea-texture.xpm" + + +static void +parse_image_data(ModeInfo *mi) +{ + atlantisstruct *ap = &atlantis[MI_SCREEN(mi)]; + ap->texture = xpm_to_ximage (mi->dpy, + mi->xgwa.visual, + mi->xgwa.colormap, + sea_texture); +} + +static void +InitFishs(atlantisstruct * ap) +{ + int i; + + for (i = 0; i < ap->num_sharks; i++) { + ap->sharks[i].x = 70000.0 + NRAND(ap->sharksize); + ap->sharks[i].y = NRAND(ap->sharksize); + ap->sharks[i].z = NRAND(ap->sharksize); + ap->sharks[i].psi = NRAND(360) - 180.0; + ap->sharks[i].v = 1.0; + } + + /* Random whale direction */ + ap->whaledir = LRAND() & 1; + + ap->dolph.x = 30000.0; + ap->dolph.y = 0.0; + ap->dolph.z = (float) (ap->sharksize); + ap->dolph.psi = (ap->whaledir) ? 90.0 : -90.0; + ap->dolph.theta = 0.0; + ap->dolph.v = 6.0; + + ap->momWhale.x = 70000.0; + ap->momWhale.y = 0.0; + ap->momWhale.z = 0.0; + ap->momWhale.psi = (ap->whaledir) ? 90.0 : -90.0; + ap->momWhale.theta = 0.0; + ap->momWhale.v = 3.0; + + ap->babyWhale.x = 60000.0; + ap->babyWhale.y = -2000.0; + ap->babyWhale.z = -2000.0; + ap->babyWhale.psi = (ap->whaledir) ? 90.0 : -90.0; + ap->babyWhale.theta = 0.0; + ap->babyWhale.v = 3.0; +} + +static void +Init(ModeInfo *mi) +{ + atlantisstruct *ap = &atlantis[MI_SCREEN(mi)]; + + static const float ambient[] = {0.1, 0.1, 0.1, 1.0}; + static const float diffuse[] = {1.0, 1.0, 1.0, 1.0}; + static const float position[] = {0.0, 1.0, 0.0, 0.0}; + static const float mat_shininess[] = {90.0}; + static const float mat_specular[] = {0.8, 0.8, 0.8, 1.0}; + static const float mat_diffuse[] = {0.46, 0.66, 0.795, 1.0}; + static const float mat_ambient[] = {0.0, 0.1, 0.2, 1.0}; + static const float lmodel_ambient[] = {0.4, 0.4, 0.4, 1.0}; + static const float lmodel_localviewer[] = {0.0}; + + float fblue = 0.0, fgreen; + + glFrontFace(GL_CCW); + + if (ap->wire) + { + glDisable(GL_DEPTH_TEST); + glDisable(GL_CULL_FACE); + glDisable(GL_LIGHTING); + glDisable(GL_NORMALIZE); + } + else + { + glDepthFunc(GL_LEQUAL); + glEnable(GL_DEPTH_TEST); + glEnable(GL_CULL_FACE); + glEnable(GL_NORMALIZE); + glShadeModel(GL_SMOOTH); + + glLightfv(GL_LIGHT0, GL_AMBIENT, ambient); + glLightfv(GL_LIGHT0, GL_DIFFUSE, diffuse); + glLightfv(GL_LIGHT0, GL_POSITION, position); + glLightModelfv(GL_LIGHT_MODEL_AMBIENT, lmodel_ambient); + glLightModelfv(GL_LIGHT_MODEL_LOCAL_VIEWER, lmodel_localviewer); + glEnable(GL_LIGHTING); + glEnable(GL_LIGHT0); + + glMaterialfv(GL_FRONT_AND_BACK, GL_SHININESS, mat_shininess); + glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, mat_specular); + glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, mat_diffuse); + glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, mat_ambient); + } + + if (ap->wire || !do_texture) + { + glDisable(GL_TEXTURE_2D); + } + else + { + GLfloat s_plane[] = { 1, 0, 0, 0 }; + GLfloat t_plane[] = { 0, 0, 1, 0 }; + GLfloat scale = 0.0005; + + if (!ap->texture) + parse_image_data (mi); + + clear_gl_error(); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, + ap->texture->width, ap->texture->height, 0, + GL_RGBA, GL_UNSIGNED_BYTE, + ap->texture->data); + check_gl_error("texture"); + + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + + glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); + + glTexGeni (GL_S, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR); + glTexGeni (GL_T, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR); + glTexGenfv(GL_S, GL_EYE_PLANE, s_plane); + glTexGenfv(GL_T, GL_EYE_PLANE, t_plane); + +# ifndef HAVE_JWZGLES + glEnable(GL_TEXTURE_GEN_S); + glEnable(GL_TEXTURE_GEN_T); +# endif + glEnable(GL_TEXTURE_2D); + + glMatrixMode(GL_TEXTURE); + glLoadIdentity(); + glScalef(scale, scale, 1); + glMatrixMode(GL_MODELVIEW); + } + + InitFishs(ap); + + /* Add a little randomness */ + fblue = ((float) (NRAND(30)) / 100.0) + 0.70; + fgreen = fblue * 0.56; + glClearColor(0.0, fgreen, fblue, 1.0); +} + +ENTRYPOINT void +reshape_atlantis(ModeInfo * mi, int width, int height) +{ + atlantisstruct *ap = &atlantis[MI_SCREEN(mi)]; + + glViewport(0, 0, ap->WinW = (GLint) width, ap->WinH = (GLint) height); + + glMatrixMode(GL_PROJECTION); + glLoadIdentity(); + gluPerspective(400.0, (GLdouble) width / (GLdouble) height, 1.0, 2000000.0); + glMatrixMode(GL_MODELVIEW); +} + + +/* Fill the background with a gradient -- thanks to + Phil Carrig for figuring out + how to do this more efficiently! + */ +static void +clear_tank (atlantisstruct * ap) +{ + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + + if (do_gradient && !ap->wire) + { + GLfloat top[4] = { 0.00, 0.40, 0.70, }; + GLfloat bot[4] = { 0.00, 0.05, 0.18, }; + + glMatrixMode(GL_PROJECTION); + glPushMatrix(); + { + glLoadIdentity(); + glMatrixMode(GL_MODELVIEW); + glPushMatrix(); + { + glLoadIdentity(); + glRotatef(current_device_rotation(), 0, 0, 1); + +# ifndef HAVE_JWZGLES + glShadeModel (GL_SMOOTH); +# endif + glDisable (GL_LIGHTING); + glBegin (GL_QUADS); + glColor3fv (bot); + glVertex3f (-1, -1, 1); glVertex3f ( 1, -1, 1); + glColor3fv (top); + glVertex3f ( 1, 1, 1); glVertex3f (-1, 1, 1); + glEnd(); + glEnable (GL_LIGHTING); + } + glPopMatrix(); + } + glMatrixMode(GL_PROJECTION); + glPopMatrix(); + + glMatrixMode(GL_MODELVIEW); + } +} + + +static void +Animate(atlantisstruct * ap) +{ + int i; + + for (i = 0; i < ap->num_sharks; i++) { + SharkPilot(&(ap->sharks[i]), ap->sharkspeed); + SharkMiss(ap, i); + } + WhalePilot(&(ap->dolph), ap->whalespeed, ap->whaledir); + ap->dolph.phi++; + WhalePilot(&(ap->momWhale), ap->whalespeed, ap->whaledir); + ap->momWhale.phi++; + WhalePilot(&(ap->babyWhale), ap->whalespeed, ap->whaledir); + ap->babyWhale.phi++; +} + +static void +AllDisplay(atlantisstruct * ap) +{ + int i; + + clear_tank(ap); + + for (i = 0; i < ap->num_sharks; i++) { + glPushMatrix(); + FishTransform(&(ap->sharks[i])); + DrawShark(&(ap->sharks[i]), ap->wire); + glPopMatrix(); + } + + glPushMatrix(); + FishTransform(&(ap->dolph)); + DrawDolphin(&(ap->dolph), ap->wire); + glPopMatrix(); + + glPushMatrix(); + FishTransform(&(ap->momWhale)); + DrawWhale(&(ap->momWhale), ap->wire); + glPopMatrix(); + + glPushMatrix(); + FishTransform(&(ap->babyWhale)); + glScalef(0.45, 0.45, 0.3); + DrawWhale(&(ap->babyWhale), ap->wire); + glPopMatrix(); +} + +/* + *----------------------------------------------------------------------------- + *----------------------------------------------------------------------------- + * Xlock hooks. + *----------------------------------------------------------------------------- + *----------------------------------------------------------------------------- + */ + +/* + *----------------------------------------------------------------------------- + * Initialize atlantis. Called each time the window changes. + *----------------------------------------------------------------------------- + */ + +ENTRYPOINT void +init_atlantis(ModeInfo * mi) +{ + int screen = MI_SCREEN(mi); + atlantisstruct *ap; + Display *display = MI_DISPLAY(mi); + Window window = MI_WINDOW(mi); + + if (atlantis == NULL) { + if ((atlantis = (atlantisstruct *) calloc(MI_NUM_SCREENS(mi), + sizeof (atlantisstruct))) == NULL) + return; + } + ap = &atlantis[screen]; + ap->num_sharks = MI_COUNT(mi); + if (ap->sharks == NULL) { + if ((ap->sharks = (fishRec *) calloc(ap->num_sharks, + sizeof (fishRec))) == NULL) { + /* free everything up to now */ + (void) free((void *) atlantis); + atlantis = NULL; + return; + } + } + ap->sharkspeed = MI_CYCLES(mi); /* has influence on the "width" + of the movement */ + ap->sharksize = MI_SIZE(mi); /* has influence on the "distance" + of the sharks */ + ap->whalespeed = whalespeed; + ap->wire = MI_IS_WIREFRAME(mi); + + if (MI_IS_DEBUG(mi)) { + (void) fprintf(stderr, + "%s:\n\tnum_sharks=%d\n\tsharkspeed=%.1f\n\tsharksize=%d\n\twhalespeed=%.1f\n\twireframe=%s\n", + MI_NAME(mi), + ap->num_sharks, + ap->sharkspeed, + ap->sharksize, + ap->whalespeed, + ap->wire ? "yes" : "no" + ); + } + if ((ap->glx_context = init_GL(mi)) != NULL) { + + reshape_atlantis(mi, MI_WIDTH(mi), MI_HEIGHT(mi)); + glDrawBuffer(GL_BACK); + Init(mi); + AllDisplay(ap); + glXSwapBuffers(display, window); + + } else { + MI_CLEARWINDOW(mi); + } +} + +/* + *----------------------------------------------------------------------------- + * Called by the mainline code periodically to update the display. + *----------------------------------------------------------------------------- + */ +ENTRYPOINT void +draw_atlantis(ModeInfo * mi) +{ + atlantisstruct *ap = &atlantis[MI_SCREEN(mi)]; + + Display *display = MI_DISPLAY(mi); + Window window = MI_WINDOW(mi); + + MI_IS_DRAWN(mi) = True; + + if (!ap->glx_context) + return; + + glXMakeCurrent(display, window, *(ap->glx_context)); + + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + + glPushMatrix(); + glRotatef(current_device_rotation(), 0, 0, 1); + AllDisplay(ap); + Animate(ap); + glPopMatrix(); + + if (mi->fps_p) do_fps (mi); + glXSwapBuffers(display, window); +} + + +/* + *----------------------------------------------------------------------------- + * The display is being taken away from us. Free up malloc'ed + * memory and X resources that we've alloc'ed. Only called + * once, we must zap everything for every screen. + *----------------------------------------------------------------------------- + */ + +ENTRYPOINT void +release_atlantis(ModeInfo * mi) +{ +#if 0 + int screen; + + if (atlantis != NULL) { + for (screen = 0; screen < MI_NUM_SCREENS(mi); screen++) { + atlantisstruct *ap = &atlantis[screen]; + + if (ap->sharks) + (void) free((void *) ap->sharks); + } + (void) free((void *) atlantis); + atlantis = NULL; + } + FreeAllGL(mi); +#endif +} + +ENTRYPOINT void +refresh_atlantis(ModeInfo * mi) +{ +} + +#ifndef STANDALONE +ENTRYPOINT void +change_atlantis(ModeInfo * mi) +{ + atlantisstruct *ap = &atlantis[MI_SCREEN(mi)]; + + if (!ap->glx_context) + return; + + glXMakeCurrent(MI_DISPLAY(mi), MI_WINDOW(mi), *(ap->glx_context)); + Init(mi); +} +#endif /* !STANDALONE */ + +XSCREENSAVER_MODULE ("Atlantis", atlantis) + +#endif /* USE_GL */ diff --git a/hacks/glx/atlantis.h b/hacks/glx/atlantis.h new file mode 100644 index 00000000..4177eeff --- /dev/null +++ b/hacks/glx/atlantis.h @@ -0,0 +1,129 @@ +/* atlantis --- Shows moving 3D sea animals */ + +/* Copyright (c) E. Lassauge, 1998. */ + +/* + * Permission to use, copy, modify, and distribute this software and its + * documentation for any purpose and without fee is hereby granted, + * provided that the above copyright notice appear in all copies and that + * both that copyright notice and this permission notice appear in + * supporting documentation. + * + * This file is provided AS IS with no warranties of any kind. The author + * shall have no liability with respect to the infringement of copyrights, + * trade secrets or any patents by this file or any part thereof. In no + * event will the author be liable for any lost revenue or profits or + * other special, indirect and consequential damages. + * + * The original code for this mode was written by Mark J. Kilgard + * as a demo for openGL programming. + * + * Porting it to xlock was possible by comparing the original Mesa's morph3d + * demo with it's ported version to xlock, so thanks for Marcelo F. Vianna + * (look at morph3d.c) for his indirect help. + * + * Thanks goes also to Brian Paul for making it possible and inexpensive + * to use OpenGL at home. + * + * My e-mail address is lassauge@users.sourceforge.net + * + * Eric Lassauge (May-13-1998) + * + */ + +/** + * (c) Copyright 1993, 1994, Silicon Graphics, Inc. + * ALL RIGHTS RESERVED + * Permission to use, copy, modify, and distribute this software for + * any purpose and without fee is hereby granted, provided that the above + * copyright notice appear in all copies and that both the copyright notice + * and this permission notice appear in supporting documentation, and that + * the name of Silicon Graphics, Inc. not be used in advertising + * or publicity pertaining to distribution of the software without specific, + * written prior permission. + * + * THE MATERIAL EMBODIED ON THIS SOFTWARE IS PROVIDED TO YOU "AS-IS" + * AND WITHOUT WARRANTY OF ANY KIND, EXPRESS, IMPLIED OR OTHERWISE, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTY OF MERCHANTABILITY OR + * FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL SILICON + * GRAPHICS, INC. BE LIABLE TO YOU OR ANYONE ELSE FOR ANY DIRECT, + * SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY + * KIND, OR ANY DAMAGES WHATSOEVER, INCLUDING WITHOUT LIMITATION, + * LOSS OF PROFIT, LOSS OF USE, SAVINGS OR REVENUE, OR THE CLAIMS OF + * THIRD PARTIES, WHETHER OR NOT SILICON GRAPHICS, INC. HAS BEEN + * ADVISED OF THE POSSIBILITY OF SUCH LOSS, HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE + * POSSESSION, USE OR PERFORMANCE OF THIS SOFTWARE. + * + * US Government Users Restricted Rights + * Use, duplication, or disclosure by the Government is subject to + * restrictions set forth in FAR 52.227.19(c)(2) or subparagraph + * (c)(1)(ii) of the Rights in Technical Data and Computer Software + * clause at DFARS 252.227-7013 and/or in similar or successor + * clauses in the FAR or the DOD or NASA FAR Supplement. + * Unpublished-- rights reserved under the copyright laws of the + * United States. Contractor/manufacturer is Silicon Graphics, + * Inc., 2011 N. Shoreline Blvd., Mountain View, CA 94039-7311. + * + * OpenGL(TM) is a trademark of Silicon Graphics, Inc. + */ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif /* HAVE_CONFIG_H */ + +#ifdef STANDALONE +# include +# include "screenhackI.h" +# ifndef HAVE_COCOA +# include +# include +# endif +#else +# include "xlock.h" +#endif + +#ifdef HAVE_JWZGLES +# include "jwzgles.h" +#endif /* HAVE_JWZGLES */ + +#define RAD 57.295 +#define RRAD 0.01745 + +/* default values */ +#define NUM_SHARKS 4 +#define SHARKSPEED 100 +#define SHARKSIZE 6000 + +typedef struct _fishRec { + float x, y, z, phi, theta, psi, v; + float xt, yt, zt; + float htail, vtail; + float dtheta; + int spurt, attack; + int sign; +} fishRec; + +typedef struct { + GLint WinH, WinW; + GLXContext *glx_context; + int num_sharks; + float sharkspeed, whalespeed; + int sharksize; + int wire; + Bool whaledir; + fishRec *sharks; + fishRec momWhale; + fishRec babyWhale; + fishRec dolph; + + XImage *texture; /* water distortion overlay bits */ +} atlantisstruct; + +extern void FishTransform(fishRec *); +extern void WhalePilot(fishRec *, float, Bool); +extern void SharkPilot(fishRec *, float); +extern void SharkMiss(atlantisstruct *, int); +extern void DrawWhale(fishRec *, int); +extern void DrawShark(fishRec *, int); +extern void DrawDolphin(fishRec *, int); diff --git a/hacks/glx/atlantis.man b/hacks/glx/atlantis.man new file mode 100644 index 00000000..0c2df5ab --- /dev/null +++ b/hacks/glx/atlantis.man @@ -0,0 +1,78 @@ +.TH XScreenSaver 1 "" "X Version 11" +.SH NAME +atlantis - draw swimming sharks, whales, and dolphins. +.SH SYNOPSIS +.B atlantis +[\-display \fIhost:display.screen\fP] +[\-visual \fIvisual\fP] +[\-window] +[\-root] +[\-whalespeed \fInumber\fP] +[\-delay \fInumber\fP] +[\-size \fInumber\fP] +[\-count \fInumber\fP] +[\-no-texture] +[\-gradient] +[\-wireframe] +[\-fps] +.SH DESCRIPTION +This is xfishtank writ large: a GL animation of a number of sharks, +dolphins, and whales. The swimming motions are great. +.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 \-whalespeed \fInumber\fP +Whale Speed. 0 - 1000. Default: 250. +.TP 8 +.B \-cycles \fInumber\fP +Shark Speed. Default: 100. +.TP 8 +.B \-size \fInumber\fP +Shark Proximity. 100 - 10000. Default: 6000. +.TP 8 +.B \-count \fInumber\fP +Number of Sharks. 0 - 20. Default: 4. +.TP 8 +.B \-texture | \-no-texture +Whether to show shimmering water. +.TP 8 +.B \-gradient +Whether to draw a gradient on the background, making it darker at the bottom. +.TP 8 +.B \-wireframe +Render in wireframe instead of solid. +.TP 8 +.B \-fps +Display the current frame rate, CPU load, and polygon count. +.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 2002 by Mark Kilgard. 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 +Mark Kilgard. + diff --git a/hacks/glx/atunnel.c b/hacks/glx/atunnel.c new file mode 100644 index 00000000..13b8399b --- /dev/null +++ b/hacks/glx/atunnel.c @@ -0,0 +1,330 @@ +/* -*- Mode: C; tab-width: 4 -*- */ +/* atunnel --- OpenGL Advanced Tunnel Screensaver */ + +#if 0 +static const char sccsid[] = "@(#)atunnel.c 5.13 2004/05/25 xlockmore"; +#endif + +/* Copyright (c) E. Lassauge, 2003-2004. */ + +/* + * Permission to use, copy, modify, and distribute this software and its + * documentation for any purpose and without fee is hereby granted, + * provided that the above copyright notice appear in all copies and that + * both that copyright notice and this permission notice appear in + * supporting documentation. + * + * This file is provided AS IS with no warranties of any kind. The author + * shall have no liability with respect to the infringement of copyrights, + * trade secrets or any patents by this file or any part thereof. In no + * event will the author be liable for any lost revenue or profits or + * other special, indirect and consequential damages. + * + * The original code for this mode was written by Roman Podobedov + * Email: romka@ut.ee + * WEB: http://romka.demonews.com + * + * Eric Lassauge (May-25-2004) + * http://lassauge.free.fr/linux.html + * + * REVISION HISTORY: + * + * E.Lassauge - 25-May-2004: + * - added more texture ! + * E.Lassauge - 16-Mar-2002: + * - created based on the Roman demo. + * - deleted all external file stuff to use xpm textures and + * hardcoded path point values. + * + */ + +#ifdef STANDALONE /* xscreensaver mode */ +#define DEFAULTS "*delay: 10000 \n" \ + "*showFPS: False \n" \ + +# define refresh_atunnel 0 +# define atunnel_handle_event 0 +#define MODE_atunnel +# include "xlockmore.h" /* from the xscreensaver distribution */ +#else /* !STANDALONE */ +# include "xlock.h" /* from the xlockmore distribution */ +#endif /* !STANDALONE */ + +#ifdef MODE_atunnel /* whole file */ + +#include +#include +#include +#include "tunnel_draw.h" + +#if defined( USE_XPM ) || defined( USE_XPMINC ) || defined(STANDALONE) +/* USE_XPM & USE_XPMINC in xlock mode ; STANDALONE in xscreensaver mode */ +#include "xpm-ximage.h" +#define I_HAVE_XPM + +#ifdef STANDALONE +#include "../images/tunnel0.xpm" +#include "../images/tunnel1.xpm" +#include "../images/tunnel2.xpm" +#include "../images/tunnel3.xpm" +#include "../images/tunnel4.xpm" +#include "../images/tunnel5.xpm" +#else /* !STANDALONE */ +#include "pixmaps/tunnel0.xpm" +#include "pixmaps/tunnel1.xpm" +#include "pixmaps/tunnel2.xpm" +#include "pixmaps/tunnel3.xpm" +#include "pixmaps/tunnel4.xpm" +#include "pixmaps/tunnel5.xpm" +#endif /* !STANDALONE */ +#endif /* HAVE_XPM */ + + +#undef countof +#define countof(x) (sizeof((x))/sizeof((*x))) + +#define DEF_LIGHT "True" +#define DEF_WIRE "False" +#define DEF_TEXTURE "True" + +static Bool do_light; +static Bool do_wire; +static Bool do_texture; + +static XrmOptionDescRec opts[] = { + {"-light", ".atunnel.light", XrmoptionNoArg, "true" }, + {"+light", ".atunnel.light", XrmoptionNoArg, "false" }, + {"-wireframe",".atunnel.wire", XrmoptionNoArg, "true" }, + {"+wireframe",".atunnel.wire", XrmoptionNoArg, "false" }, + {"-texture", ".atunnel.texture", XrmoptionNoArg, "true" }, + {"+texture", ".atunnel.texture", XrmoptionNoArg, "false" }, +}; + +static argtype vars[] = { + {&do_light, "light", "Light", DEF_LIGHT, t_Bool}, + {&do_wire, "wire", "Wire", DEF_WIRE, t_Bool}, + {&do_texture, "texture", "Texture", DEF_TEXTURE, t_Bool}, +}; + +static OptionStruct desc[] = +{ + {"-/+ light", "whether to do enable lighting (slower)"}, + {"-/+ wire", "whether to do use wireframe instead of filled (faster)"}, + {"-/+ texture", "whether to apply a texture (slower)"}, +}; + +ENTRYPOINT ModeSpecOpt atunnel_opts = {countof(opts), opts, countof(vars), vars, desc}; + +#ifdef USE_MODULES +ModStruct atunnel_description = +{"atunnel", "init_atunnel", "draw_atunnel", "release_atunnel", + "draw_atunnel", "init_atunnel", NULL, &atunnel_opts, + 1000, 1, 2, 1, 4, 1.0, "", + "OpenGL advanced tunnel screensaver", 0, NULL}; +#endif + +/* structure for holding the screensaver data */ +typedef struct { + int screen_width, screen_height; + GLXContext *glx_context; + Window window; + struct tunnel_state *ts; + GLuint texture[MAX_TEXTURE]; /* texture id: GL world */ +} atunnelstruct; + +static atunnelstruct *Atunnel = NULL; + +/*=================== Load Texture =========================================*/ +static void LoadTexture(ModeInfo * mi, char **fn, int t_num) +{ +#if defined( I_HAVE_XPM ) + atunnelstruct *sa = &Atunnel[MI_SCREEN(mi)]; + XImage *teximage; /* Texture data */ + + if ((teximage = xpm_to_ximage(MI_DISPLAY(mi), MI_VISUAL(mi), + MI_COLORMAP(mi), fn)) == None) { + (void) fprintf(stderr, "Error reading the texture.\n"); + glDeleteTextures(1, &sa->texture[t_num]); + do_texture = False; +#ifdef STANDALONE + exit(0); +#else + return; +#endif + } + +#ifdef HAVE_GLBINDTEXTURE + glBindTexture(GL_TEXTURE_2D, sa->texture[t_num]); +#endif /* HAVE_GLBINDTEXTURE */ + glPixelStorei(GL_UNPACK_ALIGNMENT, 4); + clear_gl_error(); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, teximage->width, teximage->height, + 0, GL_RGBA, + /* GL_UNSIGNED_BYTE, */ + GL_UNSIGNED_INT_8_8_8_8_REV, + teximage->data); + check_gl_error("texture"); + + /* Texture parameters, LINEAR scaling for better texture quality */ + glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + + XDestroyImage(teximage); +#else /* !I_HAVE_XPM */ + do_texture = False; +#endif /* !I_HAVE_XPM */ +} + +/*=================== Main Initialization ==================================*/ +static void Init(ModeInfo * mi) +{ + atunnelstruct *sa = &Atunnel[MI_SCREEN(mi)]; + GLfloat light_ambient[] = {1.0, 1.0, 1.0, 1.0}; + GLfloat light_diffuse[] = {1.0, 1.0, 1.0, 1.0}; + GLfloat light_specular[] = {1.0, 1.0, 1.0, 1.0}; + GLfloat light_position[] = {0.0, 0.0, 1.0, 0.0}; + GLfloat fogColor[4] = {0.8, 0.8, 0.8, 1.0}; + + if (do_texture) + { + glGenTextures(MAX_TEXTURE, sa->texture); + LoadTexture(mi, texture0,0); + LoadTexture(mi, texture1,1); + LoadTexture(mi, texture2,2); + LoadTexture(mi, texture3,3); + LoadTexture(mi, texture4,4); + LoadTexture(mi, texture5,5); + glEnable(GL_TEXTURE_2D); + } + sa->ts = atunnel_InitTunnel(); + + /* Set lighting parameters */ + if (do_light) + { + glLightfv(GL_LIGHT0, GL_AMBIENT, light_ambient); + glLightfv(GL_LIGHT0, GL_DIFFUSE, light_diffuse); + glLightfv(GL_LIGHT0, GL_SPECULAR, light_specular); + glLightfv(GL_LIGHT0, GL_POSITION, light_position); + + /* Enable light 0 */ + glEnable(GL_LIGHT0); + glDepthFunc(GL_LESS); + + glEnable(GL_LIGHTING); + } + +# ifdef HAVE_JWZGLES /* #### glPolygonMode other than GL_FILL unimplemented */ + do_wire = 0; +# endif + + if (do_wire) { + glDisable(GL_NORMALIZE); + glDisable(GL_CULL_FACE); + glDisable(GL_DEPTH_TEST); + glDisable(GL_TEXTURE_2D); + glPolygonMode(GL_FRONT,GL_LINE); + glPolygonMode(GL_BACK,GL_LINE); + } + else + { + glEnable(GL_DEPTH_TEST); + glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); + + /* Enable fog */ + glFogi(GL_FOG_MODE, GL_EXP); + glFogfv(GL_FOG_COLOR, fogColor); + glFogf(GL_FOG_DENSITY, 0.3); + glEnable(GL_FOG); + + /* Cull face */ + glCullFace(GL_FRONT); + glEnable(GL_CULL_FACE); + } + + glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST); +} + + +/* Standard reshape function */ +ENTRYPOINT void +reshape_atunnel(ModeInfo *mi, int width, int height) +{ + float a; + + glViewport(0, 0, width, height); + glMatrixMode(GL_PROJECTION); + glLoadIdentity(); + a = (float)width/(float)height; + glFrustum(-0.1*a, 0.1*a, -0.1, 0.1, 0.1, 10); + glMatrixMode(GL_MODELVIEW); +} + +/* draw the screensaver once */ +ENTRYPOINT void draw_atunnel(ModeInfo * mi) +{ + atunnelstruct *sa = &Atunnel[MI_SCREEN(mi)]; + Display *display = MI_DISPLAY(mi); + Window window = MI_WINDOW(mi); + + if (!sa->glx_context) + return; + + glXMakeCurrent(display, window, *(sa->glx_context)); + + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + + glLoadIdentity(); + + atunnel_DrawTunnel(sa->ts, do_texture, do_light, sa->texture); + atunnel_SplashScreen(sa->ts, do_wire, do_texture, do_light); + + glFlush(); + /* manage framerate display */ + if (MI_IS_FPS(mi)) do_fps (mi); + glXSwapBuffers(display, window); + +} + + +/* xscreensaver initialization routine */ +ENTRYPOINT void init_atunnel(ModeInfo * mi) +{ + int screen = MI_SCREEN(mi); + atunnelstruct *sa; + + if (Atunnel == NULL) { + if ((Atunnel = (atunnelstruct *) calloc(MI_NUM_SCREENS(mi), sizeof (atunnelstruct))) == NULL) + return; + } + sa = &Atunnel[screen]; + + sa->window = MI_WINDOW(mi); + if ((sa->glx_context = init_GL(mi)) != NULL) { + reshape_atunnel(mi, MI_WIDTH(mi), MI_HEIGHT(mi)); + Init(mi); + } else { + MI_CLEARWINDOW(mi); + } + +} + +/* all sorts of nice cleanup code should go here! */ +ENTRYPOINT void release_atunnel(ModeInfo * mi) +{ +#if 0 + int screen; + if (Atunnel != NULL) { + for (screen = 0; screen < MI_NUM_SCREENS(mi); screen++) { + atunnelstruct *sa = &Atunnel[screen]; + FreeTunnel(sa->ts); + } + (void) free((void *) Atunnel); + Atunnel = NULL; + } + FreeAllGL(mi); +#endif +} + +XSCREENSAVER_MODULE ("Atunnel", atunnel) + +#endif diff --git a/hacks/glx/atunnel.man b/hacks/glx/atunnel.man new file mode 100644 index 00000000..dc195829 --- /dev/null +++ b/hacks/glx/atunnel.man @@ -0,0 +1,83 @@ +.de EX \"Begin example +.ne 5 +.if n .sp 1 +.if t .sp .5 +.nf +.in +.5i +.. +.de EE +.fi +.in -.5i +.if n .sp 1 +.if t .sp .5 +.. +.TH XScreenSaver 1 "12-Feb-03" "X Version 11" +.SH NAME +atunnel - hypnotic GL tunnel journey +.SH SYNOPSIS +.B sballs +[\-display \fIhost:display.screen\fP] [\-window] [\-root] +[\-visual \fIvisual\fP] [\-delay \fImicroseconds\fP] +[\-light] [\-no-light] +[\-wire] [\-no-wire] +[\-texture] [\-no-texture] +[\-fps] +.SH DESCRIPTION +The \fIatunnel\fP program draws an animation of a journey in a GL tunnel. +.SH OPTIONS +.I sballs +accepts the following options: +.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 \-install +Install a private colormap for the window. +.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 \-fps +Display the current frame rate, CPU load, and polygon count. +.TP 8 +.B \-texture +Show a textured tunnel. This is the default. +.TP 8 +.B \-no\-texture +Disables texturing the animation. +.TP 8 +.B \-wire +Draw a wireframe rendition of the tunnel. +.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 2003 by Eric Lassauge. +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. + +The original code for this mode was written by +Roman Podobedov +and can be found at http://romka.demonews.com + +.SH AUTHOR +Roman Podobedov +Eric Lassauge diff --git a/hacks/glx/b_draw.c b/hacks/glx/b_draw.c new file mode 100644 index 00000000..977efbe9 --- /dev/null +++ b/hacks/glx/b_draw.c @@ -0,0 +1,239 @@ +#if 0 +static const char sccsid[] = "@(#)b_draw.c 4.11 98/06/16 xlockmore"; +#endif + +/*- + * BUBBLE3D (C) 1998 Richard W.M. Jones. + * b_draw.c: This code creates new bubbles, manages them and controls + * them as they are drawn on the screen. + */ + +#include "bubble3d.h" + +typedef struct draw_context { + /* The list of bubbles currently on the screen. */ + void **bubble_list; + int nr_bubbles; + + /* When was the last time we created a new bubble? */ + int bubble_count; + + glb_data *d; + +} draw_context; + +void * +glb_draw_init(void) +{ + draw_context *c; + + GLfloat mat_specular[] = + {1, 1, 1, 1}; + GLfloat mat_emission[] = + {0, 0, 0, 1}; + GLfloat mat_shininess[] = + {100}; + GLfloat ambient[] = + {0.5, 0.5, 0.5, 1.0}; + GLfloat light_position[][4] = + { + {0, -1, 0, 0}, + {1, 1, 0, 0}, + {-1, 0, 1, 0}}; + GLfloat light_diffuse[][4] = + { + {1, 1, 1, 1}, + {1, 1, 1, 1}, + {1, 1, 1, 1}}; + GLfloat light_specular[][4] = + { + {1, 1, 1, 1}, + {1, 1, 1, 1}, + {1, 1, 1, 1}}; + + /* Initialize the context. */ + c = (struct draw_context *) malloc(sizeof (struct draw_context)); + + if (c == 0) + return 0; + c->bubble_list = 0; + c->nr_bubbles = 0; + c->bubble_count = glb_config.create_bubbles_every; + + /* Do some GL initialization. */ + glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, glb_config.bubble_colour); + glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, mat_specular); + glMaterialfv(GL_FRONT_AND_BACK, GL_EMISSION, mat_emission); + glMaterialfv(GL_FRONT_AND_BACK, GL_SHININESS, mat_shininess); + + if (glb_config.transparent_p) + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + + glEnable(GL_LIGHTING); + glEnable(GL_LIGHT0); + glEnable(GL_LIGHT1); + glEnable(GL_LIGHT2); + + if (glb_config.transparent_p) + glEnable(GL_BLEND); + else + glEnable(GL_DEPTH_TEST); + + glEnable(GL_AUTO_NORMAL); + glEnable(GL_NORMALIZE); + + if (glb_config.transparent_p) + glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, GL_TRUE); + + glLightModelfv(GL_LIGHT_MODEL_AMBIENT, ambient); + glLightfv(GL_LIGHT0, GL_POSITION, light_position[0]); + glLightfv(GL_LIGHT0, GL_DIFFUSE, light_diffuse[0]); + glLightfv(GL_LIGHT0, GL_SPECULAR, light_specular[0]); + glLightfv(GL_LIGHT1, GL_POSITION, light_position[1]); + glLightfv(GL_LIGHT1, GL_DIFFUSE, light_diffuse[1]); + glLightfv(GL_LIGHT1, GL_SPECULAR, light_specular[1]); + glLightfv(GL_LIGHT2, GL_POSITION, light_position[2]); + glLightfv(GL_LIGHT2, GL_DIFFUSE, light_diffuse[2]); + glLightfv(GL_LIGHT2, GL_SPECULAR, light_specular[2]); + + c->d = glb_sphere_init(); + + return c; +} + +static void +delete_bubble(draw_context * c, int j) +{ + int i; + + glb_bubble_delete(c->bubble_list[j]); + + for (i = j; i < c->nr_bubbles - 1; ++i) + c->bubble_list[i] = c->bubble_list[i + 1]; + + c->nr_bubbles--; +} + +void +glb_draw_end(void *cc) +{ + draw_context *c = (draw_context *) cc; + int i; + + for (i = 0; i < c->nr_bubbles; ++i) { + delete_bubble(c, i); + i--; + } + + glb_sphere_end (c->d); + + (void) free((void *) c->bubble_list); + (void) free((void *) c); +} + +static int +create_new_bubbles(draw_context * c) +{ + int n, i; + double r = glb_drand(); + GLfloat size, speed, scale_incr, x, y, z; + void *b[4]; + void **old_bubble_list; + + /* How many bubbles to make? */ + if (r < glb_config.p_bubble_group[0]) + n = 1; + else if (r < glb_config.p_bubble_group[1]) + n = 2; + else if (r < glb_config.p_bubble_group[2]) + n = 3; + else + n = 4; + + /* Initial position of top-most bubble in group. */ + x = glb_drand() * 4 - 2; + y = glb_config.screen_bottom; + z = glb_drand() * 2 - 2; + + /* What size? */ + size = glb_config.min_size + + glb_drand() * (glb_config.max_size - glb_config.min_size); + + /* What speed? */ + speed = glb_config.min_speed + + glb_drand() * (glb_config.max_speed - glb_config.min_speed); + + /* Work out the scaling increment. Bubbles should increase by scale_factor + * as they go from bottom to top of screen. + */ + scale_incr = (size * glb_config.scale_factor - size) + / ((glb_config.screen_top - glb_config.screen_bottom) / speed); + + /* Create the bubble(s). */ + for (i = 0; i < n; ++i) { + if ((b[i] = glb_bubble_new(c->d, x, y, z, size, speed, scale_incr)) == 0) { + /* Out of memory - recover. */ + i--; + while (i >= 0) + glb_bubble_delete(b[i]); + return 0; + } + /* Create the next bubble below the last bubble. */ + y -= size * 3; + } + + /* Add the bubbles to the list. */ + c->nr_bubbles += n; + old_bubble_list = c->bubble_list; + if (c->bubble_list == 0) { + c->bubble_list = (void **) malloc(c->nr_bubbles * sizeof (void *)); + } else { + c->bubble_list = (void **) realloc(c->bubble_list, + c->nr_bubbles * sizeof (void *)); + } + + if (c->bubble_list == 0) { + /* Out of memory - recover. */ + for (i = 0; i < n; ++i) + glb_bubble_delete(b[i]); + c->bubble_list = old_bubble_list; + c->nr_bubbles -= n; + return 0; + } + for (i = 0; i < n; ++i) + c->bubble_list[c->nr_bubbles - i - 1] = b[i]; + + return 1; +} + +void +glb_draw_step(void *cc) +{ + draw_context *c = (draw_context *) cc; + int i; + + /* Consider creating a new bubble or bubbles. */ + if (c->nr_bubbles < glb_config.max_bubbles && + c->bubble_count++ > glb_config.create_bubbles_every) { + if (create_new_bubbles(c)) + c->bubble_count = 0; + } + /* Clear the display. */ + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + + /* XXX Draw the background here ... */ + + /* Draw all the bubbles on the display. */ + for (i = 0; i < c->nr_bubbles; ++i) { + void *b = c->bubble_list[i]; + + glb_bubble_step(b); + glb_bubble_draw(c->d, b); + + /* Has the bubble reached the top of the screen? */ + if (glb_bubble_get_y(b) >= glb_config.screen_top) { + delete_bubble(c, i); + i--; + } + } +} diff --git a/hacks/glx/b_lockglue.c b/hacks/glx/b_lockglue.c new file mode 100644 index 00000000..f322be2c --- /dev/null +++ b/hacks/glx/b_lockglue.c @@ -0,0 +1,237 @@ +#if 0 +static const char sccsid[] = "@(#)b_lockglue.c 4.11 98/06/16 xlockmore"; +#endif + +/*- + * BUBBLE3D (C) 1998 Richard W.M. Jones. + * b_lockglue.c: Glue to make this all work with xlockmore. + */ + +#include "bubble3d.h" + +/* XXX This lot should eventually be made configurable using the + * options stuff below. + */ +struct glb_config glb_config = +{ + 0, /* transparent_p */ +#if GLB_SLOW_GL + 2, /* subdivision_depth */ +#else + 3, /* subdivision_depth */ +#endif + 5, /* nr_nudge_axes */ + 0.01, /* nudge_angle_factor */ + 0.20, /* nudge_factor */ + 0.1, /* rotation_factor */ + 8, /* create_bubbles_every */ + 8, /* max_bubbles */ + {0.7, 0.8, 0.9, 1.0}, /* p_bubble_group */ + 0.5, /* max_size */ + 0.1, /* min_size */ + 0.03, /* max_speed */ + 0.005, /* min_speed */ + 1.5, /* scale_factor */ + -4, /* screen_bottom */ + 4, /* screen_top */ + {0.0, 0.0, 0.7, 0.3} /* bubble_colour */ +}; + +#ifdef STANDALONE +# define DEFAULTS "*delay: 10000 \n" \ + "*showFPS: False \n" + +# define refresh_bubble3d 0 +# define bubble3d_handle_event 0 +#include "xlockmore.h" +#else +#include "xlock.h" +#include "vis.h" +#endif + +#ifdef USE_GL + + +#define DEF_TRANSPARENT "True" +#define DEF_COLOR "random" + +static Bool transparent_p; +static char *bubble_color_str; + +#undef countof +#define countof(x) (sizeof((x))/sizeof((*x))) + +static XrmOptionDescRec opts[] = { + { "-transparent", ".transparent", XrmoptionNoArg, "True" }, + { "+transparent", ".transparent", XrmoptionNoArg, "False" }, + { "-color", ".bubble3d.bubblecolor", XrmoptionSepArg, 0 }, +}; + +static argtype vars[] = { + {&transparent_p, "transparent", "Transparent", DEF_TRANSPARENT, t_Bool}, + {&bubble_color_str, "bubblecolor", "BubbleColor", DEF_COLOR, t_String}, +}; + +ENTRYPOINT ModeSpecOpt bubble3d_opts = {countof(opts), opts, countof(vars), vars, NULL}; + +#ifdef USE_MODULES +ModStruct bubbles3d_description = +{"bubbles3d", + "init_bubble3d", + "draw_bubble3d", + "release_bubble3d", + "change_bubble3d", + "init_bubble3d", + NULL, + &bubble3d_opts, + 1000, 1, 2, 1, 64, 1.0, "", + "Richard Jones's GL bubbles", + 0, + NULL +}; + +#endif /* USE_MODULES */ + +struct context { + GLXContext *glx_context; + void *draw_context; +}; + +static struct context *contexts = 0; + +static void +parse_color (ModeInfo *mi, const char *name, const char *s, GLfloat *a) +{ + XColor c; + + if (! XParseColor (MI_DISPLAY(mi), MI_COLORMAP(mi), s, &c)) + { + fprintf (stderr, "%s: can't parse %s color %s", progname, name, s); + exit (1); + } + a[0] = c.red / 65536.0; + a[1] = c.green / 65536.0; + a[2] = c.blue / 65536.0; +} + +static void +init_colors(ModeInfo *mi) +{ + if (strncasecmp(bubble_color_str, "auto", strlen("auto")) == 0) { + glb_config.bubble_colour[0] = ((float) (NRAND(100)) / 100.0); + glb_config.bubble_colour[1] = ((float) (NRAND(100)) / 100.0); + /* I keep more blue */ + glb_config.bubble_colour[2] = ((float) (NRAND(50)) / 100.0) + 0.50; + } else if (strncasecmp(bubble_color_str, "random", strlen("random")) == 0) { + glb_config.bubble_colour[0] = -1.0; + } else { + parse_color(mi, "bubble", bubble_color_str, glb_config.bubble_colour); + } +} + +static void +init(struct context *c) +{ + glb_config.transparent_p = transparent_p; + glb_sphere_init(); + c->draw_context = glb_draw_init(); +} + +ENTRYPOINT void +reshape_bubble3d(ModeInfo *mi, int w, int h) +{ + glViewport(0, 0, (GLsizei) w, (GLsizei) h); + glMatrixMode(GL_PROJECTION); + glLoadIdentity(); + gluPerspective(45, (GLdouble) w / (GLdouble) h, 3, 8); + glMatrixMode(GL_MODELVIEW); + glLoadIdentity(); + glTranslatef(0, 0, -5); +} + +static void +do_display(struct context *c) +{ + glb_draw_step(c->draw_context); +} + +ENTRYPOINT void +init_bubble3d(ModeInfo * mi) +{ + Display *display = MI_DISPLAY(mi); + Window window = MI_WINDOW(mi); + int screen = MI_SCREEN(mi); + struct context *c; + + if (contexts == 0) { + contexts = (struct context *) calloc(sizeof (struct context), MI_NUM_SCREENS(mi)); + + if (contexts == 0) + return; + } + c = &contexts[screen]; + c->glx_context = init_GL(mi); + init_colors(mi); + if (c->glx_context != 0) { + init(c); + reshape_bubble3d(mi, MI_WIDTH(mi), MI_HEIGHT(mi)); + do_display(c); + glFinish(); + glXSwapBuffers(display, window); + } else + MI_CLEARWINDOW(mi); +} + +ENTRYPOINT void +draw_bubble3d(ModeInfo * mi) +{ + struct context *c = &contexts[MI_SCREEN(mi)]; + Display *display = MI_DISPLAY(mi); + Window window = MI_WINDOW(mi); + + MI_IS_DRAWN(mi) = True; + + if (!c->glx_context) + return; + + glXMakeCurrent(display, window, *(c->glx_context)); + + glb_config.polygon_count = 0; + glPushMatrix(); + glRotatef(current_device_rotation(), 0, 0, 1); + do_display(c); + glPopMatrix(); + mi->polygon_count = glb_config.polygon_count; + + if (mi->fps_p) do_fps (mi); + glFinish(); + glXSwapBuffers(display, window); +} + +#ifndef STANDALONE +ENTRYPOINT void +change_bubble3d(ModeInfo * mi) +{ + /* nothing */ +} +#endif /* !STANDALONE */ + +ENTRYPOINT void +release_bubble3d(ModeInfo * mi) +{ + if (contexts) { + int screen; + for (screen = 0; screen < MI_NUM_SCREENS(mi); screen++) { + struct context *c = &contexts[screen]; + if (c->draw_context) + glb_draw_end(c->draw_context); + } + free (contexts); + contexts = 0; + } + FreeAllGL(mi); +} + +XSCREENSAVER_MODULE ("Bubble3D", bubble3d) + +#endif /* USE_GL */ diff --git a/hacks/glx/b_sphere.c b/hacks/glx/b_sphere.c new file mode 100644 index 00000000..78be3924 --- /dev/null +++ b/hacks/glx/b_sphere.c @@ -0,0 +1,219 @@ +#if 0 +static const char sccsid[] = "@(#)b_sphere.c 4.11 98/06/16 xlockmore"; +#endif + +/*- + * BUBBLE3D (C) 1998 Richard W.M. Jones. + * b_sphere.c: Create a list of vertices and triangles in a + * normalized sphere, which is then later used as the basic shape + * for all bubbles. This code is run once when the program starts + * up. + */ + +#include "bubble3d.h" + +typedef glb_vertex vertex; +typedef glb_triangle triangle; + +struct glb_data { + + /* The list of vertices created. */ + vertex *vertices; + int nr_vertices, nr_vertices_allocated; + + /* The list of triangles created. */ + triangle *triangles; + int nr_triangles, nr_triangles_allocated; +}; + + +#define EPSILON GLB_VERTICES_EPSILON + +/* Should be taken care of already... but just in case */ +#if !defined( __GNUC__ ) && !defined(__cplusplus) && !defined(c_plusplus) +#undef inline +#define inline /* */ +#endif +static inline int +close_enough(const GLfloat * v1, const GLfloat * v2) +{ + return fabs((double) (v1[0] - v2[0])) <= EPSILON && + fabs((double) (v1[1] - v2[1])) <= EPSILON && + fabs((double) (v1[2] - v2[2])) <= EPSILON; +} + +#define INCR(n) ((n == 0) ? (n = 1) : (n *= 2)) +#define INCR_ALLOCATION(a, n, t) (a = (t *) realloc (a, INCR (n) * sizeof (t))) + +static inline GLuint +save_vertex(glb_data *d, const GLfloat * v) +{ + int i; + + /* Inefficient, but we only do this a few times. Check to see if there's + * an existing vertex which is `close enough' to this one. + */ + for (i = 0; i < d->nr_vertices; ++i) + if (close_enough(v, d->vertices[i])) + return i; + + if (d->nr_vertices_allocated <= d->nr_vertices) { + if (d->vertices == 0) { + d->vertices = (vertex *) malloc(INCR(d->nr_vertices_allocated) * sizeof (vertex)); + } else { + INCR_ALLOCATION(d->vertices, d->nr_vertices_allocated, vertex); + } + } + d->vertices[d->nr_vertices][0] = v[0]; + d->vertices[d->nr_vertices][1] = v[1]; + d->vertices[d->nr_vertices][2] = v[2]; + return d->nr_vertices++; +} + +static inline GLuint +save_triangle(glb_data *d, GLuint v1, GLuint v2, GLuint v3) +{ + if (d->nr_triangles_allocated <= d->nr_triangles) { + if (d->triangles == 0) { + d->triangles = (triangle *) malloc(INCR(d->nr_triangles_allocated) * sizeof (triangle)); + } else { + INCR_ALLOCATION(d->triangles, d->nr_triangles_allocated, triangle); + } + } + d->triangles[d->nr_triangles][0] = v1; + d->triangles[d->nr_triangles][1] = v2; + d->triangles[d->nr_triangles][2] = v3; + return d->nr_triangles++; +} + +static inline void +normalize(GLfloat v[3]) +{ + GLfloat d = (GLfloat) sqrt((double) (v[0] * v[0] + v[1] * v[1] + v[2] * v[2])); + + if (d != 0) { + v[0] /= d; + v[1] /= d; + v[2] /= d; + } else { + v[0] = v[1] = v[2] = 0; + } +} + +static void +subdivide(glb_data *d, + const GLfloat * v1, GLuint vi1, + const GLfloat * v2, GLuint vi2, + const GLfloat * v3, GLuint vi3, + int depth) +{ + int i; + + if (depth == 0) { + save_triangle(d, vi1, vi2, vi3); + } else { + GLuint vi12, vi23, vi31; + GLfloat v12[3], v23[3], v31[3]; + + for (i = 0; i < 3; ++i) { + v12[i] = v1[i] + v2[i]; + v23[i] = v2[i] + v3[i]; + v31[i] = v3[i] + v1[i]; + } + normalize(v12); + vi12 = save_vertex(d, v12); + normalize(v23); + vi23 = save_vertex(d, v23); + normalize(v31); + vi31 = save_vertex(d, v31); + subdivide(d, v1, vi1, v12, vi12, v31, vi31, depth - 1); + subdivide(d, v2, vi2, v23, vi23, v12, vi12, depth - 1); + subdivide(d, v3, vi3, v31, vi31, v23, vi23, depth - 1); + subdivide(d, v12, vi12, v23, vi23, v31, vi31, depth - 1); + } +} + +#define ICO_X 0.525731112119133606 +#define ICO_Z 0.850650808352039932 + +static const GLfloat vdata[12][3] = +{ + {-ICO_X, 0, ICO_Z}, + {ICO_X, 0, ICO_Z}, + {-ICO_X, 0, -ICO_Z}, + {ICO_X, 0, -ICO_Z}, + {0, ICO_Z, ICO_X}, + {0, ICO_Z, -ICO_X}, + {0, -ICO_Z, ICO_X}, + {0, -ICO_Z, -ICO_X}, + {ICO_Z, ICO_X, 0}, + {-ICO_Z, ICO_X, 0}, + {ICO_Z, -ICO_X, 0}, + {-ICO_Z, -ICO_X, 0} +}; + +static const GLuint tindices[20][3] = +{ + {0, 4, 1}, + {0, 9, 4}, + {9, 5, 4}, + {4, 5, 8}, + {4, 8, 1}, + {8, 10, 1}, + {8, 3, 10}, + {5, 3, 8}, + {5, 2, 3}, + {2, 7, 3}, + {7, 10, 3}, + {7, 6, 10}, + {7, 11, 6}, + {11, 0, 6}, + {0, 1, 6}, + {6, 1, 10}, + {9, 0, 11}, + {9, 11, 2}, + {9, 2, 5}, + {7, 2, 11} +}; + +/* Public interface: Create the sphere. */ +glb_data * +glb_sphere_init(void) +{ + glb_data *d = (glb_data *) calloc (1, sizeof (*d)); + int i; + + for (i = 0; i < 20; ++i) { + subdivide(d, vdata[tindices[i][0]], save_vertex(d, vdata[tindices[i][0]]), + vdata[tindices[i][1]], save_vertex(d, vdata[tindices[i][1]]), + vdata[tindices[i][2]], save_vertex(d, vdata[tindices[i][2]]), + glb_config.subdivision_depth); + } + + return d; +} + +/* Return the vertices list. */ +glb_vertex * +glb_sphere_get_vertices(glb_data *d, int *nr_vertices_ptr) +{ + *nr_vertices_ptr = d->nr_vertices; + return d->vertices; +} + +/* Return the triangles list. */ +glb_triangle * +glb_sphere_get_triangles(glb_data *d, int *nr_triangles_ptr) +{ + *nr_triangles_ptr = d->nr_triangles; + return d->triangles; +} + +/* Free up memory. */ +void +glb_sphere_end(glb_data *d) +{ + (void) free((void *) d->vertices); + (void) free((void *) d->triangles); + free (d); +} diff --git a/hacks/glx/blinkbox.c b/hacks/glx/blinkbox.c new file mode 100644 index 00000000..2b3802c8 --- /dev/null +++ b/hacks/glx/blinkbox.c @@ -0,0 +1,597 @@ +/* blinkbox, Copyright (c) 2003 Jeremy English + * + * 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. + */ + +/* motion blur added March 2005 by John Boero + */ + +#define DEFAULTS "*delay: 30000 \n" \ + "*wireframe: False \n" \ + +# define refresh_ball 0 +# define release_ball 0 +# define ball_handle_event 0 +#undef countof +#define countof(x) (sizeof((x))/sizeof((*x))) + +#include "xlockmore.h" +#include "sphere.h" +#include + +#ifdef USE_GL /* whole file */ + +#define MAX_COUNT 20 +#define ALPHA_AMT 0.05 + +/* this should be between 1 and 8 */ +#define DEF_BOXSIZE "2" +#define DEF_DISSOLVE "False" +#define DEF_FADE "True" +#define DEF_BLUR "True" + + +typedef struct{ + GLfloat x,y,z; +} Tdpos; + +typedef struct{ + int hit; + Tdpos pos; + int counter; + GLfloat color[3]; + GLfloat rot[4]; + int des_count; + int alpha_count; +}Side; + +struct Bounding_box { + Tdpos top; + Tdpos bottom; +}; + +struct Ball { + GLfloat x; + GLfloat y; + GLfloat z; + int d; +}; + +struct bscale { + GLfloat wh; /*width Height*/ + GLfloat d; /*depth*/ +}; + +static const struct Bounding_box bbox = {{14,14,20},{-14,-14,-20}}; + +typedef struct { + GLXContext *glx_context; + + struct Ball ball; + + struct bscale bscale; + + Tdpos mo; /*motion*/ + Tdpos moh; /*hold motion value*/ + + Tdpos bpos; + + GLuint ballList; + GLuint boxList; + GLfloat des_amt; + + /*sides*/ + Side lside;/*Red*/ + Side rside;/*Green*/ + Side tside;/*Blue*/ + Side bside;/*Orange*/ + Side fside;/*Yellow*/ + Side aside;/*Purple*/ + Side *sp; + +} blinkboxstruct; + +static blinkboxstruct *blinkbox = (blinkboxstruct *) NULL; + + +/* lights */ +static const float LightDiffuse[]= { 1.0f, 1.0f, 1.0f, 1.0f }; +static const float LightPosition[]= { 20.0f, 100.0f, 20.0f, 1.0f }; + +static Bool do_dissolve; +static Bool do_fade; +static Bool do_blur; +static float bscale_wh; + +static XrmOptionDescRec opts[] = { + { "-boxsize", ".boxsize", XrmoptionSepArg, 0 }, + { "-dissolve", ".dissolve", XrmoptionNoArg, "True" }, + { "+dissolve", ".dissolve", XrmoptionNoArg, "False" }, + { "-fade", ".fade", XrmoptionNoArg, "True" }, + { "+fade", ".fade", XrmoptionNoArg, "False" }, + { "-blur", ".blur", XrmoptionNoArg, "True" }, + { "+blur", ".blur", XrmoptionNoArg, "False" } + +}; + +static argtype vars[] = { + {&bscale_wh, "boxsize", "Boxsize", DEF_BOXSIZE, t_Float}, + {&do_dissolve, "dissolve", "Dissolve", DEF_DISSOLVE, t_Bool}, + {&do_fade, "fade", "Fade", DEF_FADE, t_Bool}, + {&do_blur, "blur", "Blur", DEF_BLUR, t_Bool}, +}; + +ENTRYPOINT ModeSpecOpt ball_opts = {countof(opts), opts, countof(vars), vars, NULL}; + +static void +swap(GLfloat *a, GLfloat *b) +{ + GLfloat t = *a; + *a = *b; + *b = t; +} + +static float +get_rand(void) +{ + GLfloat j = 1+(random() % 2); + return (j); +} + +static void +swap_mov(GLfloat *a, GLfloat *b) +{ + int j; + swap(a,b); + j = get_rand(); + if (*a < 0) + *a = j * -1; + else + *a = j; +} + +static void +cp_b_pos(blinkboxstruct *bp, Tdpos *s_pos) +{ + s_pos->x = bp->ball.x; + s_pos->y = bp->ball.y; + s_pos->z = bp->ball.z; +} + +static void +hit_side(blinkboxstruct *bp) +{ + if ((bp->ball.x - bp->ball.d) <= bbox.bottom.x){ + bp->lside.hit = 1; + bp->lside.counter = MAX_COUNT; + bp->lside.des_count = 1; + bp->lside.alpha_count = 0; + cp_b_pos(bp, &bp->lside.pos); + swap_mov(&bp->mo.x,&bp->moh.x); + }else + if ((bp->ball.x + bp->ball.d) >= bbox.top.x){ + bp->rside.hit = 1; + bp->rside.counter = MAX_COUNT; + bp->rside.des_count = 1; + bp->rside.alpha_count = 0; + cp_b_pos(bp, &bp->rside.pos); + swap_mov(&bp->mo.x,&bp->moh.x); + } +} + +static void +hit_top_bottom(blinkboxstruct *bp) +{ + if ((bp->ball.y - bp->ball.d) <= bbox.bottom.y){ + bp->bside.hit = 1; + bp->bside.counter = MAX_COUNT; + bp->bside.des_count = 1; + bp->bside.alpha_count = 0; + cp_b_pos(bp, &bp->bside.pos); + swap_mov(&bp->mo.y,&bp->moh.y); + }else + if ((bp->ball.y + bp->ball.d) >= bbox.top.y){ + bp->tside.hit = 1; + bp->tside.counter = MAX_COUNT; + bp->tside.des_count = 1; + bp->tside.alpha_count = 0; + cp_b_pos(bp, &bp->tside.pos); + swap_mov(&bp->mo.y,&bp->moh.y); + } +} + +static void +hit_front_back(blinkboxstruct *bp) +{ + if ((bp->ball.z - bp->ball.d) <= bbox.bottom.z){ + bp->aside.hit = 1; + bp->aside.counter = MAX_COUNT; + bp->aside.des_count = 1; + bp->aside.alpha_count = 0; + cp_b_pos(bp, &bp->aside.pos); + swap_mov(&bp->mo.z,&bp->moh.z); + }else + if((bp->ball.z + bp->ball.d) >= bbox.top.z){ + bp->fside.hit = 1; + bp->fside.counter = MAX_COUNT; + bp->fside.des_count = 1; + bp->fside.alpha_count = 0; + cp_b_pos(bp, &bp->fside.pos); + swap_mov(&bp->mo.z,&bp->moh.z); + } +} + +ENTRYPOINT void +reshape_ball (ModeInfo *mi, int width, int height) +{ + GLfloat h = (GLfloat) height / (GLfloat) width; + + glViewport (0, 0, (GLint) width, (GLint) height); + glMatrixMode(GL_PROJECTION); + glLoadIdentity(); + gluPerspective (30.0, 1/h, 1.0, 100.0); + + glMatrixMode(GL_MODELVIEW); + glLoadIdentity(); + gluLookAt( 0.0, 0.0, 40.0, + 0.0, 0.0, 0.0, + 0.0, 2.0, 10.0); + +} + +static void +unit_cube(int wire) +{ + glBegin((wire)?GL_LINE_LOOP:GL_QUADS); + glNormal3f( 0.0f, -1.0f, 0.0f); + glVertex3f(-1.0f, -1.0f, -1.0f); + glVertex3f( 1.0f, -1.0f, -1.0f); + glVertex3f( 1.0f, -1.0f, 1.0f); + glVertex3f(-1.0f, -1.0f, 1.0f); + glNormal3f( 0.0f, 0.0f, 1.0f); + glVertex3f(-1.0f, -1.0f, 1.0f); + glVertex3f( 1.0f, -1.0f, 1.0f); + glVertex3f( 1.0f, 1.0f, 1.0f); + glVertex3f(-1.0f, 1.0f, 1.0f); + glNormal3f( 0.0f, 0.0f, -1.0f); + glVertex3f(-1.0f, -1.0f, -1.0f); + glVertex3f(-1.0f, 1.0f, -1.0f); + glVertex3f( 1.0f, 1.0f, -1.0f); + glVertex3f( 1.0f, -1.0f, -1.0f); + glNormal3f( 1.0f, 0.0f, 0.0f); + glVertex3f( 1.0f, -1.0f, -1.0f); + glVertex3f( 1.0f, 1.0f, -1.0f); + glVertex3f( 1.0f, 1.0f, 1.0f); + glVertex3f( 1.0f, -1.0f, 1.0f); + glNormal3f( -1.0f, 0.0f, 0.0f); + glVertex3f(-1.0f, -1.0f, -1.0f); + glVertex3f(-1.0f, -1.0f, 1.0f); + glVertex3f(-1.0f, 1.0f, 1.0f); + glVertex3f(-1.0f, 1.0f, -1.0f); + glNormal3f( 1.0f, 1.0f, 0.0f); + glVertex3f(-1.0f, 1.0f, -1.0f); + glVertex3f(-1.0f, 1.0f, 1.0f); + glVertex3f( 1.0f, 1.0f, 1.0f); + glVertex3f( 1.0f, 1.0f, -1.0f); + glEnd(); +} + +ENTRYPOINT void +init_ball (ModeInfo *mi) +{ + int wire = MI_IS_WIREFRAME(mi); + blinkboxstruct *bp; + + if(blinkbox == NULL) { + if((blinkbox = (blinkboxstruct *) calloc(MI_NUM_SCREENS(mi), + sizeof (blinkboxstruct))) == NULL) + return; + } + bp = &blinkbox[MI_SCREEN(mi)]; + + if ((bp->glx_context = init_GL(mi)) != NULL) { + reshape_ball(mi, MI_WIDTH(mi), MI_HEIGHT(mi)); + glDrawBuffer(GL_BACK); + } + else + MI_CLEARWINDOW(mi); + + bp->ball.d = 1; + bp->bscale.wh = bscale_wh; + bp->bscale.d = 0.25; + + bp->mo.x = 1; + bp->mo.y = 1; + bp->mo.z = 1; + + bp->moh.x = -1.0; + bp->moh.y = -1.5; + bp->moh.z = -1.5; + + bp->bpos.x = 1; + bp->bpos.y = 1; + bp->bpos.z = 1; + + bp->des_amt = 1; + + bp->lside.counter = MAX_COUNT; + bp->rside.counter = MAX_COUNT; + bp->tside.counter = MAX_COUNT; + bp->bside.counter = MAX_COUNT; + bp->fside.counter = MAX_COUNT; + bp->aside.counter = MAX_COUNT; + + bp->lside.color[0] = 1; + bp->rside.color[1] = 1; + bp->tside.color[2] = 1; + + bp->bside.color[0] = 1; + bp->bside.color[1] = 0.5; + + bp->fside.color[0] = 1; + bp->fside.color[1] = 1; + + bp->aside.color[0] = 0.5; + bp->aside.color[2] = 1; + + bp->lside.rot[0] = 90; + bp->rside.rot[0] = 90; + bp->tside.rot[0] = 90; + bp->bside.rot[0] = 90; + bp->fside.rot[0] = 90; + bp->aside.rot[0] = 90; + + bp->lside.rot[2] = 1; + bp->rside.rot[2] = 1; + bp->tside.rot[1] = 1; + bp->bside.rot[1] = 1; + bp->fside.rot[3] = 1; + bp->aside.rot[3] = 1; + + bp->lside.des_count = 1; + bp->rside.des_count = 1; + bp->tside.des_count = 1; + bp->bside.des_count = 1; + bp->fside.des_count = 1; + bp->aside.des_count = 1; + + bp->lside.alpha_count = 1; + bp->rside.alpha_count = 1; + bp->tside.alpha_count = 1; + bp->bside.alpha_count = 1; + bp->fside.alpha_count = 1; + bp->aside.alpha_count = 1; + + +#define SPHERE_SLICES 12 /* how densely to render spheres */ +#define SPHERE_STACKS 16 + + bp->sp = malloc(sizeof(*bp->sp)); + if(bp->sp == NULL){ + fprintf(stderr,"Could not allocate memory\n"); + exit(1); + } + if( (bp->bscale.wh < 1) || + (bp->bscale.wh > 8) ) { + fprintf(stderr,"Boxsize out of range. Using default\n"); + bp->bscale.wh = 2; + } + if (do_dissolve){ + bp->des_amt = bp->bscale.wh / MAX_COUNT; + } + + reshape_ball(mi, MI_WIDTH(mi), MI_HEIGHT(mi)); + bp->ballList = glGenLists(1); + glNewList(bp->ballList, GL_COMPILE); + unit_sphere (SPHERE_STACKS, SPHERE_SLICES, wire); + glEndList (); + + bp->boxList = glGenLists(1); + glNewList(bp->boxList, GL_COMPILE); + unit_cube(wire); + glEndList(); + + if (wire) return; + + glEnable(GL_COLOR_MATERIAL); + glShadeModel(GL_SMOOTH); + glClearDepth(1.0f); + glEnable(GL_DEPTH_TEST); + glDepthFunc(GL_LEQUAL); + glEnable(GL_LIGHTING); + glClearDepth(1); + glLightfv(GL_LIGHT1, GL_DIFFUSE, LightDiffuse); + glLightfv(GL_LIGHT1, GL_POSITION,LightPosition); + glEnable(GL_LIGHT1); + if (do_fade || do_blur) { + glEnable(GL_BLEND); + glDisable(GL_DEPTH_TEST); + } +} + +static void +CheckBoxPos(blinkboxstruct *bp, + GLfloat bot_x, GLfloat top_x, GLfloat bot_y, GLfloat top_y) +{ + /*Make sure it's inside of the bounding box*/ + bp->bpos.x = ((bp->bpos.x - bp->bscale.wh) < bot_x) ? bot_x + bp->bscale.wh : bp->bpos.x; + bp->bpos.x = ((bp->bpos.x + bp->bscale.wh) > top_x) ? top_x - bp->bscale.wh : bp->bpos.x; + bp->bpos.y = ((bp->bpos.y - bp->bscale.wh) < bot_y) ? bot_y + bp->bscale.wh : bp->bpos.y; + bp->bpos.y = ((bp->bpos.y + bp->bscale.wh) > top_y) ? top_y - bp->bscale.wh : bp->bpos.y; +} + +ENTRYPOINT void +draw_ball (ModeInfo *mi) +{ + blinkboxstruct *bp = &blinkbox[MI_SCREEN(mi)]; + + Display *dpy = MI_DISPLAY(mi); + Window window = MI_WINDOW(mi); + int i = 0; + + if (! bp->glx_context) + return; + mi->polygon_count = 0; + glXMakeCurrent(MI_DISPLAY(mi), MI_WINDOW(mi), *(bp->glx_context)); + + glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + + hit_top_bottom(bp); + hit_front_back(bp); + hit_side(bp); + + glRotated(0.25,0,0,1); + glRotated(0.25,0,1,0); + glRotated(0.25,1,0,0); + + + glPushMatrix(); + glScalef(0.5,0.5,0.5); + + glColor3f(1,1,1); + glPushMatrix(); + + if (!do_blur || MI_IS_WIREFRAME(mi)) { + glTranslatef(bp->ball.x += bp->mo.x, + bp->ball.y += bp->mo.y, + bp->ball.z += bp->mo.z); + + glScalef(2,2,2); + glCallList(bp->ballList); + mi->polygon_count += SPHERE_SLICES*SPHERE_STACKS; + + } else { + +# define blur_detail 24.0 + float ball_alpha = 1 / blur_detail; + + glBlendFunc(GL_SRC_ALPHA,GL_ONE); + glTranslatef(bp->ball.x, bp->ball.y, bp->ball.z); + + for (i = 0; i < blur_detail; ++i) { + glTranslatef(bp->mo.x / blur_detail, + bp->mo.y / blur_detail, + bp->mo.z / blur_detail); + + /* comment the following line for quick but boring linear blur */ + ball_alpha = sin((M_PI / blur_detail) * i) / blur_detail; + + glColor4f(1, 1, 1, ball_alpha); + + glScalef(2, 2, 2); + glCallList(bp->ballList); + mi->polygon_count += SPHERE_SLICES*SPHERE_STACKS; + glScalef(.5, .5, .5); + } + i = 0; + + bp->ball.x += bp->mo.x; + bp->ball.y += bp->mo.y; + bp->ball.z += bp->mo.z; + } + + glPopMatrix(); + + while(i < 6){ + switch(i){ + case 0:{ + bp->sp = &bp->lside; + bp->bpos.x = bp->lside.pos.z*-1; + bp->bpos.y = bp->lside.pos.y; + bp->bpos.z = bbox.bottom.x - bp->bscale.d; + if (bp->sp->hit) + CheckBoxPos(bp, bbox.bottom.z,bbox.top.z,bbox.bottom.y,bbox.top.y); + break; + } + case 1:{ + bp->sp = &bp->rside; + bp->bpos.x = bp->rside.pos.z*-1; + bp->bpos.y = bp->rside.pos.y; + bp->bpos.z = bbox.top.x + bp->bscale.d; + if (bp->sp->hit) + CheckBoxPos(bp, bbox.bottom.z,bbox.top.z,bbox.bottom.y,bbox.top.y); + break; + } + case 2:{ + bp->sp = &bp->tside; + bp->bpos.x = bp->tside.pos.x; + bp->bpos.y = bp->tside.pos.z; + bp->bpos.z = bbox.bottom.y - bp->bscale.d; + if (bp->sp->hit) + CheckBoxPos(bp, bbox.bottom.x,bbox.top.x,bbox.bottom.z,bbox.top.z); + break; + } + case 3:{ + bp->sp = &bp->bside; + bp->bpos.x = bp->bside.pos.x; + bp->bpos.y = bp->bside.pos.z; + bp->bpos.z = bbox.top.y + bp->bscale.d; + if (bp->sp->hit) + CheckBoxPos(bp, bbox.bottom.x,bbox.top.x,bbox.bottom.z,bbox.top.z); + break; + } + case 4:{ + bp->sp = &bp->fside; + bp->bpos.x = bp->fside.pos.y; + bp->bpos.y = bp->fside.pos.x*-1; + bp->bpos.z = bbox.top.z + bp->bscale.d; + if (bp->sp->hit) + CheckBoxPos(bp, bbox.bottom.y,bbox.top.y,bbox.bottom.x,bbox.top.x); + break; + } + case 5:{ + bp->sp = &bp->aside; + bp->bpos.x = bp->aside.pos.y; + bp->bpos.y = bp->aside.pos.x*-1; + bp->bpos.z = bbox.bottom.z + bp->bscale.d; + if (bp->sp->hit) + CheckBoxPos(bp, bbox.bottom.y,bbox.top.y,bbox.bottom.x,bbox.top.x); + break; + } + } + if(bp->sp->hit){ + if(do_fade){ + glColor4f(bp->sp->color[0],bp->sp->color[1],bp->sp->color[2],1-(ALPHA_AMT * bp->sp->alpha_count)); + }else{ + glColor3fv(bp->sp->color); + } + glBlendFunc(GL_SRC_ALPHA,GL_ONE); + glPushMatrix(); + glRotatef(bp->sp->rot[0],bp->sp->rot[1],bp->sp->rot[2],bp->sp->rot[3]); + glTranslatef(bp->bpos.x,bp->bpos.y,bp->bpos.z); + if (do_dissolve) { + glScalef(bp->bscale.wh-(bp->des_amt*bp->sp->des_count),bp->bscale.wh-(bp->des_amt*bp->sp->des_count),bp->bscale.d); + }else{ + glScalef(bp->bscale.wh,bp->bscale.wh,bp->bscale.d); + } + glCallList(bp->boxList); + mi->polygon_count += 6; + glPopMatrix(); + bp->sp->counter--; + bp->sp->des_count++; + bp->sp->alpha_count++; + if(!bp->sp->counter) + { + bp->sp->hit = 0; + } + } + i++; + } + + + glPopMatrix(); + if (mi->fps_p) do_fps (mi); + glFinish(); + glXSwapBuffers(dpy, window); + +} + +XSCREENSAVER_MODULE_2 ("BlinkBox", blinkbox, ball) + +#endif /* USE_GL */ diff --git a/hacks/glx/blinkbox.man b/hacks/glx/blinkbox.man new file mode 100644 index 00000000..0dc2a3f8 --- /dev/null +++ b/hacks/glx/blinkbox.man @@ -0,0 +1,73 @@ +.TH XScreenSaver 1 "" "X Version 11" +.SH NAME +blinkbox \- shows a ball inside a box. +.SH SYNOPSIS +.B blinkbox +[\-display \fIhost:display.screen\fP] +[\-visual \fIvisual\fP] +[\-window] +[\-root] +[\-delay \fInumber\fP] +[\-wireframe] +[\-boxsize \fInumber\fP] +[\-dissolve] +[\-fade] +[\-no\-blur] +[\-fps] +.SH DESCRIPTION +Shows a ball contained inside of a bounding box. Colored blocks blink in +when the ball hits the edges. +.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 \-wireframe | \-no-wireframe +Render in wireframe instead of solid. +.TP 8 +.B \-boxsize +Sets the size of the colored boxes. Should be between 1 and 8. Default: 2 +.TP 8 +.B \-dissolve | \-no-dissolve +Boxes shrink instead of just vanishing. +.TP 8 +.B \-fade | \-no-fade +Boxes fade to transparency instead of just vanishing. +.TP 8 +.B \-blur | \-no-blur +Enable or disable motion blur on the ball. Default: blurry. +.TP 8 +.B \-fps +Display the current frame rate, CPU load, and polygon count. +.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 2003 by Jeremy English. 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 +Jeremy English. Motion blur by John Boero. diff --git a/hacks/glx/blocktube.c b/hacks/glx/blocktube.c new file mode 100644 index 00000000..69605e7e --- /dev/null +++ b/hacks/glx/blocktube.c @@ -0,0 +1,449 @@ +/* blocktube, Copyright (c) 2003 Lars Damerow + * + * Based on Jamie Zawinski's original dangerball code. + * + * 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. + */ + +#define DEBUG 1 + +#define DEFAULTS "*delay: 40000 \n" \ + "*wireframe: False \n" \ + "*showFPS: False \n" \ + +# define refresh_blocktube 0 +# define blocktube_handle_event 0 +#undef countof +#define countof(x) (sizeof((x))/sizeof((*x))) + +#include "xlockmore.h" +#include "colors.h" +#include +#include + +#ifdef USE_GL /* whole file */ + +#define DEF_HOLDTIME "1000" +#define DEF_CHANGETIME "200" +#define MAX_ENTITIES 1000 +#define DEF_TEXTURE "True" +#define DEF_FOG "True" + +#if defined(USE_XPM) || defined(USE_XPMINC) || defined(STANDALONE) +/* USE_XPM & USE_XPMINC in xlock mode ; HAVE_XPM in xscreensaver mode */ +#include "xpm-ximage.h" +#define I_HAVE_XPM + +#include "../images/blocktube.xpm" +#endif /* HAVE_XPM */ + +typedef struct { + int id, r, g, b; + GLfloat tVal; + int age; + int lifetime; + GLfloat position[3]; + GLfloat angle; + GLfloat angularVelocity; +} entity; + +typedef struct { + GLXContext *glx_context; + GLuint block_dlist; + int nextID; + + entity entities[MAX_ENTITIES]; + float targetR, targetG, targetB, + currentR, currentG, currentB, + deltaR, deltaG, deltaB; + int counter; + int changing; + GLfloat zoom; + GLfloat tilt; + GLuint envTexture; + XImage *texti; + + GLfloat tunnelLength; + GLfloat tunnelWidth; + int polys; + +} blocktube_configuration; + +static blocktube_configuration *lps = NULL; + +static GLint holdtime; +static GLint changetime; +static int do_texture; +static int do_fog; + +static XrmOptionDescRec opts[] = { + { "-holdtime", ".holdtime", XrmoptionSepArg, 0 }, + { "-changetime", ".changetime", XrmoptionSepArg, 0 }, + {"-texture", ".texture", XrmoptionNoArg, "True" }, + {"+texture", ".texture", XrmoptionNoArg, "False" }, + {"-fog", ".fog", XrmoptionNoArg, "True" }, + {"+fog", ".fog", XrmoptionNoArg, "False" }, +}; + +static argtype vars[] = { + {&holdtime, "holdtime", "Hold Time", DEF_HOLDTIME, t_Int}, + {&changetime, "changetime", "Change Time", DEF_CHANGETIME, \ + t_Int}, + {&do_texture, "texture", "Texture", DEF_TEXTURE, t_Bool}, + {&do_fog, "fog", "Fog", DEF_FOG, t_Bool}, +}; + +static OptionStruct desc[] = { + {"-holdtime", "how long to stay on the same color"}, + {"-changetime", "how long it takes to fade to a new color"}, +}; + +ENTRYPOINT ModeSpecOpt blocktube_opts = {countof(opts), opts, countof(vars), vars, desc}; + +#ifdef USE_MODULES +ModStruct blocktube_description = + {"blocktube", "init_blocktube", "draw_blocktube", "release_blocktube", + "draw_blocktube", "init_blocktube", (char *)NULL, &blocktube_opts, + 40000, 30, 1, 1, 64, 1.0, "", + "A shifting tunnel of reflective blocks", 0, NULL}; +#endif /* USE_MODULES */ + +#if defined( I_HAVE_XPM ) +static Bool LoadGLTextures(ModeInfo *mi) +{ + blocktube_configuration *lp = &lps[MI_SCREEN(mi)]; + Bool status; + + status = True; + glGenTextures(1, &lp->envTexture); + glBindTexture(GL_TEXTURE_2D, lp->envTexture); + lp->texti = xpm_to_ximage(MI_DISPLAY(mi), MI_VISUAL(mi), MI_COLORMAP(mi), + blocktube_xpm); + if (!lp->texti) { + status = False; + } else { + glPixelStorei(GL_UNPACK_ALIGNMENT,1); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, lp->texti->width, lp->texti->height, 0, + GL_RGBA, GL_UNSIGNED_INT_8_8_8_8_REV, lp->texti->data); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); +# ifndef HAVE_JWZGLES /* #### Sphere maps unimplemented */ + glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_SPHERE_MAP); + glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_SPHERE_MAP); +# endif + } + return status; +} +#endif + +static void newTargetColor(blocktube_configuration *lp) +{ + int luminance = 0; + + while (luminance <= 150) { + lp->targetR = random() % 256; + lp->targetG = random() % 256; + lp->targetB = random() % 256; + lp->deltaR = (lp->targetR - lp->currentR) / changetime; + lp->deltaG = (lp->targetG - lp->currentG) / changetime; + lp->deltaB = (lp->targetB - lp->currentB) / changetime; + luminance = 0.3 * lp->targetR + 0.59 * lp->targetG + 0.11 * lp->targetB; + } +} + +static void randomize_entity (blocktube_configuration *lp, entity *ent) +{ + ent->id = lp->nextID++; + ent->tVal = 1 - ((float)random() / RAND_MAX / 1.5); + ent->age = 0; + ent->lifetime = 100; + ent->angle = random() % 360; + ent->angularVelocity = 0.5-((float)(random()) / RAND_MAX); + ent->position[0] = (float)(random()) / RAND_MAX + lp->tunnelWidth; + ent->position[1] = (float)(random()) / RAND_MAX * 2; + ent->position[2] = -(float)(random()) / RAND_MAX * lp->tunnelLength; +} + +static void entityTick(blocktube_configuration *lp, entity *ent) +{ + ent->angle += ent->angularVelocity; + ent->position[2] += 0.1; + if (ent->position[2] > lp->zoom) { + ent->position[2] = -lp->tunnelLength + ((float)(random()) / RAND_MAX) * 20; + } + ent->age += 0.1; +} + +static void tick(blocktube_configuration *lp) +{ + lp->counter--; + if (!lp->counter) { + if (!lp->changing) { + newTargetColor(lp); + lp->counter = changetime; + } else { + lp->counter = holdtime; + } + lp->changing = (!lp->changing); + } else { + if (lp->changing) { + lp->currentR += lp->deltaR; + lp->currentG += lp->deltaG; + lp->currentB += lp->deltaB; + } + } +} + +static int cube_vertices(float x, float y, float z, int wire); + +ENTRYPOINT void reshape_blocktube (ModeInfo *mi, int width, int height); + +ENTRYPOINT void init_blocktube (ModeInfo *mi) +{ + int loop; + GLfloat fogColor[4] = {0,0,0,1}; + blocktube_configuration *lp; + int wire = MI_IS_WIREFRAME(mi); + + if (!lps) { + lps = (blocktube_configuration *) + calloc (MI_NUM_SCREENS(mi), sizeof (blocktube_configuration)); + if (!lps) { + fprintf(stderr, "%s: out of memory\n", progname); + exit(1); + } + } + + lp = &lps[MI_SCREEN(mi)]; + lp->glx_context = init_GL(mi); + + lp->zoom = 30; + lp->tilt = 4.5; + lp->tunnelLength = 200; + lp->tunnelWidth = 5; + + if (wire) { + do_fog = False; + do_texture = False; + glLineWidth(2); + } + + lp->block_dlist = glGenLists (1); + glNewList (lp->block_dlist, GL_COMPILE); + lp->polys = cube_vertices(0.15, 1.2, 5.25, wire); + glEndList (); + +#if defined( I_HAVE_XPM ) + if (do_texture) { + if (!LoadGLTextures(mi)) { + fprintf(stderr, "%s: can't load textures!\n", progname); + exit(1); + } + glEnable(GL_TEXTURE_2D); + } +#endif + + /* kick on the fog machine */ + if (do_fog) { + glEnable(GL_FOG); + glFogi(GL_FOG_MODE, GL_LINEAR); + glHint(GL_FOG_HINT, GL_NICEST); + glFogf(GL_FOG_START, 0); + glFogf(GL_FOG_END, lp->tunnelLength/1.8); + glFogfv(GL_FOG_COLOR, fogColor); + glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST); + } + glShadeModel(GL_SMOOTH); + glEnable(GL_DEPTH_TEST); + glEnable(GL_CULL_FACE); + glClearDepth(1.0f); + + if (!do_texture && !wire) { + /* If there is no texture, the boxes don't show up without a light. + Though I don't understand why all the blocks come out gray. + */ + GLfloat pos[4] = {0.0, 1.0, 1.0, 0.0}; + GLfloat amb[4] = {0.2, 0.2, 0.2, 1.0}; + GLfloat dif[4] = {1.0, 1.0, 1.0, 1.0}; + GLfloat spc[4] = {1.0, 1.0, 1.0, 1.0}; + glLightfv(GL_LIGHT0, GL_POSITION, pos); + glLightfv(GL_LIGHT0, GL_AMBIENT, amb); + glLightfv(GL_LIGHT0, GL_DIFFUSE, dif); + glLightfv(GL_LIGHT0, GL_SPECULAR, spc); + glEnable(GL_LIGHTING); + glEnable(GL_LIGHT0); + } + + lp->counter = holdtime; + lp->currentR = random() % 256; + lp->currentG = random() % 256; + lp->currentB = random() % 256; + newTargetColor(lp); + for (loop = 0; loop < MAX_ENTITIES; loop++) + { + randomize_entity(lp, &lp->entities[loop]); + } + reshape_blocktube(mi, MI_WIDTH(mi), MI_HEIGHT(mi)); + glFlush(); +} + +ENTRYPOINT void release_blocktube (ModeInfo *mi) +{ + if (lps) { + int screen; + for (screen = 0; screen < MI_NUM_SCREENS(mi); screen++) { + blocktube_configuration *lp = &lps[screen]; +# if defined ( I_HAVE_XPM ) + if (lp->envTexture) + glDeleteTextures(1, &lp->envTexture); + if (lp->texti) + XDestroyImage(lp->texti); +# endif + } + free (lps); + lps = 0; + } + FreeAllGL(mi); +} + +ENTRYPOINT void reshape_blocktube (ModeInfo *mi, int width, int height) +{ + GLfloat h = (GLfloat) height / (GLfloat) width; + + glViewport(0, 0, (GLint) width, (GLint) height); + glMatrixMode(GL_PROJECTION); + glLoadIdentity(); + gluPerspective(45.0, 1/h, 1.0, 100.0); + glMatrixMode(GL_MODELVIEW); +} + +static int cube_vertices(float x, float y, float z, int wire) +{ + int polygon_count = 0; + float x2, y2, z2, nv = 0.7; + x2 = x/2; + y2 = y/2; + z2 = z/2; + + glFrontFace(GL_CW); + + glNormal3f(0, 0, nv); + glBegin (wire ? GL_LINE_LOOP : GL_QUADS); + glTexCoord2f(0.0, 0.0); glVertex3f(-x2, y2, z2); + glTexCoord2f(1.0, 0.0); glVertex3f( x2, y2, z2); + glTexCoord2f(1.0, 1.0); glVertex3f( x2, -y2, z2); + glTexCoord2f(0.0, 1.0); glVertex3f(-x2, -y2, z2); + polygon_count++; + glEnd(); + + glNormal3f(0, 0, -nv); + glBegin (wire ? GL_LINE_LOOP : GL_QUADS); + glTexCoord2f(1.0, 0.0); glVertex3f(-x2, -y2, -z2); + glTexCoord2f(1.0, 1.0); glVertex3f( x2, -y2, -z2); + glTexCoord2f(0.0, 1.0); glVertex3f( x2, y2, -z2); + glTexCoord2f(0.0, 0.0); glVertex3f(-x2, y2, -z2); + polygon_count++; + glEnd(); + + glNormal3f(0, nv, 0); + glBegin (wire ? GL_LINE_LOOP : GL_QUADS); + glTexCoord2f(0.0, 1.0); glVertex3f(-x2, y2, -z2); + glTexCoord2f(0.0, 0.0); glVertex3f( x2, y2, -z2); + glTexCoord2f(1.0, 0.0); glVertex3f( x2, y2, z2); + glTexCoord2f(1.0, 1.0); glVertex3f(-x2, y2, z2); + polygon_count++; + glEnd(); + + glNormal3f(0, -nv, 0); + glBegin (wire ? GL_LINE_LOOP : GL_QUADS); + glTexCoord2f(1.0, 1.0); glVertex3f(-x2, -y2, -z2); + glTexCoord2f(0.0, 1.0); glVertex3f(-x2, -y2, z2); + glTexCoord2f(0.0, 0.0); glVertex3f( x2, -y2, z2); + glTexCoord2f(1.0, 0.0); glVertex3f( x2, -y2, -z2); + polygon_count++; + glEnd(); + + if (wire) return polygon_count; + + glNormal3f(nv, 0, 0); + glBegin (wire ? GL_LINE_LOOP : GL_QUADS); + glTexCoord2f(1.0, 0.0); glVertex3f( x2, -y2, -z2); + glTexCoord2f(1.0, 1.0); glVertex3f( x2, -y2, z2); + glTexCoord2f(0.0, 1.0); glVertex3f( x2, y2, z2); + glTexCoord2f(0.0, 0.0); glVertex3f( x2, y2, -z2); + polygon_count++; + glEnd(); + + glNormal3f(-nv, 0, 0); + glBegin (wire ? GL_LINE_LOOP : GL_QUADS); + glTexCoord2f(0.0, 0.0); glVertex3f(-x2, -y2, -z2); + glTexCoord2f(1.0, 0.0); glVertex3f(-x2, y2, -z2); + glTexCoord2f(1.0, 1.0); glVertex3f(-x2, y2, z2); + glTexCoord2f(0.0, 1.0); glVertex3f(-x2, -y2, z2); + polygon_count++; + glEnd(); + + return polygon_count; +} + +static void draw_block(ModeInfo *mi, entity *ent) +{ + blocktube_configuration *lp = &lps[MI_SCREEN(mi)]; + glCallList (lp->block_dlist); + mi->polygon_count += lp->polys; +} + +ENTRYPOINT void +draw_blocktube (ModeInfo *mi) +{ + blocktube_configuration *lp = &lps[MI_SCREEN(mi)]; + Display *dpy = MI_DISPLAY(mi); + Window window = MI_WINDOW(mi); + entity *cEnt = NULL; + int loop = 0; + + if (!lp->glx_context) + return; + + mi->polygon_count = 0; + + glXMakeCurrent(MI_DISPLAY(mi), MI_WINDOW(mi), *(lp->glx_context)); + + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + + if (do_texture) { + glEnable(GL_TEXTURE_GEN_S); + glEnable(GL_TEXTURE_GEN_T); + glBindTexture(GL_TEXTURE_2D, lp->envTexture); + } + + for (loop = 0; loop < MAX_ENTITIES; loop++) { + cEnt = &lp->entities[loop]; + + glLoadIdentity(); + glTranslatef(0.0f, 0.0f, lp->zoom); + glRotatef(lp->tilt, 1.0f, 0.0f, 0.0f); + glRotatef(cEnt->angle, 0.0f, 0.0f, 1.0f); + glTranslatef(cEnt->position[0], cEnt->position[1], cEnt->position[2]); + glColor4ub((int)(lp->currentR * cEnt->tVal), + (int)(lp->currentG * cEnt->tVal), + (int)(lp->currentB * cEnt->tVal), 255); + draw_block(mi, cEnt); + entityTick(lp, cEnt); + } + tick(lp); + + if (mi->fps_p) do_fps (mi); + glFinish(); + glXSwapBuffers(dpy, window); +} + +XSCREENSAVER_MODULE ("BlockTube", blocktube) + +#endif /* USE_GL */ diff --git a/hacks/glx/blocktube.man b/hacks/glx/blocktube.man new file mode 100644 index 00000000..5d016e09 --- /dev/null +++ b/hacks/glx/blocktube.man @@ -0,0 +1,73 @@ +.TH XScreenSaver 1 "" "X Version 11" +.SH NAME +blocktube - draws a swirling, falling tunnel of reflective slabs +.SH SYNOPSIS +.B blocktube +[\-display \fIhost:display.screen\fP] +[\-visual \fIvisual\fP] +[\-window] +[\-root] +[\-delay \fInumber\fP] +[\-holdtime \fInumber\fP] +[\-changetime \fInumber\fP] +[\-no-texture] +[\-no-fog] +[\-wireframe] +[\-fps] +.SH DESCRIPTION +Blocktube draws a swirling, falling tunnel of reflective slabs. They fade +from hue to hue. +.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: 40000 (0.04 seconds.). +.TP 8 +.B \-holdtime \fInumber\fP +How long to stay on the same color. Default: 1000 frames. +.TP 8 +.B \-changetime \fInumber\fP +How long it takes to fade to a new color. Default: 200 frames. +.TP 8 +.B \-no-texture +Draw solid blocks intstead of reflective blocks. +.TP 8 +.B \-no-fog +Do not make blocks in the distance be darker. +.TP 8 +.B \-wireframe +Only draw outlines. +.TP 8 +.B \-fps +Display the current frame rate, CPU load, and polygon count. +.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 2003 by Lars Damerow. 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 +Lars Damerow diff --git a/hacks/glx/boing.c b/hacks/glx/boing.c new file mode 100644 index 00000000..3396217f --- /dev/null +++ b/hacks/glx/boing.c @@ -0,0 +1,683 @@ +/* boing, Copyright (c) 2005-2012 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. + * + * A clone of the Amiga 1000 "Boing" demo. This was the first graphics demo + * for the Amiga, written by Dale Luck and RJ Mical during a break at the 1984 + * Consumer Electronics Show (or so the legend goes.) The boing ball was + * briefly the official logo of Amiga Inc., until they were bought by + * Commodore later that year. + * + * With no arguments, this program looks a lot like the original Amiga demo. + * With "-smooth -lighting", it looks... less old. + * + * The amiga version made noise when the ball hit the walls. This version + * does not, obviously. + */ + +#define DEFAULTS "*delay: 30000 \n" \ + "*showFPS: False \n" \ + "*wireframe: False \n" \ + +# define refresh_boing 0 +# define release_boing 0 +#undef countof +#define countof(x) (sizeof((x))/sizeof((*x))) + +#include "xlockmore.h" +#include "gltrackball.h" +#include + +#ifdef USE_GL /* whole file */ + + +#define DEF_SPIN "True" +#define DEF_LIGHTING "False" +#define DEF_SMOOTH "False" +#define DEF_SCANLINES "True" +#define DEF_SPEED "1.0" +#define DEF_BALL_SIZE "0.5" +#define DEF_ANGLE "15" +#define DEF_MERIDIANS "16" +#define DEF_PARALLELS "8" +#define DEF_TILES "12" +#define DEF_THICKNESS "0.05" + +#define DEF_BALL_COLOR1 "#CC1919" +#define DEF_BALL_COLOR2 "#F2F2F2" +#define DEF_GRID_COLOR "#991999" +#define DEF_SHADOW_COLOR "#303030" +#define DEF_BACKGROUND "#8C8C8C" + +typedef struct { GLfloat x, y, z; } XYZ; + +typedef struct { + GLXContext *glx_context; + trackball_state *trackball; + Bool button_down_p; + + GLuint ball_list; + double ball_x, ball_y, ball_z, ball_th; + double ball_dx, ball_dy, ball_dz, ball_dth; + double ball_ddx, ball_ddy, ball_ddz; + + GLfloat ball_color1[4], ball_color2[4], grid_color[4]; + GLfloat bg_color[4], shadow_color[4]; + GLfloat lightpos[4]; + +} boing_configuration; + +static boing_configuration *bps = NULL; + +static Bool spin; +static Bool lighting_p; +static Bool smooth_p; +static Bool scanlines_p; +static GLfloat speed; +static int angle; +static GLfloat ball_size; +static unsigned int meridians; +static unsigned int parallels; +static unsigned int tiles; +static GLfloat thickness; +static char *ball_color1_str, *ball_color2_str, *grid_color_str, + *shadow_str, *bg_str; + +static XrmOptionDescRec opts[] = { + { "-spin", ".spin", XrmoptionNoArg, "True" }, + { "+spin", ".spin", XrmoptionNoArg, "False" }, + { "-lighting", ".lighting", XrmoptionNoArg, "True" }, + { "+lighting", ".lighting", XrmoptionNoArg, "False" }, + { "-smooth", ".smooth", XrmoptionNoArg, "True" }, + { "+smooth", ".smooth", XrmoptionNoArg, "False" }, + { "-scanlines", ".scanlines", XrmoptionNoArg, "True" }, + { "+scanlines", ".scanlines", XrmoptionNoArg, "False" }, + { "-speed", ".speed", XrmoptionSepArg, 0 }, + { "-angle", ".angle", XrmoptionSepArg, 0 }, + { "-size", ".ballSize", XrmoptionSepArg, 0 }, + { "-meridians", ".meridians", XrmoptionSepArg, 0 }, + { "-parallels", ".parallels", XrmoptionSepArg, 0 }, + { "-tiles", ".tiles", XrmoptionSepArg, 0 }, + { "-thickness", ".thickness", XrmoptionSepArg, 0 }, + { "-ball-color1",".ballColor1",XrmoptionSepArg, 0 }, + { "-ball-color2",".ballColor2",XrmoptionSepArg, 0 }, + { "-grid-color", ".gridColor", XrmoptionSepArg, 0 }, + { "-shadow-color",".shadowColor",XrmoptionSepArg, 0 }, + { "-background", ".boingBackground",XrmoptionSepArg, 0 }, + { "-bg", ".boingBackground",XrmoptionSepArg, 0 }, +}; + +static argtype vars[] = { + {&spin, "spin", "Spin", DEF_SPIN, t_Bool}, + {&lighting_p,"lighting", "Lighting", DEF_LIGHTING, t_Bool}, + {&smooth_p, "smooth", "Smooth", DEF_SMOOTH, t_Bool}, + {&scanlines_p,"scanlines","Scanlines", DEF_SCANLINES, t_Bool}, + {&speed, "speed", "Speed", DEF_SPEED, t_Float}, + {&angle, "angle", "Angle", DEF_ANGLE, t_Int}, + {&ball_size, "ballSize", "BallSize", DEF_BALL_SIZE, t_Float}, + {&meridians, "meridians", "meridians", DEF_MERIDIANS, t_Int}, + {¶llels, "parallels", "parallels", DEF_PARALLELS, t_Int}, + {&tiles, "tiles", "Tiles", DEF_TILES, t_Int}, + {&thickness, "thickness", "Thickness", DEF_THICKNESS, t_Float}, + {&ball_color1_str, "ballColor1", "BallColor1", DEF_BALL_COLOR1, t_String}, + {&ball_color2_str, "ballColor2", "BallColor2", DEF_BALL_COLOR2, t_String}, + {&grid_color_str, "gridColor", "GridColor", DEF_GRID_COLOR, t_String}, + {&shadow_str, "shadowColor","ShadowColor",DEF_SHADOW_COLOR,t_String}, + /* dammit, -background is too magic... */ + {&bg_str, "boingBackground", "Background", DEF_BACKGROUND, t_String}, +}; + +ENTRYPOINT ModeSpecOpt boing_opts = {countof(opts), opts, countof(vars), vars, NULL}; + +static void +parse_color (ModeInfo *mi, const char *name, const char *s, GLfloat *a) +{ + XColor c; + a[3] = 1.0; /* alpha */ + + if (! XParseColor (MI_DISPLAY(mi), MI_COLORMAP(mi), s, &c)) + { + fprintf (stderr, "%s: can't parse %s color %s", progname, name, s); + exit (1); + } + a[0] = c.red / 65536.0; + a[1] = c.green / 65536.0; + a[2] = c.blue / 65536.0; +} + + +static void +draw_grid (ModeInfo *mi) +{ + boing_configuration *bp = &bps[MI_SCREEN(mi)]; + int x, y; + GLfloat t2 = (GLfloat) tiles / 2; + GLfloat s = 1.0 / (tiles + thickness); + GLfloat z = 0; + + GLfloat lw = MI_HEIGHT(mi) * 0.06 * thickness; + + glMaterialfv (GL_FRONT, GL_AMBIENT_AND_DIFFUSE, bp->grid_color); + glColor3fv (bp->grid_color); + + glPushMatrix(); + glScalef(s, s, s); + glTranslatef (-t2, -t2, 0); + + glLineWidth (lw); + glBegin (GL_LINES); + for (y = 0; y <= tiles; y++) + { + glVertex3f (0, y, z); + glVertex3f (tiles, y, z); + /*mi->polygon_count++;*/ + } + for (x = 0; x <= tiles; x++) + { + glVertex3f (x, tiles, z); + glVertex3f (x, 0, z); + /*mi->polygon_count++;*/ + } + + glEnd(); + glPopMatrix(); +} + + +static void +draw_box (ModeInfo *mi) +{ + /* boing_configuration *bp = &bps[MI_SCREEN(mi)]; */ + glPushMatrix(); + glTranslatef (0, 0, -0.5); +/* glFrontFace (GL_CCW);*/ + draw_grid (mi); + glPopMatrix(); + + glPushMatrix(); + glRotatef (90, 1, 0, 0); + glTranslatef (0, 0, 0.5); +/* glFrontFace (GL_CW);*/ + draw_grid (mi); + glPopMatrix(); +} + + +static void +draw_ball (ModeInfo *mi) +{ + boing_configuration *bp = &bps[MI_SCREEN(mi)]; + int wire = MI_IS_WIREFRAME(mi); + int x, y; + int xx = meridians; + int yy = parallels; + int scale = (smooth_p ? 5 : 1); + + if (lighting_p && !wire) + glEnable (GL_LIGHTING); + + if (parallels < 3) + scale *= 2; + + xx *= scale; + yy *= scale; + + glFrontFace (GL_CW); + + glPushMatrix(); + glTranslatef (bp->ball_x, bp->ball_y, bp->ball_z); + glScalef (ball_size, ball_size, ball_size); + glRotatef (-angle, 0, 0, 1); + glRotatef (bp->ball_th, 0, 1, 0); + + for (y = 0; y < yy; y++) + { + GLfloat thy0 = y * (M_PI * 2) / (yy * 2) + M_PI_2; + GLfloat thy1 = (y+1) * (M_PI * 2) / (yy * 2) + M_PI_2; + + for (x = 0; x < xx; x++) + { + GLfloat thx0 = x * (M_PI * 2) / xx; + GLfloat thx1 = (x+1) * (M_PI * 2) / xx; + XYZ p; + Bool bgp = ((x/scale) & 1) ^ ((y/scale) & 1); + + if (wire && bgp) continue; + + glMaterialfv (GL_FRONT, GL_AMBIENT_AND_DIFFUSE, + (bgp ? bp->ball_color2 : bp->ball_color1)); + glColor3fv (bgp ? bp->ball_color2 : bp->ball_color1); + + glBegin (wire ? GL_LINE_LOOP : GL_QUADS); + + if (!smooth_p) + { + p.x = cos((thy0+thy1)/2) * cos((thx0+thx1)/2); + p.y = sin((thy0+thy1)/2); + p.z = cos((thy0+thy1)/2) * sin((thx0+thx1)/2); + glNormal3f (-p.x, -p.y, -p.z); + } + + p.x = cos(thy0) * cos(thx0) / 2; + p.y = sin(thy0) / 2; + p.z = cos(thy0) * sin(thx0) / 2; + if (smooth_p) + glNormal3f (-p.x, -p.y, -p.z); + glVertex3f (p.x, p.y, p.z); + + p.x = cos(thy1) * cos(thx0) / 2; + p.y = sin(thy1) / 2; + p.z = cos(thy1) * sin(thx0) / 2; + if (smooth_p) + glNormal3f (-p.x, -p.y, -p.z); + glVertex3f (p.x, p.y, p.z); + + p.x = cos(thy1) * cos(thx1) / 2; + p.y = sin(thy1) / 2; + p.z = cos(thy1) * sin(thx1) / 2; + if (smooth_p) + glNormal3f (-p.x, -p.y, -p.z); + glVertex3f (p.x, p.y, p.z); + + p.x = cos(thy0) * cos(thx1) / 2; + p.y = sin(thy0) / 2; + p.z = cos(thy0) * sin(thx1) / 2; + if (smooth_p) + glNormal3f (-p.x, -p.y, -p.z); + glVertex3f (p.x, p.y, p.z); + + glEnd (); + mi->polygon_count++; + } + } + + glPopMatrix(); + + if (lighting_p && !wire) + glDisable(GL_LIGHTING); +} + + +static void +draw_shadow (ModeInfo *mi) +{ + boing_configuration *bp = &bps[MI_SCREEN(mi)]; + int wire = MI_IS_WIREFRAME(mi); + GLfloat xoff = 0.14; + GLfloat yoff = 0.07; + int y; + int yy = parallels; + int scale = (smooth_p ? 5 : 1); + + if (lighting_p && !wire) + glEnable (GL_BLEND); + + if (parallels < 3) + scale *= 2; + + yy *= scale; + + glPushMatrix(); + glTranslatef (bp->ball_x + xoff, bp->ball_y + yoff, -0.49); + glScalef (ball_size, ball_size, ball_size); + glRotatef (-angle, 0, 0, 1); + + glMaterialfv (GL_FRONT, GL_AMBIENT_AND_DIFFUSE, bp->shadow_color); + glColor4fv (bp->shadow_color); + + glFrontFace (GL_CCW); + glNormal3f (0, 0, 1); + glBegin (wire ? GL_LINE_LOOP : GL_TRIANGLE_FAN); + if (!wire) glVertex3f (0, 0, 0); + + for (y = 0; y < yy*2+1; y++) + { + GLfloat thy0 = y * (M_PI * 2) / (yy * 2) + M_PI_2; + glVertex3f (cos(thy0) / 2, sin(thy0) / 2, 0); + mi->polygon_count++; + } + + glEnd (); + + glPopMatrix(); + + if (lighting_p && !wire) + glDisable (GL_BLEND); +} + + +static void +draw_scanlines (ModeInfo *mi) +{ + /* boing_configuration *bp = &bps[MI_SCREEN(mi)]; */ + int wire = MI_IS_WIREFRAME(mi); + int w = MI_WIDTH(mi); + int h = MI_HEIGHT(mi); + + if (h <= 300) return; + + if (!wire) + { + glEnable (GL_BLEND); + glDisable (GL_DEPTH_TEST); + } + + glMatrixMode(GL_PROJECTION); + glPushMatrix(); + { + glLoadIdentity(); + glMatrixMode(GL_MODELVIEW); + glPushMatrix(); + { + int lh, ls; + int y; + glLoadIdentity(); + glOrtho (0, w, 0, h, -1, 1); + + if (h > 500) lh = 4, ls = 4; + else if (h > 300) lh = 2, ls = 1; + else lh = 1, ls = 1; + + if (lh == 1) + glDisable (GL_BLEND); + + glLineWidth (lh); + glColor4f (0, 0, 0, 0.3); + + glBegin(GL_LINES); + for (y = 0; y < h; y += lh + ls) + { + glVertex3f (0, y, 0); + glVertex3f (w, y, 0); + } + glEnd(); + } + glPopMatrix(); + } + glMatrixMode(GL_PROJECTION); + glPopMatrix(); + glMatrixMode(GL_MODELVIEW); + + if (!wire) + { + glDisable (GL_BLEND); + glEnable (GL_DEPTH_TEST); + } +} + + + +static void +tick_physics (ModeInfo *mi) +{ + boing_configuration *bp = &bps[MI_SCREEN(mi)]; + GLfloat s2 = ball_size / 2; + GLfloat max = 0.5 - s2; + GLfloat min = -max; + + bp->ball_th += bp->ball_dth; + while (bp->ball_th > 360) bp->ball_th -= 360; + while (bp->ball_th < 0) bp->ball_th += 360; + + bp->ball_dx += bp->ball_ddx; + bp->ball_x += bp->ball_dx; + if (bp->ball_x < min) bp->ball_x = min, bp->ball_dx = -bp->ball_dx, + bp->ball_dth = -bp->ball_dth, + bp->ball_dx += (frand(speed/2) - speed); + else if (bp->ball_x > max) bp->ball_x = max, bp->ball_dx = -bp->ball_dx, + bp->ball_dth = -bp->ball_dth, + bp->ball_dx += (frand(speed/2) - speed); + + bp->ball_dy += bp->ball_ddy; + bp->ball_y += bp->ball_dy; + if (bp->ball_y < min) bp->ball_y = min, bp->ball_dy = -bp->ball_dy; + else if (bp->ball_y > max) bp->ball_y = max, bp->ball_dy = -bp->ball_dy; + + bp->ball_dz += bp->ball_ddz; + bp->ball_z += bp->ball_dz; + if (bp->ball_z < min) bp->ball_z = min, bp->ball_dz = -bp->ball_dz; + else if (bp->ball_z > max) bp->ball_z = max, bp->ball_dz = -bp->ball_dz; +} + + + +/* Window management, etc + */ +ENTRYPOINT void +reshape_boing (ModeInfo *mi, int width, int height) +{ + GLfloat h = (GLfloat) height / (GLfloat) width; + + h *= 4.0 / 3.0; /* Back in the caveman days we couldn't even afford + square pixels! */ + + glViewport (0, 0, (GLint) width, (GLint) height); + + glMatrixMode(GL_PROJECTION); + glLoadIdentity(); + + if (height > width) + { + GLfloat s = width / (GLfloat) height; + glScalef (s, s, s); + } + + gluPerspective (8.0, 1/h, 1.0, 10.0); + + glMatrixMode(GL_MODELVIEW); + glLoadIdentity(); + gluLookAt (0.0, 0.0, 8.0, + 0.0, 0.0, 0.0, + 0.0, 1.0, 0.0); + + glClear(GL_COLOR_BUFFER_BIT); +} + + +ENTRYPOINT Bool +boing_handle_event (ModeInfo *mi, XEvent *event) +{ + boing_configuration *bp = &bps[MI_SCREEN(mi)]; + + if (event->xany.type == ButtonPress && + event->xbutton.button == Button1) + { + bp->button_down_p = True; + gltrackball_start (bp->trackball, + event->xbutton.x, event->xbutton.y, + MI_WIDTH (mi), MI_HEIGHT (mi)); + return True; + } + else if (event->xany.type == ButtonRelease && + event->xbutton.button == Button1) + { + bp->button_down_p = False; + return True; + } + else if (event->xany.type == ButtonPress && + (event->xbutton.button == Button4 || + event->xbutton.button == Button5 || + event->xbutton.button == Button6 || + event->xbutton.button == Button7)) + { + gltrackball_mousewheel (bp->trackball, event->xbutton.button, 10, + !!event->xbutton.state); + return True; + } + else if (event->xany.type == MotionNotify && + bp->button_down_p) + { + gltrackball_track (bp->trackball, + event->xmotion.x, event->xmotion.y, + MI_WIDTH (mi), MI_HEIGHT (mi)); + return True; + } + + return False; +} + + +ENTRYPOINT void +init_boing (ModeInfo *mi) +{ + boing_configuration *bp; + int wire = MI_IS_WIREFRAME(mi); + + if (!bps) { + bps = (boing_configuration *) + calloc (MI_NUM_SCREENS(mi), sizeof (boing_configuration)); + if (!bps) { + fprintf(stderr, "%s: out of memory\n", progname); + exit(1); + } + } + + bp = &bps[MI_SCREEN(mi)]; + + bp->glx_context = init_GL(mi); + + if (tiles < 1) tiles = 1; + + if (smooth_p) + { + if (meridians < 1) meridians = 1; + if (parallels < 1) parallels = 1; + } + else + { + if (meridians < 3) meridians = 3; + if (parallels < 2) parallels = 2; + } + + if (meridians > 1 && meridians & 1) meridians++; /* odd numbers look bad */ + + + if (thickness <= 0) thickness = 0.001; + else if (thickness > 1) thickness = 1; + + reshape_boing (mi, MI_WIDTH(mi), MI_HEIGHT(mi)); + + parse_color (mi, "ballColor1", ball_color1_str, bp->ball_color1); + parse_color (mi, "ballColor2", ball_color2_str, bp->ball_color2); + parse_color (mi, "gridColor", grid_color_str, bp->grid_color); + parse_color (mi, "shadowColor", shadow_str, bp->shadow_color); + parse_color (mi, "background", bg_str, bp->bg_color); + + bp->shadow_color[3] = 0.9; + + glClearColor (bp->bg_color[0], bp->bg_color[1], bp->bg_color[2], 1); + + if (!wire) + { + glEnable(GL_DEPTH_TEST); + glEnable(GL_CULL_FACE); + } + + bp->lightpos[0] = 0.5; + bp->lightpos[1] = 0.5; + bp->lightpos[2] = -1; + bp->lightpos[3] = 0; + + if (lighting_p && !wire) + { + GLfloat amb[4] = {0, 0, 0, 1}; + GLfloat dif[4] = {1, 1, 1, 1}; + GLfloat spc[4] = {1, 1, 1, 1}; + glEnable(GL_LIGHT0); + glLightfv(GL_LIGHT0, GL_AMBIENT, amb); + glLightfv(GL_LIGHT0, GL_DIFFUSE, dif); + glLightfv(GL_LIGHT0, GL_SPECULAR, spc); + } + + glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + + speed = speed / 800.0; + + bp->ball_dth = (spin ? -speed * 7 * 360 : 0); + + bp->ball_x = 0.5 - ((ball_size/2) + frand(1-ball_size)); + bp->ball_y = 0.2; + bp->ball_dx = speed * 6 + frand(speed); + bp->ball_ddy = -speed; + + bp->ball_dz = speed * 6 + frand(speed); + + bp->trackball = gltrackball_init (); +} + + +ENTRYPOINT void +draw_boing (ModeInfo *mi) +{ + boing_configuration *bp = &bps[MI_SCREEN(mi)]; + Display *dpy = MI_DISPLAY(mi); + Window window = MI_WINDOW(mi); + + if (!bp->glx_context) + return; + + glXMakeCurrent(MI_DISPLAY(mi), MI_WINDOW(mi), *(bp->glx_context)); + + mi->polygon_count = 0; + + glShadeModel(GL_SMOOTH); + + glEnable(GL_NORMALIZE); + + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + + if (! bp->button_down_p) + tick_physics (mi); + + glPushMatrix (); + + { + double rot = current_device_rotation(); + glRotatef(rot, 0, 0, 1); + if ((rot > 45 && rot < 135) || + (rot < -45 && rot > -135)) + { + GLfloat s = MI_WIDTH(mi) / (GLfloat) MI_HEIGHT(mi); + glScalef (1/s, s, 1); + } + } + + gltrackball_rotate (bp->trackball); + + glLightfv (GL_LIGHT0, GL_POSITION, bp->lightpos); + + glDisable (GL_CULL_FACE); + glDisable (GL_DEPTH_TEST); + + glEnable (GL_LINE_SMOOTH); + glHint (GL_LINE_SMOOTH_HINT, GL_NICEST); + glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + glEnable (GL_BLEND); + + draw_box (mi); + draw_shadow (mi); + + glEnable (GL_CULL_FACE); + glEnable (GL_DEPTH_TEST); + + draw_ball (mi); + if (scanlines_p) + draw_scanlines (mi); + + glPopMatrix (); + + if (mi->fps_p) do_fps (mi); + glFinish(); + + glXSwapBuffers(dpy, window); +} + +XSCREENSAVER_MODULE ("Boing", boing) + +#endif /* USE_GL */ diff --git a/hacks/glx/boing.man b/hacks/glx/boing.man new file mode 100644 index 00000000..1f00d723 --- /dev/null +++ b/hacks/glx/boing.man @@ -0,0 +1,105 @@ +.TH XScreenSaver 1 "30-Oct-99" "X Version 11" +.SH NAME +boing - draws a bouncing ball like the ancient Amiga demo +.SH SYNOPSIS +.B boing +[\-display \fIhost:display.screen\fP] [\-window] [\-root] [\-install] +[\-visual \fIvisual\fP] +[\-delay \fIusecs\fP] +[\-smooth] +[\-lighting] +[\-scanlines] +[\-speed] +[\-no\-spin] +[\-angle \fIdegrees\fP] +[\-size \fIratio\fP] +[\-parallels \fIn\fP] +[\-meridians \fIn\fP] +[\-wireframe] +[\-fps] +.SH DESCRIPTION +The \fIboing\fP program draws a bouncing checkered ball on a grid. + +This is a clone of the first graphics demo for the Amiga 1000, which +was written by Dale Luck and RJ Mical during a break at the 1984 +Consumer Electronics Show (or so the legend goes.) The boing ball was +briefly the official logo of Amiga Inc., until they were bought by +Commodore later that year. + +With no arguments, this program looks a lot like the original Amiga +demo. With "-smooth -lighting", it looks... less old. +.SH OPTIONS +.I boing +accepts the following options: +.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 \-install +Install a private colormap for the window. +.TP 8 +.B \-visual \fIvisual\fP\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 \-delay \fIusecs\fP +The delay between frames of the animation, in microseconds: default 15000. +.TP 8 +.B \-smooth +Draw a smooth sphere instead of a faceted polyhedron. +.TP 8 +.B \-lighting +Do shaded lighting instead of flat colors. +.TP 8 +.B \-scanlines +If the window is large enough, draw horizontal lines to simulate the +scanlines on a low resolution monitor. +.TP 8 +.B \-speed \fIratio\fP +Change the animation speed; 0.5 to go half as fast, 2.0 to go twice as fast. +.TP 8 +.B \-no\-spin +Don't rotate the ball. +.TP 8 +.B \-angle \fIdegrees\fP +The jaunty angle at which the ball sits. Default 15 degrees. +.TP 8 +.B \-size \fIratio\fP +How big the ball is; default 0.5 meaning about half the size of the window. +.TP 8 +.B \-parallels \fIn\fP +.B \-meridians \fIn\fP +The pattern of rectangles on the ball. Default 8x16. +.TP 8 +.B \-wireframe +Look crummy. +.TP 8 +.B \-fps +Display the current frame rate, CPU load, and polygon count. +.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 bsod (MANSUFFIX), +.BR pong (MANSUFFIX), +.BR xscreensaver (1), +.BR X (1) +.SH COPYRIGHT +Copyright \(co 2005 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 , 19-Feb-2005. diff --git a/hacks/glx/bouncingcow.c b/hacks/glx/bouncingcow.c new file mode 100644 index 00000000..b769c117 --- /dev/null +++ b/hacks/glx/bouncingcow.c @@ -0,0 +1,544 @@ +/* bouncingcow, Copyright (c) 2003-2006 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. + * + * Boing, boing, boing. Cow, cow, cow. + */ + +#define DEFAULTS "*delay: 30000 \n" \ + "*count: 1 \n" \ + "*showFPS: False \n" \ + "*wireframe: False \n" \ + +# define refresh_cow 0 +# define release_cow 0 +#define DEF_SPEED "1.0" +#define DEF_TEXTURE "(none)" + +#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) + +#include "xlockmore.h" +#include "rotator.h" +#include "gltrackball.h" +#include "xpm-ximage.h" +#include + +#ifdef USE_GL /* whole file */ + +#include "gllist.h" + +extern struct gllist + *cow_face, *cow_hide, *cow_hoofs, *cow_horns, *cow_tail, *cow_udder; + +static struct gllist **all_objs[] = { + &cow_face, &cow_hide, &cow_hoofs, &cow_horns, &cow_tail, &cow_udder +}; + +#define FACE 0 +#define HIDE 1 +#define HOOFS 2 +#define HORNS 3 +#define TAIL 4 +#define UDDER 5 + +typedef struct { + GLfloat x, y, z; + GLfloat ix, iy, iz; + GLfloat dx, dy, dz; + GLfloat ddx, ddy, ddz; + rotator *rot; + Bool spinner_p; +} floater; + +typedef struct { + GLXContext *glx_context; + trackball_state *trackball; + Bool button_down_p; + + GLuint *dlists; + GLuint texture; + + int nfloaters; + floater *floaters; + +} cow_configuration; + +static cow_configuration *bps = NULL; + +static GLfloat speed; +static const char *do_texture; + +static XrmOptionDescRec opts[] = { + { "-speed", ".speed", XrmoptionSepArg, 0 }, + {"-texture", ".texture", XrmoptionSepArg, 0 }, + {"+texture", ".texture", XrmoptionNoArg, "(none)" }, +}; + +static argtype vars[] = { + {&speed, "speed", "Speed", DEF_SPEED, t_Float}, + {&do_texture, "texture", "Texture", DEF_TEXTURE, t_String}, +}; + +ENTRYPOINT ModeSpecOpt cow_opts = {countof(opts), opts, countof(vars), vars, NULL}; + + +#define BOTTOM 28.0 + +static void +reset_floater (ModeInfo *mi, floater *f) +{ + cow_configuration *bp = &bps[MI_SCREEN(mi)]; + + f->y = -BOTTOM; + f->x = f->ix; + f->z = f->iz; + + /* Yes, I know I'm varying the force of gravity instead of varying the + launch velocity. That's intentional: empirical studies indicate + that it's way, way funnier that way. */ + + f->dy = 5.0; + f->dx = 0; + f->dz = 0; + + /* -0.18 max -0.3 top -0.4 middle -0.6 bottom */ + f->ddy = speed * (-0.6 + BELLRAND(0.45)); + f->ddx = 0; + f->ddz = 0; + + f->spinner_p = !(random() % (12 * bp->nfloaters)); + + if (! (random() % (30 * bp->nfloaters))) + { + f->dx = BELLRAND(1.8) * RANDSIGN(); + f->dz = BELLRAND(1.8) * RANDSIGN(); + } +} + + +static void +tick_floater (ModeInfo *mi, floater *f) +{ + cow_configuration *bp = &bps[MI_SCREEN(mi)]; + + if (bp->button_down_p) return; + + f->dx += f->ddx; + f->dy += f->ddy; + f->dz += f->ddz; + + f->x += f->dx * speed; + f->y += f->dy * speed; + f->z += f->dz * speed; + + if (f->y < -BOTTOM || + f->x < -BOTTOM*8 || f->x > BOTTOM*8 || + f->z < -BOTTOM*8 || f->z > BOTTOM*8) + reset_floater (mi, f); +} + + +/* Window management, etc + */ +ENTRYPOINT void +reshape_cow (ModeInfo *mi, int width, int height) +{ + GLfloat h = (GLfloat) height / (GLfloat) width; + + glViewport (0, 0, (GLint) width, (GLint) height); + + glMatrixMode(GL_PROJECTION); + glLoadIdentity(); + gluPerspective (30.0, 1/h, 1.0, 100); + + glMatrixMode(GL_MODELVIEW); + glLoadIdentity(); + gluLookAt( 0.0, 0.0, 30.0, + 0.0, 0.0, 0.0, + 0.0, 1.0, 0.0); + + glClear(GL_COLOR_BUFFER_BIT); +} + + +ENTRYPOINT Bool +cow_handle_event (ModeInfo *mi, XEvent *event) +{ + cow_configuration *bp = &bps[MI_SCREEN(mi)]; + + if (event->xany.type == ButtonPress && + event->xbutton.button == Button1) + { + bp->button_down_p = True; + gltrackball_start (bp->trackball, + event->xbutton.x, event->xbutton.y, + MI_WIDTH (mi), MI_HEIGHT (mi)); + return True; + } + else if (event->xany.type == ButtonRelease && + event->xbutton.button == Button1) + { + bp->button_down_p = False; + return True; + } + else if (event->xany.type == ButtonPress && + (event->xbutton.button == Button4 || + event->xbutton.button == Button5 || + event->xbutton.button == Button6 || + event->xbutton.button == Button7)) + { + gltrackball_mousewheel (bp->trackball, event->xbutton.button, 10, + !event->xbutton.state); + return True; + } + else if (event->xany.type == MotionNotify && + bp->button_down_p) + { + gltrackball_track (bp->trackball, + event->xmotion.x, event->xmotion.y, + MI_WIDTH (mi), MI_HEIGHT (mi)); + return True; + } + + return False; +} + + +/* Textures + */ + +static Bool +load_texture (ModeInfo *mi, const char *filename) +{ + Display *dpy = mi->dpy; + Visual *visual = mi->xgwa.visual; + Colormap cmap = mi->xgwa.colormap; + char buf[1024]; + XImage *image; + + if (MI_IS_WIREFRAME(mi)) + return False; + + if (!filename || + !*filename || + !strcasecmp (filename, "(none)")) + { + glDisable (GL_TEXTURE_2D); + return False; + } + + image = xpm_file_to_ximage (dpy, visual, cmap, filename); + + clear_gl_error(); + glTexImage2D (GL_TEXTURE_2D, 0, GL_RGBA, + image->width, image->height, 0, + GL_RGBA, + /* GL_UNSIGNED_BYTE, */ + GL_UNSIGNED_INT_8_8_8_8_REV, + image->data); + sprintf (buf, "texture: %.100s (%dx%d)", + filename, image->width, image->height); + check_gl_error(buf); + + glPixelStorei (GL_UNPACK_ALIGNMENT, 4); + glPixelStorei (GL_UNPACK_ROW_LENGTH, image->width); + + return True; +} + + +ENTRYPOINT void +init_cow (ModeInfo *mi) +{ + cow_configuration *bp; + int wire = MI_IS_WIREFRAME(mi); + int i; + Bool tex_p = False; + + if (!bps) { + bps = (cow_configuration *) + calloc (MI_NUM_SCREENS(mi), sizeof (cow_configuration)); + if (!bps) { + fprintf(stderr, "%s: out of memory\n", progname); + exit(1); + } + } + + bp = &bps[MI_SCREEN(mi)]; + + bp->glx_context = init_GL(mi); + + reshape_cow (mi, MI_WIDTH(mi), MI_HEIGHT(mi)); + + glShadeModel(GL_SMOOTH); + + glEnable(GL_DEPTH_TEST); + glEnable(GL_NORMALIZE); + glEnable(GL_CULL_FACE); + + if (!wire) + { + GLfloat pos[4] = {0.4, 0.2, 0.4, 0.0}; +/* GLfloat amb[4] = {0.0, 0.0, 0.0, 1.0};*/ + GLfloat amb[4] = {0.2, 0.2, 0.2, 1.0}; + GLfloat dif[4] = {1.0, 1.0, 1.0, 1.0}; + GLfloat spc[4] = {1.0, 1.0, 1.0, 1.0}; + + glEnable(GL_LIGHTING); + glEnable(GL_LIGHT0); + glEnable(GL_DEPTH_TEST); + glEnable(GL_CULL_FACE); + + glLightfv(GL_LIGHT0, GL_POSITION, pos); + glLightfv(GL_LIGHT0, GL_AMBIENT, amb); + glLightfv(GL_LIGHT0, GL_DIFFUSE, dif); + glLightfv(GL_LIGHT0, GL_SPECULAR, spc); + } + + bp->trackball = gltrackball_init (); + + bp->dlists = (GLuint *) calloc (countof(all_objs)+1, sizeof(GLuint)); + for (i = 0; i < countof(all_objs); i++) + bp->dlists[i] = glGenLists (1); + + tex_p = load_texture (mi, do_texture); + if (tex_p) + glBindTexture (GL_TEXTURE_2D, bp->texture); + + for (i = 0; i < countof(all_objs); i++) + { + GLfloat black[4] = {0, 0, 0, 1}; + const struct gllist *gll = *all_objs[i]; + + glNewList (bp->dlists[i], GL_COMPILE); + + glDisable (GL_TEXTURE_2D); + + if (i == HIDE) + { + GLfloat color[4] = {0.63, 0.43, 0.36, 1.00}; + if (tex_p) + { + /* if we have a texture, make the base color be white. */ + color[0] = color[1] = color[2] = 1.0; + + glEnable (GL_TEXTURE_2D); + + glTexGeni (GL_S, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR); + glTexGeni (GL_T, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR); + glTexEnvf (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + glEnable(GL_TEXTURE_GEN_S); + glEnable(GL_TEXTURE_GEN_T); + glEnable(GL_TEXTURE_2D); + + /* approximately line it up with ../images/earth.xpm */ + glMatrixMode (GL_TEXTURE); + glLoadIdentity(); + glTranslatef (0.45, 0.58, 0); + glScalef (0.08, 0.16, 1); + glRotatef (-5, 0, 0, 1); + glMatrixMode (GL_MODELVIEW); + } + glMaterialfv (GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, color); + glMaterialfv (GL_FRONT_AND_BACK, GL_SPECULAR, black); + glMaterialf (GL_FRONT_AND_BACK, GL_SHININESS, 128); + } + else if (i == TAIL) + { + GLfloat color[4] = {0.63, 0.43, 0.36, 1.00}; + glMaterialfv (GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, color); + glMaterialfv (GL_FRONT_AND_BACK, GL_SPECULAR, black); + glMaterialf (GL_FRONT_AND_BACK, GL_SHININESS, 128); + } + else if (i == UDDER) + { + GLfloat color[4] = {1.00, 0.53, 0.53, 1.00}; + glMaterialfv (GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, color); + glMaterialfv (GL_FRONT_AND_BACK, GL_SPECULAR, black); + glMaterialf (GL_FRONT_AND_BACK, GL_SHININESS, 128); + } + else if (i == HOOFS || i == HORNS) + { + GLfloat color[4] = {0.20, 0.20, 0.20, 1.00}; + GLfloat spec[4] = {0.30, 0.30, 0.30, 1.00}; + GLfloat shiny = 8.0; + glMaterialfv (GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, color); + glMaterialfv (GL_FRONT_AND_BACK, GL_SPECULAR, spec); + glMaterialf (GL_FRONT_AND_BACK, GL_SHININESS, shiny); + } + else if (i == FACE) + { + GLfloat color[4] = {0.10, 0.10, 0.10, 1.00}; + GLfloat spec[4] = {0.10, 0.10, 0.10, 1.00}; + GLfloat shiny = 8.0; + glMaterialfv (GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, color); + glMaterialfv (GL_FRONT_AND_BACK, GL_SPECULAR, spec); + glMaterialf (GL_FRONT_AND_BACK, GL_SHININESS, shiny); + } + else + { + GLfloat color[4] = {1.00, 1.00, 1.00, 1.00}; + GLfloat spec[4] = {1.00, 1.00, 1.00, 1.00}; + GLfloat shiny = 128.0; + glMaterialfv (GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, color); + glMaterialfv (GL_FRONT_AND_BACK, GL_SPECULAR, spec); + glMaterialf (GL_FRONT_AND_BACK, GL_SHININESS, shiny); + } + + renderList (gll, wire); + + glEndList (); + } + + bp->nfloaters = MI_COUNT (mi); + bp->floaters = (floater *) calloc (bp->nfloaters, sizeof (floater)); + + for (i = 0; i < bp->nfloaters; i++) + { + floater *f = &bp->floaters[i]; + f->rot = make_rotator (10.0, 0, 0, + 4, 0.05 * speed, + True); + if (bp->nfloaters == 2) + { + f->x = (i ? 6 : -6); + } + else if (i != 0) + { + double th = (i - 1) * M_PI*2 / (bp->nfloaters-1); + double r = 10; + f->x = r * cos(th); + f->z = r * sin(th); + } + + f->ix = f->x; + f->iy = f->y; + f->iz = f->z; + reset_floater (mi, f); + } +} + + +static void +draw_floater (ModeInfo *mi, floater *f) +{ + cow_configuration *bp = &bps[MI_SCREEN(mi)]; + GLfloat n; + double x, y, z; + + get_position (f->rot, &x, &y, &z, !bp->button_down_p); + + glPushMatrix(); + glTranslatef (f->x, f->y, f->z); + + gltrackball_rotate (bp->trackball); + + glRotatef (y * 360, 0.0, 1.0, 0.0); + if (f->spinner_p) + { + glRotatef (x * 360, 1.0, 0.0, 0.0); + glRotatef (z * 360, 0.0, 0.0, 1.0); + } + + n = 1.5; + if (bp->nfloaters > 99) n *= 0.05; + else if (bp->nfloaters > 25) n *= 0.18; + else if (bp->nfloaters > 9) n *= 0.3; + else if (bp->nfloaters > 1) n *= 0.7; + glScalef(n, n, n); + + glCallList (bp->dlists[FACE]); + mi->polygon_count += (*all_objs[FACE])->points / 3; + + glCallList (bp->dlists[HIDE]); + mi->polygon_count += (*all_objs[HIDE])->points / 3; + + glCallList (bp->dlists[HOOFS]); + mi->polygon_count += (*all_objs[HOOFS])->points / 3; + + glCallList (bp->dlists[HORNS]); + mi->polygon_count += (*all_objs[HORNS])->points / 3; + + glCallList (bp->dlists[TAIL]); + mi->polygon_count += (*all_objs[TAIL])->points / 3; + + glCallList (bp->dlists[UDDER]); + mi->polygon_count += (*all_objs[UDDER])->points / 3; + + glPopMatrix(); +} + + + +ENTRYPOINT void +draw_cow (ModeInfo *mi) +{ + cow_configuration *bp = &bps[MI_SCREEN(mi)]; + Display *dpy = MI_DISPLAY(mi); + Window window = MI_WINDOW(mi); + int i; + + if (!bp->glx_context) + return; + + glXMakeCurrent(MI_DISPLAY(mi), MI_WINDOW(mi), *(bp->glx_context)); + + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + + glPushMatrix (); + glRotatef(current_device_rotation(), 0, 0, 1); + + glScalef (0.5, 0.5, 0.5); + + mi->polygon_count = 0; + +# if 0 + { + floater F; + F.x = F.y = F.z = 0; + F.dx = F.dy = F.dz = 0; + F.ddx = F.ddy = F.ddz = 0; + F.rot = make_rotator (0, 0, 0, 1, 0, False); + glScalef(2,2,2); + draw_floater (mi, &F); + } +# else + for (i = 0; i < bp->nfloaters; i++) + { + /* "Don't kid yourself, Jimmy. If a cow ever got the chance, + he'd eat you and everyone you care about!" + -- Troy McClure in "Meat and You: Partners in Freedom" + */ + floater *f = &bp->floaters[i]; + draw_floater (mi, f); + tick_floater (mi, f); + } +# endif + + glPopMatrix (); + + if (mi->fps_p) do_fps (mi); + glFinish(); + + glXSwapBuffers(dpy, window); +} + +XSCREENSAVER_MODULE_2 ("BouncingCow", bouncingcow, cow) + +#endif /* USE_GL */ diff --git a/hacks/glx/bouncingcow.man b/hacks/glx/bouncingcow.man new file mode 100644 index 00000000..516d1de3 --- /dev/null +++ b/hacks/glx/bouncingcow.man @@ -0,0 +1,73 @@ +.TH XScreenSaver 1 "" "X Version 11" +.SH NAME +bouncingcow - a happy cow on a trampoline in 3D. Moo. +.SH SYNOPSIS +.B bouncingcow +[\-display \fIhost:display.screen\fP] +[\-visual \fIvisual\fP] +[\-window] +[\-root] +[\-delay \fInumber\fP] +[\-speed \fInumber\fP] +[\-count \fInumber\fP] +[\-texture \fIfilename\fP] +[\-wireframe] +[\-fps] +.SH DESCRIPTION +It's very silly. +.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 \-speed \fInumber\fP +How fast the cow bounces. Larger for faster. Default: 1.0. +.TP 8 +.B \-count \fInumber\fP +How many cows! Default 1. +.TP 8 +.B \-texture \fIfilename\fP +An image file to paint on the cow's hide. + +Note that on most systems, GL textures must have dimensions that are a +power of two. +.TP 8 +.B \-wireframe +Render in wireframe instead of solid. +.TP 8 +.B \-fps +Display the current frame rate, CPU load, and polygon count. +.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 2003 by Jamie Zawinski. Moo. 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. +Moo. No representations are made about the suitability of this +software for any purpose. It is provided "as is" without express or +implied warranty. Moo. +.SH AUTHOR +Jamie Zawinski + diff --git a/hacks/glx/boxed.c b/hacks/glx/boxed.c new file mode 100644 index 00000000..6a2d79a6 --- /dev/null +++ b/hacks/glx/boxed.c @@ -0,0 +1,1315 @@ +/* boxed --- 3D bouncing balls that explode */ + +#if 0 +static const char sccsid[] = "@(#)boxed.c 0.9 01/09/26 xlockmore"; +#endif + +/*- + * Permission to use, copy, modify, and distribute this software and its + * documentation for any purpose and without fee is hereby granted, + * provided that the above copyright notice appear in all copies and that + * both that copyright notice and this permission notice appear in + * supporting documentation. + * + * This file is provided AS IS with no warranties of any kind. The author + * shall have no liability with respect to the infringement of copyrights, + * trade secrets or any patents by this file or any part thereof. In no + * event will the author be liable for any lost revenue or profits or + * other special, indirect and consequential damages. + * + * Revision History: + * + * 2001: Written by Sander van Grieken + * as an OpenGL screensaver for the xscreensaver package. + * Lots of hardcoded values still in place. Also, there are some + * copy/paste leftovers from the gears hack. opts don't work. + * + * 2005: opts work. added options -balls, -ballsize, -explosion + * + * 2006: opts work. added option -decay + * + * 2008: opts work. added option -momentum + * + */ + +#include "boxed.h" + +/* +**---------------------------------------------------------------------------- +** Defines +**---------------------------------------------------------------------------- +*/ + +#ifdef STANDALONE +# define DEFAULTS "*delay: 20000 \n" \ + "*showFPS: False \n" \ + "*wireframe: False \n" + +# define refresh_boxed 0 +# define boxed_handle_event 0 +# include "xlockmore.h" /* from the xscreensaver distribution */ +#else /* !STANDALONE */ +# include "xlock.h" /* from the xlockmore distribution */ +#endif /* !STANDALONE */ + +#ifdef USE_GL + +# define DEF_SPEED "0.5" +# define DEF_BALLS "25" +# define DEF_BALLSIZE "2.0" +# define DEF_EXPLOSION "15.0" +# define DEF_DECAY "0.07" +# define DEF_MOMENTUM "0.6" + +#undef countof +#define countof(x) (int)(sizeof((x))/sizeof((*x))) +#undef rnd +#define rnd() (frand(1.0)) + +static GLfloat speed; /* jwz -- overall speed factor applied to all motion */ +static int cfg_balls; +static GLfloat cfg_ballsize; +static GLfloat cfg_explosion; +static GLfloat cfg_decay; +static GLfloat cfg_momentum; + + +static XrmOptionDescRec opts[] = { + {"-speed", ".boxed.speed", XrmoptionSepArg, 0}, + {"-balls", ".boxed.balls", XrmoptionSepArg, 0}, + {"-ballsize", ".boxed.ballsize", XrmoptionSepArg, 0}, + {"-explosion", ".boxed.explosion", XrmoptionSepArg, 0}, + {"-decay", ".boxed.decay", XrmoptionSepArg, 0}, + {"-momentum", ".boxed.momentum", XrmoptionSepArg, 0}, +}; + +static argtype vars[] = { + {&speed, "speed", "Speed", DEF_SPEED, t_Float}, + {&cfg_balls, "balls", "Balls", DEF_BALLS, t_Int}, + {&cfg_ballsize, "ballsize", "Ball Size", DEF_BALLSIZE, t_Float}, + {&cfg_explosion, "explosion", "Explosion", DEF_EXPLOSION, t_Float}, + {&cfg_decay, "decay", "Explosion Decay", DEF_DECAY, t_Float}, + {&cfg_momentum, "momentum", "Explosion Momentum", DEF_MOMENTUM, t_Float}, +}; + +ENTRYPOINT ModeSpecOpt boxed_opts = {countof(opts), opts, countof(vars), vars, NULL}; + +#ifdef USE_MODULES + +ModStruct boxed_description = { + "boxed", "init_boxed", "draw_boxed", "release_boxed", + "draw_boxed", "init_boxed", NULL, &boxed_opts, + 1000, 1, 2, 1, 4, 1.0, "", + "Shows GL's boxed balls", 0, NULL}; + +#endif + +#define BOOL int +#define TRUE 1 +#define FALSE 0 + +/* camera */ +#define CAM_HEIGHT 100.0f +#define CAMDISTANCE_MIN 20.0 +#define CAMDISTANCE_MAX 150.0 +#define CAMDISTANCE_SPEED 1.5 + +/* rendering the sphere */ +#define MESH_SIZE 10 +#define SPHERE_VERTICES (2+MESH_SIZE*MESH_SIZE*2) +#define SPHERE_INDICES ((MESH_SIZE*4 + MESH_SIZE*4*(MESH_SIZE-1))*3) + +/* +**----------------------------------------------------------------------------- +** Typedefs +**----------------------------------------------------------------------------- +*/ + +typedef struct { + GLfloat x; + GLfloat y; + GLfloat z; +} vectorf; + +typedef struct { + vectorf loc; + vectorf dir; + vectorf color; + float radius; + BOOL bounced; + int offside; + BOOL justcreated; +} ball; + +typedef struct { + int num_balls; + float ballsize; + float explosion; + ball *balls; +} ballman; + +typedef struct { + vectorf loc; + vectorf dir; + BOOL far; + BOOL gone; +} tri; + +typedef struct { + int num_tri; + int lifetime; + float scalefac; + float explosion; + float decay; + float momentum; + vectorf color; + tri *tris; + GLint *indices; + vectorf *normals; + vectorf *vertices; +} triman; + +typedef struct { + int numballs; + float ballsize; + float explosion; + float decay; + float momentum; + BOOL textures; + BOOL transparent; + float camspeed; +} boxed_config; + + +typedef struct { + float cam_x_speed, cam_z_speed, cam_y_speed; + boxed_config config; + float tic; + float camtic; + vectorf spherev[SPHERE_VERTICES]; + GLint spherei[SPHERE_INDICES]; + ballman bman; + triman *tman; + GLXContext *glx_context; + GLuint listobjects; + GLuint gllists[3]; + int list_polys[3]; + Window window; + BOOL stop; + char *tex1; +} boxedstruct; + +#define GLL_PATTERN 0 +#define GLL_BALL 1 +#define GLL_BOX 2 + +/* +**---------------------------------------------------------------------------- +** Local Variables +**---------------------------------------------------------------------------- +*/ + +static boxedstruct *boxed = NULL; + + +/* +**---------------------------------------------------------------------------- +** Functions +**---------------------------------------------------------------------------- +*/ + +/* + * Add 2 vectors + */ +static inline void addvectors(vectorf *dest, vectorf *s1, vectorf *s2) +{ + dest->x = s1->x + s2->x; + dest->y = s1->y + s2->y; + dest->z = s1->z + s2->z; +} + +/* + * Sub 2 vectors + */ +static inline void subvectors(vectorf *dest, vectorf* s1, vectorf *s2) +{ + dest->x = s1->x - s2->x; + dest->y = s1->y - s2->y; + dest->z = s1->z - s2->z; +} + +/* + * Multiply vector with scalar (scale vector) + */ +static inline void scalevector(vectorf *dest, vectorf *source, GLfloat sc) +{ + dest->x = source->x * sc; + dest->y = source->y * sc; + dest->z = source->z * sc; +} + +/* + * Copy vector + */ +static inline void copyvector(vectorf *dest, vectorf* source) +{ + dest->x = source->x; + dest->y = source->y; + dest->z = source->z; +} + + +static inline GLfloat +dotproduct(vectorf * v1, vectorf * v2) +{ + return v1->x * v2->x + v1->y * v2->y + v1->z * v2->z; +} + +static inline GLfloat +squaremagnitude(vectorf * v) +{ + return v->x * v->x + v->y * v->y + v->z * v->z; +} + +static inline GLfloat +squaremagnitudehorz(vectorf * v) +{ + return v->x * v->x + v->z * v->z; +} + + + +/* + * Generate the Sphere data + * + * Input: + */ + +static void generatesphere(boxedstruct *gp) +{ + float dj = M_PI/(MESH_SIZE+1.0f); + float di = M_PI/MESH_SIZE; + int v; /* vertex offset */ + int ind; /* indices offset */ + int i,j,si; + GLfloat r_y_plane, h_y_plane; + vectorf *spherev; + GLint *spherei; + + /* + * generate the sphere data + * vertices 0 and 1 are the north and south poles + */ + + spherei = gp->spherei; + spherev = gp->spherev; + + spherev[0].x = 0.0f; spherev[0].y =1.0f; spherev[0].z = 0.0f; + spherev[1].x = 0.0f; spherev[1].y =-1.0f; spherev[1].z = 0.0f; + + for (j=0; jloc.x = 5-10*rnd(); + newball->loc.y = 35+20*rnd(); + newball->loc.z = 5-10*rnd(); + newball->dir.x = (0.5f-rnd()) * speed; + newball->dir.y = 0.0; + newball->dir.z = (0.5-rnd()) * speed; + newball->offside = 0; + newball->bounced = FALSE; + newball->radius = cfg_ballsize; + while (r+g+b < 1.8f ) { + newball->color.x = r=rnd(); + newball->color.y = g=rnd(); + newball->color.z = b=rnd(); + } + newball->justcreated = TRUE; +} + +/* Update position of each ball */ + +static void updateballs(ballman *bman) +{ + register int b,j; + vectorf dvect,richting,relspeed,influence; + GLfloat squaredist; + + for (b=0;bnum_balls;b++) { + + GLfloat gravity = 0.30f * speed; + + /* apply gravity */ + bman->balls[b].dir.y -= gravity; + /* apply movement */ + addvectors(&bman->balls[b].loc,&bman->balls[b].loc,&bman->balls[b].dir); + /* boundary check */ + if (bman->balls[b].loc.y < bman->balls[b].radius) { /* ball onder bodem? (bodem @ y=0) */ + if ((bman->balls[b].loc.x < -95.0) || + (bman->balls[b].loc.x > 95.0) || + (bman->balls[b].loc.z < -95.0) || + (bman->balls[b].loc.z > 95.0)) { + if (bman->balls[b].loc.y < -1000.0) + createball(&bman->balls[b]); + } else { + bman->balls[b].loc.y = bman->balls[b].radius + (bman->balls[b].radius - bman->balls[b].loc.y); + bman->balls[b].dir.y = -bman->balls[b].dir.y; + if (bman->balls[b].offside) { + bman->balls[b].bounced = TRUE; /* temporary disable painting ball */ + scalevector(&bman->balls[b].dir,&bman->balls[b].dir,0.80f); + if (squaremagnitude(&bman->balls[b].dir) < 0.08f) { + createball(&bman->balls[b]); + } + if (squaremagnitudehorz(&bman->balls[b].dir) < 0.005f) { + createball(&bman->balls[b]); + } + } + } + + } + if (!bman->balls[b].offside) { + if (bman->balls[b].loc.x - bman->balls[b].radius < -20.0f) { /* x ondergrens */ + if (bman->balls[b].loc.y > 41+bman->balls[b].radius) bman->balls[b].offside=1; + else { + bman->balls[b].dir.x = -bman->balls[b].dir.x; + bman->balls[b].loc.x = -20.0f + bman->balls[b].radius; + } + } + if (bman->balls[b].loc.x + bman->balls[b].radius > 20.0f) { /* x bovengrens */ + if (bman->balls[b].loc.y > 41+bman->balls[b].radius) bman->balls[b].offside=1; + else { + bman->balls[b].dir.x = -bman->balls[b].dir.x; + bman->balls[b].loc.x = 20.0f - bman->balls[b].radius; + } + } + if (bman->balls[b].loc.z - bman->balls[b].radius < -20.0f) { /* z ondergrens */ + if (bman->balls[b].loc.y > 41+bman->balls[b].radius) bman->balls[b].offside=1; + else { + bman->balls[b].dir.z = -bman->balls[b].dir.z; + bman->balls[b].loc.z = -20.0f + bman->balls[b].radius; + } + } + if (bman->balls[b].loc.z + bman->balls[b].radius > 20.0f) { /* z bovengrens */ + if (bman->balls[b].loc.y > 41+bman->balls[b].radius) bman->balls[b].offside=1; + else { + bman->balls[b].dir.z = -bman->balls[b].dir.z; + bman->balls[b].loc.z = 20.0f - bman->balls[b].radius; + } + } + } /* end if !offside */ + + /* check voor stuiteren */ + for (j=b+1;jnum_balls;j++) { + squaredist = (bman->balls[b].radius * bman->balls[b].radius) + (bman->balls[j].radius * bman->balls[j].radius); + subvectors(&dvect,&bman->balls[b].loc,&bman->balls[j].loc); + if ( squaremagnitude(&dvect) < squaredist ) { /* balls b and j touch */ + subvectors(&richting,&bman->balls[j].loc,&bman->balls[b].loc); + subvectors(&relspeed,&bman->balls[b].dir,&bman->balls[j].dir); + /* calc mutual influence direction and magnitude */ + scalevector(&influence,&richting,(dotproduct(&richting,&relspeed)/squaremagnitude(&richting))); + + subvectors(&bman->balls[b].dir,&bman->balls[b].dir,&influence); + addvectors(&bman->balls[j].dir,&bman->balls[j].dir,&influence); + addvectors(&bman->balls[b].loc,&bman->balls[b].loc,&bman->balls[b].dir); + addvectors(&bman->balls[j].loc,&bman->balls[j].loc,&bman->balls[j].dir); + + subvectors(&dvect,&bman->balls[b].loc,&bman->balls[j].loc); + while (squaremagnitude(&dvect) < squaredist) { + addvectors(&bman->balls[b].loc,&bman->balls[b].loc,&bman->balls[b].dir); + addvectors(&bman->balls[j].loc,&bman->balls[j].loc,&bman->balls[j].dir); + subvectors(&dvect,&bman->balls[b].loc,&bman->balls[j].loc); + } + } + } /* end for j */ + } /* end for b */ +} + + +/* +* explode ball into triangles +*/ + +static void createtrisfromball(triman* tman, vectorf *spherev, GLint *spherei, int ind_num, ball *b) +{ + int pos; + float explosion; + float momentum; + float scale; + register int i; + vectorf avgdir,dvect,mvect; + + tman->scalefac = b->radius; + copyvector(&tman->color,&b->color); + explosion = 1.0f + tman->explosion * 2.0 * rnd(); + momentum = tman->momentum; + + tman->num_tri = ind_num/3; + + /* reserveer geheugen voor de poly's in een bal */ + + tman->tris = (tri *)malloc(tman->num_tri * sizeof(tri)); + tman->vertices = (vectorf *)malloc(ind_num * sizeof(vectorf)); + tman->normals = (vectorf *)malloc(ind_num/3 * sizeof(vectorf)); + + for (i=0; i<(tman->num_tri); i++) { + tman->tris[i].far = FALSE; + tman->tris[i].gone = FALSE; + pos = i * 3; + /* kopieer elke poly apart naar een tri structure */ + copyvector(&tman->vertices[pos+0],&spherev[spherei[pos+0]]); + copyvector(&tman->vertices[pos+1],&spherev[spherei[pos+1]]); + copyvector(&tman->vertices[pos+2],&spherev[spherei[pos+2]]); + /* Calculate average direction of shrapnel */ + addvectors(&avgdir,&tman->vertices[pos+0],&tman->vertices[pos+1]); + addvectors(&avgdir,&avgdir,&tman->vertices[pos+2]); + scalevector(&avgdir,&avgdir,0.33333); + + /* should normalize first, NYI */ + copyvector(&tman->normals[i],&avgdir); + + /* copy de lokatie */ + addvectors(&tman->tris[i].loc,&b->loc,&avgdir); + /* en translate alle triangles terug naar hun eigen oorsprong */ + tman->vertices[pos+0].x -= avgdir.x; + tman->vertices[pos+0].y -= avgdir.y; + tman->vertices[pos+0].z -= avgdir.z; + tman->vertices[pos+1].x -= avgdir.x; + tman->vertices[pos+1].y -= avgdir.y; + tman->vertices[pos+1].z -= avgdir.z; + tman->vertices[pos+2].x -= avgdir.x; + tman->vertices[pos+2].y -= avgdir.y; + tman->vertices[pos+2].z -= avgdir.z; + /* alwaar opschaling plaatsvindt */ + scale = b->radius * 2; + scalevector(&tman->vertices[pos+0],&tman->vertices[pos+0],scale); + scalevector(&tman->vertices[pos+1],&tman->vertices[pos+1],scale); + scalevector(&tman->vertices[pos+2],&tman->vertices[pos+2],scale); + + tman->vertices[pos+0].x += avgdir.x; + tman->vertices[pos+0].y += avgdir.y; + tman->vertices[pos+0].z += avgdir.z; + tman->vertices[pos+1].x += avgdir.x; + tman->vertices[pos+1].y += avgdir.y; + tman->vertices[pos+1].z += avgdir.z; + tman->vertices[pos+2].x += avgdir.x; + tman->vertices[pos+2].y += avgdir.y; + tman->vertices[pos+2].z += avgdir.z; + + /* bereken nieuwe richting */ + scalevector(&tman->tris[i].dir,&avgdir,explosion); + dvect.x = (0.1f - 0.2f*rnd()); + dvect.y = (0.15f - 0.3f*rnd()); + dvect.z = (0.1f - 0.2f*rnd()); + addvectors(&tman->tris[i].dir,&tman->tris[i].dir,&dvect); + + /* add ball's momentum to each piece of the exploded ball */ + mvect.x = b->dir.x * momentum; + mvect.y = 0; + mvect.z = b->dir.z * momentum; + addvectors(&tman->tris[i].dir,&tman->tris[i].dir,&mvect); + } +} + + +/* +* update position of each tri +*/ + +static void updatetris(triman *t) +{ + int b; + GLfloat xd,zd; + + for (b=0;bnum_tri;b++) { + /* the exploded triangles disappear over time */ + if (rnd() < t->decay) { t->tris[b].gone = TRUE; } + /* apply gravity */ + t->tris[b].dir.y -= (0.1f * speed); + /* apply movement */ + addvectors(&t->tris[b].loc,&t->tris[b].loc,&t->tris[b].dir); + /* boundary check */ + if (t->tris[b].far) continue; + if (t->tris[b].loc.y < 0) { /* onder bodem ? */ + if ((t->tris[b].loc.x > -95.0f) & + (t->tris[b].loc.x < 95.0f) & + (t->tris[b].loc.z > -95.0f) & + (t->tris[b].loc.z < 95.0f)) { /* in veld */ + t->tris[b].dir.y = -(t->tris[b].dir.y); + t->tris[b].loc.y = -t->tris[b].loc.y; + scalevector(&t->tris[b].dir,&t->tris[b].dir,0.80f); /* dampening */ + } + else { + t->tris[b].far = TRUE; + continue; + } + } + + if ((t->tris[b].loc.x > -21.0f) & + (t->tris[b].loc.x < 21.0f) & + (t->tris[b].loc.z > -21.0f) & + (t->tris[b].loc.z < 21.0f)) { /* in box? */ + + xd = zd = 999.0f; /* big */ + if ((t->tris[b].loc.x > -21.0f) & + (t->tris[b].loc.x < 0)) { + xd = t->tris[b].loc.x + 21.0f; + } + if ((t->tris[b].loc.x < 21.0f) & + (t->tris[b].loc.x > 0)) { + xd = 21.0f - t->tris[b].loc.x; + } + if ((t->tris[b].loc.z > -21.0f) & + (t->tris[b].loc.z < 0)) { + zd = t->tris[b].loc.z + 21.0f; + } + if ((t->tris[b].loc.z < 21.0f) & + (t->tris[b].loc.z > 0)) { + zd = 21.0f - t->tris[b].loc.z; + } + if (xd < zd) { + /* bounce x */ + if (t->tris[b].dir.x < 0) + t->tris[b].loc.x += (21.0f - t->tris[b].loc.x); + else + t->tris[b].loc.x += (-21.0f - t->tris[b].loc.x); + t->tris[b].dir.x = -t->tris[b].dir.x; + } else { + /* bounce z */ + if (t->tris[b].dir.z < 0) + t->tris[b].loc.z += (21.0f - t->tris[b].loc.z); + else + t->tris[b].loc.z += (-21.0f - t->tris[b].loc.z); + t->tris[b].dir.z = -t->tris[b].dir.z; + } + + } + } /* end for b */ +} + + +/* + * free memory allocated by a tri manager + */ +static void freetris(triman *t) +{ + if (!t) return; + if (t->tris) free(t->tris); + if (t->vertices) free(t->vertices); + if (t->normals) free(t->normals); + t->tris = NULL; + t->vertices = NULL; + t->normals = NULL; + t->num_tri = 0; + t->lifetime = 0; +} + + +/* + *load defaults in config structure + */ +static void setdefaultconfig(boxed_config *config) +{ + cfg_balls = MAX(3,MIN(40,cfg_balls)); + cfg_ballsize = MAX(1.0f,MIN(5.0f,cfg_ballsize)); + cfg_explosion = MAX(0.0f,MIN(50.0f,cfg_explosion)); + cfg_decay = MAX(0.0f,MIN(1.0f,cfg_decay)); + cfg_momentum = MAX(0.0f,MIN(1.0f,cfg_momentum)); + + config->numballs = cfg_balls; + config->textures = TRUE; + config->transparent = FALSE; + config->explosion = cfg_explosion; + config->decay = cfg_decay; + config->momentum = cfg_momentum; + config->ballsize = cfg_ballsize; + config->camspeed = 35.0f; +} + + +/* + * draw bottom + */ +static int drawfilledbox(boxedstruct *boxed, int wire) +{ + /* draws texture filled box, + top is drawn using the entire texture, + the sides are drawn using the edge of the texture + */ + int polys = 0; + + /* front */ + glBegin(wire ? GL_LINE_LOOP : GL_QUADS); + glTexCoord2f(0,1); + glVertex3f(-1.0,1.0,1.0); + glTexCoord2f(1,1); + glVertex3f(1.0,1.0,1.0); + glTexCoord2f(1,1); + glVertex3f(1.0,-1.0,1.0); + glTexCoord2f(0,1); + glVertex3f(-1.0,-1.0,1.0); + polys++; + /* rear */ + glTexCoord2f(0,1); + glVertex3f(1.0,1.0,-1.0); + glTexCoord2f(1,1); + glVertex3f(-1.0,1.0,-1.0); + glTexCoord2f(1,1); + glVertex3f(-1.0,-1.0,-1.0); + glTexCoord2f(0,1); + glVertex3f(1.0,-1.0,-1.0); + polys++; + /* left */ + glTexCoord2f(1,1); + glVertex3f(-1.0,1.0,1.0); + glTexCoord2f(1,1); + glVertex3f(-1.0,-1.0,1.0); + glTexCoord2f(0,1); + glVertex3f(-1.0,-1.0,-1.0); + glTexCoord2f(0,1); + glVertex3f(-1.0,1.0,-1.0); + polys++; + /* right */ + glTexCoord2f(0,1); + glVertex3f(1.0,1.0,1.0); + glTexCoord2f(1,1); + glVertex3f(1.0,1.0,-1.0); + glTexCoord2f(1,1); + glVertex3f(1.0,-1.0,-1.0); + glTexCoord2f(0,1); + glVertex3f(1.0,-1.0,1.0); + polys++; + /* top */ + glTexCoord2f(0.0,0.0); + glVertex3f(-1.0,1.0,1.0); + glTexCoord2f(0.0,1.0); + glVertex3f(-1.0,1.0,-1.0); + glTexCoord2f(1.0,1.0); + glVertex3f(1.0,1.0,-1.0); + glTexCoord2f(1.0,0.0); + glVertex3f(1.0,1.0,1.0); + polys++; + /* bottom */ + glTexCoord2f(0,0); + glVertex3f(-1.0,-1.0,1.0); + glTexCoord2f(0,1); + glVertex3f(-1.0,-1.0,-1.0); + glTexCoord2f(1,1); + glVertex3f(1.0,-1.0,-1.0); + glTexCoord2f(1,0); + glVertex3f(1.0,-1.0,1.0); + polys++; + glEnd(); + + return polys; +} + + +/* + * Draw a box made of lines + */ +static int drawbox(boxedstruct *boxed) +{ + int polys = 0; + /* top */ + glBegin(GL_LINE_STRIP); + glVertex3f(-1.0,1.0,1.0); + glVertex3f(-1.0,1.0,-1.0); polys++; + glVertex3f(1.0,1.0,-1.0); polys++; + glVertex3f(1.0,1.0,1.0); polys++; + glVertex3f(-1.0,1.0,1.0); polys++; + glEnd(); + /* bottom */ + glBegin(GL_LINE_STRIP); + glVertex3f(-1.0,-1.0,1.0); + glVertex3f(1.0,-1.0,1.0); polys++; + glVertex3f(1.0,-1.0,-1.0); polys++; + glVertex3f(-1.0,-1.0,-1.0); polys++; + glVertex3f(-1.0,-1.0,1.0); polys++; + glEnd(); + /* connect top & bottom */ + glBegin(GL_LINES); + glVertex3f(-1.0,1.0,1.0); + glVertex3f(-1.0,-1.0,1.0); polys++; + glVertex3f(1.0,1.0,1.0); + glVertex3f(1.0,-1.0,1.0); polys++; + glVertex3f(1.0,1.0,-1.0); + glVertex3f(1.0,-1.0,-1.0); polys++; + glVertex3f(-1.0,1.0,-1.0); + glVertex3f(-1.0,-1.0,-1.0); polys++; + glEnd(); + return polys; +} + + + +/* + * Draw ball + */ +static int drawball(boxedstruct *gp, ball *b, int wire) +{ + int polys = 0; + int i,pos,cnt; + GLint *spherei = gp->spherei; + vectorf *spherev = gp->spherev; + GLfloat col[3]; + + glPushMatrix(); + + glTranslatef(b->loc.x,b->loc.y,b->loc.z); + glScalef(b->radius,b->radius,b->radius); + glColor3f(b->color.x,b->color.y,b->color.z); + col[0] = b->color.x; + col[1] = b->color.y; + col[2] = b->color.z; + glMaterialfv(GL_FRONT, GL_DIFFUSE, col); + col[0] *= 0.5; + col[1] *= 0.5; + col[2] *= 0.5; + glMaterialfv(GL_FRONT, GL_EMISSION,col); + + if (!gp->gllists[GLL_BALL]) { + glNewList(gp->listobjects + GLL_BALL,GL_COMPILE); + cnt = SPHERE_INDICES/3; + for (i=0; ilist_polys[GLL_BALL]++; + glVertex3f(spherev[spherei[pos+1]].x,spherev[spherei[pos+1]].y,spherev[spherei[pos+1]].z); + glNormal3f(spherev[spherei[pos+2]].x,spherev[spherei[pos+2]].y,spherev[spherei[pos+2]].z); + glVertex3f(spherev[spherei[pos+2]].x,spherev[spherei[pos+2]].y,spherev[spherei[pos+2]].z); + gp->list_polys[GLL_BALL]++; + glEnd(); + } + glEndList(); + gp->gllists[GLL_BALL] = 1; + } else { + glCallList(gp->listobjects + GLL_BALL); + polys += gp->list_polys[GLL_BALL]; + } + + glPopMatrix(); + return polys; +} + + +/* + * Draw all triangles in triman + */ +static int drawtriman(triman *t, int wire) +{ + int polys = 0; + int i,pos; + vectorf *spherev = t->vertices; + GLfloat col[3]; + + glPushMatrix(); + glColor3f(t->color.x,t->color.y,t->color.z); + col[0] = t->color.x; + col[1] = t->color.y; + col[2] = t->color.z; + glMaterialfv(GL_FRONT, GL_DIFFUSE, col); + col[0] *= 0.3; + col[1] *= 0.3; + col[2] *= 0.3; + glMaterialfv(GL_FRONT, GL_EMISSION,col); + + for (i=0; inum_tri; i++) { + if (t->tris[i].gone == TRUE) { continue; } + pos = i*3; + glPushMatrix(); + glTranslatef(t->tris[i].loc.x,t->tris[i].loc.y,t->tris[i].loc.z); + glBegin(wire ? GL_LINE_LOOP : GL_TRIANGLES); + glNormal3f(t->normals[i].x,t->normals[i].y,t->normals[i].z); + glVertex3f(spherev[pos+0].x,spherev[pos+0].y,spherev[pos+0].z); + glVertex3f(spherev[pos+1].x,spherev[pos+1].y,spherev[pos+1].z); + glVertex3f(spherev[pos+2].x,spherev[pos+2].y,spherev[pos+2].z); + polys++; + glEnd(); + glPopMatrix(); + } + glPopMatrix(); + return polys; +} + +/* + * draw floor pattern + */ +static int drawpattern(boxedstruct *gp) +{ + int polys = 0; + if (!gp->gllists[GLL_PATTERN]) { + glNewList(gp->listobjects + GLL_PATTERN, GL_COMPILE); + + glBegin(GL_LINE_STRIP); + glVertex3f(-25.0f, 0.0f, 35.0f); + glVertex3f(-15.0f, 0.0f, 35.0f); gp->list_polys[GLL_PATTERN]++; + glVertex3f(-5.0f, 0.0f, 25.0f); gp->list_polys[GLL_PATTERN]++; + glVertex3f(5.0f, 0.0f, 25.0f); gp->list_polys[GLL_PATTERN]++; + glVertex3f(15.0f, 0.0f, 35.0f); gp->list_polys[GLL_PATTERN]++; + glVertex3f(25.0f, 0.0f, 35.0f); gp->list_polys[GLL_PATTERN]++; + glVertex3f(35.0f, 0.0f, 25.0f); gp->list_polys[GLL_PATTERN]++; + glVertex3f(35.0f, 0.0f, 15.0f); gp->list_polys[GLL_PATTERN]++; + glVertex3f(25.0f, 0.0f, 5.0f); gp->list_polys[GLL_PATTERN]++; + glVertex3f(25.0f, 0.0f, -5.0f); gp->list_polys[GLL_PATTERN]++; + glVertex3f(35.0f, 0.0f, -15.0f); gp->list_polys[GLL_PATTERN]++; + glVertex3f(35.0f, 0.0f, -25.0f); gp->list_polys[GLL_PATTERN]++; + glVertex3f(25.0f, 0.0f, -35.0f); gp->list_polys[GLL_PATTERN]++; + glVertex3f(15.0f, 0.0f,-35.0f); gp->list_polys[GLL_PATTERN]++; + glVertex3f(5.0f, 0.0f, -25.0f); gp->list_polys[GLL_PATTERN]++; + glVertex3f(-5.0f, 0.0f, -25.0f); gp->list_polys[GLL_PATTERN]++; + glVertex3f(-15.0f, 0.0f,-35.0f); gp->list_polys[GLL_PATTERN]++; + glVertex3f(-25.0f, 0.0f,-35.0f); gp->list_polys[GLL_PATTERN]++; + glVertex3f(-35.0f, 0.0f, -25.0f); gp->list_polys[GLL_PATTERN]++; + glVertex3f(-35.0f, 0.0f, -15.0f); gp->list_polys[GLL_PATTERN]++; + glVertex3f(-25.0f, 0.0f, -5.0f); gp->list_polys[GLL_PATTERN]++; + glVertex3f(-25.0f, 0.0f, 5.0f); gp->list_polys[GLL_PATTERN]++; + glVertex3f(-35.0f, 0.0f, 15.0f); gp->list_polys[GLL_PATTERN]++; + glVertex3f(-35.0f, 0.0f, 25.0f); gp->list_polys[GLL_PATTERN]++; + glVertex3f(-25.0f, 0.0f, 35.0f); gp->list_polys[GLL_PATTERN]++; + glEnd(); + + glBegin(GL_LINE_STRIP); + glVertex3f(-5.0f, 0.0f, 15.0f); + glVertex3f(5.0f, 0.0f, 15.0f); gp->list_polys[GLL_PATTERN]++; + glVertex3f(15.0f, 0.0f, 5.0f); gp->list_polys[GLL_PATTERN]++; + glVertex3f(15.0f, 0.0f, -5.0f); gp->list_polys[GLL_PATTERN]++; + glVertex3f(5.0f, 0.0f, -15.0f); gp->list_polys[GLL_PATTERN]++; + glVertex3f(-5.0f, 0.0f, -15.0f); gp->list_polys[GLL_PATTERN]++; + glVertex3f(-15.0f, 0.0f, -5.0f); gp->list_polys[GLL_PATTERN]++; + glVertex3f(-15.0f, 0.0f, 5.0f); gp->list_polys[GLL_PATTERN]++; + glVertex3f(-5.0f, 0.0f, 15.0f); gp->list_polys[GLL_PATTERN]++; + glEnd(); + + glEndList(); + gp->gllists[GLL_PATTERN] = 1; + } else { + glCallList(gp->listobjects + GLL_PATTERN); + polys += gp->list_polys[GLL_PATTERN]; + } + + return polys; +} + + +/* + * main rendering loop + */ +static void draw(ModeInfo * mi) +{ + boxedstruct *gp = &boxed[MI_SCREEN(mi)]; + int wire = MI_IS_WIREFRAME (mi); + vectorf v1; + GLfloat dcam; + int dx, dz; + int i; + + GLfloat dgray[4] = {0.3f, 0.3f, 0.3f, 1.0f}; + GLfloat black[4] = {0.0f, 0.0f, 0.0f, 1.0f}; + GLfloat lblue[4] = {0.4f,0.6f,1.0f }; + + GLfloat l0_ambient[] = {0.0, 0.0, 0.0, 1.0}; + GLfloat l0_specular[] = {1.0, 1.0, 1.0, 1.0}; + GLfloat l0_diffuse[] = {1.0, 1.0, 1.0, 1.0}; + GLfloat l0_position[] = {0.0, 0.0, 0.0, 1.0}; /* w != 0 -> positional light */ + GLfloat l1_ambient[] = {0.0, 0.0, 0.0, 1.0}; + GLfloat l1_specular[] = {1.0, 1.0, 1.0, 1.0}; + GLfloat l1_diffuse[] = {0.5, 0.5, 0.5, 1.0}; + GLfloat l1_position[] = {0.0, 1.0, 0.0, 0.0}; /* w = 0 -> directional light */ + + mi->polygon_count = 0; + + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + glLoadIdentity(); + + glRotatef(current_device_rotation(), 0, 0, 1); + + gp->tic += 0.01f; + gp->camtic += 0.01f + 0.01f * sin(gp->tic * speed); + + /* rotate camera around (0,0,0), looking at (0,0,0), up is (0,1,0) */ + dcam = CAMDISTANCE_MIN + (CAMDISTANCE_MAX - CAMDISTANCE_MIN) + (CAMDISTANCE_MAX - CAMDISTANCE_MIN)*cos((gp->camtic/CAMDISTANCE_SPEED) * speed); + v1.x = dcam * sin((gp->camtic/gp->cam_x_speed) * speed); + v1.z = dcam * cos((gp->camtic/gp->cam_z_speed) * speed); + v1.y = CAM_HEIGHT * sin((gp->camtic/gp->cam_y_speed) * speed) + 1.02 * CAM_HEIGHT; + gluLookAt(v1.x,v1.y,v1.z,0.0,0.0,0.0,0.0,1.0,0.0); + + if (!wire) { + glLightfv(GL_LIGHT0, GL_AMBIENT, l0_ambient); + glLightfv(GL_LIGHT0, GL_DIFFUSE, l0_diffuse); + glLightfv(GL_LIGHT0, GL_SPECULAR, l0_specular); + glLightfv(GL_LIGHT0, GL_POSITION, l0_position); + glLightfv(GL_LIGHT1, GL_AMBIENT, l1_ambient); + glLightfv(GL_LIGHT1, GL_DIFFUSE, l1_diffuse); + glLightfv(GL_LIGHT1, GL_SPECULAR, l1_specular); + glLightfv(GL_LIGHT1, GL_POSITION, l1_position); + glEnable(GL_LIGHT0); + glEnable(GL_LIGHT1); + + glFrontFace(GL_CW); + + glMaterialfv(GL_FRONT, GL_SPECULAR, black); + glMaterialfv(GL_FRONT, GL_EMISSION, lblue); + glMaterialfv(GL_FRONT,GL_AMBIENT,black); + glMaterialf(GL_FRONT, GL_SHININESS, 5.0); + } + + + /* draw ground grid */ + /* glDisable(GL_DEPTH_TEST); */ + glDisable(GL_LIGHTING); + + glColor3f(0.1,0.1,0.6); + for (dx= -2; dx<3; dx++) { + for (dz= -2; dz<3; dz++) { + glPushMatrix(); + glTranslatef(dx*30.0f, 0.0f, dz*30.0f); + drawpattern(gp); + glPopMatrix(); + } + } + + /* Set drawing mode for the boxes */ + glEnable(GL_DEPTH_TEST); + if (!wire) glEnable(GL_TEXTURE_2D); + glPushMatrix(); + glColor3f(1.0,1.0,1.0); + glScalef(20.0,0.25,20.0); + glTranslatef(0.0,2.0,0.0); + mi->polygon_count += drawfilledbox(gp, wire); + glPopMatrix(); + glDisable(GL_TEXTURE_2D); + + glPushMatrix(); + glColor3f(0.2,0.5,0.2); + glScalef(20.0,20.0,0.25); + glTranslatef(0.0,1.0,81.0); + mi->polygon_count += drawbox(gp); + glPopMatrix(); + + glPushMatrix(); + glColor3f(0.2,0.5,0.2); + glScalef(20.0,20.0,0.25); + glTranslatef(0.0,1.0,-81.0); + mi->polygon_count += drawbox(gp); + glPopMatrix(); + + glPushMatrix(); + glColor3f(0.2,0.5,0.2); + glScalef(.25,20.0,20.0); + glTranslatef(-81.0,1.0,0.0); + mi->polygon_count += drawbox(gp); + glPopMatrix(); + + glPushMatrix(); + glColor3f(0.2,0.5,0.2); + glScalef(.25,20.0,20.0); + glTranslatef(81.0,1.0,0.0); + mi->polygon_count += drawbox(gp); + glPopMatrix(); + + if (!wire) { + glEnable(GL_LIGHTING); + + glMaterialfv(GL_FRONT, GL_DIFFUSE, dgray); + glMaterialfv(GL_FRONT, GL_EMISSION, black); /* turn it off before painting the balls */ + } + + /* move the balls and shrapnel */ + updateballs(&gp->bman); + + glFrontFace(GL_CCW); + for (i=0;ibman.num_balls;i++) { + if (gp->bman.balls[i].justcreated) { + gp->bman.balls[i].justcreated = FALSE; + freetris(&gp->tman[i]); + } + if (gp->bman.balls[i].bounced) { + if (gp->tman[i].vertices == NULL) { + createtrisfromball(&gp->tman[i],gp->spherev,gp->spherei,SPHERE_INDICES,&gp->bman.balls[i]); + } else { + updatetris(&gp->tman[i]); + } + glDisable(GL_CULL_FACE); + mi->polygon_count += drawtriman(&gp->tman[i], wire); + if (!wire) glEnable(GL_CULL_FACE); + } else { + mi->polygon_count += drawball(gp, &gp->bman.balls[i], wire); + } + } + + glFlush(); +} + + + +/* + * new window size or exposure + */ +ENTRYPOINT void reshape_boxed(ModeInfo *mi, int width, int height) +{ + GLfloat h = (GLfloat) height / (GLfloat) width; + + glViewport(0, 0, (GLint) width, (GLint) height); + glMatrixMode(GL_PROJECTION); + glLoadIdentity(); + gluPerspective(50.0,1/h,2.0,1000.0); + glMatrixMode (GL_MODELVIEW); + + glLineWidth(1); + glPointSize(1); +} + + +static void +pinit(ModeInfo * mi) +{ + boxedstruct *gp = &boxed[MI_SCREEN(mi)]; + int wire = MI_IS_WIREFRAME (mi); + ballman *bman; + int i,texpixels; + char *texpixeldata; + char *texpixeltarget; + + glShadeModel(GL_SMOOTH); + glClearDepth(1.0); + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + + /* Load configuration */ + setdefaultconfig(&gp->config); + + /* give the decay parameter a better curve */ + if (gp->config.decay <= 0.8182) { gp->config.decay = gp->config.decay / 3; } + else { gp->config.decay = (gp->config.decay - 0.75) * 4; } + + bman = &gp->bman; + + bman->balls = (ball *)malloc(gp->config.numballs * sizeof(ball)); + bman->num_balls = gp->config.numballs; + bman->ballsize = gp->config.ballsize; + bman->explosion = gp->config.explosion; + + gp->tman = (triman *)malloc(bman->num_balls * sizeof(triman)); + memset(gp->tman,0,bman->num_balls * sizeof(triman)); + + for(i=0;inum_balls;i++) { + gp->tman[i].explosion = (float) (((int)gp->config.explosion) / 15.0f ); + gp->tman[i].decay = gp->config.decay; + gp->tman[i].momentum = gp->config.momentum; + gp->tman[i].vertices = NULL; + gp->tman[i].normals = NULL; + gp->tman[i].tris = NULL; + createball(&bman->balls[i]); + bman->balls[i].loc.y *= rnd(); + } + + generatesphere(gp); + + if (!wire) { + glEnable(GL_CULL_FACE); + glEnable(GL_LIGHTING); + } + + /* define cam path */ + gp->cam_x_speed = 1.0f/((float)gp->config.camspeed/50.0 + rnd()*((float)gp->config.camspeed/50.0)); + gp->cam_z_speed = 1.0f/((float)gp->config.camspeed/50.0 + rnd()*((float)gp->config.camspeed/50.0)); + gp->cam_y_speed = 1.0f/((float)gp->config.camspeed/250.0 + rnd()*((float)gp->config.camspeed/250.0)); + if (rnd() < 0.5f) gp->cam_x_speed = -gp->cam_x_speed; + if (rnd() < 0.5f) gp->cam_z_speed = -gp->cam_z_speed; + + /* define initial cam position */ + gp->tic = gp->camtic = rnd() * 100.0f; + + /* define tex1 (bottom plate) */ + gp->tex1 = (char *)malloc(3*width*height*sizeof(GLuint)); + texpixels = 256*256; /*width*height;*/ + texpixeldata = header_data; + texpixeltarget = gp->tex1; + for (i=0; i < texpixels; i++) { + HEADER_PIXEL(texpixeldata,texpixeltarget); + texpixeltarget += 3; + } + + + glPixelStorei(GL_UNPACK_ALIGNMENT, 1); + + clear_gl_error(); +#if 0 + i = gluBuild2DMipmaps(GL_TEXTURE_2D, 3, 256, 256, + GL_RGB, GL_UNSIGNED_BYTE, gp->tex1); + if (i) + { + const char *s = (char *) gluErrorString (i); + fprintf (stderr, "%s: error mipmapping texture: %s\n", + progname, (s ? s : "(unknown)")); + exit (1); + } + check_gl_error("mipmapping"); +#else + glTexImage2D (GL_TEXTURE_2D, 0, GL_RGB, 256, 256, 0, + GL_RGB, GL_UNSIGNED_BYTE, + gp->tex1); + check_gl_error("texture"); +#endif + + 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_NEAREST); + glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + +} + + + +ENTRYPOINT void +init_boxed(ModeInfo * mi) +{ + int screen = MI_SCREEN(mi); + + /* Colormap cmap; */ + /* Boolean rgba, doublebuffer, cmap_installed; */ + boxedstruct *gp; + + if (boxed == NULL) { + if ((boxed = (boxedstruct *) calloc(MI_NUM_SCREENS(mi),sizeof (boxedstruct))) == NULL) return; + } + gp = &boxed[screen]; + gp->window = MI_WINDOW(mi); + + if ((gp->glx_context = init_GL(mi)) != NULL) { + reshape_boxed(mi, MI_WIDTH(mi), MI_HEIGHT(mi)); + glDrawBuffer(GL_BACK); + if (!glIsList(gp->listobjects)) { + gp->listobjects = glGenLists(3); + gp->gllists[0] = 0; + gp->gllists[1] = 0; + gp->gllists[2] = 0; + } + pinit(mi); + } else { + MI_CLEARWINDOW(mi); + } +} + + +ENTRYPOINT void +draw_boxed(ModeInfo * mi) +{ + boxedstruct *gp = &boxed[MI_SCREEN(mi)]; + Display *display = MI_DISPLAY(mi); + Window window = MI_WINDOW(mi); + + if (!gp->glx_context) + return; + + glDrawBuffer(GL_BACK); + + glXMakeCurrent(display, window, *(gp->glx_context)); + draw(mi); + + if (mi->fps_p) do_fps (mi); + glFinish(); + glXSwapBuffers(display, window); +} + +ENTRYPOINT void +release_boxed(ModeInfo * mi) +{ + int i; + + if (boxed != NULL) { + int screen; + + for (screen = 0; screen < MI_NUM_SCREENS(mi); screen++) { + boxedstruct *gp = &boxed[screen]; + + if (gp->glx_context) { + /* Display lists MUST be freed while their glXContext is current. */ + glXMakeCurrent(MI_DISPLAY(mi), gp->window, *(gp->glx_context)); + + if (glIsList(gp->listobjects)) + glDeleteLists(gp->listobjects, 3); + + for (i=0;ibman.num_balls;i++) { + if (gp->bman.balls[i].bounced) freetris(&gp->tman[i]); + } + free (gp->bman.balls); + free (gp->tman); + free (gp->tex1); + + + } + } + (void) free((void *) boxed); + boxed = NULL; + } + FreeAllGL(mi); +} + + +XSCREENSAVER_MODULE ("Boxed", boxed) + +/*********************************************************/ + +#endif diff --git a/hacks/glx/boxed.h b/hacks/glx/boxed.h new file mode 100644 index 00000000..fd9b5e14 --- /dev/null +++ b/hacks/glx/boxed.h @@ -0,0 +1,4116 @@ +/* GIMP header image file format (RGB-only): /home/shag/build/xscreensaver-3.33/hacks/glx/thebox.h */ + +static unsigned int width = 256; +static unsigned int height = 256; + +/* Call this macro repeatedly. After each use, the pixel data can be extracted */ + +#define HEADER_PIXEL(data,pixel) \ + pixel[0] = (((data[0] - 33) << 2) | ((data[1] - 33) >> 4)); \ + pixel[1] = ((((data[1] - 33) & 0xF) << 4) | ((data[2] - 33) >> 2)); \ + pixel[2] = ((((data[2] - 33) & 0x3) << 6) | ((data[3] - 33))); \ + data += 4; + +# ifdef __GNUC__ + __extension__ /* don't warn about "string length is greater than the length + ISO C89 compilers are required to support" when including + the following constant data... */ +# endif +static char *header_data = + "!FY'\"&Q#!&M!!VM-!6Y(!&M##6Q&\"69%\"FU'!FE!!VM$!VI$!&M!!FM#!VU&!'!!" + "\"&M%#&M!\"6Q$\"')#!FY#\"FY%\"6Y\"\"&Y#\"6]$\"&U!\"G%!\"7%&!G)!!'-!!')!\"'=!" + "!G!##G5\"\"75$\"W9#!G5#!G9!!WA$#'=\"!GE#\"'A%#GI$!GI!#'A!!'E##GQ&%7Q#" + "#WU%#W=%\"W]#\"GY\"%WQ)%7Y\"\"H-!\"W]&\"8!$%8%#$8-&\"8%!#81%$85)#H!##H-&" + "$H1(#H)#\"X5#$XA%\"X9##H9#\"89#\"89!\"HA\"\"8A!\"8A!\"X=#$8E&#(I!\"8I&$HM!" + "#8I%\"8M!!HM#!HM!!HU!$(M($8Q)!H])!XQ!\"8Y!$(]'$(Y'$8Q(\"XY%#XQ#\"I!$" + "\"XY\"#Y)##)%#%(]%$Y!!#I%\"\")!%#Y!$#9%!#8]!#I%\"$)%$%HY%#HU\"$91($9-(" + "$))$#95!%8]&!9-\"$X](\")!#!)%!%)-\"#9-$#)-&#I5\"$Y%!#)-)\"I-!#91!\"Y-\"" + "\"(]\"$I-'#IA\"\"I-!#Y-&#)-##Y-##)1#!I-##)-#\"H]!#)5#\"Y-\"!)-!\"Y!&$)-!" + "#)1#\"Y%##(]!$9-)\"I)!#)1#$Y%'\"XY\"\"91#!)1!#I)\"$)%%%(]&#HY\"#(]!#I)\"" + "&8]%!(]!\"Y!##H]%#X]!#)%##(Y&\"I)!$X]!#Y!#\"(Y\"\"HY!#Y%'\"8Y!%(]+#XQ&" + "\"8M#!XQ$\"Y%%\"8M!#XU!#HI\"$XQ$#XI&\"HI!#8A\"$8E\"#(5!#8A$$(A%\"8=#$(5(" + "#X='$89##H=\"#(=!\"XA#\"(-#\"H1\"\"81!\"8-!!(5!\"X-##8!#\"H1%$(!&%X1$" + "#(%$\"G]\"!8%\"\"7M!\"7U!#'Y$\"7M!#7Y##GI$#WI%!'M#\"7A!\"GI\"!G9!!GI&!GE!" + "\"GE%!W=\"!'E#\"W!\"!G%%!W5&!G9!!W)\"\"'-#!7-'\"V]&!W1\"\"'%\"\"'%#\"&]\"!'1%" + "\"&Y##FQ%!&U!\"FU!\"&Q#!&I!!FU#!&Y!!6M\"!FM%!FI!!&M!!VM\"!VM\"!FI%\"6Q$" + "!&E#!VQ&!&E!\"FM!\"FM#!&Q!\"&I%#&I%\"&M*\"VM(!6U\"!6A\"!&I'!FM#!FM!\"6M\"" + "!FE##FU%#V]$\"&Y#\"FY!\"F]%!F]!!V]\"!G1!\"7%\"#75(!G%!\"71$\"'-#\"'1!!G5&" + "!W5$!G=!\"7)\"\"G=%\"7M#\"GM'!WA\"!'A!#7A*\"7I!#7Q&#X!*$'I!#'I\"$'U(\"7U!" + "#7Y%!GY!#GY&\"7]!!H)!$H!+\"WY##X!'#X%'\"H1!\"()#\"H=\"\"X1(%X-(!H1!#X5!" + "\"H5\"$8-&%X5'\"8-!#X-'\"XE%#H= '#XA$\"XE#\"XE#\"H=!#HE%\"XI\"!HM##(I'" + "\"8A!#H=#\"H]!#(Q#\"8Q##(Y#!HE#\"HU!\"))%$(Y$#(Q#$H]&#X]!#X]#\"HU!!)%!" + "\"Y!\"#I!&$)%%$)%$#Y-#$XQ*#95!#9)!&9%($)1'!Y)!\"Y-\"#9)$%I%'#)-#\"I-!" + "$9)(!YA'&)-*!I%#!Y5!#Y)#%I-$$I5#\"Y1%#I)%#YA&$I1)#))#!Y5!#9-$#)1#" + "\"I1!\"I1!!)1$\"I-!#I1%\"Y!#\"H]!#I)%#9)!#))#$9) -$$)='#Y1##I9\"!Y1$" + "$)-'#Y)##I-%#99$!)-!#)-&!)-'$Y-+!9-\"%9)#\"X]\"$))'\"9=#$Y)!#Y%#$Y%(" + "!I%&#Y!##(]!$I!'#9!!%I)!!Y!\"$H]#\"9!##8I(#8]$$(Y'\"I-!$8U##(Q##8I$" + "$(U'!HU#$HU!#(Q!%(I)#H](#HU\"$(E(\"XM\"\"HI!\"XA#\"HE!\"(I%&(A(#HE%#XI!" + "#H9##8=!\"HA$$8=#!H1##(=!%(1&\"H1!#85%\"X1#\"8-!$(-#\"8-!\"X-\"\"X%#\"X%!" + "!H!#!H!!#8-%!'I!\"8%!\"GY%$7M)\"GM\"!'M!\"GU\"\"WU#\"WM!\"'I#\"8!!!75\"\"'I#" + "\"79+\"G5\"\"'5!!GA#\"'-\"#'=\"!G%!#')'\"'=,!W5$\"'-#\"G!#\"')#\"'%#\"6U#!W!\"" + "\"6]#\"G!%#'!$!VU\"!&Q!\"&Q#\"6]$!FM!!&]##&Q'!&Q!!6M$!6M&!&I!!69\"!G!#" + "\"6I$!&E!!6Y\"!FI#!6M&!&M!!F='!&Q&!&M!!VE$!VI$\"&I'!6M\"\"&I#!FE!\"6E&" + "#&Y%\"W)(!VU\"\"G!)!FU!#V]&!G9!!79&\"G-\"\"7)$!G1!\"G-$!W5\"\"71$\"'5#\"'5!" + "!71\"\"'1\"!G9!!7A%\"'A#!G1&\"GI$\"'A!#7I%\"'E'#H!&\"WY#\"WM&$GU%\"']\"!GY!" + "!WY!$H!+#W]'\"8!!\"X!#\"'Y#\"W]!!H)##X1'#H-##(5##89\"#H-!\"81!\"89##H1&" + "%HE%\"8=!$(9%\"X9\"!X9!\"XA#\"HI$\"XE(#(I#$(Y*$8I(\"8I!#85!#XM!!HM!$8M&" + "#(Y##(Q!#XQ!#XY##8Q$#(Q#$9%%#HY%\"X]\"$H]&!H]!\"8Y!!Y5!$I!)'I!'$)!!" + "#9%!\"9!$%95#\"9%&#I1(#9)$\"9-#!Y%!\"Y!#\"))\"!HQ!\"I)!$91\"\"I-!#9!!$9))" + "!)-'\"I-!$I5##)9#\"I5$#8]!#Y)##)1##)1#\"I9!$I-##9=!\"YA%$9-%\")5%\"I)!" + "\"I5!$)-'$)1!\"9=#$Y5!\"Y)\"#Y5&!)A!\"Y-\"#I=!#91$#I%\"#)-#%I5!#)5##9)$" + "#)1&!9-\"#91$\"I1!\"I1$\"Y9\"#I)%!I-#!I-##)-#\"I-!\"Y5\"#I)\"!))$\"))\"!)%!" + "!X]!$)!(\"Y%#$9%\"#I%\"#I)\"$Y-'#I%#\"I!!#Y-##I%)!Y%!\"8]!#I-%#)%#$(Y'" + "$)%%#XY#\"I!!\"8]!#(U#\"HA$#HU\"&HQ)&(Q*\"HU!#8M$\"8M!#8Q$#8Q$$(E(\"8E#" + "#(A#\"HA!%85'#(=!%(=#\"H5\"#H9\"\"89!\"85!\"H-'!H5#\"8=!$85$\"8-!!X)!#'U$" + "\"8%!\"8!!$H!$#(1!\"(%#!GU#!WY!\"WU#\"7U!$GU#\"7Q!#GI$\"7M!\"7M#\"GI%\"GI\"" + "#WE*\"'E#\"WA&#'A'\"'I\"!')!\"G9\"\"W5$#W-#\"'1#\"'-#!7-\"\"&Y%\"G5\"\"'!#!'%#" + "\"'%#\"F]'\"VY&!&Q!#&Y\"\"&U!\"&Q#!FQ!\"FQ%$VU*!&E!!FM%!VM&!VM$\"F9)\"&U)" + "!&M#!&Q!!&I!!&M!!6Q\"\"6]&!&A!!FQ#!VQ$!6=\"!6Y&!6M\"$6M&#FM)!FQ!\"&Q#" + "\"6M,\"6Y$#&]$\"V]*#FY)!F]!!G!!!&]!\"')\"!W)!\"7-&!G5!!'-!\"75#!G5!!G9!" + "\"'A#!G5!!GA#\"WA#\"GA)!'E!#'A\"#GU!#WM%#7M%\"7M!#WY'#7Y%\"7Y!\"GM\"#7]%" + "\"X)##']$\"8%!#8%$%(=&\"8%!\"8)$$X)#$()#$8%)\"8-!&X1(\"X=\"$H='$(=\"%H1&" + "!HE#\"X=#\"89!!X5'$8A##XI&\"8A&#(I!&(Y##HI(#(]#\"8M!#8Q$!HQ!\"HQ!$(Y'" + "\"XU\"#9!$$X](\"XM%#HU%\"XQ(#XU&\"8Y!#9-!#8Y$\"8Y!#I!\"\"9)#\"H]!\"8]!#8U!" + "$9%##X]!\"X]\"\"I%!$Y!*!I)##9-$$914\")1(#I-%#)-#!))$$)5$$Y1*#91$\"Y1%" + "$9=\"!Y9!\"9-#$9%)\"Y5\"&)-&$)5'\"Y%#\"I5!\"I='#)9##99$#)=##I9%\"YI!#)9#" + "#)9#%I9.\"II!#Y9#\")=\"\"I9!%)1($Y9$\")E\"#Y9#\"Y9\"!YA$$I9)\"I5!#95$\")5(" + "$)1'#Y=##Y9&$I5##Y9&\")9\"#Y5##)9##9=$#9-$!Y9!$)A'\"Y-\"&9-+!)-!\"Y-\"" + "\"I)!\"I-!#91'#))##9)$\"XY\"#9)$#9%!$H]#!I)#%I)!&I%&$9!%%I1!!X]!\"8]!" + "\"8]!\"I!\"$HU'!XY!\"XU\"#(Q##(U#%(U)$XE%#8I$!(U#\"8M#\"HU$#(Q!\"HM!#HU\"" + "!XE$\"8M!\"85!!H9!\"XA\"#(=$\"X=##HI%$89##X5&\"89#!H=&#(1&\"85!\"(5\"#H-%" + "$(!&#H)%#(5#\"()#\"8)$!G]#\"']\"#W]'#8!##WY'$X!)#7U#\"WQ#\"7Q!\"WM##'Q!" + "\"7I!\"WI#\"G=\"$7E$#W5*\"'=#!G=!$75,#W='\"'5\"!79\"#71(!W%\"\"G%#\"')#\"'%#" + "#G%$\"7)$!'!!\"'!#\"G%\"\"&Y#!VU\"!6M\"!FQ!\"6]&!6=\"!F]#!VM$!&U#\"FQ#\"&E#" + "!&M#!VI$!VU*\"VU&!6M(!6Q\"\"FQ%#6M$!FQ#!FI#!VMM(\"&M#\"&U#\"&M#!F]&" + "!FY(\"6Y$!7)\"#6U\"\"W)&!G!!\"G%##G)'!W)\"!'9!\"7-$#W5#\"'-#\"'9%!W-\"\"'=\"" + "!'=!\"G9%#7Q##'E$\"GI#%'I'!GE#\"WQ!\"'Q\"\"WM##GY$#WY)\"7Y##8!%#X%!\"X%#" + "#H)$\"H%\"%(5!#'Y!$8))#7]%#H-#$81$\"H5\"#89$#(=!#85!$(5($H-$#XMY\"" + "$(E%!(M!#89\"$HM'\"(E\"\"HM!!(I!\"8I!!(I$#8]$#(E#%(Q)$HQ)#XQ'$(U'#8A$" + "\"HI!#XY#\"8Y!#(]##9!!#8]$$)!(#Y%$$9%%$9%#%(]\"#9!!\"Y%##Y)##I-\"#8Y-" + "\"I1!$9-\"$)5'\"I1!#))#\"I1!!))!#9%$!I)#\"I1!%)5\"\"95##91!$)5$$I5)#95!" + "$9=%\"I1!\"YI\"\"I9!#99$\"I9!\"Y5\"#I=%$)9!$I=#$)='!YI!\"I9!%I='!)5!#Y9#" + "$I=#!)A$\"I=!#I=%#9=$\"YQ!#)=##)A#\"YA\"\"I5!#I=(#Y9&\"II!!IA#\"9=##Y5#" + "#)9#\"I1!\"IE!#Y9&\"YI\"#Y-&\"Y=\"\"I=!#I9%#)9##I9\"$Y1'&9A&#I1%\"I!'#)1#" + "\"91#\"Y1\"#Y1&$))$$I5#!I%(\"I!$\"I)!#))#$Y)!#I1\"#I%##8]$#(]!$8Y\"#Y-#" + "#HQ(\"XY\"\"I!!#(Y#\"Y1\"#8Y$$(Y(\"HU!\"XM\"#8U$%(I#\"XQ\"\"XY\"#(M!!HI&\"(I\"" + "#HE#!HI!#HM(#8=$\"X=\"#XE'!(9&\"XE#$X=&#(A'\"81!\"H1!#8=$\"81$$81&#(-$" + "#H-%\"8%!#H))$H)\"\"8%!\"X%!#8)%\"']%#(!!\"7U!\"'E#\"WU#!GM!\"GQ\"\"7Q!#WI%" + "!WM$\"GA$\"WA!\"WE#!'A!\"'A#!7A\"#GA$!G5!\"G5$\"W5#!G5!!'1!\"W)$\"G5\"#&Y#" + "\"'%#\"'%#\"F]##6M!!F]!#6](!G!!\"FU#\"6I$!VQ\"\"FM)!&Q!!&Y!!FM#!&=#\"FM%" + "!6U\"!6M$!6M\"!FQ##&E%\"&M*!VM$!6Q\"\"6U(\"6M$\"6Q$\"6E\"!VM\"!FY#!VU$\"&]\"" + "\"FI%!&U&\"'%#\"'!\"!W!\"!G!!\"W%#\"71$\"'-#\"7%$!G-!!F]!!G=!\"'-\"#GI#\"7A#" + "\"7=$!WI\"\"GU\"!GE#\"GU\"#'Q$\"7Y&!'Q#\"W=$#7Y%$GY#\"GY%!G]#\"H)\"\"H!\"\"(!\"" + "\"7Y!$(%%\"8)$$H-%\"X-\"\"X%#$(-(#H1##81%\"85!#(A#\"89!#(9##H=%#(=!!H=#" + "\"XA%\"HE$#H=%!HI!$XQ+#(I#\"8E!#(Q#\"8M#\"XQ\"\"HI$#I%%%9%*#8Y$#(U#%)%\"" + "\"X]%\"Y-\"\"8Y!\"I!!!Y!$#(U!\"I!!$))!!Y-!%I-+%9%&\"I)!\"I!!\"I-!$)-$#I1\"" + "\"Y!%#)1#!91\"\"I-!#HY%\"I1!$Y-+#95!$I5&#Y=&#IA%\"I9!#Y9&#I=%\"I9!\"I9!" + "#9E#$)M&\"I=!!9=\"$I=#\"Y9%#Y5)$)A!$)=$#I=\"%99\"%II&#Y9##YA#$IA##Y9&" + "!)E!\"I5!#9A$$Y=!$9A$\"YM!#IA\"$YI&$IA%#I9\"$YA'#Y=#$)9$#9E!$9=%\"IE!" + "\"Y5\"\"I9!\"IQ!#I=%%9I%\"I=!#)M#\"99&!)=!#YE%#99'$I9#$Y5'#)9##)9##)1#" + "$I=#\")-%\"Y)\"!I1)'))'\"I-!\"I)!$9-%$)-!#H]%#9)!$I)#\"Y)\"#I!#\"I-!$)!$" + "#I%\"#8Y$$8U##(Q#!X]!\"X]%%H]-\"(Y\"\"H]!\"XQ\"#XQ$#(Q&%(Q)#(Q#!HQ!\"8U#" + "\"HQ!#XY&\"8Y!!HI&\"X=##(M#!(=!#8E%\"H9\"!H9#$()##8I$%(5&#()!#H9&!(-!" + "#8-%#H-%#H9##']$\"8)!\"(%##X%!\"81!!(!$$H)(!(!$\"GY)#WQ'#7U#\"7Y#!GY#" + "!'Q!\"WM#!'Q!\"W9#\"'E#!WE!\"GA%\"G=%\"'=#\"G9$!G1!!W5\"!7-\"#71(!W1'\"'%#" + "\"F]%!7%'\"&]#!6Y$\"W-&#&]'!FY!\"&Q#\"&M#\"FI%$VY%!6M*\"VM&!&M!!&M#!FM#" + "!&Q!!&U%!FM#!6M\"\"6M$!&I!\"&M%!&M!#&U%#&M'!7%$!FQ!\"VY&#&U%\"6Y&!W!$" + "!6M$!FY!!&]#\"'%%\"'1\"!G1#\"V]\"\"W1&\"W5(!G9!!G9!!79\"!'5#!'=!\"GA\"!GA#" + "!GE!#79\"\"WI!\"'I!#WE#\"GQ\"$'Q##7U#!GQ!\"X)\"\"7Y!\"'Y\"$'Y%!H!!\"8)!#(%$" + "$H-%\"(%#%(!$#X-'\"X%#\"H%!#X1$#(5#\"89#\"X9\"#XQ&\"X=#\"89!#X=!#(E#\"HE$" + "#HA##(E&#(M#\"XM%$(M!\"HI!$XM(#HQ%#HY%$H]&#)!#$9!+#H]\"%Y!#$(]$%I!+" + "\"8]!#9!!#9%!!Y)$#9-!#9-!\")%\"\"I!\"#9-$\"I-!\"I-!\"Y9\"&)9##8]!$91%#)1#" + "#9=$\"Y1\"#I9%#Y5##Y5&\"I5!$)='!Y1!#I1($9=(#)9#\"Y9\"\")=\"!YI!!Y=!!Y=!" + "#Y%$$YA&#YA\"%9E%#9=!#95!#YA##99!$)5$%Y9%$YA&%9I)$)E$%9E)#)5##9E$" + "#YM\"$IE%$YI$#9A!%)E!#9E!#9=!#Y=#$95%&)M\"$I5##I=!$)I$$YA&$IA%$9M!" + "#Y5##YA\"$9=\"#YI#$)A$#)A#$)5$&9A.$IA($)1$#9E#\"I=!!I9##)A#!95\"\"II!" + "\"99##Y1&!)9!\"Y!##Y=#$Y5.#))#\"(]\"\"I1!\"I5!\"9)#!Y-!$Y%*$))$\"I)$\"I)!" + "$)%!$I)##9!!#9!\"$HE!$(]$#8]$\"8Y!#(]##HY%\"8U#!HY!#XU&\"XU\"\"HY!\"89!" + "\"8M!#HI##XM'#XAQ$\"XI\"!H5##(9#\"XA#!H5#$X=%\"H9%$X9#%(=#$X5&#(5&" + "$H1*%X%'#(-!$(-%#8)%#H-&\"8%!#()$$(!#\"8%!#X%!$']&\"WU#\"W]#\"7U!$'U#" + "\"WQ!!GU!#'I$!'I#\"GI\"!GM!\"'I#!'E#\"WM#!W)!#'9&!G9!#'5\"!G5#!')!!7%&" + "\"G-%\"W)&!79%\"')#\"7)$\"7-$#&]&\"&U!$6Y%!FQ!!W%!\"FY%!VM\"#6E\"!V]\"\"6M&" + "!FU#!&M#!&Q!\"6M(!6M\"!&=#!VM$\"VE(\"VM$!V]\"\"&Q#\"&U#!6U$!FM!!&Y##'%%" + "!G%!!W%!\"7%$!')#!')!\"G-%#'1&$'I!!G9#\"79+!75\"\"W9&\"71$\"W-&#'U\"\"7E#" + "!WM$!'E#!GU##7I#\"WM(!G]!\"7U!#'A\"\"X!#$7]*#X!'\"8!!\"WI##(!$#H%&!H!#" + "$8)$\"X)%#8-'#(5#!H5!!(=!%XE)\"89#!X9$\"H=!\"X=%#H5&\"HE!#(M#%8I'#HE#" + "$HY)%(E+\"8]!\"8M!#(Q#\"XY\"!HI&!8I\"$8Y&\"8I!\"HI'\"XU\"#HY%#(])#8Y$#I!#" + "#9!!#H]\"#I%\"\"Y-\"!))!$))!$9=%$9-)#I)\"#9-$\"I1'\"I1!%Y=(#))&$95\"#)5#" + "$I9)#)5)$I9)&91'\"I5!%Y=$!)='\"Y-\"$Y-!#95!%9=)$IA\"$9=%%)A(#9A!#91!" + "$)E#\"IA$#9E!#IE\"\"II!$9E$%)A%%)E$&IE.#)=#$)='$IA\"$)A!#9E!%IM&$)E$" + "$)Q#$9I\"$)=!$IA#&9I'#9I$$9I$#9I!$9M!%)A+#IE$\"IE!$IA%%9=\"$9=%$Y=$" + "$)I#!)E!#YQ##9E!#YE#&)A(!YA$%)A(#YA#&)A\"&9I&#IE\"$Y=!$9=(\"IA!\"Y1\"" + "$9)\"!YA!#I9%#)%$#Y%#%95\"\"I)!$)5'\"I1!\"9%$\"I1$#Y)&#)-#$91(\"Y-%%)-%" + "\"8]!#99'#)%#%Y%,\"I-!$)!!#9-!#9!\"!Y!!$HY##(U#\"I!$#(Y##(Y#%(]%#XU#" + "#(Q#!XQ!#(Q##8I$#HQ%#8Q!#HQ\"\"XE#\"8I!#XE&\"XQ%#X9$\"XA0\"X5#$8-)!H9!" + "#(=!\"XE#\"X=#$(1#\"7]#!X1!#8%\"#H)$!(%!#H%&\"H!\"\"X%#$8-'\"H%\"\"7Y!$(!(" + "\"GQ$\"7E!!H%!#WM'\"7M!#7M#!GI#!WY$\"GA#!WE!!GE!#7I(\"W=!\"G9%\"')(#71$" + "#G%\"!'%!\"'A'\"G1\"!G%#!'!!!G!#\"G1#!FU#!FY)#&U%!&U#!VY\"\"VQ$\"FQ%!FM*" + "!VM$\"FI'\"&Q#\"&M#$&M)\"6M$!VM$\"&M##&M!\"&U##VU,\"&U!\"&U#\"FU%\"&]#!FY&" + "#')%\"G)%!FY!$7-%\"')\"\"G1%!W1(!G5%\"G9$!'9!!G=!\"'=#!G1!!W=\"!GA!\"7I!" + "\"7M!$'M(\"7M!\"7I!#WQ%\"WY#$GY%$'U#!7Y\"#W]$\"X!#\"X%#$(%%\"8)!#()!!X-$" + "\"X-#&H9'\"H5'!H5!#H)&$8=##89$\"X9#\"X=#\"8A!%8A-#(9#\"HM!#XE##HA&\"(A\"" + "\"8M!\"HA!!HI!#HQ%#HM&!XQ$$8U##XI#\"8Y!#XY##9%!#Y)&#HY%#9%!!X]$$9!&" + "$I%'#)%$%)9%$I!*$Y%!!)-!#Y1#$8](#)9#$I5,\"Y1%#I5%#95!\"I1$$95(%II&" + "$)A!\"I9!!)=!\"I=!\"Y5\"$9=%$IA#%9E\"#Y9#$9=+$)=$$)A$!Y=!$YI&#YA\"$Y=#" + "$IQ%%IE$&)I,$)I#%9I%#YM#\"II!#YI\"#)Q\"#9I!#YM\"$)I#%IQ)&)I,$9Y!%II#" + "#9M!#9M!%IA*%YA$%YQ!$)I#\"YM!#)=#\"IM!#9A!#YM#$9U$#IM\"%)I(%)M!#9E!" + "#)I&#)M##Y9#'YI*#II\"#9E!#Y=\"$)E#&9E#%YE+%YE+#9I!#9A!%IQ#%9A\"$)=!" + "#99!#Y1#!9=%#)9#%9=\"$)5!\"Y=\"\"Y=\"#I=%\"Y-\"!I%##)1#\"I1!%)=$#))&!(]#" + "\"Y1%!I-##9)$#Y-&$91(#Y))#Y)##H]\"$I)#%I!!$X]*#9)!\"X]\"!8U%$8Y\"$(Y$" + "\"8U!%HI%!XM!$(Q(\"8M##Y!'#(M&#(I'#(E$\"(U\"!(E!\"HE!!HI!$HA'!H=!\"8-!" + "$89#\"HA!#89%#(9#\"81!\"(1\"\"(-\"#(5#$8).$()(\"8%!#7U%\"8!!\"GY$\"7]!#GY&" + "\"GY\"\"WU##GQ&!GM#!GI#\"GM\"\"GI\"#7I%\"GE$!WA!\"'A%%'9#\"7=#$'A&\"'9#!W5\"" + "\"79&!W-\"!G1!!W)!\"G)%!'%##G%\"\"&Y#!VY\"!&]!\"6Y$!FU!!VU\"\"&Q##6]#!FM%" + "!FQ!!6Q$!6M$!6Q\"!6E\"\"W!&\"VM$!&I!!VM\"\"VQ##FQ)\"6Y#!W%\"\"7!\"#7)##'!%" + "\"'%\"\"'1#\"G%##G-)\"71(\"W1!\"G-%\"79$!W9\"!G9!\"W=##7A#$'E(!'I!\"GU\"\"G=%" + "\"W=#\"7=$!GE(\"WU##'U$#'I!#8%%$W](%8)(#'Y&!(!!\"']#\"(-#%'Y$#H-##X-'" + "\"X9#\"(5\"#X=#\"8)(\"X=##X5'#X=!\"8=$\"8A!!HE!$XE%!HA!\"8I!$8I)$HE*#8M$" + "#8Q2#8Y$$XQ*$HU&\"HM!$(]'\"(U\"#(]#\"H]!\"8]!$Y!!#9%!\"I!!#)1#\"9%$$))%" + "#9-!#(]!#))#\"8Q!$9A(\"I5!$99($I-##)I##YE&!I1&$99(#IE$\"I9!$I9\"\"I5!" + "\"IQ!\"IE$#9=$#9A!%IE$!YA!$)-$$II%$IE&$YA&$IQ\"$)I!\"IM!#YI#\"II$#9A!" + "\"I9!#YM#%9M)#9I#\"II!#9I!#IM\"$I=##)Y#$9I!#IE\"#IM+#YU)#Y=##9Q!#9M!" + "#9M!#9I!\"9U#$)Q'%)U'%)Q*$)A!$YU#%9M)#9Q!%IE##9M!#9E$$IQ&$)M#%YE$" + "#)M%#IM!!YM$$II##YM#\"IU!$)E#%)A!$)Q$$)I'$II##9I!$IE#$9A!$II&$IE%" + "$9A%#YA##IE!$YE*#9=!!)A!#9A'#9=!\"I9!%99#\"95#\")1%\"I-!!Y5!#Y%'$I5)" + "$(Y'#91$#9)!$9-%!)!!\"95##9)!\"8Y&%9-#$)!%%)%&\"Y!\"#(]!#(]#\"9!#\"H]$" + "$(M%#8M$#(M#$(Q(!XQ!#(Q#\"8U!\"9!##8M$!(=!#8E%\"XI\"#(I##(='\"XA\"\"8=#" + "\"8A#!(=!$(9\"\"X=\"$(=\"$(1(\"X%#!8-(#H-&!H%%$8%$\"8-!\"W]#\"8%!#7Q&\"W]#" + "#7Y#\"WY!&'E$#7U##'Q$\"7M!\"WQ#\"'A!#7M%!WE\"!WQ\"\"79\"#G=$\"GA%\"G)!!W9\"" + "\"GM$%7)'#'-&!'-!\"7!$!W-!\"'%#!FU!\"&U#!F]!!W!\"\"&U#\"&Q#!FU#\"FU!\"&I)" + "!FM!!6M\"!&]!!&=!!&M!#6M\"\"6]$$&Q'#6Y(!&U!\"&M#!F]!\"6Y#\"6Y$#'!'\"'1#" + "!G)!!')$!'-#\"G-%#G5'!G5#!GE!\"'=##G9\"\"W=%!GA%\"7A!!'M#\"WM!\"GA#\"GU\"" + "$GY*\"7Y!\"WY!#7Q\"#8!%\"7]!#']!!WY&\"7U!\"7U!$(-%\"X!##H)#$(!*#H9&$X-\"" + "#X-!#85\"#H)&\"X9#\"H5!#(='\"8E!!H9!$8A##(Q#$8M##XI&\"8=!!)!$#HI#!XQ!" + "$HU$\"(Y%\"XU\"!X]!#(U!$I1##I!&#)!&$))$#8]!$9%#'I%'\"I)$!I-##9)!$I9#" + "!Y)!!Y-!\"I1!\"I1!#))#$I5&\"I5!!I5#%I9#\"Y9%#)=&#Y9&\"II!\"I=!$I1&$YE#" + "$9I%')5*#9E!!YE!$IE&$IE%&YQ($IE#$YM#%)I/$9M!$YA$$IE##YM##YU\"%)U'" + "\"IM$$IQ)#II!%YM.#9Q!$)Y##IM!$IQ&$IU\"$)U##9Q!$IQ&#YQ##9Q!$)U#$)Q#" + "\"IU!$YQ##YQ#$9Q!\"II!$)M$')Q*$9I!$)M#$II%#YQ#'9I(#IU!$YY&\"Z!\"#9U!" + "#YQ#!YE!$)U#\"IU##9I!$YI$$9M$#9M!%IQ'$IM\"#YI#%)5!#9M!#II\"#YI#%9E)" + "#YE#\"IE!%9M)%9=*$99%#YI#\"YA\"$Y1!#Y=##99!#9=$\"9I&$9=%$Y5*#)9#\"Y=\"" + "%9E)#)1#&)5##I1%$)5*%Y)\"$9-(#X]&!Y)!#(Y&#I!\"$I)'$))!$9!%#I%\"\"8]!" + "\"X]\"\"I%!$I!##(U&\"HU!#(U#!XY$#8U$#9!$\"8E!\"(Y.#XI'$(I!#(A!#(M!\"XE#" + "#(A##8=$%(=)\"X9##X9!$(1&#(5#\"89!#(1$$()%\"()%#8)%%8%#\"H!\"\"8!!$'Y%" + "#7]%$(-#\"7Y!#(%$#7U##WU\"#7M%#'E+\"GE\"\"GE\"!GE!\"'E#\"'9!$'=&\"'9\"#'9+" + "\"'E#\"W5#\"'1'\"71&!71$\"&U#\"'-!\"&Y#\"W%$\"G%!!F]!\"F]#!&]#!FU!\"&U#!6Q'" + "!VQ$!VM\"\"VQ*!&Q!\"6M$\"&U#\"&I!\"&U#!G!!\"&]'!V]\"\"W!&!G!!!71\"!')!!')!" + "\"'-\"\"'-!\"'-#!'!%\"W1##GI#!'5!!GI!!'E!\"G=%!WE)\"7=$#7I!!WM\"#'M$\"'M\"" + "$7Y$\"GE#!X%$\"GY\"\"7]!\"8!!\"89!\"(!%#(%'\"H)\"\"8)#$X1&#X%$\"X1#\"(-($(1#" + "#X5!\"89##89%#85%!8=\"\"H5\"$HA!#8=$%8]#\"XE\"\"XI\"\"(I\"#XE!#(Q##HI%!HU!" + "\"HQ!\"8Y)!HM#\"8]!\"8U!\"X]\"$9%%%Y9!\"Y!\"$)%%$Y!'\"Y=\"$))!#Y-#$I-)\"I-!" + "$Y1*\"Y1\"\"95#$)1'\"I5$#95$#95$\"I9!#)9#\"I=!%)=(\"I9$#IE\"!Y-$#9A!#9I!" + "#I9\"#IE%\"I5!#)I#\"IM$$II&$9U$#)A#$IQ&&IM(%)M!%9E Q!#YQ#$YQ'%)Q!" + "%9Q($YY#%9Y\"&)Q(&IM$%)Y'!YU$#YM#%)U($9U($9U$%9Q($9U!&YY%%)Y$$9U$" + "\"IU'\"9M#%YE!#)]#!YQ!$YM##I]!&Y]$#)Y&\"YU$$)Y##II\"#9Q!%IU&\"9Y##IY!" + "&9M-#YQ&$Y]&$YQ'$YQ##9Q!\"YQ!#9U!#9Q!\"YQ\"$IM&$)A-#YI\"#9Q!$II%#IM$" + "\")A%\"YM\"#9I!$Y=!$9E\"$)5$#YA#%)9%!YA!#9=!#9A!#99!#)A#%IY*\"I9!\"Y9\"" + "!Y-!\"I9!&)=&!)1!!91+\"I1!#91$#I5\"#I-%$H]##9)!#))#\"I1!\"Y-\"$9%&\"I)!" + "$8U\"#(]#!(]!\"I%!#8U$\"8Y!#XU&#HE#$HQ&#HQ%#(Q##(M#$HI'#(I##(U##(E$" + "\"X=#$XA(\"8=##(9#\"(9%\"X5\"!H5#\"X5\"#89%#85$$(!(#8-*!G]#!X!$\"X%\"#8)%" + "\"X!#\"GY'!'U!\"7U!\"7U!!']#\"WQ#!WQ!$'U##7I!\"7E!!GE!#WA%\"'A*\"'A#!79\"" + "\"75(\"W9#\"G5%!W5$!G=%\"7-$#')'!G)!#7)&!G-%$7!#\"&Q#\"7%$\"FY%#FU\"#FA#" + "!&M!!&M!!VI$#&M#\"FQ!!&M!!G%!!6U$!FU!\"&Y#\"&]#\"'!\"!F]!!G!!!W)\"#W!!" + "\"'-##'1&!'1!!G9!!G5!\"7A!!GI!\"7A$\"7Q#\"7A$\"W9!#7Q%\"7Q!#'U$$'Q&\"GQ\"" + "!'M!\"7Y!\"7Y!\"7]$\"7]!\"'Y##'Y$!X%!\"X)-%$(9(#8-%#H9#!(I$#85%#(E$" + "#89$#H=%!HA##(I#\"XA%#(A#$89!\"(I\"\"HI$!(I)\"Y!#$8Q(#HQ&&HM*#(Q#!HM!" + "$(Y!!Y!'#)!##X]&\"9)#$9)\"#XU#!Y%$!Y)!$)1'!X]'$91%\"I-!$Y1!\")-\"\"9%#" + "\")5\"$I1)#IE%#Y-&$I=)#)9#\"Y5%#Y9#\"IE$%)A%&91$#IA!#YE\"#9E!#)E##9M!" + "\"II!#)I#\"9E##IM\"$YE*\"9I#%YQ'#I]!$)U##9Q!#9I!#I]!#9U!%)Q$%IY)#Y=\"" + "%IQ*%9Q($)Y#%I=#%)U'$)U#\"IY!$)Y##9U$#9U!%I]#'J!'$)Y#$9Y$$*%&$IY&" + "!YY!$)Q#$Z!##Z%)$I]%$YY##YY\"\"YM\"$IY&%YI!#IU\"\"IY!$)M$$9Y$\":!#'9]+" + "%9Y(&YU$#YI#')Q%$IU%$IU%$)U##J)!\"9E##9U#$J%%!YQ!$9E\"$IY\"$)I#\"9M#" + "\")I\"#9I!$YE U!$9A$$I]\"#99!#YI##9E!#IE!#YA#\"IE!#9A!#Y9##I9\"!)5!" + "\")E%#)9##Y=&$)1'#)5##)5##))#\"I1!\"Y1\"%)I!\"I-$\"I-$$)%'#9)$\"Y%#$))$" + "$Y%%$I)##X]!'I%*&(]&%HY$#8Y$#(Q#\"HM$#8U$#(]&\"H]!\"(=\"#XQ##(I#\"8Y#" + "$(A(!(A!#8A$\"H%!#X='#H=##(9!#X=$#H5&\"X-#!(9!\"H)\"$H-*\"8!!\"8A!\"8%!" + "!H!#\"(!#!GY#\"W]!#WY$\"7U#\"7Q!\"WU#\"7Q!\"WM#\"G9\"\"WY##7]%\"'I#!7A$!'9!" + "\"'=##'I$\"75$!G5!!71\"\"'-#\"'-#!'!!\"7-$!G!!#'!%\"VU#\"&]#!FE!!F]!\"&U!" + "!&I!!FM#!VE&\"6Y&\"&Q#\"6=(\"'!#!F]!\"&]##'%'#6]$!W%$!7)%!G)!\"G-%\"W1#" + "\"'1##'5\"\"75$!'9!!G1%!G=!\"'1#$79%!GE!\"WQ#!7E\"%GU&!GE&\"'=!#X)'\"7U#" + "\"GQ\"#'Y$\"WQ#\"8!!\"W]#\"X1#\"(%*\"()*\"8%!#81%$X-+#H!!%(=)!85\"#H=%#(=!" + "#XI'#8A$!HA#\"X=\"\"8E!\"XQ\"$HM*\"XQ%\"8A!#H]\"\"8Q##XQ#\"XE#\"8U!\"8Y!\"Y-\"" + "$H]&\"I-!#(Y!\")!##9)!#9%$\"9)&\")1\"#I)&$9)(\"Y1(#)9##))##91!!Y5!#I5\"" + "\"I9!!Y9!\"I9!!Y=!\"II!#Y=##YA##Y9#$IA#&I=(&IE$%)E(#IA!'9E+%II##99!" + "!)Q!#9M!#9=!'9M'$)M$#YQ#%II#$)Q$#IM\"#J!!%YE!$)Y##IY!#IQ!$9Y$$I]&" + "&IY.$:)!%YM.%)M($Z!&\"Z!\"%9])$:!$$I]&$J%&%)]($:-#&)Y!$:!$#I]!$:)!" + "#I]!$9]$%IY*#J)!#J)!%YU!$IQ%#IY!&*!$%*-'!I]#$9U$#Y]\"#YU\"\")M%\"I]'" + "$)Y##Y]\"#IY!#9U!#9Y#\"YY!$9]$')Y\"$)Y#\"YQ!#9I!#9U!\"IE$%)M!#IY!$IQ&" + "#9Q!#)Y&#YQ#%)M($9Y$%9I%$9E%#YI#\"YM\"!9I\"#IA\"%9E\"#Y=\"$)A!\"9E[!" + "#9A!&9=&%Y=!\"I=!\"IE!#Y5##I9\"\"I9!#Y=\"#I-%\"Y-\"#91$#9%$!)5!!Y)!\"I)!" + "\"8U!$Y-(!Y%!$)!$\"I!!\"H]!!Y!!#XY!&HY)#)!##8U$#8Q$!(Q!#XI##HQ%#HY%" + "#8I$#8M(\"XI\"#XA!!8E\"#(A!#85%#X5'\"89&\"85#!(5#%(1$\"(1##H5&$8!)!(5!" + "#(%$#85\"\"8-!\"WQ#\"7Q!#GU$\"X%\"\"WU##WU%\"WY#$'M!#'Y$#WQ'\"WM#!G=!\"'A#" + "#'I'!W=\"#G1$\"79&!71\"!W%$!W1&!'-!#')\"!79\"!W%\"\"'5#!W)(#F]'\"&Y!!FU!" + "!7!%!FY#\"VI&!FU##&Q#!6U\"\"6Y#!F]!!F]!!6]\"\"&]\"!G%!\"'5\"#G-)!'9%\"'%#" + "\"G1#\"75,!W9\"!G1!!W5\"!W5\"!GQ!!GE!#7Q#\"'Q##8%*\"7U!\"WQ#\"WU#\"GY\"!WM)" + "\"W]#!G]!#()$\"'Q\"#(%&$(%(#H))\"(1\"\"H-!!X)!\"HA\"\"85!\"85!\"XA#\"X=##(E$" + "\"X=#!HA!\"8A!\"HE!\"(I%#HE%%8M'#HQM$#(U#!)!!$)%!#(I##XY&#(]#&)%*" + "#8]$#91!$Y%!$I!$$I%'$Y)(!Y%!#I-\"#I-%#)9##I%%#)-#%I9.#)9##)A&$I9#" + "\"I=!\"I9!!YE!!Y9!$YU'#9M!$IE##9=!!IA&#YM&$)I$%)E!%)A$$9A%$9M!%)Q$" + "%)M(%YQ$!YU!#YM)$YI*$)] Q!#IY!#IU!$Y]&$9U!$)]#%*%'#IY!$IY\"#:!#" + "#Z!\"#Y]\"#I]!$Z!\"%)]$$9Y$$*%##J%!$Y]'$:!$%J)*&*%!$J%&&*!($9U($I]%" + "$:%$%*-'#YY\"#J%!$*!#$9Q!#J%!\"YQ!\"J%!$:-$#IY!%*1##J!!!*!!\"J!!$J!%" + "%)](#9]$#I]!$9U$%)Q!!YQ!#J)$$YM#$)Y#$9U$$IY\"%)Y!#9M!&)](#9I!$)U#" + "$9M!&)U$#)U##9Q#$*%##J%!\")M,$IU%$)M##YM&$YI&\")E\"\"II$$YE##YE#%)-(" + "%)E$#IA!&9M&\"I1!\"YM\"\"I=!\"99#!)9*#9-!\"I1!#95!\"I9!#))##I)_$\"I)*" + "#(Y!!Y-!!)-!#I%##I%##I!#%)1(\"I)!$8]\"#8Q!#(U#!(U!!8U(!XQ!\"8Q!!HE#" + "\"8E!$HI$\"8I!\"XE(#XY#!XA!#H5&#(I##(5$!(9!#(5$$85&#H)#$X1#$8-&\"X-\"" + "#85'!WQ'\"8!!\"X!#\"WY!#GY!\"X!#\"(%%#']$#'U'\"WM##WA'\"WM!!GQ%#'I$!GE#" + "$'A&\"7A$\"'=!!W%\"!G=!!WA!#W=%!G1!\"7%$!'E%!G)!!FY!!F]!\"6Y$!F]!\"6Q$" + "!&M'!FM!!FY!\"&U#\"&U#\"&Y\"!FU!!V]$!'!!#&]'!'%##7-#\"75&!G-!#7)#!G1!" + "#'5&!G-!\"GE#!WA!#7A(!GM!\"7I##GM&$'Y(\"WA!\"WQ%!GQ!!WQ$#7Y%!W]!\"7]!" + "!'U!#W]%\"X-##85%#()$\"85!\"(%#\"8!!#(1!$(9(!H-!\"89!\"X)#$(E'\"(=\"#XA'" + "\"8A#\"X=#\"HE!#XY#\"XM\"\"H9!#(I#\"(I%\"8U!#9!!#8I\"$XU$\"(]\"\"Y%##XI!%)))" + "#9)!$)-$$Y-$\"I-!\"Y%##)1##Y5##9=!\"I5!\"Y1\"!Y-$\")5\"$I1&#Y)&$9I%\"I9$" + "#)5##YI##99!#)E##IE\"#IE%!YI!$9A$#9E!$9M!\"YM\"#9U!$)A$#YQ##9A!#9U!" + "$9I$#)U#$9]!#II\"$99%#9]##J!!%9Q)&9Y\"$Y]'$9]$\"I]#$:!$%YI!#9U!#Z)\"" + "\"9]\"$J!%$JA!#J!!#YY\"#Z!%$:!!\"Z%$\"YY$!Z-!$Z)##J-!$IY&#J!!%)]!%Y]'" + "$J!&$*%##J1!%*!#%J-%!*%!%)I%!*-$$I]\"#Y]\"#9U!$*-#\"J%!#J)!\"YY\"$*!#" + "$*!#$*%##J!!!YY!#J!!!YQ!$*%#$J!%$)]##J!$#J)!#)]#$)]#&:!&#IU!#YY\"" + "%Z%+%9U\"$9U$#IU\"#IM%\"J%$#9Q#&II($9]'$9Q!$YM#$YU#$II%#9Q!#YE\"#9I!" + "$)=$$)A!$II&#)A&$YA$$IA\"\"I=!$YE&\"I1!#))##)9#\"))\"\"I5!\"Y-\"\"XY\"!Y-!" + "\"91##)-##))#\"Y-\"#)5##Y)##(Y!#9!!&Y!.\"X]\"\"I!!\"HY!#8]'$(Y'#XI'!8U%" + "#XQ&\"8Q!!H]!\"8Q!&(M!#H5#!HE!!8M%\"HA!#H9&\"H=\"#81%#X5'#(5!\"X-\"#8-\"" + "$(-(\"8%!$(5&#H%&!H!#\"8!!$GY#$(!%#'U$\"WU#\"GA#\"GQ\"\"7M!#7M%\"7]!#7I%" + "!WU\"#'5'\"'E#!G=!\"'9\"#'9$\"'5#\"7-$#71%\"G5$\"'-!!G)!!G%!\"G%#\"FM#!FY!" + "\"'!##&Q$#&U'!FU!!&]!\"&Y\"!F]!!G!!\"'!#\"'-#!')#\"W)\"#7)#!G1#\"'1\"!G=!" + "!W9\"\"7M#\"'=#\"'Q#\"W=%#GM(\"GI#\"'E#\"WQ#!'Q!#'Q$!'E%\"7U!!'Y#\"W]#\"W]!" + "\"WU#!X%$\"8%!#X%'#81%%(-'#X1&\"81!$(5(%(=&#(=!\"H9!#(=##HA\"\"XQ\"%8=$" + "\"8E!!HM!\"8E!!89\"#(M#!XM!#(U##(Q#\"XU\"%8Y&%)!+!HY!#(E$$XU%%)!##Y1#" + "#)%#\"Y)\"\"X]\"!)1!#I5%$)9$\"Y1\"#Y9#!Y5!#YE%#Y5##I=%$9=%\"IM!#YQ)$)A#" + "#YE#%9Q)%9A\"!YA'#YI##YQ%$)U#$YA$#YM\"#YQ)%)=!'9M+$9Y!#9U!#IY!#)Y#" + "\"IM!!IY#%YU*#YY\"$*%'\"J!!#)]##I]!%9])#9Q!$*%#$Z!#$:!$'Z!%!J!##Z!\"" + "#Z%&#J%!#Z%\"#J%!!Z%!%IM&$J1%#J!$\"J%!$*)#%:1!$J)\"#J1!$Z!\"#Z!\"$Z!#" + "#:1##I]!%Z)##J)!#Z)\"\"J!!%J)\"%Z-#$J%!#Z-\"$:-$#*5\"$:%$#J-!#I]!$*!'" + "%*%##J5!$:%$$:%$$*1#\"Z-!#)]##Z!\"$)]#$*%#$9U!$*5#$Z%&$)]#$)Y#$)]#" + "$I]%$)]#\"YU\"$9Y!$I]&%9Q(%*!!\"IQ!$IE%$9Q!%9Q($Z%#$9Q%%IQ##9I!#9I#" + "%II*#9=!$)I!$95%$9U!#Y5#$IA%%99##Y=#%9A#!9I)\"Y1\"$Y5*\"9M#\"I5!\")5%" + "#I5\"$I-'#)5#\"Y-\"#Y)&\"I%%%9!&$I) !!#Y!#&(Q'\"I!!#HU%#8U$#(M##8M$" + "\"8Q!#8U$#XI'\"XM\"#(I#!HI!\"XA#\"XE\"!HE!#(A$#(I#\"XA#!(9'#X5Q\"\"(1#" + "\"X1#!8-\"#H)%#H)%%'U\"!GI!#7Y\"\"G]\"\"W]#\"'Y%\"WU##7Q&!WE$\"7U#\"7E!$'M&" + "$7M&\"'M#\"'9\"!7A$#'5&\"G9\"\"71&\"W5+\"'1!!'-!\"G-\"!G-#!G)'\"'%!\"7%$#VY$" + "!&Q!\"W%#\"&U%\"F])!VU\"\"F]%!V]&$FU)!G%%#7)%!W1\"!G)!\"71#!G%'!W5\"\"G=#" + "\"G-$\"'E!!G9!\"'A#!WA\"\"'A!#GM$$'M!\"8%!#7Q(#GU&!GY!#'Y$!WU$\"7Q&$H!\"" + "#(%$$X%#!X!!\"8)!!8-%#(5#\"89!!(5!\"X5##XI##(=#\"H=!#8A!$(=%\"XE#!(9#" + "\"XY%#(U##XM!\"X]\"$9!($(]!\"8M!\"HM!!HM#\")!##(]#\"I!!#Y%$$I!'!Y!!#I!%" + "\"I)!\"9-#$Y1!#I)\"\")=%$I1#\"Y5\"$)9!#95$%I-$#9A$#Y=#\"IE!$)I#\"I=!$9M$" + "\"Y=\"%)I%$9Q!#9Q!')I*\"YQ$\"9M&&)I\"#YQ\"\")Q\"$9I\"#I]!%)E$$YY#$)U#%)Y!" + "$)Y#%)I%#IY!$)]#%I]*$I]%$J%!$9]$#Z!\"#Y]\"#J)!$Z%&#Z%\"#Z)\"#YU\"%:)%" + "%*-#%:)($*-*#Z!\"#Z)\"$*)#!:)\"#J-!#Z-\"#Z-\"%*-'$:-!\"Z1!$:-!#Z1\"\"J-!" + "&*-'#*)\"%Z5-#J1!$:-#$:-!$*%##Z5\"$Z1&#J!!#J%!%Z-#!*-!\"*)%#Z1\"&:%%" + "%*)'!:-%#J)!&:5)!Z)!$Z%&#J)!#J!!%:%!#J%!#J=!#J%!$:!!#:5#$Z%&$:!$" + "$*%#$J!%#9U!#9]$$*!##IQ\"\"9I&$YU'%IY&#)A##IQ!$9]$%)U(#YM#&)]($)U#" + "#9U!%9=)\"I-!#YI#\"YQ\"$IE#!YE!#YI&\"9I#%YQ!#Y=#\")=\"\"Y=\"$)9!#)9#!)1!" + "#)-#$I9##I1%#)-##I-%#))#\"Y)\"\"I)!$9%%$I5&#I!%#(]##XQ'!Y%!!9-\"#X]&" + "\"XM\"#X]&$8I#%8M*#(M#\"HY!%(I#\"89#$8E&#(A#$(E$#H9#!H=+%HA##X1'$X5+" + "!H1#$(-%#GY#\"8)!#X-'\"8!!\"X!#\"7]!!G]!\"7Q!\"WU#\"GY\"\"7U$!'Q##7Q%%7I(" + "!GM#\"WA#\"'Q\"\"7A##'9$\"7=!!GA!\"'9!\"'-!\"79$\"GA%\"71$\"6]$#&]\"#7!&\"&Y#" + "!FE!\"&M#!6Y\"#&Y#!F]!!F]!\"7!$!VQ\"!G!!#7)'\"'-#\"G1\"!'5$!G5#!G9!!WQ$" + "\"'=#\"GA##'9'\"GU\"\"GU$\"'I!!'M&\"'A!!WQ!#7U%\"W]##8!%!7U\"\"WU#\"X)#\"H-\"" + "\"8!!!H-!\"(!##(5#\"X-##(5$#H5&\"HE!#(5&$HE*#8Q$#(I#\"8A!\"8E#!(A#$(U!" + "#HM&%(Q##(Q#\"8M##(U##(U#\"Y%#\"XE\"#XY&$))!#9%!#(U!!9)\"#XQ#$))$#9%$" + "\"I1!\"8]#$Y%'$)1$#95$#I5\"$I=&#Y9#\"IE!\"9A#%)M!$Y=#%)A(#9E!$9E%#9I!" + "!YE!#II!#9M!$YU M!$IQ\"$)U#$IQ%%*!$$IY%$IQ&$:!!%)Y'\"IY$#Y]\"!9]&" + "!9U\"$9U!#J!!%:!$$J!&#Z!\"%:%!\"IY$&J%&$J))%*5#$*%##Z1\"%Z)'$Z1&\"Z)\"" + "#Z%\"!:-)#J-!')]&$:%$#J%!!:1\"#Z)\"#J-!!Z-!'J1*$*)#$Z1&$:!!$Z-#&:1%" + "$J5!$:1##J5!\"*5\"%Z1&$:1!#J1!#J-$&:--$:1$#J!!&*-!\"J!!!Z-!%J-\"#Z)\"" + "%:%!#J9!%J-\"#Z-\"#Z!\"$:%$#Z)\"#YY\"$I]\"$:1##J)!$:)!#Z%\"!*!!#Z%\"$)U'" + "$YU#%)Q$#Z!\"#Z%&$J%%$)]##Y]\"$9Y$$)M##:!#$*!#%)Y+&)I\"#I]!%*)$#Y=\"" + "%)Q!$9Y$$)A#$*)#$)Q##YI##IQ%#YE#$)E$%9M%$YE'#YE\"#9-!\"IA!$95(#Y5#" + "$)9!!Y1!\"I9!\"Y1\"#)=#!Y=!#)-##)%$$))$%9%*$)!!#Y-##I!%#)%##(]#$8U\"" + "&)%*#XQ!\"8Y!\"(Q%#I)%!H]!#XE&\"I!!#XE&\"8E!#89!#(I$#89%#(A##(9!#XA!" + "#(5!\"X)#\"81!\"X-#!H1!#H%(\"X)#$X5%\"H%!$'U#\"8!!!GY!!X%'\"GY\"$'U#\"7U!" + "#WI%\"7I!\"GI#\"'9#\"GE%!G9!\"G=%\"'5\"\"W9(!G1!\"G1%\"7-$#'-%#'!'#W)##'!'" + "!G)!!&Q!\"F]#\"&U!\"7!\"\"6](\"'!#!W)\"!G1!\"'!!!'5#!71\"\"'5!!G9!\"G9\"#'-'" + "#G))!'=!\"GA$\"7Q&#WE%\"WM#\"WQ##7E(\"WU!\"7U!#G]!!WQ$\"(!#\"H!!#(!$#G]!" + "\"8!!\"8M!\"X1#\"85+!X=&\"X=#\"X5\"$H9$\"XE\"\"XI\"#(5$#(E##XM$\"HI!$(I%#8M$" + "#8E$#)!#\"(I\"\"8Q#$(Y(!HY#\"HY$#X]##)!'$XU!$8]\"!Y)!#I%\"#I)%#)-#$)1!" + "#Y1##I5%$)5'\"I5$!9E\"#)5#\"Y-($)5!$9=\"#)M#\"9=#$YE&&9A-%YE!!IE)#9A!" + "#IM\"$9E\"#YA##YQ\"#YE#%YM$$)U#$)U#$9U!#IY!#YM%$:%$%Y]-#I]!%Y]#%YU(" + "$)]#&*!!%:!!%:-(#J)!#I]!'*-!#Z9\"$:)$$J1%&J-'%J%&$9]!#J1!&*-+$*%#" + "#Z1%$:)$$:1##J1!$J1!\"Z1!$Z=&#:1##Z1\"%J1\"$J5%#J1!#J9!$:E##Z5\"%*5'" + "#J1!$*5\"%Z5&!:5\"#J5!#J5!#*9\"$:5#%*5##J-!!ZI!%:5(#J9!$Z1\"\"J1##Z-\"" + "#J1!$Z1\"#J%!%*1##Z5\"\"J1!#Z-\"$:-!#J-!$*-'#Z5\"#Z-\"$*-#%:)!#I]!$Z%\"" + "\"J)!#J-!$J5!&Z)+#:-#$J-\"\"J%!':-*$)]##YQ\"#J!!\"YY$$IY%$*!##9U!%IQ'" + "%9Q)#9Q!%I9!#YQ##IE(!YY$#9I!&)I,$9M!#YE\"!YI!#9E!%I1'&)E&#I=!#Y=#" + "!I9)#95$\")5\"%9-'#Y9#$9-%#)5#\"I-!#)-##))#!Y-$%)%)%I%!#I-\"\"I!!\"Y1%" + "\"XU\"\"HQ!$9!#\"HU!!8U\"#8U$#(U#\"XM\"!(E!#(I#$8E)#HE#\"HE!\"85!#H=\"\"X9#" + "!()!\"X5\"\"8)!!8-\"#H-#\"81!#8)%\"X%\"\"GY\"\"7]!\"8%##'Y$\"'Y#!W]!\"W]#\"WQ#" + "\"WQ##GQ!!GE#\"G=\"!7Y%\"GE%\"W=#\"'9\"#W1%!W9&\"G9%#'1&!W5\"\"7%\"#'!'\"G)%" + "!FI!!VY\"!G!!\"&Y!!W!$!G%!!G)!!'9#\"G-%\"G1#!W1\"!W5$!W9!\"'I!!G1!#79'" + "\"WA%\"'E##GI&#'A$\"7M!\"GQ\"#'Q$\"WU#\"WY##7],#(!$#X!!#8!\"#(!$\"8)!#(9!" + "\"8)!\"X-\"\"8-!\"(5%#X-$\"X-\"$HA$$H-$#8A%!8=\"\"(=(#HM)#8Q$\"X]\"#XU##(Q!" + "#(Q##(]##XY#\"8]!$XI%$(]'#H]%$X]$'9%/#I!#\"I)!\"I)!!95\"#9-!$)1'\"I5!" + "!Y9!#95$$9)%$99\"!Y1$\"YE\"$)I$$95\"$)A$$YA$$)E#&9E##9I$$9Q!#9M!%)E(" + "#YQ\"&)Y,%)Q$$YY&$IU%%)I($IY%!YY!$IY(%I]*$IY)$I]\"$I]\"\"9Q#$*!#&*)!" + "%J%\"$:%$%J)\"$J)%%*5'%:%!#Z%\"#J)!#J5!$:-#!*-!#Z-\"$*5\"%:1)#JA!\"J1!" + "'J-'%J9\"#JA!#J9!$J)%$J5!#)]#%:5!$*A#%Z=#$J5!\"Z5!%J9)$JE%#JA!#J9!" + "$*=##*9\"\"Z%\"#Z9\"\"*1\"#J9!\"Z9!%*=#\"*1\"#JA!%:E(&*9+\"Z5!$:)!\"J%!%:1!" + "!:-\"#J1!!9Y%#J)!#Z5!#Z9!!Z!!#Z%\"$J1($*5##Z!\"\"Z1!!*-%%:)!#J-%!:-\"" + "%Z5#%*)##J)!!Z)!#J-!#Z-\"#J%!$J%)#I]!#Z!\"':)&%J))$I]\"$Z!##9Y'$)Y#" + "#9M!#YM\"#9U!#I]!#IQ+$9M%#)Q\"%)Q!$)I##IE!$II##9Q!!IA)%IE$!)A!&)-#" + "#Y9#!)=!!)1$\"I-!!)1!#)-#\"Y5\"$Y5$\"Y1\"#)-#%)!\"#Y)&$Y%+$)9!\"I%!#9)!" + "\"I)!\"8Y!$(]$#8]!#(I$#8]$#HU%\"HQ!#(M!\"8M##HI%\"XE\"!HA!\"HE!#HE\"%8=%" + "\"85!!H=!!(5!#85\"$H1*#H-#$(-##81\"\"H!\"$H%(\"8)!#(!$\"7]!$H!*\"8!!\"7U!" + "#GM&#WU'#8%$!GI!\"GI\"\"'E!!7A\"\"GA.\"G-'\"'9\"\"G9\"$79$\"'=\"\"71$\"79#\"7!&" + "\"&Y!\"&Y#!&U!\"W!(\"&Y!\"'%#!'1!!W-!$'-(\"G)'\"G9$!79\"!W=\"\"7I$#'A%\"'A#" + "!GA!\"'9!#7I%\"7Q!\"GI#$GQ\"%'Y'$'Q!$7Y'\"GQ\"$7]$#W]%!H1!\"8%!#(%$\"(-\"" + "#8-%#(5!\"X5#\"85!\"8=!\"X=##(9!\"XA#\"XE\"\"89!\"(I\"\"8A!#(I##HM%!XU$$(U%" + "\"8Q!$I!'#HU%#(U#\"I!!$(U'&)5&\"H]!$)!!!Y)!\"9-##I-%$9-+#9-!\"I-!!Y9$" + "#)5##99$$99%#)1##)A##9A!$IA&\")E\"%IE*#9M!$IU\"#YM#$YM&$YU'$9Q%#99!" + "$)Q$#9Q!$IE&%9U%#)Y\"%)U!%IY'!YM!$9]!$*!#%:)($*1#$*1#$*%#%:%(#J1!" + "$Z%##J)!#Z)&%:-!%YY$#Z-\"%:-!%*='!Z5!%*5'\":5\"%:5+(*9!#J5!#J)!#J1!" + "$*A&#JA!#J9!#Z9\"$JA!#Z5\"':1\"\"JI$$Z9\"!*9$$*M\"#ZA%\":E\"#ZA\"$J%&$J=%" + "$:=$&*E(#J=!\"Z=!#J9%\"Z=!&:=,#J9%$ZA\"\"ZU!#Z9\"%JM)\":5*$J9!%:=!$JA!" + "$J9!%:5(\":5\"!*%!%ZM\"#J5!$J5!#:5##J5!$Z5\"#Z-\"#J1!\"J1!!Z9!!*5!\"Z%!" + "#Z-\"#J1%\"Z-!#J-!#Z)\"&Z%!$IU\"$J)\"$J-!%*)'#Z%\"$J!&#*!&$)U#%9Y%#I]!" + "$)]#\"IY!!)Y!#9Q!$9]$%)U!%IQ##YE#$)E#$IM\"\"IM!#9M$$)9!$)E#\"9E#$IA#" + "#IA!#YE#$I=c$#9)$#)9)#I-(\"Y5\"%91&\"Y=+\"I-!\"I!!#9%%\"Y!#$Y%$#))#" + "$I)&\"H]!\"8]!$)%!!HQ!\"8Q!#(]##(Q#\"HQ!#(A!\"X=#\"8I!#HI%#8E%$(A($8A)" + "\"8A!\"X1#$H5*#(1$\"81!#81%#81\"\"H)%#H)##8%%$H%'#H!&#H!$#X%'\"GM\"\"WU!" + "#WQ'\"GQ\"\"WQ%#7E%!'Q#\"GI\"#7A%!'A!#'E'!G%!\"WM&\"'-\"\"W5%\"'1#\"'1'!W-!" + "\"'!#\"V]&\"G%\"!W)\"\"7)$\"7%(\"W-(\"71#!V]\"!G-#\"75(#W9\"#7=&\"7=$\"7A$!G9!" + "!GI!#7M%#WM'\"WU#\"WQ#\"7Y$#7Y%\"7Y!#'Q\"$WU!%!H!!\"8)!#85%$8-!\"85!" + "\"81!\"X5\"\"85!!(9!#81\"\"XA#$H9%!HA&\"8E!$XI%#(I!#(M&!Y!$!HQ&\"(Q%!HE&" + "!HY!$8Y\"\"8]!\"Y%#$)1!#9%%#I!#\"I%!#))#\")-(#Y1##)1##)-#$I5#\"Y1\"\"Y%\"" + "%)9(\"Y=\"#9M$$)A$#I=!#9A!#YE##IE$$YI'%99)#IE!$9E$#9Q$%)Q!$)I!$YI#" + "%YU*#J!!$)Y##9]$$IY&!YM!%YU#\"Y]$%Z5\"\"Z!%\"J!!&J)*#Z)\"#J1!#Z)\"$*)#" + "$Z1&#J)!#J-!\"*-\"\"J)!%*1#$:!!#*9\"$*5#&:9($J5!$:E#$J5!#Z)\"$*9##ZA!" + "#*=\"#ZE\"$J9!#J=!#JA!#JA!$Z=%#ZI\"%*9'%:=$$:9#$J=!$*A#$ZA&&Z5#&:E!" + "%*A'!:A\"$JE$$JI$$*A#(:9.%ZQ%$JQ!&*=($JA$&Z=.\"Z9!#J9!#Z=\"#Z=\"#Z9\"" + "#Z=\"%ZE\"#JA!$J-\"$*=#%:=($*5\"#J=!#J1(#JE!#J=!#*9\"#Z5!$:5$#ZA!\"Z-!" + "$:9#\"J1!#:-##JE!#J1!#*-\"%J))%:)!$IQ&$J1\"%*1+%J!\"#J%$%:!\"$9Y$$IY%" + "\")Q\"$9]!$Z%\"#)Y-$)Y#$YM'$)]#$9Q$$IU\"#YQ#$)Q$\"J)!#9Q!#9A!$)I$$IA&" + "$I9#$9=%$I=#$)9$!I5#$9=%#9-$%)A\"\"I5!#Y5&%)1(#9)$\"I-!\"9-##H]\"\"I!!" + "#9)!#)-##I!\"#XY!%(M)#8Y!!8U\"#(]#\"9!#\"XQ\"%XE##8M$#(M##XM!!HI&$8=(" + "!HA!\"X=#\"8=##(5#!(9$#H5&$(%(\"WY!#X-$#(-$\"X)#!H%!!H!!$'Y!\"8!!\"7Y!" + "#'E$\"WU!#']$#7I##WM\"\"7Q!\"WI#\"'E#\"7I)!G=(\"W9!\"G5%\"79&\"WI#\"')\"!G1!" + "!6]\"\"6]&\"'%#!7!\"#'))\"W-%*\"'1!\"'5##W1*!W9!!W=!\"GA%\"'9\"\"GE\"!GM!" + "$'Y&\"WY#\"GI#$'M#\"7U!\"WY%$GM#\"'Y%#GY$\"WY#\"7]##X=$!(%!#()!\"81!#(1#" + "#H-##H5#!HA&\"8E!\"X=##(A##XE!%8E$!(E!\"XI\"!XI!#(I$\"HQ!#XU!#(I#%(Y\"" + "!HU!#H]\"\"Y!##9-!\")!#&)%'#9)'!Y)$#9-!#9-!$9-%$Y=*#91$%I9$$95\"\"I9!" + "#9=$#Y=#%I9.$9E$\"IM!#YQ\"#YI##9=!$9M!#YM#%IQ*$YU##YI#$YY'$)U#$YY'" + "$)Y##YY\"#I]!#YE#&:!*\"J!$$Z!'$*%##J%!%J-\"$J-\"\"Z)%#*%#$J-%#*-\"$J-\"" + "$*)#$:-#\"J1!#Z5\"$J9%#Z)\"%J5)#J5!#J9!&:9%#:5#\"*=\"%J1\"#J9!$JA!!:E\"" + "$Z1&#Z=\"!Z%!#Z5\"$JE!&JA-#JA!\"ZI!#JA!#JA!$ZA\"$*=)#Z=\"%*I#$*Q\"%JE(" + "!ZM$#ZI\"$ZI&\"ZE!#*A\"#ZQ!%ZE\"\"ZM!#ZI\"#*A\"#J=!$ZM!#ZA!#ZA!$JQ!$JQ%" + "#JA!#J=!$*A##ZA!#J5!&JE)#J=!$JA!#ZE\"#J1!#J9!$:!$%:E$#J9!\"Z9!#Z5!" + "#Z-\"!:%\"%:9!$J1\"\"Z1!$*!##Z-\"!:-%#Z-\"$:-!%Z-&&:))$:)$$:%$%*!($9]$" + "#)]\"&J!#%J!&$J-%$*)#$9Y!$9Y$%YM!$)U##YU\"\")Q\"!9M%#9M!$)]#%IA'#9M-" + "#YM\"\"9I#$YU#%)=(#9E!#Y=&\"9=##)A##9A!!9-\"#)5#\"I!!!91%\"I-!$9E%!Y)$" + "&)9\"#HQ\"#I!#$9!##)!##(M##9!*$(I'#I-%$(M%\"XU\"#(U&!(=!\"HQ!!8E%$(E%" + "!HM#!HI#\"X=\"\"X=\"\"(!##85%$8=##(=!#H-#!(9!\"H)\"\"X!!#(%$!X!$$H!%\"W]#" + "\"7U!\"WY!!GU!\"7Y!\"WU#!WE$\"'I!\"GE\"!GQ%\"G1$!GA!!'A$\"7M!!G)#\"W1(!G1!" + "\"'!%!6]%\"'%#!W)\"\"G5\"!G-#!W-!#75%#'5%\"G5%!W=$\"GA%\"'E#!'A$#'E$\"7]!" + "!GM#!W]\"#'E$\"WU##WY\"#W]'#7M#\"X%#$(%(#X1&!X)\"#H)#\"89!$H1'\"X)#!HA!" + "#(9$\"8=!$8=##8-%#H=%\"XE\"\"8E!#HI\"\"HI!$XM+$8Q)\"HI!#HU%#HU%$(Y'#I)%" + "\"I!!#I)\"#9)!\"I)!#9!!$9)+\"I1!#Y%$#Y)'#Y)#\"Y5\"#Y%'#Y5#\"I9!\")A%$9=!" + "$)E#$)I!\"9E#$)A#$)A!%IA*%YI!#9=!#IE\"#IY!!YU!$9M!$*!##YY\"#Z%\"#9Q!" + "\"IY!$YU#$:!$$*!##)U#\"Z%!%I]*$*)##J-!$J%!!J-#\"Z9!%JA%$9]!#Z!\"$J1!" + "#J1!#Z1\"&JE)%*9#%*I'#JA!$:9$!Z-!&J9\"#Z9\"#JI!#J=!$:E$#J5!\"ZA!#*A\"" + "#ZA\"#ZQ!#JA!$:)$\"J1!#ZI\"#JE!$JE!$ZE&#JE!#JE$\"ZE!$JI$':E%$*I\"%:U'" + "$ZI&%*I#\"*Q\"#*]\"%:I$%*Q'$J=!#ZI\"#JM!%JE)$ZE\"#JE!\"ZE!$:Q##JA!\"ZI!" + "#*M\"#JE!$ZE\"%*M\"#J=!%:A(#JE!#*=\"&:E!$*=\"$:=##JA!#Z=\"%*9&#JE!#*9\"" + "!Z9!!ZA!#J5!$Z-&\"ZE!&*)(\":1##J9!!:9\"%:1!#Z)\"$Z!\"#*-\"%:)!#J1!!YU!" + "#J%!#J%!\"J!!$Z!'$*%#%9U)$Y] ]##Y]\"#IY$\"IU#$IU%#IQ$#IU!#)Q#))U," + "$9I\"%YI+$9A$\"I5!\"IA!#II!#9A!#)=##)A#\"YA\"\"I9!$9)(\"I5!\"Y1\"%Y=,!9-\"" + "!Y9!#HQ%#91!#Y%##Y-&\"9%#$(U$#X]##X]&#(Q#!8Q\"$8Q\"\"HQ!\"XQ\"$XI+\"HM!" + "\"XE%\"89!!8E%\"X1#$8E&#H9&\"HI!\"(5\"#X1'#(=!!X-!\"8)!$85)\"H%!\"H!'!()!" + "$7M$\"W]##7U%#(%&\"WQ!$WQ+#GM&#'E$#GE&\"'A#!7A$\"GA#!GA!!75'\"G1)\"'E%" + "!G)!#G%\"#W%#\"71#!G-!\"71$\"W5#\"'5\"\"'I)\"'E#\"WA!!G5!!GM!\"'E!#7A!!GQ!" + "\"WU!\"GU\"\"7U#!7]$!GM%\"8!$\"GU\"\"X)%#X%$!H)#$89(#HE\"\"X5\"#85'\"X5#\"89!" + "\"(1##8I$\"XA\"\"(I%$8M#\"(A\"#HM##(M#!XM$#(A$\"8U!#95!#I%%!HY!\"X]\"#XY&" + "$HQ##I!\"'9%%#I%\"#9-!#91!!Y)!$)1'!I=##)5##95!%9A&#)5#$Y9'%9E\"\"I=!" + "\"YU$\"IE$#)9#$9U$#Y9##9Q'$IM&$IQ\"#9Q!#9U!%IY##9U!$)Y#\"IY!$Y]'#*!#" + "\"J%!$*!#%)]!$:!'(:%+\"Z)!#J)!#J)!$9Y!$J-%$J-!%J%\"$J5%#J1!$:5##J5!" + "\"Z9%\"ZE!&:9,$J5%$J=!!Z9!$*9\"\"ZE!$*9\"$:I$#ZA\"#ZI\"#ZA\"$ZE%$ZE&$*E\"" + "%:E!#J=!!:E&\"Z=!\"ZI!#JI!$ZI%$:I##ZM!#JE!\"Z]$&:Y,#:A#$ZI!$JI!#JA!" + "#JE!$Z9&!ZA!!*Q!!ZI!%*9&#ZU!#ZQ!#:A##ZE!&*E($*9##:U\"#ZM!%:I'&JI!" + "$JE!':E1#:U#$*E\"'*U#\"Z5%#JM!$J=!#JE!#J=!#J=!\"Z=!$ZI\"#JA!#:=&\"Z-!" + "\"ZE!$*I\"#JE!#J5!#Z9!#Z9\"$J5%#Z5\"#J!!$JI$#J1!\"*1%#J-!#J-!$*-#!:-\"" + "#J1!#J%!#J%!&:-)#J!!$*!##J!!$9Q!$I]&#Y]\"\"IY!%)Y!#)]#$)Y##9Q!$YQ#" + "$)U#$)I#$9A$#IU\"#YE\"$9I!#Y=#&)A,$)A$#)M#\"IE!\")=\"!Y)!%Y1+\"I)!\")9\"" + "\"I-!#Y5&$)-$\"8U!#9!!#(Q!%91)!)!!$(]$\"(M\"#I!)\"HU$$HM*#(E$\"8]!!8M\"" + "!XI!\"8Q!%8E'#8I$%XE#\"81!\"85!\"89$\"X)\"!(1!$X5%#85%!H9(\"H-\"#X%'!G]!" + "%']'#W]'!GU#$'Y(#7Q%\"7Q!\"'Q#\"7M!#'I%#7I%\"GA$\"GE%!W=$!G=#!'-#\"G5%" + "!W%\"!W%\"!7)\"!G)#\"W5%#'5$#G5&!'=!!G9!\"'=#!GI!\"'E##'A$\"'E!\"7U!#7A#" + "\"7Q!!GU!\"7Y!$GE#\"WY##GU&!G]!\"G]\"#(%$\"8)#$7])#(I$\"81!#8A\"#(A#$H9*" + "#X-'!H=!#8A%#85\"!HA!!8I\"$8Q(\"(M\"\"8Q!$HM)\"XU\"#XY#\"XY\"#(]#\"8]!$I)'" + "%Y! %!\")!##))#\"I-!\"Y5\"$I)#\"I5!$I-&#)=##Y9&#IQ$$Y9$!YA!#9E!#YQ#" + "$IE&$)E$#IE\"#9U!#9M!&)Q(&9M.$)U#$IQ&$9Y$%)]!&9Y&%)]!$I]%%:!$%Z%*" + "$*)#$:1!#J1!#J)!&J-'\"I]!%J5%'Z-('*9%#J1!$:1#%:=!#Z=!\"J5##J9!#Z-\"" + "\"*9\"#*5\"#ZE\"#*=\"%*9&%JA%&:A!#JI!#Z9!%:A!#JM!#ZE!%ZE*$ZE\"#ZE\"%*I#" + "#*I\"$:I#&:E$%JQ!':9\"#JM!$:E#%*M&#JM!#JA!%JI)#Z]!$J]$%*Q*$JM$#JA!" + "\"ZM!#ZM!(:M*#:M\"$:M$#:I#%JI!#ZY!#JM!#JM!'JI&#JM!$ZI&#ZE\"$JI$#JM!" + "#JM!#JI!$JI!#JE!%JY(%*E'$ZA\"%ZM*#JE!\"*A!\"*I\"%*A+#J=!&*9+$:A##ZA!" + "#:A##JE!':Q(#J1!%:E!#Z-\"$Z9&&*1!#Z9\"\"Z5!%J1-#J1!\"J)!#I]!#J%!$J-%" + "!Z5!#*!##J)!%Z9*\"9]&$*!'#Z%%$*!#%IY'$)Q$$IY%&IY$$IY%!Z!!#YQ##YQ#" + "\"II$$9M!$9M(#9Q!$IM%#YE\"!9Q\"%9E%#9A!&IE($)1!#9I#\"IE!#)9#$)='#)5#" + "$I9)\"Y1\"&9-*#Y%$#9%%\"I%!$9%##(Y!!)%$#(Y##XU'#Y!&\"8Y!\"8M!#8U$!HM!" + "$(M'\"XA#\"XU\"\"8I#\"8A!\"(5\"\"XI\"\"H9\"\"X=\"\"H)\"\"(1\"!X%'\"8-!$()(\"7]!#7Y\"" + "#H)%$(%##H%##()$#G]!\"7Y!\"G]\"\"7Q!\"'Q#\"WI!#7Q'\"'E#\"G=%\"'A#\"G9\"!'1%" + "\"G-%\"'%#\"G-$!G-!\"G1$\"WM&!GE!!7A\"#'5$!WE!!WM!!7I\"\"7I!#GY!$'I)\"GA\"" + "\"H%\"\"G]%\"W]#\"G]\"#GY##H!&%8%#\"8%!\"(-#$(9%\"81!\"X%\"#(9##X='\"8)!\"8=!" + "!8A\"$8A(\"81!#(I#\"(M\"#HM\"\"XU\"%8U*#8]!$8U%\"8Y#%I%+\"8]#\"HY$#9-!\"8]!" + "$)%%$Y)+#99$#Y)'#91!#)9#!Y5!#99$#9Q#$)M&\"I5$#9E!&)A%$Y=!#9A!$YM#" + "%)9(#9M!\"YI!$IU%#YQ#%*!#!YU$$)Y##IY!#IU\"#YQ#%)]'$*%#%9U)&*%!&J%#" + "#J%!$:%$$Z9\"$:%$(Z-&$:-##J1!#*1\"$J5!#Z9\"$J9!#ZE\"#J5!#Z9!$*=&!*=!" + "#J9!&*-+#JA!%:1(%JU!$JA!#Z=\"#JE!#JE!$*5##JI!#JE!#ZI!$JM%$*U\"#JM!" + "$:E$$JM!\"ZM!\"ZM!#J=!#ZQ!%JQ(#ZQ!#ZQ!$JQ!#ZQ!$ZI%#JM!$:U##ZY!!ZQ!" + "#JM!&:Q($JE%\"ZQ!&JU%\"*Q\"\":Q\"%*I#&*Q#!Z]!$:Q#%JQ)$+)\"$*Q)#ZU!\"*Q\"" + "$:Q#%JM)$JM!$*U\"$[!&':M!%JQ!&ZM+%ZM&&:I%#ZE\"$J5!#ZY!%:E!\"Z=!\"ZE!" + "$*M\"$ZA%\"*A!%:A($*9\"#J9!!:=%#J-!#JE!%:9%#Z-\"$J5!$J=!#Z)\"#J=!\"Z)\"" + "%*1''*9)#Z9!$:-$\"Z!\"\"Z)!$*%#!Z)!%:)($*!#%Z!'#J!!$IU%$YU'!Z%!#9U!" + "\"IU!%)Q'\"9Q##YQ##9I!#9M!$IA##IQ!$)E&!)E!#Y9##Y=#\"IM!\"I-!!I5&$Y5$" + "#9A!#9=*%I1$#)-##91!#91!$9!%#9!!#9!!!Y!!#8]!\"(U\"\"I!!#(Y#\"8I#\"XQ\"" + "!(9$\"HI!\"XM\"#(I#\"HE$#(M##(=$!HE!#X1%#89%#(=!!()!$HA*#()'\"81!$(%&" + "\"X%!#']&\"8!!#8!$#GY$#'Y$!GU#\"GQ%\"7Q!#7M#$7I'\"'E\"!'Q#!7A%\"75#\"'E#" + "#')%!'-!#'5'\"W5&!G5&\"75$\"7=$\"'=#!GM!\"WE%\"'E#\"WE##7Y%\"GI#\"GQ\"#7Y#" + "\"X%##GY!\"7]!\"H%$$8%%\"\"WY#\"H)!!X-!#H1&\"H1\"\"89!%89%\"85!\"HQ$#H=\"" + "\"8E!!HE&$HI'\"XE#!(A!\"XE#\"HQ'\"8U!#XUY$#HI#\")!(%9%,$8]%#9%!!)-!" + "#))&!Y9!\"I-!$Y)(\"I!!$I5#\")5\"\"I9!!9I%$Y=!#I9\"$)I$#YE%&)E)$9I%#9I!" + "$IM%$*)##J!!%YQ'#*!&$IU%%9Y(%IY\"\"I]!#I]!#J%!$I]\"#J)!%:1($Z!&%:%!" + "%)]!#J-%%J-\"%:1(%*=+#J1!#Z)\"#Z5!$J9!#JA!#J5!#J5!#*5\"&*A+#ZA%%*A&" + "$Z-\"$Z9&#JA!$JI(%:E!#JE!#Z9!#ZI\"$JM!\"ZI!!*M!#JI!\"ZM!#ZU!\"*M\"%Z])" + "&:I!$JM!%JM!$*Q\"#JA!%*U\"#ZQ!!ZM!#Z]!#ZU!#ZU!\"ZU!**U)$*]&#ZY!\"[!!" + "%JQ!$[!!#ZU!#JI!%ZU)#JI!$J]!$ZQ%#ZU!#[)!'*U#$JI!$*]\"$Z]%%+)\"\"[!!" + "$JU!#JM!%*M\"%:Q$!*Q$%JQ!#ZU!#Z]!#:M##JM!#JM$&ZU\"$ZM\"!:Q\"#ZE!#JI!" + "%*I\"&:A,$J9!#JI!$Z=\"$*=#$JQ!\"ZA!#J5!#*=\"%Z1&#J9!$J9!#Z9%!*5!#J5!" + "#J%!#J=!#*9\"#JA!#J-!%*1'%Z)+#Z-\"\"J!!%:%(#:%##Y]\"$*!#!)]!%:%!%9Y," + "#IU!#IU\"$)]#%9U%#9U!&IM$\"YM\"$9I$$YI&&Y9/#IE(#9A!$IA%%9=%\"I=!!I=#" + "\"I1!\"(]%$9-(#9A$#9)!\"I-!$))%#))#%I%$%)!%\"8]#$X]$\"Y%##)%##))##8Y$" + "$(]$%(M##8M$\"H-*!HQ!\"XI\"#(A##8A%%H=&#(E!\"8M#\"8=!\"X1\"\"X9#\"8)!\"8)!" + "\"X=%$()(\"X!#$8%)#']$\"H!!\"WQ#!'M!\"7Q!\"GM\"\"GY\"#7I%#7I%!W1\"!GE%!WA&" + "!G-!\"7=#\"G1$#'9'#'5\"\"'5#!W9&\"79#\"W1&$7E$\"GM\"#']$#WA#!GU##7Y#$8)&" + "$'Y#\"G]!\"W]##(!$\"(!#\"8)!\"H)!\"X-#\"X-#$(9%#(9!#H1!#X5&&(=%%(E##(A$" + "!HE#!XI$#(M!#8M!\"XE#$(Q!#(U#%8Q$#(Y!#(]##HU\"#XU&#(]!#I5\"\"I1!\"I5!" + "\"I)!#))##9-$$Y1'!)1$#I=%\"I9!#9A!%Y=(%)E!#)A#\"IE!$)E#\"IA!$9U!#YM\"" + "%YM$#YM#$IU\"!9Q\"$)U#$*!#$:!!&)]$#Z!\"\"J%!\"Z%\"%Z%'%*%'$J-\"#Z!\"#J-!" + "!Z-!#*9\"'*1%#J1!#J5!$J5!!Z1!$Z9\"$:9##J=!$Z5\"#Z=!#J=!%:E!#JA!#Z=\"" + "&:I,\"JM#\"ZE!$JM$!ZY!%*I\"$:Y#%ZQ&$ZM\"$*U\"#:Q##;%&#ZQ!#ZQ!$J]!$*Y\"" + "%*I\"#:U#$JU$#*]\"%:U$$J]!#ZU!\"ZU%#[)!#[%!$*U\"$ZY%$*Y\"$*Y\"#[)!$JU$" + "$;%\"\"Z]!&[%\"\"JY#\"[!!$ZU%(J].#ZU!#*]\"%JY)\"*Y\"\"ZM!$ZY)\"ZQ!$ZY%$:Q#" + "#ZU!$JQ!#ZI!$+!\"$*U\"#JM!$*U\"\":]\"#*Q\"$*M\"!ZM!#ZQ!#:]\"%ZE*$JA%%ZU)" + "$:I#$*I\"$J9%(JI#\"*E!#ZA\"#JE!$JM!$*A\"\"JM#%JA)#ZA%#ZQ!\"*9!#:5##Z=\"" + "\"Z5!&:5!#J9!$*%##J)!%J-\"%J5\"\"J%!%:-!$:1!$:)!#*%#%J!*$:!!#J%!&9Y&" + "%YY$$)Y#$)Y##IU!#YU\"#YQ#%9U%#9U!#9A!#YI##)M#$IU%$YI'$)A!$)=$#)5#" + "#I=!#9=$\"Y=\"!Y5$%Y5%\"9-##9!*\"H]!#Y9##)%##Y-#%Y1($)%%$(]'!HY!#(E!" + "#XU##8Q$\"8Q+#8M$#HQ\"#(I#\"HU$%(E#\"XA\"!(I!\"85!\"8=#\"H=!\"8=#\"8-!\"X%#" + "!H)!\"(!%#8%$#(!$\"8)!\"(%%#WY$!7U\"!GQ#$7M'\"7Q$\"GM%#7M&!GE!\"'9##GI$" + "\"7=$#'-'!W1!!79\"\"G1'\"7=#!WA$#7A##'A'#'E$\"WQ##'E'\"WQ&\"GU\"#GU!\"W]#" + "#']$!GU!#H!&$(%(#H)!$8%)\"X)##(A$#(1 $\"(9\"$(=!$XA&#(I##(A$#XI!" + "!XI$#HI#\"8Y!\"8M##XQ&#(U##(U!\"XY\"#H]%$I)##9!!!8Y\"%I!(\"I)!\"I)!$Y1$" + "$H]#$)5'\"I1$#I1%$I9 I##I1%#IA%#)A##IA\"#9E!$)Y##)U\"\"IU!#YQ#$9Q!" + "#YE%$)U#$IQ\"$J! Q!#9]'%:!\"\"IU!#J)!$J%)$*%#%9])$J)%&*-($Z-&\"J-!" + "#Z-\"'Z1)$J5!$J9!%*A#$J9!$J9!#J)!#J5$#J=!%:5(#JA!%J9\"%JE(#JM!#ZA!" + "#J9!&ZM\"\"ZI!%*Q\"#JE!#JM!&ZI\"$JQ$!K!#'+!#![!$$JU$#ZQ!#[%!#[)!#JI!" + "%:M(#[)!$[%%#[-!#ZY!#[!!$*Y\"$[)!$ZU%$J]$#Z]!\"*]!$:]*$[%!#[-!#ZQ!" + "\"ZM!$:M$%J]%&;!#$[%!#;!#&ZY.#JM!#*]\"';!,$*]\"#Z]$#Z]!\"+!\"#ZY!%Z]\"" + "%ZU\"$*U\"'*Q+#*Q\"#JE!%K)(#*Y\"$J]!%*U'$JE$$JM!&J]!#ZQ!#J9!!ZY!$JQ$" + "%ZM\"$:M$\"JM$%ZE\"$:I$$:I$#J=!#J=!\"*E%$:E##JM!$JM!$*I\"#*A&#J1!$:=$" + "#*9\"#J9!\"J9#%:5!$JA$$J!\"%J1\"#Z-\"%J5)$:-!#J)!#J-!#Z%\"#J!!'*!0&J-\"" + "#IU\"#J)%#IY+$IY%#YQ##J)!$9Y!#9Q!#9M!#)M#%YI(%I5!#YA#$9E(#9I!$)A#" + "#)A#!Y9!&99*%)5%!Y5$$Y-'\"I5!#)%#!Y1!\"I1!$9%&$(]$\"8Y!\"Y)\"\"8U##(I'" + "!8M($(U$#(=$\"HQ!$(E(\"8I#\"8I!#HE##(=$\"HE$\"8E!$X5,#8=%$H5\"\"8-!$(-#" + "#8-%!(-!\"(5'#X%'\"8!!\"8-!\"H!!\"WY!$'Y)#7]%\"7Q!\"7M!\"7M!\"7I##'E+!G=!" + "\"7)$\"G-$\"'1\"!'1$\"'5%#79!\"'I##'E'!7U\"$7E*\"WM##7Q#\"GY\"!7Q\"!GM!\"X!#" + "$H!'$X!)#(%!\"8-!\"8%!#85\"\"H1!\"81$\"(9\"$81!#(1!#8=$!HI!$8I&\"(E\"\"8I!" + "!HE!$8M&\"(Q\"\"XE\"#)!$\"X]\"$(Y!#H]%$(]*#H]\"#Y)#$))$#I-\"\"9-##I)&$)!(" + "!)1$#)5#$95%!Y=!!Y=!\"I=!$YA&#IA\"$IA A!#YI\"#YY\"%IQ'%)Q$#IU\"%)Y$" + "$YU'#IM\"#J!!\"I]$$Y]&$*!#$9]$!J%#$)Y#$:)!&*!(#Z-\"\"J!!\"Z9!$:%$$:5$" + "#J1!#J9!%J-\"#J=!#J9!\"J=##JE!#J5!%ZE)&:M(\"ZM!$ZM%#ZE\"$JQ(#ZI!#ZU!" + "%JM!&:A$&*=+%*M&&*I'$ZQ%#ZY!#[!!$JU!$+%\"$:U$#ZU!$ZM\"$:Y'#Z]!&*Y*" + "$Z]%$K%(\"ZY!!Z]!#;%#%K!)#*]!#Z]!%;)+#[!!#[%!$Z]%#[%!$*U\"$ZY%%;!'" + "&K%!!+!$$K!$#*Y%\"[!!\"[1!#[!!#+)&$:Y*$+-\"$+!\"#ZY!#[9!$;!##[!!#[)!" + "%K)$$ZU%\"*]!$JY!#ZU!%J],$:Y#![!!\"JQ$$*U\"':I%#ZU!\"ZU!%*I'%:]#%K!)" + "$ZQ%!ZU!$*Q\"&JY!%JQ$$*M\"#*M\"$JI!#JE!%*E'\"*Q!#JE!$*E\"$Z=\"\"*I\"\"ZA%" + "#J=$#J5!$:9##Z9\"$*1&#J1!$J5!\"J1!$*-##J=!\":-\"$:)!#*1\"$:!$$J5%$:)$" + "\"J!!#Z!&\"IU!$:%!#)M%&)Y%!IQ##YQ&$)Q$#)Q#$YU#\"IM$$YI&%Y1%#9E!%)5\"" + "&)I\"!95\"#9=$#I5%#99$#)9##I9\"#Y9#!Y-!\"Y-\"$I-)#9%!#Y%$$9!&\"I1$\"8]!" + "\"(Y\"\"8Y!\"(]%\"HQ$#(]#!XU!#XI!#(I#\"8A!$XE\"\"8A!\"X=#%(1'\"X9\"#()!\"85!" + "\"89&!()#\"X!#\"G]\"\"X%#$WY!\"(%#!']!#X!\"#7Q#$'M##GQ&\"GM\"$'E!\"'E\"!W=\"" + "!71'\"'%#!'=#!W5!\"G=\"!WQ\"!WE\"$'U($GI&\"GM'\"7M!#7M&\"GQ\"\"WY##7Q%!WY$" + "!(!#$8%$\"X%##(!$&(-+\"8-!$(A\"\"(%#\"HE$#85$\"X-#!HA!#8A$\"(5%#89$#8]$" + "\"8I!\"8A!!HQ!#(Q#\"XY\"$8M#\"X]\"\"I!!%Y!#%XY\"!Y!!#Y%&$))$#Y-&!Y1!\"91#" + "#9I$$I9&#)5&#Y5 =!#)=#!YE!\"II!#)A##9I!!YM!#9Q!%9Y%$9U$#)]##IM\"" + "#)Y#&)Y!#Y]\"$YY&$)Q$%:%+!Z)!$J!%&*-!&J-\"$:-#&*-+$:1!$Z1&$Z5\"#*5%" + "%:1%#J9!#J=!#J=!#Z=\"#JA!$*A\"%*M&%*E\"&:Q,&*E$!*I$#JE!%*M*#JM!$:E#" + "!ZM!#Z]!$*M\"\"*Q!#ZU!$*M\"$:]##[!!$*I\"'JY*\"ZU$$*Y&#[%!&+)\"&:M!%:U$" + "$[!!#[!!$;%\"%[!)#;!\"$+!\"%[!&%[%)$[!&$[%!%+%&$K%$#[%!\"ZU!$+!\"$*U\"" + "#[%)#[%!$;%\"$+)\"#[%!!ZY!$K%$$[%!$[1!%+%&#[%!$+%\"#ZU!$K1$#*]!$K%$" + "\";5&%;%'%JY!#[!!![!!&:]+#[!!#:]\"%;!$%ZY\"$[!&%*Y*%:Y#$*M\"%JY($K!$" + "&;)'&JU)&JQ%$*U\"$:M$$*M\"$:Q$$*M\"%*M&%JM!%*I'$:M'%JI!\"ZM!#ZA\"#JA!" + "#JA!#JA!$:=$$*9)%*='$J%&$Z-&$JI!#J9!#J1$$:1!#Z-\"%:-%!Z%!$Z)\"#J=!" + "%9]!#J%!#YQ##Z!(#9Q!#J1!$)]#$)]#$)U#$)Q$$IQ&\"IQ!#IQ\"#YE%#Y]\"&9=$" + "#9A!#9E!#I5\"%Y=,#YA\"\"Y9\"\"I5!\"I=!\")9%$)5'#Y%'$I% %!$I%'#XU##(Q!" + "\"X]\"\"XI\"\"8Y##9!!#(E!\"HM!#XA#\"8I!\"8E#\"X=#!X=!\"8A!\"81!\"89!\"H9!#HM&" + "#']$#85%$X1#\"X)##(!'#8-%\"G]\"\"WY#&(%)#'Q$!GU!#7]%\"GE\"\"7Y!#7=%#'I\"" + "$'5&#G1$!G=%!G=!!W1&\"'E#!WE\"\"GA\"\"WM#\"7=!\"'Q#\"8%!$GY*!G]%#W]'\"7]!" + "\"X)##8!\"!(%!$H1%#(1!\"81!\"X5%\"W]##8=$%(5#\"XE#\"H-$#8E%#(I#\"XU\"\"8Q!" + "\"HU!\"I!\"\"XU\"\"XE\"!X]$!XY$\"I!!$Y!'%I-!\"XY\"\"8Y!$)5!\"I)!$Y1*\"IA!#)1#" + "#)-#!YA!\"IE!$)-$$)I$$YE$#IE!\"9I##9Q'#)]##9I!#99!\"YU!#IY!#YU\"$)Y#" + "#Z!\"$)Y#%*%'\":!\"!Z!!$9Y!%Y]'#Z%\"$Z1&&*%(#J-!$:1!#J5!#JI!\":A#%*9'" + "#JE!%:=(%:=$$ZE&%*=&$J5!&:I,$:Q#%:M$#JI!#*E\"$JY!$*M\"#ZI!#Z]!$:I#" + "#ZQ!\"*Q\"%:Q$%*Q##[!!%ZY\"%*Y\"#ZQ!$+!\"$;!#$[!!$*]\"&:],%K!)%;!#\"[)!" + "&;)#![%!#[%!\"K!$#JY$$[)!\"+!\"&+%\"$[%!\"ZQ!$[)%\"K)#'[)\"$+1\"#[1!#[)!" + "\"Z]$#+)\"%;)+$+)!$+!\"$+)\"%+).#+!\"#;)\"$[)!#[%!#[)!%+-&$[%!![1!\"[%!" + "$+!\"$;)\"#Z]!#[%!#[%!#[1!$;)'#ZY!%K!!'K%,%Z])!*]!#JI!#Z]!#Z]!%:M'" + "$:]##+%!$JU!$:Q#&:Q$$ZU\"#ZE\"$JQ!$JQ($ZE%$ZM%#ZY!$JQ!#JI!#Z5\"&:E%" + "\"ZM!#JE!%*=*$*A#$Z=\"#Z=!#JE!#ZA\"#Z5!#*5\"&*1!!*5$%Z1#$Z9&#J-!\"J)!" + "#J1!#J-!#I]!$:!$#IU\"$Y]#$)U##IY!#IU!$:!!#9]$#)Y#\"I]!#9I$$)U##)9#" + "!YE!#YE\"#9A!#II\"!I1#\"I9!#)-#\"Y5\"\"IE!#Y!'#9-$!Y5!\"(Y($HY$#I%\"#I%\"" + "!Y1!\"XM\"\"HY!#HM%\"8Y!!I%##XA$#(M!#8M$$8M\"#XE&\"XA\"#(A$#(A!!H9##H9#" + "$81)!H=!#(-!#(!$\"85!\"H)!\"W]#%8%%!7]\"\"7]#\"X!#!WQ$#WQ'\"WU#\"7]!#7I\"" + "\"'=##79!#7=(\"'=%\"W=%\"75&\"7I!\"7M!#'Q$#WQ'\"7U!\"7U!#']$#7Y%!']!!X)$" + "!H)!#H)#$H-*!XA!#X-'!H5!#X!(!H9!!X1!#(I!\"HI'\"8=!\"HA!#8Q!\"8M!$(Q(" + "%(U,#I!%#XY&#XU&#(]##9%!$9!&$X](#9%!\"I)!!)9!\"9%#!Y=!#)=&#Y-#\"I=!" + "#I9%\"I=$$9=%$Y9'$9E%$)E#$9I\"#9M!%)I!$IQ&&)]($)]##YY\"$IY&%9Y!$9U$" + "$Z!##9U$#I]!&*!!#Z1\"&J)*#Z1\"#J-$$*9\"#J1!$Z5\"#Z5\"#ZE\"#J9!#J5!%:=!" + "%*=##Z9\"$*A##ZE\"!ZI!!ZQ!#ZQ!#JI!#J=!\"ZU!!ZI$!ZQ!%*Q'':Q!\"ZU!':U%" + "!:U\"\"ZU!#ZY!#ZY!&*Y#%ZY\"(*](\";%\"%ZU)%K%!\"[!!\"[!!#[!!#[!!!:Q\"#*M\"" + "$[)!$+-\"#K)$$K9#$[)!$;!#%+)\"$+-\"$+)\"&[-.\";-&\"+1%$+-\"%+!\"$K5$$;1#" + "$[-$&;-+$;-\"%[)!$+5\"%+9&$+-!$+1\"$+)\"$*Y\"$[)!#[I!%;-'$+)\"%+)&\"[1$" + "\"[!!$+1\"#K)#%[)%\"[5!#[!!#[!$#:]\"$*]\"$+)\"#JM!%[-&$JU!%K%!#JM!$+-&" + "\":]&$Z]!$J]!%:Y$\"ZY!#Z]!&ZU*%ZU\"#;%'$:I$#ZQ!$*M\"%:M$#ZY!$J]!#JM!" + "#ZU!#JM!$ZA%%ZA&$ZE)#:=##J9!%:=(%:=($J=!$J5!$JE%$J!%$Z1&#Z9\"$J%&" + "\":)#%JA)\":%#$*%#$:-#&*!!#Y]&%*%+$9Y!'YQ*#IU!$)U##)Q##IY!\"9Q##IQ!" + "#9Q!#YE%$IE#$YA!#)9##)A#\"IA!\"95##95$\"I5!#)5##)9##I5\"#I)&#Y-##Y!$" + "#9%$\"Y!#\"X]\"#8Y$#XY!!XU'#(Q#$XQ*$(Q!\"8I!#XM#$X=+\"(E\"$8A&$H=!\"85!" + "#85!\"X5##(1&!H%#\"(-#&()(#(%&\"X%\"\"']#\"8!!#'Y$#'Y$#7U\"\"WM#\"WQ&\"WE!" + "!79%\"'9!\"'E\"\"7I!#GM!\"W=(\"WM#$'Q!\"7Q!!GU!\"7Y!\"7Y!\"G]\"#7Q##W]'#GU#" + "#(!$#H)&\"(9\"\"X5##X5&#(5)%(=##8I%$8A '\"HE!\"8Q!!(=!\"8M#\"XM\"\"XM\"" + "#HQ&\"Y%#\"I!$#(]##9-$#Y!$$I!&$))!#)1#$)A!#)1##Y1&!Y=!#)5##Y-##9=$" + "\"I=!#IA%')I\"$)E#!)U!$)I$$9M!$YM#!IQ#$YU&$IQ&$)U##II\"#Y]\"#9Q!%YU(" + "#Z!\"!*%!$J)\"!Z1!\"J1!#J-!\"*1\"#J!$#J5!#J5!$*5#$J=!'*5(#J1!%Z9##JA!" + "%Z1#\"*A\"%JE(!:E\"#*I\"$JI%$*Y\"$*M\"!ZM!#JA!#Z]!#Z]!#ZQ!&*U*#ZU!$;!\"" + "$*Y\"'JQ%$JY!#[%!#[)$#ZQ!%[!&#;!#%+!\"%Z]*#JY(&+%*%;!'#[=!&;)'#[-!" + "%JY%#[%!#[)!%+-&%K-$$+)!#[-!#ZY!#[-!$+-!#[-!$[-!%;E\"%+5!#[=!#+1!" + "#[1!\"K)#$+M!#[5!$+1\"#+1\"#[-!%K1($+1\"#[-!!;=\"$J]!'[1-%+1&%+-\"$;-&" + "$[5$#[%!$[)%\"[1!$K)$%;-\"&K)!&+)\"$+)!$[)%%[%&\"ZU!%:Y$#;%*$[!!%ZY\"" + "\"Z]!%Z])'*]+$:Q#$:]#$:Q$#ZY!%;%'#*U\"$*Q\"#*Y\"#ZQ!$*Q\"$*Y\"\"ZM!!ZY!" + "%:I'!:I%#JI!'JA\"#JE$%:M$$*A\"!*9!#J9!#Z%&#Z5\"$J1%\"Z5+#J5$#Z-\"$:9#" + "#Z%\"%:1!#J9!#Z5\"\"J%!$J!\"$YY#&J!#$)]&$*%#$Y]&$9M!#IU$$9M%%YI!$)A#" + "$9M!#YE\"#YI\"$9E\"$)A#$)=!!YA!#9Q#$)=!\"I5$$91(#I1%\"Y1\"\"I-$\"I-!\"Y)\"" + "\"Y)%#I-\"#)%#\"I-!#(Y##(A$$8Y%\"HU!\"8Q!!HM!#(9##(Y!\"8M!\"X=#\"81!\"8-!" + "#89%#X5$\"81!#()$$(9(\"7]!$X)&$8%)\"8%!\"WY%\"WI#\"WY#\"X-##WU!\"WU%\"WQ!" + "!W5\"\"W=*#'9$\"'A\"#'E$#G9$!GM!\"WQ##'I$#7U%#7Y%#H!$$(!+\"7]!\"W]#\"8!$" + "#()$$(-(#(5##(=!#H-%%H9,#85$\"H=\"#(A#\"H=!$(Q'\"8M!\"(M\"!(Q!!HQ#\"8Q!" + "#(Y#$(Q%!H]!\"8]!#9!!%I%'\"Y)\"$)%!#I)%\"I%!\"I-!\"99&\"I9$#99$#)I##Y=#" + "$)=$$)A#%)9($9Q!#YQ\"$9U$$)M##YQ#\"IU!#J%!%)E%#IY!$*!#$9]$&:)-!Z%!" + "$Z)#$*)&#*1\"%J-\"&*5,$:A#$ZI!$:5##J=!#J9!#JI!#Z5\"&:9!$J5!%JA)&:A!" + "#ZE!&JE)':I!!*A$$*M\"!*U!#JM!$*Q\"$:M#\":A\"$ZU\"#ZU!%[!&$*Y\"\"ZE!$J]!" + "#ZY!#Z]!#[%!$J]!\"K!'#[)!$+%\"#[%!%K%)#[)!#[-!$[5!$;-\"$+!\"#+-\"$;-\"" + "!+)!&+1\"#;)\"&[1&#[1!\"[1!#[1!$;1\"%+9\"#K1$$[9!#[1!$+9\"#[1!&K5$\"[%!" + "$;A\"\";5&$;5\"$;5\"#[5!$K9#\";5\"%+5!$;-\"%+9&$[5!\"[1!#[1!$[-!$+1\"$+1\"" + "#[1!$[%!$;9\"#[)!#[%!#[-!$[!!$;)\"'K-!#[5!$+)\"#[9!&K5,#[)!$+)&#+)\"" + "$K9'\"ZQ$#ZY!![%!$JU!#Z]!#Z]!#[!!%*M'$*]\"#[%!$ZU%%*U&$JY!%*U'$:Q$" + "$*M\"\"ZM!#ZM!#JM!%ZI'%:I$&:E!%:A(%ZA\"$JE$!Z5!#JA!$*9#\"Z=!&*=+#J9!" + "$Z1\"$*-'#Z-\"$:-!#:)'$J)%#J%!$*%#$J%%&J%&$)]##9U!\"J%!#I]!#9U!#YQ%" + "$9I$%)A'%)I!#YI&$YA&#IA\"\"IA!\"9A&$91\"$)5'#Y5&\"I=!$Y1*!)-$#I!##))#" + "$9)%#8]'#H]\"%)!)\"I!!\"I!!%(U##(U#!(Y!#8M$\"XM\"#(I##(E#\"8=!\"H9\"\"8A#" + "!81\"#X=)$85)#HA+\"(5#\"8)$\"(%\"#(9!\"()\"\"8!!!X!!\"']#\"WU##WY\"\"(!%\"7Q#" + "#'A$!G9#\"'I!%WM+#GI'#'I%#'I&\"7E#\"'E!\"7Q$\"GQ\"#']$\"X%#\"X!#\"(%\"$()#" + "\"89##(1#$H9'#H1&#(9!!H=##HA='\"8M!#81\"#8I%$XU+\"HQ!$HM!\"XU\"%(M#" + "#8U!\"9!$%9!*$))!$9!&\"I)!\"Y-($I-)#)1##I9+#I1\"#Y=\"%)Q*$)9'#YE#$)A!" + "#9M!#YE##9A!%)=$%)Q!#IQ!#9Q!$)Y##YI\"$)Y##9Q!%*!!$:!!#IY!&Z%$%:%!" + "$J)%$I]&#*)\"\"J)!$J5!#J1!#Z=!'*5%%J9)%:5!\":=\"&*=+#JA!#:A'#*A\"#JM!" + "\"ZE!$JQ$$:M$$JM(#ZM!#ZQ!#JQ$$*U\"\"Z]!$JU!'[-)%*Y&#Z]!#;5\"%*]&$[%%" + "$;-##ZU!$:U#$[)!#[)!$J]!#[)!$+5!%:]+%[))\"[1!#K5$$;)#$[-$%JY)&;)+" + "%[-)%+)&$+!\"$+1\"\"[%!$+9\"%;1+$+%&$[5!&[5!![1!$;)\"$+-\"#[=!%+=!%+)\"" + "%[A%%+=%%;9\"%[9!#K5'$[-!%+9\"&;9\"%K9$$[9!'+1+'[1!&[1)%;5\"&[9!$[=$" + "#[5!\"[5!#[-!$[5$\";1\"#[-!#[-!$;1\"#+1\"\";-\"$K-(![-$#+-\"$[)!%K)(%Z]%" + "$[1$$[%!$*]\"#[%!%K!$%;-\"%K!)%K!$#Z]!$*]\"$*]\"#ZY!$ZY%$ZU%%*U\"$*U\"" + "&:Q$#JM$&JE-$*M\"#ZI!\"ZM!#JI!%:E!#Z9\"%ZE\"#J=!\"JE$%J5)#J9!#Z5!#J1!" + "#*9\"%J5%#J1!#J-!\"J-!\"Z)%#J)!$:%!$*!##I]!%IQ)$)]&%I]&$:!!\")Y\"$)Q$" + "\"J!!#IY!#YM#\"YI\"!Y=!$Y9'#95!#)E##95!#95$\"I9!!IA#\"I9!\"91#!8]%#9%!" + "$I%)#I%#$HY&#(Q!!I%&#(U##XY##(Y##XU!\"HU!#XQ!!HQ!!HI!#HI&&H9*\"HA%" + "\"81$$(A(#(9##89%\"XE(!H=!\"X)##H!&#H))\"8%!\"X!#\"7]!!W]!\"WY#\"7U!#H!$" + "\"'E#%WI(!GM##'I$#GM$\"WQ&\"GQ\"#'I$!(!#%H1&\"7]!\"()##8%$#8)%\"85!$H9!" + "$X1(#XE!#(5$#X=!#H=#\"89!#8A!$(M'$HQ'\"8I!%HIA%%HQ!!HU!%)!($HE!" + "\"H]!#Y)'!H]!\"Y%##))#$)-'#Y-##I)%\"9A#\"I=!\"I9!\"IA!\"I='%YE!$)M'\")E\"" + "#YE#$IA%&9A M!\"IU$#YQ\"%)U'$YY&#J5$$I]&$Z)&\")]\"\"J!!#*%#%J)\"$*)#" + "$*-##J)!%*%'\"J1!#*5\"#Z9\"$9]$%*='#ZI\"#Z5\"!:=\"$Z=)#JE!#*E\"#JI!#JI!" + "#ZE\"$K!$%*M'$:Q$$*Q\"!ZQ!$ZU\"\"Z]!!*U(#ZY!$;!#\";-\"$JY$#[!!%+!\"#[)!" + "$*Y\"#[!!\"+)%#[-!$+)\"#[-!#+)\"\"[-!#[!!$[)!$+1\"#[)!#[%!\";1\"%K=##+5\"" + "$+9\"%;9''+5\"#[5!%+=\"#[9!$[9!%K9$%;=\"\"[9!$[9!$[9!%;-\"&;I&$[9!&[5*" + "%+=!'[E!'+1&$[A!%+5\"%+=%$[I!%+M!#[5!%;5#&[=!#[9!%;9\"$[1%$[9!%+1\"" + "$[A!%+1!$[E!&[=)#[9!'[5&\"[5!&K1$%;%#%+9!$+-!\"[5!#[%!\";)\"$+9!&+-&" + "!;5)$+5\"$K-$$K!$%;%'#[!!$+-\"$[!!%J](%;!#$*Y\"#Z]!#[%!%JY!':U)#Z]!" + "\"ZU!#ZQ!#ZU!$*I\"#JM!#JM!$*M\"#JM!$ZI%%JI(\"ZE!$ZI\"$ZA&\"Z)!$J-)#J9!" + "#*9\"#J1!#:1'\"Z9!%ZE)#Z)\"&*)!#Z-\"%:5(%Z5#$9]$%9Y(%)U+$YM'$)Y##Z!&" + "#9Q!#)Y&#YQ)$IM%')M)#YQ##I9\"#YE\"'Y=#$Y=$\"I=!#)9##YE#\"I5!!)1!$Y1'" + "#)-##Y%'$I)##9%!\"Y%\"\"9%##8]$#(]##(I$#8U!#(Y!#8M!#(E$#8=%\"X=#!8E\"" + "#(A#\"85#$(=(\"X=##85%\"X1##X-$!H1##X-'!8%\"!W]\"#8%(\"W]##7Y%\"WQ#!GU#" + "!7M%!WE\"\"7M!#WM'$WQ)$X%&\"7U!#'Q!\"G]$\"'I!\"GU\"\"8%&!(!$!H)!\"X-#\"8!!" + "!(%!!H9!#(1$\"H-\"\"H9!!HM!\"8M!\"8I!!8M\"$(E(#(Y!!HM!\"8U#\"HU!#(U#\"8]!" + "!Y%!#9-!$9-%$I%'#HY%\"I1!%)1(%91&#I5%\"I9!!99\"#I=%#9=!#9=!#YE#$YI'" + "$YY##9U!$)U#&IE+\")M\"$IU(#J%!$)U#%Z!+\"YY!#Z%\"$:%!%Z%'#Z%\"$J%%\":)\"" + "$J5%\"*1\"!Z5!%Z9&$J9!$:-#$ZE\"$J=!%JA%#Z9\"$ZE%!ZI!!:E\"#JM!$:M##JM$" + "\"*M!#ZU!$:]##ZY!#ZU!$*Y\"#[!!#ZY!#:]\"%J]!&ZQ*#[!$%+!\"%[!\"#K%$#[1!" + "#[1!'+)+#ZY!#[)!$+-&$+-\"&;A&\"[1!%+9&$KE##[1!$+1\"#[=!$K=$#[5!%+M!" + "$[E!$[=!%[=!#[9!%[9%%[E!$[=!%[5%'KI$%[9%%;9\"![=!%;E\"%[=!\"[=!$[5!" + "%;5#%K1$&KA$$[A!#+1\"$[=!!+E!\"[9!&KA(&[=!%;I\"%+=\"![I!&K9((+1\"%[-%" + "$[A!$[=!'+9\"'+9&%KE$%+=\"&[5!#[9!%+5\"$[1!$+E!#[5!#+1%$K1(%[1!$;%#" + "#;!'%+)&#[-!\"K!#$+)\"\"[)!!*]!#ZQ!\"[%!$+)\"&+!+$JU!$J]$\";)&#ZY!(ZY+" + "\"ZY!%ZY\"&:Q$#ZY!&:M+$:Y##ZU!!ZM!#*=%#JE$$JI!$JA$\"Z=!\"*A\"&:A%%*='" + "$J-%&:5%$:9##J5!$*5\"$:=$%J-\"#J%$$Z)#$J!)$Z%#\"YY\"\"YY!#J!!\"IY!#9M!" + "$YQ##YU\"&)Y)$)M$%IM##YM##9I!$9M!#9I!#Y=\"#9A!#)1##99!\"I5!\"I5!\"Y1\"" + "!)1!#I)\"#I!#\"Y%\"$9%#!(U!\"(Y%$(]'$8M#\"8M!$HU-#XQ#$(9'#HA\"\"HI!\"89!" + "#HM%\"HA\"\"8=!$(9'\"(9\"!H5!#H1U$$X-%\"X-##H-&#H-&\"7U!$W](!GQ!\"7Y!" + "#G1'#'E\"\"WQ#\"'M\"#7M%\"7U!#7E#$'Y(#(!$#8!$#(!M#!X)\"#X)\"#H-!\"85!" + "%HE\"#(=$\"(5%$(A%$8A(%HA\"$(E'#(I!\"(M\"#(I#\"(M\"$)%'\"8U#$8Y)#(]#$(]'" + "#I!#$)%$!Y)!%9))\"9%#\"9-##)%$\"9A#\"I9!\"I-!$)5$$)E$#IA!$)E!#9Q!\")E\"" + "#9M!#YM#$)U##IU\"$YY&$J%%#IY!#YY&#YY\"%J!##J%!#9U!!ZA!$J)\"&*-+#J1!" + "\"*5\"%J1)%:9($*9\"\":9#%J=\"$Z9\"#J1!%JA\"\"ZE!!ZA!$ZI&%J=%%JM!$ZM\"$*Q\"" + "&ZQ*#ZQ!$ZA&#JI!#ZY!%:U(%*]&%Z]!$*Q\"(;!-$K!$$J]'$;%#\"Z]$\";)\"$+)-" + "%[5!$+-\"![-!$;-\"$+1!$K=#\";1\"\";1\"$[-%&;5'\"[5!%+9\"#+9!$[=!$[9!%[1!" + "$[=!)[=*&;A\"'[A!$[-!(+=\"%+M!%[=!$[=!'KE,#;A\"(+A&$;M\"%KA$\"[A!$[A!" + "%+A!&[A)%+E!%[A%$[=!%+9\"%KA$%+U!';1,&[=$#;E\"%K-$&+A!$[A!%K=$'+A*" + "\";5\"$+E!';=\"&[9!\"[A!&[=!%+I!#[9!%[=%&;E\"%+=\"&K1$&+=\"$;=\"'K-!%[5!" + "#K1#$[1$%;1'&K=,#+-\"$K-$\"[-!#[%!$*]\"$;%\"#[%!&+-&%+%\"$*U\"&J]!#+!\"" + "$*U\"$JM!#*Y\"$;!\"$[%%$[!!%*Q'%JM%%JI((ZU/#JI!%*9&&JY%#:E#%:A!#JA!" + "!*5!%ZI*#J9!$J9!\"*5\"#J5!#J5!$:1$#J5!#J)!#Z%\"$*1\"$*-#&*!$#:)#\"J!!" + "')])$IQ\"')I\"\"YU%#9Q!$)9*$YM##II\"$Y=!#YA#&)=-#I5%\"Y=\"\"Y%#\"YE\"\"Y-\"" + "\"Y5\"#)-#!91+!))'%9) %!#9%!!)-$$I!&\"Y%%%)!)#(U!\"XQ%$(Q!#(U#$HI$" + "#89%\"XA##8A%#XE!$(5%\"H5\"\"(5#$H1$\"X1#\"H-'$8)!$8%)\"H!!\"8!!\"G]\"\"WY!" + "#GE)\"7M!\"8!!!H!!\"GE\"\"7]!\"WU#&'Y&\"G]!&(!,#X%\"#8%$#H%&#(-!!(9!!(9#" + "\"(%%\"89!\"85!$HE$\"HE$#HI&\"XM\"#(I$\"XY\"#(Q##XU&\"8A!&8Y(#(Y!\"Y%\"%I%'" + "&I%)#HU\"\"I)!$Y-!#I5%!Y5!#)5##))##)A#&91'$IE)#9=!$9E%#YE\"#9M!$IQ%" + "#YA#&)Q(#IQ\"#9U!$J!&$)Y#$YU*$Z%*%IU)$IY%$*%#\"Z)!\"J-!%J-\"#Z-\"%*1'" + "%Z)'%*5'%:A!#J5$!ZA!#JA!#JA!%:9$#ZM!'ZI'\"ZA!'*M'!*Y$'*Y,%:M$#ZU!" + "%JY!#ZU!#ZY!$+)!!ZQ!&JU%#Z]!$*Y\"#+%&$[%!\"[%!$JY!#[)!#ZQ!%+)\"#[9!" + "%[-&&;9+%+1\"$[9$#[1!&;5#%;5#&+5\"#;9\"%+)\"$[9!#K=#)K11%+M!![I!$[E!" + "%+9\"%KA$&;=&%[9!%;=\"%;A&%;M\"&;E'&[9)$[I!(+5\"$+U!'[A!&+E!';M/&;I\"" + "![E!%+M!%;A\"$[A!%;A\"$[I!$[E!&[E%$[I!$[E$%KE#%;M\"$[I!![A!$;I&%+9\"" + "$;E\"%;A\"#+A)'+E*&+9*$[A!&+A\"%;=\"&;A'$+=!%;='%+U!#[9!'+9\"%;I\"%[9!" + "!+1!#[1!$;=\"#[%!'+-\"%[-)&;-$$[1!#[-!#[%!%[1)%;-\"#[)!\"[)!$+)\"';-," + "%[!\"#ZQ!&+)&$:Q$%*U'#ZQ!#ZY!#ZY!#ZQ!&JQ-$JI!$JM!#ZE\"#JI!!ZE!#Z=\"" + "#ZQ!%:=(#:=#\"Z=%\"Z9!\"Z)\"#J5!$J1($Z5&&Z!$$*1#%:)!#J-$!*)!%:!(#YI&" + "$IM%#IY!\"I]!$IQ&#IU\"#9I!#IY!#J!!%)I$#IQ!\"9M##9A!!YM!!)9!#)1#$I5&" + "!95\"\"Y1\"#91!#)-#!))!!I!##9)!%)%&\"8M##8]$\"8I##HU\"#(M#\"Y%\"#XI#$(I$" + "#8=\"#8I$$HE*!(I!#(=$#X=$\"X%#\"H5\"\"X1#\"8-!!H%##H)!#7U%\"W]#\"7Q!\"(%%" + "%7A$$WM$\"7U!#H-!\"WI%#7Y#!()!#8!\"#7]##H!&$H-$!H1!#X-!\"8=!\"H1\"%H-$" + "#8=$\"8=!$X=+\"XI\"\"8I!\"8A!#(M#$HM#%HI%#(Y##HQ%\"8U!%XQ&#Y% )!#I)\"" + "#9%!#I-%#I%)#)1#\"I1!#)5##)9#\"9=#!)9!$)E!$9I%\"I9$%)I!#)I&%Y=+&99'" + "#I]!#YU\"#9M!$Z-&!YY!#J)!#J!!%Y]$#J%!#J)!$Z)&$:A#\":%##Z5\"\"Z%\"#Z=\"" + "$*9\"\":1#$J=!%J9!#ZE\"#ZI!%*E'#J1!$JQ%$ZI\"#:M\"$*M\"$JI!$*I\"$*Q\"#ZU!" + "&JY,#ZI\"%K!$#Z]!$ZY\"%+%\"#[%!%[9$';%$#[-!$;)#%+)\"%[-&#K-$$+9\"$;1+" + "%K1('[9&$[5$%+5\"\";=\"$[=!%[)&\";5\"'+=*%KI#%[=!$[A!&KA(%;A\"&;U\"'+A\"" + "%;5\"'KE($[E!%;A\"%;E\"%;E\"&;I&&[M)%+Y!$[E$%;E\"%+Y!);E($;I\"$[I!%;I\"" + "$[I!$[E!#[E!%[I$&+I%%;M\"%;1\"$+U!%;E\"%KI#%[=$$+Q!$[9!%+I%$[E!%[I!" + "%[I$$[E!&KE(&KA(%+I&$;E\"%[A$$;A\"%+U!#[A!$[=!%;A\"&[=!&[=$%+1\"%[9%" + "&[9!$+9\"#+1\"%[5!#+-\"\"[9!$[=)$;1#\"[1!%;1'$ZU!%+!\"$;-\"#[%!%[%)\"[%!" + "#[-!$[-$$+%&$;%#!JU##*]\"&:Y$$*]\"#JY$\"*E\"$*Q\"\"Z=!\"JU$%J9\"$JM$$JA!" + "#ZQ!$*M\"!ZA!&:9!%J5\"#*!#$:=$%J1&!Z1!%Z%*%*='\"ZE!$J)%#J1!$J%%#*%#" + "':!\"%9]\"\"I]!$IU%#YM&#Y]\"$Y]##9Q!$)Q$\"9Q##IE\"#9E#$)E##IA!$)9*$9=%" + "#Y=##I1%#95$&Y1-\"Y1\"#9!\"#I!#$Y%!#Y!$#(]##(]#\"XY\"#8U$$8Q(\"I!!\"XM\"" + "$(E(!(I$\"HE!!(E!\"X=(#8E%#85\"\"H1\"\"HA%\"X!!\"X%#!(-!#8)'#X!!#7Y%!']!" + "#GM$\"7E!!'U!!'U!#X%'\"7U!#H!$\"8%!#X%'#(-!\"X!##(-$!H1#\"8=#\"(-#%(9&" + "#8I$#X='\"XA!%HI%\"8I##8M$\"XQ\"$HM#!HU#%(M#%)!\"!H]!!)!$%9)&%9%*" + "\"8]!#)-#$)-'\")A%%I1$!YA$$)5!\"I5!%IA*$9U!$)=$%)E$#YI##YQ#$)I$$YY#" + "&)U!!)Q!#9U$&I]*$IY&$:!!$YY&$*%#%*!!\"Z)\"#Z-\"\"J--#J1!\"Z5!$J5!#Z=\"" + "#J1!#J=!#J=!%:Q$#ZQ!$:I#&:=%$:E$$JM%%JQ$#ZQ!$JA%&JY,$*U\"$*Y\"&*]&" + "&JY!\"ZY!$K!$#[!!%*Y&(;5($;%\"%JY(%;1#$[-%#;-\"%K-(\";=\"#+1\"%+1!$;I\"" + "&[5!\";9&$[5!%+1\"\"[5!&+=&%+A!%KE$$+E!&+A\"&;Q'&+9\"'[E!%;I\"$;E\"%;A\"" + "'KE,&[M$%;I\"';A+$[I!&+Q%%KM#$+Q!$[U%%+M%$KQ#%[5)&[]$#[M$$+M!%+M!" + "$;M\"$[M$$+M!!+Y)#+Q!$+M!&;A/#[A!%+M%#+Q!\";]\"#[E!$+U%#[I!%+M!(,!)" + "%;I\"%[E!$[A!%;M\"%;Q&$[E!%+E)'[E)&;E'$[=!$+Q!%+M!%[A$$[A!$[9!%+=!" + "$KI#$;5&%[9$%+5\"$[9!&*Y'$[1!$;-#%+1!$+1\"%+1!$;-#$;%\"%+=&#ZU!%K1$" + "\"ZM!&;!,#ZY!';5#$:U#\"+%!$J]!&J]!&*U+$:U#!ZQ!':A%$*M\"\"*A\"#JE$$ZM%" + "#*I\"%ZI\"$ZI&!ZQ!#Z=!)*%'#Z9!#ZA!%Z5\"$*5\"#JE!#Z-\"%J-%!:-&#J!!$J%\"" + "%*%'%*!$\"*!%!YU!#I]!$9U!#9U!%IQ&$9M%&9M#$)E!#9E!#9E!\")E\"\"Y=%!Y5!" + "$Y1*!)9!%95,$)1'#I-%%9-)#))&#Y%#$)!!#)5#%8]#!H]##XY#\"HU!\"HQ$#(U#" + "%X])!H1#\"8I#$8E#\"81!!(=!$(E(#X9'\"(A\"$81&#H1&$8-)\"X)#\"X%!\"X)##'Q$" + "#7M#\"'I!\"7U!#GY#\"GU\"\"WM#\"GU\"\"G]!\"H%\"\"H%'#7]%#8=%\"H5\"#(5#\"(1##89$" + "#8Q$\"8M!\"XE#!HM&!HI!!XQ!\"XM\"%HQ(!XU$#8Y$\"8Y!#Y%*#X]&$Y%!#I%#\"Y%%" + "#I-%\"I)!\"I1!!Y-$#)5#!Y9!\"IA$%)E'#Y=#$)A##9Q!#9E!#9I!%IY\"$IM\"%YY(" + "\"YU\"\"J%!$9]'&I]#$*!#\")Q\"\"J)##I]!$*!1\"Z-%\"J1!$:1!#J-!#J1!%*9&#ZA\"" + "%*9'$JE%$*A\"\"*Q\"#ZQ!\"ZE!%:I'$*E\"%:E$%JQ!$JI%#ZQ!&JY,#ZU!\"ZY!#ZU!" + "$J]!#[)%$JY!%+5\"$+%\"%+)\"$;5\"%;-#!+1$#[!!#[1!%+1&&;E\"%;5#\"[)!#[5!" + "&[)\"&K9$'+=*$[5!#[=!$[I!&;I\"%[A!%[=$&;I&&;E\"%[E$$;=&%+I%&+A&$+A%" + "%;M\"$[E$#;Q\"%+E!$;Q\"%;M&$KY#$+Q!\"+U!$+I!$+Q!$;M##[=!&[M%$+U!#;Q\"" + "&;Y\"%+M%%;U'$<%\"$+Q!$+U!$+U%$+M!%;U&&+Q%$;I\"&[],$+]!&+=!$[U$$;U\"" + "%+M%&+M!$KE#%[M1$;Q\"$KE##+I!'+=\"$KY'&[I$![A!&;A&#[A!#+I!%[E!$[A!" + "%KA$$;M\"%[9$%;A&%[E$$[9!%[=!$[A!%;=\"#[5!&K)($Z]%$[E$$[)!$;1#&+%'" + "';!$#Z]!!+%!$[)!#[-%&;!#$*Y&\"*U\"$:Y#&*Y\"#[!!$+!\"#ZE\"#*]\"$JE!\"ZM!" + "%:I'#ZA\"%*E'#JE$#JA!#Z=\"$J=!#*9\"%*9&#JE!$:5$%:-!%:-($*)#$J%\"$*)#" + "$:1!#J%$#IY!\"IY#$9Y!!9Y\"\"IE!$IY%#)M\"#II$$IM&!YU!'9E+#)A#$IA%#9A!" + "!I=&!Y9!\"Y5(#Y=&!)=$!Y)!#I9\"\"I)!$I%'$I1##I!#\"Y!##XYc$$HQ'\"XU\"" + "\"8Q##(I##8M$#(A$#(E#\"H=!!H=!!X-)\"81!\"(9\"#(9!$!8-\"\"H%'\"7U#\"7]!" + "#7Q#$7M%!'Q!\"8!!#']!#H)&#()$\"81!!(5!\"X)\"#G]!\"X-\"#(5$!H5%#85$$85&" + "#HA%\"8A!!(M!\"8I!$8M(#(M##8Q$!(U!#HY%!XY*#9)!\"8Y!#9!!$)%$#9)$\"IA!" + "$)-$#91$\"91#$IA)$Y1'!Y=!\"I=!\")=\"#)E#$9I\"!IE##IY!$YM##IY!#9Q!#Z!," + "\"IE!$9Y!$J%\"$Z!#$:1!#Y]\"%:-(':%#\"J-!%*1#%Z1#\"J1!#J5!!Z9!#ZA!!ZM!" + "%:-!\":A\"#ZI\"\"ZI!#JA!$+)\"\"*Y!%ZQ\"!ZU!\":U\"#JM!$[!!#[%!#[!!#ZU!$+%\"" + "%+!\"#;)\"(K%*%ZU\"#[!!$[-!$K-($[-!#+%\"#K9$!+5$#[%!'KI#%;I\"%[=(%+1\"" + "%[I!$[A!$[A!\"[5!$[A!%+A!$+Q!$+M!$[E!$+M!&[I!#;I\"$KI#%+M!#+M!$+M!" + "$;M\"\"+U!$;M\"$KI'$+U!$;Y\"%+Q!$;E\"&[])%[U%%+U!\"[I$'+M!$KY#%+Q!&;I\"" + "$;Y\"%[Y$*;I'%KQ#$[U%$+M!'+Q*%;U\"%KY#&[U%&;E\"([I!#K]#%K]#&KU#$[Q$" + "&[Q$$;M'$+Q!&;I+%;Q+\"[Q%%+M%\"[E!%+=&%+Q!%KM#%[I!#KE#![I!&[E)%[E!" + "#;E\"#;=&%;A\"&+9\"&;A\"'[=!%+I%$[9!$[9!&;9#%;1#![5!#[1!$[5(#*]\"$[%!" + "$J]$#[-!%+)&%[5%!+)$$ZY\"#ZU!$:]##[%!!:]*#ZY!#Z]!#ZU!\"ZY!\"ZQ!$*Q\"" + "(JM.#JM!$JM!$ZA%#ZQ!&:I!$ZA&#J9!#Z9\"$:1!\"J-!#:1#$Z1\"#Z1\"%:-%!*-!" + "#J%!#J%!#J%!$)M$()]*!)U$$II##9U!$9U$%)Q$#YE#&IQ(\")I\"$IE%$9E$#Y=\"" + "$9A$#9M$&9-.\"Y)\"#)-#\"I1!$)%!&9%.\"Y-%$)9$#H]%\"Y!#$))!\"8Y!#(Y#$(Q'" + "#HU%$8E##(Q#\"HM$$(E$\"H9\"\"XA\"!(=!\"X=#\"X5#$(!#\"8)!$8-#\"H%\"\"GU%\"7Y$" + "\"WU!!GQ%#8-%\"7Y$\"GI\"#G])#()!#8%$\"8!!!H-&#(1##85$!H9!$XM%\"X=#\"H9\"" + "#XM!$HE*\"H5\"#(M)#XM!$8E&#(U##HU\"!(Y!#HU-#(]!\"9-##X]!$Y5*\"9A#\"9)#" + "$)1$#Y5##95$$IA&#)-#\"I9!#)I##9I!%YU#$)U#%II##9U!#9E!\")U%#I]!&*%$" + "#YU\"#9]##Z!&$*!##IY!%J1&#JA!&:-)%:1!$Z1\"\":5\"%:5!\"*5\"$J-%!Z5!#ZE!" + "$Z5&$JE$#*M\"#JI!$JI$$JM%#:Q\"$JQ%$ZU\"$JY$$*Y\"#[%!\"*]\"%[!&$;)\"\"K!#" + "!Z]!%+1&$[)%%K%!$+-\"%+-&$[1!%K)$&[5!$+9\"%[5!$[9!\"[9!$;=\"$[=!#;=\"" + "%;M\"![9!$[A!%K5$%+M!'KI,$[I!%;E\"%[Q(#[M%$[I!\"KM'%;M&$KQ#&+M&(+Q%" + "\"+Q!$;I\"&KM#%+U!%+Y%&KU,%+U!%KU#%+Q!&[E%#+Q!%KY#\"+M!%+U!%+Y!%;]!" + "%;Y\"%[Y$\"KU#$;Y&%KY#%\\)($+Y!'KY+(+Y!%+]!%+Y!$+Y!%+Y!'%#&]A&$]Y!%]Y!'=U(&-U!$MY!" + "%]Y!'MY#%^!!%^%%%]]!%]Y!(-Y+%N)%%^!!&-Y!$MU!%]U!$>%%(-Q+%]U!$MU!" + "%]M!#MY!%]M!&]M!#=E!%]Q!(=I,%M=!&N!$%]Q!&]E!&]E!&=A$#MA!&-A\"'-=\"" + "(=1(&M9%$=9!&]1!%]=!%M1!&=1$']-!'M)%%]9!&M)!'M%$%]%\"$=!!%!!%^%!%]]!" + "'-]!&]Q!&N!$&MU$&=]#%]M!%]]!(-]%$N%!%]]!(-Y+%]Y!%^%!)]Y(\"-Y!(-Q!" + "%]U+%]Y!%]]!&=Q#&-Q\"'-U!)-U%%]Q!&]M!*=M+&M=$'=A($ME!%]Q!&]E!#]E#" + "'-E!$MA!'==(*=5+(]=$$]5\"&-=#)-E+&]I!']-*%]5!\"M1\"&M1%(])/%M1!&-!#" + "%<]!%%(%^-!(=Y!" + "&-]!$^!!'-M''>)''.!%$N!!'.!!'.!+&>%#&-Y\"&-]!%]]!#]]\"$N%!%^!!%^%!" + "%=Y$'-Y!%]M!%]Q!$M]!'-U&(>%!&]A!\"-Q!%=E$%]I!%ME!%M=!%=I$)=I!'-1'" + "%M9!%MA!%]-\"#=9!(M=$&]9&%]9!'-5'&]A!%]1\"%M%*(M-$'\\]&%])\"$=)!%<]!" + "%M5!')!!^!)%^)!&.!!'-]!&-U\"'N-\"%^!!" + "&.!!%^-!'.%!%]Y!$N)!'-Y!$N!!$N!!)]U)%]]!&]]%#>!!%^-!%^!!'^-$$MY!" + "%]Y!#=Y!%]Y!%^!!%]M!'.!!%]Y!%]Y!$M]!*MY!%]Q!%]Q!$=9!$MQ!&]E!&]I!" + "%]Y!&-=#'=E\"#]9#%M5!&=9$#=A!&=9)\"=9!)--!\"-)!#=)!#M%\"(M%$#=5!\"-)!" + "%=!$&M!%&M!!&\\Y'&LY&%,U#$,M)%!-%^!!(M]'%^!!%^%!!.-&%^)!%^%!#>%!&^%%" + "&.9!%^!!$N-%%^%!$N%!%.9\"$M]!%^!!'.%!%]]!%^%!%^%!'N%('.%&%]Y!$>1$" + "*^!!%]]!']])%.!(&-U!(=]!%^%!)>!*)-U*%]Q!%]M!&=U#%]Q!%^!!%]M!$MM!" + "%]I!%ME!'-=!']E$\"-E!'=A(&-E\")=9!%M-!&])&%M5!%M%!%]1\"(-1+%]!\"&=)$" + "'1!'-]!%^!+%]Y!%]Q!!.5!&>!#(>%!*^!!&.=!%^!!'.)!%^)!%^)!&>)\"%^!!" + "&.5!%^5&$^5!%^-!#>%!%^)!%^-!%^)!,N)**.%)'.%&%^!!#^)\"&.)&*.%#%]U&" + "&N!$\"-]!&>1\"%^)!%]Y!%]]!&.5!%]]!#MY+%MY%*-Y)%^%!&=Q(%]U!%]Q!%]I!" + "&-9\"%]M!&]A!&]E!\"-A!(-=!(]A)%]I!&-=\"*-I4&M5$%M5!&-E\"%\\]&']-!$]!'" + "'-)\"%]%\"$=!!&=!$)-!\"(\\Y!%!%&=]#'-Y!#=]!&M]$$N%!" + "%^!!%]]!'-Y!(>)!'^!)'.-!%^-!&N1#%]]!&>1\"%^)!)>-%'.!!%^1!&.9!$N-!" + "&.=!'>)'%^-!%^)!&.-!'-]!'>5&(=]!%^!!'>-!'>9!%^1!&N1$&N)#%^%!'>5!" + "$N)!(>%!%^%!'-Y!$N!!%^%!'.-!%]Y!'-]!%]]!'-Y!%]]!%]Q!&-U\"%^!!#]1#" + "(]I$%]M!\"-U!%MM%(-I!&]E!&]A!%MA!$MQ!&]=!%-5#%]=+&M5$(MA$&M-!\"M5\"" + "'=%)$]5\"'M%*%M!!#\\](%LU!%]!\"&LM!$!!$N!!%^!!" + "%.%\"'^)$'-U!%^)!&.%!'.)!'.)!%^-!%]]!%^)!'.1!&^5%'^1)'>1!#>-!%^1!" + "&>1($N-!(.9*'.1!).1#)^9,&>%#(.1%(^--'>1'&^5*&.5!#>!!#N-!(^)#$N1!" + "(^-#'.)!\".!!#N)&&^)%'>9!'.!!'.)%%]]!(>%+%^!!&]]%'.!!'N%#&-U!$ME!" + "&=Q#$MQ!$MQ!&]Q%%]I!%]Q!&-=\"$MI!#=I!(-A!$]-\"&M9$$-1$&]1!)=-\"$]1#" + ")--&%M-!&=)$'M)$(\\Y!'-!,&=)$%\\Y#&=%$*%!$]Y!&N%$" + "%^%!(>)!'.)!%^-!%^-!%^%!&.9!$N1!%^)!'.%!&N1$$^5!&>)\"'>5!%^-!&.5!" + "'^E#%]]!)^5&&.5!(N9!&.9!$^A!,^1*%^1!'.)&&>5\"&>1\"$^5!&>=\"&N)$%^1!" + "'>1!%^-!%^-%&.9!%^)!'.)!%>)$'^1$&^!%&>!#$N!!$N!!%]Y!#=]!$MY!&>!#" + "&]M%&-Y\"'-U&'=E((-Q%%]M!&-I\"&]E+'ME(%MA!%]5\"&MA$&=1)(=9#%]%'&-1#" + "%MA!&M-!%M%!&=5((M!%$<]!&M!!'L]!%-#'.)%" + "%^-!%^)!(>-!&.9!%^1!&.9!%^!!&.5!&N-#\">5!&>5-&.=!&.9!).9)&.9!&.9!" + "$^E!&.A!%.=\"&.9!%^1!&N9#&NA#'>9!&N-##N9!%^1!'^9)%^)!&.9!*NI$'.-!" + "'>5!%^-!(>)&&^-%%^-!%^-!(N9!&>%#%^1!(^)\"%]]!)=M,%^)!)=Y%%]]!&N!$" + "\"^!#%]M!%^%!%]M!'-U!%MA!(-M!(=I!%]M!(=U!%MA!\"-=*'M5$%==$%ME!%]5'" + "%M1!%M1!%M-!%=%$%M)!%=-$$-!)&M%%(,Y,%\\Y\"&LU!%!!&^-%)N%!%^-!)N%&&^-%$.!$(>-%" + "(^)($^!!%^1!'.%!\".-!&.5!$^5!&.I!(>-!&.5!&.9!&.5!&.=!%^)!&.=!&.=!" + "$^E!&.M!'.1!&.=!'.1%&.5!#N=!&.=!&.9!&.=!%N9$&.9!'>M&#NA!$^5&*.9\"" + "&.9!(.9%(^-(%^-!%^1!&N-#$^5!'.-!+.A,&>)\"%^%!%^%!%]M!%^-!'N)('-U!" + "(=]!'MY-%^!!(MY\"%]Y!%]I!+-M#(-M+(=U&(-=!&]M!(MQ,&MA$'ME(']=/%M1!" + "'M5*(-1'']5&'--\"&M=$$=1!%M)!%])\"$<]!%!!%]Q!#=Q!%]Y!%]]!#>-!%^)!!>-\"$N)%#>)!(=Y!(>-!'>1&%^-!&N%$" + "'N9(&.9!%^1!&.=!&.5!&.9!)^Q&&>5\"(NA,)>=/&.=!&.5!$^=!$^A!&.A!(NA!" + "&.A!&.A!'N=\"\">A!&.=!&^A$&.U!&.=!(N5!'NI'&^A$%N=$&.A!(N=!%>-$$^9!" + "&.9!$^5!&.I!+N9*&.5!&>5\"&.5!$>1$%^)!%^-!%^-!(N!!$N%!%^%!%^%!&.!!" + "!.!%'=]\")M]!'-Y!%]U!$MU!&MQ$(-M!%]M!%]M!%]I!(]E.$MA!'M=$#=5!%MA!" + "&M=)#=5!%M1!%]5\"'M-*(-)\"&M%%$=1!(\\]!%\\]\"&,]#&L]!%!!#M]!(-Q!" + "(-U*&-Y\"%^)!(=]!$M]!%^!!)=U0&>!\"%^%!%^-!%^)!'M](%^-!(N1!(.-*%^1!" + ").9)'>9!'^9#'>5&(>%!(N=!'NM'&N9#*.A''NA''>A!'>9!(NM!&.E!&>E\"(^='" + "'>E&#^M'&.9!).E#*.M!&.Q!'>A!&.E!\">M!&.E!&.]!&>A!&.=!#^A\"&.A!&.E!" + "&.=!#>=%&>=\"&.9!(>1!&.=!&.5!'>9!&.5!(>1%&>-')N10%^%!&N)$&.)!#>1!" + ")>)%%>%#(-U!(=Y&$MQ!(=U'%^%!%]Q!$MM!&MQ$%M1&)=M!*-=$&]E!%M9*$]E\"" + "%=9$#=A!%M9!$<]!%]-\"(=5-#=1!$=%!(M%$%LU!'--\"&]!!%LM\"%\\U\"%!&%^!&%^%!%^)!'.)!%^1!$N%!*^!!'.1!%^1!$^=!%^1!" + "$^E!&.E&&.=!&.5!#NA!'>9!'>E!&.5!%>U\")NQ0%^A*&NQ\"'.I%(^M'(NI!'.=%" + "(>I+&.I&&.A!&.M!&^I)&.E!)^E!&.A!'>I,'>A!&.=!$^E!&.E!&>I!%.Q'(NI&" + "'>A!&.A!&.=!&.=!$^E&&.9!#^5\"'N9'#>-!%^)!$N1!%^-!&>!\"%^)!)N)&'.%!" + "$N!!'.)!%ME!$]M!$MY!)-Y)$M]!(=Y!%]Q!']Y))-A+$MQ!&]=!'ME)$ME!(-=!" + "$MA!*=9!%M9%#M9\"&M%!%]-\"%M)!%]=!&-%$']%!%-%$'=!)%\\]\"%1'$^I!&.5!&.A!$>)$" + "(.5*&.=!&>E'&.A!&NA#'>E!'NA''>=!'^I\"(^A\"'.I%#NI!&.I!+^M#'NM'$^M!" + "%^M%*.A'&.M!'>M!&.I!&.M!&.M!&^I$\">M!'>E!'>I!&.M!&NI()^I,$^E!(^E'" + "&>E!#NI!\">E!)^A!'>E!%^1!&.=!&>5\"#N5!'>5!%N5$&.9!(.A*'^5)#^1'&.)!" + "'>-'%^1!$N%!'N!)'.!!$M]!&-Y'*MY&&]M%#ME\"%]I!%]I!%]I!%M=!'-Y&$MI!" + "&-=#'-5\"%M9!%M5!\"M=#']-*%]9&$=)!'-%#&M-%&\\Y&&L]&$\\]#$=!!&\\U&%!0&]Y%%^%!%>%#(>1!'>1,%^)!*N-%&.5!%^)!'.1!+.5'#^9\"&^9%$.A#'.=%" + "'>Q!&^A$&>=\"'.A&(>A+&.M!%.9\"&.=&&.M!#NM!&.I!&.Q!&.I&&.Q!$_)!\"^Q#" + ").Q-&?!!(NM!'>Q!&^I$'^U\"'>M!&.]!#^Q!'>U!).I.(N=!&.M!'>I&)^I!'>I!" + "&^I$(NA!)^A!&.M&&^9$'^9#&.A!&.I!$^=!'>5!'>5!'>9!%N-%&.5!&.5!&>1\"" + "'>-&'-Y&#^)\"$^!&'.!!'.!&&-]\"&]=!'=Y'&-Y\"%]Q!&=M#%]Q!%ME!$MA!%ME!" + "%]M!%]E!&M9$%M9!(-E!'-1'&=1$%M-&'])!%M%!&M)!%])\"&L]!$=!!),]!%\\U\"" + "%LM!%%!%]Q!'M])" + "%^!!%]U!\"^!#$N1!'-]+$>)$'.-!'.1!&>1\"&.%!&^9%)^=!(.5$$^=!&.A!&.Q!" + "$^E!&.E!$^Q!&.Q!(^Q!'^I#&.A!(>M*$^M!'^E#+NY.\">U!'NM''>Q!(N]&(>U$" + "(>U%&.U&&.Y!'.]$(/)().I#(>Y*(^U'&.U!'>I!&.Q!(>U/&.Q!&.I!)^I!&.M!" + "&>I!$^A!*.M!#>=%&>I!&NM#$.A#*^E%'>9!(NA!'.=%&.9!(NA!&.=&&>-\"&N1$" + "(.1*#^-\"&.-!%]]!)>)*'^!)%^1!#>1!%]Q!%]Y!(-M!&]I!'-A!#=M!$MM!%M=!" + ",]E!']9+$MM!#M5\")-9!%M5!(]5$)--!'=-$&]-'%M)!%-9#%M)!&]!'%]%\"(LU%" + "'LU!&,U#$LM\"(%/%]]!*^%!" + "!-M!&.%!$N1!$^9&(>)!'>)'%^1!&.1!\"N1'(N9+$^9!(^1-(>5+&.A!'NE''.I%" + "&NE#&NI\"&^=$&.Q!&>Y!&>Y!&NQ\"*.Q'&^U)$^Y!'^]\"&^Y#'NM!'>=!&.U!'NY'" + "'NY!(^U!*.Y'&.U!&.Q!'^Y\"&.Y!%/!!+>U'!.U!'>E&&>Q!).U''.Q%&.E!$^M!" + "'>M!(^Q!&NI#(>M%'.Q%&.A!#^E\"&.A!$^5!)^Q&$^=!'>-&$^A!$N)!'>5!&^5%" + "&.5!%^1!).-$'.)%%^)!%^-!'N5(%^!!%-]#$MQ!'-Y!'-U!'-M&'-M!%ME!'-M'" + "%]A!%]I!&-M\"%MA!%M=!%M5&\"-1%&-=#%M-!'\\M'$=)!&<]$%M!!(,U#%!%" + "%^%!).1$'>)'%^-!&>!##N=!$^5!'>1&(.9*#NI!%N=$&.9!$^A!#N9!&>E!*NM4" + "&.A!&.Q!&.M!#^=\"$^Q!#NE!(^Q!)O%#$^Q!&^U#&.Y!'NY!'^Y\"&.Y!&.Y!*>]-" + "'_)(*.]!&.]!&.]!&?%!*?!(&.U!&?!!$^U!\"^Y#&.Y!*?!!&.U!&.]!&N]\"&.I&" + "&.]!&.Q!'>U!&.M!&.M!'>I&%.Q!'>A!&.I!&NI\"&>A!&.A!(NA!%^)!&.A!'N-\"" + "#>-!$N%!%>-$&N-#%^%!&.5!%]]!%^!!$N!!']])%]Y!%]M!)-]%#=Q!%]]!&MY$" + "%-=($MI!$M9!&-A\"%]5\"&-A\"&-A#%M-!%]1\"'--#$]%\"%M%!'\\M\"%M)!$,Y$'L]%" + "%LU!&\\Q&%!!%]]!%^-!%]]!" + "(>!!$>)%%N5%'^-)'>1&!.9!$N1!'>9&(.=$&.I!&.=!%^A&&.I!&.E!&.E!&.E!" + "(NM,'>=&&NQ\"(>A+&?!!)^U,&.U!&?1!*^Y$$.Q#-_-+$^]!&?!!&.]!&.]!&.]!" + "&?!!$_!!'O-!&^Y#&?-!(_%!'O-!&?!!'^]'%^]%$_!!%N]$*.]!&.Y!&?!!&.Y!" + "(^U!$^U!(^Y!'NQ'*NQ##.Q)*.M!&.I&(.E)*NA0&.I!&.=!$^9!(^-\"%^1!&^9%" + "&.=!&.9!#N9!$N1!%.9\"+^)+%^)!&.%!%^!!&N-)'.!%&=]#$MQ!&-]!(-U!&=E$" + "'-A'%]I!(]A$%MA!&-=\"#=-!&-E\"$]9'']1*#=A!%]-\"%-1$#M%\"%!$'.1!&N-$" + "%^%!#^!\"&.5!$N1!)>5*&>E\"&.A!&.=!%^1!'.=%$^M!&NA#).I\"&.M!&.U!)^M1" + "'>Q+'>Q&(.U)&.M!&.Q!$_%!&>]!&.Y!&N]\"&.Y!'O!!&_!)&?!!(_!!&?-!#O1!" + "'_)(&O!\"'N]!'?%%&_9\"&O%\"&?!!&.]!&_!#%O!#$.Y#'/!*%_%$&.Q!'N]!&.]!" + ").]-+NU'*.U!&.Y&&.Y!%>Q#$^Y!&_!#'NI!'>I!&NI\")NA%&.E!'^)*(.A$(.=$" + "&.9!&N-#'>9!&^1%%^)!#>-!&>)\"\">!!%^)!%]]!%]]!%.!\"%]Y!(-U%(=Y!%]]!" + "%ME!%]I!+M5'%M9!#M9!(==\"&-5#%M5!&-9\"%]I!&]=!%M%!,M=&'LM!(]!!&\\]&" + "&9!'^=(+NE4$.I#&.E&'^M\"'^=(!>I''>M&#^Q\"'NY!" + "&.Y!&.]!$_!!&.Y!&.]!'^U(&^Y#&NU\"'O!'!/!!&.]!&?!!%/-!(_)!&?%!*>Y3" + "&?%!&?%!$_)!'O)!*_%#%_%%&?)!'/)$&/9%&?)!'O1!'O)!&?!!&O!\"&?!!&^]#" + "%/-!&.]!'>Q!&.Q!'NY!*.U!*^M**.M2)?!('NE!#NE!&.I!$^A!'^E\"#NA!&N=#" + ")>=/'.=&$^9!'.!!#>1!%>-$'>-!&N%$$N)!%^-!$^%!%^!!%]Y!%]M!%]Q!%]Q!" + "'MM.%]M!&-I\"#=E!&]A%%M9!&-=\"$]9\"&-A\"(=1#\"M-#(])&&=9$%M%!'\\Y!%M%!" + "%\\]\"$L]\"%LQ!&LM&%,]#%!!'=U''^%)'.%!%^%!" + "%^-!'>)'%^-!(^)(&.)'&.=!&.5!\"N5\"\">I!$^A!$^I!$^E!&>A')NY$&.Q!+NU!" + "\">U!)>Y)%^A&).U-(_%!&.]!'/5$&.Q!$_%!&?)!&?%!&O-!&?!!#O-!&?)!$_)!" + "(_%!&_)#&?-!#O!!&?)!&?)!&?%!(/A!*?)!'O),(_)!(>Y*'_%((^U!#O%!+>Q!" + "(O!%(_%!%?%\"&.]!&.]!&?!!'.M%&>U!$^U!'NM'\">M!*NM)'>I!(^Q!&.E!-NA&" + "%>=(&.A!&.9!%N5%&>5\"%^1!$>-$%^)!%^-!'.!!#>)!,>!)&=]#$]Y!&=E#$MM!" + "(=Y&&=U#\"MU\"#=I!'-I&&]=!&-A\"(]A$%]5!%M5!%]5\"(--'&=)$\"-%!(LQ!%]!\"" + "&LY!&5&&.Q!&.Y!&.M!&.Q!+>A'$^Q!&.U!" + "(^Y!)^U,'>U!&?)!'N]'#N]!(_%!$_)!&NU\"&.]!'O)'&?%!&?5!&?1!'/9$%/5!" + "&_-#$^]!%/5!'_A''O-!&?1!'/1$'/5$*_1)+O-!&?-!%/-!'O)!&?)!)?5\")?%(" + "$O!%*O!/&?%!&.]!'O!!%/!!$^Y!'>U!'.Y$'NY!(^Q!&.M!$^M!&>1\"&.E!+>M!" + "&>A\"&.9!&.9!&>=\"&.5!&.-!&.9!&N-)(.1*'.-!&>%\"&]]%%]Y!%]]!'>!')^!(" + "(-M!%]Q!$]M!%]I!\"-E!#MA!'-1'%M=!%M9!%=-$&=1$(=1('=!)%]%\"%M%!'=%(" + "']!!%LU!%M!!*1#" + "&.5!&N5#&.9!'.I/&.A!&.=!%.I!&.E!%NI$#^M!&.E!'NU!&.Y!&^A$&.Y!#>Y%" + "'N]''^]!&.M!%O%#&?%!$O5$%/-!&?)!(_!!%/-!)/5-%/-!&?1!'O)!#O1!&?1!" + "$?1#*_-)&?-!&_1#(?))'_1!&O-\"*?1'&?!!*?5''O1!&?9!(O9$&?%!'?)%&?)!" + "'/)$#NY!&?5!&?!!&.U!,/)/'O%!'/!$&.Y!&.Q!&.M!(NQ&&.M!'O!!(.E)&^E)" + "&.=!&.A!&N=#&.=!'^5#&.5!(^1-%^1!$.-#$N)!&MU$&]]%%.!\")M]!%]]!(=]," + "#=Q!%MQ$%]Q!\"-Q!%ME!%MA!%ME!$M=!%M9!&-=\"%]=!$]=\"%]5!#=)!'])+#]%#" + "&M!%(]%!)\\Y!&LQ!%LM\"%\\Q\"$%\"'.%&'N-('>1''.1!" + "%^)!)^9&&>9\"\">=!'>=!'>E!&.E!#^5\"&^Q#\">Y!'.Y%#NM!->Y*'^Y\"#NY!&.U!" + "$_%!&?!!%/5!&?1!#O)!&?)!&.Y!&/)&'_-(&?-!)/1!(?1$&_5\")/1!(/=\"(O5*" + "&O%\"&?A+%/1'%/5!&?9!&?5!)?5(&O)\"&?5!&?A!&?5!&?9!&?9!#O)!&?)!)/-!" + "&?)!)/)''/!$&?-!'NY!(_%!&?!!)/!-'>Q!$^Y&&.M!&?!!&.U!).A#'NM'(NI!" + "&.A!&.I!%N=$+>9((N5!'.A%&.5!%.-\"'.1%%^-!&>%#&=Y#%^%!*^!''-]!%]I!" + "%]Q!'>%'&-Q\"$MM!%]M!&M5%$=9!%]I!&-9\"&-E\"'=5(&-)#&-A\"%M5!&]5!%]-\"" + "&-%#']%&%%&$^1!$N%!%^1!\">5!" + "\"N)\"&.5!&>9\"&.A!&.I!$^E!&.Q!&.Q!&.I!'NY!$^U!&^U$(^U!(^Y!(_)!&.]!" + "#NU!&N]\"&.]!&O1!%/5!&?-!*/!!&?=!%?1\"%/1!'O9&%_9*&?1!*?9!&?9!%/-!" + "&O1!%/=!)O9\"'/-$&O5!'_5'&_9\"&?E!&_M\"#OA!&_5#&?-!,_5&&?!!'O1!)_A*" + "&?5!(_-+'O)!&?)!%O)#'?-%&?!!%_!$\">]!&?)!&.Y!#NU!'>U!&.M!'>I&&.M!" + "&.I!'.E+&.A!&.A!&.9!&.A!$N1!#N=!'.1!%^-!'^))'.)!\"-Q!&>%#%]]!&.!!" + "$MU!\".%!'-A\"%]Q!%-M#']=%'-E''=A(%M=!&-9\"$]1\"%M5!(])/+M%3%M%!%]!\"" + ")=='%]!\"\",M!%\\E##\\U#$\\E#%U!#NU!(>]$$_%!'?!%'.]/#O%!" + "&?-!&?)!&O)!#O1!\"?9!&?=!&O1(&?1!'?=%&_5\"&O=')/E!&?5!&?5!(/M!&?=!" + "%/=!&?A!'?=%&O=!'O=&&?=!&?9!)/A,&?=!)?=(%/9!&?9!&_9)(OA+'/1$&?)!" + "&?1!&?=!)/-!#O-!(?))%/-!$/%-&?%!&.U!#O)!#O!!(^]!&.I!'.Q*(.Q$&.U!" + "&.I!&.I!&>E!'.-%&.=!&.9!(N9!%^-!'NA!$>5)*N)%%]Y!'.-!(>%!)M]!%^!!" + "'MY#$]]&%]U!&=Q#%]M!$=E$\"-I!#=A!%]A!%M=!+M=!%]I!(-1+'-)\"'])+'--'" + "%]-!%M!&\"<]\"',Q#$\\I#'<=!$\\I#%LQ!\",I!%LI\"%\\A#%L=\"$,=!&<1!%L5'&LA\"" + "%,!!%\\)##<1\"#+Y!&+]!'+Y!&L!'%[E!$[E!%+]%%;E\"%[E$'KE($[=!$[5!&[M-" + "#[1!%;5\"%+%\"$;5\"%[%%%;!$#[%!#[!!$:Q$#JI!\"JM##ZA\"%ZI*\"ZE!%*=&$JE(" + "\"Z9!$J9!$J5!#J%!$*!##J1!%I]\"#J!!%:%(#)M#%9]%#9Q!$9M%#YM##IE\"#I=!" + "%I)(\"Y1\"%I5*%)-%&9A*$Y=#\"II!%IA##9A!#II!#YI#%9U%$)Y##IY!$:-#$IU\"" + "$:5$#J-!$J1%#Z)\"#J-!#J%!\"Z9!#Z=\"\"ZA!%ZQ&%*Q'$ZM\"$:I$'ZU\"!:A\"#[!!" + "\"Z]!#[!!#[%!#[%!![9!$+=!$+5!%[9!&+M%%+A%&;A&![I!$[I!'+M!$K]#';U+" + "%KM#&+]!&\\%#$,%!%<9!$<)\"',5-%\\9#%LM\"'<5*&LA\"%\\A##,5!$LA\"$LA\"&\\Q&" + "%)'%^%!%^!!%^1!\">-!(>%!\".1!" + "&^9$&.I!&NE#%^I%'>E&&.M!&>M!$^Q!%>]\"%>U((.Y)'O!!&.U!&.]!&?)!&?-!" + "&?-!#O)!&?)!$_!!)/%!)/E!&?5!%/9!#O=!&?9!&?E!&?=!&_E\"&?=!%/E!&_M(" + "&_A\"&OE!'_A!'/U#&?5!'?E$(O9$)_A#&?9!&?A!&_A\"&?=!)?-.&?9!&?=!&?5!" + "&_%#'?5%&?1!(/1)&?1!'O)!&?)!&O%\"$.Y##/1$&.]!'>E!$^Y!&.U!)NU/\">]!" + "*.M!&.Q!&.I!&^I$&.M!(.A*(^-.&.A!'N5'&.=!&>%(&.-!\".%!%^!!&-]\")]](" + "$MY!']Y%&-U\"'-U!']M*%]I!&-I\"%ME!%ME!$]-\"%M=!#=5!%]5\"'M-.%]1\"&M%!" + "%]!\"'-!'%L]!%M%!'M!*$A!'.)&&.5!$^9!&.9!" + "&.9!(^A!)^E!&.I!&.U!&.A!&^U#'.Y$#^I\"&?!!'NY!'.]%%/-!&?)!'O%''O)!" + "'O-!(_)!&?-!)?1))?5!'_9!&?E!)?I!&?=!#O1!&/E%'/A##OA!)?E'*OA!*_U(" + "&OI')_A*'_E!)/9!#OA!(/A!+_E!'_I!)/A!*O=!'_A!&_=\"%/=!&?=!&?-!'/9$" + "#O9!'?5*%?5\",_1&&_1)'>Y&'/-$&O-!&.Y!&?)!$_%!'>]&$^M!$^]!&.U!+.Q," + "&.U!(NI!)^I&&.Y!&.E!(.A)&.9!&.9!'>1&'N%\"%^1!$N)!%N-%'.%!\".1!'.!!" + "&=M$%^-!&]Q%'-]!%]U!#=E!(-M%&=E#$ME!)MA-(=I,%M9!'=9('=1-$=-!']5!" + "%-=#%M)!'-!(%<]!&LY&$-$&N=#'N5').5/*^A%(>5+" + "(^A-(^E-$>1*&.=!&^M$#^E\"&.Q!(NU&(N]+&NY'\"NU!*_!#&.]!&?-!&_)#&?-!" + "(_1,&O1!&?-!&?=!&?=!&O9!&?=+%?A!%/=!&?E!'_A!*_Y!'_A!*O=!*_E(&OI!" + "&_I\"+_=!'?I$&?E!%/]!&OI!'_I!&OU!)/E!&?A!*OE!'_E!-?I!#O=!'_A!'_A!" + "#O=!&O-\"&OQ!&/Q$)/5!&?=!&?)!&?E!%/)!%/%!$_!!&.]!&.]!&?%!(/)('>U!" + "(^Q!'_!(*>U\"&.M!&>E!)^E!(>A&'.5&'>=&'.I*(N5,&.5!%^%!$>)*%^)!'^%)" + "\".!!'.!!%^!!\"-U!&]M!%]Q!&=Q(#=I!$=9!%MA!$M=!$]9\"'-9\"%]M!$]1\"']-!" + "%M%!'M)$*-!!$L]\"&,Y(%-%$%\\U\"%\\Y\"%LM\"&!!&N5#%^-!%^)!#N=!$^E!&.A!&.I&" + "(NE&'^A('NM''^Y('^U(&.Q!(NA,'N]!&?-!'O!!&?1!&?-!&?1!&N]\"&_%#)/=!" + "&?5!!O9#$_%!&?9!%/9!)/5!&?=!%/Q!*OA!*/E%*/E+*OM!,_E+#OE!&OI!%O=#" + "&OM!'_Q!&OM!'_M'(_E+(/Q!&_=\"'OM%\"?E!'/M#&?E!'_I!)/9!)/E!'_I!'_I&" + "&_I\")/=,(?9)&_9\"\"OE!'_5'&O)!(/=(&?-!'_!!)O%#$_%!$_!&&N]\"&>]!&.U!" + "'NY!&.Q!&.M!$>Q$&.M!(NM!%^1!%^-!%^%!&N9#&>-\"'N1('^-#%^5&).-$%^!!" + "'-U!&]]%$MY!'=Y((=Y!%]U!!-I!%]I!!-E!'=U\"&]=!!]A$']5!%M5!'-%#\"--!" + "(])&&-%$%M!!&\\]&&-!($!%$MQ!&MY$%]U!$MU!&-Q'-N%.&M]$'.-!$N1!&>5\")^9'&.9!)>5%&.M!" + "&.E!(.M)&.M!&.Q!&.U!&.U!$^M!(NI!'N]'(?!)&?%!&?%!'?)%&?-!'/-$+O1'" + "(?5#&?5!&?A!'O5!&?=!'/E#+OI%+_E!&_E(%/I!&OM!&OQ!&OI!&O]!)?M!&OQ!" + "&OI!%/E!&OU!!/Q!*OM''_U!&OU!&OQ!&OM!)OM\")OM((_I+&OI!'_E!'_A!\"?5!" + "*?E&&?9!&OM!&?=!'?9%!/5!&?%!&?)!&?-!&?E!#O)!'?-%'_-'&.]!(/)(&.Y!" + "'^U(&.Q!&.Q!'>M!(NE!&.I!&>-\"+NQ-\">I!(^='(.=$$^A!+>E!(>-&#>)!)>%+" + "#^!\"&-]!&>!\"'MQ#%]Q!&]M!%]M!%ME!)=I!$=9!%ME!&-9#$M=!&M)!%<])&M-!" + "%M)!&]5!',Q#%=%$%\\]\"%\\]\"(-!-'LI+&%!%^)!$^9!$N-!'^9#&.9!$^9!&.=!$^A!&.E!" + "&.M!&.U!$^M!&^Q#&.M!&?1&&.M!&N]\"&?!!&?!!&?)'&?)!'O%!'O-&&?%!,O9%" + "'O)!#O9!(_=%'OA&#OA!'_=!&OM!&?E!%/E!&OI!&OM!'?]$'_M!%_U#&_U\"&OI!" + "#_M!-/Y,&OM!&OY!'/U)&_U\"(OM$%_M#(?Q)&/U$'_Q!&OY!&OI!#_Q!%/=!*_A\"" + "'_E!(/A\"$/Q\"&?=!&OE!&?9!&?9!'?-%%/1!&?5!,?A\"'O)&'O%!$_)!._!1&.Y!" + "#.U)&.Q!$^Q!&.Q!%^M%&.Q!&.A!&^=$&NM\"(N=!%^1!(>5&'.-*$]U''.-!&=]#" + "$N-!%]U!'-Y!%]Y!'-U!%^!!&-U\"%]M!%]I!']E$%]A!&M=$&M9%(]%*$M5!%M-!" + "(M1)%]-!&=-$&\\]!%5!&N)$%^-!%^1!&>1\"&.9!'>9&'>A!&^Q#'>I!" + "%.I!&.M!&.E!+>U!&.E!&.U!(_!&&.U!'_!\"\"N]!$^]!#O%!'O1!&?1!'O1!)/5!" + "&?5!'_E!'_=!)?M!'_E!'_A!)_I*'_Q!&OI!%/E!'/9#+_Q&&?E!\"OM!&OU!)_Q#" + "!/]!&P-!&OY!&P)!(/]!)?I!'_Y!)/M,(/]!&OU!&OU!(_Q$&OY!(_U+'_M!(?=)" + "%/=!-/M&)/=!&OA!%?=!'O=&&OI!'O1!'O%!'/5$(O9*&?1!(/-)&?!!&?%!&.Q!" + "&.Q!'^Y'(NE!$^Q!&.M!%.Q!+^M)&NI#'NA'&.=!'>9!&^9$&^5%(>A+%^-!%^)!" + "$^%!%^!!%]]!&]U*&N)#&-U'%=I$'-U!%M9!*=A&#=A!&]A&(=9,'M5)&M5%'M5)" + "%]%\"%]!\")-1&'-%\"$!!'>9!'>5!'^-#'N1\"'>5+&NE#$^I!&.A!'>A&'^E#" + "&.I!#^E!%>M\"*NY\"(NA,&.U!'O!!$^]!&?%!&?%!'O)!&?9!&?1&'_A''O5!)?9!" + ")/=!'?=$)/A!*OM!&?5!#/I#(OI$)/E!)?M!&OI!$/U(&_U!&OU!'_Y!%_Y#'_U!" + "&OI!+?]*&P!!%/]!%0!!(/]!&O]!&_Y!'/]\"(OY*(/Q')?U!$/U\"#_M!\"_I\")OQ\"" + "'_U!(?E)%/I!'_E!&OM!&?=!+OA7$_Q%*O=!'?-+(?1#&?1!$/1\"&?=!&?%!'O)!" + "(^M-&?!!#NU!&.U!&.]!(>I+'>U!(NI!&>I!&>E\"%^)!&.!!&.I!%^-!%^!!'.)!" + "(>!!'.%!$N1!%]Y!)-]*%]Y!']Q$%]Q!&]M!%]U!%ME!'-=\"%M=!&-5#%-5#&=12" + "(M)$%M)!$M-!(]%!%-!$&-%$%L]!'LQ!%1&'^1)(N5!'>A!&>A\"%.I\"&.I!&.]!" + "(NI!%>I()NQ*(>I%$^Y!(_!,&/!&&.]!)/-(&?)!$_%!'/1$'^]!%/5!'O1!'O9&" + ")_A/)/A!-?1)+/E#&OI!&OM!$/Y!'OU%&_Q\"&P!!\"?U!#_]!'?Y$&OU!(/]!#_]!" + ")/],(_Y$'@!#%`1\"&P)!%0!!&P%!&O]!&OU!'/]/'/Y#&OU!&OY!&OU!'P!%(/]'" + "#_M!%/]!'_E!(/I!'_=!&?=!%/A!&?A!'O1!&?5!&?1!&?A!%/-!&?)!&?%!'>Q&" + "%NM$+N]'(NM!'>A!'>Q!'>M!&.E!&>Q!'>E&+^=+&.=!%N1$%N9$(>-!&N-#$^9!" + "&^)%'>!\"%^!!%]U!$MY!%]U!$MY!%]Q!%]Q!%]I!%ME!%]I!#]E#%M1*%M5!']-*" + "'-9'']-!'])+%M1!'=))'%!%]U!#MM!%]]!&-U!%^%!)N)1(>)!'.%!&.=!&.9!&.=!'>E!&>A!&.Q!$^I!" + "&NA##NY!,.]$&.M!&.U!&.U!&?)!$_%!'O)!&_1\"&?1!'O1!(/9(%?9\")/=!&?=!" + "&OI!'_E!*_E\"%/M!'OI%(_Q$'OM%&_U\")/U,&OU!&OY!&_]!&O]!&OY!)P-!(@!\"" + ",@%!&OQ!(0!!'`!,-`1!(?]\"'_U!'0-\")@!!(O]))OU.&`%'&_Y!'@!$&_U!&/Q%" + "'_Q!&_M\"#_E!%/M!,/E!'_9!&?1!\"?1!%/9!&?9!&_5#)/1!&O)!&?-!$_)!&?%!" + "&O!\"&.Y!*?%!&.Q!&^U$\">Y!$^M!'^Q\"&>M!$^=!&>A!&.9!(NI!$^5!*.-.&.)'" + "%]Y!&^-%%^!!$M]!\".%!%]A!%]U!$MQ!%]M!&]I%%M5!%]I!'==#&-A\"%-=$(-A!" + "'-1'#M-\"$=%!$]%#&,]#%<]!%LQ!%\\Q\"&)!%]Y!'N-(#>)!'>5!$N1!'^-#'N9'&.9!%^1!&.E!#NU!&.M!" + "&NI#%>Q\"#NY!*.U!(^]1!/%!(?!$&?5!&_1\"&?1!&_1\"'_5'&?=!&?-!+_=!(?9)" + "'O-!'_A!*/M$%OE#(OM$(?M\"'_Y!)?Y!(@!\"&OU!-0-#%O]\")@-&(0)!*`)!,@-'" + ")`%)&P%!(0!!'_U!(@%!)P-!(/]!(0%!(OQ#,@!!)@!!&O]!&P1!&O]!%/Y!&OU'" + "%/]!&/Q%&OM!)?M'&OI!,?E/'_E!\"?Q!'_=!&?A!&O1!*O=-%?1\"%?!($_)!(/1)" + "&O!\"&.]!&.]!$^Y!&NU\",NQ!&.]!'N]!'>M!&.E!\">A!&.5!%^-!%^)!&.-!%^)!" + "%>1#$N)!&.%!&.)!'-Y!%]U!)=Y&%^!!&]A!$MI!']9%'-U!$MA!%M=%%M9!&M5%" + "'-9,&-A\"%]-!#=%!&,M#%M!!%<]!&,Y#',Y##LI\"%-!%^)!(>1+*^1%&>5\").93#NA!'^A(&.Y!$^I!)^E!" + "'NQ'%NY$*.Q!$^Y!&.]!(NQ&%?%\",O),'/-$&?!!&_5\"'_E!(?%*)/5!'_5'&?=!" + "&?E!(/9(&OI!)/Q&&OM!&_Y!(/Q-)_Y.)?]!&P!!(0!!,?Y4(09!'_I!(@!\"(09!" + "(0-!(0)!+0-!(@)!-`)!)@!!(0)!(P9\"(0-!)0%%)P)!(@!\"%0!!&OY!&O]!&OY!" + "(_Q+-OY!&OI!$?M#$OE$(/E!*OI!'?=%'_I&%OM\"&O9!#OA!&?1!(/=((/%#'_)!" + "$^Y!&.Q!&?%!$^U!'>U!&.Q!&NQ\"'>M!&.9!&^Q$$^A!&>=\"%.9\"&.5!&>5\"%^1!" + ",.%-&N1##>!!\".!!&-]'&-]!&]U%'-]!&-M\"&=I#'=I('=E\"&]A!%M=!&M9$%M-!" + "&]1!&]1+%M%!%M%!*-%&%M)!)-!,%)!%^%!'N5(%^-!%^-!(>)!&.=!&^9%'^=#&.5!&NM\"&.=!&.U!" + "&.I!+>U!&^Q#&.]!#^]!&_)(&?)!$O1$'O)!&?1!'/=#'O5!(/5((?=#*OA!'_I!" + "(?I#%?I!)?I!'_Q!%/]!'_Q!%@%!(?M\"'P%$(/]!(0)!$0)!(0)!\"@!!)@!!(09!" + "(0-!/?Y)(@A!(0-!(0%!+@-),@-!)01%)@!!)P)!+@-/#`%!*?Y,'_Y!'?U$(_]+" + "&O]!)O].)?Y'\"?Q!&OI!&OI!'_Q!)?Q!&?A!&?=!&?-!&?-!%_5$&?1!&O-\"'_)!" + "&?5&&?!!&.]!&.I!\">]!$^Q!&.Q!&.M!'.=%'>U&&.=!$^=!\"N=\"&.9!%^-!&>5\"" + "&.5!%>-$%^!!$N%!&]]%%]Q!$MY!(=U!!-Q!&]M!%ME!)-=!&]A!&]A&&-E\"$=A$" + "%M1!%M-!%]5\"$<]!$=%!%\\]\"%\\Q\"%LY!&\\]&'LI*%!$%^%!%^-!$N%!'.)!%^-!&.9!$^I!'NE!(>E%'>A&)^I!&.I!" + "&.U!&>I!'^Y'*.Y!&?!!'O!!$_)!&O)!(O5%'/-)*?5,&?9!'_=!*OI!!/A!)/A'" + "(?E#&OI!&OQ!(_9%!/U!%OY('`!&&P!!(0!!(`!$(0!!(@!!(05!(0-!-0)1&01$" + "#`1!\"@1!'01\"(01!(01!(/]!(P)\"*`%!&`-!*0-**P-,'0)\"(_U%(@%!+/]!)@!!" + "&O]!*/U+(/Y'%/U!&OQ!'_]&&?=!'_M!%/I!#_I!&_A\"&?9!&?5!&?1!&?1!#O-!" + "+_)(\"?%&$_!!'N]!&^U#'NU'&>I!&>M!#NI!&.E!$^E!&.A!'.A&)^9!)N1!#N9!" + "%^)!'.-!%^%!&.%!$N!!$M]!$]M\"%]U!'MI)(-E&%M5!%]M!&MA$&-=\"$=9!%]5\"" + ")MA(']1/%M1!%M5!#M%\"&,]#%-!$&L]&$\\Q#$LA\"')\"(^)(%^%%'^-#$^5!%^-!(>1!&.=!)^9''>A!&.I!&.M!%.Q!" + "*^U5'.Y$(^Y!#NY!%/%!)?!#(?-#&?-!%/1!&_1##/5$&?9!&?=!)/A!&?9!&OQ!" + "&?E!&OM!&?9!'/Y\"&OM!&OQ!+0!!*0)0#?]$&P%!'@1#&P-!(09!&`9!(01!)`-(" + "&P1!)@A%'`-%#`5!%`5#&`5!%@%!)@A%+01!(0-!)P-!,@9&+0!!%@1!%@%!(0!!" + "%?]!(0!!*OY&&_U!&P!!&?A!)_I*&?E!'_=!)OA.(_5&&?5!&?%!&O1('_A!&N]\"" + "*/!2\"?=!*>]''O%!&.Y!(/%('^Y\"#NQ!$N=%-.E0#NA!&>=\"(.%*&.A!&.9!'>5!" + "&^!%&N)#%^)!&.5!%]Y!$]Y!&]Y*&-U!(-Q%%]M!%]Q!&=A($MA!(]A/%]='(-9'" + "'-5'$]1\"%M-!%M1!(M%$&-%#&M!%'LY!&,U#%LQ!$5&&N5#&.9&!.=!(NA&)>A$&.E!&.Q!(NM!" + "'>Q!'.U%'^]\"&.U!'O!!(_%&&O-!'_-!&?9!#_9!\"?=!#_-!*_9))?I!)?E')?M'" + "&?E!'/U#&P!!-?E'(/]!\"_]((/]!+@)/)0%%(@)!(09!)@1&+`11&01$)P1!'P5$" + "+P90(05!&`9!'@A)(09!&`5!&`9!%P5!'05\"#`5!,P5!)01%&P-!(0%!)P)!(0%!" + "(0!!(0-&&OU!&OU!&OU!'_I!&_I\"\"?Q!%/U!'_A!#OA!&O=!&O9!%/5!'/1$)_)*" + ")/5!'^]\"#O!!'N]!'.]%'?%&*>E)&.Y!&.I!&NI\"&.=!\"^A#(N=!&.A!&.5!&^9$" + "&.5!&N1#(>)+).-)%^!!%^!!(-M+'=I(#]U#%]M!%=A$)-9+)=M!&-A\"(MI-!==\"" + ")\\]%#=1!%M)!%LY!\"=!\"%,Y,',U#$L]\"%]&'O!'$^]!$_)!&?-!&?5!(/A('?E$&?=!'_=!(?I#&/E%&OI'" + "&OM!+/Y)\"OU''OY%)/Y&&O]!(0%!'P)$(0!!.@A/&P%!*0-#&P-!$`A$&`9!'01\"" + "%@9!&`9!\"P-'&`5!(05!&`5!!0=!(`9#&`9!&`9!&`5!)`5((0-!&P!!(0)!'_U!" + ",/]!&O]!&_]!)?]'%/U!&OQ!'?I$&OI!'_E!'_E!%/9!&?=!&?9!(_)!&?-!&?%!" + "$^]!'/%$%/5!(^]!#NU!(NY&&.]!'O!!\">Q!&.]!&.A!&NA#&N=#&>=')^9!&.5!" + "(.5*%>-(&>-\"&.!!\"-]!(>!,$MY!&MU$%]U!&=M#&-Q\"'MA$$MI!'M=$&-E\"&-9\"" + "%M-!*=1,$]1\"%=)%%]%''=%$$<]!()!%^-!%^)!)>-%&.9!'.M%*.U!%^1!$^E!&.I!&.U!%.Q!" + "'>U!&>A!$?!#$^]&&?%!'?!&%NY#&?-!&?)'&?5!&?5!&?9!&?E!)/E!#`!!!/M!" + "(/Q('?M$&OU!'/Y#(/]!&OU!(0!!(`!$)0%%)_]))P5!(0)!'P1$'01\")P=!&`A!" + "(@=!(@A!+0A')`A!*@A*(PI!&`-!&`=')0=*'@1#(P5\"(@1!&P1!(0)!)@!!(P)\"" + ")`%\"(_Y$%/U!(0!!'_U!&OM!$/U\"&OQ!&?A!'_=!&?A!&?9!'O5!(O5$&?-!&?1!" + "&O-!&?!!&.Y!%>]($_%!&?%!%NQ))>Q#(NM!&.M!$^9!'>I!$^A&(.=$(.9*%^%!" + "%^1!&>%#(^92&>1\"%^%!(>!!(-M0+-U#(>!!%M=!%]M!&=I#%-=#$]=\"$M=!%MA!" + "&-=\"'-A\"&-=#)M!.*-%!'-%\"'-!'\"5\"&.5!&.9!&.I!&.Q!&NI().U\"&>E!(N=!&.Y!" + ")O!*(N]+&^]#&.Y!\"?)!$_!!'O1&&?5!&O)!&?9!'_9!&O=!(OE$)?Q!%/M&&OM!" + "*OQ!&OU!(/Q!%/]!'?]#)/]%(0!!(09!-`9'*@1+(`5#'P1$)P1-%@=!(@=!(@=!" + "&`A!'`I%(@Q!(@E!*PM*)@E%&`A!)`Q!(@A!&`Y!&`=!'PA*(01!)`%)(01!(`=#" + "(0)!'_Y!#_Q!)/Y&#_I!(?]('_Y&&OM!#_M!(?M\"&?A!(_=&#/9)&?9!&?5!&?1&" + "'O-!%/-!&?%!'NY'&NY\"*?!!*>U\"'.U%$^E!&.I!(.E)'>A!&.A!$N1!(>9+(^-#" + "#N!!$N-!'.)!(>!!&^!%$M]!&=I#%]Y!%^!!$=U%%]M!%]I!*]Q!'=E(\"])$$=5!" + "&-9\"%]1!&LY!$M9!'M%%%=%%&=!$%M%!&M!%%]'&?5!(_)!'O)'&?!!%O-#&?9!(?9*%/E&)OE\"'_E!(?I\"'_=!" + "%/U!(`%*%/]!+`)%&P)!(0)!+P96,@)!+0-!(0--'P5$)`9.'05\",P=!(@=!(`I\"" + "+@E')`A!&`Q!+@A!)0I$#0U#&`9!(@E!(@I!+01!&`9!&`A!#`5!+`%2(0-!(/]!" + "(0)!)P%!&P%!(/]!#_]!#`%!$?Q#&OI!&?A!'_E!*?9&(_I%&OA!'O5&*?5!'/1$" + "&?-!).U\"&?%!'/!$#N]!%NY.&.]&$^Q!'>Q&#NI!&.A!'>E!&>A!&^1%&.5!'>9!" + "%^%!%^-!$>)%%.)\").!%'^%*)M]!%]I!%-U#&]M!&]M%']I$&MQ$&]A&*-=%$]9\"" + "%M9+(-%,$]1\"']%!&]-&#\\]#&\\Q\"$\\E#'\\Y+',U#&A!&.E!'>A!&.M&'^U($^A!" + "$^U!&.]!$>]$&.Y!&?=!&?)!&O-!'O9&)/A&'O1!&?E!&?A!+?=+&_I\"&OM!#OE!" + "&P!!%_U)'O]%)P)'#`%!(0%!&P%!+@-\"&P1!#`1!,P5!(`1#(@=!(@A!+@]!(`A#" + "(@E!*PM$)`M!&`E!%@M&(@I!'P9*'0E((@E!*PE+&`9!*@9#%@A!,@-!(P-)(0-!" + "+P)1,@)!(0!!'_]&(/E!&OM!%_U)&_M\"&?A!'_Q&'_E!&_A\"&O=!'O=&#O5!%/5!" + "\"?9!#O!!)_%%*O-!(^U!$_!!&.Q!%>Q($^=!&.E!$^Y!(NE!&N-$&.A!&.I!'.5&" + "$N%!%^)!)>-*)>%0(-U+&N!$%^%!%^!!'=Q\"#]Q##=M!%]I!'=A#&M=%'-5'$=5!" + "%M5+%M1!&=-$$=-!%])\"$=5!'<])&])&%M!!$1\"*^-!$^5!&.I!&.=!&.9!*.I-#^I\"&.M!'>Q!).U\"" + "&.]!'O!')/!-&.Q!'/9##O-!'O-!'O1&&.]!'_9!&?A!&?E!(?M\"&OM!$/Y\"%OQ\"" + "&P-!%/9!%/Y&&_]!*@!$(0-!(0%!)P9!(01!&`9!(09&)`9(+P5*(09!)`I!(@I!" + "&`M!)`E!*0]!'@Y\",@M%(@I!%@M!(@A!#`9!(@Q!+@=/&`M!(`A#&`9!(@1!(0-!" + "*0)))@%&%/]!'_Q!+?Y#)OU!&OU!&OQ!&_M\"&OE!&OE!&?A!)/='$OE$*/1+)/9!" + "&?5!$O1%'/%$)/%!&?!!$^]!&?)!#O!!%.U!&.Q!$^E!).I.$^A!&N1#&N1$%N1$" + "&.%!$^I!&.)!&.9!'.%!'.!%%]Q!$MU!&-U!%]U!'=M\"'-Y!)-9&(-A!'=5##M9\"" + "%])\"&M1%#=-!&]-!%M)!%]%\"%]!\"%M!!&\\Y!#)+(>A%&.5!%.A!'>5!'>9&#NA!*>I\"&.M!$^I!(^U!" + "(_%!&?!!)/!($_%+'O%'&?9!&_1\")/5!'?-%&?1!\"?=!&?9!'_E!'OM%&OM!&OQ!" + ")_Y\"&OY!&_]!&P)!(0!!*_Y!%@)!\"@-!(0-!%@5!&`9!&`I!,0E$)PI&&`A!(@E!" + "(@M!)0I$+0Q,(@]!&`Q!+`Q\"(@]!*@I)(@M!&09#&`M!+PM/(05!(P1)(01!(@-!" + ".P)$'_Y!(/]!&OQ!&OY!(?]/&OQ!&OQ!'_M!)_E/+_E,&?A!&?=!&?5!'O!!&_5#" + ")/-!'/)$(/%((_!!&O%\"&?!!'>Q!&.I!&^M)&.U!'>E&'>M!&.A!&.I!'NA'&>5\"" + "(N1,'.-*(>-!*>%*,.%-%]Q!%^!!'=U\"'-U!(-U*(=Y!'=I()=E1$MA!'-=!&M9$" + "'M5$$]A\"&]1&&M-!&]-!'M%%\"-%!'-%''LY%),Q'#,M!&,I#%\\A#$LA\"&,I$&\\9(" + "%L=\"%\\=#%<5!%,1!$,5!%+Q!%,)!%9!%^)!'-]!%^!!&>1\"&.5!&N9#&>-\"#N=!&.=!%>=#(NQ,'^Q(#NU!" + "$.Y#$^]!&?!!&O)\")O!)(/)(&?-!%/9!&?=!&?9!&?5!$_5*+?5+&OI!*_M(*@!%" + "\"?U!&OY!&P)!&`-!/0!!)P%!(0%!&P-!(/]!(`=#(`9#%@=!(@I!(@E!,@U+&`U!" + "*0U!*`Q+(@Q!)0Y#)`Q!+@I!/`Q!(`E\"(@I!)@E%*PY*(P-\"&`9!%@9!(01!(`-$" + ")?]&(@)!(O]#&P-!&P%!&P%!&O]!&?U%&/E%'_M!'_E!&/A%#O9!*OA!)?=('O1!" + ")_-%%/1!'_1''?!&+O!!(/%\"%^I%\">Q!$^U!'>E!$^I!%.E\"'NA'$^=!&.=!#>1!" + "$^-!&^-%%^-!%^%!#>%!$N!!%]]!(>-!%]U!'-Q&(-M!%=I$'ME$(-=!'-5'$=-%" + "%M-!&=5$%M1!%])\"&M-!&=)$',U##,U!*\\Y*$!*'.-!&^5$(>)!$^1&(.1*'.-!&^5%'>A!&.A!'^E\"&.A!&.Q!'>U!'NU," + "&.Y!&?!!(?!)&?)!%/1'#O)!#_1!\"?-!'/!$&?9!%/=!&?E!%/A!&OI!'OM%)OI)" + "#_U!'O]%)?]!$P%#(/]!(0-!(0)!(05!+01!&`5!,P9!%@5!&`A!(PI!*0I\"(@M!" + ")PQ&(@U!+@Y!+P]!(@]!)PY%-@]\")`M!)`E')`I!&`=!%@A!%@9!#`9!)01$(01!" + "(P)\")P%!(0!!(/]!+@!0&OY!&OU!*OM!#OE!)_Q)&OM!'_=!'/=#'_9!+O1!\"?1!" + "(>]*)?)()_-1'/9$&?%!&_!)&.Y!'?)%&NY\"&.M!)^E!$^I!'^=)(N5!'>=!&.=!" + "%N5%&.5!%^!!%N5%'.%!%^!!%]]!#-Y$)-=!'-M&#]M(&=E$&]E&&M=%'-E'%M9!" + "&M%&&M5*%M%!']-!%M)!%1\"&>!\"%^-!(^M'(.9$'>A!'N='*N5+&.I!'NM''>Q!%^U%" + "+>Y-'O!!&O-\"%_!$(/%#(_!!'/1$(/1\"&?9!$?1#&OI!)_A#'_M!(_I%&OM!&P!!" + "(OY*&P-!%?]'*_]!(0)!%0!!,@)!)@5&%@-!(05!%@=!&`E!(09!(@E!'@I\")`A!" + "(@I!)`U!&`U!*@E)(@M!.@]!*`]+(@M!/P=!&`M!,`A!(@=!)P=!&`5!+05!)P-'" + "(P)\"*P%,*`!-&P!!&O]!&OY!%OU\"&?E!&OM!*OM!(_Q$./A%&OA!&?9!&?9!&?1!" + "&?1!&O)!*O)($_!!)?%.&>]!'NY!&>U'&.Q!&^Q$&.I!(.U##N=!$^=!&.A!(N1'" + "#NA!%^1!%^-!$MY!(=Y!%^!!%]]!%-Y\")=Q!(=M'%ME!)=I!&M=$%MA!&-=#(=9," + "&]5&%]5!+])4*-1%%]-\")=%\"$=!!&\\Y!%!#(=Y!" + "&MU%%]M!\">5!'>)!&^-%%^)!&.9!'.)!&.9!'^=#$^=!'>E&'>I!&.A!'.U*&N]\"" + "%O!)&.]!%O-#+O%!&.Q!'O%!&_5\"&?-!(O5*%/-!&?=!&?9!#OE!&OM!&OM!)?Q'" + ")?Y!&OY!*@)+'?Y$&OY!&OQ!(/]!(P-\"&`5!&`5!%`)#&`A!(@A!(@I!&`E!(@I!" + "(@A!(@Q!*0U!)0M#(@E!)`M!&`Q!%@Q!(@E!)P5')0E$&`=!,@1-&`5!#`!!(@)(" + "(0!!(0%!&OY!(P))%@)!&P!!&OM!&O]!\"_U\"%/A!(/M!&OA!%/=!'_9'*O5-%/1!" + "&?)!(_-&$_%!&?%!&.Y!&>Y!&?%!&?!!$^Q!)>M.#^M\"&.M!&.=!$^=!%N=$&.5!" + "&.9!'^%)(.-%%>1#%^!!)M]!%]Y!$M]!&]]%%]U!%]Y!'-A\"%ME!$ME!#=9!$=1!" + "%,]#&M5*']5!#,]!%M1!&-!$&=%$&,]#$!\"$^)!*>!%%^)!&.=!'.-!'.-!'>E!'>=!%^1!&.=!'^I-'.I%'.Q%#NU!&.U!" + "&^Y#*.]1$_!!&O1!&.Y!(_%'&O-\")/-!&?5!!/5!&?A!'?9*'_E!%/I!&OM!)?Q-" + "'?M*&?E!&/M%%/Q!(0)!(`)$,@-!)P)!'P1$%`1\"&`9!&`I!(@=!(PA!+0I-(@E!" + ")`M!(@M!+@Q'(@Q!(PQ!(@Q!(@M!&`=!)PQ&#`9!$@9\"&`=!(09!%@5!&P1!\"`-\"" + "(0%!(0%!(`%$&OY!&OM!&OU!*/U+&OQ!&O]!&?=!)?E(&?A!&?E!#/9#%O5#&?)!" + "'_-'%/-!&.Y!\"NY!$_!!,/%#%NY#&.U!#^Q!&.I!).A($^E!%.Q!(NA,&N9#'>=!" + "(^!)$N!!%^)!%^1!&-U!%]Y!%^!!%]U!'-Q'(MQ\"%]I!&]Q!%ME!%M=%&]A!*-=/" + "&=5$(M1.%]5\"&=-$%M)!%]%\"%-!$^5!%^%!'>-&$N-!'^5)%^=&'>9!$^E!#^I\"#NM!(NE!+^U4" + "*NI$(.Q#$>Y$&^Q##O!!(_-,&?-!#O-!%/-'&?A!&?=!#OE!'_I!'/I#'OU%%/A!" + "(/M(&OU!&OY!'_U!(0%!(P)\"(@)!-0)2)P9&(01!'`5%(@1'&`9!)P9!(@M!(@=!" + "(@U!)`I!*0M((`M\"*@I#(@E!&`E!)`E'#`M!,0A2+@1)'@5#&`A!)@!!)P1'(0-!" + "'`)&+/U\"&P!!'P-$)?]!*_M4'_M!&OM!'OE&)?M-(_9%&OA!'_9!%/1!&?)!)/A!" + "&?5!&?)!\"?)!#O%!#N]!&?!!&.Y!&^M$&.Q!'>M+&^E$'.E%&.9!'>=!&^9$$^5!" + "%^-!*^)!'>)!\"-]!&^5$'.!!(=]!'-Q&%]M!$MI!&]=!#=I!)-E+#]I\"'=E\"%M=!" + "$=9!(=9\"%]!\"%M%!']-!&M)!&]!\"%M!!'<]$(,Y#$A&&NM\"&NI\"$^Y!$^Q!&.U!" + "$NU%(^Y!'O%'&?!!#O%!&?)!'O5!*O-(+_9!%/1!%/I!#?A%)OA\"&/=%'?M$&_M\"" + "&OU!&_Y!&P1!&`%!(/]!)@)&)P%!)0)%(0)!)P1!&`5!%@I!)`A!)`=')@5%(@E!" + "(@E!(PI!(@U!(@I!(@A'*0=)(01!(@E!'P5$(09!%@A!'09!&P1!(@1((P-\")01$" + "(0-!,@%!)P!'&O]!%OI\"&OU!,OQ*&OM!%/I!)?I'&?=&'_I!*O=3&O=!)/5!&_1#" + "$_)!(/)#%/1!'/!$&.Q!'NY!$^U!'>U!%^Q%&.M!(>M+'.A%&.I!'.9&'>9!$^=!" + "%^-!#N=!%]]!(>)!'-Y!(N!-%]]!%]Y!(=Y,*MQ,&MY$&-I\"$-A$&]I!&]5&%M9!" + "'M5*#]-#&M5$)\\Y!(=5''-)\"&=1.%<]!&\\Y+&LU!(,U(*-!!$\\I#)!\"%^%!%^)!%>-#'>5!&.5!%^-!(NA!'>9!'>I!%.I!&.M!'^U'&.Q!" + "'_!('.]*(^],$^U!(O-*&_=\"&O-\"&?1!#OA!(_1+)/A!&?9!#OA!'_I!&OU!&OY!" + "'_Q!&OM!#_Y!&P%!&OQ!)/Y%(0!!(01!'@1#(01!(P%\"%@-!'0=!%@=!(09!$@E\"" + "&`5!(@E!(@E!*PE+(@A!)`M!(@=!(@A'\"@A!&`=!'@=#+05!)P-!(05!(0-!)@%&" + "&OU!/0!!)0%%%/]!&OU!&OU!(_U%#_]!)?I!)/A!*_5)&_Q\"'_9!&O5!'?5%&/-%" + "'O5!'?)%'O1!&?%!&.M!&.A!&.Q!#^Q!$^M!$^M!#NI!&>M!'>E!&.=!&>=\"(>Q%" + "&.)!%^)!%^%!'.-!%^!!'N%()M]!%]Y!%]Q!&-U!%MA!&]E!']5!%MA!'M-*)==!" + "%]1\"%M-!$]1\"%M%!#,Y!&-%#']-*(,Y,%M!!%\\U#%LM!#1\"'N1()^91&.E!)>E$&.E!&.I!'>9!&.M!&.U!" + "$^E!&.Y!&.]!&?5!(?-)&?-!$_)!%/1!$?1#&?=!$_)!&?E!%_E$+OA%%/Q!'/Q#" + "(_Q%&OQ!'_U&&O]!(/]!(0!!&`)!(@%!)P)!)0-%)P5!&`5!(P5)'/Y\")PA&&`9!" + "&`=!(`A#(@9'#`A!(@=!(@A!(P=\"&`=!(09!#`9!)@9%(05!&`=!(05!(0%!+01!" + "(0%!)@!&&OY!&P-!&OU!(OQ*)?Q!*OM!)/I,'_5!%/9!(/=\"*?9!(/5(%/1!&?1!" + "&?A!#NQ!&.U!'O!'&.U!(.Y)$_!!$^I!%>A#$^I!'>E&&>E!&.A!$^5!&.1!$>-$" + "#>1!'.1!%N)*%^-!#=Y!%]]!$MU!'-U!\"MU''=U'&N-$#=I!)=5\"&-A(%]I!$]A\"" + "&M)!%MA!%MA!%=)$%M)!%]!\"#=)!%<]!%)!'N-\"%^1!$N1!&.9!'>=!&>=\"$^E!&>E\"&.]!&.M!$_!!" + "'>M!$.Y\"&.]!'NY!&?!!&?!!%?5\"#O-!&?=!&?5!$?=#)/=!&?A!'_A!)OI('_I'" + "*OM!%/Q!&?E!&_Y!(/]!%?]!(@!!'_Y!)P)!)0-%+P5*)@1&&P)!*P)2(P9\"*050" + "&`9!(P=\"%@9!&`9!&`A!(`9#&`E!(`5#&`9!!0A!(@-!&P1!)P%!)P-!%@%!(0%!" + "&P!!&O]!&OM!)_Y\")?U!&OU!%/M!#_M!)/E!*OI!'OE&'_=!(O9*%/5!$_)!#_-!" + "%/1!&_%(#O-!#O%!(/!(&^Q#$^Y!+NY'&^U$+NQ(&.=!#NI!&.9!&.=!&^E$&.-!" + "'>1!%^!!'.=&&-]!&.!!$N)!%]Q!'=I(%]Q!%]M!%]M&&]M+$MA!&-E\"$=1!&M9$" + "(-)'%])\"%M-!%M1!$])#&M!&&,]#%])\"'\\Y!%A!#NA!&N5#$^9!&.=!&.E!&>I!$^Q!&^M$\">Q!" + "'_%!'O%!(O!%#^E\"&?!!*?)!&?)!)/%((O)*&?9!&/1%%?1\"&OI!'_E!)/E!(OE$" + "&OM!#_Q!#_Y!&P!!%?U!&O]!)@!!'_Y!)P).&P1!&P1!(0-!)01$(05!'@-#%@=!" + "(09!#`9!&0E#&P1!&`9!(09!)P5!(`5#*`)!(P1\"+01!,`-)*P%%)P)!-`%!+0)(" + "(0%!&P%!(OY*(O]#&OU!'_I'&O5(&?E!'_E!\"?9!'/E)&?=!(?A)&?9!)?5.$_-&" + "#O-!&?!!$_%!&.Y!\"NY\"$.Y\"*>M((.Q)&.I!&NI#&.M!'>E&#NI!)^A!%^1!#>-!" + "\".1!%^)!%N-%'N)#&^%%!]]$%]U!%]Y!&MQ$&=M#)]]\"#=E!%MA!%=A$']=%&-A\"" + "&M-!%M=!%=!*'])!&M%&%M!!&E!&.Q!" + "'>Q&'>U!&?!!&.U!\"?!!)?!\"&?)!&?1!&?1!&?9!&?-!$O)$'_=!'_E!%?A!$/U(" + "&_U!&O]!'_M!&OU!'/Y#'_Q!&O]!'0!\"(/]!(0!!(`-$(01!)/Y&&P%!,@1!(0-!" + "&`9!&`5!(0-'#0-#&P1!(P5)&@1%+P=0(01!)PE&(`-$*`)!*`)!&P%!(@1'*_Y!" + "%/]!&OU!'/]\"&OI!&OQ!\"?U!&?9!)?I!'?I$)/A!'_=!&_A\"\"?5!&^]#&?-!&.Y!" + "(/=.#O%!'O%!&_-#(.Y)&NU\"&.Q!$^M!&>Q!%NI$'>E!&.A!'>9!'^9#)>5%&.9!" + "$^A!$M]!#N)!\".%!'>!\"(M]'%^-!&MU$%^!!']M*%ME!#=E!%MA!&]=!%-=#%M9!" + "&]5!%]1\"%M1!(--+*M%$']!!*-%!(\\Y&%\\Y#'\\Q+%%!%]Y!#=]!$N%!&N1#%^-!&.1!$.9#)N%!&.=!%^=%'>E!$^I!$.U\"$^M!" + "'NU'$^U!'.Y%$^]!'O!!&O%\")/-!&O)\"'O-&#O5!'/!$(O9*$/9\"(O=**O=!)/E!" + "'?I$#_Y!&P!!%/Q!\"_U\"(/U'&`!!(/]!+05!(0%!'@)#)P)!*`%!)P1!(@-!&P1!" + ",@-!(P)#*@1++01!%@1!%`1)(0-!(01!(`-#(P5\"&OY!(01!(`%$(P-\")?U!&OQ!" + "&O]!&O]!&_U!&OQ!%/Q!&OM!)OA)*_M-(OA$&?E!%/9'&O-\"'O5!(O9$#O-!&?)!" + "$_%!&.Y!&?!!)?%('NE!'>A!$^U!&.M!&.E!(.I$'>E!&.Q!&.=!(>A+(>1!&.9!" + "*N-%%^-!&.%!\".-!%^!&%]Y!$MY!(]U#&>!#']E*&-I0%MA!%M-!'M5$&=9$%-9$" + ")]93%M-!%M%!$=%!&,]#%M!!%!!'>%'&.)!'.-!'>)''-]&&.5!&N=#&.=!&.A!%^=&'NI''>M!" + "&.Q!&.I!&?!!&>Y!&?%!)O!$&?%!$_)!%?-\"%/1!&?9!&?5!'_M&(/=(&?A!)/E!" + ",?E\")_U\"*_Y!'OI%&_U!)?U!&?E!'?]#&OY!(0%!&OY!+01!,`)#)`-\"$`-%,@-!" + "&`5!)P)!&`=!+@5('`1,.@-6(@-!,0-&'@)#(0)!*P)%'_U!+O]$(0!!\"?Q!(P!)" + "!/E!'0!\"&OQ!&OU!%/M!%O]\"\"_E\"'OE&'?I$'?=$&?9!%/5!%O5#&O1!'O)&&.]!" + "&?%!(?!$(^]!&_!#%.Y!&.Y!'NQ'&.Y!#NE!&^A$&.A!$^=!(>A+&.9!&.9!#NA!" + "'.)!'.%&$N)!(=],&-Y!'-Y&&-]\"'=U(%]Q!%^!!%]I!&=I$\"]A#'-='%M9!%M-!" + "'=%(&-)#'=5$*-)!%M%!&=!$%,U)&<]$%LM&%\\Q#',M#$LI\"&,I#\"<1\"\"L=#'<=%" + "%<9!&<5!%\\1#%,%!%K]#%,%%%<)!%;]&#,!!%;U\"$+U!\"[I(\";=\"%[A%%[E!\";A\"" + "%KA#$K=$%+1\"&+1*'+-/%[))$[-$#ZY!#J]$&JY!$*U\"#ZU!$*I&$ZA\"$K!$#J9!" + "\"ZA!%Z=#%Z9\"$J5%&:1!%:-(\"J!!#J%!%J-&#J!!%*%$%YY#$)M##YU\"#9A!&9I*" + "#Y-#\"I5!$)='\")%\"#9=!!IA##Y=#\"II$$9I$\"IQ!#)]&#IM%$9]$%:!$$Z-&#J%!" + "#*%\"#J-!%J5\"#J9!#JE!$*=\"#JI!#:M#$JM%\"ZQ!#[!!%:]'#*Y\"$[!)\"Z]!\"ZU!" + "![1!#K5#%K1$&+%'%K9($[=!%;A\"%K=#&[I!';I\"\"KQ#$+M!$+Q!'L!#$;Y\"%+U!" + "'[Q-%<%\"&,%)&L1&&\\1(&<5%#<1!%\\%,&<=!%\\A#%LI\"&,Q#&\\M\"%%%%^%!$N%!%^)!'^-$&N1#&.)!&^5%&^%%&.=!'NM'(>E+'>I!&NI(" + "(^Q!(>I%&.Y!&.Y!(^Y!'_!!&?!!'/))%^Y%'_A!#O1!&?=!&?=&&O=!(?=**/5+" + "(/E!#_M!&OE'&OQ!)?I!&OQ!'OM%&OU!&O]!%?]!)@%&*_Y!%@%!*`%!)P-!(0)!" + "*@1$(/]!\"@9!&P-!*`1&,@)!(0-!&P!!)P%!*`%!&/]$(/]!*@!%&_I\"(/]!#_Y'" + "\"?]!%/U!&OQ!*_Q(&_I\"%/I!'/E*(_A%&?A!&?=!&?9!'O5!&?1!)/-!(?-)\"?)!" + "'/%$*/!!&.U!&>]!&.Q!'NY'&>Q!'.M%&>Y!&.E!#NI!&.9!'>9!&.%!&.=!'>-!" + "%^-!'.%%'.%%$N!!%]Y!%]E!&MU$$MM!(-U*+-I)$MI!%ME!%ME!#=5!%-5$&-1#" + "&-=\"&M5%%=)%#=%!(-)\"%M!!'-!(%\\Q\"#LE\"&LQ&$!!%N%%\".%!&-U!'.!!&^1%&NE#&.9!'.=&&.A!&.E!)^E&(.Q$" + "+>M!'NQ!&.M!&NY\"&?!!#N]!&?!!'/-$(_)!'O-&%O1#+/%%&?5!#O=!$/E\"*OA!" + "'_A!(?U\"&?E!'_E!&OU!&OQ!%/U!#_M!$@!\"'_Y!&O]!\"@%&&`-!&P)&#_]!(0!!" + "(0%!(0%!(0!!&/U$&P1!*0%*(0!!)P%!(01!+/]((0%!&`!!(/]!&OY&%?]!!/]!" + "&OY!$OU$&_M\"&OQ!%/E!)/A!+/A#%O9#&_9)&?5!&?-!&?5!&/-&$_%!&O)(&?%!" + "(/!.&.Q!&.]!&>Y!&.]!&.Q!&.M!).I\"'>I!&.I!&.A!#N=!).=#$N1!#>)!&.=!" + "'>9!%^%!%^%!&]]%%]Q!%]U!#]]\"$MQ!$]E,#=U!&]A!$MQ!%ME!%M5!#-9$%M)!" + "%M1!$]9')M)2&=)$#=)!&<]$%<]!&,I#&!#&N-$%^-%\".%!&.=!&.5!%N=$&^=$&.E!" + "&.Q!&.Q!).]-'^U().Y!(^]!$^]!&?!!&?%!&?-!&_-#&O1!'O%!'_5''O-!%O-#" + "&_A\"*/U+&?E!&OI!'OE&&OQ!(/]!%/]!&_U!&OU!&OY!&OQ!&OY!*0!#)?]!&OY!" + ")`!))@!!)?]!(/]!)P%!%`%#)?]')@!!(_Y$&O]!,P!0*?Y1&_Y!&OY!&_Q!(/Y'" + "&OU!&OI!\"?I!&OQ!'_9''_9!&?E!%/=!&_1\"&_5#+?1%&^]#&?-!&?)!*?1!&?%!" + "'.]%'O%!'NY!*N]\"'.Y%&.M!(^Q!$.M##NE!&.A!'>A!#NE!&.5!&>E\"'^-#%^)!" + "%^1!%.1')M],%]]!#^!\"(=Y!&]M!%]I!%]M!$MI!&]E!)-Q*%M1!%M5!)-5&%]5!" + "#=1!$=-!'-1''])!'-!(%<]!%\\]\"&LU!%%#)^)!%.)\"$^9!%^1!%N5%&>E\"(NA!&.A!&.E!\"^E#" + "'>M!$^M!&.Q!'>M!*NU.\"_)\"*.]!(^U!,/%/'?)%'_-(%/=!&?5!'/9#&?9!&?9!" + "*OA!&?A!%/E!&?A!&OM!)OU.'OE%'?M$#_I!,?Q\"'_U!&P!!\"?Y!\"?Y!*/]#&O]!" + "(O]*(?](&P!!(0%!(0!!'@!#*OM!)P!!&O]!'P%$*OU2&OY!&OY!&OU!'@!##_Q!" + "*OQ&&OI!%OM\")/A!(/E!&_Q!#OA!'O5!'/A#*?)!&?-!&O-\"&>Y!&?%!&_1\"(/!(" + "(_%!%.Q!'NY!&^M$(NQ+(>I*(NM!&NI#)^E!%^1!)N%!%^)!&.5!(>%!&>5''>-'" + ")=Y!'.)!%^!!&.%!'MU#$]M!%]U!%]U!&-I\"%]I!&-E\"'-A!$M=!%MA!&=5$'M=$" + "%]5\"&=-)$<]!%M9!%)!$N-!(>)%%^1!'>5!'>-'&.A!'>I!)^A!$^=!" + "&.Q!&.M!&.M!&?!!&.Q!&?%!&?!!#O!!&?!!'?1*#O-!&?)!#/5$)/5!'?1*&O9'" + "(_M0(/=\"&?A!)?E!)_9*'/I#&OI!&_M\"#_Q!(/]!*_U!'_Y!)?U-&P!!(0-'(/]!" + "'?Q$$?]\"&O]!'P)$(/]!'@!$+OU+&OY!&O]!'OQ%&O]!&OY!'_U!)?I!&OQ!(OM*" + "+/I)+OA+&?=!)?E('_E!%/=!&_=\"%_=$*/5%&?1!'?)%&?-!(O)0'O!!&?)!'.]$" + "&>]!&N]\"&^U#$^M!$^Q!&NE#'O!!*.E2&.Y!'>A!'N=,%^-!&.5!%^1!'.1!).)*" + "%.!\"(^-#']Y$%]]!%^%!'-U!%]Q!&=Q#&]A!'MI))-A+%=A$(==\"$=5!%]-\"%]1\"" + "$=1!&-5#%-)(\"])$&M!%$L]\"%%!(N!()N%!%^)!'N%.(.1*%^1!'>9!(NA!$^I!'>E&%>E#" + "$^I&(.M)&^Y#(NU&(NQ+#>I%*?1!&^]#&?!!&.]!&?1!&N]\"%/=!'?)%&?5!'O)'" + "&?5!*?9')/=!&?A!'_A!'_E!*O],&?=!'_Q!'_I!)/Q,&OI!%?Q!(0-!&OY!'/M#" + "!0!!)?U!,OY*&OU!'_Y!(_Q+(?Q\"$/U!%/U!&OY!&_I\"&OQ!&OQ!$OE$'_I&#_9!" + "%/=!'_I!'_M!-/A'&OA'(/A!&?9!&_5\"&?9!&?1!&?-!&?-!&.]!$_!!&O!\"$^Y!" + "$^]!'?%&&>Q'&^U$'.M%$^M!)>M#(NI!)^E&&.A!&.=!(N9&&.5!&.9!%^)!&N%$" + "&N1#%^!!&-]!&M])%]Y!(>!!+=U*%]I!#]I#%]I!%MA!'-A!&-=#$]9\"$M1!%M)!" + "&M)%$=1!&-%$%-!&N-$'.)!'>9!(^=!$^5!'^A(" + "'>A!&.E!$^Q!%>Y\"(^Q!'>U!&>Y!&.]!'O!!#_!!$_)!#O9!&O)!&?)!)O9#&?1!" + "&?9!&?5!%OM\"'/=#&?E!)/=!'_E!'_A!(O=$*OI!%?M!'?M$%/=!'?Y$&OQ!(/Q(" + "(_U+&OU!&_U\"#OY%&OI'&?A!&_U!#`!&(_Q%&OQ!&OQ!&OM!&OI!'_I!%_I*)/E!" + "&?E!%OA#)?9!&?=!\"?Q!+/5*&?5!#O5!&?1!&?-!(?-/'O)&&?)!&?!!&?!!&.]!" + "'.]$(.U#&.Q!(^Q'&.M!&.I!&NI#&^U)&NI#&.=!$^9!'N9'&.5!%^-!&>-\"$N!!" + "+.)(&>!\"$N%!%]]!%]U!%]U!(-Q%&-Y\"%ME!\"]E#$MA!%]1\"(=9\"'M=$&=5$%]A!" + "'--#%M!!&-%$'<]$$\\U((LY*',Y#%\\Q\"*,U&%LM\"%!!*.!$'.%!&N1$\"^)#)>9/&.9!$^=!&.A!" + "&^=$&^I$%N]#&N=#(^U!$^Y!'>M!&.Y!$^]!$_)!&_)#&O!\"&?)!$/!\"%/-!'_A!" + "(/5)#OA&'_9!'_=!'?=$#OA!(O9$&?=!'_E!*_E)&?9!&OQ!)?M!&?E!*/M+&OM'" + "%/I!'_Q!%/U!'OQ%'0%)&OQ!&_U\"(/E(&OU!&OY!&OM!\"_I\"(?I#'/E#'_E!'_E!" + ")/A&&?A!'?E$&?=!&?9!&?E!&?9!&/A%&?1!%/=!&?)!%/1!&>Q!$_!!&.]!'>M&" + "&^Y#&.U!&.Q!'O)!&.E!&.I!'NE!$^M!'^9)'^1#&.9!%.5\"%^1!(N-!%^)!%]]!" + ")=Q,%^!!&=]#&]Q!%]Q!\"=Q!%]M!(]I$(M9)$MA!%M=!&]=!%M9!%M)!&=1$%M)!" + "(-)\"'=-)\"M-\"),]\"%L]&#,Q!$I/%^9&&.A!" + "&.A!&.E!*^Q+&.U!&.Q!&.M!$^=!&.Y!'.U%&.]!&_!#$_%!(?%*'O-!&?-''?%&" + "+?5+(O5*&?A!&?5!(/%(&?A!&?=!'?E$'_A!&/E%(/I!'_E'&OQ!)OE\"&_9.&OM!" + "&OM!&OI!&OM!%/U!&OQ!%OM)&_U\"%/M!'_I!$?I#&OU!&?E!%?E!&?A!'_E!)OM\"" + "%/=!'_A!%/A&&?1!&?5!'O5!%/-!$_)!&?1!%_-$#O!!'/!$&?!!&?%!&.M!$_%!" + "\"_%#(.M)&.Q!'>M!'^E#'.Q%'>A!&>A\"&NA#&^=$&.A!&.5!(>-&&>)\"'>5!'.A&" + "%^!!%>%#&-Y!&]Y%(=I'%]I!%]I!*MI!%]I!&]E%%]5!%M=!'M5$&-1#%M1!&]5!" + "(=9'%M%&%M1!']!&%L]!%\\U\"%-%&.9!%^-!(N=!" + "&.A!&.Q!&^=$)^Y+&.M!%.E\"&.M!%>A#'.Y%'NY!'N]!'?!%&?%!)?%(&O)!'O-!" + "-_),*/1+&_=\"&?5!$?9#'_=!'_=!'_=!&?=!'OA&%OA#)?E'\"_E\",?E6)?I!)?U!" + "&/I0'_9!&OI!&OM!(/]!&OM!'_M&)/I,'_M!*O=!&OQ!*OE!#O1!&?A!&?A!&?1!" + "'_=!(_5&*?=&&?1!&?-!$/-\"&?-!'?9%&.]!&?%!)O%$#O!!(.U)&.]!&.U!$^U!" + "&.U!#NU!&.Q!&.E!'>9!$^M!(>A+&.=!(>A+&.9!'.E%%^1!$N!!'.)!(>)!%^%!" + "'.!!#-])#>-!&MU%$MQ!&=E$%-]#%]M!']E*(-A!'-='&]9!&=1$&]1!%]5\"$=-!" + "%]%\"(M9.!=5\"%9!%^)!" + "$^5!%.E\"&.A!'>A!(.Q#&^Q$&^U#'.Y%&^U#%NY#&.M!&.]!(>U*'O)&(.])&/)&" + ")O-#'O!!%O1#&?)!'O5!'?1%'_=!)/9!&_5#&?9!&?E!#O-!'_9!'_E!-/A&)/E!" + "'_E!(_U$'_I!'_E!&OM!*OE!(OE$'_=!'O1!+/A0&OI!&O9!&?=!%/-!(_9%&?9!" + "%/1!)_5$+/5$'O)!(?1$)/1-*_1\"'O%'&?!!$_)!*.]2'N]!'>Q&&.Q!(_)!&.Q!" + "&.M!&NQ\"(NI!'NE''>E&&NA#$^=!\"^=#&.9!\"NA\"'.1!'.)!%^1!'-]!$N%!%^%!" + "%]Y!%]U!\">!!%]Q!%]Q!%]Q!$MA!&]E!(-=!&]A%)-5!']9*&=5$%M)!%M!!$])\"" + "%]1\"%\\]\")\\]!',Y#'!\"%^)!%]U!'.)!&^-*'N)\"'.-!&.=!'N5(" + "&.=!'.1%(NA!'N='&>A\"$^M!&.A!&.Q!&.Y!'^U(#NQ!&.]!#^]!'_1('O%!)_)0" + "$_)!&/1%&?-!'O1!&?5!\"?=!&/5*'?=$)?A!&?9!&?=!%/A!&O5!&?=!&?E!'OA&" + "%/M!&_A\"'?Q$&?A!#OA!&?=!%/A!)/A!'?=$\"?=!&?=!(?=)'/E#&O9!&?9!&?5!" + "&?5!%/A!&_1\"&?1!(O-*'?)%'?%%'O%!'_)!(O!+&?!!*N])'.]$$^U!&^U$&.]!" + "'>A!$^Q!&.=!&.E!'>I!'.I%&.9!&.I!$N1!&.1!'N1('>9!$M]!$N%!&>!\"(N!-" + "\"]Y#%]U!&>%#\"-Q!%]M!&-9#&]]%)-A&%MA!%]=!&-9\"&=9$%]5!(-E!&\\Y\"%5!%^)!'.1!&N5(&.9!" + "'>9!(^=!'>=!&.E!&^A$&.E!(NE!&.M!&.U!&.U!$_%!'>M!&?!!(?!$&?!!(_%!" + "&?%!'/)$-/5!%/-!&?-!+?-+'_9!'?-%&?1!&?-!&_9\"'_A!&?5!&?-!!/)!+_=!" + "&_5#'_)((?=*&?=!(OA0'?A%(_=+*_=\"*/A1)/5!&?9!(?9*&?=!&_9\"#O1!'O5!" + "'?)%&?9!'/%$\"?-!&?%!\"?)!(?%)'O%!)?!(&.Y!(_!!&.]!'>A!$^Y!(>U%&.Y!" + "&^U#&.I!&.I!$>M)&.A!(>=&&>9\"'.-!&^1%'.1!'-]&$N1!%N5$(N5!%^!!%^!!" + "$N!!%]]!%]I!%]Y!%]M!'MQ$&=E#&]A!)-A+&MQ$%M9!#MA&&-9\"%M-!\"M!'%])\"" + "%\\Y#$]1\"#=!!&,U#%!\"&>)\"%^!!(>!!&.=!$N-!'>5!%^1!" + "&.M!'>9+&.=!'>=+$^E!%.Q!(^A2&NM\"(NM!&.Q!&.M!%/!!(^]!&.M!(>]*&.Y!" + "&.U!&?9!%/1!)/1!$_)!&?-!#^U!$_)!&_9\"'O1!&?5!)?5.&?-!&?A!#O9!'_E!" + "%/-!#O9!(?9#&?1!'_9!#O9!&_5\"(?A#%O9)'_1''_=!'?%&'_1'%/I!&?1!'/5$" + "&?-!)?-\"(?))'O)!&_%#'?-%)_!0&O%\"'N]!#O!!$_!!&>U!*^U*&?!!&NM#'^M(" + "$^M!'^E(!.E!&.A!$^9!%N5%%^)%$N%!#>!!(>-!$N-!%^%!(.-*(N!!%^%!'-]!" + "%^!!%-U#%]Q!'-Q&&]M!&-I\"%ME!$MA!&-A\"%M9!'-9'#M5\"%M1!'])+%]-\"(--!" + ")=%\"'=!)%<]!$%!%^%!$N%!%^-!(>)!&>1\"" + "'>9!$^5!'^=((^=\"(N=!\">E!&.M!&.I!&.9!&.M!&.M!&>Q!#NU!+.Y1%NY)$^]!" + "$_!!'O)&#O)!\">]!'O1&&?-!#O)!&.Y!)/-!&?=!&?%!'_I!'O1!%/5!(O5$'O1!" + "&?1!'_5!*O5-%/A!&?5!%/5!'O5&%/5!'_9!'O5&%/-!&?1!$_5&&?1!%/9!&?%!" + ")/%(&?1!$_)!&?)!#N]!'/!$&.M!&?!!&.Q!'>]&$^Q!).Y!'>U!(.E$&.A!'>Q!" + "+>=\"&.A!&.=!&.A!'NI'&.9!&^9%&>)('.)!&N9#&.-!%^%!$N%!'>)!\"-]!'MM(" + "'=U\"%]U!%]Q!\"-I!'MM(%]U!%ME!']=*$M=!%]5!$=-!&]9&'-1''M-$%M9!%M!!" + "%M-!']!+%L]!'%%)M]!$M]!&M]$!-]*%^%!&>-\"%.-\"&^5$" + "&N1#&.E!)>9*(>-!&.9!&.I!!>E\"&.=!&>I!'>I!(^Y!&.I!'NY'$^Y!(_!'&.Q!" + "$NU%$_!!&>U!$_!!$_)!%O)#'O-&#O)!&?-!&?-!&?-!&?9!'_1('/-)(_!!&?-!" + "'O1!%/5!'O-&&?-'%/-!'O5&\"O9!'_1!&_1#&?)!)/%(&?1!&O)\"'NY!'_-'&?%!" + "'_1(&?!!&?%!&?)!&O1!'N]!&.]!&.U!(?!)&>U!).Y!(>U*)^I!&NM\"'^U'+NI(" + "$^E!(NA!(N=!&.9!$^9!&.9!&.5!&>1\"%^-!'>)'%]Q!%^1!'M])%^!!%.9\"#>!!" + "'-U!%ME!#]I\"&]M!)M9#'ME.&]A!%M1!\"-1!%M9!%]5\"'-1'%]5!&=)$#=)!&M%!" + "%M%!'-)'(,Y,&,Y#(,Q1#,I%%%\"&.5!#N5!$^E!&.=!!.9!&^A$'>I!&.=!&.M!&.U&&NM\"&.]!&?!!&.Q!&.]!" + "&.U!'>U!\"O%!$_!!$/%\"'O%!&O-\"&?-!\"?)!'_!('O!!'O)!&?1!+?!1&?-!$O5)" + "$_)!)/1!&?A!(?5/'O-!#O5!%/5!*?)!'O)!'>Q!*_-))/5!&?)!'?)%'O)''O%!" + "&?5!(^Q!&.Y!'^Y''>U!&?!!'>Q!,.Y5&.U!%^M**>Q\"&.M!#^M\"&.M!'N='&.I!" + "'.1!&NE##NE!&.9!&.5!$^9!%^1!$N!!$N-!(>!&'.%%$N)!%^!!*>!)'=Y\"%]U!" + "%]M!&-U!&-I\"\"MI+%]Q!%M1%(]9.$-Q$%M9!&]5&\"-)!%]1\"&]-'%9+!.9!&.9!&.E!&NE#+.E,&.E!&.M!&.Q!&>Q!&.Y!" + "&^U$$_!!&?)!&?)!&?-!&.U!$_!!&?!!&.Q!&.M!&^])'O-!&O)!'O9&'O)!'O)!" + "'O)!#NU&&?5!(_)!(?))&?!!&?1!&O1!&?=!&?%!(?-#&?%!&?%!'.]*)?)\"'?!&" + "'.Y$#O%!$_!!&?!!'.U%&.Y!$NI%&.Y!&.Y!$^Y!'>M!'>M!'^I#&>E'(NE&&.E!" + "$^A!'>=!&.E!&>E\"%^%!(>1%'>-&'.-!'>)'(>)&%]U!$.)#%^!!%]Y!'MM$'-]!" + "&-A\"'-I'%]Q!%]I!&=A$(-A!$]='&-9#(-A+)]E#&M%!&=)$%M)!%M%!',],%<]!" + "&M-!(1\"" + "'.-!%^=%&.5!#N5!#>)!%^)!'N1(&.A!&.9!&.M!#NE!&>E\"(^M!&.I!'>U!'.Q%" + "&>I!&.U!).U'(_%!'NY!\">Y!).Y'&?%!&?)!&N]\"&.Y!&O%\"\"?)!+/%+&?%!*O%." + "'O)''O)!\"_1\"+O!!&?)!%/-!&?%!)/-!'O1!&?-!)/%-%?%\"'^Y(%/-!&O)\"(_!!" + "(?!)\"O%!&.Y!'NY!'_!!&.Q!*.Q!&.U!'.E%&>M''NY!'^=('>E!$^E!&.I!%^)!" + "\">=!$^9!'>9!&.5!%^1!&^!%&>-\"(.9%#>!!'.!!+-]\"%]]!%]Y!(=]!'-Y!%ME!" + "%]M!%]Q!(]I)%M=!&]M!']5%&]=!$]9\"']9%%M1!%]1\"&M-%%]!\"%M%!%M!!%<]!" + ")-)0%\\Q\"$A!" + "&.U!&.E!(?!)'>U&\">Q!&.U!'NY!&?%!%.M!*>]'&>Y!&.]!#O!!&?)!%O)#'.]$" + "&?!!'O)''O%!'O!!&_%#)^U,'^]!&?!!&/)&$.Y##NY!&O%\"%O%#\">Q!,.]*\"N]!" + "&?!!'/1$&.]!(_)!$.U\"$^Q!'>U&$^M!&.U!&.E!&^M$#NI!&.9!&.A!&.=!$^=!" + "#N9!$^9!&.5!'.-!*.))%^1!'>9!%^%!$>5$%.!\"$MY!$M]!$M]!%]U!(-Q!&]Q!" + "'-U!%M9!$ME!&=I(%MA!%]1!%]-\"%]1\"#\\](&M%*'--\"%]%\"']%*%]%\"&L]&%M!!" + "%M!!&Y!&.Y!*.Y,&.]!&?!!'O!').].#NU!&.]!" + "#_!!'_!(&?1!(^Y''O%!(_!&&?!!&_!#&N]\"*.],'N]!&.Y!#N]!'.Q%&>Y!'.Y%" + "'>U!'>U!'NQ!&.Q!)>Y)&>A\"&.M!&.I!$^I!&.E!(^E-&.A!&>E!&N5#(>=%'.=%" + "'.%!&.5!$^E!$N1!%^-!%^)!%^%!$N%!$^!!$M]!%]]!']Y)'-U!&]]%%]U!%M5!" + "&-A#%]I!%ME!)]Q-$-=$%M=!'-9'%M5!&-1'&M5%&=9$&=-$(=%(&]!\"%M%&(,Y(" + "(!\"" + "(N),%^%!$N%!$^9!'N-\"$^5!*.=('>5!'.-!&>)\"&.=!&.A!)^Q,(NM!#N=!&.I!" + "#NA!'>=!&.U!&.A!(>M+'>E!(NU+'^U\"&>Q!'>U!(?!$&.Y!'O%!)>Y##NY!\"?-!" + "'O)&&>U!&.Y!$^]!&?%!&?!!#N]!'>]&(^Y!'^Y'&.U!(>U%&.U!'NY-+>M3'>I!" + "%>Y\"&.I&&^Q#\">I!&.Q!&.]!&.I!&.U!'NM!&.M!&.5!&.5!(>M+&.5!'>9!\">5!" + "&.5!&.=!%^-!$^9!'.)!'.)!$N%!%^%!(-Y*'-]!$ME!'-U&&]Y*%]]!']M$%M=!" + "(=I!#]E#'-A!&]I%&MA$&=-$%M5!$=%%%M9!\"--!%!!&.5!$N1!'.9&$^9!&.=!$N)!&.I!&.E!&.=!" + "&.M!&>1\"&>I!&.Q!!.M!'/!$(N=!'>U!&.]!'>Q&'>Q!&>]!#NM!&.Q!&NM#'^Y'" + "&.]!&.]!(^Y!(>Q*(NQ+(^Y!&O)!*NY#'>M!&>M!&.Q!&.M!&^U#*^Y*'>Q&&.A!" + "&.Q!&.Q!\">U!&.I!&^-%'.I%#^E!&.I!'>5!%^1!'.9&'>5!\">E!(>)&&N5#$^5!" + "&N)$&.=!&^-%'>9!&.5!#>%!).)*#>%!%^!!&^%%%]Y!'-U!&-Q\"$MQ!%]Q!%-=$" + "$ME!$M-!)-A&&-=\"%]9!&=A$%M!!)=A0&=-$%!!%^%!#^5\"%^%!\".)!%^%!&^-%'>1'$N1!%N5%&N=#%^-!%^1!(NA!#NA!$^=!" + "&.5!&.A!'>E!&>E!'>I!&.M!&>I!&.M!'>M!(_)!)NQ%&.U!&^Q##NQ!&.U!&.Y!" + "'.Y%'.]$&.I!&.I!&.U!#O%!&.U!&_%#,>I&&.I!&.Q!&.Q!(.Q$&>Q!&.Q!)^Q&" + "#NM!(NI&&.=!(.M)#NI!&^Q#&NA#!N9#)^A!#N9!&>9\"%.9\")^=!'N)('N5(&.1!" + "&N-)&^-%%^)!%^%!%^!!$N!!+>%)&>!#*-Y$&-]\"'.!!\"-Q!%=M$%]M!%ME!']A*" + "&-9#%MA!&-A#%]5\"&]9!(=9'$=1!%]!'$])\"#=%!$<]!$M!\"()!(^-.'>1&%^-!&.9!)^=!&.5!&.5!" + "$^I!$^A!'>A!#^E!&.Q!&.Q!)NU%'>I&$^I!&.M!%NM$%.M'&.M!'>Q!&.E!&.M!" + "'>Q!&^=$&^M)&.E!&>Q!&NQ\"$^Q!#NQ!&.Y!(NI!'>M+*.M!&.M!'NQ'%.Q!$^M!" + "\">E!'>I!(^E-(^I'&.I!'^=)&.A!$^=!&^=*%^-!&.9!&.5!'>5!*^5&$N)!%^-!" + "(.9*&MY$%^1!'N!#(MY(%]U!%]]!$MQ!%]Y!&MY$$MU!&-]!%]M!'-Y!%ME!$ME!" + "%MA!%M=!$M1*)=I!%]5!&])&&=9$']1!%M)!%]-!'=%)%\\U\"%M-!%<=!',I(&LU!" + "&\\Q\"%!!$N%!'.-!&-]!&>!\"%>-#%>)$)>9%%^1!%.5\"#N9!&.=!&>A\"" + "&.9!&.A,&NA#&>A\"'NI'&.9!&>Q!#NE!&NI\"'>I!'>I!#NE!)>I$&.Q!&.M!&>I'" + "&.]!)^I!(.M$(.I)&.M!)>M$&.A!'^Q\"&>Q!&.M!&NI\"&N5#&.I!(.I$&NI\"'.A%" + ").M3&.E!#>A%#NA!&>=\"%^-!*^A&)>9%&.9!'.-!#N1&$N1!&^5$%^)!%^-!\">)!" + "(N)'&.%!%^%!$N!!#=]!%^!!$MU!%]U!)=]%%]Q!%]E!$=9!&-A\"&]I%%MA!%M=!" + "&M9%']I$(-50&]5!'=5($-1$%M-!'-)#$M)!'M%%&M%&%]!\"%<]!%])\"&]5!$LQ\"" + "$L=\"%LQ!&LE&%LE\"%!!$N%!%^%!%^-!(>%!#>!!%^)!&.5!%^)!'>A!%^%!'>A&" + "%.5\"&.=!&.A!(>I+&.=!&.=!'NA\"(NA!#NI!&^I)$^E!&^E$%.E!*>I\"&.Q!&>E\"" + "&.U!&.I!&.I!&.Y!(^U!#>I%&.I!#.M)*NA*&.I!%^1!&.E!&.A!%NE$$^E!'NA\"" + "&>E!*N9+&.=!(>E+%^=&'N='&.5!&>1\"&.=!&.5!$^9!'N1((>-!&.-!(>!,\".)!" + "%N%*&.%!#>-!$M]!%]]!%]]!%]Y!'-U!$MM!%]Q!&]M+$MI!%ME!%]I!%MA!%MA!" + "(=E\"%M9%&M1%'-5'%M-!&]1!%M!!%])''-%''=!$%M%!%!%(N!\"%^)!%^1!(]]-%^!!(>%!%]]!'.1!%^-!&.)!&.5!" + "(.E)&N9#'>9!&.9!&.A!'>A!)N10'.=%&.U!&>E!'^E\"&.I!&>E\"&.M!'^5#&.I!" + "$^=!&.E!&NI#(NE!&.E!(.E*(NM!'N=!&.E!&.M!(^M-'>A!'>E,#NA!(.A$&N=#" + "(N=,(N=!(>=&&.=!(>1!&.5!'>A!&.5!%.1\"&.5!&.-!&.9!%]Y!%^-!%.-\"'.%!" + "(=]!&>!\"'-Y!%]Q!)=Q0(N-'(-M!'=Q\"'-E!&=I$%]E!'MI(%M=!'-9\"\"ME\"$]9\"" + "&-9\"$=5!&M5%$=1!&-%#$M=!'=)(%]!'\"=)!'=!$\"]-$%M%!\"L]#&,]#'LQ&*,U!" + "%A!(^).(N9!&.A!%>%#&.5!'>E&&.9!)>=$%N5%$^5!&.M!" + "%^A*&.A!&.=!&.=!&.A!\">=!&.=!'NA\"'>A!+>A(&^A$$^=!'^=($^E!&.=!%^9+" + "*>=#'.1!(>5+$^5!*.=('.-!%^-!%^1!%.1\"$>!%'>-&\".1!%^%!%^!!%.%\"$M]!" + "(.%%&=]#'.%!'=Y(%]M!&]Q!'-U!%]I!'MI)%]I!&=M$#=M!&-A#%]5!$==%#=A!" + "%M9!&-%$)]1*%]-\"%M5&%M%!(-)\"(=-('-%#&M!&%)!(>%!%^-!(.-*&.-!" + "&.=!*.E'\">5!%^1!&N1#'.1!&.1!%^-!&>9\"&.A!&^=$'>E!&.9!(>A+$^M!(NA!" + "$^5!&.A!'>9!'>9!&.9!%^%!$N9&$^=!'>5!$^=!&.=!&.A!'.=%&.9!&.9!&^I$" + "#N5!&.5!%N1*%^1!$N-!'>)'\".-!&N-#&.E!(>)+&^)%%^%!&N%$%^!!&^!%%]]!" + "'-]&%]Y!&-Y!&-Y!'-U!(-Q!$MM!%]I!#=I!&]M!&M9%&ME$&M9%&]I%'-9'%]=!" + "%]5!$M=!)-1&%M-!&=!$#=!!%M%!%=!%%L]!'<]#$)#$=U%).%$'.-!&>)(" + "%^)!%^)!&.9!$^9!)>9%'.-%'.)%$N5%#>1!(N9!(N5!&.E!&^9$&.=!'NI''>9!" + "'N5()>1*$^=!&>9\"#N5!%N9$&.5!(N9!,>A,'>5!&.9!&.A!(N5!#N5!\"^1#\".1!" + "&>5\"&.A!%^%!%N1$(NA!(^-#$^%!'^)*)N%&#M]!)>%*&.-!\"N!\"(MU-%]]!%]Q!" + "&-Y!%]U!%]U!%]Q!%]Q!$MI!&MU$\"-I!(MQ($MI!$MQ!&]Q%%=A$%]5\"'-9'&M=$" + "$-1$&M-!%]5\"&-%$(])!%M)!&-!(&LU!%<]!%%\"&>%\"%^%!%.%\"" + "\".!!%^1!$^9!(N9!'>1'#>)!&N1#'.9&'.1!&N1#*.93%^)!$N1!%^1!'.1*'>5!" + "%^1!&N-$&.5!&>I!#N1!&.5!&^9$&.A!&.5!&.5!(N-'&.5!'>1''.1!).1)'.1!" + "%^-!%^)!%.1\"(N5,&N5))N!!&.5!$N%!%^%!&>%#(]]-'M])%]]!%]]!&-Y!(]Q(" + "&^%%%ME!(]I)$MY!'=]!'MA$%M1!%ME!(-A!%MA!&-9\"&-9\"'M1*%M9!%ME*$M5!" + "%M=!&]-&%<]!%M-!'=%)\"\\E$+-!+'LQ!#=!!%\\]\"&LU!#LQ#'%#&>)\"&^5%%^-!&>-\"%^-!&N-#'^!$(>1!'^-#'.)!\".1!" + "%^1!'NA''^)*'>5!&.5!%^1!&N)#'.1!$N1%%^)!$^5!&.9!\">E!$N-!-N-(&.5!" + "%^1!#^)\"'.)&&N-$'.-%%^)!%^1!(N!'\"-]!!.%!%]Q!&-]!$MY!)MI,$MY!%^!!" + "&-]\"#MA!$MM!%]M!%]M!&-I\"%]M!&=I$$MU!'-A\"'M=)&-9\"%]E!&-1,'=)($=-!" + "'M-$&M!&%M)!%]5\"#=%!%<]!(=%$%M!!%<]!%\\U#&LU!&LM*'<9!%!\"%^!!%.)\"$>-$)>!%%^-!(>!!'.)!#^%\"'.%!%^1!'>=!(^%(%^)!%^-!$^%!" + "(N%,%^%!&>1\"%^1!&N)$&.9!(>-!%^)!$N1!&N)#*^1!).1$%^-!#>-!&.)!(>)%" + "%^%!,>9'(^%#'-Y!).%$$.%#%^!!(>!!&-Y!%]]!(=U!%]Y!&MY$$]U&%^)!'.!&" + "&=I($MI!%]M!$ME!#=U!&]E!%M=!$MA!$-=$']5!%M9!'=Q\"%]5\"%M-!%M1!$]9\"" + "$])\"#=%!%<]!%!!%^)!(^%#'.%!$N)!%^-!%^)!'>-'%^-!&^)%$N-!&.5!" + "#>)!&.)'&.5!%^%!$N!!$N)!%^%!'^-$%^-!$N-!%^-!$N)!&N5(%]]!%]U!%^1!" + "%^)!'.%!'.!&*^!!'>!''.)!%]U!$]Q!&-Y!%M]%*.!)&]Y%'.%&%]Q!'-Q'%]I!" + "\"-I!#=E!%]A!$M=!$ME!%M9!%-A('M1)$-A$']9!*-5&%M5!#=)%\"-1!%--$%]%\"" + "'=)$%]%\"$=-!',]'&LQ&&\\Q&%M-!%\\U#$,M)%LM\"&LQ!%LQ!%,A$%)!$N%!'.%!&>-\"%^%!%^%!%^%!" + "%^1!%^-!&^!%'N='%^%!#^)\"(^))$N%!&N)#'.!!(>)!+>%)'.)%(N5!%-]\"%^-!" + "(N!(&>!#'-]!%]Q!)M]2'.!%%]Q!&MY$(=Y!%=Y)$]M!'=I((-Q!+-M('=M#(-M!" + "%]U!\"MQ\"(]E/%ME!%MA!%MA!%M=!(MA.%M1!&]5!$--$&--#%M)!'=%$%]-''--#" + "%\\Y\"%-5#%M!!%M!!'!'" + "%^1!%]Q!%^%!&MY)%^%!$N%!%^%!%^)!(^!#(.!%%]U!)MU'&.)!(.%%%]Y!%]Y!" + "&=]#(=]!%]]!%]Y!$M]!%]U!$]]!&=U#&]Q!%]Q!%]U!&=M$$MU!%]M!'=A#$MI!" + "\"-Y!$MI!&]M!&]E!$ME!&MA$$=9!&-E\"%M1!'=1#&-5#&=)$*M1'%M)!%]!\"%--$" + "$M!\"'L]!'<]$$,]$%<]!&)!%]U!%]U!%]U!&-Y!&.!'%]]!%]U!$MU!'-Y!(=]!%^!!%]]!$M]!'N)#%>)$" + "'N!)#>!!'^-#'-]!&>!#%^!!%^)!'>!\"&^!%'>!''.!!%]]!%]M!%=]$)-]%#=]!" + "%^!!)]]-%]]!'-Y&(-Q!!-]%&=I#%]Q!%]Q!'=Q(&=I#(-Q!#=I!&=M#']M)&]E!" + "%MA!(-E!&]9!&-9#&]9!%]E!%]1\"&-9#$]1\"%]-!'M-*$MI!%M%!(-)!&M-!%M%!" + "%\\]\"(L]%$-!$$)!%^!!$]]!#=Q!%]]!'-Q!%]Y!$MY!&]Y%'.!!&=Y#" + "'-U!%]M!%]U!%=Y$%]Q!$]Q'%]M!'=Y'&-M,&-M\"%ME!%-I#']A%#=I!$MI/&ME$" + "&MA$#=A!(=5,&=E#'-9'&]E!'-5''-=!!=1\"(M1$&])&%M)!'M%%$=%!%M!!'--#" + "#,]!%!\"']Q$%]I!(-Q!#=Q%" + "$MM!%]Q!$MQ!&MU%&]Q!'-]!#=E!%]M!&]Q!(-Q%$MY!&MI$(=M!%]I!#=]!&]E%" + "%]Q!\"-U!*>!4'=I(&]Q!$MA!%]M!)=A+%]5\"(-E!&=M$&-1#(=9-%-5(%]9!'==(" + "'=5#%]5\"%]1!*-1*%]%\"(]5$$=)!%]-\"#M%\"%M!!%M-!&L]!&LQ&(,],'-)'&LY!" + "'M%$%LE\"&\\Q'& b ? a : b; +} + +/* Create a new bubble. */ +void * +glb_bubble_new(glb_data *d, GLfloat x, GLfloat y, GLfloat z, GLfloat scale, + GLfloat y_incr, GLfloat scale_incr) +{ + int i, j; + + /* GLfloat axes [glb_config.nr_nudge_axes][3]; */ + GLfloat axes[5][3]; /* HARD CODED for SunCC */ + int nr_vertices; + glb_vertex *vertices = glb_sphere_get_vertices(d, &nr_vertices); + + bubble *b = (bubble *) malloc(sizeof *b); + + if (b == 0) + return 0; + + if (glb_config.bubble_colour[0] == -1.0) { + b->color[0] = ((float) (NRAND(100)) / 100.0); + b->color[1] = ((float) (NRAND(100)) / 100.0); + b->color[2] = ((float) (NRAND(100)) / 100.0); + } else { + b->color[0] = glb_config.bubble_colour[0]; + b->color[1] = glb_config.bubble_colour[1]; + b->color[2] = glb_config.bubble_colour[2]; + } + b->color[3] = glb_config.bubble_colour[3]; + + + b->contributions = (GLfloat *) malloc(sizeof (GLfloat) * nr_vertices * + glb_config.nr_nudge_axes); + if (b->contributions == 0) { + (void) free((void *) b); + return 0; + } + b->nudge_angle = (GLfloat *) malloc(sizeof (GLfloat) * glb_config.nr_nudge_axes); + if (b->nudge_angle == 0) { + (void) free((void *) b->contributions); + (void) free((void *) b); + return 0; + } + b->nudge_angle_incr = (GLfloat *) malloc(sizeof (GLfloat) * glb_config.nr_nudge_axes); + if (b->nudge_angle_incr == 0) { + (void) free((void *) b->nudge_angle); + (void) free((void *) b->contributions); + (void) free((void *) b); + return 0; + } + /* Initialize primitive elements. */ + b->x = x; + b->y = y; + b->z = z; + b->scale = scale; + b->y_incr = y_incr; + b->scale_incr = scale_incr; + b->rotx = b->roty = b->rotz = 0; + b->rotx_incr = glb_drand() * glb_config.rotation_factor * 2 + - glb_config.rotation_factor; + b->roty_incr = glb_drand() * glb_config.rotation_factor * 2 + - glb_config.rotation_factor; + b->rotz_incr = glb_drand() * glb_config.rotation_factor * 2 + - glb_config.rotation_factor; + + /* Initialize the nudge angle arrays. */ + for (i = 0; i < glb_config.nr_nudge_axes; ++i) { + b->nudge_angle[i] = 0; + b->nudge_angle_incr[i] = glb_drand() * glb_config.nudge_angle_factor; + } + + /* Choose some random nudge axes. */ + for (i = 0; i < glb_config.nr_nudge_axes; ++i) { + axes[i][0] = glb_drand() * 2 - 1; + axes[i][1] = glb_drand() * 2 - 1; + axes[i][2] = glb_drand() * 2 - 1; + normalize(axes[i]); + } + + /* Calculate the contribution that each nudge axis has on each vertex. */ + for (i = 0; i < nr_vertices; ++i) + for (j = 0; j < glb_config.nr_nudge_axes; ++j) + b->contributions[i * glb_config.nr_nudge_axes + j] + = max(0, dotprod(vertices[i], axes[j])); + + return (void *) b; +} + +/* Delete a bubble and free up all memory. */ +void +glb_bubble_delete(void *bb) +{ + bubble *b = (bubble *) bb; + + if (b != NULL) { + if (b->nudge_angle_incr) { + (void) free((void *) b->nudge_angle_incr); + b->nudge_angle_incr = NULL; + } + if (b->nudge_angle) { + (void) free((void *) b->nudge_angle); + b->nudge_angle = NULL; + } + if (b->contributions) { + (void) free((void *) b->contributions); + b->contributions = NULL; + } + (void) free((void *) b); + b = NULL; + } +} + +/* Rotate and wobble a bubble by a single step. */ +void +glb_bubble_step(void *bb) +{ + int i; + bubble *b = (bubble *) bb; + + /* Update the rotation. */ + b->rotx += b->rotx_incr; + b->roty += b->roty_incr; + b->rotz += b->rotz_incr; + + /* Update the nudge angles. */ + for (i = 0; i < glb_config.nr_nudge_axes; ++i) + b->nudge_angle[i] += b->nudge_angle_incr[i]; + + /* Move it upwards & outwards. */ + b->y += b->y_incr; + b->scale += b->scale_incr; +} + +/* Draw a bubble. */ +void +glb_bubble_draw(glb_data *d, void *bb) +{ + int i, j; + bubble *b = (bubble *) bb; + int nr_vertices; + glb_vertex *vertices = glb_sphere_get_vertices(d, &nr_vertices); + int nr_triangles; + glb_triangle *triangles = glb_sphere_get_triangles(d, &nr_triangles); + glb_vertex *new_vertices; + + new_vertices = (glb_vertex *) malloc(sizeof (glb_vertex) * nr_vertices); + /* Calculate the vertices of this bubble, factoring in each nudge axis. */ + for (i = 0; i < nr_vertices; ++i) { + GLfloat s = 0; + + for (j = 0; j < glb_config.nr_nudge_axes; ++j) + s += ((GLfloat) cos((double) (b->nudge_angle[j])) * + glb_config.nudge_factor - glb_config.nudge_factor / 2) * + b->contributions[i * glb_config.nr_nudge_axes + j]; + + new_vertices[i][0] = vertices[i][0] * (s + 1); + new_vertices[i][1] = vertices[i][1] * (s + 1); + new_vertices[i][2] = vertices[i][2] * (s + 1); + } + + glPushMatrix(); + + /* Apply translation, rotation and scalings. */ + glTranslatef(b->x, b->y, b->z); + + glRotatef(b->rotx, 1, 0, 0); + glRotatef(b->roty, 0, 1, 0); + glRotatef(b->rotz, 0, 0, 1); + + glScalef(b->scale, b->scale, b->scale); + + /* Draw the bubble. */ + glFrontFace(GL_CW); + glBegin(GL_TRIANGLES); + + glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, b->color); + + for (i = 0; i < nr_triangles; ++i) { + glNormal3fv(new_vertices[triangles[i][0]]); + glVertex3fv(new_vertices[triangles[i][0]]); + glNormal3fv(new_vertices[triangles[i][1]]); + glVertex3fv(new_vertices[triangles[i][1]]); + glNormal3fv(new_vertices[triangles[i][2]]); + glVertex3fv(new_vertices[triangles[i][2]]); + } + glEnd(); + glPopMatrix(); + (void) free((void *) new_vertices); + glb_config.polygon_count += nr_triangles; +} + +/* Return y value. */ +GLfloat +glb_bubble_get_y(void *bb) +{ + bubble *b = (bubble *) bb; + + return b->y; +} diff --git a/hacks/glx/bubble3d.h b/hacks/glx/bubble3d.h new file mode 100644 index 00000000..70919c34 --- /dev/null +++ b/hacks/glx/bubble3d.h @@ -0,0 +1,100 @@ +/* GLBUBBLES (C) 1998 Richard W.M. Jones. */ + +#ifndef __bubbles3d_h__ +#define __bubbles3d_h__ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif /* HAVE_CONFIG_H */ + +#ifdef STANDALONE +# include +# include "xlockmoreI.h" /* from the xscreensaver distribution */ +#else /* !STANDALONE */ +# include "xlock.h" /* from the xlockmore distribution */ +#endif /* !STANDALONE */ + +#ifndef HAVE_COCOA +# include +# include +#endif + +#ifdef HAVE_JWZGLES +# include "jwzgles.h" +#endif /* HAVE_JWZGLES */ + +/* Static configuration. */ +#define GLB_SLOW_GL 0 /* Set this if you have a slow GL + * implementation. If you have an accelerated + * graphics card, set this to 0. + */ +#define GLB_VERTICES_EPSILON 0.0005 /* How close are identical vertices? */ + +/* Configuration structure. */ +struct glb_config { + int transparent_p; /* Whether to use alpha blending */ + + int subdivision_depth; /* Controls how many triangles are in + * each bubble. 2 and 3 are good values. + */ + int nr_nudge_axes; /* Number of directions in which each + * bubble gets stretched. Values between + * 3 and 7 seem to produce good results. + */ + GLfloat nudge_angle_factor; /* Max. amount of rotation in nudge angles. + * Controls the amount of `wobble' we see, + * and 0.3 seems to work well. + */ + GLfloat nudge_factor; /* Max. displacement of any single nudge. + * Controls the amount of the wobble. Depends + * on NR_NUDGE_AXES, and must not exceed + * 1 / NR_NUDGE_AXES. 0.1 is good. + */ + GLfloat rotation_factor; /* Max. amount by which bubbles rotate. */ + int create_bubbles_every; /* How often to create new bubbles. */ + int max_bubbles; /* Max. number of bubbles to create. */ + double p_bubble_group[4]; /* Probabilities of creating 1, 2, 3, 4 + * bubbles in a group. Cumulative. + */ + GLfloat max_size; /* Max. size. */ + GLfloat min_size; /* Min. size of bubbles. */ + GLfloat max_speed; /* Max. speed. */ + GLfloat min_speed; /* Min. speed of bubbles. */ + GLfloat scale_factor; /* Factor by which bubbles scale from bottom + * of screen to top. 1.5 - 2.0 are OK. + */ + GLfloat screen_bottom; /* Bottom of screen. */ + GLfloat screen_top; /* Top of screen. */ + GLfloat bubble_colour[4]; /* Colour of the bubbles. */ + + int polygon_count; +}; + +extern struct glb_config glb_config; + +#define glb_drand() ((double)LRAND() / (double)MAXRAND) + +/*-- From glb_sphere.c. --*/ +typedef struct glb_data glb_data; +typedef GLfloat glb_vertex[3]; +typedef GLuint glb_triangle[3]; +extern glb_data * glb_sphere_init(void); +extern glb_vertex *glb_sphere_get_vertices(glb_data *, int *nr_vertices); +extern glb_triangle *glb_sphere_get_triangles(glb_data *, int *nr_triangles); +extern void glb_sphere_end(glb_data *); + +/*-- From glb_bubble.c. --*/ +extern void *glb_bubble_new(glb_data *d, + GLfloat x, GLfloat y, GLfloat z, GLfloat scale, + GLfloat y_incr, GLfloat scale_incr); +extern void glb_bubble_delete(void *); +extern void glb_bubble_step(void *); +extern void glb_bubble_draw(glb_data *d, void *); +extern GLfloat glb_bubble_get_y(void *); + +/*-- From glb_draw.c. --*/ +extern void *glb_draw_init(void); +extern void glb_draw_step(void *); +extern void glb_draw_end(void *); + +#endif /* __bubbles3d_h__ */ diff --git a/hacks/glx/bubble3d.man b/hacks/glx/bubble3d.man new file mode 100644 index 00000000..f847e12d --- /dev/null +++ b/hacks/glx/bubble3d.man @@ -0,0 +1,62 @@ +.TH XScreenSaver 1 "" "X Version 11" +.SH NAME +bubble3d - 3d rising bubbles. +.SH SYNOPSIS +.B bubble3d +[\-display \fIhost:display.screen\fP] +[\-visual \fIvisual\fP] +[\-window] +[\-root] +[\-delay \fInumber\fP] +[\-transparent] +[\-color \fIcolor\fP] +[\-fps] +.SH DESCRIPTION +Draws a stream of rising, undulating 3D bubbles, rising toward the top of +the screen, with nice specular reflections. +.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 \-transparent +Draw transparent bubbles instead of solid ones. +.TP 8 +.B \-color \fIcolor\fP +Draw bubbles of the specified color. "Random" means a different color +for each bubble. +.TP 8 +.B \-delay \fInumber\fP +Per-frame delay, in microseconds. Default: 15000 (0.015 seconds.). +.TP 8 +.B \-fps +Display the current frame rate, CPU load, and polygon count. +.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 2002 by Richard Jones. 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 +Richard Jones. diff --git a/hacks/glx/buildlwo.c b/hacks/glx/buildlwo.c new file mode 100644 index 00000000..c20c9e2d --- /dev/null +++ b/hacks/glx/buildlwo.c @@ -0,0 +1,96 @@ + +#if 0 +static const char sccsid[] = "@(#)buildlwo.c 4.02 97/04/20 xlockmore"; +#endif + +/*- + * buildlwo.c: Lightwave Object Display List Builder for OpenGL + * + * This module can be called by any GL mode wishing to use + * objects created in NewTek's Lightwave 3D. The objects must + * first be converted to C source with my converter "lw2ogl". + * If other people are interested in this, I will put up a + * web page for it at http://www.netaxs.com/~emackey/lw2ogl/ + * + * by Ed Mackey, 4/19/97 + * + */ + +#ifndef STANDALONE +#include "xlock.h" +#endif + +#ifdef USE_GL + +#include "buildlwo.h" + +GLuint +BuildLWO(int wireframe, const struct lwo *object) +{ + GLuint dl_num; + const GLfloat *pnts, *normals, *grab; + const unsigned short int *pols; + GLfloat three[3]; + int p, num_pnts = 0; + + dl_num = glGenLists(1); + if (!dl_num) + return (0); + + pnts = object->pnts; + normals = object->normals; + pols = object->pols; + + glNewList(dl_num, GL_COMPILE); + + if (!pols) { + num_pnts = object->num_pnts; + glBegin(GL_POINTS); + for (p = 0; p < num_pnts; ++p) { + three[0] = *(pnts++); + three[1] = *(pnts++); + three[2] = *(pnts++); + glVertex3fv(three); + } + glEnd(); + } else + for (;;) { + if (num_pnts <= 0) { + num_pnts = *pols + 2; + if (num_pnts < 3) + break; + if (num_pnts == 3) { + glBegin(GL_POINTS); + } else if (num_pnts == 4) { + glBegin(GL_LINES); + } else { + three[0] = *(normals++); + three[1] = *(normals++); + three[2] = *(normals++); + glNormal3fv(three); + if (wireframe) + glBegin(GL_LINE_LOOP); + else + glBegin(GL_POLYGON); + } + } else if (num_pnts == 1) { + glEnd(); + } else { + grab = pnts + ((int) (*pols) * 3); + three[0] = *(grab++); + three[1] = *(grab++); + three[2] = *(grab); + glVertex3fv(three); + } + --num_pnts; + ++pols; + } + + glEndList(); + + return (dl_num); +} + +#endif /* USE_GL */ + +/* End of buildlwo.c */ diff --git a/hacks/glx/buildlwo.h b/hacks/glx/buildlwo.h new file mode 100644 index 00000000..4b900818 --- /dev/null +++ b/hacks/glx/buildlwo.h @@ -0,0 +1,38 @@ +/*- + * buildlwo.h: Header file for Lightwave Object Display List Builder + * for OpenGL + * + * by Ed Mackey, 4/19/97 + * + */ + +#ifndef __BUILD_LWO_H__ +#define __BUILD_LWO_H__ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif /* HAVE_CONFIG_H */ + +#ifdef STANDALONE +# ifndef HAVE_COCOA +# include +# endif +#endif + +#ifdef HAVE_JWZGLES +# include "jwzgles.h" +#endif /* HAVE_JWZGLES */ + +struct lwo { + int num_pnts; + const GLfloat *pnts; + const GLfloat *normals; + const unsigned short int *pols; + const GLfloat *smoothnormals; +}; + +GLuint BuildLWO(int wireframe, const struct lwo *object); + +#endif + +/* End of buildlwo.h */ diff --git a/hacks/glx/cage.c b/hacks/glx/cage.c new file mode 100644 index 00000000..bcd382b6 --- /dev/null +++ b/hacks/glx/cage.c @@ -0,0 +1,489 @@ +/* -*- Mode: C; tab-width: 4 -*- */ +/* cage --- the Impossible Cage, an Escher like scene. */ + +#if 0 +static const char sccsid[] = "@(#)cage.c 5.01 2001/03/01 xlockmore"; +#endif + +/*- + * Permission to use, copy, modify, and distribute this software and its + * documentation for any purpose and without fee is hereby granted, + * provided that the above copyright notice appear in all copies and that + * both that copyright notice and this permission notice appear in + * supporting documentation. + * + * This file is provided AS IS with no warranties of any kind. The author + * shall have no liability with respect to the infringement of copyrights, + * trade secrets or any patents by this file or any part thereof. In no + * event will the author be liable for any lost revenue or profits or + * other special, indirect and consequential damages. + * + * The RotateAroundU() routine was adapted from the book + * "Computer Graphics Principles and Practice + * Foley - vanDam - Feiner - Hughes + * Second Edition" Pag. 227, exercise 5.15. + * + * This mode shows some interesting scenes that are impossible OR very + * wierd to build in the real universe. Much of the scenes are inspirated + * on Mauritz Cornelis Escher's works which derivated the mode's name. + * M.C. Escher (1898-1972) was a dutch artist and many people prefer to + * say he was a mathematician. + * + * Thanks goes to Brian Paul for making it possible and inexpensive to use + * OpenGL at home. + * + * Since I'm not a native English speaker, my apologies for any grammatical + * mistakes. + * + * My e-mail address is + * mfvianna@centroin.com.br + * + * Marcelo F. Vianna (Jun-01-1997) + * + * Revision History: + * 05-Apr-2002: Removed all gllist uses (fix some bug with nvidia driver) + * 01-Mar-2001: Added FPS stuff E.Lassauge + * 01-Nov-2000: Allocation checks + * 01-Jan-1998: Mode separated from escher and renamed + * 08-Jun-1997: New scene implemented: "Impossible Cage" based in a M.C. + * Escher's painting with the same name (quite similar). The + * first GL mode to use texture mapping. + * The "Impossible Cage" scene doesn't use DEPTH BUFFER, the + * wood planks are drawn consistently using GL_CULL_FACE, and + * the painter's algorithm is used to sort the planks. + * Marcelo F. Vianna. + * 07-Jun-1997: Speed ups in Moebius Strip using GL_CULL_FACE. + * Marcelo F. Vianna. + * 03-Jun-1997: Initial Release (Only one scene: "Moebius Strip") + * The Moebius Strip scene was inspirated in a M.C. Escher's + * painting named Moebius Strip II in wich ants walk across a + * Moebius Strip path, sometimes meeting each other and sometimes + * being in "opposite faces" (note that the moebius strip has + * only one face and one edge). + * Marcelo F. Vianna. + */ + +/*- + * Texture mapping is only available on RGBA contexts, Mono and color index + * visuals DO NOT support texture mapping in OpenGL. + * + * BUT Mesa do implements RGBA contexts in pseudo color visuals, so texture + * mapping shuld work on PseudoColor, DirectColor, TrueColor using Mesa. Mono + * is not officially supported for both OpenGL and Mesa, but seems to not crash + * Mesa. + * + * In real OpenGL, PseudoColor DO NOT support texture map (as far as I know). + */ + +#ifdef STANDALONE +# define MODE_cage +# define DEFAULTS "*delay: 25000 \n" \ + "*showFPS: False \n" \ + "*wireframe: False \n" + +# define refresh_cage 0 +# define reshape_cage 0 +# define cage_handle_event 0 +# include "xlockmore.h" /* from the xscreensaver distribution */ +#else /* !STANDALONE */ +# include "xlock.h" /* from the xlockmore distribution */ +#endif /* !STANDALONE */ + +#ifdef MODE_cage + +#if 0 +#include "e_textures.h" +#else +#include "xpm-ximage.h" +#include "../images/wood.xpm" +#endif + +ENTRYPOINT ModeSpecOpt cage_opts = +{0, (XrmOptionDescRec *) NULL, 0, (argtype *) NULL, (OptionStruct *) NULL}; + +#ifdef USE_MODULES +ModStruct cage_description = +{"cage", "init_cage", "draw_cage", "release_cage", + "draw_cage", "change_cage", (char *) NULL, &cage_opts, + 25000, 1, 1, 1, 1.0, 4, "", + "Shows the Impossible Cage, an Escher-like GL scene", 0, NULL}; + +#endif + +#define Scale4Window 0.3 +#define Scale4Iconic 0.4 + +#define sqr(A) ((A)*(A)) + +#ifndef Pi +#define Pi M_PI +#endif + +#define ObjWoodPlank 0 +#define MaxObj 1 + +/*************************************************************************/ + +typedef struct { + GLint WindH, WindW; + GLfloat step; + GLXContext *glx_context; +} cagestruct; + +static const float front_shininess[] = {60.0}; +static const float front_specular[] = {0.7, 0.7, 0.7, 1.0}; +static const float ambient[] = {0.0, 0.0, 0.0, 1.0}; +static const float diffuse[] = {1.0, 1.0, 1.0, 1.0}; +static const float position0[] = {1.0, 1.0, 1.0, 0.0}; +static const float position1[] = {-1.0, -1.0, 1.0, 0.0}; +static const float lmodel_ambient[] = {0.5, 0.5, 0.5, 1.0}; +static const float lmodel_twoside[] = {GL_TRUE}; + +static const float MaterialWhite[] = {0.7, 0.7, 0.7, 1.0}; + +static cagestruct *cage = (cagestruct *) NULL; + +#define PlankWidth 3.0 +#define PlankHeight 0.35 +#define PlankThickness 0.15 + +static Bool +draw_woodplank(ModeInfo *mi, cagestruct * cp, int wire) +{ + glBegin(wire ? GL_LINES : GL_QUADS); + glNormal3f(0, 0, 1); + glTexCoord2f(0, 0); + glVertex3f(-PlankWidth, -PlankHeight, PlankThickness); + glTexCoord2f(1, 0); + glVertex3f(PlankWidth, -PlankHeight, PlankThickness); + glTexCoord2f(1, 1); + glVertex3f(PlankWidth, PlankHeight, PlankThickness); + glTexCoord2f(0, 1); + glVertex3f(-PlankWidth, PlankHeight, PlankThickness); + mi->polygon_count++; + glNormal3f(0, 0, -1); + glTexCoord2f(0, 0); + glVertex3f(-PlankWidth, PlankHeight, -PlankThickness); + glTexCoord2f(1, 0); + glVertex3f(PlankWidth, PlankHeight, -PlankThickness); + glTexCoord2f(1, 1); + glVertex3f(PlankWidth, -PlankHeight, -PlankThickness); + glTexCoord2f(0, 1); + glVertex3f(-PlankWidth, -PlankHeight, -PlankThickness); + mi->polygon_count++; + glNormal3f(0, 1, 0); + glTexCoord2f(0, 0); + glVertex3f(-PlankWidth, PlankHeight, PlankThickness); + glTexCoord2f(1, 0); + glVertex3f(PlankWidth, PlankHeight, PlankThickness); + glTexCoord2f(1, 1); + glVertex3f(PlankWidth, PlankHeight, -PlankThickness); + glTexCoord2f(0, 1); + glVertex3f(-PlankWidth, PlankHeight, -PlankThickness); + mi->polygon_count++; + glNormal3f(0, -1, 0); + glTexCoord2f(0, 0); + glVertex3f(-PlankWidth, -PlankHeight, -PlankThickness); + glTexCoord2f(1, 0); + glVertex3f(PlankWidth, -PlankHeight, -PlankThickness); + glTexCoord2f(1, 1); + glVertex3f(PlankWidth, -PlankHeight, PlankThickness); + glTexCoord2f(0, 1); + glVertex3f(-PlankWidth, -PlankHeight, PlankThickness); + mi->polygon_count++; + glNormal3f(1, 0, 0); + glTexCoord2f(0, 0); + glVertex3f(PlankWidth, -PlankHeight, PlankThickness); + glTexCoord2f(1, 0); + glVertex3f(PlankWidth, -PlankHeight, -PlankThickness); + glTexCoord2f(1, 1); + glVertex3f(PlankWidth, PlankHeight, -PlankThickness); + glTexCoord2f(0, 1); + glVertex3f(PlankWidth, PlankHeight, PlankThickness); + mi->polygon_count++; + glNormal3f(-1, 0, 0); + glTexCoord2f(0, 0); + glVertex3f(-PlankWidth, PlankHeight, PlankThickness); + glTexCoord2f(1, 0); + glVertex3f(-PlankWidth, PlankHeight, -PlankThickness); + glTexCoord2f(1, 1); + glVertex3f(-PlankWidth, -PlankHeight, -PlankThickness); + glTexCoord2f(0, 1); + glVertex3f(-PlankWidth, -PlankHeight, PlankThickness); + mi->polygon_count++; + glEnd(); + + return True; +} + +static Bool +draw_impossiblecage(ModeInfo *mi, cagestruct * cp, int wire) +{ + glPushMatrix(); + glRotatef(90, 0, 1, 0); + glTranslatef(0.0, PlankHeight - PlankWidth, -PlankThickness - PlankWidth); + if (!draw_woodplank(mi, cp, wire)) + return False; + glPopMatrix(); + glPushMatrix(); + glRotatef(90, 0, 0, 1); + glTranslatef(0.0, PlankHeight - PlankWidth, PlankWidth - PlankThickness); + if (!draw_woodplank(mi, cp, wire)) + return False; + glPopMatrix(); + glPushMatrix(); + glRotatef(90, 0, 1, 0); + glTranslatef(0.0, PlankWidth - PlankHeight, -PlankThickness - PlankWidth); + if (!draw_woodplank(mi, cp, wire)) + return False; + glPopMatrix(); + glPushMatrix(); + glTranslatef(0.0, PlankWidth - PlankHeight, 3 * PlankThickness - PlankWidth); + if (!draw_woodplank(mi, cp, wire)) + return False; + glPopMatrix(); + glPushMatrix(); + glRotatef(90, 0, 0, 1); + glTranslatef(0.0, PlankWidth - PlankHeight, PlankWidth - PlankThickness); + if (!draw_woodplank(mi, cp, wire)) + return False; + glPopMatrix(); + glPushMatrix(); + glTranslatef(0.0, PlankWidth - PlankHeight, PlankWidth - 3 * PlankThickness); + if (!draw_woodplank(mi, cp, wire)) + return False; + glPopMatrix(); + glPushMatrix(); + glTranslatef(0.0, PlankHeight - PlankWidth, 3 * PlankThickness - PlankWidth); + if (!draw_woodplank(mi, cp, wire)) + return False; + glPopMatrix(); + glPushMatrix(); + glRotatef(90, 0, 0, 1); + glTranslatef(0.0, PlankHeight - PlankWidth, PlankThickness - PlankWidth); + if (!draw_woodplank(mi, cp, wire)) + return False; + glPopMatrix(); + glPushMatrix(); + glTranslatef(0.0, PlankHeight - PlankWidth, PlankWidth - 3 * PlankThickness); + if (!draw_woodplank(mi, cp, wire)) + return False; + glPopMatrix(); + glPushMatrix(); + glRotatef(90, 0, 1, 0); + glTranslatef(0.0, PlankHeight - PlankWidth, PlankWidth + PlankThickness); + if (!draw_woodplank(mi, cp, wire)) + return False; + glPopMatrix(); + glPushMatrix(); + glRotatef(90, 0, 0, 1); + glTranslatef(0.0, PlankWidth - PlankHeight, PlankThickness - PlankWidth); + if (!draw_woodplank(mi, cp, wire)) + return False; + glPopMatrix(); + glPushMatrix(); + glRotatef(90, 0, 1, 0); + glTranslatef(0.0, PlankWidth - PlankHeight, PlankWidth + PlankThickness); + if (!draw_woodplank(mi, cp, wire)) + return False; + glPopMatrix(); + return True; +} + +static void +reshape(ModeInfo * mi, int width, int height) +{ + cagestruct *cp = &cage[MI_SCREEN(mi)]; + int i; + + glViewport(0, 0, cp->WindW = (GLint) width, cp->WindH = (GLint) height); + glMatrixMode(GL_PROJECTION); + glLoadIdentity(); + glFrustum(-1.0, 1.0, -1.0, 1.0, 5.0, 15.0); + glMatrixMode(GL_MODELVIEW); + i = width / 512 + 1; + glLineWidth(i); + glPointSize(i); +} + +static void +pinit(ModeInfo *mi) +{ + /* int status; */ + + if (MI_IS_WIREFRAME(mi)) + return; + + glLightfv(GL_LIGHT0, GL_AMBIENT, ambient); + glLightfv(GL_LIGHT0, GL_DIFFUSE, diffuse); + glLightfv(GL_LIGHT0, GL_POSITION, position0); + glLightfv(GL_LIGHT1, GL_AMBIENT, ambient); + glLightfv(GL_LIGHT1, GL_DIFFUSE, diffuse); + glLightfv(GL_LIGHT1, GL_POSITION, position1); + glLightModelfv(GL_LIGHT_MODEL_AMBIENT, lmodel_ambient); + glLightModelfv(GL_LIGHT_MODEL_TWO_SIDE, lmodel_twoside); + glEnable(GL_LIGHTING); + glEnable(GL_LIGHT0); + glEnable(GL_LIGHT1); + glEnable(GL_NORMALIZE); + glFrontFace(GL_CCW); + glCullFace(GL_BACK); + + /* cage */ + glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, MaterialWhite); + glShadeModel(GL_FLAT); + glDisable(GL_DEPTH_TEST); + glEnable(GL_TEXTURE_2D); + glEnable(GL_CULL_FACE); + + glPixelStorei(GL_UNPACK_ALIGNMENT, 1); + +#if 0 + clear_gl_error(); + if (MI_IS_MONO(mi)) + status = 0; + else + status = gluBuild2DMipmaps(GL_TEXTURE_2D, 3, + WoodTextureWidth, WoodTextureHeight, + GL_RGB, GL_UNSIGNED_BYTE, WoodTextureData); + if (status) + { + const char *s = (char *) gluErrorString (status); + fprintf (stderr, "%s: error mipmapping texture: %s\n", + progname, (s ? s : "(unknown)")); + exit (1); + } + check_gl_error("mipmapping"); +#else + { + XImage *img = xpm_to_ximage (mi->dpy, + mi->xgwa.visual, + mi->xgwa.colormap, + wood_texture); + glTexImage2D (GL_TEXTURE_2D, 0, GL_RGBA, + img->width, img->height, 0, + GL_RGBA, + /* GL_UNSIGNED_BYTE, */ + GL_UNSIGNED_INT_8_8_8_8_REV, + img->data); + check_gl_error("texture"); + XDestroyImage (img); + } +#endif + + 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_NEAREST); + glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + + glMaterialfv(GL_FRONT_AND_BACK, GL_SHININESS, front_shininess); + glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, front_specular); +} + +ENTRYPOINT void +release_cage (ModeInfo * mi) +{ + if (cage != NULL) { + int screen; + + for (screen = 0; screen < MI_NUM_SCREENS(mi); screen++) { + cagestruct *cp = &cage[screen]; + + if (cp->glx_context) { + cp->glx_context = (GLXContext *) NULL; + } + } + (void) free((void *) cage); + cage = (cagestruct *) NULL; + } + FreeAllGL(mi); +} + +ENTRYPOINT void +init_cage (ModeInfo * mi) +{ + cagestruct *cp; + + if (cage == NULL) { + if ((cage = (cagestruct *) calloc(MI_NUM_SCREENS(mi), + sizeof (cagestruct))) == NULL) + return; + } + cp = &cage[MI_SCREEN(mi)]; + + cp->step = NRAND(90); + if ((cp->glx_context = init_GL(mi)) != NULL) { + + reshape(mi, MI_WIDTH(mi), MI_HEIGHT(mi)); + glDrawBuffer(GL_BACK); + pinit(mi); + } else { + MI_CLEARWINDOW(mi); + } +} + +ENTRYPOINT void +draw_cage (ModeInfo * mi) +{ + Display *display = MI_DISPLAY(mi); + Window window = MI_WINDOW(mi); + cagestruct *cp; + + if (cage == NULL) + return; + cp = &cage[MI_SCREEN(mi)]; + + MI_IS_DRAWN(mi) = True; + if (!cp->glx_context) + return; + + mi->polygon_count = 0; + glXMakeCurrent(display, window, *(cp->glx_context)); + + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + + glPushMatrix(); + glTranslatef(0.0, 0.0, -10.0); + + if (!MI_IS_ICONIC(mi)) { + glScalef(Scale4Window * cp->WindH / cp->WindW, Scale4Window, Scale4Window); + } else { + glScalef(Scale4Iconic * cp->WindH / cp->WindW, Scale4Iconic, Scale4Iconic); + } + + /* cage */ + glRotatef(cp->step * 100, 0, 0, 1); + glRotatef(25 + cos(cp->step * 5) * 6, 1, 0, 0); + glRotatef(204.5 - sin(cp->step * 5) * 8, 0, 1, 0); + if (!draw_impossiblecage(mi, cp, MI_IS_WIREFRAME(mi))) { + release_cage(mi); + return; + } + + glPopMatrix(); + if (MI_IS_FPS(mi)) do_fps (mi); + glFlush(); + + glXSwapBuffers(display, window); + + cp->step += 0.025; +} + +#ifndef STANDALONE +ENTRYPOINT void +change_cage (ModeInfo * mi) +{ + cagestruct *cp = &cage[MI_SCREEN(mi)]; + + if (!cp->glx_context) + return; + + glXMakeCurrent(MI_DISPLAY(mi), MI_WINDOW(mi), *(cp->glx_context)); + pinit(mi); +} +#endif /* !STANDALONE */ + +XSCREENSAVER_MODULE ("Cage", cage) + +#endif diff --git a/hacks/glx/cage.man b/hacks/glx/cage.man new file mode 100644 index 00000000..dc5595b9 --- /dev/null +++ b/hacks/glx/cage.man @@ -0,0 +1,61 @@ +.TH XScreenSaver 1 "" "X Version 11" +.SH NAME +cage - Escher's impossible cage, for xscreensaver. +.SH SYNOPSIS +.B cage +[\-display \fIhost:display.screen\fP] +[\-visual \fIvisual\fP] +[\-window] +[\-root] +[\-delay \fInumber\fP] +[\-mono] +[\-wireframe] +[\-fps] +.SH DESCRIPTION +This draws Escher's "Impossible Cage", a 3d analog of a moebius strip, +and rotates it in three dimensions. +.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: 25000 (0.03 seconds.). +.TP 8 +.B \-mono +Render solid instead of textured. +.TP 8 +.B \-wireframe +Render in wireframe instead of textured. +.TP 8 +.B \-fps +Display the current frame rate, CPU load, and polygon count. +.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 2002 by Marcelo Vianna. 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 +Marcelo Vianna. diff --git a/hacks/glx/carousel.c b/hacks/glx/carousel.c new file mode 100644 index 00000000..49abc581 --- /dev/null +++ b/hacks/glx/carousel.c @@ -0,0 +1,916 @@ +/* carousel, Copyright (c) 2005-2012 Jamie Zawinski + * Loads a sequence of images and rotates them around. + * + * 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. + * + * Created: 21-Feb-2005 + */ + +#define DEF_FONT "-*-helvetica-bold-r-normal-*-240-*" +#define DEFAULTS "*count: 7 \n" \ + "*delay: 10000 \n" \ + "*wireframe: False \n" \ + "*showFPS: False \n" \ + "*fpsSolid: True \n" \ + "*useSHM: True \n" \ + "*font: " DEF_FONT "\n" \ + "*desktopGrabber: xscreensaver-getimage -no-desktop %s\n" \ + "*grabDesktopImages: False \n" \ + "*chooseRandomImages: True \n" + +# define refresh_carousel 0 +# define release_carousel 0 +# include "xlockmore.h" + +#undef countof +#define countof(x) (sizeof((x))/sizeof((*x))) + +#ifdef USE_GL + +# define DEF_SPEED "1.0" +# define DEF_DURATION "20" +# define DEF_TITLES "True" +# define DEF_ZOOM "True" +# define DEF_TILT "XY" +# define DEF_MIPMAP "True" +# define DEF_DEBUG "False" + +#include "rotator.h" +#include "gltrackball.h" +#include "grab-ximage.h" +#include "texfont.h" + +# ifndef HAVE_COCOA +# include /* for XrmDatabase in -debug mode */ +# endif + +/* Should be in */ +# ifndef GL_TEXTURE_MAX_ANISOTROPY_EXT +# define GL_TEXTURE_MAX_ANISOTROPY_EXT 0x84FE +# endif +# ifndef GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT +# define GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT 0x84FF +# endif + +typedef struct { + double x, y, w, h; +} rect; + +typedef enum { EARLY, NORMAL, LOADING, OUT, IN, DEAD } fade_mode; +static int fade_ticks = 60; + +typedef struct { + char *title; /* the filename of this image */ + int w, h; /* size in pixels of the image */ + int tw, th; /* size in pixels of the texture */ + XRectangle geom; /* where in the image the bits are */ + GLuint texid; +} image; + +typedef struct { + ModeInfo *mi; + image current, loading; + GLfloat r, theta; /* radius and rotation on the tube */ + rotator *rot; /* for zoomery */ + Bool from_top_p; /* whether this image drops in or rises up */ + time_t expires; /* when this image should be replaced */ + fade_mode mode; /* in/out animation state */ + int mode_tick; + Bool loaded_p; /* whether background load is done */ +} image_frame; + + +typedef struct { + GLXContext *glx_context; + GLfloat anisotropic; + rotator *rot; + trackball_state *trackball; + Bool button_down_p; + time_t button_down_time; + + int nframes; /* how many frames are loaded */ + int frames_size; + image_frame **frames; /* pointers to the frames */ + + Bool awaiting_first_images_p; + int loads_in_progress; + + texture_font_data *texfont; + + fade_mode mode; + int mode_tick; + + int loading_sw, loading_sh; + + time_t last_time, now; + int draw_tick; + +} carousel_state; + +static carousel_state *sss = NULL; + + +/* Command-line arguments + */ +static GLfloat speed; /* animation speed scale factor */ +static int duration; /* reload images after this long */ +static Bool mipmap_p; /* Use mipmaps instead of single textures. */ +static Bool titles_p; /* Display image titles. */ +static Bool zoom_p; /* Throb the images in and out as they spin. */ +static char *tilt_str; +static Bool tilt_x_p; /* Tilt axis towards the viewer */ +static Bool tilt_y_p; /* Tilt axis side to side */ +static Bool debug_p; /* Be loud and do weird things. */ + + +static XrmOptionDescRec opts[] = { + {"-zoom", ".zoom", XrmoptionNoArg, "True" }, + {"-no-zoom", ".zoom", XrmoptionNoArg, "False" }, + {"-tilt", ".tilt", XrmoptionSepArg, 0 }, + {"-no-tilt", ".tilt", XrmoptionNoArg, "" }, + {"-titles", ".titles", XrmoptionNoArg, "True" }, + {"-no-titles", ".titles", XrmoptionNoArg, "False" }, + {"-mipmaps", ".mipmap", XrmoptionNoArg, "True" }, + {"-no-mipmaps", ".mipmap", XrmoptionNoArg, "False" }, + {"-duration", ".duration", XrmoptionSepArg, 0 }, + {"-debug", ".debug", XrmoptionNoArg, "True" }, + {"-font", ".font", XrmoptionSepArg, 0 }, + {"-speed", ".speed", XrmoptionSepArg, 0 }, +}; + +static argtype vars[] = { + { &mipmap_p, "mipmap", "Mipmap", DEF_MIPMAP, t_Bool}, + { &debug_p, "debug", "Debug", DEF_DEBUG, t_Bool}, + { &titles_p, "titles", "Titles", DEF_TITLES, t_Bool}, + { &zoom_p, "zoom", "Zoom", DEF_ZOOM, t_Bool}, + { &tilt_str, "tilt", "Tilt", DEF_TILT, t_String}, + { &speed, "speed", "Speed", DEF_SPEED, t_Float}, + { &duration, "duration", "Duration", DEF_DURATION, t_Int}, +}; + +ENTRYPOINT ModeSpecOpt carousel_opts = {countof(opts), opts, countof(vars), vars, NULL}; + + +/* Allocates a frame structure and stores it in the list. + */ +static image_frame * +alloc_frame (ModeInfo *mi) +{ + carousel_state *ss = &sss[MI_SCREEN(mi)]; + image_frame *frame = (image_frame *) calloc (1, sizeof (*frame)); + + frame->mi = mi; + frame->mode = EARLY; + frame->rot = make_rotator (0, 0, 0, 0, 0.04 * frand(1.0) * speed, False); + + glGenTextures (1, &frame->current.texid); + glGenTextures (1, &frame->loading.texid); + if (frame->current.texid <= 0) abort(); + if (frame->loading.texid <= 0) abort(); + + if (ss->frames_size <= ss->nframes) + { + ss->frames_size = (ss->frames_size * 1.2) + ss->nframes; + ss->frames = (image_frame **) + realloc (ss->frames, ss->frames_size * sizeof(*ss->frames)); + if (! ss->frames) + { + fprintf (stderr, "%s: out of memory (%d images)\n", + progname, ss->frames_size); + exit (1); + } + } + + ss->frames[ss->nframes++] = frame; + + return frame; +} + + +static void image_loaded_cb (const char *filename, XRectangle *geom, + int image_width, int image_height, + int texture_width, int texture_height, + void *closure); + + +/* Load a new file into the given image struct. + */ +static void +load_image (ModeInfo *mi, image_frame *frame) +{ + carousel_state *ss = &sss[MI_SCREEN(mi)]; + int wire = MI_IS_WIREFRAME(mi); + + if (debug_p && !wire && frame->current.w != 0) + fprintf (stderr, "%s: dropped %4d x %-4d %4d x %-4d \"%s\"\n", + progname, + frame->current.geom.width, + frame->current.geom.height, + frame->current.tw, frame->current.th, + (frame->current.title ? frame->current.title : "(null)")); + + switch (frame->mode) + { + case EARLY: break; + case NORMAL: frame->mode = LOADING; break; + default: abort(); + } + + ss->loads_in_progress++; + + if (wire) + image_loaded_cb (0, 0, 0, 0, 0, 0, frame); + else + { + int w = (MI_WIDTH(mi) / 2) - 1; + int h = (MI_HEIGHT(mi) / 2) - 1; + if (w <= 10) w = 10; + if (h <= 10) h = 10; + load_texture_async (mi->xgwa.screen, mi->window, *ss->glx_context, w, h, + mipmap_p, frame->loading.texid, + image_loaded_cb, frame); + } +} + + +/* Callback that tells us that the texture has been loaded. + */ +static void +image_loaded_cb (const char *filename, XRectangle *geom, + int image_width, int image_height, + int texture_width, int texture_height, + void *closure) +{ + image_frame *frame = (image_frame *) closure; + ModeInfo *mi = frame->mi; + carousel_state *ss = &sss[MI_SCREEN(mi)]; + int wire = MI_IS_WIREFRAME(mi); + + if (wire) + { + frame->loading.w = MI_WIDTH (mi) * (0.5 + frand (1.0)); + frame->loading.h = MI_HEIGHT (mi); + frame->loading.geom.width = frame->loading.w; + frame->loading.geom.height = frame->loading.h; + goto DONE; + } + + if (image_width == 0 || image_height == 0) + exit (1); + + glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, + mipmap_p ? GL_LINEAR_MIPMAP_LINEAR : GL_LINEAR); + + if (ss->anisotropic >= 1.0) + glTexParameterf (GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, + ss->anisotropic); + + glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); + glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); + + frame->loading.w = image_width; + frame->loading.h = image_height; + frame->loading.tw = texture_width; + frame->loading.th = texture_height; + frame->loading.geom = *geom; + + if (frame->loading.title) + free (frame->loading.title); + frame->loading.title = (filename ? strdup (filename) : 0); + + /* xscreensaver-getimage returns paths relative to the image directory + now, so leave the sub-directory part in. Unless it's an absolute path. + */ + if (frame->loading.title && frame->loading.title[0] == '/') + { /* strip filename to part after last /. */ + char *s = strrchr (frame->loading.title, '/'); + if (s) strcpy (frame->loading.title, s+1); + } + + if (debug_p) + fprintf (stderr, "%s: loaded %4d x %-4d %4d x %-4d \"%s\"\n", + progname, + frame->loading.geom.width, + frame->loading.geom.height, + frame->loading.tw, frame->loading.th, + (frame->loading.title ? frame->loading.title : "(null)")); + + DONE: + + frame->loaded_p = True; + + if (ss->loads_in_progress <= 0) abort(); + ss->loads_in_progress--; + + /* This image expires N seconds after it finished loading. */ + frame->expires = time((time_t *) 0) + (duration * MI_COUNT(mi)); + + switch (frame->mode) + { + case EARLY: /* part of the initial batch of images */ + { + image swap = frame->current; + frame->current = frame->loading; + frame->loading = swap; + } + break; + case LOADING: /* start dropping the old image out */ + { + frame->mode = OUT; + frame->mode_tick = fade_ticks / speed; + frame->from_top_p = random() & 1; + } + break; + default: + abort(); + } +} + + +static void loading_msg (ModeInfo *mi, int n); + +static Bool +load_initial_images (ModeInfo *mi) +{ + carousel_state *ss = &sss[MI_SCREEN(mi)]; + int i; + Bool all_loaded_p = True; + for (i = 0; i < ss->nframes; i++) + if (! ss->frames[i]->loaded_p) + all_loaded_p = False; + + if (all_loaded_p) + { + if (ss->nframes < MI_COUNT (mi)) + { + /* The frames currently on the list are fully loaded. + Start the next one loading. (We run the image loader + asynchronously, but we load them one at a time.) + */ + load_image (mi, alloc_frame (mi)); + } + else + { + /* The first batch of images are now all loaded! + Stagger the expire times so that they don't all drop out at once. + */ + time_t now = time((time_t *) 0); + int i; + + for (i = 0; i < ss->nframes; i++) + { + image_frame *frame = ss->frames[i]; + frame->r = 1.0; + frame->theta = i * 360.0 / ss->nframes; + frame->expires = now + (duration * (i + 1)); + frame->mode = NORMAL; + } + + /* Instead of always going clockwise, shuffle the expire times + of the frames so that they drop out in a random order. + */ + for (i = 0; i < ss->nframes; i++) + { + image_frame *frame1 = ss->frames[i]; + image_frame *frame2 = ss->frames[random() % ss->nframes]; + time_t swap = frame1->expires; + frame1->expires = frame2->expires; + frame2->expires = swap; + } + + ss->awaiting_first_images_p = False; + } + } + + loading_msg (mi, ss->nframes-1); + + return !ss->awaiting_first_images_p; +} + + +ENTRYPOINT void +reshape_carousel (ModeInfo *mi, int width, int height) +{ + GLfloat h = (GLfloat) height / (GLfloat) width; + + glViewport (0, 0, (GLint) width, (GLint) height); + + glMatrixMode(GL_PROJECTION); + glLoadIdentity(); + gluPerspective (60.0, 1/h, 1.0, 8.0); + + glMatrixMode(GL_MODELVIEW); + glLoadIdentity(); + gluLookAt( 0.0, 0.0, 2.6, + 0.0, 0.0, 0.0, + 0.0, 1.0, 0.0); + + glClear(GL_COLOR_BUFFER_BIT); +} + + +ENTRYPOINT Bool +carousel_handle_event (ModeInfo *mi, XEvent *event) +{ + carousel_state *ss = &sss[MI_SCREEN(mi)]; + + if (event->xany.type == ButtonPress && + event->xbutton.button == Button1) + { + if (! ss->button_down_p) + ss->button_down_time = time((time_t *) 0); + ss->button_down_p = True; + gltrackball_start (ss->trackball, + event->xbutton.x, event->xbutton.y, + MI_WIDTH (mi), MI_HEIGHT (mi)); + return True; + } + else if (event->xany.type == ButtonRelease && + event->xbutton.button == Button1) + { + if (ss->button_down_p) + { + /* Add the time the mouse was held to the expire times of all + frames, so that mouse-dragging doesn't count against + image expiration. + */ + int secs = time((time_t *) 0) - ss->button_down_time; + int i; + for (i = 0; i < ss->nframes; i++) + ss->frames[i]->expires += secs; + } + ss->button_down_p = False; + return True; + } + else if (event->xany.type == ButtonPress && + (event->xbutton.button == Button4 || + event->xbutton.button == Button5 || + event->xbutton.button == Button6 || + event->xbutton.button == Button7)) + { + gltrackball_mousewheel (ss->trackball, event->xbutton.button, 5, + !event->xbutton.state); + return True; + } + else if (event->xany.type == MotionNotify && + ss->button_down_p) + { + gltrackball_track (ss->trackball, + event->xmotion.x, event->xmotion.y, + MI_WIDTH (mi), MI_HEIGHT (mi)); + return True; + } + + return False; +} + + +/* Kludge to add "-v" to invocation of "xscreensaver-getimage" in -debug mode + */ +static void +hack_resources (Display *dpy) +{ +# ifndef HAVE_COCOA + char *res = "desktopGrabber"; + char *val = get_string_resource (dpy, res, "DesktopGrabber"); + char buf1[255]; + char buf2[255]; + XrmValue value; + XrmDatabase db = XtDatabase (dpy); + sprintf (buf1, "%.100s.%.100s", progname, res); + sprintf (buf2, "%.200s -v", val); + value.addr = buf2; + value.size = strlen(buf2); + XrmPutResource (&db, buf1, "String", &value); +# endif /* !HAVE_COCOA */ +} + + +static void +loading_msg (ModeInfo *mi, int n) +{ + carousel_state *ss = &sss[MI_SCREEN(mi)]; + int wire = MI_IS_WIREFRAME(mi); + char text[100]; + + if (wire) return; + + if (n == 0) + sprintf (text, "Loading images..."); + else + sprintf (text, "Loading images... (%d%%)", + (int) (n * 100 / MI_COUNT(mi))); + + if (ss->loading_sw == 0) /* only do this once, so that the string doesn't move. */ + ss->loading_sw = texture_string_width (ss->texfont, text, &ss->loading_sh); + + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + + glMatrixMode(GL_PROJECTION); + glPushMatrix(); + glLoadIdentity(); + + glMatrixMode(GL_MODELVIEW); + glPushMatrix(); + glLoadIdentity(); + + { + double rot = current_device_rotation(); + glRotatef(rot, 0, 0, 1); + if ((rot > 45 && rot < 135) || + (rot < -45 && rot > -135)) + { + GLfloat s = MI_WIDTH(mi) / (GLfloat) MI_HEIGHT(mi); + glScalef (s, 1/s, 1); + } + } + + glOrtho(0, MI_WIDTH(mi), 0, MI_HEIGHT(mi), -1, 1); + glTranslatef ((MI_WIDTH(mi) - ss->loading_sw) / 2, + (MI_HEIGHT(mi) - ss->loading_sh) / 2, + 0); + glColor3f (1, 1, 0); + glEnable (GL_TEXTURE_2D); + glDisable (GL_DEPTH_TEST); + print_texture_string (ss->texfont, text); + glEnable (GL_DEPTH_TEST); + glPopMatrix(); + + glMatrixMode(GL_PROJECTION); + glPopMatrix(); + + glMatrixMode(GL_MODELVIEW); + + glFinish(); + glXSwapBuffers (MI_DISPLAY (mi), MI_WINDOW(mi)); +} + + +ENTRYPOINT void +init_carousel (ModeInfo *mi) +{ + int screen = MI_SCREEN(mi); + carousel_state *ss; + int wire = MI_IS_WIREFRAME(mi); + + if (sss == NULL) { + if ((sss = (carousel_state *) + calloc (MI_NUM_SCREENS(mi), sizeof(carousel_state))) == NULL) + return; + } + ss = &sss[screen]; + + if ((ss->glx_context = init_GL(mi)) != NULL) { + reshape_carousel (mi, MI_WIDTH(mi), MI_HEIGHT(mi)); + clear_gl_error(); /* WTF? sometimes "invalid op" from glViewport! */ + } else { + MI_CLEARWINDOW(mi); + } + + if (!tilt_str || !*tilt_str) + ; + else if (!strcasecmp (tilt_str, "0")) + ; + else if (!strcasecmp (tilt_str, "X")) + tilt_x_p = 1; + else if (!strcasecmp (tilt_str, "Y")) + tilt_y_p = 1; + else if (!strcasecmp (tilt_str, "XY")) + tilt_x_p = tilt_y_p = 1; + else + { + fprintf (stderr, "%s: tilt must be 'X', 'Y', 'XY' or '', not '%s'\n", + progname, tilt_str); + exit (1); + } + + { + double spin_speed = speed * 0.2; /* rotation of tube around axis */ + double spin_accel = speed * 0.1; + double wander_speed = speed * 0.001; /* tilting of axis */ + + spin_speed *= 0.9 + frand(0.2); + wander_speed *= 0.9 + frand(0.2); + + ss->rot = make_rotator (spin_speed, spin_speed, spin_speed, + spin_accel, wander_speed, True); + + ss->trackball = gltrackball_init (); + } + + if (strstr ((char *) glGetString(GL_EXTENSIONS), + "GL_EXT_texture_filter_anisotropic")) + glGetFloatv (GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, &ss->anisotropic); + else + ss->anisotropic = 0.0; + + glDisable (GL_LIGHTING); + glEnable (GL_DEPTH_TEST); + glDisable (GL_CULL_FACE); + + if (! wire) + { + glShadeModel (GL_SMOOTH); + glEnable (GL_LINE_SMOOTH); + /* This gives us a transparent diagonal slice through each image! */ + /* glEnable (GL_POLYGON_SMOOTH); */ + glHint (GL_LINE_SMOOTH_HINT, GL_NICEST); + glEnable (GL_BLEND); + glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + glEnable (GL_ALPHA_TEST); + + glEnable (GL_POLYGON_OFFSET_FILL); + glPolygonOffset (1.0, 1.0); + + } + + ss->texfont = load_texture_font (MI_DISPLAY(mi), "font"); + + if (debug_p) + hack_resources (MI_DISPLAY (mi)); + + ss->nframes = 0; + ss->frames_size = 10; + ss->frames = (image_frame **) + calloc (1, ss->frames_size * sizeof(*ss->frames)); + + ss->mode = IN; + ss->mode_tick = fade_ticks / speed; + + ss->awaiting_first_images_p = True; +} + + +static void +draw_frame (ModeInfo *mi, image_frame *frame, time_t now, Bool body_p) +{ + carousel_state *ss = &sss[MI_SCREEN(mi)]; + int wire = MI_IS_WIREFRAME(mi); + + GLfloat texw = frame->current.geom.width / (GLfloat) frame->current.tw; + GLfloat texh = frame->current.geom.height / (GLfloat) frame->current.th; + GLfloat texx1 = frame->current.geom.x / (GLfloat) frame->current.tw; + GLfloat texy1 = frame->current.geom.y / (GLfloat) frame->current.th; + GLfloat texx2 = texx1 + texw; + GLfloat texy2 = texy1 + texh; + GLfloat aspect = ((GLfloat) frame->current.geom.height / + (GLfloat) frame->current.geom.width); + + glBindTexture (GL_TEXTURE_2D, frame->current.texid); + + glPushMatrix(); + + /* Position this image on the wheel. + */ + glRotatef (frame->theta, 0, 1, 0); + glTranslatef (0, 0, frame->r); + + /* Scale down the image so that all N frames fit on the wheel + without bumping in to each other. + */ + { + GLfloat t, s; + switch (ss->nframes) + { + case 1: t = -1.0; s = 1.7; break; + case 2: t = -0.8; s = 1.6; break; + case 3: t = -0.4; s = 1.5; break; + case 4: t = -0.2; s = 1.3; break; + default: t = 0.0; s = 6.0 / ss->nframes; break; + } + glTranslatef (0, 0, t); + glScalef (s, s, s); + } + + /* Center this image on the wheel plane. + */ + glTranslatef (-0.5, -(aspect/2), 0); + + /* Move as per the "zoom in and out" setting. + */ + if (zoom_p) + { + double x, y, z; + /* Only use the Z component of the rotator for in/out position. */ + get_position (frame->rot, &x, &y, &z, !ss->button_down_p); + glTranslatef (0, 0, z/2); + } + + /* Compute the "drop in and out" state. + */ + switch (frame->mode) + { + case EARLY: + abort(); + break; + case NORMAL: + if (!ss->button_down_p && + now >= frame->expires && + ss->loads_in_progress == 0) /* only load one at a time */ + load_image (mi, frame); + break; + case LOADING: + break; + case OUT: + if (--frame->mode_tick <= 0) { + image swap = frame->current; + frame->current = frame->loading; + frame->loading = swap; + + frame->mode = IN; + frame->mode_tick = fade_ticks / speed; + } + break; + case IN: + if (--frame->mode_tick <= 0) + frame->mode = NORMAL; + break; + default: + abort(); + } + + /* Now translate for current in/out state. + */ + if (frame->mode == OUT || frame->mode == IN) + { + GLfloat t = (frame->mode == OUT + ? frame->mode_tick / (fade_ticks / speed) + : (((fade_ticks / speed) - frame->mode_tick + 1) / + (fade_ticks / speed))); + t = 5 * (1 - t); + if (frame->from_top_p) t = -t; + glTranslatef (0, t, 0); + } + + if (body_p) /* Draw the image quad. */ + { + if (! wire) + { + glColor3f (1, 1, 1); + glNormal3f (0, 0, 1); + glEnable (GL_TEXTURE_2D); + glBegin (GL_QUADS); + glNormal3f (0, 0, 1); + glTexCoord2f (texx1, texy2); glVertex3f (0, 0, 0); + glTexCoord2f (texx2, texy2); glVertex3f (1, 0, 0); + glTexCoord2f (texx2, texy1); glVertex3f (1, aspect, 0); + glTexCoord2f (texx1, texy1); glVertex3f (0, aspect, 0); + glEnd(); + } + + /* Draw a box around it. + */ + glLineWidth (2.0); + glColor3f (0.5, 0.5, 0.5); + glDisable (GL_TEXTURE_2D); + glBegin (GL_LINE_LOOP); + glVertex3f (0, 0, 0); + glVertex3f (1, 0, 0); + glVertex3f (1, aspect, 0); + glVertex3f (0, aspect, 0); + glEnd(); + + } + else /* Draw a title under the image. */ + { + int sw, sh; + GLfloat scale = 0.05; + char *title = frame->current.title ? frame->current.title : "(untitled)"; + sw = texture_string_width (ss->texfont, title, &sh); + + glTranslatef (0, -scale, 0); + + scale /= sh; + glScalef (scale, scale, scale); + + glTranslatef (((1/scale) - sw) / 2, 0, 0); + glColor3f (1, 1, 1); + + if (!wire) + { + glEnable (GL_TEXTURE_2D); + print_texture_string (ss->texfont, title); + } + else + { + glBegin (GL_LINE_LOOP); + glVertex3f (0, 0, 0); + glVertex3f (sw, 0, 0); + glVertex3f (sw, sh, 0); + glVertex3f (0, sh, 0); + glEnd(); + } + } + + glPopMatrix(); +} + + +ENTRYPOINT void +draw_carousel (ModeInfo *mi) +{ + carousel_state *ss = &sss[MI_SCREEN(mi)]; + int i; + + if (!ss->glx_context) + return; + + glXMakeCurrent(MI_DISPLAY(mi), MI_WINDOW(mi), *(ss->glx_context)); + + if (ss->awaiting_first_images_p) + if (!load_initial_images (mi)) + return; + + /* Only check the wall clock every 10 frames */ + { + if (ss->now == 0 || ss->draw_tick++ > 10) + { + ss->now = time((time_t *) 0); + if (ss->last_time == 0) ss->last_time = ss->now; + ss->draw_tick = 0; + } + } + + + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + + glPushMatrix(); + + glRotatef(current_device_rotation(), 0, 0, 1); + + + /* Run the startup "un-shrink" animation. + */ + switch (ss->mode) + { + case IN: + if (--ss->mode_tick <= 0) + { + ss->mode = NORMAL; + ss->last_time = time((time_t *) 0); + } + break; + case NORMAL: + break; + default: + abort(); + } + + + /* Scale as per the startup "un-shrink" animation. + */ + if (ss->mode != NORMAL) + { + GLfloat s = (ss->mode == OUT + ? ss->mode_tick / (fade_ticks / speed) + : (((fade_ticks / speed) - ss->mode_tick + 1) / + (fade_ticks / speed))); + glScalef (s, s, s); + } + + /* Rotate and tilt as per the user, and the motion modeller. + */ + { + double x, y, z; + gltrackball_rotate (ss->trackball); + + /* Tilt the tube up or down by up to 30 degrees */ + get_position (ss->rot, &x, &y, &z, !ss->button_down_p); + if (tilt_x_p) + glRotatef (15 - (x * 30), 1, 0, 0); + if (tilt_y_p) + glRotatef (7 - (y * 14), 0, 0, 1); + + /* Only use the Y component of the rotator. */ + get_rotation (ss->rot, &x, &y, &z, !ss->button_down_p); + glRotatef (y * 360, 0, 1, 0); + } + + /* First draw each image, then draw the titles. GL insists that you + draw back-to-front in order to make alpha blending work properly, + so we need to draw all of the 100% opaque images before drawing + any of the not-100%-opaque titles. + */ + for (i = 0; i < ss->nframes; i++) + draw_frame (mi, ss->frames[i], ss->now, True); + if (titles_p) + for (i = 0; i < ss->nframes; i++) + draw_frame (mi, ss->frames[i], ss->now, False); + + glPopMatrix(); + + if (mi->fps_p) do_fps (mi); + glFinish(); + glXSwapBuffers (MI_DISPLAY (mi), MI_WINDOW(mi)); +} + +XSCREENSAVER_MODULE ("Carousel", carousel) + +#endif /* USE_GL */ diff --git a/hacks/glx/carousel.man b/hacks/glx/carousel.man new file mode 100644 index 00000000..d5c9e430 --- /dev/null +++ b/hacks/glx/carousel.man @@ -0,0 +1,109 @@ +.TH XScreenSaver 1 "" "X Version 11" +.SH NAME +carousel - displays multiple images rotating in a circular formation +.SH SYNOPSIS +.B carousel +[\-display \fIhost:display.screen\fP] +[\-visual \fIvisual\fP] +[\-window] +[\-root] +[\-count \fIint\fP] +[\-zoom | \-no\-zoom] +[\-tilt \fIXY\fP] +[\-titles | \-no\-titles] +[\-font \fIfont\fP] +[\-speed \fIratio\fP] +[\-duration \fIseconds\fP] +[\-fps] +[\-debug] +[\-wireframe] +.SH DESCRIPTION +Loads several random images, and displays them flying in a circular +formation. The circle changes speed and direction randomly, tilts on +its axis, and the images move in and out. + +This program requires a good video card capable of supporting large +textures. + +To specify the directory that images are loaded from, run +.BR xscreensaver-demo (1) +and click on the "Advanced" tab. +.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 \-count \fIint\fP +How many images to display. Default 7. +.TP 8 +.B \-zoom \fB| \-no\-zoom\fP +Whether the images should move in and out (toward and away from the +axis of rotation). Default true. +.TP 8 +.B \-tilt \fIXY\fP \fB| \-no\-tilt\fP +Whether the axis of rotation should tilt, and how. \fB-tilt X\fP +means that it will tilt toward and away from the viewer. +\fB-tilt Y\fP means that it will tilt to the left and right of the +screen. \fB-tilt XY\fP (the default) means it will do both. +.TP 8 +.B \-titles \fB| \-no\-titles\fP +Whether to display the file names of the images beneath them. Default: yes. +.TP 8 +.B \-font \fIfont-name\fP +The font to use for titles. Note that the size of the font affects +the clarity of the characters, not their size (it is auto-scaled.) +.TP 8 +.B \-duration \fIseconds\fP +Every \fIduration\fP seconds, one of the images will be replaced +with a new one. Default 20 seconds. +.TP 8 +.B \-speed \fIratio\fP +Speed up or slow down the animation. 0.5 means half as fast as the +default; 2.0 means twice as fast. +.TP 8 +.B \-delay \fInumber\fP +Per-frame delay, in microseconds. Default: 20000 (0.02 seconds.). +.TP 8 +.B \-fps +Display the current frame rate, CPU load, and polygon count. +.TP 8 +.B \-debug +Prints debugging info to stderr. +.TP 8 +.B \-wireframe +Another debug mode. +.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-demo (1) +.BR xscreensaver-getimage (1) +.BR xscreensaver (1) +.BR glslideshow (MANSUFFIX) +.BR photopile (MANSUFFIX) +.SH COPYRIGHT +Copyright \(co 2005 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/glx/chessgames.h b/hacks/glx/chessgames.h new file mode 100644 index 00000000..28f5c570 --- /dev/null +++ b/hacks/glx/chessgames.h @@ -0,0 +1,343 @@ +/* + * endgame -- plays through a chess game ending. enjoy. + * + * Copyright (C) 2002 Blair Tennessy (tennessy@cs.ubc.ca) + * + * 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. + */ + +#ifndef __CHESSGAMES_H__ +#define __CHESSGAMES_H__ + +/** structure for a chess game */ +typedef struct { + + /** original board configuration */ + int board[BOARDSIZE][BOARDSIZE]; + + /** total moves */ + int movecount; + + /** + moves in game. this is a slight hack: moves are encoded in + integer pairs (x,y). the first pair, _from_, determines the + piece to move. the second pair, _to_, determines where to move. + + in case _to_ is held by another piece, that piece is taken. + (see drawTakePiece(), draw_chess()) + + in case the move promotes a pawn, we assume a queening. + (see drawMovingPiece()) + + what's lacking? + castling, en passant, under-promotions. + */ + int moves[40][4]; +} ChessGame; + +#define GAMES 7 +static ChessGame games[GAMES] = { + + /** + game 1: + + E. N. Somov-Nasimovitsch + White to play and win. + + "Zadachi I Etiudi" + 1928 + */ + { + { + { 0, 0, 0, 0, 0, BKING, 0, 0}, + { BPAWN, 0, BPAWN, 0, BPAWN, 0, 0, 0}, + { 0, 0, BPAWN, 0, BPAWN, 0, 0, KNIGHT}, + { PAWN, 0, ROOK, 0, 0, 0, 0, 0}, + { PAWN, 0, 0, 0, KING, PAWN, 0, 0}, + { 0, 0, 0, 0, 0, 0, 0, 0}, + { BPAWN, 0, 0, 0, 0, 0, 0, PAWN}, + { BBISHOP,0, 0, 0, 0, 0, 0, 0}, + }, + + 24, + + { + {3, 2, 6, 2}, + {7, 0, 6, 1}, + {6, 2, 6, 6}, + {0, 5, 0, 4}, + {6, 6, 0, 6}, + {0, 4, 1, 3}, + {2, 7, 1, 5}, + {2, 2, 3, 2}, + {0, 6, 0, 3}, + {1, 3, 2, 2}, + {0, 3, 6, 3}, + {3, 2, 4, 2}, /* pawn to bishop 5 */ + {1, 5, 0, 3}, /* check */ + {2, 2, 3, 2}, + {0, 3, 2, 4}, /* takes pawn */ + {3, 2, 2, 2}, + {2, 4, 0, 3}, + {2, 2, 3, 2}, + {6, 3, 6, 1}, /* rook takes bishop */ + {6, 0, 7, 0}, + {6, 1, 3, 1}, + {3, 2, 2, 3}, + {3, 1, 3, 3}, + {0, 0, 2, 3}, + } + }, + + /** + game 2: + + K. A. L. Kubbel + White to play and win. + + "Chess in the USSR" + 1936 + */ + { + { + { 0, 0, 0, 0, 0, 0, 0, 0}, + { 0, 0, 0, 0, 0, 0, 0, BPAWN}, + { 0, 0, 0, 0, BPAWN, KING, 0, BKING}, + { 0, 0, 0, 0, 0, ROOK, 0, 0}, + { 0, 0, 0, 0, 0, 0, 0, 0}, + { 0,BBISHOP, 0, 0, BROOK, 0, PAWN, 0}, + { 0, 0, 0, 0, 0, 0, 0, 0}, + { 0, 0, 0, 0, 0,BISHOP, 0, 0}, + }, + + 10, + + { + {3, 5, 6, 5}, + {5, 1, 7, 3}, + {6, 5, 6, 7}, /* check */ + {7, 3, 3, 7}, + {7, 5, 6, 4}, + {5, 4, 6, 4}, + {5, 6, 4, 6}, /* ! */ + {6, 4, 6, 7}, + {4, 6, 3, 6}, + {0, 0, 2, 7} + } + }, + + /** + game 3: + + J. Hasek + White to play and win. + + "Le Strategie" + 1929 + */ + { + { + { 0, 0, 0, KNIGHT, 0, 0, 0, KNIGHT}, + { 0, KING, BPAWN, BPAWN, 0, 0, 0, 0}, + { 0, 0, 0, 0, 0, 0, 0, 0}, + { 0, BKING, 0, 0, 0, 0, 0, 0}, + { 0, PAWN, 0, 0, 0, BPAWN, 0, 0}, + { PAWN, 0, PAWN, 0, 0, 0, 0, 0}, + { 0, 0, 0, 0, 0, 0, 0, 0}, + { 0, 0, 0, 0, 0, 0, 0, 0}, + }, + + 11, + + { + {0, 3, 2, 2}, + {1, 3, 2, 2}, + {0, 7, 2, 6}, + {4, 5, 5, 5}, + {2, 6, 3, 4}, + {5, 5, 6, 5}, + {3, 4, 5, 3}, /* ! */ + {6, 5, 7, 5}, + {5, 3, 6, 1}, + {0, 0, 0, 0}, /* mull it over... */ + {0, 0, 3, 1} + } + }, + + /** + game 4: + + M.B. Newman + White to play and win. + + "Chess Amateur" + 1913 + */ + { + { + { 0, 0, 0, 0, BQUEEN, 0, 0, 0}, + {BKNIGHT, 0, 0, 0, 0, 0, 0, 0}, + { 0, 0, 0, 0, 0, 0, 0, 0}, + { 0, 0, 0, 0, 0, 0, 0, PAWN}, + { BKING, 0, BISHOP, 0, KNIGHT, 0, 0, 0}, + { PAWN, 0, 0, 0, KNIGHT, 0, 0, 0}, + { 0, 0, 0, 0, 0, 0, 0, 0}, + { KING, 0, 0, 0, 0, 0, 0, 0}, + }, + + 15, + + { + {4, 2, 3, 1}, + {0, 4, 3, 1}, /* queen wins bishop */ + {4, 4, 5, 2}, + {4, 0, 5, 0}, /* king takes pawn */ + {5, 2, 3, 1}, /* knight takes queen, check */ + {1, 0, 3, 1}, /* knight takes knight */ + {3, 7, 2, 7}, /* pawn advances */ + {3, 1, 2, 3}, + {5, 4, 4, 2}, + {2, 3, 4, 2}, + {2, 7, 1, 7}, /* pawn advances */ + {4, 2, 2, 3}, + {1, 7, 0, 7}, + {0, 0, 0, 0}, + {0, 0, 5, 0} + } + }, + + /** + game 5: + + V.A. Korolikov + White to play and win + + First Prize - "Truda" + 1935 + */ + { + { + { 0, 0, BISHOP, 0, 0, 0, 0, 0}, + { BPAWN, ROOK, 0, 0, 0, 0, 0, 0}, + { 0, 0, BPAWN, PAWN, 0, BKING, 0, 0}, + { 0, 0, 0, 0, 0, 0, 0, 0}, + { 0, 0, 0, 0, 0, 0, KING, BBISHOP}, + { 0, 0, 0, 0, BPAWN, 0, PAWN, 0}, + { 0, 0, 0, 0, 0, BPAWN, 0, 0}, + { 0, 0, 0, 0, 0, 0, 0, 0}, + }, + + 21, + + { + {2, 3, 1, 3}, /* pawn to q7 */ + {2, 5, 1, 4}, /* cover with king */ + {1, 1, 0, 1}, + {4, 7, 5, 6}, /* bishop takes pawn */ + {0, 1, 0, 0}, /* r - r8 */ + {6, 5, 7, 5}, /* queened */ + {1, 3, 0, 3}, /* white pawn promoted */ + {1, 4, 0, 3}, /* king takes queen */ + {0, 2, 2, 0}, /* discovered check */ + {5, 6, 0, 1}, /* pull back bishop */ + {2, 0, 7, 5}, /* bishop takes queen */ + {0, 3, 1, 2}, + {7, 5, 2, 0}, /* save rook */ + {5, 4, 6, 4}, + {2, 0, 6, 4}, /* bishop takes pawn */ + {1, 2, 1, 1}, /* king moves in */ + {6, 4, 5, 5}, + {1, 1, 0, 0}, + {5, 5, 2, 2}, + {0, 0, 0, 0}, + {0, 0, 0, 0} + } + }, + + /** + game 6: + + T.B. Gorgiev + White to play and win + + First Prize - "64" + 1929 + */ + { + { + { 0, 0, 0, 0, 0, 0, KNIGHT, 0}, + { BKNIGHT, 0, 0, 0, 0, 0, 0, 0}, + { 0, 0, 0, BKING, BKNIGHT, 0, 0, 0}, + { KING, 0, 0, 0, 0, 0, 0, 0}, + { 0, 0, 0, 0, 0, 0, KNIGHT, 0}, + { 0, 0, 0, 0, 0, 0, 0, 0}, + { 0, 0, 0, 0, 0, 0, 0, 0}, + { 0, 0, 0, 0, BISHOP, 0, 0, 0}, + }, + + 13, + + { + {3, 0, 2, 1}, /* king on move */ + {1, 0, 0, 2}, /* check */ + {2, 1, 1, 1}, + {0, 2, 1, 4}, /* knight moves on */ + {7, 4, 5, 6}, /* bishop puts king in check */ + {2, 3, 1, 3}, /* king moves back */ + {0, 6, 2, 5}, /* knight moves in, check */ + {1, 3, 0, 3}, /* king moves back queen */ + {5, 6, 1, 2}, /* bishop - b7 ch!! */ + {2, 4, 1, 2}, /* black knight takes bishop */ + {4, 6, 3, 4}, /* knight to k5 */ + {0, 0, 0, 0}, /* mate */ + {0, 0, 0, 0} + } + }, + + /** + game 7: + + K. A. L. Kubbel + White to play and win + + "Schachmatny Listok" + 1922 + */ + { + { + { 0, KNIGHT, 0, 0, 0, 0, 0, 0}, + { 0, 0, 0, 0, 0, 0, 0, 0}, + { KING, 0, 0, 0, 0, 0, 0, 0}, + { 0, 0, 0, BKING, 0, 0, 0, 0}, + { 0, 0, 0, BPAWN, 0, 0, 0, BISHOP}, + { BPAWN, 0, 0, 0, 0, 0, 0, 0}, + { 0, 0, PAWN, PAWN, 0, 0, 0, 0}, + { 0, 0, 0, 0, 0, 0, 0, 0}, + }, + + 12, + + { + {0, 1, 2, 2}, /* kt-b6 */ + {3, 3, 2, 2}, /* k x kt */ + {4, 7, 2, 5}, /* b-b6 */ + {2, 2, 3, 3}, /* king back to original position */ + {6, 3, 5, 3}, /* p-q3! */ + {5, 0, 6, 0}, /* p-r7 */ + {6, 2, 4, 2}, /* p-b4ch */ + {3, 3, 3, 2}, /* king moves, black cannot capture in passing */ + {2, 0, 1, 1}, /* k-kt7! */ + {6, 0, 7, 0}, /* promo */ + {2, 5, 1, 4}, /* mate */ + {0, 0, 3, 2}, + } + }, +}; + +#endif /* __CHESSGAMES_H__ */ diff --git a/hacks/glx/chessmodels.c b/hacks/glx/chessmodels.c new file mode 100644 index 00000000..eac7b252 --- /dev/null +++ b/hacks/glx/chessmodels.c @@ -0,0 +1,1733 @@ +/* + * models for the xss chess screensavers + * hacked from: + * + * glChess - A 3D chess interface + * + * Copyright (C) 2006 John-Paul Gignac + * + * Copyright (C) 2002 Robert Ancell + * Michael Duelli + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* chessmodels.c: Contains the code for piece model creation */ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif /* HAVE_CONFIG_H */ + +#include +#include + +#ifndef HAVE_COCOA +# include +# include +#endif + +#ifdef HAVE_JWZGLES +# include "jwzgles.h" +#endif /* HAVE_JWZGLES */ + +#include "chessmodels.h" + +/* End of Data */ +#define ENDOFDATA 65535 + +/* Section headers */ +#define SPIN 65534 +#define VERTICES 65533 +#define QUADS 65532 +#define TRIANGLES 65531 +#define POLARQUADSTRIP 65530 +#define QUADSTRIP 65529 + +/* Special spin-related commands */ +#define SEAM 65528 +#define PATTERN 65527 +#define STEPUP 65526 +#define STEPDOWN 65525 +#define SETBACKREF 65524 +#define BACKREF 65523 + +static unsigned short classic_pawn_data[] = { + SPIN,16, + 350,0,SEAM,350,200,SEAM,250,300,SEAM,250,400,SEAM,150,600,SEAM,100,880, + SEAM,180,880,SEAM,100,920,SEAM,200,1160,SEAM,100,1340,0,1340, + ENDOFDATA +}; + +static unsigned short classic_rook_data[] = { + SPIN,16, + 380,0,SEAM,380,200,SEAM,260,500,SEAM,200,1020,SEAM,280,1020,SEAM,280,1360,SEAM,220,1360,SEAM,220,1300,0,1300, + ENDOFDATA +}; + +static unsigned short classic_knight_data[] = { + SPIN,16, + 410,0,SEAM,410,200,SEAM,200,360,SEAM,200,480,260,580, + + VERTICES, + 260,580,260, -260,580,260, -260,580,-80, 260,580,-80, 80,1620,400, + 100,1680,340, -100,1680,340, -80,1620,400, 100,1680,340, 100,1680,300, + -100,1680,300, -100,1680,340, 100,1680,300, 50,1680,160, -50,1680,160, + -100,1680,300, 50,1680,160, 100,1680,20, -100,1680,20, -50,1680,160, + 100,1680,20, 100,1680,-20, -100,1680,-20, -100,1680,20, 100,1680,-20, + 40,1680,-110, -40,1680,-110, -100,1680,-20, 40,1680,-110, + 100,1680,-200, -100,1680,-200, -40,1680,-110, 100,1680,-200, + 100,1680,-440, -100,1680,-440, -100,1680,-200, -100,1680,-440, + 100,1680,-440, 100,1500,-440, -100,1500,-440, -100,1500,-440, + 100,1500,-440, 55,1480,-280, -55,1480,-280, -100,1680,300, -50,1680,160, + -100,1400,130, -120,1380,240, -50,1680,160, -80,1680,20, -120,1380,20, + -100,1400,130, -83,1660,20, -80,1680,20, -100,1680,-20, -100,1660,-38, + -120,1380,20, -88,1620,20, -100,1620,-74, -120,1360,-20, -120,1360,-20, + -100,1620,-74, -100,1580,-110, -60,1400,-140, -100,1680,-200, + -55,1480,-280, -60,1400,-140, -100,1580,-110, -100,1680,-200, + -100,1680,-440, -100,1500,-440, -55,1480,-280, 100,1680,300, + 120,1380,240, 100,1400,130, 50,1680,160, 50,1680,160, 100,1400,130, + 120,1380,20, 80,1680,20, 83,1660,20, 100,1660,-38, 100,1680,-20, + 80,1680,20, 120,1380,20, 120,1360,-20, 100,1620,-74, 88,1620,20, + 120,1360,-20, 60,1400,-140, 100,1580,-110, 100,1620,-74, 100,1680,-200, + 100,1580,-110, 60,1400,-140, 55,1480,-280, 100,1680,-200, 55,1480,-280, + 100,1500,-440, 100,1680,-440, 88,1620,20, 100,1620,-74, 80,1640,-56, + 61,1640,20, 61,1640,20, 80,1640,-56, 100,1660,-38, 83,1660,20, + -88,1620,20, -61,1640,20, -80,1640,-56, -100,1620,-74, -61,1640,20, + -83,1660,20, -100,1660,-38, -80,1640,-56, 35,1780,-80, 35,1780,-440, + -35,1780,-440, -35,1780,-80, 35,1780,-80, 35,1680,-80, 35,1680,-440, + 35,1780,-440, -35,1780,-80, -35,1780,-440, -35,1680,-440, -35,1680,-80, + 35,1780,-80, -35,1780,-80, -35,1680,-80, 35,1680,-80, 35,1780,-440, + 35,1680,-440, -35,1680,-440, -35,1780,-440, -100,1400,130, -120,1380,20, + 120,1380,20, 100,1400,130, -100,1400,130, 100,1400,130, 120,1380,240, + -120,1380,240, -260,580,-80, -55,1480,-280, 0,1500,-360, 0,780,-400, + 260,580,-80, 0,780,-400, 0,1500,-360, 55,1480,-280, -50,1380,40, + -200,880,400, 200,880,400, 50,1380,40, -200,880,400, -260,580,260, + 260,580,260, 200,880,400, -50,1380,40, -140,1220,-40, -260,580,260, + -200,880,400, -140,1220,-40, -114,1220,-222, -260,580,-80, -260,580,260, + -55,1480,-280, -114,1220,-222, -140,1220,-40, -60,1400,-140, + 50,1380,40, 200,880,400, 260,580,260, 140,1220,-40, 140,1220,-40, + 260,580,260, 260,580,-80, 114,1220,-222, 55,1480,-280, 60,1400,-140, + 140,1220,-40, 114,1220,-222, 260,580,-80, 144,580,-260, 0,780,-400, + 144,580,-260, -144,580,-260, 0,780,-400, -260,580,-80, 0,780,-400, + -144,580,-260, 0,1400,400, 80,1620,400, -80,1620,400, 0,1400,400, + -80,1620,400, -120,1380,240, -120,1380,240, -80,1620,400, -100,1680,340, + -120,1380,240, -100,1680,340, -100,1680,300, 0,1400,400, 120,1380,240, + 80,1620,400, 120,1380,240, 100,1680,340, 80,1620,400, 120,1380,240, + 100,1680,300, 100,1680,340, 0,1400,400, -120,1380,240, 120,1380,240, + -60,1400,-140, -140,1220,-40, -45,1380,-20, -45,1380,-20, -140,1220,-40, + -50,1380,40, 60,1400,-140, 45,1380,-20, 140,1220,-40, 45,1380,-20, + 50,1380,40, 140,1220,-40, 60,1400,-140, 120,1360,-20, 45,1380,-20, + 50,1380,40, 45,1380,-20, 120,1360,-20, 50,1380,40, 120,1360,-20, + 120,1380,20, -60,1400,-140, -45,1380,-20, -120,1360,-20, -50,1380,40, + -120,1360,-20, -45,1380,-20, -50,1380,40, -120,1380,20, -120,1360,-20, + 88,1620,20, 61,1640,20, 83,1660,20, 100,1620,-74, 100,1660,-38, + 80,1640,-56, -88,1620,20, -83,1660,20, -61,1640,20, -100,1620,-74, + -80,1640,-56, -100,1660,-38, -40,1680,-110, -100,1680,-200, + -100,1580,-110, -100,1680,-20, -40,1680,-110, -100,1580,-110, + 40,1680,-110, 100,1580,-110, 100,1680,-200, 100,1680,-20, 100,1580,-110, + 40,1680,-110, + + QUADS, 0,1,2,3, 4,5,6,7, 8,9,10,11, 12,13,14,15, 16,17,18,19, + 20,21,22,23, 24,25,26,27, 28,29,30,31, 32,33,34,35, 36,37,38,39, + 40,41,42,43, 44,45,46,47, 48,49,50,51, 52,53,54,55, 56,57,58,59, + 60,61,62,63, 64,65,66,67, 68,69,70,71, 72,73,74,75, 76,77,78,79, + 80,81,82,83, 84,85,86,87, 88,89,90,91, 92,93,94,95, 96,97,98,99, + 100,101,102,103, 104,105,106,107, 108,109,110,111, 112,113,114,115, + 116,117,118,119, 120,121,122,123, 124,125,126,127, 128,129,130,131, + 132,133,134,135, 136,137,138,139, 140,141,142,143, 144,145,146,147, + 148,149,150,151, 152,153,154,155, 156,157,158,159, 160,161,162,163, + 164,165,166,167, 168,169,170,171, 172,173,174,175, 176,177,178,179, + 180,181,182,183, + + TRIANGLES, 184,185,186, 187,188,189, 190,191,192, 193,194,195, + 196,197,198, 199,200,201, 202,203,204, 205,206,207, 208,209,210, + 211,212,213, 214,215,216, 217,218,219, 220,221,222, 223,224,225, + 226,227,228, 229,230,231, 232,233,234, 235,236,237, 238,239,240, + 241,242,243, 244,245,246, 247,248,249, 250,251,252, 253,254,255, + 256,257,258, 259,260,261, 262,263,264, 265,266,267, 268,269,270, + + ENDOFDATA +}; + +static unsigned short classic_bishop_data[] = { + SPIN,16, + 400,0,SEAM,400,200,SEAM,250,300,SEAM,250,400,SEAM,150,700,SEAM,120,940, + SEAM,250,940,SEAM,170,1100,SEAM,170,1220,SEAM,220,1320,SEAM,220,1480, + SEAM,100,1600,SEAM,80,1700,SEAM,120,1770,SEAM,80,1840,0,1840, + ENDOFDATA +}; + +static unsigned short classic_queen_data[] = { + SPIN,16, + 480,0,SEAM,480,220,SEAM,340,400,SEAM,340,500,SEAM,180,800,SEAM,140,1180, + SEAM,290,1180,SEAM,180,1360,SEAM,180,1520,SEAM,200,1780,SEAM,270,1920, + SEAM,240,2000,SEAM,170,2000,SEAM,95,2080,SEAM,70,2080,SEAM,90,2140, + SEAM,70,2200,0,2200, + ENDOFDATA +}; + +static unsigned short classic_king_data[] = { + SPIN,16, + 500,0,SEAM,500,200,SEAM,350,300,SEAM,350,460,SEAM,200,760,SEAM,140,1260, + SEAM,300,1260,SEAM,200,1460,SEAM,200,1560,SEAM,280,1910,SEAM,160,1970, + SEAM,160,2010,0,2010, + + VERTICES, + -30,2010,35, 30,2010,35, 30,2310,35, -30,2310,35, -90,2110,35, + -30,2110,35, -30,2210,35, -90,2210,35, 90,2110,35, 90,2210,35, + 30,2210,35, 30,2110,35, 30,2010,-35, -30,2010,-35, -30,2310,-35, + 30,2310,-35, -30,2110,-35, -90,2110,-35, -90,2210,-35, -30,2210,-35, + 30,2110,-35, 30,2210,-35, 90,2210,-35, 90,2110,-35, -90,2110,35, + -90,2210,35, -90,2210,-35, -90,2110,-35, -30,2010,35, -30,2110,35, + -30,2110,-35, -30,2010,-35, -30,2210,30, -30,2310,30, -30,2310,-30, + -30,2210,-30, 90,2110,-35, 90,2210,-35, 90,2210,35, 90,2110,35, + 30,2010,-35, 30,2110,-35, 30,2110,35, 30,2010,35, 30,2210,-35, + 30,2310,-35, 30,2310,35, 30,2210,35, -90,2210,-35, -90,2210,35, + -30,2210,35, -30,2210,-35, 30,2210,-35, 30,2210,35, 90,2210,35, + 90,2210,-35, -30,2310,-35, -30,2310,35, 30,2310,35, 30,2310,-35, + + QUADS, 0,1,2,3, 4,5,6,7, 8,9,10,11, 12,13,14,15, 16,17,18,19, + 20,21,22,23, 24,25,26,27, 28,29,30,31, 32,33,34,35, 36,37,38,39, + 40,41,42,43, 44,45,46,47, 48,49,50,51, 52,53,54,55, 56,57,58,59, + + ENDOFDATA +}; + +static unsigned short knight_data[] = { + VERTICES, SETBACKREF,0, 7910,8863,0, 7790,8863,1326, 7433,8863,2611, + 6850,8863,3817, 6059,8863,4907, 5084,8863,5847, 3955,8863,6611, + 2705,8863,7173, 1373,8863,7517, 0,8863,7633, -1373,8863,7517, + -2705,8863,7173, -3955,8863,6611, -5084,8863,5847, -6059,8863,4907, + -6850,8863,3817, -7433,8863,2611, -7790,8863,1326, -7910,8863,0, + -7790,8863,-1326, -7433,8863,-2611, -6850,8863,-3817, + -6059,8863,-4907, -5066,8863,-5896, -3955,8863,-6611, + -2705,8863,-7173, -1373,8863,-7517, 0,8863,-7633, 1373,8863,-7517, + 2705,8863,-7173, 3955,8863,-6611, 5066,8863,-5896, 6059,8863,-4907, + 6850,8863,-3817, 7433,8863,-2611, 7790,8863,-1326, -1183,11744,7939, + -1183,12003,7939, -1183,14019,6547, -1183,16307,5288, + -1183,16555,5281, -1183,20128,2191, -1134,20304,2131, + -1183,20516,2156, -1417,21874,1842, -1417,23109,2185, + -1417,23961,3121, -1417,24001,4252, 0,23917,5637, -1418,23893,5418, + -1151,23389,6664, -1151,23501,6906, -1151,23806,6987, + -1151,24102,6987, -1151,24209,7189, -1151,24371,7513, + -1151,24605,7715, -1151,24939,7674, -1313,25568,7149, + -1313,25695,7149, -1598,26707,7610, 0,26837,7841, 0,27354,8076, + -1598,27262,7839, -1598,27842,7723, 0,27919,7998, 0,28449,7606, + -1598,28309,7303, -1302,28414,6723, 0,28544,6980, 0,28540,6197, + -1187,28523,5990, -1304,28447,4204, -1158,28789,1627, + -561,28931,-1220, -357,29608,-1244, -357,30527,-1441, + -357,31249,-1837, -357,31511,-2627, -357,31511,-3484, + -357,31118,-4143, -357,30264,-4538, -436,29406,-5256, 0,29409,-5243, + -2207,29018,-6763, -914,28658,-6964, 0,26292,-7237, -1305,26324,-7143, + -806,23401,-6784, -812,20723,-6228, -796,16757,-6210, + -1559,24934,7435, -1566,24633,7460, -1531,24429,7334, + -1475,24293,7131, -1440,24203,7004, -1372,23935,7015, + -1364,23606,6868, -1389,23515,6705, -1687,28010,6952, + -1687,27926,7343, -1687,27629,7491, -1687,27324,7552, + -1687,27032,7432, -1687,26791,7148, -1642,27135,7165, + -1642,27254,7304, -1642,27397,7364, -1642,27546,7334, + -1642,27693,7261, -1642,27737,7088, -1611,10591,8159, + -888,9327,-8560, -4491,13292,1032, -3840,15084,786, -3412,17397,397, + -2937,20005,-35, -5108,11669,1240, -6344,10251,1395, -6345,10246,1248, + -5109,11664,1092, -2964,20022,-132, -3413,17393,250, -3841,15079,638, + -4491,13288,885, -3743,13207,-535, -3085,15092,-710, -2727,17642,-878, + -2569,20636,-797, -4348,11575,-324, -5584,10108,-169, + -5403,10079,-1732, -4167,11644,-1888, -2465,20842,-2651, + -2522,18130,-2392, -2905,15407,-2077, -3562,13227,-1951, + -3901,13568,-3294, -3243,15993,-3519, -2861,18863,-3735, + -2776,22447,-4309, -4486,11792,-3132, -5783,9930,-2931, + -5783,9930,-3054, -4486,11792,-3255, -2776,22438,-4430, + -2861,18863,-3858, -3243,15993,-3641, -3901,13568,-3417, + -6199,9466,4558, -5766,10642,5726, -5228,11829,6090, -4801,12891,6048, + -4155,14560,5246, -3546,16847,3719, -3334,17643,2937, + -2860,20062,1230, -4822,12054,7102, -5325,10909,7208, + -5732,9938,6026, -4026,14701,5522, -2852,20170,1447, -3319,17801,3175, + -3538,16955,3935, -4090,13256,1679, -2874,20073,676, -3706,15083,1464, + -3301,17348,1117, -5931,10206,1996, -4695,11624,1840, + -4445,11658,2844, -5681,10240,3000, -3074,17398,2202, + -3456,15117,2468, -3840,13290,2683, -4642,13358,4019, + -4257,15194,3908, -6017,10188,3746, -5237,11714,4039, + -5621,11218,5077, -5026,12862,5058, -5134,10861,-3154, + -4193,12680,-3336, -2832,20609,-4118, -3052,17428,-3750, + -3572,14780,-3529, -3579,14774,-3623, -3059,17422,-3843, + -2839,20596,-4211, -4200,12674,-3429, -5141,10855,-3248, + -3908,13562,-3510, -3250,15987,-3735, -2868,18857,-3952, + -4492,11786,-3348, -5789,9924,-3148, -4817,11321,-3298, + -5465,10389,-3198, -4054,13118,-3470, -4346,12230,-3389, + -2853,19681,-4056, -2825,21511,-4367, -3155,16705,-3789, + -2963,18140,-3897, -3744,14168,-3567, -3415,15381,-3679, + -845,13482,-6604, -945,10997,-7893, -981,11110,-7735, + -859,13469,-6526, -899,9307,-8439, -813,16486,-6146, -832,20681,-6100, + -826,23358,-6656, -882,10149,-8148, -913,12323,-7139, + -822,14910,-6353, -817,18235,-6210, -827,21937,-6382, + -846,21937,-6341, -841,14912,-6313, -931,12326,-7098, + -901,10152,-8107, -844,23359,-6615, -851,20681,-6059, + -831,16487,-6105, -919,9307,-8399, -869,13482,-6492, -999,11113,-7694, + -860,9726,-8255, -942,10578,-7958, -962,11715,-7413, -900,12896,-6796, + -863,14065,-6404, -818,15760,-6221, -828,17367,-6171, + -854,19800,-5994, -848,21309,-6200, -843,22566,-6482, + -3407,15409,-3785, -3736,14196,-3673, -2911,18365,-4048, + -3147,16733,-3895, -2726,21608,-4455, -2808,19905,-4191, + -4338,12259,-3495, -4046,13146,-3576, -5457,10418,-3304, + -4809,11349,-3404, -4484,11815,-3454, -2715,22288,-4534, + -2832,19035,-4066, -3242,16015,-3841, -3900,13590,-3616, + -5133,10883,-3354, -4171,12742,-3524, -2803,20773,-4339, + -3051,17450,-3949, -3571,14803,-3729, -4979,11072,-3368, + -5619,10185,-3279, -4119,12924,-3556, -4411,12037,-3475, + -2801,20363,-4269, -2721,21826,-4489, -3099,17092,-3922, + -2887,18618,-4038, -3653,14499,-3701, -3325,15712,-3813, + -3489,15106,-3757, -3818,13893,-3645, -3011,17758,-3971, + -3194,16374,-3868, -2755,21085,-4385, -2815,19494,-4139, + -4265,12481,-3515, -3973,13368,-3596, -5304,10595,-3318, + -4664,11477,-3407, -5441,10207,-3361, -5350,10338,-3375, + -5139,10672,-3428, -5058,10742,-3431, -4831,11101,-3457, + -4742,11228,-3470, -4516,11559,-3504, -4423,11693,-3518, + -4277,12079,-3558, -4232,12180,-3571, -4138,12522,-3597, + -4094,12603,-3609, -3979,12935,-3675, -3943,13043,-3671, + -3852,13383,-3699, -3813,13496,-3705, -3692,13947,-3767, + -3653,14073,-3790, -3506,14587,-3772, -3467,14685,-3777, + -3349,15192,-3888, -3308,15317,-3887, -3162,15800,-3957, + -3119,15954,-3961, -3009,16528,-3946, -3002,16637,-3937, + -2914,17260,-4014, -2909,17347,-4006, -2834,17893,-4049, + -2813,18060,-4060, -2760,18849,-4232, -2746,18968,-4242, + -850,22569,-6438, -855,21313,-6156, -861,19804,-5949, + -834,17371,-6127, -824,15765,-6176, -869,14070,-6360, + -906,12901,-6751, -968,11720,-7368, -948,10645,-7895, -865,9731,-8211, + -1006,11164,-7630, -875,13487,-6447, -926,9310,-8354, + -837,16490,-6061, -857,20684,-6015, -867,23379,-6515, + -907,10157,-8062, -937,12331,-7053, -847,14917,-6268, + -842,18236,-6111, -852,21941,-6297, -885,9891,-8156, -985,10905,-7724, + -947,11969,-7255, -885,13125,-6649, -858,14493,-6314, + -839,16049,-6111, -836,17735,-6083, -859,20244,-5982, + -891,21559,-6157, -848,22883,-6508, -851,22255,-6367, + -856,20999,-6085, -867,19042,-6000, -836,16930,-6094, + -835,15341,-6222, -880,13646,-6405, -916,12540,-6953, + -981,11337,-7564, -927,10370,-7988, -932,9518,-8285, -931,9583,-8174, + -863,9671,-8145, -892,9982,-8037, -903,10075,-7996, -952,10454,-7865, + -961,10550,-7832, -1008,10963,-7617, -1018,11105,-7567, + -996,11458,-7405, -992,11582,-7342, -972,12080,-7057, + -968,12210,-6984, -935,12620,-6792, -931,12759,-6714, + -914,13199,-6441, -910,13346,-6359, -915,13767,-6194, + -910,13941,-6175, -890,14633,-6107, -886,14783,-6091, + -864,15476,-6035, -859,15645,-6017, -870,16062,-5957, + -873,16231,-5936, -853,17048,-5965, -861,17185,-5974, + -879,17812,-5997, -885,17961,-5997, -851,18486,-6138, + -865,18526,-5933, -872,18761,-5875, -870,19337,-5971, + -864,19470,-5784, -937,19590,-5786, -833,19023,-6126, + -851,20344,-5894, -851,20576,-5912, -855,21086,-5973, + -854,21224,-6003, -871,21651,-6070, -852,21853,-6116, + -850,22332,-6224, -849,22490,-6259, -831,22924,-6338, + -834,23240,-6364, -2743,19661,-4287, -2740,19863,-4312, + -2723,20501,-4469, -2705,20711,-4503, -2661,21262,-4565, + -2658,21427,-4593, -2687,22088,-4631, -2695,22209,-4643, + -2774,23170,-4392, -2633,23103,-4527, -2681,22439,-4516, + -2656,22665,-4573, -2552,22727,-4653, -2534,23015,-4628, + -2607,23397,-4556, -2759,23681,-4398, -2740,24136,-4370, + -2610,24100,-4580, -2412,24481,-5089, -2671,24389,-4569, + -2397,24935,-5652, -2562,25022,-5528, -939,23708,-6566, + -1009,24359,-6776, -1095,24912,-6886, -1049,24117,-6493, + -990,23894,-6415, -2290,23837,-4814, -2312,23612,-4723, + -2183,24804,-5574, -2191,24632,-5391, -1156,24771,-6650, + -1154,24624,-6586, -1104,24526,-6656, -1281,9161,-8432, + -2524,9161,-8046, -3691,9161,-7572, -4745,9161,-6945, + -5662,9127,-6096, -3697,9192,-7581, -2531,9192,-8056, + -4753,9183,-6951, -5664,9161,-6101, -5664,9185,-6101, + -4753,9207,-6951, -2531,9216,-8055, -3697,9216,-7581, + -3684,9232,-7560, -2518,9232,-8034, -4740,9223,-6930, + -5651,9200,-6080, -2828,20259,1366, -2798,20256,1187, -2820,20237,692, + -2843,20292,-25, -2874,20473,735, -2975,20508,90, -2474,20772,-759, + -2660,20879,-691, -2471,21553,-1445, -2498,22175,-1940, + -2471,24346,-2830, -2556,22373,-1903, -2528,21595,-1351, + -2493,24314,-2936, -2576,22239,-2123, -2548,21461,-1571, + -2823,20635,1307, -2741,20503,1328, -1490,23972,5392, + -1489,24080,4226, -1489,24040,3095, -1489,23188,2159, + -1489,21953,1816, -2479,22156,182, -1515,23830,2117, -1605,24415,3131, + -1599,24460,4263, -1580,24357,5431, -1448,23885,6743, + -1252,24770,5442, -1271,24873,4274, -1277,24828,3142, + -1389,24618,2016, -1479,24733,1993, -1301,25010,3165, + -1295,25055,4297, -1391,24890,5460, -1512,25216,5507, + -1602,25353,4317, -1608,25308,3186, -1979,23458,-29, -1320,25312,1928, + -1495,25055,546, -2438,25790,-488, -1605,25585,5599, -1583,26793,6150, + -1850,26272,4298, -1578,27435,7117, -1658,27625,6884, + -1671,27398,6846, -1678,27176,6937, -1715,27784,6626, + -1744,27323,6551, -1753,26904,6776, -1884,28809,-1688, + -1555,28655,1620, -1658,28252,4204, -1581,28263,5997, + -1567,28312,6790, -1935,27827,4220, -1818,28249,1603, + -1570,27742,6195, -1532,27288,6120, -2038,27074,4245, -1418,28416,228, + -413,30264,-4539, -424,31094,-4152, -418,31478,-3497, + -410,31453,-2653, -410,31190,-1863, -410,30468,-1467, + -410,29550,-1270, -411,31041,-1902, -448,31253,-2696, + -449,31323,-3466, -425,31182,-3496, -411,31060,-2738, + -387,30899,-1932, -316,30806,-1957, -335,30952,-2766, + -353,31089,-3521, -322,31007,-3540, -303,30871,-2786, + -284,30725,-1976, -304,30630,-1993, -323,30776,-2802, + -342,30912,-3557, -396,30843,-3565, -378,30707,-2811, + -358,30561,-2001, -414,30477,-2013, -433,30623,-2822, + -452,30759,-3576, -474,30560,-3616, -456,30424,-2861, + -436,30278,-2052, -349,30194,-2077, -368,30340,-2886, + -386,30477,-3641, -309,30389,-3665, -291,30253,-2911, + -271,30107,-2102, -267,29996,-2124, -286,30142,-2933, + -305,30278,-3688, -376,30179,-3700, -357,30043,-2945, + -338,29897,-2136, -420,29789,-2150, -439,29935,-2959, + -458,30071,-3713, -500,29883,-3751, -463,29601,-2187, + -470,30974,-4049, -462,30153,-4391, -466,30563,-4220, + -410,30009,-1368, -725,29372,-3225, -677,29335,-5130, + -908,29205,-3300, -632,29533,-4803, -2587,28768,-3408, + -2730,28611,-3456, -2404,28568,-6916, -2413,28849,-6612, + -1904,26715,1801, -1394,25919,831, -2224,27270,-3994, + -2730,28438,-3011, -2587,28570,-2864, -2826,28152,-3163, + -2476,28668,-6523, -2476,28433,-6776, -2787,28338,-3507, + -2216,27658,-3972, -2207,27950,-5907, -2311,28216,-6128, + -2320,27876,-3971, -2311,28118,-6301, -2311,27845,-6252, + -2320,27703,-3749, -2320,27084,-3798, -2320,26986,-4070, + -2698,26705,-4014, -2557,26974,-3547, -2557,27739,-3485, + -2572,27738,-6362, -2436,28204,-6533, -2436,28421,-6303, + -2556,28092,-3822, -2431,28142,-6975, -2544,27863,-6726, + -2266,28229,-1686, -1939,28156,-1065, -2569,27943,-2270, + -2381,27545,-1682, -2799,27594,-3104, -2750,27866,-2738, + -2539,27578,-6309, -2720,26853,-3133, -2788,26461,-3776, + -1061,27543,-7078, -1780,27941,135, -1859,27747,-527, -1756,27784,691, + -1855,27001,736, -1950,26711,19, -1964,27006,-630, -2342,26955,-1898, + -2595,25515,-3113, -2147,27855,132, -2126,27722,601, -2213,27691,-428, + -2210,27061,639, -2290,26816,34, -2302,27065,-515, -2347,27680,100, + -2335,27602,376, -2386,27584,-229, -2385,27213,398, -2432,27069,42, + -2439,27215,-281, -2481,27452,103, -1786,24263,399, -2278,24851,-562, + -2372,25143,-1163, 7383,9172,0, 7270,9172,-1487, 6937,9172,-2929, + 6393,9172,-4281, 1282,9172,-8433, 0,9172,-8563, 1301,9439,8159, + 2371,9313,7844, 3857,9286,7355, 4477,9172,6559, 5704,9174,5179, + 6393,9172,4281, 6937,9172,2929, 7270,9172,1487, -7270,9172,-1487, + -6937,9172,-2929, -6393,9172,-4281, -1282,9172,-8433, 0,9339,8274, + -1301,9439,8159, -2371,9313,7844, -3857,9286,7355, -4477,9172,6559, + -5704,9174,5179, -6393,9172,4281, -6937,9172,2929, -7270,9172,1487, + -796,9467,8260, 0,9503,8356, 0,9667,8438, -796,9666,8325, + -807,10584,8327, -7383,9172,0, 796,9467,8260, 796,9666,8325, + 807,10584,8327, 0,10584,8457, 0,11744,8130, 1183,11744,7939, + 1183,12003,7939, 0,12003,8130, 0,14019,6737, 1183,14019,6547, + 1183,16307,5288, 0,16307,5479, 0,16555,5472, 1183,16555,5281, + 1183,20128,2191, 0,20128,2382, 0,20304,2322, 1134,20304,2131, + 1183,20516,2156, 0,20516,2346, 0,21898,2060, 1417,21874,1842, + 1417,23109,2185, 0,23133,2404, 0,23985,3339, 1417,23961,3121, + 1417,24001,4252, 0,24025,4470, 1418,23893,5418, 1151,23389,6664, + 0,23394,6882, 0,23506,7125, 1151,23501,6906, 1151,23806,6987, + 0,23811,7205, 0,24107,7205, 1151,24102,6987, 1151,24209,7189, + 0,24213,7407, 0,24376,7731, 1151,24371,7513, 1151,24605,7715, + 0,24610,7933, 0,24944,7892, 1151,24939,7674, 1313,25568,7149, + 0,25562,7367, 0,25689,7367, 1313,25695,7149, 1598,26707,7610, + 1598,27262,7839, 1598,27842,7723, 1598,28309,7303, 1302,28414,6723, + 1187,28523,5990, 1304,28447,4204, 0,28469,4435, 0,28654,1893, + 1158,28789,1627, 561,28931,-1220, 0,29310,-864, 0,29574,-1062, + 357,29608,-1244, 357,30527,-1441, 0,30496,-1259, 0,31221,-1655, + 357,31249,-1837, 357,31511,-2627, 0,31485,-2445, 0,31485,-3302, + 357,31511,-3484, 357,31118,-4143, 0,31089,-3961, 0,30233,-4356, + 357,30264,-4538, 436,29406,-5256, 0,29018,-6407, 2207,29018,-6763, + 914,28658,-6964, 0,28472,-7040, 1305,26324,-7143, 806,23401,-6784, + 0,23246,-6890, 0,20735,-6319, 812,20723,-6228, 796,16757,-6210, + 0,17171,-6133, 1559,24934,7435, 1566,24633,7460, 1531,24429,7334, + 1475,24293,7131, 1440,24203,7004, 1372,23935,7015, 1364,23606,6868, + 1389,23515,6705, 1687,28010,6952, 1687,27926,7343, 1687,27629,7491, + 1687,27324,7552, 1687,27032,7432, 1687,26791,7148, 1642,27135,7165, + 1642,27254,7304, 1642,27397,7364, 1642,27546,7334, 1642,27693,7261, + 1642,27737,7088, 1611,10591,8159, 888,9327,-8560, 4491,13292,1032, + 3840,15084,786, 3412,17397,397, 2937,20005,-35, 5108,11669,1240, + 6344,10251,1395, 6345,10246,1248, 5109,11664,1092, 2964,20022,-132, + 3413,17393,250, 3841,15079,638, 4491,13288,885, 3743,13207,-535, + 3085,15092,-710, 2727,17642,-878, 2569,20636,-797, 4348,11575,-324, + 5584,10108,-169, 5403,10079,-1732, 4167,11644,-1888, + 2465,20842,-2651, 2522,18130,-2392, 2905,15407,-2077, + 3562,13227,-1951, 3901,13568,-3294, 3243,15993,-3519, + 2861,18863,-3735, 2776,22447,-4309, 4486,11792,-3132, 5783,9930,-2931, + 5783,9930,-3054, 4486,11792,-3255, 2776,22438,-4430, 2861,18863,-3858, + 3243,15993,-3641, 3901,13568,-3417, 6199,9466,4558, 5766,10642,5726, + 5228,11829,6090, 4801,12891,6048, 4155,14560,5246, 3546,16847,3719, + 3334,17643,2937, 2860,20062,1230, 4822,12054,7102, 5325,10909,7208, + 5732,9938,6026, 4026,14701,5522, 2852,20170,1447, 3319,17801,3175, + 3538,16955,3935, 4090,13256,1679, 2874,20073,676, 3706,15083,1464, + 3301,17348,1117, 5931,10206,1996, 4695,11624,1840, 4445,11658,2844, + 5681,10240,3000, 3074,17398,2202, 3456,15117,2468, 3840,13290,2683, + 4642,13358,4019, 4257,15194,3908, 6017,10188,3746, 5237,11714,4039, + 5621,11218,5077, 5026,12862,5058, 5134,10861,-3154, 4193,12680,-3336, + 2832,20609,-4118, 3052,17428,-3750, 3572,14780,-3529, + 3579,14774,-3623, 3059,17422,-3843, 2839,20596,-4211, + 4200,12674,-3429, 5141,10855,-3248, 3908,13562,-3510, + 3250,15987,-3735, 2868,18857,-3952, 4492,11786,-3348, 5789,9924,-3148, + 4817,11321,-3298, 5465,10389,-3198, 4054,13118,-3470, + 4346,12230,-3389, 2853,19681,-4056, 2825,21511,-4367, + 3155,16705,-3789, 2963,18140,-3897, 3744,14168,-3567, + 3415,15381,-3679, 0,14037,-6616, 845,13482,-6604, 945,10997,-7893, + 0,11066,-7866, 981,11110,-7735, 859,13469,-6526, 899,9307,-8439, + 813,16486,-6146, 832,20681,-6100, 826,23358,-6656, 882,10149,-8148, + 913,12323,-7139, 822,14910,-6353, 817,18235,-6210, 827,21937,-6382, + 846,21937,-6341, 841,14912,-6313, 931,12326,-7098, 901,10152,-8107, + 844,23359,-6615, 851,20681,-6059, 831,16487,-6105, 919,9307,-8399, + 869,13482,-6492, 999,11113,-7694, 860,9726,-8255, 942,10578,-7958, + 962,11715,-7413, 900,12896,-6796, 863,14065,-6404, 818,15760,-6221, + 828,17367,-6171, 854,19800,-5994, 848,21309,-6200, 843,22566,-6482, + 3407,15409,-3785, 3736,14196,-3673, 2911,18365,-4048, + 3147,16733,-3895, 2726,21608,-4455, 2808,19905,-4191, + 4338,12259,-3495, 4046,13146,-3576, 5457,10418,-3304, + 4809,11349,-3404, 4484,11815,-3454, 2715,22288,-4534, + 2832,19035,-4066, 3242,16015,-3841, 3900,13590,-3616, + 5133,10883,-3354, 4171,12742,-3524, 2803,20773,-4339, + 3051,17450,-3949, 3571,14803,-3729, 4979,11072,-3368, + 5619,10185,-3279, 4119,12924,-3556, 4411,12037,-3475, + 2801,20363,-4269, 2721,21826,-4489, 3099,17092,-3922, + 2887,18618,-4038, 3653,14499,-3701, 3325,15712,-3813, + 3489,15106,-3757, 3818,13893,-3645, 3011,17758,-3971, + 3194,16374,-3868, 2755,21085,-4385, 2815,19494,-4139, + 4265,12481,-3515, 3973,13368,-3596, 5304,10595,-3318, + 4664,11477,-3407, 5441,10207,-3361, 5350,10338,-3375, + 5139,10672,-3428, 5058,10742,-3431, 4831,11101,-3457, + 4742,11228,-3470, 4516,11559,-3504, 4423,11693,-3518, + 4277,12079,-3558, 4232,12180,-3571, 4138,12522,-3597, + 4094,12603,-3609, 3979,12935,-3675, 3943,13043,-3671, + 3852,13383,-3699, 3813,13496,-3705, 3692,13947,-3767, + 3653,14073,-3790, 3506,14587,-3772, 3467,14685,-3777, + 3349,15192,-3888, 3308,15317,-3887, 3162,15800,-3957, + 3119,15954,-3961, 3009,16528,-3946, 3002,16637,-3937, + 2914,17260,-4014, 2909,17347,-4006, 2834,17893,-4049, + 2813,18060,-4060, 2760,18849,-4232, 2746,18968,-4242, 850,22569,-6438, + 855,21313,-6156, 860,19804,-5949, 834,17371,-6127, 824,15765,-6176, + 869,14070,-6360, 906,12901,-6751, 968,11720,-7368, 948,10645,-7895, + 865,9731,-8211, 1006,11164,-7630, 875,13487,-6447, 926,9310,-8354, + 837,16490,-6061, 857,20684,-6015, 867,23379,-6515, 907,10157,-8062, + 937,12331,-7053, 847,14917,-6268, 842,18236,-6111, 852,21941,-6297, + 885,9891,-8156, 985,10905,-7724, 947,11969,-7255, 885,13125,-6649, + 858,14493,-6314, 839,16049,-6111, 836,17735,-6083, 859,20244,-5982, + 891,21559,-6157, 848,22883,-6508, 851,22255,-6367, 856,20999,-6085, + 867,19042,-6000, 836,16930,-6094, 835,15341,-6222, 880,13646,-6405, + 916,12540,-6953, 981,11337,-7564, 927,10370,-7988, 932,9518,-8285, + 931,9583,-8174, 863,9671,-8145, 892,9982,-8037, 903,10075,-7996, + 952,10454,-7865, 961,10550,-7832, 1008,10963,-7617, 1018,11105,-7567, + 996,11458,-7405, 992,11582,-7342, 972,12080,-7057, 968,12210,-6984, + 935,12620,-6792, 931,12759,-6714, 914,13199,-6441, 910,13346,-6359, + 915,13767,-6194, 910,13941,-6175, 890,14633,-6107, 886,14783,-6091, + 864,15476,-6035, 859,15645,-6017, 870,16062,-5957, 873,16231,-5936, + 853,17048,-5965, 861,17185,-5974, 879,17812,-5997, 885,17961,-5997, + 851,18486,-6138, 865,18526,-5933, 872,18761,-5875, 870,19337,-5971, + 864,19470,-5784, 937,19590,-5786, 833,19023,-6126, 851,20344,-5894, + 851,20576,-5912, 855,21086,-5973, 854,21224,-6003, 871,21651,-6070, + 852,21853,-6116, 850,22332,-6224, 849,22490,-6259, 831,22924,-6338, + 834,23240,-6364, 2743,19661,-4287, 2740,19863,-4312, 2723,20501,-4469, + 2705,20711,-4503, 2661,21262,-4565, 2658,21427,-4593, + 2687,22088,-4631, 2695,22209,-4643, 2774,23170,-4392, + 2633,23103,-4527, 2681,22439,-4516, 2656,22665,-4573, + 2552,22727,-4653, 2534,23015,-4628, 2607,23397,-4556, + 2759,23681,-4398, 2740,24136,-4370, 2610,24100,-4580, + 2412,24481,-5089, 2671,24389,-4569, 2397,24935,-5652, + 2562,25022,-5528, 939,23708,-6566, 1009,24359,-6776, 1095,24912,-6886, + 1049,24117,-6493, 990,23894,-6415, 2290,23837,-4814, 2312,23612,-4723, + 2183,24804,-5574, 2191,24632,-5391, 1156,24771,-6650, + 1154,24624,-6586, 1104,24526,-6656, 0,9161,-8562, 1281,9161,-8432, + 2524,9161,-8046, 3691,9161,-7572, 4745,9161,-6945, 5662,9127,-6096, + 3697,9192,-7581, 2531,9192,-8056, 4753,9183,-6951, 5664,9161,-6101, + 5664,9185,-6101, 4753,9207,-6951, 2531,9216,-8055, 3697,9216,-7581, + 3684,9232,-7560, 2518,9232,-8034, 4740,9223,-6930, 5651,9200,-6080, + 2828,20259,1366, 2798,20256,1187, 2820,20237,692, 2843,20292,-25, + 2874,20473,735, 2975,20508,90, 2474,20772,-759, 2660,20879,-691, + 2471,21553,-1445, 2498,22175,-1940, 2471,24346,-2830, + 2556,22373,-1903, 2528,21595,-1351, 2493,24314,-2936, + 2576,22239,-2123, 2548,21461,-1571, 2823,20635,1307, 2741,20503,1328, + 1490,23972,5392, 1489,24080,4226, 1489,24040,3095, 1489,23188,2159, + 1489,21953,1816, 2479,22156,182, 1515,23830,2117, 1605,24415,3131, + 1599,24460,4263, 1580,24357,5431, 1448,23885,6743, 1252,24770,5442, + 1271,24873,4274, 1277,24828,3142, 1389,24618,2016, 1479,24733,1993, + 1301,25010,3165, 1295,25055,4297, 1391,24890,5460, 1512,25216,5507, + 1602,25353,4317, 1608,25308,3186, 1979,23458,-29, 1320,25312,1928, + 1495,25055,546, 2438,25790,-488, 1605,25585,5599, 1583,26793,6150, + 1850,26272,4298, 1578,27435,7117, 1658,27625,6884, 1671,27398,6846, + 1678,27176,6937, 1715,27784,6626, 1744,27323,6551, 1753,26904,6776, + 1884,28809,-1688, 1555,28655,1620, 1658,28252,4204, 1581,28263,5997, + 1567,28312,6790, 1935,27827,4220, 1818,28249,1603, 1570,27742,6195, + 1532,27288,6120, 2038,27074,4245, 1418,28416,228, 413,30264,-4539, + 424,31094,-4152, 418,31478,-3497, 410,31453,-2653, 410,31190,-1863, + 410,30468,-1467, 410,29550,-1270, 411,31041,-1902, 448,31253,-2696, + 449,31323,-3466, 425,31182,-3496, 411,31060,-2738, 387,30899,-1932, + 316,30806,-1957, 335,30952,-2766, 353,31089,-3521, 322,31007,-3540, + 303,30871,-2786, 284,30725,-1976, 304,30630,-1993, 323,30776,-2802, + 342,30912,-3557, 396,30843,-3565, 378,30707,-2811, 358,30561,-2001, + 414,30477,-2013, 433,30623,-2822, 452,30759,-3576, 474,30560,-3616, + 456,30424,-2861, 436,30278,-2052, 349,30194,-2077, 368,30340,-2886, + 386,30477,-3641, 309,30389,-3665, 291,30253,-2911, 271,30107,-2102, + 267,29996,-2124, 286,30142,-2933, 305,30278,-3688, 376,30179,-3700, + 357,30043,-2945, 338,29897,-2136, 420,29789,-2150, 439,29935,-2959, + 458,30071,-3713, 500,29883,-3751, 463,29601,-2187, 470,30974,-4049, + 462,30153,-4391, 466,30563,-4220, 410,30009,-1368, 725,29372,-3225, + 677,29335,-5130, 908,29205,-3300, 632,29533,-4803, 2587,28768,-3408, + 2730,28611,-3456, 2404,28568,-6916, 2413,28849,-6612, + 1904,26715,1801, 1394,25919,831, 2224,27270,-3994, 2730,28438,-3011, + 2587,28570,-2864, 2826,28152,-3163, 2476,28668,-6523, + 2476,28433,-6776, 2787,28338,-3507, 2216,27658,-3972, + 2207,27950,-5907, 2311,28216,-6128, 2320,27876,-3971, + 2311,28118,-6301, 2311,27845,-6252, 2320,27703,-3749, + 2320,27084,-3798, 2320,26986,-4070, 2698,26705,-4014, + 2557,26974,-3547, 2557,27739,-3485, 2572,27738,-6362, + 2436,28204,-6533, 2436,28421,-6303, 2556,28092,-3822, + 2431,28142,-6975, 2544,27863,-6726, 2266,28229,-1686, + 1939,28156,-1065, 2569,27943,-2270, 2381,27545,-1682, + 2799,27594,-3104, 2750,27866,-2738, 2539,27578,-6309, + 2720,26853,-3133, 2788,26461,-3776, 1061,27543,-7078, 1780,27941,135, + 1859,27747,-527, 1756,27784,691, 1855,27001,736, 1950,26711,19, + 1964,27006,-630, 2342,26955,-1898, 2595,25515,-3113, 2147,27855,132, + 2126,27722,601, 2213,27691,-428, 2210,27061,639, 2290,26816,34, + 2302,27065,-515, 2347,27680,100, 2335,27602,376, 2386,27584,-229, + 2385,27213,398, 2432,27069,42, 2439,27215,-281, 2481,27452,103, + 1786,24263,399, 2278,24851,-562, 2372,25143,-1163, -2567,23141,-2607, + -2513,23156,-2494, 2513,23156,-2494, 2567,23141,-2607, + + TRIANGLES, 657,656,159, 100,506,99, 1003,900,995, 1048,1009,901, + 1051,901,1009, 1070,1073,1071, 1070,803,808, 1071,1077,1070, + 1072,1006,1073, 1072,808,915, 1073,808,1072, 1077,1071,1076, + 1078,1283,1127, 1081,1078,1079, 1081,1079,1080, 1083,1082,1086, + 1083,747,1274, 1084,888,1085, 1085,878,1086, 1085,1086,1095, + 1086,747,1083, 1093,1095,1086, 1094,1095,1093, 658,657,149, + 1101,637,32, 1103,638,1108, 1105,637,1101, 1106,637,1105, + 1108,638,1111, 111,36,158, 111,653,665, 111,665,36, 1110,858,1112, + 1111,988,1110, 1111,638,891, 1111,891,988, 1112,858,1113, + 1113,637,1106, 1117,779,784, 112,214,207, 112,651,210, 1124,1297,1154, + 1125,1123,1128, 1125,1302,1154, 1127,1077,1078, 1129,791,796, + 1130,1118,1137, 1136,1130,1137, 1137,1118,1119, 1137,1119,1121, + 1137,1121,1126, 1142,758,759, 1142,759,760, 1142,760,761, + 1147,1146,1154, 1150,755,756, 1150,756,757, 1154,1302,1124, + 1155,1147,1154, 1155,1297,1156, 1155,1154,1297, 1156,1240,1155, + 1156,1298,1157, 1157,1240,1156, 1157,1299,1273, 1157,1282,1281, + 1158,1151,1152, 1161,768,1164, 1162,773,1161, 1162,1161,1163, + 1163,1161,1164, 1165,1172,762, 1168,726,1178, 1168,1267,1266, + 1169,1178,725, 1171,1172,1165, 1171,720,1172, 1171,1165,1175, + 1178,1169,1174, 1178,1174,1278, 1179,1229,1228, 118,660,168, + 1180,1229,1179, 1185,726,1226, 1186,1183,1184, 1186,1184,1191, + 119,660,118, 1191,1184,1192, 1192,1184,1197, 1197,1184,1198, + 1198,1184,1203, 1203,1184,1204, 121,116,451, 1210,1209,1230, + 1215,1210,1230, 1216,1215,1230, 1221,1216,1230, 1222,1185,1226, + 1222,1221,1230, 1223,1222,1226, 1224,1223,1225, 1225,1223,1226, + 1226,726,1231, 1227,1188,1189, 1227,1189,1194, 1227,1194,1195, + 1227,1195,1200, 1227,1200,1201, 1227,1201,1206, 1228,1224,1225, + 1228,1225,1234, 1229,1207,1212, 1229,1212,1213, 1229,1213,1218, + 1229,1218,1219, 1229,1219,1224, 1229,1180,1227, 1229,1224,1228, + 1230,729,1185, 1230,1185,1222, 1231,1225,1226, 1232,1179,1234, + 1233,744,1232, 1234,1179,1228, 1234,1225,1231, 1235,744,1233, + 1237,744,1238, 1239,1155,1240, 1240,1157,1239, 1243,1168,1266, + 1248,1241,1249, 1250,1249,1252, 1252,1249,1253, 1254,1248,1251, + 1256,1241,1255, 1259,1244,1270, 1264,745,1237, 1265,1260,1272, + 1267,1168,1178, 1267,1178,1277, 1269,1282,1270, 1270,1282,1273, + 1271,1268,1269, 1271,1269,1270, 1273,1283,1274, 1274,1078,1081, + 1274,1081,1083, 1274,747,1275, 1275,745,1264, 1275,1264,1265, + 1275,1265,1272, 1275,1272,1274, 1276,1178,1278, 1277,1178,1276, + 1280,1157,1281, 1281,1269,1277, 1282,1157,1273, 1282,1269,1281, + 1283,1078,1274, 1292,1290,1296, 1295,1292,1296, 1296,1290,1291, + 1296,1291,1293, 1296,1293,1294, 1296,1294,1295, 1297,1298,1156, + 1297,1124,1298, 1298,1124,1299, 1299,1124,1273, 1299,1157,1298, + 660,659,168, 133,128,463, 137,182,141, 138,185,137, 139,184,138, + 140,183,139, 141,181,142, 141,182,144, 142,181,143, 143,649,142, + 143,197,195, 144,196,181, 144,199,194, 145,183,140, 145,201,183, + 145,140,405, 146,184,139, 146,139,183, 146,203,184, 147,185,138, + 147,138,184, 147,205,185, 148,198,182, 148,137,185, 149,657,159, + 150,149,159, 151,150,157, 152,151,157, 153,152,157, 157,150,158, + 157,38,160, 157,37,38, 158,150,159, 160,153,157, 160,39,163, + 160,38,39, 162,41,161, 163,39,40, 168,659,171, 172,155,156, + 176,153,154, 176,154,155, 177,658,149, 179,149,150, 179,150,151, + 180,152,153, 181,197,143, 181,141,144, 181,196,190, 182,199,144, + 182,137,148, 182,198,189, 183,200,146, 184,202,147, 185,204,148, + 186,204,185, 186,267,204, 186,185,205, 187,202,184, 187,265,202, + 187,184,203, 188,200,183, 188,263,200, 188,183,201, 189,275,199, + 189,261,255, 190,277,197, 190,259,254, 191,276,198, 191,148,204, + 192,205,147, 192,147,202, 192,268,205, 193,203,146, 193,146,200, + 193,266,203, 194,278,196, 194,262,249, 196,259,190, 196,144,194, + 196,278,248, 197,181,190, 197,260,195, 197,277,247, 198,261,189, + 198,148,191, 198,276,246, 199,182,189, 199,262,194, 199,275,245, + 200,274,193, 201,273,188, 202,272,192, 203,271,187, 204,270,191, + 205,269,186, 206,215,209, 206,216,90, 207,215,206, 207,214,208, + 208,231,215, 208,230,228, 209,233,216, 209,232,227, 210,229,214, + 210,651,226, 211,235,217, 211,234,225, 212,237,218, 212,236,224, + 212,386,236, 213,238,223, 213,421,88, 214,230,208, 214,112,210, + 214,229,222, 215,207,208, 215,232,209, 215,231,221, 216,206,209, + 216,234,211, 216,233,220, 217,90,211, 217,386,212, 218,89,212, + 218,238,213, 218,237,219, 219,342,238, 219,340,331, 220,346,234, + 220,336,329, 221,348,232, 221,334,328, 222,350,230, 222,332,327, + 223,341,326, 224,343,237, 224,339,325, 225,345,235, 225,337,324, + 226,351,229, 226,651,445, 227,347,233, 227,335,322, 228,349,231, + 228,333,321, 229,332,222, 229,210,226, 229,351,320, 230,214,222, + 230,333,228, 230,350,319, 231,334,221, 231,208,228, 231,349,318, + 232,215,221, 232,335,227, 232,348,317, 233,336,220, 233,209,227, + 233,347,316, 234,216,220, 234,337,225, 234,346,315, 235,211,225, + 235,345,314, 236,339,224, 236,383,313, 236,344,383, 237,340,219, + 237,212,224, 237,343,312, 238,218,219, 238,341,223, 238,342,311, + 239,269,205, 239,205,268, 240,270,204, 240,204,267, 241,271,203, + 241,203,266, 242,272,202, 242,202,265, 243,273,201, 243,201,264, + 244,274,200, 244,200,263, 250,145,407, 251,266,193, 251,193,274, + 252,268,192, 252,192,272, 253,191,270, 256,263,188, 256,188,273, + 257,265,187, 257,187,271, 258,267,186, 258,186,269, 259,196,248, + 22,650,435, 260,197,247, 261,198,246, 262,199,245, 21,650,22, + 275,189,255, 276,191,253, 277,190,254, 278,194,249, 323,226,445, + 330,217,235, 330,235,338, 332,229,320, 333,230,319, 334,231,318, + 335,232,317, 336,233,316, 337,234,315, 338,235,314, 339,236,313, + 664,653,661, 340,237,312, 341,238,311, 342,219,331, 343,224,325, + 344,236,386, 345,225,324, 346,220,329, 347,227,322, 348,221,328, + 349,228,321, 665,653,664, 350,222,327, 351,226,323, 380,217,330, + 405,408,145, 405,412,406, 406,408,405, 407,145,408, 408,341,407, + 411,406,412, 413,412,461, 414,413,416, 415,414,416, 416,413,608, + 418,87,421, 418,416,608, 419,223,326, 420,213,223, 420,223,419, + 421,417,418, 421,213,420, 421,430,428, 421,87,88, 428,430,429, + 430,421,420, 435,650,439, 439,650,440, 440,650,447, 442,651,437, + 444,195,323, 444,323,445, 445,651,442, 446,195,444, 447,650,195, + 447,195,446, 453,452,471, 455,453,471, 460,455,471, 461,617,413, + 462,457,459, 465,43,44, 471,452,464, 471,464,470, 486,485,492, + 488,458,1301, 488,631,458, 488,1301,459, 488,480,481, 488,481,489, + 489,574,490, 490,631,489, 490,574,491, 490,632,631, 491,632,490, + 495,105,106, 495,106,107, 495,107,108, 495,108,109, 495,109,110, + 495,110,496, 497,495,496, 498,105,495, 498,495,497, 499,506,505, + 505,68,71, 506,68,505, 506,67,68, 508,503,512, 509,499,505, + 512,74,502, 512,502,601, 513,563,514, 518,517,520, 518,564,76, + 519,75,564, 519,74,75, 523,522,561, 525,518,520, 526,518,525, + 528,523,561, 529,528,561, 531,518,526, 532,518,531, 534,529,561, + 535,534,561, 537,518,532, 538,518,537, 540,535,561, 546,541,563, + 547,546,563, 552,547,563, 553,552,563, 556,519,564, 558,553,563, + 559,557,558, 559,558,562, 560,74,519, 560,519,556, 560,556,557, + 560,557,559, 560,559,565, 561,514,563, 562,563,513, 562,558,563, + 562,513,568, 564,543,544, 564,544,549, 564,549,550, 564,550,555, + 564,555,556, 565,74,560, 565,559,568, 566,84,567, 567,84,569, + 568,559,562, 568,513,566, 571,85,598, 571,84,85, 572,84,571, + 573,491,574, 574,489,573, 583,575,582, 585,582,588, 586,583,584, + 587,583,586, 589,575,590, 598,85,609, 599,598,609, 653,111,654, + 600,601,502, 600,502,577, 603,602,605, 604,578,593, 604,616,603, + 604,603,605, 606,594,599, 606,599,609, 607,633,491, 607,616,604, + 607,491,616, 607,458,633, 608,87,418, 608,617,607, 608,606,609, + 608,413,617, 609,87,608, 609,86,87, 610,512,611, 611,512,601, + 611,603,615, 612,508,512, 612,512,610, 615,616,491, 615,491,614, + 615,603,616, 625,624,630, 627,625,630, 628,627,630, 629,628,630, + 630,624,626, 630,626,629, 631,488,489, 632,458,631, 632,491,633, + 633,458,632, 639,651,112, 641,774,640, 32,637,33, 667,640,668, + 668,640,669, 669,640,774, 67,506,100, 672,669,774, 676,673,820, + 677,676,823, 680,677,826, 688,685,1131, 712,711,754, 720,719,1172, + 721,720,1171, 725,1178,726, 729,726,1185, 729,1230,730, 73,512,503, + 730,1230,1184, 74,512,73, 743,82,83, 745,744,1237, 745,743,744, + 745,1275,746, 746,85,743, 746,743,745, 746,609,85, 746,1275,86, + 747,86,1275, 748,747,1086, 748,883,751, 748,1086,878, 751,882,752, + 752,881,870, 76,564,75, 762,1172,763, 763,1172,719, 769,768,1161, + 770,769,1161, 771,770,1161, 772,771,1161, 773,772,1161, 774,641,642, + 775,638,639, 781,647,782, 655,654,111, 800,848,801, 801,847,802, + 801,848,810, 802,846,803, 802,847,809, 803,846,808, 804,845,800, + 805,844,804, 805,636,806, 806,844,805, 806,860,844, 807,845,804, + 807,804,844, 807,862,845, 808,1073,1070, 809,863,846, 809,866,856, + 810,865,847, 810,868,855, 811,800,845, 811,867,848, 812,644,645, + 812,645,840, 813,812,842, 814,813,842, 816,815,843, 817,816,839, + 818,817,839, 819,818,835, 820,813,814, 820,814,815, 820,815,816, + 820,816,823, 821,672,774, 821,813,820, 822,642,643, 822,643,644, + 822,644,812, 822,812,813, 822,813,821, 823,676,820, 824,681,825, + 826,677,823, 83,742,743, 831,646,647, 831,647,781, 834,646,831, + 844,859,807, 845,861,811, 846,864,808, 846,802,809, 846,863,851, + 847,866,809, 847,801,810, 847,865,850, 848,868,810, 848,800,811, + 848,867,849, 849,934,868, 849,932,923, 85,84,743, 850,936,866, + 850,930,922, 851,938,864, 851,928,921, 852,861,845, 852,926,861, + 852,845,862, 853,859,844, 853,924,859, 853,844,860, 854,811,861, + 854,935,867, 855,937,865, 855,933,917, 856,939,863, 856,931,916, + 857,862,807, 857,807,859, 857,927,862, 858,637,1113, 858,860,806, + 858,925,860, 859,943,857, 86,609,746, 860,942,853, 861,941,854, + 862,940,852, 863,928,851, 863,809,856, 863,939,909, 864,846,851, + 864,938,908, 865,930,850, 865,810,855, 865,937,907, 866,847,850, + 866,931,856, 866,936,906, 867,932,849, 867,811,854, 867,935,905, + 868,848,849, 868,933,855, 868,934,904, 870,880,871, 871,879,775, + 873,879,871, 873,895,879, 873,871,880, 874,880,870, 874,897,880, + 874,870,881, 875,638,775, 875,775,879, 876,881,752, 876,899,881, + 876,752,882, 877,882,751, 877,1051,882, 877,751,883, 878,883,748, + 878,903,883, 879,894,875, 88,218,213, 880,896,873, 881,898,874, + 882,900,876, 883,902,877, 884,902,883, 884,1005,902, 884,883,903, + 885,898,881, 885,1001,898, 885,881,899, 886,896,880, 886,999,896, + 886,880,897, 887,894,879, 887,997,894, 887,879,895, 888,878,1085, + 888,903,878, 888,1006,903, 889,901,877, 889,1004,901, 889,877,902, + 89,217,212, 89,218,88, 890,899,876, 890,1002,899, 890,876,900, + 891,638,875, 891,875,894, 892,897,874, 892,1000,897, 892,874,898, + 893,895,873, 893,998,895, 893,873,896, 894,1016,891, 895,1015,887, + 896,1014,893, 897,1013,886, 898,1012,892, 899,1011,885, 656,655,159, + 90,216,211, 90,217,89, 900,1010,890, 900,882,995, 901,1051,877, + 902,1008,889, 903,1007,884, 91,57,58, 910,940,862, 910,862,927, + 911,941,861, 911,861,926, 912,942,860, 912,860,925, 913,943,859, + 913,859,924, 914,927,857, 914,857,943, 918,854,941, 919,924,853, + 919,853,942, 920,926,852, 920,852,940, 928,863,909, 929,864,908, + 93,92,484, 930,865,907, 931,866,906, 932,867,905, 933,868,904, + 934,849,923, 935,854,918, 936,850,922, 937,855,917, 938,851,921, + 939,856,916, 94,93,484, 96,95,476, 97,96,476, 976,903,1006, + 976,1007,903, 977,902,1005, 977,1008,902, 978,901,1004, 978,1048,901, + 979,900,1003, 979,1010,900, 98,97,476, 980,899,1002, 980,1011,899, + 981,898,1001, 981,1012,898, 982,897,1000, 982,1013,897, 983,1014,896, + 983,896,999, 984,1015,895, 984,895,998, 985,1016,894, 985,894,997, + 986,893,1014, 986,998,893, 987,892,1012, 987,1000,892, 988,891,1016, + 988,858,1110, 989,890,1010, 989,1002,890, 99,506,499, 990,889,1008, + 990,1004,889, 991,888,1084, 991,1006,888, 992,887,1015, 992,997,887, + 993,886,1013, 993,999,886, 994,885,1011, 994,1001,885, 995,882,1045, + 996,884,1007, 996,1005,884, + + QUADS, 648,666,130,131, 648,649,20,19, 657,658,15,14, + 1000,987,1032,1031, 1001,994,1036,1035, 1002,989,1040,1039, + 1003,995,1044,1043, 1004,990,1053,1052, 1005,996,1057,1056, + 1006,991,1061,1060, 1007,976,1059,1058, 1008,977,1055,1054, + 1009,906,973,1047, 101,64,67,100, 1010,979,1042,1041, + 1011,980,1038,1037, 1012,981,1034,1033, 1013,982,1030,1029, + 1014,983,1026,1025, 1015,984,1022,1021, 1016,985,1018,1017, + 102,63,64,101, 103,60,63,102, 104,59,60,103, 1045,882,1051,1009, + 1045,1009,1047,1046, 1048,978,1050,1049, 105,104,103,106, + 106,103,102,107, 1061,991,1071,1075, 1062,939,1004,1052, + 1062,1052,1053,1063, 1063,909,939,1062, 1064,928,1008,1054, + 1064,1054,1055,1065, 1065,921,928,1064, 1066,938,1005,1056, + 1066,1056,1057,1067, 1067,908,938,1066, 1068,929,1007,1058, + 1068,1058,1059,1069, 1069,915,929,1068, 107,102,101,108, + 1071,991,1084,1076, 1072,915,976,1006, 1073,1006,1060,1074, + 1074,1060,1061,1075, 1075,1071,1073,1074, 1078,1077,1076,1079, + 108,101,100,109, 1080,1079,1085,1095, 1081,1080,1082,1083, + 1082,1080,1092,1091, 1084,1085,1087,1088, 1085,1079,1089,1087, + 1086,1082,1091,1093, 1088,1087,1089,1090, 1089,1079,1076,1090, + 109,100,99,110, 1090,1076,1084,1088, 1092,1080,1095,1094, + 1093,1091,1092,1094, 1096,27,26,431, 1097,638,1103,1098, + 658,659,16,15, 110,99,499,496, 1100,1099,1102,1104, + 1101,1100,1104,1105, 1102,1099,1098,1103, 1106,1105,1104,1107, + 1107,1104,1102,1109, 1109,1102,1103,1108, 1110,1109,1108,1111, + 1112,1107,1109,1110, 1113,1106,1107,1112, 1115,819,828,1116, + 1117,784,791,1120, 1118,1116,1117,1119, 1119,1117,1120,1121, + 1120,791,1129,1122, 1121,1120,1122,1126, 1122,1123,1125,1126, + 1126,1125,1154,1137, 1127,1124,1302,1303, 1128,1123,1122,1129, + 1128,803,1070,1303, 1129,796,803,1128, 113,114,123,124, + 1130,1115,1116,1118, 1131,1114,1115,1130, 1132,1133,1140,1141, + 1133,1134,1139,1140, 1134,1135,1138,1139, 1136,688,1131,1130, + 1138,1135,1136,1137, 1138,1137,1154,1146, 1139,1138,1146,1145, + 114,115,122,123, 1140,1139,1145,1144, 1141,1140,1144,1143, + 1142,761,1132,1141, 1143,758,1142,1141, 1143,1144,1149,1150, + 1144,1145,1148,1149, 1145,1146,1147,1148, 1148,1147,1155,1153, + 1149,1148,1153,1152, 115,116,121,122, 115,114,166,167, + 1150,757,758,1143, 1150,1149,1152,1151, 1151,754,755,1150, + 1158,712,754,1151, 1158,1152,1160,1159, 1160,1152,1153,1155, + 1160,1155,1239,1177, 1165,762,773,1162, 1165,1162,1163,1166, + 1166,1163,1164,1167, 1167,1159,1176,1166, 1169,1170,1173,1174, + 1173,1170,1171,1175, 1174,1173,1177,1239, 1175,1165,1166,1176, + 1176,1159,1160,1177, 1177,1173,1175,1176, 1182,1183,1186,1187, + 1187,1186,1191,1190, 1188,1181,1182,1187, 1189,1188,1187,1190, + 119,118,117,120, 1190,1191,1192,1193, 1193,1192,1197,1196, + 1194,1189,1190,1193, 1195,1194,1193,1196, 1196,1197,1198,1199, + 1199,1198,1203,1202, 659,660,17,16, 659,658,177,171, 120,117,113,124, + 1200,1195,1196,1199, 1201,1200,1199,1202, 1202,1203,1204,1205, + 1204,1184,1230,1209, 1205,1204,1209,1208, 1206,1201,1202,1205, + 1207,1206,1205,1208, 1208,1209,1210,1211, 1211,1210,1215,1214, + 1212,1207,1208,1211, 1213,1212,1211,1214, 1214,1215,1216,1217, + 1217,1216,1221,1220, 1218,1213,1214,1217, 1219,1218,1217,1220, + 122,121,128,127, 1220,1221,1222,1223, 1224,1219,1220,1223, + 1227,1180,1181,1188, 1227,1206,1207,1229, 123,122,127,126, + 1231,726,1168,1233, 1233,1168,1243,1235, 1234,1231,1233,1232, + 1236,1235,1243,1242, 1236,1242,1244,1247, 1237,1238,1245,1246, + 1238,744,1235,1236, 1239,1157,1280,1279, 124,123,126,125, + 1244,1242,1271,1270, 1245,1238,1236,1247, 1246,1245,1262,1261, + 1247,1244,1259,1263, 1249,1241,1256,1253, 125,126,135,136, + 1251,1248,1249,1250, 1251,1250,1262,1263, 1254,1251,1263,1259, + 1255,1241,1248,1254, 1257,1256,1255,1258, 1258,1255,1254,1259, + 126,127,134,135, 1260,1253,1256,1257, 1261,1252,1253,1260, + 1262,1250,1252,1261, 1262,1245,1247,1263, 1264,1237,1246,1265, + 1265,1246,1261,1260, 1268,1243,1266,1269, 1269,1266,1267,1277, + 127,128,133,134, 1271,1242,1243,1268, 1272,1260,1257,1274, + 1273,1258,1259,1270, 1273,1124,1127,1283, 1274,1257,1258,1273, + 1278,1174,1239,1279, 128,121,451,454, 1284,1276,1278,1285, + 1285,1278,1279,1287, 1286,1277,1276,1284, 1287,1279,1280,1288, + 1288,1280,1281,1289, 1289,1281,1277,1286, 129,120,124,125, + 1290,1284,1285,1291, 1291,1285,1287,1293, 1292,1286,1284,1290, + 1293,1287,1288,1294, 1294,1288,1289,1295, 1295,1289,1286,1292, + 660,666,18,17, 130,666,660,119, 130,119,120,129, 1301,458,461,1300, + 1301,1300,462,459, 1303,1070,1077,1127, 1303,1302,1125,1128, + 131,130,129,132, 132,129,125,136, 134,133,140,139, 135,134,139,138, + 136,135,138,137, 140,133,463,462, 141,132,136,137, 142,131,132,141, + 154,153,160,163, 158,36,37,157, 159,655,111,158, 161,156,155,162, + 161,41,42,448, 162,155,154,163, 163,40,41,162, 164,113,117,169, + 164,169,170,174, 165,116,115,167, 165,156,449,450, 166,114,113,164, + 167,166,173,172, 169,117,118,168, 170,169,168,171, 172,156,165,167, + 173,166,164,174, 174,170,178,175, 175,178,179,180, 176,155,172,173, + 176,173,174,175, 177,149,179,178, 178,170,171,177, 179,151,152,180, + 180,153,176,175, 649,648,131,142, 649,650,21,20, 201,145,250,264, + 206,90,753,869, 207,206,869,872, 263,256,400,399, 264,250,404,403, + 265,257,306,305, 266,251,310,309, 267,258,298,297, 268,252,302,301, + 269,239,300,299, 270,240,296,295, 271,241,308,307, 272,242,304,303, + 273,243,402,401, 274,244,398,397, 279,260,247,280, 280,247,320,353, + 281,277,254,282, 282,254,327,355, 283,259,248,284, 284,248,319,357, + 285,278,249,286, 286,249,321,359, 287,262,245,288, 288,245,318,361, + 289,275,255,290, 19,18,666,648, 290,255,328,363, 291,261,246,292, + 292,246,317,365, 293,276,253,294, 294,253,322,367, 296,240,316,369, + 298,258,329,371, 650,649,143,195, 300,239,315,373, 302,252,324,375, + 304,242,314,377, 306,257,330,379, 308,241,344,382, 661,653,652,662, + 310,251,313,385, 311,250,407,341, 312,256,273,340, 313,251,274,339, + 314,242,265,338, 315,239,268,337, 316,240,267,336, 317,246,276,335, + 318,245,275,334, 319,248,278,333, 662,667,668,663, 320,247,277,332, + 321,249,262,349, 322,253,270,347, 323,195,260,351, 324,252,272,345, + 325,244,263,343, 327,254,259,350, 328,255,261,348, 329,258,269,346, + 663,668,669,670, 330,257,271,380, 331,243,264,342, 332,277,281,354, + 333,278,285,358, 334,275,289,362, 335,276,293,366, 336,267,297,370, + 337,268,301,374, 338,265,305,378, 339,274,397,387, 664,661,662,663, + 340,273,401,391, 342,264,403,393, 343,263,399,389, 344,241,266,383, + 345,272,303,376, 346,269,299,372, 347,270,295,368, 348,261,291,364, + 349,262,287,360, 665,664,663,670, 350,259,283,356, 351,260,279,352, + 352,279,280,353, 353,320,351,352, 354,281,282,355, 355,327,332,354, + 356,283,284,357, 357,319,350,356, 358,285,286,359, 359,321,333,358, + 36,665,670,671, 360,287,288,361, 361,318,349,360, 362,289,290,363, + 363,328,334,362, 364,291,292,365, 365,317,348,364, 366,293,294,367, + 367,322,335,366, 368,295,296,369, 369,316,347,368, 37,36,671,674, + 370,297,298,371, 371,329,336,370, 372,299,300,373, 373,315,346,372, + 374,301,302,375, 375,324,337,374, 376,303,304,377, 377,314,345,376, + 378,305,306,379, 379,330,338,378, 38,37,674,675, 380,271,307,381, + 381,307,308,382, 382,344,380,381, 383,266,309,384, 384,309,310,385, + 385,313,383,384, 386,217,380,344, 388,325,339,387, 388,387,397,398, + 39,38,675,678, 390,312,343,389, 390,389,399,400, 392,331,340,391, + 392,391,401,402, 394,311,342,393, 394,393,403,404, 395,341,408,409, + 396,326,341,395, 396,395,409,410, 398,244,325,388, 40,39,678,679, + 400,256,312,390, 402,243,331,392, 404,250,311,394, 405,140,462,1300, + 406,326,396,410, 408,406,410,409, 41,40,679,682, 411,412,413,414, + 411,414,424,425, 412,405,1300,461, 417,415,416,418, 419,326,406,411, + 419,411,425,423, 42,41,682,683, 420,414,415,430, 422,420,419,423, + 424,414,420,422, 424,422,423,425, 426,417,421,428, 427,415,417,426, + 427,426,428,429, 43,42,683,686, 430,415,427,429, 431,651,639,1096, + 431,26,25,432, 432,25,24,433, 432,433,436,437, 433,24,23,434, + 434,23,22,435, 436,433,434,438, 436,438,441,443, 437,651,431,432, + 437,436,443,442, 438,434,435,439, 438,439,440,441, 44,43,686,687, + 441,440,447,446, 442,443,444,445, 443,441,446,444, 448,42,43,465, + 449,156,161,448, 449,448,465,464, 45,44,687,690, 450,449,464,452, + 451,116,165,450, 451,450,452,453, 454,451,453,455, 456,454,455,460, + 456,457,462,463, 459,457,456,460, 46,45,690,691, 461,458,607,617, + 463,128,454,456, 465,44,470,464, 466,98,476,475, 466,49,50,98, + 467,47,49,466, 468,46,47,467, 469,45,46,468, 47,46,691,694, + 470,44,45,469, 470,469,472,471, 472,469,468,473, 473,468,467,474, + 474,467,466,475, 476,95,477,475, 478,474,475,477, 479,473,474,478, + 48,695,696,697, 480,472,473,479, 481,480,479,482, 482,479,478,483, + 483,478,477,484, 486,483,484,485, 487,482,483,486, 487,486,494,489, + 488,459,460,471, 488,471,472,480, 489,481,482,487, 49,47,694,48, + 492,58,59,493, 493,59,104,501, 494,486,492,493, 494,493,510,511, + 497,496,499,500, 498,497,500,501, 652,640,667,662, 652,653,10,9, + 50,49,48,697, 500,499,509,510, 501,104,105,498, 502,74,565,567, + 504,72,73,503, 505,71,72,504, 505,504,507,509, 507,504,503,508, + 509,507,511,510, 51,50,697,698, 510,493,501,500, 511,507,508,573, + 513,81,82,566, 514,80,81,513, 515,79,80,514, 515,514,561,522, + 516,78,79,515, 516,515,522,521, 517,77,78,516, 518,76,77,517, + 52,51,698,701, 520,517,516,521, 521,522,523,524, 524,523,528,527, + 525,520,521,524, 526,525,524,527, 527,528,529,530, 53,52,701,702, + 530,529,534,533, 531,526,527,530, 532,531,530,533, 533,534,535,536, + 536,535,540,539, 537,532,533,536, 538,537,536,539, 539,540,541,542, + 54,53,702,705, 541,540,561,563, 542,541,546,545, 543,538,539,542, + 544,543,542,545, 545,546,547,548, 548,547,552,551, 549,544,545,548, + 55,54,705,706, 550,549,548,551, 551,552,553,554, 554,553,558,557, + 555,550,551,554, 556,555,554,557, 56,55,706,709, 564,518,538,543, + 566,82,743,84, 567,565,568,566, 569,84,572,570, 57,56,709,710, + 570,572,579,581, 573,489,494,511, 573,508,612,613, 577,502,567,569, + 577,569,570,576, 577,576,605,602, 578,576,570,581, 579,572,571,580, + 58,57,710,713, 580,571,598,599, 581,579,596,597, 582,575,589,588, + 583,582,585,584, 586,584,596,595, 587,586,595,594, 588,589,592,593, + 589,590,591,592, 59,58,713,714, 590,575,583,587, 590,587,594,591, + 591,594,606,608, 592,591,608,607, 593,578,581,597, 593,592,607,604, + 595,580,599,594, 596,579,580,595, 596,584,585,597, 597,585,588,593, + 653,654,11,10, 60,59,714,61, 600,577,602,603, 601,600,603,611, + 605,576,578,604, 61,716,717,62, 610,611,620,618, 611,615,623,620, + 612,610,618,619, 613,612,619,621, 614,491,573,613, 614,613,621,622, + 615,614,622,623, 618,620,626,624, 619,618,624,625, 62,717,718,65, + 620,623,629,626, 621,619,625,627, 622,621,627,628, 623,622,628,629, + 63,60,61,62, 639,638,1097,1096, 64,63,62,65, 647,634,793,782, + 1,647,646,2, 2,646,645,3, 65,718,719,66, 3,645,644,4, 4,644,643,5, + 5,643,642,6, 6,642,641,7, 7,641,640,8, 8,640,652,9, 28,27,1096,1097, + 29,28,1097,1098, 66,719,720,69, 30,29,1098,1099, 31,30,1099,1100, + 32,31,1100,1101, 33,637,636,34, 34,636,635,35, 35,635,634,0, + 0,634,647,1, 67,64,65,66, 670,669,672,671, 671,672,673,674, + 673,672,821,820, 674,673,676,675, 675,676,677,678, 678,677,680,679, + 679,680,681,682, 68,67,66,69, 681,680,826,825, 682,681,684,683, + 683,684,685,686, 684,681,824,1114, 685,684,1114,1131, + 686,685,688,687, 687,688,689,690, 689,688,1136,1135, 69,720,721,70, + 690,689,692,691, 691,692,693,694, 692,689,1135,1134, + 693,692,1134,1133, 694,693,695,48, 695,693,1133,1132, + 696,695,1132,761, 697,696,699,698, 698,699,700,701, 699,696,761,760, + 654,655,12,11, 70,721,722,723, 700,699,760,759, 701,700,703,702, + 702,703,704,705, 703,700,759,758, 704,703,758,757, 705,704,707,706, + 706,707,708,709, 707,704,757,756, 708,707,756,755, 709,708,711,710, + 71,68,69,70, 710,711,712,713, 711,708,755,754, 713,712,715,714, + 714,715,716,61, 715,712,1158,1159, 716,715,767,766, 717,716,766,765, + 718,717,765,764, 719,718,764,763, 72,71,70,723, 722,721,1171,1170, + 723,722,725,724, 724,725,726,727, 725,722,1170,1169, 727,726,729,728, + 728,729,730,731, 73,72,723,724, 731,730,733,732, 732,733,734,735, + 733,730,1184,1183, 734,733,1183,1182, 735,734,737,736, + 736,737,738,739, 737,734,1182,1181, 738,737,1181,1180, + 739,738,741,740, 74,73,724,727, 740,741,742,83, 741,738,1180,1179, + 742,741,1179,1232, 743,742,1232,744, 749,748,751,750, 75,74,727,728, + 750,751,752,753, 753,752,870,869, 76,75,728,731, 762,763,772,773, + 763,764,771,772, 764,765,770,771, 765,766,769,770, 766,767,768,769, + 767,715,1159,1167, 768,767,1167,1164, 77,76,731,732, 774,642,822,821, + 775,639,872,871, 776,780,783,787, 776,777,829,827, 778,779,828,830, + 78,77,732,735, 780,781,782,783, 780,776,827,832, 781,780,832,831, + 783,782,793,792, 784,779,778,785, 785,778,777,786, 786,777,776,787, + 787,783,792,788, 788,792,795,799, 789,786,787,788, 79,78,735,736, + 790,785,786,789, 791,784,785,790, 792,793,794,795, 793,634,635,794, + 794,635,636,805, 795,794,805,804, 796,791,790,797, 797,790,789,798, + 798,789,788,799, 799,795,804,800, 655,656,13,12, 80,79,736,739, + 801,798,799,800, 802,797,798,801, 803,796,797,802, 806,636,637,858, + 81,80,739,740, 815,814,842,843, 817,818,825,826, 818,819,824,825, + 82,81,740,83, 823,816,817,826, 824,819,1115,1114, 827,829,836,837, + 828,779,1117,1116, 828,819,835,830, 829,777,778,830, 831,832,833,834, + 833,832,827,837, 834,833,841,840, 835,818,839,836, 836,829,830,835, + 837,836,839,838, 839,816,843,838, 840,645,646,834, 841,833,837,838, + 842,812,840,841, 842,841,838,843, 86,747,748,749, 869,870,871,872, + 872,639,112,207, 88,87,86,749, 89,88,749,750, 656,657,14,13, + 90,89,750,753, 91,58,492,485, 910,927,952,953, 911,926,956,957, + 912,925,944,945, 913,924,948,949, 914,943,950,951, 915,808,864,929, + 918,941,958,959, 919,942,946,947, 92,91,485,484, 92,56,57,91, + 920,940,954,955, 924,919,992,1015, 925,858,988,1016, 926,920,993,1013, + 927,914,986,1014, 928,909,990,1008, 929,908,996,1007, 93,55,56,92, + 930,907,979,1003, 931,906,1009,1048, 932,905,981,1001, + 933,904,980,1002, 934,923,994,1011, 935,918,987,1012, + 936,922,995,1045, 937,917,989,1010, 938,921,977,1005, + 939,916,978,1004, 94,54,55,93, 940,910,983,999, 941,911,982,1000, + 942,912,985,997, 943,913,984,998, 944,925,1016,1017, + 945,944,1017,1018, 946,942,997,1019, 947,946,1019,1020, + 948,924,1015,1021, 949,948,1021,1022, 95,94,484,477, 95,53,54,94, + 950,943,998,1023, 951,950,1023,1024, 952,927,1014,1025, + 953,952,1025,1026, 954,940,999,1027, 955,954,1027,1028, + 956,926,1013,1029, 957,956,1029,1030, 958,941,1000,1031, + 959,958,1031,1032, 96,52,53,95, 960,935,1012,1033, 961,960,1033,1034, + 961,905,935,960, 962,932,1001,1035, 963,962,1035,1036, + 963,923,932,962, 964,934,1011,1037, 965,964,1037,1038, + 965,904,934,964, 966,933,1002,1039, 967,966,1039,1040, + 967,917,933,966, 968,937,1010,1041, 969,968,1041,1042, + 969,907,937,968, 97,51,52,96, 970,930,1003,1043, 971,970,1043,1044, + 971,922,930,970, 972,936,1045,1046, 973,972,1046,1047, + 973,906,936,972, 974,931,1048,1049, 975,974,1049,1050, + 975,916,931,974, 976,915,1069,1059, 977,921,1065,1055, + 978,916,975,1050, 979,907,969,1042, 98,50,51,97, 980,904,965,1038, + 981,905,961,1034, 982,911,957,1030, 983,910,953,1026, + 984,913,949,1022, 985,912,945,1018, 986,914,951,1024, + 987,918,959,1032, 989,917,967,1040, 990,909,1063,1053, + 992,919,947,1020, 993,920,955,1028, 994,923,963,1036, + 995,922,971,1044, 996,908,1067,1057, 997,992,1020,1019, + 998,986,1024,1023, 999,993,1028,1027, + + /* The base of the knight */ + SPIN,18, + 9510,0, 9510,756, SEAM, 9134,1129, 9447,1487, + 9447,1951, 9103,2371, STEPDOWN, 8211,3083, + 7167,4242, 6662,5664, 7040,7142, STEPUP, SEAM, 7935,8560, + STEPUP, BACKREF,0, + + ENDOFDATA +}; + +static unsigned short bishop_data[] = { + VERTICES, SETBACKREF,0, 5233,26960,0, 5154,26960,909, 4918,26960,1790, + 4532,26960,2617, 4009,26960,3364, 3364,26960,4009, 2617,26960,4532, + 1790,26960,4918, 909,26960,5154, 0,26833,5233, -909,26960,5154, + -1790,26960,4918, -2617,26960,4532, -3364,26960,4009, + -4009,26960,3364, -4532,26960,2617, -4918,26960,1790, + -5154,26960,909, -5233,26960,0, -5154,26960,-909, -4918,26960,-1790, + -4532,26960,-2617, -4009,26960,-3364, -3364,26960,-4009, + -2617,26960,-4532, -1790,26960,-4918, -909,26960,-5154, 0,26833,-5233, + 909,26960,-5154, 1790,26960,-4918, 2617,26960,-4532, 3364,26960,-4009, + 4009,26960,-3364, 4532,26960,-2617, 4918,26960,-1790, 5154,26960,-909, + SETBACKREF,1, 3812,31178,0, 3765,31144,729, 3624,31040,1435, + 3395,30872,2153, 3084,30642,2820, 2701,30360,3389, 2076,29899,4102, + 1492,30015,4340, 845,30033,4442, 0,30044,4511, -657,30063,4443, + -1481,30081,4214, -2190,30081,3884, -2830,30081,3435, + -3383,30081,2883, -3831,30081,2242, -4162,30081,1534, + -4364,30081,779, -4432,30081,0, -4364,30081,-779, -4162,30081,-1534, + -3831,30081,-2242, -3383,30081,-2883, -2830,30081,-3435, + -2190,30081,-3884, -1481,30081,-4214, -657,30063,-4443, 0,30044,-4511, + 845,30033,-4442, 1492,30015,-4340, 2076,29899,-4102, 2701,30360,-3388, + 3084,30642,-2820, 3395,30872,-2153, 3624,31040,-1435, 3765,31144,-729, + 240,28546,-4957, 884,29021,-4784, 1490,29467,-4537, 2076,29899,-4102, + 2701,30360,-3388, 3084,30642,-2820, 3395,30872,-2153, + 3624,31040,-1435, 3765,31144,-729, 2177,28477,4637, 1021,27605,5037, + 1021,27605,-5042, 2170,28478,-4644, 0,26833,-5233, 0,26833,5233, + -3153,28619,-3758, 240,28546,4957, 884,29021,4784, 2076,29899,4102, + 2701,30360,3389, 3084,30642,2820, 3395,30872,2153, 3624,31040,1435, + 3765,31144,729, -719,28582,4883, 4863,28569,977, 4560,28569,1925, + 4064,28569,2815, 3465,28569,3723, 2622,28569,4448, 2621,28583,-4401, + 3473,28588,-3691, 4064,28569,-2815, 4560,28569,-1925, 4863,28569,-977, + 4965,28569,0, -1678,28619,4610, -3153,28619,3758, -2453,28619,4248, + -4248,28619,2453, -3758,28619,3153, -4831,28619,852, -4906,28619,0, + -4831,28619,-852, -4610,28619,-1678, -4248,28619,-2453, + -3758,28619,-3153, -1678,28619,-4610, -2453,28619,-4248, + -644,27895,5037, -644,27895,-5037, -4610,28619,1678, -719,28582,-4883, + 2170,28478,-4644, 1021,27605,-5042, 1021,27605,5037, 2177,28477,4637, + 0,26833,-5233, 0,26833,5233, -644,27895,-5037, -644,27895,5037, + -644,27895,5037, -644,27895,-5037, 1490,29467,-4537, 884,29021,-4784, + 240,28546,-4957, 240,28546,4957, 884,29021,4784, 3812,31178,0, + 4349,30116,-867, 4197,30001,-1705, 3948,29813,-2492, 3610,29558,-3203, + 3193,29244,-3817, 2711,28880,-4315, 4349,30116,-867, 4197,30001,-1705, + 3948,29813,-2492, 3610,29558,-3203, 3193,29244,-3817, + 2711,28880,-4315, 1608,28047,-4906, 1608,28047,4901, 2711,28880,4310, + 3193,29244,3812, 3610,29558,3198, 3948,29813,2487, 4197,30001,1701, + 4349,30116,862, 4401,30155,-176, 1490,29467,4537, 1490,29467,4537, + 4401,30155,-176, 4349,30116,862, 4197,30001,1701, 3948,29813,2487, + 3610,29558,3198, 3193,29244,3812, 2711,28880,4310, 1608,28047,4901, + 1608,28047,-4906, + + TRIANGLES, 8,127,9, 7,128,154, 2,98,3, 121,96,10, 121,10,9, 121,138,96, + 122,27,26, 27,126,28, 66,135,65, 162,42,43, 165,164,141, 80,140,95, + 103,151,150, 102,125,152, 101,155,128, 100,157,156, 124,137,122, + 33,105,34, 29,153,125, 26,124,122, + + QUADS, 22,118,87,23, 21,117,118,22, 20,116,117,21, 19,115,116,20, + 18,114,115,19, 17,113,114,18, 16,123,113,17, 15,111,123,16, 14,112,111,15, + 13,109,112,14, 12,110,109,13, 11,108,110,12, 7,154,127,8, 110,108,47,48, + 135,136,64,65, 136,137,63,64, 138,139,44,45, 139,162,43,44, 109,110,48,49, + 147,161,107,106, 166,165,141,142, 167,166,142,143, 168,167,143,144, + 169,168,144,145, 112,109,49,50, 170,169,145,146, 171,81,84,172, + 111,112,50,51, 72,88,133,134, 73,89,88,72, 74,163,89,73, 75,90,163,74, + 76,91,90,75, 77,92,91,76, 78,93,92,77, 79,94,93,78, 80,95,94,79, + 81,170,146,84, 82,171,172,83, 86,82,83,85, 130,129,131,132, 123,111,51,52, + 113,123,52,53, 114,113,53,54, 115,114,54,55, 116,115,55,56, 117,116,56,57, + 118,117,57,58, 87,118,58,59, 120,87,59,60, 119,120,60,61, 107,161,160,97, + 106,107,0,35, 105,148,147,106, 105,106,35,34, 104,149,148,105, + 104,105,33,32, 103,150,149,104, 103,104,32,31, 102,152,151,103, + 102,103,31,30, 101,128,7,6, 100,101,6,5, 100,156,155,101, 99,100,5,4, + 99,158,157,100, 98,99,4,3, 98,159,158,99, 97,98,2,1, 97,160,159,98, + 96,108,11,10, 96,138,45,46, 124,119,61,62, 47,108,96,46, 63,137,124,62, + 0,107,97,1, 29,125,102,30, 28,126,153,29, 25,119,124,26, 24,120,119,25, + 23,87,120,24, + + /* Everything above the slit */ + SPIN,18, + 8870,0,8870,731,SEAM,8519,1091,8811,1438,8811,1886,8626,2292, + STEPDOWN,6989,2980,5927,4133,5548,5735, + STEPUP,5388,7642,5228,7807,STEPDOWN,4427,8149,4057,8434, + 3493,9185,2816,13524,SEAM,2690,18532,5301,18690, + STEPUP,6810,19005,6861,19277,6804,19625,STEPDOWN,6502,19845, + SEAM,4305,20394,STEPUP,4796,20522,4924,20759,4778,20979, + STEPDOWN,SEAM,3727,21207,SEAM,3726,22181,STEPUP,SEAM,4546,22705, + SEAM,3846,23385,4718,24227,5226,25516,STEPUP,BACKREF,0, + + /* Everything below the slit */ + SPIN,36, + BACKREF,1,STEPDOWN,3548,31590,STEPDOWN,2724,32633,SEAM,1581,33500, + 2013,33901,STEPUP,2281,34500,2281,34936,STEPDOWN,1947,35372, + STEPDOWN,1233,35734,STEPDOWN,0,35891, + + ENDOFDATA +}; + +static unsigned short king_data[] = { + SPIN,20, + 11378,0,11378,856,SEAM,10928,1152, + 11302,1684,11302,2209,11065,2684, + STEPDOWN,8964,3490,7603,4841,7116,6717, + STEPUP,6911,8950,6705,9144,STEPDOWN,5678,9545,5204,9878, + 4481,10758,3696,14808,SEAM,3065,26979, + 5813,27155,STEPUP,7145,27507,7424,27812,7352,28288,7131,28533, + 5477,28882,5397,29010,5406,29363,4903,29934, + STEPDOWN,SEAM,3944,30227, + SEAM,3974,31478,4703,31849,STEPUP,4832,32092,4756,32370, + SEAM,3975,32620,6899,39055,6877,39351,2833,39514, + 2786,39612,2786,39807,2734,39856,STEPDOWN,STEPDOWN,2590,39905,0,39969, + /* The cross */ + SETBACKREF,0, + QUADSTRIP,-1613,39866,0,-1543,39866,702,-1651,40481,0,-1580,40590,702, + -1531,40917,0,-1465,41008,702, + QUADSTRIP,-1531,40917,0,-1465,41008,702,-2956,41104,0,-2829,41187,702, + -3075,41520,0,-2943,41585,702,-3075,43849,0,-2943,43805,702, + -2862,44347,0,-2739,44282,702,-1116,44636,0,-1068,44554,702, + QUADSTRIP,-1116,44636,0,-1068,44554,702,-1102,45692,0,-1054,45576,702, + -973,45829,0,-973,45747,702,973,45829,0,973,45747,702,1102,45692,0, + 1054,45576,702,1116,44636,0,1068,44554,702, + QUADSTRIP,1116,44636,0,1068,44554,702,2862,44347,0,2739,44282,702, + 3075,43849,0,2943,43805,702,3075,41520,0,2943,41585,702,2956,41104,0, + 2829,41187,702,1531,40917,0,1465,41008,702, + QUADSTRIP,1531,40917,0,1465,41008,702,1651,40481,0,1580,40590,702, + 1613,39866,0,1543,39866,702, + QUADSTRIP,-1543,39866,702,1543,39866,702,-1580,40590,702, + 1580,40590,702,-1465,41008,702,1465,41008,702,-2829,41187,702, + 2829,41187,702,-2943,41585,702,2943,41585,702,-2943,43805,702, + 2943,43805,702,-2739,44282,702,2739,44282,702,-1068,44554,702, + 1068,44554,702,-1054,45576,702,1054,45576,702,-973,45747,702, + 973,45747,702, + QUADSTRIP,-1543,39866,-702,BACKREF,0,0,-1580,40590,-702,BACKREF,0,2, + -1465,41008,-702,BACKREF,0,4, + QUADSTRIP,-1465,41008,-702,BACKREF,0,6,-2829,41187,-702,BACKREF,0,8, + -2943,41585,-702,BACKREF,0,10,-2943,43805,-702,BACKREF,0,12, + -2739,44282,-702,BACKREF,0,14,-1068,44554,-702,BACKREF,0,16, + QUADSTRIP,-1068,44554,-702,BACKREF,0,18,-1054,45576,-702, + BACKREF,0,20,-973,45747,-702,BACKREF,0,22,973,45747,-702,BACKREF,0,24, + 1054,45576,-702,BACKREF,0,26,1068,44554,-702,BACKREF,0,28, + QUADSTRIP,1068,44554,-702,BACKREF,0,30,2739,44282,-702, + BACKREF,0,32,2943,43805,-702,BACKREF,0,34,2943,41585,-702,BACKREF,0,36, + 2829,41187,-702,BACKREF,0,38,1465,41008,-702,BACKREF,0,40, + QUADSTRIP,1465,41008,-702,BACKREF,0,42,1580,40590,-702, + BACKREF,0,44,1543,39866,-702,BACKREF,0,46, + QUADSTRIP,1543,39866,-702,-1543,39866,-702,1580,40590,-702, + -1580,40590,-702,1465,41008,-702,-1465,41008,-702,2829,41187,-702, + -2829,41187,-702,2943,41585,-702,-2943,41585,-702,2943,43805,-702, + -2943,43805,-702,2739,44282,-702,-2739,44282,-702,1068,44554,-702, + -1068,44554,-702,1054,45576,-702,-1054,45576,-702,973,45747,-702, + -973,45747,-702, + ENDOFDATA +}; + +static unsigned short queen_data[] = { + SPIN,24, + 11092,0,11092,914,SEAM,10653,1284, + 11018,1798,11018,2358,10787,2866, + STEPDOWN,8739,3726,7412,5168,6937,7171, + STEPUP,6737,9556,6537,9762,STEPDOWN,5536,10191,5073,10546, + 4368,11485,3678,15137,SEAM,3259,26879, + 5966,27091,STEPUP,7332,27515,7619,27882,7545,28455,7317,28751, + 5654,29177,5538,29326,5542,29982,5377,30278, + STEPDOWN,SEAM,4194,30585, + SEAM,4226,31822,5002,32218,STEPUP,5139,32477,5058,32774, + SEAM,4227,33040,STEPDOWN,4421,34778,5042,36612,5874,38429, + STEPUP,SEAM,PATTERN,3,6018,39660,6018,39660,6804,39977, + SEAM,PATTERN,3,5015,41139,5015,41139,5673,41460, + SEAM,4349,40044, + STEPDOWN,SEAM,1381,41188, + 1396,42332,STEPDOWN,1082,43072,481,43476,0,43543, + ENDOFDATA +}; + +static unsigned short pawn_data[] = { + SPIN,16, + 7395,0,7395,609, + SEAM,7102,910,7345,1199,7345,1572,7191,1910, + STEPDOWN,5826,2484,4941,3446,4625,4781, + STEPUP,4492,6371,4358,6508, + STEPDOWN,3691,6794,2912,7657,2473,10091, + SEAM,2100,15344, + STEPUP,4518,15697,4695,15900,4649,16218,4509,16382, + STEPDOWN,SEAM,3150,16755,STEPUP,3858,17678,4303,18752,4455,19905, + 4303,21058,3858,22132, + STEPDOWN,3150,23055,2227,23763,STEPDOWN,1153,24208,0,24360, + ENDOFDATA +}; + +static unsigned short rook_data[] = { + SPIN,20, + 9374,0,9374,756,SEAM,9003,1062,9311,1487, + 9311,1951,9116,2371,8521,3083,6701,5807,SEAM,6009,7595, + 6167,7812,6138,8066,5926,8460,5216,12608, + SEAM,4883,21434, + SEAM,5140,21608, + SEAM,5176,22792, + SEAM,5953,23030, +/* SEAM,PATTERN,5,6103,26819,6143,27971,6143,27971,6143,27971,6103,26819, */ +/* SEAM,PATTERN,5, 5020,26819,5053,27971,5053,27971,5053,27971, 5020,26819, */ + SETBACKREF,0, + 6103,26819, + + SETBACKREF,1, + SPIN,20, + 5020,26819,5020,26114,4906,25858,0,25666, + + POLARQUADSTRIP,20,BACKREF,0,1,1,6143,27971,BACKREF,0,2,2,6143,27971, + BACKREF,0,3,3,6143,27971,BACKREF,0,4,4,6143,27971, + POLARQUADSTRIP,20,BACKREF,0,6,6,6143,27971,BACKREF,0,7,7,6143,27971, + BACKREF,0,8,8,6143,27971,BACKREF,0,9,9,6143,27971, + POLARQUADSTRIP,20,BACKREF,0,11,11,6143,27971,BACKREF,0,12,12,6143,27971, + BACKREF,0,13,13,6143,27971,BACKREF,0,14,14,6143,27971, + POLARQUADSTRIP,20,BACKREF,0,16,16,6143,27971,BACKREF,0,17,17,6143,27971, + BACKREF,0,18,18,6143,27971,BACKREF,0,19,19,6143,27971, + + POLARQUADSTRIP,20,1,5053,27971,BACKREF,1,1,2,5053,27971,BACKREF,1,2, + 3,5053,27971,BACKREF,1,3,4,5053,27971,BACKREF,1,4, + POLARQUADSTRIP,20,6,5053,27971,BACKREF,1,6,7,5053,27971,BACKREF,1,7, + 8,5053,27971,BACKREF,1,8,9,5053,27971,BACKREF,1,9, + POLARQUADSTRIP,20,11,5053,27971,BACKREF,1,11,12,5053,27971,BACKREF,1,12, + 13,5053,27971,BACKREF,1,13,14,5053,27971,BACKREF,1,14, + POLARQUADSTRIP,20,16,5053,27971,BACKREF,1,16,17,5053,27971,BACKREF,1,17, + 18,5053,27971,BACKREF,1,18,19,5053,27971,BACKREF,1,19, + + POLARQUADSTRIP,20,1,5020,26819,1,6103,26819, + 0,5020,26819,0,6103,26819,19,5020,26819,19,6103,26819, + POLARQUADSTRIP,20,6,5020,26819,6,6103,26819, + 5,5020,26819,5,6103,26819,4,5020,26819,4,6103,26819, + POLARQUADSTRIP,20,11,5020,26819,11,6103,26819, + 10,5020,26819,10,6103,26819,9,5020,26819,9,6103,26819, + POLARQUADSTRIP,20,16,5020,26819,16,6103,26819, + 15,5020,26819,15,6103,26819,14,5020,26819,14,6103,26819, + + POLARQUADSTRIP,20,1,5053,27971,1,6143,27971,1,5020,26819,1,6103,26819, + POLARQUADSTRIP,20,4,5020,26819,4,6103,26819,4,5053,27971,4,6143,27971, + POLARQUADSTRIP,20,6,5053,27971,6,6143,27971,6,5020,26819,6,6103,26819, + POLARQUADSTRIP,20,9,5020,26819,9,6103,26819,9,5053,27971,9,6143,27971, + POLARQUADSTRIP,20,11,5053,27971,11,6143,27971,11,5020,26819,11,6103,26819, + POLARQUADSTRIP,20,14,5020,26819,14,6103,26819,14,5053,27971,14,6143,27971, + POLARQUADSTRIP,20,16,5053,27971,16,6143,27971,16,5020,26819,16,6103,26819, + POLARQUADSTRIP,20,19,5020,26819,19,6103,26819,19,5053,27971,19,6143,27971, + + POLARQUADSTRIP,20,1,6143,27971,1,5053,27971,2,6143,27971,2,5053,27971, + 3,6143,27971,3,5053,27971,4,6143,27971,4,5053,27971, + POLARQUADSTRIP,20,6,6143,27971,6,5053,27971,7,6143,27971,7,5053,27971, + 8,6143,27971,8,5053,27971,9,6143,27971,9,5053,27971, + POLARQUADSTRIP,20,11,6143,27971,11,5053,27971,12,6143,27971,12,5053,27971, + 13,6143,27971,13,5053,27971,14,6143,27971,14,5053,27971, + POLARQUADSTRIP,20,16,6143,27971,16,5053,27971,17,6143,27971,17,5053,27971, + 18,6143,27971,18,5053,27971,19,6143,27971,19,5053,27971, + + ENDOFDATA +}; + +static double piece_size; + +static int +enumerate_ring_vertices( int steps, unsigned short *data, void *h, + void (*process_vertex)(void *h,double x,double y,double z)) +{ + int patlen = 1,i; + unsigned short *pts = data; + double dtheta = M_PI * 2 / steps; + + if( data[0] == PATTERN) { + patlen = data[1]; + pts += 2; + } + + if( pts[0] == 0) steps = 1; + + for( i=0; i < steps; i++) { + double r = pts[(i % patlen)*2] * piece_size; + double y = pts[(i % patlen)*2+1] * piece_size; + double theta = dtheta * i; + + process_vertex( h, r * cos(theta), y, r * sin(theta)); + } + + return pts + patlen * 2 - data; +} + +static void +enumerate_vertices( unsigned short *data, void *h, + void (*process_vertex)(void *h,double x,double y,double z)) +{ + while(1) { + if( data[0] == SPIN) { + int steps; + steps = data[1]; + data += 2; + + while(data[0] <= SEAM) { + if( data[0] == SETBACKREF || data[0] == BACKREF) { + data += 2; + continue; + } else if( data[0] == STEPUP) { + steps *= 2; + data++; + continue; + } else if( data[0] == STEPDOWN) { + steps /= 2; + data++; + continue; + } else if( data[0] == SEAM) { + data ++; + /* Visit seam vertices twice */ + enumerate_ring_vertices( steps, data, + h, process_vertex); + data += enumerate_ring_vertices( steps, data, + h, process_vertex); + } else { + data += enumerate_ring_vertices( steps, data, + h, process_vertex); + } + } + } else if( data[0] == POLARQUADSTRIP) { + int steps = data[1]; + double dtheta; + data += 2; + + dtheta = M_PI * 2 / steps; + + while(data[0] <= SEAM) { + if( data[0] != BACKREF) { + double theta = dtheta * data[0]; + double r = data[1] * piece_size; + double y = data[2] * piece_size; + process_vertex( h, r * cos(theta), y, r * sin(theta)); + } + data += 3; + } + } else if( data[0] == QUADSTRIP || data[0] == VERTICES) { + data ++; + + while(data[0] <= SEAM) { + if( data[0] == SETBACKREF) { + data += 2; + continue; + } + + if( data[0] != BACKREF) { + double x = (signed short)data[0] * piece_size; + double y = data[1] * piece_size; + double z = (signed short)data[2] * piece_size; + process_vertex( h, x, y, z); + } + data += 3; + } + } else if( data[0] == QUADS || data[0] == TRIANGLES) { + data ++; + while( data[0] <= SEAM) data++; + } else { + break; + } + } +} + +static void +enumerate_ring_faces( int basevertex, int steps, + int prevbase, int prevsteps, void *h, int *count_ret, + void (*process_face)(void *h,int v1,int v2,int v3,int v4)) +{ + int i,j; + + if( steps == 1) { + for( i=0; i < prevsteps; i++) { + process_face( h, + basevertex, + prevbase + i, + prevbase + (i ? i-1 : prevsteps-1), + -1); + if (count_ret) (*count_ret)++; + } + } else if( steps == prevsteps) { + for( i=0; i < steps; i++) { + process_face( h, + basevertex + i, + prevbase + i, + prevbase + (i ? i-1 : steps-1), + basevertex + (i ? i-1 : steps-1)); + if (count_ret) (*count_ret)++; + } + } else { + j = 0; + for( i=0;; i++) { + while( j < prevsteps && steps*(1+2*j) < prevsteps*(1+2*i)) { + process_face( h, + basevertex + (i%steps), + prevbase + ((j+1)%prevsteps), + prevbase + j, + -1); + if (count_ret) (*count_ret)++; + j++; + } + if( i == steps) break; + process_face( h, + basevertex + i, + basevertex + ((i+1)%steps), + prevbase + (j%prevsteps), + -1); + if (count_ret) (*count_ret)++; + } + } +} + +static void +enumerate_faces( unsigned short *data, void *h, int *count_ret, + void (*process_face)(void *h,int v1,int v2,int v3,int v4)) +{ + int basevertex = 0, startofvertices = 0; + int backrefs[5]; + + while(1) { + if( data[0] == SPIN) { + int steps; + int prevsteps = -1,prevbase = 0; + + steps = data[1]; + data += 2; + + while( data[0] <= SEAM) { + if( data[0] == SETBACKREF) { + backrefs[data[1]] = basevertex; + data += 2; + continue; + } + + if( data[0] == STEPUP) { + steps *= 2; + data++; + continue; + } else if( data[0] == STEPDOWN) { + steps /= 2; + data++; + continue; + } + + if( data[0] == BACKREF) { + if( prevsteps != -1) { + enumerate_ring_faces( backrefs[data[1]], steps, + prevbase, prevsteps, h, + count_ret, process_face); + } + + prevbase = backrefs[data[1]]; + data += 2; + } else { + int isseam = 0; + if( data[0] == SEAM) { + isseam = 1; + data++; + } + + if( data[0] == PATTERN) { + data += 2 + data[1]*2; + } else { + if( data[0] == 0) steps = 1; + data += 2; + } + + if( prevsteps != -1) { + enumerate_ring_faces( basevertex, steps, + prevbase, prevsteps, h, + count_ret, process_face); + } + + if( isseam) basevertex += steps; + prevbase = basevertex; + basevertex += steps; + } + + prevsteps = steps; + } + } else if( data[0] == POLARQUADSTRIP || data[0] == QUADSTRIP) { + int v0=-1,v1=0,v2,v3; + if( data[0] == POLARQUADSTRIP) data += 2; + else data ++; + while(data[0] <= SEAM) { + if( data[0] == BACKREF) { + v2 = backrefs[data[1]]+data[2]; + } else { + v2 = basevertex; + basevertex++; + } + if( data[3] == BACKREF) { + v3 = backrefs[data[4]]+data[5]; + } else { + v3 = basevertex; + basevertex++; + } + data += 6; + if( v0 != -1) { + process_face( h, v0, v1, v3, v2); + if (count_ret) (*count_ret)++; + } + v0 = v2; + v1 = v3; + } + } else if( data[0] == VERTICES) { + data ++; + startofvertices = basevertex; + while( data[0] <= SEAM) { + if( data[0] == SETBACKREF) { + backrefs[data[1]] = basevertex; + data += 2; + continue; + } + data += 3; + basevertex ++; + } + } else if( data[0] == QUADS) { + data ++; + while( data[0] <= SEAM) { + process_face( h, + data[0] + startofvertices, + data[1] + startofvertices, + data[2] + startofvertices, + data[3] + startofvertices); + if (count_ret) (*count_ret)++; + data += 4; + } + } else if( data[0] == TRIANGLES) { + data ++; + while( data[0] <= SEAM) { + process_face( h, + data[0] + startofvertices, + data[1] + startofvertices, + data[2] + startofvertices, -1); + if (count_ret) (*count_ret)++; + data += 3; + } + } else { + break; + } + } +} + +static void +normalize( float v[3]) { + float d = sqrt(v[0]*v[0]+v[1]*v[1]+v[2]*v[2]); + + if( d == 0.0) { + /* The direction is undefined - normalize it anyway */ + v[0] = 1.0; + v[1] = 0.0; + v[2] = 0.0; + return; + } + + v[0] /= d; + v[1] /= d; + v[2] /= d; +} + +static void +normcrossprod( float v1[3], float v2[3], float out[3]) +{ + out[0] = v1[1] * v2[2] - v1[2] * v2[1]; + out[1] = v1[2] * v2[0] - v1[0] * v2[2]; + out[2] = v1[0] * v2[1] - v1[1] * v2[0]; + normalize( out); +} + +#define vectordiff(v1,v2,out) \ + ((out)[0] = (v1)[0] - (v2)[0], \ + (out)[1] = (v1)[1] - (v2)[1], \ + (out)[2] = (v1)[2] - (v2)[2]) + +#define vectoradd(v1,v2) \ + ((v1)[0] += (v2)[0], \ + (v1)[1] += (v2)[1], \ + (v1)[2] += (v2)[2]) + +static int numverts; +static float *vertices; +static float *normals; + +static void +count_vertex( void *dummy, double x, double y, double z) +{ + numverts++; +} + +static void +add_normal( void *dummy, int v1, int v2, int v3, int v4) +{ + float surfnormal[3],d1[3],d2[3]; + + if( v4 == -1) { + vectordiff( vertices + 3 * v2, vertices + 3 * v1, d1); + vectordiff( vertices + 3 * v3, vertices + 3 * v1, d2); + normcrossprod( d1, d2, surfnormal); + vectoradd( normals + 3 * v1, surfnormal); + vectoradd( normals + 3 * v2, surfnormal); + vectoradd( normals + 3 * v3, surfnormal); + } else { + vectordiff( vertices + 3 * v2, vertices + 3 * v1, d1); + vectordiff( vertices + 3 * v4, vertices + 3 * v1, d2); + normcrossprod( d1, d2, surfnormal); + vectoradd( normals + 3 * v1, surfnormal); + vectordiff( vertices + 3 * v3, vertices + 3 * v2, d1); + vectordiff( vertices + 3 * v1, vertices + 3 * v2, d2); + normcrossprod( d1, d2, surfnormal); + vectoradd( normals + 3 * v2, surfnormal); + vectordiff( vertices + 3 * v4, vertices + 3 * v3, d1); + vectordiff( vertices + 3 * v2, vertices + 3 * v3, d2); + normcrossprod( d1, d2, surfnormal); + vectoradd( normals + 3 * v3, surfnormal); + vectordiff( vertices + 3 * v1, vertices + 3 * v4, d1); + vectordiff( vertices + 3 * v3, vertices + 3 * v4, d2); + normcrossprod( d1, d2, surfnormal); + vectoradd( normals + 3 * v4, surfnormal); + } +} + +static void +collect_vertex( void *curvert, double x, double y, double z) +{ + (*(float**)curvert)[0] = x; + (*(float**)curvert)[1] = y; + (*(float**)curvert)[2] = z; + (*(float**)curvert) += 3; +} + +static void +draw_face( void *dummy, int v1, int v2, int v3, int v4) +{ + glBegin( v4 == -1 ? GL_TRIANGLES : GL_QUADS); + glNormal3f( normals[v1*3], normals[v1*3+1], normals[v1*3+2]); + glVertex3f( vertices[v1*3], vertices[v1*3+1], vertices[v1*3+2]); + glNormal3f( normals[v2*3], normals[v2*3+1], normals[v2*3+2]); + glVertex3f( vertices[v2*3], vertices[v2*3+1], vertices[v2*3+2]); + glNormal3f( normals[v3*3], normals[v3*3+1], normals[v3*3+2]); + glVertex3f( vertices[v3*3], vertices[v3*3+1], vertices[v3*3+2]); + if( v4 != -1) { + glNormal3f( normals[v4*3], normals[v4*3+1], normals[v4*3+2]); + glVertex3f( vertices[v4*3], vertices[v4*3+1], vertices[v4*3+2]); + } + glEnd(); +} + +static int +draw_piece( unsigned short *piece_data) +{ + int i; + float *curvert; + int count = 0; + + /* Count how many vertices this piece has */ + enumerate_vertices( piece_data, NULL, count_vertex); + + /* Allocate memory for the vertices and for the vertex normals */ + vertices = malloc( sizeof(float) * 3 * numverts); + normals = malloc( sizeof(float) * 3 * numverts); + if( !vertices || !normals) exit(1); + + /* Collect the vertex coordinates */ + curvert = vertices; + enumerate_vertices( piece_data, &curvert, collect_vertex); + + /* Zero out the normals */ + for( i=0; i < numverts * 3; i++) { + normals[i] = 0.0; + } + + /* Add up all the face normals at each vertex */ + enumerate_faces( piece_data, NULL, NULL, add_normal); + + /* Normalize the vertex normals */ + for( i=0; i < numverts; i++) { + normalize( normals + i * 3); + } + + /* Now draw the faces */ + enumerate_faces( piece_data, NULL, &count, draw_face); + + free( normals); + free( vertices); + + if (count <= 1) abort(); + return count; +} + +void chessmodels_gen_lists( int classic, int poly_count[PIECES]) { + + Bool queen_only_p = classic < 0; + if (classic < 0) classic = 0; + + piece_size = classic ? 0.095 / 100 : 0.3 / 8192; + + glGenLists (20); /* this is horrible! List numbers are hardcoded! */ + + glNewList(QUEEN, GL_COMPILE); + poly_count[QUEEN] = draw_piece( classic ? classic_queen_data : queen_data); + glEndList(); + + if (queen_only_p) return; + + glNewList(KING, GL_COMPILE); + poly_count[KING] = draw_piece( classic ? classic_king_data : king_data); + glEndList(); + + glNewList(BISHOP, GL_COMPILE); + poly_count[BISHOP] = draw_piece( classic ? classic_bishop_data : bishop_data); + glEndList(); + + glNewList(KNIGHT, GL_COMPILE); + poly_count[KNIGHT] = draw_piece( classic ? classic_knight_data : knight_data); + glEndList(); + + glNewList(ROOK, GL_COMPILE); + poly_count[ROOK] = draw_piece( classic ? classic_rook_data : rook_data); + glEndList(); + + glNewList(PAWN, GL_COMPILE); + poly_count[PAWN] = draw_piece( classic ? classic_pawn_data : pawn_data); + glEndList(); +} diff --git a/hacks/glx/chessmodels.h b/hacks/glx/chessmodels.h new file mode 100644 index 00000000..6e41e224 --- /dev/null +++ b/hacks/glx/chessmodels.h @@ -0,0 +1,44 @@ +/* + * models for the xss chess screensavers + * hacked from: + * + * glChess - A 3D chess interface + * + * Copyright (C) 2006 John-Paul Gignac + * + * Copyright (C) 2002 Robert Ancell + * Michael Duelli + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ugggggggly */ +#define PIECES 7 +#define NONE 0 +#define KING 1 +#define QUEEN 2 +#define BISHOP 3 +#define KNIGHT 4 +#define ROOK 5 +#define PAWN 6 +#define BKING 8 +#define BQUEEN 9 +#define BBISHOP 10 +#define BKNIGHT 11 +#define BROOK 12 +#define BPAWN 13 + +extern void chessmodels_gen_lists( int classic, int poly_count[PIECES]); + diff --git a/hacks/glx/circuit.c b/hacks/glx/circuit.c new file mode 100644 index 00000000..b59b470b --- /dev/null +++ b/hacks/glx/circuit.c @@ -0,0 +1,2283 @@ +/* + * circuit - Random electronic components floating around + * + * version 1.4 + * + * Since version 1.1: added to-220 transistor, added fuse + * Since version 1.2: random display digits, LED improvements (flickering) + * Since version 1.3: ICs look better, font textures, improved normals to + * eliminate segmenting on curved surfaces, speedups + * Since version 1.4: Added RCA connector, 3.5mm connector, slide switch, + * surface mount, to-92 markings. Fixed ~5min crash. + * Better LED illumination. Other minor changes. + * + * Copyright (C) 2001,2002 Ben Buxton (bb@cactii.net) + * + * 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. + */ + +/* Written over a few days in a (successful) bid to learn GL coding + * + * -seven option is dedicated to all the Slarkeners + * + * This hack uses lookup tables for sin, cos and tan - it can do a lot + */ + +#ifdef STANDALONE +#define DEFAULTS "*delay: 20000 \n" \ + "*showFPS: False \n" + +# define refresh_circuit 0 +# define circuit_handle_event 0 +# include "xlockmore.h" /* from the xscreensaver distribution */ +#else /* !STANDALONE */ +# include "xlock.h" /* from the xlockmore distribution */ +#endif /* !STANDALONE */ + +#define DEF_SPIN "True" +#define DEF_SEVEN "False" +#define DEF_PARTS "10" +#define DEF_ROTATESPEED "1" +#define DEF_LIGHT "True" + +/* lifted from lament.c */ +#define RAND(n) ((long) ((random() & 0x7fffffff) % ((long) (n)))) +#define RANDSIGN() ((random() & 1) ? 1 : -1) + + +#ifdef USE_GL + +#include "font-ximage.h" + +#undef countof +#define countof(x) (sizeof((x))/sizeof((*x))) + +static int maxparts; +static char *font; +static int rotatespeed; +static int spin; +static int uselight; +static int seven; + +#undef countof +#define countof(x) (sizeof((x))/sizeof((*x))) + +static XrmOptionDescRec opts[] = { + {"-parts", ".circuit.parts", XrmoptionSepArg, 0 }, + {"-font", ".circuit.font", XrmoptionSepArg, 0 }, + {"-rotate-speed", ".circuit.rotatespeed", XrmoptionSepArg, 0 }, + {"+spin", ".circuit.spin", XrmoptionNoArg, "false" }, + {"-spin", ".circuit.spin", XrmoptionNoArg, "true" }, + {"+light", ".circuit.light", XrmoptionNoArg, "false" }, + {"-light", ".circuit.light", XrmoptionNoArg, "true" }, + {"+seven", ".circuit.seven", XrmoptionNoArg, "false" }, + {"-seven", ".circuit.seven", XrmoptionNoArg, "true" }, +}; + +static argtype vars[] = { + {&maxparts, "parts", "Parts", DEF_PARTS, t_Int}, + {&font, "font", "Font", "fixed", t_String}, + {&rotatespeed, "rotatespeed", "Rotatespeed", DEF_ROTATESPEED, t_Int}, + {&spin, "spin", "Spin", DEF_SPIN, t_Bool}, + {&uselight, "light", "Light", DEF_LIGHT, t_Bool}, + {&seven, "seven", "Seven", DEF_SEVEN, t_Bool}, +}; + +ENTRYPOINT ModeSpecOpt circuit_opts = {countof(opts), opts, countof(vars), vars, NULL}; + +#ifdef USE_MODULES +ModStruct circuit_description = +{"circuit", "init_circuit", "draw_circuit", "release_circuit", + "draw_circuit", "init_circuit", NULL, &circuit_opts, + 1000, 1, 2, 1, 4, 1.0, "", + "Flying electronic components", 0, NULL}; + +#endif + +#define MAX_COMPONENTS 400 +#define MOVE_MULT 0.02 + +static float f_rand(void) +{ + return ((float)RAND(10000)/(float)10000); +} + +#define RAND_RANGE(min, max) ((min) + (max - min) * f_rand()) + +/* used for allocating font textures */ +typedef struct { + int num; /* index number */ + int w; /* width */ + int h; /* height */ +} TexNum; + +/* Represents a band on a resistor/diode/etc */ +typedef struct { + float pos; /* relative position from start/previous band */ + GLfloat r, g, b; /* colour of the band */ + float len; /* length as a fraction of total length */ +} Band; + +typedef struct { + Band *b1, *b2, *b3, *b4; /* bands */ + int b[4]; +} Resistor; + +typedef struct { + Band *band; + GLfloat r, g, b; /* body colour */ +} Diode; + +static const char * const transistortypes[] = { + "TIP2955", + "TIP32C", + "LM 350T", + "IRF730", + "ULN2577", + "7805T", + "7912T", + "TIP120", + "2N6401", + "BD239", + "2SC1590", + "MRF485", + "SC141D" +}; + +static const char * const to92types[] = { + "C\n548", + "C\n848", + "74\nL05", + "C\n858", + "BC\n212L", + "BC\n640", + "BC\n337", + "BC\n338", + "S817", + "78\nL12", + "TL\n431", + "LM\n35DZ", +}; + +static const char * const smctypes[] = { + "1M-", + "1K", + "1F", + "B10", + "S14", + "Q3", + "4A" +}; + +typedef struct { + int type; /* package type. 0 = to-92, 1 = to-220 */ + GLfloat tw, th; /* texture dimensions */ + GLuint tnum; /* texture binding */ +} Transistor; + +typedef struct { + GLfloat r,g,b; /* LED colour */ + int light; /* are we the light source? */ +} LED; + +typedef struct { + int type; /* 0 = electro, 1 = ceramic */ + float width; /* width of an electro/ceramic */ + float length; /* length of an electro */ +} Capacitor; + +/* 3.5 mm plug */ +typedef struct { + int blah; +} ThreeFive; + +/* slide switch */ +typedef struct { + int position; +} Switch; + +typedef struct { + int pins; + const char *val; +} ICTypes; + +static const ICTypes ictypes[] = { + {8, "NE 555"}, + {8, "LM 386N"}, + {8, "ADC0831"}, + {8, "LM 383T"}, + {8, "TL071"}, + {8, "LM 311"}, + {8, "LM393"}, + {8, "LM 3909"}, + + {14, "LM 380N"}, + {14, "NE 556"}, + {14, "TL074"}, + {14, "LM324"}, + {14, "LM339"}, + {14, "MC1488"}, + {14, "MC1489"}, + {14, "LM1877-9"}, + {14, "4011"}, + {14, "4017"}, + {14, "4013"}, + {14, "4024"}, + {14, "4066"}, + + {16, "4076"}, + {16, "4049"}, + {16, "4094"}, + {16, "4043"}, + {16, "4510"}, + {16, "4511"}, + {16, "4035"}, + {16, "RS232"}, + {16, "MC1800"}, + {16, "ULN2081"}, + {16, "UDN2953"}, + + {24, "ISD1416P"}, + {24, "4515"}, + {24, "TMS6264L"}, + {24, "MC146818"} +}; + +typedef struct { + int type; /* 0 = DIL, 1 = flat square */ + int pins; + float tw, th; /* texture dimensions for markings */ + int tnum; /* texture number */ +} IC; + +/* 7 segment display */ + +typedef struct { + int value; /* displayed number */ +} Disp; + +typedef struct { + GLfloat l, w; +} Fuse; + +typedef struct { + GLfloat l, w; + int col; +} RCA; + +typedef struct { + GLfloat x, y, z; /* current co-ordinates */ + GLfloat dx, dy, dz; /* current direction */ + GLfloat rotx, roty, rotz; /* rotation vector */ + GLfloat drot; /* rotation velocity (degrees per frame) */ + int norm; /* Normalize this component (for shine) */ + int rdeg; /* current rotation degrees */ + int angle; /* angle about the z axis */ + int alpha; /* 0 if not a transparent component */ + int type; /* 0 = resistor, 1 = diode, 2 = transistor, 3 = LED, 4 = cap, 5=IC, + 6 = 7 seg disp */ + void * c; /* pointer to the component */ +} Component; + +/* standard colour codes */ + +static const GLfloat colorcodes [12][3] = { + {0.0,0.0,0.0}, /* black 0 */ + {0.49,0.25,0.08}, /* brown 1 */ + {1.0,0.0,0.0}, /* red 2 */ + {1.0,0.5,0.0}, /* orange 3 */ + {1.0,1.0,0.0}, /* yellow 4 */ + {0.0,1.0,0.0}, /* green 5 */ + {0.0,0.5,1.0}, /* blue 6 */ + {0.7,0.2,1.0}, /* violet 7 */ + {0.5,0.5,0.5}, /* grey 8 */ + {1.0,1.0,1.0}, /* white 9 */ + {0.66,0.56,0.2}, /* gold 10 */ + {0.8,0.8,0.8}, /* silver 11 */ +}; + +/* base values for components - we can multiply by 0 - 1M */ +static const int values [9][2] = { + {1,0}, + {2,2}, + {3,3}, + {4,7}, + {5,6}, + {6,8}, + {7,5}, + {8,2}, + {9,1} +}; + +typedef struct { + GLXContext *glx_context; + Window window; + + int XMAX, YMAX; + int win_w, win_h; + + /* one lucky led gets to be a light source , unless -no-light*/ + int light; + int lighton; + + /* stores refs to textures */ + int s_refs[50]; + + GLfloat viewer[3]; + GLfloat lightpos[4]; + + float sin_table[720]; + float cos_table[720]; + float tan_table[720]; + + Component *components[MAX_COMPONENTS]; + int band_list[12]; + int band_list_polys[12]; + + GLfloat grid_col[3], grid_col2[3]; + + int display_i; + GLfloat rotate_angle; + + char *font_strings[50]; /* max of 40 textures */ + int font_w[50], font_h[50]; + int font_init; + + GLfloat draw_sx, draw_sy; /* bright spot co-ords */ + int draw_sdir; /* 0 = left-right, 1 = right-left, 2 = up->dn, 3 = dn->up */ + int draw_s; /* if spot is enabled */ + float draw_ds; /* speed of spot */ + +} Circuit; + +static Circuit *circuit = NULL; + + +static int DrawResistor(Circuit *, Resistor *); +static int DrawDiode(Circuit *, Diode *); +static int DrawTransistor(Circuit *, Transistor *); +static int DrawLED(Circuit *, LED *); +static int DrawIC(Circuit *, IC *); +static int DrawCapacitor(Circuit *, Capacitor *); +static int DrawDisp(Circuit *, Disp *); +static int DrawFuse(Circuit *, Fuse *); +static int DrawRCA(Circuit *, RCA *); +static int DrawThreeFive(Circuit *, ThreeFive *); +static int DrawSwitch(Circuit *, Switch *); + +static void freetexture(Circuit *, GLuint); +static void reorder(Component *[]); +static int circle(Circuit *, float, int,int); +static int bandedCylinder(Circuit *, + float, float , GLfloat, GLfloat , GLfloat, + Band **, int); +static TexNum *fonttexturealloc(ModeInfo *, const char *, float *, float *); +static int Rect(GLfloat , GLfloat , GLfloat, GLfloat , GLfloat ,GLfloat); +static int ICLeg(GLfloat, GLfloat, GLfloat, int); +static int HoledRectangle(Circuit *ci, + GLfloat, GLfloat, GLfloat, GLfloat, int); +static Resistor *NewResistor(void); +static Diode *NewDiode(void); +static Transistor *NewTransistor(ModeInfo *); +static LED * NewLED(Circuit *); +static Capacitor *NewCapacitor(Circuit *); +static IC* NewIC(ModeInfo *); +static Disp* NewDisp(Circuit *); +static Fuse *NewFuse(Circuit *); +static RCA *NewRCA(Circuit *); +static ThreeFive *NewThreeFive(Circuit *); +static Switch *NewSwitch(Circuit *); + +/* we use trig tables to speed things up - 200 calls to sin() + in one frame can be a bit harsh.. +*/ + +static void make_tables(Circuit *ci) +{ +int i; +float f; + + f = 360 / (M_PI * 2); + for (i = 0 ; i < 720 ; i++) { + ci->sin_table[i] = sin(i/f); + } + for (i = 0 ; i < 720 ; i++) { + ci->cos_table[i] = cos(i/f); + } + for (i = 0 ; i < 720 ; i++) { + ci->tan_table[i] = tan(i/f); + } +} + + +static int createCylinder (Circuit *ci, + float length, float radius, int endcaps, int half) +{ + int polys = 0; + int a; /* current angle around cylinder */ + int angle, norm; + float z1, y1, z2, y2,ex; + int nsegs; + + glPushMatrix(); + nsegs = radius*MAX(ci->win_w, ci->win_h)/20; + nsegs = MAX(nsegs, 4); + if (nsegs % 2) + nsegs += 1; + angle = (half) ? (180 - 90/nsegs) : 374; + z1 = radius; y1 = 0; + glBegin(GL_QUADS); + for (a = 0 ; a <= angle ; a+= angle/nsegs) { + y2=radius*(float)ci->sin_table[(int)a]; + z2=radius*(float)ci->cos_table[(int)a]; + glNormal3f(0, y1, z1); + glVertex3f(0,y1,z1); + glVertex3f(length,y1,z1); + glNormal3f(0, y2, z2); + glVertex3f(length,y2,z2); + glVertex3f(0,y2,z2); + polys++; + z1=z2; + y1=y2; + } + glEnd(); + if (half) { + glBegin(GL_POLYGON); + glNormal3f(0, 1, 0); + glVertex3f(0, 0, radius); + glVertex3f(length, 0, radius); + glVertex3f(length, 0, 0 - radius); + glVertex3f(0, 0, 0 - radius); + polys++; + glEnd(); + } + if (endcaps) { + for(ex = 0 ; ex <= length ; ex += length) { + z1 = radius; y1 = 0; + norm = (ex == length) ? 1 : -1; + glBegin(GL_TRIANGLES); + glNormal3f(norm, 0, 0); + for (a = 0 ; a <= angle ; a+= angle/nsegs) { + y2=radius*(float)ci->sin_table[(int)a]; + z2=radius*(float)ci->cos_table[(int)a]; + glVertex3f(ex,0, 0); + glVertex3f(ex,y1,z1); + glVertex3f(ex,y2,z2); + polys++; + z1=z2; + y1=y2; + } + glEnd(); + } + } + glPopMatrix(); + return polys; +} + +static int circle(Circuit *ci, float radius, int segments, int half) +{ + int polys = 0; + float x1 = 0, x2 = 0; + float y1 = 0, y2 = 0; + int i, t, s; + + if (half) { + t = 270; s = 90; + x1 = radius, y1 = 0; + } else { + t = 360, s = 0; + } + glBegin(GL_TRIANGLES); + glNormal3f(1, 0, 0); + for(i=s;i<=t;i+=10) + { + float angle=i; + x2=radius*(float)ci->cos_table[(int)angle]; + y2=radius*(float)ci->sin_table[(int)angle]; + glVertex3f(0,0,0); + glVertex3f(0,y1,x1); + glVertex3f(0,y2,x2); + polys++; + x1=x2; + y1=y2; + } + glEnd(); + return polys; +} + +static int wire(Circuit *ci, float len) +{ + int polys = 0; + GLfloat col[] = {0.3, 0.3, 0.3, 1.0}; + GLfloat spec[] = {0.9, 0.9, 0.9, 1.0}; + GLfloat nospec[] = {0.4, 0.4, 0.4, 1.0}; + GLfloat shin = 30; + int n; + + glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, col); + glMaterialfv(GL_FRONT, GL_SPECULAR, spec); + glMaterialfv(GL_FRONT, GL_SHININESS, &shin); + n = glIsEnabled(GL_NORMALIZE); + if (!n) glEnable(GL_NORMALIZE); + polys += createCylinder(ci, len, 0.05, 1, 0); + if (!n) glDisable(GL_NORMALIZE); + glMaterialfv(GL_FRONT, GL_SPECULAR, nospec); + return polys; +} + +#if 0 +static int ring(GLfloat inner, GLfloat outer, int nsegs) +{ + int polys = 0; + GLfloat z1, z2, y1, y2; + GLfloat Z1, Z2, Y1, Y2; + int i; + + z1 = inner; y1 = 0; + Z1 = outer; Y1 = 0; + glBegin(GL_QUADS); + glNormal3f(1, 0, 0); + for(i=0; i <=360 ; i+= 360/nsegs) + { + float angle=i; + z2=inner*(float)ci->sin_table[(int)angle]; + y2=inner*(float)ci->cos_table[(int)angle]; + Z2=outer*(float)ci->sin_table[(int)angle]; + Y2=outer*(float)ci->cos_table[(int)angle]; + glVertex3f(0, Y1, Z1); + glVertex3f(0, y1, z1); + glVertex3f(0, y2, z2); + glVertex3f(0, Y2, Z2); + polys++; + z1=z2; + y1=y2; + Z1=Z2; + Y1=Y2; + } + glEnd(); + return polys; +} +#endif + +static int sphere(Circuit *ci, GLfloat r, float stacks, float slices, + int startstack, int endstack, int startslice, + int endslice) +{ + int polys = 0; + GLfloat d, d1, dr, dr1, Dr, Dr1, D, D1, z1, z2, y1, y2, Y1, Z1, Y2, Z2; + int a, a1, b, b1, c0, c1; + GLfloat step, sstep; + + step = 180/stacks; + sstep = 360/slices; + a1 = startstack * step; + b1 = startslice * sstep; + y1 = z1 = Y1 = Z1 = 0; + c0 = (endslice / slices) * 360; + c1 = (endstack/stacks)*180; + glBegin(GL_QUADS); + for (a = startstack * step ; a <= c1 ; a+= step) { + d=ci->sin_table[a]; + d1=ci->sin_table[a1]; + D=ci->cos_table[a]; + D1=ci->cos_table[a1]; + dr = d * r; + dr1 = d1 * r; + Dr = D * r; + Dr1 = D1 * r; + for (b = b1 ; b <= c0 ; b+= sstep) { + y2=dr*ci->sin_table[b]; + z2=dr*ci->cos_table[b]; + Y2=dr1*ci->sin_table[b]; + Z2=dr1*ci->cos_table[b]; + glNormal3f(Dr, y1, z1); + glVertex3f(Dr,y1,z1); + glNormal3f(Dr, y2, z2); + glVertex3f(Dr,y2,z2); + glNormal3f(Dr1, Y2, Z2); + glVertex3f(Dr1,Y2,Z2); + glNormal3f(Dr1, Y1, Z1); + glVertex3f(Dr1,Y1,Z1); + polys++; + z1=z2; + y1=y2; + Z1=Z2; + Y1=Y2; + } + a1 = a; + } + glEnd(); + return polys; +} + +static int DrawComponent(Circuit *ci, Component *c, unsigned long *polysP) +{ + int polys = *polysP; + int ret = 0; /* return 1 if component is freed */ + + glPushMatrix(); + glTranslatef(c->x, c->y, c->z); + if (c->angle > 0) { + glRotatef(c->angle, c->rotx, c->roty, c->rotz); + } + if (spin) { + glRotatef(c->rdeg, c->rotx, c->roty, c->rotz); + c->rdeg += c->drot; + } + + if (c->norm) + glEnable(GL_NORMALIZE); + else + glDisable(GL_NORMALIZE); + + /* call object draw routine here */ + if (c->type == 0) { + polys += DrawResistor(ci, c->c); + } else if (c->type == 1) { + polys += DrawDiode(ci, c->c); + } else if (c->type == 2) { + polys += DrawTransistor(ci, c->c); + } else if (c->type == 3) { + if (((LED *)c->c)->light && ci->light) { + GLfloat lp[] = {0.1, 0, 0, 1}; + glEnable(GL_LIGHT1); + glLightfv(GL_LIGHT1, GL_POSITION, lp); + } + polys += DrawLED(ci, c->c); + } else if (c->type == 4) { + polys += DrawCapacitor(ci, c->c); + } else if (c->type == 5) { + polys += DrawIC(ci, c->c); + } else if (c->type == 6) { + polys += DrawDisp(ci, c->c); + } else if (c->type == 7) { + polys += DrawFuse(ci, c->c); + } else if (c->type == 8) { + polys += DrawRCA(ci, c->c); + } else if (c->type == 9) { + polys += DrawThreeFive(ci, c->c); + } else if (c->type == 10) { + polys += DrawSwitch(ci, c->c); + } + c->x += c->dx * MOVE_MULT; + c->y += c->dy * MOVE_MULT; + if (c->x > ci->XMAX/2 || c->x < 0 - ci->XMAX/2 || + c->y > ci->YMAX/2 || c->y < 0 - ci->YMAX/2) { + if (c->type == 3 && ((LED *)c->c)->light && ci->light) { + glDisable(GL_LIGHT1); + ci->light = 0; ci->lighton = 0; + } + if (c->type == 5) { + if (((IC *)c->c)->tnum) + freetexture(ci, ((IC *)c->c)->tnum); + } + if (c->type == 2) { + if (((Transistor *)c->c)->tnum) + freetexture(ci, ((Transistor *)c->c)->tnum); + } + if (c->type == 1) + free(((Diode *)c->c)->band); /* remember to free diode band */ + free(c->c); + ret = 1; + } + + glPopMatrix(); + glDisable(GL_NORMALIZE); + *polysP = polys; + return ret; +} + +/* draw a resistor */ + +static int DrawResistor(Circuit *ci, Resistor *r) +{ + int polys = 0; + int i; + GLfloat col[] = {0.74, 0.62, 0.46, 1.0}; + GLfloat spec[] = {0.8, 0.8, 0.8, 1.0}; + GLfloat shine = 30; + + glTranslatef(-4, 0, 0); + polys += wire(ci, 3); + glTranslatef(3, 0, 0); + glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, col); + glMaterialfv(GL_FRONT, GL_SPECULAR, spec); + glMaterialfv(GL_FRONT, GL_SHININESS, &shine); + polys += createCylinder(ci, 1.8, 0.4, 1, 0); + glPushMatrix(); + for (i = 0 ; i < 4 ; i++) { + glTranslatef(0.35, 0, 0); + glCallList(ci->band_list[r->b[i]]); + polys += ci->band_list_polys[r->b[i]]; + } + glPopMatrix(); + glTranslatef(1.8, 0, 0); + polys += wire(ci, 3); + return polys; +} + +static int DrawRCA(Circuit *ci, RCA *rca) +{ + int polys = 0; + GLfloat col[] = {0.6, 0.6, 0.6, 1.0}; /* metal */ + GLfloat red[] = {1.0, 0.0, 0.0, 1.0}; /* red */ + GLfloat white[] = {1.0, 1.0, 1.0, 1.0}; /* white */ + GLfloat spec[] = {1, 1, 1, 1}; /* glass */ + + glPushMatrix(); + glTranslatef(0.3, 0, 0); + glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, col); + glMateriali(GL_FRONT, GL_SHININESS, 40); + glMaterialfv(GL_FRONT, GL_SPECULAR, spec); + polys += createCylinder(ci, 0.7, 0.45, 0, 0); + glTranslatef(0.4, 0, 0); + polys += createCylinder(ci, 0.9, 0.15, 1, 0); + glTranslatef(-1.9, 0, 0); + glMateriali(GL_FRONT, GL_SHININESS, 20); + glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, rca->col ? white : red); + polys += createCylinder(ci, 1.5, 0.6, 1, 0); + glTranslatef(-0.9, 0, 0); + polys += createCylinder(ci, 0.9, 0.25, 0, 0); + glTranslatef(0.1, 0, 0); + polys += createCylinder(ci, 0.2, 0.3, 0, 0); + glTranslatef(0.3, 0, 0); + polys += createCylinder(ci, 0.2, 0.3, 1, 0); + glTranslatef(0.3, 0, 0); + polys += createCylinder(ci, 0.2, 0.3, 1, 0); + glPopMatrix(); + return polys; +} + +static int DrawSwitch(Circuit *ci, Switch *f) +{ + int polys = 0; + GLfloat col[] = {0.6, 0.6, 0.6, 0}; /* metal */ + GLfloat dark[] = {0.1, 0.1, 0.1, 1.0}; /* dark */ + GLfloat brown[] = {0.69, 0.32, 0, 1.0}; /* brown */ + GLfloat spec[] = {0.9, 0.9, 0.9, 1}; /* shiny */ + + glPushMatrix(); + glMaterialfv(GL_FRONT, GL_DIFFUSE, col); + glMaterialfv(GL_FRONT, GL_AMBIENT, dark); + glMaterialfv(GL_FRONT, GL_SPECULAR, spec); + glMateriali(GL_FRONT, GL_SHININESS, 90); + polys += Rect(-0.25, 0, 0, 1.5, 0.5, 0.75); +/* polys += Rect(-0.5, 0.5, 0, 2, 0.1, 0.75); */ + glPushMatrix(); + glRotatef(90, 1, 0, 0); + glTranslatef(-0.5, -0.4, -0.4); + polys += HoledRectangle(ci, 0.5, 0.75, 0.1, 0.15, 8); + glTranslatef(2, 0, 0); + polys += HoledRectangle(ci, 0.5, 0.75, 0.1, 0.15, 8); + glPopMatrix(); + polys += Rect(0.1, -0.4, -0.25, 0.1, 0.4, 0.05); + polys += Rect(0.5, -0.4, -0.25, 0.1, 0.4, 0.05); + polys += Rect(0.9, -0.4, -0.25, 0.1, 0.4, 0.05); + polys += Rect(0.1, -0.4, -0.5, 0.1, 0.4, 0.05); + polys += Rect(0.5, -0.4, -0.5, 0.1, 0.4, 0.05); + polys += Rect(0.9, -0.4, -0.5, 0.1, 0.4, 0.05); + glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, dark); + glMaterialfv(GL_FRONT, GL_SPECULAR, spec); + polys += Rect(0, 0.5, -0.1, 1, 0.05, 0.5); + polys += Rect(0, 0.6, -0.1, 0.5, 0.6, 0.5); + glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, brown); + polys += Rect(-0.2, -0.01, -0.1, 1.4, 0.1, 0.55); + glPopMatrix(); + return polys; +} + + +static int DrawFuse(Circuit *ci, Fuse *f) +{ + int polys = 0; + GLfloat col[] = {0.5, 0.5, 0.5, 1.0}; /* endcaps */ + GLfloat glass[] = {0.4, 0.4, 0.4, 0.3}; /* glass */ + GLfloat spec[] = {1, 1, 1, 1}; /* glass */ + + glPushMatrix(); + glTranslatef(-1.8, 0, 0); + glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, col); + glMaterialfv(GL_FRONT, GL_SPECULAR, spec); + glMateriali(GL_FRONT, GL_SHININESS, 40); + polys += createCylinder(ci, 0.8, 0.45, 1, 0); + glTranslatef(0.8, 0, 0); + glEnable(GL_BLEND); + glDepthMask(GL_FALSE); + glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, glass); + glMateriali(GL_FRONT_AND_BACK, GL_SHININESS, 40); + polys += createCylinder(ci, 2, 0.4, 0, 0); + polys += createCylinder(ci, 2, 0.3, 0, 0); + glDisable(GL_BLEND); + glDepthMask(GL_TRUE); + glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, col); + glMateriali(GL_FRONT, GL_SHININESS, 40); + glBegin(GL_LINES); + glVertex3f(0, 0, 0); + glVertex3f(2, 0. ,0); + glEnd(); + glTranslatef(2, 0, 0); + polys += createCylinder(ci, 0.8, 0.45, 1, 0); + glPopMatrix(); + return polys; +} + + +static int DrawCapacitor(Circuit *ci, Capacitor *c) +{ + int polys = 0; + GLfloat col[] = {0, 0, 0, 0}; + GLfloat spec[] = {0.8, 0.8, 0.8, 0}; + GLfloat brown[] = {0.84, 0.5, 0}; + GLfloat shine = 40; + + glPushMatrix(); + if (c->type) { + glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, brown); + polys += sphere(ci, c->width, 15, 15, 0, 4 ,0, 15); + glTranslatef(1.35*c->width, 0, 0); + polys += sphere(ci, c->width, 15, 15, 11, 15, 0, 15); + glRotatef(90, 0, 0, 1); + glTranslatef(0, 0.7*c->width, 0.3*c->width); + polys += wire(ci, 3*c->width); + glTranslatef(0, 0, -0.6*c->width); + polys += wire(ci, 3*c->width); + } else { + glTranslatef(0-c->length*2, 0, 0); + glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, col); + glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, spec); + glMaterialfv(GL_FRONT_AND_BACK, GL_SHININESS, &shine); + glBegin(GL_POLYGON); + glVertex3f(0, 0.82*c->width, -0.1); + glVertex3f(3*c->length, 0.82*c->width, -0.1); + glVertex3f(3*c->length, 0.82*c->width, 0.1); + glVertex3f(0, 0.82*c->width, 0.1); + glEnd(); + col[0] = 0.0; + col[1] = 0.2; + col[2] = 0.9; + glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, col); + glEnable(GL_POLYGON_OFFSET_FILL); + glPolygonOffset(1.0, 1.0); + polys += createCylinder(ci, 3.0*c->length, 0.8*c->width, 1, 0); + glDisable(GL_POLYGON_OFFSET_FILL); + col[0] = 0.7; + col[1] = 0.7; + col[2] = 0.7; + glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, col); + polys += circle(ci, 0.6*c->width, 30, 0); + col[0] = 0; + col[1] = 0; + col[2] = 0; + glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, col); + glTranslatef(3.0*c->length, 0.0, 0); + polys += circle(ci, 0.6*c->width, 30, 0); + glTranslatef(0, 0.4*c->width, 0); + polys += wire(ci, 3*c->length); + glTranslatef(0.0, -0.8*c->width, 0); + polys += wire(ci, 3.3*c->length); + } + glPopMatrix(); + return polys; +} + +static int DrawLED(Circuit *ci, LED *l) +{ + int polys = 0; + GLfloat col[] = {0, 0, 0, 0.6}; + GLfloat black[] = {0, 0, 0, 0.6}; + + col[0] = l->r; col[1] = l->g; col[2] = l->b; + if (l->light && ci->light) { + GLfloat dir[] = {-1, 0, 0}; + glLightfv(GL_LIGHT1, GL_SPOT_DIRECTION, dir); + if (!ci->lighton) { + glLightfv(GL_LIGHT1, GL_SPECULAR, col); + glLightfv(GL_LIGHT1, GL_AMBIENT, black); + col[0] /= 1.5; col[1] /= 1.5; col[2] /= 1.5; + glLightfv(GL_LIGHT1, GL_DIFFUSE, col); + glLighti(GL_LIGHT1, GL_SPOT_CUTOFF, (GLint) 90); + glLighti(GL_LIGHT1, GL_CONSTANT_ATTENUATION, (GLfloat)1); + glLighti(GL_LIGHT1, GL_LINEAR_ATTENUATION, (GLfloat)0); + glLighti(GL_LIGHT1, GL_QUADRATIC_ATTENUATION, (GLfloat)0); + glLighti(GL_LIGHT1, GL_SPOT_EXPONENT, (GLint) 20); + ci->lighton = 1; + } + } + glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, col); + glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, col); + /* no transparency when LED is lit */ + if (!l->light) { + glEnable(GL_BLEND); + glDepthMask(GL_FALSE); + glBlendFunc(GL_ONE_MINUS_SRC_ALPHA, GL_SRC_ALPHA); + } + glTranslatef(-0.9, 0, 0); + polys += createCylinder(ci, 1.2, 0.3, 0, 0); + if (l->light && ci->light) { + glDisable(GL_LIGHTING); + glColor3fv(col); + } + polys += sphere(ci, 0.3, 7, 7, 3, 7, 0, 7); + if (l->light && ci->light) { + glEnable(GL_LIGHTING); + } else { + glDepthMask(GL_TRUE); + glDisable(GL_BLEND); + } + + glTranslatef(1.2, 0, 0); + polys += createCylinder(ci, 0.1, 0.38, 1, 0); + glTranslatef(-0.3, 0.15, 0); + polys += wire(ci, 3); + glTranslatef(0, -0.3, 0); + polys += wire(ci, 3.3); + if (random() % 50 == 25) { + if (l->light) { + l->light = 0; ci->light = 0; ci->lighton = 0; + glDisable(GL_LIGHT1); + } else if (!ci->light) { + l->light = 1; + ci->light = 1; + } + } + return polys; +} + + +static int DrawThreeFive(Circuit *ci, ThreeFive *d) +{ + int polys = 0; + GLfloat shine = 40; + GLfloat const dark[] = {0.3, 0.3, 0.3, 0}; + GLfloat const light[] = {0.6, 0.6, 0.6, 0}; + GLfloat const cream[] = {0.8, 0.8, 0.6, 0}; + GLfloat const spec[] = {0.7, 0.7, 0.7, 0}; + + glPushMatrix(); + glMaterialfv(GL_FRONT, GL_SHININESS, &shine); + glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, cream); + glMaterialfv(GL_FRONT, GL_SPECULAR, spec); + + glTranslatef(-2.0, 0, 0); + polys += createCylinder(ci, 0.7, 0.2, 0, 0); + glTranslatef(0.7, 0, 0); + polys += createCylinder(ci, 1.3, 0.4, 1, 0); + glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, light); + glTranslatef(1.3, 0, 0); + polys += createCylinder(ci, 1.3, 0.2, 0, 0); + glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, dark); + glTranslatef(0.65, 0, 0); + polys += createCylinder(ci, 0.15, 0.21, 0, 0); + glTranslatef(0.3, 0, 0); + polys += createCylinder(ci, 0.15, 0.21, 0, 0); + glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, light); + glTranslatef(0.4, 0, 0); + polys += sphere(ci, 0.23, 7, 7, 0, 5, 0, 7); + + glPopMatrix(); + return polys; +} + +static int DrawDiode(Circuit *ci, Diode *d) +{ + int polys = 0; + GLfloat shine = 40; + GLfloat col[] = {0.3, 0.3, 0.3, 0}; + GLfloat spec[] = {0.7, 0.7, 0.7, 0}; + + glPushMatrix(); + glMaterialfv(GL_FRONT, GL_SHININESS, &shine); + glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, col); + glMaterialfv(GL_FRONT, GL_SPECULAR, spec); + glTranslatef(-4, 0, 0); + polys += wire(ci, 3); + glTranslatef(3, 0, 0); + polys += bandedCylinder(ci, 0.3, 1.5, d->r, d->g, d->b, &(d->band), 1); + glTranslatef(1.5, 0, 0); + polys += wire(ci, 3); + glPopMatrix(); + return polys; +} + +static int Rect(GLfloat x, GLfloat y, GLfloat z, GLfloat w, GLfloat h, + GLfloat t) +{ + int polys = 0; + GLfloat yh; + GLfloat xw; + GLfloat zt; + + yh = y+h; xw = x+w; zt = z - t; + + glBegin(GL_QUADS); /* front */ + glNormal3f(0, 0, 1); + glVertex3f(x, y, z); + glVertex3f(x, yh, z); + glVertex3f(xw, yh, z); + glVertex3f(xw, y, z); + polys++; + /* back */ + glNormal3f(0, 0, -1); + glVertex3f(x, y, zt); + glVertex3f(x, yh, zt); + glVertex3f(xw, yh, zt); + glVertex3f(xw, y, zt); + polys++; + /* top */ + glNormal3f(0, 1, 0); + glVertex3f(x, yh, z); + glVertex3f(x, yh, zt); + glVertex3f(xw, yh, zt); + glVertex3f(xw, yh, z); + polys++; + /* bottom */ + glNormal3f(0, -1, 0); + glVertex3f(x, y, z); + glVertex3f(x, y, zt); + glVertex3f(xw, y, zt); + glVertex3f(xw, y, z); + polys++; + /* left */ + glNormal3f(-1, 0, 0); + glVertex3f(x, y, z); + glVertex3f(x, y, zt); + glVertex3f(x, yh, zt); + glVertex3f(x, yh, z); + polys++; + /* right */ + glNormal3f(1, 0, 0); + glVertex3f(xw, y, z); + glVertex3f(xw, y, zt); + glVertex3f(xw, yh, zt); + glVertex3f(xw, yh, z); + polys++; + glEnd(); + return polys; +} + +/* IC pins */ + +static int ICLeg(GLfloat x, GLfloat y, GLfloat z, int dir) +{ + int polys = 0; + if (dir) { + polys += Rect(x-0.1, y, z, 0.1, 0.1, 0.02); + polys += Rect(x-0.1, y, z, 0.02, 0.1, 0.1); + polys += Rect(x-0.1, y+0.03, z-0.1, 0.02, 0.05, 0.3); + } else { + polys += Rect(x, y, z, 0.1, 0.1, 0.02); + polys += Rect(x+0.8*0.1, y, z, 0.02, 0.1, 0.1); + polys += Rect(x+0.8*0.1, y+0.03, z-0.1, 0.02, 0.05, 0.3); + } + return polys; +} + + +static int DrawIC(Circuit *ci, IC *c) +{ + int polys = 0; + GLfloat w, h, d; + int z; + GLfloat col[] = {0.1, 0.1, 0.1, 0}; + GLfloat col2[] = {0.2, 0.2, 0.2, 0}; + GLfloat spec[] = {0.6, 0.6, 0.6, 0}; + GLfloat shine = 40; + GLfloat lspec[] = {0.6, 0.6, 0.6, 0}; + GLfloat lcol[] = {0.4, 0.4, 0.4, 0}; + GLfloat lshine = 40; + float mult, th, size; + + glPushMatrix(); + glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, col); + glMaterialfv(GL_FRONT, GL_SPECULAR, spec); + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + glMaterialfv(GL_FRONT, GL_SHININESS, &shine); + switch(c->pins) { + case 8: + w = 1.0; h = 1.5; + break; + case 14: + w = 1.0; h = 3; + break; + case 16: + w = 1.0; h = 3; + break; + case 24: + default: + w = 1.5; h = 3.5; + break; + } + w = w/2; h = h/2; + glEnable(GL_POLYGON_OFFSET_FILL); + glPolygonOffset(1.0, 1.0); + glBegin(GL_QUADS); + glNormal3f(0, 0, 1); + glVertex3f(w, h, 0.1); + glVertex3f(w, -h, 0.1); + glVertex3f(-w, -h, 0.1); + glVertex3f(-w, h, 0.1); + polys++; + glNormal3f(0, 0, -1); + glVertex3f(w, h, -0.1); + glVertex3f(w, -h, -0.1); + glVertex3f(-w, -h, -0.1); + glVertex3f(-w, h, -0.1); + polys++; + glNormal3f(1, 0, 0); + glVertex3f(w, h, -0.1); + glVertex3f(w, -h, -0.1); + glVertex3f(w, -h, 0.1); + glVertex3f(w, h, 0.1); + polys++; + glNormal3f(0, -1, 0); + glVertex3f(w, -h, -0.1); + glVertex3f(w, -h, 0.1); + glVertex3f(-w, -h, 0.1); + glVertex3f(-w, -h, -0.1); + polys++; + glNormal3f(-1, 0, 0); + glVertex3f(-w, h, -0.1); + glVertex3f(-w, h, 0.1); + glVertex3f(-w, -h, 0.1); + glVertex3f(-w, -h, -0.1); + polys++; + glNormal3f(0, -1, 0); + glVertex3f(-w, h, -0.1); + glVertex3f(w, h, -0.1); + glVertex3f(w, h, 0.1); + glVertex3f(-w, h, 0.1); + polys++; + glEnd(); + glDisable(GL_POLYGON_OFFSET_FILL); + if (c->tnum) glBindTexture(GL_TEXTURE_2D, c->tnum); + glEnable(GL_TEXTURE_2D); + glEnable(GL_BLEND); + if (c->pins == 8) + size = 0.4; + else + size = 0.6; + th = size*2/3; + mult = size*c->tw / c->th; + mult /= 2; + glBegin(GL_QUADS); /* text markings */ + glNormal3f(0, 0, 1); + glTexCoord2f(0, 1); + glVertex3f(th, mult, 0.1); + glTexCoord2f(1, 1); + glVertex3f(th, -mult, 0.1); + glTexCoord2f(1, 0); + glVertex3f(-th, -mult, 0.1); + glTexCoord2f(0, 0); + glVertex3f(-th, mult, 0.1); + polys++; + glEnd(); + glDisable(GL_TEXTURE_2D); + glDisable(GL_BLEND); + d = (h*2-0.1) / c->pins; + d*=2; + glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, lcol); + glMaterialfv(GL_FRONT, GL_SPECULAR, lspec); + glMaterialfv(GL_FRONT, GL_SHININESS, &lshine); + for (z = 0 ; z < c->pins/2 ; z++) { + polys += ICLeg(w, -h + z*d + d/2, 0, 0); + } + for (z = 0 ; z < c->pins/2 ; z++) { + polys += ICLeg(-w, -h + z*d + d/2, 0, 1); + } + glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, col2); + glTranslatef(-w+0.3, h-0.3, 0.1); + glRotatef(90, 0, 1, 0); + polys += circle(ci, 0.1, 7, 0); + glPopMatrix(); + return polys; +} + +static int DrawDisp(Circuit *ci, Disp *d) +{ + int polys = 0; + GLfloat col[] = {0.8, 0.8, 0.8, 1.0}; /* body colour */ + GLfloat front[] = {0.2, 0.2, 0.2, 1.0}; /* front colour */ + GLfloat on[] = {0.9, 0, 0, 1}; /* 'on' segment */ + GLfloat off[] = {0.3, 0, 0, 1}; /* 'off' segment */ + int i, j, k; + GLfloat x, y; /* for the pins */ + GLfloat spec[] = {0.6, 0.6, 0.6, 0}; + GLfloat lcol[] = {0.4, 0.4, 0.4, 0}; + GLfloat shine = 40; + static const GLfloat vdata_h[6][2] = { + {0, 0}, + {0.1, 0.1}, + {0.9, 0.1}, + {1, 0}, + {0.9, -0.1}, + {0.1, -0.1} + }; + static const GLfloat vdata_v[6][2] = { + {0.27, 0}, + {0.35, -0.1}, + {0.2, -0.9}, + {0.1, -1}, + {0, -0.9}, + {0.15, -0.15} + }; + + static const GLfloat seg_start[7][2] = { + {0.55, 2.26}, + {1.35, 2.26}, + {1.2, 1.27}, + {0.25, 0.25}, + {0.06, 1.25}, + {0.25, 2.25}, + {0.39, 1.24} + }; + + static const int nums[10][7] = { + {1, 1, 1, 1, 1, 1, 0}, /* 0 */ + {0, 1, 1, 0, 0, 0, 0}, /* 1 */ + {1, 1, 0, 1, 1, 0, 1}, /* 2 */ + {1, 1, 1, 1, 0, 0, 1}, /* 3 */ + {0, 1, 1, 0, 0, 1, 1}, /* 4 */ + {1, 0, 1, 1, 0, 1, 1}, /* 5 */ + {1, 0, 1, 1, 1, 1, 1}, /* 6 */ + {1, 1, 1, 0, 0, 0, 0}, /* 7 */ + {1, 1, 1, 1, 1, 1, 1}, /* 8 */ + {1, 1, 1, 0, 0, 1, 1} /* 9 */ + }; + + glTranslatef(-0.9, -1.8, 0); + glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, col); + polys += Rect(0, 0, -0.01, 1.8, 2.6, 0.7); + glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, front); + glBegin(GL_QUADS); + glVertex2f(-0.05, -0.05); + glVertex2f(-0.05, 2.65); + glVertex2f(1.85, 2.65); + glVertex2f(1.85, -0.05); + polys++; + glEnd(); + glDisable(GL_LIGHTING); /* lit segments dont need light */ + if (!seven && (random() % 30) == 19) { /* randomly change value */ + d->value = random() % 10; + } + for (j = 0 ; j < 7 ; j++) { /* draw the segments */ + GLfloat xx[6], yy[6]; + if (nums[d->value][j]) + glColor3fv(on); + else + glColor3fv(off); + for (k = 0 ; k < 6 ; k++) { + if (j == 0 || j == 3 || j == 6) { + xx[k] = seg_start[j][0] + vdata_h[k][0]; + yy[k] = seg_start[j][1] + vdata_h[k][1]; + } else { + xx[k] = seg_start[j][0] + vdata_v[k][0]; + yy[k] = seg_start[j][1] + vdata_v[k][1]; + } + } + glBegin(GL_POLYGON); + for(i = 0 ; i < 6 ; i++) { + glVertex3f(xx[i], yy[i], 0.01); + } + polys++; + glEnd(); + } + glColor3fv(on); + glPointSize(4); + glBegin(GL_POINTS); + glVertex3f(1.5, 0.2, 0.01); + polys++; + glEnd(); + glEnable(GL_LIGHTING); + glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, lcol); + glMaterialfv(GL_FRONT, GL_SPECULAR, spec); + glMaterialfv(GL_FRONT, GL_SHININESS, &shine); + for (x = 0.35 ; x <= 1.5 ; x+= 1.15) { + for ( y = 0.2 ; y <= 2.4 ; y += 0.3) { + polys += ICLeg(x, y, -0.7, 1); + } + } + return polys; +} + +static int HoledRectangle(Circuit *ci, + GLfloat w, GLfloat h, GLfloat d, GLfloat radius, + int p) +{ + int polys = 0; + int step, a; + GLfloat x1, y1, x2, y2; + GLfloat yr, yr1, xr, xr1, side, side1; + GLfloat nx, ny; + + step = 360 / p; + x1 = radius; y1 = 0; + xr1 = w/2; yr1 = 0; + side = w/2; + side1 = h/2; + glBegin(GL_QUADS); + for (a = 0 ; a <= 360 ; a+= step) { + y2=radius*(float)ci->sin_table[(int)a]; + x2=radius*(float)ci->cos_table[(int)a]; + + if (a < 45 || a > 315) { + xr = side; + yr = side1 * ci->tan_table[a]; + nx = 1; ny = 0; + } else if (a <= 135 || a >= 225) { + xr = side/ci->tan_table[a]; + if (a >= 225) { + yr = -side1; + xr = 0 - xr; + nx = 0; ny = -1; + } else { + yr = side1; + nx = 0; ny = 1; + } + } else { + xr = -side; + yr = -side1 * ci->tan_table[a]; + nx = -1; ny = 0; + } + + glNormal3f(-x1, -y1, 0); /* cylinder */ + glVertex3f(x1,y1,0); + glVertex3f(x1,y1,-d); + glVertex3f(x2,y2,-d); + glVertex3f(x2,y2,0); + polys++; + + glNormal3f(0, 0, 1); /* front face */ + glVertex3f(x1,y1,0); + glVertex3f(xr1, yr1, 0); + glVertex3f(xr, yr, 0); + glVertex3f(x2, y2, 0); + polys++; + + glNormal3f(nx, ny, 0); /* side */ + glVertex3f(xr, yr, 0); + glVertex3f(xr, yr, -d); + glVertex3f(xr1, yr1, -d); + glVertex3f(xr1, yr1, 0); + polys++; + + glNormal3f(0, 0, -1); /* back */ + glVertex3f(xr, yr, -d); + glVertex3f(x2, y2, -d); + glVertex3f(x1, y1, -d); + glVertex3f(xr1, yr1, -d); + polys++; + + x1=x2; + y1=y2; + xr1 = xr; yr1 = yr; + } + glEnd(); + return polys; +} + +static int DrawTransistor(Circuit *ci, Transistor *t) +{ + int polys = 0; + GLfloat col[] = {0.3, 0.3, 0.3, 1.0}; + GLfloat spec[] = {0.9, 0.9, 0.9, 1.0}; + GLfloat nospec[] = {0.4, 0.4, 0.4, 1.0}; + GLfloat shin = 30; + + glPushMatrix(); + glMaterialfv(GL_FRONT, GL_SHININESS, &shin); + glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, col); + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + if (t->type == 1) { /* TO-92 style */ + float mult, y1, y2; + mult = 1.5*t->th/t->tw; + y1 = 0.2+mult/2; + y2 = 0.8-mult/2; + glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, col); + glRotatef(90, 0, 1, 0); + glRotatef(90, 0, 0, 1); + polys += createCylinder(ci, 1.0, 0.4, 1, 1); + polys += Rect(0, -0.2, 0.4, 1, 0.2, 0.8); +/* Draw the markings */ + glEnable(GL_TEXTURE_2D); + if (t->tnum) glBindTexture(GL_TEXTURE_2D, t->tnum); + glEnable(GL_BLEND); + glDepthMask(GL_FALSE); + glBegin (GL_QUADS); + glNormal3f(0, 0, 1); + glTexCoord2f(0, 1); + glVertex3f(y1, -0.21, 0.3); + glTexCoord2f(1, 1); + glVertex3f(y1, -0.21, -0.3); + glTexCoord2f(1, 0); + glVertex3f(y2, -0.21, -0.3); + glTexCoord2f(0, 0); + glVertex3f(y2, -0.21, 0.3); + polys++; + glEnd(); + glDisable(GL_TEXTURE_2D); + glDisable(GL_BLEND); + glDepthMask(GL_TRUE); + glTranslatef(-2, 0, -0.2); + polys += wire(ci, 2); + glTranslatef(0, 0, 0.2); + polys += wire(ci, 2); + glTranslatef(0, 0, 0.2); + polys += wire(ci, 2); + } else if (t->type == 0) { /* TO-220 Style */ + float mult, y1, y2; + mult = 1.5*t->th/t->tw; + y1 = 0.75+mult/2; + y2 = 0.75-mult/2; + polys += Rect(0, 0, 0, 1.5, 1.5, 0.5); + glEnable(GL_TEXTURE_2D); + if (t->tnum) glBindTexture(GL_TEXTURE_2D, t->tnum); + glEnable(GL_BLEND); + glDepthMask(GL_FALSE); + glBegin (GL_QUADS); + glNormal3f(0, 0, 1); + glTexCoord2f(0, 1); + glVertex3f(0, y1, 0.01); + glTexCoord2f(1, 1); + glVertex3f(1.5, y1, 0.01); + glTexCoord2f(1, 0); + glVertex3f(1.5, y2, 0.01); + glTexCoord2f(0, 0); + glVertex3f(0, y2, 0.01); + glEnd(); + glDisable(GL_TEXTURE_2D); + glDisable(GL_BLEND); + glDepthMask(GL_TRUE); + glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, col); + glMaterialfv(GL_FRONT, GL_SPECULAR, spec); + glMaterialfv(GL_FRONT, GL_SHININESS, &shin); + polys += Rect(0, 0, -0.5, 1.5, 1.5, 0.30); + if (!glIsEnabled(GL_NORMALIZE)) glEnable(GL_NORMALIZE); + glTranslatef(0.75, 1.875, -0.55); + polys += HoledRectangle(ci, 1.5, 0.75, 0.25, 0.2, 8); + glMaterialfv(GL_FRONT, GL_SPECULAR, nospec); + glTranslatef(-0.375, -1.875, 0); + glRotatef(90, 0, 0, -1); + polys += wire(ci, 2); + glTranslatef(0, 0.375, 0); + polys += wire(ci, 2); + glTranslatef(0, 0.375, 0); + polys += wire(ci, 2); + } else { /* SMC transistor */ +/* Draw the body */ + glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, col); + glTranslatef(-0.5, -0.25, 0.1); + polys += Rect(0, 0, 0, 1, 0.5, 0.2); +/* Draw the markings */ + glEnable(GL_TEXTURE_2D); + if (t->tnum) glBindTexture(GL_TEXTURE_2D, t->tnum); + glEnable(GL_BLEND); + glDepthMask(GL_FALSE); + glBegin (GL_QUADS); + glNormal3f(0, 0, 1); + glTexCoord2f(0, 1); + glVertex3f(0.2, 0, 0.01); + glTexCoord2f(1, 1); + glVertex3f(0.8, 0, 0.01); + glTexCoord2f(1, 0); + glVertex3f(0.8, 0.5, 0.01); + glTexCoord2f(0, 0); + glVertex3f(0.2, 0.5, 0.01); + polys++; + glEnd(); + glDisable(GL_TEXTURE_2D); + glDisable(GL_BLEND); + glDepthMask(GL_TRUE); +/* Now draw the legs */ + glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, col); + glMaterialfv(GL_FRONT, GL_SPECULAR, spec); + glMaterialfv(GL_FRONT, GL_SHININESS, &shin); + polys += Rect(0.25, -0.1, -0.05, 0.1, 0.1, 0.2); + polys += Rect(0.75, -0.1, -0.05, 0.1, 0.1, 0.2); + polys += Rect(0.5, 0.5, -0.05, 0.1, 0.1, 0.2); + polys += Rect(0.25, -0.2, -0.2, 0.1, 0.15, 0.1); + polys += Rect(0.75, -0.2, -0.2, 0.1, 0.15, 0.1); + polys += Rect(0.5, 0.5, -0.2, 0.1, 0.15, 0.1); + } + glPopMatrix(); + return polys; +} + +static Component * NewComponent(ModeInfo *mi) +{ + Circuit *ci = &circuit[MI_SCREEN(mi)]; + Component *c; + float rnd; + + c = malloc(sizeof(Component)); + c->angle = RAND_RANGE(0,360); + rnd = f_rand(); + if (rnd < 0.25) { /* come from the top */ + c->y = ci->YMAX/2; + c->x = RAND_RANGE(0, ci->XMAX) - ci->XMAX/2; + if (c->x > 0) + c->dx = 0 - RAND_RANGE(0.5, 2); + else + c->dx = RAND_RANGE(0.5, 2); + c->dy = 0 - RAND_RANGE(0.5, 2); + } else if (rnd < 0.5) { /* come from the bottom */ + c->y = 0 - ci->YMAX/2; + c->x = RAND_RANGE(0, ci->XMAX) - ci->XMAX/2; + if (c->x > 0) + c->dx = 0 - RAND_RANGE(0.5, 2); + else + c->dx = RAND_RANGE(0.5, 2); + c->dy = RAND_RANGE(0.5, 2); + } else if (rnd < 0.75) { /* come from the left */ + c->x = 0 - ci->XMAX/2; + c->y = RAND_RANGE(0, ci->YMAX) - ci->YMAX/2; + c->dx = RAND_RANGE(0.5, 2); + if (c->y > 0) + c->dy = 0 - RAND_RANGE(0.5, 2); + else + c->dy = RAND_RANGE(0.5, 2); + } else { /* come from the right */ + c->x = ci->XMAX/2; + c->y = RAND_RANGE(0, ci->YMAX) - ci->YMAX/2; + c->dx = 0 - RAND_RANGE(0.5, 2); + if (c->y > 0) + c->dy = 0 - RAND_RANGE(0.5, 2); + else + c->dy = RAND_RANGE(0.5, 2); + } + c->z = RAND_RANGE(0, 7) - 9; + c->rotx = f_rand(); + c->roty = f_rand(); + c->rotz = f_rand(); + c->drot = f_rand() * 3; + c->rdeg = 0; + c->dz = f_rand()*2 - 1; + c->norm = 0; + c->alpha = 0; /* explicitly set to 1 later */ + rnd = random() % 11; + if (rnd < 1) { + c->c = NewResistor(); + c->type = 0; + if (f_rand() < 0.4) + c->norm = 1; /* some resistors shine */ + } else if (rnd < 2) { + c->c = NewDiode(); + if (f_rand() < 0.4) + c->norm = 1; /* some diodes shine */ + c->type = 1; + } else if (rnd < 3) { + c->c = NewTransistor(mi); + c->norm = 1; + c->type = 2; + } else if (rnd < 4) { + c->c = NewCapacitor(ci); + c->norm = 1; + c->type = 4; + } else if (rnd < 5) { + c->c = NewIC(mi); + c->type = 5; + c->norm = 1; + } else if (rnd < 6) { + c->c = NewLED(ci); + c->type = 3; + c->norm = 1; + c->alpha = 1; + } else if (rnd < 7) { + c->c = NewFuse(ci); + c->norm = 1; + c->type = 7; + c->alpha = 1; + } else if (rnd < 8) { + c->c = NewRCA(ci); + c->norm = 1; + c->type = 8; + } else if (rnd < 9) { + c->c = NewThreeFive(ci); + c->norm = 1; + c->type = 9; + } else if (rnd < 10) { + c->c = NewSwitch(ci); + c->norm = 1; + c->type = 10; + } else { + c->c = NewDisp(ci); + c->type = 6; + } + return c; +} + +static Transistor *NewTransistor(ModeInfo *mi) +{ + Transistor *t; + float texfg[] = {0.7, 0.7, 0.7, 1.0}; + float texbg[] = {0.3, 0.3, 0.3, 0.1}; + TexNum *tn; + const char *val; + + t = malloc(sizeof(Transistor)); + t->type = (random() % 3); + if (t->type == 0) { + val = transistortypes[random() % countof(transistortypes)]; + tn = fonttexturealloc(mi, val, texfg, texbg); + if (tn == NULL) { + fprintf(stderr, "Error getting a texture for a string!\n"); + t->tnum = 0; + } else { + t->tnum = tn->num; + t->tw = tn->w; t->th = tn->h; + free(tn); + } + } else if (t->type == 2) { + val = smctypes[random() % countof(smctypes)]; + tn = fonttexturealloc(mi, val, texfg, texbg); + if (tn == NULL) { + fprintf(stderr, "Error getting a texture for a string!\n"); + t->tnum = 0; + } else { + t->tnum = tn->num; + t->tw = tn->w; t->th = tn->h; + free(tn); + } + } else if (t->type == 1) { + val = to92types[random() % countof(to92types)]; + tn = fonttexturealloc(mi, val, texfg, texbg); + if (tn == NULL) { + fprintf(stderr, "Error getting a texture for a string!\n"); + t->tnum = 0; + } else { + t->tnum = tn->num; + t->tw = tn->w; t->th = tn->h; + free(tn); + } + } + + return t; +} + +static Capacitor *NewCapacitor(Circuit *ci) +{ + Capacitor *c; + + c = malloc(sizeof(Capacitor)); + c->type = (f_rand() < 0.5); + if (!c->type) { + c->length = RAND_RANGE(0.5, 1); + c->width = RAND_RANGE(0.5, 1); + } else { + c->width = RAND_RANGE(0.3, 1); + } + return c; +} + +/* 7 segment display */ + +static Disp *NewDisp(Circuit *ci) +{ + Disp *d; + + d = malloc(sizeof(Disp)); + if (seven) + d->value = 7; + else + d->value = RAND_RANGE(0, 10); + return d; +} + + +static IC *NewIC(ModeInfo *mi) +{ + IC *c; + int pins; + TexNum *tn; + float texfg[] = {0.7, 0.7, 0.7, 1.0}; + float texbg[] = {0.1, 0.1, 0.1, 0}; + const char *val; + char *str; + int types[countof(ictypes)], i, n = 0; + + c = malloc(sizeof(IC)); + c->type = 0; + switch((int)RAND_RANGE(0,4)) { + case 0: + pins = 8; + break; + case 1: + pins = 14; + break; + case 2: + pins = 16; + break; + case 3: + default: + pins = 24; + break; + } + for (i = 0 ; i < countof(ictypes) ; i++) { + if (ictypes[i].pins == pins) { + types[n] = i; + n++; + } + } + + if (n > countof(types)) abort(); + val = ictypes[types[random() % n]].val; + str = malloc(strlen(val) + 1 + 4 + 1); /* add space for production date */ + sprintf(str, "%s\n%02d%02d", val, (int)RAND_RANGE(80, 100), (int)RAND_RANGE(1,53)); + tn = fonttexturealloc(mi, str, texfg, texbg); + free(str); + if (tn == NULL) { + fprintf(stderr, "Error allocating font texture for '%s'\n", val); + c->tnum = 0; + } else { + c->tw = tn->w; c->th = tn->h; + c->tnum = tn->num; + free(tn); + } + c->pins = pins; + return c; +} + +static LED *NewLED(Circuit *ci) +{ + LED *l; + float r; + + l = malloc(sizeof(LED)); + r = f_rand(); + l->light = 0; + if (!ci->light && (f_rand() < 0.4)) { + ci->light = 1; + l->light = 1; + } + if (r < 0.2) { + l->r = 0.9; l->g = 0; l->b = 0; + } else if (r < 0.4) { + l->r = 0.3; l->g = 0.9; l->b = 0; + } else if (r < 0.6) { + l->r = 0.8; l->g = 0.9; l->b = 0; + } else if (r < 0.8) { + l->r = 0.0; l->g = 0.2; l->b = 0.8; + } else { + l->r = 0.9, l->g = 0.55, l->b = 0; + } + return l; +} + +static Fuse *NewFuse(Circuit *ci) +{ + Fuse *f; + + f = malloc(sizeof(Fuse)); + return f; +} + +static RCA *NewRCA(Circuit *ci) +{ + RCA *r; + + r = malloc(sizeof(RCA)); + r->col = (random() % 10 < 5); + return r; +} + +static ThreeFive *NewThreeFive(Circuit *ci) +{ + ThreeFive *r; + + r = malloc(sizeof(ThreeFive)); + return r; +} + +static Switch *NewSwitch(Circuit *ci) +{ + Switch *s; + + s = malloc(sizeof(Switch)); + s->position = 0; + return s; +} + +static Diode *NewDiode(void) +{ + Band *b; + Diode *ret; + + ret = malloc(sizeof(Diode)); + b = malloc(sizeof(Band)); + b->pos = 0.8; + b->len = 0.1; + if (f_rand() < 0.5) { + b->r = 1; + b->g = 1; + b->b = 1; + ret->r = 0.7; ret->g = 0.1 ; ret->b = 0.1; + } else { + b->r = 1; + b->g = 1; + b->b = 1; + ret->r = 0.2; ret->g = 0.2 ; ret->b = 0.2; + } + ret->band = b; + return ret; +} + + +static Resistor * NewResistor(void) +{ + int v, m, t; /* value, multiplier, tolerance */ + Resistor *ret; + + v = RAND(9); + m = RAND(5); + t = (RAND(10) < 5) ? 10 : 11; + ret = malloc(sizeof(Resistor)); + + if (seven) { + ret->b[0] = ret->b[1] = ret->b[2] = 7; + } else { + ret->b[0] = values[v][0]; + ret->b[1] = values[v][1]; + ret->b[2] = m; + } + ret->b[3] = t; + + return ret; +} + +static void makebandlist(Circuit *ci) +{ + int i; + GLfloat col[] = {0,0,0,0}; + GLfloat spec[] = {0.8,0.8,0.8,0}; + GLfloat shine = 40; + + for (i = 0 ; i < 12 ; i++) { + ci->band_list[i] = glGenLists(1); + glNewList(ci->band_list[i], GL_COMPILE); + col[0] = colorcodes[i][0]; + col[1] = colorcodes[i][1]; + col[2] = colorcodes[i][2]; + glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, col); + glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, spec); + glMaterialfv(GL_FRONT_AND_BACK, GL_SHININESS, &shine); + ci->band_list_polys[i] = createCylinder(ci, 0.1, 0.42, 0, 0); + glEndList(); + } +} + + +static int bandedCylinder(Circuit *ci, + float radius, float l, + GLfloat r, GLfloat g, GLfloat bl, + Band **b, int nbands) +{ + int polys = 0; + int n; /* band number */ + GLfloat col[] = {0,0,0,0}; + + col[0] = r; col[1] = g; col[2] = bl; + glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, col); + polys += createCylinder(ci, l, radius, 1, 0); /* body */ + for (n = 0 ; n < nbands ; n++) { + glPushMatrix(); + glTranslatef(b[n]->pos*l, 0, 0); + col[0] = b[n]->r; col[1] = b[n]->g; col[2] = b[n]->b; + glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, col); + polys += createCylinder(ci, b[n]->len*l, radius*1.05, 0, 0); /* band */ + glPopMatrix(); + } + return polys; +} + +static int drawgrid(Circuit *ci) +{ + int polys = 0; + GLfloat x, y; + GLfloat col3[] = {0, 0.8, 0}; + + if (!ci->draw_s) { + if (f_rand() < ((rotatespeed > 0) ? 0.05 : 0.01)) { + ci->draw_sdir = RAND_RANGE(0, 4); + ci->draw_ds = RAND_RANGE(0.4, 0.8); + switch (ci->draw_sdir) { + case 0: + ci->draw_sx = -ci->XMAX/2; + ci->draw_sy = ((int)RAND_RANGE(0, ci->YMAX/2))*2 - ci->YMAX/2; + break; + case 1: + ci->draw_sx = ci->XMAX/2; + ci->draw_sy = ((int)RAND_RANGE(0, ci->YMAX/2))*2 - ci->YMAX/2; + break; + case 2: + ci->draw_sy = ci->YMAX/2; + ci->draw_sx = ((int)RAND_RANGE(0, ci->XMAX/2))*2 - ci->XMAX/2; + break; + case 3: + ci->draw_sy = -ci->YMAX/2; + ci->draw_sx = ((int)RAND_RANGE(0, ci->XMAX/2))*2 - ci->XMAX/2; + break; + } + ci->draw_s = 1; + } + } else if (rotatespeed <= 0) { + if (ci->grid_col[1] < 0.25) { + ci->grid_col[1] += 0.025; ci->grid_col[2] += 0.005; + ci->grid_col2[1] += 0.015 ; ci->grid_col2[2] += 0.005; + } + } + + glDisable(GL_LIGHTING); + if (ci->draw_s) { + glColor3fv(col3); + glPushMatrix(); + glTranslatef(ci->draw_sx, ci->draw_sy, -10); + polys += sphere(ci, 0.1, 10, 10, 0, 10, 0, 10); + if (ci->draw_sdir == 0) + glTranslatef(-ci->draw_ds, 0, 0); + if (ci->draw_sdir == 1) + glTranslatef(ci->draw_ds, 0, 0); + if (ci->draw_sdir == 2) + glTranslatef(0, ci->draw_ds, 0); + if (ci->draw_sdir == 3) + glTranslatef(0, -ci->draw_ds, 0); + polys += sphere(ci, 0.05, 10, 10, 0, 10, 0, 10); + glPopMatrix(); + if (ci->draw_sdir == 0) { + ci->draw_sx += ci->draw_ds; + if (ci->draw_sx > ci->XMAX/2) + ci->draw_s = 0; + } + if (ci->draw_sdir == 1) { + ci->draw_sx -= ci->draw_ds; + if (ci->draw_sx < -ci->XMAX/2) + ci->draw_s = 0; + } + if (ci->draw_sdir == 2) { + ci->draw_sy -= ci->draw_ds; + if (ci->draw_sy < ci->YMAX/2) + ci->draw_s = 0; + } + if (ci->draw_sdir == 3) { + ci->draw_sy += ci->draw_ds; + if (ci->draw_sy > ci->YMAX/2) + ci->draw_s = 0; + } + } else if (rotatespeed <= 0) { + if (ci->grid_col[1] > 0) { + ci->grid_col[1] -= 0.0025; ci->grid_col[2] -= 0.0005; + ci->grid_col2[1] -= 0.0015 ; ci->grid_col2[2] -= 0.0005; + } + } + for (x = -ci->XMAX/2 ; x <= ci->XMAX/2 ; x+= 2) { + glColor3fv(ci->grid_col); + glBegin(GL_LINES); + glVertex3f(x, ci->YMAX/2, -10); + glVertex3f(x, -ci->YMAX/2, -10); + glColor3fv(ci->grid_col2); + glVertex3f(x-0.02, ci->YMAX/2, -10); + glVertex3f(x-0.02, -ci->YMAX/2, -10); + glVertex3f(x+0.02, ci->YMAX/2, -10); + glVertex3f(x+0.02, -ci->YMAX/2, -10); + glEnd(); + } + for (y = -ci->YMAX/2 ; y <= ci->YMAX/2 ; y+= 2) { + glColor3fv(ci->grid_col); + glBegin(GL_LINES); + glVertex3f(-ci->XMAX/2, y, -10); + glVertex3f(ci->XMAX/2, y, -10); + glColor3fv(ci->grid_col2); + glVertex3f(-ci->XMAX/2, y-0.02, -10); + glVertex3f(ci->XMAX/2, y-0.02, -10); + glVertex3f(-ci->XMAX/2, y+0.02, -10); + glVertex3f(ci->XMAX/2, y+0.02, -10); + glEnd(); + } + glEnable(GL_LIGHTING); + return polys; +} + +static void display(ModeInfo *mi) +{ + Circuit *ci = &circuit[MI_SCREEN(mi)]; + GLfloat light_sp[] = {0.8, 0.8, 0.8, 1.0}; + GLfloat black[] = {0, 0, 0, 1.0}; + int j; + + mi->polygon_count = 0; + + if (ci->display_i == 0) { + for (ci->display_i = 0 ; ci->display_i < maxparts ; ci->display_i++) { + ci->components[ci->display_i] = NULL; + } + } + glEnable(GL_LIGHTING); + glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT); + glLoadIdentity(); + glRotatef(current_device_rotation(), 0, 0, 1); + gluLookAt(ci->viewer[0], ci->viewer[1], ci->viewer[2], + 0.0, 0.0, 0.0, + 0.0, 1.0, 0.0); + glPushMatrix(); + glRotatef(ci->rotate_angle, 0, 0, 1); + ci->rotate_angle += 0.01 * (float)rotatespeed; + if (ci->rotate_angle >= 360) ci->rotate_angle = 0; + + glLightfv(GL_LIGHT0, GL_POSITION, ci->lightpos); + glLightfv(GL_LIGHT0, GL_SPECULAR, light_sp); + glLightfv(GL_LIGHT0, GL_DIFFUSE, light_sp); + glLighti(GL_LIGHT0, GL_CONSTANT_ATTENUATION, (GLfloat)1); + glLighti(GL_LIGHT0, GL_LINEAR_ATTENUATION, (GLfloat)0.5); + glLighti(GL_LIGHT0, GL_QUADRATIC_ATTENUATION, (GLfloat)0); + mi->polygon_count += drawgrid(ci); + glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, light_sp); + if (f_rand() < 0.05) { + for (j = 0 ; j < maxparts ; j++) { + if (ci->components[j] == NULL) { + ci->components[j] = NewComponent(mi); + j = maxparts; + } + } + reorder(&ci->components[0]); + } + for (j = 0 ; j < maxparts ; j++) { + glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, black); + glMaterialfv(GL_FRONT, GL_EMISSION, black); + glMaterialfv(GL_FRONT, GL_SPECULAR, black); + if (ci->components[j] != NULL) { + if (DrawComponent(ci, ci->components[j], &mi->polygon_count)) { + free(ci->components[j]); ci->components[j] = NULL; + } + } + } + glPopMatrix(); + glFlush(); +} + +static void freetexture (Circuit *ci, GLuint texture) +{ + ci->s_refs[texture]--; + if (ci->s_refs[texture] < 1) { + glDeleteTextures(1, &texture); + } +} + +static TexNum * fonttexturealloc (ModeInfo *mi, + const char *str, float *fg, float *bg) +{ + Circuit *ci = &circuit[MI_SCREEN(mi)]; + int i; + XImage *ximage; + char *c; + TexNum *t; + GLuint mintex; + if (ci->font_init == 0) { + for (i = 0 ; i < 50 ; i++) { + ci->font_strings[i] = NULL; + ci->s_refs[i] = 0; + ci->font_w[i] = 0; ci->font_h[i] = 0; + } + ci->font_init++; + } + for (i = 0 ; i < 50 ; i++) { + if (!ci->s_refs[i] && ci->font_strings[i]) { + free (ci->font_strings[i]); + ci->font_strings[i] = NULL; + } + if (ci->font_strings[i] && !strcmp(str, ci->font_strings[i])) { /* if one matches */ + t = malloc(sizeof(TexNum)); + t->w = ci->font_w[i]; t->h = ci->font_h[i]; + t->num = i; + ci->s_refs[i]++; + return t; + } + } + + /* at this point we need to make the new texture */ + ximage = text_to_ximage (mi->xgwa.screen, + mi->xgwa.visual, + font, str, + fg, bg); + glGenTextures (1, &mintex); + for (i = mintex ; ci->font_strings[i] != NULL ; i++) { /* set i to the next unused value */ + if (i > 49) { + fprintf(stderr, "Texture cache full!\n"); + free(ximage->data); + ximage->data = 0; + XFree (ximage); + return NULL; + } + } + + glBindTexture(GL_TEXTURE_2D, i); + glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + + clear_gl_error(); +#if 0 + i = gluBuild2DMipmaps(GL_TEXTURE_2D, 4, + ximage->width, ximage->height, + GL_RGBA, GL_UNSIGNED_BYTE, ximage->data); + if (i) + { + const char *s = (char *) gluErrorString (i); + fprintf (stderr, "%s: error mipmapping %dx%d texture: %s\n", + progname, ximage->width, ximage->height, + (s ? s : "(unknown)")); + abort(); + } + check_gl_error("mipmapping"); +#else + glTexImage2D (GL_TEXTURE_2D, 0, GL_RGBA, ximage->width, ximage->height, 0, + GL_RGBA, GL_UNSIGNED_BYTE, ximage->data); + check_gl_error("texture"); +#endif + + t = malloc(sizeof(TexNum)); + t->w = ximage->width; + t->h = ximage->height; + ci->font_w[i] = t->w; ci->font_h[i] = t->h; + free(ximage->data); + ximage->data = 0; + XFree (ximage); + c = malloc(strlen(str)+1); + strncpy(c, str, strlen(str)+1); + ci->font_strings[i] = c; + ci->s_refs[i]++; + t->num = i; + return t; +} + +/* ensure transparent components are at the end */ +static void reorder(Component *c[]) +{ + int i, j, k; + Component *c1[MAX_COMPONENTS]; + Component *c2[MAX_COMPONENTS]; + + j = 0; + for (i = 0 ; i < maxparts ; i++) { /* clear old matrix */ + c1[i] = NULL; + c2[i] = NULL; + } + for (i = 0 ; i < maxparts ; i++) { + if (c[i] == NULL) continue; + if (c[i]->alpha) { /* transparent parts go to c1 */ + c1[j] = c[i]; + j++; + } else { /* opaque parts go to c2 */ + c2[i] = c[i]; + } + } + for (i = 0 ; i < maxparts ; i++) { /* clear old matrix */ + c[i] = NULL; + } + k = 0; + for (i = 0 ; i < maxparts ; i++) { /* insert opaque part */ + if (c2[i] != NULL) { + c[k] = c2[i]; + k++; + } + } + for (i = 0 ; i < j ; i++) { /* insert transparent parts */ + c[k] = c1[i]; + k++; + } +} + +ENTRYPOINT void reshape_circuit(ModeInfo *mi, int width, int height) +{ + Circuit *ci = &circuit[MI_SCREEN(mi)]; + GLfloat h = (GLfloat) height / (GLfloat) width; + glViewport(0,0,(GLint)width, (GLint) height); + glMatrixMode(GL_PROJECTION); + glLoadIdentity(); + glFrustum(-1.0,1.0,-h,h,1.5,35.0); + glMatrixMode(GL_MODELVIEW); + ci->win_h = height; + ci->win_w = width; + ci->YMAX = ci->XMAX * h; +} + + +ENTRYPOINT void init_circuit(ModeInfo *mi) +{ +int screen = MI_SCREEN(mi); +Circuit *ci; + + if (circuit == NULL) { + if ((circuit = (Circuit *) calloc(MI_NUM_SCREENS(mi), + sizeof(Circuit))) == NULL) + return; + } + ci = &circuit[screen]; + ci->window = MI_WINDOW(mi); + + ci->XMAX = ci->YMAX = 30; + ci->viewer[2] = 14; + ci->lightpos[0] = 7; + ci->lightpos[1] = 7; + ci->lightpos[2] = 15; + ci->lightpos[3] = 1; + + ci->grid_col[1] = 0.25; + ci->grid_col[2] = 0.05; + ci->grid_col2[1] = 0.125; + ci->grid_col2[2] = 0.05; + + if (maxparts >= MAX_COMPONENTS) + maxparts = MAX_COMPONENTS-1; + + if ((ci->glx_context = init_GL(mi)) != NULL) { + reshape_circuit(mi, MI_WIDTH(mi), MI_HEIGHT(mi)); + } else { + MI_CLEARWINDOW(mi); + } + if (uselight == 0) + ci->light = 1; + glShadeModel(GL_SMOOTH); + glPolygonMode(GL_FRONT_AND_BACK,GL_FILL); + glEnable(GL_DEPTH_TEST); + glEnable(GL_LIGHTING); + glEnable(GL_LIGHT0); + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + make_tables(ci); + makebandlist(ci); + +} + +ENTRYPOINT void draw_circuit(ModeInfo *mi) +{ + Circuit *ci = &circuit[MI_SCREEN(mi)]; + Window w = MI_WINDOW(mi); + Display *disp = MI_DISPLAY(mi); + + if (!ci->glx_context) + return; + + glXMakeCurrent(disp, w, *(ci->glx_context)); + + display(mi); + + if(mi->fps_p) do_fps(mi); + glFinish(); + glXSwapBuffers(disp, w); +} + +ENTRYPOINT void release_circuit(ModeInfo *mi) +{ + if (circuit != NULL) { + (void) free((void *) circuit); + circuit = NULL; + } + FreeAllGL(mi); +} + +XSCREENSAVER_MODULE ("Circuit", circuit) + +#endif diff --git a/hacks/glx/circuit.man b/hacks/glx/circuit.man new file mode 100644 index 00000000..794f97bc --- /dev/null +++ b/hacks/glx/circuit.man @@ -0,0 +1,72 @@ +.TH XScreenSaver 1 "5-May-2004" "X Version 11" +.SH NAME +circuit - animates a number of 3D electronic components. +.SH SYNOPSIS +.B circuit +[\-display \fIhost:display.screen\fP] +[\-visual \fIvisual\fP] +[\-window] +[\-root] +[\-delay \fInumber\fP] +[\-parts \fInumber\fP] +[\-no-spin] +[\-rotate] +[\-speed \fInumber\fP] +[\-no-light] +[\-fps] +.SH DESCRIPTION +Animates a number of 3D electronic components. +.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: 20000 (0.02 seconds.). +.TP 8 +.B \-parts \fInumber\fP +Number of parts. Default: 10. +.TP 8 +.B \-spin | \-no-spin +Whether the objects should spin. +.TP 8 +.B \-rotate | \-no-rotate +Whether the scene should spin. +.TP 8 +.B \-speed \fInumber\fP +Rotation speed, 0 - 100. Default: 1. +.TP 8 +.B \-light | \-no-light +Whether to us lighting, or flat coloring. +.TP 8 +.B \-fps +Display the current frame rate, CPU load, and polygon count. +.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 2002 by Ben Buxton. 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 +Ben Buxton. diff --git a/hacks/glx/companion.c b/hacks/glx/companion.c new file mode 100644 index 00000000..d0c84ed0 --- /dev/null +++ b/hacks/glx/companion.c @@ -0,0 +1,614 @@ +/* companioncube, Copyright (c) 2011 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. + */ + +/* The symptoms most commonly produced by Enrichment Center testing are + superstition, perceiving inanimate objects as alive, and hallucinations. + The Enrichment Center reminds you that the weighted companion cube will + never threaten to stab you and, in fact, cannot speak. In the event that + the Weighted Companion Cube does speak, the Enrichment Center urges you to + disregard its advice. + */ + + +#define DEFAULTS "*delay: 30000 \n" \ + "*count: 1 \n" \ + "*showFPS: False \n" \ + "*count: 3 \n" \ + "*wireframe: False \n" \ + +/* #define DEBUG */ + + +# define refresh_cube 0 +# define release_cube 0 +#define DEF_SPEED "1.0" +#define DEF_SPIN "False" +#define DEF_WANDER "False" + +#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) + +#include "xlockmore.h" +#include "rotator.h" +#include "gltrackball.h" +#include "xpm-ximage.h" +#include + +#ifdef USE_GL /* whole file */ + +#include "gllist.h" + +extern const struct gllist *companion_quad, *companion_disc, *companion_heart; +static const struct gllist * const *all_objs[] = { + &companion_quad, &companion_disc, &companion_heart +}; +#define BASE_QUAD 0 +#define BASE_DISC 1 +#define BASE_HEART 2 +#define FULL_CUBE 3 + +#define SPEED_SCALE 0.2 + +typedef struct { + GLfloat x, y, z; + GLfloat ix, iy, iz; + GLfloat dx, dy, dz; + GLfloat ddx, ddy, ddz; + GLfloat zr; + rotator *rot; + Bool spinner_p; +} floater; + +typedef struct { + GLXContext *glx_context; + trackball_state *trackball; + Bool button_down_p; + + GLuint *dlists; + int cube_polys; + + int nfloaters; + floater *floaters; + +} cube_configuration; + +static cube_configuration *bps = NULL; + +static GLfloat speed; +static Bool do_spin; +static Bool do_wander; + +static XrmOptionDescRec opts[] = { + { "-speed", ".speed", XrmoptionSepArg, 0 }, + { "-spin", ".spin", XrmoptionNoArg, "True" }, + { "+spin", ".spin", XrmoptionNoArg, "False" }, + { "-wander", ".wander", XrmoptionNoArg, "True" }, + { "+wander", ".wander", XrmoptionNoArg, "False" }, +}; + +static argtype vars[] = { + {&speed, "speed", "Speed", DEF_SPEED, t_Float}, + {&do_spin, "spin", "Spin", DEF_SPIN, t_Bool}, + {&do_wander, "wander", "Wander", DEF_WANDER, t_Bool}, +}; + +ENTRYPOINT ModeSpecOpt cube_opts = {countof(opts), opts, countof(vars), vars, NULL}; + + +#define BOTTOM 28.0 + +static void +reset_floater (ModeInfo *mi, floater *f) +{ + cube_configuration *bp = &bps[MI_SCREEN(mi)]; + + f->y = -BOTTOM; + f->x = f->ix; + f->z = f->iz; + + /* Yes, I know I'm varying the force of gravity instead of varying the + launch velocity. That's intentional: empirical studies indicate + that it's way, way funnier that way. */ + + f->dy = 5.0; + f->dx = 0; + f->dz = 0; + + /* -0.18 max -0.3 top -0.4 middle -0.6 bottom */ + f->ddy = speed * SPEED_SCALE * (-0.6 + BELLRAND(0.45)); + f->ddx = 0; + f->ddz = 0; + + if (do_spin || do_wander) + f->spinner_p = 0; + else + f->spinner_p = !(random() % (3 * bp->nfloaters)); + + if (! (random() % (30 * bp->nfloaters))) + { + f->dx = BELLRAND(1.8) * RANDSIGN(); + f->dz = BELLRAND(1.8) * RANDSIGN(); + } + + f->zr = frand(180); + if (do_spin || do_wander) + { + f->y = 0; + if (bp->nfloaters > 2) + f->y += frand(3.0) * RANDSIGN(); + } +} + + +static void +tick_floater (ModeInfo *mi, floater *f) +{ + cube_configuration *bp = &bps[MI_SCREEN(mi)]; + + if (bp->button_down_p) return; + + if (do_spin || do_wander) return; + + f->dx += f->ddx; + f->dy += f->ddy; + f->dz += f->ddz; + + f->x += f->dx * speed * SPEED_SCALE; + f->y += f->dy * speed * SPEED_SCALE; + f->z += f->dz * speed * SPEED_SCALE; + + if (f->y < -BOTTOM || + f->x < -BOTTOM*8 || f->x > BOTTOM*8 || + f->z < -BOTTOM*8 || f->z > BOTTOM*8) + reset_floater (mi, f); +} + + + + + +static int +build_corner (ModeInfo *mi) +{ + cube_configuration *bp = &bps[MI_SCREEN(mi)]; + GLfloat s; + const struct gllist *gll = *all_objs[BASE_QUAD]; + + glPushMatrix(); + glTranslatef (-0.5, -0.5, -0.5); + s = 0.659; + glScalef (s, s, s); + + glRotatef (180, 0, 1, 0); + glRotatef (180, 0, 0, 1); + glTranslatef (-0.12, -1.64, 0.12); + glCallList (bp->dlists[BASE_QUAD]); + glPopMatrix(); + + return gll->points / 3; +} + + +static int +build_face (ModeInfo *mi) +{ + int polys = 0; + cube_configuration *bp = &bps[MI_SCREEN(mi)]; + int wire = MI_IS_WIREFRAME(mi); + GLfloat s; + const struct gllist *gll; + + GLfloat base_color[4] = {0.53, 0.60, 0.66, 1.00}; + GLfloat heart_color[4] = {0.92, 0.67, 1.00, 1.00}; + GLfloat disc_color[4] = {0.75, 0.92, 1.00, 1.00}; + GLfloat corner_color[4] = {0.75, 0.92, 1.00, 1.00}; + + if (!wire) + { + GLfloat w = 0.010; + glMaterialfv (GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, base_color); + glPushMatrix(); + glNormal3f (0, 0, -1); + glTranslatef (-0.5, -0.5, -0.5); + + glBegin(GL_QUADS); + glVertex3f (0, 0, 0); + glVertex3f (0, 0.5-w, 0); + glVertex3f (0.5-w, 0.5-w, 0); + glVertex3f (0.5-w, 0, 0); + + glVertex3f (0.5+w, 0, 0); + glVertex3f (0.5+w, 0.5-w, 0); + glVertex3f (1, 0.5-w, 0); + glVertex3f (1, 0, 0); + + glVertex3f (0, 0.5+w, 0); + glVertex3f (0, 1, 0); + glVertex3f (0.5-w, 1, 0); + glVertex3f (0.5-w, 0.5+w, 0); + + glVertex3f (0.5+w, 0.5+w, 0); + glVertex3f (0.5+w, 1, 0); + glVertex3f (1, 1, 0); + glVertex3f (1, 0.5+w, 0); + glEnd(); + + glMaterialfv (GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, heart_color); + + glNormal3f (0, -1, 0); + glBegin(GL_QUADS); + glVertex3f (0, 0.5+w, 0); + glVertex3f (1, 0.5+w, 0); + glVertex3f (1, 0.5+w, w); + glVertex3f (0, 0.5+w, w); + glEnd(); + + glNormal3f (0, 1, 0); + glBegin(GL_QUADS); + glVertex3f (0, 0.5-w, w); + glVertex3f (1, 0.5-w, w); + glVertex3f (1, 0.5-w, 0); + glVertex3f (0, 0.5-w, 0); + glEnd(); + + glNormal3f (-1, 0, 0); + glBegin(GL_QUADS); + glVertex3f (0.5+w, 0, w); + glVertex3f (0.5+w, 1, w); + glVertex3f (0.5+w, 1, 0); + glVertex3f (0.5+w, 0, 0); + glEnd(); + + glNormal3f (1, 0, 0); + glBegin(GL_QUADS); + glVertex3f (0.5-w, 0, 0); + glVertex3f (0.5-w, 1, 0); + glVertex3f (0.5-w, 1, w); + glVertex3f (0.5-w, 0, w); + glEnd(); + + glMaterialfv (GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, heart_color); + + glNormal3f (0, 0, -1); + glTranslatef (0, 0, w); + glBegin(GL_QUADS); + glVertex3f (0, 0, 0); + glVertex3f (0, 1, 0); + glVertex3f (1, 1, 0); + glVertex3f (1, 0, 0); + glEnd(); + + glPopMatrix(); + } + + glMaterialfv (GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, corner_color); + + glPushMatrix(); + polys += build_corner (mi); glRotatef (90, 0, 0, 1); + polys += build_corner (mi); glRotatef (90, 0, 0, 1); + polys += build_corner (mi); glRotatef (90, 0, 0, 1); + polys += build_corner (mi); + + glRotatef (90, 0, 0, 1); + glTranslatef (0.585, -0.585, -0.5655); + + s = 10.5; + glScalef (s, s, s); + glRotatef (180, 0, 1, 0); + + if (! wire) + { + gll = *all_objs[BASE_HEART]; + glMaterialfv (GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, heart_color); + glCallList (bp->dlists[BASE_HEART]); + polys += gll->points / 3; + } + + gll = *all_objs[BASE_DISC]; + glMaterialfv (GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, disc_color); + glCallList (bp->dlists[BASE_DISC]); + polys += gll->points / 3; + + glPopMatrix(); + return polys; +} + + +static int +build_cube (ModeInfo *mi) +{ + int polys = 0; + glPushMatrix(); + polys += build_face (mi); glRotatef (90, 0, 1, 0); + polys += build_face (mi); glRotatef (90, 0, 1, 0); + polys += build_face (mi); glRotatef (90, 0, 1, 0); + polys += build_face (mi); glRotatef (90, 1, 0, 0); + polys += build_face (mi); glRotatef (180,1, 0, 0); + polys += build_face (mi); + glPopMatrix(); + return polys; +} + + +/* Window management, etc + */ +ENTRYPOINT void +reshape_cube (ModeInfo *mi, int width, int height) +{ + GLfloat h = (GLfloat) height / (GLfloat) width; + + glViewport (0, 0, (GLint) width, (GLint) height); + + glMatrixMode(GL_PROJECTION); + glLoadIdentity(); + gluPerspective (30.0, 1/h, 1.0, 100); + + glMatrixMode(GL_MODELVIEW); + glLoadIdentity(); + gluLookAt( 0.0, 0.0, 30.0, + 0.0, 0.0, 0.0, + 0.0, 1.0, 0.0); + + glClear(GL_COLOR_BUFFER_BIT); +} + + +ENTRYPOINT Bool +cube_handle_event (ModeInfo *mi, XEvent *event) +{ + cube_configuration *bp = &bps[MI_SCREEN(mi)]; + + if (event->xany.type == ButtonPress && + event->xbutton.button == Button1) + { + bp->button_down_p = True; + gltrackball_start (bp->trackball, + event->xbutton.x, event->xbutton.y, + MI_WIDTH (mi), MI_HEIGHT (mi)); + return True; + } + else if (event->xany.type == ButtonRelease && + event->xbutton.button == Button1) + { + bp->button_down_p = False; + return True; + } + else if (event->xany.type == ButtonPress && + (event->xbutton.button == Button4 || + event->xbutton.button == Button5 || + event->xbutton.button == Button6 || + event->xbutton.button == Button7)) + { + gltrackball_mousewheel (bp->trackball, event->xbutton.button, 3, + !event->xbutton.state); + return True; + } + else if (event->xany.type == MotionNotify && + bp->button_down_p) + { + gltrackball_track (bp->trackball, + event->xmotion.x, event->xmotion.y, + MI_WIDTH (mi), MI_HEIGHT (mi)); + return True; + } + + return False; +} + + +ENTRYPOINT void +init_cube (ModeInfo *mi) +{ + cube_configuration *bp; + int wire = MI_IS_WIREFRAME(mi); + int i; + + if (!bps) { + bps = (cube_configuration *) + calloc (MI_NUM_SCREENS(mi), sizeof (cube_configuration)); + if (!bps) { + fprintf(stderr, "%s: out of memory\n", progname); + exit(1); + } + } + + bp = &bps[MI_SCREEN(mi)]; + + bp->glx_context = init_GL(mi); + + reshape_cube (mi, MI_WIDTH(mi), MI_HEIGHT(mi)); + + glShadeModel(GL_SMOOTH); + + glEnable(GL_DEPTH_TEST); + glEnable(GL_NORMALIZE); + glEnable(GL_CULL_FACE); + + if (!wire) + { + GLfloat pos[4] = {0.7, 0.2, 0.4, 0.0}; +/* GLfloat amb[4] = {0.0, 0.0, 0.0, 1.0};*/ + GLfloat amb[4] = {0.2, 0.2, 0.2, 1.0}; + GLfloat dif[4] = {1.0, 1.0, 1.0, 1.0}; + GLfloat spc[4] = {1.0, 1.0, 1.0, 1.0}; + + glEnable(GL_LIGHTING); + glEnable(GL_LIGHT0); + glEnable(GL_DEPTH_TEST); + glEnable(GL_CULL_FACE); + + glLightfv(GL_LIGHT0, GL_POSITION, pos); + glLightfv(GL_LIGHT0, GL_AMBIENT, amb); + glLightfv(GL_LIGHT0, GL_DIFFUSE, dif); + glLightfv(GL_LIGHT0, GL_SPECULAR, spc); + } + + bp->trackball = gltrackball_init (); + + bp->dlists = (GLuint *) calloc (countof(all_objs)+2, sizeof(GLuint)); + for (i = 0; i < countof(all_objs)+1; i++) + bp->dlists[i] = glGenLists (1); + + for (i = 0; i < countof(all_objs); i++) + { + const struct gllist *gll = *all_objs[i]; + glNewList (bp->dlists[i], GL_COMPILE); + renderList (gll, wire); + glEndList (); + } + + glNewList (bp->dlists[i], GL_COMPILE); + bp->cube_polys = build_cube (mi); + glEndList (); + + + bp->nfloaters = MI_COUNT (mi); + bp->floaters = (floater *) calloc (bp->nfloaters, sizeof (floater)); + + for (i = 0; i < bp->nfloaters; i++) + { + floater *f = &bp->floaters[i]; + double spin_speed = do_spin ? 0.7 : 10; + double wander_speed = do_wander ? 0.02 : 0.05 * speed * SPEED_SCALE; + double spin_accel = 0.5; + f->rot = make_rotator (spin_speed, spin_speed, spin_speed, + spin_accel, + wander_speed, + True); + if (bp->nfloaters == 2) + { + f->x = (i ? 2 : -2); + } + else if (i != 0) + { + double th = (i - 1) * M_PI*2 / (bp->nfloaters-1); + double r = 3; + f->x = r * cos(th); + f->z = r * sin(th); + } + + f->ix = f->x; + f->iy = f->y; + f->iz = f->z; + reset_floater (mi, f); + } +} + + +static void +draw_floater (ModeInfo *mi, floater *f) +{ + cube_configuration *bp = &bps[MI_SCREEN(mi)]; + GLfloat n; + double x, y, z; + + get_position (f->rot, &x, &y, &z, !bp->button_down_p); + + glPushMatrix(); + glTranslatef (f->x, f->y, f->z); + + if (do_wander) + glTranslatef (x, y, z); + + if (do_spin) + get_rotation (f->rot, &x, &y, &z, !bp->button_down_p); + + if (do_spin || f->spinner_p) + { + glRotatef (x * 360, 1, 0, 0); + glRotatef (y * 360, 0, 1, 0); + glRotatef (z * 360, 0, 0, 1); + } + else + { + glRotatef (f->zr * 360, 0, 1, 0); + } + + n = 1.5; + if (bp->nfloaters > 99) n *= 0.05; + else if (bp->nfloaters > 25) n *= 0.18; + else if (bp->nfloaters > 9) n *= 0.3; + else if (bp->nfloaters > 1) n *= 0.7; + + n *= 2; + + if ((do_spin || do_wander) && bp->nfloaters > 1) + n *= 0.7; + + glScalef(n, n, n); + + glCallList (bp->dlists[FULL_CUBE]); + mi->polygon_count += bp->cube_polys; +/* build_cube (mi);*/ + + glPopMatrix(); +} + + + +ENTRYPOINT void +draw_cube (ModeInfo *mi) +{ + cube_configuration *bp = &bps[MI_SCREEN(mi)]; + Display *dpy = MI_DISPLAY(mi); + Window window = MI_WINDOW(mi); + int i; + + if (!bp->glx_context) + return; + + glXMakeCurrent(MI_DISPLAY(mi), MI_WINDOW(mi), *(bp->glx_context)); + + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + + glPushMatrix (); + glRotatef(current_device_rotation(), 0, 0, 1); + gltrackball_rotate (bp->trackball); + + glScalef (2, 2, 2); + + mi->polygon_count = 0; + +# if 0 + { + floater F; + F.x = F.y = F.z = 0; + F.dx = F.dy = F.dz = 0; + F.ddx = F.ddy = F.ddz = 0; + F.rot = make_rotator (0, 0, 0, 1, 0, False); + glRotatef (45, 0, 1, 0); + draw_floater (mi, &F); + } +# else + for (i = 0; i < bp->nfloaters; i++) + { + floater *f = &bp->floaters[i]; + draw_floater (mi, f); + tick_floater (mi, f); + } +# endif + + glPopMatrix (); + + if (mi->fps_p) do_fps (mi); + glFinish(); + + glXSwapBuffers(dpy, window); +} + +XSCREENSAVER_MODULE_2 ("CompanionCube", companioncube, cube) + +#endif /* USE_GL */ diff --git a/hacks/glx/companion_disc.c b/hacks/glx/companion_disc.c new file mode 100644 index 00000000..b2f18303 --- /dev/null +++ b/hacks/glx/companion_disc.c @@ -0,0 +1,9593 @@ +#include "gllist.h" +static const float data[]={ + -0.904813,-0.425773,0.005552,0.040192,0.048501,-0.006167, + -0.902569,-0.424717,0.070606,0.040194,0.048502,-0.006013, + -0.927456,-0.367206,0.070606,0.039761,0.049501,-0.006013, + -0.904813,-0.425773,0.005552,0.040192,0.048501,-0.006167, + -0.927456,-0.367206,0.070606,0.039761,0.049501,-0.006013, + -0.929762,-0.368119,0.005552,0.03976,0.049501,-0.006167, + -0.876293,-0.481746,0.005552,0.040687,0.04753,-0.006167, + -0.87412,-0.480551,0.070606,0.040688,0.047531,-0.006013, + -0.902569,-0.424717,0.070606,0.040194,0.048502,-0.006013, + -0.876293,-0.481746,0.005552,0.040687,0.04753,-0.006167, + -0.902569,-0.424717,0.070606,0.040194,0.048502,-0.006013, + -0.904813,-0.425773,0.005552,0.040192,0.048501,-0.006167, + -0.844315,-0.535819,0.005552,0.041241,0.046592,-0.006167, + -0.842221,-0.53449,0.070606,0.041243,0.046593,-0.006013, + -0.87412,-0.480551,0.070606,0.040688,0.047531,-0.006013, + -0.844315,-0.535819,0.005552,0.041241,0.046592,-0.006167, + -0.87412,-0.480551,0.070606,0.040688,0.047531,-0.006013, + -0.876293,-0.481746,0.005552,0.040687,0.04753,-0.006167, + -0.809005,-0.587776,0.005552,0.041854,0.045691,-0.006167, + -0.806998,-0.586318,0.070606,0.041855,0.045692,-0.006013, + -0.842221,-0.53449,0.070606,0.041243,0.046593,-0.006013, + -0.809005,-0.587776,0.005552,0.041854,0.045691,-0.006167, + -0.842221,-0.53449,0.070606,0.041243,0.046593,-0.006013, + -0.844315,-0.535819,0.005552,0.041241,0.046592,-0.006167, + -0.770501,-0.637414,0.005552,0.042522,0.04483,-0.006167, + -0.76859,-0.635833,0.070606,0.042523,0.044831,-0.006013, + -0.806998,-0.586318,0.070606,0.041855,0.045692,-0.006013, + -0.770501,-0.637414,0.005552,0.042522,0.04483,-0.006167, + -0.806998,-0.586318,0.070606,0.041855,0.045692,-0.006013, + -0.809005,-0.587776,0.005552,0.041854,0.045691,-0.006167, + -0.728957,-0.684537,0.005552,0.043242,0.044013,-0.006167, + -0.727149,-0.682839,0.070606,0.043243,0.044014,-0.006013, + -0.76859,-0.635833,0.070606,0.042523,0.044831,-0.006013, + -0.728957,-0.684537,0.005552,0.043242,0.044013,-0.006167, + -0.76859,-0.635833,0.070606,0.042523,0.044831,-0.006013, + -0.770501,-0.637414,0.005552,0.042522,0.04483,-0.006167, + -0.684537,-0.728957,0.005552,0.044013,0.043242,-0.006167, + -0.682839,-0.727149,0.070606,0.044014,0.043243,-0.006013, + -0.727149,-0.682839,0.070606,0.043243,0.044014,-0.006013, + -0.684537,-0.728957,0.005552,0.044013,0.043242,-0.006167, + -0.727149,-0.682839,0.070606,0.043243,0.044014,-0.006013, + -0.728957,-0.684537,0.005552,0.043242,0.044013,-0.006167, + -0.637414,-0.770501,0.005552,0.04483,0.042522,-0.006167, + -0.635833,-0.76859,0.070606,0.044831,0.042523,-0.006013, + -0.682839,-0.727149,0.070606,0.044014,0.043243,-0.006013, + -0.637414,-0.770501,0.005552,0.04483,0.042522,-0.006167, + -0.682839,-0.727149,0.070606,0.044014,0.043243,-0.006013, + -0.684537,-0.728957,0.005552,0.044013,0.043242,-0.006167, + -0.587776,-0.809005,0.005552,0.045691,0.041854,-0.006167, + -0.586318,-0.806998,0.070606,0.045692,0.041855,-0.006013, + -0.635833,-0.76859,0.070606,0.044831,0.042523,-0.006013, + -0.587776,-0.809005,0.005552,0.045691,0.041854,-0.006167, + -0.635833,-0.76859,0.070606,0.044831,0.042523,-0.006013, + -0.637414,-0.770501,0.005552,0.04483,0.042522,-0.006167, + -0.535819,-0.844315,0.005552,0.046592,0.041241,-0.006167, + -0.53449,-0.842221,0.070606,0.046593,0.041243,-0.006013, + -0.586318,-0.806998,0.070606,0.045692,0.041855,-0.006013, + -0.535819,-0.844315,0.005552,0.046592,0.041241,-0.006167, + -0.586318,-0.806998,0.070606,0.045692,0.041855,-0.006013, + -0.587776,-0.809005,0.005552,0.045691,0.041854,-0.006167, + -0.481746,-0.876293,0.005552,0.04753,0.040687,-0.006167, + -0.480551,-0.87412,0.070606,0.047531,0.040688,-0.006013, + -0.53449,-0.842221,0.070606,0.046593,0.041243,-0.006013, + -0.481746,-0.876293,0.005552,0.04753,0.040687,-0.006167, + -0.53449,-0.842221,0.070606,0.046593,0.041243,-0.006013, + -0.535819,-0.844315,0.005552,0.046592,0.041241,-0.006167, + -0.425773,-0.904813,0.005552,0.048501,0.040192,-0.006167, + -0.424717,-0.902569,0.070606,0.048502,0.040194,-0.006013, + -0.480551,-0.87412,0.070606,0.047531,0.040688,-0.006013, + -0.425773,-0.904813,0.005552,0.048501,0.040192,-0.006167, + -0.480551,-0.87412,0.070606,0.047531,0.040688,-0.006013, + -0.481746,-0.876293,0.005552,0.04753,0.040687,-0.006167, + -0.368119,-0.929762,0.005552,0.049501,0.03976,-0.006167, + -0.367206,-0.927456,0.070606,0.049501,0.039761,-0.006013, + -0.424717,-0.902569,0.070606,0.048502,0.040194,-0.006013, + -0.368119,-0.929762,0.005552,0.049501,0.03976,-0.006167, + -0.424717,-0.902569,0.070606,0.048502,0.040194,-0.006013, + -0.425773,-0.904813,0.005552,0.048501,0.040192,-0.006167, + -0.309012,-0.951042,0.005552,0.050526,0.03939,-0.006167, + -0.308246,-0.948683,0.070606,0.050526,0.039392,-0.006013, + -0.367206,-0.927456,0.070606,0.049501,0.039761,-0.006013, + -0.309012,-0.951042,0.005552,0.050526,0.03939,-0.006167, + -0.367206,-0.927456,0.070606,0.049501,0.039761,-0.006013, + -0.368119,-0.929762,0.005552,0.049501,0.03976,-0.006167, + -0.248686,-0.968568,0.005552,0.051572,0.039087,-0.006167, + -0.248069,-0.966166,0.070606,0.051572,0.039088,-0.006013, + -0.308246,-0.948683,0.070606,0.050526,0.039392,-0.006013, + -0.248686,-0.968568,0.005552,0.051572,0.039087,-0.006167, + -0.308246,-0.948683,0.070606,0.050526,0.039392,-0.006013, + -0.309012,-0.951042,0.005552,0.050526,0.03939,-0.006167, + -0.187378,-0.982272,0.005552,0.052635,0.038849,-0.006167, + -0.186914,-0.979836,0.070606,0.052636,0.03885,-0.006013, + -0.248069,-0.966166,0.070606,0.051572,0.039088,-0.006013, + -0.187378,-0.982272,0.005552,0.052635,0.038849,-0.006167, + -0.248069,-0.966166,0.070606,0.051572,0.039088,-0.006013, + -0.248686,-0.968568,0.005552,0.051572,0.039087,-0.006167, + -0.125331,-0.992099,0.005552,0.053712,0.038678,-0.006167, + -0.12502,-0.989639,0.070606,0.053712,0.03868,-0.006013, + -0.186914,-0.979836,0.070606,0.052636,0.03885,-0.006013, + -0.125331,-0.992099,0.005552,0.053712,0.038678,-0.006167, + -0.186914,-0.979836,0.070606,0.052636,0.03885,-0.006013, + -0.187378,-0.982272,0.005552,0.052635,0.038849,-0.006167, + -0.07324,-0.997287,0.007402,0.054796,0.038576,-0.006167, + -0.062634,-0.995536,0.070606,0.054796,0.038577,-0.006013, + -0.12502,-0.989639,0.070606,0.053712,0.03868,-0.006013, + -0.07324,-0.997287,0.007402,0.054796,0.038576,-0.006167, + -0.12502,-0.989639,0.070606,0.053712,0.03868,-0.006013, + -0.125331,-0.992099,0.005552,0.053712,0.038678,-0.006167, + 0,-0.999938,0.011104,0.055885,0.038542,-0.006167, + 0,-0.997504,0.070606,0.055885,0.038543,-0.006013, + -0.062634,-0.995536,0.070606,0.054796,0.038577,-0.006013, + 0,-0.999938,0.011104,0.055885,0.038542,-0.006167, + -0.062634,-0.995536,0.070606,0.054796,0.038577,-0.006013, + -0.07324,-0.997287,0.007402,0.054796,0.038576,-0.006167, + 0.07324,-0.997287,0.007402,0.056974,0.038576,-0.006167, + 0.062634,-0.995536,0.070606,0.056974,0.038577,-0.006013, + 0,-0.997504,0.070606,0.055885,0.038543,-0.006013, + 0.07324,-0.997287,0.007402,0.056974,0.038576,-0.006167, + 0,-0.997504,0.070606,0.055885,0.038543,-0.006013, + 0,-0.999938,0.011104,0.055885,0.038542,-0.006167, + 0.125331,-0.992099,0.005552,0.058059,0.038678,-0.006167, + 0.12502,-0.989639,0.070606,0.058059,0.03868,-0.006013, + 0.062634,-0.995536,0.070606,0.056974,0.038577,-0.006013, + 0.125331,-0.992099,0.005552,0.058059,0.038678,-0.006167, + 0.062634,-0.995536,0.070606,0.056974,0.038577,-0.006013, + 0.07324,-0.997287,0.007402,0.056974,0.038576,-0.006167, + 0.187378,-0.982272,0.005552,0.059135,0.038849,-0.006167, + 0.186914,-0.979836,0.070606,0.059135,0.03885,-0.006013, + 0.12502,-0.989639,0.070606,0.058059,0.03868,-0.006013, + 0.187378,-0.982272,0.005552,0.059135,0.038849,-0.006167, + 0.12502,-0.989639,0.070606,0.058059,0.03868,-0.006013, + 0.125331,-0.992099,0.005552,0.058059,0.038678,-0.006167, + 0.248686,-0.968568,0.005552,0.060198,0.039087,-0.006167, + 0.248069,-0.966166,0.070606,0.060198,0.039088,-0.006013, + 0.186914,-0.979836,0.070606,0.059135,0.03885,-0.006013, + 0.248686,-0.968568,0.005552,0.060198,0.039087,-0.006167, + 0.186914,-0.979836,0.070606,0.059135,0.03885,-0.006013, + 0.187378,-0.982272,0.005552,0.059135,0.038849,-0.006167, + 0.309012,-0.951042,0.005552,0.061245,0.03939,-0.006167, + 0.308246,-0.948683,0.070606,0.061244,0.039392,-0.006013, + 0.248069,-0.966166,0.070606,0.060198,0.039088,-0.006013, + 0.309012,-0.951042,0.005552,0.061245,0.03939,-0.006167, + 0.248069,-0.966166,0.070606,0.060198,0.039088,-0.006013, + 0.248686,-0.968568,0.005552,0.060198,0.039087,-0.006167, + 0.368119,-0.929762,0.005552,0.06227,0.03976,-0.006167, + 0.367206,-0.927456,0.070606,0.062269,0.039761,-0.006013, + 0.308246,-0.948683,0.070606,0.061244,0.039392,-0.006013, + 0.368119,-0.929762,0.005552,0.06227,0.03976,-0.006167, + 0.308246,-0.948683,0.070606,0.061244,0.039392,-0.006013, + 0.309012,-0.951042,0.005552,0.061245,0.03939,-0.006167, + 0.425773,-0.904813,0.005552,0.06327,0.040192,-0.006167, + 0.424717,-0.902569,0.070606,0.063269,0.040194,-0.006013, + 0.367206,-0.927456,0.070606,0.062269,0.039761,-0.006013, + 0.425773,-0.904813,0.005552,0.06327,0.040192,-0.006167, + 0.367206,-0.927456,0.070606,0.062269,0.039761,-0.006013, + 0.368119,-0.929762,0.005552,0.06227,0.03976,-0.006167, + 0.481746,-0.876293,0.005552,0.064241,0.040687,-0.006167, + 0.480551,-0.87412,0.070606,0.06424,0.040688,-0.006013, + 0.424717,-0.902569,0.070606,0.063269,0.040194,-0.006013, + 0.481746,-0.876293,0.005552,0.064241,0.040687,-0.006167, + 0.424717,-0.902569,0.070606,0.063269,0.040194,-0.006013, + 0.425773,-0.904813,0.005552,0.06327,0.040192,-0.006167, + 0.535819,-0.844315,0.005552,0.065178,0.041241,-0.006167, + 0.53449,-0.842221,0.070606,0.065178,0.041243,-0.006013, + 0.480551,-0.87412,0.070606,0.06424,0.040688,-0.006013, + 0.535819,-0.844315,0.005552,0.065178,0.041241,-0.006167, + 0.480551,-0.87412,0.070606,0.06424,0.040688,-0.006013, + 0.481746,-0.876293,0.005552,0.064241,0.040687,-0.006167, + 0.587776,-0.809005,0.005552,0.06608,0.041854,-0.006167, + 0.586318,-0.806998,0.070606,0.066079,0.041855,-0.006013, + 0.53449,-0.842221,0.070606,0.065178,0.041243,-0.006013, + 0.587776,-0.809005,0.005552,0.06608,0.041854,-0.006167, + 0.53449,-0.842221,0.070606,0.065178,0.041243,-0.006013, + 0.535819,-0.844315,0.005552,0.065178,0.041241,-0.006167, + 0.637414,-0.770501,0.005552,0.066941,0.042522,-0.006167, + 0.635833,-0.76859,0.070606,0.06694,0.042523,-0.006013, + 0.586318,-0.806998,0.070606,0.066079,0.041855,-0.006013, + 0.637414,-0.770501,0.005552,0.066941,0.042522,-0.006167, + 0.586318,-0.806998,0.070606,0.066079,0.041855,-0.006013, + 0.587776,-0.809005,0.005552,0.06608,0.041854,-0.006167, + 0.684537,-0.728957,0.005552,0.067758,0.043242,-0.006167, + 0.682839,-0.727149,0.070606,0.067757,0.043243,-0.006013, + 0.635833,-0.76859,0.070606,0.06694,0.042523,-0.006013, + 0.684537,-0.728957,0.005552,0.067758,0.043242,-0.006167, + 0.635833,-0.76859,0.070606,0.06694,0.042523,-0.006013, + 0.637414,-0.770501,0.005552,0.066941,0.042522,-0.006167, + 0.728957,-0.684537,0.005552,0.068528,0.044013,-0.006167, + 0.727149,-0.682839,0.070606,0.068527,0.044014,-0.006013, + 0.682839,-0.727149,0.070606,0.067757,0.043243,-0.006013, + 0.728957,-0.684537,0.005552,0.068528,0.044013,-0.006167, + 0.682839,-0.727149,0.070606,0.067757,0.043243,-0.006013, + 0.684537,-0.728957,0.005552,0.067758,0.043242,-0.006167, + 0.770501,-0.637414,0.005552,0.069249,0.04483,-0.006167, + 0.76859,-0.635833,0.070606,0.069247,0.044831,-0.006013, + 0.727149,-0.682839,0.070606,0.068527,0.044014,-0.006013, + 0.770501,-0.637414,0.005552,0.069249,0.04483,-0.006167, + 0.727149,-0.682839,0.070606,0.068527,0.044014,-0.006013, + 0.728957,-0.684537,0.005552,0.068528,0.044013,-0.006167, + 0.809005,-0.587776,0.005552,0.069917,0.045691,-0.006167, + 0.806998,-0.586318,0.070606,0.069915,0.045692,-0.006013, + 0.76859,-0.635833,0.070606,0.069247,0.044831,-0.006013, + 0.809005,-0.587776,0.005552,0.069917,0.045691,-0.006167, + 0.76859,-0.635833,0.070606,0.069247,0.044831,-0.006013, + 0.770501,-0.637414,0.005552,0.069249,0.04483,-0.006167, + 0.844315,-0.535819,0.005552,0.070529,0.046592,-0.006167, + 0.842221,-0.53449,0.070606,0.070528,0.046593,-0.006013, + 0.806998,-0.586318,0.070606,0.069915,0.045692,-0.006013, + 0.844315,-0.535819,0.005552,0.070529,0.046592,-0.006167, + 0.806998,-0.586318,0.070606,0.069915,0.045692,-0.006013, + 0.809005,-0.587776,0.005552,0.069917,0.045691,-0.006167, + 0.876293,-0.481746,0.005552,0.071084,0.04753,-0.006167, + 0.87412,-0.480551,0.070606,0.071082,0.047531,-0.006013, + 0.842221,-0.53449,0.070606,0.070528,0.046593,-0.006013, + 0.876293,-0.481746,0.005552,0.071084,0.04753,-0.006167, + 0.842221,-0.53449,0.070606,0.070528,0.046593,-0.006013, + 0.844315,-0.535819,0.005552,0.070529,0.046592,-0.006167, + 0.904813,-0.425773,0.005552,0.071578,0.048501,-0.006167, + 0.902569,-0.424717,0.070606,0.071577,0.048502,-0.006013, + 0.87412,-0.480551,0.070606,0.071082,0.047531,-0.006013, + 0.904813,-0.425773,0.005552,0.071578,0.048501,-0.006167, + 0.87412,-0.480551,0.070606,0.071082,0.047531,-0.006013, + 0.876293,-0.481746,0.005552,0.071084,0.04753,-0.006167, + 0.929762,-0.368119,0.005552,0.072011,0.049501,-0.006167, + 0.927456,-0.367206,0.070606,0.07201,0.049501,-0.006013, + 0.902569,-0.424717,0.070606,0.071577,0.048502,-0.006013, + 0.929762,-0.368119,0.005552,0.072011,0.049501,-0.006167, + 0.902569,-0.424717,0.070606,0.071577,0.048502,-0.006013, + 0.904813,-0.425773,0.005552,0.071578,0.048501,-0.006167, + 0.951042,-0.309012,0.005552,0.07238,0.050526,-0.006167, + 0.948683,-0.308246,0.070606,0.072379,0.050526,-0.006013, + 0.927456,-0.367206,0.070606,0.07201,0.049501,-0.006013, + 0.951042,-0.309012,0.005552,0.07238,0.050526,-0.006167, + 0.927456,-0.367206,0.070606,0.07201,0.049501,-0.006013, + 0.929762,-0.368119,0.005552,0.072011,0.049501,-0.006167, + 0.968568,-0.248686,0.005552,0.072684,0.051572,-0.006167, + 0.966166,-0.248069,0.070606,0.072682,0.051572,-0.006013, + 0.948683,-0.308246,0.070606,0.072379,0.050526,-0.006013, + 0.968568,-0.248686,0.005552,0.072684,0.051572,-0.006167, + 0.948683,-0.308246,0.070606,0.072379,0.050526,-0.006013, + 0.951042,-0.309012,0.005552,0.07238,0.050526,-0.006167, + 0.982272,-0.187378,0.005552,0.072922,0.052635,-0.006167, + 0.979836,-0.186914,0.070606,0.07292,0.052636,-0.006013, + 0.966166,-0.248069,0.070606,0.072682,0.051572,-0.006013, + 0.982272,-0.187378,0.005552,0.072922,0.052635,-0.006167, + 0.966166,-0.248069,0.070606,0.072682,0.051572,-0.006013, + 0.968568,-0.248686,0.005552,0.072684,0.051572,-0.006167, + 0.992099,-0.125331,0.005552,0.073092,0.053712,-0.006167, + 0.989639,-0.12502,0.070606,0.073091,0.053712,-0.006013, + 0.979836,-0.186914,0.070606,0.07292,0.052636,-0.006013, + 0.992099,-0.125331,0.005552,0.073092,0.053712,-0.006167, + 0.979836,-0.186914,0.070606,0.07292,0.052636,-0.006013, + 0.982272,-0.187378,0.005552,0.072922,0.052635,-0.006167, + 0.997287,-0.07324,0.007402,0.073195,0.054796,-0.006167, + 0.995536,-0.062634,0.070606,0.073193,0.054796,-0.006013, + 0.989639,-0.12502,0.070606,0.073091,0.053712,-0.006013, + 0.997287,-0.07324,0.007402,0.073195,0.054796,-0.006167, + 0.989639,-0.12502,0.070606,0.073091,0.053712,-0.006013, + 0.992099,-0.125331,0.005552,0.073092,0.053712,-0.006167, + 0.999938,0,0.011104,0.073229,0.055885,-0.006167, + 0.997504,0,0.070606,0.073227,0.055885,-0.006013, + 0.995536,-0.062634,0.070606,0.073193,0.054796,-0.006013, + 0.999938,0,0.011104,0.073229,0.055885,-0.006167, + 0.995536,-0.062634,0.070606,0.073193,0.054796,-0.006013, + 0.997287,-0.07324,0.007402,0.073195,0.054796,-0.006167, + 0.997287,0.07324,0.007402,0.073195,0.056974,-0.006167, + 0.995536,0.062634,0.070606,0.073193,0.056974,-0.006013, + 0.997504,0,0.070606,0.073227,0.055885,-0.006013, + 0.997287,0.07324,0.007402,0.073195,0.056974,-0.006167, + 0.997504,0,0.070606,0.073227,0.055885,-0.006013, + 0.999938,0,0.011104,0.073229,0.055885,-0.006167, + 0.992099,0.125331,0.005552,0.073092,0.058059,-0.006167, + 0.989639,0.12502,0.070606,0.073091,0.058059,-0.006013, + 0.995536,0.062634,0.070606,0.073193,0.056974,-0.006013, + 0.992099,0.125331,0.005552,0.073092,0.058059,-0.006167, + 0.995536,0.062634,0.070606,0.073193,0.056974,-0.006013, + 0.997287,0.07324,0.007402,0.073195,0.056974,-0.006167, + 0.982272,0.187378,0.005552,0.072922,0.059135,-0.006167, + 0.979836,0.186914,0.070606,0.07292,0.059135,-0.006013, + 0.989639,0.12502,0.070606,0.073091,0.058059,-0.006013, + 0.982272,0.187378,0.005552,0.072922,0.059135,-0.006167, + 0.989639,0.12502,0.070606,0.073091,0.058059,-0.006013, + 0.992099,0.125331,0.005552,0.073092,0.058059,-0.006167, + 0.968568,0.248686,0.005552,0.072684,0.060198,-0.006167, + 0.966166,0.248069,0.070606,0.072682,0.060198,-0.006013, + 0.979836,0.186914,0.070606,0.07292,0.059135,-0.006013, + 0.968568,0.248686,0.005552,0.072684,0.060198,-0.006167, + 0.979836,0.186914,0.070606,0.07292,0.059135,-0.006013, + 0.982272,0.187378,0.005552,0.072922,0.059135,-0.006167, + 0.951042,0.309012,0.005552,0.07238,0.061245,-0.006167, + 0.948683,0.308246,0.070606,0.072379,0.061244,-0.006013, + 0.966166,0.248069,0.070606,0.072682,0.060198,-0.006013, + 0.951042,0.309012,0.005552,0.07238,0.061245,-0.006167, + 0.966166,0.248069,0.070606,0.072682,0.060198,-0.006013, + 0.968568,0.248686,0.005552,0.072684,0.060198,-0.006167, + 0.929762,0.368119,0.005552,0.072011,0.06227,-0.006167, + 0.927456,0.367206,0.070606,0.07201,0.062269,-0.006013, + 0.948683,0.308246,0.070606,0.072379,0.061244,-0.006013, + 0.929762,0.368119,0.005552,0.072011,0.06227,-0.006167, + 0.948683,0.308246,0.070606,0.072379,0.061244,-0.006013, + 0.951042,0.309012,0.005552,0.07238,0.061245,-0.006167, + 0.904813,0.425773,0.005552,0.071578,0.06327,-0.006167, + 0.902569,0.424717,0.070606,0.071577,0.063269,-0.006013, + 0.927456,0.367206,0.070606,0.07201,0.062269,-0.006013, + 0.904813,0.425773,0.005552,0.071578,0.06327,-0.006167, + 0.927456,0.367206,0.070606,0.07201,0.062269,-0.006013, + 0.929762,0.368119,0.005552,0.072011,0.06227,-0.006167, + 0.876293,0.481746,0.005552,0.071084,0.064241,-0.006167, + 0.87412,0.480551,0.070606,0.071082,0.06424,-0.006013, + 0.902569,0.424717,0.070606,0.071577,0.063269,-0.006013, + 0.876293,0.481746,0.005552,0.071084,0.064241,-0.006167, + 0.902569,0.424717,0.070606,0.071577,0.063269,-0.006013, + 0.904813,0.425773,0.005552,0.071578,0.06327,-0.006167, + 0.844315,0.535819,0.005552,0.070529,0.065178,-0.006167, + 0.842221,0.53449,0.070606,0.070528,0.065178,-0.006013, + 0.87412,0.480551,0.070606,0.071082,0.06424,-0.006013, + 0.844315,0.535819,0.005552,0.070529,0.065178,-0.006167, + 0.87412,0.480551,0.070606,0.071082,0.06424,-0.006013, + 0.876293,0.481746,0.005552,0.071084,0.064241,-0.006167, + 0.809005,0.587776,0.005552,0.069917,0.06608,-0.006167, + 0.806998,0.586318,0.070606,0.069915,0.066079,-0.006013, + 0.842221,0.53449,0.070606,0.070528,0.065178,-0.006013, + 0.809005,0.587776,0.005552,0.069917,0.06608,-0.006167, + 0.842221,0.53449,0.070606,0.070528,0.065178,-0.006013, + 0.844315,0.535819,0.005552,0.070529,0.065178,-0.006167, + 0.770501,0.637414,0.005552,0.069249,0.066941,-0.006167, + 0.76859,0.635833,0.070606,0.069247,0.06694,-0.006013, + 0.806998,0.586318,0.070606,0.069915,0.066079,-0.006013, + 0.770501,0.637414,0.005552,0.069249,0.066941,-0.006167, + 0.806998,0.586318,0.070606,0.069915,0.066079,-0.006013, + 0.809005,0.587776,0.005552,0.069917,0.06608,-0.006167, + 0.728957,0.684537,0.005552,0.068528,0.067758,-0.006167, + 0.727149,0.682839,0.070606,0.068527,0.067757,-0.006013, + 0.76859,0.635833,0.070606,0.069247,0.06694,-0.006013, + 0.728957,0.684537,0.005552,0.068528,0.067758,-0.006167, + 0.76859,0.635833,0.070606,0.069247,0.06694,-0.006013, + 0.770501,0.637414,0.005552,0.069249,0.066941,-0.006167, + 0.684537,0.728957,0.005552,0.067758,0.068528,-0.006167, + 0.682839,0.727149,0.070606,0.067757,0.068527,-0.006013, + 0.727149,0.682839,0.070606,0.068527,0.067757,-0.006013, + 0.684537,0.728957,0.005552,0.067758,0.068528,-0.006167, + 0.727149,0.682839,0.070606,0.068527,0.067757,-0.006013, + 0.728957,0.684537,0.005552,0.068528,0.067758,-0.006167, + 0.637414,0.770501,0.005552,0.066941,0.069249,-0.006167, + 0.635833,0.76859,0.070606,0.06694,0.069247,-0.006013, + 0.682839,0.727149,0.070606,0.067757,0.068527,-0.006013, + 0.637414,0.770501,0.005552,0.066941,0.069249,-0.006167, + 0.682839,0.727149,0.070606,0.067757,0.068527,-0.006013, + 0.684537,0.728957,0.005552,0.067758,0.068528,-0.006167, + 0.587776,0.809005,0.005552,0.06608,0.069917,-0.006167, + 0.586318,0.806998,0.070606,0.066079,0.069915,-0.006013, + 0.635833,0.76859,0.070606,0.06694,0.069247,-0.006013, + 0.587776,0.809005,0.005552,0.06608,0.069917,-0.006167, + 0.635833,0.76859,0.070606,0.06694,0.069247,-0.006013, + 0.637414,0.770501,0.005552,0.066941,0.069249,-0.006167, + 0.535819,0.844315,0.005552,0.065178,0.070529,-0.006167, + 0.53449,0.842221,0.070606,0.065178,0.070528,-0.006013, + 0.586318,0.806998,0.070606,0.066079,0.069915,-0.006013, + 0.535819,0.844315,0.005552,0.065178,0.070529,-0.006167, + 0.586318,0.806998,0.070606,0.066079,0.069915,-0.006013, + 0.587776,0.809005,0.005552,0.06608,0.069917,-0.006167, + 0.481746,0.876293,0.005552,0.064241,0.071084,-0.006167, + 0.480551,0.87412,0.070606,0.06424,0.071082,-0.006013, + 0.53449,0.842221,0.070606,0.065178,0.070528,-0.006013, + 0.481746,0.876293,0.005552,0.064241,0.071084,-0.006167, + 0.53449,0.842221,0.070606,0.065178,0.070528,-0.006013, + 0.535819,0.844315,0.005552,0.065178,0.070529,-0.006167, + 0.425773,0.904813,0.005552,0.06327,0.071578,-0.006167, + 0.424717,0.902569,0.070606,0.063269,0.071577,-0.006013, + 0.480551,0.87412,0.070606,0.06424,0.071082,-0.006013, + 0.425773,0.904813,0.005552,0.06327,0.071578,-0.006167, + 0.480551,0.87412,0.070606,0.06424,0.071082,-0.006013, + 0.481746,0.876293,0.005552,0.064241,0.071084,-0.006167, + 0.368119,0.929762,0.005552,0.06227,0.072011,-0.006167, + 0.367206,0.927456,0.070606,0.062269,0.07201,-0.006013, + 0.424717,0.902569,0.070606,0.063269,0.071577,-0.006013, + 0.368119,0.929762,0.005552,0.06227,0.072011,-0.006167, + 0.424717,0.902569,0.070606,0.063269,0.071577,-0.006013, + 0.425773,0.904813,0.005552,0.06327,0.071578,-0.006167, + 0.309012,0.951042,0.005552,0.061245,0.07238,-0.006167, + 0.308246,0.948683,0.070606,0.061244,0.072379,-0.006013, + 0.367206,0.927456,0.070606,0.062269,0.07201,-0.006013, + 0.309012,0.951042,0.005552,0.061245,0.07238,-0.006167, + 0.367206,0.927456,0.070606,0.062269,0.07201,-0.006013, + 0.368119,0.929762,0.005552,0.06227,0.072011,-0.006167, + 0.248686,0.968568,0.005552,0.060198,0.072684,-0.006167, + 0.248069,0.966166,0.070606,0.060198,0.072682,-0.006013, + 0.308246,0.948683,0.070606,0.061244,0.072379,-0.006013, + 0.248686,0.968568,0.005552,0.060198,0.072684,-0.006167, + 0.308246,0.948683,0.070606,0.061244,0.072379,-0.006013, + 0.309012,0.951042,0.005552,0.061245,0.07238,-0.006167, + 0.187378,0.982272,0.005552,0.059135,0.072922,-0.006167, + 0.186914,0.979836,0.070606,0.059135,0.07292,-0.006013, + 0.248069,0.966166,0.070606,0.060198,0.072682,-0.006013, + 0.187378,0.982272,0.005552,0.059135,0.072922,-0.006167, + 0.248069,0.966166,0.070606,0.060198,0.072682,-0.006013, + 0.248686,0.968568,0.005552,0.060198,0.072684,-0.006167, + 0.125331,0.992099,0.005552,0.058059,0.073092,-0.006167, + 0.12502,0.989639,0.070606,0.058059,0.073091,-0.006013, + 0.186914,0.979836,0.070606,0.059135,0.07292,-0.006013, + 0.125331,0.992099,0.005552,0.058059,0.073092,-0.006167, + 0.186914,0.979836,0.070606,0.059135,0.07292,-0.006013, + 0.187378,0.982272,0.005552,0.059135,0.072922,-0.006167, + 0.07324,0.997287,0.007402,0.056974,0.073195,-0.006167, + 0.062634,0.995536,0.070606,0.056974,0.073193,-0.006013, + 0.12502,0.989639,0.070606,0.058059,0.073091,-0.006013, + 0.07324,0.997287,0.007402,0.056974,0.073195,-0.006167, + 0.12502,0.989639,0.070606,0.058059,0.073091,-0.006013, + 0.125331,0.992099,0.005552,0.058059,0.073092,-0.006167, + 0,0.999938,0.011104,0.055885,0.073229,-0.006167, + 0,0.997504,0.070606,0.055885,0.073227,-0.006013, + 0.062634,0.995536,0.070606,0.056974,0.073193,-0.006013, + 0,0.999938,0.011104,0.055885,0.073229,-0.006167, + 0.062634,0.995536,0.070606,0.056974,0.073193,-0.006013, + 0.07324,0.997287,0.007402,0.056974,0.073195,-0.006167, + -0.07324,0.997287,0.007402,0.054796,0.073195,-0.006167, + -0.062634,0.995536,0.070606,0.054796,0.073193,-0.006013, + 0,0.997504,0.070606,0.055885,0.073227,-0.006013, + -0.07324,0.997287,0.007402,0.054796,0.073195,-0.006167, + 0,0.997504,0.070606,0.055885,0.073227,-0.006013, + 0,0.999938,0.011104,0.055885,0.073229,-0.006167, + -0.125331,0.992099,0.005552,0.053712,0.073092,-0.006167, + -0.12502,0.989639,0.070606,0.053712,0.073091,-0.006013, + -0.062634,0.995536,0.070606,0.054796,0.073193,-0.006013, + -0.125331,0.992099,0.005552,0.053712,0.073092,-0.006167, + -0.062634,0.995536,0.070606,0.054796,0.073193,-0.006013, + -0.07324,0.997287,0.007402,0.054796,0.073195,-0.006167, + -0.187378,0.982272,0.005552,0.052635,0.072922,-0.006167, + -0.186914,0.979836,0.070606,0.052636,0.07292,-0.006013, + -0.12502,0.989639,0.070606,0.053712,0.073091,-0.006013, + -0.187378,0.982272,0.005552,0.052635,0.072922,-0.006167, + -0.12502,0.989639,0.070606,0.053712,0.073091,-0.006013, + -0.125331,0.992099,0.005552,0.053712,0.073092,-0.006167, + -0.248686,0.968568,0.005552,0.051572,0.072684,-0.006167, + -0.248069,0.966166,0.070606,0.051572,0.072682,-0.006013, + -0.186914,0.979836,0.070606,0.052636,0.07292,-0.006013, + -0.248686,0.968568,0.005552,0.051572,0.072684,-0.006167, + -0.186914,0.979836,0.070606,0.052636,0.07292,-0.006013, + -0.187378,0.982272,0.005552,0.052635,0.072922,-0.006167, + -0.309012,0.951042,0.005552,0.050526,0.07238,-0.006167, + -0.308246,0.948683,0.070606,0.050526,0.072379,-0.006013, + -0.248069,0.966166,0.070606,0.051572,0.072682,-0.006013, + -0.309012,0.951042,0.005552,0.050526,0.07238,-0.006167, + -0.248069,0.966166,0.070606,0.051572,0.072682,-0.006013, + -0.248686,0.968568,0.005552,0.051572,0.072684,-0.006167, + -0.368119,0.929762,0.005552,0.049501,0.072011,-0.006167, + -0.367206,0.927456,0.070606,0.049501,0.07201,-0.006013, + -0.308246,0.948683,0.070606,0.050526,0.072379,-0.006013, + -0.368119,0.929762,0.005552,0.049501,0.072011,-0.006167, + -0.308246,0.948683,0.070606,0.050526,0.072379,-0.006013, + -0.309012,0.951042,0.005552,0.050526,0.07238,-0.006167, + -0.425773,0.904813,0.005552,0.048501,0.071578,-0.006167, + -0.424717,0.902569,0.070606,0.048502,0.071577,-0.006013, + -0.367206,0.927456,0.070606,0.049501,0.07201,-0.006013, + -0.425773,0.904813,0.005552,0.048501,0.071578,-0.006167, + -0.367206,0.927456,0.070606,0.049501,0.07201,-0.006013, + -0.368119,0.929762,0.005552,0.049501,0.072011,-0.006167, + -0.481746,0.876293,0.005552,0.04753,0.071084,-0.006167, + -0.480551,0.87412,0.070606,0.047531,0.071082,-0.006013, + -0.424717,0.902569,0.070606,0.048502,0.071577,-0.006013, + -0.481746,0.876293,0.005552,0.04753,0.071084,-0.006167, + -0.424717,0.902569,0.070606,0.048502,0.071577,-0.006013, + -0.425773,0.904813,0.005552,0.048501,0.071578,-0.006167, + -0.535819,0.844315,0.005552,0.046592,0.070529,-0.006167, + -0.53449,0.842221,0.070606,0.046593,0.070528,-0.006013, + -0.480551,0.87412,0.070606,0.047531,0.071082,-0.006013, + -0.535819,0.844315,0.005552,0.046592,0.070529,-0.006167, + -0.480551,0.87412,0.070606,0.047531,0.071082,-0.006013, + -0.481746,0.876293,0.005552,0.04753,0.071084,-0.006167, + -0.587776,0.809005,0.005552,0.045691,0.069917,-0.006167, + -0.586318,0.806998,0.070606,0.045692,0.069915,-0.006013, + -0.53449,0.842221,0.070606,0.046593,0.070528,-0.006013, + -0.587776,0.809005,0.005552,0.045691,0.069917,-0.006167, + -0.53449,0.842221,0.070606,0.046593,0.070528,-0.006013, + -0.535819,0.844315,0.005552,0.046592,0.070529,-0.006167, + -0.637414,0.770501,0.005552,0.04483,0.069249,-0.006167, + -0.635833,0.76859,0.070606,0.044831,0.069247,-0.006013, + -0.586318,0.806998,0.070606,0.045692,0.069915,-0.006013, + -0.637414,0.770501,0.005552,0.04483,0.069249,-0.006167, + -0.586318,0.806998,0.070606,0.045692,0.069915,-0.006013, + -0.587776,0.809005,0.005552,0.045691,0.069917,-0.006167, + -0.684537,0.728957,0.005552,0.044013,0.068528,-0.006167, + -0.682839,0.727149,0.070606,0.044014,0.068527,-0.006013, + -0.635833,0.76859,0.070606,0.044831,0.069247,-0.006013, + -0.684537,0.728957,0.005552,0.044013,0.068528,-0.006167, + -0.635833,0.76859,0.070606,0.044831,0.069247,-0.006013, + -0.637414,0.770501,0.005552,0.04483,0.069249,-0.006167, + -0.728957,0.684537,0.005552,0.043242,0.067758,-0.006167, + -0.727149,0.682839,0.070606,0.043243,0.067757,-0.006013, + -0.682839,0.727149,0.070606,0.044014,0.068527,-0.006013, + -0.728957,0.684537,0.005552,0.043242,0.067758,-0.006167, + -0.682839,0.727149,0.070606,0.044014,0.068527,-0.006013, + -0.684537,0.728957,0.005552,0.044013,0.068528,-0.006167, + -0.770501,0.637414,0.005552,0.042522,0.066941,-0.006167, + -0.76859,0.635833,0.070606,0.042523,0.06694,-0.006013, + -0.727149,0.682839,0.070606,0.043243,0.067757,-0.006013, + -0.770501,0.637414,0.005552,0.042522,0.066941,-0.006167, + -0.727149,0.682839,0.070606,0.043243,0.067757,-0.006013, + -0.728957,0.684537,0.005552,0.043242,0.067758,-0.006167, + -0.809005,0.587776,0.005552,0.041854,0.06608,-0.006167, + -0.806998,0.586318,0.070606,0.041855,0.066079,-0.006013, + -0.76859,0.635833,0.070606,0.042523,0.06694,-0.006013, + -0.809005,0.587776,0.005552,0.041854,0.06608,-0.006167, + -0.76859,0.635833,0.070606,0.042523,0.06694,-0.006013, + -0.770501,0.637414,0.005552,0.042522,0.066941,-0.006167, + -0.844315,0.535819,0.005552,0.041241,0.065178,-0.006167, + -0.842221,0.53449,0.070606,0.041243,0.065178,-0.006013, + -0.806998,0.586318,0.070606,0.041855,0.066079,-0.006013, + -0.844315,0.535819,0.005552,0.041241,0.065178,-0.006167, + -0.806998,0.586318,0.070606,0.041855,0.066079,-0.006013, + -0.809005,0.587776,0.005552,0.041854,0.06608,-0.006167, + -0.876293,0.481746,0.005552,0.040687,0.064241,-0.006167, + -0.87412,0.480551,0.070606,0.040688,0.06424,-0.006013, + -0.842221,0.53449,0.070606,0.041243,0.065178,-0.006013, + -0.876293,0.481746,0.005552,0.040687,0.064241,-0.006167, + -0.842221,0.53449,0.070606,0.041243,0.065178,-0.006013, + -0.844315,0.535819,0.005552,0.041241,0.065178,-0.006167, + -0.904813,0.425773,0.005552,0.040192,0.06327,-0.006167, + -0.902569,0.424717,0.070606,0.040194,0.063269,-0.006013, + -0.87412,0.480551,0.070606,0.040688,0.06424,-0.006013, + -0.904813,0.425773,0.005552,0.040192,0.06327,-0.006167, + -0.87412,0.480551,0.070606,0.040688,0.06424,-0.006013, + -0.876293,0.481746,0.005552,0.040687,0.064241,-0.006167, + -0.929762,0.368119,0.005552,0.03976,0.06227,-0.006167, + -0.927456,0.367206,0.070606,0.039761,0.062269,-0.006013, + -0.902569,0.424717,0.070606,0.040194,0.063269,-0.006013, + -0.929762,0.368119,0.005552,0.03976,0.06227,-0.006167, + -0.902569,0.424717,0.070606,0.040194,0.063269,-0.006013, + -0.904813,0.425773,0.005552,0.040192,0.06327,-0.006167, + -0.951042,0.309012,0.005552,0.03939,0.061245,-0.006167, + -0.948683,0.308246,0.070606,0.039392,0.061244,-0.006013, + -0.927456,0.367206,0.070606,0.039761,0.062269,-0.006013, + -0.951042,0.309012,0.005552,0.03939,0.061245,-0.006167, + -0.927456,0.367206,0.070606,0.039761,0.062269,-0.006013, + -0.929762,0.368119,0.005552,0.03976,0.06227,-0.006167, + -0.968568,0.248686,0.005552,0.039087,0.060198,-0.006167, + -0.966166,0.248069,0.070606,0.039088,0.060198,-0.006013, + -0.948683,0.308246,0.070606,0.039392,0.061244,-0.006013, + -0.968568,0.248686,0.005552,0.039087,0.060198,-0.006167, + -0.948683,0.308246,0.070606,0.039392,0.061244,-0.006013, + -0.951042,0.309012,0.005552,0.03939,0.061245,-0.006167, + -0.982272,0.187378,0.005552,0.038849,0.059135,-0.006167, + -0.979836,0.186914,0.070606,0.03885,0.059135,-0.006013, + -0.966166,0.248069,0.070606,0.039088,0.060198,-0.006013, + -0.982272,0.187378,0.005552,0.038849,0.059135,-0.006167, + -0.966166,0.248069,0.070606,0.039088,0.060198,-0.006013, + -0.968568,0.248686,0.005552,0.039087,0.060198,-0.006167, + -0.992099,0.125331,0.005552,0.038678,0.058059,-0.006167, + -0.989639,0.12502,0.070606,0.03868,0.058059,-0.006013, + -0.979836,0.186914,0.070606,0.03885,0.059135,-0.006013, + -0.992099,0.125331,0.005552,0.038678,0.058059,-0.006167, + -0.979836,0.186914,0.070606,0.03885,0.059135,-0.006013, + -0.982272,0.187378,0.005552,0.038849,0.059135,-0.006167, + -0.997287,0.07324,0.007402,0.038576,0.056974,-0.006167, + -0.995536,0.062634,0.070606,0.038577,0.056974,-0.006013, + -0.989639,0.12502,0.070606,0.03868,0.058059,-0.006013, + -0.997287,0.07324,0.007402,0.038576,0.056974,-0.006167, + -0.989639,0.12502,0.070606,0.03868,0.058059,-0.006013, + -0.992099,0.125331,0.005552,0.038678,0.058059,-0.006167, + -0.999938,0,0.011104,0.038542,0.055885,-0.006167, + -0.997504,0,0.070606,0.038543,0.055885,-0.006013, + -0.995536,0.062634,0.070606,0.038577,0.056974,-0.006013, + -0.999938,0,0.011104,0.038542,0.055885,-0.006167, + -0.995536,0.062634,0.070606,0.038577,0.056974,-0.006013, + -0.997287,0.07324,0.007402,0.038576,0.056974,-0.006167, + -0.997287,-0.07324,0.007402,0.038576,0.054796,-0.006167, + -0.995536,-0.062634,0.070606,0.038577,0.054796,-0.006013, + -0.997504,0,0.070606,0.038543,0.055885,-0.006013, + -0.997287,-0.07324,0.007402,0.038576,0.054796,-0.006167, + -0.997504,0,0.070606,0.038543,0.055885,-0.006013, + -0.999938,0,0.011104,0.038542,0.055885,-0.006167, + -0.992099,-0.125331,0.005552,0.038678,0.053712,-0.006167, + -0.989639,-0.12502,0.070606,0.03868,0.053712,-0.006013, + -0.995536,-0.062634,0.070606,0.038577,0.054796,-0.006013, + -0.992099,-0.125331,0.005552,0.038678,0.053712,-0.006167, + -0.995536,-0.062634,0.070606,0.038577,0.054796,-0.006013, + -0.997287,-0.07324,0.007402,0.038576,0.054796,-0.006167, + -0.982272,-0.187378,0.005552,0.038849,0.052635,-0.006167, + -0.979836,-0.186914,0.070606,0.03885,0.052636,-0.006013, + -0.989639,-0.12502,0.070606,0.03868,0.053712,-0.006013, + -0.982272,-0.187378,0.005552,0.038849,0.052635,-0.006167, + -0.989639,-0.12502,0.070606,0.03868,0.053712,-0.006013, + -0.992099,-0.125331,0.005552,0.038678,0.053712,-0.006167, + -0.968568,-0.248686,0.005552,0.039087,0.051572,-0.006167, + -0.966166,-0.248069,0.070606,0.039088,0.051572,-0.006013, + -0.979836,-0.186914,0.070606,0.03885,0.052636,-0.006013, + -0.968568,-0.248686,0.005552,0.039087,0.051572,-0.006167, + -0.979836,-0.186914,0.070606,0.03885,0.052636,-0.006013, + -0.982272,-0.187378,0.005552,0.038849,0.052635,-0.006167, + -0.951042,-0.309012,0.005552,0.03939,0.050526,-0.006167, + -0.948683,-0.308246,0.070606,0.039392,0.050526,-0.006013, + -0.966166,-0.248069,0.070606,0.039088,0.051572,-0.006013, + -0.951042,-0.309012,0.005552,0.03939,0.050526,-0.006167, + -0.966166,-0.248069,0.070606,0.039088,0.051572,-0.006013, + -0.968568,-0.248686,0.005552,0.039087,0.051572,-0.006167, + -0.929762,-0.368119,0.005552,0.03976,0.049501,-0.006167, + -0.927456,-0.367206,0.070606,0.039761,0.049501,-0.006013, + -0.948683,-0.308246,0.070606,0.039392,0.050526,-0.006013, + -0.929762,-0.368119,0.005552,0.03976,0.049501,-0.006167, + -0.948683,-0.308246,0.070606,0.039392,0.050526,-0.006013, + -0.951042,-0.309012,0.005552,0.03939,0.050526,-0.006167, + -0.927456,-0.367206,0.070606,0.039761,0.049501,-0.006013, + -0.913082,-0.361515,0.18865,0.03978,0.049509,-0.005861, + -0.93398,-0.303468,0.18865,0.039411,0.050532,-0.005861, + -0.927456,-0.367206,0.070606,0.039761,0.049501,-0.006013, + -0.93398,-0.303468,0.18865,0.039411,0.050532,-0.005861, + -0.948683,-0.308246,0.070606,0.039392,0.050526,-0.006013, + -0.902569,-0.424717,0.070606,0.040194,0.048502,-0.006013, + -0.88858,-0.418134,0.18865,0.040212,0.04851,-0.005861, + -0.913082,-0.361515,0.18865,0.03978,0.049509,-0.005861, + -0.902569,-0.424717,0.070606,0.040194,0.048502,-0.006013, + -0.913082,-0.361515,0.18865,0.03978,0.049509,-0.005861, + -0.927456,-0.367206,0.070606,0.039761,0.049501,-0.006013, + -0.87412,-0.480551,0.070606,0.040688,0.047531,-0.006013, + -0.860572,-0.473103,0.18865,0.040706,0.04754,-0.005861, + -0.88858,-0.418134,0.18865,0.040212,0.04851,-0.005861, + -0.87412,-0.480551,0.070606,0.040688,0.047531,-0.006013, + -0.88858,-0.418134,0.18865,0.040212,0.04851,-0.005861, + -0.902569,-0.424717,0.070606,0.040194,0.048502,-0.006013, + -0.842221,-0.53449,0.070606,0.041243,0.046593,-0.006013, + -0.829167,-0.526206,0.18865,0.04126,0.046604,-0.005861, + -0.860572,-0.473103,0.18865,0.040706,0.04754,-0.005861, + -0.842221,-0.53449,0.070606,0.041243,0.046593,-0.006013, + -0.860572,-0.473103,0.18865,0.040706,0.04754,-0.005861, + -0.87412,-0.480551,0.070606,0.040688,0.047531,-0.006013, + -0.806998,-0.586318,0.070606,0.041855,0.045692,-0.006013, + -0.794491,-0.577231,0.18865,0.041871,0.045704,-0.005861, + -0.829167,-0.526206,0.18865,0.04126,0.046604,-0.005861, + -0.806998,-0.586318,0.070606,0.041855,0.045692,-0.006013, + -0.829167,-0.526206,0.18865,0.04126,0.046604,-0.005861, + -0.842221,-0.53449,0.070606,0.041243,0.046593,-0.006013, + -0.76859,-0.635833,0.070606,0.042523,0.044831,-0.006013, + -0.756678,-0.625979,0.18865,0.042538,0.044844,-0.005861, + -0.794491,-0.577231,0.18865,0.041871,0.045704,-0.005861, + -0.76859,-0.635833,0.070606,0.042523,0.044831,-0.006013, + -0.794491,-0.577231,0.18865,0.041871,0.045704,-0.005861, + -0.806998,-0.586318,0.070606,0.041855,0.045692,-0.006013, + -0.727149,-0.682839,0.070606,0.043243,0.044014,-0.006013, + -0.715879,-0.672256,0.18865,0.043258,0.044028,-0.005861, + -0.756678,-0.625979,0.18865,0.042538,0.044844,-0.005861, + -0.727149,-0.682839,0.070606,0.043243,0.044014,-0.006013, + -0.756678,-0.625979,0.18865,0.042538,0.044844,-0.005861, + -0.76859,-0.635833,0.070606,0.042523,0.044831,-0.006013, + -0.682839,-0.727149,0.070606,0.044014,0.043243,-0.006013, + -0.672256,-0.715879,0.18865,0.044028,0.043258,-0.005861, + -0.715879,-0.672256,0.18865,0.043258,0.044028,-0.005861, + -0.682839,-0.727149,0.070606,0.044014,0.043243,-0.006013, + -0.715879,-0.672256,0.18865,0.043258,0.044028,-0.005861, + -0.727149,-0.682839,0.070606,0.043243,0.044014,-0.006013, + -0.635833,-0.76859,0.070606,0.044831,0.042523,-0.006013, + -0.625979,-0.756678,0.18865,0.044844,0.042538,-0.005861, + -0.672256,-0.715879,0.18865,0.044028,0.043258,-0.005861, + -0.635833,-0.76859,0.070606,0.044831,0.042523,-0.006013, + -0.672256,-0.715879,0.18865,0.044028,0.043258,-0.005861, + -0.682839,-0.727149,0.070606,0.044014,0.043243,-0.006013, + -0.586318,-0.806998,0.070606,0.045692,0.041855,-0.006013, + -0.577231,-0.794491,0.18865,0.045704,0.041871,-0.005861, + -0.625979,-0.756678,0.18865,0.044844,0.042538,-0.005861, + -0.586318,-0.806998,0.070606,0.045692,0.041855,-0.006013, + -0.625979,-0.756678,0.18865,0.044844,0.042538,-0.005861, + -0.635833,-0.76859,0.070606,0.044831,0.042523,-0.006013, + -0.53449,-0.842221,0.070606,0.046593,0.041243,-0.006013, + -0.526206,-0.829167,0.18865,0.046604,0.04126,-0.005861, + -0.577231,-0.794491,0.18865,0.045704,0.041871,-0.005861, + -0.53449,-0.842221,0.070606,0.046593,0.041243,-0.006013, + -0.577231,-0.794491,0.18865,0.045704,0.041871,-0.005861, + -0.586318,-0.806998,0.070606,0.045692,0.041855,-0.006013, + -0.480551,-0.87412,0.070606,0.047531,0.040688,-0.006013, + -0.473103,-0.860572,0.18865,0.04754,0.040706,-0.005861, + -0.526206,-0.829167,0.18865,0.046604,0.04126,-0.005861, + -0.480551,-0.87412,0.070606,0.047531,0.040688,-0.006013, + -0.526206,-0.829167,0.18865,0.046604,0.04126,-0.005861, + -0.53449,-0.842221,0.070606,0.046593,0.041243,-0.006013, + -0.424717,-0.902569,0.070606,0.048502,0.040194,-0.006013, + -0.418134,-0.88858,0.18865,0.04851,0.040212,-0.005861, + -0.473103,-0.860572,0.18865,0.04754,0.040706,-0.005861, + -0.424717,-0.902569,0.070606,0.048502,0.040194,-0.006013, + -0.473103,-0.860572,0.18865,0.04754,0.040706,-0.005861, + -0.480551,-0.87412,0.070606,0.047531,0.040688,-0.006013, + -0.367206,-0.927456,0.070606,0.049501,0.039761,-0.006013, + -0.361515,-0.913082,0.18865,0.049509,0.03978,-0.005861, + -0.418134,-0.88858,0.18865,0.04851,0.040212,-0.005861, + -0.367206,-0.927456,0.070606,0.049501,0.039761,-0.006013, + -0.418134,-0.88858,0.18865,0.04851,0.040212,-0.005861, + -0.424717,-0.902569,0.070606,0.048502,0.040194,-0.006013, + -0.308246,-0.948683,0.070606,0.050526,0.039392,-0.006013, + -0.303468,-0.93398,0.18865,0.050532,0.039411,-0.005861, + -0.361515,-0.913082,0.18865,0.049509,0.03978,-0.005861, + -0.308246,-0.948683,0.070606,0.050526,0.039392,-0.006013, + -0.361515,-0.913082,0.18865,0.049509,0.03978,-0.005861, + -0.367206,-0.927456,0.070606,0.049501,0.039761,-0.006013, + -0.248069,-0.966166,0.070606,0.051572,0.039088,-0.006013, + -0.244224,-0.951192,0.18865,0.051578,0.039107,-0.005861, + -0.303468,-0.93398,0.18865,0.050532,0.039411,-0.005861, + -0.248069,-0.966166,0.070606,0.051572,0.039088,-0.006013, + -0.303468,-0.93398,0.18865,0.050532,0.039411,-0.005861, + -0.308246,-0.948683,0.070606,0.050526,0.039392,-0.006013, + -0.186914,-0.979836,0.070606,0.052636,0.03885,-0.006013, + -0.184017,-0.96465,0.18865,0.05264,0.03887,-0.005861, + -0.244224,-0.951192,0.18865,0.051578,0.039107,-0.005861, + -0.186914,-0.979836,0.070606,0.052636,0.03885,-0.006013, + -0.244224,-0.951192,0.18865,0.051578,0.039107,-0.005861, + -0.248069,-0.966166,0.070606,0.051572,0.039088,-0.006013, + -0.12502,-0.989639,0.070606,0.053712,0.03868,-0.006013, + -0.123083,-0.974301,0.18865,0.053714,0.0387,-0.005861, + -0.184017,-0.96465,0.18865,0.05264,0.03887,-0.005861, + -0.12502,-0.989639,0.070606,0.053712,0.03868,-0.006013, + -0.184017,-0.96465,0.18865,0.05264,0.03887,-0.005861, + -0.186914,-0.979836,0.070606,0.052636,0.03885,-0.006013, + -0.062634,-0.995536,0.070606,0.054796,0.038577,-0.006013, + -0.061663,-0.980106,0.18865,0.054798,0.038597,-0.005861, + -0.123083,-0.974301,0.18865,0.053714,0.0387,-0.005861, + -0.062634,-0.995536,0.070606,0.054796,0.038577,-0.006013, + -0.123083,-0.974301,0.18865,0.053714,0.0387,-0.005861, + -0.12502,-0.989639,0.070606,0.053712,0.03868,-0.006013, + 0,-0.997504,0.070606,0.055885,0.038543,-0.006013, + 0,-0.982044,0.18865,0.055885,0.038563,-0.005861, + -0.061663,-0.980106,0.18865,0.054798,0.038597,-0.005861, + 0,-0.997504,0.070606,0.055885,0.038543,-0.006013, + -0.061663,-0.980106,0.18865,0.054798,0.038597,-0.005861, + -0.062634,-0.995536,0.070606,0.054796,0.038577,-0.006013, + 0.062634,-0.995536,0.070606,0.056974,0.038577,-0.006013, + 0.061663,-0.980106,0.18865,0.056973,0.038597,-0.005861, + 0,-0.982044,0.18865,0.055885,0.038563,-0.005861, + 0.062634,-0.995536,0.070606,0.056974,0.038577,-0.006013, + 0,-0.982044,0.18865,0.055885,0.038563,-0.005861, + 0,-0.997504,0.070606,0.055885,0.038543,-0.006013, + 0.12502,-0.989639,0.070606,0.058059,0.03868,-0.006013, + 0.123083,-0.974301,0.18865,0.058056,0.0387,-0.005861, + 0.061663,-0.980106,0.18865,0.056973,0.038597,-0.005861, + 0.12502,-0.989639,0.070606,0.058059,0.03868,-0.006013, + 0.061663,-0.980106,0.18865,0.056973,0.038597,-0.005861, + 0.062634,-0.995536,0.070606,0.056974,0.038577,-0.006013, + 0.186914,-0.979836,0.070606,0.059135,0.03885,-0.006013, + 0.184017,-0.96465,0.18865,0.059131,0.03887,-0.005861, + 0.123083,-0.974301,0.18865,0.058056,0.0387,-0.005861, + 0.186914,-0.979836,0.070606,0.059135,0.03885,-0.006013, + 0.123083,-0.974301,0.18865,0.058056,0.0387,-0.005861, + 0.12502,-0.989639,0.070606,0.058059,0.03868,-0.006013, + 0.248069,-0.966166,0.070606,0.060198,0.039088,-0.006013, + 0.244224,-0.951192,0.18865,0.060193,0.039107,-0.005861, + 0.184017,-0.96465,0.18865,0.059131,0.03887,-0.005861, + 0.248069,-0.966166,0.070606,0.060198,0.039088,-0.006013, + 0.184017,-0.96465,0.18865,0.059131,0.03887,-0.005861, + 0.186914,-0.979836,0.070606,0.059135,0.03885,-0.006013, + 0.308246,-0.948683,0.070606,0.061244,0.039392,-0.006013, + 0.303468,-0.93398,0.18865,0.061238,0.039411,-0.005861, + 0.244224,-0.951192,0.18865,0.060193,0.039107,-0.005861, + 0.308246,-0.948683,0.070606,0.061244,0.039392,-0.006013, + 0.244224,-0.951192,0.18865,0.060193,0.039107,-0.005861, + 0.248069,-0.966166,0.070606,0.060198,0.039088,-0.006013, + 0.367206,-0.927456,0.070606,0.062269,0.039761,-0.006013, + 0.361515,-0.913082,0.18865,0.062262,0.03978,-0.005861, + 0.303468,-0.93398,0.18865,0.061238,0.039411,-0.005861, + 0.367206,-0.927456,0.070606,0.062269,0.039761,-0.006013, + 0.303468,-0.93398,0.18865,0.061238,0.039411,-0.005861, + 0.308246,-0.948683,0.070606,0.061244,0.039392,-0.006013, + 0.424717,-0.902569,0.070606,0.063269,0.040194,-0.006013, + 0.418134,-0.88858,0.18865,0.063261,0.040212,-0.005861, + 0.361515,-0.913082,0.18865,0.062262,0.03978,-0.005861, + 0.424717,-0.902569,0.070606,0.063269,0.040194,-0.006013, + 0.361515,-0.913082,0.18865,0.062262,0.03978,-0.005861, + 0.367206,-0.927456,0.070606,0.062269,0.039761,-0.006013, + 0.480551,-0.87412,0.070606,0.06424,0.040688,-0.006013, + 0.473103,-0.860572,0.18865,0.06423,0.040706,-0.005861, + 0.418134,-0.88858,0.18865,0.063261,0.040212,-0.005861, + 0.480551,-0.87412,0.070606,0.06424,0.040688,-0.006013, + 0.418134,-0.88858,0.18865,0.063261,0.040212,-0.005861, + 0.424717,-0.902569,0.070606,0.063269,0.040194,-0.006013, + 0.53449,-0.842221,0.070606,0.065178,0.041243,-0.006013, + 0.526206,-0.829167,0.18865,0.065167,0.04126,-0.005861, + 0.473103,-0.860572,0.18865,0.06423,0.040706,-0.005861, + 0.53449,-0.842221,0.070606,0.065178,0.041243,-0.006013, + 0.473103,-0.860572,0.18865,0.06423,0.040706,-0.005861, + 0.480551,-0.87412,0.070606,0.06424,0.040688,-0.006013, + 0.586318,-0.806998,0.070606,0.066079,0.041855,-0.006013, + 0.577231,-0.794491,0.18865,0.066067,0.041871,-0.005861, + 0.526206,-0.829167,0.18865,0.065167,0.04126,-0.005861, + 0.586318,-0.806998,0.070606,0.066079,0.041855,-0.006013, + 0.526206,-0.829167,0.18865,0.065167,0.04126,-0.005861, + 0.53449,-0.842221,0.070606,0.065178,0.041243,-0.006013, + 0.635833,-0.76859,0.070606,0.06694,0.042523,-0.006013, + 0.625979,-0.756678,0.18865,0.066927,0.042538,-0.005861, + 0.577231,-0.794491,0.18865,0.066067,0.041871,-0.005861, + 0.635833,-0.76859,0.070606,0.06694,0.042523,-0.006013, + 0.577231,-0.794491,0.18865,0.066067,0.041871,-0.005861, + 0.586318,-0.806998,0.070606,0.066079,0.041855,-0.006013, + 0.682839,-0.727149,0.070606,0.067757,0.043243,-0.006013, + 0.672256,-0.715879,0.18865,0.067743,0.043258,-0.005861, + 0.625979,-0.756678,0.18865,0.066927,0.042538,-0.005861, + 0.682839,-0.727149,0.070606,0.067757,0.043243,-0.006013, + 0.625979,-0.756678,0.18865,0.066927,0.042538,-0.005861, + 0.635833,-0.76859,0.070606,0.06694,0.042523,-0.006013, + 0.727149,-0.682839,0.070606,0.068527,0.044014,-0.006013, + 0.715879,-0.672256,0.18865,0.068512,0.044028,-0.005861, + 0.672256,-0.715879,0.18865,0.067743,0.043258,-0.005861, + 0.727149,-0.682839,0.070606,0.068527,0.044014,-0.006013, + 0.672256,-0.715879,0.18865,0.067743,0.043258,-0.005861, + 0.682839,-0.727149,0.070606,0.067757,0.043243,-0.006013, + 0.76859,-0.635833,0.070606,0.069247,0.044831,-0.006013, + 0.756678,-0.625979,0.18865,0.069232,0.044844,-0.005861, + 0.715879,-0.672256,0.18865,0.068512,0.044028,-0.005861, + 0.76859,-0.635833,0.070606,0.069247,0.044831,-0.006013, + 0.715879,-0.672256,0.18865,0.068512,0.044028,-0.005861, + 0.727149,-0.682839,0.070606,0.068527,0.044014,-0.006013, + 0.806998,-0.586318,0.070606,0.069915,0.045692,-0.006013, + 0.794491,-0.577231,0.18865,0.069899,0.045704,-0.005861, + 0.756678,-0.625979,0.18865,0.069232,0.044844,-0.005861, + 0.806998,-0.586318,0.070606,0.069915,0.045692,-0.006013, + 0.756678,-0.625979,0.18865,0.069232,0.044844,-0.005861, + 0.76859,-0.635833,0.070606,0.069247,0.044831,-0.006013, + 0.842221,-0.53449,0.070606,0.070528,0.046593,-0.006013, + 0.829167,-0.526206,0.18865,0.070511,0.046604,-0.005861, + 0.794491,-0.577231,0.18865,0.069899,0.045704,-0.005861, + 0.842221,-0.53449,0.070606,0.070528,0.046593,-0.006013, + 0.794491,-0.577231,0.18865,0.069899,0.045704,-0.005861, + 0.806998,-0.586318,0.070606,0.069915,0.045692,-0.006013, + 0.87412,-0.480551,0.070606,0.071082,0.047531,-0.006013, + 0.860572,-0.473103,0.18865,0.071065,0.04754,-0.005861, + 0.829167,-0.526206,0.18865,0.070511,0.046604,-0.005861, + 0.87412,-0.480551,0.070606,0.071082,0.047531,-0.006013, + 0.829167,-0.526206,0.18865,0.070511,0.046604,-0.005861, + 0.842221,-0.53449,0.070606,0.070528,0.046593,-0.006013, + 0.902569,-0.424717,0.070606,0.071577,0.048502,-0.006013, + 0.88858,-0.418134,0.18865,0.071559,0.04851,-0.005861, + 0.860572,-0.473103,0.18865,0.071065,0.04754,-0.005861, + 0.902569,-0.424717,0.070606,0.071577,0.048502,-0.006013, + 0.860572,-0.473103,0.18865,0.071065,0.04754,-0.005861, + 0.87412,-0.480551,0.070606,0.071082,0.047531,-0.006013, + 0.927456,-0.367206,0.070606,0.07201,0.049501,-0.006013, + 0.913082,-0.361515,0.18865,0.071991,0.049509,-0.005861, + 0.88858,-0.418134,0.18865,0.071559,0.04851,-0.005861, + 0.927456,-0.367206,0.070606,0.07201,0.049501,-0.006013, + 0.88858,-0.418134,0.18865,0.071559,0.04851,-0.005861, + 0.902569,-0.424717,0.070606,0.071577,0.048502,-0.006013, + 0.948683,-0.308246,0.070606,0.072379,0.050526,-0.006013, + 0.93398,-0.303468,0.18865,0.07236,0.050532,-0.005861, + 0.913082,-0.361515,0.18865,0.071991,0.049509,-0.005861, + 0.948683,-0.308246,0.070606,0.072379,0.050526,-0.006013, + 0.913082,-0.361515,0.18865,0.071991,0.049509,-0.005861, + 0.927456,-0.367206,0.070606,0.07201,0.049501,-0.006013, + 0.966166,-0.248069,0.070606,0.072682,0.051572,-0.006013, + 0.951192,-0.244224,0.18865,0.072663,0.051578,-0.005861, + 0.93398,-0.303468,0.18865,0.07236,0.050532,-0.005861, + 0.966166,-0.248069,0.070606,0.072682,0.051572,-0.006013, + 0.93398,-0.303468,0.18865,0.07236,0.050532,-0.005861, + 0.948683,-0.308246,0.070606,0.072379,0.050526,-0.006013, + 0.979836,-0.186914,0.070606,0.07292,0.052636,-0.006013, + 0.96465,-0.184017,0.18865,0.072901,0.05264,-0.005861, + 0.951192,-0.244224,0.18865,0.072663,0.051578,-0.005861, + 0.979836,-0.186914,0.070606,0.07292,0.052636,-0.006013, + 0.951192,-0.244224,0.18865,0.072663,0.051578,-0.005861, + 0.966166,-0.248069,0.070606,0.072682,0.051572,-0.006013, + 0.989639,-0.12502,0.070606,0.073091,0.053712,-0.006013, + 0.974301,-0.123083,0.18865,0.073071,0.053714,-0.005861, + 0.96465,-0.184017,0.18865,0.072901,0.05264,-0.005861, + 0.989639,-0.12502,0.070606,0.073091,0.053712,-0.006013, + 0.96465,-0.184017,0.18865,0.072901,0.05264,-0.005861, + 0.979836,-0.186914,0.070606,0.07292,0.052636,-0.006013, + 0.995536,-0.062634,0.070606,0.073193,0.054796,-0.006013, + 0.980106,-0.061663,0.18865,0.073173,0.054798,-0.005861, + 0.974301,-0.123083,0.18865,0.073071,0.053714,-0.005861, + 0.995536,-0.062634,0.070606,0.073193,0.054796,-0.006013, + 0.974301,-0.123083,0.18865,0.073071,0.053714,-0.005861, + 0.989639,-0.12502,0.070606,0.073091,0.053712,-0.006013, + 0.997504,0,0.070606,0.073227,0.055885,-0.006013, + 0.982044,0,0.18865,0.073207,0.055885,-0.005861, + 0.980106,-0.061663,0.18865,0.073173,0.054798,-0.005861, + 0.997504,0,0.070606,0.073227,0.055885,-0.006013, + 0.980106,-0.061663,0.18865,0.073173,0.054798,-0.005861, + 0.995536,-0.062634,0.070606,0.073193,0.054796,-0.006013, + 0.995536,0.062634,0.070606,0.073193,0.056974,-0.006013, + 0.980106,0.061663,0.18865,0.073173,0.056973,-0.005861, + 0.982044,0,0.18865,0.073207,0.055885,-0.005861, + 0.995536,0.062634,0.070606,0.073193,0.056974,-0.006013, + 0.982044,0,0.18865,0.073207,0.055885,-0.005861, + 0.997504,0,0.070606,0.073227,0.055885,-0.006013, + 0.989639,0.12502,0.070606,0.073091,0.058059,-0.006013, + 0.974301,0.123083,0.18865,0.073071,0.058056,-0.005861, + 0.980106,0.061663,0.18865,0.073173,0.056973,-0.005861, + 0.989639,0.12502,0.070606,0.073091,0.058059,-0.006013, + 0.980106,0.061663,0.18865,0.073173,0.056973,-0.005861, + 0.995536,0.062634,0.070606,0.073193,0.056974,-0.006013, + 0.979836,0.186914,0.070606,0.07292,0.059135,-0.006013, + 0.96465,0.184017,0.18865,0.072901,0.059131,-0.005861, + 0.974301,0.123083,0.18865,0.073071,0.058056,-0.005861, + 0.979836,0.186914,0.070606,0.07292,0.059135,-0.006013, + 0.974301,0.123083,0.18865,0.073071,0.058056,-0.005861, + 0.989639,0.12502,0.070606,0.073091,0.058059,-0.006013, + 0.966166,0.248069,0.070606,0.072682,0.060198,-0.006013, + 0.951192,0.244224,0.18865,0.072663,0.060193,-0.005861, + 0.96465,0.184017,0.18865,0.072901,0.059131,-0.005861, + 0.966166,0.248069,0.070606,0.072682,0.060198,-0.006013, + 0.96465,0.184017,0.18865,0.072901,0.059131,-0.005861, + 0.979836,0.186914,0.070606,0.07292,0.059135,-0.006013, + 0.948683,0.308246,0.070606,0.072379,0.061244,-0.006013, + 0.93398,0.303468,0.18865,0.07236,0.061238,-0.005861, + 0.951192,0.244224,0.18865,0.072663,0.060193,-0.005861, + 0.948683,0.308246,0.070606,0.072379,0.061244,-0.006013, + 0.951192,0.244224,0.18865,0.072663,0.060193,-0.005861, + 0.966166,0.248069,0.070606,0.072682,0.060198,-0.006013, + 0.927456,0.367206,0.070606,0.07201,0.062269,-0.006013, + 0.913082,0.361515,0.18865,0.071991,0.062262,-0.005861, + 0.93398,0.303468,0.18865,0.07236,0.061238,-0.005861, + 0.927456,0.367206,0.070606,0.07201,0.062269,-0.006013, + 0.93398,0.303468,0.18865,0.07236,0.061238,-0.005861, + 0.948683,0.308246,0.070606,0.072379,0.061244,-0.006013, + 0.902569,0.424717,0.070606,0.071577,0.063269,-0.006013, + 0.88858,0.418134,0.18865,0.071559,0.063261,-0.005861, + 0.913082,0.361515,0.18865,0.071991,0.062262,-0.005861, + 0.902569,0.424717,0.070606,0.071577,0.063269,-0.006013, + 0.913082,0.361515,0.18865,0.071991,0.062262,-0.005861, + 0.927456,0.367206,0.070606,0.07201,0.062269,-0.006013, + 0.87412,0.480551,0.070606,0.071082,0.06424,-0.006013, + 0.860572,0.473103,0.18865,0.071065,0.06423,-0.005861, + 0.88858,0.418134,0.18865,0.071559,0.063261,-0.005861, + 0.87412,0.480551,0.070606,0.071082,0.06424,-0.006013, + 0.88858,0.418134,0.18865,0.071559,0.063261,-0.005861, + 0.902569,0.424717,0.070606,0.071577,0.063269,-0.006013, + 0.842221,0.53449,0.070606,0.070528,0.065178,-0.006013, + 0.829167,0.526206,0.18865,0.070511,0.065167,-0.005861, + 0.860572,0.473103,0.18865,0.071065,0.06423,-0.005861, + 0.842221,0.53449,0.070606,0.070528,0.065178,-0.006013, + 0.860572,0.473103,0.18865,0.071065,0.06423,-0.005861, + 0.87412,0.480551,0.070606,0.071082,0.06424,-0.006013, + 0.806998,0.586318,0.070606,0.069915,0.066079,-0.006013, + 0.794491,0.577231,0.18865,0.069899,0.066067,-0.005861, + 0.829167,0.526206,0.18865,0.070511,0.065167,-0.005861, + 0.806998,0.586318,0.070606,0.069915,0.066079,-0.006013, + 0.829167,0.526206,0.18865,0.070511,0.065167,-0.005861, + 0.842221,0.53449,0.070606,0.070528,0.065178,-0.006013, + 0.76859,0.635833,0.070606,0.069247,0.06694,-0.006013, + 0.756678,0.625979,0.18865,0.069232,0.066927,-0.005861, + 0.794491,0.577231,0.18865,0.069899,0.066067,-0.005861, + 0.76859,0.635833,0.070606,0.069247,0.06694,-0.006013, + 0.794491,0.577231,0.18865,0.069899,0.066067,-0.005861, + 0.806998,0.586318,0.070606,0.069915,0.066079,-0.006013, + 0.727149,0.682839,0.070606,0.068527,0.067757,-0.006013, + 0.715879,0.672256,0.18865,0.068512,0.067743,-0.005861, + 0.756678,0.625979,0.18865,0.069232,0.066927,-0.005861, + 0.727149,0.682839,0.070606,0.068527,0.067757,-0.006013, + 0.756678,0.625979,0.18865,0.069232,0.066927,-0.005861, + 0.76859,0.635833,0.070606,0.069247,0.06694,-0.006013, + 0.682839,0.727149,0.070606,0.067757,0.068527,-0.006013, + 0.672256,0.715879,0.18865,0.067743,0.068512,-0.005861, + 0.715879,0.672256,0.18865,0.068512,0.067743,-0.005861, + 0.682839,0.727149,0.070606,0.067757,0.068527,-0.006013, + 0.715879,0.672256,0.18865,0.068512,0.067743,-0.005861, + 0.727149,0.682839,0.070606,0.068527,0.067757,-0.006013, + 0.635833,0.76859,0.070606,0.06694,0.069247,-0.006013, + 0.625979,0.756678,0.18865,0.066927,0.069232,-0.005861, + 0.672256,0.715879,0.18865,0.067743,0.068512,-0.005861, + 0.635833,0.76859,0.070606,0.06694,0.069247,-0.006013, + 0.672256,0.715879,0.18865,0.067743,0.068512,-0.005861, + 0.682839,0.727149,0.070606,0.067757,0.068527,-0.006013, + 0.586318,0.806998,0.070606,0.066079,0.069915,-0.006013, + 0.577231,0.794491,0.18865,0.066067,0.069899,-0.005861, + 0.625979,0.756678,0.18865,0.066927,0.069232,-0.005861, + 0.586318,0.806998,0.070606,0.066079,0.069915,-0.006013, + 0.625979,0.756678,0.18865,0.066927,0.069232,-0.005861, + 0.635833,0.76859,0.070606,0.06694,0.069247,-0.006013, + 0.53449,0.842221,0.070606,0.065178,0.070528,-0.006013, + 0.526206,0.829167,0.18865,0.065167,0.070511,-0.005861, + 0.577231,0.794491,0.18865,0.066067,0.069899,-0.005861, + 0.53449,0.842221,0.070606,0.065178,0.070528,-0.006013, + 0.577231,0.794491,0.18865,0.066067,0.069899,-0.005861, + 0.586318,0.806998,0.070606,0.066079,0.069915,-0.006013, + 0.480551,0.87412,0.070606,0.06424,0.071082,-0.006013, + 0.473103,0.860572,0.18865,0.06423,0.071065,-0.005861, + 0.526206,0.829167,0.18865,0.065167,0.070511,-0.005861, + 0.480551,0.87412,0.070606,0.06424,0.071082,-0.006013, + 0.526206,0.829167,0.18865,0.065167,0.070511,-0.005861, + 0.53449,0.842221,0.070606,0.065178,0.070528,-0.006013, + 0.424717,0.902569,0.070606,0.063269,0.071577,-0.006013, + 0.418134,0.88858,0.18865,0.063261,0.071559,-0.005861, + 0.473103,0.860572,0.18865,0.06423,0.071065,-0.005861, + 0.424717,0.902569,0.070606,0.063269,0.071577,-0.006013, + 0.473103,0.860572,0.18865,0.06423,0.071065,-0.005861, + 0.480551,0.87412,0.070606,0.06424,0.071082,-0.006013, + 0.367206,0.927456,0.070606,0.062269,0.07201,-0.006013, + 0.361515,0.913082,0.18865,0.062262,0.071991,-0.005861, + 0.418134,0.88858,0.18865,0.063261,0.071559,-0.005861, + 0.367206,0.927456,0.070606,0.062269,0.07201,-0.006013, + 0.418134,0.88858,0.18865,0.063261,0.071559,-0.005861, + 0.424717,0.902569,0.070606,0.063269,0.071577,-0.006013, + 0.308246,0.948683,0.070606,0.061244,0.072379,-0.006013, + 0.303468,0.93398,0.18865,0.061238,0.07236,-0.005861, + 0.361515,0.913082,0.18865,0.062262,0.071991,-0.005861, + 0.308246,0.948683,0.070606,0.061244,0.072379,-0.006013, + 0.361515,0.913082,0.18865,0.062262,0.071991,-0.005861, + 0.367206,0.927456,0.070606,0.062269,0.07201,-0.006013, + 0.248069,0.966166,0.070606,0.060198,0.072682,-0.006013, + 0.244224,0.951192,0.18865,0.060193,0.072663,-0.005861, + 0.303468,0.93398,0.18865,0.061238,0.07236,-0.005861, + 0.248069,0.966166,0.070606,0.060198,0.072682,-0.006013, + 0.303468,0.93398,0.18865,0.061238,0.07236,-0.005861, + 0.308246,0.948683,0.070606,0.061244,0.072379,-0.006013, + 0.186914,0.979836,0.070606,0.059135,0.07292,-0.006013, + 0.184017,0.96465,0.18865,0.059131,0.072901,-0.005861, + 0.244224,0.951192,0.18865,0.060193,0.072663,-0.005861, + 0.186914,0.979836,0.070606,0.059135,0.07292,-0.006013, + 0.244224,0.951192,0.18865,0.060193,0.072663,-0.005861, + 0.248069,0.966166,0.070606,0.060198,0.072682,-0.006013, + 0.12502,0.989639,0.070606,0.058059,0.073091,-0.006013, + 0.123083,0.974301,0.18865,0.058056,0.073071,-0.005861, + 0.184017,0.96465,0.18865,0.059131,0.072901,-0.005861, + 0.12502,0.989639,0.070606,0.058059,0.073091,-0.006013, + 0.184017,0.96465,0.18865,0.059131,0.072901,-0.005861, + 0.186914,0.979836,0.070606,0.059135,0.07292,-0.006013, + 0.062634,0.995536,0.070606,0.056974,0.073193,-0.006013, + 0.061663,0.980106,0.18865,0.056973,0.073173,-0.005861, + 0.123083,0.974301,0.18865,0.058056,0.073071,-0.005861, + 0.062634,0.995536,0.070606,0.056974,0.073193,-0.006013, + 0.123083,0.974301,0.18865,0.058056,0.073071,-0.005861, + 0.12502,0.989639,0.070606,0.058059,0.073091,-0.006013, + 0,0.997504,0.070606,0.055885,0.073227,-0.006013, + 0,0.982044,0.18865,0.055885,0.073207,-0.005861, + 0.061663,0.980106,0.18865,0.056973,0.073173,-0.005861, + 0,0.997504,0.070606,0.055885,0.073227,-0.006013, + 0.061663,0.980106,0.18865,0.056973,0.073173,-0.005861, + 0.062634,0.995536,0.070606,0.056974,0.073193,-0.006013, + -0.062634,0.995536,0.070606,0.054796,0.073193,-0.006013, + -0.061663,0.980106,0.18865,0.054798,0.073173,-0.005861, + 0,0.982044,0.18865,0.055885,0.073207,-0.005861, + -0.062634,0.995536,0.070606,0.054796,0.073193,-0.006013, + 0,0.982044,0.18865,0.055885,0.073207,-0.005861, + 0,0.997504,0.070606,0.055885,0.073227,-0.006013, + -0.12502,0.989639,0.070606,0.053712,0.073091,-0.006013, + -0.123083,0.974301,0.18865,0.053714,0.073071,-0.005861, + -0.061663,0.980106,0.18865,0.054798,0.073173,-0.005861, + -0.12502,0.989639,0.070606,0.053712,0.073091,-0.006013, + -0.061663,0.980106,0.18865,0.054798,0.073173,-0.005861, + -0.062634,0.995536,0.070606,0.054796,0.073193,-0.006013, + -0.186914,0.979836,0.070606,0.052636,0.07292,-0.006013, + -0.184017,0.96465,0.18865,0.05264,0.072901,-0.005861, + -0.123083,0.974301,0.18865,0.053714,0.073071,-0.005861, + -0.186914,0.979836,0.070606,0.052636,0.07292,-0.006013, + -0.123083,0.974301,0.18865,0.053714,0.073071,-0.005861, + -0.12502,0.989639,0.070606,0.053712,0.073091,-0.006013, + -0.248069,0.966166,0.070606,0.051572,0.072682,-0.006013, + -0.244224,0.951192,0.18865,0.051578,0.072663,-0.005861, + -0.184017,0.96465,0.18865,0.05264,0.072901,-0.005861, + -0.248069,0.966166,0.070606,0.051572,0.072682,-0.006013, + -0.184017,0.96465,0.18865,0.05264,0.072901,-0.005861, + -0.186914,0.979836,0.070606,0.052636,0.07292,-0.006013, + -0.308246,0.948683,0.070606,0.050526,0.072379,-0.006013, + -0.303468,0.93398,0.18865,0.050532,0.07236,-0.005861, + -0.244224,0.951192,0.18865,0.051578,0.072663,-0.005861, + -0.308246,0.948683,0.070606,0.050526,0.072379,-0.006013, + -0.244224,0.951192,0.18865,0.051578,0.072663,-0.005861, + -0.248069,0.966166,0.070606,0.051572,0.072682,-0.006013, + -0.367206,0.927456,0.070606,0.049501,0.07201,-0.006013, + -0.361515,0.913082,0.18865,0.049509,0.071991,-0.005861, + -0.303468,0.93398,0.18865,0.050532,0.07236,-0.005861, + -0.367206,0.927456,0.070606,0.049501,0.07201,-0.006013, + -0.303468,0.93398,0.18865,0.050532,0.07236,-0.005861, + -0.308246,0.948683,0.070606,0.050526,0.072379,-0.006013, + -0.424717,0.902569,0.070606,0.048502,0.071577,-0.006013, + -0.418134,0.88858,0.18865,0.04851,0.071559,-0.005861, + -0.361515,0.913082,0.18865,0.049509,0.071991,-0.005861, + -0.424717,0.902569,0.070606,0.048502,0.071577,-0.006013, + -0.361515,0.913082,0.18865,0.049509,0.071991,-0.005861, + -0.367206,0.927456,0.070606,0.049501,0.07201,-0.006013, + -0.480551,0.87412,0.070606,0.047531,0.071082,-0.006013, + -0.473103,0.860572,0.18865,0.04754,0.071065,-0.005861, + -0.418134,0.88858,0.18865,0.04851,0.071559,-0.005861, + -0.480551,0.87412,0.070606,0.047531,0.071082,-0.006013, + -0.418134,0.88858,0.18865,0.04851,0.071559,-0.005861, + -0.424717,0.902569,0.070606,0.048502,0.071577,-0.006013, + -0.53449,0.842221,0.070606,0.046593,0.070528,-0.006013, + -0.526206,0.829167,0.18865,0.046604,0.070511,-0.005861, + -0.473103,0.860572,0.18865,0.04754,0.071065,-0.005861, + -0.53449,0.842221,0.070606,0.046593,0.070528,-0.006013, + -0.473103,0.860572,0.18865,0.04754,0.071065,-0.005861, + -0.480551,0.87412,0.070606,0.047531,0.071082,-0.006013, + -0.586318,0.806998,0.070606,0.045692,0.069915,-0.006013, + -0.577231,0.794491,0.18865,0.045704,0.069899,-0.005861, + -0.526206,0.829167,0.18865,0.046604,0.070511,-0.005861, + -0.586318,0.806998,0.070606,0.045692,0.069915,-0.006013, + -0.526206,0.829167,0.18865,0.046604,0.070511,-0.005861, + -0.53449,0.842221,0.070606,0.046593,0.070528,-0.006013, + -0.635833,0.76859,0.070606,0.044831,0.069247,-0.006013, + -0.625979,0.756678,0.18865,0.044844,0.069232,-0.005861, + -0.577231,0.794491,0.18865,0.045704,0.069899,-0.005861, + -0.635833,0.76859,0.070606,0.044831,0.069247,-0.006013, + -0.577231,0.794491,0.18865,0.045704,0.069899,-0.005861, + -0.586318,0.806998,0.070606,0.045692,0.069915,-0.006013, + -0.682839,0.727149,0.070606,0.044014,0.068527,-0.006013, + -0.672256,0.715879,0.18865,0.044028,0.068512,-0.005861, + -0.625979,0.756678,0.18865,0.044844,0.069232,-0.005861, + -0.682839,0.727149,0.070606,0.044014,0.068527,-0.006013, + -0.625979,0.756678,0.18865,0.044844,0.069232,-0.005861, + -0.635833,0.76859,0.070606,0.044831,0.069247,-0.006013, + -0.727149,0.682839,0.070606,0.043243,0.067757,-0.006013, + -0.715879,0.672256,0.18865,0.043258,0.067743,-0.005861, + -0.672256,0.715879,0.18865,0.044028,0.068512,-0.005861, + -0.727149,0.682839,0.070606,0.043243,0.067757,-0.006013, + -0.672256,0.715879,0.18865,0.044028,0.068512,-0.005861, + -0.682839,0.727149,0.070606,0.044014,0.068527,-0.006013, + -0.76859,0.635833,0.070606,0.042523,0.06694,-0.006013, + -0.756678,0.625979,0.18865,0.042538,0.066927,-0.005861, + -0.715879,0.672256,0.18865,0.043258,0.067743,-0.005861, + -0.76859,0.635833,0.070606,0.042523,0.06694,-0.006013, + -0.715879,0.672256,0.18865,0.043258,0.067743,-0.005861, + -0.727149,0.682839,0.070606,0.043243,0.067757,-0.006013, + -0.806998,0.586318,0.070606,0.041855,0.066079,-0.006013, + -0.794491,0.577231,0.18865,0.041871,0.066067,-0.005861, + -0.756678,0.625979,0.18865,0.042538,0.066927,-0.005861, + -0.806998,0.586318,0.070606,0.041855,0.066079,-0.006013, + -0.756678,0.625979,0.18865,0.042538,0.066927,-0.005861, + -0.76859,0.635833,0.070606,0.042523,0.06694,-0.006013, + -0.842221,0.53449,0.070606,0.041243,0.065178,-0.006013, + -0.829167,0.526206,0.18865,0.04126,0.065167,-0.005861, + -0.794491,0.577231,0.18865,0.041871,0.066067,-0.005861, + -0.842221,0.53449,0.070606,0.041243,0.065178,-0.006013, + -0.794491,0.577231,0.18865,0.041871,0.066067,-0.005861, + -0.806998,0.586318,0.070606,0.041855,0.066079,-0.006013, + -0.87412,0.480551,0.070606,0.040688,0.06424,-0.006013, + -0.860572,0.473103,0.18865,0.040706,0.06423,-0.005861, + -0.829167,0.526206,0.18865,0.04126,0.065167,-0.005861, + -0.87412,0.480551,0.070606,0.040688,0.06424,-0.006013, + -0.829167,0.526206,0.18865,0.04126,0.065167,-0.005861, + -0.842221,0.53449,0.070606,0.041243,0.065178,-0.006013, + -0.902569,0.424717,0.070606,0.040194,0.063269,-0.006013, + -0.88858,0.418134,0.18865,0.040212,0.063261,-0.005861, + -0.860572,0.473103,0.18865,0.040706,0.06423,-0.005861, + -0.902569,0.424717,0.070606,0.040194,0.063269,-0.006013, + -0.860572,0.473103,0.18865,0.040706,0.06423,-0.005861, + -0.87412,0.480551,0.070606,0.040688,0.06424,-0.006013, + -0.927456,0.367206,0.070606,0.039761,0.062269,-0.006013, + -0.913082,0.361515,0.18865,0.03978,0.062262,-0.005861, + -0.88858,0.418134,0.18865,0.040212,0.063261,-0.005861, + -0.927456,0.367206,0.070606,0.039761,0.062269,-0.006013, + -0.88858,0.418134,0.18865,0.040212,0.063261,-0.005861, + -0.902569,0.424717,0.070606,0.040194,0.063269,-0.006013, + -0.948683,0.308246,0.070606,0.039392,0.061244,-0.006013, + -0.93398,0.303468,0.18865,0.039411,0.061238,-0.005861, + -0.913082,0.361515,0.18865,0.03978,0.062262,-0.005861, + -0.948683,0.308246,0.070606,0.039392,0.061244,-0.006013, + -0.913082,0.361515,0.18865,0.03978,0.062262,-0.005861, + -0.927456,0.367206,0.070606,0.039761,0.062269,-0.006013, + -0.966166,0.248069,0.070606,0.039088,0.060198,-0.006013, + -0.951192,0.244224,0.18865,0.039107,0.060193,-0.005861, + -0.93398,0.303468,0.18865,0.039411,0.061238,-0.005861, + -0.966166,0.248069,0.070606,0.039088,0.060198,-0.006013, + -0.93398,0.303468,0.18865,0.039411,0.061238,-0.005861, + -0.948683,0.308246,0.070606,0.039392,0.061244,-0.006013, + -0.979836,0.186914,0.070606,0.03885,0.059135,-0.006013, + -0.96465,0.184017,0.18865,0.03887,0.059131,-0.005861, + -0.951192,0.244224,0.18865,0.039107,0.060193,-0.005861, + -0.979836,0.186914,0.070606,0.03885,0.059135,-0.006013, + -0.951192,0.244224,0.18865,0.039107,0.060193,-0.005861, + -0.966166,0.248069,0.070606,0.039088,0.060198,-0.006013, + -0.989639,0.12502,0.070606,0.03868,0.058059,-0.006013, + -0.974301,0.123083,0.18865,0.0387,0.058056,-0.005861, + -0.96465,0.184017,0.18865,0.03887,0.059131,-0.005861, + -0.989639,0.12502,0.070606,0.03868,0.058059,-0.006013, + -0.96465,0.184017,0.18865,0.03887,0.059131,-0.005861, + -0.979836,0.186914,0.070606,0.03885,0.059135,-0.006013, + -0.995536,0.062634,0.070606,0.038577,0.056974,-0.006013, + -0.980106,0.061663,0.18865,0.038597,0.056973,-0.005861, + -0.974301,0.123083,0.18865,0.0387,0.058056,-0.005861, + -0.995536,0.062634,0.070606,0.038577,0.056974,-0.006013, + -0.974301,0.123083,0.18865,0.0387,0.058056,-0.005861, + -0.989639,0.12502,0.070606,0.03868,0.058059,-0.006013, + -0.997504,0,0.070606,0.038543,0.055885,-0.006013, + -0.982044,0,0.18865,0.038563,0.055885,-0.005861, + -0.980106,0.061663,0.18865,0.038597,0.056973,-0.005861, + -0.997504,0,0.070606,0.038543,0.055885,-0.006013, + -0.980106,0.061663,0.18865,0.038597,0.056973,-0.005861, + -0.995536,0.062634,0.070606,0.038577,0.056974,-0.006013, + -0.995536,-0.062634,0.070606,0.038577,0.054796,-0.006013, + -0.980106,-0.061663,0.18865,0.038597,0.054798,-0.005861, + -0.982044,0,0.18865,0.038563,0.055885,-0.005861, + -0.995536,-0.062634,0.070606,0.038577,0.054796,-0.006013, + -0.982044,0,0.18865,0.038563,0.055885,-0.005861, + -0.997504,0,0.070606,0.038543,0.055885,-0.006013, + -0.989639,-0.12502,0.070606,0.03868,0.053712,-0.006013, + -0.974301,-0.123083,0.18865,0.0387,0.053714,-0.005861, + -0.980106,-0.061663,0.18865,0.038597,0.054798,-0.005861, + -0.989639,-0.12502,0.070606,0.03868,0.053712,-0.006013, + -0.980106,-0.061663,0.18865,0.038597,0.054798,-0.005861, + -0.995536,-0.062634,0.070606,0.038577,0.054796,-0.006013, + -0.979836,-0.186914,0.070606,0.03885,0.052636,-0.006013, + -0.96465,-0.184017,0.18865,0.03887,0.05264,-0.005861, + -0.974301,-0.123083,0.18865,0.0387,0.053714,-0.005861, + -0.979836,-0.186914,0.070606,0.03885,0.052636,-0.006013, + -0.974301,-0.123083,0.18865,0.0387,0.053714,-0.005861, + -0.989639,-0.12502,0.070606,0.03868,0.053712,-0.006013, + -0.966166,-0.248069,0.070606,0.039088,0.051572,-0.006013, + -0.951192,-0.244224,0.18865,0.039107,0.051578,-0.005861, + -0.96465,-0.184017,0.18865,0.03887,0.05264,-0.005861, + -0.966166,-0.248069,0.070606,0.039088,0.051572,-0.006013, + -0.96465,-0.184017,0.18865,0.03887,0.05264,-0.005861, + -0.979836,-0.186914,0.070606,0.03885,0.052636,-0.006013, + -0.948683,-0.308246,0.070606,0.039392,0.050526,-0.006013, + -0.93398,-0.303468,0.18865,0.039411,0.050532,-0.005861, + -0.951192,-0.244224,0.18865,0.039107,0.051578,-0.005861, + -0.948683,-0.308246,0.070606,0.039392,0.050526,-0.006013, + -0.951192,-0.244224,0.18865,0.039107,0.051578,-0.005861, + -0.966166,-0.248069,0.070606,0.039088,0.051572,-0.006013, + -0.93398,-0.303468,0.18865,0.039411,0.050532,-0.005861, + -0.906039,-0.29439,0.304021,0.039447,0.050544,-0.005713, + -0.922736,-0.236918,0.304021,0.039144,0.051587,-0.005713, + -0.93398,-0.303468,0.18865,0.039411,0.050532,-0.005861, + -0.922736,-0.236918,0.304021,0.039144,0.051587,-0.005713, + -0.951192,-0.244224,0.18865,0.039107,0.051578,-0.005861, + -0.913082,-0.361515,0.18865,0.03978,0.049509,-0.005861, + -0.885766,-0.3507,0.304021,0.039815,0.049522,-0.005713, + -0.906039,-0.29439,0.304021,0.039447,0.050544,-0.005713, + -0.913082,-0.361515,0.18865,0.03978,0.049509,-0.005861, + -0.906039,-0.29439,0.304021,0.039447,0.050544,-0.005713, + -0.93398,-0.303468,0.18865,0.039411,0.050532,-0.005861, + -0.88858,-0.418134,0.18865,0.040212,0.04851,-0.005861, + -0.861997,-0.405625,0.304021,0.040246,0.048526,-0.005713, + -0.885766,-0.3507,0.304021,0.039815,0.049522,-0.005713, + -0.88858,-0.418134,0.18865,0.040212,0.04851,-0.005861, + -0.885766,-0.3507,0.304021,0.039815,0.049522,-0.005713, + -0.913082,-0.361515,0.18865,0.03978,0.049509,-0.005861, + -0.860572,-0.473103,0.18865,0.040706,0.04754,-0.005861, + -0.834827,-0.45895,0.304021,0.040739,0.047559,-0.005713, + -0.861997,-0.405625,0.304021,0.040246,0.048526,-0.005713, + -0.860572,-0.473103,0.18865,0.040706,0.04754,-0.005861, + -0.861997,-0.405625,0.304021,0.040246,0.048526,-0.005713, + -0.88858,-0.418134,0.18865,0.040212,0.04851,-0.005861, + -0.829167,-0.526206,0.18865,0.04126,0.046604,-0.005861, + -0.804362,-0.510464,0.304021,0.041292,0.046624,-0.005713, + -0.834827,-0.45895,0.304021,0.040739,0.047559,-0.005713, + -0.829167,-0.526206,0.18865,0.04126,0.046604,-0.005861, + -0.834827,-0.45895,0.304021,0.040739,0.047559,-0.005713, + -0.860572,-0.473103,0.18865,0.040706,0.04754,-0.005861, + -0.794491,-0.577231,0.18865,0.041871,0.045704,-0.005861, + -0.770723,-0.559963,0.304021,0.041902,0.045726,-0.005713, + -0.804362,-0.510464,0.304021,0.041292,0.046624,-0.005713, + -0.794491,-0.577231,0.18865,0.041871,0.045704,-0.005861, + -0.804362,-0.510464,0.304021,0.041292,0.046624,-0.005713, + -0.829167,-0.526206,0.18865,0.04126,0.046604,-0.005861, + -0.756678,-0.625979,0.18865,0.042538,0.044844,-0.005861, + -0.734041,-0.607252,0.304021,0.042568,0.044868,-0.005713, + -0.770723,-0.559963,0.304021,0.041902,0.045726,-0.005713, + -0.756678,-0.625979,0.18865,0.042538,0.044844,-0.005861, + -0.770723,-0.559963,0.304021,0.041902,0.045726,-0.005713, + -0.794491,-0.577231,0.18865,0.041871,0.045704,-0.005861, + -0.715879,-0.672256,0.18865,0.043258,0.044028,-0.005861, + -0.694463,-0.652144,0.304021,0.043286,0.044053,-0.005713, + -0.734041,-0.607252,0.304021,0.042568,0.044868,-0.005713, + -0.715879,-0.672256,0.18865,0.043258,0.044028,-0.005861, + -0.734041,-0.607252,0.304021,0.042568,0.044868,-0.005713, + -0.756678,-0.625979,0.18865,0.042538,0.044844,-0.005861, + -0.672256,-0.715879,0.18865,0.044028,0.043258,-0.005861, + -0.652144,-0.694463,0.304021,0.044053,0.043286,-0.005713, + -0.694463,-0.652144,0.304021,0.043286,0.044053,-0.005713, + -0.672256,-0.715879,0.18865,0.044028,0.043258,-0.005861, + -0.694463,-0.652144,0.304021,0.043286,0.044053,-0.005713, + -0.715879,-0.672256,0.18865,0.043258,0.044028,-0.005861, + -0.625979,-0.756678,0.18865,0.044844,0.042538,-0.005861, + -0.607252,-0.734041,0.304021,0.044868,0.042568,-0.005713, + -0.652144,-0.694463,0.304021,0.044053,0.043286,-0.005713, + -0.625979,-0.756678,0.18865,0.044844,0.042538,-0.005861, + -0.652144,-0.694463,0.304021,0.044053,0.043286,-0.005713, + -0.672256,-0.715879,0.18865,0.044028,0.043258,-0.005861, + -0.577231,-0.794491,0.18865,0.045704,0.041871,-0.005861, + -0.559963,-0.770723,0.304021,0.045726,0.041902,-0.005713, + -0.607252,-0.734041,0.304021,0.044868,0.042568,-0.005713, + -0.577231,-0.794491,0.18865,0.045704,0.041871,-0.005861, + -0.607252,-0.734041,0.304021,0.044868,0.042568,-0.005713, + -0.625979,-0.756678,0.18865,0.044844,0.042538,-0.005861, + -0.526206,-0.829167,0.18865,0.046604,0.04126,-0.005861, + -0.510464,-0.804362,0.304021,0.046624,0.041292,-0.005713, + -0.559963,-0.770723,0.304021,0.045726,0.041902,-0.005713, + -0.526206,-0.829167,0.18865,0.046604,0.04126,-0.005861, + -0.559963,-0.770723,0.304021,0.045726,0.041902,-0.005713, + -0.577231,-0.794491,0.18865,0.045704,0.041871,-0.005861, + -0.473103,-0.860572,0.18865,0.04754,0.040706,-0.005861, + -0.45895,-0.834827,0.304021,0.047559,0.040739,-0.005713, + -0.510464,-0.804362,0.304021,0.046624,0.041292,-0.005713, + -0.473103,-0.860572,0.18865,0.04754,0.040706,-0.005861, + -0.510464,-0.804362,0.304021,0.046624,0.041292,-0.005713, + -0.526206,-0.829167,0.18865,0.046604,0.04126,-0.005861, + -0.418134,-0.88858,0.18865,0.04851,0.040212,-0.005861, + -0.405625,-0.861997,0.304021,0.048526,0.040246,-0.005713, + -0.45895,-0.834827,0.304021,0.047559,0.040739,-0.005713, + -0.418134,-0.88858,0.18865,0.04851,0.040212,-0.005861, + -0.45895,-0.834827,0.304021,0.047559,0.040739,-0.005713, + -0.473103,-0.860572,0.18865,0.04754,0.040706,-0.005861, + -0.361515,-0.913082,0.18865,0.049509,0.03978,-0.005861, + -0.3507,-0.885766,0.304021,0.049522,0.039815,-0.005713, + -0.405625,-0.861997,0.304021,0.048526,0.040246,-0.005713, + -0.361515,-0.913082,0.18865,0.049509,0.03978,-0.005861, + -0.405625,-0.861997,0.304021,0.048526,0.040246,-0.005713, + -0.418134,-0.88858,0.18865,0.04851,0.040212,-0.005861, + -0.303468,-0.93398,0.18865,0.050532,0.039411,-0.005861, + -0.29439,-0.906039,0.304021,0.050544,0.039447,-0.005713, + -0.3507,-0.885766,0.304021,0.049522,0.039815,-0.005713, + -0.303468,-0.93398,0.18865,0.050532,0.039411,-0.005861, + -0.3507,-0.885766,0.304021,0.049522,0.039815,-0.005713, + -0.361515,-0.913082,0.18865,0.049509,0.03978,-0.005861, + -0.244224,-0.951192,0.18865,0.051578,0.039107,-0.005861, + -0.236918,-0.922736,0.304021,0.051587,0.039144,-0.005713, + -0.29439,-0.906039,0.304021,0.050544,0.039447,-0.005713, + -0.244224,-0.951192,0.18865,0.051578,0.039107,-0.005861, + -0.29439,-0.906039,0.304021,0.050544,0.039447,-0.005713, + -0.303468,-0.93398,0.18865,0.050532,0.039411,-0.005861, + -0.184017,-0.96465,0.18865,0.05264,0.03887,-0.005861, + -0.178512,-0.935791,0.304021,0.052646,0.038907,-0.005713, + -0.236918,-0.922736,0.304021,0.051587,0.039144,-0.005713, + -0.184017,-0.96465,0.18865,0.05264,0.03887,-0.005861, + -0.236918,-0.922736,0.304021,0.051587,0.039144,-0.005713, + -0.244224,-0.951192,0.18865,0.051578,0.039107,-0.005861, + -0.123083,-0.974301,0.18865,0.053714,0.0387,-0.005861, + -0.119401,-0.945153,0.304021,0.053719,0.038737,-0.005713, + -0.178512,-0.935791,0.304021,0.052646,0.038907,-0.005713, + -0.123083,-0.974301,0.18865,0.053714,0.0387,-0.005861, + -0.178512,-0.935791,0.304021,0.052646,0.038907,-0.005713, + -0.184017,-0.96465,0.18865,0.05264,0.03887,-0.005861, + -0.061663,-0.980106,0.18865,0.054798,0.038597,-0.005861, + -0.059818,-0.950786,0.304021,0.0548,0.038635,-0.005713, + -0.119401,-0.945153,0.304021,0.053719,0.038737,-0.005713, + -0.061663,-0.980106,0.18865,0.054798,0.038597,-0.005861, + -0.119401,-0.945153,0.304021,0.053719,0.038737,-0.005713, + -0.123083,-0.974301,0.18865,0.053714,0.0387,-0.005861, + 0,-0.982044,0.18865,0.055885,0.038563,-0.005861, + 0,-0.952665,0.304021,0.055885,0.038601,-0.005713, + -0.059818,-0.950786,0.304021,0.0548,0.038635,-0.005713, + 0,-0.982044,0.18865,0.055885,0.038563,-0.005861, + -0.059818,-0.950786,0.304021,0.0548,0.038635,-0.005713, + -0.061663,-0.980106,0.18865,0.054798,0.038597,-0.005861, + 0.061663,-0.980106,0.18865,0.056973,0.038597,-0.005861, + 0.059818,-0.950786,0.304021,0.056971,0.038635,-0.005713, + 0,-0.952665,0.304021,0.055885,0.038601,-0.005713, + 0.061663,-0.980106,0.18865,0.056973,0.038597,-0.005861, + 0,-0.952665,0.304021,0.055885,0.038601,-0.005713, + 0,-0.982044,0.18865,0.055885,0.038563,-0.005861, + 0.123083,-0.974301,0.18865,0.058056,0.0387,-0.005861, + 0.119401,-0.945153,0.304021,0.058052,0.038737,-0.005713, + 0.059818,-0.950786,0.304021,0.056971,0.038635,-0.005713, + 0.123083,-0.974301,0.18865,0.058056,0.0387,-0.005861, + 0.059818,-0.950786,0.304021,0.056971,0.038635,-0.005713, + 0.061663,-0.980106,0.18865,0.056973,0.038597,-0.005861, + 0.184017,-0.96465,0.18865,0.059131,0.03887,-0.005861, + 0.178512,-0.935791,0.304021,0.059124,0.038907,-0.005713, + 0.119401,-0.945153,0.304021,0.058052,0.038737,-0.005713, + 0.184017,-0.96465,0.18865,0.059131,0.03887,-0.005861, + 0.119401,-0.945153,0.304021,0.058052,0.038737,-0.005713, + 0.123083,-0.974301,0.18865,0.058056,0.0387,-0.005861, + 0.244224,-0.951192,0.18865,0.060193,0.039107,-0.005861, + 0.236918,-0.922736,0.304021,0.060184,0.039144,-0.005713, + 0.178512,-0.935791,0.304021,0.059124,0.038907,-0.005713, + 0.244224,-0.951192,0.18865,0.060193,0.039107,-0.005861, + 0.178512,-0.935791,0.304021,0.059124,0.038907,-0.005713, + 0.184017,-0.96465,0.18865,0.059131,0.03887,-0.005861, + 0.303468,-0.93398,0.18865,0.061238,0.039411,-0.005861, + 0.29439,-0.906039,0.304021,0.061226,0.039447,-0.005713, + 0.236918,-0.922736,0.304021,0.060184,0.039144,-0.005713, + 0.303468,-0.93398,0.18865,0.061238,0.039411,-0.005861, + 0.236918,-0.922736,0.304021,0.060184,0.039144,-0.005713, + 0.244224,-0.951192,0.18865,0.060193,0.039107,-0.005861, + 0.361515,-0.913082,0.18865,0.062262,0.03978,-0.005861, + 0.3507,-0.885766,0.304021,0.062248,0.039815,-0.005713, + 0.29439,-0.906039,0.304021,0.061226,0.039447,-0.005713, + 0.361515,-0.913082,0.18865,0.062262,0.03978,-0.005861, + 0.29439,-0.906039,0.304021,0.061226,0.039447,-0.005713, + 0.303468,-0.93398,0.18865,0.061238,0.039411,-0.005861, + 0.418134,-0.88858,0.18865,0.063261,0.040212,-0.005861, + 0.405625,-0.861997,0.304021,0.063245,0.040246,-0.005713, + 0.3507,-0.885766,0.304021,0.062248,0.039815,-0.005713, + 0.418134,-0.88858,0.18865,0.063261,0.040212,-0.005861, + 0.3507,-0.885766,0.304021,0.062248,0.039815,-0.005713, + 0.361515,-0.913082,0.18865,0.062262,0.03978,-0.005861, + 0.473103,-0.860572,0.18865,0.06423,0.040706,-0.005861, + 0.45895,-0.834827,0.304021,0.064212,0.040739,-0.005713, + 0.405625,-0.861997,0.304021,0.063245,0.040246,-0.005713, + 0.473103,-0.860572,0.18865,0.06423,0.040706,-0.005861, + 0.405625,-0.861997,0.304021,0.063245,0.040246,-0.005713, + 0.418134,-0.88858,0.18865,0.063261,0.040212,-0.005861, + 0.526206,-0.829167,0.18865,0.065167,0.04126,-0.005861, + 0.510464,-0.804362,0.304021,0.065147,0.041292,-0.005713, + 0.45895,-0.834827,0.304021,0.064212,0.040739,-0.005713, + 0.526206,-0.829167,0.18865,0.065167,0.04126,-0.005861, + 0.45895,-0.834827,0.304021,0.064212,0.040739,-0.005713, + 0.473103,-0.860572,0.18865,0.06423,0.040706,-0.005861, + 0.577231,-0.794491,0.18865,0.066067,0.041871,-0.005861, + 0.559963,-0.770723,0.304021,0.066045,0.041902,-0.005713, + 0.510464,-0.804362,0.304021,0.065147,0.041292,-0.005713, + 0.577231,-0.794491,0.18865,0.066067,0.041871,-0.005861, + 0.510464,-0.804362,0.304021,0.065147,0.041292,-0.005713, + 0.526206,-0.829167,0.18865,0.065167,0.04126,-0.005861, + 0.625979,-0.756678,0.18865,0.066927,0.042538,-0.005861, + 0.607252,-0.734041,0.304021,0.066903,0.042568,-0.005713, + 0.559963,-0.770723,0.304021,0.066045,0.041902,-0.005713, + 0.625979,-0.756678,0.18865,0.066927,0.042538,-0.005861, + 0.559963,-0.770723,0.304021,0.066045,0.041902,-0.005713, + 0.577231,-0.794491,0.18865,0.066067,0.041871,-0.005861, + 0.672256,-0.715879,0.18865,0.067743,0.043258,-0.005861, + 0.652144,-0.694463,0.304021,0.067717,0.043286,-0.005713, + 0.607252,-0.734041,0.304021,0.066903,0.042568,-0.005713, + 0.672256,-0.715879,0.18865,0.067743,0.043258,-0.005861, + 0.607252,-0.734041,0.304021,0.066903,0.042568,-0.005713, + 0.625979,-0.756678,0.18865,0.066927,0.042538,-0.005861, + 0.715879,-0.672256,0.18865,0.068512,0.044028,-0.005861, + 0.694463,-0.652144,0.304021,0.068485,0.044053,-0.005713, + 0.652144,-0.694463,0.304021,0.067717,0.043286,-0.005713, + 0.715879,-0.672256,0.18865,0.068512,0.044028,-0.005861, + 0.652144,-0.694463,0.304021,0.067717,0.043286,-0.005713, + 0.672256,-0.715879,0.18865,0.067743,0.043258,-0.005861, + 0.756678,-0.625979,0.18865,0.069232,0.044844,-0.005861, + 0.734041,-0.607252,0.304021,0.069203,0.044868,-0.005713, + 0.694463,-0.652144,0.304021,0.068485,0.044053,-0.005713, + 0.756678,-0.625979,0.18865,0.069232,0.044844,-0.005861, + 0.694463,-0.652144,0.304021,0.068485,0.044053,-0.005713, + 0.715879,-0.672256,0.18865,0.068512,0.044028,-0.005861, + 0.794491,-0.577231,0.18865,0.069899,0.045704,-0.005861, + 0.770723,-0.559963,0.304021,0.069869,0.045726,-0.005713, + 0.734041,-0.607252,0.304021,0.069203,0.044868,-0.005713, + 0.794491,-0.577231,0.18865,0.069899,0.045704,-0.005861, + 0.734041,-0.607252,0.304021,0.069203,0.044868,-0.005713, + 0.756678,-0.625979,0.18865,0.069232,0.044844,-0.005861, + 0.829167,-0.526206,0.18865,0.070511,0.046604,-0.005861, + 0.804362,-0.510464,0.304021,0.070479,0.046624,-0.005713, + 0.770723,-0.559963,0.304021,0.069869,0.045726,-0.005713, + 0.829167,-0.526206,0.18865,0.070511,0.046604,-0.005861, + 0.770723,-0.559963,0.304021,0.069869,0.045726,-0.005713, + 0.794491,-0.577231,0.18865,0.069899,0.045704,-0.005861, + 0.860572,-0.473103,0.18865,0.071065,0.04754,-0.005861, + 0.834827,-0.45895,0.304021,0.071032,0.047559,-0.005713, + 0.804362,-0.510464,0.304021,0.070479,0.046624,-0.005713, + 0.860572,-0.473103,0.18865,0.071065,0.04754,-0.005861, + 0.804362,-0.510464,0.304021,0.070479,0.046624,-0.005713, + 0.829167,-0.526206,0.18865,0.070511,0.046604,-0.005861, + 0.88858,-0.418134,0.18865,0.071559,0.04851,-0.005861, + 0.861997,-0.405625,0.304021,0.071525,0.048526,-0.005713, + 0.834827,-0.45895,0.304021,0.071032,0.047559,-0.005713, + 0.88858,-0.418134,0.18865,0.071559,0.04851,-0.005861, + 0.834827,-0.45895,0.304021,0.071032,0.047559,-0.005713, + 0.860572,-0.473103,0.18865,0.071065,0.04754,-0.005861, + 0.913082,-0.361515,0.18865,0.071991,0.049509,-0.005861, + 0.885766,-0.3507,0.304021,0.071956,0.049522,-0.005713, + 0.861997,-0.405625,0.304021,0.071525,0.048526,-0.005713, + 0.913082,-0.361515,0.18865,0.071991,0.049509,-0.005861, + 0.861997,-0.405625,0.304021,0.071525,0.048526,-0.005713, + 0.88858,-0.418134,0.18865,0.071559,0.04851,-0.005861, + 0.93398,-0.303468,0.18865,0.07236,0.050532,-0.005861, + 0.906039,-0.29439,0.304021,0.072324,0.050544,-0.005713, + 0.885766,-0.3507,0.304021,0.071956,0.049522,-0.005713, + 0.93398,-0.303468,0.18865,0.07236,0.050532,-0.005861, + 0.885766,-0.3507,0.304021,0.071956,0.049522,-0.005713, + 0.913082,-0.361515,0.18865,0.071991,0.049509,-0.005861, + 0.951192,-0.244224,0.18865,0.072663,0.051578,-0.005861, + 0.922736,-0.236918,0.304021,0.072627,0.051587,-0.005713, + 0.906039,-0.29439,0.304021,0.072324,0.050544,-0.005713, + 0.951192,-0.244224,0.18865,0.072663,0.051578,-0.005861, + 0.906039,-0.29439,0.304021,0.072324,0.050544,-0.005713, + 0.93398,-0.303468,0.18865,0.07236,0.050532,-0.005861, + 0.96465,-0.184017,0.18865,0.072901,0.05264,-0.005861, + 0.935791,-0.178512,0.304021,0.072863,0.052646,-0.005713, + 0.922736,-0.236918,0.304021,0.072627,0.051587,-0.005713, + 0.96465,-0.184017,0.18865,0.072901,0.05264,-0.005861, + 0.922736,-0.236918,0.304021,0.072627,0.051587,-0.005713, + 0.951192,-0.244224,0.18865,0.072663,0.051578,-0.005861, + 0.974301,-0.123083,0.18865,0.073071,0.053714,-0.005861, + 0.945153,-0.119401,0.304021,0.073033,0.053719,-0.005713, + 0.935791,-0.178512,0.304021,0.072863,0.052646,-0.005713, + 0.974301,-0.123083,0.18865,0.073071,0.053714,-0.005861, + 0.935791,-0.178512,0.304021,0.072863,0.052646,-0.005713, + 0.96465,-0.184017,0.18865,0.072901,0.05264,-0.005861, + 0.980106,-0.061663,0.18865,0.073173,0.054798,-0.005861, + 0.950786,-0.059818,0.304021,0.073135,0.0548,-0.005713, + 0.945153,-0.119401,0.304021,0.073033,0.053719,-0.005713, + 0.980106,-0.061663,0.18865,0.073173,0.054798,-0.005861, + 0.945153,-0.119401,0.304021,0.073033,0.053719,-0.005713, + 0.974301,-0.123083,0.18865,0.073071,0.053714,-0.005861, + 0.982044,0,0.18865,0.073207,0.055885,-0.005861, + 0.952665,0,0.304021,0.073169,0.055885,-0.005713, + 0.950786,-0.059818,0.304021,0.073135,0.0548,-0.005713, + 0.982044,0,0.18865,0.073207,0.055885,-0.005861, + 0.950786,-0.059818,0.304021,0.073135,0.0548,-0.005713, + 0.980106,-0.061663,0.18865,0.073173,0.054798,-0.005861, + 0.980106,0.061663,0.18865,0.073173,0.056973,-0.005861, + 0.950786,0.059818,0.304021,0.073135,0.056971,-0.005713, + 0.952665,0,0.304021,0.073169,0.055885,-0.005713, + 0.980106,0.061663,0.18865,0.073173,0.056973,-0.005861, + 0.952665,0,0.304021,0.073169,0.055885,-0.005713, + 0.982044,0,0.18865,0.073207,0.055885,-0.005861, + 0.974301,0.123083,0.18865,0.073071,0.058056,-0.005861, + 0.945153,0.119401,0.304021,0.073033,0.058052,-0.005713, + 0.950786,0.059818,0.304021,0.073135,0.056971,-0.005713, + 0.974301,0.123083,0.18865,0.073071,0.058056,-0.005861, + 0.950786,0.059818,0.304021,0.073135,0.056971,-0.005713, + 0.980106,0.061663,0.18865,0.073173,0.056973,-0.005861, + 0.96465,0.184017,0.18865,0.072901,0.059131,-0.005861, + 0.935791,0.178512,0.304021,0.072863,0.059124,-0.005713, + 0.945153,0.119401,0.304021,0.073033,0.058052,-0.005713, + 0.96465,0.184017,0.18865,0.072901,0.059131,-0.005861, + 0.945153,0.119401,0.304021,0.073033,0.058052,-0.005713, + 0.974301,0.123083,0.18865,0.073071,0.058056,-0.005861, + 0.951192,0.244224,0.18865,0.072663,0.060193,-0.005861, + 0.922736,0.236918,0.304021,0.072627,0.060184,-0.005713, + 0.935791,0.178512,0.304021,0.072863,0.059124,-0.005713, + 0.951192,0.244224,0.18865,0.072663,0.060193,-0.005861, + 0.935791,0.178512,0.304021,0.072863,0.059124,-0.005713, + 0.96465,0.184017,0.18865,0.072901,0.059131,-0.005861, + 0.93398,0.303468,0.18865,0.07236,0.061238,-0.005861, + 0.906039,0.29439,0.304021,0.072324,0.061226,-0.005713, + 0.922736,0.236918,0.304021,0.072627,0.060184,-0.005713, + 0.93398,0.303468,0.18865,0.07236,0.061238,-0.005861, + 0.922736,0.236918,0.304021,0.072627,0.060184,-0.005713, + 0.951192,0.244224,0.18865,0.072663,0.060193,-0.005861, + 0.913082,0.361515,0.18865,0.071991,0.062262,-0.005861, + 0.885766,0.3507,0.304021,0.071956,0.062248,-0.005713, + 0.906039,0.29439,0.304021,0.072324,0.061226,-0.005713, + 0.913082,0.361515,0.18865,0.071991,0.062262,-0.005861, + 0.906039,0.29439,0.304021,0.072324,0.061226,-0.005713, + 0.93398,0.303468,0.18865,0.07236,0.061238,-0.005861, + 0.88858,0.418134,0.18865,0.071559,0.063261,-0.005861, + 0.861997,0.405625,0.304021,0.071525,0.063245,-0.005713, + 0.885766,0.3507,0.304021,0.071956,0.062248,-0.005713, + 0.88858,0.418134,0.18865,0.071559,0.063261,-0.005861, + 0.885766,0.3507,0.304021,0.071956,0.062248,-0.005713, + 0.913082,0.361515,0.18865,0.071991,0.062262,-0.005861, + 0.860572,0.473103,0.18865,0.071065,0.06423,-0.005861, + 0.834827,0.45895,0.304021,0.071032,0.064212,-0.005713, + 0.861997,0.405625,0.304021,0.071525,0.063245,-0.005713, + 0.860572,0.473103,0.18865,0.071065,0.06423,-0.005861, + 0.861997,0.405625,0.304021,0.071525,0.063245,-0.005713, + 0.88858,0.418134,0.18865,0.071559,0.063261,-0.005861, + 0.829167,0.526206,0.18865,0.070511,0.065167,-0.005861, + 0.804362,0.510464,0.304021,0.070479,0.065147,-0.005713, + 0.834827,0.45895,0.304021,0.071032,0.064212,-0.005713, + 0.829167,0.526206,0.18865,0.070511,0.065167,-0.005861, + 0.834827,0.45895,0.304021,0.071032,0.064212,-0.005713, + 0.860572,0.473103,0.18865,0.071065,0.06423,-0.005861, + 0.794491,0.577231,0.18865,0.069899,0.066067,-0.005861, + 0.770723,0.559963,0.304021,0.069869,0.066045,-0.005713, + 0.804362,0.510464,0.304021,0.070479,0.065147,-0.005713, + 0.794491,0.577231,0.18865,0.069899,0.066067,-0.005861, + 0.804362,0.510464,0.304021,0.070479,0.065147,-0.005713, + 0.829167,0.526206,0.18865,0.070511,0.065167,-0.005861, + 0.756678,0.625979,0.18865,0.069232,0.066927,-0.005861, + 0.734041,0.607252,0.304021,0.069203,0.066903,-0.005713, + 0.770723,0.559963,0.304021,0.069869,0.066045,-0.005713, + 0.756678,0.625979,0.18865,0.069232,0.066927,-0.005861, + 0.770723,0.559963,0.304021,0.069869,0.066045,-0.005713, + 0.794491,0.577231,0.18865,0.069899,0.066067,-0.005861, + 0.715879,0.672256,0.18865,0.068512,0.067743,-0.005861, + 0.694463,0.652144,0.304021,0.068485,0.067717,-0.005713, + 0.734041,0.607252,0.304021,0.069203,0.066903,-0.005713, + 0.715879,0.672256,0.18865,0.068512,0.067743,-0.005861, + 0.734041,0.607252,0.304021,0.069203,0.066903,-0.005713, + 0.756678,0.625979,0.18865,0.069232,0.066927,-0.005861, + 0.672256,0.715879,0.18865,0.067743,0.068512,-0.005861, + 0.652144,0.694463,0.304021,0.067717,0.068485,-0.005713, + 0.694463,0.652144,0.304021,0.068485,0.067717,-0.005713, + 0.672256,0.715879,0.18865,0.067743,0.068512,-0.005861, + 0.694463,0.652144,0.304021,0.068485,0.067717,-0.005713, + 0.715879,0.672256,0.18865,0.068512,0.067743,-0.005861, + 0.625979,0.756678,0.18865,0.066927,0.069232,-0.005861, + 0.607252,0.734041,0.304021,0.066903,0.069203,-0.005713, + 0.652144,0.694463,0.304021,0.067717,0.068485,-0.005713, + 0.625979,0.756678,0.18865,0.066927,0.069232,-0.005861, + 0.652144,0.694463,0.304021,0.067717,0.068485,-0.005713, + 0.672256,0.715879,0.18865,0.067743,0.068512,-0.005861, + 0.577231,0.794491,0.18865,0.066067,0.069899,-0.005861, + 0.559963,0.770723,0.304021,0.066045,0.069869,-0.005713, + 0.607252,0.734041,0.304021,0.066903,0.069203,-0.005713, + 0.577231,0.794491,0.18865,0.066067,0.069899,-0.005861, + 0.607252,0.734041,0.304021,0.066903,0.069203,-0.005713, + 0.625979,0.756678,0.18865,0.066927,0.069232,-0.005861, + 0.526206,0.829167,0.18865,0.065167,0.070511,-0.005861, + 0.510464,0.804362,0.304021,0.065147,0.070479,-0.005713, + 0.559963,0.770723,0.304021,0.066045,0.069869,-0.005713, + 0.526206,0.829167,0.18865,0.065167,0.070511,-0.005861, + 0.559963,0.770723,0.304021,0.066045,0.069869,-0.005713, + 0.577231,0.794491,0.18865,0.066067,0.069899,-0.005861, + 0.473103,0.860572,0.18865,0.06423,0.071065,-0.005861, + 0.45895,0.834827,0.304021,0.064212,0.071032,-0.005713, + 0.510464,0.804362,0.304021,0.065147,0.070479,-0.005713, + 0.473103,0.860572,0.18865,0.06423,0.071065,-0.005861, + 0.510464,0.804362,0.304021,0.065147,0.070479,-0.005713, + 0.526206,0.829167,0.18865,0.065167,0.070511,-0.005861, + 0.418134,0.88858,0.18865,0.063261,0.071559,-0.005861, + 0.405625,0.861997,0.304021,0.063245,0.071525,-0.005713, + 0.45895,0.834827,0.304021,0.064212,0.071032,-0.005713, + 0.418134,0.88858,0.18865,0.063261,0.071559,-0.005861, + 0.45895,0.834827,0.304021,0.064212,0.071032,-0.005713, + 0.473103,0.860572,0.18865,0.06423,0.071065,-0.005861, + 0.361515,0.913082,0.18865,0.062262,0.071991,-0.005861, + 0.3507,0.885766,0.304021,0.062248,0.071956,-0.005713, + 0.405625,0.861997,0.304021,0.063245,0.071525,-0.005713, + 0.361515,0.913082,0.18865,0.062262,0.071991,-0.005861, + 0.405625,0.861997,0.304021,0.063245,0.071525,-0.005713, + 0.418134,0.88858,0.18865,0.063261,0.071559,-0.005861, + 0.303468,0.93398,0.18865,0.061238,0.07236,-0.005861, + 0.29439,0.906039,0.304021,0.061226,0.072324,-0.005713, + 0.3507,0.885766,0.304021,0.062248,0.071956,-0.005713, + 0.303468,0.93398,0.18865,0.061238,0.07236,-0.005861, + 0.3507,0.885766,0.304021,0.062248,0.071956,-0.005713, + 0.361515,0.913082,0.18865,0.062262,0.071991,-0.005861, + 0.244224,0.951192,0.18865,0.060193,0.072663,-0.005861, + 0.236918,0.922736,0.304021,0.060184,0.072627,-0.005713, + 0.29439,0.906039,0.304021,0.061226,0.072324,-0.005713, + 0.244224,0.951192,0.18865,0.060193,0.072663,-0.005861, + 0.29439,0.906039,0.304021,0.061226,0.072324,-0.005713, + 0.303468,0.93398,0.18865,0.061238,0.07236,-0.005861, + 0.184017,0.96465,0.18865,0.059131,0.072901,-0.005861, + 0.178512,0.935791,0.304021,0.059124,0.072863,-0.005713, + 0.236918,0.922736,0.304021,0.060184,0.072627,-0.005713, + 0.184017,0.96465,0.18865,0.059131,0.072901,-0.005861, + 0.236918,0.922736,0.304021,0.060184,0.072627,-0.005713, + 0.244224,0.951192,0.18865,0.060193,0.072663,-0.005861, + 0.123083,0.974301,0.18865,0.058056,0.073071,-0.005861, + 0.119401,0.945153,0.304021,0.058052,0.073033,-0.005713, + 0.178512,0.935791,0.304021,0.059124,0.072863,-0.005713, + 0.123083,0.974301,0.18865,0.058056,0.073071,-0.005861, + 0.178512,0.935791,0.304021,0.059124,0.072863,-0.005713, + 0.184017,0.96465,0.18865,0.059131,0.072901,-0.005861, + 0.061663,0.980106,0.18865,0.056973,0.073173,-0.005861, + 0.059818,0.950786,0.304021,0.056971,0.073135,-0.005713, + 0.119401,0.945153,0.304021,0.058052,0.073033,-0.005713, + 0.061663,0.980106,0.18865,0.056973,0.073173,-0.005861, + 0.119401,0.945153,0.304021,0.058052,0.073033,-0.005713, + 0.123083,0.974301,0.18865,0.058056,0.073071,-0.005861, + 0,0.982044,0.18865,0.055885,0.073207,-0.005861, + 0,0.952665,0.304021,0.055885,0.073169,-0.005713, + 0.059818,0.950786,0.304021,0.056971,0.073135,-0.005713, + 0,0.982044,0.18865,0.055885,0.073207,-0.005861, + 0.059818,0.950786,0.304021,0.056971,0.073135,-0.005713, + 0.061663,0.980106,0.18865,0.056973,0.073173,-0.005861, + -0.061663,0.980106,0.18865,0.054798,0.073173,-0.005861, + -0.059818,0.950786,0.304021,0.0548,0.073135,-0.005713, + 0,0.952665,0.304021,0.055885,0.073169,-0.005713, + -0.061663,0.980106,0.18865,0.054798,0.073173,-0.005861, + 0,0.952665,0.304021,0.055885,0.073169,-0.005713, + 0,0.982044,0.18865,0.055885,0.073207,-0.005861, + -0.123083,0.974301,0.18865,0.053714,0.073071,-0.005861, + -0.119401,0.945153,0.304021,0.053719,0.073033,-0.005713, + -0.059818,0.950786,0.304021,0.0548,0.073135,-0.005713, + -0.123083,0.974301,0.18865,0.053714,0.073071,-0.005861, + -0.059818,0.950786,0.304021,0.0548,0.073135,-0.005713, + -0.061663,0.980106,0.18865,0.054798,0.073173,-0.005861, + -0.184017,0.96465,0.18865,0.05264,0.072901,-0.005861, + -0.178512,0.935791,0.304021,0.052646,0.072863,-0.005713, + -0.119401,0.945153,0.304021,0.053719,0.073033,-0.005713, + -0.184017,0.96465,0.18865,0.05264,0.072901,-0.005861, + -0.119401,0.945153,0.304021,0.053719,0.073033,-0.005713, + -0.123083,0.974301,0.18865,0.053714,0.073071,-0.005861, + -0.244224,0.951192,0.18865,0.051578,0.072663,-0.005861, + -0.236918,0.922736,0.304021,0.051587,0.072627,-0.005713, + -0.178512,0.935791,0.304021,0.052646,0.072863,-0.005713, + -0.244224,0.951192,0.18865,0.051578,0.072663,-0.005861, + -0.178512,0.935791,0.304021,0.052646,0.072863,-0.005713, + -0.184017,0.96465,0.18865,0.05264,0.072901,-0.005861, + -0.303468,0.93398,0.18865,0.050532,0.07236,-0.005861, + -0.29439,0.906039,0.304021,0.050544,0.072324,-0.005713, + -0.236918,0.922736,0.304021,0.051587,0.072627,-0.005713, + -0.303468,0.93398,0.18865,0.050532,0.07236,-0.005861, + -0.236918,0.922736,0.304021,0.051587,0.072627,-0.005713, + -0.244224,0.951192,0.18865,0.051578,0.072663,-0.005861, + -0.361515,0.913082,0.18865,0.049509,0.071991,-0.005861, + -0.3507,0.885766,0.304021,0.049522,0.071956,-0.005713, + -0.29439,0.906039,0.304021,0.050544,0.072324,-0.005713, + -0.361515,0.913082,0.18865,0.049509,0.071991,-0.005861, + -0.29439,0.906039,0.304021,0.050544,0.072324,-0.005713, + -0.303468,0.93398,0.18865,0.050532,0.07236,-0.005861, + -0.418134,0.88858,0.18865,0.04851,0.071559,-0.005861, + -0.405625,0.861997,0.304021,0.048526,0.071525,-0.005713, + -0.3507,0.885766,0.304021,0.049522,0.071956,-0.005713, + -0.418134,0.88858,0.18865,0.04851,0.071559,-0.005861, + -0.3507,0.885766,0.304021,0.049522,0.071956,-0.005713, + -0.361515,0.913082,0.18865,0.049509,0.071991,-0.005861, + -0.473103,0.860572,0.18865,0.04754,0.071065,-0.005861, + -0.45895,0.834827,0.304021,0.047559,0.071032,-0.005713, + -0.405625,0.861997,0.304021,0.048526,0.071525,-0.005713, + -0.473103,0.860572,0.18865,0.04754,0.071065,-0.005861, + -0.405625,0.861997,0.304021,0.048526,0.071525,-0.005713, + -0.418134,0.88858,0.18865,0.04851,0.071559,-0.005861, + -0.526206,0.829167,0.18865,0.046604,0.070511,-0.005861, + -0.510464,0.804362,0.304021,0.046624,0.070479,-0.005713, + -0.45895,0.834827,0.304021,0.047559,0.071032,-0.005713, + -0.526206,0.829167,0.18865,0.046604,0.070511,-0.005861, + -0.45895,0.834827,0.304021,0.047559,0.071032,-0.005713, + -0.473103,0.860572,0.18865,0.04754,0.071065,-0.005861, + -0.577231,0.794491,0.18865,0.045704,0.069899,-0.005861, + -0.559963,0.770723,0.304021,0.045726,0.069869,-0.005713, + -0.510464,0.804362,0.304021,0.046624,0.070479,-0.005713, + -0.577231,0.794491,0.18865,0.045704,0.069899,-0.005861, + -0.510464,0.804362,0.304021,0.046624,0.070479,-0.005713, + -0.526206,0.829167,0.18865,0.046604,0.070511,-0.005861, + -0.625979,0.756678,0.18865,0.044844,0.069232,-0.005861, + -0.607252,0.734041,0.304021,0.044868,0.069203,-0.005713, + -0.559963,0.770723,0.304021,0.045726,0.069869,-0.005713, + -0.625979,0.756678,0.18865,0.044844,0.069232,-0.005861, + -0.559963,0.770723,0.304021,0.045726,0.069869,-0.005713, + -0.577231,0.794491,0.18865,0.045704,0.069899,-0.005861, + -0.672256,0.715879,0.18865,0.044028,0.068512,-0.005861, + -0.652144,0.694463,0.304021,0.044053,0.068485,-0.005713, + -0.607252,0.734041,0.304021,0.044868,0.069203,-0.005713, + -0.672256,0.715879,0.18865,0.044028,0.068512,-0.005861, + -0.607252,0.734041,0.304021,0.044868,0.069203,-0.005713, + -0.625979,0.756678,0.18865,0.044844,0.069232,-0.005861, + -0.715879,0.672256,0.18865,0.043258,0.067743,-0.005861, + -0.694463,0.652144,0.304021,0.043286,0.067717,-0.005713, + -0.652144,0.694463,0.304021,0.044053,0.068485,-0.005713, + -0.715879,0.672256,0.18865,0.043258,0.067743,-0.005861, + -0.652144,0.694463,0.304021,0.044053,0.068485,-0.005713, + -0.672256,0.715879,0.18865,0.044028,0.068512,-0.005861, + -0.756678,0.625979,0.18865,0.042538,0.066927,-0.005861, + -0.734041,0.607252,0.304021,0.042568,0.066903,-0.005713, + -0.694463,0.652144,0.304021,0.043286,0.067717,-0.005713, + -0.756678,0.625979,0.18865,0.042538,0.066927,-0.005861, + -0.694463,0.652144,0.304021,0.043286,0.067717,-0.005713, + -0.715879,0.672256,0.18865,0.043258,0.067743,-0.005861, + -0.794491,0.577231,0.18865,0.041871,0.066067,-0.005861, + -0.770723,0.559963,0.304021,0.041902,0.066045,-0.005713, + -0.734041,0.607252,0.304021,0.042568,0.066903,-0.005713, + -0.794491,0.577231,0.18865,0.041871,0.066067,-0.005861, + -0.734041,0.607252,0.304021,0.042568,0.066903,-0.005713, + -0.756678,0.625979,0.18865,0.042538,0.066927,-0.005861, + -0.829167,0.526206,0.18865,0.04126,0.065167,-0.005861, + -0.804362,0.510464,0.304021,0.041292,0.065147,-0.005713, + -0.770723,0.559963,0.304021,0.041902,0.066045,-0.005713, + -0.829167,0.526206,0.18865,0.04126,0.065167,-0.005861, + -0.770723,0.559963,0.304021,0.041902,0.066045,-0.005713, + -0.794491,0.577231,0.18865,0.041871,0.066067,-0.005861, + -0.860572,0.473103,0.18865,0.040706,0.06423,-0.005861, + -0.834827,0.45895,0.304021,0.040739,0.064212,-0.005713, + -0.804362,0.510464,0.304021,0.041292,0.065147,-0.005713, + -0.860572,0.473103,0.18865,0.040706,0.06423,-0.005861, + -0.804362,0.510464,0.304021,0.041292,0.065147,-0.005713, + -0.829167,0.526206,0.18865,0.04126,0.065167,-0.005861, + -0.88858,0.418134,0.18865,0.040212,0.063261,-0.005861, + -0.861997,0.405625,0.304021,0.040246,0.063245,-0.005713, + -0.834827,0.45895,0.304021,0.040739,0.064212,-0.005713, + -0.88858,0.418134,0.18865,0.040212,0.063261,-0.005861, + -0.834827,0.45895,0.304021,0.040739,0.064212,-0.005713, + -0.860572,0.473103,0.18865,0.040706,0.06423,-0.005861, + -0.913082,0.361515,0.18865,0.03978,0.062262,-0.005861, + -0.885766,0.3507,0.304021,0.039815,0.062248,-0.005713, + -0.861997,0.405625,0.304021,0.040246,0.063245,-0.005713, + -0.913082,0.361515,0.18865,0.03978,0.062262,-0.005861, + -0.861997,0.405625,0.304021,0.040246,0.063245,-0.005713, + -0.88858,0.418134,0.18865,0.040212,0.063261,-0.005861, + -0.93398,0.303468,0.18865,0.039411,0.061238,-0.005861, + -0.906039,0.29439,0.304021,0.039447,0.061226,-0.005713, + -0.885766,0.3507,0.304021,0.039815,0.062248,-0.005713, + -0.93398,0.303468,0.18865,0.039411,0.061238,-0.005861, + -0.885766,0.3507,0.304021,0.039815,0.062248,-0.005713, + -0.913082,0.361515,0.18865,0.03978,0.062262,-0.005861, + -0.951192,0.244224,0.18865,0.039107,0.060193,-0.005861, + -0.922736,0.236918,0.304021,0.039144,0.060184,-0.005713, + -0.906039,0.29439,0.304021,0.039447,0.061226,-0.005713, + -0.951192,0.244224,0.18865,0.039107,0.060193,-0.005861, + -0.906039,0.29439,0.304021,0.039447,0.061226,-0.005713, + -0.93398,0.303468,0.18865,0.039411,0.061238,-0.005861, + -0.96465,0.184017,0.18865,0.03887,0.059131,-0.005861, + -0.935791,0.178512,0.304021,0.038907,0.059124,-0.005713, + -0.922736,0.236918,0.304021,0.039144,0.060184,-0.005713, + -0.96465,0.184017,0.18865,0.03887,0.059131,-0.005861, + -0.922736,0.236918,0.304021,0.039144,0.060184,-0.005713, + -0.951192,0.244224,0.18865,0.039107,0.060193,-0.005861, + -0.974301,0.123083,0.18865,0.0387,0.058056,-0.005861, + -0.945153,0.119401,0.304021,0.038737,0.058052,-0.005713, + -0.935791,0.178512,0.304021,0.038907,0.059124,-0.005713, + -0.974301,0.123083,0.18865,0.0387,0.058056,-0.005861, + -0.935791,0.178512,0.304021,0.038907,0.059124,-0.005713, + -0.96465,0.184017,0.18865,0.03887,0.059131,-0.005861, + -0.980106,0.061663,0.18865,0.038597,0.056973,-0.005861, + -0.950786,0.059818,0.304021,0.038635,0.056971,-0.005713, + -0.945153,0.119401,0.304021,0.038737,0.058052,-0.005713, + -0.980106,0.061663,0.18865,0.038597,0.056973,-0.005861, + -0.945153,0.119401,0.304021,0.038737,0.058052,-0.005713, + -0.974301,0.123083,0.18865,0.0387,0.058056,-0.005861, + -0.982044,0,0.18865,0.038563,0.055885,-0.005861, + -0.952665,0,0.304021,0.038601,0.055885,-0.005713, + -0.950786,0.059818,0.304021,0.038635,0.056971,-0.005713, + -0.982044,0,0.18865,0.038563,0.055885,-0.005861, + -0.950786,0.059818,0.304021,0.038635,0.056971,-0.005713, + -0.980106,0.061663,0.18865,0.038597,0.056973,-0.005861, + -0.980106,-0.061663,0.18865,0.038597,0.054798,-0.005861, + -0.950786,-0.059818,0.304021,0.038635,0.0548,-0.005713, + -0.952665,0,0.304021,0.038601,0.055885,-0.005713, + -0.980106,-0.061663,0.18865,0.038597,0.054798,-0.005861, + -0.952665,0,0.304021,0.038601,0.055885,-0.005713, + -0.982044,0,0.18865,0.038563,0.055885,-0.005861, + -0.974301,-0.123083,0.18865,0.0387,0.053714,-0.005861, + -0.945153,-0.119401,0.304021,0.038737,0.053719,-0.005713, + -0.950786,-0.059818,0.304021,0.038635,0.0548,-0.005713, + -0.974301,-0.123083,0.18865,0.0387,0.053714,-0.005861, + -0.950786,-0.059818,0.304021,0.038635,0.0548,-0.005713, + -0.980106,-0.061663,0.18865,0.038597,0.054798,-0.005861, + -0.96465,-0.184017,0.18865,0.03887,0.05264,-0.005861, + -0.935791,-0.178512,0.304021,0.038907,0.052646,-0.005713, + -0.945153,-0.119401,0.304021,0.038737,0.053719,-0.005713, + -0.96465,-0.184017,0.18865,0.03887,0.05264,-0.005861, + -0.945153,-0.119401,0.304021,0.038737,0.053719,-0.005713, + -0.974301,-0.123083,0.18865,0.0387,0.053714,-0.005861, + -0.951192,-0.244224,0.18865,0.039107,0.051578,-0.005861, + -0.922736,-0.236918,0.304021,0.039144,0.051587,-0.005713, + -0.935791,-0.178512,0.304021,0.038907,0.052646,-0.005713, + -0.951192,-0.244224,0.18865,0.039107,0.051578,-0.005861, + -0.935791,-0.178512,0.304021,0.038907,0.052646,-0.005713, + -0.96465,-0.184017,0.18865,0.03887,0.05264,-0.005861, + -0.922736,-0.236918,0.304021,0.039144,0.051587,-0.005713, + -0.881202,-0.226254,0.415082,0.039198,0.051601,-0.00557, + -0.893669,-0.170477,0.415082,0.038961,0.052657,-0.00557, + -0.922736,-0.236918,0.304021,0.039144,0.051587,-0.005713, + -0.893669,-0.170477,0.415082,0.038961,0.052657,-0.00557, + -0.935791,-0.178512,0.304021,0.038907,0.052646,-0.005713, + -0.906039,-0.29439,0.304021,0.039447,0.050544,-0.005713, + -0.865256,-0.281139,0.415082,0.0395,0.050561,-0.00557, + -0.881202,-0.226254,0.415082,0.039198,0.051601,-0.00557, + -0.906039,-0.29439,0.304021,0.039447,0.050544,-0.005713, + -0.881202,-0.226254,0.415082,0.039198,0.051601,-0.00557, + -0.922736,-0.236918,0.304021,0.039144,0.051587,-0.005713, + -0.885766,-0.3507,0.304021,0.039815,0.049522,-0.005713, + -0.845896,-0.334914,0.415082,0.039866,0.049543,-0.00557, + -0.865256,-0.281139,0.415082,0.0395,0.050561,-0.00557, + -0.885766,-0.3507,0.304021,0.039815,0.049522,-0.005713, + -0.865256,-0.281139,0.415082,0.0395,0.050561,-0.00557, + -0.906039,-0.29439,0.304021,0.039447,0.050544,-0.005713, + -0.861997,-0.405625,0.304021,0.040246,0.048526,-0.005713, + -0.823197,-0.387367,0.415082,0.040296,0.048549,-0.00557, + -0.845896,-0.334914,0.415082,0.039866,0.049543,-0.00557, + -0.861997,-0.405625,0.304021,0.040246,0.048526,-0.005713, + -0.845896,-0.334914,0.415082,0.039866,0.049543,-0.00557, + -0.885766,-0.3507,0.304021,0.039815,0.049522,-0.005713, + -0.834827,-0.45895,0.304021,0.040739,0.047559,-0.005713, + -0.79725,-0.438292,0.415082,0.040787,0.047585,-0.00557, + -0.823197,-0.387367,0.415082,0.040296,0.048549,-0.00557, + -0.834827,-0.45895,0.304021,0.040739,0.047559,-0.005713, + -0.823197,-0.387367,0.415082,0.040296,0.048549,-0.00557, + -0.861997,-0.405625,0.304021,0.040246,0.048526,-0.005713, + -0.804362,-0.510464,0.304021,0.041292,0.046624,-0.005713, + -0.768156,-0.487487,0.415082,0.041338,0.046653,-0.00557, + -0.79725,-0.438292,0.415082,0.040787,0.047585,-0.00557, + -0.804362,-0.510464,0.304021,0.041292,0.046624,-0.005713, + -0.79725,-0.438292,0.415082,0.040787,0.047585,-0.00557, + -0.834827,-0.45895,0.304021,0.040739,0.047559,-0.005713, + -0.770723,-0.559963,0.304021,0.041902,0.045726,-0.005713, + -0.736031,-0.534758,0.415082,0.041947,0.045758,-0.00557, + -0.768156,-0.487487,0.415082,0.041338,0.046653,-0.00557, + -0.770723,-0.559963,0.304021,0.041902,0.045726,-0.005713, + -0.768156,-0.487487,0.415082,0.041338,0.046653,-0.00557, + -0.804362,-0.510464,0.304021,0.041292,0.046624,-0.005713, + -0.734041,-0.607252,0.304021,0.042568,0.044868,-0.005713, + -0.701001,-0.579918,0.415082,0.04261,0.044903,-0.00557, + -0.736031,-0.534758,0.415082,0.041947,0.045758,-0.00557, + -0.734041,-0.607252,0.304021,0.042568,0.044868,-0.005713, + -0.736031,-0.534758,0.415082,0.041947,0.045758,-0.00557, + -0.770723,-0.559963,0.304021,0.041902,0.045726,-0.005713, + -0.694463,-0.652144,0.304021,0.043286,0.044053,-0.005713, + -0.663204,-0.62279,0.415082,0.043326,0.044091,-0.00557, + -0.701001,-0.579918,0.415082,0.04261,0.044903,-0.00557, + -0.694463,-0.652144,0.304021,0.043286,0.044053,-0.005713, + -0.701001,-0.579918,0.415082,0.04261,0.044903,-0.00557, + -0.734041,-0.607252,0.304021,0.042568,0.044868,-0.005713, + -0.652144,-0.694463,0.304021,0.044053,0.043286,-0.005713, + -0.62279,-0.663204,0.415082,0.044091,0.043326,-0.00557, + -0.663204,-0.62279,0.415082,0.043326,0.044091,-0.00557, + -0.652144,-0.694463,0.304021,0.044053,0.043286,-0.005713, + -0.663204,-0.62279,0.415082,0.043326,0.044091,-0.00557, + -0.694463,-0.652144,0.304021,0.043286,0.044053,-0.005713, + -0.607252,-0.734041,0.304021,0.044868,0.042568,-0.005713, + -0.579918,-0.701001,0.415082,0.044903,0.04261,-0.00557, + -0.62279,-0.663204,0.415082,0.044091,0.043326,-0.00557, + -0.607252,-0.734041,0.304021,0.044868,0.042568,-0.005713, + -0.62279,-0.663204,0.415082,0.044091,0.043326,-0.00557, + -0.652144,-0.694463,0.304021,0.044053,0.043286,-0.005713, + -0.559963,-0.770723,0.304021,0.045726,0.041902,-0.005713, + -0.534758,-0.736031,0.415082,0.045758,0.041947,-0.00557, + -0.579918,-0.701001,0.415082,0.044903,0.04261,-0.00557, + -0.559963,-0.770723,0.304021,0.045726,0.041902,-0.005713, + -0.579918,-0.701001,0.415082,0.044903,0.04261,-0.00557, + -0.607252,-0.734041,0.304021,0.044868,0.042568,-0.005713, + -0.510464,-0.804362,0.304021,0.046624,0.041292,-0.005713, + -0.487487,-0.768156,0.415082,0.046653,0.041338,-0.00557, + -0.534758,-0.736031,0.415082,0.045758,0.041947,-0.00557, + -0.510464,-0.804362,0.304021,0.046624,0.041292,-0.005713, + -0.534758,-0.736031,0.415082,0.045758,0.041947,-0.00557, + -0.559963,-0.770723,0.304021,0.045726,0.041902,-0.005713, + -0.45895,-0.834827,0.304021,0.047559,0.040739,-0.005713, + -0.438292,-0.79725,0.415082,0.047585,0.040787,-0.00557, + -0.487487,-0.768156,0.415082,0.046653,0.041338,-0.00557, + -0.45895,-0.834827,0.304021,0.047559,0.040739,-0.005713, + -0.487487,-0.768156,0.415082,0.046653,0.041338,-0.00557, + -0.510464,-0.804362,0.304021,0.046624,0.041292,-0.005713, + -0.405625,-0.861997,0.304021,0.048526,0.040246,-0.005713, + -0.387367,-0.823197,0.415082,0.048549,0.040296,-0.00557, + -0.438292,-0.79725,0.415082,0.047585,0.040787,-0.00557, + -0.405625,-0.861997,0.304021,0.048526,0.040246,-0.005713, + -0.438292,-0.79725,0.415082,0.047585,0.040787,-0.00557, + -0.45895,-0.834827,0.304021,0.047559,0.040739,-0.005713, + -0.3507,-0.885766,0.304021,0.049522,0.039815,-0.005713, + -0.334914,-0.845896,0.415082,0.049543,0.039866,-0.00557, + -0.387367,-0.823197,0.415082,0.048549,0.040296,-0.00557, + -0.3507,-0.885766,0.304021,0.049522,0.039815,-0.005713, + -0.387367,-0.823197,0.415082,0.048549,0.040296,-0.00557, + -0.405625,-0.861997,0.304021,0.048526,0.040246,-0.005713, + -0.29439,-0.906039,0.304021,0.050544,0.039447,-0.005713, + -0.281139,-0.865256,0.415082,0.050561,0.0395,-0.00557, + -0.334914,-0.845896,0.415082,0.049543,0.039866,-0.00557, + -0.29439,-0.906039,0.304021,0.050544,0.039447,-0.005713, + -0.334914,-0.845896,0.415082,0.049543,0.039866,-0.00557, + -0.3507,-0.885766,0.304021,0.049522,0.039815,-0.005713, + -0.236918,-0.922736,0.304021,0.051587,0.039144,-0.005713, + -0.226254,-0.881202,0.415082,0.051601,0.039198,-0.00557, + -0.281139,-0.865256,0.415082,0.050561,0.0395,-0.00557, + -0.236918,-0.922736,0.304021,0.051587,0.039144,-0.005713, + -0.281139,-0.865256,0.415082,0.050561,0.0395,-0.00557, + -0.29439,-0.906039,0.304021,0.050544,0.039447,-0.005713, + -0.178512,-0.935791,0.304021,0.052646,0.038907,-0.005713, + -0.170477,-0.893669,0.415082,0.052657,0.038961,-0.00557, + -0.226254,-0.881202,0.415082,0.051601,0.039198,-0.00557, + -0.178512,-0.935791,0.304021,0.052646,0.038907,-0.005713, + -0.226254,-0.881202,0.415082,0.051601,0.039198,-0.00557, + -0.236918,-0.922736,0.304021,0.051587,0.039144,-0.005713, + -0.119401,-0.945153,0.304021,0.053719,0.038737,-0.005713, + -0.114026,-0.90261,0.415082,0.053726,0.038792,-0.00557, + -0.170477,-0.893669,0.415082,0.052657,0.038961,-0.00557, + -0.119401,-0.945153,0.304021,0.053719,0.038737,-0.005713, + -0.170477,-0.893669,0.415082,0.052657,0.038961,-0.00557, + -0.178512,-0.935791,0.304021,0.052646,0.038907,-0.005713, + -0.059818,-0.950786,0.304021,0.0548,0.038635,-0.005713, + -0.057126,-0.907989,0.415082,0.054803,0.03869,-0.00557, + -0.114026,-0.90261,0.415082,0.053726,0.038792,-0.00557, + -0.059818,-0.950786,0.304021,0.0548,0.038635,-0.005713, + -0.114026,-0.90261,0.415082,0.053726,0.038792,-0.00557, + -0.119401,-0.945153,0.304021,0.053719,0.038737,-0.005713, + 0,-0.952665,0.304021,0.055885,0.038601,-0.005713, + 0,-0.909784,0.415082,0.055885,0.038656,-0.00557, + -0.057126,-0.907989,0.415082,0.054803,0.03869,-0.00557, + 0,-0.952665,0.304021,0.055885,0.038601,-0.005713, + -0.057126,-0.907989,0.415082,0.054803,0.03869,-0.00557, + -0.059818,-0.950786,0.304021,0.0548,0.038635,-0.005713, + 0.059818,-0.950786,0.304021,0.056971,0.038635,-0.005713, + 0.057126,-0.907989,0.415082,0.056967,0.03869,-0.00557, + 0,-0.909784,0.415082,0.055885,0.038656,-0.00557, + 0.059818,-0.950786,0.304021,0.056971,0.038635,-0.005713, + 0,-0.909784,0.415082,0.055885,0.038656,-0.00557, + 0,-0.952665,0.304021,0.055885,0.038601,-0.005713, + 0.119401,-0.945153,0.304021,0.058052,0.038737,-0.005713, + 0.114026,-0.90261,0.415082,0.058045,0.038792,-0.00557, + 0.057126,-0.907989,0.415082,0.056967,0.03869,-0.00557, + 0.119401,-0.945153,0.304021,0.058052,0.038737,-0.005713, + 0.057126,-0.907989,0.415082,0.056967,0.03869,-0.00557, + 0.059818,-0.950786,0.304021,0.056971,0.038635,-0.005713, + 0.178512,-0.935791,0.304021,0.059124,0.038907,-0.005713, + 0.170477,-0.893669,0.415082,0.059114,0.038961,-0.00557, + 0.114026,-0.90261,0.415082,0.058045,0.038792,-0.00557, + 0.178512,-0.935791,0.304021,0.059124,0.038907,-0.005713, + 0.114026,-0.90261,0.415082,0.058045,0.038792,-0.00557, + 0.119401,-0.945153,0.304021,0.058052,0.038737,-0.005713, + 0.236918,-0.922736,0.304021,0.060184,0.039144,-0.005713, + 0.226254,-0.881202,0.415082,0.06017,0.039198,-0.00557, + 0.170477,-0.893669,0.415082,0.059114,0.038961,-0.00557, + 0.236918,-0.922736,0.304021,0.060184,0.039144,-0.005713, + 0.170477,-0.893669,0.415082,0.059114,0.038961,-0.00557, + 0.178512,-0.935791,0.304021,0.059124,0.038907,-0.005713, + 0.29439,-0.906039,0.304021,0.061226,0.039447,-0.005713, + 0.281139,-0.865256,0.415082,0.061209,0.0395,-0.00557, + 0.226254,-0.881202,0.415082,0.06017,0.039198,-0.00557, + 0.29439,-0.906039,0.304021,0.061226,0.039447,-0.005713, + 0.226254,-0.881202,0.415082,0.06017,0.039198,-0.00557, + 0.236918,-0.922736,0.304021,0.060184,0.039144,-0.005713, + 0.3507,-0.885766,0.304021,0.062248,0.039815,-0.005713, + 0.334914,-0.845896,0.415082,0.062228,0.039866,-0.00557, + 0.281139,-0.865256,0.415082,0.061209,0.0395,-0.00557, + 0.3507,-0.885766,0.304021,0.062248,0.039815,-0.005713, + 0.281139,-0.865256,0.415082,0.061209,0.0395,-0.00557, + 0.29439,-0.906039,0.304021,0.061226,0.039447,-0.005713, + 0.405625,-0.861997,0.304021,0.063245,0.040246,-0.005713, + 0.387367,-0.823197,0.415082,0.063221,0.040296,-0.00557, + 0.334914,-0.845896,0.415082,0.062228,0.039866,-0.00557, + 0.405625,-0.861997,0.304021,0.063245,0.040246,-0.005713, + 0.334914,-0.845896,0.415082,0.062228,0.039866,-0.00557, + 0.3507,-0.885766,0.304021,0.062248,0.039815,-0.005713, + 0.45895,-0.834827,0.304021,0.064212,0.040739,-0.005713, + 0.438292,-0.79725,0.415082,0.064185,0.040787,-0.00557, + 0.387367,-0.823197,0.415082,0.063221,0.040296,-0.00557, + 0.45895,-0.834827,0.304021,0.064212,0.040739,-0.005713, + 0.387367,-0.823197,0.415082,0.063221,0.040296,-0.00557, + 0.405625,-0.861997,0.304021,0.063245,0.040246,-0.005713, + 0.510464,-0.804362,0.304021,0.065147,0.041292,-0.005713, + 0.487487,-0.768156,0.415082,0.065117,0.041338,-0.00557, + 0.438292,-0.79725,0.415082,0.064185,0.040787,-0.00557, + 0.510464,-0.804362,0.304021,0.065147,0.041292,-0.005713, + 0.438292,-0.79725,0.415082,0.064185,0.040787,-0.00557, + 0.45895,-0.834827,0.304021,0.064212,0.040739,-0.005713, + 0.559963,-0.770723,0.304021,0.066045,0.041902,-0.005713, + 0.534758,-0.736031,0.415082,0.066012,0.041947,-0.00557, + 0.487487,-0.768156,0.415082,0.065117,0.041338,-0.00557, + 0.559963,-0.770723,0.304021,0.066045,0.041902,-0.005713, + 0.487487,-0.768156,0.415082,0.065117,0.041338,-0.00557, + 0.510464,-0.804362,0.304021,0.065147,0.041292,-0.005713, + 0.607252,-0.734041,0.304021,0.066903,0.042568,-0.005713, + 0.579918,-0.701001,0.415082,0.066868,0.04261,-0.00557, + 0.534758,-0.736031,0.415082,0.066012,0.041947,-0.00557, + 0.607252,-0.734041,0.304021,0.066903,0.042568,-0.005713, + 0.534758,-0.736031,0.415082,0.066012,0.041947,-0.00557, + 0.559963,-0.770723,0.304021,0.066045,0.041902,-0.005713, + 0.652144,-0.694463,0.304021,0.067717,0.043286,-0.005713, + 0.62279,-0.663204,0.415082,0.067679,0.043326,-0.00557, + 0.579918,-0.701001,0.415082,0.066868,0.04261,-0.00557, + 0.652144,-0.694463,0.304021,0.067717,0.043286,-0.005713, + 0.579918,-0.701001,0.415082,0.066868,0.04261,-0.00557, + 0.607252,-0.734041,0.304021,0.066903,0.042568,-0.005713, + 0.694463,-0.652144,0.304021,0.068485,0.044053,-0.005713, + 0.663204,-0.62279,0.415082,0.068445,0.044091,-0.00557, + 0.62279,-0.663204,0.415082,0.067679,0.043326,-0.00557, + 0.694463,-0.652144,0.304021,0.068485,0.044053,-0.005713, + 0.62279,-0.663204,0.415082,0.067679,0.043326,-0.00557, + 0.652144,-0.694463,0.304021,0.067717,0.043286,-0.005713, + 0.734041,-0.607252,0.304021,0.069203,0.044868,-0.005713, + 0.701001,-0.579918,0.415082,0.069161,0.044903,-0.00557, + 0.663204,-0.62279,0.415082,0.068445,0.044091,-0.00557, + 0.734041,-0.607252,0.304021,0.069203,0.044868,-0.005713, + 0.663204,-0.62279,0.415082,0.068445,0.044091,-0.00557, + 0.694463,-0.652144,0.304021,0.068485,0.044053,-0.005713, + 0.770723,-0.559963,0.304021,0.069869,0.045726,-0.005713, + 0.736031,-0.534758,0.415082,0.069824,0.045758,-0.00557, + 0.701001,-0.579918,0.415082,0.069161,0.044903,-0.00557, + 0.770723,-0.559963,0.304021,0.069869,0.045726,-0.005713, + 0.701001,-0.579918,0.415082,0.069161,0.044903,-0.00557, + 0.734041,-0.607252,0.304021,0.069203,0.044868,-0.005713, + 0.804362,-0.510464,0.304021,0.070479,0.046624,-0.005713, + 0.768156,-0.487487,0.415082,0.070432,0.046653,-0.00557, + 0.736031,-0.534758,0.415082,0.069824,0.045758,-0.00557, + 0.804362,-0.510464,0.304021,0.070479,0.046624,-0.005713, + 0.736031,-0.534758,0.415082,0.069824,0.045758,-0.00557, + 0.770723,-0.559963,0.304021,0.069869,0.045726,-0.005713, + 0.834827,-0.45895,0.304021,0.071032,0.047559,-0.005713, + 0.79725,-0.438292,0.415082,0.070983,0.047585,-0.00557, + 0.768156,-0.487487,0.415082,0.070432,0.046653,-0.00557, + 0.834827,-0.45895,0.304021,0.071032,0.047559,-0.005713, + 0.768156,-0.487487,0.415082,0.070432,0.046653,-0.00557, + 0.804362,-0.510464,0.304021,0.070479,0.046624,-0.005713, + 0.861997,-0.405625,0.304021,0.071525,0.048526,-0.005713, + 0.823197,-0.387367,0.415082,0.071475,0.048549,-0.00557, + 0.79725,-0.438292,0.415082,0.070983,0.047585,-0.00557, + 0.861997,-0.405625,0.304021,0.071525,0.048526,-0.005713, + 0.79725,-0.438292,0.415082,0.070983,0.047585,-0.00557, + 0.834827,-0.45895,0.304021,0.071032,0.047559,-0.005713, + 0.885766,-0.3507,0.304021,0.071956,0.049522,-0.005713, + 0.845896,-0.334914,0.415082,0.071905,0.049543,-0.00557, + 0.823197,-0.387367,0.415082,0.071475,0.048549,-0.00557, + 0.885766,-0.3507,0.304021,0.071956,0.049522,-0.005713, + 0.823197,-0.387367,0.415082,0.071475,0.048549,-0.00557, + 0.861997,-0.405625,0.304021,0.071525,0.048526,-0.005713, + 0.906039,-0.29439,0.304021,0.072324,0.050544,-0.005713, + 0.865256,-0.281139,0.415082,0.072271,0.050561,-0.00557, + 0.845896,-0.334914,0.415082,0.071905,0.049543,-0.00557, + 0.906039,-0.29439,0.304021,0.072324,0.050544,-0.005713, + 0.845896,-0.334914,0.415082,0.071905,0.049543,-0.00557, + 0.885766,-0.3507,0.304021,0.071956,0.049522,-0.005713, + 0.922736,-0.236918,0.304021,0.072627,0.051587,-0.005713, + 0.881202,-0.226254,0.415082,0.072573,0.051601,-0.00557, + 0.865256,-0.281139,0.415082,0.072271,0.050561,-0.00557, + 0.922736,-0.236918,0.304021,0.072627,0.051587,-0.005713, + 0.865256,-0.281139,0.415082,0.072271,0.050561,-0.00557, + 0.906039,-0.29439,0.304021,0.072324,0.050544,-0.005713, + 0.935791,-0.178512,0.304021,0.072863,0.052646,-0.005713, + 0.893669,-0.170477,0.415082,0.072809,0.052657,-0.00557, + 0.881202,-0.226254,0.415082,0.072573,0.051601,-0.00557, + 0.935791,-0.178512,0.304021,0.072863,0.052646,-0.005713, + 0.881202,-0.226254,0.415082,0.072573,0.051601,-0.00557, + 0.922736,-0.236918,0.304021,0.072627,0.051587,-0.005713, + 0.945153,-0.119401,0.304021,0.073033,0.053719,-0.005713, + 0.90261,-0.114026,0.415082,0.072978,0.053726,-0.00557, + 0.893669,-0.170477,0.415082,0.072809,0.052657,-0.00557, + 0.945153,-0.119401,0.304021,0.073033,0.053719,-0.005713, + 0.893669,-0.170477,0.415082,0.072809,0.052657,-0.00557, + 0.935791,-0.178512,0.304021,0.072863,0.052646,-0.005713, + 0.950786,-0.059818,0.304021,0.073135,0.0548,-0.005713, + 0.907989,-0.057126,0.415082,0.07308,0.054803,-0.00557, + 0.90261,-0.114026,0.415082,0.072978,0.053726,-0.00557, + 0.950786,-0.059818,0.304021,0.073135,0.0548,-0.005713, + 0.90261,-0.114026,0.415082,0.072978,0.053726,-0.00557, + 0.945153,-0.119401,0.304021,0.073033,0.053719,-0.005713, + 0.952665,0,0.304021,0.073169,0.055885,-0.005713, + 0.909784,0,0.415082,0.073114,0.055885,-0.00557, + 0.907989,-0.057126,0.415082,0.07308,0.054803,-0.00557, + 0.952665,0,0.304021,0.073169,0.055885,-0.005713, + 0.907989,-0.057126,0.415082,0.07308,0.054803,-0.00557, + 0.950786,-0.059818,0.304021,0.073135,0.0548,-0.005713, + 0.950786,0.059818,0.304021,0.073135,0.056971,-0.005713, + 0.907989,0.057126,0.415082,0.07308,0.056967,-0.00557, + 0.909784,0,0.415082,0.073114,0.055885,-0.00557, + 0.950786,0.059818,0.304021,0.073135,0.056971,-0.005713, + 0.909784,0,0.415082,0.073114,0.055885,-0.00557, + 0.952665,0,0.304021,0.073169,0.055885,-0.005713, + 0.945153,0.119401,0.304021,0.073033,0.058052,-0.005713, + 0.90261,0.114026,0.415082,0.072978,0.058045,-0.00557, + 0.907989,0.057126,0.415082,0.07308,0.056967,-0.00557, + 0.945153,0.119401,0.304021,0.073033,0.058052,-0.005713, + 0.907989,0.057126,0.415082,0.07308,0.056967,-0.00557, + 0.950786,0.059818,0.304021,0.073135,0.056971,-0.005713, + 0.935791,0.178512,0.304021,0.072863,0.059124,-0.005713, + 0.893669,0.170477,0.415082,0.072809,0.059114,-0.00557, + 0.90261,0.114026,0.415082,0.072978,0.058045,-0.00557, + 0.935791,0.178512,0.304021,0.072863,0.059124,-0.005713, + 0.90261,0.114026,0.415082,0.072978,0.058045,-0.00557, + 0.945153,0.119401,0.304021,0.073033,0.058052,-0.005713, + 0.922736,0.236918,0.304021,0.072627,0.060184,-0.005713, + 0.881202,0.226254,0.415082,0.072573,0.06017,-0.00557, + 0.893669,0.170477,0.415082,0.072809,0.059114,-0.00557, + 0.922736,0.236918,0.304021,0.072627,0.060184,-0.005713, + 0.893669,0.170477,0.415082,0.072809,0.059114,-0.00557, + 0.935791,0.178512,0.304021,0.072863,0.059124,-0.005713, + 0.906039,0.29439,0.304021,0.072324,0.061226,-0.005713, + 0.865256,0.281139,0.415082,0.072271,0.061209,-0.00557, + 0.881202,0.226254,0.415082,0.072573,0.06017,-0.00557, + 0.906039,0.29439,0.304021,0.072324,0.061226,-0.005713, + 0.881202,0.226254,0.415082,0.072573,0.06017,-0.00557, + 0.922736,0.236918,0.304021,0.072627,0.060184,-0.005713, + 0.885766,0.3507,0.304021,0.071956,0.062248,-0.005713, + 0.845896,0.334914,0.415082,0.071905,0.062228,-0.00557, + 0.865256,0.281139,0.415082,0.072271,0.061209,-0.00557, + 0.885766,0.3507,0.304021,0.071956,0.062248,-0.005713, + 0.865256,0.281139,0.415082,0.072271,0.061209,-0.00557, + 0.906039,0.29439,0.304021,0.072324,0.061226,-0.005713, + 0.861997,0.405625,0.304021,0.071525,0.063245,-0.005713, + 0.823197,0.387367,0.415082,0.071475,0.063221,-0.00557, + 0.845896,0.334914,0.415082,0.071905,0.062228,-0.00557, + 0.861997,0.405625,0.304021,0.071525,0.063245,-0.005713, + 0.845896,0.334914,0.415082,0.071905,0.062228,-0.00557, + 0.885766,0.3507,0.304021,0.071956,0.062248,-0.005713, + 0.834827,0.45895,0.304021,0.071032,0.064212,-0.005713, + 0.79725,0.438292,0.415082,0.070983,0.064185,-0.00557, + 0.823197,0.387367,0.415082,0.071475,0.063221,-0.00557, + 0.834827,0.45895,0.304021,0.071032,0.064212,-0.005713, + 0.823197,0.387367,0.415082,0.071475,0.063221,-0.00557, + 0.861997,0.405625,0.304021,0.071525,0.063245,-0.005713, + 0.804362,0.510464,0.304021,0.070479,0.065147,-0.005713, + 0.768156,0.487487,0.415082,0.070432,0.065117,-0.00557, + 0.79725,0.438292,0.415082,0.070983,0.064185,-0.00557, + 0.804362,0.510464,0.304021,0.070479,0.065147,-0.005713, + 0.79725,0.438292,0.415082,0.070983,0.064185,-0.00557, + 0.834827,0.45895,0.304021,0.071032,0.064212,-0.005713, + 0.770723,0.559963,0.304021,0.069869,0.066045,-0.005713, + 0.736031,0.534758,0.415082,0.069824,0.066012,-0.00557, + 0.768156,0.487487,0.415082,0.070432,0.065117,-0.00557, + 0.770723,0.559963,0.304021,0.069869,0.066045,-0.005713, + 0.768156,0.487487,0.415082,0.070432,0.065117,-0.00557, + 0.804362,0.510464,0.304021,0.070479,0.065147,-0.005713, + 0.734041,0.607252,0.304021,0.069203,0.066903,-0.005713, + 0.701001,0.579918,0.415082,0.069161,0.066868,-0.00557, + 0.736031,0.534758,0.415082,0.069824,0.066012,-0.00557, + 0.734041,0.607252,0.304021,0.069203,0.066903,-0.005713, + 0.736031,0.534758,0.415082,0.069824,0.066012,-0.00557, + 0.770723,0.559963,0.304021,0.069869,0.066045,-0.005713, + 0.694463,0.652144,0.304021,0.068485,0.067717,-0.005713, + 0.663204,0.62279,0.415082,0.068445,0.067679,-0.00557, + 0.701001,0.579918,0.415082,0.069161,0.066868,-0.00557, + 0.694463,0.652144,0.304021,0.068485,0.067717,-0.005713, + 0.701001,0.579918,0.415082,0.069161,0.066868,-0.00557, + 0.734041,0.607252,0.304021,0.069203,0.066903,-0.005713, + 0.652144,0.694463,0.304021,0.067717,0.068485,-0.005713, + 0.62279,0.663204,0.415082,0.067679,0.068445,-0.00557, + 0.663204,0.62279,0.415082,0.068445,0.067679,-0.00557, + 0.652144,0.694463,0.304021,0.067717,0.068485,-0.005713, + 0.663204,0.62279,0.415082,0.068445,0.067679,-0.00557, + 0.694463,0.652144,0.304021,0.068485,0.067717,-0.005713, + 0.607252,0.734041,0.304021,0.066903,0.069203,-0.005713, + 0.579918,0.701001,0.415082,0.066868,0.069161,-0.00557, + 0.62279,0.663204,0.415082,0.067679,0.068445,-0.00557, + 0.607252,0.734041,0.304021,0.066903,0.069203,-0.005713, + 0.62279,0.663204,0.415082,0.067679,0.068445,-0.00557, + 0.652144,0.694463,0.304021,0.067717,0.068485,-0.005713, + 0.559963,0.770723,0.304021,0.066045,0.069869,-0.005713, + 0.534758,0.736031,0.415082,0.066012,0.069824,-0.00557, + 0.579918,0.701001,0.415082,0.066868,0.069161,-0.00557, + 0.559963,0.770723,0.304021,0.066045,0.069869,-0.005713, + 0.579918,0.701001,0.415082,0.066868,0.069161,-0.00557, + 0.607252,0.734041,0.304021,0.066903,0.069203,-0.005713, + 0.510464,0.804362,0.304021,0.065147,0.070479,-0.005713, + 0.487487,0.768156,0.415082,0.065117,0.070432,-0.00557, + 0.534758,0.736031,0.415082,0.066012,0.069824,-0.00557, + 0.510464,0.804362,0.304021,0.065147,0.070479,-0.005713, + 0.534758,0.736031,0.415082,0.066012,0.069824,-0.00557, + 0.559963,0.770723,0.304021,0.066045,0.069869,-0.005713, + 0.45895,0.834827,0.304021,0.064212,0.071032,-0.005713, + 0.438292,0.79725,0.415082,0.064185,0.070983,-0.00557, + 0.487487,0.768156,0.415082,0.065117,0.070432,-0.00557, + 0.45895,0.834827,0.304021,0.064212,0.071032,-0.005713, + 0.487487,0.768156,0.415082,0.065117,0.070432,-0.00557, + 0.510464,0.804362,0.304021,0.065147,0.070479,-0.005713, + 0.405625,0.861997,0.304021,0.063245,0.071525,-0.005713, + 0.387367,0.823197,0.415082,0.063221,0.071475,-0.00557, + 0.438292,0.79725,0.415082,0.064185,0.070983,-0.00557, + 0.405625,0.861997,0.304021,0.063245,0.071525,-0.005713, + 0.438292,0.79725,0.415082,0.064185,0.070983,-0.00557, + 0.45895,0.834827,0.304021,0.064212,0.071032,-0.005713, + 0.3507,0.885766,0.304021,0.062248,0.071956,-0.005713, + 0.334914,0.845896,0.415082,0.062228,0.071905,-0.00557, + 0.387367,0.823197,0.415082,0.063221,0.071475,-0.00557, + 0.3507,0.885766,0.304021,0.062248,0.071956,-0.005713, + 0.387367,0.823197,0.415082,0.063221,0.071475,-0.00557, + 0.405625,0.861997,0.304021,0.063245,0.071525,-0.005713, + 0.29439,0.906039,0.304021,0.061226,0.072324,-0.005713, + 0.281139,0.865256,0.415082,0.061209,0.072271,-0.00557, + 0.334914,0.845896,0.415082,0.062228,0.071905,-0.00557, + 0.29439,0.906039,0.304021,0.061226,0.072324,-0.005713, + 0.334914,0.845896,0.415082,0.062228,0.071905,-0.00557, + 0.3507,0.885766,0.304021,0.062248,0.071956,-0.005713, + 0.236918,0.922736,0.304021,0.060184,0.072627,-0.005713, + 0.226254,0.881202,0.415082,0.06017,0.072573,-0.00557, + 0.281139,0.865256,0.415082,0.061209,0.072271,-0.00557, + 0.236918,0.922736,0.304021,0.060184,0.072627,-0.005713, + 0.281139,0.865256,0.415082,0.061209,0.072271,-0.00557, + 0.29439,0.906039,0.304021,0.061226,0.072324,-0.005713, + 0.178512,0.935791,0.304021,0.059124,0.072863,-0.005713, + 0.170477,0.893669,0.415082,0.059114,0.072809,-0.00557, + 0.226254,0.881202,0.415082,0.06017,0.072573,-0.00557, + 0.178512,0.935791,0.304021,0.059124,0.072863,-0.005713, + 0.226254,0.881202,0.415082,0.06017,0.072573,-0.00557, + 0.236918,0.922736,0.304021,0.060184,0.072627,-0.005713, + 0.119401,0.945153,0.304021,0.058052,0.073033,-0.005713, + 0.114026,0.90261,0.415082,0.058045,0.072978,-0.00557, + 0.170477,0.893669,0.415082,0.059114,0.072809,-0.00557, + 0.119401,0.945153,0.304021,0.058052,0.073033,-0.005713, + 0.170477,0.893669,0.415082,0.059114,0.072809,-0.00557, + 0.178512,0.935791,0.304021,0.059124,0.072863,-0.005713, + 0.059818,0.950786,0.304021,0.056971,0.073135,-0.005713, + 0.057126,0.907989,0.415082,0.056967,0.07308,-0.00557, + 0.114026,0.90261,0.415082,0.058045,0.072978,-0.00557, + 0.059818,0.950786,0.304021,0.056971,0.073135,-0.005713, + 0.114026,0.90261,0.415082,0.058045,0.072978,-0.00557, + 0.119401,0.945153,0.304021,0.058052,0.073033,-0.005713, + 0,0.952665,0.304021,0.055885,0.073169,-0.005713, + 0,0.909784,0.415082,0.055885,0.073114,-0.00557, + 0.057126,0.907989,0.415082,0.056967,0.07308,-0.00557, + 0,0.952665,0.304021,0.055885,0.073169,-0.005713, + 0.057126,0.907989,0.415082,0.056967,0.07308,-0.00557, + 0.059818,0.950786,0.304021,0.056971,0.073135,-0.005713, + -0.059818,0.950786,0.304021,0.0548,0.073135,-0.005713, + -0.057126,0.907989,0.415082,0.054803,0.07308,-0.00557, + 0,0.909784,0.415082,0.055885,0.073114,-0.00557, + -0.059818,0.950786,0.304021,0.0548,0.073135,-0.005713, + 0,0.909784,0.415082,0.055885,0.073114,-0.00557, + 0,0.952665,0.304021,0.055885,0.073169,-0.005713, + -0.119401,0.945153,0.304021,0.053719,0.073033,-0.005713, + -0.114026,0.90261,0.415082,0.053726,0.072978,-0.00557, + -0.057126,0.907989,0.415082,0.054803,0.07308,-0.00557, + -0.119401,0.945153,0.304021,0.053719,0.073033,-0.005713, + -0.057126,0.907989,0.415082,0.054803,0.07308,-0.00557, + -0.059818,0.950786,0.304021,0.0548,0.073135,-0.005713, + -0.178512,0.935791,0.304021,0.052646,0.072863,-0.005713, + -0.170477,0.893669,0.415082,0.052657,0.072809,-0.00557, + -0.114026,0.90261,0.415082,0.053726,0.072978,-0.00557, + -0.178512,0.935791,0.304021,0.052646,0.072863,-0.005713, + -0.114026,0.90261,0.415082,0.053726,0.072978,-0.00557, + -0.119401,0.945153,0.304021,0.053719,0.073033,-0.005713, + -0.236918,0.922736,0.304021,0.051587,0.072627,-0.005713, + -0.226254,0.881202,0.415082,0.051601,0.072573,-0.00557, + -0.170477,0.893669,0.415082,0.052657,0.072809,-0.00557, + -0.236918,0.922736,0.304021,0.051587,0.072627,-0.005713, + -0.170477,0.893669,0.415082,0.052657,0.072809,-0.00557, + -0.178512,0.935791,0.304021,0.052646,0.072863,-0.005713, + -0.29439,0.906039,0.304021,0.050544,0.072324,-0.005713, + -0.281139,0.865256,0.415082,0.050561,0.072271,-0.00557, + -0.226254,0.881202,0.415082,0.051601,0.072573,-0.00557, + -0.29439,0.906039,0.304021,0.050544,0.072324,-0.005713, + -0.226254,0.881202,0.415082,0.051601,0.072573,-0.00557, + -0.236918,0.922736,0.304021,0.051587,0.072627,-0.005713, + -0.3507,0.885766,0.304021,0.049522,0.071956,-0.005713, + -0.334914,0.845896,0.415082,0.049543,0.071905,-0.00557, + -0.281139,0.865256,0.415082,0.050561,0.072271,-0.00557, + -0.3507,0.885766,0.304021,0.049522,0.071956,-0.005713, + -0.281139,0.865256,0.415082,0.050561,0.072271,-0.00557, + -0.29439,0.906039,0.304021,0.050544,0.072324,-0.005713, + -0.405625,0.861997,0.304021,0.048526,0.071525,-0.005713, + -0.387367,0.823197,0.415082,0.048549,0.071475,-0.00557, + -0.334914,0.845896,0.415082,0.049543,0.071905,-0.00557, + -0.405625,0.861997,0.304021,0.048526,0.071525,-0.005713, + -0.334914,0.845896,0.415082,0.049543,0.071905,-0.00557, + -0.3507,0.885766,0.304021,0.049522,0.071956,-0.005713, + -0.45895,0.834827,0.304021,0.047559,0.071032,-0.005713, + -0.438292,0.79725,0.415082,0.047585,0.070983,-0.00557, + -0.387367,0.823197,0.415082,0.048549,0.071475,-0.00557, + -0.45895,0.834827,0.304021,0.047559,0.071032,-0.005713, + -0.387367,0.823197,0.415082,0.048549,0.071475,-0.00557, + -0.405625,0.861997,0.304021,0.048526,0.071525,-0.005713, + -0.510464,0.804362,0.304021,0.046624,0.070479,-0.005713, + -0.487487,0.768156,0.415082,0.046653,0.070432,-0.00557, + -0.438292,0.79725,0.415082,0.047585,0.070983,-0.00557, + -0.510464,0.804362,0.304021,0.046624,0.070479,-0.005713, + -0.438292,0.79725,0.415082,0.047585,0.070983,-0.00557, + -0.45895,0.834827,0.304021,0.047559,0.071032,-0.005713, + -0.559963,0.770723,0.304021,0.045726,0.069869,-0.005713, + -0.534758,0.736031,0.415082,0.045758,0.069824,-0.00557, + -0.487487,0.768156,0.415082,0.046653,0.070432,-0.00557, + -0.559963,0.770723,0.304021,0.045726,0.069869,-0.005713, + -0.487487,0.768156,0.415082,0.046653,0.070432,-0.00557, + -0.510464,0.804362,0.304021,0.046624,0.070479,-0.005713, + -0.607252,0.734041,0.304021,0.044868,0.069203,-0.005713, + -0.579918,0.701001,0.415082,0.044903,0.069161,-0.00557, + -0.534758,0.736031,0.415082,0.045758,0.069824,-0.00557, + -0.607252,0.734041,0.304021,0.044868,0.069203,-0.005713, + -0.534758,0.736031,0.415082,0.045758,0.069824,-0.00557, + -0.559963,0.770723,0.304021,0.045726,0.069869,-0.005713, + -0.652144,0.694463,0.304021,0.044053,0.068485,-0.005713, + -0.62279,0.663204,0.415082,0.044091,0.068445,-0.00557, + -0.579918,0.701001,0.415082,0.044903,0.069161,-0.00557, + -0.652144,0.694463,0.304021,0.044053,0.068485,-0.005713, + -0.579918,0.701001,0.415082,0.044903,0.069161,-0.00557, + -0.607252,0.734041,0.304021,0.044868,0.069203,-0.005713, + -0.694463,0.652144,0.304021,0.043286,0.067717,-0.005713, + -0.663204,0.62279,0.415082,0.043326,0.067679,-0.00557, + -0.62279,0.663204,0.415082,0.044091,0.068445,-0.00557, + -0.694463,0.652144,0.304021,0.043286,0.067717,-0.005713, + -0.62279,0.663204,0.415082,0.044091,0.068445,-0.00557, + -0.652144,0.694463,0.304021,0.044053,0.068485,-0.005713, + -0.734041,0.607252,0.304021,0.042568,0.066903,-0.005713, + -0.701001,0.579918,0.415082,0.04261,0.066868,-0.00557, + -0.663204,0.62279,0.415082,0.043326,0.067679,-0.00557, + -0.734041,0.607252,0.304021,0.042568,0.066903,-0.005713, + -0.663204,0.62279,0.415082,0.043326,0.067679,-0.00557, + -0.694463,0.652144,0.304021,0.043286,0.067717,-0.005713, + -0.770723,0.559963,0.304021,0.041902,0.066045,-0.005713, + -0.736031,0.534758,0.415082,0.041947,0.066012,-0.00557, + -0.701001,0.579918,0.415082,0.04261,0.066868,-0.00557, + -0.770723,0.559963,0.304021,0.041902,0.066045,-0.005713, + -0.701001,0.579918,0.415082,0.04261,0.066868,-0.00557, + -0.734041,0.607252,0.304021,0.042568,0.066903,-0.005713, + -0.804362,0.510464,0.304021,0.041292,0.065147,-0.005713, + -0.768156,0.487487,0.415082,0.041338,0.065117,-0.00557, + -0.736031,0.534758,0.415082,0.041947,0.066012,-0.00557, + -0.804362,0.510464,0.304021,0.041292,0.065147,-0.005713, + -0.736031,0.534758,0.415082,0.041947,0.066012,-0.00557, + -0.770723,0.559963,0.304021,0.041902,0.066045,-0.005713, + -0.834827,0.45895,0.304021,0.040739,0.064212,-0.005713, + -0.79725,0.438292,0.415082,0.040787,0.064185,-0.00557, + -0.768156,0.487487,0.415082,0.041338,0.065117,-0.00557, + -0.834827,0.45895,0.304021,0.040739,0.064212,-0.005713, + -0.768156,0.487487,0.415082,0.041338,0.065117,-0.00557, + -0.804362,0.510464,0.304021,0.041292,0.065147,-0.005713, + -0.861997,0.405625,0.304021,0.040246,0.063245,-0.005713, + -0.823197,0.387367,0.415082,0.040296,0.063221,-0.00557, + -0.79725,0.438292,0.415082,0.040787,0.064185,-0.00557, + -0.861997,0.405625,0.304021,0.040246,0.063245,-0.005713, + -0.79725,0.438292,0.415082,0.040787,0.064185,-0.00557, + -0.834827,0.45895,0.304021,0.040739,0.064212,-0.005713, + -0.885766,0.3507,0.304021,0.039815,0.062248,-0.005713, + -0.845896,0.334914,0.415082,0.039866,0.062228,-0.00557, + -0.823197,0.387367,0.415082,0.040296,0.063221,-0.00557, + -0.885766,0.3507,0.304021,0.039815,0.062248,-0.005713, + -0.823197,0.387367,0.415082,0.040296,0.063221,-0.00557, + -0.861997,0.405625,0.304021,0.040246,0.063245,-0.005713, + -0.906039,0.29439,0.304021,0.039447,0.061226,-0.005713, + -0.865256,0.281139,0.415082,0.0395,0.061209,-0.00557, + -0.845896,0.334914,0.415082,0.039866,0.062228,-0.00557, + -0.906039,0.29439,0.304021,0.039447,0.061226,-0.005713, + -0.845896,0.334914,0.415082,0.039866,0.062228,-0.00557, + -0.885766,0.3507,0.304021,0.039815,0.062248,-0.005713, + -0.922736,0.236918,0.304021,0.039144,0.060184,-0.005713, + -0.881202,0.226254,0.415082,0.039198,0.06017,-0.00557, + -0.865256,0.281139,0.415082,0.0395,0.061209,-0.00557, + -0.922736,0.236918,0.304021,0.039144,0.060184,-0.005713, + -0.865256,0.281139,0.415082,0.0395,0.061209,-0.00557, + -0.906039,0.29439,0.304021,0.039447,0.061226,-0.005713, + -0.935791,0.178512,0.304021,0.038907,0.059124,-0.005713, + -0.893669,0.170477,0.415082,0.038961,0.059114,-0.00557, + -0.881202,0.226254,0.415082,0.039198,0.06017,-0.00557, + -0.935791,0.178512,0.304021,0.038907,0.059124,-0.005713, + -0.881202,0.226254,0.415082,0.039198,0.06017,-0.00557, + -0.922736,0.236918,0.304021,0.039144,0.060184,-0.005713, + -0.945153,0.119401,0.304021,0.038737,0.058052,-0.005713, + -0.90261,0.114026,0.415082,0.038792,0.058045,-0.00557, + -0.893669,0.170477,0.415082,0.038961,0.059114,-0.00557, + -0.945153,0.119401,0.304021,0.038737,0.058052,-0.005713, + -0.893669,0.170477,0.415082,0.038961,0.059114,-0.00557, + -0.935791,0.178512,0.304021,0.038907,0.059124,-0.005713, + -0.950786,0.059818,0.304021,0.038635,0.056971,-0.005713, + -0.907989,0.057126,0.415082,0.03869,0.056967,-0.00557, + -0.90261,0.114026,0.415082,0.038792,0.058045,-0.00557, + -0.950786,0.059818,0.304021,0.038635,0.056971,-0.005713, + -0.90261,0.114026,0.415082,0.038792,0.058045,-0.00557, + -0.945153,0.119401,0.304021,0.038737,0.058052,-0.005713, + -0.952665,0,0.304021,0.038601,0.055885,-0.005713, + -0.909784,0,0.415082,0.038656,0.055885,-0.00557, + -0.907989,0.057126,0.415082,0.03869,0.056967,-0.00557, + -0.952665,0,0.304021,0.038601,0.055885,-0.005713, + -0.907989,0.057126,0.415082,0.03869,0.056967,-0.00557, + -0.950786,0.059818,0.304021,0.038635,0.056971,-0.005713, + -0.950786,-0.059818,0.304021,0.038635,0.0548,-0.005713, + -0.907989,-0.057126,0.415082,0.03869,0.054803,-0.00557, + -0.909784,0,0.415082,0.038656,0.055885,-0.00557, + -0.950786,-0.059818,0.304021,0.038635,0.0548,-0.005713, + -0.909784,0,0.415082,0.038656,0.055885,-0.00557, + -0.952665,0,0.304021,0.038601,0.055885,-0.005713, + -0.945153,-0.119401,0.304021,0.038737,0.053719,-0.005713, + -0.90261,-0.114026,0.415082,0.038792,0.053726,-0.00557, + -0.907989,-0.057126,0.415082,0.03869,0.054803,-0.00557, + -0.945153,-0.119401,0.304021,0.038737,0.053719,-0.005713, + -0.907989,-0.057126,0.415082,0.03869,0.054803,-0.00557, + -0.950786,-0.059818,0.304021,0.038635,0.0548,-0.005713, + -0.935791,-0.178512,0.304021,0.038907,0.052646,-0.005713, + -0.893669,-0.170477,0.415082,0.038961,0.052657,-0.00557, + -0.90261,-0.114026,0.415082,0.038792,0.053726,-0.00557, + -0.935791,-0.178512,0.304021,0.038907,0.052646,-0.005713, + -0.90261,-0.114026,0.415082,0.038792,0.053726,-0.00557, + -0.945153,-0.119401,0.304021,0.038737,0.053719,-0.005713, + -0.893669,-0.170477,0.415082,0.038961,0.052657,-0.00557, + -0.838881,-0.160025,0.52026,0.039032,0.05267,-0.005434, + -0.847274,-0.107036,0.52026,0.038863,0.053735,-0.005434, + -0.893669,-0.170477,0.415082,0.038961,0.052657,-0.00557, + -0.847274,-0.107036,0.52026,0.038863,0.053735,-0.005434, + -0.90261,-0.114026,0.415082,0.038792,0.053726,-0.00557, + -0.881202,-0.226254,0.415082,0.039198,0.051601,-0.00557, + -0.827178,-0.212383,0.52026,0.039267,0.051619,-0.005434, + -0.838881,-0.160025,0.52026,0.039032,0.05267,-0.005434, + -0.881202,-0.226254,0.415082,0.039198,0.051601,-0.00557, + -0.838881,-0.160025,0.52026,0.039032,0.05267,-0.005434, + -0.893669,-0.170477,0.415082,0.038961,0.052657,-0.00557, + -0.865256,-0.281139,0.415082,0.0395,0.050561,-0.00557, + -0.81221,-0.263903,0.52026,0.039568,0.050584,-0.005434, + -0.827178,-0.212383,0.52026,0.039267,0.051619,-0.005434, + -0.865256,-0.281139,0.415082,0.0395,0.050561,-0.00557, + -0.827178,-0.212383,0.52026,0.039267,0.051619,-0.005434, + -0.881202,-0.226254,0.415082,0.039198,0.051601,-0.00557, + -0.845896,-0.334914,0.415082,0.039866,0.049543,-0.00557, + -0.794037,-0.314381,0.52026,0.039933,0.049569,-0.005434, + -0.81221,-0.263903,0.52026,0.039568,0.050584,-0.005434, + -0.845896,-0.334914,0.415082,0.039866,0.049543,-0.00557, + -0.81221,-0.263903,0.52026,0.039568,0.050584,-0.005434, + -0.865256,-0.281139,0.415082,0.0395,0.050561,-0.00557, + -0.823197,-0.387367,0.415082,0.040296,0.048549,-0.00557, + -0.77273,-0.363619,0.52026,0.040361,0.04858,-0.005434, + -0.794037,-0.314381,0.52026,0.039933,0.049569,-0.005434, + -0.823197,-0.387367,0.415082,0.040296,0.048549,-0.00557, + -0.794037,-0.314381,0.52026,0.039933,0.049569,-0.005434, + -0.845896,-0.334914,0.415082,0.039866,0.049543,-0.00557, + -0.79725,-0.438292,0.415082,0.040787,0.047585,-0.00557, + -0.748373,-0.411421,0.52026,0.04085,0.04762,-0.005434, + -0.77273,-0.363619,0.52026,0.040361,0.04858,-0.005434, + -0.79725,-0.438292,0.415082,0.040787,0.047585,-0.00557, + -0.77273,-0.363619,0.52026,0.040361,0.04858,-0.005434, + -0.823197,-0.387367,0.415082,0.040296,0.048549,-0.00557, + -0.768156,-0.487487,0.415082,0.041338,0.046653,-0.00557, + -0.721063,-0.4576,0.52026,0.041399,0.046692,-0.005434, + -0.748373,-0.411421,0.52026,0.04085,0.04762,-0.005434, + -0.768156,-0.487487,0.415082,0.041338,0.046653,-0.00557, + -0.748373,-0.411421,0.52026,0.04085,0.04762,-0.005434, + -0.79725,-0.438292,0.415082,0.040787,0.047585,-0.00557, + -0.736031,-0.534758,0.415082,0.041947,0.045758,-0.00557, + -0.690907,-0.501973,0.52026,0.042005,0.045801,-0.005434, + -0.721063,-0.4576,0.52026,0.041399,0.046692,-0.005434, + -0.736031,-0.534758,0.415082,0.041947,0.045758,-0.00557, + -0.721063,-0.4576,0.52026,0.041399,0.046692,-0.005434, + -0.768156,-0.487487,0.415082,0.041338,0.046653,-0.00557, + -0.701001,-0.579918,0.415082,0.04261,0.044903,-0.00557, + -0.658024,-0.544365,0.52026,0.042666,0.044949,-0.005434, + -0.690907,-0.501973,0.52026,0.042005,0.045801,-0.005434, + -0.701001,-0.579918,0.415082,0.04261,0.044903,-0.00557, + -0.690907,-0.501973,0.52026,0.042005,0.045801,-0.005434, + -0.736031,-0.534758,0.415082,0.041947,0.045758,-0.00557, + -0.663204,-0.62279,0.415082,0.043326,0.044091,-0.00557, + -0.622545,-0.584609,0.52026,0.043378,0.04414,-0.005434, + -0.658024,-0.544365,0.52026,0.042666,0.044949,-0.005434, + -0.663204,-0.62279,0.415082,0.043326,0.044091,-0.00557, + -0.658024,-0.544365,0.52026,0.042666,0.044949,-0.005434, + -0.701001,-0.579918,0.415082,0.04261,0.044903,-0.00557, + -0.62279,-0.663204,0.415082,0.044091,0.043326,-0.00557, + -0.584609,-0.622545,0.52026,0.04414,0.043378,-0.005434, + -0.622545,-0.584609,0.52026,0.043378,0.04414,-0.005434, + -0.62279,-0.663204,0.415082,0.044091,0.043326,-0.00557, + -0.622545,-0.584609,0.52026,0.043378,0.04414,-0.005434, + -0.663204,-0.62279,0.415082,0.043326,0.044091,-0.00557, + -0.579918,-0.701001,0.415082,0.044903,0.04261,-0.00557, + -0.544365,-0.658024,0.52026,0.044949,0.042666,-0.005434, + -0.584609,-0.622545,0.52026,0.04414,0.043378,-0.005434, + -0.579918,-0.701001,0.415082,0.044903,0.04261,-0.00557, + -0.584609,-0.622545,0.52026,0.04414,0.043378,-0.005434, + -0.62279,-0.663204,0.415082,0.044091,0.043326,-0.00557, + -0.534758,-0.736031,0.415082,0.045758,0.041947,-0.00557, + -0.501973,-0.690907,0.52026,0.045801,0.042005,-0.005434, + -0.544365,-0.658024,0.52026,0.044949,0.042666,-0.005434, + -0.534758,-0.736031,0.415082,0.045758,0.041947,-0.00557, + -0.544365,-0.658024,0.52026,0.044949,0.042666,-0.005434, + -0.579918,-0.701001,0.415082,0.044903,0.04261,-0.00557, + -0.487487,-0.768156,0.415082,0.046653,0.041338,-0.00557, + -0.4576,-0.721063,0.52026,0.046692,0.041399,-0.005434, + -0.501973,-0.690907,0.52026,0.045801,0.042005,-0.005434, + -0.487487,-0.768156,0.415082,0.046653,0.041338,-0.00557, + -0.501973,-0.690907,0.52026,0.045801,0.042005,-0.005434, + -0.534758,-0.736031,0.415082,0.045758,0.041947,-0.00557, + -0.438292,-0.79725,0.415082,0.047585,0.040787,-0.00557, + -0.411421,-0.748373,0.52026,0.04762,0.04085,-0.005434, + -0.4576,-0.721063,0.52026,0.046692,0.041399,-0.005434, + -0.438292,-0.79725,0.415082,0.047585,0.040787,-0.00557, + -0.4576,-0.721063,0.52026,0.046692,0.041399,-0.005434, + -0.487487,-0.768156,0.415082,0.046653,0.041338,-0.00557, + -0.387367,-0.823197,0.415082,0.048549,0.040296,-0.00557, + -0.363619,-0.77273,0.52026,0.04858,0.040361,-0.005434, + -0.411421,-0.748373,0.52026,0.04762,0.04085,-0.005434, + -0.387367,-0.823197,0.415082,0.048549,0.040296,-0.00557, + -0.411421,-0.748373,0.52026,0.04762,0.04085,-0.005434, + -0.438292,-0.79725,0.415082,0.047585,0.040787,-0.00557, + -0.334914,-0.845896,0.415082,0.049543,0.039866,-0.00557, + -0.314381,-0.794037,0.52026,0.049569,0.039933,-0.005434, + -0.363619,-0.77273,0.52026,0.04858,0.040361,-0.005434, + -0.334914,-0.845896,0.415082,0.049543,0.039866,-0.00557, + -0.363619,-0.77273,0.52026,0.04858,0.040361,-0.005434, + -0.387367,-0.823197,0.415082,0.048549,0.040296,-0.00557, + -0.281139,-0.865256,0.415082,0.050561,0.0395,-0.00557, + -0.263903,-0.81221,0.52026,0.050584,0.039568,-0.005434, + -0.314381,-0.794037,0.52026,0.049569,0.039933,-0.005434, + -0.281139,-0.865256,0.415082,0.050561,0.0395,-0.00557, + -0.314381,-0.794037,0.52026,0.049569,0.039933,-0.005434, + -0.334914,-0.845896,0.415082,0.049543,0.039866,-0.00557, + -0.226254,-0.881202,0.415082,0.051601,0.039198,-0.00557, + -0.212383,-0.827178,0.52026,0.051619,0.039267,-0.005434, + -0.263903,-0.81221,0.52026,0.050584,0.039568,-0.005434, + -0.226254,-0.881202,0.415082,0.051601,0.039198,-0.00557, + -0.263903,-0.81221,0.52026,0.050584,0.039568,-0.005434, + -0.281139,-0.865256,0.415082,0.050561,0.0395,-0.00557, + -0.170477,-0.893669,0.415082,0.052657,0.038961,-0.00557, + -0.160025,-0.838881,0.52026,0.05267,0.039032,-0.005434, + -0.212383,-0.827178,0.52026,0.051619,0.039267,-0.005434, + -0.170477,-0.893669,0.415082,0.052657,0.038961,-0.00557, + -0.212383,-0.827178,0.52026,0.051619,0.039267,-0.005434, + -0.226254,-0.881202,0.415082,0.051601,0.039198,-0.00557, + -0.114026,-0.90261,0.415082,0.053726,0.038792,-0.00557, + -0.107036,-0.847274,0.52026,0.053735,0.038863,-0.005434, + -0.160025,-0.838881,0.52026,0.05267,0.039032,-0.005434, + -0.114026,-0.90261,0.415082,0.053726,0.038792,-0.00557, + -0.160025,-0.838881,0.52026,0.05267,0.039032,-0.005434, + -0.170477,-0.893669,0.415082,0.052657,0.038961,-0.00557, + -0.057126,-0.907989,0.415082,0.054803,0.03869,-0.00557, + -0.053624,-0.852323,0.52026,0.054808,0.038762,-0.005434, + -0.107036,-0.847274,0.52026,0.053735,0.038863,-0.005434, + -0.057126,-0.907989,0.415082,0.054803,0.03869,-0.00557, + -0.107036,-0.847274,0.52026,0.053735,0.038863,-0.005434, + -0.114026,-0.90261,0.415082,0.053726,0.038792,-0.00557, + 0,-0.909784,0.415082,0.055885,0.038656,-0.00557, + 0,-0.854008,0.52026,0.055885,0.038728,-0.005434, + -0.053624,-0.852323,0.52026,0.054808,0.038762,-0.005434, + 0,-0.909784,0.415082,0.055885,0.038656,-0.00557, + -0.053624,-0.852323,0.52026,0.054808,0.038762,-0.005434, + -0.057126,-0.907989,0.415082,0.054803,0.03869,-0.00557, + 0.057126,-0.907989,0.415082,0.056967,0.03869,-0.00557, + 0.053624,-0.852323,0.52026,0.056963,0.038762,-0.005434, + 0,-0.854008,0.52026,0.055885,0.038728,-0.005434, + 0.057126,-0.907989,0.415082,0.056967,0.03869,-0.00557, + 0,-0.854008,0.52026,0.055885,0.038728,-0.005434, + 0,-0.909784,0.415082,0.055885,0.038656,-0.00557, + 0.114026,-0.90261,0.415082,0.058045,0.038792,-0.00557, + 0.107036,-0.847274,0.52026,0.058036,0.038863,-0.005434, + 0.053624,-0.852323,0.52026,0.056963,0.038762,-0.005434, + 0.114026,-0.90261,0.415082,0.058045,0.038792,-0.00557, + 0.053624,-0.852323,0.52026,0.056963,0.038762,-0.005434, + 0.057126,-0.907989,0.415082,0.056967,0.03869,-0.00557, + 0.170477,-0.893669,0.415082,0.059114,0.038961,-0.00557, + 0.160025,-0.838881,0.52026,0.0591,0.039032,-0.005434, + 0.107036,-0.847274,0.52026,0.058036,0.038863,-0.005434, + 0.170477,-0.893669,0.415082,0.059114,0.038961,-0.00557, + 0.107036,-0.847274,0.52026,0.058036,0.038863,-0.005434, + 0.114026,-0.90261,0.415082,0.058045,0.038792,-0.00557, + 0.226254,-0.881202,0.415082,0.06017,0.039198,-0.00557, + 0.212383,-0.827178,0.52026,0.060152,0.039267,-0.005434, + 0.160025,-0.838881,0.52026,0.0591,0.039032,-0.005434, + 0.226254,-0.881202,0.415082,0.06017,0.039198,-0.00557, + 0.160025,-0.838881,0.52026,0.0591,0.039032,-0.005434, + 0.170477,-0.893669,0.415082,0.059114,0.038961,-0.00557, + 0.281139,-0.865256,0.415082,0.061209,0.0395,-0.00557, + 0.263903,-0.81221,0.52026,0.061187,0.039568,-0.005434, + 0.212383,-0.827178,0.52026,0.060152,0.039267,-0.005434, + 0.281139,-0.865256,0.415082,0.061209,0.0395,-0.00557, + 0.212383,-0.827178,0.52026,0.060152,0.039267,-0.005434, + 0.226254,-0.881202,0.415082,0.06017,0.039198,-0.00557, + 0.334914,-0.845896,0.415082,0.062228,0.039866,-0.00557, + 0.314381,-0.794037,0.52026,0.062201,0.039933,-0.005434, + 0.263903,-0.81221,0.52026,0.061187,0.039568,-0.005434, + 0.334914,-0.845896,0.415082,0.062228,0.039866,-0.00557, + 0.263903,-0.81221,0.52026,0.061187,0.039568,-0.005434, + 0.281139,-0.865256,0.415082,0.061209,0.0395,-0.00557, + 0.387367,-0.823197,0.415082,0.063221,0.040296,-0.00557, + 0.363619,-0.77273,0.52026,0.06319,0.040361,-0.005434, + 0.314381,-0.794037,0.52026,0.062201,0.039933,-0.005434, + 0.387367,-0.823197,0.415082,0.063221,0.040296,-0.00557, + 0.314381,-0.794037,0.52026,0.062201,0.039933,-0.005434, + 0.334914,-0.845896,0.415082,0.062228,0.039866,-0.00557, + 0.438292,-0.79725,0.415082,0.064185,0.040787,-0.00557, + 0.411421,-0.748373,0.52026,0.064151,0.04085,-0.005434, + 0.363619,-0.77273,0.52026,0.06319,0.040361,-0.005434, + 0.438292,-0.79725,0.415082,0.064185,0.040787,-0.00557, + 0.363619,-0.77273,0.52026,0.06319,0.040361,-0.005434, + 0.387367,-0.823197,0.415082,0.063221,0.040296,-0.00557, + 0.487487,-0.768156,0.415082,0.065117,0.041338,-0.00557, + 0.4576,-0.721063,0.52026,0.065079,0.041399,-0.005434, + 0.411421,-0.748373,0.52026,0.064151,0.04085,-0.005434, + 0.487487,-0.768156,0.415082,0.065117,0.041338,-0.00557, + 0.411421,-0.748373,0.52026,0.064151,0.04085,-0.005434, + 0.438292,-0.79725,0.415082,0.064185,0.040787,-0.00557, + 0.534758,-0.736031,0.415082,0.066012,0.041947,-0.00557, + 0.501973,-0.690907,0.52026,0.06597,0.042005,-0.005434, + 0.4576,-0.721063,0.52026,0.065079,0.041399,-0.005434, + 0.534758,-0.736031,0.415082,0.066012,0.041947,-0.00557, + 0.4576,-0.721063,0.52026,0.065079,0.041399,-0.005434, + 0.487487,-0.768156,0.415082,0.065117,0.041338,-0.00557, + 0.579918,-0.701001,0.415082,0.066868,0.04261,-0.00557, + 0.544365,-0.658024,0.52026,0.066822,0.042666,-0.005434, + 0.501973,-0.690907,0.52026,0.06597,0.042005,-0.005434, + 0.579918,-0.701001,0.415082,0.066868,0.04261,-0.00557, + 0.501973,-0.690907,0.52026,0.06597,0.042005,-0.005434, + 0.534758,-0.736031,0.415082,0.066012,0.041947,-0.00557, + 0.62279,-0.663204,0.415082,0.067679,0.043326,-0.00557, + 0.584609,-0.622545,0.52026,0.06763,0.043378,-0.005434, + 0.544365,-0.658024,0.52026,0.066822,0.042666,-0.005434, + 0.62279,-0.663204,0.415082,0.067679,0.043326,-0.00557, + 0.544365,-0.658024,0.52026,0.066822,0.042666,-0.005434, + 0.579918,-0.701001,0.415082,0.066868,0.04261,-0.00557, + 0.663204,-0.62279,0.415082,0.068445,0.044091,-0.00557, + 0.622545,-0.584609,0.52026,0.068392,0.04414,-0.005434, + 0.584609,-0.622545,0.52026,0.06763,0.043378,-0.005434, + 0.663204,-0.62279,0.415082,0.068445,0.044091,-0.00557, + 0.584609,-0.622545,0.52026,0.06763,0.043378,-0.005434, + 0.62279,-0.663204,0.415082,0.067679,0.043326,-0.00557, + 0.701001,-0.579918,0.415082,0.069161,0.044903,-0.00557, + 0.658024,-0.544365,0.52026,0.069105,0.044949,-0.005434, + 0.622545,-0.584609,0.52026,0.068392,0.04414,-0.005434, + 0.701001,-0.579918,0.415082,0.069161,0.044903,-0.00557, + 0.622545,-0.584609,0.52026,0.068392,0.04414,-0.005434, + 0.663204,-0.62279,0.415082,0.068445,0.044091,-0.00557, + 0.736031,-0.534758,0.415082,0.069824,0.045758,-0.00557, + 0.690907,-0.501973,0.52026,0.069766,0.045801,-0.005434, + 0.658024,-0.544365,0.52026,0.069105,0.044949,-0.005434, + 0.736031,-0.534758,0.415082,0.069824,0.045758,-0.00557, + 0.658024,-0.544365,0.52026,0.069105,0.044949,-0.005434, + 0.701001,-0.579918,0.415082,0.069161,0.044903,-0.00557, + 0.768156,-0.487487,0.415082,0.070432,0.046653,-0.00557, + 0.721063,-0.4576,0.52026,0.070372,0.046692,-0.005434, + 0.690907,-0.501973,0.52026,0.069766,0.045801,-0.005434, + 0.768156,-0.487487,0.415082,0.070432,0.046653,-0.00557, + 0.690907,-0.501973,0.52026,0.069766,0.045801,-0.005434, + 0.736031,-0.534758,0.415082,0.069824,0.045758,-0.00557, + 0.79725,-0.438292,0.415082,0.070983,0.047585,-0.00557, + 0.748373,-0.411421,0.52026,0.07092,0.04762,-0.005434, + 0.721063,-0.4576,0.52026,0.070372,0.046692,-0.005434, + 0.79725,-0.438292,0.415082,0.070983,0.047585,-0.00557, + 0.721063,-0.4576,0.52026,0.070372,0.046692,-0.005434, + 0.768156,-0.487487,0.415082,0.070432,0.046653,-0.00557, + 0.823197,-0.387367,0.415082,0.071475,0.048549,-0.00557, + 0.77273,-0.363619,0.52026,0.07141,0.04858,-0.005434, + 0.748373,-0.411421,0.52026,0.07092,0.04762,-0.005434, + 0.823197,-0.387367,0.415082,0.071475,0.048549,-0.00557, + 0.748373,-0.411421,0.52026,0.07092,0.04762,-0.005434, + 0.79725,-0.438292,0.415082,0.070983,0.047585,-0.00557, + 0.845896,-0.334914,0.415082,0.071905,0.049543,-0.00557, + 0.794037,-0.314381,0.52026,0.071838,0.049569,-0.005434, + 0.77273,-0.363619,0.52026,0.07141,0.04858,-0.005434, + 0.845896,-0.334914,0.415082,0.071905,0.049543,-0.00557, + 0.77273,-0.363619,0.52026,0.07141,0.04858,-0.005434, + 0.823197,-0.387367,0.415082,0.071475,0.048549,-0.00557, + 0.865256,-0.281139,0.415082,0.072271,0.050561,-0.00557, + 0.81221,-0.263903,0.52026,0.072203,0.050584,-0.005434, + 0.794037,-0.314381,0.52026,0.071838,0.049569,-0.005434, + 0.865256,-0.281139,0.415082,0.072271,0.050561,-0.00557, + 0.794037,-0.314381,0.52026,0.071838,0.049569,-0.005434, + 0.845896,-0.334914,0.415082,0.071905,0.049543,-0.00557, + 0.881202,-0.226254,0.415082,0.072573,0.051601,-0.00557, + 0.827178,-0.212383,0.52026,0.072503,0.051619,-0.005434, + 0.81221,-0.263903,0.52026,0.072203,0.050584,-0.005434, + 0.881202,-0.226254,0.415082,0.072573,0.051601,-0.00557, + 0.81221,-0.263903,0.52026,0.072203,0.050584,-0.005434, + 0.865256,-0.281139,0.415082,0.072271,0.050561,-0.00557, + 0.893669,-0.170477,0.415082,0.072809,0.052657,-0.00557, + 0.838881,-0.160025,0.52026,0.072739,0.05267,-0.005434, + 0.827178,-0.212383,0.52026,0.072503,0.051619,-0.005434, + 0.893669,-0.170477,0.415082,0.072809,0.052657,-0.00557, + 0.827178,-0.212383,0.52026,0.072503,0.051619,-0.005434, + 0.881202,-0.226254,0.415082,0.072573,0.051601,-0.00557, + 0.90261,-0.114026,0.415082,0.072978,0.053726,-0.00557, + 0.847274,-0.107036,0.52026,0.072907,0.053735,-0.005434, + 0.838881,-0.160025,0.52026,0.072739,0.05267,-0.005434, + 0.90261,-0.114026,0.415082,0.072978,0.053726,-0.00557, + 0.838881,-0.160025,0.52026,0.072739,0.05267,-0.005434, + 0.893669,-0.170477,0.415082,0.072809,0.052657,-0.00557, + 0.907989,-0.057126,0.415082,0.07308,0.054803,-0.00557, + 0.852323,-0.053624,0.52026,0.073009,0.054808,-0.005434, + 0.847274,-0.107036,0.52026,0.072907,0.053735,-0.005434, + 0.907989,-0.057126,0.415082,0.07308,0.054803,-0.00557, + 0.847274,-0.107036,0.52026,0.072907,0.053735,-0.005434, + 0.90261,-0.114026,0.415082,0.072978,0.053726,-0.00557, + 0.909784,0,0.415082,0.073114,0.055885,-0.00557, + 0.854008,0,0.52026,0.073042,0.055885,-0.005434, + 0.852323,-0.053624,0.52026,0.073009,0.054808,-0.005434, + 0.909784,0,0.415082,0.073114,0.055885,-0.00557, + 0.852323,-0.053624,0.52026,0.073009,0.054808,-0.005434, + 0.907989,-0.057126,0.415082,0.07308,0.054803,-0.00557, + 0.907989,0.057126,0.415082,0.07308,0.056967,-0.00557, + 0.852323,0.053624,0.52026,0.073009,0.056963,-0.005434, + 0.854008,0,0.52026,0.073042,0.055885,-0.005434, + 0.907989,0.057126,0.415082,0.07308,0.056967,-0.00557, + 0.854008,0,0.52026,0.073042,0.055885,-0.005434, + 0.909784,0,0.415082,0.073114,0.055885,-0.00557, + 0.90261,0.114026,0.415082,0.072978,0.058045,-0.00557, + 0.847274,0.107036,0.52026,0.072907,0.058036,-0.005434, + 0.852323,0.053624,0.52026,0.073009,0.056963,-0.005434, + 0.90261,0.114026,0.415082,0.072978,0.058045,-0.00557, + 0.852323,0.053624,0.52026,0.073009,0.056963,-0.005434, + 0.907989,0.057126,0.415082,0.07308,0.056967,-0.00557, + 0.893669,0.170477,0.415082,0.072809,0.059114,-0.00557, + 0.838881,0.160025,0.52026,0.072739,0.0591,-0.005434, + 0.847274,0.107036,0.52026,0.072907,0.058036,-0.005434, + 0.893669,0.170477,0.415082,0.072809,0.059114,-0.00557, + 0.847274,0.107036,0.52026,0.072907,0.058036,-0.005434, + 0.90261,0.114026,0.415082,0.072978,0.058045,-0.00557, + 0.881202,0.226254,0.415082,0.072573,0.06017,-0.00557, + 0.827178,0.212383,0.52026,0.072503,0.060152,-0.005434, + 0.838881,0.160025,0.52026,0.072739,0.0591,-0.005434, + 0.881202,0.226254,0.415082,0.072573,0.06017,-0.00557, + 0.838881,0.160025,0.52026,0.072739,0.0591,-0.005434, + 0.893669,0.170477,0.415082,0.072809,0.059114,-0.00557, + 0.865256,0.281139,0.415082,0.072271,0.061209,-0.00557, + 0.81221,0.263903,0.52026,0.072203,0.061187,-0.005434, + 0.827178,0.212383,0.52026,0.072503,0.060152,-0.005434, + 0.865256,0.281139,0.415082,0.072271,0.061209,-0.00557, + 0.827178,0.212383,0.52026,0.072503,0.060152,-0.005434, + 0.881202,0.226254,0.415082,0.072573,0.06017,-0.00557, + 0.845896,0.334914,0.415082,0.071905,0.062228,-0.00557, + 0.794037,0.314381,0.52026,0.071838,0.062201,-0.005434, + 0.81221,0.263903,0.52026,0.072203,0.061187,-0.005434, + 0.845896,0.334914,0.415082,0.071905,0.062228,-0.00557, + 0.81221,0.263903,0.52026,0.072203,0.061187,-0.005434, + 0.865256,0.281139,0.415082,0.072271,0.061209,-0.00557, + 0.823197,0.387367,0.415082,0.071475,0.063221,-0.00557, + 0.77273,0.363619,0.52026,0.07141,0.06319,-0.005434, + 0.794037,0.314381,0.52026,0.071838,0.062201,-0.005434, + 0.823197,0.387367,0.415082,0.071475,0.063221,-0.00557, + 0.794037,0.314381,0.52026,0.071838,0.062201,-0.005434, + 0.845896,0.334914,0.415082,0.071905,0.062228,-0.00557, + 0.79725,0.438292,0.415082,0.070983,0.064185,-0.00557, + 0.748373,0.411421,0.52026,0.07092,0.064151,-0.005434, + 0.77273,0.363619,0.52026,0.07141,0.06319,-0.005434, + 0.79725,0.438292,0.415082,0.070983,0.064185,-0.00557, + 0.77273,0.363619,0.52026,0.07141,0.06319,-0.005434, + 0.823197,0.387367,0.415082,0.071475,0.063221,-0.00557, + 0.768156,0.487487,0.415082,0.070432,0.065117,-0.00557, + 0.721063,0.4576,0.52026,0.070372,0.065079,-0.005434, + 0.748373,0.411421,0.52026,0.07092,0.064151,-0.005434, + 0.768156,0.487487,0.415082,0.070432,0.065117,-0.00557, + 0.748373,0.411421,0.52026,0.07092,0.064151,-0.005434, + 0.79725,0.438292,0.415082,0.070983,0.064185,-0.00557, + 0.736031,0.534758,0.415082,0.069824,0.066012,-0.00557, + 0.690907,0.501973,0.52026,0.069766,0.06597,-0.005434, + 0.721063,0.4576,0.52026,0.070372,0.065079,-0.005434, + 0.736031,0.534758,0.415082,0.069824,0.066012,-0.00557, + 0.721063,0.4576,0.52026,0.070372,0.065079,-0.005434, + 0.768156,0.487487,0.415082,0.070432,0.065117,-0.00557, + 0.701001,0.579918,0.415082,0.069161,0.066868,-0.00557, + 0.658024,0.544365,0.52026,0.069105,0.066822,-0.005434, + 0.690907,0.501973,0.52026,0.069766,0.06597,-0.005434, + 0.701001,0.579918,0.415082,0.069161,0.066868,-0.00557, + 0.690907,0.501973,0.52026,0.069766,0.06597,-0.005434, + 0.736031,0.534758,0.415082,0.069824,0.066012,-0.00557, + 0.663204,0.62279,0.415082,0.068445,0.067679,-0.00557, + 0.622545,0.584609,0.52026,0.068392,0.06763,-0.005434, + 0.658024,0.544365,0.52026,0.069105,0.066822,-0.005434, + 0.663204,0.62279,0.415082,0.068445,0.067679,-0.00557, + 0.658024,0.544365,0.52026,0.069105,0.066822,-0.005434, + 0.701001,0.579918,0.415082,0.069161,0.066868,-0.00557, + 0.62279,0.663204,0.415082,0.067679,0.068445,-0.00557, + 0.584609,0.622545,0.52026,0.06763,0.068392,-0.005434, + 0.622545,0.584609,0.52026,0.068392,0.06763,-0.005434, + 0.62279,0.663204,0.415082,0.067679,0.068445,-0.00557, + 0.622545,0.584609,0.52026,0.068392,0.06763,-0.005434, + 0.663204,0.62279,0.415082,0.068445,0.067679,-0.00557, + 0.579918,0.701001,0.415082,0.066868,0.069161,-0.00557, + 0.544365,0.658024,0.52026,0.066822,0.069105,-0.005434, + 0.584609,0.622545,0.52026,0.06763,0.068392,-0.005434, + 0.579918,0.701001,0.415082,0.066868,0.069161,-0.00557, + 0.584609,0.622545,0.52026,0.06763,0.068392,-0.005434, + 0.62279,0.663204,0.415082,0.067679,0.068445,-0.00557, + 0.534758,0.736031,0.415082,0.066012,0.069824,-0.00557, + 0.501973,0.690907,0.52026,0.06597,0.069766,-0.005434, + 0.544365,0.658024,0.52026,0.066822,0.069105,-0.005434, + 0.534758,0.736031,0.415082,0.066012,0.069824,-0.00557, + 0.544365,0.658024,0.52026,0.066822,0.069105,-0.005434, + 0.579918,0.701001,0.415082,0.066868,0.069161,-0.00557, + 0.487487,0.768156,0.415082,0.065117,0.070432,-0.00557, + 0.4576,0.721063,0.52026,0.065079,0.070372,-0.005434, + 0.501973,0.690907,0.52026,0.06597,0.069766,-0.005434, + 0.487487,0.768156,0.415082,0.065117,0.070432,-0.00557, + 0.501973,0.690907,0.52026,0.06597,0.069766,-0.005434, + 0.534758,0.736031,0.415082,0.066012,0.069824,-0.00557, + 0.438292,0.79725,0.415082,0.064185,0.070983,-0.00557, + 0.411421,0.748373,0.52026,0.064151,0.07092,-0.005434, + 0.4576,0.721063,0.52026,0.065079,0.070372,-0.005434, + 0.438292,0.79725,0.415082,0.064185,0.070983,-0.00557, + 0.4576,0.721063,0.52026,0.065079,0.070372,-0.005434, + 0.487487,0.768156,0.415082,0.065117,0.070432,-0.00557, + 0.387367,0.823197,0.415082,0.063221,0.071475,-0.00557, + 0.363619,0.77273,0.52026,0.06319,0.07141,-0.005434, + 0.411421,0.748373,0.52026,0.064151,0.07092,-0.005434, + 0.387367,0.823197,0.415082,0.063221,0.071475,-0.00557, + 0.411421,0.748373,0.52026,0.064151,0.07092,-0.005434, + 0.438292,0.79725,0.415082,0.064185,0.070983,-0.00557, + 0.334914,0.845896,0.415082,0.062228,0.071905,-0.00557, + 0.314381,0.794037,0.52026,0.062201,0.071838,-0.005434, + 0.363619,0.77273,0.52026,0.06319,0.07141,-0.005434, + 0.334914,0.845896,0.415082,0.062228,0.071905,-0.00557, + 0.363619,0.77273,0.52026,0.06319,0.07141,-0.005434, + 0.387367,0.823197,0.415082,0.063221,0.071475,-0.00557, + 0.281139,0.865256,0.415082,0.061209,0.072271,-0.00557, + 0.263903,0.81221,0.52026,0.061187,0.072203,-0.005434, + 0.314381,0.794037,0.52026,0.062201,0.071838,-0.005434, + 0.281139,0.865256,0.415082,0.061209,0.072271,-0.00557, + 0.314381,0.794037,0.52026,0.062201,0.071838,-0.005434, + 0.334914,0.845896,0.415082,0.062228,0.071905,-0.00557, + 0.226254,0.881202,0.415082,0.06017,0.072573,-0.00557, + 0.212383,0.827178,0.52026,0.060152,0.072503,-0.005434, + 0.263903,0.81221,0.52026,0.061187,0.072203,-0.005434, + 0.226254,0.881202,0.415082,0.06017,0.072573,-0.00557, + 0.263903,0.81221,0.52026,0.061187,0.072203,-0.005434, + 0.281139,0.865256,0.415082,0.061209,0.072271,-0.00557, + 0.170477,0.893669,0.415082,0.059114,0.072809,-0.00557, + 0.160025,0.838881,0.52026,0.0591,0.072739,-0.005434, + 0.212383,0.827178,0.52026,0.060152,0.072503,-0.005434, + 0.170477,0.893669,0.415082,0.059114,0.072809,-0.00557, + 0.212383,0.827178,0.52026,0.060152,0.072503,-0.005434, + 0.226254,0.881202,0.415082,0.06017,0.072573,-0.00557, + 0.114026,0.90261,0.415082,0.058045,0.072978,-0.00557, + 0.107036,0.847274,0.52026,0.058036,0.072907,-0.005434, + 0.160025,0.838881,0.52026,0.0591,0.072739,-0.005434, + 0.114026,0.90261,0.415082,0.058045,0.072978,-0.00557, + 0.160025,0.838881,0.52026,0.0591,0.072739,-0.005434, + 0.170477,0.893669,0.415082,0.059114,0.072809,-0.00557, + 0.057126,0.907989,0.415082,0.056967,0.07308,-0.00557, + 0.053624,0.852323,0.52026,0.056963,0.073009,-0.005434, + 0.107036,0.847274,0.52026,0.058036,0.072907,-0.005434, + 0.057126,0.907989,0.415082,0.056967,0.07308,-0.00557, + 0.107036,0.847274,0.52026,0.058036,0.072907,-0.005434, + 0.114026,0.90261,0.415082,0.058045,0.072978,-0.00557, + 0,0.909784,0.415082,0.055885,0.073114,-0.00557, + 0,0.854008,0.52026,0.055885,0.073042,-0.005434, + 0.053624,0.852323,0.52026,0.056963,0.073009,-0.005434, + 0,0.909784,0.415082,0.055885,0.073114,-0.00557, + 0.053624,0.852323,0.52026,0.056963,0.073009,-0.005434, + 0.057126,0.907989,0.415082,0.056967,0.07308,-0.00557, + -0.057126,0.907989,0.415082,0.054803,0.07308,-0.00557, + -0.053624,0.852323,0.52026,0.054808,0.073009,-0.005434, + 0,0.854008,0.52026,0.055885,0.073042,-0.005434, + -0.057126,0.907989,0.415082,0.054803,0.07308,-0.00557, + 0,0.854008,0.52026,0.055885,0.073042,-0.005434, + 0,0.909784,0.415082,0.055885,0.073114,-0.00557, + -0.114026,0.90261,0.415082,0.053726,0.072978,-0.00557, + -0.107036,0.847274,0.52026,0.053735,0.072907,-0.005434, + -0.053624,0.852323,0.52026,0.054808,0.073009,-0.005434, + -0.114026,0.90261,0.415082,0.053726,0.072978,-0.00557, + -0.053624,0.852323,0.52026,0.054808,0.073009,-0.005434, + -0.057126,0.907989,0.415082,0.054803,0.07308,-0.00557, + -0.170477,0.893669,0.415082,0.052657,0.072809,-0.00557, + -0.160025,0.838881,0.52026,0.05267,0.072739,-0.005434, + -0.107036,0.847274,0.52026,0.053735,0.072907,-0.005434, + -0.170477,0.893669,0.415082,0.052657,0.072809,-0.00557, + -0.107036,0.847274,0.52026,0.053735,0.072907,-0.005434, + -0.114026,0.90261,0.415082,0.053726,0.072978,-0.00557, + -0.226254,0.881202,0.415082,0.051601,0.072573,-0.00557, + -0.212383,0.827178,0.52026,0.051619,0.072503,-0.005434, + -0.160025,0.838881,0.52026,0.05267,0.072739,-0.005434, + -0.226254,0.881202,0.415082,0.051601,0.072573,-0.00557, + -0.160025,0.838881,0.52026,0.05267,0.072739,-0.005434, + -0.170477,0.893669,0.415082,0.052657,0.072809,-0.00557, + -0.281139,0.865256,0.415082,0.050561,0.072271,-0.00557, + -0.263903,0.81221,0.52026,0.050584,0.072203,-0.005434, + -0.212383,0.827178,0.52026,0.051619,0.072503,-0.005434, + -0.281139,0.865256,0.415082,0.050561,0.072271,-0.00557, + -0.212383,0.827178,0.52026,0.051619,0.072503,-0.005434, + -0.226254,0.881202,0.415082,0.051601,0.072573,-0.00557, + -0.334914,0.845896,0.415082,0.049543,0.071905,-0.00557, + -0.314381,0.794037,0.52026,0.049569,0.071838,-0.005434, + -0.263903,0.81221,0.52026,0.050584,0.072203,-0.005434, + -0.334914,0.845896,0.415082,0.049543,0.071905,-0.00557, + -0.263903,0.81221,0.52026,0.050584,0.072203,-0.005434, + -0.281139,0.865256,0.415082,0.050561,0.072271,-0.00557, + -0.387367,0.823197,0.415082,0.048549,0.071475,-0.00557, + -0.363619,0.77273,0.52026,0.04858,0.07141,-0.005434, + -0.314381,0.794037,0.52026,0.049569,0.071838,-0.005434, + -0.387367,0.823197,0.415082,0.048549,0.071475,-0.00557, + -0.314381,0.794037,0.52026,0.049569,0.071838,-0.005434, + -0.334914,0.845896,0.415082,0.049543,0.071905,-0.00557, + -0.438292,0.79725,0.415082,0.047585,0.070983,-0.00557, + -0.411421,0.748373,0.52026,0.04762,0.07092,-0.005434, + -0.363619,0.77273,0.52026,0.04858,0.07141,-0.005434, + -0.438292,0.79725,0.415082,0.047585,0.070983,-0.00557, + -0.363619,0.77273,0.52026,0.04858,0.07141,-0.005434, + -0.387367,0.823197,0.415082,0.048549,0.071475,-0.00557, + -0.487487,0.768156,0.415082,0.046653,0.070432,-0.00557, + -0.4576,0.721063,0.52026,0.046692,0.070372,-0.005434, + -0.411421,0.748373,0.52026,0.04762,0.07092,-0.005434, + -0.487487,0.768156,0.415082,0.046653,0.070432,-0.00557, + -0.411421,0.748373,0.52026,0.04762,0.07092,-0.005434, + -0.438292,0.79725,0.415082,0.047585,0.070983,-0.00557, + -0.534758,0.736031,0.415082,0.045758,0.069824,-0.00557, + -0.501973,0.690907,0.52026,0.045801,0.069766,-0.005434, + -0.4576,0.721063,0.52026,0.046692,0.070372,-0.005434, + -0.534758,0.736031,0.415082,0.045758,0.069824,-0.00557, + -0.4576,0.721063,0.52026,0.046692,0.070372,-0.005434, + -0.487487,0.768156,0.415082,0.046653,0.070432,-0.00557, + -0.579918,0.701001,0.415082,0.044903,0.069161,-0.00557, + -0.544365,0.658024,0.52026,0.044949,0.069105,-0.005434, + -0.501973,0.690907,0.52026,0.045801,0.069766,-0.005434, + -0.579918,0.701001,0.415082,0.044903,0.069161,-0.00557, + -0.501973,0.690907,0.52026,0.045801,0.069766,-0.005434, + -0.534758,0.736031,0.415082,0.045758,0.069824,-0.00557, + -0.62279,0.663204,0.415082,0.044091,0.068445,-0.00557, + -0.584609,0.622545,0.52026,0.04414,0.068392,-0.005434, + -0.544365,0.658024,0.52026,0.044949,0.069105,-0.005434, + -0.62279,0.663204,0.415082,0.044091,0.068445,-0.00557, + -0.544365,0.658024,0.52026,0.044949,0.069105,-0.005434, + -0.579918,0.701001,0.415082,0.044903,0.069161,-0.00557, + -0.663204,0.62279,0.415082,0.043326,0.067679,-0.00557, + -0.622545,0.584609,0.52026,0.043378,0.06763,-0.005434, + -0.584609,0.622545,0.52026,0.04414,0.068392,-0.005434, + -0.663204,0.62279,0.415082,0.043326,0.067679,-0.00557, + -0.584609,0.622545,0.52026,0.04414,0.068392,-0.005434, + -0.62279,0.663204,0.415082,0.044091,0.068445,-0.00557, + -0.701001,0.579918,0.415082,0.04261,0.066868,-0.00557, + -0.658024,0.544365,0.52026,0.042666,0.066822,-0.005434, + -0.622545,0.584609,0.52026,0.043378,0.06763,-0.005434, + -0.701001,0.579918,0.415082,0.04261,0.066868,-0.00557, + -0.622545,0.584609,0.52026,0.043378,0.06763,-0.005434, + -0.663204,0.62279,0.415082,0.043326,0.067679,-0.00557, + -0.736031,0.534758,0.415082,0.041947,0.066012,-0.00557, + -0.690907,0.501973,0.52026,0.042005,0.06597,-0.005434, + -0.658024,0.544365,0.52026,0.042666,0.066822,-0.005434, + -0.736031,0.534758,0.415082,0.041947,0.066012,-0.00557, + -0.658024,0.544365,0.52026,0.042666,0.066822,-0.005434, + -0.701001,0.579918,0.415082,0.04261,0.066868,-0.00557, + -0.768156,0.487487,0.415082,0.041338,0.065117,-0.00557, + -0.721063,0.4576,0.52026,0.041399,0.065079,-0.005434, + -0.690907,0.501973,0.52026,0.042005,0.06597,-0.005434, + -0.768156,0.487487,0.415082,0.041338,0.065117,-0.00557, + -0.690907,0.501973,0.52026,0.042005,0.06597,-0.005434, + -0.736031,0.534758,0.415082,0.041947,0.066012,-0.00557, + -0.79725,0.438292,0.415082,0.040787,0.064185,-0.00557, + -0.748373,0.411421,0.52026,0.04085,0.064151,-0.005434, + -0.721063,0.4576,0.52026,0.041399,0.065079,-0.005434, + -0.79725,0.438292,0.415082,0.040787,0.064185,-0.00557, + -0.721063,0.4576,0.52026,0.041399,0.065079,-0.005434, + -0.768156,0.487487,0.415082,0.041338,0.065117,-0.00557, + -0.823197,0.387367,0.415082,0.040296,0.063221,-0.00557, + -0.77273,0.363619,0.52026,0.040361,0.06319,-0.005434, + -0.748373,0.411421,0.52026,0.04085,0.064151,-0.005434, + -0.823197,0.387367,0.415082,0.040296,0.063221,-0.00557, + -0.748373,0.411421,0.52026,0.04085,0.064151,-0.005434, + -0.79725,0.438292,0.415082,0.040787,0.064185,-0.00557, + -0.845896,0.334914,0.415082,0.039866,0.062228,-0.00557, + -0.794037,0.314381,0.52026,0.039933,0.062201,-0.005434, + -0.77273,0.363619,0.52026,0.040361,0.06319,-0.005434, + -0.845896,0.334914,0.415082,0.039866,0.062228,-0.00557, + -0.77273,0.363619,0.52026,0.040361,0.06319,-0.005434, + -0.823197,0.387367,0.415082,0.040296,0.063221,-0.00557, + -0.865256,0.281139,0.415082,0.0395,0.061209,-0.00557, + -0.81221,0.263903,0.52026,0.039568,0.061187,-0.005434, + -0.794037,0.314381,0.52026,0.039933,0.062201,-0.005434, + -0.865256,0.281139,0.415082,0.0395,0.061209,-0.00557, + -0.794037,0.314381,0.52026,0.039933,0.062201,-0.005434, + -0.845896,0.334914,0.415082,0.039866,0.062228,-0.00557, + -0.881202,0.226254,0.415082,0.039198,0.06017,-0.00557, + -0.827178,0.212383,0.52026,0.039267,0.060152,-0.005434, + -0.81221,0.263903,0.52026,0.039568,0.061187,-0.005434, + -0.881202,0.226254,0.415082,0.039198,0.06017,-0.00557, + -0.81221,0.263903,0.52026,0.039568,0.061187,-0.005434, + -0.865256,0.281139,0.415082,0.0395,0.061209,-0.00557, + -0.893669,0.170477,0.415082,0.038961,0.059114,-0.00557, + -0.838881,0.160025,0.52026,0.039032,0.0591,-0.005434, + -0.827178,0.212383,0.52026,0.039267,0.060152,-0.005434, + -0.893669,0.170477,0.415082,0.038961,0.059114,-0.00557, + -0.827178,0.212383,0.52026,0.039267,0.060152,-0.005434, + -0.881202,0.226254,0.415082,0.039198,0.06017,-0.00557, + -0.90261,0.114026,0.415082,0.038792,0.058045,-0.00557, + -0.847274,0.107036,0.52026,0.038863,0.058036,-0.005434, + -0.838881,0.160025,0.52026,0.039032,0.0591,-0.005434, + -0.90261,0.114026,0.415082,0.038792,0.058045,-0.00557, + -0.838881,0.160025,0.52026,0.039032,0.0591,-0.005434, + -0.893669,0.170477,0.415082,0.038961,0.059114,-0.00557, + -0.907989,0.057126,0.415082,0.03869,0.056967,-0.00557, + -0.852323,0.053624,0.52026,0.038762,0.056963,-0.005434, + -0.847274,0.107036,0.52026,0.038863,0.058036,-0.005434, + -0.907989,0.057126,0.415082,0.03869,0.056967,-0.00557, + -0.847274,0.107036,0.52026,0.038863,0.058036,-0.005434, + -0.90261,0.114026,0.415082,0.038792,0.058045,-0.00557, + -0.909784,0,0.415082,0.038656,0.055885,-0.00557, + -0.854008,0,0.52026,0.038728,0.055885,-0.005434, + -0.852323,0.053624,0.52026,0.038762,0.056963,-0.005434, + -0.909784,0,0.415082,0.038656,0.055885,-0.00557, + -0.852323,0.053624,0.52026,0.038762,0.056963,-0.005434, + -0.907989,0.057126,0.415082,0.03869,0.056967,-0.00557, + -0.907989,-0.057126,0.415082,0.03869,0.054803,-0.00557, + -0.852323,-0.053624,0.52026,0.038762,0.054808,-0.005434, + -0.854008,0,0.52026,0.038728,0.055885,-0.005434, + -0.907989,-0.057126,0.415082,0.03869,0.054803,-0.00557, + -0.854008,0,0.52026,0.038728,0.055885,-0.005434, + -0.909784,0,0.415082,0.038656,0.055885,-0.00557, + -0.90261,-0.114026,0.415082,0.038792,0.053726,-0.00557, + -0.847274,-0.107036,0.52026,0.038863,0.053735,-0.005434, + -0.852323,-0.053624,0.52026,0.038762,0.054808,-0.005434, + -0.90261,-0.114026,0.415082,0.038792,0.053726,-0.00557, + -0.852323,-0.053624,0.52026,0.038762,0.054808,-0.005434, + -0.907989,-0.057126,0.415082,0.03869,0.054803,-0.00557, + -0.847274,-0.107036,0.52026,0.038863,0.053735,-0.005434, + -0.779929,-0.098528,0.618064,0.03895,0.053746,-0.005308, + -0.784577,-0.049361,0.618064,0.038849,0.054813,-0.005308, + -0.847274,-0.107036,0.52026,0.038863,0.053735,-0.005434, + -0.784577,-0.049361,0.618064,0.038849,0.054813,-0.005308, + -0.852323,-0.053624,0.52026,0.038762,0.054808,-0.005434, + -0.838881,-0.160025,0.52026,0.039032,0.05267,-0.005434, + -0.772203,-0.147306,0.618064,0.039118,0.052687,-0.005308, + -0.779929,-0.098528,0.618064,0.03895,0.053746,-0.005308, + -0.838881,-0.160025,0.52026,0.039032,0.05267,-0.005434, + -0.779929,-0.098528,0.618064,0.03895,0.053746,-0.005308, + -0.847274,-0.107036,0.52026,0.038863,0.053735,-0.005434, + -0.827178,-0.212383,0.52026,0.039267,0.051619,-0.005434, + -0.76143,-0.195502,0.618064,0.039352,0.05164,-0.005308, + -0.772203,-0.147306,0.618064,0.039118,0.052687,-0.005308, + -0.827178,-0.212383,0.52026,0.039267,0.051619,-0.005434, + -0.772203,-0.147306,0.618064,0.039118,0.052687,-0.005308, + -0.838881,-0.160025,0.52026,0.039032,0.05267,-0.005434, + -0.81221,-0.263903,0.52026,0.039568,0.050584,-0.005434, + -0.747652,-0.242927,0.618064,0.039651,0.05061,-0.005308, + -0.76143,-0.195502,0.618064,0.039352,0.05164,-0.005308, + -0.81221,-0.263903,0.52026,0.039568,0.050584,-0.005434, + -0.76143,-0.195502,0.618064,0.039352,0.05164,-0.005308, + -0.827178,-0.212383,0.52026,0.039267,0.051619,-0.005434, + -0.794037,-0.314381,0.52026,0.039933,0.049569,-0.005434, + -0.730923,-0.289393,0.618064,0.040014,0.049601,-0.005308, + -0.747652,-0.242927,0.618064,0.039651,0.05061,-0.005308, + -0.794037,-0.314381,0.52026,0.039933,0.049569,-0.005434, + -0.747652,-0.242927,0.618064,0.039651,0.05061,-0.005308, + -0.81221,-0.263903,0.52026,0.039568,0.050584,-0.005434, + -0.77273,-0.363619,0.52026,0.040361,0.04858,-0.005434, + -0.71131,-0.334717,0.618064,0.04044,0.048617,-0.005308, + -0.730923,-0.289393,0.618064,0.040014,0.049601,-0.005308, + -0.77273,-0.363619,0.52026,0.040361,0.04858,-0.005434, + -0.730923,-0.289393,0.618064,0.040014,0.049601,-0.005308, + -0.794037,-0.314381,0.52026,0.039933,0.049569,-0.005434, + -0.748373,-0.411421,0.52026,0.04085,0.04762,-0.005434, + -0.688889,-0.37872,0.618064,0.040927,0.047662,-0.005308, + -0.71131,-0.334717,0.618064,0.04044,0.048617,-0.005308, + -0.748373,-0.411421,0.52026,0.04085,0.04762,-0.005434, + -0.71131,-0.334717,0.618064,0.04044,0.048617,-0.005308, + -0.77273,-0.363619,0.52026,0.040361,0.04858,-0.005434, + -0.721063,-0.4576,0.52026,0.041399,0.046692,-0.005434, + -0.66375,-0.421228,0.618064,0.041473,0.046739,-0.005308, + -0.688889,-0.37872,0.618064,0.040927,0.047662,-0.005308, + -0.721063,-0.4576,0.52026,0.041399,0.046692,-0.005434, + -0.688889,-0.37872,0.618064,0.040927,0.047662,-0.005308, + -0.748373,-0.411421,0.52026,0.04085,0.04762,-0.005434, + -0.690907,-0.501973,0.52026,0.042005,0.045801,-0.005434, + -0.635991,-0.462074,0.618064,0.042076,0.045852,-0.005308, + -0.66375,-0.421228,0.618064,0.041473,0.046739,-0.005308, + -0.690907,-0.501973,0.52026,0.042005,0.045801,-0.005434, + -0.66375,-0.421228,0.618064,0.041473,0.046739,-0.005308, + -0.721063,-0.4576,0.52026,0.041399,0.046692,-0.005434, + -0.658024,-0.544365,0.52026,0.042666,0.044949,-0.005434, + -0.605722,-0.501097,0.618064,0.042733,0.045005,-0.005308, + -0.635991,-0.462074,0.618064,0.042076,0.045852,-0.005308, + -0.658024,-0.544365,0.52026,0.042666,0.044949,-0.005434, + -0.635991,-0.462074,0.618064,0.042076,0.045852,-0.005308, + -0.690907,-0.501973,0.52026,0.042005,0.045801,-0.005434, + -0.622545,-0.584609,0.52026,0.043378,0.04414,-0.005434, + -0.573062,-0.538141,0.618064,0.043442,0.0442,-0.005308, + -0.605722,-0.501097,0.618064,0.042733,0.045005,-0.005308, + -0.622545,-0.584609,0.52026,0.043378,0.04414,-0.005434, + -0.605722,-0.501097,0.618064,0.042733,0.045005,-0.005308, + -0.658024,-0.544365,0.52026,0.042666,0.044949,-0.005434, + -0.584609,-0.622545,0.52026,0.04414,0.043378,-0.005434, + -0.538141,-0.573062,0.618064,0.0442,0.043442,-0.005308, + -0.573062,-0.538141,0.618064,0.043442,0.0442,-0.005308, + -0.584609,-0.622545,0.52026,0.04414,0.043378,-0.005434, + -0.573062,-0.538141,0.618064,0.043442,0.0442,-0.005308, + -0.622545,-0.584609,0.52026,0.043378,0.04414,-0.005434, + -0.544365,-0.658024,0.52026,0.044949,0.042666,-0.005434, + -0.501097,-0.605722,0.618064,0.045005,0.042733,-0.005308, + -0.538141,-0.573062,0.618064,0.0442,0.043442,-0.005308, + -0.544365,-0.658024,0.52026,0.044949,0.042666,-0.005434, + -0.538141,-0.573062,0.618064,0.0442,0.043442,-0.005308, + -0.584609,-0.622545,0.52026,0.04414,0.043378,-0.005434, + -0.501973,-0.690907,0.52026,0.045801,0.042005,-0.005434, + -0.462074,-0.635991,0.618064,0.045852,0.042076,-0.005308, + -0.501097,-0.605722,0.618064,0.045005,0.042733,-0.005308, + -0.501973,-0.690907,0.52026,0.045801,0.042005,-0.005434, + -0.501097,-0.605722,0.618064,0.045005,0.042733,-0.005308, + -0.544365,-0.658024,0.52026,0.044949,0.042666,-0.005434, + -0.4576,-0.721063,0.52026,0.046692,0.041399,-0.005434, + -0.421228,-0.66375,0.618064,0.046739,0.041473,-0.005308, + -0.462074,-0.635991,0.618064,0.045852,0.042076,-0.005308, + -0.4576,-0.721063,0.52026,0.046692,0.041399,-0.005434, + -0.462074,-0.635991,0.618064,0.045852,0.042076,-0.005308, + -0.501973,-0.690907,0.52026,0.045801,0.042005,-0.005434, + -0.411421,-0.748373,0.52026,0.04762,0.04085,-0.005434, + -0.37872,-0.688889,0.618064,0.047662,0.040927,-0.005308, + -0.421228,-0.66375,0.618064,0.046739,0.041473,-0.005308, + -0.411421,-0.748373,0.52026,0.04762,0.04085,-0.005434, + -0.421228,-0.66375,0.618064,0.046739,0.041473,-0.005308, + -0.4576,-0.721063,0.52026,0.046692,0.041399,-0.005434, + -0.363619,-0.77273,0.52026,0.04858,0.040361,-0.005434, + -0.334717,-0.71131,0.618064,0.048617,0.04044,-0.005308, + -0.37872,-0.688889,0.618064,0.047662,0.040927,-0.005308, + -0.363619,-0.77273,0.52026,0.04858,0.040361,-0.005434, + -0.37872,-0.688889,0.618064,0.047662,0.040927,-0.005308, + -0.411421,-0.748373,0.52026,0.04762,0.04085,-0.005434, + -0.314381,-0.794037,0.52026,0.049569,0.039933,-0.005434, + -0.289393,-0.730923,0.618064,0.049601,0.040014,-0.005308, + -0.334717,-0.71131,0.618064,0.048617,0.04044,-0.005308, + -0.314381,-0.794037,0.52026,0.049569,0.039933,-0.005434, + -0.334717,-0.71131,0.618064,0.048617,0.04044,-0.005308, + -0.363619,-0.77273,0.52026,0.04858,0.040361,-0.005434, + -0.263903,-0.81221,0.52026,0.050584,0.039568,-0.005434, + -0.242927,-0.747652,0.618064,0.05061,0.039651,-0.005308, + -0.289393,-0.730923,0.618064,0.049601,0.040014,-0.005308, + -0.263903,-0.81221,0.52026,0.050584,0.039568,-0.005434, + -0.289393,-0.730923,0.618064,0.049601,0.040014,-0.005308, + -0.314381,-0.794037,0.52026,0.049569,0.039933,-0.005434, + -0.212383,-0.827178,0.52026,0.051619,0.039267,-0.005434, + -0.195502,-0.76143,0.618064,0.05164,0.039352,-0.005308, + -0.242927,-0.747652,0.618064,0.05061,0.039651,-0.005308, + -0.212383,-0.827178,0.52026,0.051619,0.039267,-0.005434, + -0.242927,-0.747652,0.618064,0.05061,0.039651,-0.005308, + -0.263903,-0.81221,0.52026,0.050584,0.039568,-0.005434, + -0.160025,-0.838881,0.52026,0.05267,0.039032,-0.005434, + -0.147306,-0.772203,0.618064,0.052687,0.039118,-0.005308, + -0.195502,-0.76143,0.618064,0.05164,0.039352,-0.005308, + -0.160025,-0.838881,0.52026,0.05267,0.039032,-0.005434, + -0.195502,-0.76143,0.618064,0.05164,0.039352,-0.005308, + -0.212383,-0.827178,0.52026,0.051619,0.039267,-0.005434, + -0.107036,-0.847274,0.52026,0.053735,0.038863,-0.005434, + -0.098528,-0.779929,0.618064,0.053746,0.03895,-0.005308, + -0.147306,-0.772203,0.618064,0.052687,0.039118,-0.005308, + -0.107036,-0.847274,0.52026,0.053735,0.038863,-0.005434, + -0.147306,-0.772203,0.618064,0.052687,0.039118,-0.005308, + -0.160025,-0.838881,0.52026,0.05267,0.039032,-0.005434, + -0.053624,-0.852323,0.52026,0.054808,0.038762,-0.005434, + -0.049361,-0.784577,0.618064,0.054813,0.038849,-0.005308, + -0.098528,-0.779929,0.618064,0.053746,0.03895,-0.005308, + -0.053624,-0.852323,0.52026,0.054808,0.038762,-0.005434, + -0.098528,-0.779929,0.618064,0.053746,0.03895,-0.005308, + -0.107036,-0.847274,0.52026,0.053735,0.038863,-0.005434, + 0,-0.854008,0.52026,0.055885,0.038728,-0.005434, + 0,-0.786128,0.618064,0.055885,0.038816,-0.005308, + -0.049361,-0.784577,0.618064,0.054813,0.038849,-0.005308, + 0,-0.854008,0.52026,0.055885,0.038728,-0.005434, + -0.049361,-0.784577,0.618064,0.054813,0.038849,-0.005308, + -0.053624,-0.852323,0.52026,0.054808,0.038762,-0.005434, + 0.053624,-0.852323,0.52026,0.056963,0.038762,-0.005434, + 0.049361,-0.784577,0.618064,0.056957,0.038849,-0.005308, + 0,-0.786128,0.618064,0.055885,0.038816,-0.005308, + 0.053624,-0.852323,0.52026,0.056963,0.038762,-0.005434, + 0,-0.786128,0.618064,0.055885,0.038816,-0.005308, + 0,-0.854008,0.52026,0.055885,0.038728,-0.005434, + 0.107036,-0.847274,0.52026,0.058036,0.038863,-0.005434, + 0.098528,-0.779929,0.618064,0.058025,0.03895,-0.005308, + 0.049361,-0.784577,0.618064,0.056957,0.038849,-0.005308, + 0.107036,-0.847274,0.52026,0.058036,0.038863,-0.005434, + 0.049361,-0.784577,0.618064,0.056957,0.038849,-0.005308, + 0.053624,-0.852323,0.52026,0.056963,0.038762,-0.005434, + 0.160025,-0.838881,0.52026,0.0591,0.039032,-0.005434, + 0.147306,-0.772203,0.618064,0.059084,0.039118,-0.005308, + 0.098528,-0.779929,0.618064,0.058025,0.03895,-0.005308, + 0.160025,-0.838881,0.52026,0.0591,0.039032,-0.005434, + 0.098528,-0.779929,0.618064,0.058025,0.03895,-0.005308, + 0.107036,-0.847274,0.52026,0.058036,0.038863,-0.005434, + 0.212383,-0.827178,0.52026,0.060152,0.039267,-0.005434, + 0.195502,-0.76143,0.618064,0.06013,0.039352,-0.005308, + 0.147306,-0.772203,0.618064,0.059084,0.039118,-0.005308, + 0.212383,-0.827178,0.52026,0.060152,0.039267,-0.005434, + 0.147306,-0.772203,0.618064,0.059084,0.039118,-0.005308, + 0.160025,-0.838881,0.52026,0.0591,0.039032,-0.005434, + 0.263903,-0.81221,0.52026,0.061187,0.039568,-0.005434, + 0.242927,-0.747652,0.618064,0.06116,0.039651,-0.005308, + 0.195502,-0.76143,0.618064,0.06013,0.039352,-0.005308, + 0.263903,-0.81221,0.52026,0.061187,0.039568,-0.005434, + 0.195502,-0.76143,0.618064,0.06013,0.039352,-0.005308, + 0.212383,-0.827178,0.52026,0.060152,0.039267,-0.005434, + 0.314381,-0.794037,0.52026,0.062201,0.039933,-0.005434, + 0.289393,-0.730923,0.618064,0.062169,0.040014,-0.005308, + 0.242927,-0.747652,0.618064,0.06116,0.039651,-0.005308, + 0.314381,-0.794037,0.52026,0.062201,0.039933,-0.005434, + 0.242927,-0.747652,0.618064,0.06116,0.039651,-0.005308, + 0.263903,-0.81221,0.52026,0.061187,0.039568,-0.005434, + 0.363619,-0.77273,0.52026,0.06319,0.040361,-0.005434, + 0.334717,-0.71131,0.618064,0.063153,0.04044,-0.005308, + 0.289393,-0.730923,0.618064,0.062169,0.040014,-0.005308, + 0.363619,-0.77273,0.52026,0.06319,0.040361,-0.005434, + 0.289393,-0.730923,0.618064,0.062169,0.040014,-0.005308, + 0.314381,-0.794037,0.52026,0.062201,0.039933,-0.005434, + 0.411421,-0.748373,0.52026,0.064151,0.04085,-0.005434, + 0.37872,-0.688889,0.618064,0.064109,0.040927,-0.005308, + 0.334717,-0.71131,0.618064,0.063153,0.04044,-0.005308, + 0.411421,-0.748373,0.52026,0.064151,0.04085,-0.005434, + 0.334717,-0.71131,0.618064,0.063153,0.04044,-0.005308, + 0.363619,-0.77273,0.52026,0.06319,0.040361,-0.005434, + 0.4576,-0.721063,0.52026,0.065079,0.041399,-0.005434, + 0.421228,-0.66375,0.618064,0.065032,0.041473,-0.005308, + 0.37872,-0.688889,0.618064,0.064109,0.040927,-0.005308, + 0.4576,-0.721063,0.52026,0.065079,0.041399,-0.005434, + 0.37872,-0.688889,0.618064,0.064109,0.040927,-0.005308, + 0.411421,-0.748373,0.52026,0.064151,0.04085,-0.005434, + 0.501973,-0.690907,0.52026,0.06597,0.042005,-0.005434, + 0.462074,-0.635991,0.618064,0.065919,0.042076,-0.005308, + 0.421228,-0.66375,0.618064,0.065032,0.041473,-0.005308, + 0.501973,-0.690907,0.52026,0.06597,0.042005,-0.005434, + 0.421228,-0.66375,0.618064,0.065032,0.041473,-0.005308, + 0.4576,-0.721063,0.52026,0.065079,0.041399,-0.005434, + 0.544365,-0.658024,0.52026,0.066822,0.042666,-0.005434, + 0.501097,-0.605722,0.618064,0.066766,0.042733,-0.005308, + 0.462074,-0.635991,0.618064,0.065919,0.042076,-0.005308, + 0.544365,-0.658024,0.52026,0.066822,0.042666,-0.005434, + 0.462074,-0.635991,0.618064,0.065919,0.042076,-0.005308, + 0.501973,-0.690907,0.52026,0.06597,0.042005,-0.005434, + 0.584609,-0.622545,0.52026,0.06763,0.043378,-0.005434, + 0.538141,-0.573062,0.618064,0.06757,0.043442,-0.005308, + 0.501097,-0.605722,0.618064,0.066766,0.042733,-0.005308, + 0.584609,-0.622545,0.52026,0.06763,0.043378,-0.005434, + 0.501097,-0.605722,0.618064,0.066766,0.042733,-0.005308, + 0.544365,-0.658024,0.52026,0.066822,0.042666,-0.005434, + 0.622545,-0.584609,0.52026,0.068392,0.04414,-0.005434, + 0.573062,-0.538141,0.618064,0.068329,0.0442,-0.005308, + 0.538141,-0.573062,0.618064,0.06757,0.043442,-0.005308, + 0.622545,-0.584609,0.52026,0.068392,0.04414,-0.005434, + 0.538141,-0.573062,0.618064,0.06757,0.043442,-0.005308, + 0.584609,-0.622545,0.52026,0.06763,0.043378,-0.005434, + 0.658024,-0.544365,0.52026,0.069105,0.044949,-0.005434, + 0.605722,-0.501097,0.618064,0.069038,0.045005,-0.005308, + 0.573062,-0.538141,0.618064,0.068329,0.0442,-0.005308, + 0.658024,-0.544365,0.52026,0.069105,0.044949,-0.005434, + 0.573062,-0.538141,0.618064,0.068329,0.0442,-0.005308, + 0.622545,-0.584609,0.52026,0.068392,0.04414,-0.005434, + 0.690907,-0.501973,0.52026,0.069766,0.045801,-0.005434, + 0.635991,-0.462074,0.618064,0.069695,0.045852,-0.005308, + 0.605722,-0.501097,0.618064,0.069038,0.045005,-0.005308, + 0.690907,-0.501973,0.52026,0.069766,0.045801,-0.005434, + 0.605722,-0.501097,0.618064,0.069038,0.045005,-0.005308, + 0.658024,-0.544365,0.52026,0.069105,0.044949,-0.005434, + 0.721063,-0.4576,0.52026,0.070372,0.046692,-0.005434, + 0.66375,-0.421228,0.618064,0.070298,0.046739,-0.005308, + 0.635991,-0.462074,0.618064,0.069695,0.045852,-0.005308, + 0.721063,-0.4576,0.52026,0.070372,0.046692,-0.005434, + 0.635991,-0.462074,0.618064,0.069695,0.045852,-0.005308, + 0.690907,-0.501973,0.52026,0.069766,0.045801,-0.005434, + 0.748373,-0.411421,0.52026,0.07092,0.04762,-0.005434, + 0.688889,-0.37872,0.618064,0.070844,0.047662,-0.005308, + 0.66375,-0.421228,0.618064,0.070298,0.046739,-0.005308, + 0.748373,-0.411421,0.52026,0.07092,0.04762,-0.005434, + 0.66375,-0.421228,0.618064,0.070298,0.046739,-0.005308, + 0.721063,-0.4576,0.52026,0.070372,0.046692,-0.005434, + 0.77273,-0.363619,0.52026,0.07141,0.04858,-0.005434, + 0.71131,-0.334717,0.618064,0.07133,0.048617,-0.005308, + 0.688889,-0.37872,0.618064,0.070844,0.047662,-0.005308, + 0.77273,-0.363619,0.52026,0.07141,0.04858,-0.005434, + 0.688889,-0.37872,0.618064,0.070844,0.047662,-0.005308, + 0.748373,-0.411421,0.52026,0.07092,0.04762,-0.005434, + 0.794037,-0.314381,0.52026,0.071838,0.049569,-0.005434, + 0.730923,-0.289393,0.618064,0.071756,0.049601,-0.005308, + 0.71131,-0.334717,0.618064,0.07133,0.048617,-0.005308, + 0.794037,-0.314381,0.52026,0.071838,0.049569,-0.005434, + 0.71131,-0.334717,0.618064,0.07133,0.048617,-0.005308, + 0.77273,-0.363619,0.52026,0.07141,0.04858,-0.005434, + 0.81221,-0.263903,0.52026,0.072203,0.050584,-0.005434, + 0.747652,-0.242927,0.618064,0.07212,0.05061,-0.005308, + 0.730923,-0.289393,0.618064,0.071756,0.049601,-0.005308, + 0.81221,-0.263903,0.52026,0.072203,0.050584,-0.005434, + 0.730923,-0.289393,0.618064,0.071756,0.049601,-0.005308, + 0.794037,-0.314381,0.52026,0.071838,0.049569,-0.005434, + 0.827178,-0.212383,0.52026,0.072503,0.051619,-0.005434, + 0.76143,-0.195502,0.618064,0.072419,0.05164,-0.005308, + 0.747652,-0.242927,0.618064,0.07212,0.05061,-0.005308, + 0.827178,-0.212383,0.52026,0.072503,0.051619,-0.005434, + 0.747652,-0.242927,0.618064,0.07212,0.05061,-0.005308, + 0.81221,-0.263903,0.52026,0.072203,0.050584,-0.005434, + 0.838881,-0.160025,0.52026,0.072739,0.05267,-0.005434, + 0.772203,-0.147306,0.618064,0.072653,0.052687,-0.005308, + 0.76143,-0.195502,0.618064,0.072419,0.05164,-0.005308, + 0.838881,-0.160025,0.52026,0.072739,0.05267,-0.005434, + 0.76143,-0.195502,0.618064,0.072419,0.05164,-0.005308, + 0.827178,-0.212383,0.52026,0.072503,0.051619,-0.005434, + 0.847274,-0.107036,0.52026,0.072907,0.053735,-0.005434, + 0.779929,-0.098528,0.618064,0.07282,0.053746,-0.005308, + 0.772203,-0.147306,0.618064,0.072653,0.052687,-0.005308, + 0.847274,-0.107036,0.52026,0.072907,0.053735,-0.005434, + 0.772203,-0.147306,0.618064,0.072653,0.052687,-0.005308, + 0.838881,-0.160025,0.52026,0.072739,0.05267,-0.005434, + 0.852323,-0.053624,0.52026,0.073009,0.054808,-0.005434, + 0.784577,-0.049361,0.618064,0.072921,0.054813,-0.005308, + 0.779929,-0.098528,0.618064,0.07282,0.053746,-0.005308, + 0.852323,-0.053624,0.52026,0.073009,0.054808,-0.005434, + 0.779929,-0.098528,0.618064,0.07282,0.053746,-0.005308, + 0.847274,-0.107036,0.52026,0.072907,0.053735,-0.005434, + 0.854008,0,0.52026,0.073042,0.055885,-0.005434, + 0.786128,0,0.618064,0.072955,0.055885,-0.005308, + 0.784577,-0.049361,0.618064,0.072921,0.054813,-0.005308, + 0.854008,0,0.52026,0.073042,0.055885,-0.005434, + 0.784577,-0.049361,0.618064,0.072921,0.054813,-0.005308, + 0.852323,-0.053624,0.52026,0.073009,0.054808,-0.005434, + 0.852323,0.053624,0.52026,0.073009,0.056963,-0.005434, + 0.784577,0.049361,0.618064,0.072921,0.056957,-0.005308, + 0.786128,0,0.618064,0.072955,0.055885,-0.005308, + 0.852323,0.053624,0.52026,0.073009,0.056963,-0.005434, + 0.786128,0,0.618064,0.072955,0.055885,-0.005308, + 0.854008,0,0.52026,0.073042,0.055885,-0.005434, + 0.847274,0.107036,0.52026,0.072907,0.058036,-0.005434, + 0.779929,0.098528,0.618064,0.07282,0.058025,-0.005308, + 0.784577,0.049361,0.618064,0.072921,0.056957,-0.005308, + 0.847274,0.107036,0.52026,0.072907,0.058036,-0.005434, + 0.784577,0.049361,0.618064,0.072921,0.056957,-0.005308, + 0.852323,0.053624,0.52026,0.073009,0.056963,-0.005434, + 0.838881,0.160025,0.52026,0.072739,0.0591,-0.005434, + 0.772203,0.147306,0.618064,0.072653,0.059084,-0.005308, + 0.779929,0.098528,0.618064,0.07282,0.058025,-0.005308, + 0.838881,0.160025,0.52026,0.072739,0.0591,-0.005434, + 0.779929,0.098528,0.618064,0.07282,0.058025,-0.005308, + 0.847274,0.107036,0.52026,0.072907,0.058036,-0.005434, + 0.827178,0.212383,0.52026,0.072503,0.060152,-0.005434, + 0.76143,0.195502,0.618064,0.072419,0.06013,-0.005308, + 0.772203,0.147306,0.618064,0.072653,0.059084,-0.005308, + 0.827178,0.212383,0.52026,0.072503,0.060152,-0.005434, + 0.772203,0.147306,0.618064,0.072653,0.059084,-0.005308, + 0.838881,0.160025,0.52026,0.072739,0.0591,-0.005434, + 0.81221,0.263903,0.52026,0.072203,0.061187,-0.005434, + 0.747652,0.242927,0.618064,0.07212,0.06116,-0.005308, + 0.76143,0.195502,0.618064,0.072419,0.06013,-0.005308, + 0.81221,0.263903,0.52026,0.072203,0.061187,-0.005434, + 0.76143,0.195502,0.618064,0.072419,0.06013,-0.005308, + 0.827178,0.212383,0.52026,0.072503,0.060152,-0.005434, + 0.794037,0.314381,0.52026,0.071838,0.062201,-0.005434, + 0.730923,0.289393,0.618064,0.071756,0.062169,-0.005308, + 0.747652,0.242927,0.618064,0.07212,0.06116,-0.005308, + 0.794037,0.314381,0.52026,0.071838,0.062201,-0.005434, + 0.747652,0.242927,0.618064,0.07212,0.06116,-0.005308, + 0.81221,0.263903,0.52026,0.072203,0.061187,-0.005434, + 0.77273,0.363619,0.52026,0.07141,0.06319,-0.005434, + 0.71131,0.334717,0.618064,0.07133,0.063153,-0.005308, + 0.730923,0.289393,0.618064,0.071756,0.062169,-0.005308, + 0.77273,0.363619,0.52026,0.07141,0.06319,-0.005434, + 0.730923,0.289393,0.618064,0.071756,0.062169,-0.005308, + 0.794037,0.314381,0.52026,0.071838,0.062201,-0.005434, + 0.748373,0.411421,0.52026,0.07092,0.064151,-0.005434, + 0.688889,0.37872,0.618064,0.070844,0.064109,-0.005308, + 0.71131,0.334717,0.618064,0.07133,0.063153,-0.005308, + 0.748373,0.411421,0.52026,0.07092,0.064151,-0.005434, + 0.71131,0.334717,0.618064,0.07133,0.063153,-0.005308, + 0.77273,0.363619,0.52026,0.07141,0.06319,-0.005434, + 0.721063,0.4576,0.52026,0.070372,0.065079,-0.005434, + 0.66375,0.421228,0.618064,0.070298,0.065032,-0.005308, + 0.688889,0.37872,0.618064,0.070844,0.064109,-0.005308, + 0.721063,0.4576,0.52026,0.070372,0.065079,-0.005434, + 0.688889,0.37872,0.618064,0.070844,0.064109,-0.005308, + 0.748373,0.411421,0.52026,0.07092,0.064151,-0.005434, + 0.690907,0.501973,0.52026,0.069766,0.06597,-0.005434, + 0.635991,0.462074,0.618064,0.069695,0.065919,-0.005308, + 0.66375,0.421228,0.618064,0.070298,0.065032,-0.005308, + 0.690907,0.501973,0.52026,0.069766,0.06597,-0.005434, + 0.66375,0.421228,0.618064,0.070298,0.065032,-0.005308, + 0.721063,0.4576,0.52026,0.070372,0.065079,-0.005434, + 0.658024,0.544365,0.52026,0.069105,0.066822,-0.005434, + 0.605722,0.501097,0.618064,0.069038,0.066766,-0.005308, + 0.635991,0.462074,0.618064,0.069695,0.065919,-0.005308, + 0.658024,0.544365,0.52026,0.069105,0.066822,-0.005434, + 0.635991,0.462074,0.618064,0.069695,0.065919,-0.005308, + 0.690907,0.501973,0.52026,0.069766,0.06597,-0.005434, + 0.622545,0.584609,0.52026,0.068392,0.06763,-0.005434, + 0.573062,0.538141,0.618064,0.068329,0.06757,-0.005308, + 0.605722,0.501097,0.618064,0.069038,0.066766,-0.005308, + 0.622545,0.584609,0.52026,0.068392,0.06763,-0.005434, + 0.605722,0.501097,0.618064,0.069038,0.066766,-0.005308, + 0.658024,0.544365,0.52026,0.069105,0.066822,-0.005434, + 0.584609,0.622545,0.52026,0.06763,0.068392,-0.005434, + 0.538141,0.573062,0.618064,0.06757,0.068329,-0.005308, + 0.573062,0.538141,0.618064,0.068329,0.06757,-0.005308, + 0.584609,0.622545,0.52026,0.06763,0.068392,-0.005434, + 0.573062,0.538141,0.618064,0.068329,0.06757,-0.005308, + 0.622545,0.584609,0.52026,0.068392,0.06763,-0.005434, + 0.544365,0.658024,0.52026,0.066822,0.069105,-0.005434, + 0.501097,0.605722,0.618064,0.066766,0.069038,-0.005308, + 0.538141,0.573062,0.618064,0.06757,0.068329,-0.005308, + 0.544365,0.658024,0.52026,0.066822,0.069105,-0.005434, + 0.538141,0.573062,0.618064,0.06757,0.068329,-0.005308, + 0.584609,0.622545,0.52026,0.06763,0.068392,-0.005434, + 0.501973,0.690907,0.52026,0.06597,0.069766,-0.005434, + 0.462074,0.635991,0.618064,0.065919,0.069695,-0.005308, + 0.501097,0.605722,0.618064,0.066766,0.069038,-0.005308, + 0.501973,0.690907,0.52026,0.06597,0.069766,-0.005434, + 0.501097,0.605722,0.618064,0.066766,0.069038,-0.005308, + 0.544365,0.658024,0.52026,0.066822,0.069105,-0.005434, + 0.4576,0.721063,0.52026,0.065079,0.070372,-0.005434, + 0.421228,0.66375,0.618064,0.065032,0.070298,-0.005308, + 0.462074,0.635991,0.618064,0.065919,0.069695,-0.005308, + 0.4576,0.721063,0.52026,0.065079,0.070372,-0.005434, + 0.462074,0.635991,0.618064,0.065919,0.069695,-0.005308, + 0.501973,0.690907,0.52026,0.06597,0.069766,-0.005434, + 0.411421,0.748373,0.52026,0.064151,0.07092,-0.005434, + 0.37872,0.688889,0.618064,0.064109,0.070844,-0.005308, + 0.421228,0.66375,0.618064,0.065032,0.070298,-0.005308, + 0.411421,0.748373,0.52026,0.064151,0.07092,-0.005434, + 0.421228,0.66375,0.618064,0.065032,0.070298,-0.005308, + 0.4576,0.721063,0.52026,0.065079,0.070372,-0.005434, + 0.363619,0.77273,0.52026,0.06319,0.07141,-0.005434, + 0.334717,0.71131,0.618064,0.063153,0.07133,-0.005308, + 0.37872,0.688889,0.618064,0.064109,0.070844,-0.005308, + 0.363619,0.77273,0.52026,0.06319,0.07141,-0.005434, + 0.37872,0.688889,0.618064,0.064109,0.070844,-0.005308, + 0.411421,0.748373,0.52026,0.064151,0.07092,-0.005434, + 0.314381,0.794037,0.52026,0.062201,0.071838,-0.005434, + 0.289393,0.730923,0.618064,0.062169,0.071756,-0.005308, + 0.334717,0.71131,0.618064,0.063153,0.07133,-0.005308, + 0.314381,0.794037,0.52026,0.062201,0.071838,-0.005434, + 0.334717,0.71131,0.618064,0.063153,0.07133,-0.005308, + 0.363619,0.77273,0.52026,0.06319,0.07141,-0.005434, + 0.263903,0.81221,0.52026,0.061187,0.072203,-0.005434, + 0.242927,0.747652,0.618064,0.06116,0.07212,-0.005308, + 0.289393,0.730923,0.618064,0.062169,0.071756,-0.005308, + 0.263903,0.81221,0.52026,0.061187,0.072203,-0.005434, + 0.289393,0.730923,0.618064,0.062169,0.071756,-0.005308, + 0.314381,0.794037,0.52026,0.062201,0.071838,-0.005434, + 0.212383,0.827178,0.52026,0.060152,0.072503,-0.005434, + 0.195502,0.76143,0.618064,0.06013,0.072419,-0.005308, + 0.242927,0.747652,0.618064,0.06116,0.07212,-0.005308, + 0.212383,0.827178,0.52026,0.060152,0.072503,-0.005434, + 0.242927,0.747652,0.618064,0.06116,0.07212,-0.005308, + 0.263903,0.81221,0.52026,0.061187,0.072203,-0.005434, + 0.160025,0.838881,0.52026,0.0591,0.072739,-0.005434, + 0.147306,0.772203,0.618064,0.059084,0.072653,-0.005308, + 0.195502,0.76143,0.618064,0.06013,0.072419,-0.005308, + 0.160025,0.838881,0.52026,0.0591,0.072739,-0.005434, + 0.195502,0.76143,0.618064,0.06013,0.072419,-0.005308, + 0.212383,0.827178,0.52026,0.060152,0.072503,-0.005434, + 0.107036,0.847274,0.52026,0.058036,0.072907,-0.005434, + 0.098528,0.779929,0.618064,0.058025,0.07282,-0.005308, + 0.147306,0.772203,0.618064,0.059084,0.072653,-0.005308, + 0.107036,0.847274,0.52026,0.058036,0.072907,-0.005434, + 0.147306,0.772203,0.618064,0.059084,0.072653,-0.005308, + 0.160025,0.838881,0.52026,0.0591,0.072739,-0.005434, + 0.053624,0.852323,0.52026,0.056963,0.073009,-0.005434, + 0.049361,0.784577,0.618064,0.056957,0.072921,-0.005308, + 0.098528,0.779929,0.618064,0.058025,0.07282,-0.005308, + 0.053624,0.852323,0.52026,0.056963,0.073009,-0.005434, + 0.098528,0.779929,0.618064,0.058025,0.07282,-0.005308, + 0.107036,0.847274,0.52026,0.058036,0.072907,-0.005434, + 0,0.854008,0.52026,0.055885,0.073042,-0.005434, + 0,0.786128,0.618064,0.055885,0.072955,-0.005308, + 0.049361,0.784577,0.618064,0.056957,0.072921,-0.005308, + 0,0.854008,0.52026,0.055885,0.073042,-0.005434, + 0.049361,0.784577,0.618064,0.056957,0.072921,-0.005308, + 0.053624,0.852323,0.52026,0.056963,0.073009,-0.005434, + -0.053624,0.852323,0.52026,0.054808,0.073009,-0.005434, + -0.049361,0.784577,0.618064,0.054813,0.072921,-0.005308, + 0,0.786128,0.618064,0.055885,0.072955,-0.005308, + -0.053624,0.852323,0.52026,0.054808,0.073009,-0.005434, + 0,0.786128,0.618064,0.055885,0.072955,-0.005308, + 0,0.854008,0.52026,0.055885,0.073042,-0.005434, + -0.107036,0.847274,0.52026,0.053735,0.072907,-0.005434, + -0.098528,0.779929,0.618064,0.053746,0.07282,-0.005308, + -0.049361,0.784577,0.618064,0.054813,0.072921,-0.005308, + -0.107036,0.847274,0.52026,0.053735,0.072907,-0.005434, + -0.049361,0.784577,0.618064,0.054813,0.072921,-0.005308, + -0.053624,0.852323,0.52026,0.054808,0.073009,-0.005434, + -0.160025,0.838881,0.52026,0.05267,0.072739,-0.005434, + -0.147306,0.772203,0.618064,0.052687,0.072653,-0.005308, + -0.098528,0.779929,0.618064,0.053746,0.07282,-0.005308, + -0.160025,0.838881,0.52026,0.05267,0.072739,-0.005434, + -0.098528,0.779929,0.618064,0.053746,0.07282,-0.005308, + -0.107036,0.847274,0.52026,0.053735,0.072907,-0.005434, + -0.212383,0.827178,0.52026,0.051619,0.072503,-0.005434, + -0.195502,0.76143,0.618064,0.05164,0.072419,-0.005308, + -0.147306,0.772203,0.618064,0.052687,0.072653,-0.005308, + -0.212383,0.827178,0.52026,0.051619,0.072503,-0.005434, + -0.147306,0.772203,0.618064,0.052687,0.072653,-0.005308, + -0.160025,0.838881,0.52026,0.05267,0.072739,-0.005434, + -0.263903,0.81221,0.52026,0.050584,0.072203,-0.005434, + -0.242927,0.747652,0.618064,0.05061,0.07212,-0.005308, + -0.195502,0.76143,0.618064,0.05164,0.072419,-0.005308, + -0.263903,0.81221,0.52026,0.050584,0.072203,-0.005434, + -0.195502,0.76143,0.618064,0.05164,0.072419,-0.005308, + -0.212383,0.827178,0.52026,0.051619,0.072503,-0.005434, + -0.314381,0.794037,0.52026,0.049569,0.071838,-0.005434, + -0.289393,0.730923,0.618064,0.049601,0.071756,-0.005308, + -0.242927,0.747652,0.618064,0.05061,0.07212,-0.005308, + -0.314381,0.794037,0.52026,0.049569,0.071838,-0.005434, + -0.242927,0.747652,0.618064,0.05061,0.07212,-0.005308, + -0.263903,0.81221,0.52026,0.050584,0.072203,-0.005434, + -0.363619,0.77273,0.52026,0.04858,0.07141,-0.005434, + -0.334717,0.71131,0.618064,0.048617,0.07133,-0.005308, + -0.289393,0.730923,0.618064,0.049601,0.071756,-0.005308, + -0.363619,0.77273,0.52026,0.04858,0.07141,-0.005434, + -0.289393,0.730923,0.618064,0.049601,0.071756,-0.005308, + -0.314381,0.794037,0.52026,0.049569,0.071838,-0.005434, + -0.411421,0.748373,0.52026,0.04762,0.07092,-0.005434, + -0.37872,0.688889,0.618064,0.047662,0.070844,-0.005308, + -0.334717,0.71131,0.618064,0.048617,0.07133,-0.005308, + -0.411421,0.748373,0.52026,0.04762,0.07092,-0.005434, + -0.334717,0.71131,0.618064,0.048617,0.07133,-0.005308, + -0.363619,0.77273,0.52026,0.04858,0.07141,-0.005434, + -0.4576,0.721063,0.52026,0.046692,0.070372,-0.005434, + -0.421228,0.66375,0.618064,0.046739,0.070298,-0.005308, + -0.37872,0.688889,0.618064,0.047662,0.070844,-0.005308, + -0.4576,0.721063,0.52026,0.046692,0.070372,-0.005434, + -0.37872,0.688889,0.618064,0.047662,0.070844,-0.005308, + -0.411421,0.748373,0.52026,0.04762,0.07092,-0.005434, + -0.501973,0.690907,0.52026,0.045801,0.069766,-0.005434, + -0.462074,0.635991,0.618064,0.045852,0.069695,-0.005308, + -0.421228,0.66375,0.618064,0.046739,0.070298,-0.005308, + -0.501973,0.690907,0.52026,0.045801,0.069766,-0.005434, + -0.421228,0.66375,0.618064,0.046739,0.070298,-0.005308, + -0.4576,0.721063,0.52026,0.046692,0.070372,-0.005434, + -0.544365,0.658024,0.52026,0.044949,0.069105,-0.005434, + -0.501097,0.605722,0.618064,0.045005,0.069038,-0.005308, + -0.462074,0.635991,0.618064,0.045852,0.069695,-0.005308, + -0.544365,0.658024,0.52026,0.044949,0.069105,-0.005434, + -0.462074,0.635991,0.618064,0.045852,0.069695,-0.005308, + -0.501973,0.690907,0.52026,0.045801,0.069766,-0.005434, + -0.584609,0.622545,0.52026,0.04414,0.068392,-0.005434, + -0.538141,0.573062,0.618064,0.0442,0.068329,-0.005308, + -0.501097,0.605722,0.618064,0.045005,0.069038,-0.005308, + -0.584609,0.622545,0.52026,0.04414,0.068392,-0.005434, + -0.501097,0.605722,0.618064,0.045005,0.069038,-0.005308, + -0.544365,0.658024,0.52026,0.044949,0.069105,-0.005434, + -0.622545,0.584609,0.52026,0.043378,0.06763,-0.005434, + -0.573062,0.538141,0.618064,0.043442,0.06757,-0.005308, + -0.538141,0.573062,0.618064,0.0442,0.068329,-0.005308, + -0.622545,0.584609,0.52026,0.043378,0.06763,-0.005434, + -0.538141,0.573062,0.618064,0.0442,0.068329,-0.005308, + -0.584609,0.622545,0.52026,0.04414,0.068392,-0.005434, + -0.658024,0.544365,0.52026,0.042666,0.066822,-0.005434, + -0.605722,0.501097,0.618064,0.042733,0.066766,-0.005308, + -0.573062,0.538141,0.618064,0.043442,0.06757,-0.005308, + -0.658024,0.544365,0.52026,0.042666,0.066822,-0.005434, + -0.573062,0.538141,0.618064,0.043442,0.06757,-0.005308, + -0.622545,0.584609,0.52026,0.043378,0.06763,-0.005434, + -0.690907,0.501973,0.52026,0.042005,0.06597,-0.005434, + -0.635991,0.462074,0.618064,0.042076,0.065919,-0.005308, + -0.605722,0.501097,0.618064,0.042733,0.066766,-0.005308, + -0.690907,0.501973,0.52026,0.042005,0.06597,-0.005434, + -0.605722,0.501097,0.618064,0.042733,0.066766,-0.005308, + -0.658024,0.544365,0.52026,0.042666,0.066822,-0.005434, + -0.721063,0.4576,0.52026,0.041399,0.065079,-0.005434, + -0.66375,0.421228,0.618064,0.041473,0.065032,-0.005308, + -0.635991,0.462074,0.618064,0.042076,0.065919,-0.005308, + -0.721063,0.4576,0.52026,0.041399,0.065079,-0.005434, + -0.635991,0.462074,0.618064,0.042076,0.065919,-0.005308, + -0.690907,0.501973,0.52026,0.042005,0.06597,-0.005434, + -0.748373,0.411421,0.52026,0.04085,0.064151,-0.005434, + -0.688889,0.37872,0.618064,0.040927,0.064109,-0.005308, + -0.66375,0.421228,0.618064,0.041473,0.065032,-0.005308, + -0.748373,0.411421,0.52026,0.04085,0.064151,-0.005434, + -0.66375,0.421228,0.618064,0.041473,0.065032,-0.005308, + -0.721063,0.4576,0.52026,0.041399,0.065079,-0.005434, + -0.77273,0.363619,0.52026,0.040361,0.06319,-0.005434, + -0.71131,0.334717,0.618064,0.04044,0.063153,-0.005308, + -0.688889,0.37872,0.618064,0.040927,0.064109,-0.005308, + -0.77273,0.363619,0.52026,0.040361,0.06319,-0.005434, + -0.688889,0.37872,0.618064,0.040927,0.064109,-0.005308, + -0.748373,0.411421,0.52026,0.04085,0.064151,-0.005434, + -0.794037,0.314381,0.52026,0.039933,0.062201,-0.005434, + -0.730923,0.289393,0.618064,0.040014,0.062169,-0.005308, + -0.71131,0.334717,0.618064,0.04044,0.063153,-0.005308, + -0.794037,0.314381,0.52026,0.039933,0.062201,-0.005434, + -0.71131,0.334717,0.618064,0.04044,0.063153,-0.005308, + -0.77273,0.363619,0.52026,0.040361,0.06319,-0.005434, + -0.81221,0.263903,0.52026,0.039568,0.061187,-0.005434, + -0.747652,0.242927,0.618064,0.039651,0.06116,-0.005308, + -0.730923,0.289393,0.618064,0.040014,0.062169,-0.005308, + -0.81221,0.263903,0.52026,0.039568,0.061187,-0.005434, + -0.730923,0.289393,0.618064,0.040014,0.062169,-0.005308, + -0.794037,0.314381,0.52026,0.039933,0.062201,-0.005434, + -0.827178,0.212383,0.52026,0.039267,0.060152,-0.005434, + -0.76143,0.195502,0.618064,0.039352,0.06013,-0.005308, + -0.747652,0.242927,0.618064,0.039651,0.06116,-0.005308, + -0.827178,0.212383,0.52026,0.039267,0.060152,-0.005434, + -0.747652,0.242927,0.618064,0.039651,0.06116,-0.005308, + -0.81221,0.263903,0.52026,0.039568,0.061187,-0.005434, + -0.838881,0.160025,0.52026,0.039032,0.0591,-0.005434, + -0.772203,0.147306,0.618064,0.039118,0.059084,-0.005308, + -0.76143,0.195502,0.618064,0.039352,0.06013,-0.005308, + -0.838881,0.160025,0.52026,0.039032,0.0591,-0.005434, + -0.76143,0.195502,0.618064,0.039352,0.06013,-0.005308, + -0.827178,0.212383,0.52026,0.039267,0.060152,-0.005434, + -0.847274,0.107036,0.52026,0.038863,0.058036,-0.005434, + -0.779929,0.098528,0.618064,0.03895,0.058025,-0.005308, + -0.772203,0.147306,0.618064,0.039118,0.059084,-0.005308, + -0.847274,0.107036,0.52026,0.038863,0.058036,-0.005434, + -0.772203,0.147306,0.618064,0.039118,0.059084,-0.005308, + -0.838881,0.160025,0.52026,0.039032,0.0591,-0.005434, + -0.852323,0.053624,0.52026,0.038762,0.056963,-0.005434, + -0.784577,0.049361,0.618064,0.038849,0.056957,-0.005308, + -0.779929,0.098528,0.618064,0.03895,0.058025,-0.005308, + -0.852323,0.053624,0.52026,0.038762,0.056963,-0.005434, + -0.779929,0.098528,0.618064,0.03895,0.058025,-0.005308, + -0.847274,0.107036,0.52026,0.038863,0.058036,-0.005434, + -0.854008,0,0.52026,0.038728,0.055885,-0.005434, + -0.786128,0,0.618064,0.038816,0.055885,-0.005308, + -0.784577,0.049361,0.618064,0.038849,0.056957,-0.005308, + -0.854008,0,0.52026,0.038728,0.055885,-0.005434, + -0.784577,0.049361,0.618064,0.038849,0.056957,-0.005308, + -0.852323,0.053624,0.52026,0.038762,0.056963,-0.005434, + -0.852323,-0.053624,0.52026,0.038762,0.054808,-0.005434, + -0.784577,-0.049361,0.618064,0.038849,0.054813,-0.005308, + -0.786128,0,0.618064,0.038816,0.055885,-0.005308, + -0.852323,-0.053624,0.52026,0.038762,0.054808,-0.005434, + -0.786128,0,0.618064,0.038816,0.055885,-0.005308, + -0.854008,0,0.52026,0.038728,0.055885,-0.005434, + -0.784577,-0.049361,0.618064,0.038849,0.054813,-0.005308, + -0.70571,-0.0444,0.707108,0.038951,0.05482,-0.005193, + -0.707106,0,0.707108,0.038917,0.055885,-0.005193, + -0.784577,-0.049361,0.618064,0.038849,0.054813,-0.005308, + -0.707106,0,0.707108,0.038917,0.055885,-0.005193, + -0.786128,0,0.618064,0.038816,0.055885,-0.005308, + -0.779929,-0.098528,0.618064,0.03895,0.053746,-0.005308, + -0.70153,-0.088624,0.707108,0.039051,0.053759,-0.005193, + -0.70571,-0.0444,0.707108,0.038951,0.05482,-0.005193, + -0.779929,-0.098528,0.618064,0.03895,0.053746,-0.005308, + -0.70571,-0.0444,0.707108,0.038951,0.05482,-0.005193, + -0.784577,-0.049361,0.618064,0.038849,0.054813,-0.005308, + -0.772203,-0.147306,0.618064,0.039118,0.052687,-0.005308, + -0.694581,-0.132498,0.707108,0.039218,0.052706,-0.005193, + -0.70153,-0.088624,0.707108,0.039051,0.053759,-0.005193, + -0.772203,-0.147306,0.618064,0.039118,0.052687,-0.005308, + -0.70153,-0.088624,0.707108,0.039051,0.053759,-0.005193, + -0.779929,-0.098528,0.618064,0.03895,0.053746,-0.005308, + -0.76143,-0.195502,0.618064,0.039352,0.05164,-0.005308, + -0.684891,-0.17585,0.707108,0.03945,0.051666,-0.005193, + -0.694581,-0.132498,0.707108,0.039218,0.052706,-0.005193, + -0.76143,-0.195502,0.618064,0.039352,0.05164,-0.005308, + -0.694581,-0.132498,0.707108,0.039218,0.052706,-0.005193, + -0.772203,-0.147306,0.618064,0.039118,0.052687,-0.005308, + -0.747652,-0.242927,0.618064,0.039651,0.05061,-0.005308, + -0.672497,-0.218508,0.707108,0.039748,0.050642,-0.005193, + -0.684891,-0.17585,0.707108,0.03945,0.051666,-0.005193, + -0.747652,-0.242927,0.618064,0.039651,0.05061,-0.005308, + -0.684891,-0.17585,0.707108,0.03945,0.051666,-0.005193, + -0.76143,-0.195502,0.618064,0.039352,0.05164,-0.005308, + -0.730923,-0.289393,0.618064,0.040014,0.049601,-0.005308, + -0.65745,-0.260303,0.707108,0.040109,0.049639,-0.005193, + -0.672497,-0.218508,0.707108,0.039748,0.050642,-0.005193, + -0.730923,-0.289393,0.618064,0.040014,0.049601,-0.005308, + -0.672497,-0.218508,0.707108,0.039748,0.050642,-0.005193, + -0.747652,-0.242927,0.618064,0.039651,0.05061,-0.005308, + -0.71131,-0.334717,0.618064,0.04044,0.048617,-0.005308, + -0.639808,-0.301071,0.707108,0.040532,0.048661,-0.005193, + -0.65745,-0.260303,0.707108,0.040109,0.049639,-0.005193, + -0.71131,-0.334717,0.618064,0.04044,0.048617,-0.005308, + -0.65745,-0.260303,0.707108,0.040109,0.049639,-0.005193, + -0.730923,-0.289393,0.618064,0.040014,0.049601,-0.005308, + -0.688889,-0.37872,0.618064,0.040927,0.047662,-0.005308, + -0.619641,-0.340651,0.707108,0.041016,0.047711,-0.005193, + -0.639808,-0.301071,0.707108,0.040532,0.048661,-0.005193, + -0.688889,-0.37872,0.618064,0.040927,0.047662,-0.005308, + -0.639808,-0.301071,0.707108,0.040532,0.048661,-0.005193, + -0.71131,-0.334717,0.618064,0.04044,0.048617,-0.005308, + -0.66375,-0.421228,0.618064,0.041473,0.046739,-0.005308, + -0.597029,-0.378886,0.707108,0.041559,0.046793,-0.005193, + -0.619641,-0.340651,0.707108,0.041016,0.047711,-0.005193, + -0.66375,-0.421228,0.618064,0.041473,0.046739,-0.005308, + -0.619641,-0.340651,0.707108,0.041016,0.047711,-0.005193, + -0.688889,-0.37872,0.618064,0.040927,0.047662,-0.005308, + -0.635991,-0.462074,0.618064,0.042076,0.045852,-0.005308, + -0.57206,-0.415626,0.707108,0.042158,0.045912,-0.005193, + -0.597029,-0.378886,0.707108,0.041559,0.046793,-0.005193, + -0.635991,-0.462074,0.618064,0.042076,0.045852,-0.005308, + -0.597029,-0.378886,0.707108,0.041559,0.046793,-0.005193, + -0.66375,-0.421228,0.618064,0.041473,0.046739,-0.005308, + -0.605722,-0.501097,0.618064,0.042733,0.045005,-0.005308, + -0.544834,-0.450726,0.707108,0.042811,0.04507,-0.005193, + -0.57206,-0.415626,0.707108,0.042158,0.045912,-0.005193, + -0.605722,-0.501097,0.618064,0.042733,0.045005,-0.005308, + -0.57206,-0.415626,0.707108,0.042158,0.045912,-0.005193, + -0.635991,-0.462074,0.618064,0.042076,0.045852,-0.005308, + -0.573062,-0.538141,0.618064,0.043442,0.0442,-0.005308, + -0.515458,-0.484047,0.707108,0.043516,0.04427,-0.005193, + -0.544834,-0.450726,0.707108,0.042811,0.04507,-0.005193, + -0.573062,-0.538141,0.618064,0.043442,0.0442,-0.005308, + -0.544834,-0.450726,0.707108,0.042811,0.04507,-0.005193, + -0.605722,-0.501097,0.618064,0.042733,0.045005,-0.005308, + -0.538141,-0.573062,0.618064,0.0442,0.043442,-0.005308, + -0.484047,-0.515458,0.707108,0.04427,0.043516,-0.005193, + -0.515458,-0.484047,0.707108,0.043516,0.04427,-0.005193, + -0.538141,-0.573062,0.618064,0.0442,0.043442,-0.005308, + -0.515458,-0.484047,0.707108,0.043516,0.04427,-0.005193, + -0.573062,-0.538141,0.618064,0.043442,0.0442,-0.005308, + -0.501097,-0.605722,0.618064,0.045005,0.042733,-0.005308, + -0.450726,-0.544834,0.707108,0.04507,0.042811,-0.005193, + -0.484047,-0.515458,0.707108,0.04427,0.043516,-0.005193, + -0.501097,-0.605722,0.618064,0.045005,0.042733,-0.005308, + -0.484047,-0.515458,0.707108,0.04427,0.043516,-0.005193, + -0.538141,-0.573062,0.618064,0.0442,0.043442,-0.005308, + -0.462074,-0.635991,0.618064,0.045852,0.042076,-0.005308, + -0.415626,-0.57206,0.707108,0.045912,0.042158,-0.005193, + -0.450726,-0.544834,0.707108,0.04507,0.042811,-0.005193, + -0.462074,-0.635991,0.618064,0.045852,0.042076,-0.005308, + -0.450726,-0.544834,0.707108,0.04507,0.042811,-0.005193, + -0.501097,-0.605722,0.618064,0.045005,0.042733,-0.005308, + -0.421228,-0.66375,0.618064,0.046739,0.041473,-0.005308, + -0.378886,-0.597029,0.707108,0.046793,0.041559,-0.005193, + -0.415626,-0.57206,0.707108,0.045912,0.042158,-0.005193, + -0.421228,-0.66375,0.618064,0.046739,0.041473,-0.005308, + -0.415626,-0.57206,0.707108,0.045912,0.042158,-0.005193, + -0.462074,-0.635991,0.618064,0.045852,0.042076,-0.005308, + -0.37872,-0.688889,0.618064,0.047662,0.040927,-0.005308, + -0.340651,-0.619641,0.707108,0.047711,0.041016,-0.005193, + -0.378886,-0.597029,0.707108,0.046793,0.041559,-0.005193, + -0.37872,-0.688889,0.618064,0.047662,0.040927,-0.005308, + -0.378886,-0.597029,0.707108,0.046793,0.041559,-0.005193, + -0.421228,-0.66375,0.618064,0.046739,0.041473,-0.005308, + -0.334717,-0.71131,0.618064,0.048617,0.04044,-0.005308, + -0.301071,-0.639808,0.707108,0.048661,0.040532,-0.005193, + -0.340651,-0.619641,0.707108,0.047711,0.041016,-0.005193, + -0.334717,-0.71131,0.618064,0.048617,0.04044,-0.005308, + -0.340651,-0.619641,0.707108,0.047711,0.041016,-0.005193, + -0.37872,-0.688889,0.618064,0.047662,0.040927,-0.005308, + -0.289393,-0.730923,0.618064,0.049601,0.040014,-0.005308, + -0.260303,-0.65745,0.707108,0.049639,0.040109,-0.005193, + -0.301071,-0.639808,0.707108,0.048661,0.040532,-0.005193, + -0.289393,-0.730923,0.618064,0.049601,0.040014,-0.005308, + -0.301071,-0.639808,0.707108,0.048661,0.040532,-0.005193, + -0.334717,-0.71131,0.618064,0.048617,0.04044,-0.005308, + -0.242927,-0.747652,0.618064,0.05061,0.039651,-0.005308, + -0.218508,-0.672497,0.707108,0.050642,0.039748,-0.005193, + -0.260303,-0.65745,0.707108,0.049639,0.040109,-0.005193, + -0.242927,-0.747652,0.618064,0.05061,0.039651,-0.005308, + -0.260303,-0.65745,0.707108,0.049639,0.040109,-0.005193, + -0.289393,-0.730923,0.618064,0.049601,0.040014,-0.005308, + -0.195502,-0.76143,0.618064,0.05164,0.039352,-0.005308, + -0.17585,-0.684891,0.707108,0.051666,0.03945,-0.005193, + -0.218508,-0.672497,0.707108,0.050642,0.039748,-0.005193, + -0.195502,-0.76143,0.618064,0.05164,0.039352,-0.005308, + -0.218508,-0.672497,0.707108,0.050642,0.039748,-0.005193, + -0.242927,-0.747652,0.618064,0.05061,0.039651,-0.005308, + -0.147306,-0.772203,0.618064,0.052687,0.039118,-0.005308, + -0.132498,-0.694581,0.707108,0.052706,0.039218,-0.005193, + -0.17585,-0.684891,0.707108,0.051666,0.03945,-0.005193, + -0.147306,-0.772203,0.618064,0.052687,0.039118,-0.005308, + -0.17585,-0.684891,0.707108,0.051666,0.03945,-0.005193, + -0.195502,-0.76143,0.618064,0.05164,0.039352,-0.005308, + -0.098528,-0.779929,0.618064,0.053746,0.03895,-0.005308, + -0.088624,-0.70153,0.707108,0.053759,0.039051,-0.005193, + -0.132498,-0.694581,0.707108,0.052706,0.039218,-0.005193, + -0.098528,-0.779929,0.618064,0.053746,0.03895,-0.005308, + -0.132498,-0.694581,0.707108,0.052706,0.039218,-0.005193, + -0.147306,-0.772203,0.618064,0.052687,0.039118,-0.005308, + -0.049361,-0.784577,0.618064,0.054813,0.038849,-0.005308, + -0.0444,-0.70571,0.707108,0.05482,0.038951,-0.005193, + -0.088624,-0.70153,0.707108,0.053759,0.039051,-0.005193, + -0.049361,-0.784577,0.618064,0.054813,0.038849,-0.005308, + -0.088624,-0.70153,0.707108,0.053759,0.039051,-0.005193, + -0.098528,-0.779929,0.618064,0.053746,0.03895,-0.005308, + 0,-0.786128,0.618064,0.055885,0.038816,-0.005308, + 0,-0.707106,0.707108,0.055885,0.038917,-0.005193, + -0.0444,-0.70571,0.707108,0.05482,0.038951,-0.005193, + 0,-0.786128,0.618064,0.055885,0.038816,-0.005308, + -0.0444,-0.70571,0.707108,0.05482,0.038951,-0.005193, + -0.049361,-0.784577,0.618064,0.054813,0.038849,-0.005308, + 0.049361,-0.784577,0.618064,0.056957,0.038849,-0.005308, + 0.0444,-0.70571,0.707108,0.056951,0.038951,-0.005193, + 0,-0.707106,0.707108,0.055885,0.038917,-0.005193, + 0.049361,-0.784577,0.618064,0.056957,0.038849,-0.005308, + 0,-0.707106,0.707108,0.055885,0.038917,-0.005193, + 0,-0.786128,0.618064,0.055885,0.038816,-0.005308, + 0.098528,-0.779929,0.618064,0.058025,0.03895,-0.005308, + 0.088624,-0.70153,0.707108,0.058012,0.039051,-0.005193, + 0.0444,-0.70571,0.707108,0.056951,0.038951,-0.005193, + 0.098528,-0.779929,0.618064,0.058025,0.03895,-0.005308, + 0.0444,-0.70571,0.707108,0.056951,0.038951,-0.005193, + 0.049361,-0.784577,0.618064,0.056957,0.038849,-0.005308, + 0.147306,-0.772203,0.618064,0.059084,0.039118,-0.005308, + 0.132498,-0.694581,0.707108,0.059065,0.039218,-0.005193, + 0.088624,-0.70153,0.707108,0.058012,0.039051,-0.005193, + 0.147306,-0.772203,0.618064,0.059084,0.039118,-0.005308, + 0.088624,-0.70153,0.707108,0.058012,0.039051,-0.005193, + 0.098528,-0.779929,0.618064,0.058025,0.03895,-0.005308, + 0.195502,-0.76143,0.618064,0.06013,0.039352,-0.005308, + 0.17585,-0.684891,0.707108,0.060105,0.03945,-0.005193, + 0.132498,-0.694581,0.707108,0.059065,0.039218,-0.005193, + 0.195502,-0.76143,0.618064,0.06013,0.039352,-0.005308, + 0.132498,-0.694581,0.707108,0.059065,0.039218,-0.005193, + 0.147306,-0.772203,0.618064,0.059084,0.039118,-0.005308, + 0.242927,-0.747652,0.618064,0.06116,0.039651,-0.005308, + 0.218508,-0.672497,0.707108,0.061129,0.039748,-0.005193, + 0.17585,-0.684891,0.707108,0.060105,0.03945,-0.005193, + 0.242927,-0.747652,0.618064,0.06116,0.039651,-0.005308, + 0.17585,-0.684891,0.707108,0.060105,0.03945,-0.005193, + 0.195502,-0.76143,0.618064,0.06013,0.039352,-0.005308, + 0.289393,-0.730923,0.618064,0.062169,0.040014,-0.005308, + 0.260303,-0.65745,0.707108,0.062132,0.040109,-0.005193, + 0.218508,-0.672497,0.707108,0.061129,0.039748,-0.005193, + 0.289393,-0.730923,0.618064,0.062169,0.040014,-0.005308, + 0.218508,-0.672497,0.707108,0.061129,0.039748,-0.005193, + 0.242927,-0.747652,0.618064,0.06116,0.039651,-0.005308, + 0.334717,-0.71131,0.618064,0.063153,0.04044,-0.005308, + 0.301071,-0.639808,0.707108,0.06311,0.040532,-0.005193, + 0.260303,-0.65745,0.707108,0.062132,0.040109,-0.005193, + 0.334717,-0.71131,0.618064,0.063153,0.04044,-0.005308, + 0.260303,-0.65745,0.707108,0.062132,0.040109,-0.005193, + 0.289393,-0.730923,0.618064,0.062169,0.040014,-0.005308, + 0.37872,-0.688889,0.618064,0.064109,0.040927,-0.005308, + 0.340651,-0.619641,0.707108,0.06406,0.041016,-0.005193, + 0.301071,-0.639808,0.707108,0.06311,0.040532,-0.005193, + 0.37872,-0.688889,0.618064,0.064109,0.040927,-0.005308, + 0.301071,-0.639808,0.707108,0.06311,0.040532,-0.005193, + 0.334717,-0.71131,0.618064,0.063153,0.04044,-0.005308, + 0.421228,-0.66375,0.618064,0.065032,0.041473,-0.005308, + 0.378886,-0.597029,0.707108,0.064977,0.041559,-0.005193, + 0.340651,-0.619641,0.707108,0.06406,0.041016,-0.005193, + 0.421228,-0.66375,0.618064,0.065032,0.041473,-0.005308, + 0.340651,-0.619641,0.707108,0.06406,0.041016,-0.005193, + 0.37872,-0.688889,0.618064,0.064109,0.040927,-0.005308, + 0.462074,-0.635991,0.618064,0.065919,0.042076,-0.005308, + 0.415626,-0.57206,0.707108,0.065859,0.042158,-0.005193, + 0.378886,-0.597029,0.707108,0.064977,0.041559,-0.005193, + 0.462074,-0.635991,0.618064,0.065919,0.042076,-0.005308, + 0.378886,-0.597029,0.707108,0.064977,0.041559,-0.005193, + 0.421228,-0.66375,0.618064,0.065032,0.041473,-0.005308, + 0.501097,-0.605722,0.618064,0.066766,0.042733,-0.005308, + 0.450726,-0.544834,0.707108,0.066701,0.042811,-0.005193, + 0.415626,-0.57206,0.707108,0.065859,0.042158,-0.005193, + 0.501097,-0.605722,0.618064,0.066766,0.042733,-0.005308, + 0.415626,-0.57206,0.707108,0.065859,0.042158,-0.005193, + 0.462074,-0.635991,0.618064,0.065919,0.042076,-0.005308, + 0.538141,-0.573062,0.618064,0.06757,0.043442,-0.005308, + 0.484047,-0.515458,0.707108,0.067501,0.043516,-0.005193, + 0.450726,-0.544834,0.707108,0.066701,0.042811,-0.005193, + 0.538141,-0.573062,0.618064,0.06757,0.043442,-0.005308, + 0.450726,-0.544834,0.707108,0.066701,0.042811,-0.005193, + 0.501097,-0.605722,0.618064,0.066766,0.042733,-0.005308, + 0.573062,-0.538141,0.618064,0.068329,0.0442,-0.005308, + 0.515458,-0.484047,0.707108,0.068254,0.04427,-0.005193, + 0.484047,-0.515458,0.707108,0.067501,0.043516,-0.005193, + 0.573062,-0.538141,0.618064,0.068329,0.0442,-0.005308, + 0.484047,-0.515458,0.707108,0.067501,0.043516,-0.005193, + 0.538141,-0.573062,0.618064,0.06757,0.043442,-0.005308, + 0.605722,-0.501097,0.618064,0.069038,0.045005,-0.005308, + 0.544834,-0.450726,0.707108,0.068959,0.04507,-0.005193, + 0.515458,-0.484047,0.707108,0.068254,0.04427,-0.005193, + 0.605722,-0.501097,0.618064,0.069038,0.045005,-0.005308, + 0.515458,-0.484047,0.707108,0.068254,0.04427,-0.005193, + 0.573062,-0.538141,0.618064,0.068329,0.0442,-0.005308, + 0.635991,-0.462074,0.618064,0.069695,0.045852,-0.005308, + 0.57206,-0.415626,0.707108,0.069613,0.045912,-0.005193, + 0.544834,-0.450726,0.707108,0.068959,0.04507,-0.005193, + 0.635991,-0.462074,0.618064,0.069695,0.045852,-0.005308, + 0.544834,-0.450726,0.707108,0.068959,0.04507,-0.005193, + 0.605722,-0.501097,0.618064,0.069038,0.045005,-0.005308, + 0.66375,-0.421228,0.618064,0.070298,0.046739,-0.005308, + 0.597029,-0.378886,0.707108,0.070212,0.046793,-0.005193, + 0.57206,-0.415626,0.707108,0.069613,0.045912,-0.005193, + 0.66375,-0.421228,0.618064,0.070298,0.046739,-0.005308, + 0.57206,-0.415626,0.707108,0.069613,0.045912,-0.005193, + 0.635991,-0.462074,0.618064,0.069695,0.045852,-0.005308, + 0.688889,-0.37872,0.618064,0.070844,0.047662,-0.005308, + 0.619641,-0.340651,0.707108,0.070754,0.047711,-0.005193, + 0.597029,-0.378886,0.707108,0.070212,0.046793,-0.005193, + 0.688889,-0.37872,0.618064,0.070844,0.047662,-0.005308, + 0.597029,-0.378886,0.707108,0.070212,0.046793,-0.005193, + 0.66375,-0.421228,0.618064,0.070298,0.046739,-0.005308, + 0.71131,-0.334717,0.618064,0.07133,0.048617,-0.005308, + 0.639808,-0.301071,0.707108,0.071238,0.048661,-0.005193, + 0.619641,-0.340651,0.707108,0.070754,0.047711,-0.005193, + 0.71131,-0.334717,0.618064,0.07133,0.048617,-0.005308, + 0.619641,-0.340651,0.707108,0.070754,0.047711,-0.005193, + 0.688889,-0.37872,0.618064,0.070844,0.047662,-0.005308, + 0.730923,-0.289393,0.618064,0.071756,0.049601,-0.005308, + 0.65745,-0.260303,0.707108,0.071662,0.049639,-0.005193, + 0.639808,-0.301071,0.707108,0.071238,0.048661,-0.005193, + 0.730923,-0.289393,0.618064,0.071756,0.049601,-0.005308, + 0.639808,-0.301071,0.707108,0.071238,0.048661,-0.005193, + 0.71131,-0.334717,0.618064,0.07133,0.048617,-0.005308, + 0.747652,-0.242927,0.618064,0.07212,0.05061,-0.005308, + 0.672497,-0.218508,0.707108,0.072023,0.050642,-0.005193, + 0.65745,-0.260303,0.707108,0.071662,0.049639,-0.005193, + 0.747652,-0.242927,0.618064,0.07212,0.05061,-0.005308, + 0.65745,-0.260303,0.707108,0.071662,0.049639,-0.005193, + 0.730923,-0.289393,0.618064,0.071756,0.049601,-0.005308, + 0.76143,-0.195502,0.618064,0.072419,0.05164,-0.005308, + 0.684891,-0.17585,0.707108,0.07232,0.051666,-0.005193, + 0.672497,-0.218508,0.707108,0.072023,0.050642,-0.005193, + 0.76143,-0.195502,0.618064,0.072419,0.05164,-0.005308, + 0.672497,-0.218508,0.707108,0.072023,0.050642,-0.005193, + 0.747652,-0.242927,0.618064,0.07212,0.05061,-0.005308, + 0.772203,-0.147306,0.618064,0.072653,0.052687,-0.005308, + 0.694581,-0.132498,0.707108,0.072553,0.052706,-0.005193, + 0.684891,-0.17585,0.707108,0.07232,0.051666,-0.005193, + 0.772203,-0.147306,0.618064,0.072653,0.052687,-0.005308, + 0.684891,-0.17585,0.707108,0.07232,0.051666,-0.005193, + 0.76143,-0.195502,0.618064,0.072419,0.05164,-0.005308, + 0.779929,-0.098528,0.618064,0.07282,0.053746,-0.005308, + 0.70153,-0.088624,0.707108,0.072719,0.053759,-0.005193, + 0.694581,-0.132498,0.707108,0.072553,0.052706,-0.005193, + 0.779929,-0.098528,0.618064,0.07282,0.053746,-0.005308, + 0.694581,-0.132498,0.707108,0.072553,0.052706,-0.005193, + 0.772203,-0.147306,0.618064,0.072653,0.052687,-0.005308, + 0.784577,-0.049361,0.618064,0.072921,0.054813,-0.005308, + 0.70571,-0.0444,0.707108,0.07282,0.05482,-0.005193, + 0.70153,-0.088624,0.707108,0.072719,0.053759,-0.005193, + 0.784577,-0.049361,0.618064,0.072921,0.054813,-0.005308, + 0.70153,-0.088624,0.707108,0.072719,0.053759,-0.005193, + 0.779929,-0.098528,0.618064,0.07282,0.053746,-0.005308, + 0.786128,0,0.618064,0.072955,0.055885,-0.005308, + 0.707106,0,0.707108,0.072853,0.055885,-0.005193, + 0.70571,-0.0444,0.707108,0.07282,0.05482,-0.005193, + 0.786128,0,0.618064,0.072955,0.055885,-0.005308, + 0.70571,-0.0444,0.707108,0.07282,0.05482,-0.005193, + 0.784577,-0.049361,0.618064,0.072921,0.054813,-0.005308, + 0.784577,0.049361,0.618064,0.072921,0.056957,-0.005308, + 0.70571,0.0444,0.707108,0.07282,0.056951,-0.005193, + 0.707106,0,0.707108,0.072853,0.055885,-0.005193, + 0.784577,0.049361,0.618064,0.072921,0.056957,-0.005308, + 0.707106,0,0.707108,0.072853,0.055885,-0.005193, + 0.786128,0,0.618064,0.072955,0.055885,-0.005308, + 0.779929,0.098528,0.618064,0.07282,0.058025,-0.005308, + 0.70153,0.088624,0.707108,0.072719,0.058012,-0.005193, + 0.70571,0.0444,0.707108,0.07282,0.056951,-0.005193, + 0.779929,0.098528,0.618064,0.07282,0.058025,-0.005308, + 0.70571,0.0444,0.707108,0.07282,0.056951,-0.005193, + 0.784577,0.049361,0.618064,0.072921,0.056957,-0.005308, + 0.772203,0.147306,0.618064,0.072653,0.059084,-0.005308, + 0.694581,0.132498,0.707108,0.072553,0.059065,-0.005193, + 0.70153,0.088624,0.707108,0.072719,0.058012,-0.005193, + 0.772203,0.147306,0.618064,0.072653,0.059084,-0.005308, + 0.70153,0.088624,0.707108,0.072719,0.058012,-0.005193, + 0.779929,0.098528,0.618064,0.07282,0.058025,-0.005308, + 0.76143,0.195502,0.618064,0.072419,0.06013,-0.005308, + 0.684891,0.17585,0.707108,0.07232,0.060105,-0.005193, + 0.694581,0.132498,0.707108,0.072553,0.059065,-0.005193, + 0.76143,0.195502,0.618064,0.072419,0.06013,-0.005308, + 0.694581,0.132498,0.707108,0.072553,0.059065,-0.005193, + 0.772203,0.147306,0.618064,0.072653,0.059084,-0.005308, + 0.747652,0.242927,0.618064,0.07212,0.06116,-0.005308, + 0.672497,0.218508,0.707108,0.072023,0.061129,-0.005193, + 0.684891,0.17585,0.707108,0.07232,0.060105,-0.005193, + 0.747652,0.242927,0.618064,0.07212,0.06116,-0.005308, + 0.684891,0.17585,0.707108,0.07232,0.060105,-0.005193, + 0.76143,0.195502,0.618064,0.072419,0.06013,-0.005308, + 0.730923,0.289393,0.618064,0.071756,0.062169,-0.005308, + 0.65745,0.260303,0.707108,0.071662,0.062132,-0.005193, + 0.672497,0.218508,0.707108,0.072023,0.061129,-0.005193, + 0.730923,0.289393,0.618064,0.071756,0.062169,-0.005308, + 0.672497,0.218508,0.707108,0.072023,0.061129,-0.005193, + 0.747652,0.242927,0.618064,0.07212,0.06116,-0.005308, + 0.71131,0.334717,0.618064,0.07133,0.063153,-0.005308, + 0.639808,0.301071,0.707108,0.071238,0.06311,-0.005193, + 0.65745,0.260303,0.707108,0.071662,0.062132,-0.005193, + 0.71131,0.334717,0.618064,0.07133,0.063153,-0.005308, + 0.65745,0.260303,0.707108,0.071662,0.062132,-0.005193, + 0.730923,0.289393,0.618064,0.071756,0.062169,-0.005308, + 0.688889,0.37872,0.618064,0.070844,0.064109,-0.005308, + 0.619641,0.340651,0.707108,0.070754,0.06406,-0.005193, + 0.639808,0.301071,0.707108,0.071238,0.06311,-0.005193, + 0.688889,0.37872,0.618064,0.070844,0.064109,-0.005308, + 0.639808,0.301071,0.707108,0.071238,0.06311,-0.005193, + 0.71131,0.334717,0.618064,0.07133,0.063153,-0.005308, + 0.66375,0.421228,0.618064,0.070298,0.065032,-0.005308, + 0.597029,0.378886,0.707108,0.070212,0.064977,-0.005193, + 0.619641,0.340651,0.707108,0.070754,0.06406,-0.005193, + 0.66375,0.421228,0.618064,0.070298,0.065032,-0.005308, + 0.619641,0.340651,0.707108,0.070754,0.06406,-0.005193, + 0.688889,0.37872,0.618064,0.070844,0.064109,-0.005308, + 0.635991,0.462074,0.618064,0.069695,0.065919,-0.005308, + 0.57206,0.415626,0.707108,0.069613,0.065859,-0.005193, + 0.597029,0.378886,0.707108,0.070212,0.064977,-0.005193, + 0.635991,0.462074,0.618064,0.069695,0.065919,-0.005308, + 0.597029,0.378886,0.707108,0.070212,0.064977,-0.005193, + 0.66375,0.421228,0.618064,0.070298,0.065032,-0.005308, + 0.605722,0.501097,0.618064,0.069038,0.066766,-0.005308, + 0.544834,0.450726,0.707108,0.068959,0.066701,-0.005193, + 0.57206,0.415626,0.707108,0.069613,0.065859,-0.005193, + 0.605722,0.501097,0.618064,0.069038,0.066766,-0.005308, + 0.57206,0.415626,0.707108,0.069613,0.065859,-0.005193, + 0.635991,0.462074,0.618064,0.069695,0.065919,-0.005308, + 0.573062,0.538141,0.618064,0.068329,0.06757,-0.005308, + 0.515458,0.484047,0.707108,0.068254,0.067501,-0.005193, + 0.544834,0.450726,0.707108,0.068959,0.066701,-0.005193, + 0.573062,0.538141,0.618064,0.068329,0.06757,-0.005308, + 0.544834,0.450726,0.707108,0.068959,0.066701,-0.005193, + 0.605722,0.501097,0.618064,0.069038,0.066766,-0.005308, + 0.538141,0.573062,0.618064,0.06757,0.068329,-0.005308, + 0.484047,0.515458,0.707108,0.067501,0.068254,-0.005193, + 0.515458,0.484047,0.707108,0.068254,0.067501,-0.005193, + 0.538141,0.573062,0.618064,0.06757,0.068329,-0.005308, + 0.515458,0.484047,0.707108,0.068254,0.067501,-0.005193, + 0.573062,0.538141,0.618064,0.068329,0.06757,-0.005308, + 0.501097,0.605722,0.618064,0.066766,0.069038,-0.005308, + 0.450726,0.544834,0.707108,0.066701,0.068959,-0.005193, + 0.484047,0.515458,0.707108,0.067501,0.068254,-0.005193, + 0.501097,0.605722,0.618064,0.066766,0.069038,-0.005308, + 0.484047,0.515458,0.707108,0.067501,0.068254,-0.005193, + 0.538141,0.573062,0.618064,0.06757,0.068329,-0.005308, + 0.462074,0.635991,0.618064,0.065919,0.069695,-0.005308, + 0.415626,0.57206,0.707108,0.065859,0.069613,-0.005193, + 0.450726,0.544834,0.707108,0.066701,0.068959,-0.005193, + 0.462074,0.635991,0.618064,0.065919,0.069695,-0.005308, + 0.450726,0.544834,0.707108,0.066701,0.068959,-0.005193, + 0.501097,0.605722,0.618064,0.066766,0.069038,-0.005308, + 0.421228,0.66375,0.618064,0.065032,0.070298,-0.005308, + 0.378886,0.597029,0.707108,0.064977,0.070212,-0.005193, + 0.415626,0.57206,0.707108,0.065859,0.069613,-0.005193, + 0.421228,0.66375,0.618064,0.065032,0.070298,-0.005308, + 0.415626,0.57206,0.707108,0.065859,0.069613,-0.005193, + 0.462074,0.635991,0.618064,0.065919,0.069695,-0.005308, + 0.37872,0.688889,0.618064,0.064109,0.070844,-0.005308, + 0.340651,0.619641,0.707108,0.06406,0.070754,-0.005193, + 0.378886,0.597029,0.707108,0.064977,0.070212,-0.005193, + 0.37872,0.688889,0.618064,0.064109,0.070844,-0.005308, + 0.378886,0.597029,0.707108,0.064977,0.070212,-0.005193, + 0.421228,0.66375,0.618064,0.065032,0.070298,-0.005308, + 0.334717,0.71131,0.618064,0.063153,0.07133,-0.005308, + 0.301071,0.639808,0.707108,0.06311,0.071238,-0.005193, + 0.340651,0.619641,0.707108,0.06406,0.070754,-0.005193, + 0.334717,0.71131,0.618064,0.063153,0.07133,-0.005308, + 0.340651,0.619641,0.707108,0.06406,0.070754,-0.005193, + 0.37872,0.688889,0.618064,0.064109,0.070844,-0.005308, + 0.289393,0.730923,0.618064,0.062169,0.071756,-0.005308, + 0.260303,0.65745,0.707108,0.062132,0.071662,-0.005193, + 0.301071,0.639808,0.707108,0.06311,0.071238,-0.005193, + 0.289393,0.730923,0.618064,0.062169,0.071756,-0.005308, + 0.301071,0.639808,0.707108,0.06311,0.071238,-0.005193, + 0.334717,0.71131,0.618064,0.063153,0.07133,-0.005308, + 0.242927,0.747652,0.618064,0.06116,0.07212,-0.005308, + 0.218508,0.672497,0.707108,0.061129,0.072023,-0.005193, + 0.260303,0.65745,0.707108,0.062132,0.071662,-0.005193, + 0.242927,0.747652,0.618064,0.06116,0.07212,-0.005308, + 0.260303,0.65745,0.707108,0.062132,0.071662,-0.005193, + 0.289393,0.730923,0.618064,0.062169,0.071756,-0.005308, + 0.195502,0.76143,0.618064,0.06013,0.072419,-0.005308, + 0.17585,0.684891,0.707108,0.060105,0.07232,-0.005193, + 0.218508,0.672497,0.707108,0.061129,0.072023,-0.005193, + 0.195502,0.76143,0.618064,0.06013,0.072419,-0.005308, + 0.218508,0.672497,0.707108,0.061129,0.072023,-0.005193, + 0.242927,0.747652,0.618064,0.06116,0.07212,-0.005308, + 0.147306,0.772203,0.618064,0.059084,0.072653,-0.005308, + 0.132498,0.694581,0.707108,0.059065,0.072553,-0.005193, + 0.17585,0.684891,0.707108,0.060105,0.07232,-0.005193, + 0.147306,0.772203,0.618064,0.059084,0.072653,-0.005308, + 0.17585,0.684891,0.707108,0.060105,0.07232,-0.005193, + 0.195502,0.76143,0.618064,0.06013,0.072419,-0.005308, + 0.098528,0.779929,0.618064,0.058025,0.07282,-0.005308, + 0.088624,0.70153,0.707108,0.058012,0.072719,-0.005193, + 0.132498,0.694581,0.707108,0.059065,0.072553,-0.005193, + 0.098528,0.779929,0.618064,0.058025,0.07282,-0.005308, + 0.132498,0.694581,0.707108,0.059065,0.072553,-0.005193, + 0.147306,0.772203,0.618064,0.059084,0.072653,-0.005308, + 0.049361,0.784577,0.618064,0.056957,0.072921,-0.005308, + 0.0444,0.70571,0.707108,0.056951,0.07282,-0.005193, + 0.088624,0.70153,0.707108,0.058012,0.072719,-0.005193, + 0.049361,0.784577,0.618064,0.056957,0.072921,-0.005308, + 0.088624,0.70153,0.707108,0.058012,0.072719,-0.005193, + 0.098528,0.779929,0.618064,0.058025,0.07282,-0.005308, + 0,0.786128,0.618064,0.055885,0.072955,-0.005308, + 0,0.707106,0.707108,0.055885,0.072853,-0.005193, + 0.0444,0.70571,0.707108,0.056951,0.07282,-0.005193, + 0,0.786128,0.618064,0.055885,0.072955,-0.005308, + 0.0444,0.70571,0.707108,0.056951,0.07282,-0.005193, + 0.049361,0.784577,0.618064,0.056957,0.072921,-0.005308, + -0.049361,0.784577,0.618064,0.054813,0.072921,-0.005308, + -0.0444,0.70571,0.707108,0.05482,0.07282,-0.005193, + 0,0.707106,0.707108,0.055885,0.072853,-0.005193, + -0.049361,0.784577,0.618064,0.054813,0.072921,-0.005308, + 0,0.707106,0.707108,0.055885,0.072853,-0.005193, + 0,0.786128,0.618064,0.055885,0.072955,-0.005308, + -0.098528,0.779929,0.618064,0.053746,0.07282,-0.005308, + -0.088624,0.70153,0.707108,0.053759,0.072719,-0.005193, + -0.0444,0.70571,0.707108,0.05482,0.07282,-0.005193, + -0.098528,0.779929,0.618064,0.053746,0.07282,-0.005308, + -0.0444,0.70571,0.707108,0.05482,0.07282,-0.005193, + -0.049361,0.784577,0.618064,0.054813,0.072921,-0.005308, + -0.147306,0.772203,0.618064,0.052687,0.072653,-0.005308, + -0.132498,0.694581,0.707108,0.052706,0.072553,-0.005193, + -0.088624,0.70153,0.707108,0.053759,0.072719,-0.005193, + -0.147306,0.772203,0.618064,0.052687,0.072653,-0.005308, + -0.088624,0.70153,0.707108,0.053759,0.072719,-0.005193, + -0.098528,0.779929,0.618064,0.053746,0.07282,-0.005308, + -0.195502,0.76143,0.618064,0.05164,0.072419,-0.005308, + -0.17585,0.684891,0.707108,0.051666,0.07232,-0.005193, + -0.132498,0.694581,0.707108,0.052706,0.072553,-0.005193, + -0.195502,0.76143,0.618064,0.05164,0.072419,-0.005308, + -0.132498,0.694581,0.707108,0.052706,0.072553,-0.005193, + -0.147306,0.772203,0.618064,0.052687,0.072653,-0.005308, + -0.242927,0.747652,0.618064,0.05061,0.07212,-0.005308, + -0.218508,0.672497,0.707108,0.050642,0.072023,-0.005193, + -0.17585,0.684891,0.707108,0.051666,0.07232,-0.005193, + -0.242927,0.747652,0.618064,0.05061,0.07212,-0.005308, + -0.17585,0.684891,0.707108,0.051666,0.07232,-0.005193, + -0.195502,0.76143,0.618064,0.05164,0.072419,-0.005308, + -0.289393,0.730923,0.618064,0.049601,0.071756,-0.005308, + -0.260303,0.65745,0.707108,0.049639,0.071662,-0.005193, + -0.218508,0.672497,0.707108,0.050642,0.072023,-0.005193, + -0.289393,0.730923,0.618064,0.049601,0.071756,-0.005308, + -0.218508,0.672497,0.707108,0.050642,0.072023,-0.005193, + -0.242927,0.747652,0.618064,0.05061,0.07212,-0.005308, + -0.334717,0.71131,0.618064,0.048617,0.07133,-0.005308, + -0.301071,0.639808,0.707108,0.048661,0.071238,-0.005193, + -0.260303,0.65745,0.707108,0.049639,0.071662,-0.005193, + -0.334717,0.71131,0.618064,0.048617,0.07133,-0.005308, + -0.260303,0.65745,0.707108,0.049639,0.071662,-0.005193, + -0.289393,0.730923,0.618064,0.049601,0.071756,-0.005308, + -0.37872,0.688889,0.618064,0.047662,0.070844,-0.005308, + -0.340651,0.619641,0.707108,0.047711,0.070754,-0.005193, + -0.301071,0.639808,0.707108,0.048661,0.071238,-0.005193, + -0.37872,0.688889,0.618064,0.047662,0.070844,-0.005308, + -0.301071,0.639808,0.707108,0.048661,0.071238,-0.005193, + -0.334717,0.71131,0.618064,0.048617,0.07133,-0.005308, + -0.421228,0.66375,0.618064,0.046739,0.070298,-0.005308, + -0.378886,0.597029,0.707108,0.046793,0.070212,-0.005193, + -0.340651,0.619641,0.707108,0.047711,0.070754,-0.005193, + -0.421228,0.66375,0.618064,0.046739,0.070298,-0.005308, + -0.340651,0.619641,0.707108,0.047711,0.070754,-0.005193, + -0.37872,0.688889,0.618064,0.047662,0.070844,-0.005308, + -0.462074,0.635991,0.618064,0.045852,0.069695,-0.005308, + -0.415626,0.57206,0.707108,0.045912,0.069613,-0.005193, + -0.378886,0.597029,0.707108,0.046793,0.070212,-0.005193, + -0.462074,0.635991,0.618064,0.045852,0.069695,-0.005308, + -0.378886,0.597029,0.707108,0.046793,0.070212,-0.005193, + -0.421228,0.66375,0.618064,0.046739,0.070298,-0.005308, + -0.501097,0.605722,0.618064,0.045005,0.069038,-0.005308, + -0.450726,0.544834,0.707108,0.04507,0.068959,-0.005193, + -0.415626,0.57206,0.707108,0.045912,0.069613,-0.005193, + -0.501097,0.605722,0.618064,0.045005,0.069038,-0.005308, + -0.415626,0.57206,0.707108,0.045912,0.069613,-0.005193, + -0.462074,0.635991,0.618064,0.045852,0.069695,-0.005308, + -0.538141,0.573062,0.618064,0.0442,0.068329,-0.005308, + -0.484047,0.515458,0.707108,0.04427,0.068254,-0.005193, + -0.450726,0.544834,0.707108,0.04507,0.068959,-0.005193, + -0.538141,0.573062,0.618064,0.0442,0.068329,-0.005308, + -0.450726,0.544834,0.707108,0.04507,0.068959,-0.005193, + -0.501097,0.605722,0.618064,0.045005,0.069038,-0.005308, + -0.573062,0.538141,0.618064,0.043442,0.06757,-0.005308, + -0.515458,0.484047,0.707108,0.043516,0.067501,-0.005193, + -0.484047,0.515458,0.707108,0.04427,0.068254,-0.005193, + -0.573062,0.538141,0.618064,0.043442,0.06757,-0.005308, + -0.484047,0.515458,0.707108,0.04427,0.068254,-0.005193, + -0.538141,0.573062,0.618064,0.0442,0.068329,-0.005308, + -0.605722,0.501097,0.618064,0.042733,0.066766,-0.005308, + -0.544834,0.450726,0.707108,0.042811,0.066701,-0.005193, + -0.515458,0.484047,0.707108,0.043516,0.067501,-0.005193, + -0.605722,0.501097,0.618064,0.042733,0.066766,-0.005308, + -0.515458,0.484047,0.707108,0.043516,0.067501,-0.005193, + -0.573062,0.538141,0.618064,0.043442,0.06757,-0.005308, + -0.635991,0.462074,0.618064,0.042076,0.065919,-0.005308, + -0.57206,0.415626,0.707108,0.042158,0.065859,-0.005193, + -0.544834,0.450726,0.707108,0.042811,0.066701,-0.005193, + -0.635991,0.462074,0.618064,0.042076,0.065919,-0.005308, + -0.544834,0.450726,0.707108,0.042811,0.066701,-0.005193, + -0.605722,0.501097,0.618064,0.042733,0.066766,-0.005308, + -0.66375,0.421228,0.618064,0.041473,0.065032,-0.005308, + -0.597029,0.378886,0.707108,0.041559,0.064977,-0.005193, + -0.57206,0.415626,0.707108,0.042158,0.065859,-0.005193, + -0.66375,0.421228,0.618064,0.041473,0.065032,-0.005308, + -0.57206,0.415626,0.707108,0.042158,0.065859,-0.005193, + -0.635991,0.462074,0.618064,0.042076,0.065919,-0.005308, + -0.688889,0.37872,0.618064,0.040927,0.064109,-0.005308, + -0.619641,0.340651,0.707108,0.041016,0.06406,-0.005193, + -0.597029,0.378886,0.707108,0.041559,0.064977,-0.005193, + -0.688889,0.37872,0.618064,0.040927,0.064109,-0.005308, + -0.597029,0.378886,0.707108,0.041559,0.064977,-0.005193, + -0.66375,0.421228,0.618064,0.041473,0.065032,-0.005308, + -0.71131,0.334717,0.618064,0.04044,0.063153,-0.005308, + -0.639808,0.301071,0.707108,0.040532,0.06311,-0.005193, + -0.619641,0.340651,0.707108,0.041016,0.06406,-0.005193, + -0.71131,0.334717,0.618064,0.04044,0.063153,-0.005308, + -0.619641,0.340651,0.707108,0.041016,0.06406,-0.005193, + -0.688889,0.37872,0.618064,0.040927,0.064109,-0.005308, + -0.730923,0.289393,0.618064,0.040014,0.062169,-0.005308, + -0.65745,0.260303,0.707108,0.040109,0.062132,-0.005193, + -0.639808,0.301071,0.707108,0.040532,0.06311,-0.005193, + -0.730923,0.289393,0.618064,0.040014,0.062169,-0.005308, + -0.639808,0.301071,0.707108,0.040532,0.06311,-0.005193, + -0.71131,0.334717,0.618064,0.04044,0.063153,-0.005308, + -0.747652,0.242927,0.618064,0.039651,0.06116,-0.005308, + -0.672497,0.218508,0.707108,0.039748,0.061129,-0.005193, + -0.65745,0.260303,0.707108,0.040109,0.062132,-0.005193, + -0.747652,0.242927,0.618064,0.039651,0.06116,-0.005308, + -0.65745,0.260303,0.707108,0.040109,0.062132,-0.005193, + -0.730923,0.289393,0.618064,0.040014,0.062169,-0.005308, + -0.76143,0.195502,0.618064,0.039352,0.06013,-0.005308, + -0.684891,0.17585,0.707108,0.03945,0.060105,-0.005193, + -0.672497,0.218508,0.707108,0.039748,0.061129,-0.005193, + -0.76143,0.195502,0.618064,0.039352,0.06013,-0.005308, + -0.672497,0.218508,0.707108,0.039748,0.061129,-0.005193, + -0.747652,0.242927,0.618064,0.039651,0.06116,-0.005308, + -0.772203,0.147306,0.618064,0.039118,0.059084,-0.005308, + -0.694581,0.132498,0.707108,0.039218,0.059065,-0.005193, + -0.684891,0.17585,0.707108,0.03945,0.060105,-0.005193, + -0.772203,0.147306,0.618064,0.039118,0.059084,-0.005308, + -0.684891,0.17585,0.707108,0.03945,0.060105,-0.005193, + -0.76143,0.195502,0.618064,0.039352,0.06013,-0.005308, + -0.779929,0.098528,0.618064,0.03895,0.058025,-0.005308, + -0.70153,0.088624,0.707108,0.039051,0.058012,-0.005193, + -0.694581,0.132498,0.707108,0.039218,0.059065,-0.005193, + -0.779929,0.098528,0.618064,0.03895,0.058025,-0.005308, + -0.694581,0.132498,0.707108,0.039218,0.059065,-0.005193, + -0.772203,0.147306,0.618064,0.039118,0.059084,-0.005308, + -0.784577,0.049361,0.618064,0.038849,0.056957,-0.005308, + -0.70571,0.0444,0.707108,0.038951,0.056951,-0.005193, + -0.70153,0.088624,0.707108,0.039051,0.058012,-0.005193, + -0.784577,0.049361,0.618064,0.038849,0.056957,-0.005308, + -0.70153,0.088624,0.707108,0.039051,0.058012,-0.005193, + -0.779929,0.098528,0.618064,0.03895,0.058025,-0.005308, + -0.786128,0,0.618064,0.038816,0.055885,-0.005308, + -0.707106,0,0.707108,0.038917,0.055885,-0.005193, + -0.70571,0.0444,0.707108,0.038951,0.056951,-0.005193, + -0.786128,0,0.618064,0.038816,0.055885,-0.005308, + -0.70571,0.0444,0.707108,0.038951,0.056951,-0.005193, + -0.784577,0.049361,0.618064,0.038849,0.056957,-0.005308, + -0.707106,0,0.707108,0.038917,0.055885,-0.005193, + -0.618061,0,0.78613,0.039032,0.055885,-0.005092, + -0.616842,0.038808,0.78613,0.039065,0.056943,-0.005092, + -0.707106,0,0.707108,0.038917,0.055885,-0.005193, + -0.616842,0.038808,0.78613,0.039065,0.056943,-0.005092, + -0.70571,0.0444,0.707108,0.038951,0.056951,-0.005193, + -0.70571,-0.0444,0.707108,0.038951,0.05482,-0.005193, + -0.616842,-0.038808,0.78613,0.039065,0.054827,-0.005092, + -0.618061,0,0.78613,0.039032,0.055885,-0.005092, + -0.70571,-0.0444,0.707108,0.038951,0.05482,-0.005193, + -0.618061,0,0.78613,0.039032,0.055885,-0.005092, + -0.707106,0,0.707108,0.038917,0.055885,-0.005193, + -0.70153,-0.088624,0.707108,0.039051,0.053759,-0.005193, + -0.613188,-0.077464,0.78613,0.039165,0.053773,-0.005092, + -0.616842,-0.038808,0.78613,0.039065,0.054827,-0.005092, + -0.70153,-0.088624,0.707108,0.039051,0.053759,-0.005193, + -0.616842,-0.038808,0.78613,0.039065,0.054827,-0.005092, + -0.70571,-0.0444,0.707108,0.038951,0.05482,-0.005193, + -0.694581,-0.132498,0.707108,0.039218,0.052706,-0.005193, + -0.607114,-0.115813,0.78613,0.039331,0.052727,-0.005092, + -0.613188,-0.077464,0.78613,0.039165,0.053773,-0.005092, + -0.694581,-0.132498,0.707108,0.039218,0.052706,-0.005193, + -0.613188,-0.077464,0.78613,0.039165,0.053773,-0.005092, + -0.70153,-0.088624,0.707108,0.039051,0.053759,-0.005193, + -0.684891,-0.17585,0.707108,0.03945,0.051666,-0.005193, + -0.598644,-0.153706,0.78613,0.039562,0.051694,-0.005092, + -0.607114,-0.115813,0.78613,0.039331,0.052727,-0.005092, + -0.684891,-0.17585,0.707108,0.03945,0.051666,-0.005193, + -0.607114,-0.115813,0.78613,0.039331,0.052727,-0.005092, + -0.694581,-0.132498,0.707108,0.039218,0.052706,-0.005193, + -0.672497,-0.218508,0.707108,0.039748,0.050642,-0.005193, + -0.587811,-0.190991,0.78613,0.039857,0.050677,-0.005092, + -0.598644,-0.153706,0.78613,0.039562,0.051694,-0.005092, + -0.672497,-0.218508,0.707108,0.039748,0.050642,-0.005193, + -0.598644,-0.153706,0.78613,0.039562,0.051694,-0.005092, + -0.684891,-0.17585,0.707108,0.03945,0.051666,-0.005193, + -0.65745,-0.260303,0.707108,0.040109,0.049639,-0.005193, + -0.574659,-0.227524,0.78613,0.040215,0.049681,-0.005092, + -0.587811,-0.190991,0.78613,0.039857,0.050677,-0.005092, + -0.65745,-0.260303,0.707108,0.040109,0.049639,-0.005193, + -0.587811,-0.190991,0.78613,0.039857,0.050677,-0.005092, + -0.672497,-0.218508,0.707108,0.039748,0.050642,-0.005193, + -0.639808,-0.301071,0.707108,0.040532,0.048661,-0.005193, + -0.559239,-0.263158,0.78613,0.040636,0.048709,-0.005092, + -0.574659,-0.227524,0.78613,0.040215,0.049681,-0.005092, + -0.639808,-0.301071,0.707108,0.040532,0.048661,-0.005193, + -0.574659,-0.227524,0.78613,0.040215,0.049681,-0.005092, + -0.65745,-0.260303,0.707108,0.040109,0.049639,-0.005193, + -0.619641,-0.340651,0.707108,0.041016,0.047711,-0.005193, + -0.541611,-0.297753,0.78613,0.041117,0.047766,-0.005092, + -0.559239,-0.263158,0.78613,0.040636,0.048709,-0.005092, + -0.619641,-0.340651,0.707108,0.041016,0.047711,-0.005193, + -0.559239,-0.263158,0.78613,0.040636,0.048709,-0.005092, + -0.639808,-0.301071,0.707108,0.040532,0.048661,-0.005193, + -0.597029,-0.378886,0.707108,0.041559,0.046793,-0.005193, + -0.521846,-0.331174,0.78613,0.041656,0.046855,-0.005092, + -0.541611,-0.297753,0.78613,0.041117,0.047766,-0.005092, + -0.597029,-0.378886,0.707108,0.041559,0.046793,-0.005193, + -0.541611,-0.297753,0.78613,0.041117,0.047766,-0.005092, + -0.619641,-0.340651,0.707108,0.041016,0.047711,-0.005193, + -0.57206,-0.415626,0.707108,0.042158,0.045912,-0.005193, + -0.500022,-0.363287,0.78613,0.042251,0.045979,-0.005092, + -0.521846,-0.331174,0.78613,0.041656,0.046855,-0.005092, + -0.57206,-0.415626,0.707108,0.042158,0.045912,-0.005193, + -0.521846,-0.331174,0.78613,0.041656,0.046855,-0.005092, + -0.597029,-0.378886,0.707108,0.041559,0.046793,-0.005193, + -0.544834,-0.450726,0.707108,0.042811,0.04507,-0.005193, + -0.476224,-0.393967,0.78613,0.0429,0.045143,-0.005092, + -0.500022,-0.363287,0.78613,0.042251,0.045979,-0.005092, + -0.544834,-0.450726,0.707108,0.042811,0.04507,-0.005193, + -0.500022,-0.363287,0.78613,0.042251,0.045979,-0.005092, + -0.57206,-0.415626,0.707108,0.042158,0.045912,-0.005193, + -0.515458,-0.484047,0.707108,0.043516,0.04427,-0.005193, + -0.450547,-0.423092,0.78613,0.0436,0.044348,-0.005092, + -0.476224,-0.393967,0.78613,0.0429,0.045143,-0.005092, + -0.515458,-0.484047,0.707108,0.043516,0.04427,-0.005193, + -0.476224,-0.393967,0.78613,0.0429,0.045143,-0.005092, + -0.544834,-0.450726,0.707108,0.042811,0.04507,-0.005193, + -0.484047,-0.515458,0.707108,0.04427,0.043516,-0.005193, + -0.423092,-0.450547,0.78613,0.044348,0.0436,-0.005092, + -0.450547,-0.423092,0.78613,0.0436,0.044348,-0.005092, + -0.484047,-0.515458,0.707108,0.04427,0.043516,-0.005193, + -0.450547,-0.423092,0.78613,0.0436,0.044348,-0.005092, + -0.515458,-0.484047,0.707108,0.043516,0.04427,-0.005193, + -0.450726,-0.544834,0.707108,0.04507,0.042811,-0.005193, + -0.393967,-0.476224,0.78613,0.045143,0.0429,-0.005092, + -0.423092,-0.450547,0.78613,0.044348,0.0436,-0.005092, + -0.450726,-0.544834,0.707108,0.04507,0.042811,-0.005193, + -0.423092,-0.450547,0.78613,0.044348,0.0436,-0.005092, + -0.484047,-0.515458,0.707108,0.04427,0.043516,-0.005193, + -0.415626,-0.57206,0.707108,0.045912,0.042158,-0.005193, + -0.363287,-0.500022,0.78613,0.045979,0.042251,-0.005092, + -0.393967,-0.476224,0.78613,0.045143,0.0429,-0.005092, + -0.415626,-0.57206,0.707108,0.045912,0.042158,-0.005193, + -0.393967,-0.476224,0.78613,0.045143,0.0429,-0.005092, + -0.450726,-0.544834,0.707108,0.04507,0.042811,-0.005193, + -0.378886,-0.597029,0.707108,0.046793,0.041559,-0.005193, + -0.331174,-0.521846,0.78613,0.046855,0.041656,-0.005092, + -0.363287,-0.500022,0.78613,0.045979,0.042251,-0.005092, + -0.378886,-0.597029,0.707108,0.046793,0.041559,-0.005193, + -0.363287,-0.500022,0.78613,0.045979,0.042251,-0.005092, + -0.415626,-0.57206,0.707108,0.045912,0.042158,-0.005193, + -0.340651,-0.619641,0.707108,0.047711,0.041016,-0.005193, + -0.297753,-0.541611,0.78613,0.047766,0.041117,-0.005092, + -0.331174,-0.521846,0.78613,0.046855,0.041656,-0.005092, + -0.340651,-0.619641,0.707108,0.047711,0.041016,-0.005193, + -0.331174,-0.521846,0.78613,0.046855,0.041656,-0.005092, + -0.378886,-0.597029,0.707108,0.046793,0.041559,-0.005193, + -0.301071,-0.639808,0.707108,0.048661,0.040532,-0.005193, + -0.263158,-0.559239,0.78613,0.048709,0.040636,-0.005092, + -0.297753,-0.541611,0.78613,0.047766,0.041117,-0.005092, + -0.301071,-0.639808,0.707108,0.048661,0.040532,-0.005193, + -0.297753,-0.541611,0.78613,0.047766,0.041117,-0.005092, + -0.340651,-0.619641,0.707108,0.047711,0.041016,-0.005193, + -0.260303,-0.65745,0.707108,0.049639,0.040109,-0.005193, + -0.227524,-0.574659,0.78613,0.049681,0.040215,-0.005092, + -0.263158,-0.559239,0.78613,0.048709,0.040636,-0.005092, + -0.260303,-0.65745,0.707108,0.049639,0.040109,-0.005193, + -0.263158,-0.559239,0.78613,0.048709,0.040636,-0.005092, + -0.301071,-0.639808,0.707108,0.048661,0.040532,-0.005193, + -0.218508,-0.672497,0.707108,0.050642,0.039748,-0.005193, + -0.190991,-0.587811,0.78613,0.050677,0.039857,-0.005092, + -0.227524,-0.574659,0.78613,0.049681,0.040215,-0.005092, + -0.218508,-0.672497,0.707108,0.050642,0.039748,-0.005193, + -0.227524,-0.574659,0.78613,0.049681,0.040215,-0.005092, + -0.260303,-0.65745,0.707108,0.049639,0.040109,-0.005193, + -0.17585,-0.684891,0.707108,0.051666,0.03945,-0.005193, + -0.153706,-0.598644,0.78613,0.051694,0.039562,-0.005092, + -0.190991,-0.587811,0.78613,0.050677,0.039857,-0.005092, + -0.17585,-0.684891,0.707108,0.051666,0.03945,-0.005193, + -0.190991,-0.587811,0.78613,0.050677,0.039857,-0.005092, + -0.218508,-0.672497,0.707108,0.050642,0.039748,-0.005193, + -0.132498,-0.694581,0.707108,0.052706,0.039218,-0.005193, + -0.115813,-0.607114,0.78613,0.052727,0.039331,-0.005092, + -0.153706,-0.598644,0.78613,0.051694,0.039562,-0.005092, + -0.132498,-0.694581,0.707108,0.052706,0.039218,-0.005193, + -0.153706,-0.598644,0.78613,0.051694,0.039562,-0.005092, + -0.17585,-0.684891,0.707108,0.051666,0.03945,-0.005193, + -0.088624,-0.70153,0.707108,0.053759,0.039051,-0.005193, + -0.077464,-0.613188,0.78613,0.053773,0.039165,-0.005092, + -0.115813,-0.607114,0.78613,0.052727,0.039331,-0.005092, + -0.088624,-0.70153,0.707108,0.053759,0.039051,-0.005193, + -0.115813,-0.607114,0.78613,0.052727,0.039331,-0.005092, + -0.132498,-0.694581,0.707108,0.052706,0.039218,-0.005193, + -0.0444,-0.70571,0.707108,0.05482,0.038951,-0.005193, + -0.038808,-0.616842,0.78613,0.054827,0.039065,-0.005092, + -0.077464,-0.613188,0.78613,0.053773,0.039165,-0.005092, + -0.0444,-0.70571,0.707108,0.05482,0.038951,-0.005193, + -0.077464,-0.613188,0.78613,0.053773,0.039165,-0.005092, + -0.088624,-0.70153,0.707108,0.053759,0.039051,-0.005193, + 0,-0.707106,0.707108,0.055885,0.038917,-0.005193, + 0,-0.618061,0.78613,0.055885,0.039032,-0.005092, + -0.038808,-0.616842,0.78613,0.054827,0.039065,-0.005092, + 0,-0.707106,0.707108,0.055885,0.038917,-0.005193, + -0.038808,-0.616842,0.78613,0.054827,0.039065,-0.005092, + -0.0444,-0.70571,0.707108,0.05482,0.038951,-0.005193, + 0.0444,-0.70571,0.707108,0.056951,0.038951,-0.005193, + 0.038808,-0.616842,0.78613,0.056943,0.039065,-0.005092, + 0,-0.618061,0.78613,0.055885,0.039032,-0.005092, + 0.0444,-0.70571,0.707108,0.056951,0.038951,-0.005193, + 0,-0.618061,0.78613,0.055885,0.039032,-0.005092, + 0,-0.707106,0.707108,0.055885,0.038917,-0.005193, + 0.088624,-0.70153,0.707108,0.058012,0.039051,-0.005193, + 0.077464,-0.613188,0.78613,0.057998,0.039165,-0.005092, + 0.038808,-0.616842,0.78613,0.056943,0.039065,-0.005092, + 0.088624,-0.70153,0.707108,0.058012,0.039051,-0.005193, + 0.038808,-0.616842,0.78613,0.056943,0.039065,-0.005092, + 0.0444,-0.70571,0.707108,0.056951,0.038951,-0.005193, + 0.132498,-0.694581,0.707108,0.059065,0.039218,-0.005193, + 0.115813,-0.607114,0.78613,0.059043,0.039331,-0.005092, + 0.077464,-0.613188,0.78613,0.057998,0.039165,-0.005092, + 0.132498,-0.694581,0.707108,0.059065,0.039218,-0.005193, + 0.077464,-0.613188,0.78613,0.057998,0.039165,-0.005092, + 0.088624,-0.70153,0.707108,0.058012,0.039051,-0.005193, + 0.17585,-0.684891,0.707108,0.060105,0.03945,-0.005193, + 0.153706,-0.598644,0.78613,0.060077,0.039562,-0.005092, + 0.115813,-0.607114,0.78613,0.059043,0.039331,-0.005092, + 0.17585,-0.684891,0.707108,0.060105,0.03945,-0.005193, + 0.115813,-0.607114,0.78613,0.059043,0.039331,-0.005092, + 0.132498,-0.694581,0.707108,0.059065,0.039218,-0.005193, + 0.218508,-0.672497,0.707108,0.061129,0.039748,-0.005193, + 0.190991,-0.587811,0.78613,0.061093,0.039857,-0.005092, + 0.153706,-0.598644,0.78613,0.060077,0.039562,-0.005092, + 0.218508,-0.672497,0.707108,0.061129,0.039748,-0.005193, + 0.153706,-0.598644,0.78613,0.060077,0.039562,-0.005092, + 0.17585,-0.684891,0.707108,0.060105,0.03945,-0.005193, + 0.260303,-0.65745,0.707108,0.062132,0.040109,-0.005193, + 0.227524,-0.574659,0.78613,0.062089,0.040215,-0.005092, + 0.190991,-0.587811,0.78613,0.061093,0.039857,-0.005092, + 0.260303,-0.65745,0.707108,0.062132,0.040109,-0.005193, + 0.190991,-0.587811,0.78613,0.061093,0.039857,-0.005092, + 0.218508,-0.672497,0.707108,0.061129,0.039748,-0.005193, + 0.301071,-0.639808,0.707108,0.06311,0.040532,-0.005193, + 0.263158,-0.559239,0.78613,0.063061,0.040636,-0.005092, + 0.227524,-0.574659,0.78613,0.062089,0.040215,-0.005092, + 0.301071,-0.639808,0.707108,0.06311,0.040532,-0.005193, + 0.227524,-0.574659,0.78613,0.062089,0.040215,-0.005092, + 0.260303,-0.65745,0.707108,0.062132,0.040109,-0.005193, + 0.340651,-0.619641,0.707108,0.06406,0.041016,-0.005193, + 0.297753,-0.541611,0.78613,0.064004,0.041117,-0.005092, + 0.263158,-0.559239,0.78613,0.063061,0.040636,-0.005092, + 0.340651,-0.619641,0.707108,0.06406,0.041016,-0.005193, + 0.263158,-0.559239,0.78613,0.063061,0.040636,-0.005092, + 0.301071,-0.639808,0.707108,0.06311,0.040532,-0.005193, + 0.378886,-0.597029,0.707108,0.064977,0.041559,-0.005193, + 0.331174,-0.521846,0.78613,0.064916,0.041656,-0.005092, + 0.297753,-0.541611,0.78613,0.064004,0.041117,-0.005092, + 0.378886,-0.597029,0.707108,0.064977,0.041559,-0.005193, + 0.297753,-0.541611,0.78613,0.064004,0.041117,-0.005092, + 0.340651,-0.619641,0.707108,0.06406,0.041016,-0.005193, + 0.415626,-0.57206,0.707108,0.065859,0.042158,-0.005193, + 0.363287,-0.500022,0.78613,0.065791,0.042251,-0.005092, + 0.331174,-0.521846,0.78613,0.064916,0.041656,-0.005092, + 0.415626,-0.57206,0.707108,0.065859,0.042158,-0.005193, + 0.331174,-0.521846,0.78613,0.064916,0.041656,-0.005092, + 0.378886,-0.597029,0.707108,0.064977,0.041559,-0.005193, + 0.450726,-0.544834,0.707108,0.066701,0.042811,-0.005193, + 0.393967,-0.476224,0.78613,0.066628,0.0429,-0.005092, + 0.363287,-0.500022,0.78613,0.065791,0.042251,-0.005092, + 0.450726,-0.544834,0.707108,0.066701,0.042811,-0.005193, + 0.363287,-0.500022,0.78613,0.065791,0.042251,-0.005092, + 0.415626,-0.57206,0.707108,0.065859,0.042158,-0.005193, + 0.484047,-0.515458,0.707108,0.067501,0.043516,-0.005193, + 0.423092,-0.450547,0.78613,0.067422,0.0436,-0.005092, + 0.393967,-0.476224,0.78613,0.066628,0.0429,-0.005092, + 0.484047,-0.515458,0.707108,0.067501,0.043516,-0.005193, + 0.393967,-0.476224,0.78613,0.066628,0.0429,-0.005092, + 0.450726,-0.544834,0.707108,0.066701,0.042811,-0.005193, + 0.515458,-0.484047,0.707108,0.068254,0.04427,-0.005193, + 0.450547,-0.423092,0.78613,0.068171,0.044348,-0.005092, + 0.423092,-0.450547,0.78613,0.067422,0.0436,-0.005092, + 0.515458,-0.484047,0.707108,0.068254,0.04427,-0.005193, + 0.423092,-0.450547,0.78613,0.067422,0.0436,-0.005092, + 0.484047,-0.515458,0.707108,0.067501,0.043516,-0.005193, + 0.544834,-0.450726,0.707108,0.068959,0.04507,-0.005193, + 0.476224,-0.393967,0.78613,0.068871,0.045143,-0.005092, + 0.450547,-0.423092,0.78613,0.068171,0.044348,-0.005092, + 0.544834,-0.450726,0.707108,0.068959,0.04507,-0.005193, + 0.450547,-0.423092,0.78613,0.068171,0.044348,-0.005092, + 0.515458,-0.484047,0.707108,0.068254,0.04427,-0.005193, + 0.57206,-0.415626,0.707108,0.069613,0.045912,-0.005193, + 0.500022,-0.363287,0.78613,0.06952,0.045979,-0.005092, + 0.476224,-0.393967,0.78613,0.068871,0.045143,-0.005092, + 0.57206,-0.415626,0.707108,0.069613,0.045912,-0.005193, + 0.476224,-0.393967,0.78613,0.068871,0.045143,-0.005092, + 0.544834,-0.450726,0.707108,0.068959,0.04507,-0.005193, + 0.597029,-0.378886,0.707108,0.070212,0.046793,-0.005193, + 0.521846,-0.331174,0.78613,0.070115,0.046855,-0.005092, + 0.500022,-0.363287,0.78613,0.06952,0.045979,-0.005092, + 0.597029,-0.378886,0.707108,0.070212,0.046793,-0.005193, + 0.500022,-0.363287,0.78613,0.06952,0.045979,-0.005092, + 0.57206,-0.415626,0.707108,0.069613,0.045912,-0.005193, + 0.619641,-0.340651,0.707108,0.070754,0.047711,-0.005193, + 0.541611,-0.297753,0.78613,0.070654,0.047766,-0.005092, + 0.521846,-0.331174,0.78613,0.070115,0.046855,-0.005092, + 0.619641,-0.340651,0.707108,0.070754,0.047711,-0.005193, + 0.521846,-0.331174,0.78613,0.070115,0.046855,-0.005092, + 0.597029,-0.378886,0.707108,0.070212,0.046793,-0.005193, + 0.639808,-0.301071,0.707108,0.071238,0.048661,-0.005193, + 0.559239,-0.263158,0.78613,0.071135,0.048709,-0.005092, + 0.541611,-0.297753,0.78613,0.070654,0.047766,-0.005092, + 0.639808,-0.301071,0.707108,0.071238,0.048661,-0.005193, + 0.541611,-0.297753,0.78613,0.070654,0.047766,-0.005092, + 0.619641,-0.340651,0.707108,0.070754,0.047711,-0.005193, + 0.65745,-0.260303,0.707108,0.071662,0.049639,-0.005193, + 0.574659,-0.227524,0.78613,0.071555,0.049681,-0.005092, + 0.559239,-0.263158,0.78613,0.071135,0.048709,-0.005092, + 0.65745,-0.260303,0.707108,0.071662,0.049639,-0.005193, + 0.559239,-0.263158,0.78613,0.071135,0.048709,-0.005092, + 0.639808,-0.301071,0.707108,0.071238,0.048661,-0.005193, + 0.672497,-0.218508,0.707108,0.072023,0.050642,-0.005193, + 0.587811,-0.190991,0.78613,0.071914,0.050677,-0.005092, + 0.574659,-0.227524,0.78613,0.071555,0.049681,-0.005092, + 0.672497,-0.218508,0.707108,0.072023,0.050642,-0.005193, + 0.574659,-0.227524,0.78613,0.071555,0.049681,-0.005092, + 0.65745,-0.260303,0.707108,0.071662,0.049639,-0.005193, + 0.684891,-0.17585,0.707108,0.07232,0.051666,-0.005193, + 0.598644,-0.153706,0.78613,0.072209,0.051694,-0.005092, + 0.587811,-0.190991,0.78613,0.071914,0.050677,-0.005092, + 0.684891,-0.17585,0.707108,0.07232,0.051666,-0.005193, + 0.587811,-0.190991,0.78613,0.071914,0.050677,-0.005092, + 0.672497,-0.218508,0.707108,0.072023,0.050642,-0.005193, + 0.694581,-0.132498,0.707108,0.072553,0.052706,-0.005193, + 0.607114,-0.115813,0.78613,0.07244,0.052727,-0.005092, + 0.598644,-0.153706,0.78613,0.072209,0.051694,-0.005092, + 0.694581,-0.132498,0.707108,0.072553,0.052706,-0.005193, + 0.598644,-0.153706,0.78613,0.072209,0.051694,-0.005092, + 0.684891,-0.17585,0.707108,0.07232,0.051666,-0.005193, + 0.70153,-0.088624,0.707108,0.072719,0.053759,-0.005193, + 0.613188,-0.077464,0.78613,0.072606,0.053773,-0.005092, + 0.607114,-0.115813,0.78613,0.07244,0.052727,-0.005092, + 0.70153,-0.088624,0.707108,0.072719,0.053759,-0.005193, + 0.607114,-0.115813,0.78613,0.07244,0.052727,-0.005092, + 0.694581,-0.132498,0.707108,0.072553,0.052706,-0.005193, + 0.70571,-0.0444,0.707108,0.07282,0.05482,-0.005193, + 0.616842,-0.038808,0.78613,0.072705,0.054827,-0.005092, + 0.613188,-0.077464,0.78613,0.072606,0.053773,-0.005092, + 0.70571,-0.0444,0.707108,0.07282,0.05482,-0.005193, + 0.613188,-0.077464,0.78613,0.072606,0.053773,-0.005092, + 0.70153,-0.088624,0.707108,0.072719,0.053759,-0.005193, + 0.707106,0,0.707108,0.072853,0.055885,-0.005193, + 0.618061,0,0.78613,0.072739,0.055885,-0.005092, + 0.616842,-0.038808,0.78613,0.072705,0.054827,-0.005092, + 0.707106,0,0.707108,0.072853,0.055885,-0.005193, + 0.616842,-0.038808,0.78613,0.072705,0.054827,-0.005092, + 0.70571,-0.0444,0.707108,0.07282,0.05482,-0.005193, + 0.70571,0.0444,0.707108,0.07282,0.056951,-0.005193, + 0.616842,0.038808,0.78613,0.072705,0.056943,-0.005092, + 0.618061,0,0.78613,0.072739,0.055885,-0.005092, + 0.70571,0.0444,0.707108,0.07282,0.056951,-0.005193, + 0.618061,0,0.78613,0.072739,0.055885,-0.005092, + 0.707106,0,0.707108,0.072853,0.055885,-0.005193, + 0.70153,0.088624,0.707108,0.072719,0.058012,-0.005193, + 0.613188,0.077464,0.78613,0.072606,0.057998,-0.005092, + 0.616842,0.038808,0.78613,0.072705,0.056943,-0.005092, + 0.70153,0.088624,0.707108,0.072719,0.058012,-0.005193, + 0.616842,0.038808,0.78613,0.072705,0.056943,-0.005092, + 0.70571,0.0444,0.707108,0.07282,0.056951,-0.005193, + 0.694581,0.132498,0.707108,0.072553,0.059065,-0.005193, + 0.607114,0.115813,0.78613,0.07244,0.059043,-0.005092, + 0.613188,0.077464,0.78613,0.072606,0.057998,-0.005092, + 0.694581,0.132498,0.707108,0.072553,0.059065,-0.005193, + 0.613188,0.077464,0.78613,0.072606,0.057998,-0.005092, + 0.70153,0.088624,0.707108,0.072719,0.058012,-0.005193, + 0.684891,0.17585,0.707108,0.07232,0.060105,-0.005193, + 0.598644,0.153706,0.78613,0.072209,0.060077,-0.005092, + 0.607114,0.115813,0.78613,0.07244,0.059043,-0.005092, + 0.684891,0.17585,0.707108,0.07232,0.060105,-0.005193, + 0.607114,0.115813,0.78613,0.07244,0.059043,-0.005092, + 0.694581,0.132498,0.707108,0.072553,0.059065,-0.005193, + 0.672497,0.218508,0.707108,0.072023,0.061129,-0.005193, + 0.587811,0.190991,0.78613,0.071914,0.061093,-0.005092, + 0.598644,0.153706,0.78613,0.072209,0.060077,-0.005092, + 0.672497,0.218508,0.707108,0.072023,0.061129,-0.005193, + 0.598644,0.153706,0.78613,0.072209,0.060077,-0.005092, + 0.684891,0.17585,0.707108,0.07232,0.060105,-0.005193, + 0.65745,0.260303,0.707108,0.071662,0.062132,-0.005193, + 0.574659,0.227524,0.78613,0.071555,0.062089,-0.005092, + 0.587811,0.190991,0.78613,0.071914,0.061093,-0.005092, + 0.65745,0.260303,0.707108,0.071662,0.062132,-0.005193, + 0.587811,0.190991,0.78613,0.071914,0.061093,-0.005092, + 0.672497,0.218508,0.707108,0.072023,0.061129,-0.005193, + 0.639808,0.301071,0.707108,0.071238,0.06311,-0.005193, + 0.559239,0.263158,0.78613,0.071135,0.063061,-0.005092, + 0.574659,0.227524,0.78613,0.071555,0.062089,-0.005092, + 0.639808,0.301071,0.707108,0.071238,0.06311,-0.005193, + 0.574659,0.227524,0.78613,0.071555,0.062089,-0.005092, + 0.65745,0.260303,0.707108,0.071662,0.062132,-0.005193, + 0.619641,0.340651,0.707108,0.070754,0.06406,-0.005193, + 0.541611,0.297753,0.78613,0.070654,0.064004,-0.005092, + 0.559239,0.263158,0.78613,0.071135,0.063061,-0.005092, + 0.619641,0.340651,0.707108,0.070754,0.06406,-0.005193, + 0.559239,0.263158,0.78613,0.071135,0.063061,-0.005092, + 0.639808,0.301071,0.707108,0.071238,0.06311,-0.005193, + 0.597029,0.378886,0.707108,0.070212,0.064977,-0.005193, + 0.521846,0.331174,0.78613,0.070115,0.064916,-0.005092, + 0.541611,0.297753,0.78613,0.070654,0.064004,-0.005092, + 0.597029,0.378886,0.707108,0.070212,0.064977,-0.005193, + 0.541611,0.297753,0.78613,0.070654,0.064004,-0.005092, + 0.619641,0.340651,0.707108,0.070754,0.06406,-0.005193, + 0.57206,0.415626,0.707108,0.069613,0.065859,-0.005193, + 0.500022,0.363287,0.78613,0.06952,0.065791,-0.005092, + 0.521846,0.331174,0.78613,0.070115,0.064916,-0.005092, + 0.57206,0.415626,0.707108,0.069613,0.065859,-0.005193, + 0.521846,0.331174,0.78613,0.070115,0.064916,-0.005092, + 0.597029,0.378886,0.707108,0.070212,0.064977,-0.005193, + 0.544834,0.450726,0.707108,0.068959,0.066701,-0.005193, + 0.476224,0.393967,0.78613,0.068871,0.066628,-0.005092, + 0.500022,0.363287,0.78613,0.06952,0.065791,-0.005092, + 0.544834,0.450726,0.707108,0.068959,0.066701,-0.005193, + 0.500022,0.363287,0.78613,0.06952,0.065791,-0.005092, + 0.57206,0.415626,0.707108,0.069613,0.065859,-0.005193, + 0.515458,0.484047,0.707108,0.068254,0.067501,-0.005193, + 0.450547,0.423092,0.78613,0.068171,0.067422,-0.005092, + 0.476224,0.393967,0.78613,0.068871,0.066628,-0.005092, + 0.515458,0.484047,0.707108,0.068254,0.067501,-0.005193, + 0.476224,0.393967,0.78613,0.068871,0.066628,-0.005092, + 0.544834,0.450726,0.707108,0.068959,0.066701,-0.005193, + 0.484047,0.515458,0.707108,0.067501,0.068254,-0.005193, + 0.423092,0.450547,0.78613,0.067422,0.068171,-0.005092, + 0.450547,0.423092,0.78613,0.068171,0.067422,-0.005092, + 0.484047,0.515458,0.707108,0.067501,0.068254,-0.005193, + 0.450547,0.423092,0.78613,0.068171,0.067422,-0.005092, + 0.515458,0.484047,0.707108,0.068254,0.067501,-0.005193, + 0.450726,0.544834,0.707108,0.066701,0.068959,-0.005193, + 0.393967,0.476224,0.78613,0.066628,0.068871,-0.005092, + 0.423092,0.450547,0.78613,0.067422,0.068171,-0.005092, + 0.450726,0.544834,0.707108,0.066701,0.068959,-0.005193, + 0.423092,0.450547,0.78613,0.067422,0.068171,-0.005092, + 0.484047,0.515458,0.707108,0.067501,0.068254,-0.005193, + 0.415626,0.57206,0.707108,0.065859,0.069613,-0.005193, + 0.363287,0.500022,0.78613,0.065791,0.06952,-0.005092, + 0.393967,0.476224,0.78613,0.066628,0.068871,-0.005092, + 0.415626,0.57206,0.707108,0.065859,0.069613,-0.005193, + 0.393967,0.476224,0.78613,0.066628,0.068871,-0.005092, + 0.450726,0.544834,0.707108,0.066701,0.068959,-0.005193, + 0.378886,0.597029,0.707108,0.064977,0.070212,-0.005193, + 0.331174,0.521846,0.78613,0.064916,0.070115,-0.005092, + 0.363287,0.500022,0.78613,0.065791,0.06952,-0.005092, + 0.378886,0.597029,0.707108,0.064977,0.070212,-0.005193, + 0.363287,0.500022,0.78613,0.065791,0.06952,-0.005092, + 0.415626,0.57206,0.707108,0.065859,0.069613,-0.005193, + 0.340651,0.619641,0.707108,0.06406,0.070754,-0.005193, + 0.297753,0.541611,0.78613,0.064004,0.070654,-0.005092, + 0.331174,0.521846,0.78613,0.064916,0.070115,-0.005092, + 0.340651,0.619641,0.707108,0.06406,0.070754,-0.005193, + 0.331174,0.521846,0.78613,0.064916,0.070115,-0.005092, + 0.378886,0.597029,0.707108,0.064977,0.070212,-0.005193, + 0.301071,0.639808,0.707108,0.06311,0.071238,-0.005193, + 0.263158,0.559239,0.78613,0.063061,0.071135,-0.005092, + 0.297753,0.541611,0.78613,0.064004,0.070654,-0.005092, + 0.301071,0.639808,0.707108,0.06311,0.071238,-0.005193, + 0.297753,0.541611,0.78613,0.064004,0.070654,-0.005092, + 0.340651,0.619641,0.707108,0.06406,0.070754,-0.005193, + 0.260303,0.65745,0.707108,0.062132,0.071662,-0.005193, + 0.227524,0.574659,0.78613,0.062089,0.071555,-0.005092, + 0.263158,0.559239,0.78613,0.063061,0.071135,-0.005092, + 0.260303,0.65745,0.707108,0.062132,0.071662,-0.005193, + 0.263158,0.559239,0.78613,0.063061,0.071135,-0.005092, + 0.301071,0.639808,0.707108,0.06311,0.071238,-0.005193, + 0.218508,0.672497,0.707108,0.061129,0.072023,-0.005193, + 0.190991,0.587811,0.78613,0.061093,0.071914,-0.005092, + 0.227524,0.574659,0.78613,0.062089,0.071555,-0.005092, + 0.218508,0.672497,0.707108,0.061129,0.072023,-0.005193, + 0.227524,0.574659,0.78613,0.062089,0.071555,-0.005092, + 0.260303,0.65745,0.707108,0.062132,0.071662,-0.005193, + 0.17585,0.684891,0.707108,0.060105,0.07232,-0.005193, + 0.153706,0.598644,0.78613,0.060077,0.072209,-0.005092, + 0.190991,0.587811,0.78613,0.061093,0.071914,-0.005092, + 0.17585,0.684891,0.707108,0.060105,0.07232,-0.005193, + 0.190991,0.587811,0.78613,0.061093,0.071914,-0.005092, + 0.218508,0.672497,0.707108,0.061129,0.072023,-0.005193, + 0.132498,0.694581,0.707108,0.059065,0.072553,-0.005193, + 0.115813,0.607114,0.78613,0.059043,0.07244,-0.005092, + 0.153706,0.598644,0.78613,0.060077,0.072209,-0.005092, + 0.132498,0.694581,0.707108,0.059065,0.072553,-0.005193, + 0.153706,0.598644,0.78613,0.060077,0.072209,-0.005092, + 0.17585,0.684891,0.707108,0.060105,0.07232,-0.005193, + 0.088624,0.70153,0.707108,0.058012,0.072719,-0.005193, + 0.077464,0.613188,0.78613,0.057998,0.072606,-0.005092, + 0.115813,0.607114,0.78613,0.059043,0.07244,-0.005092, + 0.088624,0.70153,0.707108,0.058012,0.072719,-0.005193, + 0.115813,0.607114,0.78613,0.059043,0.07244,-0.005092, + 0.132498,0.694581,0.707108,0.059065,0.072553,-0.005193, + 0.0444,0.70571,0.707108,0.056951,0.07282,-0.005193, + 0.038808,0.616842,0.78613,0.056943,0.072705,-0.005092, + 0.077464,0.613188,0.78613,0.057998,0.072606,-0.005092, + 0.0444,0.70571,0.707108,0.056951,0.07282,-0.005193, + 0.077464,0.613188,0.78613,0.057998,0.072606,-0.005092, + 0.088624,0.70153,0.707108,0.058012,0.072719,-0.005193, + 0,0.707106,0.707108,0.055885,0.072853,-0.005193, + 0,0.618061,0.78613,0.055885,0.072739,-0.005092, + 0.038808,0.616842,0.78613,0.056943,0.072705,-0.005092, + 0,0.707106,0.707108,0.055885,0.072853,-0.005193, + 0.038808,0.616842,0.78613,0.056943,0.072705,-0.005092, + 0.0444,0.70571,0.707108,0.056951,0.07282,-0.005193, + -0.0444,0.70571,0.707108,0.05482,0.07282,-0.005193, + -0.038808,0.616842,0.78613,0.054827,0.072705,-0.005092, + 0,0.618061,0.78613,0.055885,0.072739,-0.005092, + -0.0444,0.70571,0.707108,0.05482,0.07282,-0.005193, + 0,0.618061,0.78613,0.055885,0.072739,-0.005092, + 0,0.707106,0.707108,0.055885,0.072853,-0.005193, + -0.088624,0.70153,0.707108,0.053759,0.072719,-0.005193, + -0.077464,0.613188,0.78613,0.053773,0.072606,-0.005092, + -0.038808,0.616842,0.78613,0.054827,0.072705,-0.005092, + -0.088624,0.70153,0.707108,0.053759,0.072719,-0.005193, + -0.038808,0.616842,0.78613,0.054827,0.072705,-0.005092, + -0.0444,0.70571,0.707108,0.05482,0.07282,-0.005193, + -0.132498,0.694581,0.707108,0.052706,0.072553,-0.005193, + -0.115813,0.607114,0.78613,0.052727,0.07244,-0.005092, + -0.077464,0.613188,0.78613,0.053773,0.072606,-0.005092, + -0.132498,0.694581,0.707108,0.052706,0.072553,-0.005193, + -0.077464,0.613188,0.78613,0.053773,0.072606,-0.005092, + -0.088624,0.70153,0.707108,0.053759,0.072719,-0.005193, + -0.17585,0.684891,0.707108,0.051666,0.07232,-0.005193, + -0.153706,0.598644,0.78613,0.051694,0.072209,-0.005092, + -0.115813,0.607114,0.78613,0.052727,0.07244,-0.005092, + -0.17585,0.684891,0.707108,0.051666,0.07232,-0.005193, + -0.115813,0.607114,0.78613,0.052727,0.07244,-0.005092, + -0.132498,0.694581,0.707108,0.052706,0.072553,-0.005193, + -0.218508,0.672497,0.707108,0.050642,0.072023,-0.005193, + -0.190991,0.587811,0.78613,0.050677,0.071914,-0.005092, + -0.153706,0.598644,0.78613,0.051694,0.072209,-0.005092, + -0.218508,0.672497,0.707108,0.050642,0.072023,-0.005193, + -0.153706,0.598644,0.78613,0.051694,0.072209,-0.005092, + -0.17585,0.684891,0.707108,0.051666,0.07232,-0.005193, + -0.260303,0.65745,0.707108,0.049639,0.071662,-0.005193, + -0.227524,0.574659,0.78613,0.049681,0.071555,-0.005092, + -0.190991,0.587811,0.78613,0.050677,0.071914,-0.005092, + -0.260303,0.65745,0.707108,0.049639,0.071662,-0.005193, + -0.190991,0.587811,0.78613,0.050677,0.071914,-0.005092, + -0.218508,0.672497,0.707108,0.050642,0.072023,-0.005193, + -0.301071,0.639808,0.707108,0.048661,0.071238,-0.005193, + -0.263158,0.559239,0.78613,0.048709,0.071135,-0.005092, + -0.227524,0.574659,0.78613,0.049681,0.071555,-0.005092, + -0.301071,0.639808,0.707108,0.048661,0.071238,-0.005193, + -0.227524,0.574659,0.78613,0.049681,0.071555,-0.005092, + -0.260303,0.65745,0.707108,0.049639,0.071662,-0.005193, + -0.340651,0.619641,0.707108,0.047711,0.070754,-0.005193, + -0.297753,0.541611,0.78613,0.047766,0.070654,-0.005092, + -0.263158,0.559239,0.78613,0.048709,0.071135,-0.005092, + -0.340651,0.619641,0.707108,0.047711,0.070754,-0.005193, + -0.263158,0.559239,0.78613,0.048709,0.071135,-0.005092, + -0.301071,0.639808,0.707108,0.048661,0.071238,-0.005193, + -0.378886,0.597029,0.707108,0.046793,0.070212,-0.005193, + -0.331174,0.521846,0.78613,0.046855,0.070115,-0.005092, + -0.297753,0.541611,0.78613,0.047766,0.070654,-0.005092, + -0.378886,0.597029,0.707108,0.046793,0.070212,-0.005193, + -0.297753,0.541611,0.78613,0.047766,0.070654,-0.005092, + -0.340651,0.619641,0.707108,0.047711,0.070754,-0.005193, + -0.415626,0.57206,0.707108,0.045912,0.069613,-0.005193, + -0.363287,0.500022,0.78613,0.045979,0.06952,-0.005092, + -0.331174,0.521846,0.78613,0.046855,0.070115,-0.005092, + -0.415626,0.57206,0.707108,0.045912,0.069613,-0.005193, + -0.331174,0.521846,0.78613,0.046855,0.070115,-0.005092, + -0.378886,0.597029,0.707108,0.046793,0.070212,-0.005193, + -0.450726,0.544834,0.707108,0.04507,0.068959,-0.005193, + -0.393967,0.476224,0.78613,0.045143,0.068871,-0.005092, + -0.363287,0.500022,0.78613,0.045979,0.06952,-0.005092, + -0.450726,0.544834,0.707108,0.04507,0.068959,-0.005193, + -0.363287,0.500022,0.78613,0.045979,0.06952,-0.005092, + -0.415626,0.57206,0.707108,0.045912,0.069613,-0.005193, + -0.484047,0.515458,0.707108,0.04427,0.068254,-0.005193, + -0.423092,0.450547,0.78613,0.044348,0.068171,-0.005092, + -0.393967,0.476224,0.78613,0.045143,0.068871,-0.005092, + -0.484047,0.515458,0.707108,0.04427,0.068254,-0.005193, + -0.393967,0.476224,0.78613,0.045143,0.068871,-0.005092, + -0.450726,0.544834,0.707108,0.04507,0.068959,-0.005193, + -0.515458,0.484047,0.707108,0.043516,0.067501,-0.005193, + -0.450547,0.423092,0.78613,0.0436,0.067422,-0.005092, + -0.423092,0.450547,0.78613,0.044348,0.068171,-0.005092, + -0.515458,0.484047,0.707108,0.043516,0.067501,-0.005193, + -0.423092,0.450547,0.78613,0.044348,0.068171,-0.005092, + -0.484047,0.515458,0.707108,0.04427,0.068254,-0.005193, + -0.544834,0.450726,0.707108,0.042811,0.066701,-0.005193, + -0.476224,0.393967,0.78613,0.0429,0.066628,-0.005092, + -0.450547,0.423092,0.78613,0.0436,0.067422,-0.005092, + -0.544834,0.450726,0.707108,0.042811,0.066701,-0.005193, + -0.450547,0.423092,0.78613,0.0436,0.067422,-0.005092, + -0.515458,0.484047,0.707108,0.043516,0.067501,-0.005193, + -0.57206,0.415626,0.707108,0.042158,0.065859,-0.005193, + -0.500022,0.363287,0.78613,0.042251,0.065791,-0.005092, + -0.476224,0.393967,0.78613,0.0429,0.066628,-0.005092, + -0.57206,0.415626,0.707108,0.042158,0.065859,-0.005193, + -0.476224,0.393967,0.78613,0.0429,0.066628,-0.005092, + -0.544834,0.450726,0.707108,0.042811,0.066701,-0.005193, + -0.597029,0.378886,0.707108,0.041559,0.064977,-0.005193, + -0.521846,0.331174,0.78613,0.041656,0.064916,-0.005092, + -0.500022,0.363287,0.78613,0.042251,0.065791,-0.005092, + -0.597029,0.378886,0.707108,0.041559,0.064977,-0.005193, + -0.500022,0.363287,0.78613,0.042251,0.065791,-0.005092, + -0.57206,0.415626,0.707108,0.042158,0.065859,-0.005193, + -0.619641,0.340651,0.707108,0.041016,0.06406,-0.005193, + -0.541611,0.297753,0.78613,0.041117,0.064004,-0.005092, + -0.521846,0.331174,0.78613,0.041656,0.064916,-0.005092, + -0.619641,0.340651,0.707108,0.041016,0.06406,-0.005193, + -0.521846,0.331174,0.78613,0.041656,0.064916,-0.005092, + -0.597029,0.378886,0.707108,0.041559,0.064977,-0.005193, + -0.639808,0.301071,0.707108,0.040532,0.06311,-0.005193, + -0.559239,0.263158,0.78613,0.040636,0.063061,-0.005092, + -0.541611,0.297753,0.78613,0.041117,0.064004,-0.005092, + -0.639808,0.301071,0.707108,0.040532,0.06311,-0.005193, + -0.541611,0.297753,0.78613,0.041117,0.064004,-0.005092, + -0.619641,0.340651,0.707108,0.041016,0.06406,-0.005193, + -0.65745,0.260303,0.707108,0.040109,0.062132,-0.005193, + -0.574659,0.227524,0.78613,0.040215,0.062089,-0.005092, + -0.559239,0.263158,0.78613,0.040636,0.063061,-0.005092, + -0.65745,0.260303,0.707108,0.040109,0.062132,-0.005193, + -0.559239,0.263158,0.78613,0.040636,0.063061,-0.005092, + -0.639808,0.301071,0.707108,0.040532,0.06311,-0.005193, + -0.672497,0.218508,0.707108,0.039748,0.061129,-0.005193, + -0.587811,0.190991,0.78613,0.039857,0.061093,-0.005092, + -0.574659,0.227524,0.78613,0.040215,0.062089,-0.005092, + -0.672497,0.218508,0.707108,0.039748,0.061129,-0.005193, + -0.574659,0.227524,0.78613,0.040215,0.062089,-0.005092, + -0.65745,0.260303,0.707108,0.040109,0.062132,-0.005193, + -0.684891,0.17585,0.707108,0.03945,0.060105,-0.005193, + -0.598644,0.153706,0.78613,0.039562,0.060077,-0.005092, + -0.587811,0.190991,0.78613,0.039857,0.061093,-0.005092, + -0.684891,0.17585,0.707108,0.03945,0.060105,-0.005193, + -0.587811,0.190991,0.78613,0.039857,0.061093,-0.005092, + -0.672497,0.218508,0.707108,0.039748,0.061129,-0.005193, + -0.694581,0.132498,0.707108,0.039218,0.059065,-0.005193, + -0.607114,0.115813,0.78613,0.039331,0.059043,-0.005092, + -0.598644,0.153706,0.78613,0.039562,0.060077,-0.005092, + -0.694581,0.132498,0.707108,0.039218,0.059065,-0.005193, + -0.598644,0.153706,0.78613,0.039562,0.060077,-0.005092, + -0.684891,0.17585,0.707108,0.03945,0.060105,-0.005193, + -0.70153,0.088624,0.707108,0.039051,0.058012,-0.005193, + -0.613188,0.077464,0.78613,0.039165,0.057998,-0.005092, + -0.607114,0.115813,0.78613,0.039331,0.059043,-0.005092, + -0.70153,0.088624,0.707108,0.039051,0.058012,-0.005193, + -0.607114,0.115813,0.78613,0.039331,0.059043,-0.005092, + -0.694581,0.132498,0.707108,0.039218,0.059065,-0.005193, + -0.70571,0.0444,0.707108,0.038951,0.056951,-0.005193, + -0.616842,0.038808,0.78613,0.039065,0.056943,-0.005092, + -0.613188,0.077464,0.78613,0.039165,0.057998,-0.005092, + -0.70571,0.0444,0.707108,0.038951,0.056951,-0.005193, + -0.613188,0.077464,0.78613,0.039165,0.057998,-0.005092, + -0.70153,0.088624,0.707108,0.039051,0.058012,-0.005193, + -0.616842,0.038808,0.78613,0.039065,0.056943,-0.005092, + -0.519231,0.032667,0.85401,0.039191,0.056936,-0.005004, + -0.516155,0.065205,0.85401,0.03929,0.057982,-0.005004, + -0.616842,0.038808,0.78613,0.039065,0.056943,-0.005092, + -0.516155,0.065205,0.85401,0.03929,0.057982,-0.005004, + -0.613188,0.077464,0.78613,0.039165,0.057998,-0.005092, + -0.618061,0,0.78613,0.039032,0.055885,-0.005092, + -0.520257,0,0.85401,0.039158,0.055885,-0.005004, + -0.519231,0.032667,0.85401,0.039191,0.056936,-0.005004, + -0.618061,0,0.78613,0.039032,0.055885,-0.005092, + -0.519231,0.032667,0.85401,0.039191,0.056936,-0.005004, + -0.616842,0.038808,0.78613,0.039065,0.056943,-0.005092, + -0.616842,-0.038808,0.78613,0.039065,0.054827,-0.005092, + -0.519231,-0.032667,0.85401,0.039191,0.054835,-0.005004, + -0.520257,0,0.85401,0.039158,0.055885,-0.005004, + -0.616842,-0.038808,0.78613,0.039065,0.054827,-0.005092, + -0.520257,0,0.85401,0.039158,0.055885,-0.005004, + -0.618061,0,0.78613,0.039032,0.055885,-0.005092, + -0.613188,-0.077464,0.78613,0.039165,0.053773,-0.005092, + -0.516155,-0.065205,0.85401,0.03929,0.053789,-0.005004, + -0.519231,-0.032667,0.85401,0.039191,0.054835,-0.005004, + -0.613188,-0.077464,0.78613,0.039165,0.053773,-0.005092, + -0.519231,-0.032667,0.85401,0.039191,0.054835,-0.005004, + -0.616842,-0.038808,0.78613,0.039065,0.054827,-0.005092, + -0.607114,-0.115813,0.78613,0.039331,0.052727,-0.005092, + -0.511042,-0.097487,0.85401,0.039454,0.052751,-0.005004, + -0.516155,-0.065205,0.85401,0.03929,0.053789,-0.005004, + -0.607114,-0.115813,0.78613,0.039331,0.052727,-0.005092, + -0.516155,-0.065205,0.85401,0.03929,0.053789,-0.005004, + -0.613188,-0.077464,0.78613,0.039165,0.053773,-0.005092, + -0.598644,-0.153706,0.78613,0.039562,0.051694,-0.005092, + -0.503912,-0.129383,0.85401,0.039684,0.051725,-0.005004, + -0.511042,-0.097487,0.85401,0.039454,0.052751,-0.005004, + -0.598644,-0.153706,0.78613,0.039562,0.051694,-0.005092, + -0.511042,-0.097487,0.85401,0.039454,0.052751,-0.005004, + -0.607114,-0.115813,0.78613,0.039331,0.052727,-0.005092, + -0.587811,-0.190991,0.78613,0.039857,0.050677,-0.005092, + -0.494794,-0.160768,0.85401,0.039977,0.050716,-0.005004, + -0.503912,-0.129383,0.85401,0.039684,0.051725,-0.005004, + -0.587811,-0.190991,0.78613,0.039857,0.050677,-0.005092, + -0.503912,-0.129383,0.85401,0.039684,0.051725,-0.005004, + -0.598644,-0.153706,0.78613,0.039562,0.051694,-0.005092, + -0.574659,-0.227524,0.78613,0.040215,0.049681,-0.005092, + -0.483723,-0.191519,0.85401,0.040333,0.049728,-0.005004, + -0.494794,-0.160768,0.85401,0.039977,0.050716,-0.005004, + -0.574659,-0.227524,0.78613,0.040215,0.049681,-0.005092, + -0.494794,-0.160768,0.85401,0.039977,0.050716,-0.005004, + -0.587811,-0.190991,0.78613,0.039857,0.050677,-0.005092, + -0.559239,-0.263158,0.78613,0.040636,0.048709,-0.005092, + -0.470743,-0.221515,0.85401,0.04075,0.048763,-0.005004, + -0.483723,-0.191519,0.85401,0.040333,0.049728,-0.005004, + -0.559239,-0.263158,0.78613,0.040636,0.048709,-0.005092, + -0.483723,-0.191519,0.85401,0.040333,0.049728,-0.005004, + -0.574659,-0.227524,0.78613,0.040215,0.049681,-0.005092, + -0.541611,-0.297753,0.78613,0.041117,0.047766,-0.005092, + -0.455905,-0.250636,0.85401,0.041227,0.047827,-0.005004, + -0.470743,-0.221515,0.85401,0.04075,0.048763,-0.005004, + -0.541611,-0.297753,0.78613,0.041117,0.047766,-0.005092, + -0.470743,-0.221515,0.85401,0.04075,0.048763,-0.005004, + -0.559239,-0.263158,0.78613,0.040636,0.048709,-0.005092, + -0.521846,-0.331174,0.78613,0.041656,0.046855,-0.005092, + -0.439268,-0.278768,0.85401,0.041762,0.046922,-0.005004, + -0.455905,-0.250636,0.85401,0.041227,0.047827,-0.005004, + -0.521846,-0.331174,0.78613,0.041656,0.046855,-0.005092, + -0.455905,-0.250636,0.85401,0.041227,0.047827,-0.005004, + -0.541611,-0.297753,0.78613,0.041117,0.047766,-0.005092, + -0.500022,-0.363287,0.78613,0.042251,0.045979,-0.005092, + -0.420897,-0.3058,0.85401,0.042353,0.046053,-0.005004, + -0.439268,-0.278768,0.85401,0.041762,0.046922,-0.005004, + -0.500022,-0.363287,0.78613,0.042251,0.045979,-0.005092, + -0.439268,-0.278768,0.85401,0.041762,0.046922,-0.005004, + -0.521846,-0.331174,0.78613,0.041656,0.046855,-0.005092, + -0.476224,-0.393967,0.78613,0.0429,0.045143,-0.005092, + -0.400865,-0.331624,0.85401,0.042997,0.045223,-0.005004, + -0.420897,-0.3058,0.85401,0.042353,0.046053,-0.005004, + -0.476224,-0.393967,0.78613,0.0429,0.045143,-0.005092, + -0.420897,-0.3058,0.85401,0.042353,0.046053,-0.005004, + -0.500022,-0.363287,0.78613,0.042251,0.045979,-0.005092, + -0.450547,-0.423092,0.78613,0.0436,0.044348,-0.005092, + -0.379251,-0.356141,0.85401,0.043692,0.044435,-0.005004, + -0.400865,-0.331624,0.85401,0.042997,0.045223,-0.005004, + -0.450547,-0.423092,0.78613,0.0436,0.044348,-0.005092, + -0.400865,-0.331624,0.85401,0.042997,0.045223,-0.005004, + -0.476224,-0.393967,0.78613,0.0429,0.045143,-0.005092, + -0.423092,-0.450547,0.78613,0.044348,0.0436,-0.005092, + -0.356141,-0.379251,0.85401,0.044435,0.043692,-0.005004, + -0.379251,-0.356141,0.85401,0.043692,0.044435,-0.005004, + -0.423092,-0.450547,0.78613,0.044348,0.0436,-0.005092, + -0.379251,-0.356141,0.85401,0.043692,0.044435,-0.005004, + -0.450547,-0.423092,0.78613,0.0436,0.044348,-0.005092, + -0.393967,-0.476224,0.78613,0.045143,0.0429,-0.005092, + -0.331624,-0.400865,0.85401,0.045223,0.042997,-0.005004, + -0.356141,-0.379251,0.85401,0.044435,0.043692,-0.005004, + -0.393967,-0.476224,0.78613,0.045143,0.0429,-0.005092, + -0.356141,-0.379251,0.85401,0.044435,0.043692,-0.005004, + -0.423092,-0.450547,0.78613,0.044348,0.0436,-0.005092, + -0.363287,-0.500022,0.78613,0.045979,0.042251,-0.005092, + -0.3058,-0.420897,0.85401,0.046053,0.042353,-0.005004, + -0.331624,-0.400865,0.85401,0.045223,0.042997,-0.005004, + -0.363287,-0.500022,0.78613,0.045979,0.042251,-0.005092, + -0.331624,-0.400865,0.85401,0.045223,0.042997,-0.005004, + -0.393967,-0.476224,0.78613,0.045143,0.0429,-0.005092, + -0.331174,-0.521846,0.78613,0.046855,0.041656,-0.005092, + -0.278768,-0.439268,0.85401,0.046922,0.041762,-0.005004, + -0.3058,-0.420897,0.85401,0.046053,0.042353,-0.005004, + -0.331174,-0.521846,0.78613,0.046855,0.041656,-0.005092, + -0.3058,-0.420897,0.85401,0.046053,0.042353,-0.005004, + -0.363287,-0.500022,0.78613,0.045979,0.042251,-0.005092, + -0.297753,-0.541611,0.78613,0.047766,0.041117,-0.005092, + -0.250636,-0.455905,0.85401,0.047827,0.041227,-0.005004, + -0.278768,-0.439268,0.85401,0.046922,0.041762,-0.005004, + -0.297753,-0.541611,0.78613,0.047766,0.041117,-0.005092, + -0.278768,-0.439268,0.85401,0.046922,0.041762,-0.005004, + -0.331174,-0.521846,0.78613,0.046855,0.041656,-0.005092, + -0.263158,-0.559239,0.78613,0.048709,0.040636,-0.005092, + -0.221515,-0.470743,0.85401,0.048763,0.04075,-0.005004, + -0.250636,-0.455905,0.85401,0.047827,0.041227,-0.005004, + -0.263158,-0.559239,0.78613,0.048709,0.040636,-0.005092, + -0.250636,-0.455905,0.85401,0.047827,0.041227,-0.005004, + -0.297753,-0.541611,0.78613,0.047766,0.041117,-0.005092, + -0.227524,-0.574659,0.78613,0.049681,0.040215,-0.005092, + -0.191519,-0.483723,0.85401,0.049728,0.040333,-0.005004, + -0.221515,-0.470743,0.85401,0.048763,0.04075,-0.005004, + -0.227524,-0.574659,0.78613,0.049681,0.040215,-0.005092, + -0.221515,-0.470743,0.85401,0.048763,0.04075,-0.005004, + -0.263158,-0.559239,0.78613,0.048709,0.040636,-0.005092, + -0.190991,-0.587811,0.78613,0.050677,0.039857,-0.005092, + -0.160768,-0.494794,0.85401,0.050716,0.039977,-0.005004, + -0.191519,-0.483723,0.85401,0.049728,0.040333,-0.005004, + -0.190991,-0.587811,0.78613,0.050677,0.039857,-0.005092, + -0.191519,-0.483723,0.85401,0.049728,0.040333,-0.005004, + -0.227524,-0.574659,0.78613,0.049681,0.040215,-0.005092, + -0.153706,-0.598644,0.78613,0.051694,0.039562,-0.005092, + -0.129383,-0.503912,0.85401,0.051725,0.039684,-0.005004, + -0.160768,-0.494794,0.85401,0.050716,0.039977,-0.005004, + -0.153706,-0.598644,0.78613,0.051694,0.039562,-0.005092, + -0.160768,-0.494794,0.85401,0.050716,0.039977,-0.005004, + -0.190991,-0.587811,0.78613,0.050677,0.039857,-0.005092, + -0.115813,-0.607114,0.78613,0.052727,0.039331,-0.005092, + -0.097487,-0.511042,0.85401,0.052751,0.039454,-0.005004, + -0.129383,-0.503912,0.85401,0.051725,0.039684,-0.005004, + -0.115813,-0.607114,0.78613,0.052727,0.039331,-0.005092, + -0.129383,-0.503912,0.85401,0.051725,0.039684,-0.005004, + -0.153706,-0.598644,0.78613,0.051694,0.039562,-0.005092, + -0.077464,-0.613188,0.78613,0.053773,0.039165,-0.005092, + -0.065205,-0.516155,0.85401,0.053789,0.03929,-0.005004, + -0.097487,-0.511042,0.85401,0.052751,0.039454,-0.005004, + -0.077464,-0.613188,0.78613,0.053773,0.039165,-0.005092, + -0.097487,-0.511042,0.85401,0.052751,0.039454,-0.005004, + -0.115813,-0.607114,0.78613,0.052727,0.039331,-0.005092, + -0.038808,-0.616842,0.78613,0.054827,0.039065,-0.005092, + -0.032667,-0.519231,0.85401,0.054835,0.039191,-0.005004, + -0.065205,-0.516155,0.85401,0.053789,0.03929,-0.005004, + -0.038808,-0.616842,0.78613,0.054827,0.039065,-0.005092, + -0.065205,-0.516155,0.85401,0.053789,0.03929,-0.005004, + -0.077464,-0.613188,0.78613,0.053773,0.039165,-0.005092, + 0,-0.618061,0.78613,0.055885,0.039032,-0.005092, + 0,-0.520257,0.85401,0.055885,0.039158,-0.005004, + -0.032667,-0.519231,0.85401,0.054835,0.039191,-0.005004, + 0,-0.618061,0.78613,0.055885,0.039032,-0.005092, + -0.032667,-0.519231,0.85401,0.054835,0.039191,-0.005004, + -0.038808,-0.616842,0.78613,0.054827,0.039065,-0.005092, + 0.038808,-0.616842,0.78613,0.056943,0.039065,-0.005092, + 0.032667,-0.519231,0.85401,0.056936,0.039191,-0.005004, + 0,-0.520257,0.85401,0.055885,0.039158,-0.005004, + 0.038808,-0.616842,0.78613,0.056943,0.039065,-0.005092, + 0,-0.520257,0.85401,0.055885,0.039158,-0.005004, + 0,-0.618061,0.78613,0.055885,0.039032,-0.005092, + 0.077464,-0.613188,0.78613,0.057998,0.039165,-0.005092, + 0.065205,-0.516155,0.85401,0.057982,0.03929,-0.005004, + 0.032667,-0.519231,0.85401,0.056936,0.039191,-0.005004, + 0.077464,-0.613188,0.78613,0.057998,0.039165,-0.005092, + 0.032667,-0.519231,0.85401,0.056936,0.039191,-0.005004, + 0.038808,-0.616842,0.78613,0.056943,0.039065,-0.005092, + 0.115813,-0.607114,0.78613,0.059043,0.039331,-0.005092, + 0.097487,-0.511042,0.85401,0.05902,0.039454,-0.005004, + 0.065205,-0.516155,0.85401,0.057982,0.03929,-0.005004, + 0.115813,-0.607114,0.78613,0.059043,0.039331,-0.005092, + 0.065205,-0.516155,0.85401,0.057982,0.03929,-0.005004, + 0.077464,-0.613188,0.78613,0.057998,0.039165,-0.005092, + 0.153706,-0.598644,0.78613,0.060077,0.039562,-0.005092, + 0.129383,-0.503912,0.85401,0.060045,0.039684,-0.005004, + 0.097487,-0.511042,0.85401,0.05902,0.039454,-0.005004, + 0.153706,-0.598644,0.78613,0.060077,0.039562,-0.005092, + 0.097487,-0.511042,0.85401,0.05902,0.039454,-0.005004, + 0.115813,-0.607114,0.78613,0.059043,0.039331,-0.005092, + 0.190991,-0.587811,0.78613,0.061093,0.039857,-0.005092, + 0.160768,-0.494794,0.85401,0.061054,0.039977,-0.005004, + 0.129383,-0.503912,0.85401,0.060045,0.039684,-0.005004, + 0.190991,-0.587811,0.78613,0.061093,0.039857,-0.005092, + 0.129383,-0.503912,0.85401,0.060045,0.039684,-0.005004, + 0.153706,-0.598644,0.78613,0.060077,0.039562,-0.005092, + 0.227524,-0.574659,0.78613,0.062089,0.040215,-0.005092, + 0.191519,-0.483723,0.85401,0.062043,0.040333,-0.005004, + 0.160768,-0.494794,0.85401,0.061054,0.039977,-0.005004, + 0.227524,-0.574659,0.78613,0.062089,0.040215,-0.005092, + 0.160768,-0.494794,0.85401,0.061054,0.039977,-0.005004, + 0.190991,-0.587811,0.78613,0.061093,0.039857,-0.005092, + 0.263158,-0.559239,0.78613,0.063061,0.040636,-0.005092, + 0.221515,-0.470743,0.85401,0.063007,0.04075,-0.005004, + 0.191519,-0.483723,0.85401,0.062043,0.040333,-0.005004, + 0.263158,-0.559239,0.78613,0.063061,0.040636,-0.005092, + 0.191519,-0.483723,0.85401,0.062043,0.040333,-0.005004, + 0.227524,-0.574659,0.78613,0.062089,0.040215,-0.005092, + 0.297753,-0.541611,0.78613,0.064004,0.041117,-0.005092, + 0.250636,-0.455905,0.85401,0.063944,0.041227,-0.005004, + 0.221515,-0.470743,0.85401,0.063007,0.04075,-0.005004, + 0.297753,-0.541611,0.78613,0.064004,0.041117,-0.005092, + 0.221515,-0.470743,0.85401,0.063007,0.04075,-0.005004, + 0.263158,-0.559239,0.78613,0.063061,0.040636,-0.005092, + 0.331174,-0.521846,0.78613,0.064916,0.041656,-0.005092, + 0.278768,-0.439268,0.85401,0.064848,0.041762,-0.005004, + 0.250636,-0.455905,0.85401,0.063944,0.041227,-0.005004, + 0.331174,-0.521846,0.78613,0.064916,0.041656,-0.005092, + 0.250636,-0.455905,0.85401,0.063944,0.041227,-0.005004, + 0.297753,-0.541611,0.78613,0.064004,0.041117,-0.005092, + 0.363287,-0.500022,0.78613,0.065791,0.042251,-0.005092, + 0.3058,-0.420897,0.85401,0.065717,0.042353,-0.005004, + 0.278768,-0.439268,0.85401,0.064848,0.041762,-0.005004, + 0.363287,-0.500022,0.78613,0.065791,0.042251,-0.005092, + 0.278768,-0.439268,0.85401,0.064848,0.041762,-0.005004, + 0.331174,-0.521846,0.78613,0.064916,0.041656,-0.005092, + 0.393967,-0.476224,0.78613,0.066628,0.0429,-0.005092, + 0.331624,-0.400865,0.85401,0.066548,0.042997,-0.005004, + 0.3058,-0.420897,0.85401,0.065717,0.042353,-0.005004, + 0.393967,-0.476224,0.78613,0.066628,0.0429,-0.005092, + 0.3058,-0.420897,0.85401,0.065717,0.042353,-0.005004, + 0.363287,-0.500022,0.78613,0.065791,0.042251,-0.005092, + 0.423092,-0.450547,0.78613,0.067422,0.0436,-0.005092, + 0.356141,-0.379251,0.85401,0.067336,0.043692,-0.005004, + 0.331624,-0.400865,0.85401,0.066548,0.042997,-0.005004, + 0.423092,-0.450547,0.78613,0.067422,0.0436,-0.005092, + 0.331624,-0.400865,0.85401,0.066548,0.042997,-0.005004, + 0.393967,-0.476224,0.78613,0.066628,0.0429,-0.005092, + 0.450547,-0.423092,0.78613,0.068171,0.044348,-0.005092, + 0.379251,-0.356141,0.85401,0.068079,0.044435,-0.005004, + 0.356141,-0.379251,0.85401,0.067336,0.043692,-0.005004, + 0.450547,-0.423092,0.78613,0.068171,0.044348,-0.005092, + 0.356141,-0.379251,0.85401,0.067336,0.043692,-0.005004, + 0.423092,-0.450547,0.78613,0.067422,0.0436,-0.005092, + 0.476224,-0.393967,0.78613,0.068871,0.045143,-0.005092, + 0.400865,-0.331624,0.85401,0.068774,0.045223,-0.005004, + 0.379251,-0.356141,0.85401,0.068079,0.044435,-0.005004, + 0.476224,-0.393967,0.78613,0.068871,0.045143,-0.005092, + 0.379251,-0.356141,0.85401,0.068079,0.044435,-0.005004, + 0.450547,-0.423092,0.78613,0.068171,0.044348,-0.005092, + 0.500022,-0.363287,0.78613,0.06952,0.045979,-0.005092, + 0.420897,-0.3058,0.85401,0.069418,0.046053,-0.005004, + 0.400865,-0.331624,0.85401,0.068774,0.045223,-0.005004, + 0.500022,-0.363287,0.78613,0.06952,0.045979,-0.005092, + 0.400865,-0.331624,0.85401,0.068774,0.045223,-0.005004, + 0.476224,-0.393967,0.78613,0.068871,0.045143,-0.005092, + 0.521846,-0.331174,0.78613,0.070115,0.046855,-0.005092, + 0.439268,-0.278768,0.85401,0.070009,0.046922,-0.005004, + 0.420897,-0.3058,0.85401,0.069418,0.046053,-0.005004, + 0.521846,-0.331174,0.78613,0.070115,0.046855,-0.005092, + 0.420897,-0.3058,0.85401,0.069418,0.046053,-0.005004, + 0.500022,-0.363287,0.78613,0.06952,0.045979,-0.005092, + 0.541611,-0.297753,0.78613,0.070654,0.047766,-0.005092, + 0.455905,-0.250636,0.85401,0.070543,0.047827,-0.005004, + 0.439268,-0.278768,0.85401,0.070009,0.046922,-0.005004, + 0.541611,-0.297753,0.78613,0.070654,0.047766,-0.005092, + 0.439268,-0.278768,0.85401,0.070009,0.046922,-0.005004, + 0.521846,-0.331174,0.78613,0.070115,0.046855,-0.005092, + 0.559239,-0.263158,0.78613,0.071135,0.048709,-0.005092, + 0.470743,-0.221515,0.85401,0.071021,0.048763,-0.005004, + 0.455905,-0.250636,0.85401,0.070543,0.047827,-0.005004, + 0.559239,-0.263158,0.78613,0.071135,0.048709,-0.005092, + 0.455905,-0.250636,0.85401,0.070543,0.047827,-0.005004, + 0.541611,-0.297753,0.78613,0.070654,0.047766,-0.005092, + 0.574659,-0.227524,0.78613,0.071555,0.049681,-0.005092, + 0.483723,-0.191519,0.85401,0.071438,0.049728,-0.005004, + 0.470743,-0.221515,0.85401,0.071021,0.048763,-0.005004, + 0.574659,-0.227524,0.78613,0.071555,0.049681,-0.005092, + 0.470743,-0.221515,0.85401,0.071021,0.048763,-0.005004, + 0.559239,-0.263158,0.78613,0.071135,0.048709,-0.005092, + 0.587811,-0.190991,0.78613,0.071914,0.050677,-0.005092, + 0.494794,-0.160768,0.85401,0.071794,0.050716,-0.005004, + 0.483723,-0.191519,0.85401,0.071438,0.049728,-0.005004, + 0.587811,-0.190991,0.78613,0.071914,0.050677,-0.005092, + 0.483723,-0.191519,0.85401,0.071438,0.049728,-0.005004, + 0.574659,-0.227524,0.78613,0.071555,0.049681,-0.005092, + 0.598644,-0.153706,0.78613,0.072209,0.051694,-0.005092, + 0.503912,-0.129383,0.85401,0.072087,0.051725,-0.005004, + 0.494794,-0.160768,0.85401,0.071794,0.050716,-0.005004, + 0.598644,-0.153706,0.78613,0.072209,0.051694,-0.005092, + 0.494794,-0.160768,0.85401,0.071794,0.050716,-0.005004, + 0.587811,-0.190991,0.78613,0.071914,0.050677,-0.005092, + 0.607114,-0.115813,0.78613,0.07244,0.052727,-0.005092, + 0.511042,-0.097487,0.85401,0.072316,0.052751,-0.005004, + 0.503912,-0.129383,0.85401,0.072087,0.051725,-0.005004, + 0.607114,-0.115813,0.78613,0.07244,0.052727,-0.005092, + 0.503912,-0.129383,0.85401,0.072087,0.051725,-0.005004, + 0.598644,-0.153706,0.78613,0.072209,0.051694,-0.005092, + 0.613188,-0.077464,0.78613,0.072606,0.053773,-0.005092, + 0.516155,-0.065205,0.85401,0.072481,0.053789,-0.005004, + 0.511042,-0.097487,0.85401,0.072316,0.052751,-0.005004, + 0.613188,-0.077464,0.78613,0.072606,0.053773,-0.005092, + 0.511042,-0.097487,0.85401,0.072316,0.052751,-0.005004, + 0.607114,-0.115813,0.78613,0.07244,0.052727,-0.005092, + 0.616842,-0.038808,0.78613,0.072705,0.054827,-0.005092, + 0.519231,-0.032667,0.85401,0.07258,0.054835,-0.005004, + 0.516155,-0.065205,0.85401,0.072481,0.053789,-0.005004, + 0.616842,-0.038808,0.78613,0.072705,0.054827,-0.005092, + 0.516155,-0.065205,0.85401,0.072481,0.053789,-0.005004, + 0.613188,-0.077464,0.78613,0.072606,0.053773,-0.005092, + 0.618061,0,0.78613,0.072739,0.055885,-0.005092, + 0.520257,0,0.85401,0.072613,0.055885,-0.005004, + 0.519231,-0.032667,0.85401,0.07258,0.054835,-0.005004, + 0.618061,0,0.78613,0.072739,0.055885,-0.005092, + 0.519231,-0.032667,0.85401,0.07258,0.054835,-0.005004, + 0.616842,-0.038808,0.78613,0.072705,0.054827,-0.005092, + 0.616842,0.038808,0.78613,0.072705,0.056943,-0.005092, + 0.519231,0.032667,0.85401,0.07258,0.056936,-0.005004, + 0.520257,0,0.85401,0.072613,0.055885,-0.005004, + 0.616842,0.038808,0.78613,0.072705,0.056943,-0.005092, + 0.520257,0,0.85401,0.072613,0.055885,-0.005004, + 0.618061,0,0.78613,0.072739,0.055885,-0.005092, + 0.613188,0.077464,0.78613,0.072606,0.057998,-0.005092, + 0.516155,0.065205,0.85401,0.072481,0.057982,-0.005004, + 0.519231,0.032667,0.85401,0.07258,0.056936,-0.005004, + 0.613188,0.077464,0.78613,0.072606,0.057998,-0.005092, + 0.519231,0.032667,0.85401,0.07258,0.056936,-0.005004, + 0.616842,0.038808,0.78613,0.072705,0.056943,-0.005092, + 0.607114,0.115813,0.78613,0.07244,0.059043,-0.005092, + 0.511042,0.097487,0.85401,0.072316,0.05902,-0.005004, + 0.516155,0.065205,0.85401,0.072481,0.057982,-0.005004, + 0.607114,0.115813,0.78613,0.07244,0.059043,-0.005092, + 0.516155,0.065205,0.85401,0.072481,0.057982,-0.005004, + 0.613188,0.077464,0.78613,0.072606,0.057998,-0.005092, + 0.598644,0.153706,0.78613,0.072209,0.060077,-0.005092, + 0.503912,0.129383,0.85401,0.072087,0.060045,-0.005004, + 0.511042,0.097487,0.85401,0.072316,0.05902,-0.005004, + 0.598644,0.153706,0.78613,0.072209,0.060077,-0.005092, + 0.511042,0.097487,0.85401,0.072316,0.05902,-0.005004, + 0.607114,0.115813,0.78613,0.07244,0.059043,-0.005092, + 0.587811,0.190991,0.78613,0.071914,0.061093,-0.005092, + 0.494794,0.160768,0.85401,0.071794,0.061054,-0.005004, + 0.503912,0.129383,0.85401,0.072087,0.060045,-0.005004, + 0.587811,0.190991,0.78613,0.071914,0.061093,-0.005092, + 0.503912,0.129383,0.85401,0.072087,0.060045,-0.005004, + 0.598644,0.153706,0.78613,0.072209,0.060077,-0.005092, + 0.574659,0.227524,0.78613,0.071555,0.062089,-0.005092, + 0.483723,0.191519,0.85401,0.071438,0.062043,-0.005004, + 0.494794,0.160768,0.85401,0.071794,0.061054,-0.005004, + 0.574659,0.227524,0.78613,0.071555,0.062089,-0.005092, + 0.494794,0.160768,0.85401,0.071794,0.061054,-0.005004, + 0.587811,0.190991,0.78613,0.071914,0.061093,-0.005092, + 0.559239,0.263158,0.78613,0.071135,0.063061,-0.005092, + 0.470743,0.221515,0.85401,0.071021,0.063007,-0.005004, + 0.483723,0.191519,0.85401,0.071438,0.062043,-0.005004, + 0.559239,0.263158,0.78613,0.071135,0.063061,-0.005092, + 0.483723,0.191519,0.85401,0.071438,0.062043,-0.005004, + 0.574659,0.227524,0.78613,0.071555,0.062089,-0.005092, + 0.541611,0.297753,0.78613,0.070654,0.064004,-0.005092, + 0.455905,0.250636,0.85401,0.070543,0.063944,-0.005004, + 0.470743,0.221515,0.85401,0.071021,0.063007,-0.005004, + 0.541611,0.297753,0.78613,0.070654,0.064004,-0.005092, + 0.470743,0.221515,0.85401,0.071021,0.063007,-0.005004, + 0.559239,0.263158,0.78613,0.071135,0.063061,-0.005092, + 0.521846,0.331174,0.78613,0.070115,0.064916,-0.005092, + 0.439268,0.278768,0.85401,0.070009,0.064848,-0.005004, + 0.455905,0.250636,0.85401,0.070543,0.063944,-0.005004, + 0.521846,0.331174,0.78613,0.070115,0.064916,-0.005092, + 0.455905,0.250636,0.85401,0.070543,0.063944,-0.005004, + 0.541611,0.297753,0.78613,0.070654,0.064004,-0.005092, + 0.500022,0.363287,0.78613,0.06952,0.065791,-0.005092, + 0.420897,0.3058,0.85401,0.069418,0.065717,-0.005004, + 0.439268,0.278768,0.85401,0.070009,0.064848,-0.005004, + 0.500022,0.363287,0.78613,0.06952,0.065791,-0.005092, + 0.439268,0.278768,0.85401,0.070009,0.064848,-0.005004, + 0.521846,0.331174,0.78613,0.070115,0.064916,-0.005092, + 0.476224,0.393967,0.78613,0.068871,0.066628,-0.005092, + 0.400865,0.331624,0.85401,0.068774,0.066548,-0.005004, + 0.420897,0.3058,0.85401,0.069418,0.065717,-0.005004, + 0.476224,0.393967,0.78613,0.068871,0.066628,-0.005092, + 0.420897,0.3058,0.85401,0.069418,0.065717,-0.005004, + 0.500022,0.363287,0.78613,0.06952,0.065791,-0.005092, + 0.450547,0.423092,0.78613,0.068171,0.067422,-0.005092, + 0.379251,0.356141,0.85401,0.068079,0.067336,-0.005004, + 0.400865,0.331624,0.85401,0.068774,0.066548,-0.005004, + 0.450547,0.423092,0.78613,0.068171,0.067422,-0.005092, + 0.400865,0.331624,0.85401,0.068774,0.066548,-0.005004, + 0.476224,0.393967,0.78613,0.068871,0.066628,-0.005092, + 0.423092,0.450547,0.78613,0.067422,0.068171,-0.005092, + 0.356141,0.379251,0.85401,0.067336,0.068079,-0.005004, + 0.379251,0.356141,0.85401,0.068079,0.067336,-0.005004, + 0.423092,0.450547,0.78613,0.067422,0.068171,-0.005092, + 0.379251,0.356141,0.85401,0.068079,0.067336,-0.005004, + 0.450547,0.423092,0.78613,0.068171,0.067422,-0.005092, + 0.393967,0.476224,0.78613,0.066628,0.068871,-0.005092, + 0.331624,0.400865,0.85401,0.066548,0.068774,-0.005004, + 0.356141,0.379251,0.85401,0.067336,0.068079,-0.005004, + 0.393967,0.476224,0.78613,0.066628,0.068871,-0.005092, + 0.356141,0.379251,0.85401,0.067336,0.068079,-0.005004, + 0.423092,0.450547,0.78613,0.067422,0.068171,-0.005092, + 0.363287,0.500022,0.78613,0.065791,0.06952,-0.005092, + 0.3058,0.420897,0.85401,0.065717,0.069418,-0.005004, + 0.331624,0.400865,0.85401,0.066548,0.068774,-0.005004, + 0.363287,0.500022,0.78613,0.065791,0.06952,-0.005092, + 0.331624,0.400865,0.85401,0.066548,0.068774,-0.005004, + 0.393967,0.476224,0.78613,0.066628,0.068871,-0.005092, + 0.331174,0.521846,0.78613,0.064916,0.070115,-0.005092, + 0.278768,0.439268,0.85401,0.064848,0.070009,-0.005004, + 0.3058,0.420897,0.85401,0.065717,0.069418,-0.005004, + 0.331174,0.521846,0.78613,0.064916,0.070115,-0.005092, + 0.3058,0.420897,0.85401,0.065717,0.069418,-0.005004, + 0.363287,0.500022,0.78613,0.065791,0.06952,-0.005092, + 0.297753,0.541611,0.78613,0.064004,0.070654,-0.005092, + 0.250636,0.455905,0.85401,0.063944,0.070543,-0.005004, + 0.278768,0.439268,0.85401,0.064848,0.070009,-0.005004, + 0.297753,0.541611,0.78613,0.064004,0.070654,-0.005092, + 0.278768,0.439268,0.85401,0.064848,0.070009,-0.005004, + 0.331174,0.521846,0.78613,0.064916,0.070115,-0.005092, + 0.263158,0.559239,0.78613,0.063061,0.071135,-0.005092, + 0.221515,0.470743,0.85401,0.063007,0.071021,-0.005004, + 0.250636,0.455905,0.85401,0.063944,0.070543,-0.005004, + 0.263158,0.559239,0.78613,0.063061,0.071135,-0.005092, + 0.250636,0.455905,0.85401,0.063944,0.070543,-0.005004, + 0.297753,0.541611,0.78613,0.064004,0.070654,-0.005092, + 0.227524,0.574659,0.78613,0.062089,0.071555,-0.005092, + 0.191519,0.483723,0.85401,0.062043,0.071438,-0.005004, + 0.221515,0.470743,0.85401,0.063007,0.071021,-0.005004, + 0.227524,0.574659,0.78613,0.062089,0.071555,-0.005092, + 0.221515,0.470743,0.85401,0.063007,0.071021,-0.005004, + 0.263158,0.559239,0.78613,0.063061,0.071135,-0.005092, + 0.190991,0.587811,0.78613,0.061093,0.071914,-0.005092, + 0.160768,0.494794,0.85401,0.061054,0.071794,-0.005004, + 0.191519,0.483723,0.85401,0.062043,0.071438,-0.005004, + 0.190991,0.587811,0.78613,0.061093,0.071914,-0.005092, + 0.191519,0.483723,0.85401,0.062043,0.071438,-0.005004, + 0.227524,0.574659,0.78613,0.062089,0.071555,-0.005092, + 0.153706,0.598644,0.78613,0.060077,0.072209,-0.005092, + 0.129383,0.503912,0.85401,0.060045,0.072087,-0.005004, + 0.160768,0.494794,0.85401,0.061054,0.071794,-0.005004, + 0.153706,0.598644,0.78613,0.060077,0.072209,-0.005092, + 0.160768,0.494794,0.85401,0.061054,0.071794,-0.005004, + 0.190991,0.587811,0.78613,0.061093,0.071914,-0.005092, + 0.115813,0.607114,0.78613,0.059043,0.07244,-0.005092, + 0.097487,0.511042,0.85401,0.05902,0.072316,-0.005004, + 0.129383,0.503912,0.85401,0.060045,0.072087,-0.005004, + 0.115813,0.607114,0.78613,0.059043,0.07244,-0.005092, + 0.129383,0.503912,0.85401,0.060045,0.072087,-0.005004, + 0.153706,0.598644,0.78613,0.060077,0.072209,-0.005092, + 0.077464,0.613188,0.78613,0.057998,0.072606,-0.005092, + 0.065205,0.516155,0.85401,0.057982,0.072481,-0.005004, + 0.097487,0.511042,0.85401,0.05902,0.072316,-0.005004, + 0.077464,0.613188,0.78613,0.057998,0.072606,-0.005092, + 0.097487,0.511042,0.85401,0.05902,0.072316,-0.005004, + 0.115813,0.607114,0.78613,0.059043,0.07244,-0.005092, + 0.038808,0.616842,0.78613,0.056943,0.072705,-0.005092, + 0.032667,0.519231,0.85401,0.056936,0.07258,-0.005004, + 0.065205,0.516155,0.85401,0.057982,0.072481,-0.005004, + 0.038808,0.616842,0.78613,0.056943,0.072705,-0.005092, + 0.065205,0.516155,0.85401,0.057982,0.072481,-0.005004, + 0.077464,0.613188,0.78613,0.057998,0.072606,-0.005092, + 0,0.618061,0.78613,0.055885,0.072739,-0.005092, + 0,0.520257,0.85401,0.055885,0.072613,-0.005004, + 0.032667,0.519231,0.85401,0.056936,0.07258,-0.005004, + 0,0.618061,0.78613,0.055885,0.072739,-0.005092, + 0.032667,0.519231,0.85401,0.056936,0.07258,-0.005004, + 0.038808,0.616842,0.78613,0.056943,0.072705,-0.005092, + -0.038808,0.616842,0.78613,0.054827,0.072705,-0.005092, + -0.032667,0.519231,0.85401,0.054835,0.07258,-0.005004, + 0,0.520257,0.85401,0.055885,0.072613,-0.005004, + -0.038808,0.616842,0.78613,0.054827,0.072705,-0.005092, + 0,0.520257,0.85401,0.055885,0.072613,-0.005004, + 0,0.618061,0.78613,0.055885,0.072739,-0.005092, + -0.077464,0.613188,0.78613,0.053773,0.072606,-0.005092, + -0.065205,0.516155,0.85401,0.053789,0.072481,-0.005004, + -0.032667,0.519231,0.85401,0.054835,0.07258,-0.005004, + -0.077464,0.613188,0.78613,0.053773,0.072606,-0.005092, + -0.032667,0.519231,0.85401,0.054835,0.07258,-0.005004, + -0.038808,0.616842,0.78613,0.054827,0.072705,-0.005092, + -0.115813,0.607114,0.78613,0.052727,0.07244,-0.005092, + -0.097487,0.511042,0.85401,0.052751,0.072316,-0.005004, + -0.065205,0.516155,0.85401,0.053789,0.072481,-0.005004, + -0.115813,0.607114,0.78613,0.052727,0.07244,-0.005092, + -0.065205,0.516155,0.85401,0.053789,0.072481,-0.005004, + -0.077464,0.613188,0.78613,0.053773,0.072606,-0.005092, + -0.153706,0.598644,0.78613,0.051694,0.072209,-0.005092, + -0.129383,0.503912,0.85401,0.051725,0.072087,-0.005004, + -0.097487,0.511042,0.85401,0.052751,0.072316,-0.005004, + -0.153706,0.598644,0.78613,0.051694,0.072209,-0.005092, + -0.097487,0.511042,0.85401,0.052751,0.072316,-0.005004, + -0.115813,0.607114,0.78613,0.052727,0.07244,-0.005092, + -0.190991,0.587811,0.78613,0.050677,0.071914,-0.005092, + -0.160768,0.494794,0.85401,0.050716,0.071794,-0.005004, + -0.129383,0.503912,0.85401,0.051725,0.072087,-0.005004, + -0.190991,0.587811,0.78613,0.050677,0.071914,-0.005092, + -0.129383,0.503912,0.85401,0.051725,0.072087,-0.005004, + -0.153706,0.598644,0.78613,0.051694,0.072209,-0.005092, + -0.227524,0.574659,0.78613,0.049681,0.071555,-0.005092, + -0.191519,0.483723,0.85401,0.049728,0.071438,-0.005004, + -0.160768,0.494794,0.85401,0.050716,0.071794,-0.005004, + -0.227524,0.574659,0.78613,0.049681,0.071555,-0.005092, + -0.160768,0.494794,0.85401,0.050716,0.071794,-0.005004, + -0.190991,0.587811,0.78613,0.050677,0.071914,-0.005092, + -0.263158,0.559239,0.78613,0.048709,0.071135,-0.005092, + -0.221515,0.470743,0.85401,0.048763,0.071021,-0.005004, + -0.191519,0.483723,0.85401,0.049728,0.071438,-0.005004, + -0.263158,0.559239,0.78613,0.048709,0.071135,-0.005092, + -0.191519,0.483723,0.85401,0.049728,0.071438,-0.005004, + -0.227524,0.574659,0.78613,0.049681,0.071555,-0.005092, + -0.297753,0.541611,0.78613,0.047766,0.070654,-0.005092, + -0.250636,0.455905,0.85401,0.047827,0.070543,-0.005004, + -0.221515,0.470743,0.85401,0.048763,0.071021,-0.005004, + -0.297753,0.541611,0.78613,0.047766,0.070654,-0.005092, + -0.221515,0.470743,0.85401,0.048763,0.071021,-0.005004, + -0.263158,0.559239,0.78613,0.048709,0.071135,-0.005092, + -0.331174,0.521846,0.78613,0.046855,0.070115,-0.005092, + -0.278768,0.439268,0.85401,0.046922,0.070009,-0.005004, + -0.250636,0.455905,0.85401,0.047827,0.070543,-0.005004, + -0.331174,0.521846,0.78613,0.046855,0.070115,-0.005092, + -0.250636,0.455905,0.85401,0.047827,0.070543,-0.005004, + -0.297753,0.541611,0.78613,0.047766,0.070654,-0.005092, + -0.363287,0.500022,0.78613,0.045979,0.06952,-0.005092, + -0.3058,0.420897,0.85401,0.046053,0.069418,-0.005004, + -0.278768,0.439268,0.85401,0.046922,0.070009,-0.005004, + -0.363287,0.500022,0.78613,0.045979,0.06952,-0.005092, + -0.278768,0.439268,0.85401,0.046922,0.070009,-0.005004, + -0.331174,0.521846,0.78613,0.046855,0.070115,-0.005092, + -0.393967,0.476224,0.78613,0.045143,0.068871,-0.005092, + -0.331624,0.400865,0.85401,0.045223,0.068774,-0.005004, + -0.3058,0.420897,0.85401,0.046053,0.069418,-0.005004, + -0.393967,0.476224,0.78613,0.045143,0.068871,-0.005092, + -0.3058,0.420897,0.85401,0.046053,0.069418,-0.005004, + -0.363287,0.500022,0.78613,0.045979,0.06952,-0.005092, + -0.423092,0.450547,0.78613,0.044348,0.068171,-0.005092, + -0.356141,0.379251,0.85401,0.044435,0.068079,-0.005004, + -0.331624,0.400865,0.85401,0.045223,0.068774,-0.005004, + -0.423092,0.450547,0.78613,0.044348,0.068171,-0.005092, + -0.331624,0.400865,0.85401,0.045223,0.068774,-0.005004, + -0.393967,0.476224,0.78613,0.045143,0.068871,-0.005092, + -0.450547,0.423092,0.78613,0.0436,0.067422,-0.005092, + -0.379251,0.356141,0.85401,0.043692,0.067336,-0.005004, + -0.356141,0.379251,0.85401,0.044435,0.068079,-0.005004, + -0.450547,0.423092,0.78613,0.0436,0.067422,-0.005092, + -0.356141,0.379251,0.85401,0.044435,0.068079,-0.005004, + -0.423092,0.450547,0.78613,0.044348,0.068171,-0.005092, + -0.476224,0.393967,0.78613,0.0429,0.066628,-0.005092, + -0.400865,0.331624,0.85401,0.042997,0.066548,-0.005004, + -0.379251,0.356141,0.85401,0.043692,0.067336,-0.005004, + -0.476224,0.393967,0.78613,0.0429,0.066628,-0.005092, + -0.379251,0.356141,0.85401,0.043692,0.067336,-0.005004, + -0.450547,0.423092,0.78613,0.0436,0.067422,-0.005092, + -0.500022,0.363287,0.78613,0.042251,0.065791,-0.005092, + -0.420897,0.3058,0.85401,0.042353,0.065717,-0.005004, + -0.400865,0.331624,0.85401,0.042997,0.066548,-0.005004, + -0.500022,0.363287,0.78613,0.042251,0.065791,-0.005092, + -0.400865,0.331624,0.85401,0.042997,0.066548,-0.005004, + -0.476224,0.393967,0.78613,0.0429,0.066628,-0.005092, + -0.521846,0.331174,0.78613,0.041656,0.064916,-0.005092, + -0.439268,0.278768,0.85401,0.041762,0.064848,-0.005004, + -0.420897,0.3058,0.85401,0.042353,0.065717,-0.005004, + -0.521846,0.331174,0.78613,0.041656,0.064916,-0.005092, + -0.420897,0.3058,0.85401,0.042353,0.065717,-0.005004, + -0.500022,0.363287,0.78613,0.042251,0.065791,-0.005092, + -0.541611,0.297753,0.78613,0.041117,0.064004,-0.005092, + -0.455905,0.250636,0.85401,0.041227,0.063944,-0.005004, + -0.439268,0.278768,0.85401,0.041762,0.064848,-0.005004, + -0.541611,0.297753,0.78613,0.041117,0.064004,-0.005092, + -0.439268,0.278768,0.85401,0.041762,0.064848,-0.005004, + -0.521846,0.331174,0.78613,0.041656,0.064916,-0.005092, + -0.559239,0.263158,0.78613,0.040636,0.063061,-0.005092, + -0.470743,0.221515,0.85401,0.04075,0.063007,-0.005004, + -0.455905,0.250636,0.85401,0.041227,0.063944,-0.005004, + -0.559239,0.263158,0.78613,0.040636,0.063061,-0.005092, + -0.455905,0.250636,0.85401,0.041227,0.063944,-0.005004, + -0.541611,0.297753,0.78613,0.041117,0.064004,-0.005092, + -0.574659,0.227524,0.78613,0.040215,0.062089,-0.005092, + -0.483723,0.191519,0.85401,0.040333,0.062043,-0.005004, + -0.470743,0.221515,0.85401,0.04075,0.063007,-0.005004, + -0.574659,0.227524,0.78613,0.040215,0.062089,-0.005092, + -0.470743,0.221515,0.85401,0.04075,0.063007,-0.005004, + -0.559239,0.263158,0.78613,0.040636,0.063061,-0.005092, + -0.587811,0.190991,0.78613,0.039857,0.061093,-0.005092, + -0.494794,0.160768,0.85401,0.039977,0.061054,-0.005004, + -0.483723,0.191519,0.85401,0.040333,0.062043,-0.005004, + -0.587811,0.190991,0.78613,0.039857,0.061093,-0.005092, + -0.483723,0.191519,0.85401,0.040333,0.062043,-0.005004, + -0.574659,0.227524,0.78613,0.040215,0.062089,-0.005092, + -0.598644,0.153706,0.78613,0.039562,0.060077,-0.005092, + -0.503912,0.129383,0.85401,0.039684,0.060045,-0.005004, + -0.494794,0.160768,0.85401,0.039977,0.061054,-0.005004, + -0.598644,0.153706,0.78613,0.039562,0.060077,-0.005092, + -0.494794,0.160768,0.85401,0.039977,0.061054,-0.005004, + -0.587811,0.190991,0.78613,0.039857,0.061093,-0.005092, + -0.607114,0.115813,0.78613,0.039331,0.059043,-0.005092, + -0.511042,0.097487,0.85401,0.039454,0.05902,-0.005004, + -0.503912,0.129383,0.85401,0.039684,0.060045,-0.005004, + -0.607114,0.115813,0.78613,0.039331,0.059043,-0.005092, + -0.503912,0.129383,0.85401,0.039684,0.060045,-0.005004, + -0.598644,0.153706,0.78613,0.039562,0.060077,-0.005092, + -0.613188,0.077464,0.78613,0.039165,0.057998,-0.005092, + -0.516155,0.065205,0.85401,0.03929,0.057982,-0.005004, + -0.511042,0.097487,0.85401,0.039454,0.05902,-0.005004, + -0.613188,0.077464,0.78613,0.039165,0.057998,-0.005092, + -0.511042,0.097487,0.85401,0.039454,0.05902,-0.005004, + -0.607114,0.115813,0.78613,0.039331,0.059043,-0.005092, + -0.516155,0.065205,0.85401,0.03929,0.057982,-0.005004, + -0.411806,0.052023,0.909785,0.039424,0.057965,-0.004932, + -0.407727,0.077778,0.909785,0.039587,0.058994,-0.004932, + -0.516155,0.065205,0.85401,0.03929,0.057982,-0.005004, + -0.407727,0.077778,0.909785,0.039587,0.058994,-0.004932, + -0.511042,0.097487,0.85401,0.039454,0.05902,-0.005004, + -0.519231,0.032667,0.85401,0.039191,0.056936,-0.005004, + -0.41426,0.026063,0.909785,0.039326,0.056927,-0.004932, + -0.411806,0.052023,0.909785,0.039424,0.057965,-0.004932, + -0.519231,0.032667,0.85401,0.039191,0.056936,-0.005004, + -0.411806,0.052023,0.909785,0.039424,0.057965,-0.004932, + -0.516155,0.065205,0.85401,0.03929,0.057982,-0.005004, + -0.520257,0,0.85401,0.039158,0.055885,-0.005004, + -0.415079,0,0.909785,0.039294,0.055885,-0.004932, + -0.41426,0.026063,0.909785,0.039326,0.056927,-0.004932, + -0.520257,0,0.85401,0.039158,0.055885,-0.005004, + -0.41426,0.026063,0.909785,0.039326,0.056927,-0.004932, + -0.519231,0.032667,0.85401,0.039191,0.056936,-0.005004, + -0.519231,-0.032667,0.85401,0.039191,0.054835,-0.005004, + -0.41426,-0.026063,0.909785,0.039326,0.054844,-0.004932, + -0.415079,0,0.909785,0.039294,0.055885,-0.004932, + -0.519231,-0.032667,0.85401,0.039191,0.054835,-0.005004, + -0.415079,0,0.909785,0.039294,0.055885,-0.004932, + -0.520257,0,0.85401,0.039158,0.055885,-0.005004, + -0.516155,-0.065205,0.85401,0.03929,0.053789,-0.005004, + -0.411806,-0.052023,0.909785,0.039424,0.053806,-0.004932, + -0.41426,-0.026063,0.909785,0.039326,0.054844,-0.004932, + -0.516155,-0.065205,0.85401,0.03929,0.053789,-0.005004, + -0.41426,-0.026063,0.909785,0.039326,0.054844,-0.004932, + -0.519231,-0.032667,0.85401,0.039191,0.054835,-0.005004, + -0.511042,-0.097487,0.85401,0.039454,0.052751,-0.005004, + -0.407727,-0.077778,0.909785,0.039587,0.052776,-0.004932, + -0.411806,-0.052023,0.909785,0.039424,0.053806,-0.004932, + -0.511042,-0.097487,0.85401,0.039454,0.052751,-0.005004, + -0.411806,-0.052023,0.909785,0.039424,0.053806,-0.004932, + -0.516155,-0.065205,0.85401,0.03929,0.053789,-0.005004, + -0.503912,-0.129383,0.85401,0.039684,0.051725,-0.005004, + -0.402039,-0.103226,0.909785,0.039815,0.051759,-0.004932, + -0.407727,-0.077778,0.909785,0.039587,0.052776,-0.004932, + -0.503912,-0.129383,0.85401,0.039684,0.051725,-0.005004, + -0.407727,-0.077778,0.909785,0.039587,0.052776,-0.004932, + -0.511042,-0.097487,0.85401,0.039454,0.052751,-0.005004, + -0.494794,-0.160768,0.85401,0.039977,0.050716,-0.005004, + -0.394764,-0.128267,0.909785,0.040106,0.050758,-0.004932, + -0.402039,-0.103226,0.909785,0.039815,0.051759,-0.004932, + -0.494794,-0.160768,0.85401,0.039977,0.050716,-0.005004, + -0.402039,-0.103226,0.909785,0.039815,0.051759,-0.004932, + -0.503912,-0.129383,0.85401,0.039684,0.051725,-0.005004, + -0.483723,-0.191519,0.85401,0.040333,0.049728,-0.005004, + -0.385931,-0.152801,0.909785,0.040459,0.049777,-0.004932, + -0.394764,-0.128267,0.909785,0.040106,0.050758,-0.004932, + -0.483723,-0.191519,0.85401,0.040333,0.049728,-0.005004, + -0.394764,-0.128267,0.909785,0.040106,0.050758,-0.004932, + -0.494794,-0.160768,0.85401,0.039977,0.050716,-0.005004, + -0.470743,-0.221515,0.85401,0.04075,0.048763,-0.005004, + -0.375575,-0.176732,0.909785,0.040873,0.048821,-0.004932, + -0.385931,-0.152801,0.909785,0.040459,0.049777,-0.004932, + -0.470743,-0.221515,0.85401,0.04075,0.048763,-0.005004, + -0.385931,-0.152801,0.909785,0.040459,0.049777,-0.004932, + -0.483723,-0.191519,0.85401,0.040333,0.049728,-0.005004, + -0.455905,-0.250636,0.85401,0.041227,0.047827,-0.005004, + -0.363737,-0.199966,0.909785,0.041346,0.047892,-0.004932, + -0.375575,-0.176732,0.909785,0.040873,0.048821,-0.004932, + -0.455905,-0.250636,0.85401,0.041227,0.047827,-0.005004, + -0.375575,-0.176732,0.909785,0.040873,0.048821,-0.004932, + -0.470743,-0.221515,0.85401,0.04075,0.048763,-0.005004, + -0.439268,-0.278768,0.85401,0.041762,0.046922,-0.005004, + -0.350463,-0.222411,0.909785,0.041876,0.046995,-0.004932, + -0.363737,-0.199966,0.909785,0.041346,0.047892,-0.004932, + -0.439268,-0.278768,0.85401,0.041762,0.046922,-0.005004, + -0.363737,-0.199966,0.909785,0.041346,0.047892,-0.004932, + -0.455905,-0.250636,0.85401,0.041227,0.047827,-0.005004, + -0.420897,-0.3058,0.85401,0.042353,0.046053,-0.005004, + -0.335806,-0.243978,0.909785,0.042462,0.046133,-0.004932, + -0.350463,-0.222411,0.909785,0.041876,0.046995,-0.004932, + -0.420897,-0.3058,0.85401,0.042353,0.046053,-0.005004, + -0.350463,-0.222411,0.909785,0.041876,0.046995,-0.004932, + -0.439268,-0.278768,0.85401,0.041762,0.046922,-0.005004, + -0.400865,-0.331624,0.85401,0.042997,0.045223,-0.005004, + -0.319824,-0.264582,0.909785,0.043101,0.045309,-0.004932, + -0.335806,-0.243978,0.909785,0.042462,0.046133,-0.004932, + -0.400865,-0.331624,0.85401,0.042997,0.045223,-0.005004, + -0.335806,-0.243978,0.909785,0.042462,0.046133,-0.004932, + -0.420897,-0.3058,0.85401,0.042353,0.046053,-0.005004, + -0.379251,-0.356141,0.85401,0.043692,0.044435,-0.005004, + -0.30258,-0.284141,0.909785,0.04379,0.044527,-0.004932, + -0.319824,-0.264582,0.909785,0.043101,0.045309,-0.004932, + -0.379251,-0.356141,0.85401,0.043692,0.044435,-0.005004, + -0.319824,-0.264582,0.909785,0.043101,0.045309,-0.004932, + -0.400865,-0.331624,0.85401,0.042997,0.045223,-0.005004, + -0.356141,-0.379251,0.85401,0.044435,0.043692,-0.005004, + -0.284141,-0.30258,0.909785,0.044527,0.04379,-0.004932, + -0.30258,-0.284141,0.909785,0.04379,0.044527,-0.004932, + -0.356141,-0.379251,0.85401,0.044435,0.043692,-0.005004, + -0.30258,-0.284141,0.909785,0.04379,0.044527,-0.004932, + -0.379251,-0.356141,0.85401,0.043692,0.044435,-0.005004, + -0.331624,-0.400865,0.85401,0.045223,0.042997,-0.005004, + -0.264582,-0.319824,0.909785,0.045309,0.043101,-0.004932, + -0.284141,-0.30258,0.909785,0.044527,0.04379,-0.004932, + -0.331624,-0.400865,0.85401,0.045223,0.042997,-0.005004, + -0.284141,-0.30258,0.909785,0.044527,0.04379,-0.004932, + -0.356141,-0.379251,0.85401,0.044435,0.043692,-0.005004, + -0.3058,-0.420897,0.85401,0.046053,0.042353,-0.005004, + -0.243978,-0.335806,0.909785,0.046133,0.042462,-0.004932, + -0.264582,-0.319824,0.909785,0.045309,0.043101,-0.004932, + -0.3058,-0.420897,0.85401,0.046053,0.042353,-0.005004, + -0.264582,-0.319824,0.909785,0.045309,0.043101,-0.004932, + -0.331624,-0.400865,0.85401,0.045223,0.042997,-0.005004, + -0.278768,-0.439268,0.85401,0.046922,0.041762,-0.005004, + -0.222411,-0.350463,0.909785,0.046995,0.041876,-0.004932, + -0.243978,-0.335806,0.909785,0.046133,0.042462,-0.004932, + -0.278768,-0.439268,0.85401,0.046922,0.041762,-0.005004, + -0.243978,-0.335806,0.909785,0.046133,0.042462,-0.004932, + -0.3058,-0.420897,0.85401,0.046053,0.042353,-0.005004, + -0.250636,-0.455905,0.85401,0.047827,0.041227,-0.005004, + -0.199966,-0.363737,0.909785,0.047892,0.041346,-0.004932, + -0.222411,-0.350463,0.909785,0.046995,0.041876,-0.004932, + -0.250636,-0.455905,0.85401,0.047827,0.041227,-0.005004, + -0.222411,-0.350463,0.909785,0.046995,0.041876,-0.004932, + -0.278768,-0.439268,0.85401,0.046922,0.041762,-0.005004, + -0.221515,-0.470743,0.85401,0.048763,0.04075,-0.005004, + -0.176732,-0.375575,0.909785,0.048821,0.040873,-0.004932, + -0.199966,-0.363737,0.909785,0.047892,0.041346,-0.004932, + -0.221515,-0.470743,0.85401,0.048763,0.04075,-0.005004, + -0.199966,-0.363737,0.909785,0.047892,0.041346,-0.004932, + -0.250636,-0.455905,0.85401,0.047827,0.041227,-0.005004, + -0.191519,-0.483723,0.85401,0.049728,0.040333,-0.005004, + -0.152801,-0.385931,0.909785,0.049777,0.040459,-0.004932, + -0.176732,-0.375575,0.909785,0.048821,0.040873,-0.004932, + -0.191519,-0.483723,0.85401,0.049728,0.040333,-0.005004, + -0.176732,-0.375575,0.909785,0.048821,0.040873,-0.004932, + -0.221515,-0.470743,0.85401,0.048763,0.04075,-0.005004, + -0.160768,-0.494794,0.85401,0.050716,0.039977,-0.005004, + -0.128267,-0.394764,0.909785,0.050758,0.040106,-0.004932, + -0.152801,-0.385931,0.909785,0.049777,0.040459,-0.004932, + -0.160768,-0.494794,0.85401,0.050716,0.039977,-0.005004, + -0.152801,-0.385931,0.909785,0.049777,0.040459,-0.004932, + -0.191519,-0.483723,0.85401,0.049728,0.040333,-0.005004, + -0.129383,-0.503912,0.85401,0.051725,0.039684,-0.005004, + -0.103226,-0.402039,0.909785,0.051759,0.039815,-0.004932, + -0.128267,-0.394764,0.909785,0.050758,0.040106,-0.004932, + -0.129383,-0.503912,0.85401,0.051725,0.039684,-0.005004, + -0.128267,-0.394764,0.909785,0.050758,0.040106,-0.004932, + -0.160768,-0.494794,0.85401,0.050716,0.039977,-0.005004, + -0.097487,-0.511042,0.85401,0.052751,0.039454,-0.005004, + -0.077778,-0.407727,0.909785,0.052776,0.039587,-0.004932, + -0.103226,-0.402039,0.909785,0.051759,0.039815,-0.004932, + -0.097487,-0.511042,0.85401,0.052751,0.039454,-0.005004, + -0.103226,-0.402039,0.909785,0.051759,0.039815,-0.004932, + -0.129383,-0.503912,0.85401,0.051725,0.039684,-0.005004, + -0.065205,-0.516155,0.85401,0.053789,0.03929,-0.005004, + -0.052023,-0.411806,0.909785,0.053806,0.039424,-0.004932, + -0.077778,-0.407727,0.909785,0.052776,0.039587,-0.004932, + -0.065205,-0.516155,0.85401,0.053789,0.03929,-0.005004, + -0.077778,-0.407727,0.909785,0.052776,0.039587,-0.004932, + -0.097487,-0.511042,0.85401,0.052751,0.039454,-0.005004, + -0.032667,-0.519231,0.85401,0.054835,0.039191,-0.005004, + -0.026063,-0.41426,0.909785,0.054844,0.039326,-0.004932, + -0.052023,-0.411806,0.909785,0.053806,0.039424,-0.004932, + -0.032667,-0.519231,0.85401,0.054835,0.039191,-0.005004, + -0.052023,-0.411806,0.909785,0.053806,0.039424,-0.004932, + -0.065205,-0.516155,0.85401,0.053789,0.03929,-0.005004, + 0,-0.520257,0.85401,0.055885,0.039158,-0.005004, + 0,-0.415079,0.909785,0.055885,0.039294,-0.004932, + -0.026063,-0.41426,0.909785,0.054844,0.039326,-0.004932, + 0,-0.520257,0.85401,0.055885,0.039158,-0.005004, + -0.026063,-0.41426,0.909785,0.054844,0.039326,-0.004932, + -0.032667,-0.519231,0.85401,0.054835,0.039191,-0.005004, + 0.032667,-0.519231,0.85401,0.056936,0.039191,-0.005004, + 0.026063,-0.41426,0.909785,0.056927,0.039326,-0.004932, + 0,-0.415079,0.909785,0.055885,0.039294,-0.004932, + 0.032667,-0.519231,0.85401,0.056936,0.039191,-0.005004, + 0,-0.415079,0.909785,0.055885,0.039294,-0.004932, + 0,-0.520257,0.85401,0.055885,0.039158,-0.005004, + 0.065205,-0.516155,0.85401,0.057982,0.03929,-0.005004, + 0.052023,-0.411806,0.909785,0.057965,0.039424,-0.004932, + 0.026063,-0.41426,0.909785,0.056927,0.039326,-0.004932, + 0.065205,-0.516155,0.85401,0.057982,0.03929,-0.005004, + 0.026063,-0.41426,0.909785,0.056927,0.039326,-0.004932, + 0.032667,-0.519231,0.85401,0.056936,0.039191,-0.005004, + 0.097487,-0.511042,0.85401,0.05902,0.039454,-0.005004, + 0.077778,-0.407727,0.909785,0.058994,0.039587,-0.004932, + 0.052023,-0.411806,0.909785,0.057965,0.039424,-0.004932, + 0.097487,-0.511042,0.85401,0.05902,0.039454,-0.005004, + 0.052023,-0.411806,0.909785,0.057965,0.039424,-0.004932, + 0.065205,-0.516155,0.85401,0.057982,0.03929,-0.005004, + 0.129383,-0.503912,0.85401,0.060045,0.039684,-0.005004, + 0.103226,-0.402039,0.909785,0.060012,0.039815,-0.004932, + 0.077778,-0.407727,0.909785,0.058994,0.039587,-0.004932, + 0.129383,-0.503912,0.85401,0.060045,0.039684,-0.005004, + 0.077778,-0.407727,0.909785,0.058994,0.039587,-0.004932, + 0.097487,-0.511042,0.85401,0.05902,0.039454,-0.005004, + 0.160768,-0.494794,0.85401,0.061054,0.039977,-0.005004, + 0.128267,-0.394764,0.909785,0.061012,0.040106,-0.004932, + 0.103226,-0.402039,0.909785,0.060012,0.039815,-0.004932, + 0.160768,-0.494794,0.85401,0.061054,0.039977,-0.005004, + 0.103226,-0.402039,0.909785,0.060012,0.039815,-0.004932, + 0.129383,-0.503912,0.85401,0.060045,0.039684,-0.005004, + 0.191519,-0.483723,0.85401,0.062043,0.040333,-0.005004, + 0.152801,-0.385931,0.909785,0.061993,0.040459,-0.004932, + 0.128267,-0.394764,0.909785,0.061012,0.040106,-0.004932, + 0.191519,-0.483723,0.85401,0.062043,0.040333,-0.005004, + 0.128267,-0.394764,0.909785,0.061012,0.040106,-0.004932, + 0.160768,-0.494794,0.85401,0.061054,0.039977,-0.005004, + 0.221515,-0.470743,0.85401,0.063007,0.04075,-0.005004, + 0.176732,-0.375575,0.909785,0.06295,0.040873,-0.004932, + 0.152801,-0.385931,0.909785,0.061993,0.040459,-0.004932, + 0.221515,-0.470743,0.85401,0.063007,0.04075,-0.005004, + 0.152801,-0.385931,0.909785,0.061993,0.040459,-0.004932, + 0.191519,-0.483723,0.85401,0.062043,0.040333,-0.005004, + 0.250636,-0.455905,0.85401,0.063944,0.041227,-0.005004, + 0.199966,-0.363737,0.909785,0.063878,0.041346,-0.004932, + 0.176732,-0.375575,0.909785,0.06295,0.040873,-0.004932, + 0.250636,-0.455905,0.85401,0.063944,0.041227,-0.005004, + 0.176732,-0.375575,0.909785,0.06295,0.040873,-0.004932, + 0.221515,-0.470743,0.85401,0.063007,0.04075,-0.005004, + 0.278768,-0.439268,0.85401,0.064848,0.041762,-0.005004, + 0.222411,-0.350463,0.909785,0.064776,0.041876,-0.004932, + 0.199966,-0.363737,0.909785,0.063878,0.041346,-0.004932, + 0.278768,-0.439268,0.85401,0.064848,0.041762,-0.005004, + 0.199966,-0.363737,0.909785,0.063878,0.041346,-0.004932, + 0.250636,-0.455905,0.85401,0.063944,0.041227,-0.005004, + 0.3058,-0.420897,0.85401,0.065717,0.042353,-0.005004, + 0.243978,-0.335806,0.909785,0.065638,0.042462,-0.004932, + 0.222411,-0.350463,0.909785,0.064776,0.041876,-0.004932, + 0.3058,-0.420897,0.85401,0.065717,0.042353,-0.005004, + 0.222411,-0.350463,0.909785,0.064776,0.041876,-0.004932, + 0.278768,-0.439268,0.85401,0.064848,0.041762,-0.005004, + 0.331624,-0.400865,0.85401,0.066548,0.042997,-0.005004, + 0.264582,-0.319824,0.909785,0.066461,0.043101,-0.004932, + 0.243978,-0.335806,0.909785,0.065638,0.042462,-0.004932, + 0.331624,-0.400865,0.85401,0.066548,0.042997,-0.005004, + 0.243978,-0.335806,0.909785,0.065638,0.042462,-0.004932, + 0.3058,-0.420897,0.85401,0.065717,0.042353,-0.005004, + 0.356141,-0.379251,0.85401,0.067336,0.043692,-0.005004, + 0.284141,-0.30258,0.909785,0.067243,0.04379,-0.004932, + 0.264582,-0.319824,0.909785,0.066461,0.043101,-0.004932, + 0.356141,-0.379251,0.85401,0.067336,0.043692,-0.005004, + 0.264582,-0.319824,0.909785,0.066461,0.043101,-0.004932, + 0.331624,-0.400865,0.85401,0.066548,0.042997,-0.005004, + 0.379251,-0.356141,0.85401,0.068079,0.044435,-0.005004, + 0.30258,-0.284141,0.909785,0.06798,0.044527,-0.004932, + 0.284141,-0.30258,0.909785,0.067243,0.04379,-0.004932, + 0.379251,-0.356141,0.85401,0.068079,0.044435,-0.005004, + 0.284141,-0.30258,0.909785,0.067243,0.04379,-0.004932, + 0.356141,-0.379251,0.85401,0.067336,0.043692,-0.005004, + 0.400865,-0.331624,0.85401,0.068774,0.045223,-0.005004, + 0.319824,-0.264582,0.909785,0.06867,0.045309,-0.004932, + 0.30258,-0.284141,0.909785,0.06798,0.044527,-0.004932, + 0.400865,-0.331624,0.85401,0.068774,0.045223,-0.005004, + 0.30258,-0.284141,0.909785,0.06798,0.044527,-0.004932, + 0.379251,-0.356141,0.85401,0.068079,0.044435,-0.005004, + 0.420897,-0.3058,0.85401,0.069418,0.046053,-0.005004, + 0.335806,-0.243978,0.909785,0.069308,0.046133,-0.004932, + 0.319824,-0.264582,0.909785,0.06867,0.045309,-0.004932, + 0.420897,-0.3058,0.85401,0.069418,0.046053,-0.005004, + 0.319824,-0.264582,0.909785,0.06867,0.045309,-0.004932, + 0.400865,-0.331624,0.85401,0.068774,0.045223,-0.005004, + 0.439268,-0.278768,0.85401,0.070009,0.046922,-0.005004, + 0.350463,-0.222411,0.909785,0.069894,0.046995,-0.004932, + 0.335806,-0.243978,0.909785,0.069308,0.046133,-0.004932, + 0.439268,-0.278768,0.85401,0.070009,0.046922,-0.005004, + 0.335806,-0.243978,0.909785,0.069308,0.046133,-0.004932, + 0.420897,-0.3058,0.85401,0.069418,0.046053,-0.005004, + 0.455905,-0.250636,0.85401,0.070543,0.047827,-0.005004, + 0.363737,-0.199966,0.909785,0.070425,0.047892,-0.004932, + 0.350463,-0.222411,0.909785,0.069894,0.046995,-0.004932, + 0.455905,-0.250636,0.85401,0.070543,0.047827,-0.005004, + 0.350463,-0.222411,0.909785,0.069894,0.046995,-0.004932, + 0.439268,-0.278768,0.85401,0.070009,0.046922,-0.005004, + 0.470743,-0.221515,0.85401,0.071021,0.048763,-0.005004, + 0.375575,-0.176732,0.909785,0.070898,0.048821,-0.004932, + 0.363737,-0.199966,0.909785,0.070425,0.047892,-0.004932, + 0.470743,-0.221515,0.85401,0.071021,0.048763,-0.005004, + 0.363737,-0.199966,0.909785,0.070425,0.047892,-0.004932, + 0.455905,-0.250636,0.85401,0.070543,0.047827,-0.005004, + 0.483723,-0.191519,0.85401,0.071438,0.049728,-0.005004, + 0.385931,-0.152801,0.909785,0.071312,0.049777,-0.004932, + 0.375575,-0.176732,0.909785,0.070898,0.048821,-0.004932, + 0.483723,-0.191519,0.85401,0.071438,0.049728,-0.005004, + 0.375575,-0.176732,0.909785,0.070898,0.048821,-0.004932, + 0.470743,-0.221515,0.85401,0.071021,0.048763,-0.005004, + 0.494794,-0.160768,0.85401,0.071794,0.050716,-0.005004, + 0.394764,-0.128267,0.909785,0.071665,0.050758,-0.004932, + 0.385931,-0.152801,0.909785,0.071312,0.049777,-0.004932, + 0.494794,-0.160768,0.85401,0.071794,0.050716,-0.005004, + 0.385931,-0.152801,0.909785,0.071312,0.049777,-0.004932, + 0.483723,-0.191519,0.85401,0.071438,0.049728,-0.005004, + 0.503912,-0.129383,0.85401,0.072087,0.051725,-0.005004, + 0.402039,-0.103226,0.909785,0.071956,0.051759,-0.004932, + 0.394764,-0.128267,0.909785,0.071665,0.050758,-0.004932, + 0.503912,-0.129383,0.85401,0.072087,0.051725,-0.005004, + 0.394764,-0.128267,0.909785,0.071665,0.050758,-0.004932, + 0.494794,-0.160768,0.85401,0.071794,0.050716,-0.005004, + 0.511042,-0.097487,0.85401,0.072316,0.052751,-0.005004, + 0.407727,-0.077778,0.909785,0.072183,0.052776,-0.004932, + 0.402039,-0.103226,0.909785,0.071956,0.051759,-0.004932, + 0.511042,-0.097487,0.85401,0.072316,0.052751,-0.005004, + 0.402039,-0.103226,0.909785,0.071956,0.051759,-0.004932, + 0.503912,-0.129383,0.85401,0.072087,0.051725,-0.005004, + 0.516155,-0.065205,0.85401,0.072481,0.053789,-0.005004, + 0.411806,-0.052023,0.909785,0.072346,0.053806,-0.004932, + 0.407727,-0.077778,0.909785,0.072183,0.052776,-0.004932, + 0.516155,-0.065205,0.85401,0.072481,0.053789,-0.005004, + 0.407727,-0.077778,0.909785,0.072183,0.052776,-0.004932, + 0.511042,-0.097487,0.85401,0.072316,0.052751,-0.005004, + 0.519231,-0.032667,0.85401,0.07258,0.054835,-0.005004, + 0.41426,-0.026063,0.909785,0.072444,0.054844,-0.004932, + 0.411806,-0.052023,0.909785,0.072346,0.053806,-0.004932, + 0.519231,-0.032667,0.85401,0.07258,0.054835,-0.005004, + 0.411806,-0.052023,0.909785,0.072346,0.053806,-0.004932, + 0.516155,-0.065205,0.85401,0.072481,0.053789,-0.005004, + 0.520257,0,0.85401,0.072613,0.055885,-0.005004, + 0.415079,0,0.909785,0.072477,0.055885,-0.004932, + 0.41426,-0.026063,0.909785,0.072444,0.054844,-0.004932, + 0.520257,0,0.85401,0.072613,0.055885,-0.005004, + 0.41426,-0.026063,0.909785,0.072444,0.054844,-0.004932, + 0.519231,-0.032667,0.85401,0.07258,0.054835,-0.005004, + 0.519231,0.032667,0.85401,0.07258,0.056936,-0.005004, + 0.41426,0.026063,0.909785,0.072444,0.056927,-0.004932, + 0.415079,0,0.909785,0.072477,0.055885,-0.004932, + 0.519231,0.032667,0.85401,0.07258,0.056936,-0.005004, + 0.415079,0,0.909785,0.072477,0.055885,-0.004932, + 0.520257,0,0.85401,0.072613,0.055885,-0.005004, + 0.516155,0.065205,0.85401,0.072481,0.057982,-0.005004, + 0.411806,0.052023,0.909785,0.072346,0.057965,-0.004932, + 0.41426,0.026063,0.909785,0.072444,0.056927,-0.004932, + 0.516155,0.065205,0.85401,0.072481,0.057982,-0.005004, + 0.41426,0.026063,0.909785,0.072444,0.056927,-0.004932, + 0.519231,0.032667,0.85401,0.07258,0.056936,-0.005004, + 0.511042,0.097487,0.85401,0.072316,0.05902,-0.005004, + 0.407727,0.077778,0.909785,0.072183,0.058994,-0.004932, + 0.411806,0.052023,0.909785,0.072346,0.057965,-0.004932, + 0.511042,0.097487,0.85401,0.072316,0.05902,-0.005004, + 0.411806,0.052023,0.909785,0.072346,0.057965,-0.004932, + 0.516155,0.065205,0.85401,0.072481,0.057982,-0.005004, + 0.503912,0.129383,0.85401,0.072087,0.060045,-0.005004, + 0.402039,0.103226,0.909785,0.071956,0.060012,-0.004932, + 0.407727,0.077778,0.909785,0.072183,0.058994,-0.004932, + 0.503912,0.129383,0.85401,0.072087,0.060045,-0.005004, + 0.407727,0.077778,0.909785,0.072183,0.058994,-0.004932, + 0.511042,0.097487,0.85401,0.072316,0.05902,-0.005004, + 0.494794,0.160768,0.85401,0.071794,0.061054,-0.005004, + 0.394764,0.128267,0.909785,0.071665,0.061012,-0.004932, + 0.402039,0.103226,0.909785,0.071956,0.060012,-0.004932, + 0.494794,0.160768,0.85401,0.071794,0.061054,-0.005004, + 0.402039,0.103226,0.909785,0.071956,0.060012,-0.004932, + 0.503912,0.129383,0.85401,0.072087,0.060045,-0.005004, + 0.483723,0.191519,0.85401,0.071438,0.062043,-0.005004, + 0.385931,0.152801,0.909785,0.071312,0.061993,-0.004932, + 0.394764,0.128267,0.909785,0.071665,0.061012,-0.004932, + 0.483723,0.191519,0.85401,0.071438,0.062043,-0.005004, + 0.394764,0.128267,0.909785,0.071665,0.061012,-0.004932, + 0.494794,0.160768,0.85401,0.071794,0.061054,-0.005004, + 0.470743,0.221515,0.85401,0.071021,0.063007,-0.005004, + 0.375575,0.176732,0.909785,0.070898,0.06295,-0.004932, + 0.385931,0.152801,0.909785,0.071312,0.061993,-0.004932, + 0.470743,0.221515,0.85401,0.071021,0.063007,-0.005004, + 0.385931,0.152801,0.909785,0.071312,0.061993,-0.004932, + 0.483723,0.191519,0.85401,0.071438,0.062043,-0.005004, + 0.455905,0.250636,0.85401,0.070543,0.063944,-0.005004, + 0.363737,0.199966,0.909785,0.070425,0.063878,-0.004932, + 0.375575,0.176732,0.909785,0.070898,0.06295,-0.004932, + 0.455905,0.250636,0.85401,0.070543,0.063944,-0.005004, + 0.375575,0.176732,0.909785,0.070898,0.06295,-0.004932, + 0.470743,0.221515,0.85401,0.071021,0.063007,-0.005004, + 0.439268,0.278768,0.85401,0.070009,0.064848,-0.005004, + 0.350463,0.222411,0.909785,0.069894,0.064776,-0.004932, + 0.363737,0.199966,0.909785,0.070425,0.063878,-0.004932, + 0.439268,0.278768,0.85401,0.070009,0.064848,-0.005004, + 0.363737,0.199966,0.909785,0.070425,0.063878,-0.004932, + 0.455905,0.250636,0.85401,0.070543,0.063944,-0.005004, + 0.420897,0.3058,0.85401,0.069418,0.065717,-0.005004, + 0.335806,0.243978,0.909785,0.069308,0.065638,-0.004932, + 0.350463,0.222411,0.909785,0.069894,0.064776,-0.004932, + 0.420897,0.3058,0.85401,0.069418,0.065717,-0.005004, + 0.350463,0.222411,0.909785,0.069894,0.064776,-0.004932, + 0.439268,0.278768,0.85401,0.070009,0.064848,-0.005004, + 0.400865,0.331624,0.85401,0.068774,0.066548,-0.005004, + 0.319824,0.264582,0.909785,0.06867,0.066461,-0.004932, + 0.335806,0.243978,0.909785,0.069308,0.065638,-0.004932, + 0.400865,0.331624,0.85401,0.068774,0.066548,-0.005004, + 0.335806,0.243978,0.909785,0.069308,0.065638,-0.004932, + 0.420897,0.3058,0.85401,0.069418,0.065717,-0.005004, + 0.379251,0.356141,0.85401,0.068079,0.067336,-0.005004, + 0.30258,0.284141,0.909785,0.06798,0.067243,-0.004932, + 0.319824,0.264582,0.909785,0.06867,0.066461,-0.004932, + 0.379251,0.356141,0.85401,0.068079,0.067336,-0.005004, + 0.319824,0.264582,0.909785,0.06867,0.066461,-0.004932, + 0.400865,0.331624,0.85401,0.068774,0.066548,-0.005004, + 0.356141,0.379251,0.85401,0.067336,0.068079,-0.005004, + 0.284141,0.30258,0.909785,0.067243,0.06798,-0.004932, + 0.30258,0.284141,0.909785,0.06798,0.067243,-0.004932, + 0.356141,0.379251,0.85401,0.067336,0.068079,-0.005004, + 0.30258,0.284141,0.909785,0.06798,0.067243,-0.004932, + 0.379251,0.356141,0.85401,0.068079,0.067336,-0.005004, + 0.331624,0.400865,0.85401,0.066548,0.068774,-0.005004, + 0.264582,0.319824,0.909785,0.066461,0.06867,-0.004932, + 0.284141,0.30258,0.909785,0.067243,0.06798,-0.004932, + 0.331624,0.400865,0.85401,0.066548,0.068774,-0.005004, + 0.284141,0.30258,0.909785,0.067243,0.06798,-0.004932, + 0.356141,0.379251,0.85401,0.067336,0.068079,-0.005004, + 0.3058,0.420897,0.85401,0.065717,0.069418,-0.005004, + 0.243978,0.335806,0.909785,0.065638,0.069308,-0.004932, + 0.264582,0.319824,0.909785,0.066461,0.06867,-0.004932, + 0.3058,0.420897,0.85401,0.065717,0.069418,-0.005004, + 0.264582,0.319824,0.909785,0.066461,0.06867,-0.004932, + 0.331624,0.400865,0.85401,0.066548,0.068774,-0.005004, + 0.278768,0.439268,0.85401,0.064848,0.070009,-0.005004, + 0.222411,0.350463,0.909785,0.064776,0.069894,-0.004932, + 0.243978,0.335806,0.909785,0.065638,0.069308,-0.004932, + 0.278768,0.439268,0.85401,0.064848,0.070009,-0.005004, + 0.243978,0.335806,0.909785,0.065638,0.069308,-0.004932, + 0.3058,0.420897,0.85401,0.065717,0.069418,-0.005004, + 0.250636,0.455905,0.85401,0.063944,0.070543,-0.005004, + 0.199966,0.363737,0.909785,0.063878,0.070425,-0.004932, + 0.222411,0.350463,0.909785,0.064776,0.069894,-0.004932, + 0.250636,0.455905,0.85401,0.063944,0.070543,-0.005004, + 0.222411,0.350463,0.909785,0.064776,0.069894,-0.004932, + 0.278768,0.439268,0.85401,0.064848,0.070009,-0.005004, + 0.221515,0.470743,0.85401,0.063007,0.071021,-0.005004, + 0.176732,0.375575,0.909785,0.06295,0.070898,-0.004932, + 0.199966,0.363737,0.909785,0.063878,0.070425,-0.004932, + 0.221515,0.470743,0.85401,0.063007,0.071021,-0.005004, + 0.199966,0.363737,0.909785,0.063878,0.070425,-0.004932, + 0.250636,0.455905,0.85401,0.063944,0.070543,-0.005004, + 0.191519,0.483723,0.85401,0.062043,0.071438,-0.005004, + 0.152801,0.385931,0.909785,0.061993,0.071312,-0.004932, + 0.176732,0.375575,0.909785,0.06295,0.070898,-0.004932, + 0.191519,0.483723,0.85401,0.062043,0.071438,-0.005004, + 0.176732,0.375575,0.909785,0.06295,0.070898,-0.004932, + 0.221515,0.470743,0.85401,0.063007,0.071021,-0.005004, + 0.160768,0.494794,0.85401,0.061054,0.071794,-0.005004, + 0.128267,0.394764,0.909785,0.061012,0.071665,-0.004932, + 0.152801,0.385931,0.909785,0.061993,0.071312,-0.004932, + 0.160768,0.494794,0.85401,0.061054,0.071794,-0.005004, + 0.152801,0.385931,0.909785,0.061993,0.071312,-0.004932, + 0.191519,0.483723,0.85401,0.062043,0.071438,-0.005004, + 0.129383,0.503912,0.85401,0.060045,0.072087,-0.005004, + 0.103226,0.402039,0.909785,0.060012,0.071956,-0.004932, + 0.128267,0.394764,0.909785,0.061012,0.071665,-0.004932, + 0.129383,0.503912,0.85401,0.060045,0.072087,-0.005004, + 0.128267,0.394764,0.909785,0.061012,0.071665,-0.004932, + 0.160768,0.494794,0.85401,0.061054,0.071794,-0.005004, + 0.097487,0.511042,0.85401,0.05902,0.072316,-0.005004, + 0.077778,0.407727,0.909785,0.058994,0.072183,-0.004932, + 0.103226,0.402039,0.909785,0.060012,0.071956,-0.004932, + 0.097487,0.511042,0.85401,0.05902,0.072316,-0.005004, + 0.103226,0.402039,0.909785,0.060012,0.071956,-0.004932, + 0.129383,0.503912,0.85401,0.060045,0.072087,-0.005004, + 0.065205,0.516155,0.85401,0.057982,0.072481,-0.005004, + 0.052023,0.411806,0.909785,0.057965,0.072346,-0.004932, + 0.077778,0.407727,0.909785,0.058994,0.072183,-0.004932, + 0.065205,0.516155,0.85401,0.057982,0.072481,-0.005004, + 0.077778,0.407727,0.909785,0.058994,0.072183,-0.004932, + 0.097487,0.511042,0.85401,0.05902,0.072316,-0.005004, + 0.032667,0.519231,0.85401,0.056936,0.07258,-0.005004, + 0.026063,0.41426,0.909785,0.056927,0.072444,-0.004932, + 0.052023,0.411806,0.909785,0.057965,0.072346,-0.004932, + 0.032667,0.519231,0.85401,0.056936,0.07258,-0.005004, + 0.052023,0.411806,0.909785,0.057965,0.072346,-0.004932, + 0.065205,0.516155,0.85401,0.057982,0.072481,-0.005004, + 0,0.520257,0.85401,0.055885,0.072613,-0.005004, + 0,0.415079,0.909785,0.055885,0.072477,-0.004932, + 0.026063,0.41426,0.909785,0.056927,0.072444,-0.004932, + 0,0.520257,0.85401,0.055885,0.072613,-0.005004, + 0.026063,0.41426,0.909785,0.056927,0.072444,-0.004932, + 0.032667,0.519231,0.85401,0.056936,0.07258,-0.005004, + -0.032667,0.519231,0.85401,0.054835,0.07258,-0.005004, + -0.026063,0.41426,0.909785,0.054844,0.072444,-0.004932, + 0,0.415079,0.909785,0.055885,0.072477,-0.004932, + -0.032667,0.519231,0.85401,0.054835,0.07258,-0.005004, + 0,0.415079,0.909785,0.055885,0.072477,-0.004932, + 0,0.520257,0.85401,0.055885,0.072613,-0.005004, + -0.065205,0.516155,0.85401,0.053789,0.072481,-0.005004, + -0.052023,0.411806,0.909785,0.053806,0.072346,-0.004932, + -0.026063,0.41426,0.909785,0.054844,0.072444,-0.004932, + -0.065205,0.516155,0.85401,0.053789,0.072481,-0.005004, + -0.026063,0.41426,0.909785,0.054844,0.072444,-0.004932, + -0.032667,0.519231,0.85401,0.054835,0.07258,-0.005004, + -0.097487,0.511042,0.85401,0.052751,0.072316,-0.005004, + -0.077778,0.407727,0.909785,0.052776,0.072183,-0.004932, + -0.052023,0.411806,0.909785,0.053806,0.072346,-0.004932, + -0.097487,0.511042,0.85401,0.052751,0.072316,-0.005004, + -0.052023,0.411806,0.909785,0.053806,0.072346,-0.004932, + -0.065205,0.516155,0.85401,0.053789,0.072481,-0.005004, + -0.129383,0.503912,0.85401,0.051725,0.072087,-0.005004, + -0.103226,0.402039,0.909785,0.051759,0.071956,-0.004932, + -0.077778,0.407727,0.909785,0.052776,0.072183,-0.004932, + -0.129383,0.503912,0.85401,0.051725,0.072087,-0.005004, + -0.077778,0.407727,0.909785,0.052776,0.072183,-0.004932, + -0.097487,0.511042,0.85401,0.052751,0.072316,-0.005004, + -0.160768,0.494794,0.85401,0.050716,0.071794,-0.005004, + -0.128267,0.394764,0.909785,0.050758,0.071665,-0.004932, + -0.103226,0.402039,0.909785,0.051759,0.071956,-0.004932, + -0.160768,0.494794,0.85401,0.050716,0.071794,-0.005004, + -0.103226,0.402039,0.909785,0.051759,0.071956,-0.004932, + -0.129383,0.503912,0.85401,0.051725,0.072087,-0.005004, + -0.191519,0.483723,0.85401,0.049728,0.071438,-0.005004, + -0.152801,0.385931,0.909785,0.049777,0.071312,-0.004932, + -0.128267,0.394764,0.909785,0.050758,0.071665,-0.004932, + -0.191519,0.483723,0.85401,0.049728,0.071438,-0.005004, + -0.128267,0.394764,0.909785,0.050758,0.071665,-0.004932, + -0.160768,0.494794,0.85401,0.050716,0.071794,-0.005004, + -0.221515,0.470743,0.85401,0.048763,0.071021,-0.005004, + -0.176732,0.375575,0.909785,0.048821,0.070898,-0.004932, + -0.152801,0.385931,0.909785,0.049777,0.071312,-0.004932, + -0.221515,0.470743,0.85401,0.048763,0.071021,-0.005004, + -0.152801,0.385931,0.909785,0.049777,0.071312,-0.004932, + -0.191519,0.483723,0.85401,0.049728,0.071438,-0.005004, + -0.250636,0.455905,0.85401,0.047827,0.070543,-0.005004, + -0.199966,0.363737,0.909785,0.047892,0.070425,-0.004932, + -0.176732,0.375575,0.909785,0.048821,0.070898,-0.004932, + -0.250636,0.455905,0.85401,0.047827,0.070543,-0.005004, + -0.176732,0.375575,0.909785,0.048821,0.070898,-0.004932, + -0.221515,0.470743,0.85401,0.048763,0.071021,-0.005004, + -0.278768,0.439268,0.85401,0.046922,0.070009,-0.005004, + -0.222411,0.350463,0.909785,0.046995,0.069894,-0.004932, + -0.199966,0.363737,0.909785,0.047892,0.070425,-0.004932, + -0.278768,0.439268,0.85401,0.046922,0.070009,-0.005004, + -0.199966,0.363737,0.909785,0.047892,0.070425,-0.004932, + -0.250636,0.455905,0.85401,0.047827,0.070543,-0.005004, + -0.3058,0.420897,0.85401,0.046053,0.069418,-0.005004, + -0.243978,0.335806,0.909785,0.046133,0.069308,-0.004932, + -0.222411,0.350463,0.909785,0.046995,0.069894,-0.004932, + -0.3058,0.420897,0.85401,0.046053,0.069418,-0.005004, + -0.222411,0.350463,0.909785,0.046995,0.069894,-0.004932, + -0.278768,0.439268,0.85401,0.046922,0.070009,-0.005004, + -0.331624,0.400865,0.85401,0.045223,0.068774,-0.005004, + -0.264582,0.319824,0.909785,0.045309,0.06867,-0.004932, + -0.243978,0.335806,0.909785,0.046133,0.069308,-0.004932, + -0.331624,0.400865,0.85401,0.045223,0.068774,-0.005004, + -0.243978,0.335806,0.909785,0.046133,0.069308,-0.004932, + -0.3058,0.420897,0.85401,0.046053,0.069418,-0.005004, + -0.356141,0.379251,0.85401,0.044435,0.068079,-0.005004, + -0.284141,0.30258,0.909785,0.044527,0.06798,-0.004932, + -0.264582,0.319824,0.909785,0.045309,0.06867,-0.004932, + -0.356141,0.379251,0.85401,0.044435,0.068079,-0.005004, + -0.264582,0.319824,0.909785,0.045309,0.06867,-0.004932, + -0.331624,0.400865,0.85401,0.045223,0.068774,-0.005004, + -0.379251,0.356141,0.85401,0.043692,0.067336,-0.005004, + -0.30258,0.284141,0.909785,0.04379,0.067243,-0.004932, + -0.284141,0.30258,0.909785,0.044527,0.06798,-0.004932, + -0.379251,0.356141,0.85401,0.043692,0.067336,-0.005004, + -0.284141,0.30258,0.909785,0.044527,0.06798,-0.004932, + -0.356141,0.379251,0.85401,0.044435,0.068079,-0.005004, + -0.400865,0.331624,0.85401,0.042997,0.066548,-0.005004, + -0.319824,0.264582,0.909785,0.043101,0.066461,-0.004932, + -0.30258,0.284141,0.909785,0.04379,0.067243,-0.004932, + -0.400865,0.331624,0.85401,0.042997,0.066548,-0.005004, + -0.30258,0.284141,0.909785,0.04379,0.067243,-0.004932, + -0.379251,0.356141,0.85401,0.043692,0.067336,-0.005004, + -0.420897,0.3058,0.85401,0.042353,0.065717,-0.005004, + -0.335806,0.243978,0.909785,0.042462,0.065638,-0.004932, + -0.319824,0.264582,0.909785,0.043101,0.066461,-0.004932, + -0.420897,0.3058,0.85401,0.042353,0.065717,-0.005004, + -0.319824,0.264582,0.909785,0.043101,0.066461,-0.004932, + -0.400865,0.331624,0.85401,0.042997,0.066548,-0.005004, + -0.439268,0.278768,0.85401,0.041762,0.064848,-0.005004, + -0.350463,0.222411,0.909785,0.041876,0.064776,-0.004932, + -0.335806,0.243978,0.909785,0.042462,0.065638,-0.004932, + -0.439268,0.278768,0.85401,0.041762,0.064848,-0.005004, + -0.335806,0.243978,0.909785,0.042462,0.065638,-0.004932, + -0.420897,0.3058,0.85401,0.042353,0.065717,-0.005004, + -0.455905,0.250636,0.85401,0.041227,0.063944,-0.005004, + -0.363737,0.199966,0.909785,0.041346,0.063878,-0.004932, + -0.350463,0.222411,0.909785,0.041876,0.064776,-0.004932, + -0.455905,0.250636,0.85401,0.041227,0.063944,-0.005004, + -0.350463,0.222411,0.909785,0.041876,0.064776,-0.004932, + -0.439268,0.278768,0.85401,0.041762,0.064848,-0.005004, + -0.470743,0.221515,0.85401,0.04075,0.063007,-0.005004, + -0.375575,0.176732,0.909785,0.040873,0.06295,-0.004932, + -0.363737,0.199966,0.909785,0.041346,0.063878,-0.004932, + -0.470743,0.221515,0.85401,0.04075,0.063007,-0.005004, + -0.363737,0.199966,0.909785,0.041346,0.063878,-0.004932, + -0.455905,0.250636,0.85401,0.041227,0.063944,-0.005004, + -0.483723,0.191519,0.85401,0.040333,0.062043,-0.005004, + -0.385931,0.152801,0.909785,0.040459,0.061993,-0.004932, + -0.375575,0.176732,0.909785,0.040873,0.06295,-0.004932, + -0.483723,0.191519,0.85401,0.040333,0.062043,-0.005004, + -0.375575,0.176732,0.909785,0.040873,0.06295,-0.004932, + -0.470743,0.221515,0.85401,0.04075,0.063007,-0.005004, + -0.494794,0.160768,0.85401,0.039977,0.061054,-0.005004, + -0.394764,0.128267,0.909785,0.040106,0.061012,-0.004932, + -0.385931,0.152801,0.909785,0.040459,0.061993,-0.004932, + -0.494794,0.160768,0.85401,0.039977,0.061054,-0.005004, + -0.385931,0.152801,0.909785,0.040459,0.061993,-0.004932, + -0.483723,0.191519,0.85401,0.040333,0.062043,-0.005004, + -0.503912,0.129383,0.85401,0.039684,0.060045,-0.005004, + -0.402039,0.103226,0.909785,0.039815,0.060012,-0.004932, + -0.394764,0.128267,0.909785,0.040106,0.061012,-0.004932, + -0.503912,0.129383,0.85401,0.039684,0.060045,-0.005004, + -0.394764,0.128267,0.909785,0.040106,0.061012,-0.004932, + -0.494794,0.160768,0.85401,0.039977,0.061054,-0.005004, + -0.511042,0.097487,0.85401,0.039454,0.05902,-0.005004, + -0.407727,0.077778,0.909785,0.039587,0.058994,-0.004932, + -0.402039,0.103226,0.909785,0.039815,0.060012,-0.004932, + -0.511042,0.097487,0.85401,0.039454,0.05902,-0.005004, + -0.402039,0.103226,0.909785,0.039815,0.060012,-0.004932, + -0.503912,0.129383,0.85401,0.039684,0.060045,-0.005004, + -0.407727,0.077778,0.909785,0.039587,0.058994,-0.004932, + -0.298634,0.056967,0.952666,0.039728,0.058967,-0.004877, + -0.294467,0.075606,0.952666,0.039953,0.059976,-0.004877, + -0.407727,0.077778,0.909785,0.039587,0.058994,-0.004932, + -0.294467,0.075606,0.952666,0.039953,0.059976,-0.004877, + -0.402039,0.103226,0.909785,0.039815,0.060012,-0.004932, + -0.411806,0.052023,0.909785,0.039424,0.057965,-0.004932, + -0.301621,0.038104,0.952666,0.039566,0.057947,-0.004877, + -0.298634,0.056967,0.952666,0.039728,0.058967,-0.004877, + -0.411806,0.052023,0.909785,0.039424,0.057965,-0.004932, + -0.298634,0.056967,0.952666,0.039728,0.058967,-0.004877, + -0.407727,0.077778,0.909785,0.039587,0.058994,-0.004932, + -0.41426,0.026063,0.909785,0.039326,0.056927,-0.004932, + -0.303419,0.019089,0.952666,0.039469,0.056918,-0.004877, + -0.301621,0.038104,0.952666,0.039566,0.057947,-0.004877, + -0.41426,0.026063,0.909785,0.039326,0.056927,-0.004932, + -0.301621,0.038104,0.952666,0.039566,0.057947,-0.004877, + -0.411806,0.052023,0.909785,0.039424,0.057965,-0.004932, + -0.415079,0,0.909785,0.039294,0.055885,-0.004932, + -0.304019,0,0.952666,0.039437,0.055885,-0.004877, + -0.303419,0.019089,0.952666,0.039469,0.056918,-0.004877, + -0.415079,0,0.909785,0.039294,0.055885,-0.004932, + -0.303419,0.019089,0.952666,0.039469,0.056918,-0.004877, + -0.41426,0.026063,0.909785,0.039326,0.056927,-0.004932, + -0.41426,-0.026063,0.909785,0.039326,0.054844,-0.004932, + -0.303419,-0.019089,0.952666,0.039469,0.054852,-0.004877, + -0.304019,0,0.952666,0.039437,0.055885,-0.004877, + -0.41426,-0.026063,0.909785,0.039326,0.054844,-0.004932, + -0.304019,0,0.952666,0.039437,0.055885,-0.004877, + -0.415079,0,0.909785,0.039294,0.055885,-0.004932, + -0.411806,-0.052023,0.909785,0.039424,0.053806,-0.004932, + -0.301621,-0.038104,0.952666,0.039566,0.053824,-0.004877, + -0.303419,-0.019089,0.952666,0.039469,0.054852,-0.004877, + -0.411806,-0.052023,0.909785,0.039424,0.053806,-0.004932, + -0.303419,-0.019089,0.952666,0.039469,0.054852,-0.004877, + -0.41426,-0.026063,0.909785,0.039326,0.054844,-0.004932, + -0.407727,-0.077778,0.909785,0.039587,0.052776,-0.004932, + -0.298634,-0.056967,0.952666,0.039728,0.052803,-0.004877, + -0.301621,-0.038104,0.952666,0.039566,0.053824,-0.004877, + -0.407727,-0.077778,0.909785,0.039587,0.052776,-0.004932, + -0.301621,-0.038104,0.952666,0.039566,0.053824,-0.004877, + -0.411806,-0.052023,0.909785,0.039424,0.053806,-0.004932, + -0.402039,-0.103226,0.909785,0.039815,0.051759,-0.004932, + -0.294467,-0.075606,0.952666,0.039953,0.051795,-0.004877, + -0.298634,-0.056967,0.952666,0.039728,0.052803,-0.004877, + -0.402039,-0.103226,0.909785,0.039815,0.051759,-0.004932, + -0.298634,-0.056967,0.952666,0.039728,0.052803,-0.004877, + -0.407727,-0.077778,0.909785,0.039587,0.052776,-0.004932, + -0.394764,-0.128267,0.909785,0.040106,0.050758,-0.004932, + -0.289139,-0.093947,0.952666,0.040242,0.050802,-0.004877, + -0.294467,-0.075606,0.952666,0.039953,0.051795,-0.004877, + -0.394764,-0.128267,0.909785,0.040106,0.050758,-0.004932, + -0.294467,-0.075606,0.952666,0.039953,0.051795,-0.004877, + -0.402039,-0.103226,0.909785,0.039815,0.051759,-0.004932, + -0.385931,-0.152801,0.909785,0.040459,0.049777,-0.004932, + -0.282669,-0.111917,0.952666,0.040592,0.04983,-0.004877, + -0.289139,-0.093947,0.952666,0.040242,0.050802,-0.004877, + -0.385931,-0.152801,0.909785,0.040459,0.049777,-0.004932, + -0.289139,-0.093947,0.952666,0.040242,0.050802,-0.004877, + -0.394764,-0.128267,0.909785,0.040106,0.050758,-0.004932, + -0.375575,-0.176732,0.909785,0.040873,0.048821,-0.004932, + -0.275084,-0.129445,0.952666,0.041002,0.048882,-0.004877, + -0.282669,-0.111917,0.952666,0.040592,0.04983,-0.004877, + -0.375575,-0.176732,0.909785,0.040873,0.048821,-0.004932, + -0.282669,-0.111917,0.952666,0.040592,0.04983,-0.004877, + -0.385931,-0.152801,0.909785,0.040459,0.049777,-0.004932, + -0.363737,-0.199966,0.909785,0.041346,0.047892,-0.004932, + -0.266414,-0.146462,0.952666,0.041471,0.047961,-0.004877, + -0.275084,-0.129445,0.952666,0.041002,0.048882,-0.004877, + -0.363737,-0.199966,0.909785,0.041346,0.047892,-0.004932, + -0.275084,-0.129445,0.952666,0.041002,0.048882,-0.004877, + -0.375575,-0.176732,0.909785,0.040873,0.048821,-0.004932, + -0.350463,-0.222411,0.909785,0.041876,0.046995,-0.004932, + -0.256692,-0.162901,0.952666,0.041997,0.047072,-0.004877, + -0.266414,-0.146462,0.952666,0.041471,0.047961,-0.004877, + -0.350463,-0.222411,0.909785,0.041876,0.046995,-0.004932, + -0.266414,-0.146462,0.952666,0.041471,0.047961,-0.004877, + -0.363737,-0.199966,0.909785,0.041346,0.047892,-0.004932, + -0.335806,-0.243978,0.909785,0.042462,0.046133,-0.004932, + -0.245956,-0.178698,0.952666,0.042578,0.046217,-0.004877, + -0.256692,-0.162901,0.952666,0.041997,0.047072,-0.004877, + -0.335806,-0.243978,0.909785,0.042462,0.046133,-0.004932, + -0.256692,-0.162901,0.952666,0.041997,0.047072,-0.004877, + -0.350463,-0.222411,0.909785,0.041876,0.046995,-0.004932, + -0.319824,-0.264582,0.909785,0.043101,0.045309,-0.004932, + -0.23425,-0.193789,0.952666,0.043211,0.0454,-0.004877, + -0.245956,-0.178698,0.952666,0.042578,0.046217,-0.004877, + -0.319824,-0.264582,0.909785,0.043101,0.045309,-0.004932, + -0.245956,-0.178698,0.952666,0.042578,0.046217,-0.004877, + -0.335806,-0.243978,0.909785,0.042462,0.046133,-0.004932, + -0.30258,-0.284141,0.909785,0.04379,0.044527,-0.004932, + -0.22162,-0.208115,0.952666,0.043895,0.044625,-0.004877, + -0.23425,-0.193789,0.952666,0.043211,0.0454,-0.004877, + -0.30258,-0.284141,0.909785,0.04379,0.044527,-0.004932, + -0.23425,-0.193789,0.952666,0.043211,0.0454,-0.004877, + -0.319824,-0.264582,0.909785,0.043101,0.045309,-0.004932, + -0.284141,-0.30258,0.909785,0.044527,0.04379,-0.004932, + -0.208115,-0.22162,0.952666,0.044625,0.043895,-0.004877, + -0.22162,-0.208115,0.952666,0.043895,0.044625,-0.004877, + -0.284141,-0.30258,0.909785,0.044527,0.04379,-0.004932, + -0.22162,-0.208115,0.952666,0.043895,0.044625,-0.004877, + -0.30258,-0.284141,0.909785,0.04379,0.044527,-0.004932, + -0.264582,-0.319824,0.909785,0.045309,0.043101,-0.004932, + -0.193789,-0.23425,0.952666,0.0454,0.043211,-0.004877, + -0.208115,-0.22162,0.952666,0.044625,0.043895,-0.004877, + -0.264582,-0.319824,0.909785,0.045309,0.043101,-0.004932, + -0.208115,-0.22162,0.952666,0.044625,0.043895,-0.004877, + -0.284141,-0.30258,0.909785,0.044527,0.04379,-0.004932, + -0.243978,-0.335806,0.909785,0.046133,0.042462,-0.004932, + -0.178698,-0.245956,0.952666,0.046217,0.042578,-0.004877, + -0.193789,-0.23425,0.952666,0.0454,0.043211,-0.004877, + -0.243978,-0.335806,0.909785,0.046133,0.042462,-0.004932, + -0.193789,-0.23425,0.952666,0.0454,0.043211,-0.004877, + -0.264582,-0.319824,0.909785,0.045309,0.043101,-0.004932, + -0.222411,-0.350463,0.909785,0.046995,0.041876,-0.004932, + -0.162901,-0.256692,0.952666,0.047072,0.041997,-0.004877, + -0.178698,-0.245956,0.952666,0.046217,0.042578,-0.004877, + -0.222411,-0.350463,0.909785,0.046995,0.041876,-0.004932, + -0.178698,-0.245956,0.952666,0.046217,0.042578,-0.004877, + -0.243978,-0.335806,0.909785,0.046133,0.042462,-0.004932, + -0.199966,-0.363737,0.909785,0.047892,0.041346,-0.004932, + -0.146462,-0.266414,0.952666,0.047961,0.041471,-0.004877, + -0.162901,-0.256692,0.952666,0.047072,0.041997,-0.004877, + -0.199966,-0.363737,0.909785,0.047892,0.041346,-0.004932, + -0.162901,-0.256692,0.952666,0.047072,0.041997,-0.004877, + -0.222411,-0.350463,0.909785,0.046995,0.041876,-0.004932, + -0.176732,-0.375575,0.909785,0.048821,0.040873,-0.004932, + -0.129445,-0.275084,0.952666,0.048882,0.041002,-0.004877, + -0.146462,-0.266414,0.952666,0.047961,0.041471,-0.004877, + -0.176732,-0.375575,0.909785,0.048821,0.040873,-0.004932, + -0.146462,-0.266414,0.952666,0.047961,0.041471,-0.004877, + -0.199966,-0.363737,0.909785,0.047892,0.041346,-0.004932, + -0.152801,-0.385931,0.909785,0.049777,0.040459,-0.004932, + -0.111917,-0.282669,0.952666,0.04983,0.040592,-0.004877, + -0.129445,-0.275084,0.952666,0.048882,0.041002,-0.004877, + -0.152801,-0.385931,0.909785,0.049777,0.040459,-0.004932, + -0.129445,-0.275084,0.952666,0.048882,0.041002,-0.004877, + -0.176732,-0.375575,0.909785,0.048821,0.040873,-0.004932, + -0.128267,-0.394764,0.909785,0.050758,0.040106,-0.004932, + -0.093947,-0.289139,0.952666,0.050802,0.040242,-0.004877, + -0.111917,-0.282669,0.952666,0.04983,0.040592,-0.004877, + -0.128267,-0.394764,0.909785,0.050758,0.040106,-0.004932, + -0.111917,-0.282669,0.952666,0.04983,0.040592,-0.004877, + -0.152801,-0.385931,0.909785,0.049777,0.040459,-0.004932, + -0.103226,-0.402039,0.909785,0.051759,0.039815,-0.004932, + -0.075606,-0.294467,0.952666,0.051795,0.039953,-0.004877, + -0.093947,-0.289139,0.952666,0.050802,0.040242,-0.004877, + -0.103226,-0.402039,0.909785,0.051759,0.039815,-0.004932, + -0.093947,-0.289139,0.952666,0.050802,0.040242,-0.004877, + -0.128267,-0.394764,0.909785,0.050758,0.040106,-0.004932, + -0.077778,-0.407727,0.909785,0.052776,0.039587,-0.004932, + -0.056967,-0.298634,0.952666,0.052803,0.039728,-0.004877, + -0.075606,-0.294467,0.952666,0.051795,0.039953,-0.004877, + -0.077778,-0.407727,0.909785,0.052776,0.039587,-0.004932, + -0.075606,-0.294467,0.952666,0.051795,0.039953,-0.004877, + -0.103226,-0.402039,0.909785,0.051759,0.039815,-0.004932, + -0.052023,-0.411806,0.909785,0.053806,0.039424,-0.004932, + -0.038104,-0.301621,0.952666,0.053824,0.039566,-0.004877, + -0.056967,-0.298634,0.952666,0.052803,0.039728,-0.004877, + -0.052023,-0.411806,0.909785,0.053806,0.039424,-0.004932, + -0.056967,-0.298634,0.952666,0.052803,0.039728,-0.004877, + -0.077778,-0.407727,0.909785,0.052776,0.039587,-0.004932, + -0.026063,-0.41426,0.909785,0.054844,0.039326,-0.004932, + -0.019089,-0.303419,0.952666,0.054852,0.039469,-0.004877, + -0.038104,-0.301621,0.952666,0.053824,0.039566,-0.004877, + -0.026063,-0.41426,0.909785,0.054844,0.039326,-0.004932, + -0.038104,-0.301621,0.952666,0.053824,0.039566,-0.004877, + -0.052023,-0.411806,0.909785,0.053806,0.039424,-0.004932, + 0,-0.415079,0.909785,0.055885,0.039294,-0.004932, + 0,-0.304019,0.952666,0.055885,0.039437,-0.004877, + -0.019089,-0.303419,0.952666,0.054852,0.039469,-0.004877, + 0,-0.415079,0.909785,0.055885,0.039294,-0.004932, + -0.019089,-0.303419,0.952666,0.054852,0.039469,-0.004877, + -0.026063,-0.41426,0.909785,0.054844,0.039326,-0.004932, + 0.026063,-0.41426,0.909785,0.056927,0.039326,-0.004932, + 0.019089,-0.303419,0.952666,0.056918,0.039469,-0.004877, + 0,-0.304019,0.952666,0.055885,0.039437,-0.004877, + 0.026063,-0.41426,0.909785,0.056927,0.039326,-0.004932, + 0,-0.304019,0.952666,0.055885,0.039437,-0.004877, + 0,-0.415079,0.909785,0.055885,0.039294,-0.004932, + 0.052023,-0.411806,0.909785,0.057965,0.039424,-0.004932, + 0.038104,-0.301621,0.952666,0.057947,0.039566,-0.004877, + 0.019089,-0.303419,0.952666,0.056918,0.039469,-0.004877, + 0.052023,-0.411806,0.909785,0.057965,0.039424,-0.004932, + 0.019089,-0.303419,0.952666,0.056918,0.039469,-0.004877, + 0.026063,-0.41426,0.909785,0.056927,0.039326,-0.004932, + 0.077778,-0.407727,0.909785,0.058994,0.039587,-0.004932, + 0.056967,-0.298634,0.952666,0.058967,0.039728,-0.004877, + 0.038104,-0.301621,0.952666,0.057947,0.039566,-0.004877, + 0.077778,-0.407727,0.909785,0.058994,0.039587,-0.004932, + 0.038104,-0.301621,0.952666,0.057947,0.039566,-0.004877, + 0.052023,-0.411806,0.909785,0.057965,0.039424,-0.004932, + 0.103226,-0.402039,0.909785,0.060012,0.039815,-0.004932, + 0.075606,-0.294467,0.952666,0.059976,0.039953,-0.004877, + 0.056967,-0.298634,0.952666,0.058967,0.039728,-0.004877, + 0.103226,-0.402039,0.909785,0.060012,0.039815,-0.004932, + 0.056967,-0.298634,0.952666,0.058967,0.039728,-0.004877, + 0.077778,-0.407727,0.909785,0.058994,0.039587,-0.004932, + 0.128267,-0.394764,0.909785,0.061012,0.040106,-0.004932, + 0.093947,-0.289139,0.952666,0.060968,0.040242,-0.004877, + 0.075606,-0.294467,0.952666,0.059976,0.039953,-0.004877, + 0.128267,-0.394764,0.909785,0.061012,0.040106,-0.004932, + 0.075606,-0.294467,0.952666,0.059976,0.039953,-0.004877, + 0.103226,-0.402039,0.909785,0.060012,0.039815,-0.004932, + 0.152801,-0.385931,0.909785,0.061993,0.040459,-0.004932, + 0.111917,-0.282669,0.952666,0.061941,0.040592,-0.004877, + 0.093947,-0.289139,0.952666,0.060968,0.040242,-0.004877, + 0.152801,-0.385931,0.909785,0.061993,0.040459,-0.004932, + 0.093947,-0.289139,0.952666,0.060968,0.040242,-0.004877, + 0.128267,-0.394764,0.909785,0.061012,0.040106,-0.004932, + 0.176732,-0.375575,0.909785,0.06295,0.040873,-0.004932, + 0.129445,-0.275084,0.952666,0.062889,0.041002,-0.004877, + 0.111917,-0.282669,0.952666,0.061941,0.040592,-0.004877, + 0.176732,-0.375575,0.909785,0.06295,0.040873,-0.004932, + 0.111917,-0.282669,0.952666,0.061941,0.040592,-0.004877, + 0.152801,-0.385931,0.909785,0.061993,0.040459,-0.004932, + 0.199966,-0.363737,0.909785,0.063878,0.041346,-0.004932, + 0.146462,-0.266414,0.952666,0.063809,0.041471,-0.004877, + 0.129445,-0.275084,0.952666,0.062889,0.041002,-0.004877, + 0.199966,-0.363737,0.909785,0.063878,0.041346,-0.004932, + 0.129445,-0.275084,0.952666,0.062889,0.041002,-0.004877, + 0.176732,-0.375575,0.909785,0.06295,0.040873,-0.004932, + 0.222411,-0.350463,0.909785,0.064776,0.041876,-0.004932, + 0.162901,-0.256692,0.952666,0.064699,0.041997,-0.004877, + 0.146462,-0.266414,0.952666,0.063809,0.041471,-0.004877, + 0.222411,-0.350463,0.909785,0.064776,0.041876,-0.004932, + 0.146462,-0.266414,0.952666,0.063809,0.041471,-0.004877, + 0.199966,-0.363737,0.909785,0.063878,0.041346,-0.004932, + 0.243978,-0.335806,0.909785,0.065638,0.042462,-0.004932, + 0.178698,-0.245956,0.952666,0.065554,0.042578,-0.004877, + 0.162901,-0.256692,0.952666,0.064699,0.041997,-0.004877, + 0.243978,-0.335806,0.909785,0.065638,0.042462,-0.004932, + 0.162901,-0.256692,0.952666,0.064699,0.041997,-0.004877, + 0.222411,-0.350463,0.909785,0.064776,0.041876,-0.004932, + 0.264582,-0.319824,0.909785,0.066461,0.043101,-0.004932, + 0.193789,-0.23425,0.952666,0.06637,0.043211,-0.004877, + 0.178698,-0.245956,0.952666,0.065554,0.042578,-0.004877, + 0.264582,-0.319824,0.909785,0.066461,0.043101,-0.004932, + 0.178698,-0.245956,0.952666,0.065554,0.042578,-0.004877, + 0.243978,-0.335806,0.909785,0.065638,0.042462,-0.004932, + 0.284141,-0.30258,0.909785,0.067243,0.04379,-0.004932, + 0.208115,-0.22162,0.952666,0.067145,0.043895,-0.004877, + 0.193789,-0.23425,0.952666,0.06637,0.043211,-0.004877, + 0.284141,-0.30258,0.909785,0.067243,0.04379,-0.004932, + 0.193789,-0.23425,0.952666,0.06637,0.043211,-0.004877, + 0.264582,-0.319824,0.909785,0.066461,0.043101,-0.004932, + 0.30258,-0.284141,0.909785,0.06798,0.044527,-0.004932, + 0.22162,-0.208115,0.952666,0.067876,0.044625,-0.004877, + 0.208115,-0.22162,0.952666,0.067145,0.043895,-0.004877, + 0.30258,-0.284141,0.909785,0.06798,0.044527,-0.004932, + 0.208115,-0.22162,0.952666,0.067145,0.043895,-0.004877, + 0.284141,-0.30258,0.909785,0.067243,0.04379,-0.004932, + 0.319824,-0.264582,0.909785,0.06867,0.045309,-0.004932, + 0.23425,-0.193789,0.952666,0.068559,0.0454,-0.004877, + 0.22162,-0.208115,0.952666,0.067876,0.044625,-0.004877, + 0.319824,-0.264582,0.909785,0.06867,0.045309,-0.004932, + 0.22162,-0.208115,0.952666,0.067876,0.044625,-0.004877, + 0.30258,-0.284141,0.909785,0.06798,0.044527,-0.004932, + 0.335806,-0.243978,0.909785,0.069308,0.046133,-0.004932, + 0.245956,-0.178698,0.952666,0.069193,0.046217,-0.004877, + 0.23425,-0.193789,0.952666,0.068559,0.0454,-0.004877, + 0.335806,-0.243978,0.909785,0.069308,0.046133,-0.004932, + 0.23425,-0.193789,0.952666,0.068559,0.0454,-0.004877, + 0.319824,-0.264582,0.909785,0.06867,0.045309,-0.004932, + 0.350463,-0.222411,0.909785,0.069894,0.046995,-0.004932, + 0.256692,-0.162901,0.952666,0.069773,0.047072,-0.004877, + 0.245956,-0.178698,0.952666,0.069193,0.046217,-0.004877, + 0.350463,-0.222411,0.909785,0.069894,0.046995,-0.004932, + 0.245956,-0.178698,0.952666,0.069193,0.046217,-0.004877, + 0.335806,-0.243978,0.909785,0.069308,0.046133,-0.004932, + 0.363737,-0.199966,0.909785,0.070425,0.047892,-0.004932, + 0.266414,-0.146462,0.952666,0.070299,0.047961,-0.004877, + 0.256692,-0.162901,0.952666,0.069773,0.047072,-0.004877, + 0.363737,-0.199966,0.909785,0.070425,0.047892,-0.004932, + 0.256692,-0.162901,0.952666,0.069773,0.047072,-0.004877, + 0.350463,-0.222411,0.909785,0.069894,0.046995,-0.004932, + 0.375575,-0.176732,0.909785,0.070898,0.048821,-0.004932, + 0.275084,-0.129445,0.952666,0.070769,0.048882,-0.004877, + 0.266414,-0.146462,0.952666,0.070299,0.047961,-0.004877, + 0.375575,-0.176732,0.909785,0.070898,0.048821,-0.004932, + 0.266414,-0.146462,0.952666,0.070299,0.047961,-0.004877, + 0.363737,-0.199966,0.909785,0.070425,0.047892,-0.004932, + 0.385931,-0.152801,0.909785,0.071312,0.049777,-0.004932, + 0.282669,-0.111917,0.952666,0.071179,0.04983,-0.004877, + 0.275084,-0.129445,0.952666,0.070769,0.048882,-0.004877, + 0.385931,-0.152801,0.909785,0.071312,0.049777,-0.004932, + 0.275084,-0.129445,0.952666,0.070769,0.048882,-0.004877, + 0.375575,-0.176732,0.909785,0.070898,0.048821,-0.004932, + 0.394764,-0.128267,0.909785,0.071665,0.050758,-0.004932, + 0.289139,-0.093947,0.952666,0.071529,0.050802,-0.004877, + 0.282669,-0.111917,0.952666,0.071179,0.04983,-0.004877, + 0.394764,-0.128267,0.909785,0.071665,0.050758,-0.004932, + 0.282669,-0.111917,0.952666,0.071179,0.04983,-0.004877, + 0.385931,-0.152801,0.909785,0.071312,0.049777,-0.004932, + 0.402039,-0.103226,0.909785,0.071956,0.051759,-0.004932, + 0.294467,-0.075606,0.952666,0.071817,0.051795,-0.004877, + 0.289139,-0.093947,0.952666,0.071529,0.050802,-0.004877, + 0.402039,-0.103226,0.909785,0.071956,0.051759,-0.004932, + 0.289139,-0.093947,0.952666,0.071529,0.050802,-0.004877, + 0.394764,-0.128267,0.909785,0.071665,0.050758,-0.004932, + 0.407727,-0.077778,0.909785,0.072183,0.052776,-0.004932, + 0.298634,-0.056967,0.952666,0.072043,0.052803,-0.004877, + 0.294467,-0.075606,0.952666,0.071817,0.051795,-0.004877, + 0.407727,-0.077778,0.909785,0.072183,0.052776,-0.004932, + 0.294467,-0.075606,0.952666,0.071817,0.051795,-0.004877, + 0.402039,-0.103226,0.909785,0.071956,0.051759,-0.004932, + 0.411806,-0.052023,0.909785,0.072346,0.053806,-0.004932, + 0.301621,-0.038104,0.952666,0.072204,0.053824,-0.004877, + 0.298634,-0.056967,0.952666,0.072043,0.052803,-0.004877, + 0.411806,-0.052023,0.909785,0.072346,0.053806,-0.004932, + 0.298634,-0.056967,0.952666,0.072043,0.052803,-0.004877, + 0.407727,-0.077778,0.909785,0.072183,0.052776,-0.004932, + 0.41426,-0.026063,0.909785,0.072444,0.054844,-0.004932, + 0.303419,-0.019089,0.952666,0.072302,0.054852,-0.004877, + 0.301621,-0.038104,0.952666,0.072204,0.053824,-0.004877, + 0.41426,-0.026063,0.909785,0.072444,0.054844,-0.004932, + 0.301621,-0.038104,0.952666,0.072204,0.053824,-0.004877, + 0.411806,-0.052023,0.909785,0.072346,0.053806,-0.004932, + 0.415079,0,0.909785,0.072477,0.055885,-0.004932, + 0.304019,0,0.952666,0.072334,0.055885,-0.004877, + 0.303419,-0.019089,0.952666,0.072302,0.054852,-0.004877, + 0.415079,0,0.909785,0.072477,0.055885,-0.004932, + 0.303419,-0.019089,0.952666,0.072302,0.054852,-0.004877, + 0.41426,-0.026063,0.909785,0.072444,0.054844,-0.004932, + 0.41426,0.026063,0.909785,0.072444,0.056927,-0.004932, + 0.303419,0.019089,0.952666,0.072302,0.056918,-0.004877, + 0.304019,0,0.952666,0.072334,0.055885,-0.004877, + 0.41426,0.026063,0.909785,0.072444,0.056927,-0.004932, + 0.304019,0,0.952666,0.072334,0.055885,-0.004877, + 0.415079,0,0.909785,0.072477,0.055885,-0.004932, + 0.411806,0.052023,0.909785,0.072346,0.057965,-0.004932, + 0.301621,0.038104,0.952666,0.072204,0.057947,-0.004877, + 0.303419,0.019089,0.952666,0.072302,0.056918,-0.004877, + 0.411806,0.052023,0.909785,0.072346,0.057965,-0.004932, + 0.303419,0.019089,0.952666,0.072302,0.056918,-0.004877, + 0.41426,0.026063,0.909785,0.072444,0.056927,-0.004932, + 0.407727,0.077778,0.909785,0.072183,0.058994,-0.004932, + 0.298634,0.056967,0.952666,0.072043,0.058967,-0.004877, + 0.301621,0.038104,0.952666,0.072204,0.057947,-0.004877, + 0.407727,0.077778,0.909785,0.072183,0.058994,-0.004932, + 0.301621,0.038104,0.952666,0.072204,0.057947,-0.004877, + 0.411806,0.052023,0.909785,0.072346,0.057965,-0.004932, + 0.402039,0.103226,0.909785,0.071956,0.060012,-0.004932, + 0.294467,0.075606,0.952666,0.071817,0.059976,-0.004877, + 0.298634,0.056967,0.952666,0.072043,0.058967,-0.004877, + 0.402039,0.103226,0.909785,0.071956,0.060012,-0.004932, + 0.298634,0.056967,0.952666,0.072043,0.058967,-0.004877, + 0.407727,0.077778,0.909785,0.072183,0.058994,-0.004932, + 0.394764,0.128267,0.909785,0.071665,0.061012,-0.004932, + 0.289139,0.093947,0.952666,0.071529,0.060968,-0.004877, + 0.294467,0.075606,0.952666,0.071817,0.059976,-0.004877, + 0.394764,0.128267,0.909785,0.071665,0.061012,-0.004932, + 0.294467,0.075606,0.952666,0.071817,0.059976,-0.004877, + 0.402039,0.103226,0.909785,0.071956,0.060012,-0.004932, + 0.385931,0.152801,0.909785,0.071312,0.061993,-0.004932, + 0.282669,0.111917,0.952666,0.071179,0.061941,-0.004877, + 0.289139,0.093947,0.952666,0.071529,0.060968,-0.004877, + 0.385931,0.152801,0.909785,0.071312,0.061993,-0.004932, + 0.289139,0.093947,0.952666,0.071529,0.060968,-0.004877, + 0.394764,0.128267,0.909785,0.071665,0.061012,-0.004932, + 0.375575,0.176732,0.909785,0.070898,0.06295,-0.004932, + 0.275084,0.129445,0.952666,0.070769,0.062889,-0.004877, + 0.282669,0.111917,0.952666,0.071179,0.061941,-0.004877, + 0.375575,0.176732,0.909785,0.070898,0.06295,-0.004932, + 0.282669,0.111917,0.952666,0.071179,0.061941,-0.004877, + 0.385931,0.152801,0.909785,0.071312,0.061993,-0.004932, + 0.363737,0.199966,0.909785,0.070425,0.063878,-0.004932, + 0.266414,0.146462,0.952666,0.070299,0.063809,-0.004877, + 0.275084,0.129445,0.952666,0.070769,0.062889,-0.004877, + 0.363737,0.199966,0.909785,0.070425,0.063878,-0.004932, + 0.275084,0.129445,0.952666,0.070769,0.062889,-0.004877, + 0.375575,0.176732,0.909785,0.070898,0.06295,-0.004932, + 0.350463,0.222411,0.909785,0.069894,0.064776,-0.004932, + 0.256692,0.162901,0.952666,0.069773,0.064699,-0.004877, + 0.266414,0.146462,0.952666,0.070299,0.063809,-0.004877, + 0.350463,0.222411,0.909785,0.069894,0.064776,-0.004932, + 0.266414,0.146462,0.952666,0.070299,0.063809,-0.004877, + 0.363737,0.199966,0.909785,0.070425,0.063878,-0.004932, + 0.335806,0.243978,0.909785,0.069308,0.065638,-0.004932, + 0.245956,0.178698,0.952666,0.069193,0.065554,-0.004877, + 0.256692,0.162901,0.952666,0.069773,0.064699,-0.004877, + 0.335806,0.243978,0.909785,0.069308,0.065638,-0.004932, + 0.256692,0.162901,0.952666,0.069773,0.064699,-0.004877, + 0.350463,0.222411,0.909785,0.069894,0.064776,-0.004932, + 0.319824,0.264582,0.909785,0.06867,0.066461,-0.004932, + 0.23425,0.193789,0.952666,0.068559,0.06637,-0.004877, + 0.245956,0.178698,0.952666,0.069193,0.065554,-0.004877, + 0.319824,0.264582,0.909785,0.06867,0.066461,-0.004932, + 0.245956,0.178698,0.952666,0.069193,0.065554,-0.004877, + 0.335806,0.243978,0.909785,0.069308,0.065638,-0.004932, + 0.30258,0.284141,0.909785,0.06798,0.067243,-0.004932, + 0.22162,0.208115,0.952666,0.067876,0.067145,-0.004877, + 0.23425,0.193789,0.952666,0.068559,0.06637,-0.004877, + 0.30258,0.284141,0.909785,0.06798,0.067243,-0.004932, + 0.23425,0.193789,0.952666,0.068559,0.06637,-0.004877, + 0.319824,0.264582,0.909785,0.06867,0.066461,-0.004932, + 0.284141,0.30258,0.909785,0.067243,0.06798,-0.004932, + 0.208115,0.22162,0.952666,0.067145,0.067876,-0.004877, + 0.22162,0.208115,0.952666,0.067876,0.067145,-0.004877, + 0.284141,0.30258,0.909785,0.067243,0.06798,-0.004932, + 0.22162,0.208115,0.952666,0.067876,0.067145,-0.004877, + 0.30258,0.284141,0.909785,0.06798,0.067243,-0.004932, + 0.264582,0.319824,0.909785,0.066461,0.06867,-0.004932, + 0.193789,0.23425,0.952666,0.06637,0.068559,-0.004877, + 0.208115,0.22162,0.952666,0.067145,0.067876,-0.004877, + 0.264582,0.319824,0.909785,0.066461,0.06867,-0.004932, + 0.208115,0.22162,0.952666,0.067145,0.067876,-0.004877, + 0.284141,0.30258,0.909785,0.067243,0.06798,-0.004932, + 0.243978,0.335806,0.909785,0.065638,0.069308,-0.004932, + 0.178698,0.245956,0.952666,0.065554,0.069193,-0.004877, + 0.193789,0.23425,0.952666,0.06637,0.068559,-0.004877, + 0.243978,0.335806,0.909785,0.065638,0.069308,-0.004932, + 0.193789,0.23425,0.952666,0.06637,0.068559,-0.004877, + 0.264582,0.319824,0.909785,0.066461,0.06867,-0.004932, + 0.222411,0.350463,0.909785,0.064776,0.069894,-0.004932, + 0.162901,0.256692,0.952666,0.064699,0.069773,-0.004877, + 0.178698,0.245956,0.952666,0.065554,0.069193,-0.004877, + 0.222411,0.350463,0.909785,0.064776,0.069894,-0.004932, + 0.178698,0.245956,0.952666,0.065554,0.069193,-0.004877, + 0.243978,0.335806,0.909785,0.065638,0.069308,-0.004932, + 0.199966,0.363737,0.909785,0.063878,0.070425,-0.004932, + 0.146462,0.266414,0.952666,0.063809,0.070299,-0.004877, + 0.162901,0.256692,0.952666,0.064699,0.069773,-0.004877, + 0.199966,0.363737,0.909785,0.063878,0.070425,-0.004932, + 0.162901,0.256692,0.952666,0.064699,0.069773,-0.004877, + 0.222411,0.350463,0.909785,0.064776,0.069894,-0.004932, + 0.176732,0.375575,0.909785,0.06295,0.070898,-0.004932, + 0.129445,0.275084,0.952666,0.062889,0.070769,-0.004877, + 0.146462,0.266414,0.952666,0.063809,0.070299,-0.004877, + 0.176732,0.375575,0.909785,0.06295,0.070898,-0.004932, + 0.146462,0.266414,0.952666,0.063809,0.070299,-0.004877, + 0.199966,0.363737,0.909785,0.063878,0.070425,-0.004932, + 0.152801,0.385931,0.909785,0.061993,0.071312,-0.004932, + 0.111917,0.282669,0.952666,0.061941,0.071179,-0.004877, + 0.129445,0.275084,0.952666,0.062889,0.070769,-0.004877, + 0.152801,0.385931,0.909785,0.061993,0.071312,-0.004932, + 0.129445,0.275084,0.952666,0.062889,0.070769,-0.004877, + 0.176732,0.375575,0.909785,0.06295,0.070898,-0.004932, + 0.128267,0.394764,0.909785,0.061012,0.071665,-0.004932, + 0.093947,0.289139,0.952666,0.060968,0.071529,-0.004877, + 0.111917,0.282669,0.952666,0.061941,0.071179,-0.004877, + 0.128267,0.394764,0.909785,0.061012,0.071665,-0.004932, + 0.111917,0.282669,0.952666,0.061941,0.071179,-0.004877, + 0.152801,0.385931,0.909785,0.061993,0.071312,-0.004932, + 0.103226,0.402039,0.909785,0.060012,0.071956,-0.004932, + 0.075606,0.294467,0.952666,0.059976,0.071817,-0.004877, + 0.093947,0.289139,0.952666,0.060968,0.071529,-0.004877, + 0.103226,0.402039,0.909785,0.060012,0.071956,-0.004932, + 0.093947,0.289139,0.952666,0.060968,0.071529,-0.004877, + 0.128267,0.394764,0.909785,0.061012,0.071665,-0.004932, + 0.077778,0.407727,0.909785,0.058994,0.072183,-0.004932, + 0.056967,0.298634,0.952666,0.058967,0.072043,-0.004877, + 0.075606,0.294467,0.952666,0.059976,0.071817,-0.004877, + 0.077778,0.407727,0.909785,0.058994,0.072183,-0.004932, + 0.075606,0.294467,0.952666,0.059976,0.071817,-0.004877, + 0.103226,0.402039,0.909785,0.060012,0.071956,-0.004932, + 0.052023,0.411806,0.909785,0.057965,0.072346,-0.004932, + 0.038104,0.301621,0.952666,0.057947,0.072204,-0.004877, + 0.056967,0.298634,0.952666,0.058967,0.072043,-0.004877, + 0.052023,0.411806,0.909785,0.057965,0.072346,-0.004932, + 0.056967,0.298634,0.952666,0.058967,0.072043,-0.004877, + 0.077778,0.407727,0.909785,0.058994,0.072183,-0.004932, + 0.026063,0.41426,0.909785,0.056927,0.072444,-0.004932, + 0.019089,0.303419,0.952666,0.056918,0.072302,-0.004877, + 0.038104,0.301621,0.952666,0.057947,0.072204,-0.004877, + 0.026063,0.41426,0.909785,0.056927,0.072444,-0.004932, + 0.038104,0.301621,0.952666,0.057947,0.072204,-0.004877, + 0.052023,0.411806,0.909785,0.057965,0.072346,-0.004932, + 0,0.415079,0.909785,0.055885,0.072477,-0.004932, + 0,0.304019,0.952666,0.055885,0.072334,-0.004877, + 0.019089,0.303419,0.952666,0.056918,0.072302,-0.004877, + 0,0.415079,0.909785,0.055885,0.072477,-0.004932, + 0.019089,0.303419,0.952666,0.056918,0.072302,-0.004877, + 0.026063,0.41426,0.909785,0.056927,0.072444,-0.004932, + -0.026063,0.41426,0.909785,0.054844,0.072444,-0.004932, + -0.019089,0.303419,0.952666,0.054852,0.072302,-0.004877, + 0,0.304019,0.952666,0.055885,0.072334,-0.004877, + -0.026063,0.41426,0.909785,0.054844,0.072444,-0.004932, + 0,0.304019,0.952666,0.055885,0.072334,-0.004877, + 0,0.415079,0.909785,0.055885,0.072477,-0.004932, + -0.052023,0.411806,0.909785,0.053806,0.072346,-0.004932, + -0.038104,0.301621,0.952666,0.053824,0.072204,-0.004877, + -0.019089,0.303419,0.952666,0.054852,0.072302,-0.004877, + -0.052023,0.411806,0.909785,0.053806,0.072346,-0.004932, + -0.019089,0.303419,0.952666,0.054852,0.072302,-0.004877, + -0.026063,0.41426,0.909785,0.054844,0.072444,-0.004932, + -0.077778,0.407727,0.909785,0.052776,0.072183,-0.004932, + -0.056967,0.298634,0.952666,0.052803,0.072043,-0.004877, + -0.038104,0.301621,0.952666,0.053824,0.072204,-0.004877, + -0.077778,0.407727,0.909785,0.052776,0.072183,-0.004932, + -0.038104,0.301621,0.952666,0.053824,0.072204,-0.004877, + -0.052023,0.411806,0.909785,0.053806,0.072346,-0.004932, + -0.103226,0.402039,0.909785,0.051759,0.071956,-0.004932, + -0.075606,0.294467,0.952666,0.051795,0.071817,-0.004877, + -0.056967,0.298634,0.952666,0.052803,0.072043,-0.004877, + -0.103226,0.402039,0.909785,0.051759,0.071956,-0.004932, + -0.056967,0.298634,0.952666,0.052803,0.072043,-0.004877, + -0.077778,0.407727,0.909785,0.052776,0.072183,-0.004932, + -0.128267,0.394764,0.909785,0.050758,0.071665,-0.004932, + -0.093947,0.289139,0.952666,0.050802,0.071529,-0.004877, + -0.075606,0.294467,0.952666,0.051795,0.071817,-0.004877, + -0.128267,0.394764,0.909785,0.050758,0.071665,-0.004932, + -0.075606,0.294467,0.952666,0.051795,0.071817,-0.004877, + -0.103226,0.402039,0.909785,0.051759,0.071956,-0.004932, + -0.152801,0.385931,0.909785,0.049777,0.071312,-0.004932, + -0.111917,0.282669,0.952666,0.04983,0.071179,-0.004877, + -0.093947,0.289139,0.952666,0.050802,0.071529,-0.004877, + -0.152801,0.385931,0.909785,0.049777,0.071312,-0.004932, + -0.093947,0.289139,0.952666,0.050802,0.071529,-0.004877, + -0.128267,0.394764,0.909785,0.050758,0.071665,-0.004932, + -0.176732,0.375575,0.909785,0.048821,0.070898,-0.004932, + -0.129445,0.275084,0.952666,0.048882,0.070769,-0.004877, + -0.111917,0.282669,0.952666,0.04983,0.071179,-0.004877, + -0.176732,0.375575,0.909785,0.048821,0.070898,-0.004932, + -0.111917,0.282669,0.952666,0.04983,0.071179,-0.004877, + -0.152801,0.385931,0.909785,0.049777,0.071312,-0.004932, + -0.199966,0.363737,0.909785,0.047892,0.070425,-0.004932, + -0.146462,0.266414,0.952666,0.047961,0.070299,-0.004877, + -0.129445,0.275084,0.952666,0.048882,0.070769,-0.004877, + -0.199966,0.363737,0.909785,0.047892,0.070425,-0.004932, + -0.129445,0.275084,0.952666,0.048882,0.070769,-0.004877, + -0.176732,0.375575,0.909785,0.048821,0.070898,-0.004932, + -0.222411,0.350463,0.909785,0.046995,0.069894,-0.004932, + -0.162901,0.256692,0.952666,0.047072,0.069773,-0.004877, + -0.146462,0.266414,0.952666,0.047961,0.070299,-0.004877, + -0.222411,0.350463,0.909785,0.046995,0.069894,-0.004932, + -0.146462,0.266414,0.952666,0.047961,0.070299,-0.004877, + -0.199966,0.363737,0.909785,0.047892,0.070425,-0.004932, + -0.243978,0.335806,0.909785,0.046133,0.069308,-0.004932, + -0.178698,0.245956,0.952666,0.046217,0.069193,-0.004877, + -0.162901,0.256692,0.952666,0.047072,0.069773,-0.004877, + -0.243978,0.335806,0.909785,0.046133,0.069308,-0.004932, + -0.162901,0.256692,0.952666,0.047072,0.069773,-0.004877, + -0.222411,0.350463,0.909785,0.046995,0.069894,-0.004932, + -0.264582,0.319824,0.909785,0.045309,0.06867,-0.004932, + -0.193789,0.23425,0.952666,0.0454,0.068559,-0.004877, + -0.178698,0.245956,0.952666,0.046217,0.069193,-0.004877, + -0.264582,0.319824,0.909785,0.045309,0.06867,-0.004932, + -0.178698,0.245956,0.952666,0.046217,0.069193,-0.004877, + -0.243978,0.335806,0.909785,0.046133,0.069308,-0.004932, + -0.284141,0.30258,0.909785,0.044527,0.06798,-0.004932, + -0.208115,0.22162,0.952666,0.044625,0.067876,-0.004877, + -0.193789,0.23425,0.952666,0.0454,0.068559,-0.004877, + -0.284141,0.30258,0.909785,0.044527,0.06798,-0.004932, + -0.193789,0.23425,0.952666,0.0454,0.068559,-0.004877, + -0.264582,0.319824,0.909785,0.045309,0.06867,-0.004932, + -0.30258,0.284141,0.909785,0.04379,0.067243,-0.004932, + -0.22162,0.208115,0.952666,0.043895,0.067145,-0.004877, + -0.208115,0.22162,0.952666,0.044625,0.067876,-0.004877, + -0.30258,0.284141,0.909785,0.04379,0.067243,-0.004932, + -0.208115,0.22162,0.952666,0.044625,0.067876,-0.004877, + -0.284141,0.30258,0.909785,0.044527,0.06798,-0.004932, + -0.319824,0.264582,0.909785,0.043101,0.066461,-0.004932, + -0.23425,0.193789,0.952666,0.043211,0.06637,-0.004877, + -0.22162,0.208115,0.952666,0.043895,0.067145,-0.004877, + -0.319824,0.264582,0.909785,0.043101,0.066461,-0.004932, + -0.22162,0.208115,0.952666,0.043895,0.067145,-0.004877, + -0.30258,0.284141,0.909785,0.04379,0.067243,-0.004932, + -0.335806,0.243978,0.909785,0.042462,0.065638,-0.004932, + -0.245956,0.178698,0.952666,0.042578,0.065554,-0.004877, + -0.23425,0.193789,0.952666,0.043211,0.06637,-0.004877, + -0.335806,0.243978,0.909785,0.042462,0.065638,-0.004932, + -0.23425,0.193789,0.952666,0.043211,0.06637,-0.004877, + -0.319824,0.264582,0.909785,0.043101,0.066461,-0.004932, + -0.350463,0.222411,0.909785,0.041876,0.064776,-0.004932, + -0.256692,0.162901,0.952666,0.041997,0.064699,-0.004877, + -0.245956,0.178698,0.952666,0.042578,0.065554,-0.004877, + -0.350463,0.222411,0.909785,0.041876,0.064776,-0.004932, + -0.245956,0.178698,0.952666,0.042578,0.065554,-0.004877, + -0.335806,0.243978,0.909785,0.042462,0.065638,-0.004932, + -0.363737,0.199966,0.909785,0.041346,0.063878,-0.004932, + -0.266414,0.146462,0.952666,0.041471,0.063809,-0.004877, + -0.256692,0.162901,0.952666,0.041997,0.064699,-0.004877, + -0.363737,0.199966,0.909785,0.041346,0.063878,-0.004932, + -0.256692,0.162901,0.952666,0.041997,0.064699,-0.004877, + -0.350463,0.222411,0.909785,0.041876,0.064776,-0.004932, + -0.375575,0.176732,0.909785,0.040873,0.06295,-0.004932, + -0.275084,0.129445,0.952666,0.041002,0.062889,-0.004877, + -0.266414,0.146462,0.952666,0.041471,0.063809,-0.004877, + -0.375575,0.176732,0.909785,0.040873,0.06295,-0.004932, + -0.266414,0.146462,0.952666,0.041471,0.063809,-0.004877, + -0.363737,0.199966,0.909785,0.041346,0.063878,-0.004932, + -0.385931,0.152801,0.909785,0.040459,0.061993,-0.004932, + -0.282669,0.111917,0.952666,0.040592,0.061941,-0.004877, + -0.275084,0.129445,0.952666,0.041002,0.062889,-0.004877, + -0.385931,0.152801,0.909785,0.040459,0.061993,-0.004932, + -0.275084,0.129445,0.952666,0.041002,0.062889,-0.004877, + -0.375575,0.176732,0.909785,0.040873,0.06295,-0.004932, + -0.394764,0.128267,0.909785,0.040106,0.061012,-0.004932, + -0.289139,0.093947,0.952666,0.040242,0.060968,-0.004877, + -0.282669,0.111917,0.952666,0.040592,0.061941,-0.004877, + -0.394764,0.128267,0.909785,0.040106,0.061012,-0.004932, + -0.282669,0.111917,0.952666,0.040592,0.061941,-0.004877, + -0.385931,0.152801,0.909785,0.040459,0.061993,-0.004932, + -0.402039,0.103226,0.909785,0.039815,0.060012,-0.004932, + -0.294467,0.075606,0.952666,0.039953,0.059976,-0.004877, + -0.289139,0.093947,0.952666,0.040242,0.060968,-0.004877, + -0.402039,0.103226,0.909785,0.039815,0.060012,-0.004932, + -0.289139,0.093947,0.952666,0.040242,0.060968,-0.004877, + -0.394764,0.128267,0.909785,0.040106,0.061012,-0.004932, + -0.294467,0.075606,0.952666,0.039953,0.059976,-0.004877, + -0.182722,0.046915,0.982045,0.040097,0.059939,-0.004839, + -0.179416,0.058296,0.982045,0.040383,0.060922,-0.004839, + -0.294467,0.075606,0.952666,0.039953,0.059976,-0.004877, + -0.179416,0.058296,0.982045,0.040383,0.060922,-0.004839, + -0.289139,0.093947,0.952666,0.040242,0.060968,-0.004877, + -0.298634,0.056967,0.952666,0.039728,0.058967,-0.004877, + -0.185308,0.035349,0.982045,0.039874,0.05894,-0.004839, + -0.182722,0.046915,0.982045,0.040097,0.059939,-0.004839, + -0.298634,0.056967,0.952666,0.039728,0.058967,-0.004877, + -0.182722,0.046915,0.982045,0.040097,0.059939,-0.004839, + -0.294467,0.075606,0.952666,0.039953,0.059976,-0.004877, + -0.301621,0.038104,0.952666,0.039566,0.057947,-0.004877, + -0.187162,0.023644,0.982045,0.039714,0.057928,-0.004839, + -0.185308,0.035349,0.982045,0.039874,0.05894,-0.004839, + -0.301621,0.038104,0.952666,0.039566,0.057947,-0.004877, + -0.185308,0.035349,0.982045,0.039874,0.05894,-0.004839, + -0.298634,0.056967,0.952666,0.039728,0.058967,-0.004877, + -0.303419,0.019089,0.952666,0.039469,0.056918,-0.004877, + -0.188277,0.011845,0.982045,0.039617,0.056909,-0.004839, + -0.187162,0.023644,0.982045,0.039714,0.057928,-0.004839, + -0.303419,0.019089,0.952666,0.039469,0.056918,-0.004877, + -0.187162,0.023644,0.982045,0.039714,0.057928,-0.004839, + -0.301621,0.038104,0.952666,0.039566,0.057947,-0.004877, + -0.304019,0,0.952666,0.039437,0.055885,-0.004877, + -0.188649,0,0.982045,0.039585,0.055885,-0.004839, + -0.188277,0.011845,0.982045,0.039617,0.056909,-0.004839, + -0.304019,0,0.952666,0.039437,0.055885,-0.004877, + -0.188277,0.011845,0.982045,0.039617,0.056909,-0.004839, + -0.303419,0.019089,0.952666,0.039469,0.056918,-0.004877, + -0.303419,-0.019089,0.952666,0.039469,0.054852,-0.004877, + -0.188277,-0.011845,0.982045,0.039617,0.054862,-0.004839, + -0.188649,0,0.982045,0.039585,0.055885,-0.004839, + -0.303419,-0.019089,0.952666,0.039469,0.054852,-0.004877, + -0.188649,0,0.982045,0.039585,0.055885,-0.004839, + -0.304019,0,0.952666,0.039437,0.055885,-0.004877, + -0.301621,-0.038104,0.952666,0.039566,0.053824,-0.004877, + -0.187162,-0.023644,0.982045,0.039714,0.053842,-0.004839, + -0.188277,-0.011845,0.982045,0.039617,0.054862,-0.004839, + -0.301621,-0.038104,0.952666,0.039566,0.053824,-0.004877, + -0.188277,-0.011845,0.982045,0.039617,0.054862,-0.004839, + -0.303419,-0.019089,0.952666,0.039469,0.054852,-0.004877, + -0.298634,-0.056967,0.952666,0.039728,0.052803,-0.004877, + -0.185308,-0.035349,0.982045,0.039874,0.052831,-0.004839, + -0.187162,-0.023644,0.982045,0.039714,0.053842,-0.004839, + -0.298634,-0.056967,0.952666,0.039728,0.052803,-0.004877, + -0.187162,-0.023644,0.982045,0.039714,0.053842,-0.004839, + -0.301621,-0.038104,0.952666,0.039566,0.053824,-0.004877, + -0.294467,-0.075606,0.952666,0.039953,0.051795,-0.004877, + -0.182722,-0.046915,0.982045,0.040097,0.051832,-0.004839, + -0.185308,-0.035349,0.982045,0.039874,0.052831,-0.004839, + -0.294467,-0.075606,0.952666,0.039953,0.051795,-0.004877, + -0.185308,-0.035349,0.982045,0.039874,0.052831,-0.004839, + -0.298634,-0.056967,0.952666,0.039728,0.052803,-0.004877, + -0.289139,-0.093947,0.952666,0.040242,0.050802,-0.004877, + -0.179416,-0.058296,0.982045,0.040383,0.050848,-0.004839, + -0.182722,-0.046915,0.982045,0.040097,0.051832,-0.004839, + -0.289139,-0.093947,0.952666,0.040242,0.050802,-0.004877, + -0.182722,-0.046915,0.982045,0.040097,0.051832,-0.004839, + -0.294467,-0.075606,0.952666,0.039953,0.051795,-0.004877, + -0.282669,-0.111917,0.952666,0.040592,0.04983,-0.004877, + -0.175402,-0.069446,0.982045,0.04073,0.049885,-0.004839, + -0.179416,-0.058296,0.982045,0.040383,0.050848,-0.004839, + -0.282669,-0.111917,0.952666,0.040592,0.04983,-0.004877, + -0.179416,-0.058296,0.982045,0.040383,0.050848,-0.004839, + -0.289139,-0.093947,0.952666,0.040242,0.050802,-0.004877, + -0.275084,-0.129445,0.952666,0.041002,0.048882,-0.004877, + -0.170695,-0.080323,0.982045,0.041136,0.048945,-0.004839, + -0.175402,-0.069446,0.982045,0.04073,0.049885,-0.004839, + -0.275084,-0.129445,0.952666,0.041002,0.048882,-0.004877, + -0.175402,-0.069446,0.982045,0.04073,0.049885,-0.004839, + -0.282669,-0.111917,0.952666,0.040592,0.04983,-0.004877, + -0.266414,-0.146462,0.952666,0.041471,0.047961,-0.004877, + -0.165314,-0.090882,0.982045,0.041601,0.048033,-0.004839, + -0.170695,-0.080323,0.982045,0.041136,0.048945,-0.004839, + -0.266414,-0.146462,0.952666,0.041471,0.047961,-0.004877, + -0.170695,-0.080323,0.982045,0.041136,0.048945,-0.004839, + -0.275084,-0.129445,0.952666,0.041002,0.048882,-0.004877, + -0.256692,-0.162901,0.952666,0.041997,0.047072,-0.004877, + -0.159282,-0.101083,0.982045,0.042123,0.047151,-0.004839, + -0.165314,-0.090882,0.982045,0.041601,0.048033,-0.004839, + -0.256692,-0.162901,0.952666,0.041997,0.047072,-0.004877, + -0.165314,-0.090882,0.982045,0.041601,0.048033,-0.004839, + -0.266414,-0.146462,0.952666,0.041471,0.047961,-0.004877, + -0.245956,-0.178698,0.952666,0.042578,0.046217,-0.004877, + -0.15262,-0.110885,0.982045,0.042698,0.046304,-0.004839, + -0.159282,-0.101083,0.982045,0.042123,0.047151,-0.004839, + -0.245956,-0.178698,0.952666,0.042578,0.046217,-0.004877, + -0.159282,-0.101083,0.982045,0.042123,0.047151,-0.004839, + -0.256692,-0.162901,0.952666,0.041997,0.047072,-0.004877, + -0.23425,-0.193789,0.952666,0.043211,0.0454,-0.004877, + -0.145357,-0.120249,0.982045,0.043326,0.045495,-0.004839, + -0.15262,-0.110885,0.982045,0.042698,0.046304,-0.004839, + -0.23425,-0.193789,0.952666,0.043211,0.0454,-0.004877, + -0.15262,-0.110885,0.982045,0.042698,0.046304,-0.004839, + -0.245956,-0.178698,0.952666,0.042578,0.046217,-0.004877, + -0.22162,-0.208115,0.952666,0.043895,0.044625,-0.004877, + -0.137519,-0.129139,0.982045,0.044003,0.044727,-0.004839, + -0.145357,-0.120249,0.982045,0.043326,0.045495,-0.004839, + -0.22162,-0.208115,0.952666,0.043895,0.044625,-0.004877, + -0.145357,-0.120249,0.982045,0.043326,0.045495,-0.004839, + -0.23425,-0.193789,0.952666,0.043211,0.0454,-0.004877, + -0.208115,-0.22162,0.952666,0.044625,0.043895,-0.004877, + -0.129139,-0.137519,0.982045,0.044727,0.044003,-0.004839, + -0.137519,-0.129139,0.982045,0.044003,0.044727,-0.004839, + -0.208115,-0.22162,0.952666,0.044625,0.043895,-0.004877, + -0.137519,-0.129139,0.982045,0.044003,0.044727,-0.004839, + -0.22162,-0.208115,0.952666,0.043895,0.044625,-0.004877, + -0.193789,-0.23425,0.952666,0.0454,0.043211,-0.004877, + -0.120249,-0.145357,0.982045,0.045495,0.043326,-0.004839, + -0.129139,-0.137519,0.982045,0.044727,0.044003,-0.004839, + -0.193789,-0.23425,0.952666,0.0454,0.043211,-0.004877, + -0.129139,-0.137519,0.982045,0.044727,0.044003,-0.004839, + -0.208115,-0.22162,0.952666,0.044625,0.043895,-0.004877, + -0.178698,-0.245956,0.952666,0.046217,0.042578,-0.004877, + -0.110885,-0.15262,0.982045,0.046304,0.042698,-0.004839, + -0.120249,-0.145357,0.982045,0.045495,0.043326,-0.004839, + -0.178698,-0.245956,0.952666,0.046217,0.042578,-0.004877, + -0.120249,-0.145357,0.982045,0.045495,0.043326,-0.004839, + -0.193789,-0.23425,0.952666,0.0454,0.043211,-0.004877, + -0.162901,-0.256692,0.952666,0.047072,0.041997,-0.004877, + -0.101083,-0.159282,0.982045,0.047151,0.042123,-0.004839, + -0.110885,-0.15262,0.982045,0.046304,0.042698,-0.004839, + -0.162901,-0.256692,0.952666,0.047072,0.041997,-0.004877, + -0.110885,-0.15262,0.982045,0.046304,0.042698,-0.004839, + -0.178698,-0.245956,0.952666,0.046217,0.042578,-0.004877, + -0.146462,-0.266414,0.952666,0.047961,0.041471,-0.004877, + -0.090882,-0.165314,0.982045,0.048033,0.041601,-0.004839, + -0.101083,-0.159282,0.982045,0.047151,0.042123,-0.004839, + -0.146462,-0.266414,0.952666,0.047961,0.041471,-0.004877, + -0.101083,-0.159282,0.982045,0.047151,0.042123,-0.004839, + -0.162901,-0.256692,0.952666,0.047072,0.041997,-0.004877, + -0.129445,-0.275084,0.952666,0.048882,0.041002,-0.004877, + -0.080323,-0.170695,0.982045,0.048945,0.041136,-0.004839, + -0.090882,-0.165314,0.982045,0.048033,0.041601,-0.004839, + -0.129445,-0.275084,0.952666,0.048882,0.041002,-0.004877, + -0.090882,-0.165314,0.982045,0.048033,0.041601,-0.004839, + -0.146462,-0.266414,0.952666,0.047961,0.041471,-0.004877, + -0.111917,-0.282669,0.952666,0.04983,0.040592,-0.004877, + -0.069446,-0.175402,0.982045,0.049885,0.04073,-0.004839, + -0.080323,-0.170695,0.982045,0.048945,0.041136,-0.004839, + -0.111917,-0.282669,0.952666,0.04983,0.040592,-0.004877, + -0.080323,-0.170695,0.982045,0.048945,0.041136,-0.004839, + -0.129445,-0.275084,0.952666,0.048882,0.041002,-0.004877, + -0.093947,-0.289139,0.952666,0.050802,0.040242,-0.004877, + -0.058296,-0.179416,0.982045,0.050848,0.040383,-0.004839, + -0.069446,-0.175402,0.982045,0.049885,0.04073,-0.004839, + -0.093947,-0.289139,0.952666,0.050802,0.040242,-0.004877, + -0.069446,-0.175402,0.982045,0.049885,0.04073,-0.004839, + -0.111917,-0.282669,0.952666,0.04983,0.040592,-0.004877, + -0.075606,-0.294467,0.952666,0.051795,0.039953,-0.004877, + -0.046915,-0.182722,0.982045,0.051832,0.040097,-0.004839, + -0.058296,-0.179416,0.982045,0.050848,0.040383,-0.004839, + -0.075606,-0.294467,0.952666,0.051795,0.039953,-0.004877, + -0.058296,-0.179416,0.982045,0.050848,0.040383,-0.004839, + -0.093947,-0.289139,0.952666,0.050802,0.040242,-0.004877, + -0.056967,-0.298634,0.952666,0.052803,0.039728,-0.004877, + -0.035349,-0.185308,0.982045,0.052831,0.039874,-0.004839, + -0.046915,-0.182722,0.982045,0.051832,0.040097,-0.004839, + -0.056967,-0.298634,0.952666,0.052803,0.039728,-0.004877, + -0.046915,-0.182722,0.982045,0.051832,0.040097,-0.004839, + -0.075606,-0.294467,0.952666,0.051795,0.039953,-0.004877, + -0.038104,-0.301621,0.952666,0.053824,0.039566,-0.004877, + -0.023644,-0.187162,0.982045,0.053842,0.039714,-0.004839, + -0.035349,-0.185308,0.982045,0.052831,0.039874,-0.004839, + -0.038104,-0.301621,0.952666,0.053824,0.039566,-0.004877, + -0.035349,-0.185308,0.982045,0.052831,0.039874,-0.004839, + -0.056967,-0.298634,0.952666,0.052803,0.039728,-0.004877, + -0.019089,-0.303419,0.952666,0.054852,0.039469,-0.004877, + -0.011845,-0.188277,0.982045,0.054862,0.039617,-0.004839, + -0.023644,-0.187162,0.982045,0.053842,0.039714,-0.004839, + -0.019089,-0.303419,0.952666,0.054852,0.039469,-0.004877, + -0.023644,-0.187162,0.982045,0.053842,0.039714,-0.004839, + -0.038104,-0.301621,0.952666,0.053824,0.039566,-0.004877, + 0,-0.304019,0.952666,0.055885,0.039437,-0.004877, + 0,-0.188649,0.982045,0.055885,0.039585,-0.004839, + -0.011845,-0.188277,0.982045,0.054862,0.039617,-0.004839, + 0,-0.304019,0.952666,0.055885,0.039437,-0.004877, + -0.011845,-0.188277,0.982045,0.054862,0.039617,-0.004839, + -0.019089,-0.303419,0.952666,0.054852,0.039469,-0.004877, + 0.019089,-0.303419,0.952666,0.056918,0.039469,-0.004877, + 0.011845,-0.188277,0.982045,0.056909,0.039617,-0.004839, + 0,-0.188649,0.982045,0.055885,0.039585,-0.004839, + 0.019089,-0.303419,0.952666,0.056918,0.039469,-0.004877, + 0,-0.188649,0.982045,0.055885,0.039585,-0.004839, + 0,-0.304019,0.952666,0.055885,0.039437,-0.004877, + 0.038104,-0.301621,0.952666,0.057947,0.039566,-0.004877, + 0.023644,-0.187162,0.982045,0.057928,0.039714,-0.004839, + 0.011845,-0.188277,0.982045,0.056909,0.039617,-0.004839, + 0.038104,-0.301621,0.952666,0.057947,0.039566,-0.004877, + 0.011845,-0.188277,0.982045,0.056909,0.039617,-0.004839, + 0.019089,-0.303419,0.952666,0.056918,0.039469,-0.004877, + 0.056967,-0.298634,0.952666,0.058967,0.039728,-0.004877, + 0.035349,-0.185308,0.982045,0.05894,0.039874,-0.004839, + 0.023644,-0.187162,0.982045,0.057928,0.039714,-0.004839, + 0.056967,-0.298634,0.952666,0.058967,0.039728,-0.004877, + 0.023644,-0.187162,0.982045,0.057928,0.039714,-0.004839, + 0.038104,-0.301621,0.952666,0.057947,0.039566,-0.004877, + 0.075606,-0.294467,0.952666,0.059976,0.039953,-0.004877, + 0.046915,-0.182722,0.982045,0.059939,0.040097,-0.004839, + 0.035349,-0.185308,0.982045,0.05894,0.039874,-0.004839, + 0.075606,-0.294467,0.952666,0.059976,0.039953,-0.004877, + 0.035349,-0.185308,0.982045,0.05894,0.039874,-0.004839, + 0.056967,-0.298634,0.952666,0.058967,0.039728,-0.004877, + 0.093947,-0.289139,0.952666,0.060968,0.040242,-0.004877, + 0.058296,-0.179416,0.982045,0.060922,0.040383,-0.004839, + 0.046915,-0.182722,0.982045,0.059939,0.040097,-0.004839, + 0.093947,-0.289139,0.952666,0.060968,0.040242,-0.004877, + 0.046915,-0.182722,0.982045,0.059939,0.040097,-0.004839, + 0.075606,-0.294467,0.952666,0.059976,0.039953,-0.004877, + 0.111917,-0.282669,0.952666,0.061941,0.040592,-0.004877, + 0.069446,-0.175402,0.982045,0.061886,0.04073,-0.004839, + 0.058296,-0.179416,0.982045,0.060922,0.040383,-0.004839, + 0.111917,-0.282669,0.952666,0.061941,0.040592,-0.004877, + 0.058296,-0.179416,0.982045,0.060922,0.040383,-0.004839, + 0.093947,-0.289139,0.952666,0.060968,0.040242,-0.004877, + 0.129445,-0.275084,0.952666,0.062889,0.041002,-0.004877, + 0.080323,-0.170695,0.982045,0.062825,0.041136,-0.004839, + 0.069446,-0.175402,0.982045,0.061886,0.04073,-0.004839, + 0.129445,-0.275084,0.952666,0.062889,0.041002,-0.004877, + 0.069446,-0.175402,0.982045,0.061886,0.04073,-0.004839, + 0.111917,-0.282669,0.952666,0.061941,0.040592,-0.004877, + 0.146462,-0.266414,0.952666,0.063809,0.041471,-0.004877, + 0.090882,-0.165314,0.982045,0.063738,0.041601,-0.004839, + 0.080323,-0.170695,0.982045,0.062825,0.041136,-0.004839, + 0.146462,-0.266414,0.952666,0.063809,0.041471,-0.004877, + 0.080323,-0.170695,0.982045,0.062825,0.041136,-0.004839, + 0.129445,-0.275084,0.952666,0.062889,0.041002,-0.004877, + 0.162901,-0.256692,0.952666,0.064699,0.041997,-0.004877, + 0.101083,-0.159282,0.982045,0.064619,0.042123,-0.004839, + 0.090882,-0.165314,0.982045,0.063738,0.041601,-0.004839, + 0.162901,-0.256692,0.952666,0.064699,0.041997,-0.004877, + 0.090882,-0.165314,0.982045,0.063738,0.041601,-0.004839, + 0.146462,-0.266414,0.952666,0.063809,0.041471,-0.004877, + 0.178698,-0.245956,0.952666,0.065554,0.042578,-0.004877, + 0.110885,-0.15262,0.982045,0.065466,0.042698,-0.004839, + 0.101083,-0.159282,0.982045,0.064619,0.042123,-0.004839, + 0.178698,-0.245956,0.952666,0.065554,0.042578,-0.004877, + 0.101083,-0.159282,0.982045,0.064619,0.042123,-0.004839, + 0.162901,-0.256692,0.952666,0.064699,0.041997,-0.004877, + 0.193789,-0.23425,0.952666,0.06637,0.043211,-0.004877, + 0.120249,-0.145357,0.982045,0.066275,0.043326,-0.004839, + 0.110885,-0.15262,0.982045,0.065466,0.042698,-0.004839, + 0.193789,-0.23425,0.952666,0.06637,0.043211,-0.004877, + 0.110885,-0.15262,0.982045,0.065466,0.042698,-0.004839, + 0.178698,-0.245956,0.952666,0.065554,0.042578,-0.004877, + 0.208115,-0.22162,0.952666,0.067145,0.043895,-0.004877, + 0.129139,-0.137519,0.982045,0.067043,0.044003,-0.004839, + 0.120249,-0.145357,0.982045,0.066275,0.043326,-0.004839, + 0.208115,-0.22162,0.952666,0.067145,0.043895,-0.004877, + 0.120249,-0.145357,0.982045,0.066275,0.043326,-0.004839, + 0.193789,-0.23425,0.952666,0.06637,0.043211,-0.004877, + 0.22162,-0.208115,0.952666,0.067876,0.044625,-0.004877, + 0.137519,-0.129139,0.982045,0.067768,0.044727,-0.004839, + 0.129139,-0.137519,0.982045,0.067043,0.044003,-0.004839, + 0.22162,-0.208115,0.952666,0.067876,0.044625,-0.004877, + 0.129139,-0.137519,0.982045,0.067043,0.044003,-0.004839, + 0.208115,-0.22162,0.952666,0.067145,0.043895,-0.004877, + 0.23425,-0.193789,0.952666,0.068559,0.0454,-0.004877, + 0.145357,-0.120249,0.982045,0.068445,0.045495,-0.004839, + 0.137519,-0.129139,0.982045,0.067768,0.044727,-0.004839, + 0.23425,-0.193789,0.952666,0.068559,0.0454,-0.004877, + 0.137519,-0.129139,0.982045,0.067768,0.044727,-0.004839, + 0.22162,-0.208115,0.952666,0.067876,0.044625,-0.004877, + 0.245956,-0.178698,0.952666,0.069193,0.046217,-0.004877, + 0.15262,-0.110885,0.982045,0.069072,0.046304,-0.004839, + 0.145357,-0.120249,0.982045,0.068445,0.045495,-0.004839, + 0.245956,-0.178698,0.952666,0.069193,0.046217,-0.004877, + 0.145357,-0.120249,0.982045,0.068445,0.045495,-0.004839, + 0.23425,-0.193789,0.952666,0.068559,0.0454,-0.004877, + 0.256692,-0.162901,0.952666,0.069773,0.047072,-0.004877, + 0.159282,-0.101083,0.982045,0.069648,0.047151,-0.004839, + 0.15262,-0.110885,0.982045,0.069072,0.046304,-0.004839, + 0.256692,-0.162901,0.952666,0.069773,0.047072,-0.004877, + 0.15262,-0.110885,0.982045,0.069072,0.046304,-0.004839, + 0.245956,-0.178698,0.952666,0.069193,0.046217,-0.004877, + 0.266414,-0.146462,0.952666,0.070299,0.047961,-0.004877, + 0.165314,-0.090882,0.982045,0.070169,0.048033,-0.004839, + 0.159282,-0.101083,0.982045,0.069648,0.047151,-0.004839, + 0.266414,-0.146462,0.952666,0.070299,0.047961,-0.004877, + 0.159282,-0.101083,0.982045,0.069648,0.047151,-0.004839, + 0.256692,-0.162901,0.952666,0.069773,0.047072,-0.004877, + 0.275084,-0.129445,0.952666,0.070769,0.048882,-0.004877, + 0.170695,-0.080323,0.982045,0.070634,0.048945,-0.004839, + 0.165314,-0.090882,0.982045,0.070169,0.048033,-0.004839, + 0.275084,-0.129445,0.952666,0.070769,0.048882,-0.004877, + 0.165314,-0.090882,0.982045,0.070169,0.048033,-0.004839, + 0.266414,-0.146462,0.952666,0.070299,0.047961,-0.004877, + 0.282669,-0.111917,0.952666,0.071179,0.04983,-0.004877, + 0.175402,-0.069446,0.982045,0.071041,0.049885,-0.004839, + 0.170695,-0.080323,0.982045,0.070634,0.048945,-0.004839, + 0.282669,-0.111917,0.952666,0.071179,0.04983,-0.004877, + 0.170695,-0.080323,0.982045,0.070634,0.048945,-0.004839, + 0.275084,-0.129445,0.952666,0.070769,0.048882,-0.004877, + 0.289139,-0.093947,0.952666,0.071529,0.050802,-0.004877, + 0.179416,-0.058296,0.982045,0.071388,0.050848,-0.004839, + 0.175402,-0.069446,0.982045,0.071041,0.049885,-0.004839, + 0.289139,-0.093947,0.952666,0.071529,0.050802,-0.004877, + 0.175402,-0.069446,0.982045,0.071041,0.049885,-0.004839, + 0.282669,-0.111917,0.952666,0.071179,0.04983,-0.004877, + 0.294467,-0.075606,0.952666,0.071817,0.051795,-0.004877, + 0.182722,-0.046915,0.982045,0.071673,0.051832,-0.004839, + 0.179416,-0.058296,0.982045,0.071388,0.050848,-0.004839, + 0.294467,-0.075606,0.952666,0.071817,0.051795,-0.004877, + 0.179416,-0.058296,0.982045,0.071388,0.050848,-0.004839, + 0.289139,-0.093947,0.952666,0.071529,0.050802,-0.004877, + 0.298634,-0.056967,0.952666,0.072043,0.052803,-0.004877, + 0.185308,-0.035349,0.982045,0.071897,0.052831,-0.004839, + 0.182722,-0.046915,0.982045,0.071673,0.051832,-0.004839, + 0.298634,-0.056967,0.952666,0.072043,0.052803,-0.004877, + 0.182722,-0.046915,0.982045,0.071673,0.051832,-0.004839, + 0.294467,-0.075606,0.952666,0.071817,0.051795,-0.004877, + 0.301621,-0.038104,0.952666,0.072204,0.053824,-0.004877, + 0.187162,-0.023644,0.982045,0.072057,0.053842,-0.004839, + 0.185308,-0.035349,0.982045,0.071897,0.052831,-0.004839, + 0.301621,-0.038104,0.952666,0.072204,0.053824,-0.004877, + 0.185308,-0.035349,0.982045,0.071897,0.052831,-0.004839, + 0.298634,-0.056967,0.952666,0.072043,0.052803,-0.004877, + 0.303419,-0.019089,0.952666,0.072302,0.054852,-0.004877, + 0.188277,-0.011845,0.982045,0.072153,0.054862,-0.004839, + 0.187162,-0.023644,0.982045,0.072057,0.053842,-0.004839, + 0.303419,-0.019089,0.952666,0.072302,0.054852,-0.004877, + 0.187162,-0.023644,0.982045,0.072057,0.053842,-0.004839, + 0.301621,-0.038104,0.952666,0.072204,0.053824,-0.004877, + 0.304019,0,0.952666,0.072334,0.055885,-0.004877, + 0.188649,0,0.982045,0.072186,0.055885,-0.004839, + 0.188277,-0.011845,0.982045,0.072153,0.054862,-0.004839, + 0.304019,0,0.952666,0.072334,0.055885,-0.004877, + 0.188277,-0.011845,0.982045,0.072153,0.054862,-0.004839, + 0.303419,-0.019089,0.952666,0.072302,0.054852,-0.004877, + 0.303419,0.019089,0.952666,0.072302,0.056918,-0.004877, + 0.188277,0.011845,0.982045,0.072153,0.056909,-0.004839, + 0.188649,0,0.982045,0.072186,0.055885,-0.004839, + 0.303419,0.019089,0.952666,0.072302,0.056918,-0.004877, + 0.188649,0,0.982045,0.072186,0.055885,-0.004839, + 0.304019,0,0.952666,0.072334,0.055885,-0.004877, + 0.301621,0.038104,0.952666,0.072204,0.057947,-0.004877, + 0.187162,0.023644,0.982045,0.072057,0.057928,-0.004839, + 0.188277,0.011845,0.982045,0.072153,0.056909,-0.004839, + 0.301621,0.038104,0.952666,0.072204,0.057947,-0.004877, + 0.188277,0.011845,0.982045,0.072153,0.056909,-0.004839, + 0.303419,0.019089,0.952666,0.072302,0.056918,-0.004877, + 0.298634,0.056967,0.952666,0.072043,0.058967,-0.004877, + 0.185308,0.035349,0.982045,0.071897,0.05894,-0.004839, + 0.187162,0.023644,0.982045,0.072057,0.057928,-0.004839, + 0.298634,0.056967,0.952666,0.072043,0.058967,-0.004877, + 0.187162,0.023644,0.982045,0.072057,0.057928,-0.004839, + 0.301621,0.038104,0.952666,0.072204,0.057947,-0.004877, + 0.294467,0.075606,0.952666,0.071817,0.059976,-0.004877, + 0.182722,0.046915,0.982045,0.071673,0.059939,-0.004839, + 0.185308,0.035349,0.982045,0.071897,0.05894,-0.004839, + 0.294467,0.075606,0.952666,0.071817,0.059976,-0.004877, + 0.185308,0.035349,0.982045,0.071897,0.05894,-0.004839, + 0.298634,0.056967,0.952666,0.072043,0.058967,-0.004877, + 0.289139,0.093947,0.952666,0.071529,0.060968,-0.004877, + 0.179416,0.058296,0.982045,0.071388,0.060922,-0.004839, + 0.182722,0.046915,0.982045,0.071673,0.059939,-0.004839, + 0.289139,0.093947,0.952666,0.071529,0.060968,-0.004877, + 0.182722,0.046915,0.982045,0.071673,0.059939,-0.004839, + 0.294467,0.075606,0.952666,0.071817,0.059976,-0.004877, + 0.282669,0.111917,0.952666,0.071179,0.061941,-0.004877, + 0.175402,0.069446,0.982045,0.071041,0.061886,-0.004839, + 0.179416,0.058296,0.982045,0.071388,0.060922,-0.004839, + 0.282669,0.111917,0.952666,0.071179,0.061941,-0.004877, + 0.179416,0.058296,0.982045,0.071388,0.060922,-0.004839, + 0.289139,0.093947,0.952666,0.071529,0.060968,-0.004877, + 0.275084,0.129445,0.952666,0.070769,0.062889,-0.004877, + 0.170695,0.080323,0.982045,0.070634,0.062825,-0.004839, + 0.175402,0.069446,0.982045,0.071041,0.061886,-0.004839, + 0.275084,0.129445,0.952666,0.070769,0.062889,-0.004877, + 0.175402,0.069446,0.982045,0.071041,0.061886,-0.004839, + 0.282669,0.111917,0.952666,0.071179,0.061941,-0.004877, + 0.266414,0.146462,0.952666,0.070299,0.063809,-0.004877, + 0.165314,0.090882,0.982045,0.070169,0.063738,-0.004839, + 0.170695,0.080323,0.982045,0.070634,0.062825,-0.004839, + 0.266414,0.146462,0.952666,0.070299,0.063809,-0.004877, + 0.170695,0.080323,0.982045,0.070634,0.062825,-0.004839, + 0.275084,0.129445,0.952666,0.070769,0.062889,-0.004877, + 0.256692,0.162901,0.952666,0.069773,0.064699,-0.004877, + 0.159282,0.101083,0.982045,0.069648,0.064619,-0.004839, + 0.165314,0.090882,0.982045,0.070169,0.063738,-0.004839, + 0.256692,0.162901,0.952666,0.069773,0.064699,-0.004877, + 0.165314,0.090882,0.982045,0.070169,0.063738,-0.004839, + 0.266414,0.146462,0.952666,0.070299,0.063809,-0.004877, + 0.245956,0.178698,0.952666,0.069193,0.065554,-0.004877, + 0.15262,0.110885,0.982045,0.069072,0.065466,-0.004839, + 0.159282,0.101083,0.982045,0.069648,0.064619,-0.004839, + 0.245956,0.178698,0.952666,0.069193,0.065554,-0.004877, + 0.159282,0.101083,0.982045,0.069648,0.064619,-0.004839, + 0.256692,0.162901,0.952666,0.069773,0.064699,-0.004877, + 0.23425,0.193789,0.952666,0.068559,0.06637,-0.004877, + 0.145357,0.120249,0.982045,0.068445,0.066275,-0.004839, + 0.15262,0.110885,0.982045,0.069072,0.065466,-0.004839, + 0.23425,0.193789,0.952666,0.068559,0.06637,-0.004877, + 0.15262,0.110885,0.982045,0.069072,0.065466,-0.004839, + 0.245956,0.178698,0.952666,0.069193,0.065554,-0.004877, + 0.22162,0.208115,0.952666,0.067876,0.067145,-0.004877, + 0.137519,0.129139,0.982045,0.067768,0.067043,-0.004839, + 0.145357,0.120249,0.982045,0.068445,0.066275,-0.004839, + 0.22162,0.208115,0.952666,0.067876,0.067145,-0.004877, + 0.145357,0.120249,0.982045,0.068445,0.066275,-0.004839, + 0.23425,0.193789,0.952666,0.068559,0.06637,-0.004877, + 0.208115,0.22162,0.952666,0.067145,0.067876,-0.004877, + 0.129139,0.137519,0.982045,0.067043,0.067768,-0.004839, + 0.137519,0.129139,0.982045,0.067768,0.067043,-0.004839, + 0.208115,0.22162,0.952666,0.067145,0.067876,-0.004877, + 0.137519,0.129139,0.982045,0.067768,0.067043,-0.004839, + 0.22162,0.208115,0.952666,0.067876,0.067145,-0.004877, + 0.193789,0.23425,0.952666,0.06637,0.068559,-0.004877, + 0.120249,0.145357,0.982045,0.066275,0.068445,-0.004839, + 0.129139,0.137519,0.982045,0.067043,0.067768,-0.004839, + 0.193789,0.23425,0.952666,0.06637,0.068559,-0.004877, + 0.129139,0.137519,0.982045,0.067043,0.067768,-0.004839, + 0.208115,0.22162,0.952666,0.067145,0.067876,-0.004877, + 0.178698,0.245956,0.952666,0.065554,0.069193,-0.004877, + 0.110885,0.15262,0.982045,0.065466,0.069072,-0.004839, + 0.120249,0.145357,0.982045,0.066275,0.068445,-0.004839, + 0.178698,0.245956,0.952666,0.065554,0.069193,-0.004877, + 0.120249,0.145357,0.982045,0.066275,0.068445,-0.004839, + 0.193789,0.23425,0.952666,0.06637,0.068559,-0.004877, + 0.162901,0.256692,0.952666,0.064699,0.069773,-0.004877, + 0.101083,0.159282,0.982045,0.064619,0.069648,-0.004839, + 0.110885,0.15262,0.982045,0.065466,0.069072,-0.004839, + 0.162901,0.256692,0.952666,0.064699,0.069773,-0.004877, + 0.110885,0.15262,0.982045,0.065466,0.069072,-0.004839, + 0.178698,0.245956,0.952666,0.065554,0.069193,-0.004877, + 0.146462,0.266414,0.952666,0.063809,0.070299,-0.004877, + 0.090882,0.165314,0.982045,0.063738,0.070169,-0.004839, + 0.101083,0.159282,0.982045,0.064619,0.069648,-0.004839, + 0.146462,0.266414,0.952666,0.063809,0.070299,-0.004877, + 0.101083,0.159282,0.982045,0.064619,0.069648,-0.004839, + 0.162901,0.256692,0.952666,0.064699,0.069773,-0.004877, + 0.129445,0.275084,0.952666,0.062889,0.070769,-0.004877, + 0.080323,0.170695,0.982045,0.062825,0.070634,-0.004839, + 0.090882,0.165314,0.982045,0.063738,0.070169,-0.004839, + 0.129445,0.275084,0.952666,0.062889,0.070769,-0.004877, + 0.090882,0.165314,0.982045,0.063738,0.070169,-0.004839, + 0.146462,0.266414,0.952666,0.063809,0.070299,-0.004877, + 0.111917,0.282669,0.952666,0.061941,0.071179,-0.004877, + 0.069446,0.175402,0.982045,0.061886,0.071041,-0.004839, + 0.080323,0.170695,0.982045,0.062825,0.070634,-0.004839, + 0.111917,0.282669,0.952666,0.061941,0.071179,-0.004877, + 0.080323,0.170695,0.982045,0.062825,0.070634,-0.004839, + 0.129445,0.275084,0.952666,0.062889,0.070769,-0.004877, + 0.093947,0.289139,0.952666,0.060968,0.071529,-0.004877, + 0.058296,0.179416,0.982045,0.060922,0.071388,-0.004839, + 0.069446,0.175402,0.982045,0.061886,0.071041,-0.004839, + 0.093947,0.289139,0.952666,0.060968,0.071529,-0.004877, + 0.069446,0.175402,0.982045,0.061886,0.071041,-0.004839, + 0.111917,0.282669,0.952666,0.061941,0.071179,-0.004877, + 0.075606,0.294467,0.952666,0.059976,0.071817,-0.004877, + 0.046915,0.182722,0.982045,0.059939,0.071673,-0.004839, + 0.058296,0.179416,0.982045,0.060922,0.071388,-0.004839, + 0.075606,0.294467,0.952666,0.059976,0.071817,-0.004877, + 0.058296,0.179416,0.982045,0.060922,0.071388,-0.004839, + 0.093947,0.289139,0.952666,0.060968,0.071529,-0.004877, + 0.056967,0.298634,0.952666,0.058967,0.072043,-0.004877, + 0.035349,0.185308,0.982045,0.05894,0.071897,-0.004839, + 0.046915,0.182722,0.982045,0.059939,0.071673,-0.004839, + 0.056967,0.298634,0.952666,0.058967,0.072043,-0.004877, + 0.046915,0.182722,0.982045,0.059939,0.071673,-0.004839, + 0.075606,0.294467,0.952666,0.059976,0.071817,-0.004877, + 0.038104,0.301621,0.952666,0.057947,0.072204,-0.004877, + 0.023644,0.187162,0.982045,0.057928,0.072057,-0.004839, + 0.035349,0.185308,0.982045,0.05894,0.071897,-0.004839, + 0.038104,0.301621,0.952666,0.057947,0.072204,-0.004877, + 0.035349,0.185308,0.982045,0.05894,0.071897,-0.004839, + 0.056967,0.298634,0.952666,0.058967,0.072043,-0.004877, + 0.019089,0.303419,0.952666,0.056918,0.072302,-0.004877, + 0.011845,0.188277,0.982045,0.056909,0.072153,-0.004839, + 0.023644,0.187162,0.982045,0.057928,0.072057,-0.004839, + 0.019089,0.303419,0.952666,0.056918,0.072302,-0.004877, + 0.023644,0.187162,0.982045,0.057928,0.072057,-0.004839, + 0.038104,0.301621,0.952666,0.057947,0.072204,-0.004877, + 0,0.304019,0.952666,0.055885,0.072334,-0.004877, + 0,0.188649,0.982045,0.055885,0.072186,-0.004839, + 0.011845,0.188277,0.982045,0.056909,0.072153,-0.004839, + 0,0.304019,0.952666,0.055885,0.072334,-0.004877, + 0.011845,0.188277,0.982045,0.056909,0.072153,-0.004839, + 0.019089,0.303419,0.952666,0.056918,0.072302,-0.004877, + -0.019089,0.303419,0.952666,0.054852,0.072302,-0.004877, + -0.011845,0.188277,0.982045,0.054862,0.072153,-0.004839, + 0,0.188649,0.982045,0.055885,0.072186,-0.004839, + -0.019089,0.303419,0.952666,0.054852,0.072302,-0.004877, + 0,0.188649,0.982045,0.055885,0.072186,-0.004839, + 0,0.304019,0.952666,0.055885,0.072334,-0.004877, + -0.038104,0.301621,0.952666,0.053824,0.072204,-0.004877, + -0.023644,0.187162,0.982045,0.053842,0.072057,-0.004839, + -0.011845,0.188277,0.982045,0.054862,0.072153,-0.004839, + -0.038104,0.301621,0.952666,0.053824,0.072204,-0.004877, + -0.011845,0.188277,0.982045,0.054862,0.072153,-0.004839, + -0.019089,0.303419,0.952666,0.054852,0.072302,-0.004877, + -0.056967,0.298634,0.952666,0.052803,0.072043,-0.004877, + -0.035349,0.185308,0.982045,0.052831,0.071897,-0.004839, + -0.023644,0.187162,0.982045,0.053842,0.072057,-0.004839, + -0.056967,0.298634,0.952666,0.052803,0.072043,-0.004877, + -0.023644,0.187162,0.982045,0.053842,0.072057,-0.004839, + -0.038104,0.301621,0.952666,0.053824,0.072204,-0.004877, + -0.075606,0.294467,0.952666,0.051795,0.071817,-0.004877, + -0.046915,0.182722,0.982045,0.051832,0.071673,-0.004839, + -0.035349,0.185308,0.982045,0.052831,0.071897,-0.004839, + -0.075606,0.294467,0.952666,0.051795,0.071817,-0.004877, + -0.035349,0.185308,0.982045,0.052831,0.071897,-0.004839, + -0.056967,0.298634,0.952666,0.052803,0.072043,-0.004877, + -0.093947,0.289139,0.952666,0.050802,0.071529,-0.004877, + -0.058296,0.179416,0.982045,0.050848,0.071388,-0.004839, + -0.046915,0.182722,0.982045,0.051832,0.071673,-0.004839, + -0.093947,0.289139,0.952666,0.050802,0.071529,-0.004877, + -0.046915,0.182722,0.982045,0.051832,0.071673,-0.004839, + -0.075606,0.294467,0.952666,0.051795,0.071817,-0.004877, + -0.111917,0.282669,0.952666,0.04983,0.071179,-0.004877, + -0.069446,0.175402,0.982045,0.049885,0.071041,-0.004839, + -0.058296,0.179416,0.982045,0.050848,0.071388,-0.004839, + -0.111917,0.282669,0.952666,0.04983,0.071179,-0.004877, + -0.058296,0.179416,0.982045,0.050848,0.071388,-0.004839, + -0.093947,0.289139,0.952666,0.050802,0.071529,-0.004877, + -0.129445,0.275084,0.952666,0.048882,0.070769,-0.004877, + -0.080323,0.170695,0.982045,0.048945,0.070634,-0.004839, + -0.069446,0.175402,0.982045,0.049885,0.071041,-0.004839, + -0.129445,0.275084,0.952666,0.048882,0.070769,-0.004877, + -0.069446,0.175402,0.982045,0.049885,0.071041,-0.004839, + -0.111917,0.282669,0.952666,0.04983,0.071179,-0.004877, + -0.146462,0.266414,0.952666,0.047961,0.070299,-0.004877, + -0.090882,0.165314,0.982045,0.048033,0.070169,-0.004839, + -0.080323,0.170695,0.982045,0.048945,0.070634,-0.004839, + -0.146462,0.266414,0.952666,0.047961,0.070299,-0.004877, + -0.080323,0.170695,0.982045,0.048945,0.070634,-0.004839, + -0.129445,0.275084,0.952666,0.048882,0.070769,-0.004877, + -0.162901,0.256692,0.952666,0.047072,0.069773,-0.004877, + -0.101083,0.159282,0.982045,0.047151,0.069648,-0.004839, + -0.090882,0.165314,0.982045,0.048033,0.070169,-0.004839, + -0.162901,0.256692,0.952666,0.047072,0.069773,-0.004877, + -0.090882,0.165314,0.982045,0.048033,0.070169,-0.004839, + -0.146462,0.266414,0.952666,0.047961,0.070299,-0.004877, + -0.178698,0.245956,0.952666,0.046217,0.069193,-0.004877, + -0.110885,0.15262,0.982045,0.046304,0.069072,-0.004839, + -0.101083,0.159282,0.982045,0.047151,0.069648,-0.004839, + -0.178698,0.245956,0.952666,0.046217,0.069193,-0.004877, + -0.101083,0.159282,0.982045,0.047151,0.069648,-0.004839, + -0.162901,0.256692,0.952666,0.047072,0.069773,-0.004877, + -0.193789,0.23425,0.952666,0.0454,0.068559,-0.004877, + -0.120249,0.145357,0.982045,0.045495,0.068445,-0.004839, + -0.110885,0.15262,0.982045,0.046304,0.069072,-0.004839, + -0.193789,0.23425,0.952666,0.0454,0.068559,-0.004877, + -0.110885,0.15262,0.982045,0.046304,0.069072,-0.004839, + -0.178698,0.245956,0.952666,0.046217,0.069193,-0.004877, + -0.208115,0.22162,0.952666,0.044625,0.067876,-0.004877, + -0.129139,0.137519,0.982045,0.044727,0.067768,-0.004839, + -0.120249,0.145357,0.982045,0.045495,0.068445,-0.004839, + -0.208115,0.22162,0.952666,0.044625,0.067876,-0.004877, + -0.120249,0.145357,0.982045,0.045495,0.068445,-0.004839, + -0.193789,0.23425,0.952666,0.0454,0.068559,-0.004877, + -0.22162,0.208115,0.952666,0.043895,0.067145,-0.004877, + -0.137519,0.129139,0.982045,0.044003,0.067043,-0.004839, + -0.129139,0.137519,0.982045,0.044727,0.067768,-0.004839, + -0.22162,0.208115,0.952666,0.043895,0.067145,-0.004877, + -0.129139,0.137519,0.982045,0.044727,0.067768,-0.004839, + -0.208115,0.22162,0.952666,0.044625,0.067876,-0.004877, + -0.23425,0.193789,0.952666,0.043211,0.06637,-0.004877, + -0.145357,0.120249,0.982045,0.043326,0.066275,-0.004839, + -0.137519,0.129139,0.982045,0.044003,0.067043,-0.004839, + -0.23425,0.193789,0.952666,0.043211,0.06637,-0.004877, + -0.137519,0.129139,0.982045,0.044003,0.067043,-0.004839, + -0.22162,0.208115,0.952666,0.043895,0.067145,-0.004877, + -0.245956,0.178698,0.952666,0.042578,0.065554,-0.004877, + -0.15262,0.110885,0.982045,0.042698,0.065466,-0.004839, + -0.145357,0.120249,0.982045,0.043326,0.066275,-0.004839, + -0.245956,0.178698,0.952666,0.042578,0.065554,-0.004877, + -0.145357,0.120249,0.982045,0.043326,0.066275,-0.004839, + -0.23425,0.193789,0.952666,0.043211,0.06637,-0.004877, + -0.256692,0.162901,0.952666,0.041997,0.064699,-0.004877, + -0.159282,0.101083,0.982045,0.042123,0.064619,-0.004839, + -0.15262,0.110885,0.982045,0.042698,0.065466,-0.004839, + -0.256692,0.162901,0.952666,0.041997,0.064699,-0.004877, + -0.15262,0.110885,0.982045,0.042698,0.065466,-0.004839, + -0.245956,0.178698,0.952666,0.042578,0.065554,-0.004877, + -0.266414,0.146462,0.952666,0.041471,0.063809,-0.004877, + -0.165314,0.090882,0.982045,0.041601,0.063738,-0.004839, + -0.159282,0.101083,0.982045,0.042123,0.064619,-0.004839, + -0.266414,0.146462,0.952666,0.041471,0.063809,-0.004877, + -0.159282,0.101083,0.982045,0.042123,0.064619,-0.004839, + -0.256692,0.162901,0.952666,0.041997,0.064699,-0.004877, + -0.275084,0.129445,0.952666,0.041002,0.062889,-0.004877, + -0.170695,0.080323,0.982045,0.041136,0.062825,-0.004839, + -0.165314,0.090882,0.982045,0.041601,0.063738,-0.004839, + -0.275084,0.129445,0.952666,0.041002,0.062889,-0.004877, + -0.165314,0.090882,0.982045,0.041601,0.063738,-0.004839, + -0.266414,0.146462,0.952666,0.041471,0.063809,-0.004877, + -0.282669,0.111917,0.952666,0.040592,0.061941,-0.004877, + -0.175402,0.069446,0.982045,0.04073,0.061886,-0.004839, + -0.170695,0.080323,0.982045,0.041136,0.062825,-0.004839, + -0.282669,0.111917,0.952666,0.040592,0.061941,-0.004877, + -0.170695,0.080323,0.982045,0.041136,0.062825,-0.004839, + -0.275084,0.129445,0.952666,0.041002,0.062889,-0.004877, + -0.289139,0.093947,0.952666,0.040242,0.060968,-0.004877, + -0.179416,0.058296,0.982045,0.040383,0.060922,-0.004839, + -0.175402,0.069446,0.982045,0.04073,0.061886,-0.004839, + -0.289139,0.093947,0.952666,0.040242,0.060968,-0.004877, + -0.175402,0.069446,0.982045,0.04073,0.061886,-0.004839, + -0.282669,0.111917,0.952666,0.040592,0.061941,-0.004877, + -0.179416,0.058296,0.982045,0.040383,0.060922,-0.004839, + -0.06715,0.021818,0.997504,0.040528,0.060875,-0.004819, + -0.065648,0.025992,0.997504,0.040871,0.06183,-0.004819, + -0.179416,0.058296,0.982045,0.040383,0.060922,-0.004839, + -0.065648,0.025992,0.997504,0.040871,0.06183,-0.004819, + -0.175402,0.069446,0.982045,0.04073,0.061886,-0.004839, + -0.182722,0.046915,0.982045,0.040097,0.059939,-0.004839, + -0.068388,0.017559,0.997504,0.040245,0.059901,-0.004819, + -0.06715,0.021818,0.997504,0.040528,0.060875,-0.004819, + -0.182722,0.046915,0.982045,0.040097,0.059939,-0.004839, + -0.06715,0.021818,0.997504,0.040528,0.060875,-0.004819, + -0.179416,0.058296,0.982045,0.040383,0.060922,-0.004839, + -0.185308,0.035349,0.982045,0.039874,0.05894,-0.004839, + -0.069355,0.01323,0.997504,0.040023,0.058911,-0.004819, + -0.068388,0.017559,0.997504,0.040245,0.059901,-0.004819, + -0.185308,0.035349,0.982045,0.039874,0.05894,-0.004839, + -0.068388,0.017559,0.997504,0.040245,0.059901,-0.004819, + -0.182722,0.046915,0.982045,0.040097,0.059939,-0.004839, + -0.187162,0.023644,0.982045,0.039714,0.057928,-0.004839, + -0.070049,0.008849,0.997504,0.039865,0.057909,-0.004819, + -0.069355,0.01323,0.997504,0.040023,0.058911,-0.004819, + -0.187162,0.023644,0.982045,0.039714,0.057928,-0.004839, + -0.069355,0.01323,0.997504,0.040023,0.058911,-0.004819, + -0.185308,0.035349,0.982045,0.039874,0.05894,-0.004839, + -0.188277,0.011845,0.982045,0.039617,0.056909,-0.004839, + -0.070467,0.004433,0.997504,0.039769,0.056899,-0.004819, + -0.070049,0.008849,0.997504,0.039865,0.057909,-0.004819, + -0.188277,0.011845,0.982045,0.039617,0.056909,-0.004839, + -0.070049,0.008849,0.997504,0.039865,0.057909,-0.004819, + -0.187162,0.023644,0.982045,0.039714,0.057928,-0.004839, + -0.188649,0,0.982045,0.039585,0.055885,-0.004839, + -0.070606,0,0.997504,0.039737,0.055885,-0.004819, + -0.070467,0.004433,0.997504,0.039769,0.056899,-0.004819, + -0.188649,0,0.982045,0.039585,0.055885,-0.004839, + -0.070467,0.004433,0.997504,0.039769,0.056899,-0.004819, + -0.188277,0.011845,0.982045,0.039617,0.056909,-0.004839, + -0.188277,-0.011845,0.982045,0.039617,0.054862,-0.004839, + -0.070467,-0.004433,0.997504,0.039769,0.054871,-0.004819, + -0.070606,0,0.997504,0.039737,0.055885,-0.004819, + -0.188277,-0.011845,0.982045,0.039617,0.054862,-0.004839, + -0.070606,0,0.997504,0.039737,0.055885,-0.004819, + -0.188649,0,0.982045,0.039585,0.055885,-0.004839, + -0.187162,-0.023644,0.982045,0.039714,0.053842,-0.004839, + -0.070049,-0.008849,0.997504,0.039865,0.053861,-0.004819, + -0.070467,-0.004433,0.997504,0.039769,0.054871,-0.004819, + -0.187162,-0.023644,0.982045,0.039714,0.053842,-0.004839, + -0.070467,-0.004433,0.997504,0.039769,0.054871,-0.004819, + -0.188277,-0.011845,0.982045,0.039617,0.054862,-0.004839, + -0.185308,-0.035349,0.982045,0.039874,0.052831,-0.004839, + -0.069355,-0.01323,0.997504,0.040023,0.052859,-0.004819, + -0.070049,-0.008849,0.997504,0.039865,0.053861,-0.004819, + -0.185308,-0.035349,0.982045,0.039874,0.052831,-0.004839, + -0.070049,-0.008849,0.997504,0.039865,0.053861,-0.004819, + -0.187162,-0.023644,0.982045,0.039714,0.053842,-0.004839, + -0.182722,-0.046915,0.982045,0.040097,0.051832,-0.004839, + -0.068388,-0.017559,0.997504,0.040245,0.051869,-0.004819, + -0.069355,-0.01323,0.997504,0.040023,0.052859,-0.004819, + -0.182722,-0.046915,0.982045,0.040097,0.051832,-0.004839, + -0.069355,-0.01323,0.997504,0.040023,0.052859,-0.004819, + -0.185308,-0.035349,0.982045,0.039874,0.052831,-0.004839, + -0.179416,-0.058296,0.982045,0.040383,0.050848,-0.004839, + -0.06715,-0.021818,0.997504,0.040528,0.050895,-0.004819, + -0.068388,-0.017559,0.997504,0.040245,0.051869,-0.004819, + -0.179416,-0.058296,0.982045,0.040383,0.050848,-0.004839, + -0.068388,-0.017559,0.997504,0.040245,0.051869,-0.004819, + -0.182722,-0.046915,0.982045,0.040097,0.051832,-0.004839, + -0.175402,-0.069446,0.982045,0.04073,0.049885,-0.004839, + -0.065648,-0.025992,0.997504,0.040871,0.049941,-0.004819, + -0.06715,-0.021818,0.997504,0.040528,0.050895,-0.004819, + -0.175402,-0.069446,0.982045,0.04073,0.049885,-0.004839, + -0.06715,-0.021818,0.997504,0.040528,0.050895,-0.004819, + -0.179416,-0.058296,0.982045,0.040383,0.050848,-0.004839, + -0.170695,-0.080323,0.982045,0.041136,0.048945,-0.004839, + -0.063886,-0.030062,0.997504,0.041274,0.04901,-0.004819, + -0.065648,-0.025992,0.997504,0.040871,0.049941,-0.004819, + -0.170695,-0.080323,0.982045,0.041136,0.048945,-0.004839, + -0.065648,-0.025992,0.997504,0.040871,0.049941,-0.004819, + -0.175402,-0.069446,0.982045,0.04073,0.049885,-0.004839, + -0.165314,-0.090882,0.982045,0.041601,0.048033,-0.004839, + -0.061872,-0.034015,0.997504,0.041735,0.048106,-0.004819, + -0.063886,-0.030062,0.997504,0.041274,0.04901,-0.004819, + -0.165314,-0.090882,0.982045,0.041601,0.048033,-0.004839, + -0.063886,-0.030062,0.997504,0.041274,0.04901,-0.004819, + -0.170695,-0.080323,0.982045,0.041136,0.048945,-0.004839, + -0.159282,-0.101083,0.982045,0.042123,0.047151,-0.004839, + -0.059614,-0.037832,0.997504,0.042251,0.047233,-0.004819, + -0.061872,-0.034015,0.997504,0.041735,0.048106,-0.004819, + -0.159282,-0.101083,0.982045,0.042123,0.047151,-0.004839, + -0.061872,-0.034015,0.997504,0.041735,0.048106,-0.004819, + -0.165314,-0.090882,0.982045,0.041601,0.048033,-0.004839, + -0.15262,-0.110885,0.982045,0.042698,0.046304,-0.004839, + -0.057121,-0.041501,0.997504,0.042821,0.046394,-0.004819, + -0.059614,-0.037832,0.997504,0.042251,0.047233,-0.004819, + -0.15262,-0.110885,0.982045,0.042698,0.046304,-0.004839, + -0.059614,-0.037832,0.997504,0.042251,0.047233,-0.004819, + -0.159282,-0.101083,0.982045,0.042123,0.047151,-0.004839, + -0.145357,-0.120249,0.982045,0.043326,0.045495,-0.004839, + -0.054403,-0.045006,0.997504,0.043443,0.045592,-0.004819, + -0.057121,-0.041501,0.997504,0.042821,0.046394,-0.004819, + -0.145357,-0.120249,0.982045,0.043326,0.045495,-0.004839, + -0.057121,-0.041501,0.997504,0.042821,0.046394,-0.004819, + -0.15262,-0.110885,0.982045,0.042698,0.046304,-0.004839, + -0.137519,-0.129139,0.982045,0.044003,0.044727,-0.004839, + -0.051469,-0.048333,0.997504,0.044114,0.044831,-0.004819, + -0.054403,-0.045006,0.997504,0.043443,0.045592,-0.004819, + -0.137519,-0.129139,0.982045,0.044003,0.044727,-0.004839, + -0.054403,-0.045006,0.997504,0.043443,0.045592,-0.004819, + -0.145357,-0.120249,0.982045,0.043326,0.045495,-0.004839, + -0.129139,-0.137519,0.982045,0.044727,0.044003,-0.004839, + -0.048333,-0.051469,0.997504,0.044831,0.044114,-0.004819, + -0.051469,-0.048333,0.997504,0.044114,0.044831,-0.004819, + -0.129139,-0.137519,0.982045,0.044727,0.044003,-0.004839, + -0.051469,-0.048333,0.997504,0.044114,0.044831,-0.004819, + -0.137519,-0.129139,0.982045,0.044003,0.044727,-0.004839, + -0.120249,-0.145357,0.982045,0.045495,0.043326,-0.004839, + -0.045006,-0.054403,0.997504,0.045592,0.043443,-0.004819, + -0.048333,-0.051469,0.997504,0.044831,0.044114,-0.004819, + -0.120249,-0.145357,0.982045,0.045495,0.043326,-0.004839, + -0.048333,-0.051469,0.997504,0.044831,0.044114,-0.004819, + -0.129139,-0.137519,0.982045,0.044727,0.044003,-0.004839, + -0.110885,-0.15262,0.982045,0.046304,0.042698,-0.004839, + -0.041501,-0.057121,0.997504,0.046394,0.042821,-0.004819, + -0.045006,-0.054403,0.997504,0.045592,0.043443,-0.004819, + -0.110885,-0.15262,0.982045,0.046304,0.042698,-0.004839, + -0.045006,-0.054403,0.997504,0.045592,0.043443,-0.004819, + -0.120249,-0.145357,0.982045,0.045495,0.043326,-0.004839, + -0.101083,-0.159282,0.982045,0.047151,0.042123,-0.004839, + -0.037832,-0.059614,0.997504,0.047233,0.042251,-0.004819, + -0.041501,-0.057121,0.997504,0.046394,0.042821,-0.004819, + -0.101083,-0.159282,0.982045,0.047151,0.042123,-0.004839, + -0.041501,-0.057121,0.997504,0.046394,0.042821,-0.004819, + -0.110885,-0.15262,0.982045,0.046304,0.042698,-0.004839, + -0.090882,-0.165314,0.982045,0.048033,0.041601,-0.004839, + -0.034015,-0.061872,0.997504,0.048106,0.041735,-0.004819, + -0.037832,-0.059614,0.997504,0.047233,0.042251,-0.004819, + -0.090882,-0.165314,0.982045,0.048033,0.041601,-0.004839, + -0.037832,-0.059614,0.997504,0.047233,0.042251,-0.004819, + -0.101083,-0.159282,0.982045,0.047151,0.042123,-0.004839, + -0.080323,-0.170695,0.982045,0.048945,0.041136,-0.004839, + -0.030062,-0.063886,0.997504,0.04901,0.041274,-0.004819, + -0.034015,-0.061872,0.997504,0.048106,0.041735,-0.004819, + -0.080323,-0.170695,0.982045,0.048945,0.041136,-0.004839, + -0.034015,-0.061872,0.997504,0.048106,0.041735,-0.004819, + -0.090882,-0.165314,0.982045,0.048033,0.041601,-0.004839, + -0.069446,-0.175402,0.982045,0.049885,0.04073,-0.004839, + -0.025992,-0.065648,0.997504,0.049941,0.040871,-0.004819, + -0.030062,-0.063886,0.997504,0.04901,0.041274,-0.004819, + -0.069446,-0.175402,0.982045,0.049885,0.04073,-0.004839, + -0.030062,-0.063886,0.997504,0.04901,0.041274,-0.004819, + -0.080323,-0.170695,0.982045,0.048945,0.041136,-0.004839, + -0.058296,-0.179416,0.982045,0.050848,0.040383,-0.004839, + -0.021818,-0.06715,0.997504,0.050895,0.040528,-0.004819, + -0.025992,-0.065648,0.997504,0.049941,0.040871,-0.004819, + -0.058296,-0.179416,0.982045,0.050848,0.040383,-0.004839, + -0.025992,-0.065648,0.997504,0.049941,0.040871,-0.004819, + -0.069446,-0.175402,0.982045,0.049885,0.04073,-0.004839, + -0.046915,-0.182722,0.982045,0.051832,0.040097,-0.004839, + -0.017559,-0.068388,0.997504,0.051869,0.040245,-0.004819, + -0.021818,-0.06715,0.997504,0.050895,0.040528,-0.004819, + -0.046915,-0.182722,0.982045,0.051832,0.040097,-0.004839, + -0.021818,-0.06715,0.997504,0.050895,0.040528,-0.004819, + -0.058296,-0.179416,0.982045,0.050848,0.040383,-0.004839, + -0.035349,-0.185308,0.982045,0.052831,0.039874,-0.004839, + -0.01323,-0.069355,0.997504,0.052859,0.040023,-0.004819, + -0.017559,-0.068388,0.997504,0.051869,0.040245,-0.004819, + -0.035349,-0.185308,0.982045,0.052831,0.039874,-0.004839, + -0.017559,-0.068388,0.997504,0.051869,0.040245,-0.004819, + -0.046915,-0.182722,0.982045,0.051832,0.040097,-0.004839, + -0.023644,-0.187162,0.982045,0.053842,0.039714,-0.004839, + -0.008849,-0.070049,0.997504,0.053861,0.039865,-0.004819, + -0.01323,-0.069355,0.997504,0.052859,0.040023,-0.004819, + -0.023644,-0.187162,0.982045,0.053842,0.039714,-0.004839, + -0.01323,-0.069355,0.997504,0.052859,0.040023,-0.004819, + -0.035349,-0.185308,0.982045,0.052831,0.039874,-0.004839, + -0.011845,-0.188277,0.982045,0.054862,0.039617,-0.004839, + -0.004433,-0.070467,0.997504,0.054871,0.039769,-0.004819, + -0.008849,-0.070049,0.997504,0.053861,0.039865,-0.004819, + -0.011845,-0.188277,0.982045,0.054862,0.039617,-0.004839, + -0.008849,-0.070049,0.997504,0.053861,0.039865,-0.004819, + -0.023644,-0.187162,0.982045,0.053842,0.039714,-0.004839, + 0,-0.188649,0.982045,0.055885,0.039585,-0.004839, + 0,-0.070606,0.997504,0.055885,0.039737,-0.004819, + -0.004433,-0.070467,0.997504,0.054871,0.039769,-0.004819, + 0,-0.188649,0.982045,0.055885,0.039585,-0.004839, + -0.004433,-0.070467,0.997504,0.054871,0.039769,-0.004819, + -0.011845,-0.188277,0.982045,0.054862,0.039617,-0.004839, + 0.011845,-0.188277,0.982045,0.056909,0.039617,-0.004839, + 0.004433,-0.070467,0.997504,0.056899,0.039769,-0.004819, + 0,-0.070606,0.997504,0.055885,0.039737,-0.004819, + 0.011845,-0.188277,0.982045,0.056909,0.039617,-0.004839, + 0,-0.070606,0.997504,0.055885,0.039737,-0.004819, + 0,-0.188649,0.982045,0.055885,0.039585,-0.004839, + 0.023644,-0.187162,0.982045,0.057928,0.039714,-0.004839, + 0.008849,-0.070049,0.997504,0.057909,0.039865,-0.004819, + 0.004433,-0.070467,0.997504,0.056899,0.039769,-0.004819, + 0.023644,-0.187162,0.982045,0.057928,0.039714,-0.004839, + 0.004433,-0.070467,0.997504,0.056899,0.039769,-0.004819, + 0.011845,-0.188277,0.982045,0.056909,0.039617,-0.004839, + 0.035349,-0.185308,0.982045,0.05894,0.039874,-0.004839, + 0.01323,-0.069355,0.997504,0.058911,0.040023,-0.004819, + 0.008849,-0.070049,0.997504,0.057909,0.039865,-0.004819, + 0.035349,-0.185308,0.982045,0.05894,0.039874,-0.004839, + 0.008849,-0.070049,0.997504,0.057909,0.039865,-0.004819, + 0.023644,-0.187162,0.982045,0.057928,0.039714,-0.004839, + 0.046915,-0.182722,0.982045,0.059939,0.040097,-0.004839, + 0.017559,-0.068388,0.997504,0.059901,0.040245,-0.004819, + 0.01323,-0.069355,0.997504,0.058911,0.040023,-0.004819, + 0.046915,-0.182722,0.982045,0.059939,0.040097,-0.004839, + 0.01323,-0.069355,0.997504,0.058911,0.040023,-0.004819, + 0.035349,-0.185308,0.982045,0.05894,0.039874,-0.004839, + 0.058296,-0.179416,0.982045,0.060922,0.040383,-0.004839, + 0.021818,-0.06715,0.997504,0.060875,0.040528,-0.004819, + 0.017559,-0.068388,0.997504,0.059901,0.040245,-0.004819, + 0.058296,-0.179416,0.982045,0.060922,0.040383,-0.004839, + 0.017559,-0.068388,0.997504,0.059901,0.040245,-0.004819, + 0.046915,-0.182722,0.982045,0.059939,0.040097,-0.004839, + 0.069446,-0.175402,0.982045,0.061886,0.04073,-0.004839, + 0.025992,-0.065648,0.997504,0.06183,0.040871,-0.004819, + 0.021818,-0.06715,0.997504,0.060875,0.040528,-0.004819, + 0.069446,-0.175402,0.982045,0.061886,0.04073,-0.004839, + 0.021818,-0.06715,0.997504,0.060875,0.040528,-0.004819, + 0.058296,-0.179416,0.982045,0.060922,0.040383,-0.004839, + 0.080323,-0.170695,0.982045,0.062825,0.041136,-0.004839, + 0.030062,-0.063886,0.997504,0.062761,0.041274,-0.004819, + 0.025992,-0.065648,0.997504,0.06183,0.040871,-0.004819, + 0.080323,-0.170695,0.982045,0.062825,0.041136,-0.004839, + 0.025992,-0.065648,0.997504,0.06183,0.040871,-0.004819, + 0.069446,-0.175402,0.982045,0.061886,0.04073,-0.004839, + 0.090882,-0.165314,0.982045,0.063738,0.041601,-0.004839, + 0.034015,-0.061872,0.997504,0.063665,0.041735,-0.004819, + 0.030062,-0.063886,0.997504,0.062761,0.041274,-0.004819, + 0.090882,-0.165314,0.982045,0.063738,0.041601,-0.004839, + 0.030062,-0.063886,0.997504,0.062761,0.041274,-0.004819, + 0.080323,-0.170695,0.982045,0.062825,0.041136,-0.004839, + 0.101083,-0.159282,0.982045,0.064619,0.042123,-0.004839, + 0.037832,-0.059614,0.997504,0.064538,0.042251,-0.004819, + 0.034015,-0.061872,0.997504,0.063665,0.041735,-0.004819, + 0.101083,-0.159282,0.982045,0.064619,0.042123,-0.004839, + 0.034015,-0.061872,0.997504,0.063665,0.041735,-0.004819, + 0.090882,-0.165314,0.982045,0.063738,0.041601,-0.004839, + 0.110885,-0.15262,0.982045,0.065466,0.042698,-0.004839, + 0.041501,-0.057121,0.997504,0.065377,0.042821,-0.004819, + 0.037832,-0.059614,0.997504,0.064538,0.042251,-0.004819, + 0.110885,-0.15262,0.982045,0.065466,0.042698,-0.004839, + 0.037832,-0.059614,0.997504,0.064538,0.042251,-0.004819, + 0.101083,-0.159282,0.982045,0.064619,0.042123,-0.004839, + 0.120249,-0.145357,0.982045,0.066275,0.043326,-0.004839, + 0.045006,-0.054403,0.997504,0.066178,0.043443,-0.004819, + 0.041501,-0.057121,0.997504,0.065377,0.042821,-0.004819, + 0.120249,-0.145357,0.982045,0.066275,0.043326,-0.004839, + 0.041501,-0.057121,0.997504,0.065377,0.042821,-0.004819, + 0.110885,-0.15262,0.982045,0.065466,0.042698,-0.004839, + 0.129139,-0.137519,0.982045,0.067043,0.044003,-0.004839, + 0.048333,-0.051469,0.997504,0.066939,0.044114,-0.004819, + 0.045006,-0.054403,0.997504,0.066178,0.043443,-0.004819, + 0.129139,-0.137519,0.982045,0.067043,0.044003,-0.004839, + 0.045006,-0.054403,0.997504,0.066178,0.043443,-0.004819, + 0.120249,-0.145357,0.982045,0.066275,0.043326,-0.004839, + 0.137519,-0.129139,0.982045,0.067768,0.044727,-0.004839, + 0.051469,-0.048333,0.997504,0.067657,0.044831,-0.004819, + 0.048333,-0.051469,0.997504,0.066939,0.044114,-0.004819, + 0.137519,-0.129139,0.982045,0.067768,0.044727,-0.004839, + 0.048333,-0.051469,0.997504,0.066939,0.044114,-0.004819, + 0.129139,-0.137519,0.982045,0.067043,0.044003,-0.004839, + 0.145357,-0.120249,0.982045,0.068445,0.045495,-0.004839, + 0.054403,-0.045006,0.997504,0.068328,0.045592,-0.004819, + 0.051469,-0.048333,0.997504,0.067657,0.044831,-0.004819, + 0.145357,-0.120249,0.982045,0.068445,0.045495,-0.004839, + 0.051469,-0.048333,0.997504,0.067657,0.044831,-0.004819, + 0.137519,-0.129139,0.982045,0.067768,0.044727,-0.004839, + 0.15262,-0.110885,0.982045,0.069072,0.046304,-0.004839, + 0.057121,-0.041501,0.997504,0.068949,0.046394,-0.004819, + 0.054403,-0.045006,0.997504,0.068328,0.045592,-0.004819, + 0.15262,-0.110885,0.982045,0.069072,0.046304,-0.004839, + 0.054403,-0.045006,0.997504,0.068328,0.045592,-0.004819, + 0.145357,-0.120249,0.982045,0.068445,0.045495,-0.004839, + 0.159282,-0.101083,0.982045,0.069648,0.047151,-0.004839, + 0.059614,-0.037832,0.997504,0.06952,0.047233,-0.004819, + 0.057121,-0.041501,0.997504,0.068949,0.046394,-0.004819, + 0.159282,-0.101083,0.982045,0.069648,0.047151,-0.004839, + 0.057121,-0.041501,0.997504,0.068949,0.046394,-0.004819, + 0.15262,-0.110885,0.982045,0.069072,0.046304,-0.004839, + 0.165314,-0.090882,0.982045,0.070169,0.048033,-0.004839, + 0.061872,-0.034015,0.997504,0.070036,0.048106,-0.004819, + 0.059614,-0.037832,0.997504,0.06952,0.047233,-0.004819, + 0.165314,-0.090882,0.982045,0.070169,0.048033,-0.004839, + 0.059614,-0.037832,0.997504,0.06952,0.047233,-0.004819, + 0.159282,-0.101083,0.982045,0.069648,0.047151,-0.004839, + 0.170695,-0.080323,0.982045,0.070634,0.048945,-0.004839, + 0.063886,-0.030062,0.997504,0.070497,0.04901,-0.004819, + 0.061872,-0.034015,0.997504,0.070036,0.048106,-0.004819, + 0.170695,-0.080323,0.982045,0.070634,0.048945,-0.004839, + 0.061872,-0.034015,0.997504,0.070036,0.048106,-0.004819, + 0.165314,-0.090882,0.982045,0.070169,0.048033,-0.004839, + 0.175402,-0.069446,0.982045,0.071041,0.049885,-0.004839, + 0.065648,-0.025992,0.997504,0.070899,0.049941,-0.004819, + 0.063886,-0.030062,0.997504,0.070497,0.04901,-0.004819, + 0.175402,-0.069446,0.982045,0.071041,0.049885,-0.004839, + 0.063886,-0.030062,0.997504,0.070497,0.04901,-0.004819, + 0.170695,-0.080323,0.982045,0.070634,0.048945,-0.004839, + 0.179416,-0.058296,0.982045,0.071388,0.050848,-0.004839, + 0.06715,-0.021818,0.997504,0.071243,0.050895,-0.004819, + 0.065648,-0.025992,0.997504,0.070899,0.049941,-0.004819, + 0.179416,-0.058296,0.982045,0.071388,0.050848,-0.004839, + 0.065648,-0.025992,0.997504,0.070899,0.049941,-0.004819, + 0.175402,-0.069446,0.982045,0.071041,0.049885,-0.004839, + 0.182722,-0.046915,0.982045,0.071673,0.051832,-0.004839, + 0.068388,-0.017559,0.997504,0.071526,0.051869,-0.004819, + 0.06715,-0.021818,0.997504,0.071243,0.050895,-0.004819, + 0.182722,-0.046915,0.982045,0.071673,0.051832,-0.004839, + 0.06715,-0.021818,0.997504,0.071243,0.050895,-0.004819, + 0.179416,-0.058296,0.982045,0.071388,0.050848,-0.004839, + 0.185308,-0.035349,0.982045,0.071897,0.052831,-0.004839, + 0.069355,-0.01323,0.997504,0.071747,0.052859,-0.004819, + 0.068388,-0.017559,0.997504,0.071526,0.051869,-0.004819, + 0.185308,-0.035349,0.982045,0.071897,0.052831,-0.004839, + 0.068388,-0.017559,0.997504,0.071526,0.051869,-0.004819, + 0.182722,-0.046915,0.982045,0.071673,0.051832,-0.004839, + 0.187162,-0.023644,0.982045,0.072057,0.053842,-0.004839, + 0.070049,-0.008849,0.997504,0.071906,0.053861,-0.004819, + 0.069355,-0.01323,0.997504,0.071747,0.052859,-0.004819, + 0.187162,-0.023644,0.982045,0.072057,0.053842,-0.004839, + 0.069355,-0.01323,0.997504,0.071747,0.052859,-0.004819, + 0.185308,-0.035349,0.982045,0.071897,0.052831,-0.004839, + 0.188277,-0.011845,0.982045,0.072153,0.054862,-0.004839, + 0.070467,-0.004433,0.997504,0.072001,0.054871,-0.004819, + 0.070049,-0.008849,0.997504,0.071906,0.053861,-0.004819, + 0.188277,-0.011845,0.982045,0.072153,0.054862,-0.004839, + 0.070049,-0.008849,0.997504,0.071906,0.053861,-0.004819, + 0.187162,-0.023644,0.982045,0.072057,0.053842,-0.004839, + 0.188649,0,0.982045,0.072186,0.055885,-0.004839, + 0.070606,0,0.997504,0.072033,0.055885,-0.004819, + 0.070467,-0.004433,0.997504,0.072001,0.054871,-0.004819, + 0.188649,0,0.982045,0.072186,0.055885,-0.004839, + 0.070467,-0.004433,0.997504,0.072001,0.054871,-0.004819, + 0.188277,-0.011845,0.982045,0.072153,0.054862,-0.004839, + 0.188277,0.011845,0.982045,0.072153,0.056909,-0.004839, + 0.070467,0.004433,0.997504,0.072001,0.056899,-0.004819, + 0.070606,0,0.997504,0.072033,0.055885,-0.004819, + 0.188277,0.011845,0.982045,0.072153,0.056909,-0.004839, + 0.070606,0,0.997504,0.072033,0.055885,-0.004819, + 0.188649,0,0.982045,0.072186,0.055885,-0.004839, + 0.187162,0.023644,0.982045,0.072057,0.057928,-0.004839, + 0.070049,0.008849,0.997504,0.071906,0.057909,-0.004819, + 0.070467,0.004433,0.997504,0.072001,0.056899,-0.004819, + 0.187162,0.023644,0.982045,0.072057,0.057928,-0.004839, + 0.070467,0.004433,0.997504,0.072001,0.056899,-0.004819, + 0.188277,0.011845,0.982045,0.072153,0.056909,-0.004839, + 0.185308,0.035349,0.982045,0.071897,0.05894,-0.004839, + 0.069355,0.01323,0.997504,0.071747,0.058911,-0.004819, + 0.070049,0.008849,0.997504,0.071906,0.057909,-0.004819, + 0.185308,0.035349,0.982045,0.071897,0.05894,-0.004839, + 0.070049,0.008849,0.997504,0.071906,0.057909,-0.004819, + 0.187162,0.023644,0.982045,0.072057,0.057928,-0.004839, + 0.182722,0.046915,0.982045,0.071673,0.059939,-0.004839, + 0.068388,0.017559,0.997504,0.071526,0.059901,-0.004819, + 0.069355,0.01323,0.997504,0.071747,0.058911,-0.004819, + 0.182722,0.046915,0.982045,0.071673,0.059939,-0.004839, + 0.069355,0.01323,0.997504,0.071747,0.058911,-0.004819, + 0.185308,0.035349,0.982045,0.071897,0.05894,-0.004839, + 0.179416,0.058296,0.982045,0.071388,0.060922,-0.004839, + 0.06715,0.021818,0.997504,0.071243,0.060875,-0.004819, + 0.068388,0.017559,0.997504,0.071526,0.059901,-0.004819, + 0.179416,0.058296,0.982045,0.071388,0.060922,-0.004839, + 0.068388,0.017559,0.997504,0.071526,0.059901,-0.004819, + 0.182722,0.046915,0.982045,0.071673,0.059939,-0.004839, + 0.175402,0.069446,0.982045,0.071041,0.061886,-0.004839, + 0.065648,0.025992,0.997504,0.070899,0.06183,-0.004819, + 0.06715,0.021818,0.997504,0.071243,0.060875,-0.004819, + 0.175402,0.069446,0.982045,0.071041,0.061886,-0.004839, + 0.06715,0.021818,0.997504,0.071243,0.060875,-0.004819, + 0.179416,0.058296,0.982045,0.071388,0.060922,-0.004839, + 0.170695,0.080323,0.982045,0.070634,0.062825,-0.004839, + 0.063886,0.030062,0.997504,0.070497,0.062761,-0.004819, + 0.065648,0.025992,0.997504,0.070899,0.06183,-0.004819, + 0.170695,0.080323,0.982045,0.070634,0.062825,-0.004839, + 0.065648,0.025992,0.997504,0.070899,0.06183,-0.004819, + 0.175402,0.069446,0.982045,0.071041,0.061886,-0.004839, + 0.165314,0.090882,0.982045,0.070169,0.063738,-0.004839, + 0.061872,0.034015,0.997504,0.070036,0.063665,-0.004819, + 0.063886,0.030062,0.997504,0.070497,0.062761,-0.004819, + 0.165314,0.090882,0.982045,0.070169,0.063738,-0.004839, + 0.063886,0.030062,0.997504,0.070497,0.062761,-0.004819, + 0.170695,0.080323,0.982045,0.070634,0.062825,-0.004839, + 0.159282,0.101083,0.982045,0.069648,0.064619,-0.004839, + 0.059614,0.037832,0.997504,0.06952,0.064538,-0.004819, + 0.061872,0.034015,0.997504,0.070036,0.063665,-0.004819, + 0.159282,0.101083,0.982045,0.069648,0.064619,-0.004839, + 0.061872,0.034015,0.997504,0.070036,0.063665,-0.004819, + 0.165314,0.090882,0.982045,0.070169,0.063738,-0.004839, + 0.15262,0.110885,0.982045,0.069072,0.065466,-0.004839, + 0.057121,0.041501,0.997504,0.068949,0.065377,-0.004819, + 0.059614,0.037832,0.997504,0.06952,0.064538,-0.004819, + 0.15262,0.110885,0.982045,0.069072,0.065466,-0.004839, + 0.059614,0.037832,0.997504,0.06952,0.064538,-0.004819, + 0.159282,0.101083,0.982045,0.069648,0.064619,-0.004839, + 0.145357,0.120249,0.982045,0.068445,0.066275,-0.004839, + 0.054403,0.045006,0.997504,0.068328,0.066178,-0.004819, + 0.057121,0.041501,0.997504,0.068949,0.065377,-0.004819, + 0.145357,0.120249,0.982045,0.068445,0.066275,-0.004839, + 0.057121,0.041501,0.997504,0.068949,0.065377,-0.004819, + 0.15262,0.110885,0.982045,0.069072,0.065466,-0.004839, + 0.137519,0.129139,0.982045,0.067768,0.067043,-0.004839, + 0.051469,0.048333,0.997504,0.067657,0.066939,-0.004819, + 0.054403,0.045006,0.997504,0.068328,0.066178,-0.004819, + 0.137519,0.129139,0.982045,0.067768,0.067043,-0.004839, + 0.054403,0.045006,0.997504,0.068328,0.066178,-0.004819, + 0.145357,0.120249,0.982045,0.068445,0.066275,-0.004839, + 0.129139,0.137519,0.982045,0.067043,0.067768,-0.004839, + 0.048333,0.051469,0.997504,0.066939,0.067657,-0.004819, + 0.051469,0.048333,0.997504,0.067657,0.066939,-0.004819, + 0.129139,0.137519,0.982045,0.067043,0.067768,-0.004839, + 0.051469,0.048333,0.997504,0.067657,0.066939,-0.004819, + 0.137519,0.129139,0.982045,0.067768,0.067043,-0.004839, + 0.120249,0.145357,0.982045,0.066275,0.068445,-0.004839, + 0.045006,0.054403,0.997504,0.066178,0.068328,-0.004819, + 0.048333,0.051469,0.997504,0.066939,0.067657,-0.004819, + 0.120249,0.145357,0.982045,0.066275,0.068445,-0.004839, + 0.048333,0.051469,0.997504,0.066939,0.067657,-0.004819, + 0.129139,0.137519,0.982045,0.067043,0.067768,-0.004839, + 0.110885,0.15262,0.982045,0.065466,0.069072,-0.004839, + 0.041501,0.057121,0.997504,0.065377,0.068949,-0.004819, + 0.045006,0.054403,0.997504,0.066178,0.068328,-0.004819, + 0.110885,0.15262,0.982045,0.065466,0.069072,-0.004839, + 0.045006,0.054403,0.997504,0.066178,0.068328,-0.004819, + 0.120249,0.145357,0.982045,0.066275,0.068445,-0.004839, + 0.101083,0.159282,0.982045,0.064619,0.069648,-0.004839, + 0.037832,0.059614,0.997504,0.064538,0.06952,-0.004819, + 0.041501,0.057121,0.997504,0.065377,0.068949,-0.004819, + 0.101083,0.159282,0.982045,0.064619,0.069648,-0.004839, + 0.041501,0.057121,0.997504,0.065377,0.068949,-0.004819, + 0.110885,0.15262,0.982045,0.065466,0.069072,-0.004839, + 0.090882,0.165314,0.982045,0.063738,0.070169,-0.004839, + 0.034015,0.061872,0.997504,0.063665,0.070036,-0.004819, + 0.037832,0.059614,0.997504,0.064538,0.06952,-0.004819, + 0.090882,0.165314,0.982045,0.063738,0.070169,-0.004839, + 0.037832,0.059614,0.997504,0.064538,0.06952,-0.004819, + 0.101083,0.159282,0.982045,0.064619,0.069648,-0.004839, + 0.080323,0.170695,0.982045,0.062825,0.070634,-0.004839, + 0.030062,0.063886,0.997504,0.062761,0.070497,-0.004819, + 0.034015,0.061872,0.997504,0.063665,0.070036,-0.004819, + 0.080323,0.170695,0.982045,0.062825,0.070634,-0.004839, + 0.034015,0.061872,0.997504,0.063665,0.070036,-0.004819, + 0.090882,0.165314,0.982045,0.063738,0.070169,-0.004839, + 0.069446,0.175402,0.982045,0.061886,0.071041,-0.004839, + 0.025992,0.065648,0.997504,0.06183,0.070899,-0.004819, + 0.030062,0.063886,0.997504,0.062761,0.070497,-0.004819, + 0.069446,0.175402,0.982045,0.061886,0.071041,-0.004839, + 0.030062,0.063886,0.997504,0.062761,0.070497,-0.004819, + 0.080323,0.170695,0.982045,0.062825,0.070634,-0.004839, + 0.058296,0.179416,0.982045,0.060922,0.071388,-0.004839, + 0.021818,0.06715,0.997504,0.060875,0.071243,-0.004819, + 0.025992,0.065648,0.997504,0.06183,0.070899,-0.004819, + 0.058296,0.179416,0.982045,0.060922,0.071388,-0.004839, + 0.025992,0.065648,0.997504,0.06183,0.070899,-0.004819, + 0.069446,0.175402,0.982045,0.061886,0.071041,-0.004839, + 0.046915,0.182722,0.982045,0.059939,0.071673,-0.004839, + 0.017559,0.068388,0.997504,0.059901,0.071526,-0.004819, + 0.021818,0.06715,0.997504,0.060875,0.071243,-0.004819, + 0.046915,0.182722,0.982045,0.059939,0.071673,-0.004839, + 0.021818,0.06715,0.997504,0.060875,0.071243,-0.004819, + 0.058296,0.179416,0.982045,0.060922,0.071388,-0.004839, + 0.035349,0.185308,0.982045,0.05894,0.071897,-0.004839, + 0.01323,0.069355,0.997504,0.058911,0.071747,-0.004819, + 0.017559,0.068388,0.997504,0.059901,0.071526,-0.004819, + 0.035349,0.185308,0.982045,0.05894,0.071897,-0.004839, + 0.017559,0.068388,0.997504,0.059901,0.071526,-0.004819, + 0.046915,0.182722,0.982045,0.059939,0.071673,-0.004839, + 0.023644,0.187162,0.982045,0.057928,0.072057,-0.004839, + 0.008849,0.070049,0.997504,0.057909,0.071906,-0.004819, + 0.01323,0.069355,0.997504,0.058911,0.071747,-0.004819, + 0.023644,0.187162,0.982045,0.057928,0.072057,-0.004839, + 0.01323,0.069355,0.997504,0.058911,0.071747,-0.004819, + 0.035349,0.185308,0.982045,0.05894,0.071897,-0.004839, + 0.011845,0.188277,0.982045,0.056909,0.072153,-0.004839, + 0.004433,0.070467,0.997504,0.056899,0.072001,-0.004819, + 0.008849,0.070049,0.997504,0.057909,0.071906,-0.004819, + 0.011845,0.188277,0.982045,0.056909,0.072153,-0.004839, + 0.008849,0.070049,0.997504,0.057909,0.071906,-0.004819, + 0.023644,0.187162,0.982045,0.057928,0.072057,-0.004839, + 0,0.188649,0.982045,0.055885,0.072186,-0.004839, + 0,0.070606,0.997504,0.055885,0.072033,-0.004819, + 0.004433,0.070467,0.997504,0.056899,0.072001,-0.004819, + 0,0.188649,0.982045,0.055885,0.072186,-0.004839, + 0.004433,0.070467,0.997504,0.056899,0.072001,-0.004819, + 0.011845,0.188277,0.982045,0.056909,0.072153,-0.004839, + -0.011845,0.188277,0.982045,0.054862,0.072153,-0.004839, + -0.004433,0.070467,0.997504,0.054871,0.072001,-0.004819, + 0,0.070606,0.997504,0.055885,0.072033,-0.004819, + -0.011845,0.188277,0.982045,0.054862,0.072153,-0.004839, + 0,0.070606,0.997504,0.055885,0.072033,-0.004819, + 0,0.188649,0.982045,0.055885,0.072186,-0.004839, + -0.023644,0.187162,0.982045,0.053842,0.072057,-0.004839, + -0.008849,0.070049,0.997504,0.053861,0.071906,-0.004819, + -0.004433,0.070467,0.997504,0.054871,0.072001,-0.004819, + -0.023644,0.187162,0.982045,0.053842,0.072057,-0.004839, + -0.004433,0.070467,0.997504,0.054871,0.072001,-0.004819, + -0.011845,0.188277,0.982045,0.054862,0.072153,-0.004839, + -0.035349,0.185308,0.982045,0.052831,0.071897,-0.004839, + -0.01323,0.069355,0.997504,0.052859,0.071747,-0.004819, + -0.008849,0.070049,0.997504,0.053861,0.071906,-0.004819, + -0.035349,0.185308,0.982045,0.052831,0.071897,-0.004839, + -0.008849,0.070049,0.997504,0.053861,0.071906,-0.004819, + -0.023644,0.187162,0.982045,0.053842,0.072057,-0.004839, + -0.046915,0.182722,0.982045,0.051832,0.071673,-0.004839, + -0.017559,0.068388,0.997504,0.051869,0.071526,-0.004819, + -0.01323,0.069355,0.997504,0.052859,0.071747,-0.004819, + -0.046915,0.182722,0.982045,0.051832,0.071673,-0.004839, + -0.01323,0.069355,0.997504,0.052859,0.071747,-0.004819, + -0.035349,0.185308,0.982045,0.052831,0.071897,-0.004839, + -0.058296,0.179416,0.982045,0.050848,0.071388,-0.004839, + -0.021818,0.06715,0.997504,0.050895,0.071243,-0.004819, + -0.017559,0.068388,0.997504,0.051869,0.071526,-0.004819, + -0.058296,0.179416,0.982045,0.050848,0.071388,-0.004839, + -0.017559,0.068388,0.997504,0.051869,0.071526,-0.004819, + -0.046915,0.182722,0.982045,0.051832,0.071673,-0.004839, + -0.069446,0.175402,0.982045,0.049885,0.071041,-0.004839, + -0.025992,0.065648,0.997504,0.049941,0.070899,-0.004819, + -0.021818,0.06715,0.997504,0.050895,0.071243,-0.004819, + -0.069446,0.175402,0.982045,0.049885,0.071041,-0.004839, + -0.021818,0.06715,0.997504,0.050895,0.071243,-0.004819, + -0.058296,0.179416,0.982045,0.050848,0.071388,-0.004839, + -0.080323,0.170695,0.982045,0.048945,0.070634,-0.004839, + -0.030062,0.063886,0.997504,0.04901,0.070497,-0.004819, + -0.025992,0.065648,0.997504,0.049941,0.070899,-0.004819, + -0.080323,0.170695,0.982045,0.048945,0.070634,-0.004839, + -0.025992,0.065648,0.997504,0.049941,0.070899,-0.004819, + -0.069446,0.175402,0.982045,0.049885,0.071041,-0.004839, + -0.090882,0.165314,0.982045,0.048033,0.070169,-0.004839, + -0.034015,0.061872,0.997504,0.048106,0.070036,-0.004819, + -0.030062,0.063886,0.997504,0.04901,0.070497,-0.004819, + -0.090882,0.165314,0.982045,0.048033,0.070169,-0.004839, + -0.030062,0.063886,0.997504,0.04901,0.070497,-0.004819, + -0.080323,0.170695,0.982045,0.048945,0.070634,-0.004839, + -0.101083,0.159282,0.982045,0.047151,0.069648,-0.004839, + -0.037832,0.059614,0.997504,0.047233,0.06952,-0.004819, + -0.034015,0.061872,0.997504,0.048106,0.070036,-0.004819, + -0.101083,0.159282,0.982045,0.047151,0.069648,-0.004839, + -0.034015,0.061872,0.997504,0.048106,0.070036,-0.004819, + -0.090882,0.165314,0.982045,0.048033,0.070169,-0.004839, + -0.110885,0.15262,0.982045,0.046304,0.069072,-0.004839, + -0.041501,0.057121,0.997504,0.046394,0.068949,-0.004819, + -0.037832,0.059614,0.997504,0.047233,0.06952,-0.004819, + -0.110885,0.15262,0.982045,0.046304,0.069072,-0.004839, + -0.037832,0.059614,0.997504,0.047233,0.06952,-0.004819, + -0.101083,0.159282,0.982045,0.047151,0.069648,-0.004839, + -0.120249,0.145357,0.982045,0.045495,0.068445,-0.004839, + -0.045006,0.054403,0.997504,0.045592,0.068328,-0.004819, + -0.041501,0.057121,0.997504,0.046394,0.068949,-0.004819, + -0.120249,0.145357,0.982045,0.045495,0.068445,-0.004839, + -0.041501,0.057121,0.997504,0.046394,0.068949,-0.004819, + -0.110885,0.15262,0.982045,0.046304,0.069072,-0.004839, + -0.129139,0.137519,0.982045,0.044727,0.067768,-0.004839, + -0.048333,0.051469,0.997504,0.044831,0.067657,-0.004819, + -0.045006,0.054403,0.997504,0.045592,0.068328,-0.004819, + -0.129139,0.137519,0.982045,0.044727,0.067768,-0.004839, + -0.045006,0.054403,0.997504,0.045592,0.068328,-0.004819, + -0.120249,0.145357,0.982045,0.045495,0.068445,-0.004839, + -0.137519,0.129139,0.982045,0.044003,0.067043,-0.004839, + -0.051469,0.048333,0.997504,0.044114,0.066939,-0.004819, + -0.048333,0.051469,0.997504,0.044831,0.067657,-0.004819, + -0.137519,0.129139,0.982045,0.044003,0.067043,-0.004839, + -0.048333,0.051469,0.997504,0.044831,0.067657,-0.004819, + -0.129139,0.137519,0.982045,0.044727,0.067768,-0.004839, + -0.145357,0.120249,0.982045,0.043326,0.066275,-0.004839, + -0.054403,0.045006,0.997504,0.043443,0.066178,-0.004819, + -0.051469,0.048333,0.997504,0.044114,0.066939,-0.004819, + -0.145357,0.120249,0.982045,0.043326,0.066275,-0.004839, + -0.051469,0.048333,0.997504,0.044114,0.066939,-0.004819, + -0.137519,0.129139,0.982045,0.044003,0.067043,-0.004839, + -0.15262,0.110885,0.982045,0.042698,0.065466,-0.004839, + -0.057121,0.041501,0.997504,0.042821,0.065377,-0.004819, + -0.054403,0.045006,0.997504,0.043443,0.066178,-0.004819, + -0.15262,0.110885,0.982045,0.042698,0.065466,-0.004839, + -0.054403,0.045006,0.997504,0.043443,0.066178,-0.004819, + -0.145357,0.120249,0.982045,0.043326,0.066275,-0.004839, + -0.159282,0.101083,0.982045,0.042123,0.064619,-0.004839, + -0.059614,0.037832,0.997504,0.042251,0.064538,-0.004819, + -0.057121,0.041501,0.997504,0.042821,0.065377,-0.004819, + -0.159282,0.101083,0.982045,0.042123,0.064619,-0.004839, + -0.057121,0.041501,0.997504,0.042821,0.065377,-0.004819, + -0.15262,0.110885,0.982045,0.042698,0.065466,-0.004839, + -0.165314,0.090882,0.982045,0.041601,0.063738,-0.004839, + -0.061872,0.034015,0.997504,0.041735,0.063665,-0.004819, + -0.059614,0.037832,0.997504,0.042251,0.064538,-0.004819, + -0.165314,0.090882,0.982045,0.041601,0.063738,-0.004839, + -0.059614,0.037832,0.997504,0.042251,0.064538,-0.004819, + -0.159282,0.101083,0.982045,0.042123,0.064619,-0.004839, + -0.170695,0.080323,0.982045,0.041136,0.062825,-0.004839, + -0.063886,0.030062,0.997504,0.041274,0.062761,-0.004819, + -0.061872,0.034015,0.997504,0.041735,0.063665,-0.004819, + -0.170695,0.080323,0.982045,0.041136,0.062825,-0.004839, + -0.061872,0.034015,0.997504,0.041735,0.063665,-0.004819, + -0.165314,0.090882,0.982045,0.041601,0.063738,-0.004839, + -0.175402,0.069446,0.982045,0.04073,0.061886,-0.004839, + -0.065648,0.025992,0.997504,0.040871,0.06183,-0.004819, + -0.063886,0.030062,0.997504,0.041274,0.062761,-0.004819, + -0.175402,0.069446,0.982045,0.04073,0.061886,-0.004839, + -0.063886,0.030062,0.997504,0.041274,0.062761,-0.004819, + -0.170695,0.080323,0.982045,0.041136,0.062825,-0.004839, + -0.065648,0.025992,0.997504,0.040871,0.06183,-0.004819, + -0.006883,0.002725,0.999973,0.041014,0.061773,-0.004818, + -0.006698,0.003152,0.999973,0.041413,0.062696,-0.004818, + -0.065648,0.025992,0.997504,0.040871,0.06183,-0.004819, + -0.006698,0.003152,0.999973,0.041413,0.062696,-0.004818, + -0.063886,0.030062,0.997504,0.041274,0.062761,-0.004819, + -0.06715,0.021818,0.997504,0.040528,0.060875,-0.004819, + -0.00704,0.002287,0.999973,0.040673,0.060828,-0.004818, + -0.006883,0.002725,0.999973,0.041014,0.061773,-0.004818, + -0.06715,0.021818,0.997504,0.040528,0.060875,-0.004819, + -0.006883,0.002725,0.999973,0.041014,0.061773,-0.004818, + -0.065648,0.025992,0.997504,0.040871,0.06183,-0.004819, + -0.068388,0.017559,0.997504,0.040245,0.059901,-0.004819, + -0.00717,0.001841,0.999973,0.040393,0.059863,-0.004818, + -0.00704,0.002287,0.999973,0.040673,0.060828,-0.004818, + -0.068388,0.017559,0.997504,0.040245,0.059901,-0.004819, + -0.00704,0.002287,0.999973,0.040673,0.060828,-0.004818, + -0.06715,0.021818,0.997504,0.040528,0.060875,-0.004819, + -0.069355,0.01323,0.997504,0.040023,0.058911,-0.004819, + -0.007271,0.001387,0.999973,0.040174,0.058882,-0.004818, + -0.00717,0.001841,0.999973,0.040393,0.059863,-0.004818, + -0.069355,0.01323,0.997504,0.040023,0.058911,-0.004819, + -0.00717,0.001841,0.999973,0.040393,0.059863,-0.004818, + -0.068388,0.017559,0.997504,0.040245,0.059901,-0.004819, + -0.070049,0.008849,0.997504,0.039865,0.057909,-0.004819, + -0.007344,0.000928,0.999973,0.040017,0.05789,-0.004818, + -0.007271,0.001387,0.999973,0.040174,0.058882,-0.004818, + -0.070049,0.008849,0.997504,0.039865,0.057909,-0.004819, + -0.007271,0.001387,0.999973,0.040174,0.058882,-0.004818, + -0.069355,0.01323,0.997504,0.040023,0.058911,-0.004819, + -0.070467,0.004433,0.997504,0.039769,0.056899,-0.004819, + -0.007388,0.000465,0.999973,0.039922,0.05689,-0.004818, + -0.007344,0.000928,0.999973,0.040017,0.05789,-0.004818, + -0.070467,0.004433,0.997504,0.039769,0.056899,-0.004819, + -0.007344,0.000928,0.999973,0.040017,0.05789,-0.004818, + -0.070049,0.008849,0.997504,0.039865,0.057909,-0.004819, + -0.070606,0,0.997504,0.039737,0.055885,-0.004819, + -0.007402,0,0.999973,0.039891,0.055885,-0.004818, + -0.007388,0.000465,0.999973,0.039922,0.05689,-0.004818, + -0.070606,0,0.997504,0.039737,0.055885,-0.004819, + -0.007388,0.000465,0.999973,0.039922,0.05689,-0.004818, + -0.070467,0.004433,0.997504,0.039769,0.056899,-0.004819, + -0.070467,-0.004433,0.997504,0.039769,0.054871,-0.004819, + -0.007388,-0.000465,0.999973,0.039922,0.054881,-0.004818, + -0.007402,0,0.999973,0.039891,0.055885,-0.004818, + -0.070467,-0.004433,0.997504,0.039769,0.054871,-0.004819, + -0.007402,0,0.999973,0.039891,0.055885,-0.004818, + -0.070606,0,0.997504,0.039737,0.055885,-0.004819, + -0.070049,-0.008849,0.997504,0.039865,0.053861,-0.004819, + -0.007344,-0.000928,0.999973,0.040017,0.053881,-0.004818, + -0.007388,-0.000465,0.999973,0.039922,0.054881,-0.004818, + -0.070049,-0.008849,0.997504,0.039865,0.053861,-0.004819, + -0.007388,-0.000465,0.999973,0.039922,0.054881,-0.004818, + -0.070467,-0.004433,0.997504,0.039769,0.054871,-0.004819, + -0.069355,-0.01323,0.997504,0.040023,0.052859,-0.004819, + -0.007271,-0.001387,0.999973,0.040174,0.052888,-0.004818, + -0.007344,-0.000928,0.999973,0.040017,0.053881,-0.004818, + -0.069355,-0.01323,0.997504,0.040023,0.052859,-0.004819, + -0.007344,-0.000928,0.999973,0.040017,0.053881,-0.004818, + -0.070049,-0.008849,0.997504,0.039865,0.053861,-0.004819, + -0.068388,-0.017559,0.997504,0.040245,0.051869,-0.004819, + -0.00717,-0.001841,0.999973,0.040393,0.051908,-0.004818, + -0.007271,-0.001387,0.999973,0.040174,0.052888,-0.004818, + -0.068388,-0.017559,0.997504,0.040245,0.051869,-0.004819, + -0.007271,-0.001387,0.999973,0.040174,0.052888,-0.004818, + -0.069355,-0.01323,0.997504,0.040023,0.052859,-0.004819, + -0.06715,-0.021818,0.997504,0.040528,0.050895,-0.004819, + -0.00704,-0.002287,0.999973,0.040673,0.050943,-0.004818, + -0.00717,-0.001841,0.999973,0.040393,0.051908,-0.004818, + -0.06715,-0.021818,0.997504,0.040528,0.050895,-0.004819, + -0.00717,-0.001841,0.999973,0.040393,0.051908,-0.004818, + -0.068388,-0.017559,0.997504,0.040245,0.051869,-0.004819, + -0.065648,-0.025992,0.997504,0.040871,0.049941,-0.004819, + -0.006883,-0.002725,0.999973,0.041014,0.049997,-0.004818, + -0.00704,-0.002287,0.999973,0.040673,0.050943,-0.004818, + -0.065648,-0.025992,0.997504,0.040871,0.049941,-0.004819, + -0.00704,-0.002287,0.999973,0.040673,0.050943,-0.004818, + -0.06715,-0.021818,0.997504,0.040528,0.050895,-0.004819, + -0.063886,-0.030062,0.997504,0.041274,0.04901,-0.004819, + -0.006698,-0.003152,0.999973,0.041413,0.049075,-0.004818, + -0.006883,-0.002725,0.999973,0.041014,0.049997,-0.004818, + -0.063886,-0.030062,0.997504,0.041274,0.04901,-0.004819, + -0.006883,-0.002725,0.999973,0.041014,0.049997,-0.004818, + -0.065648,-0.025992,0.997504,0.040871,0.049941,-0.004819, + -0.061872,-0.034015,0.997504,0.041735,0.048106,-0.004819, + -0.006487,-0.003566,0.999973,0.041869,0.04818,-0.004818, + -0.006698,-0.003152,0.999973,0.041413,0.049075,-0.004818, + -0.061872,-0.034015,0.997504,0.041735,0.048106,-0.004819, + -0.006698,-0.003152,0.999973,0.041413,0.049075,-0.004818, + -0.063886,-0.030062,0.997504,0.041274,0.04901,-0.004819, + -0.059614,-0.037832,0.997504,0.042251,0.047233,-0.004819, + -0.00625,-0.003966,0.999973,0.042381,0.047315,-0.004818, + -0.006487,-0.003566,0.999973,0.041869,0.04818,-0.004818, + -0.059614,-0.037832,0.997504,0.042251,0.047233,-0.004819, + -0.006487,-0.003566,0.999973,0.041869,0.04818,-0.004818, + -0.061872,-0.034015,0.997504,0.041735,0.048106,-0.004819, + -0.057121,-0.041501,0.997504,0.042821,0.046394,-0.004819, + -0.005989,-0.004351,0.999973,0.042945,0.046484,-0.004818, + -0.00625,-0.003966,0.999973,0.042381,0.047315,-0.004818, + -0.057121,-0.041501,0.997504,0.042821,0.046394,-0.004819, + -0.00625,-0.003966,0.999973,0.042381,0.047315,-0.004818, + -0.059614,-0.037832,0.997504,0.042251,0.047233,-0.004819, + -0.054403,-0.045006,0.997504,0.043443,0.045592,-0.004819, + -0.005704,-0.004718,0.999973,0.043561,0.04569,-0.004818, + -0.005989,-0.004351,0.999973,0.042945,0.046484,-0.004818, + -0.054403,-0.045006,0.997504,0.043443,0.045592,-0.004819, + -0.005989,-0.004351,0.999973,0.042945,0.046484,-0.004818, + -0.057121,-0.041501,0.997504,0.042821,0.046394,-0.004819, + -0.051469,-0.048333,0.997504,0.044114,0.044831,-0.004819, + -0.005396,-0.005067,0.999973,0.044226,0.044936,-0.004818, + -0.005704,-0.004718,0.999973,0.043561,0.04569,-0.004818, + -0.051469,-0.048333,0.997504,0.044114,0.044831,-0.004819, + -0.005704,-0.004718,0.999973,0.043561,0.04569,-0.004818, + -0.054403,-0.045006,0.997504,0.043443,0.045592,-0.004819, + -0.048333,-0.051469,0.997504,0.044831,0.044114,-0.004819, + -0.005067,-0.005396,0.999973,0.044936,0.044226,-0.004818, + -0.005396,-0.005067,0.999973,0.044226,0.044936,-0.004818, + -0.048333,-0.051469,0.997504,0.044831,0.044114,-0.004819, + -0.005396,-0.005067,0.999973,0.044226,0.044936,-0.004818, + -0.051469,-0.048333,0.997504,0.044114,0.044831,-0.004819, + -0.045006,-0.054403,0.997504,0.045592,0.043443,-0.004819, + -0.004718,-0.005704,0.999973,0.04569,0.043561,-0.004818, + -0.005067,-0.005396,0.999973,0.044936,0.044226,-0.004818, + -0.045006,-0.054403,0.997504,0.045592,0.043443,-0.004819, + -0.005067,-0.005396,0.999973,0.044936,0.044226,-0.004818, + -0.048333,-0.051469,0.997504,0.044831,0.044114,-0.004819, + -0.041501,-0.057121,0.997504,0.046394,0.042821,-0.004819, + -0.004351,-0.005989,0.999973,0.046484,0.042945,-0.004818, + -0.004718,-0.005704,0.999973,0.04569,0.043561,-0.004818, + -0.041501,-0.057121,0.997504,0.046394,0.042821,-0.004819, + -0.004718,-0.005704,0.999973,0.04569,0.043561,-0.004818, + -0.045006,-0.054403,0.997504,0.045592,0.043443,-0.004819, + -0.037832,-0.059614,0.997504,0.047233,0.042251,-0.004819, + -0.003966,-0.00625,0.999973,0.047315,0.042381,-0.004818, + -0.004351,-0.005989,0.999973,0.046484,0.042945,-0.004818, + -0.037832,-0.059614,0.997504,0.047233,0.042251,-0.004819, + -0.004351,-0.005989,0.999973,0.046484,0.042945,-0.004818, + -0.041501,-0.057121,0.997504,0.046394,0.042821,-0.004819, + -0.034015,-0.061872,0.997504,0.048106,0.041735,-0.004819, + -0.003566,-0.006487,0.999973,0.04818,0.041869,-0.004818, + -0.003966,-0.00625,0.999973,0.047315,0.042381,-0.004818, + -0.034015,-0.061872,0.997504,0.048106,0.041735,-0.004819, + -0.003966,-0.00625,0.999973,0.047315,0.042381,-0.004818, + -0.037832,-0.059614,0.997504,0.047233,0.042251,-0.004819, + -0.030062,-0.063886,0.997504,0.04901,0.041274,-0.004819, + -0.003152,-0.006698,0.999973,0.049075,0.041413,-0.004818, + -0.003566,-0.006487,0.999973,0.04818,0.041869,-0.004818, + -0.030062,-0.063886,0.997504,0.04901,0.041274,-0.004819, + -0.003566,-0.006487,0.999973,0.04818,0.041869,-0.004818, + -0.034015,-0.061872,0.997504,0.048106,0.041735,-0.004819, + -0.025992,-0.065648,0.997504,0.049941,0.040871,-0.004819, + -0.002725,-0.006883,0.999973,0.049997,0.041014,-0.004818, + -0.003152,-0.006698,0.999973,0.049075,0.041413,-0.004818, + -0.025992,-0.065648,0.997504,0.049941,0.040871,-0.004819, + -0.003152,-0.006698,0.999973,0.049075,0.041413,-0.004818, + -0.030062,-0.063886,0.997504,0.04901,0.041274,-0.004819, + -0.021818,-0.06715,0.997504,0.050895,0.040528,-0.004819, + -0.002287,-0.00704,0.999973,0.050943,0.040673,-0.004818, + -0.002725,-0.006883,0.999973,0.049997,0.041014,-0.004818, + -0.021818,-0.06715,0.997504,0.050895,0.040528,-0.004819, + -0.002725,-0.006883,0.999973,0.049997,0.041014,-0.004818, + -0.025992,-0.065648,0.997504,0.049941,0.040871,-0.004819, + -0.017559,-0.068388,0.997504,0.051869,0.040245,-0.004819, + -0.001841,-0.00717,0.999973,0.051908,0.040393,-0.004818, + -0.002287,-0.00704,0.999973,0.050943,0.040673,-0.004818, + -0.017559,-0.068388,0.997504,0.051869,0.040245,-0.004819, + -0.002287,-0.00704,0.999973,0.050943,0.040673,-0.004818, + -0.021818,-0.06715,0.997504,0.050895,0.040528,-0.004819, + -0.01323,-0.069355,0.997504,0.052859,0.040023,-0.004819, + -0.001387,-0.007271,0.999973,0.052888,0.040174,-0.004818, + -0.001841,-0.00717,0.999973,0.051908,0.040393,-0.004818, + -0.01323,-0.069355,0.997504,0.052859,0.040023,-0.004819, + -0.001841,-0.00717,0.999973,0.051908,0.040393,-0.004818, + -0.017559,-0.068388,0.997504,0.051869,0.040245,-0.004819, + -0.008849,-0.070049,0.997504,0.053861,0.039865,-0.004819, + -0.000928,-0.007344,0.999973,0.053881,0.040017,-0.004818, + -0.001387,-0.007271,0.999973,0.052888,0.040174,-0.004818, + -0.008849,-0.070049,0.997504,0.053861,0.039865,-0.004819, + -0.001387,-0.007271,0.999973,0.052888,0.040174,-0.004818, + -0.01323,-0.069355,0.997504,0.052859,0.040023,-0.004819, + -0.004433,-0.070467,0.997504,0.054871,0.039769,-0.004819, + -0.000465,-0.007388,0.999973,0.054881,0.039922,-0.004818, + -0.000928,-0.007344,0.999973,0.053881,0.040017,-0.004818, + -0.004433,-0.070467,0.997504,0.054871,0.039769,-0.004819, + -0.000928,-0.007344,0.999973,0.053881,0.040017,-0.004818, + -0.008849,-0.070049,0.997504,0.053861,0.039865,-0.004819, + 0,-0.070606,0.997504,0.055885,0.039737,-0.004819, + 0,-0.007402,0.999973,0.055885,0.039891,-0.004818, + -0.000465,-0.007388,0.999973,0.054881,0.039922,-0.004818, + 0,-0.070606,0.997504,0.055885,0.039737,-0.004819, + -0.000465,-0.007388,0.999973,0.054881,0.039922,-0.004818, + -0.004433,-0.070467,0.997504,0.054871,0.039769,-0.004819, + 0.004433,-0.070467,0.997504,0.056899,0.039769,-0.004819, + 0.000465,-0.007388,0.999973,0.05689,0.039922,-0.004818, + 0,-0.007402,0.999973,0.055885,0.039891,-0.004818, + 0.004433,-0.070467,0.997504,0.056899,0.039769,-0.004819, + 0,-0.007402,0.999973,0.055885,0.039891,-0.004818, + 0,-0.070606,0.997504,0.055885,0.039737,-0.004819, + 0.008849,-0.070049,0.997504,0.057909,0.039865,-0.004819, + 0.000928,-0.007344,0.999973,0.05789,0.040017,-0.004818, + 0.000465,-0.007388,0.999973,0.05689,0.039922,-0.004818, + 0.008849,-0.070049,0.997504,0.057909,0.039865,-0.004819, + 0.000465,-0.007388,0.999973,0.05689,0.039922,-0.004818, + 0.004433,-0.070467,0.997504,0.056899,0.039769,-0.004819, + 0.01323,-0.069355,0.997504,0.058911,0.040023,-0.004819, + 0.001387,-0.007271,0.999973,0.058882,0.040174,-0.004818, + 0.000928,-0.007344,0.999973,0.05789,0.040017,-0.004818, + 0.01323,-0.069355,0.997504,0.058911,0.040023,-0.004819, + 0.000928,-0.007344,0.999973,0.05789,0.040017,-0.004818, + 0.008849,-0.070049,0.997504,0.057909,0.039865,-0.004819, + 0.017559,-0.068388,0.997504,0.059901,0.040245,-0.004819, + 0.001841,-0.00717,0.999973,0.059863,0.040393,-0.004818, + 0.001387,-0.007271,0.999973,0.058882,0.040174,-0.004818, + 0.017559,-0.068388,0.997504,0.059901,0.040245,-0.004819, + 0.001387,-0.007271,0.999973,0.058882,0.040174,-0.004818, + 0.01323,-0.069355,0.997504,0.058911,0.040023,-0.004819, + 0.021818,-0.06715,0.997504,0.060875,0.040528,-0.004819, + 0.002287,-0.00704,0.999973,0.060828,0.040673,-0.004818, + 0.001841,-0.00717,0.999973,0.059863,0.040393,-0.004818, + 0.021818,-0.06715,0.997504,0.060875,0.040528,-0.004819, + 0.001841,-0.00717,0.999973,0.059863,0.040393,-0.004818, + 0.017559,-0.068388,0.997504,0.059901,0.040245,-0.004819, + 0.025992,-0.065648,0.997504,0.06183,0.040871,-0.004819, + 0.002725,-0.006883,0.999973,0.061773,0.041014,-0.004818, + 0.002287,-0.00704,0.999973,0.060828,0.040673,-0.004818, + 0.025992,-0.065648,0.997504,0.06183,0.040871,-0.004819, + 0.002287,-0.00704,0.999973,0.060828,0.040673,-0.004818, + 0.021818,-0.06715,0.997504,0.060875,0.040528,-0.004819, + 0.030062,-0.063886,0.997504,0.062761,0.041274,-0.004819, + 0.003152,-0.006698,0.999973,0.062696,0.041413,-0.004818, + 0.002725,-0.006883,0.999973,0.061773,0.041014,-0.004818, + 0.030062,-0.063886,0.997504,0.062761,0.041274,-0.004819, + 0.002725,-0.006883,0.999973,0.061773,0.041014,-0.004818, + 0.025992,-0.065648,0.997504,0.06183,0.040871,-0.004819, + 0.034015,-0.061872,0.997504,0.063665,0.041735,-0.004819, + 0.003566,-0.006487,0.999973,0.063591,0.041869,-0.004818, + 0.003152,-0.006698,0.999973,0.062696,0.041413,-0.004818, + 0.034015,-0.061872,0.997504,0.063665,0.041735,-0.004819, + 0.003152,-0.006698,0.999973,0.062696,0.041413,-0.004818, + 0.030062,-0.063886,0.997504,0.062761,0.041274,-0.004819, + 0.037832,-0.059614,0.997504,0.064538,0.042251,-0.004819, + 0.003966,-0.00625,0.999973,0.064456,0.042381,-0.004818, + 0.003566,-0.006487,0.999973,0.063591,0.041869,-0.004818, + 0.037832,-0.059614,0.997504,0.064538,0.042251,-0.004819, + 0.003566,-0.006487,0.999973,0.063591,0.041869,-0.004818, + 0.034015,-0.061872,0.997504,0.063665,0.041735,-0.004819, + 0.041501,-0.057121,0.997504,0.065377,0.042821,-0.004819, + 0.004351,-0.005989,0.999973,0.065287,0.042945,-0.004818, + 0.003966,-0.00625,0.999973,0.064456,0.042381,-0.004818, + 0.041501,-0.057121,0.997504,0.065377,0.042821,-0.004819, + 0.003966,-0.00625,0.999973,0.064456,0.042381,-0.004818, + 0.037832,-0.059614,0.997504,0.064538,0.042251,-0.004819, + 0.045006,-0.054403,0.997504,0.066178,0.043443,-0.004819, + 0.004718,-0.005704,0.999973,0.066081,0.043561,-0.004818, + 0.004351,-0.005989,0.999973,0.065287,0.042945,-0.004818, + 0.045006,-0.054403,0.997504,0.066178,0.043443,-0.004819, + 0.004351,-0.005989,0.999973,0.065287,0.042945,-0.004818, + 0.041501,-0.057121,0.997504,0.065377,0.042821,-0.004819, + 0.048333,-0.051469,0.997504,0.066939,0.044114,-0.004819, + 0.005067,-0.005396,0.999973,0.066834,0.044226,-0.004818, + 0.004718,-0.005704,0.999973,0.066081,0.043561,-0.004818, + 0.048333,-0.051469,0.997504,0.066939,0.044114,-0.004819, + 0.004718,-0.005704,0.999973,0.066081,0.043561,-0.004818, + 0.045006,-0.054403,0.997504,0.066178,0.043443,-0.004819, + 0.051469,-0.048333,0.997504,0.067657,0.044831,-0.004819, + 0.005396,-0.005067,0.999973,0.067545,0.044936,-0.004818, + 0.005067,-0.005396,0.999973,0.066834,0.044226,-0.004818, + 0.051469,-0.048333,0.997504,0.067657,0.044831,-0.004819, + 0.005067,-0.005396,0.999973,0.066834,0.044226,-0.004818, + 0.048333,-0.051469,0.997504,0.066939,0.044114,-0.004819, + 0.054403,-0.045006,0.997504,0.068328,0.045592,-0.004819, + 0.005704,-0.004718,0.999973,0.06821,0.04569,-0.004818, + 0.005396,-0.005067,0.999973,0.067545,0.044936,-0.004818, + 0.054403,-0.045006,0.997504,0.068328,0.045592,-0.004819, + 0.005396,-0.005067,0.999973,0.067545,0.044936,-0.004818, + 0.051469,-0.048333,0.997504,0.067657,0.044831,-0.004819, + 0.057121,-0.041501,0.997504,0.068949,0.046394,-0.004819, + 0.005989,-0.004351,0.999973,0.068825,0.046484,-0.004818, + 0.005704,-0.004718,0.999973,0.06821,0.04569,-0.004818, + 0.057121,-0.041501,0.997504,0.068949,0.046394,-0.004819, + 0.005704,-0.004718,0.999973,0.06821,0.04569,-0.004818, + 0.054403,-0.045006,0.997504,0.068328,0.045592,-0.004819, + 0.059614,-0.037832,0.997504,0.06952,0.047233,-0.004819, + 0.00625,-0.003966,0.999973,0.06939,0.047315,-0.004818, + 0.005989,-0.004351,0.999973,0.068825,0.046484,-0.004818, + 0.059614,-0.037832,0.997504,0.06952,0.047233,-0.004819, + 0.005989,-0.004351,0.999973,0.068825,0.046484,-0.004818, + 0.057121,-0.041501,0.997504,0.068949,0.046394,-0.004819, + 0.061872,-0.034015,0.997504,0.070036,0.048106,-0.004819, + 0.006487,-0.003566,0.999973,0.069902,0.04818,-0.004818, + 0.00625,-0.003966,0.999973,0.06939,0.047315,-0.004818, + 0.061872,-0.034015,0.997504,0.070036,0.048106,-0.004819, + 0.00625,-0.003966,0.999973,0.06939,0.047315,-0.004818, + 0.059614,-0.037832,0.997504,0.06952,0.047233,-0.004819, + 0.063886,-0.030062,0.997504,0.070497,0.04901,-0.004819, + 0.006698,-0.003152,0.999973,0.070358,0.049075,-0.004818, + 0.006487,-0.003566,0.999973,0.069902,0.04818,-0.004818, + 0.063886,-0.030062,0.997504,0.070497,0.04901,-0.004819, + 0.006487,-0.003566,0.999973,0.069902,0.04818,-0.004818, + 0.061872,-0.034015,0.997504,0.070036,0.048106,-0.004819, + 0.065648,-0.025992,0.997504,0.070899,0.049941,-0.004819, + 0.006883,-0.002725,0.999973,0.070757,0.049997,-0.004818, + 0.006698,-0.003152,0.999973,0.070358,0.049075,-0.004818, + 0.065648,-0.025992,0.997504,0.070899,0.049941,-0.004819, + 0.006698,-0.003152,0.999973,0.070358,0.049075,-0.004818, + 0.063886,-0.030062,0.997504,0.070497,0.04901,-0.004819, + 0.06715,-0.021818,0.997504,0.071243,0.050895,-0.004819, + 0.00704,-0.002287,0.999973,0.071097,0.050943,-0.004818, + 0.006883,-0.002725,0.999973,0.070757,0.049997,-0.004818, + 0.06715,-0.021818,0.997504,0.071243,0.050895,-0.004819, + 0.006883,-0.002725,0.999973,0.070757,0.049997,-0.004818, + 0.065648,-0.025992,0.997504,0.070899,0.049941,-0.004819, + 0.068388,-0.017559,0.997504,0.071526,0.051869,-0.004819, + 0.00717,-0.001841,0.999973,0.071377,0.051908,-0.004818, + 0.00704,-0.002287,0.999973,0.071097,0.050943,-0.004818, + 0.068388,-0.017559,0.997504,0.071526,0.051869,-0.004819, + 0.00704,-0.002287,0.999973,0.071097,0.050943,-0.004818, + 0.06715,-0.021818,0.997504,0.071243,0.050895,-0.004819, + 0.069355,-0.01323,0.997504,0.071747,0.052859,-0.004819, + 0.007271,-0.001387,0.999973,0.071597,0.052888,-0.004818, + 0.00717,-0.001841,0.999973,0.071377,0.051908,-0.004818, + 0.069355,-0.01323,0.997504,0.071747,0.052859,-0.004819, + 0.00717,-0.001841,0.999973,0.071377,0.051908,-0.004818, + 0.068388,-0.017559,0.997504,0.071526,0.051869,-0.004819, + 0.070049,-0.008849,0.997504,0.071906,0.053861,-0.004819, + 0.007344,-0.000928,0.999973,0.071754,0.053881,-0.004818, + 0.007271,-0.001387,0.999973,0.071597,0.052888,-0.004818, + 0.070049,-0.008849,0.997504,0.071906,0.053861,-0.004819, + 0.007271,-0.001387,0.999973,0.071597,0.052888,-0.004818, + 0.069355,-0.01323,0.997504,0.071747,0.052859,-0.004819, + 0.070467,-0.004433,0.997504,0.072001,0.054871,-0.004819, + 0.007388,-0.000465,0.999973,0.071848,0.054881,-0.004818, + 0.007344,-0.000928,0.999973,0.071754,0.053881,-0.004818, + 0.070467,-0.004433,0.997504,0.072001,0.054871,-0.004819, + 0.007344,-0.000928,0.999973,0.071754,0.053881,-0.004818, + 0.070049,-0.008849,0.997504,0.071906,0.053861,-0.004819, + 0.070606,0,0.997504,0.072033,0.055885,-0.004819, + 0.007402,0,0.999973,0.07188,0.055885,-0.004818, + 0.007388,-0.000465,0.999973,0.071848,0.054881,-0.004818, + 0.070606,0,0.997504,0.072033,0.055885,-0.004819, + 0.007388,-0.000465,0.999973,0.071848,0.054881,-0.004818, + 0.070467,-0.004433,0.997504,0.072001,0.054871,-0.004819, + 0.070467,0.004433,0.997504,0.072001,0.056899,-0.004819, + 0.007388,0.000465,0.999973,0.071848,0.05689,-0.004818, + 0.007402,0,0.999973,0.07188,0.055885,-0.004818, + 0.070467,0.004433,0.997504,0.072001,0.056899,-0.004819, + 0.007402,0,0.999973,0.07188,0.055885,-0.004818, + 0.070606,0,0.997504,0.072033,0.055885,-0.004819, + 0.070049,0.008849,0.997504,0.071906,0.057909,-0.004819, + 0.007344,0.000928,0.999973,0.071754,0.05789,-0.004818, + 0.007388,0.000465,0.999973,0.071848,0.05689,-0.004818, + 0.070049,0.008849,0.997504,0.071906,0.057909,-0.004819, + 0.007388,0.000465,0.999973,0.071848,0.05689,-0.004818, + 0.070467,0.004433,0.997504,0.072001,0.056899,-0.004819, + 0.069355,0.01323,0.997504,0.071747,0.058911,-0.004819, + 0.007271,0.001387,0.999973,0.071597,0.058882,-0.004818, + 0.007344,0.000928,0.999973,0.071754,0.05789,-0.004818, + 0.069355,0.01323,0.997504,0.071747,0.058911,-0.004819, + 0.007344,0.000928,0.999973,0.071754,0.05789,-0.004818, + 0.070049,0.008849,0.997504,0.071906,0.057909,-0.004819, + 0.068388,0.017559,0.997504,0.071526,0.059901,-0.004819, + 0.00717,0.001841,0.999973,0.071377,0.059863,-0.004818, + 0.007271,0.001387,0.999973,0.071597,0.058882,-0.004818, + 0.068388,0.017559,0.997504,0.071526,0.059901,-0.004819, + 0.007271,0.001387,0.999973,0.071597,0.058882,-0.004818, + 0.069355,0.01323,0.997504,0.071747,0.058911,-0.004819, + 0.06715,0.021818,0.997504,0.071243,0.060875,-0.004819, + 0.00704,0.002287,0.999973,0.071097,0.060828,-0.004818, + 0.00717,0.001841,0.999973,0.071377,0.059863,-0.004818, + 0.06715,0.021818,0.997504,0.071243,0.060875,-0.004819, + 0.00717,0.001841,0.999973,0.071377,0.059863,-0.004818, + 0.068388,0.017559,0.997504,0.071526,0.059901,-0.004819, + 0.065648,0.025992,0.997504,0.070899,0.06183,-0.004819, + 0.006883,0.002725,0.999973,0.070757,0.061773,-0.004818, + 0.00704,0.002287,0.999973,0.071097,0.060828,-0.004818, + 0.065648,0.025992,0.997504,0.070899,0.06183,-0.004819, + 0.00704,0.002287,0.999973,0.071097,0.060828,-0.004818, + 0.06715,0.021818,0.997504,0.071243,0.060875,-0.004819, + 0.063886,0.030062,0.997504,0.070497,0.062761,-0.004819, + 0.006698,0.003152,0.999973,0.070358,0.062696,-0.004818, + 0.006883,0.002725,0.999973,0.070757,0.061773,-0.004818, + 0.063886,0.030062,0.997504,0.070497,0.062761,-0.004819, + 0.006883,0.002725,0.999973,0.070757,0.061773,-0.004818, + 0.065648,0.025992,0.997504,0.070899,0.06183,-0.004819, + 0.061872,0.034015,0.997504,0.070036,0.063665,-0.004819, + 0.006487,0.003566,0.999973,0.069902,0.063591,-0.004818, + 0.006698,0.003152,0.999973,0.070358,0.062696,-0.004818, + 0.061872,0.034015,0.997504,0.070036,0.063665,-0.004819, + 0.006698,0.003152,0.999973,0.070358,0.062696,-0.004818, + 0.063886,0.030062,0.997504,0.070497,0.062761,-0.004819, + 0.059614,0.037832,0.997504,0.06952,0.064538,-0.004819, + 0.00625,0.003966,0.999973,0.06939,0.064456,-0.004818, + 0.006487,0.003566,0.999973,0.069902,0.063591,-0.004818, + 0.059614,0.037832,0.997504,0.06952,0.064538,-0.004819, + 0.006487,0.003566,0.999973,0.069902,0.063591,-0.004818, + 0.061872,0.034015,0.997504,0.070036,0.063665,-0.004819, + 0.057121,0.041501,0.997504,0.068949,0.065377,-0.004819, + 0.005989,0.004351,0.999973,0.068825,0.065287,-0.004818, + 0.00625,0.003966,0.999973,0.06939,0.064456,-0.004818, + 0.057121,0.041501,0.997504,0.068949,0.065377,-0.004819, + 0.00625,0.003966,0.999973,0.06939,0.064456,-0.004818, + 0.059614,0.037832,0.997504,0.06952,0.064538,-0.004819, + 0.054403,0.045006,0.997504,0.068328,0.066178,-0.004819, + 0.005704,0.004718,0.999973,0.06821,0.066081,-0.004818, + 0.005989,0.004351,0.999973,0.068825,0.065287,-0.004818, + 0.054403,0.045006,0.997504,0.068328,0.066178,-0.004819, + 0.005989,0.004351,0.999973,0.068825,0.065287,-0.004818, + 0.057121,0.041501,0.997504,0.068949,0.065377,-0.004819, + 0.051469,0.048333,0.997504,0.067657,0.066939,-0.004819, + 0.005396,0.005067,0.999973,0.067545,0.066834,-0.004818, + 0.005704,0.004718,0.999973,0.06821,0.066081,-0.004818, + 0.051469,0.048333,0.997504,0.067657,0.066939,-0.004819, + 0.005704,0.004718,0.999973,0.06821,0.066081,-0.004818, + 0.054403,0.045006,0.997504,0.068328,0.066178,-0.004819, + 0.048333,0.051469,0.997504,0.066939,0.067657,-0.004819, + 0.005067,0.005396,0.999973,0.066834,0.067545,-0.004818, + 0.005396,0.005067,0.999973,0.067545,0.066834,-0.004818, + 0.048333,0.051469,0.997504,0.066939,0.067657,-0.004819, + 0.005396,0.005067,0.999973,0.067545,0.066834,-0.004818, + 0.051469,0.048333,0.997504,0.067657,0.066939,-0.004819, + 0.045006,0.054403,0.997504,0.066178,0.068328,-0.004819, + 0.004718,0.005704,0.999973,0.066081,0.06821,-0.004818, + 0.005067,0.005396,0.999973,0.066834,0.067545,-0.004818, + 0.045006,0.054403,0.997504,0.066178,0.068328,-0.004819, + 0.005067,0.005396,0.999973,0.066834,0.067545,-0.004818, + 0.048333,0.051469,0.997504,0.066939,0.067657,-0.004819, + 0.041501,0.057121,0.997504,0.065377,0.068949,-0.004819, + 0.004351,0.005989,0.999973,0.065287,0.068825,-0.004818, + 0.004718,0.005704,0.999973,0.066081,0.06821,-0.004818, + 0.041501,0.057121,0.997504,0.065377,0.068949,-0.004819, + 0.004718,0.005704,0.999973,0.066081,0.06821,-0.004818, + 0.045006,0.054403,0.997504,0.066178,0.068328,-0.004819, + 0.037832,0.059614,0.997504,0.064538,0.06952,-0.004819, + 0.003966,0.00625,0.999973,0.064456,0.06939,-0.004818, + 0.004351,0.005989,0.999973,0.065287,0.068825,-0.004818, + 0.037832,0.059614,0.997504,0.064538,0.06952,-0.004819, + 0.004351,0.005989,0.999973,0.065287,0.068825,-0.004818, + 0.041501,0.057121,0.997504,0.065377,0.068949,-0.004819, + 0.034015,0.061872,0.997504,0.063665,0.070036,-0.004819, + 0.003566,0.006487,0.999973,0.063591,0.069902,-0.004818, + 0.003966,0.00625,0.999973,0.064456,0.06939,-0.004818, + 0.034015,0.061872,0.997504,0.063665,0.070036,-0.004819, + 0.003966,0.00625,0.999973,0.064456,0.06939,-0.004818, + 0.037832,0.059614,0.997504,0.064538,0.06952,-0.004819, + 0.030062,0.063886,0.997504,0.062761,0.070497,-0.004819, + 0.003152,0.006698,0.999973,0.062696,0.070358,-0.004818, + 0.003566,0.006487,0.999973,0.063591,0.069902,-0.004818, + 0.030062,0.063886,0.997504,0.062761,0.070497,-0.004819, + 0.003566,0.006487,0.999973,0.063591,0.069902,-0.004818, + 0.034015,0.061872,0.997504,0.063665,0.070036,-0.004819, + 0.025992,0.065648,0.997504,0.06183,0.070899,-0.004819, + 0.002725,0.006883,0.999973,0.061773,0.070757,-0.004818, + 0.003152,0.006698,0.999973,0.062696,0.070358,-0.004818, + 0.025992,0.065648,0.997504,0.06183,0.070899,-0.004819, + 0.003152,0.006698,0.999973,0.062696,0.070358,-0.004818, + 0.030062,0.063886,0.997504,0.062761,0.070497,-0.004819, + 0.021818,0.06715,0.997504,0.060875,0.071243,-0.004819, + 0.002287,0.00704,0.999973,0.060828,0.071097,-0.004818, + 0.002725,0.006883,0.999973,0.061773,0.070757,-0.004818, + 0.021818,0.06715,0.997504,0.060875,0.071243,-0.004819, + 0.002725,0.006883,0.999973,0.061773,0.070757,-0.004818, + 0.025992,0.065648,0.997504,0.06183,0.070899,-0.004819, + 0.017559,0.068388,0.997504,0.059901,0.071526,-0.004819, + 0.001841,0.00717,0.999973,0.059863,0.071377,-0.004818, + 0.002287,0.00704,0.999973,0.060828,0.071097,-0.004818, + 0.017559,0.068388,0.997504,0.059901,0.071526,-0.004819, + 0.002287,0.00704,0.999973,0.060828,0.071097,-0.004818, + 0.021818,0.06715,0.997504,0.060875,0.071243,-0.004819, + 0.01323,0.069355,0.997504,0.058911,0.071747,-0.004819, + 0.001387,0.007271,0.999973,0.058882,0.071597,-0.004818, + 0.001841,0.00717,0.999973,0.059863,0.071377,-0.004818, + 0.01323,0.069355,0.997504,0.058911,0.071747,-0.004819, + 0.001841,0.00717,0.999973,0.059863,0.071377,-0.004818, + 0.017559,0.068388,0.997504,0.059901,0.071526,-0.004819, + 0.008849,0.070049,0.997504,0.057909,0.071906,-0.004819, + 0.000928,0.007344,0.999973,0.05789,0.071754,-0.004818, + 0.001387,0.007271,0.999973,0.058882,0.071597,-0.004818, + 0.008849,0.070049,0.997504,0.057909,0.071906,-0.004819, + 0.001387,0.007271,0.999973,0.058882,0.071597,-0.004818, + 0.01323,0.069355,0.997504,0.058911,0.071747,-0.004819, + 0.004433,0.070467,0.997504,0.056899,0.072001,-0.004819, + 0.000465,0.007388,0.999973,0.05689,0.071848,-0.004818, + 0.000928,0.007344,0.999973,0.05789,0.071754,-0.004818, + 0.004433,0.070467,0.997504,0.056899,0.072001,-0.004819, + 0.000928,0.007344,0.999973,0.05789,0.071754,-0.004818, + 0.008849,0.070049,0.997504,0.057909,0.071906,-0.004819, + 0,0.070606,0.997504,0.055885,0.072033,-0.004819, + 0,0.007402,0.999973,0.055885,0.07188,-0.004818, + 0.000465,0.007388,0.999973,0.05689,0.071848,-0.004818, + 0,0.070606,0.997504,0.055885,0.072033,-0.004819, + 0.000465,0.007388,0.999973,0.05689,0.071848,-0.004818, + 0.004433,0.070467,0.997504,0.056899,0.072001,-0.004819, + -0.004433,0.070467,0.997504,0.054871,0.072001,-0.004819, + -0.000465,0.007388,0.999973,0.054881,0.071848,-0.004818, + 0,0.007402,0.999973,0.055885,0.07188,-0.004818, + -0.004433,0.070467,0.997504,0.054871,0.072001,-0.004819, + 0,0.007402,0.999973,0.055885,0.07188,-0.004818, + 0,0.070606,0.997504,0.055885,0.072033,-0.004819, + -0.008849,0.070049,0.997504,0.053861,0.071906,-0.004819, + -0.000928,0.007344,0.999973,0.053881,0.071754,-0.004818, + -0.000465,0.007388,0.999973,0.054881,0.071848,-0.004818, + -0.008849,0.070049,0.997504,0.053861,0.071906,-0.004819, + -0.000465,0.007388,0.999973,0.054881,0.071848,-0.004818, + -0.004433,0.070467,0.997504,0.054871,0.072001,-0.004819, + -0.01323,0.069355,0.997504,0.052859,0.071747,-0.004819, + -0.001387,0.007271,0.999973,0.052888,0.071597,-0.004818, + -0.000928,0.007344,0.999973,0.053881,0.071754,-0.004818, + -0.01323,0.069355,0.997504,0.052859,0.071747,-0.004819, + -0.000928,0.007344,0.999973,0.053881,0.071754,-0.004818, + -0.008849,0.070049,0.997504,0.053861,0.071906,-0.004819, + -0.017559,0.068388,0.997504,0.051869,0.071526,-0.004819, + -0.001841,0.00717,0.999973,0.051908,0.071377,-0.004818, + -0.001387,0.007271,0.999973,0.052888,0.071597,-0.004818, + -0.017559,0.068388,0.997504,0.051869,0.071526,-0.004819, + -0.001387,0.007271,0.999973,0.052888,0.071597,-0.004818, + -0.01323,0.069355,0.997504,0.052859,0.071747,-0.004819, + -0.021818,0.06715,0.997504,0.050895,0.071243,-0.004819, + -0.002287,0.00704,0.999973,0.050943,0.071097,-0.004818, + -0.001841,0.00717,0.999973,0.051908,0.071377,-0.004818, + -0.021818,0.06715,0.997504,0.050895,0.071243,-0.004819, + -0.001841,0.00717,0.999973,0.051908,0.071377,-0.004818, + -0.017559,0.068388,0.997504,0.051869,0.071526,-0.004819, + -0.025992,0.065648,0.997504,0.049941,0.070899,-0.004819, + -0.002725,0.006883,0.999973,0.049997,0.070757,-0.004818, + -0.002287,0.00704,0.999973,0.050943,0.071097,-0.004818, + -0.025992,0.065648,0.997504,0.049941,0.070899,-0.004819, + -0.002287,0.00704,0.999973,0.050943,0.071097,-0.004818, + -0.021818,0.06715,0.997504,0.050895,0.071243,-0.004819, + -0.030062,0.063886,0.997504,0.04901,0.070497,-0.004819, + -0.003152,0.006698,0.999973,0.049075,0.070358,-0.004818, + -0.002725,0.006883,0.999973,0.049997,0.070757,-0.004818, + -0.030062,0.063886,0.997504,0.04901,0.070497,-0.004819, + -0.002725,0.006883,0.999973,0.049997,0.070757,-0.004818, + -0.025992,0.065648,0.997504,0.049941,0.070899,-0.004819, + -0.034015,0.061872,0.997504,0.048106,0.070036,-0.004819, + -0.003566,0.006487,0.999973,0.04818,0.069902,-0.004818, + -0.003152,0.006698,0.999973,0.049075,0.070358,-0.004818, + -0.034015,0.061872,0.997504,0.048106,0.070036,-0.004819, + -0.003152,0.006698,0.999973,0.049075,0.070358,-0.004818, + -0.030062,0.063886,0.997504,0.04901,0.070497,-0.004819, + -0.037832,0.059614,0.997504,0.047233,0.06952,-0.004819, + -0.003966,0.00625,0.999973,0.047315,0.06939,-0.004818, + -0.003566,0.006487,0.999973,0.04818,0.069902,-0.004818, + -0.037832,0.059614,0.997504,0.047233,0.06952,-0.004819, + -0.003566,0.006487,0.999973,0.04818,0.069902,-0.004818, + -0.034015,0.061872,0.997504,0.048106,0.070036,-0.004819, + -0.041501,0.057121,0.997504,0.046394,0.068949,-0.004819, + -0.004351,0.005989,0.999973,0.046484,0.068825,-0.004818, + -0.003966,0.00625,0.999973,0.047315,0.06939,-0.004818, + -0.041501,0.057121,0.997504,0.046394,0.068949,-0.004819, + -0.003966,0.00625,0.999973,0.047315,0.06939,-0.004818, + -0.037832,0.059614,0.997504,0.047233,0.06952,-0.004819, + -0.045006,0.054403,0.997504,0.045592,0.068328,-0.004819, + -0.004718,0.005704,0.999973,0.04569,0.06821,-0.004818, + -0.004351,0.005989,0.999973,0.046484,0.068825,-0.004818, + -0.045006,0.054403,0.997504,0.045592,0.068328,-0.004819, + -0.004351,0.005989,0.999973,0.046484,0.068825,-0.004818, + -0.041501,0.057121,0.997504,0.046394,0.068949,-0.004819, + -0.048333,0.051469,0.997504,0.044831,0.067657,-0.004819, + -0.005067,0.005396,0.999973,0.044936,0.067545,-0.004818, + -0.004718,0.005704,0.999973,0.04569,0.06821,-0.004818, + -0.048333,0.051469,0.997504,0.044831,0.067657,-0.004819, + -0.004718,0.005704,0.999973,0.04569,0.06821,-0.004818, + -0.045006,0.054403,0.997504,0.045592,0.068328,-0.004819, + -0.051469,0.048333,0.997504,0.044114,0.066939,-0.004819, + -0.005396,0.005067,0.999973,0.044226,0.066834,-0.004818, + -0.005067,0.005396,0.999973,0.044936,0.067545,-0.004818, + -0.051469,0.048333,0.997504,0.044114,0.066939,-0.004819, + -0.005067,0.005396,0.999973,0.044936,0.067545,-0.004818, + -0.048333,0.051469,0.997504,0.044831,0.067657,-0.004819, + -0.054403,0.045006,0.997504,0.043443,0.066178,-0.004819, + -0.005704,0.004718,0.999973,0.043561,0.066081,-0.004818, + -0.005396,0.005067,0.999973,0.044226,0.066834,-0.004818, + -0.054403,0.045006,0.997504,0.043443,0.066178,-0.004819, + -0.005396,0.005067,0.999973,0.044226,0.066834,-0.004818, + -0.051469,0.048333,0.997504,0.044114,0.066939,-0.004819, + -0.057121,0.041501,0.997504,0.042821,0.065377,-0.004819, + -0.005989,0.004351,0.999973,0.042945,0.065287,-0.004818, + -0.005704,0.004718,0.999973,0.043561,0.066081,-0.004818, + -0.057121,0.041501,0.997504,0.042821,0.065377,-0.004819, + -0.005704,0.004718,0.999973,0.043561,0.066081,-0.004818, + -0.054403,0.045006,0.997504,0.043443,0.066178,-0.004819, + -0.059614,0.037832,0.997504,0.042251,0.064538,-0.004819, + -0.00625,0.003966,0.999973,0.042381,0.064456,-0.004818, + -0.005989,0.004351,0.999973,0.042945,0.065287,-0.004818, + -0.059614,0.037832,0.997504,0.042251,0.064538,-0.004819, + -0.005989,0.004351,0.999973,0.042945,0.065287,-0.004818, + -0.057121,0.041501,0.997504,0.042821,0.065377,-0.004819, + -0.061872,0.034015,0.997504,0.041735,0.063665,-0.004819, + -0.006487,0.003566,0.999973,0.041869,0.063591,-0.004818, + -0.00625,0.003966,0.999973,0.042381,0.064456,-0.004818, + -0.061872,0.034015,0.997504,0.041735,0.063665,-0.004819, + -0.00625,0.003966,0.999973,0.042381,0.064456,-0.004818, + -0.059614,0.037832,0.997504,0.042251,0.064538,-0.004819, + -0.063886,0.030062,0.997504,0.041274,0.062761,-0.004819, + -0.006698,0.003152,0.999973,0.041413,0.062696,-0.004818, + -0.006487,0.003566,0.999973,0.041869,0.063591,-0.004818, + -0.063886,0.030062,0.997504,0.041274,0.062761,-0.004819, + -0.006487,0.003566,0.999973,0.041869,0.063591,-0.004818, + -0.061872,0.034015,0.997504,0.041735,0.063665,-0.004819, + -0.006698,0.003152,0.999973,0.041413,0.062696,-0.004818, + 0,0,1,0.044613,0.063997,-0.004818, + -0.006487,0.003566,0.999973,0.041869,0.063591,-0.004818, + -0.006698,0.003152,0.999973,0.041413,0.062696,-0.004818, + 0,0,1,0.043898,0.062655,-0.004818, + 0,0,1,0.044613,0.063997,-0.004818, + -0.006883,0.002725,0.999973,0.041014,0.061773,-0.004818, + 0,0,1,0.043898,0.062655,-0.004818, + -0.006698,0.003152,0.999973,0.041413,0.062696,-0.004818, + -0.006883,0.002725,0.999973,0.041014,0.061773,-0.004818, + 0,0,1,0.043489,0.061186,-0.004818, + 0,0,1,0.043898,0.062655,-0.004818, + -0.00704,0.002287,0.999973,0.040673,0.060828,-0.004818, + 0,0,1,0.043489,0.061186,-0.004818, + -0.006883,0.002725,0.999973,0.041014,0.061773,-0.004818, + -0.00717,0.001841,0.999973,0.040393,0.059863,-0.004818, + 0,0,1,0.043489,0.061186,-0.004818, + -0.00704,0.002287,0.999973,0.040673,0.060828,-0.004818, + -0.00717,0.001841,0.999973,0.040393,0.059863,-0.004818, + 0,0,1,0.043409,0.05966,-0.004818, + 0,0,1,0.043489,0.061186,-0.004818, + -0.007271,0.001387,0.999973,0.040174,0.058882,-0.004818, + 0,0,1,0.043409,0.05966,-0.004818, + -0.00717,0.001841,0.999973,0.040393,0.059863,-0.004818, + -0.007271,0.001387,0.999973,0.040174,0.058882,-0.004818, + 0,0,1,0.043472,0.058741,-0.004818, + 0,0,1,0.043409,0.05966,-0.004818, + -0.007344,0.000928,0.999973,0.040017,0.05789,-0.004818, + 0,0,1,0.043472,0.058741,-0.004818, + -0.007271,0.001387,0.999973,0.040174,0.058882,-0.004818, + -0.007344,0.000928,0.999973,0.040017,0.05789,-0.004818, + 0,0,1,0.04361,0.057831,-0.004818, + 0,0,1,0.043472,0.058741,-0.004818, + -0.007344,0.000928,0.999973,0.040017,0.05789,-0.004818, + 0,0,1,0.043821,0.056936,-0.004818, + 0,0,1,0.04361,0.057831,-0.004818, + -0.007388,0.000465,0.999973,0.039922,0.05689,-0.004818, + 0,0,1,0.043821,0.056936,-0.004818, + -0.007344,0.000928,0.999973,0.040017,0.05789,-0.004818, + -0.007388,0.000465,0.999973,0.039922,0.05689,-0.004818, + 0,0,1,0.044105,0.056061,-0.004818, + 0,0,1,0.043821,0.056936,-0.004818, + -0.007402,0,0.999973,0.039891,0.055885,-0.004818, + 0,0,1,0.044105,0.056061,-0.004818, + -0.007388,0.000465,0.999973,0.039922,0.05689,-0.004818, + -0.007402,0,0.999973,0.039891,0.055885,-0.004818, + 0,0,1,0.044458,0.055214,-0.004818, + 0,0,1,0.044105,0.056061,-0.004818, + -0.007388,-0.000465,0.999973,0.039922,0.054881,-0.004818, + 0,0,1,0.044458,0.055214,-0.004818, + -0.007402,0,0.999973,0.039891,0.055885,-0.004818, + -0.007388,-0.000465,0.999973,0.039922,0.054881,-0.004818, + 0,0,1,0.044879,0.054399,-0.004818, + 0,0,1,0.044458,0.055214,-0.004818, + -0.007344,-0.000928,0.999973,0.040017,0.053881,-0.004818, + 0,0,1,0.044879,0.054399,-0.004818, + -0.007388,-0.000465,0.999973,0.039922,0.054881,-0.004818, + -0.007344,-0.000928,0.999973,0.040017,0.053881,-0.004818, + 0,0,1,0.045365,0.053623,-0.004818, + 0,0,1,0.044879,0.054399,-0.004818, + -0.007344,-0.000928,0.999973,0.040017,0.053881,-0.004818, + 0,0,1,0.045912,0.05289,-0.004818, + 0,0,1,0.045365,0.053623,-0.004818, + -0.007271,-0.001387,0.999973,0.040174,0.052888,-0.004818, + 0,0,1,0.045912,0.05289,-0.004818, + -0.007344,-0.000928,0.999973,0.040017,0.053881,-0.004818, + -0.007271,-0.001387,0.999973,0.040174,0.052888,-0.004818, + 0,0,1,0.046517,0.052206,-0.004818, + 0,0,1,0.045912,0.05289,-0.004818, + -0.00717,-0.001841,0.999973,0.040393,0.051908,-0.004818, + 0,0,1,0.046517,0.052206,-0.004818, + -0.007271,-0.001387,0.999973,0.040174,0.052888,-0.004818, + -0.00717,-0.001841,0.999973,0.040393,0.051908,-0.004818, + 0,0,1,0.047175,0.051576,-0.004818, + 0,0,1,0.046517,0.052206,-0.004818, + -0.00717,-0.001841,0.999973,0.040393,0.051908,-0.004818, + 0,0,1,0.047882,0.051003,-0.004818, + 0,0,1,0.047175,0.051576,-0.004818, + -0.00704,-0.002287,0.999973,0.040673,0.050943,-0.004818, + 0,0,1,0.047882,0.051003,-0.004818, + -0.00717,-0.001841,0.999973,0.040393,0.051908,-0.004818, + -0.00704,-0.002287,0.999973,0.040673,0.050943,-0.004818, + 0,0,1,0.048634,0.050493,-0.004818, + 0,0,1,0.047882,0.051003,-0.004818, + -0.00704,-0.002287,0.999973,0.040673,0.050943,-0.004818, + 0,0,1,0.049354,0.050026,-0.004818, + 0,0,1,0.048634,0.050493,-0.004818, + -0.006883,-0.002725,0.999973,0.041014,0.049997,-0.004818, + 0,0,1,0.049354,0.050026,-0.004818, + -0.00704,-0.002287,0.999973,0.040673,0.050943,-0.004818, + -0.006883,-0.002725,0.999973,0.041014,0.049997,-0.004818, + 0,0,1,0.050057,0.049532,-0.004818, + 0,0,1,0.049354,0.050026,-0.004818, + -0.006698,-0.003152,0.999973,0.041413,0.049075,-0.004818, + 0,0,1,0.050057,0.049532,-0.004818, + -0.006883,-0.002725,0.999973,0.041014,0.049997,-0.004818, + -0.006698,-0.003152,0.999973,0.041413,0.049075,-0.004818, + 0,0,1,0.050741,0.049011,-0.004818, + 0,0,1,0.050057,0.049532,-0.004818, + -0.006698,-0.003152,0.999973,0.041413,0.049075,-0.004818, + 0,0,1,0.051404,0.048464,-0.004818, + 0,0,1,0.050741,0.049011,-0.004818, + -0.006487,-0.003566,0.999973,0.041869,0.04818,-0.004818, + 0,0,1,0.051404,0.048464,-0.004818, + -0.006698,-0.003152,0.999973,0.041413,0.049075,-0.004818, + -0.006487,-0.003566,0.999973,0.041869,0.04818,-0.004818, + 0,0,1,0.052047,0.047891,-0.004818, + 0,0,1,0.051404,0.048464,-0.004818, + -0.00625,-0.003966,0.999973,0.042381,0.047315,-0.004818, + 0,0,1,0.052047,0.047891,-0.004818, + -0.006487,-0.003566,0.999973,0.041869,0.04818,-0.004818, + -0.00625,-0.003966,0.999973,0.042381,0.047315,-0.004818, + 0,0,1,0.052668,0.047293,-0.004818, + 0,0,1,0.052047,0.047891,-0.004818, + -0.00625,-0.003966,0.999973,0.042381,0.047315,-0.004818, + 0,0,1,0.053266,0.046673,-0.004818, + 0,0,1,0.052668,0.047293,-0.004818, + -0.005989,-0.004351,0.999973,0.042945,0.046484,-0.004818, + 0,0,1,0.053266,0.046673,-0.004818, + -0.00625,-0.003966,0.999973,0.042381,0.047315,-0.004818, + -0.005989,-0.004351,0.999973,0.042945,0.046484,-0.004818, + 0,0,1,0.05384,0.046029,-0.004818, + 0,0,1,0.053266,0.046673,-0.004818, + -0.005704,-0.004718,0.999973,0.043561,0.04569,-0.004818, + 0,0,1,0.05384,0.046029,-0.004818, + -0.005989,-0.004351,0.999973,0.042945,0.046484,-0.004818, + -0.005704,-0.004718,0.999973,0.043561,0.04569,-0.004818, + 0,0,1,0.05439,0.045363,-0.004818, + 0,0,1,0.05384,0.046029,-0.004818, + -0.005396,-0.005067,0.999973,0.044226,0.044936,-0.004818, + 0,0,1,0.05439,0.045363,-0.004818, + -0.005704,-0.004718,0.999973,0.043561,0.04569,-0.004818, + -0.005396,-0.005067,0.999973,0.044226,0.044936,-0.004818, + 0,0,1,0.054915,0.044676,-0.004818, + 0,0,1,0.05439,0.045363,-0.004818, + -0.005067,-0.005396,0.999973,0.044936,0.044226,-0.004818, + 0,0,1,0.054915,0.044676,-0.004818, + -0.005396,-0.005067,0.999973,0.044226,0.044936,-0.004818, + -0.005067,-0.005396,0.999973,0.044936,0.044226,-0.004818, + 0,0,1,0.055414,0.04397,-0.004818, + 0,0,1,0.054915,0.044676,-0.004818, + -0.004718,-0.005704,0.999973,0.04569,0.043561,-0.004818, + 0,0,1,0.055414,0.04397,-0.004818, + -0.005067,-0.005396,0.999973,0.044936,0.044226,-0.004818, + -0.004718,-0.005704,0.999973,0.04569,0.043561,-0.004818, + 0,0,1,0.055885,0.043244,-0.004818, + 0,0,1,0.055414,0.04397,-0.004818, + -0.004718,-0.005704,0.999973,0.04569,0.043561,-0.004818, + 0.004351,-0.005989,0.999973,0.065287,0.042945,-0.004818, + 0,0,1,0.055885,0.043244,-0.004818, + -0.004351,-0.005989,0.999973,0.046484,0.042945,-0.004818, + 0.004351,-0.005989,0.999973,0.065287,0.042945,-0.004818, + -0.004718,-0.005704,0.999973,0.04569,0.043561,-0.004818, + -0.004351,-0.005989,0.999973,0.046484,0.042945,-0.004818, + 0.003966,-0.00625,0.999973,0.064456,0.042381,-0.004818, + 0.004351,-0.005989,0.999973,0.065287,0.042945,-0.004818, + -0.003966,-0.00625,0.999973,0.047315,0.042381,-0.004818, + 0.003966,-0.00625,0.999973,0.064456,0.042381,-0.004818, + -0.004351,-0.005989,0.999973,0.046484,0.042945,-0.004818, + -0.003966,-0.00625,0.999973,0.047315,0.042381,-0.004818, + 0.003566,-0.006487,0.999973,0.063591,0.041869,-0.004818, + 0.003966,-0.00625,0.999973,0.064456,0.042381,-0.004818, + -0.003566,-0.006487,0.999973,0.04818,0.041869,-0.004818, + 0.003566,-0.006487,0.999973,0.063591,0.041869,-0.004818, + -0.003966,-0.00625,0.999973,0.047315,0.042381,-0.004818, + -0.003566,-0.006487,0.999973,0.04818,0.041869,-0.004818, + 0.003152,-0.006698,0.999973,0.062696,0.041413,-0.004818, + 0.003566,-0.006487,0.999973,0.063591,0.041869,-0.004818, + -0.003152,-0.006698,0.999973,0.049075,0.041413,-0.004818, + 0.003152,-0.006698,0.999973,0.062696,0.041413,-0.004818, + -0.003566,-0.006487,0.999973,0.04818,0.041869,-0.004818, + -0.003152,-0.006698,0.999973,0.049075,0.041413,-0.004818, + 0.002725,-0.006883,0.999973,0.061773,0.041014,-0.004818, + 0.003152,-0.006698,0.999973,0.062696,0.041413,-0.004818, + -0.002725,-0.006883,0.999973,0.049997,0.041014,-0.004818, + 0.002725,-0.006883,0.999973,0.061773,0.041014,-0.004818, + -0.003152,-0.006698,0.999973,0.049075,0.041413,-0.004818, + -0.002725,-0.006883,0.999973,0.049997,0.041014,-0.004818, + 0.002287,-0.00704,0.999973,0.060828,0.040673,-0.004818, + 0.002725,-0.006883,0.999973,0.061773,0.041014,-0.004818, + -0.002287,-0.00704,0.999973,0.050943,0.040673,-0.004818, + 0.002287,-0.00704,0.999973,0.060828,0.040673,-0.004818, + -0.002725,-0.006883,0.999973,0.049997,0.041014,-0.004818, + -0.002287,-0.00704,0.999973,0.050943,0.040673,-0.004818, + 0.001841,-0.00717,0.999973,0.059863,0.040393,-0.004818, + 0.002287,-0.00704,0.999973,0.060828,0.040673,-0.004818, + -0.001841,-0.00717,0.999973,0.051908,0.040393,-0.004818, + 0.001841,-0.00717,0.999973,0.059863,0.040393,-0.004818, + -0.002287,-0.00704,0.999973,0.050943,0.040673,-0.004818, + -0.001841,-0.00717,0.999973,0.051908,0.040393,-0.004818, + 0.001387,-0.007271,0.999973,0.058882,0.040174,-0.004818, + 0.001841,-0.00717,0.999973,0.059863,0.040393,-0.004818, + -0.001387,-0.007271,0.999973,0.052888,0.040174,-0.004818, + 0.001387,-0.007271,0.999973,0.058882,0.040174,-0.004818, + -0.001841,-0.00717,0.999973,0.051908,0.040393,-0.004818, + -0.001387,-0.007271,0.999973,0.052888,0.040174,-0.004818, + 0.000928,-0.007344,0.999973,0.05789,0.040017,-0.004818, + 0.001387,-0.007271,0.999973,0.058882,0.040174,-0.004818, + -0.000928,-0.007344,0.999973,0.053881,0.040017,-0.004818, + 0.000928,-0.007344,0.999973,0.05789,0.040017,-0.004818, + -0.001387,-0.007271,0.999973,0.052888,0.040174,-0.004818, + -0.000928,-0.007344,0.999973,0.053881,0.040017,-0.004818, + 0.000465,-0.007388,0.999973,0.05689,0.039922,-0.004818, + 0.000928,-0.007344,0.999973,0.05789,0.040017,-0.004818, + -0.000465,-0.007388,0.999973,0.054881,0.039922,-0.004818, + 0.000465,-0.007388,0.999973,0.05689,0.039922,-0.004818, + -0.000928,-0.007344,0.999973,0.053881,0.040017,-0.004818, + 0.000465,-0.007388,0.999973,0.05689,0.039922,-0.004818, + -0.000465,-0.007388,0.999973,0.054881,0.039922,-0.004818, + 0,-0.007402,0.999973,0.055885,0.039891,-0.004818, + 0.004718,-0.005704,0.999973,0.066081,0.043561,-0.004818, + 0,0,1,0.055885,0.043244,-0.004818, + 0.004351,-0.005989,0.999973,0.065287,0.042945,-0.004818, + 0,0,1,0.055885,0.043244,-0.004818, + 0.004718,-0.005704,0.999973,0.066081,0.043561,-0.004818, + 0,0,1,0.056357,0.04397,-0.004818, + 0,0,1,0.056357,0.04397,-0.004818, + 0.004718,-0.005704,0.999973,0.066081,0.043561,-0.004818, + 0.005067,-0.005396,0.999973,0.066834,0.044226,-0.004818, + 0,0,1,0.056357,0.04397,-0.004818, + 0.005067,-0.005396,0.999973,0.066834,0.044226,-0.004818, + 0,0,1,0.056856,0.044676,-0.004818, + 0,0,1,0.056856,0.044676,-0.004818, + 0.005067,-0.005396,0.999973,0.066834,0.044226,-0.004818, + 0.005396,-0.005067,0.999973,0.067545,0.044936,-0.004818, + 0,0,1,0.056856,0.044676,-0.004818, + 0.005396,-0.005067,0.999973,0.067545,0.044936,-0.004818, + 0,0,1,0.05738,0.045363,-0.004818, + 0,0,1,0.05738,0.045363,-0.004818, + 0.005396,-0.005067,0.999973,0.067545,0.044936,-0.004818, + 0.005704,-0.004718,0.999973,0.06821,0.04569,-0.004818, + 0,0,1,0.05738,0.045363,-0.004818, + 0.005704,-0.004718,0.999973,0.06821,0.04569,-0.004818, + 0,0,1,0.05793,0.046029,-0.004818, + 0,0,1,0.05793,0.046029,-0.004818, + 0.005704,-0.004718,0.999973,0.06821,0.04569,-0.004818, + 0.005989,-0.004351,0.999973,0.068825,0.046484,-0.004818, + 0,0,1,0.05793,0.046029,-0.004818, + 0.005989,-0.004351,0.999973,0.068825,0.046484,-0.004818, + 0,0,1,0.058505,0.046673,-0.004818, + 0,0,1,0.058505,0.046673,-0.004818, + 0.005989,-0.004351,0.999973,0.068825,0.046484,-0.004818, + 0.00625,-0.003966,0.999973,0.06939,0.047315,-0.004818, + 0,0,1,0.058505,0.046673,-0.004818, + 0.00625,-0.003966,0.999973,0.06939,0.047315,-0.004818, + 0,0,1,0.059103,0.047293,-0.004818, + 0,0,1,0.059103,0.047293,-0.004818, + 0.00625,-0.003966,0.999973,0.06939,0.047315,-0.004818, + 0,0,1,0.059724,0.047891,-0.004818, + 0,0,1,0.059724,0.047891,-0.004818, + 0.00625,-0.003966,0.999973,0.06939,0.047315,-0.004818, + 0.006487,-0.003566,0.999973,0.069902,0.04818,-0.004818, + 0,0,1,0.059724,0.047891,-0.004818, + 0.006487,-0.003566,0.999973,0.069902,0.04818,-0.004818, + 0,0,1,0.060366,0.048464,-0.004818, + 0,0,1,0.060366,0.048464,-0.004818, + 0.006487,-0.003566,0.999973,0.069902,0.04818,-0.004818, + 0.006698,-0.003152,0.999973,0.070358,0.049075,-0.004818, + 0,0,1,0.060366,0.048464,-0.004818, + 0.006698,-0.003152,0.999973,0.070358,0.049075,-0.004818, + 0,0,1,0.06103,0.049011,-0.004818, + 0,0,1,0.06103,0.049011,-0.004818, + 0.006698,-0.003152,0.999973,0.070358,0.049075,-0.004818, + 0,0,1,0.061714,0.049532,-0.004818, + 0,0,1,0.061714,0.049532,-0.004818, + 0.006698,-0.003152,0.999973,0.070358,0.049075,-0.004818, + 0.006883,-0.002725,0.999973,0.070757,0.049997,-0.004818, + 0,0,1,0.061714,0.049532,-0.004818, + 0.006883,-0.002725,0.999973,0.070757,0.049997,-0.004818, + 0,0,1,0.062416,0.050026,-0.004818, + 0,0,1,0.062416,0.050026,-0.004818, + 0.006883,-0.002725,0.999973,0.070757,0.049997,-0.004818, + 0.00704,-0.002287,0.999973,0.071097,0.050943,-0.004818, + 0,0,1,0.062416,0.050026,-0.004818, + 0.00704,-0.002287,0.999973,0.071097,0.050943,-0.004818, + 0,0,1,0.063137,0.050493,-0.004818, + 0,0,1,0.063137,0.050493,-0.004818, + 0.00704,-0.002287,0.999973,0.071097,0.050943,-0.004818, + 0,0,1,0.063888,0.051003,-0.004818, + 0,0,1,0.063888,0.051003,-0.004818, + 0.00704,-0.002287,0.999973,0.071097,0.050943,-0.004818, + 0.00717,-0.001841,0.999973,0.071377,0.051908,-0.004818, + 0,0,1,0.063888,0.051003,-0.004818, + 0.00717,-0.001841,0.999973,0.071377,0.051908,-0.004818, + 0,0,1,0.064596,0.051576,-0.004818, + 0,0,1,0.064596,0.051576,-0.004818, + 0.00717,-0.001841,0.999973,0.071377,0.051908,-0.004818, + 0,0,1,0.065254,0.052206,-0.004818, + 0,0,1,0.065254,0.052206,-0.004818, + 0.00717,-0.001841,0.999973,0.071377,0.051908,-0.004818, + 0.007271,-0.001387,0.999973,0.071597,0.052888,-0.004818, + 0,0,1,0.065254,0.052206,-0.004818, + 0.007271,-0.001387,0.999973,0.071597,0.052888,-0.004818, + 0,0,1,0.065859,0.05289,-0.004818, + 0,0,1,0.065859,0.05289,-0.004818, + 0.007271,-0.001387,0.999973,0.071597,0.052888,-0.004818, + 0.007344,-0.000928,0.999973,0.071754,0.053881,-0.004818, + 0,0,1,0.065859,0.05289,-0.004818, + 0.007344,-0.000928,0.999973,0.071754,0.053881,-0.004818, + 0,0,1,0.066406,0.053623,-0.004818, + 0,0,1,0.066406,0.053623,-0.004818, + 0.007344,-0.000928,0.999973,0.071754,0.053881,-0.004818, + 0,0,1,0.066892,0.054399,-0.004818, + 0,0,1,0.066892,0.054399,-0.004818, + 0.007344,-0.000928,0.999973,0.071754,0.053881,-0.004818, + 0.007388,-0.000465,0.999973,0.071848,0.054881,-0.004818, + 0,0,1,0.066892,0.054399,-0.004818, + 0.007388,-0.000465,0.999973,0.071848,0.054881,-0.004818, + 0,0,1,0.067313,0.055214,-0.004818, + 0,0,1,0.067313,0.055214,-0.004818, + 0.007388,-0.000465,0.999973,0.071848,0.054881,-0.004818, + 0.007402,0,0.999973,0.07188,0.055885,-0.004818, + 0,0,1,0.067313,0.055214,-0.004818, + 0.007402,0,0.999973,0.07188,0.055885,-0.004818, + 0,0,1,0.067666,0.056061,-0.004818, + 0,0,1,0.067666,0.056061,-0.004818, + 0.007402,0,0.999973,0.07188,0.055885,-0.004818, + 0.007388,0.000465,0.999973,0.071848,0.05689,-0.004818, + 0,0,1,0.067666,0.056061,-0.004818, + 0.007388,0.000465,0.999973,0.071848,0.05689,-0.004818, + 0,0,1,0.067949,0.056936,-0.004818, + 0,0,1,0.067949,0.056936,-0.004818, + 0.007388,0.000465,0.999973,0.071848,0.05689,-0.004818, + 0.007344,0.000928,0.999973,0.071754,0.05789,-0.004818, + 0,0,1,0.067949,0.056936,-0.004818, + 0.007344,0.000928,0.999973,0.071754,0.05789,-0.004818, + 0,0,1,0.068161,0.057831,-0.004818, + 0,0,1,0.068161,0.057831,-0.004818, + 0.007344,0.000928,0.999973,0.071754,0.05789,-0.004818, + 0,0,1,0.068298,0.058741,-0.004818, + 0,0,1,0.068298,0.058741,-0.004818, + 0.007344,0.000928,0.999973,0.071754,0.05789,-0.004818, + 0.007271,0.001387,0.999973,0.071597,0.058882,-0.004818, + 0,0,1,0.068298,0.058741,-0.004818, + 0.007271,0.001387,0.999973,0.071597,0.058882,-0.004818, + 0,0,1,0.068362,0.05966,-0.004818, + 0,0,1,0.068362,0.05966,-0.004818, + 0.007271,0.001387,0.999973,0.071597,0.058882,-0.004818, + 0.00717,0.001841,0.999973,0.071377,0.059863,-0.004818, + 0,0,1,0.068362,0.05966,-0.004818, + 0.00717,0.001841,0.999973,0.071377,0.059863,-0.004818, + 0,0,1,0.068281,0.061186,-0.004818, + 0,0,1,0.068281,0.061186,-0.004818, + 0.00717,0.001841,0.999973,0.071377,0.059863,-0.004818, + 0.00704,0.002287,0.999973,0.071097,0.060828,-0.004818, + 0,0,1,0.068281,0.061186,-0.004818, + 0.00704,0.002287,0.999973,0.071097,0.060828,-0.004818, + 0.006883,0.002725,0.999973,0.070757,0.061773,-0.004818, + 0,0,1,0.068281,0.061186,-0.004818, + 0.006883,0.002725,0.999973,0.070757,0.061773,-0.004818, + 0,0,1,0.067873,0.062655,-0.004818, + 0,0,1,0.067873,0.062655,-0.004818, + 0.006883,0.002725,0.999973,0.070757,0.061773,-0.004818, + 0.006698,0.003152,0.999973,0.070358,0.062696,-0.004818, + 0,0,1,0.067873,0.062655,-0.004818, + 0.006698,0.003152,0.999973,0.070358,0.062696,-0.004818, + 0,0,1,0.067158,0.063997,-0.004818, + 0,0,1,0.067158,0.063997,-0.004818, + 0.006698,0.003152,0.999973,0.070358,0.062696,-0.004818, + 0.006487,0.003566,0.999973,0.069902,0.063591,-0.004818, + 0,0,1,0.067158,0.063997,-0.004818, + 0.006487,0.003566,0.999973,0.069902,0.063591,-0.004818, + 0.00625,0.003966,0.999973,0.06939,0.064456,-0.004818, + 0,0,1,0.067158,0.063997,-0.004818, + 0.00625,0.003966,0.999973,0.06939,0.064456,-0.004818, + 0,0,1,0.06617,0.065145,-0.004818, + 0,0,1,0.06617,0.065145,-0.004818, + 0.00625,0.003966,0.999973,0.06939,0.064456,-0.004818, + 0.005989,0.004351,0.999973,0.068825,0.065287,-0.004818, + 0,0,1,0.06617,0.065145,-0.004818, + 0.005989,0.004351,0.999973,0.068825,0.065287,-0.004818, + 0,0,1,0.064959,0.066043,-0.004818, + 0,0,1,0.064959,0.066043,-0.004818, + 0.005989,0.004351,0.999973,0.068825,0.065287,-0.004818, + 0.005704,0.004718,0.999973,0.06821,0.066081,-0.004818, + 0,0,1,0.064959,0.066043,-0.004818, + 0.005704,0.004718,0.999973,0.06821,0.066081,-0.004818, + 0,0,1,0.063583,0.066646,-0.004818, + 0,0,1,0.063583,0.066646,-0.004818, + 0.005704,0.004718,0.999973,0.06821,0.066081,-0.004818, + 0.005396,0.005067,0.999973,0.067545,0.066834,-0.004818, + 0,0,1,0.063583,0.066646,-0.004818, + 0.005396,0.005067,0.999973,0.067545,0.066834,-0.004818, + 0,0,1,0.06211,0.066926,-0.004818, + 0,0,1,0.06211,0.066926,-0.004818, + 0.005396,0.005067,0.999973,0.067545,0.066834,-0.004818, + 0.005067,0.005396,0.999973,0.066834,0.067545,-0.004818, + 0,0,1,0.06211,0.066926,-0.004818, + 0.005067,0.005396,0.999973,0.066834,0.067545,-0.004818, + -0.005067,0.005396,0.999973,0.044936,0.067545,-0.004818, + -0.005067,0.005396,0.999973,0.044936,0.067545,-0.004818, + 0.005067,0.005396,0.999973,0.066834,0.067545,-0.004818, + -0.004718,0.005704,0.999973,0.04569,0.06821,-0.004818, + -0.004718,0.005704,0.999973,0.04569,0.06821,-0.004818, + 0.005067,0.005396,0.999973,0.066834,0.067545,-0.004818, + 0.004718,0.005704,0.999973,0.066081,0.06821,-0.004818, + -0.004718,0.005704,0.999973,0.04569,0.06821,-0.004818, + 0.004718,0.005704,0.999973,0.066081,0.06821,-0.004818, + -0.004351,0.005989,0.999973,0.046484,0.068825,-0.004818, + -0.004351,0.005989,0.999973,0.046484,0.068825,-0.004818, + 0.004718,0.005704,0.999973,0.066081,0.06821,-0.004818, + 0.004351,0.005989,0.999973,0.065287,0.068825,-0.004818, + -0.004351,0.005989,0.999973,0.046484,0.068825,-0.004818, + 0.004351,0.005989,0.999973,0.065287,0.068825,-0.004818, + -0.003966,0.00625,0.999973,0.047315,0.06939,-0.004818, + -0.003966,0.00625,0.999973,0.047315,0.06939,-0.004818, + 0.004351,0.005989,0.999973,0.065287,0.068825,-0.004818, + 0.003966,0.00625,0.999973,0.064456,0.06939,-0.004818, + -0.003966,0.00625,0.999973,0.047315,0.06939,-0.004818, + 0.003966,0.00625,0.999973,0.064456,0.06939,-0.004818, + -0.003566,0.006487,0.999973,0.04818,0.069902,-0.004818, + -0.003566,0.006487,0.999973,0.04818,0.069902,-0.004818, + 0.003966,0.00625,0.999973,0.064456,0.06939,-0.004818, + 0.003566,0.006487,0.999973,0.063591,0.069902,-0.004818, + -0.003566,0.006487,0.999973,0.04818,0.069902,-0.004818, + 0.003566,0.006487,0.999973,0.063591,0.069902,-0.004818, + 0.003152,0.006698,0.999973,0.062696,0.070358,-0.004818, + -0.003566,0.006487,0.999973,0.04818,0.069902,-0.004818, + 0.003152,0.006698,0.999973,0.062696,0.070358,-0.004818, + -0.003152,0.006698,0.999973,0.049075,0.070358,-0.004818, + -0.003152,0.006698,0.999973,0.049075,0.070358,-0.004818, + 0.003152,0.006698,0.999973,0.062696,0.070358,-0.004818, + -0.002725,0.006883,0.999973,0.049997,0.070757,-0.004818, + -0.002725,0.006883,0.999973,0.049997,0.070757,-0.004818, + 0.003152,0.006698,0.999973,0.062696,0.070358,-0.004818, + 0.002725,0.006883,0.999973,0.061773,0.070757,-0.004818, + -0.002725,0.006883,0.999973,0.049997,0.070757,-0.004818, + 0.002725,0.006883,0.999973,0.061773,0.070757,-0.004818, + -0.002287,0.00704,0.999973,0.050943,0.071097,-0.004818, + -0.002287,0.00704,0.999973,0.050943,0.071097,-0.004818, + 0.002725,0.006883,0.999973,0.061773,0.070757,-0.004818, + 0.002287,0.00704,0.999973,0.060828,0.071097,-0.004818, + -0.002287,0.00704,0.999973,0.050943,0.071097,-0.004818, + 0.002287,0.00704,0.999973,0.060828,0.071097,-0.004818, + -0.001841,0.00717,0.999973,0.051908,0.071377,-0.004818, + -0.001841,0.00717,0.999973,0.051908,0.071377,-0.004818, + 0.002287,0.00704,0.999973,0.060828,0.071097,-0.004818, + 0.001841,0.00717,0.999973,0.059863,0.071377,-0.004818, + -0.001841,0.00717,0.999973,0.051908,0.071377,-0.004818, + 0.001841,0.00717,0.999973,0.059863,0.071377,-0.004818, + 0.001387,0.007271,0.999973,0.058882,0.071597,-0.004818, + -0.001841,0.00717,0.999973,0.051908,0.071377,-0.004818, + 0.001387,0.007271,0.999973,0.058882,0.071597,-0.004818, + -0.001387,0.007271,0.999973,0.052888,0.071597,-0.004818, + -0.001387,0.007271,0.999973,0.052888,0.071597,-0.004818, + 0.001387,0.007271,0.999973,0.058882,0.071597,-0.004818, + -0.000928,0.007344,0.999973,0.053881,0.071754,-0.004818, + -0.000928,0.007344,0.999973,0.053881,0.071754,-0.004818, + 0.001387,0.007271,0.999973,0.058882,0.071597,-0.004818, + 0.000928,0.007344,0.999973,0.05789,0.071754,-0.004818, + -0.000928,0.007344,0.999973,0.053881,0.071754,-0.004818, + 0.000928,0.007344,0.999973,0.05789,0.071754,-0.004818, + -0.000465,0.007388,0.999973,0.054881,0.071848,-0.004818, + -0.000465,0.007388,0.999973,0.054881,0.071848,-0.004818, + 0.000928,0.007344,0.999973,0.05789,0.071754,-0.004818, + 0.000465,0.007388,0.999973,0.05689,0.071848,-0.004818, + -0.000465,0.007388,0.999973,0.054881,0.071848,-0.004818, + 0.000465,0.007388,0.999973,0.05689,0.071848,-0.004818, + 0,0.007402,0.999973,0.055885,0.07188,-0.004818, + -0.005067,0.005396,0.999973,0.044936,0.067545,-0.004818, + 0,0,1,0.04966,0.066926,-0.004818, + 0,0,1,0.06211,0.066926,-0.004818, + -0.005396,0.005067,0.999973,0.044226,0.066834,-0.004818, + 0,0,1,0.04966,0.066926,-0.004818, + -0.005067,0.005396,0.999973,0.044936,0.067545,-0.004818, + -0.005396,0.005067,0.999973,0.044226,0.066834,-0.004818, + 0,0,1,0.048188,0.066646,-0.004818, + 0,0,1,0.04966,0.066926,-0.004818, + -0.005704,0.004718,0.999973,0.043561,0.066081,-0.004818, + 0,0,1,0.048188,0.066646,-0.004818, + -0.005396,0.005067,0.999973,0.044226,0.066834,-0.004818, + -0.005704,0.004718,0.999973,0.043561,0.066081,-0.004818, + 0,0,1,0.046812,0.066043,-0.004818, + 0,0,1,0.048188,0.066646,-0.004818, + -0.005989,0.004351,0.999973,0.042945,0.065287,-0.004818, + 0,0,1,0.046812,0.066043,-0.004818, + -0.005704,0.004718,0.999973,0.043561,0.066081,-0.004818, + -0.005989,0.004351,0.999973,0.042945,0.065287,-0.004818, + 0,0,1,0.0456,0.065145,-0.004818, + 0,0,1,0.046812,0.066043,-0.004818, + -0.00625,0.003966,0.999973,0.042381,0.064456,-0.004818, + 0,0,1,0.0456,0.065145,-0.004818, + -0.005989,0.004351,0.999973,0.042945,0.065287,-0.004818, + -0.00625,0.003966,0.999973,0.042381,0.064456,-0.004818, + 0,0,1,0.044613,0.063997,-0.004818, + 0,0,1,0.0456,0.065145,-0.004818, + -0.006487,0.003566,0.999973,0.041869,0.063591,-0.004818, + 0,0,1,0.044613,0.063997,-0.004818, + -0.00625,0.003966,0.999973,0.042381,0.064456,-0.004818, + 0,0,1,0.04966,0.066926,-0.004818, + 0,0,1,0.060613,0.066867,-0.004818, + 0,0,1,0.06211,0.066926,-0.004818, + 0,0,1,0.051157,0.066867,-0.004818, + 0,0,1,0.060613,0.066867,-0.004818, + 0,0,1,0.04966,0.066926,-0.004818, + 0,0,1,0.051157,0.066867,-0.004818, + 0,0,1,0.059165,0.066474,-0.004818, + 0,0,1,0.060613,0.066867,-0.004818, + 0,0,1,0.052605,0.066474,-0.004818, + 0,0,1,0.059165,0.066474,-0.004818, + 0,0,1,0.051157,0.066867,-0.004818, + 0,0,1,0.052605,0.066474,-0.004818, + 0,0,1,0.057837,0.065766,-0.004818, + 0,0,1,0.059165,0.066474,-0.004818, + 0,0,1,0.053934,0.065766,-0.004818, + 0,0,1,0.057837,0.065766,-0.004818, + 0,0,1,0.052605,0.066474,-0.004818, + 0,0,1,0.053934,0.065766,-0.004818, + 0,0,1,0.056739,0.064761,-0.004818, + 0,0,1,0.057837,0.065766,-0.004818, + 0,0,1,0.055031,0.064761,-0.004818, + 0,0,1,0.056739,0.064761,-0.004818, + 0,0,1,0.053934,0.065766,-0.004818, + 0,0,1,0.056739,0.064761,-0.004818, + 0,0,1,0.055031,0.064761,-0.004818, + 0,0,1,0.055885,0.063727,-0.004818, + -0.929776,-0.368125,0,0.03976,0.049501,-0.007708, + -0.929762,-0.368119,0.005552,0.03976,0.049501,-0.006167, + -0.951042,-0.309012,0.005552,0.03939,0.050526,-0.006167, + -0.929776,-0.368125,0,0.03976,0.049501,-0.007708, + -0.951042,-0.309012,0.005552,0.03939,0.050526,-0.006167, + -0.951057,-0.309017,0,0.03939,0.050526,-0.007708, + -0.904827,-0.425779,0,0.040192,0.048501,-0.007708, + -0.904813,-0.425773,0.005552,0.040192,0.048501,-0.006167, + -0.929762,-0.368119,0.005552,0.03976,0.049501,-0.006167, + -0.904827,-0.425779,0,0.040192,0.048501,-0.007708, + -0.929762,-0.368119,0.005552,0.03976,0.049501,-0.006167, + -0.929776,-0.368125,0,0.03976,0.049501,-0.007708, + -0.876307,-0.481754,0,0.040687,0.04753,-0.007708, + -0.876293,-0.481746,0.005552,0.040687,0.04753,-0.006167, + -0.904813,-0.425773,0.005552,0.040192,0.048501,-0.006167, + -0.876307,-0.481754,0,0.040687,0.04753,-0.007708, + -0.904813,-0.425773,0.005552,0.040192,0.048501,-0.006167, + -0.904827,-0.425779,0,0.040192,0.048501,-0.007708, + -0.844328,-0.535827,0,0.041241,0.046592,-0.007708, + -0.844315,-0.535819,0.005552,0.041241,0.046592,-0.006167, + -0.876293,-0.481746,0.005552,0.040687,0.04753,-0.006167, + -0.844328,-0.535827,0,0.041241,0.046592,-0.007708, + -0.876293,-0.481746,0.005552,0.040687,0.04753,-0.006167, + -0.876307,-0.481754,0,0.040687,0.04753,-0.007708, + -0.844328,-0.535827,0,0.041241,0.046592,-0.007708, + -0.876307,-0.481754,0,0.040687,0.04753,-0.007708, + -0.860742,-0.509041,0,0.040845,0.047263,-0.007708, + -0.844328,-0.535827,0,0.041241,0.046592,-0.007708, + -0.860742,-0.509041,0,0.040845,0.047263,-0.007708, + -0.860742,-0.509041,0,0.040904,0.047163,-0.007708, + -0.809017,-0.587785,0,0.041854,0.045691,-0.007708, + -0.809005,-0.587776,0.005552,0.041854,0.045691,-0.006167, + -0.844315,-0.535819,0.005552,0.041241,0.046592,-0.006167, + -0.809017,-0.587785,0,0.041854,0.045691,-0.007708, + -0.844315,-0.535819,0.005552,0.041241,0.046592,-0.006167, + -0.844328,-0.535827,0,0.041241,0.046592,-0.007708, + -0.770513,-0.637424,0,0.042522,0.04483,-0.007708, + -0.770501,-0.637414,0.005552,0.042522,0.04483,-0.006167, + -0.809005,-0.587776,0.005552,0.041854,0.045691,-0.006167, + -0.770513,-0.637424,0,0.042522,0.04483,-0.007708, + -0.809005,-0.587776,0.005552,0.041854,0.045691,-0.006167, + -0.809017,-0.587785,0,0.041854,0.045691,-0.007708, + -0.728969,-0.684547,0,0.043242,0.044013,-0.007708, + -0.728957,-0.684537,0.005552,0.043242,0.044013,-0.006167, + -0.770501,-0.637414,0.005552,0.042522,0.04483,-0.006167, + -0.728969,-0.684547,0,0.043242,0.044013,-0.007708, + -0.770501,-0.637414,0.005552,0.042522,0.04483,-0.006167, + -0.770513,-0.637424,0,0.042522,0.04483,-0.007708, + -0.684547,-0.728969,0,0.044013,0.043242,-0.007708, + -0.684537,-0.728957,0.005552,0.044013,0.043242,-0.006167, + -0.728957,-0.684537,0.005552,0.043242,0.044013,-0.006167, + -0.684547,-0.728969,0,0.044013,0.043242,-0.007708, + -0.728957,-0.684537,0.005552,0.043242,0.044013,-0.006167, + -0.728969,-0.684547,0,0.043242,0.044013,-0.007708, + -0.684547,-0.728969,0,0.044013,0.043242,-0.007708, + -0.728969,-0.684547,0,0.043242,0.044013,-0.007708, + -0.707107,-0.707107,0,0.043581,0.043673,-0.007708, + -0.684547,-0.728969,0,0.044013,0.043242,-0.007708, + -0.707107,-0.707107,0,0.043581,0.043673,-0.007708, + -0.707107,-0.707107,0,0.043673,0.043581,-0.007708, + -0.637424,-0.770513,0,0.04483,0.042522,-0.007708, + -0.637414,-0.770501,0.005552,0.04483,0.042522,-0.006167, + -0.684537,-0.728957,0.005552,0.044013,0.043242,-0.006167, + -0.637424,-0.770513,0,0.04483,0.042522,-0.007708, + -0.684537,-0.728957,0.005552,0.044013,0.043242,-0.006167, + -0.684547,-0.728969,0,0.044013,0.043242,-0.007708, + -0.587785,-0.809017,0,0.045691,0.041854,-0.007708, + -0.587776,-0.809005,0.005552,0.045691,0.041854,-0.006167, + -0.637414,-0.770501,0.005552,0.04483,0.042522,-0.006167, + -0.587785,-0.809017,0,0.045691,0.041854,-0.007708, + -0.637414,-0.770501,0.005552,0.04483,0.042522,-0.006167, + -0.637424,-0.770513,0,0.04483,0.042522,-0.007708, + -0.535827,-0.844328,0,0.046592,0.041241,-0.007708, + -0.535819,-0.844315,0.005552,0.046592,0.041241,-0.006167, + -0.587776,-0.809005,0.005552,0.045691,0.041854,-0.006167, + -0.535827,-0.844328,0,0.046592,0.041241,-0.007708, + -0.587776,-0.809005,0.005552,0.045691,0.041854,-0.006167, + -0.587785,-0.809017,0,0.045691,0.041854,-0.007708, + -0.481754,-0.876307,0,0.04753,0.040687,-0.007708, + -0.481746,-0.876293,0.005552,0.04753,0.040687,-0.006167, + -0.535819,-0.844315,0.005552,0.046592,0.041241,-0.006167, + -0.481754,-0.876307,0,0.04753,0.040687,-0.007708, + -0.535819,-0.844315,0.005552,0.046592,0.041241,-0.006167, + -0.535827,-0.844328,0,0.046592,0.041241,-0.007708, + -0.481754,-0.876307,0,0.04753,0.040687,-0.007708, + -0.535827,-0.844328,0,0.046592,0.041241,-0.007708, + -0.509041,-0.860742,0,0.047163,0.040904,-0.007708, + -0.481754,-0.876307,0,0.04753,0.040687,-0.007708, + -0.509041,-0.860742,0,0.047163,0.040904,-0.007708, + -0.509041,-0.860742,0,0.047263,0.040845,-0.007708, + -0.425779,-0.904827,0,0.048501,0.040192,-0.007708, + -0.425773,-0.904813,0.005552,0.048501,0.040192,-0.006167, + -0.481746,-0.876293,0.005552,0.04753,0.040687,-0.006167, + -0.425779,-0.904827,0,0.048501,0.040192,-0.007708, + -0.481746,-0.876293,0.005552,0.04753,0.040687,-0.006167, + -0.481754,-0.876307,0,0.04753,0.040687,-0.007708, + -0.368125,-0.929776,0,0.049501,0.03976,-0.007708, + -0.368119,-0.929762,0.005552,0.049501,0.03976,-0.006167, + -0.425773,-0.904813,0.005552,0.048501,0.040192,-0.006167, + -0.368125,-0.929776,0,0.049501,0.03976,-0.007708, + -0.425773,-0.904813,0.005552,0.048501,0.040192,-0.006167, + -0.425779,-0.904827,0,0.048501,0.040192,-0.007708, + -0.309017,-0.951057,0,0.050526,0.03939,-0.007708, + -0.309012,-0.951042,0.005552,0.050526,0.03939,-0.006167, + -0.368119,-0.929762,0.005552,0.049501,0.03976,-0.006167, + -0.309017,-0.951057,0,0.050526,0.03939,-0.007708, + -0.368119,-0.929762,0.005552,0.049501,0.03976,-0.006167, + -0.368125,-0.929776,0,0.049501,0.03976,-0.007708, + -0.24869,-0.968583,0,0.051572,0.039087,-0.007708, + -0.248686,-0.968568,0.005552,0.051572,0.039087,-0.006167, + -0.309012,-0.951042,0.005552,0.050526,0.03939,-0.006167, + -0.24869,-0.968583,0,0.051572,0.039087,-0.007708, + -0.309012,-0.951042,0.005552,0.050526,0.03939,-0.006167, + -0.309017,-0.951057,0,0.050526,0.03939,-0.007708, + -0.24869,-0.968583,0,0.051572,0.039087,-0.007708, + -0.309017,-0.951057,0,0.050526,0.03939,-0.007708, + -0.278991,-0.960294,0,0.051356,0.039149,-0.007708, + -0.24869,-0.968583,0,0.051572,0.039087,-0.007708, + -0.278991,-0.960294,0,0.051356,0.039149,-0.007708, + -0.278991,-0.960294,0,0.051428,0.039128,-0.007708, + -0.187381,-0.982287,0,0.052635,0.038849,-0.007708, + -0.187378,-0.982272,0.005552,0.052635,0.038849,-0.006167, + -0.248686,-0.968568,0.005552,0.051572,0.039087,-0.006167, + -0.187381,-0.982287,0,0.052635,0.038849,-0.007708, + -0.248686,-0.968568,0.005552,0.051572,0.039087,-0.006167, + -0.24869,-0.968583,0,0.051572,0.039087,-0.007708, + -0.125333,-0.992115,0,0.053712,0.038678,-0.007708, + -0.125331,-0.992099,0.005552,0.053712,0.038678,-0.006167, + -0.187378,-0.982272,0.005552,0.052635,0.038849,-0.006167, + -0.125333,-0.992115,0,0.053712,0.038678,-0.007708, + -0.187378,-0.982272,0.005552,0.052635,0.038849,-0.006167, + -0.187381,-0.982287,0,0.052635,0.038849,-0.007708, + -0.094108,-0.995562,0,0.054796,0.038576,-0.007708, + -0.07324,-0.997287,0.007402,0.054796,0.038576,-0.006167, + -0.125331,-0.992099,0.005552,0.053712,0.038678,-0.006167, + -0.094108,-0.995562,0,0.054796,0.038576,-0.007708, + -0.125331,-0.992099,0.005552,0.053712,0.038678,-0.006167, + -0.125333,-0.992115,0,0.053712,0.038678,-0.007708, + -0.951057,-0.309017,0,0.03939,0.050526,-0.007708, + -0.951042,-0.309012,0.005552,0.03939,0.050526,-0.006167, + -0.968568,-0.248686,0.005552,0.039087,0.051572,-0.006167, + -0.951057,-0.309017,0,0.03939,0.050526,-0.007708, + -0.968568,-0.248686,0.005552,0.039087,0.051572,-0.006167, + -0.968583,-0.24869,0,0.039087,0.051572,-0.007708, + -0.951057,-0.309017,0,0.03939,0.050526,-0.007708, + -0.968583,-0.24869,0,0.039087,0.051572,-0.007708, + -0.960294,-0.278991,0,0.039128,0.051428,-0.007708, + -0.951057,-0.309017,0,0.03939,0.050526,-0.007708, + -0.960294,-0.278991,0,0.039128,0.051428,-0.007708, + -0.960294,-0.278991,0,0.039149,0.051356,-0.007708, + -0.968583,-0.24869,0,0.039087,0.051572,-0.007708, + -0.968568,-0.248686,0.005552,0.039087,0.051572,-0.006167, + -0.982272,-0.187378,0.005552,0.038849,0.052635,-0.006167, + -0.968583,-0.24869,0,0.039087,0.051572,-0.007708, + -0.982272,-0.187378,0.005552,0.038849,0.052635,-0.006167, + -0.982287,-0.187381,0,0.038849,0.052635,-0.007708, + -0.982287,-0.187381,0,0.038849,0.052635,-0.007708, + -0.982272,-0.187378,0.005552,0.038849,0.052635,-0.006167, + -0.992099,-0.125331,0.005552,0.038678,0.053712,-0.006167, + -0.982287,-0.187381,0,0.038849,0.052635,-0.007708, + -0.992099,-0.125331,0.005552,0.038678,0.053712,-0.006167, + -0.992115,-0.125333,0,0.038678,0.053712,-0.007708, + -0.992115,-0.125333,0,0.038678,0.053712,-0.007708, + -0.992099,-0.125331,0.005552,0.038678,0.053712,-0.006167, + -0.997287,-0.07324,0.007402,0.038576,0.054796,-0.006167, + -0.992115,-0.125333,0,0.038678,0.053712,-0.007708, + -0.997287,-0.07324,0.007402,0.038576,0.054796,-0.006167, + -0.995562,-0.094108,0,0.038576,0.054796,-0.007708, + -0.995562,0.094108,0,0.038576,0.056974,-0.007708, + -0.997287,0.07324,0.007402,0.038576,0.056974,-0.006167, + -0.992099,0.125331,0.005552,0.038678,0.058059,-0.006167, + -0.995562,0.094108,0,0.038576,0.056974,-0.007708, + -0.992099,0.125331,0.005552,0.038678,0.058059,-0.006167, + -0.992115,0.125333,0,0.038678,0.058059,-0.007708, + -0.992115,0.125333,0,0.038678,0.058059,-0.007708, + -0.992099,0.125331,0.005552,0.038678,0.058059,-0.006167, + -0.982272,0.187378,0.005552,0.038849,0.059135,-0.006167, + -0.992115,0.125333,0,0.038678,0.058059,-0.007708, + -0.982272,0.187378,0.005552,0.038849,0.059135,-0.006167, + -0.982287,0.187381,0,0.038849,0.059135,-0.007708, + -0.982287,0.187381,0,0.038849,0.059135,-0.007708, + -0.982272,0.187378,0.005552,0.038849,0.059135,-0.006167, + -0.968568,0.248686,0.005552,0.039087,0.060198,-0.006167, + -0.982287,0.187381,0,0.038849,0.059135,-0.007708, + -0.968568,0.248686,0.005552,0.039087,0.060198,-0.006167, + -0.968583,0.24869,0,0.039087,0.060198,-0.007708, + -0.968583,0.24869,0,0.039087,0.060198,-0.007708, + -0.968568,0.248686,0.005552,0.039087,0.060198,-0.006167, + -0.951042,0.309012,0.005552,0.03939,0.061245,-0.006167, + -0.968583,0.24869,0,0.039087,0.060198,-0.007708, + -0.951042,0.309012,0.005552,0.03939,0.061245,-0.006167, + -0.951057,0.309017,0,0.03939,0.061245,-0.007708, + -0.968583,0.24869,0,0.039087,0.060198,-0.007708, + -0.951057,0.309017,0,0.03939,0.061245,-0.007708, + -0.960294,0.278991,0,0.039149,0.060414,-0.007708, + -0.968583,0.24869,0,0.039087,0.060198,-0.007708, + -0.960294,0.278991,0,0.039149,0.060414,-0.007708, + -0.960294,0.278991,0,0.039128,0.060343,-0.007708, + -0.951057,0.309017,0,0.03939,0.061245,-0.007708, + -0.951042,0.309012,0.005552,0.03939,0.061245,-0.006167, + -0.929762,0.368119,0.005552,0.03976,0.06227,-0.006167, + -0.951057,0.309017,0,0.03939,0.061245,-0.007708, + -0.929762,0.368119,0.005552,0.03976,0.06227,-0.006167, + -0.929776,0.368125,0,0.03976,0.06227,-0.007708, + -0.929776,0.368125,0,0.03976,0.06227,-0.007708, + -0.929762,0.368119,0.005552,0.03976,0.06227,-0.006167, + -0.904813,0.425773,0.005552,0.040192,0.06327,-0.006167, + -0.929776,0.368125,0,0.03976,0.06227,-0.007708, + -0.904813,0.425773,0.005552,0.040192,0.06327,-0.006167, + -0.904827,0.425779,0,0.040192,0.06327,-0.007708, + -0.904827,0.425779,0,0.040192,0.06327,-0.007708, + -0.904813,0.425773,0.005552,0.040192,0.06327,-0.006167, + -0.876293,0.481746,0.005552,0.040687,0.064241,-0.006167, + -0.904827,0.425779,0,0.040192,0.06327,-0.007708, + -0.876293,0.481746,0.005552,0.040687,0.064241,-0.006167, + -0.876307,0.481754,0,0.040687,0.064241,-0.007708, + -0.876307,0.481754,0,0.040687,0.064241,-0.007708, + -0.876293,0.481746,0.005552,0.040687,0.064241,-0.006167, + -0.844315,0.535819,0.005552,0.041241,0.065178,-0.006167, + -0.876307,0.481754,0,0.040687,0.064241,-0.007708, + -0.844315,0.535819,0.005552,0.041241,0.065178,-0.006167, + -0.844328,0.535827,0,0.041241,0.065178,-0.007708, + -0.876307,0.481754,0,0.040687,0.064241,-0.007708, + -0.844328,0.535827,0,0.041241,0.065178,-0.007708, + -0.860742,0.509041,0,0.040904,0.064607,-0.007708, + -0.876307,0.481754,0,0.040687,0.064241,-0.007708, + -0.860742,0.509041,0,0.040904,0.064607,-0.007708, + -0.860742,0.509041,0,0.040845,0.064507,-0.007708, + -0.844328,0.535827,0,0.041241,0.065178,-0.007708, + -0.844315,0.535819,0.005552,0.041241,0.065178,-0.006167, + -0.809005,0.587776,0.005552,0.041854,0.06608,-0.006167, + -0.844328,0.535827,0,0.041241,0.065178,-0.007708, + -0.809005,0.587776,0.005552,0.041854,0.06608,-0.006167, + -0.809017,0.587785,0,0.041854,0.06608,-0.007708, + -0.809017,0.587785,0,0.041854,0.06608,-0.007708, + -0.809005,0.587776,0.005552,0.041854,0.06608,-0.006167, + -0.770501,0.637414,0.005552,0.042522,0.066941,-0.006167, + -0.809017,0.587785,0,0.041854,0.06608,-0.007708, + -0.770501,0.637414,0.005552,0.042522,0.066941,-0.006167, + -0.770513,0.637424,0,0.042522,0.066941,-0.007708, + -0.770513,0.637424,0,0.042522,0.066941,-0.007708, + -0.770501,0.637414,0.005552,0.042522,0.066941,-0.006167, + -0.728957,0.684537,0.005552,0.043242,0.067758,-0.006167, + -0.770513,0.637424,0,0.042522,0.066941,-0.007708, + -0.728957,0.684537,0.005552,0.043242,0.067758,-0.006167, + -0.728969,0.684547,0,0.043242,0.067758,-0.007708, + -0.728969,0.684547,0,0.043242,0.067758,-0.007708, + -0.728957,0.684537,0.005552,0.043242,0.067758,-0.006167, + -0.684537,0.728957,0.005552,0.044013,0.068528,-0.006167, + -0.728969,0.684547,0,0.043242,0.067758,-0.007708, + -0.684537,0.728957,0.005552,0.044013,0.068528,-0.006167, + -0.684547,0.728969,0,0.044013,0.068528,-0.007708, + -0.728969,0.684547,0,0.043242,0.067758,-0.007708, + -0.684547,0.728969,0,0.044013,0.068528,-0.007708, + -0.707107,0.707107,0,0.043673,0.068189,-0.007708, + -0.728969,0.684547,0,0.043242,0.067758,-0.007708, + -0.707107,0.707107,0,0.043673,0.068189,-0.007708, + -0.707107,0.707107,0,0.043581,0.068097,-0.007708, + -0.684547,0.728969,0,0.044013,0.068528,-0.007708, + -0.684537,0.728957,0.005552,0.044013,0.068528,-0.006167, + -0.637414,0.770501,0.005552,0.04483,0.069249,-0.006167, + -0.684547,0.728969,0,0.044013,0.068528,-0.007708, + -0.637414,0.770501,0.005552,0.04483,0.069249,-0.006167, + -0.637424,0.770513,0,0.04483,0.069249,-0.007708, + -0.637424,0.770513,0,0.04483,0.069249,-0.007708, + -0.637414,0.770501,0.005552,0.04483,0.069249,-0.006167, + -0.587776,0.809005,0.005552,0.045691,0.069917,-0.006167, + -0.637424,0.770513,0,0.04483,0.069249,-0.007708, + -0.587776,0.809005,0.005552,0.045691,0.069917,-0.006167, + -0.587785,0.809017,0,0.045691,0.069917,-0.007708, + -0.587785,0.809017,0,0.045691,0.069917,-0.007708, + -0.587776,0.809005,0.005552,0.045691,0.069917,-0.006167, + -0.535819,0.844315,0.005552,0.046592,0.070529,-0.006167, + -0.587785,0.809017,0,0.045691,0.069917,-0.007708, + -0.535819,0.844315,0.005552,0.046592,0.070529,-0.006167, + -0.535827,0.844328,0,0.046592,0.070529,-0.007708, + -0.535827,0.844328,0,0.046592,0.070529,-0.007708, + -0.535819,0.844315,0.005552,0.046592,0.070529,-0.006167, + -0.481746,0.876293,0.005552,0.04753,0.071084,-0.006167, + -0.535827,0.844328,0,0.046592,0.070529,-0.007708, + -0.481746,0.876293,0.005552,0.04753,0.071084,-0.006167, + -0.481754,0.876307,0,0.04753,0.071084,-0.007708, + -0.535827,0.844328,0,0.046592,0.070529,-0.007708, + -0.481754,0.876307,0,0.04753,0.071084,-0.007708, + -0.509041,0.860742,0,0.047263,0.070926,-0.007708, + -0.535827,0.844328,0,0.046592,0.070529,-0.007708, + -0.509041,0.860742,0,0.047263,0.070926,-0.007708, + -0.509041,0.860742,0,0.047163,0.070867,-0.007708, + -0.481754,0.876307,0,0.04753,0.071084,-0.007708, + -0.481746,0.876293,0.005552,0.04753,0.071084,-0.006167, + -0.425773,0.904813,0.005552,0.048501,0.071578,-0.006167, + -0.481754,0.876307,0,0.04753,0.071084,-0.007708, + -0.425773,0.904813,0.005552,0.048501,0.071578,-0.006167, + -0.425779,0.904827,0,0.048501,0.071578,-0.007708, + -0.425779,0.904827,0,0.048501,0.071578,-0.007708, + -0.425773,0.904813,0.005552,0.048501,0.071578,-0.006167, + -0.368119,0.929762,0.005552,0.049501,0.072011,-0.006167, + -0.425779,0.904827,0,0.048501,0.071578,-0.007708, + -0.368119,0.929762,0.005552,0.049501,0.072011,-0.006167, + -0.368125,0.929776,0,0.049501,0.072011,-0.007708, + -0.368125,0.929776,0,0.049501,0.072011,-0.007708, + -0.368119,0.929762,0.005552,0.049501,0.072011,-0.006167, + -0.309012,0.951042,0.005552,0.050526,0.07238,-0.006167, + -0.368125,0.929776,0,0.049501,0.072011,-0.007708, + -0.309012,0.951042,0.005552,0.050526,0.07238,-0.006167, + -0.309017,0.951057,0,0.050526,0.07238,-0.007708, + -0.309017,0.951057,0,0.050526,0.07238,-0.007708, + -0.309012,0.951042,0.005552,0.050526,0.07238,-0.006167, + -0.248686,0.968568,0.005552,0.051572,0.072684,-0.006167, + -0.309017,0.951057,0,0.050526,0.07238,-0.007708, + -0.248686,0.968568,0.005552,0.051572,0.072684,-0.006167, + -0.24869,0.968583,0,0.051572,0.072684,-0.007708, + -0.309017,0.951057,0,0.050526,0.07238,-0.007708, + -0.24869,0.968583,0,0.051572,0.072684,-0.007708, + -0.278991,0.960294,0,0.051428,0.072642,-0.007708, + -0.309017,0.951057,0,0.050526,0.07238,-0.007708, + -0.278991,0.960294,0,0.051428,0.072642,-0.007708, + -0.278991,0.960294,0,0.051356,0.072621,-0.007708, + -0.24869,0.968583,0,0.051572,0.072684,-0.007708, + -0.248686,0.968568,0.005552,0.051572,0.072684,-0.006167, + -0.187378,0.982272,0.005552,0.052635,0.072922,-0.006167, + -0.24869,0.968583,0,0.051572,0.072684,-0.007708, + -0.187378,0.982272,0.005552,0.052635,0.072922,-0.006167, + -0.187381,0.982287,0,0.052635,0.072922,-0.007708, + -0.187381,0.982287,0,0.052635,0.072922,-0.007708, + -0.187378,0.982272,0.005552,0.052635,0.072922,-0.006167, + -0.125331,0.992099,0.005552,0.053712,0.073092,-0.006167, + -0.187381,0.982287,0,0.052635,0.072922,-0.007708, + -0.125331,0.992099,0.005552,0.053712,0.073092,-0.006167, + -0.125333,0.992115,0,0.053712,0.073092,-0.007708, + -0.125333,0.992115,0,0.053712,0.073092,-0.007708, + -0.125331,0.992099,0.005552,0.053712,0.073092,-0.006167, + -0.07324,0.997287,0.007402,0.054796,0.073195,-0.006167, + -0.125333,0.992115,0,0.053712,0.073092,-0.007708, + -0.07324,0.997287,0.007402,0.054796,0.073195,-0.006167, + -0.094108,0.995562,0,0.054796,0.073195,-0.007708, + 0.094108,0.995562,0,0.056974,0.073195,-0.007708, + 0.07324,0.997287,0.007402,0.056974,0.073195,-0.006167, + 0.125331,0.992099,0.005552,0.058059,0.073092,-0.006167, + 0.094108,0.995562,0,0.056974,0.073195,-0.007708, + 0.125331,0.992099,0.005552,0.058059,0.073092,-0.006167, + 0.125333,0.992115,0,0.058059,0.073092,-0.007708, + 0.125333,0.992115,0,0.058059,0.073092,-0.007708, + 0.125331,0.992099,0.005552,0.058059,0.073092,-0.006167, + 0.187378,0.982272,0.005552,0.059135,0.072922,-0.006167, + 0.125333,0.992115,0,0.058059,0.073092,-0.007708, + 0.187378,0.982272,0.005552,0.059135,0.072922,-0.006167, + 0.187381,0.982287,0,0.059135,0.072922,-0.007708, + 0.187381,0.982287,0,0.059135,0.072922,-0.007708, + 0.187378,0.982272,0.005552,0.059135,0.072922,-0.006167, + 0.248686,0.968568,0.005552,0.060198,0.072684,-0.006167, + 0.187381,0.982287,0,0.059135,0.072922,-0.007708, + 0.248686,0.968568,0.005552,0.060198,0.072684,-0.006167, + 0.24869,0.968583,0,0.060198,0.072684,-0.007708, + 0.24869,0.968583,0,0.060198,0.072684,-0.007708, + 0.248686,0.968568,0.005552,0.060198,0.072684,-0.006167, + 0.309012,0.951042,0.005552,0.061245,0.07238,-0.006167, + 0.24869,0.968583,0,0.060198,0.072684,-0.007708, + 0.309012,0.951042,0.005552,0.061245,0.07238,-0.006167, + 0.309017,0.951057,0,0.061245,0.07238,-0.007708, + 0.24869,0.968583,0,0.060198,0.072684,-0.007708, + 0.309017,0.951057,0,0.061245,0.07238,-0.007708, + 0.278991,0.960294,0,0.060414,0.072621,-0.007708, + 0.24869,0.968583,0,0.060198,0.072684,-0.007708, + 0.278991,0.960294,0,0.060414,0.072621,-0.007708, + 0.278991,0.960294,0,0.060343,0.072642,-0.007708, + 0.309017,0.951057,0,0.061245,0.07238,-0.007708, + 0.309012,0.951042,0.005552,0.061245,0.07238,-0.006167, + 0.368119,0.929762,0.005552,0.06227,0.072011,-0.006167, + 0.309017,0.951057,0,0.061245,0.07238,-0.007708, + 0.368119,0.929762,0.005552,0.06227,0.072011,-0.006167, + 0.368125,0.929776,0,0.06227,0.072011,-0.007708, + 0.368125,0.929776,0,0.06227,0.072011,-0.007708, + 0.368119,0.929762,0.005552,0.06227,0.072011,-0.006167, + 0.425773,0.904813,0.005552,0.06327,0.071578,-0.006167, + 0.368125,0.929776,0,0.06227,0.072011,-0.007708, + 0.425773,0.904813,0.005552,0.06327,0.071578,-0.006167, + 0.425779,0.904827,0,0.06327,0.071578,-0.007708, + 0.425779,0.904827,0,0.06327,0.071578,-0.007708, + 0.425773,0.904813,0.005552,0.06327,0.071578,-0.006167, + 0.481746,0.876293,0.005552,0.064241,0.071084,-0.006167, + 0.425779,0.904827,0,0.06327,0.071578,-0.007708, + 0.481746,0.876293,0.005552,0.064241,0.071084,-0.006167, + 0.481754,0.876307,0,0.064241,0.071084,-0.007708, + 0.481754,0.876307,0,0.064241,0.071084,-0.007708, + 0.481746,0.876293,0.005552,0.064241,0.071084,-0.006167, + 0.535819,0.844315,0.005552,0.065178,0.070529,-0.006167, + 0.481754,0.876307,0,0.064241,0.071084,-0.007708, + 0.535819,0.844315,0.005552,0.065178,0.070529,-0.006167, + 0.535827,0.844328,0,0.065178,0.070529,-0.007708, + 0.481754,0.876307,0,0.064241,0.071084,-0.007708, + 0.535827,0.844328,0,0.065178,0.070529,-0.007708, + 0.509041,0.860742,0,0.064607,0.070867,-0.007708, + 0.481754,0.876307,0,0.064241,0.071084,-0.007708, + 0.509041,0.860742,0,0.064607,0.070867,-0.007708, + 0.509041,0.860742,0,0.064507,0.070926,-0.007708, + 0.535827,0.844328,0,0.065178,0.070529,-0.007708, + 0.535819,0.844315,0.005552,0.065178,0.070529,-0.006167, + 0.587776,0.809005,0.005552,0.06608,0.069917,-0.006167, + 0.535827,0.844328,0,0.065178,0.070529,-0.007708, + 0.587776,0.809005,0.005552,0.06608,0.069917,-0.006167, + 0.587785,0.809017,0,0.06608,0.069917,-0.007708, + 0.587785,0.809017,0,0.06608,0.069917,-0.007708, + 0.587776,0.809005,0.005552,0.06608,0.069917,-0.006167, + 0.637414,0.770501,0.005552,0.066941,0.069249,-0.006167, + 0.587785,0.809017,0,0.06608,0.069917,-0.007708, + 0.637414,0.770501,0.005552,0.066941,0.069249,-0.006167, + 0.637424,0.770513,0,0.066941,0.069249,-0.007708, + 0.637424,0.770513,0,0.066941,0.069249,-0.007708, + 0.637414,0.770501,0.005552,0.066941,0.069249,-0.006167, + 0.684537,0.728957,0.005552,0.067758,0.068528,-0.006167, + 0.637424,0.770513,0,0.066941,0.069249,-0.007708, + 0.684537,0.728957,0.005552,0.067758,0.068528,-0.006167, + 0.684547,0.728969,0,0.067758,0.068528,-0.007708, + 0.684547,0.728969,0,0.067758,0.068528,-0.007708, + 0.684537,0.728957,0.005552,0.067758,0.068528,-0.006167, + 0.728957,0.684537,0.005552,0.068528,0.067758,-0.006167, + 0.684547,0.728969,0,0.067758,0.068528,-0.007708, + 0.728957,0.684537,0.005552,0.068528,0.067758,-0.006167, + 0.728969,0.684547,0,0.068528,0.067758,-0.007708, + 0.684547,0.728969,0,0.067758,0.068528,-0.007708, + 0.728969,0.684547,0,0.068528,0.067758,-0.007708, + 0.707107,0.707107,0,0.068189,0.068097,-0.007708, + 0.684547,0.728969,0,0.067758,0.068528,-0.007708, + 0.707107,0.707107,0,0.068189,0.068097,-0.007708, + 0.707107,0.707107,0,0.068097,0.068189,-0.007708, + 0.728969,0.684547,0,0.068528,0.067758,-0.007708, + 0.728957,0.684537,0.005552,0.068528,0.067758,-0.006167, + 0.770501,0.637414,0.005552,0.069249,0.066941,-0.006167, + 0.728969,0.684547,0,0.068528,0.067758,-0.007708, + 0.770501,0.637414,0.005552,0.069249,0.066941,-0.006167, + 0.770513,0.637424,0,0.069249,0.066941,-0.007708, + 0.770513,0.637424,0,0.069249,0.066941,-0.007708, + 0.770501,0.637414,0.005552,0.069249,0.066941,-0.006167, + 0.809005,0.587776,0.005552,0.069917,0.06608,-0.006167, + 0.770513,0.637424,0,0.069249,0.066941,-0.007708, + 0.809005,0.587776,0.005552,0.069917,0.06608,-0.006167, + 0.809017,0.587785,0,0.069917,0.06608,-0.007708, + 0.809017,0.587785,0,0.069917,0.06608,-0.007708, + 0.809005,0.587776,0.005552,0.069917,0.06608,-0.006167, + 0.844315,0.535819,0.005552,0.070529,0.065178,-0.006167, + 0.809017,0.587785,0,0.069917,0.06608,-0.007708, + 0.844315,0.535819,0.005552,0.070529,0.065178,-0.006167, + 0.844328,0.535827,0,0.070529,0.065178,-0.007708, + 0.844328,0.535827,0,0.070529,0.065178,-0.007708, + 0.844315,0.535819,0.005552,0.070529,0.065178,-0.006167, + 0.876293,0.481746,0.005552,0.071084,0.064241,-0.006167, + 0.844328,0.535827,0,0.070529,0.065178,-0.007708, + 0.876293,0.481746,0.005552,0.071084,0.064241,-0.006167, + 0.876307,0.481754,0,0.071084,0.064241,-0.007708, + 0.844328,0.535827,0,0.070529,0.065178,-0.007708, + 0.876307,0.481754,0,0.071084,0.064241,-0.007708, + 0.860742,0.509041,0,0.070926,0.064507,-0.007708, + 0.844328,0.535827,0,0.070529,0.065178,-0.007708, + 0.860742,0.509041,0,0.070926,0.064507,-0.007708, + 0.860742,0.509041,0,0.070867,0.064607,-0.007708, + 0.876307,0.481754,0,0.071084,0.064241,-0.007708, + 0.876293,0.481746,0.005552,0.071084,0.064241,-0.006167, + 0.904813,0.425773,0.005552,0.071578,0.06327,-0.006167, + 0.876307,0.481754,0,0.071084,0.064241,-0.007708, + 0.904813,0.425773,0.005552,0.071578,0.06327,-0.006167, + 0.904827,0.425779,0,0.071578,0.06327,-0.007708, + 0.904827,0.425779,0,0.071578,0.06327,-0.007708, + 0.904813,0.425773,0.005552,0.071578,0.06327,-0.006167, + 0.929762,0.368119,0.005552,0.072011,0.06227,-0.006167, + 0.904827,0.425779,0,0.071578,0.06327,-0.007708, + 0.929762,0.368119,0.005552,0.072011,0.06227,-0.006167, + 0.929776,0.368125,0,0.072011,0.06227,-0.007708, + 0.929776,0.368125,0,0.072011,0.06227,-0.007708, + 0.929762,0.368119,0.005552,0.072011,0.06227,-0.006167, + 0.951042,0.309012,0.005552,0.07238,0.061245,-0.006167, + 0.929776,0.368125,0,0.072011,0.06227,-0.007708, + 0.951042,0.309012,0.005552,0.07238,0.061245,-0.006167, + 0.951057,0.309017,0,0.07238,0.061245,-0.007708, + 0.951057,0.309017,0,0.07238,0.061245,-0.007708, + 0.951042,0.309012,0.005552,0.07238,0.061245,-0.006167, + 0.968568,0.248686,0.005552,0.072684,0.060198,-0.006167, + 0.951057,0.309017,0,0.07238,0.061245,-0.007708, + 0.968568,0.248686,0.005552,0.072684,0.060198,-0.006167, + 0.968583,0.24869,0,0.072684,0.060198,-0.007708, + 0.951057,0.309017,0,0.07238,0.061245,-0.007708, + 0.968583,0.24869,0,0.072684,0.060198,-0.007708, + 0.960294,0.278991,0,0.072642,0.060343,-0.007708, + 0.951057,0.309017,0,0.07238,0.061245,-0.007708, + 0.960294,0.278991,0,0.072642,0.060343,-0.007708, + 0.960294,0.278991,0,0.072621,0.060414,-0.007708, + 0.968583,0.24869,0,0.072684,0.060198,-0.007708, + 0.968568,0.248686,0.005552,0.072684,0.060198,-0.006167, + 0.982272,0.187378,0.005552,0.072922,0.059135,-0.006167, + 0.968583,0.24869,0,0.072684,0.060198,-0.007708, + 0.982272,0.187378,0.005552,0.072922,0.059135,-0.006167, + 0.982287,0.187381,0,0.072922,0.059135,-0.007708, + 0.982287,0.187381,0,0.072922,0.059135,-0.007708, + 0.982272,0.187378,0.005552,0.072922,0.059135,-0.006167, + 0.992099,0.125331,0.005552,0.073092,0.058059,-0.006167, + 0.982287,0.187381,0,0.072922,0.059135,-0.007708, + 0.992099,0.125331,0.005552,0.073092,0.058059,-0.006167, + 0.992115,0.125333,0,0.073092,0.058059,-0.007708, + 0.992115,0.125333,0,0.073092,0.058059,-0.007708, + 0.992099,0.125331,0.005552,0.073092,0.058059,-0.006167, + 0.997287,0.07324,0.007402,0.073195,0.056974,-0.006167, + 0.992115,0.125333,0,0.073092,0.058059,-0.007708, + 0.997287,0.07324,0.007402,0.073195,0.056974,-0.006167, + 0.995562,0.094108,0,0.073195,0.056974,-0.007708, + 0.995562,-0.094108,0,0.073195,0.054796,-0.007708, + 0.997287,-0.07324,0.007402,0.073195,0.054796,-0.006167, + 0.992099,-0.125331,0.005552,0.073092,0.053712,-0.006167, + 0.995562,-0.094108,0,0.073195,0.054796,-0.007708, + 0.992099,-0.125331,0.005552,0.073092,0.053712,-0.006167, + 0.992115,-0.125333,0,0.073092,0.053712,-0.007708, + 0.992115,-0.125333,0,0.073092,0.053712,-0.007708, + 0.992099,-0.125331,0.005552,0.073092,0.053712,-0.006167, + 0.982272,-0.187378,0.005552,0.072922,0.052635,-0.006167, + 0.992115,-0.125333,0,0.073092,0.053712,-0.007708, + 0.982272,-0.187378,0.005552,0.072922,0.052635,-0.006167, + 0.982287,-0.187381,0,0.072922,0.052635,-0.007708, + 0.982287,-0.187381,0,0.072922,0.052635,-0.007708, + 0.982272,-0.187378,0.005552,0.072922,0.052635,-0.006167, + 0.968568,-0.248686,0.005552,0.072684,0.051572,-0.006167, + 0.982287,-0.187381,0,0.072922,0.052635,-0.007708, + 0.968568,-0.248686,0.005552,0.072684,0.051572,-0.006167, + 0.968583,-0.24869,0,0.072684,0.051572,-0.007708, + 0.968583,-0.24869,0,0.072684,0.051572,-0.007708, + 0.968568,-0.248686,0.005552,0.072684,0.051572,-0.006167, + 0.951042,-0.309012,0.005552,0.07238,0.050526,-0.006167, + 0.968583,-0.24869,0,0.072684,0.051572,-0.007708, + 0.951042,-0.309012,0.005552,0.07238,0.050526,-0.006167, + 0.951057,-0.309017,0,0.07238,0.050526,-0.007708, + 0.968583,-0.24869,0,0.072684,0.051572,-0.007708, + 0.951057,-0.309017,0,0.07238,0.050526,-0.007708, + 0.960294,-0.278991,0,0.072621,0.051356,-0.007708, + 0.968583,-0.24869,0,0.072684,0.051572,-0.007708, + 0.960294,-0.278991,0,0.072621,0.051356,-0.007708, + 0.960294,-0.278991,0,0.072642,0.051428,-0.007708, + 0.951057,-0.309017,0,0.07238,0.050526,-0.007708, + 0.951042,-0.309012,0.005552,0.07238,0.050526,-0.006167, + 0.929762,-0.368119,0.005552,0.072011,0.049501,-0.006167, + 0.951057,-0.309017,0,0.07238,0.050526,-0.007708, + 0.929762,-0.368119,0.005552,0.072011,0.049501,-0.006167, + 0.929776,-0.368125,0,0.072011,0.049501,-0.007708, + 0.929776,-0.368125,0,0.072011,0.049501,-0.007708, + 0.929762,-0.368119,0.005552,0.072011,0.049501,-0.006167, + 0.904813,-0.425773,0.005552,0.071578,0.048501,-0.006167, + 0.929776,-0.368125,0,0.072011,0.049501,-0.007708, + 0.904813,-0.425773,0.005552,0.071578,0.048501,-0.006167, + 0.904827,-0.425779,0,0.071578,0.048501,-0.007708, + 0.904827,-0.425779,0,0.071578,0.048501,-0.007708, + 0.904813,-0.425773,0.005552,0.071578,0.048501,-0.006167, + 0.876293,-0.481746,0.005552,0.071084,0.04753,-0.006167, + 0.904827,-0.425779,0,0.071578,0.048501,-0.007708, + 0.876293,-0.481746,0.005552,0.071084,0.04753,-0.006167, + 0.876307,-0.481754,0,0.071084,0.04753,-0.007708, + 0.876307,-0.481754,0,0.071084,0.04753,-0.007708, + 0.876293,-0.481746,0.005552,0.071084,0.04753,-0.006167, + 0.844315,-0.535819,0.005552,0.070529,0.046592,-0.006167, + 0.876307,-0.481754,0,0.071084,0.04753,-0.007708, + 0.844315,-0.535819,0.005552,0.070529,0.046592,-0.006167, + 0.844328,-0.535827,0,0.070529,0.046592,-0.007708, + 0.876307,-0.481754,0,0.071084,0.04753,-0.007708, + 0.844328,-0.535827,0,0.070529,0.046592,-0.007708, + 0.860742,-0.509041,0,0.070867,0.047163,-0.007708, + 0.876307,-0.481754,0,0.071084,0.04753,-0.007708, + 0.860742,-0.509041,0,0.070867,0.047163,-0.007708, + 0.860742,-0.509041,0,0.070926,0.047263,-0.007708, + 0.844328,-0.535827,0,0.070529,0.046592,-0.007708, + 0.844315,-0.535819,0.005552,0.070529,0.046592,-0.006167, + 0.809005,-0.587776,0.005552,0.069917,0.045691,-0.006167, + 0.844328,-0.535827,0,0.070529,0.046592,-0.007708, + 0.809005,-0.587776,0.005552,0.069917,0.045691,-0.006167, + 0.809017,-0.587785,0,0.069917,0.045691,-0.007708, + 0.809017,-0.587785,0,0.069917,0.045691,-0.007708, + 0.809005,-0.587776,0.005552,0.069917,0.045691,-0.006167, + 0.770501,-0.637414,0.005552,0.069249,0.04483,-0.006167, + 0.809017,-0.587785,0,0.069917,0.045691,-0.007708, + 0.770501,-0.637414,0.005552,0.069249,0.04483,-0.006167, + 0.770513,-0.637424,0,0.069249,0.04483,-0.007708, + 0.770513,-0.637424,0,0.069249,0.04483,-0.007708, + 0.770501,-0.637414,0.005552,0.069249,0.04483,-0.006167, + 0.728957,-0.684537,0.005552,0.068528,0.044013,-0.006167, + 0.770513,-0.637424,0,0.069249,0.04483,-0.007708, + 0.728957,-0.684537,0.005552,0.068528,0.044013,-0.006167, + 0.728969,-0.684547,0,0.068528,0.044013,-0.007708, + 0.728969,-0.684547,0,0.068528,0.044013,-0.007708, + 0.728957,-0.684537,0.005552,0.068528,0.044013,-0.006167, + 0.684537,-0.728957,0.005552,0.067758,0.043242,-0.006167, + 0.728969,-0.684547,0,0.068528,0.044013,-0.007708, + 0.684537,-0.728957,0.005552,0.067758,0.043242,-0.006167, + 0.684547,-0.728969,0,0.067758,0.043242,-0.007708, + 0.728969,-0.684547,0,0.068528,0.044013,-0.007708, + 0.684547,-0.728969,0,0.067758,0.043242,-0.007708, + 0.707107,-0.707107,0,0.068097,0.043581,-0.007708, + 0.728969,-0.684547,0,0.068528,0.044013,-0.007708, + 0.707107,-0.707107,0,0.068097,0.043581,-0.007708, + 0.707107,-0.707107,0,0.068189,0.043673,-0.007708, + 0.684547,-0.728969,0,0.067758,0.043242,-0.007708, + 0.684537,-0.728957,0.005552,0.067758,0.043242,-0.006167, + 0.637414,-0.770501,0.005552,0.066941,0.042522,-0.006167, + 0.684547,-0.728969,0,0.067758,0.043242,-0.007708, + 0.637414,-0.770501,0.005552,0.066941,0.042522,-0.006167, + 0.637424,-0.770513,0,0.066941,0.042522,-0.007708, + 0.637424,-0.770513,0,0.066941,0.042522,-0.007708, + 0.637414,-0.770501,0.005552,0.066941,0.042522,-0.006167, + 0.587776,-0.809005,0.005552,0.06608,0.041854,-0.006167, + 0.637424,-0.770513,0,0.066941,0.042522,-0.007708, + 0.587776,-0.809005,0.005552,0.06608,0.041854,-0.006167, + 0.587785,-0.809017,0,0.06608,0.041854,-0.007708, + 0.587785,-0.809017,0,0.06608,0.041854,-0.007708, + 0.587776,-0.809005,0.005552,0.06608,0.041854,-0.006167, + 0.535819,-0.844315,0.005552,0.065178,0.041241,-0.006167, + 0.587785,-0.809017,0,0.06608,0.041854,-0.007708, + 0.535819,-0.844315,0.005552,0.065178,0.041241,-0.006167, + 0.535827,-0.844328,0,0.065178,0.041241,-0.007708, + 0.535827,-0.844328,0,0.065178,0.041241,-0.007708, + 0.535819,-0.844315,0.005552,0.065178,0.041241,-0.006167, + 0.481746,-0.876293,0.005552,0.064241,0.040687,-0.006167, + 0.535827,-0.844328,0,0.065178,0.041241,-0.007708, + 0.481746,-0.876293,0.005552,0.064241,0.040687,-0.006167, + 0.481754,-0.876307,0,0.064241,0.040687,-0.007708, + 0.535827,-0.844328,0,0.065178,0.041241,-0.007708, + 0.481754,-0.876307,0,0.064241,0.040687,-0.007708, + 0.509041,-0.860742,0,0.064507,0.040845,-0.007708, + 0.535827,-0.844328,0,0.065178,0.041241,-0.007708, + 0.509041,-0.860742,0,0.064507,0.040845,-0.007708, + 0.509041,-0.860742,0,0.064607,0.040904,-0.007708, + 0.481754,-0.876307,0,0.064241,0.040687,-0.007708, + 0.481746,-0.876293,0.005552,0.064241,0.040687,-0.006167, + 0.425773,-0.904813,0.005552,0.06327,0.040192,-0.006167, + 0.481754,-0.876307,0,0.064241,0.040687,-0.007708, + 0.425773,-0.904813,0.005552,0.06327,0.040192,-0.006167, + 0.425779,-0.904827,0,0.06327,0.040192,-0.007708, + 0.425779,-0.904827,0,0.06327,0.040192,-0.007708, + 0.425773,-0.904813,0.005552,0.06327,0.040192,-0.006167, + 0.368119,-0.929762,0.005552,0.06227,0.03976,-0.006167, + 0.425779,-0.904827,0,0.06327,0.040192,-0.007708, + 0.368119,-0.929762,0.005552,0.06227,0.03976,-0.006167, + 0.368125,-0.929776,0,0.06227,0.03976,-0.007708, + 0.368125,-0.929776,0,0.06227,0.03976,-0.007708, + 0.368119,-0.929762,0.005552,0.06227,0.03976,-0.006167, + 0.309012,-0.951042,0.005552,0.061245,0.03939,-0.006167, + 0.368125,-0.929776,0,0.06227,0.03976,-0.007708, + 0.309012,-0.951042,0.005552,0.061245,0.03939,-0.006167, + 0.309017,-0.951057,0,0.061245,0.03939,-0.007708, + 0.309017,-0.951057,0,0.061245,0.03939,-0.007708, + 0.309012,-0.951042,0.005552,0.061245,0.03939,-0.006167, + 0.248686,-0.968568,0.005552,0.060198,0.039087,-0.006167, + 0.309017,-0.951057,0,0.061245,0.03939,-0.007708, + 0.248686,-0.968568,0.005552,0.060198,0.039087,-0.006167, + 0.24869,-0.968583,0,0.060198,0.039087,-0.007708, + 0.309017,-0.951057,0,0.061245,0.03939,-0.007708, + 0.24869,-0.968583,0,0.060198,0.039087,-0.007708, + 0.278991,-0.960294,0,0.060343,0.039128,-0.007708, + 0.309017,-0.951057,0,0.061245,0.03939,-0.007708, + 0.278991,-0.960294,0,0.060343,0.039128,-0.007708, + 0.278991,-0.960294,0,0.060414,0.039149,-0.007708, + 0.24869,-0.968583,0,0.060198,0.039087,-0.007708, + 0.248686,-0.968568,0.005552,0.060198,0.039087,-0.006167, + 0.187378,-0.982272,0.005552,0.059135,0.038849,-0.006167, + 0.24869,-0.968583,0,0.060198,0.039087,-0.007708, + 0.187378,-0.982272,0.005552,0.059135,0.038849,-0.006167, + 0.187381,-0.982287,0,0.059135,0.038849,-0.007708, + 0.187381,-0.982287,0,0.059135,0.038849,-0.007708, + 0.187378,-0.982272,0.005552,0.059135,0.038849,-0.006167, + 0.125331,-0.992099,0.005552,0.058059,0.038678,-0.006167, + 0.187381,-0.982287,0,0.059135,0.038849,-0.007708, + 0.125331,-0.992099,0.005552,0.058059,0.038678,-0.006167, + 0.125333,-0.992115,0,0.058059,0.038678,-0.007708, + 0.125333,-0.992115,0,0.058059,0.038678,-0.007708, + 0.125331,-0.992099,0.005552,0.058059,0.038678,-0.006167, + 0.07324,-0.997287,0.007402,0.056974,0.038576,-0.006167, + 0.125333,-0.992115,0,0.058059,0.038678,-0.007708, + 0.07324,-0.997287,0.007402,0.056974,0.038576,-0.006167, + 0.094108,-0.995562,0,0.056974,0.038576,-0.007708 +}; +static const struct gllist frame={GL_N3F_V3F,GL_TRIANGLES,9588,data,NULL}; +const struct gllist *companion_disc=&frame; diff --git a/hacks/glx/companion_heart.c b/hacks/glx/companion_heart.c new file mode 100644 index 00000000..1786a621 --- /dev/null +++ b/hacks/glx/companion_heart.c @@ -0,0 +1,653 @@ +#include "gllist.h" +static const float data[]={ + -0.126112,-0.516835,0.846745,0.062716,0.065295,-0.005781, + -0.233173,-0.466563,0.853199,0.063951,0.064804,-0.005781, + -0.169323,-0.502195,0.848015,0.063583,0.066646,-0.004818, + 0,0,1,0.055885,0.06242,-0.005781, + 0,0,1,0.055116,0.063504,-0.005781, + 0,0,1,0.054127,0.064391,-0.005781, + 0,0,1,0.055885,0.06242,-0.005781, + 0,0,1,0.054127,0.064391,-0.005781, + 0,0,1,0.052967,0.065039,-0.005781, + 0,0,1,0.055885,0.06242,-0.005781, + 0,0,1,0.052967,0.065039,-0.005781, + 0,0,1,0.051693,0.065415,-0.005781, + 0,0,1,0.055885,0.06242,-0.005781, + 0,0,1,0.051693,0.065415,-0.005781, + 0,0,1,0.050367,0.065502,-0.005781, + 0,0,1,0.055885,0.06242,-0.005781, + 0,0,1,0.050367,0.065502,-0.005781, + 0,0,1,0.049054,0.065295,-0.005781, + 0,0,1,0.055885,0.06242,-0.005781, + 0,0,1,0.049054,0.065295,-0.005781, + 0,0,1,0.04782,0.064804,-0.005781, + 0,0,1,0.055885,0.06242,-0.005781, + 0,0,1,0.04782,0.064804,-0.005781, + 0,0,1,0.046724,0.064053,-0.005781, + 0,0,1,0.055885,0.06242,-0.005781, + 0,0,1,0.046724,0.064053,-0.005781, + 0,0,1,0.04582,0.063079,-0.005781, + 0,0,1,0.055885,0.06242,-0.005781, + 0,0,1,0.04582,0.063079,-0.005781, + 0,0,1,0.045152,0.06193,-0.005781, + 0,0,1,0.055885,0.06242,-0.005781, + 0,0,1,0.045152,0.06193,-0.005781, + 0,0,1,0.044754,0.060662,-0.005781, + 0,0,1,0.055885,0.06242,-0.005781, + 0,0,1,0.044754,0.060662,-0.005781, + 0,0,1,0.044645,0.059338,-0.005781, + 0,0,1,0.055885,0.06242,-0.005781, + 0,0,1,0.044645,0.059338,-0.005781, + 0,0,1,0.044702,0.058527,-0.005781, + 0,0,1,0.055885,0.06242,-0.005781, + 0,0,1,0.044702,0.058527,-0.005781, + 0,0,1,0.044827,0.057723,-0.005781, + 0,0,1,0.055885,0.06242,-0.005781, + 0,0,1,0.044827,0.057723,-0.005781, + 0,0,1,0.045017,0.056932,-0.005781, + 0,0,1,0.055885,0.06242,-0.005781, + 0,0,1,0.045017,0.056932,-0.005781, + 0,0,1,0.045272,0.05616,-0.005781, + 0,0,1,0.055885,0.06242,-0.005781, + 0,0,1,0.045272,0.05616,-0.005781, + 0,0,1,0.04559,0.055411,-0.005781, + 0,0,1,0.055885,0.06242,-0.005781, + 0,0,1,0.04559,0.055411,-0.005781, + 0,0,1,0.04597,0.054691,-0.005781, + 0,0,1,0.055885,0.06242,-0.005781, + 0,0,1,0.04597,0.054691,-0.005781, + 0,0,1,0.046407,0.054006,-0.005781, + 0,0,1,0.055885,0.06242,-0.005781, + 0,0,1,0.046407,0.054006,-0.005781, + 0,0,1,0.0469,0.053359,-0.005781, + 0,0,1,0.055885,0.06242,-0.005781, + 0,0,1,0.0469,0.053359,-0.005781, + 0,0,1,0.047445,0.052755,-0.005781, + 0,0,1,0.055885,0.06242,-0.005781, + 0,0,1,0.047445,0.052755,-0.005781, + 0,0,1,0.048038,0.052198,-0.005781, + 0,0,1,0.055885,0.06242,-0.005781, + 0,0,1,0.048038,0.052198,-0.005781, + 0,0,1,0.048675,0.051693,-0.005781, + 0,0,1,0.055885,0.06242,-0.005781, + 0,0,1,0.048675,0.051693,-0.005781, + 0,0,1,0.049352,0.051241,-0.005781, + 0,0,1,0.055885,0.06242,-0.005781, + 0,0,1,0.049352,0.051241,-0.005781, + 0,0,1,0.050001,0.050829,-0.005781, + 0,0,1,0.055885,0.06242,-0.005781, + 0,0,1,0.050001,0.050829,-0.005781, + 0,0,1,0.050634,0.050393,-0.005781, + 0,0,1,0.055885,0.06242,-0.005781, + 0,0,1,0.050634,0.050393,-0.005781, + 0,0,1,0.05125,0.049933,-0.005781, + 0,0,1,0.055885,0.06242,-0.005781, + 0,0,1,0.05125,0.049933,-0.005781, + 0,0,1,0.051848,0.049449,-0.005781, + 0,0,1,0.055885,0.06242,-0.005781, + 0,0,1,0.051848,0.049449,-0.005781, + 0,0,1,0.052427,0.048943,-0.005781, + 0,0,1,0.055885,0.06242,-0.005781, + 0,0,1,0.052427,0.048943,-0.005781, + 0,0,1,0.052987,0.048416,-0.005781, + 0,0,1,0.055885,0.06242,-0.005781, + 0,0,1,0.052987,0.048416,-0.005781, + 0,0,1,0.053525,0.047867,-0.005781, + 0,0,1,0.055885,0.06242,-0.005781, + 0,0,1,0.053525,0.047867,-0.005781, + 0,0,1,0.054043,0.047299,-0.005781, + 0,0,1,0.055885,0.06242,-0.005781, + 0,0,1,0.054043,0.047299,-0.005781, + 0,0,1,0.054538,0.046711,-0.005781, + 0,0,1,0.055885,0.06242,-0.005781, + 0,0,1,0.054538,0.046711,-0.005781, + 0,0,1,0.055011,0.046104,-0.005781, + 0,0,1,0.055885,0.06242,-0.005781, + 0,0,1,0.055011,0.046104,-0.005781, + 0,0,1,0.05546,0.04548,-0.005781, + 0,0,1,0.055885,0.06242,-0.005781, + 0,0,1,0.05546,0.04548,-0.005781, + 0,0,1,0.055885,0.044839,-0.005781, + 0,0,1,0.055885,0.06242,-0.005781, + 0,0,1,0.055885,0.044839,-0.005781, + 0,0,1,0.05631,0.04548,-0.005781, + 0,0,1,0.055885,0.06242,-0.005781, + 0,0,1,0.05631,0.04548,-0.005781, + 0,0,1,0.05676,0.046104,-0.005781, + 0,0,1,0.055885,0.06242,-0.005781, + 0,0,1,0.05676,0.046104,-0.005781, + 0,0,1,0.057232,0.046711,-0.005781, + 0,0,1,0.055885,0.06242,-0.005781, + 0,0,1,0.057232,0.046711,-0.005781, + 0,0,1,0.057728,0.047299,-0.005781, + 0,0,1,0.055885,0.06242,-0.005781, + 0,0,1,0.057728,0.047299,-0.005781, + 0,0,1,0.058245,0.047867,-0.005781, + 0,0,1,0.055885,0.06242,-0.005781, + 0,0,1,0.058245,0.047867,-0.005781, + 0,0,1,0.058784,0.048416,-0.005781, + 0,0,1,0.055885,0.06242,-0.005781, + 0,0,1,0.058784,0.048416,-0.005781, + 0,0,1,0.059343,0.048943,-0.005781, + 0,0,1,0.055885,0.06242,-0.005781, + 0,0,1,0.059343,0.048943,-0.005781, + 0,0,1,0.059922,0.049449,-0.005781, + 0,0,1,0.055885,0.06242,-0.005781, + 0,0,1,0.059922,0.049449,-0.005781, + 0,0,1,0.06052,0.049933,-0.005781, + 0,0,1,0.055885,0.06242,-0.005781, + 0,0,1,0.06052,0.049933,-0.005781, + 0,0,1,0.061136,0.050393,-0.005781, + 0,0,1,0.055885,0.06242,-0.005781, + 0,0,1,0.061136,0.050393,-0.005781, + 0,0,1,0.061769,0.050829,-0.005781, + 0,0,1,0.055885,0.06242,-0.005781, + 0,0,1,0.061769,0.050829,-0.005781, + 0,0,1,0.062418,0.051241,-0.005781, + 0,0,1,0.055885,0.06242,-0.005781, + 0,0,1,0.062418,0.051241,-0.005781, + 0,0,1,0.063095,0.051693,-0.005781, + 0,0,1,0.055885,0.06242,-0.005781, + 0,0,1,0.063095,0.051693,-0.005781, + 0,0,1,0.063732,0.052198,-0.005781, + 0,0,1,0.055885,0.06242,-0.005781, + 0,0,1,0.063732,0.052198,-0.005781, + 0,0,1,0.064326,0.052755,-0.005781, + 0,0,1,0.055885,0.06242,-0.005781, + 0,0,1,0.064326,0.052755,-0.005781, + 0,0,1,0.06487,0.053359,-0.005781, + 0,0,1,0.055885,0.06242,-0.005781, + 0,0,1,0.06487,0.053359,-0.005781, + 0,0,1,0.065363,0.054006,-0.005781, + 0,0,1,0.055885,0.06242,-0.005781, + 0,0,1,0.065363,0.054006,-0.005781, + 0,0,1,0.065801,0.054691,-0.005781, + 0,0,1,0.055885,0.06242,-0.005781, + 0,0,1,0.065801,0.054691,-0.005781, + 0,0,1,0.06618,0.055411,-0.005781, + 0,0,1,0.055885,0.06242,-0.005781, + 0,0,1,0.06618,0.055411,-0.005781, + 0,0,1,0.066498,0.05616,-0.005781, + 0,0,1,0.055885,0.06242,-0.005781, + 0,0,1,0.066498,0.05616,-0.005781, + 0,0,1,0.066754,0.056932,-0.005781, + 0,0,1,0.055885,0.06242,-0.005781, + 0,0,1,0.066754,0.056932,-0.005781, + 0,0,1,0.066944,0.057723,-0.005781, + 0,0,1,0.055885,0.06242,-0.005781, + 0,0,1,0.066944,0.057723,-0.005781, + 0,0,1,0.067068,0.058527,-0.005781, + 0,0,1,0.055885,0.06242,-0.005781, + 0,0,1,0.067068,0.058527,-0.005781, + 0,0,1,0.067125,0.059338,-0.005781, + 0,0,1,0.055885,0.06242,-0.005781, + 0,0,1,0.067125,0.059338,-0.005781, + 0,0,1,0.067016,0.060662,-0.005781, + 0,0,1,0.055885,0.06242,-0.005781, + 0,0,1,0.067016,0.060662,-0.005781, + 0,0,1,0.066618,0.06193,-0.005781, + 0,0,1,0.055885,0.06242,-0.005781, + 0,0,1,0.066618,0.06193,-0.005781, + 0,0,1,0.065951,0.063079,-0.005781, + 0,0,1,0.055885,0.06242,-0.005781, + 0,0,1,0.065951,0.063079,-0.005781, + 0,0,1,0.065047,0.064053,-0.005781, + 0,0,1,0.055885,0.06242,-0.005781, + 0,0,1,0.065047,0.064053,-0.005781, + 0,0,1,0.063951,0.064804,-0.005781, + 0,0,1,0.055885,0.06242,-0.005781, + 0,0,1,0.063951,0.064804,-0.005781, + 0,0,1,0.062716,0.065295,-0.005781, + 0,0,1,0.055885,0.06242,-0.005781, + 0,0,1,0.062716,0.065295,-0.005781, + 0,0,1,0.061404,0.065502,-0.005781, + 0,0,1,0.055885,0.06242,-0.005781, + 0,0,1,0.061404,0.065502,-0.005781, + 0,0,1,0.060078,0.065415,-0.005781, + 0,0,1,0.055885,0.06242,-0.005781, + 0,0,1,0.060078,0.065415,-0.005781, + 0,0,1,0.058804,0.065039,-0.005781, + 0,0,1,0.055885,0.06242,-0.005781, + 0,0,1,0.058804,0.065039,-0.005781, + 0,0,1,0.057644,0.064391,-0.005781, + 0,0,1,0.055885,0.06242,-0.005781, + 0,0,1,0.057644,0.064391,-0.005781, + 0,0,1,0.056655,0.063504,-0.005781, + 0,0,1,0.055885,0.06242,-0.005781, + 0,0,1,0.056655,0.063504,-0.005781, + 0,0,1,0.055885,0.06242,-0.005781, + 0,0,1,0.055885,0.06242,-0.005781, + 0,0,1,0.055885,0.06242,-0.005781, + 0,0,1,0.055116,0.063504,-0.005781, + 0.600355,0.41774,0.681958,0.05546,0.04548,-0.005781, + 0.611328,0.411243,0.676134,0.055414,0.04397,-0.004818, + 0.619748,0.407106,0.670953,0.055885,0.044839,-0.005781, + 0.611328,0.411243,0.676134,0.055414,0.04397,-0.004818, + 0.600355,0.41774,0.681958,0.05546,0.04548,-0.005781, + 0.583861,0.425853,0.691199,0.054915,0.044676,-0.004818, + 0.573435,0.432324,0.695894,0.055011,0.046104,-0.005781, + 0.583861,0.425853,0.691199,0.054915,0.044676,-0.004818, + 0.600355,0.41774,0.681958,0.05546,0.04548,-0.005781, + 0.583861,0.425853,0.691199,0.054915,0.044676,-0.004818, + 0.573435,0.432324,0.695894,0.055011,0.046104,-0.005781, + 0.557839,0.440321,0.703515,0.05439,0.045363,-0.004818, + 0.547914,0.446817,0.707209,0.054538,0.046711,-0.005781, + 0.557839,0.440321,0.703515,0.05439,0.045363,-0.004818, + 0.573435,0.432324,0.695894,0.055011,0.046104,-0.005781, + 0.557839,0.440321,0.703515,0.05439,0.045363,-0.004818, + 0.547914,0.446817,0.707209,0.054538,0.046711,-0.005781, + 0.528358,0.458036,0.714871,0.05384,0.046029,-0.004818, + 0.525024,0.459644,0.716294,0.054043,0.047299,-0.005781, + 0.528358,0.458036,0.714871,0.05384,0.046029,-0.004818, + 0.547914,0.446817,0.707209,0.054538,0.046711,-0.005781, + 0.525024,0.459644,0.716294,0.054043,0.047299,-0.005781, + 0.507344,0.470385,0.722039,0.053525,0.047867,-0.005781, + 0.528358,0.458036,0.714871,0.05384,0.046029,-0.004818, + 0.502587,0.474851,0.722443,0.053266,0.046673,-0.004818, + 0.528358,0.458036,0.714871,0.05384,0.046029,-0.004818, + 0.507344,0.470385,0.722039,0.053525,0.047867,-0.005781, + 0.507344,0.470385,0.722039,0.053525,0.047867,-0.005781, + 0.484849,0.48521,0.727662,0.052987,0.048416,-0.005781, + 0.502587,0.474851,0.722443,0.053266,0.046673,-0.004818, + 0.480277,0.489774,0.727637,0.052668,0.047293,-0.004818, + 0.502587,0.474851,0.722443,0.053266,0.046673,-0.004818, + 0.484849,0.48521,0.727662,0.052987,0.048416,-0.005781, + 0.484849,0.48521,0.727662,0.052987,0.048416,-0.005781, + 0.463202,0.500363,0.731492,0.052427,0.048943,-0.005781, + 0.480277,0.489774,0.727637,0.052668,0.047293,-0.004818, + 0.458764,0.50505,0.731068,0.052047,0.047891,-0.004818, + 0.480277,0.489774,0.727637,0.052668,0.047293,-0.004818, + 0.463202,0.500363,0.731492,0.052427,0.048943,-0.005781, + 0.463202,0.500363,0.731492,0.052427,0.048943,-0.005781, + 0.442255,0.515933,0.733637,0.051848,0.049449,-0.005781, + 0.458764,0.50505,0.731068,0.052047,0.047891,-0.004818, + 0.437903,0.520767,0.732832,0.051404,0.048464,-0.004818, + 0.458764,0.50505,0.731068,0.052047,0.047891,-0.004818, + 0.442255,0.515933,0.733637,0.051848,0.049449,-0.005781, + 0.442255,0.515933,0.733637,0.051848,0.049449,-0.005781, + 0.419718,0.534563,0.733539,0.05125,0.049933,-0.005781, + 0.437903,0.520767,0.732832,0.051404,0.048464,-0.004818, + 0.42249,0.532759,0.73326,0.050741,0.049011,-0.004818, + 0.437903,0.520767,0.732832,0.051404,0.048464,-0.004818, + 0.419718,0.534563,0.733539,0.05125,0.049933,-0.005781, + 0.42249,0.532759,0.73326,0.050741,0.049011,-0.004818, + 0.419718,0.534563,0.733539,0.05125,0.049933,-0.005781, + 0.403677,0.547538,0.732971,0.050057,0.049532,-0.004818, + 0.395847,0.555175,0.731496,0.050634,0.050393,-0.005781, + 0.403677,0.547538,0.732971,0.050057,0.049532,-0.004818, + 0.419718,0.534563,0.733539,0.05125,0.049933,-0.005781, + 0.403677,0.547538,0.732971,0.050057,0.049532,-0.004818, + 0.395847,0.555175,0.731496,0.050634,0.050393,-0.005781, + 0.38391,0.564835,0.730462,0.049354,0.050026,-0.004818, + 0.376177,0.572732,0.728333,0.050001,0.050829,-0.005781, + 0.38391,0.564835,0.730462,0.049354,0.050026,-0.004818, + 0.395847,0.555175,0.731496,0.050634,0.050393,-0.005781, + 0.38391,0.564835,0.730462,0.049354,0.050026,-0.004818, + 0.376177,0.572732,0.728333,0.050001,0.050829,-0.005781, + 0.375296,0.574093,0.727715,0.048634,0.050493,-0.004818, + 0.378691,0.573667,0.726291,0.049352,0.051241,-0.005781, + 0.375296,0.574093,0.727715,0.048634,0.050493,-0.004818, + 0.376177,0.572732,0.728333,0.050001,0.050829,-0.005781, + 0.375296,0.574093,0.727715,0.048634,0.050493,-0.004818, + 0.378691,0.573667,0.726291,0.049352,0.051241,-0.005781, + 0.405711,0.551851,0.728601,0.047882,0.051003,-0.004818, + 0.403275,0.554082,0.72826,0.048675,0.051693,-0.005781, + 0.405711,0.551851,0.728601,0.047882,0.051003,-0.004818, + 0.378691,0.573667,0.726291,0.049352,0.051241,-0.005781, + 0.403275,0.554082,0.72826,0.048675,0.051693,-0.005781, + 0.439698,0.520339,0.732061,0.048038,0.052198,-0.005781, + 0.405711,0.551851,0.728601,0.047882,0.051003,-0.004818, + 0.455156,0.505988,0.732672,0.047175,0.051576,-0.004818, + 0.405711,0.551851,0.728601,0.047882,0.051003,-0.004818, + 0.439698,0.520339,0.732061,0.048038,0.052198,-0.005781, + 0.439698,0.520339,0.732061,0.048038,0.052198,-0.005781, + 0.478388,0.479119,0.735928,0.047445,0.052755,-0.005781, + 0.455156,0.505988,0.732672,0.047175,0.051576,-0.004818, + 0.492434,0.463571,0.736621,0.046517,0.052206,-0.004818, + 0.455156,0.505988,0.732672,0.047175,0.051576,-0.004818, + 0.478388,0.479119,0.735928,0.047445,0.052755,-0.005781, + 0.478388,0.479119,0.735928,0.047445,0.052755,-0.005781, + 0.513034,0.434953,0.740008,0.0469,0.053359,-0.005781, + 0.492434,0.463571,0.736621,0.046517,0.052206,-0.004818, + 0.525496,0.418365,0.740827,0.045912,0.05289,-0.004818, + 0.492434,0.463571,0.736621,0.046517,0.052206,-0.004818, + 0.513034,0.434953,0.740008,0.0469,0.053359,-0.005781, + 0.513034,0.434953,0.740008,0.0469,0.053359,-0.005781, + 0.543337,0.388194,0.744372,0.046407,0.054006,-0.005781, + 0.525496,0.418365,0.740827,0.045912,0.05289,-0.004818, + 0.554068,0.370754,0.745352,0.045365,0.053623,-0.004818, + 0.525496,0.418365,0.740827,0.045912,0.05289,-0.004818, + 0.543337,0.388194,0.744372,0.046407,0.054006,-0.005781, + 0.543337,0.388194,0.744372,0.046407,0.054006,-0.005781, + 0.569031,0.339242,0.749078,0.04597,0.054691,-0.005781, + 0.554068,0.370754,0.745352,0.045365,0.053623,-0.004818, + 0.577912,0.321162,0.750248,0.044879,0.054399,-0.004818, + 0.554068,0.370754,0.745352,0.045365,0.053623,-0.004818, + 0.569031,0.339242,0.749078,0.04597,0.054691,-0.005781, + 0.569031,0.339242,0.749078,0.04597,0.054691,-0.005781, + 0.589896,0.288542,0.754166,0.04559,0.055411,-0.005781, + 0.577912,0.321162,0.750248,0.044879,0.054399,-0.004818, + 0.596848,0.270049,0.755544,0.044458,0.055214,-0.004818, + 0.577912,0.321162,0.750248,0.044879,0.054399,-0.004818, + 0.589896,0.288542,0.754166,0.04559,0.055411,-0.005781, + 0.589896,0.288542,0.754166,0.04559,0.055411,-0.005781, + 0.60577,0.236571,0.759656,0.045272,0.05616,-0.005781, + 0.596848,0.270049,0.755544,0.044458,0.055214,-0.004818, + 0.610753,0.217903,0.761249,0.044105,0.056061,-0.004818, + 0.596848,0.270049,0.755544,0.044458,0.055214,-0.004818, + 0.60577,0.236571,0.759656,0.045272,0.05616,-0.005781, + 0.60577,0.236571,0.759656,0.045272,0.05616,-0.005781, + 0.616557,0.183837,0.765546,0.045017,0.056932,-0.005781, + 0.610753,0.217903,0.761249,0.044105,0.056061,-0.004818, + 0.619574,0.165232,0.767351,0.043821,0.056936,-0.004818, + 0.610753,0.217903,0.761249,0.044105,0.056061,-0.004818, + 0.616557,0.183837,0.765546,0.045017,0.056932,-0.005781, + 0.616557,0.183837,0.765546,0.045017,0.056932,-0.005781, + 0.622238,0.13086,0.771813,0.044827,0.057723,-0.005781, + 0.619574,0.165232,0.767351,0.043821,0.056936,-0.004818, + 0.623333,0.112547,0.773815,0.04361,0.057831,-0.004818, + 0.619574,0.165232,0.767351,0.043821,0.056936,-0.004818, + 0.622238,0.13086,0.771813,0.044827,0.057723,-0.005781, + 0.622238,0.13086,0.771813,0.044827,0.057723,-0.005781, + 0.622921,0.078006,0.778386,0.044702,0.058527,-0.005781, + 0.623333,0.112547,0.773815,0.04361,0.057831,-0.004818, + 0.622674,0.06887,0.779444,0.043472,0.058741,-0.004818, + 0.623333,0.112547,0.773815,0.04361,0.057831,-0.004818, + 0.622921,0.078006,0.778386,0.044702,0.058527,-0.005781, + 0.615482,0.005518,0.788132,0.043409,0.05966,-0.004818, + 0.622674,0.06887,0.779444,0.043472,0.058741,-0.004818, + 0.622921,0.078006,0.778386,0.044702,0.058527,-0.005781, + 0.615482,0.005518,0.788132,0.043409,0.05966,-0.004818, + 0.622921,0.078006,0.778386,0.044702,0.058527,-0.005781, + 0.608032,-0.012608,0.793813,0.044645,0.059338,-0.005781, + 0.615482,0.005518,0.788132,0.043409,0.05966,-0.004818, + 0.608032,-0.012608,0.793813,0.044645,0.059338,-0.005781, + 0.587334,-0.078712,0.805508,0.043489,0.061186,-0.004818, + 0.563271,-0.124273,0.816873,0.044754,0.060662,-0.005781, + 0.587334,-0.078712,0.805508,0.043489,0.061186,-0.004818, + 0.608032,-0.012608,0.793813,0.044645,0.059338,-0.005781, + 0.587334,-0.078712,0.805508,0.043489,0.061186,-0.004818, + 0.563271,-0.124273,0.816873,0.044754,0.060662,-0.005781, + 0.528554,-0.194938,0.826214,0.043898,0.062655,-0.004818, + 0.498136,-0.2337,0.835012,0.045152,0.06193,-0.005781, + 0.528554,-0.194938,0.826214,0.043898,0.062655,-0.004818, + 0.563271,-0.124273,0.816873,0.044754,0.060662,-0.005781, + 0.528554,-0.194938,0.826214,0.043898,0.062655,-0.004818, + 0.498136,-0.2337,0.835012,0.045152,0.06193,-0.005781, + 0.454671,-0.294294,0.840634,0.044613,0.063997,-0.004818, + 0.419714,-0.3263,0.846976,0.04582,0.063079,-0.005781, + 0.454671,-0.294294,0.840634,0.044613,0.063997,-0.004818, + 0.498136,-0.2337,0.835012,0.045152,0.06193,-0.005781, + 0.454671,-0.294294,0.840634,0.044613,0.063997,-0.004818, + 0.419714,-0.3263,0.846976,0.04582,0.063079,-0.005781, + 0.369159,-0.377727,0.849143,0.0456,0.065145,-0.004818, + 0.33096,-0.403408,0.853069,0.046724,0.064053,-0.005781, + 0.369159,-0.377727,0.849143,0.0456,0.065145,-0.004818, + 0.419714,-0.3263,0.846976,0.04582,0.063079,-0.005781, + 0.369159,-0.377727,0.849143,0.0456,0.065145,-0.004818, + 0.33096,-0.403408,0.853069,0.046724,0.064053,-0.005781, + 0.273921,-0.44663,0.851756,0.046812,0.066043,-0.004818, + 0.233173,-0.466563,0.853199,0.04782,0.064804,-0.005781, + 0.273921,-0.44663,0.851756,0.046812,0.066043,-0.004818, + 0.33096,-0.403408,0.853069,0.046724,0.064053,-0.005781, + 0.273921,-0.44663,0.851756,0.046812,0.066043,-0.004818, + 0.233173,-0.466563,0.853199,0.04782,0.064804,-0.005781, + 0.169323,-0.502195,0.848015,0.048188,0.066646,-0.004818, + 0.126112,-0.516835,0.846745,0.049054,0.065295,-0.005781, + 0.169323,-0.502195,0.848015,0.048188,0.066646,-0.004818, + 0.233173,-0.466563,0.853199,0.04782,0.064804,-0.005781, + 0.169323,-0.502195,0.848015,0.048188,0.066646,-0.004818, + 0.126112,-0.516835,0.846745,0.049054,0.065295,-0.005781, + 0.054393,-0.544766,0.836822,0.04966,0.066926,-0.004818, + 0.00829,-0.554159,0.832369,0.050367,0.065502,-0.005781, + 0.054393,-0.544766,0.836822,0.04966,0.066926,-0.004818, + 0.126112,-0.516835,0.846745,0.049054,0.065295,-0.005781, + 0.054393,-0.544766,0.836822,0.04966,0.066926,-0.004818, + 0.00829,-0.554159,0.832369,0.050367,0.065502,-0.005781, + -0.072758,-0.573144,0.816219,0.051157,0.066867,-0.004818, + -0.12248,-0.576612,0.807785,0.051693,0.065415,-0.005781, + -0.072758,-0.573144,0.816219,0.051157,0.066867,-0.004818, + 0.00829,-0.554159,0.832369,0.050367,0.065502,-0.005781, + -0.072758,-0.573144,0.816219,0.051157,0.066867,-0.004818, + -0.12248,-0.576612,0.807785,0.051693,0.065415,-0.005781, + -0.241161,-0.582165,0.776482,0.052605,0.066474,-0.004818, + -0.248853,-0.582215,0.774014,0.052967,0.065039,-0.005781, + -0.241161,-0.582165,0.776482,0.052605,0.066474,-0.004818, + -0.12248,-0.576612,0.807785,0.051693,0.065415,-0.005781, + -0.248853,-0.582215,0.774014,0.052967,0.065039,-0.005781, + -0.375277,-0.56983,0.731068,0.054127,0.064391,-0.005781, + -0.241161,-0.582165,0.776482,0.052605,0.066474,-0.004818, + -0.434459,-0.558606,0.706544,0.053934,0.065766,-0.004818, + -0.241161,-0.582165,0.776482,0.052605,0.066474,-0.004818, + -0.375277,-0.56983,0.731068,0.054127,0.064391,-0.005781, + -0.375277,-0.56983,0.731068,0.054127,0.064391,-0.005781, + -0.563066,-0.515371,0.646025,0.055116,0.063504,-0.005781, + -0.434459,-0.558606,0.706544,0.053934,0.065766,-0.004818, + -0.558162,-0.527957,0.640091,0.055031,0.064761,-0.004818, + -0.434459,-0.558606,0.706544,0.053934,0.065766,-0.004818, + -0.563066,-0.515371,0.646025,0.055116,0.063504,-0.005781, + -0.558162,-0.527957,0.640091,0.055031,0.064761,-0.004818, + -0.563066,-0.515371,0.646025,0.055116,0.063504,-0.005781, + -0.627283,-0.480953,0.612536,0.055885,0.063727,-0.004818, + -0.641198,-0.455323,0.617694,0.055885,0.06242,-0.005781, + -0.627283,-0.480953,0.612536,0.055885,0.063727,-0.004818, + -0.563066,-0.515371,0.646025,0.055116,0.063504,-0.005781, + 0.641198,-0.455323,0.617694,0.055885,0.06242,-0.005781, + 0.584317,-0.505368,0.634963,0.056655,0.063504,-0.005781, + 0.627283,-0.480953,0.612536,0.055885,0.063727,-0.004818, + 0.53575,-0.534369,0.653775,0.056739,0.064761,-0.004818, + 0.627283,-0.480953,0.612536,0.055885,0.063727,-0.004818, + 0.584317,-0.505368,0.634963,0.056655,0.063504,-0.005781, + 0.584317,-0.505368,0.634963,0.056655,0.063504,-0.005781, + 0.438876,-0.557947,0.704332,0.057644,0.064391,-0.005781, + 0.53575,-0.534369,0.653775,0.056739,0.064761,-0.004818, + 0.377865,-0.569077,0.730322,0.057837,0.065766,-0.004818, + 0.53575,-0.534369,0.653775,0.056739,0.064761,-0.004818, + 0.438876,-0.557947,0.704332,0.057644,0.064391,-0.005781, + 0.438876,-0.557947,0.704332,0.057644,0.064391,-0.005781, + 0.267975,-0.579599,0.769581,0.058804,0.065039,-0.005781, + 0.377865,-0.569077,0.730322,0.057837,0.065766,-0.004818, + 0.214084,-0.583805,0.78316,0.059165,0.066474,-0.004818, + 0.377865,-0.569077,0.730322,0.057837,0.065766,-0.004818, + 0.267975,-0.579599,0.769581,0.058804,0.065039,-0.005781, + 0.267975,-0.579599,0.769581,0.058804,0.065039,-0.005781, + 0.12248,-0.576612,0.807785,0.060078,0.065415,-0.005781, + 0.214084,-0.583805,0.78316,0.059165,0.066474,-0.004818, + 0.072758,-0.573144,0.816219,0.060613,0.066867,-0.004818, + 0.214084,-0.583805,0.78316,0.059165,0.066474,-0.004818, + 0.12248,-0.576612,0.807785,0.060078,0.065415,-0.005781, + 0.12248,-0.576612,0.807785,0.060078,0.065415,-0.005781, + -0.00829,-0.554159,0.832369,0.061404,0.065502,-0.005781, + 0.072758,-0.573144,0.816219,0.060613,0.066867,-0.004818, + -0.054393,-0.544766,0.836822,0.06211,0.066926,-0.004818, + 0.072758,-0.573144,0.816219,0.060613,0.066867,-0.004818, + -0.00829,-0.554159,0.832369,0.061404,0.065502,-0.005781, + -0.00829,-0.554159,0.832369,0.061404,0.065502,-0.005781, + -0.126112,-0.516835,0.846745,0.062716,0.065295,-0.005781, + -0.054393,-0.544766,0.836822,0.06211,0.066926,-0.004818, + -0.169323,-0.502195,0.848015,0.063583,0.066646,-0.004818, + -0.054393,-0.544766,0.836822,0.06211,0.066926,-0.004818, + -0.126112,-0.516835,0.846745,0.062716,0.065295,-0.005781, + 0.622274,0.404734,0.670049,0.055885,0.043244,-0.004818, + 0.619748,0.407106,0.670953,0.055885,0.044839,-0.005781, + 0.611328,0.411243,0.676134,0.055414,0.04397,-0.004818, + -0.622274,0.404734,0.670049,0.055885,0.043244,-0.004818, + -0.611328,0.411243,0.676134,0.056357,0.04397,-0.004818, + -0.619748,0.407106,0.670953,0.055885,0.044839,-0.005781, + -0.600355,0.41774,0.681958,0.05631,0.04548,-0.005781, + -0.619748,0.407106,0.670953,0.055885,0.044839,-0.005781, + -0.611328,0.411243,0.676134,0.056357,0.04397,-0.004818, + -0.611328,0.411243,0.676134,0.056357,0.04397,-0.004818, + -0.583861,0.425853,0.691199,0.056856,0.044676,-0.004818, + -0.600355,0.41774,0.681958,0.05631,0.04548,-0.005781, + -0.573435,0.432324,0.695894,0.05676,0.046104,-0.005781, + -0.600355,0.41774,0.681958,0.05631,0.04548,-0.005781, + -0.583861,0.425853,0.691199,0.056856,0.044676,-0.004818, + -0.583861,0.425853,0.691199,0.056856,0.044676,-0.004818, + -0.557839,0.440321,0.703515,0.05738,0.045363,-0.004818, + -0.573435,0.432324,0.695894,0.05676,0.046104,-0.005781, + -0.547914,0.446817,0.707209,0.057232,0.046711,-0.005781, + -0.573435,0.432324,0.695894,0.05676,0.046104,-0.005781, + -0.557839,0.440321,0.703515,0.05738,0.045363,-0.004818, + -0.557839,0.440321,0.703515,0.05738,0.045363,-0.004818, + -0.528358,0.458036,0.714871,0.05793,0.046029,-0.004818, + -0.547914,0.446817,0.707209,0.057232,0.046711,-0.005781, + -0.525024,0.459644,0.716294,0.057728,0.047299,-0.005781, + -0.547914,0.446817,0.707209,0.057232,0.046711,-0.005781, + -0.528358,0.458036,0.714871,0.05793,0.046029,-0.004818, + -0.525024,0.459644,0.716294,0.057728,0.047299,-0.005781, + -0.528358,0.458036,0.714871,0.05793,0.046029,-0.004818, + -0.507344,0.470385,0.722039,0.058245,0.047867,-0.005781, + -0.502587,0.474851,0.722443,0.058505,0.046673,-0.004818, + -0.507344,0.470385,0.722039,0.058245,0.047867,-0.005781, + -0.528358,0.458036,0.714871,0.05793,0.046029,-0.004818, + -0.507344,0.470385,0.722039,0.058245,0.047867,-0.005781, + -0.502587,0.474851,0.722443,0.058505,0.046673,-0.004818, + -0.484849,0.48521,0.727662,0.058784,0.048416,-0.005781, + -0.480277,0.489774,0.727637,0.059103,0.047293,-0.004818, + -0.484849,0.48521,0.727662,0.058784,0.048416,-0.005781, + -0.502587,0.474851,0.722443,0.058505,0.046673,-0.004818, + -0.484849,0.48521,0.727662,0.058784,0.048416,-0.005781, + -0.480277,0.489774,0.727637,0.059103,0.047293,-0.004818, + -0.463202,0.500363,0.731492,0.059343,0.048943,-0.005781, + -0.458764,0.50505,0.731068,0.059724,0.047891,-0.004818, + -0.463202,0.500363,0.731492,0.059343,0.048943,-0.005781, + -0.480277,0.489774,0.727637,0.059103,0.047293,-0.004818, + -0.463202,0.500363,0.731492,0.059343,0.048943,-0.005781, + -0.458764,0.50505,0.731068,0.059724,0.047891,-0.004818, + -0.442255,0.515933,0.733637,0.059922,0.049449,-0.005781, + -0.437903,0.520767,0.732832,0.060366,0.048464,-0.004818, + -0.442255,0.515933,0.733637,0.059922,0.049449,-0.005781, + -0.458764,0.50505,0.731068,0.059724,0.047891,-0.004818, + -0.442255,0.515933,0.733637,0.059922,0.049449,-0.005781, + -0.437903,0.520767,0.732832,0.060366,0.048464,-0.004818, + -0.421867,0.532005,0.734165,0.06052,0.049933,-0.005781, + -0.417553,0.537009,0.732987,0.06103,0.049011,-0.004818, + -0.421867,0.532005,0.734165,0.06052,0.049933,-0.005781, + -0.437903,0.520767,0.732832,0.060366,0.048464,-0.004818, + -0.421867,0.532005,0.734165,0.06052,0.049933,-0.005781, + -0.417553,0.537009,0.732987,0.06103,0.049011,-0.004818, + -0.401898,0.548661,0.73311,0.061136,0.050393,-0.005781, + -0.397577,0.553859,0.731555,0.061714,0.049532,-0.004818, + -0.401898,0.548661,0.73311,0.061136,0.050393,-0.005781, + -0.417553,0.537009,0.732987,0.06103,0.049011,-0.004818, + -0.401898,0.548661,0.73311,0.061136,0.050393,-0.005781, + -0.397577,0.553859,0.731555,0.061714,0.049532,-0.004818, + -0.382209,0.565977,0.730469,0.061769,0.050829,-0.005781, + -0.377837,0.571394,0.728525,0.062416,0.050026,-0.004818, + -0.382209,0.565977,0.730469,0.061769,0.050829,-0.005781, + -0.397577,0.553859,0.731555,0.061714,0.049532,-0.004818, + -0.382209,0.565977,0.730469,0.061769,0.050829,-0.005781, + -0.377837,0.571394,0.728525,0.062416,0.050026,-0.004818, + -0.37698,0.573856,0.727032,0.062418,0.051241,-0.005781, + -0.379372,0.571846,0.727371,0.063137,0.050493,-0.004818, + -0.37698,0.573856,0.727032,0.062418,0.051241,-0.005781, + -0.377837,0.571394,0.728525,0.062416,0.050026,-0.004818, + -0.379372,0.571846,0.727371,0.063137,0.050493,-0.004818, + -0.405711,0.551851,0.728601,0.063888,0.051003,-0.004818, + -0.37698,0.573856,0.727032,0.062418,0.051241,-0.005781, + -0.403275,0.554082,0.72826,0.063095,0.051693,-0.005781, + -0.37698,0.573856,0.727032,0.062418,0.051241,-0.005781, + -0.405711,0.551851,0.728601,0.063888,0.051003,-0.004818, + -0.403275,0.554082,0.72826,0.063095,0.051693,-0.005781, + -0.405711,0.551851,0.728601,0.063888,0.051003,-0.004818, + -0.439698,0.520339,0.732061,0.063732,0.052198,-0.005781, + -0.455156,0.505988,0.732672,0.064596,0.051576,-0.004818, + -0.439698,0.520339,0.732061,0.063732,0.052198,-0.005781, + -0.405711,0.551851,0.728601,0.063888,0.051003,-0.004818, + -0.439698,0.520339,0.732061,0.063732,0.052198,-0.005781, + -0.455156,0.505988,0.732672,0.064596,0.051576,-0.004818, + -0.478388,0.479119,0.735928,0.064326,0.052755,-0.005781, + -0.492434,0.463571,0.736621,0.065254,0.052206,-0.004818, + -0.478388,0.479119,0.735928,0.064326,0.052755,-0.005781, + -0.455156,0.505988,0.732672,0.064596,0.051576,-0.004818, + -0.478388,0.479119,0.735928,0.064326,0.052755,-0.005781, + -0.492434,0.463571,0.736621,0.065254,0.052206,-0.004818, + -0.513034,0.434953,0.740008,0.06487,0.053359,-0.005781, + -0.525496,0.418365,0.740827,0.065859,0.05289,-0.004818, + -0.513034,0.434953,0.740008,0.06487,0.053359,-0.005781, + -0.492434,0.463571,0.736621,0.065254,0.052206,-0.004818, + -0.513034,0.434953,0.740008,0.06487,0.053359,-0.005781, + -0.525496,0.418365,0.740827,0.065859,0.05289,-0.004818, + -0.543337,0.388194,0.744372,0.065363,0.054006,-0.005781, + -0.554068,0.370754,0.745352,0.066406,0.053623,-0.004818, + -0.543337,0.388194,0.744372,0.065363,0.054006,-0.005781, + -0.525496,0.418365,0.740827,0.065859,0.05289,-0.004818, + -0.543337,0.388194,0.744372,0.065363,0.054006,-0.005781, + -0.554068,0.370754,0.745352,0.066406,0.053623,-0.004818, + -0.569031,0.339242,0.749078,0.065801,0.054691,-0.005781, + -0.577912,0.321162,0.750248,0.066892,0.054399,-0.004818, + -0.569031,0.339242,0.749078,0.065801,0.054691,-0.005781, + -0.554068,0.370754,0.745352,0.066406,0.053623,-0.004818, + -0.569031,0.339242,0.749078,0.065801,0.054691,-0.005781, + -0.577912,0.321162,0.750248,0.066892,0.054399,-0.004818, + -0.589896,0.288542,0.754166,0.06618,0.055411,-0.005781, + -0.596848,0.270049,0.755544,0.067313,0.055214,-0.004818, + -0.589896,0.288542,0.754166,0.06618,0.055411,-0.005781, + -0.577912,0.321162,0.750248,0.066892,0.054399,-0.004818, + -0.589896,0.288542,0.754166,0.06618,0.055411,-0.005781, + -0.596848,0.270049,0.755544,0.067313,0.055214,-0.004818, + -0.60577,0.236571,0.759656,0.066498,0.05616,-0.005781, + -0.610753,0.217903,0.761249,0.067666,0.056061,-0.004818, + -0.60577,0.236571,0.759656,0.066498,0.05616,-0.005781, + -0.596848,0.270049,0.755544,0.067313,0.055214,-0.004818, + -0.60577,0.236571,0.759656,0.066498,0.05616,-0.005781, + -0.610753,0.217903,0.761249,0.067666,0.056061,-0.004818, + -0.616557,0.183837,0.765546,0.066754,0.056932,-0.005781, + -0.619574,0.165232,0.767351,0.067949,0.056936,-0.004818, + -0.616557,0.183837,0.765546,0.066754,0.056932,-0.005781, + -0.610753,0.217903,0.761249,0.067666,0.056061,-0.004818, + -0.616557,0.183837,0.765546,0.066754,0.056932,-0.005781, + -0.619574,0.165232,0.767351,0.067949,0.056936,-0.004818, + -0.622238,0.13086,0.771813,0.066944,0.057723,-0.005781, + -0.623333,0.112547,0.773815,0.068161,0.057831,-0.004818, + -0.622238,0.13086,0.771813,0.066944,0.057723,-0.005781, + -0.619574,0.165232,0.767351,0.067949,0.056936,-0.004818, + -0.622238,0.13086,0.771813,0.066944,0.057723,-0.005781, + -0.623333,0.112547,0.773815,0.068161,0.057831,-0.004818, + -0.622921,0.078006,0.778386,0.067068,0.058527,-0.005781, + -0.622674,0.06887,0.779444,0.068298,0.058741,-0.004818, + -0.622921,0.078006,0.778386,0.067068,0.058527,-0.005781, + -0.623333,0.112547,0.773815,0.068161,0.057831,-0.004818, + -0.622921,0.078006,0.778386,0.067068,0.058527,-0.005781, + -0.622674,0.06887,0.779444,0.068298,0.058741,-0.004818, + -0.615482,0.005518,0.788132,0.068362,0.05966,-0.004818, + -0.622921,0.078006,0.778386,0.067068,0.058527,-0.005781, + -0.615482,0.005518,0.788132,0.068362,0.05966,-0.004818, + -0.608032,-0.012608,0.793813,0.067125,0.059338,-0.005781, + -0.615482,0.005518,0.788132,0.068362,0.05966,-0.004818, + -0.587334,-0.078712,0.805508,0.068281,0.061186,-0.004818, + -0.608032,-0.012608,0.793813,0.067125,0.059338,-0.005781, + -0.563271,-0.124273,0.816873,0.067016,0.060662,-0.005781, + -0.608032,-0.012608,0.793813,0.067125,0.059338,-0.005781, + -0.587334,-0.078712,0.805508,0.068281,0.061186,-0.004818, + -0.587334,-0.078712,0.805508,0.068281,0.061186,-0.004818, + -0.528554,-0.194938,0.826214,0.067873,0.062655,-0.004818, + -0.563271,-0.124273,0.816873,0.067016,0.060662,-0.005781, + -0.498136,-0.2337,0.835012,0.066618,0.06193,-0.005781, + -0.563271,-0.124273,0.816873,0.067016,0.060662,-0.005781, + -0.528554,-0.194938,0.826214,0.067873,0.062655,-0.004818, + -0.528554,-0.194938,0.826214,0.067873,0.062655,-0.004818, + -0.454671,-0.294294,0.840634,0.067158,0.063997,-0.004818, + -0.498136,-0.2337,0.835012,0.066618,0.06193,-0.005781, + -0.419714,-0.3263,0.846976,0.065951,0.063079,-0.005781, + -0.498136,-0.2337,0.835012,0.066618,0.06193,-0.005781, + -0.454671,-0.294294,0.840634,0.067158,0.063997,-0.004818, + -0.454671,-0.294294,0.840634,0.067158,0.063997,-0.004818, + -0.369159,-0.377727,0.849143,0.06617,0.065145,-0.004818, + -0.419714,-0.3263,0.846976,0.065951,0.063079,-0.005781, + -0.33096,-0.403408,0.853069,0.065047,0.064053,-0.005781, + -0.419714,-0.3263,0.846976,0.065951,0.063079,-0.005781, + -0.369159,-0.377727,0.849143,0.06617,0.065145,-0.004818, + -0.369159,-0.377727,0.849143,0.06617,0.065145,-0.004818, + -0.273921,-0.44663,0.851756,0.064959,0.066043,-0.004818, + -0.33096,-0.403408,0.853069,0.065047,0.064053,-0.005781, + -0.233173,-0.466563,0.853199,0.063951,0.064804,-0.005781, + -0.33096,-0.403408,0.853069,0.065047,0.064053,-0.005781, + -0.273921,-0.44663,0.851756,0.064959,0.066043,-0.004818, + -0.273921,-0.44663,0.851756,0.064959,0.066043,-0.004818, + -0.169323,-0.502195,0.848015,0.063583,0.066646,-0.004818, + -0.233173,-0.466563,0.853199,0.063951,0.064804,-0.005781 +}; +static const struct gllist frame={GL_N3F_V3F,GL_TRIANGLES,648,data,NULL}; +const struct gllist *companion_heart=&frame; diff --git a/hacks/glx/companion_quad.c b/hacks/glx/companion_quad.c new file mode 100644 index 00000000..3cfd2309 --- /dev/null +++ b/hacks/glx/companion_quad.c @@ -0,0 +1,389 @@ +#include "gllist.h" +static const float data[]={ + 0.11097,0.464834,-0.878416,0.79903,1.636364,-0.247442, + 0.138522,0.464654,-0.87459,0.773415,1.636364,-0.251499, + 0.138522,0.464654,-0.87459,0.775033,1.681818,-0.227094, + 0.11097,0.464834,-0.878416,0.79903,1.636364,-0.247442, + 0.138522,0.464654,-0.87459,0.775033,1.681818,-0.227094, + 0.11097,0.464834,-0.878416,0.796039,1.681818,-0.223767, + -0.917485,0.21303,-0.335916,0.757576,1.636364,-0.208242, + -0.917485,0.21303,-0.335916,0.757576,1.681818,-0.179415, + -0.917485,0.21303,-0.335916,0.775033,1.681818,-0.227094, + -0.917485,0.21303,-0.335916,0.757576,1.636364,-0.208242, + -0.917485,0.21303,-0.335916,0.775033,1.681818,-0.227094, + -0.917485,0.21303,-0.335916,0.773415,1.636364,-0.251499, + -1,0,0,0.757576,1.636364,-0.208242, + -1,0,0,0.757576,1.636364,-0.121212, + -1,0,0,0.757576,1.549333,-0.121212, + -1,0,0,0.757576,1.636364,-0.208242, + -1,0,0,0.757576,1.549333,-0.121212, + -1,0,0,0.757576,1.578161,-0.075758, + -1,0,0,0.757576,1.636364,-0.208242, + -1,0,0,0.757576,1.578161,-0.075758, + -1,0,0,0.757576,1.636364,-0.075758, + -1,0,0,0.757576,1.636364,-0.208242, + -1,0,0,0.757576,1.636364,-0.075758, + -1,0,0,0.757576,1.681818,-0.121212, + -1,0,0,0.757576,1.636364,-0.208242, + -1,0,0,0.757576,1.681818,-0.121212, + -1,0,0,0.757576,1.681818,-0.179415, + -0.917485,-0.335916,0.21303,0.757576,1.578161,-0.075758, + -0.917485,-0.335916,0.21303,0.757576,1.549333,-0.121212, + -0.917485,-0.335916,0.21303,0.773415,1.506076,-0.121212, + -0.917485,-0.335916,0.21303,0.757576,1.578161,-0.075758, + -0.917485,-0.335916,0.21303,0.773415,1.506076,-0.121212, + -0.917485,-0.335916,0.21303,0.775033,1.530482,-0.075758, + 0.138522,-0.87459,0.464654,0.773415,1.506076,-0.121212, + 0.11097,-0.878416,0.464834,0.79903,1.510133,-0.121212, + 0.11097,-0.878416,0.464834,0.796039,1.533809,-0.075758, + 0.138522,-0.87459,0.464654,0.773415,1.506076,-0.121212, + 0.11097,-0.878416,0.464834,0.796039,1.533809,-0.075758, + 0.138522,-0.87459,0.464654,0.775033,1.530482,-0.075758, + 0.11097,-0.878416,0.464834,0.796039,1.533809,-0.075758, + 0.11097,-0.878416,0.464834,0.79903,1.510133,-0.121212, + 0.055595,-0.883651,0.464834,0.83883,1.513897,-0.121212, + 0.11097,-0.878416,0.464834,0.796039,1.533809,-0.075758, + 0.055595,-0.883651,0.464834,0.83883,1.513897,-0.121212, + 0.055595,-0.883651,0.464834,0.837333,1.537712,-0.075758, + 0.055595,-0.883651,0.464834,0.837333,1.537712,-0.075758, + 0.055595,-0.883651,0.464834,0.83883,1.513897,-0.121212, + 0,-0.885398,0.464834,0.878788,1.515152,-0.121212, + 0.055595,-0.883651,0.464834,0.837333,1.537712,-0.075758, + 0,-0.885398,0.464834,0.878788,1.515152,-0.121212, + 0,-0.885398,0.464834,0.878788,1.539015,-0.075758, + -0.055595,-0.883651,0.464834,0.918745,1.513897,-0.121212, + -0.055595,-0.883651,0.464834,0.920242,1.537712,-0.075758, + 0,-0.885398,0.464834,0.878788,1.539015,-0.075758, + -0.055595,-0.883651,0.464834,0.918745,1.513897,-0.121212, + 0,-0.885398,0.464834,0.878788,1.539015,-0.075758, + 0,-0.885398,0.464834,0.878788,1.515152,-0.121212, + -0.11097,-0.878416,0.464834,0.958545,1.510133,-0.121212, + -0.11097,-0.878416,0.464834,0.961536,1.533809,-0.075758, + -0.055595,-0.883651,0.464834,0.920242,1.537712,-0.075758, + -0.11097,-0.878416,0.464834,0.958545,1.510133,-0.121212, + -0.055595,-0.883651,0.464834,0.920242,1.537712,-0.075758, + -0.055595,-0.883651,0.464834,0.918745,1.513897,-0.121212, + -0.11097,-0.878416,0.464834,0.958545,1.510133,-0.121212, + -0.138522,-0.87459,0.464654,0.984161,1.506076,-0.121212, + -0.138522,-0.87459,0.464654,0.982542,1.530482,-0.075758, + -0.11097,-0.878416,0.464834,0.958545,1.510133,-0.121212, + -0.138522,-0.87459,0.464654,0.982542,1.530482,-0.075758, + -0.11097,-0.878416,0.464834,0.961536,1.533809,-0.075758, + 0.917485,-0.335916,0.21303,1,1.549333,-0.121212, + 0.917485,-0.335916,0.21303,1,1.578161,-0.075758, + 0.917485,-0.335916,0.21303,0.982542,1.530482,-0.075758, + 0.917485,-0.335916,0.21303,1,1.549333,-0.121212, + 0.917485,-0.335916,0.21303,0.982542,1.530482,-0.075758, + 0.917485,-0.335916,0.21303,0.984161,1.506076,-0.121212, + 1,0,0,1,1.636364,-0.121212, + 1,0,0,1,1.636364,-0.208242, + 1,0,0,1,1.681818,-0.179415, + 1,0,0,1,1.636364,-0.121212, + 1,0,0,1,1.681818,-0.179415, + 1,0,0,1,1.681818,-0.121212, + 1,0,0,1,1.636364,-0.121212, + 1,0,0,1,1.681818,-0.121212, + 1,0,0,1,1.636364,-0.075758, + 1,0,0,1,1.636364,-0.121212, + 1,0,0,1,1.636364,-0.075758, + 1,0,0,1,1.578161,-0.075758, + 1,0,0,1,1.636364,-0.121212, + 1,0,0,1,1.578161,-0.075758, + 1,0,0,1,1.549333,-0.121212, + 0.917485,0.21303,-0.335916,1,1.681818,-0.179415, + 0.917485,0.21303,-0.335916,1,1.636364,-0.208242, + 0.917485,0.21303,-0.335916,0.984161,1.636364,-0.251499, + 0.917485,0.21303,-0.335916,1,1.681818,-0.179415, + 0.917485,0.21303,-0.335916,0.984161,1.636364,-0.251499, + 0.917485,0.21303,-0.335916,0.982542,1.681818,-0.227094, + -0.138522,0.464654,-0.87459,0.984161,1.636364,-0.251499, + -0.11097,0.464834,-0.878416,0.958545,1.636364,-0.247442, + -0.11097,0.464834,-0.878416,0.961536,1.681818,-0.223767, + -0.138522,0.464654,-0.87459,0.984161,1.636364,-0.251499, + -0.11097,0.464834,-0.878416,0.961536,1.681818,-0.223767, + -0.138522,0.464654,-0.87459,0.982542,1.681818,-0.227094, + -0.11097,0.464834,-0.878416,0.961536,1.681818,-0.223767, + -0.11097,0.464834,-0.878416,0.958545,1.636364,-0.247442, + -0.055595,0.464834,-0.883651,0.918745,1.636364,-0.24368, + -0.11097,0.464834,-0.878416,0.961536,1.681818,-0.223767, + -0.055595,0.464834,-0.883651,0.918745,1.636364,-0.24368, + -0.055595,0.464834,-0.883651,0.920242,1.681818,-0.219863, + -0.055595,0.464834,-0.883651,0.920242,1.681818,-0.219863, + -0.055595,0.464834,-0.883651,0.918745,1.636364,-0.24368, + 0,0.464834,-0.885398,0.878788,1.636364,-0.242424, + -0.055595,0.464834,-0.883651,0.920242,1.681818,-0.219863, + 0,0.464834,-0.885398,0.878788,1.636364,-0.242424, + 0,0.464834,-0.885398,0.878788,1.681818,-0.218561, + 0.055595,0.464834,-0.883651,0.83883,1.636364,-0.24368, + 0.055595,0.464834,-0.883651,0.837333,1.681818,-0.219863, + 0,0.464834,-0.885398,0.878788,1.681818,-0.218561, + 0.055595,0.464834,-0.883651,0.83883,1.636364,-0.24368, + 0,0.464834,-0.885398,0.878788,1.681818,-0.218561, + 0,0.464834,-0.885398,0.878788,1.636364,-0.242424, + 0.11097,0.464834,-0.878416,0.79903,1.636364,-0.247442, + 0.11097,0.464834,-0.878416,0.796039,1.681818,-0.223767, + 0.055595,0.464834,-0.883651,0.837333,1.681818,-0.219863, + 0.11097,0.464834,-0.878416,0.79903,1.636364,-0.247442, + 0.055595,0.464834,-0.883651,0.837333,1.681818,-0.219863, + 0.055595,0.464834,-0.883651,0.83883,1.636364,-0.24368, + 0,1,0,0.920242,1.681818,-0.219863, + 0,1,0,0.878788,1.681818,-0.218561, + 0,1,0,0.837333,1.681818,-0.219863, + 0,1,0,0.920242,1.681818,-0.219863, + 0,1,0,0.837333,1.681818,-0.219863, + 0,1,0,0.796039,1.681818,-0.223767, + 0,1,0,0.920242,1.681818,-0.219863, + 0,1,0,0.796039,1.681818,-0.223767, + 0,1,0,0.775033,1.681818,-0.227094, + 0,1,0,0.920242,1.681818,-0.219863, + 0,1,0,0.775033,1.681818,-0.227094, + 0,1,0,0.757576,1.681818,-0.179415, + 0,1,0,0.920242,1.681818,-0.219863, + 0,1,0,0.757576,1.681818,-0.179415, + 0,1,0,0.757576,1.681818,-0.121212, + 0,1,0,0.920242,1.681818,-0.219863, + 0,1,0,0.757576,1.681818,-0.121212, + 0,1,0,1,1.681818,-0.121212, + 0,1,0,0.920242,1.681818,-0.219863, + 0,1,0,1,1.681818,-0.121212, + 0,1,0,1,1.681818,-0.179415, + 0,1,0,0.920242,1.681818,-0.219863, + 0,1,0,1,1.681818,-0.179415, + 0,1,0,0.982542,1.681818,-0.227094, + 0,1,0,0.920242,1.681818,-0.219863, + 0,1,0,0.982542,1.681818,-0.227094, + 0,1,0,0.961536,1.681818,-0.223767, + 0,0.707107,0.707107,0.757576,1.681818,-0.121212, + 0,0.707107,0.707107,0.757576,1.636364,-0.075758, + 0,0.707107,0.707107,1,1.636364,-0.075758, + 0,0.707107,0.707107,0.757576,1.681818,-0.121212, + 0,0.707107,0.707107,1,1.636364,-0.075758, + 0,0.707107,0.707107,1,1.681818,-0.121212, + 0,0,1,1,1.578161,-0.075758, + 0,0,1,1,1.636364,-0.075758, + 0,0,1,0.757576,1.636364,-0.075758, + 0,0,1,1,1.578161,-0.075758, + 0,0,1,0.757576,1.636364,-0.075758, + 0,0,1,0.757576,1.578161,-0.075758, + 0,0,1,1,1.578161,-0.075758, + 0,0,1,0.757576,1.578161,-0.075758, + 0,0,1,0.775033,1.530482,-0.075758, + 0,0,1,1,1.578161,-0.075758, + 0,0,1,0.775033,1.530482,-0.075758, + 0,0,1,0.796039,1.533809,-0.075758, + 0,0,1,1,1.578161,-0.075758, + 0,0,1,0.796039,1.533809,-0.075758, + 0,0,1,0.837333,1.537712,-0.075758, + 0,0,1,1,1.578161,-0.075758, + 0,0,1,0.837333,1.537712,-0.075758, + 0,0,1,0.878788,1.539015,-0.075758, + 0,0,1,1,1.578161,-0.075758, + 0,0,1,0.878788,1.539015,-0.075758, + 0,0,1,0.920242,1.537712,-0.075758, + 0,0,1,1,1.578161,-0.075758, + 0,0,1,0.920242,1.537712,-0.075758, + 0,0,1,0.961536,1.533809,-0.075758, + 0,0,1,1,1.578161,-0.075758, + 0,0,1,0.961536,1.533809,-0.075758, + 0,0,1,0.982542,1.530482,-0.075758, + 0,0,1,0.121212,1.636364,0, + 0,0,1,0.121212,1.125055,0, + 0,0,1,0.223833,1.125055,0, + 0,0,1,0.121212,1.636364,0, + 0,0,1,0.223833,1.125055,0, + 0,0,1,0.227944,1.136476,0, + 0,0,1,0.121212,1.636364,0, + 0,0,1,0.227944,1.136476,0, + 0,0,1,0.245409,1.176833,0, + 0,0,1,0.121212,1.636364,0, + 0,0,1,0.245409,1.176833,0, + 0,0,1,0.265373,1.216015,0, + 0,0,1,0.121212,1.636364,0, + 0,0,1,0.265373,1.216015,0, + 0,0,1,0.287758,1.253867,0, + 0,0,1,0.121212,1.636364,0, + 0,0,1,0.287758,1.253867,0, + 0,0,1,0.312476,1.290236,0, + 0,0,1,0.121212,1.636364,0, + 0,0,1,0.312476,1.290236,0, + 0,0,1,0.339427,1.324985,0, + 0,0,1,0.121212,1.636364,0, + 0,0,1,0.339427,1.324985,0, + 0,0,1,0.368509,1.35797,0, + 0,0,1,0.121212,1.636364,0, + 0,0,1,0.368509,1.35797,0, + 0,0,1,0.399606,1.389067,0, + 0,0,1,0.121212,1.636364,0, + 0,0,1,0.399606,1.389067,0, + 0,0,1,0.432591,1.418148,0, + 0,0,1,0.121212,1.636364,0, + 0,0,1,0.432591,1.418148,0, + 0,0,1,0.467339,1.4451,0, + 0,0,1,0.121212,1.636364,0, + 0,0,1,0.467339,1.4451,0, + 0,0,1,0.503709,1.469818,0, + 0,0,1,0.121212,1.636364,0, + 0,0,1,0.503709,1.469818,0, + 0,0,1,0.541561,1.492203,0, + 0,0,1,0.121212,1.636364,0, + 0,0,1,0.541561,1.492203,0, + 0,0,1,0.580742,1.512167,0, + 0,0,1,0.121212,1.636364,0, + 0,0,1,0.580742,1.512167,0, + 0,0,1,0.6211,1.52963,0, + 0,0,1,0.121212,1.636364,0, + 0,0,1,0.6211,1.52963,0, + 0,0,1,0.632521,1.533742,0, + 0,0,1,0.121212,1.636364,0, + 0,0,1,0.632521,1.533742,0, + 0,0,1,0.632521,1.636364,0, + 0,0,1,0.121212,1.636364,0, + 0,0,1,0.632521,1.636364,0, + 0,0,1,0.121212,1.636364,0, + 0,0,1,0.121212,1.636364,0, + 0,0,1,0.121212,1.636364,0, + 0,0,1,0.121212,1.125055,0, + 0.645427,-0.606097,0.464834,0.4149,1.314409,-0.121212, + 0.645427,-0.606097,0.464834,0.368509,1.35797,0, + 0.682211,-0.564374,0.464834,0.339427,1.324985,0, + 0.645427,-0.606097,0.464834,0.4149,1.314409,-0.121212, + 0.682211,-0.564374,0.464834,0.339427,1.324985,0, + 0.682211,-0.564374,0.464834,0.388461,1.284421,-0.121212, + 0.645427,-0.606097,0.464834,0.368509,1.35797,0, + 0.645427,-0.606097,0.464834,0.4149,1.314409,-0.121212, + 0.606097,-0.645427,0.464834,0.443167,1.342676,-0.121212, + 0.645427,-0.606097,0.464834,0.368509,1.35797,0, + 0.606097,-0.645427,0.464834,0.443167,1.342676,-0.121212, + 0.606097,-0.645427,0.464834,0.399606,1.389067,0, + 0.606097,-0.645427,0.464834,0.399606,1.389067,0, + 0.606097,-0.645427,0.464834,0.443167,1.342676,-0.121212, + 0.564374,-0.682211,0.464834,0.473155,1.369115,-0.121212, + 0.606097,-0.645427,0.464834,0.399606,1.389067,0, + 0.564374,-0.682211,0.464834,0.473155,1.369115,-0.121212, + 0.564374,-0.682211,0.464834,0.432591,1.418148,0, + 0.564374,-0.682211,0.464834,0.432591,1.418148,0, + 0.564374,-0.682211,0.464834,0.473155,1.369115,-0.121212, + 0.520424,-0.716302,0.464834,0.504742,1.393618,-0.121212, + 0.564374,-0.682211,0.464834,0.432591,1.418148,0, + 0.520424,-0.716302,0.464834,0.504742,1.393618,-0.121212, + 0.520424,-0.716302,0.464834,0.467339,1.4451,0, + 0.520424,-0.716302,0.464834,0.467339,1.4451,0, + 0.520424,-0.716302,0.464834,0.504742,1.393618,-0.121212, + 0.47442,-0.747566,0.464834,0.537806,1.416088,-0.121212, + 0.520424,-0.716302,0.464834,0.467339,1.4451,0, + 0.47442,-0.747566,0.464834,0.537806,1.416088,-0.121212, + 0.47442,-0.747566,0.464834,0.503709,1.469818,0, + 0.47442,-0.747566,0.464834,0.503709,1.469818,0, + 0.47442,-0.747566,0.464834,0.537806,1.416088,-0.121212, + 0.426544,-0.77588,0.464834,0.572218,1.436436,-0.121212, + 0.47442,-0.747566,0.464834,0.503709,1.469818,0, + 0.426544,-0.77588,0.464834,0.572218,1.436436,-0.121212, + 0.426544,-0.77588,0.464834,0.541561,1.492203,0, + 0.426544,-0.77588,0.464834,0.541561,1.492203,0, + 0.426544,-0.77588,0.464834,0.572218,1.436436,-0.121212, + 0.376984,-0.801132,0.464834,0.607836,1.454588,-0.121212, + 0.426544,-0.77588,0.464834,0.541561,1.492203,0, + 0.376984,-0.801132,0.464834,0.607836,1.454588,-0.121212, + 0.376984,-0.801132,0.464834,0.580742,1.512167,0, + 0.376984,-0.801132,0.464834,0.580742,1.512167,0, + 0.376984,-0.801132,0.464834,0.607836,1.454588,-0.121212, + 0.325937,-0.823222,0.464834,0.644527,1.470464,-0.121212, + 0.376984,-0.801132,0.464834,0.580742,1.512167,0, + 0.325937,-0.823222,0.464834,0.644527,1.470464,-0.121212, + 0.325937,-0.823222,0.464834,0.6211,1.52963,0, + 0.29995,-0.833143,0.464654,0.632521,1.533742,0, + 0.325937,-0.823222,0.464834,0.6211,1.52963,0, + 0.325937,-0.823222,0.464834,0.644527,1.470464,-0.121212, + 0.29995,-0.833143,0.464654,0.632521,1.533742,0, + 0.325937,-0.823222,0.464834,0.644527,1.470464,-0.121212, + 0.273603,-0.842063,0.464834,0.682139,1.484006,-0.121212, + 0.29995,-0.833143,0.464654,0.632521,1.533742,0, + 0.273603,-0.842063,0.464834,0.682139,1.484006,-0.121212, + 0.273603,-0.842063,0.464834,0.67563,1.504045,-0.081077, + 0.273603,-0.842063,0.464834,0.67563,1.504045,-0.081077, + 0.273603,-0.842063,0.464834,0.682139,1.484006,-0.121212, + 0.247044,-0.850333,0.464654,0.69697,1.488315,-0.121212, + 0.882948,0,0.469472,0.632521,1.636364,0, + 0.882948,0,0.469472,0.632521,1.533742,0, + 0.882948,0,0.469472,0.67563,1.504045,-0.081077, + 0.882948,0,0.469472,0.632521,1.636364,0, + 0.882948,0,0.469472,0.67563,1.504045,-0.081077, + 0.882948,0,0.469472,0.69697,1.488315,-0.121212, + 0.882948,0,0.469472,0.632521,1.636364,0, + 0.882948,0,0.469472,0.69697,1.488315,-0.121212, + 0.882948,0,0.469472,0.69697,1.636364,-0.121212, + 0.799251,0.424969,0.424969,0.69697,1.636364,-0.121212, + 0.799251,0.424969,0.424969,0.632521,1.757576,-0.121212, + 0.799251,0.424969,0.424969,0.632521,1.636364,0, + 0,0.707107,0.707107,0.632521,1.757576,-0.121212, + 0,0.707107,0.707107,0.121212,1.757576,-0.121212, + 0,0.707107,0.707107,0.121212,1.636364,0, + 0,0.707107,0.707107,0.632521,1.757576,-0.121212, + 0,0.707107,0.707107,0.121212,1.636364,0, + 0,0.707107,0.707107,0.632521,1.636364,0, + -0.57735,0.57735,0.57735,0.121212,1.757576,-0.121212, + -0.57735,0.57735,0.57735,0,1.636364,-0.121212, + -0.57735,0.57735,0.57735,0.121212,1.636364,0, + -0.707107,0,0.707107,0,1.636364,-0.121212, + -0.707107,0,0.707107,0,1.125055,-0.121212, + -0.707107,0,0.707107,0.121212,1.125055,0, + -0.707107,0,0.707107,0,1.636364,-0.121212, + -0.707107,0,0.707107,0.121212,1.125055,0, + -0.707107,0,0.707107,0.121212,1.636364,0, + -0.424969,-0.799251,0.424969,0,1.125055,-0.121212, + -0.424969,-0.799251,0.424969,0.121212,1.060606,-0.121212, + -0.424969,-0.799251,0.424969,0.121212,1.125055,0, + 0,-0.882948,0.469472,0.223833,1.125055,0, + 0,-0.882948,0.469472,0.121212,1.125055,0, + 0,-0.882948,0.469472,0.121212,1.060606,-0.121212, + 0,-0.882948,0.469472,0.223833,1.125055,0, + 0,-0.882948,0.469472,0.121212,1.060606,-0.121212, + 0,-0.882948,0.469472,0.269262,1.060606,-0.121212, + 0,-0.882948,0.469472,0.223833,1.125055,0, + 0,-0.882948,0.469472,0.269262,1.060606,-0.121212, + 0,-0.882948,0.469472,0.25353,1.081945,-0.081077, + 0.842063,-0.273603,0.464834,0.27357,1.075436,-0.121212, + 0.842063,-0.273603,0.464834,0.25353,1.081945,-0.081077, + 0.850333,-0.247044,0.464654,0.269262,1.060606,-0.121212, + 0.823222,-0.325937,0.464834,0.227944,1.136476,0, + 0.833143,-0.29995,0.464654,0.223833,1.125055,0, + 0.842063,-0.273603,0.464834,0.25353,1.081945,-0.081077, + 0.823222,-0.325937,0.464834,0.227944,1.136476,0, + 0.842063,-0.273603,0.464834,0.25353,1.081945,-0.081077, + 0.842063,-0.273603,0.464834,0.27357,1.075436,-0.121212, + 0.823222,-0.325937,0.464834,0.227944,1.136476,0, + 0.842063,-0.273603,0.464834,0.27357,1.075436,-0.121212, + 0.823222,-0.325937,0.464834,0.287112,1.113048,-0.121212, + 0.801132,-0.376984,0.464834,0.302989,1.149739,-0.121212, + 0.801132,-0.376984,0.464834,0.245409,1.176833,0, + 0.823222,-0.325937,0.464834,0.227944,1.136476,0, + 0.801132,-0.376984,0.464834,0.302989,1.149739,-0.121212, + 0.823222,-0.325937,0.464834,0.227944,1.136476,0, + 0.823222,-0.325937,0.464834,0.287112,1.113048,-0.121212, + 0.77588,-0.426544,0.464834,0.321139,1.185358,-0.121212, + 0.77588,-0.426544,0.464834,0.265373,1.216015,0, + 0.801132,-0.376984,0.464834,0.245409,1.176833,0, + 0.77588,-0.426544,0.464834,0.321139,1.185358,-0.121212, + 0.801132,-0.376984,0.464834,0.245409,1.176833,0, + 0.801132,-0.376984,0.464834,0.302989,1.149739,-0.121212, + 0.747566,-0.47442,0.464834,0.341488,1.21977,-0.121212, + 0.747566,-0.47442,0.464834,0.287758,1.253867,0, + 0.77588,-0.426544,0.464834,0.265373,1.216015,0, + 0.747566,-0.47442,0.464834,0.341488,1.21977,-0.121212, + 0.77588,-0.426544,0.464834,0.265373,1.216015,0, + 0.77588,-0.426544,0.464834,0.321139,1.185358,-0.121212, + 0.716302,-0.520424,0.464834,0.363958,1.252833,-0.121212, + 0.716302,-0.520424,0.464834,0.312476,1.290236,0, + 0.747566,-0.47442,0.464834,0.287758,1.253867,0, + 0.716302,-0.520424,0.464834,0.363958,1.252833,-0.121212, + 0.747566,-0.47442,0.464834,0.287758,1.253867,0, + 0.747566,-0.47442,0.464834,0.341488,1.21977,-0.121212, + 0.682211,-0.564374,0.464834,0.388461,1.284421,-0.121212, + 0.682211,-0.564374,0.464834,0.339427,1.324985,0, + 0.716302,-0.520424,0.464834,0.312476,1.290236,0, + 0.682211,-0.564374,0.464834,0.388461,1.284421,-0.121212, + 0.716302,-0.520424,0.464834,0.312476,1.290236,0, + 0.716302,-0.520424,0.464834,0.363958,1.252833,-0.121212 +}; +static const struct gllist frame={GL_N3F_V3F,GL_TRIANGLES,384,data,NULL}; +const struct gllist *companion_quad=&frame; diff --git a/hacks/glx/companioncube.man b/hacks/glx/companioncube.man new file mode 100644 index 00000000..e15b15eb --- /dev/null +++ b/hacks/glx/companioncube.man @@ -0,0 +1,85 @@ +.TH XScreenSaver 1 "" "X Version 11" +.SH NAME +companioncube - a vital aparatus. +.SH SYNOPSIS +.B companioncube +[\-display \fIhost:display.screen\fP] +[\-visual \fIvisual\fP] +[\-window] +[\-root] +[\-delay \fInumber\fP] +[\-speed \fIratio\fP] +[\-spin] +[\-wander] +[\-count \fInumber\fP] +[\-wireframe] +[\-fps] +.SH DESCRIPTION +The symptoms most commonly produced by Enrichment Center testing are +superstition, perceiving inanimate objects as alive, and hallucinations. +The Enrichment Center reminds you that the weighted companion cube will +never threaten to stab you and, in fact, cannot speak. In the event that +the Weighted Companion Cube does speak, the Enrichment Center urges you to +disregard its advice. +.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 \-speed \fInumber\fP +How fast the animation should run. +Less than 1 for slower, greater than 1 for faster. +.TP 8 +.B \-count \fInumber\fP +How many cubes. Default 3. +.TP 8 +.B \-spin +.B \-no\-spin +Instead of bouncing, float and spin. +.TP 8 +.B \-wander +.B \-no\-wander +Instead of bouncing, float and drift. +.TP 8 +.B \-wireframe +Render in wireframe instead of solid. +.TP 8 +.B \-fps +Display the current frame rate, CPU load, and polygon count. +.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 tronbit (1), +.BR lament (1), +.BR dangerball (1), +.BR xscreensaver (1) +.SH COPYRIGHT +Copyright \(co 2011 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, with apologies to the fine folks at Valve Software +and Aperture Science. diff --git a/hacks/glx/cow_face.c b/hacks/glx/cow_face.c new file mode 100644 index 00000000..e57d2bbc --- /dev/null +++ b/hacks/glx/cow_face.c @@ -0,0 +1,341 @@ +#include "gllist.h" +static const float data[]={ + 0.193291,-0.074799,-0.978286,4.897808,1.946794,-0.628057, + 0.133638,0.26732,-0.954296,4.925394,1.955229,-0.618837, + 0.555353,0.50765,-0.658692,4.953739,1.95258,-0.592256, + 0.193291,-0.074799,-0.978286,4.897808,1.946794,-0.628057, + 0.555353,0.50765,-0.658692,4.953739,1.95258,-0.592256, + 0.823157,0.134624,-0.551625,4.971872,1.924079,-0.586026, + 0.193291,-0.074799,-0.978286,4.897808,1.946794,-0.628057, + 0.823157,0.134624,-0.551625,4.971872,1.924079,-0.586026, + 0.774925,-0.116115,-0.621296,4.953403,1.907939,-0.605609, + 0.193291,-0.074799,-0.978286,4.897808,1.946794,-0.628057, + 0.774925,-0.116115,-0.621296,4.953403,1.907939,-0.605609, + 0.546619,0.025491,-0.836994,4.925499,1.917814,-0.613413, + 0.872792,-0.115436,-0.474246,4.973133,1.992779,-0.533466, + 0.412833,-0.156453,-0.897269,5.001903,1.914398,-0.486724, + 0.823157,0.134624,-0.551625,4.971872,1.924079,-0.586026, + 0.872792,-0.115436,-0.474246,4.973133,1.992779,-0.533466, + 0.823157,0.134624,-0.551625,4.971872,1.924079,-0.586026, + 0.555353,0.50765,-0.658692,4.953739,1.95258,-0.592256, + 0.823157,0.134624,-0.551625,4.971872,1.924079,-0.586026, + 0.412833,-0.156453,-0.897269,5.001903,1.914398,-0.486724, + 0.108828,-0.182644,-0.977137,4.982364,1.8733,-0.53619, + 0.823157,0.134624,-0.551625,4.971872,1.924079,-0.586026, + 0.108828,-0.182644,-0.977137,4.982364,1.8733,-0.53619, + 0.774925,-0.116115,-0.621296,4.953403,1.907939,-0.605609, + 0.774925,-0.116115,-0.621296,4.953403,1.907939,-0.605609, + 0.108828,-0.182644,-0.977137,4.982364,1.8733,-0.53619, + 0.746476,-0.187741,-0.638379,4.926194,1.859813,-0.582137, + 0.546619,0.025491,-0.836994,4.925499,1.917814,-0.613413, + 0.774925,-0.116115,-0.621296,4.953403,1.907939,-0.605609, + 0.746476,-0.187741,-0.638379,4.926194,1.859813,-0.582137, + 0.546619,0.025491,-0.836994,4.925499,1.917814,-0.613413, + 0.746476,-0.187741,-0.638379,4.926194,1.859813,-0.582137, + 0.897742,-0.15037,-0.414063,4.852578,1.889721,-0.605031, + 0.193291,-0.074799,-0.978286,4.897808,1.946794,-0.628057, + 0.546619,0.025491,-0.836994,4.925499,1.917814,-0.613413, + 0.897742,-0.15037,-0.414063,4.852578,1.889721,-0.605031, + 0.193291,-0.074799,-0.978286,4.897808,1.946794,-0.628057, + 0.897742,-0.15037,-0.414063,4.852578,1.889721,-0.605031, + 0.544735,0.449335,-0.708069,4.824747,1.946835,-0.626358, + 0.193291,-0.074799,-0.978286,4.897808,1.946794,-0.628057, + 0.544735,0.449335,-0.708069,4.824747,1.946835,-0.626358, + 0.721999,0.398917,-0.565316,4.861611,2.001639,-0.621913, + 0.711192,0.127662,-0.69131,4.935561,2.016016,-0.5857, + 0.872792,-0.115436,-0.474246,4.973133,1.992779,-0.533466, + 0.555353,0.50765,-0.658692,4.953739,1.95258,-0.592256, + 0.711192,0.127662,-0.69131,4.935561,2.016016,-0.5857, + 0.555353,0.50765,-0.658692,4.953739,1.95258,-0.592256, + 0.133638,0.26732,-0.954296,4.925394,1.955229,-0.618837, + 0.909103,0.416568,-0.001454,5.908782,1.066916,0.001121, + 0.535268,0.844682,0.000171,5.871947,1.021428,0.001102, + -0.091049,-0.145989,-0.985087,5.897758,1.009309,-0.080583, + 0.909103,0.416568,-0.001454,5.908782,1.066916,0.001121, + -0.091049,-0.145989,-0.985087,5.897758,1.009309,-0.080583, + 0.054456,-0.320459,-0.945696,5.934596,1.054796,-0.077039, + 0.054456,-0.320459,-0.945696,5.934596,1.054796,-0.077039, + -0.091049,-0.145989,-0.985087,5.897758,1.009309,-0.080583, + -0.126433,-0.433465,-0.892257,5.87863,0.986485,-0.128292, + 0.054456,-0.320459,-0.945696,5.934596,1.054796,-0.077039, + -0.126433,-0.433465,-0.892257,5.87863,0.986485,-0.128292, + 0.169576,-0.140705,-0.975421,5.923808,1.025283,-0.153084, + 0.169576,-0.140705,-0.975421,5.923808,1.025283,-0.153084, + -0.126433,-0.433465,-0.892257,5.87863,0.986485,-0.128292, + 0.256335,-0.2349,-0.937611,5.757506,0.9579,-0.210732, + 0.169576,-0.140705,-0.975421,5.923808,1.025283,-0.153084, + 0.256335,-0.2349,-0.937611,5.757506,0.9579,-0.210732, + 0.120494,-0.516376,-0.847843,5.85775,0.997026,-0.236768, + 0.396941,-0.593504,-0.700137,5.755282,1.004149,-0.307505, + 0.120494,-0.516376,-0.847843,5.85775,0.997026,-0.236768, + 0.256335,-0.2349,-0.937611,5.757506,0.9579,-0.210732, + 0.396941,-0.593504,-0.700137,5.755282,1.004149,-0.307505, + 0.256335,-0.2349,-0.937611,5.757506,0.9579,-0.210732, + 0.204472,-0.587725,-0.782797,5.674999,0.950754,-0.22796, + 0.485455,-0.874253,0.003847,5.895899,1.18273,-0.164705, + 0.223936,-0.919046,-0.324355,5.959462,1.157227,-0.187097, + 0.051115,-0.906355,-0.419414,5.912147,1.117911,-0.254197, + 0.035706,-0.99787,-0.054588,5.849792,1.19348,-0.181047, + 0.485455,-0.874253,0.003847,5.895899,1.18273,-0.164705, + 0.051115,-0.906355,-0.419414,5.912147,1.117911,-0.254197, + 0.035706,-0.99787,-0.054588,5.849792,1.19348,-0.181047, + 0.051115,-0.906355,-0.419414,5.912147,1.117911,-0.254197, + 0.161367,-0.802085,-0.574996,5.837875,1.141493,-0.305184, + -0.034221,-0.995012,-0.093703,5.803425,1.260787,-0.210002, + 0.064626,-0.99783,0.012619,5.840665,1.221942,-0.187128, + 0.218068,-0.756332,-0.616772,5.77341,1.225861,-0.323025, + -0.034221,-0.995012,-0.093703,5.803425,1.260787,-0.210002, + 0.218068,-0.756332,-0.616772,5.77341,1.225861,-0.323025, + 0.725751,-0.657941,-0.200998,5.764774,1.279824,-0.308562, + -0.034221,-0.995012,-0.093703,5.803425,1.260787,-0.210002, + 0.725751,-0.657941,-0.200998,5.764774,1.279824,-0.308562, + 0.188634,-0.17518,-0.966297,5.783731,1.341471,-0.28459, + -0.034221,-0.995012,-0.093703,5.803425,1.260787,-0.210002, + 0.188634,-0.17518,-0.966297,5.783731,1.341471,-0.28459, + 0.244568,-0.04472,-0.9686,5.847989,1.311569,-0.261476, + -0.034221,-0.995012,-0.093703,5.803425,1.260787,-0.210002, + 0.244568,-0.04472,-0.9686,5.847989,1.311569,-0.261476, + 0.193495,-0.385604,-0.902147,5.931474,1.233483,-0.215613, + -0.034221,-0.995012,-0.093703,5.803425,1.260787,-0.210002, + 0.193495,-0.385604,-0.902147,5.931474,1.233483,-0.215613, + 0.064626,-0.99783,0.012619,5.840665,1.221942,-0.187128, + 0.064626,-0.99783,0.012619,5.840665,1.221942,-0.187128, + 0.193495,-0.385604,-0.902147,5.931474,1.233483,-0.215613, + 0.035706,-0.99787,-0.054588,5.849792,1.19348,-0.181047, + 0.193495,-0.385604,-0.902147,5.931474,1.233483,-0.215613, + -0.026148,0.006311,-0.999638,5.998088,1.231874,-0.107334, + 0.485455,-0.874253,0.003847,5.895899,1.18273,-0.164705, + 0.193495,-0.385604,-0.902147,5.931474,1.233483,-0.215613, + 0.485455,-0.874253,0.003847,5.895899,1.18273,-0.164705, + 0.035706,-0.99787,-0.054588,5.849792,1.19348,-0.181047, + 0.173726,-0.983856,0.042973,5.672385,1.007694,-0.341778, + 0.396941,-0.593504,-0.700137,5.755282,1.004149,-0.307505, + 0.204472,-0.587725,-0.782797,5.674999,0.950754,-0.22796, + 0.173726,-0.983856,0.042973,5.672385,1.007694,-0.341778, + 0.204472,-0.587725,-0.782797,5.674999,0.950754,-0.22796, + -0.007021,-0.990239,-0.139206,5.573803,0.952578,-0.243886, + 0.148862,-0.934725,-0.322692,5.580727,0.99933,-0.349867, + 0.173726,-0.983856,0.042973,5.672385,1.007694,-0.341778, + -0.007021,-0.990239,-0.139206,5.573803,0.952578,-0.243886, + 0.148862,-0.934725,-0.322692,5.580727,0.99933,-0.349867, + -0.007021,-0.990239,-0.139206,5.573803,0.952578,-0.243886, + 0.241652,-0.897637,-0.368581,5.535184,0.98018,-0.341257, + -0.007021,-0.990239,-0.139206,5.573803,0.952578,-0.243886, + 0.204472,-0.587725,-0.782797,5.674999,0.950754,-0.22796, + -0.045194,-0.595739,-0.801906,5.638369,0.904402,-0.222548, + -0.007021,-0.990239,-0.139206,5.573803,0.952578,-0.243886, + -0.045194,-0.595739,-0.801906,5.638369,0.904402,-0.222548, + -0.016623,-0.697515,-0.716378,5.546347,0.916044,-0.246782, + 0.204472,-0.587725,-0.782797,5.674999,0.950754,-0.22796, + 0.256335,-0.2349,-0.937611,5.757506,0.9579,-0.210732, + -0.105003,-0.636187,-0.764356,5.748613,0.92049,-0.205099, + 0.204472,-0.587725,-0.782797,5.674999,0.950754,-0.22796, + -0.105003,-0.636187,-0.764356,5.748613,0.92049,-0.205099, + -0.045194,-0.595739,-0.801906,5.638369,0.904402,-0.222548, + -0.126433,-0.433465,-0.892257,5.87863,0.986485,-0.128292, + -0.106359,-0.394397,-0.912764,5.851404,0.929008,-0.105362, + -0.105003,-0.636187,-0.764356,5.748613,0.92049,-0.205099, + -0.126433,-0.433465,-0.892257,5.87863,0.986485,-0.128292, + -0.105003,-0.636187,-0.764356,5.748613,0.92049,-0.205099, + 0.256335,-0.2349,-0.937611,5.757506,0.9579,-0.210732, + 0.535268,0.844682,0.000171,5.871947,1.021428,0.001102, + 0.997356,-0.072614,-0.002907,5.836005,0.945722,0.001092, + -0.091049,-0.145989,-0.985087,5.897758,1.009309,-0.080583, + -0.091049,-0.145989,-0.985087,5.897758,1.009309,-0.080583, + 0.997356,-0.072614,-0.002907,5.836005,0.945722,0.001092, + -0.106359,-0.394397,-0.912764,5.851404,0.929008,-0.105362, + -0.091049,-0.145989,-0.985087,5.897758,1.009309,-0.080583, + -0.106359,-0.394397,-0.912764,5.851404,0.929008,-0.105362, + -0.126433,-0.433465,-0.892257,5.87863,0.986485,-0.128292, + -0.026148,0.006311,-0.999638,5.998088,1.231874,-0.107334, + 0.223936,-0.919046,-0.324355,5.959462,1.157227,-0.187097, + 0.485455,-0.874253,0.003847,5.895899,1.18273,-0.164705, + 0.161367,-0.802085,-0.574996,5.837875,1.141493,-0.305184, + 0.218068,-0.756332,-0.616772,5.77341,1.225861,-0.323025, + 0.064626,-0.99783,0.012619,5.840665,1.221942,-0.187128, + 0.161367,-0.802085,-0.574996,5.837875,1.141493,-0.305184, + 0.064626,-0.99783,0.012619,5.840665,1.221942,-0.187128, + 0.035706,-0.99787,-0.054588,5.849792,1.19348,-0.181047, + 0.241652,-0.897637,-0.368581,5.535184,0.98018,-0.341257, + -0.007021,-0.990239,-0.139206,5.573803,0.952578,-0.243886, + -0.016623,-0.697515,-0.716378,5.546347,0.916044,-0.246782, + 0.241652,-0.897637,-0.368581,5.535184,0.98018,-0.341257, + -0.016623,-0.697515,-0.716378,5.546347,0.916044,-0.246782, + 0.241049,-0.626018,-0.741618,5.480649,0.941387,-0.316248, + 0.193291,-0.074799,-0.978286,4.897808,1.946794,-0.628057, + 0.721999,0.398917,-0.565316,4.861611,2.001639,-0.621913, + 0.711192,0.127662,-0.69131,4.935561,2.016016,-0.5857, + 0.193291,-0.074799,-0.978286,4.897808,1.946794,-0.628057, + 0.711192,0.127662,-0.69131,4.935561,2.016016,-0.5857, + 0.133638,0.26732,-0.954296,4.925394,1.955229,-0.618837, + 0.347878,0.028988,0.937092,4.925499,1.917814,0.613413, + 0.458202,0.052175,0.887316,4.953403,1.907939,0.605609, + 0.444094,0.036127,0.895251,4.971872,1.924079,0.586026, + 0.347878,0.028988,0.937092,4.925499,1.917814,0.613413, + 0.444094,0.036127,0.895251,4.971872,1.924079,0.586026, + 0.328548,0.219459,0.918637,4.953739,1.95258,0.592256, + 0.347878,0.028988,0.937092,4.925499,1.917814,0.613413, + 0.328548,0.219459,0.918637,4.953739,1.95258,0.592256, + 0.719268,0.159442,0.676189,4.925394,1.955229,0.618837, + 0.347878,0.028988,0.937092,4.925499,1.917814,0.613413, + 0.719268,0.159442,0.676189,4.925394,1.955229,0.618837, + 0.561013,0.750789,0.348684,4.897808,1.946794,0.628057, + 0.328548,0.219459,0.918637,4.953739,1.95258,0.592256, + 0.444094,0.036127,0.895251,4.971872,1.924079,0.586026, + 0.380651,0.443224,0.811577,5.001903,1.914398,0.486724, + 0.328548,0.219459,0.918637,4.953739,1.95258,0.592256, + 0.380651,0.443224,0.811577,5.001903,1.914398,0.486724, + 0.282492,0.026081,0.958915,4.973133,1.992779,0.533466, + 0.458202,0.052175,0.887316,4.953403,1.907939,0.605609, + 0.362705,0.428702,0.827442,4.982364,1.8733,0.53619, + 0.380651,0.443224,0.811577,5.001903,1.914398,0.486724, + 0.458202,0.052175,0.887316,4.953403,1.907939,0.605609, + 0.380651,0.443224,0.811577,5.001903,1.914398,0.486724, + 0.444094,0.036127,0.895251,4.971872,1.924079,0.586026, + 0.332757,0.286207,0.898531,4.926194,1.859813,0.582137, + 0.362705,0.428702,0.827442,4.982364,1.8733,0.53619, + 0.458202,0.052175,0.887316,4.953403,1.907939,0.605609, + 0.302716,0.058971,0.951255,4.852578,1.889721,0.605031, + 0.332757,0.286207,0.898531,4.926194,1.859813,0.582137, + 0.458202,0.052175,0.887316,4.953403,1.907939,0.605609, + 0.302716,0.058971,0.951255,4.852578,1.889721,0.605031, + 0.458202,0.052175,0.887316,4.953403,1.907939,0.605609, + 0.347878,0.028988,0.937092,4.925499,1.917814,0.613413, + 0.347794,0.132396,0.928176,4.824747,1.946835,0.626358, + 0.302716,0.058971,0.951255,4.852578,1.889721,0.605031, + 0.347878,0.028988,0.937092,4.925499,1.917814,0.613413, + 0.347794,0.132396,0.928176,4.824747,1.946835,0.626358, + 0.347878,0.028988,0.937092,4.925499,1.917814,0.613413, + 0.561013,0.750789,0.348684,4.897808,1.946794,0.628057, + 0.36359,0.089346,0.927264,4.861611,2.001639,0.621913, + 0.347794,0.132396,0.928176,4.824747,1.946835,0.626358, + 0.561013,0.750789,0.348684,4.897808,1.946794,0.628057, + 0.719268,0.159442,0.676189,4.925394,1.955229,0.618837, + 0.328548,0.219459,0.918637,4.953739,1.95258,0.592256, + 0.282492,0.026081,0.958915,4.973133,1.992779,0.533466, + 0.719268,0.159442,0.676189,4.925394,1.955229,0.618837, + 0.282492,0.026081,0.958915,4.973133,1.992779,0.533466, + 0.361081,-0.056526,0.93082,4.935561,2.016016,0.5857, + 0.800967,0.453079,-0.391371,5.934596,1.054796,0.077039, + 0.054059,0.926072,-0.373455,5.897758,1.009309,0.080583, + 0.535268,0.844682,0.000171,5.871947,1.021428,0.001102, + 0.800967,0.453079,-0.391371,5.934596,1.054796,0.077039, + 0.535268,0.844682,0.000171,5.871947,1.021428,0.001102, + 0.909103,0.416568,-0.001454,5.908782,1.066916,0.001121, + 0.693689,0.317887,-0.646331,5.923808,1.025283,0.153084, + 0.329366,0.742755,-0.582952,5.87863,0.986485,0.128292, + 0.054059,0.926072,-0.373455,5.897758,1.009309,0.080583, + 0.693689,0.317887,-0.646331,5.923808,1.025283,0.153084, + 0.054059,0.926072,-0.373455,5.897758,1.009309,0.080583, + 0.800967,0.453079,-0.391371,5.934596,1.054796,0.077039, + -0.051423,0.948155,-0.31362,5.85775,0.997026,0.236768, + 0.971427,0.045661,-0.232906,5.757506,0.9579,0.210732, + 0.329366,0.742755,-0.582952,5.87863,0.986485,0.128292, + -0.051423,0.948155,-0.31362,5.85775,0.997026,0.236768, + 0.329366,0.742755,-0.582952,5.87863,0.986485,0.128292, + 0.693689,0.317887,-0.646331,5.923808,1.025283,0.153084, + 0.850248,-0.122854,-0.511845,5.674999,0.950754,0.22796, + 0.971427,0.045661,-0.232906,5.757506,0.9579,0.210732, + -0.051423,0.948155,-0.31362,5.85775,0.997026,0.236768, + 0.850248,-0.122854,-0.511845,5.674999,0.950754,0.22796, + -0.051423,0.948155,-0.31362,5.85775,0.997026,0.236768, + 0.104327,0.725166,-0.680625,5.755282,1.004149,0.307505, + 0.811896,0.498733,0.303464,5.912147,1.117911,0.254197, + 0.969409,0.243854,0.027951,5.959462,1.157227,0.187097, + 0.169215,-0.167065,-0.971317,5.895899,1.18273,0.164705, + 0.603382,-0.138832,-0.785275,5.837875,1.141493,0.305184, + 0.811896,0.498733,0.303464,5.912147,1.117911,0.254197, + 0.169215,-0.167065,-0.971317,5.895899,1.18273,0.164705, + 0.603382,-0.138832,-0.785275,5.837875,1.141493,0.305184, + 0.169215,-0.167065,-0.971317,5.895899,1.18273,0.164705, + 0.054838,0.68532,-0.726174,5.849792,1.19348,0.181047, + 0.104604,0.236958,-0.965872,5.764774,1.279824,0.308562, + 0.335985,-0.093512,-0.937214,5.77341,1.225861,0.323025, + -0.071389,0.260053,-0.962952,5.840665,1.221942,0.187128, + 0.104604,0.236958,-0.965872,5.764774,1.279824,0.308562, + -0.071389,0.260053,-0.962952,5.840665,1.221942,0.187128, + -0.026478,0.945923,-0.323309,5.803425,1.260787,0.210002, + -0.0511,0.977083,-0.206633,5.783731,1.341471,0.28459, + 0.104604,0.236958,-0.965872,5.764774,1.279824,0.308562, + -0.026478,0.945923,-0.323309,5.803425,1.260787,0.210002, + 0.481644,0.842268,-0.242082,5.847989,1.311569,0.261476, + -0.0511,0.977083,-0.206633,5.783731,1.341471,0.28459, + -0.026478,0.945923,-0.323309,5.803425,1.260787,0.210002, + -0.071389,0.260053,-0.962952,5.840665,1.221942,0.187128, + 0.794567,0.588129,-0.15089,5.931474,1.233483,0.215613, + 0.481644,0.842268,-0.242082,5.847989,1.311569,0.261476, + -0.071389,0.260053,-0.962952,5.840665,1.221942,0.187128, + 0.481644,0.842268,-0.242082,5.847989,1.311569,0.261476, + -0.026478,0.945923,-0.323309,5.803425,1.260787,0.210002, + 0.054838,0.68532,-0.726174,5.849792,1.19348,0.181047, + 0.794567,0.588129,-0.15089,5.931474,1.233483,0.215613, + -0.071389,0.260053,-0.962952,5.840665,1.221942,0.187128, + 0.054838,0.68532,-0.726174,5.849792,1.19348,0.181047, + 0.169215,-0.167065,-0.971317,5.895899,1.18273,0.164705, + 0.04154,0.947538,-0.316933,5.998088,1.231874,0.107334, + 0.054838,0.68532,-0.726174,5.849792,1.19348,0.181047, + 0.04154,0.947538,-0.316933,5.998088,1.231874,0.107334, + 0.794567,0.588129,-0.15089,5.931474,1.233483,0.215613, + -0.03479,0.696668,-0.716549,5.573803,0.952578,0.243886, + 0.850248,-0.122854,-0.511845,5.674999,0.950754,0.22796, + 0.104327,0.725166,-0.680625,5.755282,1.004149,0.307505, + -0.03479,0.696668,-0.716549,5.573803,0.952578,0.243886, + 0.104327,0.725166,-0.680625,5.755282,1.004149,0.307505, + -0.011269,-0.268801,-0.96313,5.672385,1.007694,0.341778, + -0.03479,0.696668,-0.716549,5.573803,0.952578,0.243886, + -0.011269,-0.268801,-0.96313,5.672385,1.007694,0.341778, + -0.01139,0.953897,-0.299918,5.580727,0.99933,0.349867, + -0.151742,0.274295,-0.949598,5.535184,0.98018,0.341257, + -0.03479,0.696668,-0.716549,5.573803,0.952578,0.243886, + -0.01139,0.953897,-0.299918,5.580727,0.99933,0.349867, + 0.176955,-0.903058,0.391373,5.546347,0.916044,0.246782, + 0.571342,-0.680689,-0.45851,5.638369,0.904402,0.222548, + 0.850248,-0.122854,-0.511845,5.674999,0.950754,0.22796, + 0.176955,-0.903058,0.391373,5.546347,0.916044,0.246782, + 0.850248,-0.122854,-0.511845,5.674999,0.950754,0.22796, + -0.03479,0.696668,-0.716549,5.573803,0.952578,0.243886, + 0.571342,-0.680689,-0.45851,5.638369,0.904402,0.222548, + 0.388502,-0.6643,-0.63857,5.748613,0.92049,0.205099, + 0.971427,0.045661,-0.232906,5.757506,0.9579,0.210732, + 0.571342,-0.680689,-0.45851,5.638369,0.904402,0.222548, + 0.971427,0.045661,-0.232906,5.757506,0.9579,0.210732, + 0.850248,-0.122854,-0.511845,5.674999,0.950754,0.22796, + 0.971427,0.045661,-0.232906,5.757506,0.9579,0.210732, + 0.388502,-0.6643,-0.63857,5.748613,0.92049,0.205099, + 0.20994,-0.930128,0.301309,5.851404,0.929008,0.105362, + 0.971427,0.045661,-0.232906,5.757506,0.9579,0.210732, + 0.20994,-0.930128,0.301309,5.851404,0.929008,0.105362, + 0.329366,0.742755,-0.582952,5.87863,0.986485,0.128292, + 0.054059,0.926072,-0.373455,5.897758,1.009309,0.080583, + 0.997356,-0.072614,-0.002907,5.836005,0.945722,0.001092, + 0.535268,0.844682,0.000171,5.871947,1.021428,0.001102, + 0.329366,0.742755,-0.582952,5.87863,0.986485,0.128292, + 0.20994,-0.930128,0.301309,5.851404,0.929008,0.105362, + 0.997356,-0.072614,-0.002907,5.836005,0.945722,0.001092, + 0.329366,0.742755,-0.582952,5.87863,0.986485,0.128292, + 0.997356,-0.072614,-0.002907,5.836005,0.945722,0.001092, + 0.054059,0.926072,-0.373455,5.897758,1.009309,0.080583, + 0.169215,-0.167065,-0.971317,5.895899,1.18273,0.164705, + 0.969409,0.243854,0.027951,5.959462,1.157227,0.187097, + 0.04154,0.947538,-0.316933,5.998088,1.231874,0.107334, + 0.054838,0.68532,-0.726174,5.849792,1.19348,0.181047, + -0.071389,0.260053,-0.962952,5.840665,1.221942,0.187128, + 0.335985,-0.093512,-0.937214,5.77341,1.225861,0.323025, + 0.054838,0.68532,-0.726174,5.849792,1.19348,0.181047, + 0.335985,-0.093512,-0.937214,5.77341,1.225861,0.323025, + 0.603382,-0.138832,-0.785275,5.837875,1.141493,0.305184, + 0.083641,-0.81989,0.566378,5.480649,0.941387,0.316248, + 0.176955,-0.903058,0.391373,5.546347,0.916044,0.246782, + -0.03479,0.696668,-0.716549,5.573803,0.952578,0.243886, + 0.083641,-0.81989,0.566378,5.480649,0.941387,0.316248, + -0.03479,0.696668,-0.716549,5.573803,0.952578,0.243886, + -0.151742,0.274295,-0.949598,5.535184,0.98018,0.341257, + 0.719268,0.159442,0.676189,4.925394,1.955229,0.618837, + 0.361081,-0.056526,0.93082,4.935561,2.016016,0.5857, + 0.36359,0.089346,0.927264,4.861611,2.001639,0.621913, + 0.719268,0.159442,0.676189,4.925394,1.955229,0.618837, + 0.36359,0.089346,0.927264,4.861611,2.001639,0.621913, + 0.561013,0.750789,0.348684,4.897808,1.946794,0.628057 +}; +static const struct gllist frame={GL_N3F_V3F,GL_TRIANGLES,336,data,NULL}; +const struct gllist *cow_face=&frame; diff --git a/hacks/glx/cow_hide.c b/hacks/glx/cow_hide.c new file mode 100644 index 00000000..3728eef6 --- /dev/null +++ b/hacks/glx/cow_hide.c @@ -0,0 +1,13055 @@ +#include "gllist.h" +static const float data[]={ + -0.012663,0.029084,-0.999497,2.229345,-0.992723,-0.862826, + -0.096144,-0.182414,-0.97851,2.292449,-0.871852,-0.8824, + 0.795625,-0.129968,-0.591684,2.410367,-0.777999,-0.841105, + -0.012663,0.029084,-0.999497,2.229345,-0.992723,-0.862826, + 0.795625,-0.129968,-0.591684,2.410367,-0.777999,-0.841105, + -0.200187,-0.124247,-0.971848,2.407309,-0.97498,-0.805091, + -0.200187,-0.124247,-0.971848,2.407309,-0.97498,-0.805091, + 0.795625,-0.129968,-0.591684,2.410367,-0.777999,-0.841105, + 0.908163,-0.140074,-0.394486,2.5392,-0.727778,-0.750475, + -0.200187,-0.124247,-0.971848,2.407309,-0.97498,-0.805091, + 0.908163,-0.140074,-0.394486,2.5392,-0.727778,-0.750475, + 0.023112,-0.187685,-0.981957,2.520417,-0.954785,-0.739445, + 0.023112,-0.187685,-0.981957,2.520417,-0.954785,-0.739445, + 0.908163,-0.140074,-0.394486,2.5392,-0.727778,-0.750475, + 0.720876,-0.356662,-0.594247,2.637655,-0.768176,-0.637039, + 0.720876,-0.356662,-0.594247,2.637655,-0.768176,-0.637039, + 0.709718,-0.453838,-0.538824,2.669281,-0.930664,-0.557166, + 0.4379,-0.250054,-0.863549,2.514167,-1.077721,-0.706614, + 0.720876,-0.356662,-0.594247,2.637655,-0.768176,-0.637039, + 0.4379,-0.250054,-0.863549,2.514167,-1.077721,-0.706614, + 0.023112,-0.187685,-0.981957,2.520417,-0.954785,-0.739445, + 0.023112,-0.187685,-0.981957,2.520417,-0.954785,-0.739445, + 0.4379,-0.250054,-0.863549,2.514167,-1.077721,-0.706614, + 0.6483,-0.171023,-0.741928,2.386465,-1.116066,-0.761367, + 0.023112,-0.187685,-0.981957,2.520417,-0.954785,-0.739445, + 0.6483,-0.171023,-0.741928,2.386465,-1.116066,-0.761367, + -0.200187,-0.124247,-0.971848,2.407309,-0.97498,-0.805091, + -0.200187,-0.124247,-0.971848,2.407309,-0.97498,-0.805091, + 0.6483,-0.171023,-0.741928,2.386465,-1.116066,-0.761367, + 0.70745,-0.193334,-0.679806,2.180012,-1.130557,-0.821812, + -0.200187,-0.124247,-0.971848,2.407309,-0.97498,-0.805091, + 0.70745,-0.193334,-0.679806,2.180012,-1.130557,-0.821812, + -0.012663,0.029084,-0.999497,2.229345,-0.992723,-0.862826, + 0.70745,-0.193334,-0.679806,2.180012,-1.130557,-0.821812, + 0.6483,-0.171023,-0.741928,2.386465,-1.116066,-0.761367, + 0.71475,-0.118625,-0.689246,2.354287,-1.193746,-0.735189, + 0.70745,-0.193334,-0.679806,2.180012,-1.130557,-0.821812, + 0.71475,-0.118625,-0.689246,2.354287,-1.193746,-0.735189, + 0.608407,-0.244593,-0.754993,2.158051,-1.209613,-0.783941, + 0.608407,-0.244593,-0.754993,2.158051,-1.209613,-0.783941, + 0.71475,-0.118625,-0.689246,2.354287,-1.193746,-0.735189, + 0.370396,-0.365961,-0.853744,2.318787,-1.29409,-0.673863, + 0.608407,-0.244593,-0.754993,2.158051,-1.209613,-0.783941, + 0.370396,-0.365961,-0.853744,2.318787,-1.29409,-0.673863, + 0.727678,-0.414895,-0.546211,2.126237,-1.330172,-0.721011, + 0.727678,-0.414895,-0.546211,2.126237,-1.330172,-0.721011, + 0.370396,-0.365961,-0.853744,2.318787,-1.29409,-0.673863, + 0.324748,-0.466051,-0.823003,2.274533,-1.433487,-0.567366, + 0.324748,-0.466051,-0.823003,2.274533,-1.433487,-0.567366, + 0.370396,-0.365961,-0.853744,2.318787,-1.29409,-0.673863, + 0.727708,-0.453484,-0.514581,2.486533,-1.274971,-0.627822, + 0.324748,-0.466051,-0.823003,2.274533,-1.433487,-0.567366, + 0.727708,-0.453484,-0.514581,2.486533,-1.274971,-0.627822, + 0.287759,-0.574148,-0.766517,2.45706,-1.400958,-0.539866, + 0.287759,-0.574148,-0.766517,2.45706,-1.400958,-0.539866, + 0.727708,-0.453484,-0.514581,2.486533,-1.274971,-0.627822, + 0.677632,-0.514013,-0.525933,2.549322,-1.335209,-0.535156, + 0.677632,-0.514013,-0.525933,2.549322,-1.335209,-0.535156, + 0.727708,-0.453484,-0.514581,2.486533,-1.274971,-0.627822, + 0.290845,-0.56858,-0.769497,2.61797,-1.235597,-0.520238, + 0.290845,-0.56858,-0.769497,2.61797,-1.235597,-0.520238, + 0.727708,-0.453484,-0.514581,2.486533,-1.274971,-0.627822, + 0.478274,-0.500384,-0.721713,2.510841,-1.158786,-0.678057, + 0.290845,-0.56858,-0.769497,2.61797,-1.235597,-0.520238, + 0.478274,-0.500384,-0.721713,2.510841,-1.158786,-0.678057, + 0.245892,-0.489895,-0.836385,2.670253,-1.108365,-0.544018, + 0.478274,-0.500384,-0.721713,2.510841,-1.158786,-0.678057, + 0.727708,-0.453484,-0.514581,2.486533,-1.274971,-0.627822, + 0.370396,-0.365961,-0.853744,2.318787,-1.29409,-0.673863, + 0.478274,-0.500384,-0.721713,2.510841,-1.158786,-0.678057, + 0.370396,-0.365961,-0.853744,2.318787,-1.29409,-0.673863, + 0.71475,-0.118625,-0.689246,2.354287,-1.193746,-0.735189, + 0.71475,-0.118625,-0.689246,2.354287,-1.193746,-0.735189, + 0.6483,-0.171023,-0.741928,2.386465,-1.116066,-0.761367, + 0.4379,-0.250054,-0.863549,2.514167,-1.077721,-0.706614, + 0.71475,-0.118625,-0.689246,2.354287,-1.193746,-0.735189, + 0.4379,-0.250054,-0.863549,2.514167,-1.077721,-0.706614, + 0.478274,-0.500384,-0.721713,2.510841,-1.158786,-0.678057, + 0.478274,-0.500384,-0.721713,2.510841,-1.158786,-0.678057, + 0.4379,-0.250054,-0.863549,2.514167,-1.077721,-0.706614, + 0.709718,-0.453838,-0.538824,2.669281,-0.930664,-0.557166, + 0.478274,-0.500384,-0.721713,2.510841,-1.158786,-0.678057, + 0.709718,-0.453838,-0.538824,2.669281,-0.930664,-0.557166, + 0.245892,-0.489895,-0.836385,2.670253,-1.108365,-0.544018, + 0.709718,-0.453838,-0.538824,2.669281,-0.930664,-0.557166, + 0.720876,-0.356662,-0.594247,2.637655,-0.768176,-0.637039, + 0.430574,-0.353967,-0.830249,2.710721,-0.830091,-0.532493, + 0.245892,-0.489895,-0.836385,2.670253,-1.108365,-0.544018, + 0.539192,-0.226204,-0.811236,2.857666,-0.930625,-0.391195, + 0.543412,-0.359347,-0.758665,2.757946,-1.099958,-0.471684, + 0.543412,-0.359347,-0.758665,2.757946,-1.099958,-0.471684, + 0.290845,-0.56858,-0.769497,2.61797,-1.235597,-0.520238, + 0.245892,-0.489895,-0.836385,2.670253,-1.108365,-0.544018, + 0.543412,-0.359347,-0.758665,2.757946,-1.099958,-0.471684, + 0.663699,-0.195183,-0.722085,2.847364,-1.103812,-0.402301, + 0.675576,-0.202498,-0.708937,2.803736,-1.255869,-0.438328, + 0.543412,-0.359347,-0.758665,2.757946,-1.099958,-0.471684, + 0.675576,-0.202498,-0.708937,2.803736,-1.255869,-0.438328, + 0.290845,-0.56858,-0.769497,2.61797,-1.235597,-0.520238, + 0.663699,-0.195183,-0.722085,2.847364,-1.103812,-0.402301, + 0.543412,-0.359347,-0.758665,2.757946,-1.099958,-0.471684, + 0.539192,-0.226204,-0.811236,2.857666,-0.930625,-0.391195, + 0.290845,-0.56858,-0.769497,2.61797,-1.235597,-0.520238, + 0.675576,-0.202498,-0.708937,2.803736,-1.255869,-0.438328, + 0.655995,-0.105886,-0.747301,2.740886,-1.339225,-0.463604, + 0.290845,-0.56858,-0.769497,2.61797,-1.235597,-0.520238, + 0.655995,-0.105886,-0.747301,2.740886,-1.339225,-0.463604, + 0.594643,-0.107364,-0.796789,2.663024,-1.440487,-0.478149, + 0.290845,-0.56858,-0.769497,2.61797,-1.235597,-0.520238, + 0.594643,-0.107364,-0.796789,2.663024,-1.440487,-0.478149, + 0.677632,-0.514013,-0.525933,2.549322,-1.335209,-0.535156, + 0.677632,-0.514013,-0.525933,2.549322,-1.335209,-0.535156, + 0.594643,-0.107364,-0.796789,2.663024,-1.440487,-0.478149, + 0.648132,-0.027411,-0.761034,2.515314,-1.507063,-0.483275, + 0.677632,-0.514013,-0.525933,2.549322,-1.335209,-0.535156, + 0.648132,-0.027411,-0.761034,2.515314,-1.507063,-0.483275, + 0.287759,-0.574148,-0.766517,2.45706,-1.400958,-0.539866, + 0.287759,-0.574148,-0.766517,2.45706,-1.400958,-0.539866, + 0.648132,-0.027411,-0.761034,2.515314,-1.507063,-0.483275, + 0.58512,-0.108234,-0.803692,2.422296,-1.510915,-0.494169, + 0.287759,-0.574148,-0.766517,2.45706,-1.400958,-0.539866, + 0.58512,-0.108234,-0.803692,2.422296,-1.510915,-0.494169, + 0.518786,-0.204527,-0.830078,2.249663,-1.492705,-0.53127, + 0.287759,-0.574148,-0.766517,2.45706,-1.400958,-0.539866, + 0.518786,-0.204527,-0.830078,2.249663,-1.492705,-0.53127, + 0.324748,-0.466051,-0.823003,2.274533,-1.433487,-0.567366, + 0.324748,-0.466051,-0.823003,2.274533,-1.433487,-0.567366, + 0.518786,-0.204527,-0.830078,2.249663,-1.492705,-0.53127, + 0.437631,-0.408484,-0.801012,2.0796,-1.473377,-0.654997, + 0.324748,-0.466051,-0.823003,2.274533,-1.433487,-0.567366, + 0.437631,-0.408484,-0.801012,2.0796,-1.473377,-0.654997, + 0.727678,-0.414895,-0.546211,2.126237,-1.330172,-0.721011, + 0.539192,-0.226204,-0.811236,2.857666,-0.930625,-0.391195, + 0.189478,-0.558571,-0.807525,2.960118,-0.941827,-0.284743, + 0.112446,-0.61866,-0.77757,2.928787,-1.107467,-0.312054, + 0.539192,-0.226204,-0.811236,2.857666,-0.930625,-0.391195, + 0.112446,-0.61866,-0.77757,2.928787,-1.107467,-0.312054, + 0.663699,-0.195183,-0.722085,2.847364,-1.103812,-0.402301, + 0.663699,-0.195183,-0.722085,2.847364,-1.103812,-0.402301, + 0.112446,-0.61866,-0.77757,2.928787,-1.107467,-0.312054, + 0.276661,-0.626708,-0.728489,2.893096,-1.302168,-0.332049, + 0.663699,-0.195183,-0.722085,2.847364,-1.103812,-0.402301, + 0.276661,-0.626708,-0.728489,2.893096,-1.302168,-0.332049, + 0.675576,-0.202498,-0.708937,2.803736,-1.255869,-0.438328, + 0.675576,-0.202498,-0.708937,2.803736,-1.255869,-0.438328, + 0.276661,-0.626708,-0.728489,2.893096,-1.302168,-0.332049, + 0.690473,-0.61586,-0.379425,2.824356,-1.407256,-0.355013, + 0.675576,-0.202498,-0.708937,2.803736,-1.255869,-0.438328, + 0.690473,-0.61586,-0.379425,2.824356,-1.407256,-0.355013, + 0.655995,-0.105886,-0.747301,2.740886,-1.339225,-0.463604, + 0.690473,-0.61586,-0.379425,2.824356,-1.407256,-0.355013, + 0.883063,-0.251635,-0.396079,2.721135,-1.520418,-0.362378, + 0.594643,-0.107364,-0.796789,2.663024,-1.440487,-0.478149, + 0.594643,-0.107364,-0.796789,2.663024,-1.440487,-0.478149, + 0.883063,-0.251635,-0.396079,2.721135,-1.520418,-0.362378, + 0.918784,-0.122699,-0.375208,2.545261,-1.5933,-0.38631, + 0.594643,-0.107364,-0.796789,2.663024,-1.440487,-0.478149, + 0.918784,-0.122699,-0.375208,2.545261,-1.5933,-0.38631, + 0.648132,-0.027411,-0.761034,2.515314,-1.507063,-0.483275, + 0.648132,-0.027411,-0.761034,2.515314,-1.507063,-0.483275, + 0.918784,-0.122699,-0.375208,2.545261,-1.5933,-0.38631, + 0.876436,-0.293555,-0.381688,2.396607,-1.593239,-0.389972, + 0.648132,-0.027411,-0.761034,2.515314,-1.507063,-0.483275, + 0.876436,-0.293555,-0.381688,2.396607,-1.593239,-0.389972, + 0.58512,-0.108234,-0.803692,2.422296,-1.510915,-0.494169, + 0.58512,-0.108234,-0.803692,2.422296,-1.510915,-0.494169, + 0.876436,-0.293555,-0.381688,2.396607,-1.593239,-0.389972, + 0.728904,-0.519576,-0.445802,2.243492,-1.584783,-0.431143, + 0.58512,-0.108234,-0.803692,2.422296,-1.510915,-0.494169, + 0.728904,-0.519576,-0.445802,2.243492,-1.584783,-0.431143, + 0.518786,-0.204527,-0.830078,2.249663,-1.492705,-0.53127, + 0.518786,-0.204527,-0.830078,2.249663,-1.492705,-0.53127, + 0.728904,-0.519576,-0.445802,2.243492,-1.584783,-0.431143, + 0.552828,-0.750794,-0.36151,2.0482,-1.581983,-0.555832, + 0.518786,-0.204527,-0.830078,2.249663,-1.492705,-0.53127, + 0.552828,-0.750794,-0.36151,2.0482,-1.581983,-0.555832, + 0.437631,-0.408484,-0.801012,2.0796,-1.473377,-0.654997, + 0.189478,-0.558571,-0.807525,2.960118,-0.941827,-0.284743, + -0.334515,0.94239,0,2.970902,-0.959664,0, + 0.820584,-0.571526,0,2.931756,-1.129655,0, + 0.189478,-0.558571,-0.807525,2.960118,-0.941827,-0.284743, + 0.820584,-0.571526,0,2.931756,-1.129655,0, + 0.112446,-0.61866,-0.77757,2.928787,-1.107467,-0.312054, + 0.112446,-0.61866,-0.77757,2.928787,-1.107467,-0.312054, + 0.820584,-0.571526,0,2.931756,-1.129655,0, + -0.255632,0.966774,0,2.896234,-1.31956,0, + 0.112446,-0.61866,-0.77757,2.928787,-1.107467,-0.312054, + -0.255632,0.966774,0,2.896234,-1.31956,0, + 0.276661,-0.626708,-0.728489,2.893096,-1.302168,-0.332049, + 0.276661,-0.626708,-0.728489,2.893096,-1.302168,-0.332049, + -0.255632,0.966774,0,2.896234,-1.31956,0, + 0.826305,-0.563222,0,2.821376,-1.431534,0, + 0.276661,-0.626708,-0.728489,2.893096,-1.302168,-0.332049, + 0.826305,-0.563222,0,2.821376,-1.431534,0, + 0.690473,-0.61586,-0.379425,2.824356,-1.407256,-0.355013, + 0.690473,-0.61586,-0.379425,2.824356,-1.407256,-0.355013, + 0.826305,-0.563222,0,2.821376,-1.431534,0, + -0.133012,0.991114,0,2.706963,-1.528854,0, + 0.690473,-0.61586,-0.379425,2.824356,-1.407256,-0.355013, + -0.133012,0.991114,0,2.706963,-1.528854,0, + 0.883063,-0.251635,-0.396079,2.721135,-1.520418,-0.362378, + 0.883063,-0.251635,-0.396079,2.721135,-1.520418,-0.362378, + -0.133012,0.991114,0,2.706963,-1.528854,0, + 0.815341,-0.578981,0,2.534227,-1.617078,0, + 0.883063,-0.251635,-0.396079,2.721135,-1.520418,-0.362378, + 0.815341,-0.578981,0,2.534227,-1.617078,0, + 0.918784,-0.122699,-0.375208,2.545261,-1.5933,-0.38631, + 0.918784,-0.122699,-0.375208,2.545261,-1.5933,-0.38631, + 0.815341,-0.578981,0,2.534227,-1.617078,0, + -0.144073,0.989567,0,2.348182,-1.624595,0, + 0.918784,-0.122699,-0.375208,2.545261,-1.5933,-0.38631, + -0.144073,0.989567,0,2.348182,-1.624595,0, + 0.876436,-0.293555,-0.381688,2.396607,-1.593239,-0.389972, + 0.876436,-0.293555,-0.381688,2.396607,-1.593239,-0.389972, + -0.144073,0.989567,0,2.348182,-1.624595,0, + -0.073566,0.99729,0,2.167167,-1.596326,0, + 0.876436,-0.293555,-0.381688,2.396607,-1.593239,-0.389972, + -0.073566,0.99729,0,2.167167,-1.596326,0, + 0.728904,-0.519576,-0.445802,2.243492,-1.584783,-0.431143, + 0.728904,-0.519576,-0.445802,2.243492,-1.584783,-0.431143, + -0.073566,0.99729,0,2.167167,-1.596326,0, + -0.034649,0.9994,0,1.920432,-1.567396,0, + 0.728904,-0.519576,-0.445802,2.243492,-1.584783,-0.431143, + -0.034649,0.9994,0,1.920432,-1.567396,0, + 0.552828,-0.750794,-0.36151,2.0482,-1.581983,-0.555832, + 0.226413,-0.89822,-0.376747,2.881063,-0.493146,-0.521968, + 0.763734,0.228435,-0.603761,2.736198,-0.346225,-0.659345, + 0.016767,-0.927537,-0.373356,2.835437,-0.231101,-0.57789, + 0.016767,-0.927537,-0.373356,2.835437,-0.231101,-0.57789, + 0.486425,0.192908,-0.852161,2.986408,-0.413503,-0.428964, + 0.226413,-0.89822,-0.376747,2.881063,-0.493146,-0.521968, + 0.226413,-0.89822,-0.376747,2.881063,-0.493146,-0.521968, + 0.486425,0.192908,-0.852161,2.986408,-0.413503,-0.428964, + 0.08136,-0.929085,-0.360806,2.910769,-0.638444,-0.431191, + 0.08136,-0.929085,-0.360806,2.910769,-0.638444,-0.431191, + 0.295093,-0.940225,-0.16999,2.82554,-0.567578,-0.552597, + 0.226413,-0.89822,-0.376747,2.881063,-0.493146,-0.521968, + 0.226413,-0.89822,-0.376747,2.881063,-0.493146,-0.521968, + 0.295093,-0.940225,-0.16999,2.82554,-0.567578,-0.552597, + 0.769758,0.095155,-0.631204,2.688131,-0.517509,-0.672975, + 0.720876,-0.356662,-0.594247,2.637655,-0.768176,-0.637039, + 0.908163,-0.140074,-0.394486,2.5392,-0.727778,-0.750475, + 0.771881,-0.100912,-0.627707,2.647368,-0.61155,-0.669485, + 0.771881,-0.100912,-0.627707,2.647368,-0.61155,-0.669485, + 0.908163,-0.140074,-0.394486,2.5392,-0.727778,-0.750475, + 0.907314,0.09913,-0.4086,2.618307,-0.549092,-0.805491, + 0.907314,0.09913,-0.4086,2.618307,-0.549092,-0.805491, + 0.769758,0.095155,-0.631204,2.688131,-0.517509,-0.672975, + 0.771881,-0.100912,-0.627707,2.647368,-0.61155,-0.669485, + 0.720876,-0.356662,-0.594247,2.637655,-0.768176,-0.637039, + 0.295093,-0.940225,-0.16999,2.82554,-0.567578,-0.552597, + 0.08136,-0.929085,-0.360806,2.910769,-0.638444,-0.431191, + 0.720876,-0.356662,-0.594247,2.637655,-0.768176,-0.637039, + 0.08136,-0.929085,-0.360806,2.910769,-0.638444,-0.431191, + 0.430574,-0.353967,-0.830249,2.710721,-0.830091,-0.532493, + 0.430574,-0.353967,-0.830249,2.710721,-0.830091,-0.532493, + 0.08136,-0.929085,-0.360806,2.910769,-0.638444,-0.431191, + 0.539192,-0.226204,-0.811236,2.857666,-0.930625,-0.391195, + 0.539192,-0.226204,-0.811236,2.857666,-0.930625,-0.391195, + 0.08136,-0.929085,-0.360806,2.910769,-0.638444,-0.431191, + 0.676544,-0.141883,-0.722604,2.993075,-0.708434,-0.342596, + 0.676544,-0.141883,-0.722604,2.993075,-0.708434,-0.342596, + 0.667276,-0.159228,-0.727591,3.045715,-0.767786,-0.261741, + 0.189478,-0.558571,-0.807525,2.960118,-0.941827,-0.284743, + 0.676544,-0.141883,-0.722604,2.993075,-0.708434,-0.342596, + 0.189478,-0.558571,-0.807525,2.960118,-0.941827,-0.284743, + 0.539192,-0.226204,-0.811236,2.857666,-0.930625,-0.391195, + 0.189478,-0.558571,-0.807525,2.960118,-0.941827,-0.284743, + 0.667276,-0.159228,-0.727591,3.045715,-0.767786,-0.261741, + 0.942695,-0.333657,0,3.065544,-0.788768,0, + 0.189478,-0.558571,-0.807525,2.960118,-0.941827,-0.284743, + 0.942695,-0.333657,0,3.065544,-0.788768,0, + -0.334515,0.94239,0,2.970902,-0.959664,0, + 0.942695,-0.333657,0,3.065544,-0.788768,0, + 0.667276,-0.159228,-0.727591,3.045715,-0.767786,-0.261741, + 0.533629,-0.162705,-0.82992,3.107533,-0.691019,-0.264602, + 0.942695,-0.333657,0,3.065544,-0.788768,0, + 0.533629,-0.162705,-0.82992,3.107533,-0.691019,-0.264602, + -0.476715,0.879058,0,3.118124,-0.703925,0, + 0.539192,-0.226204,-0.811236,2.857666,-0.930625,-0.391195, + 0.245892,-0.489895,-0.836385,2.670253,-1.108365,-0.544018, + 0.709718,-0.453838,-0.538824,2.669281,-0.930664,-0.557166, + 0.430574,-0.353967,-0.830249,2.710721,-0.830091,-0.532493, + 0.539192,-0.226204,-0.811236,2.857666,-0.930625,-0.391195, + 0.709718,-0.453838,-0.538824,2.669281,-0.930664,-0.557166, + 0.771881,-0.100912,-0.627707,2.647368,-0.61155,-0.669485, + 0.769758,0.095155,-0.631204,2.688131,-0.517509,-0.672975, + 0.295093,-0.940225,-0.16999,2.82554,-0.567578,-0.552597, + 0.720876,-0.356662,-0.594247,2.637655,-0.768176,-0.637039, + 0.771881,-0.100912,-0.627707,2.647368,-0.61155,-0.669485, + 0.295093,-0.940225,-0.16999,2.82554,-0.567578,-0.552597, + 0.486425,0.192908,-0.852161,2.986408,-0.413503,-0.428964, + 0.449624,0.075438,-0.890027,3.053144,-0.609681,-0.326931, + 0.676544,-0.141883,-0.722604,2.993075,-0.708434,-0.342596, + 0.486425,0.192908,-0.852161,2.986408,-0.413503,-0.428964, + 0.676544,-0.141883,-0.722604,2.993075,-0.708434,-0.342596, + 0.08136,-0.929085,-0.360806,2.910769,-0.638444,-0.431191, + 0.676544,-0.141883,-0.722604,2.993075,-0.708434,-0.342596, + 0.449624,0.075438,-0.890027,3.053144,-0.609681,-0.326931, + 0.533629,-0.162705,-0.82992,3.107533,-0.691019,-0.264602, + 0.676544,-0.141883,-0.722604,2.993075,-0.708434,-0.342596, + 0.533629,-0.162705,-0.82992,3.107533,-0.691019,-0.264602, + 0.667276,-0.159228,-0.727591,3.045715,-0.767786,-0.261741, + -0.218261,-0.26262,-0.93989,-0.953236,-1.545941,-0.89918, + -0.11636,-0.749063,-0.6522,-1.091175,-1.70712,-0.727242, + 0.162276,-0.745105,-0.646905,-1.226563,-1.655159,-0.687343, + -0.218261,-0.26262,-0.93989,-0.953236,-1.545941,-0.89918, + 0.162276,-0.745105,-0.646905,-1.226563,-1.655159,-0.687343, + 0.215155,-0.464575,-0.858999,-1.200688,-1.577575,-0.799188, + 0.215155,-0.464575,-0.858999,-1.200688,-1.577575,-0.799188, + 0.162276,-0.745105,-0.646905,-1.226563,-1.655159,-0.687343, + -0.504483,-0.438591,-0.743731,-1.376186,-1.661988,-0.718954, + 0.162276,-0.745105,-0.646905,-1.226563,-1.655159,-0.687343, + -0.11636,-0.749063,-0.6522,-1.091175,-1.70712,-0.727242, + -0.351476,-0.711504,-0.608463,-1.089642,-1.757196,-0.685154, + 0.162276,-0.745105,-0.646905,-1.226563,-1.655159,-0.687343, + -0.351476,-0.711504,-0.608463,-1.089642,-1.757196,-0.685154, + -0.149005,-0.65467,-0.741084,-1.266738,-1.691944,-0.557922, + -0.11636,-0.749063,-0.6522,-1.091175,-1.70712,-0.727242, + -0.218261,-0.26262,-0.93989,-0.953236,-1.545941,-0.89918, + -0.231653,-0.530839,-0.815198,-0.972089,-1.774507,-0.76857, + -0.231653,-0.530839,-0.815198,-0.972089,-1.774507,-0.76857, + -0.218261,-0.26262,-0.93989,-0.953236,-1.545941,-0.89918, + -0.468954,-0.586277,-0.660577,-0.812845,-1.785424,-0.768511, + -0.468954,-0.586277,-0.660577,-0.812845,-1.785424,-0.768511, + -0.218261,-0.26262,-0.93989,-0.953236,-1.545941,-0.89918, + 0.10737,-0.293005,-0.950063,-0.535144,-1.615983,-0.920556, + -0.468954,-0.586277,-0.660577,-0.812845,-1.785424,-0.768511, + 0.10737,-0.293005,-0.950063,-0.535144,-1.615983,-0.920556, + -0.150892,-0.83775,-0.524792,-0.680046,-1.768325,-0.81908, + -0.150892,-0.83775,-0.524792,-0.680046,-1.768325,-0.81908, + 0.10737,-0.293005,-0.950063,-0.535144,-1.615983,-0.920556, + 0.100949,-0.548551,-0.830001,-0.564074,-1.789401,-0.803191, + 0.100949,-0.548551,-0.830001,-0.564074,-1.789401,-0.803191, + 0.10737,-0.293005,-0.950063,-0.535144,-1.615983,-0.920556, + -0.4144,-0.844957,-0.338113,-0.422877,-1.7512,-0.823423, + -0.4144,-0.844957,-0.338113,-0.422877,-1.7512,-0.823423, + 0.10737,-0.293005,-0.950063,-0.535144,-1.615983,-0.920556, + 0.33122,-0.270106,-0.904067,-0.063012,-1.583021,-0.865082, + -0.4144,-0.844957,-0.338113,-0.422877,-1.7512,-0.823423, + 0.33122,-0.270106,-0.904067,-0.063012,-1.583021,-0.865082, + 0.327725,-0.489439,-0.808112,-0.07847,-1.688266,-0.80023, + -0.4144,-0.844957,-0.338113,-0.422877,-1.7512,-0.823423, + 0.327725,-0.489439,-0.808112,-0.07847,-1.688266,-0.80023, + 0.291858,-0.681117,-0.67149,-0.094135,-1.769086,-0.556924, + -0.4144,-0.844957,-0.338113,-0.422877,-1.7512,-0.823423, + 0.291858,-0.681117,-0.67149,-0.094135,-1.769086,-0.556924, + 0.068777,-0.757383,-0.649339,-0.543078,-1.810473,-0.563825, + 0.068777,-0.757383,-0.649339,-0.543078,-1.810473,-0.563825, + 0.100949,-0.548551,-0.830001,-0.564074,-1.789401,-0.803191, + -0.4144,-0.844957,-0.338113,-0.422877,-1.7512,-0.823423, + 0.100949,-0.548551,-0.830001,-0.564074,-1.789401,-0.803191, + 0.068777,-0.757383,-0.649339,-0.543078,-1.810473,-0.563825, + -0.150892,-0.83775,-0.524792,-0.680046,-1.768325,-0.81908, + -0.150892,-0.83775,-0.524792,-0.680046,-1.768325,-0.81908, + 0.068777,-0.757383,-0.649339,-0.543078,-1.810473,-0.563825, + -0.253979,-0.745808,-0.615845,-0.977375,-1.793126,-0.498747, + -0.150892,-0.83775,-0.524792,-0.680046,-1.768325,-0.81908, + -0.253979,-0.745808,-0.615845,-0.977375,-1.793126,-0.498747, + -0.468954,-0.586277,-0.660577,-0.812845,-1.785424,-0.768511, + -0.351476,-0.711504,-0.608463,-1.089642,-1.757196,-0.685154, + -0.11636,-0.749063,-0.6522,-1.091175,-1.70712,-0.727242, + -0.231653,-0.530839,-0.815198,-0.972089,-1.774507,-0.76857, + -0.149005,-0.65467,-0.741084,-1.266738,-1.691944,-0.557922, + -0.351476,-0.711504,-0.608463,-1.089642,-1.757196,-0.685154, + -0.253979,-0.745808,-0.615845,-0.977375,-1.793126,-0.498747, + -0.149005,-0.65467,-0.741084,-1.266738,-1.691944,-0.557922, + -0.253979,-0.745808,-0.615845,-0.977375,-1.793126,-0.498747, + -0.176655,-0.950799,-0.254508,-1.108758,-1.770749,-0.473033, + -0.176655,-0.950799,-0.254508,-1.108758,-1.770749,-0.473033, + -0.079302,-0.84299,-0.532051,-1.305099,-1.70846,-0.48423, + -0.149005,-0.65467,-0.741084,-1.266738,-1.691944,-0.557922, + -0.149005,-0.65467,-0.741084,-1.266738,-1.691944,-0.557922, + -0.504483,-0.438591,-0.743731,-1.376186,-1.661988,-0.718954, + 0.162276,-0.745105,-0.646905,-1.226563,-1.655159,-0.687343, + -0.504483,-0.438591,-0.743731,-1.376186,-1.661988,-0.718954, + -0.149005,-0.65467,-0.741084,-1.266738,-1.691944,-0.557922, + -0.094238,-0.851252,-0.516225,-1.397474,-1.693815,-0.570541, + -0.53858,-0.616299,-0.57455,-1.386502,-1.718441,-0.350823, + -0.171647,-0.971664,-0.162499,-1.406693,-1.697325,-0.450399, + -0.079302,-0.84299,-0.532051,-1.305099,-1.70846,-0.48423, + -0.53858,-0.616299,-0.57455,-1.386502,-1.718441,-0.350823, + -0.079302,-0.84299,-0.532051,-1.305099,-1.70846,-0.48423, + -0.040019,-0.929968,-0.365457,-0.972514,-1.822778,-0.372649, + -0.040019,-0.929968,-0.365457,-0.972514,-1.822778,-0.372649, + -0.253979,-0.745808,-0.615845,-0.977375,-1.793126,-0.498747, + 0.068777,-0.757383,-0.649339,-0.543078,-1.810473,-0.563825, + -0.040019,-0.929968,-0.365457,-0.972514,-1.822778,-0.372649, + 0.068777,-0.757383,-0.649339,-0.543078,-1.810473,-0.563825, + 0.023352,-0.872807,-0.487506,-0.523838,-1.850065,-0.388007, + 0.023352,-0.872807,-0.487506,-0.523838,-1.850065,-0.388007, + 0.068777,-0.757383,-0.649339,-0.543078,-1.810473,-0.563825, + 0.291858,-0.681117,-0.67149,-0.094135,-1.769086,-0.556924, + 0.023352,-0.872807,-0.487506,-0.523838,-1.850065,-0.388007, + 0.291858,-0.681117,-0.67149,-0.094135,-1.769086,-0.556924, + 0.248915,-0.807091,-0.535392,-0.112666,-1.806584,-0.383324, + 0.248915,-0.807091,-0.535392,-0.112666,-1.806584,-0.383324, + 0.291858,-0.681117,-0.67149,-0.094135,-1.769086,-0.556924, + 0.420794,-0.405156,-0.811653,0.489819,-1.524947,-0.672392, + 0.248915,-0.807091,-0.535392,-0.112666,-1.806584,-0.383324, + 0.420794,-0.405156,-0.811653,0.489819,-1.524947,-0.672392, + 0.383978,-0.566345,-0.729256,0.480235,-1.631521,-0.401961, + 0.383978,-0.566345,-0.729256,0.480235,-1.631521,-0.401961, + 0.226963,-0.973903,0,0.44655,-1.67295,0, + -0.084764,-0.996401,0,-0.155114,-1.828285,0, + 0.383978,-0.566345,-0.729256,0.480235,-1.631521,-0.401961, + -0.084764,-0.996401,0,-0.155114,-1.828285,0, + 0.248915,-0.807091,-0.535392,-0.112666,-1.806584,-0.383324, + 0.248915,-0.807091,-0.535392,-0.112666,-1.806584,-0.383324, + -0.084764,-0.996401,0,-0.155114,-1.828285,0, + 0.854132,-0.520056,0,-0.530369,-1.860806,0, + 0.248915,-0.807091,-0.535392,-0.112666,-1.806584,-0.383324, + 0.854132,-0.520056,0,-0.530369,-1.860806,0, + 0.023352,-0.872807,-0.487506,-0.523838,-1.850065,-0.388007, + 0.023352,-0.872807,-0.487506,-0.523838,-1.850065,-0.388007, + 0.854132,-0.520056,0,-0.530369,-1.860806,0, + 0.113474,-0.993541,0,-0.956007,-1.825728,0, + 0.023352,-0.872807,-0.487506,-0.523838,-1.850065,-0.388007, + 0.113474,-0.993541,0,-0.956007,-1.825728,0, + -0.040019,-0.929968,-0.365457,-0.972514,-1.822778,-0.372649, + -0.040019,-0.929968,-0.365457,-0.972514,-1.822778,-0.372649, + 0.113474,-0.993541,0,-0.956007,-1.825728,0, + 0.011286,0.999936,0,-1.395728,-1.723811,0, + -0.040019,-0.929968,-0.365457,-0.972514,-1.822778,-0.372649, + 0.011286,0.999936,0,-1.395728,-1.723811,0, + -0.53858,-0.616299,-0.57455,-1.386502,-1.718441,-0.350823, + -0.351476,-0.711504,-0.608463,-1.089642,-1.757196,-0.685154, + -0.231653,-0.530839,-0.815198,-0.972089,-1.774507,-0.76857, + -0.253979,-0.745808,-0.615845,-0.977375,-1.793126,-0.498747, + -0.468954,-0.586277,-0.660577,-0.812845,-1.785424,-0.768511, + -0.253979,-0.745808,-0.615845,-0.977375,-1.793126,-0.498747, + -0.231653,-0.530839,-0.815198,-0.972089,-1.774507,-0.76857, + -0.024032,-0.835976,0.54824,1.734568,-2.965876,-0.986396, + -0.246054,-0.154918,-0.956796,1.718315,-2.775468,-0.921796, + -0.069043,-0.157333,-0.985129,1.771416,-2.769024,-0.9461, + -0.024032,-0.835976,0.54824,1.734568,-2.965876,-0.986396, + -0.069043,-0.157333,-0.985129,1.771416,-2.769024,-0.9461, + -0.044013,0.340434,-0.939238,1.806371,-2.949735,-0.984058, + -0.1083,-0.048546,0.992932,1.911792,-2.895773,-0.950117, + 0.820312,-0.193024,-0.538358,1.880971,-2.733242,-0.8902, + 0.186476,0.252953,-0.949337,1.960643,-2.71286,-0.90089, + -0.1083,-0.048546,0.992932,1.911792,-2.895773,-0.950117, + 0.186476,0.252953,-0.949337,1.960643,-2.71286,-0.90089, + 0.43768,-0.823149,0.361748,2.021366,-2.881725,-0.945561, + 0.43768,-0.823149,0.361748,2.021366,-2.881725,-0.945561, + 0.186476,0.252953,-0.949337,1.960643,-2.71286,-0.90089, + -0.247433,-0.24804,-0.936618,1.994078,-2.713047,-0.824553, + 0.43768,-0.823149,0.361748,2.021366,-2.881725,-0.945561, + -0.247433,-0.24804,-0.936618,1.994078,-2.713047,-0.824553, + -0.671694,-0.023528,-0.740455,2.057496,-2.887282,-0.844225, + -0.024032,-0.835976,0.54824,1.734568,-2.965876,-0.986396, + -0.044013,0.340434,-0.939238,1.806371,-2.949735,-0.984058, + -0.088841,0.02472,-0.995739,1.735077,-3.022732,-0.972751, + -0.088841,0.02472,-0.995739,1.735077,-3.022732,-0.972751, + 0.57446,0.218241,-0.788902,1.802387,-3.089615,-0.961851, + 0.526213,0.349004,-0.775433,1.721745,-3.116887,-0.979111, + 0.526213,0.349004,-0.775433,1.721745,-3.116887,-0.979111, + 0.57446,0.218241,-0.788902,1.802387,-3.089615,-0.961851, + 0.926951,0.366239,0.081429,1.811797,-3.135641,-0.933096, + 0.43768,-0.823149,0.361748,2.021366,-2.881725,-0.945561, + -0.671694,-0.023528,-0.740455,2.057496,-2.887282,-0.844225, + 0.672893,0.661099,-0.331908,2.113587,-3.011851,-0.851648, + 0.43768,-0.823149,0.361748,2.021366,-2.881725,-0.945561, + 0.672893,0.661099,-0.331908,2.113587,-3.011851,-0.851648, + -0.541077,0.245809,-0.804247,2.091539,-3.032437,-0.947029, + -0.1083,-0.048546,0.992932,1.911792,-2.895773,-0.950117, + -0.496829,-0.096649,-0.86245,1.848272,-2.92726,-0.996966, + -0.845931,-0.255219,0.468256,1.830669,-2.736121,-0.903313, + -0.1083,-0.048546,0.992932,1.911792,-2.895773,-0.950117, + -0.845931,-0.255219,0.468256,1.830669,-2.736121,-0.903313, + 0.820312,-0.193024,-0.538358,1.880971,-2.733242,-0.8902, + -0.044013,0.340434,-0.939238,1.806371,-2.949735,-0.984058, + -0.069043,-0.157333,-0.985129,1.771416,-2.769024,-0.9461, + -0.845931,-0.255219,0.468256,1.830669,-2.736121,-0.903313, + -0.044013,0.340434,-0.939238,1.806371,-2.949735,-0.984058, + -0.845931,-0.255219,0.468256,1.830669,-2.736121,-0.903313, + -0.496829,-0.096649,-0.86245,1.848272,-2.92726,-0.996966, + -0.90358,0.003167,-0.428408,1.705953,-3.006628,-0.83263, + -0.088841,0.02472,-0.995739,1.735077,-3.022732,-0.972751, + 0.526213,0.349004,-0.775433,1.721745,-3.116887,-0.979111, + -0.90358,0.003167,-0.428408,1.705953,-3.006628,-0.83263, + 0.526213,0.349004,-0.775433,1.721745,-3.116887,-0.979111, + -0.874488,-0.088621,-0.476882,1.709173,-3.133145,-0.80794, + -0.874488,-0.088621,-0.476882,1.709173,-3.133145,-0.80794, + 0.526213,0.349004,-0.775433,1.721745,-3.116887,-0.979111, + 0.926951,0.366239,0.081429,1.811797,-3.135641,-0.933096, + -0.874488,-0.088621,-0.476882,1.709173,-3.133145,-0.80794, + 0.926951,0.366239,0.081429,1.811797,-3.135641,-0.933096, + -0.783521,-0.393963,-0.480508,1.806407,-3.173343,-0.834455, + -0.967491,-0.143323,0.208372,1.741854,-3.114181,-0.700705, + -0.874488,-0.088621,-0.476882,1.709173,-3.133145,-0.80794, + -0.783521,-0.393963,-0.480508,1.806407,-3.173343,-0.834455, + -0.967491,-0.143323,0.208372,1.741854,-3.114181,-0.700705, + -0.783521,-0.393963,-0.480508,1.806407,-3.173343,-0.834455, + -0.630099,-0.773677,0.066329,1.900481,-3.131932,-0.728621, + -0.90358,0.003167,-0.428408,1.705953,-3.006628,-0.83263, + -0.874488,-0.088621,-0.476882,1.709173,-3.133145,-0.80794, + -0.967491,-0.143323,0.208372,1.741854,-3.114181,-0.700705, + -0.90358,0.003167,-0.428408,1.705953,-3.006628,-0.83263, + -0.967491,-0.143323,0.208372,1.741854,-3.114181,-0.700705, + -0.343436,-0.507052,0.790537,1.776024,-2.980086,-0.707575, + -0.343436,-0.507052,0.790537,1.776024,-2.980086,-0.707575, + 0.056398,-0.684481,0.726846,1.736425,-2.743683,-0.736866, + 0.21689,-0.976039,0.017487,1.700797,-2.794792,-0.82425, + -0.343436,-0.507052,0.790537,1.776024,-2.980086,-0.707575, + 0.21689,-0.976039,0.017487,1.700797,-2.794792,-0.82425, + -0.90358,0.003167,-0.428408,1.705953,-3.006628,-0.83263, + 0.43768,-0.823149,0.361748,2.021366,-2.881725,-0.945561, + -0.541077,0.245809,-0.804247,2.091539,-3.032437,-0.947029, + 0.872426,0.488735,0.003222,1.980621,-3.043895,-0.964237, + 0.43768,-0.823149,0.361748,2.021366,-2.881725,-0.945561, + 0.872426,0.488735,0.003222,1.980621,-3.043895,-0.964237, + -0.1083,-0.048546,0.992932,1.911792,-2.895773,-0.950117, + 0.872426,0.488735,0.003222,1.980621,-3.043895,-0.964237, + -0.069765,-0.126006,0.989573,1.898573,-3.068274,-0.994338, + -0.496829,-0.096649,-0.86245,1.848272,-2.92726,-0.996966, + 0.872426,0.488735,0.003222,1.980621,-3.043895,-0.964237, + -0.496829,-0.096649,-0.86245,1.848272,-2.92726,-0.996966, + -0.1083,-0.048546,0.992932,1.911792,-2.895773,-0.950117, + -0.496829,-0.096649,-0.86245,1.848272,-2.92726,-0.996966, + -0.069765,-0.126006,0.989573,1.898573,-3.068274,-0.994338, + 0.383337,-0.601981,0.700479,1.855134,-3.083228,-0.986129, + -0.496829,-0.096649,-0.86245,1.848272,-2.92726,-0.996966, + 0.383337,-0.601981,0.700479,1.855134,-3.083228,-0.986129, + -0.044013,0.340434,-0.939238,1.806371,-2.949735,-0.984058, + 0.57446,0.218241,-0.788902,1.802387,-3.089615,-0.961851, + 0.383337,-0.601981,0.700479,1.855134,-3.083228,-0.986129, + 0.926951,0.366239,0.081429,1.811797,-3.135641,-0.933096, + -0.088841,0.02472,-0.995739,1.735077,-3.022732,-0.972751, + -0.044013,0.340434,-0.939238,1.806371,-2.949735,-0.984058, + 0.383337,-0.601981,0.700479,1.855134,-3.083228,-0.986129, + -0.088841,0.02472,-0.995739,1.735077,-3.022732,-0.972751, + 0.383337,-0.601981,0.700479,1.855134,-3.083228,-0.986129, + 0.57446,0.218241,-0.788902,1.802387,-3.089615,-0.961851, + -0.088841,0.02472,-0.995739,1.735077,-3.022732,-0.972751, + -0.90358,0.003167,-0.428408,1.705953,-3.006628,-0.83263, + -0.024032,-0.835976,0.54824,1.734568,-2.965876,-0.986396, + 0.672893,0.661099,-0.331908,2.113587,-3.011851,-0.851648, + -0.671694,-0.023528,-0.740455,2.057496,-2.887282,-0.844225, + -0.990285,-0.10079,0.095796,2.001343,-2.847715,-0.762517, + 0.672893,0.661099,-0.331908,2.113587,-3.011851,-0.851648, + -0.990285,-0.10079,0.095796,2.001343,-2.847715,-0.762517, + -0.701253,0.091018,0.707079,2.07369,-3.020848,-0.782654, + -0.967491,-0.143323,0.208372,1.741854,-3.114181,-0.700705, + -0.630099,-0.773677,0.066329,1.900481,-3.131932,-0.728621, + 0.963394,-0.268066,-0.003702,1.857471,-2.950722,-0.669988, + -0.967491,-0.143323,0.208372,1.741854,-3.114181,-0.700705, + 0.963394,-0.268066,-0.003702,1.857471,-2.950722,-0.669988, + -0.343436,-0.507052,0.790537,1.776024,-2.980086,-0.707575, + -0.630099,-0.773677,0.066329,1.900481,-3.131932,-0.728621, + 0.714275,0.465374,0.522723,1.998099,-3.039955,-0.718855, + 0.81992,-0.126246,0.558385,1.945632,-2.87671,-0.703118, + -0.630099,-0.773677,0.066329,1.900481,-3.131932,-0.728621, + 0.81992,-0.126246,0.558385,1.945632,-2.87671,-0.703118, + 0.963394,-0.268066,-0.003702,1.857471,-2.950722,-0.669988, + 0.714275,0.465374,0.522723,1.998099,-3.039955,-0.718855, + -0.701253,0.091018,0.707079,2.07369,-3.020848,-0.782654, + -0.990285,-0.10079,0.095796,2.001343,-2.847715,-0.762517, + 0.714275,0.465374,0.522723,1.998099,-3.039955,-0.718855, + -0.990285,-0.10079,0.095796,2.001343,-2.847715,-0.762517, + 0.81992,-0.126246,0.558385,1.945632,-2.87671,-0.703118, + 0.963394,-0.268066,-0.003702,1.857471,-2.950722,-0.669988, + 0.81992,-0.126246,0.558385,1.945632,-2.87671,-0.703118, + 0.751149,0.43192,0.49922,1.884318,-2.724404,-0.701999, + 0.963394,-0.268066,-0.003702,1.857471,-2.950722,-0.669988, + 0.751149,0.43192,0.49922,1.884318,-2.724404,-0.701999, + 0.975634,-0.187232,0.114377,1.841282,-2.716008,-0.708009, + 0.751149,0.43192,0.49922,1.884318,-2.724404,-0.701999, + 0.81992,-0.126246,0.558385,1.945632,-2.87671,-0.703118, + -0.990285,-0.10079,0.095796,2.001343,-2.847715,-0.762517, + 0.751149,0.43192,0.49922,1.884318,-2.724404,-0.701999, + -0.990285,-0.10079,0.095796,2.001343,-2.847715,-0.762517, + -0.062994,-0.00854,0.997977,1.972647,-2.728848,-0.772496, + -0.343436,-0.507052,0.790537,1.776024,-2.980086,-0.707575, + 0.963394,-0.268066,-0.003702,1.857471,-2.950722,-0.669988, + 0.975634,-0.187232,0.114377,1.841282,-2.716008,-0.708009, + -0.343436,-0.507052,0.790537,1.776024,-2.980086,-0.707575, + 0.975634,-0.187232,0.114377,1.841282,-2.716008,-0.708009, + 0.056398,-0.684481,0.726846,1.736425,-2.743683,-0.736866, + 0.137764,-0.289893,-0.947092,-2.591357,-1.510845,-0.88547, + 0.048753,-0.975535,-0.21437,-2.734184,-1.717948,-0.749581, + 0.26198,0.048424,0.963858,-2.837147,-1.791733,-0.921563, + 0.137764,-0.289893,-0.947092,-2.591357,-1.510845,-0.88547, + 0.26198,0.048424,0.963858,-2.837147,-1.791733,-0.921563, + 0.79444,0.150524,0.588394,-2.687162,-1.539807,-0.988048, + 0.79444,0.150524,0.588394,-2.687162,-1.539807,-0.988048, + 0.26198,0.048424,0.963858,-2.837147,-1.791733,-0.921563, + 0.24139,0.178826,0.953809,-2.918293,-1.904184,-1.004659, + 0.79444,0.150524,0.588394,-2.687162,-1.539807,-0.988048, + 0.24139,0.178826,0.953809,-2.918293,-1.904184,-1.004659, + -0.15812,-0.033626,-0.986847,-2.765069,-1.561164,-1.084313, + -0.15812,-0.033626,-0.986847,-2.765069,-1.561164,-1.084313, + 0.24139,0.178826,0.953809,-2.918293,-1.904184,-1.004659, + 0.247956,0.087485,0.964813,-3.010917,-1.884498,-1.08351, + -0.15812,-0.033626,-0.986847,-2.765069,-1.561164,-1.084313, + 0.247956,0.087485,0.964813,-3.010917,-1.884498,-1.08351, + -0.234266,0.044111,-0.971171,-2.862576,-1.546894,-1.117139, + -0.234266,0.044111,-0.971171,-2.862576,-1.546894,-1.117139, + 0.247956,0.087485,0.964813,-3.010917,-1.884498,-1.08351, + 0.81802,-0.47123,-0.329827,-3.117476,-1.866892,-1.108034, + -0.234266,0.044111,-0.971171,-2.862576,-1.546894,-1.117139, + 0.81802,-0.47123,-0.329827,-3.117476,-1.866892,-1.108034, + 0.726897,-0.546446,-0.415953,-2.955052,-1.49684,-1.128812, + 0.726897,-0.546446,-0.415953,-2.955052,-1.49684,-1.128812, + 0.81802,-0.47123,-0.329827,-3.117476,-1.866892,-1.108034, + 0.776291,-0.374868,-0.5068,-3.23261,-1.834299,-1.087832, + 0.726897,-0.546446,-0.415953,-2.955052,-1.49684,-1.128812, + 0.776291,-0.374868,-0.5068,-3.23261,-1.834299,-1.087832, + -0.390861,0.032481,-0.919876,-3.063133,-1.440555,-1.090926, + -0.086361,-0.084973,-0.992634,-3.36599,-1.48517,-0.888076, + -0.424393,0.057227,-0.903668,-3.49052,-1.760417,-0.903104, + -0.51975,0.138222,-0.843063,-3.498521,-1.762078,-0.762472, + -0.086361,-0.084973,-0.992634,-3.36599,-1.48517,-0.888076, + -0.51975,0.138222,-0.843063,-3.498521,-1.762078,-0.762472, + -0.354058,-0.732075,0.581987,-3.387254,-1.486027,-0.672861, + -0.354058,-0.732075,0.581987,-3.387254,-1.486027,-0.672861, + -0.782249,0.198377,-0.590536,-3.335942,-1.365685,-0.72459, + -0.811102,-0.12903,-0.570495,-3.319817,-1.365015,-0.886015, + -0.354058,-0.732075,0.581987,-3.387254,-1.486027,-0.672861, + -0.811102,-0.12903,-0.570495,-3.319817,-1.365015,-0.886015, + -0.086361,-0.084973,-0.992634,-3.36599,-1.48517,-0.888076, + -0.775358,0.344514,-0.529274,-3.078699,-2.553982,-1.046834, + -0.440199,0.219838,-0.870572,-3.162498,-2.556375,-1.058409, + -0.820357,0.160676,-0.548815,-3.177824,-2.279173,-1.04758, + -0.775358,0.344514,-0.529274,-3.078699,-2.553982,-1.046834, + -0.820357,0.160676,-0.548815,-3.177824,-2.279173,-1.04758, + -0.906134,0.012265,0.422812,-3.068444,-2.260195,-1.03507, + -0.906134,0.012265,0.422812,-3.068444,-2.260195,-1.03507, + -0.820357,0.160676,-0.548815,-3.177824,-2.279173,-1.04758, + 0.000667,0.002295,-0.999997,-3.169489,-2.110039,-1.076796, + -0.906134,0.012265,0.422812,-3.068444,-2.260195,-1.03507, + 0.000667,0.002295,-0.999997,-3.169489,-2.110039,-1.076796, + 0.461464,-0.003303,-0.887153,-3.047974,-2.109628,-1.063497, + 0.461464,-0.003303,-0.887153,-3.047974,-2.109628,-1.063497, + 0.000667,0.002295,-0.999997,-3.169489,-2.110039,-1.076796, + 0.81802,-0.47123,-0.329827,-3.117476,-1.866892,-1.108034, + 0.461464,-0.003303,-0.887153,-3.047974,-2.109628,-1.063497, + 0.81802,-0.47123,-0.329827,-3.117476,-1.866892,-1.108034, + 0.247956,0.087485,0.964813,-3.010917,-1.884498,-1.08351, + -0.820357,0.160676,-0.548815,-3.177824,-2.279173,-1.04758, + -0.156447,-0.088128,-0.983747,-3.207447,-2.103206,-1.071366, + 0.000667,0.002295,-0.999997,-3.169489,-2.110039,-1.076796, + 0.000667,0.002295,-0.999997,-3.169489,-2.110039,-1.076796, + -0.156447,-0.088128,-0.983747,-3.207447,-2.103206,-1.071366, + 0.776291,-0.374868,-0.5068,-3.23261,-1.834299,-1.087832, + 0.000667,0.002295,-0.999997,-3.169489,-2.110039,-1.076796, + 0.776291,-0.374868,-0.5068,-3.23261,-1.834299,-1.087832, + 0.81802,-0.47123,-0.329827,-3.117476,-1.866892,-1.108034, + -0.440199,0.219838,-0.870572,-3.162498,-2.556375,-1.058409, + 0.433219,-0.09361,-0.896414,-3.251541,-2.56405,-1.023627, + -0.019303,-0.142974,-0.989538,-3.281816,-2.305055,-1.001878, + -0.440199,0.219838,-0.870572,-3.162498,-2.556375,-1.058409, + -0.019303,-0.142974,-0.989538,-3.281816,-2.305055,-1.001878, + -0.820357,0.160676,-0.548815,-3.177824,-2.279173,-1.04758, + -0.820357,0.160676,-0.548815,-3.177824,-2.279173,-1.04758, + -0.019303,-0.142974,-0.989538,-3.281816,-2.305055,-1.001878, + 0.422569,-0.18743,-0.886739,-3.327526,-2.075729,-1.005328, + -0.820357,0.160676,-0.548815,-3.177824,-2.279173,-1.04758, + 0.422569,-0.18743,-0.886739,-3.327526,-2.075729,-1.005328, + -0.156447,-0.088128,-0.983747,-3.207447,-2.103206,-1.071366, + -0.156447,-0.088128,-0.983747,-3.207447,-2.103206,-1.071366, + 0.422569,-0.18743,-0.886739,-3.327526,-2.075729,-1.005328, + 0.356923,-0.210291,-0.910156,-3.357996,-1.811803,-0.975625, + -0.156447,-0.088128,-0.983747,-3.207447,-2.103206,-1.071366, + 0.356923,-0.210291,-0.910156,-3.357996,-1.811803,-0.975625, + 0.776291,-0.374868,-0.5068,-3.23261,-1.834299,-1.087832, + 0.433219,-0.09361,-0.896414,-3.251541,-2.56405,-1.023627, + -0.354049,-0.10839,-0.928925,-3.347304,-2.573628,-0.955211, + -0.35872,0.092902,-0.928811,-3.389388,-2.305625,-0.950348, + 0.433219,-0.09361,-0.896414,-3.251541,-2.56405,-1.023627, + -0.35872,0.092902,-0.928811,-3.389388,-2.305625,-0.950348, + -0.019303,-0.142974,-0.989538,-3.281816,-2.305055,-1.001878, + -0.019303,-0.142974,-0.989538,-3.281816,-2.305055,-1.001878, + -0.35872,0.092902,-0.928811,-3.389388,-2.305625,-0.950348, + -0.453746,-0.057149,-0.889297,-3.451965,-2.077314,-0.931974, + -0.019303,-0.142974,-0.989538,-3.281816,-2.305055,-1.001878, + -0.453746,-0.057149,-0.889297,-3.451965,-2.077314,-0.931974, + 0.422569,-0.18743,-0.886739,-3.327526,-2.075729,-1.005328, + 0.422569,-0.18743,-0.886739,-3.327526,-2.075729,-1.005328, + -0.453746,-0.057149,-0.889297,-3.451965,-2.077314,-0.931974, + -0.424393,0.057227,-0.903668,-3.49052,-1.760417,-0.903104, + 0.422569,-0.18743,-0.886739,-3.327526,-2.075729,-1.005328, + -0.424393,0.057227,-0.903668,-3.49052,-1.760417,-0.903104, + 0.356923,-0.210291,-0.910156,-3.357996,-1.811803,-0.975625, + -0.501053,-0.05946,-0.863371,-3.022819,-2.52224,-0.979148, + -0.775358,0.344514,-0.529274,-3.078699,-2.553982,-1.046834, + -0.906134,0.012265,0.422812,-3.068444,-2.260195,-1.03507, + -0.501053,-0.05946,-0.863371,-3.022819,-2.52224,-0.979148, + -0.906134,0.012265,0.422812,-3.068444,-2.260195,-1.03507, + -0.779685,0.025369,-0.625657,-3.007483,-2.270712,-0.984279, + -0.779685,0.025369,-0.625657,-3.007483,-2.270712,-0.984279, + -0.906134,0.012265,0.422812,-3.068444,-2.260195,-1.03507, + 0.461464,-0.003303,-0.887153,-3.047974,-2.109628,-1.063497, + -0.779685,0.025369,-0.625657,-3.007483,-2.270712,-0.984279, + 0.461464,-0.003303,-0.887153,-3.047974,-2.109628,-1.063497, + -0.765488,-0.115048,-0.633082,-2.969687,-2.097941,-0.982836, + -0.765488,-0.115048,-0.633082,-2.969687,-2.097941,-0.982836, + 0.461464,-0.003303,-0.887153,-3.047974,-2.109628,-1.063497, + 0.247956,0.087485,0.964813,-3.010917,-1.884498,-1.08351, + -0.765488,-0.115048,-0.633082,-2.969687,-2.097941,-0.982836, + 0.247956,0.087485,0.964813,-3.010917,-1.884498,-1.08351, + 0.24139,0.178826,0.953809,-2.918293,-1.904184,-1.004659, + -0.807765,-0.096776,-0.581507,-2.892438,-1.95081,-0.87812, + 0.24139,0.178826,0.953809,-2.918293,-1.904184,-1.004659, + 0.26198,0.048424,0.963858,-2.837147,-1.791733,-0.921563, + 0.24139,0.178826,0.953809,-2.918293,-1.904184,-1.004659, + -0.807765,-0.096776,-0.581507,-2.892438,-1.95081,-0.87812, + 0.937141,-0.149709,-0.315204,-2.981187,-2.142718,-0.858353, + 0.24139,0.178826,0.953809,-2.918293,-1.904184,-1.004659, + 0.937141,-0.149709,-0.315204,-2.981187,-2.142718,-0.858353, + -0.765488,-0.115048,-0.633082,-2.969687,-2.097941,-0.982836, + -0.765488,-0.115048,-0.633082,-2.969687,-2.097941,-0.982836, + 0.937141,-0.149709,-0.315204,-2.981187,-2.142718,-0.858353, + 0.866897,-0.268351,-0.420091,-3.030605,-2.311222,-0.88433, + -0.765488,-0.115048,-0.633082,-2.969687,-2.097941,-0.982836, + 0.866897,-0.268351,-0.420091,-3.030605,-2.311222,-0.88433, + -0.779685,0.025369,-0.625657,-3.007483,-2.270712,-0.984279, + -0.779685,0.025369,-0.625657,-3.007483,-2.270712,-0.984279, + 0.866897,-0.268351,-0.420091,-3.030605,-2.311222,-0.88433, + 0.886562,-0.46255,-0.007485,-3.04661,-2.510881,-0.900772, + -0.779685,0.025369,-0.625657,-3.007483,-2.270712,-0.984279, + 0.886562,-0.46255,-0.007485,-3.04661,-2.510881,-0.900772, + -0.501053,-0.05946,-0.863371,-3.022819,-2.52224,-0.979148, + -0.807765,-0.096776,-0.581507,-2.892438,-1.95081,-0.87812, + 0.982106,-0.010346,-0.188044,-2.964215,-1.978727,-0.776572, + 0.567578,-0.469833,0.6761,-3.040398,-2.156239,-0.808208, + -0.807765,-0.096776,-0.581507,-2.892438,-1.95081,-0.87812, + 0.567578,-0.469833,0.6761,-3.040398,-2.156239,-0.808208, + 0.937141,-0.149709,-0.315204,-2.981187,-2.142718,-0.858353, + 0.937141,-0.149709,-0.315204,-2.981187,-2.142718,-0.858353, + 0.567578,-0.469833,0.6761,-3.040398,-2.156239,-0.808208, + 0.866897,-0.268351,-0.420091,-3.030605,-2.311222,-0.88433, + 0.866897,-0.268351,-0.420091,-3.030605,-2.311222,-0.88433, + 0.567578,-0.469833,0.6761,-3.040398,-2.156239,-0.808208, + 0.890357,-0.340018,0.302742,-3.120761,-2.15777,-0.766432, + 0.866897,-0.268351,-0.420091,-3.030605,-2.311222,-0.88433, + 0.890357,-0.340018,0.302742,-3.120761,-2.15777,-0.766432, + 0.773659,-0.235087,0.588375,-3.144012,-2.333635,-0.829994, + 0.982106,-0.010346,-0.188044,-2.964215,-1.978727,-0.776572, + 0.789099,-0.039289,0.613008,-3.066022,-1.953125,-0.719516, + 0.890357,-0.340018,0.302742,-3.120761,-2.15777,-0.766432, + 0.982106,-0.010346,-0.188044,-2.964215,-1.978727,-0.776572, + 0.890357,-0.340018,0.302742,-3.120761,-2.15777,-0.766432, + 0.567578,-0.469833,0.6761,-3.040398,-2.156239,-0.808208, + 0.789099,-0.039289,0.613008,-3.066022,-1.953125,-0.719516, + 0.230893,-0.309688,0.922378,-3.211005,-1.850398,-0.700723, + 0.257818,-0.230014,0.938415,-3.253309,-2.137354,-0.760713, + 0.789099,-0.039289,0.613008,-3.066022,-1.953125,-0.719516, + 0.257818,-0.230014,0.938415,-3.253309,-2.137354,-0.760713, + 0.890357,-0.340018,0.302742,-3.120761,-2.15777,-0.766432, + 0.890357,-0.340018,0.302742,-3.120761,-2.15777,-0.766432, + 0.257818,-0.230014,0.938415,-3.253309,-2.137354,-0.760713, + 0.148388,-0.325205,0.933929,-3.235873,-2.335338,-0.820588, + 0.890357,-0.340018,0.302742,-3.120761,-2.15777,-0.766432, + 0.148388,-0.325205,0.933929,-3.235873,-2.335338,-0.820588, + 0.773659,-0.235087,0.588375,-3.144012,-2.333635,-0.829994, + 0.773659,-0.235087,0.588375,-3.144012,-2.333635,-0.829994, + 0.148388,-0.325205,0.933929,-3.235873,-2.335338,-0.820588, + -0.215783,-0.895808,0.388544,-3.240554,-2.555467,-0.856262, + 0.773659,-0.235087,0.588375,-3.144012,-2.333635,-0.829994, + -0.215783,-0.895808,0.388544,-3.240554,-2.555467,-0.856262, + -0.065687,-0.249194,0.966223,-3.132772,-2.528669,-0.848639, + 0.515412,-0.714946,0.472444,-3.304804,-1.582192,-0.643445, + -0.354058,-0.732075,0.581987,-3.387254,-1.486027,-0.672861, + -0.51975,0.138222,-0.843063,-3.498521,-1.762078,-0.762472, + 0.515412,-0.714946,0.472444,-3.304804,-1.582192,-0.643445, + -0.51975,0.138222,-0.843063,-3.498521,-1.762078,-0.762472, + -0.050511,-0.258376,0.964723,-3.381262,-1.828189,-0.697034, + -0.050511,-0.258376,0.964723,-3.381262,-1.828189,-0.697034, + 0.230893,-0.309688,0.922378,-3.211005,-1.850398,-0.700723, + -0.012978,-0.998326,0.056357,-3.139394,-1.687482,-0.638546, + -0.050511,-0.258376,0.964723,-3.381262,-1.828189,-0.697034, + -0.012978,-0.998326,0.056357,-3.139394,-1.687482,-0.638546, + 0.515412,-0.714946,0.472444,-3.304804,-1.582192,-0.643445, + 0.230893,-0.309688,0.922378,-3.211005,-1.850398,-0.700723, + -0.050511,-0.258376,0.964723,-3.381262,-1.828189,-0.697034, + -0.042094,-0.220101,0.974568,-3.422698,-2.070796,-0.773898, + 0.230893,-0.309688,0.922378,-3.211005,-1.850398,-0.700723, + -0.042094,-0.220101,0.974568,-3.422698,-2.070796,-0.773898, + 0.257818,-0.230014,0.938415,-3.253309,-2.137354,-0.760713, + 0.257818,-0.230014,0.938415,-3.253309,-2.137354,-0.760713, + -0.042094,-0.220101,0.974568,-3.422698,-2.070796,-0.773898, + -0.085416,-0.081635,0.992995,-3.339489,-2.328145,-0.827572, + 0.257818,-0.230014,0.938415,-3.253309,-2.137354,-0.760713, + -0.085416,-0.081635,0.992995,-3.339489,-2.328145,-0.827572, + 0.148388,-0.325205,0.933929,-3.235873,-2.335338,-0.820588, + 0.148388,-0.325205,0.933929,-3.235873,-2.335338,-0.820588, + -0.085416,-0.081635,0.992995,-3.339489,-2.328145,-0.827572, + 0.255431,-0.055528,0.965231,-3.297886,-2.54902,-0.861657, + 0.148388,-0.325205,0.933929,-3.235873,-2.335338,-0.820588, + 0.255431,-0.055528,0.965231,-3.297886,-2.54902,-0.861657, + -0.215783,-0.895808,0.388544,-3.240554,-2.555467,-0.856262, + -0.050511,-0.258376,0.964723,-3.381262,-1.828189,-0.697034, + -0.51975,0.138222,-0.843063,-3.498521,-1.762078,-0.762472, + -0.348227,-0.192528,0.917426,-3.463753,-2.079892,-0.844667, + -0.050511,-0.258376,0.964723,-3.381262,-1.828189,-0.697034, + -0.348227,-0.192528,0.917426,-3.463753,-2.079892,-0.844667, + -0.042094,-0.220101,0.974568,-3.422698,-2.070796,-0.773898, + -0.042094,-0.220101,0.974568,-3.422698,-2.070796,-0.773898, + -0.348227,-0.192528,0.917426,-3.463753,-2.079892,-0.844667, + -0.401279,-0.250965,0.880904,-3.412068,-2.356105,-0.865813, + -0.042094,-0.220101,0.974568,-3.422698,-2.070796,-0.773898, + -0.401279,-0.250965,0.880904,-3.412068,-2.356105,-0.865813, + -0.085416,-0.081635,0.992995,-3.339489,-2.328145,-0.827572, + -0.085416,-0.081635,0.992995,-3.339489,-2.328145,-0.827572, + -0.401279,-0.250965,0.880904,-3.412068,-2.356105,-0.865813, + -0.326843,-0.236652,0.91497,-3.372066,-2.569159,-0.904785, + -0.085416,-0.081635,0.992995,-3.339489,-2.328145,-0.827572, + -0.326843,-0.236652,0.91497,-3.372066,-2.569159,-0.904785, + 0.255431,-0.055528,0.965231,-3.297886,-2.54902,-0.861657, + -0.348227,-0.192528,0.917426,-3.463753,-2.079892,-0.844667, + -0.453746,-0.057149,-0.889297,-3.451965,-2.077314,-0.931974, + -0.35872,0.092902,-0.928811,-3.389388,-2.305625,-0.950348, + -0.348227,-0.192528,0.917426,-3.463753,-2.079892,-0.844667, + -0.35872,0.092902,-0.928811,-3.389388,-2.305625,-0.950348, + -0.401279,-0.250965,0.880904,-3.412068,-2.356105,-0.865813, + -0.401279,-0.250965,0.880904,-3.412068,-2.356105,-0.865813, + -0.35872,0.092902,-0.928811,-3.389388,-2.305625,-0.950348, + -0.354049,-0.10839,-0.928925,-3.347304,-2.573628,-0.955211, + -0.401279,-0.250965,0.880904,-3.412068,-2.356105,-0.865813, + -0.354049,-0.10839,-0.928925,-3.347304,-2.573628,-0.955211, + -0.326843,-0.236652,0.91497,-3.372066,-2.569159,-0.904785, + -0.51975,0.138222,-0.843063,-3.498521,-1.762078,-0.762472, + -0.424393,0.057227,-0.903668,-3.49052,-1.760417,-0.903104, + -0.453746,-0.057149,-0.889297,-3.451965,-2.077314,-0.931974, + -0.51975,0.138222,-0.843063,-3.498521,-1.762078,-0.762472, + -0.453746,-0.057149,-0.889297,-3.451965,-2.077314,-0.931974, + -0.348227,-0.192528,0.917426,-3.463753,-2.079892,-0.844667, + 0.356923,-0.210291,-0.910156,-3.357996,-1.811803,-0.975625, + -0.424393,0.057227,-0.903668,-3.49052,-1.760417,-0.903104, + -0.086361,-0.084973,-0.992634,-3.36599,-1.48517,-0.888076, + 0.356923,-0.210291,-0.910156,-3.357996,-1.811803,-0.975625, + -0.086361,-0.084973,-0.992634,-3.36599,-1.48517,-0.888076, + -0.032036,-0.072305,-0.996868,-3.342096,-1.533989,-0.921628, + -0.587844,-0.244917,-0.771009,1.953911,-2.462233,-0.830594, + 0.985192,-0.12583,0.116459,1.930747,-2.463535,-0.894743, + 0.996811,-0.048518,0.063355,1.98533,-2.221319,-0.893145, + -0.587844,-0.244917,-0.771009,1.953911,-2.462233,-0.830594, + 0.996811,-0.048518,0.063355,1.98533,-2.221319,-0.893145, + -0.845196,-0.27877,-0.455994,2.02453,-2.195334,-0.811284, + -0.845196,-0.27877,-0.455994,2.02453,-2.195334,-0.811284, + 0.996811,-0.048518,0.063355,1.98533,-2.221319,-0.893145, + 0.957938,-0.285979,-0.023877,2.013095,-2.051912,-0.911043, + -0.845196,-0.27877,-0.455994,2.02453,-2.195334,-0.811284, + 0.957938,-0.285979,-0.023877,2.013095,-2.051912,-0.911043, + -0.732521,-0.474279,-0.488336,2.047696,-2.050138,-0.814712, + -0.732521,-0.474279,-0.488336,2.047696,-2.050138,-0.814712, + 0.957938,-0.285979,-0.023877,2.013095,-2.051912,-0.911043, + -0.274087,0.000043,0.961705,2.021591,-1.755289,-0.912093, + -0.732521,-0.474279,-0.488336,2.047696,-2.050138,-0.814712, + -0.274087,0.000043,0.961705,2.021591,-1.755289,-0.912093, + 0.972392,0.232654,-0.018037,2.053108,-1.738285,-0.824853, + 0.972392,0.232654,-0.018037,2.053108,-1.738285,-0.824853, + -0.274087,0.000043,0.961705,2.021591,-1.755289,-0.912093, + 0.74023,-0.090866,-0.666185,2.036036,-1.57908,-0.967151, + 0.972392,0.232654,-0.018037,2.053108,-1.738285,-0.824853, + 0.74023,-0.090866,-0.666185,2.036036,-1.57908,-0.967151, + 0.999491,-0.02584,-0.01873,2.059844,-1.561331,-0.858957, + -0.176356,-0.113876,-0.977717,1.678986,-2.513137,-0.891745, + -0.051713,-0.100832,-0.993559,1.737623,-2.485017,-0.918334, + -0.069043,-0.157333,-0.985129,1.771416,-2.769024,-0.9461, + -0.176356,-0.113876,-0.977717,1.678986,-2.513137,-0.891745, + -0.069043,-0.157333,-0.985129,1.771416,-2.769024,-0.9461, + -0.246054,-0.154918,-0.956796,1.718315,-2.775468,-0.921796, + -0.136917,-0.20176,-0.969818,1.648793,-2.280014,-0.929365, + 0.039,-0.185675,-0.981837,1.710406,-2.272223,-0.954296, + -0.051713,-0.100832,-0.993559,1.737623,-2.485017,-0.918334, + -0.136917,-0.20176,-0.969818,1.648793,-2.280014,-0.929365, + -0.051713,-0.100832,-0.993559,1.737623,-2.485017,-0.918334, + -0.176356,-0.113876,-0.977717,1.678986,-2.513137,-0.891745, + -0.17902,-0.308668,-0.934171,1.6249,-2.087301,-0.963391, + 0.109483,-0.310605,-0.944213,1.720031,-2.105568,-0.971354, + 0.039,-0.185675,-0.981837,1.710406,-2.272223,-0.954296, + -0.17902,-0.308668,-0.934171,1.6249,-2.087301,-0.963391, + 0.039,-0.185675,-0.981837,1.710406,-2.272223,-0.954296, + -0.136917,-0.20176,-0.969818,1.648793,-2.280014,-0.929365, + -0.739347,0.031953,-0.672566,1.572979,-1.827591,-0.985823, + -0.09542,0.162222,-0.98213,1.717145,-1.80953,-1.004092, + 0.109483,-0.310605,-0.944213,1.720031,-2.105568,-0.971354, + -0.739347,0.031953,-0.672566,1.572979,-1.827591,-0.985823, + 0.109483,-0.310605,-0.944213,1.720031,-2.105568,-0.971354, + -0.17902,-0.308668,-0.934171,1.6249,-2.087301,-0.963391, + -0.652584,-0.147678,-0.743186,1.54175,-1.643613,-1.01419, + -0.211092,-0.082708,-0.973961,1.650318,-1.645881,-1.053347, + -0.09542,0.162222,-0.98213,1.717145,-1.80953,-1.004092, + -0.652584,-0.147678,-0.743186,1.54175,-1.643613,-1.01419, + -0.09542,0.162222,-0.98213,1.717145,-1.80953,-1.004092, + -0.739347,0.031953,-0.672566,1.572979,-1.827591,-0.985823, + -0.4008,-0.167777,-0.900672,1.586321,-2.273752,-0.880969, + -0.136917,-0.20176,-0.969818,1.648793,-2.280014,-0.929365, + -0.176356,-0.113876,-0.977717,1.678986,-2.513137,-0.891745, + -0.4008,-0.167777,-0.900672,1.586321,-2.273752,-0.880969, + -0.176356,-0.113876,-0.977717,1.678986,-2.513137,-0.891745, + -0.483189,-0.207332,-0.850613,1.655948,-2.520927,-0.844269, + -0.417424,-0.199203,-0.886609,1.529305,-2.092083,-0.887353, + -0.17902,-0.308668,-0.934171,1.6249,-2.087301,-0.963391, + -0.136917,-0.20176,-0.969818,1.648793,-2.280014,-0.929365, + -0.417424,-0.199203,-0.886609,1.529305,-2.092083,-0.887353, + -0.136917,-0.20176,-0.969818,1.648793,-2.280014,-0.929365, + -0.4008,-0.167777,-0.900672,1.586321,-2.273752,-0.880969, + -0.521685,-0.261319,-0.812131,1.508714,-1.808578,-0.934359, + -0.739347,0.031953,-0.672566,1.572979,-1.827591,-0.985823, + -0.17902,-0.308668,-0.934171,1.6249,-2.087301,-0.963391, + -0.521685,-0.261319,-0.812131,1.508714,-1.808578,-0.934359, + -0.17902,-0.308668,-0.934171,1.6249,-2.087301,-0.963391, + -0.417424,-0.199203,-0.886609,1.529305,-2.092083,-0.887353, + -0.970971,-0.219011,-0.096178,1.480629,-1.640132,-0.953447, + -0.652584,-0.147678,-0.743186,1.54175,-1.643613,-1.01419, + -0.739347,0.031953,-0.672566,1.572979,-1.827591,-0.985823, + -0.970971,-0.219011,-0.096178,1.480629,-1.640132,-0.953447, + -0.739347,0.031953,-0.672566,1.572979,-1.827591,-0.985823, + -0.521685,-0.261319,-0.812131,1.508714,-1.808578,-0.934359, + -0.883058,-0.239959,-0.403273,1.60129,-2.267132,-0.787696, + -0.4008,-0.167777,-0.900672,1.586321,-2.273752,-0.880969, + -0.483189,-0.207332,-0.850613,1.655948,-2.520927,-0.844269, + -0.883058,-0.239959,-0.403273,1.60129,-2.267132,-0.787696, + -0.483189,-0.207332,-0.850613,1.655948,-2.520927,-0.844269, + -0.912869,-0.285577,-0.291747,1.663494,-2.485963,-0.790773, + -0.872722,-0.174901,-0.455813,1.544087,-2.080722,-0.786432, + -0.417424,-0.199203,-0.886609,1.529305,-2.092083,-0.887353, + -0.4008,-0.167777,-0.900672,1.586321,-2.273752,-0.880969, + -0.872722,-0.174901,-0.455813,1.544087,-2.080722,-0.786432, + -0.4008,-0.167777,-0.900672,1.586321,-2.273752,-0.880969, + -0.883058,-0.239959,-0.403273,1.60129,-2.267132,-0.787696, + -0.874358,-0.225285,-0.429819,1.473886,-1.818947,-0.799576, + -0.521685,-0.261319,-0.812131,1.508714,-1.808578,-0.934359, + -0.417424,-0.199203,-0.886609,1.529305,-2.092083,-0.887353, + -0.874358,-0.225285,-0.429819,1.473886,-1.818947,-0.799576, + -0.417424,-0.199203,-0.886609,1.529305,-2.092083,-0.887353, + -0.872722,-0.174901,-0.455813,1.544087,-2.080722,-0.786432, + -0.794709,-0.185222,0.578041,1.451825,-1.576856,-0.702758, + -0.970971,-0.219011,-0.096178,1.480629,-1.640132,-0.953447, + -0.521685,-0.261319,-0.812131,1.508714,-1.808578,-0.934359, + -0.794709,-0.185222,0.578041,1.451825,-1.576856,-0.702758, + -0.521685,-0.261319,-0.812131,1.508714,-1.808578,-0.934359, + -0.874358,-0.225285,-0.429819,1.473886,-1.818947,-0.799576, + -0.898389,-0.217201,0.381735,1.677597,-2.237953,-0.696318, + -0.883058,-0.239959,-0.403273,1.60129,-2.267132,-0.787696, + -0.912869,-0.285577,-0.291747,1.663494,-2.485963,-0.790773, + -0.898389,-0.217201,0.381735,1.677597,-2.237953,-0.696318, + -0.912869,-0.285577,-0.291747,1.663494,-2.485963,-0.790773, + -0.887036,-0.210048,0.411154,1.756349,-2.446399,-0.705428, + -0.819257,-0.566976,-0.085772,1.643403,-2.076583,-0.689565, + -0.872722,-0.174901,-0.455813,1.544087,-2.080722,-0.786432, + -0.883058,-0.239959,-0.403273,1.60129,-2.267132,-0.787696, + -0.819257,-0.566976,-0.085772,1.643403,-2.076583,-0.689565, + -0.883058,-0.239959,-0.403273,1.60129,-2.267132,-0.787696, + -0.898389,-0.217201,0.381735,1.677597,-2.237953,-0.696318, + 0.193853,0.161608,-0.967628,1.596751,-1.722028,-0.684655, + -0.874358,-0.225285,-0.429819,1.473886,-1.818947,-0.799576, + -0.872722,-0.174901,-0.455813,1.544087,-2.080722,-0.786432, + 0.193853,0.161608,-0.967628,1.596751,-1.722028,-0.684655, + -0.872722,-0.174901,-0.455813,1.544087,-2.080722,-0.786432, + -0.819257,-0.566976,-0.085772,1.643403,-2.076583,-0.689565, + -0.493424,-0.165611,0.853877,1.599889,-1.595526,-0.623185, + -0.794709,-0.185222,0.578041,1.451825,-1.576856,-0.702758, + -0.874358,-0.225285,-0.429819,1.473886,-1.818947,-0.799576, + -0.493424,-0.165611,0.853877,1.599889,-1.595526,-0.623185, + -0.874358,-0.225285,-0.429819,1.473886,-1.818947,-0.799576, + 0.193853,0.161608,-0.967628,1.596751,-1.722028,-0.684655, + 0.985192,-0.12583,0.116459,1.930747,-2.463535,-0.894743, + -0.587844,-0.244917,-0.771009,1.953911,-2.462233,-0.830594, + -0.247433,-0.24804,-0.936618,1.994078,-2.713047,-0.824553, + 0.985192,-0.12583,0.116459,1.930747,-2.463535,-0.894743, + -0.247433,-0.24804,-0.936618,1.994078,-2.713047,-0.824553, + 0.186476,0.252953,-0.949337,1.960643,-2.71286,-0.90089, + 0.843062,-0.10517,-0.527433,1.864064,-2.469953,-0.935601, + 0.985192,-0.12583,0.116459,1.930747,-2.463535,-0.894743, + 0.186476,0.252953,-0.949337,1.960643,-2.71286,-0.90089, + 0.843062,-0.10517,-0.527433,1.864064,-2.469953,-0.935601, + 0.186476,0.252953,-0.949337,1.960643,-2.71286,-0.90089, + 0.820312,-0.193024,-0.538358,1.880971,-2.733242,-0.8902, + 0.159615,0.129847,-0.978602,1.941767,-1.759457,-0.997454, + 0.290478,-0.146424,-0.945612,1.937009,-1.625419,-1.026843, + 0.74023,-0.090866,-0.666185,2.036036,-1.57908,-0.967151, + 0.159615,0.129847,-0.978602,1.941767,-1.759457,-0.997454, + 0.74023,-0.090866,-0.666185,2.036036,-1.57908,-0.967151, + -0.274087,0.000043,0.961705,2.021591,-1.755289,-0.912093, + 0.830793,-0.244757,-0.499878,1.918641,-2.083654,-1.001275, + 0.159615,0.129847,-0.978602,1.941767,-1.759457,-0.997454, + -0.274087,0.000043,0.961705,2.021591,-1.755289,-0.912093, + 0.830793,-0.244757,-0.499878,1.918641,-2.083654,-1.001275, + -0.274087,0.000043,0.961705,2.021591,-1.755289,-0.912093, + 0.957938,-0.285979,-0.023877,2.013095,-2.051912,-0.911043, + 0.846555,-0.103661,-0.52211,1.90637,-2.282284,-0.964887, + 0.996811,-0.048518,0.063355,1.98533,-2.221319,-0.893145, + 0.985192,-0.12583,0.116459,1.930747,-2.463535,-0.894743, + 0.846555,-0.103661,-0.52211,1.90637,-2.282284,-0.964887, + 0.985192,-0.12583,0.116459,1.930747,-2.463535,-0.894743, + 0.843062,-0.10517,-0.527433,1.864064,-2.469953,-0.935601, + 0.846555,-0.103661,-0.52211,1.90637,-2.282284,-0.964887, + 0.830793,-0.244757,-0.499878,1.918641,-2.083654,-1.001275, + 0.957938,-0.285979,-0.023877,2.013095,-2.051912,-0.911043, + 0.846555,-0.103661,-0.52211,1.90637,-2.282284,-0.964887, + 0.957938,-0.285979,-0.023877,2.013095,-2.051912,-0.911043, + 0.996811,-0.048518,0.063355,1.98533,-2.221319,-0.893145, + -0.069043,-0.157333,-0.985129,1.771416,-2.769024,-0.9461, + -0.051713,-0.100832,-0.993559,1.737623,-2.485017,-0.918334, + 0.407719,-0.190267,-0.893064,1.801127,-2.48469,-0.938593, + -0.069043,-0.157333,-0.985129,1.771416,-2.769024,-0.9461, + 0.407719,-0.190267,-0.893064,1.801127,-2.48469,-0.938593, + -0.845931,-0.255219,0.468256,1.830669,-2.736121,-0.903313, + 0.407719,-0.190267,-0.893064,1.801127,-2.48469,-0.938593, + 0.843062,-0.10517,-0.527433,1.864064,-2.469953,-0.935601, + 0.820312,-0.193024,-0.538358,1.880971,-2.733242,-0.8902, + 0.407719,-0.190267,-0.893064,1.801127,-2.48469,-0.938593, + 0.820312,-0.193024,-0.538358,1.880971,-2.733242,-0.8902, + -0.845931,-0.255219,0.468256,1.830669,-2.736121,-0.903313, + -0.09542,0.162222,-0.98213,1.717145,-1.80953,-1.004092, + -0.211092,-0.082708,-0.973961,1.650318,-1.645881,-1.053347, + 0.051664,-0.122235,-0.991156,1.804927,-1.581954,-1.089198, + -0.09542,0.162222,-0.98213,1.717145,-1.80953,-1.004092, + 0.051664,-0.122235,-0.991156,1.804927,-1.581954,-1.089198, + 0.473622,-0.284001,-0.833682,1.818846,-1.756976,-1.023593, + 0.109483,-0.310605,-0.944213,1.720031,-2.105568,-0.971354, + -0.09542,0.162222,-0.98213,1.717145,-1.80953,-1.004092, + 0.473622,-0.284001,-0.833682,1.818846,-1.756976,-1.023593, + 0.109483,-0.310605,-0.944213,1.720031,-2.105568,-0.971354, + 0.473622,-0.284001,-0.833682,1.818846,-1.756976,-1.023593, + 0.459595,-0.144347,-0.87632,1.839224,-2.109267,-0.998351, + 0.039,-0.185675,-0.981837,1.710406,-2.272223,-0.954296, + 0.109483,-0.310605,-0.944213,1.720031,-2.105568,-0.971354, + 0.459595,-0.144347,-0.87632,1.839224,-2.109267,-0.998351, + 0.039,-0.185675,-0.981837,1.710406,-2.272223,-0.954296, + 0.459595,-0.144347,-0.87632,1.839224,-2.109267,-0.998351, + 0.431429,-0.109339,-0.895497,1.818266,-2.313852,-0.968652, + -0.051713,-0.100832,-0.993559,1.737623,-2.485017,-0.918334, + 0.039,-0.185675,-0.981837,1.710406,-2.272223,-0.954296, + 0.431429,-0.109339,-0.895497,1.818266,-2.313852,-0.968652, + -0.051713,-0.100832,-0.993559,1.737623,-2.485017,-0.918334, + 0.431429,-0.109339,-0.895497,1.818266,-2.313852,-0.968652, + 0.407719,-0.190267,-0.893064,1.801127,-2.48469,-0.938593, + 0.473622,-0.284001,-0.833682,1.818846,-1.756976,-1.023593, + 0.051664,-0.122235,-0.991156,1.804927,-1.581954,-1.089198, + 0.290478,-0.146424,-0.945612,1.937009,-1.625419,-1.026843, + 0.473622,-0.284001,-0.833682,1.818846,-1.756976,-1.023593, + 0.290478,-0.146424,-0.945612,1.937009,-1.625419,-1.026843, + 0.159615,0.129847,-0.978602,1.941767,-1.759457,-0.997454, + 0.459595,-0.144347,-0.87632,1.839224,-2.109267,-0.998351, + 0.473622,-0.284001,-0.833682,1.818846,-1.756976,-1.023593, + 0.159615,0.129847,-0.978602,1.941767,-1.759457,-0.997454, + 0.459595,-0.144347,-0.87632,1.839224,-2.109267,-0.998351, + 0.159615,0.129847,-0.978602,1.941767,-1.759457,-0.997454, + 0.830793,-0.244757,-0.499878,1.918641,-2.083654,-1.001275, + 0.431429,-0.109339,-0.895497,1.818266,-2.313852,-0.968652, + 0.459595,-0.144347,-0.87632,1.839224,-2.109267,-0.998351, + 0.830793,-0.244757,-0.499878,1.918641,-2.083654,-1.001275, + 0.431429,-0.109339,-0.895497,1.818266,-2.313852,-0.968652, + 0.830793,-0.244757,-0.499878,1.918641,-2.083654,-1.001275, + 0.846555,-0.103661,-0.52211,1.90637,-2.282284,-0.964887, + 0.407719,-0.190267,-0.893064,1.801127,-2.48469,-0.938593, + 0.431429,-0.109339,-0.895497,1.818266,-2.313852,-0.968652, + 0.846555,-0.103661,-0.52211,1.90637,-2.282284,-0.964887, + 0.407719,-0.190267,-0.893064,1.801127,-2.48469,-0.938593, + 0.846555,-0.103661,-0.52211,1.90637,-2.282284,-0.964887, + 0.843062,-0.10517,-0.527433,1.864064,-2.469953,-0.935601, + 0.975634,-0.187232,0.114377,1.841282,-2.716008,-0.708009, + -0.887036,-0.210048,0.411154,1.756349,-2.446399,-0.705428, + -0.912869,-0.285577,-0.291747,1.663494,-2.485963,-0.790773, + 0.975634,-0.187232,0.114377,1.841282,-2.716008,-0.708009, + -0.912869,-0.285577,-0.291747,1.663494,-2.485963,-0.790773, + 0.056398,-0.684481,0.726846,1.736425,-2.743683,-0.736866, + -0.382074,-0.25681,0.887732,1.740323,-1.67983,-0.664098, + -0.217942,-0.897186,0.384134,1.721211,-1.590185,-0.601932, + -0.493424,-0.165611,0.853877,1.599889,-1.595526,-0.623185, + -0.382074,-0.25681,0.887732,1.740323,-1.67983,-0.664098, + -0.493424,-0.165611,0.853877,1.599889,-1.595526,-0.623185, + 0.193853,0.161608,-0.967628,1.596751,-1.722028,-0.684655, + -0.53197,-0.108751,0.839751,1.747671,-2.067518,-0.638841, + -0.382074,-0.25681,0.887732,1.740323,-1.67983,-0.664098, + 0.193853,0.161608,-0.967628,1.596751,-1.722028,-0.684655, + -0.53197,-0.108751,0.839751,1.747671,-2.067518,-0.638841, + 0.193853,0.161608,-0.967628,1.596751,-1.722028,-0.684655, + -0.819257,-0.566976,-0.085772,1.643403,-2.076583,-0.689565, + -0.570406,-0.192005,0.798606,1.772999,-2.230292,-0.64494, + -0.53197,-0.108751,0.839751,1.747671,-2.067518,-0.638841, + -0.819257,-0.566976,-0.085772,1.643403,-2.076583,-0.689565, + -0.570406,-0.192005,0.798606,1.772999,-2.230292,-0.64494, + -0.819257,-0.566976,-0.085772,1.643403,-2.076583,-0.689565, + -0.898389,-0.217201,0.381735,1.677597,-2.237953,-0.696318, + -0.912869,-0.285577,-0.291747,1.663494,-2.485963,-0.790773, + -0.483189,-0.207332,-0.850613,1.655948,-2.520927,-0.844269, + 0.21689,-0.976039,0.017487,1.700797,-2.794792,-0.82425, + -0.912869,-0.285577,-0.291747,1.663494,-2.485963,-0.790773, + 0.21689,-0.976039,0.017487,1.700797,-2.794792,-0.82425, + 0.056398,-0.684481,0.726846,1.736425,-2.743683,-0.736866, + -0.671694,-0.023528,-0.740455,2.057496,-2.887282,-0.844225, + -0.247433,-0.24804,-0.936618,1.994078,-2.713047,-0.824553, + -0.062994,-0.00854,0.997977,1.972647,-2.728848,-0.772496, + -0.671694,-0.023528,-0.740455,2.057496,-2.887282,-0.844225, + -0.062994,-0.00854,0.997977,1.972647,-2.728848,-0.772496, + -0.990285,-0.10079,0.095796,2.001343,-2.847715,-0.762517, + 0.601229,-0.111152,0.791308,1.828658,-2.477348,-0.67347, + 0.751149,0.43192,0.49922,1.884318,-2.724404,-0.701999, + -0.062994,-0.00854,0.997977,1.972647,-2.728848,-0.772496, + 0.601229,-0.111152,0.791308,1.828658,-2.477348,-0.67347, + -0.062994,-0.00854,0.997977,1.972647,-2.728848,-0.772496, + -0.943599,-0.160394,0.289646,1.947264,-2.443232,-0.732587, + -0.570406,-0.192005,0.798606,1.772999,-2.230292,-0.64494, + 0.601229,-0.111152,0.791308,1.828658,-2.477348,-0.67347, + -0.943599,-0.160394,0.289646,1.947264,-2.443232,-0.732587, + -0.570406,-0.192005,0.798606,1.772999,-2.230292,-0.64494, + -0.943599,-0.160394,0.289646,1.947264,-2.443232,-0.732587, + -0.363523,-0.150625,0.919327,1.921881,-2.157616,-0.692678, + 0.601229,-0.111152,0.791308,1.828658,-2.477348,-0.67347, + -0.887036,-0.210048,0.411154,1.756349,-2.446399,-0.705428, + 0.975634,-0.187232,0.114377,1.841282,-2.716008,-0.708009, + 0.601229,-0.111152,0.791308,1.828658,-2.477348,-0.67347, + 0.975634,-0.187232,0.114377,1.841282,-2.716008,-0.708009, + 0.751149,0.43192,0.49922,1.884318,-2.724404,-0.701999, + 0.601229,-0.111152,0.791308,1.828658,-2.477348,-0.67347, + -0.570406,-0.192005,0.798606,1.772999,-2.230292,-0.64494, + -0.898389,-0.217201,0.381735,1.677597,-2.237953,-0.696318, + 0.601229,-0.111152,0.791308,1.828658,-2.477348,-0.67347, + -0.898389,-0.217201,0.381735,1.677597,-2.237953,-0.696318, + -0.887036,-0.210048,0.411154,1.756349,-2.446399,-0.705428, + -0.587844,-0.244917,-0.771009,1.953911,-2.462233,-0.830594, + -0.943599,-0.160394,0.289646,1.947264,-2.443232,-0.732587, + -0.062994,-0.00854,0.997977,1.972647,-2.728848,-0.772496, + -0.587844,-0.244917,-0.771009,1.953911,-2.462233,-0.830594, + -0.062994,-0.00854,0.997977,1.972647,-2.728848,-0.772496, + -0.247433,-0.24804,-0.936618,1.994078,-2.713047,-0.824553, + -0.924461,-0.213386,0.315973,1.991892,-1.7484,-0.65277, + -0.084936,-0.226589,0.97028,1.963153,-1.588839,-0.612861, + -0.217942,-0.897186,0.384134,1.721211,-1.590185,-0.601932, + -0.924461,-0.213386,0.315973,1.991892,-1.7484,-0.65277, + -0.217942,-0.897186,0.384134,1.721211,-1.590185,-0.601932, + -0.382074,-0.25681,0.887732,1.740323,-1.67983,-0.664098, + -0.914496,-0.253608,0.315247,1.945206,-2.015769,-0.672724, + -0.924461,-0.213386,0.315973,1.991892,-1.7484,-0.65277, + -0.382074,-0.25681,0.887732,1.740323,-1.67983,-0.664098, + -0.914496,-0.253608,0.315247,1.945206,-2.015769,-0.672724, + -0.382074,-0.25681,0.887732,1.740323,-1.67983,-0.664098, + -0.53197,-0.108751,0.839751,1.747671,-2.067518,-0.638841, + 0.972392,0.232654,-0.018037,2.053108,-1.738285,-0.824853, + 0.999491,-0.02584,-0.01873,2.059844,-1.561331,-0.858957, + -0.084936,-0.226589,0.97028,1.963153,-1.588839,-0.612861, + 0.972392,0.232654,-0.018037,2.053108,-1.738285,-0.824853, + -0.084936,-0.226589,0.97028,1.963153,-1.588839,-0.612861, + -0.924461,-0.213386,0.315973,1.991892,-1.7484,-0.65277, + -0.732521,-0.474279,-0.488336,2.047696,-2.050138,-0.814712, + 0.972392,0.232654,-0.018037,2.053108,-1.738285,-0.824853, + -0.924461,-0.213386,0.315973,1.991892,-1.7484,-0.65277, + -0.732521,-0.474279,-0.488336,2.047696,-2.050138,-0.814712, + -0.924461,-0.213386,0.315973,1.991892,-1.7484,-0.65277, + -0.914496,-0.253608,0.315247,1.945206,-2.015769,-0.672724, + -0.845196,-0.27877,-0.455994,2.02453,-2.195334,-0.811284, + -0.732521,-0.474279,-0.488336,2.047696,-2.050138,-0.814712, + -0.914496,-0.253608,0.315247,1.945206,-2.015769,-0.672724, + -0.845196,-0.27877,-0.455994,2.02453,-2.195334,-0.811284, + -0.914496,-0.253608,0.315247,1.945206,-2.015769,-0.672724, + -0.363523,-0.150625,0.919327,1.921881,-2.157616,-0.692678, + -0.587844,-0.244917,-0.771009,1.953911,-2.462233,-0.830594, + -0.845196,-0.27877,-0.455994,2.02453,-2.195334,-0.811284, + -0.363523,-0.150625,0.919327,1.921881,-2.157616,-0.692678, + -0.587844,-0.244917,-0.771009,1.953911,-2.462233,-0.830594, + -0.363523,-0.150625,0.919327,1.921881,-2.157616,-0.692678, + -0.943599,-0.160394,0.289646,1.947264,-2.443232,-0.732587, + -0.239734,-0.173966,-0.955125,2.111557,-1.376942,-0.89657, + -0.157802,-0.148625,-0.976222,2.141273,-1.234642,-0.941254, + 0.608407,-0.244593,-0.754993,2.158051,-1.209613,-0.783941, + -0.239734,-0.173966,-0.955125,2.111557,-1.376942,-0.89657, + 0.608407,-0.244593,-0.754993,2.158051,-1.209613,-0.783941, + 0.727678,-0.414895,-0.546211,2.126237,-1.330172,-0.721011, + -0.498756,-0.2241,-0.83727,2.071448,-1.410118,-1.006192, + -0.329905,-0.225598,-0.916661,2.099566,-1.259996,-1.055763, + -0.157802,-0.148625,-0.976222,2.141273,-1.234642,-0.941254, + -0.498756,-0.2241,-0.83727,2.071448,-1.410118,-1.006192, + -0.157802,-0.148625,-0.976222,2.141273,-1.234642,-0.941254, + -0.239734,-0.173966,-0.955125,2.111557,-1.376942,-0.89657, + -0.759627,-0.28527,-0.584455,1.974215,-1.469208,-1.068951, + -0.661097,-0.258238,-0.70446,1.966698,-1.22816,-1.153716, + -0.329905,-0.225598,-0.916661,2.099566,-1.259996,-1.055763, + -0.759627,-0.28527,-0.584455,1.974215,-1.469208,-1.068951, + -0.329905,-0.225598,-0.916661,2.099566,-1.259996,-1.055763, + -0.498756,-0.2241,-0.83727,2.071448,-1.410118,-1.006192, + -0.672688,-0.442616,-0.592944,1.801794,-1.465464,-1.129277, + -0.632119,-0.359381,-0.686491,1.805207,-1.268427,-1.165317, + -0.661097,-0.258238,-0.70446,1.966698,-1.22816,-1.153716, + -0.672688,-0.442616,-0.592944,1.801794,-1.465464,-1.129277, + -0.661097,-0.258238,-0.70446,1.966698,-1.22816,-1.153716, + -0.759627,-0.28527,-0.584455,1.974215,-1.469208,-1.068951, + 0.954473,-0.270031,-0.126745,1.612396,-1.485728,-1.099731, + 0.942118,-0.292663,-0.163592,1.601721,-1.262359,-1.14142, + -0.632119,-0.359381,-0.686491,1.805207,-1.268427,-1.165317, + 0.954473,-0.270031,-0.126745,1.612396,-1.485728,-1.099731, + -0.632119,-0.359381,-0.686491,1.805207,-1.268427,-1.165317, + -0.672688,-0.442616,-0.592944,1.801794,-1.465464,-1.129277, + 0.80128,-0.303744,-0.515451,1.5167,-1.45305,-1.068516, + 0.772916,-0.305378,-0.556189,1.49748,-1.283201,-1.088258, + 0.942118,-0.292663,-0.163592,1.601721,-1.262359,-1.14142, + 0.80128,-0.303744,-0.515451,1.5167,-1.45305,-1.068516, + 0.942118,-0.292663,-0.163592,1.601721,-1.262359,-1.14142, + 0.954473,-0.270031,-0.126745,1.612396,-1.485728,-1.099731, + 0.441315,-0.29978,-0.845797,1.454817,-1.430228,-0.976569, + 0.38578,-0.259547,-0.88533,1.430817,-1.301205,-1.024924, + 0.772916,-0.305378,-0.556189,1.49748,-1.283201,-1.088258, + 0.441315,-0.29978,-0.845797,1.454817,-1.430228,-0.976569, + 0.772916,-0.305378,-0.556189,1.49748,-1.283201,-1.088258, + 0.80128,-0.303744,-0.515451,1.5167,-1.45305,-1.068516, + 0.080262,-0.270606,-0.959339,1.328862,-1.352627,-0.758733, + 0.02992,-0.202031,-0.978922,1.348219,-1.282064,-0.845204, + 0.38578,-0.259547,-0.88533,1.430817,-1.301205,-1.024924, + 0.080262,-0.270606,-0.959339,1.328862,-1.352627,-0.758733, + 0.38578,-0.259547,-0.88533,1.430817,-1.301205,-1.024924, + 0.441315,-0.29978,-0.845797,1.454817,-1.430228,-0.976569, + -0.157802,-0.148625,-0.976222,2.141273,-1.234642,-0.941254, + -0.019419,-0.11596,-0.993064,2.17745,-1.127765,-0.974416, + 0.70745,-0.193334,-0.679806,2.180012,-1.130557,-0.821812, + -0.157802,-0.148625,-0.976222,2.141273,-1.234642,-0.941254, + 0.70745,-0.193334,-0.679806,2.180012,-1.130557,-0.821812, + 0.608407,-0.244593,-0.754993,2.158051,-1.209613,-0.783941, + -0.329905,-0.225598,-0.916661,2.099566,-1.259996,-1.055763, + -0.182029,-0.190207,-0.964721,2.148553,-1.103067,-1.06541, + -0.019419,-0.11596,-0.993064,2.17745,-1.127765,-0.974416, + -0.329905,-0.225598,-0.916661,2.099566,-1.259996,-1.055763, + -0.019419,-0.11596,-0.993064,2.17745,-1.127765,-0.974416, + -0.157802,-0.148625,-0.976222,2.141273,-1.234642,-0.941254, + -0.661097,-0.258238,-0.70446,1.966698,-1.22816,-1.153716, + -0.571338,-0.120921,-0.811758,2.024692,-1.074646,-1.172465, + -0.182029,-0.190207,-0.964721,2.148553,-1.103067,-1.06541, + -0.661097,-0.258238,-0.70446,1.966698,-1.22816,-1.153716, + -0.182029,-0.190207,-0.964721,2.148553,-1.103067,-1.06541, + -0.329905,-0.225598,-0.916661,2.099566,-1.259996,-1.055763, + -0.632119,-0.359381,-0.686491,1.805207,-1.268427,-1.165317, + -0.587909,-0.233166,-0.774594,1.838895,-1.087204,-1.201408, + -0.571338,-0.120921,-0.811758,2.024692,-1.074646,-1.172465, + -0.632119,-0.359381,-0.686491,1.805207,-1.268427,-1.165317, + -0.571338,-0.120921,-0.811758,2.024692,-1.074646,-1.172465, + -0.661097,-0.258238,-0.70446,1.966698,-1.22816,-1.153716, + 0.942118,-0.292663,-0.163592,1.601721,-1.262359,-1.14142, + 0.924702,-0.311562,-0.218757,1.645819,-1.087442,-1.173773, + -0.587909,-0.233166,-0.774594,1.838895,-1.087204,-1.201408, + 0.942118,-0.292663,-0.163592,1.601721,-1.262359,-1.14142, + -0.587909,-0.233166,-0.774594,1.838895,-1.087204,-1.201408, + -0.632119,-0.359381,-0.686491,1.805207,-1.268427,-1.165317, + 0.772916,-0.305378,-0.556189,1.49748,-1.283201,-1.088258, + 0.73827,-0.277136,-0.614942,1.524407,-1.125312,-1.142248, + 0.924702,-0.311562,-0.218757,1.645819,-1.087442,-1.173773, + 0.772916,-0.305378,-0.556189,1.49748,-1.283201,-1.088258, + 0.924702,-0.311562,-0.218757,1.645819,-1.087442,-1.173773, + 0.942118,-0.292663,-0.163592,1.601721,-1.262359,-1.14142, + 0.38578,-0.259547,-0.88533,1.430817,-1.301205,-1.024924, + 0.366416,-0.175098,-0.913827,1.438439,-1.148029,-1.098069, + 0.73827,-0.277136,-0.614942,1.524407,-1.125312,-1.142248, + 0.38578,-0.259547,-0.88533,1.430817,-1.301205,-1.024924, + 0.73827,-0.277136,-0.614942,1.524407,-1.125312,-1.142248, + 0.772916,-0.305378,-0.556189,1.49748,-1.283201,-1.088258, + 0.02992,-0.202031,-0.978922,1.348219,-1.282064,-0.845204, + 0.023392,-0.110333,-0.993619,1.310865,-1.136322,-0.914838, + 0.366416,-0.175098,-0.913827,1.438439,-1.148029,-1.098069, + 0.02992,-0.202031,-0.978922,1.348219,-1.282064,-0.845204, + 0.366416,-0.175098,-0.913827,1.438439,-1.148029,-1.098069, + 0.38578,-0.259547,-0.88533,1.430817,-1.301205,-1.024924, + 0.999491,-0.02584,-0.01873,2.059844,-1.561331,-0.858957, + 0.437631,-0.408484,-0.801012,2.0796,-1.473377,-0.654997, + 0.552828,-0.750794,-0.36151,2.0482,-1.581983,-0.555832, + 0.999491,-0.02584,-0.01873,2.059844,-1.561331,-0.858957, + 0.552828,-0.750794,-0.36151,2.0482,-1.581983,-0.555832, + -0.084936,-0.226589,0.97028,1.963153,-1.588839,-0.612861, + 0.051664,-0.122235,-0.991156,1.804927,-1.581954,-1.089198, + -0.211092,-0.082708,-0.973961,1.650318,-1.645881,-1.053347, + 0.954473,-0.270031,-0.126745,1.612396,-1.485728,-1.099731, + 0.051664,-0.122235,-0.991156,1.804927,-1.581954,-1.089198, + 0.954473,-0.270031,-0.126745,1.612396,-1.485728,-1.099731, + -0.672688,-0.442616,-0.592944,1.801794,-1.465464,-1.129277, + 0.290478,-0.146424,-0.945612,1.937009,-1.625419,-1.026843, + 0.051664,-0.122235,-0.991156,1.804927,-1.581954,-1.089198, + -0.672688,-0.442616,-0.592944,1.801794,-1.465464,-1.129277, + 0.290478,-0.146424,-0.945612,1.937009,-1.625419,-1.026843, + -0.672688,-0.442616,-0.592944,1.801794,-1.465464,-1.129277, + -0.759627,-0.28527,-0.584455,1.974215,-1.469208,-1.068951, + 0.74023,-0.090866,-0.666185,2.036036,-1.57908,-0.967151, + 0.290478,-0.146424,-0.945612,1.937009,-1.625419,-1.026843, + -0.759627,-0.28527,-0.584455,1.974215,-1.469208,-1.068951, + 0.74023,-0.090866,-0.666185,2.036036,-1.57908,-0.967151, + -0.759627,-0.28527,-0.584455,1.974215,-1.469208,-1.068951, + -0.498756,-0.2241,-0.83727,2.071448,-1.410118,-1.006192, + 0.999491,-0.02584,-0.01873,2.059844,-1.561331,-0.858957, + 0.74023,-0.090866,-0.666185,2.036036,-1.57908,-0.967151, + -0.498756,-0.2241,-0.83727,2.071448,-1.410118,-1.006192, + 0.999491,-0.02584,-0.01873,2.059844,-1.561331,-0.858957, + -0.498756,-0.2241,-0.83727,2.071448,-1.410118,-1.006192, + -0.239734,-0.173966,-0.955125,2.111557,-1.376942,-0.89657, + 0.999491,-0.02584,-0.01873,2.059844,-1.561331,-0.858957, + -0.239734,-0.173966,-0.955125,2.111557,-1.376942,-0.89657, + 0.727678,-0.414895,-0.546211,2.126237,-1.330172,-0.721011, + 0.999491,-0.02584,-0.01873,2.059844,-1.561331,-0.858957, + 0.727678,-0.414895,-0.546211,2.126237,-1.330172,-0.721011, + 0.437631,-0.408484,-0.801012,2.0796,-1.473377,-0.654997, + 0.70745,-0.193334,-0.679806,2.180012,-1.130557,-0.821812, + -0.019419,-0.11596,-0.993064,2.17745,-1.127765,-0.974416, + -0.742985,0.015712,-0.669123,2.222082,-0.957342,-1.014137, + 0.70745,-0.193334,-0.679806,2.180012,-1.130557,-0.821812, + -0.742985,0.015712,-0.669123,2.222082,-0.957342,-1.014137, + -0.012663,0.029084,-0.999497,2.229345,-0.992723,-0.862826, + -0.587909,-0.233166,-0.774594,1.838895,-1.087204,-1.201408, + 0.924702,-0.311562,-0.218757,1.645819,-1.087442,-1.173773, + 0.859237,-0.17312,-0.481395,1.635139,-0.965221,-1.184968, + -0.587909,-0.233166,-0.774594,1.838895,-1.087204,-1.201408, + 0.859237,-0.17312,-0.481395,1.635139,-0.965221,-1.184968, + -0.942755,-0.29871,0.148273,1.867657,-0.920633,-1.206933, + -0.571338,-0.120921,-0.811758,2.024692,-1.074646,-1.172465, + -0.587909,-0.233166,-0.774594,1.838895,-1.087204,-1.201408, + -0.942755,-0.29871,0.148273,1.867657,-0.920633,-1.206933, + -0.571338,-0.120921,-0.811758,2.024692,-1.074646,-1.172465, + -0.942755,-0.29871,0.148273,1.867657,-0.920633,-1.206933, + -0.965506,-0.176768,0.191185,2.058189,-0.931238,-1.163518, + -0.182029,-0.190207,-0.964721,2.148553,-1.103067,-1.06541, + -0.571338,-0.120921,-0.811758,2.024692,-1.074646,-1.172465, + -0.965506,-0.176768,0.191185,2.058189,-0.931238,-1.163518, + -0.182029,-0.190207,-0.964721,2.148553,-1.103067,-1.06541, + -0.965506,-0.176768,0.191185,2.058189,-0.931238,-1.163518, + -0.809154,0.004832,-0.587577,2.158585,-0.955809,-1.113647, + -0.019419,-0.11596,-0.993064,2.17745,-1.127765,-0.974416, + -0.182029,-0.190207,-0.964721,2.148553,-1.103067,-1.06541, + -0.809154,0.004832,-0.587577,2.158585,-0.955809,-1.113647, + -0.019419,-0.11596,-0.993064,2.17745,-1.127765,-0.974416, + -0.809154,0.004832,-0.587577,2.158585,-0.955809,-1.113647, + -0.742985,0.015712,-0.669123,2.222082,-0.957342,-1.014137, + 0.080262,-0.270606,-0.959339,1.328862,-1.352627,-0.758733, + 0.441315,-0.29978,-0.845797,1.454817,-1.430228,-0.976569, + -0.970971,-0.219011,-0.096178,1.480629,-1.640132,-0.953447, + 0.080262,-0.270606,-0.959339,1.328862,-1.352627,-0.758733, + -0.970971,-0.219011,-0.096178,1.480629,-1.640132,-0.953447, + -0.794709,-0.185222,0.578041,1.451825,-1.576856,-0.702758, + 0.045651,-0.004499,-0.998947,1.337875,-0.945716,-1.021299, + 0.419396,-0.035927,-0.907092,1.428883,-0.98669,-1.133905, + 0.366416,-0.175098,-0.913827,1.438439,-1.148029,-1.098069, + 0.045651,-0.004499,-0.998947,1.337875,-0.945716,-1.021299, + 0.366416,-0.175098,-0.913827,1.438439,-1.148029,-1.098069, + 0.023392,-0.110333,-0.993619,1.310865,-1.136322,-0.914838, + 0.80128,-0.303744,-0.515451,1.5167,-1.45305,-1.068516, + 0.954473,-0.270031,-0.126745,1.612396,-1.485728,-1.099731, + -0.211092,-0.082708,-0.973961,1.650318,-1.645881,-1.053347, + 0.80128,-0.303744,-0.515451,1.5167,-1.45305,-1.068516, + -0.211092,-0.082708,-0.973961,1.650318,-1.645881,-1.053347, + -0.652584,-0.147678,-0.743186,1.54175,-1.643613,-1.01419, + 0.441315,-0.29978,-0.845797,1.454817,-1.430228,-0.976569, + 0.80128,-0.303744,-0.515451,1.5167,-1.45305,-1.068516, + -0.652584,-0.147678,-0.743186,1.54175,-1.643613,-1.01419, + 0.441315,-0.29978,-0.845797,1.454817,-1.430228,-0.976569, + -0.652584,-0.147678,-0.743186,1.54175,-1.643613,-1.01419, + -0.970971,-0.219011,-0.096178,1.480629,-1.640132,-0.953447, + 0.714393,-0.109998,-0.691045,1.536037,-0.985876,-1.185597, + 0.859237,-0.17312,-0.481395,1.635139,-0.965221,-1.184968, + 0.924702,-0.311562,-0.218757,1.645819,-1.087442,-1.173773, + 0.714393,-0.109998,-0.691045,1.536037,-0.985876,-1.185597, + 0.924702,-0.311562,-0.218757,1.645819,-1.087442,-1.173773, + 0.73827,-0.277136,-0.614942,1.524407,-1.125312,-1.142248, + 0.419396,-0.035927,-0.907092,1.428883,-0.98669,-1.133905, + 0.714393,-0.109998,-0.691045,1.536037,-0.985876,-1.185597, + 0.73827,-0.277136,-0.614942,1.524407,-1.125312,-1.142248, + 0.419396,-0.035927,-0.907092,1.428883,-0.98669,-1.133905, + 0.73827,-0.277136,-0.614942,1.524407,-1.125312,-1.142248, + 0.366416,-0.175098,-0.913827,1.438439,-1.148029,-1.098069, + 0.261393,-0.399072,-0.878872,3.233975,2.059193,-0.072431, + 0.441787,-0.375177,-0.814903,3.009101,1.971604,-0.03422, + 0.889638,-0.392482,0.233458,2.985371,1.982663,0, + 0.261393,-0.399072,-0.878872,3.233975,2.059193,-0.072431, + 0.889638,-0.392482,0.233458,2.985371,1.982663,0, + -0.861251,0.383698,-0.333202,3.247406,2.073333,0, + 0.428291,-0.499911,-0.752765,3.252224,2.026347,-0.148215, + 0.483908,-0.405185,-0.775667,3.036361,1.913989,-0.169838, + 0.441787,-0.375177,-0.814903,3.009101,1.971604,-0.03422, + 0.428291,-0.499911,-0.752765,3.252224,2.026347,-0.148215, + 0.441787,-0.375177,-0.814903,3.009101,1.971604,-0.03422, + 0.261393,-0.399072,-0.878872,3.233975,2.059193,-0.072431, + 0.454048,-0.464454,-0.760344,3.276333,1.863773,-0.294266, + 0.482381,-0.398126,-0.780259,3.058366,1.773346,-0.297337, + 0.483908,-0.405185,-0.775667,3.036361,1.913989,-0.169838, + 0.454048,-0.464454,-0.760344,3.276333,1.863773,-0.294266, + 0.483908,-0.405185,-0.775667,3.036361,1.913989,-0.169838, + 0.428291,-0.499911,-0.752765,3.252224,2.026347,-0.148215, + 0.673211,-0.58089,-0.457551,3.337545,1.748927,-0.34021, + 0.702554,-0.570096,-0.42592,3.086666,1.632991,-0.338863, + 0.482381,-0.398126,-0.780259,3.058366,1.773346,-0.297337, + 0.673211,-0.58089,-0.457551,3.337545,1.748927,-0.34021, + 0.482381,-0.398126,-0.780259,3.058366,1.773346,-0.297337, + 0.454048,-0.464454,-0.760344,3.276333,1.863773,-0.294266, + -0.384424,0.863444,-0.326623,3.377233,1.5878,-0.400781, + -0.317114,0.866865,-0.384686,3.115383,1.49239,-0.380228, + 0.702554,-0.570096,-0.42592,3.086666,1.632991,-0.338863, + -0.384424,0.863444,-0.326623,3.377233,1.5878,-0.400781, + 0.702554,-0.570096,-0.42592,3.086666,1.632991,-0.338863, + 0.673211,-0.58089,-0.457551,3.337545,1.748927,-0.34021, + -0.354832,0.724971,-0.590348,3.47341,1.366149,-0.454658, + -0.273708,0.760234,-0.589175,3.163181,1.209972,-0.462438, + -0.317114,0.866865,-0.384686,3.115383,1.49239,-0.380228, + -0.354832,0.724971,-0.590348,3.47341,1.366149,-0.454658, + -0.317114,0.866865,-0.384686,3.115383,1.49239,-0.380228, + -0.384424,0.863444,-0.326623,3.377233,1.5878,-0.400781, + -0.270788,0.46353,-0.84369,3.528445,1.060127,-0.489443, + -0.158888,0.47696,-0.864444,3.189664,0.907503,-0.500122, + -0.273708,0.760234,-0.589175,3.163181,1.209972,-0.462438, + -0.270788,0.46353,-0.84369,3.528445,1.060127,-0.489443, + -0.273708,0.760234,-0.589175,3.163181,1.209972,-0.462438, + -0.354832,0.724971,-0.590348,3.47341,1.366149,-0.454658, + -0.203969,0.261593,-0.94338,3.559394,0.706516,-0.452535, + -0.095989,0.297871,-0.949768,3.280681,0.510802,-0.499434, + -0.158888,0.47696,-0.864444,3.189664,0.907503,-0.500122, + -0.203969,0.261593,-0.94338,3.559394,0.706516,-0.452535, + -0.158888,0.47696,-0.864444,3.189664,0.907503,-0.500122, + -0.270788,0.46353,-0.84369,3.528445,1.060127,-0.489443, + -0.175197,0.22468,-0.958553,3.61965,0.472046,-0.391742, + -0.078774,0.27578,-0.957987,3.321825,0.26669,-0.46575, + -0.095989,0.297871,-0.949768,3.280681,0.510802,-0.499434, + -0.175197,0.22468,-0.958553,3.61965,0.472046,-0.391742, + -0.095989,0.297871,-0.949768,3.280681,0.510802,-0.499434, + -0.203969,0.261593,-0.94338,3.559394,0.706516,-0.452535, + -0.128537,0.152973,-0.979835,3.641195,0.407454,-0.362198, + -0.027323,0.180938,-0.983115,3.36004,0.165487,-0.412685, + -0.078774,0.27578,-0.957987,3.321825,0.26669,-0.46575, + -0.128537,0.152973,-0.979835,3.641195,0.407454,-0.362198, + -0.078774,0.27578,-0.957987,3.321825,0.26669,-0.46575, + -0.175197,0.22468,-0.958553,3.61965,0.472046,-0.391742, + -0.023695,0.006701,-0.999697,3.67471,0.338839,-0.30784, + 0.065337,0.07376,-0.995133,3.378799,0.073736,-0.355362, + -0.027323,0.180938,-0.983115,3.36004,0.165487,-0.412685, + -0.023695,0.006701,-0.999697,3.67471,0.338839,-0.30784, + -0.027323,0.180938,-0.983115,3.36004,0.165487,-0.412685, + -0.128537,0.152973,-0.979835,3.641195,0.407454,-0.362198, + 0.144017,-0.141696,-0.979378,3.700363,0.265794,-0.240762, + 0.226651,-0.023678,-0.973688,3.43895,-0.08258,-0.257015, + 0.065337,0.07376,-0.995133,3.378799,0.073736,-0.355362, + 0.144017,-0.141696,-0.979378,3.700363,0.265794,-0.240762, + 0.065337,0.07376,-0.995133,3.378799,0.073736,-0.355362, + -0.023695,0.006701,-0.999697,3.67471,0.338839,-0.30784, + 0.325831,-0.277459,-0.903798,3.737014,0.181837,-0.176819, + 0.383941,-0.196382,-0.902232,3.514981,-0.121886,-0.187589, + 0.226651,-0.023678,-0.973688,3.43895,-0.08258,-0.257015, + 0.325831,-0.277459,-0.903798,3.737014,0.181837,-0.176819, + 0.226651,-0.023678,-0.973688,3.43895,-0.08258,-0.257015, + 0.144017,-0.141696,-0.979378,3.700363,0.265794,-0.240762, + -0.910859,-0.100368,-0.400327,3.731689,0.186391,0, + 0.431966,-0.771434,0.46722,3.486028,-0.141683,0, + 0.383941,-0.196382,-0.902232,3.514981,-0.121886,-0.187589, + -0.910859,-0.100368,-0.400327,3.731689,0.186391,0, + 0.383941,-0.196382,-0.902232,3.514981,-0.121886,-0.187589, + 0.325831,-0.277459,-0.903798,3.737014,0.181837,-0.176819, + 0.431966,-0.771434,-0.46722,3.71636,2.343387,0, + -0.451389,0.892327,-0.00019,3.727093,2.308406,-0.150049, + 0.020519,-0.282941,-0.958918,3.4583,2.151656,-0.102662, + 0.431966,-0.771434,-0.46722,3.71636,2.343387,0, + 0.020519,-0.282941,-0.958918,3.4583,2.151656,-0.102662, + 0.694153,-0.467999,0.546926,3.454971,2.169877,0, + -0.086812,-0.050981,-0.994919,4.120842,0.627141,-0.185461, + -0.926486,-0.356041,-0.121897,4.126565,0.642027,0, + 0.338485,-0.103202,-0.935295,3.929251,0.411689,0, + -0.086812,-0.050981,-0.994919,4.120842,0.627141,-0.185461, + 0.338485,-0.103202,-0.935295,3.929251,0.411689,0, + 0.07924,-0.231862,-0.969516,3.955635,0.432417,-0.197586, + -0.086812,-0.050981,-0.994919,4.120842,0.627141,-0.185461, + 0.07924,-0.231862,-0.969516,3.955635,0.432417,-0.197586, + -0.081635,-0.03459,-0.996062,3.889626,0.475277,-0.247365, + -0.172151,0.101796,-0.979797,4.105198,0.672581,-0.300001, + -0.086812,-0.050981,-0.994919,4.120842,0.627141,-0.185461, + -0.081635,-0.03459,-0.996062,3.889626,0.475277,-0.247365, + -0.172151,0.101796,-0.979797,4.105198,0.672581,-0.300001, + -0.081635,-0.03459,-0.996062,3.889626,0.475277,-0.247365, + -0.178707,0.132414,-0.974951,3.861841,0.560638,-0.311961, + -0.195132,0.128745,-0.97229,4.068249,0.798926,-0.400813, + -0.172151,0.101796,-0.979797,4.105198,0.672581,-0.300001, + -0.178707,0.132414,-0.974951,3.861841,0.560638,-0.311961, + -0.195132,0.128745,-0.97229,4.068249,0.798926,-0.400813, + -0.178707,0.132414,-0.974951,3.861841,0.560638,-0.311961, + -0.21777,0.161093,-0.962614,3.849352,0.664451,-0.387198, + -0.434016,0.136262,-0.890541,4.041657,1.039756,-0.496922, + -0.195132,0.128745,-0.97229,4.068249,0.798926,-0.400813, + -0.21777,0.161093,-0.962614,3.849352,0.664451,-0.387198, + -0.434016,0.136262,-0.890541,4.041657,1.039756,-0.496922, + -0.21777,0.161093,-0.962614,3.849352,0.664451,-0.387198, + -0.273816,0.228927,-0.93414,3.823137,0.853054,-0.461519, + -0.601466,0.441167,-0.666041,3.98851,1.297806,-0.539537, + -0.434016,0.136262,-0.890541,4.041657,1.039756,-0.496922, + -0.273816,0.228927,-0.93414,3.823137,0.853054,-0.461519, + -0.601466,0.441167,-0.666041,3.98851,1.297806,-0.539537, + -0.273816,0.228927,-0.93414,3.823137,0.853054,-0.461519, + -0.385487,0.478576,-0.788901,3.747724,1.184933,-0.518662, + -0.571598,0.654164,-0.495323,3.886058,1.550141,-0.50483, + -0.601466,0.441167,-0.666041,3.98851,1.297806,-0.539537, + -0.385487,0.478576,-0.788901,3.747724,1.184933,-0.518662, + -0.571598,0.654164,-0.495323,3.886058,1.550141,-0.50483, + -0.385487,0.478576,-0.788901,3.747724,1.184933,-0.518662, + -0.447812,0.698934,-0.557634,3.650974,1.46374,-0.478617, + -0.564871,0.754993,-0.333026,3.881998,1.764428,-0.476337, + -0.571598,0.654164,-0.495323,3.886058,1.550141,-0.50483, + -0.447812,0.698934,-0.557634,3.650974,1.46374,-0.478617, + -0.564871,0.754993,-0.333026,3.881998,1.764428,-0.476337, + -0.447812,0.698934,-0.557634,3.650974,1.46374,-0.478617, + -0.463441,0.825581,-0.321928,3.590526,1.70109,-0.411994, + -0.512639,0.858604,-0.000762,3.814876,1.968416,-0.443, + -0.564871,0.754993,-0.333026,3.881998,1.764428,-0.476337, + -0.463441,0.825581,-0.321928,3.590526,1.70109,-0.411994, + -0.512639,0.858604,-0.000762,3.814876,1.968416,-0.443, + -0.463441,0.825581,-0.321928,3.590526,1.70109,-0.411994, + 0.492397,-0.77993,-0.386336,3.541188,1.849183,-0.386366, + -0.698288,0.715816,-0.000608,3.758215,2.206683,-0.323051, + -0.512639,0.858604,-0.000762,3.814876,1.968416,-0.443, + 0.492397,-0.77993,-0.386336,3.541188,1.849183,-0.386366, + -0.698288,0.715816,-0.000608,3.758215,2.206683,-0.323051, + 0.492397,-0.77993,-0.386336,3.541188,1.849183,-0.386366, + 0.313443,-0.691245,-0.651102,3.479418,1.97825,-0.317478, + -0.777939,0.62834,-0.000226,3.745669,2.266001,-0.24193, + -0.698288,0.715816,-0.000608,3.758215,2.206683,-0.323051, + 0.313443,-0.691245,-0.651102,3.479418,1.97825,-0.317478, + -0.777939,0.62834,-0.000226,3.745669,2.266001,-0.24193, + 0.313443,-0.691245,-0.651102,3.479418,1.97825,-0.317478, + 0.161194,-0.480657,-0.861966,3.460196,2.103494,-0.180368, + -0.451389,0.892327,-0.00019,3.727093,2.308406,-0.150049, + -0.777939,0.62834,-0.000226,3.745669,2.266001,-0.24193, + 0.161194,-0.480657,-0.861966,3.460196,2.103494,-0.180368, + -0.451389,0.892327,-0.00019,3.727093,2.308406,-0.150049, + 0.161194,-0.480657,-0.861966,3.460196,2.103494,-0.180368, + 0.020519,-0.282941,-0.958918,3.4583,2.151656,-0.102662, + -0.476715,0.879058,0,3.118124,-0.703925,0, + 0.533629,-0.162705,-0.82992,3.107533,-0.691019,-0.264602, + 0.445439,-0.182623,-0.876489,3.342159,-0.384674,-0.201349, + -0.476715,0.879058,0,3.118124,-0.703925,0, + 0.445439,-0.182623,-0.876489,3.342159,-0.384674,-0.201349, + -0.560204,0.828355,-0.00034,3.33521,-0.375755,0, + 0.474213,-0.311965,-0.823286,2.361089,1.76666,-0.202595, + 0.536218,-0.84408,0.000006,2.339597,1.807702,0, + -0.926486,-0.356041,0.121897,2.723503,1.898839,0, + 0.474213,-0.311965,-0.823286,2.361089,1.76666,-0.202595, + -0.926486,-0.356041,0.121897,2.723503,1.898839,0, + 0.45552,-0.330524,-0.826593,2.715712,1.828219,-0.167709, + 0.488174,-0.280956,-0.826287,2.406969,1.645328,-0.341479, + 0.474213,-0.311965,-0.823286,2.361089,1.76666,-0.202595, + 0.45552,-0.330524,-0.826593,2.715712,1.828219,-0.167709, + 0.488174,-0.280956,-0.826287,2.406969,1.645328,-0.341479, + 0.45552,-0.330524,-0.826593,2.715712,1.828219,-0.167709, + 0.489736,-0.346185,-0.800197,2.738132,1.687333,-0.295046, + 0.531574,-0.288506,-0.796362,2.519027,1.485931,-0.422962, + 0.488174,-0.280956,-0.826287,2.406969,1.645328,-0.341479, + 0.489736,-0.346185,-0.800197,2.738132,1.687333,-0.295046, + 0.531574,-0.288506,-0.796362,2.519027,1.485931,-0.422962, + 0.489736,-0.346185,-0.800197,2.738132,1.687333,-0.295046, + 0.5205,-0.336657,-0.784692,2.77568,1.53871,-0.352829, + 0.769657,-0.480833,-0.420033,2.553871,1.284278,-0.512335, + 0.531574,-0.288506,-0.796362,2.519027,1.485931,-0.422962, + 0.5205,-0.336657,-0.784692,2.77568,1.53871,-0.352829, + 0.769657,-0.480833,-0.420033,2.553871,1.284278,-0.512335, + 0.5205,-0.336657,-0.784692,2.77568,1.53871,-0.352829, + 0.760747,-0.509474,-0.40212,2.815366,1.377583,-0.413399, + -0.080985,0.883253,-0.461851,2.637461,1.01726,-0.581611, + 0.769657,-0.480833,-0.420033,2.553871,1.284278,-0.512335, + 0.760747,-0.509474,-0.40212,2.815366,1.377583,-0.413399, + -0.080985,0.883253,-0.461851,2.637461,1.01726,-0.581611, + 0.760747,-0.509474,-0.40212,2.815366,1.377583,-0.413399, + -0.16423,0.819635,-0.548842,2.854291,1.093951,-0.49465, + 0.040193,0.650965,-0.758043,2.747937,0.712253,-0.615674, + -0.080985,0.883253,-0.461851,2.637461,1.01726,-0.581611, + -0.16423,0.819635,-0.548842,2.854291,1.093951,-0.49465, + 0.040193,0.650965,-0.758043,2.747937,0.712253,-0.615674, + -0.16423,0.819635,-0.548842,2.854291,1.093951,-0.49465, + -0.043323,0.541029,-0.839887,2.948387,0.783357,-0.515058, + 0.177367,0.480226,-0.859025,2.811504,0.469098,-0.657443, + 0.040193,0.650965,-0.758043,2.747937,0.712253,-0.615674, + -0.043323,0.541029,-0.839887,2.948387,0.783357,-0.515058, + 0.177367,0.480226,-0.859025,2.811504,0.469098,-0.657443, + -0.043323,0.541029,-0.839887,2.948387,0.783357,-0.515058, + 0.04432,0.372862,-0.926828,3.06109,0.397226,-0.574193, + 0.288711,0.386915,-0.875753,2.898733,0.271916,-0.651298, + 0.177367,0.480226,-0.859025,2.811504,0.469098,-0.657443, + 0.04432,0.372862,-0.926828,3.06109,0.397226,-0.574193, + 0.41428,0.318289,-0.852681,2.91987,0.084875,-0.64246, + 0.288711,0.386915,-0.875753,2.898733,0.271916,-0.651298, + 0.04432,0.372862,-0.926828,3.06109,0.397226,-0.574193, + 0.41428,0.318289,-0.852681,2.91987,0.084875,-0.64246, + 0.04432,0.372862,-0.926828,3.06109,0.397226,-0.574193, + 0.098376,0.32868,-0.939304,3.136321,0.171237,-0.539896, + 0.519338,0.264458,-0.812619,2.953029,-0.12769,-0.520499, + 0.41428,0.318289,-0.852681,2.91987,0.084875,-0.64246, + 0.098376,0.32868,-0.939304,3.136321,0.171237,-0.539896, + 0.519338,0.264458,-0.812619,2.953029,-0.12769,-0.520499, + 0.098376,0.32868,-0.939304,3.136321,0.171237,-0.539896, + 0.159882,0.223439,-0.961516,3.16616,0.02131,-0.457261, + 0.486425,0.192908,-0.852161,2.986408,-0.413503,-0.428964, + 0.519338,0.264458,-0.812619,2.953029,-0.12769,-0.520499, + 0.159882,0.223439,-0.961516,3.16616,0.02131,-0.457261, + 0.486425,0.192908,-0.852161,2.986408,-0.413503,-0.428964, + 0.159882,0.223439,-0.961516,3.16616,0.02131,-0.457261, + 0.224429,0.165293,-0.96037,3.199571,-0.153739,-0.38015, + 0.449624,0.075438,-0.890027,3.053144,-0.609681,-0.326931, + 0.486425,0.192908,-0.852161,2.986408,-0.413503,-0.428964, + 0.224429,0.165293,-0.96037,3.199571,-0.153739,-0.38015, + 0.449624,0.075438,-0.890027,3.053144,-0.609681,-0.326931, + 0.224429,0.165293,-0.96037,3.199571,-0.153739,-0.38015, + 0.331391,0.08899,-0.939287,3.286426,-0.300744,-0.276331, + 0.533629,-0.162705,-0.82992,3.107533,-0.691019,-0.264602, + 0.449624,0.075438,-0.890027,3.053144,-0.609681,-0.326931, + 0.331391,0.08899,-0.939287,3.286426,-0.300744,-0.276331, + 0.533629,-0.162705,-0.82992,3.107533,-0.691019,-0.264602, + 0.331391,0.08899,-0.939287,3.286426,-0.300744,-0.276331, + 0.445439,-0.182623,-0.876489,3.342159,-0.384674,-0.201349, + 0.694153,-0.467999,0.546926,3.454971,2.169877,0, + 0.020519,-0.282941,-0.958918,3.4583,2.151656,-0.102662, + 0.261393,-0.399072,-0.878872,3.233975,2.059193,-0.072431, + 0.694153,-0.467999,0.546926,3.454971,2.169877,0, + 0.261393,-0.399072,-0.878872,3.233975,2.059193,-0.072431, + -0.861251,0.383698,-0.333202,3.247406,2.073333,0, + -0.560204,0.828355,-0.00034,3.33521,-0.375755,0, + 0.445439,-0.182623,-0.876489,3.342159,-0.384674,-0.201349, + 0.383941,-0.196382,-0.902232,3.514981,-0.121886,-0.187589, + -0.560204,0.828355,-0.00034,3.33521,-0.375755,0, + 0.383941,-0.196382,-0.902232,3.514981,-0.121886,-0.187589, + 0.431966,-0.771434,0.46722,3.486028,-0.141683,0, + -0.926486,-0.356041,0.121897,2.723503,1.898839,0, + 0.889638,-0.392482,0.233458,2.985371,1.982663,0, + 0.441787,-0.375177,-0.814903,3.009101,1.971604,-0.03422, + 0.45552,-0.330524,-0.826593,2.715712,1.828219,-0.167709, + -0.926486,-0.356041,0.121897,2.723503,1.898839,0, + 0.441787,-0.375177,-0.814903,3.009101,1.971604,-0.03422, + 0.45552,-0.330524,-0.826593,2.715712,1.828219,-0.167709, + 0.441787,-0.375177,-0.814903,3.009101,1.971604,-0.03422, + 0.483908,-0.405185,-0.775667,3.036361,1.913989,-0.169838, + 0.489736,-0.346185,-0.800197,2.738132,1.687333,-0.295046, + 0.45552,-0.330524,-0.826593,2.715712,1.828219,-0.167709, + 0.483908,-0.405185,-0.775667,3.036361,1.913989,-0.169838, + 0.489736,-0.346185,-0.800197,2.738132,1.687333,-0.295046, + 0.483908,-0.405185,-0.775667,3.036361,1.913989,-0.169838, + 0.482381,-0.398126,-0.780259,3.058366,1.773346,-0.297337, + 0.5205,-0.336657,-0.784692,2.77568,1.53871,-0.352829, + 0.489736,-0.346185,-0.800197,2.738132,1.687333,-0.295046, + 0.482381,-0.398126,-0.780259,3.058366,1.773346,-0.297337, + 0.5205,-0.336657,-0.784692,2.77568,1.53871,-0.352829, + 0.482381,-0.398126,-0.780259,3.058366,1.773346,-0.297337, + 0.702554,-0.570096,-0.42592,3.086666,1.632991,-0.338863, + 0.760747,-0.509474,-0.40212,2.815366,1.377583,-0.413399, + 0.5205,-0.336657,-0.784692,2.77568,1.53871,-0.352829, + 0.702554,-0.570096,-0.42592,3.086666,1.632991,-0.338863, + 0.760747,-0.509474,-0.40212,2.815366,1.377583,-0.413399, + 0.702554,-0.570096,-0.42592,3.086666,1.632991,-0.338863, + -0.317114,0.866865,-0.384686,3.115383,1.49239,-0.380228, + -0.16423,0.819635,-0.548842,2.854291,1.093951,-0.49465, + 0.760747,-0.509474,-0.40212,2.815366,1.377583,-0.413399, + -0.317114,0.866865,-0.384686,3.115383,1.49239,-0.380228, + -0.16423,0.819635,-0.548842,2.854291,1.093951,-0.49465, + -0.317114,0.866865,-0.384686,3.115383,1.49239,-0.380228, + -0.273708,0.760234,-0.589175,3.163181,1.209972,-0.462438, + -0.043323,0.541029,-0.839887,2.948387,0.783357,-0.515058, + -0.16423,0.819635,-0.548842,2.854291,1.093951,-0.49465, + -0.273708,0.760234,-0.589175,3.163181,1.209972,-0.462438, + -0.043323,0.541029,-0.839887,2.948387,0.783357,-0.515058, + -0.273708,0.760234,-0.589175,3.163181,1.209972,-0.462438, + -0.158888,0.47696,-0.864444,3.189664,0.907503,-0.500122, + 0.04432,0.372862,-0.926828,3.06109,0.397226,-0.574193, + -0.043323,0.541029,-0.839887,2.948387,0.783357,-0.515058, + -0.158888,0.47696,-0.864444,3.189664,0.907503,-0.500122, + 0.04432,0.372862,-0.926828,3.06109,0.397226,-0.574193, + -0.158888,0.47696,-0.864444,3.189664,0.907503,-0.500122, + -0.095989,0.297871,-0.949768,3.280681,0.510802,-0.499434, + 0.098376,0.32868,-0.939304,3.136321,0.171237,-0.539896, + 0.04432,0.372862,-0.926828,3.06109,0.397226,-0.574193, + -0.095989,0.297871,-0.949768,3.280681,0.510802,-0.499434, + 0.098376,0.32868,-0.939304,3.136321,0.171237,-0.539896, + -0.095989,0.297871,-0.949768,3.280681,0.510802,-0.499434, + -0.078774,0.27578,-0.957987,3.321825,0.26669,-0.46575, + 0.159882,0.223439,-0.961516,3.16616,0.02131,-0.457261, + 0.098376,0.32868,-0.939304,3.136321,0.171237,-0.539896, + -0.078774,0.27578,-0.957987,3.321825,0.26669,-0.46575, + 0.159882,0.223439,-0.961516,3.16616,0.02131,-0.457261, + -0.078774,0.27578,-0.957987,3.321825,0.26669,-0.46575, + -0.027323,0.180938,-0.983115,3.36004,0.165487,-0.412685, + 0.224429,0.165293,-0.96037,3.199571,-0.153739,-0.38015, + 0.159882,0.223439,-0.961516,3.16616,0.02131,-0.457261, + -0.027323,0.180938,-0.983115,3.36004,0.165487,-0.412685, + 0.224429,0.165293,-0.96037,3.199571,-0.153739,-0.38015, + -0.027323,0.180938,-0.983115,3.36004,0.165487,-0.412685, + 0.065337,0.07376,-0.995133,3.378799,0.073736,-0.355362, + 0.331391,0.08899,-0.939287,3.286426,-0.300744,-0.276331, + 0.224429,0.165293,-0.96037,3.199571,-0.153739,-0.38015, + 0.065337,0.07376,-0.995133,3.378799,0.073736,-0.355362, + 0.331391,0.08899,-0.939287,3.286426,-0.300744,-0.276331, + 0.065337,0.07376,-0.995133,3.378799,0.073736,-0.355362, + 0.226651,-0.023678,-0.973688,3.43895,-0.08258,-0.257015, + 0.445439,-0.182623,-0.876489,3.342159,-0.384674,-0.201349, + 0.331391,0.08899,-0.939287,3.286426,-0.300744,-0.276331, + 0.226651,-0.023678,-0.973688,3.43895,-0.08258,-0.257015, + 0.445439,-0.182623,-0.876489,3.342159,-0.384674,-0.201349, + 0.226651,-0.023678,-0.973688,3.43895,-0.08258,-0.257015, + 0.383941,-0.196382,-0.902232,3.514981,-0.121886,-0.187589, + 0.07924,-0.231862,-0.969516,3.955635,0.432417,-0.197586, + 0.338485,-0.103202,-0.935295,3.929251,0.411689,0, + -0.910859,-0.100368,-0.400327,3.731689,0.186391,0, + 0.07924,-0.231862,-0.969516,3.955635,0.432417,-0.197586, + -0.910859,-0.100368,-0.400327,3.731689,0.186391,0, + 0.325831,-0.277459,-0.903798,3.737014,0.181837,-0.176819, + -0.081635,-0.03459,-0.996062,3.889626,0.475277,-0.247365, + 0.07924,-0.231862,-0.969516,3.955635,0.432417,-0.197586, + 0.325831,-0.277459,-0.903798,3.737014,0.181837,-0.176819, + -0.081635,-0.03459,-0.996062,3.889626,0.475277,-0.247365, + 0.325831,-0.277459,-0.903798,3.737014,0.181837,-0.176819, + 0.144017,-0.141696,-0.979378,3.700363,0.265794,-0.240762, + -0.178707,0.132414,-0.974951,3.861841,0.560638,-0.311961, + -0.081635,-0.03459,-0.996062,3.889626,0.475277,-0.247365, + 0.144017,-0.141696,-0.979378,3.700363,0.265794,-0.240762, + -0.178707,0.132414,-0.974951,3.861841,0.560638,-0.311961, + 0.144017,-0.141696,-0.979378,3.700363,0.265794,-0.240762, + -0.023695,0.006701,-0.999697,3.67471,0.338839,-0.30784, + -0.178707,0.132414,-0.974951,3.861841,0.560638,-0.311961, + -0.023695,0.006701,-0.999697,3.67471,0.338839,-0.30784, + -0.128537,0.152973,-0.979835,3.641195,0.407454,-0.362198, + -0.21777,0.161093,-0.962614,3.849352,0.664451,-0.387198, + -0.178707,0.132414,-0.974951,3.861841,0.560638,-0.311961, + -0.128537,0.152973,-0.979835,3.641195,0.407454,-0.362198, + -0.21777,0.161093,-0.962614,3.849352,0.664451,-0.387198, + -0.128537,0.152973,-0.979835,3.641195,0.407454,-0.362198, + -0.175197,0.22468,-0.958553,3.61965,0.472046,-0.391742, + -0.273816,0.228927,-0.93414,3.823137,0.853054,-0.461519, + -0.21777,0.161093,-0.962614,3.849352,0.664451,-0.387198, + -0.175197,0.22468,-0.958553,3.61965,0.472046,-0.391742, + -0.273816,0.228927,-0.93414,3.823137,0.853054,-0.461519, + -0.175197,0.22468,-0.958553,3.61965,0.472046,-0.391742, + -0.203969,0.261593,-0.94338,3.559394,0.706516,-0.452535, + -0.385487,0.478576,-0.788901,3.747724,1.184933,-0.518662, + -0.273816,0.228927,-0.93414,3.823137,0.853054,-0.461519, + -0.203969,0.261593,-0.94338,3.559394,0.706516,-0.452535, + -0.385487,0.478576,-0.788901,3.747724,1.184933,-0.518662, + -0.203969,0.261593,-0.94338,3.559394,0.706516,-0.452535, + -0.270788,0.46353,-0.84369,3.528445,1.060127,-0.489443, + -0.447812,0.698934,-0.557634,3.650974,1.46374,-0.478617, + -0.385487,0.478576,-0.788901,3.747724,1.184933,-0.518662, + -0.270788,0.46353,-0.84369,3.528445,1.060127,-0.489443, + -0.447812,0.698934,-0.557634,3.650974,1.46374,-0.478617, + -0.270788,0.46353,-0.84369,3.528445,1.060127,-0.489443, + -0.354832,0.724971,-0.590348,3.47341,1.366149,-0.454658, + -0.463441,0.825581,-0.321928,3.590526,1.70109,-0.411994, + -0.447812,0.698934,-0.557634,3.650974,1.46374,-0.478617, + -0.354832,0.724971,-0.590348,3.47341,1.366149,-0.454658, + -0.463441,0.825581,-0.321928,3.590526,1.70109,-0.411994, + -0.354832,0.724971,-0.590348,3.47341,1.366149,-0.454658, + -0.384424,0.863444,-0.326623,3.377233,1.5878,-0.400781, + 0.492397,-0.77993,-0.386336,3.541188,1.849183,-0.386366, + -0.463441,0.825581,-0.321928,3.590526,1.70109,-0.411994, + -0.384424,0.863444,-0.326623,3.377233,1.5878,-0.400781, + 0.492397,-0.77993,-0.386336,3.541188,1.849183,-0.386366, + -0.384424,0.863444,-0.326623,3.377233,1.5878,-0.400781, + 0.673211,-0.58089,-0.457551,3.337545,1.748927,-0.34021, + 0.313443,-0.691245,-0.651102,3.479418,1.97825,-0.317478, + 0.492397,-0.77993,-0.386336,3.541188,1.849183,-0.386366, + 0.673211,-0.58089,-0.457551,3.337545,1.748927,-0.34021, + 0.313443,-0.691245,-0.651102,3.479418,1.97825,-0.317478, + 0.673211,-0.58089,-0.457551,3.337545,1.748927,-0.34021, + 0.454048,-0.464454,-0.760344,3.276333,1.863773,-0.294266, + 0.161194,-0.480657,-0.861966,3.460196,2.103494,-0.180368, + 0.313443,-0.691245,-0.651102,3.479418,1.97825,-0.317478, + 0.454048,-0.464454,-0.760344,3.276333,1.863773,-0.294266, + 0.161194,-0.480657,-0.861966,3.460196,2.103494,-0.180368, + 0.454048,-0.464454,-0.760344,3.276333,1.863773,-0.294266, + 0.428291,-0.499911,-0.752765,3.252224,2.026347,-0.148215, + 0.020519,-0.282941,-0.958918,3.4583,2.151656,-0.102662, + 0.161194,-0.480657,-0.861966,3.460196,2.103494,-0.180368, + 0.428291,-0.499911,-0.752765,3.252224,2.026347,-0.148215, + 0.020519,-0.282941,-0.958918,3.4583,2.151656,-0.102662, + 0.428291,-0.499911,-0.752765,3.252224,2.026347,-0.148215, + 0.261393,-0.399072,-0.878872,3.233975,2.059193,-0.072431, + 0.486425,0.192908,-0.852161,2.986408,-0.413503,-0.428964, + 0.016767,-0.927537,-0.373356,2.835437,-0.231101,-0.57789, + 0.519338,0.264458,-0.812619,2.953029,-0.12769,-0.520499, + 0.241303,0.584583,-0.77462,2.753156,0.400829,-0.713141, + 0.072694,0.752739,-0.654294,2.679445,0.687427,-0.720573, + 0.040193,0.650965,-0.758043,2.747937,0.712253,-0.615674, + 0.241303,0.584583,-0.77462,2.753156,0.400829,-0.713141, + 0.040193,0.650965,-0.758043,2.747937,0.712253,-0.615674, + 0.177367,0.480226,-0.859025,2.811504,0.469098,-0.657443, + 0.462789,0.48004,-0.745243,2.790681,0.219187,-0.718263, + 0.241303,0.584583,-0.77462,2.753156,0.400829,-0.713141, + 0.177367,0.480226,-0.859025,2.811504,0.469098,-0.657443, + 0.462789,0.48004,-0.745243,2.790681,0.219187,-0.718263, + 0.177367,0.480226,-0.859025,2.811504,0.469098,-0.657443, + 0.288711,0.386915,-0.875753,2.898733,0.271916,-0.651298, + 0.539114,0.412574,-0.734261,2.790657,0.044324,-0.717488, + 0.462789,0.48004,-0.745243,2.790681,0.219187,-0.718263, + 0.288711,0.386915,-0.875753,2.898733,0.271916,-0.651298, + 0.539114,0.412574,-0.734261,2.790657,0.044324,-0.717488, + 0.288711,0.386915,-0.875753,2.898733,0.271916,-0.651298, + 0.41428,0.318289,-0.852681,2.91987,0.084875,-0.64246, + 0.016767,-0.927537,-0.373356,2.835437,-0.231101,-0.57789, + 0.763734,0.228435,-0.603761,2.736198,-0.346225,-0.659345, + 0.696162,0.333274,-0.635835,2.743995,-0.129852,-0.718277, + 0.696162,0.333274,-0.635835,2.743995,-0.129852,-0.718277, + 0.41428,0.318289,-0.852681,2.91987,0.084875,-0.64246, + 0.519338,0.264458,-0.812619,2.953029,-0.12769,-0.520499, + 0.696162,0.333274,-0.635835,2.743995,-0.129852,-0.718277, + 0.519338,0.264458,-0.812619,2.953029,-0.12769,-0.520499, + 0.016767,-0.927537,-0.373356,2.835437,-0.231101,-0.57789, + 0.696162,0.333274,-0.635835,2.743995,-0.129852,-0.718277, + 0.539114,0.412574,-0.734261,2.790657,0.044324,-0.717488, + 0.41428,0.318289,-0.852681,2.91987,0.084875,-0.64246, + 0.788801,-0.19938,-0.581412,2.514162,0.988713,-0.674527, + 0.906617,-0.14387,-0.39667,2.482917,0.997637,-0.702425, + 0.752227,-0.484776,-0.446258,2.396355,1.242239,-0.597722, + 0.907314,0.09913,-0.4086,2.618307,-0.549092,-0.805491, + 0.908163,-0.140074,-0.394486,2.5392,-0.727778,-0.750475, + 0.795625,-0.129968,-0.591684,2.410367,-0.777999,-0.841105, + 0.907314,0.09913,-0.4086,2.618307,-0.549092,-0.805491, + 0.795625,-0.129968,-0.591684,2.410367,-0.777999,-0.841105, + 0.748939,0.152982,-0.644738,2.543372,-0.548031,-0.937182, + 0.85208,0.278905,-0.442914,2.690576,-0.368057,-0.819343, + 0.907314,0.09913,-0.4086,2.618307,-0.549092,-0.805491, + 0.748939,0.152982,-0.644738,2.543372,-0.548031,-0.937182, + 0.85208,0.278905,-0.442914,2.690576,-0.368057,-0.819343, + 0.748939,0.152982,-0.644738,2.543372,-0.548031,-0.937182, + 0.69338,0.351142,-0.629224,2.594499,-0.422948,-0.981263, + 0.759315,0.386803,-0.523282,2.702577,-0.197406,-0.795611, + 0.85208,0.278905,-0.442914,2.690576,-0.368057,-0.819343, + 0.69338,0.351142,-0.629224,2.594499,-0.422948,-0.981263, + 0.759315,0.386803,-0.523282,2.702577,-0.197406,-0.795611, + 0.69338,0.351142,-0.629224,2.594499,-0.422948,-0.981263, + 0.662294,0.443714,-0.603725,2.60743,-0.208248,-0.974218, + 0.636794,0.461927,-0.617346,2.734183,0.038769,-0.86581, + 0.759315,0.386803,-0.523282,2.702577,-0.197406,-0.795611, + 0.662294,0.443714,-0.603725,2.60743,-0.208248,-0.974218, + 0.636794,0.461927,-0.617346,2.734183,0.038769,-0.86581, + 0.662294,0.443714,-0.603725,2.60743,-0.208248,-0.974218, + 0.614456,0.489786,-0.618509,2.649413,0.031535,-1.024796, + 0.722145,-0.312679,-0.617041,2.731512,0.219003,-0.891585, + 0.636794,0.461927,-0.617346,2.734183,0.038769,-0.86581, + 0.614456,0.489786,-0.618509,2.649413,0.031535,-1.024796, + 0.722145,-0.312679,-0.617041,2.731512,0.219003,-0.891585, + 0.614456,0.489786,-0.618509,2.649413,0.031535,-1.024796, + 0.718673,-0.290446,-0.631784,2.668936,0.206182,-1.014371, + 0.742962,-0.255405,-0.618688,2.70696,0.393597,-0.849582, + 0.722145,-0.312679,-0.617041,2.731512,0.219003,-0.891585, + 0.718673,-0.290446,-0.631784,2.668936,0.206182,-1.014371, + 0.742962,-0.255405,-0.618688,2.70696,0.393597,-0.849582, + 0.718673,-0.290446,-0.631784,2.668936,0.206182,-1.014371, + 0.815771,-0.424495,-0.392838,2.616001,0.447717,-0.960748, + 0.804239,-0.153549,-0.574128,2.604217,0.728827,-0.769671, + 0.742962,-0.255405,-0.618688,2.70696,0.393597,-0.849582, + 0.815771,-0.424495,-0.392838,2.616001,0.447717,-0.960748, + 0.804239,-0.153549,-0.574128,2.604217,0.728827,-0.769671, + 0.815771,-0.424495,-0.392838,2.616001,0.447717,-0.960748, + 0.900366,-0.205985,-0.38329,2.5704,0.738683,-0.830405, + 0.788801,-0.19938,-0.581412,2.514162,0.988713,-0.674527, + 0.804239,-0.153549,-0.574128,2.604217,0.728827,-0.769671, + 0.900366,-0.205985,-0.38329,2.5704,0.738683,-0.830405, + 0.788801,-0.19938,-0.581412,2.514162,0.988713,-0.674527, + 0.900366,-0.205985,-0.38329,2.5704,0.738683,-0.830405, + 0.906617,-0.14387,-0.39667,2.482917,0.997637,-0.702425, + 0.907314,0.09913,-0.4086,2.618307,-0.549092,-0.805491, + 0.85208,0.278905,-0.442914,2.690576,-0.368057,-0.819343, + 0.763734,0.228435,-0.603761,2.736198,-0.346225,-0.659345, + 0.907314,0.09913,-0.4086,2.618307,-0.549092,-0.805491, + 0.763734,0.228435,-0.603761,2.736198,-0.346225,-0.659345, + 0.769758,0.095155,-0.631204,2.688131,-0.517509,-0.672975, + 0.788801,-0.19938,-0.581412,2.514162,0.988713,-0.674527, + 0.752227,-0.484776,-0.446258,2.396355,1.242239,-0.597722, + -0.071584,0.92252,-0.379253,2.542439,0.999928,-0.648592, + 0.804239,-0.153549,-0.574128,2.604217,0.728827,-0.769671, + 0.788801,-0.19938,-0.581412,2.514162,0.988713,-0.674527, + -0.071584,0.92252,-0.379253,2.542439,0.999928,-0.648592, + 0.804239,-0.153549,-0.574128,2.604217,0.728827,-0.769671, + -0.071584,0.92252,-0.379253,2.542439,0.999928,-0.648592, + 0.072694,0.752739,-0.654294,2.679445,0.687427,-0.720573, + 0.742962,-0.255405,-0.618688,2.70696,0.393597,-0.849582, + 0.804239,-0.153549,-0.574128,2.604217,0.728827,-0.769671, + 0.072694,0.752739,-0.654294,2.679445,0.687427,-0.720573, + 0.742962,-0.255405,-0.618688,2.70696,0.393597,-0.849582, + 0.072694,0.752739,-0.654294,2.679445,0.687427,-0.720573, + 0.241303,0.584583,-0.77462,2.753156,0.400829,-0.713141, + 0.722145,-0.312679,-0.617041,2.731512,0.219003,-0.891585, + 0.742962,-0.255405,-0.618688,2.70696,0.393597,-0.849582, + 0.241303,0.584583,-0.77462,2.753156,0.400829,-0.713141, + 0.722145,-0.312679,-0.617041,2.731512,0.219003,-0.891585, + 0.241303,0.584583,-0.77462,2.753156,0.400829,-0.713141, + 0.462789,0.48004,-0.745243,2.790681,0.219187,-0.718263, + 0.636794,0.461927,-0.617346,2.734183,0.038769,-0.86581, + 0.722145,-0.312679,-0.617041,2.731512,0.219003,-0.891585, + 0.462789,0.48004,-0.745243,2.790681,0.219187,-0.718263, + 0.636794,0.461927,-0.617346,2.734183,0.038769,-0.86581, + 0.462789,0.48004,-0.745243,2.790681,0.219187,-0.718263, + 0.539114,0.412574,-0.734261,2.790657,0.044324,-0.717488, + 0.759315,0.386803,-0.523282,2.702577,-0.197406,-0.795611, + 0.636794,0.461927,-0.617346,2.734183,0.038769,-0.86581, + 0.539114,0.412574,-0.734261,2.790657,0.044324,-0.717488, + 0.759315,0.386803,-0.523282,2.702577,-0.197406,-0.795611, + 0.539114,0.412574,-0.734261,2.790657,0.044324,-0.717488, + 0.696162,0.333274,-0.635835,2.743995,-0.129852,-0.718277, + 0.85208,0.278905,-0.442914,2.690576,-0.368057,-0.819343, + 0.759315,0.386803,-0.523282,2.702577,-0.197406,-0.795611, + 0.696162,0.333274,-0.635835,2.743995,-0.129852,-0.718277, + 0.85208,0.278905,-0.442914,2.690576,-0.368057,-0.819343, + 0.696162,0.333274,-0.635835,2.743995,-0.129852,-0.718277, + 0.763734,0.228435,-0.603761,2.736198,-0.346225,-0.659345, + 0.072694,0.752739,-0.654294,2.679445,0.687427,-0.720573, + -0.071584,0.92252,-0.379253,2.542439,0.999928,-0.648592, + -0.080985,0.883253,-0.461851,2.637461,1.01726,-0.581611, + 0.072694,0.752739,-0.654294,2.679445,0.687427,-0.720573, + -0.080985,0.883253,-0.461851,2.637461,1.01726,-0.581611, + 0.040193,0.650965,-0.758043,2.747937,0.712253,-0.615674, + 0.547549,-0.279581,-0.788686,2.13239,1.755821,-0.180271, + 0.756976,-0.653442,0,2.128139,1.788397,0, + 0.536218,-0.84408,0.000006,2.339597,1.807702,0, + 0.547549,-0.279581,-0.788686,2.13239,1.755821,-0.180271, + 0.536218,-0.84408,0.000006,2.339597,1.807702,0, + 0.474213,-0.311965,-0.823286,2.361089,1.76666,-0.202595, + 0.598679,-0.200355,-0.775527,2.183003,1.65407,-0.341767, + 0.547549,-0.279581,-0.788686,2.13239,1.755821,-0.180271, + 0.474213,-0.311965,-0.823286,2.361089,1.76666,-0.202595, + 0.598679,-0.200355,-0.775527,2.183003,1.65407,-0.341767, + 0.474213,-0.311965,-0.823286,2.361089,1.76666,-0.202595, + 0.488174,-0.280956,-0.826287,2.406969,1.645328,-0.341479, + 0.561098,-0.272385,-0.781649,2.301359,1.397721,-0.546015, + 0.598679,-0.200355,-0.775527,2.183003,1.65407,-0.341767, + 0.488174,-0.280956,-0.826287,2.406969,1.645328,-0.341479, + 0.561098,-0.272385,-0.781649,2.301359,1.397721,-0.546015, + 0.488174,-0.280956,-0.826287,2.406969,1.645328,-0.341479, + 0.531574,-0.288506,-0.796362,2.519027,1.485931,-0.422962, + 0.752227,-0.484776,-0.446258,2.396355,1.242239,-0.597722, + 0.561098,-0.272385,-0.781649,2.301359,1.397721,-0.546015, + 0.531574,-0.288506,-0.796362,2.519027,1.485931,-0.422962, + 0.752227,-0.484776,-0.446258,2.396355,1.242239,-0.597722, + 0.531574,-0.288506,-0.796362,2.519027,1.485931,-0.422962, + 0.769657,-0.480833,-0.420033,2.553871,1.284278,-0.512335, + -0.071584,0.92252,-0.379253,2.542439,0.999928,-0.648592, + 0.752227,-0.484776,-0.446258,2.396355,1.242239,-0.597722, + 0.769657,-0.480833,-0.420033,2.553871,1.284278,-0.512335, + -0.071584,0.92252,-0.379253,2.542439,0.999928,-0.648592, + 0.769657,-0.480833,-0.420033,2.553871,1.284278,-0.512335, + -0.080985,0.883253,-0.461851,2.637461,1.01726,-0.581611, + -0.096144,-0.182414,-0.97851,2.292449,-0.871852,-0.8824, + 0.561574,-0.148323,-0.814024,2.245624,-0.864372,-0.995778, + 0.525142,-0.062799,-0.848694,2.346081,-0.74535,-1.013296, + -0.096144,-0.182414,-0.97851,2.292449,-0.871852,-0.8824, + 0.525142,-0.062799,-0.848694,2.346081,-0.74535,-1.013296, + 0.795625,-0.129968,-0.591684,2.410367,-0.777999,-0.841105, + 0.805898,-0.146097,-0.573745,2.096552,1.678482,-0.32681, + 0.546571,-0.125171,0.828005,2.069379,1.727818,-0.212746, + 0.547549,-0.279581,-0.788686,2.13239,1.755821,-0.180271, + 0.805898,-0.146097,-0.573745,2.096552,1.678482,-0.32681, + 0.547549,-0.279581,-0.788686,2.13239,1.755821,-0.180271, + 0.598679,-0.200355,-0.775527,2.183003,1.65407,-0.341767, + 0.772313,-0.244122,-0.586461,2.189848,1.468992,-0.517501, + 0.805898,-0.146097,-0.573745,2.096552,1.678482,-0.32681, + 0.598679,-0.200355,-0.775527,2.183003,1.65407,-0.341767, + 0.772313,-0.244122,-0.586461,2.189848,1.468992,-0.517501, + 0.598679,-0.200355,-0.775527,2.183003,1.65407,-0.341767, + 0.561098,-0.272385,-0.781649,2.301359,1.397721,-0.546015, + 0.697438,-0.478568,-0.533435,2.266003,1.273253,-0.663332, + 0.772313,-0.244122,-0.586461,2.189848,1.468992,-0.517501, + 0.561098,-0.272385,-0.781649,2.301359,1.397721,-0.546015, + 0.697438,-0.478568,-0.533435,2.266003,1.273253,-0.663332, + 0.561098,-0.272385,-0.781649,2.301359,1.397721,-0.546015, + 0.752227,-0.484776,-0.446258,2.396355,1.242239,-0.597722, + 0.628361,-0.426126,-0.65083,2.347317,1.066114,-0.758763, + 0.697438,-0.478568,-0.533435,2.266003,1.273253,-0.663332, + 0.752227,-0.484776,-0.446258,2.396355,1.242239,-0.597722, + 0.628361,-0.426126,-0.65083,2.347317,1.066114,-0.758763, + 0.752227,-0.484776,-0.446258,2.396355,1.242239,-0.597722, + 0.906617,-0.14387,-0.39667,2.482917,0.997637,-0.702425, + 0.065855,0.814333,-0.576649,2.399389,0.782091,-0.915279, + 0.628361,-0.426126,-0.65083,2.347317,1.066114,-0.758763, + 0.906617,-0.14387,-0.39667,2.482917,0.997637,-0.702425, + 0.065855,0.814333,-0.576649,2.399389,0.782091,-0.915279, + 0.906617,-0.14387,-0.39667,2.482917,0.997637,-0.702425, + 0.900366,-0.205985,-0.38329,2.5704,0.738683,-0.830405, + 0.187431,0.691784,-0.697355,2.448969,0.529858,-1.037335, + 0.065855,0.814333,-0.576649,2.399389,0.782091,-0.915279, + 0.900366,-0.205985,-0.38329,2.5704,0.738683,-0.830405, + 0.187431,0.691784,-0.697355,2.448969,0.529858,-1.037335, + 0.900366,-0.205985,-0.38329,2.5704,0.738683,-0.830405, + 0.815771,-0.424495,-0.392838,2.616001,0.447717,-0.960748, + 0.328244,0.603536,-0.726637,2.495354,0.250522,-1.132081, + 0.187431,0.691784,-0.697355,2.448969,0.529858,-1.037335, + 0.815771,-0.424495,-0.392838,2.616001,0.447717,-0.960748, + 0.328244,0.603536,-0.726637,2.495354,0.250522,-1.132081, + 0.815771,-0.424495,-0.392838,2.616001,0.447717,-0.960748, + 0.718673,-0.290446,-0.631784,2.668936,0.206182,-1.014371, + 0.387394,0.516219,-0.763835,2.50049,-0.035029,-1.170179, + 0.328244,0.603536,-0.726637,2.495354,0.250522,-1.132081, + 0.718673,-0.290446,-0.631784,2.668936,0.206182,-1.014371, + 0.387394,0.516219,-0.763835,2.50049,-0.035029,-1.170179, + 0.718673,-0.290446,-0.631784,2.668936,0.206182,-1.014371, + 0.614456,0.489786,-0.618509,2.649413,0.031535,-1.024796, + 0.387987,0.466054,-0.795148,2.452588,-0.244072,-1.138797, + 0.387394,0.516219,-0.763835,2.50049,-0.035029,-1.170179, + 0.614456,0.489786,-0.618509,2.649413,0.031535,-1.024796, + 0.387987,0.466054,-0.795148,2.452588,-0.244072,-1.138797, + 0.614456,0.489786,-0.618509,2.649413,0.031535,-1.024796, + 0.662294,0.443714,-0.603725,2.60743,-0.208248,-0.974218, + 0.397823,0.403779,-0.823832,2.439827,-0.395385,-1.131324, + 0.387987,0.466054,-0.795148,2.452588,-0.244072,-1.138797, + 0.662294,0.443714,-0.603725,2.60743,-0.208248,-0.974218, + 0.397823,0.403779,-0.823832,2.439827,-0.395385,-1.131324, + 0.662294,0.443714,-0.603725,2.60743,-0.208248,-0.974218, + 0.69338,0.351142,-0.629224,2.594499,-0.422948,-0.981263, + 0.449887,0.239006,-0.860511,2.384638,-0.591919,-1.043058, + 0.397823,0.403779,-0.823832,2.439827,-0.395385,-1.131324, + 0.69338,0.351142,-0.629224,2.594499,-0.422948,-0.981263, + 0.449887,0.239006,-0.860511,2.384638,-0.591919,-1.043058, + 0.69338,0.351142,-0.629224,2.594499,-0.422948,-0.981263, + 0.748939,0.152982,-0.644738,2.543372,-0.548031,-0.937182, + 0.525142,-0.062799,-0.848694,2.346081,-0.74535,-1.013296, + 0.449887,0.239006,-0.860511,2.384638,-0.591919,-1.043058, + 0.748939,0.152982,-0.644738,2.543372,-0.548031,-0.937182, + 0.525142,-0.062799,-0.848694,2.346081,-0.74535,-1.013296, + 0.748939,0.152982,-0.644738,2.543372,-0.548031,-0.937182, + 0.795625,-0.129968,-0.591684,2.410367,-0.777999,-0.841105, + -0.096144,-0.182414,-0.97851,2.292449,-0.871852,-0.8824, + -0.012663,0.029084,-0.999497,2.229345,-0.992723,-0.862826, + -0.742985,0.015712,-0.669123,2.222082,-0.957342,-1.014137, + -0.096144,-0.182414,-0.97851,2.292449,-0.871852,-0.8824, + -0.742985,0.015712,-0.669123,2.222082,-0.957342,-1.014137, + 0.561574,-0.148323,-0.814024,2.245624,-0.864372,-0.995778, + 0.525142,-0.062799,-0.848694,2.346081,-0.74535,-1.013296, + 0.561574,-0.148323,-0.814024,2.245624,-0.864372,-0.995778, + 0.097864,0.250653,-0.963118,2.013534,-0.662303,-1.191491, + 0.449887,0.239006,-0.860511,2.384638,-0.591919,-1.043058, + 0.525142,-0.062799,-0.848694,2.346081,-0.74535,-1.013296, + 0.097864,0.250653,-0.963118,2.013534,-0.662303,-1.191491, + 0.449887,0.239006,-0.860511,2.384638,-0.591919,-1.043058, + 0.097864,0.250653,-0.963118,2.013534,-0.662303,-1.191491, + 0.10998,0.376752,-0.919762,2.108912,-0.357128,-1.259691, + -0.385788,0.922588,0,2.042206,1.777154,0, + 0.546571,-0.125171,0.828005,2.069379,1.727818,-0.212746, + 0.513731,-0.239493,-0.823847,1.807583,1.756546,-0.177627, + -0.385788,0.922588,0,2.042206,1.777154,0, + 0.513731,-0.239493,-0.823847,1.807583,1.756546,-0.177627, + -0.720176,-0.693792,0,1.794465,1.787719,0, + 0.397823,0.403779,-0.823832,2.439827,-0.395385,-1.131324, + 0.449887,0.239006,-0.860511,2.384638,-0.591919,-1.043058, + 0.10998,0.376752,-0.919762,2.108912,-0.357128,-1.259691, + 0.397823,0.403779,-0.823832,2.439827,-0.395385,-1.131324, + 0.10998,0.376752,-0.919762,2.108912,-0.357128,-1.259691, + 0.12555,0.440005,-0.889176,2.136269,-0.187666,-1.278057, + 0.387987,0.466054,-0.795148,2.452588,-0.244072,-1.138797, + 0.397823,0.403779,-0.823832,2.439827,-0.395385,-1.131324, + 0.12555,0.440005,-0.889176,2.136269,-0.187666,-1.278057, + 0.387394,0.516219,-0.763835,2.50049,-0.035029,-1.170179, + 0.387987,0.466054,-0.795148,2.452588,-0.244072,-1.138797, + 0.12555,0.440005,-0.889176,2.136269,-0.187666,-1.278057, + 0.387394,0.516219,-0.763835,2.50049,-0.035029,-1.170179, + 0.12555,0.440005,-0.889176,2.136269,-0.187666,-1.278057, + 0.146937,0.551946,-0.820832,2.14179,-0.055306,-1.295565, + 0.328244,0.603536,-0.726637,2.495354,0.250522,-1.132081, + 0.387394,0.516219,-0.763835,2.50049,-0.035029,-1.170179, + 0.146937,0.551946,-0.820832,2.14179,-0.055306,-1.295565, + 0.328244,0.603536,-0.726637,2.495354,0.250522,-1.132081, + 0.146937,0.551946,-0.820832,2.14179,-0.055306,-1.295565, + 0.115383,0.694944,-0.709746,2.0817,0.283249,-1.259461, + 0.187431,0.691784,-0.697355,2.448969,0.529858,-1.037335, + 0.328244,0.603536,-0.726637,2.495354,0.250522,-1.132081, + 0.115383,0.694944,-0.709746,2.0817,0.283249,-1.259461, + 0.187431,0.691784,-0.697355,2.448969,0.529858,-1.037335, + 0.115383,0.694944,-0.709746,2.0817,0.283249,-1.259461, + 0.052979,0.780732,-0.622616,2.023441,0.529338,-1.144399, + 0.065855,0.814333,-0.576649,2.399389,0.782091,-0.915279, + 0.187431,0.691784,-0.697355,2.448969,0.529858,-1.037335, + 0.052979,0.780732,-0.622616,2.023441,0.529338,-1.144399, + 0.065855,0.814333,-0.576649,2.399389,0.782091,-0.915279, + 0.052979,0.780732,-0.622616,2.023441,0.529338,-1.144399, + 0.019336,0.837694,-0.545798,1.975941,0.827957,-1.018423, + 0.628361,-0.426126,-0.65083,2.347317,1.066114,-0.758763, + 0.065855,0.814333,-0.576649,2.399389,0.782091,-0.915279, + 0.019336,0.837694,-0.545798,1.975941,0.827957,-1.018423, + 0.628361,-0.426126,-0.65083,2.347317,1.066114,-0.758763, + 0.019336,0.837694,-0.545798,1.975941,0.827957,-1.018423, + 0.026499,0.942993,-0.331757,1.958254,1.130271,-0.861813, + 0.697438,-0.478568,-0.533435,2.266003,1.273253,-0.663332, + 0.628361,-0.426126,-0.65083,2.347317,1.066114,-0.758763, + 0.026499,0.942993,-0.331757,1.958254,1.130271,-0.861813, + 0.697438,-0.478568,-0.533435,2.266003,1.273253,-0.663332, + 0.026499,0.942993,-0.331757,1.958254,1.130271,-0.861813, + 0.696414,-0.392791,-0.600602,1.859443,1.450393,-0.632222, + 0.772313,-0.244122,-0.586461,2.189848,1.468992,-0.517501, + 0.697438,-0.478568,-0.533435,2.266003,1.273253,-0.663332, + 0.696414,-0.392791,-0.600602,1.859443,1.450393,-0.632222, + 0.772313,-0.244122,-0.586461,2.189848,1.468992,-0.517501, + 0.696414,-0.392791,-0.600602,1.859443,1.450393,-0.632222, + 0.552632,-0.484765,-0.677938,1.821946,1.618209,-0.403751, + 0.805898,-0.146097,-0.573745,2.096552,1.678482,-0.32681, + 0.772313,-0.244122,-0.586461,2.189848,1.468992,-0.517501, + 0.552632,-0.484765,-0.677938,1.821946,1.618209,-0.403751, + 0.805898,-0.146097,-0.573745,2.096552,1.678482,-0.32681, + 0.552632,-0.484765,-0.677938,1.821946,1.618209,-0.403751, + 0.506924,-0.406124,-0.760323,1.798719,1.714447,-0.259352, + 0.546571,-0.125171,0.828005,2.069379,1.727818,-0.212746, + 0.805898,-0.146097,-0.573745,2.096552,1.678482,-0.32681, + 0.506924,-0.406124,-0.760323,1.798719,1.714447,-0.259352, + 0.546571,-0.125171,0.828005,2.069379,1.727818,-0.212746, + 0.506924,-0.406124,-0.760323,1.798719,1.714447,-0.259352, + 0.513731,-0.239493,-0.823847,1.807583,1.756546,-0.177627, + 0.659349,-0.248914,-0.709437,0.737904,1.604213,-0.281713, + -0.208715,-0.624734,-0.752427,0.223642,1.684075,-0.160743, + 0.566114,-0.824327,0,0.234527,1.730117,0, + 0.659349,-0.248914,-0.709437,0.737904,1.604213,-0.281713, + 0.566114,-0.824327,0,0.234527,1.730117,0, + 0.981421,-0.191868,0,0.733818,1.740873,0, + 0.631747,-0.24686,-0.734817,0.725959,1.478055,-0.461804, + -0.251063,-0.683027,-0.685888,0.23733,1.595746,-0.288672, + -0.208715,-0.624734,-0.752427,0.223642,1.684075,-0.160743, + 0.631747,-0.24686,-0.734817,0.725959,1.478055,-0.461804, + -0.208715,-0.624734,-0.752427,0.223642,1.684075,-0.160743, + 0.659349,-0.248914,-0.709437,0.737904,1.604213,-0.281713, + 0.623235,-0.257987,-0.738255,0.760722,1.205036,-0.700545, + -0.252973,-0.819125,-0.51482,0.289039,1.496446,-0.430055, + -0.251063,-0.683027,-0.685888,0.23733,1.595746,-0.288672, + 0.623235,-0.257987,-0.738255,0.760722,1.205036,-0.700545, + -0.251063,-0.683027,-0.685888,0.23733,1.595746,-0.288672, + 0.631747,-0.24686,-0.734817,0.725959,1.478055,-0.461804, + 0.791391,-0.43807,-0.426373,0.857323,0.985001,-0.874029, + -0.13716,-0.98063,-0.139827,0.305671,1.298417,-0.629719, + -0.252973,-0.819125,-0.51482,0.289039,1.496446,-0.430055, + 0.791391,-0.43807,-0.426373,0.857323,0.985001,-0.874029, + -0.252973,-0.819125,-0.51482,0.289039,1.496446,-0.430055, + 0.623235,-0.257987,-0.738255,0.760722,1.205036,-0.700545, + -0.06371,0.842533,-0.534864,0.921312,0.755659,-0.99933, + 0.007127,0.896038,-0.44392,0.243473,1.134082,-0.819993, + -0.13716,-0.98063,-0.139827,0.305671,1.298417,-0.629719, + -0.06371,0.842533,-0.534864,0.921312,0.755659,-0.99933, + -0.13716,-0.98063,-0.139827,0.305671,1.298417,-0.629719, + 0.791391,-0.43807,-0.426373,0.857323,0.985001,-0.874029, + -0.069142,0.724976,-0.685295,0.939271,0.379986,-1.185872, + 0.009434,0.815301,-0.578961,0.316341,0.785311,-1.08626, + 0.007127,0.896038,-0.44392,0.243473,1.134082,-0.819993, + -0.069142,0.724976,-0.685295,0.939271,0.379986,-1.185872, + 0.007127,0.896038,-0.44392,0.243473,1.134082,-0.819993, + -0.06371,0.842533,-0.534864,0.921312,0.755659,-0.99933, + -0.057955,0.638634,-0.767325,0.927775,0.195225,-1.233043, + 0.040473,0.760778,-0.647749,0.539252,0.353984,-1.254493, + 0.009434,0.815301,-0.578961,0.316341,0.785311,-1.08626, + -0.057955,0.638634,-0.767325,0.927775,0.195225,-1.233043, + 0.009434,0.815301,-0.578961,0.316341,0.785311,-1.08626, + -0.069142,0.724976,-0.685295,0.939271,0.379986,-1.185872, + -0.024013,0.58573,-0.810151,0.950215,0.042751,-1.256188, + 0.080812,0.697931,-0.711591,0.53915,0.148262,-1.321014, + 0.040473,0.760778,-0.647749,0.539252,0.353984,-1.254493, + -0.024013,0.58573,-0.810151,0.950215,0.042751,-1.256188, + 0.040473,0.760778,-0.647749,0.539252,0.353984,-1.254493, + -0.057955,0.638634,-0.767325,0.927775,0.195225,-1.233043, + 0.016737,0.497476,-0.867316,0.943855,-0.101127,-1.274771, + 0.09853,0.626571,-0.773111,0.516872,-0.020713,-1.356627, + 0.080812,0.697931,-0.711591,0.53915,0.148262,-1.321014, + 0.016737,0.497476,-0.867316,0.943855,-0.101127,-1.274771, + 0.080812,0.697931,-0.711591,0.53915,0.148262,-1.321014, + -0.024013,0.58573,-0.810151,0.950215,0.042751,-1.256188, + 0.060533,0.377837,-0.923891,0.960321,-0.308052,-1.243133, + 0.111825,0.518485,-0.847743,0.542386,-0.188227,-1.370375, + 0.09853,0.626571,-0.773111,0.516872,-0.020713,-1.356627, + 0.060533,0.377837,-0.923891,0.960321,-0.308052,-1.243133, + 0.09853,0.626571,-0.773111,0.516872,-0.020713,-1.356627, + 0.016737,0.497476,-0.867316,0.943855,-0.101127,-1.274771, + 0.088722,0.251367,-0.963817,0.97453,-0.525273,-1.140353, + 0.163727,0.387435,-0.907242,0.546875,-0.39094,-1.363244, + 0.111825,0.518485,-0.847743,0.542386,-0.188227,-1.370375, + 0.088722,0.251367,-0.963817,0.97453,-0.525273,-1.140353, + 0.111825,0.518485,-0.847743,0.542386,-0.188227,-1.370375, + 0.060533,0.377837,-0.923891,0.960321,-0.308052,-1.243133, + 0.107989,0.168108,-0.979836,0.948819,-0.638568,-1.102958, + 0.227108,0.258715,-0.938876,0.550658,-0.633015,-1.331311, + 0.163727,0.387435,-0.907242,0.546875,-0.39094,-1.363244, + 0.107989,0.168108,-0.979836,0.948819,-0.638568,-1.102958, + 0.163727,0.387435,-0.907242,0.546875,-0.39094,-1.363244, + 0.088722,0.251367,-0.963817,0.97453,-0.525273,-1.140353, + 0.10833,0.05569,-0.992554,0.939974,-0.894739,-1.019809, + 0.263434,0.119819,-0.957207,0.527724,-0.862854,-1.253811, + 0.227108,0.258715,-0.938876,0.550658,-0.633015,-1.331311, + 0.10833,0.05569,-0.992554,0.939974,-0.894739,-1.019809, + 0.227108,0.258715,-0.938876,0.550658,-0.633015,-1.331311, + 0.107989,0.168108,-0.979836,0.948819,-0.638568,-1.102958, + 0.114032,-0.218132,-0.969234,0.956456,-1.070504,-0.921063, + 0.304293,-0.024391,-0.952266,0.544825,-1.133123,-1.096902, + 0.263434,0.119819,-0.957207,0.527724,-0.862854,-1.253811, + 0.114032,-0.218132,-0.969234,0.956456,-1.070504,-0.921063, + 0.263434,0.119819,-0.957207,0.527724,-0.862854,-1.253811, + 0.10833,0.05569,-0.992554,0.939974,-0.894739,-1.019809, + 0.187438,-0.340915,-0.921219,0.93066,-1.216516,-0.831196, + 0.372063,-0.134052,-0.918477,0.530629,-1.316423,-0.929842, + 0.304293,-0.024391,-0.952266,0.544825,-1.133123,-1.096902, + 0.187438,-0.340915,-0.921219,0.93066,-1.216516,-0.831196, + 0.304293,-0.024391,-0.952266,0.544825,-1.133123,-1.096902, + 0.114032,-0.218132,-0.969234,0.956456,-1.070504,-0.921063, + 0.25339,-0.287519,-0.923648,0.922703,-1.296032,-0.728307, + 0.424286,-0.254348,-0.869073,0.538756,-1.408602,-0.764911, + 0.372063,-0.134052,-0.918477,0.530629,-1.316423,-0.929842, + 0.25339,-0.287519,-0.923648,0.922703,-1.296032,-0.728307, + 0.372063,-0.134052,-0.918477,0.530629,-1.316423,-0.929842, + 0.187438,-0.340915,-0.921219,0.93066,-1.216516,-0.831196, + 0.23972,-0.400363,-0.884445,0.912699,-1.455066,-0.576185, + 0.420794,-0.405156,-0.811653,0.489819,-1.524947,-0.672392, + 0.424286,-0.254348,-0.869073,0.538756,-1.408602,-0.764911, + 0.23972,-0.400363,-0.884445,0.912699,-1.455066,-0.576185, + 0.424286,-0.254348,-0.869073,0.538756,-1.408602,-0.764911, + 0.25339,-0.287519,-0.923648,0.922703,-1.296032,-0.728307, + 0.213167,-0.525559,-0.823619,0.912989,-1.499314,-0.419547, + 0.383978,-0.566345,-0.729256,0.480235,-1.631521,-0.401961, + 0.420794,-0.405156,-0.811653,0.489819,-1.524947,-0.672392, + 0.213167,-0.525559,-0.823619,0.912989,-1.499314,-0.419547, + 0.420794,-0.405156,-0.811653,0.489819,-1.524947,-0.672392, + 0.23972,-0.400363,-0.884445,0.912699,-1.455066,-0.576185, + 0.92802,-0.37253,0,0.927497,-1.558489,0, + 0.226963,-0.973903,0,0.44655,-1.67295,0, + 0.383978,-0.566345,-0.729256,0.480235,-1.631521,-0.401961, + 0.92802,-0.37253,0,0.927497,-1.558489,0, + 0.383978,-0.566345,-0.729256,0.480235,-1.631521,-0.401961, + 0.213167,-0.525559,-0.823619,0.912989,-1.499314,-0.419547, + 0.335626,-0.735806,-0.588171,-0.221516,1.686349,-0.151403, + 0.235033,-0.721825,-0.650944,-0.559706,1.69418,-0.186107, + -0.009814,-0.999952,0,-0.547248,1.742126,0, + 0.335626,-0.735806,-0.588171,-0.221516,1.686349,-0.151403, + -0.009814,-0.999952,0,-0.547248,1.742126,0, + -0.039092,-0.999236,0,-0.228904,1.734267,0, + 0.303379,-0.73119,-0.611002,-0.267035,1.627058,-0.266577, + 0.244106,-0.79539,-0.554768,-0.557624,1.641278,-0.271462, + 0.235033,-0.721825,-0.650944,-0.559706,1.69418,-0.186107, + 0.303379,-0.73119,-0.611002,-0.267035,1.627058,-0.266577, + 0.235033,-0.721825,-0.650944,-0.559706,1.69418,-0.186107, + 0.335626,-0.735806,-0.588171,-0.221516,1.686349,-0.151403, + 0.298349,-0.828641,-0.473647,-0.247999,1.565146,-0.389142, + 0.213948,-0.943673,-0.252405,-0.626493,1.585426,-0.443136, + 0.244106,-0.79539,-0.554768,-0.557624,1.641278,-0.271462, + 0.298349,-0.828641,-0.473647,-0.247999,1.565146,-0.389142, + 0.244106,-0.79539,-0.554768,-0.557624,1.641278,-0.271462, + 0.303379,-0.73119,-0.611002,-0.267035,1.627058,-0.266577, + 0.267279,-0.944479,-0.191107,-0.179548,1.471301,-0.544513, + 0.190577,-0.970681,-0.146488,-0.597781,1.48962,-0.641047, + 0.213948,-0.943673,-0.252405,-0.626493,1.585426,-0.443136, + 0.267279,-0.944479,-0.191107,-0.179548,1.471301,-0.544513, + 0.213948,-0.943673,-0.252405,-0.626493,1.585426,-0.443136, + 0.298349,-0.828641,-0.473647,-0.247999,1.565146,-0.389142, + 0.029207,0.916877,-0.398099,-0.192546,1.305535,-0.70008, + 0.048754,0.934073,-0.353738,-0.674657,1.333008,-0.761059, + 0.190577,-0.970681,-0.146488,-0.597781,1.48962,-0.641047, + 0.029207,0.916877,-0.398099,-0.192546,1.305535,-0.70008, + 0.190577,-0.970681,-0.146488,-0.597781,1.48962,-0.641047, + 0.267279,-0.944479,-0.191107,-0.179548,1.471301,-0.544513, + 0.051939,0.876473,-0.478641,-0.406155,1.005088,-0.971088, + 0.081223,0.915345,-0.394394,-0.910602,1.204118,-0.83774, + 0.048754,0.934073,-0.353738,-0.674657,1.333008,-0.761059, + 0.051939,0.876473,-0.478641,-0.406155,1.005088,-0.971088, + 0.048754,0.934073,-0.353738,-0.674657,1.333008,-0.761059, + 0.029207,0.916877,-0.398099,-0.192546,1.305535,-0.70008, + 0.092427,0.86666,-0.490263,-0.11519,0.458427,-1.346197, + 0.120116,0.912706,-0.390565,-0.969076,0.901205,-1.146223, + 0.081223,0.915345,-0.394394,-0.910602,1.204118,-0.83774, + 0.092427,0.86666,-0.490263,-0.11519,0.458427,-1.346197, + 0.081223,0.915345,-0.394394,-0.910602,1.204118,-0.83774, + 0.051939,0.876473,-0.478641,-0.406155,1.005088,-0.971088, + 0.129186,0.757141,-0.64035,0.005537,0.163519,-1.472265, + 0.1717,0.74071,-0.649514,-0.752416,0.438132,-1.467349, + 0.120116,0.912706,-0.390565,-0.969076,0.901205,-1.146223, + 0.129186,0.757141,-0.64035,0.005537,0.163519,-1.472265, + 0.120116,0.912706,-0.390565,-0.969076,0.901205,-1.146223, + 0.092427,0.86666,-0.490263,-0.11519,0.458427,-1.346197, + 0.101272,0.634315,-0.766413,0.018086,0.002865,-1.523199, + 0.167704,0.495674,-0.852164,-0.645496,0.179261,-1.584316, + 0.1717,0.74071,-0.649514,-0.752416,0.438132,-1.467349, + 0.101272,0.634315,-0.766413,0.018086,0.002865,-1.523199, + 0.1717,0.74071,-0.649514,-0.752416,0.438132,-1.467349, + 0.129186,0.757141,-0.64035,0.005537,0.163519,-1.472265, + 0.089104,0.59547,-0.798421,0.034087,-0.225059,-1.542949, + 0.140536,0.558684,-0.817388,-0.536767,-0.144454,-1.682232, + 0.167704,0.495674,-0.852164,-0.645496,0.179261,-1.584316, + 0.089104,0.59547,-0.798421,0.034087,-0.225059,-1.542949, + 0.167704,0.495674,-0.852164,-0.645496,0.179261,-1.584316, + 0.101272,0.634315,-0.766413,0.018086,0.002865,-1.523199, + 0.147941,0.53134,-0.834141,0.010486,-0.502317,-1.576297, + 0.136523,0.621747,-0.771228,-0.533528,-0.58228,-1.701405, + 0.140536,0.558684,-0.817388,-0.536767,-0.144454,-1.682232, + 0.147941,0.53134,-0.834141,0.010486,-0.502317,-1.576297, + 0.140536,0.558684,-0.817388,-0.536767,-0.144454,-1.682232, + 0.089104,0.59547,-0.798421,0.034087,-0.225059,-1.542949, + 0.206788,0.399922,-0.892917,0.021051,-0.831931,-1.511548, + 0.100131,0.509748,-0.854477,-0.505045,-0.913827,-1.645612, + 0.136523,0.621747,-0.771228,-0.533528,-0.58228,-1.701405, + 0.206788,0.399922,-0.892917,0.021051,-0.831931,-1.511548, + 0.136523,0.621747,-0.771228,-0.533528,-0.58228,-1.701405, + 0.147941,0.53134,-0.834141,0.010486,-0.502317,-1.576297, + 0.246802,0.252523,-0.935586,-0.04157,-1.143825,-1.395176, + 0.063174,0.351351,-0.93411,-0.487217,-1.193519,-1.504026, + 0.100131,0.509748,-0.854477,-0.505045,-0.913827,-1.645612, + 0.246802,0.252523,-0.935586,-0.04157,-1.143825,-1.395176, + 0.100131,0.509748,-0.854477,-0.505045,-0.913827,-1.645612, + 0.206788,0.399922,-0.892917,0.021051,-0.831931,-1.511548, + 0.274567,0.116527,-0.954481,-0.071941,-1.346991,-1.237379, + 0.078896,0.195617,-0.977502,-0.524231,-1.399266,-1.313019, + 0.063174,0.351351,-0.93411,-0.487217,-1.193519,-1.504026, + 0.274567,0.116527,-0.954481,-0.071941,-1.346991,-1.237379, + 0.063174,0.351351,-0.93411,-0.487217,-1.193519,-1.504026, + 0.246802,0.252523,-0.935586,-0.04157,-1.143825,-1.395176, + 0.303729,-0.050718,-0.951408,-0.0723,-1.450245,-1.087397, + 0.097816,-0.016117,-0.995074,-0.526127,-1.495,-1.167736, + 0.078896,0.195617,-0.977502,-0.524231,-1.399266,-1.313019, + 0.303729,-0.050718,-0.951408,-0.0723,-1.450245,-1.087397, + 0.078896,0.195617,-0.977502,-0.524231,-1.399266,-1.313019, + 0.274567,0.116527,-0.954481,-0.071941,-1.346991,-1.237379, + 0.33122,-0.270106,-0.904067,-0.063012,-1.583021,-0.865082, + 0.10737,-0.293005,-0.950063,-0.535144,-1.615983,-0.920556, + 0.097816,-0.016117,-0.995074,-0.526127,-1.495,-1.167736, + 0.33122,-0.270106,-0.904067,-0.063012,-1.583021,-0.865082, + 0.097816,-0.016117,-0.995074,-0.526127,-1.495,-1.167736, + 0.303729,-0.050718,-0.951408,-0.0723,-1.450245,-1.087397, + 0.004725,-0.680391,-0.732834,-0.894132,1.712652,-0.151911, + -0.267766,-0.862787,-0.428835,-1.215563,1.757097,-0.133494, + -0.065586,-0.997847,0,-1.179474,1.786649,0, + 0.004725,-0.680391,-0.732834,-0.894132,1.712652,-0.151911, + -0.065586,-0.997847,0,-1.179474,1.786649,0, + -0.098179,0.995169,0,-0.866132,1.75467,0, + 0.034172,-0.858604,-0.511498,-0.954897,1.677544,-0.293034, + -0.263452,-0.648591,-0.714089,-1.227613,1.709095,-0.276029, + -0.267766,-0.862787,-0.428835,-1.215563,1.757097,-0.133494, + 0.034172,-0.858604,-0.511498,-0.954897,1.677544,-0.293034, + -0.267766,-0.862787,-0.428835,-1.215563,1.757097,-0.133494, + 0.004725,-0.680391,-0.732834,-0.894132,1.712652,-0.151911, + 0.037423,-0.986705,-0.158154,-1.017767,1.607824,-0.541965, + -0.301558,-0.77828,-0.550766,-1.292756,1.656509,-0.51403, + -0.263452,-0.648591,-0.714089,-1.227613,1.709095,-0.276029, + 0.037423,-0.986705,-0.158154,-1.017767,1.607824,-0.541965, + -0.263452,-0.648591,-0.714089,-1.227613,1.709095,-0.276029, + 0.034172,-0.858604,-0.511498,-0.954897,1.677544,-0.293034, + 0.013768,-0.992402,-0.122267,-1.04607,1.509097,-0.76106, + -0.154129,-0.981148,-0.116585,-1.338488,1.613735,-0.725441, + -0.301558,-0.77828,-0.550766,-1.292756,1.656509,-0.51403, + 0.013768,-0.992402,-0.122267,-1.04607,1.509097,-0.76106, + -0.301558,-0.77828,-0.550766,-1.292756,1.656509,-0.51403, + 0.037423,-0.986705,-0.158154,-1.017767,1.607824,-0.541965, + 0.076524,0.950336,-0.301672,-1.115594,1.39238,-0.819623, + 0.095331,0.952335,-0.289775,-1.403848,1.533059,-0.902827, + -0.154129,-0.981148,-0.116585,-1.338488,1.613735,-0.725441, + 0.076524,0.950336,-0.301672,-1.115594,1.39238,-0.819623, + -0.154129,-0.981148,-0.116585,-1.338488,1.613735,-0.725441, + 0.013768,-0.992402,-0.122267,-1.04607,1.509097,-0.76106, + 0.100598,0.942931,-0.317428,-1.278903,1.192051,-0.946843, + 0.10291,0.954344,-0.280422,-1.551526,1.400025,-1.050193, + 0.095331,0.952335,-0.289775,-1.403848,1.533059,-0.902827, + 0.100598,0.942931,-0.317428,-1.278903,1.192051,-0.946843, + 0.095331,0.952335,-0.289775,-1.403848,1.533059,-0.902827, + 0.076524,0.950336,-0.301672,-1.115594,1.39238,-0.819623, + 0.150328,0.92948,-0.336851,-1.200768,0.978822,-1.103391, + 0.172251,0.950689,-0.257916,-1.552899,1.128654,-1.15104, + 0.10291,0.954344,-0.280422,-1.551526,1.400025,-1.050193, + 0.150328,0.92948,-0.336851,-1.200768,0.978822,-1.103391, + 0.10291,0.954344,-0.280422,-1.551526,1.400025,-1.050193, + 0.100598,0.942931,-0.317428,-1.278903,1.192051,-0.946843, + 0.235667,0.756618,-0.60991,-1.147922,0.807955,-1.254191, + 0.28101,0.853935,-0.437982,-1.454529,0.875045,-1.238858, + 0.172251,0.950689,-0.257916,-1.552899,1.128654,-1.15104, + 0.235667,0.756618,-0.60991,-1.147922,0.807955,-1.254191, + 0.172251,0.950689,-0.257916,-1.552899,1.128654,-1.15104, + 0.150328,0.92948,-0.336851,-1.200768,0.978822,-1.103391, + 0.305452,0.425365,-0.851918,-1.120716,0.424016,-1.45699, + 0.381239,0.555717,-0.738807,-1.405685,0.573835,-1.352181, + 0.28101,0.853935,-0.437982,-1.454529,0.875045,-1.238858, + 0.305452,0.425365,-0.851918,-1.120716,0.424016,-1.45699, + 0.28101,0.853935,-0.437982,-1.454529,0.875045,-1.238858, + 0.235667,0.756618,-0.60991,-1.147922,0.807955,-1.254191, + 0.325482,0.443544,-0.835063,-1.077307,0.165008,-1.553393, + 0.376012,0.360026,-0.853813,-1.479588,0.295746,-1.440042, + 0.381239,0.555717,-0.738807,-1.405685,0.573835,-1.352181, + 0.325482,0.443544,-0.835063,-1.077307,0.165008,-1.553393, + 0.381239,0.555717,-0.738807,-1.405685,0.573835,-1.352181, + 0.305452,0.425365,-0.851918,-1.120716,0.424016,-1.45699, + 0.242426,0.58207,-0.77616,-1.053434,-0.342553,-1.690245, + 0.207079,0.373404,-0.904261,-1.489699,-0.024215,-1.510987, + 0.376012,0.360026,-0.853813,-1.479588,0.295746,-1.440042, + 0.242426,0.58207,-0.77616,-1.053434,-0.342553,-1.690245, + 0.376012,0.360026,-0.853813,-1.479588,0.295746,-1.440042, + 0.325482,0.443544,-0.835063,-1.077307,0.165008,-1.553393, + 0.070189,0.510248,-0.857158,-1.077209,-0.869649,-1.633144, + -0.045242,0.348413,-0.936249,-1.395501,-0.698702,-1.553257, + 0.207079,0.373404,-0.904261,-1.489699,-0.024215,-1.510987, + 0.070189,0.510248,-0.857158,-1.077209,-0.869649,-1.633144, + 0.207079,0.373404,-0.904261,-1.489699,-0.024215,-1.510987, + 0.242426,0.58207,-0.77616,-1.053434,-0.342553,-1.690245, + -0.078623,0.370994,-0.925301,-1.061272,-1.141877,-1.49623, + -0.212948,0.334057,-0.918182,-1.376176,-0.948757,-1.451608, + -0.045242,0.348413,-0.936249,-1.395501,-0.698702,-1.553257, + -0.078623,0.370994,-0.925301,-1.061272,-1.141877,-1.49623, + -0.045242,0.348413,-0.936249,-1.395501,-0.698702,-1.553257, + 0.070189,0.510248,-0.857158,-1.077209,-0.869649,-1.633144, + -0.123389,0.256577,-0.958615,-1.001366,-1.335897,-1.353338, + -0.282152,0.285245,-0.915983,-1.402349,-1.127845,-1.309055, + -0.212948,0.334057,-0.918182,-1.376176,-0.948757,-1.451608, + -0.123389,0.256577,-0.958615,-1.001366,-1.335897,-1.353338, + -0.212948,0.334057,-0.918182,-1.376176,-0.948757,-1.451608, + -0.078623,0.370994,-0.925301,-1.061272,-1.141877,-1.49623, + -0.165685,0.059692,-0.98437,-0.952525,-1.440582,-1.16865, + -0.326048,0.118611,-0.937883,-1.407658,-1.236026,-1.11293, + -0.282152,0.285245,-0.915983,-1.402349,-1.127845,-1.309055, + -0.165685,0.059692,-0.98437,-0.952525,-1.440582,-1.16865, + -0.282152,0.285245,-0.915983,-1.402349,-1.127845,-1.309055, + -0.123389,0.256577,-0.958615,-1.001366,-1.335897,-1.353338, + -0.031021,0.098798,-0.994624,1.644178,-0.857872,-1.208494, + -0.039079,0.203923,-0.978207,1.640095,-0.674556,-1.246804, + 0.097864,0.250653,-0.963118,2.013534,-0.662303,-1.191491, + 0.12742,0.021045,-0.991626,1.462507,1.745481,-0.222394, + 0.779025,-0.626993,0,1.456656,1.785879,0, + -0.720176,-0.693792,0,1.794465,1.787719,0, + 0.12742,0.021045,-0.991626,1.462507,1.745481,-0.222394, + -0.720176,-0.693792,0,1.794465,1.787719,0, + 0.513731,-0.239493,-0.823847,1.807583,1.756546,-0.177627, + 0.206882,-0.117024,-0.971342,1.483832,1.697594,-0.288781, + 0.12742,0.021045,-0.991626,1.462507,1.745481,-0.222394, + 0.513731,-0.239493,-0.823847,1.807583,1.756546,-0.177627, + 0.206882,-0.117024,-0.971342,1.483832,1.697594,-0.288781, + 0.513731,-0.239493,-0.823847,1.807583,1.756546,-0.177627, + 0.506924,-0.406124,-0.760323,1.798719,1.714447,-0.259352, + 0.218538,-0.213954,-0.952084,1.497138,1.618935,-0.401108, + 0.206882,-0.117024,-0.971342,1.483832,1.697594,-0.288781, + 0.506924,-0.406124,-0.760323,1.798719,1.714447,-0.259352, + 0.218538,-0.213954,-0.952084,1.497138,1.618935,-0.401108, + 0.506924,-0.406124,-0.760323,1.798719,1.714447,-0.259352, + 0.552632,-0.484765,-0.677938,1.821946,1.618209,-0.403751, + 0.304965,-0.136677,-0.942505,1.504951,1.483493,-0.585976, + 0.218538,-0.213954,-0.952084,1.497138,1.618935,-0.401108, + 0.552632,-0.484765,-0.677938,1.821946,1.618209,-0.403751, + 0.304965,-0.136677,-0.942505,1.504951,1.483493,-0.585976, + 0.552632,-0.484765,-0.677938,1.821946,1.618209,-0.403751, + 0.696414,-0.392791,-0.600602,1.859443,1.450393,-0.632222, + -0.061264,0.921927,-0.382487,1.517126,1.334367,-0.741076, + 0.304965,-0.136677,-0.942505,1.504951,1.483493,-0.585976, + 0.696414,-0.392791,-0.600602,1.859443,1.450393,-0.632222, + -0.061264,0.921927,-0.382487,1.517126,1.334367,-0.741076, + 0.696414,-0.392791,-0.600602,1.859443,1.450393,-0.632222, + 0.026499,0.942993,-0.331757,1.958254,1.130271,-0.861813, + -0.070642,0.834207,-0.546908,1.570685,0.938327,-0.989108, + -0.061264,0.921927,-0.382487,1.517126,1.334367,-0.741076, + 0.026499,0.942993,-0.331757,1.958254,1.130271,-0.861813, + -0.070642,0.834207,-0.546908,1.570685,0.938327,-0.989108, + 0.026499,0.942993,-0.331757,1.958254,1.130271,-0.861813, + 0.019336,0.837694,-0.545798,1.975941,0.827957,-1.018423, + -0.055544,0.828008,-0.557959,1.582203,0.771083,-1.06818, + -0.070642,0.834207,-0.546908,1.570685,0.938327,-0.989108, + 0.019336,0.837694,-0.545798,1.975941,0.827957,-1.018423, + -0.047373,0.758242,-0.65025,1.63008,0.420236,-1.172369, + -0.055544,0.828008,-0.557959,1.582203,0.771083,-1.06818, + 0.019336,0.837694,-0.545798,1.975941,0.827957,-1.018423, + -0.047373,0.758242,-0.65025,1.63008,0.420236,-1.172369, + 0.019336,0.837694,-0.545798,1.975941,0.827957,-1.018423, + 0.052979,0.780732,-0.622616,2.023441,0.529338,-1.144399, + -0.046579,0.627301,-0.777383,1.649027,0.224458,-1.211969, + -0.047373,0.758242,-0.65025,1.63008,0.420236,-1.172369, + 0.052979,0.780732,-0.622616,2.023441,0.529338,-1.144399, + -0.046579,0.627301,-0.777383,1.649027,0.224458,-1.211969, + 0.052979,0.780732,-0.622616,2.023441,0.529338,-1.144399, + 0.115383,0.694944,-0.709746,2.0817,0.283249,-1.259461, + -0.05128,0.509983,-0.858655,1.660355,0.019397,-1.246002, + -0.046579,0.627301,-0.777383,1.649027,0.224458,-1.211969, + 0.115383,0.694944,-0.709746,2.0817,0.283249,-1.259461, + -0.05128,0.509983,-0.858655,1.660355,0.019397,-1.246002, + 0.115383,0.694944,-0.709746,2.0817,0.283249,-1.259461, + 0.146937,0.551946,-0.820832,2.14179,-0.055306,-1.295565, + -0.02226,0.394285,-0.918719,1.664159,-0.189659,-1.266729, + -0.05128,0.509983,-0.858655,1.660355,0.019397,-1.246002, + 0.146937,0.551946,-0.820832,2.14179,-0.055306,-1.295565, + -0.02226,0.394285,-0.918719,1.664159,-0.189659,-1.266729, + 0.146937,0.551946,-0.820832,2.14179,-0.055306,-1.295565, + 0.12555,0.440005,-0.889176,2.136269,-0.187666,-1.278057, + -0.026262,0.311275,-0.949957,1.678622,-0.410061,-1.291177, + -0.02226,0.394285,-0.918719,1.664159,-0.189659,-1.266729, + 0.12555,0.440005,-0.889176,2.136269,-0.187666,-1.278057, + -0.026262,0.311275,-0.949957,1.678622,-0.410061,-1.291177, + 0.12555,0.440005,-0.889176,2.136269,-0.187666,-1.278057, + 0.10998,0.376752,-0.919762,2.108912,-0.357128,-1.259691, + -0.039079,0.203923,-0.978207,1.640095,-0.674556,-1.246804, + -0.026262,0.311275,-0.949957,1.678622,-0.410061,-1.291177, + 0.10998,0.376752,-0.919762,2.108912,-0.357128,-1.259691, + -0.039079,0.203923,-0.978207,1.640095,-0.674556,-1.246804, + 0.10998,0.376752,-0.919762,2.108912,-0.357128,-1.259691, + 0.097864,0.250653,-0.963118,2.013534,-0.662303,-1.191491, + -0.742985,0.015712,-0.669123,2.222082,-0.957342,-1.014137, + -0.809154,0.004832,-0.587577,2.158585,-0.955809,-1.113647, + -0.965506,-0.176768,0.191185,2.058189,-0.931238,-1.163518, + -0.742985,0.015712,-0.669123,2.222082,-0.957342,-1.014137, + -0.965506,-0.176768,0.191185,2.058189,-0.931238,-1.163518, + 0.097864,0.250653,-0.963118,2.013534,-0.662303,-1.191491, + 0.561574,-0.148323,-0.814024,2.245624,-0.864372,-0.995778, + -0.742985,0.015712,-0.669123,2.222082,-0.957342,-1.014137, + 0.097864,0.250653,-0.963118,2.013534,-0.662303,-1.191491, + 0.859237,-0.17312,-0.481395,1.635139,-0.965221,-1.184968, + -0.031021,0.098798,-0.994624,1.644178,-0.857872,-1.208494, + 0.097864,0.250653,-0.963118,2.013534,-0.662303,-1.191491, + -0.942755,-0.29871,0.148273,1.867657,-0.920633,-1.206933, + 0.859237,-0.17312,-0.481395,1.635139,-0.965221,-1.184968, + 0.097864,0.250653,-0.963118,2.013534,-0.662303,-1.191491, + -0.965506,-0.176768,0.191185,2.058189,-0.931238,-1.163518, + -0.942755,-0.29871,0.148273,1.867657,-0.920633,-1.206933, + 0.097864,0.250653,-0.963118,2.013534,-0.662303,-1.191491, + -0.560667,-0.828041,0,1.604939,-1.556997,0, + -0.217942,-0.897186,0.384134,1.721211,-1.590185,-0.601932, + -0.084936,-0.226589,0.97028,1.963153,-1.588839,-0.612861, + -0.560667,-0.828041,0,1.604939,-1.556997,0, + -0.084936,-0.226589,0.97028,1.963153,-1.588839,-0.612861, + -0.034649,0.9994,0,1.920432,-1.567396,0, + -0.148631,-0.373855,-0.915501,1.210555,-1.460061,-0.576841, + -0.305786,-0.232288,-0.923329,1.19204,-1.330605,-0.678707, + 0.080262,-0.270606,-0.959339,1.328862,-1.352627,-0.758733, + -0.148631,-0.373855,-0.915501,1.210555,-1.460061,-0.576841, + 0.080262,-0.270606,-0.959339,1.328862,-1.352627,-0.758733, + -0.794709,-0.185222,0.578041,1.451825,-1.576856,-0.702758, + -0.185127,-0.491394,-0.851035,1.223415,-1.532658,-0.434522, + -0.148631,-0.373855,-0.915501,1.210555,-1.460061,-0.576841, + -0.794709,-0.185222,0.578041,1.451825,-1.576856,-0.702758, + -0.185127,-0.491394,-0.851035,1.223415,-1.532658,-0.434522, + -0.794709,-0.185222,0.578041,1.451825,-1.576856,-0.702758, + -0.493424,-0.165611,0.853877,1.599889,-1.595526,-0.623185, + -0.084936,-0.226589,0.97028,1.963153,-1.588839,-0.612861, + 0.552828,-0.750794,-0.36151,2.0482,-1.581983,-0.555832, + -0.034649,0.9994,0,1.920432,-1.567396,0, + -0.560667,-0.828041,0,1.604939,-1.556997,0, + 0.770209,-0.637792,0,1.289448,-1.546597,0, + -0.185127,-0.491394,-0.851035,1.223415,-1.532658,-0.434522, + -0.560667,-0.828041,0,1.604939,-1.556997,0, + -0.185127,-0.491394,-0.851035,1.223415,-1.532658,-0.434522, + -0.493424,-0.165611,0.853877,1.599889,-1.595526,-0.623185, + -0.560667,-0.828041,0,1.604939,-1.556997,0, + -0.493424,-0.165611,0.853877,1.599889,-1.595526,-0.623185, + -0.217942,-0.897186,0.384134,1.721211,-1.590185,-0.601932, + -0.305786,-0.232288,-0.923329,1.19204,-1.330605,-0.678707, + 0.102263,-0.969566,-0.222452,1.219163,-1.218342,-0.823029, + 0.02992,-0.202031,-0.978922,1.348219,-1.282064,-0.845204, + -0.305786,-0.232288,-0.923329,1.19204,-1.330605,-0.678707, + 0.02992,-0.202031,-0.978922,1.348219,-1.282064,-0.845204, + 0.080262,-0.270606,-0.959339,1.328862,-1.352627,-0.758733, + 0.152876,-0.742504,-0.652163,1.252961,-0.928825,-1.001643, + 0.184661,-0.694307,-0.695585,1.373216,-0.56462,-1.106245, + 0.045651,-0.004499,-0.998947,1.337875,-0.945716,-1.021299, + 0.120054,-0.825719,-0.551157,1.230116,-1.085439,-0.894543, + 0.152876,-0.742504,-0.652163,1.252961,-0.928825,-1.001643, + 0.045651,-0.004499,-0.998947,1.337875,-0.945716,-1.021299, + 0.120054,-0.825719,-0.551157,1.230116,-1.085439,-0.894543, + 0.045651,-0.004499,-0.998947,1.337875,-0.945716,-1.021299, + 0.023392,-0.110333,-0.993619,1.310865,-1.136322,-0.914838, + 0.102263,-0.969566,-0.222452,1.219163,-1.218342,-0.823029, + 0.120054,-0.825719,-0.551157,1.230116,-1.085439,-0.894543, + 0.023392,-0.110333,-0.993619,1.310865,-1.136322,-0.914838, + 0.102263,-0.969566,-0.222452,1.219163,-1.218342,-0.823029, + 0.023392,-0.110333,-0.993619,1.310865,-1.136322,-0.914838, + 0.02992,-0.202031,-0.978922,1.348219,-1.282064,-0.845204, + -0.031021,0.098798,-0.994624,1.644178,-0.857872,-1.208494, + 0.859237,-0.17312,-0.481395,1.635139,-0.965221,-1.184968, + 0.714393,-0.109998,-0.691045,1.536037,-0.985876,-1.185597, + -0.039079,0.203923,-0.978207,1.640095,-0.674556,-1.246804, + -0.031021,0.098798,-0.994624,1.644178,-0.857872,-1.208494, + 0.714393,-0.109998,-0.691045,1.536037,-0.985876,-1.185597, + -0.039079,0.203923,-0.978207,1.640095,-0.674556,-1.246804, + 0.714393,-0.109998,-0.691045,1.536037,-0.985876,-1.185597, + 0.419396,-0.035927,-0.907092,1.428883,-0.98669,-1.133905, + 0.184661,-0.694307,-0.695585,1.373216,-0.56462,-1.106245, + -0.026262,0.311275,-0.949957,1.678622,-0.410061,-1.291177, + -0.039079,0.203923,-0.978207,1.640095,-0.674556,-1.246804, + 0.184661,-0.694307,-0.695585,1.373216,-0.56462,-1.106245, + -0.039079,0.203923,-0.978207,1.640095,-0.674556,-1.246804, + 0.419396,-0.035927,-0.907092,1.428883,-0.98669,-1.133905, + 0.779025,-0.626993,0,1.456656,1.785879,0, + 0.12742,0.021045,-0.991626,1.462507,1.745481,-0.222394, + 0.981421,-0.191868,0,0.733818,1.740873,0, + -0.185127,-0.491394,-0.851035,1.223415,-1.532658,-0.434522, + 0.770209,-0.637792,0,1.289448,-1.546597,0, + 0.92802,-0.37253,0,0.927497,-1.558489,0, + -0.185127,-0.491394,-0.851035,1.223415,-1.532658,-0.434522, + 0.92802,-0.37253,0,0.927497,-1.558489,0, + 0.213167,-0.525559,-0.823619,0.912989,-1.499314,-0.419547, + -0.148631,-0.373855,-0.915501,1.210555,-1.460061,-0.576841, + -0.185127,-0.491394,-0.851035,1.223415,-1.532658,-0.434522, + 0.213167,-0.525559,-0.823619,0.912989,-1.499314,-0.419547, + -0.148631,-0.373855,-0.915501,1.210555,-1.460061,-0.576841, + 0.213167,-0.525559,-0.823619,0.912989,-1.499314,-0.419547, + 0.23972,-0.400363,-0.884445,0.912699,-1.455066,-0.576185, + -0.305786,-0.232288,-0.923329,1.19204,-1.330605,-0.678707, + -0.148631,-0.373855,-0.915501,1.210555,-1.460061,-0.576841, + 0.23972,-0.400363,-0.884445,0.912699,-1.455066,-0.576185, + -0.305786,-0.232288,-0.923329,1.19204,-1.330605,-0.678707, + 0.23972,-0.400363,-0.884445,0.912699,-1.455066,-0.576185, + 0.25339,-0.287519,-0.923648,0.922703,-1.296032,-0.728307, + 0.102263,-0.969566,-0.222452,1.219163,-1.218342,-0.823029, + -0.305786,-0.232288,-0.923329,1.19204,-1.330605,-0.678707, + 0.25339,-0.287519,-0.923648,0.922703,-1.296032,-0.728307, + 0.102263,-0.969566,-0.222452,1.219163,-1.218342,-0.823029, + 0.25339,-0.287519,-0.923648,0.922703,-1.296032,-0.728307, + 0.187438,-0.340915,-0.921219,0.93066,-1.216516,-0.831196, + 0.120054,-0.825719,-0.551157,1.230116,-1.085439,-0.894543, + 0.102263,-0.969566,-0.222452,1.219163,-1.218342,-0.823029, + 0.187438,-0.340915,-0.921219,0.93066,-1.216516,-0.831196, + 0.120054,-0.825719,-0.551157,1.230116,-1.085439,-0.894543, + 0.187438,-0.340915,-0.921219,0.93066,-1.216516,-0.831196, + 0.114032,-0.218132,-0.969234,0.956456,-1.070504,-0.921063, + 0.152876,-0.742504,-0.652163,1.252961,-0.928825,-1.001643, + 0.120054,-0.825719,-0.551157,1.230116,-1.085439,-0.894543, + 0.114032,-0.218132,-0.969234,0.956456,-1.070504,-0.921063, + 0.152876,-0.742504,-0.652163,1.252961,-0.928825,-1.001643, + 0.114032,-0.218132,-0.969234,0.956456,-1.070504,-0.921063, + 0.10833,0.05569,-0.992554,0.939974,-0.894739,-1.019809, + 0.184661,-0.694307,-0.695585,1.373216,-0.56462,-1.106245, + 0.152876,-0.742504,-0.652163,1.252961,-0.928825,-1.001643, + 0.10833,0.05569,-0.992554,0.939974,-0.894739,-1.019809, + 0.184661,-0.694307,-0.695585,1.373216,-0.56462,-1.106245, + 0.10833,0.05569,-0.992554,0.939974,-0.894739,-1.019809, + 0.107989,0.168108,-0.979836,0.948819,-0.638568,-1.102958, + 0.184661,-0.694307,-0.695585,1.373216,-0.56462,-1.106245, + 0.107989,0.168108,-0.979836,0.948819,-0.638568,-1.102958, + 0.088722,0.251367,-0.963817,0.97453,-0.525273,-1.140353, + -0.026262,0.311275,-0.949957,1.678622,-0.410061,-1.291177, + 0.184661,-0.694307,-0.695585,1.373216,-0.56462,-1.106245, + 0.088722,0.251367,-0.963817,0.97453,-0.525273,-1.140353, + -0.026262,0.311275,-0.949957,1.678622,-0.410061,-1.291177, + 0.088722,0.251367,-0.963817,0.97453,-0.525273,-1.140353, + 0.060533,0.377837,-0.923891,0.960321,-0.308052,-1.243133, + -0.02226,0.394285,-0.918719,1.664159,-0.189659,-1.266729, + -0.026262,0.311275,-0.949957,1.678622,-0.410061,-1.291177, + 0.060533,0.377837,-0.923891,0.960321,-0.308052,-1.243133, + -0.02226,0.394285,-0.918719,1.664159,-0.189659,-1.266729, + 0.060533,0.377837,-0.923891,0.960321,-0.308052,-1.243133, + 0.016737,0.497476,-0.867316,0.943855,-0.101127,-1.274771, + -0.05128,0.509983,-0.858655,1.660355,0.019397,-1.246002, + -0.02226,0.394285,-0.918719,1.664159,-0.189659,-1.266729, + 0.016737,0.497476,-0.867316,0.943855,-0.101127,-1.274771, + -0.05128,0.509983,-0.858655,1.660355,0.019397,-1.246002, + 0.016737,0.497476,-0.867316,0.943855,-0.101127,-1.274771, + -0.024013,0.58573,-0.810151,0.950215,0.042751,-1.256188, + -0.046579,0.627301,-0.777383,1.649027,0.224458,-1.211969, + -0.05128,0.509983,-0.858655,1.660355,0.019397,-1.246002, + -0.024013,0.58573,-0.810151,0.950215,0.042751,-1.256188, + -0.046579,0.627301,-0.777383,1.649027,0.224458,-1.211969, + -0.024013,0.58573,-0.810151,0.950215,0.042751,-1.256188, + -0.057955,0.638634,-0.767325,0.927775,0.195225,-1.233043, + -0.047373,0.758242,-0.65025,1.63008,0.420236,-1.172369, + -0.046579,0.627301,-0.777383,1.649027,0.224458,-1.211969, + -0.057955,0.638634,-0.767325,0.927775,0.195225,-1.233043, + -0.047373,0.758242,-0.65025,1.63008,0.420236,-1.172369, + -0.057955,0.638634,-0.767325,0.927775,0.195225,-1.233043, + -0.069142,0.724976,-0.685295,0.939271,0.379986,-1.185872, + -0.055544,0.828008,-0.557959,1.582203,0.771083,-1.06818, + -0.047373,0.758242,-0.65025,1.63008,0.420236,-1.172369, + -0.069142,0.724976,-0.685295,0.939271,0.379986,-1.185872, + -0.055544,0.828008,-0.557959,1.582203,0.771083,-1.06818, + -0.069142,0.724976,-0.685295,0.939271,0.379986,-1.185872, + -0.06371,0.842533,-0.534864,0.921312,0.755659,-0.99933, + -0.070642,0.834207,-0.546908,1.570685,0.938327,-0.989108, + -0.055544,0.828008,-0.557959,1.582203,0.771083,-1.06818, + -0.06371,0.842533,-0.534864,0.921312,0.755659,-0.99933, + -0.070642,0.834207,-0.546908,1.570685,0.938327,-0.989108, + -0.06371,0.842533,-0.534864,0.921312,0.755659,-0.99933, + 0.791391,-0.43807,-0.426373,0.857323,0.985001,-0.874029, + -0.070642,0.834207,-0.546908,1.570685,0.938327,-0.989108, + 0.791391,-0.43807,-0.426373,0.857323,0.985001,-0.874029, + 0.623235,-0.257987,-0.738255,0.760722,1.205036,-0.700545, + -0.061264,0.921927,-0.382487,1.517126,1.334367,-0.741076, + -0.070642,0.834207,-0.546908,1.570685,0.938327,-0.989108, + 0.623235,-0.257987,-0.738255,0.760722,1.205036,-0.700545, + -0.061264,0.921927,-0.382487,1.517126,1.334367,-0.741076, + 0.623235,-0.257987,-0.738255,0.760722,1.205036,-0.700545, + 0.631747,-0.24686,-0.734817,0.725959,1.478055,-0.461804, + 0.304965,-0.136677,-0.942505,1.504951,1.483493,-0.585976, + -0.061264,0.921927,-0.382487,1.517126,1.334367,-0.741076, + 0.631747,-0.24686,-0.734817,0.725959,1.478055,-0.461804, + 0.304965,-0.136677,-0.942505,1.504951,1.483493,-0.585976, + 0.631747,-0.24686,-0.734817,0.725959,1.478055,-0.461804, + 0.659349,-0.248914,-0.709437,0.737904,1.604213,-0.281713, + 0.218538,-0.213954,-0.952084,1.497138,1.618935,-0.401108, + 0.304965,-0.136677,-0.942505,1.504951,1.483493,-0.585976, + 0.659349,-0.248914,-0.709437,0.737904,1.604213,-0.281713, + 0.206882,-0.117024,-0.971342,1.483832,1.697594,-0.288781, + 0.218538,-0.213954,-0.952084,1.497138,1.618935,-0.401108, + 0.659349,-0.248914,-0.709437,0.737904,1.604213,-0.281713, + 0.206882,-0.117024,-0.971342,1.483832,1.697594,-0.288781, + 0.659349,-0.248914,-0.709437,0.737904,1.604213,-0.281713, + 0.981421,-0.191868,0,0.733818,1.740873,0, + 0.12742,0.021045,-0.991626,1.462507,1.745481,-0.222394, + 0.206882,-0.117024,-0.971342,1.483832,1.697594,-0.288781, + 0.981421,-0.191868,0,0.733818,1.740873,0, + -0.208715,-0.624734,-0.752427,0.223642,1.684075,-0.160743, + 0.335626,-0.735806,-0.588171,-0.221516,1.686349,-0.151403, + -0.039092,-0.999236,0,-0.228904,1.734267,0, + -0.208715,-0.624734,-0.752427,0.223642,1.684075,-0.160743, + -0.039092,-0.999236,0,-0.228904,1.734267,0, + 0.566114,-0.824327,0,0.234527,1.730117,0, + -0.251063,-0.683027,-0.685888,0.23733,1.595746,-0.288672, + 0.303379,-0.73119,-0.611002,-0.267035,1.627058,-0.266577, + 0.335626,-0.735806,-0.588171,-0.221516,1.686349,-0.151403, + -0.251063,-0.683027,-0.685888,0.23733,1.595746,-0.288672, + 0.335626,-0.735806,-0.588171,-0.221516,1.686349,-0.151403, + -0.208715,-0.624734,-0.752427,0.223642,1.684075,-0.160743, + -0.252973,-0.819125,-0.51482,0.289039,1.496446,-0.430055, + 0.298349,-0.828641,-0.473647,-0.247999,1.565146,-0.389142, + 0.303379,-0.73119,-0.611002,-0.267035,1.627058,-0.266577, + -0.252973,-0.819125,-0.51482,0.289039,1.496446,-0.430055, + 0.303379,-0.73119,-0.611002,-0.267035,1.627058,-0.266577, + -0.251063,-0.683027,-0.685888,0.23733,1.595746,-0.288672, + -0.13716,-0.98063,-0.139827,0.305671,1.298417,-0.629719, + 0.267279,-0.944479,-0.191107,-0.179548,1.471301,-0.544513, + 0.298349,-0.828641,-0.473647,-0.247999,1.565146,-0.389142, + -0.13716,-0.98063,-0.139827,0.305671,1.298417,-0.629719, + 0.298349,-0.828641,-0.473647,-0.247999,1.565146,-0.389142, + -0.252973,-0.819125,-0.51482,0.289039,1.496446,-0.430055, + 0.007127,0.896038,-0.44392,0.243473,1.134082,-0.819993, + 0.029207,0.916877,-0.398099,-0.192546,1.305535,-0.70008, + 0.267279,-0.944479,-0.191107,-0.179548,1.471301,-0.544513, + 0.007127,0.896038,-0.44392,0.243473,1.134082,-0.819993, + 0.267279,-0.944479,-0.191107,-0.179548,1.471301,-0.544513, + -0.13716,-0.98063,-0.139827,0.305671,1.298417,-0.629719, + 0.009434,0.815301,-0.578961,0.316341,0.785311,-1.08626, + 0.051939,0.876473,-0.478641,-0.406155,1.005088,-0.971088, + 0.029207,0.916877,-0.398099,-0.192546,1.305535,-0.70008, + 0.009434,0.815301,-0.578961,0.316341,0.785311,-1.08626, + 0.029207,0.916877,-0.398099,-0.192546,1.305535,-0.70008, + 0.007127,0.896038,-0.44392,0.243473,1.134082,-0.819993, + 0.040473,0.760778,-0.647749,0.539252,0.353984,-1.254493, + 0.092427,0.86666,-0.490263,-0.11519,0.458427,-1.346197, + 0.051939,0.876473,-0.478641,-0.406155,1.005088,-0.971088, + 0.040473,0.760778,-0.647749,0.539252,0.353984,-1.254493, + 0.051939,0.876473,-0.478641,-0.406155,1.005088,-0.971088, + 0.009434,0.815301,-0.578961,0.316341,0.785311,-1.08626, + 0.080812,0.697931,-0.711591,0.53915,0.148262,-1.321014, + 0.129186,0.757141,-0.64035,0.005537,0.163519,-1.472265, + 0.092427,0.86666,-0.490263,-0.11519,0.458427,-1.346197, + 0.080812,0.697931,-0.711591,0.53915,0.148262,-1.321014, + 0.092427,0.86666,-0.490263,-0.11519,0.458427,-1.346197, + 0.040473,0.760778,-0.647749,0.539252,0.353984,-1.254493, + 0.09853,0.626571,-0.773111,0.516872,-0.020713,-1.356627, + 0.101272,0.634315,-0.766413,0.018086,0.002865,-1.523199, + 0.129186,0.757141,-0.64035,0.005537,0.163519,-1.472265, + 0.09853,0.626571,-0.773111,0.516872,-0.020713,-1.356627, + 0.129186,0.757141,-0.64035,0.005537,0.163519,-1.472265, + 0.080812,0.697931,-0.711591,0.53915,0.148262,-1.321014, + 0.111825,0.518485,-0.847743,0.542386,-0.188227,-1.370375, + 0.089104,0.59547,-0.798421,0.034087,-0.225059,-1.542949, + 0.101272,0.634315,-0.766413,0.018086,0.002865,-1.523199, + 0.111825,0.518485,-0.847743,0.542386,-0.188227,-1.370375, + 0.101272,0.634315,-0.766413,0.018086,0.002865,-1.523199, + 0.09853,0.626571,-0.773111,0.516872,-0.020713,-1.356627, + 0.163727,0.387435,-0.907242,0.546875,-0.39094,-1.363244, + 0.147941,0.53134,-0.834141,0.010486,-0.502317,-1.576297, + 0.089104,0.59547,-0.798421,0.034087,-0.225059,-1.542949, + 0.163727,0.387435,-0.907242,0.546875,-0.39094,-1.363244, + 0.089104,0.59547,-0.798421,0.034087,-0.225059,-1.542949, + 0.111825,0.518485,-0.847743,0.542386,-0.188227,-1.370375, + 0.227108,0.258715,-0.938876,0.550658,-0.633015,-1.331311, + 0.206788,0.399922,-0.892917,0.021051,-0.831931,-1.511548, + 0.147941,0.53134,-0.834141,0.010486,-0.502317,-1.576297, + 0.227108,0.258715,-0.938876,0.550658,-0.633015,-1.331311, + 0.147941,0.53134,-0.834141,0.010486,-0.502317,-1.576297, + 0.163727,0.387435,-0.907242,0.546875,-0.39094,-1.363244, + 0.263434,0.119819,-0.957207,0.527724,-0.862854,-1.253811, + 0.246802,0.252523,-0.935586,-0.04157,-1.143825,-1.395176, + 0.206788,0.399922,-0.892917,0.021051,-0.831931,-1.511548, + 0.263434,0.119819,-0.957207,0.527724,-0.862854,-1.253811, + 0.206788,0.399922,-0.892917,0.021051,-0.831931,-1.511548, + 0.227108,0.258715,-0.938876,0.550658,-0.633015,-1.331311, + 0.304293,-0.024391,-0.952266,0.544825,-1.133123,-1.096902, + 0.274567,0.116527,-0.954481,-0.071941,-1.346991,-1.237379, + 0.246802,0.252523,-0.935586,-0.04157,-1.143825,-1.395176, + 0.304293,-0.024391,-0.952266,0.544825,-1.133123,-1.096902, + 0.246802,0.252523,-0.935586,-0.04157,-1.143825,-1.395176, + 0.263434,0.119819,-0.957207,0.527724,-0.862854,-1.253811, + 0.372063,-0.134052,-0.918477,0.530629,-1.316423,-0.929842, + 0.303729,-0.050718,-0.951408,-0.0723,-1.450245,-1.087397, + 0.274567,0.116527,-0.954481,-0.071941,-1.346991,-1.237379, + 0.372063,-0.134052,-0.918477,0.530629,-1.316423,-0.929842, + 0.274567,0.116527,-0.954481,-0.071941,-1.346991,-1.237379, + 0.304293,-0.024391,-0.952266,0.544825,-1.133123,-1.096902, + 0.424286,-0.254348,-0.869073,0.538756,-1.408602,-0.764911, + 0.33122,-0.270106,-0.904067,-0.063012,-1.583021,-0.865082, + 0.303729,-0.050718,-0.951408,-0.0723,-1.450245,-1.087397, + 0.424286,-0.254348,-0.869073,0.538756,-1.408602,-0.764911, + 0.303729,-0.050718,-0.951408,-0.0723,-1.450245,-1.087397, + 0.372063,-0.134052,-0.918477,0.530629,-1.316423,-0.929842, + 0.420794,-0.405156,-0.811653,0.489819,-1.524947,-0.672392, + 0.327725,-0.489439,-0.808112,-0.07847,-1.688266,-0.80023, + 0.33122,-0.270106,-0.904067,-0.063012,-1.583021,-0.865082, + 0.420794,-0.405156,-0.811653,0.489819,-1.524947,-0.672392, + 0.33122,-0.270106,-0.904067,-0.063012,-1.583021,-0.865082, + 0.424286,-0.254348,-0.869073,0.538756,-1.408602,-0.764911, + 0.420794,-0.405156,-0.811653,0.489819,-1.524947,-0.672392, + 0.291858,-0.681117,-0.67149,-0.094135,-1.769086,-0.556924, + 0.327725,-0.489439,-0.808112,-0.07847,-1.688266,-0.80023, + 0.235033,-0.721825,-0.650944,-0.559706,1.69418,-0.186107, + 0.004725,-0.680391,-0.732834,-0.894132,1.712652,-0.151911, + -0.098179,0.995169,0,-0.866132,1.75467,0, + 0.235033,-0.721825,-0.650944,-0.559706,1.69418,-0.186107, + -0.098179,0.995169,0,-0.866132,1.75467,0, + -0.009814,-0.999952,0,-0.547248,1.742126,0, + 0.244106,-0.79539,-0.554768,-0.557624,1.641278,-0.271462, + 0.034172,-0.858604,-0.511498,-0.954897,1.677544,-0.293034, + 0.004725,-0.680391,-0.732834,-0.894132,1.712652,-0.151911, + 0.244106,-0.79539,-0.554768,-0.557624,1.641278,-0.271462, + 0.004725,-0.680391,-0.732834,-0.894132,1.712652,-0.151911, + 0.235033,-0.721825,-0.650944,-0.559706,1.69418,-0.186107, + 0.213948,-0.943673,-0.252405,-0.626493,1.585426,-0.443136, + 0.037423,-0.986705,-0.158154,-1.017767,1.607824,-0.541965, + 0.034172,-0.858604,-0.511498,-0.954897,1.677544,-0.293034, + 0.213948,-0.943673,-0.252405,-0.626493,1.585426,-0.443136, + 0.034172,-0.858604,-0.511498,-0.954897,1.677544,-0.293034, + 0.244106,-0.79539,-0.554768,-0.557624,1.641278,-0.271462, + 0.190577,-0.970681,-0.146488,-0.597781,1.48962,-0.641047, + 0.013768,-0.992402,-0.122267,-1.04607,1.509097,-0.76106, + 0.037423,-0.986705,-0.158154,-1.017767,1.607824,-0.541965, + 0.190577,-0.970681,-0.146488,-0.597781,1.48962,-0.641047, + 0.037423,-0.986705,-0.158154,-1.017767,1.607824,-0.541965, + 0.213948,-0.943673,-0.252405,-0.626493,1.585426,-0.443136, + 0.048754,0.934073,-0.353738,-0.674657,1.333008,-0.761059, + 0.076524,0.950336,-0.301672,-1.115594,1.39238,-0.819623, + 0.013768,-0.992402,-0.122267,-1.04607,1.509097,-0.76106, + 0.048754,0.934073,-0.353738,-0.674657,1.333008,-0.761059, + 0.013768,-0.992402,-0.122267,-1.04607,1.509097,-0.76106, + 0.190577,-0.970681,-0.146488,-0.597781,1.48962,-0.641047, + 0.081223,0.915345,-0.394394,-0.910602,1.204118,-0.83774, + 0.100598,0.942931,-0.317428,-1.278903,1.192051,-0.946843, + 0.076524,0.950336,-0.301672,-1.115594,1.39238,-0.819623, + 0.081223,0.915345,-0.394394,-0.910602,1.204118,-0.83774, + 0.076524,0.950336,-0.301672,-1.115594,1.39238,-0.819623, + 0.048754,0.934073,-0.353738,-0.674657,1.333008,-0.761059, + 0.120116,0.912706,-0.390565,-0.969076,0.901205,-1.146223, + 0.150328,0.92948,-0.336851,-1.200768,0.978822,-1.103391, + 0.100598,0.942931,-0.317428,-1.278903,1.192051,-0.946843, + 0.120116,0.912706,-0.390565,-0.969076,0.901205,-1.146223, + 0.100598,0.942931,-0.317428,-1.278903,1.192051,-0.946843, + 0.081223,0.915345,-0.394394,-0.910602,1.204118,-0.83774, + 0.1717,0.74071,-0.649514,-0.752416,0.438132,-1.467349, + 0.235667,0.756618,-0.60991,-1.147922,0.807955,-1.254191, + 0.150328,0.92948,-0.336851,-1.200768,0.978822,-1.103391, + 0.1717,0.74071,-0.649514,-0.752416,0.438132,-1.467349, + 0.150328,0.92948,-0.336851,-1.200768,0.978822,-1.103391, + 0.120116,0.912706,-0.390565,-0.969076,0.901205,-1.146223, + 0.167704,0.495674,-0.852164,-0.645496,0.179261,-1.584316, + 0.305452,0.425365,-0.851918,-1.120716,0.424016,-1.45699, + 0.235667,0.756618,-0.60991,-1.147922,0.807955,-1.254191, + 0.167704,0.495674,-0.852164,-0.645496,0.179261,-1.584316, + 0.235667,0.756618,-0.60991,-1.147922,0.807955,-1.254191, + 0.1717,0.74071,-0.649514,-0.752416,0.438132,-1.467349, + 0.140536,0.558684,-0.817388,-0.536767,-0.144454,-1.682232, + 0.325482,0.443544,-0.835063,-1.077307,0.165008,-1.553393, + 0.305452,0.425365,-0.851918,-1.120716,0.424016,-1.45699, + 0.140536,0.558684,-0.817388,-0.536767,-0.144454,-1.682232, + 0.305452,0.425365,-0.851918,-1.120716,0.424016,-1.45699, + 0.167704,0.495674,-0.852164,-0.645496,0.179261,-1.584316, + 0.136523,0.621747,-0.771228,-0.533528,-0.58228,-1.701405, + 0.242426,0.58207,-0.77616,-1.053434,-0.342553,-1.690245, + 0.325482,0.443544,-0.835063,-1.077307,0.165008,-1.553393, + 0.136523,0.621747,-0.771228,-0.533528,-0.58228,-1.701405, + 0.325482,0.443544,-0.835063,-1.077307,0.165008,-1.553393, + 0.140536,0.558684,-0.817388,-0.536767,-0.144454,-1.682232, + 0.100131,0.509748,-0.854477,-0.505045,-0.913827,-1.645612, + 0.070189,0.510248,-0.857158,-1.077209,-0.869649,-1.633144, + 0.242426,0.58207,-0.77616,-1.053434,-0.342553,-1.690245, + 0.100131,0.509748,-0.854477,-0.505045,-0.913827,-1.645612, + 0.242426,0.58207,-0.77616,-1.053434,-0.342553,-1.690245, + 0.136523,0.621747,-0.771228,-0.533528,-0.58228,-1.701405, + 0.063174,0.351351,-0.93411,-0.487217,-1.193519,-1.504026, + -0.078623,0.370994,-0.925301,-1.061272,-1.141877,-1.49623, + 0.070189,0.510248,-0.857158,-1.077209,-0.869649,-1.633144, + 0.063174,0.351351,-0.93411,-0.487217,-1.193519,-1.504026, + 0.070189,0.510248,-0.857158,-1.077209,-0.869649,-1.633144, + 0.100131,0.509748,-0.854477,-0.505045,-0.913827,-1.645612, + 0.078896,0.195617,-0.977502,-0.524231,-1.399266,-1.313019, + -0.123389,0.256577,-0.958615,-1.001366,-1.335897,-1.353338, + -0.078623,0.370994,-0.925301,-1.061272,-1.141877,-1.49623, + 0.078896,0.195617,-0.977502,-0.524231,-1.399266,-1.313019, + -0.078623,0.370994,-0.925301,-1.061272,-1.141877,-1.49623, + 0.063174,0.351351,-0.93411,-0.487217,-1.193519,-1.504026, + 0.097816,-0.016117,-0.995074,-0.526127,-1.495,-1.167736, + -0.165685,0.059692,-0.98437,-0.952525,-1.440582,-1.16865, + -0.123389,0.256577,-0.958615,-1.001366,-1.335897,-1.353338, + 0.097816,-0.016117,-0.995074,-0.526127,-1.495,-1.167736, + -0.123389,0.256577,-0.958615,-1.001366,-1.335897,-1.353338, + 0.078896,0.195617,-0.977502,-0.524231,-1.399266,-1.313019, + 0.10737,-0.293005,-0.950063,-0.535144,-1.615983,-0.920556, + -0.218261,-0.26262,-0.93989,-0.953236,-1.545941,-0.89918, + -0.165685,0.059692,-0.98437,-0.952525,-1.440582,-1.16865, + 0.10737,-0.293005,-0.950063,-0.535144,-1.615983,-0.920556, + -0.165685,0.059692,-0.98437,-0.952525,-1.440582,-1.16865, + 0.097816,-0.016117,-0.995074,-0.526127,-1.495,-1.167736, + 0.769758,0.095155,-0.631204,2.688131,-0.517509,-0.672975, + 0.763734,0.228435,-0.603761,2.736198,-0.346225,-0.659345, + 0.226413,-0.89822,-0.376747,2.881063,-0.493146,-0.521968, + 0.594643,-0.107364,-0.796789,2.663024,-1.440487,-0.478149, + 0.655995,-0.105886,-0.747301,2.740886,-1.339225,-0.463604, + 0.690473,-0.61586,-0.379425,2.824356,-1.407256,-0.355013, + 0.184661,-0.694307,-0.695585,1.373216,-0.56462,-1.106245, + 0.419396,-0.035927,-0.907092,1.428883,-0.98669,-1.133905, + 0.045651,-0.004499,-0.998947,1.337875,-0.945716,-1.021299, + -0.267766,-0.862787,-0.428835,-1.215563,1.757097,-0.133494, + -0.507894,-0.767261,-0.391606,-1.365948,1.769608,-0.133901, + 0.262234,-0.965004,0,-1.35095,1.807009,0, + -0.267766,-0.862787,-0.428835,-1.215563,1.757097,-0.133494, + 0.262234,-0.965004,0,-1.35095,1.807009,0, + -0.065586,-0.997847,0,-1.179474,1.786649,0, + -0.263452,-0.648591,-0.714089,-1.227613,1.709095,-0.276029, + -0.375453,-0.69207,-0.616502,-1.396332,1.723782,-0.267642, + -0.507894,-0.767261,-0.391606,-1.365948,1.769608,-0.133901, + -0.263452,-0.648591,-0.714089,-1.227613,1.709095,-0.276029, + -0.507894,-0.767261,-0.391606,-1.365948,1.769608,-0.133901, + -0.267766,-0.862787,-0.428835,-1.215563,1.757097,-0.133494, + -0.301558,-0.77828,-0.550766,-1.292756,1.656509,-0.51403, + -0.1427,-0.847733,-0.510868,-1.417595,1.67618,-0.529265, + -0.375453,-0.69207,-0.616502,-1.396332,1.723782,-0.267642, + -0.301558,-0.77828,-0.550766,-1.292756,1.656509,-0.51403, + -0.375453,-0.69207,-0.616502,-1.396332,1.723782,-0.267642, + -0.263452,-0.648591,-0.714089,-1.227613,1.709095,-0.276029, + -0.154129,-0.981148,-0.116585,-1.338488,1.613735,-0.725441, + -0.178511,-0.973481,-0.143068,-1.465432,1.655336,-0.722125, + -0.1427,-0.847733,-0.510868,-1.417595,1.67618,-0.529265, + -0.154129,-0.981148,-0.116585,-1.338488,1.613735,-0.725441, + -0.1427,-0.847733,-0.510868,-1.417595,1.67618,-0.529265, + -0.301558,-0.77828,-0.550766,-1.292756,1.656509,-0.51403, + 0.095331,0.952335,-0.289775,-1.403848,1.533059,-0.902827, + 0.067879,0.951186,-0.30106,-1.582187,1.567542,-0.982349, + -0.178511,-0.973481,-0.143068,-1.465432,1.655336,-0.722125, + 0.095331,0.952335,-0.289775,-1.403848,1.533059,-0.902827, + -0.178511,-0.973481,-0.143068,-1.465432,1.655336,-0.722125, + -0.154129,-0.981148,-0.116585,-1.338488,1.613735,-0.725441, + 0.10291,0.954344,-0.280422,-1.551526,1.400025,-1.050193, + 0.085022,0.963119,-0.255291,-1.721806,1.391264,-1.113307, + 0.067879,0.951186,-0.30106,-1.582187,1.567542,-0.982349, + 0.10291,0.954344,-0.280422,-1.551526,1.400025,-1.050193, + 0.067879,0.951186,-0.30106,-1.582187,1.567542,-0.982349, + 0.095331,0.952335,-0.289775,-1.403848,1.533059,-0.902827, + 0.172251,0.950689,-0.257916,-1.552899,1.128654,-1.15104, + 0.120743,0.971588,-0.203561,-1.733703,1.083864,-1.181489, + 0.085022,0.963119,-0.255291,-1.721806,1.391264,-1.113307, + 0.172251,0.950689,-0.257916,-1.552899,1.128654,-1.15104, + 0.085022,0.963119,-0.255291,-1.721806,1.391264,-1.113307, + 0.10291,0.954344,-0.280422,-1.551526,1.400025,-1.050193, + 0.28101,0.853935,-0.437982,-1.454529,0.875045,-1.238858, + 0.117963,0.926753,-0.356669,-1.807421,0.657142,-1.209422, + 0.120743,0.971588,-0.203561,-1.733703,1.083864,-1.181489, + 0.28101,0.853935,-0.437982,-1.454529,0.875045,-1.238858, + 0.120743,0.971588,-0.203561,-1.733703,1.083864,-1.181489, + 0.172251,0.950689,-0.257916,-1.552899,1.128654,-1.15104, + 0.381239,0.555717,-0.738807,-1.405685,0.573835,-1.352181, + 0.109947,0.693426,-0.712089,-1.796156,0.452382,-1.243643, + 0.117963,0.926753,-0.356669,-1.807421,0.657142,-1.209422, + 0.381239,0.555717,-0.738807,-1.405685,0.573835,-1.352181, + 0.117963,0.926753,-0.356669,-1.807421,0.657142,-1.209422, + 0.28101,0.853935,-0.437982,-1.454529,0.875045,-1.238858, + 0.376012,0.360026,-0.853813,-1.479588,0.295746,-1.440042, + 0.076565,0.333251,-0.939724,-1.81092,0.287592,-1.292257, + 0.109947,0.693426,-0.712089,-1.796156,0.452382,-1.243643, + 0.376012,0.360026,-0.853813,-1.479588,0.295746,-1.440042, + 0.109947,0.693426,-0.712089,-1.796156,0.452382,-1.243643, + 0.381239,0.555717,-0.738807,-1.405685,0.573835,-1.352181, + 0.207079,0.373404,-0.904261,-1.489699,-0.024215,-1.510987, + -0.039599,0.171847,-0.984327,-1.79513,0.033439,-1.37116, + 0.076565,0.333251,-0.939724,-1.81092,0.287592,-1.292257, + 0.207079,0.373404,-0.904261,-1.489699,-0.024215,-1.510987, + 0.076565,0.333251,-0.939724,-1.81092,0.287592,-1.292257, + 0.376012,0.360026,-0.853813,-1.479588,0.295746,-1.440042, + -0.045242,0.348413,-0.936249,-1.395501,-0.698702,-1.553257, + -0.164972,0.181757,-0.969406,-1.802864,-0.282523,-1.401315, + -0.039599,0.171847,-0.984327,-1.79513,0.033439,-1.37116, + -0.045242,0.348413,-0.936249,-1.395501,-0.698702,-1.553257, + -0.039599,0.171847,-0.984327,-1.79513,0.033439,-1.37116, + 0.207079,0.373404,-0.904261,-1.489699,-0.024215,-1.510987, + -0.212948,0.334057,-0.918182,-1.376176,-0.948757,-1.451608, + -0.216817,0.278777,-0.935561,-1.837859,-0.540871,-1.295851, + -0.164972,0.181757,-0.969406,-1.802864,-0.282523,-1.401315, + -0.212948,0.334057,-0.918182,-1.376176,-0.948757,-1.451608, + -0.164972,0.181757,-0.969406,-1.802864,-0.282523,-1.401315, + -0.045242,0.348413,-0.936249,-1.395501,-0.698702,-1.553257, + -0.282152,0.285245,-0.915983,-1.402349,-1.127845,-1.309055, + -0.219724,0.297861,-0.928978,-1.782928,-0.770786,-1.173619, + -0.216817,0.278777,-0.935561,-1.837859,-0.540871,-1.295851, + -0.282152,0.285245,-0.915983,-1.402349,-1.127845,-1.309055, + -0.216817,0.278777,-0.935561,-1.837859,-0.540871,-1.295851, + -0.212948,0.334057,-0.918182,-1.376176,-0.948757,-1.451608, + -0.326048,0.118611,-0.937883,-1.407658,-1.236026,-1.11293, + -0.227368,0.161984,-0.960242,-1.757573,-0.945337,-1.075832, + -0.219724,0.297861,-0.928978,-1.782928,-0.770786,-1.173619, + -0.326048,0.118611,-0.937883,-1.407658,-1.236026,-1.11293, + -0.219724,0.297861,-0.928978,-1.782928,-0.770786,-1.173619, + -0.282152,0.285245,-0.915983,-1.402349,-1.127845,-1.309055, + -0.507894,-0.767261,-0.391606,-1.365948,1.769608,-0.133901, + -0.387895,-0.42081,-0.820034,-1.683863,1.789041,-0.121501, + 0.021487,0.999769,0,-1.67651,1.826886,0, + -0.507894,-0.767261,-0.391606,-1.365948,1.769608,-0.133901, + 0.021487,0.999769,0,-1.67651,1.826886,0, + 0.262234,-0.965004,0,-1.35095,1.807009,0, + -0.375453,-0.69207,-0.616502,-1.396332,1.723782,-0.267642, + -0.433119,-0.541143,-0.720814,-1.714432,1.747956,-0.247594, + -0.387895,-0.42081,-0.820034,-1.683863,1.789041,-0.121501, + -0.375453,-0.69207,-0.616502,-1.396332,1.723782,-0.267642, + -0.387895,-0.42081,-0.820034,-1.683863,1.789041,-0.121501, + -0.507894,-0.767261,-0.391606,-1.365948,1.769608,-0.133901, + -0.1427,-0.847733,-0.510868,-1.417595,1.67618,-0.529265, + -0.455057,-0.684123,-0.569999,-1.744732,1.734849,-0.433807, + -0.433119,-0.541143,-0.720814,-1.714432,1.747956,-0.247594, + -0.1427,-0.847733,-0.510868,-1.417595,1.67618,-0.529265, + -0.433119,-0.541143,-0.720814,-1.714432,1.747956,-0.247594, + -0.375453,-0.69207,-0.616502,-1.396332,1.723782,-0.267642, + -0.178511,-0.973481,-0.143068,-1.465432,1.655336,-0.722125, + -0.084259,-0.367691,-0.926123,-1.929731,1.617188,-0.80639, + -0.455057,-0.684123,-0.569999,-1.744732,1.734849,-0.433807, + -0.178511,-0.973481,-0.143068,-1.465432,1.655336,-0.722125, + -0.455057,-0.684123,-0.569999,-1.744732,1.734849,-0.433807, + -0.1427,-0.847733,-0.510868,-1.417595,1.67618,-0.529265, + 0.067879,0.951186,-0.30106,-1.582187,1.567542,-0.982349, + 0.061261,0.954316,-0.292452,-1.996117,1.387891,-1.064104, + -0.084259,-0.367691,-0.926123,-1.929731,1.617188,-0.80639, + 0.067879,0.951186,-0.30106,-1.582187,1.567542,-0.982349, + -0.084259,-0.367691,-0.926123,-1.929731,1.617188,-0.80639, + -0.178511,-0.973481,-0.143068,-1.465432,1.655336,-0.722125, + 0.085022,0.963119,-0.255291,-1.721806,1.391264,-1.113307, + 0.076969,0.969253,-0.233719,-1.980388,1.134038,-1.143196, + 0.061261,0.954316,-0.292452,-1.996117,1.387891,-1.064104, + 0.085022,0.963119,-0.255291,-1.721806,1.391264,-1.113307, + 0.061261,0.954316,-0.292452,-1.996117,1.387891,-1.064104, + 0.067879,0.951186,-0.30106,-1.582187,1.567542,-0.982349, + 0.120743,0.971588,-0.203561,-1.733703,1.083864,-1.181489, + 0.057779,0.975002,-0.214553,-2.013663,0.810726,-1.158827, + 0.076969,0.969253,-0.233719,-1.980388,1.134038,-1.143196, + 0.120743,0.971588,-0.203561,-1.733703,1.083864,-1.181489, + 0.076969,0.969253,-0.233719,-1.980388,1.134038,-1.143196, + 0.085022,0.963119,-0.255291,-1.721806,1.391264,-1.113307, + 0.117963,0.926753,-0.356669,-1.807421,0.657142,-1.209422, + -0.021294,0.896295,-0.442946,-2.030191,0.547622,-1.189762, + 0.057779,0.975002,-0.214553,-2.013663,0.810726,-1.158827, + 0.117963,0.926753,-0.356669,-1.807421,0.657142,-1.209422, + 0.057779,0.975002,-0.214553,-2.013663,0.810726,-1.158827, + 0.120743,0.971588,-0.203561,-1.733703,1.083864,-1.181489, + 0.109947,0.693426,-0.712089,-1.796156,0.452382,-1.243643, + -0.072244,0.618144,-0.782738,-2.021159,0.411979,-1.234679, + -0.021294,0.896295,-0.442946,-2.030191,0.547622,-1.189762, + 0.109947,0.693426,-0.712089,-1.796156,0.452382,-1.243643, + -0.021294,0.896295,-0.442946,-2.030191,0.547622,-1.189762, + 0.117963,0.926753,-0.356669,-1.807421,0.657142,-1.209422, + 0.076565,0.333251,-0.939724,-1.81092,0.287592,-1.292257, + -0.038944,0.247819,-0.968023,-1.932916,0.232972,-1.304589, + -0.072244,0.618144,-0.782738,-2.021159,0.411979,-1.234679, + 0.076565,0.333251,-0.939724,-1.81092,0.287592,-1.292257, + -0.072244,0.618144,-0.782738,-2.021159,0.411979,-1.234679, + 0.109947,0.693426,-0.712089,-1.796156,0.452382,-1.243643, + -0.039599,0.171847,-0.984327,-1.79513,0.033439,-1.37116, + -0.00315,0.115338,-0.993321,-1.897394,0.037852,-1.365798, + -0.038944,0.247819,-0.968023,-1.932916,0.232972,-1.304589, + -0.039599,0.171847,-0.984327,-1.79513,0.033439,-1.37116, + -0.038944,0.247819,-0.968023,-1.932916,0.232972,-1.304589, + 0.076565,0.333251,-0.939724,-1.81092,0.287592,-1.292257, + -0.164972,0.181757,-0.969406,-1.802864,-0.282523,-1.401315, + 0.016683,0.197618,-0.980137,-1.950547,-0.275573,-1.377028, + -0.00315,0.115338,-0.993321,-1.897394,0.037852,-1.365798, + -0.164972,0.181757,-0.969406,-1.802864,-0.282523,-1.401315, + -0.00315,0.115338,-0.993321,-1.897394,0.037852,-1.365798, + -0.039599,0.171847,-0.984327,-1.79513,0.033439,-1.37116, + -0.216817,0.278777,-0.935561,-1.837859,-0.540871,-1.295851, + 0.032424,0.316591,-0.948008,-2.033655,-0.526012,-1.277639, + 0.016683,0.197618,-0.980137,-1.950547,-0.275573,-1.377028, + -0.216817,0.278777,-0.935561,-1.837859,-0.540871,-1.295851, + 0.016683,0.197618,-0.980137,-1.950547,-0.275573,-1.377028, + -0.164972,0.181757,-0.969406,-1.802864,-0.282523,-1.401315, + -0.219724,0.297861,-0.928978,-1.782928,-0.770786,-1.173619, + 0.053195,0.343167,-0.937767,-2.050292,-0.755566,-1.114167, + 0.032424,0.316591,-0.948008,-2.033655,-0.526012,-1.277639, + -0.219724,0.297861,-0.928978,-1.782928,-0.770786,-1.173619, + 0.032424,0.316591,-0.948008,-2.033655,-0.526012,-1.277639, + -0.216817,0.278777,-0.935561,-1.837859,-0.540871,-1.295851, + -0.227368,0.161984,-0.960242,-1.757573,-0.945337,-1.075832, + 0.057735,0.173734,-0.983099,-2.043593,-0.875823,-1.028879, + 0.053195,0.343167,-0.937767,-2.050292,-0.755566,-1.114167, + -0.227368,0.161984,-0.960242,-1.757573,-0.945337,-1.075832, + 0.053195,0.343167,-0.937767,-2.050292,-0.755566,-1.114167, + -0.219724,0.297861,-0.928978,-1.782928,-0.770786,-1.173619, + -0.30296,-0.137183,-0.943078,-1.782298,-1.020581,-0.943381, + 0.058723,-0.195869,-0.97887,-2.033406,-0.91003,-0.96422, + 0.057735,0.173734,-0.983099,-2.043593,-0.875823,-1.028879, + -0.30296,-0.137183,-0.943078,-1.782298,-1.020581,-0.943381, + 0.057735,0.173734,-0.983099,-2.043593,-0.875823,-1.028879, + -0.227368,0.161984,-0.960242,-1.757573,-0.945337,-1.075832, + 0.121987,-0.426326,-0.896306,-1.198513,-1.456102,-0.885435, + -0.326048,0.118611,-0.937883,-1.407658,-1.236026,-1.11293, + -0.165685,0.059692,-0.98437,-0.952525,-1.440582,-1.16865, + 0.121987,-0.426326,-0.896306,-1.198513,-1.456102,-0.885435, + -0.165685,0.059692,-0.98437,-0.952525,-1.440582,-1.16865, + -0.218261,-0.26262,-0.93989,-0.953236,-1.545941,-0.89918, + 0.095733,-0.224552,-0.969748,-1.456655,-1.295527,-0.89424, + -0.30296,-0.137183,-0.943078,-1.782298,-1.020581,-0.943381, + -0.227368,0.161984,-0.960242,-1.757573,-0.945337,-1.075832, + 0.095733,-0.224552,-0.969748,-1.456655,-1.295527,-0.89424, + -0.227368,0.161984,-0.960242,-1.757573,-0.945337,-1.075832, + -0.326048,0.118611,-0.937883,-1.407658,-1.236026,-1.11293, + -0.422758,-0.178302,-0.888529,-1.366873,-1.340211,-0.907567, + 0.095733,-0.224552,-0.969748,-1.456655,-1.295527,-0.89424, + -0.326048,0.118611,-0.937883,-1.407658,-1.236026,-1.11293, + 0.121987,-0.426326,-0.896306,-1.198513,-1.456102,-0.885435, + -0.422758,-0.178302,-0.888529,-1.366873,-1.340211,-0.907567, + -0.326048,0.118611,-0.937883,-1.407658,-1.236026,-1.11293, + -0.387895,-0.42081,-0.820034,-1.683863,1.789041,-0.121501, + 0.088769,-0.475351,-0.875307,-2.079597,1.817785,-0.138375, + 0.181762,-0.983343,0,-2.057387,1.841308,0, + -0.387895,-0.42081,-0.820034,-1.683863,1.789041,-0.121501, + 0.181762,-0.983343,0,-2.057387,1.841308,0, + 0.021487,0.999769,0,-1.67651,1.826886,0, + -0.433119,-0.541143,-0.720814,-1.714432,1.747956,-0.247594, + 0.099302,-0.563694,-0.819993,-2.10017,1.78998,-0.229245, + 0.088769,-0.475351,-0.875307,-2.079597,1.817785,-0.138375, + -0.433119,-0.541143,-0.720814,-1.714432,1.747956,-0.247594, + 0.088769,-0.475351,-0.875307,-2.079597,1.817785,-0.138375, + -0.387895,-0.42081,-0.820034,-1.683863,1.789041,-0.121501, + -0.455057,-0.684123,-0.569999,-1.744732,1.734849,-0.433807, + 0.093801,-0.705497,-0.702478,-2.137524,1.753182,-0.433142, + 0.099302,-0.563694,-0.819993,-2.10017,1.78998,-0.229245, + -0.455057,-0.684123,-0.569999,-1.744732,1.734849,-0.433807, + 0.099302,-0.563694,-0.819993,-2.10017,1.78998,-0.229245, + -0.433119,-0.541143,-0.720814,-1.714432,1.747956,-0.247594, + -0.084259,-0.367691,-0.926123,-1.929731,1.617188,-0.80639, + 0.058028,-0.329667,-0.942312,-2.172139,1.62301,-0.805318, + 0.093801,-0.705497,-0.702478,-2.137524,1.753182,-0.433142, + -0.084259,-0.367691,-0.926123,-1.929731,1.617188,-0.80639, + 0.093801,-0.705497,-0.702478,-2.137524,1.753182,-0.433142, + -0.455057,-0.684123,-0.569999,-1.744732,1.734849,-0.433807, + 0.061261,0.954316,-0.292452,-1.996117,1.387891,-1.064104, + 0.096347,0.961203,-0.258467,-2.205791,1.356023,-1.081662, + 0.058028,-0.329667,-0.942312,-2.172139,1.62301,-0.805318, + 0.061261,0.954316,-0.292452,-1.996117,1.387891,-1.064104, + 0.058028,-0.329667,-0.942312,-2.172139,1.62301,-0.805318, + -0.084259,-0.367691,-0.926123,-1.929731,1.617188,-0.80639, + 0.076969,0.969253,-0.233719,-1.980388,1.134038,-1.143196, + 0.098712,0.966371,-0.23745,-2.296056,1.06281,-1.171139, + 0.096347,0.961203,-0.258467,-2.205791,1.356023,-1.081662, + 0.076969,0.969253,-0.233719,-1.980388,1.134038,-1.143196, + 0.096347,0.961203,-0.258467,-2.205791,1.356023,-1.081662, + 0.061261,0.954316,-0.292452,-1.996117,1.387891,-1.064104, + 0.057779,0.975002,-0.214553,-2.013663,0.810726,-1.158827, + 0.079848,0.962653,-0.258695,-2.298249,0.768333,-1.203884, + 0.098712,0.966371,-0.23745,-2.296056,1.06281,-1.171139, + 0.057779,0.975002,-0.214553,-2.013663,0.810726,-1.158827, + 0.098712,0.966371,-0.23745,-2.296056,1.06281,-1.171139, + 0.076969,0.969253,-0.233719,-1.980388,1.134038,-1.143196, + -0.021294,0.896295,-0.442946,-2.030191,0.547622,-1.189762, + 0.031476,0.864418,-0.501788,-2.256285,0.547326,-1.238301, + 0.079848,0.962653,-0.258695,-2.298249,0.768333,-1.203884, + -0.021294,0.896295,-0.442946,-2.030191,0.547622,-1.189762, + 0.079848,0.962653,-0.258695,-2.298249,0.768333,-1.203884, + 0.057779,0.975002,-0.214553,-2.013663,0.810726,-1.158827, + -0.072244,0.618144,-0.782738,-2.021159,0.411979,-1.234679, + -0.004377,0.58747,-0.809234,-2.1584,0.381542,-1.272962, + 0.031476,0.864418,-0.501788,-2.256285,0.547326,-1.238301, + -0.072244,0.618144,-0.782738,-2.021159,0.411979,-1.234679, + 0.031476,0.864418,-0.501788,-2.256285,0.547326,-1.238301, + -0.021294,0.896295,-0.442946,-2.030191,0.547622,-1.189762, + -0.038944,0.247819,-0.968023,-1.932916,0.232972,-1.304589, + 0.044022,0.273891,-0.960753,-2.070413,0.207766,-1.335106, + -0.004377,0.58747,-0.809234,-2.1584,0.381542,-1.272962, + -0.038944,0.247819,-0.968023,-1.932916,0.232972,-1.304589, + -0.004377,0.58747,-0.809234,-2.1584,0.381542,-1.272962, + -0.072244,0.618144,-0.782738,-2.021159,0.411979,-1.234679, + -0.00315,0.115338,-0.993321,-1.897394,0.037852,-1.365798, + 0.136965,0.155729,-0.978258,-2.064786,0.018789,-1.411866, + 0.044022,0.273891,-0.960753,-2.070413,0.207766,-1.335106, + -0.00315,0.115338,-0.993321,-1.897394,0.037852,-1.365798, + 0.044022,0.273891,-0.960753,-2.070413,0.207766,-1.335106, + -0.038944,0.247819,-0.968023,-1.932916,0.232972,-1.304589, + 0.016683,0.197618,-0.980137,-1.950547,-0.275573,-1.377028, + 0.173447,0.205435,-0.963178,-2.187634,-0.375454,-1.406902, + 0.136965,0.155729,-0.978258,-2.064786,0.018789,-1.411866, + 0.016683,0.197618,-0.980137,-1.950547,-0.275573,-1.377028, + 0.136965,0.155729,-0.978258,-2.064786,0.018789,-1.411866, + -0.00315,0.115338,-0.993321,-1.897394,0.037852,-1.365798, + 0.032424,0.316591,-0.948008,-2.033655,-0.526012,-1.277639, + 0.136801,0.29658,-0.945159,-2.276341,-0.689823,-1.268026, + 0.173447,0.205435,-0.963178,-2.187634,-0.375454,-1.406902, + 0.032424,0.316591,-0.948008,-2.033655,-0.526012,-1.277639, + 0.173447,0.205435,-0.963178,-2.187634,-0.375454,-1.406902, + 0.016683,0.197618,-0.980137,-1.950547,-0.275573,-1.377028, + 0.053195,0.343167,-0.937767,-2.050292,-0.755566,-1.114167, + 0.095019,0.330845,-0.938889,-2.292049,-0.933921,-1.128136, + 0.136801,0.29658,-0.945159,-2.276341,-0.689823,-1.268026, + 0.053195,0.343167,-0.937767,-2.050292,-0.755566,-1.114167, + 0.136801,0.29658,-0.945159,-2.276341,-0.689823,-1.268026, + 0.032424,0.316591,-0.948008,-2.033655,-0.526012,-1.277639, + 0.057735,0.173734,-0.983099,-2.043593,-0.875823,-1.028879, + 0.53288,-0.088285,0.841573,-2.299356,-1.025449,-1.044687, + 0.095019,0.330845,-0.938889,-2.292049,-0.933921,-1.128136, + 0.057735,0.173734,-0.983099,-2.043593,-0.875823,-1.028879, + 0.095019,0.330845,-0.938889,-2.292049,-0.933921,-1.128136, + 0.053195,0.343167,-0.937767,-2.050292,-0.755566,-1.114167, + 0.058723,-0.195869,-0.97887,-2.033406,-0.91003,-0.96422, + 0.07657,0.16758,-0.982881,-2.306662,-1.116976,-0.961238, + 0.53288,-0.088285,0.841573,-2.299356,-1.025449,-1.044687, + 0.058723,-0.195869,-0.97887,-2.033406,-0.91003,-0.96422, + 0.53288,-0.088285,0.841573,-2.299356,-1.025449,-1.044687, + 0.057735,0.173734,-0.983099,-2.043593,-0.875823,-1.028879, + 0.088769,-0.475351,-0.875307,-2.079597,1.817785,-0.138375, + 0.079214,-0.175111,-0.981357,-2.672899,1.90511,-0.067168, + 0.03611,0.999348,0,-2.629466,1.918204,0, + 0.088769,-0.475351,-0.875307,-2.079597,1.817785,-0.138375, + 0.03611,0.999348,0,-2.629466,1.918204,0, + 0.181762,-0.983343,0,-2.057387,1.841308,0, + 0.099302,-0.563694,-0.819993,-2.10017,1.78998,-0.229245, + 0.204115,-0.405276,-0.891116,-2.697367,1.871291,-0.218796, + 0.079214,-0.175111,-0.981357,-2.672899,1.90511,-0.067168, + 0.099302,-0.563694,-0.819993,-2.10017,1.78998,-0.229245, + 0.079214,-0.175111,-0.981357,-2.672899,1.90511,-0.067168, + 0.088769,-0.475351,-0.875307,-2.079597,1.817785,-0.138375, + 0.093801,-0.705497,-0.702478,-2.137524,1.753182,-0.433142, + 0.396045,-0.47666,-0.784821,-2.703112,1.825435,-0.395127, + 0.204115,-0.405276,-0.891116,-2.697367,1.871291,-0.218796, + 0.093801,-0.705497,-0.702478,-2.137524,1.753182,-0.433142, + 0.204115,-0.405276,-0.891116,-2.697367,1.871291,-0.218796, + 0.099302,-0.563694,-0.819993,-2.10017,1.78998,-0.229245, + 0.058028,-0.329667,-0.942312,-2.172139,1.62301,-0.805318, + 0.238702,-0.258568,-0.936037,-2.715246,1.746763,-0.604653, + 0.396045,-0.47666,-0.784821,-2.703112,1.825435,-0.395127, + 0.058028,-0.329667,-0.942312,-2.172139,1.62301,-0.805318, + 0.396045,-0.47666,-0.784821,-2.703112,1.825435,-0.395127, + 0.093801,-0.705497,-0.702478,-2.137524,1.753182,-0.433142, + 0.096347,0.961203,-0.258467,-2.205791,1.356023,-1.081662, + 0.11717,0.938619,-0.324447,-2.71748,1.576797,-0.875971, + 0.238702,-0.258568,-0.936037,-2.715246,1.746763,-0.604653, + 0.096347,0.961203,-0.258467,-2.205791,1.356023,-1.081662, + 0.238702,-0.258568,-0.936037,-2.715246,1.746763,-0.604653, + 0.058028,-0.329667,-0.942312,-2.172139,1.62301,-0.805318, + 0.098712,0.966371,-0.23745,-2.296056,1.06281,-1.171139, + 0.080398,0.9582,-0.274571,-2.68493,1.262021,-1.11049, + 0.11717,0.938619,-0.324447,-2.71748,1.576797,-0.875971, + 0.098712,0.966371,-0.23745,-2.296056,1.06281,-1.171139, + 0.11717,0.938619,-0.324447,-2.71748,1.576797,-0.875971, + 0.096347,0.961203,-0.258467,-2.205791,1.356023,-1.081662, + 0.079848,0.962653,-0.258695,-2.298249,0.768333,-1.203884, + 0.069061,0.958871,-0.275312,-2.572286,0.835495,-1.252192, + 0.080398,0.9582,-0.274571,-2.68493,1.262021,-1.11049, + 0.079848,0.962653,-0.258695,-2.298249,0.768333,-1.203884, + 0.080398,0.9582,-0.274571,-2.68493,1.262021,-1.11049, + 0.098712,0.966371,-0.23745,-2.296056,1.06281,-1.171139, + 0.031476,0.864418,-0.501788,-2.256285,0.547326,-1.238301, + 0.051291,0.888276,-0.456438,-2.536112,0.656633,-1.269661, + 0.069061,0.958871,-0.275312,-2.572286,0.835495,-1.252192, + 0.031476,0.864418,-0.501788,-2.256285,0.547326,-1.238301, + 0.069061,0.958871,-0.275312,-2.572286,0.835495,-1.252192, + 0.079848,0.962653,-0.258695,-2.298249,0.768333,-1.203884, + -0.004377,0.58747,-0.809234,-2.1584,0.381542,-1.272962, + -0.008282,0.691944,-0.721904,-2.520947,0.559036,-1.273617, + 0.051291,0.888276,-0.456438,-2.536112,0.656633,-1.269661, + -0.004377,0.58747,-0.809234,-2.1584,0.381542,-1.272962, + 0.051291,0.888276,-0.456438,-2.536112,0.656633,-1.269661, + 0.031476,0.864418,-0.501788,-2.256285,0.547326,-1.238301, + 0.044022,0.273891,-0.960753,-2.070413,0.207766,-1.335106, + -0.0448,0.42163,-0.905661,-2.47375,0.300945,-1.316695, + -0.008282,0.691944,-0.721904,-2.520947,0.559036,-1.273617, + 0.044022,0.273891,-0.960753,-2.070413,0.207766,-1.335106, + -0.008282,0.691944,-0.721904,-2.520947,0.559036,-1.273617, + -0.004377,0.58747,-0.809234,-2.1584,0.381542,-1.272962, + 0.136965,0.155729,-0.978258,-2.064786,0.018789,-1.411866, + -0.02449,0.224062,-0.974267,-2.433366,0.078222,-1.371269, + -0.0448,0.42163,-0.905661,-2.47375,0.300945,-1.316695, + 0.136965,0.155729,-0.978258,-2.064786,0.018789,-1.411866, + -0.0448,0.42163,-0.905661,-2.47375,0.300945,-1.316695, + 0.044022,0.273891,-0.960753,-2.070413,0.207766,-1.335106, + 0.173447,0.205435,-0.963178,-2.187634,-0.375454,-1.406902, + -0.017579,0.132168,-0.991072,-2.41473,-0.108377,-1.395384, + -0.02449,0.224062,-0.974267,-2.433366,0.078222,-1.371269, + 0.173447,0.205435,-0.963178,-2.187634,-0.375454,-1.406902, + -0.02449,0.224062,-0.974267,-2.433366,0.078222,-1.371269, + 0.136965,0.155729,-0.978258,-2.064786,0.018789,-1.411866, + 0.136801,0.29658,-0.945159,-2.276341,-0.689823,-1.268026, + -0.055858,0.145868,-0.987726,-2.38292,-0.41745,-1.375045, + -0.017579,0.132168,-0.991072,-2.41473,-0.108377,-1.395384, + 0.136801,0.29658,-0.945159,-2.276341,-0.689823,-1.268026, + -0.017579,0.132168,-0.991072,-2.41473,-0.108377,-1.395384, + 0.173447,0.205435,-0.963178,-2.187634,-0.375454,-1.406902, + 0.095019,0.330845,-0.938889,-2.292049,-0.933921,-1.128136, + -0.115746,0.20405,-0.972094,-2.430508,-0.822313,-1.254486, + -0.055858,0.145868,-0.987726,-2.38292,-0.41745,-1.375045, + 0.095019,0.330845,-0.938889,-2.292049,-0.933921,-1.128136, + -0.055858,0.145868,-0.987726,-2.38292,-0.41745,-1.375045, + 0.136801,0.29658,-0.945159,-2.276341,-0.689823,-1.268026, + 0.53288,-0.088285,0.841573,-2.299356,-1.025449,-1.044687, + -0.164191,0.153328,-0.974439,-2.566746,-1.211312,-1.167101, + -0.115746,0.20405,-0.972094,-2.430508,-0.822313,-1.254486, + 0.53288,-0.088285,0.841573,-2.299356,-1.025449,-1.044687, + -0.115746,0.20405,-0.972094,-2.430508,-0.822313,-1.254486, + 0.095019,0.330845,-0.938889,-2.292049,-0.933921,-1.128136, + 0.079214,-0.175111,-0.981357,-2.672899,1.90511,-0.067168, + 0.005821,-0.234321,-0.972142,-3.053102,1.96881,-0.051104, + 0.012502,-0.999922,0,-3.037562,2.001526,0, + 0.079214,-0.175111,-0.981357,-2.672899,1.90511,-0.067168, + 0.012502,-0.999922,0,-3.037562,2.001526,0, + 0.03611,0.999348,0,-2.629466,1.918204,0, + 0.204115,-0.405276,-0.891116,-2.697367,1.871291,-0.218796, + 0.243464,-0.335965,-0.909864,-3.077669,1.871112,-0.217368, + 0.005821,-0.234321,-0.972142,-3.053102,1.96881,-0.051104, + 0.204115,-0.405276,-0.891116,-2.697367,1.871291,-0.218796, + 0.005821,-0.234321,-0.972142,-3.053102,1.96881,-0.051104, + 0.079214,-0.175111,-0.981357,-2.672899,1.90511,-0.067168, + 0.396045,-0.47666,-0.784821,-2.703112,1.825435,-0.395127, + 0.49938,-0.45475,-0.737443,-3.07531,1.846,-0.363149, + 0.243464,-0.335965,-0.909864,-3.077669,1.871112,-0.217368, + 0.396045,-0.47666,-0.784821,-2.703112,1.825435,-0.395127, + 0.243464,-0.335965,-0.909864,-3.077669,1.871112,-0.217368, + 0.204115,-0.405276,-0.891116,-2.697367,1.871291,-0.218796, + 0.238702,-0.258568,-0.936037,-2.715246,1.746763,-0.604653, + 0.573426,-0.441087,-0.69038,-3.109047,1.789477,-0.565323, + 0.49938,-0.45475,-0.737443,-3.07531,1.846,-0.363149, + 0.238702,-0.258568,-0.936037,-2.715246,1.746763,-0.604653, + 0.49938,-0.45475,-0.737443,-3.07531,1.846,-0.363149, + 0.396045,-0.47666,-0.784821,-2.703112,1.825435,-0.395127, + 0.11717,0.938619,-0.324447,-2.71748,1.576797,-0.875971, + 0.1643,0.873906,-0.457487,-3.08565,1.65734,-0.784479, + 0.573426,-0.441087,-0.69038,-3.109047,1.789477,-0.565323, + 0.11717,0.938619,-0.324447,-2.71748,1.576797,-0.875971, + 0.573426,-0.441087,-0.69038,-3.109047,1.789477,-0.565323, + 0.238702,-0.258568,-0.936037,-2.715246,1.746763,-0.604653, + 0.080398,0.9582,-0.274571,-2.68493,1.262021,-1.11049, + -0.012448,0.906487,-0.422051,-3.028932,1.461517,-0.941324, + 0.1643,0.873906,-0.457487,-3.08565,1.65734,-0.784479, + 0.080398,0.9582,-0.274571,-2.68493,1.262021,-1.11049, + 0.1643,0.873906,-0.457487,-3.08565,1.65734,-0.784479, + 0.11717,0.938619,-0.324447,-2.71748,1.576797,-0.875971, + 0.069061,0.958871,-0.275312,-2.572286,0.835495,-1.252192, + -0.051905,0.965082,-0.256753,-2.930312,1.10358,-1.125876, + -0.012448,0.906487,-0.422051,-3.028932,1.461517,-0.941324, + 0.069061,0.958871,-0.275312,-2.572286,0.835495,-1.252192, + -0.012448,0.906487,-0.422051,-3.028932,1.461517,-0.941324, + 0.080398,0.9582,-0.274571,-2.68493,1.262021,-1.11049, + 0.051291,0.888276,-0.456438,-2.536112,0.656633,-1.269661, + -0.088843,0.888,-0.45118,-2.825835,0.755899,-1.209042, + -0.051905,0.965082,-0.256753,-2.930312,1.10358,-1.125876, + 0.051291,0.888276,-0.456438,-2.536112,0.656633,-1.269661, + -0.051905,0.965082,-0.256753,-2.930312,1.10358,-1.125876, + 0.069061,0.958871,-0.275312,-2.572286,0.835495,-1.252192, + -0.008282,0.691944,-0.721904,-2.520947,0.559036,-1.273617, + -0.169971,0.704712,-0.688833,-2.79063,0.46881,-1.224273, + -0.088843,0.888,-0.45118,-2.825835,0.755899,-1.209042, + -0.008282,0.691944,-0.721904,-2.520947,0.559036,-1.273617, + -0.088843,0.888,-0.45118,-2.825835,0.755899,-1.209042, + 0.051291,0.888276,-0.456438,-2.536112,0.656633,-1.269661, + -0.0448,0.42163,-0.905661,-2.47375,0.300945,-1.316695, + -0.261543,0.44691,-0.855492,-2.787011,0.264495,-1.237352, + -0.169971,0.704712,-0.688833,-2.79063,0.46881,-1.224273, + -0.0448,0.42163,-0.905661,-2.47375,0.300945,-1.316695, + -0.169971,0.704712,-0.688833,-2.79063,0.46881,-1.224273, + -0.008282,0.691944,-0.721904,-2.520947,0.559036,-1.273617, + -0.02449,0.224062,-0.974267,-2.433366,0.078222,-1.371269, + -0.33898,0.203127,-0.918603,-2.687022,0.076781,-1.290565, + -0.261543,0.44691,-0.855492,-2.787011,0.264495,-1.237352, + -0.02449,0.224062,-0.974267,-2.433366,0.078222,-1.371269, + -0.261543,0.44691,-0.855492,-2.787011,0.264495,-1.237352, + -0.0448,0.42163,-0.905661,-2.47375,0.300945,-1.316695, + -0.017579,0.132168,-0.991072,-2.41473,-0.108377,-1.395384, + -0.351241,0.075821,-0.93321,-2.649338,-0.241719,-1.339644, + -0.33898,0.203127,-0.918603,-2.687022,0.076781,-1.290565, + -0.017579,0.132168,-0.991072,-2.41473,-0.108377,-1.395384, + -0.33898,0.203127,-0.918603,-2.687022,0.076781,-1.290565, + -0.02449,0.224062,-0.974267,-2.433366,0.078222,-1.371269, + -0.055858,0.145868,-0.987726,-2.38292,-0.41745,-1.375045, + -0.311485,0.082882,-0.94663,-2.616467,-0.511373,-1.344133, + -0.351241,0.075821,-0.93321,-2.649338,-0.241719,-1.339644, + -0.055858,0.145868,-0.987726,-2.38292,-0.41745,-1.375045, + -0.351241,0.075821,-0.93321,-2.649338,-0.241719,-1.339644, + -0.017579,0.132168,-0.991072,-2.41473,-0.108377,-1.395384, + -0.115746,0.20405,-0.972094,-2.430508,-0.822313,-1.254486, + -0.285709,0.130064,-0.949449,-2.624856,-0.8882,-1.261176, + -0.311485,0.082882,-0.94663,-2.616467,-0.511373,-1.344133, + -0.115746,0.20405,-0.972094,-2.430508,-0.822313,-1.254486, + -0.311485,0.082882,-0.94663,-2.616467,-0.511373,-1.344133, + -0.055858,0.145868,-0.987726,-2.38292,-0.41745,-1.375045, + -0.164191,0.153328,-0.974439,-2.566746,-1.211312,-1.167101, + -0.279485,0.127803,-0.951606,-2.725776,-1.214862,-1.190384, + -0.285709,0.130064,-0.949449,-2.624856,-0.8882,-1.261176, + -0.164191,0.153328,-0.974439,-2.566746,-1.211312,-1.167101, + -0.285709,0.130064,-0.949449,-2.624856,-0.8882,-1.261176, + -0.115746,0.20405,-0.972094,-2.430508,-0.822313,-1.254486, + -0.15812,-0.033626,-0.986847,-2.765069,-1.561164,-1.084313, + -0.234266,0.044111,-0.971171,-2.862576,-1.546894,-1.117139, + -0.279485,0.127803,-0.951606,-2.725776,-1.214862,-1.190384, + -0.15812,-0.033626,-0.986847,-2.765069,-1.561164,-1.084313, + -0.279485,0.127803,-0.951606,-2.725776,-1.214862,-1.190384, + -0.164191,0.153328,-0.974439,-2.566746,-1.211312,-1.167101, + -0.108631,-0.122719,-0.986478,-3.35851,1.810253,-0.380095, + -0.379807,-0.084066,-0.921238,-3.519716,1.685231,-0.31713, + -0.153783,-0.988105,0,-3.507689,1.700214,0, + -0.108631,-0.122719,-0.986478,-3.35851,1.810253,-0.380095, + -0.153783,-0.988105,0,-3.507689,1.700214,0, + 0.072535,0.997366,0,-3.392806,1.769365,0, + -0.006683,-0.232823,-0.972496,-3.395381,1.726325,-0.55477, + -0.373751,-0.169261,-0.911954,-3.527168,1.583508,-0.512679, + -0.379807,-0.084066,-0.921238,-3.519716,1.685231,-0.31713, + -0.006683,-0.232823,-0.972496,-3.395381,1.726325,-0.55477, + -0.379807,-0.084066,-0.921238,-3.519716,1.685231,-0.31713, + -0.108631,-0.122719,-0.986478,-3.35851,1.810253,-0.380095, + -0.004872,-0.216103,-0.976358,-3.338742,1.598933,-0.689636, + -0.426971,-0.09322,-0.899447,-3.512997,1.44805,-0.611386, + -0.373751,-0.169261,-0.911954,-3.527168,1.583508,-0.512679, + -0.004872,-0.216103,-0.976358,-3.338742,1.598933,-0.689636, + -0.373751,-0.169261,-0.911954,-3.527168,1.583508,-0.512679, + -0.006683,-0.232823,-0.972496,-3.395381,1.726325,-0.55477, + 0.193955,-0.251788,-0.948148,-3.27808,1.432418,-0.853958, + -0.457657,0.090776,-0.884483,-3.476235,1.287798,-0.704766, + -0.426971,-0.09322,-0.899447,-3.512997,1.44805,-0.611386, + 0.193955,-0.251788,-0.948148,-3.27808,1.432418,-0.853958, + -0.426971,-0.09322,-0.899447,-3.512997,1.44805,-0.611386, + -0.004872,-0.216103,-0.976358,-3.338742,1.598933,-0.689636, + -0.337275,0.918092,-0.208215,-3.244771,1.19554,-0.910945, + -0.575033,0.794917,-0.193504,-3.442151,1.105486,-0.762934, + -0.457657,0.090776,-0.884483,-3.476235,1.287798,-0.704766, + -0.337275,0.918092,-0.208215,-3.244771,1.19554,-0.910945, + -0.457657,0.090776,-0.884483,-3.476235,1.287798,-0.704766, + 0.193955,-0.251788,-0.948148,-3.27808,1.432418,-0.853958, + -0.47652,0.732046,-0.486866,-3.19641,0.797564,-0.985913, + -0.636638,0.552106,-0.538397,-3.379131,0.767915,-0.885996, + -0.575033,0.794917,-0.193504,-3.442151,1.105486,-0.762934, + -0.47652,0.732046,-0.486866,-3.19641,0.797564,-0.985913, + -0.575033,0.794917,-0.193504,-3.442151,1.105486,-0.762934, + -0.337275,0.918092,-0.208215,-3.244771,1.19554,-0.910945, + -0.505556,0.519614,-0.688778,-3.112555,0.457376,-1.084816, + -0.643784,0.341688,-0.684684,-3.306875,0.379713,-0.98762, + -0.636638,0.552106,-0.538397,-3.379131,0.767915,-0.885996, + -0.505556,0.519614,-0.688778,-3.112555,0.457376,-1.084816, + -0.636638,0.552106,-0.538397,-3.379131,0.767915,-0.885996, + -0.47652,0.732046,-0.486866,-3.19641,0.797564,-0.985913, + -0.539732,0.31653,-0.780063,-3.044646,0.224321,-1.164934, + -0.646492,0.202786,-0.735477,-3.251181,0.175063,-1.053445, + -0.643784,0.341688,-0.684684,-3.306875,0.379713,-0.98762, + -0.539732,0.31653,-0.780063,-3.044646,0.224321,-1.164934, + -0.643784,0.341688,-0.684684,-3.306875,0.379713,-0.98762, + -0.505556,0.519614,-0.688778,-3.112555,0.457376,-1.084816, + -0.545639,0.142044,-0.825894,-2.971546,0.032038,-1.215971, + -0.624566,0.121329,-0.77149,-3.160225,-0.018852,-1.113626, + -0.646492,0.202786,-0.735477,-3.251181,0.175063,-1.053445, + -0.545639,0.142044,-0.825894,-2.971546,0.032038,-1.215971, + -0.646492,0.202786,-0.735477,-3.251181,0.175063,-1.053445, + -0.539732,0.31653,-0.780063,-3.044646,0.224321,-1.164934, + -0.512472,0.102596,-0.852553,-2.90708,-0.345582,-1.281557, + -0.588581,0.130279,-0.797872,-3.101125,-0.35476,-1.162409, + -0.624566,0.121329,-0.77149,-3.160225,-0.018852,-1.113626, + -0.512472,0.102596,-0.852553,-2.90708,-0.345582,-1.281557, + -0.624566,0.121329,-0.77149,-3.160225,-0.018852,-1.113626, + -0.545639,0.142044,-0.825894,-2.971546,0.032038,-1.215971, + -0.449233,0.123555,-0.88483,-2.901159,-0.619504,-1.284058, + -0.553145,0.12021,-0.824367,-3.096267,-0.6681,-1.140081, + -0.588581,0.130279,-0.797872,-3.101125,-0.35476,-1.162409, + -0.449233,0.123555,-0.88483,-2.901159,-0.619504,-1.284058, + -0.588581,0.130279,-0.797872,-3.101125,-0.35476,-1.162409, + -0.512472,0.102596,-0.852553,-2.90708,-0.345582,-1.281557, + -0.404056,0.117264,-0.907187,-2.937658,-1.002749,-1.219413, + -0.547788,0.055501,-0.834774,-3.122061,-0.998702,-1.065015, + -0.553145,0.12021,-0.824367,-3.096267,-0.6681,-1.140081, + -0.404056,0.117264,-0.907187,-2.937658,-1.002749,-1.219413, + -0.553145,0.12021,-0.824367,-3.096267,-0.6681,-1.140081, + -0.449233,0.123555,-0.88483,-2.901159,-0.619504,-1.284058, + -0.387051,0.087837,-0.917865,-2.982676,-1.264649,-1.133596, + -0.563128,0.005618,-0.826351,-3.15021,-1.259588,-1.001021, + -0.547788,0.055501,-0.834774,-3.122061,-0.998702,-1.065015, + -0.387051,0.087837,-0.917865,-2.982676,-1.264649,-1.133596, + -0.547788,0.055501,-0.834774,-3.122061,-0.998702,-1.065015, + -0.404056,0.117264,-0.907187,-2.937658,-1.002749,-1.219413, + -0.390861,0.032481,-0.919876,-3.063133,-1.440555,-1.090926, + -0.596319,-0.021767,-0.802452,-3.188954,-1.408279,-0.963611, + -0.563128,0.005618,-0.826351,-3.15021,-1.259588,-1.001021, + -0.390861,0.032481,-0.919876,-3.063133,-1.440555,-1.090926, + -0.563128,0.005618,-0.826351,-3.15021,-1.259588,-1.001021, + -0.387051,0.087837,-0.917865,-2.982676,-1.264649,-1.133596, + -0.379807,-0.084066,-0.921238,-3.519716,1.685231,-0.31713, + -0.6343,-0.110875,-0.765095,-3.734989,1.589433,-0.295202, + -0.626255,-0.080061,-0.775497,-3.690685,1.60208,0, + -0.379807,-0.084066,-0.921238,-3.519716,1.685231,-0.31713, + -0.626255,-0.080061,-0.775497,-3.690685,1.60208,0, + -0.153783,-0.988105,0,-3.507689,1.700214,0, + -0.373751,-0.169261,-0.911954,-3.527168,1.583508,-0.512679, + -0.619245,-0.050391,-0.783579,-3.697974,1.466697,-0.433432, + -0.6343,-0.110875,-0.765095,-3.734989,1.589433,-0.295202, + -0.373751,-0.169261,-0.911954,-3.527168,1.583508,-0.512679, + -0.6343,-0.110875,-0.765095,-3.734989,1.589433,-0.295202, + -0.379807,-0.084066,-0.921238,-3.519716,1.685231,-0.31713, + -0.426971,-0.09322,-0.899447,-3.512997,1.44805,-0.611386, + -0.549206,0.149158,-0.822268,-3.684619,1.35069,-0.501428, + -0.619245,-0.050391,-0.783579,-3.697974,1.466697,-0.433432, + -0.426971,-0.09322,-0.899447,-3.512997,1.44805,-0.611386, + -0.619245,-0.050391,-0.783579,-3.697974,1.466697,-0.433432, + -0.373751,-0.169261,-0.911954,-3.527168,1.583508,-0.512679, + -0.457657,0.090776,-0.884483,-3.476235,1.287798,-0.704766, + -0.846545,0.532317,0,-3.655148,1.190938,-0.573692, + -0.549206,0.149158,-0.822268,-3.684619,1.35069,-0.501428, + -0.457657,0.090776,-0.884483,-3.476235,1.287798,-0.704766, + -0.549206,0.149158,-0.822268,-3.684619,1.35069,-0.501428, + -0.426971,-0.09322,-0.899447,-3.512997,1.44805,-0.611386, + -0.575033,0.794917,-0.193504,-3.442151,1.105486,-0.762934, + -0.881408,0.44424,-0.16053,-3.639878,1.015186,-0.615203, + -0.846545,0.532317,0,-3.655148,1.190938,-0.573692, + -0.575033,0.794917,-0.193504,-3.442151,1.105486,-0.762934, + -0.846545,0.532317,0,-3.655148,1.190938,-0.573692, + -0.457657,0.090776,-0.884483,-3.476235,1.287798,-0.704766, + -0.636638,0.552106,-0.538397,-3.379131,0.767915,-0.885996, + -0.881352,0.261345,-0.393596,-3.582867,0.734419,-0.697787, + -0.881408,0.44424,-0.16053,-3.639878,1.015186,-0.615203, + -0.636638,0.552106,-0.538397,-3.379131,0.767915,-0.885996, + -0.881408,0.44424,-0.16053,-3.639878,1.015186,-0.615203, + -0.575033,0.794917,-0.193504,-3.442151,1.105486,-0.762934, + -0.643784,0.341688,-0.684684,-3.306875,0.379713,-0.98762, + -0.880731,0.130089,-0.4554,-3.504525,0.405574,-0.847066, + -0.881352,0.261345,-0.393596,-3.582867,0.734419,-0.697787, + -0.643784,0.341688,-0.684684,-3.306875,0.379713,-0.98762, + -0.881352,0.261345,-0.393596,-3.582867,0.734419,-0.697787, + -0.636638,0.552106,-0.538397,-3.379131,0.767915,-0.885996, + -0.646492,0.202786,-0.735477,-3.251181,0.175063,-1.053445, + -0.874101,0.053175,-0.482825,-3.424258,0.158638,-0.918279, + -0.880731,0.130089,-0.4554,-3.504525,0.405574,-0.847066, + -0.646492,0.202786,-0.735477,-3.251181,0.175063,-1.053445, + -0.880731,0.130089,-0.4554,-3.504525,0.405574,-0.847066, + -0.643784,0.341688,-0.684684,-3.306875,0.379713,-0.98762, + -0.624566,0.121329,-0.77149,-3.160225,-0.018852,-1.113626, + -0.875552,0.01506,-0.482889,-3.365413,-0.113447,-0.9524, + -0.874101,0.053175,-0.482825,-3.424258,0.158638,-0.918279, + -0.624566,0.121329,-0.77149,-3.160225,-0.018852,-1.113626, + -0.874101,0.053175,-0.482825,-3.424258,0.158638,-0.918279, + -0.646492,0.202786,-0.735477,-3.251181,0.175063,-1.053445, + -0.588581,0.130279,-0.797872,-3.101125,-0.35476,-1.162409, + -0.86587,-0.001845,-0.500266,-3.290393,-0.424259,-0.984153, + -0.875552,0.01506,-0.482889,-3.365413,-0.113447,-0.9524, + -0.588581,0.130279,-0.797872,-3.101125,-0.35476,-1.162409, + -0.875552,0.01506,-0.482889,-3.365413,-0.113447,-0.9524, + -0.624566,0.121329,-0.77149,-3.160225,-0.018852,-1.113626, + -0.553145,0.12021,-0.824367,-3.096267,-0.6681,-1.140081, + -0.84112,-0.026303,-0.540209,-3.233333,-0.683782,-1.015512, + -0.86587,-0.001845,-0.500266,-3.290393,-0.424259,-0.984153, + -0.553145,0.12021,-0.824367,-3.096267,-0.6681,-1.140081, + -0.86587,-0.001845,-0.500266,-3.290393,-0.424259,-0.984153, + -0.588581,0.130279,-0.797872,-3.101125,-0.35476,-1.162409, + -0.547788,0.055501,-0.834774,-3.122061,-0.998702,-1.065015, + -0.813168,-0.06637,-0.578232,-3.238094,-0.979377,-0.961631, + -0.84112,-0.026303,-0.540209,-3.233333,-0.683782,-1.015512, + -0.547788,0.055501,-0.834774,-3.122061,-0.998702,-1.065015, + -0.84112,-0.026303,-0.540209,-3.233333,-0.683782,-1.015512, + -0.553145,0.12021,-0.824367,-3.096267,-0.6681,-1.140081, + -0.563128,0.005618,-0.826351,-3.15021,-1.259588,-1.001021, + -0.799953,-0.096213,-0.592299,-3.27751,-1.177346,-0.9153, + -0.813168,-0.06637,-0.578232,-3.238094,-0.979377,-0.961631, + -0.563128,0.005618,-0.826351,-3.15021,-1.259588,-1.001021, + -0.813168,-0.06637,-0.578232,-3.238094,-0.979377,-0.961631, + -0.547788,0.055501,-0.834774,-3.122061,-0.998702,-1.065015, + -0.596319,-0.021767,-0.802452,-3.188954,-1.408279,-0.963611, + -0.811102,-0.12903,-0.570495,-3.319817,-1.365015,-0.886015, + -0.799953,-0.096213,-0.592299,-3.27751,-1.177346,-0.9153, + -0.596319,-0.021767,-0.802452,-3.188954,-1.408279,-0.963611, + -0.799953,-0.096213,-0.592299,-3.27751,-1.177346,-0.9153, + -0.563128,0.005618,-0.826351,-3.15021,-1.259588,-1.001021, + -0.6343,-0.110875,-0.765095,-3.734989,1.589433,-0.295202, + -0.880002,-0.033987,-0.473752,-3.709741,1.351194,-0.211745, + -0.848349,-0.120539,-0.515533,-3.709827,1.417763,0, + -0.6343,-0.110875,-0.765095,-3.734989,1.589433,-0.295202, + -0.848349,-0.120539,-0.515533,-3.709827,1.417763,0, + -0.626255,-0.080061,-0.775497,-3.690685,1.60208,0, + -0.619245,-0.050391,-0.783579,-3.697974,1.466697,-0.433432, + -0.870331,0.069096,-0.487595,-3.701634,1.27265,-0.270469, + -0.880002,-0.033987,-0.473752,-3.709741,1.351194,-0.211745, + -0.619245,-0.050391,-0.783579,-3.697974,1.466697,-0.433432, + -0.880002,-0.033987,-0.473752,-3.709741,1.351194,-0.211745, + -0.6343,-0.110875,-0.765095,-3.734989,1.589433,-0.295202, + -0.549206,0.149158,-0.822268,-3.684619,1.35069,-0.501428, + -0.822733,0.223687,-0.522565,-3.695872,1.156978,-0.316829, + -0.870331,0.069096,-0.487595,-3.701634,1.27265,-0.270469, + -0.549206,0.149158,-0.822268,-3.684619,1.35069,-0.501428, + -0.870331,0.069096,-0.487595,-3.701634,1.27265,-0.270469, + -0.619245,-0.050391,-0.783579,-3.697974,1.466697,-0.433432, + -0.846545,0.532317,0,-3.655148,1.190938,-0.573692, + -0.938447,-0.345423,0,-3.672431,1.044224,-0.364991, + -0.822733,0.223687,-0.522565,-3.695872,1.156978,-0.316829, + -0.846545,0.532317,0,-3.655148,1.190938,-0.573692, + -0.822733,0.223687,-0.522565,-3.695872,1.156978,-0.316829, + -0.549206,0.149158,-0.822268,-3.684619,1.35069,-0.501428, + -0.881408,0.44424,-0.16053,-3.639878,1.015186,-0.615203, + -0.946902,-0.290276,0.138264,-3.664355,0.932851,-0.370749, + -0.938447,-0.345423,0,-3.672431,1.044224,-0.364991, + -0.881408,0.44424,-0.16053,-3.639878,1.015186,-0.615203, + -0.938447,-0.345423,0,-3.672431,1.044224,-0.364991, + -0.846545,0.532317,0,-3.655148,1.190938,-0.573692, + -0.881352,0.261345,-0.393596,-3.582867,0.734419,-0.697787, + -0.982633,-0.143429,0.11773,-3.631292,0.701013,-0.420276, + -0.946902,-0.290276,0.138264,-3.664355,0.932851,-0.370749, + -0.881352,0.261345,-0.393596,-3.582867,0.734419,-0.697787, + -0.946902,-0.290276,0.138264,-3.664355,0.932851,-0.370749, + -0.881408,0.44424,-0.16053,-3.639878,1.015186,-0.615203, + -0.880731,0.130089,-0.4554,-3.504525,0.405574,-0.847066, + -0.995584,-0.070631,0.061842,-3.570384,0.385564,-0.52448, + -0.982633,-0.143429,0.11773,-3.631292,0.701013,-0.420276, + -0.880731,0.130089,-0.4554,-3.504525,0.405574,-0.847066, + -0.982633,-0.143429,0.11773,-3.631292,0.701013,-0.420276, + -0.881352,0.261345,-0.393596,-3.582867,0.734419,-0.697787, + -0.874101,0.053175,-0.482825,-3.424258,0.158638,-0.918279, + -0.997475,-0.070819,0.005318,-3.520188,0.140164,-0.618561, + -0.995584,-0.070631,0.061842,-3.570384,0.385564,-0.52448, + -0.874101,0.053175,-0.482825,-3.424258,0.158638,-0.918279, + -0.995584,-0.070631,0.061842,-3.570384,0.385564,-0.52448, + -0.880731,0.130089,-0.4554,-3.504525,0.405574,-0.847066, + -0.875552,0.01506,-0.482889,-3.365413,-0.113447,-0.9524, + -0.980175,-0.184883,0.071243,-3.458251,-0.12595,-0.731712, + -0.997475,-0.070819,0.005318,-3.520188,0.140164,-0.618561, + -0.875552,0.01506,-0.482889,-3.365413,-0.113447,-0.9524, + -0.997475,-0.070819,0.005318,-3.520188,0.140164,-0.618561, + -0.874101,0.053175,-0.482825,-3.424258,0.158638,-0.918279, + -0.86587,-0.001845,-0.500266,-3.290393,-0.424259,-0.984153, + -0.976177,-0.17359,0.130171,-3.406618,-0.343461,-0.746456, + -0.980175,-0.184883,0.071243,-3.458251,-0.12595,-0.731712, + -0.86587,-0.001845,-0.500266,-3.290393,-0.424259,-0.984153, + -0.980175,-0.184883,0.071243,-3.458251,-0.12595,-0.731712, + -0.875552,0.01506,-0.482889,-3.365413,-0.113447,-0.9524, + -0.84112,-0.026303,-0.540209,-3.233333,-0.683782,-1.015512, + -0.984416,-0.175855,-0.000915,-3.283698,-0.730967,-0.793898, + -0.976177,-0.17359,0.130171,-3.406618,-0.343461,-0.746456, + -0.84112,-0.026303,-0.540209,-3.233333,-0.683782,-1.015512, + -0.976177,-0.17359,0.130171,-3.406618,-0.343461,-0.746456, + -0.86587,-0.001845,-0.500266,-3.290393,-0.424259,-0.984153, + -0.285709,0.130064,-0.949449,-2.624856,-0.8882,-1.261176, + -0.279485,0.127803,-0.951606,-2.725776,-1.214862,-1.190384, + -0.387051,0.087837,-0.917865,-2.982676,-1.264649,-1.133596, + -0.285709,0.130064,-0.949449,-2.624856,-0.8882,-1.261176, + -0.387051,0.087837,-0.917865,-2.982676,-1.264649,-1.133596, + -0.404056,0.117264,-0.907187,-2.937658,-1.002749,-1.219413, + -0.311485,0.082882,-0.94663,-2.616467,-0.511373,-1.344133, + -0.285709,0.130064,-0.949449,-2.624856,-0.8882,-1.261176, + -0.404056,0.117264,-0.907187,-2.937658,-1.002749,-1.219413, + -0.311485,0.082882,-0.94663,-2.616467,-0.511373,-1.344133, + -0.404056,0.117264,-0.907187,-2.937658,-1.002749,-1.219413, + -0.449233,0.123555,-0.88483,-2.901159,-0.619504,-1.284058, + -0.351241,0.075821,-0.93321,-2.649338,-0.241719,-1.339644, + -0.311485,0.082882,-0.94663,-2.616467,-0.511373,-1.344133, + -0.449233,0.123555,-0.88483,-2.901159,-0.619504,-1.284058, + -0.351241,0.075821,-0.93321,-2.649338,-0.241719,-1.339644, + -0.449233,0.123555,-0.88483,-2.901159,-0.619504,-1.284058, + -0.512472,0.102596,-0.852553,-2.90708,-0.345582,-1.281557, + -0.33898,0.203127,-0.918603,-2.687022,0.076781,-1.290565, + -0.351241,0.075821,-0.93321,-2.649338,-0.241719,-1.339644, + -0.512472,0.102596,-0.852553,-2.90708,-0.345582,-1.281557, + -0.33898,0.203127,-0.918603,-2.687022,0.076781,-1.290565, + -0.512472,0.102596,-0.852553,-2.90708,-0.345582,-1.281557, + -0.545639,0.142044,-0.825894,-2.971546,0.032038,-1.215971, + -0.261543,0.44691,-0.855492,-2.787011,0.264495,-1.237352, + -0.33898,0.203127,-0.918603,-2.687022,0.076781,-1.290565, + -0.545639,0.142044,-0.825894,-2.971546,0.032038,-1.215971, + -0.261543,0.44691,-0.855492,-2.787011,0.264495,-1.237352, + -0.545639,0.142044,-0.825894,-2.971546,0.032038,-1.215971, + -0.539732,0.31653,-0.780063,-3.044646,0.224321,-1.164934, + -0.169971,0.704712,-0.688833,-2.79063,0.46881,-1.224273, + -0.261543,0.44691,-0.855492,-2.787011,0.264495,-1.237352, + -0.539732,0.31653,-0.780063,-3.044646,0.224321,-1.164934, + -0.169971,0.704712,-0.688833,-2.79063,0.46881,-1.224273, + -0.539732,0.31653,-0.780063,-3.044646,0.224321,-1.164934, + -0.505556,0.519614,-0.688778,-3.112555,0.457376,-1.084816, + -0.088843,0.888,-0.45118,-2.825835,0.755899,-1.209042, + -0.169971,0.704712,-0.688833,-2.79063,0.46881,-1.224273, + -0.505556,0.519614,-0.688778,-3.112555,0.457376,-1.084816, + -0.088843,0.888,-0.45118,-2.825835,0.755899,-1.209042, + -0.505556,0.519614,-0.688778,-3.112555,0.457376,-1.084816, + -0.47652,0.732046,-0.486866,-3.19641,0.797564,-0.985913, + -0.051905,0.965082,-0.256753,-2.930312,1.10358,-1.125876, + -0.088843,0.888,-0.45118,-2.825835,0.755899,-1.209042, + -0.47652,0.732046,-0.486866,-3.19641,0.797564,-0.985913, + -0.051905,0.965082,-0.256753,-2.930312,1.10358,-1.125876, + -0.47652,0.732046,-0.486866,-3.19641,0.797564,-0.985913, + -0.337275,0.918092,-0.208215,-3.244771,1.19554,-0.910945, + -0.012448,0.906487,-0.422051,-3.028932,1.461517,-0.941324, + -0.051905,0.965082,-0.256753,-2.930312,1.10358,-1.125876, + -0.337275,0.918092,-0.208215,-3.244771,1.19554,-0.910945, + -0.012448,0.906487,-0.422051,-3.028932,1.461517,-0.941324, + -0.337275,0.918092,-0.208215,-3.244771,1.19554,-0.910945, + 0.193955,-0.251788,-0.948148,-3.27808,1.432418,-0.853958, + 0.1643,0.873906,-0.457487,-3.08565,1.65734,-0.784479, + -0.012448,0.906487,-0.422051,-3.028932,1.461517,-0.941324, + 0.193955,-0.251788,-0.948148,-3.27808,1.432418,-0.853958, + 0.1643,0.873906,-0.457487,-3.08565,1.65734,-0.784479, + 0.193955,-0.251788,-0.948148,-3.27808,1.432418,-0.853958, + -0.004872,-0.216103,-0.976358,-3.338742,1.598933,-0.689636, + 0.573426,-0.441087,-0.69038,-3.109047,1.789477,-0.565323, + 0.1643,0.873906,-0.457487,-3.08565,1.65734,-0.784479, + -0.004872,-0.216103,-0.976358,-3.338742,1.598933,-0.689636, + 0.573426,-0.441087,-0.69038,-3.109047,1.789477,-0.565323, + -0.004872,-0.216103,-0.976358,-3.338742,1.598933,-0.689636, + -0.006683,-0.232823,-0.972496,-3.395381,1.726325,-0.55477, + 0.49938,-0.45475,-0.737443,-3.07531,1.846,-0.363149, + 0.573426,-0.441087,-0.69038,-3.109047,1.789477,-0.565323, + -0.006683,-0.232823,-0.972496,-3.395381,1.726325,-0.55477, + 0.49938,-0.45475,-0.737443,-3.07531,1.846,-0.363149, + -0.006683,-0.232823,-0.972496,-3.395381,1.726325,-0.55477, + -0.108631,-0.122719,-0.986478,-3.35851,1.810253,-0.380095, + -0.15812,-0.033626,-0.986847,-2.765069,-1.561164,-1.084313, + -0.164191,0.153328,-0.974439,-2.566746,-1.211312,-1.167101, + 0.79444,0.150524,0.588394,-2.687162,-1.539807,-0.988048, + -0.164191,0.153328,-0.974439,-2.566746,-1.211312,-1.167101, + 0.53288,-0.088285,0.841573,-2.299356,-1.025449,-1.044687, + 0.07657,0.16758,-0.982881,-2.306662,-1.116976,-0.961238, + -0.164191,0.153328,-0.974439,-2.566746,-1.211312,-1.167101, + 0.07657,0.16758,-0.982881,-2.306662,-1.116976,-0.961238, + -0.955382,-0.23808,-0.174826,-2.462835,-1.3055,-0.966395, + -0.164191,0.153328,-0.974439,-2.566746,-1.211312,-1.167101, + -0.955382,-0.23808,-0.174826,-2.462835,-1.3055,-0.966395, + 0.137764,-0.289893,-0.947092,-2.591357,-1.510845,-0.88547, + -0.164191,0.153328,-0.974439,-2.566746,-1.211312,-1.167101, + 0.137764,-0.289893,-0.947092,-2.591357,-1.510845,-0.88547, + 0.79444,0.150524,0.588394,-2.687162,-1.539807,-0.988048, + -0.363523,-0.150625,0.919327,1.921881,-2.157616,-0.692678, + -0.914496,-0.253608,0.315247,1.945206,-2.015769,-0.672724, + -0.53197,-0.108751,0.839751,1.747671,-2.067518,-0.638841, + -0.363523,-0.150625,0.919327,1.921881,-2.157616,-0.692678, + -0.53197,-0.108751,0.839751,1.747671,-2.067518,-0.638841, + -0.570406,-0.192005,0.798606,1.772999,-2.230292,-0.64494, + 0.546571,-0.125171,0.828005,2.069379,1.727818,-0.212746, + -0.385788,0.922588,0,2.042206,1.777154,0, + 0.756976,-0.653442,0,2.128139,1.788397,0, + 0.546571,-0.125171,0.828005,2.069379,1.727818,-0.212746, + 0.756976,-0.653442,0,2.128139,1.788397,0, + 0.547549,-0.279581,-0.788686,2.13239,1.755821,-0.180271, + 0.726897,-0.546446,-0.415953,-2.955052,-1.49684,-1.128812, + -0.279485,0.127803,-0.951606,-2.725776,-1.214862,-1.190384, + -0.234266,0.044111,-0.971171,-2.862576,-1.546894,-1.117139, + 0.776291,-0.374868,-0.5068,-3.23261,-1.834299,-1.087832, + 0.356923,-0.210291,-0.910156,-3.357996,-1.811803,-0.975625, + -0.596319,-0.021767,-0.802452,-3.188954,-1.408279,-0.963611, + 0.776291,-0.374868,-0.5068,-3.23261,-1.834299,-1.087832, + -0.596319,-0.021767,-0.802452,-3.188954,-1.408279,-0.963611, + -0.390861,0.032481,-0.919876,-3.063133,-1.440555,-1.090926, + 0.726897,-0.546446,-0.415953,-2.955052,-1.49684,-1.128812, + -0.390861,0.032481,-0.919876,-3.063133,-1.440555,-1.090926, + -0.387051,0.087837,-0.917865,-2.982676,-1.264649,-1.133596, + 0.726897,-0.546446,-0.415953,-2.955052,-1.49684,-1.128812, + -0.387051,0.087837,-0.917865,-2.982676,-1.264649,-1.133596, + -0.279485,0.127803,-0.951606,-2.725776,-1.214862,-1.190384, + -0.032036,-0.072305,-0.996868,-3.342096,-1.533989,-0.921628, + -0.086361,-0.084973,-0.992634,-3.36599,-1.48517,-0.888076, + -0.811102,-0.12903,-0.570495,-3.319817,-1.365015,-0.886015, + -0.032036,-0.072305,-0.996868,-3.342096,-1.533989,-0.921628, + -0.811102,-0.12903,-0.570495,-3.319817,-1.365015,-0.886015, + -0.596319,-0.021767,-0.802452,-3.188954,-1.408279,-0.963611, + 0.356923,-0.210291,-0.910156,-3.357996,-1.811803,-0.975625, + -0.032036,-0.072305,-0.996868,-3.342096,-1.533989,-0.921628, + -0.596319,-0.021767,-0.802452,-3.188954,-1.408279,-0.963611, + -0.807765,-0.096776,-0.581507,-2.892438,-1.95081,-0.87812, + 0.048753,-0.975535,-0.21437,-2.734184,-1.717948,-0.749581, + 0.43907,-0.579988,-0.686171,-2.811581,-1.79821,-0.712737, + -0.807765,-0.096776,-0.581507,-2.892438,-1.95081,-0.87812, + 0.43907,-0.579988,-0.686171,-2.811581,-1.79821,-0.712737, + 0.982106,-0.010346,-0.188044,-2.964215,-1.978727,-0.776572, + -0.807765,-0.096776,-0.581507,-2.892438,-1.95081,-0.87812, + 0.26198,0.048424,0.963858,-2.837147,-1.791733,-0.921563, + 0.048753,-0.975535,-0.21437,-2.734184,-1.717948,-0.749581, + 0.866897,-0.268351,-0.420091,-3.030605,-2.311222,-0.88433, + 0.773659,-0.235087,0.588375,-3.144012,-2.333635,-0.829994, + -0.065687,-0.249194,0.966223,-3.132772,-2.528669,-0.848639, + 0.866897,-0.268351,-0.420091,-3.030605,-2.311222,-0.88433, + -0.065687,-0.249194,0.966223,-3.132772,-2.528669,-0.848639, + 0.886562,-0.46255,-0.007485,-3.04661,-2.510881,-0.900772, + 0.517272,-0.552302,-0.653753,-3.302419,-3.017921,-1.128514, + -0.020456,0.943466,-0.330837,-3.32033,-2.827513,-1.063914, + 0.030762,-0.124297,0.991768,-3.26181,-2.821069,-1.088218, + 0.517272,-0.552302,-0.653753,-3.302419,-3.017921,-1.128514, + 0.030762,-0.124297,0.991768,-3.26181,-2.821069,-1.088218, + 0.753698,-0.027204,0.656657,-3.223286,-3.00178,-1.126176, + -0.661663,-0.02548,-0.749368,-3.107105,-2.947818,-1.092235, + -0.753891,0.130682,-0.643872,-3.141072,-2.785287,-1.032318, + -0.156071,0.243426,-0.95728,-3.053267,-2.764905,-1.043008, + -0.661663,-0.02548,-0.749368,-3.107105,-2.947818,-1.092235, + -0.156071,0.243426,-0.95728,-3.053267,-2.764905,-1.043008, + -0.080858,0.024731,-0.996419,-2.986345,-2.93377,-1.087679, + -0.080858,0.024731,-0.996419,-2.986345,-2.93377,-1.087679, + -0.156071,0.243426,-0.95728,-3.053267,-2.764905,-1.043008, + 0.484364,0.195734,-0.85269,-3.016419,-2.765091,-0.966671, + -0.080858,0.024731,-0.996419,-2.986345,-2.93377,-1.087679, + 0.484364,0.195734,-0.85269,-3.016419,-2.765091,-0.966671, + 0.507452,0.36284,-0.781563,-2.946527,-2.939327,-0.986343, + 0.517272,-0.552302,-0.653753,-3.302419,-3.017921,-1.128514, + 0.753698,-0.027204,0.656657,-3.223286,-3.00178,-1.126176, + 0.121953,0.140869,-0.982488,-3.301857,-3.074776,-1.114869, + 0.121953,0.140869,-0.982488,-3.301857,-3.074776,-1.114869, + 0.913315,0.39776,0.087427,-3.227676,-3.14166,-1.103969, + 0.170703,0.25395,-0.952035,-3.316551,-3.168932,-1.121229, + 0.170703,0.25395,-0.952035,-3.316551,-3.168932,-1.121229, + 0.913315,0.39776,0.087427,-3.227676,-3.14166,-1.103969, + 0.977763,0.208696,-0.020643,-3.217306,-3.187686,-1.075214, + -0.080858,0.024731,-0.996419,-2.986345,-2.93377,-1.087679, + 0.507452,0.36284,-0.781563,-2.946527,-2.939327,-0.986343, + 0.737412,0.542596,-0.402261,-2.884711,-3.063896,-0.993766, + -0.080858,0.024731,-0.996419,-2.986345,-2.93377,-1.087679, + 0.737412,0.542596,-0.402261,-2.884711,-3.063896,-0.993766, + 0.637284,0.689194,-0.344791,-2.90901,-3.084482,-1.089147, + -0.661663,-0.02548,-0.749368,-3.107105,-2.947818,-1.092235, + -0.833016,0.038682,-0.551896,-3.177108,-2.979305,-1.139084, + -0.637764,0.107242,-0.76273,-3.196508,-2.788166,-1.045431, + -0.661663,-0.02548,-0.749368,-3.107105,-2.947818,-1.092235, + -0.637764,0.107242,-0.76273,-3.196508,-2.788166,-1.045431, + -0.753891,0.130682,-0.643872,-3.141072,-2.785287,-1.032318, + 0.753698,-0.027204,0.656657,-3.223286,-3.00178,-1.126176, + 0.030762,-0.124297,0.991768,-3.26181,-2.821069,-1.088218, + -0.637764,0.107242,-0.76273,-3.196508,-2.788166,-1.045431, + 0.753698,-0.027204,0.656657,-3.223286,-3.00178,-1.126176, + -0.637764,0.107242,-0.76273,-3.196508,-2.788166,-1.045431, + -0.833016,0.038682,-0.551896,-3.177108,-2.979305,-1.139084, + 0.197648,0.486888,-0.850809,-3.333954,-3.058673,-0.974748, + 0.121953,0.140869,-0.982488,-3.301857,-3.074776,-1.114869, + 0.170703,0.25395,-0.952035,-3.316551,-3.168932,-1.121229, + 0.197648,0.486888,-0.850809,-3.333954,-3.058673,-0.974748, + 0.170703,0.25395,-0.952035,-3.316551,-3.168932,-1.121229, + -0.67011,-0.018974,-0.742019,-3.330406,-3.18519,-0.950058, + -0.67011,-0.018974,-0.742019,-3.330406,-3.18519,-0.950058, + 0.170703,0.25395,-0.952035,-3.316551,-3.168932,-1.121229, + 0.977763,0.208696,-0.020643,-3.217306,-3.187686,-1.075214, + -0.67011,-0.018974,-0.742019,-3.330406,-3.18519,-0.950058, + 0.977763,0.208696,-0.020643,-3.217306,-3.187686,-1.075214, + 0.163153,0.19945,-0.96623,-3.223246,-3.225388,-0.976573, + -0.178214,-0.110838,0.977729,-3.294389,-3.166225,-0.842823, + -0.67011,-0.018974,-0.742019,-3.330406,-3.18519,-0.950058, + 0.163153,0.19945,-0.96623,-3.223246,-3.225388,-0.976573, + -0.178214,-0.110838,0.977729,-3.294389,-3.166225,-0.842823, + 0.163153,0.19945,-0.96623,-3.223246,-3.225388,-0.976573, + -0.948594,-0.185732,0.256269,-3.11957,-3.183977,-0.870739, + 0.197648,0.486888,-0.850809,-3.333954,-3.058673,-0.974748, + -0.67011,-0.018974,-0.742019,-3.330406,-3.18519,-0.950058, + -0.178214,-0.110838,0.977729,-3.294389,-3.166225,-0.842823, + 0.197648,0.486888,-0.850809,-3.333954,-3.058673,-0.974748, + -0.178214,-0.110838,0.977729,-3.294389,-3.166225,-0.842823, + -0.674431,0.094186,0.732306,-3.256731,-3.032131,-0.849693, + -0.674431,0.094186,0.732306,-3.256731,-3.032131,-0.849693, + -0.556404,-0.045521,0.829664,-3.300372,-2.795728,-0.878984, + -0.978077,-0.070308,0.196017,-3.339637,-2.846837,-0.966368, + -0.674431,0.094186,0.732306,-3.256731,-3.032131,-0.849693, + -0.978077,-0.070308,0.196017,-3.339637,-2.846837,-0.966368, + 0.197648,0.486888,-0.850809,-3.333954,-3.058673,-0.974748, + -0.080858,0.024731,-0.996419,-2.986345,-2.93377,-1.087679, + 0.637284,0.689194,-0.344791,-2.90901,-3.084482,-1.089147, + 0.503689,0.453945,-0.735004,-3.03125,-3.09594,-1.106355, + -0.080858,0.024731,-0.996419,-2.986345,-2.93377,-1.087679, + 0.503689,0.453945,-0.735004,-3.03125,-3.09594,-1.106355, + -0.661663,-0.02548,-0.749368,-3.107105,-2.947818,-1.092235, + 0.503689,0.453945,-0.735004,-3.03125,-3.09594,-1.106355, + -0.039603,0.339955,-0.939607,-3.121673,-3.120319,-1.136456, + -0.833016,0.038682,-0.551896,-3.177108,-2.979305,-1.139084, + 0.503689,0.453945,-0.735004,-3.03125,-3.09594,-1.106355, + -0.833016,0.038682,-0.551896,-3.177108,-2.979305,-1.139084, + -0.661663,-0.02548,-0.749368,-3.107105,-2.947818,-1.092235, + -0.833016,0.038682,-0.551896,-3.177108,-2.979305,-1.139084, + -0.039603,0.339955,-0.939607,-3.121673,-3.120319,-1.136456, + -0.377491,-0.043727,-0.92498,-3.169546,-3.135273,-1.128247, + -0.833016,0.038682,-0.551896,-3.177108,-2.979305,-1.139084, + -0.377491,-0.043727,-0.92498,-3.169546,-3.135273,-1.128247, + 0.753698,-0.027204,0.656657,-3.223286,-3.00178,-1.126176, + 0.913315,0.39776,0.087427,-3.227676,-3.14166,-1.103969, + -0.377491,-0.043727,-0.92498,-3.169546,-3.135273,-1.128247, + 0.977763,0.208696,-0.020643,-3.217306,-3.187686,-1.075214, + 0.121953,0.140869,-0.982488,-3.301857,-3.074776,-1.114869, + 0.753698,-0.027204,0.656657,-3.223286,-3.00178,-1.126176, + -0.377491,-0.043727,-0.92498,-3.169546,-3.135273,-1.128247, + 0.121953,0.140869,-0.982488,-3.301857,-3.074776,-1.114869, + -0.377491,-0.043727,-0.92498,-3.169546,-3.135273,-1.128247, + 0.913315,0.39776,0.087427,-3.227676,-3.14166,-1.103969, + 0.121953,0.140869,-0.982488,-3.301857,-3.074776,-1.114869, + 0.197648,0.486888,-0.850809,-3.333954,-3.058673,-0.974748, + 0.517272,-0.552302,-0.653753,-3.302419,-3.017921,-1.128514, + -0.978077,-0.070308,0.196017,-3.339637,-2.846837,-0.966368, + -0.020456,0.943466,-0.330837,-3.32033,-2.827513,-1.063914, + 0.517272,-0.552302,-0.653753,-3.302419,-3.017921,-1.128514, + -0.978077,-0.070308,0.196017,-3.339637,-2.846837,-0.966368, + 0.517272,-0.552302,-0.653753,-3.302419,-3.017921,-1.128514, + 0.197648,0.486888,-0.850809,-3.333954,-3.058673,-0.974748, + 0.737412,0.542596,-0.402261,-2.884711,-3.063896,-0.993766, + 0.507452,0.36284,-0.781563,-2.946527,-2.939327,-0.986343, + 0.72114,0.258272,0.642848,-3.008412,-2.89976,-0.904635, + 0.737412,0.542596,-0.402261,-2.884711,-3.063896,-0.993766, + 0.72114,0.258272,0.642848,-3.008412,-2.89976,-0.904635, + 0.684558,0.361154,0.633205,-2.928681,-3.072892,-0.924772, + -0.178214,-0.110838,0.977729,-3.294389,-3.166225,-0.842823, + -0.948594,-0.185732,0.256269,-3.11957,-3.183977,-0.870739, + -0.058899,-0.007802,0.998233,-3.166971,-3.002766,-0.812106, + -0.178214,-0.110838,0.977729,-3.294389,-3.166225,-0.842823, + -0.058899,-0.007802,0.998233,-3.166971,-3.002766,-0.812106, + -0.674431,0.094186,0.732306,-3.256731,-3.032131,-0.849693, + -0.948594,-0.185732,0.256269,-3.11957,-3.183977,-0.870739, + 0.308087,0.149605,0.939521,-3.011987,-3.092,-0.860973, + 0.403627,0.101273,0.909301,-3.06981,-2.928755,-0.845236, + -0.948594,-0.185732,0.256269,-3.11957,-3.183977,-0.870739, + 0.403627,0.101273,0.909301,-3.06981,-2.928755,-0.845236, + -0.058899,-0.007802,0.998233,-3.166971,-3.002766,-0.812106, + 0.308087,0.149605,0.939521,-3.011987,-3.092,-0.860973, + 0.684558,0.361154,0.633205,-2.928681,-3.072892,-0.924772, + 0.72114,0.258272,0.642848,-3.008412,-2.89976,-0.904635, + 0.308087,0.149605,0.939521,-3.011987,-3.092,-0.860973, + 0.72114,0.258272,0.642848,-3.008412,-2.89976,-0.904635, + 0.403627,0.101273,0.909301,-3.06981,-2.928755,-0.845236, + -0.058899,-0.007802,0.998233,-3.166971,-3.002766,-0.812106, + 0.403627,0.101273,0.909301,-3.06981,-2.928755,-0.845236, + 0.313529,0.096126,0.944701,-3.137383,-2.776449,-0.844117, + -0.058899,-0.007802,0.998233,-3.166971,-3.002766,-0.812106, + 0.313529,0.096126,0.944701,-3.137383,-2.776449,-0.844117, + -0.121543,0.046,0.99152,-3.184812,-2.768053,-0.850127, + 0.313529,0.096126,0.944701,-3.137383,-2.776449,-0.844117, + 0.403627,0.101273,0.909301,-3.06981,-2.928755,-0.845236, + 0.72114,0.258272,0.642848,-3.008412,-2.89976,-0.904635, + 0.313529,0.096126,0.944701,-3.137383,-2.776449,-0.844117, + 0.72114,0.258272,0.642848,-3.008412,-2.89976,-0.904635, + 0.761939,0.13671,0.633055,-3.040038,-2.780893,-0.914614, + -0.674431,0.094186,0.732306,-3.256731,-3.032131,-0.849693, + -0.058899,-0.007802,0.998233,-3.166971,-3.002766,-0.812106, + -0.121543,0.046,0.99152,-3.184812,-2.768053,-0.850127, + -0.674431,0.094186,0.732306,-3.256731,-3.032131,-0.849693, + -0.121543,0.046,0.99152,-3.184812,-2.768053,-0.850127, + -0.556404,-0.045521,0.829664,-3.300372,-2.795728,-0.878984, + 0.507452,0.36284,-0.781563,-2.946527,-2.939327,-0.986343, + 0.484364,0.195734,-0.85269,-3.016419,-2.765091,-0.966671, + 0.761939,0.13671,0.633055,-3.040038,-2.780893,-0.914614, + 0.507452,0.36284,-0.781563,-2.946527,-2.939327,-0.986343, + 0.761939,0.13671,0.633055,-3.040038,-2.780893,-0.914614, + 0.72114,0.258272,0.642848,-3.008412,-2.89976,-0.904635, + -0.156071,0.243426,-0.95728,-3.053267,-2.764905,-1.043008, + -0.753891,0.130682,-0.643872,-3.141072,-2.785287,-1.032318, + -0.440199,0.219838,-0.870572,-3.162498,-2.556375,-1.058409, + -0.156071,0.243426,-0.95728,-3.053267,-2.764905,-1.043008, + -0.440199,0.219838,-0.870572,-3.162498,-2.556375,-1.058409, + -0.775358,0.344514,-0.529274,-3.078699,-2.553982,-1.046834, + -0.020456,0.943466,-0.330837,-3.32033,-2.827513,-1.063914, + -0.978077,-0.070308,0.196017,-3.339637,-2.846837,-0.966368, + -0.326843,-0.236652,0.91497,-3.372066,-2.569159,-0.904785, + -0.020456,0.943466,-0.330837,-3.32033,-2.827513,-1.063914, + -0.326843,-0.236652,0.91497,-3.372066,-2.569159,-0.904785, + -0.354049,-0.10839,-0.928925,-3.347304,-2.573628,-0.955211, + 0.030762,-0.124297,0.991768,-3.26181,-2.821069,-1.088218, + -0.020456,0.943466,-0.330837,-3.32033,-2.827513,-1.063914, + -0.354049,-0.10839,-0.928925,-3.347304,-2.573628,-0.955211, + 0.030762,-0.124297,0.991768,-3.26181,-2.821069,-1.088218, + -0.354049,-0.10839,-0.928925,-3.347304,-2.573628,-0.955211, + 0.433219,-0.09361,-0.896414,-3.251541,-2.56405,-1.023627, + -0.637764,0.107242,-0.76273,-3.196508,-2.788166,-1.045431, + 0.030762,-0.124297,0.991768,-3.26181,-2.821069,-1.088218, + 0.433219,-0.09361,-0.896414,-3.251541,-2.56405,-1.023627, + -0.637764,0.107242,-0.76273,-3.196508,-2.788166,-1.045431, + 0.433219,-0.09361,-0.896414,-3.251541,-2.56405,-1.023627, + -0.440199,0.219838,-0.870572,-3.162498,-2.556375,-1.058409, + -0.753891,0.130682,-0.643872,-3.141072,-2.785287,-1.032318, + -0.637764,0.107242,-0.76273,-3.196508,-2.788166,-1.045431, + -0.440199,0.219838,-0.870572,-3.162498,-2.556375,-1.058409, + -0.775358,0.344514,-0.529274,-3.078699,-2.553982,-1.046834, + -0.501053,-0.05946,-0.863371,-3.022819,-2.52224,-0.979148, + 0.484364,0.195734,-0.85269,-3.016419,-2.765091,-0.966671, + -0.775358,0.344514,-0.529274,-3.078699,-2.553982,-1.046834, + 0.484364,0.195734,-0.85269,-3.016419,-2.765091,-0.966671, + -0.156071,0.243426,-0.95728,-3.053267,-2.764905,-1.043008, + 0.255431,-0.055528,0.965231,-3.297886,-2.54902,-0.861657, + -0.326843,-0.236652,0.91497,-3.372066,-2.569159,-0.904785, + -0.978077,-0.070308,0.196017,-3.339637,-2.846837,-0.966368, + 0.255431,-0.055528,0.965231,-3.297886,-2.54902,-0.861657, + -0.978077,-0.070308,0.196017,-3.339637,-2.846837,-0.966368, + -0.556404,-0.045521,0.829664,-3.300372,-2.795728,-0.878984, + -0.215783,-0.895808,0.388544,-3.240554,-2.555467,-0.856262, + 0.255431,-0.055528,0.965231,-3.297886,-2.54902,-0.861657, + -0.556404,-0.045521,0.829664,-3.300372,-2.795728,-0.878984, + -0.215783,-0.895808,0.388544,-3.240554,-2.555467,-0.856262, + -0.556404,-0.045521,0.829664,-3.300372,-2.795728,-0.878984, + -0.121543,0.046,0.99152,-3.184812,-2.768053,-0.850127, + -0.065687,-0.249194,0.966223,-3.132772,-2.528669,-0.848639, + -0.215783,-0.895808,0.388544,-3.240554,-2.555467,-0.856262, + -0.121543,0.046,0.99152,-3.184812,-2.768053,-0.850127, + -0.065687,-0.249194,0.966223,-3.132772,-2.528669,-0.848639, + -0.121543,0.046,0.99152,-3.184812,-2.768053,-0.850127, + 0.313529,0.096126,0.944701,-3.137383,-2.776449,-0.844117, + 0.886562,-0.46255,-0.007485,-3.04661,-2.510881,-0.900772, + -0.065687,-0.249194,0.966223,-3.132772,-2.528669,-0.848639, + 0.313529,0.096126,0.944701,-3.137383,-2.776449,-0.844117, + 0.886562,-0.46255,-0.007485,-3.04661,-2.510881,-0.900772, + 0.313529,0.096126,0.944701,-3.137383,-2.776449,-0.844117, + 0.761939,0.13671,0.633055,-3.040038,-2.780893,-0.914614, + -0.501053,-0.05946,-0.863371,-3.022819,-2.52224,-0.979148, + 0.886562,-0.46255,-0.007485,-3.04661,-2.510881,-0.900772, + 0.761939,0.13671,0.633055,-3.040038,-2.780893,-0.914614, + -0.501053,-0.05946,-0.863371,-3.022819,-2.52224,-0.979148, + 0.761939,0.13671,0.633055,-3.040038,-2.780893,-0.914614, + 0.484364,0.195734,-0.85269,-3.016419,-2.765091,-0.966671, + -0.823768,0.005745,-0.566899,-3.27979,-1.162072,-0.784602, + -0.799953,-0.096213,-0.592299,-3.27751,-1.177346,-0.9153, + -0.811102,-0.12903,-0.570495,-3.319817,-1.365015,-0.886015, + -0.823768,0.005745,-0.566899,-3.27979,-1.162072,-0.784602, + -0.811102,-0.12903,-0.570495,-3.319817,-1.365015,-0.886015, + -0.782249,0.198377,-0.590536,-3.335942,-1.365685,-0.72459, + -0.838192,0.000365,-0.545375,-3.25121,-0.948205,-0.819868, + -0.984416,-0.175855,-0.000915,-3.283698,-0.730967,-0.793898, + -0.84112,-0.026303,-0.540209,-3.233333,-0.683782,-1.015512, + -0.838192,0.000365,-0.545375,-3.25121,-0.948205,-0.819868, + -0.84112,-0.026303,-0.540209,-3.233333,-0.683782,-1.015512, + -0.813168,-0.06637,-0.578232,-3.238094,-0.979377,-0.961631, + -0.823768,0.005745,-0.566899,-3.27979,-1.162072,-0.784602, + -0.838192,0.000365,-0.545375,-3.25121,-0.948205,-0.819868, + -0.813168,-0.06637,-0.578232,-3.238094,-0.979377,-0.961631, + -0.823768,0.005745,-0.566899,-3.27979,-1.162072,-0.784602, + -0.813168,-0.06637,-0.578232,-3.238094,-0.979377,-0.961631, + -0.799953,-0.096213,-0.592299,-3.27751,-1.177346,-0.9153, + -0.743901,0.102645,-0.66036,-3.415655,-0.308965,-0.671045, + -0.976177,-0.17359,0.130171,-3.406618,-0.343461,-0.746456, + -0.984416,-0.175855,-0.000915,-3.283698,-0.730967,-0.793898, + -0.472479,0.093412,-0.876377,-3.556552,0.704883,-0.28063, + -0.43302,-0.02622,-0.901003,-3.57817,0.837714,-0.288502, + -0.946902,-0.290276,0.138264,-3.664355,0.932851,-0.370749, + -0.472479,0.093412,-0.876377,-3.556552,0.704883,-0.28063, + -0.946902,-0.290276,0.138264,-3.664355,0.932851,-0.370749, + -0.982633,-0.143429,0.11773,-3.631292,0.701013,-0.420276, + -0.971344,0.144305,-0.188856,-3.536654,0.442277,-0.322, + -0.472479,0.093412,-0.876377,-3.556552,0.704883,-0.28063, + -0.982633,-0.143429,0.11773,-3.631292,0.701013,-0.420276, + -0.971344,0.144305,-0.188856,-3.536654,0.442277,-0.322, + -0.982633,-0.143429,0.11773,-3.631292,0.701013,-0.420276, + -0.995584,-0.070631,0.061842,-3.570384,0.385564,-0.52448, + -0.923845,0.18432,-0.335466,-3.51684,0.149002,-0.430359, + -0.971344,0.144305,-0.188856,-3.536654,0.442277,-0.322, + -0.995584,-0.070631,0.061842,-3.570384,0.385564,-0.52448, + -0.923845,0.18432,-0.335466,-3.51684,0.149002,-0.430359, + -0.995584,-0.070631,0.061842,-3.570384,0.385564,-0.52448, + -0.997475,-0.070819,0.005318,-3.520188,0.140164,-0.618561, + -0.908258,0.139498,-0.394471,-3.470778,-0.078218,-0.546398, + -0.923845,0.18432,-0.335466,-3.51684,0.149002,-0.430359, + -0.997475,-0.070819,0.005318,-3.520188,0.140164,-0.618561, + -0.908258,0.139498,-0.394471,-3.470778,-0.078218,-0.546398, + -0.997475,-0.070819,0.005318,-3.520188,0.140164,-0.618561, + -0.980175,-0.184883,0.071243,-3.458251,-0.12595,-0.731712, + -0.743901,0.102645,-0.66036,-3.415655,-0.308965,-0.671045, + -0.908258,0.139498,-0.394471,-3.470778,-0.078218,-0.546398, + -0.980175,-0.184883,0.071243,-3.458251,-0.12595,-0.731712, + -0.743901,0.102645,-0.66036,-3.415655,-0.308965,-0.671045, + -0.980175,-0.184883,0.071243,-3.458251,-0.12595,-0.731712, + -0.976177,-0.17359,0.130171,-3.406618,-0.343461,-0.746456, + -0.996668,0.081567,0,-3.623861,0.911561,0, + -0.946902,-0.290276,0.138264,-3.664355,0.932851,-0.370749, + -0.43302,-0.02622,-0.901003,-3.57817,0.837714,-0.288502, + -0.996668,0.081567,0,-3.623861,0.911561,0, + -0.43302,-0.02622,-0.901003,-3.57817,0.837714,-0.288502, + -0.989171,0.146765,0,-3.599077,0.796217,0, + -0.844095,-0.536194,0,-3.601668,1.293049,0, + -0.848349,-0.120539,-0.515533,-3.709827,1.417763,0, + -0.880002,-0.033987,-0.473752,-3.709741,1.351194,-0.211745, + -0.844095,-0.536194,0,-3.601668,1.293049,0, + -0.880002,-0.033987,-0.473752,-3.709741,1.351194,-0.211745, + -0.870331,0.069096,-0.487595,-3.701634,1.27265,-0.270469, + -0.946116,-0.323827,0,-3.608593,1.163581,0, + -0.844095,-0.536194,0,-3.601668,1.293049,0, + -0.870331,0.069096,-0.487595,-3.701634,1.27265,-0.270469, + -0.946116,-0.323827,0,-3.608593,1.163581,0, + -0.870331,0.069096,-0.487595,-3.701634,1.27265,-0.270469, + -0.822733,0.223687,-0.522565,-3.695872,1.156978,-0.316829, + -0.997181,-0.075036,0,-3.622326,1.005378,0, + -0.946116,-0.323827,0,-3.608593,1.163581,0, + -0.822733,0.223687,-0.522565,-3.695872,1.156978,-0.316829, + -0.997181,-0.075036,0,-3.622326,1.005378,0, + -0.822733,0.223687,-0.522565,-3.695872,1.156978,-0.316829, + -0.938447,-0.345423,0,-3.672431,1.044224,-0.364991, + -0.996668,0.081567,0,-3.623861,0.911561,0, + -0.997181,-0.075036,0,-3.622326,1.005378,0, + -0.938447,-0.345423,0,-3.672431,1.044224,-0.364991, + -0.996668,0.081567,0,-3.623861,0.911561,0, + -0.938447,-0.345423,0,-3.672431,1.044224,-0.364991, + -0.946902,-0.290276,0.138264,-3.664355,0.932851,-0.370749, + -0.999862,-0.016634,0,-3.900566,1.002504,0, + -0.891992,-0.016938,-0.451734,-3.88734,1.003866,-0.057635, + -0.888551,-0.077176,-0.452239,-3.84447,0.498176,-0.053132, + -0.999862,-0.016634,0,-3.900566,1.002504,0, + -0.888551,-0.077176,-0.452239,-3.84447,0.498176,-0.053132, + -0.996511,-0.083465,-0.000062,-3.856649,0.496801,0, + -0.964752,0.26316,0,-3.87514,1.480358,0, + -0.860797,0.234294,-0.451812,-3.86082,1.479723,-0.062137, + -0.891992,-0.016938,-0.451734,-3.88734,1.003866,-0.057635, + -0.964752,0.26316,0,-3.87514,1.480358,0, + -0.891992,-0.016938,-0.451734,-3.88734,1.003866,-0.057635, + -0.999862,-0.016634,0,-3.900566,1.002504,0, + -0.766357,0.642415,0,-3.712832,1.794492,0, + -0.686439,0.576002,-0.443872,-3.698925,1.787941,-0.06664, + -0.860797,0.234294,-0.451812,-3.86082,1.479723,-0.062137, + -0.766357,0.642415,0,-3.712832,1.794492,0, + -0.860797,0.234294,-0.451812,-3.86082,1.479723,-0.062137, + -0.964752,0.26316,0,-3.87514,1.480358,0, + -0.410619,0.911807,0,-3.47843,1.975409,0, + -0.369855,0.817227,-0.441981,-3.469715,1.961504,-0.071141, + -0.686439,0.576002,-0.443872,-3.698925,1.787941,-0.06664, + -0.410619,0.911807,0,-3.47843,1.975409,0, + -0.686439,0.576002,-0.443872,-3.698925,1.787941,-0.06664, + -0.766357,0.642415,0,-3.712832,1.794492,0, + -0.433128,-0.901332,0,-3.242148,2.021387,0, + 0.011581,0.887039,-0.461548,-3.238225,2.005405,-0.075645, + -0.369855,0.817227,-0.441981,-3.469715,1.961504,-0.071141, + -0.433128,-0.901332,0,-3.242148,2.021387,0, + -0.369855,0.817227,-0.441981,-3.469715,1.961504,-0.071141, + -0.410619,0.911807,0,-3.47843,1.975409,0, + -0.891992,-0.016938,-0.451734,-3.88734,1.003866,-0.057635, + -0.548359,-0.017804,-0.836053,-3.851206,1.007586,-0.099831, + -0.545298,-0.056465,-0.836338,-3.811194,0.501935,-0.092033, + -0.891992,-0.016938,-0.451734,-3.88734,1.003866,-0.057635, + -0.545298,-0.056465,-0.836338,-3.811194,0.501935,-0.092033, + -0.888551,-0.077176,-0.452239,-3.84447,0.498176,-0.053132, + -0.860797,0.234294,-0.451812,-3.86082,1.479723,-0.062137, + -0.530021,0.13773,-0.836725,-3.821694,1.477989,-0.107631, + -0.548359,-0.017804,-0.836053,-3.851206,1.007586,-0.099831, + -0.860797,0.234294,-0.451812,-3.86082,1.479723,-0.062137, + -0.548359,-0.017804,-0.836053,-3.851206,1.007586,-0.099831, + -0.891992,-0.016938,-0.451734,-3.88734,1.003866,-0.057635, + -0.686439,0.576002,-0.443872,-3.698925,1.787941,-0.06664, + -0.429713,0.351913,-0.831568,-3.660928,1.770041,-0.115431, + -0.530021,0.13773,-0.836725,-3.821694,1.477989,-0.107631, + -0.686439,0.576002,-0.443872,-3.698925,1.787941,-0.06664, + -0.530021,0.13773,-0.836725,-3.821694,1.477989,-0.107631, + -0.860797,0.234294,-0.451812,-3.86082,1.479723,-0.062137, + -0.369855,0.817227,-0.441981,-3.469715,1.961504,-0.071141, + -0.240211,0.502412,-0.830591,-3.445903,1.923509,-0.123229, + -0.429713,0.351913,-0.831568,-3.660928,1.770041,-0.115431, + -0.369855,0.817227,-0.441981,-3.469715,1.961504,-0.071141, + -0.429713,0.351913,-0.831568,-3.660928,1.770041,-0.115431, + -0.686439,0.576002,-0.443872,-3.698925,1.787941,-0.06664, + 0.011581,0.887039,-0.461548,-3.238225,2.005405,-0.075645, + 0.000909,0.669011,-0.743252,-3.227504,1.961738,-0.131029, + -0.240211,0.502412,-0.830591,-3.445903,1.923509,-0.123229, + 0.011581,0.887039,-0.461548,-3.238225,2.005405,-0.075645, + -0.240211,0.502412,-0.830591,-3.445903,1.923509,-0.123229, + -0.369855,0.817227,-0.441981,-3.469715,1.961504,-0.071141, + -0.548359,-0.017804,-0.836053,-3.851206,1.007586,-0.099831, + 0.000763,-0.01871,-0.999825,-3.80184,1.012668,-0.115288, + 0.002291,-0.021629,-0.999763,-3.765736,0.50707,-0.106281, + -0.548359,-0.017804,-0.836053,-3.851206,1.007586,-0.099831, + 0.002291,-0.021629,-0.999763,-3.765736,0.50707,-0.106281, + -0.545298,-0.056465,-0.836338,-3.811194,0.501935,-0.092033, + -0.530021,0.13773,-0.836725,-3.821694,1.477989,-0.107631, + -0.004656,-0.025693,-0.999659,-3.768245,1.475619,-0.124295, + 0.000763,-0.01871,-0.999825,-3.80184,1.012668,-0.115288, + -0.530021,0.13773,-0.836725,-3.821694,1.477989,-0.107631, + 0.000763,-0.01871,-0.999825,-3.80184,1.012668,-0.115288, + -0.548359,-0.017804,-0.836053,-3.851206,1.007586,-0.099831, + -0.429713,0.351913,-0.831568,-3.660928,1.770041,-0.115431, + -0.020872,-0.032587,-0.999251,-3.609021,1.745588,-0.133304, + -0.004656,-0.025693,-0.999659,-3.768245,1.475619,-0.124295, + -0.429713,0.351913,-0.831568,-3.660928,1.770041,-0.115431, + -0.004656,-0.025693,-0.999659,-3.768245,1.475619,-0.124295, + -0.530021,0.13773,-0.836725,-3.821694,1.477989,-0.107631, + -0.240211,0.502412,-0.830591,-3.445903,1.923509,-0.123229, + -0.091034,0.391629,-0.915609,-3.413372,1.871604,-0.142309, + -0.020872,-0.032587,-0.999251,-3.609021,1.745588,-0.133304, + -0.240211,0.502412,-0.830591,-3.445903,1.923509,-0.123229, + -0.020872,-0.032587,-0.999251,-3.609021,1.745588,-0.133304, + -0.429713,0.351913,-0.831568,-3.660928,1.770041,-0.115431, + 0.000909,0.669011,-0.743252,-3.227504,1.961738,-0.131029, + -0.091034,0.391629,-0.915609,-3.413372,1.871604,-0.142309, + -0.240211,0.502412,-0.830591,-3.445903,1.923509,-0.123229, + 0.000763,-0.01871,-0.999825,-3.80184,1.012668,-0.115288, + 0.549332,-0.018885,-0.835391,-3.752468,1.017751,-0.099865, + 0.549192,0.015162,-0.835559,-3.720269,0.512205,-0.092064, + 0.000763,-0.01871,-0.999825,-3.80184,1.012668,-0.115288, + 0.549192,0.015162,-0.835559,-3.720269,0.512205,-0.092064, + 0.002291,-0.021629,-0.999763,-3.765736,0.50707,-0.106281, + -0.004656,-0.025693,-0.999659,-3.768245,1.475619,-0.124295, + 0.516335,-0.196022,-0.833651,-3.714787,1.473248,-0.107668, + 0.549332,-0.018885,-0.835391,-3.752468,1.017751,-0.099865, + -0.004656,-0.025693,-0.999659,-3.768245,1.475619,-0.124295, + 0.549332,-0.018885,-0.835391,-3.752468,1.017751,-0.099865, + 0.000763,-0.01871,-0.999825,-3.80184,1.012668,-0.115288, + -0.020872,-0.032587,-0.999251,-3.609021,1.745588,-0.133304, + 0.368421,-0.433142,-0.82259,-3.557104,1.72113,-0.11547, + 0.516335,-0.196022,-0.833651,-3.714787,1.473248,-0.107668, + -0.020872,-0.032587,-0.999251,-3.609021,1.745588,-0.133304, + 0.516335,-0.196022,-0.833651,-3.714787,1.473248,-0.107668, + -0.004656,-0.025693,-0.999659,-3.768245,1.475619,-0.124295, + -0.091034,0.391629,-0.915609,-3.413372,1.871604,-0.142309, + 0.255239,-0.528231,-0.80983,-3.380836,1.819691,-0.123273, + 0.368421,-0.433142,-0.82259,-3.557104,1.72113,-0.11547, + -0.091034,0.391629,-0.915609,-3.413372,1.871604,-0.142309, + 0.368421,-0.433142,-0.82259,-3.557104,1.72113,-0.11547, + -0.020872,-0.032587,-0.999251,-3.609021,1.745588,-0.133304, + 0.549332,-0.018885,-0.835391,-3.752468,1.017751,-0.099865, + 0.892142,-0.018571,-0.451373,-3.716312,1.021474,-0.057693, + 0.891325,0.039302,-0.451658,-3.686972,0.515966,-0.053185, + 0.549332,-0.018885,-0.835391,-3.752468,1.017751,-0.099865, + 0.891325,0.039302,-0.451658,-3.686972,0.515966,-0.053185, + 0.549192,0.015162,-0.835559,-3.720269,0.512205,-0.092064, + 0.516335,-0.196022,-0.833651,-3.714787,1.473248,-0.107668, + 0.843387,-0.305323,-0.442128,-3.675638,1.471512,-0.062201, + 0.892142,-0.018571,-0.451373,-3.716312,1.021474,-0.057693, + 0.516335,-0.196022,-0.833651,-3.714787,1.473248,-0.107668, + 0.892142,-0.018571,-0.451373,-3.716312,1.021474,-0.057693, + 0.549332,-0.018885,-0.835391,-3.752468,1.017751,-0.099865, + 0.368421,-0.433142,-0.82259,-3.557104,1.72113,-0.11547, + 0.589192,-0.69056,-0.4195,-3.519086,1.70322,-0.066709, + 0.843387,-0.305323,-0.442128,-3.675638,1.471512,-0.062201, + 0.368421,-0.433142,-0.82259,-3.557104,1.72113,-0.11547, + 0.843387,-0.305323,-0.442128,-3.675638,1.471512,-0.062201, + 0.516335,-0.196022,-0.833651,-3.714787,1.473248,-0.107668, + 0.255239,-0.528231,-0.80983,-3.380836,1.819691,-0.123273, + 0.389161,-0.829175,-0.401277,-3.357009,1.781675,-0.071216, + 0.589192,-0.69056,-0.4195,-3.519086,1.70322,-0.066709, + 0.255239,-0.528231,-0.80983,-3.380836,1.819691,-0.123273, + 0.589192,-0.69056,-0.4195,-3.519086,1.70322,-0.066709, + 0.368421,-0.433142,-0.82259,-3.557104,1.72113,-0.11547, + 0.892142,-0.018571,-0.451373,-3.716312,1.021474,-0.057693, + 0.999831,-0.018401,-0.000261,-3.703058,1.022838,-0.000069, + 0.998889,0.047122,-0.000074,-3.674766,0.517345,-0.000063, + 0.892142,-0.018571,-0.451373,-3.716312,1.021474,-0.057693, + 0.998889,0.047122,-0.000074,-3.674766,0.517345,-0.000063, + 0.891325,0.039302,-0.451658,-3.686972,0.515966,-0.053185, + 0.843387,-0.305323,-0.442128,-3.675638,1.471512,-0.062201, + 0.941293,-0.337592,-0.000186,-3.661286,1.470876,-0.000074, + 0.999831,-0.018401,-0.000261,-3.703058,1.022838,-0.000069, + 0.843387,-0.305323,-0.442128,-3.675638,1.471512,-0.062201, + 0.999831,-0.018401,-0.000261,-3.703058,1.022838,-0.000069, + 0.892142,-0.018571,-0.451373,-3.716312,1.021474,-0.057693, + 0.589192,-0.69056,-0.4195,-3.519086,1.70322,-0.066709, + -0.153783,-0.988105,0,-3.507689,1.700214,0, + 0.941293,-0.337592,-0.000186,-3.661286,1.470876,-0.000074, + 0.589192,-0.69056,-0.4195,-3.519086,1.70322,-0.066709, + 0.941293,-0.337592,-0.000186,-3.661286,1.470876,-0.000074, + 0.843387,-0.305323,-0.442128,-3.675638,1.471512,-0.062201, + 0.389161,-0.829175,-0.401277,-3.357009,1.781675,-0.071216, + 0.411442,-0.911436,-0.000099,-3.348274,1.767738,-0.000085, + -0.153783,-0.988105,0,-3.507689,1.700214,0, + 0.389161,-0.829175,-0.401277,-3.357009,1.781675,-0.071216, + -0.153783,-0.988105,0,-3.507689,1.700214,0, + 0.589192,-0.69056,-0.4195,-3.519086,1.70322,-0.066709, + 0.000909,0.669011,-0.743252,-3.227504,1.961738,-0.131029, + 0.243464,-0.335965,-0.909864,-3.077669,1.871112,-0.217368, + -0.091034,0.391629,-0.915609,-3.413372,1.871604,-0.142309, + 0.011581,0.887039,-0.461548,-3.238225,2.005405,-0.075645, + -0.433128,-0.901332,0,-3.242148,2.021387,0, + 0.012502,-0.999922,0,-3.037562,2.001526,0, + 0.011581,0.887039,-0.461548,-3.238225,2.005405,-0.075645, + 0.012502,-0.999922,0,-3.037562,2.001526,0, + 0.005821,-0.234321,-0.972142,-3.053102,1.96881,-0.051104, + 0.000909,0.669011,-0.743252,-3.227504,1.961738,-0.131029, + 0.011581,0.887039,-0.461548,-3.238225,2.005405,-0.075645, + 0.005821,-0.234321,-0.972142,-3.053102,1.96881,-0.051104, + 0.000909,0.669011,-0.743252,-3.227504,1.961738,-0.131029, + 0.005821,-0.234321,-0.972142,-3.053102,1.96881,-0.051104, + 0.243464,-0.335965,-0.909864,-3.077669,1.871112,-0.217368, + 0.243464,-0.335965,-0.909864,-3.077669,1.871112,-0.217368, + -0.108631,-0.122719,-0.986478,-3.35851,1.810253,-0.380095, + -0.091034,0.391629,-0.915609,-3.413372,1.871604,-0.142309, + 0.243464,-0.335965,-0.909864,-3.077669,1.871112,-0.217368, + 0.49938,-0.45475,-0.737443,-3.07531,1.846,-0.363149, + -0.108631,-0.122719,-0.986478,-3.35851,1.810253,-0.380095, + 0.269343,0.329305,-0.904993,4.760921,1.881357,-0.61312, + 0.544735,0.449335,-0.708069,4.824747,1.946835,-0.626358, + 0.897742,-0.15037,-0.414063,4.852578,1.889721,-0.605031, + 0.269343,0.329305,-0.904993,4.760921,1.881357,-0.61312, + 0.897742,-0.15037,-0.414063,4.852578,1.889721,-0.605031, + 0.397989,0.4494,-0.799778,4.861618,1.854067,-0.618095, + 0.721999,0.398917,-0.565316,4.861611,2.001639,-0.621913, + 0.264979,0.116702,-0.957166,4.842883,2.021333,-0.638025, + 0.312982,-0.015529,-0.949632,4.93588,2.051665,-0.572853, + 0.721999,0.398917,-0.565316,4.861611,2.001639,-0.621913, + 0.312982,-0.015529,-0.949632,4.93588,2.051665,-0.572853, + 0.711192,0.127662,-0.69131,4.935561,2.016016,-0.5857, + 0.470021,0.182979,-0.863481,4.991746,2.009819,-0.523206, + 0.412833,-0.156453,-0.897269,5.001903,1.914398,-0.486724, + 0.872792,-0.115436,-0.474246,4.973133,1.992779,-0.533466, + 0.746476,-0.187741,-0.638379,4.926194,1.859813,-0.582137, + 0.560378,0.257626,-0.78715,4.944706,1.840663,-0.575374, + 0.397989,0.4494,-0.799778,4.861618,1.854067,-0.618095, + 0.746476,-0.187741,-0.638379,4.926194,1.859813,-0.582137, + 0.397989,0.4494,-0.799778,4.861618,1.854067,-0.618095, + 0.897742,-0.15037,-0.414063,4.852578,1.889721,-0.605031, + 0.746476,-0.187741,-0.638379,4.926194,1.859813,-0.582137, + 0.108828,-0.182644,-0.977137,4.982364,1.8733,-0.53619, + 0.661825,0.260115,-0.703085,4.991709,1.844295,-0.520761, + 0.746476,-0.187741,-0.638379,4.926194,1.859813,-0.582137, + 0.661825,0.260115,-0.703085,4.991709,1.844295,-0.520761, + 0.560378,0.257626,-0.78715,4.944706,1.840663,-0.575374, + 0.397989,0.4494,-0.799778,4.861618,1.854067,-0.618095, + 0.560378,0.257626,-0.78715,4.944706,1.840663,-0.575374, + 0.675892,0.137563,-0.724049,4.908019,1.796041,-0.587882, + 0.397989,0.4494,-0.799778,4.861618,1.854067,-0.618095, + 0.675892,0.137563,-0.724049,4.908019,1.796041,-0.587882, + 0.708269,-0.122724,-0.695193,4.852582,1.816115,-0.603105, + 0.560378,0.257626,-0.78715,4.944706,1.840663,-0.575374, + 0.661825,0.260115,-0.703085,4.991709,1.844295,-0.520761, + 0.683237,-0.051725,-0.728363,4.963546,1.783161,-0.553515, + 0.560378,0.257626,-0.78715,4.944706,1.840663,-0.575374, + 0.683237,-0.051725,-0.728363,4.963546,1.783161,-0.553515, + 0.675892,0.137563,-0.724049,4.908019,1.796041,-0.587882, + 0.661825,0.260115,-0.703085,4.991709,1.844295,-0.520761, + 0.762434,-0.012904,-0.646937,4.983034,1.806343,-0.505779, + 0.683237,-0.051725,-0.728363,4.963546,1.783161,-0.553515, + 0.661825,0.260115,-0.703085,4.991709,1.844295,-0.520761, + 0.431713,0.22912,-0.872427,5.01143,1.875569,-0.463205, + 0.762434,-0.012904,-0.646937,4.983034,1.806343,-0.505779, + 0.588787,-0.248293,-0.769207,4.918466,2.084725,-0.532713, + 0.274422,-0.24433,-0.930051,4.964945,2.053575,-0.499903, + 0.470021,0.182979,-0.863481,4.991746,2.009819,-0.523206, + 0.588787,-0.248293,-0.769207,4.918466,2.084725,-0.532713, + 0.470021,0.182979,-0.863481,4.991746,2.009819,-0.523206, + 0.312982,-0.015529,-0.949632,4.93588,2.051665,-0.572853, + 0.274422,-0.24433,-0.930051,4.964945,2.053575,-0.499903, + 0.017555,-0.142899,-0.989582,5.020077,1.97817,-0.480978, + 0.470021,0.182979,-0.863481,4.991746,2.009819,-0.523206, + 0.470021,0.182979,-0.863481,4.991746,2.009819,-0.523206, + 0.017555,-0.142899,-0.989582,5.020077,1.97817,-0.480978, + 0.431713,0.22912,-0.872427,5.01143,1.875569,-0.463205, + 0.264979,0.116702,-0.957166,4.842883,2.021333,-0.638025, + 0.961046,0.110911,-0.253159,4.825996,2.089176,-0.576083, + 0.910294,-0.144636,-0.387873,4.881574,2.094571,-0.539949, + 0.264979,0.116702,-0.957166,4.842883,2.021333,-0.638025, + 0.910294,-0.144636,-0.387873,4.881574,2.094571,-0.539949, + 0.312982,-0.015529,-0.949632,4.93588,2.051665,-0.572853, + 0.961046,0.110911,-0.253159,4.825996,2.089176,-0.576083, + 0.264979,0.116702,-0.957166,4.842883,2.021333,-0.638025, + 0.269343,0.329305,-0.904993,4.760921,1.881357,-0.61312, + 0.961046,0.110911,-0.253159,4.825996,2.089176,-0.576083, + 0.269343,0.329305,-0.904993,4.760921,1.881357,-0.61312, + 0.813293,0.022433,-0.581422,4.788476,2.028047,-0.608619, + 0.699393,0.056752,-0.71248,4.751519,2.039658,-0.634134, + 0.490646,-0.178293,-0.852923,4.798297,2.118191,-0.591085, + 0.961046,0.110911,-0.253159,4.825996,2.089176,-0.576083, + 0.699393,0.056752,-0.71248,4.751519,2.039658,-0.634134, + 0.961046,0.110911,-0.253159,4.825996,2.089176,-0.576083, + 0.813293,0.022433,-0.581422,4.788476,2.028047,-0.608619, + 0.490646,-0.178293,-0.852923,4.798297,2.118191,-0.591085, + 0.267717,-0.172975,-0.947844,4.872539,2.159259,-0.542891, + 0.910294,-0.144636,-0.387873,4.881574,2.094571,-0.539949, + 0.490646,-0.178293,-0.852923,4.798297,2.118191,-0.591085, + 0.910294,-0.144636,-0.387873,4.881574,2.094571,-0.539949, + 0.961046,0.110911,-0.253159,4.825996,2.089176,-0.576083, + 0.267717,-0.172975,-0.947844,4.872539,2.159259,-0.542891, + -0.028502,-0.108631,-0.993673,4.927885,2.15656,-0.516579, + 0.588787,-0.248293,-0.769207,4.918466,2.084725,-0.532713, + 0.267717,-0.172975,-0.947844,4.872539,2.159259,-0.542891, + 0.588787,-0.248293,-0.769207,4.918466,2.084725,-0.532713, + 0.910294,-0.144636,-0.387873,4.881574,2.094571,-0.539949, + -0.028502,-0.108631,-0.993673,4.927885,2.15656,-0.516579, + -0.064166,-0.189382,-0.979805,5.00244,2.105746,-0.468233, + 0.274422,-0.24433,-0.930051,4.964945,2.053575,-0.499903, + -0.028502,-0.108631,-0.993673,4.927885,2.15656,-0.516579, + 0.274422,-0.24433,-0.930051,4.964945,2.053575,-0.499903, + 0.588787,-0.248293,-0.769207,4.918466,2.084725,-0.532713, + -0.064166,-0.189382,-0.979805,5.00244,2.105746,-0.468233, + 0.781868,0.537364,-0.316105,5.057495,2.002751,-0.451974, + 0.017555,-0.142899,-0.989582,5.020077,1.97817,-0.480978, + -0.064166,-0.189382,-0.979805,5.00244,2.105746,-0.468233, + 0.017555,-0.142899,-0.989582,5.020077,1.97817,-0.480978, + 0.274422,-0.24433,-0.930051,4.964945,2.053575,-0.499903, + 0.781868,0.537364,-0.316105,5.057495,2.002751,-0.451974, + 0.89264,0.34991,-0.284178,5.075994,1.900999,-0.443793, + 0.431713,0.22912,-0.872427,5.01143,1.875569,-0.463205, + 0.781868,0.537364,-0.316105,5.057495,2.002751,-0.451974, + 0.431713,0.22912,-0.872427,5.01143,1.875569,-0.463205, + 0.017555,-0.142899,-0.989582,5.020077,1.97817,-0.480978, + 0.89264,0.34991,-0.284178,5.075994,1.900999,-0.443793, + 0.618085,0.650911,-0.440779,5.030289,1.827419,-0.440803, + 0.431713,0.22912,-0.872427,5.01143,1.875569,-0.463205, + 0.431713,0.22912,-0.872427,5.01143,1.875569,-0.463205, + 0.618085,0.650911,-0.440779,5.030289,1.827419,-0.440803, + 0.352601,0.621479,-0.699597,4.991904,1.760829,-0.510386, + 0.431713,0.22912,-0.872427,5.01143,1.875569,-0.463205, + 0.352601,0.621479,-0.699597,4.991904,1.760829,-0.510386, + 0.762434,-0.012904,-0.646937,4.983034,1.806343,-0.505779, + 0.762434,-0.012904,-0.646937,4.983034,1.806343,-0.505779, + 0.352601,0.621479,-0.699597,4.991904,1.760829,-0.510386, + 0.171039,0.554898,-0.814146,4.936066,1.737668,-0.557276, + 0.762434,-0.012904,-0.646937,4.983034,1.806343,-0.505779, + 0.171039,0.554898,-0.814146,4.936066,1.737668,-0.557276, + 0.683237,-0.051725,-0.728363,4.963546,1.783161,-0.553515, + 0.675892,0.137563,-0.724049,4.908019,1.796041,-0.587882, + 0.683237,-0.051725,-0.728363,4.963546,1.783161,-0.553515, + 0.171039,0.554898,-0.814146,4.936066,1.737668,-0.557276, + 0.675892,0.137563,-0.724049,4.908019,1.796041,-0.587882, + 0.171039,0.554898,-0.814146,4.936066,1.737668,-0.557276, + -0.281999,-0.030938,-0.958916,4.871155,1.741238,-0.592326, + 0.708269,-0.122724,-0.695193,4.852582,1.816115,-0.603105, + 0.675892,0.137563,-0.724049,4.908019,1.796041,-0.587882, + -0.281999,-0.030938,-0.958916,4.871155,1.741238,-0.592326, + 0.708269,-0.122724,-0.695193,4.852582,1.816115,-0.603105, + -0.281999,-0.030938,-0.958916,4.871155,1.741238,-0.592326, + -0.120429,-0.209965,-0.970264,4.816181,1.79786,-0.604026, + 0.269343,0.329305,-0.904993,4.760921,1.881357,-0.61312, + 0.708269,-0.122724,-0.695193,4.852582,1.816115,-0.603105, + -0.120429,-0.209965,-0.970264,4.816181,1.79786,-0.604026, + 0.89264,0.34991,-0.284178,5.075994,1.900999,-0.443793, + 0.077536,0.770695,-0.632469,5.095375,1.961238,-0.401516, + -0.222902,0.035918,-0.974179,5.085813,1.888503,-0.408327, + 0.89264,0.34991,-0.284178,5.075994,1.900999,-0.443793, + -0.222902,0.035918,-0.974179,5.085813,1.888503,-0.408327, + 0.269003,0.864361,-0.424874,5.058179,1.788186,-0.417387, + 0.89264,0.34991,-0.284178,5.075994,1.900999,-0.443793, + 0.269003,0.864361,-0.424874,5.058179,1.788186,-0.417387, + 0.618085,0.650911,-0.440779,5.030289,1.827419,-0.440803, + 0.618085,0.650911,-0.440779,5.030289,1.827419,-0.440803, + 0.269003,0.864361,-0.424874,5.058179,1.788186,-0.417387, + 0.532717,0.840798,-0.09629,5.019836,1.739907,-0.485562, + 0.618085,0.650911,-0.440779,5.030289,1.827419,-0.440803, + 0.532717,0.840798,-0.09629,5.019836,1.739907,-0.485562, + 0.352601,0.621479,-0.699597,4.991904,1.760829,-0.510386, + 0.352601,0.621479,-0.699597,4.991904,1.760829,-0.510386, + 0.532717,0.840798,-0.09629,5.019836,1.739907,-0.485562, + 0.722741,0.690989,0.01339,4.917973,1.68148,-0.544201, + 0.352601,0.621479,-0.699597,4.991904,1.760829,-0.510386, + 0.722741,0.690989,0.01339,4.917973,1.68148,-0.544201, + 0.171039,0.554898,-0.814146,4.936066,1.737668,-0.557276, + -0.281999,-0.030938,-0.958916,4.871155,1.741238,-0.592326, + 0.171039,0.554898,-0.814146,4.936066,1.737668,-0.557276, + 0.722741,0.690989,0.01339,4.917973,1.68148,-0.544201, + -0.281999,-0.030938,-0.958916,4.871155,1.741238,-0.592326, + 0.722741,0.690989,0.01339,4.917973,1.68148,-0.544201, + 0.870384,0.492055,-0.017698,4.862636,1.684144,-0.570155, + -0.120429,-0.209965,-0.970264,4.816181,1.79786,-0.604026, + -0.281999,-0.030938,-0.958916,4.871155,1.741238,-0.592326, + 0.870384,0.492055,-0.017698,4.862636,1.684144,-0.570155, + -0.120429,-0.209965,-0.970264,4.816181,1.79786,-0.604026, + 0.870384,0.492055,-0.017698,4.862636,1.684144,-0.570155, + 0.947044,0.280641,-0.156039,4.752337,1.723388,-0.591296, + 0.269343,0.329305,-0.904993,4.760921,1.881357,-0.61312, + -0.120429,-0.209965,-0.970264,4.816181,1.79786,-0.604026, + 0.947044,0.280641,-0.156039,4.752337,1.723388,-0.591296, + 0.269343,0.329305,-0.904993,4.760921,1.881357,-0.61312, + 0.947044,0.280641,-0.156039,4.752337,1.723388,-0.591296, + 0.925586,0.05083,-0.375109,4.697607,1.768061,-0.576663, + -0.064166,-0.189382,-0.979805,5.00244,2.105746,-0.468233, + -0.212651,-0.104685,-0.971504,5.030641,2.102197,-0.432329, + 0.332526,0.910491,-0.245832,5.067202,2.027704,-0.422291, + -0.064166,-0.189382,-0.979805,5.00244,2.105746,-0.468233, + 0.332526,0.910491,-0.245832,5.067202,2.027704,-0.422291, + 0.781868,0.537364,-0.316105,5.057495,2.002751,-0.451974, + 0.530808,0.847432,0.010124,4.93795,2.181155,-0.486939, + -0.212651,-0.104685,-0.971504,5.030641,2.102197,-0.432329, + -0.064166,-0.189382,-0.979805,5.00244,2.105746,-0.468233, + 0.530808,0.847432,0.010124,4.93795,2.181155,-0.486939, + -0.064166,-0.189382,-0.979805,5.00244,2.105746,-0.468233, + -0.028502,-0.108631,-0.993673,4.927885,2.15656,-0.516579, + 0.668087,0.738269,0.092842,4.881855,2.194544,-0.530288, + 0.530808,0.847432,0.010124,4.93795,2.181155,-0.486939, + -0.028502,-0.108631,-0.993673,4.927885,2.15656,-0.516579, + 0.668087,0.738269,0.092842,4.881855,2.194544,-0.530288, + -0.028502,-0.108631,-0.993673,4.927885,2.15656,-0.516579, + 0.267717,-0.172975,-0.947844,4.872539,2.159259,-0.542891, + 0.668087,0.738269,0.092842,4.881855,2.194544,-0.530288, + 0.267717,-0.172975,-0.947844,4.872539,2.159259,-0.542891, + 0.490646,-0.178293,-0.852923,4.798297,2.118191,-0.591085, + 0.668087,0.738269,0.092842,4.881855,2.194544,-0.530288, + 0.490646,-0.178293,-0.852923,4.798297,2.118191,-0.591085, + 0.787133,0.61647,0.019654,4.807794,2.143653,-0.570393, + 0.787133,0.61647,0.019654,4.807794,2.143653,-0.570393, + 0.490646,-0.178293,-0.852923,4.798297,2.118191,-0.591085, + 0.699393,0.056752,-0.71248,4.751519,2.039658,-0.634134, + 0.787133,0.61647,0.019654,4.807794,2.143653,-0.570393, + 0.699393,0.056752,-0.71248,4.751519,2.039658,-0.634134, + 0.856604,0.474873,-0.201803,4.728963,2.036146,-0.614307, + 0.827569,0.284292,-0.484054,4.742358,1.882232,-0.62165, + 0.856604,0.474873,-0.201803,4.728963,2.036146,-0.614307, + 0.699393,0.056752,-0.71248,4.751519,2.039658,-0.634134, + 0.827569,0.284292,-0.484054,4.742358,1.882232,-0.62165, + 0.699393,0.056752,-0.71248,4.751519,2.039658,-0.634134, + 0.269343,0.329305,-0.904993,4.760921,1.881357,-0.61312, + 0.827569,0.284292,-0.484054,4.742358,1.882232,-0.62165, + 0.269343,0.329305,-0.904993,4.760921,1.881357,-0.61312, + 0.925586,0.05083,-0.375109,4.697607,1.768061,-0.576663, + 0.766773,0.253147,-0.589894,4.74405,2.179337,-0.556057, + 0.787133,0.61647,0.019654,4.807794,2.143653,-0.570393, + 0.856604,0.474873,-0.201803,4.728963,2.036146,-0.614307, + 0.766773,0.253147,-0.589894,4.74405,2.179337,-0.556057, + 0.856604,0.474873,-0.201803,4.728963,2.036146,-0.614307, + 0.667258,0.181112,-0.722471,4.688114,2.046378,-0.604518, + 0.766773,0.253147,-0.589894,4.74405,2.179337,-0.556057, + 0.45571,-0.00339,-0.890122,4.837331,2.235678,-0.479332, + 0.668087,0.738269,0.092842,4.881855,2.194544,-0.530288, + 0.766773,0.253147,-0.589894,4.74405,2.179337,-0.556057, + 0.668087,0.738269,0.092842,4.881855,2.194544,-0.530288, + 0.787133,0.61647,0.019654,4.807794,2.143653,-0.570393, + 0.45571,-0.00339,-0.890122,4.837331,2.235678,-0.479332, + 0.373808,-0.059429,-0.9256,4.89385,2.220523,-0.417713, + 0.530808,0.847432,0.010124,4.93795,2.181155,-0.486939, + 0.45571,-0.00339,-0.890122,4.837331,2.235678,-0.479332, + 0.530808,0.847432,0.010124,4.93795,2.181155,-0.486939, + 0.668087,0.738269,0.092842,4.881855,2.194544,-0.530288, + 0.373808,-0.059429,-0.9256,4.89385,2.220523,-0.417713, + 0.276212,-0.065585,-0.958856,4.995978,2.148785,-0.344534, + -0.212651,-0.104685,-0.971504,5.030641,2.102197,-0.432329, + 0.373808,-0.059429,-0.9256,4.89385,2.220523,-0.417713, + -0.212651,-0.104685,-0.971504,5.030641,2.102197,-0.432329, + 0.530808,0.847432,0.010124,4.93795,2.181155,-0.486939, + 0.276212,-0.065585,-0.958856,4.995978,2.148785,-0.344534, + 0.122987,-0.006582,-0.992386,5.06084,2.053335,-0.309324, + 0.332526,0.910491,-0.245832,5.067202,2.027704,-0.422291, + 0.276212,-0.065585,-0.958856,4.995978,2.148785,-0.344534, + 0.332526,0.910491,-0.245832,5.067202,2.027704,-0.422291, + -0.212651,-0.104685,-0.971504,5.030641,2.102197,-0.432329, + 0.122987,-0.006582,-0.992386,5.06084,2.053335,-0.309324, + 0.041586,0.068165,-0.996807,5.097062,1.954206,-0.328795, + 0.077536,0.770695,-0.632469,5.095375,1.961238,-0.401516, + 0.122987,-0.006582,-0.992386,5.06084,2.053335,-0.309324, + 0.077536,0.770695,-0.632469,5.095375,1.961238,-0.401516, + 0.332526,0.910491,-0.245832,5.067202,2.027704,-0.422291, + 0.077536,0.770695,-0.632469,5.095375,1.961238,-0.401516, + 0.041586,0.068165,-0.996807,5.097062,1.954206,-0.328795, + 0.035084,0.005692,-0.999368,5.105589,1.864086,-0.347113, + 0.077536,0.770695,-0.632469,5.095375,1.961238,-0.401516, + 0.035084,0.005692,-0.999368,5.105589,1.864086,-0.347113, + -0.222902,0.035918,-0.974179,5.085813,1.888503,-0.408327, + -0.222902,0.035918,-0.974179,5.085813,1.888503,-0.408327, + 0.035084,0.005692,-0.999368,5.105589,1.864086,-0.347113, + 0.269003,0.864361,-0.424874,5.058179,1.788186,-0.417387, + -0.013461,-0.014478,-0.999805,4.697024,1.862575,-0.604048, + 0.827569,0.284292,-0.484054,4.742358,1.882232,-0.62165, + 0.925586,0.05083,-0.375109,4.697607,1.768061,-0.576663, + 0.45571,-0.00339,-0.890122,4.837331,2.235678,-0.479332, + -0.114527,0.103064,-0.988059,4.739441,2.299169,-0.369987, + 0.2189,0.87846,-0.424724,4.83289,2.262727,-0.283787, + 0.45571,-0.00339,-0.890122,4.837331,2.235678,-0.479332, + 0.2189,0.87846,-0.424724,4.83289,2.262727,-0.283787, + 0.373808,-0.059429,-0.9256,4.89385,2.220523,-0.417713, + 0.2189,0.87846,-0.424724,4.83289,2.262727,-0.283787, + -0.194126,0.280848,-0.939914,4.971394,2.146686,-0.224781, + 0.276212,-0.065585,-0.958856,4.995978,2.148785,-0.344534, + 0.2189,0.87846,-0.424724,4.83289,2.262727,-0.283787, + 0.276212,-0.065585,-0.958856,4.995978,2.148785,-0.344534, + 0.373808,-0.059429,-0.9256,4.89385,2.220523,-0.417713, + -0.194126,0.280848,-0.939914,4.971394,2.146686,-0.224781, + 0.742633,0.65679,-0.130853,5.072165,2.04363,-0.209228, + 0.122987,-0.006582,-0.992386,5.06084,2.053335,-0.309324, + -0.194126,0.280848,-0.939914,4.971394,2.146686,-0.224781, + 0.122987,-0.006582,-0.992386,5.06084,2.053335,-0.309324, + 0.276212,-0.065585,-0.958856,4.995978,2.148785,-0.344534, + 0.742633,0.65679,-0.130853,5.072165,2.04363,-0.209228, + 0.681964,0.386262,-0.621069,5.127157,1.942759,-0.211214, + 0.041586,0.068165,-0.996807,5.097062,1.954206,-0.328795, + 0.742633,0.65679,-0.130853,5.072165,2.04363,-0.209228, + 0.041586,0.068165,-0.996807,5.097062,1.954206,-0.328795, + 0.122987,-0.006582,-0.992386,5.06084,2.053335,-0.309324, + 0.681964,0.386262,-0.621069,5.127157,1.942759,-0.211214, + 0.584509,0.341142,-0.736187,5.152698,1.830661,-0.287042, + 0.035084,0.005692,-0.999368,5.105589,1.864086,-0.347113, + 0.681964,0.386262,-0.621069,5.127157,1.942759,-0.211214, + 0.035084,0.005692,-0.999368,5.105589,1.864086,-0.347113, + 0.041586,0.068165,-0.996807,5.097062,1.954206,-0.328795, + 0.035084,0.005692,-0.999368,5.105589,1.864086,-0.347113, + 0.584509,0.341142,-0.736187,5.152698,1.830661,-0.287042, + 0.577823,0.271654,-0.769626,5.133171,1.715563,-0.334258, + 0.035084,0.005692,-0.999368,5.105589,1.864086,-0.347113, + 0.577823,0.271654,-0.769626,5.133171,1.715563,-0.334258, + 0.269003,0.864361,-0.424874,5.058179,1.788186,-0.417387, + 0.269003,0.864361,-0.424874,5.058179,1.788186,-0.417387, + 0.577823,0.271654,-0.769626,5.133171,1.715563,-0.334258, + 0.237937,0.08172,-0.967837,5.103427,1.624404,-0.434275, + 0.269003,0.864361,-0.424874,5.058179,1.788186,-0.417387, + 0.237937,0.08172,-0.967837,5.103427,1.624404,-0.434275, + 0.532717,0.840798,-0.09629,5.019836,1.739907,-0.485562, + 0.532717,0.840798,-0.09629,5.019836,1.739907,-0.485562, + 0.237937,0.08172,-0.967837,5.103427,1.624404,-0.434275, + 0.198142,0.152918,-0.968171,4.982822,1.503071,-0.507606, + 0.532717,0.840798,-0.09629,5.019836,1.739907,-0.485562, + 0.198142,0.152918,-0.968171,4.982822,1.503071,-0.507606, + 0.722741,0.690989,0.01339,4.917973,1.68148,-0.544201, + 0.870384,0.492055,-0.017698,4.862636,1.684144,-0.570155, + 0.722741,0.690989,0.01339,4.917973,1.68148,-0.544201, + 0.198142,0.152918,-0.968171,4.982822,1.503071,-0.507606, + 0.870384,0.492055,-0.017698,4.862636,1.684144,-0.570155, + 0.198142,0.152918,-0.968171,4.982822,1.503071,-0.507606, + 0.198441,0.172024,-0.964898,4.927282,1.486953,-0.526327, + 0.870384,0.492055,-0.017698,4.862636,1.684144,-0.570155, + 0.198441,0.172024,-0.964898,4.927282,1.486953,-0.526327, + 0.204819,0.130792,-0.970022,4.79841,1.473149,-0.570618, + 0.947044,0.280641,-0.156039,4.752337,1.723388,-0.591296, + 0.870384,0.492055,-0.017698,4.862636,1.684144,-0.570155, + 0.204819,0.130792,-0.970022,4.79841,1.473149,-0.570618, + 0.947044,0.280641,-0.156039,4.752337,1.723388,-0.591296, + 0.204819,0.130792,-0.970022,4.79841,1.473149,-0.570618, + 0.154028,0.078449,-0.984947,4.715646,1.502195,-0.584339, + 0.925586,0.05083,-0.375109,4.697607,1.768061,-0.576663, + 0.947044,0.280641,-0.156039,4.752337,1.723388,-0.591296, + 0.154028,0.078449,-0.984947,4.715646,1.502195,-0.584339, + 0.925586,0.05083,-0.375109,4.697607,1.768061,-0.576663, + 0.154028,0.078449,-0.984947,4.715646,1.502195,-0.584339, + 0.032152,0.123743,-0.991793,4.615408,1.639641,-0.577768, + -0.013461,-0.014478,-0.999805,4.697024,1.862575,-0.604048, + 0.925586,0.05083,-0.375109,4.697607,1.768061,-0.576663, + 0.032152,0.123743,-0.991793,4.615408,1.639641,-0.577768, + -0.013461,-0.014478,-0.999805,4.697024,1.862575,-0.604048, + 0.032152,0.123743,-0.991793,4.615408,1.639641,-0.577768, + -0.077208,0.343417,-0.936004,4.560751,1.785154,-0.562428, + 0.510305,0.850999,-0.124054,4.551484,1.841749,-0.575191, + 0.667258,0.181112,-0.722471,4.688114,2.046378,-0.604518, + -0.013461,-0.014478,-0.999805,4.697024,1.862575,-0.604048, + 0.510305,0.850999,-0.124054,4.551484,1.841749,-0.575191, + -0.013461,-0.014478,-0.999805,4.697024,1.862575,-0.604048, + -0.077208,0.343417,-0.936004,4.560751,1.785154,-0.562428, + 0.561002,0.750769,-0.348745,4.533113,1.989009,-0.578975, + 0.667258,0.181112,-0.722471,4.688114,2.046378,-0.604518, + 0.510305,0.850999,-0.124054,4.551484,1.841749,-0.575191, + 0.719268,0.159441,-0.676189,4.636582,2.263383,-0.471997, + 0.766773,0.253147,-0.589894,4.74405,2.179337,-0.556057, + 0.667258,0.181112,-0.722471,4.688114,2.046378,-0.604518, + 0.719268,0.159441,-0.676189,4.636582,2.263383,-0.471997, + 0.667258,0.181112,-0.722471,4.688114,2.046378,-0.604518, + 0.328548,0.219459,-0.918637,4.561299,2.133066,-0.547248, + 0.328548,0.219459,-0.918637,4.561299,2.133066,-0.547248, + 0.667258,0.181112,-0.722471,4.688114,2.046378,-0.604518, + 0.561002,0.750769,-0.348745,4.533113,1.989009,-0.578975, + -0.989689,-0.143234,0,4.912303,2.162645,-0.00009, + -0.941169,-0.337937,0,5.04969,2.032731,0.000071, + 0.742633,0.65679,-0.130853,5.072165,2.04363,-0.209228, + -0.989689,-0.143234,0,4.912303,2.162645,-0.00009, + 0.742633,0.65679,-0.130853,5.072165,2.04363,-0.209228, + -0.194126,0.280848,-0.939914,4.971394,2.146686,-0.224781, + -0.941169,-0.337937,0,5.04969,2.032731,0.000071, + 0.444094,0.036128,-0.895251,5.156645,1.942902,-0.119993, + 0.681964,0.386262,-0.621069,5.127157,1.942759,-0.211214, + -0.941169,-0.337937,0,5.04969,2.032731,0.000071, + 0.681964,0.386262,-0.621069,5.127157,1.942759,-0.211214, + 0.742633,0.65679,-0.130853,5.072165,2.04363,-0.209228, + 0.444094,0.036128,-0.895251,5.156645,1.942902,-0.119993, + 0.458202,0.052175,-0.887316,5.218821,1.803552,-0.199306, + 0.584509,0.341142,-0.736187,5.152698,1.830661,-0.287042, + 0.444094,0.036128,-0.895251,5.156645,1.942902,-0.119993, + 0.584509,0.341142,-0.736187,5.152698,1.830661,-0.287042, + 0.681964,0.386262,-0.621069,5.127157,1.942759,-0.211214, + 0.458202,0.052175,-0.887316,5.218821,1.803552,-0.199306, + 0.347878,0.028988,-0.937092,5.216855,1.636645,-0.279797, + 0.577823,0.271654,-0.769626,5.133171,1.715563,-0.334258, + 0.458202,0.052175,-0.887316,5.218821,1.803552,-0.199306, + 0.577823,0.271654,-0.769626,5.133171,1.715563,-0.334258, + 0.584509,0.341142,-0.736187,5.152698,1.830661,-0.287042, + 0.577823,0.271654,-0.769626,5.133171,1.715563,-0.334258, + 0.347878,0.028988,-0.937092,5.216855,1.636645,-0.279797, + 0.282492,0.026082,-0.958915,5.233176,1.442459,-0.362988, + 0.577823,0.271654,-0.769626,5.133171,1.715563,-0.334258, + 0.282492,0.026082,-0.958915,5.233176,1.442459,-0.362988, + 0.237937,0.08172,-0.967837,5.103427,1.624404,-0.434275, + 0.032152,0.123743,-0.991793,4.615408,1.639641,-0.577768, + 0.154028,0.078449,-0.984947,4.715646,1.502195,-0.584339, + 0.380651,0.443224,-0.811577,4.679116,1.438434,-0.589658, + 0.032152,0.123743,-0.991793,4.615408,1.639641,-0.577768, + 0.380651,0.443224,-0.811577,4.679116,1.438434,-0.589658, + 0.362705,0.428702,-0.827442,4.596478,1.512987,-0.598982, + 0.032152,0.123743,-0.991793,4.615408,1.639641,-0.577768, + 0.362705,0.428702,-0.827442,4.596478,1.512987,-0.598982, + 0.332757,0.286207,-0.898531,4.560024,1.604023,-0.589333, + -0.077208,0.343417,-0.936004,4.560751,1.785154,-0.562428, + 0.032152,0.123743,-0.991793,4.615408,1.639641,-0.577768, + 0.332757,0.286207,-0.898531,4.560024,1.604023,-0.589333, + -0.077208,0.343417,-0.936004,4.560751,1.785154,-0.562428, + 0.332757,0.286207,-0.898531,4.560024,1.604023,-0.589333, + 0.302715,0.058971,-0.951255,4.477781,1.687858,-0.597407, + 0.510305,0.850999,-0.124054,4.551484,1.841749,-0.575191, + -0.077208,0.343417,-0.936004,4.560751,1.785154,-0.562428, + 0.302715,0.058971,-0.951255,4.477781,1.687858,-0.597407, + 0.510305,0.850999,-0.124054,4.551484,1.841749,-0.575191, + 0.302715,0.058971,-0.951255,4.477781,1.687858,-0.597407, + 0.347794,0.132396,-0.928176,4.459682,1.778884,-0.588185, + 0.36359,0.089346,-0.927264,4.43261,1.878873,-0.577888, + 0.561002,0.750769,-0.348745,4.533113,1.989009,-0.578975, + 0.510305,0.850999,-0.124054,4.551484,1.841749,-0.575191, + 0.36359,0.089346,-0.927264,4.43261,1.878873,-0.577888, + 0.510305,0.850999,-0.124054,4.551484,1.841749,-0.575191, + 0.347794,0.132396,-0.928176,4.459682,1.778884,-0.588185, + 0.361081,-0.056526,-0.93082,4.43302,2.024714,-0.563794, + 0.328548,0.219459,-0.918637,4.561299,2.133066,-0.547248, + 0.561002,0.750769,-0.348745,4.533113,1.989009,-0.578975, + 0.361081,-0.056526,-0.93082,4.43302,2.024714,-0.563794, + 0.561002,0.750769,-0.348745,4.533113,1.989009,-0.578975, + 0.36359,0.089346,-0.927264,4.43261,1.878873,-0.577888, + 0.337014,-0.030018,-0.941021,4.634996,2.369115,-0.140117, + -0.965284,-0.261201,0,4.747988,2.300163,-0.000276, + 0.2189,0.87846,-0.424724,4.83289,2.262727,-0.283787, + 0.337014,-0.030018,-0.941021,4.634996,2.369115,-0.140117, + 0.2189,0.87846,-0.424724,4.83289,2.262727,-0.283787, + -0.114527,0.103064,-0.988059,4.739441,2.299169,-0.369987, + 0.272203,0.043076,-0.961275,4.577573,2.389535,-0.256196, + 0.337014,-0.030018,-0.941021,4.634996,2.369115,-0.140117, + -0.114527,0.103064,-0.988059,4.739441,2.299169,-0.369987, + 0.272203,0.043076,-0.961275,4.577573,2.389535,-0.256196, + -0.114527,0.103064,-0.988059,4.739441,2.299169,-0.369987, + 0.719268,0.159441,-0.676189,4.636582,2.263383,-0.471997, + 0.195545,0.103956,-0.975169,4.472349,2.325133,-0.443764, + 0.272203,0.043076,-0.961275,4.577573,2.389535,-0.256196, + 0.719268,0.159441,-0.676189,4.636582,2.263383,-0.471997, + 0.195545,0.103956,-0.975169,4.472349,2.325133,-0.443764, + 0.719268,0.159441,-0.676189,4.636582,2.263383,-0.471997, + 0.328548,0.219459,-0.918637,4.561299,2.133066,-0.547248, + 0.195545,0.103956,-0.975169,4.472349,2.325133,-0.443764, + 0.328548,0.219459,-0.918637,4.561299,2.133066,-0.547248, + 0.196849,0.14562,-0.969559,4.389484,2.190421,-0.47332, + 0.196849,0.14562,-0.969559,4.389484,2.190421,-0.47332, + 0.328548,0.219459,-0.918637,4.561299,2.133066,-0.547248, + 0.361081,-0.056526,-0.93082,4.43302,2.024714,-0.563794, + 0.237937,0.08172,-0.967837,5.103427,1.624404,-0.434275, + 0.282492,0.026082,-0.958915,5.233176,1.442459,-0.362988, + 0.210495,0.185422,-0.959849,5.223191,1.371491,-0.388069, + 0.237937,0.08172,-0.967837,5.103427,1.624404,-0.434275, + 0.210495,0.185422,-0.959849,5.223191,1.371491,-0.388069, + 0.198142,0.152918,-0.968171,4.982822,1.503071,-0.507606, + 0.198142,0.152918,-0.968171,4.982822,1.503071,-0.507606, + 0.210495,0.185422,-0.959849,5.223191,1.371491,-0.388069, + 0.154687,0.171026,-0.973048,5.158322,1.23677,-0.418043, + 0.198142,0.152918,-0.968171,4.982822,1.503071,-0.507606, + 0.154687,0.171026,-0.973048,5.158322,1.23677,-0.418043, + 0.198441,0.172024,-0.964898,4.927282,1.486953,-0.526327, + 0.198441,0.172024,-0.964898,4.927282,1.486953,-0.526327, + 0.154687,0.171026,-0.973048,5.158322,1.23677,-0.418043, + -0.03359,0.173471,-0.984266,4.95536,1.236724,-0.50523, + 0.198441,0.172024,-0.964898,4.927282,1.486953,-0.526327, + -0.03359,0.173471,-0.984266,4.95536,1.236724,-0.50523, + 0.204819,0.130792,-0.970022,4.79841,1.473149,-0.570618, + 0.204819,0.130792,-0.970022,4.79841,1.473149,-0.570618, + -0.03359,0.173471,-0.984266,4.95536,1.236724,-0.50523, + 0.289202,0.572304,-0.767353,4.761601,1.363013,-0.57137, + 0.204819,0.130792,-0.970022,4.79841,1.473149,-0.570618, + 0.289202,0.572304,-0.767353,4.761601,1.363013,-0.57137, + 0.154028,0.078449,-0.984947,4.715646,1.502195,-0.584339, + 0.154028,0.078449,-0.984947,4.715646,1.502195,-0.584339, + 0.289202,0.572304,-0.767353,4.761601,1.363013,-0.57137, + 0.380651,0.443224,-0.811577,4.679116,1.438434,-0.589658, + -0.998597,-0.052951,0,5.177545,1.932323,0.000214, + 0.243507,0.533327,-0.810103,5.321136,1.795562,-0.119606, + 0.458202,0.052175,-0.887316,5.218821,1.803552,-0.199306, + -0.998597,-0.052951,0,5.177545,1.932323,0.000214, + 0.458202,0.052175,-0.887316,5.218821,1.803552,-0.199306, + 0.444094,0.036128,-0.895251,5.156645,1.942902,-0.119993, + -0.998597,-0.052951,0,5.177545,1.932323,0.000214, + -0.99798,-0.063521,0,5.378289,1.768448,0.000441, + 0.243507,0.533327,-0.810103,5.321136,1.795562,-0.119606, + -0.99798,-0.063521,0,5.378289,1.768448,0.000441, + -0.925873,-0.377836,0,5.424281,1.721152,0.000496, + 0.168187,0.30029,-0.938903,5.421809,1.685349,-0.123555, + -0.99798,-0.063521,0,5.378289,1.768448,0.000441, + 0.168187,0.30029,-0.938903,5.421809,1.685349,-0.123555, + 0.243507,0.533327,-0.810103,5.321136,1.795562,-0.119606, + 0.458202,0.052175,-0.887316,5.218821,1.803552,-0.199306, + 0.243507,0.533327,-0.810103,5.321136,1.795562,-0.119606, + 0.168187,0.30029,-0.938903,5.421809,1.685349,-0.123555, + 0.458202,0.052175,-0.887316,5.218821,1.803552,-0.199306, + 0.168187,0.30029,-0.938903,5.421809,1.685349,-0.123555, + 0.112152,0.130705,-0.985057,5.383208,1.619661,-0.202452, + 0.458202,0.052175,-0.887316,5.218821,1.803552,-0.199306, + 0.112152,0.130705,-0.985057,5.383208,1.619661,-0.202452, + 0.069483,0.206284,-0.976022,5.373133,1.541142,-0.246712, + 0.458202,0.052175,-0.887316,5.218821,1.803552,-0.199306, + 0.069483,0.206284,-0.976022,5.373133,1.541142,-0.246712, + 0.347878,0.028988,-0.937092,5.216855,1.636645,-0.279797, + 0.347878,0.028988,-0.937092,5.216855,1.636645,-0.279797, + 0.069483,0.206284,-0.976022,5.373133,1.541142,-0.246712, + 0.054287,0.055115,-0.997003,5.334328,1.402713,-0.332639, + 0.347878,0.028988,-0.937092,5.216855,1.636645,-0.279797, + 0.054287,0.055115,-0.997003,5.334328,1.402713,-0.332639, + 0.282492,0.026082,-0.958915,5.233176,1.442459,-0.362988, + 0.282492,0.026082,-0.958915,5.233176,1.442459,-0.362988, + 0.054287,0.055115,-0.997003,5.334328,1.402713,-0.332639, + 0.235746,0.648569,-0.723728,5.296963,1.322443,-0.357984, + 0.282492,0.026082,-0.958915,5.233176,1.442459,-0.362988, + 0.235746,0.648569,-0.723728,5.296963,1.322443,-0.357984, + 0.210495,0.185422,-0.959849,5.223191,1.371491,-0.388069, + 0.210495,0.185422,-0.959849,5.223191,1.371491,-0.388069, + 0.235746,0.648569,-0.723728,5.296963,1.322443,-0.357984, + 0.101496,0.616609,-0.780699,5.260653,1.184173,-0.352062, + 0.210495,0.185422,-0.959849,5.223191,1.371491,-0.388069, + 0.101496,0.616609,-0.780699,5.260653,1.184173,-0.352062, + 0.154687,0.171026,-0.973048,5.158322,1.23677,-0.418043, + 0.154687,0.171026,-0.973048,5.158322,1.23677,-0.418043, + 0.101496,0.616609,-0.780699,5.260653,1.184173,-0.352062, + 0.043397,0.435461,-0.899161,5.250485,1.123029,-0.385234, + 0.154687,0.171026,-0.973048,5.158322,1.23677,-0.418043, + 0.043397,0.435461,-0.899161,5.250485,1.123029,-0.385234, + 0.012421,0.392537,-0.919653,4.991713,1.163096,-0.504149, + 0.154687,0.171026,-0.973048,5.158322,1.23677,-0.418043, + 0.012421,0.392537,-0.919653,4.991713,1.163096,-0.504149, + -0.03359,0.173471,-0.984266,4.95536,1.236724,-0.50523, + 0.289202,0.572304,-0.767353,4.761601,1.363013,-0.57137, + -0.03359,0.173471,-0.984266,4.95536,1.236724,-0.50523, + 0.012421,0.392537,-0.919653,4.991713,1.163096,-0.504149, + 0.289202,0.572304,-0.767353,4.761601,1.363013,-0.57137, + 0.012421,0.392537,-0.919653,4.991713,1.163096,-0.504149, + 0.067357,0.280762,-0.957411,4.733657,1.227371,-0.592883, + 0.380651,0.443224,-0.811577,4.679116,1.438434,-0.589658, + 0.289202,0.572304,-0.767353,4.761601,1.363013,-0.57137, + 0.067357,0.280762,-0.957411,4.733657,1.227371,-0.592883, + 0.380651,0.443224,-0.811577,4.679116,1.438434,-0.589658, + 0.067357,0.280762,-0.957411,4.733657,1.227371,-0.592883, + -0.026366,0.234118,-0.971851,4.641547,1.285422,-0.622034, + 0.362705,0.428702,-0.827442,4.596478,1.512987,-0.598982, + 0.380651,0.443224,-0.811577,4.679116,1.438434,-0.589658, + -0.026366,0.234118,-0.971851,4.641547,1.285422,-0.622034, + 0.362705,0.428702,-0.827442,4.596478,1.512987,-0.598982, + -0.026366,0.234118,-0.971851,4.641547,1.285422,-0.622034, + 0.184871,0.227139,-0.956154,4.522247,1.398278,-0.644892, + 0.332757,0.286207,-0.898531,4.560024,1.604023,-0.589333, + 0.362705,0.428702,-0.827442,4.596478,1.512987,-0.598982, + 0.184871,0.227139,-0.956154,4.522247,1.398278,-0.644892, + 0.332757,0.286207,-0.898531,4.560024,1.604023,-0.589333, + 0.184871,0.227139,-0.956154,4.522247,1.398278,-0.644892, + -0.034875,0.308036,-0.950735,4.430999,1.535753,-0.638888, + 0.302715,0.058971,-0.951255,4.477781,1.687858,-0.597407, + 0.332757,0.286207,-0.898531,4.560024,1.604023,-0.589333, + -0.034875,0.308036,-0.950735,4.430999,1.535753,-0.638888, + 0.302715,0.058971,-0.951255,4.477781,1.687858,-0.597407, + -0.034875,0.308036,-0.950735,4.430999,1.535753,-0.638888, + -0.148853,0.101172,-0.98367,4.404221,1.662433,-0.61661, + 0.504832,0.844097,-0.180678,4.38638,1.770868,-0.596666, + 0.347794,0.132396,-0.928176,4.459682,1.778884,-0.588185, + 0.302715,0.058971,-0.951255,4.477781,1.687858,-0.597407, + 0.504832,0.844097,-0.180678,4.38638,1.770868,-0.596666, + 0.302715,0.058971,-0.951255,4.477781,1.687858,-0.597407, + -0.148853,0.101172,-0.98367,4.404221,1.662433,-0.61661, + 0.615047,0.769185,-0.17341,4.377095,1.871713,-0.595743, + 0.36359,0.089346,-0.927264,4.43261,1.878873,-0.577888, + 0.347794,0.132396,-0.928176,4.459682,1.778884,-0.588185, + 0.615047,0.769185,-0.17341,4.377095,1.871713,-0.595743, + 0.347794,0.132396,-0.928176,4.459682,1.778884,-0.588185, + 0.504832,0.844097,-0.180678,4.38638,1.770868,-0.596666, + -0.925873,-0.377836,0,5.424281,1.721152,0.000496, + 0.027992,0.999608,0,5.588763,1.573846,0.000686, + 0.550962,0.627632,-0.550018,5.604888,1.546091,-0.113773, + -0.925873,-0.377836,0,5.424281,1.721152,0.000496, + 0.550962,0.627632,-0.550018,5.604888,1.546091,-0.113773, + 0.168187,0.30029,-0.938903,5.421809,1.685349,-0.123555, + 0.168187,0.30029,-0.938903,5.421809,1.685349,-0.123555, + 0.550962,0.627632,-0.550018,5.604888,1.546091,-0.113773, + 0.477288,0.71618,-0.509197,5.566339,1.498677,-0.190905, + 0.168187,0.30029,-0.938903,5.421809,1.685349,-0.123555, + 0.477288,0.71618,-0.509197,5.566339,1.498677,-0.190905, + 0.112152,0.130705,-0.985057,5.383208,1.619661,-0.202452, + 0.112152,0.130705,-0.985057,5.383208,1.619661,-0.202452, + 0.477288,0.71618,-0.509197,5.566339,1.498677,-0.190905, + 0.887994,0.419811,-0.187682,5.528186,1.44018,-0.250666, + 0.112152,0.130705,-0.985057,5.383208,1.619661,-0.202452, + 0.887994,0.419811,-0.187682,5.528186,1.44018,-0.250666, + 0.069483,0.206284,-0.976022,5.373133,1.541142,-0.246712, + 0.069483,0.206284,-0.976022,5.373133,1.541142,-0.246712, + 0.887994,0.419811,-0.187682,5.528186,1.44018,-0.250666, + 0.749779,0.312647,-0.583167,5.471928,1.345179,-0.313899, + 0.069483,0.206284,-0.976022,5.373133,1.541142,-0.246712, + 0.749779,0.312647,-0.583167,5.471928,1.345179,-0.313899, + 0.054287,0.055115,-0.997003,5.334328,1.402713,-0.332639, + 0.054287,0.055115,-0.997003,5.334328,1.402713,-0.332639, + 0.749779,0.312647,-0.583167,5.471928,1.345179,-0.313899, + 0.358075,0.480709,-0.800438,5.425783,1.264372,-0.329687, + 0.054287,0.055115,-0.997003,5.334328,1.402713,-0.332639, + 0.358075,0.480709,-0.800438,5.425783,1.264372,-0.329687, + 0.235746,0.648569,-0.723728,5.296963,1.322443,-0.357984, + 0.235746,0.648569,-0.723728,5.296963,1.322443,-0.357984, + 0.358075,0.480709,-0.800438,5.425783,1.264372,-0.329687, + 0.524848,0.480957,-0.702293,5.397967,1.174238,-0.346802, + 0.235746,0.648569,-0.723728,5.296963,1.322443,-0.357984, + 0.524848,0.480957,-0.702293,5.397967,1.174238,-0.346802, + 0.101496,0.616609,-0.780699,5.260653,1.184173,-0.352062, + 0.101496,0.616609,-0.780699,5.260653,1.184173,-0.352062, + 0.524848,0.480957,-0.702293,5.397967,1.174238,-0.346802, + 0.72603,0.248277,-0.641279,5.388455,1.119419,-0.351883, + 0.101496,0.616609,-0.780699,5.260653,1.184173,-0.352062, + 0.72603,0.248277,-0.641279,5.388455,1.119419,-0.351883, + 0.043397,0.435461,-0.899161,5.250485,1.123029,-0.385234, + 0.987857,-0.047506,-0.147925,5.687035,1.499636,-0.110765, + 0.936734,-0.314344,0.154001,5.741781,1.463956,-0.124891, + 0.831976,-0.511655,0.214534,5.730427,1.435668,-0.209848, + 0.987857,-0.047506,-0.147925,5.687035,1.499636,-0.110765, + 0.831976,-0.511655,0.214534,5.730427,1.435668,-0.209848, + 0.798302,-0.559383,0.22317,5.685194,1.452202,-0.188749, + 0.744254,-0.654161,-0.134758,5.710154,1.360653,-0.290072, + 0.884602,-0.366981,-0.287755,5.608974,1.317869,-0.319719, + 0.707709,-0.687035,-0.164711,5.647186,1.394606,-0.257833, + 0.884602,-0.366981,-0.287755,5.608974,1.317869,-0.319719, + 0.744254,-0.654161,-0.134758,5.710154,1.360653,-0.290072, + 0.364327,0.145753,-0.919795,5.681726,1.282503,-0.333871, + 0.884602,-0.366981,-0.287755,5.608974,1.317869,-0.319719, + 0.364327,0.145753,-0.919795,5.681726,1.282503,-0.333871, + 0.777215,-0.378098,-0.50297,5.563253,1.235295,-0.317238, + 0.777215,-0.378098,-0.50297,5.563253,1.235295,-0.317238, + 0.364327,0.145753,-0.919795,5.681726,1.282503,-0.333871, + 0.612046,-0.714077,-0.339844,5.672187,1.164767,-0.35408, + 0.777215,-0.378098,-0.50297,5.563253,1.235295,-0.317238, + 0.612046,-0.714077,-0.339844,5.672187,1.164767,-0.35408, + 0.348619,-0.077188,-0.934081,5.580797,1.174135,-0.351054, + -0.026558,-0.999647,0,5.680007,1.510009,0.000786, + 0.987857,-0.047506,-0.147925,5.687035,1.499636,-0.110765, + 0.550962,0.627632,-0.550018,5.604888,1.546091,-0.113773, + -0.026558,-0.999647,0,5.680007,1.510009,0.000786, + 0.550962,0.627632,-0.550018,5.604888,1.546091,-0.113773, + 0.027992,0.999608,0,5.588763,1.573846,0.000686, + 0.550962,0.627632,-0.550018,5.604888,1.546091,-0.113773, + 0.987857,-0.047506,-0.147925,5.687035,1.499636,-0.110765, + 0.798302,-0.559383,0.22317,5.685194,1.452202,-0.188749, + 0.550962,0.627632,-0.550018,5.604888,1.546091,-0.113773, + 0.798302,-0.559383,0.22317,5.685194,1.452202,-0.188749, + 0.477288,0.71618,-0.509197,5.566339,1.498677,-0.190905, + 0.798302,-0.559383,0.22317,5.685194,1.452202,-0.188749, + 0.707709,-0.687035,-0.164711,5.647186,1.394606,-0.257833, + 0.887994,0.419811,-0.187682,5.528186,1.44018,-0.250666, + 0.798302,-0.559383,0.22317,5.685194,1.452202,-0.188749, + 0.887994,0.419811,-0.187682,5.528186,1.44018,-0.250666, + 0.477288,0.71618,-0.509197,5.566339,1.498677,-0.190905, + 0.887994,0.419811,-0.187682,5.528186,1.44018,-0.250666, + 0.707709,-0.687035,-0.164711,5.647186,1.394606,-0.257833, + 0.884602,-0.366981,-0.287755,5.608974,1.317869,-0.319719, + 0.887994,0.419811,-0.187682,5.528186,1.44018,-0.250666, + 0.884602,-0.366981,-0.287755,5.608974,1.317869,-0.319719, + 0.749779,0.312647,-0.583167,5.471928,1.345179,-0.313899, + 0.749779,0.312647,-0.583167,5.471928,1.345179,-0.313899, + 0.884602,-0.366981,-0.287755,5.608974,1.317869,-0.319719, + 0.777215,-0.378098,-0.50297,5.563253,1.235295,-0.317238, + 0.749779,0.312647,-0.583167,5.471928,1.345179,-0.313899, + 0.777215,-0.378098,-0.50297,5.563253,1.235295,-0.317238, + 0.358075,0.480709,-0.800438,5.425783,1.264372,-0.329687, + 0.358075,0.480709,-0.800438,5.425783,1.264372,-0.329687, + 0.777215,-0.378098,-0.50297,5.563253,1.235295,-0.317238, + 0.348619,-0.077188,-0.934081,5.580797,1.174135,-0.351054, + 0.358075,0.480709,-0.800438,5.425783,1.264372,-0.329687, + 0.348619,-0.077188,-0.934081,5.580797,1.174135,-0.351054, + 0.524848,0.480957,-0.702293,5.397967,1.174238,-0.346802, + 0.524848,0.480957,-0.702293,5.397967,1.174238,-0.346802, + 0.348619,-0.077188,-0.934081,5.580797,1.174135,-0.351054, + 0.802898,-0.287005,-0.522477,5.47963,1.11131,-0.364188, + 0.524848,0.480957,-0.702293,5.397967,1.174238,-0.346802, + 0.802898,-0.287005,-0.522477,5.47963,1.11131,-0.364188, + 0.72603,0.248277,-0.641279,5.388455,1.119419,-0.351883, + 0.901575,-0.270544,-0.337593,5.842092,1.427708,-0.130724, + 0.461068,-0.584089,-0.668024,5.915025,1.382159,-0.13682, + 0.194103,-0.204609,-0.959406,5.886832,1.385674,-0.172365, + 0.901575,-0.270544,-0.337593,5.842092,1.427708,-0.130724, + 0.194103,-0.204609,-0.959406,5.886832,1.385674,-0.172365, + 0.286794,0.030057,-0.957521,5.813217,1.415581,-0.195261, + -0.016213,0.999869,0,5.908842,1.388968,0.001026, + 0.663563,0.74812,0.000025,5.963117,1.307775,0.001098, + 0.259896,0.111139,-0.95922,5.979357,1.325532,-0.125337, + -0.016213,0.999869,0,5.908842,1.388968,0.001026, + 0.259896,0.111139,-0.95922,5.979357,1.325532,-0.125337, + 0.461068,-0.584089,-0.668024,5.915025,1.382159,-0.13682, + 0.461068,-0.584089,-0.668024,5.915025,1.382159,-0.13682, + 0.259896,0.111139,-0.95922,5.979357,1.325532,-0.125337, + 0.230527,0.277297,-0.932718,5.941384,1.330818,-0.178936, + 0.461068,-0.584089,-0.668024,5.915025,1.382159,-0.13682, + 0.230527,0.277297,-0.932718,5.941384,1.330818,-0.178936, + 0.194103,-0.204609,-0.959406,5.886832,1.385674,-0.172365, + 0.694651,0.719347,0.000019,5.743997,1.482739,0.000851, + 0.569495,0.821995,-0.000075,5.835498,1.43628,0.000946, + 0.901575,-0.270544,-0.337593,5.842092,1.427708,-0.130724, + 0.694651,0.719347,0.000019,5.743997,1.482739,0.000851, + 0.901575,-0.270544,-0.337593,5.842092,1.427708,-0.130724, + 0.936734,-0.314344,0.154001,5.741781,1.463956,-0.124891, + 0.936734,-0.314344,0.154001,5.741781,1.463956,-0.124891, + 0.901575,-0.270544,-0.337593,5.842092,1.427708,-0.130724, + 0.286794,0.030057,-0.957521,5.813217,1.415581,-0.195261, + 0.936734,-0.314344,0.154001,5.741781,1.463956,-0.124891, + 0.286794,0.030057,-0.957521,5.813217,1.415581,-0.195261, + 0.831976,-0.511655,0.214534,5.730427,1.435668,-0.209848, + 0.831976,-0.511655,0.214534,5.730427,1.435668,-0.209848, + 0.286794,0.030057,-0.957521,5.813217,1.415581,-0.195261, + 0.188634,-0.17518,-0.966297,5.783731,1.341471,-0.28459, + 0.831976,-0.511655,0.214534,5.730427,1.435668,-0.209848, + 0.188634,-0.17518,-0.966297,5.783731,1.341471,-0.28459, + 0.744254,-0.654161,-0.134758,5.710154,1.360653,-0.290072, + 0.286794,0.030057,-0.957521,5.813217,1.415581,-0.195261, + 0.194103,-0.204609,-0.959406,5.886832,1.385674,-0.172365, + 0.244568,-0.04472,-0.9686,5.847989,1.311569,-0.261476, + 0.286794,0.030057,-0.957521,5.813217,1.415581,-0.195261, + 0.244568,-0.04472,-0.9686,5.847989,1.311569,-0.261476, + 0.188634,-0.17518,-0.966297,5.783731,1.341471,-0.28459, + 0.194103,-0.204609,-0.959406,5.886832,1.385674,-0.172365, + 0.230527,0.277297,-0.932718,5.941384,1.330818,-0.178936, + 0.193495,-0.385604,-0.902147,5.931474,1.233483,-0.215613, + 0.194103,-0.204609,-0.959406,5.886832,1.385674,-0.172365, + 0.193495,-0.385604,-0.902147,5.931474,1.233483,-0.215613, + 0.244568,-0.04472,-0.9686,5.847989,1.311569,-0.261476, + 0.259896,0.111139,-0.95922,5.979357,1.325532,-0.125337, + -0.026148,0.006311,-0.999638,5.998088,1.231874,-0.107334, + 0.230527,0.277297,-0.932718,5.941384,1.330818,-0.178936, + 0.663563,0.74812,0.000025,5.963117,1.307775,0.001098, + 0.617634,0.786466,0.000062,5.963527,1.232407,0.001121, + -0.026148,0.006311,-0.999638,5.998088,1.231874,-0.107334, + 0.663563,0.74812,0.000025,5.963117,1.307775,0.001098, + -0.026148,0.006311,-0.999638,5.998088,1.231874,-0.107334, + 0.259896,0.111139,-0.95922,5.979357,1.325532,-0.125337, + 0.230527,0.277297,-0.932718,5.941384,1.330818,-0.178936, + -0.026148,0.006311,-0.999638,5.998088,1.231874,-0.107334, + 0.193495,-0.385604,-0.902147,5.931474,1.233483,-0.215613, + -0.026148,0.006311,-0.999638,5.998088,1.231874,-0.107334, + 0.617634,0.786466,0.000062,5.963527,1.232407,0.001121, + 0.651313,0.75881,-0.000286,5.92711,1.131195,0.001118, + -0.026148,0.006311,-0.999638,5.998088,1.231874,-0.107334, + 0.651313,0.75881,-0.000286,5.92711,1.131195,0.001118, + -0.2127,-0.171223,-0.961999,5.961686,1.110978,-0.090324, + 0.651313,0.75881,-0.000286,5.92711,1.131195,0.001118, + 0.909103,0.416568,-0.001454,5.908782,1.066916,0.001121, + 0.054456,-0.320459,-0.945696,5.934596,1.054796,-0.077039, + 0.651313,0.75881,-0.000286,5.92711,1.131195,0.001118, + 0.054456,-0.320459,-0.945696,5.934596,1.054796,-0.077039, + -0.2127,-0.171223,-0.961999,5.961686,1.110978,-0.090324, + -0.2127,-0.171223,-0.961999,5.961686,1.110978,-0.090324, + 0.054456,-0.320459,-0.945696,5.934596,1.054796,-0.077039, + 0.169576,-0.140705,-0.975421,5.923808,1.025283,-0.153084, + -0.2127,-0.171223,-0.961999,5.961686,1.110978,-0.090324, + 0.169576,-0.140705,-0.975421,5.923808,1.025283,-0.153084, + 0.111896,-0.605741,-0.787755,5.950684,1.082725,-0.175648, + 0.063422,-0.817077,-0.573029,5.800778,1.078596,-0.31945, + 0.16399,-0.527952,-0.833291,5.884856,1.062202,-0.249545, + 0.120494,-0.516376,-0.847843,5.85775,0.997026,-0.236768, + 0.063422,-0.817077,-0.573029,5.800778,1.078596,-0.31945, + 0.120494,-0.516376,-0.847843,5.85775,0.997026,-0.236768, + 0.396941,-0.593504,-0.700137,5.755282,1.004149,-0.307505, + 0.063422,-0.817077,-0.573029,5.800778,1.078596,-0.31945, + 0.396941,-0.593504,-0.700137,5.755282,1.004149,-0.307505, + 0.010578,-0.902776,-0.429981,5.763952,1.062109,-0.338641, + 0.051115,-0.906355,-0.419414,5.912147,1.117911,-0.254197, + 0.223936,-0.919046,-0.324355,5.959462,1.157227,-0.187097, + 0.111896,-0.605741,-0.787755,5.950684,1.082725,-0.175648, + 0.051115,-0.906355,-0.419414,5.912147,1.117911,-0.254197, + 0.111896,-0.605741,-0.787755,5.950684,1.082725,-0.175648, + 0.16399,-0.527952,-0.833291,5.884856,1.062202,-0.249545, + 0.16399,-0.527952,-0.833291,5.884856,1.062202,-0.249545, + 0.111896,-0.605741,-0.787755,5.950684,1.082725,-0.175648, + 0.169576,-0.140705,-0.975421,5.923808,1.025283,-0.153084, + 0.16399,-0.527952,-0.833291,5.884856,1.062202,-0.249545, + 0.169576,-0.140705,-0.975421,5.923808,1.025283,-0.153084, + 0.120494,-0.516376,-0.847843,5.85775,0.997026,-0.236768, + 0.063422,-0.817077,-0.573029,5.800778,1.078596,-0.31945, + 0.161367,-0.802085,-0.574996,5.837875,1.141493,-0.305184, + 0.051115,-0.906355,-0.419414,5.912147,1.117911,-0.254197, + 0.063422,-0.817077,-0.573029,5.800778,1.078596,-0.31945, + 0.051115,-0.906355,-0.419414,5.912147,1.117911,-0.254197, + 0.16399,-0.527952,-0.833291,5.884856,1.062202,-0.249545, + 0.612046,-0.714077,-0.339844,5.672187,1.164767,-0.35408, + 0.218068,-0.756332,-0.616772,5.77341,1.225861,-0.323025, + 0.161367,-0.802085,-0.574996,5.837875,1.141493,-0.305184, + 0.612046,-0.714077,-0.339844,5.672187,1.164767,-0.35408, + 0.161367,-0.802085,-0.574996,5.837875,1.141493,-0.305184, + 0.063422,-0.817077,-0.573029,5.800778,1.078596,-0.31945, + 0.364327,0.145753,-0.919795,5.681726,1.282503,-0.333871, + 0.725751,-0.657941,-0.200998,5.764774,1.279824,-0.308562, + 0.218068,-0.756332,-0.616772,5.77341,1.225861,-0.323025, + 0.364327,0.145753,-0.919795,5.681726,1.282503,-0.333871, + 0.218068,-0.756332,-0.616772,5.77341,1.225861,-0.323025, + 0.612046,-0.714077,-0.339844,5.672187,1.164767,-0.35408, + 0.744254,-0.654161,-0.134758,5.710154,1.360653,-0.290072, + 0.188634,-0.17518,-0.966297,5.783731,1.341471,-0.28459, + 0.725751,-0.657941,-0.200998,5.764774,1.279824,-0.308562, + 0.744254,-0.654161,-0.134758,5.710154,1.360653,-0.290072, + 0.725751,-0.657941,-0.200998,5.764774,1.279824,-0.308562, + 0.364327,0.145753,-0.919795,5.681726,1.282503,-0.333871, + 0.17011,-0.985049,0.027217,5.690122,1.092917,-0.37085, + 0.010578,-0.902776,-0.429981,5.763952,1.062109,-0.338641, + 0.231006,-0.859096,-0.456717,5.681086,1.054964,-0.35586, + 0.612046,-0.714077,-0.339844,5.672187,1.164767,-0.35408, + 0.063422,-0.817077,-0.573029,5.800778,1.078596,-0.31945, + 0.010578,-0.902776,-0.429981,5.763952,1.062109,-0.338641, + 0.612046,-0.714077,-0.339844,5.672187,1.164767,-0.35408, + 0.010578,-0.902776,-0.429981,5.763952,1.062109,-0.338641, + 0.17011,-0.985049,0.027217,5.690122,1.092917,-0.37085, + 0.348619,-0.077188,-0.934081,5.580797,1.174135,-0.351054, + 0.612046,-0.714077,-0.339844,5.672187,1.164767,-0.35408, + 0.17011,-0.985049,0.027217,5.690122,1.092917,-0.37085, + 0.348619,-0.077188,-0.934081,5.580797,1.174135,-0.351054, + 0.17011,-0.985049,0.027217,5.690122,1.092917,-0.37085, + 0.108306,-0.808441,-0.578527,5.598282,1.094735,-0.386994, + 0.348619,-0.077188,-0.934081,5.580797,1.174135,-0.351054, + 0.108306,-0.808441,-0.578527,5.598282,1.094735,-0.386994, + 0.802898,-0.287005,-0.522477,5.47963,1.11131,-0.364188, + 0.802898,-0.287005,-0.522477,5.47963,1.11131,-0.364188, + 0.108306,-0.808441,-0.578527,5.598282,1.094735,-0.386994, + 0.155351,-0.987262,-0.034337,5.470775,1.009574,-0.355371, + 0.108306,-0.808441,-0.578527,5.598282,1.094735,-0.386994, + 0.17011,-0.985049,0.027217,5.690122,1.092917,-0.37085, + 0.231006,-0.859096,-0.456717,5.681086,1.054964,-0.35586, + 0.108306,-0.808441,-0.578527,5.598282,1.094735,-0.386994, + 0.231006,-0.859096,-0.456717,5.681086,1.054964,-0.35586, + 0.228199,-0.705361,-0.671112,5.580223,1.04747,-0.372696, + 0.228199,-0.705361,-0.671112,5.580223,1.04747,-0.372696, + 0.231006,-0.859096,-0.456717,5.681086,1.054964,-0.35586, + 0.173726,-0.983856,0.042973,5.672385,1.007694,-0.341778, + 0.228199,-0.705361,-0.671112,5.580223,1.04747,-0.372696, + 0.173726,-0.983856,0.042973,5.672385,1.007694,-0.341778, + 0.148862,-0.934725,-0.322692,5.580727,0.99933,-0.349867, + 0.228199,-0.705361,-0.671112,5.580223,1.04747,-0.372696, + 0.155351,-0.987262,-0.034337,5.470775,1.009574,-0.355371, + 0.108306,-0.808441,-0.578527,5.598282,1.094735,-0.386994, + 0.228199,-0.705361,-0.671112,5.580223,1.04747,-0.372696, + 0.148862,-0.934725,-0.322692,5.580727,0.99933,-0.349867, + 0.241652,-0.897637,-0.368581,5.535184,0.98018,-0.341257, + 0.228199,-0.705361,-0.671112,5.580223,1.04747,-0.372696, + 0.241652,-0.897637,-0.368581,5.535184,0.98018,-0.341257, + 0.155351,-0.987262,-0.034337,5.470775,1.009574,-0.355371, + 0.72603,0.248277,-0.641279,5.388455,1.119419,-0.351883, + 0.802898,-0.287005,-0.522477,5.47963,1.11131,-0.364188, + 0.155351,-0.987262,-0.034337,5.470775,1.009574,-0.355371, + 0.72603,0.248277,-0.641279,5.388455,1.119419,-0.351883, + 0.155351,-0.987262,-0.034337,5.470775,1.009574,-0.355371, + 0.114701,-0.691524,-0.713188,5.425352,1.035967,-0.34272, + 0.114701,-0.691524,-0.713188,5.425352,1.035967,-0.34272, + 0.155351,-0.987262,-0.034337,5.470775,1.009574,-0.355371, + 0.298912,-0.321997,-0.898315,5.434594,0.970412,-0.330823, + 0.155351,-0.987262,-0.034337,5.470775,1.009574,-0.355371, + 0.241652,-0.897637,-0.368581,5.535184,0.98018,-0.341257, + 0.298912,-0.321997,-0.898315,5.434594,0.970412,-0.330823, + 0.241652,-0.897637,-0.368581,5.535184,0.98018,-0.341257, + 0.241049,-0.626018,-0.741618,5.480649,0.941387,-0.316248, + 0.298912,-0.321997,-0.898315,5.434594,0.970412,-0.330823, + 0.72603,0.248277,-0.641279,5.388455,1.119419,-0.351883, + 0.114701,-0.691524,-0.713188,5.425352,1.035967,-0.34272, + 0.272751,-0.332382,-0.902845,5.379461,1.045817,-0.349748, + 0.272751,-0.332382,-0.902845,5.379461,1.045817,-0.349748, + 0.114701,-0.691524,-0.713188,5.425352,1.035967,-0.34272, + 0.298912,-0.321997,-0.898315,5.434594,0.970412,-0.330823, + 0.272751,-0.332382,-0.902845,5.379461,1.045817,-0.349748, + 0.298912,-0.321997,-0.898315,5.434594,0.970412,-0.330823, + 0.161397,-0.648357,-0.744032,5.370709,0.980272,-0.337432, + 0.298912,-0.321997,-0.898315,5.434594,0.970412,-0.330823, + 0.241049,-0.626018,-0.741618,5.480649,0.941387,-0.316248, + 0.142784,-0.229696,-0.962732,5.373646,0.885375,-0.20884, + 0.161397,-0.648357,-0.744032,5.370709,0.980272,-0.337432, + 0.298912,-0.321997,-0.898315,5.434594,0.970412,-0.330823, + 0.142784,-0.229696,-0.962732,5.373646,0.885375,-0.20884, + 0.241049,-0.626018,-0.741618,5.480649,0.941387,-0.316248, + -0.016623,-0.697515,-0.716378,5.546347,0.916044,-0.246782, + 0.009824,-0.644035,-0.764933,5.511556,0.863525,-0.177613, + 0.241049,-0.626018,-0.741618,5.480649,0.941387,-0.316248, + 0.009824,-0.644035,-0.764933,5.511556,0.863525,-0.177613, + 0.142784,-0.229696,-0.962732,5.373646,0.885375,-0.20884, + -0.016623,-0.697515,-0.716378,5.546347,0.916044,-0.246782, + -0.045194,-0.595739,-0.801906,5.638369,0.904402,-0.222548, + -0.023775,-0.598435,-0.800819,5.60337,0.852748,-0.162335, + -0.016623,-0.697515,-0.716378,5.546347,0.916044,-0.246782, + -0.023775,-0.598435,-0.800819,5.60337,0.852748,-0.162335, + 0.009824,-0.644035,-0.764933,5.511556,0.863525,-0.177613, + -0.045194,-0.595739,-0.801906,5.638369,0.904402,-0.222548, + -0.105003,-0.636187,-0.764356,5.748613,0.92049,-0.205099, + 0.200817,-0.971977,-0.122205,5.70463,0.849158,-0.12813, + -0.045194,-0.595739,-0.801906,5.638369,0.904402,-0.222548, + 0.200817,-0.971977,-0.122205,5.70463,0.849158,-0.12813, + -0.023775,-0.598435,-0.800819,5.60337,0.852748,-0.162335, + 0.043397,0.435461,-0.899161,5.250485,1.123029,-0.385234, + 0.72603,0.248277,-0.641279,5.388455,1.119419,-0.351883, + 0.272751,-0.332382,-0.902845,5.379461,1.045817,-0.349748, + 0.043397,0.435461,-0.899161,5.250485,1.123029,-0.385234, + 0.272751,-0.332382,-0.902845,5.379461,1.045817,-0.349748, + 0.123418,-0.784469,-0.607763,5.241466,1.040469,-0.383965, + 0.123418,-0.784469,-0.607763,5.241466,1.040469,-0.383965, + 0.272751,-0.332382,-0.902845,5.379461,1.045817,-0.349748, + 0.161397,-0.648357,-0.744032,5.370709,0.980272,-0.337432, + 0.123418,-0.784469,-0.607763,5.241466,1.040469,-0.383965, + 0.161397,-0.648357,-0.744032,5.370709,0.980272,-0.337432, + 0.050019,-0.552867,-0.831767,5.223571,0.974029,-0.362117, + 0.161397,-0.648357,-0.744032,5.370709,0.980272,-0.337432, + 0.142784,-0.229696,-0.962732,5.373646,0.885375,-0.20884, + 0.037801,-0.082839,-0.995846,5.299005,0.908991,-0.260177, + 0.050019,-0.552867,-0.831767,5.223571,0.974029,-0.362117, + 0.161397,-0.648357,-0.744032,5.370709,0.980272,-0.337432, + 0.037801,-0.082839,-0.995846,5.299005,0.908991,-0.260177, + 0.050019,-0.552867,-0.831767,5.223571,0.974029,-0.362117, + 0.037801,-0.082839,-0.995846,5.299005,0.908991,-0.260177, + -0.196146,-0.333078,-0.922272,5.197562,0.922406,-0.302473, + 0.997356,-0.072614,-0.002907,5.836005,0.945722,0.001092, + 0.953994,-0.299798,-0.004126,5.78079,0.891286,0.001059, + -0.277696,-0.435918,-0.856073,5.797411,0.880032,-0.072306, + 0.997356,-0.072614,-0.002907,5.836005,0.945722,0.001092, + -0.277696,-0.435918,-0.856073,5.797411,0.880032,-0.072306, + -0.106359,-0.394397,-0.912764,5.851404,0.929008,-0.105362, + -0.106359,-0.394397,-0.912764,5.851404,0.929008,-0.105362, + -0.277696,-0.435918,-0.856073,5.797411,0.880032,-0.072306, + 0.200817,-0.971977,-0.122205,5.70463,0.849158,-0.12813, + -0.106359,-0.394397,-0.912764,5.851404,0.929008,-0.105362, + 0.200817,-0.971977,-0.122205,5.70463,0.849158,-0.12813, + -0.105003,-0.636187,-0.764356,5.748613,0.92049,-0.205099, + -0.277696,-0.435918,-0.856073,5.797411,0.880032,-0.072306, + 0.953994,-0.299798,-0.004126,5.78079,0.891286,0.001059, + 0.874313,-0.485341,-0.004579,5.679621,0.8395,0.000985, + -0.277696,-0.435918,-0.856073,5.797411,0.880032,-0.072306, + 0.874313,-0.485341,-0.004579,5.679621,0.8395,0.000985, + -0.301162,-0.110218,-0.947182,5.568745,0.834653,-0.07139, + -0.277696,-0.435918,-0.856073,5.797411,0.880032,-0.072306, + -0.301162,-0.110218,-0.947182,5.568745,0.834653,-0.07139, + 0.200817,-0.971977,-0.122205,5.70463,0.849158,-0.12813, + 0.874313,-0.485341,-0.004579,5.679621,0.8395,0.000985, + 0.84332,-0.537393,-0.004381,5.579253,0.837796,0.000896, + -0.301162,-0.110218,-0.947182,5.568745,0.834653,-0.07139, + 0.200817,-0.971977,-0.122205,5.70463,0.849158,-0.12813, + -0.301162,-0.110218,-0.947182,5.568745,0.834653,-0.07139, + -0.430969,-0.132769,-0.892546,5.449164,0.847535,-0.103909, + 0.200817,-0.971977,-0.122205,5.70463,0.849158,-0.12813, + -0.430969,-0.132769,-0.892546,5.449164,0.847535,-0.103909, + -0.023775,-0.598435,-0.800819,5.60337,0.852748,-0.162335, + -0.293162,-0.051827,-0.954657,5.247762,0.848549,-0.108546, + 0.832605,-0.553861,-0.002629,5.213434,0.856784,0.000565, + 0.598791,-0.8009,-0.003109,5.112563,0.840686,0.00048, + -0.293162,-0.051827,-0.954657,5.247762,0.848549,-0.108546, + 0.598791,-0.8009,-0.003109,5.112563,0.840686,0.00048, + -0.034138,0.050771,-0.998127,5.137075,0.824518,-0.144842, + -0.023775,-0.598435,-0.800819,5.60337,0.852748,-0.162335, + -0.430969,-0.132769,-0.892546,5.449164,0.847535,-0.103909, + -0.101883,0.176778,-0.978963,5.3569,0.85112,-0.138324, + -0.023775,-0.598435,-0.800819,5.60337,0.852748,-0.162335, + -0.101883,0.176778,-0.978963,5.3569,0.85112,-0.138324, + 0.009824,-0.644035,-0.764933,5.511556,0.863525,-0.177613, + 0.009824,-0.644035,-0.764933,5.511556,0.863525,-0.177613, + -0.101883,0.176778,-0.978963,5.3569,0.85112,-0.138324, + -0.172671,0.234525,-0.956652,5.26443,0.855571,-0.181694, + 0.009824,-0.644035,-0.764933,5.511556,0.863525,-0.177613, + -0.172671,0.234525,-0.956652,5.26443,0.855571,-0.181694, + 0.142784,-0.229696,-0.962732,5.373646,0.885375,-0.20884, + 0.224122,-0.97456,-0.001209,5.323232,0.866039,0.00066, + 0.832605,-0.553861,-0.002629,5.213434,0.856784,0.000565, + -0.293162,-0.051827,-0.954657,5.247762,0.848549,-0.108546, + -0.301162,-0.110218,-0.947182,5.568745,0.834653,-0.07139, + 0.84332,-0.537393,-0.004381,5.579253,0.837796,0.000896, + -0.020035,-0.999799,-0.000148,5.469641,0.838722,0.000798, + -0.301162,-0.110218,-0.947182,5.568745,0.834653,-0.07139, + -0.020035,-0.999799,-0.000148,5.469641,0.838722,0.000798, + -0.430969,-0.132769,-0.892546,5.449164,0.847535,-0.103909, + -0.430969,-0.132769,-0.892546,5.449164,0.847535,-0.103909, + -0.020035,-0.999799,-0.000148,5.469641,0.838722,0.000798, + 0.224122,-0.97456,-0.001209,5.323232,0.866039,0.00066, + -0.430969,-0.132769,-0.892546,5.449164,0.847535,-0.103909, + 0.224122,-0.97456,-0.001209,5.323232,0.866039,0.00066, + -0.293162,-0.051827,-0.954657,5.247762,0.848549,-0.108546, + -0.101883,0.176778,-0.978963,5.3569,0.85112,-0.138324, + -0.430969,-0.132769,-0.892546,5.449164,0.847535,-0.103909, + -0.293162,-0.051827,-0.954657,5.247762,0.848549,-0.108546, + -0.101883,0.176778,-0.978963,5.3569,0.85112,-0.138324, + -0.293162,-0.051827,-0.954657,5.247762,0.848549,-0.108546, + -0.172671,0.234525,-0.956652,5.26443,0.855571,-0.181694, + 0.037801,-0.082839,-0.995846,5.299005,0.908991,-0.260177, + 0.142784,-0.229696,-0.962732,5.373646,0.885375,-0.20884, + -0.172671,0.234525,-0.956652,5.26443,0.855571,-0.181694, + -0.196146,-0.333078,-0.922272,5.197562,0.922406,-0.302473, + 0.037801,-0.082839,-0.995846,5.299005,0.908991,-0.260177, + -0.172671,0.234525,-0.956652,5.26443,0.855571,-0.181694, + -0.196146,-0.333078,-0.922272,5.197562,0.922406,-0.302473, + -0.172671,0.234525,-0.956652,5.26443,0.855571,-0.181694, + -0.317809,0.237299,-0.91798,5.153735,0.831575,-0.218348, + -0.172671,0.234525,-0.956652,5.26443,0.855571,-0.181694, + -0.293162,-0.051827,-0.954657,5.247762,0.848549,-0.108546, + -0.034138,0.050771,-0.998127,5.137075,0.824518,-0.144842, + -0.172671,0.234525,-0.956652,5.26443,0.855571,-0.181694, + -0.034138,0.050771,-0.998127,5.137075,0.824518,-0.144842, + -0.317809,0.237299,-0.91798,5.153735,0.831575,-0.218348, + -0.034138,0.050771,-0.998127,5.137075,0.824518,-0.144842, + 0.598791,-0.8009,-0.003109,5.112563,0.840686,0.00048, + 0.124158,-0.992262,-0.000543,4.920855,0.812339,0.000318, + -0.034138,0.050771,-0.998127,5.137075,0.824518,-0.144842, + 0.124158,-0.992262,-0.000543,4.920855,0.812339,0.000318, + -0.241534,0.200654,-0.949421,4.963526,0.797382,-0.14344, + -0.317809,0.237299,-0.91798,5.153735,0.831575,-0.218348, + -0.034138,0.050771,-0.998127,5.137075,0.824518,-0.144842, + -0.241534,0.200654,-0.949421,4.963526,0.797382,-0.14344, + -0.317809,0.237299,-0.91798,5.153735,0.831575,-0.218348, + -0.241534,0.200654,-0.949421,4.963526,0.797382,-0.14344, + -0.31398,0.125785,-0.94106,4.99671,0.81056,-0.280771, + -0.434729,0.079706,-0.897027,4.712067,0.770512,-0.333393, + -0.31398,0.125785,-0.94106,4.99671,0.81056,-0.280771, + -0.241534,0.200654,-0.949421,4.963526,0.797382,-0.14344, + -0.434729,0.079706,-0.897027,4.712067,0.770512,-0.333393, + -0.241534,0.200654,-0.949421,4.963526,0.797382,-0.14344, + -0.419631,0.061765,-0.905591,4.66969,0.738163,-0.188296, + -0.241534,0.200654,-0.949421,4.963526,0.797382,-0.14344, + 0.124158,-0.992262,-0.000543,4.920855,0.812339,0.000318, + 0.157494,-0.98752,-0.000465,4.655453,0.758022,0.000098, + -0.241534,0.200654,-0.949421,4.963526,0.797382,-0.14344, + 0.157494,-0.98752,-0.000465,4.655453,0.758022,0.000098, + -0.419631,0.061765,-0.905591,4.66969,0.738163,-0.188296, + -0.400711,0.089185,-0.911853,5.004627,0.908637,-0.345273, + -0.196146,-0.333078,-0.922272,5.197562,0.922406,-0.302473, + -0.317809,0.237299,-0.91798,5.153735,0.831575,-0.218348, + -0.400711,0.089185,-0.911853,5.004627,0.908637,-0.345273, + -0.317809,0.237299,-0.91798,5.153735,0.831575,-0.218348, + -0.31398,0.125785,-0.94106,4.99671,0.81056,-0.280771, + -0.497134,0.140473,-0.856227,4.728809,0.878731,-0.405801, + -0.400711,0.089185,-0.911853,5.004627,0.908637,-0.345273, + -0.31398,0.125785,-0.94106,4.99671,0.81056,-0.280771, + -0.497134,0.140473,-0.856227,4.728809,0.878731,-0.405801, + -0.31398,0.125785,-0.94106,4.99671,0.81056,-0.280771, + -0.434729,0.079706,-0.897027,4.712067,0.770512,-0.333393, + 0.274481,0.961015,-0.033322,5.011084,1.06677,-0.458562, + 0.123418,-0.784469,-0.607763,5.241466,1.040469,-0.383965, + 0.050019,-0.552867,-0.831767,5.223571,0.974029,-0.362117, + 0.274481,0.961015,-0.033322,5.011084,1.06677,-0.458562, + 0.050019,-0.552867,-0.831767,5.223571,0.974029,-0.362117, + 0.563602,0.822451,-0.076991,5.021254,0.951308,-0.405567, + 0.050019,-0.552867,-0.831767,5.223571,0.974029,-0.362117, + -0.196146,-0.333078,-0.922272,5.197562,0.922406,-0.302473, + -0.400711,0.089185,-0.911853,5.004627,0.908637,-0.345273, + 0.050019,-0.552867,-0.831767,5.223571,0.974029,-0.362117, + -0.400711,0.089185,-0.911853,5.004627,0.908637,-0.345273, + 0.563602,0.822451,-0.076991,5.021254,0.951308,-0.405567, + 0.067357,0.280762,-0.957411,4.733657,1.227371,-0.592883, + 0.012421,0.392537,-0.919653,4.991713,1.163096,-0.504149, + 0.274481,0.961015,-0.033322,5.011084,1.06677,-0.458562, + 0.067357,0.280762,-0.957411,4.733657,1.227371,-0.592883, + 0.274481,0.961015,-0.033322,5.011084,1.06677,-0.458562, + 0.311768,0.950117,0.008871,4.74325,1.05921,-0.563421, + 0.311768,0.950117,0.008871,4.74325,1.05921,-0.563421, + 0.274481,0.961015,-0.033322,5.011084,1.06677,-0.458562, + 0.563602,0.822451,-0.076991,5.021254,0.951308,-0.405567, + 0.311768,0.950117,0.008871,4.74325,1.05921,-0.563421, + 0.563602,0.822451,-0.076991,5.021254,0.951308,-0.405567, + 0.609817,0.770093,-0.187297,4.744871,0.950945,-0.491082, + 0.609817,0.770093,-0.187297,4.744871,0.950945,-0.491082, + 0.563602,0.822451,-0.076991,5.021254,0.951308,-0.405567, + -0.400711,0.089185,-0.911853,5.004627,0.908637,-0.345273, + 0.609817,0.770093,-0.187297,4.744871,0.950945,-0.491082, + -0.400711,0.089185,-0.911853,5.004627,0.908637,-0.345273, + -0.497134,0.140473,-0.856227,4.728809,0.878731,-0.405801, + -0.026366,0.234118,-0.971851,4.641547,1.285422,-0.622034, + 0.067357,0.280762,-0.957411,4.733657,1.227371,-0.592883, + 0.311768,0.950117,0.008871,4.74325,1.05921,-0.563421, + -0.026366,0.234118,-0.971851,4.641547,1.285422,-0.622034, + 0.311768,0.950117,0.008871,4.74325,1.05921,-0.563421, + 0.381066,0.919021,-0.100938,4.567896,1.149805,-0.642484, + 0.381066,0.919021,-0.100938,4.567896,1.149805,-0.642484, + 0.311768,0.950117,0.008871,4.74325,1.05921,-0.563421, + 0.609817,0.770093,-0.187297,4.744871,0.950945,-0.491082, + 0.381066,0.919021,-0.100938,4.567896,1.149805,-0.642484, + 0.609817,0.770093,-0.187297,4.744871,0.950945,-0.491082, + 0.651262,0.697944,-0.29788,4.496191,1.024566,-0.579491, + 0.651262,0.697944,-0.29788,4.496191,1.024566,-0.579491, + 0.609817,0.770093,-0.187297,4.744871,0.950945,-0.491082, + -0.497134,0.140473,-0.856227,4.728809,0.878731,-0.405801, + 0.651262,0.697944,-0.29788,4.496191,1.024566,-0.579491, + -0.497134,0.140473,-0.856227,4.728809,0.878731,-0.405801, + -0.062739,0.996071,-0.062495,4.416475,0.921264,-0.458839, + -0.11884,0.991349,0.055713,4.333503,0.951176,-0.481517, + -0.062739,0.996071,-0.062495,4.416475,0.921264,-0.458839, + -0.134248,0.990294,0.035989,4.399629,0.850459,-0.391855, + -0.11884,0.991349,0.055713,4.333503,0.951176,-0.481517, + -0.134248,0.990294,0.035989,4.399629,0.850459,-0.391855, + -0.081906,0.996619,0.006487,4.297891,0.911506,-0.447987, + -0.419631,0.061765,-0.905591,4.66969,0.738163,-0.188296, + 0.157494,-0.98752,-0.000465,4.655453,0.758022,0.000098, + 0.000801,-1,-0.000539,4.380854,0.704574,-0.00013, + -0.419631,0.061765,-0.905591,4.66969,0.738163,-0.188296, + 0.000801,-1,-0.000539,4.380854,0.704574,-0.00013, + 0.448666,0.893201,-0.029856,4.359048,0.700414,-0.166651, + -0.434729,0.079706,-0.897027,4.712067,0.770512,-0.333393, + -0.419631,0.061765,-0.905591,4.66969,0.738163,-0.188296, + 0.448666,0.893201,-0.029856,4.359048,0.700414,-0.166651, + -0.434729,0.079706,-0.897027,4.712067,0.770512,-0.333393, + 0.448666,0.893201,-0.029856,4.359048,0.700414,-0.166651, + 0.731768,0.675964,-0.087106,4.319799,0.731007,-0.291212, + -0.134248,0.990294,0.035989,4.399629,0.850459,-0.391855, + -0.434729,0.079706,-0.897027,4.712067,0.770512,-0.333393, + 0.731768,0.675964,-0.087106,4.319799,0.731007,-0.291212, + -0.134248,0.990294,0.035989,4.399629,0.850459,-0.391855, + 0.731768,0.675964,-0.087106,4.319799,0.731007,-0.291212, + -0.051101,0.977083,0.206633,4.216374,0.852328,-0.405873, + -0.134248,0.990294,0.035989,4.399629,0.850459,-0.391855, + -0.051101,0.977083,0.206633,4.216374,0.852328,-0.405873, + -0.081906,0.996619,0.006487,4.297891,0.911506,-0.447987, + -0.134248,0.990294,0.035989,4.399629,0.850459,-0.391855, + -0.062739,0.996071,-0.062495,4.416475,0.921264,-0.458839, + -0.497134,0.140473,-0.856227,4.728809,0.878731,-0.405801, + -0.134248,0.990294,0.035989,4.399629,0.850459,-0.391855, + -0.497134,0.140473,-0.856227,4.728809,0.878731,-0.405801, + -0.434729,0.079706,-0.897027,4.712067,0.770512,-0.333393, + 0.481644,0.842268,0.242081,4.449011,1.260929,-0.647431, + 0.381066,0.919021,-0.100938,4.567896,1.149805,-0.642484, + 0.651262,0.697944,-0.29788,4.496191,1.024566,-0.579491, + 0.481644,0.842268,0.242081,4.449011,1.260929,-0.647431, + 0.651262,0.697944,-0.29788,4.496191,1.024566,-0.579491, + 0.794567,0.588129,0.15089,4.366867,1.131136,-0.630581, + 0.04154,0.947538,0.316932,4.141189,1.008775,-0.499342, + -0.081906,0.996619,0.006487,4.297891,0.911506,-0.447987, + -0.051101,0.977083,0.206633,4.216374,0.852328,-0.405873, + 0.04154,0.947538,0.316932,4.141189,1.008775,-0.499342, + 0.461485,0.788927,0.405742,4.277227,1.077746,-0.550819, + -0.11884,0.991349,0.055713,4.333503,0.951176,-0.481517, + 0.04154,0.947538,0.316932,4.141189,1.008775,-0.499342, + -0.11884,0.991349,0.055713,4.333503,0.951176,-0.481517, + -0.081906,0.996619,0.006487,4.297891,0.911506,-0.447987, + 0.800967,0.453078,0.391371,4.085564,1.288885,-0.544406, + 0.054059,0.926072,0.373454,4.175444,1.350332,-0.613988, + 0.461485,0.788927,0.405742,4.277227,1.077746,-0.550819, + 0.800967,0.453078,0.391371,4.085564,1.288885,-0.544406, + 0.461485,0.788927,0.405742,4.277227,1.077746,-0.550819, + 0.04154,0.947538,0.316932,4.141189,1.008775,-0.499342, + -0.11884,0.991349,0.055713,4.333503,0.951176,-0.481517, + 0.651262,0.697944,-0.29788,4.496191,1.024566,-0.579491, + -0.062739,0.996071,-0.062495,4.416475,0.921264,-0.458839, + 0.461485,0.788927,0.405742,4.277227,1.077746,-0.550819, + 0.794567,0.588129,0.15089,4.366867,1.131136,-0.630581, + 0.651262,0.697944,-0.29788,4.496191,1.024566,-0.579491, + 0.461485,0.788927,0.405742,4.277227,1.077746,-0.550819, + 0.651262,0.697944,-0.29788,4.496191,1.024566,-0.579491, + -0.11884,0.991349,0.055713,4.333503,0.951176,-0.481517, + 0.054059,0.926072,0.373454,4.175444,1.350332,-0.613988, + 0.329366,0.742755,0.582952,4.247733,1.381058,-0.649596, + 0.794567,0.588129,0.15089,4.366867,1.131136,-0.630581, + 0.054059,0.926072,0.373454,4.175444,1.350332,-0.613988, + 0.794567,0.588129,0.15089,4.366867,1.131136,-0.630581, + 0.461485,0.788927,0.405742,4.277227,1.077746,-0.550819, + 0.329366,0.742755,0.582952,4.247733,1.381058,-0.649596, + 0.693689,0.317886,0.646331,4.329607,1.464801,-0.661485, + 0.481644,0.842268,0.242081,4.449011,1.260929,-0.647431, + 0.329366,0.742755,0.582952,4.247733,1.381058,-0.649596, + 0.481644,0.842268,0.242081,4.449011,1.260929,-0.647431, + 0.794567,0.588129,0.15089,4.366867,1.131136,-0.630581, + 0.693689,0.317886,0.646331,4.329607,1.464801,-0.661485, + -0.034875,0.308036,-0.950735,4.430999,1.535753,-0.638888, + 0.184871,0.227139,-0.956154,4.522247,1.398278,-0.644892, + 0.693689,0.317886,0.646331,4.329607,1.464801,-0.661485, + 0.184871,0.227139,-0.956154,4.522247,1.398278,-0.644892, + 0.481644,0.842268,0.242081,4.449011,1.260929,-0.647431, + 0.000755,0.939587,0.34231,4.312225,1.683392,-0.639944, + -0.148853,0.101172,-0.98367,4.404221,1.662433,-0.61661, + -0.034875,0.308036,-0.950735,4.430999,1.535753,-0.638888, + 0.000755,0.939587,0.34231,4.312225,1.683392,-0.639944, + -0.034875,0.308036,-0.950735,4.430999,1.535753,-0.638888, + 0.693689,0.317886,0.646331,4.329607,1.464801,-0.661485, + 0.204286,0.745568,0.634347,4.303615,1.799914,-0.610388, + 0.504832,0.844097,-0.180678,4.38638,1.770868,-0.596666, + -0.148853,0.101172,-0.98367,4.404221,1.662433,-0.61661, + 0.204286,0.745568,0.634347,4.303615,1.799914,-0.610388, + -0.148853,0.101172,-0.98367,4.404221,1.662433,-0.61661, + 0.000755,0.939587,0.34231,4.312225,1.683392,-0.639944, + 0.525316,0.261331,0.809784,4.304562,1.906537,-0.572242, + 0.615047,0.769185,-0.17341,4.377095,1.871713,-0.595743, + 0.504832,0.844097,-0.180678,4.38638,1.770868,-0.596666, + 0.525316,0.261331,0.809784,4.304562,1.906537,-0.572242, + 0.504832,0.844097,-0.180678,4.38638,1.770868,-0.596666, + 0.204286,0.745568,0.634347,4.303615,1.799914,-0.610388, + -0.051423,0.948155,0.313619,4.240116,1.770049,-0.583946, + 0.204286,0.745568,0.634347,4.303615,1.799914,-0.610388, + 0.000755,0.939587,0.34231,4.312225,1.683392,-0.639944, + -0.051423,0.948155,0.313619,4.240116,1.770049,-0.583946, + 0.000755,0.939587,0.34231,4.312225,1.683392,-0.639944, + 0.104327,0.725166,0.680624,4.221814,1.660769,-0.59409, + 0.104327,0.725166,0.680624,4.221814,1.660769,-0.59409, + 0.000755,0.939587,0.34231,4.312225,1.683392,-0.639944, + 0.693689,0.317886,0.646331,4.329607,1.464801,-0.661485, + 0.104327,0.725166,0.680624,4.221814,1.660769,-0.59409, + 0.693689,0.317886,0.646331,4.329607,1.464801,-0.661485, + 0.329366,0.742755,0.582952,4.247733,1.381058,-0.649596, + 0.288171,0.239224,0.927216,4.121121,1.614451,-0.587188, + 0.104327,0.725166,0.680624,4.221814,1.660769,-0.59409, + 0.329366,0.742755,0.582952,4.247733,1.381058,-0.649596, + 0.288171,0.239224,0.927216,4.121121,1.614451,-0.587188, + 0.329366,0.742755,0.582952,4.247733,1.381058,-0.649596, + 0.054059,0.926072,0.373454,4.175444,1.350332,-0.613988, + 0.811896,0.498733,-0.303464,4.067576,1.572668,-0.534997, + 0.288171,0.239224,0.927216,4.121121,1.614451,-0.587188, + 0.054059,0.926072,0.373454,4.175444,1.350332,-0.613988, + 0.811896,0.498733,-0.303464,4.067576,1.572668,-0.534997, + 0.054059,0.926072,0.373454,4.175444,1.350332,-0.613988, + 0.800967,0.453078,0.391371,4.085564,1.288885,-0.544406, + 0.969409,0.243853,-0.027951,4.148883,1.759918,-0.573765, + -0.051423,0.948155,0.313619,4.240116,1.770049,-0.583946, + 0.104327,0.725166,0.680624,4.221814,1.660769,-0.59409, + 0.969409,0.243853,-0.027951,4.148883,1.759918,-0.573765, + 0.104327,0.725166,0.680624,4.221814,1.660769,-0.59409, + 0.288171,0.239224,0.927216,4.121121,1.614451,-0.587188, + 0.971427,0.04566,0.232906,4.076852,1.746601,-0.527436, + 0.969409,0.243853,-0.027951,4.148883,1.759918,-0.573765, + 0.288171,0.239224,0.927216,4.121121,1.614451,-0.587188, + 0.971427,0.04566,0.232906,4.076852,1.746601,-0.527436, + 0.288171,0.239224,0.927216,4.121121,1.614451,-0.587188, + 0.811896,0.498733,-0.303464,4.067576,1.572668,-0.534997, + -0.965284,-0.261201,0,4.747988,2.300163,-0.000276, + -0.989689,-0.143234,0,4.912303,2.162645,-0.00009, + -0.194126,0.280848,-0.939914,4.971394,2.146686,-0.224781, + -0.965284,-0.261201,0,4.747988,2.300163,-0.000276, + -0.194126,0.280848,-0.939914,4.971394,2.146686,-0.224781, + 0.2189,0.87846,-0.424724,4.83289,2.262727,-0.283787, + -0.941169,-0.337937,0,5.04969,2.032731,0.000071, + -0.998597,-0.052951,0,5.177545,1.932323,0.000214, + 0.444094,0.036128,-0.895251,5.156645,1.942902,-0.119993, + -0.026558,-0.999647,0,5.680007,1.510009,0.000786, + 0.694651,0.719347,0.000019,5.743997,1.482739,0.000851, + 0.936734,-0.314344,0.154001,5.741781,1.463956,-0.124891, + -0.026558,-0.999647,0,5.680007,1.510009,0.000786, + 0.936734,-0.314344,0.154001,5.741781,1.463956,-0.124891, + 0.987857,-0.047506,-0.147925,5.687035,1.499636,-0.110765, + 0.569495,0.821995,-0.000075,5.835498,1.43628,0.000946, + -0.016213,0.999869,0,5.908842,1.388968,0.001026, + 0.461068,-0.584089,-0.668024,5.915025,1.382159,-0.13682, + 0.569495,0.821995,-0.000075,5.835498,1.43628,0.000946, + 0.461068,-0.584089,-0.668024,5.915025,1.382159,-0.13682, + 0.901575,-0.270544,-0.337593,5.842092,1.427708,-0.130724, + 0.850248,-0.122855,0.511845,4.342351,2.581176,-0.140317, + -0.069594,-0.997575,-0.000151,4.317602,2.588926,-0.000745, + 0.169654,-0.985504,-0.000285,4.454962,2.523303,-0.000603, + 0.850248,-0.122855,0.511845,4.342351,2.581176,-0.140317, + 0.169654,-0.985504,-0.000285,4.454962,2.523303,-0.000603, + 0.603381,-0.138834,0.785275,4.452383,2.524558,-0.130255, + 0.335985,-0.093511,0.937214,4.332083,2.586481,-0.194917, + 0.850248,-0.122855,0.511845,4.342351,2.581176,-0.140317, + 0.603381,-0.138834,0.785275,4.452383,2.524558,-0.130255, + 0.335985,-0.093511,0.937214,4.332083,2.586481,-0.194917, + 0.603381,-0.138834,0.785275,4.452383,2.524558,-0.130255, + 0.104604,0.23696,0.965872,4.440143,2.510529,-0.269164, + 0.169215,-0.167065,0.971316,4.339601,2.592642,-0.258891, + 0.335985,-0.093511,0.937214,4.332083,2.586481,-0.194917, + 0.104604,0.23696,0.965872,4.440143,2.510529,-0.269164, + 0.169215,-0.167065,0.971316,4.339601,2.592642,-0.258891, + 0.104604,0.23696,0.965872,4.440143,2.510529,-0.269164, + 0.054838,0.685321,0.726174,4.429895,2.495758,-0.306894, + -0.026478,0.945923,0.32331,4.187258,2.590221,-0.135844, + 0.172357,-0.985035,-0.000083,4.189883,2.606916,-0.000863, + -0.069594,-0.997575,-0.000151,4.317602,2.588926,-0.000745, + -0.026478,0.945923,0.32331,4.187258,2.590221,-0.135844, + -0.069594,-0.997575,-0.000151,4.317602,2.588926,-0.000745, + 0.850248,-0.122855,0.511845,4.342351,2.581176,-0.140317, + -0.071389,0.260054,0.962951,4.203325,2.589186,-0.219164, + -0.026478,0.945923,0.32331,4.187258,2.590221,-0.135844, + 0.850248,-0.122855,0.511845,4.342351,2.581176,-0.140317, + -0.071389,0.260054,0.962951,4.203325,2.589186,-0.219164, + 0.850248,-0.122855,0.511845,4.342351,2.581176,-0.140317, + 0.335985,-0.093511,0.937214,4.332083,2.586481,-0.194917, + -0.01127,-0.268802,0.96313,4.211652,2.602538,-0.264011, + -0.071389,0.260054,0.962951,4.203325,2.589186,-0.219164, + 0.335985,-0.093511,0.937214,4.332083,2.586481,-0.194917, + -0.01127,-0.268802,0.96313,4.211652,2.602538,-0.264011, + 0.335985,-0.093511,0.937214,4.332083,2.586481,-0.194917, + 0.169215,-0.167065,0.971316,4.339601,2.592642,-0.258891, + -0.03479,0.69667,0.716547,4.209941,2.600612,-0.337597, + -0.01127,-0.268802,0.96313,4.211652,2.602538,-0.264011, + 0.169215,-0.167065,0.971316,4.339601,2.592642,-0.258891, + -0.03479,0.69667,0.716547,4.209941,2.600612,-0.337597, + 0.169215,-0.167065,0.971316,4.339601,2.592642,-0.258891, + -0.01139,0.953897,0.299916,4.328606,2.563996,-0.343892, + -0.01139,0.953897,0.299916,4.328606,2.563996,-0.343892, + 0.169215,-0.167065,0.971316,4.339601,2.592642,-0.258891, + 0.054838,0.685321,0.726174,4.429895,2.495758,-0.306894, + -0.01139,0.953897,0.299916,4.328606,2.563996,-0.343892, + 0.054838,0.685321,0.726174,4.429895,2.495758,-0.306894, + -0.151742,0.274295,0.949598,4.410844,2.500167,-0.351972, + 0.210866,-0.977515,0.000009,4.528082,2.467537,-0.000521, + -0.965284,-0.261201,0,4.747988,2.300163,-0.000276, + 0.337014,-0.030018,-0.941021,4.634996,2.369115,-0.140117, + 0.603381,-0.138834,0.785275,4.452383,2.524558,-0.130255, + 0.169654,-0.985504,-0.000285,4.454962,2.523303,-0.000603, + 0.210866,-0.977515,0.000009,4.528082,2.467537,-0.000521, + 0.603381,-0.138834,0.785275,4.452383,2.524558,-0.130255, + 0.210866,-0.977515,0.000009,4.528082,2.467537,-0.000521, + 0.337014,-0.030018,-0.941021,4.634996,2.369115,-0.140117, + 0.603381,-0.138834,0.785275,4.452383,2.524558,-0.130255, + 0.337014,-0.030018,-0.941021,4.634996,2.369115,-0.140117, + 0.272203,0.043076,-0.961275,4.577573,2.389535,-0.256196, + 0.104604,0.23696,0.965872,4.440143,2.510529,-0.269164, + 0.603381,-0.138834,0.785275,4.452383,2.524558,-0.130255, + 0.272203,0.043076,-0.961275,4.577573,2.389535,-0.256196, + 0.054838,0.685321,0.726174,4.429895,2.495758,-0.306894, + 0.104604,0.23696,0.965872,4.440143,2.510529,-0.269164, + 0.272203,0.043076,-0.961275,4.577573,2.389535,-0.256196, + 0.288841,-0.745301,0.600914,4.474318,2.418432,-0.361347, + -0.151742,0.274295,0.949598,4.410844,2.500167,-0.351972, + 0.054838,0.685321,0.726174,4.429895,2.495758,-0.306894, + 0.288841,-0.745301,0.600914,4.474318,2.418432,-0.361347, + 0.054838,0.685321,0.726174,4.429895,2.495758,-0.306894, + 0.272203,0.043076,-0.961275,4.577573,2.389535,-0.256196, + 0.288841,-0.745301,0.600914,4.474318,2.418432,-0.361347, + 0.272203,0.043076,-0.961275,4.577573,2.389535,-0.256196, + 0.195545,0.103956,-0.975169,4.472349,2.325133,-0.443764, + -0.130291,0.991051,-0.029017,4.063205,2.509679,-0.342987, + -0.904972,-0.026554,-0.424642,4.088356,2.510913,-0.453793, + -0.330515,0.821242,-0.465103,4.07851,2.41181,-0.472193, + -0.130291,0.991051,-0.029017,4.063205,2.509679,-0.342987, + -0.330515,0.821242,-0.465103,4.07851,2.41181,-0.472193, + -0.501952,0.842503,-0.195533,4.043796,2.386524,-0.400392, + -0.778384,0.466328,-0.420305,4.055262,2.505284,-0.297282, + -0.130291,0.991051,-0.029017,4.063205,2.509679,-0.342987, + -0.501952,0.842503,-0.195533,4.043796,2.386524,-0.400392, + -0.778384,0.466328,-0.420305,4.055262,2.505284,-0.297282, + -0.501952,0.842503,-0.195533,4.043796,2.386524,-0.400392, + -0.877603,-0.025307,-0.47872,4.035753,2.399538,-0.343957, + -0.026478,0.945923,0.32331,4.187258,2.590221,-0.135844, + 0.223577,0.97296,0.057987,4.084506,2.570978,-0.218168, + 0.272993,0.962016,-0.000199,4.079812,2.571649,-0.000951, + -0.026478,0.945923,0.32331,4.187258,2.590221,-0.135844, + 0.272993,0.962016,-0.000199,4.079812,2.571649,-0.000951, + 0.172357,-0.985035,-0.000083,4.189883,2.606916,-0.000863, + -0.071389,0.260054,0.962951,4.203325,2.589186,-0.219164, + -0.247355,0.948391,0.198417,4.101754,2.557092,-0.265856, + 0.223577,0.97296,0.057987,4.084506,2.570978,-0.218168, + -0.071389,0.260054,0.962951,4.203325,2.589186,-0.219164, + 0.223577,0.97296,0.057987,4.084506,2.570978,-0.218168, + -0.026478,0.945923,0.32331,4.187258,2.590221,-0.135844, + -0.01127,-0.268802,0.96313,4.211652,2.602538,-0.264011, + -0.671787,0.737297,-0.07138,4.100907,2.560626,-0.302396, + -0.247355,0.948391,0.198417,4.101754,2.557092,-0.265856, + -0.01127,-0.268802,0.96313,4.211652,2.602538,-0.264011, + -0.247355,0.948391,0.198417,4.101754,2.557092,-0.265856, + -0.071389,0.260054,0.962951,4.203325,2.589186,-0.219164, + -0.03479,0.69667,0.716547,4.209941,2.600612,-0.337597, + -0.860594,0.405545,-0.308076,4.117367,2.568514,-0.3845, + -0.671787,0.737297,-0.07138,4.100907,2.560626,-0.302396, + -0.03479,0.69667,0.716547,4.209941,2.600612,-0.337597, + -0.671787,0.737297,-0.07138,4.100907,2.560626,-0.302396, + -0.01127,-0.268802,0.96313,4.211652,2.602538,-0.264011, + -0.877603,-0.025307,-0.47872,4.035753,2.399538,-0.343957, + -0.683788,0.700764,0.203383,4.00011,2.424158,-0.313254, + -0.849668,0.488772,0.197904,4.029016,2.519175,-0.249385, + -0.877603,-0.025307,-0.47872,4.035753,2.399538,-0.343957, + -0.849668,0.488772,0.197904,4.029016,2.519175,-0.249385, + -0.778384,0.466328,-0.420305,4.055262,2.505284,-0.297282, + 0.544067,0.839042,-0.000076,4.024214,2.527933,-0.000987, + -0.849668,0.488772,0.197904,4.029016,2.519175,-0.249385, + -0.683788,0.700764,0.203383,4.00011,2.424158,-0.313254, + 0.544067,0.839042,-0.000076,4.024214,2.527933,-0.000987, + -0.683788,0.700764,0.203383,4.00011,2.424158,-0.313254, + -0.069267,0.997598,-0.000362,3.988172,2.489642,-0.001008, + 0.544067,0.839042,-0.000076,4.024214,2.527933,-0.000987, + 0.272993,0.962016,-0.000199,4.079812,2.571649,-0.000951, + 0.223577,0.97296,0.057987,4.084506,2.570978,-0.218168, + 0.544067,0.839042,-0.000076,4.024214,2.527933,-0.000987, + 0.223577,0.97296,0.057987,4.084506,2.570978,-0.218168, + -0.849668,0.488772,0.197904,4.029016,2.519175,-0.249385, + -0.849668,0.488772,0.197904,4.029016,2.519175,-0.249385, + 0.223577,0.97296,0.057987,4.084506,2.570978,-0.218168, + -0.247355,0.948391,0.198417,4.101754,2.557092,-0.265856, + -0.849668,0.488772,0.197904,4.029016,2.519175,-0.249385, + -0.247355,0.948391,0.198417,4.101754,2.557092,-0.265856, + -0.778384,0.466328,-0.420305,4.055262,2.505284,-0.297282, + -0.778384,0.466328,-0.420305,4.055262,2.505284,-0.297282, + -0.247355,0.948391,0.198417,4.101754,2.557092,-0.265856, + -0.671787,0.737297,-0.07138,4.100907,2.560626,-0.302396, + -0.778384,0.466328,-0.420305,4.055262,2.505284,-0.297282, + -0.671787,0.737297,-0.07138,4.100907,2.560626,-0.302396, + -0.130291,0.991051,-0.029017,4.063205,2.509679,-0.342987, + -0.130291,0.991051,-0.029017,4.063205,2.509679,-0.342987, + -0.671787,0.737297,-0.07138,4.100907,2.560626,-0.302396, + -0.860594,0.405545,-0.308076,4.117367,2.568514,-0.3845, + -0.130291,0.991051,-0.029017,4.063205,2.509679,-0.342987, + -0.860594,0.405545,-0.308076,4.117367,2.568514,-0.3845, + -0.904972,-0.026554,-0.424642,4.088356,2.510913,-0.453793, + 0.622247,0.782821,-0.000247,3.787342,2.396113,-0.001159, + -0.069267,0.997598,-0.000362,3.988172,2.489642,-0.001008, + -0.683788,0.700764,0.203383,4.00011,2.424158,-0.313254, + 0.622247,0.782821,-0.000247,3.787342,2.396113,-0.001159, + -0.683788,0.700764,0.203383,4.00011,2.424158,-0.313254, + -0.210883,0.942026,0.260987,3.828001,2.35254,-0.233341, + -0.683788,0.700764,0.203383,4.00011,2.424158,-0.313254, + -0.892748,0.392127,0.221893,3.961908,2.347745,-0.374747, + -0.502349,0.838172,0.212398,3.870548,2.292106,-0.368964, + -0.683788,0.700764,0.203383,4.00011,2.424158,-0.313254, + -0.502349,0.838172,0.212398,3.870548,2.292106,-0.368964, + -0.210883,0.942026,0.260987,3.828001,2.35254,-0.233341, + -0.683788,0.700764,0.203383,4.00011,2.424158,-0.313254, + -0.877603,-0.025307,-0.47872,4.035753,2.399538,-0.343957, + -0.501952,0.842503,-0.195533,4.043796,2.386524,-0.400392, + -0.683788,0.700764,0.203383,4.00011,2.424158,-0.313254, + -0.501952,0.842503,-0.195533,4.043796,2.386524,-0.400392, + -0.981668,0.173926,0.077954,4.025364,2.3593,-0.402597, + -0.683788,0.700764,0.203383,4.00011,2.424158,-0.313254, + -0.981668,0.173926,0.077954,4.025364,2.3593,-0.402597, + -0.892748,0.392127,0.221893,3.961908,2.347745,-0.374747, + -0.892748,0.392127,0.221893,3.961908,2.347745,-0.374747, + -0.981668,0.173926,0.077954,4.025364,2.3593,-0.402597, + -0.990661,0.056144,0.124249,4.077563,2.305187,-0.510338, + -0.892748,0.392127,0.221893,3.961908,2.347745,-0.374747, + -0.990661,0.056144,0.124249,4.077563,2.305187,-0.510338, + -0.894795,0.444359,0.043442,3.967085,2.280648,-0.537643, + -0.502349,0.838172,0.212398,3.870548,2.292106,-0.368964, + -0.892748,0.392127,0.221893,3.961908,2.347745,-0.374747, + -0.894795,0.444359,0.043442,3.967085,2.280648,-0.537643, + -0.502349,0.838172,0.212398,3.870548,2.292106,-0.368964, + -0.894795,0.444359,0.043442,3.967085,2.280648,-0.537643, + -0.941564,0.056552,-0.332054,3.903911,2.241501,-0.512468, + -0.502349,0.838172,0.212398,3.870548,2.292106,-0.368964, + -0.941564,0.056552,-0.332054,3.903911,2.241501,-0.512468, + -0.984655,0.15519,-0.07981,3.857922,2.141554,-0.521067, + -0.502349,0.838172,0.212398,3.870548,2.292106,-0.368964, + -0.984655,0.15519,-0.07981,3.857922,2.141554,-0.521067, + -0.768362,0.592232,0.242656,3.823349,2.141733,-0.428356, + -0.501952,0.842503,-0.195533,4.043796,2.386524,-0.400392, + -0.330515,0.821242,-0.465103,4.07851,2.41181,-0.472193, + -0.536307,0.710867,-0.45502,4.113935,2.334131,-0.526471, + -0.501952,0.842503,-0.195533,4.043796,2.386524,-0.400392, + -0.536307,0.710867,-0.45502,4.113935,2.334131,-0.526471, + -0.990661,0.056144,0.124249,4.077563,2.305187,-0.510338, + -0.501952,0.842503,-0.195533,4.043796,2.386524,-0.400392, + -0.990661,0.056144,0.124249,4.077563,2.305187,-0.510338, + -0.981668,0.173926,0.077954,4.025364,2.3593,-0.402597, + -0.990661,0.056144,0.124249,4.077563,2.305187,-0.510338, + -0.978317,0.206989,0.00716,4.112302,2.285832,-0.5955, + -0.463096,-0.149334,-0.873637,4.010847,2.270246,-0.622149, + -0.990661,0.056144,0.124249,4.077563,2.305187,-0.510338, + -0.463096,-0.149334,-0.873637,4.010847,2.270246,-0.622149, + -0.894795,0.444359,0.043442,3.967085,2.280648,-0.537643, + -0.894795,0.444359,0.043442,3.967085,2.280648,-0.537643, + -0.463096,-0.149334,-0.873637,4.010847,2.270246,-0.622149, + -0.641549,-0.578509,-0.503727,3.928869,2.223919,-0.615683, + -0.894795,0.444359,0.043442,3.967085,2.280648,-0.537643, + -0.641549,-0.578509,-0.503727,3.928869,2.223919,-0.615683, + -0.941564,0.056552,-0.332054,3.903911,2.241501,-0.512468, + -0.941564,0.056552,-0.332054,3.903911,2.241501,-0.512468, + -0.641549,-0.578509,-0.503727,3.928869,2.223919,-0.615683, + -0.791764,-0.610494,0.020171,3.892378,2.149432,-0.603589, + -0.941564,0.056552,-0.332054,3.903911,2.241501,-0.512468, + -0.791764,-0.610494,0.020171,3.892378,2.149432,-0.603589, + -0.984655,0.15519,-0.07981,3.857922,2.141554,-0.521067, + -0.978317,0.206989,0.00716,4.112302,2.285832,-0.5955, + -0.832539,-0.5495,-0.070196,4.146067,2.278102,-0.707372, + -0.862876,-0.450622,-0.228877,4.04473,2.254459,-0.744209, + -0.978317,0.206989,0.00716,4.112302,2.285832,-0.5955, + -0.862876,-0.450622,-0.228877,4.04473,2.254459,-0.744209, + -0.463096,-0.149334,-0.873637,4.010847,2.270246,-0.622149, + -0.641549,-0.578509,-0.503727,3.928869,2.223919,-0.615683, + -0.463096,-0.149334,-0.873637,4.010847,2.270246,-0.622149, + -0.862876,-0.450622,-0.228877,4.04473,2.254459,-0.744209, + -0.641549,-0.578509,-0.503727,3.928869,2.223919,-0.615683, + -0.862876,-0.450622,-0.228877,4.04473,2.254459,-0.744209, + -0.916648,-0.2944,-0.270344,3.990744,2.205448,-0.710795, + -0.641549,-0.578509,-0.503727,3.928869,2.223919,-0.615683, + -0.916648,-0.2944,-0.270344,3.990744,2.205448,-0.710795, + -0.975013,-0.179567,-0.130791,3.945464,2.1301,-0.689536, + -0.641549,-0.578509,-0.503727,3.928869,2.223919,-0.615683, + -0.975013,-0.179567,-0.130791,3.945464,2.1301,-0.689536, + -0.791764,-0.610494,0.020171,3.892378,2.149432,-0.603589, + -0.536307,0.710867,-0.45502,4.113935,2.334131,-0.526471, + -0.091679,0.768658,-0.633056,4.296769,2.260422,-0.528796, + -0.963659,-0.230665,-0.134738,4.212974,2.303184,-0.587113, + -0.990661,0.056144,0.124249,4.077563,2.305187,-0.510338, + -0.536307,0.710867,-0.45502,4.113935,2.334131,-0.526471, + -0.963659,-0.230665,-0.134738,4.212974,2.303184,-0.587113, + -0.990661,0.056144,0.124249,4.077563,2.305187,-0.510338, + -0.963659,-0.230665,-0.134738,4.212974,2.303184,-0.587113, + -0.978317,0.206989,0.00716,4.112302,2.285832,-0.5955, + -0.963659,-0.230665,-0.134738,4.212974,2.303184,-0.587113, + -0.990956,-0.062739,-0.118613,4.212058,2.27945,-0.625927, + -0.832539,-0.5495,-0.070196,4.146067,2.278102,-0.707372, + -0.963659,-0.230665,-0.134738,4.212974,2.303184,-0.587113, + -0.832539,-0.5495,-0.070196,4.146067,2.278102,-0.707372, + -0.978317,0.206989,0.00716,4.112302,2.285832,-0.5955, + -0.990956,-0.062739,-0.118613,4.212058,2.27945,-0.625927, + -0.938303,-0.3372,-0.076703,4.229332,2.274522,-0.672749, + -0.473779,-0.24744,-0.845167,4.172143,2.303394,-0.778972, + -0.990956,-0.062739,-0.118613,4.212058,2.27945,-0.625927, + -0.473779,-0.24744,-0.845167,4.172143,2.303394,-0.778972, + -0.832539,-0.5495,-0.070196,4.146067,2.278102,-0.707372, + -0.832539,-0.5495,-0.070196,4.146067,2.278102,-0.707372, + -0.473779,-0.24744,-0.845167,4.172143,2.303394,-0.778972, + -0.713872,-0.610821,-0.342469,4.079122,2.264104,-0.84501, + -0.832539,-0.5495,-0.070196,4.146067,2.278102,-0.707372, + -0.713872,-0.610821,-0.342469,4.079122,2.264104,-0.84501, + -0.862876,-0.450622,-0.228877,4.04473,2.254459,-0.744209, + -0.862876,-0.450622,-0.228877,4.04473,2.254459,-0.744209, + -0.713872,-0.610821,-0.342469,4.079122,2.264104,-0.84501, + -0.719395,-0.61545,-0.322011,4.0247,2.187859,-0.814219, + -0.862876,-0.450622,-0.228877,4.04473,2.254459,-0.744209, + -0.719395,-0.61545,-0.322011,4.0247,2.187859,-0.814219, + -0.916648,-0.2944,-0.270344,3.990744,2.205448,-0.710795, + -0.938303,-0.3372,-0.076703,4.229332,2.274522,-0.672749, + -0.841909,-0.49598,-0.212588,4.273005,2.310529,-0.762172, + 0.760119,-0.003927,-0.649772,4.215419,2.350484,-0.885764, + -0.938303,-0.3372,-0.076703,4.229332,2.274522,-0.672749, + 0.760119,-0.003927,-0.649772,4.215419,2.350484,-0.885764, + -0.473779,-0.24744,-0.845167,4.172143,2.303394,-0.778972, + -0.473779,-0.24744,-0.845167,4.172143,2.303394,-0.778972, + 0.760119,-0.003927,-0.649772,4.215419,2.350484,-0.885764, + 0.911709,-0.064352,-0.405765,4.104864,2.298353,-0.915735, + -0.473779,-0.24744,-0.845167,4.172143,2.303394,-0.778972, + 0.911709,-0.064352,-0.405765,4.104864,2.298353,-0.915735, + -0.713872,-0.610821,-0.342469,4.079122,2.264104,-0.84501, + -0.713872,-0.610821,-0.342469,4.079122,2.264104,-0.84501, + 0.911709,-0.064352,-0.405765,4.104864,2.298353,-0.915735, + 0.3335,0.232683,-0.913584,4.059714,2.194906,-0.888152, + -0.713872,-0.610821,-0.342469,4.079122,2.264104,-0.84501, + 0.3335,0.232683,-0.913584,4.059714,2.194906,-0.888152, + -0.719395,-0.61545,-0.322011,4.0247,2.187859,-0.814219, + 0.245858,0.150988,-0.957474,4.061989,2.231988,-1.178382, + 0.89585,0.32639,-0.301532,4.102304,2.29996,-1.025862, + -0.396467,0.225967,-0.889805,4.155551,2.388662,-1.09196, + 0.245858,0.150988,-0.957474,4.061989,2.231988,-1.178382, + -0.396467,0.225967,-0.889805,4.155551,2.388662,-1.09196, + -0.279333,0.256919,-0.925184,4.097362,2.3666,-1.239986, + 0.911709,-0.064352,-0.405765,4.104864,2.298353,-0.915735, + 0.760119,-0.003927,-0.649772,4.215419,2.350484,-0.885764, + -0.564249,0.755597,0.33271,4.194233,2.408334,-1.008471, + 0.911709,-0.064352,-0.405765,4.104864,2.298353,-0.915735, + -0.564249,0.755597,0.33271,4.194233,2.408334,-1.008471, + 0.89585,0.32639,-0.301532,4.102304,2.29996,-1.025862, + 0.89585,0.32639,-0.301532,4.102304,2.29996,-1.025862, + -0.564249,0.755597,0.33271,4.194233,2.408334,-1.008471, + -0.396467,0.225967,-0.889805,4.155551,2.388662,-1.09196, + 0.760119,-0.003927,-0.649772,4.215419,2.350484,-0.885764, + -0.841909,-0.49598,-0.212588,4.273005,2.310529,-0.762172, + -0.571598,0.654164,0.495323,4.307092,2.367482,-0.877202, + 0.760119,-0.003927,-0.649772,4.215419,2.350484,-0.885764, + -0.571598,0.654164,0.495323,4.307092,2.367482,-0.877202, + -0.601466,0.441167,0.666041,4.266263,2.421651,-1.054799, + 0.760119,-0.003927,-0.649772,4.215419,2.350484,-0.885764, + -0.601466,0.441167,0.666041,4.266263,2.421651,-1.054799, + -0.564249,0.755597,0.33271,4.194233,2.408334,-1.008471, + -0.564249,0.755597,0.33271,4.194233,2.408334,-1.008471, + -0.601466,0.441167,0.666041,4.266263,2.421651,-1.054799, + -0.434016,0.136262,0.890541,4.228523,2.435029,-1.098575, + -0.564249,0.755597,0.33271,4.194233,2.408334,-1.008471, + -0.434016,0.136262,0.890541,4.228523,2.435029,-1.098575, + -0.396467,0.225967,-0.889805,4.155551,2.388662,-1.09196, + -0.396467,0.225967,-0.889805,4.155551,2.388662,-1.09196, + -0.434016,0.136262,0.890541,4.228523,2.435029,-1.098575, + -0.195132,0.128745,0.97229,4.17047,2.458441,-1.241846, + -0.396467,0.225967,-0.889805,4.155551,2.388662,-1.09196, + -0.195132,0.128745,0.97229,4.17047,2.458441,-1.241846, + -0.279333,0.256919,-0.925184,4.097362,2.3666,-1.239986, + -0.279333,0.256919,-0.925184,4.097362,2.3666,-1.239986, + -0.195132,0.128745,0.97229,4.17047,2.458441,-1.241846, + -0.172151,0.101796,0.979797,4.094116,2.426172,-1.381032, + -0.279333,0.256919,-0.925184,4.097362,2.3666,-1.239986, + -0.172151,0.101796,0.979797,4.094116,2.426172,-1.381032, + -0.086812,-0.050981,0.994919,4.058311,2.293363,-1.338054, + -0.086812,-0.050981,0.994919,4.058311,2.293363,-1.338054, + -0.172151,0.101796,0.979797,4.094116,2.426172,-1.381032, + 0.020519,-0.282941,0.958918,4.046673,2.341349,-1.45253, + 0.3335,0.232683,-0.913584,4.059714,2.194906,-0.888152, + 0.911709,-0.064352,-0.405765,4.104864,2.298353,-0.915735, + 0.89585,0.32639,-0.301532,4.102304,2.29996,-1.025862, + 0.3335,0.232683,-0.913584,4.059714,2.194906,-0.888152, + 0.89585,0.32639,-0.301532,4.102304,2.29996,-1.025862, + 0.161194,-0.480657,0.861966,4.047406,2.207209,-1.015108, + 0.161194,-0.480657,0.861966,4.047406,2.207209,-1.015108, + 0.89585,0.32639,-0.301532,4.102304,2.29996,-1.025862, + 0.245858,0.150988,-0.957474,4.061989,2.231988,-1.178382, + -0.975013,-0.179567,-0.130791,3.945464,2.1301,-0.689536, + -0.916648,-0.2944,-0.270344,3.990744,2.205448,-0.710795, + -0.719395,-0.61545,-0.322011,4.0247,2.187859,-0.814219, + -0.975013,-0.179567,-0.130791,3.945464,2.1301,-0.689536, + -0.719395,-0.61545,-0.322011,4.0247,2.187859,-0.814219, + 0.313443,-0.691245,0.651102,3.989434,2.118832,-0.765086, + 0.313443,-0.691245,0.651102,3.989434,2.118832,-0.765086, + -0.719395,-0.61545,-0.322011,4.0247,2.187859,-0.814219, + 0.3335,0.232683,-0.913584,4.059714,2.194906,-0.888152, + 0.313443,-0.691245,0.651102,3.989434,2.118832,-0.765086, + 0.3335,0.232683,-0.913584,4.059714,2.194906,-0.888152, + 0.492393,-0.77993,0.38634,4.022592,2.123052,-0.903284, + 0.492393,-0.77993,0.38634,4.022592,2.123052,-0.903284, + 0.3335,0.232683,-0.913584,4.059714,2.194906,-0.888152, + 0.161194,-0.480657,0.861966,4.047406,2.207209,-1.015108, + 0.492393,-0.77993,0.38634,4.022592,2.123052,-0.903284, + 0.161194,-0.480657,0.861966,4.047406,2.207209,-1.015108, + -0.463441,0.825581,0.321928,4.020299,2.141675,-1.002365, + -0.463441,0.825581,0.321928,4.020299,2.141675,-1.002365, + 0.161194,-0.480657,0.861966,4.047406,2.207209,-1.015108, + 0.245858,0.150988,-0.957474,4.061989,2.231988,-1.178382, + 0.245858,0.150988,-0.957474,4.061989,2.231988,-1.178382, + -0.279333,0.256919,-0.925184,4.097362,2.3666,-1.239986, + -0.086812,-0.050981,0.994919,4.058311,2.293363,-1.338054, + 0.261393,-0.399072,0.878872,4.036947,1.992167,-1.072561, + -0.463441,0.825581,0.321928,4.020299,2.141675,-1.002365, + 0.245858,0.150988,-0.957474,4.061989,2.231988,-1.178382, + 0.261393,-0.399072,0.878872,4.036947,1.992167,-1.072561, + 0.245858,0.150988,-0.957474,4.061989,2.231988,-1.178382, + 0.428291,-0.499911,0.752765,4.024858,2.106568,-1.208099, + 0.428291,-0.499911,0.752765,4.024858,2.106568,-1.208099, + 0.245858,0.150988,-0.957474,4.061989,2.231988,-1.178382, + -0.086812,-0.050981,0.994919,4.058311,2.293363,-1.338054, + -0.086812,-0.050981,0.994919,4.058311,2.293363,-1.338054, + 0.020519,-0.282941,0.958918,4.046673,2.341349,-1.45253, + 0.07924,-0.231863,0.969516,4.082988,2.175805,-1.45093, + -0.081635,-0.03459,0.996062,4.103303,2.038565,-1.363737, + 0.428291,-0.499911,0.752765,4.024858,2.106568,-1.208099, + -0.086812,-0.050981,0.994919,4.058311,2.293363,-1.338054, + -0.081635,-0.03459,0.996062,4.103303,2.038565,-1.363737, + -0.086812,-0.050981,0.994919,4.058311,2.293363,-1.338054, + 0.07924,-0.231863,0.969516,4.082988,2.175805,-1.45093, + 0.428291,-0.499911,0.752765,4.024858,2.106568,-1.208099, + -0.081635,-0.03459,0.996062,4.103303,2.038565,-1.363737, + -0.178707,0.132414,0.974951,4.152166,1.868775,-1.225002, + 0.428291,-0.499911,0.752765,4.024858,2.106568,-1.208099, + -0.178707,0.132414,0.974951,4.152166,1.868775,-1.225002, + 0.261393,-0.399072,0.878872,4.036947,1.992167,-1.072561, + 0.454048,-0.464454,0.760344,4.031515,1.968248,-0.91846, + 0.261393,-0.399072,0.878872,4.036947,1.992167,-1.072561, + -0.178707,0.132414,0.974951,4.152166,1.868775,-1.225002, + 0.454048,-0.464454,0.760344,4.031515,1.968248,-0.91846, + -0.178707,0.132414,0.974951,4.152166,1.868775,-1.225002, + -0.21777,0.161093,0.962614,4.127903,1.828359,-1.090512, + 0.454048,-0.464454,0.760344,4.031515,1.968248,-0.91846, + 0.492393,-0.77993,0.38634,4.022592,2.123052,-0.903284, + -0.463441,0.825581,0.321928,4.020299,2.141675,-1.002365, + 0.454048,-0.464454,0.760344,4.031515,1.968248,-0.91846, + -0.463441,0.825581,0.321928,4.020299,2.141675,-1.002365, + 0.261393,-0.399072,0.878872,4.036947,1.992167,-1.072561, + 0.673211,-0.580891,0.457551,3.922437,1.972461,-0.483563, + -0.768362,0.592232,0.242656,3.823349,2.141733,-0.428356, + -0.984655,0.15519,-0.07981,3.857922,2.141554,-0.521067, + 0.673211,-0.580891,0.457551,3.922437,1.972461,-0.483563, + -0.984655,0.15519,-0.07981,3.857922,2.141554,-0.521067, + -0.384424,0.863444,0.326623,3.966639,1.969285,-0.549291, + -0.384424,0.863444,0.326623,3.966639,1.969285,-0.549291, + -0.984655,0.15519,-0.07981,3.857922,2.141554,-0.521067, + -0.791764,-0.610494,0.020171,3.892378,2.149432,-0.603589, + -0.384424,0.863444,0.326623,3.966639,1.969285,-0.549291, + -0.791764,-0.610494,0.020171,3.892378,2.149432,-0.603589, + -0.354832,0.724971,0.590348,3.98291,1.987391,-0.639809, + 0.673211,-0.580891,0.457551,3.922437,1.972461,-0.483563, + -0.384424,0.863444,0.326623,3.966639,1.969285,-0.549291, + -0.385487,0.478576,0.788901,4.094112,1.889281,-0.578435, + 0.673211,-0.580891,0.457551,3.922437,1.972461,-0.483563, + -0.385487,0.478576,0.788901,4.094112,1.889281,-0.578435, + -0.447812,0.698934,0.557634,4.059885,1.86046,-0.470087, + -0.384424,0.863444,0.326623,3.966639,1.969285,-0.549291, + -0.354832,0.724971,0.590348,3.98291,1.987391,-0.639809, + -0.385487,0.478576,0.788901,4.094112,1.889281,-0.578435, + 0.313443,-0.691245,0.651102,3.989434,2.118832,-0.765086, + 0.492393,-0.77993,0.38634,4.022592,2.123052,-0.903284, + 0.454048,-0.464454,0.760344,4.031515,1.968248,-0.91846, + 0.313443,-0.691245,0.651102,3.989434,2.118832,-0.765086, + 0.454048,-0.464454,0.760344,4.031515,1.968248,-0.91846, + -0.270788,0.46353,0.843691,4.017509,1.996169,-0.731654, + -0.270788,0.46353,0.843691,4.017509,1.996169,-0.731654, + -0.975013,-0.179567,-0.130791,3.945464,2.1301,-0.689536, + 0.313443,-0.691245,0.651102,3.989434,2.118832,-0.765086, + -0.354832,0.724971,0.590348,3.98291,1.987391,-0.639809, + -0.791764,-0.610494,0.020171,3.892378,2.149432,-0.603589, + -0.975013,-0.179567,-0.130791,3.945464,2.1301,-0.689536, + -0.354832,0.724971,0.590348,3.98291,1.987391,-0.639809, + -0.975013,-0.179567,-0.130791,3.945464,2.1301,-0.689536, + -0.270788,0.46353,0.843691,4.017509,1.996169,-0.731654, + -0.354832,0.724971,0.590348,3.98291,1.987391,-0.639809, + -0.270788,0.46353,0.843691,4.017509,1.996169,-0.731654, + -0.385487,0.478576,0.788901,4.094112,1.889281,-0.578435, + -0.270788,0.46353,0.843691,4.017509,1.996169,-0.731654, + -0.273816,0.228927,0.93414,4.150297,1.820575,-0.917046, + -0.385487,0.478576,0.788901,4.094112,1.889281,-0.578435, + -0.270788,0.46353,0.843691,4.017509,1.996169,-0.731654, + 0.454048,-0.464454,0.760344,4.031515,1.968248,-0.91846, + -0.21777,0.161093,0.962614,4.127903,1.828359,-1.090512, + -0.270788,0.46353,0.843691,4.017509,1.996169,-0.731654, + -0.21777,0.161093,0.962614,4.127903,1.828359,-1.090512, + -0.273816,0.228927,0.93414,4.150297,1.820575,-0.917046, + -0.091679,0.768658,-0.633056,4.296769,2.260422,-0.528796, + 0.195545,0.103956,-0.975169,4.472349,2.325133,-0.443764, + 0.196849,0.14562,-0.969559,4.389484,2.190421,-0.47332, + -0.203969,0.261593,0.94338,4.314791,2.142163,-0.54065, + 0.196849,0.14562,-0.969559,4.389484,2.190421,-0.47332, + 0.159882,0.223439,0.961516,4.3427,2.112281,-0.516692, + -0.203969,0.261593,0.94338,4.314791,2.142163,-0.54065, + 0.159882,0.223439,0.961516,4.3427,2.112281,-0.516692, + 0.224429,0.165293,0.96037,4.305411,2.059245,-0.539407, + -0.203969,0.261593,0.94338,4.314791,2.142163,-0.54065, + -0.091679,0.768658,-0.633056,4.296769,2.260422,-0.528796, + 0.196849,0.14562,-0.969559,4.389484,2.190421,-0.47332, + 0.159882,0.223439,0.961516,4.3427,2.112281,-0.516692, + 0.196849,0.14562,-0.969559,4.389484,2.190421,-0.47332, + 0.361081,-0.056526,-0.93082,4.43302,2.024714,-0.563794, + 0.224429,0.165293,0.96037,4.305411,2.059245,-0.539407, + 0.159882,0.223439,0.961516,4.3427,2.112281,-0.516692, + 0.361081,-0.056526,-0.93082,4.43302,2.024714,-0.563794, + 0.020519,-0.282941,0.958918,4.046673,2.341349,-1.45253, + -0.172151,0.101796,0.979797,4.094116,2.426172,-1.381032, + 0.482381,-0.398126,0.780259,4.148927,2.388726,-1.376879, + 0.020519,-0.282941,0.958918,4.046673,2.341349,-1.45253, + 0.482381,-0.398126,0.780259,4.148927,2.388726,-1.376879, + 0.702554,-0.570096,0.42592,4.101726,2.312318,-1.438163, + 0.45552,-0.330523,0.826593,4.149438,2.34055,-1.353693, + 0.331391,0.08899,0.939287,4.169404,2.306276,-1.284031, + 0.445439,-0.182623,0.876489,4.140097,2.295949,-1.367196, + 0.45552,-0.330523,0.826593,4.149438,2.34055,-1.353693, + 0.445439,-0.182623,0.876489,4.140097,2.295949,-1.367196, + 0.489736,-0.346185,0.800197,4.129926,2.30877,-1.402259, + 0.331391,0.08899,0.939287,4.169404,2.306276,-1.284031, + 0.474213,-0.311965,0.823286,4.141759,2.279958,-1.29534, + 0.445439,-0.182623,0.876489,4.140097,2.295949,-1.367196, + -0.172151,0.101796,0.979797,4.094116,2.426172,-1.381032, + -0.195132,0.128745,0.97229,4.17047,2.458441,-1.241846, + 0.483908,-0.405185,0.775667,4.197644,2.394643,-1.248646, + -0.172151,0.101796,0.979797,4.094116,2.426172,-1.381032, + 0.483908,-0.405185,0.775667,4.197644,2.394643,-1.248646, + 0.482381,-0.398126,0.780259,4.148927,2.388726,-1.376879, + 0.482381,-0.398126,0.780259,4.148927,2.388726,-1.376879, + 0.483908,-0.405185,0.775667,4.197644,2.394643,-1.248646, + 0.383941,-0.196382,0.902232,4.197516,2.349135,-1.253043, + 0.482381,-0.398126,0.780259,4.148927,2.388726,-1.376879, + 0.383941,-0.196382,0.902232,4.197516,2.349135,-1.253043, + 0.45552,-0.330523,0.826593,4.149438,2.34055,-1.353693, + 0.383941,-0.196382,0.902232,4.197516,2.349135,-1.253043, + 0.488174,-0.280956,0.826287,4.199317,2.304652,-1.17454, + 0.331391,0.08899,0.939287,4.169404,2.306276,-1.284031, + 0.383941,-0.196382,0.902232,4.197516,2.349135,-1.253043, + 0.331391,0.08899,0.939287,4.169404,2.306276,-1.284031, + 0.45552,-0.330523,0.826593,4.149438,2.34055,-1.353693, + 0.531574,-0.288506,0.796362,4.274886,2.22003,-0.679075, + -0.091679,0.768658,-0.633056,4.296769,2.260422,-0.528796, + -0.203969,0.261593,0.94338,4.314791,2.142163,-0.54065, + 0.531574,-0.288506,0.796362,4.274886,2.22003,-0.679075, + -0.203969,0.261593,0.94338,4.314791,2.142163,-0.54065, + -0.175197,0.22468,0.958553,4.26732,2.121987,-0.61494, + -0.023695,0.006701,0.999697,4.38099,2.207701,-0.839016, + 0.531574,-0.288506,0.796362,4.274886,2.22003,-0.679075, + -0.175197,0.22468,0.958553,4.26732,2.121987,-0.61494, + -0.023695,0.006701,0.999697,4.38099,2.207701,-0.839016, + -0.175197,0.22468,0.958553,4.26732,2.121987,-0.61494, + -0.128537,0.152973,0.979835,4.354411,2.102985,-0.80258, + -0.963659,-0.230665,-0.134738,4.212974,2.303184,-0.587113, + -0.091679,0.768658,-0.633056,4.296769,2.260422,-0.528796, + -0.990956,-0.062739,-0.118613,4.212058,2.27945,-0.625927, + -0.990956,-0.062739,-0.118613,4.212058,2.27945,-0.625927, + -0.091679,0.768658,-0.633056,4.296769,2.260422,-0.528796, + -0.938303,-0.3372,-0.076703,4.229332,2.274522,-0.672749, + -0.938303,-0.3372,-0.076703,4.229332,2.274522,-0.672749, + -0.091679,0.768658,-0.633056,4.296769,2.260422,-0.528796, + 0.531574,-0.288506,0.796362,4.274886,2.22003,-0.679075, + -0.841909,-0.49598,-0.212588,4.273005,2.310529,-0.762172, + -0.938303,-0.3372,-0.076703,4.229332,2.274522,-0.672749, + 0.531574,-0.288506,0.796362,4.274886,2.22003,-0.679075, + -0.841909,-0.49598,-0.212588,4.273005,2.310529,-0.762172, + 0.531574,-0.288506,0.796362,4.274886,2.22003,-0.679075, + -0.571598,0.654164,0.495323,4.307092,2.367482,-0.877202, + -0.175197,0.22468,0.958553,4.26732,2.121987,-0.61494, + -0.203969,0.261593,0.94338,4.314791,2.142163,-0.54065, + 0.224429,0.165293,0.96037,4.305411,2.059245,-0.539407, + -0.571598,0.654164,0.495323,4.307092,2.367482,-0.877202, + 0.531574,-0.288506,0.796362,4.274886,2.22003,-0.679075, + -0.023695,0.006701,0.999697,4.38099,2.207701,-0.839016, + -0.571598,0.654164,0.495323,4.307092,2.367482,-0.877202, + -0.023695,0.006701,0.999697,4.38099,2.207701,-0.839016, + 0.144017,-0.141696,0.979378,4.369751,2.298204,-0.921894, + 0.325831,-0.277459,0.903798,4.303193,2.347123,-1.044413, + -0.601466,0.441167,0.666041,4.266263,2.421651,-1.054799, + -0.571598,0.654164,0.495323,4.307092,2.367482,-0.877202, + 0.325831,-0.277459,0.903798,4.303193,2.347123,-1.044413, + -0.571598,0.654164,0.495323,4.307092,2.367482,-0.877202, + 0.144017,-0.141696,0.979378,4.369751,2.298204,-0.921894, + 0.441787,-0.375177,0.814903,4.245861,2.375093,-1.141312, + -0.434016,0.136262,0.890541,4.228523,2.435029,-1.098575, + -0.601466,0.441167,0.666041,4.266263,2.421651,-1.054799, + 0.441787,-0.375177,0.814903,4.245861,2.375093,-1.141312, + -0.601466,0.441167,0.666041,4.266263,2.421651,-1.054799, + 0.325831,-0.277459,0.903798,4.303193,2.347123,-1.044413, + 0.441787,-0.375177,0.814903,4.245861,2.375093,-1.141312, + 0.483908,-0.405185,0.775667,4.197644,2.394643,-1.248646, + -0.195132,0.128745,0.97229,4.17047,2.458441,-1.241846, + 0.441787,-0.375177,0.814903,4.245861,2.375093,-1.141312, + -0.195132,0.128745,0.97229,4.17047,2.458441,-1.241846, + -0.434016,0.136262,0.890541,4.228523,2.435029,-1.098575, + 0.383941,-0.196382,0.902232,4.197516,2.349135,-1.253043, + 0.483908,-0.405185,0.775667,4.197644,2.394643,-1.248646, + 0.441787,-0.375177,0.814903,4.245861,2.375093,-1.141312, + 0.383941,-0.196382,0.902232,4.197516,2.349135,-1.253043, + 0.441787,-0.375177,0.814903,4.245861,2.375093,-1.141312, + 0.226651,-0.023678,0.973688,4.218457,2.356834,-1.142444, + 0.226651,-0.023678,0.973688,4.218457,2.356834,-1.142444, + 0.441787,-0.375177,0.814903,4.245861,2.375093,-1.141312, + 0.325831,-0.277459,0.903798,4.303193,2.347123,-1.044413, + 0.226651,-0.023678,0.973688,4.218457,2.356834,-1.142444, + 0.325831,-0.277459,0.903798,4.303193,2.347123,-1.044413, + 0.065337,0.07376,0.995133,4.275405,2.319905,-1.0464, + 0.325831,-0.277459,0.903798,4.303193,2.347123,-1.044413, + 0.144017,-0.141696,0.979378,4.369751,2.298204,-0.921894, + -0.027323,0.180938,0.983115,4.296538,2.243779,-0.925459, + 0.325831,-0.277459,0.903798,4.303193,2.347123,-1.044413, + -0.027323,0.180938,0.983115,4.296538,2.243779,-0.925459, + 0.065337,0.07376,0.995133,4.275405,2.319905,-1.0464, + 0.144017,-0.141696,0.979378,4.369751,2.298204,-0.921894, + -0.023695,0.006701,0.999697,4.38099,2.207701,-0.839016, + -0.078774,0.27578,0.957987,4.289048,2.172969,-0.858693, + 0.144017,-0.141696,0.979378,4.369751,2.298204,-0.921894, + -0.078774,0.27578,0.957987,4.289048,2.172969,-0.858693, + -0.027323,0.180938,0.983115,4.296538,2.243779,-0.925459, + 0.488174,-0.280956,0.826287,4.199317,2.304652,-1.17454, + 0.383941,-0.196382,0.902232,4.197516,2.349135,-1.253043, + 0.226651,-0.023678,0.973688,4.218457,2.356834,-1.142444, + 0.488174,-0.280956,0.826287,4.199317,2.304652,-1.17454, + 0.226651,-0.023678,0.973688,4.218457,2.356834,-1.142444, + 0.065337,0.07376,0.995133,4.275405,2.319905,-1.0464, + 0.488174,-0.280956,0.826287,4.199317,2.304652,-1.17454, + 0.065337,0.07376,0.995133,4.275405,2.319905,-1.0464, + 0.769657,-0.480833,0.420033,4.211815,2.28249,-1.039137, + -0.128537,0.152973,0.979835,4.354411,2.102985,-0.80258, + -0.175197,0.22468,0.958553,4.26732,2.121987,-0.61494, + 0.224429,0.165293,0.96037,4.305411,2.059245,-0.539407, + -0.128537,0.152973,0.979835,4.354411,2.102985,-0.80258, + 0.224429,0.165293,0.96037,4.305411,2.059245,-0.539407, + -0.080985,0.883253,0.461851,4.278045,1.97666,-0.537351, + -0.078774,0.27578,0.957987,4.289048,2.172969,-0.858693, + -0.023695,0.006701,0.999697,4.38099,2.207701,-0.839016, + -0.128537,0.152973,0.979835,4.354411,2.102985,-0.80258, + -0.078774,0.27578,0.957987,4.289048,2.172969,-0.858693, + -0.128537,0.152973,0.979835,4.354411,2.102985,-0.80258, + -0.095989,0.297871,0.949768,4.290375,2.112337,-0.80019, + 0.769657,-0.480833,0.420033,4.211815,2.28249,-1.039137, + 0.065337,0.07376,0.995133,4.275405,2.319905,-1.0464, + -0.027323,0.180938,0.983115,4.296538,2.243779,-0.925459, + 0.769657,-0.480833,0.420033,4.211815,2.28249,-1.039137, + -0.027323,0.180938,0.983115,4.296538,2.243779,-0.925459, + 0.040193,0.650965,0.758043,4.222795,2.228178,-0.952752, + 0.040193,0.650965,0.758043,4.222795,2.228178,-0.952752, + -0.027323,0.180938,0.983115,4.296538,2.243779,-0.925459, + -0.078774,0.27578,0.957987,4.289048,2.172969,-0.858693, + 0.040193,0.650965,0.758043,4.222795,2.228178,-0.952752, + -0.078774,0.27578,0.957987,4.289048,2.172969,-0.858693, + 0.177367,0.480226,0.859025,4.197609,2.164063,-0.857433, + 0.177367,0.480226,0.859025,4.197609,2.164063,-0.857433, + -0.078774,0.27578,0.957987,4.289048,2.172969,-0.858693, + -0.095989,0.297871,0.949768,4.290375,2.112337,-0.80019, + 0.177367,0.480226,0.859025,4.197609,2.164063,-0.857433, + -0.095989,0.297871,0.949768,4.290375,2.112337,-0.80019, + 0.288711,0.386915,0.875753,4.153175,2.084823,-0.799668, + 0.41428,0.318289,0.85268,4.15109,2.102939,-0.889759, + 0.177367,0.480226,0.859025,4.197609,2.164063,-0.857433, + 0.288711,0.386915,0.875753,4.153175,2.084823,-0.799668, + 0.519338,0.264458,0.812619,4.148865,2.148829,-0.986567, + 0.040193,0.650965,0.758043,4.222795,2.228178,-0.952752, + 0.177367,0.480226,0.859025,4.197609,2.164063,-0.857433, + 0.519338,0.264458,0.812619,4.148865,2.148829,-0.986567, + 0.177367,0.480226,0.859025,4.197609,2.164063,-0.857433, + 0.41428,0.318289,0.85268,4.15109,2.102939,-0.889759, + 0.486425,0.192908,0.852161,4.154566,2.19048,-1.129552, + 0.769657,-0.480833,0.420033,4.211815,2.28249,-1.039137, + 0.040193,0.650965,0.758043,4.222795,2.228178,-0.952752, + 0.486425,0.192908,0.852161,4.154566,2.19048,-1.129552, + 0.040193,0.650965,0.758043,4.222795,2.228178,-0.952752, + 0.519338,0.264458,0.812619,4.148865,2.148829,-0.986567, + 0.449624,0.075438,0.890027,4.152557,2.235471,-1.217046, + 0.488174,-0.280956,0.826287,4.199317,2.304652,-1.17454, + 0.769657,-0.480833,0.420033,4.211815,2.28249,-1.039137, + 0.449624,0.075438,0.890027,4.152557,2.235471,-1.217046, + 0.769657,-0.480833,0.420033,4.211815,2.28249,-1.039137, + 0.486425,0.192908,0.852161,4.154566,2.19048,-1.129552, + 0.474213,-0.311965,0.823286,4.141759,2.279958,-1.29534, + 0.331391,0.08899,0.939287,4.169404,2.306276,-1.284031, + 0.488174,-0.280956,0.826287,4.199317,2.304652,-1.17454, + 0.474213,-0.311965,0.823286,4.141759,2.279958,-1.29534, + 0.488174,-0.280956,0.826287,4.199317,2.304652,-1.17454, + 0.449624,0.075438,0.890027,4.152557,2.235471,-1.217046, + 0.533629,-0.162705,0.82992,4.131949,2.050757,-0.921856, + 0.41428,0.318289,0.85268,4.15109,2.102939,-0.889759, + 0.288711,0.386915,0.875753,4.153175,2.084823,-0.799668, + 0.547549,-0.279581,0.788686,4.119993,2.063095,-1.049178, + 0.519338,0.264458,0.812619,4.148865,2.148829,-0.986567, + 0.41428,0.318289,0.85268,4.15109,2.102939,-0.889759, + 0.547549,-0.279581,0.788686,4.119993,2.063095,-1.049178, + 0.41428,0.318289,0.85268,4.15109,2.102939,-0.889759, + 0.533629,-0.162705,0.82992,4.131949,2.050757,-0.921856, + 0.598679,-0.200355,0.775527,4.12616,2.12093,-1.17252, + 0.486425,0.192908,0.852161,4.154566,2.19048,-1.129552, + 0.519338,0.264458,0.812619,4.148865,2.148829,-0.986567, + 0.598679,-0.200355,0.775527,4.12616,2.12093,-1.17252, + 0.519338,0.264458,0.812619,4.148865,2.148829,-0.986567, + 0.547549,-0.279581,0.788686,4.119993,2.063095,-1.049178, + 0.561098,-0.272385,0.78165,4.133175,2.175231,-1.259323, + 0.449624,0.075438,0.890027,4.152557,2.235471,-1.217046, + 0.486425,0.192908,0.852161,4.154566,2.19048,-1.129552, + 0.561098,-0.272385,0.78165,4.133175,2.175231,-1.259323, + 0.486425,0.192908,0.852161,4.154566,2.19048,-1.129552, + 0.598679,-0.200355,0.775527,4.12616,2.12093,-1.17252, + 0.561098,-0.272385,0.78165,4.133175,2.175231,-1.259323, + 0.474213,-0.311965,0.823286,4.141759,2.279958,-1.29534, + 0.449624,0.075438,0.890027,4.152557,2.235471,-1.217046, + 0.760747,-0.509474,0.40212,4.137657,1.944837,-1.061024, + 0.547549,-0.279581,0.788686,4.119993,2.063095,-1.049178, + 0.533629,-0.162705,0.82992,4.131949,2.050757,-0.921856, + 0.760747,-0.509474,0.40212,4.137657,1.944837,-1.061024, + 0.533629,-0.162705,0.82992,4.131949,2.050757,-0.921856, + 0.5205,-0.336657,0.784692,4.159229,1.949902,-0.923197, + -0.16423,0.819635,0.548842,4.143794,2.01372,-1.201386, + 0.598679,-0.200355,0.775527,4.12616,2.12093,-1.17252, + 0.547549,-0.279581,0.788686,4.119993,2.063095,-1.049178, + -0.16423,0.819635,0.548842,4.143794,2.01372,-1.201386, + 0.547549,-0.279581,0.788686,4.119993,2.063095,-1.049178, + 0.760747,-0.509474,0.40212,4.137657,1.944837,-1.061024, + -0.043323,0.541029,0.839887,4.12329,2.086854,-1.295135, + 0.561098,-0.272385,0.78165,4.133175,2.175231,-1.259323, + 0.598679,-0.200355,0.775527,4.12616,2.12093,-1.17252, + -0.043323,0.541029,0.839887,4.12329,2.086854,-1.295135, + 0.598679,-0.200355,0.775527,4.12616,2.12093,-1.17252, + -0.16423,0.819635,0.548842,4.143794,2.01372,-1.201386, + 0.04432,0.372862,0.926827,4.11268,2.195089,-1.366908, + 0.474213,-0.311965,0.823286,4.141759,2.279958,-1.29534, + 0.561098,-0.272385,0.78165,4.133175,2.175231,-1.259323, + 0.04432,0.372862,0.926827,4.11268,2.195089,-1.366908, + 0.561098,-0.272385,0.78165,4.133175,2.175231,-1.259323, + -0.043323,0.541029,0.839887,4.12329,2.086854,-1.295135, + 0.098376,0.32868,0.939304,4.111934,2.234814,-1.399949, + 0.445439,-0.182623,0.876489,4.140097,2.295949,-1.367196, + 0.474213,-0.311965,0.823286,4.141759,2.279958,-1.29534, + 0.098376,0.32868,0.939304,4.111934,2.234814,-1.399949, + 0.474213,-0.311965,0.823286,4.141759,2.279958,-1.29534, + 0.04432,0.372862,0.926827,4.11268,2.195089,-1.366908, + 0.098376,0.32868,0.939304,4.111934,2.234814,-1.399949, + 0.489736,-0.346185,0.800197,4.129926,2.30877,-1.402259, + 0.445439,-0.182623,0.876489,4.140097,2.295949,-1.367196, + -0.080985,0.883253,0.461851,4.278045,1.97666,-0.537351, + 0.525316,0.261331,0.809784,4.304562,1.906537,-0.572242, + 0.752227,-0.484776,0.446258,4.232341,1.903079,-0.534362, + -0.051423,0.948155,0.313619,4.240116,1.770049,-0.583946, + 0.752227,-0.484776,0.446258,4.232341,1.903079,-0.534362, + 0.525316,0.261331,0.809784,4.304562,1.906537,-0.572242, + -0.051423,0.948155,0.313619,4.240116,1.770049,-0.583946, + 0.525316,0.261331,0.809784,4.304562,1.906537,-0.572242, + 0.204286,0.745568,0.634347,4.303615,1.799914,-0.610388, + 0.525316,0.261331,0.809784,4.304562,1.906537,-0.572242, + -0.080985,0.883253,0.461851,4.278045,1.97666,-0.537351, + 0.224429,0.165293,0.96037,4.305411,2.059245,-0.539407, + 0.525316,0.261331,0.809784,4.304562,1.906537,-0.572242, + 0.224429,0.165293,0.96037,4.305411,2.059245,-0.539407, + 0.615047,0.769185,-0.17341,4.377095,1.871713,-0.595743, + 0.615047,0.769185,-0.17341,4.377095,1.871713,-0.595743, + 0.224429,0.165293,0.96037,4.305411,2.059245,-0.539407, + 0.361081,-0.056526,-0.93082,4.43302,2.024714,-0.563794, + 0.615047,0.769185,-0.17341,4.377095,1.871713,-0.595743, + 0.361081,-0.056526,-0.93082,4.43302,2.024714,-0.563794, + 0.36359,0.089346,-0.927264,4.43261,1.878873,-0.577888, + 0.969409,0.243853,-0.027951,4.148883,1.759918,-0.573765, + -0.385487,0.478576,0.788901,4.094112,1.889281,-0.578435, + 0.752227,-0.484776,0.446258,4.232341,1.903079,-0.534362, + 0.969409,0.243853,-0.027951,4.148883,1.759918,-0.573765, + 0.752227,-0.484776,0.446258,4.232341,1.903079,-0.534362, + -0.051423,0.948155,0.313619,4.240116,1.770049,-0.583946, + -0.095989,0.297871,0.949768,4.290375,2.112337,-0.80019, + -0.128537,0.152973,0.979835,4.354411,2.102985,-0.80258, + -0.158888,0.47696,0.864444,4.281287,2.055751,-0.787, + -0.128537,0.152973,0.979835,4.354411,2.102985,-0.80258, + -0.317114,0.866865,0.384686,4.354941,2.064161,-0.778851, + -0.158888,0.47696,0.864444,4.281287,2.055751,-0.787, + -0.158888,0.47696,0.864444,4.281287,2.055751,-0.787, + -0.317114,0.866865,0.384686,4.354941,2.064161,-0.778851, + -0.273708,0.760234,0.589175,4.245225,2.008532,-0.772641, + 0.288711,0.386915,0.875753,4.153175,2.084823,-0.799668, + -0.095989,0.297871,0.949768,4.290375,2.112337,-0.80019, + -0.158888,0.47696,0.864444,4.281287,2.055751,-0.787, + 0.533629,-0.162705,0.82992,4.131949,2.050757,-0.921856, + 0.288711,0.386915,0.875753,4.153175,2.084823,-0.799668, + -0.158888,0.47696,0.864444,4.281287,2.055751,-0.787, + 0.533629,-0.162705,0.82992,4.131949,2.050757,-0.921856, + -0.158888,0.47696,0.864444,4.281287,2.055751,-0.787, + 0.5205,-0.336657,0.784692,4.159229,1.949902,-0.923197, + -0.317114,0.866865,0.384686,4.354941,2.064161,-0.778851, + -0.128537,0.152973,0.979835,4.354411,2.102985,-0.80258, + -0.080985,0.883253,0.461851,4.278045,1.97666,-0.537351, + -0.317114,0.866865,0.384686,4.354941,2.064161,-0.778851, + -0.080985,0.883253,0.461851,4.278045,1.97666,-0.537351, + 0.752227,-0.484776,0.446258,4.232341,1.903079,-0.534362, + -0.317114,0.866865,0.384686,4.354941,2.064161,-0.778851, + 0.752227,-0.484776,0.446258,4.232341,1.903079,-0.534362, + -0.273708,0.760234,0.589175,4.245225,2.008532,-0.772641, + 0.5205,-0.336657,0.784692,4.159229,1.949902,-0.923197, + -0.158888,0.47696,0.864444,4.281287,2.055751,-0.787, + -0.273708,0.760234,0.589175,4.245225,2.008532,-0.772641, + -0.026148,0.006311,-0.999638,5.998088,1.231874,-0.107334, + -0.2127,-0.171223,-0.961999,5.961686,1.110978,-0.090324, + 0.111896,-0.605741,-0.787755,5.950684,1.082725,-0.175648, + -0.026148,0.006311,-0.999638,5.998088,1.231874,-0.107334, + 0.111896,-0.605741,-0.787755,5.950684,1.082725,-0.175648, + 0.223936,-0.919046,-0.324355,5.959462,1.157227,-0.187097, + 0.173726,-0.983856,0.042973,5.672385,1.007694,-0.341778, + 0.231006,-0.859096,-0.456717,5.681086,1.054964,-0.35586, + 0.010578,-0.902776,-0.429981,5.763952,1.062109,-0.338641, + 0.173726,-0.983856,0.042973,5.672385,1.007694,-0.341778, + 0.010578,-0.902776,-0.429981,5.763952,1.062109,-0.338641, + 0.396941,-0.593504,-0.700137,5.755282,1.004149,-0.307505, + 0.707709,-0.687035,-0.164711,5.647186,1.394606,-0.257833, + 0.798302,-0.559383,0.22317,5.685194,1.452202,-0.188749, + 0.831976,-0.511655,0.214534,5.730427,1.435668,-0.209848, + 0.707709,-0.687035,-0.164711,5.647186,1.394606,-0.257833, + 0.831976,-0.511655,0.214534,5.730427,1.435668,-0.209848, + 0.744254,-0.654161,-0.134758,5.710154,1.360653,-0.290072, + 0.043397,0.435461,-0.899161,5.250485,1.123029,-0.385234, + 0.123418,-0.784469,-0.607763,5.241466,1.040469,-0.383965, + 0.274481,0.961015,-0.033322,5.011084,1.06677,-0.458562, + 0.043397,0.435461,-0.899161,5.250485,1.123029,-0.385234, + 0.274481,0.961015,-0.033322,5.011084,1.06677,-0.458562, + 0.012421,0.392537,-0.919653,4.991713,1.163096,-0.504149, + 0.381066,0.919021,-0.100938,4.567896,1.149805,-0.642484, + 0.481644,0.842268,0.242081,4.449011,1.260929,-0.647431, + 0.184871,0.227139,-0.956154,4.522247,1.398278,-0.644892, + 0.381066,0.919021,-0.100938,4.567896,1.149805,-0.642484, + 0.184871,0.227139,-0.956154,4.522247,1.398278,-0.644892, + -0.026366,0.234118,-0.971851,4.641547,1.285422,-0.622034, + -0.013461,-0.014478,-0.999805,4.697024,1.862575,-0.604048, + 0.667258,0.181112,-0.722471,4.688114,2.046378,-0.604518, + 0.856604,0.474873,-0.201803,4.728963,2.036146,-0.614307, + -0.013461,-0.014478,-0.999805,4.697024,1.862575,-0.604048, + 0.856604,0.474873,-0.201803,4.728963,2.036146,-0.614307, + 0.827569,0.284292,-0.484054,4.742358,1.882232,-0.62165, + 0.264979,0.116702,-0.957166,4.842883,2.021333,-0.638025, + 0.721999,0.398917,-0.565316,4.861611,2.001639,-0.621913, + 0.544735,0.449335,-0.708069,4.824747,1.946835,-0.626358, + 0.264979,0.116702,-0.957166,4.842883,2.021333,-0.638025, + 0.544735,0.449335,-0.708069,4.824747,1.946835,-0.626358, + 0.269343,0.329305,-0.904993,4.760921,1.881357,-0.61312, + 0.269343,0.329305,-0.904993,4.760921,1.881357,-0.61312, + 0.397989,0.4494,-0.799778,4.861618,1.854067,-0.618095, + 0.708269,-0.122724,-0.695193,4.852582,1.816115,-0.603105, + 0.711192,0.127662,-0.69131,4.935561,2.016016,-0.5857, + 0.312982,-0.015529,-0.949632,4.93588,2.051665,-0.572853, + 0.470021,0.182979,-0.863481,4.991746,2.009819,-0.523206, + 0.711192,0.127662,-0.69131,4.935561,2.016016,-0.5857, + 0.470021,0.182979,-0.863481,4.991746,2.009819,-0.523206, + 0.872792,-0.115436,-0.474246,4.973133,1.992779,-0.533466, + 0.699393,0.056752,-0.71248,4.751519,2.039658,-0.634134, + 0.813293,0.022433,-0.581422,4.788476,2.028047,-0.608619, + 0.269343,0.329305,-0.904993,4.760921,1.881357,-0.61312, + 0.108828,-0.182644,-0.977137,4.982364,1.8733,-0.53619, + 0.412833,-0.156453,-0.897269,5.001903,1.914398,-0.486724, + 0.431713,0.22912,-0.872427,5.01143,1.875569,-0.463205, + 0.108828,-0.182644,-0.977137,4.982364,1.8733,-0.53619, + 0.431713,0.22912,-0.872427,5.01143,1.875569,-0.463205, + 0.661825,0.260115,-0.703085,4.991709,1.844295,-0.520761, + 0.470021,0.182979,-0.863481,4.991746,2.009819,-0.523206, + 0.431713,0.22912,-0.872427,5.01143,1.875569,-0.463205, + 0.412833,-0.156453,-0.897269,5.001903,1.914398,-0.486724, + 0.910294,-0.144636,-0.387873,4.881574,2.094571,-0.539949, + 0.588787,-0.248293,-0.769207,4.918466,2.084725,-0.532713, + 0.312982,-0.015529,-0.949632,4.93588,2.051665,-0.572853, + 0.719268,0.159441,-0.676189,4.636582,2.263383,-0.471997, + -0.114527,0.103064,-0.988059,4.739441,2.299169,-0.369987, + 0.45571,-0.00339,-0.890122,4.837331,2.235678,-0.479332, + 0.719268,0.159441,-0.676189,4.636582,2.263383,-0.471997, + 0.45571,-0.00339,-0.890122,4.837331,2.235678,-0.479332, + 0.766773,0.253147,-0.589894,4.74405,2.179337,-0.556057, + 0.781868,0.537364,-0.316105,5.057495,2.002751,-0.451974, + 0.332526,0.910491,-0.245832,5.067202,2.027704,-0.422291, + 0.077536,0.770695,-0.632469,5.095375,1.961238,-0.401516, + 0.781868,0.537364,-0.316105,5.057495,2.002751,-0.451974, + 0.077536,0.770695,-0.632469,5.095375,1.961238,-0.401516, + 0.89264,0.34991,-0.284178,5.075994,1.900999,-0.443793, + 0.07924,-0.231863,0.969516,4.082988,2.175805,-1.45093, + 0.020519,-0.282941,0.958918,4.046673,2.341349,-1.45253, + 0.702554,-0.570096,0.42592,4.101726,2.312318,-1.438163, + 0.07924,-0.231863,0.969516,4.082988,2.175805,-1.45093, + 0.702554,-0.570096,0.42592,4.101726,2.312318,-1.438163, + 0.489736,-0.346185,0.800197,4.129926,2.30877,-1.402259, + 0.07924,-0.231863,0.969516,4.082988,2.175805,-1.45093, + 0.489736,-0.346185,0.800197,4.129926,2.30877,-1.402259, + 0.098376,0.32868,0.939304,4.111934,2.234814,-1.399949, + 0.5205,-0.336657,0.784692,4.159229,1.949902,-0.923197, + -0.273708,0.760234,0.589175,4.245225,2.008532,-0.772641, + -0.385487,0.478576,0.788901,4.094112,1.889281,-0.578435, + 0.5205,-0.336657,0.784692,4.159229,1.949902,-0.923197, + -0.385487,0.478576,0.788901,4.094112,1.889281,-0.578435, + -0.273816,0.228927,0.93414,4.150297,1.820575,-0.917046, + 0.760747,-0.509474,0.40212,4.137657,1.944837,-1.061024, + 0.5205,-0.336657,0.784692,4.159229,1.949902,-0.923197, + -0.273816,0.228927,0.93414,4.150297,1.820575,-0.917046, + 0.760747,-0.509474,0.40212,4.137657,1.944837,-1.061024, + -0.273816,0.228927,0.93414,4.150297,1.820575,-0.917046, + -0.21777,0.161093,0.962614,4.127903,1.828359,-1.090512, + -0.16423,0.819635,0.548842,4.143794,2.01372,-1.201386, + 0.760747,-0.509474,0.40212,4.137657,1.944837,-1.061024, + -0.21777,0.161093,0.962614,4.127903,1.828359,-1.090512, + -0.16423,0.819635,0.548842,4.143794,2.01372,-1.201386, + -0.21777,0.161093,0.962614,4.127903,1.828359,-1.090512, + -0.178707,0.132414,0.974951,4.152166,1.868775,-1.225002, + -0.043323,0.541029,0.839887,4.12329,2.086854,-1.295135, + -0.16423,0.819635,0.548842,4.143794,2.01372,-1.201386, + -0.178707,0.132414,0.974951,4.152166,1.868775,-1.225002, + -0.043323,0.541029,0.839887,4.12329,2.086854,-1.295135, + -0.178707,0.132414,0.974951,4.152166,1.868775,-1.225002, + -0.081635,-0.03459,0.996062,4.103303,2.038565,-1.363737, + 0.04432,0.372862,0.926827,4.11268,2.195089,-1.366908, + -0.043323,0.541029,0.839887,4.12329,2.086854,-1.295135, + -0.081635,-0.03459,0.996062,4.103303,2.038565,-1.363737, + 0.04432,0.372862,0.926827,4.11268,2.195089,-1.366908, + -0.081635,-0.03459,0.996062,4.103303,2.038565,-1.363737, + 0.07924,-0.231863,0.969516,4.082988,2.175805,-1.45093, + 0.098376,0.32868,0.939304,4.111934,2.234814,-1.399949, + 0.04432,0.372862,0.926827,4.11268,2.195089,-1.366908, + 0.07924,-0.231863,0.969516,4.082988,2.175805,-1.45093, + -0.447812,0.698934,0.557634,4.059885,1.86046,-0.470087, + -0.385487,0.478576,0.788901,4.094112,1.889281,-0.578435, + 0.969409,0.243853,-0.027951,4.148883,1.759918,-0.573765, + -0.447812,0.698934,0.557634,4.059885,1.86046,-0.470087, + 0.969409,0.243853,-0.027951,4.148883,1.759918,-0.573765, + 0.971427,0.04566,0.232906,4.076852,1.746601,-0.527436, + -0.926486,-0.356041,-0.121897,4.126565,0.642027,0, + -0.086812,-0.050981,-0.994919,4.120842,0.627141,-0.185461, + 0.448666,0.893201,-0.029856,4.359048,0.700414,-0.166651, + -0.926486,-0.356041,-0.121897,4.126565,0.642027,0, + 0.448666,0.893201,-0.029856,4.359048,0.700414,-0.166651, + 0.000801,-1,-0.000539,4.380854,0.704574,-0.00013, + -0.564871,0.754993,-0.333026,3.881998,1.764428,-0.476337, + -0.447812,0.698934,0.557634,4.059885,1.86046,-0.470087, + 0.971427,0.04566,0.232906,4.076852,1.746601,-0.527436, + -0.571598,0.654164,-0.495323,3.886058,1.550141,-0.50483, + -0.564871,0.754993,-0.333026,3.881998,1.764428,-0.476337, + 0.971427,0.04566,0.232906,4.076852,1.746601,-0.527436, + -0.571598,0.654164,-0.495323,3.886058,1.550141,-0.50483, + 0.971427,0.04566,0.232906,4.076852,1.746601,-0.527436, + 0.811896,0.498733,-0.303464,4.067576,1.572668,-0.534997, + -0.601466,0.441167,-0.666041,3.98851,1.297806,-0.539537, + -0.571598,0.654164,-0.495323,3.886058,1.550141,-0.50483, + 0.811896,0.498733,-0.303464,4.067576,1.572668,-0.534997, + -0.601466,0.441167,-0.666041,3.98851,1.297806,-0.539537, + 0.811896,0.498733,-0.303464,4.067576,1.572668,-0.534997, + 0.800967,0.453078,0.391371,4.085564,1.288885,-0.544406, + -0.434016,0.136262,-0.890541,4.041657,1.039756,-0.496922, + -0.601466,0.441167,-0.666041,3.98851,1.297806,-0.539537, + 0.800967,0.453078,0.391371,4.085564,1.288885,-0.544406, + -0.434016,0.136262,-0.890541,4.041657,1.039756,-0.496922, + 0.800967,0.453078,0.391371,4.085564,1.288885,-0.544406, + 0.04154,0.947538,0.316932,4.141189,1.008775,-0.499342, + -0.195132,0.128745,-0.97229,4.068249,0.798926,-0.400813, + -0.434016,0.136262,-0.890541,4.041657,1.039756,-0.496922, + 0.04154,0.947538,0.316932,4.141189,1.008775,-0.499342, + -0.195132,0.128745,-0.97229,4.068249,0.798926,-0.400813, + 0.04154,0.947538,0.316932,4.141189,1.008775,-0.499342, + -0.051101,0.977083,0.206633,4.216374,0.852328,-0.405873, + -0.172151,0.101796,-0.979797,4.105198,0.672581,-0.300001, + -0.195132,0.128745,-0.97229,4.068249,0.798926,-0.400813, + -0.051101,0.977083,0.206633,4.216374,0.852328,-0.405873, + -0.172151,0.101796,-0.979797,4.105198,0.672581,-0.300001, + -0.051101,0.977083,0.206633,4.216374,0.852328,-0.405873, + 0.731768,0.675964,-0.087106,4.319799,0.731007,-0.291212, + -0.086812,-0.050981,-0.994919,4.120842,0.627141,-0.185461, + -0.172151,0.101796,-0.979797,4.105198,0.672581,-0.300001, + 0.731768,0.675964,-0.087106,4.319799,0.731007,-0.291212, + -0.086812,-0.050981,-0.994919,4.120842,0.627141,-0.185461, + 0.731768,0.675964,-0.087106,4.319799,0.731007,-0.291212, + 0.448666,0.893201,-0.029856,4.359048,0.700414,-0.166651, + -0.777939,0.62834,-0.000226,3.745669,2.266001,-0.24193, + -0.210883,0.942026,0.260987,3.828001,2.35254,-0.233341, + -0.502349,0.838172,0.212398,3.870548,2.292106,-0.368964, + -0.777939,0.62834,-0.000226,3.745669,2.266001,-0.24193, + -0.502349,0.838172,0.212398,3.870548,2.292106,-0.368964, + -0.698288,0.715816,-0.000608,3.758215,2.206683,-0.323051, + -0.451389,0.892327,-0.00019,3.727093,2.308406,-0.150049, + 0.431966,-0.771434,-0.46722,3.71636,2.343387,0, + 0.622247,0.782821,-0.000247,3.787342,2.396113,-0.001159, + -0.451389,0.892327,-0.00019,3.727093,2.308406,-0.150049, + 0.622247,0.782821,-0.000247,3.787342,2.396113,-0.001159, + -0.210883,0.942026,0.260987,3.828001,2.35254,-0.233341, + -0.777939,0.62834,-0.000226,3.745669,2.266001,-0.24193, + -0.451389,0.892327,-0.00019,3.727093,2.308406,-0.150049, + -0.210883,0.942026,0.260987,3.828001,2.35254,-0.233341, + 0.673211,-0.580891,0.457551,3.922437,1.972461,-0.483563, + -0.447812,0.698934,0.557634,4.059885,1.86046,-0.470087, + -0.564871,0.754993,-0.333026,3.881998,1.764428,-0.476337, + 0.673211,-0.580891,0.457551,3.922437,1.972461,-0.483563, + -0.564871,0.754993,-0.333026,3.881998,1.764428,-0.476337, + -0.512639,0.858604,-0.000762,3.814876,1.968416,-0.443, + -0.768362,0.592232,0.242656,3.823349,2.141733,-0.428356, + 0.673211,-0.580891,0.457551,3.922437,1.972461,-0.483563, + -0.512639,0.858604,-0.000762,3.814876,1.968416,-0.443, + -0.768362,0.592232,0.242656,3.823349,2.141733,-0.428356, + -0.512639,0.858604,-0.000762,3.814876,1.968416,-0.443, + -0.698288,0.715816,-0.000608,3.758215,2.206683,-0.323051, + -0.502349,0.838172,0.212398,3.870548,2.292106,-0.368964, + -0.768362,0.592232,0.242656,3.823349,2.141733,-0.428356, + -0.698288,0.715816,-0.000608,3.758215,2.206683,-0.323051, + -0.273708,0.760234,0.589175,4.245225,2.008532,-0.772641, + 0.752227,-0.484776,0.446258,4.232341,1.903079,-0.534362, + -0.385487,0.478576,0.788901,4.094112,1.889281,-0.578435, + -0.483189,-0.207332,-0.850613,1.655948,-2.520927,-0.844269, + -0.176356,-0.113876,-0.977717,1.678986,-2.513137,-0.891745, + -0.246054,-0.154918,-0.956796,1.718315,-2.775468,-0.921796, + -0.483189,-0.207332,-0.850613,1.655948,-2.520927,-0.844269, + -0.246054,-0.154918,-0.956796,1.718315,-2.775468,-0.921796, + 0.21689,-0.976039,0.017487,1.700797,-2.794792,-0.82425, + -0.246054,-0.154918,-0.956796,1.718315,-2.775468,-0.921796, + -0.024032,-0.835976,0.54824,1.734568,-2.965876,-0.986396, + -0.90358,0.003167,-0.428408,1.705953,-3.006628,-0.83263, + -0.246054,-0.154918,-0.956796,1.718315,-2.775468,-0.921796, + -0.90358,0.003167,-0.428408,1.705953,-3.006628,-0.83263, + 0.21689,-0.976039,0.017487,1.700797,-2.794792,-0.82425, + -0.079302,-0.84299,-0.532051,-1.305099,-1.70846,-0.48423, + -0.176655,-0.950799,-0.254508,-1.108758,-1.770749,-0.473033, + -0.253979,-0.745808,-0.615845,-0.977375,-1.793126,-0.498747, + -0.079302,-0.84299,-0.532051,-1.305099,-1.70846,-0.48423, + -0.253979,-0.745808,-0.615845,-0.977375,-1.793126,-0.498747, + -0.040019,-0.929968,-0.365457,-0.972514,-1.822778,-0.372649, + -0.171647,-0.971664,-0.162499,-1.406693,-1.697325,-0.450399, + -0.094238,-0.851252,-0.516225,-1.397474,-1.693815,-0.570541, + -0.149005,-0.65467,-0.741084,-1.266738,-1.691944,-0.557922, + -0.171647,-0.971664,-0.162499,-1.406693,-1.697325,-0.450399, + -0.149005,-0.65467,-0.741084,-1.266738,-1.691944,-0.557922, + -0.079302,-0.84299,-0.532051,-1.305099,-1.70846,-0.48423, + 0.072535,0.997366,0,-3.392806,1.769365,0, + -0.091034,0.391629,-0.915609,-3.413372,1.871604,-0.142309, + -0.108631,-0.122719,-0.986478,-3.35851,1.810253,-0.380095, + 0.411442,-0.911436,-0.000099,-3.348274,1.767738,-0.000085, + 0.255239,-0.528231,-0.80983,-3.380836,1.819691,-0.123273, + -0.091034,0.391629,-0.915609,-3.413372,1.871604,-0.142309, + 0.411442,-0.911436,-0.000099,-3.348274,1.767738,-0.000085, + -0.091034,0.391629,-0.915609,-3.413372,1.871604,-0.142309, + 0.072535,0.997366,0,-3.392806,1.769365,0, + 0.45552,-0.330523,0.826593,4.149438,2.34055,-1.353693, + 0.489736,-0.346185,0.800197,4.129926,2.30877,-1.402259, + 0.702554,-0.570096,0.42592,4.101726,2.312318,-1.438163, + 0.45552,-0.330523,0.826593,4.149438,2.34055,-1.353693, + 0.702554,-0.570096,0.42592,4.101726,2.312318,-1.438163, + 0.482381,-0.398126,0.780259,4.148927,2.388726,-1.376879, + 0.43907,-0.579988,-0.686171,-2.811581,-1.79821,-0.712737, + 0.579344,-0.339433,0.741044,-3.008323,-1.759271,-0.655672, + 0.789099,-0.039289,0.613008,-3.066022,-1.953125,-0.719516, + 0.43907,-0.579988,-0.686171,-2.811581,-1.79821,-0.712737, + 0.789099,-0.039289,0.613008,-3.066022,-1.953125,-0.719516, + 0.982106,-0.010346,-0.188044,-2.964215,-1.978727,-0.776572, + 0.579344,-0.339433,0.741044,-3.008323,-1.759271,-0.655672, + -0.012978,-0.998326,0.056357,-3.139394,-1.687482,-0.638546, + 0.230893,-0.309688,0.922378,-3.211005,-1.850398,-0.700723, + 0.579344,-0.339433,0.741044,-3.008323,-1.759271,-0.655672, + 0.230893,-0.309688,0.922378,-3.211005,-1.850398,-0.700723, + 0.789099,-0.039289,0.613008,-3.066022,-1.953125,-0.719516, + 0.111825,0.518485,0.847743,2.407309,-0.97498,0.805091, + 0.728904,-0.519577,0.445802,2.410367,-0.777999,0.841105, + 0.09853,0.626571,0.773111,2.292449,-0.871852,0.8824, + 0.111825,0.518485,0.847743,2.407309,-0.97498,0.805091, + 0.09853,0.626571,0.773111,2.292449,-0.871852,0.8824, + 0.080812,0.697931,0.711591,2.229345,-0.992723,0.862826, + 0.163727,0.387435,0.907242,2.520417,-0.954785,0.739445, + 0.518786,-0.204527,0.830078,2.5392,-0.727778,0.750475, + 0.728904,-0.519577,0.445802,2.410367,-0.777999,0.841105, + 0.163727,0.387435,0.907242,2.520417,-0.954785,0.739445, + 0.728904,-0.519577,0.445802,2.410367,-0.777999,0.841105, + 0.111825,0.518485,0.847743,2.407309,-0.97498,0.805091, + 0.227108,0.258715,0.938876,2.637655,-0.768176,0.637039, + 0.518786,-0.204527,0.830078,2.5392,-0.727778,0.750475, + 0.163727,0.387435,0.907242,2.520417,-0.954785,0.739445, + 0.163727,0.387435,0.907242,2.520417,-0.954785,0.739445, + 0.304293,-0.024391,0.952266,2.514167,-1.077721,0.706614, + 0.263434,0.119819,0.957207,2.669281,-0.930664,0.557166, + 0.163727,0.387435,0.907242,2.520417,-0.954785,0.739445, + 0.263434,0.119819,0.957207,2.669281,-0.930664,0.557166, + 0.227108,0.258715,0.938876,2.637655,-0.768176,0.637039, + 0.111825,0.518485,0.847743,2.407309,-0.97498,0.805091, + 0.372063,-0.134052,0.918477,2.386465,-1.116066,0.761367, + 0.304293,-0.024391,0.952266,2.514167,-1.077721,0.706614, + 0.111825,0.518485,0.847743,2.407309,-0.97498,0.805091, + 0.304293,-0.024391,0.952266,2.514167,-1.077721,0.706614, + 0.163727,0.387435,0.907242,2.520417,-0.954785,0.739445, + 0.080812,0.697931,0.711591,2.229345,-0.992723,0.862826, + 0.424286,-0.254348,0.869073,2.180012,-1.130557,0.821812, + 0.372063,-0.134052,0.918477,2.386465,-1.116066,0.761367, + 0.080812,0.697931,0.711591,2.229345,-0.992723,0.862826, + 0.372063,-0.134052,0.918477,2.386465,-1.116066,0.761367, + 0.111825,0.518485,0.847743,2.407309,-0.97498,0.805091, + 0.383978,-0.566345,0.729256,2.158051,-1.209613,0.783941, + 0.420794,-0.405156,0.811653,2.354287,-1.193746,0.735189, + 0.372063,-0.134052,0.918477,2.386465,-1.116066,0.761367, + 0.383978,-0.566345,0.729256,2.158051,-1.209613,0.783941, + 0.372063,-0.134052,0.918477,2.386465,-1.116066,0.761367, + 0.424286,-0.254348,0.869073,2.180012,-1.130557,0.821812, + 0.303379,-0.73119,0.611002,2.126237,-1.330172,0.721011, + 0.335626,-0.735806,0.588171,2.318787,-1.29409,0.673863, + 0.420794,-0.405156,0.811653,2.354287,-1.193746,0.735189, + 0.303379,-0.73119,0.611002,2.126237,-1.330172,0.721011, + 0.420794,-0.405156,0.811653,2.354287,-1.193746,0.735189, + 0.383978,-0.566345,0.729256,2.158051,-1.209613,0.783941, + 0.298349,-0.828641,0.473647,2.274533,-1.433487,0.567366, + 0.335626,-0.735806,0.588171,2.318787,-1.29409,0.673863, + 0.303379,-0.73119,0.611002,2.126237,-1.330172,0.721011, + 0.029207,0.916877,0.398099,2.45706,-1.400958,0.539866, + 0.267279,-0.944479,0.191107,2.486533,-1.274971,0.627822, + 0.335626,-0.735806,0.588171,2.318787,-1.29409,0.673863, + 0.029207,0.916877,0.398099,2.45706,-1.400958,0.539866, + 0.335626,-0.735806,0.588171,2.318787,-1.29409,0.673863, + 0.298349,-0.828641,0.473647,2.274533,-1.433487,0.567366, + 0.051939,0.876473,0.478641,2.549322,-1.335209,0.535156, + 0.267279,-0.944479,0.191107,2.486533,-1.274971,0.627822, + 0.029207,0.916877,0.398099,2.45706,-1.400958,0.539866, + 0.092427,0.86666,0.490262,2.61797,-1.235597,0.520238, + 0.267279,-0.944479,0.191107,2.486533,-1.274971,0.627822, + 0.051939,0.876473,0.478641,2.549322,-1.335209,0.535156, + 0.101272,0.634315,0.766413,2.670253,-1.108365,0.544018, + 0.129186,0.757141,0.64035,2.510841,-1.158786,0.678057, + 0.267279,-0.944479,0.191107,2.486533,-1.274971,0.627822, + 0.101272,0.634315,0.766413,2.670253,-1.108365,0.544018, + 0.267279,-0.944479,0.191107,2.486533,-1.274971,0.627822, + 0.092427,0.86666,0.490262,2.61797,-1.235597,0.520238, + 0.420794,-0.405156,0.811653,2.354287,-1.193746,0.735189, + 0.335626,-0.735806,0.588171,2.318787,-1.29409,0.673863, + 0.267279,-0.944479,0.191107,2.486533,-1.274971,0.627822, + 0.420794,-0.405156,0.811653,2.354287,-1.193746,0.735189, + 0.267279,-0.944479,0.191107,2.486533,-1.274971,0.627822, + 0.129186,0.757141,0.64035,2.510841,-1.158786,0.678057, + 0.129186,0.757141,0.64035,2.510841,-1.158786,0.678057, + 0.304293,-0.024391,0.952266,2.514167,-1.077721,0.706614, + 0.372063,-0.134052,0.918477,2.386465,-1.116066,0.761367, + 0.129186,0.757141,0.64035,2.510841,-1.158786,0.678057, + 0.372063,-0.134052,0.918477,2.386465,-1.116066,0.761367, + 0.420794,-0.405156,0.811653,2.354287,-1.193746,0.735189, + 0.101272,0.634315,0.766413,2.670253,-1.108365,0.544018, + 0.263434,0.119819,0.957207,2.669281,-0.930664,0.557166, + 0.304293,-0.024391,0.952266,2.514167,-1.077721,0.706614, + 0.101272,0.634315,0.766413,2.670253,-1.108365,0.544018, + 0.304293,-0.024391,0.952266,2.514167,-1.077721,0.706614, + 0.129186,0.757141,0.64035,2.510841,-1.158786,0.678057, + 0.089104,0.59547,0.798421,2.710721,-0.830091,0.532493, + 0.227108,0.258715,0.938876,2.637655,-0.768176,0.637039, + 0.263434,0.119819,0.957207,2.669281,-0.930664,0.557166, + 0.206788,0.399922,0.892917,2.757946,-1.099958,0.471684, + 0.147941,0.53134,0.834141,2.857666,-0.930625,0.391195, + 0.101272,0.634315,0.766413,2.670253,-1.108365,0.544018, + 0.101272,0.634315,0.766413,2.670253,-1.108365,0.544018, + 0.092427,0.86666,0.490262,2.61797,-1.235597,0.520238, + 0.206788,0.399922,0.892917,2.757946,-1.099958,0.471684, + 0.092427,0.86666,0.490262,2.61797,-1.235597,0.520238, + 0.274567,0.116527,0.954481,2.803736,-1.255869,0.438328, + 0.246802,0.252523,0.935586,2.847364,-1.103812,0.402301, + 0.092427,0.86666,0.490262,2.61797,-1.235597,0.520238, + 0.246802,0.252523,0.935586,2.847364,-1.103812,0.402301, + 0.206788,0.399922,0.892917,2.757946,-1.099958,0.471684, + 0.147941,0.53134,0.834141,2.857666,-0.930625,0.391195, + 0.206788,0.399922,0.892917,2.757946,-1.099958,0.471684, + 0.246802,0.252523,0.935586,2.847364,-1.103812,0.402301, + 0.303729,-0.050718,0.951408,2.740886,-1.339225,0.463604, + 0.274567,0.116527,0.954481,2.803736,-1.255869,0.438328, + 0.092427,0.86666,0.490262,2.61797,-1.235597,0.520238, + 0.051939,0.876473,0.478641,2.549322,-1.335209,0.535156, + 0.33122,-0.270106,0.904067,2.663024,-1.440487,0.478149, + 0.303729,-0.050718,0.951408,2.740886,-1.339225,0.463604, + 0.051939,0.876473,0.478641,2.549322,-1.335209,0.535156, + 0.303729,-0.050718,0.951408,2.740886,-1.339225,0.463604, + 0.092427,0.86666,0.490262,2.61797,-1.235597,0.520238, + 0.029207,0.916877,0.398099,2.45706,-1.400958,0.539866, + 0.327725,-0.489439,0.808112,2.515314,-1.507063,0.483275, + 0.33122,-0.270106,0.904067,2.663024,-1.440487,0.478149, + 0.029207,0.916877,0.398099,2.45706,-1.400958,0.539866, + 0.33122,-0.270106,0.904067,2.663024,-1.440487,0.478149, + 0.051939,0.876473,0.478641,2.549322,-1.335209,0.535156, + 0.291858,-0.681117,0.67149,2.422296,-1.510915,0.494169, + 0.327725,-0.489439,0.808112,2.515314,-1.507063,0.483275, + 0.029207,0.916877,0.398099,2.45706,-1.400958,0.539866, + 0.298349,-0.828641,0.473647,2.274533,-1.433487,0.567366, + 0.248915,-0.807091,0.535392,2.249663,-1.492705,0.53127, + 0.291858,-0.681117,0.67149,2.422296,-1.510915,0.494169, + 0.298349,-0.828641,0.473647,2.274533,-1.433487,0.567366, + 0.291858,-0.681117,0.67149,2.422296,-1.510915,0.494169, + 0.029207,0.916877,0.398099,2.45706,-1.400958,0.539866, + 0.303379,-0.73119,0.611002,2.126237,-1.330172,0.721011, + 0.235033,-0.721825,0.650944,2.0796,-1.473377,0.654997, + 0.248915,-0.807091,0.535392,2.249663,-1.492705,0.53127, + 0.303379,-0.73119,0.611002,2.126237,-1.330172,0.721011, + 0.248915,-0.807091,0.535392,2.249663,-1.492705,0.53127, + 0.298349,-0.828641,0.473647,2.274533,-1.433487,0.567366, + 0.246802,0.252523,0.935586,2.847364,-1.103812,0.402301, + 0.213948,-0.943673,0.252405,2.928787,-1.107467,0.312054, + 0.244106,-0.79539,0.554768,2.960118,-0.941827,0.284743, + 0.246802,0.252523,0.935586,2.847364,-1.103812,0.402301, + 0.244106,-0.79539,0.554768,2.960118,-0.941827,0.284743, + 0.147941,0.53134,0.834141,2.857666,-0.930625,0.391195, + 0.274567,0.116527,0.954481,2.803736,-1.255869,0.438328, + 0.190577,-0.970681,0.146488,2.893096,-1.302168,0.332049, + 0.213948,-0.943673,0.252405,2.928787,-1.107467,0.312054, + 0.274567,0.116527,0.954481,2.803736,-1.255869,0.438328, + 0.213948,-0.943673,0.252405,2.928787,-1.107467,0.312054, + 0.246802,0.252523,0.935586,2.847364,-1.103812,0.402301, + 0.303729,-0.050718,0.951408,2.740886,-1.339225,0.463604, + 0.048754,0.934073,0.353738,2.824356,-1.407256,0.355013, + 0.190577,-0.970681,0.146488,2.893096,-1.302168,0.332049, + 0.303729,-0.050718,0.951408,2.740886,-1.339225,0.463604, + 0.190577,-0.970681,0.146488,2.893096,-1.302168,0.332049, + 0.274567,0.116527,0.954481,2.803736,-1.255869,0.438328, + 0.33122,-0.270106,0.904067,2.663024,-1.440487,0.478149, + 0.081223,0.915345,0.394394,2.721135,-1.520418,0.362378, + 0.048754,0.934073,0.353738,2.824356,-1.407256,0.355013, + 0.327725,-0.489439,0.808112,2.515314,-1.507063,0.483275, + 0.120116,0.912706,0.390565,2.545261,-1.5933,0.38631, + 0.081223,0.915345,0.394394,2.721135,-1.520418,0.362378, + 0.327725,-0.489439,0.808112,2.515314,-1.507063,0.483275, + 0.081223,0.915345,0.394394,2.721135,-1.520418,0.362378, + 0.33122,-0.270106,0.904067,2.663024,-1.440487,0.478149, + 0.291858,-0.681117,0.67149,2.422296,-1.510915,0.494169, + 0.1717,0.74071,0.649514,2.396607,-1.593239,0.389972, + 0.120116,0.912706,0.390565,2.545261,-1.5933,0.38631, + 0.291858,-0.681117,0.67149,2.422296,-1.510915,0.494169, + 0.120116,0.912706,0.390565,2.545261,-1.5933,0.38631, + 0.327725,-0.489439,0.808112,2.515314,-1.507063,0.483275, + 0.248915,-0.807091,0.535392,2.249663,-1.492705,0.53127, + 0.167704,0.495674,0.852164,2.243492,-1.584783,0.431143, + 0.1717,0.74071,0.649514,2.396607,-1.593239,0.389972, + 0.248915,-0.807091,0.535392,2.249663,-1.492705,0.53127, + 0.1717,0.74071,0.649514,2.396607,-1.593239,0.389972, + 0.291858,-0.681117,0.67149,2.422296,-1.510915,0.494169, + 0.235033,-0.721825,0.650944,2.0796,-1.473377,0.654997, + 0.140536,0.558684,0.817388,2.0482,-1.581983,0.555832, + 0.167704,0.495674,0.852164,2.243492,-1.584783,0.431143, + 0.235033,-0.721825,0.650944,2.0796,-1.473377,0.654997, + 0.167704,0.495674,0.852164,2.243492,-1.584783,0.431143, + 0.248915,-0.807091,0.535392,2.249663,-1.492705,0.53127, + 0.213948,-0.943673,0.252405,2.928787,-1.107467,0.312054, + 0.820584,-0.571526,0,2.931756,-1.129655,0, + -0.334515,0.94239,0,2.970902,-0.959664,0, + 0.213948,-0.943673,0.252405,2.928787,-1.107467,0.312054, + -0.334515,0.94239,0,2.970902,-0.959664,0, + 0.244106,-0.79539,0.554768,2.960118,-0.941827,0.284743, + 0.190577,-0.970681,0.146488,2.893096,-1.302168,0.332049, + -0.255632,0.966774,0,2.896234,-1.31956,0, + 0.820584,-0.571526,0,2.931756,-1.129655,0, + 0.190577,-0.970681,0.146488,2.893096,-1.302168,0.332049, + 0.820584,-0.571526,0,2.931756,-1.129655,0, + 0.213948,-0.943673,0.252405,2.928787,-1.107467,0.312054, + 0.048754,0.934073,0.353738,2.824356,-1.407256,0.355013, + 0.826305,-0.563222,0,2.821376,-1.431534,0, + -0.255632,0.966774,0,2.896234,-1.31956,0, + 0.048754,0.934073,0.353738,2.824356,-1.407256,0.355013, + -0.255632,0.966774,0,2.896234,-1.31956,0, + 0.190577,-0.970681,0.146488,2.893096,-1.302168,0.332049, + 0.081223,0.915345,0.394394,2.721135,-1.520418,0.362378, + -0.133012,0.991114,0,2.706963,-1.528854,0, + 0.826305,-0.563222,0,2.821376,-1.431534,0, + 0.081223,0.915345,0.394394,2.721135,-1.520418,0.362378, + 0.826305,-0.563222,0,2.821376,-1.431534,0, + 0.048754,0.934073,0.353738,2.824356,-1.407256,0.355013, + 0.120116,0.912706,0.390565,2.545261,-1.5933,0.38631, + 0.815341,-0.578981,0,2.534227,-1.617078,0, + -0.133012,0.991114,0,2.706963,-1.528854,0, + 0.120116,0.912706,0.390565,2.545261,-1.5933,0.38631, + -0.133012,0.991114,0,2.706963,-1.528854,0, + 0.081223,0.915345,0.394394,2.721135,-1.520418,0.362378, + 0.1717,0.74071,0.649514,2.396607,-1.593239,0.389972, + -0.144073,0.989567,0,2.348182,-1.624595,0, + 0.815341,-0.578981,0,2.534227,-1.617078,0, + 0.1717,0.74071,0.649514,2.396607,-1.593239,0.389972, + 0.815341,-0.578981,0,2.534227,-1.617078,0, + 0.120116,0.912706,0.390565,2.545261,-1.5933,0.38631, + 0.167704,0.495674,0.852164,2.243492,-1.584783,0.431143, + -0.073566,0.99729,0,2.167167,-1.596326,0, + -0.144073,0.989567,0,2.348182,-1.624595,0, + 0.167704,0.495674,0.852164,2.243492,-1.584783,0.431143, + -0.144073,0.989567,0,2.348182,-1.624595,0, + 0.1717,0.74071,0.649514,2.396607,-1.593239,0.389972, + 0.140536,0.558684,0.817388,2.0482,-1.581983,0.555832, + -0.034649,0.9994,0,1.920432,-1.567396,0, + -0.073566,0.99729,0,2.167167,-1.596326,0, + 0.140536,0.558684,0.817388,2.0482,-1.581983,0.555832, + -0.073566,0.99729,0,2.167167,-1.596326,0, + 0.167704,0.495674,0.852164,2.243492,-1.584783,0.431143, + 0.100131,0.509748,0.854477,2.835437,-0.231101,0.57789, + 0.478274,-0.500384,0.721713,2.736198,-0.346225,0.659345, + 0.136523,0.621747,0.771228,2.881063,-0.493146,0.521968, + 0.136523,0.621747,0.771228,2.881063,-0.493146,0.521968, + 0.709718,-0.453837,0.538824,2.986408,-0.413503,0.428964, + 0.100131,0.509748,0.854477,2.835437,-0.231101,0.57789, + 0.063174,0.351351,0.93411,2.910769,-0.638444,0.431191, + 0.709718,-0.453837,0.538824,2.986408,-0.413503,0.428964, + 0.136523,0.621747,0.771228,2.881063,-0.493146,0.521968, + 0.136523,0.621747,0.771228,2.881063,-0.493146,0.521968, + 0.078896,0.195617,0.977502,2.82554,-0.567578,0.552597, + 0.063174,0.351351,0.93411,2.910769,-0.638444,0.431191, + 0.245892,-0.489895,0.836385,2.688131,-0.517509,0.672975, + 0.078896,0.195617,0.977502,2.82554,-0.567578,0.552597, + 0.136523,0.621747,0.771228,2.881063,-0.493146,0.521968, + 0.430574,-0.353967,0.830249,2.647368,-0.61155,0.669485, + 0.518786,-0.204527,0.830078,2.5392,-0.727778,0.750475, + 0.227108,0.258715,0.938876,2.637655,-0.768176,0.637039, + 0.58512,-0.108234,0.803692,2.618307,-0.549092,0.805491, + 0.518786,-0.204527,0.830078,2.5392,-0.727778,0.750475, + 0.430574,-0.353967,0.830249,2.647368,-0.61155,0.669485, + 0.430574,-0.353967,0.830249,2.647368,-0.61155,0.669485, + 0.245892,-0.489895,0.836385,2.688131,-0.517509,0.672975, + 0.58512,-0.108234,0.803692,2.618307,-0.549092,0.805491, + 0.089104,0.59547,0.798421,2.710721,-0.830091,0.532493, + 0.063174,0.351351,0.93411,2.910769,-0.638444,0.431191, + 0.078896,0.195617,0.977502,2.82554,-0.567578,0.552597, + 0.089104,0.59547,0.798421,2.710721,-0.830091,0.532493, + 0.078896,0.195617,0.977502,2.82554,-0.567578,0.552597, + 0.227108,0.258715,0.938876,2.637655,-0.768176,0.637039, + 0.147941,0.53134,0.834141,2.857666,-0.930625,0.391195, + 0.063174,0.351351,0.93411,2.910769,-0.638444,0.431191, + 0.089104,0.59547,0.798421,2.710721,-0.830091,0.532493, + 0.097816,-0.016117,0.995074,2.993075,-0.708434,0.342596, + 0.063174,0.351351,0.93411,2.910769,-0.638444,0.431191, + 0.147941,0.53134,0.834141,2.857666,-0.930625,0.391195, + 0.147941,0.53134,0.834141,2.857666,-0.930625,0.391195, + 0.244106,-0.79539,0.554768,2.960118,-0.941827,0.284743, + 0.10737,-0.293005,0.950063,3.045715,-0.767786,0.261741, + 0.147941,0.53134,0.834141,2.857666,-0.930625,0.391195, + 0.10737,-0.293005,0.950063,3.045715,-0.767786,0.261741, + 0.097816,-0.016117,0.995074,2.993075,-0.708434,0.342596, + -0.334515,0.94239,0,2.970902,-0.959664,0, + 0.942695,-0.333657,0,3.065544,-0.788768,0, + 0.10737,-0.293005,0.950063,3.045715,-0.767786,0.261741, + -0.334515,0.94239,0,2.970902,-0.959664,0, + 0.10737,-0.293005,0.950063,3.045715,-0.767786,0.261741, + 0.244106,-0.79539,0.554768,2.960118,-0.941827,0.284743, + -0.476715,0.879058,0,3.118124,-0.703925,0, + 0.6483,-0.171023,0.741928,3.107533,-0.691019,0.264602, + 0.10737,-0.293005,0.950063,3.045715,-0.767786,0.261741, + -0.476715,0.879058,0,3.118124,-0.703925,0, + 0.10737,-0.293005,0.950063,3.045715,-0.767786,0.261741, + 0.942695,-0.333657,0,3.065544,-0.788768,0, + 0.263434,0.119819,0.957207,2.669281,-0.930664,0.557166, + 0.101272,0.634315,0.766413,2.670253,-1.108365,0.544018, + 0.147941,0.53134,0.834141,2.857666,-0.930625,0.391195, + 0.263434,0.119819,0.957207,2.669281,-0.930664,0.557166, + 0.147941,0.53134,0.834141,2.857666,-0.930625,0.391195, + 0.089104,0.59547,0.798421,2.710721,-0.830091,0.532493, + 0.078896,0.195617,0.977502,2.82554,-0.567578,0.552597, + 0.245892,-0.489895,0.836385,2.688131,-0.517509,0.672975, + 0.430574,-0.353967,0.830249,2.647368,-0.61155,0.669485, + 0.078896,0.195617,0.977502,2.82554,-0.567578,0.552597, + 0.430574,-0.353967,0.830249,2.647368,-0.61155,0.669485, + 0.227108,0.258715,0.938876,2.637655,-0.768176,0.637039, + 0.063174,0.351351,0.93411,2.910769,-0.638444,0.431191, + 0.097816,-0.016117,0.995074,2.993075,-0.708434,0.342596, + 0.4379,-0.250054,0.863549,3.053144,-0.609681,0.326931, + 0.063174,0.351351,0.93411,2.910769,-0.638444,0.431191, + 0.4379,-0.250054,0.863549,3.053144,-0.609681,0.326931, + 0.709718,-0.453837,0.538824,2.986408,-0.413503,0.428964, + 0.10737,-0.293005,0.950063,3.045715,-0.767786,0.261741, + 0.6483,-0.171023,0.741928,3.107533,-0.691019,0.264602, + 0.4379,-0.250054,0.863549,3.053144,-0.609681,0.326931, + 0.10737,-0.293005,0.950063,3.045715,-0.767786,0.261741, + 0.4379,-0.250054,0.863549,3.053144,-0.609681,0.326931, + 0.097816,-0.016117,0.995074,2.993075,-0.708434,0.342596, + -0.809154,0.004832,0.587577,-1.200688,-1.577575,0.799188, + -0.942755,-0.29871,-0.148273,-1.226563,-1.655159,0.687343, + -0.965506,-0.176768,-0.191185,-1.091175,-1.70712,0.727242, + -0.809154,0.004832,0.587577,-1.200688,-1.577575,0.799188, + -0.965506,-0.176768,-0.191185,-1.091175,-1.70712,0.727242, + -0.02449,0.224062,0.974267,-0.953236,-1.545941,0.89918, + -0.285709,0.130064,0.949449,-1.376186,-1.661988,0.718954, + -0.942755,-0.29871,-0.148273,-1.226563,-1.655159,0.687343, + -0.809154,0.004832,0.587577,-1.200688,-1.577575,0.799188, + 0.714393,-0.109998,0.691045,-1.266738,-1.691944,0.557922, + 0.859237,-0.17312,0.481395,-1.089642,-1.757196,0.685154, + -0.965506,-0.176768,-0.191185,-1.091175,-1.70712,0.727242, + 0.714393,-0.109998,0.691045,-1.266738,-1.691944,0.557922, + -0.965506,-0.176768,-0.191185,-1.091175,-1.70712,0.727242, + -0.942755,-0.29871,-0.148273,-1.226563,-1.655159,0.687343, + -0.017579,0.132168,0.991072,-0.972089,-1.774507,0.76857, + -0.02449,0.224062,0.974267,-0.953236,-1.545941,0.89918, + -0.965506,-0.176768,-0.191185,-1.091175,-1.70712,0.727242, + 0.419396,-0.035927,0.907092,-0.812845,-1.785424,0.768511, + -0.02449,0.224062,0.974267,-0.953236,-1.545941,0.89918, + -0.017579,0.132168,0.991072,-0.972089,-1.774507,0.76857, + 0.045651,-0.004499,0.998947,-0.680046,-1.768325,0.81908, + 0.079848,0.962653,0.258695,-0.535144,-1.615983,0.920556, + -0.02449,0.224062,0.974267,-0.953236,-1.545941,0.89918, + 0.045651,-0.004499,0.998947,-0.680046,-1.768325,0.81908, + -0.02449,0.224062,0.974267,-0.953236,-1.545941,0.89918, + 0.419396,-0.035927,0.907092,-0.812845,-1.785424,0.768511, + 0.031476,0.864418,0.501787,-0.564074,-1.789401,0.803191, + 0.079848,0.962653,0.258695,-0.535144,-1.615983,0.920556, + 0.045651,-0.004499,0.998947,-0.680046,-1.768325,0.81908, + -0.019419,-0.11596,0.993064,-0.422877,-1.7512,0.823423, + 0.079848,0.962653,0.258695,-0.535144,-1.615983,0.920556, + 0.031476,0.864418,0.501787,-0.564074,-1.789401,0.803191, + 0.061261,0.954316,0.292452,-0.07847,-1.688266,0.80023, + -0.084259,-0.367691,0.926123,-0.063012,-1.583021,0.865082, + 0.079848,0.962653,0.258695,-0.535144,-1.615983,0.920556, + 0.061261,0.954316,0.292452,-0.07847,-1.688266,0.80023, + 0.079848,0.962653,0.258695,-0.535144,-1.615983,0.920556, + -0.019419,-0.11596,0.993064,-0.422877,-1.7512,0.823423, + -0.004377,0.58747,0.809234,-0.543078,-1.810473,0.563825, + 0.076968,0.969253,0.233719,-0.094135,-1.769086,0.556924, + 0.061261,0.954316,0.292452,-0.07847,-1.688266,0.80023, + -0.004377,0.58747,0.809234,-0.543078,-1.810473,0.563825, + 0.061261,0.954316,0.292452,-0.07847,-1.688266,0.80023, + -0.019419,-0.11596,0.993064,-0.422877,-1.7512,0.823423, + -0.019419,-0.11596,0.993064,-0.422877,-1.7512,0.823423, + 0.031476,0.864418,0.501787,-0.564074,-1.789401,0.803191, + -0.004377,0.58747,0.809234,-0.543078,-1.810473,0.563825, + 0.045651,-0.004499,0.998947,-0.680046,-1.768325,0.81908, + -0.004377,0.58747,0.809234,-0.543078,-1.810473,0.563825, + 0.031476,0.864418,0.501787,-0.564074,-1.789401,0.803191, + 0.419396,-0.035927,0.907092,-0.812845,-1.785424,0.768511, + -0.055857,0.145868,0.987726,-0.977375,-1.793126,0.498747, + -0.004377,0.58747,0.809234,-0.543078,-1.810473,0.563825, + 0.419396,-0.035927,0.907092,-0.812845,-1.785424,0.768511, + -0.004377,0.58747,0.809234,-0.543078,-1.810473,0.563825, + 0.045651,-0.004499,0.998947,-0.680046,-1.768325,0.81908, + -0.017579,0.132168,0.991072,-0.972089,-1.774507,0.76857, + -0.965506,-0.176768,-0.191185,-1.091175,-1.70712,0.727242, + 0.859237,-0.17312,0.481395,-1.089642,-1.757196,0.685154, + -0.182029,-0.190207,0.964721,-1.108758,-1.770749,0.473033, + -0.055857,0.145868,0.987726,-0.977375,-1.793126,0.498747, + 0.859237,-0.17312,0.481395,-1.089642,-1.757196,0.685154, + -0.182029,-0.190207,0.964721,-1.108758,-1.770749,0.473033, + 0.859237,-0.17312,0.481395,-1.089642,-1.757196,0.685154, + 0.714393,-0.109998,0.691045,-1.266738,-1.691944,0.557922, + 0.714393,-0.109998,0.691045,-1.266738,-1.691944,0.557922, + -0.571338,-0.120921,0.811758,-1.305099,-1.70846,0.48423, + -0.182029,-0.190207,0.964721,-1.108758,-1.770749,0.473033, + -0.942755,-0.29871,-0.148273,-1.226563,-1.655159,0.687343, + -0.285709,0.130064,0.949449,-1.376186,-1.661988,0.718954, + 0.714393,-0.109998,0.691045,-1.266738,-1.691944,0.557922, + -0.587909,-0.233166,0.774594,-1.397474,-1.693815,0.570541, + 0.714393,-0.109998,0.691045,-1.266738,-1.691944,0.557922, + -0.285709,0.130064,0.949449,-1.376186,-1.661988,0.718954, + -0.571338,-0.120921,0.811758,-1.305099,-1.70846,0.48423, + 0.023392,-0.110333,0.993619,-1.406693,-1.697325,0.450399, + -0.279485,0.127803,0.951606,-1.386502,-1.718441,0.350823, + -0.329905,-0.225598,0.916661,-0.972514,-1.822778,0.372649, + -0.571338,-0.120921,0.811758,-1.305099,-1.70846,0.48423, + -0.279485,0.127803,0.951606,-1.386502,-1.718441,0.350823, + 0.044022,0.273891,0.960753,-0.523838,-1.850065,0.388007, + -0.004377,0.58747,0.809234,-0.543078,-1.810473,0.563825, + -0.055857,0.145868,0.987726,-0.977375,-1.793126,0.498747, + 0.044022,0.273891,0.960753,-0.523838,-1.850065,0.388007, + -0.055857,0.145868,0.987726,-0.977375,-1.793126,0.498747, + -0.329905,-0.225598,0.916661,-0.972514,-1.822778,0.372649, + 0.057779,0.975002,0.214553,-0.112666,-1.806584,0.383324, + 0.076968,0.969253,0.233719,-0.094135,-1.769086,0.556924, + -0.004377,0.58747,0.809234,-0.543078,-1.810473,0.563825, + 0.057779,0.975002,0.214553,-0.112666,-1.806584,0.383324, + -0.004377,0.58747,0.809234,-0.543078,-1.810473,0.563825, + 0.044022,0.273891,0.960753,-0.523838,-1.850065,0.388007, + -0.178511,-0.973481,0.143068,0.480235,-1.631521,0.401961, + -0.1427,-0.847733,0.510868,0.489819,-1.524947,0.672392, + 0.076968,0.969253,0.233719,-0.094135,-1.769086,0.556924, + -0.178511,-0.973481,0.143068,0.480235,-1.631521,0.401961, + 0.076968,0.969253,0.233719,-0.094135,-1.769086,0.556924, + 0.057779,0.975002,0.214553,-0.112666,-1.806584,0.383324, + 0.057779,0.975002,0.214553,-0.112666,-1.806584,0.383324, + -0.084764,-0.996401,0,-0.155114,-1.828285,0, + 0.226963,-0.973903,0,0.44655,-1.67295,0, + 0.057779,0.975002,0.214553,-0.112666,-1.806584,0.383324, + 0.226963,-0.973903,0,0.44655,-1.67295,0, + -0.178511,-0.973481,0.143068,0.480235,-1.631521,0.401961, + 0.044022,0.273891,0.960753,-0.523838,-1.850065,0.388007, + 0.854132,-0.520056,0,-0.530369,-1.860806,0, + -0.084764,-0.996401,0,-0.155114,-1.828285,0, + 0.044022,0.273891,0.960753,-0.523838,-1.850065,0.388007, + -0.084764,-0.996401,0,-0.155114,-1.828285,0, + 0.057779,0.975002,0.214553,-0.112666,-1.806584,0.383324, + -0.329905,-0.225598,0.916661,-0.972514,-1.822778,0.372649, + 0.113474,-0.993541,0,-0.956007,-1.825728,0, + 0.854132,-0.520056,0,-0.530369,-1.860806,0, + -0.329905,-0.225598,0.916661,-0.972514,-1.822778,0.372649, + 0.854132,-0.520056,0,-0.530369,-1.860806,0, + 0.044022,0.273891,0.960753,-0.523838,-1.850065,0.388007, + -0.279485,0.127803,0.951606,-1.386502,-1.718441,0.350823, + 0.011286,0.999936,0,-1.395728,-1.723811,0, + 0.113474,-0.993541,0,-0.956007,-1.825728,0, + -0.279485,0.127803,0.951606,-1.386502,-1.718441,0.350823, + 0.113474,-0.993541,0,-0.956007,-1.825728,0, + -0.329905,-0.225598,0.916661,-0.972514,-1.822778,0.372649, + -0.055857,0.145868,0.987726,-0.977375,-1.793126,0.498747, + -0.017579,0.132168,0.991072,-0.972089,-1.774507,0.76857, + 0.859237,-0.17312,0.481395,-1.089642,-1.757196,0.685154, + -0.017579,0.132168,0.991072,-0.972089,-1.774507,0.76857, + -0.055857,0.145868,0.987726,-0.977375,-1.793126,0.498747, + 0.419396,-0.035927,0.907092,-0.812845,-1.785424,0.768511, + -0.51975,0.138222,0.843063,1.806371,-2.949735,0.984058, + -0.4909,0.016111,-0.871067,1.771416,-2.769024,0.9461, + 0.21689,-0.976039,-0.017487,1.718315,-2.775468,0.921796, + -0.51975,0.138222,0.843063,1.806371,-2.949735,0.984058, + 0.21689,-0.976039,-0.017487,1.718315,-2.775468,0.921796, + -0.424393,0.057227,0.903668,1.734568,-2.965876,0.986396, + -0.775358,0.344514,0.529274,2.021366,-2.881725,0.945561, + -0.440199,0.219838,0.870572,1.960643,-2.71286,0.90089, + -0.90358,0.003168,0.428409,1.880971,-2.733242,0.8902, + -0.775358,0.344514,0.529274,2.021366,-2.881725,0.945561, + -0.90358,0.003168,0.428409,1.880971,-2.733242,0.8902, + -0.032037,-0.072305,0.996868,1.911792,-2.895773,0.950117, + -0.820357,0.160676,0.548815,2.057496,-2.887282,0.844225, + 0.636282,0.100894,0.76483,1.994078,-2.713047,0.824553, + -0.440199,0.219838,0.870572,1.960643,-2.71286,0.90089, + -0.820357,0.160676,0.548815,2.057496,-2.887282,0.844225, + -0.440199,0.219838,0.870572,1.960643,-2.71286,0.90089, + -0.775358,0.344514,0.529274,2.021366,-2.881725,0.945561, + -0.906134,0.012265,-0.422813,1.735077,-3.022732,0.972751, + -0.51975,0.138222,0.843063,1.806371,-2.949735,0.984058, + -0.424393,0.057227,0.903668,1.734568,-2.965876,0.986396, + 0.461464,-0.003303,0.887153,1.721745,-3.116887,0.979111, + 0.000666,0.002295,0.999997,1.802387,-3.089615,0.961851, + -0.906134,0.012265,-0.422813,1.735077,-3.022732,0.972751, + -0.156447,-0.088128,0.983747,1.811797,-3.135641,0.933096, + 0.000666,0.002295,0.999997,1.802387,-3.089615,0.961851, + 0.461464,-0.003303,0.887153,1.721745,-3.116887,0.979111, + 0.773659,-0.235087,-0.588375,2.091539,-3.032437,0.947029, + 0.789099,-0.039289,-0.613008,2.113587,-3.011851,0.851648, + -0.820357,0.160676,0.548815,2.057496,-2.887282,0.844225, + 0.773659,-0.235087,-0.588375,2.091539,-3.032437,0.947029, + -0.820357,0.160676,0.548815,2.057496,-2.887282,0.844225, + -0.775358,0.344514,0.529274,2.021366,-2.881725,0.945561, + -0.90358,0.003168,0.428409,1.880971,-2.733242,0.8902, + -0.062994,-0.00854,-0.997977,1.830669,-2.736121,0.903313, + 0.433219,-0.09361,0.896414,1.848272,-2.92726,0.996966, + -0.90358,0.003168,0.428409,1.880971,-2.733242,0.8902, + 0.433219,-0.09361,0.896414,1.848272,-2.92726,0.996966, + -0.032037,-0.072305,0.996868,1.911792,-2.895773,0.950117, + 0.433219,-0.09361,0.896414,1.848272,-2.92726,0.996966, + -0.062994,-0.00854,-0.997977,1.830669,-2.736121,0.903313, + -0.4909,0.016111,-0.871067,1.771416,-2.769024,0.9461, + 0.433219,-0.09361,0.896414,1.848272,-2.92726,0.996966, + -0.4909,0.016111,-0.871067,1.771416,-2.769024,0.9461, + -0.51975,0.138222,0.843063,1.806371,-2.949735,0.984058, + -0.050511,-0.258376,-0.964723,1.709173,-3.133145,0.80794, + 0.461464,-0.003303,0.887153,1.721745,-3.116887,0.979111, + -0.906134,0.012265,-0.422813,1.735077,-3.022732,0.972751, + -0.050511,-0.258376,-0.964723,1.709173,-3.133145,0.80794, + -0.906134,0.012265,-0.422813,1.735077,-3.022732,0.972751, + -0.065687,-0.249194,-0.966223,1.705953,-3.006628,0.83263, + -0.042094,-0.220101,-0.974568,1.806407,-3.173343,0.834455, + -0.156447,-0.088128,0.983747,1.811797,-3.135641,0.933096, + 0.461464,-0.003303,0.887153,1.721745,-3.116887,0.979111, + -0.042094,-0.220101,-0.974568,1.806407,-3.173343,0.834455, + 0.461464,-0.003303,0.887153,1.721745,-3.116887,0.979111, + -0.050511,-0.258376,-0.964723,1.709173,-3.133145,0.80794, + -0.363523,-0.150625,-0.919327,1.900481,-3.131932,0.728621, + -0.042094,-0.220101,-0.974568,1.806407,-3.173343,0.834455, + -0.050511,-0.258376,-0.964723,1.709173,-3.133145,0.80794, + -0.363523,-0.150625,-0.919327,1.900481,-3.131932,0.728621, + -0.050511,-0.258376,-0.964723,1.709173,-3.133145,0.80794, + -0.326843,-0.236651,-0.91497,1.741854,-3.114181,0.700705, + 0.753698,-0.027204,-0.656657,1.776024,-2.980086,0.707575, + -0.326843,-0.236651,-0.91497,1.741854,-3.114181,0.700705, + -0.050511,-0.258376,-0.964723,1.709173,-3.133145,0.80794, + 0.753698,-0.027204,-0.656657,1.776024,-2.980086,0.707575, + -0.050511,-0.258376,-0.964723,1.709173,-3.133145,0.80794, + -0.065687,-0.249194,-0.966223,1.705953,-3.006628,0.83263, + -0.065687,-0.249194,-0.966223,1.705953,-3.006628,0.83263, + -0.020456,0.943466,0.330837,1.700797,-2.794792,0.82425, + 0.030762,-0.124297,-0.991768,1.736425,-2.743683,0.736866, + -0.065687,-0.249194,-0.966223,1.705953,-3.006628,0.83263, + 0.030762,-0.124297,-0.991768,1.736425,-2.743683,0.736866, + 0.753698,-0.027204,-0.656657,1.776024,-2.980086,0.707575, + -0.032037,-0.072305,0.996868,1.911792,-2.895773,0.950117, + -0.215783,-0.895808,-0.388544,1.980621,-3.043895,0.964237, + 0.773659,-0.235087,-0.588375,2.091539,-3.032437,0.947029, + -0.032037,-0.072305,0.996868,1.911792,-2.895773,0.950117, + 0.773659,-0.235087,-0.588375,2.091539,-3.032437,0.947029, + -0.775358,0.344514,0.529274,2.021366,-2.881725,0.945561, + -0.032037,-0.072305,0.996868,1.911792,-2.895773,0.950117, + 0.433219,-0.09361,0.896414,1.848272,-2.92726,0.996966, + 0.356923,-0.210291,0.910156,1.898573,-3.068274,0.994338, + -0.032037,-0.072305,0.996868,1.911792,-2.895773,0.950117, + 0.356923,-0.210291,0.910156,1.898573,-3.068274,0.994338, + -0.215783,-0.895808,-0.388544,1.980621,-3.043895,0.964237, + -0.51975,0.138222,0.843063,1.806371,-2.949735,0.984058, + 0.517272,-0.552302,0.653753,1.855134,-3.083228,0.986129, + 0.356923,-0.210291,0.910156,1.898573,-3.068274,0.994338, + -0.51975,0.138222,0.843063,1.806371,-2.949735,0.984058, + 0.356923,-0.210291,0.910156,1.898573,-3.068274,0.994338, + 0.433219,-0.09361,0.896414,1.848272,-2.92726,0.996966, + -0.156447,-0.088128,0.983747,1.811797,-3.135641,0.933096, + 0.517272,-0.552302,0.653753,1.855134,-3.083228,0.986129, + 0.000666,0.002295,0.999997,1.802387,-3.089615,0.961851, + 0.000666,0.002295,0.999997,1.802387,-3.089615,0.961851, + 0.517272,-0.552302,0.653753,1.855134,-3.083228,0.986129, + -0.51975,0.138222,0.843063,1.806371,-2.949735,0.984058, + 0.000666,0.002295,0.999997,1.802387,-3.089615,0.961851, + -0.51975,0.138222,0.843063,1.806371,-2.949735,0.984058, + -0.906134,0.012265,-0.422813,1.735077,-3.022732,0.972751, + -0.424393,0.057227,0.903668,1.734568,-2.965876,0.986396, + -0.065687,-0.249194,-0.966223,1.705953,-3.006628,0.83263, + -0.906134,0.012265,-0.422813,1.735077,-3.022732,0.972751, + -0.080858,0.024731,0.996419,2.07369,-3.020848,0.782654, + -0.753891,0.130682,0.643872,2.001343,-2.847715,0.762517, + -0.820357,0.160676,0.548815,2.057496,-2.887282,0.844225, + -0.080858,0.024731,0.996419,2.07369,-3.020848,0.782654, + -0.820357,0.160676,0.548815,2.057496,-2.887282,0.844225, + 0.789099,-0.039289,-0.613008,2.113587,-3.011851,0.851648, + -0.492859,-0.096404,0.864752,1.857471,-2.950722,0.669988, + -0.363523,-0.150625,-0.919327,1.900481,-3.131932,0.728621, + -0.326843,-0.236651,-0.91497,1.741854,-3.114181,0.700705, + 0.753698,-0.027204,-0.656657,1.776024,-2.980086,0.707575, + -0.492859,-0.096404,0.864752,1.857471,-2.950722,0.669988, + -0.326843,-0.236651,-0.91497,1.741854,-3.114181,0.700705, + -0.492859,-0.096404,0.864752,1.857471,-2.950722,0.669988, + 0.012244,-0.298111,0.954453,1.945632,-2.87671,0.703118, + -0.245482,-0.183394,0.951896,1.998099,-3.039955,0.718855, + -0.492859,-0.096404,0.864752,1.857471,-2.950722,0.669988, + -0.245482,-0.183394,0.951896,1.998099,-3.039955,0.718855, + -0.363523,-0.150625,-0.919327,1.900481,-3.131932,0.728621, + 0.012244,-0.298111,0.954453,1.945632,-2.87671,0.703118, + -0.753891,0.130682,0.643872,2.001343,-2.847715,0.762517, + -0.080858,0.024731,0.996419,2.07369,-3.020848,0.782654, + 0.012244,-0.298111,0.954453,1.945632,-2.87671,0.703118, + -0.080858,0.024731,0.996419,2.07369,-3.020848,0.782654, + -0.245482,-0.183394,0.951896,1.998099,-3.039955,0.718855, + 0.672894,0.661099,0.331907,1.841282,-2.716008,0.708009, + -0.545598,-0.330416,0.770161,1.884318,-2.724404,0.701999, + 0.012244,-0.298111,0.954453,1.945632,-2.87671,0.703118, + 0.672894,0.661099,0.331907,1.841282,-2.716008,0.708009, + 0.012244,-0.298111,0.954453,1.945632,-2.87671,0.703118, + -0.492859,-0.096404,0.864752,1.857471,-2.950722,0.669988, + -0.074103,0.409269,0.909399,1.972647,-2.728848,0.772496, + -0.753891,0.130682,0.643872,2.001343,-2.847715,0.762517, + 0.012244,-0.298111,0.954453,1.945632,-2.87671,0.703118, + -0.074103,0.409269,0.909399,1.972647,-2.728848,0.772496, + 0.012244,-0.298111,0.954453,1.945632,-2.87671,0.703118, + -0.545598,-0.330416,0.770161,1.884318,-2.724404,0.701999, + 0.030762,-0.124297,-0.991768,1.736425,-2.743683,0.736866, + 0.672894,0.661099,0.331907,1.841282,-2.716008,0.708009, + -0.492859,-0.096404,0.864752,1.857471,-2.950722,0.669988, + 0.030762,-0.124297,-0.991768,1.736425,-2.743683,0.736866, + -0.492859,-0.096404,0.864752,1.857471,-2.950722,0.669988, + 0.753698,-0.027204,-0.656657,1.776024,-2.980086,0.707575, + 0.009712,0.399549,0.91666,-2.687162,-1.539807,0.988048, + -0.13251,0.440061,0.888137,-2.837147,-1.791733,0.921563, + 0.942117,-0.292664,0.163592,-2.734184,-1.717948,0.749581, + 0.009712,0.399549,0.91666,-2.687162,-1.539807,0.988048, + 0.942117,-0.292664,0.163592,-2.734184,-1.717948,0.749581, + -0.995081,-0.092251,-0.036114,-2.591357,-1.510845,0.88547, + 0.095733,-0.224552,0.969748,-2.765069,-1.561164,1.084313, + 0.413011,0.629609,0.658038,-2.918293,-1.904184,1.004659, + -0.13251,0.440061,0.888137,-2.837147,-1.791733,0.921563, + 0.095733,-0.224552,0.969748,-2.765069,-1.561164,1.084313, + -0.13251,0.440061,0.888137,-2.837147,-1.791733,0.921563, + 0.009712,0.399549,0.91666,-2.687162,-1.539807,0.988048, + -0.149005,-0.65467,0.741084,-2.862576,-1.546894,1.117139, + 0.070969,0.266956,0.961092,-3.010917,-1.884498,1.08351, + 0.413011,0.629609,0.658038,-2.918293,-1.904184,1.004659, + -0.149005,-0.65467,0.741084,-2.862576,-1.546894,1.117139, + 0.413011,0.629609,0.658038,-2.918293,-1.904184,1.004659, + 0.095733,-0.224552,0.969748,-2.765069,-1.561164,1.084313, + -0.461794,0.113692,0.879671,-2.955052,-1.49684,1.128812, + 0.405633,0.578229,0.707893,-3.117476,-1.866892,1.108034, + 0.070969,0.266956,0.961092,-3.010917,-1.884498,1.08351, + -0.461794,0.113692,0.879671,-2.955052,-1.49684,1.128812, + 0.070969,0.266956,0.961092,-3.010917,-1.884498,1.08351, + -0.149005,-0.65467,0.741084,-2.862576,-1.546894,1.117139, + -0.18119,-0.970212,0.160805,-3.063133,-1.440555,1.090926, + -0.431118,-0.034268,0.901645,-3.23261,-1.834299,1.087832, + 0.405633,0.578229,0.707893,-3.117476,-1.866892,1.108034, + -0.18119,-0.970212,0.160805,-3.063133,-1.440555,1.090926, + 0.405633,0.578229,0.707893,-3.117476,-1.866892,1.108034, + -0.461794,0.113692,0.879671,-2.955052,-1.49684,1.128812, + 0.290478,-0.146424,0.945612,-3.387254,-1.486027,0.672861, + 0.596352,0.583149,0.551635,-3.498521,-1.762078,0.762472, + 0.637284,0.689194,0.344791,-3.49052,-1.760417,0.903104, + 0.290478,-0.146424,0.945612,-3.387254,-1.486027,0.672861, + 0.637284,0.689194,0.344791,-3.49052,-1.760417,0.903104, + 0.737412,0.542596,0.402261,-3.36599,-1.48517,0.888076, + 0.737412,0.542596,0.402261,-3.36599,-1.48517,0.888076, + 0.515412,-0.714946,-0.472444,-3.319817,-1.365015,0.886015, + -0.521685,-0.261319,0.812131,-3.335942,-1.365685,0.72459, + 0.737412,0.542596,0.402261,-3.36599,-1.48517,0.888076, + -0.521685,-0.261319,0.812131,-3.335942,-1.365685,0.72459, + 0.290478,-0.146424,0.945612,-3.387254,-1.486027,0.672861, + -0.637763,0.107242,0.76273,-3.068444,-2.260195,1.03507, + 0.503689,0.453945,0.735004,-3.177824,-2.279173,1.04758, + 0.851754,0.52393,-0.003494,-3.162498,-2.556375,1.058409, + -0.637763,0.107242,0.76273,-3.068444,-2.260195,1.03507, + 0.851754,0.52393,-0.003494,-3.162498,-2.556375,1.058409, + 0.840313,0.535537,-0.084107,-3.078699,-2.553982,1.046834, + -0.67011,-0.018974,0.742019,-3.047974,-2.109628,1.063497, + -0.833016,0.038682,0.551896,-3.169489,-2.110039,1.076796, + 0.503689,0.453945,0.735004,-3.177824,-2.279173,1.04758, + -0.67011,-0.018974,0.742019,-3.047974,-2.109628,1.063497, + 0.503689,0.453945,0.735004,-3.177824,-2.279173,1.04758, + -0.637763,0.107242,0.76273,-3.068444,-2.260195,1.03507, + 0.070969,0.266956,0.961092,-3.010917,-1.884498,1.08351, + 0.405633,0.578229,0.707893,-3.117476,-1.866892,1.108034, + -0.833016,0.038682,0.551896,-3.169489,-2.110039,1.076796, + 0.070969,0.266956,0.961092,-3.010917,-1.884498,1.08351, + -0.833016,0.038682,0.551896,-3.169489,-2.110039,1.076796, + -0.67011,-0.018974,0.742019,-3.047974,-2.109628,1.063497, + -0.833016,0.038682,0.551896,-3.169489,-2.110039,1.076796, + 0.197648,0.486888,0.850809,-3.207447,-2.103206,1.071366, + 0.503689,0.453945,0.735004,-3.177824,-2.279173,1.04758, + 0.405633,0.578229,0.707893,-3.117476,-1.866892,1.108034, + -0.431118,-0.034268,0.901645,-3.23261,-1.834299,1.087832, + 0.197648,0.486888,0.850809,-3.207447,-2.103206,1.071366, + 0.405633,0.578229,0.707893,-3.117476,-1.866892,1.108034, + 0.197648,0.486888,0.850809,-3.207447,-2.103206,1.071366, + -0.833016,0.038682,0.551896,-3.169489,-2.110039,1.076796, + 0.503689,0.453945,0.735004,-3.177824,-2.279173,1.04758, + 0.144389,0.231536,0.962051,-3.281816,-2.305055,1.001878, + 0.163153,0.19945,0.96623,-3.251541,-2.56405,1.023627, + 0.503689,0.453945,0.735004,-3.177824,-2.279173,1.04758, + 0.163153,0.19945,0.96623,-3.251541,-2.56405,1.023627, + 0.851754,0.52393,-0.003494,-3.162498,-2.556375,1.058409, + 0.197648,0.486888,0.850809,-3.207447,-2.103206,1.071366, + -0.985013,0.106757,-0.135469,-3.327526,-2.075729,1.005328, + 0.144389,0.231536,0.962051,-3.281816,-2.305055,1.001878, + 0.197648,0.486888,0.850809,-3.207447,-2.103206,1.071366, + 0.144389,0.231536,0.962051,-3.281816,-2.305055,1.001878, + 0.503689,0.453945,0.735004,-3.177824,-2.279173,1.04758, + -0.431118,-0.034268,0.901645,-3.23261,-1.834299,1.087832, + -0.46316,0.228643,0.856274,-3.357996,-1.811803,0.975625, + -0.985013,0.106757,-0.135469,-3.327526,-2.075729,1.005328, + -0.431118,-0.034268,0.901645,-3.23261,-1.834299,1.087832, + -0.985013,0.106757,-0.135469,-3.327526,-2.075729,1.005328, + 0.197648,0.486888,0.850809,-3.207447,-2.103206,1.071366, + 0.144389,0.231536,0.962051,-3.281816,-2.305055,1.001878, + -0.948593,-0.185732,-0.25627,-3.389388,-2.305625,0.950348, + -0.99734,0.010762,-0.072093,-3.347304,-2.573628,0.955211, + 0.144389,0.231536,0.962051,-3.281816,-2.305055,1.001878, + -0.99734,0.010762,-0.072093,-3.347304,-2.573628,0.955211, + 0.163153,0.19945,0.96623,-3.251541,-2.56405,1.023627, + -0.985013,0.106757,-0.135469,-3.327526,-2.075729,1.005328, + -0.948593,-0.185732,-0.25627,-3.451965,-2.077314,0.931974, + -0.948593,-0.185732,-0.25627,-3.389388,-2.305625,0.950348, + -0.985013,0.106757,-0.135469,-3.327526,-2.075729,1.005328, + -0.948593,-0.185732,-0.25627,-3.389388,-2.305625,0.950348, + 0.144389,0.231536,0.962051,-3.281816,-2.305055,1.001878, + -0.46316,0.228643,0.856274,-3.357996,-1.811803,0.975625, + 0.637284,0.689194,0.344791,-3.49052,-1.760417,0.903104, + -0.948593,-0.185732,-0.25627,-3.451965,-2.077314,0.931974, + -0.46316,0.228643,0.856274,-3.357996,-1.811803,0.975625, + -0.948593,-0.185732,-0.25627,-3.451965,-2.077314,0.931974, + -0.985013,0.106757,-0.135469,-3.327526,-2.075729,1.005328, + -0.471141,0.022027,-0.881783,-3.007483,-2.270712,0.984279, + -0.637763,0.107242,0.76273,-3.068444,-2.260195,1.03507, + 0.840313,0.535537,-0.084107,-3.078699,-2.553982,1.046834, + -0.471141,0.022027,-0.881783,-3.007483,-2.270712,0.984279, + 0.840313,0.535537,-0.084107,-3.078699,-2.553982,1.046834, + -0.178214,-0.110838,-0.977729,-3.022819,-2.52224,0.979148, + -0.385346,-0.01874,-0.922582,-2.969687,-2.097941,0.982836, + -0.67011,-0.018974,0.742019,-3.047974,-2.109628,1.063497, + -0.637763,0.107242,0.76273,-3.068444,-2.260195,1.03507, + -0.385346,-0.01874,-0.922582,-2.969687,-2.097941,0.982836, + -0.637763,0.107242,0.76273,-3.068444,-2.260195,1.03507, + -0.471141,0.022027,-0.881783,-3.007483,-2.270712,0.984279, + 0.413011,0.629609,0.658038,-2.918293,-1.904184,1.004659, + 0.070969,0.266956,0.961092,-3.010917,-1.884498,1.08351, + -0.67011,-0.018974,0.742019,-3.047974,-2.109628,1.063497, + 0.413011,0.629609,0.658038,-2.918293,-1.904184,1.004659, + -0.67011,-0.018974,0.742019,-3.047974,-2.109628,1.063497, + -0.385346,-0.01874,-0.922582,-2.969687,-2.097941,0.982836, + -0.13251,0.440061,0.888137,-2.837147,-1.791733,0.921563, + 0.413011,0.629609,0.658038,-2.918293,-1.904184,1.004659, + -0.11646,-0.017993,-0.993032,-2.892438,-1.95081,0.87812, + -0.385346,-0.01874,-0.922582,-2.969687,-2.097941,0.982836, + 0.156207,-0.109405,-0.981647,-2.981187,-2.142718,0.858353, + -0.11646,-0.017993,-0.993032,-2.892438,-1.95081,0.87812, + -0.385346,-0.01874,-0.922582,-2.969687,-2.097941,0.982836, + -0.11646,-0.017993,-0.993032,-2.892438,-1.95081,0.87812, + 0.413011,0.629609,0.658038,-2.918293,-1.904184,1.004659, + -0.471141,0.022027,-0.881783,-3.007483,-2.270712,0.984279, + 0.339875,0.026681,-0.940092,-3.030605,-2.311222,0.88433, + 0.156207,-0.109405,-0.981647,-2.981187,-2.142718,0.858353, + -0.471141,0.022027,-0.881783,-3.007483,-2.270712,0.984279, + 0.156207,-0.109405,-0.981647,-2.981187,-2.142718,0.858353, + -0.385346,-0.01874,-0.922582,-2.969687,-2.097941,0.982836, + -0.178214,-0.110838,-0.977729,-3.022819,-2.52224,0.979148, + -0.674431,0.094186,-0.732306,-3.04661,-2.510881,0.900772, + 0.339875,0.026681,-0.940092,-3.030605,-2.311222,0.88433, + -0.178214,-0.110838,-0.977729,-3.022819,-2.52224,0.979148, + 0.339875,0.026681,-0.940092,-3.030605,-2.311222,0.88433, + -0.471141,0.022027,-0.881783,-3.007483,-2.270712,0.984279, + 0.156207,-0.109405,-0.981647,-2.981187,-2.142718,0.858353, + -0.978077,-0.070308,-0.196017,-3.040398,-2.156239,0.808208, + -0.037581,-0.042039,-0.998409,-2.964215,-1.978727,0.776572, + 0.156207,-0.109405,-0.981647,-2.981187,-2.142718,0.858353, + -0.037581,-0.042039,-0.998409,-2.964215,-1.978727,0.776572, + -0.11646,-0.017993,-0.993032,-2.892438,-1.95081,0.87812, + 0.339875,0.026681,-0.940092,-3.030605,-2.311222,0.88433, + -0.978077,-0.070308,-0.196017,-3.040398,-2.156239,0.808208, + 0.156207,-0.109405,-0.981647,-2.981187,-2.142718,0.858353, + -0.039603,0.339955,0.939607,-3.144012,-2.333635,0.829994, + -0.556404,-0.045521,-0.829664,-3.120761,-2.15777,0.766432, + -0.978077,-0.070308,-0.196017,-3.040398,-2.156239,0.808208, + -0.039603,0.339955,0.939607,-3.144012,-2.333635,0.829994, + -0.978077,-0.070308,-0.196017,-3.040398,-2.156239,0.808208, + 0.339875,0.026681,-0.940092,-3.030605,-2.311222,0.88433, + -0.978077,-0.070308,-0.196017,-3.040398,-2.156239,0.808208, + -0.556404,-0.045521,-0.829664,-3.120761,-2.15777,0.766432, + -0.377491,-0.043727,0.92498,-3.066022,-1.953125,0.719516, + -0.978077,-0.070308,-0.196017,-3.040398,-2.156239,0.808208, + -0.377491,-0.043727,0.92498,-3.066022,-1.953125,0.719516, + -0.037581,-0.042039,-0.998409,-2.964215,-1.978727,0.776572, + -0.556404,-0.045521,-0.829664,-3.120761,-2.15777,0.766432, + 0.72114,0.258271,-0.642848,-3.253309,-2.137354,0.760713, + 0.684558,0.361153,-0.633205,-3.211005,-1.850398,0.700723, + -0.556404,-0.045521,-0.829664,-3.120761,-2.15777,0.766432, + 0.684558,0.361153,-0.633205,-3.211005,-1.850398,0.700723, + -0.377491,-0.043727,0.92498,-3.066022,-1.953125,0.719516, + -0.039603,0.339955,0.939607,-3.144012,-2.333635,0.829994, + 0.845209,0.529005,0.075999,-3.235873,-2.335338,0.820588, + 0.72114,0.258271,-0.642848,-3.253309,-2.137354,0.760713, + -0.039603,0.339955,0.939607,-3.144012,-2.333635,0.829994, + 0.72114,0.258271,-0.642848,-3.253309,-2.137354,0.760713, + -0.556404,-0.045521,-0.829664,-3.120761,-2.15777,0.766432, + 0.780958,0.624512,0.00945,-3.132772,-2.528669,0.848639, + 0.61389,0.702597,0.359856,-3.240554,-2.555467,0.856262, + 0.845209,0.529005,0.075999,-3.235873,-2.335338,0.820588, + 0.780958,0.624512,0.00945,-3.132772,-2.528669,0.848639, + 0.845209,0.529005,0.075999,-3.235873,-2.335338,0.820588, + -0.039603,0.339955,0.939607,-3.144012,-2.333635,0.829994, + 0.77125,0.634502,0.050796,-3.381262,-1.828189,0.697034, + 0.596352,0.583149,0.551635,-3.498521,-1.762078,0.762472, + 0.290478,-0.146424,0.945612,-3.387254,-1.486027,0.672861, + 0.77125,0.634502,0.050796,-3.381262,-1.828189,0.697034, + 0.290478,-0.146424,0.945612,-3.387254,-1.486027,0.672861, + 0.830793,-0.244757,0.499877,-3.304804,-1.582192,0.643445, + 0.830793,-0.244757,0.499877,-3.304804,-1.582192,0.643445, + 0.843062,-0.10517,0.527433,-3.139394,-1.687482,0.638546, + 0.684558,0.361153,-0.633205,-3.211005,-1.850398,0.700723, + 0.830793,-0.244757,0.499877,-3.304804,-1.582192,0.643445, + 0.684558,0.361153,-0.633205,-3.211005,-1.850398,0.700723, + 0.77125,0.634502,0.050796,-3.381262,-1.828189,0.697034, + 0.72114,0.258271,-0.642848,-3.253309,-2.137354,0.760713, + 0.712283,0.385668,-0.586441,-3.422698,-2.070796,0.773898, + 0.77125,0.634502,0.050796,-3.381262,-1.828189,0.697034, + 0.72114,0.258271,-0.642848,-3.253309,-2.137354,0.760713, + 0.77125,0.634502,0.050796,-3.381262,-1.828189,0.697034, + 0.684558,0.361153,-0.633205,-3.211005,-1.850398,0.700723, + 0.845209,0.529005,0.075999,-3.235873,-2.335338,0.820588, + 0.684834,0.490952,-0.538488,-3.339489,-2.328145,0.827572, + 0.712283,0.385668,-0.586441,-3.422698,-2.070796,0.773898, + 0.845209,0.529005,0.075999,-3.235873,-2.335338,0.820588, + 0.712283,0.385668,-0.586441,-3.422698,-2.070796,0.773898, + 0.72114,0.258271,-0.642848,-3.253309,-2.137354,0.760713, + 0.61389,0.702597,0.359856,-3.240554,-2.555467,0.856262, + 0.722847,0.455753,-0.519404,-3.297886,-2.54902,0.861657, + 0.684834,0.490952,-0.538488,-3.339489,-2.328145,0.827572, + 0.61389,0.702597,0.359856,-3.240554,-2.555467,0.856262, + 0.684834,0.490952,-0.538488,-3.339489,-2.328145,0.827572, + 0.845209,0.529005,0.075999,-3.235873,-2.335338,0.820588, + 0.712283,0.385668,-0.586441,-3.422698,-2.070796,0.773898, + -0.058899,-0.007802,-0.998233,-3.463753,-2.079892,0.844667, + 0.596352,0.583149,0.551635,-3.498521,-1.762078,0.762472, + 0.712283,0.385668,-0.586441,-3.422698,-2.070796,0.773898, + 0.596352,0.583149,0.551635,-3.498521,-1.762078,0.762472, + 0.77125,0.634502,0.050796,-3.381262,-1.828189,0.697034, + 0.684834,0.490952,-0.538488,-3.339489,-2.328145,0.827572, + 0.403627,0.101273,-0.909302,-3.412068,-2.356105,0.865813, + -0.058899,-0.007802,-0.998233,-3.463753,-2.079892,0.844667, + 0.684834,0.490952,-0.538488,-3.339489,-2.328145,0.827572, + -0.058899,-0.007802,-0.998233,-3.463753,-2.079892,0.844667, + 0.712283,0.385668,-0.586441,-3.422698,-2.070796,0.773898, + 0.722847,0.455753,-0.519404,-3.297886,-2.54902,0.861657, + 0.308087,0.149605,-0.939522,-3.372066,-2.569159,0.904785, + 0.403627,0.101273,-0.909302,-3.412068,-2.356105,0.865813, + 0.722847,0.455753,-0.519404,-3.297886,-2.54902,0.861657, + 0.403627,0.101273,-0.909302,-3.412068,-2.356105,0.865813, + 0.684834,0.490952,-0.538488,-3.339489,-2.328145,0.827572, + 0.403627,0.101273,-0.909302,-3.412068,-2.356105,0.865813, + -0.948593,-0.185732,-0.25627,-3.389388,-2.305625,0.950348, + -0.948593,-0.185732,-0.25627,-3.451965,-2.077314,0.931974, + 0.403627,0.101273,-0.909302,-3.412068,-2.356105,0.865813, + -0.948593,-0.185732,-0.25627,-3.451965,-2.077314,0.931974, + -0.058899,-0.007802,-0.998233,-3.463753,-2.079892,0.844667, + 0.308087,0.149605,-0.939522,-3.372066,-2.569159,0.904785, + -0.99734,0.010762,-0.072093,-3.347304,-2.573628,0.955211, + -0.948593,-0.185732,-0.25627,-3.389388,-2.305625,0.950348, + 0.308087,0.149605,-0.939522,-3.372066,-2.569159,0.904785, + -0.948593,-0.185732,-0.25627,-3.389388,-2.305625,0.950348, + 0.403627,0.101273,-0.909302,-3.412068,-2.356105,0.865813, + -0.058899,-0.007802,-0.998233,-3.463753,-2.079892,0.844667, + -0.948593,-0.185732,-0.25627,-3.451965,-2.077314,0.931974, + 0.637284,0.689194,0.344791,-3.49052,-1.760417,0.903104, + -0.058899,-0.007802,-0.998233,-3.463753,-2.079892,0.844667, + 0.637284,0.689194,0.344791,-3.49052,-1.760417,0.903104, + 0.596352,0.583149,0.551635,-3.498521,-1.762078,0.762472, + -0.508357,0.250892,0.823787,-3.342096,-1.533989,0.921628, + 0.737412,0.542596,0.402261,-3.36599,-1.48517,0.888076, + 0.637284,0.689194,0.344791,-3.49052,-1.760417,0.903104, + -0.508357,0.250892,0.823787,-3.342096,-1.533989,0.921628, + 0.637284,0.689194,0.344791,-3.49052,-1.760417,0.903104, + -0.46316,0.228643,0.856274,-3.357996,-1.811803,0.975625, + -0.430524,-0.648446,0.627828,2.02453,-2.195334,0.811284, + 0.626232,0.565165,0.53705,1.98533,-2.221319,0.893145, + 0.768073,0.514956,0.380637,1.930747,-2.463535,0.894743, + -0.430524,-0.648446,0.627828,2.02453,-2.195334,0.811284, + 0.768073,0.514956,0.380637,1.930747,-2.463535,0.894743, + 0.213417,-0.547722,0.808983,1.953911,-2.462233,0.830594, + -0.492627,0.113675,0.862784,2.047696,-2.050138,0.814712, + 0.52783,0.437826,0.727807,2.013095,-2.051912,0.911043, + 0.626232,0.565165,0.53705,1.98533,-2.221319,0.893145, + -0.492627,0.113675,0.862784,2.047696,-2.050138,0.814712, + 0.626232,0.565165,0.53705,1.98533,-2.221319,0.893145, + -0.430524,-0.648446,0.627828,2.02453,-2.195334,0.811284, + -0.495591,0.225654,0.838731,2.053108,-1.738285,0.824853, + 0.862528,0.499882,-0.078511,2.021591,-1.755289,0.912093, + 0.52783,0.437826,0.727807,2.013095,-2.051912,0.911043, + -0.495591,0.225654,0.838731,2.053108,-1.738285,0.824853, + 0.52783,0.437826,0.727807,2.013095,-2.051912,0.911043, + -0.492627,0.113675,0.862784,2.047696,-2.050138,0.814712, + -0.541077,0.245809,0.804247,2.059844,-1.561331,0.858957, + 0.872426,0.488735,-0.003223,2.036036,-1.57908,0.967151, + 0.862528,0.499882,-0.078511,2.021591,-1.755289,0.912093, + -0.541077,0.245809,0.804247,2.059844,-1.561331,0.858957, + 0.862528,0.499882,-0.078511,2.021591,-1.755289,0.912093, + -0.495591,0.225654,0.838731,2.053108,-1.738285,0.824853, + 0.21689,-0.976039,-0.017487,1.718315,-2.775468,0.921796, + -0.4909,0.016111,-0.871067,1.771416,-2.769024,0.9461, + -0.184432,-0.109597,-0.976716,1.737623,-2.485017,0.918334, + 0.21689,-0.976039,-0.017487,1.718315,-2.775468,0.921796, + -0.184432,-0.109597,-0.976716,1.737623,-2.485017,0.918334, + 0.383337,-0.601981,-0.700479,1.678986,-2.513137,0.891745, + 0.383337,-0.601981,-0.700479,1.678986,-2.513137,0.891745, + -0.184432,-0.109597,-0.976716,1.737623,-2.485017,0.918334, + -0.554502,-0.046423,-0.830886,1.710406,-2.272223,0.954296, + 0.383337,-0.601981,-0.700479,1.678986,-2.513137,0.891745, + -0.554502,-0.046423,-0.830886,1.710406,-2.272223,0.954296, + -0.701253,0.091018,-0.707079,1.648793,-2.280014,0.929365, + -0.701253,0.091018,-0.707079,1.648793,-2.280014,0.929365, + -0.554502,-0.046423,-0.830886,1.710406,-2.272223,0.954296, + -0.554151,-0.205896,-0.80655,1.720031,-2.105568,0.971354, + -0.701253,0.091018,-0.707079,1.648793,-2.280014,0.929365, + -0.554151,-0.205896,-0.80655,1.720031,-2.105568,0.971354, + -0.706628,-0.050081,-0.705811,1.6249,-2.087301,0.963391, + -0.706628,-0.050081,-0.705811,1.6249,-2.087301,0.963391, + -0.554151,-0.205896,-0.80655,1.720031,-2.105568,0.971354, + -0.343436,-0.507052,-0.790537,1.717145,-1.80953,1.004092, + -0.706628,-0.050081,-0.705811,1.6249,-2.087301,0.963391, + -0.343436,-0.507052,-0.790537,1.717145,-1.80953,1.004092, + -0.990285,-0.10079,-0.095796,1.572979,-1.827591,0.985823, + -0.990285,-0.10079,-0.095796,1.572979,-1.827591,0.985823, + -0.343436,-0.507052,-0.790537,1.717145,-1.80953,1.004092, + 0.056398,-0.684481,-0.726846,1.650318,-1.645881,1.053347, + -0.990285,-0.10079,-0.095796,1.572979,-1.827591,0.985823, + 0.056398,-0.684481,-0.726846,1.650318,-1.645881,1.053347, + -0.404532,-0.045989,0.913367,1.54175,-1.643613,1.01419, + 0.717573,0.343682,-0.605782,1.655948,-2.520927,0.844269, + 0.383337,-0.601981,-0.700479,1.678986,-2.513137,0.891745, + -0.701253,0.091018,-0.707079,1.648793,-2.280014,0.929365, + 0.717573,0.343682,-0.605782,1.655948,-2.520927,0.844269, + -0.701253,0.091018,-0.707079,1.648793,-2.280014,0.929365, + 0.743894,0.373896,-0.553916,1.586321,-2.273752,0.880969, + 0.743894,0.373896,-0.553916,1.586321,-2.273752,0.880969, + -0.701253,0.091018,-0.707079,1.648793,-2.280014,0.929365, + -0.706628,-0.050081,-0.705811,1.6249,-2.087301,0.963391, + 0.743894,0.373896,-0.553916,1.586321,-2.273752,0.880969, + -0.706628,-0.050081,-0.705811,1.6249,-2.087301,0.963391, + 0.752232,0.244351,-0.611914,1.529305,-2.092083,0.887353, + 0.752232,0.244351,-0.611914,1.529305,-2.092083,0.887353, + -0.706628,-0.050081,-0.705811,1.6249,-2.087301,0.963391, + -0.990285,-0.10079,-0.095796,1.572979,-1.827591,0.985823, + 0.752232,0.244351,-0.611914,1.529305,-2.092083,0.887353, + -0.990285,-0.10079,-0.095796,1.572979,-1.827591,0.985823, + 0.866543,0.493887,0.071972,1.508714,-1.808578,0.934359, + 0.866543,0.493887,0.071972,1.508714,-1.808578,0.934359, + -0.990285,-0.10079,-0.095796,1.572979,-1.827591,0.985823, + -0.404532,-0.045989,0.913367,1.54175,-1.643613,1.01419, + 0.866543,0.493887,0.071972,1.508714,-1.808578,0.934359, + -0.404532,-0.045989,0.913367,1.54175,-1.643613,1.01419, + 0.874983,0.217677,0.432459,1.480629,-1.640132,0.953447, + 0.79991,0.598082,0.049409,1.663494,-2.485963,0.790773, + 0.717573,0.343682,-0.605782,1.655948,-2.520927,0.844269, + 0.743894,0.373896,-0.553916,1.586321,-2.273752,0.880969, + 0.79991,0.598082,0.049409,1.663494,-2.485963,0.790773, + 0.743894,0.373896,-0.553916,1.586321,-2.273752,0.880969, + 0.963394,-0.268066,0.003702,1.60129,-2.267132,0.787696, + 0.963394,-0.268066,0.003702,1.60129,-2.267132,0.787696, + 0.743894,0.373896,-0.553916,1.586321,-2.273752,0.880969, + 0.752232,0.244351,-0.611914,1.529305,-2.092083,0.887353, + 0.963394,-0.268066,0.003702,1.60129,-2.267132,0.787696, + 0.752232,0.244351,-0.611914,1.529305,-2.092083,0.887353, + 0.714275,0.465374,-0.522723,1.544087,-2.080722,0.786432, + 0.714275,0.465374,-0.522723,1.544087,-2.080722,0.786432, + 0.752232,0.244351,-0.611914,1.529305,-2.092083,0.887353, + 0.866543,0.493887,0.071972,1.508714,-1.808578,0.934359, + 0.714275,0.465374,-0.522723,1.544087,-2.080722,0.786432, + 0.866543,0.493887,0.071972,1.508714,-1.808578,0.934359, + 0.81992,-0.126246,-0.558385,1.473886,-1.818947,0.799576, + 0.81992,-0.126246,-0.558385,1.473886,-1.818947,0.799576, + 0.866543,0.493887,0.071972,1.508714,-1.808578,0.934359, + 0.874983,0.217677,0.432459,1.480629,-1.640132,0.953447, + 0.81992,-0.126246,-0.558385,1.473886,-1.818947,0.799576, + 0.874983,0.217677,0.432459,1.480629,-1.640132,0.953447, + 0.751148,0.43192,-0.49922,1.451825,-1.576856,0.702758, + 0.331576,0.146631,-0.931964,1.756349,-2.446399,0.705428, + 0.79991,0.598082,0.049409,1.663494,-2.485963,0.790773, + 0.963394,-0.268066,0.003702,1.60129,-2.267132,0.787696, + 0.331576,0.146631,-0.931964,1.756349,-2.446399,0.705428, + 0.963394,-0.268066,0.003702,1.60129,-2.267132,0.787696, + 0.43336,0.0979,-0.895888,1.677597,-2.237953,0.696318, + 0.43336,0.0979,-0.895888,1.677597,-2.237953,0.696318, + 0.963394,-0.268066,0.003702,1.60129,-2.267132,0.787696, + 0.714275,0.465374,-0.522723,1.544087,-2.080722,0.786432, + 0.43336,0.0979,-0.895888,1.677597,-2.237953,0.696318, + 0.714275,0.465374,-0.522723,1.544087,-2.080722,0.786432, + 0.261981,0.048424,-0.963857,1.643403,-2.076583,0.689565, + 0.261981,0.048424,-0.963857,1.643403,-2.076583,0.689565, + 0.714275,0.465374,-0.522723,1.544087,-2.080722,0.786432, + 0.81992,-0.126246,-0.558385,1.473886,-1.818947,0.799576, + 0.261981,0.048424,-0.963857,1.643403,-2.076583,0.689565, + 0.81992,-0.126246,-0.558385,1.473886,-1.818947,0.799576, + 0.79444,0.150525,-0.588393,1.596751,-1.722028,0.684655, + 0.79444,0.150525,-0.588393,1.596751,-1.722028,0.684655, + 0.81992,-0.126246,-0.558385,1.473886,-1.818947,0.799576, + 0.751148,0.43192,-0.49922,1.451825,-1.576856,0.702758, + 0.79444,0.150525,-0.588393,1.596751,-1.722028,0.684655, + 0.751148,0.43192,-0.49922,1.451825,-1.576856,0.702758, + 0.24139,0.178826,-0.953809,1.599889,-1.595526,0.623185, + -0.440199,0.219838,0.870572,1.960643,-2.71286,0.90089, + 0.636282,0.100894,0.76483,1.994078,-2.713047,0.824553, + 0.213417,-0.547722,0.808983,1.953911,-2.462233,0.830594, + -0.440199,0.219838,0.870572,1.960643,-2.71286,0.90089, + 0.213417,-0.547722,0.808983,1.953911,-2.462233,0.830594, + 0.768073,0.514956,0.380637,1.930747,-2.463535,0.894743, + -0.90358,0.003168,0.428409,1.880971,-2.733242,0.8902, + -0.440199,0.219838,0.870572,1.960643,-2.71286,0.90089, + 0.768073,0.514956,0.380637,1.930747,-2.463535,0.894743, + -0.90358,0.003168,0.428409,1.880971,-2.733242,0.8902, + 0.768073,0.514956,0.380637,1.930747,-2.463535,0.894743, + -0.874488,-0.088621,0.476882,1.864064,-2.469953,0.935601, + 0.862528,0.499882,-0.078511,2.021591,-1.755289,0.912093, + 0.872426,0.488735,-0.003223,2.036036,-1.57908,0.967151, + -0.987313,0.097591,-0.125253,1.937009,-1.625419,1.026843, + 0.862528,0.499882,-0.078511,2.021591,-1.755289,0.912093, + -0.987313,0.097591,-0.125253,1.937009,-1.625419,1.026843, + -0.997638,0.009858,-0.067986,1.941767,-1.759457,0.997454, + 0.52783,0.437826,0.727807,2.013095,-2.051912,0.911043, + 0.862528,0.499882,-0.078511,2.021591,-1.755289,0.912093, + -0.997638,0.009858,-0.067986,1.941767,-1.759457,0.997454, + 0.52783,0.437826,0.727807,2.013095,-2.051912,0.911043, + -0.997638,0.009858,-0.067986,1.941767,-1.759457,0.997454, + 0.21581,0.484483,0.847763,1.918641,-2.083654,1.001275, + -0.874488,-0.088621,0.476882,1.864064,-2.469953,0.935601, + 0.768073,0.514956,0.380637,1.930747,-2.463535,0.894743, + 0.626232,0.565165,0.53705,1.98533,-2.221319,0.893145, + -0.874488,-0.088621,0.476882,1.864064,-2.469953,0.935601, + 0.626232,0.565165,0.53705,1.98533,-2.221319,0.893145, + -0.783521,-0.393963,0.480508,1.90637,-2.282284,0.964887, + 0.626232,0.565165,0.53705,1.98533,-2.221319,0.893145, + 0.52783,0.437826,0.727807,2.013095,-2.051912,0.911043, + 0.21581,0.484483,0.847763,1.918641,-2.083654,1.001275, + 0.626232,0.565165,0.53705,1.98533,-2.221319,0.893145, + 0.21581,0.484483,0.847763,1.918641,-2.083654,1.001275, + -0.783521,-0.393963,0.480508,1.90637,-2.282284,0.964887, + -0.062994,-0.00854,-0.997977,1.830669,-2.736121,0.903313, + -0.955753,-0.169718,-0.240275,1.801127,-2.48469,0.938593, + -0.184432,-0.109597,-0.976716,1.737623,-2.485017,0.918334, + -0.062994,-0.00854,-0.997977,1.830669,-2.736121,0.903313, + -0.184432,-0.109597,-0.976716,1.737623,-2.485017,0.918334, + -0.4909,0.016111,-0.871067,1.771416,-2.769024,0.9461, + -0.062994,-0.00854,-0.997977,1.830669,-2.736121,0.903313, + -0.90358,0.003168,0.428409,1.880971,-2.733242,0.8902, + -0.874488,-0.088621,0.476882,1.864064,-2.469953,0.935601, + -0.062994,-0.00854,-0.997977,1.830669,-2.736121,0.903313, + -0.874488,-0.088621,0.476882,1.864064,-2.469953,0.935601, + -0.955753,-0.169718,-0.240275,1.801127,-2.48469,0.938593, + -0.150944,-0.987886,-0.036012,1.818846,-1.756976,1.023593, + -0.937976,-0.320543,-0.132115,1.804927,-1.581954,1.089198, + 0.056398,-0.684481,-0.726846,1.650318,-1.645881,1.053347, + -0.150944,-0.987886,-0.036012,1.818846,-1.756976,1.023593, + 0.056398,-0.684481,-0.726846,1.650318,-1.645881,1.053347, + -0.343436,-0.507052,-0.790537,1.717145,-1.80953,1.004092, + -0.630099,-0.773677,-0.066329,1.839224,-2.109267,0.998351, + -0.150944,-0.987886,-0.036012,1.818846,-1.756976,1.023593, + -0.343436,-0.507052,-0.790537,1.717145,-1.80953,1.004092, + -0.630099,-0.773677,-0.066329,1.839224,-2.109267,0.998351, + -0.343436,-0.507052,-0.790537,1.717145,-1.80953,1.004092, + -0.554151,-0.205896,-0.80655,1.720031,-2.105568,0.971354, + -0.967491,-0.143323,-0.208372,1.818266,-2.313852,0.968652, + -0.630099,-0.773677,-0.066329,1.839224,-2.109267,0.998351, + -0.554151,-0.205896,-0.80655,1.720031,-2.105568,0.971354, + -0.967491,-0.143323,-0.208372,1.818266,-2.313852,0.968652, + -0.554151,-0.205896,-0.80655,1.720031,-2.105568,0.971354, + -0.554502,-0.046423,-0.830886,1.710406,-2.272223,0.954296, + -0.955753,-0.169718,-0.240275,1.801127,-2.48469,0.938593, + -0.967491,-0.143323,-0.208372,1.818266,-2.313852,0.968652, + -0.554502,-0.046423,-0.830886,1.710406,-2.272223,0.954296, + -0.955753,-0.169718,-0.240275,1.801127,-2.48469,0.938593, + -0.554502,-0.046423,-0.830886,1.710406,-2.272223,0.954296, + -0.184432,-0.109597,-0.976716,1.737623,-2.485017,0.918334, + -0.997638,0.009858,-0.067986,1.941767,-1.759457,0.997454, + -0.987313,0.097591,-0.125253,1.937009,-1.625419,1.026843, + -0.937976,-0.320543,-0.132115,1.804927,-1.581954,1.089198, + -0.997638,0.009858,-0.067986,1.941767,-1.759457,0.997454, + -0.937976,-0.320543,-0.132115,1.804927,-1.581954,1.089198, + -0.150944,-0.987886,-0.036012,1.818846,-1.756976,1.023593, + 0.21581,0.484483,0.847763,1.918641,-2.083654,1.001275, + -0.997638,0.009858,-0.067986,1.941767,-1.759457,0.997454, + -0.150944,-0.987886,-0.036012,1.818846,-1.756976,1.023593, + 0.21581,0.484483,0.847763,1.918641,-2.083654,1.001275, + -0.150944,-0.987886,-0.036012,1.818846,-1.756976,1.023593, + -0.630099,-0.773677,-0.066329,1.839224,-2.109267,0.998351, + -0.783521,-0.393963,0.480508,1.90637,-2.282284,0.964887, + 0.21581,0.484483,0.847763,1.918641,-2.083654,1.001275, + -0.630099,-0.773677,-0.066329,1.839224,-2.109267,0.998351, + -0.783521,-0.393963,0.480508,1.90637,-2.282284,0.964887, + -0.630099,-0.773677,-0.066329,1.839224,-2.109267,0.998351, + -0.967491,-0.143323,-0.208372,1.818266,-2.313852,0.968652, + -0.874488,-0.088621,0.476882,1.864064,-2.469953,0.935601, + -0.783521,-0.393963,0.480508,1.90637,-2.282284,0.964887, + -0.967491,-0.143323,-0.208372,1.818266,-2.313852,0.968652, + -0.874488,-0.088621,0.476882,1.864064,-2.469953,0.935601, + -0.967491,-0.143323,-0.208372,1.818266,-2.313852,0.968652, + -0.955753,-0.169718,-0.240275,1.801127,-2.48469,0.938593, + 0.030762,-0.124297,-0.991768,1.736425,-2.743683,0.736866, + 0.79991,0.598082,0.049409,1.663494,-2.485963,0.790773, + 0.331576,0.146631,-0.931964,1.756349,-2.446399,0.705428, + 0.030762,-0.124297,-0.991768,1.736425,-2.743683,0.736866, + 0.331576,0.146631,-0.931964,1.756349,-2.446399,0.705428, + 0.672894,0.661099,0.331907,1.841282,-2.716008,0.708009, + 0.79444,0.150525,-0.588393,1.596751,-1.722028,0.684655, + 0.24139,0.178826,-0.953809,1.599889,-1.595526,0.623185, + 0.776291,-0.374867,0.5068,1.721211,-1.590185,0.601932, + 0.79444,0.150525,-0.588393,1.596751,-1.722028,0.684655, + 0.776291,-0.374867,0.5068,1.721211,-1.590185,0.601932, + 0.726897,-0.546447,0.415952,1.740323,-1.67983,0.664098, + 0.261981,0.048424,-0.963857,1.643403,-2.076583,0.689565, + 0.79444,0.150525,-0.588393,1.596751,-1.722028,0.684655, + 0.726897,-0.546447,0.415952,1.740323,-1.67983,0.664098, + 0.261981,0.048424,-0.963857,1.643403,-2.076583,0.689565, + 0.726897,-0.546447,0.415952,1.740323,-1.67983,0.664098, + 0.81802,-0.47123,0.329827,1.747671,-2.067518,0.638841, + 0.43336,0.0979,-0.895888,1.677597,-2.237953,0.696318, + 0.261981,0.048424,-0.963857,1.643403,-2.076583,0.689565, + 0.81802,-0.47123,0.329827,1.747671,-2.067518,0.638841, + 0.43336,0.0979,-0.895888,1.677597,-2.237953,0.696318, + 0.81802,-0.47123,0.329827,1.747671,-2.067518,0.638841, + 0.247956,0.087485,-0.964813,1.772999,-2.230292,0.64494, + 0.030762,-0.124297,-0.991768,1.736425,-2.743683,0.736866, + -0.020456,0.943466,0.330837,1.700797,-2.794792,0.82425, + 0.717573,0.343682,-0.605782,1.655948,-2.520927,0.844269, + 0.030762,-0.124297,-0.991768,1.736425,-2.743683,0.736866, + 0.717573,0.343682,-0.605782,1.655948,-2.520927,0.844269, + 0.79991,0.598082,0.049409,1.663494,-2.485963,0.790773, + -0.753891,0.130682,0.643872,2.001343,-2.847715,0.762517, + -0.074103,0.409269,0.909399,1.972647,-2.728848,0.772496, + 0.636282,0.100894,0.76483,1.994078,-2.713047,0.824553, + -0.753891,0.130682,0.643872,2.001343,-2.847715,0.762517, + 0.636282,0.100894,0.76483,1.994078,-2.713047,0.824553, + -0.820357,0.160676,0.548815,2.057496,-2.887282,0.844225, + 0.225987,0.181604,-0.957053,1.947264,-2.443232,0.732587, + -0.074103,0.409269,0.909399,1.972647,-2.728848,0.772496, + -0.545598,-0.330416,0.770161,1.884318,-2.724404,0.701999, + 0.225987,0.181604,-0.957053,1.947264,-2.443232,0.732587, + -0.545598,-0.330416,0.770161,1.884318,-2.724404,0.701999, + 0.229413,0.089674,-0.96919,1.828658,-2.477348,0.67347, + -0.121543,0.046,-0.99152,1.921881,-2.157616,0.692678, + 0.225987,0.181604,-0.957053,1.947264,-2.443232,0.732587, + 0.229413,0.089674,-0.96919,1.828658,-2.477348,0.67347, + -0.121543,0.046,-0.99152,1.921881,-2.157616,0.692678, + 0.229413,0.089674,-0.96919,1.828658,-2.477348,0.67347, + 0.247956,0.087485,-0.964813,1.772999,-2.230292,0.64494, + -0.545598,-0.330416,0.770161,1.884318,-2.724404,0.701999, + 0.672894,0.661099,0.331907,1.841282,-2.716008,0.708009, + 0.331576,0.146631,-0.931964,1.756349,-2.446399,0.705428, + -0.545598,-0.330416,0.770161,1.884318,-2.724404,0.701999, + 0.331576,0.146631,-0.931964,1.756349,-2.446399,0.705428, + 0.229413,0.089674,-0.96919,1.828658,-2.477348,0.67347, + 0.331576,0.146631,-0.931964,1.756349,-2.446399,0.705428, + 0.43336,0.0979,-0.895888,1.677597,-2.237953,0.696318, + 0.247956,0.087485,-0.964813,1.772999,-2.230292,0.64494, + 0.331576,0.146631,-0.931964,1.756349,-2.446399,0.705428, + 0.247956,0.087485,-0.964813,1.772999,-2.230292,0.64494, + 0.229413,0.089674,-0.96919,1.828658,-2.477348,0.67347, + 0.636282,0.100894,0.76483,1.994078,-2.713047,0.824553, + -0.074103,0.409269,0.909399,1.972647,-2.728848,0.772496, + 0.225987,0.181604,-0.957053,1.947264,-2.443232,0.732587, + 0.636282,0.100894,0.76483,1.994078,-2.713047,0.824553, + 0.225987,0.181604,-0.957053,1.947264,-2.443232,0.732587, + 0.213417,-0.547722,0.808983,1.953911,-2.462233,0.830594, + 0.726897,-0.546447,0.415952,1.740323,-1.67983,0.664098, + 0.776291,-0.374867,0.5068,1.721211,-1.590185,0.601932, + -0.086361,-0.084973,0.992634,1.963153,-1.588839,0.612861, + 0.726897,-0.546447,0.415952,1.740323,-1.67983,0.664098, + -0.086361,-0.084973,0.992634,1.963153,-1.588839,0.612861, + 0.313529,0.096126,-0.944701,1.991892,-1.7484,0.65277, + 0.81802,-0.47123,0.329827,1.747671,-2.067518,0.638841, + 0.726897,-0.546447,0.415952,1.740323,-1.67983,0.664098, + 0.313529,0.096126,-0.944701,1.991892,-1.7484,0.65277, + 0.81802,-0.47123,0.329827,1.747671,-2.067518,0.638841, + 0.313529,0.096126,-0.944701,1.991892,-1.7484,0.65277, + 0.761939,0.13671,-0.633055,1.945206,-2.015769,0.672724, + 0.313529,0.096126,-0.944701,1.991892,-1.7484,0.65277, + -0.086361,-0.084973,0.992634,1.963153,-1.588839,0.612861, + -0.541077,0.245809,0.804247,2.059844,-1.561331,0.858957, + 0.313529,0.096126,-0.944701,1.991892,-1.7484,0.65277, + -0.541077,0.245809,0.804247,2.059844,-1.561331,0.858957, + -0.495591,0.225654,0.838731,2.053108,-1.738285,0.824853, + 0.761939,0.13671,-0.633055,1.945206,-2.015769,0.672724, + 0.313529,0.096126,-0.944701,1.991892,-1.7484,0.65277, + -0.495591,0.225654,0.838731,2.053108,-1.738285,0.824853, + 0.761939,0.13671,-0.633055,1.945206,-2.015769,0.672724, + -0.495591,0.225654,0.838731,2.053108,-1.738285,0.824853, + -0.492627,0.113675,0.862784,2.047696,-2.050138,0.814712, + -0.121543,0.046,-0.99152,1.921881,-2.157616,0.692678, + 0.761939,0.13671,-0.633055,1.945206,-2.015769,0.672724, + -0.492627,0.113675,0.862784,2.047696,-2.050138,0.814712, + -0.121543,0.046,-0.99152,1.921881,-2.157616,0.692678, + -0.492627,0.113675,0.862784,2.047696,-2.050138,0.814712, + -0.430524,-0.648446,0.627828,2.02453,-2.195334,0.811284, + 0.225987,0.181604,-0.957053,1.947264,-2.443232,0.732587, + -0.121543,0.046,-0.99152,1.921881,-2.157616,0.692678, + -0.430524,-0.648446,0.627828,2.02453,-2.195334,0.811284, + 0.225987,0.181604,-0.957053,1.947264,-2.443232,0.732587, + -0.430524,-0.648446,0.627828,2.02453,-2.195334,0.811284, + 0.213417,-0.547722,0.808983,1.953911,-2.462233,0.830594, + 0.303379,-0.73119,0.611002,2.126237,-1.330172,0.721011, + 0.383978,-0.566345,0.729256,2.158051,-1.209613,0.783941, + -0.671694,-0.023528,0.740455,2.141273,-1.234642,0.941254, + 0.303379,-0.73119,0.611002,2.126237,-1.330172,0.721011, + -0.671694,-0.023528,0.740455,2.141273,-1.234642,0.941254, + -0.562282,-0.328887,0.758731,2.111557,-1.376942,0.89657, + -0.562282,-0.328887,0.758731,2.111557,-1.376942,0.89657, + -0.671694,-0.023528,0.740455,2.141273,-1.234642,0.941254, + -0.088841,0.02472,0.995739,2.099566,-1.259996,1.055763, + -0.562282,-0.328887,0.758731,2.111557,-1.376942,0.89657, + -0.088841,0.02472,0.995739,2.099566,-1.259996,1.055763, + 0.157806,0.230905,0.960094,2.071448,-1.410118,1.006192, + 0.157806,0.230905,0.960094,2.071448,-1.410118,1.006192, + -0.088841,0.02472,0.995739,2.099566,-1.259996,1.055763, + 0.57446,0.218241,0.788902,1.966698,-1.22816,1.153716, + 0.157806,0.230905,0.960094,2.071448,-1.410118,1.006192, + 0.57446,0.218241,0.788902,1.966698,-1.22816,1.153716, + -0.144755,0.439659,0.886423,1.974215,-1.469208,1.068951, + -0.144755,0.439659,0.886423,1.974215,-1.469208,1.068951, + 0.57446,0.218241,0.788902,1.966698,-1.22816,1.153716, + 0.526213,0.349004,0.775433,1.805207,-1.268427,1.165317, + -0.144755,0.439659,0.886423,1.974215,-1.469208,1.068951, + 0.526213,0.349004,0.775433,1.805207,-1.268427,1.165317, + 0.339699,0.626415,0.701576,1.801794,-1.465464,1.129277, + 0.339699,0.626415,0.701576,1.801794,-1.465464,1.129277, + 0.526213,0.349004,0.775433,1.805207,-1.268427,1.165317, + 0.926951,0.366239,-0.081429,1.601721,-1.262359,1.14142, + 0.339699,0.626415,0.701576,1.801794,-1.465464,1.129277, + 0.926951,0.366239,-0.081429,1.601721,-1.262359,1.14142, + 0.457853,0.537523,0.708124,1.612396,-1.485728,1.099731, + 0.457853,0.537523,0.708124,1.612396,-1.485728,1.099731, + 0.926951,0.366239,-0.081429,1.601721,-1.262359,1.14142, + -0.496829,-0.096649,0.86245,1.49748,-1.283201,1.088258, + 0.457853,0.537523,0.708124,1.612396,-1.485728,1.099731, + -0.496829,-0.096649,0.86245,1.49748,-1.283201,1.088258, + -0.081045,0.40912,0.908874,1.5167,-1.45305,1.068516, + -0.081045,0.40912,0.908874,1.5167,-1.45305,1.068516, + -0.496829,-0.096649,0.86245,1.49748,-1.283201,1.088258, + 0.013288,-0.297478,0.954636,1.430817,-1.301205,1.024924, + -0.081045,0.40912,0.908874,1.5167,-1.45305,1.068516, + 0.013288,-0.297478,0.954636,1.430817,-1.301205,1.024924, + 0.444124,0.617476,0.649214,1.454817,-1.430228,0.976569, + 0.444124,0.617476,0.649214,1.454817,-1.430228,0.976569, + 0.013288,-0.297478,0.954636,1.430817,-1.301205,1.024924, + -0.228294,-0.186048,0.955651,1.348219,-1.282064,0.845204, + 0.444124,0.617476,0.649214,1.454817,-1.430228,0.976569, + -0.228294,-0.186048,0.955651,1.348219,-1.282064,0.845204, + 0.010538,0.399391,0.91672,1.328862,-1.352627,0.758733, + 0.383978,-0.566345,0.729256,2.158051,-1.209613,0.783941, + 0.424286,-0.254348,0.869073,2.180012,-1.130557,0.821812, + -0.217942,-0.897186,-0.384133,2.17745,-1.127765,0.974416, + 0.383978,-0.566345,0.729256,2.158051,-1.209613,0.783941, + -0.217942,-0.897186,-0.384133,2.17745,-1.127765,0.974416, + -0.671694,-0.023528,0.740455,2.141273,-1.234642,0.941254, + -0.671694,-0.023528,0.740455,2.141273,-1.234642,0.941254, + -0.217942,-0.897186,-0.384133,2.17745,-1.127765,0.974416, + -0.069765,-0.126006,-0.989573,2.148553,-1.103067,1.06541, + -0.671694,-0.023528,0.740455,2.141273,-1.234642,0.941254, + -0.069765,-0.126006,-0.989573,2.148553,-1.103067,1.06541, + -0.088841,0.02472,0.995739,2.099566,-1.259996,1.055763, + -0.088841,0.02472,0.995739,2.099566,-1.259996,1.055763, + -0.069765,-0.126006,-0.989573,2.148553,-1.103067,1.06541, + -0.1083,-0.048546,-0.992932,2.024692,-1.074646,1.172465, + -0.088841,0.02472,0.995739,2.099566,-1.259996,1.055763, + -0.1083,-0.048546,-0.992932,2.024692,-1.074646,1.172465, + 0.57446,0.218241,0.788902,1.966698,-1.22816,1.153716, + 0.57446,0.218241,0.788902,1.966698,-1.22816,1.153716, + -0.1083,-0.048546,-0.992932,2.024692,-1.074646,1.172465, + -0.084936,-0.226589,-0.97028,1.838895,-1.087204,1.201408, + 0.57446,0.218241,0.788902,1.966698,-1.22816,1.153716, + -0.084936,-0.226589,-0.97028,1.838895,-1.087204,1.201408, + 0.526213,0.349004,0.775433,1.805207,-1.268427,1.165317, + 0.526213,0.349004,0.775433,1.805207,-1.268427,1.165317, + -0.084936,-0.226589,-0.97028,1.838895,-1.087204,1.201408, + -0.024032,-0.835976,-0.54824,1.645819,-1.087442,1.173773, + 0.526213,0.349004,0.775433,1.805207,-1.268427,1.165317, + -0.024032,-0.835976,-0.54824,1.645819,-1.087442,1.173773, + 0.926951,0.366239,-0.081429,1.601721,-1.262359,1.14142, + 0.926951,0.366239,-0.081429,1.601721,-1.262359,1.14142, + -0.024032,-0.835976,-0.54824,1.645819,-1.087442,1.173773, + -0.044013,0.340434,0.939238,1.524407,-1.125312,1.142248, + 0.926951,0.366239,-0.081429,1.601721,-1.262359,1.14142, + -0.044013,0.340434,0.939238,1.524407,-1.125312,1.142248, + -0.496829,-0.096649,0.86245,1.49748,-1.283201,1.088258, + -0.496829,-0.096649,0.86245,1.49748,-1.283201,1.088258, + -0.044013,0.340434,0.939238,1.524407,-1.125312,1.142248, + 0.186476,0.252953,0.949337,1.438439,-1.148029,1.098069, + -0.496829,-0.096649,0.86245,1.49748,-1.283201,1.088258, + 0.186476,0.252953,0.949337,1.438439,-1.148029,1.098069, + 0.013288,-0.297478,0.954636,1.430817,-1.301205,1.024924, + 0.013288,-0.297478,0.954636,1.430817,-1.301205,1.024924, + 0.186476,0.252953,0.949337,1.438439,-1.148029,1.098069, + 0.43768,-0.823149,-0.361748,1.310865,-1.136322,0.914838, + 0.013288,-0.297478,0.954636,1.430817,-1.301205,1.024924, + 0.43768,-0.823149,-0.361748,1.310865,-1.136322,0.914838, + -0.228294,-0.186048,0.955651,1.348219,-1.282064,0.845204, + -0.086361,-0.084973,0.992634,1.963153,-1.588839,0.612861, + 0.140536,0.558684,0.817388,2.0482,-1.581983,0.555832, + 0.235033,-0.721825,0.650944,2.0796,-1.473377,0.654997, + -0.086361,-0.084973,0.992634,1.963153,-1.588839,0.612861, + 0.235033,-0.721825,0.650944,2.0796,-1.473377,0.654997, + -0.541077,0.245809,0.804247,2.059844,-1.561331,0.858957, + 0.339699,0.626415,0.701576,1.801794,-1.465464,1.129277, + 0.457853,0.537523,0.708124,1.612396,-1.485728,1.099731, + 0.056398,-0.684481,-0.726846,1.650318,-1.645881,1.053347, + 0.339699,0.626415,0.701576,1.801794,-1.465464,1.129277, + 0.056398,-0.684481,-0.726846,1.650318,-1.645881,1.053347, + -0.937976,-0.320543,-0.132115,1.804927,-1.581954,1.089198, + -0.144755,0.439659,0.886423,1.974215,-1.469208,1.068951, + 0.339699,0.626415,0.701576,1.801794,-1.465464,1.129277, + -0.937976,-0.320543,-0.132115,1.804927,-1.581954,1.089198, + -0.144755,0.439659,0.886423,1.974215,-1.469208,1.068951, + -0.937976,-0.320543,-0.132115,1.804927,-1.581954,1.089198, + -0.987313,0.097591,-0.125253,1.937009,-1.625419,1.026843, + 0.157806,0.230905,0.960094,2.071448,-1.410118,1.006192, + -0.144755,0.439659,0.886423,1.974215,-1.469208,1.068951, + -0.987313,0.097591,-0.125253,1.937009,-1.625419,1.026843, + 0.157806,0.230905,0.960094,2.071448,-1.410118,1.006192, + -0.987313,0.097591,-0.125253,1.937009,-1.625419,1.026843, + 0.872426,0.488735,-0.003223,2.036036,-1.57908,0.967151, + -0.562282,-0.328887,0.758731,2.111557,-1.376942,0.89657, + 0.157806,0.230905,0.960094,2.071448,-1.410118,1.006192, + 0.872426,0.488735,-0.003223,2.036036,-1.57908,0.967151, + -0.562282,-0.328887,0.758731,2.111557,-1.376942,0.89657, + 0.872426,0.488735,-0.003223,2.036036,-1.57908,0.967151, + -0.541077,0.245809,0.804247,2.059844,-1.561331,0.858957, + 0.235033,-0.721825,0.650944,2.0796,-1.473377,0.654997, + 0.303379,-0.73119,0.611002,2.126237,-1.330172,0.721011, + -0.562282,-0.328887,0.758731,2.111557,-1.376942,0.89657, + 0.235033,-0.721825,0.650944,2.0796,-1.473377,0.654997, + -0.562282,-0.328887,0.758731,2.111557,-1.376942,0.89657, + -0.541077,0.245809,0.804247,2.059844,-1.561331,0.858957, + 0.080812,0.697931,0.711591,2.229345,-0.992723,0.862826, + -0.887036,-0.210048,-0.411154,2.222082,-0.957342,1.014137, + -0.217942,-0.897186,-0.384133,2.17745,-1.127765,0.974416, + 0.080812,0.697931,0.711591,2.229345,-0.992723,0.862826, + -0.217942,-0.897186,-0.384133,2.17745,-1.127765,0.974416, + 0.424286,-0.254348,0.869073,2.180012,-1.130557,0.821812, + 0.193853,0.161608,0.967628,1.867657,-0.920633,1.206933, + -0.493424,-0.16561,-0.853877,1.635139,-0.965221,1.184968, + -0.024032,-0.835976,-0.54824,1.645819,-1.087442,1.173773, + 0.193853,0.161608,0.967628,1.867657,-0.920633,1.206933, + -0.024032,-0.835976,-0.54824,1.645819,-1.087442,1.173773, + -0.084936,-0.226589,-0.97028,1.838895,-1.087204,1.201408, + -0.819256,-0.566976,0.085772,2.058189,-0.931238,1.163518, + 0.193853,0.161608,0.967628,1.867657,-0.920633,1.206933, + -0.084936,-0.226589,-0.97028,1.838895,-1.087204,1.201408, + -0.819256,-0.566976,0.085772,2.058189,-0.931238,1.163518, + -0.084936,-0.226589,-0.97028,1.838895,-1.087204,1.201408, + -0.1083,-0.048546,-0.992932,2.024692,-1.074646,1.172465, + -0.898389,-0.217201,-0.381735,2.158585,-0.955809,1.113647, + -0.819256,-0.566976,0.085772,2.058189,-0.931238,1.163518, + -0.1083,-0.048546,-0.992932,2.024692,-1.074646,1.172465, + -0.898389,-0.217201,-0.381735,2.158585,-0.955809,1.113647, + -0.1083,-0.048546,-0.992932,2.024692,-1.074646,1.172465, + -0.069765,-0.126006,-0.989573,2.148553,-1.103067,1.06541, + -0.887036,-0.210048,-0.411154,2.222082,-0.957342,1.014137, + -0.898389,-0.217201,-0.381735,2.158585,-0.955809,1.113647, + -0.069765,-0.126006,-0.989573,2.148553,-1.103067,1.06541, + -0.887036,-0.210048,-0.411154,2.222082,-0.957342,1.014137, + -0.069765,-0.126006,-0.989573,2.148553,-1.103067,1.06541, + -0.217942,-0.897186,-0.384133,2.17745,-1.127765,0.974416, + 0.751148,0.43192,-0.49922,1.451825,-1.576856,0.702758, + 0.874983,0.217677,0.432459,1.480629,-1.640132,0.953447, + 0.444124,0.617476,0.649214,1.454817,-1.430228,0.976569, + 0.751148,0.43192,-0.49922,1.451825,-1.576856,0.702758, + 0.444124,0.617476,0.649214,1.454817,-1.430228,0.976569, + 0.010538,0.399391,0.91672,1.328862,-1.352627,0.758733, + 0.43768,-0.823149,-0.361748,1.310865,-1.136322,0.914838, + 0.186476,0.252953,0.949337,1.438439,-1.148029,1.098069, + -0.53197,-0.108751,-0.839751,1.428883,-0.98669,1.133905, + 0.43768,-0.823149,-0.361748,1.310865,-1.136322,0.914838, + -0.53197,-0.108751,-0.839751,1.428883,-0.98669,1.133905, + -0.382074,-0.25681,-0.887732,1.337875,-0.945716,1.021299, + -0.404532,-0.045989,0.913367,1.54175,-1.643613,1.01419, + 0.056398,-0.684481,-0.726846,1.650318,-1.645881,1.053347, + 0.457853,0.537523,0.708124,1.612396,-1.485728,1.099731, + -0.404532,-0.045989,0.913367,1.54175,-1.643613,1.01419, + 0.457853,0.537523,0.708124,1.612396,-1.485728,1.099731, + -0.081045,0.40912,0.908874,1.5167,-1.45305,1.068516, + 0.874983,0.217677,0.432459,1.480629,-1.640132,0.953447, + -0.404532,-0.045989,0.913367,1.54175,-1.643613,1.01419, + -0.081045,0.40912,0.908874,1.5167,-1.45305,1.068516, + 0.874983,0.217677,0.432459,1.480629,-1.640132,0.953447, + -0.081045,0.40912,0.908874,1.5167,-1.45305,1.068516, + 0.444124,0.617476,0.649214,1.454817,-1.430228,0.976569, + -0.044013,0.340434,0.939238,1.524407,-1.125312,1.142248, + -0.024032,-0.835976,-0.54824,1.645819,-1.087442,1.173773, + -0.493424,-0.16561,-0.853877,1.635139,-0.965221,1.184968, + -0.044013,0.340434,0.939238,1.524407,-1.125312,1.142248, + -0.493424,-0.16561,-0.853877,1.635139,-0.965221,1.184968, + -0.570406,-0.192005,-0.798606,1.536037,-0.985876,1.185597, + 0.186476,0.252953,0.949337,1.438439,-1.148029,1.098069, + -0.044013,0.340434,0.939238,1.524407,-1.125312,1.142248, + -0.570406,-0.192005,-0.798606,1.536037,-0.985876,1.185597, + 0.186476,0.252953,0.949337,1.438439,-1.148029,1.098069, + -0.570406,-0.192005,-0.798606,1.536037,-0.985876,1.185597, + -0.53197,-0.108751,-0.839751,1.428883,-0.98669,1.133905, + -0.861251,0.383698,-0.333202,3.247406,2.073333,0, + 0.889638,-0.392482,0.233458,2.985371,1.982663,0, + 0.397823,0.403779,0.823832,3.009101,1.971604,0.03422, + -0.861251,0.383698,-0.333202,3.247406,2.073333,0, + 0.397823,0.403779,0.823832,3.009101,1.971604,0.03422, + 0.662294,0.443714,0.603726,3.233975,2.059193,0.072431, + 0.662294,0.443714,0.603726,3.233975,2.059193,0.072431, + 0.397823,0.403779,0.823832,3.009101,1.971604,0.03422, + 0.449887,0.239005,0.860511,3.036361,1.913989,0.169838, + 0.662294,0.443714,0.603726,3.233975,2.059193,0.072431, + 0.449887,0.239005,0.860511,3.036361,1.913989,0.169838, + 0.693381,0.351142,0.629224,3.252224,2.026347,0.148215, + 0.693381,0.351142,0.629224,3.252224,2.026347,0.148215, + 0.449887,0.239005,0.860511,3.036361,1.913989,0.169838, + 0.525142,-0.062799,0.848695,3.058366,1.773346,0.297337, + 0.693381,0.351142,0.629224,3.252224,2.026347,0.148215, + 0.525142,-0.062799,0.848695,3.058366,1.773346,0.297337, + 0.748939,0.152982,0.644738,3.276333,1.863773,0.294266, + 0.748939,0.152982,0.644738,3.276333,1.863773,0.294266, + 0.525142,-0.062799,0.848695,3.058366,1.773346,0.297337, + 0.561573,-0.148323,0.814024,3.086666,1.632991,0.338863, + 0.748939,0.152982,0.644738,3.276333,1.863773,0.294266, + 0.561573,-0.148323,0.814024,3.086666,1.632991,0.338863, + 0.795625,-0.129968,0.591684,3.337545,1.748927,0.34021, + 0.795625,-0.129968,0.591684,3.337545,1.748927,0.34021, + 0.561573,-0.148323,0.814024,3.086666,1.632991,0.338863, + 0.513731,-0.239493,0.823847,3.115383,1.49239,0.380228, + 0.795625,-0.129968,0.591684,3.337545,1.748927,0.34021, + 0.513731,-0.239493,0.823847,3.115383,1.49239,0.380228, + 0.805898,-0.146097,0.573745,3.377233,1.5878,0.400781, + 0.805898,-0.146097,0.573745,3.377233,1.5878,0.400781, + 0.513731,-0.239493,0.823847,3.115383,1.49239,0.380228, + 0.506924,-0.406124,0.760323,3.163181,1.209972,0.462438, + 0.805898,-0.146097,0.573745,3.377233,1.5878,0.400781, + 0.506924,-0.406124,0.760323,3.163181,1.209972,0.462438, + 0.772313,-0.244122,0.586461,3.47341,1.366149,0.454658, + 0.772313,-0.244122,0.586461,3.47341,1.366149,0.454658, + 0.506924,-0.406124,0.760323,3.163181,1.209972,0.462438, + 0.552633,-0.484765,0.677938,3.189664,0.907503,0.500122, + 0.772313,-0.244122,0.586461,3.47341,1.366149,0.454658, + 0.552633,-0.484765,0.677938,3.189664,0.907503,0.500122, + 0.697438,-0.478568,0.533435,3.528445,1.060127,0.489443, + 0.697438,-0.478568,0.533435,3.528445,1.060127,0.489443, + 0.552633,-0.484765,0.677938,3.189664,0.907503,0.500122, + 0.696414,-0.392791,0.600602,3.280681,0.510802,0.499434, + 0.697438,-0.478568,0.533435,3.528445,1.060127,0.489443, + 0.696414,-0.392791,0.600602,3.280681,0.510802,0.499434, + 0.628361,-0.426126,0.65083,3.559394,0.706516,0.452535, + 0.628361,-0.426126,0.65083,3.559394,0.706516,0.452535, + 0.696414,-0.392791,0.600602,3.280681,0.510802,0.499434, + 0.026499,0.942993,0.331757,3.321825,0.26669,0.46575, + 0.628361,-0.426126,0.65083,3.559394,0.706516,0.452535, + 0.026499,0.942993,0.331757,3.321825,0.26669,0.46575, + 0.065855,0.814333,0.576649,3.61965,0.472046,0.391742, + 0.065855,0.814333,0.576649,3.61965,0.472046,0.391742, + 0.026499,0.942993,0.331757,3.321825,0.26669,0.46575, + 0.019336,0.837694,0.545798,3.36004,0.165487,0.412685, + 0.065855,0.814333,0.576649,3.61965,0.472046,0.391742, + 0.019336,0.837694,0.545798,3.36004,0.165487,0.412685, + 0.187432,0.691784,0.697355,3.641195,0.407454,0.362198, + 0.187432,0.691784,0.697355,3.641195,0.407454,0.362198, + 0.019336,0.837694,0.545798,3.36004,0.165487,0.412685, + 0.05298,0.780732,0.622615,3.378799,0.073736,0.355362, + 0.187432,0.691784,0.697355,3.641195,0.407454,0.362198, + 0.05298,0.780732,0.622615,3.378799,0.073736,0.355362, + 0.328244,0.603535,0.726637,3.67471,0.338839,0.30784, + 0.328244,0.603535,0.726637,3.67471,0.338839,0.30784, + 0.05298,0.780732,0.622615,3.378799,0.073736,0.355362, + 0.115383,0.694945,0.709746,3.43895,-0.08258,0.257015, + 0.328244,0.603535,0.726637,3.67471,0.338839,0.30784, + 0.115383,0.694945,0.709746,3.43895,-0.08258,0.257015, + 0.387394,0.516219,0.763835,3.700363,0.265794,0.240762, + 0.387394,0.516219,0.763835,3.700363,0.265794,0.240762, + 0.115383,0.694945,0.709746,3.43895,-0.08258,0.257015, + 0.146937,0.551946,0.820832,3.514981,-0.121886,0.187589, + 0.387394,0.516219,0.763835,3.700363,0.265794,0.240762, + 0.146937,0.551946,0.820832,3.514981,-0.121886,0.187589, + 0.387987,0.466053,0.795148,3.737014,0.181837,0.176819, + 0.387987,0.466053,0.795148,3.737014,0.181837,0.176819, + 0.146937,0.551946,0.820832,3.514981,-0.121886,0.187589, + 0.431966,-0.771434,0.46722,3.486028,-0.141683,0, + 0.387987,0.466053,0.795148,3.737014,0.181837,0.176819, + 0.431966,-0.771434,0.46722,3.486028,-0.141683,0, + -0.910859,-0.100368,-0.400327,3.731689,0.186391,0, + 0.694153,-0.467999,0.546926,3.454971,2.169877,0, + 0.742962,-0.255405,0.618688,3.4583,2.151656,0.102662, + -0.071584,0.92252,0.379253,3.727093,2.308406,0.150049, + 0.694153,-0.467999,0.546926,3.454971,2.169877,0, + -0.071584,0.92252,0.379253,3.727093,2.308406,0.150049, + 0.431966,-0.771434,-0.46722,3.71636,2.343387,0, + 0.614456,0.489786,0.618509,3.955635,0.432417,0.197586, + 0.338485,-0.103202,-0.935295,3.929251,0.411689,0, + -0.926486,-0.356041,-0.121897,4.126565,0.642027,0, + 0.614456,0.489786,0.618509,3.955635,0.432417,0.197586, + -0.926486,-0.356041,-0.121897,4.126565,0.642027,0, + 0.804239,-0.153549,0.574128,4.120842,0.627141,0.185461, + 0.718673,-0.290446,0.631784,3.889626,0.475277,0.247365, + 0.614456,0.489786,0.618509,3.955635,0.432417,0.197586, + 0.804239,-0.153549,0.574128,4.120842,0.627141,0.185461, + 0.815771,-0.424495,0.392838,3.861841,0.560638,0.311961, + 0.718673,-0.290446,0.631784,3.889626,0.475277,0.247365, + 0.804239,-0.153549,0.574128,4.120842,0.627141,0.185461, + 0.815771,-0.424495,0.392838,3.861841,0.560638,0.311961, + 0.804239,-0.153549,0.574128,4.120842,0.627141,0.185461, + 0.788801,-0.199379,0.581412,4.105198,0.672581,0.300001, + 0.900366,-0.205985,0.38329,3.849352,0.664451,0.387198, + 0.815771,-0.424495,0.392838,3.861841,0.560638,0.311961, + 0.788801,-0.199379,0.581412,4.105198,0.672581,0.300001, + 0.900366,-0.205985,0.38329,3.849352,0.664451,0.387198, + 0.788801,-0.199379,0.581412,4.105198,0.672581,0.300001, + 0.771881,-0.100912,0.627707,4.068249,0.798926,0.400813, + 0.906617,-0.14387,0.39667,3.823137,0.853054,0.461519, + 0.900366,-0.205985,0.38329,3.849352,0.664451,0.387198, + 0.771881,-0.100912,0.627707,4.068249,0.798926,0.400813, + 0.906617,-0.14387,0.39667,3.823137,0.853054,0.461519, + 0.771881,-0.100912,0.627707,4.068249,0.798926,0.400813, + 0.769758,0.095155,0.631204,4.041657,1.039756,0.496922, + 0.908163,-0.140074,0.394486,3.747724,1.184933,0.518662, + 0.906617,-0.14387,0.39667,3.823137,0.853054,0.461519, + 0.769758,0.095155,0.631204,4.041657,1.039756,0.496922, + 0.908163,-0.140074,0.394486,3.747724,1.184933,0.518662, + 0.769758,0.095155,0.631204,4.041657,1.039756,0.496922, + 0.763734,0.228435,0.603761,3.98851,1.297806,0.539537, + 0.907314,0.09913,0.4086,3.650974,1.46374,0.478617, + 0.908163,-0.140074,0.394486,3.747724,1.184933,0.518662, + 0.763734,0.228435,0.603761,3.98851,1.297806,0.539537, + 0.907314,0.09913,0.4086,3.650974,1.46374,0.478617, + 0.763734,0.228435,0.603761,3.98851,1.297806,0.539537, + 0.696162,0.333274,0.635835,3.886058,1.550141,0.50483, + 0.85208,0.278905,0.442914,3.590526,1.70109,0.411994, + 0.907314,0.09913,0.4086,3.650974,1.46374,0.478617, + 0.696162,0.333274,0.635835,3.886058,1.550141,0.50483, + 0.85208,0.278905,0.442914,3.590526,1.70109,0.411994, + 0.696162,0.333274,0.635835,3.886058,1.550141,0.50483, + 0.539114,0.412574,0.734261,3.881998,1.764428,0.476337, + 0.759315,0.386803,0.523282,3.541188,1.849183,0.386366, + 0.85208,0.278905,0.442914,3.590526,1.70109,0.411994, + 0.539114,0.412574,0.734261,3.881998,1.764428,0.476337, + 0.759315,0.386803,0.523282,3.541188,1.849183,0.386366, + 0.539114,0.412574,0.734261,3.881998,1.764428,0.476337, + 0.462789,0.48004,0.745243,3.814876,1.968416,0.443, + 0.636794,0.461927,0.617346,3.479418,1.97825,0.317478, + 0.759315,0.386803,0.523282,3.541188,1.849183,0.386366, + 0.462789,0.48004,0.745243,3.814876,1.968416,0.443, + 0.636794,0.461927,0.617346,3.479418,1.97825,0.317478, + 0.462789,0.48004,0.745243,3.814876,1.968416,0.443, + 0.241303,0.584582,0.77462,3.758215,2.206683,0.323051, + 0.722145,-0.312679,0.617041,3.460196,2.103494,0.180368, + 0.636794,0.461927,0.617346,3.479418,1.97825,0.317478, + 0.241303,0.584582,0.77462,3.758215,2.206683,0.323051, + 0.722145,-0.312679,0.617041,3.460196,2.103494,0.180368, + 0.241303,0.584582,0.77462,3.758215,2.206683,0.323051, + 0.072694,0.752739,0.654294,3.745669,2.266001,0.24193, + 0.742962,-0.255405,0.618688,3.4583,2.151656,0.102662, + 0.722145,-0.312679,0.617041,3.460196,2.103494,0.180368, + 0.072694,0.752739,0.654294,3.745669,2.266001,0.24193, + 0.742962,-0.255405,0.618688,3.4583,2.151656,0.102662, + 0.072694,0.752739,0.654294,3.745669,2.266001,0.24193, + -0.071584,0.92252,0.379253,3.727093,2.308406,0.150049, + -0.560204,0.828355,-0.00034,3.33521,-0.375755,0, + -0.046579,0.627301,0.777383,3.342159,-0.384674,0.201349, + 0.6483,-0.171023,0.741928,3.107533,-0.691019,0.264602, + -0.560204,0.828355,-0.00034,3.33521,-0.375755,0, + 0.6483,-0.171023,0.741928,3.107533,-0.691019,0.264602, + -0.476715,0.879058,0,3.118124,-0.703925,0, + 0.12555,0.440005,0.889176,2.715712,1.828219,0.167709, + -0.926486,-0.356041,0.121897,2.723503,1.898839,0, + 0.536218,-0.84408,0.000006,2.339597,1.807702,0, + 0.12555,0.440005,0.889176,2.715712,1.828219,0.167709, + 0.536218,-0.84408,0.000006,2.339597,1.807702,0, + -0.05128,0.509983,0.858655,2.361089,1.76666,0.202595, + 0.10998,0.376752,0.919762,2.738132,1.687333,0.295046, + 0.12555,0.440005,0.889176,2.715712,1.828219,0.167709, + -0.05128,0.509983,0.858655,2.361089,1.76666,0.202595, + 0.10998,0.376752,0.919762,2.738132,1.687333,0.295046, + -0.05128,0.509983,0.858655,2.361089,1.76666,0.202595, + -0.02226,0.394285,0.918719,2.406969,1.645328,0.341479, + 0.097864,0.250653,0.963118,2.77568,1.53871,0.352829, + 0.10998,0.376752,0.919762,2.738132,1.687333,0.295046, + -0.02226,0.394285,0.918719,2.406969,1.645328,0.341479, + 0.097864,0.250653,0.963118,2.77568,1.53871,0.352829, + -0.02226,0.394285,0.918719,2.406969,1.645328,0.341479, + -0.026262,0.311275,0.949957,2.519027,1.485931,0.422962, + 0.12742,0.021045,0.991626,2.815366,1.377583,0.413399, + 0.097864,0.250653,0.963118,2.77568,1.53871,0.352829, + -0.026262,0.311275,0.949957,2.519027,1.485931,0.422962, + 0.12742,0.021045,0.991626,2.815366,1.377583,0.413399, + -0.026262,0.311275,0.949957,2.519027,1.485931,0.422962, + -0.039079,0.203923,0.978207,2.553871,1.284278,0.512335, + 0.206882,-0.117024,0.971342,2.854291,1.093951,0.49465, + 0.12742,0.021045,0.991626,2.815366,1.377583,0.413399, + -0.039079,0.203923,0.978207,2.553871,1.284278,0.512335, + 0.206882,-0.117024,0.971342,2.854291,1.093951,0.49465, + -0.039079,0.203923,0.978207,2.553871,1.284278,0.512335, + -0.031021,0.098798,0.994624,2.637461,1.01726,0.581611, + 0.218538,-0.213954,0.952084,2.948387,0.783357,0.515058, + 0.206882,-0.117024,0.971342,2.854291,1.093951,0.49465, + -0.031021,0.098798,0.994624,2.637461,1.01726,0.581611, + 0.218538,-0.213954,0.952084,2.948387,0.783357,0.515058, + -0.031021,0.098798,0.994624,2.637461,1.01726,0.581611, + -0.012663,0.029084,0.999497,2.747937,0.712253,0.615674, + 0.304965,-0.136677,0.942505,3.06109,0.397226,0.574193, + 0.218538,-0.213954,0.952084,2.948387,0.783357,0.515058, + -0.012663,0.029084,0.999497,2.747937,0.712253,0.615674, + 0.304965,-0.136677,0.942505,3.06109,0.397226,0.574193, + -0.012663,0.029084,0.999497,2.747937,0.712253,0.615674, + -0.096144,-0.182414,0.97851,2.811504,0.469098,0.657443, + 0.304965,-0.136677,0.942505,3.06109,0.397226,0.574193, + -0.096144,-0.182414,0.97851,2.811504,0.469098,0.657443, + -0.200187,-0.124247,0.971848,2.898733,0.271916,0.651298, + -0.061264,0.921927,0.382487,3.136321,0.171237,0.539896, + 0.304965,-0.136677,0.942505,3.06109,0.397226,0.574193, + -0.200187,-0.124247,0.971848,2.898733,0.271916,0.651298, + -0.061264,0.921927,0.382487,3.136321,0.171237,0.539896, + -0.200187,-0.124247,0.971848,2.898733,0.271916,0.651298, + 0.023112,-0.187685,0.981957,2.91987,0.084875,0.64246, + -0.070642,0.834207,0.546908,3.16616,0.02131,0.457261, + -0.061264,0.921927,0.382487,3.136321,0.171237,0.539896, + 0.023112,-0.187685,0.981957,2.91987,0.084875,0.64246, + -0.070642,0.834207,0.546908,3.16616,0.02131,0.457261, + 0.023112,-0.187685,0.981957,2.91987,0.084875,0.64246, + 0.720876,-0.356662,0.594247,2.953029,-0.12769,0.520499, + -0.055544,0.828008,0.557959,3.199571,-0.153739,0.38015, + -0.070642,0.834207,0.546908,3.16616,0.02131,0.457261, + 0.720876,-0.356662,0.594247,2.953029,-0.12769,0.520499, + -0.055544,0.828008,0.557959,3.199571,-0.153739,0.38015, + 0.720876,-0.356662,0.594247,2.953029,-0.12769,0.520499, + 0.709718,-0.453837,0.538824,2.986408,-0.413503,0.428964, + -0.047374,0.758242,0.65025,3.286426,-0.300744,0.276331, + -0.055544,0.828008,0.557959,3.199571,-0.153739,0.38015, + 0.709718,-0.453837,0.538824,2.986408,-0.413503,0.428964, + -0.047374,0.758242,0.65025,3.286426,-0.300744,0.276331, + 0.709718,-0.453837,0.538824,2.986408,-0.413503,0.428964, + 0.4379,-0.250054,0.863549,3.053144,-0.609681,0.326931, + -0.046579,0.627301,0.777383,3.342159,-0.384674,0.201349, + -0.047374,0.758242,0.65025,3.286426,-0.300744,0.276331, + 0.4379,-0.250054,0.863549,3.053144,-0.609681,0.326931, + -0.046579,0.627301,0.777383,3.342159,-0.384674,0.201349, + 0.4379,-0.250054,0.863549,3.053144,-0.609681,0.326931, + 0.6483,-0.171023,0.741928,3.107533,-0.691019,0.264602, + -0.861251,0.383698,-0.333202,3.247406,2.073333,0, + 0.662294,0.443714,0.603726,3.233975,2.059193,0.072431, + 0.742962,-0.255405,0.618688,3.4583,2.151656,0.102662, + -0.861251,0.383698,-0.333202,3.247406,2.073333,0, + 0.742962,-0.255405,0.618688,3.4583,2.151656,0.102662, + 0.694153,-0.467999,0.546926,3.454971,2.169877,0, + 0.431966,-0.771434,0.46722,3.486028,-0.141683,0, + 0.146937,0.551946,0.820832,3.514981,-0.121886,0.187589, + -0.046579,0.627301,0.777383,3.342159,-0.384674,0.201349, + 0.431966,-0.771434,0.46722,3.486028,-0.141683,0, + -0.046579,0.627301,0.777383,3.342159,-0.384674,0.201349, + -0.560204,0.828355,-0.00034,3.33521,-0.375755,0, + 0.397823,0.403779,0.823832,3.009101,1.971604,0.03422, + 0.889638,-0.392482,0.233458,2.985371,1.982663,0, + -0.926486,-0.356041,0.121897,2.723503,1.898839,0, + 0.449887,0.239005,0.860511,3.036361,1.913989,0.169838, + 0.397823,0.403779,0.823832,3.009101,1.971604,0.03422, + -0.926486,-0.356041,0.121897,2.723503,1.898839,0, + 0.449887,0.239005,0.860511,3.036361,1.913989,0.169838, + -0.926486,-0.356041,0.121897,2.723503,1.898839,0, + 0.12555,0.440005,0.889176,2.715712,1.828219,0.167709, + 0.525142,-0.062799,0.848695,3.058366,1.773346,0.297337, + 0.449887,0.239005,0.860511,3.036361,1.913989,0.169838, + 0.12555,0.440005,0.889176,2.715712,1.828219,0.167709, + 0.525142,-0.062799,0.848695,3.058366,1.773346,0.297337, + 0.12555,0.440005,0.889176,2.715712,1.828219,0.167709, + 0.10998,0.376752,0.919762,2.738132,1.687333,0.295046, + 0.561573,-0.148323,0.814024,3.086666,1.632991,0.338863, + 0.525142,-0.062799,0.848695,3.058366,1.773346,0.297337, + 0.10998,0.376752,0.919762,2.738132,1.687333,0.295046, + 0.561573,-0.148323,0.814024,3.086666,1.632991,0.338863, + 0.10998,0.376752,0.919762,2.738132,1.687333,0.295046, + 0.097864,0.250653,0.963118,2.77568,1.53871,0.352829, + 0.513731,-0.239493,0.823847,3.115383,1.49239,0.380228, + 0.561573,-0.148323,0.814024,3.086666,1.632991,0.338863, + 0.097864,0.250653,0.963118,2.77568,1.53871,0.352829, + 0.513731,-0.239493,0.823847,3.115383,1.49239,0.380228, + 0.097864,0.250653,0.963118,2.77568,1.53871,0.352829, + 0.12742,0.021045,0.991626,2.815366,1.377583,0.413399, + 0.506924,-0.406124,0.760323,3.163181,1.209972,0.462438, + 0.513731,-0.239493,0.823847,3.115383,1.49239,0.380228, + 0.12742,0.021045,0.991626,2.815366,1.377583,0.413399, + 0.506924,-0.406124,0.760323,3.163181,1.209972,0.462438, + 0.12742,0.021045,0.991626,2.815366,1.377583,0.413399, + 0.206882,-0.117024,0.971342,2.854291,1.093951,0.49465, + 0.552633,-0.484765,0.677938,3.189664,0.907503,0.500122, + 0.506924,-0.406124,0.760323,3.163181,1.209972,0.462438, + 0.206882,-0.117024,0.971342,2.854291,1.093951,0.49465, + 0.552633,-0.484765,0.677938,3.189664,0.907503,0.500122, + 0.206882,-0.117024,0.971342,2.854291,1.093951,0.49465, + 0.218538,-0.213954,0.952084,2.948387,0.783357,0.515058, + 0.696414,-0.392791,0.600602,3.280681,0.510802,0.499434, + 0.552633,-0.484765,0.677938,3.189664,0.907503,0.500122, + 0.218538,-0.213954,0.952084,2.948387,0.783357,0.515058, + 0.696414,-0.392791,0.600602,3.280681,0.510802,0.499434, + 0.218538,-0.213954,0.952084,2.948387,0.783357,0.515058, + 0.304965,-0.136677,0.942505,3.06109,0.397226,0.574193, + 0.026499,0.942993,0.331757,3.321825,0.26669,0.46575, + 0.696414,-0.392791,0.600602,3.280681,0.510802,0.499434, + 0.304965,-0.136677,0.942505,3.06109,0.397226,0.574193, + 0.026499,0.942993,0.331757,3.321825,0.26669,0.46575, + 0.304965,-0.136677,0.942505,3.06109,0.397226,0.574193, + -0.061264,0.921927,0.382487,3.136321,0.171237,0.539896, + 0.019336,0.837694,0.545798,3.36004,0.165487,0.412685, + 0.026499,0.942993,0.331757,3.321825,0.26669,0.46575, + -0.061264,0.921927,0.382487,3.136321,0.171237,0.539896, + 0.019336,0.837694,0.545798,3.36004,0.165487,0.412685, + -0.061264,0.921927,0.382487,3.136321,0.171237,0.539896, + -0.070642,0.834207,0.546908,3.16616,0.02131,0.457261, + 0.05298,0.780732,0.622615,3.378799,0.073736,0.355362, + 0.019336,0.837694,0.545798,3.36004,0.165487,0.412685, + -0.070642,0.834207,0.546908,3.16616,0.02131,0.457261, + 0.05298,0.780732,0.622615,3.378799,0.073736,0.355362, + -0.070642,0.834207,0.546908,3.16616,0.02131,0.457261, + -0.055544,0.828008,0.557959,3.199571,-0.153739,0.38015, + 0.115383,0.694945,0.709746,3.43895,-0.08258,0.257015, + 0.05298,0.780732,0.622615,3.378799,0.073736,0.355362, + -0.055544,0.828008,0.557959,3.199571,-0.153739,0.38015, + 0.115383,0.694945,0.709746,3.43895,-0.08258,0.257015, + -0.055544,0.828008,0.557959,3.199571,-0.153739,0.38015, + -0.047374,0.758242,0.65025,3.286426,-0.300744,0.276331, + 0.146937,0.551946,0.820832,3.514981,-0.121886,0.187589, + 0.115383,0.694945,0.709746,3.43895,-0.08258,0.257015, + -0.047374,0.758242,0.65025,3.286426,-0.300744,0.276331, + 0.146937,0.551946,0.820832,3.514981,-0.121886,0.187589, + -0.047374,0.758242,0.65025,3.286426,-0.300744,0.276331, + -0.046579,0.627301,0.777383,3.342159,-0.384674,0.201349, + 0.387987,0.466053,0.795148,3.737014,0.181837,0.176819, + -0.910859,-0.100368,-0.400327,3.731689,0.186391,0, + 0.338485,-0.103202,-0.935295,3.929251,0.411689,0, + 0.387987,0.466053,0.795148,3.737014,0.181837,0.176819, + 0.338485,-0.103202,-0.935295,3.929251,0.411689,0, + 0.614456,0.489786,0.618509,3.955635,0.432417,0.197586, + 0.387394,0.516219,0.763835,3.700363,0.265794,0.240762, + 0.387987,0.466053,0.795148,3.737014,0.181837,0.176819, + 0.614456,0.489786,0.618509,3.955635,0.432417,0.197586, + 0.387394,0.516219,0.763835,3.700363,0.265794,0.240762, + 0.614456,0.489786,0.618509,3.955635,0.432417,0.197586, + 0.718673,-0.290446,0.631784,3.889626,0.475277,0.247365, + 0.328244,0.603535,0.726637,3.67471,0.338839,0.30784, + 0.387394,0.516219,0.763835,3.700363,0.265794,0.240762, + 0.718673,-0.290446,0.631784,3.889626,0.475277,0.247365, + 0.328244,0.603535,0.726637,3.67471,0.338839,0.30784, + 0.718673,-0.290446,0.631784,3.889626,0.475277,0.247365, + 0.815771,-0.424495,0.392838,3.861841,0.560638,0.311961, + 0.187432,0.691784,0.697355,3.641195,0.407454,0.362198, + 0.328244,0.603535,0.726637,3.67471,0.338839,0.30784, + 0.815771,-0.424495,0.392838,3.861841,0.560638,0.311961, + 0.065855,0.814333,0.576649,3.61965,0.472046,0.391742, + 0.187432,0.691784,0.697355,3.641195,0.407454,0.362198, + 0.815771,-0.424495,0.392838,3.861841,0.560638,0.311961, + 0.065855,0.814333,0.576649,3.61965,0.472046,0.391742, + 0.815771,-0.424495,0.392838,3.861841,0.560638,0.311961, + 0.900366,-0.205985,0.38329,3.849352,0.664451,0.387198, + 0.628361,-0.426126,0.65083,3.559394,0.706516,0.452535, + 0.065855,0.814333,0.576649,3.61965,0.472046,0.391742, + 0.900366,-0.205985,0.38329,3.849352,0.664451,0.387198, + 0.628361,-0.426126,0.65083,3.559394,0.706516,0.452535, + 0.900366,-0.205985,0.38329,3.849352,0.664451,0.387198, + 0.906617,-0.14387,0.39667,3.823137,0.853054,0.461519, + 0.697438,-0.478568,0.533435,3.528445,1.060127,0.489443, + 0.628361,-0.426126,0.65083,3.559394,0.706516,0.452535, + 0.906617,-0.14387,0.39667,3.823137,0.853054,0.461519, + 0.697438,-0.478568,0.533435,3.528445,1.060127,0.489443, + 0.906617,-0.14387,0.39667,3.823137,0.853054,0.461519, + 0.908163,-0.140074,0.394486,3.747724,1.184933,0.518662, + 0.772313,-0.244122,0.586461,3.47341,1.366149,0.454658, + 0.697438,-0.478568,0.533435,3.528445,1.060127,0.489443, + 0.908163,-0.140074,0.394486,3.747724,1.184933,0.518662, + 0.772313,-0.244122,0.586461,3.47341,1.366149,0.454658, + 0.908163,-0.140074,0.394486,3.747724,1.184933,0.518662, + 0.907314,0.09913,0.4086,3.650974,1.46374,0.478617, + 0.805898,-0.146097,0.573745,3.377233,1.5878,0.400781, + 0.772313,-0.244122,0.586461,3.47341,1.366149,0.454658, + 0.907314,0.09913,0.4086,3.650974,1.46374,0.478617, + 0.805898,-0.146097,0.573745,3.377233,1.5878,0.400781, + 0.907314,0.09913,0.4086,3.650974,1.46374,0.478617, + 0.85208,0.278905,0.442914,3.590526,1.70109,0.411994, + 0.795625,-0.129968,0.591684,3.337545,1.748927,0.34021, + 0.805898,-0.146097,0.573745,3.377233,1.5878,0.400781, + 0.85208,0.278905,0.442914,3.590526,1.70109,0.411994, + 0.795625,-0.129968,0.591684,3.337545,1.748927,0.34021, + 0.85208,0.278905,0.442914,3.590526,1.70109,0.411994, + 0.759315,0.386803,0.523282,3.541188,1.849183,0.386366, + 0.748939,0.152982,0.644738,3.276333,1.863773,0.294266, + 0.795625,-0.129968,0.591684,3.337545,1.748927,0.34021, + 0.759315,0.386803,0.523282,3.541188,1.849183,0.386366, + 0.748939,0.152982,0.644738,3.276333,1.863773,0.294266, + 0.759315,0.386803,0.523282,3.541188,1.849183,0.386366, + 0.636794,0.461927,0.617346,3.479418,1.97825,0.317478, + 0.693381,0.351142,0.629224,3.252224,2.026347,0.148215, + 0.748939,0.152982,0.644738,3.276333,1.863773,0.294266, + 0.636794,0.461927,0.617346,3.479418,1.97825,0.317478, + 0.693381,0.351142,0.629224,3.252224,2.026347,0.148215, + 0.636794,0.461927,0.617346,3.479418,1.97825,0.317478, + 0.722145,-0.312679,0.617041,3.460196,2.103494,0.180368, + 0.662294,0.443714,0.603726,3.233975,2.059193,0.072431, + 0.693381,0.351142,0.629224,3.252224,2.026347,0.148215, + 0.722145,-0.312679,0.617041,3.460196,2.103494,0.180368, + 0.662294,0.443714,0.603726,3.233975,2.059193,0.072431, + 0.722145,-0.312679,0.617041,3.460196,2.103494,0.180368, + 0.742962,-0.255405,0.618688,3.4583,2.151656,0.102662, + 0.720876,-0.356662,0.594247,2.953029,-0.12769,0.520499, + 0.100131,0.509748,0.854477,2.835437,-0.231101,0.57789, + 0.709718,-0.453837,0.538824,2.986408,-0.413503,0.428964, + -0.096144,-0.182414,0.97851,2.811504,0.469098,0.657443, + -0.012663,0.029084,0.999497,2.747937,0.712253,0.615674, + 0.324748,-0.466051,0.823004,2.679445,0.687427,0.720573, + -0.096144,-0.182414,0.97851,2.811504,0.469098,0.657443, + 0.324748,-0.466051,0.823004,2.679445,0.687427,0.720573, + 0.727708,-0.453484,0.514581,2.753156,0.400829,0.713141, + -0.200187,-0.124247,0.971848,2.898733,0.271916,0.651298, + -0.096144,-0.182414,0.97851,2.811504,0.469098,0.657443, + 0.727708,-0.453484,0.514581,2.753156,0.400829,0.713141, + -0.200187,-0.124247,0.971848,2.898733,0.271916,0.651298, + 0.727708,-0.453484,0.514581,2.753156,0.400829,0.713141, + 0.287759,-0.574148,0.766517,2.790681,0.219187,0.718263, + 0.023112,-0.187685,0.981957,2.91987,0.084875,0.64246, + -0.200187,-0.124247,0.971848,2.898733,0.271916,0.651298, + 0.287759,-0.574148,0.766517,2.790681,0.219187,0.718263, + 0.023112,-0.187685,0.981957,2.91987,0.084875,0.64246, + 0.287759,-0.574148,0.766517,2.790681,0.219187,0.718263, + 0.677632,-0.514013,0.525933,2.790657,0.044324,0.717488, + 0.290845,-0.568581,0.769497,2.743995,-0.129852,0.718277, + 0.478274,-0.500384,0.721713,2.736198,-0.346225,0.659345, + 0.100131,0.509748,0.854477,2.835437,-0.231101,0.57789, + 0.100131,0.509748,0.854477,2.835437,-0.231101,0.57789, + 0.720876,-0.356662,0.594247,2.953029,-0.12769,0.520499, + 0.023112,-0.187685,0.981957,2.91987,0.084875,0.64246, + 0.100131,0.509748,0.854477,2.835437,-0.231101,0.57789, + 0.023112,-0.187685,0.981957,2.91987,0.084875,0.64246, + 0.290845,-0.568581,0.769497,2.743995,-0.129852,0.718277, + 0.023112,-0.187685,0.981957,2.91987,0.084875,0.64246, + 0.677632,-0.514013,0.525933,2.790657,0.044324,0.717488, + 0.290845,-0.568581,0.769497,2.743995,-0.129852,0.718277, + 0.370396,-0.36596,0.853745,2.396355,1.242239,0.597722, + 0.437631,-0.408484,0.801012,2.482917,0.997637,0.702425, + 0.539192,-0.226204,0.811236,2.514162,0.988713,0.674527, + 0.876436,-0.293555,0.381688,2.543372,-0.548031,0.937182, + 0.728904,-0.519577,0.445802,2.410367,-0.777999,0.841105, + 0.518786,-0.204527,0.830078,2.5392,-0.727778,0.750475, + 0.876436,-0.293555,0.381688,2.543372,-0.548031,0.937182, + 0.518786,-0.204527,0.830078,2.5392,-0.727778,0.750475, + 0.58512,-0.108234,0.803692,2.618307,-0.549092,0.805491, + 0.918784,-0.122699,0.375208,2.594499,-0.422948,0.981263, + 0.876436,-0.293555,0.381688,2.543372,-0.548031,0.937182, + 0.58512,-0.108234,0.803692,2.618307,-0.549092,0.805491, + 0.918784,-0.122699,0.375208,2.594499,-0.422948,0.981263, + 0.58512,-0.108234,0.803692,2.618307,-0.549092,0.805491, + 0.648132,-0.027411,0.761034,2.690576,-0.368057,0.819343, + 0.883063,-0.251635,0.396079,2.60743,-0.208248,0.974218, + 0.918784,-0.122699,0.375208,2.594499,-0.422948,0.981263, + 0.648132,-0.027411,0.761034,2.690576,-0.368057,0.819343, + 0.883063,-0.251635,0.396079,2.60743,-0.208248,0.974218, + 0.648132,-0.027411,0.761034,2.690576,-0.368057,0.819343, + 0.594643,-0.107364,0.796789,2.702577,-0.197406,0.795611, + 0.690473,-0.61586,0.379425,2.649413,0.031535,1.024796, + 0.883063,-0.251635,0.396079,2.60743,-0.208248,0.974218, + 0.594643,-0.107364,0.796789,2.702577,-0.197406,0.795611, + 0.690473,-0.61586,0.379425,2.649413,0.031535,1.024796, + 0.594643,-0.107364,0.796789,2.702577,-0.197406,0.795611, + 0.655995,-0.105886,0.747301,2.734183,0.038769,0.86581, + 0.276661,-0.626708,0.728489,2.668936,0.206182,1.014371, + 0.690473,-0.61586,0.379425,2.649413,0.031535,1.024796, + 0.655995,-0.105886,0.747301,2.734183,0.038769,0.86581, + 0.276661,-0.626708,0.728489,2.668936,0.206182,1.014371, + 0.655995,-0.105886,0.747301,2.734183,0.038769,0.86581, + 0.675576,-0.202498,0.708937,2.731512,0.219003,0.891585, + 0.112446,-0.618661,0.77757,2.616001,0.447717,0.960748, + 0.276661,-0.626708,0.728489,2.668936,0.206182,1.014371, + 0.675576,-0.202498,0.708937,2.731512,0.219003,0.891585, + 0.112446,-0.618661,0.77757,2.616001,0.447717,0.960748, + 0.675576,-0.202498,0.708937,2.731512,0.219003,0.891585, + 0.663699,-0.195183,0.722085,2.70696,0.393597,0.849582, + 0.189478,-0.558571,0.807525,2.5704,0.738683,0.830405, + 0.112446,-0.618661,0.77757,2.616001,0.447717,0.960748, + 0.663699,-0.195183,0.722085,2.70696,0.393597,0.849582, + 0.189478,-0.558571,0.807525,2.5704,0.738683,0.830405, + 0.663699,-0.195183,0.722085,2.70696,0.393597,0.849582, + 0.543412,-0.359347,0.758665,2.604217,0.728827,0.769671, + 0.437631,-0.408484,0.801012,2.482917,0.997637,0.702425, + 0.189478,-0.558571,0.807525,2.5704,0.738683,0.830405, + 0.543412,-0.359347,0.758665,2.604217,0.728827,0.769671, + 0.437631,-0.408484,0.801012,2.482917,0.997637,0.702425, + 0.543412,-0.359347,0.758665,2.604217,0.728827,0.769671, + 0.539192,-0.226204,0.811236,2.514162,0.988713,0.674527, + 0.245892,-0.489895,0.836385,2.688131,-0.517509,0.672975, + 0.478274,-0.500384,0.721713,2.736198,-0.346225,0.659345, + 0.648132,-0.027411,0.761034,2.690576,-0.368057,0.819343, + 0.245892,-0.489895,0.836385,2.688131,-0.517509,0.672975, + 0.648132,-0.027411,0.761034,2.690576,-0.368057,0.819343, + 0.58512,-0.108234,0.803692,2.618307,-0.549092,0.805491, + 0.727678,-0.414895,0.546211,2.542439,0.999928,0.648592, + 0.370396,-0.36596,0.853745,2.396355,1.242239,0.597722, + 0.539192,-0.226204,0.811236,2.514162,0.988713,0.674527, + 0.324748,-0.466051,0.823004,2.679445,0.687427,0.720573, + 0.727678,-0.414895,0.546211,2.542439,0.999928,0.648592, + 0.539192,-0.226204,0.811236,2.514162,0.988713,0.674527, + 0.324748,-0.466051,0.823004,2.679445,0.687427,0.720573, + 0.539192,-0.226204,0.811236,2.514162,0.988713,0.674527, + 0.543412,-0.359347,0.758665,2.604217,0.728827,0.769671, + 0.727708,-0.453484,0.514581,2.753156,0.400829,0.713141, + 0.324748,-0.466051,0.823004,2.679445,0.687427,0.720573, + 0.543412,-0.359347,0.758665,2.604217,0.728827,0.769671, + 0.727708,-0.453484,0.514581,2.753156,0.400829,0.713141, + 0.543412,-0.359347,0.758665,2.604217,0.728827,0.769671, + 0.663699,-0.195183,0.722085,2.70696,0.393597,0.849582, + 0.287759,-0.574148,0.766517,2.790681,0.219187,0.718263, + 0.727708,-0.453484,0.514581,2.753156,0.400829,0.713141, + 0.663699,-0.195183,0.722085,2.70696,0.393597,0.849582, + 0.287759,-0.574148,0.766517,2.790681,0.219187,0.718263, + 0.663699,-0.195183,0.722085,2.70696,0.393597,0.849582, + 0.675576,-0.202498,0.708937,2.731512,0.219003,0.891585, + 0.677632,-0.514013,0.525933,2.790657,0.044324,0.717488, + 0.287759,-0.574148,0.766517,2.790681,0.219187,0.718263, + 0.675576,-0.202498,0.708937,2.731512,0.219003,0.891585, + 0.677632,-0.514013,0.525933,2.790657,0.044324,0.717488, + 0.675576,-0.202498,0.708937,2.731512,0.219003,0.891585, + 0.655995,-0.105886,0.747301,2.734183,0.038769,0.86581, + 0.290845,-0.568581,0.769497,2.743995,-0.129852,0.718277, + 0.677632,-0.514013,0.525933,2.790657,0.044324,0.717488, + 0.655995,-0.105886,0.747301,2.734183,0.038769,0.86581, + 0.290845,-0.568581,0.769497,2.743995,-0.129852,0.718277, + 0.655995,-0.105886,0.747301,2.734183,0.038769,0.86581, + 0.594643,-0.107364,0.796789,2.702577,-0.197406,0.795611, + 0.478274,-0.500384,0.721713,2.736198,-0.346225,0.659345, + 0.290845,-0.568581,0.769497,2.743995,-0.129852,0.718277, + 0.594643,-0.107364,0.796789,2.702577,-0.197406,0.795611, + 0.478274,-0.500384,0.721713,2.736198,-0.346225,0.659345, + 0.594643,-0.107364,0.796789,2.702577,-0.197406,0.795611, + 0.648132,-0.027411,0.761034,2.690576,-0.368057,0.819343, + -0.012663,0.029084,0.999497,2.747937,0.712253,0.615674, + -0.031021,0.098798,0.994624,2.637461,1.01726,0.581611, + 0.727678,-0.414895,0.546211,2.542439,0.999928,0.648592, + -0.012663,0.029084,0.999497,2.747937,0.712253,0.615674, + 0.727678,-0.414895,0.546211,2.542439,0.999928,0.648592, + 0.324748,-0.466051,0.823004,2.679445,0.687427,0.720573, + -0.05128,0.509983,0.858655,2.361089,1.76666,0.202595, + 0.536218,-0.84408,0.000006,2.339597,1.807702,0, + 0.756976,-0.653442,0,2.128139,1.788397,0, + -0.05128,0.509983,0.858655,2.361089,1.76666,0.202595, + 0.756976,-0.653442,0,2.128139,1.788397,0, + 0.70745,-0.193334,0.679806,2.13239,1.755821,0.180271, + -0.02226,0.394285,0.918719,2.406969,1.645328,0.341479, + -0.05128,0.509983,0.858655,2.361089,1.76666,0.202595, + 0.70745,-0.193334,0.679806,2.13239,1.755821,0.180271, + -0.02226,0.394285,0.918719,2.406969,1.645328,0.341479, + 0.70745,-0.193334,0.679806,2.13239,1.755821,0.180271, + 0.71475,-0.118625,0.689247,2.183003,1.65407,0.341767, + -0.026262,0.311275,0.949957,2.519027,1.485931,0.422962, + -0.02226,0.394285,0.918719,2.406969,1.645328,0.341479, + 0.71475,-0.118625,0.689247,2.183003,1.65407,0.341767, + -0.026262,0.311275,0.949957,2.519027,1.485931,0.422962, + 0.71475,-0.118625,0.689247,2.183003,1.65407,0.341767, + 0.608407,-0.244593,0.754993,2.301359,1.397721,0.546015, + -0.039079,0.203923,0.978207,2.553871,1.284278,0.512335, + -0.026262,0.311275,0.949957,2.519027,1.485931,0.422962, + 0.608407,-0.244593,0.754993,2.301359,1.397721,0.546015, + -0.039079,0.203923,0.978207,2.553871,1.284278,0.512335, + 0.608407,-0.244593,0.754993,2.301359,1.397721,0.546015, + 0.370396,-0.36596,0.853745,2.396355,1.242239,0.597722, + -0.031021,0.098798,0.994624,2.637461,1.01726,0.581611, + -0.039079,0.203923,0.978207,2.553871,1.284278,0.512335, + 0.370396,-0.36596,0.853745,2.396355,1.242239,0.597722, + -0.031021,0.098798,0.994624,2.637461,1.01726,0.581611, + 0.370396,-0.36596,0.853745,2.396355,1.242239,0.597722, + 0.727678,-0.414895,0.546211,2.542439,0.999928,0.648592, + 0.728904,-0.519577,0.445802,2.410367,-0.777999,0.841105, + -0.06371,0.842533,0.534864,2.346081,-0.74535,1.013296, + -0.069142,0.724976,0.685295,2.245624,-0.864372,0.995778, + 0.728904,-0.519577,0.445802,2.410367,-0.777999,0.841105, + -0.069142,0.724976,0.685295,2.245624,-0.864372,0.995778, + 0.09853,0.626571,0.773111,2.292449,-0.871852,0.8824, + 0.71475,-0.118625,0.689247,2.183003,1.65407,0.341767, + 0.70745,-0.193334,0.679806,2.13239,1.755821,0.180271, + 0.411872,0.04507,0.910127,2.069379,1.727818,0.212746, + 0.71475,-0.118625,0.689247,2.183003,1.65407,0.341767, + 0.411872,0.04507,0.910127,2.069379,1.727818,0.212746, + 0.552828,-0.750794,0.36151,2.096552,1.678482,0.32681, + 0.608407,-0.244593,0.754993,2.301359,1.397721,0.546015, + 0.71475,-0.118625,0.689247,2.183003,1.65407,0.341767, + 0.552828,-0.750794,0.36151,2.096552,1.678482,0.32681, + 0.608407,-0.244593,0.754993,2.301359,1.397721,0.546015, + 0.552828,-0.750794,0.36151,2.096552,1.678482,0.32681, + 0.226413,-0.89822,0.376747,2.189848,1.468992,0.517501, + 0.370396,-0.36596,0.853745,2.396355,1.242239,0.597722, + 0.608407,-0.244593,0.754993,2.301359,1.397721,0.546015, + 0.226413,-0.89822,0.376747,2.189848,1.468992,0.517501, + 0.370396,-0.36596,0.853745,2.396355,1.242239,0.597722, + 0.226413,-0.89822,0.376747,2.189848,1.468992,0.517501, + 0.016767,-0.927537,0.373356,2.266003,1.273253,0.663332, + 0.437631,-0.408484,0.801012,2.482917,0.997637,0.702425, + 0.370396,-0.36596,0.853745,2.396355,1.242239,0.597722, + 0.016767,-0.927537,0.373356,2.266003,1.273253,0.663332, + 0.437631,-0.408484,0.801012,2.482917,0.997637,0.702425, + 0.016767,-0.927537,0.373356,2.266003,1.273253,0.663332, + 0.08136,-0.929085,0.360806,2.347317,1.066114,0.758763, + 0.189478,-0.558571,0.807525,2.5704,0.738683,0.830405, + 0.437631,-0.408484,0.801012,2.482917,0.997637,0.702425, + 0.08136,-0.929085,0.360806,2.347317,1.066114,0.758763, + 0.189478,-0.558571,0.807525,2.5704,0.738683,0.830405, + 0.08136,-0.929085,0.360806,2.347317,1.066114,0.758763, + 0.295093,-0.940225,0.16999,2.399389,0.782091,0.915279, + 0.112446,-0.618661,0.77757,2.616001,0.447717,0.960748, + 0.189478,-0.558571,0.807525,2.5704,0.738683,0.830405, + 0.295093,-0.940225,0.16999,2.399389,0.782091,0.915279, + 0.112446,-0.618661,0.77757,2.616001,0.447717,0.960748, + 0.295093,-0.940225,0.16999,2.399389,0.782091,0.915279, + 0.676544,-0.141883,0.722604,2.448969,0.529858,1.037335, + 0.276661,-0.626708,0.728489,2.668936,0.206182,1.014371, + 0.112446,-0.618661,0.77757,2.616001,0.447717,0.960748, + 0.676544,-0.141883,0.722604,2.448969,0.529858,1.037335, + 0.276661,-0.626708,0.728489,2.668936,0.206182,1.014371, + 0.676544,-0.141883,0.722604,2.448969,0.529858,1.037335, + 0.667276,-0.159228,0.727591,2.495354,0.250522,1.132081, + 0.690473,-0.61586,0.379425,2.649413,0.031535,1.024796, + 0.276661,-0.626708,0.728489,2.668936,0.206182,1.014371, + 0.667276,-0.159228,0.727591,2.495354,0.250522,1.132081, + 0.690473,-0.61586,0.379425,2.649413,0.031535,1.024796, + 0.667276,-0.159228,0.727591,2.495354,0.250522,1.132081, + 0.659349,-0.248914,0.709437,2.50049,-0.035029,1.170179, + 0.883063,-0.251635,0.396079,2.60743,-0.208248,0.974218, + 0.690473,-0.61586,0.379425,2.649413,0.031535,1.024796, + 0.659349,-0.248914,0.709437,2.50049,-0.035029,1.170179, + 0.883063,-0.251635,0.396079,2.60743,-0.208248,0.974218, + 0.659349,-0.248914,0.709437,2.50049,-0.035029,1.170179, + 0.631747,-0.24686,0.734817,2.452588,-0.244072,1.138797, + 0.918784,-0.122699,0.375208,2.594499,-0.422948,0.981263, + 0.883063,-0.251635,0.396079,2.60743,-0.208248,0.974218, + 0.631747,-0.24686,0.734817,2.452588,-0.244072,1.138797, + 0.918784,-0.122699,0.375208,2.594499,-0.422948,0.981263, + 0.631747,-0.24686,0.734817,2.452588,-0.244072,1.138797, + 0.623235,-0.257987,0.738255,2.439827,-0.395385,1.131324, + 0.876436,-0.293555,0.381688,2.543372,-0.548031,0.937182, + 0.918784,-0.122699,0.375208,2.594499,-0.422948,0.981263, + 0.623235,-0.257987,0.738255,2.439827,-0.395385,1.131324, + 0.876436,-0.293555,0.381688,2.543372,-0.548031,0.937182, + 0.623235,-0.257987,0.738255,2.439827,-0.395385,1.131324, + 0.791391,-0.43807,0.426373,2.384638,-0.591919,1.043058, + 0.728904,-0.519577,0.445802,2.410367,-0.777999,0.841105, + 0.876436,-0.293555,0.381688,2.543372,-0.548031,0.937182, + 0.791391,-0.43807,0.426373,2.384638,-0.591919,1.043058, + 0.728904,-0.519577,0.445802,2.410367,-0.777999,0.841105, + 0.791391,-0.43807,0.426373,2.384638,-0.591919,1.043058, + -0.06371,0.842533,0.534864,2.346081,-0.74535,1.013296, + -0.069142,0.724976,0.685295,2.245624,-0.864372,0.995778, + -0.887036,-0.210048,-0.411154,2.222082,-0.957342,1.014137, + 0.080812,0.697931,0.711591,2.229345,-0.992723,0.862826, + -0.069142,0.724976,0.685295,2.245624,-0.864372,0.995778, + 0.080812,0.697931,0.711591,2.229345,-0.992723,0.862826, + 0.09853,0.626571,0.773111,2.292449,-0.871852,0.8824, + 0.213167,-0.525559,0.823619,2.013534,-0.662303,1.191491, + -0.069142,0.724976,0.685295,2.245624,-0.864372,0.995778, + -0.06371,0.842533,0.534864,2.346081,-0.74535,1.013296, + 0.23972,-0.400363,0.884445,2.108912,-0.357128,1.259691, + 0.213167,-0.525559,0.823619,2.013534,-0.662303,1.191491, + -0.06371,0.842533,0.534864,2.346081,-0.74535,1.013296, + 0.23972,-0.400363,0.884445,2.108912,-0.357128,1.259691, + -0.06371,0.842533,0.534864,2.346081,-0.74535,1.013296, + 0.791391,-0.43807,0.426373,2.384638,-0.591919,1.043058, + -0.720176,-0.693792,0,1.794465,1.787719,0, + -0.057955,0.638634,0.767325,1.807583,1.756546,0.177627, + 0.411872,0.04507,0.910127,2.069379,1.727818,0.212746, + -0.720176,-0.693792,0,1.794465,1.787719,0, + 0.411872,0.04507,0.910127,2.069379,1.727818,0.212746, + -0.385788,0.922588,0,2.042206,1.777154,0, + 0.25339,-0.287519,0.923648,2.136269,-0.187666,1.278057, + 0.23972,-0.400363,0.884445,2.108912,-0.357128,1.259691, + 0.791391,-0.43807,0.426373,2.384638,-0.591919,1.043058, + 0.25339,-0.287519,0.923648,2.136269,-0.187666,1.278057, + 0.791391,-0.43807,0.426373,2.384638,-0.591919,1.043058, + 0.623235,-0.257987,0.738255,2.439827,-0.395385,1.131324, + 0.25339,-0.287519,0.923648,2.136269,-0.187666,1.278057, + 0.623235,-0.257987,0.738255,2.439827,-0.395385,1.131324, + 0.631747,-0.24686,0.734817,2.452588,-0.244072,1.138797, + 0.187438,-0.340915,0.921219,2.14179,-0.055306,1.295565, + 0.25339,-0.287519,0.923648,2.136269,-0.187666,1.278057, + 0.631747,-0.24686,0.734817,2.452588,-0.244072,1.138797, + 0.187438,-0.340915,0.921219,2.14179,-0.055306,1.295565, + 0.631747,-0.24686,0.734817,2.452588,-0.244072,1.138797, + 0.659349,-0.248914,0.709437,2.50049,-0.035029,1.170179, + 0.114032,-0.218132,0.969234,2.0817,0.283249,1.259461, + 0.187438,-0.340915,0.921219,2.14179,-0.055306,1.295565, + 0.659349,-0.248914,0.709437,2.50049,-0.035029,1.170179, + 0.114032,-0.218132,0.969234,2.0817,0.283249,1.259461, + 0.659349,-0.248914,0.709437,2.50049,-0.035029,1.170179, + 0.667276,-0.159228,0.727591,2.495354,0.250522,1.132081, + 0.10833,0.05569,0.992554,2.023441,0.529338,1.144399, + 0.114032,-0.218132,0.969234,2.0817,0.283249,1.259461, + 0.667276,-0.159228,0.727591,2.495354,0.250522,1.132081, + 0.10833,0.05569,0.992554,2.023441,0.529338,1.144399, + 0.667276,-0.159228,0.727591,2.495354,0.250522,1.132081, + 0.676544,-0.141883,0.722604,2.448969,0.529858,1.037335, + 0.107989,0.168108,0.979836,1.975941,0.827957,1.018423, + 0.10833,0.05569,0.992554,2.023441,0.529338,1.144399, + 0.676544,-0.141883,0.722604,2.448969,0.529858,1.037335, + 0.107989,0.168108,0.979836,1.975941,0.827957,1.018423, + 0.676544,-0.141883,0.722604,2.448969,0.529858,1.037335, + 0.295093,-0.940225,0.16999,2.399389,0.782091,0.915279, + 0.088722,0.251367,0.963817,1.958254,1.130271,0.861813, + 0.107989,0.168108,0.979836,1.975941,0.827957,1.018423, + 0.295093,-0.940225,0.16999,2.399389,0.782091,0.915279, + 0.088722,0.251367,0.963817,1.958254,1.130271,0.861813, + 0.295093,-0.940225,0.16999,2.399389,0.782091,0.915279, + 0.08136,-0.929085,0.360806,2.347317,1.066114,0.758763, + 0.060533,0.377837,0.923891,1.859443,1.450393,0.632222, + 0.088722,0.251367,0.963817,1.958254,1.130271,0.861813, + 0.08136,-0.929085,0.360806,2.347317,1.066114,0.758763, + 0.060533,0.377837,0.923891,1.859443,1.450393,0.632222, + 0.08136,-0.929085,0.360806,2.347317,1.066114,0.758763, + 0.016767,-0.927537,0.373356,2.266003,1.273253,0.663332, + 0.016737,0.497476,0.867316,1.821946,1.618209,0.403751, + 0.060533,0.377837,0.923891,1.859443,1.450393,0.632222, + 0.016767,-0.927537,0.373356,2.266003,1.273253,0.663332, + 0.016737,0.497476,0.867316,1.821946,1.618209,0.403751, + 0.016767,-0.927537,0.373356,2.266003,1.273253,0.663332, + 0.226413,-0.89822,0.376747,2.189848,1.468992,0.517501, + -0.024013,0.58573,0.810151,1.798719,1.714447,0.259352, + 0.016737,0.497476,0.867316,1.821946,1.618209,0.403751, + 0.226413,-0.89822,0.376747,2.189848,1.468992,0.517501, + -0.024013,0.58573,0.810151,1.798719,1.714447,0.259352, + 0.226413,-0.89822,0.376747,2.189848,1.468992,0.517501, + 0.552828,-0.750794,0.36151,2.096552,1.678482,0.32681, + -0.057955,0.638634,0.767325,1.807583,1.756546,0.177627, + -0.024013,0.58573,0.810151,1.798719,1.714447,0.259352, + 0.552828,-0.750794,0.36151,2.096552,1.678482,0.32681, + -0.057955,0.638634,0.767325,1.807583,1.756546,0.177627, + 0.552828,-0.750794,0.36151,2.096552,1.678482,0.32681, + 0.411872,0.04507,0.910127,2.069379,1.727818,0.212746, + 0.981421,-0.191868,0,0.733818,1.740873,0, + 0.566114,-0.824327,0,0.234527,1.730117,0, + 0.095331,0.952335,0.289775,0.223642,1.684075,0.160743, + 0.981421,-0.191868,0,0.733818,1.740873,0, + 0.095331,0.952335,0.289775,0.223642,1.684075,0.160743, + 0.100949,-0.548551,0.830001,0.737904,1.604213,0.281713, + 0.100949,-0.548551,0.830001,0.737904,1.604213,0.281713, + 0.095331,0.952335,0.289775,0.223642,1.684075,0.160743, + 0.10291,0.954344,0.280422,0.23733,1.595746,0.288672, + 0.100949,-0.548551,0.830001,0.737904,1.604213,0.281713, + 0.10291,0.954344,0.280422,0.23733,1.595746,0.288672, + 0.068777,-0.757383,0.649339,0.725959,1.478055,0.461804, + 0.068777,-0.757383,0.649339,0.725959,1.478055,0.461804, + 0.10291,0.954344,0.280422,0.23733,1.595746,0.288672, + 0.172251,0.950689,0.257916,0.289039,1.496446,0.430055, + 0.068777,-0.757383,0.649339,0.725959,1.478055,0.461804, + 0.172251,0.950689,0.257916,0.289039,1.496446,0.430055, + 0.023352,-0.872807,0.487506,0.760722,1.205036,0.700545, + 0.023352,-0.872807,0.487506,0.760722,1.205036,0.700545, + 0.172251,0.950689,0.257916,0.289039,1.496446,0.430055, + 0.28101,0.853935,0.437982,0.305671,1.298417,0.629719, + 0.023352,-0.872807,0.487506,0.760722,1.205036,0.700545, + 0.28101,0.853935,0.437982,0.305671,1.298417,0.629719, + 0.004725,-0.680391,0.732834,0.857323,0.985001,0.874029, + 0.004725,-0.680391,0.732834,0.857323,0.985001,0.874029, + 0.28101,0.853935,0.437982,0.305671,1.298417,0.629719, + 0.381239,0.555717,0.738807,0.243473,1.134082,0.819993, + 0.004725,-0.680391,0.732834,0.857323,0.985001,0.874029, + 0.381239,0.555717,0.738807,0.243473,1.134082,0.819993, + 0.034172,-0.858604,0.511498,0.921312,0.755659,0.99933, + 0.034172,-0.858604,0.511498,0.921312,0.755659,0.99933, + 0.381239,0.555717,0.738807,0.243473,1.134082,0.819993, + 0.376012,0.360026,0.853813,0.316341,0.785311,1.08626, + 0.034172,-0.858604,0.511498,0.921312,0.755659,0.99933, + 0.376012,0.360026,0.853813,0.316341,0.785311,1.08626, + 0.037423,-0.986705,0.158154,0.939271,0.379986,1.185872, + 0.037423,-0.986705,0.158154,0.939271,0.379986,1.185872, + 0.376012,0.360026,0.853813,0.316341,0.785311,1.08626, + 0.207079,0.373404,0.904261,0.539252,0.353984,1.254493, + 0.037423,-0.986705,0.158154,0.939271,0.379986,1.185872, + 0.207079,0.373404,0.904261,0.539252,0.353984,1.254493, + 0.013768,-0.992402,0.122267,0.927775,0.195225,1.233043, + 0.013768,-0.992402,0.122267,0.927775,0.195225,1.233043, + 0.207079,0.373404,0.904261,0.539252,0.353984,1.254493, + -0.045242,0.348413,0.936249,0.53915,0.148262,1.321014, + 0.013768,-0.992402,0.122267,0.927775,0.195225,1.233043, + -0.045242,0.348413,0.936249,0.53915,0.148262,1.321014, + 0.076524,0.950336,0.301672,0.950215,0.042751,1.256188, + 0.076524,0.950336,0.301672,0.950215,0.042751,1.256188, + -0.045242,0.348413,0.936249,0.53915,0.148262,1.321014, + -0.212948,0.334057,0.918182,0.516872,-0.020713,1.356627, + 0.076524,0.950336,0.301672,0.950215,0.042751,1.256188, + -0.212948,0.334057,0.918182,0.516872,-0.020713,1.356627, + 0.100598,0.942931,0.317428,0.943855,-0.101127,1.274771, + 0.100598,0.942931,0.317428,0.943855,-0.101127,1.274771, + -0.212948,0.334057,0.918182,0.516872,-0.020713,1.356627, + -0.282152,0.285245,0.915983,0.542386,-0.188227,1.370375, + 0.100598,0.942931,0.317428,0.943855,-0.101127,1.274771, + -0.282152,0.285245,0.915983,0.542386,-0.188227,1.370375, + 0.150328,0.92948,0.336851,0.960321,-0.308052,1.243133, + 0.150328,0.92948,0.336851,0.960321,-0.308052,1.243133, + -0.282152,0.285245,0.915983,0.542386,-0.188227,1.370375, + -0.326048,0.118611,0.937883,0.546875,-0.39094,1.363244, + 0.150328,0.92948,0.336851,0.960321,-0.308052,1.243133, + -0.326048,0.118611,0.937883,0.546875,-0.39094,1.363244, + 0.235667,0.756618,0.60991,0.97453,-0.525273,1.140353, + 0.235667,0.756618,0.60991,0.97453,-0.525273,1.140353, + -0.326048,0.118611,0.937883,0.546875,-0.39094,1.363244, + -0.422758,-0.178302,0.888529,0.550658,-0.633015,1.331311, + 0.235667,0.756618,0.60991,0.97453,-0.525273,1.140353, + -0.422758,-0.178302,0.888529,0.550658,-0.633015,1.331311, + 0.305452,0.425365,0.851918,0.948819,-0.638568,1.102958, + 0.305452,0.425365,0.851918,0.948819,-0.638568,1.102958, + -0.422758,-0.178302,0.888529,0.550658,-0.633015,1.331311, + -0.504483,-0.438591,0.743731,0.527724,-0.862854,1.253811, + 0.305452,0.425365,0.851918,0.948819,-0.638568,1.102958, + -0.504483,-0.438591,0.743731,0.527724,-0.862854,1.253811, + 0.325482,0.443544,0.835063,0.939974,-0.894739,1.019809, + 0.325482,0.443544,0.835063,0.939974,-0.894739,1.019809, + -0.504483,-0.438591,0.743731,0.527724,-0.862854,1.253811, + -0.53858,-0.616298,0.57455,0.544825,-1.133123,1.096902, + 0.325482,0.443544,0.835063,0.939974,-0.894739,1.019809, + -0.53858,-0.616298,0.57455,0.544825,-1.133123,1.096902, + 0.242426,0.58207,0.77616,0.956456,-1.070504,0.921063, + 0.242426,0.58207,0.77616,0.956456,-1.070504,0.921063, + -0.53858,-0.616298,0.57455,0.544825,-1.133123,1.096902, + -0.507894,-0.767261,0.391606,0.530629,-1.316423,0.929842, + 0.242426,0.58207,0.77616,0.956456,-1.070504,0.921063, + -0.507894,-0.767261,0.391606,0.530629,-1.316423,0.929842, + 0.070189,0.510248,0.857158,0.93066,-1.216516,0.831196, + 0.070189,0.510248,0.857158,0.93066,-1.216516,0.831196, + -0.507894,-0.767261,0.391606,0.530629,-1.316423,0.929842, + -0.375453,-0.69207,0.616502,0.538756,-1.408602,0.764911, + 0.070189,0.510248,0.857158,0.93066,-1.216516,0.831196, + -0.375453,-0.69207,0.616502,0.538756,-1.408602,0.764911, + -0.078623,0.370994,0.925301,0.922703,-1.296032,0.728307, + -0.078623,0.370994,0.925301,0.922703,-1.296032,0.728307, + -0.375453,-0.69207,0.616502,0.538756,-1.408602,0.764911, + -0.1427,-0.847733,0.510868,0.489819,-1.524947,0.672392, + -0.078623,0.370994,0.925301,0.922703,-1.296032,0.728307, + -0.1427,-0.847733,0.510868,0.489819,-1.524947,0.672392, + -0.123389,0.256577,0.958615,0.912699,-1.455066,0.576185, + -0.123389,0.256577,0.958615,0.912699,-1.455066,0.576185, + -0.1427,-0.847733,0.510868,0.489819,-1.524947,0.672392, + -0.178511,-0.973481,0.143068,0.480235,-1.631521,0.401961, + -0.123389,0.256577,0.958615,0.912699,-1.455066,0.576185, + -0.178511,-0.973481,0.143068,0.480235,-1.631521,0.401961, + -0.165685,0.059692,0.98437,0.912989,-1.499314,0.419547, + -0.165685,0.059692,0.98437,0.912989,-1.499314,0.419547, + -0.178511,-0.973481,0.143068,0.480235,-1.631521,0.401961, + 0.226963,-0.973903,0,0.44655,-1.67295,0, + -0.165685,0.059692,0.98437,0.912989,-1.499314,0.419547, + 0.226963,-0.973903,0,0.44655,-1.67295,0, + 0.92802,-0.37253,0,0.927497,-1.558489,0, + -0.039092,-0.999236,0,-0.228904,1.734267,0, + -0.009814,-0.999952,0,-0.547248,1.742126,0, + -0.021294,0.896295,0.442946,-0.559706,1.69418,0.186107, + -0.039092,-0.999236,0,-0.228904,1.734267,0, + -0.021294,0.896295,0.442946,-0.559706,1.69418,0.186107, + 0.067879,0.951186,0.30106,-0.221516,1.686349,0.151403, + 0.067879,0.951186,0.30106,-0.221516,1.686349,0.151403, + -0.021294,0.896295,0.442946,-0.559706,1.69418,0.186107, + -0.072244,0.618144,0.782738,-0.557624,1.641278,0.271462, + 0.067879,0.951186,0.30106,-0.221516,1.686349,0.151403, + -0.072244,0.618144,0.782738,-0.557624,1.641278,0.271462, + 0.085022,0.963119,0.255291,-0.267035,1.627058,0.266577, + 0.085022,0.963119,0.255291,-0.267035,1.627058,0.266577, + -0.072244,0.618144,0.782738,-0.557624,1.641278,0.271462, + -0.038944,0.247819,0.968023,-0.626493,1.585426,0.443136, + 0.085022,0.963119,0.255291,-0.267035,1.627058,0.266577, + -0.038944,0.247819,0.968023,-0.626493,1.585426,0.443136, + 0.120743,0.971588,0.203561,-0.247999,1.565146,0.389142, + 0.120743,0.971588,0.203561,-0.247999,1.565146,0.389142, + -0.038944,0.247819,0.968023,-0.626493,1.585426,0.443136, + -0.00315,0.115338,0.993321,-0.597781,1.48962,0.641047, + 0.120743,0.971588,0.203561,-0.247999,1.565146,0.389142, + -0.00315,0.115338,0.993321,-0.597781,1.48962,0.641047, + 0.117963,0.926753,0.356669,-0.179548,1.471301,0.544513, + 0.117963,0.926753,0.356669,-0.179548,1.471301,0.544513, + -0.00315,0.115338,0.993321,-0.597781,1.48962,0.641047, + 0.016683,0.197618,0.980137,-0.674657,1.333008,0.761059, + 0.117963,0.926753,0.356669,-0.179548,1.471301,0.544513, + 0.016683,0.197618,0.980137,-0.674657,1.333008,0.761059, + 0.109947,0.693426,0.71209,-0.192546,1.305535,0.70008, + 0.109947,0.693426,0.71209,-0.192546,1.305535,0.70008, + 0.016683,0.197618,0.980137,-0.674657,1.333008,0.761059, + 0.032424,0.316591,0.948008,-0.910602,1.204118,0.83774, + 0.109947,0.693426,0.71209,-0.192546,1.305535,0.70008, + 0.032424,0.316591,0.948008,-0.910602,1.204118,0.83774, + 0.076565,0.333251,0.939724,-0.406155,1.005088,0.971088, + 0.076565,0.333251,0.939724,-0.406155,1.005088,0.971088, + 0.032424,0.316591,0.948008,-0.910602,1.204118,0.83774, + 0.053195,0.343167,0.937767,-0.969076,0.901205,1.146223, + 0.076565,0.333251,0.939724,-0.406155,1.005088,0.971088, + 0.053195,0.343167,0.937767,-0.969076,0.901205,1.146223, + -0.039599,0.171847,0.984327,-0.11519,0.458427,1.346197, + -0.039599,0.171847,0.984327,-0.11519,0.458427,1.346197, + 0.053195,0.343167,0.937767,-0.969076,0.901205,1.146223, + 0.057735,0.173734,0.983099,-0.752416,0.438132,1.467349, + -0.039599,0.171847,0.984327,-0.11519,0.458427,1.346197, + 0.057735,0.173734,0.983099,-0.752416,0.438132,1.467349, + -0.164971,0.181757,0.969406,0.005537,0.163519,1.472265, + -0.164971,0.181757,0.969406,0.005537,0.163519,1.472265, + 0.057735,0.173734,0.983099,-0.752416,0.438132,1.467349, + 0.058723,-0.195869,0.97887,-0.645496,0.179261,1.584316, + -0.164971,0.181757,0.969406,0.005537,0.163519,1.472265, + 0.058723,-0.195869,0.97887,-0.645496,0.179261,1.584316, + -0.216817,0.278777,0.935561,0.018086,0.002865,1.523199, + -0.216817,0.278777,0.935561,0.018086,0.002865,1.523199, + 0.058723,-0.195869,0.97887,-0.645496,0.179261,1.584316, + 0.088769,-0.475351,0.875307,-0.536767,-0.144454,1.682232, + -0.216817,0.278777,0.935561,0.018086,0.002865,1.523199, + 0.088769,-0.475351,0.875307,-0.536767,-0.144454,1.682232, + -0.219724,0.297861,0.928978,0.034087,-0.225059,1.542949, + -0.219724,0.297861,0.928978,0.034087,-0.225059,1.542949, + 0.088769,-0.475351,0.875307,-0.536767,-0.144454,1.682232, + 0.099302,-0.563694,0.819993,-0.533528,-0.58228,1.701405, + -0.219724,0.297861,0.928978,0.034087,-0.225059,1.542949, + 0.099302,-0.563694,0.819993,-0.533528,-0.58228,1.701405, + -0.227369,0.161984,0.960242,0.010486,-0.502317,1.576297, + -0.227369,0.161984,0.960242,0.010486,-0.502317,1.576297, + 0.099302,-0.563694,0.819993,-0.533528,-0.58228,1.701405, + 0.093802,-0.705497,0.702478,-0.505045,-0.913827,1.645612, + -0.227369,0.161984,0.960242,0.010486,-0.502317,1.576297, + 0.093802,-0.705497,0.702478,-0.505045,-0.913827,1.645612, + -0.30296,-0.137183,0.943078,0.021051,-0.831931,1.511548, + -0.30296,-0.137183,0.943078,0.021051,-0.831931,1.511548, + 0.093802,-0.705497,0.702478,-0.505045,-0.913827,1.645612, + 0.058028,-0.329667,0.942312,-0.487217,-1.193519,1.504026, + -0.30296,-0.137183,0.943078,0.021051,-0.831931,1.511548, + 0.058028,-0.329667,0.942312,-0.487217,-1.193519,1.504026, + -0.387895,-0.42081,0.820034,-0.04157,-1.143825,1.395176, + -0.387895,-0.42081,0.820034,-0.04157,-1.143825,1.395176, + 0.058028,-0.329667,0.942312,-0.487217,-1.193519,1.504026, + 0.096347,0.961203,0.258467,-0.524231,-1.399266,1.313019, + -0.387895,-0.42081,0.820034,-0.04157,-1.143825,1.395176, + 0.096347,0.961203,0.258467,-0.524231,-1.399266,1.313019, + -0.433119,-0.541142,0.720814,-0.071941,-1.346991,1.237379, + -0.433119,-0.541142,0.720814,-0.071941,-1.346991,1.237379, + 0.096347,0.961203,0.258467,-0.524231,-1.399266,1.313019, + 0.098712,0.966371,0.23745,-0.526127,-1.495,1.167736, + -0.433119,-0.541142,0.720814,-0.071941,-1.346991,1.237379, + 0.098712,0.966371,0.23745,-0.526127,-1.495,1.167736, + -0.455057,-0.684123,0.569999,-0.0723,-1.450245,1.087397, + -0.455057,-0.684123,0.569999,-0.0723,-1.450245,1.087397, + 0.098712,0.966371,0.23745,-0.526127,-1.495,1.167736, + 0.079848,0.962653,0.258695,-0.535144,-1.615983,0.920556, + -0.455057,-0.684123,0.569999,-0.0723,-1.450245,1.087397, + 0.079848,0.962653,0.258695,-0.535144,-1.615983,0.920556, + -0.084259,-0.367691,0.926123,-0.063012,-1.583021,0.865082, + -0.098179,0.995169,0,-0.866132,1.75467,0, + -0.065586,-0.997847,0,-1.179474,1.786649,0, + -0.115746,0.20405,0.972094,-1.215563,1.757097,0.133494, + -0.098179,0.995169,0,-0.866132,1.75467,0, + -0.115746,0.20405,0.972094,-1.215563,1.757097,0.133494, + 0.136965,0.155729,0.978258,-0.894132,1.712652,0.151911, + 0.136965,0.155729,0.978258,-0.894132,1.712652,0.151911, + -0.115746,0.20405,0.972094,-1.215563,1.757097,0.133494, + -0.164191,0.153328,0.974439,-1.227613,1.709095,0.276029, + 0.136965,0.155729,0.978258,-0.894132,1.712652,0.151911, + -0.164191,0.153328,0.974439,-1.227613,1.709095,0.276029, + 0.173447,0.205435,0.963178,-0.954897,1.677544,0.293034, + 0.173447,0.205435,0.963178,-0.954897,1.677544,0.293034, + -0.164191,0.153328,0.974439,-1.227613,1.709095,0.276029, + -0.15812,-0.033626,0.986847,-1.292756,1.656509,0.51403, + 0.173447,0.205435,0.963178,-0.954897,1.677544,0.293034, + -0.15812,-0.033626,0.986847,-1.292756,1.656509,0.51403, + 0.136801,0.29658,0.945159,-1.017767,1.607824,0.541965, + 0.136801,0.29658,0.945159,-1.017767,1.607824,0.541965, + -0.15812,-0.033626,0.986847,-1.292756,1.656509,0.51403, + 0.005821,-0.234321,0.972142,-1.338488,1.613735,0.725441, + 0.136801,0.29658,0.945159,-1.017767,1.607824,0.541965, + 0.005821,-0.234321,0.972142,-1.338488,1.613735,0.725441, + 0.095019,0.330845,0.938889,-1.04607,1.509097,0.76106, + 0.095019,0.330845,0.938889,-1.04607,1.509097,0.76106, + 0.005821,-0.234321,0.972142,-1.338488,1.613735,0.725441, + 0.243464,-0.335965,0.909864,-1.403848,1.533059,0.902827, + 0.095019,0.330845,0.938889,-1.04607,1.509097,0.76106, + 0.243464,-0.335965,0.909864,-1.403848,1.533059,0.902827, + 0.07657,0.16758,0.982881,-1.115594,1.39238,0.819623, + 0.07657,0.16758,0.982881,-1.115594,1.39238,0.819623, + 0.243464,-0.335965,0.909864,-1.403848,1.533059,0.902827, + 0.49938,-0.45475,0.737443,-1.551526,1.400025,1.050193, + 0.07657,0.16758,0.982881,-1.115594,1.39238,0.819623, + 0.49938,-0.45475,0.737443,-1.551526,1.400025,1.050193, + 0.079214,-0.175111,0.981357,-1.278903,1.192051,0.946843, + 0.079214,-0.175111,0.981357,-1.278903,1.192051,0.946843, + 0.49938,-0.45475,0.737443,-1.551526,1.400025,1.050193, + 0.573426,-0.441087,0.69038,-1.552899,1.128654,1.15104, + 0.079214,-0.175111,0.981357,-1.278903,1.192051,0.946843, + 0.573426,-0.441087,0.69038,-1.552899,1.128654,1.15104, + 0.204115,-0.405276,0.891116,-1.200768,0.978822,1.103391, + 0.204115,-0.405276,0.891116,-1.200768,0.978822,1.103391, + 0.573426,-0.441087,0.69038,-1.552899,1.128654,1.15104, + 0.1643,0.873906,0.457487,-1.454529,0.875045,1.238858, + 0.204115,-0.405276,0.891116,-1.200768,0.978822,1.103391, + 0.1643,0.873906,0.457487,-1.454529,0.875045,1.238858, + 0.396045,-0.47666,0.784821,-1.147922,0.807955,1.254191, + 0.396045,-0.47666,0.784821,-1.147922,0.807955,1.254191, + 0.1643,0.873906,0.457487,-1.454529,0.875045,1.238858, + -0.012448,0.906487,0.422051,-1.405685,0.573835,1.352181, + 0.396045,-0.47666,0.784821,-1.147922,0.807955,1.254191, + -0.012448,0.906487,0.422051,-1.405685,0.573835,1.352181, + 0.238702,-0.258568,0.936036,-1.120716,0.424016,1.45699, + 0.238702,-0.258568,0.936036,-1.120716,0.424016,1.45699, + -0.012448,0.906487,0.422051,-1.405685,0.573835,1.352181, + -0.051905,0.965082,0.256753,-1.479588,0.295746,1.440042, + 0.238702,-0.258568,0.936036,-1.120716,0.424016,1.45699, + -0.051905,0.965082,0.256753,-1.479588,0.295746,1.440042, + 0.11717,0.938619,0.324447,-1.077307,0.165008,1.553393, + 0.11717,0.938619,0.324447,-1.077307,0.165008,1.553393, + -0.051905,0.965082,0.256753,-1.479588,0.295746,1.440042, + -0.088843,0.888,0.45118,-1.489699,-0.024215,1.510987, + 0.11717,0.938619,0.324447,-1.077307,0.165008,1.553393, + -0.088843,0.888,0.45118,-1.489699,-0.024215,1.510987, + 0.080398,0.9582,0.274571,-1.053434,-0.342553,1.690245, + 0.080398,0.9582,0.274571,-1.053434,-0.342553,1.690245, + -0.088843,0.888,0.45118,-1.489699,-0.024215,1.510987, + -0.169971,0.704712,0.688832,-1.395501,-0.698702,1.553257, + 0.080398,0.9582,0.274571,-1.053434,-0.342553,1.690245, + -0.169971,0.704712,0.688832,-1.395501,-0.698702,1.553257, + 0.069061,0.958871,0.275312,-1.077209,-0.869649,1.633144, + 0.069061,0.958871,0.275312,-1.077209,-0.869649,1.633144, + -0.169971,0.704712,0.688832,-1.395501,-0.698702,1.553257, + -0.261543,0.44691,0.855492,-1.376176,-0.948757,1.451608, + 0.069061,0.958871,0.275312,-1.077209,-0.869649,1.633144, + -0.261543,0.44691,0.855492,-1.376176,-0.948757,1.451608, + 0.051291,0.888276,0.456438,-1.061272,-1.141877,1.49623, + 0.051291,0.888276,0.456438,-1.061272,-1.141877,1.49623, + -0.261543,0.44691,0.855492,-1.376176,-0.948757,1.451608, + -0.33898,0.203127,0.918603,-1.402349,-1.127845,1.309055, + 0.051291,0.888276,0.456438,-1.061272,-1.141877,1.49623, + -0.33898,0.203127,0.918603,-1.402349,-1.127845,1.309055, + -0.008282,0.691944,0.721904,-1.001366,-1.335897,1.353338, + -0.008282,0.691944,0.721904,-1.001366,-1.335897,1.353338, + -0.33898,0.203127,0.918603,-1.402349,-1.127845,1.309055, + -0.351241,0.07582,0.93321,-1.407658,-1.236026,1.11293, + -0.008282,0.691944,0.721904,-1.001366,-1.335897,1.353338, + -0.351241,0.07582,0.93321,-1.407658,-1.236026,1.11293, + -0.0448,0.42163,0.905661,-0.952525,-1.440582,1.16865, + 0.213167,-0.525559,0.823619,2.013534,-0.662303,1.191491, + 0.009434,0.815301,0.578961,1.640095,-0.674556,1.246804, + 0.040473,0.760778,0.647749,1.644178,-0.857872,1.208494, + -0.057955,0.638634,0.767325,1.807583,1.756546,0.177627, + -0.720176,-0.693792,0,1.794465,1.787719,0, + 0.779025,-0.626993,0,1.456656,1.785879,0, + -0.057955,0.638634,0.767325,1.807583,1.756546,0.177627, + 0.779025,-0.626993,0,1.456656,1.785879,0, + 0.184661,-0.694307,0.695585,1.462507,1.745481,0.222394, + -0.024013,0.58573,0.810151,1.798719,1.714447,0.259352, + -0.057955,0.638634,0.767325,1.807583,1.756546,0.177627, + 0.184661,-0.694307,0.695585,1.462507,1.745481,0.222394, + -0.024013,0.58573,0.810151,1.798719,1.714447,0.259352, + 0.184661,-0.694307,0.695585,1.462507,1.745481,0.222394, + 0.152876,-0.742504,0.652163,1.483832,1.697594,0.288781, + 0.016737,0.497476,0.867316,1.821946,1.618209,0.403751, + -0.024013,0.58573,0.810151,1.798719,1.714447,0.259352, + 0.152876,-0.742504,0.652163,1.483832,1.697594,0.288781, + 0.016737,0.497476,0.867316,1.821946,1.618209,0.403751, + 0.152876,-0.742504,0.652163,1.483832,1.697594,0.288781, + 0.120054,-0.825719,0.551157,1.497138,1.618935,0.401108, + 0.060533,0.377837,0.923891,1.859443,1.450393,0.632222, + 0.016737,0.497476,0.867316,1.821946,1.618209,0.403751, + 0.120054,-0.825719,0.551157,1.497138,1.618935,0.401108, + 0.060533,0.377837,0.923891,1.859443,1.450393,0.632222, + 0.120054,-0.825719,0.551157,1.497138,1.618935,0.401108, + 0.102263,-0.969566,0.222452,1.504951,1.483493,0.585976, + 0.088722,0.251367,0.963817,1.958254,1.130271,0.861813, + 0.060533,0.377837,0.923891,1.859443,1.450393,0.632222, + 0.102263,-0.969566,0.222452,1.504951,1.483493,0.585976, + 0.088722,0.251367,0.963817,1.958254,1.130271,0.861813, + 0.102263,-0.969566,0.222452,1.504951,1.483493,0.585976, + -0.305786,-0.232288,0.923329,1.517126,1.334367,0.741076, + 0.107989,0.168108,0.979836,1.975941,0.827957,1.018423, + 0.088722,0.251367,0.963817,1.958254,1.130271,0.861813, + -0.305786,-0.232288,0.923329,1.517126,1.334367,0.741076, + 0.107989,0.168108,0.979836,1.975941,0.827957,1.018423, + -0.305786,-0.232288,0.923329,1.517126,1.334367,0.741076, + -0.148631,-0.373855,0.915501,1.570685,0.938327,0.989108, + 0.107989,0.168108,0.979836,1.975941,0.827957,1.018423, + -0.148631,-0.373855,0.915501,1.570685,0.938327,0.989108, + -0.185127,-0.491394,0.851035,1.582203,0.771083,1.06818, + 0.10833,0.05569,0.992554,2.023441,0.529338,1.144399, + 0.107989,0.168108,0.979836,1.975941,0.827957,1.018423, + -0.185127,-0.491394,0.851035,1.582203,0.771083,1.06818, + 0.10833,0.05569,0.992554,2.023441,0.529338,1.144399, + -0.185127,-0.491394,0.851035,1.582203,0.771083,1.06818, + -0.208715,-0.624734,0.752427,1.63008,0.420236,1.172369, + 0.114032,-0.218132,0.969234,2.0817,0.283249,1.259461, + 0.10833,0.05569,0.992554,2.023441,0.529338,1.144399, + -0.208715,-0.624734,0.752427,1.63008,0.420236,1.172369, + 0.114032,-0.218132,0.969234,2.0817,0.283249,1.259461, + -0.208715,-0.624734,0.752427,1.63008,0.420236,1.172369, + -0.251063,-0.683027,0.685888,1.649027,0.224458,1.211969, + 0.187438,-0.340915,0.921219,2.14179,-0.055306,1.295565, + 0.114032,-0.218132,0.969234,2.0817,0.283249,1.259461, + -0.251063,-0.683027,0.685888,1.649027,0.224458,1.211969, + 0.187438,-0.340915,0.921219,2.14179,-0.055306,1.295565, + -0.251063,-0.683027,0.685888,1.649027,0.224458,1.211969, + -0.252973,-0.819125,0.51482,1.660355,0.019397,1.246002, + 0.25339,-0.287519,0.923648,2.136269,-0.187666,1.278057, + 0.187438,-0.340915,0.921219,2.14179,-0.055306,1.295565, + -0.252973,-0.819125,0.51482,1.660355,0.019397,1.246002, + 0.25339,-0.287519,0.923648,2.136269,-0.187666,1.278057, + -0.252973,-0.819125,0.51482,1.660355,0.019397,1.246002, + -0.137161,-0.98063,0.139827,1.664159,-0.189659,1.266729, + 0.23972,-0.400363,0.884445,2.108912,-0.357128,1.259691, + 0.25339,-0.287519,0.923648,2.136269,-0.187666,1.278057, + -0.137161,-0.98063,0.139827,1.664159,-0.189659,1.266729, + 0.23972,-0.400363,0.884445,2.108912,-0.357128,1.259691, + -0.137161,-0.98063,0.139827,1.664159,-0.189659,1.266729, + 0.007127,0.896038,0.44392,1.678622,-0.410061,1.291177, + 0.213167,-0.525559,0.823619,2.013534,-0.662303,1.191491, + 0.23972,-0.400363,0.884445,2.108912,-0.357128,1.259691, + 0.007127,0.896038,0.44392,1.678622,-0.410061,1.291177, + 0.213167,-0.525559,0.823619,2.013534,-0.662303,1.191491, + 0.007127,0.896038,0.44392,1.678622,-0.410061,1.291177, + 0.009434,0.815301,0.578961,1.640095,-0.674556,1.246804, + 0.213167,-0.525559,0.823619,2.013534,-0.662303,1.191491, + -0.819256,-0.566976,0.085772,2.058189,-0.931238,1.163518, + -0.898389,-0.217201,-0.381735,2.158585,-0.955809,1.113647, + 0.213167,-0.525559,0.823619,2.013534,-0.662303,1.191491, + -0.898389,-0.217201,-0.381735,2.158585,-0.955809,1.113647, + -0.887036,-0.210048,-0.411154,2.222082,-0.957342,1.014137, + 0.213167,-0.525559,0.823619,2.013534,-0.662303,1.191491, + -0.887036,-0.210048,-0.411154,2.222082,-0.957342,1.014137, + -0.069142,0.724976,0.685295,2.245624,-0.864372,0.995778, + 0.213167,-0.525559,0.823619,2.013534,-0.662303,1.191491, + 0.040473,0.760778,0.647749,1.644178,-0.857872,1.208494, + -0.493424,-0.16561,-0.853877,1.635139,-0.965221,1.184968, + 0.213167,-0.525559,0.823619,2.013534,-0.662303,1.191491, + -0.493424,-0.16561,-0.853877,1.635139,-0.965221,1.184968, + 0.193853,0.161608,0.967628,1.867657,-0.920633,1.206933, + 0.213167,-0.525559,0.823619,2.013534,-0.662303,1.191491, + 0.193853,0.161608,0.967628,1.867657,-0.920633,1.206933, + -0.819256,-0.566976,0.085772,2.058189,-0.931238,1.163518, + -0.034649,0.9994,0,1.920432,-1.567396,0, + -0.086361,-0.084973,0.992634,1.963153,-1.588839,0.612861, + 0.776291,-0.374867,0.5068,1.721211,-1.590185,0.601932, + -0.034649,0.9994,0,1.920432,-1.567396,0, + 0.776291,-0.374867,0.5068,1.721211,-1.590185,0.601932, + -0.560667,-0.828041,0,1.604939,-1.556997,0, + 0.751148,0.43192,-0.49922,1.451825,-1.576856,0.702758, + 0.010538,0.399391,0.91672,1.328862,-1.352627,0.758733, + -0.263451,-0.648591,0.714089,1.19204,-1.330605,0.678707, + 0.751148,0.43192,-0.49922,1.451825,-1.576856,0.702758, + -0.263451,-0.648591,0.714089,1.19204,-1.330605,0.678707, + -0.301558,-0.77828,0.550766,1.210555,-1.460061,0.576841, + 0.24139,0.178826,-0.953809,1.599889,-1.595526,0.623185, + 0.751148,0.43192,-0.49922,1.451825,-1.576856,0.702758, + -0.301558,-0.77828,0.550766,1.210555,-1.460061,0.576841, + 0.24139,0.178826,-0.953809,1.599889,-1.595526,0.623185, + -0.301558,-0.77828,0.550766,1.210555,-1.460061,0.576841, + -0.154129,-0.981148,0.116585,1.223415,-1.532658,0.434522, + -0.034649,0.9994,0,1.920432,-1.567396,0, + 0.140536,0.558684,0.817388,2.0482,-1.581983,0.555832, + -0.086361,-0.084973,0.992634,1.963153,-1.588839,0.612861, + 0.24139,0.178826,-0.953809,1.599889,-1.595526,0.623185, + -0.154129,-0.981148,0.116585,1.223415,-1.532658,0.434522, + 0.770209,-0.637792,0,1.289448,-1.546597,0, + 0.24139,0.178826,-0.953809,1.599889,-1.595526,0.623185, + 0.770209,-0.637792,0,1.289448,-1.546597,0, + -0.560667,-0.828041,0,1.604939,-1.556997,0, + 0.776291,-0.374867,0.5068,1.721211,-1.590185,0.601932, + 0.24139,0.178826,-0.953809,1.599889,-1.595526,0.623185, + -0.560667,-0.828041,0,1.604939,-1.556997,0, + 0.010538,0.399391,0.91672,1.328862,-1.352627,0.758733, + -0.228294,-0.186048,0.955651,1.348219,-1.282064,0.845204, + -0.267766,-0.862787,0.428835,1.219163,-1.218342,0.823029, + 0.010538,0.399391,0.91672,1.328862,-1.352627,0.758733, + -0.267766,-0.862787,0.428835,1.219163,-1.218342,0.823029, + -0.263451,-0.648591,0.714089,1.19204,-1.330605,0.678707, + -0.382074,-0.25681,-0.887732,1.337875,-0.945716,1.021299, + -0.218261,-0.26262,0.93989,1.373216,-0.56462,1.106245, + -0.231653,-0.530839,0.815198,1.252961,-0.928825,1.001643, + 0.43768,-0.823149,-0.361748,1.310865,-1.136322,0.914838, + -0.382074,-0.25681,-0.887732,1.337875,-0.945716,1.021299, + -0.231653,-0.530839,0.815198,1.252961,-0.928825,1.001643, + 0.43768,-0.823149,-0.361748,1.310865,-1.136322,0.914838, + -0.231653,-0.530839,0.815198,1.252961,-0.928825,1.001643, + -0.253979,-0.745808,0.615845,1.230116,-1.085439,0.894543, + -0.228294,-0.186048,0.955651,1.348219,-1.282064,0.845204, + 0.43768,-0.823149,-0.361748,1.310865,-1.136322,0.914838, + -0.253979,-0.745808,0.615845,1.230116,-1.085439,0.894543, + -0.228294,-0.186048,0.955651,1.348219,-1.282064,0.845204, + -0.253979,-0.745808,0.615845,1.230116,-1.085439,0.894543, + -0.267766,-0.862787,0.428835,1.219163,-1.218342,0.823029, + -0.570406,-0.192005,-0.798606,1.536037,-0.985876,1.185597, + -0.493424,-0.16561,-0.853877,1.635139,-0.965221,1.184968, + 0.040473,0.760778,0.647749,1.644178,-0.857872,1.208494, + -0.53197,-0.108751,-0.839751,1.428883,-0.98669,1.133905, + -0.570406,-0.192005,-0.798606,1.536037,-0.985876,1.185597, + 0.040473,0.760778,0.647749,1.644178,-0.857872,1.208494, + -0.53197,-0.108751,-0.839751,1.428883,-0.98669,1.133905, + 0.040473,0.760778,0.647749,1.644178,-0.857872,1.208494, + 0.009434,0.815301,0.578961,1.640095,-0.674556,1.246804, + 0.009434,0.815301,0.578961,1.640095,-0.674556,1.246804, + 0.007127,0.896038,0.44392,1.678622,-0.410061,1.291177, + -0.218261,-0.26262,0.93989,1.373216,-0.56462,1.106245, + -0.53197,-0.108751,-0.839751,1.428883,-0.98669,1.133905, + 0.009434,0.815301,0.578961,1.640095,-0.674556,1.246804, + -0.218261,-0.26262,0.93989,1.373216,-0.56462,1.106245, + 0.981421,-0.191868,0,0.733818,1.740873,0, + 0.184661,-0.694307,0.695585,1.462507,1.745481,0.222394, + 0.779025,-0.626993,0,1.456656,1.785879,0, + -0.165685,0.059692,0.98437,0.912989,-1.499314,0.419547, + 0.92802,-0.37253,0,0.927497,-1.558489,0, + 0.770209,-0.637792,0,1.289448,-1.546597,0, + -0.165685,0.059692,0.98437,0.912989,-1.499314,0.419547, + 0.770209,-0.637792,0,1.289448,-1.546597,0, + -0.154129,-0.981148,0.116585,1.223415,-1.532658,0.434522, + -0.123389,0.256577,0.958615,0.912699,-1.455066,0.576185, + -0.165685,0.059692,0.98437,0.912989,-1.499314,0.419547, + -0.154129,-0.981148,0.116585,1.223415,-1.532658,0.434522, + -0.123389,0.256577,0.958615,0.912699,-1.455066,0.576185, + -0.154129,-0.981148,0.116585,1.223415,-1.532658,0.434522, + -0.301558,-0.77828,0.550766,1.210555,-1.460061,0.576841, + -0.078623,0.370994,0.925301,0.922703,-1.296032,0.728307, + -0.123389,0.256577,0.958615,0.912699,-1.455066,0.576185, + -0.301558,-0.77828,0.550766,1.210555,-1.460061,0.576841, + -0.078623,0.370994,0.925301,0.922703,-1.296032,0.728307, + -0.301558,-0.77828,0.550766,1.210555,-1.460061,0.576841, + -0.263451,-0.648591,0.714089,1.19204,-1.330605,0.678707, + 0.070189,0.510248,0.857158,0.93066,-1.216516,0.831196, + -0.078623,0.370994,0.925301,0.922703,-1.296032,0.728307, + -0.263451,-0.648591,0.714089,1.19204,-1.330605,0.678707, + 0.070189,0.510248,0.857158,0.93066,-1.216516,0.831196, + -0.263451,-0.648591,0.714089,1.19204,-1.330605,0.678707, + -0.267766,-0.862787,0.428835,1.219163,-1.218342,0.823029, + 0.242426,0.58207,0.77616,0.956456,-1.070504,0.921063, + 0.070189,0.510248,0.857158,0.93066,-1.216516,0.831196, + -0.267766,-0.862787,0.428835,1.219163,-1.218342,0.823029, + 0.242426,0.58207,0.77616,0.956456,-1.070504,0.921063, + -0.267766,-0.862787,0.428835,1.219163,-1.218342,0.823029, + -0.253979,-0.745808,0.615845,1.230116,-1.085439,0.894543, + 0.325482,0.443544,0.835063,0.939974,-0.894739,1.019809, + 0.242426,0.58207,0.77616,0.956456,-1.070504,0.921063, + -0.253979,-0.745808,0.615845,1.230116,-1.085439,0.894543, + 0.325482,0.443544,0.835063,0.939974,-0.894739,1.019809, + -0.253979,-0.745808,0.615845,1.230116,-1.085439,0.894543, + -0.231653,-0.530839,0.815198,1.252961,-0.928825,1.001643, + 0.305452,0.425365,0.851918,0.948819,-0.638568,1.102958, + 0.325482,0.443544,0.835063,0.939974,-0.894739,1.019809, + -0.231653,-0.530839,0.815198,1.252961,-0.928825,1.001643, + 0.305452,0.425365,0.851918,0.948819,-0.638568,1.102958, + -0.231653,-0.530839,0.815198,1.252961,-0.928825,1.001643, + -0.218261,-0.26262,0.93989,1.373216,-0.56462,1.106245, + 0.235667,0.756618,0.60991,0.97453,-0.525273,1.140353, + 0.305452,0.425365,0.851918,0.948819,-0.638568,1.102958, + -0.218261,-0.26262,0.93989,1.373216,-0.56462,1.106245, + 0.150328,0.92948,0.336851,0.960321,-0.308052,1.243133, + 0.235667,0.756618,0.60991,0.97453,-0.525273,1.140353, + -0.218261,-0.26262,0.93989,1.373216,-0.56462,1.106245, + 0.150328,0.92948,0.336851,0.960321,-0.308052,1.243133, + -0.218261,-0.26262,0.93989,1.373216,-0.56462,1.106245, + 0.007127,0.896038,0.44392,1.678622,-0.410061,1.291177, + 0.100598,0.942931,0.317428,0.943855,-0.101127,1.274771, + 0.150328,0.92948,0.336851,0.960321,-0.308052,1.243133, + 0.007127,0.896038,0.44392,1.678622,-0.410061,1.291177, + 0.100598,0.942931,0.317428,0.943855,-0.101127,1.274771, + 0.007127,0.896038,0.44392,1.678622,-0.410061,1.291177, + -0.137161,-0.98063,0.139827,1.664159,-0.189659,1.266729, + 0.076524,0.950336,0.301672,0.950215,0.042751,1.256188, + 0.100598,0.942931,0.317428,0.943855,-0.101127,1.274771, + -0.137161,-0.98063,0.139827,1.664159,-0.189659,1.266729, + 0.076524,0.950336,0.301672,0.950215,0.042751,1.256188, + -0.137161,-0.98063,0.139827,1.664159,-0.189659,1.266729, + -0.252973,-0.819125,0.51482,1.660355,0.019397,1.246002, + 0.013768,-0.992402,0.122267,0.927775,0.195225,1.233043, + 0.076524,0.950336,0.301672,0.950215,0.042751,1.256188, + -0.252973,-0.819125,0.51482,1.660355,0.019397,1.246002, + 0.013768,-0.992402,0.122267,0.927775,0.195225,1.233043, + -0.252973,-0.819125,0.51482,1.660355,0.019397,1.246002, + -0.251063,-0.683027,0.685888,1.649027,0.224458,1.211969, + 0.037423,-0.986705,0.158154,0.939271,0.379986,1.185872, + 0.013768,-0.992402,0.122267,0.927775,0.195225,1.233043, + -0.251063,-0.683027,0.685888,1.649027,0.224458,1.211969, + 0.037423,-0.986705,0.158154,0.939271,0.379986,1.185872, + -0.251063,-0.683027,0.685888,1.649027,0.224458,1.211969, + -0.208715,-0.624734,0.752427,1.63008,0.420236,1.172369, + 0.034172,-0.858604,0.511498,0.921312,0.755659,0.99933, + 0.037423,-0.986705,0.158154,0.939271,0.379986,1.185872, + -0.208715,-0.624734,0.752427,1.63008,0.420236,1.172369, + 0.034172,-0.858604,0.511498,0.921312,0.755659,0.99933, + -0.208715,-0.624734,0.752427,1.63008,0.420236,1.172369, + -0.185127,-0.491394,0.851035,1.582203,0.771083,1.06818, + 0.004725,-0.680391,0.732834,0.857323,0.985001,0.874029, + 0.034172,-0.858604,0.511498,0.921312,0.755659,0.99933, + -0.185127,-0.491394,0.851035,1.582203,0.771083,1.06818, + 0.004725,-0.680391,0.732834,0.857323,0.985001,0.874029, + -0.185127,-0.491394,0.851035,1.582203,0.771083,1.06818, + -0.148631,-0.373855,0.915501,1.570685,0.938327,0.989108, + 0.023352,-0.872807,0.487506,0.760722,1.205036,0.700545, + 0.004725,-0.680391,0.732834,0.857323,0.985001,0.874029, + -0.148631,-0.373855,0.915501,1.570685,0.938327,0.989108, + 0.068777,-0.757383,0.649339,0.725959,1.478055,0.461804, + 0.023352,-0.872807,0.487506,0.760722,1.205036,0.700545, + -0.148631,-0.373855,0.915501,1.570685,0.938327,0.989108, + 0.068777,-0.757383,0.649339,0.725959,1.478055,0.461804, + -0.148631,-0.373855,0.915501,1.570685,0.938327,0.989108, + -0.305786,-0.232288,0.923329,1.517126,1.334367,0.741076, + 0.100949,-0.548551,0.830001,0.737904,1.604213,0.281713, + 0.068777,-0.757383,0.649339,0.725959,1.478055,0.461804, + -0.305786,-0.232288,0.923329,1.517126,1.334367,0.741076, + 0.100949,-0.548551,0.830001,0.737904,1.604213,0.281713, + -0.305786,-0.232288,0.923329,1.517126,1.334367,0.741076, + 0.102263,-0.969566,0.222452,1.504951,1.483493,0.585976, + 0.100949,-0.548551,0.830001,0.737904,1.604213,0.281713, + 0.102263,-0.969566,0.222452,1.504951,1.483493,0.585976, + 0.120054,-0.825719,0.551157,1.497138,1.618935,0.401108, + 0.981421,-0.191868,0,0.733818,1.740873,0, + 0.100949,-0.548551,0.830001,0.737904,1.604213,0.281713, + 0.120054,-0.825719,0.551157,1.497138,1.618935,0.401108, + 0.981421,-0.191868,0,0.733818,1.740873,0, + 0.120054,-0.825719,0.551157,1.497138,1.618935,0.401108, + 0.152876,-0.742504,0.652163,1.483832,1.697594,0.288781, + 0.981421,-0.191868,0,0.733818,1.740873,0, + 0.152876,-0.742504,0.652163,1.483832,1.697594,0.288781, + 0.184661,-0.694307,0.695585,1.462507,1.745481,0.222394, + 0.566114,-0.824327,0,0.234527,1.730117,0, + -0.039092,-0.999236,0,-0.228904,1.734267,0, + 0.067879,0.951186,0.30106,-0.221516,1.686349,0.151403, + 0.566114,-0.824327,0,0.234527,1.730117,0, + 0.067879,0.951186,0.30106,-0.221516,1.686349,0.151403, + 0.095331,0.952335,0.289775,0.223642,1.684075,0.160743, + 0.095331,0.952335,0.289775,0.223642,1.684075,0.160743, + 0.067879,0.951186,0.30106,-0.221516,1.686349,0.151403, + 0.085022,0.963119,0.255291,-0.267035,1.627058,0.266577, + 0.095331,0.952335,0.289775,0.223642,1.684075,0.160743, + 0.085022,0.963119,0.255291,-0.267035,1.627058,0.266577, + 0.10291,0.954344,0.280422,0.23733,1.595746,0.288672, + 0.10291,0.954344,0.280422,0.23733,1.595746,0.288672, + 0.085022,0.963119,0.255291,-0.267035,1.627058,0.266577, + 0.120743,0.971588,0.203561,-0.247999,1.565146,0.389142, + 0.10291,0.954344,0.280422,0.23733,1.595746,0.288672, + 0.120743,0.971588,0.203561,-0.247999,1.565146,0.389142, + 0.172251,0.950689,0.257916,0.289039,1.496446,0.430055, + 0.172251,0.950689,0.257916,0.289039,1.496446,0.430055, + 0.120743,0.971588,0.203561,-0.247999,1.565146,0.389142, + 0.117963,0.926753,0.356669,-0.179548,1.471301,0.544513, + 0.172251,0.950689,0.257916,0.289039,1.496446,0.430055, + 0.117963,0.926753,0.356669,-0.179548,1.471301,0.544513, + 0.28101,0.853935,0.437982,0.305671,1.298417,0.629719, + 0.28101,0.853935,0.437982,0.305671,1.298417,0.629719, + 0.117963,0.926753,0.356669,-0.179548,1.471301,0.544513, + 0.109947,0.693426,0.71209,-0.192546,1.305535,0.70008, + 0.28101,0.853935,0.437982,0.305671,1.298417,0.629719, + 0.109947,0.693426,0.71209,-0.192546,1.305535,0.70008, + 0.381239,0.555717,0.738807,0.243473,1.134082,0.819993, + 0.381239,0.555717,0.738807,0.243473,1.134082,0.819993, + 0.109947,0.693426,0.71209,-0.192546,1.305535,0.70008, + 0.076565,0.333251,0.939724,-0.406155,1.005088,0.971088, + 0.381239,0.555717,0.738807,0.243473,1.134082,0.819993, + 0.076565,0.333251,0.939724,-0.406155,1.005088,0.971088, + 0.376012,0.360026,0.853813,0.316341,0.785311,1.08626, + 0.376012,0.360026,0.853813,0.316341,0.785311,1.08626, + 0.076565,0.333251,0.939724,-0.406155,1.005088,0.971088, + -0.039599,0.171847,0.984327,-0.11519,0.458427,1.346197, + 0.376012,0.360026,0.853813,0.316341,0.785311,1.08626, + -0.039599,0.171847,0.984327,-0.11519,0.458427,1.346197, + 0.207079,0.373404,0.904261,0.539252,0.353984,1.254493, + 0.207079,0.373404,0.904261,0.539252,0.353984,1.254493, + -0.039599,0.171847,0.984327,-0.11519,0.458427,1.346197, + -0.164971,0.181757,0.969406,0.005537,0.163519,1.472265, + 0.207079,0.373404,0.904261,0.539252,0.353984,1.254493, + -0.164971,0.181757,0.969406,0.005537,0.163519,1.472265, + -0.045242,0.348413,0.936249,0.53915,0.148262,1.321014, + -0.045242,0.348413,0.936249,0.53915,0.148262,1.321014, + -0.164971,0.181757,0.969406,0.005537,0.163519,1.472265, + -0.216817,0.278777,0.935561,0.018086,0.002865,1.523199, + -0.045242,0.348413,0.936249,0.53915,0.148262,1.321014, + -0.216817,0.278777,0.935561,0.018086,0.002865,1.523199, + -0.212948,0.334057,0.918182,0.516872,-0.020713,1.356627, + -0.212948,0.334057,0.918182,0.516872,-0.020713,1.356627, + -0.216817,0.278777,0.935561,0.018086,0.002865,1.523199, + -0.219724,0.297861,0.928978,0.034087,-0.225059,1.542949, + -0.212948,0.334057,0.918182,0.516872,-0.020713,1.356627, + -0.219724,0.297861,0.928978,0.034087,-0.225059,1.542949, + -0.282152,0.285245,0.915983,0.542386,-0.188227,1.370375, + -0.282152,0.285245,0.915983,0.542386,-0.188227,1.370375, + -0.219724,0.297861,0.928978,0.034087,-0.225059,1.542949, + -0.227369,0.161984,0.960242,0.010486,-0.502317,1.576297, + -0.282152,0.285245,0.915983,0.542386,-0.188227,1.370375, + -0.227369,0.161984,0.960242,0.010486,-0.502317,1.576297, + -0.326048,0.118611,0.937883,0.546875,-0.39094,1.363244, + -0.326048,0.118611,0.937883,0.546875,-0.39094,1.363244, + -0.227369,0.161984,0.960242,0.010486,-0.502317,1.576297, + -0.30296,-0.137183,0.943078,0.021051,-0.831931,1.511548, + -0.326048,0.118611,0.937883,0.546875,-0.39094,1.363244, + -0.30296,-0.137183,0.943078,0.021051,-0.831931,1.511548, + -0.422758,-0.178302,0.888529,0.550658,-0.633015,1.331311, + -0.422758,-0.178302,0.888529,0.550658,-0.633015,1.331311, + -0.30296,-0.137183,0.943078,0.021051,-0.831931,1.511548, + -0.387895,-0.42081,0.820034,-0.04157,-1.143825,1.395176, + -0.422758,-0.178302,0.888529,0.550658,-0.633015,1.331311, + -0.387895,-0.42081,0.820034,-0.04157,-1.143825,1.395176, + -0.504483,-0.438591,0.743731,0.527724,-0.862854,1.253811, + -0.504483,-0.438591,0.743731,0.527724,-0.862854,1.253811, + -0.387895,-0.42081,0.820034,-0.04157,-1.143825,1.395176, + -0.433119,-0.541142,0.720814,-0.071941,-1.346991,1.237379, + -0.504483,-0.438591,0.743731,0.527724,-0.862854,1.253811, + -0.433119,-0.541142,0.720814,-0.071941,-1.346991,1.237379, + -0.53858,-0.616298,0.57455,0.544825,-1.133123,1.096902, + -0.53858,-0.616298,0.57455,0.544825,-1.133123,1.096902, + -0.433119,-0.541142,0.720814,-0.071941,-1.346991,1.237379, + -0.455057,-0.684123,0.569999,-0.0723,-1.450245,1.087397, + -0.53858,-0.616298,0.57455,0.544825,-1.133123,1.096902, + -0.455057,-0.684123,0.569999,-0.0723,-1.450245,1.087397, + -0.507894,-0.767261,0.391606,0.530629,-1.316423,0.929842, + -0.507894,-0.767261,0.391606,0.530629,-1.316423,0.929842, + -0.455057,-0.684123,0.569999,-0.0723,-1.450245,1.087397, + -0.084259,-0.367691,0.926123,-0.063012,-1.583021,0.865082, + -0.507894,-0.767261,0.391606,0.530629,-1.316423,0.929842, + -0.084259,-0.367691,0.926123,-0.063012,-1.583021,0.865082, + -0.375453,-0.69207,0.616502,0.538756,-1.408602,0.764911, + -0.375453,-0.69207,0.616502,0.538756,-1.408602,0.764911, + -0.084259,-0.367691,0.926123,-0.063012,-1.583021,0.865082, + 0.061261,0.954316,0.292452,-0.07847,-1.688266,0.80023, + -0.375453,-0.69207,0.616502,0.538756,-1.408602,0.764911, + 0.061261,0.954316,0.292452,-0.07847,-1.688266,0.80023, + -0.1427,-0.847733,0.510868,0.489819,-1.524947,0.672392, + 0.061261,0.954316,0.292452,-0.07847,-1.688266,0.80023, + 0.076968,0.969253,0.233719,-0.094135,-1.769086,0.556924, + -0.1427,-0.847733,0.510868,0.489819,-1.524947,0.672392, + -0.009814,-0.999952,0,-0.547248,1.742126,0, + -0.098179,0.995169,0,-0.866132,1.75467,0, + 0.136965,0.155729,0.978258,-0.894132,1.712652,0.151911, + -0.009814,-0.999952,0,-0.547248,1.742126,0, + 0.136965,0.155729,0.978258,-0.894132,1.712652,0.151911, + -0.021294,0.896295,0.442946,-0.559706,1.69418,0.186107, + -0.021294,0.896295,0.442946,-0.559706,1.69418,0.186107, + 0.136965,0.155729,0.978258,-0.894132,1.712652,0.151911, + 0.173447,0.205435,0.963178,-0.954897,1.677544,0.293034, + -0.021294,0.896295,0.442946,-0.559706,1.69418,0.186107, + 0.173447,0.205435,0.963178,-0.954897,1.677544,0.293034, + -0.072244,0.618144,0.782738,-0.557624,1.641278,0.271462, + -0.072244,0.618144,0.782738,-0.557624,1.641278,0.271462, + 0.173447,0.205435,0.963178,-0.954897,1.677544,0.293034, + 0.136801,0.29658,0.945159,-1.017767,1.607824,0.541965, + -0.072244,0.618144,0.782738,-0.557624,1.641278,0.271462, + 0.136801,0.29658,0.945159,-1.017767,1.607824,0.541965, + -0.038944,0.247819,0.968023,-0.626493,1.585426,0.443136, + -0.038944,0.247819,0.968023,-0.626493,1.585426,0.443136, + 0.136801,0.29658,0.945159,-1.017767,1.607824,0.541965, + 0.095019,0.330845,0.938889,-1.04607,1.509097,0.76106, + -0.038944,0.247819,0.968023,-0.626493,1.585426,0.443136, + 0.095019,0.330845,0.938889,-1.04607,1.509097,0.76106, + -0.00315,0.115338,0.993321,-0.597781,1.48962,0.641047, + -0.00315,0.115338,0.993321,-0.597781,1.48962,0.641047, + 0.095019,0.330845,0.938889,-1.04607,1.509097,0.76106, + 0.07657,0.16758,0.982881,-1.115594,1.39238,0.819623, + -0.00315,0.115338,0.993321,-0.597781,1.48962,0.641047, + 0.07657,0.16758,0.982881,-1.115594,1.39238,0.819623, + 0.016683,0.197618,0.980137,-0.674657,1.333008,0.761059, + 0.016683,0.197618,0.980137,-0.674657,1.333008,0.761059, + 0.07657,0.16758,0.982881,-1.115594,1.39238,0.819623, + 0.079214,-0.175111,0.981357,-1.278903,1.192051,0.946843, + 0.016683,0.197618,0.980137,-0.674657,1.333008,0.761059, + 0.079214,-0.175111,0.981357,-1.278903,1.192051,0.946843, + 0.032424,0.316591,0.948008,-0.910602,1.204118,0.83774, + 0.032424,0.316591,0.948008,-0.910602,1.204118,0.83774, + 0.079214,-0.175111,0.981357,-1.278903,1.192051,0.946843, + 0.204115,-0.405276,0.891116,-1.200768,0.978822,1.103391, + 0.032424,0.316591,0.948008,-0.910602,1.204118,0.83774, + 0.204115,-0.405276,0.891116,-1.200768,0.978822,1.103391, + 0.053195,0.343167,0.937767,-0.969076,0.901205,1.146223, + 0.053195,0.343167,0.937767,-0.969076,0.901205,1.146223, + 0.204115,-0.405276,0.891116,-1.200768,0.978822,1.103391, + 0.396045,-0.47666,0.784821,-1.147922,0.807955,1.254191, + 0.053195,0.343167,0.937767,-0.969076,0.901205,1.146223, + 0.396045,-0.47666,0.784821,-1.147922,0.807955,1.254191, + 0.057735,0.173734,0.983099,-0.752416,0.438132,1.467349, + 0.057735,0.173734,0.983099,-0.752416,0.438132,1.467349, + 0.396045,-0.47666,0.784821,-1.147922,0.807955,1.254191, + 0.238702,-0.258568,0.936036,-1.120716,0.424016,1.45699, + 0.057735,0.173734,0.983099,-0.752416,0.438132,1.467349, + 0.238702,-0.258568,0.936036,-1.120716,0.424016,1.45699, + 0.058723,-0.195869,0.97887,-0.645496,0.179261,1.584316, + 0.058723,-0.195869,0.97887,-0.645496,0.179261,1.584316, + 0.238702,-0.258568,0.936036,-1.120716,0.424016,1.45699, + 0.11717,0.938619,0.324447,-1.077307,0.165008,1.553393, + 0.058723,-0.195869,0.97887,-0.645496,0.179261,1.584316, + 0.11717,0.938619,0.324447,-1.077307,0.165008,1.553393, + 0.088769,-0.475351,0.875307,-0.536767,-0.144454,1.682232, + 0.088769,-0.475351,0.875307,-0.536767,-0.144454,1.682232, + 0.11717,0.938619,0.324447,-1.077307,0.165008,1.553393, + 0.080398,0.9582,0.274571,-1.053434,-0.342553,1.690245, + 0.088769,-0.475351,0.875307,-0.536767,-0.144454,1.682232, + 0.080398,0.9582,0.274571,-1.053434,-0.342553,1.690245, + 0.099302,-0.563694,0.819993,-0.533528,-0.58228,1.701405, + 0.099302,-0.563694,0.819993,-0.533528,-0.58228,1.701405, + 0.080398,0.9582,0.274571,-1.053434,-0.342553,1.690245, + 0.069061,0.958871,0.275312,-1.077209,-0.869649,1.633144, + 0.099302,-0.563694,0.819993,-0.533528,-0.58228,1.701405, + 0.069061,0.958871,0.275312,-1.077209,-0.869649,1.633144, + 0.093802,-0.705497,0.702478,-0.505045,-0.913827,1.645612, + 0.093802,-0.705497,0.702478,-0.505045,-0.913827,1.645612, + 0.069061,0.958871,0.275312,-1.077209,-0.869649,1.633144, + 0.051291,0.888276,0.456438,-1.061272,-1.141877,1.49623, + 0.093802,-0.705497,0.702478,-0.505045,-0.913827,1.645612, + 0.051291,0.888276,0.456438,-1.061272,-1.141877,1.49623, + 0.058028,-0.329667,0.942312,-0.487217,-1.193519,1.504026, + 0.058028,-0.329667,0.942312,-0.487217,-1.193519,1.504026, + 0.051291,0.888276,0.456438,-1.061272,-1.141877,1.49623, + -0.008282,0.691944,0.721904,-1.001366,-1.335897,1.353338, + 0.058028,-0.329667,0.942312,-0.487217,-1.193519,1.504026, + -0.008282,0.691944,0.721904,-1.001366,-1.335897,1.353338, + 0.096347,0.961203,0.258467,-0.524231,-1.399266,1.313019, + 0.096347,0.961203,0.258467,-0.524231,-1.399266,1.313019, + -0.008282,0.691944,0.721904,-1.001366,-1.335897,1.353338, + -0.0448,0.42163,0.905661,-0.952525,-1.440582,1.16865, + 0.096347,0.961203,0.258467,-0.524231,-1.399266,1.313019, + -0.0448,0.42163,0.905661,-0.952525,-1.440582,1.16865, + 0.098712,0.966371,0.23745,-0.526127,-1.495,1.167736, + 0.098712,0.966371,0.23745,-0.526127,-1.495,1.167736, + -0.0448,0.42163,0.905661,-0.952525,-1.440582,1.16865, + -0.02449,0.224062,0.974267,-0.953236,-1.545941,0.89918, + 0.098712,0.966371,0.23745,-0.526127,-1.495,1.167736, + -0.02449,0.224062,0.974267,-0.953236,-1.545941,0.89918, + 0.079848,0.962653,0.258695,-0.535144,-1.615983,0.920556, + 0.136523,0.621747,0.771228,2.881063,-0.493146,0.521968, + 0.478274,-0.500384,0.721713,2.736198,-0.346225,0.659345, + 0.245892,-0.489895,0.836385,2.688131,-0.517509,0.672975, + 0.048754,0.934073,0.353738,2.824356,-1.407256,0.355013, + 0.303729,-0.050718,0.951408,2.740886,-1.339225,0.463604, + 0.33122,-0.270106,0.904067,2.663024,-1.440487,0.478149, + -0.382074,-0.25681,-0.887732,1.337875,-0.945716,1.021299, + -0.53197,-0.108751,-0.839751,1.428883,-0.98669,1.133905, + -0.218261,-0.26262,0.93989,1.373216,-0.56462,1.106245, + -0.065586,-0.997847,0,-1.179474,1.786649,0, + 0.262234,-0.965004,0,-1.35095,1.807009,0, + -0.234266,0.044111,0.971171,-1.365948,1.769608,0.133901, + -0.065586,-0.997847,0,-1.179474,1.786649,0, + -0.234266,0.044111,0.971171,-1.365948,1.769608,0.133901, + -0.115746,0.20405,0.972094,-1.215563,1.757097,0.133494, + -0.115746,0.20405,0.972094,-1.215563,1.757097,0.133494, + -0.234266,0.044111,0.971171,-1.365948,1.769608,0.133901, + -0.108631,-0.122719,0.986478,-1.396332,1.723782,0.267642, + -0.115746,0.20405,0.972094,-1.215563,1.757097,0.133494, + -0.108631,-0.122719,0.986478,-1.396332,1.723782,0.267642, + -0.164191,0.153328,0.974439,-1.227613,1.709095,0.276029, + -0.164191,0.153328,0.974439,-1.227613,1.709095,0.276029, + -0.108631,-0.122719,0.986478,-1.396332,1.723782,0.267642, + -0.006683,-0.232823,0.972496,-1.417595,1.67618,0.529265, + -0.164191,0.153328,0.974439,-1.227613,1.709095,0.276029, + -0.006683,-0.232823,0.972496,-1.417595,1.67618,0.529265, + -0.15812,-0.033626,0.986847,-1.292756,1.656509,0.51403, + -0.15812,-0.033626,0.986847,-1.292756,1.656509,0.51403, + -0.006683,-0.232823,0.972496,-1.417595,1.67618,0.529265, + -0.004872,-0.216103,0.976358,-1.465432,1.655336,0.722125, + -0.15812,-0.033626,0.986847,-1.292756,1.656509,0.51403, + -0.004872,-0.216103,0.976358,-1.465432,1.655336,0.722125, + 0.005821,-0.234321,0.972142,-1.338488,1.613735,0.725441, + 0.005821,-0.234321,0.972142,-1.338488,1.613735,0.725441, + -0.004872,-0.216103,0.976358,-1.465432,1.655336,0.722125, + 0.193955,-0.251788,0.948148,-1.582187,1.567542,0.982349, + 0.005821,-0.234321,0.972142,-1.338488,1.613735,0.725441, + 0.193955,-0.251788,0.948148,-1.582187,1.567542,0.982349, + 0.243464,-0.335965,0.909864,-1.403848,1.533059,0.902827, + 0.243464,-0.335965,0.909864,-1.403848,1.533059,0.902827, + 0.193955,-0.251788,0.948148,-1.582187,1.567542,0.982349, + -0.337275,0.918092,0.208215,-1.721806,1.391264,1.113307, + 0.243464,-0.335965,0.909864,-1.403848,1.533059,0.902827, + -0.337275,0.918092,0.208215,-1.721806,1.391264,1.113307, + 0.49938,-0.45475,0.737443,-1.551526,1.400025,1.050193, + 0.49938,-0.45475,0.737443,-1.551526,1.400025,1.050193, + -0.337275,0.918092,0.208215,-1.721806,1.391264,1.113307, + -0.47652,0.732046,0.486866,-1.733703,1.083864,1.181489, + 0.49938,-0.45475,0.737443,-1.551526,1.400025,1.050193, + -0.47652,0.732046,0.486866,-1.733703,1.083864,1.181489, + 0.573426,-0.441087,0.69038,-1.552899,1.128654,1.15104, + 0.573426,-0.441087,0.69038,-1.552899,1.128654,1.15104, + -0.47652,0.732046,0.486866,-1.733703,1.083864,1.181489, + -0.505556,0.519614,0.688777,-1.807421,0.657142,1.209422, + 0.573426,-0.441087,0.69038,-1.552899,1.128654,1.15104, + -0.505556,0.519614,0.688777,-1.807421,0.657142,1.209422, + 0.1643,0.873906,0.457487,-1.454529,0.875045,1.238858, + 0.1643,0.873906,0.457487,-1.454529,0.875045,1.238858, + -0.505556,0.519614,0.688777,-1.807421,0.657142,1.209422, + -0.539732,0.31653,0.780063,-1.796156,0.452382,1.243643, + 0.1643,0.873906,0.457487,-1.454529,0.875045,1.238858, + -0.539732,0.31653,0.780063,-1.796156,0.452382,1.243643, + -0.012448,0.906487,0.422051,-1.405685,0.573835,1.352181, + -0.012448,0.906487,0.422051,-1.405685,0.573835,1.352181, + -0.539732,0.31653,0.780063,-1.796156,0.452382,1.243643, + -0.545639,0.142044,0.825894,-1.81092,0.287592,1.292257, + -0.012448,0.906487,0.422051,-1.405685,0.573835,1.352181, + -0.545639,0.142044,0.825894,-1.81092,0.287592,1.292257, + -0.051905,0.965082,0.256753,-1.479588,0.295746,1.440042, + -0.051905,0.965082,0.256753,-1.479588,0.295746,1.440042, + -0.545639,0.142044,0.825894,-1.81092,0.287592,1.292257, + -0.512472,0.102596,0.852553,-1.79513,0.033439,1.37116, + -0.051905,0.965082,0.256753,-1.479588,0.295746,1.440042, + -0.512472,0.102596,0.852553,-1.79513,0.033439,1.37116, + -0.088843,0.888,0.45118,-1.489699,-0.024215,1.510987, + -0.088843,0.888,0.45118,-1.489699,-0.024215,1.510987, + -0.512472,0.102596,0.852553,-1.79513,0.033439,1.37116, + -0.449233,0.123555,0.88483,-1.802864,-0.282523,1.401315, + -0.088843,0.888,0.45118,-1.489699,-0.024215,1.510987, + -0.449233,0.123555,0.88483,-1.802864,-0.282523,1.401315, + -0.169971,0.704712,0.688832,-1.395501,-0.698702,1.553257, + -0.169971,0.704712,0.688832,-1.395501,-0.698702,1.553257, + -0.449233,0.123555,0.88483,-1.802864,-0.282523,1.401315, + -0.404056,0.117264,0.907187,-1.837859,-0.540871,1.295851, + -0.169971,0.704712,0.688832,-1.395501,-0.698702,1.553257, + -0.404056,0.117264,0.907187,-1.837859,-0.540871,1.295851, + -0.261543,0.44691,0.855492,-1.376176,-0.948757,1.451608, + -0.261543,0.44691,0.855492,-1.376176,-0.948757,1.451608, + -0.404056,0.117264,0.907187,-1.837859,-0.540871,1.295851, + -0.387051,0.087836,0.917865,-1.782928,-0.770786,1.173619, + -0.261543,0.44691,0.855492,-1.376176,-0.948757,1.451608, + -0.387051,0.087836,0.917865,-1.782928,-0.770786,1.173619, + -0.33898,0.203127,0.918603,-1.402349,-1.127845,1.309055, + -0.33898,0.203127,0.918603,-1.402349,-1.127845,1.309055, + -0.387051,0.087836,0.917865,-1.782928,-0.770786,1.173619, + -0.390861,0.032481,0.919876,-1.757573,-0.945337,1.075832, + -0.33898,0.203127,0.918603,-1.402349,-1.127845,1.309055, + -0.390861,0.032481,0.919876,-1.757573,-0.945337,1.075832, + -0.351241,0.07582,0.93321,-1.407658,-1.236026,1.11293, + 0.262234,-0.965004,0,-1.35095,1.807009,0, + 0.021487,0.999769,0,-1.67651,1.826886,0, + -0.373751,-0.169261,0.911954,-1.683863,1.789041,0.121501, + 0.262234,-0.965004,0,-1.35095,1.807009,0, + -0.373751,-0.169261,0.911954,-1.683863,1.789041,0.121501, + -0.234266,0.044111,0.971171,-1.365948,1.769608,0.133901, + -0.234266,0.044111,0.971171,-1.365948,1.769608,0.133901, + -0.373751,-0.169261,0.911954,-1.683863,1.789041,0.121501, + -0.426971,-0.09322,0.899447,-1.714432,1.747956,0.247594, + -0.234266,0.044111,0.971171,-1.365948,1.769608,0.133901, + -0.426971,-0.09322,0.899447,-1.714432,1.747956,0.247594, + -0.108631,-0.122719,0.986478,-1.396332,1.723782,0.267642, + -0.108631,-0.122719,0.986478,-1.396332,1.723782,0.267642, + -0.426971,-0.09322,0.899447,-1.714432,1.747956,0.247594, + -0.457657,0.090776,0.884483,-1.744732,1.734849,0.433807, + -0.108631,-0.122719,0.986478,-1.396332,1.723782,0.267642, + -0.457657,0.090776,0.884483,-1.744732,1.734849,0.433807, + -0.006683,-0.232823,0.972496,-1.417595,1.67618,0.529265, + -0.006683,-0.232823,0.972496,-1.417595,1.67618,0.529265, + -0.457657,0.090776,0.884483,-1.744732,1.734849,0.433807, + -0.575033,0.794917,0.193504,-1.929731,1.617188,0.80639, + -0.006683,-0.232823,0.972496,-1.417595,1.67618,0.529265, + -0.575033,0.794917,0.193504,-1.929731,1.617188,0.80639, + -0.004872,-0.216103,0.976358,-1.465432,1.655336,0.722125, + -0.004872,-0.216103,0.976358,-1.465432,1.655336,0.722125, + -0.575033,0.794917,0.193504,-1.929731,1.617188,0.80639, + -0.636638,0.552106,0.538397,-1.996117,1.387891,1.064104, + -0.004872,-0.216103,0.976358,-1.465432,1.655336,0.722125, + -0.636638,0.552106,0.538397,-1.996117,1.387891,1.064104, + 0.193955,-0.251788,0.948148,-1.582187,1.567542,0.982349, + 0.193955,-0.251788,0.948148,-1.582187,1.567542,0.982349, + -0.636638,0.552106,0.538397,-1.996117,1.387891,1.064104, + -0.643784,0.341688,0.684684,-1.980388,1.134038,1.143196, + 0.193955,-0.251788,0.948148,-1.582187,1.567542,0.982349, + -0.643784,0.341688,0.684684,-1.980388,1.134038,1.143196, + -0.337275,0.918092,0.208215,-1.721806,1.391264,1.113307, + -0.337275,0.918092,0.208215,-1.721806,1.391264,1.113307, + -0.643784,0.341688,0.684684,-1.980388,1.134038,1.143196, + -0.646492,0.202786,0.735477,-2.013663,0.810726,1.158827, + -0.337275,0.918092,0.208215,-1.721806,1.391264,1.113307, + -0.646492,0.202786,0.735477,-2.013663,0.810726,1.158827, + -0.47652,0.732046,0.486866,-1.733703,1.083864,1.181489, + -0.47652,0.732046,0.486866,-1.733703,1.083864,1.181489, + -0.646492,0.202786,0.735477,-2.013663,0.810726,1.158827, + -0.624566,0.121329,0.77149,-2.030191,0.547622,1.189762, + -0.47652,0.732046,0.486866,-1.733703,1.083864,1.181489, + -0.624566,0.121329,0.77149,-2.030191,0.547622,1.189762, + -0.505556,0.519614,0.688777,-1.807421,0.657142,1.209422, + -0.505556,0.519614,0.688777,-1.807421,0.657142,1.209422, + -0.624566,0.121329,0.77149,-2.030191,0.547622,1.189762, + -0.588582,0.130278,0.797872,-2.021159,0.411979,1.234679, + -0.505556,0.519614,0.688777,-1.807421,0.657142,1.209422, + -0.588582,0.130278,0.797872,-2.021159,0.411979,1.234679, + -0.539732,0.31653,0.780063,-1.796156,0.452382,1.243643, + -0.539732,0.31653,0.780063,-1.796156,0.452382,1.243643, + -0.588582,0.130278,0.797872,-2.021159,0.411979,1.234679, + -0.553145,0.120209,0.824367,-1.932916,0.232972,1.304589, + -0.539732,0.31653,0.780063,-1.796156,0.452382,1.243643, + -0.553145,0.120209,0.824367,-1.932916,0.232972,1.304589, + -0.545639,0.142044,0.825894,-1.81092,0.287592,1.292257, + -0.545639,0.142044,0.825894,-1.81092,0.287592,1.292257, + -0.553145,0.120209,0.824367,-1.932916,0.232972,1.304589, + -0.547788,0.055501,0.834774,-1.897394,0.037852,1.365798, + -0.545639,0.142044,0.825894,-1.81092,0.287592,1.292257, + -0.547788,0.055501,0.834774,-1.897394,0.037852,1.365798, + -0.512472,0.102596,0.852553,-1.79513,0.033439,1.37116, + -0.512472,0.102596,0.852553,-1.79513,0.033439,1.37116, + -0.547788,0.055501,0.834774,-1.897394,0.037852,1.365798, + -0.563128,0.005618,0.826351,-1.950547,-0.275573,1.377028, + -0.512472,0.102596,0.852553,-1.79513,0.033439,1.37116, + -0.563128,0.005618,0.826351,-1.950547,-0.275573,1.377028, + -0.449233,0.123555,0.88483,-1.802864,-0.282523,1.401315, + -0.449233,0.123555,0.88483,-1.802864,-0.282523,1.401315, + -0.563128,0.005618,0.826351,-1.950547,-0.275573,1.377028, + -0.596319,-0.021767,0.802452,-2.033655,-0.526012,1.277639, + -0.449233,0.123555,0.88483,-1.802864,-0.282523,1.401315, + -0.596319,-0.021767,0.802452,-2.033655,-0.526012,1.277639, + -0.404056,0.117264,0.907187,-1.837859,-0.540871,1.295851, + -0.404056,0.117264,0.907187,-1.837859,-0.540871,1.295851, + -0.596319,-0.021767,0.802452,-2.033655,-0.526012,1.277639, + -0.626255,-0.080061,0.775497,-2.050292,-0.755566,1.114167, + -0.404056,0.117264,0.907187,-1.837859,-0.540871,1.295851, + -0.626255,-0.080061,0.775497,-2.050292,-0.755566,1.114167, + -0.387051,0.087836,0.917865,-1.782928,-0.770786,1.173619, + -0.387051,0.087836,0.917865,-1.782928,-0.770786,1.173619, + -0.626255,-0.080061,0.775497,-2.050292,-0.755566,1.114167, + -0.6343,-0.110875,0.765095,-2.043593,-0.875823,1.028879, + -0.387051,0.087836,0.917865,-1.782928,-0.770786,1.173619, + -0.6343,-0.110875,0.765095,-2.043593,-0.875823,1.028879, + -0.390861,0.032481,0.919876,-1.757573,-0.945337,1.075832, + -0.390861,0.032481,0.919876,-1.757573,-0.945337,1.075832, + -0.6343,-0.110875,0.765095,-2.043593,-0.875823,1.028879, + -0.619245,-0.050391,0.783579,-2.033406,-0.91003,0.96422, + -0.390861,0.032481,0.919876,-1.757573,-0.945337,1.075832, + -0.619245,-0.050391,0.783579,-2.033406,-0.91003,0.96422, + -0.379807,-0.084066,0.921238,-1.782298,-1.020581,0.943381, + -0.02449,0.224062,0.974267,-0.953236,-1.545941,0.89918, + -0.0448,0.42163,0.905661,-0.952525,-1.440582,1.16865, + -0.351241,0.07582,0.93321,-1.407658,-1.236026,1.11293, + -0.02449,0.224062,0.974267,-0.953236,-1.545941,0.89918, + -0.351241,0.07582,0.93321,-1.407658,-1.236026,1.11293, + -0.742985,0.015712,0.669123,-1.198513,-1.456102,0.885435, + -0.351241,0.07582,0.93321,-1.407658,-1.236026,1.11293, + -0.390861,0.032481,0.919876,-1.757573,-0.945337,1.075832, + -0.379807,-0.084066,0.921238,-1.782298,-1.020581,0.943381, + -0.351241,0.07582,0.93321,-1.407658,-1.236026,1.11293, + -0.379807,-0.084066,0.921238,-1.782298,-1.020581,0.943381, + -0.982334,-0.04331,0.182057,-1.456655,-1.295527,0.89424, + -0.351241,0.07582,0.93321,-1.407658,-1.236026,1.11293, + -0.982334,-0.04331,0.182057,-1.456655,-1.295527,0.89424, + -0.311485,0.082882,0.94663,-1.366873,-1.340211,0.907567, + -0.351241,0.07582,0.93321,-1.407658,-1.236026,1.11293, + -0.311485,0.082882,0.94663,-1.366873,-1.340211,0.907567, + -0.742985,0.015712,0.669123,-1.198513,-1.456102,0.885435, + 0.021487,0.999769,0,-1.67651,1.826886,0, + 0.181762,-0.983343,0,-2.057387,1.841308,0, + -0.549206,0.149158,0.822268,-2.079597,1.817785,0.138375, + 0.021487,0.999769,0,-1.67651,1.826886,0, + -0.549206,0.149158,0.822268,-2.079597,1.817785,0.138375, + -0.373751,-0.169261,0.911954,-1.683863,1.789041,0.121501, + -0.373751,-0.169261,0.911954,-1.683863,1.789041,0.121501, + -0.549206,0.149158,0.822268,-2.079597,1.817785,0.138375, + -0.881408,0.44424,0.16053,-2.10017,1.78998,0.229245, + -0.373751,-0.169261,0.911954,-1.683863,1.789041,0.121501, + -0.881408,0.44424,0.16053,-2.10017,1.78998,0.229245, + -0.426971,-0.09322,0.899447,-1.714432,1.747956,0.247594, + -0.426971,-0.09322,0.899447,-1.714432,1.747956,0.247594, + -0.881408,0.44424,0.16053,-2.10017,1.78998,0.229245, + -0.881352,0.261345,0.393596,-2.137524,1.753182,0.433142, + -0.426971,-0.09322,0.899447,-1.714432,1.747956,0.247594, + -0.881352,0.261345,0.393596,-2.137524,1.753182,0.433142, + -0.457657,0.090776,0.884483,-1.744732,1.734849,0.433807, + -0.457657,0.090776,0.884483,-1.744732,1.734849,0.433807, + -0.881352,0.261345,0.393596,-2.137524,1.753182,0.433142, + -0.880731,0.130088,0.4554,-2.172139,1.62301,0.805318, + -0.457657,0.090776,0.884483,-1.744732,1.734849,0.433807, + -0.880731,0.130088,0.4554,-2.172139,1.62301,0.805318, + -0.575033,0.794917,0.193504,-1.929731,1.617188,0.80639, + -0.575033,0.794917,0.193504,-1.929731,1.617188,0.80639, + -0.880731,0.130088,0.4554,-2.172139,1.62301,0.805318, + -0.874101,0.053175,0.482825,-2.205791,1.356023,1.081662, + -0.575033,0.794917,0.193504,-1.929731,1.617188,0.80639, + -0.874101,0.053175,0.482825,-2.205791,1.356023,1.081662, + -0.636638,0.552106,0.538397,-1.996117,1.387891,1.064104, + -0.636638,0.552106,0.538397,-1.996117,1.387891,1.064104, + -0.874101,0.053175,0.482825,-2.205791,1.356023,1.081662, + -0.875552,0.01506,0.482889,-2.296056,1.06281,1.171139, + -0.636638,0.552106,0.538397,-1.996117,1.387891,1.064104, + -0.875552,0.01506,0.482889,-2.296056,1.06281,1.171139, + -0.643784,0.341688,0.684684,-1.980388,1.134038,1.143196, + -0.643784,0.341688,0.684684,-1.980388,1.134038,1.143196, + -0.875552,0.01506,0.482889,-2.296056,1.06281,1.171139, + -0.86587,-0.001845,0.500266,-2.298249,0.768333,1.203884, + -0.643784,0.341688,0.684684,-1.980388,1.134038,1.143196, + -0.86587,-0.001845,0.500266,-2.298249,0.768333,1.203884, + -0.646492,0.202786,0.735477,-2.013663,0.810726,1.158827, + -0.646492,0.202786,0.735477,-2.013663,0.810726,1.158827, + -0.86587,-0.001845,0.500266,-2.298249,0.768333,1.203884, + -0.84112,-0.026303,0.540209,-2.256285,0.547326,1.238301, + -0.646492,0.202786,0.735477,-2.013663,0.810726,1.158827, + -0.84112,-0.026303,0.540209,-2.256285,0.547326,1.238301, + -0.624566,0.121329,0.77149,-2.030191,0.547622,1.189762, + -0.624566,0.121329,0.77149,-2.030191,0.547622,1.189762, + -0.84112,-0.026303,0.540209,-2.256285,0.547326,1.238301, + -0.813168,-0.06637,0.578232,-2.1584,0.381542,1.272962, + -0.624566,0.121329,0.77149,-2.030191,0.547622,1.189762, + -0.813168,-0.06637,0.578232,-2.1584,0.381542,1.272962, + -0.588582,0.130278,0.797872,-2.021159,0.411979,1.234679, + -0.588582,0.130278,0.797872,-2.021159,0.411979,1.234679, + -0.813168,-0.06637,0.578232,-2.1584,0.381542,1.272962, + -0.799953,-0.096213,0.592299,-2.070413,0.207766,1.335106, + -0.588582,0.130278,0.797872,-2.021159,0.411979,1.234679, + -0.799953,-0.096213,0.592299,-2.070413,0.207766,1.335106, + -0.553145,0.120209,0.824367,-1.932916,0.232972,1.304589, + -0.553145,0.120209,0.824367,-1.932916,0.232972,1.304589, + -0.799953,-0.096213,0.592299,-2.070413,0.207766,1.335106, + -0.811102,-0.12903,0.570495,-2.064786,0.018789,1.411866, + -0.553145,0.120209,0.824367,-1.932916,0.232972,1.304589, + -0.811102,-0.12903,0.570495,-2.064786,0.018789,1.411866, + -0.547788,0.055501,0.834774,-1.897394,0.037852,1.365798, + -0.547788,0.055501,0.834774,-1.897394,0.037852,1.365798, + -0.811102,-0.12903,0.570495,-2.064786,0.018789,1.411866, + -0.848349,-0.120539,0.515533,-2.187634,-0.375454,1.406902, + -0.547788,0.055501,0.834774,-1.897394,0.037852,1.365798, + -0.848349,-0.120539,0.515533,-2.187634,-0.375454,1.406902, + -0.563128,0.005618,0.826351,-1.950547,-0.275573,1.377028, + -0.563128,0.005618,0.826351,-1.950547,-0.275573,1.377028, + -0.848349,-0.120539,0.515533,-2.187634,-0.375454,1.406902, + -0.880002,-0.033987,0.473752,-2.276341,-0.689823,1.268026, + -0.563128,0.005618,0.826351,-1.950547,-0.275573,1.377028, + -0.880002,-0.033987,0.473752,-2.276341,-0.689823,1.268026, + -0.596319,-0.021767,0.802452,-2.033655,-0.526012,1.277639, + -0.596319,-0.021767,0.802452,-2.033655,-0.526012,1.277639, + -0.880002,-0.033987,0.473752,-2.276341,-0.689823,1.268026, + -0.870332,0.069095,0.487595,-2.292049,-0.933921,1.128136, + -0.596319,-0.021767,0.802452,-2.033655,-0.526012,1.277639, + -0.870332,0.069095,0.487595,-2.292049,-0.933921,1.128136, + -0.626255,-0.080061,0.775497,-2.050292,-0.755566,1.114167, + -0.626255,-0.080061,0.775497,-2.050292,-0.755566,1.114167, + -0.870332,0.069095,0.487595,-2.292049,-0.933921,1.128136, + 0.074896,0.047734,0.996048,-2.299356,-1.025449,1.044687, + -0.626255,-0.080061,0.775497,-2.050292,-0.755566,1.114167, + 0.074896,0.047734,0.996048,-2.299356,-1.025449,1.044687, + -0.6343,-0.110875,0.765095,-2.043593,-0.875823,1.028879, + -0.6343,-0.110875,0.765095,-2.043593,-0.875823,1.028879, + 0.074896,0.047734,0.996048,-2.299356,-1.025449,1.044687, + -0.822733,0.223687,0.522565,-2.306662,-1.116976,0.961238, + -0.6343,-0.110875,0.765095,-2.043593,-0.875823,1.028879, + -0.822733,0.223687,0.522565,-2.306662,-1.116976,0.961238, + -0.619245,-0.050391,0.783579,-2.033406,-0.91003,0.96422, + 0.181762,-0.983343,0,-2.057387,1.841308,0, + 0.03611,0.999348,0,-2.629466,1.918204,0, + -0.946902,-0.290276,-0.138264,-2.672899,1.90511,0.067168, + 0.181762,-0.983343,0,-2.057387,1.841308,0, + -0.946902,-0.290276,-0.138264,-2.672899,1.90511,0.067168, + -0.549206,0.149158,0.822268,-2.079597,1.817785,0.138375, + -0.549206,0.149158,0.822268,-2.079597,1.817785,0.138375, + -0.946902,-0.290276,-0.138264,-2.672899,1.90511,0.067168, + -0.982633,-0.14343,-0.11773,-2.697367,1.871291,0.218796, + -0.549206,0.149158,0.822268,-2.079597,1.817785,0.138375, + -0.982633,-0.14343,-0.11773,-2.697367,1.871291,0.218796, + -0.881408,0.44424,0.16053,-2.10017,1.78998,0.229245, + -0.881408,0.44424,0.16053,-2.10017,1.78998,0.229245, + -0.982633,-0.14343,-0.11773,-2.697367,1.871291,0.218796, + -0.995584,-0.070631,-0.061842,-2.703112,1.825435,0.395127, + -0.881408,0.44424,0.16053,-2.10017,1.78998,0.229245, + -0.995584,-0.070631,-0.061842,-2.703112,1.825435,0.395127, + -0.881352,0.261345,0.393596,-2.137524,1.753182,0.433142, + -0.881352,0.261345,0.393596,-2.137524,1.753182,0.433142, + -0.995584,-0.070631,-0.061842,-2.703112,1.825435,0.395127, + -0.997475,-0.070819,-0.005318,-2.715246,1.746763,0.604653, + -0.881352,0.261345,0.393596,-2.137524,1.753182,0.433142, + -0.997475,-0.070819,-0.005318,-2.715246,1.746763,0.604653, + -0.880731,0.130088,0.4554,-2.172139,1.62301,0.805318, + -0.880731,0.130088,0.4554,-2.172139,1.62301,0.805318, + -0.997475,-0.070819,-0.005318,-2.715246,1.746763,0.604653, + -0.980175,-0.184883,-0.071243,-2.71748,1.576797,0.875971, + -0.880731,0.130088,0.4554,-2.172139,1.62301,0.805318, + -0.980175,-0.184883,-0.071243,-2.71748,1.576797,0.875971, + -0.874101,0.053175,0.482825,-2.205791,1.356023,1.081662, + -0.874101,0.053175,0.482825,-2.205791,1.356023,1.081662, + -0.980175,-0.184883,-0.071243,-2.71748,1.576797,0.875971, + -0.976177,-0.17359,-0.130171,-2.68493,1.262021,1.11049, + -0.874101,0.053175,0.482825,-2.205791,1.356023,1.081662, + -0.976177,-0.17359,-0.130171,-2.68493,1.262021,1.11049, + -0.875552,0.01506,0.482889,-2.296056,1.06281,1.171139, + -0.875552,0.01506,0.482889,-2.296056,1.06281,1.171139, + -0.976177,-0.17359,-0.130171,-2.68493,1.262021,1.11049, + -0.984416,-0.175855,0.000915,-2.572286,0.835495,1.252192, + -0.875552,0.01506,0.482889,-2.296056,1.06281,1.171139, + -0.984416,-0.175855,0.000915,-2.572286,0.835495,1.252192, + -0.86587,-0.001845,0.500266,-2.298249,0.768333,1.203884, + -0.86587,-0.001845,0.500266,-2.298249,0.768333,1.203884, + -0.984416,-0.175855,0.000915,-2.572286,0.835495,1.252192, + -0.977902,-0.171035,0.12023,-2.536112,0.656633,1.269661, + -0.86587,-0.001845,0.500266,-2.298249,0.768333,1.203884, + -0.977902,-0.171035,0.12023,-2.536112,0.656633,1.269661, + -0.84112,-0.026303,0.540209,-2.256285,0.547326,1.238301, + -0.84112,-0.026303,0.540209,-2.256285,0.547326,1.238301, + -0.977902,-0.171035,0.12023,-2.536112,0.656633,1.269661, + -0.964119,-0.189683,0.18573,-2.520947,0.559036,1.273617, + -0.84112,-0.026303,0.540209,-2.256285,0.547326,1.238301, + -0.964119,-0.189683,0.18573,-2.520947,0.559036,1.273617, + -0.813168,-0.06637,0.578232,-2.1584,0.381542,1.272962, + -0.813168,-0.06637,0.578232,-2.1584,0.381542,1.272962, + -0.964119,-0.189683,0.18573,-2.520947,0.559036,1.273617, + -0.955381,-0.23808,0.174826,-2.47375,0.300945,1.316695, + -0.813168,-0.06637,0.578232,-2.1584,0.381542,1.272962, + -0.955381,-0.23808,0.174826,-2.47375,0.300945,1.316695, + -0.799953,-0.096213,0.592299,-2.070413,0.207766,1.335106, + -0.799953,-0.096213,0.592299,-2.070413,0.207766,1.335106, + -0.955381,-0.23808,0.174826,-2.47375,0.300945,1.316695, + -0.843742,-0.096325,0.528036,-2.433366,0.078222,1.371269, + -0.799953,-0.096213,0.592299,-2.070413,0.207766,1.335106, + -0.843742,-0.096325,0.528036,-2.433366,0.078222,1.371269, + -0.811102,-0.12903,0.570495,-2.064786,0.018789,1.411866, + -0.811102,-0.12903,0.570495,-2.064786,0.018789,1.411866, + -0.843742,-0.096325,0.528036,-2.433366,0.078222,1.371269, + 0.028952,-0.016247,0.999449,-2.41473,-0.108377,1.395384, + -0.811102,-0.12903,0.570495,-2.064786,0.018789,1.411866, + 0.028952,-0.016247,0.999449,-2.41473,-0.108377,1.395384, + -0.848349,-0.120539,0.515533,-2.187634,-0.375454,1.406902, + -0.848349,-0.120539,0.515533,-2.187634,-0.375454,1.406902, + 0.028952,-0.016247,0.999449,-2.41473,-0.108377,1.395384, + 0.093953,-0.049433,0.994349,-2.38292,-0.41745,1.375045, + -0.848349,-0.120539,0.515533,-2.187634,-0.375454,1.406902, + 0.093953,-0.049433,0.994349,-2.38292,-0.41745,1.375045, + -0.880002,-0.033987,0.473752,-2.276341,-0.689823,1.268026, + -0.880002,-0.033987,0.473752,-2.276341,-0.689823,1.268026, + 0.093953,-0.049433,0.994349,-2.38292,-0.41745,1.375045, + 0.335613,-0.388493,0.858159,-2.430508,-0.822313,1.254486, + -0.880002,-0.033987,0.473752,-2.276341,-0.689823,1.268026, + 0.335613,-0.388493,0.858159,-2.430508,-0.822313,1.254486, + -0.870332,0.069095,0.487595,-2.292049,-0.933921,1.128136, + -0.870332,0.069095,0.487595,-2.292049,-0.933921,1.128136, + 0.335613,-0.388493,0.858159,-2.430508,-0.822313,1.254486, + -0.004413,-0.170526,0.985343,-2.566746,-1.211312,1.167101, + -0.870332,0.069095,0.487595,-2.292049,-0.933921,1.128136, + -0.004413,-0.170526,0.985343,-2.566746,-1.211312,1.167101, + 0.074896,0.047734,0.996048,-2.299356,-1.025449,1.044687, + 0.03611,0.999348,0,-2.629466,1.918204,0, + 0.012502,-0.999922,0,-3.037562,2.001526,0, + 0.137764,-0.289893,0.947092,-3.053102,1.96881,0.051104, + 0.03611,0.999348,0,-2.629466,1.918204,0, + 0.137764,-0.289893,0.947092,-3.053102,1.96881,0.051104, + -0.946902,-0.290276,-0.138264,-2.672899,1.90511,0.067168, + -0.946902,-0.290276,-0.138264,-2.672899,1.90511,0.067168, + 0.137764,-0.289893,0.947092,-3.053102,1.96881,0.051104, + 0.137206,-0.207537,0.968557,-3.077669,1.871112,0.217368, + -0.946902,-0.290276,-0.138264,-2.672899,1.90511,0.067168, + 0.137206,-0.207537,0.968557,-3.077669,1.871112,0.217368, + -0.982633,-0.14343,-0.11773,-2.697367,1.871291,0.218796, + -0.982633,-0.14343,-0.11773,-2.697367,1.871291,0.218796, + 0.137206,-0.207537,0.968557,-3.077669,1.871112,0.217368, + 0.094371,-0.230057,0.968591,-3.07531,1.846,0.363149, + -0.982633,-0.14343,-0.11773,-2.697367,1.871291,0.218796, + 0.094371,-0.230057,0.968591,-3.07531,1.846,0.363149, + -0.995584,-0.070631,-0.061842,-2.703112,1.825435,0.395127, + -0.995584,-0.070631,-0.061842,-2.703112,1.825435,0.395127, + 0.094371,-0.230057,0.968591,-3.07531,1.846,0.363149, + -0.201818,-0.568242,0.797728,-3.109047,1.789477,0.565323, + -0.995584,-0.070631,-0.061842,-2.703112,1.825435,0.395127, + -0.201818,-0.568242,0.797728,-3.109047,1.789477,0.565323, + -0.997475,-0.070819,-0.005318,-2.715246,1.746763,0.604653, + -0.997475,-0.070819,-0.005318,-2.715246,1.746763,0.604653, + -0.201818,-0.568242,0.797728,-3.109047,1.789477,0.565323, + 0.357021,-0.590654,0.723646,-3.08565,1.65734,0.784479, + -0.997475,-0.070819,-0.005318,-2.715246,1.746763,0.604653, + 0.357021,-0.590654,0.723646,-3.08565,1.65734,0.784479, + -0.980175,-0.184883,-0.071243,-2.71748,1.576797,0.875971, + -0.980175,-0.184883,-0.071243,-2.71748,1.576797,0.875971, + 0.357021,-0.590654,0.723646,-3.08565,1.65734,0.784479, + 0.008663,-0.516082,0.856495,-3.028932,1.461517,0.941324, + -0.980175,-0.184883,-0.071243,-2.71748,1.576797,0.875971, + 0.008663,-0.516082,0.856495,-3.028932,1.461517,0.941324, + -0.976177,-0.17359,-0.130171,-2.68493,1.262021,1.11049, + -0.976177,-0.17359,-0.130171,-2.68493,1.262021,1.11049, + 0.008663,-0.516082,0.856495,-3.028932,1.461517,0.941324, + 0.106237,-0.558927,0.822383,-2.930312,1.10358,1.125876, + -0.976177,-0.17359,-0.130171,-2.68493,1.262021,1.11049, + 0.106237,-0.558927,0.822383,-2.930312,1.10358,1.125876, + -0.984416,-0.175855,0.000915,-2.572286,0.835495,1.252192, + -0.984416,-0.175855,0.000915,-2.572286,0.835495,1.252192, + 0.106237,-0.558927,0.822383,-2.930312,1.10358,1.125876, + 0.155794,-0.590112,0.792146,-2.825835,0.755899,1.209042, + -0.984416,-0.175855,0.000915,-2.572286,0.835495,1.252192, + 0.155794,-0.590112,0.792146,-2.825835,0.755899,1.209042, + -0.977902,-0.171035,0.12023,-2.536112,0.656633,1.269661, + -0.977902,-0.171035,0.12023,-2.536112,0.656633,1.269661, + 0.155794,-0.590112,0.792146,-2.825835,0.755899,1.209042, + 0.08565,-0.422547,0.902285,-2.79063,0.46881,1.224273, + -0.977902,-0.171035,0.12023,-2.536112,0.656633,1.269661, + 0.08565,-0.422547,0.902285,-2.79063,0.46881,1.224273, + -0.964119,-0.189683,0.18573,-2.520947,0.559036,1.273617, + -0.964119,-0.189683,0.18573,-2.520947,0.559036,1.273617, + 0.08565,-0.422547,0.902285,-2.79063,0.46881,1.224273, + 0.161064,-0.731195,0.662882,-2.787011,0.264495,1.237352, + -0.964119,-0.189683,0.18573,-2.520947,0.559036,1.273617, + 0.161064,-0.731195,0.662882,-2.787011,0.264495,1.237352, + -0.955381,-0.23808,0.174826,-2.47375,0.300945,1.316695, + -0.955381,-0.23808,0.174826,-2.47375,0.300945,1.316695, + 0.161064,-0.731195,0.662882,-2.787011,0.264495,1.237352, + 0.121987,-0.426327,0.896306,-2.687022,0.076781,1.290565, + -0.955381,-0.23808,0.174826,-2.47375,0.300945,1.316695, + 0.121987,-0.426327,0.896306,-2.687022,0.076781,1.290565, + -0.843742,-0.096325,0.528036,-2.433366,0.078222,1.371269, + -0.843742,-0.096325,0.528036,-2.433366,0.078222,1.371269, + 0.121987,-0.426327,0.896306,-2.687022,0.076781,1.290565, + 0.215155,-0.464575,0.858999,-2.649338,-0.241719,1.339644, + -0.843742,-0.096325,0.528036,-2.433366,0.078222,1.371269, + 0.215155,-0.464575,0.858999,-2.649338,-0.241719,1.339644, + 0.028952,-0.016247,0.999449,-2.41473,-0.108377,1.395384, + 0.028952,-0.016247,0.999449,-2.41473,-0.108377,1.395384, + 0.215155,-0.464575,0.858999,-2.649338,-0.241719,1.339644, + -0.11636,-0.749063,0.652201,-2.616467,-0.511373,1.344133, + 0.028952,-0.016247,0.999449,-2.41473,-0.108377,1.395384, + -0.11636,-0.749063,0.652201,-2.616467,-0.511373,1.344133, + 0.093953,-0.049433,0.994349,-2.38292,-0.41745,1.375045, + 0.093953,-0.049433,0.994349,-2.38292,-0.41745,1.375045, + -0.11636,-0.749063,0.652201,-2.616467,-0.511373,1.344133, + 0.162276,-0.745105,0.646905,-2.624856,-0.8882,1.261176, + 0.093953,-0.049433,0.994349,-2.38292,-0.41745,1.375045, + 0.162276,-0.745105,0.646905,-2.624856,-0.8882,1.261176, + 0.335613,-0.388493,0.858159,-2.430508,-0.822313,1.254486, + 0.335613,-0.388493,0.858159,-2.430508,-0.822313,1.254486, + 0.162276,-0.745105,0.646905,-2.624856,-0.8882,1.261176, + -0.351476,-0.711504,0.608463,-2.725776,-1.214862,1.190384, + 0.335613,-0.388493,0.858159,-2.430508,-0.822313,1.254486, + -0.351476,-0.711504,0.608463,-2.725776,-1.214862,1.190384, + -0.004413,-0.170526,0.985343,-2.566746,-1.211312,1.167101, + -0.004413,-0.170526,0.985343,-2.566746,-1.211312,1.167101, + -0.351476,-0.711504,0.608463,-2.725776,-1.214862,1.190384, + -0.149005,-0.65467,0.741084,-2.862576,-1.546894,1.117139, + -0.004413,-0.170526,0.985343,-2.566746,-1.211312,1.167101, + -0.149005,-0.65467,0.741084,-2.862576,-1.546894,1.117139, + 0.095733,-0.224552,0.969748,-2.765069,-1.561164,1.084313, + 0.072535,0.997366,0,-3.392806,1.769365,0, + -0.153783,-0.988105,0,-3.507689,1.700214,0, + 0.048753,-0.975535,0.21437,-3.519716,1.685231,0.31713, + 0.072535,0.997366,0,-3.392806,1.769365,0, + 0.048753,-0.975535,0.21437,-3.519716,1.685231,0.31713, + -0.468954,-0.586277,0.660577,-3.35851,1.810253,0.380095, + -0.468954,-0.586277,0.660577,-3.35851,1.810253,0.380095, + 0.048753,-0.975535,0.21437,-3.519716,1.685231,0.31713, + -0.177142,-0.976279,0.124502,-3.527168,1.583508,0.512679, + -0.468954,-0.586277,0.660577,-3.35851,1.810253,0.380095, + -0.177142,-0.976279,0.124502,-3.527168,1.583508,0.512679, + -0.150892,-0.83775,0.524792,-3.395381,1.726325,0.55477, + -0.150892,-0.83775,0.524792,-3.395381,1.726325,0.55477, + -0.177142,-0.976279,0.124502,-3.527168,1.583508,0.512679, + 0.430742,-0.887318,0.164705,-3.512997,1.44805,0.611386, + -0.150892,-0.83775,0.524792,-3.395381,1.726325,0.55477, + 0.430742,-0.887318,0.164705,-3.512997,1.44805,0.611386, + -0.4144,-0.844957,0.338113,-3.338742,1.598933,0.689636, + -0.4144,-0.844957,0.338113,-3.338742,1.598933,0.689636, + 0.430742,-0.887318,0.164705,-3.512997,1.44805,0.611386, + 0.35682,-0.781398,0.511954,-3.476235,1.287798,0.704766, + -0.4144,-0.844957,0.338113,-3.338742,1.598933,0.689636, + 0.35682,-0.781398,0.511954,-3.476235,1.287798,0.704766, + -0.176655,-0.950799,0.254508,-3.27808,1.432418,0.853958, + -0.176655,-0.950799,0.254508,-3.27808,1.432418,0.853958, + 0.35682,-0.781398,0.511954,-3.476235,1.287798,0.704766, + 0.493535,-0.729115,0.474147,-3.442151,1.105486,0.762934, + -0.176655,-0.950799,0.254508,-3.27808,1.432418,0.853958, + 0.493535,-0.729115,0.474147,-3.442151,1.105486,0.762934, + -0.079302,-0.84299,0.532051,-3.244771,1.19554,0.910945, + -0.079302,-0.84299,0.532051,-3.244771,1.19554,0.910945, + 0.493535,-0.729115,0.474147,-3.442151,1.105486,0.762934, + 0.04422,-0.704109,0.708714,-3.379131,0.767915,0.885996, + -0.079302,-0.84299,0.532051,-3.244771,1.19554,0.910945, + 0.04422,-0.704109,0.708714,-3.379131,0.767915,0.885996, + -0.094238,-0.851252,0.516225,-3.19641,0.797564,0.985913, + -0.094238,-0.851252,0.516225,-3.19641,0.797564,0.985913, + 0.04422,-0.704109,0.708714,-3.379131,0.767915,0.885996, + 0.083262,-0.787311,0.610908,-3.306875,0.379713,0.98762, + -0.094238,-0.851252,0.516225,-3.19641,0.797564,0.985913, + 0.083262,-0.787311,0.610908,-3.306875,0.379713,0.98762, + 0.152347,-0.821467,0.549529,-3.112555,0.457376,1.084816, + 0.152347,-0.821467,0.549529,-3.112555,0.457376,1.084816, + 0.083262,-0.787311,0.610908,-3.306875,0.379713,0.98762, + 0.170756,-0.748007,0.641349,-3.251181,0.175063,1.053445, + 0.152347,-0.821467,0.549529,-3.112555,0.457376,1.084816, + 0.170756,-0.748007,0.641349,-3.251181,0.175063,1.053445, + -0.279342,-0.940234,0.19475,-3.044646,0.224321,1.164934, + -0.279342,-0.940234,0.19475,-3.044646,0.224321,1.164934, + 0.170756,-0.748007,0.641349,-3.251181,0.175063,1.053445, + 0.64791,-0.754869,-0.101908,-3.160225,-0.018852,1.113626, + -0.279342,-0.940234,0.19475,-3.044646,0.224321,1.164934, + 0.64791,-0.754869,-0.101908,-3.160225,-0.018852,1.113626, + -0.198045,-0.959194,0.201804,-2.971546,0.032038,1.215971, + -0.198045,-0.959194,0.201804,-2.971546,0.032038,1.215971, + 0.64791,-0.754869,-0.101908,-3.160225,-0.018852,1.113626, + 0.381337,-0.795981,0.470103,-3.101125,-0.35476,1.162409, + -0.198045,-0.959194,0.201804,-2.971546,0.032038,1.215971, + 0.381337,-0.795981,0.470103,-3.101125,-0.35476,1.162409, + -0.171647,-0.971664,0.162499,-2.90708,-0.345582,1.281557, + -0.171647,-0.971664,0.162499,-2.90708,-0.345582,1.281557, + 0.381337,-0.795981,0.470103,-3.101125,-0.35476,1.162409, + 0.183908,-0.773381,0.606679,-3.096267,-0.6681,1.140081, + -0.171647,-0.971664,0.162499,-2.90708,-0.345582,1.281557, + 0.183908,-0.773381,0.606679,-3.096267,-0.6681,1.140081, + -0.403877,-0.879274,0.252509,-2.901159,-0.619504,1.284058, + -0.403877,-0.879274,0.252509,-2.901159,-0.619504,1.284058, + 0.183908,-0.773381,0.606679,-3.096267,-0.6681,1.140081, + 0.018755,-0.837462,0.546174,-3.122061,-0.998702,1.065015, + -0.403877,-0.879274,0.252509,-2.901159,-0.619504,1.284058, + 0.018755,-0.837462,0.546174,-3.122061,-0.998702,1.065015, + -0.040019,-0.929968,0.365457,-2.937658,-1.002749,1.219413, + -0.040019,-0.929968,0.365457,-2.937658,-1.002749,1.219413, + 0.018755,-0.837462,0.546174,-3.122061,-0.998702,1.065015, + -0.094688,-0.959937,0.263734,-3.15021,-1.259588,1.001021, + -0.040019,-0.929968,0.365457,-2.937658,-1.002749,1.219413, + -0.094688,-0.959937,0.263734,-3.15021,-1.259588,1.001021, + -0.299215,-0.929389,0.216115,-2.982676,-1.264649,1.133596, + -0.299215,-0.929389,0.216115,-2.982676,-1.264649,1.133596, + -0.094688,-0.959937,0.263734,-3.15021,-1.259588,1.001021, + 0.059023,-0.965365,0.25414,-3.188954,-1.408279,0.963611, + -0.299215,-0.929389,0.216115,-2.982676,-1.264649,1.133596, + 0.059023,-0.965365,0.25414,-3.188954,-1.408279,0.963611, + -0.18119,-0.970212,0.160805,-3.063133,-1.440555,1.090926, + -0.153783,-0.988105,0,-3.507689,1.700214,0, + -0.626255,-0.080061,-0.775497,-3.690685,1.60208,0, + 0.49176,-0.810764,0.317543,-3.734989,1.589433,0.295202, + -0.153783,-0.988105,0,-3.507689,1.700214,0, + 0.49176,-0.810764,0.317543,-3.734989,1.589433,0.295202, + 0.048753,-0.975535,0.21437,-3.519716,1.685231,0.31713, + 0.048753,-0.975535,0.21437,-3.519716,1.685231,0.31713, + 0.49176,-0.810764,0.317543,-3.734989,1.589433,0.295202, + 0.43907,-0.579988,0.686172,-3.697974,1.466697,0.433432, + 0.048753,-0.975535,0.21437,-3.519716,1.685231,0.31713, + 0.43907,-0.579988,0.686172,-3.697974,1.466697,0.433432, + -0.177142,-0.976279,0.124502,-3.527168,1.583508,0.512679, + -0.177142,-0.976279,0.124502,-3.527168,1.583508,0.512679, + 0.43907,-0.579988,0.686172,-3.697974,1.466697,0.433432, + 0.099157,-0.476834,0.873383,-3.684619,1.35069,0.501428, + -0.177142,-0.976279,0.124502,-3.527168,1.583508,0.512679, + 0.099157,-0.476834,0.873383,-3.684619,1.35069,0.501428, + 0.430742,-0.887318,0.164705,-3.512997,1.44805,0.611386, + 0.430742,-0.887318,0.164705,-3.512997,1.44805,0.611386, + 0.099157,-0.476834,0.873383,-3.684619,1.35069,0.501428, + -0.073547,-0.481419,0.8734,-3.655148,1.190938,0.573692, + 0.430742,-0.887318,0.164705,-3.512997,1.44805,0.611386, + -0.073547,-0.481419,0.8734,-3.655148,1.190938,0.573692, + 0.35682,-0.781398,0.511954,-3.476235,1.287798,0.704766, + 0.35682,-0.781398,0.511954,-3.476235,1.287798,0.704766, + -0.073547,-0.481419,0.8734,-3.655148,1.190938,0.573692, + -0.147229,-0.706225,0.69251,-3.639878,1.015186,0.615203, + 0.35682,-0.781398,0.511954,-3.476235,1.287798,0.704766, + -0.147229,-0.706225,0.69251,-3.639878,1.015186,0.615203, + 0.493535,-0.729115,0.474147,-3.442151,1.105486,0.762934, + 0.493535,-0.729115,0.474147,-3.442151,1.105486,0.762934, + -0.147229,-0.706225,0.69251,-3.639878,1.015186,0.615203, + 0.328487,-0.940917,-0.082286,-3.582867,0.734419,0.697787, + 0.493535,-0.729115,0.474147,-3.442151,1.105486,0.762934, + 0.328487,-0.940917,-0.082286,-3.582867,0.734419,0.697787, + 0.04422,-0.704109,0.708714,-3.379131,0.767915,0.885996, + 0.04422,-0.704109,0.708714,-3.379131,0.767915,0.885996, + 0.328487,-0.940917,-0.082286,-3.582867,0.734419,0.697787, + -0.319475,-0.944225,0.079844,-3.504525,0.405574,0.847066, + 0.04422,-0.704109,0.708714,-3.379131,0.767915,0.885996, + -0.319475,-0.944225,0.079844,-3.504525,0.405574,0.847066, + 0.083262,-0.787311,0.610908,-3.306875,0.379713,0.98762, + 0.083262,-0.787311,0.610908,-3.306875,0.379713,0.98762, + -0.319475,-0.944225,0.079844,-3.504525,0.405574,0.847066, + -0.393694,-0.919049,-0.018795,-3.424258,0.158638,0.918279, + 0.083262,-0.787311,0.610908,-3.306875,0.379713,0.98762, + -0.393694,-0.919049,-0.018795,-3.424258,0.158638,0.918279, + 0.170756,-0.748007,0.641349,-3.251181,0.175063,1.053445, + 0.170756,-0.748007,0.641349,-3.251181,0.175063,1.053445, + -0.393694,-0.919049,-0.018795,-3.424258,0.158638,0.918279, + -0.327707,-0.94199,-0.072547,-3.365413,-0.113447,0.9524, + 0.170756,-0.748007,0.641349,-3.251181,0.175063,1.053445, + -0.327707,-0.94199,-0.072547,-3.365413,-0.113447,0.9524, + 0.64791,-0.754869,-0.101908,-3.160225,-0.018852,1.113626, + 0.64791,-0.754869,-0.101908,-3.160225,-0.018852,1.113626, + -0.327707,-0.94199,-0.072547,-3.365413,-0.113447,0.9524, + -0.163041,-0.980692,-0.107986,-3.290393,-0.424259,0.984153, + 0.64791,-0.754869,-0.101908,-3.160225,-0.018852,1.113626, + -0.163041,-0.980692,-0.107986,-3.290393,-0.424259,0.984153, + 0.381337,-0.795981,0.470103,-3.101125,-0.35476,1.162409, + 0.381337,-0.795981,0.470103,-3.101125,-0.35476,1.162409, + -0.163041,-0.980692,-0.107986,-3.290393,-0.424259,0.984153, + 0.074429,-0.99521,-0.063385,-3.233333,-0.683782,1.015512, + 0.381337,-0.795981,0.470103,-3.101125,-0.35476,1.162409, + 0.074429,-0.99521,-0.063385,-3.233333,-0.683782,1.015512, + 0.183908,-0.773381,0.606679,-3.096267,-0.6681,1.140081, + 0.183908,-0.773381,0.606679,-3.096267,-0.6681,1.140081, + 0.074429,-0.99521,-0.063385,-3.233333,-0.683782,1.015512, + -0.012978,-0.998326,-0.056357,-3.238094,-0.979377,0.961631, + 0.183908,-0.773381,0.606679,-3.096267,-0.6681,1.140081, + -0.012978,-0.998326,-0.056357,-3.238094,-0.979377,0.961631, + 0.018755,-0.837462,0.546174,-3.122061,-0.998702,1.065015, + 0.018755,-0.837462,0.546174,-3.122061,-0.998702,1.065015, + -0.012978,-0.998326,-0.056357,-3.238094,-0.979377,0.961631, + 0.249604,-0.855993,-0.452741,-3.27751,-1.177346,0.9153, + 0.018755,-0.837462,0.546174,-3.122061,-0.998702,1.065015, + 0.249604,-0.855993,-0.452741,-3.27751,-1.177346,0.9153, + -0.094688,-0.959937,0.263734,-3.15021,-1.259588,1.001021, + -0.094688,-0.959937,0.263734,-3.15021,-1.259588,1.001021, + 0.249604,-0.855993,-0.452741,-3.27751,-1.177346,0.9153, + 0.515412,-0.714946,-0.472444,-3.319817,-1.365015,0.886015, + -0.094688,-0.959937,0.263734,-3.15021,-1.259588,1.001021, + 0.515412,-0.714946,-0.472444,-3.319817,-1.365015,0.886015, + 0.059023,-0.965365,0.25414,-3.188954,-1.408279,0.963611, + -0.626255,-0.080061,-0.775497,-3.690685,1.60208,0, + -0.848349,-0.120539,-0.515533,-3.709827,1.417763,0, + -0.454242,-0.890878,-0.000928,-3.709741,1.351194,0.211745, + -0.626255,-0.080061,-0.775497,-3.690685,1.60208,0, + -0.454242,-0.890878,-0.000928,-3.709741,1.351194,0.211745, + 0.49176,-0.810764,0.317543,-3.734989,1.589433,0.295202, + 0.49176,-0.810764,0.317543,-3.734989,1.589433,0.295202, + -0.454242,-0.890878,-0.000928,-3.709741,1.351194,0.211745, + -0.354058,-0.732075,-0.581987,-3.701634,1.27265,0.270469, + 0.49176,-0.810764,0.317543,-3.734989,1.589433,0.295202, + -0.354058,-0.732075,-0.581987,-3.701634,1.27265,0.270469, + 0.43907,-0.579988,0.686172,-3.697974,1.466697,0.433432, + 0.43907,-0.579988,0.686172,-3.697974,1.466697,0.433432, + -0.354058,-0.732075,-0.581987,-3.701634,1.27265,0.270469, + -0.587869,-0.808404,0.029894,-3.695872,1.156978,0.316829, + 0.43907,-0.579988,0.686172,-3.697974,1.466697,0.433432, + -0.587869,-0.808404,0.029894,-3.695872,1.156978,0.316829, + 0.099157,-0.476834,0.873383,-3.684619,1.35069,0.501428, + 0.099157,-0.476834,0.873383,-3.684619,1.35069,0.501428, + -0.587869,-0.808404,0.029894,-3.695872,1.156978,0.316829, + -0.581301,-0.608503,-0.540197,-3.672431,1.044224,0.364991, + 0.099157,-0.476834,0.873383,-3.684619,1.35069,0.501428, + -0.581301,-0.608503,-0.540197,-3.672431,1.044224,0.364991, + -0.073547,-0.481419,0.8734,-3.655148,1.190938,0.573692, + -0.073547,-0.481419,0.8734,-3.655148,1.190938,0.573692, + -0.581301,-0.608503,-0.540197,-3.672431,1.044224,0.364991, + -0.736087,-0.675143,0.048562,-3.664355,0.932851,0.370749, + -0.073547,-0.481419,0.8734,-3.655148,1.190938,0.573692, + -0.736087,-0.675143,0.048562,-3.664355,0.932851,0.370749, + -0.147229,-0.706225,0.69251,-3.639878,1.015186,0.615203, + -0.147229,-0.706225,0.69251,-3.639878,1.015186,0.615203, + -0.736087,-0.675143,0.048562,-3.664355,0.932851,0.370749, + -0.98615,-0.150918,0.068783,-3.631292,0.701013,0.420276, + -0.147229,-0.706225,0.69251,-3.639878,1.015186,0.615203, + -0.98615,-0.150918,0.068783,-3.631292,0.701013,0.420276, + 0.328487,-0.940917,-0.082286,-3.582867,0.734419,0.697787, + 0.328487,-0.940917,-0.082286,-3.582867,0.734419,0.697787, + -0.98615,-0.150918,0.068783,-3.631292,0.701013,0.420276, + -0.84728,-0.52968,0.039439,-3.570384,0.385564,0.52448, + 0.328487,-0.940917,-0.082286,-3.582867,0.734419,0.697787, + -0.84728,-0.52968,0.039439,-3.570384,0.385564,0.52448, + -0.319475,-0.944225,0.079844,-3.504525,0.405574,0.847066, + -0.319475,-0.944225,0.079844,-3.504525,0.405574,0.847066, + -0.84728,-0.52968,0.039439,-3.570384,0.385564,0.52448, + -0.815087,-0.388054,0.430171,-3.520188,0.140164,0.618561, + -0.319475,-0.944225,0.079844,-3.504525,0.405574,0.847066, + -0.815087,-0.388054,0.430171,-3.520188,0.140164,0.618561, + -0.393694,-0.919049,-0.018795,-3.424258,0.158638,0.918279, + -0.393694,-0.919049,-0.018795,-3.424258,0.158638,0.918279, + -0.815087,-0.388054,0.430171,-3.520188,0.140164,0.618561, + -0.945906,-0.323169,0.028687,-3.458251,-0.12595,0.731712, + -0.393694,-0.919049,-0.018795,-3.424258,0.158638,0.918279, + -0.945906,-0.323169,0.028687,-3.458251,-0.12595,0.731712, + -0.327707,-0.94199,-0.072547,-3.365413,-0.113447,0.9524, + -0.327707,-0.94199,-0.072547,-3.365413,-0.113447,0.9524, + -0.945906,-0.323169,0.028687,-3.458251,-0.12595,0.731712, + -0.896964,-0.287307,0.336022,-3.406618,-0.343461,0.746456, + -0.327707,-0.94199,-0.072547,-3.365413,-0.113447,0.9524, + -0.896964,-0.287307,0.336022,-3.406618,-0.343461,0.746456, + -0.163041,-0.980692,-0.107986,-3.290393,-0.424259,0.984153, + -0.163041,-0.980692,-0.107986,-3.290393,-0.424259,0.984153, + -0.896964,-0.287307,0.336022,-3.406618,-0.343461,0.746456, + -0.99574,-0.082547,0.041071,-3.283698,-0.730967,0.793898, + -0.163041,-0.980692,-0.107986,-3.290393,-0.424259,0.984153, + -0.99574,-0.082547,0.041071,-3.283698,-0.730967,0.793898, + 0.074429,-0.99521,-0.063385,-3.233333,-0.683782,1.015512, + -0.040019,-0.929968,0.365457,-2.937658,-1.002749,1.219413, + -0.299215,-0.929389,0.216115,-2.982676,-1.264649,1.133596, + -0.351476,-0.711504,0.608463,-2.725776,-1.214862,1.190384, + -0.040019,-0.929968,0.365457,-2.937658,-1.002749,1.219413, + -0.351476,-0.711504,0.608463,-2.725776,-1.214862,1.190384, + 0.162276,-0.745105,0.646905,-2.624856,-0.8882,1.261176, + -0.403877,-0.879274,0.252509,-2.901159,-0.619504,1.284058, + -0.040019,-0.929968,0.365457,-2.937658,-1.002749,1.219413, + 0.162276,-0.745105,0.646905,-2.624856,-0.8882,1.261176, + -0.403877,-0.879274,0.252509,-2.901159,-0.619504,1.284058, + 0.162276,-0.745105,0.646905,-2.624856,-0.8882,1.261176, + -0.11636,-0.749063,0.652201,-2.616467,-0.511373,1.344133, + -0.171647,-0.971664,0.162499,-2.90708,-0.345582,1.281557, + -0.403877,-0.879274,0.252509,-2.901159,-0.619504,1.284058, + -0.11636,-0.749063,0.652201,-2.616467,-0.511373,1.344133, + -0.171647,-0.971664,0.162499,-2.90708,-0.345582,1.281557, + -0.11636,-0.749063,0.652201,-2.616467,-0.511373,1.344133, + 0.215155,-0.464575,0.858999,-2.649338,-0.241719,1.339644, + -0.198045,-0.959194,0.201804,-2.971546,0.032038,1.215971, + -0.171647,-0.971664,0.162499,-2.90708,-0.345582,1.281557, + 0.215155,-0.464575,0.858999,-2.649338,-0.241719,1.339644, + -0.198045,-0.959194,0.201804,-2.971546,0.032038,1.215971, + 0.215155,-0.464575,0.858999,-2.649338,-0.241719,1.339644, + 0.121987,-0.426327,0.896306,-2.687022,0.076781,1.290565, + -0.279342,-0.940234,0.19475,-3.044646,0.224321,1.164934, + -0.198045,-0.959194,0.201804,-2.971546,0.032038,1.215971, + 0.121987,-0.426327,0.896306,-2.687022,0.076781,1.290565, + -0.279342,-0.940234,0.19475,-3.044646,0.224321,1.164934, + 0.121987,-0.426327,0.896306,-2.687022,0.076781,1.290565, + 0.161064,-0.731195,0.662882,-2.787011,0.264495,1.237352, + 0.152347,-0.821467,0.549529,-3.112555,0.457376,1.084816, + -0.279342,-0.940234,0.19475,-3.044646,0.224321,1.164934, + 0.161064,-0.731195,0.662882,-2.787011,0.264495,1.237352, + 0.152347,-0.821467,0.549529,-3.112555,0.457376,1.084816, + 0.161064,-0.731195,0.662882,-2.787011,0.264495,1.237352, + 0.08565,-0.422547,0.902285,-2.79063,0.46881,1.224273, + -0.094238,-0.851252,0.516225,-3.19641,0.797564,0.985913, + 0.152347,-0.821467,0.549529,-3.112555,0.457376,1.084816, + 0.08565,-0.422547,0.902285,-2.79063,0.46881,1.224273, + -0.094238,-0.851252,0.516225,-3.19641,0.797564,0.985913, + 0.08565,-0.422547,0.902285,-2.79063,0.46881,1.224273, + 0.155794,-0.590112,0.792146,-2.825835,0.755899,1.209042, + -0.079302,-0.84299,0.532051,-3.244771,1.19554,0.910945, + -0.094238,-0.851252,0.516225,-3.19641,0.797564,0.985913, + 0.155794,-0.590112,0.792146,-2.825835,0.755899,1.209042, + -0.079302,-0.84299,0.532051,-3.244771,1.19554,0.910945, + 0.155794,-0.590112,0.792146,-2.825835,0.755899,1.209042, + 0.106237,-0.558927,0.822383,-2.930312,1.10358,1.125876, + -0.176655,-0.950799,0.254508,-3.27808,1.432418,0.853958, + -0.079302,-0.84299,0.532051,-3.244771,1.19554,0.910945, + 0.106237,-0.558927,0.822383,-2.930312,1.10358,1.125876, + -0.176655,-0.950799,0.254508,-3.27808,1.432418,0.853958, + 0.106237,-0.558927,0.822383,-2.930312,1.10358,1.125876, + 0.008663,-0.516082,0.856495,-3.028932,1.461517,0.941324, + -0.4144,-0.844957,0.338113,-3.338742,1.598933,0.689636, + -0.176655,-0.950799,0.254508,-3.27808,1.432418,0.853958, + 0.008663,-0.516082,0.856495,-3.028932,1.461517,0.941324, + -0.4144,-0.844957,0.338113,-3.338742,1.598933,0.689636, + 0.008663,-0.516082,0.856495,-3.028932,1.461517,0.941324, + 0.357021,-0.590654,0.723646,-3.08565,1.65734,0.784479, + -0.150892,-0.83775,0.524792,-3.395381,1.726325,0.55477, + -0.4144,-0.844957,0.338113,-3.338742,1.598933,0.689636, + 0.357021,-0.590654,0.723646,-3.08565,1.65734,0.784479, + -0.150892,-0.83775,0.524792,-3.395381,1.726325,0.55477, + 0.357021,-0.590654,0.723646,-3.08565,1.65734,0.784479, + -0.201818,-0.568242,0.797728,-3.109047,1.789477,0.565323, + -0.468954,-0.586277,0.660577,-3.35851,1.810253,0.380095, + -0.150892,-0.83775,0.524792,-3.395381,1.726325,0.55477, + -0.201818,-0.568242,0.797728,-3.109047,1.789477,0.565323, + -0.468954,-0.586277,0.660577,-3.35851,1.810253,0.380095, + -0.201818,-0.568242,0.797728,-3.109047,1.789477,0.565323, + 0.094371,-0.230057,0.968591,-3.07531,1.846,0.363149, + 0.009712,0.399549,0.91666,-2.687162,-1.539807,0.988048, + -0.004413,-0.170526,0.985343,-2.566746,-1.211312,1.167101, + 0.095733,-0.224552,0.969748,-2.765069,-1.561164,1.084313, + -0.951862,0.098243,0.290356,-2.462835,-1.3055,0.966395, + -0.822733,0.223687,0.522565,-2.306662,-1.116976,0.961238, + 0.074896,0.047734,0.996048,-2.299356,-1.025449,1.044687, + -0.951862,0.098243,0.290356,-2.462835,-1.3055,0.966395, + 0.074896,0.047734,0.996048,-2.299356,-1.025449,1.044687, + -0.004413,-0.170526,0.985343,-2.566746,-1.211312,1.167101, + 0.009712,0.399549,0.91666,-2.687162,-1.539807,0.988048, + -0.995081,-0.092251,-0.036114,-2.591357,-1.510845,0.88547, + -0.951862,0.098243,0.290356,-2.462835,-1.3055,0.966395, + 0.009712,0.399549,0.91666,-2.687162,-1.539807,0.988048, + -0.951862,0.098243,0.290356,-2.462835,-1.3055,0.966395, + -0.004413,-0.170526,0.985343,-2.566746,-1.211312,1.167101, + 0.247956,0.087485,-0.964813,1.772999,-2.230292,0.64494, + 0.81802,-0.47123,0.329827,1.747671,-2.067518,0.638841, + 0.761939,0.13671,-0.633055,1.945206,-2.015769,0.672724, + 0.247956,0.087485,-0.964813,1.772999,-2.230292,0.64494, + 0.761939,0.13671,-0.633055,1.945206,-2.015769,0.672724, + -0.121543,0.046,-0.99152,1.921881,-2.157616,0.692678, + 0.70745,-0.193334,0.679806,2.13239,1.755821,0.180271, + 0.756976,-0.653442,0,2.128139,1.788397,0, + -0.385788,0.922588,0,2.042206,1.777154,0, + 0.70745,-0.193334,0.679806,2.13239,1.755821,0.180271, + -0.385788,0.922588,0,2.042206,1.777154,0, + 0.411872,0.04507,0.910127,2.069379,1.727818,0.212746, + -0.149005,-0.65467,0.741084,-2.862576,-1.546894,1.117139, + -0.351476,-0.711504,0.608463,-2.725776,-1.214862,1.190384, + -0.461794,0.113692,0.879671,-2.955052,-1.49684,1.128812, + -0.18119,-0.970212,0.160805,-3.063133,-1.440555,1.090926, + 0.059023,-0.965365,0.25414,-3.188954,-1.408279,0.963611, + -0.46316,0.228643,0.856274,-3.357996,-1.811803,0.975625, + -0.18119,-0.970212,0.160805,-3.063133,-1.440555,1.090926, + -0.46316,0.228643,0.856274,-3.357996,-1.811803,0.975625, + -0.431118,-0.034268,0.901645,-3.23261,-1.834299,1.087832, + -0.351476,-0.711504,0.608463,-2.725776,-1.214862,1.190384, + -0.299215,-0.929389,0.216115,-2.982676,-1.264649,1.133596, + -0.18119,-0.970212,0.160805,-3.063133,-1.440555,1.090926, + -0.351476,-0.711504,0.608463,-2.725776,-1.214862,1.190384, + -0.18119,-0.970212,0.160805,-3.063133,-1.440555,1.090926, + -0.461794,0.113692,0.879671,-2.955052,-1.49684,1.128812, + 0.059023,-0.965365,0.25414,-3.188954,-1.408279,0.963611, + 0.515412,-0.714946,-0.472444,-3.319817,-1.365015,0.886015, + 0.737412,0.542596,0.402261,-3.36599,-1.48517,0.888076, + 0.059023,-0.965365,0.25414,-3.188954,-1.408279,0.963611, + 0.737412,0.542596,0.402261,-3.36599,-1.48517,0.888076, + -0.508357,0.250892,0.823787,-3.342096,-1.533989,0.921628, + 0.059023,-0.965365,0.25414,-3.188954,-1.408279,0.963611, + -0.508357,0.250892,0.823787,-3.342096,-1.533989,0.921628, + -0.46316,0.228643,0.856274,-3.357996,-1.811803,0.975625, + -0.037581,-0.042039,-0.998409,-2.964215,-1.978727,0.776572, + -0.732521,-0.474279,0.488336,-2.811581,-1.79821,0.712737, + 0.942117,-0.292664,0.163592,-2.734184,-1.717948,0.749581, + -0.037581,-0.042039,-0.998409,-2.964215,-1.978727,0.776572, + 0.942117,-0.292664,0.163592,-2.734184,-1.717948,0.749581, + -0.11646,-0.017993,-0.993032,-2.892438,-1.95081,0.87812, + 0.942117,-0.292664,0.163592,-2.734184,-1.717948,0.749581, + -0.13251,0.440061,0.888137,-2.837147,-1.791733,0.921563, + -0.11646,-0.017993,-0.993032,-2.892438,-1.95081,0.87812, + -0.674431,0.094186,-0.732306,-3.04661,-2.510881,0.900772, + 0.780958,0.624512,0.00945,-3.132772,-2.528669,0.848639, + -0.039603,0.339955,0.939607,-3.144012,-2.333635,0.829994, + -0.674431,0.094186,-0.732306,-3.04661,-2.510881,0.900772, + -0.039603,0.339955,0.939607,-3.144012,-2.333635,0.829994, + 0.339875,0.026681,-0.940092,-3.030605,-2.311222,0.88433, + 0.245984,0.029506,0.968825,-3.223286,-3.00178,1.126176, + 0.567548,-0.015056,0.823203,-3.26181,-2.821069,1.088218, + 0.71789,-0.165877,0.676106,-3.32033,-2.827513,1.063914, + 0.245984,0.029506,0.968825,-3.223286,-3.00178,1.126176, + 0.71789,-0.165877,0.676106,-3.32033,-2.827513,1.063914, + 0.788485,-0.288832,0.543017,-3.302419,-3.017921,1.128514, + 0.701058,-0.463233,0.542155,-2.986345,-2.93377,1.087679, + 0.705477,-0.524425,0.47674,-3.053267,-2.764905,1.043008, + -0.119083,0.074969,0.99005,-3.141072,-2.785287,1.032318, + 0.701058,-0.463233,0.542155,-2.986345,-2.93377,1.087679, + -0.119083,0.074969,0.99005,-3.141072,-2.785287,1.032318, + 0.021785,0.053611,0.998324,-3.107105,-2.947818,1.092235, + 0.23503,0.016105,0.971855,-2.946527,-2.939327,0.986343, + 0.441943,-0.143195,0.88554,-3.016419,-2.765091,0.966671, + 0.705477,-0.524425,0.47674,-3.053267,-2.764905,1.043008, + 0.23503,0.016105,0.971855,-2.946527,-2.939327,0.986343, + 0.705477,-0.524425,0.47674,-3.053267,-2.764905,1.043008, + 0.701058,-0.463233,0.542155,-2.986345,-2.93377,1.087679, + 0.586456,-0.375618,0.717621,-3.301857,-3.074776,1.114869, + 0.245984,0.029506,0.968825,-3.223286,-3.00178,1.126176, + 0.788485,-0.288832,0.543017,-3.302419,-3.017921,1.128514, + 0.585043,-0.503499,0.635777,-3.316551,-3.168932,1.121229, + -0.140754,0.08766,0.986156,-3.227676,-3.14166,1.103969, + 0.586456,-0.375618,0.717621,-3.301857,-3.074776,1.114869, + 0.085126,0.114843,0.98973,-3.217306,-3.187686,1.075214, + -0.140754,0.08766,0.986156,-3.227676,-3.14166,1.103969, + 0.585043,-0.503499,0.635777,-3.316551,-3.168932,1.121229, + 0.07463,0.029476,0.996776,-2.90901,-3.084482,1.089147, + -0.161613,0.16539,0.972896,-2.884711,-3.063896,0.993766, + 0.23503,0.016105,0.971855,-2.946527,-2.939327,0.986343, + 0.07463,0.029476,0.996776,-2.90901,-3.084482,1.089147, + 0.23503,0.016105,0.971855,-2.946527,-2.939327,0.986343, + 0.701058,-0.463233,0.542155,-2.986345,-2.93377,1.087679, + -0.119083,0.074969,0.99005,-3.141072,-2.785287,1.032318, + -0.347185,0.293858,0.890567,-3.196508,-2.788166,1.045431, + -0.225282,0.274902,0.934707,-3.177108,-2.979305,1.139084, + -0.119083,0.074969,0.99005,-3.141072,-2.785287,1.032318, + -0.225282,0.274902,0.934707,-3.177108,-2.979305,1.139084, + 0.021785,0.053611,0.998324,-3.107105,-2.947818,1.092235, + -0.225282,0.274902,0.934707,-3.177108,-2.979305,1.139084, + -0.347185,0.293858,0.890567,-3.196508,-2.788166,1.045431, + 0.567548,-0.015056,0.823203,-3.26181,-2.821069,1.088218, + -0.225282,0.274902,0.934707,-3.177108,-2.979305,1.139084, + 0.567548,-0.015056,0.823203,-3.26181,-2.821069,1.088218, + 0.245984,0.029506,0.968825,-3.223286,-3.00178,1.126176, + -0.921044,0.324519,0.215325,-3.330406,-3.18519,0.950058, + 0.585043,-0.503499,0.635777,-3.316551,-3.168932,1.121229, + 0.586456,-0.375618,0.717621,-3.301857,-3.074776,1.114869, + -0.921044,0.324519,0.215325,-3.330406,-3.18519,0.950058, + 0.586456,-0.375618,0.717621,-3.301857,-3.074776,1.114869, + -0.904362,0.426369,-0.018424,-3.333954,-3.058673,0.974748, + -0.588311,0.26373,0.764419,-3.223246,-3.225388,0.976573, + 0.085126,0.114843,0.98973,-3.217306,-3.187686,1.075214, + 0.585043,-0.503499,0.635777,-3.316551,-3.168932,1.121229, + -0.588311,0.26373,0.764419,-3.223246,-3.225388,0.976573, + 0.585043,-0.503499,0.635777,-3.316551,-3.168932,1.121229, + -0.921044,0.324519,0.215325,-3.330406,-3.18519,0.950058, + -0.64352,0.086605,-0.760514,-3.11957,-3.183977,0.870739, + -0.588311,0.26373,0.764419,-3.223246,-3.225388,0.976573, + -0.921044,0.324519,0.215325,-3.330406,-3.18519,0.950058, + -0.64352,0.086605,-0.760514,-3.11957,-3.183977,0.870739, + -0.921044,0.324519,0.215325,-3.330406,-3.18519,0.950058, + -0.190279,0.223108,-0.956042,-3.294389,-3.166225,0.842823, + -0.121989,0.019056,-0.992349,-3.256731,-3.032131,0.849693, + -0.190279,0.223108,-0.956042,-3.294389,-3.166225,0.842823, + -0.921044,0.324519,0.215325,-3.330406,-3.18519,0.950058, + -0.121989,0.019056,-0.992349,-3.256731,-3.032131,0.849693, + -0.921044,0.324519,0.215325,-3.330406,-3.18519,0.950058, + -0.904362,0.426369,-0.018424,-3.333954,-3.058673,0.974748, + -0.904362,0.426369,-0.018424,-3.333954,-3.058673,0.974748, + -0.149743,-0.291108,-0.944898,-3.339637,-2.846837,0.966368, + -0.146645,-0.575935,-0.804235,-3.300372,-2.795728,0.878984, + -0.904362,0.426369,-0.018424,-3.333954,-3.058673,0.974748, + -0.146645,-0.575935,-0.804235,-3.300372,-2.795728,0.878984, + -0.121989,0.019056,-0.992349,-3.256731,-3.032131,0.849693, + 0.021785,0.053611,0.998324,-3.107105,-2.947818,1.092235, + -0.541406,0.227835,0.809302,-3.03125,-3.09594,1.106355, + 0.07463,0.029476,0.996776,-2.90901,-3.084482,1.089147, + 0.021785,0.053611,0.998324,-3.107105,-2.947818,1.092235, + 0.07463,0.029476,0.996776,-2.90901,-3.084482,1.089147, + 0.701058,-0.463233,0.542155,-2.986345,-2.93377,1.087679, + 0.021785,0.053611,0.998324,-3.107105,-2.947818,1.092235, + -0.225282,0.274902,0.934707,-3.177108,-2.979305,1.139084, + -0.125911,-0.68432,-0.718229,-3.121673,-3.120319,1.136456, + 0.021785,0.053611,0.998324,-3.107105,-2.947818,1.092235, + -0.125911,-0.68432,-0.718229,-3.121673,-3.120319,1.136456, + -0.541406,0.227835,0.809302,-3.03125,-3.09594,1.106355, + 0.245984,0.029506,0.968825,-3.223286,-3.00178,1.126176, + 0.535863,0.090315,-0.83946,-3.169546,-3.135273,1.128247, + -0.125911,-0.68432,-0.718229,-3.121673,-3.120319,1.136456, + 0.245984,0.029506,0.968825,-3.223286,-3.00178,1.126176, + -0.125911,-0.68432,-0.718229,-3.121673,-3.120319,1.136456, + -0.225282,0.274902,0.934707,-3.177108,-2.979305,1.139084, + 0.085126,0.114843,0.98973,-3.217306,-3.187686,1.075214, + 0.535863,0.090315,-0.83946,-3.169546,-3.135273,1.128247, + -0.140754,0.08766,0.986156,-3.227676,-3.14166,1.103969, + -0.140754,0.08766,0.986156,-3.227676,-3.14166,1.103969, + 0.535863,0.090315,-0.83946,-3.169546,-3.135273,1.128247, + 0.245984,0.029506,0.968825,-3.223286,-3.00178,1.126176, + -0.140754,0.08766,0.986156,-3.227676,-3.14166,1.103969, + 0.245984,0.029506,0.968825,-3.223286,-3.00178,1.126176, + 0.586456,-0.375618,0.717621,-3.301857,-3.074776,1.114869, + 0.788485,-0.288832,0.543017,-3.302419,-3.017921,1.128514, + -0.904362,0.426369,-0.018424,-3.333954,-3.058673,0.974748, + 0.586456,-0.375618,0.717621,-3.301857,-3.074776,1.114869, + -0.904362,0.426369,-0.018424,-3.333954,-3.058673,0.974748, + 0.788485,-0.288832,0.543017,-3.302419,-3.017921,1.128514, + 0.71789,-0.165877,0.676106,-3.32033,-2.827513,1.063914, + -0.904362,0.426369,-0.018424,-3.333954,-3.058673,0.974748, + 0.71789,-0.165877,0.676106,-3.32033,-2.827513,1.063914, + -0.149743,-0.291108,-0.944898,-3.339637,-2.846837,0.966368, + 0.236645,-0.06852,-0.969177,-2.928681,-3.072892,0.924772, + 0.091886,-0.230243,-0.968785,-3.008412,-2.89976,0.904635, + 0.23503,0.016105,0.971855,-2.946527,-2.939327,0.986343, + 0.236645,-0.06852,-0.969177,-2.928681,-3.072892,0.924772, + 0.23503,0.016105,0.971855,-2.946527,-2.939327,0.986343, + -0.161613,0.16539,0.972896,-2.884711,-3.063896,0.993766, + -0.888643,-0.077171,0.45206,-3.166971,-3.002766,0.812106, + -0.64352,0.086605,-0.760514,-3.11957,-3.183977,0.870739, + -0.190279,0.223108,-0.956042,-3.294389,-3.166225,0.842823, + -0.121989,0.019056,-0.992349,-3.256731,-3.032131,0.849693, + -0.888643,-0.077171,0.45206,-3.166971,-3.002766,0.812106, + -0.190279,0.223108,-0.956042,-3.294389,-3.166225,0.842823, + -0.888643,-0.077171,0.45206,-3.166971,-3.002766,0.812106, + -0.891992,-0.016937,0.451734,-3.06981,-2.928755,0.845236, + -0.860798,0.234294,0.451812,-3.011987,-3.092,0.860973, + -0.888643,-0.077171,0.45206,-3.166971,-3.002766,0.812106, + -0.860798,0.234294,0.451812,-3.011987,-3.092,0.860973, + -0.64352,0.086605,-0.760514,-3.11957,-3.183977,0.870739, + -0.891992,-0.016937,0.451734,-3.06981,-2.928755,0.845236, + 0.091886,-0.230243,-0.968785,-3.008412,-2.89976,0.904635, + 0.236645,-0.06852,-0.969177,-2.928681,-3.072892,0.924772, + -0.891992,-0.016937,0.451734,-3.06981,-2.928755,0.845236, + 0.236645,-0.06852,-0.969177,-2.928681,-3.072892,0.924772, + -0.860798,0.234294,0.451812,-3.011987,-3.092,0.860973, + -0.686439,0.576002,0.443872,-3.184812,-2.768053,0.850127, + -0.369855,0.817227,0.441981,-3.137383,-2.776449,0.844117, + -0.891992,-0.016937,0.451734,-3.06981,-2.928755,0.845236, + -0.686439,0.576002,0.443872,-3.184812,-2.768053,0.850127, + -0.891992,-0.016937,0.451734,-3.06981,-2.928755,0.845236, + -0.888643,-0.077171,0.45206,-3.166971,-3.002766,0.812106, + 0.011581,0.887039,0.461548,-3.040038,-2.780893,0.914614, + 0.091886,-0.230243,-0.968785,-3.008412,-2.89976,0.904635, + -0.891992,-0.016937,0.451734,-3.06981,-2.928755,0.845236, + 0.011581,0.887039,0.461548,-3.040038,-2.780893,0.914614, + -0.891992,-0.016937,0.451734,-3.06981,-2.928755,0.845236, + -0.369855,0.817227,0.441981,-3.137383,-2.776449,0.844117, + -0.146645,-0.575935,-0.804235,-3.300372,-2.795728,0.878984, + -0.686439,0.576002,0.443872,-3.184812,-2.768053,0.850127, + -0.888643,-0.077171,0.45206,-3.166971,-3.002766,0.812106, + -0.146645,-0.575935,-0.804235,-3.300372,-2.795728,0.878984, + -0.888643,-0.077171,0.45206,-3.166971,-3.002766,0.812106, + -0.121989,0.019056,-0.992349,-3.256731,-3.032131,0.849693, + 0.091886,-0.230243,-0.968785,-3.008412,-2.89976,0.904635, + 0.011581,0.887039,0.461548,-3.040038,-2.780893,0.914614, + 0.441943,-0.143195,0.88554,-3.016419,-2.765091,0.966671, + 0.091886,-0.230243,-0.968785,-3.008412,-2.89976,0.904635, + 0.441943,-0.143195,0.88554,-3.016419,-2.765091,0.966671, + 0.23503,0.016105,0.971855,-2.946527,-2.939327,0.986343, + 0.840313,0.535537,-0.084107,-3.078699,-2.553982,1.046834, + 0.851754,0.52393,-0.003494,-3.162498,-2.556375,1.058409, + -0.119083,0.074969,0.99005,-3.141072,-2.785287,1.032318, + 0.840313,0.535537,-0.084107,-3.078699,-2.553982,1.046834, + -0.119083,0.074969,0.99005,-3.141072,-2.785287,1.032318, + 0.705477,-0.524425,0.47674,-3.053267,-2.764905,1.043008, + -0.99734,0.010762,-0.072093,-3.347304,-2.573628,0.955211, + 0.308087,0.149605,-0.939522,-3.372066,-2.569159,0.904785, + -0.149743,-0.291108,-0.944898,-3.339637,-2.846837,0.966368, + -0.99734,0.010762,-0.072093,-3.347304,-2.573628,0.955211, + -0.149743,-0.291108,-0.944898,-3.339637,-2.846837,0.966368, + 0.71789,-0.165877,0.676106,-3.32033,-2.827513,1.063914, + 0.163153,0.19945,0.96623,-3.251541,-2.56405,1.023627, + -0.99734,0.010762,-0.072093,-3.347304,-2.573628,0.955211, + 0.71789,-0.165877,0.676106,-3.32033,-2.827513,1.063914, + 0.163153,0.19945,0.96623,-3.251541,-2.56405,1.023627, + 0.71789,-0.165877,0.676106,-3.32033,-2.827513,1.063914, + 0.567548,-0.015056,0.823203,-3.26181,-2.821069,1.088218, + 0.851754,0.52393,-0.003494,-3.162498,-2.556375,1.058409, + 0.163153,0.19945,0.96623,-3.251541,-2.56405,1.023627, + 0.567548,-0.015056,0.823203,-3.26181,-2.821069,1.088218, + 0.851754,0.52393,-0.003494,-3.162498,-2.556375,1.058409, + 0.567548,-0.015056,0.823203,-3.26181,-2.821069,1.088218, + -0.347185,0.293858,0.890567,-3.196508,-2.788166,1.045431, + 0.851754,0.52393,-0.003494,-3.162498,-2.556375,1.058409, + -0.347185,0.293858,0.890567,-3.196508,-2.788166,1.045431, + -0.119083,0.074969,0.99005,-3.141072,-2.785287,1.032318, + 0.705477,-0.524425,0.47674,-3.053267,-2.764905,1.043008, + 0.441943,-0.143195,0.88554,-3.016419,-2.765091,0.966671, + -0.178214,-0.110838,-0.977729,-3.022819,-2.52224,0.979148, + 0.705477,-0.524425,0.47674,-3.053267,-2.764905,1.043008, + -0.178214,-0.110838,-0.977729,-3.022819,-2.52224,0.979148, + 0.840313,0.535537,-0.084107,-3.078699,-2.553982,1.046834, + -0.146645,-0.575935,-0.804235,-3.300372,-2.795728,0.878984, + -0.149743,-0.291108,-0.944898,-3.339637,-2.846837,0.966368, + 0.308087,0.149605,-0.939522,-3.372066,-2.569159,0.904785, + -0.146645,-0.575935,-0.804235,-3.300372,-2.795728,0.878984, + 0.308087,0.149605,-0.939522,-3.372066,-2.569159,0.904785, + 0.722847,0.455753,-0.519404,-3.297886,-2.54902,0.861657, + -0.686439,0.576002,0.443872,-3.184812,-2.768053,0.850127, + -0.146645,-0.575935,-0.804235,-3.300372,-2.795728,0.878984, + 0.722847,0.455753,-0.519404,-3.297886,-2.54902,0.861657, + -0.686439,0.576002,0.443872,-3.184812,-2.768053,0.850127, + 0.722847,0.455753,-0.519404,-3.297886,-2.54902,0.861657, + 0.61389,0.702597,0.359856,-3.240554,-2.555467,0.856262, + -0.369855,0.817227,0.441981,-3.137383,-2.776449,0.844117, + -0.686439,0.576002,0.443872,-3.184812,-2.768053,0.850127, + 0.61389,0.702597,0.359856,-3.240554,-2.555467,0.856262, + -0.369855,0.817227,0.441981,-3.137383,-2.776449,0.844117, + 0.61389,0.702597,0.359856,-3.240554,-2.555467,0.856262, + 0.780958,0.624512,0.00945,-3.132772,-2.528669,0.848639, + 0.011581,0.887039,0.461548,-3.040038,-2.780893,0.914614, + -0.369855,0.817227,0.441981,-3.137383,-2.776449,0.844117, + 0.780958,0.624512,0.00945,-3.132772,-2.528669,0.848639, + 0.011581,0.887039,0.461548,-3.040038,-2.780893,0.914614, + 0.780958,0.624512,0.00945,-3.132772,-2.528669,0.848639, + -0.674431,0.094186,-0.732306,-3.04661,-2.510881,0.900772, + 0.441943,-0.143195,0.88554,-3.016419,-2.765091,0.966671, + 0.011581,0.887039,0.461548,-3.040038,-2.780893,0.914614, + -0.674431,0.094186,-0.732306,-3.04661,-2.510881,0.900772, + 0.441943,-0.143195,0.88554,-3.016419,-2.765091,0.966671, + -0.674431,0.094186,-0.732306,-3.04661,-2.510881,0.900772, + -0.178214,-0.110838,-0.977729,-3.022819,-2.52224,0.979148, + -0.521685,-0.261319,0.812131,-3.335942,-1.365685,0.72459, + 0.515412,-0.714946,-0.472444,-3.319817,-1.365015,0.886015, + 0.249604,-0.855993,-0.452741,-3.27751,-1.177346,0.9153, + -0.521685,-0.261319,0.812131,-3.335942,-1.365685,0.72459, + 0.249604,-0.855993,-0.452741,-3.27751,-1.177346,0.9153, + -0.872722,-0.174901,0.455813,-3.27979,-1.162072,0.784602, + -0.012978,-0.998326,-0.056357,-3.238094,-0.979377,0.961631, + 0.074429,-0.99521,-0.063385,-3.233333,-0.683782,1.015512, + -0.99574,-0.082547,0.041071,-3.283698,-0.730967,0.793898, + -0.012978,-0.998326,-0.056357,-3.238094,-0.979377,0.961631, + -0.99574,-0.082547,0.041071,-3.283698,-0.730967,0.793898, + -0.874358,-0.225285,0.429819,-3.25121,-0.948205,0.819868, + 0.249604,-0.855993,-0.452741,-3.27751,-1.177346,0.9153, + -0.012978,-0.998326,-0.056357,-3.238094,-0.979377,0.961631, + -0.874358,-0.225285,0.429819,-3.25121,-0.948205,0.819868, + 0.249604,-0.855993,-0.452741,-3.27751,-1.177346,0.9153, + -0.874358,-0.225285,0.429819,-3.25121,-0.948205,0.819868, + -0.872722,-0.174901,0.455813,-3.27979,-1.162072,0.784602, + -0.99574,-0.082547,0.041071,-3.283698,-0.730967,0.793898, + -0.896964,-0.287307,0.336022,-3.406618,-0.343461,0.746456, + -0.970971,-0.219011,0.096178,-3.415655,-0.308965,0.671045, + -0.98615,-0.150918,0.068783,-3.631292,0.701013,0.420276, + -0.736087,-0.675143,0.048562,-3.664355,0.932851,0.370749, + -0.845931,-0.255219,-0.468256,-3.57817,0.837714,0.288502, + -0.98615,-0.150918,0.068783,-3.631292,0.701013,0.420276, + -0.845931,-0.255219,-0.468256,-3.57817,0.837714,0.288502, + -0.794709,-0.185222,-0.57804,-3.556552,0.704883,0.28063, + -0.84728,-0.52968,0.039439,-3.570384,0.385564,0.52448, + -0.98615,-0.150918,0.068783,-3.631292,0.701013,0.420276, + -0.794709,-0.185222,-0.57804,-3.556552,0.704883,0.28063, + -0.84728,-0.52968,0.039439,-3.570384,0.385564,0.52448, + -0.794709,-0.185222,-0.57804,-3.556552,0.704883,0.28063, + -0.17902,-0.308668,0.934171,-3.536654,0.442277,0.322, + -0.815087,-0.388054,0.430171,-3.520188,0.140164,0.618561, + -0.84728,-0.52968,0.039439,-3.570384,0.385564,0.52448, + -0.17902,-0.308668,0.934171,-3.536654,0.442277,0.322, + -0.815087,-0.388054,0.430171,-3.520188,0.140164,0.618561, + -0.17902,-0.308668,0.934171,-3.536654,0.442277,0.322, + -0.136917,-0.20176,0.969818,-3.51684,0.149002,0.430359, + -0.945906,-0.323169,0.028687,-3.458251,-0.12595,0.731712, + -0.815087,-0.388054,0.430171,-3.520188,0.140164,0.618561, + -0.136917,-0.20176,0.969818,-3.51684,0.149002,0.430359, + -0.945906,-0.323169,0.028687,-3.458251,-0.12595,0.731712, + -0.136917,-0.20176,0.969818,-3.51684,0.149002,0.430359, + -0.739347,0.031953,0.672566,-3.470778,-0.078218,0.546398, + -0.896964,-0.287307,0.336022,-3.406618,-0.343461,0.746456, + -0.945906,-0.323169,0.028687,-3.458251,-0.12595,0.731712, + -0.739347,0.031953,0.672566,-3.470778,-0.078218,0.546398, + -0.896964,-0.287307,0.336022,-3.406618,-0.343461,0.746456, + -0.739347,0.031953,0.672566,-3.470778,-0.078218,0.546398, + -0.970971,-0.219011,0.096178,-3.415655,-0.308965,0.671045, + -0.989171,0.146765,0,-3.599077,0.796217,0, + -0.845931,-0.255219,-0.468256,-3.57817,0.837714,0.288502, + -0.736087,-0.675143,0.048562,-3.664355,0.932851,0.370749, + -0.989171,0.146765,0,-3.599077,0.796217,0, + -0.736087,-0.675143,0.048562,-3.664355,0.932851,0.370749, + -0.996668,0.081567,0,-3.623861,0.911561,0, + -0.454242,-0.890878,-0.000928,-3.709741,1.351194,0.211745, + -0.848349,-0.120539,-0.515533,-3.709827,1.417763,0, + -0.844095,-0.536194,0,-3.601668,1.293049,0, + -0.354058,-0.732075,-0.581987,-3.701634,1.27265,0.270469, + -0.454242,-0.890878,-0.000928,-3.709741,1.351194,0.211745, + -0.844095,-0.536194,0,-3.601668,1.293049,0, + -0.587869,-0.808404,0.029894,-3.695872,1.156978,0.316829, + -0.354058,-0.732075,-0.581987,-3.701634,1.27265,0.270469, + -0.844095,-0.536194,0,-3.601668,1.293049,0, + -0.587869,-0.808404,0.029894,-3.695872,1.156978,0.316829, + -0.844095,-0.536194,0,-3.601668,1.293049,0, + -0.946116,-0.323827,0,-3.608593,1.163581,0, + -0.581301,-0.608503,-0.540197,-3.672431,1.044224,0.364991, + -0.587869,-0.808404,0.029894,-3.695872,1.156978,0.316829, + -0.946116,-0.323827,0,-3.608593,1.163581,0, + -0.581301,-0.608503,-0.540197,-3.672431,1.044224,0.364991, + -0.946116,-0.323827,0,-3.608593,1.163581,0, + -0.997181,-0.075036,0,-3.622326,1.005378,0, + -0.736087,-0.675143,0.048562,-3.664355,0.932851,0.370749, + -0.581301,-0.608503,-0.540197,-3.672431,1.044224,0.364991, + -0.997181,-0.075036,0,-3.622326,1.005378,0, + -0.736087,-0.675143,0.048562,-3.664355,0.932851,0.370749, + -0.997181,-0.075036,0,-3.622326,1.005378,0, + -0.996668,0.081567,0,-3.623861,0.911561,0, + 0.166377,-0.157108,0.973466,-3.86074,-0.188349,-0.024962, + 0.238843,0.101951,0.965691,-3.84599,-0.18882,0.019164, + 0.604306,0.20436,0.770098,-3.81743,0.150343,0.048629, + 0.166377,-0.157108,0.973466,-3.86074,-0.188349,-0.024962, + 0.604306,0.20436,0.770098,-3.81743,0.150343,0.048629, + 0.054863,-0.132814,0.989621,-3.828633,0.149083,0, + 0.054863,-0.132814,0.989621,-3.828633,0.149083,0, + 0.604306,0.20436,0.770098,-3.81743,0.150343,0.048629, + 0.02054,-0.128179,0.991538,-3.84447,0.498176,0.053132, + 0.054863,-0.132814,0.989621,-3.828633,0.149083,0, + 0.02054,-0.128179,0.991538,-3.84447,0.498176,0.053132, + -0.996511,-0.083465,-0.000062,-3.856649,0.496801,0, + -0.996511,-0.083465,-0.000062,-3.856649,0.496801,0, + 0.02054,-0.128179,0.991538,-3.84447,0.498176,0.053132, + 0.193291,-0.0748,0.978286,-3.88734,1.003866,0.057635, + -0.996511,-0.083465,-0.000062,-3.856649,0.496801,0, + 0.193291,-0.0748,0.978286,-3.88734,1.003866,0.057635, + -0.999862,-0.016634,0,-3.900566,1.002504,0, + -0.999862,-0.016634,0,-3.900566,1.002504,0, + 0.193291,-0.0748,0.978286,-3.88734,1.003866,0.057635, + 0.133637,0.26732,0.954296,-3.86082,1.479723,0.062137, + -0.999862,-0.016634,0,-3.900566,1.002504,0, + 0.133637,0.26732,0.954296,-3.86082,1.479723,0.062137, + -0.964752,0.26316,0,-3.87514,1.480358,0, + -0.964752,0.26316,0,-3.87514,1.480358,0, + 0.133637,0.26732,0.954296,-3.86082,1.479723,0.062137, + 0.555353,0.507651,0.65869,-3.698925,1.787941,0.06664, + -0.964752,0.26316,0,-3.87514,1.480358,0, + 0.555353,0.507651,0.65869,-3.698925,1.787941,0.06664, + -0.766357,0.642415,0,-3.712832,1.794492,0, + -0.766357,0.642415,0,-3.712832,1.794492,0, + 0.555353,0.507651,0.65869,-3.698925,1.787941,0.06664, + 0.823156,0.134626,0.551624,-3.469715,1.961504,0.071141, + -0.766357,0.642415,0,-3.712832,1.794492,0, + 0.823156,0.134626,0.551624,-3.469715,1.961504,0.071141, + -0.410619,0.911807,0,-3.47843,1.975409,0, + -0.410619,0.911807,0,-3.47843,1.975409,0, + 0.823156,0.134626,0.551624,-3.469715,1.961504,0.071141, + 0.707626,-0.125604,0.695334,-3.238225,2.005405,0.075645, + -0.410619,0.911807,0,-3.47843,1.975409,0, + 0.707626,-0.125604,0.695334,-3.238225,2.005405,0.075645, + -0.433128,-0.901332,0,-3.242148,2.021387,0, + 0.238843,0.101951,0.965691,-3.84599,-0.18882,0.019164, + 0.546619,0.025488,0.836993,-3.805688,-0.190106,0.051472, + 0.836108,-0.069219,0.54418,-3.786822,0.153783,0.084233, + 0.238843,0.101951,0.965691,-3.84599,-0.18882,0.019164, + 0.836108,-0.069219,0.54418,-3.786822,0.153783,0.084233, + 0.604306,0.20436,0.770098,-3.81743,0.150343,0.048629, + 0.604306,0.20436,0.770098,-3.81743,0.150343,0.048629, + 0.836108,-0.069219,0.54418,-3.786822,0.153783,0.084233, + 0.412833,-0.156454,0.897269,-3.811194,0.501935,0.092033, + 0.604306,0.20436,0.770098,-3.81743,0.150343,0.048629, + 0.412833,-0.156454,0.897269,-3.811194,0.501935,0.092033, + 0.02054,-0.128179,0.991538,-3.84447,0.498176,0.053132, + 0.02054,-0.128179,0.991538,-3.84447,0.498176,0.053132, + 0.412833,-0.156454,0.897269,-3.811194,0.501935,0.092033, + 0.108828,-0.182644,0.977137,-3.851206,1.007586,0.099831, + 0.02054,-0.128179,0.991538,-3.84447,0.498176,0.053132, + 0.108828,-0.182644,0.977137,-3.851206,1.007586,0.099831, + 0.193291,-0.0748,0.978286,-3.88734,1.003866,0.057635, + 0.193291,-0.0748,0.978286,-3.88734,1.003866,0.057635, + 0.108828,-0.182644,0.977137,-3.851206,1.007586,0.099831, + 0.746476,-0.187741,0.638379,-3.821694,1.477989,0.107631, + 0.193291,-0.0748,0.978286,-3.88734,1.003866,0.057635, + 0.746476,-0.187741,0.638379,-3.821694,1.477989,0.107631, + 0.133637,0.26732,0.954296,-3.86082,1.479723,0.062137, + 0.133637,0.26732,0.954296,-3.86082,1.479723,0.062137, + 0.746476,-0.187741,0.638379,-3.821694,1.477989,0.107631, + 0.883859,-0.211187,0.417364,-3.660928,1.770041,0.115431, + 0.133637,0.26732,0.954296,-3.86082,1.479723,0.062137, + 0.883859,-0.211187,0.417364,-3.660928,1.770041,0.115431, + 0.555353,0.507651,0.65869,-3.698925,1.787941,0.06664, + 0.555353,0.507651,0.65869,-3.698925,1.787941,0.06664, + 0.883859,-0.211187,0.417364,-3.660928,1.770041,0.115431, + 0.544736,0.449333,0.708069,-3.445903,1.923509,0.123229, + 0.555353,0.507651,0.65869,-3.698925,1.787941,0.06664, + 0.544736,0.449333,0.708069,-3.445903,1.923509,0.123229, + 0.823156,0.134626,0.551624,-3.469715,1.961504,0.071141, + 0.823156,0.134626,0.551624,-3.469715,1.961504,0.071141, + 0.544736,0.449333,0.708069,-3.445903,1.923509,0.123229, + 0.722,0.398916,0.565317,-3.227504,1.961738,0.131029, + 0.823156,0.134626,0.551624,-3.469715,1.961504,0.071141, + 0.722,0.398916,0.565317,-3.227504,1.961738,0.131029, + 0.707626,-0.125604,0.695334,-3.238225,2.005405,0.075645, + 0.546619,0.025488,0.836993,-3.805688,-0.190106,0.051472, + 0.711192,0.127662,0.69131,-3.75063,-0.191863,0.063305, + 0.269343,0.329305,0.904993,-3.745007,0.158482,0.097274, + 0.546619,0.025488,0.836993,-3.805688,-0.190106,0.051472, + 0.269343,0.329305,0.904993,-3.745007,0.158482,0.097274, + 0.836108,-0.069219,0.54418,-3.786822,0.153783,0.084233, + 0.836108,-0.069219,0.54418,-3.786822,0.153783,0.084233, + 0.269343,0.329305,0.904993,-3.745007,0.158482,0.097274, + 0.397989,0.4494,0.799778,-3.765736,0.50707,0.106281, + 0.836108,-0.069219,0.54418,-3.786822,0.153783,0.084233, + 0.397989,0.4494,0.799778,-3.765736,0.50707,0.106281, + 0.412833,-0.156454,0.897269,-3.811194,0.501935,0.092033, + 0.412833,-0.156454,0.897269,-3.811194,0.501935,0.092033, + 0.397989,0.4494,0.799778,-3.765736,0.50707,0.106281, + 0.264978,0.116702,0.957166,-3.80184,1.012668,0.115288, + 0.412833,-0.156454,0.897269,-3.811194,0.501935,0.092033, + 0.264978,0.116702,0.957166,-3.80184,1.012668,0.115288, + 0.108828,-0.182644,0.977137,-3.851206,1.007586,0.099831, + 0.108828,-0.182644,0.977137,-3.851206,1.007586,0.099831, + 0.264978,0.116702,0.957166,-3.80184,1.012668,0.115288, + 0.312982,-0.015529,0.949632,-3.768245,1.475619,0.124295, + 0.108828,-0.182644,0.977137,-3.851206,1.007586,0.099831, + 0.312982,-0.015529,0.949632,-3.768245,1.475619,0.124295, + 0.746476,-0.187741,0.638379,-3.821694,1.477989,0.107631, + 0.746476,-0.187741,0.638379,-3.821694,1.477989,0.107631, + 0.312982,-0.015529,0.949632,-3.768245,1.475619,0.124295, + 0.470021,0.18298,0.863481,-3.609021,1.745588,0.133304, + 0.746476,-0.187741,0.638379,-3.821694,1.477989,0.107631, + 0.470021,0.18298,0.863481,-3.609021,1.745588,0.133304, + 0.883859,-0.211187,0.417364,-3.660928,1.770041,0.115431, + 0.883859,-0.211187,0.417364,-3.660928,1.770041,0.115431, + 0.470021,0.18298,0.863481,-3.609021,1.745588,0.133304, + 0.431712,0.22912,0.872427,-3.413372,1.871604,0.142309, + 0.883859,-0.211187,0.417364,-3.660928,1.770041,0.115431, + 0.431712,0.22912,0.872427,-3.413372,1.871604,0.142309, + 0.544736,0.449333,0.708069,-3.445903,1.923509,0.123229, + 0.544736,0.449333,0.708069,-3.445903,1.923509,0.123229, + 0.431712,0.22912,0.872427,-3.413372,1.871604,0.142309, + 0.722,0.398916,0.565317,-3.227504,1.961738,0.131029, + 0.711192,0.127662,0.69131,-3.75063,-0.191863,0.063305, + 0.560378,0.257624,0.787151,-3.695565,-0.19362,0.051497, + 0.661824,0.260114,0.703086,-3.703185,0.163182,0.084262, + 0.711192,0.127662,0.69131,-3.75063,-0.191863,0.063305, + 0.661824,0.260114,0.703086,-3.703185,0.163182,0.084262, + 0.269343,0.329305,0.904993,-3.745007,0.158482,0.097274, + 0.269343,0.329305,0.904993,-3.745007,0.158482,0.097274, + 0.661824,0.260114,0.703086,-3.703185,0.163182,0.084262, + 0.675892,0.137563,0.724049,-3.720269,0.512205,0.092064, + 0.269343,0.329305,0.904993,-3.745007,0.158482,0.097274, + 0.675892,0.137563,0.724049,-3.720269,0.512205,0.092064, + 0.397989,0.4494,0.799778,-3.765736,0.50707,0.106281, + 0.397989,0.4494,0.799778,-3.765736,0.50707,0.106281, + 0.675892,0.137563,0.724049,-3.720269,0.512205,0.092064, + 0.708269,-0.122725,0.695193,-3.752468,1.017751,0.099865, + 0.397989,0.4494,0.799778,-3.765736,0.50707,0.106281, + 0.708269,-0.122725,0.695193,-3.752468,1.017751,0.099865, + 0.264978,0.116702,0.957166,-3.80184,1.012668,0.115288, + 0.264978,0.116702,0.957166,-3.80184,1.012668,0.115288, + 0.708269,-0.122725,0.695193,-3.752468,1.017751,0.099865, + 0.540204,-0.272055,0.796345,-3.714787,1.473248,0.107668, + 0.264978,0.116702,0.957166,-3.80184,1.012668,0.115288, + 0.540204,-0.272055,0.796345,-3.714787,1.473248,0.107668, + 0.312982,-0.015529,0.949632,-3.768245,1.475619,0.124295, + 0.312982,-0.015529,0.949632,-3.768245,1.475619,0.124295, + 0.540204,-0.272055,0.796345,-3.714787,1.473248,0.107668, + 0.723289,-0.195474,0.662302,-3.557104,1.72113,0.11547, + 0.312982,-0.015529,0.949632,-3.768245,1.475619,0.124295, + 0.723289,-0.195474,0.662302,-3.557104,1.72113,0.11547, + 0.470021,0.18298,0.863481,-3.609021,1.745588,0.133304, + 0.470021,0.18298,0.863481,-3.609021,1.745588,0.133304, + 0.723289,-0.195474,0.662302,-3.557104,1.72113,0.11547, + 0.588787,-0.248294,0.769207,-3.380836,1.819691,0.123273, + 0.470021,0.18298,0.863481,-3.609021,1.745588,0.133304, + 0.588787,-0.248294,0.769207,-3.380836,1.819691,0.123273, + 0.431712,0.22912,0.872427,-3.413372,1.871604,0.142309, + 0.560378,0.257624,0.787151,-3.695565,-0.19362,0.051497, + 0.274422,-0.24433,0.930051,-3.65524,-0.194907,0.019209, + 0.017555,-0.142899,0.989582,-3.672559,0.166625,0.048678, + 0.560378,0.257624,0.787151,-3.695565,-0.19362,0.051497, + 0.017555,-0.142899,0.989582,-3.672559,0.166625,0.048678, + 0.661824,0.260114,0.703086,-3.703185,0.163182,0.084262, + 0.661824,0.260114,0.703086,-3.703185,0.163182,0.084262, + 0.017555,-0.142899,0.989582,-3.672559,0.166625,0.048678, + 0.961046,0.110911,0.253159,-3.686972,0.515966,0.053185, + 0.661824,0.260114,0.703086,-3.703185,0.163182,0.084262, + 0.961046,0.110911,0.253159,-3.686972,0.515966,0.053185, + 0.675892,0.137563,0.724049,-3.720269,0.512205,0.092064, + 0.675892,0.137563,0.724049,-3.720269,0.512205,0.092064, + 0.961046,0.110911,0.253159,-3.686972,0.515966,0.053185, + 0.910294,-0.144636,0.387873,-3.716312,1.021474,0.057693, + 0.675892,0.137563,0.724049,-3.720269,0.512205,0.092064, + 0.910294,-0.144636,0.387873,-3.716312,1.021474,0.057693, + 0.708269,-0.122725,0.695193,-3.752468,1.017751,0.099865, + 0.708269,-0.122725,0.695193,-3.752468,1.017751,0.099865, + 0.910294,-0.144636,0.387873,-3.716312,1.021474,0.057693, + 0.813709,-0.132052,0.566074,-3.675638,1.471512,0.062201, + 0.708269,-0.122725,0.695193,-3.752468,1.017751,0.099865, + 0.813709,-0.132052,0.566074,-3.675638,1.471512,0.062201, + 0.540204,-0.272055,0.796345,-3.714787,1.473248,0.107668, + 0.540204,-0.272055,0.796345,-3.714787,1.473248,0.107668, + 0.813709,-0.132052,0.566074,-3.675638,1.471512,0.062201, + 0.577502,-0.140087,0.804281,-3.519086,1.70322,0.066709, + 0.540204,-0.272055,0.796345,-3.714787,1.473248,0.107668, + 0.577502,-0.140087,0.804281,-3.519086,1.70322,0.066709, + 0.723289,-0.195474,0.662302,-3.557104,1.72113,0.11547, + 0.723289,-0.195474,0.662302,-3.557104,1.72113,0.11547, + 0.577502,-0.140087,0.804281,-3.519086,1.70322,0.066709, + 0.490646,-0.178294,0.852923,-3.357009,1.781675,0.071216, + 0.723289,-0.195474,0.662302,-3.557104,1.72113,0.11547, + 0.490646,-0.178294,0.852923,-3.357009,1.781675,0.071216, + 0.588787,-0.248294,0.769207,-3.380836,1.819691,0.123273, + 0.274422,-0.24433,0.930051,-3.65524,-0.194907,0.019209, + 0.267717,-0.172975,0.947844,-3.640457,-0.195379,-0.024909, + -0.028502,-0.108631,0.993674,-3.661331,0.167886,0.000058, + 0.274422,-0.24433,0.930051,-3.65524,-0.194907,0.019209, + -0.028502,-0.108631,0.993674,-3.661331,0.167886,0.000058, + 0.017555,-0.142899,0.989582,-3.672559,0.166625,0.048678, + 0.017555,-0.142899,0.989582,-3.672559,0.166625,0.048678, + -0.028502,-0.108631,0.993674,-3.661331,0.167886,0.000058, + 0.998889,0.047122,-0.000074,-3.674766,0.517345,-0.000063, + 0.017555,-0.142899,0.989582,-3.672559,0.166625,0.048678, + 0.998889,0.047122,-0.000074,-3.674766,0.517345,-0.000063, + 0.961046,0.110911,0.253159,-3.686972,0.515966,0.053185, + 0.961046,0.110911,0.253159,-3.686972,0.515966,0.053185, + 0.998889,0.047122,-0.000074,-3.674766,0.517345,-0.000063, + 0.999831,-0.018401,-0.000261,-3.703058,1.022838,-0.000069, + 0.961046,0.110911,0.253159,-3.686972,0.515966,0.053185, + 0.999831,-0.018401,-0.000261,-3.703058,1.022838,-0.000069, + 0.910294,-0.144636,0.387873,-3.716312,1.021474,0.057693, + 0.910294,-0.144636,0.387873,-3.716312,1.021474,0.057693, + 0.999831,-0.018401,-0.000261,-3.703058,1.022838,-0.000069, + 0.941293,-0.337592,-0.000186,-3.661286,1.470876,-0.000074, + 0.910294,-0.144636,0.387873,-3.716312,1.021474,0.057693, + 0.941293,-0.337592,-0.000186,-3.661286,1.470876,-0.000074, + 0.813709,-0.132052,0.566074,-3.675638,1.471512,0.062201, + 0.813709,-0.132052,0.566074,-3.675638,1.471512,0.062201, + 0.941293,-0.337592,-0.000186,-3.661286,1.470876,-0.000074, + -0.153783,-0.988105,0,-3.507689,1.700214,0, + 0.813709,-0.132052,0.566074,-3.675638,1.471512,0.062201, + -0.153783,-0.988105,0,-3.507689,1.700214,0, + 0.577502,-0.140087,0.804281,-3.519086,1.70322,0.066709, + 0.577502,-0.140087,0.804281,-3.519086,1.70322,0.066709, + -0.153783,-0.988105,0,-3.507689,1.700214,0, + 0.411442,-0.911436,-0.000099,-3.348274,1.767738,-0.000085, + 0.577502,-0.140087,0.804281,-3.519086,1.70322,0.066709, + 0.411442,-0.911436,-0.000099,-3.348274,1.767738,-0.000085, + 0.490646,-0.178294,0.852923,-3.357009,1.781675,0.071216, + 0.267717,-0.172975,0.947844,-3.640457,-0.195379,-0.024909, + -0.064166,-0.189382,0.979805,-3.655175,-0.194909,-0.069044, + 0.781868,0.537363,0.316106,-3.67251,0.16663,-0.048579, + 0.267717,-0.172975,0.947844,-3.640457,-0.195379,-0.024909, + 0.781868,0.537363,0.316106,-3.67251,0.16663,-0.048579, + -0.028502,-0.108631,0.993674,-3.661331,0.167886,0.000058, + -0.028502,-0.108631,0.993674,-3.661331,0.167886,0.000058, + 0.781868,0.537363,0.316106,-3.67251,0.16663,-0.048579, + 0.891325,0.039302,-0.451658,-3.686972,0.515966,-0.053185, + -0.028502,-0.108631,0.993674,-3.661331,0.167886,0.000058, + 0.891325,0.039302,-0.451658,-3.686972,0.515966,-0.053185, + 0.998889,0.047122,-0.000074,-3.674766,0.517345,-0.000063, + -0.064166,-0.189382,0.979805,-3.655175,-0.194909,-0.069044, + 0.89264,0.349909,0.284178,-3.695452,-0.193624,-0.101369, + 0.618085,0.65091,0.440781,-3.703099,0.163192,-0.084205, + -0.064166,-0.189382,0.979805,-3.655175,-0.194909,-0.069044, + 0.618085,0.65091,0.440781,-3.703099,0.163192,-0.084205, + 0.781868,0.537363,0.316106,-3.67251,0.16663,-0.048579, + 0.781868,0.537363,0.316106,-3.67251,0.16663,-0.048579, + 0.618085,0.65091,0.440781,-3.703099,0.163192,-0.084205, + 0.549192,0.015162,-0.835559,-3.720269,0.512205,-0.092064, + 0.781868,0.537363,0.316106,-3.67251,0.16663,-0.048579, + 0.549192,0.015162,-0.835559,-3.720269,0.512205,-0.092064, + 0.891325,0.039302,-0.451658,-3.686972,0.515966,-0.053185, + 0.89264,0.349909,0.284178,-3.695452,-0.193624,-0.101369, + 0.3526,0.621479,0.699598,-3.7505,-0.191867,-0.11323, + 0.171039,0.554898,0.814146,-3.744907,0.158493,-0.097274, + 0.89264,0.349909,0.284178,-3.695452,-0.193624,-0.101369, + 0.171039,0.554898,0.814146,-3.744907,0.158493,-0.097274, + 0.618085,0.65091,0.440781,-3.703099,0.163192,-0.084205, + 0.618085,0.65091,0.440781,-3.703099,0.163192,-0.084205, + 0.171039,0.554898,0.814146,-3.744907,0.158493,-0.097274, + 0.002291,-0.021629,-0.999763,-3.765736,0.50707,-0.106281, + 0.618085,0.65091,0.440781,-3.703099,0.163192,-0.084205, + 0.002291,-0.021629,-0.999763,-3.765736,0.50707,-0.106281, + 0.549192,0.015162,-0.835559,-3.720269,0.512205,-0.092064, + 0.3526,0.621479,0.699598,-3.7505,-0.191867,-0.11323, + -0.281998,-0.030938,0.958916,-3.805575,-0.190109,-0.101447, + -0.120429,-0.209965,0.970264,-3.786736,0.153792,-0.084291, + 0.3526,0.621479,0.699598,-3.7505,-0.191867,-0.11323, + -0.120429,-0.209965,0.970264,-3.786736,0.153792,-0.084291, + 0.171039,0.554898,0.814146,-3.744907,0.158493,-0.097274, + 0.171039,0.554898,0.814146,-3.744907,0.158493,-0.097274, + -0.120429,-0.209965,0.970264,-3.786736,0.153792,-0.084291, + -0.545298,-0.056465,-0.836338,-3.811194,0.501935,-0.092033, + 0.171039,0.554898,0.814146,-3.744907,0.158493,-0.097274, + -0.545298,-0.056465,-0.836338,-3.811194,0.501935,-0.092033, + 0.002291,-0.021629,-0.999763,-3.765736,0.50707,-0.106281, + -0.281998,-0.030938,0.958916,-3.805575,-0.190109,-0.101447, + 0.077536,0.770695,0.632469,-3.845923,-0.188822,-0.06918, + -0.222902,0.035918,0.974179,-3.817381,0.150348,-0.048728, + -0.281998,-0.030938,0.958916,-3.805575,-0.190109,-0.101447, + -0.222902,0.035918,0.974179,-3.817381,0.150348,-0.048728, + -0.120429,-0.209965,0.970264,-3.786736,0.153792,-0.084291, + -0.120429,-0.209965,0.970264,-3.786736,0.153792,-0.084291, + -0.222902,0.035918,0.974179,-3.817381,0.150348,-0.048728, + -0.888551,-0.077176,-0.452239,-3.84447,0.498176,-0.053132, + -0.120429,-0.209965,0.970264,-3.786736,0.153792,-0.084291, + -0.888551,-0.077176,-0.452239,-3.84447,0.498176,-0.053132, + -0.545298,-0.056465,-0.836338,-3.811194,0.501935,-0.092033, + 0.077536,0.770695,0.632469,-3.845923,-0.188822,-0.06918, + 0.166377,-0.157108,0.973466,-3.86074,-0.188349,-0.024962, + 0.054863,-0.132814,0.989621,-3.828633,0.149083,0, + 0.077536,0.770695,0.632469,-3.845923,-0.188822,-0.06918, + 0.054863,-0.132814,0.989621,-3.828633,0.149083,0, + -0.222902,0.035918,0.974179,-3.817381,0.150348,-0.048728, + -0.222902,0.035918,0.974179,-3.817381,0.150348,-0.048728, + 0.054863,-0.132814,0.989621,-3.828633,0.149083,0, + -0.996511,-0.083465,-0.000062,-3.856649,0.496801,0, + -0.222902,0.035918,0.974179,-3.817381,0.150348,-0.048728, + -0.996511,-0.083465,-0.000062,-3.856649,0.496801,0, + -0.888551,-0.077176,-0.452239,-3.84447,0.498176,-0.053132, + 0.431712,0.22912,0.872427,-3.413372,1.871604,0.142309, + 0.137206,-0.207537,0.968557,-3.077669,1.871112,0.217368, + 0.722,0.398916,0.565317,-3.227504,1.961738,0.131029, + 0.137764,-0.289893,0.947092,-3.053102,1.96881,0.051104, + 0.012502,-0.999922,0,-3.037562,2.001526,0, + -0.433128,-0.901332,0,-3.242148,2.021387,0, + 0.137764,-0.289893,0.947092,-3.053102,1.96881,0.051104, + -0.433128,-0.901332,0,-3.242148,2.021387,0, + 0.707626,-0.125604,0.695334,-3.238225,2.005405,0.075645, + 0.137764,-0.289893,0.947092,-3.053102,1.96881,0.051104, + 0.707626,-0.125604,0.695334,-3.238225,2.005405,0.075645, + 0.722,0.398916,0.565317,-3.227504,1.961738,0.131029, + 0.137206,-0.207537,0.968557,-3.077669,1.871112,0.217368, + 0.137764,-0.289893,0.947092,-3.053102,1.96881,0.051104, + 0.722,0.398916,0.565317,-3.227504,1.961738,0.131029, + 0.431712,0.22912,0.872427,-3.413372,1.871604,0.142309, + -0.468954,-0.586277,0.660577,-3.35851,1.810253,0.380095, + 0.137206,-0.207537,0.968557,-3.077669,1.871112,0.217368, + -0.468954,-0.586277,0.660577,-3.35851,1.810253,0.380095, + 0.094371,-0.230057,0.968591,-3.07531,1.846,0.363149, + 0.137206,-0.207537,0.968557,-3.077669,1.871112,0.217368, + 0.272203,0.043076,0.961275,4.861618,1.854067,0.618095, + 0.302716,0.058971,0.951255,4.852578,1.889721,0.605031, + 0.347794,0.132396,0.928176,4.824747,1.946835,0.626358, + 0.272203,0.043076,0.961275,4.861618,1.854067,0.618095, + 0.347794,0.132396,0.928176,4.824747,1.946835,0.626358, + 0.337014,-0.030018,0.941021,4.760921,1.881357,0.61312, + 0.361081,-0.056526,0.93082,4.935561,2.016016,0.5857, + 0.196849,0.14562,0.969559,4.93588,2.051665,0.572853, + 0.195545,0.103956,0.975169,4.842883,2.021333,0.638025, + 0.361081,-0.056526,0.93082,4.935561,2.016016,0.5857, + 0.195545,0.103956,0.975169,4.842883,2.021333,0.638025, + 0.36359,0.089346,0.927264,4.861611,2.001639,0.621913, + 0.282492,0.026081,0.958915,4.973133,1.992779,0.533466, + 0.380651,0.443224,0.811577,5.001903,1.914398,0.486724, + 0.210495,0.185422,0.959849,4.991746,2.009819,0.523206, + 0.302716,0.058971,0.951255,4.852578,1.889721,0.605031, + 0.272203,0.043076,0.961275,4.861618,1.854067,0.618095, + -0.03359,0.173471,0.984266,4.944706,1.840663,0.575374, + 0.302716,0.058971,0.951255,4.852578,1.889721,0.605031, + -0.03359,0.173471,0.984266,4.944706,1.840663,0.575374, + 0.332757,0.286207,0.898531,4.926194,1.859813,0.582137, + -0.03359,0.173471,0.984266,4.944706,1.840663,0.575374, + 0.289202,0.572304,0.767353,4.991709,1.844295,0.520761, + 0.362705,0.428702,0.827442,4.982364,1.8733,0.53619, + -0.03359,0.173471,0.984266,4.944706,1.840663,0.575374, + 0.362705,0.428702,0.827442,4.982364,1.8733,0.53619, + 0.332757,0.286207,0.898531,4.926194,1.859813,0.582137, + 0.168187,0.300291,0.938903,4.852582,1.816115,0.603105, + 0.243508,0.533327,0.810103,4.908019,1.796041,0.587882, + -0.03359,0.173471,0.984266,4.944706,1.840663,0.575374, + 0.168187,0.300291,0.938903,4.852582,1.816115,0.603105, + -0.03359,0.173471,0.984266,4.944706,1.840663,0.575374, + 0.272203,0.043076,0.961275,4.861618,1.854067,0.618095, + 0.243508,0.533327,0.810103,4.908019,1.796041,0.587882, + 0.112152,0.130705,0.985057,4.963546,1.783161,0.553515, + 0.289202,0.572304,0.767353,4.991709,1.844295,0.520761, + 0.243508,0.533327,0.810103,4.908019,1.796041,0.587882, + 0.289202,0.572304,0.767353,4.991709,1.844295,0.520761, + -0.03359,0.173471,0.984266,4.944706,1.840663,0.575374, + 0.112152,0.130705,0.985057,4.963546,1.783161,0.553515, + 0.069483,0.206285,0.976022,4.983034,1.806343,0.505779, + 0.289202,0.572304,0.767353,4.991709,1.844295,0.520761, + 0.069483,0.206285,0.976022,4.983034,1.806343,0.505779, + 0.154687,0.171026,0.973048,5.01143,1.875569,0.463205, + 0.289202,0.572304,0.767353,4.991709,1.844295,0.520761, + 0.196849,0.14562,0.969559,4.93588,2.051665,0.572853, + 0.210495,0.185422,0.959849,4.991746,2.009819,0.523206, + 0.235746,0.648569,0.723728,4.964945,2.053575,0.499903, + 0.196849,0.14562,0.969559,4.93588,2.051665,0.572853, + 0.235746,0.648569,0.723728,4.964945,2.053575,0.499903, + 0.054287,0.055115,0.997003,4.918466,2.084725,0.532713, + 0.210495,0.185422,0.959849,4.991746,2.009819,0.523206, + 0.101497,0.61661,0.780699,5.020077,1.97817,0.480978, + 0.235746,0.648569,0.723728,4.964945,2.053575,0.499903, + 0.154687,0.171026,0.973048,5.01143,1.875569,0.463205, + 0.101497,0.61661,0.780699,5.020077,1.97817,0.480978, + 0.210495,0.185422,0.959849,4.991746,2.009819,0.523206, + 0.196849,0.14562,0.969559,4.93588,2.051665,0.572853, + 0.012421,0.392537,0.919652,4.881574,2.094571,0.539949, + 0.043397,0.435463,0.89916,4.825996,2.089176,0.576083, + 0.196849,0.14562,0.969559,4.93588,2.051665,0.572853, + 0.043397,0.435463,0.89916,4.825996,2.089176,0.576083, + 0.195545,0.103956,0.975169,4.842883,2.021333,0.638025, + 0.067357,0.280764,0.95741,4.788476,2.028047,0.608619, + 0.337014,-0.030018,0.941021,4.760921,1.881357,0.61312, + 0.195545,0.103956,0.975169,4.842883,2.021333,0.638025, + 0.067357,0.280764,0.95741,4.788476,2.028047,0.608619, + 0.195545,0.103956,0.975169,4.842883,2.021333,0.638025, + 0.043397,0.435463,0.89916,4.825996,2.089176,0.576083, + 0.067357,0.280764,0.95741,4.788476,2.028047,0.608619, + 0.043397,0.435463,0.89916,4.825996,2.089176,0.576083, + 0.184871,0.227138,0.956154,4.798297,2.118191,0.591085, + 0.067357,0.280764,0.95741,4.788476,2.028047,0.608619, + 0.184871,0.227138,0.956154,4.798297,2.118191,0.591085, + -0.026366,0.234118,0.971851,4.751519,2.039658,0.634134, + 0.043397,0.435463,0.89916,4.825996,2.089176,0.576083, + 0.012421,0.392537,0.919652,4.881574,2.094571,0.539949, + -0.034875,0.308036,0.950735,4.872539,2.159259,0.542891, + 0.043397,0.435463,0.89916,4.825996,2.089176,0.576083, + -0.034875,0.308036,0.950735,4.872539,2.159259,0.542891, + 0.184871,0.227138,0.956154,4.798297,2.118191,0.591085, + 0.012421,0.392537,0.919652,4.881574,2.094571,0.539949, + 0.054287,0.055115,0.997003,4.918466,2.084725,0.532713, + -0.148853,0.101172,0.98367,4.927885,2.15656,0.516579, + 0.012421,0.392537,0.919652,4.881574,2.094571,0.539949, + -0.148853,0.101172,0.98367,4.927885,2.15656,0.516579, + -0.034875,0.308036,0.950735,4.872539,2.159259,0.542891, + 0.054287,0.055115,0.997003,4.918466,2.084725,0.532713, + 0.235746,0.648569,0.723728,4.964945,2.053575,0.499903, + 0.504806,0.844077,0.180846,5.00244,2.105746,0.468233, + 0.054287,0.055115,0.997003,4.918466,2.084725,0.532713, + 0.504806,0.844077,0.180846,5.00244,2.105746,0.468233, + -0.148853,0.101172,0.98367,4.927885,2.15656,0.516579, + 0.235746,0.648569,0.723728,4.964945,2.053575,0.499903, + 0.101497,0.61661,0.780699,5.020077,1.97817,0.480978, + 0.615065,0.769234,0.173133,5.057495,2.002751,0.451974, + 0.235746,0.648569,0.723728,4.964945,2.053575,0.499903, + 0.615065,0.769234,0.173133,5.057495,2.002751,0.451974, + 0.504806,0.844077,0.180846,5.00244,2.105746,0.468233, + 0.101497,0.61661,0.780699,5.020077,1.97817,0.480978, + 0.154687,0.171026,0.973048,5.01143,1.875569,0.463205, + 0.550963,0.62763,0.550018,5.075994,1.900999,0.443793, + 0.101497,0.61661,0.780699,5.020077,1.97817,0.480978, + 0.550963,0.62763,0.550018,5.075994,1.900999,0.443793, + 0.615065,0.769234,0.173133,5.057495,2.002751,0.451974, + 0.154687,0.171026,0.973048,5.01143,1.875569,0.463205, + 0.477291,0.716177,0.509199,5.030289,1.827419,0.440803, + 0.550963,0.62763,0.550018,5.075994,1.900999,0.443793, + 0.069483,0.206285,0.976022,4.983034,1.806343,0.505779, + 0.888167,0.420088,0.186241,4.991904,1.760829,0.510386, + 0.477291,0.716177,0.509199,5.030289,1.827419,0.440803, + 0.069483,0.206285,0.976022,4.983034,1.806343,0.505779, + 0.477291,0.716177,0.509199,5.030289,1.827419,0.440803, + 0.154687,0.171026,0.973048,5.01143,1.875569,0.463205, + 0.112152,0.130705,0.985057,4.963546,1.783161,0.553515, + 0.749779,0.312648,0.583167,4.936066,1.737668,0.557276, + 0.888167,0.420088,0.186241,4.991904,1.760829,0.510386, + 0.112152,0.130705,0.985057,4.963546,1.783161,0.553515, + 0.888167,0.420088,0.186241,4.991904,1.760829,0.510386, + 0.069483,0.206285,0.976022,4.983034,1.806343,0.505779, + 0.358075,0.480709,0.800438,4.871155,1.741238,0.592326, + 0.749779,0.312648,0.583167,4.936066,1.737668,0.557276, + 0.112152,0.130705,0.985057,4.963546,1.783161,0.553515, + 0.358075,0.480709,0.800438,4.871155,1.741238,0.592326, + 0.112152,0.130705,0.985057,4.963546,1.783161,0.553515, + 0.243508,0.533327,0.810103,4.908019,1.796041,0.587882, + 0.524848,0.480955,0.702294,4.816181,1.79786,0.604026, + 0.358075,0.480709,0.800438,4.871155,1.741238,0.592326, + 0.243508,0.533327,0.810103,4.908019,1.796041,0.587882, + 0.524848,0.480955,0.702294,4.816181,1.79786,0.604026, + 0.243508,0.533327,0.810103,4.908019,1.796041,0.587882, + 0.168187,0.300291,0.938903,4.852582,1.816115,0.603105, + 0.524848,0.480955,0.702294,4.816181,1.79786,0.604026, + 0.168187,0.300291,0.938903,4.852582,1.816115,0.603105, + 0.337014,-0.030018,0.941021,4.760921,1.881357,0.61312, + 0.988203,-0.047217,0.145687,5.085813,1.888503,0.408327, + 0.72603,0.248277,0.641279,5.095375,1.961238,0.401516, + 0.550963,0.62763,0.550018,5.075994,1.900999,0.443793, + 0.477291,0.716177,0.509199,5.030289,1.827419,0.440803, + 0.936242,-0.313777,-0.158096,5.058179,1.788186,0.417387, + 0.988203,-0.047217,0.145687,5.085813,1.888503,0.408327, + 0.477291,0.716177,0.509199,5.030289,1.827419,0.440803, + 0.988203,-0.047217,0.145687,5.085813,1.888503,0.408327, + 0.550963,0.62763,0.550018,5.075994,1.900999,0.443793, + 0.888167,0.420088,0.186241,4.991904,1.760829,0.510386, + 0.831186,-0.511045,-0.219005,5.019836,1.739907,0.485562, + 0.936242,-0.313777,-0.158096,5.058179,1.788186,0.417387, + 0.888167,0.420088,0.186241,4.991904,1.760829,0.510386, + 0.936242,-0.313777,-0.158096,5.058179,1.788186,0.417387, + 0.477291,0.716177,0.509199,5.030289,1.827419,0.440803, + 0.749779,0.312648,0.583167,4.936066,1.737668,0.557276, + 0.797293,-0.558933,-0.227857,4.917973,1.68148,0.544201, + 0.831186,-0.511045,-0.219005,5.019836,1.739907,0.485562, + 0.749779,0.312648,0.583167,4.936066,1.737668,0.557276, + 0.831186,-0.511045,-0.219005,5.019836,1.739907,0.485562, + 0.888167,0.420088,0.186241,4.991904,1.760829,0.510386, + 0.707669,-0.687185,0.164261,4.862636,1.684144,0.570155, + 0.797293,-0.558933,-0.227857,4.917973,1.68148,0.544201, + 0.749779,0.312648,0.583167,4.936066,1.737668,0.557276, + 0.707669,-0.687185,0.164261,4.862636,1.684144,0.570155, + 0.749779,0.312648,0.583167,4.936066,1.737668,0.557276, + 0.358075,0.480709,0.800438,4.871155,1.741238,0.592326, + 0.744254,-0.65416,0.134758,4.752337,1.723388,0.591296, + 0.707669,-0.687185,0.164261,4.862636,1.684144,0.570155, + 0.358075,0.480709,0.800438,4.871155,1.741238,0.592326, + 0.744254,-0.65416,0.134758,4.752337,1.723388,0.591296, + 0.358075,0.480709,0.800438,4.871155,1.741238,0.592326, + 0.524848,0.480955,0.702294,4.816181,1.79786,0.604026, + 0.884603,-0.366979,0.287755,4.697607,1.768061,0.576663, + 0.744254,-0.65416,0.134758,4.752337,1.723388,0.591296, + 0.524848,0.480955,0.702294,4.816181,1.79786,0.604026, + 0.884603,-0.366979,0.287755,4.697607,1.768061,0.576663, + 0.524848,0.480955,0.702294,4.816181,1.79786,0.604026, + 0.337014,-0.030018,0.941021,4.760921,1.881357,0.61312, + 0.615065,0.769234,0.173133,5.057495,2.002751,0.451974, + 0.670109,-0.356989,0.650778,5.067202,2.027704,0.422291, + 0.468872,-0.092982,0.878359,5.030641,2.102197,0.432329, + 0.615065,0.769234,0.173133,5.057495,2.002751,0.451974, + 0.468872,-0.092982,0.878359,5.030641,2.102197,0.432329, + 0.504806,0.844077,0.180846,5.00244,2.105746,0.468233, + -0.148853,0.101172,0.98367,4.927885,2.15656,0.516579, + 0.504806,0.844077,0.180846,5.00244,2.105746,0.468233, + 0.468872,-0.092982,0.878359,5.030641,2.102197,0.432329, + -0.148853,0.101172,0.98367,4.927885,2.15656,0.516579, + 0.468872,-0.092982,0.878359,5.030641,2.102197,0.432329, + 0.507131,-0.710633,0.487667,4.93795,2.181155,0.486939, + -0.034875,0.308036,0.950735,4.872539,2.159259,0.542891, + -0.148853,0.101172,0.98367,4.927885,2.15656,0.516579, + 0.507131,-0.710633,0.487667,4.93795,2.181155,0.486939, + -0.034875,0.308036,0.950735,4.872539,2.159259,0.542891, + 0.507131,-0.710633,0.487667,4.93795,2.181155,0.486939, + 0.292794,-0.691168,0.660725,4.881855,2.194544,0.530288, + 0.384025,-0.256534,0.88697,4.807794,2.143653,0.570393, + 0.184871,0.227138,0.956154,4.798297,2.118191,0.591085, + -0.034875,0.308036,0.950735,4.872539,2.159259,0.542891, + 0.384025,-0.256534,0.88697,4.807794,2.143653,0.570393, + -0.034875,0.308036,0.950735,4.872539,2.159259,0.542891, + 0.292794,-0.691168,0.660725,4.881855,2.194544,0.530288, + 0.689769,-0.265624,0.673544,4.728963,2.036146,0.614307, + -0.026366,0.234118,0.971851,4.751519,2.039658,0.634134, + 0.184871,0.227138,0.956154,4.798297,2.118191,0.591085, + 0.689769,-0.265624,0.673544,4.728963,2.036146,0.614307, + 0.184871,0.227138,0.956154,4.798297,2.118191,0.591085, + 0.384025,-0.256534,0.88697,4.807794,2.143653,0.570393, + 0.337014,-0.030018,0.941021,4.760921,1.881357,0.61312, + -0.026366,0.234118,0.971851,4.751519,2.039658,0.634134, + 0.689769,-0.265624,0.673544,4.728963,2.036146,0.614307, + 0.337014,-0.030018,0.941021,4.760921,1.881357,0.61312, + 0.689769,-0.265624,0.673544,4.728963,2.036146,0.614307, + 0.901575,-0.270544,0.337593,4.742358,1.882232,0.62165, + 0.884603,-0.366979,0.287755,4.697607,1.768061,0.576663, + 0.337014,-0.030018,0.941021,4.760921,1.881357,0.61312, + 0.901575,-0.270544,0.337593,4.742358,1.882232,0.62165, + 0.190357,-0.604308,0.773677,4.688114,2.046378,0.604518, + 0.689769,-0.265624,0.673544,4.728963,2.036146,0.614307, + 0.384025,-0.256534,0.88697,4.807794,2.143653,0.570393, + 0.190357,-0.604308,0.773677,4.688114,2.046378,0.604518, + 0.384025,-0.256534,0.88697,4.807794,2.143653,0.570393, + 0.399187,-0.679804,0.615237,4.74405,2.179337,0.556057, + 0.384025,-0.256534,0.88697,4.807794,2.143653,0.570393, + 0.292794,-0.691168,0.660725,4.881855,2.194544,0.530288, + 0.428199,-0.104479,0.897624,4.837331,2.235678,0.479332, + 0.384025,-0.256534,0.88697,4.807794,2.143653,0.570393, + 0.428199,-0.104479,0.897624,4.837331,2.235678,0.479332, + 0.399187,-0.679804,0.615237,4.74405,2.179337,0.556057, + 0.292794,-0.691168,0.660725,4.881855,2.194544,0.530288, + 0.507131,-0.710633,0.487667,4.93795,2.181155,0.486939, + 0.259896,0.111139,0.95922,4.89385,2.220523,0.417713, + 0.292794,-0.691168,0.660725,4.881855,2.194544,0.530288, + 0.259896,0.111139,0.95922,4.89385,2.220523,0.417713, + 0.428199,-0.104479,0.897624,4.837331,2.235678,0.479332, + 0.507131,-0.710633,0.487667,4.93795,2.181155,0.486939, + 0.468872,-0.092982,0.878359,5.030641,2.102197,0.432329, + 0.230527,0.277299,0.932718,4.995978,2.148785,0.344534, + 0.507131,-0.710633,0.487667,4.93795,2.181155,0.486939, + 0.230527,0.277299,0.932718,4.995978,2.148785,0.344534, + 0.259896,0.111139,0.95922,4.89385,2.220523,0.417713, + 0.468872,-0.092982,0.878359,5.030641,2.102197,0.432329, + 0.670109,-0.356989,0.650778,5.067202,2.027704,0.422291, + 0.171367,-0.69152,0.701736,5.06084,2.053335,0.309324, + 0.468872,-0.092982,0.878359,5.030641,2.102197,0.432329, + 0.171367,-0.69152,0.701736,5.06084,2.053335,0.309324, + 0.230527,0.277299,0.932718,4.995978,2.148785,0.344534, + 0.670109,-0.356989,0.650778,5.067202,2.027704,0.422291, + 0.72603,0.248277,0.641279,5.095375,1.961238,0.401516, + 0.258975,-0.768157,0.585548,5.097062,1.954206,0.328795, + 0.670109,-0.356989,0.650778,5.067202,2.027704,0.422291, + 0.258975,-0.768157,0.585548,5.097062,1.954206,0.328795, + 0.171367,-0.69152,0.701736,5.06084,2.053335,0.309324, + 0.988203,-0.047217,0.145687,5.085813,1.888503,0.408327, + 0.154813,-0.698608,0.698556,5.105589,1.864086,0.347113, + 0.258975,-0.768157,0.585548,5.097062,1.954206,0.328795, + 0.988203,-0.047217,0.145687,5.085813,1.888503,0.408327, + 0.258975,-0.768157,0.585548,5.097062,1.954206,0.328795, + 0.72603,0.248277,0.641279,5.095375,1.961238,0.401516, + 0.936242,-0.313777,-0.158096,5.058179,1.788186,0.417387, + 0.154813,-0.698608,0.698556,5.105589,1.864086,0.347113, + 0.988203,-0.047217,0.145687,5.085813,1.888503,0.408327, + 0.884603,-0.366979,0.287755,4.697607,1.768061,0.576663, + 0.901575,-0.270544,0.337593,4.742358,1.882232,0.62165, + 0.152967,-0.640193,0.752831,4.697024,1.862575,0.604048, + 0.259896,0.111139,0.95922,4.89385,2.220523,0.417713, + 0.203778,-0.389736,0.898098,4.83289,2.262727,0.283787, + 0.244568,-0.044721,0.9686,4.739441,2.299169,0.369987, + 0.259896,0.111139,0.95922,4.89385,2.220523,0.417713, + 0.244568,-0.044721,0.9686,4.739441,2.299169,0.369987, + 0.428199,-0.104479,0.897624,4.837331,2.235678,0.479332, + 0.259896,0.111139,0.95922,4.89385,2.220523,0.417713, + 0.230527,0.277299,0.932718,4.995978,2.148785,0.344534, + -0.026148,0.006311,0.999638,4.971394,2.146686,0.224781, + 0.259896,0.111139,0.95922,4.89385,2.220523,0.417713, + -0.026148,0.006311,0.999638,4.971394,2.146686,0.224781, + 0.203778,-0.389736,0.898098,4.83289,2.262727,0.283787, + 0.230527,0.277299,0.932718,4.995978,2.148785,0.344534, + 0.171367,-0.69152,0.701736,5.06084,2.053335,0.309324, + -0.149467,-0.273889,0.950076,5.072165,2.04363,0.209228, + 0.230527,0.277299,0.932718,4.995978,2.148785,0.344534, + -0.149467,-0.273889,0.950076,5.072165,2.04363,0.209228, + -0.026148,0.006311,0.999638,4.971394,2.146686,0.224781, + 0.171367,-0.69152,0.701736,5.06084,2.053335,0.309324, + 0.258975,-0.768157,0.585548,5.097062,1.954206,0.328795, + 0.06611,-0.359829,0.930673,5.127157,1.942759,0.211214, + 0.171367,-0.69152,0.701736,5.06084,2.053335,0.309324, + 0.06611,-0.359829,0.930673,5.127157,1.942759,0.211214, + -0.149467,-0.273889,0.950076,5.072165,2.04363,0.209228, + 0.258975,-0.768157,0.585548,5.097062,1.954206,0.328795, + 0.154813,-0.698608,0.698556,5.105589,1.864086,0.347113, + -0.091049,-0.145989,0.985087,5.152698,1.830661,0.287042, + 0.258975,-0.768157,0.585548,5.097062,1.954206,0.328795, + -0.091049,-0.145989,0.985087,5.152698,1.830661,0.287042, + 0.06611,-0.359829,0.930673,5.127157,1.942759,0.211214, + 0.936242,-0.313777,-0.158096,5.058179,1.788186,0.417387, + -0.12102,-0.514608,0.848842,5.133171,1.715563,0.334258, + -0.091049,-0.145989,0.985087,5.152698,1.830661,0.287042, + 0.936242,-0.313777,-0.158096,5.058179,1.788186,0.417387, + -0.091049,-0.145989,0.985087,5.152698,1.830661,0.287042, + 0.154813,-0.698608,0.698556,5.105589,1.864086,0.347113, + 0.831186,-0.511045,-0.219005,5.019836,1.739907,0.485562, + 0.063508,-0.739371,0.670296,5.103427,1.624404,0.434275, + -0.12102,-0.514608,0.848842,5.133171,1.715563,0.334258, + 0.831186,-0.511045,-0.219005,5.019836,1.739907,0.485562, + -0.12102,-0.514608,0.848842,5.133171,1.715563,0.334258, + 0.936242,-0.313777,-0.158096,5.058179,1.788186,0.417387, + 0.797293,-0.558933,-0.227857,4.917973,1.68148,0.544201, + 0.169576,-0.140705,0.975421,4.982822,1.503071,0.507606, + 0.063508,-0.739371,0.670296,5.103427,1.624404,0.434275, + 0.797293,-0.558933,-0.227857,4.917973,1.68148,0.544201, + 0.063508,-0.739371,0.670296,5.103427,1.624404,0.434275, + 0.831186,-0.511045,-0.219005,5.019836,1.739907,0.485562, + 0.111896,-0.605741,0.787755,4.927282,1.486953,0.526327, + 0.169576,-0.140705,0.975421,4.982822,1.503071,0.507606, + 0.797293,-0.558933,-0.227857,4.917973,1.68148,0.544201, + 0.111896,-0.605741,0.787755,4.927282,1.486953,0.526327, + 0.797293,-0.558933,-0.227857,4.917973,1.68148,0.544201, + 0.707669,-0.687185,0.164261,4.862636,1.684144,0.570155, + 0.002178,-0.833415,0.552643,4.79841,1.473149,0.570618, + 0.111896,-0.605741,0.787755,4.927282,1.486953,0.526327, + 0.707669,-0.687185,0.164261,4.862636,1.684144,0.570155, + 0.16399,-0.527953,0.833291,4.715646,1.502195,0.584339, + 0.002178,-0.833415,0.552643,4.79841,1.473149,0.570618, + 0.707669,-0.687185,0.164261,4.862636,1.684144,0.570155, + 0.16399,-0.527953,0.833291,4.715646,1.502195,0.584339, + 0.707669,-0.687185,0.164261,4.862636,1.684144,0.570155, + 0.744254,-0.65416,0.134758,4.752337,1.723388,0.591296, + 0.205809,-0.680492,0.703259,4.615408,1.639641,0.577768, + 0.16399,-0.527953,0.833291,4.715646,1.502195,0.584339, + 0.744254,-0.65416,0.134758,4.752337,1.723388,0.591296, + 0.205809,-0.680492,0.703259,4.615408,1.639641,0.577768, + 0.744254,-0.65416,0.134758,4.752337,1.723388,0.591296, + 0.884603,-0.366979,0.287755,4.697607,1.768061,0.576663, + 0.396941,-0.593503,0.700137,4.560751,1.785154,0.562428, + 0.205809,-0.680492,0.703259,4.615408,1.639641,0.577768, + 0.884603,-0.366979,0.287755,4.697607,1.768061,0.576663, + 0.396941,-0.593503,0.700137,4.560751,1.785154,0.562428, + 0.884603,-0.366979,0.287755,4.697607,1.768061,0.576663, + 0.152967,-0.640193,0.752831,4.697024,1.862575,0.604048, + 0.396941,-0.593503,0.700137,4.560751,1.785154,0.562428, + 0.152967,-0.640193,0.752831,4.697024,1.862575,0.604048, + 0.190357,-0.604308,0.773677,4.688114,2.046378,0.604518, + 0.396941,-0.593503,0.700137,4.560751,1.785154,0.562428, + 0.190357,-0.604308,0.773677,4.688114,2.046378,0.604518, + 0.025716,-0.894111,0.447106,4.551484,1.841749,0.575191, + 0.025716,-0.894111,0.447106,4.551484,1.841749,0.575191, + 0.190357,-0.604308,0.773677,4.688114,2.046378,0.604518, + 0.051115,-0.906355,0.419413,4.533113,1.989009,0.578975, + 0.256335,-0.2349,0.937611,4.561299,2.133066,0.547248, + 0.190357,-0.604308,0.773677,4.688114,2.046378,0.604518, + 0.399187,-0.679804,0.615237,4.74405,2.179337,0.556057, + 0.256335,-0.2349,0.937611,4.561299,2.133066,0.547248, + 0.399187,-0.679804,0.615237,4.74405,2.179337,0.556057, + 0.223925,-0.919003,0.324486,4.636582,2.263383,0.471997, + 0.051115,-0.906355,0.419413,4.533113,1.989009,0.578975, + 0.190357,-0.604308,0.773677,4.688114,2.046378,0.604518, + 0.256335,-0.2349,0.937611,4.561299,2.133066,0.547248, + -0.026148,0.006311,0.999638,4.971394,2.146686,0.224781, + -0.149467,-0.273889,0.950076,5.072165,2.04363,0.209228, + -0.941169,-0.337937,0,5.04969,2.032731,0.000071, + -0.026148,0.006311,0.999638,4.971394,2.146686,0.224781, + -0.941169,-0.337937,0,5.04969,2.032731,0.000071, + -0.989689,-0.143234,0,4.912303,2.162645,-0.00009, + -0.149467,-0.273889,0.950076,5.072165,2.04363,0.209228, + 0.06611,-0.359829,0.930673,5.127157,1.942759,0.211214, + 0.204472,-0.587725,0.782797,5.156645,1.942902,0.119993, + -0.149467,-0.273889,0.950076,5.072165,2.04363,0.209228, + 0.204472,-0.587725,0.782797,5.156645,1.942902,0.119993, + -0.941169,-0.337937,0,5.04969,2.032731,0.000071, + 0.06611,-0.359829,0.930673,5.127157,1.942759,0.211214, + -0.091049,-0.145989,0.985087,5.152698,1.830661,0.287042, + 0.161367,-0.802085,0.574996,5.218821,1.803552,0.199306, + 0.06611,-0.359829,0.930673,5.127157,1.942759,0.211214, + 0.161367,-0.802085,0.574996,5.218821,1.803552,0.199306, + 0.204472,-0.587725,0.782797,5.156645,1.942902,0.119993, + -0.091049,-0.145989,0.985087,5.152698,1.830661,0.287042, + -0.12102,-0.514608,0.848842,5.133171,1.715563,0.334258, + 0.218068,-0.756333,0.616772,5.216855,1.636645,0.279797, + -0.091049,-0.145989,0.985087,5.152698,1.830661,0.287042, + 0.218068,-0.756333,0.616772,5.216855,1.636645,0.279797, + 0.161367,-0.802085,0.574996,5.218821,1.803552,0.199306, + 0.726183,-0.658007,0.199213,5.233176,1.442459,0.362988, + 0.218068,-0.756333,0.616772,5.216855,1.636645,0.279797, + -0.12102,-0.514608,0.848842,5.133171,1.715563,0.334258, + 0.063508,-0.739371,0.670296,5.103427,1.624404,0.434275, + 0.726183,-0.658007,0.199213,5.233176,1.442459,0.362988, + -0.12102,-0.514608,0.848842,5.133171,1.715563,0.334258, + 0.035735,-0.99787,0.054579,4.596478,1.512987,0.598982, + 0.485742,-0.874075,-0.006874,4.679116,1.438434,0.589658, + 0.16399,-0.527953,0.833291,4.715646,1.502195,0.584339, + 0.035735,-0.99787,0.054579,4.596478,1.512987,0.598982, + 0.16399,-0.527953,0.833291,4.715646,1.502195,0.584339, + 0.205809,-0.680492,0.703259,4.615408,1.639641,0.577768, + -0.034202,-0.995024,0.093584,4.560024,1.604023,0.589333, + 0.035735,-0.99787,0.054579,4.596478,1.512987,0.598982, + 0.205809,-0.680492,0.703259,4.615408,1.639641,0.577768, + 0.06465,-0.997821,-0.013157,4.477781,1.687858,0.597407, + -0.034202,-0.995024,0.093584,4.560024,1.604023,0.589333, + 0.205809,-0.680492,0.703259,4.615408,1.639641,0.577768, + 0.06465,-0.997821,-0.013157,4.477781,1.687858,0.597407, + 0.205809,-0.680492,0.703259,4.615408,1.639641,0.577768, + 0.396941,-0.593503,0.700137,4.560751,1.785154,0.562428, + 0.173736,-0.983834,-0.043437,4.459682,1.778884,0.588185, + 0.06465,-0.997821,-0.013157,4.477781,1.687858,0.597407, + 0.396941,-0.593503,0.700137,4.560751,1.785154,0.562428, + 0.173736,-0.983834,-0.043437,4.459682,1.778884,0.588185, + 0.396941,-0.593503,0.700137,4.560751,1.785154,0.562428, + 0.025716,-0.894111,0.447106,4.551484,1.841749,0.575191, + 0.173736,-0.983834,-0.043437,4.459682,1.778884,0.588185, + 0.025716,-0.894111,0.447106,4.551484,1.841749,0.575191, + 0.051115,-0.906355,0.419413,4.533113,1.989009,0.578975, + 0.173736,-0.983834,-0.043437,4.459682,1.778884,0.588185, + 0.051115,-0.906355,0.419413,4.533113,1.989009,0.578975, + 0.003817,-0.976864,0.213829,4.43261,1.878873,0.577888, + 0.003817,-0.976864,0.213829,4.43261,1.878873,0.577888, + 0.051115,-0.906355,0.419413,4.533113,1.989009,0.578975, + 0.256335,-0.2349,0.937611,4.561299,2.133066,0.547248, + 0.003817,-0.976864,0.213829,4.43261,1.878873,0.577888, + 0.256335,-0.2349,0.937611,4.561299,2.133066,0.547248, + 0.125846,-0.929941,0.345503,4.43302,2.024714,0.563794, + 0.244568,-0.044721,0.9686,4.739441,2.299169,0.369987, + 0.203778,-0.389736,0.898098,4.83289,2.262727,0.283787, + -0.965284,-0.261201,0,4.747988,2.300163,-0.000276, + 0.244568,-0.044721,0.9686,4.739441,2.299169,0.369987, + -0.965284,-0.261201,0,4.747988,2.300163,-0.000276, + 0.241652,-0.897637,0.368581,4.634996,2.369115,0.140117, + 0.223925,-0.919003,0.324486,4.636582,2.263383,0.471997, + 0.244568,-0.044721,0.9686,4.739441,2.299169,0.369987, + 0.241652,-0.897637,0.368581,4.634996,2.369115,0.140117, + 0.223925,-0.919003,0.324486,4.636582,2.263383,0.471997, + 0.241652,-0.897637,0.368581,4.634996,2.369115,0.140117, + 0.170159,-0.985033,-0.027502,4.577573,2.389535,0.256196, + 0.223925,-0.919003,0.324486,4.636582,2.263383,0.471997, + 0.170159,-0.985033,-0.027502,4.577573,2.389535,0.256196, + 0.231006,-0.859096,0.456717,4.472349,2.325133,0.443764, + 0.108306,-0.808441,0.578527,4.389484,2.190421,0.47332, + 0.256335,-0.2349,0.937611,4.561299,2.133066,0.547248, + 0.223925,-0.919003,0.324486,4.636582,2.263383,0.471997, + 0.108306,-0.808441,0.578527,4.389484,2.190421,0.47332, + 0.223925,-0.919003,0.324486,4.636582,2.263383,0.471997, + 0.231006,-0.859096,0.456717,4.472349,2.325133,0.443764, + 0.125846,-0.929941,0.345503,4.43302,2.024714,0.563794, + 0.256335,-0.2349,0.937611,4.561299,2.133066,0.547248, + 0.108306,-0.808441,0.578527,4.389484,2.190421,0.47332, + 0.169576,-0.140705,0.975421,4.982822,1.503071,0.507606, + 0.155382,-0.98726,0.034255,5.223191,1.371491,0.388069, + 0.726183,-0.658007,0.199213,5.233176,1.442459,0.362988, + 0.169576,-0.140705,0.975421,4.982822,1.503071,0.507606, + 0.726183,-0.658007,0.199213,5.233176,1.442459,0.362988, + 0.063508,-0.739371,0.670296,5.103427,1.624404,0.434275, + 0.111896,-0.605741,0.787755,4.927282,1.486953,0.526327, + 0.228199,-0.705361,0.671111,5.158322,1.23677,0.418043, + 0.155382,-0.98726,0.034255,5.223191,1.371491,0.388069, + 0.111896,-0.605741,0.787755,4.927282,1.486953,0.526327, + 0.155382,-0.98726,0.034255,5.223191,1.371491,0.388069, + 0.169576,-0.140705,0.975421,4.982822,1.503071,0.507606, + 0.002178,-0.833415,0.552643,4.79841,1.473149,0.570618, + 0.114701,-0.691525,0.713188,4.95536,1.236724,0.50523, + 0.228199,-0.705361,0.671111,5.158322,1.23677,0.418043, + 0.002178,-0.833415,0.552643,4.79841,1.473149,0.570618, + 0.228199,-0.705361,0.671111,5.158322,1.23677,0.418043, + 0.111896,-0.605741,0.787755,4.927282,1.486953,0.526327, + 0.16399,-0.527953,0.833291,4.715646,1.502195,0.584339, + 0.298912,-0.321997,0.898315,4.761601,1.363013,0.57137, + 0.114701,-0.691525,0.713188,4.95536,1.236724,0.50523, + 0.16399,-0.527953,0.833291,4.715646,1.502195,0.584339, + 0.114701,-0.691525,0.713188,4.95536,1.236724,0.50523, + 0.002178,-0.833415,0.552643,4.79841,1.473149,0.570618, + 0.485742,-0.874075,-0.006874,4.679116,1.438434,0.589658, + 0.298912,-0.321997,0.898315,4.761601,1.363013,0.57137, + 0.16399,-0.527953,0.833291,4.715646,1.502195,0.584339, + 0.204472,-0.587725,0.782797,5.156645,1.942902,0.119993, + 0.161367,-0.802085,0.574996,5.218821,1.803552,0.199306, + 0.241049,-0.626018,0.741618,5.321136,1.795562,0.119606, + 0.204472,-0.587725,0.782797,5.156645,1.942902,0.119993, + 0.241049,-0.626018,0.741618,5.321136,1.795562,0.119606, + -0.998597,-0.052951,0,5.177545,1.932323,0.000214, + 0.241049,-0.626018,0.741618,5.321136,1.795562,0.119606, + -0.99798,-0.063521,0,5.378289,1.768448,0.000441, + -0.998597,-0.052951,0,5.177545,1.932323,0.000214, + 0.241049,-0.626018,0.741618,5.321136,1.795562,0.119606, + 0.272751,-0.332382,0.902845,5.421809,1.685349,0.123555, + -0.925873,-0.377836,0,5.424281,1.721152,0.000496, + 0.241049,-0.626018,0.741618,5.321136,1.795562,0.119606, + -0.925873,-0.377836,0,5.424281,1.721152,0.000496, + -0.99798,-0.063521,0,5.378289,1.768448,0.000441, + 0.161397,-0.648358,0.744032,5.383208,1.619661,0.202452, + 0.272751,-0.332382,0.902845,5.421809,1.685349,0.123555, + 0.241049,-0.626018,0.741618,5.321136,1.795562,0.119606, + 0.161397,-0.648358,0.744032,5.383208,1.619661,0.202452, + 0.241049,-0.626018,0.741618,5.321136,1.795562,0.119606, + 0.161367,-0.802085,0.574996,5.218821,1.803552,0.199306, + 0.218068,-0.756333,0.616772,5.216855,1.636645,0.279797, + 0.142784,-0.229696,0.962732,5.373133,1.541142,0.246712, + 0.161397,-0.648358,0.744032,5.383208,1.619661,0.202452, + 0.218068,-0.756333,0.616772,5.216855,1.636645,0.279797, + 0.161397,-0.648358,0.744032,5.383208,1.619661,0.202452, + 0.161367,-0.802085,0.574996,5.218821,1.803552,0.199306, + 0.726183,-0.658007,0.199213,5.233176,1.442459,0.362988, + -0.045194,-0.595739,0.801906,5.334328,1.402713,0.332639, + 0.142784,-0.229696,0.962732,5.373133,1.541142,0.246712, + 0.726183,-0.658007,0.199213,5.233176,1.442459,0.362988, + 0.142784,-0.229696,0.962732,5.373133,1.541142,0.246712, + 0.218068,-0.756333,0.616772,5.216855,1.636645,0.279797, + 0.155382,-0.98726,0.034255,5.223191,1.371491,0.388069, + -0.016623,-0.697515,0.716377,5.296963,1.322443,0.357984, + -0.045194,-0.595739,0.801906,5.334328,1.402713,0.332639, + 0.155382,-0.98726,0.034255,5.223191,1.371491,0.388069, + -0.045194,-0.595739,0.801906,5.334328,1.402713,0.332639, + 0.726183,-0.658007,0.199213,5.233176,1.442459,0.362988, + 0.228199,-0.705361,0.671111,5.158322,1.23677,0.418043, + -0.105003,-0.636187,0.764356,5.260653,1.184173,0.352062, + -0.016623,-0.697515,0.716377,5.296963,1.322443,0.357984, + 0.228199,-0.705361,0.671111,5.158322,1.23677,0.418043, + -0.016623,-0.697515,0.716377,5.296963,1.322443,0.357984, + 0.155382,-0.98726,0.034255,5.223191,1.371491,0.388069, + 0.009824,-0.644035,0.764933,5.250485,1.123029,0.385234, + -0.105003,-0.636187,0.764356,5.260653,1.184173,0.352062, + 0.228199,-0.705361,0.671111,5.158322,1.23677,0.418043, + 0.114701,-0.691525,0.713188,4.95536,1.236724,0.50523, + -0.023775,-0.598435,0.800818,4.991713,1.163096,0.504149, + 0.009824,-0.644035,0.764933,5.250485,1.123029,0.385234, + 0.114701,-0.691525,0.713188,4.95536,1.236724,0.50523, + 0.009824,-0.644035,0.764933,5.250485,1.123029,0.385234, + 0.228199,-0.705361,0.671111,5.158322,1.23677,0.418043, + 0.200825,-0.971974,0.122213,4.733657,1.227371,0.592883, + -0.023775,-0.598435,0.800818,4.991713,1.163096,0.504149, + 0.114701,-0.691525,0.713188,4.95536,1.236724,0.50523, + 0.200825,-0.971974,0.122213,4.733657,1.227371,0.592883, + 0.114701,-0.691525,0.713188,4.95536,1.236724,0.50523, + 0.298912,-0.321997,0.898315,4.761601,1.363013,0.57137, + 0.123418,-0.784469,0.607763,4.641547,1.285422,0.622034, + 0.200825,-0.971974,0.122213,4.733657,1.227371,0.592883, + 0.298912,-0.321997,0.898315,4.761601,1.363013,0.57137, + 0.123418,-0.784469,0.607763,4.641547,1.285422,0.622034, + 0.298912,-0.321997,0.898315,4.761601,1.363013,0.57137, + 0.485742,-0.874075,-0.006874,4.679116,1.438434,0.589658, + 0.050019,-0.552867,0.831767,4.522247,1.398278,0.644892, + 0.123418,-0.784469,0.607763,4.641547,1.285422,0.622034, + 0.485742,-0.874075,-0.006874,4.679116,1.438434,0.589658, + 0.050019,-0.552867,0.831767,4.522247,1.398278,0.644892, + 0.485742,-0.874075,-0.006874,4.679116,1.438434,0.589658, + 0.035735,-0.99787,0.054579,4.596478,1.512987,0.598982, + 0.037801,-0.082839,0.995846,4.430999,1.535753,0.638888, + 0.050019,-0.552867,0.831767,4.522247,1.398278,0.644892, + 0.035735,-0.99787,0.054579,4.596478,1.512987,0.598982, + 0.037801,-0.082839,0.995846,4.430999,1.535753,0.638888, + 0.035735,-0.99787,0.054579,4.596478,1.512987,0.598982, + -0.034202,-0.995024,0.093584,4.560024,1.604023,0.589333, + -0.196146,-0.333078,0.922272,4.404221,1.662433,0.61661, + 0.037801,-0.082839,0.995846,4.430999,1.535753,0.638888, + -0.034202,-0.995024,0.093584,4.560024,1.604023,0.589333, + -0.196146,-0.333078,0.922272,4.404221,1.662433,0.61661, + -0.034202,-0.995024,0.093584,4.560024,1.604023,0.589333, + 0.06465,-0.997821,-0.013157,4.477781,1.687858,0.597407, + -0.196146,-0.333078,0.922272,4.404221,1.662433,0.61661, + 0.06465,-0.997821,-0.013157,4.477781,1.687858,0.597407, + 0.173736,-0.983834,-0.043437,4.459682,1.778884,0.588185, + -0.196146,-0.333078,0.922272,4.404221,1.662433,0.61661, + 0.173736,-0.983834,-0.043437,4.459682,1.778884,0.588185, + -0.106358,-0.394397,0.912765,4.38638,1.770868,0.596666, + -0.106358,-0.394397,0.912765,4.38638,1.770868,0.596666, + 0.173736,-0.983834,-0.043437,4.459682,1.778884,0.588185, + 0.003817,-0.976864,0.213829,4.43261,1.878873,0.577888, + -0.106358,-0.394397,0.912765,4.38638,1.770868,0.596666, + 0.003817,-0.976864,0.213829,4.43261,1.878873,0.577888, + -0.277696,-0.435918,0.856073,4.377095,1.871713,0.595743, + 0.272751,-0.332382,0.902845,5.421809,1.685349,0.123555, + -0.301162,-0.110219,0.947182,5.604888,1.546091,0.113773, + 0.027992,0.999608,0,5.588763,1.573846,0.000686, + 0.272751,-0.332382,0.902845,5.421809,1.685349,0.123555, + 0.027992,0.999608,0,5.588763,1.573846,0.000686, + -0.925873,-0.377836,0,5.424281,1.721152,0.000496, + 0.161397,-0.648358,0.744032,5.383208,1.619661,0.202452, + -0.430969,-0.132769,0.892546,5.566339,1.498677,0.190905, + -0.301162,-0.110219,0.947182,5.604888,1.546091,0.113773, + 0.161397,-0.648358,0.744032,5.383208,1.619661,0.202452, + -0.301162,-0.110219,0.947182,5.604888,1.546091,0.113773, + 0.272751,-0.332382,0.902845,5.421809,1.685349,0.123555, + 0.142784,-0.229696,0.962732,5.373133,1.541142,0.246712, + -0.293162,-0.051827,0.954657,5.528186,1.44018,0.250666, + -0.430969,-0.132769,0.892546,5.566339,1.498677,0.190905, + 0.142784,-0.229696,0.962732,5.373133,1.541142,0.246712, + -0.430969,-0.132769,0.892546,5.566339,1.498677,0.190905, + 0.161397,-0.648358,0.744032,5.383208,1.619661,0.202452, + -0.045194,-0.595739,0.801906,5.334328,1.402713,0.332639, + -0.034138,0.050771,0.998127,5.471928,1.345179,0.313899, + -0.293162,-0.051827,0.954657,5.528186,1.44018,0.250666, + -0.045194,-0.595739,0.801906,5.334328,1.402713,0.332639, + -0.293162,-0.051827,0.954657,5.528186,1.44018,0.250666, + 0.142784,-0.229696,0.962732,5.373133,1.541142,0.246712, + -0.016623,-0.697515,0.716377,5.296963,1.322443,0.357984, + -0.101883,0.176778,0.978963,5.425783,1.264372,0.329687, + -0.034138,0.050771,0.998127,5.471928,1.345179,0.313899, + -0.016623,-0.697515,0.716377,5.296963,1.322443,0.357984, + -0.034138,0.050771,0.998127,5.471928,1.345179,0.313899, + -0.045194,-0.595739,0.801906,5.334328,1.402713,0.332639, + -0.105003,-0.636187,0.764356,5.260653,1.184173,0.352062, + -0.172671,0.234525,0.956652,5.397967,1.174238,0.346802, + -0.101883,0.176778,0.978963,5.425783,1.264372,0.329687, + -0.105003,-0.636187,0.764356,5.260653,1.184173,0.352062, + -0.101883,0.176778,0.978963,5.425783,1.264372,0.329687, + -0.016623,-0.697515,0.716377,5.296963,1.322443,0.357984, + 0.009824,-0.644035,0.764933,5.250485,1.123029,0.385234, + -0.317809,0.237298,0.91798,5.388455,1.119419,0.351883, + -0.172671,0.234525,0.956652,5.397967,1.174238,0.346802, + 0.009824,-0.644035,0.764933,5.250485,1.123029,0.385234, + -0.172671,0.234525,0.956652,5.397967,1.174238,0.346802, + -0.105003,-0.636187,0.764356,5.260653,1.184173,0.352062, + -0.419631,0.061765,0.905591,5.685194,1.452202,0.188749, + -0.434729,0.079706,0.897027,5.730427,1.435668,0.209848, + -0.31398,0.125786,0.94106,5.741781,1.463956,0.124891, + -0.419631,0.061765,0.905591,5.685194,1.452202,0.188749, + -0.31398,0.125786,0.94106,5.741781,1.463956,0.124891, + -0.241533,0.200654,0.949421,5.687035,1.499636,0.110765, + -0.400711,0.089186,0.911853,5.647186,1.394606,0.257833, + 0.274471,0.961025,0.033122,5.608974,1.317869,0.319719, + -0.497134,0.140474,0.856227,5.710154,1.360653,0.290072, + 0.311768,0.950117,-0.008871,5.563253,1.235295,0.317238, + 0.563605,0.822456,0.076915,5.681726,1.282503,0.333871, + -0.497134,0.140474,0.856227,5.710154,1.360653,0.290072, + 0.311768,0.950117,-0.008871,5.563253,1.235295,0.317238, + -0.497134,0.140474,0.856227,5.710154,1.360653,0.290072, + 0.274471,0.961025,0.033122,5.608974,1.317869,0.319719, + 0.381066,0.919021,0.100938,5.580797,1.174135,0.351054, + 0.609817,0.770093,0.187296,5.672187,1.164767,0.35408, + 0.563605,0.822456,0.076915,5.681726,1.282503,0.333871, + 0.381066,0.919021,0.100938,5.580797,1.174135,0.351054, + 0.563605,0.822456,0.076915,5.681726,1.282503,0.333871, + 0.311768,0.950117,-0.008871,5.563253,1.235295,0.317238, + 0.027992,0.999608,0,5.588763,1.573846,0.000686, + -0.301162,-0.110219,0.947182,5.604888,1.546091,0.113773, + -0.241533,0.200654,0.949421,5.687035,1.499636,0.110765, + 0.027992,0.999608,0,5.588763,1.573846,0.000686, + -0.241533,0.200654,0.949421,5.687035,1.499636,0.110765, + -0.026558,-0.999647,0,5.680007,1.510009,0.000786, + -0.430969,-0.132769,0.892546,5.566339,1.498677,0.190905, + -0.419631,0.061765,0.905591,5.685194,1.452202,0.188749, + -0.241533,0.200654,0.949421,5.687035,1.499636,0.110765, + -0.430969,-0.132769,0.892546,5.566339,1.498677,0.190905, + -0.241533,0.200654,0.949421,5.687035,1.499636,0.110765, + -0.301162,-0.110219,0.947182,5.604888,1.546091,0.113773, + -0.430969,-0.132769,0.892546,5.566339,1.498677,0.190905, + -0.293162,-0.051827,0.954657,5.528186,1.44018,0.250666, + -0.400711,0.089186,0.911853,5.647186,1.394606,0.257833, + -0.430969,-0.132769,0.892546,5.566339,1.498677,0.190905, + -0.400711,0.089186,0.911853,5.647186,1.394606,0.257833, + -0.419631,0.061765,0.905591,5.685194,1.452202,0.188749, + -0.034138,0.050771,0.998127,5.471928,1.345179,0.313899, + 0.274471,0.961025,0.033122,5.608974,1.317869,0.319719, + -0.400711,0.089186,0.911853,5.647186,1.394606,0.257833, + -0.034138,0.050771,0.998127,5.471928,1.345179,0.313899, + -0.400711,0.089186,0.911853,5.647186,1.394606,0.257833, + -0.293162,-0.051827,0.954657,5.528186,1.44018,0.250666, + -0.101883,0.176778,0.978963,5.425783,1.264372,0.329687, + 0.311768,0.950117,-0.008871,5.563253,1.235295,0.317238, + 0.274471,0.961025,0.033122,5.608974,1.317869,0.319719, + -0.101883,0.176778,0.978963,5.425783,1.264372,0.329687, + 0.274471,0.961025,0.033122,5.608974,1.317869,0.319719, + -0.034138,0.050771,0.998127,5.471928,1.345179,0.313899, + -0.172671,0.234525,0.956652,5.397967,1.174238,0.346802, + 0.381066,0.919021,0.100938,5.580797,1.174135,0.351054, + 0.311768,0.950117,-0.008871,5.563253,1.235295,0.317238, + -0.172671,0.234525,0.956652,5.397967,1.174238,0.346802, + 0.311768,0.950117,-0.008871,5.563253,1.235295,0.317238, + -0.101883,0.176778,0.978963,5.425783,1.264372,0.329687, + -0.317809,0.237298,0.91798,5.388455,1.119419,0.351883, + 0.651262,0.697944,0.297879,5.47963,1.11131,0.364188, + 0.381066,0.919021,0.100938,5.580797,1.174135,0.351054, + -0.317809,0.237298,0.91798,5.388455,1.119419,0.351883, + 0.381066,0.919021,0.100938,5.580797,1.174135,0.351054, + -0.172671,0.234525,0.956652,5.397967,1.174238,0.346802, + -0.081905,0.996619,-0.006486,5.813217,1.415581,0.195261, + -0.134248,0.990294,-0.035988,5.886832,1.385674,0.172365, + -0.11884,0.991349,-0.055713,5.915025,1.382159,0.13682, + -0.081905,0.996619,-0.006486,5.813217,1.415581,0.195261, + -0.11884,0.991349,-0.055713,5.915025,1.382159,0.13682, + -0.062808,0.99609,0.062134,5.842092,1.427708,0.130724, + -0.11884,0.991349,-0.055713,5.915025,1.382159,0.13682, + 0.448666,0.893201,0.029856,5.979357,1.325532,0.125337, + 0.663563,0.74812,0.000025,5.963117,1.307775,0.001098, + -0.11884,0.991349,-0.055713,5.915025,1.382159,0.13682, + 0.663563,0.74812,0.000025,5.963117,1.307775,0.001098, + -0.016213,0.999869,0,5.908842,1.388968,0.001026, + -0.134248,0.990294,-0.035988,5.886832,1.385674,0.172365, + 0.731768,0.675964,0.087106,5.941384,1.330818,0.178936, + 0.448666,0.893201,0.029856,5.979357,1.325532,0.125337, + -0.134248,0.990294,-0.035988,5.886832,1.385674,0.172365, + 0.448666,0.893201,0.029856,5.979357,1.325532,0.125337, + -0.11884,0.991349,-0.055713,5.915025,1.382159,0.13682, + -0.31398,0.125786,0.94106,5.741781,1.463956,0.124891, + -0.062808,0.99609,0.062134,5.842092,1.427708,0.130724, + 0.569495,0.821995,-0.000075,5.835498,1.43628,0.000946, + -0.31398,0.125786,0.94106,5.741781,1.463956,0.124891, + 0.569495,0.821995,-0.000075,5.835498,1.43628,0.000946, + 0.694651,0.719347,0.000019,5.743997,1.482739,0.000851, + -0.434729,0.079706,0.897027,5.730427,1.435668,0.209848, + -0.081905,0.996619,-0.006486,5.813217,1.415581,0.195261, + -0.062808,0.99609,0.062134,5.842092,1.427708,0.130724, + -0.434729,0.079706,0.897027,5.730427,1.435668,0.209848, + -0.062808,0.99609,0.062134,5.842092,1.427708,0.130724, + -0.31398,0.125786,0.94106,5.741781,1.463956,0.124891, + -0.497134,0.140474,0.856227,5.710154,1.360653,0.290072, + -0.0511,0.977083,-0.206633,5.783731,1.341471,0.28459, + -0.081905,0.996619,-0.006486,5.813217,1.415581,0.195261, + -0.497134,0.140474,0.856227,5.710154,1.360653,0.290072, + -0.081905,0.996619,-0.006486,5.813217,1.415581,0.195261, + -0.434729,0.079706,0.897027,5.730427,1.435668,0.209848, + -0.0511,0.977083,-0.206633,5.783731,1.341471,0.28459, + 0.481644,0.842268,-0.242082,5.847989,1.311569,0.261476, + -0.134248,0.990294,-0.035988,5.886832,1.385674,0.172365, + -0.0511,0.977083,-0.206633,5.783731,1.341471,0.28459, + -0.134248,0.990294,-0.035988,5.886832,1.385674,0.172365, + -0.081905,0.996619,-0.006486,5.813217,1.415581,0.195261, + 0.481644,0.842268,-0.242082,5.847989,1.311569,0.261476, + 0.794567,0.588129,-0.15089,5.931474,1.233483,0.215613, + 0.731768,0.675964,0.087106,5.941384,1.330818,0.178936, + 0.481644,0.842268,-0.242082,5.847989,1.311569,0.261476, + 0.731768,0.675964,0.087106,5.941384,1.330818,0.178936, + -0.134248,0.990294,-0.035988,5.886832,1.385674,0.172365, + 0.731768,0.675964,0.087106,5.941384,1.330818,0.178936, + 0.04154,0.947538,-0.316933,5.998088,1.231874,0.107334, + 0.448666,0.893201,0.029856,5.979357,1.325532,0.125337, + 0.448666,0.893201,0.029856,5.979357,1.325532,0.125337, + 0.04154,0.947538,-0.316933,5.998088,1.231874,0.107334, + 0.617634,0.786466,0.000062,5.963527,1.232407,0.001121, + 0.448666,0.893201,0.029856,5.979357,1.325532,0.125337, + 0.617634,0.786466,0.000062,5.963527,1.232407,0.001121, + 0.663563,0.74812,0.000025,5.963117,1.307775,0.001098, + 0.794567,0.588129,-0.15089,5.931474,1.233483,0.215613, + 0.04154,0.947538,-0.316933,5.998088,1.231874,0.107334, + 0.731768,0.675964,0.087106,5.941384,1.330818,0.178936, + 0.461485,0.788926,-0.405742,5.961686,1.110978,0.090324, + 0.651313,0.75881,-0.000286,5.92711,1.131195,0.001118, + 0.617634,0.786466,0.000062,5.963527,1.232407,0.001121, + 0.461485,0.788926,-0.405742,5.961686,1.110978,0.090324, + 0.617634,0.786466,0.000062,5.963527,1.232407,0.001121, + 0.04154,0.947538,-0.316933,5.998088,1.231874,0.107334, + 0.461485,0.788926,-0.405742,5.961686,1.110978,0.090324, + 0.800967,0.453079,-0.391371,5.934596,1.054796,0.077039, + 0.909103,0.416568,-0.001454,5.908782,1.066916,0.001121, + 0.461485,0.788926,-0.405742,5.961686,1.110978,0.090324, + 0.909103,0.416568,-0.001454,5.908782,1.066916,0.001121, + 0.651313,0.75881,-0.000286,5.92711,1.131195,0.001118, + 0.000755,0.939586,-0.342312,5.950684,1.082725,0.175648, + 0.693689,0.317887,-0.646331,5.923808,1.025283,0.153084, + 0.800967,0.453079,-0.391371,5.934596,1.054796,0.077039, + 0.000755,0.939586,-0.342312,5.950684,1.082725,0.175648, + 0.800967,0.453079,-0.391371,5.934596,1.054796,0.077039, + 0.461485,0.788926,-0.405742,5.961686,1.110978,0.090324, + 0.288171,0.239223,-0.927216,5.763952,1.062109,0.338641, + 0.104327,0.725166,-0.680625,5.755282,1.004149,0.307505, + -0.051423,0.948155,-0.31362,5.85775,0.997026,0.236768, + 0.288171,0.239223,-0.927216,5.763952,1.062109,0.338641, + -0.051423,0.948155,-0.31362,5.85775,0.997026,0.236768, + 0.525316,0.261332,-0.809783,5.884856,1.062202,0.249545, + 0.288171,0.239223,-0.927216,5.763952,1.062109,0.338641, + 0.525316,0.261332,-0.809783,5.884856,1.062202,0.249545, + 0.204286,0.745568,-0.634347,5.800778,1.078596,0.31945, + 0.525316,0.261332,-0.809783,5.884856,1.062202,0.249545, + 0.000755,0.939586,-0.342312,5.950684,1.082725,0.175648, + 0.969409,0.243854,0.027951,5.959462,1.157227,0.187097, + 0.525316,0.261332,-0.809783,5.884856,1.062202,0.249545, + 0.969409,0.243854,0.027951,5.959462,1.157227,0.187097, + 0.811896,0.498733,0.303464,5.912147,1.117911,0.254197, + -0.051423,0.948155,-0.31362,5.85775,0.997026,0.236768, + 0.693689,0.317887,-0.646331,5.923808,1.025283,0.153084, + 0.000755,0.939586,-0.342312,5.950684,1.082725,0.175648, + -0.051423,0.948155,-0.31362,5.85775,0.997026,0.236768, + 0.000755,0.939586,-0.342312,5.950684,1.082725,0.175648, + 0.525316,0.261332,-0.809783,5.884856,1.062202,0.249545, + 0.525316,0.261332,-0.809783,5.884856,1.062202,0.249545, + 0.811896,0.498733,0.303464,5.912147,1.117911,0.254197, + 0.603382,-0.138832,-0.785275,5.837875,1.141493,0.305184, + 0.525316,0.261332,-0.809783,5.884856,1.062202,0.249545, + 0.603382,-0.138832,-0.785275,5.837875,1.141493,0.305184, + 0.204286,0.745568,-0.634347,5.800778,1.078596,0.31945, + 0.204286,0.745568,-0.634347,5.800778,1.078596,0.31945, + 0.603382,-0.138832,-0.785275,5.837875,1.141493,0.305184, + 0.335985,-0.093512,-0.937214,5.77341,1.225861,0.323025, + 0.204286,0.745568,-0.634347,5.800778,1.078596,0.31945, + 0.335985,-0.093512,-0.937214,5.77341,1.225861,0.323025, + 0.609817,0.770093,0.187296,5.672187,1.164767,0.35408, + 0.609817,0.770093,0.187296,5.672187,1.164767,0.35408, + 0.335985,-0.093512,-0.937214,5.77341,1.225861,0.323025, + 0.104604,0.236958,-0.965872,5.764774,1.279824,0.308562, + 0.609817,0.770093,0.187296,5.672187,1.164767,0.35408, + 0.104604,0.236958,-0.965872,5.764774,1.279824,0.308562, + 0.563605,0.822456,0.076915,5.681726,1.282503,0.333871, + 0.563605,0.822456,0.076915,5.681726,1.282503,0.333871, + 0.104604,0.236958,-0.965872,5.764774,1.279824,0.308562, + -0.0511,0.977083,-0.206633,5.783731,1.341471,0.28459, + 0.563605,0.822456,0.076915,5.681726,1.282503,0.333871, + -0.0511,0.977083,-0.206633,5.783731,1.341471,0.28459, + -0.497134,0.140474,0.856227,5.710154,1.360653,0.290072, + -0.163152,0.699849,-0.695408,5.681086,1.054964,0.35586, + 0.288171,0.239223,-0.927216,5.763952,1.062109,0.338641, + -0.000715,-0.295728,-0.955272,5.690122,1.092917,0.37085, + -0.000715,-0.295728,-0.955272,5.690122,1.092917,0.37085, + 0.288171,0.239223,-0.927216,5.763952,1.062109,0.338641, + 0.204286,0.745568,-0.634347,5.800778,1.078596,0.31945, + -0.000715,-0.295728,-0.955272,5.690122,1.092917,0.37085, + 0.204286,0.745568,-0.634347,5.800778,1.078596,0.31945, + 0.609817,0.770093,0.187296,5.672187,1.164767,0.35408, + -0.090939,0.953561,-0.287143,5.598282,1.094735,0.386994, + -0.000715,-0.295728,-0.955272,5.690122,1.092917,0.37085, + 0.609817,0.770093,0.187296,5.672187,1.164767,0.35408, + -0.090939,0.953561,-0.287143,5.598282,1.094735,0.386994, + 0.609817,0.770093,0.187296,5.672187,1.164767,0.35408, + 0.381066,0.919021,0.100938,5.580797,1.174135,0.351054, + 0.651262,0.697944,0.297879,5.47963,1.11131,0.364188, + -0.090939,0.953561,-0.287143,5.598282,1.094735,0.386994, + 0.381066,0.919021,0.100938,5.580797,1.174135,0.351054, + 0.008972,0.708004,-0.706152,5.470775,1.009574,0.355371, + -0.090939,0.953561,-0.287143,5.598282,1.094735,0.386994, + 0.651262,0.697944,0.297879,5.47963,1.11131,0.364188, + 0.809878,-0.450756,0.375387,5.580223,1.04747,0.372696, + -0.163152,0.699849,-0.695408,5.681086,1.054964,0.35586, + -0.000715,-0.295728,-0.955272,5.690122,1.092917,0.37085, + 0.809878,-0.450756,0.375387,5.580223,1.04747,0.372696, + -0.000715,-0.295728,-0.955272,5.690122,1.092917,0.37085, + -0.090939,0.953561,-0.287143,5.598282,1.094735,0.386994, + -0.01139,0.953897,-0.299918,5.580727,0.99933,0.349867, + -0.011269,-0.268801,-0.96313,5.672385,1.007694,0.341778, + -0.163152,0.699849,-0.695408,5.681086,1.054964,0.35586, + -0.01139,0.953897,-0.299918,5.580727,0.99933,0.349867, + -0.163152,0.699849,-0.695408,5.681086,1.054964,0.35586, + 0.809878,-0.450756,0.375387,5.580223,1.04747,0.372696, + -0.090939,0.953561,-0.287143,5.598282,1.094735,0.386994, + 0.008972,0.708004,-0.706152,5.470775,1.009574,0.355371, + 0.809878,-0.450756,0.375387,5.580223,1.04747,0.372696, + 0.008972,0.708004,-0.706152,5.470775,1.009574,0.355371, + -0.151742,0.274295,-0.949598,5.535184,0.98018,0.341257, + -0.01139,0.953897,-0.299918,5.580727,0.99933,0.349867, + 0.008972,0.708004,-0.706152,5.470775,1.009574,0.355371, + -0.01139,0.953897,-0.299918,5.580727,0.99933,0.349867, + 0.809878,-0.450756,0.375387,5.580223,1.04747,0.372696, + 0.795507,-0.586003,0.154171,5.425352,1.035967,0.34272, + 0.008972,0.708004,-0.706152,5.470775,1.009574,0.355371, + 0.651262,0.697944,0.297879,5.47963,1.11131,0.364188, + 0.795507,-0.586003,0.154171,5.425352,1.035967,0.34272, + 0.651262,0.697944,0.297879,5.47963,1.11131,0.364188, + -0.317809,0.237298,0.91798,5.388455,1.119419,0.351883, + 0.743898,-0.655713,-0.129057,5.434594,0.970412,0.330823, + 0.008972,0.708004,-0.706152,5.470775,1.009574,0.355371, + 0.795507,-0.586003,0.154171,5.425352,1.035967,0.34272, + 0.743898,-0.655713,-0.129057,5.434594,0.970412,0.330823, + -0.151742,0.274295,-0.949598,5.535184,0.98018,0.341257, + 0.008972,0.708004,-0.706152,5.470775,1.009574,0.355371, + 0.743898,-0.655713,-0.129057,5.434594,0.970412,0.330823, + 0.083641,-0.81989,0.566378,5.480649,0.941387,0.316248, + -0.151742,0.274295,-0.949598,5.535184,0.98018,0.341257, + 0.042118,-0.881893,0.469564,5.379461,1.045817,0.349748, + 0.795507,-0.586003,0.154171,5.425352,1.035967,0.34272, + -0.317809,0.237298,0.91798,5.388455,1.119419,0.351883, + 0.713982,0.301535,0.631907,5.370709,0.980272,0.337432, + 0.743898,-0.655713,-0.129057,5.434594,0.970412,0.330823, + 0.795507,-0.586003,0.154171,5.425352,1.035967,0.34272, + 0.713982,0.301535,0.631907,5.370709,0.980272,0.337432, + 0.795507,-0.586003,0.154171,5.425352,1.035967,0.34272, + 0.042118,-0.881893,0.469564,5.379461,1.045817,0.349748, + 0.086688,-0.887002,0.453556,5.373646,0.885375,0.20884, + 0.083641,-0.81989,0.566378,5.480649,0.941387,0.316248, + 0.743898,-0.655713,-0.129057,5.434594,0.970412,0.330823, + 0.086688,-0.887002,0.453556,5.373646,0.885375,0.20884, + 0.743898,-0.655713,-0.129057,5.434594,0.970412,0.330823, + 0.713982,0.301535,0.631907,5.370709,0.980272,0.337432, + 0.086688,-0.887002,0.453556,5.373646,0.885375,0.20884, + 0.21141,-0.953268,0.215838,5.511556,0.863525,0.177613, + 0.176955,-0.903058,0.391373,5.546347,0.916044,0.246782, + 0.086688,-0.887002,0.453556,5.373646,0.885375,0.20884, + 0.176955,-0.903058,0.391373,5.546347,0.916044,0.246782, + 0.083641,-0.81989,0.566378,5.480649,0.941387,0.316248, + 0.21141,-0.953268,0.215838,5.511556,0.863525,0.177613, + 0.288841,-0.745301,-0.600914,5.60337,0.852748,0.162335, + 0.571342,-0.680689,-0.45851,5.638369,0.904402,0.222548, + 0.21141,-0.953268,0.215838,5.511556,0.863525,0.177613, + 0.571342,-0.680689,-0.45851,5.638369,0.904402,0.222548, + 0.176955,-0.903058,0.391373,5.546347,0.916044,0.246782, + 0.288841,-0.745301,-0.600914,5.60337,0.852748,0.162335, + 0.237421,-0.963021,0.127366,5.70463,0.849158,0.12813, + 0.388502,-0.6643,-0.63857,5.748613,0.92049,0.205099, + 0.288841,-0.745301,-0.600914,5.60337,0.852748,0.162335, + 0.388502,-0.6643,-0.63857,5.748613,0.92049,0.205099, + 0.571342,-0.680689,-0.45851,5.638369,0.904402,0.222548, + 0.157921,-0.851177,-0.500559,5.241466,1.040469,0.383965, + 0.042118,-0.881893,0.469564,5.379461,1.045817,0.349748, + -0.317809,0.237298,0.91798,5.388455,1.119419,0.351883, + 0.157921,-0.851177,-0.500559,5.241466,1.040469,0.383965, + -0.317809,0.237298,0.91798,5.388455,1.119419,0.351883, + 0.009824,-0.644035,0.764933,5.250485,1.123029,0.385234, + 0.254106,-0.95176,0.171999,5.223571,0.974029,0.362117, + 0.713982,0.301535,0.631907,5.370709,0.980272,0.337432, + 0.042118,-0.881893,0.469564,5.379461,1.045817,0.349748, + 0.254106,-0.95176,0.171999,5.223571,0.974029,0.362117, + 0.042118,-0.881893,0.469564,5.379461,1.045817,0.349748, + 0.157921,-0.851177,-0.500559,5.241466,1.040469,0.383965, + 0.165259,-0.797056,-0.580854,5.299005,0.908991,0.260177, + 0.086688,-0.887002,0.453556,5.373646,0.885375,0.20884, + 0.713982,0.301535,0.631907,5.370709,0.980272,0.337432, + 0.243744,-0.944481,0.220328,5.197562,0.922406,0.302473, + 0.165259,-0.797056,-0.580854,5.299005,0.908991,0.260177, + 0.713982,0.301535,0.631907,5.370709,0.980272,0.337432, + 0.243744,-0.944481,0.220328,5.197562,0.922406,0.302473, + 0.713982,0.301535,0.631907,5.370709,0.980272,0.337432, + 0.254106,-0.95176,0.171999,5.223571,0.974029,0.362117, + 0.20994,-0.930128,0.301309,5.851404,0.929008,0.105362, + -0.05208,-0.715695,0.696469,5.797411,0.880032,0.072306, + 0.953994,-0.299798,-0.004126,5.78079,0.891286,0.001059, + 0.20994,-0.930128,0.301309,5.851404,0.929008,0.105362, + 0.953994,-0.299798,-0.004126,5.78079,0.891286,0.001059, + 0.997356,-0.072614,-0.002907,5.836005,0.945722,0.001092, + 0.388502,-0.6643,-0.63857,5.748613,0.92049,0.205099, + 0.237421,-0.963021,0.127366,5.70463,0.849158,0.12813, + -0.05208,-0.715695,0.696469,5.797411,0.880032,0.072306, + 0.388502,-0.6643,-0.63857,5.748613,0.92049,0.205099, + -0.05208,-0.715695,0.696469,5.797411,0.880032,0.072306, + 0.20994,-0.930128,0.301309,5.851404,0.929008,0.105362, + 0.874313,-0.485341,-0.004579,5.679621,0.8395,0.000985, + 0.953994,-0.299798,-0.004126,5.78079,0.891286,0.001059, + -0.05208,-0.715695,0.696469,5.797411,0.880032,0.072306, + 0.237421,-0.963021,0.127366,5.70463,0.849158,0.12813, + 0.287073,-0.905921,0.311283,5.568745,0.834653,0.07139, + 0.874313,-0.485341,-0.004579,5.679621,0.8395,0.000985, + 0.237421,-0.963021,0.127366,5.70463,0.849158,0.12813, + 0.874313,-0.485341,-0.004579,5.679621,0.8395,0.000985, + -0.05208,-0.715695,0.696469,5.797411,0.880032,0.072306, + 0.287073,-0.905921,0.311283,5.568745,0.834653,0.07139, + 0.84332,-0.537393,-0.004381,5.579253,0.837796,0.000896, + 0.874313,-0.485341,-0.004579,5.679621,0.8395,0.000985, + 0.288841,-0.745301,-0.600914,5.60337,0.852748,0.162335, + 0.267121,-0.895396,0.356249,5.449164,0.847535,0.103909, + 0.287073,-0.905921,0.311283,5.568745,0.834653,0.07139, + 0.288841,-0.745301,-0.600914,5.60337,0.852748,0.162335, + 0.287073,-0.905921,0.311283,5.568745,0.834653,0.07139, + 0.237421,-0.963021,0.127366,5.70463,0.849158,0.12813, + -0.501598,-0.526154,0.686704,5.137075,0.824518,0.144842, + 0.598791,-0.8009,-0.003109,5.112563,0.840686,0.00048, + 0.832605,-0.553861,-0.002629,5.213434,0.856784,0.000565, + -0.501598,-0.526154,0.686704,5.137075,0.824518,0.144842, + 0.832605,-0.553861,-0.002629,5.213434,0.856784,0.000565, + -0.290459,-0.499809,0.815981,5.247762,0.848549,0.108546, + 0.21141,-0.953268,0.215838,5.511556,0.863525,0.177613, + -0.538845,-0.659239,0.524452,5.3569,0.85112,0.138324, + 0.267121,-0.895396,0.356249,5.449164,0.847535,0.103909, + 0.21141,-0.953268,0.215838,5.511556,0.863525,0.177613, + 0.267121,-0.895396,0.356249,5.449164,0.847535,0.103909, + 0.288841,-0.745301,-0.600914,5.60337,0.852748,0.162335, + 0.086688,-0.887002,0.453556,5.373646,0.885375,0.20884, + -0.53682,-0.608254,0.58468,5.26443,0.855571,0.181694, + -0.538845,-0.659239,0.524452,5.3569,0.85112,0.138324, + 0.086688,-0.887002,0.453556,5.373646,0.885375,0.20884, + -0.538845,-0.659239,0.524452,5.3569,0.85112,0.138324, + 0.21141,-0.953268,0.215838,5.511556,0.863525,0.177613, + -0.290459,-0.499809,0.815981,5.247762,0.848549,0.108546, + 0.832605,-0.553861,-0.002629,5.213434,0.856784,0.000565, + 0.224122,-0.97456,-0.001209,5.323232,0.866039,0.00066, + 0.267121,-0.895396,0.356249,5.449164,0.847535,0.103909, + -0.020035,-0.999799,-0.000148,5.469641,0.838722,0.000798, + 0.84332,-0.537393,-0.004381,5.579253,0.837796,0.000896, + 0.267121,-0.895396,0.356249,5.449164,0.847535,0.103909, + 0.84332,-0.537393,-0.004381,5.579253,0.837796,0.000896, + 0.287073,-0.905921,0.311283,5.568745,0.834653,0.07139, + -0.290459,-0.499809,0.815981,5.247762,0.848549,0.108546, + 0.224122,-0.97456,-0.001209,5.323232,0.866039,0.00066, + -0.020035,-0.999799,-0.000148,5.469641,0.838722,0.000798, + -0.290459,-0.499809,0.815981,5.247762,0.848549,0.108546, + -0.020035,-0.999799,-0.000148,5.469641,0.838722,0.000798, + 0.267121,-0.895396,0.356249,5.449164,0.847535,0.103909, + -0.290459,-0.499809,0.815981,5.247762,0.848549,0.108546, + 0.267121,-0.895396,0.356249,5.449164,0.847535,0.103909, + -0.538845,-0.659239,0.524452,5.3569,0.85112,0.138324, + -0.53682,-0.608254,0.58468,5.26443,0.855571,0.181694, + -0.290459,-0.499809,0.815981,5.247762,0.848549,0.108546, + -0.538845,-0.659239,0.524452,5.3569,0.85112,0.138324, + -0.53682,-0.608254,0.58468,5.26443,0.855571,0.181694, + 0.086688,-0.887002,0.453556,5.373646,0.885375,0.20884, + 0.165259,-0.797056,-0.580854,5.299005,0.908991,0.260177, + -0.635877,0.324329,0.700337,5.153735,0.831575,0.218348, + -0.53682,-0.608254,0.58468,5.26443,0.855571,0.181694, + 0.165259,-0.797056,-0.580854,5.299005,0.908991,0.260177, + -0.635877,0.324329,0.700337,5.153735,0.831575,0.218348, + 0.165259,-0.797056,-0.580854,5.299005,0.908991,0.260177, + 0.243744,-0.944481,0.220328,5.197562,0.922406,0.302473, + -0.635877,0.324329,0.700337,5.153735,0.831575,0.218348, + -0.501598,-0.526154,0.686704,5.137075,0.824518,0.144842, + -0.290459,-0.499809,0.815981,5.247762,0.848549,0.108546, + -0.635877,0.324329,0.700337,5.153735,0.831575,0.218348, + -0.290459,-0.499809,0.815981,5.247762,0.848549,0.108546, + -0.53682,-0.608254,0.58468,5.26443,0.855571,0.181694, + -0.376273,-0.140159,0.915846,4.963526,0.797382,0.14344, + 0.124158,-0.992262,-0.000543,4.920855,0.812339,0.000318, + 0.598791,-0.8009,-0.003109,5.112563,0.840686,0.00048, + -0.376273,-0.140159,0.915846,4.963526,0.797382,0.14344, + 0.598791,-0.8009,-0.003109,5.112563,0.840686,0.00048, + -0.501598,-0.526154,0.686704,5.137075,0.824518,0.144842, + -0.508574,-0.111047,0.853827,4.99671,0.81056,0.280771, + -0.376273,-0.140159,0.915846,4.963526,0.797382,0.14344, + -0.501598,-0.526154,0.686704,5.137075,0.824518,0.144842, + -0.508574,-0.111047,0.853827,4.99671,0.81056,0.280771, + -0.501598,-0.526154,0.686704,5.137075,0.824518,0.144842, + -0.635877,0.324329,0.700337,5.153735,0.831575,0.218348, + -0.86136,-0.239794,0.447836,4.66969,0.738163,0.188296, + -0.376273,-0.140159,0.915846,4.963526,0.797382,0.14344, + -0.508574,-0.111047,0.853827,4.99671,0.81056,0.280771, + -0.86136,-0.239794,0.447836,4.66969,0.738163,0.188296, + -0.508574,-0.111047,0.853827,4.99671,0.81056,0.280771, + -0.724544,-0.128977,0.677054,4.712067,0.770512,0.333393, + -0.86136,-0.239794,0.447836,4.66969,0.738163,0.188296, + 0.157494,-0.98752,-0.000465,4.655453,0.758022,0.000098, + 0.124158,-0.992262,-0.000543,4.920855,0.812339,0.000318, + -0.86136,-0.239794,0.447836,4.66969,0.738163,0.188296, + 0.124158,-0.992262,-0.000543,4.920855,0.812339,0.000318, + -0.376273,-0.140159,0.915846,4.963526,0.797382,0.14344, + -0.508574,-0.111047,0.853827,4.99671,0.81056,0.280771, + -0.635877,0.324329,0.700337,5.153735,0.831575,0.218348, + 0.243744,-0.944481,0.220328,5.197562,0.922406,0.302473, + -0.508574,-0.111047,0.853827,4.99671,0.81056,0.280771, + 0.243744,-0.944481,0.220328,5.197562,0.922406,0.302473, + -0.903777,-0.182749,0.387027,5.004627,0.908637,0.345273, + -0.724544,-0.128977,0.677054,4.712067,0.770512,0.333393, + -0.508574,-0.111047,0.853827,4.99671,0.81056,0.280771, + -0.903777,-0.182749,0.387027,5.004627,0.908637,0.345273, + -0.724544,-0.128977,0.677054,4.712067,0.770512,0.333393, + -0.903777,-0.182749,0.387027,5.004627,0.908637,0.345273, + -0.911341,0.002265,0.411646,4.728809,0.878731,0.405801, + -0.566117,0.431683,0.702254,5.021254,0.951308,0.405567, + 0.254106,-0.95176,0.171999,5.223571,0.974029,0.362117, + 0.157921,-0.851177,-0.500559,5.241466,1.040469,0.383965, + -0.566117,0.431683,0.702254,5.021254,0.951308,0.405567, + 0.157921,-0.851177,-0.500559,5.241466,1.040469,0.383965, + -0.77316,0.344902,0.532228,5.011084,1.06677,0.458562, + -0.566117,0.431683,0.702254,5.021254,0.951308,0.405567, + -0.903777,-0.182749,0.387027,5.004627,0.908637,0.345273, + 0.243744,-0.944481,0.220328,5.197562,0.922406,0.302473, + -0.566117,0.431683,0.702254,5.021254,0.951308,0.405567, + 0.243744,-0.944481,0.220328,5.197562,0.922406,0.302473, + 0.254106,-0.95176,0.171999,5.223571,0.974029,0.362117, + -0.383862,0.612068,0.691392,4.74325,1.05921,0.563421, + -0.77316,0.344902,0.532228,5.011084,1.06677,0.458562, + -0.023775,-0.598435,0.800818,4.991713,1.163096,0.504149, + -0.383862,0.612068,0.691392,4.74325,1.05921,0.563421, + -0.023775,-0.598435,0.800818,4.991713,1.163096,0.504149, + 0.200825,-0.971974,0.122213,4.733657,1.227371,0.592883, + -0.091679,0.768658,0.633057,4.744871,0.950945,0.491082, + -0.566117,0.431683,0.702254,5.021254,0.951308,0.405567, + -0.77316,0.344902,0.532228,5.011084,1.06677,0.458562, + -0.091679,0.768658,0.633057,4.744871,0.950945,0.491082, + -0.77316,0.344902,0.532228,5.011084,1.06677,0.458562, + -0.383862,0.612068,0.691392,4.74325,1.05921,0.563421, + -0.911341,0.002265,0.411646,4.728809,0.878731,0.405801, + -0.903777,-0.182749,0.387027,5.004627,0.908637,0.345273, + -0.566117,0.431683,0.702254,5.021254,0.951308,0.405567, + -0.911341,0.002265,0.411646,4.728809,0.878731,0.405801, + -0.566117,0.431683,0.702254,5.021254,0.951308,0.405567, + -0.091679,0.768658,0.633057,4.744871,0.950945,0.491082, + -0.911194,0.285551,0.296961,4.567896,1.149805,0.642484, + -0.383862,0.612068,0.691392,4.74325,1.05921,0.563421, + 0.200825,-0.971974,0.122213,4.733657,1.227371,0.592883, + -0.911194,0.285551,0.296961,4.567896,1.149805,0.642484, + 0.200825,-0.971974,0.122213,4.733657,1.227371,0.592883, + 0.123418,-0.784469,0.607763,4.641547,1.285422,0.622034, + -0.931592,0.319003,0.174278,4.496191,1.024566,0.579491, + -0.091679,0.768658,0.633057,4.744871,0.950945,0.491082, + -0.383862,0.612068,0.691392,4.74325,1.05921,0.563421, + -0.931592,0.319003,0.174278,4.496191,1.024566,0.579491, + -0.383862,0.612068,0.691392,4.74325,1.05921,0.563421, + -0.911194,0.285551,0.296961,4.567896,1.149805,0.642484, + -0.895156,0.397807,0.201112,4.416475,0.921264,0.458839, + -0.911341,0.002265,0.411646,4.728809,0.878731,0.405801, + -0.091679,0.768658,0.633057,4.744871,0.950945,0.491082, + -0.895156,0.397807,0.201112,4.416475,0.921264,0.458839, + -0.091679,0.768658,0.633057,4.744871,0.950945,0.491082, + -0.931592,0.319003,0.174278,4.496191,1.024566,0.579491, + -0.742898,0.572423,0.347036,4.297891,0.911506,0.447987, + -0.821562,0.369566,0.434117,4.399629,0.850459,0.391855, + -0.895156,0.397807,0.201112,4.416475,0.921264,0.458839, + -0.742898,0.572423,0.347036,4.297891,0.911506,0.447987, + -0.895156,0.397807,0.201112,4.416475,0.921264,0.458839, + -0.885175,0.439902,0.1515,4.333503,0.951176,0.481517, + -0.659696,0.567802,0.492343,4.359048,0.700414,0.166651, + 0.000801,-1,-0.000539,4.380854,0.704574,-0.00013, + 0.157494,-0.98752,-0.000465,4.655453,0.758022,0.000098, + -0.659696,0.567802,0.492343,4.359048,0.700414,0.166651, + 0.157494,-0.98752,-0.000465,4.655453,0.758022,0.000098, + -0.86136,-0.239794,0.447836,4.66969,0.738163,0.188296, + 0.11638,0.680311,0.723624,4.319799,0.731007,0.291212, + -0.659696,0.567802,0.492343,4.359048,0.700414,0.166651, + -0.86136,-0.239794,0.447836,4.66969,0.738163,0.188296, + 0.11638,0.680311,0.723624,4.319799,0.731007,0.291212, + -0.86136,-0.239794,0.447836,4.66969,0.738163,0.188296, + -0.724544,-0.128977,0.677054,4.712067,0.770512,0.333393, + 0.11638,0.680311,0.723624,4.319799,0.731007,0.291212, + -0.724544,-0.128977,0.677054,4.712067,0.770512,0.333393, + -0.821562,0.369566,0.434117,4.399629,0.850459,0.391855, + -0.742898,0.572423,0.347036,4.297891,0.911506,0.447987, + 0.206279,0.744917,0.634467,4.216374,0.852328,0.405873, + 0.11638,0.680311,0.723624,4.319799,0.731007,0.291212, + -0.742898,0.572423,0.347036,4.297891,0.911506,0.447987, + 0.11638,0.680311,0.723624,4.319799,0.731007,0.291212, + -0.821562,0.369566,0.434117,4.399629,0.850459,0.391855, + -0.724544,-0.128977,0.677054,4.712067,0.770512,0.333393, + -0.911341,0.002265,0.411646,4.728809,0.878731,0.405801, + -0.895156,0.397807,0.201112,4.416475,0.921264,0.458839, + -0.724544,-0.128977,0.677054,4.712067,0.770512,0.333393, + -0.895156,0.397807,0.201112,4.416475,0.921264,0.458839, + -0.821562,0.369566,0.434117,4.399629,0.850459,0.391855, + -0.476949,0.871027,0.117605,4.366867,1.131136,0.630581, + -0.931592,0.319003,0.174278,4.496191,1.024566,0.579491, + -0.911194,0.285551,0.296961,4.567896,1.149805,0.642484, + -0.476949,0.871027,0.117605,4.366867,1.131136,0.630581, + -0.911194,0.285551,0.296961,4.567896,1.149805,0.642484, + -0.395804,0.901672,0.174144,4.449011,1.260929,0.647431, + 0.206279,0.744917,0.634467,4.216374,0.852328,0.405873, + -0.742898,0.572423,0.347036,4.297891,0.911506,0.447987, + -0.590367,0.807126,-0.003753,4.141189,1.008775,0.499342, + -0.742898,0.572423,0.347036,4.297891,0.911506,0.447987, + -0.885175,0.439902,0.1515,4.333503,0.951176,0.481517, + -0.594389,0.803108,0.041468,4.277227,1.077746,0.550819, + -0.742898,0.572423,0.347036,4.297891,0.911506,0.447987, + -0.594389,0.803108,0.041468,4.277227,1.077746,0.550819, + -0.590367,0.807126,-0.003753,4.141189,1.008775,0.499342, + -0.590367,0.807126,-0.003753,4.141189,1.008775,0.499342, + -0.594389,0.803108,0.041468,4.277227,1.077746,0.550819, + -0.091114,0.94565,0.312162,4.175444,1.350332,0.613988, + -0.590367,0.807126,-0.003753,4.141189,1.008775,0.499342, + -0.091114,0.94565,0.312162,4.175444,1.350332,0.613988, + -0.610894,0.790229,-0.048447,4.085564,1.288885,0.544406, + -0.895156,0.397807,0.201112,4.416475,0.921264,0.458839, + -0.931592,0.319003,0.174278,4.496191,1.024566,0.579491, + -0.885175,0.439902,0.1515,4.333503,0.951176,0.481517, + -0.885175,0.439902,0.1515,4.333503,0.951176,0.481517, + -0.931592,0.319003,0.174278,4.496191,1.024566,0.579491, + -0.476949,0.871027,0.117605,4.366867,1.131136,0.630581, + -0.885175,0.439902,0.1515,4.333503,0.951176,0.481517, + -0.476949,0.871027,0.117605,4.366867,1.131136,0.630581, + -0.594389,0.803108,0.041468,4.277227,1.077746,0.550819, + -0.594389,0.803108,0.041468,4.277227,1.077746,0.550819, + -0.476949,0.871027,0.117605,4.366867,1.131136,0.630581, + -0.216454,0.960138,0.176868,4.247733,1.381058,0.649596, + -0.594389,0.803108,0.041468,4.277227,1.077746,0.550819, + -0.216454,0.960138,0.176868,4.247733,1.381058,0.649596, + -0.091114,0.94565,0.312162,4.175444,1.350332,0.613988, + -0.476949,0.871027,0.117605,4.366867,1.131136,0.630581, + -0.395804,0.901672,0.174144,4.449011,1.260929,0.647431, + -0.283495,0.953867,0.098839,4.329607,1.464801,0.661485, + -0.476949,0.871027,0.117605,4.366867,1.131136,0.630581, + -0.283495,0.953867,0.098839,4.329607,1.464801,0.661485, + -0.216454,0.960138,0.176868,4.247733,1.381058,0.649596, + -0.395804,0.901672,0.174144,4.449011,1.260929,0.647431, + 0.050019,-0.552867,0.831767,4.522247,1.398278,0.644892, + 0.037801,-0.082839,0.995846,4.430999,1.535753,0.638888, + -0.395804,0.901672,0.174144,4.449011,1.260929,0.647431, + 0.037801,-0.082839,0.995846,4.430999,1.535753,0.638888, + -0.283495,0.953867,0.098839,4.329607,1.464801,0.661485, + -0.283495,0.953867,0.098839,4.329607,1.464801,0.661485, + 0.037801,-0.082839,0.995846,4.430999,1.535753,0.638888, + -0.196146,-0.333078,0.922272,4.404221,1.662433,0.61661, + -0.283495,0.953867,0.098839,4.329607,1.464801,0.661485, + -0.196146,-0.333078,0.922272,4.404221,1.662433,0.61661, + -0.421166,0.906102,0.039982,4.312225,1.683392,0.639944, + -0.421166,0.906102,0.039982,4.312225,1.683392,0.639944, + -0.196146,-0.333078,0.922272,4.404221,1.662433,0.61661, + -0.106358,-0.394397,0.912765,4.38638,1.770868,0.596666, + -0.421166,0.906102,0.039982,4.312225,1.683392,0.639944, + -0.106358,-0.394397,0.912765,4.38638,1.770868,0.596666, + -0.557881,0.828586,-0.047048,4.303615,1.799914,0.610388, + -0.557881,0.828586,-0.047048,4.303615,1.799914,0.610388, + -0.106358,-0.394397,0.912765,4.38638,1.770868,0.596666, + -0.277696,-0.435918,0.856073,4.377095,1.871713,0.595743, + -0.557881,0.828586,-0.047048,4.303615,1.799914,0.610388, + -0.277696,-0.435918,0.856073,4.377095,1.871713,0.595743, + -0.536419,0.710997,0.454685,4.304562,1.906537,0.572242, + 0.055369,0.916343,0.396547,4.221814,1.660769,0.59409, + -0.421166,0.906102,0.039982,4.312225,1.683392,0.639944, + -0.557881,0.828586,-0.047048,4.303615,1.799914,0.610388, + 0.055369,0.916343,0.396547,4.221814,1.660769,0.59409, + -0.557881,0.828586,-0.047048,4.303615,1.799914,0.610388, + -0.678336,0.658323,0.326299,4.240116,1.770049,0.583946, + -0.216454,0.960138,0.176868,4.247733,1.381058,0.649596, + -0.283495,0.953867,0.098839,4.329607,1.464801,0.661485, + -0.421166,0.906102,0.039982,4.312225,1.683392,0.639944, + -0.216454,0.960138,0.176868,4.247733,1.381058,0.649596, + -0.421166,0.906102,0.039982,4.312225,1.683392,0.639944, + 0.055369,0.916343,0.396547,4.221814,1.660769,0.59409, + -0.091114,0.94565,0.312162,4.175444,1.350332,0.613988, + -0.216454,0.960138,0.176868,4.247733,1.381058,0.649596, + 0.055369,0.916343,0.396547,4.221814,1.660769,0.59409, + -0.091114,0.94565,0.312162,4.175444,1.350332,0.613988, + 0.055369,0.916343,0.396547,4.221814,1.660769,0.59409, + 0.090337,0.942369,0.32215,4.121121,1.614451,0.587188, + -0.610894,0.790229,-0.048447,4.085564,1.288885,0.544406, + -0.091114,0.94565,0.312162,4.175444,1.350332,0.613988, + 0.090337,0.942369,0.32215,4.121121,1.614451,0.587188, + -0.610894,0.790229,-0.048447,4.085564,1.288885,0.544406, + 0.090337,0.942369,0.32215,4.121121,1.614451,0.587188, + -0.560402,0.735791,0.380211,4.067576,1.572668,0.534997, + 0.090337,0.942369,0.32215,4.121121,1.614451,0.587188, + 0.055369,0.916343,0.396547,4.221814,1.660769,0.59409, + -0.678336,0.658323,0.326299,4.240116,1.770049,0.583946, + 0.090337,0.942369,0.32215,4.121121,1.614451,0.587188, + -0.678336,0.658323,0.326299,4.240116,1.770049,0.583946, + -0.641133,0.599375,0.479267,4.148883,1.759918,0.573765, + -0.560402,0.735791,0.380211,4.067576,1.572668,0.534997, + 0.090337,0.942369,0.32215,4.121121,1.614451,0.587188, + -0.641133,0.599375,0.479267,4.148883,1.759918,0.573765, + -0.560402,0.735791,0.380211,4.067576,1.572668,0.534997, + -0.641133,0.599375,0.479267,4.148883,1.759918,0.573765, + -0.760994,0.140163,0.633437,4.076852,1.746601,0.527436, + 0.203778,-0.389736,0.898098,4.83289,2.262727,0.283787, + -0.026148,0.006311,0.999638,4.971394,2.146686,0.224781, + -0.989689,-0.143234,0,4.912303,2.162645,-0.00009, + 0.203778,-0.389736,0.898098,4.83289,2.262727,0.283787, + -0.989689,-0.143234,0,4.912303,2.162645,-0.00009, + -0.965284,-0.261201,0,4.747988,2.300163,-0.000276, + 0.204472,-0.587725,0.782797,5.156645,1.942902,0.119993, + -0.998597,-0.052951,0,5.177545,1.932323,0.000214, + -0.941169,-0.337937,0,5.04969,2.032731,0.000071, + -0.241533,0.200654,0.949421,5.687035,1.499636,0.110765, + -0.31398,0.125786,0.94106,5.741781,1.463956,0.124891, + 0.694651,0.719347,0.000019,5.743997,1.482739,0.000851, + -0.241533,0.200654,0.949421,5.687035,1.499636,0.110765, + 0.694651,0.719347,0.000019,5.743997,1.482739,0.000851, + -0.026558,-0.999647,0,5.680007,1.510009,0.000786, + -0.062808,0.99609,0.062134,5.842092,1.427708,0.130724, + -0.11884,0.991349,-0.055713,5.915025,1.382159,0.13682, + -0.016213,0.999869,0,5.908842,1.388968,0.001026, + -0.062808,0.99609,0.062134,5.842092,1.427708,0.130724, + -0.016213,0.999869,0,5.908842,1.388968,0.001026, + 0.569495,0.821995,-0.000075,5.835498,1.43628,0.000946, + -0.395037,0.740118,0.544216,4.452383,2.524558,0.130255, + 0.169654,-0.985504,-0.000285,4.454962,2.523303,-0.000603, + -0.069594,-0.997575,-0.000151,4.317602,2.588926,-0.000745, + -0.395037,0.740118,0.544216,4.452383,2.524558,0.130255, + -0.069594,-0.997575,-0.000151,4.317602,2.588926,-0.000745, + -0.411843,0.771855,0.484381,4.342351,2.581176,0.140317, + -0.353793,0.870619,0.341838,4.440143,2.510529,0.269164, + -0.395037,0.740118,0.544216,4.452383,2.524558,0.130255, + -0.411843,0.771855,0.484381,4.342351,2.581176,0.140317, + -0.353793,0.870619,0.341838,4.440143,2.510529,0.269164, + -0.411843,0.771855,0.484381,4.342351,2.581176,0.140317, + -0.330516,0.821242,0.465104,4.332083,2.586481,0.194917, + -0.929249,-0.009268,0.369337,4.429895,2.495758,0.306894, + -0.353793,0.870619,0.341838,4.440143,2.510529,0.269164, + -0.330516,0.821242,0.465104,4.332083,2.586481,0.194917, + -0.929249,-0.009268,0.369337,4.429895,2.495758,0.306894, + -0.330516,0.821242,0.465104,4.332083,2.586481,0.194917, + -0.718934,0.608496,0.335955,4.339601,2.592642,0.258891, + -0.411843,0.771855,0.484381,4.342351,2.581176,0.140317, + -0.069594,-0.997575,-0.000151,4.317602,2.588926,-0.000745, + 0.172357,-0.985035,-0.000083,4.189883,2.606916,-0.000863, + -0.411843,0.771855,0.484381,4.342351,2.581176,0.140317, + 0.172357,-0.985035,-0.000083,4.189883,2.606916,-0.000863, + -0.144656,0.947613,0.284787,4.187258,2.590221,0.135844, + -0.330516,0.821242,0.465104,4.332083,2.586481,0.194917, + -0.411843,0.771855,0.484381,4.342351,2.581176,0.140317, + -0.144656,0.947613,0.284787,4.187258,2.590221,0.135844, + -0.330516,0.821242,0.465104,4.332083,2.586481,0.194917, + -0.144656,0.947613,0.284787,4.187258,2.590221,0.135844, + -0.364192,0.890167,0.273801,4.203325,2.589186,0.219164, + -0.718934,0.608496,0.335955,4.339601,2.592642,0.258891, + -0.330516,0.821242,0.465104,4.332083,2.586481,0.194917, + -0.364192,0.890167,0.273801,4.203325,2.589186,0.219164, + -0.718934,0.608496,0.335955,4.339601,2.592642,0.258891, + -0.364192,0.890167,0.273801,4.203325,2.589186,0.219164, + -0.719327,0.568276,0.399538,4.211652,2.602538,0.264011, + -0.130291,0.991051,0.029017,4.328606,2.563996,0.343892, + -0.718934,0.608496,0.335955,4.339601,2.592642,0.258891, + -0.719327,0.568276,0.399538,4.211652,2.602538,0.264011, + -0.130291,0.991051,0.029017,4.328606,2.563996,0.343892, + -0.719327,0.568276,0.399538,4.211652,2.602538,0.264011, + -0.904972,-0.026555,0.424641,4.209941,2.600612,0.337597, + -0.501953,0.842502,0.195534,4.410844,2.500167,0.351972, + -0.929249,-0.009268,0.369337,4.429895,2.495758,0.306894, + -0.718934,0.608496,0.335955,4.339601,2.592642,0.258891, + -0.501953,0.842502,0.195534,4.410844,2.500167,0.351972, + -0.718934,0.608496,0.335955,4.339601,2.592642,0.258891, + -0.130291,0.991051,0.029017,4.328606,2.563996,0.343892, + 0.241652,-0.897637,0.368581,4.634996,2.369115,0.140117, + -0.965284,-0.261201,0,4.747988,2.300163,-0.000276, + 0.210866,-0.977515,0.000009,4.528082,2.467537,-0.000521, + 0.170159,-0.985033,-0.027502,4.577573,2.389535,0.256196, + 0.241652,-0.897637,0.368581,4.634996,2.369115,0.140117, + 0.210866,-0.977515,0.000009,4.528082,2.467537,-0.000521, + 0.170159,-0.985033,-0.027502,4.577573,2.389535,0.256196, + 0.210866,-0.977515,0.000009,4.528082,2.467537,-0.000521, + 0.169654,-0.985504,-0.000285,4.454962,2.523303,-0.000603, + 0.170159,-0.985033,-0.027502,4.577573,2.389535,0.256196, + 0.169654,-0.985504,-0.000285,4.454962,2.523303,-0.000603, + -0.395037,0.740118,0.544216,4.452383,2.524558,0.130255, + 0.170159,-0.985033,-0.027502,4.577573,2.389535,0.256196, + -0.395037,0.740118,0.544216,4.452383,2.524558,0.130255, + -0.353793,0.870619,0.341838,4.440143,2.510529,0.269164, + 0.170159,-0.985033,-0.027502,4.577573,2.389535,0.256196, + -0.353793,0.870619,0.341838,4.440143,2.510529,0.269164, + -0.929249,-0.009268,0.369337,4.429895,2.495758,0.306894, + -0.929249,-0.009268,0.369337,4.429895,2.495758,0.306894, + -0.501953,0.842502,0.195534,4.410844,2.500167,0.351972, + -0.849668,0.488771,-0.197904,4.474318,2.418432,0.361347, + 0.170159,-0.985033,-0.027502,4.577573,2.389535,0.256196, + -0.929249,-0.009268,0.369337,4.429895,2.495758,0.306894, + -0.849668,0.488771,-0.197904,4.474318,2.418432,0.361347, + 0.231006,-0.859096,0.456717,4.472349,2.325133,0.443764, + 0.170159,-0.985033,-0.027502,4.577573,2.389535,0.256196, + -0.849668,0.488771,-0.197904,4.474318,2.418432,0.361347, + 0.361848,-0.921221,-0.142892,4.043796,2.386524,0.400392, + -0.138401,-0.989733,0.035683,4.07851,2.41181,0.472193, + 0.207048,-0.965263,0.159371,4.088356,2.510913,0.453793, + 0.361848,-0.921221,-0.142892,4.043796,2.386524,0.400392, + 0.207048,-0.965263,0.159371,4.088356,2.510913,0.453793, + 0.198783,-0.979888,0.017481,4.063205,2.509679,0.342987, + 0.3579,-0.920931,0.154253,4.035753,2.399538,0.343957, + 0.361848,-0.921221,-0.142892,4.043796,2.386524,0.400392, + 0.198783,-0.979888,0.017481,4.063205,2.509679,0.342987, + 0.3579,-0.920931,0.154253,4.035753,2.399538,0.343957, + 0.198783,-0.979888,0.017481,4.063205,2.509679,0.342987, + 0.363913,-0.931415,0.005744,4.055262,2.505284,0.297282, + 0.172357,-0.985035,-0.000083,4.189883,2.606916,-0.000863, + 0.272993,0.962016,-0.000199,4.079812,2.571649,-0.000951, + 0.579082,-0.064826,-0.812688,4.084506,2.570978,0.218168, + 0.172357,-0.985035,-0.000083,4.189883,2.606916,-0.000863, + 0.579082,-0.064826,-0.812688,4.084506,2.570978,0.218168, + -0.144656,0.947613,0.284787,4.187258,2.590221,0.135844, + -0.144656,0.947613,0.284787,4.187258,2.590221,0.135844, + 0.579082,-0.064826,-0.812688,4.084506,2.570978,0.218168, + 0.849086,-0.12151,-0.51409,4.101754,2.557092,0.265856, + -0.144656,0.947613,0.284787,4.187258,2.590221,0.135844, + 0.849086,-0.12151,-0.51409,4.101754,2.557092,0.265856, + -0.364192,0.890167,0.273801,4.203325,2.589186,0.219164, + -0.364192,0.890167,0.273801,4.203325,2.589186,0.219164, + 0.849086,-0.12151,-0.51409,4.101754,2.557092,0.265856, + 0.727891,-0.103877,-0.677779,4.100907,2.560626,0.302396, + -0.364192,0.890167,0.273801,4.203325,2.589186,0.219164, + 0.727891,-0.103877,-0.677779,4.100907,2.560626,0.302396, + -0.719327,0.568276,0.399538,4.211652,2.602538,0.264011, + -0.719327,0.568276,0.399538,4.211652,2.602538,0.264011, + 0.727891,-0.103877,-0.677779,4.100907,2.560626,0.302396, + 0.576293,-0.081905,-0.813128,4.117367,2.568514,0.3845, + -0.719327,0.568276,0.399538,4.211652,2.602538,0.264011, + 0.576293,-0.081905,-0.813128,4.117367,2.568514,0.3845, + -0.904972,-0.026555,0.424641,4.209941,2.600612,0.337597, + 0.363913,-0.931415,0.005744,4.055262,2.505284,0.297282, + 0.740815,-0.598363,-0.305214,4.029016,2.519175,0.249385, + 0.640669,-0.433938,-0.633436,4.00011,2.424158,0.313254, + 0.363913,-0.931415,0.005744,4.055262,2.505284,0.297282, + 0.640669,-0.433938,-0.633436,4.00011,2.424158,0.313254, + 0.3579,-0.920931,0.154253,4.035753,2.399538,0.343957, + -0.069267,0.997598,-0.000362,3.988172,2.489642,-0.001008, + 0.640669,-0.433938,-0.633436,4.00011,2.424158,0.313254, + 0.740815,-0.598363,-0.305214,4.029016,2.519175,0.249385, + -0.069267,0.997598,-0.000362,3.988172,2.489642,-0.001008, + 0.740815,-0.598363,-0.305214,4.029016,2.519175,0.249385, + 0.544067,0.839042,-0.000076,4.024214,2.527933,-0.000987, + 0.740815,-0.598363,-0.305214,4.029016,2.519175,0.249385, + 0.579082,-0.064826,-0.812688,4.084506,2.570978,0.218168, + 0.272993,0.962016,-0.000199,4.079812,2.571649,-0.000951, + 0.740815,-0.598363,-0.305214,4.029016,2.519175,0.249385, + 0.272993,0.962016,-0.000199,4.079812,2.571649,-0.000951, + 0.544067,0.839042,-0.000076,4.024214,2.527933,-0.000987, + 0.363913,-0.931415,0.005744,4.055262,2.505284,0.297282, + 0.849086,-0.12151,-0.51409,4.101754,2.557092,0.265856, + 0.579082,-0.064826,-0.812688,4.084506,2.570978,0.218168, + 0.363913,-0.931415,0.005744,4.055262,2.505284,0.297282, + 0.579082,-0.064826,-0.812688,4.084506,2.570978,0.218168, + 0.740815,-0.598363,-0.305214,4.029016,2.519175,0.249385, + 0.198783,-0.979888,0.017481,4.063205,2.509679,0.342987, + 0.727891,-0.103877,-0.677779,4.100907,2.560626,0.302396, + 0.849086,-0.12151,-0.51409,4.101754,2.557092,0.265856, + 0.198783,-0.979888,0.017481,4.063205,2.509679,0.342987, + 0.849086,-0.12151,-0.51409,4.101754,2.557092,0.265856, + 0.363913,-0.931415,0.005744,4.055262,2.505284,0.297282, + 0.207048,-0.965263,0.159371,4.088356,2.510913,0.453793, + 0.576293,-0.081905,-0.813128,4.117367,2.568514,0.3845, + 0.727891,-0.103877,-0.677779,4.100907,2.560626,0.302396, + 0.207048,-0.965263,0.159371,4.088356,2.510913,0.453793, + 0.727891,-0.103877,-0.677779,4.100907,2.560626,0.302396, + 0.198783,-0.979888,0.017481,4.063205,2.509679,0.342987, + -0.613241,-0.041068,-0.788827,3.828001,2.35254,0.233341, + 0.640669,-0.433938,-0.633436,4.00011,2.424158,0.313254, + -0.069267,0.997598,-0.000362,3.988172,2.489642,-0.001008, + -0.613241,-0.041068,-0.788827,3.828001,2.35254,0.233341, + -0.069267,0.997598,-0.000362,3.988172,2.489642,-0.001008, + 0.622247,0.782821,-0.000247,3.787342,2.396113,-0.001159, + -0.613241,-0.041068,-0.788827,3.828001,2.35254,0.233341, + -0.745507,-0.065161,-0.663305,3.870548,2.292106,0.368964, + -0.611332,-0.037351,-0.790492,3.961908,2.347745,0.374747, + -0.613241,-0.041068,-0.788827,3.828001,2.35254,0.233341, + -0.611332,-0.037351,-0.790492,3.961908,2.347745,0.374747, + 0.640669,-0.433938,-0.633436,4.00011,2.424158,0.313254, + -0.747931,-0.041912,-0.662452,4.025364,2.3593,0.402597, + 0.361848,-0.921221,-0.142892,4.043796,2.386524,0.400392, + 0.3579,-0.920931,0.154253,4.035753,2.399538,0.343957, + -0.747931,-0.041912,-0.662452,4.025364,2.3593,0.402597, + 0.3579,-0.920931,0.154253,4.035753,2.399538,0.343957, + 0.640669,-0.433938,-0.633436,4.00011,2.424158,0.313254, + -0.611332,-0.037351,-0.790492,3.961908,2.347745,0.374747, + -0.747931,-0.041912,-0.662452,4.025364,2.3593,0.402597, + 0.640669,-0.433938,-0.633436,4.00011,2.424158,0.313254, + -0.609407,-0.033626,-0.792144,3.967085,2.280648,0.537643, + -0.749946,-0.01864,-0.661236,4.077563,2.305187,0.510338, + -0.747931,-0.041912,-0.662452,4.025364,2.3593,0.402597, + -0.609407,-0.033626,-0.792144,3.967085,2.280648,0.537643, + -0.747931,-0.041912,-0.662452,4.025364,2.3593,0.402597, + -0.611332,-0.037351,-0.790492,3.961908,2.347745,0.374747, + -0.446251,-0.047365,-0.893653,3.903911,2.241501,0.512468, + -0.609407,-0.033626,-0.792144,3.967085,2.280648,0.537643, + -0.611332,-0.037351,-0.790492,3.961908,2.347745,0.374747, + -0.446251,-0.047365,-0.893653,3.903911,2.241501,0.512468, + -0.611332,-0.037351,-0.790492,3.961908,2.347745,0.374747, + -0.745507,-0.065161,-0.663305,3.870548,2.292106,0.368964, + -0.453311,-0.031481,-0.890797,3.823349,2.141733,0.428356, + -0.93621,-0.256398,0.240355,3.857922,2.141554,0.521067, + -0.446251,-0.047365,-0.893653,3.903911,2.241501,0.512468, + -0.453311,-0.031481,-0.890797,3.823349,2.141733,0.428356, + -0.446251,-0.047365,-0.893653,3.903911,2.241501,0.512468, + -0.745507,-0.065161,-0.663305,3.870548,2.292106,0.368964, + -0.124529,-0.930217,0.345238,4.113935,2.334131,0.526471, + -0.138401,-0.989733,0.035683,4.07851,2.41181,0.472193, + 0.361848,-0.921221,-0.142892,4.043796,2.386524,0.400392, + -0.747931,-0.041912,-0.662452,4.025364,2.3593,0.402597, + -0.749946,-0.01864,-0.661236,4.077563,2.305187,0.510338, + -0.124529,-0.930217,0.345238,4.113935,2.334131,0.526471, + -0.747931,-0.041912,-0.662452,4.025364,2.3593,0.402597, + -0.124529,-0.930217,0.345238,4.113935,2.334131,0.526471, + 0.361848,-0.921221,-0.142892,4.043796,2.386524,0.400392, + -0.609407,-0.033626,-0.792144,3.967085,2.280648,0.537643, + -0.450889,-0.363512,0.815205,4.010847,2.270246,0.622149, + -0.749779,-0.335085,0.57057,4.112302,2.285832,0.5955, + -0.609407,-0.033626,-0.792144,3.967085,2.280648,0.537643, + -0.749779,-0.335085,0.57057,4.112302,2.285832,0.5955, + -0.749946,-0.01864,-0.661236,4.077563,2.305187,0.510338, + -0.446251,-0.047365,-0.893653,3.903911,2.241501,0.512468, + -0.948723,-0.104868,0.298208,3.928869,2.223919,0.615683, + -0.450889,-0.363512,0.815205,4.010847,2.270246,0.622149, + -0.446251,-0.047365,-0.893653,3.903911,2.241501,0.512468, + -0.450889,-0.363512,0.815205,4.010847,2.270246,0.622149, + -0.609407,-0.033626,-0.792144,3.967085,2.280648,0.537643, + -0.93621,-0.256398,0.240355,3.857922,2.141554,0.521067, + -0.782361,-0.139191,0.607073,3.892378,2.149432,0.603589, + -0.948723,-0.104868,0.298208,3.928869,2.223919,0.615683, + -0.93621,-0.256398,0.240355,3.857922,2.141554,0.521067, + -0.948723,-0.104868,0.298208,3.928869,2.223919,0.615683, + -0.446251,-0.047365,-0.893653,3.903911,2.241501,0.512468, + -0.450889,-0.363512,0.815205,4.010847,2.270246,0.622149, + -0.555116,0.058381,0.829722,4.04473,2.254459,0.744209, + -0.515329,-0.156304,0.842618,4.146067,2.278102,0.707372, + -0.450889,-0.363512,0.815205,4.010847,2.270246,0.622149, + -0.515329,-0.156304,0.842618,4.146067,2.278102,0.707372, + -0.749779,-0.335085,0.57057,4.112302,2.285832,0.5955, + -0.783471,0.056646,0.618841,3.990744,2.205448,0.710795, + -0.555116,0.058381,0.829722,4.04473,2.254459,0.744209, + -0.450889,-0.363512,0.815205,4.010847,2.270246,0.622149, + -0.783471,0.056646,0.618841,3.990744,2.205448,0.710795, + -0.450889,-0.363512,0.815205,4.010847,2.270246,0.622149, + -0.948723,-0.104868,0.298208,3.928869,2.223919,0.615683, + -0.782361,-0.139191,0.607073,3.892378,2.149432,0.603589, + -0.936127,0.049437,0.348169,3.945464,2.1301,0.689536, + -0.783471,0.056646,0.618841,3.990744,2.205448,0.710795, + -0.782361,-0.139191,0.607073,3.892378,2.149432,0.603589, + -0.783471,0.056646,0.618841,3.990744,2.205448,0.710795, + -0.948723,-0.104868,0.298208,3.928869,2.223919,0.615683, + 0.73986,-0.312403,0.595828,4.212974,2.303184,0.587113, + -0.713872,-0.610821,0.342469,4.296769,2.260422,0.528796, + -0.124529,-0.930217,0.345238,4.113935,2.334131,0.526471, + -0.749779,-0.335085,0.57057,4.112302,2.285832,0.5955, + 0.73986,-0.312403,0.595828,4.212974,2.303184,0.587113, + -0.124529,-0.930217,0.345238,4.113935,2.334131,0.526471, + -0.749779,-0.335085,0.57057,4.112302,2.285832,0.5955, + -0.124529,-0.930217,0.345238,4.113935,2.334131,0.526471, + -0.749946,-0.01864,-0.661236,4.077563,2.305187,0.510338, + -0.749779,-0.335085,0.57057,4.112302,2.285832,0.5955, + -0.515329,-0.156304,0.842618,4.146067,2.278102,0.707372, + -0.965005,-0.14502,-0.218484,4.212058,2.27945,0.625927, + -0.749779,-0.335085,0.57057,4.112302,2.285832,0.5955, + -0.965005,-0.14502,-0.218484,4.212058,2.27945,0.625927, + 0.73986,-0.312403,0.595828,4.212974,2.303184,0.587113, + -0.515329,-0.156304,0.842618,4.146067,2.278102,0.707372, + -0.766653,-0.188233,0.61385,4.172143,2.303394,0.778972, + -0.98488,-0.159984,0.066451,4.229332,2.274522,0.672749, + -0.515329,-0.156304,0.842618,4.146067,2.278102,0.707372, + -0.98488,-0.159984,0.066451,4.229332,2.274522,0.672749, + -0.965005,-0.14502,-0.218484,4.212058,2.27945,0.625927, + -0.555116,0.058381,0.829722,4.04473,2.254459,0.744209, + -0.172109,-0.240744,0.955207,4.079122,2.264104,0.84501, + -0.766653,-0.188233,0.61385,4.172143,2.303394,0.778972, + -0.555116,0.058381,0.829722,4.04473,2.254459,0.744209, + -0.766653,-0.188233,0.61385,4.172143,2.303394,0.778972, + -0.515329,-0.156304,0.842618,4.146067,2.278102,0.707372, + -0.783471,0.056646,0.618841,3.990744,2.205448,0.710795, + 0.50391,-0.29577,0.811538,4.0247,2.187859,0.814219, + -0.172109,-0.240744,0.955207,4.079122,2.264104,0.84501, + -0.783471,0.056646,0.618841,3.990744,2.205448,0.710795, + -0.172109,-0.240744,0.955207,4.079122,2.264104,0.84501, + -0.555116,0.058381,0.829722,4.04473,2.254459,0.744209, + -0.766653,-0.188233,0.61385,4.172143,2.303394,0.778972, + -0.986028,-0.026302,-0.164487,4.215419,2.350484,0.885764, + 0.74814,-0.190428,0.635629,4.273005,2.310529,0.762172, + -0.766653,-0.188233,0.61385,4.172143,2.303394,0.778972, + 0.74814,-0.190428,0.635629,4.273005,2.310529,0.762172, + -0.98488,-0.159984,0.066451,4.229332,2.274522,0.672749, + -0.172109,-0.240744,0.955207,4.079122,2.264104,0.84501, + -0.993835,-0.024167,0.108201,4.104864,2.298353,0.915735, + -0.986028,-0.026302,-0.164487,4.215419,2.350484,0.885764, + -0.172109,-0.240744,0.955207,4.079122,2.264104,0.84501, + -0.986028,-0.026302,-0.164487,4.215419,2.350484,0.885764, + -0.766653,-0.188233,0.61385,4.172143,2.303394,0.778972, + 0.50391,-0.29577,0.811538,4.0247,2.187859,0.814219, + -0.76371,-0.034453,0.644639,4.059714,2.194906,0.888152, + -0.993835,-0.024167,0.108201,4.104864,2.298353,0.915735, + 0.50391,-0.29577,0.811538,4.0247,2.187859,0.814219, + -0.993835,-0.024167,0.108201,4.104864,2.298353,0.915735, + -0.172109,-0.240744,0.955207,4.079122,2.264104,0.84501, + 0.513205,-0.021212,0.858004,4.097362,2.3666,1.239986, + 0.744052,-0.065305,0.664923,4.155551,2.388662,1.09196, + 0.513577,-0.159689,0.843053,4.102304,2.29996,1.025862, + 0.513205,-0.021212,0.858004,4.097362,2.3666,1.239986, + 0.513577,-0.159689,0.843053,4.102304,2.29996,1.025862, + -0.158973,-0.085654,0.98356,4.061989,2.231988,1.178382, + 0.513577,-0.159689,0.843053,4.102304,2.29996,1.025862, + -0.141926,0.071007,0.987327,4.194233,2.408334,1.008471, + -0.986028,-0.026302,-0.164487,4.215419,2.350484,0.885764, + 0.513577,-0.159689,0.843053,4.102304,2.29996,1.025862, + -0.986028,-0.026302,-0.164487,4.215419,2.350484,0.885764, + -0.993835,-0.024167,0.108201,4.104864,2.298353,0.915735, + 0.744052,-0.065305,0.664923,4.155551,2.388662,1.09196, + -0.141926,0.071007,0.987327,4.194233,2.408334,1.008471, + 0.513577,-0.159689,0.843053,4.102304,2.29996,1.025862, + -0.741934,0.120389,0.659576,4.307092,2.367482,0.877202, + 0.74814,-0.190428,0.635629,4.273005,2.310529,0.762172, + -0.986028,-0.026302,-0.164487,4.215419,2.350484,0.885764, + -0.141926,0.071007,0.987327,4.194233,2.408334,1.008471, + -0.982826,0.110983,0.147432,4.266263,2.421651,1.054799, + -0.741934,0.120389,0.659576,4.307092,2.367482,0.877202, + -0.141926,0.071007,0.987327,4.194233,2.408334,1.008471, + -0.741934,0.120389,0.659576,4.307092,2.367482,0.877202, + -0.986028,-0.026302,-0.164487,4.215419,2.350484,0.885764, + 0.744052,-0.065305,0.664923,4.155551,2.388662,1.09196, + -0.989845,0.092874,-0.10762,4.228523,2.435029,1.098575, + -0.982826,0.110983,0.147432,4.266263,2.421651,1.054799, + 0.744052,-0.065305,0.664923,4.155551,2.388662,1.09196, + -0.982826,0.110983,0.147432,4.266263,2.421651,1.054799, + -0.141926,0.071007,0.987327,4.194233,2.408334,1.008471, + 0.513205,-0.021212,0.858004,4.097362,2.3666,1.239986, + 0.3936,0.919282,0.000642,4.17047,2.458441,1.241846, + -0.989845,0.092874,-0.10762,4.228523,2.435029,1.098575, + 0.513205,-0.021212,0.858004,4.097362,2.3666,1.239986, + -0.989845,0.092874,-0.10762,4.228523,2.435029,1.098575, + 0.744052,-0.065305,0.664923,4.155551,2.388662,1.09196, + -0.570564,0.630958,-0.525689,4.058311,2.293363,1.338054, + 0.3936,0.919282,0.000642,4.094116,2.426172,1.381032, + 0.3936,0.919282,0.000642,4.17047,2.458441,1.241846, + -0.570564,0.630958,-0.525689,4.058311,2.293363,1.338054, + 0.3936,0.919282,0.000642,4.17047,2.458441,1.241846, + 0.513205,-0.021212,0.858004,4.097362,2.3666,1.239986, + -0.570564,0.630958,-0.525689,4.046673,2.341349,1.45253, + 0.3936,0.919282,0.000642,4.094116,2.426172,1.381032, + -0.570564,0.630958,-0.525689,4.058311,2.293363,1.338054, + -0.329373,0.540393,-0.774267,4.047406,2.207209,1.015108, + 0.513577,-0.159689,0.843053,4.102304,2.29996,1.025862, + -0.993835,-0.024167,0.108201,4.104864,2.298353,0.915735, + -0.329373,0.540393,-0.774267,4.047406,2.207209,1.015108, + -0.993835,-0.024167,0.108201,4.104864,2.298353,0.915735, + -0.76371,-0.034453,0.644639,4.059714,2.194906,0.888152, + -0.158973,-0.085654,0.98356,4.061989,2.231988,1.178382, + 0.513577,-0.159689,0.843053,4.102304,2.29996,1.025862, + -0.329373,0.540393,-0.774267,4.047406,2.207209,1.015108, + -0.329373,0.540393,-0.774267,3.989434,2.118832,0.765086, + 0.50391,-0.29577,0.811538,4.0247,2.187859,0.814219, + -0.783471,0.056646,0.618841,3.990744,2.205448,0.710795, + -0.329373,0.540393,-0.774267,3.989434,2.118832,0.765086, + -0.783471,0.056646,0.618841,3.990744,2.205448,0.710795, + -0.936127,0.049437,0.348169,3.945464,2.1301,0.689536, + -0.105514,0.43457,-0.894436,4.022592,2.123052,0.903284, + -0.76371,-0.034453,0.644639,4.059714,2.194906,0.888152, + 0.50391,-0.29577,0.811538,4.0247,2.187859,0.814219, + -0.105514,0.43457,-0.894436,4.022592,2.123052,0.903284, + 0.50391,-0.29577,0.811538,4.0247,2.187859,0.814219, + -0.329373,0.540393,-0.774267,3.989434,2.118832,0.765086, + -0.105514,0.43457,-0.894436,4.020299,2.141675,1.002365, + -0.329373,0.540393,-0.774267,4.047406,2.207209,1.015108, + -0.76371,-0.034453,0.644639,4.059714,2.194906,0.888152, + -0.105514,0.43457,-0.894436,4.020299,2.141675,1.002365, + -0.76371,-0.034453,0.644639,4.059714,2.194906,0.888152, + -0.105514,0.43457,-0.894436,4.022592,2.123052,0.903284, + -0.158973,-0.085654,0.98356,4.061989,2.231988,1.178382, + -0.329373,0.540393,-0.774267,4.047406,2.207209,1.015108, + -0.105514,0.43457,-0.894436,4.020299,2.141675,1.002365, + -0.570564,0.630958,-0.525689,4.058311,2.293363,1.338054, + 0.513205,-0.021212,0.858004,4.097362,2.3666,1.239986, + -0.158973,-0.085654,0.98356,4.061989,2.231988,1.178382, + 0.908355,-0.087284,0.408989,4.024858,2.106568,1.208099, + -0.158973,-0.085654,0.98356,4.061989,2.231988,1.178382, + -0.105514,0.43457,-0.894436,4.020299,2.141675,1.002365, + 0.908355,-0.087284,0.408989,4.024858,2.106568,1.208099, + -0.105514,0.43457,-0.894436,4.020299,2.141675,1.002365, + 0.944023,-0.282834,0.169783,4.036947,1.992167,1.072561, + -0.570564,0.630958,-0.525689,4.058311,2.293363,1.338054, + -0.158973,-0.085654,0.98356,4.061989,2.231988,1.178382, + 0.908355,-0.087284,0.408989,4.024858,2.106568,1.208099, + 0.908355,-0.087284,0.408989,4.082988,2.175805,1.45093, + -0.570564,0.630958,-0.525689,4.046673,2.341349,1.45253, + -0.570564,0.630958,-0.525689,4.058311,2.293363,1.338054, + 0.908355,-0.087284,0.408989,4.082988,2.175805,1.45093, + -0.570564,0.630958,-0.525689,4.058311,2.293363,1.338054, + 0.908355,-0.087284,0.408989,4.024858,2.106568,1.208099, + 0.908355,-0.087284,0.408989,4.082988,2.175805,1.45093, + 0.908355,-0.087284,0.408989,4.024858,2.106568,1.208099, + 0.392037,0.915475,-0.09062,4.103303,2.038565,1.363737, + 0.944023,-0.282834,0.169783,4.036947,1.992167,1.072561, + 0.392037,0.915475,-0.09062,4.152166,1.868775,1.225002, + 0.392037,0.915475,-0.09062,4.103303,2.038565,1.363737, + 0.944023,-0.282834,0.169783,4.036947,1.992167,1.072561, + 0.392037,0.915475,-0.09062,4.103303,2.038565,1.363737, + 0.908355,-0.087284,0.408989,4.024858,2.106568,1.208099, + -0.121207,0.426739,-0.896216,4.127903,1.828359,1.090512, + 0.392037,0.915475,-0.09062,4.152166,1.868775,1.225002, + 0.944023,-0.282834,0.169783,4.036947,1.992167,1.072561, + -0.121207,0.426739,-0.896216,4.127903,1.828359,1.090512, + 0.944023,-0.282834,0.169783,4.036947,1.992167,1.072561, + -0.570559,0.630963,0.525688,4.031515,1.968248,0.91846, + 0.944023,-0.282834,0.169783,4.036947,1.992167,1.072561, + -0.105514,0.43457,-0.894436,4.020299,2.141675,1.002365, + -0.105514,0.43457,-0.894436,4.022592,2.123052,0.903284, + 0.944023,-0.282834,0.169783,4.036947,1.992167,1.072561, + -0.105514,0.43457,-0.894436,4.022592,2.123052,0.903284, + -0.570559,0.630963,0.525688,4.031515,1.968248,0.91846, + 0.774828,0.16858,0.60928,3.966639,1.969285,0.549291, + -0.93621,-0.256398,0.240355,3.857922,2.141554,0.521067, + -0.453311,-0.031481,-0.890797,3.823349,2.141733,0.428356, + 0.774828,0.16858,0.60928,3.966639,1.969285,0.549291, + -0.453311,-0.031481,-0.890797,3.823349,2.141733,0.428356, + -0.570559,0.630963,0.525688,3.922437,1.972461,0.483563, + 0.774828,0.16858,0.60928,3.98291,1.987391,0.639809, + -0.782361,-0.139191,0.607073,3.892378,2.149432,0.603589, + -0.93621,-0.256398,0.240355,3.857922,2.141554,0.521067, + 0.774828,0.16858,0.60928,3.98291,1.987391,0.639809, + -0.93621,-0.256398,0.240355,3.857922,2.141554,0.521067, + 0.774828,0.16858,0.60928,3.966639,1.969285,0.549291, + -0.142868,0.456449,-0.878204,4.059885,1.86046,0.470087, + -0.142868,0.456449,-0.878204,4.094112,1.889281,0.578435, + 0.774828,0.16858,0.60928,3.966639,1.969285,0.549291, + -0.142868,0.456449,-0.878204,4.059885,1.86046,0.470087, + 0.774828,0.16858,0.60928,3.966639,1.969285,0.549291, + -0.570559,0.630963,0.525688,3.922437,1.972461,0.483563, + -0.142868,0.456449,-0.878204,4.094112,1.889281,0.578435, + 0.774828,0.16858,0.60928,3.98291,1.987391,0.639809, + 0.774828,0.16858,0.60928,3.966639,1.969285,0.549291, + 0.77718,0.24762,0.578512,4.017509,1.996169,0.731654, + -0.570559,0.630963,0.525688,4.031515,1.968248,0.91846, + -0.105514,0.43457,-0.894436,4.022592,2.123052,0.903284, + 0.77718,0.24762,0.578512,4.017509,1.996169,0.731654, + -0.105514,0.43457,-0.894436,4.022592,2.123052,0.903284, + -0.329373,0.540393,-0.774267,3.989434,2.118832,0.765086, + -0.329373,0.540393,-0.774267,3.989434,2.118832,0.765086, + -0.936127,0.049437,0.348169,3.945464,2.1301,0.689536, + 0.77718,0.24762,0.578512,4.017509,1.996169,0.731654, + 0.77718,0.24762,0.578512,4.017509,1.996169,0.731654, + -0.936127,0.049437,0.348169,3.945464,2.1301,0.689536, + -0.782361,-0.139191,0.607073,3.892378,2.149432,0.603589, + 0.77718,0.24762,0.578512,4.017509,1.996169,0.731654, + -0.782361,-0.139191,0.607073,3.892378,2.149432,0.603589, + 0.774828,0.16858,0.60928,3.98291,1.987391,0.639809, + -0.142868,0.456449,-0.878204,4.094112,1.889281,0.578435, + 0.77718,0.24762,0.578512,4.017509,1.996169,0.731654, + 0.774828,0.16858,0.60928,3.98291,1.987391,0.639809, + -0.142868,0.456449,-0.878204,4.094112,1.889281,0.578435, + -0.121207,0.426739,-0.896216,4.150297,1.820575,0.917046, + 0.77718,0.24762,0.578512,4.017509,1.996169,0.731654, + -0.121207,0.426739,-0.896216,4.150297,1.820575,0.917046, + -0.121207,0.426739,-0.896216,4.127903,1.828359,1.090512, + -0.570559,0.630963,0.525688,4.031515,1.968248,0.91846, + -0.121207,0.426739,-0.896216,4.150297,1.820575,0.917046, + -0.570559,0.630963,0.525688,4.031515,1.968248,0.91846, + 0.77718,0.24762,0.578512,4.017509,1.996169,0.731654, + 0.108306,-0.808441,0.578527,4.389484,2.190421,0.47332, + 0.231006,-0.859096,0.456717,4.472349,2.325133,0.443764, + -0.713872,-0.610821,0.342469,4.296769,2.260422,0.528796, + 0.424214,0.855079,-0.298131,4.3427,2.112281,0.516692, + 0.108306,-0.808441,0.578527,4.389484,2.190421,0.47332, + 0.77718,0.24762,0.578512,4.314791,2.142163,0.54065, + 0.353564,0.891052,-0.284638,4.305411,2.059245,0.539407, + 0.424214,0.855079,-0.298131,4.3427,2.112281,0.516692, + 0.77718,0.24762,0.578512,4.314791,2.142163,0.54065, + 0.108306,-0.808441,0.578527,4.389484,2.190421,0.47332, + -0.713872,-0.610821,0.342469,4.296769,2.260422,0.528796, + 0.77718,0.24762,0.578512,4.314791,2.142163,0.54065, + 0.125846,-0.929941,0.345503,4.43302,2.024714,0.563794, + 0.108306,-0.808441,0.578527,4.389484,2.190421,0.47332, + 0.424214,0.855079,-0.298131,4.3427,2.112281,0.516692, + 0.125846,-0.929941,0.345503,4.43302,2.024714,0.563794, + 0.424214,0.855079,-0.298131,4.3427,2.112281,0.516692, + 0.353564,0.891052,-0.284638,4.305411,2.059245,0.539407, + 0.771387,0.339113,0.538483,4.101726,2.312318,1.438163, + -0.142868,0.456449,0.878205,4.148927,2.388726,1.376879, + 0.3936,0.919282,0.000642,4.094116,2.426172,1.381032, + 0.771387,0.339113,0.538483,4.101726,2.312318,1.438163, + 0.3936,0.919282,0.000642,4.094116,2.426172,1.381032, + -0.570564,0.630958,-0.525689,4.046673,2.341349,1.45253, + 0.63166,0.704336,-0.323908,4.129926,2.30877,1.402259, + 0.229942,0.797697,-0.5575,4.140097,2.295949,1.367196, + 0.22211,0.815123,-0.535015,4.169404,2.306276,1.284031, + 0.63166,0.704336,-0.323908,4.129926,2.30877,1.402259, + 0.22211,0.815123,-0.535015,4.169404,2.306276,1.284031, + 0.459043,0.888414,0.000701,4.149438,2.34055,1.353693, + 0.229942,0.797697,-0.5575,4.140097,2.295949,1.367196, + 0.017957,0.744062,-0.667869,4.141759,2.279958,1.29534, + 0.22211,0.815123,-0.535015,4.169404,2.306276,1.284031, + -0.142868,0.456449,0.878205,4.148927,2.388726,1.376879, + -0.142868,0.456449,0.878205,4.197644,2.394643,1.248646, + 0.3936,0.919282,0.000642,4.17047,2.458441,1.241846, + -0.142868,0.456449,0.878205,4.148927,2.388726,1.376879, + 0.3936,0.919282,0.000642,4.17047,2.458441,1.241846, + 0.3936,0.919282,0.000642,4.094116,2.426172,1.381032, + 0.459043,0.888414,0.000701,4.149438,2.34055,1.353693, + 0.498956,0.866627,0.000639,4.197516,2.349135,1.253043, + -0.142868,0.456449,0.878205,4.197644,2.394643,1.248646, + 0.459043,0.888414,0.000701,4.149438,2.34055,1.353693, + -0.142868,0.456449,0.878205,4.197644,2.394643,1.248646, + -0.142868,0.456449,0.878205,4.148927,2.388726,1.376879, + 0.459043,0.888414,0.000701,4.149438,2.34055,1.353693, + 0.22211,0.815123,-0.535015,4.169404,2.306276,1.284031, + 0.13983,0.720686,-0.679014,4.199317,2.304652,1.17454, + 0.459043,0.888414,0.000701,4.149438,2.34055,1.353693, + 0.13983,0.720686,-0.679014,4.199317,2.304652,1.17454, + 0.498956,0.866627,0.000639,4.197516,2.349135,1.253043, + -0.329371,0.540395,0.774266,4.26732,2.121987,0.61494, + 0.77718,0.24762,0.578512,4.314791,2.142163,0.54065, + -0.713872,-0.610821,0.342469,4.296769,2.260422,0.528796, + -0.329371,0.540395,0.774266,4.26732,2.121987,0.61494, + -0.713872,-0.610821,0.342469,4.296769,2.260422,0.528796, + 0.292429,0.900404,-0.322114,4.274886,2.22003,0.679075, + -0.329371,0.540395,0.774266,4.354411,2.102985,0.80258, + -0.329371,0.540395,0.774266,4.26732,2.121987,0.61494, + 0.292429,0.900404,-0.322114,4.274886,2.22003,0.679075, + -0.329371,0.540395,0.774266,4.354411,2.102985,0.80258, + 0.292429,0.900404,-0.322114,4.274886,2.22003,0.679075, + -0.105515,0.43457,0.894436,4.38099,2.207701,0.839016, + -0.965005,-0.14502,-0.218484,4.212058,2.27945,0.625927, + -0.713872,-0.610821,0.342469,4.296769,2.260422,0.528796, + 0.73986,-0.312403,0.595828,4.212974,2.303184,0.587113, + -0.98488,-0.159984,0.066451,4.229332,2.274522,0.672749, + -0.713872,-0.610821,0.342469,4.296769,2.260422,0.528796, + -0.965005,-0.14502,-0.218484,4.212058,2.27945,0.625927, + 0.292429,0.900404,-0.322114,4.274886,2.22003,0.679075, + -0.713872,-0.610821,0.342469,4.296769,2.260422,0.528796, + -0.98488,-0.159984,0.066451,4.229332,2.274522,0.672749, + 0.292429,0.900404,-0.322114,4.274886,2.22003,0.679075, + -0.98488,-0.159984,0.066451,4.229332,2.274522,0.672749, + 0.74814,-0.190428,0.635629,4.273005,2.310529,0.762172, + -0.741934,0.120389,0.659576,4.307092,2.367482,0.877202, + 0.292429,0.900404,-0.322114,4.274886,2.22003,0.679075, + 0.74814,-0.190428,0.635629,4.273005,2.310529,0.762172, + 0.353564,0.891052,-0.284638,4.305411,2.059245,0.539407, + 0.77718,0.24762,0.578512,4.314791,2.142163,0.54065, + -0.329371,0.540395,0.774266,4.26732,2.121987,0.61494, + -0.105515,0.43457,0.894436,4.369751,2.298204,0.921894, + -0.105515,0.43457,0.894436,4.38099,2.207701,0.839016, + 0.292429,0.900404,-0.322114,4.274886,2.22003,0.679075, + -0.105515,0.43457,0.894436,4.369751,2.298204,0.921894, + 0.292429,0.900404,-0.322114,4.274886,2.22003,0.679075, + -0.741934,0.120389,0.659576,4.307092,2.367482,0.877202, + -0.105515,0.43457,0.894436,4.369751,2.298204,0.921894, + -0.741934,0.120389,0.659576,4.307092,2.367482,0.877202, + -0.982826,0.110983,0.147432,4.266263,2.421651,1.054799, + -0.105515,0.43457,0.894436,4.369751,2.298204,0.921894, + -0.982826,0.110983,0.147432,4.266263,2.421651,1.054799, + 0.781263,0.307132,0.543414,4.303193,2.347123,1.044413, + 0.781263,0.307132,0.543414,4.303193,2.347123,1.044413, + -0.982826,0.110983,0.147432,4.266263,2.421651,1.054799, + -0.989845,0.092874,-0.10762,4.228523,2.435029,1.098575, + 0.781263,0.307132,0.543414,4.303193,2.347123,1.044413, + -0.989845,0.092874,-0.10762,4.228523,2.435029,1.098575, + 0.781263,0.307132,0.543414,4.245861,2.375093,1.141312, + -0.989845,0.092874,-0.10762,4.228523,2.435029,1.098575, + 0.3936,0.919282,0.000642,4.17047,2.458441,1.241846, + -0.142868,0.456449,0.878205,4.197644,2.394643,1.248646, + -0.989845,0.092874,-0.10762,4.228523,2.435029,1.098575, + -0.142868,0.456449,0.878205,4.197644,2.394643,1.248646, + 0.781263,0.307132,0.543414,4.245861,2.375093,1.141312, + 0.589285,0.807925,0.000704,4.218457,2.356834,1.142444, + 0.781263,0.307132,0.543414,4.245861,2.375093,1.141312, + -0.142868,0.456449,0.878205,4.197644,2.394643,1.248646, + 0.589285,0.807925,0.000704,4.218457,2.356834,1.142444, + -0.142868,0.456449,0.878205,4.197644,2.394643,1.248646, + 0.498956,0.866627,0.000639,4.197516,2.349135,1.253043, + 0.685325,0.728237,0.000788,4.275405,2.319905,1.0464, + 0.781263,0.307132,0.543414,4.303193,2.347123,1.044413, + 0.781263,0.307132,0.543414,4.245861,2.375093,1.141312, + 0.685325,0.728237,0.000788,4.275405,2.319905,1.0464, + 0.781263,0.307132,0.543414,4.245861,2.375093,1.141312, + 0.589285,0.807925,0.000704,4.218457,2.356834,1.142444, + 0.685325,0.728237,0.000788,4.275405,2.319905,1.0464, + 0.682044,0.731311,0.000573,4.296538,2.243779,0.925459, + -0.105515,0.43457,0.894436,4.369751,2.298204,0.921894, + 0.685325,0.728237,0.000788,4.275405,2.319905,1.0464, + -0.105515,0.43457,0.894436,4.369751,2.298204,0.921894, + 0.781263,0.307132,0.543414,4.303193,2.347123,1.044413, + 0.682044,0.731311,0.000573,4.296538,2.243779,0.925459, + 0.649774,0.760128,0.000367,4.289048,2.172969,0.858693, + -0.105515,0.43457,0.894436,4.38099,2.207701,0.839016, + 0.682044,0.731311,0.000573,4.296538,2.243779,0.925459, + -0.105515,0.43457,0.894436,4.38099,2.207701,0.839016, + -0.105515,0.43457,0.894436,4.369751,2.298204,0.921894, + 0.589285,0.807925,0.000704,4.218457,2.356834,1.142444, + 0.498956,0.866627,0.000639,4.197516,2.349135,1.253043, + 0.13983,0.720686,-0.679014,4.199317,2.304652,1.17454, + 0.282216,0.811186,-0.512182,4.211815,2.28249,1.039137, + 0.685325,0.728237,0.000788,4.275405,2.319905,1.0464, + 0.589285,0.807925,0.000704,4.218457,2.356834,1.142444, + 0.282216,0.811186,-0.512182,4.211815,2.28249,1.039137, + 0.589285,0.807925,0.000704,4.218457,2.356834,1.142444, + 0.13983,0.720686,-0.679014,4.199317,2.304652,1.17454, + 0.259533,0.686122,-0.679617,4.278045,1.97666,0.537351, + 0.353564,0.891052,-0.284638,4.305411,2.059245,0.539407, + -0.329371,0.540395,0.774266,4.26732,2.121987,0.61494, + 0.259533,0.686122,-0.679617,4.278045,1.97666,0.537351, + -0.329371,0.540395,0.774266,4.26732,2.121987,0.61494, + -0.329371,0.540395,0.774266,4.354411,2.102985,0.80258, + 0.391878,0.915416,0.091898,4.290375,2.112337,0.80019, + -0.329371,0.540395,0.774266,4.354411,2.102985,0.80258, + -0.105515,0.43457,0.894436,4.38099,2.207701,0.839016, + 0.391878,0.915416,0.091898,4.290375,2.112337,0.80019, + -0.105515,0.43457,0.894436,4.38099,2.207701,0.839016, + 0.649774,0.760128,0.000367,4.289048,2.172969,0.858693, + 0.540427,-0.323841,-0.776573,4.222795,2.228178,0.952752, + 0.682044,0.731311,0.000573,4.296538,2.243779,0.925459, + 0.685325,0.728237,0.000788,4.275405,2.319905,1.0464, + 0.540427,-0.323841,-0.776573,4.222795,2.228178,0.952752, + 0.685325,0.728237,0.000788,4.275405,2.319905,1.0464, + 0.282216,0.811186,-0.512182,4.211815,2.28249,1.039137, + 0.540427,-0.323841,-0.776573,4.197609,2.164063,0.857433, + 0.649774,0.760128,0.000367,4.289048,2.172969,0.858693, + 0.682044,0.731311,0.000573,4.296538,2.243779,0.925459, + 0.540427,-0.323841,-0.776573,4.197609,2.164063,0.857433, + 0.682044,0.731311,0.000573,4.296538,2.243779,0.925459, + 0.540427,-0.323841,-0.776573,4.222795,2.228178,0.952752, + 0.384749,-0.683591,-0.620219,4.153175,2.084823,0.799668, + 0.391878,0.915416,0.091898,4.290375,2.112337,0.80019, + 0.649774,0.760128,0.000367,4.289048,2.172969,0.858693, + 0.384749,-0.683591,-0.620219,4.153175,2.084823,0.799668, + 0.649774,0.760128,0.000367,4.289048,2.172969,0.858693, + 0.540427,-0.323841,-0.776573,4.197609,2.164063,0.857433, + 0.384749,-0.683591,-0.620219,4.153175,2.084823,0.799668, + 0.540427,-0.323841,-0.776573,4.197609,2.164063,0.857433, + 0.292794,-0.691168,-0.660725,4.15109,2.102939,0.889759, + 0.292794,-0.691168,-0.660725,4.15109,2.102939,0.889759, + 0.540427,-0.323841,-0.776573,4.197609,2.164063,0.857433, + 0.540427,-0.323841,-0.776573,4.222795,2.228178,0.952752, + 0.292794,-0.691168,-0.660725,4.15109,2.102939,0.889759, + 0.540427,-0.323841,-0.776573,4.222795,2.228178,0.952752, + 0.404933,-0.417851,-0.813283,4.148865,2.148829,0.986567, + 0.404933,-0.417851,-0.813283,4.148865,2.148829,0.986567, + 0.540427,-0.323841,-0.776573,4.222795,2.228178,0.952752, + 0.282216,0.811186,-0.512182,4.211815,2.28249,1.039137, + 0.404933,-0.417851,-0.813283,4.148865,2.148829,0.986567, + 0.282216,0.811186,-0.512182,4.211815,2.28249,1.039137, + 0.551755,-0.23466,-0.800313,4.154566,2.19048,1.129552, + 0.551755,-0.23466,-0.800313,4.154566,2.19048,1.129552, + 0.282216,0.811186,-0.512182,4.211815,2.28249,1.039137, + 0.13983,0.720686,-0.679014,4.199317,2.304652,1.17454, + 0.551755,-0.23466,-0.800313,4.154566,2.19048,1.129552, + 0.13983,0.720686,-0.679014,4.199317,2.304652,1.17454, + 0.202713,-0.881703,-0.426036,4.152557,2.235471,1.217046, + 0.202713,-0.881703,-0.426036,4.152557,2.235471,1.217046, + 0.13983,0.720686,-0.679014,4.199317,2.304652,1.17454, + 0.22211,0.815123,-0.535015,4.169404,2.306276,1.284031, + 0.202713,-0.881703,-0.426036,4.152557,2.235471,1.217046, + 0.22211,0.815123,-0.535015,4.169404,2.306276,1.284031, + 0.017957,0.744062,-0.667869,4.141759,2.279958,1.29534, + 0.384749,-0.683591,-0.620219,4.153175,2.084823,0.799668, + 0.292794,-0.691168,-0.660725,4.15109,2.102939,0.889759, + 0.149569,-0.88683,-0.437221,4.131949,2.050757,0.921856, + 0.149569,-0.88683,-0.437221,4.131949,2.050757,0.921856, + 0.292794,-0.691168,-0.660725,4.15109,2.102939,0.889759, + 0.404933,-0.417851,-0.813283,4.148865,2.148829,0.986567, + 0.149569,-0.88683,-0.437221,4.131949,2.050757,0.921856, + 0.404933,-0.417851,-0.813283,4.148865,2.148829,0.986567, + 0.551755,-0.23466,-0.800313,4.119993,2.063095,1.049178, + 0.551755,-0.23466,-0.800313,4.119993,2.063095,1.049178, + 0.404933,-0.417851,-0.813283,4.148865,2.148829,0.986567, + 0.551755,-0.23466,-0.800313,4.154566,2.19048,1.129552, + 0.551755,-0.23466,-0.800313,4.119993,2.063095,1.049178, + 0.551755,-0.23466,-0.800313,4.154566,2.19048,1.129552, + 0.171366,-0.691521,-0.701735,4.12616,2.12093,1.17252, + 0.171366,-0.691521,-0.701735,4.12616,2.12093,1.17252, + 0.551755,-0.23466,-0.800313,4.154566,2.19048,1.129552, + 0.202713,-0.881703,-0.426036,4.152557,2.235471,1.217046, + 0.171366,-0.691521,-0.701735,4.12616,2.12093,1.17252, + 0.202713,-0.881703,-0.426036,4.152557,2.235471,1.217046, + 0.256636,-0.859143,-0.442732,4.133175,2.175231,1.259323, + 0.202713,-0.881703,-0.426036,4.152557,2.235471,1.217046, + 0.017957,0.744062,-0.667869,4.141759,2.279958,1.29534, + 0.256636,-0.859143,-0.442732,4.133175,2.175231,1.259323, + 0.600629,0.618513,-0.506642,4.159229,1.949902,0.923197, + 0.149569,-0.88683,-0.437221,4.131949,2.050757,0.921856, + 0.551755,-0.23466,-0.800313,4.119993,2.063095,1.049178, + 0.600629,0.618513,-0.506642,4.159229,1.949902,0.923197, + 0.551755,-0.23466,-0.800313,4.119993,2.063095,1.049178, + 0.648166,0.682063,-0.338631,4.137657,1.944837,1.061024, + 0.648166,0.682063,-0.338631,4.137657,1.944837,1.061024, + 0.551755,-0.23466,-0.800313,4.119993,2.063095,1.049178, + 0.171366,-0.691521,-0.701735,4.12616,2.12093,1.17252, + 0.648166,0.682063,-0.338631,4.137657,1.944837,1.061024, + 0.171366,-0.691521,-0.701735,4.12616,2.12093,1.17252, + 0.61118,0.658001,-0.439878,4.143794,2.01372,1.201386, + 0.61118,0.658001,-0.439878,4.143794,2.01372,1.201386, + 0.171366,-0.691521,-0.701735,4.12616,2.12093,1.17252, + 0.256636,-0.859143,-0.442732,4.133175,2.175231,1.259323, + 0.61118,0.658001,-0.439878,4.143794,2.01372,1.201386, + 0.256636,-0.859143,-0.442732,4.133175,2.175231,1.259323, + 0.503641,0.551737,-0.66478,4.12329,2.086854,1.295135, + 0.503641,0.551737,-0.66478,4.12329,2.086854,1.295135, + 0.256636,-0.859143,-0.442732,4.133175,2.175231,1.259323, + 0.017957,0.744062,-0.667869,4.141759,2.279958,1.29534, + 0.503641,0.551737,-0.66478,4.12329,2.086854,1.295135, + 0.017957,0.744062,-0.667869,4.141759,2.279958,1.29534, + 0.517427,0.766113,-0.381235,4.11268,2.195089,1.366908, + 0.517427,0.766113,-0.381235,4.11268,2.195089,1.366908, + 0.017957,0.744062,-0.667869,4.141759,2.279958,1.29534, + 0.229942,0.797697,-0.5575,4.140097,2.295949,1.367196, + 0.517427,0.766113,-0.381235,4.11268,2.195089,1.366908, + 0.229942,0.797697,-0.5575,4.140097,2.295949,1.367196, + 0.41344,0.676483,-0.609457,4.111934,2.234814,1.399949, + 0.229942,0.797697,-0.5575,4.140097,2.295949,1.367196, + 0.63166,0.704336,-0.323908,4.129926,2.30877,1.402259, + 0.41344,0.676483,-0.609457,4.111934,2.234814,1.399949, + 0.154813,-0.698608,-0.698555,4.232341,1.903079,0.534362, + -0.536419,0.710997,0.454685,4.304562,1.906537,0.572242, + 0.259533,0.686122,-0.679617,4.278045,1.97666,0.537351, + -0.557881,0.828586,-0.047048,4.303615,1.799914,0.610388, + -0.536419,0.710997,0.454685,4.304562,1.906537,0.572242, + 0.154813,-0.698608,-0.698555,4.232341,1.903079,0.534362, + -0.557881,0.828586,-0.047048,4.303615,1.799914,0.610388, + 0.154813,-0.698608,-0.698555,4.232341,1.903079,0.534362, + -0.678336,0.658323,0.326299,4.240116,1.770049,0.583946, + -0.277696,-0.435918,0.856073,4.377095,1.871713,0.595743, + 0.353564,0.891052,-0.284638,4.305411,2.059245,0.539407, + 0.259533,0.686122,-0.679617,4.278045,1.97666,0.537351, + -0.277696,-0.435918,0.856073,4.377095,1.871713,0.595743, + 0.259533,0.686122,-0.679617,4.278045,1.97666,0.537351, + -0.536419,0.710997,0.454685,4.304562,1.906537,0.572242, + 0.003817,-0.976864,0.213829,4.43261,1.878873,0.577888, + 0.125846,-0.929941,0.345503,4.43302,2.024714,0.563794, + 0.353564,0.891052,-0.284638,4.305411,2.059245,0.539407, + 0.003817,-0.976864,0.213829,4.43261,1.878873,0.577888, + 0.353564,0.891052,-0.284638,4.305411,2.059245,0.539407, + -0.277696,-0.435918,0.856073,4.377095,1.871713,0.595743, + -0.678336,0.658323,0.326299,4.240116,1.770049,0.583946, + 0.154813,-0.698608,-0.698555,4.232341,1.903079,0.534362, + -0.142868,0.456449,-0.878204,4.094112,1.889281,0.578435, + -0.678336,0.658323,0.326299,4.240116,1.770049,0.583946, + -0.142868,0.456449,-0.878204,4.094112,1.889281,0.578435, + -0.641133,0.599375,0.479267,4.148883,1.759918,0.573765, + 0.391878,0.915416,0.091898,4.281287,2.055751,0.787, + -0.329371,0.540395,0.774266,4.354411,2.102985,0.80258, + 0.391878,0.915416,0.091898,4.290375,2.112337,0.80019, + 0.391878,0.915416,0.091898,4.281287,2.055751,0.787, + -0.121207,0.426739,0.896216,4.354941,2.064161,0.778851, + -0.329371,0.540395,0.774266,4.354411,2.102985,0.80258, + -0.121207,0.426739,0.896216,4.245225,2.008532,0.772641, + -0.121207,0.426739,0.896216,4.354941,2.064161,0.778851, + 0.391878,0.915416,0.091898,4.281287,2.055751,0.787, + 0.391878,0.915416,0.091898,4.281287,2.055751,0.787, + 0.391878,0.915416,0.091898,4.290375,2.112337,0.80019, + 0.384749,-0.683591,-0.620219,4.153175,2.084823,0.799668, + 0.600629,0.618513,-0.506642,4.159229,1.949902,0.923197, + 0.391878,0.915416,0.091898,4.281287,2.055751,0.787, + 0.384749,-0.683591,-0.620219,4.153175,2.084823,0.799668, + 0.600629,0.618513,-0.506642,4.159229,1.949902,0.923197, + 0.384749,-0.683591,-0.620219,4.153175,2.084823,0.799668, + 0.149569,-0.88683,-0.437221,4.131949,2.050757,0.921856, + 0.259533,0.686122,-0.679617,4.278045,1.97666,0.537351, + -0.329371,0.540395,0.774266,4.354411,2.102985,0.80258, + -0.121207,0.426739,0.896216,4.354941,2.064161,0.778851, + -0.121207,0.426739,0.896216,4.245225,2.008532,0.772641, + 0.154813,-0.698608,-0.698555,4.232341,1.903079,0.534362, + 0.259533,0.686122,-0.679617,4.278045,1.97666,0.537351, + -0.121207,0.426739,0.896216,4.245225,2.008532,0.772641, + 0.259533,0.686122,-0.679617,4.278045,1.97666,0.537351, + -0.121207,0.426739,0.896216,4.354941,2.064161,0.778851, + -0.121207,0.426739,0.896216,4.245225,2.008532,0.772641, + 0.391878,0.915416,0.091898,4.281287,2.055751,0.787, + 0.600629,0.618513,-0.506642,4.159229,1.949902,0.923197, + 0.969409,0.243854,0.027951,5.959462,1.157227,0.187097, + 0.000755,0.939586,-0.342312,5.950684,1.082725,0.175648, + 0.461485,0.788926,-0.405742,5.961686,1.110978,0.090324, + 0.969409,0.243854,0.027951,5.959462,1.157227,0.187097, + 0.461485,0.788926,-0.405742,5.961686,1.110978,0.090324, + 0.04154,0.947538,-0.316933,5.998088,1.231874,0.107334, + 0.104327,0.725166,-0.680625,5.755282,1.004149,0.307505, + 0.288171,0.239223,-0.927216,5.763952,1.062109,0.338641, + -0.163152,0.699849,-0.695408,5.681086,1.054964,0.35586, + 0.104327,0.725166,-0.680625,5.755282,1.004149,0.307505, + -0.163152,0.699849,-0.695408,5.681086,1.054964,0.35586, + -0.011269,-0.268801,-0.96313,5.672385,1.007694,0.341778, + -0.497134,0.140474,0.856227,5.710154,1.360653,0.290072, + -0.434729,0.079706,0.897027,5.730427,1.435668,0.209848, + -0.419631,0.061765,0.905591,5.685194,1.452202,0.188749, + -0.497134,0.140474,0.856227,5.710154,1.360653,0.290072, + -0.419631,0.061765,0.905591,5.685194,1.452202,0.188749, + -0.400711,0.089186,0.911853,5.647186,1.394606,0.257833, + -0.023775,-0.598435,0.800818,4.991713,1.163096,0.504149, + -0.77316,0.344902,0.532228,5.011084,1.06677,0.458562, + 0.157921,-0.851177,-0.500559,5.241466,1.040469,0.383965, + -0.023775,-0.598435,0.800818,4.991713,1.163096,0.504149, + 0.157921,-0.851177,-0.500559,5.241466,1.040469,0.383965, + 0.009824,-0.644035,0.764933,5.250485,1.123029,0.385234, + 0.123418,-0.784469,0.607763,4.641547,1.285422,0.622034, + 0.050019,-0.552867,0.831767,4.522247,1.398278,0.644892, + -0.395804,0.901672,0.174144,4.449011,1.260929,0.647431, + 0.123418,-0.784469,0.607763,4.641547,1.285422,0.622034, + -0.395804,0.901672,0.174144,4.449011,1.260929,0.647431, + -0.911194,0.285551,0.296961,4.567896,1.149805,0.642484, + 0.901575,-0.270544,0.337593,4.742358,1.882232,0.62165, + 0.689769,-0.265624,0.673544,4.728963,2.036146,0.614307, + 0.190357,-0.604308,0.773677,4.688114,2.046378,0.604518, + 0.901575,-0.270544,0.337593,4.742358,1.882232,0.62165, + 0.190357,-0.604308,0.773677,4.688114,2.046378,0.604518, + 0.152967,-0.640193,0.752831,4.697024,1.862575,0.604048, + 0.337014,-0.030018,0.941021,4.760921,1.881357,0.61312, + 0.347794,0.132396,0.928176,4.824747,1.946835,0.626358, + 0.36359,0.089346,0.927264,4.861611,2.001639,0.621913, + 0.337014,-0.030018,0.941021,4.760921,1.881357,0.61312, + 0.36359,0.089346,0.927264,4.861611,2.001639,0.621913, + 0.195545,0.103956,0.975169,4.842883,2.021333,0.638025, + 0.168187,0.300291,0.938903,4.852582,1.816115,0.603105, + 0.272203,0.043076,0.961275,4.861618,1.854067,0.618095, + 0.337014,-0.030018,0.941021,4.760921,1.881357,0.61312, + 0.282492,0.026081,0.958915,4.973133,1.992779,0.533466, + 0.210495,0.185422,0.959849,4.991746,2.009819,0.523206, + 0.196849,0.14562,0.969559,4.93588,2.051665,0.572853, + 0.282492,0.026081,0.958915,4.973133,1.992779,0.533466, + 0.196849,0.14562,0.969559,4.93588,2.051665,0.572853, + 0.361081,-0.056526,0.93082,4.935561,2.016016,0.5857, + 0.337014,-0.030018,0.941021,4.760921,1.881357,0.61312, + 0.067357,0.280764,0.95741,4.788476,2.028047,0.608619, + -0.026366,0.234118,0.971851,4.751519,2.039658,0.634134, + 0.289202,0.572304,0.767353,4.991709,1.844295,0.520761, + 0.154687,0.171026,0.973048,5.01143,1.875569,0.463205, + 0.380651,0.443224,0.811577,5.001903,1.914398,0.486724, + 0.289202,0.572304,0.767353,4.991709,1.844295,0.520761, + 0.380651,0.443224,0.811577,5.001903,1.914398,0.486724, + 0.362705,0.428702,0.827442,4.982364,1.8733,0.53619, + 0.380651,0.443224,0.811577,5.001903,1.914398,0.486724, + 0.154687,0.171026,0.973048,5.01143,1.875569,0.463205, + 0.210495,0.185422,0.959849,4.991746,2.009819,0.523206, + 0.196849,0.14562,0.969559,4.93588,2.051665,0.572853, + 0.054287,0.055115,0.997003,4.918466,2.084725,0.532713, + 0.012421,0.392537,0.919652,4.881574,2.094571,0.539949, + 0.399187,-0.679804,0.615237,4.74405,2.179337,0.556057, + 0.428199,-0.104479,0.897624,4.837331,2.235678,0.479332, + 0.244568,-0.044721,0.9686,4.739441,2.299169,0.369987, + 0.399187,-0.679804,0.615237,4.74405,2.179337,0.556057, + 0.244568,-0.044721,0.9686,4.739441,2.299169,0.369987, + 0.223925,-0.919003,0.324486,4.636582,2.263383,0.471997, + 0.550963,0.62763,0.550018,5.075994,1.900999,0.443793, + 0.72603,0.248277,0.641279,5.095375,1.961238,0.401516, + 0.670109,-0.356989,0.650778,5.067202,2.027704,0.422291, + 0.550963,0.62763,0.550018,5.075994,1.900999,0.443793, + 0.670109,-0.356989,0.650778,5.067202,2.027704,0.422291, + 0.615065,0.769234,0.173133,5.057495,2.002751,0.451974, + 0.771387,0.339113,0.538483,4.101726,2.312318,1.438163, + -0.570564,0.630958,-0.525689,4.046673,2.341349,1.45253, + 0.908355,-0.087284,0.408989,4.082988,2.175805,1.45093, + 0.41344,0.676483,-0.609457,4.111934,2.234814,1.399949, + 0.63166,0.704336,-0.323908,4.129926,2.30877,1.402259, + 0.771387,0.339113,0.538483,4.101726,2.312318,1.438163, + 0.41344,0.676483,-0.609457,4.111934,2.234814,1.399949, + 0.771387,0.339113,0.538483,4.101726,2.312318,1.438163, + 0.908355,-0.087284,0.408989,4.082988,2.175805,1.45093, + -0.121207,0.426739,-0.896216,4.150297,1.820575,0.917046, + -0.142868,0.456449,-0.878204,4.094112,1.889281,0.578435, + -0.121207,0.426739,0.896216,4.245225,2.008532,0.772641, + -0.121207,0.426739,-0.896216,4.150297,1.820575,0.917046, + -0.121207,0.426739,0.896216,4.245225,2.008532,0.772641, + 0.600629,0.618513,-0.506642,4.159229,1.949902,0.923197, + -0.121207,0.426739,-0.896216,4.127903,1.828359,1.090512, + -0.121207,0.426739,-0.896216,4.150297,1.820575,0.917046, + 0.600629,0.618513,-0.506642,4.159229,1.949902,0.923197, + -0.121207,0.426739,-0.896216,4.127903,1.828359,1.090512, + 0.600629,0.618513,-0.506642,4.159229,1.949902,0.923197, + 0.648166,0.682063,-0.338631,4.137657,1.944837,1.061024, + 0.392037,0.915475,-0.09062,4.152166,1.868775,1.225002, + -0.121207,0.426739,-0.896216,4.127903,1.828359,1.090512, + 0.648166,0.682063,-0.338631,4.137657,1.944837,1.061024, + 0.392037,0.915475,-0.09062,4.152166,1.868775,1.225002, + 0.648166,0.682063,-0.338631,4.137657,1.944837,1.061024, + 0.61118,0.658001,-0.439878,4.143794,2.01372,1.201386, + 0.392037,0.915475,-0.09062,4.103303,2.038565,1.363737, + 0.392037,0.915475,-0.09062,4.152166,1.868775,1.225002, + 0.61118,0.658001,-0.439878,4.143794,2.01372,1.201386, + 0.392037,0.915475,-0.09062,4.103303,2.038565,1.363737, + 0.61118,0.658001,-0.439878,4.143794,2.01372,1.201386, + 0.503641,0.551737,-0.66478,4.12329,2.086854,1.295135, + 0.908355,-0.087284,0.408989,4.082988,2.175805,1.45093, + 0.392037,0.915475,-0.09062,4.103303,2.038565,1.363737, + 0.503641,0.551737,-0.66478,4.12329,2.086854,1.295135, + 0.908355,-0.087284,0.408989,4.082988,2.175805,1.45093, + 0.503641,0.551737,-0.66478,4.12329,2.086854,1.295135, + 0.517427,0.766113,-0.381235,4.11268,2.195089,1.366908, + 0.908355,-0.087284,0.408989,4.082988,2.175805,1.45093, + 0.517427,0.766113,-0.381235,4.11268,2.195089,1.366908, + 0.41344,0.676483,-0.609457,4.111934,2.234814,1.399949, + -0.760994,0.140163,0.633437,4.076852,1.746601,0.527436, + -0.641133,0.599375,0.479267,4.148883,1.759918,0.573765, + -0.142868,0.456449,-0.878204,4.094112,1.889281,0.578435, + -0.760994,0.140163,0.633437,4.076852,1.746601,0.527436, + -0.142868,0.456449,-0.878204,4.094112,1.889281,0.578435, + -0.142868,0.456449,-0.878204,4.059885,1.86046,0.470087, + 0.000801,-1,-0.000539,4.380854,0.704574,-0.00013, + -0.659696,0.567802,0.492343,4.359048,0.700414,0.166651, + 0.804239,-0.153549,0.574128,4.120842,0.627141,0.185461, + 0.000801,-1,-0.000539,4.380854,0.704574,-0.00013, + 0.804239,-0.153549,0.574128,4.120842,0.627141,0.185461, + -0.926486,-0.356041,-0.121897,4.126565,0.642027,0, + -0.760994,0.140163,0.633437,4.076852,1.746601,0.527436, + -0.142868,0.456449,-0.878204,4.059885,1.86046,0.470087, + 0.539114,0.412574,0.734261,3.881998,1.764428,0.476337, + -0.560402,0.735791,0.380211,4.067576,1.572668,0.534997, + -0.760994,0.140163,0.633437,4.076852,1.746601,0.527436, + 0.539114,0.412574,0.734261,3.881998,1.764428,0.476337, + -0.560402,0.735791,0.380211,4.067576,1.572668,0.534997, + 0.539114,0.412574,0.734261,3.881998,1.764428,0.476337, + 0.696162,0.333274,0.635835,3.886058,1.550141,0.50483, + -0.610894,0.790229,-0.048447,4.085564,1.288885,0.544406, + -0.560402,0.735791,0.380211,4.067576,1.572668,0.534997, + 0.696162,0.333274,0.635835,3.886058,1.550141,0.50483, + -0.610894,0.790229,-0.048447,4.085564,1.288885,0.544406, + 0.696162,0.333274,0.635835,3.886058,1.550141,0.50483, + 0.763734,0.228435,0.603761,3.98851,1.297806,0.539537, + -0.590367,0.807126,-0.003753,4.141189,1.008775,0.499342, + -0.610894,0.790229,-0.048447,4.085564,1.288885,0.544406, + 0.763734,0.228435,0.603761,3.98851,1.297806,0.539537, + -0.590367,0.807126,-0.003753,4.141189,1.008775,0.499342, + 0.763734,0.228435,0.603761,3.98851,1.297806,0.539537, + 0.769758,0.095155,0.631204,4.041657,1.039756,0.496922, + 0.206279,0.744917,0.634467,4.216374,0.852328,0.405873, + -0.590367,0.807126,-0.003753,4.141189,1.008775,0.499342, + 0.769758,0.095155,0.631204,4.041657,1.039756,0.496922, + 0.206279,0.744917,0.634467,4.216374,0.852328,0.405873, + 0.769758,0.095155,0.631204,4.041657,1.039756,0.496922, + 0.771881,-0.100912,0.627707,4.068249,0.798926,0.400813, + 0.11638,0.680311,0.723624,4.319799,0.731007,0.291212, + 0.206279,0.744917,0.634467,4.216374,0.852328,0.405873, + 0.771881,-0.100912,0.627707,4.068249,0.798926,0.400813, + 0.11638,0.680311,0.723624,4.319799,0.731007,0.291212, + 0.771881,-0.100912,0.627707,4.068249,0.798926,0.400813, + 0.788801,-0.199379,0.581412,4.105198,0.672581,0.300001, + -0.659696,0.567802,0.492343,4.359048,0.700414,0.166651, + 0.11638,0.680311,0.723624,4.319799,0.731007,0.291212, + 0.788801,-0.199379,0.581412,4.105198,0.672581,0.300001, + -0.659696,0.567802,0.492343,4.359048,0.700414,0.166651, + 0.788801,-0.199379,0.581412,4.105198,0.672581,0.300001, + 0.804239,-0.153549,0.574128,4.120842,0.627141,0.185461, + 0.241303,0.584582,0.77462,3.758215,2.206683,0.323051, + -0.745507,-0.065161,-0.663305,3.870548,2.292106,0.368964, + -0.613241,-0.041068,-0.788827,3.828001,2.35254,0.233341, + 0.241303,0.584582,0.77462,3.758215,2.206683,0.323051, + -0.613241,-0.041068,-0.788827,3.828001,2.35254,0.233341, + 0.072694,0.752739,0.654294,3.745669,2.266001,0.24193, + -0.613241,-0.041068,-0.788827,3.828001,2.35254,0.233341, + 0.622247,0.782821,-0.000247,3.787342,2.396113,-0.001159, + 0.431966,-0.771434,-0.46722,3.71636,2.343387,0, + -0.613241,-0.041068,-0.788827,3.828001,2.35254,0.233341, + 0.431966,-0.771434,-0.46722,3.71636,2.343387,0, + -0.071584,0.92252,0.379253,3.727093,2.308406,0.150049, + -0.613241,-0.041068,-0.788827,3.828001,2.35254,0.233341, + -0.071584,0.92252,0.379253,3.727093,2.308406,0.150049, + 0.072694,0.752739,0.654294,3.745669,2.266001,0.24193, + 0.539114,0.412574,0.734261,3.881998,1.764428,0.476337, + -0.142868,0.456449,-0.878204,4.059885,1.86046,0.470087, + -0.570559,0.630963,0.525688,3.922437,1.972461,0.483563, + 0.462789,0.48004,0.745243,3.814876,1.968416,0.443, + 0.539114,0.412574,0.734261,3.881998,1.764428,0.476337, + -0.570559,0.630963,0.525688,3.922437,1.972461,0.483563, + 0.462789,0.48004,0.745243,3.814876,1.968416,0.443, + -0.570559,0.630963,0.525688,3.922437,1.972461,0.483563, + -0.453311,-0.031481,-0.890797,3.823349,2.141733,0.428356, + 0.241303,0.584582,0.77462,3.758215,2.206683,0.323051, + 0.462789,0.48004,0.745243,3.814876,1.968416,0.443, + -0.453311,-0.031481,-0.890797,3.823349,2.141733,0.428356, + 0.241303,0.584582,0.77462,3.758215,2.206683,0.323051, + -0.453311,-0.031481,-0.890797,3.823349,2.141733,0.428356, + -0.745507,-0.065161,-0.663305,3.870548,2.292106,0.368964, + -0.142868,0.456449,-0.878204,4.094112,1.889281,0.578435, + 0.154813,-0.698608,-0.698555,4.232341,1.903079,0.534362, + -0.121207,0.426739,0.896216,4.245225,2.008532,0.772641, + -0.020456,0.943466,0.330837,1.700797,-2.794792,0.82425, + 0.21689,-0.976039,-0.017487,1.718315,-2.775468,0.921796, + 0.383337,-0.601981,-0.700479,1.678986,-2.513137,0.891745, + -0.020456,0.943466,0.330837,1.700797,-2.794792,0.82425, + 0.383337,-0.601981,-0.700479,1.678986,-2.513137,0.891745, + 0.717573,0.343682,-0.605782,1.655948,-2.520927,0.844269, + -0.020456,0.943466,0.330837,1.700797,-2.794792,0.82425, + -0.065687,-0.249194,-0.966223,1.705953,-3.006628,0.83263, + -0.424393,0.057227,0.903668,1.734568,-2.965876,0.986396, + -0.020456,0.943466,0.330837,1.700797,-2.794792,0.82425, + -0.424393,0.057227,0.903668,1.734568,-2.965876,0.986396, + 0.21689,-0.976039,-0.017487,1.718315,-2.775468,0.921796, + -0.329905,-0.225598,0.916661,-0.972514,-1.822778,0.372649, + -0.055857,0.145868,0.987726,-0.977375,-1.793126,0.498747, + -0.182029,-0.190207,0.964721,-1.108758,-1.770749,0.473033, + -0.329905,-0.225598,0.916661,-0.972514,-1.822778,0.372649, + -0.182029,-0.190207,0.964721,-1.108758,-1.770749,0.473033, + -0.571338,-0.120921,0.811758,-1.305099,-1.70846,0.48423, + -0.571338,-0.120921,0.811758,-1.305099,-1.70846,0.48423, + 0.714393,-0.109998,0.691045,-1.266738,-1.691944,0.557922, + -0.587909,-0.233166,0.774594,-1.397474,-1.693815,0.570541, + -0.571338,-0.120921,0.811758,-1.305099,-1.70846,0.48423, + -0.587909,-0.233166,0.774594,-1.397474,-1.693815,0.570541, + 0.023392,-0.110333,0.993619,-1.406693,-1.697325,0.450399, + -0.468954,-0.586277,0.660577,-3.35851,1.810253,0.380095, + 0.431712,0.22912,0.872427,-3.413372,1.871604,0.142309, + 0.072535,0.997366,0,-3.392806,1.769365,0, + 0.072535,0.997366,0,-3.392806,1.769365,0, + 0.431712,0.22912,0.872427,-3.413372,1.871604,0.142309, + 0.588787,-0.248294,0.769207,-3.380836,1.819691,0.123273, + 0.072535,0.997366,0,-3.392806,1.769365,0, + 0.588787,-0.248294,0.769207,-3.380836,1.819691,0.123273, + 0.411442,-0.911436,-0.000099,-3.348274,1.767738,-0.000085, + -0.142868,0.456449,0.878205,4.148927,2.388726,1.376879, + 0.771387,0.339113,0.538483,4.101726,2.312318,1.438163, + 0.63166,0.704336,-0.323908,4.129926,2.30877,1.402259, + -0.142868,0.456449,0.878205,4.148927,2.388726,1.376879, + 0.63166,0.704336,-0.323908,4.129926,2.30877,1.402259, + 0.459043,0.888414,0.000701,4.149438,2.34055,1.353693, + -0.037581,-0.042039,-0.998409,-2.964215,-1.978727,0.776572, + -0.377491,-0.043727,0.92498,-3.066022,-1.953125,0.719516, + 0.713401,0.39471,-0.579019,-3.008323,-1.759271,0.655672, + -0.037581,-0.042039,-0.998409,-2.964215,-1.978727,0.776572, + 0.713401,0.39471,-0.579019,-3.008323,-1.759271,0.655672, + -0.732521,-0.474279,0.488336,-2.811581,-1.79821,0.712737, + -0.377491,-0.043727,0.92498,-3.066022,-1.953125,0.719516, + 0.684558,0.361153,-0.633205,-3.211005,-1.850398,0.700723, + 0.843062,-0.10517,0.527433,-3.139394,-1.687482,0.638546, + -0.377491,-0.043727,0.92498,-3.066022,-1.953125,0.719516, + 0.843062,-0.10517,0.527433,-3.139394,-1.687482,0.638546, + 0.713401,0.39471,-0.579019,-3.008323,-1.759271,0.655672, + 0.588787,-0.248294,0.769207,-3.380836,1.819691,0.123273, + 0.490646,-0.178294,0.852923,-3.357009,1.781675,0.071216, + 0.411442,-0.911436,-0.000099,-3.348274,1.767738,-0.000085, + 0.389161,-0.829175,-0.401277,-3.357009,1.781675,-0.071216, + 0.255239,-0.528231,-0.80983,-3.380836,1.819691,-0.123273, + 0.411442,-0.911436,-0.000099,-3.348274,1.767738,-0.000085 +}; +static const struct gllist frame={GL_N3F_V3F,GL_TRIANGLES,13050,data,NULL}; +const struct gllist *cow_hide=&frame; diff --git a/hacks/glx/cow_hoofs.c b/hacks/glx/cow_hoofs.c new file mode 100644 index 00000000..b66ef885 --- /dev/null +++ b/hacks/glx/cow_hoofs.c @@ -0,0 +1,1037 @@ +#include "gllist.h" +static const float data[]={ + 0.013288,-0.297478,-0.954636,1.970051,-3.141862,-1.065178, + -0.228294,-0.186048,-0.955651,2.110033,-3.148257,-1.068816, + -0.562282,-0.328888,-0.75873,2.14888,-3.221616,-1.076203, + 0.013288,-0.297478,-0.954636,1.970051,-3.141862,-1.065178, + -0.562282,-0.328888,-0.75873,2.14888,-3.221616,-1.076203, + 0.157806,0.230904,-0.960094,2.031262,-3.256709,-1.111122, + 0.157806,0.230904,-0.960094,2.031262,-3.256709,-1.111122, + -0.562282,-0.328888,-0.75873,2.14888,-3.221616,-1.076203, + -0.144755,0.439659,-0.886423,2.247981,-3.342804,-1.127459, + 0.157806,0.230904,-0.960094,2.031262,-3.256709,-1.111122, + -0.144755,0.439659,-0.886423,2.247981,-3.342804,-1.127459, + 0.339699,0.626415,-0.701576,2.138771,-3.397683,-1.214726, + 0.339699,0.626415,-0.701576,2.138771,-3.397683,-1.214726, + -0.144755,0.439659,-0.886423,2.247981,-3.342804,-1.127459, + 0.457854,0.537523,-0.708123,2.343303,-3.507846,-1.195262, + 0.339699,0.626415,-0.701576,2.138771,-3.397683,-1.214726, + 0.457854,0.537523,-0.708123,2.343303,-3.507846,-1.195262, + -0.081045,0.409121,-0.908874,2.254361,-3.550931,-1.235118, + -0.081045,0.409121,-0.908874,2.254361,-3.550931,-1.235118, + 0.444124,0.617475,-0.649214,2.025468,-3.556842,-1.204841, + 0.010538,0.399391,-0.91672,1.981186,-3.441282,-1.180532, + -0.081045,0.409121,-0.908874,2.254361,-3.550931,-1.235118, + 0.010538,0.399391,-0.91672,1.981186,-3.441282,-1.180532, + 0.339699,0.626415,-0.701576,2.138771,-3.397683,-1.214726, + 0.339699,0.626415,-0.701576,2.138771,-3.397683,-1.214726, + 0.010538,0.399391,-0.91672,1.981186,-3.441282,-1.180532, + 0.636282,0.100893,-0.764831,1.926176,-3.28888,-1.093746, + 0.339699,0.626415,-0.701576,2.138771,-3.397683,-1.214726, + 0.636282,0.100893,-0.764831,1.926176,-3.28888,-1.093746, + 0.157806,0.230904,-0.960094,2.031262,-3.256709,-1.111122, + 0.157806,0.230904,-0.960094,2.031262,-3.256709,-1.111122, + 0.636282,0.100893,-0.764831,1.926176,-3.28888,-1.093746, + 0.213417,-0.547723,-0.808983,1.886443,-3.191742,-1.047318, + 0.157806,0.230904,-0.960094,2.031262,-3.256709,-1.111122, + 0.213417,-0.547723,-0.808983,1.886443,-3.191742,-1.047318, + 0.013288,-0.297478,-0.954636,1.970051,-3.141862,-1.065178, + -0.430523,-0.648445,-0.627828,2.281229,-3.33825,-1.043475, + -0.144755,0.439659,-0.886423,2.247981,-3.342804,-1.127459, + -0.562282,-0.328888,-0.75873,2.14888,-3.221616,-1.076203, + -0.430523,-0.648445,-0.627828,2.281229,-3.33825,-1.043475, + -0.562282,-0.328888,-0.75873,2.14888,-3.221616,-1.076203, + -0.492627,0.113675,-0.862784,2.201939,-3.226457,-0.996503, + -0.492627,0.113675,-0.862784,2.201939,-3.226457,-0.996503, + -0.562282,-0.328888,-0.75873,2.14888,-3.221616,-1.076203, + -0.228294,-0.186048,-0.955651,2.110033,-3.148257,-1.068816, + -0.492627,0.113675,-0.862784,2.201939,-3.226457,-0.996503, + -0.228294,-0.186048,-0.955651,2.110033,-3.148257,-1.068816, + -0.495591,0.225654,-0.838731,2.170039,-3.134504,-0.978866, + -0.495591,0.225654,-0.838731,2.170039,-3.134504,-0.978866, + -0.541077,0.245809,-0.804247,2.091539,-3.032437,-0.947029, + 0.672893,0.661099,-0.331908,2.113587,-3.011851,-0.851648, + -0.495591,0.225654,-0.838731,2.170039,-3.134504,-0.978866, + 0.672893,0.661099,-0.331908,2.113587,-3.011851,-0.851648, + 0.768072,0.514957,-0.380637,2.217369,-3.156093,-0.888927, + 0.626232,0.565165,-0.53705,1.841888,-3.246003,-1.014774, + 0.213417,-0.547723,-0.808983,1.886443,-3.191742,-1.047318, + 0.636282,0.100893,-0.764831,1.926176,-3.28888,-1.093746, + 0.626232,0.565165,-0.53705,1.841888,-3.246003,-1.014774, + 0.636282,0.100893,-0.764831,1.926176,-3.28888,-1.093746, + 0.52783,0.437826,-0.727807,1.865135,-3.353827,-1.054981, + 0.862528,0.499882,0.078511,1.919391,-3.487078,-1.110869, + 0.52783,0.437826,-0.727807,1.865135,-3.353827,-1.054981, + 0.636282,0.100893,-0.764831,1.926176,-3.28888,-1.093746, + 0.862528,0.499882,0.078511,1.919391,-3.487078,-1.110869, + 0.636282,0.100893,-0.764831,1.926176,-3.28888,-1.093746, + 0.010538,0.399391,-0.91672,1.981186,-3.441282,-1.180532, + 0.010538,0.399391,-0.91672,1.981186,-3.441282,-1.180532, + 0.444124,0.617475,-0.649214,2.025468,-3.556842,-1.204841, + 0.862528,0.499882,0.078511,1.919391,-3.487078,-1.110869, + 0.872426,0.488735,0.003222,1.980621,-3.043895,-0.964237, + -0.495591,0.225654,-0.838731,2.170039,-3.134504,-0.978866, + -0.228294,-0.186048,-0.955651,2.110033,-3.148257,-1.068816, + -0.783521,-0.393963,-0.480508,1.806407,-3.173343,-0.834455, + 0.926951,0.366239,0.081429,1.811797,-3.135641,-0.933096, + 0.626232,0.565165,-0.53705,1.841888,-3.246003,-1.014774, + -0.783521,-0.393963,-0.480508,1.806407,-3.173343,-0.834455, + 0.626232,0.565165,-0.53705,1.841888,-3.246003,-1.014774, + 0.215809,0.484483,-0.847763,1.83279,-3.296508,-0.865078, + -0.997638,0.009858,0.067986,1.933899,-3.546253,-0.912438, + 0.862528,0.499882,0.078511,1.919391,-3.487078,-1.110869, + 0.444124,0.617475,-0.649214,2.025468,-3.556842,-1.204841, + -0.997638,0.009858,0.067986,1.933899,-3.546253,-0.912438, + 0.444124,0.617475,-0.649214,2.025468,-3.556842,-1.204841, + -0.987313,0.097592,0.125253,2.078928,-3.584991,-0.917088, + 0.215809,0.484483,-0.847763,1.83279,-3.296508,-0.865078, + 0.626232,0.565165,-0.53705,1.841888,-3.246003,-1.014774, + 0.52783,0.437826,-0.727807,1.865135,-3.353827,-1.054981, + 0.215809,0.484483,-0.847763,1.83279,-3.296508,-0.865078, + 0.52783,0.437826,-0.727807,1.865135,-3.353827,-1.054981, + -0.955753,-0.169718,0.240275,1.839523,-3.405292,-0.883488, + -0.955753,-0.169718,0.240275,1.839523,-3.405292,-0.883488, + 0.52783,0.437826,-0.727807,1.865135,-3.353827,-1.054981, + 0.862528,0.499882,0.078511,1.919391,-3.487078,-1.110869, + -0.955753,-0.169718,0.240275,1.839523,-3.405292,-0.883488, + 0.862528,0.499882,0.078511,1.919391,-3.487078,-1.110869, + -0.997638,0.009858,0.067986,1.933899,-3.546253,-0.912438, + 0.215809,0.484483,-0.847763,1.83279,-3.296508,-0.865078, + -0.150944,-0.987886,0.036011,1.92973,-3.298418,-0.689538, + -0.630099,-0.773677,0.066329,1.900481,-3.131932,-0.728621, + 0.215809,0.484483,-0.847763,1.83279,-3.296508,-0.865078, + -0.630099,-0.773677,0.066329,1.900481,-3.131932,-0.728621, + -0.783521,-0.393963,-0.480508,1.806407,-3.173343,-0.834455, + 0.215809,0.484483,-0.847763,1.83279,-3.296508,-0.865078, + -0.955753,-0.169718,0.240275,1.839523,-3.405292,-0.883488, + -0.937976,-0.320543,0.132115,1.941325,-3.434803,-0.701314, + 0.215809,0.484483,-0.847763,1.83279,-3.296508,-0.865078, + -0.937976,-0.320543,0.132115,1.941325,-3.434803,-0.701314, + -0.150944,-0.987886,0.036011,1.92973,-3.298418,-0.689538, + -0.937976,-0.320543,0.132115,1.941325,-3.434803,-0.701314, + -0.955753,-0.169718,0.240275,1.839523,-3.405292,-0.883488, + -0.997638,0.009858,0.067986,1.933899,-3.546253,-0.912438, + -0.937976,-0.320543,0.132115,1.941325,-3.434803,-0.701314, + -0.997638,0.009858,0.067986,1.933899,-3.546253,-0.912438, + -0.4909,0.016111,0.871067,2.002745,-3.52342,-0.688103, + -0.4909,0.016111,0.871067,2.002745,-3.52342,-0.688103, + -0.997638,0.009858,0.067986,1.933899,-3.546253,-0.912438, + -0.987313,0.097592,0.125253,2.078928,-3.584991,-0.917088, + -0.4909,0.016111,0.871067,2.002745,-3.52342,-0.688103, + -0.987313,0.097592,0.125253,2.078928,-3.584991,-0.917088, + -0.184432,-0.109597,0.976716,2.126553,-3.549679,-0.701005, + -0.184432,-0.109597,0.976716,2.126553,-3.549679,-0.701005, + -0.987313,0.097592,0.125253,2.078928,-3.584991,-0.917088, + -0.554502,-0.046423,0.830886,2.197935,-3.583948,-0.936437, + -0.184432,-0.109597,0.976716,2.126553,-3.549679,-0.701005, + -0.554502,-0.046423,0.830886,2.197935,-3.583948,-0.936437, + -0.554151,-0.205896,0.806551,2.244147,-3.545557,-0.732888, + -0.069765,-0.126006,0.989573,1.898573,-3.068274,-0.994338, + 0.872426,0.488735,0.003222,1.980621,-3.043895,-0.964237, + -0.228294,-0.186048,-0.955651,2.110033,-3.148257,-1.068816, + -0.069765,-0.126006,0.989573,1.898573,-3.068274,-0.994338, + -0.228294,-0.186048,-0.955651,2.110033,-3.148257,-1.068816, + 0.013288,-0.297478,-0.954636,1.970051,-3.141862,-1.065178, + 0.383337,-0.601981,0.700479,1.855134,-3.083228,-0.986129, + -0.069765,-0.126006,0.989573,1.898573,-3.068274,-0.994338, + 0.013288,-0.297478,-0.954636,1.970051,-3.141862,-1.065178, + 0.383337,-0.601981,0.700479,1.855134,-3.083228,-0.986129, + 0.013288,-0.297478,-0.954636,1.970051,-3.141862,-1.065178, + 0.213417,-0.547723,-0.808983,1.886443,-3.191742,-1.047318, + 0.926951,0.366239,0.081429,1.811797,-3.135641,-0.933096, + 0.383337,-0.601981,0.700479,1.855134,-3.083228,-0.986129, + 0.213417,-0.547723,-0.808983,1.886443,-3.191742,-1.047318, + 0.926951,0.366239,0.081429,1.811797,-3.135641,-0.933096, + 0.213417,-0.547723,-0.808983,1.886443,-3.191742,-1.047318, + 0.626232,0.565165,-0.53705,1.841888,-3.246003,-1.014774, + 0.768072,0.514957,-0.380637,2.217369,-3.156093,-0.888927, + 0.672893,0.661099,-0.331908,2.113587,-3.011851,-0.851648, + -0.701253,0.091018,0.707079,2.07369,-3.020848,-0.782654, + 0.768072,0.514957,-0.380637,2.217369,-3.156093,-0.888927, + -0.701253,0.091018,0.707079,2.07369,-3.020848,-0.782654, + -0.706628,-0.050081,0.705811,2.187495,-3.161535,-0.800285, + -0.495591,0.225654,-0.838731,2.170039,-3.134504,-0.978866, + 0.768072,0.514957,-0.380637,2.217369,-3.156093,-0.888927, + -0.404532,-0.045989,-0.913367,2.236407,-3.220054,-0.89203, + -0.495591,0.225654,-0.838731,2.170039,-3.134504,-0.978866, + -0.404532,-0.045989,-0.913367,2.236407,-3.220054,-0.89203, + -0.492627,0.113675,-0.862784,2.201939,-3.226457,-0.996503, + -0.144755,0.439659,-0.886423,2.247981,-3.342804,-1.127459, + -0.430523,-0.648445,-0.627828,2.281229,-3.33825,-1.043475, + 0.717573,0.343682,0.605781,2.386827,-3.462222,-1.13648, + -0.144755,0.439659,-0.886423,2.247981,-3.342804,-1.127459, + 0.717573,0.343682,0.605781,2.386827,-3.462222,-1.13648, + 0.457854,0.537523,-0.708123,2.343303,-3.507846,-1.195262, + 0.717573,0.343682,0.605781,2.386827,-3.462222,-1.13648, + -0.430523,-0.648445,-0.627828,2.281229,-3.33825,-1.043475, + 0.743895,0.373896,0.553916,2.327021,-3.352317,-0.958234, + 0.717573,0.343682,0.605781,2.386827,-3.462222,-1.13648, + 0.743895,0.373896,0.553916,2.327021,-3.352317,-0.958234, + 0.752232,0.244352,0.611914,2.440236,-3.509564,-1.019417, + 0.743895,0.373896,0.553916,2.327021,-3.352317,-0.958234, + -0.430523,-0.648445,-0.627828,2.281229,-3.33825,-1.043475, + -0.492627,0.113675,-0.862784,2.201939,-3.226457,-0.996503, + 0.743895,0.373896,0.553916,2.327021,-3.352317,-0.958234, + -0.492627,0.113675,-0.862784,2.201939,-3.226457,-0.996503, + -0.404532,-0.045989,-0.913367,2.236407,-3.220054,-0.89203, + 0.752232,0.244352,0.611914,2.440236,-3.509564,-1.019417, + 0.743895,0.373896,0.553916,2.327021,-3.352317,-0.958234, + 0.866542,0.493887,-0.071973,2.309358,-3.345468,-0.801508, + 0.752232,0.244352,0.611914,2.440236,-3.509564,-1.019417, + 0.866542,0.493887,-0.071973,2.309358,-3.345468,-0.801508, + 0.874983,0.217676,-0.43246,2.377814,-3.484109,-0.800332, + 0.866542,0.493887,-0.071973,2.309358,-3.345468,-0.801508, + 0.743895,0.373896,0.553916,2.327021,-3.352317,-0.958234, + -0.404532,-0.045989,-0.913367,2.236407,-3.220054,-0.89203, + 0.866542,0.493887,-0.071973,2.309358,-3.345468,-0.801508, + -0.404532,-0.045989,-0.913367,2.236407,-3.220054,-0.89203, + 0.79991,0.598082,-0.049409,2.235942,-3.243103,-0.823955, + 0.79991,0.598082,-0.049409,2.235942,-3.243103,-0.823955, + -0.404532,-0.045989,-0.913367,2.236407,-3.220054,-0.89203, + 0.768072,0.514957,-0.380637,2.217369,-3.156093,-0.888927, + 0.79991,0.598082,-0.049409,2.235942,-3.243103,-0.823955, + 0.768072,0.514957,-0.380637,2.217369,-3.156093,-0.888927, + -0.706628,-0.050081,0.705811,2.187495,-3.161535,-0.800285, + -0.630099,-0.773677,0.066329,1.900481,-3.131932,-0.728621, + -0.150944,-0.987886,0.036011,1.92973,-3.298418,-0.689538, + 0.331575,0.146631,0.931964,2.059222,-3.230076,-0.674936, + -0.630099,-0.773677,0.066329,1.900481,-3.131932,-0.728621, + 0.331575,0.146631,0.931964,2.059222,-3.230076,-0.674936, + 0.714275,0.465374,0.522723,1.998099,-3.039955,-0.718855, + 0.714275,0.465374,0.522723,1.998099,-3.039955,-0.718855, + 0.331575,0.146631,0.931964,2.059222,-3.230076,-0.674936, + -0.706628,-0.050081,0.705811,2.187495,-3.161535,-0.800285, + 0.714275,0.465374,0.522723,1.998099,-3.039955,-0.718855, + -0.706628,-0.050081,0.705811,2.187495,-3.161535,-0.800285, + -0.701253,0.091018,0.707079,2.07369,-3.020848,-0.782654, + -0.150944,-0.987886,0.036011,1.92973,-3.298418,-0.689538, + -0.937976,-0.320543,0.132115,1.941325,-3.434803,-0.701314, + 0.43336,0.0979,0.895888,2.107985,-3.363571,-0.677007, + -0.150944,-0.987886,0.036011,1.92973,-3.298418,-0.689538, + 0.43336,0.0979,0.895888,2.107985,-3.363571,-0.677007, + 0.331575,0.146631,0.931964,2.059222,-3.230076,-0.674936, + 0.331575,0.146631,0.931964,2.059222,-3.230076,-0.674936, + 0.43336,0.0979,0.895888,2.107985,-3.363571,-0.677007, + 0.79991,0.598082,-0.049409,2.235942,-3.243103,-0.823955, + 0.331575,0.146631,0.931964,2.059222,-3.230076,-0.674936, + 0.79991,0.598082,-0.049409,2.235942,-3.243103,-0.823955, + -0.706628,-0.050081,0.705811,2.187495,-3.161535,-0.800285, + 0.43336,0.0979,0.895888,2.107985,-3.363571,-0.677007, + -0.937976,-0.320543,0.132115,1.941325,-3.434803,-0.701314, + -0.4909,0.016111,0.871067,2.002745,-3.52342,-0.688103, + -0.184432,-0.109597,0.976716,2.126553,-3.549679,-0.701005, + 0.43336,0.0979,0.895888,2.107985,-3.363571,-0.677007, + -0.4909,0.016111,0.871067,2.002745,-3.52342,-0.688103, + 0.79991,0.598082,-0.049409,2.235942,-3.243103,-0.823955, + 0.43336,0.0979,0.895888,2.107985,-3.363571,-0.677007, + 0.866542,0.493887,-0.071973,2.309358,-3.345468,-0.801508, + -0.184432,-0.109597,0.976716,2.126553,-3.549679,-0.701005, + -0.554151,-0.205896,0.806551,2.244147,-3.545557,-0.732888, + 0.43336,0.0979,0.895888,2.107985,-3.363571,-0.677007, + 0.874983,0.217676,-0.43246,2.377814,-3.484109,-0.800332, + 0.866542,0.493887,-0.071973,2.309358,-3.345468,-0.801508, + 0.43336,0.0979,0.895888,2.107985,-3.363571,-0.677007, + 0.874983,0.217676,-0.43246,2.377814,-3.484109,-0.800332, + 0.43336,0.0979,0.895888,2.107985,-3.363571,-0.677007, + -0.554151,-0.205896,0.806551,2.244147,-3.545557,-0.732888, + 0.752232,0.244352,0.611914,2.440236,-3.509564,-1.019417, + 0.874983,0.217676,-0.43246,2.377814,-3.484109,-0.800332, + -0.554151,-0.205896,0.806551,2.244147,-3.545557,-0.732888, + 0.752232,0.244352,0.611914,2.440236,-3.509564,-1.019417, + -0.554151,-0.205896,0.806551,2.244147,-3.545557,-0.732888, + -0.554502,-0.046423,0.830886,2.197935,-3.583948,-0.936437, + -0.987313,0.097592,0.125253,2.078928,-3.584991,-0.917088, + 0.444124,0.617475,-0.649214,2.025468,-3.556842,-1.204841, + -0.081045,0.409121,-0.908874,2.254361,-3.550931,-1.235118, + -0.987313,0.097592,0.125253,2.078928,-3.584991,-0.917088, + -0.081045,0.409121,-0.908874,2.254361,-3.550931,-1.235118, + -0.554502,-0.046423,0.830886,2.197935,-3.583948,-0.936437, + 0.872426,0.488735,0.003222,1.980621,-3.043895,-0.964237, + -0.541077,0.245809,-0.804247,2.091539,-3.032437,-0.947029, + -0.495591,0.225654,-0.838731,2.170039,-3.134504,-0.978866, + -0.554502,-0.046423,0.830886,2.197935,-3.583948,-0.936437, + -0.081045,0.409121,-0.908874,2.254361,-3.550931,-1.235118, + 0.457854,0.537523,-0.708123,2.343303,-3.507846,-1.195262, + -0.554502,-0.046423,0.830886,2.197935,-3.583948,-0.936437, + 0.457854,0.537523,-0.708123,2.343303,-3.507846,-1.195262, + 0.717573,0.343682,0.605781,2.386827,-3.462222,-1.13648, + -0.554502,-0.046423,0.830886,2.197935,-3.583948,-0.936437, + 0.717573,0.343682,0.605781,2.386827,-3.462222,-1.13648, + 0.752232,0.244352,0.611914,2.440236,-3.509564,-1.019417, + -0.545598,-0.330415,-0.770161,-3.042899,-3.193907,-1.207296, + 0.012244,-0.298111,-0.954453,-2.888628,-3.200302,-1.210934, + -0.245482,-0.183395,-0.951896,-2.845816,-3.273661,-1.218321, + -0.545598,-0.330415,-0.770161,-3.042899,-3.193907,-1.207296, + -0.245482,-0.183395,-0.951896,-2.845816,-3.273661,-1.218321, + -0.492859,-0.096405,-0.864752,-2.975439,-3.308754,-1.25324, + -0.492859,-0.096405,-0.864752,-2.975439,-3.308754,-1.25324, + -0.245482,-0.183395,-0.951896,-2.845816,-3.273661,-1.218321, + 0.430301,0.548598,-0.716855,-2.736599,-3.394849,-1.269577, + -0.492859,-0.096405,-0.864752,-2.975439,-3.308754,-1.25324, + 0.430301,0.548598,-0.716855,-2.736599,-3.394849,-1.269577, + -0.074103,0.409269,-0.909399,-2.856957,-3.449728,-1.356844, + -0.074103,0.409269,-0.909399,-2.856957,-3.449728,-1.356844, + 0.430301,0.548598,-0.716855,-2.736599,-3.394849,-1.269577, + -0.13251,0.440061,-0.888137,-2.631547,-3.559891,-1.33738, + -0.074103,0.409269,-0.909399,-2.856957,-3.449728,-1.356844, + -0.13251,0.440061,-0.888137,-2.631547,-3.559891,-1.33738, + 0.317837,0.631876,-0.706903,-2.729567,-3.602976,-1.377236, + 0.317837,0.631876,-0.706903,-2.729567,-3.602976,-1.377236, + 0.413011,0.629609,-0.658038,-2.981824,-3.608887,-1.346959, + 0.009712,0.399549,-0.91666,-3.030627,-3.493327,-1.32265, + 0.317837,0.631876,-0.706903,-2.729567,-3.602976,-1.377236, + 0.009712,0.399549,-0.91666,-3.030627,-3.493327,-1.32265, + -0.074103,0.409269,-0.909399,-2.856957,-3.449728,-1.356844, + -0.074103,0.409269,-0.909399,-2.856957,-3.449728,-1.356844, + 0.009712,0.399549,-0.91666,-3.030627,-3.493327,-1.32265, + 0.070969,0.266956,-0.961092,-3.091252,-3.340925,-1.235864, + -0.074103,0.409269,-0.909399,-2.856957,-3.449728,-1.356844, + 0.070969,0.266956,-0.961092,-3.091252,-3.340925,-1.235864, + -0.492859,-0.096405,-0.864752,-2.975439,-3.308754,-1.25324, + -0.492859,-0.096405,-0.864752,-2.975439,-3.308754,-1.25324, + 0.070969,0.266956,-0.961092,-3.091252,-3.340925,-1.235864, + 0.405633,0.57823,-0.707893,-3.135041,-3.243787,-1.189436, + -0.492859,-0.096405,-0.864752,-2.975439,-3.308754,-1.25324, + 0.405633,0.57823,-0.707893,-3.135041,-3.243787,-1.189436, + -0.545598,-0.330415,-0.770161,-3.042899,-3.193907,-1.207296, + -0.431117,-0.034268,-0.901645,-2.699957,-3.390295,-1.185593, + 0.430301,0.548598,-0.716855,-2.736599,-3.394849,-1.269577, + -0.245482,-0.183395,-0.951896,-2.845816,-3.273661,-1.218321, + -0.431117,-0.034268,-0.901645,-2.699957,-3.390295,-1.185593, + -0.245482,-0.183395,-0.951896,-2.845816,-3.273661,-1.218321, + -0.461794,0.113692,-0.879671,-2.787341,-3.278502,-1.138621, + -0.461794,0.113692,-0.879671,-2.787341,-3.278502,-1.138621, + -0.245482,-0.183395,-0.951896,-2.845816,-3.273661,-1.218321, + 0.012244,-0.298111,-0.954453,-2.888628,-3.200302,-1.210934, + -0.461794,0.113692,-0.879671,-2.787341,-3.278502,-1.138621, + 0.012244,-0.298111,-0.954453,-2.888628,-3.200302,-1.210934, + -0.46316,0.228643,-0.856274,-2.822497,-3.186549,-1.120984, + -0.46316,0.228643,-0.856274,-2.822497,-3.186549,-1.120984, + 0.637284,0.689194,-0.344791,-2.90901,-3.084482,-1.089147, + 0.737412,0.542596,-0.402261,-2.884711,-3.063896,-0.993766, + -0.46316,0.228643,-0.856274,-2.822497,-3.186549,-1.120984, + 0.737412,0.542596,-0.402261,-2.884711,-3.063896,-0.993766, + -0.508358,0.250892,-0.823787,-2.770335,-3.208138,-1.031045, + 0.851754,0.52393,0.003494,-3.184143,-3.298048,-1.156892, + 0.405633,0.57823,-0.707893,-3.135041,-3.243787,-1.189436, + 0.070969,0.266956,-0.961092,-3.091252,-3.340925,-1.235864, + 0.851754,0.52393,0.003494,-3.184143,-3.298048,-1.156892, + 0.070969,0.266956,-0.961092,-3.091252,-3.340925,-1.235864, + 0.596352,0.583149,-0.551635,-3.158524,-3.405872,-1.197099, + 0.840313,0.535537,0.084106,-3.09873,-3.539123,-1.252987, + 0.596352,0.583149,-0.551635,-3.158524,-3.405872,-1.197099, + 0.070969,0.266956,-0.961092,-3.091252,-3.340925,-1.235864, + 0.840313,0.535537,0.084106,-3.09873,-3.539123,-1.252987, + 0.070969,0.266956,-0.961092,-3.091252,-3.340925,-1.235864, + 0.009712,0.399549,-0.91666,-3.030627,-3.493327,-1.32265, + 0.009712,0.399549,-0.91666,-3.030627,-3.493327,-1.32265, + 0.413011,0.629609,-0.658038,-2.981824,-3.608887,-1.346959, + 0.840313,0.535537,0.084106,-3.09873,-3.539123,-1.252987, + 0.503689,0.453945,-0.735004,-3.03125,-3.09594,-1.106355, + -0.46316,0.228643,-0.856274,-2.822497,-3.186549,-1.120984, + 0.012244,-0.298111,-0.954453,-2.888628,-3.200302,-1.210934, + 0.163153,0.19945,-0.96623,-3.223246,-3.225388,-0.976573, + 0.977763,0.208696,-0.020643,-3.217306,-3.187686,-1.075214, + 0.851754,0.52393,0.003494,-3.184143,-3.298048,-1.156892, + 0.163153,0.19945,-0.96623,-3.223246,-3.225388,-0.976573, + 0.851754,0.52393,0.003494,-3.184143,-3.298048,-1.156892, + 0.144389,0.231536,-0.962051,-3.19417,-3.348553,-1.007196, + -0.99734,0.010761,0.072093,-3.082741,-3.598298,-1.054556, + 0.840313,0.535537,0.084106,-3.09873,-3.539123,-1.252987, + 0.413011,0.629609,-0.658038,-2.981824,-3.608887,-1.346959, + -0.99734,0.010761,0.072093,-3.082741,-3.598298,-1.054556, + 0.413011,0.629609,-0.658038,-2.981824,-3.608887,-1.346959, + -0.985013,0.106756,0.135469,-2.922908,-3.637036,-1.059206, + 0.144389,0.231536,-0.962051,-3.19417,-3.348553,-1.007196, + 0.851754,0.52393,0.003494,-3.184143,-3.298048,-1.156892, + 0.596352,0.583149,-0.551635,-3.158524,-3.405872,-1.197099, + 0.144389,0.231536,-0.962051,-3.19417,-3.348553,-1.007196, + 0.596352,0.583149,-0.551635,-3.158524,-3.405872,-1.197099, + -0.948594,-0.185732,0.256269,-3.18675,-3.457336,-1.025606, + -0.948594,-0.185732,0.256269,-3.18675,-3.457336,-1.025606, + 0.596352,0.583149,-0.551635,-3.158524,-3.405872,-1.197099, + 0.840313,0.535537,0.084106,-3.09873,-3.539123,-1.252987, + -0.948594,-0.185732,0.256269,-3.18675,-3.457336,-1.025606, + 0.840313,0.535537,0.084106,-3.09873,-3.539123,-1.252987, + -0.99734,0.010761,0.072093,-3.082741,-3.598298,-1.054556, + 0.144389,0.231536,-0.962051,-3.19417,-3.348553,-1.007196, + -0.471141,0.022027,0.881783,-3.087335,-3.350463,-0.831656, + -0.948594,-0.185732,0.256269,-3.11957,-3.183977,-0.870739, + 0.144389,0.231536,-0.962051,-3.19417,-3.348553,-1.007196, + -0.948594,-0.185732,0.256269,-3.11957,-3.183977,-0.870739, + 0.163153,0.19945,-0.96623,-3.223246,-3.225388,-0.976573, + 0.144389,0.231536,-0.962051,-3.19417,-3.348553,-1.007196, + -0.948594,-0.185732,0.256269,-3.18675,-3.457336,-1.025606, + -0.385346,-0.01874,0.922582,-3.074557,-3.486847,-0.843432, + 0.144389,0.231536,-0.962051,-3.19417,-3.348553,-1.007196, + -0.385346,-0.01874,0.922582,-3.074557,-3.486847,-0.843432, + -0.471141,0.022027,0.881783,-3.087335,-3.350463,-0.831656, + -0.385346,-0.01874,0.922582,-3.074557,-3.486847,-0.843432, + -0.948594,-0.185732,0.256269,-3.18675,-3.457336,-1.025606, + -0.99734,0.010761,0.072093,-3.082741,-3.598298,-1.054556, + -0.385346,-0.01874,0.922582,-3.074557,-3.486847,-0.843432, + -0.99734,0.010761,0.072093,-3.082741,-3.598298,-1.054556, + -0.11646,-0.017993,0.993032,-3.006867,-3.575464,-0.830221, + -0.11646,-0.017993,0.993032,-3.006867,-3.575464,-0.830221, + -0.99734,0.010761,0.072093,-3.082741,-3.598298,-1.054556, + -0.985013,0.106756,0.135469,-2.922908,-3.637036,-1.059206, + -0.11646,-0.017993,0.993032,-3.006867,-3.575464,-0.830221, + -0.985013,0.106756,0.135469,-2.922908,-3.637036,-1.059206, + -0.037581,-0.042039,0.998409,-2.870422,-3.601724,-0.843123, + -0.037581,-0.042039,0.998409,-2.870422,-3.601724,-0.843123, + -0.985013,0.106756,0.135469,-2.922908,-3.637036,-1.059206, + 0.339875,0.026681,0.940092,-2.791754,-3.635993,-1.078555, + -0.037581,-0.042039,0.998409,-2.870422,-3.601724,-0.843123, + 0.339875,0.026681,0.940092,-2.791754,-3.635993,-1.078555, + 0.156207,-0.109405,0.981647,-2.740824,-3.597601,-0.875006, + -0.039603,0.339955,-0.939607,-3.121673,-3.120319,-1.136456, + 0.503689,0.453945,-0.735004,-3.03125,-3.09594,-1.106355, + 0.012244,-0.298111,-0.954453,-2.888628,-3.200302,-1.210934, + -0.039603,0.339955,-0.939607,-3.121673,-3.120319,-1.136456, + 0.012244,-0.298111,-0.954453,-2.888628,-3.200302,-1.210934, + -0.545598,-0.330415,-0.770161,-3.042899,-3.193907,-1.207296, + -0.377491,-0.043727,-0.92498,-3.169546,-3.135273,-1.128247, + -0.039603,0.339955,-0.939607,-3.121673,-3.120319,-1.136456, + -0.545598,-0.330415,-0.770161,-3.042899,-3.193907,-1.207296, + -0.377491,-0.043727,-0.92498,-3.169546,-3.135273,-1.128247, + -0.545598,-0.330415,-0.770161,-3.042899,-3.193907,-1.207296, + 0.405633,0.57823,-0.707893,-3.135041,-3.243787,-1.189436, + 0.977763,0.208696,-0.020643,-3.217306,-3.187686,-1.075214, + -0.377491,-0.043727,-0.92498,-3.169546,-3.135273,-1.128247, + 0.405633,0.57823,-0.707893,-3.135041,-3.243787,-1.189436, + 0.977763,0.208696,-0.020643,-3.217306,-3.187686,-1.075214, + 0.405633,0.57823,-0.707893,-3.135041,-3.243787,-1.189436, + 0.851754,0.52393,0.003494,-3.184143,-3.298048,-1.156892, + -0.508358,0.250892,-0.823787,-2.770335,-3.208138,-1.031045, + 0.737412,0.542596,-0.402261,-2.884711,-3.063896,-0.993766, + 0.684558,0.361154,0.633205,-2.928681,-3.072892,-0.924772, + -0.508358,0.250892,-0.823787,-2.770335,-3.208138,-1.031045, + 0.684558,0.361154,0.633205,-2.928681,-3.072892,-0.924772, + 0.713402,0.39471,0.579018,-2.80326,-3.21358,-0.942403, + -0.46316,0.228643,-0.856274,-2.822497,-3.186549,-1.120984, + -0.508358,0.250892,-0.823787,-2.770335,-3.208138,-1.031045, + 0.845209,0.529004,-0.075999,-2.749355,-3.272099,-1.034148, + -0.46316,0.228643,-0.856274,-2.822497,-3.186549,-1.120984, + 0.845209,0.529004,-0.075999,-2.749355,-3.272099,-1.034148, + -0.461794,0.113692,-0.879671,-2.787341,-3.278502,-1.138621, + 0.430301,0.548598,-0.716855,-2.736599,-3.394849,-1.269577, + -0.431117,-0.034268,-0.901645,-2.699957,-3.390295,-1.185593, + 0.61389,0.702597,-0.359856,-2.58358,-3.514267,-1.278598, + 0.430301,0.548598,-0.716855,-2.736599,-3.394849,-1.269577, + 0.61389,0.702597,-0.359856,-2.58358,-3.514267,-1.278598, + -0.13251,0.440061,-0.888137,-2.631547,-3.559891,-1.33738, + 0.61389,0.702597,-0.359856,-2.58358,-3.514267,-1.278598, + -0.431117,-0.034268,-0.901645,-2.699957,-3.390295,-1.185593, + 0.77125,0.634502,-0.050796,-2.649491,-3.404362,-1.100352, + 0.61389,0.702597,-0.359856,-2.58358,-3.514267,-1.278598, + 0.77125,0.634502,-0.050796,-2.649491,-3.404362,-1.100352, + 0.780958,0.624512,-0.009449,-2.52472,-3.561609,-1.161535, + 0.77125,0.634502,-0.050796,-2.649491,-3.404362,-1.100352, + -0.431117,-0.034268,-0.901645,-2.699957,-3.390295,-1.185593, + -0.461794,0.113692,-0.879671,-2.787341,-3.278502,-1.138621, + 0.77125,0.634502,-0.050796,-2.649491,-3.404362,-1.100352, + -0.461794,0.113692,-0.879671,-2.787341,-3.278502,-1.138621, + 0.845209,0.529004,-0.075999,-2.749355,-3.272099,-1.034148, + 0.780958,0.624512,-0.009449,-2.52472,-3.561609,-1.161535, + 0.77125,0.634502,-0.050796,-2.649491,-3.404362,-1.100352, + 0.684834,0.490952,0.538488,-2.668957,-3.397513,-0.943626, + 0.780958,0.624512,-0.009449,-2.52472,-3.561609,-1.161535, + 0.684834,0.490952,0.538488,-2.668957,-3.397513,-0.943626, + 0.712283,0.385667,0.586441,-2.593513,-3.536154,-0.94245, + 0.684834,0.490952,0.538488,-2.668957,-3.397513,-0.943626, + 0.77125,0.634502,-0.050796,-2.649491,-3.404362,-1.100352, + 0.845209,0.529004,-0.075999,-2.749355,-3.272099,-1.034148, + 0.684834,0.490952,0.538488,-2.668957,-3.397513,-0.943626, + 0.845209,0.529004,-0.075999,-2.749355,-3.272099,-1.034148, + 0.722848,0.455753,0.519404,-2.749867,-3.295148,-0.966073, + 0.722848,0.455753,0.519404,-2.749867,-3.295148,-0.966073, + 0.845209,0.529004,-0.075999,-2.749355,-3.272099,-1.034148, + -0.508358,0.250892,-0.823787,-2.770335,-3.208138,-1.031045, + 0.722848,0.455753,0.519404,-2.749867,-3.295148,-0.966073, + -0.508358,0.250892,-0.823787,-2.770335,-3.208138,-1.031045, + 0.713402,0.39471,0.579018,-2.80326,-3.21358,-0.942403, + -0.948594,-0.185732,0.256269,-3.11957,-3.183977,-0.870739, + -0.471141,0.022027,0.881783,-3.087335,-3.350463,-0.831656, + 0.225987,0.181605,0.957053,-2.944625,-3.282121,-0.817054, + -0.948594,-0.185732,0.256269,-3.11957,-3.183977,-0.870739, + 0.225987,0.181605,0.957053,-2.944625,-3.282121,-0.817054, + 0.308087,0.149605,0.939521,-3.011987,-3.092,-0.860973, + 0.308087,0.149605,0.939521,-3.011987,-3.092,-0.860973, + 0.225987,0.181605,0.957053,-2.944625,-3.282121,-0.817054, + 0.713402,0.39471,0.579018,-2.80326,-3.21358,-0.942403, + 0.308087,0.149605,0.939521,-3.011987,-3.092,-0.860973, + 0.713402,0.39471,0.579018,-2.80326,-3.21358,-0.942403, + 0.684558,0.361154,0.633205,-2.928681,-3.072892,-0.924772, + -0.471141,0.022027,0.881783,-3.087335,-3.350463,-0.831656, + -0.385346,-0.01874,0.922582,-3.074557,-3.486847,-0.843432, + 0.229413,0.089674,0.96919,-2.890885,-3.415616,-0.819125, + -0.471141,0.022027,0.881783,-3.087335,-3.350463,-0.831656, + 0.229413,0.089674,0.96919,-2.890885,-3.415616,-0.819125, + 0.225987,0.181605,0.957053,-2.944625,-3.282121,-0.817054, + 0.225987,0.181605,0.957053,-2.944625,-3.282121,-0.817054, + 0.229413,0.089674,0.96919,-2.890885,-3.415616,-0.819125, + 0.722848,0.455753,0.519404,-2.749867,-3.295148,-0.966073, + 0.225987,0.181605,0.957053,-2.944625,-3.282121,-0.817054, + 0.722848,0.455753,0.519404,-2.749867,-3.295148,-0.966073, + 0.713402,0.39471,0.579018,-2.80326,-3.21358,-0.942403, + 0.229413,0.089674,0.96919,-2.890885,-3.415616,-0.819125, + -0.385346,-0.01874,0.922582,-3.074557,-3.486847,-0.843432, + -0.11646,-0.017993,0.993032,-3.006867,-3.575464,-0.830221, + -0.037581,-0.042039,0.998409,-2.870422,-3.601724,-0.843123, + 0.229413,0.089674,0.96919,-2.890885,-3.415616,-0.819125, + -0.11646,-0.017993,0.993032,-3.006867,-3.575464,-0.830221, + 0.722848,0.455753,0.519404,-2.749867,-3.295148,-0.966073, + 0.229413,0.089674,0.96919,-2.890885,-3.415616,-0.819125, + 0.684834,0.490952,0.538488,-2.668957,-3.397513,-0.943626, + -0.037581,-0.042039,0.998409,-2.870422,-3.601724,-0.843123, + 0.156207,-0.109405,0.981647,-2.740824,-3.597601,-0.875006, + 0.229413,0.089674,0.96919,-2.890885,-3.415616,-0.819125, + 0.712283,0.385667,0.586441,-2.593513,-3.536154,-0.94245, + 0.684834,0.490952,0.538488,-2.668957,-3.397513,-0.943626, + 0.229413,0.089674,0.96919,-2.890885,-3.415616,-0.819125, + 0.712283,0.385667,0.586441,-2.593513,-3.536154,-0.94245, + 0.229413,0.089674,0.96919,-2.890885,-3.415616,-0.819125, + 0.156207,-0.109405,0.981647,-2.740824,-3.597601,-0.875006, + 0.780958,0.624512,-0.009449,-2.52472,-3.561609,-1.161535, + 0.712283,0.385667,0.586441,-2.593513,-3.536154,-0.94245, + 0.156207,-0.109405,0.981647,-2.740824,-3.597601,-0.875006, + 0.780958,0.624512,-0.009449,-2.52472,-3.561609,-1.161535, + 0.156207,-0.109405,0.981647,-2.740824,-3.597601,-0.875006, + 0.339875,0.026681,0.940092,-2.791754,-3.635993,-1.078555, + -0.985013,0.106756,0.135469,-2.922908,-3.637036,-1.059206, + 0.413011,0.629609,-0.658038,-2.981824,-3.608887,-1.346959, + 0.317837,0.631876,-0.706903,-2.729567,-3.602976,-1.377236, + -0.985013,0.106756,0.135469,-2.922908,-3.637036,-1.059206, + 0.317837,0.631876,-0.706903,-2.729567,-3.602976,-1.377236, + 0.339875,0.026681,0.940092,-2.791754,-3.635993,-1.078555, + 0.503689,0.453945,-0.735004,-3.03125,-3.09594,-1.106355, + 0.637284,0.689194,-0.344791,-2.90901,-3.084482,-1.089147, + -0.46316,0.228643,-0.856274,-2.822497,-3.186549,-1.120984, + 0.339875,0.026681,0.940092,-2.791754,-3.635993,-1.078555, + 0.317837,0.631876,-0.706903,-2.729567,-3.602976,-1.377236, + -0.13251,0.440061,-0.888137,-2.631547,-3.559891,-1.33738, + 0.339875,0.026681,0.940092,-2.791754,-3.635993,-1.078555, + -0.13251,0.440061,-0.888137,-2.631547,-3.559891,-1.33738, + 0.61389,0.702597,-0.359856,-2.58358,-3.514267,-1.278598, + 0.339875,0.026681,0.940092,-2.791754,-3.635993,-1.078555, + 0.61389,0.702597,-0.359856,-2.58358,-3.514267,-1.278598, + 0.780958,0.624512,-0.009449,-2.52472,-3.561609,-1.161535, + -0.35872,0.092902,0.928811,2.031262,-3.256709,1.111122, + -0.354049,-0.10839,0.928924,2.14888,-3.221616,1.076203, + 0.422569,-0.18743,0.886739,2.110033,-3.148257,1.068816, + -0.35872,0.092902,0.928811,2.031262,-3.256709,1.111122, + 0.422569,-0.18743,0.886739,2.110033,-3.148257,1.068816, + -0.019303,-0.142974,0.989538,1.970051,-3.141862,1.065178, + -0.501053,-0.05946,0.863371,2.138771,-3.397683,1.214726, + -0.453746,-0.057149,0.889297,2.247981,-3.342804,1.127459, + -0.354049,-0.10839,0.928924,2.14888,-3.221616,1.076203, + -0.501053,-0.05946,0.863371,2.138771,-3.397683,1.214726, + -0.354049,-0.10839,0.928924,2.14888,-3.221616,1.076203, + -0.35872,0.092902,0.928811,2.031262,-3.256709,1.111122, + -0.765488,-0.115047,0.633082,2.254361,-3.550931,1.235118, + -0.779685,0.02537,0.625657,2.343303,-3.507846,1.195262, + -0.453746,-0.057149,0.889297,2.247981,-3.342804,1.127459, + -0.765488,-0.115047,0.633082,2.254361,-3.550931,1.235118, + -0.453746,-0.057149,0.889297,2.247981,-3.342804,1.127459, + -0.501053,-0.05946,0.863371,2.138771,-3.397683,1.214726, + -0.501053,-0.05946,0.863371,2.138771,-3.397683,1.214726, + 0.982106,-0.010346,0.188044,1.981186,-3.441282,1.180532, + -0.807765,-0.096776,0.581507,2.025468,-3.556842,1.204841, + -0.501053,-0.05946,0.863371,2.138771,-3.397683,1.214726, + -0.807765,-0.096776,0.581507,2.025468,-3.556842,1.204841, + -0.765488,-0.115047,0.633082,2.254361,-3.550931,1.235118, + -0.35872,0.092902,0.928811,2.031262,-3.256709,1.111122, + 0.937141,-0.149709,0.315204,1.926176,-3.28888,1.093746, + 0.982106,-0.010346,0.188044,1.981186,-3.441282,1.180532, + -0.35872,0.092902,0.928811,2.031262,-3.256709,1.111122, + 0.982106,-0.010346,0.188044,1.981186,-3.441282,1.180532, + -0.501053,-0.05946,0.863371,2.138771,-3.397683,1.214726, + -0.019303,-0.142974,0.989538,1.970051,-3.141862,1.065178, + 0.866898,-0.268351,0.420091,1.886443,-3.191742,1.047318, + 0.937141,-0.149709,0.315204,1.926176,-3.28888,1.093746, + -0.019303,-0.142974,0.989538,1.970051,-3.141862,1.065178, + 0.937141,-0.149709,0.315204,1.926176,-3.28888,1.093746, + -0.35872,0.092902,0.928811,2.031262,-3.256709,1.111122, + 0.567579,-0.469834,-0.6761,2.201939,-3.226457,0.996503, + -0.354049,-0.10839,0.928924,2.14888,-3.221616,1.076203, + -0.453746,-0.057149,0.889297,2.247981,-3.342804,1.127459, + 0.567579,-0.469834,-0.6761,2.201939,-3.226457,0.996503, + -0.453746,-0.057149,0.889297,2.247981,-3.342804,1.127459, + 0.886562,-0.46255,0.007486,2.281229,-3.33825,1.043475, + 0.890357,-0.340018,-0.302742,2.170039,-3.134504,0.978866, + 0.422569,-0.18743,0.886739,2.110033,-3.148257,1.068816, + -0.354049,-0.10839,0.928924,2.14888,-3.221616,1.076203, + 0.890357,-0.340018,-0.302742,2.170039,-3.134504,0.978866, + -0.354049,-0.10839,0.928924,2.14888,-3.221616,1.076203, + 0.567579,-0.469834,-0.6761,2.201939,-3.226457,0.996503, + 0.579344,-0.339433,-0.741044,2.217369,-3.156093,0.888927, + 0.789099,-0.039289,-0.613008,2.113587,-3.011851,0.851648, + 0.773659,-0.235087,-0.588375,2.091539,-3.032437,0.947029, + 0.579344,-0.339433,-0.741044,2.217369,-3.156093,0.888927, + 0.773659,-0.235087,-0.588375,2.091539,-3.032437,0.947029, + 0.890357,-0.340018,-0.302742,2.170039,-3.134504,0.978866, + 0.257818,-0.230014,-0.938415,1.865135,-3.353827,1.054981, + 0.937141,-0.149709,0.315204,1.926176,-3.28888,1.093746, + 0.866898,-0.268351,0.420091,1.886443,-3.191742,1.047318, + 0.257818,-0.230014,-0.938415,1.865135,-3.353827,1.054981, + 0.866898,-0.268351,0.420091,1.886443,-3.191742,1.047318, + 0.230893,-0.309688,-0.922378,1.841888,-3.246003,1.014774, + 0.982106,-0.010346,0.188044,1.981186,-3.441282,1.180532, + 0.937141,-0.149709,0.315204,1.926176,-3.28888,1.093746, + 0.257818,-0.230014,-0.938415,1.865135,-3.353827,1.054981, + 0.982106,-0.010346,0.188044,1.981186,-3.441282,1.180532, + 0.257818,-0.230014,-0.938415,1.865135,-3.353827,1.054981, + 0.148388,-0.325205,-0.933929,1.919391,-3.487078,1.110869, + 0.148388,-0.325205,-0.933929,1.919391,-3.487078,1.110869, + -0.807765,-0.096776,0.581507,2.025468,-3.556842,1.204841, + 0.982106,-0.010346,0.188044,1.981186,-3.441282,1.180532, + 0.422569,-0.18743,0.886739,2.110033,-3.148257,1.068816, + 0.890357,-0.340018,-0.302742,2.170039,-3.134504,0.978866, + -0.215783,-0.895808,-0.388544,1.980621,-3.043895,0.964237, + -0.085416,-0.081635,-0.992995,1.83279,-3.296508,0.865078, + 0.230893,-0.309688,-0.922378,1.841888,-3.246003,1.014774, + -0.156447,-0.088128,0.983747,1.811797,-3.135641,0.933096, + -0.085416,-0.081635,-0.992995,1.83279,-3.296508,0.865078, + -0.156447,-0.088128,0.983747,1.811797,-3.135641,0.933096, + -0.042094,-0.220101,-0.974568,1.806407,-3.173343,0.834455, + -0.348227,-0.192527,-0.917427,2.078928,-3.584991,0.917088, + -0.807765,-0.096776,0.581507,2.025468,-3.556842,1.204841, + 0.148388,-0.325205,-0.933929,1.919391,-3.487078,1.110869, + -0.348227,-0.192527,-0.917427,2.078928,-3.584991,0.917088, + 0.148388,-0.325205,-0.933929,1.919391,-3.487078,1.110869, + 0.255431,-0.055528,-0.965231,1.933899,-3.546253,0.912438, + -0.401279,-0.250965,-0.880904,1.839523,-3.405292,0.883488, + 0.257818,-0.230014,-0.938415,1.865135,-3.353827,1.054981, + 0.230893,-0.309688,-0.922378,1.841888,-3.246003,1.014774, + -0.401279,-0.250965,-0.880904,1.839523,-3.405292,0.883488, + 0.230893,-0.309688,-0.922378,1.841888,-3.246003,1.014774, + -0.085416,-0.081635,-0.992995,1.83279,-3.296508,0.865078, + 0.255431,-0.055528,-0.965231,1.933899,-3.546253,0.912438, + 0.148388,-0.325205,-0.933929,1.919391,-3.487078,1.110869, + 0.257818,-0.230014,-0.938415,1.865135,-3.353827,1.054981, + 0.255431,-0.055528,-0.965231,1.933899,-3.546253,0.912438, + 0.257818,-0.230014,-0.938415,1.865135,-3.353827,1.054981, + -0.401279,-0.250965,-0.880904,1.839523,-3.405292,0.883488, + -0.042094,-0.220101,-0.974568,1.806407,-3.173343,0.834455, + -0.363523,-0.150625,-0.919327,1.900481,-3.131932,0.728621, + -0.924461,-0.213385,-0.315973,1.92973,-3.298418,0.689538, + -0.042094,-0.220101,-0.974568,1.806407,-3.173343,0.834455, + -0.924461,-0.213385,-0.315973,1.92973,-3.298418,0.689538, + -0.085416,-0.081635,-0.992995,1.83279,-3.296508,0.865078, + -0.924461,-0.213385,-0.315973,1.92973,-3.298418,0.689538, + -0.914496,-0.253607,-0.315247,1.941325,-3.434803,0.701314, + -0.401279,-0.250965,-0.880904,1.839523,-3.405292,0.883488, + -0.924461,-0.213385,-0.315973,1.92973,-3.298418,0.689538, + -0.401279,-0.250965,-0.880904,1.839523,-3.405292,0.883488, + -0.085416,-0.081635,-0.992995,1.83279,-3.296508,0.865078, + -0.943599,-0.160394,-0.289646,2.002745,-3.52342,0.688103, + 0.255431,-0.055528,-0.965231,1.933899,-3.546253,0.912438, + -0.401279,-0.250965,-0.880904,1.839523,-3.405292,0.883488, + -0.943599,-0.160394,-0.289646,2.002745,-3.52342,0.688103, + -0.401279,-0.250965,-0.880904,1.839523,-3.405292,0.883488, + -0.914496,-0.253607,-0.315247,1.941325,-3.434803,0.701314, + 0.601229,-0.111151,-0.791308,2.126553,-3.549679,0.701005, + -0.348227,-0.192527,-0.917427,2.078928,-3.584991,0.917088, + 0.255431,-0.055528,-0.965231,1.933899,-3.546253,0.912438, + 0.601229,-0.111151,-0.791308,2.126553,-3.549679,0.701005, + 0.255431,-0.055528,-0.965231,1.933899,-3.546253,0.912438, + -0.943599,-0.160394,-0.289646,2.002745,-3.52342,0.688103, + 0.53288,-0.088285,-0.841572,2.244147,-3.545557,0.732888, + 0.546571,-0.125171,-0.828005,2.197935,-3.583948,0.936437, + -0.348227,-0.192527,-0.917427,2.078928,-3.584991,0.917088, + 0.53288,-0.088285,-0.841572,2.244147,-3.545557,0.732888, + -0.348227,-0.192527,-0.917427,2.078928,-3.584991,0.917088, + 0.601229,-0.111151,-0.791308,2.126553,-3.549679,0.701005, + -0.019303,-0.142974,0.989538,1.970051,-3.141862,1.065178, + 0.422569,-0.18743,0.886739,2.110033,-3.148257,1.068816, + -0.215783,-0.895808,-0.388544,1.980621,-3.043895,0.964237, + -0.019303,-0.142974,0.989538,1.970051,-3.141862,1.065178, + -0.215783,-0.895808,-0.388544,1.980621,-3.043895,0.964237, + 0.356923,-0.210291,0.910156,1.898573,-3.068274,0.994338, + 0.866898,-0.268351,0.420091,1.886443,-3.191742,1.047318, + -0.019303,-0.142974,0.989538,1.970051,-3.141862,1.065178, + 0.356923,-0.210291,0.910156,1.898573,-3.068274,0.994338, + 0.866898,-0.268351,0.420091,1.886443,-3.191742,1.047318, + 0.356923,-0.210291,0.910156,1.898573,-3.068274,0.994338, + 0.517272,-0.552302,0.653753,1.855134,-3.083228,0.986129, + 0.230893,-0.309688,-0.922378,1.841888,-3.246003,1.014774, + 0.866898,-0.268351,0.420091,1.886443,-3.191742,1.047318, + 0.517272,-0.552302,0.653753,1.855134,-3.083228,0.986129, + 0.230893,-0.309688,-0.922378,1.841888,-3.246003,1.014774, + 0.517272,-0.552302,0.653753,1.855134,-3.083228,0.986129, + -0.156447,-0.088128,0.983747,1.811797,-3.135641,0.933096, + -0.156072,0.243426,0.95728,2.187495,-3.161535,0.800285, + -0.080858,0.024731,0.996419,2.07369,-3.020848,0.782654, + 0.789099,-0.039289,-0.613008,2.113587,-3.011851,0.851648, + -0.156072,0.243426,0.95728,2.187495,-3.161535,0.800285, + 0.789099,-0.039289,-0.613008,2.113587,-3.011851,0.851648, + 0.579344,-0.339433,-0.741044,2.217369,-3.156093,0.888927, + 0.567579,-0.469834,-0.6761,2.201939,-3.226457,0.996503, + -0.661663,-0.025481,0.749369,2.236407,-3.220054,0.89203, + 0.579344,-0.339433,-0.741044,2.217369,-3.156093,0.888927, + 0.567579,-0.469834,-0.6761,2.201939,-3.226457,0.996503, + 0.579344,-0.339433,-0.741044,2.217369,-3.156093,0.888927, + 0.890357,-0.340018,-0.302742,2.170039,-3.134504,0.978866, + -0.779685,0.02537,0.625657,2.343303,-3.507846,1.195262, + 0.507452,0.36284,0.781562,2.386827,-3.462222,1.13648, + 0.886562,-0.46255,0.007486,2.281229,-3.33825,1.043475, + -0.779685,0.02537,0.625657,2.343303,-3.507846,1.195262, + 0.886562,-0.46255,0.007486,2.281229,-3.33825,1.043475, + -0.453746,-0.057149,0.889297,2.247981,-3.342804,1.127459, + 0.121953,0.140869,0.982488,2.440236,-3.509564,1.019417, + 0.484364,0.195735,0.85269,2.327021,-3.352317,0.958234, + 0.886562,-0.46255,0.007486,2.281229,-3.33825,1.043475, + 0.121953,0.140869,0.982488,2.440236,-3.509564,1.019417, + 0.886562,-0.46255,0.007486,2.281229,-3.33825,1.043475, + 0.507452,0.36284,0.781562,2.386827,-3.462222,1.13648, + -0.661663,-0.025481,0.749369,2.236407,-3.220054,0.89203, + 0.567579,-0.469834,-0.6761,2.201939,-3.226457,0.996503, + 0.886562,-0.46255,0.007486,2.281229,-3.33825,1.043475, + -0.661663,-0.025481,0.749369,2.236407,-3.220054,0.89203, + 0.886562,-0.46255,0.007486,2.281229,-3.33825,1.043475, + 0.484364,0.195735,0.85269,2.327021,-3.352317,0.958234, + 0.913315,0.39776,-0.087428,2.377814,-3.484109,0.800332, + 0.170703,0.25395,0.952035,2.309358,-3.345468,0.801508, + 0.484364,0.195735,0.85269,2.327021,-3.352317,0.958234, + 0.913315,0.39776,-0.087428,2.377814,-3.484109,0.800332, + 0.484364,0.195735,0.85269,2.327021,-3.352317,0.958234, + 0.121953,0.140869,0.982488,2.440236,-3.509564,1.019417, + 0.977763,0.208696,0.020643,2.235942,-3.243103,0.823955, + -0.661663,-0.025481,0.749369,2.236407,-3.220054,0.89203, + 0.484364,0.195735,0.85269,2.327021,-3.352317,0.958234, + 0.977763,0.208696,0.020643,2.235942,-3.243103,0.823955, + 0.484364,0.195735,0.85269,2.327021,-3.352317,0.958234, + 0.170703,0.25395,0.952035,2.309358,-3.345468,0.801508, + -0.156072,0.243426,0.95728,2.187495,-3.161535,0.800285, + 0.579344,-0.339433,-0.741044,2.217369,-3.156093,0.888927, + -0.661663,-0.025481,0.749369,2.236407,-3.220054,0.89203, + -0.156072,0.243426,0.95728,2.187495,-3.161535,0.800285, + -0.661663,-0.025481,0.749369,2.236407,-3.220054,0.89203, + 0.977763,0.208696,0.020643,2.235942,-3.243103,0.823955, + -0.245482,-0.183394,0.951896,1.998099,-3.039955,0.718855, + 0.430301,0.548598,0.716855,2.059222,-3.230076,0.674936, + -0.924461,-0.213385,-0.315973,1.92973,-3.298418,0.689538, + -0.245482,-0.183394,0.951896,1.998099,-3.039955,0.718855, + -0.924461,-0.213385,-0.315973,1.92973,-3.298418,0.689538, + -0.363523,-0.150625,-0.919327,1.900481,-3.131932,0.728621, + -0.080858,0.024731,0.996419,2.07369,-3.020848,0.782654, + -0.156072,0.243426,0.95728,2.187495,-3.161535,0.800285, + 0.430301,0.548598,0.716855,2.059222,-3.230076,0.674936, + -0.080858,0.024731,0.996419,2.07369,-3.020848,0.782654, + 0.430301,0.548598,0.716855,2.059222,-3.230076,0.674936, + -0.245482,-0.183394,0.951896,1.998099,-3.039955,0.718855, + 0.430301,0.548598,0.716855,2.059222,-3.230076,0.674936, + 0.317836,0.631876,0.706903,2.107985,-3.363571,0.677007, + -0.914496,-0.253607,-0.315247,1.941325,-3.434803,0.701314, + 0.430301,0.548598,0.716855,2.059222,-3.230076,0.674936, + -0.914496,-0.253607,-0.315247,1.941325,-3.434803,0.701314, + -0.924461,-0.213385,-0.315973,1.92973,-3.298418,0.689538, + -0.156072,0.243426,0.95728,2.187495,-3.161535,0.800285, + 0.977763,0.208696,0.020643,2.235942,-3.243103,0.823955, + 0.317836,0.631876,0.706903,2.107985,-3.363571,0.677007, + -0.156072,0.243426,0.95728,2.187495,-3.161535,0.800285, + 0.317836,0.631876,0.706903,2.107985,-3.363571,0.677007, + 0.430301,0.548598,0.716855,2.059222,-3.230076,0.674936, + -0.943599,-0.160394,-0.289646,2.002745,-3.52342,0.688103, + -0.914496,-0.253607,-0.315247,1.941325,-3.434803,0.701314, + 0.317836,0.631876,0.706903,2.107985,-3.363571,0.677007, + -0.943599,-0.160394,-0.289646,2.002745,-3.52342,0.688103, + 0.317836,0.631876,0.706903,2.107985,-3.363571,0.677007, + 0.601229,-0.111151,-0.791308,2.126553,-3.549679,0.701005, + 0.170703,0.25395,0.952035,2.309358,-3.345468,0.801508, + 0.317836,0.631876,0.706903,2.107985,-3.363571,0.677007, + 0.977763,0.208696,0.020643,2.235942,-3.243103,0.823955, + 0.317836,0.631876,0.706903,2.107985,-3.363571,0.677007, + 0.53288,-0.088285,-0.841572,2.244147,-3.545557,0.732888, + 0.601229,-0.111151,-0.791308,2.126553,-3.549679,0.701005, + 0.53288,-0.088285,-0.841572,2.244147,-3.545557,0.732888, + 0.317836,0.631876,0.706903,2.107985,-3.363571,0.677007, + 0.170703,0.25395,0.952035,2.309358,-3.345468,0.801508, + 0.53288,-0.088285,-0.841572,2.244147,-3.545557,0.732888, + 0.170703,0.25395,0.952035,2.309358,-3.345468,0.801508, + 0.913315,0.39776,-0.087428,2.377814,-3.484109,0.800332, + 0.546571,-0.125171,-0.828005,2.197935,-3.583948,0.936437, + 0.53288,-0.088285,-0.841572,2.244147,-3.545557,0.732888, + 0.913315,0.39776,-0.087428,2.377814,-3.484109,0.800332, + 0.546571,-0.125171,-0.828005,2.197935,-3.583948,0.936437, + 0.913315,0.39776,-0.087428,2.377814,-3.484109,0.800332, + 0.121953,0.140869,0.982488,2.440236,-3.509564,1.019417, + 0.546571,-0.125171,-0.828005,2.197935,-3.583948,0.936437, + -0.765488,-0.115047,0.633082,2.254361,-3.550931,1.235118, + -0.807765,-0.096776,0.581507,2.025468,-3.556842,1.204841, + 0.546571,-0.125171,-0.828005,2.197935,-3.583948,0.936437, + -0.807765,-0.096776,0.581507,2.025468,-3.556842,1.204841, + -0.348227,-0.192527,-0.917427,2.078928,-3.584991,0.917088, + 0.890357,-0.340018,-0.302742,2.170039,-3.134504,0.978866, + 0.773659,-0.235087,-0.588375,2.091539,-3.032437,0.947029, + -0.215783,-0.895808,-0.388544,1.980621,-3.043895,0.964237, + 0.121953,0.140869,0.982488,2.440236,-3.509564,1.019417, + 0.507452,0.36284,0.781562,2.386827,-3.462222,1.13648, + -0.779685,0.02537,0.625657,2.343303,-3.507846,1.195262, + 0.121953,0.140869,0.982488,2.440236,-3.509564,1.019417, + -0.779685,0.02537,0.625657,2.343303,-3.507846,1.195262, + -0.765488,-0.115047,0.633082,2.254361,-3.550931,1.235118, + 0.121953,0.140869,0.982488,2.440236,-3.509564,1.019417, + -0.765488,-0.115047,0.633082,2.254361,-3.550931,1.235118, + 0.546571,-0.125171,-0.828005,2.197935,-3.583948,0.936437, + 0.205604,0.070037,0.976126,-2.975439,-3.308754,1.25324, + 0.193496,0.00102,0.981101,-2.845816,-3.273661,1.218321, + 0.254799,-0.149124,0.955426,-2.888628,-3.200302,1.210934, + 0.205604,0.070037,0.976126,-2.975439,-3.308754,1.25324, + 0.254799,-0.149124,0.955426,-2.888628,-3.200302,1.210934, + 0.405755,-0.293021,0.865737,-3.042899,-3.193907,1.207296, + 0.580504,-0.526296,0.621312,-2.856957,-3.449728,1.356844, + 0.011655,0.055061,0.998415,-2.736599,-3.394849,1.269577, + 0.193496,0.00102,0.981101,-2.845816,-3.273661,1.218321, + 0.580504,-0.526296,0.621312,-2.856957,-3.449728,1.356844, + 0.193496,0.00102,0.981101,-2.845816,-3.273661,1.218321, + 0.205604,0.070037,0.976126,-2.975439,-3.308754,1.25324, + -0.093334,0.204552,0.974396,-2.729567,-3.602976,1.377236, + -0.026425,0.178249,0.983631,-2.631547,-3.559891,1.33738, + 0.011655,0.055061,0.998415,-2.736599,-3.394849,1.269577, + -0.093334,0.204552,0.974396,-2.729567,-3.602976,1.377236, + 0.011655,0.055061,0.998415,-2.736599,-3.394849,1.269577, + 0.580504,-0.526296,0.621312,-2.856957,-3.449728,1.356844, + 0.580504,-0.526296,0.621312,-2.856957,-3.449728,1.356844, + -0.028076,0.054588,0.998114,-3.030627,-3.493327,1.32265, + -0.057735,0.03099,0.997851,-2.981824,-3.608887,1.346959, + 0.580504,-0.526296,0.621312,-2.856957,-3.449728,1.356844, + -0.057735,0.03099,0.997851,-2.981824,-3.608887,1.346959, + -0.093334,0.204552,0.974396,-2.729567,-3.602976,1.377236, + 0.205604,0.070037,0.976126,-2.975439,-3.308754,1.25324, + 0.089482,-0.029551,0.99555,-3.091252,-3.340925,1.235864, + -0.028076,0.054588,0.998114,-3.030627,-3.493327,1.32265, + 0.205604,0.070037,0.976126,-2.975439,-3.308754,1.25324, + -0.028076,0.054588,0.998114,-3.030627,-3.493327,1.32265, + 0.580504,-0.526296,0.621312,-2.856957,-3.449728,1.356844, + 0.405755,-0.293021,0.865737,-3.042899,-3.193907,1.207296, + 0.487947,-0.44627,0.750167,-3.135041,-3.243787,1.189436, + 0.089482,-0.029551,0.99555,-3.091252,-3.340925,1.235864, + 0.405755,-0.293021,0.865737,-3.042899,-3.193907,1.207296, + 0.089482,-0.029551,0.99555,-3.091252,-3.340925,1.235864, + 0.205604,0.070037,0.976126,-2.975439,-3.308754,1.25324, + 0.177373,0.037311,0.983436,-2.787341,-3.278502,1.138621, + 0.193496,0.00102,0.981101,-2.845816,-3.273661,1.218321, + 0.011655,0.055061,0.998415,-2.736599,-3.394849,1.269577, + 0.177373,0.037311,0.983436,-2.787341,-3.278502,1.138621, + 0.011655,0.055061,0.998415,-2.736599,-3.394849,1.269577, + -0.048366,0.138166,0.989227,-2.699957,-3.390295,1.185593, + -0.308543,0.191148,0.931807,-2.822497,-3.186549,1.120984, + 0.254799,-0.149124,0.955426,-2.888628,-3.200302,1.210934, + 0.193496,0.00102,0.981101,-2.845816,-3.273661,1.218321, + -0.308543,0.191148,0.931807,-2.822497,-3.186549,1.120984, + 0.193496,0.00102,0.981101,-2.845816,-3.273661,1.218321, + 0.177373,0.037311,0.983436,-2.787341,-3.278502,1.138621, + -0.206994,0.072903,0.975622,-2.770335,-3.208138,1.031045, + -0.161613,0.16539,0.972896,-2.884711,-3.063896,0.993766, + 0.07463,0.029476,0.996776,-2.90901,-3.084482,1.089147, + -0.206994,0.072903,0.975622,-2.770335,-3.208138,1.031045, + 0.07463,0.029476,0.996776,-2.90901,-3.084482,1.089147, + -0.308543,0.191148,0.931807,-2.822497,-3.186549,1.120984, + -0.730585,0.298655,0.614045,-3.158524,-3.405872,1.197099, + 0.089482,-0.029551,0.99555,-3.091252,-3.340925,1.235864, + 0.487947,-0.44627,0.750167,-3.135041,-3.243787,1.189436, + -0.730585,0.298655,0.614045,-3.158524,-3.405872,1.197099, + 0.487947,-0.44627,0.750167,-3.135041,-3.243787,1.189436, + -0.059163,0.13391,0.989226,-3.184143,-3.298048,1.156892, + -0.028076,0.054588,0.998114,-3.030627,-3.493327,1.32265, + 0.089482,-0.029551,0.99555,-3.091252,-3.340925,1.235864, + -0.730585,0.298655,0.614045,-3.158524,-3.405872,1.197099, + -0.028076,0.054588,0.998114,-3.030627,-3.493327,1.32265, + -0.730585,0.298655,0.614045,-3.158524,-3.405872,1.197099, + -0.498861,0.185917,0.846506,-3.09873,-3.539123,1.252987, + -0.498861,0.185917,0.846506,-3.09873,-3.539123,1.252987, + -0.057735,0.03099,0.997851,-2.981824,-3.608887,1.346959, + -0.028076,0.054588,0.998114,-3.030627,-3.493327,1.32265, + 0.254799,-0.149124,0.955426,-2.888628,-3.200302,1.210934, + -0.308543,0.191148,0.931807,-2.822497,-3.186549,1.120984, + -0.541406,0.227835,0.809302,-3.03125,-3.09594,1.106355, + -0.626758,0.377346,0.681751,-3.19417,-3.348553,1.007196, + -0.059163,0.13391,0.989226,-3.184143,-3.298048,1.156892, + 0.085126,0.114843,0.98973,-3.217306,-3.187686,1.075214, + -0.626758,0.377346,0.681751,-3.19417,-3.348553,1.007196, + 0.085126,0.114843,0.98973,-3.217306,-3.187686,1.075214, + -0.588311,0.26373,0.764419,-3.223246,-3.225388,0.976573, + -0.670566,0.283017,-0.685743,-2.922908,-3.637036,1.059206, + -0.057735,0.03099,0.997851,-2.981824,-3.608887,1.346959, + -0.498861,0.185917,0.846506,-3.09873,-3.539123,1.252987, + -0.670566,0.283017,-0.685743,-2.922908,-3.637036,1.059206, + -0.498861,0.185917,0.846506,-3.09873,-3.539123,1.252987, + -0.738865,0.325814,-0.589851,-3.082741,-3.598298,1.054556, + -0.701121,0.259575,-0.664117,-3.18675,-3.457336,1.025606, + -0.730585,0.298655,0.614045,-3.158524,-3.405872,1.197099, + -0.059163,0.13391,0.989226,-3.184143,-3.298048,1.156892, + -0.701121,0.259575,-0.664117,-3.18675,-3.457336,1.025606, + -0.059163,0.13391,0.989226,-3.184143,-3.298048,1.156892, + -0.626758,0.377346,0.681751,-3.19417,-3.348553,1.007196, + -0.738865,0.325814,-0.589851,-3.082741,-3.598298,1.054556, + -0.498861,0.185917,0.846506,-3.09873,-3.539123,1.252987, + -0.730585,0.298655,0.614045,-3.158524,-3.405872,1.197099, + -0.738865,0.325814,-0.589851,-3.082741,-3.598298,1.054556, + -0.730585,0.298655,0.614045,-3.158524,-3.405872,1.197099, + -0.701121,0.259575,-0.664117,-3.18675,-3.457336,1.025606, + -0.588311,0.26373,0.764419,-3.223246,-3.225388,0.976573, + -0.64352,0.086605,-0.760514,-3.11957,-3.183977,0.870739, + -0.382827,0.20765,-0.900181,-3.087335,-3.350463,0.831656, + -0.588311,0.26373,0.764419,-3.223246,-3.225388,0.976573, + -0.382827,0.20765,-0.900181,-3.087335,-3.350463,0.831656, + -0.626758,0.377346,0.681751,-3.19417,-3.348553,1.007196, + -0.382827,0.20765,-0.900181,-3.087335,-3.350463,0.831656, + -0.421241,0.09636,-0.901815,-3.074557,-3.486847,0.843432, + -0.701121,0.259575,-0.664117,-3.18675,-3.457336,1.025606, + -0.382827,0.20765,-0.900181,-3.087335,-3.350463,0.831656, + -0.701121,0.259575,-0.664117,-3.18675,-3.457336,1.025606, + -0.626758,0.377346,0.681751,-3.19417,-3.348553,1.007196, + -0.482826,-0.146891,-0.863309,-3.006867,-3.575464,0.830221, + -0.738865,0.325814,-0.589851,-3.082741,-3.598298,1.054556, + -0.701121,0.259575,-0.664117,-3.18675,-3.457336,1.025606, + -0.482826,-0.146891,-0.863309,-3.006867,-3.575464,0.830221, + -0.701121,0.259575,-0.664117,-3.18675,-3.457336,1.025606, + -0.421241,0.09636,-0.901815,-3.074557,-3.486847,0.843432, + -0.562406,-0.352304,-0.748051,-2.870422,-3.601724,0.843123, + -0.670566,0.283017,-0.685743,-2.922908,-3.637036,1.059206, + -0.738865,0.325814,-0.589851,-3.082741,-3.598298,1.054556, + -0.562406,-0.352304,-0.748051,-2.870422,-3.601724,0.843123, + -0.738865,0.325814,-0.589851,-3.082741,-3.598298,1.054556, + -0.482826,-0.146891,-0.863309,-3.006867,-3.575464,0.830221, + 0.115225,0.169061,-0.978847,-2.740824,-3.597601,0.875006, + 0.024044,0.175693,-0.984151,-2.791754,-3.635993,1.078555, + -0.670566,0.283017,-0.685743,-2.922908,-3.637036,1.059206, + 0.115225,0.169061,-0.978847,-2.740824,-3.597601,0.875006, + -0.670566,0.283017,-0.685743,-2.922908,-3.637036,1.059206, + -0.562406,-0.352304,-0.748051,-2.870422,-3.601724,0.843123, + 0.405755,-0.293021,0.865737,-3.042899,-3.193907,1.207296, + 0.254799,-0.149124,0.955426,-2.888628,-3.200302,1.210934, + -0.541406,0.227835,0.809302,-3.03125,-3.09594,1.106355, + 0.405755,-0.293021,0.865737,-3.042899,-3.193907,1.207296, + -0.541406,0.227835,0.809302,-3.03125,-3.09594,1.106355, + -0.125911,-0.68432,-0.718229,-3.121673,-3.120319,1.136456, + 0.487947,-0.44627,0.750167,-3.135041,-3.243787,1.189436, + 0.405755,-0.293021,0.865737,-3.042899,-3.193907,1.207296, + -0.125911,-0.68432,-0.718229,-3.121673,-3.120319,1.136456, + 0.487947,-0.44627,0.750167,-3.135041,-3.243787,1.189436, + -0.125911,-0.68432,-0.718229,-3.121673,-3.120319,1.136456, + 0.535863,0.090315,-0.83946,-3.169546,-3.135273,1.128247, + -0.059163,0.13391,0.989226,-3.184143,-3.298048,1.156892, + 0.487947,-0.44627,0.750167,-3.135041,-3.243787,1.189436, + 0.535863,0.090315,-0.83946,-3.169546,-3.135273,1.128247, + -0.059163,0.13391,0.989226,-3.184143,-3.298048,1.156892, + 0.535863,0.090315,-0.83946,-3.169546,-3.135273,1.128247, + 0.085126,0.114843,0.98973,-3.217306,-3.187686,1.075214, + 0.199599,0.097869,-0.974978,-2.80326,-3.21358,0.942403, + 0.236645,-0.06852,-0.969177,-2.928681,-3.072892,0.924772, + -0.161613,0.16539,0.972896,-2.884711,-3.063896,0.993766, + 0.199599,0.097869,-0.974978,-2.80326,-3.21358,0.942403, + -0.161613,0.16539,0.972896,-2.884711,-3.063896,0.993766, + -0.206994,0.072903,0.975622,-2.770335,-3.208138,1.031045, + 0.177373,0.037311,0.983436,-2.787341,-3.278502,1.138621, + 0.159383,-0.507401,-0.846842,-2.749355,-3.272099,1.034148, + -0.206994,0.072903,0.975622,-2.770335,-3.208138,1.031045, + 0.177373,0.037311,0.983436,-2.787341,-3.278502,1.138621, + -0.206994,0.072903,0.975622,-2.770335,-3.208138,1.031045, + -0.308543,0.191148,0.931807,-2.822497,-3.186549,1.120984, + -0.026425,0.178249,0.983631,-2.631547,-3.559891,1.33738, + 0.35124,-0.91474,-0.199704,-2.58358,-3.514267,1.278598, + -0.048366,0.138166,0.989227,-2.699957,-3.390295,1.185593, + -0.026425,0.178249,0.983631,-2.631547,-3.559891,1.33738, + -0.048366,0.138166,0.989227,-2.699957,-3.390295,1.185593, + 0.011655,0.055061,0.998415,-2.736599,-3.394849,1.269577, + 0.285409,-0.933801,-0.215773,-2.52472,-3.561609,1.161535, + -0.97518,0.20982,-0.070713,-2.649491,-3.404362,1.100352, + -0.048366,0.138166,0.989227,-2.699957,-3.390295,1.185593, + 0.285409,-0.933801,-0.215773,-2.52472,-3.561609,1.161535, + -0.048366,0.138166,0.989227,-2.699957,-3.390295,1.185593, + 0.35124,-0.91474,-0.199704,-2.58358,-3.514267,1.278598, + 0.159383,-0.507401,-0.846842,-2.749355,-3.272099,1.034148, + 0.177373,0.037311,0.983436,-2.787341,-3.278502,1.138621, + -0.048366,0.138166,0.989227,-2.699957,-3.390295,1.185593, + 0.159383,-0.507401,-0.846842,-2.749355,-3.272099,1.034148, + -0.048366,0.138166,0.989227,-2.699957,-3.390295,1.185593, + -0.97518,0.20982,-0.070713,-2.649491,-3.404362,1.100352, + -0.999995,0.003039,0.000095,-2.593513,-3.536154,0.94245, + -0.830756,0.127038,0.541946,-2.668957,-3.397513,0.943626, + -0.97518,0.20982,-0.070713,-2.649491,-3.404362,1.100352, + -0.999995,0.003039,0.000095,-2.593513,-3.536154,0.94245, + -0.97518,0.20982,-0.070713,-2.649491,-3.404362,1.100352, + 0.285409,-0.933801,-0.215773,-2.52472,-3.561609,1.161535, + -0.874688,-0.025586,0.48401,-2.749867,-3.295148,0.966073, + 0.159383,-0.507401,-0.846842,-2.749355,-3.272099,1.034148, + -0.97518,0.20982,-0.070713,-2.649491,-3.404362,1.100352, + -0.874688,-0.025586,0.48401,-2.749867,-3.295148,0.966073, + -0.97518,0.20982,-0.070713,-2.649491,-3.404362,1.100352, + -0.830756,0.127038,0.541946,-2.668957,-3.397513,0.943626, + 0.199599,0.097869,-0.974978,-2.80326,-3.21358,0.942403, + -0.206994,0.072903,0.975622,-2.770335,-3.208138,1.031045, + 0.159383,-0.507401,-0.846842,-2.749355,-3.272099,1.034148, + 0.199599,0.097869,-0.974978,-2.80326,-3.21358,0.942403, + 0.159383,-0.507401,-0.846842,-2.749355,-3.272099,1.034148, + -0.874688,-0.025586,0.48401,-2.749867,-3.295148,0.966073, + -0.860798,0.234294,0.451812,-3.011987,-3.092,0.860973, + -0.405387,0.054444,0.912522,-2.944625,-3.282121,0.817054, + -0.382827,0.20765,-0.900181,-3.087335,-3.350463,0.831656, + -0.860798,0.234294,0.451812,-3.011987,-3.092,0.860973, + -0.382827,0.20765,-0.900181,-3.087335,-3.350463,0.831656, + -0.64352,0.086605,-0.760514,-3.11957,-3.183977,0.870739, + 0.236645,-0.06852,-0.969177,-2.928681,-3.072892,0.924772, + 0.199599,0.097869,-0.974978,-2.80326,-3.21358,0.942403, + -0.405387,0.054444,0.912522,-2.944625,-3.282121,0.817054, + 0.236645,-0.06852,-0.969177,-2.928681,-3.072892,0.924772, + -0.405387,0.054444,0.912522,-2.944625,-3.282121,0.817054, + -0.860798,0.234294,0.451812,-3.011987,-3.092,0.860973, + -0.405387,0.054444,0.912522,-2.944625,-3.282121,0.817054, + -0.51506,-0.054833,0.855398,-2.890885,-3.415616,0.819125, + -0.421241,0.09636,-0.901815,-3.074557,-3.486847,0.843432, + -0.405387,0.054444,0.912522,-2.944625,-3.282121,0.817054, + -0.421241,0.09636,-0.901815,-3.074557,-3.486847,0.843432, + -0.382827,0.20765,-0.900181,-3.087335,-3.350463,0.831656, + 0.199599,0.097869,-0.974978,-2.80326,-3.21358,0.942403, + -0.874688,-0.025586,0.48401,-2.749867,-3.295148,0.966073, + -0.51506,-0.054833,0.855398,-2.890885,-3.415616,0.819125, + 0.199599,0.097869,-0.974978,-2.80326,-3.21358,0.942403, + -0.51506,-0.054833,0.855398,-2.890885,-3.415616,0.819125, + -0.405387,0.054444,0.912522,-2.944625,-3.282121,0.817054, + -0.482826,-0.146891,-0.863309,-3.006867,-3.575464,0.830221, + -0.421241,0.09636,-0.901815,-3.074557,-3.486847,0.843432, + -0.51506,-0.054833,0.855398,-2.890885,-3.415616,0.819125, + -0.482826,-0.146891,-0.863309,-3.006867,-3.575464,0.830221, + -0.51506,-0.054833,0.855398,-2.890885,-3.415616,0.819125, + -0.562406,-0.352304,-0.748051,-2.870422,-3.601724,0.843123, + -0.830756,0.127038,0.541946,-2.668957,-3.397513,0.943626, + -0.51506,-0.054833,0.855398,-2.890885,-3.415616,0.819125, + -0.874688,-0.025586,0.48401,-2.749867,-3.295148,0.966073, + -0.51506,-0.054833,0.855398,-2.890885,-3.415616,0.819125, + 0.115225,0.169061,-0.978847,-2.740824,-3.597601,0.875006, + -0.562406,-0.352304,-0.748051,-2.870422,-3.601724,0.843123, + 0.115225,0.169061,-0.978847,-2.740824,-3.597601,0.875006, + -0.51506,-0.054833,0.855398,-2.890885,-3.415616,0.819125, + -0.830756,0.127038,0.541946,-2.668957,-3.397513,0.943626, + 0.115225,0.169061,-0.978847,-2.740824,-3.597601,0.875006, + -0.830756,0.127038,0.541946,-2.668957,-3.397513,0.943626, + -0.999995,0.003039,0.000095,-2.593513,-3.536154,0.94245, + 0.024044,0.175693,-0.984151,-2.791754,-3.635993,1.078555, + 0.115225,0.169061,-0.978847,-2.740824,-3.597601,0.875006, + -0.999995,0.003039,0.000095,-2.593513,-3.536154,0.94245, + 0.024044,0.175693,-0.984151,-2.791754,-3.635993,1.078555, + -0.999995,0.003039,0.000095,-2.593513,-3.536154,0.94245, + 0.285409,-0.933801,-0.215773,-2.52472,-3.561609,1.161535, + 0.024044,0.175693,-0.984151,-2.791754,-3.635993,1.078555, + -0.093334,0.204552,0.974396,-2.729567,-3.602976,1.377236, + -0.057735,0.03099,0.997851,-2.981824,-3.608887,1.346959, + 0.024044,0.175693,-0.984151,-2.791754,-3.635993,1.078555, + -0.057735,0.03099,0.997851,-2.981824,-3.608887,1.346959, + -0.670566,0.283017,-0.685743,-2.922908,-3.637036,1.059206, + -0.308543,0.191148,0.931807,-2.822497,-3.186549,1.120984, + 0.07463,0.029476,0.996776,-2.90901,-3.084482,1.089147, + -0.541406,0.227835,0.809302,-3.03125,-3.09594,1.106355, + 0.285409,-0.933801,-0.215773,-2.52472,-3.561609,1.161535, + 0.35124,-0.91474,-0.199704,-2.58358,-3.514267,1.278598, + -0.026425,0.178249,0.983631,-2.631547,-3.559891,1.33738, + 0.285409,-0.933801,-0.215773,-2.52472,-3.561609,1.161535, + -0.026425,0.178249,0.983631,-2.631547,-3.559891,1.33738, + -0.093334,0.204552,0.974396,-2.729567,-3.602976,1.377236, + 0.285409,-0.933801,-0.215773,-2.52472,-3.561609,1.161535, + -0.093334,0.204552,0.974396,-2.729567,-3.602976,1.377236, + 0.024044,0.175693,-0.984151,-2.791754,-3.635993,1.078555 +}; +static const struct gllist frame={GL_N3F_V3F,GL_TRIANGLES,1032,data,NULL}; +const struct gllist *cow_hoofs=&frame; diff --git a/hacks/glx/cow_horns.c b/hacks/glx/cow_horns.c new file mode 100644 index 00000000..2d5dbe9f --- /dev/null +++ b/hacks/glx/cow_horns.c @@ -0,0 +1,1025 @@ +#include "gllist.h" +static const float data[]={ + -0.000715,-0.295728,0.955272,4.22473,2.624525,-0.491916, + -0.03479,0.69667,0.716547,4.209941,2.600612,-0.337597, + -0.01139,0.953897,0.299916,4.328606,2.563996,-0.343892, + -0.000715,-0.295728,0.955272,4.22473,2.624525,-0.491916, + -0.01139,0.953897,0.299916,4.328606,2.563996,-0.343892, + -0.163152,0.69985,0.695407,4.344028,2.585635,-0.470949, + -0.163152,0.69985,0.695407,4.344028,2.585635,-0.470949, + -0.01139,0.953897,0.299916,4.328606,2.563996,-0.343892, + -0.151742,0.274295,0.949598,4.410844,2.500167,-0.351972, + -0.163152,0.69985,0.695407,4.344028,2.585635,-0.470949, + -0.151742,0.274295,0.949598,4.410844,2.500167,-0.351972, + -0.090939,0.953562,0.287141,4.407729,2.53164,-0.486692, + 0.008972,0.708004,0.706152,4.277169,2.652435,-0.591369, + -0.000715,-0.295728,0.955272,4.22473,2.624525,-0.491916, + -0.163152,0.69985,0.695407,4.344028,2.585635,-0.470949, + 0.008972,0.708004,0.706152,4.277169,2.652435,-0.591369, + -0.163152,0.69985,0.695407,4.344028,2.585635,-0.470949, + 0.809878,-0.450757,-0.375386,4.359483,2.615839,-0.596817, + 0.809878,-0.450757,-0.375386,4.359483,2.615839,-0.596817, + -0.163152,0.69985,0.695407,4.344028,2.585635,-0.470949, + -0.090939,0.953562,0.287141,4.407729,2.53164,-0.486692, + 0.809878,-0.450757,-0.375386,4.359483,2.615839,-0.596817, + -0.090939,0.953562,0.287141,4.407729,2.53164,-0.486692, + 0.795507,-0.586003,-0.154171,4.423033,2.561337,-0.603562, + 0.743898,-0.655714,0.129057,4.35668,2.682996,-0.71905, + 0.008972,0.708004,0.706152,4.277169,2.652435,-0.591369, + 0.809878,-0.450757,-0.375386,4.359483,2.615839,-0.596817, + 0.743898,-0.655714,0.129057,4.35668,2.682996,-0.71905, + 0.809878,-0.450757,-0.375386,4.359483,2.615839,-0.596817, + 0.083641,-0.819891,-0.566378,4.411541,2.663824,-0.713132, + 0.083641,-0.819891,-0.566378,4.411541,2.663824,-0.713132, + 0.809878,-0.450757,-0.375386,4.359483,2.615839,-0.596817, + 0.795507,-0.586003,-0.154171,4.423033,2.561337,-0.603562, + 0.083641,-0.819891,-0.566378,4.411541,2.663824,-0.713132, + 0.795507,-0.586003,-0.154171,4.423033,2.561337,-0.603562, + 0.042118,-0.881894,-0.469563,4.47609,2.606654,-0.692301, + 0.713982,0.301536,-0.631907,4.418954,2.707401,-0.782531, + 0.743898,-0.655714,0.129057,4.35668,2.682996,-0.71905, + 0.083641,-0.819891,-0.566378,4.411541,2.663824,-0.713132, + 0.713982,0.301536,-0.631907,4.418954,2.707401,-0.782531, + 0.083641,-0.819891,-0.566378,4.411541,2.663824,-0.713132, + 0.086688,-0.887002,-0.453556,4.465268,2.695425,-0.757267, + 0.083641,-0.819891,-0.566378,4.411541,2.663824,-0.713132, + 0.042118,-0.881894,-0.469563,4.47609,2.606654,-0.692301, + 0.571341,-0.68069,0.458509,4.520603,2.639162,-0.745542, + 0.083641,-0.819891,-0.566378,4.411541,2.663824,-0.713132, + 0.571341,-0.68069,0.458509,4.520603,2.639162,-0.745542, + 0.086688,-0.887002,-0.453556,4.465268,2.695425,-0.757267, + 0.176955,-0.903058,-0.391373,4.509555,2.719807,-0.819972, + 0.713982,0.301536,-0.631907,4.418954,2.707401,-0.782531, + 0.086688,-0.887002,-0.453556,4.465268,2.695425,-0.757267, + 0.176955,-0.903058,-0.391373,4.509555,2.719807,-0.819972, + 0.086688,-0.887002,-0.453556,4.465268,2.695425,-0.757267, + 0.388502,-0.664299,0.638571,4.546655,2.709095,-0.80378, + 0.086688,-0.887002,-0.453556,4.465268,2.695425,-0.757267, + 0.571341,-0.68069,0.458509,4.520603,2.639162,-0.745542, + 0.21141,-0.953268,-0.215838,4.574545,2.669863,-0.780363, + 0.086688,-0.887002,-0.453556,4.465268,2.695425,-0.757267, + 0.21141,-0.953268,-0.215838,4.574545,2.669863,-0.780363, + 0.388502,-0.664299,0.638571,4.546655,2.709095,-0.80378, + -0.090939,0.953562,0.287141,4.407729,2.53164,-0.486692, + -0.151742,0.274295,0.949598,4.410844,2.500167,-0.351972, + 0.288841,-0.745301,0.600914,4.474318,2.418432,-0.361347, + -0.090939,0.953562,0.287141,4.407729,2.53164,-0.486692, + 0.288841,-0.745301,0.600914,4.474318,2.418432,-0.361347, + 0.237421,-0.963021,-0.127365,4.44385,2.449921,-0.495432, + 0.795507,-0.586003,-0.154171,4.423033,2.561337,-0.603562, + -0.090939,0.953562,0.287141,4.407729,2.53164,-0.486692, + 0.237421,-0.963021,-0.127365,4.44385,2.449921,-0.495432, + 0.795507,-0.586003,-0.154171,4.423033,2.561337,-0.603562, + 0.237421,-0.963021,-0.127365,4.44385,2.449921,-0.495432, + 0.157921,-0.851177,0.500558,4.44076,2.490353,-0.629287, + 0.042118,-0.881894,-0.469563,4.47609,2.606654,-0.692301, + 0.795507,-0.586003,-0.154171,4.423033,2.561337,-0.603562, + 0.157921,-0.851177,0.500558,4.44076,2.490353,-0.629287, + 0.042118,-0.881894,-0.469563,4.47609,2.606654,-0.692301, + 0.157921,-0.851177,0.500558,4.44076,2.490353,-0.629287, + 0.254106,-0.95176,-0.171999,4.484667,2.534451,-0.708888, + 0.571341,-0.68069,0.458509,4.520603,2.639162,-0.745542, + 0.042118,-0.881894,-0.469563,4.47609,2.606654,-0.692301, + 0.254106,-0.95176,-0.171999,4.484667,2.534451,-0.708888, + 0.571341,-0.68069,0.458509,4.520603,2.639162,-0.745542, + 0.254106,-0.95176,-0.171999,4.484667,2.534451,-0.708888, + 0.165259,-0.797056,0.580854,4.520165,2.557971,-0.762427, + 0.21141,-0.953268,-0.215838,4.574545,2.669863,-0.780363, + 0.571341,-0.68069,0.458509,4.520603,2.639162,-0.745542, + 0.165259,-0.797056,0.580854,4.520165,2.557971,-0.762427, + 0.21141,-0.953268,-0.215838,4.574545,2.669863,-0.780363, + 0.165259,-0.797056,0.580854,4.520165,2.557971,-0.762427, + 0.243744,-0.944481,-0.220328,4.59262,2.569879,-0.790452, + 0.209939,-0.930128,-0.301309,4.656565,2.680542,-0.799684, + 0.21141,-0.953268,-0.215838,4.574545,2.669863,-0.780363, + 0.243744,-0.944481,-0.220328,4.59262,2.569879,-0.790452, + 0.209939,-0.930128,-0.301309,4.656565,2.680542,-0.799684, + 0.243744,-0.944481,-0.220328,4.59262,2.569879,-0.790452, + -0.05208,-0.715695,-0.696469,4.674691,2.598833,-0.808006, + 0.287073,-0.905921,-0.311283,4.646703,2.728688,-0.822295, + 0.388502,-0.664299,0.638571,4.546655,2.709095,-0.80378, + 0.21141,-0.953268,-0.215838,4.574545,2.669863,-0.780363, + 0.287073,-0.905921,-0.311283,4.646703,2.728688,-0.822295, + 0.21141,-0.953268,-0.215838,4.574545,2.669863,-0.780363, + 0.209939,-0.930128,-0.301309,4.656565,2.680542,-0.799684, + 0.267121,-0.895396,-0.356249,4.636909,2.750501,-0.856859, + 0.176955,-0.903058,-0.391373,4.509555,2.719807,-0.819972, + 0.388502,-0.664299,0.638571,4.546655,2.709095,-0.80378, + 0.267121,-0.895396,-0.356249,4.636909,2.750501,-0.856859, + 0.388502,-0.664299,0.638571,4.546655,2.709095,-0.80378, + 0.287073,-0.905921,-0.311283,4.646703,2.728688,-0.822295, + -0.290459,-0.499809,-0.815981,4.748031,2.683805,-0.800044, + 0.209939,-0.930128,-0.301309,4.656565,2.680542,-0.799684, + -0.05208,-0.715695,-0.696469,4.674691,2.598833,-0.808006, + -0.290459,-0.499809,-0.815981,4.748031,2.683805,-0.800044, + -0.05208,-0.715695,-0.696469,4.674691,2.598833,-0.808006, + -0.501597,-0.526154,-0.686704,4.729447,2.606204,-0.807513, + -0.538845,-0.659239,-0.524452,4.728931,2.721892,-0.832625, + 0.287073,-0.905921,-0.311283,4.646703,2.728688,-0.822295, + 0.209939,-0.930128,-0.301309,4.656565,2.680542,-0.799684, + -0.538845,-0.659239,-0.524452,4.728931,2.721892,-0.832625, + 0.209939,-0.930128,-0.301309,4.656565,2.680542,-0.799684, + -0.290459,-0.499809,-0.815981,4.748031,2.683805,-0.800044, + -0.53682,-0.608254,-0.58468,4.719171,2.751091,-0.865965, + 0.267121,-0.895396,-0.356249,4.636909,2.750501,-0.856859, + 0.287073,-0.905921,-0.311283,4.646703,2.728688,-0.822295, + -0.53682,-0.608254,-0.58468,4.719171,2.751091,-0.865965, + 0.287073,-0.905921,-0.311283,4.646703,2.728688,-0.822295, + -0.538845,-0.659239,-0.524452,4.728931,2.721892,-0.832625, + -0.635876,0.32433,-0.700337,4.821325,2.691794,-0.791887, + -0.290459,-0.499809,-0.815981,4.748031,2.683805,-0.800044, + -0.501597,-0.526154,-0.686704,4.729447,2.606204,-0.807513, + -0.635876,0.32433,-0.700337,4.821325,2.691794,-0.791887, + -0.501597,-0.526154,-0.686704,4.729447,2.606204,-0.807513, + -0.376273,-0.14016,-0.915846,4.821336,2.621498,-0.789636, + -0.508573,-0.111047,-0.853828,4.811798,2.72868,-0.815406, + -0.538845,-0.659239,-0.524452,4.728931,2.721892,-0.832625, + -0.290459,-0.499809,-0.815981,4.748031,2.683805,-0.800044, + -0.508573,-0.111047,-0.853828,4.811798,2.72868,-0.815406, + -0.290459,-0.499809,-0.815981,4.748031,2.683805,-0.800044, + -0.635876,0.32433,-0.700337,4.821325,2.691794,-0.791887, + -0.53682,-0.608254,-0.58468,4.719171,2.751091,-0.865965, + -0.538845,-0.659239,-0.524452,4.728931,2.721892,-0.832625, + -0.508573,-0.111047,-0.853828,4.811798,2.72868,-0.815406, + -0.53682,-0.608254,-0.58468,4.719171,2.751091,-0.865965, + -0.508573,-0.111047,-0.853828,4.811798,2.72868,-0.815406, + -0.724543,-0.128977,-0.677054,4.801436,2.750224,-0.858918, + -0.86136,-0.239794,-0.447836,5.096148,2.75972,-0.774729, + -0.724543,-0.128977,-0.677054,4.801436,2.750224,-0.858918, + -0.508573,-0.111047,-0.853828,4.811798,2.72868,-0.815406, + -0.86136,-0.239794,-0.447836,5.096148,2.75972,-0.774729, + -0.508573,-0.111047,-0.853828,4.811798,2.72868,-0.815406, + -0.635876,0.32433,-0.700337,4.821325,2.691794,-0.791887, + -0.86136,-0.239794,-0.447836,5.096148,2.75972,-0.774729, + -0.635876,0.32433,-0.700337,4.821325,2.691794,-0.791887, + -0.376273,-0.14016,-0.915846,4.821336,2.621498,-0.789636, + -0.903777,-0.182749,-0.387027,4.442912,2.343263,-0.53322, + 0.237421,-0.963021,-0.127365,4.44385,2.449921,-0.495432, + 0.288841,-0.745301,0.600914,4.474318,2.418432,-0.361347, + -0.903777,-0.182749,-0.387027,4.442912,2.343263,-0.53322, + 0.288841,-0.745301,0.600914,4.474318,2.418432,-0.361347, + 0.195545,0.103956,-0.975169,4.472349,2.325133,-0.443764, + -0.911341,0.002265,-0.411646,4.440713,2.398472,-0.629128, + 0.157921,-0.851177,0.500558,4.44076,2.490353,-0.629287, + 0.237421,-0.963021,-0.127365,4.44385,2.449921,-0.495432, + -0.911341,0.002265,-0.411646,4.440713,2.398472,-0.629128, + 0.237421,-0.963021,-0.127365,4.44385,2.449921,-0.495432, + -0.903777,-0.182749,-0.387027,4.442912,2.343263,-0.53322, + 0.254106,-0.95176,-0.171999,4.484667,2.534451,-0.708888, + 0.157921,-0.851177,0.500558,4.44076,2.490353,-0.629287, + -0.911341,0.002265,-0.411646,4.440713,2.398472,-0.629128, + 0.254106,-0.95176,-0.171999,4.484667,2.534451,-0.708888, + -0.911341,0.002265,-0.411646,4.440713,2.398472,-0.629128, + -0.77316,0.344901,-0.532228,4.474625,2.465214,-0.75189, + -0.911341,0.002265,-0.411646,4.440713,2.398472,-0.629128, + -0.903777,-0.182749,-0.387027,4.442912,2.343263,-0.53322, + -0.566117,0.431682,-0.702255,4.314039,2.32946,-0.57751, + -0.911341,0.002265,-0.411646,4.440713,2.398472,-0.629128, + -0.566117,0.431682,-0.702255,4.314039,2.32946,-0.57751, + -0.383863,0.612068,-0.691392,4.32063,2.385528,-0.682583, + -0.566117,0.431682,-0.702255,4.314039,2.32946,-0.57751, + -0.903777,-0.182749,-0.387027,4.442912,2.343263,-0.53322, + 0.195545,0.103956,-0.975169,4.472349,2.325133,-0.443764, + -0.566117,0.431682,-0.702255,4.314039,2.32946,-0.57751, + 0.195545,0.103956,-0.975169,4.472349,2.325133,-0.443764, + -0.091679,0.768658,-0.633056,4.296769,2.260422,-0.528796, + -0.77316,0.344901,-0.532228,4.474625,2.465214,-0.75189, + -0.911341,0.002265,-0.411646,4.440713,2.398472,-0.629128, + -0.383863,0.612068,-0.691392,4.32063,2.385528,-0.682583, + -0.77316,0.344901,-0.532228,4.474625,2.465214,-0.75189, + -0.383863,0.612068,-0.691392,4.32063,2.385528,-0.682583, + -0.911194,0.285551,-0.296961,4.382053,2.433474,-0.798757, + 0.165259,-0.797056,0.580854,4.520165,2.557971,-0.762427, + 0.254106,-0.95176,-0.171999,4.484667,2.534451,-0.708888, + -0.77316,0.344901,-0.532228,4.474625,2.465214,-0.75189, + 0.165259,-0.797056,0.580854,4.520165,2.557971,-0.762427, + -0.77316,0.344901,-0.532228,4.474625,2.465214,-0.75189, + -0.931592,0.319003,-0.174277,4.538177,2.513353,-0.776566, + -0.931592,0.319003,-0.174277,4.538177,2.513353,-0.776566, + -0.77316,0.344901,-0.532228,4.474625,2.465214,-0.75189, + -0.911194,0.285551,-0.296961,4.382053,2.433474,-0.798757, + -0.931592,0.319003,-0.174277,4.538177,2.513353,-0.776566, + -0.911194,0.285551,-0.296961,4.382053,2.433474,-0.798757, + -0.895156,0.397807,-0.201111,4.444739,2.475795,-0.860515, + 0.243744,-0.944481,-0.220328,4.59262,2.569879,-0.790452, + 0.165259,-0.797056,0.580854,4.520165,2.557971,-0.762427, + -0.931592,0.319003,-0.174277,4.538177,2.513353,-0.776566, + 0.243744,-0.944481,-0.220328,4.59262,2.569879,-0.790452, + -0.931592,0.319003,-0.174277,4.538177,2.513353,-0.776566, + -0.885174,0.439903,-0.1515,4.601515,2.533324,-0.794193, + -0.885174,0.439903,-0.1515,4.601515,2.533324,-0.794193, + -0.931592,0.319003,-0.174277,4.538177,2.513353,-0.776566, + -0.895156,0.397807,-0.201111,4.444739,2.475795,-0.860515, + -0.885174,0.439903,-0.1515,4.601515,2.533324,-0.794193, + -0.895156,0.397807,-0.201111,4.444739,2.475795,-0.860515, + -0.821561,0.369567,-0.434116,4.554459,2.511417,-0.850571, + -0.05208,-0.715695,-0.696469,4.674691,2.598833,-0.808006, + 0.243744,-0.944481,-0.220328,4.59262,2.569879,-0.790452, + -0.885174,0.439903,-0.1515,4.601515,2.533324,-0.794193, + -0.05208,-0.715695,-0.696469,4.674691,2.598833,-0.808006, + -0.885174,0.439903,-0.1515,4.601515,2.533324,-0.794193, + -0.742898,0.572423,-0.347037,4.683344,2.554221,-0.821927, + -0.742898,0.572423,-0.347037,4.683344,2.554221,-0.821927, + -0.885174,0.439903,-0.1515,4.601515,2.533324,-0.794193, + -0.821561,0.369567,-0.434116,4.554459,2.511417,-0.850571, + -0.742898,0.572423,-0.347037,4.683344,2.554221,-0.821927, + -0.821561,0.369567,-0.434116,4.554459,2.511417,-0.850571, + -0.659696,0.567803,-0.492342,4.681847,2.551036,-0.886235, + 0.11638,0.680313,-0.723623,4.737893,2.564648,-0.830389, + -0.742898,0.572423,-0.347037,4.683344,2.554221,-0.821927, + -0.659696,0.567803,-0.492342,4.681847,2.551036,-0.886235, + 0.11638,0.680313,-0.723623,4.737893,2.564648,-0.830389, + -0.659696,0.567803,-0.492342,4.681847,2.551036,-0.886235, + 0.206279,0.744918,-0.634466,4.755192,2.568818,-0.876311, + -0.395723,0.901671,-0.174334,4.829566,2.580797,-0.821827, + 0.11638,0.680313,-0.723623,4.737893,2.564648,-0.830389, + 0.206279,0.744918,-0.634466,4.755192,2.568818,-0.876311, + -0.395723,0.901671,-0.174334,4.829566,2.580797,-0.821827, + 0.206279,0.744918,-0.634466,4.755192,2.568818,-0.876311, + -0.476949,0.871028,-0.117606,4.856249,2.593812,-0.867067, + -0.501597,-0.526154,-0.686704,4.729447,2.606204,-0.807513, + -0.05208,-0.715695,-0.696469,4.674691,2.598833,-0.808006, + -0.742898,0.572423,-0.347037,4.683344,2.554221,-0.821927, + -0.501597,-0.526154,-0.686704,4.729447,2.606204,-0.807513, + -0.742898,0.572423,-0.347037,4.683344,2.554221,-0.821927, + 0.11638,0.680313,-0.723623,4.737893,2.564648,-0.830389, + -0.376273,-0.14016,-0.915846,4.821336,2.621498,-0.789636, + -0.501597,-0.526154,-0.686704,4.729447,2.606204,-0.807513, + 0.11638,0.680313,-0.723623,4.737893,2.564648,-0.830389, + -0.376273,-0.14016,-0.915846,4.821336,2.621498,-0.789636, + 0.11638,0.680313,-0.723623,4.737893,2.564648,-0.830389, + -0.395723,0.901671,-0.174334,4.829566,2.580797,-0.821827, + -0.590366,0.807127,0.003753,4.662221,2.556346,-0.940618, + -0.659696,0.567803,-0.492342,4.681847,2.551036,-0.886235, + -0.821561,0.369567,-0.434116,4.554459,2.511417,-0.850571, + -0.590366,0.807127,0.003753,4.662221,2.556346,-0.940618, + -0.821561,0.369567,-0.434116,4.554459,2.511417,-0.850571, + -0.594389,0.803108,-0.041468,4.497719,2.54748,-0.937659, + -0.659696,0.567803,-0.492342,4.681847,2.551036,-0.886235, + -0.590366,0.807127,0.003753,4.662221,2.556346,-0.940618, + -0.610894,0.790229,0.048447,4.763337,2.590834,-0.929248, + -0.659696,0.567803,-0.492342,4.681847,2.551036,-0.886235, + -0.610894,0.790229,0.048447,4.763337,2.590834,-0.929248, + 0.206279,0.744918,-0.634466,4.755192,2.568818,-0.876311, + -0.091114,0.94565,-0.312161,4.883022,2.613658,-0.893163, + -0.476949,0.871028,-0.117606,4.856249,2.593812,-0.867067, + 0.206279,0.744918,-0.634466,4.755192,2.568818,-0.876311, + -0.091114,0.94565,-0.312161,4.883022,2.613658,-0.893163, + 0.206279,0.744918,-0.634466,4.755192,2.568818,-0.876311, + -0.610894,0.790229,0.048447,4.763337,2.590834,-0.929248, + -0.821561,0.369567,-0.434116,4.554459,2.511417,-0.850571, + -0.895156,0.397807,-0.201111,4.444739,2.475795,-0.860515, + -0.216454,0.960138,-0.176868,4.352603,2.524888,-0.890532, + -0.821561,0.369567,-0.434116,4.554459,2.511417,-0.850571, + -0.216454,0.960138,-0.176868,4.352603,2.524888,-0.890532, + -0.594389,0.803108,-0.041468,4.497719,2.54748,-0.937659, + -0.216454,0.960138,-0.176868,4.352603,2.524888,-0.890532, + -0.895156,0.397807,-0.201111,4.444739,2.475795,-0.860515, + -0.911194,0.285551,-0.296961,4.382053,2.433474,-0.798757, + -0.216454,0.960138,-0.176868,4.352603,2.524888,-0.890532, + -0.911194,0.285551,-0.296961,4.382053,2.433474,-0.798757, + -0.283496,0.953866,-0.098841,4.262798,2.490674,-0.818316, + -0.283496,0.953866,-0.098841,4.262798,2.490674,-0.818316, + -0.911194,0.285551,-0.296961,4.382053,2.433474,-0.798757, + -0.383863,0.612068,-0.691392,4.32063,2.385528,-0.682583, + -0.283496,0.953866,-0.098841,4.262798,2.490674,-0.818316, + -0.383863,0.612068,-0.691392,4.32063,2.385528,-0.682583, + -0.421167,0.906102,-0.039984,4.192789,2.411967,-0.668016, + -0.421167,0.906102,-0.039984,4.192789,2.411967,-0.668016, + -0.383863,0.612068,-0.691392,4.32063,2.385528,-0.682583, + -0.566117,0.431682,-0.702255,4.314039,2.32946,-0.57751, + -0.421167,0.906102,-0.039984,4.192789,2.411967,-0.668016, + -0.566117,0.431682,-0.702255,4.314039,2.32946,-0.57751, + -0.557881,0.828586,0.047047,4.193959,2.370476,-0.616705, + -0.536307,0.710867,-0.45502,4.113935,2.334131,-0.526471, + -0.557881,0.828586,0.047047,4.193959,2.370476,-0.616705, + -0.566117,0.431682,-0.702255,4.314039,2.32946,-0.57751, + -0.536307,0.710867,-0.45502,4.113935,2.334131,-0.526471, + -0.566117,0.431682,-0.702255,4.314039,2.32946,-0.57751, + -0.091679,0.768658,-0.633056,4.296769,2.260422,-0.528796, + -0.091114,0.94565,-0.312161,4.883022,2.613658,-0.893163, + -0.86136,-0.239794,-0.447836,5.096148,2.75972,-0.774729, + -0.476949,0.871028,-0.117606,4.856249,2.593812,-0.867067, + -0.610894,0.790229,0.048447,4.763337,2.590834,-0.929248, + -0.678216,0.658343,-0.326508,4.735139,2.645464,-0.95089, + 0.05537,0.916343,-0.396546,4.854957,2.660227,-0.92431, + -0.610894,0.790229,0.048447,4.763337,2.590834,-0.929248, + 0.05537,0.916343,-0.396546,4.854957,2.660227,-0.92431, + -0.091114,0.94565,-0.312161,4.883022,2.613658,-0.893163, + -0.590366,0.807127,0.003753,4.662221,2.556346,-0.940618, + 0.090337,0.942369,-0.32215,4.615662,2.63387,-0.977986, + -0.678216,0.658343,-0.326508,4.735139,2.645464,-0.95089, + -0.590366,0.807127,0.003753,4.662221,2.556346,-0.940618, + -0.678216,0.658343,-0.326508,4.735139,2.645464,-0.95089, + -0.610894,0.790229,0.048447,4.763337,2.590834,-0.929248, + -0.594389,0.803108,-0.041468,4.497719,2.54748,-0.937659, + -0.560855,0.735161,-0.380763,4.460582,2.622875,-0.957002, + 0.090337,0.942369,-0.32215,4.615662,2.63387,-0.977986, + -0.594389,0.803108,-0.041468,4.497719,2.54748,-0.937659, + 0.090337,0.942369,-0.32215,4.615662,2.63387,-0.977986, + -0.590366,0.807127,0.003753,4.662221,2.556346,-0.940618, + -0.216454,0.960138,-0.176868,4.352603,2.524888,-0.890532, + -0.641133,0.599375,-0.479267,4.343217,2.589542,-0.893106, + -0.560855,0.735161,-0.380763,4.460582,2.622875,-0.957002, + -0.216454,0.960138,-0.176868,4.352603,2.524888,-0.890532, + -0.560855,0.735161,-0.380763,4.460582,2.622875,-0.957002, + -0.594389,0.803108,-0.041468,4.497719,2.54748,-0.937659, + -0.283496,0.953866,-0.098841,4.262798,2.490674,-0.818316, + -0.760994,0.140162,-0.633436,4.244622,2.554467,-0.811726, + -0.641133,0.599375,-0.479267,4.343217,2.589542,-0.893106, + -0.283496,0.953866,-0.098841,4.262798,2.490674,-0.818316, + -0.641133,0.599375,-0.479267,4.343217,2.589542,-0.893106, + -0.216454,0.960138,-0.176868,4.352603,2.524888,-0.890532, + -0.421167,0.906102,-0.039984,4.192789,2.411967,-0.668016, + -0.411843,0.771855,-0.484381,4.138687,2.474013,-0.642311, + -0.760994,0.140162,-0.633436,4.244622,2.554467,-0.811726, + -0.421167,0.906102,-0.039984,4.192789,2.411967,-0.668016, + -0.760994,0.140162,-0.633436,4.244622,2.554467,-0.811726, + -0.283496,0.953866,-0.098841,4.262798,2.490674,-0.818316, + -0.091114,0.94565,-0.312161,4.883022,2.613658,-0.893163, + 0.05537,0.916343,-0.396546,4.854957,2.660227,-0.92431, + -0.86136,-0.239794,-0.447836,5.096148,2.75972,-0.774729, + -0.395036,0.74012,-0.544214,4.121994,2.458034,-0.570029, + -0.411843,0.771855,-0.484381,4.138687,2.474013,-0.642311, + -0.421167,0.906102,-0.039984,4.192789,2.411967,-0.668016, + -0.395036,0.74012,-0.544214,4.121994,2.458034,-0.570029, + -0.421167,0.906102,-0.039984,4.192789,2.411967,-0.668016, + -0.557881,0.828586,0.047047,4.193959,2.370476,-0.616705, + -0.395036,0.74012,-0.544214,4.121994,2.458034,-0.570029, + -0.557881,0.828586,0.047047,4.193959,2.370476,-0.616705, + -0.536307,0.710867,-0.45502,4.113935,2.334131,-0.526471, + -0.395036,0.74012,-0.544214,4.121994,2.458034,-0.570029, + -0.536307,0.710867,-0.45502,4.113935,2.334131,-0.526471, + -0.330515,0.821242,-0.465103,4.07851,2.41181,-0.472193, + -0.760994,0.140162,-0.633436,4.244622,2.554467,-0.811726, + -0.353793,0.870619,-0.341838,4.235494,2.636171,-0.803613, + -0.718934,0.608496,-0.335955,4.342998,2.664049,-0.904347, + -0.760994,0.140162,-0.633436,4.244622,2.554467,-0.811726, + -0.718934,0.608496,-0.335955,4.342998,2.664049,-0.904347, + -0.641133,0.599375,-0.479267,4.343217,2.589542,-0.893106, + -0.641133,0.599375,-0.479267,4.343217,2.589542,-0.893106, + -0.718934,0.608496,-0.335955,4.342998,2.664049,-0.904347, + -0.929249,-0.009269,-0.369337,4.460786,2.695616,-0.949972, + -0.641133,0.599375,-0.479267,4.343217,2.589542,-0.893106, + -0.929249,-0.009269,-0.369337,4.460786,2.695616,-0.949972, + -0.560855,0.735161,-0.380763,4.460582,2.622875,-0.957002, + -0.560855,0.735161,-0.380763,4.460582,2.622875,-0.957002, + -0.929249,-0.009269,-0.369337,4.460786,2.695616,-0.949972, + -0.144656,0.947613,-0.284787,4.6248,2.708372,-0.989445, + -0.560855,0.735161,-0.380763,4.460582,2.622875,-0.957002, + -0.144656,0.947613,-0.284787,4.6248,2.708372,-0.989445, + 0.090337,0.942369,-0.32215,4.615662,2.63387,-0.977986, + -0.411843,0.771855,-0.484381,4.138687,2.474013,-0.642311, + -0.364192,0.890167,-0.2738,4.138494,2.557838,-0.652651, + -0.353793,0.870619,-0.341838,4.235494,2.636171,-0.803613, + -0.411843,0.771855,-0.484381,4.138687,2.474013,-0.642311, + -0.353793,0.870619,-0.341838,4.235494,2.636171,-0.803613, + -0.760994,0.140162,-0.633436,4.244622,2.554467,-0.811726, + -0.719327,0.568277,-0.399538,4.104292,2.537976,-0.543437, + -0.364192,0.890167,-0.2738,4.138494,2.557838,-0.652651, + -0.411843,0.771855,-0.484381,4.138687,2.474013,-0.642311, + -0.719327,0.568277,-0.399538,4.104292,2.537976,-0.543437, + -0.411843,0.771855,-0.484381,4.138687,2.474013,-0.642311, + -0.395036,0.74012,-0.544214,4.121994,2.458034,-0.570029, + -0.904972,-0.026554,-0.424642,4.088356,2.510913,-0.453793, + -0.719327,0.568277,-0.399538,4.104292,2.537976,-0.543437, + -0.395036,0.74012,-0.544214,4.121994,2.458034,-0.570029, + -0.904972,-0.026554,-0.424642,4.088356,2.510913,-0.453793, + -0.395036,0.74012,-0.544214,4.121994,2.458034,-0.570029, + -0.330515,0.821242,-0.465103,4.07851,2.41181,-0.472193, + -0.144656,0.947613,-0.284787,4.6248,2.708372,-0.989445, + 0.197027,0.937222,-0.287742,4.753015,2.699695,-0.973279, + -0.678216,0.658343,-0.326508,4.735139,2.645464,-0.95089, + -0.144656,0.947613,-0.284787,4.6248,2.708372,-0.989445, + -0.678216,0.658343,-0.326508,4.735139,2.645464,-0.95089, + 0.090337,0.942369,-0.32215,4.615662,2.63387,-0.977986, + -0.678216,0.658343,-0.326508,4.735139,2.645464,-0.95089, + 0.197027,0.937222,-0.287742,4.753015,2.699695,-0.973279, + 0.225135,0.965893,-0.127928,4.863709,2.722151,-0.93666, + -0.678216,0.658343,-0.326508,4.735139,2.645464,-0.95089, + 0.225135,0.965893,-0.127928,4.863709,2.722151,-0.93666, + 0.05537,0.916343,-0.396546,4.854957,2.660227,-0.92431, + -0.000715,-0.295728,0.955272,4.22473,2.624525,-0.491916, + -0.162972,0.917259,0.363422,4.151183,2.579059,-0.494606, + -0.860594,0.405545,-0.308076,4.117367,2.568514,-0.3845, + -0.000715,-0.295728,0.955272,4.22473,2.624525,-0.491916, + -0.860594,0.405545,-0.308076,4.117367,2.568514,-0.3845, + -0.03479,0.69667,0.716547,4.209941,2.600612,-0.337597, + 0.267121,-0.895396,-0.356249,4.636909,2.750501,-0.856859, + -0.31499,0.894135,0.318282,4.616626,2.749486,-0.939333, + -0.758791,0.646991,0.075091,4.462368,2.725999,-0.882675, + 0.267121,-0.895396,-0.356249,4.636909,2.750501,-0.856859, + -0.758791,0.646991,0.075091,4.462368,2.725999,-0.882675, + 0.176955,-0.903058,-0.391373,4.509555,2.719807,-0.819972, + 0.176955,-0.903058,-0.391373,4.509555,2.719807,-0.819972, + -0.758791,0.646991,0.075091,4.462368,2.725999,-0.882675, + -0.900694,0.426849,-0.080936,4.354196,2.711836,-0.826545, + 0.176955,-0.903058,-0.391373,4.509555,2.719807,-0.819972, + -0.900694,0.426849,-0.080936,4.354196,2.711836,-0.826545, + 0.713982,0.301536,-0.631907,4.418954,2.707401,-0.782531, + 0.713982,0.301536,-0.631907,4.418954,2.707401,-0.782531, + -0.900694,0.426849,-0.080936,4.354196,2.711836,-0.826545, + -0.940255,0.335069,0.060403,4.273414,2.686575,-0.753674, + 0.713982,0.301536,-0.631907,4.418954,2.707401,-0.782531, + -0.940255,0.335069,0.060403,4.273414,2.686575,-0.753674, + 0.743898,-0.655714,0.129057,4.35668,2.682996,-0.71905, + -0.162972,0.917259,0.363422,4.151183,2.579059,-0.494606, + -0.000715,-0.295728,0.955272,4.22473,2.624525,-0.491916, + 0.008972,0.708004,0.706152,4.277169,2.652435,-0.591369, + -0.162972,0.917259,0.363422,4.151183,2.579059,-0.494606, + 0.008972,0.708004,0.706152,4.277169,2.652435,-0.591369, + -0.816521,0.559553,0.142109,4.176065,2.636883,-0.618384, + -0.904972,-0.026554,-0.424642,4.088356,2.510913,-0.453793, + -0.860594,0.405545,-0.308076,4.117367,2.568514,-0.3845, + -0.162972,0.917259,0.363422,4.151183,2.579059,-0.494606, + -0.904972,-0.026554,-0.424642,4.088356,2.510913,-0.453793, + -0.162972,0.917259,0.363422,4.151183,2.579059,-0.494606, + -0.719327,0.568277,-0.399538,4.104292,2.537976,-0.543437, + -0.816521,0.559553,0.142109,4.176065,2.636883,-0.618384, + 0.008972,0.708004,0.706152,4.277169,2.652435,-0.591369, + 0.743898,-0.655714,0.129057,4.35668,2.682996,-0.71905, + -0.816521,0.559553,0.142109,4.176065,2.636883,-0.618384, + 0.743898,-0.655714,0.129057,4.35668,2.682996,-0.71905, + -0.940255,0.335069,0.060403,4.273414,2.686575,-0.753674, + -0.719327,0.568277,-0.399538,4.104292,2.537976,-0.543437, + -0.162972,0.917259,0.363422,4.151183,2.579059,-0.494606, + -0.816521,0.559553,0.142109,4.176065,2.636883,-0.618384, + -0.719327,0.568277,-0.399538,4.104292,2.537976,-0.543437, + -0.816521,0.559553,0.142109,4.176065,2.636883,-0.618384, + -0.364192,0.890167,-0.2738,4.138494,2.557838,-0.652651, + -0.364192,0.890167,-0.2738,4.138494,2.557838,-0.652651, + -0.816521,0.559553,0.142109,4.176065,2.636883,-0.618384, + -0.940255,0.335069,0.060403,4.273414,2.686575,-0.753674, + -0.364192,0.890167,-0.2738,4.138494,2.557838,-0.652651, + -0.940255,0.335069,0.060403,4.273414,2.686575,-0.753674, + -0.353793,0.870619,-0.341838,4.235494,2.636171,-0.803613, + -0.353793,0.870619,-0.341838,4.235494,2.636171,-0.803613, + -0.940255,0.335069,0.060403,4.273414,2.686575,-0.753674, + -0.900694,0.426849,-0.080936,4.354196,2.711836,-0.826545, + -0.353793,0.870619,-0.341838,4.235494,2.636171,-0.803613, + -0.900694,0.426849,-0.080936,4.354196,2.711836,-0.826545, + -0.718934,0.608496,-0.335955,4.342998,2.664049,-0.904347, + -0.718934,0.608496,-0.335955,4.342998,2.664049,-0.904347, + -0.900694,0.426849,-0.080936,4.354196,2.711836,-0.826545, + -0.758791,0.646991,0.075091,4.462368,2.725999,-0.882675, + -0.718934,0.608496,-0.335955,4.342998,2.664049,-0.904347, + -0.758791,0.646991,0.075091,4.462368,2.725999,-0.882675, + -0.929249,-0.009269,-0.369337,4.460786,2.695616,-0.949972, + 0.267121,-0.895396,-0.356249,4.636909,2.750501,-0.856859, + -0.53682,-0.608254,-0.58468,4.719171,2.751091,-0.865965, + -0.47673,0.840923,0.25608,4.735445,2.749285,-0.940329, + 0.267121,-0.895396,-0.356249,4.636909,2.750501,-0.856859, + -0.47673,0.840923,0.25608,4.735445,2.749285,-0.940329, + -0.31499,0.894135,0.318282,4.616626,2.749486,-0.939333, + -0.724543,-0.128977,-0.677054,4.801436,2.750224,-0.858918, + -0.145585,0.915338,0.375448,4.827733,2.75439,-0.905049, + -0.47673,0.840923,0.25608,4.735445,2.749285,-0.940329, + -0.724543,-0.128977,-0.677054,4.801436,2.750224,-0.858918, + -0.47673,0.840923,0.25608,4.735445,2.749285,-0.940329, + -0.53682,-0.608254,-0.58468,4.719171,2.751091,-0.865965, + -0.145585,0.915338,0.375448,4.827733,2.75439,-0.905049, + -0.724543,-0.128977,-0.677054,4.801436,2.750224,-0.858918, + -0.86136,-0.239794,-0.447836,5.096148,2.75972,-0.774729, + -0.758791,0.646991,0.075091,4.462368,2.725999,-0.882675, + -0.31499,0.894135,0.318282,4.616626,2.749486,-0.939333, + -0.144656,0.947613,-0.284787,4.6248,2.708372,-0.989445, + -0.758791,0.646991,0.075091,4.462368,2.725999,-0.882675, + -0.144656,0.947613,-0.284787,4.6248,2.708372,-0.989445, + -0.929249,-0.009269,-0.369337,4.460786,2.695616,-0.949972, + -0.31499,0.894135,0.318282,4.616626,2.749486,-0.939333, + -0.47673,0.840923,0.25608,4.735445,2.749285,-0.940329, + 0.197027,0.937222,-0.287742,4.753015,2.699695,-0.973279, + -0.31499,0.894135,0.318282,4.616626,2.749486,-0.939333, + 0.197027,0.937222,-0.287742,4.753015,2.699695,-0.973279, + -0.144656,0.947613,-0.284787,4.6248,2.708372,-0.989445, + 0.225135,0.965893,-0.127928,4.863709,2.722151,-0.93666, + 0.197027,0.937222,-0.287742,4.753015,2.699695,-0.973279, + -0.47673,0.840923,0.25608,4.735445,2.749285,-0.940329, + 0.225135,0.965893,-0.127928,4.863709,2.722151,-0.93666, + -0.47673,0.840923,0.25608,4.735445,2.749285,-0.940329, + -0.145585,0.915338,0.375448,4.827733,2.75439,-0.905049, + 0.225135,0.965893,-0.127928,4.863709,2.722151,-0.93666, + -0.145585,0.915338,0.375448,4.827733,2.75439,-0.905049, + -0.86136,-0.239794,-0.447836,5.096148,2.75972,-0.774729, + 0.05537,0.916343,-0.396546,4.854957,2.660227,-0.92431, + 0.225135,0.965893,-0.127928,4.863709,2.722151,-0.93666, + -0.86136,-0.239794,-0.447836,5.096148,2.75972,-0.774729, + -0.376273,-0.14016,-0.915846,4.821336,2.621498,-0.789636, + -0.395723,0.901671,-0.174334,4.829566,2.580797,-0.821827, + -0.86136,-0.239794,-0.447836,5.096148,2.75972,-0.774729, + -0.395723,0.901671,-0.174334,4.829566,2.580797,-0.821827, + -0.476949,0.871028,-0.117606,4.856249,2.593812,-0.867067, + -0.86136,-0.239794,-0.447836,5.096148,2.75972,-0.774729, + -0.877603,-0.025309,0.478719,4.344028,2.585635,0.470949, + -0.130291,0.991051,0.029017,4.328606,2.563996,0.343892, + -0.904972,-0.026555,0.424641,4.209941,2.600612,0.337597, + -0.877603,-0.025309,0.478719,4.344028,2.585635,0.470949, + -0.904972,-0.026555,0.424641,4.209941,2.600612,0.337597, + -0.778386,0.466325,0.420305,4.22473,2.624525,0.491916, + 0.197027,0.937222,0.287741,4.407729,2.53164,0.486692, + -0.501953,0.842502,0.195534,4.410844,2.500167,0.351972, + -0.130291,0.991051,0.029017,4.328606,2.563996,0.343892, + 0.197027,0.937222,0.287741,4.407729,2.53164,0.486692, + -0.130291,0.991051,0.029017,4.328606,2.563996,0.343892, + -0.877603,-0.025309,0.478719,4.344028,2.585635,0.470949, + 0.223577,0.97296,-0.057987,4.359483,2.615839,0.596817, + -0.877603,-0.025309,0.478719,4.344028,2.585635,0.470949, + -0.778386,0.466325,0.420305,4.22473,2.624525,0.491916, + 0.223577,0.97296,-0.057987,4.359483,2.615839,0.596817, + -0.778386,0.466325,0.420305,4.22473,2.624525,0.491916, + 0.225135,0.965893,0.127928,4.277169,2.652435,0.591369, + -0.247355,0.948391,-0.198417,4.423033,2.561337,0.603562, + 0.197027,0.937222,0.287741,4.407729,2.53164,0.486692, + -0.877603,-0.025309,0.478719,4.344028,2.585635,0.470949, + -0.247355,0.948391,-0.198417,4.423033,2.561337,0.603562, + -0.877603,-0.025309,0.478719,4.344028,2.585635,0.470949, + 0.223577,0.97296,-0.057987,4.359483,2.615839,0.596817, + -0.860595,0.405543,0.308077,4.411541,2.663824,0.713132, + 0.223577,0.97296,-0.057987,4.359483,2.615839,0.596817, + 0.225135,0.965893,0.127928,4.277169,2.652435,0.591369, + -0.860595,0.405543,0.308077,4.411541,2.663824,0.713132, + 0.225135,0.965893,0.127928,4.277169,2.652435,0.591369, + -0.671788,0.737297,0.07138,4.35668,2.682996,0.71905, + -0.162972,0.917259,-0.363422,4.47609,2.606654,0.692301, + -0.247355,0.948391,-0.198417,4.423033,2.561337,0.603562, + 0.223577,0.97296,-0.057987,4.359483,2.615839,0.596817, + -0.162972,0.917259,-0.363422,4.47609,2.606654,0.692301, + 0.223577,0.97296,-0.057987,4.359483,2.615839,0.596817, + -0.860595,0.405543,0.308077,4.411541,2.663824,0.713132, + -0.758791,0.646991,-0.075091,4.465268,2.695425,0.757267, + -0.860595,0.405543,0.308077,4.411541,2.663824,0.713132, + -0.671788,0.737297,0.07138,4.35668,2.682996,0.71905, + -0.758791,0.646991,-0.075091,4.465268,2.695425,0.757267, + -0.671788,0.737297,0.07138,4.35668,2.682996,0.71905, + -0.31499,0.894135,-0.318282,4.418954,2.707401,0.782531, + -0.758791,0.646991,-0.075091,4.465268,2.695425,0.757267, + -0.900694,0.426849,0.080936,4.520603,2.639162,0.745542, + -0.162972,0.917259,-0.363422,4.47609,2.606654,0.692301, + -0.758791,0.646991,-0.075091,4.465268,2.695425,0.757267, + -0.162972,0.917259,-0.363422,4.47609,2.606654,0.692301, + -0.860595,0.405543,0.308077,4.411541,2.663824,0.713132, + -0.816521,0.559553,-0.142109,4.546655,2.709095,0.80378, + -0.758791,0.646991,-0.075091,4.465268,2.695425,0.757267, + -0.31499,0.894135,-0.318282,4.418954,2.707401,0.782531, + -0.816521,0.559553,-0.142109,4.546655,2.709095,0.80378, + -0.31499,0.894135,-0.318282,4.418954,2.707401,0.782531, + -0.940256,0.335069,-0.060403,4.509555,2.719807,0.819972, + -0.816521,0.559553,-0.142109,4.546655,2.709095,0.80378, + -0.683788,0.700764,-0.203383,4.574545,2.669863,0.780363, + -0.900694,0.426849,0.080936,4.520603,2.639162,0.745542, + -0.816521,0.559553,-0.142109,4.546655,2.709095,0.80378, + -0.900694,0.426849,0.080936,4.520603,2.639162,0.745542, + -0.758791,0.646991,-0.075091,4.465268,2.695425,0.757267, + -0.476729,0.840923,-0.25608,4.44385,2.449921,0.495432, + -0.849668,0.488771,-0.197904,4.474318,2.418432,0.361347, + -0.501953,0.842502,0.195534,4.410844,2.500167,0.351972, + -0.476729,0.840923,-0.25608,4.44385,2.449921,0.495432, + -0.501953,0.842502,0.195534,4.410844,2.500167,0.351972, + 0.197027,0.937222,0.287741,4.407729,2.53164,0.486692, + -0.145585,0.915338,-0.375448,4.44076,2.490353,0.629287, + -0.476729,0.840923,-0.25608,4.44385,2.449921,0.495432, + 0.197027,0.937222,0.287741,4.407729,2.53164,0.486692, + -0.145585,0.915338,-0.375448,4.44076,2.490353,0.629287, + 0.197027,0.937222,0.287741,4.407729,2.53164,0.486692, + -0.247355,0.948391,-0.198417,4.423033,2.561337,0.603562, + -0.210882,0.942026,-0.260988,4.484667,2.534451,0.708888, + -0.145585,0.915338,-0.375448,4.44076,2.490353,0.629287, + -0.247355,0.948391,-0.198417,4.423033,2.561337,0.603562, + -0.210882,0.942026,-0.260988,4.484667,2.534451,0.708888, + -0.247355,0.948391,-0.198417,4.423033,2.561337,0.603562, + -0.162972,0.917259,-0.363422,4.47609,2.606654,0.692301, + -0.502348,0.838173,-0.212398,4.520165,2.557971,0.762427, + -0.210882,0.942026,-0.260988,4.484667,2.534451,0.708888, + -0.162972,0.917259,-0.363422,4.47609,2.606654,0.692301, + -0.502348,0.838173,-0.212398,4.520165,2.557971,0.762427, + -0.162972,0.917259,-0.363422,4.47609,2.606654,0.692301, + -0.900694,0.426849,0.080936,4.520603,2.639162,0.745542, + -0.768362,0.592231,-0.242657,4.59262,2.569879,0.790452, + -0.502348,0.838173,-0.212398,4.520165,2.557971,0.762427, + -0.900694,0.426849,0.080936,4.520603,2.639162,0.745542, + -0.768362,0.592231,-0.242657,4.59262,2.569879,0.790452, + -0.900694,0.426849,0.080936,4.520603,2.639162,0.745542, + -0.683788,0.700764,-0.203383,4.574545,2.669863,0.780363, + -0.981668,0.173926,-0.077954,4.674691,2.598833,0.808006, + -0.768362,0.592231,-0.242657,4.59262,2.569879,0.790452, + -0.683788,0.700764,-0.203383,4.574545,2.669863,0.780363, + -0.981668,0.173926,-0.077954,4.674691,2.598833,0.808006, + -0.683788,0.700764,-0.203383,4.574545,2.669863,0.780363, + -0.892748,0.392127,-0.221893,4.656565,2.680542,0.799684, + -0.892748,0.392127,-0.221893,4.656565,2.680542,0.799684, + -0.683788,0.700764,-0.203383,4.574545,2.669863,0.780363, + -0.816521,0.559553,-0.142109,4.546655,2.709095,0.80378, + -0.892748,0.392127,-0.221893,4.656565,2.680542,0.799684, + -0.816521,0.559553,-0.142109,4.546655,2.709095,0.80378, + -0.990661,0.056144,-0.124249,4.646703,2.728688,0.822295, + -0.990661,0.056144,-0.124249,4.646703,2.728688,0.822295, + -0.816521,0.559553,-0.142109,4.546655,2.709095,0.80378, + -0.940256,0.335069,-0.060403,4.509555,2.719807,0.819972, + -0.990661,0.056144,-0.124249,4.646703,2.728688,0.822295, + -0.940256,0.335069,-0.060403,4.509555,2.719807,0.819972, + -0.894795,0.444359,-0.043442,4.636909,2.750501,0.856859, + -0.984655,0.15519,0.07981,4.729447,2.606204,0.807513, + -0.981668,0.173926,-0.077954,4.674691,2.598833,0.808006, + -0.892748,0.392127,-0.221893,4.656565,2.680542,0.799684, + -0.984655,0.15519,0.07981,4.729447,2.606204,0.807513, + -0.892748,0.392127,-0.221893,4.656565,2.680542,0.799684, + -0.941564,0.056551,0.332054,4.748031,2.683805,0.800044, + -0.941564,0.056551,0.332054,4.748031,2.683805,0.800044, + -0.892748,0.392127,-0.221893,4.656565,2.680542,0.799684, + -0.990661,0.056144,-0.124249,4.646703,2.728688,0.822295, + -0.941564,0.056551,0.332054,4.748031,2.683805,0.800044, + -0.990661,0.056144,-0.124249,4.646703,2.728688,0.822295, + -0.978317,0.206989,-0.00716,4.728931,2.721892,0.832625, + -0.978317,0.206989,-0.00716,4.728931,2.721892,0.832625, + -0.990661,0.056144,-0.124249,4.646703,2.728688,0.822295, + -0.894795,0.444359,-0.043442,4.636909,2.750501,0.856859, + -0.978317,0.206989,-0.00716,4.728931,2.721892,0.832625, + -0.894795,0.444359,-0.043442,4.636909,2.750501,0.856859, + -0.463096,-0.149333,0.873637,4.719171,2.751091,0.865965, + -0.791764,-0.610494,-0.020171,4.821336,2.621498,0.789636, + -0.984655,0.15519,0.07981,4.729447,2.606204,0.807513, + -0.941564,0.056551,0.332054,4.748031,2.683805,0.800044, + -0.791764,-0.610494,-0.020171,4.821336,2.621498,0.789636, + -0.941564,0.056551,0.332054,4.748031,2.683805,0.800044, + -0.64155,-0.578509,0.503727,4.821325,2.691794,0.791887, + -0.64155,-0.578509,0.503727,4.821325,2.691794,0.791887, + -0.941564,0.056551,0.332054,4.748031,2.683805,0.800044, + -0.978317,0.206989,-0.00716,4.728931,2.721892,0.832625, + -0.64155,-0.578509,0.503727,4.821325,2.691794,0.791887, + -0.978317,0.206989,-0.00716,4.728931,2.721892,0.832625, + -0.832539,-0.5495,0.070196,4.811798,2.72868,0.815406, + -0.862876,-0.450622,0.228877,4.801436,2.750224,0.858918, + -0.832539,-0.5495,0.070196,4.811798,2.72868,0.815406, + -0.978317,0.206989,-0.00716,4.728931,2.721892,0.832625, + -0.862876,-0.450622,0.228877,4.801436,2.750224,0.858918, + -0.978317,0.206989,-0.00716,4.728931,2.721892,0.832625, + -0.463096,-0.149333,0.873637,4.719171,2.751091,0.865965, + -0.832539,-0.5495,0.070196,4.811798,2.72868,0.815406, + -0.862876,-0.450622,0.228877,4.801436,2.750224,0.858918, + -0.916647,-0.2944,0.270344,5.096148,2.75972,0.774729, + -0.64155,-0.578509,0.503727,4.821325,2.691794,0.791887, + -0.832539,-0.5495,0.070196,4.811798,2.72868,0.815406, + -0.916647,-0.2944,0.270344,5.096148,2.75972,0.774729, + -0.791764,-0.610494,-0.020171,4.821336,2.621498,0.789636, + -0.64155,-0.578509,0.503727,4.821325,2.691794,0.791887, + -0.916647,-0.2944,0.270344,5.096148,2.75972,0.774729, + 0.231006,-0.859096,0.456717,4.472349,2.325133,0.443764, + -0.849668,0.488771,-0.197904,4.474318,2.418432,0.361347, + -0.476729,0.840923,-0.25608,4.44385,2.449921,0.495432, + 0.231006,-0.859096,0.456717,4.472349,2.325133,0.443764, + -0.476729,0.840923,-0.25608,4.44385,2.449921,0.495432, + -0.975013,-0.179566,0.130791,4.442912,2.343263,0.53322, + -0.975013,-0.179566,0.130791,4.442912,2.343263,0.53322, + -0.476729,0.840923,-0.25608,4.44385,2.449921,0.495432, + -0.145585,0.915338,-0.375448,4.44076,2.490353,0.629287, + -0.975013,-0.179566,0.130791,4.442912,2.343263,0.53322, + -0.145585,0.915338,-0.375448,4.44076,2.490353,0.629287, + -0.963659,-0.230665,0.134738,4.440713,2.398472,0.629128, + -0.990956,-0.062739,0.118613,4.474625,2.465214,0.75189, + -0.963659,-0.230665,0.134738,4.440713,2.398472,0.629128, + -0.145585,0.915338,-0.375448,4.44076,2.490353,0.629287, + -0.990956,-0.062739,0.118613,4.474625,2.465214,0.75189, + -0.145585,0.915338,-0.375448,4.44076,2.490353,0.629287, + -0.210882,0.942026,-0.260988,4.484667,2.534451,0.708888, + -0.473779,-0.24744,0.845167,4.32063,2.385528,0.682583, + -0.938303,-0.3372,0.076703,4.314039,2.32946,0.57751, + -0.975013,-0.179566,0.130791,4.442912,2.343263,0.53322, + -0.473779,-0.24744,0.845167,4.32063,2.385528,0.682583, + -0.975013,-0.179566,0.130791,4.442912,2.343263,0.53322, + -0.963659,-0.230665,0.134738,4.440713,2.398472,0.629128, + -0.713872,-0.610821,0.342469,4.296769,2.260422,0.528796, + 0.231006,-0.859096,0.456717,4.472349,2.325133,0.443764, + -0.975013,-0.179566,0.130791,4.442912,2.343263,0.53322, + -0.713872,-0.610821,0.342469,4.296769,2.260422,0.528796, + -0.975013,-0.179566,0.130791,4.442912,2.343263,0.53322, + -0.938303,-0.3372,0.076703,4.314039,2.32946,0.57751, + -0.719395,-0.61545,0.322011,4.382053,2.433474,0.798757, + -0.473779,-0.24744,0.845167,4.32063,2.385528,0.682583, + -0.963659,-0.230665,0.134738,4.440713,2.398472,0.629128, + -0.719395,-0.61545,0.322011,4.382053,2.433474,0.798757, + -0.963659,-0.230665,0.134738,4.440713,2.398472,0.629128, + -0.990956,-0.062739,0.118613,4.474625,2.465214,0.75189, + -0.841909,-0.49598,0.212588,4.538177,2.513353,0.776566, + -0.990956,-0.062739,0.118613,4.474625,2.465214,0.75189, + -0.210882,0.942026,-0.260988,4.484667,2.534451,0.708888, + -0.841909,-0.49598,0.212588,4.538177,2.513353,0.776566, + -0.210882,0.942026,-0.260988,4.484667,2.534451,0.708888, + -0.502348,0.838173,-0.212398,4.520165,2.557971,0.762427, + 0.760119,-0.003927,0.649772,4.444739,2.475795,0.860515, + -0.719395,-0.61545,0.322011,4.382053,2.433474,0.798757, + -0.990956,-0.062739,0.118613,4.474625,2.465214,0.75189, + 0.760119,-0.003927,0.649772,4.444739,2.475795,0.860515, + -0.990956,-0.062739,0.118613,4.474625,2.465214,0.75189, + -0.841909,-0.49598,0.212588,4.538177,2.513353,0.776566, + 0.911709,-0.064353,0.405764,4.601515,2.533324,0.794193, + -0.841909,-0.49598,0.212588,4.538177,2.513353,0.776566, + -0.502348,0.838173,-0.212398,4.520165,2.557971,0.762427, + 0.911709,-0.064353,0.405764,4.601515,2.533324,0.794193, + -0.502348,0.838173,-0.212398,4.520165,2.557971,0.762427, + -0.768362,0.592231,-0.242657,4.59262,2.569879,0.790452, + 0.3335,0.232683,0.913584,4.554459,2.511417,0.850571, + 0.760119,-0.003927,0.649772,4.444739,2.475795,0.860515, + -0.841909,-0.49598,0.212588,4.538177,2.513353,0.776566, + 0.3335,0.232683,0.913584,4.554459,2.511417,0.850571, + -0.841909,-0.49598,0.212588,4.538177,2.513353,0.776566, + 0.911709,-0.064353,0.405764,4.601515,2.533324,0.794193, + 0.245858,0.150988,0.957474,4.683344,2.554221,0.821927, + 0.911709,-0.064353,0.405764,4.601515,2.533324,0.794193, + -0.768362,0.592231,-0.242657,4.59262,2.569879,0.790452, + 0.245858,0.150988,0.957474,4.683344,2.554221,0.821927, + -0.768362,0.592231,-0.242657,4.59262,2.569879,0.790452, + -0.981668,0.173926,-0.077954,4.674691,2.598833,0.808006, + 0.895851,0.326389,0.301532,4.681847,2.551036,0.886235, + 0.3335,0.232683,0.913584,4.554459,2.511417,0.850571, + 0.911709,-0.064353,0.405764,4.601515,2.533324,0.794193, + 0.895851,0.326389,0.301532,4.681847,2.551036,0.886235, + 0.911709,-0.064353,0.405764,4.601515,2.533324,0.794193, + 0.245858,0.150988,0.957474,4.683344,2.554221,0.821927, + -0.279333,0.256918,0.925184,4.755192,2.568818,0.876311, + 0.895851,0.326389,0.301532,4.681847,2.551036,0.886235, + 0.245858,0.150988,0.957474,4.683344,2.554221,0.821927, + -0.279333,0.256918,0.925184,4.755192,2.568818,0.876311, + 0.245858,0.150988,0.957474,4.683344,2.554221,0.821927, + -0.396467,0.225967,0.889805,4.737893,2.564648,0.830389, + -0.274209,-0.939323,-0.20611,4.856249,2.593812,0.867067, + -0.279333,0.256918,0.925184,4.755192,2.568818,0.876311, + -0.396467,0.225967,0.889805,4.737893,2.564648,0.830389, + -0.274209,-0.939323,-0.20611,4.856249,2.593812,0.867067, + -0.396467,0.225967,0.889805,4.737893,2.564648,0.830389, + -0.274209,-0.939323,-0.20611,4.829566,2.580797,0.821827, + -0.396467,0.225967,0.889805,4.737893,2.564648,0.830389, + 0.245858,0.150988,0.957474,4.683344,2.554221,0.821927, + -0.981668,0.173926,-0.077954,4.674691,2.598833,0.808006, + -0.396467,0.225967,0.889805,4.737893,2.564648,0.830389, + -0.981668,0.173926,-0.077954,4.674691,2.598833,0.808006, + -0.984655,0.15519,0.07981,4.729447,2.606204,0.807513, + -0.274209,-0.939323,-0.20611,4.829566,2.580797,0.821827, + -0.396467,0.225967,0.889805,4.737893,2.564648,0.830389, + -0.984655,0.15519,0.07981,4.729447,2.606204,0.807513, + -0.274209,-0.939323,-0.20611,4.829566,2.580797,0.821827, + -0.984655,0.15519,0.07981,4.729447,2.606204,0.807513, + -0.791764,-0.610494,-0.020171,4.821336,2.621498,0.789636, + -0.21443,-0.974064,0.072245,4.497719,2.54748,0.937659, + 0.3335,0.232683,0.913584,4.554459,2.511417,0.850571, + 0.895851,0.326389,0.301532,4.681847,2.551036,0.886235, + -0.21443,-0.974064,0.072245,4.497719,2.54748,0.937659, + 0.895851,0.326389,0.301532,4.681847,2.551036,0.886235, + -0.21443,-0.974064,0.072245,4.662221,2.556346,0.940618, + -0.279333,0.256918,0.925184,4.755192,2.568818,0.876311, + -0.137011,-0.928676,0.344657,4.763337,2.590834,0.929248, + -0.21443,-0.974064,0.072245,4.662221,2.556346,0.940618, + -0.279333,0.256918,0.925184,4.755192,2.568818,0.876311, + -0.21443,-0.974064,0.072245,4.662221,2.556346,0.940618, + 0.895851,0.326389,0.301532,4.681847,2.551036,0.886235, + -0.137011,-0.928676,0.344657,4.763337,2.590834,0.929248, + -0.279333,0.256918,0.925184,4.755192,2.568818,0.876311, + -0.274209,-0.939323,-0.20611,4.856249,2.593812,0.867067, + -0.137011,-0.928676,0.344657,4.763337,2.590834,0.929248, + -0.274209,-0.939323,-0.20611,4.856249,2.593812,0.867067, + -0.137011,-0.928676,0.344657,4.883022,2.613658,0.893163, + -0.21443,-0.974064,0.072245,4.497719,2.54748,0.937659, + -0.250481,-0.945625,-0.207493,4.352603,2.524888,0.890532, + 0.760119,-0.003927,0.649772,4.444739,2.475795,0.860515, + -0.21443,-0.974064,0.072245,4.497719,2.54748,0.937659, + 0.760119,-0.003927,0.649772,4.444739,2.475795,0.860515, + 0.3335,0.232683,0.913584,4.554459,2.511417,0.850571, + -0.250481,-0.945625,-0.207493,4.262798,2.490674,0.818316, + -0.719395,-0.61545,0.322011,4.382053,2.433474,0.798757, + 0.760119,-0.003927,0.649772,4.444739,2.475795,0.860515, + -0.250481,-0.945625,-0.207493,4.262798,2.490674,0.818316, + 0.760119,-0.003927,0.649772,4.444739,2.475795,0.860515, + -0.250481,-0.945625,-0.207493,4.352603,2.524888,0.890532, + -0.19553,-0.978064,0.071821,4.192789,2.411967,0.668016, + -0.473779,-0.24744,0.845167,4.32063,2.385528,0.682583, + -0.719395,-0.61545,0.322011,4.382053,2.433474,0.798757, + -0.19553,-0.978064,0.071821,4.192789,2.411967,0.668016, + -0.719395,-0.61545,0.322011,4.382053,2.433474,0.798757, + -0.250481,-0.945625,-0.207493,4.262798,2.490674,0.818316, + -0.19553,-0.978064,0.071821,4.193959,2.370476,0.616705, + -0.938303,-0.3372,0.076703,4.314039,2.32946,0.57751, + -0.473779,-0.24744,0.845167,4.32063,2.385528,0.682583, + -0.19553,-0.978064,0.071821,4.193959,2.370476,0.616705, + -0.473779,-0.24744,0.845167,4.32063,2.385528,0.682583, + -0.19553,-0.978064,0.071821,4.192789,2.411967,0.668016, + -0.713872,-0.610821,0.342469,4.296769,2.260422,0.528796, + -0.938303,-0.3372,0.076703,4.314039,2.32946,0.57751, + -0.19553,-0.978064,0.071821,4.193959,2.370476,0.616705, + -0.713872,-0.610821,0.342469,4.296769,2.260422,0.528796, + -0.19553,-0.978064,0.071821,4.193959,2.370476,0.616705, + -0.124529,-0.930217,0.345238,4.113935,2.334131,0.526471, + -0.274209,-0.939323,-0.20611,4.856249,2.593812,0.867067, + -0.916647,-0.2944,0.270344,5.096148,2.75972,0.774729, + -0.137011,-0.928676,0.344657,4.883022,2.613658,0.893163, + -0.137011,-0.928676,0.344657,4.883022,2.613658,0.893163, + 0.186393,-0.974436,-0.125429,4.854957,2.660227,0.92431, + -0.124529,-0.930217,0.345238,4.735139,2.645464,0.95089, + -0.137011,-0.928676,0.344657,4.883022,2.613658,0.893163, + -0.124529,-0.930217,0.345238,4.735139,2.645464,0.95089, + -0.137011,-0.928676,0.344657,4.763337,2.590834,0.929248, + -0.137011,-0.928676,0.344657,4.763337,2.590834,0.929248, + -0.124529,-0.930217,0.345238,4.735139,2.645464,0.95089, + 0.361848,-0.921221,-0.142892,4.615662,2.63387,0.977986, + -0.137011,-0.928676,0.344657,4.763337,2.590834,0.929248, + 0.361848,-0.921221,-0.142892,4.615662,2.63387,0.977986, + -0.21443,-0.974064,0.072245,4.662221,2.556346,0.940618, + -0.21443,-0.974064,0.072245,4.662221,2.556346,0.940618, + 0.361848,-0.921221,-0.142892,4.615662,2.63387,0.977986, + -0.199236,-0.974239,-0.105658,4.460582,2.622875,0.957002, + -0.21443,-0.974064,0.072245,4.662221,2.556346,0.940618, + -0.199236,-0.974239,-0.105658,4.460582,2.622875,0.957002, + -0.21443,-0.974064,0.072245,4.497719,2.54748,0.937659, + -0.21443,-0.974064,0.072245,4.497719,2.54748,0.937659, + -0.199236,-0.974239,-0.105658,4.460582,2.622875,0.957002, + -0.942162,-0.29295,-0.162822,4.343217,2.589542,0.893106, + -0.21443,-0.974064,0.072245,4.497719,2.54748,0.937659, + -0.942162,-0.29295,-0.162822,4.343217,2.589542,0.893106, + -0.250481,-0.945625,-0.207493,4.352603,2.524888,0.890532, + -0.250481,-0.945625,-0.207493,4.352603,2.524888,0.890532, + -0.942162,-0.29295,-0.162822,4.343217,2.589542,0.893106, + -0.982438,-0.108835,-0.151559,4.244622,2.554467,0.811726, + -0.250481,-0.945625,-0.207493,4.352603,2.524888,0.890532, + -0.982438,-0.108835,-0.151559,4.244622,2.554467,0.811726, + -0.250481,-0.945625,-0.207493,4.262798,2.490674,0.818316, + -0.250481,-0.945625,-0.207493,4.262798,2.490674,0.818316, + -0.982438,-0.108835,-0.151559,4.244622,2.554467,0.811726, + -0.668254,-0.729938,-0.143622,4.138687,2.474013,0.642311, + -0.250481,-0.945625,-0.207493,4.262798,2.490674,0.818316, + -0.668254,-0.729938,-0.143622,4.138687,2.474013,0.642311, + -0.19553,-0.978064,0.071821,4.192789,2.411967,0.668016, + -0.916647,-0.2944,0.270344,5.096148,2.75972,0.774729, + 0.186393,-0.974436,-0.125429,4.854957,2.660227,0.92431, + -0.137011,-0.928676,0.344657,4.883022,2.613658,0.893163, + -0.19553,-0.978064,0.071821,4.193959,2.370476,0.616705, + -0.19553,-0.978064,0.071821,4.192789,2.411967,0.668016, + -0.668254,-0.729938,-0.143622,4.138687,2.474013,0.642311, + -0.19553,-0.978064,0.071821,4.193959,2.370476,0.616705, + -0.668254,-0.729938,-0.143622,4.138687,2.474013,0.642311, + -0.973393,-0.128296,0.18986,4.121994,2.458034,0.570029, + -0.138401,-0.989733,0.035683,4.07851,2.41181,0.472193, + -0.124529,-0.930217,0.345238,4.113935,2.334131,0.526471, + -0.19553,-0.978064,0.071821,4.193959,2.370476,0.616705, + -0.138401,-0.989733,0.035683,4.07851,2.41181,0.472193, + -0.19553,-0.978064,0.071821,4.193959,2.370476,0.616705, + -0.973393,-0.128296,0.18986,4.121994,2.458034,0.570029, + -0.942162,-0.29295,-0.162822,4.343217,2.589542,0.893106, + -0.927379,-0.346541,0.14099,4.342998,2.664049,0.904347, + -0.601432,-0.796051,0.067694,4.235494,2.636171,0.803613, + -0.942162,-0.29295,-0.162822,4.343217,2.589542,0.893106, + -0.601432,-0.796051,0.067694,4.235494,2.636171,0.803613, + -0.982438,-0.108835,-0.151559,4.244622,2.554467,0.811726, + -0.199236,-0.974239,-0.105658,4.460582,2.622875,0.957002, + -0.850433,-0.132742,0.509061,4.460786,2.695616,0.949972, + -0.927379,-0.346541,0.14099,4.342998,2.664049,0.904347, + -0.199236,-0.974239,-0.105658,4.460582,2.622875,0.957002, + -0.927379,-0.346541,0.14099,4.342998,2.664049,0.904347, + -0.942162,-0.29295,-0.162822,4.343217,2.589542,0.893106, + 0.361848,-0.921221,-0.142892,4.615662,2.63387,0.977986, + -0.822149,-0.367113,0.435086,4.6248,2.708372,0.989445, + -0.850433,-0.132742,0.509061,4.460786,2.695616,0.949972, + 0.361848,-0.921221,-0.142892,4.615662,2.63387,0.977986, + -0.850433,-0.132742,0.509061,4.460786,2.695616,0.949972, + -0.199236,-0.974239,-0.105658,4.460582,2.622875,0.957002, + -0.982438,-0.108835,-0.151559,4.244622,2.554467,0.811726, + -0.601432,-0.796051,0.067694,4.235494,2.636171,0.803613, + -0.501842,-0.819591,0.27645,4.138494,2.557838,0.652651, + -0.982438,-0.108835,-0.151559,4.244622,2.554467,0.811726, + -0.501842,-0.819591,0.27645,4.138494,2.557838,0.652651, + -0.668254,-0.729938,-0.143622,4.138687,2.474013,0.642311, + -0.973393,-0.128296,0.18986,4.121994,2.458034,0.570029, + -0.668254,-0.729938,-0.143622,4.138687,2.474013,0.642311, + -0.501842,-0.819591,0.27645,4.138494,2.557838,0.652651, + -0.973393,-0.128296,0.18986,4.121994,2.458034,0.570029, + -0.501842,-0.819591,0.27645,4.138494,2.557838,0.652651, + -0.075112,-0.981815,0.174346,4.104292,2.537976,0.543437, + -0.138401,-0.989733,0.035683,4.07851,2.41181,0.472193, + -0.973393,-0.128296,0.18986,4.121994,2.458034,0.570029, + -0.075112,-0.981815,0.174346,4.104292,2.537976,0.543437, + -0.138401,-0.989733,0.035683,4.07851,2.41181,0.472193, + -0.075112,-0.981815,0.174346,4.104292,2.537976,0.543437, + 0.207048,-0.965263,0.159371,4.088356,2.510913,0.453793, + 0.361848,-0.921221,-0.142892,4.615662,2.63387,0.977986, + -0.124529,-0.930217,0.345238,4.735139,2.645464,0.95089, + 0.846486,-0.14409,-0.512541,4.753015,2.699695,0.973279, + 0.361848,-0.921221,-0.142892,4.615662,2.63387,0.977986, + 0.846486,-0.14409,-0.512541,4.753015,2.699695,0.973279, + -0.822149,-0.367113,0.435086,4.6248,2.708372,0.989445, + 0.186393,-0.974436,-0.125429,4.854957,2.660227,0.92431, + 0.728229,-0.106722,-0.676973,4.863709,2.722151,0.93666, + 0.846486,-0.14409,-0.512541,4.753015,2.699695,0.973279, + 0.186393,-0.974436,-0.125429,4.854957,2.660227,0.92431, + 0.846486,-0.14409,-0.512541,4.753015,2.699695,0.973279, + -0.124529,-0.930217,0.345238,4.735139,2.645464,0.95089, + -0.904972,-0.026555,0.424641,4.209941,2.600612,0.337597, + 0.576293,-0.081905,-0.813128,4.117367,2.568514,0.3845, + 0.42646,-0.865041,0.264264,4.151183,2.579059,0.494606, + -0.904972,-0.026555,0.424641,4.209941,2.600612,0.337597, + 0.42646,-0.865041,0.264264,4.151183,2.579059,0.494606, + -0.778386,0.466325,0.420305,4.22473,2.624525,0.491916, + -0.940256,0.335069,-0.060403,4.509555,2.719807,0.819972, + -0.266521,-0.953514,0.14063,4.462368,2.725999,0.882675, + 0.078387,-0.886884,0.455294,4.616626,2.749486,0.939333, + -0.940256,0.335069,-0.060403,4.509555,2.719807,0.819972, + 0.078387,-0.886884,0.455294,4.616626,2.749486,0.939333, + -0.894795,0.444359,-0.043442,4.636909,2.750501,0.856859, + -0.31499,0.894135,-0.318282,4.418954,2.707401,0.782531, + -0.393317,-0.870591,-0.295589,4.354196,2.711836,0.826545, + -0.266521,-0.953514,0.14063,4.462368,2.725999,0.882675, + -0.31499,0.894135,-0.318282,4.418954,2.707401,0.782531, + -0.266521,-0.953514,0.14063,4.462368,2.725999,0.882675, + -0.940256,0.335069,-0.060403,4.509555,2.719807,0.819972, + -0.671788,0.737297,0.07138,4.35668,2.682996,0.71905, + -0.180888,-0.792822,-0.58199,4.273414,2.686575,0.753674, + -0.393317,-0.870591,-0.295589,4.354196,2.711836,0.826545, + -0.671788,0.737297,0.07138,4.35668,2.682996,0.71905, + -0.393317,-0.870591,-0.295589,4.354196,2.711836,0.826545, + -0.31499,0.894135,-0.318282,4.418954,2.707401,0.782531, + 0.333262,-0.530645,-0.779328,4.176065,2.636883,0.618384, + 0.225135,0.965893,0.127928,4.277169,2.652435,0.591369, + -0.778386,0.466325,0.420305,4.22473,2.624525,0.491916, + 0.333262,-0.530645,-0.779328,4.176065,2.636883,0.618384, + -0.778386,0.466325,0.420305,4.22473,2.624525,0.491916, + 0.42646,-0.865041,0.264264,4.151183,2.579059,0.494606, + -0.075112,-0.981815,0.174346,4.104292,2.537976,0.543437, + 0.42646,-0.865041,0.264264,4.151183,2.579059,0.494606, + 0.576293,-0.081905,-0.813128,4.117367,2.568514,0.3845, + -0.075112,-0.981815,0.174346,4.104292,2.537976,0.543437, + 0.576293,-0.081905,-0.813128,4.117367,2.568514,0.3845, + 0.207048,-0.965263,0.159371,4.088356,2.510913,0.453793, + -0.180888,-0.792822,-0.58199,4.273414,2.686575,0.753674, + -0.671788,0.737297,0.07138,4.35668,2.682996,0.71905, + 0.225135,0.965893,0.127928,4.277169,2.652435,0.591369, + -0.180888,-0.792822,-0.58199,4.273414,2.686575,0.753674, + 0.225135,0.965893,0.127928,4.277169,2.652435,0.591369, + 0.333262,-0.530645,-0.779328,4.176065,2.636883,0.618384, + -0.501842,-0.819591,0.27645,4.138494,2.557838,0.652651, + 0.333262,-0.530645,-0.779328,4.176065,2.636883,0.618384, + 0.42646,-0.865041,0.264264,4.151183,2.579059,0.494606, + -0.501842,-0.819591,0.27645,4.138494,2.557838,0.652651, + 0.42646,-0.865041,0.264264,4.151183,2.579059,0.494606, + -0.075112,-0.981815,0.174346,4.104292,2.537976,0.543437, + -0.601432,-0.796051,0.067694,4.235494,2.636171,0.803613, + -0.180888,-0.792822,-0.58199,4.273414,2.686575,0.753674, + 0.333262,-0.530645,-0.779328,4.176065,2.636883,0.618384, + -0.601432,-0.796051,0.067694,4.235494,2.636171,0.803613, + 0.333262,-0.530645,-0.779328,4.176065,2.636883,0.618384, + -0.501842,-0.819591,0.27645,4.138494,2.557838,0.652651, + -0.927379,-0.346541,0.14099,4.342998,2.664049,0.904347, + -0.393317,-0.870591,-0.295589,4.354196,2.711836,0.826545, + -0.180888,-0.792822,-0.58199,4.273414,2.686575,0.753674, + -0.927379,-0.346541,0.14099,4.342998,2.664049,0.904347, + -0.180888,-0.792822,-0.58199,4.273414,2.686575,0.753674, + -0.601432,-0.796051,0.067694,4.235494,2.636171,0.803613, + -0.850433,-0.132742,0.509061,4.460786,2.695616,0.949972, + -0.266521,-0.953514,0.14063,4.462368,2.725999,0.882675, + -0.393317,-0.870591,-0.295589,4.354196,2.711836,0.826545, + -0.850433,-0.132742,0.509061,4.460786,2.695616,0.949972, + -0.393317,-0.870591,-0.295589,4.354196,2.711836,0.826545, + -0.927379,-0.346541,0.14099,4.342998,2.664049,0.904347, + 0.078387,-0.886884,0.455294,4.616626,2.749486,0.939333, + 0.136995,-0.968757,-0.206741,4.735445,2.749285,0.940329, + -0.463096,-0.149333,0.873637,4.719171,2.751091,0.865965, + 0.078387,-0.886884,0.455294,4.616626,2.749486,0.939333, + -0.463096,-0.149333,0.873637,4.719171,2.751091,0.865965, + -0.894795,0.444359,-0.043442,4.636909,2.750501,0.856859, + -0.463096,-0.149333,0.873637,4.719171,2.751091,0.865965, + 0.136995,-0.968757,-0.206741,4.735445,2.749285,0.940329, + -0.460229,-0.015586,-0.887663,4.827733,2.75439,0.905049, + -0.463096,-0.149333,0.873637,4.719171,2.751091,0.865965, + -0.460229,-0.015586,-0.887663,4.827733,2.75439,0.905049, + -0.862876,-0.450622,0.228877,4.801436,2.750224,0.858918, + -0.916647,-0.2944,0.270344,5.096148,2.75972,0.774729, + -0.862876,-0.450622,0.228877,4.801436,2.750224,0.858918, + -0.460229,-0.015586,-0.887663,4.827733,2.75439,0.905049, + -0.850433,-0.132742,0.509061,4.460786,2.695616,0.949972, + -0.822149,-0.367113,0.435086,4.6248,2.708372,0.989445, + 0.078387,-0.886884,0.455294,4.616626,2.749486,0.939333, + -0.850433,-0.132742,0.509061,4.460786,2.695616,0.949972, + 0.078387,-0.886884,0.455294,4.616626,2.749486,0.939333, + -0.266521,-0.953514,0.14063,4.462368,2.725999,0.882675, + -0.822149,-0.367113,0.435086,4.6248,2.708372,0.989445, + 0.846486,-0.14409,-0.512541,4.753015,2.699695,0.973279, + 0.136995,-0.968757,-0.206741,4.735445,2.749285,0.940329, + -0.822149,-0.367113,0.435086,4.6248,2.708372,0.989445, + 0.136995,-0.968757,-0.206741,4.735445,2.749285,0.940329, + 0.078387,-0.886884,0.455294,4.616626,2.749486,0.939333, + -0.460229,-0.015586,-0.887663,4.827733,2.75439,0.905049, + 0.136995,-0.968757,-0.206741,4.735445,2.749285,0.940329, + 0.846486,-0.14409,-0.512541,4.753015,2.699695,0.973279, + -0.460229,-0.015586,-0.887663,4.827733,2.75439,0.905049, + 0.846486,-0.14409,-0.512541,4.753015,2.699695,0.973279, + 0.728229,-0.106722,-0.676973,4.863709,2.722151,0.93666, + -0.916647,-0.2944,0.270344,5.096148,2.75972,0.774729, + -0.460229,-0.015586,-0.887663,4.827733,2.75439,0.905049, + 0.728229,-0.106722,-0.676973,4.863709,2.722151,0.93666, + -0.916647,-0.2944,0.270344,5.096148,2.75972,0.774729, + 0.728229,-0.106722,-0.676973,4.863709,2.722151,0.93666, + 0.186393,-0.974436,-0.125429,4.854957,2.660227,0.92431, + -0.916647,-0.2944,0.270344,5.096148,2.75972,0.774729, + -0.274209,-0.939323,-0.20611,4.829566,2.580797,0.821827, + -0.791764,-0.610494,-0.020171,4.821336,2.621498,0.789636, + -0.916647,-0.2944,0.270344,5.096148,2.75972,0.774729, + -0.274209,-0.939323,-0.20611,4.856249,2.593812,0.867067, + -0.274209,-0.939323,-0.20611,4.829566,2.580797,0.821827 +}; +static const struct gllist frame={GL_N3F_V3F,GL_TRIANGLES,1020,data,NULL}; +const struct gllist *cow_horns=&frame; diff --git a/hacks/glx/cow_tail.c b/hacks/glx/cow_tail.c new file mode 100644 index 00000000..895f05c6 --- /dev/null +++ b/hacks/glx/cow_tail.c @@ -0,0 +1,464 @@ +#include "gllist.h" +static const float data[]={ + -0.54555,-0.056478,0.836173,-3.67645,-0.551317,0.077574, + 0.00197,-0.021649,0.999764,-3.740631,-0.558176,0.085478, + 0.000763,-0.01871,0.999825,-3.72947,-0.869371,0.096946, + -0.54555,-0.056478,0.836173,-3.67645,-0.551317,0.077574, + 0.000763,-0.01871,0.999825,-3.72947,-0.869371,0.096946, + -0.548359,-0.017804,0.836053,-3.699784,-0.759901,0.088664, + -0.548359,-0.017804,0.836053,-3.699784,-0.759901,0.088664, + 0.000763,-0.01871,0.999825,-3.72947,-0.869371,0.096946, + -0.530021,0.13773,0.836724,-3.697889,-0.951955,0.098793, + -0.530021,0.13773,0.836724,-3.697889,-0.951955,0.098793, + 0.000763,-0.01871,0.999825,-3.72947,-0.869371,0.096946, + -0.004656,-0.025693,0.999659,-3.733767,-1.141917,0.111139, + -0.530021,0.13773,0.836724,-3.697889,-0.951955,0.098793, + -0.004656,-0.025693,0.999659,-3.733767,-1.141917,0.111139, + -0.429713,0.351913,0.831567,-3.666536,-1.140372,0.078261, + -0.429713,0.351913,0.831567,-3.666536,-1.140372,0.078261, + -0.004656,-0.025693,0.999659,-3.733767,-1.141917,0.111139, + -0.020872,-0.032587,0.999251,-3.743747,-1.367219,0.100951, + -0.429713,0.351913,0.831567,-3.666536,-1.140372,0.078261, + -0.020872,-0.032587,0.999251,-3.743747,-1.367219,0.100951, + -0.24021,0.502412,0.830591,-3.639696,-1.242349,0.05719, + -0.24021,0.502412,0.830591,-3.639696,-1.242349,0.05719, + -0.020872,-0.032587,0.999251,-3.743747,-1.367219,0.100951, + -0.091034,0.391629,0.915609,-3.823638,-1.557534,0.081533, + -0.24021,0.502412,0.830591,-3.639696,-1.242349,0.05719, + -0.091034,0.391629,0.915609,-3.823638,-1.557534,0.081533, + 0.000909,0.669011,0.743252,-3.581963,-1.413947,-0.104371, + 0.000909,0.669011,0.743252,-3.581963,-1.413947,-0.104371, + -0.091034,0.391629,0.915609,-3.823638,-1.557534,0.081533, + -0.041225,-0.030655,0.99868,-3.683069,-1.591975,-0.115233, + -0.041225,-0.030655,0.99868,-3.683069,-1.591975,-0.115233, + -0.091034,0.391629,0.915609,-3.823638,-1.557534,0.081533, + 0.231733,0.017467,0.972623,-3.890388,-1.750102,0.017612, + -0.041225,-0.030655,0.99868,-3.683069,-1.591975,-0.115233, + 0.231733,0.017467,0.972623,-3.890388,-1.750102,0.017612, + 0.002322,-0.058071,0.99831,-3.828485,-1.786559,-0.114095, + 0.00197,-0.021649,0.999764,-3.740631,-0.558176,0.085478, + 0.518386,-0.029316,0.854644,-3.778908,-0.541975,0.064258, + 0.000763,-0.01871,0.999825,-3.72947,-0.869371,0.096946, + 0.518386,-0.029316,0.854644,-3.778908,-0.541975,0.064258, + 0.548941,0.015145,0.835724,-3.805841,-0.798961,0.099237, + 0.000763,-0.01871,0.999825,-3.72947,-0.869371,0.096946, + 0.000763,-0.01871,0.999825,-3.72947,-0.869371,0.096946, + 0.548941,0.015145,0.835724,-3.805841,-0.798961,0.099237, + -0.004656,-0.025693,0.999659,-3.733767,-1.141917,0.111139, + 0.548941,0.015145,0.835724,-3.805841,-0.798961,0.099237, + 0.549332,-0.018885,0.835391,-3.843256,-0.981402,0.116282, + -0.004656,-0.025693,0.999659,-3.733767,-1.141917,0.111139, + 0.549332,-0.018885,0.835391,-3.843256,-0.981402,0.116282, + 0.516335,-0.196022,0.833651,-3.884588,-1.261469,0.148322, + -0.004656,-0.025693,0.999659,-3.733767,-1.141917,0.111139, + -0.004656,-0.025693,0.999659,-3.733767,-1.141917,0.111139, + 0.516335,-0.196022,0.833651,-3.884588,-1.261469,0.148322, + -0.020872,-0.032587,0.999251,-3.743747,-1.367219,0.100951, + 0.516335,-0.196022,0.833651,-3.884588,-1.261469,0.148322, + 0.368421,-0.433142,0.82259,-3.914006,-1.486854,0.149147, + -0.020872,-0.032587,0.999251,-3.743747,-1.367219,0.100951, + -0.020872,-0.032587,0.999251,-3.743747,-1.367219,0.100951, + 0.368421,-0.433142,0.82259,-3.914006,-1.486854,0.149147, + -0.091034,0.391629,0.915609,-3.823638,-1.557534,0.081533, + 0.368421,-0.433142,0.82259,-3.914006,-1.486854,0.149147, + 0.255239,-0.528232,0.80983,-4.015306,-1.659952,0.130331, + -0.091034,0.391629,0.915609,-3.823638,-1.557534,0.081533, + -0.091034,0.391629,0.915609,-3.823638,-1.557534,0.081533, + 0.255239,-0.528232,0.80983,-4.015306,-1.659952,0.130331, + 0.231733,0.017467,0.972623,-3.890388,-1.750102,0.017612, + 0.255239,-0.528232,0.80983,-4.015306,-1.659952,0.130331, + 0.791625,0.052579,0.608741,-4.107191,-1.83652,0.120149, + 0.231733,0.017467,0.972623,-3.890388,-1.750102,0.017612, + 0.518386,-0.029316,0.854644,-3.778908,-0.541975,0.064258, + 0.875325,0.013439,0.483348,-3.818598,-0.52269,0.055572, + 0.891295,0.039311,0.451717,-3.900964,-0.780883,0.091579, + 0.518386,-0.029316,0.854644,-3.778908,-0.541975,0.064258, + 0.891295,0.039311,0.451717,-3.900964,-0.780883,0.091579, + 0.548941,0.015145,0.835724,-3.805841,-0.798961,0.099237, + 0.548941,0.015145,0.835724,-3.805841,-0.798961,0.099237, + 0.891295,0.039311,0.451717,-3.900964,-0.780883,0.091579, + 0.892259,-0.018571,0.451141,-3.949814,-0.963797,0.140806, + 0.548941,0.015145,0.835724,-3.805841,-0.798961,0.099237, + 0.892259,-0.018571,0.451141,-3.949814,-0.963797,0.140806, + 0.549332,-0.018885,0.835391,-3.843256,-0.981402,0.116282, + 0.549332,-0.018885,0.835391,-3.843256,-0.981402,0.116282, + 0.892259,-0.018571,0.451141,-3.949814,-0.963797,0.140806, + 0.843461,-0.305355,0.441963,-3.974499,-1.1696,0.164243, + 0.549332,-0.018885,0.835391,-3.843256,-0.981402,0.116282, + 0.843461,-0.305355,0.441963,-3.974499,-1.1696,0.164243, + 0.516335,-0.196022,0.833651,-3.884588,-1.261469,0.148322, + 0.516335,-0.196022,0.833651,-3.884588,-1.261469,0.148322, + 0.843461,-0.305355,0.441963,-3.974499,-1.1696,0.164243, + 0.589229,-0.690587,0.419402,-4.018866,-1.413191,0.154149, + 0.516335,-0.196022,0.833651,-3.884588,-1.261469,0.148322, + 0.589229,-0.690587,0.419402,-4.018866,-1.413191,0.154149, + 0.368421,-0.433142,0.82259,-3.914006,-1.486854,0.149147, + 0.368421,-0.433142,0.82259,-3.914006,-1.486854,0.149147, + 0.589229,-0.690587,0.419402,-4.018866,-1.413191,0.154149, + 0.389217,-0.829193,0.401185,-4.154334,-1.677827,0.165852, + 0.368421,-0.433142,0.82259,-3.914006,-1.486854,0.149147, + 0.389217,-0.829193,0.401185,-4.154334,-1.677827,0.165852, + 0.255239,-0.528232,0.80983,-4.015306,-1.659952,0.130331, + 0.255239,-0.528232,0.80983,-4.015306,-1.659952,0.130331, + 0.389217,-0.829193,0.401185,-4.154334,-1.677827,0.165852, + 0.981696,0.042552,-0.185638,-4.207566,-1.922824,0.155104, + 0.255239,-0.528232,0.80983,-4.015306,-1.659952,0.130331, + 0.981696,0.042552,-0.185638,-4.207566,-1.922824,0.155104, + 0.791625,0.052579,0.608741,-4.107191,-1.83652,0.120149, + 0.875325,0.013439,0.483348,-3.818598,-0.52269,0.055572, + 0.999006,0.044565,0.000415,-3.896204,-0.629183,0.077883, + 0.839295,0.00969,-0.54359,-3.978115,-0.82344,0.09928, + 0.875325,0.013439,0.483348,-3.818598,-0.52269,0.055572, + 0.839295,0.00969,-0.54359,-3.978115,-0.82344,0.09928, + 0.891295,0.039311,0.451717,-3.900964,-0.780883,0.091579, + 0.891295,0.039311,0.451717,-3.900964,-0.780883,0.091579, + 0.839295,0.00969,-0.54359,-3.978115,-0.82344,0.09928, + 0.874434,0.048946,-0.48267,-4.029726,-1.043238,0.136305, + 0.891295,0.039311,0.451717,-3.900964,-0.780883,0.091579, + 0.874434,0.048946,-0.48267,-4.029726,-1.043238,0.136305, + 0.892259,-0.018571,0.451141,-3.949814,-0.963797,0.140806, + 0.892259,-0.018571,0.451141,-3.949814,-0.963797,0.140806, + 0.874434,0.048946,-0.48267,-4.029726,-1.043238,0.136305, + 0.843461,-0.305355,0.441963,-3.974499,-1.1696,0.164243, + 0.843461,-0.305355,0.441963,-3.974499,-1.1696,0.164243, + 0.874434,0.048946,-0.48267,-4.029726,-1.043238,0.136305, + 0.432653,0.056559,-0.899785,-4.129295,-1.228786,0.120745, + 0.843461,-0.305355,0.441963,-3.974499,-1.1696,0.164243, + 0.432653,0.056559,-0.899785,-4.129295,-1.228786,0.120745, + 0.589229,-0.690587,0.419402,-4.018866,-1.413191,0.154149, + 0.589229,-0.690587,0.419402,-4.018866,-1.413191,0.154149, + 0.432653,0.056559,-0.899785,-4.129295,-1.228786,0.120745, + 0.517516,0.032105,-0.855071,-4.184154,-1.59808,0.151191, + 0.589229,-0.690587,0.419402,-4.018866,-1.413191,0.154149, + 0.517516,0.032105,-0.855071,-4.184154,-1.59808,0.151191, + 0.389217,-0.829193,0.401185,-4.154334,-1.677827,0.165852, + 0.389217,-0.829193,0.401185,-4.154334,-1.677827,0.165852, + 0.517516,0.032105,-0.855071,-4.184154,-1.59808,0.151191, + 0.002983,0.098874,-0.995096,-4.297769,-1.889903,0.177707, + 0.389217,-0.829193,0.401185,-4.154334,-1.677827,0.165852, + 0.002983,0.098874,-0.995096,-4.297769,-1.889903,0.177707, + 0.981696,0.042552,-0.185638,-4.207566,-1.922824,0.155104, + 0.999006,0.044565,0.000415,-3.896204,-0.629183,0.077883, + 0.001234,0.013557,-0.999907,-3.932489,-0.556566,0.037354, + -0.369174,0.174156,-0.912897,-4.070739,-0.947648,0.110554, + 0.999006,0.044565,0.000415,-3.896204,-0.629183,0.077883, + -0.369174,0.174156,-0.912897,-4.070739,-0.947648,0.110554, + 0.839295,0.00969,-0.54359,-3.978115,-0.82344,0.09928, + 0.839295,0.00969,-0.54359,-3.978115,-0.82344,0.09928, + -0.369174,0.174156,-0.912897,-4.070739,-0.947648,0.110554, + -0.516127,0.008586,-0.856469,-4.227645,-1.227895,0.069894, + 0.839295,0.00969,-0.54359,-3.978115,-0.82344,0.09928, + -0.516127,0.008586,-0.856469,-4.227645,-1.227895,0.069894, + 0.874434,0.048946,-0.48267,-4.029726,-1.043238,0.136305, + 0.874434,0.048946,-0.48267,-4.029726,-1.043238,0.136305, + -0.516127,0.008586,-0.856469,-4.227645,-1.227895,0.069894, + -0.822516,0.195417,-0.534116,-4.229164,-1.473093,0.11156, + 0.874434,0.048946,-0.48267,-4.029726,-1.043238,0.136305, + -0.822516,0.195417,-0.534116,-4.229164,-1.473093,0.11156, + 0.432653,0.056559,-0.899785,-4.129295,-1.228786,0.120745, + 0.432653,0.056559,-0.899785,-4.129295,-1.228786,0.120745, + -0.822516,0.195417,-0.534116,-4.229164,-1.473093,0.11156, + -0.874954,0.011842,-0.484061,-4.309744,-1.743848,0.150329, + 0.432653,0.056559,-0.899785,-4.129295,-1.228786,0.120745, + -0.874954,0.011842,-0.484061,-4.309744,-1.743848,0.150329, + 0.517516,0.032105,-0.855071,-4.184154,-1.59808,0.151191, + 0.517516,0.032105,-0.855071,-4.184154,-1.59808,0.151191, + -0.874954,0.011842,-0.484061,-4.309744,-1.743848,0.150329, + 0.924466,0.048977,0.378105,-4.405365,-1.921443,0.192978, + 0.517516,0.032105,-0.855071,-4.184154,-1.59808,0.151191, + 0.924466,0.048977,0.378105,-4.405365,-1.921443,0.192978, + 0.002983,0.098874,-0.995096,-4.297769,-1.889903,0.177707, + 0.001234,0.013557,-0.999907,-3.932489,-0.556566,0.037354, + 0.728068,-0.191899,-0.658097,-3.975337,-0.554961,-0.014407, + 0.313565,-0.18353,-0.931662,-4.112449,-0.875765,0.016326, + 0.001234,0.013557,-0.999907,-3.932489,-0.556566,0.037354, + 0.313565,-0.18353,-0.931662,-4.112449,-0.875765,0.016326, + -0.369174,0.174156,-0.912897,-4.070739,-0.947648,0.110554, + -0.369174,0.174156,-0.912897,-4.070739,-0.947648,0.110554, + 0.313565,-0.18353,-0.931662,-4.112449,-0.875765,0.016326, + 0.537835,-0.193789,-0.820475,-4.233834,-1.166542,0.022074, + -0.369174,0.174156,-0.912897,-4.070739,-0.947648,0.110554, + 0.537835,-0.193789,-0.820475,-4.233834,-1.166542,0.022074, + -0.516127,0.008586,-0.856469,-4.227645,-1.227895,0.069894, + -0.516127,0.008586,-0.856469,-4.227645,-1.227895,0.069894, + 0.537835,-0.193789,-0.820475,-4.233834,-1.166542,0.022074, + 0.908243,-0.229695,0.349765,-4.333831,-1.548255,0.056938, + -0.516127,0.008586,-0.856469,-4.227645,-1.227895,0.069894, + 0.908243,-0.229695,0.349765,-4.333831,-1.548255,0.056938, + -0.822516,0.195417,-0.534116,-4.229164,-1.473093,0.11156, + -0.822516,0.195417,-0.534116,-4.229164,-1.473093,0.11156, + 0.908243,-0.229695,0.349765,-4.333831,-1.548255,0.056938, + 0.701057,-0.21056,0.68131,-4.424122,-1.831742,0.130839, + -0.822516,0.195417,-0.534116,-4.229164,-1.473093,0.11156, + 0.701057,-0.21056,0.68131,-4.424122,-1.831742,0.130839, + -0.874954,0.011842,-0.484061,-4.309744,-1.743848,0.150329, + -0.874954,0.011842,-0.484061,-4.309744,-1.743848,0.150329, + 0.701057,-0.21056,0.68131,-4.424122,-1.831742,0.130839, + 0.129519,-0.132707,0.982656,-4.445835,-2.015127,0.189702, + -0.874954,0.011842,-0.484061,-4.309744,-1.743848,0.150329, + 0.129519,-0.132707,0.982656,-4.445835,-2.015127,0.189702, + 0.924466,0.048977,0.378105,-4.405365,-1.921443,0.192978, + 0.728068,-0.191899,-0.658097,-3.975337,-0.554961,-0.014407, + -0.276108,-0.088023,0.957087,-3.921874,-0.538502,-0.145307, + -0.409041,-0.077841,0.90919,-4.042715,-0.87671,-0.168968, + 0.728068,-0.191899,-0.658097,-3.975337,-0.554961,-0.014407, + -0.409041,-0.077841,0.90919,-4.042715,-0.87671,-0.168968, + 0.313565,-0.18353,-0.931662,-4.112449,-0.875765,0.016326, + 0.313565,-0.18353,-0.931662,-4.112449,-0.875765,0.016326, + -0.409041,-0.077841,0.90919,-4.042715,-0.87671,-0.168968, + 0.50178,0.000639,-0.864995,-4.216296,-1.160854,-0.104034, + 0.313565,-0.18353,-0.931662,-4.112449,-0.875765,0.016326, + 0.50178,0.000639,-0.864995,-4.216296,-1.160854,-0.104034, + 0.537835,-0.193789,-0.820475,-4.233834,-1.166542,0.022074, + 0.537835,-0.193789,-0.820475,-4.233834,-1.166542,0.022074, + 0.50178,0.000639,-0.864995,-4.216296,-1.160854,-0.104034, + 0.300485,0.019099,-0.953595,-4.252683,-1.437854,-0.14562, + 0.537835,-0.193789,-0.820475,-4.233834,-1.166542,0.022074, + 0.300485,0.019099,-0.953595,-4.252683,-1.437854,-0.14562, + 0.908243,-0.229695,0.349765,-4.333831,-1.548255,0.056938, + 0.908243,-0.229695,0.349765,-4.333831,-1.548255,0.056938, + 0.300485,0.019099,-0.953595,-4.252683,-1.437854,-0.14562, + 0.678632,-0.017853,-0.734261,-4.331331,-1.69259,-0.043593, + 0.908243,-0.229695,0.349765,-4.333831,-1.548255,0.056938, + 0.678632,-0.017853,-0.734261,-4.331331,-1.69259,-0.043593, + 0.701057,-0.21056,0.68131,-4.424122,-1.831742,0.130839, + 0.701057,-0.21056,0.68131,-4.424122,-1.831742,0.130839, + 0.678632,-0.017853,-0.734261,-4.331331,-1.69259,-0.043593, + 0.687126,-0.68509,0.241888,-4.387148,-1.967814,0.045602, + 0.701057,-0.21056,0.68131,-4.424122,-1.831742,0.130839, + 0.687126,-0.68509,0.241888,-4.387148,-1.967814,0.045602, + 0.129519,-0.132707,0.982656,-4.445835,-2.015127,0.189702, + -0.276108,-0.088023,0.957087,-3.921874,-0.538502,-0.145307, + 0.260319,-0.908993,-0.325523,-3.910546,-0.601719,-0.163159, + -0.148191,-0.901516,-0.40658,-3.988138,-0.962789,-0.223649, + -0.276108,-0.088023,0.957087,-3.921874,-0.538502,-0.145307, + -0.148191,-0.901516,-0.40658,-3.988138,-0.962789,-0.223649, + -0.409041,-0.077841,0.90919,-4.042715,-0.87671,-0.168968, + -0.409041,-0.077841,0.90919,-4.042715,-0.87671,-0.168968, + -0.148191,-0.901516,-0.40658,-3.988138,-0.962789,-0.223649, + -0.443612,-0.876487,-0.187028,-4.111927,-1.333141,-0.26716, + -0.409041,-0.077841,0.90919,-4.042715,-0.87671,-0.168968, + -0.443612,-0.876487,-0.187028,-4.111927,-1.333141,-0.26716, + 0.50178,0.000639,-0.864995,-4.216296,-1.160854,-0.104034, + 0.50178,0.000639,-0.864995,-4.216296,-1.160854,-0.104034, + -0.443612,-0.876487,-0.187028,-4.111927,-1.333141,-0.26716, + -0.508388,-0.837291,0.20121,-4.201904,-1.668554,-0.214859, + 0.50178,0.000639,-0.864995,-4.216296,-1.160854,-0.104034, + -0.508388,-0.837291,0.20121,-4.201904,-1.668554,-0.214859, + 0.300485,0.019099,-0.953595,-4.252683,-1.437854,-0.14562, + 0.300485,0.019099,-0.953595,-4.252683,-1.437854,-0.14562, + -0.508388,-0.837291,0.20121,-4.201904,-1.668554,-0.214859, + -0.409829,-0.525605,0.745506,-4.273069,-1.798884,-0.099878, + 0.300485,0.019099,-0.953595,-4.252683,-1.437854,-0.14562, + -0.409829,-0.525605,0.745506,-4.273069,-1.798884,-0.099878, + 0.678632,-0.017853,-0.734261,-4.331331,-1.69259,-0.043593, + 0.678632,-0.017853,-0.734261,-4.331331,-1.69259,-0.043593, + -0.409829,-0.525605,0.745506,-4.273069,-1.798884,-0.099878, + -0.227573,-0.361148,0.904313,-4.351543,-1.947675,0.02502, + 0.678632,-0.017853,-0.734261,-4.331331,-1.69259,-0.043593, + -0.227573,-0.361148,0.904313,-4.351543,-1.947675,0.02502, + 0.687126,-0.68509,0.241888,-4.387148,-1.967814,0.045602, + 0.260319,-0.908993,-0.325523,-3.910546,-0.601719,-0.163159, + 0.10009,-0.380026,0.919545,-3.873622,-0.759035,-0.197169, + 0.547733,-0.470267,0.691981,-3.917882,-1.082831,-0.289171, + 0.260319,-0.908993,-0.325523,-3.910546,-0.601719,-0.163159, + 0.547733,-0.470267,0.691981,-3.917882,-1.082831,-0.289171, + -0.148191,-0.901516,-0.40658,-3.988138,-0.962789,-0.223649, + -0.148191,-0.901516,-0.40658,-3.988138,-0.962789,-0.223649, + 0.547733,-0.470267,0.691981,-3.917882,-1.082831,-0.289171, + -0.071182,-0.950841,0.301389,-4.001496,-1.375703,-0.285641, + -0.148191,-0.901516,-0.40658,-3.988138,-0.962789,-0.223649, + -0.071182,-0.950841,0.301389,-4.001496,-1.375703,-0.285641, + -0.443612,-0.876487,-0.187028,-4.111927,-1.333141,-0.26716, + -0.443612,-0.876487,-0.187028,-4.111927,-1.333141,-0.26716, + -0.071182,-0.950841,0.301389,-4.001496,-1.375703,-0.285641, + 0.216747,0.039317,0.975436,-4.073086,-1.649491,-0.238382, + -0.443612,-0.876487,-0.187028,-4.111927,-1.333141,-0.26716, + 0.216747,0.039317,0.975436,-4.073086,-1.649491,-0.238382, + -0.508388,-0.837291,0.20121,-4.201904,-1.668554,-0.214859, + -0.508388,-0.837291,0.20121,-4.201904,-1.668554,-0.214859, + 0.216747,0.039317,0.975436,-4.073086,-1.649491,-0.238382, + 0.555948,0.246866,0.793712,-4.175757,-1.808223,-0.140659, + -0.508388,-0.837291,0.20121,-4.201904,-1.668554,-0.214859, + 0.555948,0.246866,0.793712,-4.175757,-1.808223,-0.140659, + -0.409829,-0.525605,0.745506,-4.273069,-1.798884,-0.099878, + -0.409829,-0.525605,0.745506,-4.273069,-1.798884,-0.099878, + 0.555948,0.246866,0.793712,-4.175757,-1.808223,-0.140659, + 0.768311,0.202351,0.60725,-4.321269,-1.963488,0.025072, + -0.409829,-0.525605,0.745506,-4.273069,-1.798884,-0.099878, + 0.768311,0.202351,0.60725,-4.321269,-1.963488,0.025072, + -0.227573,-0.361148,0.904313,-4.351543,-1.947675,0.02502, + 0.10009,-0.380026,0.919545,-3.873622,-0.759035,-0.197169, + 0.833232,0.046885,0.550932,-3.742608,-0.729374,-0.149361, + 0.547733,-0.470267,0.691981,-3.917882,-1.082831,-0.289171, + 0.833232,0.046885,0.550932,-3.742608,-0.729374,-0.149361, + 0.587809,-0.328909,0.739121,-3.777709,-1.051411,-0.240495, + 0.547733,-0.470267,0.691981,-3.917882,-1.082831,-0.289171, + 0.547733,-0.470267,0.691981,-3.917882,-1.082831,-0.289171, + 0.587809,-0.328909,0.739121,-3.777709,-1.051411,-0.240495, + -0.071182,-0.950841,0.301389,-4.001496,-1.375703,-0.285641, + 0.587809,-0.328909,0.739121,-3.777709,-1.051411,-0.240495, + 0.213242,-0.278117,0.936578,-3.82037,-1.239135,-0.269807, + -0.071182,-0.950841,0.301389,-4.001496,-1.375703,-0.285641, + 0.213242,-0.278117,0.936578,-3.82037,-1.239135,-0.269807, + 0.794828,0.083383,0.601079,-4.000019,-1.567512,-0.27535, + -0.071182,-0.950841,0.301389,-4.001496,-1.375703,-0.285641, + -0.071182,-0.950841,0.301389,-4.001496,-1.375703,-0.285641, + 0.794828,0.083383,0.601079,-4.000019,-1.567512,-0.27535, + 0.216747,0.039317,0.975436,-4.073086,-1.649491,-0.238382, + 0.794828,0.083383,0.601079,-4.000019,-1.567512,-0.27535, + 0.873201,-0.045461,0.485235,-3.977657,-1.750845,-0.184909, + 0.216747,0.039317,0.975436,-4.073086,-1.649491,-0.238382, + 0.216747,0.039317,0.975436,-4.073086,-1.649491,-0.238382, + 0.873201,-0.045461,0.485235,-3.977657,-1.750845,-0.184909, + 0.555948,0.246866,0.793712,-4.175757,-1.808223,-0.140659, + 0.873201,-0.045461,0.485235,-3.977657,-1.750845,-0.184909, + 0.829377,-0.173626,0.531026,-4.075028,-1.904403,-0.041324, + 0.555948,0.246866,0.793712,-4.175757,-1.808223,-0.140659, + 0.555948,0.246866,0.793712,-4.175757,-1.808223,-0.140659, + 0.829377,-0.173626,0.531026,-4.075028,-1.904403,-0.041324, + 0.768311,0.202351,0.60725,-4.321269,-1.963488,0.025072, + 0.829377,-0.173626,0.531026,-4.075028,-1.904403,-0.041324, + 0.506864,-0.193038,0.840134,-4.192486,-1.953852,0.017313, + 0.768311,0.202351,0.60725,-4.321269,-1.963488,0.025072, + 0.274422,-0.24433,0.930051,-3.65524,-0.194907,0.019209, + 0.560378,0.257624,0.787151,-3.695565,-0.19362,0.051497, + 0.00197,-0.021649,0.999764,-3.740631,-0.558176,0.085478, + 0.274422,-0.24433,0.930051,-3.65524,-0.194907,0.019209, + 0.00197,-0.021649,0.999764,-3.740631,-0.558176,0.085478, + -0.54555,-0.056478,0.836173,-3.67645,-0.551317,0.077574, + 0.546619,0.025488,0.836993,-3.805688,-0.190106,0.051472, + 0.728068,-0.191899,-0.658097,-3.975337,-0.554961,-0.014407, + 0.001234,0.013557,-0.999907,-3.932489,-0.556566,0.037354, + 0.546619,0.025488,0.836993,-3.805688,-0.190106,0.051472, + 0.001234,0.013557,-0.999907,-3.932489,-0.556566,0.037354, + 0.999006,0.044565,0.000415,-3.896204,-0.629183,0.077883, + 0.546619,0.025488,0.836993,-3.805688,-0.190106,0.051472, + 0.999006,0.044565,0.000415,-3.896204,-0.629183,0.077883, + 0.875325,0.013439,0.483348,-3.818598,-0.52269,0.055572, + 0.711192,0.127662,0.69131,-3.75063,-0.191863,0.063305, + 0.546619,0.025488,0.836993,-3.805688,-0.190106,0.051472, + 0.875325,0.013439,0.483348,-3.818598,-0.52269,0.055572, + 0.711192,0.127662,0.69131,-3.75063,-0.191863,0.063305, + 0.875325,0.013439,0.483348,-3.818598,-0.52269,0.055572, + 0.518386,-0.029316,0.854644,-3.778908,-0.541975,0.064258, + 0.560378,0.257624,0.787151,-3.695565,-0.19362,0.051497, + 0.518386,-0.029316,0.854644,-3.778908,-0.541975,0.064258, + 0.00197,-0.021649,0.999764,-3.740631,-0.558176,0.085478, + 0.238843,0.101951,0.965691,-3.84599,-0.18882,0.019164, + 0.166377,-0.157108,0.973466,-3.86074,-0.188349,-0.024962, + 0.728068,-0.191899,-0.658097,-3.975337,-0.554961,-0.014407, + 0.89264,0.349909,0.284178,-3.695452,-0.193624,-0.101369, + 0.833232,0.046885,0.550932,-3.742608,-0.729374,-0.149361, + 0.10009,-0.380026,0.919545,-3.873622,-0.759035,-0.197169, + 0.3526,0.621479,0.699598,-3.7505,-0.191867,-0.11323, + 0.89264,0.349909,0.284178,-3.695452,-0.193624,-0.101369, + 0.10009,-0.380026,0.919545,-3.873622,-0.759035,-0.197169, + -0.281998,-0.030938,0.958916,-3.805575,-0.190109,-0.101447, + 0.3526,0.621479,0.699598,-3.7505,-0.191867,-0.11323, + 0.10009,-0.380026,0.919545,-3.873622,-0.759035,-0.197169, + -0.281998,-0.030938,0.958916,-3.805575,-0.190109,-0.101447, + 0.10009,-0.380026,0.919545,-3.873622,-0.759035,-0.197169, + 0.260319,-0.908993,-0.325523,-3.910546,-0.601719,-0.163159, + -0.281998,-0.030938,0.958916,-3.805575,-0.190109,-0.101447, + 0.260319,-0.908993,-0.325523,-3.910546,-0.601719,-0.163159, + -0.276108,-0.088023,0.957087,-3.921874,-0.538502,-0.145307, + 0.077536,0.770695,0.632469,-3.845923,-0.188822,-0.06918, + -0.281998,-0.030938,0.958916,-3.805575,-0.190109,-0.101447, + -0.276108,-0.088023,0.957087,-3.921874,-0.538502,-0.145307, + 0.166377,-0.157108,0.973466,-3.86074,-0.188349,-0.024962, + -0.276108,-0.088023,0.957087,-3.921874,-0.538502,-0.145307, + 0.728068,-0.191899,-0.658097,-3.975337,-0.554961,-0.014407, + 0.833232,0.046885,0.550932,-3.742608,-0.729374,-0.149361, + -0.064166,-0.189382,0.979805,-3.655175,-0.194909,-0.069044, + 0.267717,-0.172975,0.947844,-3.640457,-0.195379,-0.024909, + 0.833232,0.046885,0.550932,-3.742608,-0.729374,-0.149361, + 0.89264,0.349909,0.284178,-3.695452,-0.193624,-0.101369, + -0.064166,-0.189382,0.979805,-3.655175,-0.194909,-0.069044, + 0.274422,-0.24433,0.930051,-3.65524,-0.194907,0.019209, + -0.54555,-0.056478,0.836173,-3.67645,-0.551317,0.077574, + 0.269003,0.86436,0.424875,-3.569386,-0.761644,-0.035893, + 0.269003,0.86436,0.424875,-3.569386,-0.761644,-0.035893, + 0.833232,0.046885,0.550932,-3.742608,-0.729374,-0.149361, + 0.267717,-0.172975,0.947844,-3.640457,-0.195379,-0.024909, + -0.54555,-0.056478,0.836173,-3.67645,-0.551317,0.077574, + -0.530021,0.13773,0.836724,-3.697889,-0.951955,0.098793, + -0.429713,0.351913,0.831567,-3.666536,-1.140372,0.078261, + 0.213242,-0.278117,0.936578,-3.82037,-1.239135,-0.269807, + 0.587809,-0.328909,0.739121,-3.777709,-1.051411,-0.240495, + 0.000909,0.669011,0.743252,-3.581963,-1.413947,-0.104371, + 0.269003,0.86436,0.424875,-3.569386,-0.761644,-0.035893, + -0.54555,-0.056478,0.836173,-3.67645,-0.551317,0.077574, + -0.429713,0.351913,0.831567,-3.666536,-1.140372,0.078261, + 0.269003,0.86436,0.424875,-3.569386,-0.761644,-0.035893, + -0.429713,0.351913,0.831567,-3.666536,-1.140372,0.078261, + -0.24021,0.502412,0.830591,-3.639696,-1.242349,0.05719, + 0.269003,0.86436,0.424875,-3.569386,-0.761644,-0.035893, + -0.24021,0.502412,0.830591,-3.639696,-1.242349,0.05719, + 0.000909,0.669011,0.743252,-3.581963,-1.413947,-0.104371, + 0.833232,0.046885,0.550932,-3.742608,-0.729374,-0.149361, + 0.269003,0.86436,0.424875,-3.569386,-0.761644,-0.035893, + 0.000909,0.669011,0.743252,-3.581963,-1.413947,-0.104371, + 0.587809,-0.328909,0.739121,-3.777709,-1.051411,-0.240495, + 0.833232,0.046885,0.550932,-3.742608,-0.729374,-0.149361, + 0.000909,0.669011,0.743252,-3.581963,-1.413947,-0.104371, + 0.873201,-0.045461,0.485235,-3.977657,-1.750845,-0.184909, + 0.231733,0.017467,0.972623,-3.890388,-1.750102,0.017612, + 0.829377,-0.173626,0.531026,-4.075028,-1.904403,-0.041324, + 0.873201,-0.045461,0.485235,-3.977657,-1.750845,-0.184909, + 0.794828,0.083383,0.601079,-4.000019,-1.567512,-0.27535, + 0.213242,-0.278117,0.936578,-3.82037,-1.239135,-0.269807, + 0.213242,-0.278117,0.936578,-3.82037,-1.239135,-0.269807, + 0.000909,0.669011,0.743252,-3.581963,-1.413947,-0.104371, + -0.041225,-0.030655,0.99868,-3.683069,-1.591975,-0.115233, + 0.213242,-0.278117,0.936578,-3.82037,-1.239135,-0.269807, + -0.041225,-0.030655,0.99868,-3.683069,-1.591975,-0.115233, + 0.002322,-0.058071,0.99831,-3.828485,-1.786559,-0.114095, + 0.213242,-0.278117,0.936578,-3.82037,-1.239135,-0.269807, + 0.002322,-0.058071,0.99831,-3.828485,-1.786559,-0.114095, + 0.231733,0.017467,0.972623,-3.890388,-1.750102,0.017612, + 0.873201,-0.045461,0.485235,-3.977657,-1.750845,-0.184909, + 0.213242,-0.278117,0.936578,-3.82037,-1.239135,-0.269807, + 0.231733,0.017467,0.972623,-3.890388,-1.750102,0.017612, + 0.231733,0.017467,0.972623,-3.890388,-1.750102,0.017612, + 0.791625,0.052579,0.608741,-4.107191,-1.83652,0.120149, + 0.829377,-0.173626,0.531026,-4.075028,-1.904403,-0.041324, + 0.791625,0.052579,0.608741,-4.107191,-1.83652,0.120149, + 0.981696,0.042552,-0.185638,-4.207566,-1.922824,0.155104, + 0.829377,-0.173626,0.531026,-4.075028,-1.904403,-0.041324, + 0.924466,0.048977,0.378105,-4.405365,-1.921443,0.192978, + 0.687126,-0.68509,0.241888,-4.387148,-1.967814,0.045602, + 0.002983,0.098874,-0.995096,-4.297769,-1.889903,0.177707, + 0.506864,-0.193038,0.840134,-4.192486,-1.953852,0.017313, + 0.829377,-0.173626,0.531026,-4.075028,-1.904403,-0.041324, + 0.981696,0.042552,-0.185638,-4.207566,-1.922824,0.155104, + 0.506864,-0.193038,0.840134,-4.192486,-1.953852,0.017313, + 0.981696,0.042552,-0.185638,-4.207566,-1.922824,0.155104, + 0.002983,0.098874,-0.995096,-4.297769,-1.889903,0.177707, + 0.768311,0.202351,0.60725,-4.321269,-1.963488,0.025072, + 0.506864,-0.193038,0.840134,-4.192486,-1.953852,0.017313, + 0.002983,0.098874,-0.995096,-4.297769,-1.889903,0.177707, + -0.227573,-0.361148,0.904313,-4.351543,-1.947675,0.02502, + 0.768311,0.202351,0.60725,-4.321269,-1.963488,0.025072, + 0.002983,0.098874,-0.995096,-4.297769,-1.889903,0.177707, + 0.687126,-0.68509,0.241888,-4.387148,-1.967814,0.045602, + -0.227573,-0.361148,0.904313,-4.351543,-1.947675,0.02502, + 0.002983,0.098874,-0.995096,-4.297769,-1.889903,0.177707, + 0.924466,0.048977,0.378105,-4.405365,-1.921443,0.192978, + 0.129519,-0.132707,0.982656,-4.445835,-2.015127,0.189702, + 0.687126,-0.68509,0.241888,-4.387148,-1.967814,0.045602, + 0.560378,0.257624,0.787151,-3.695565,-0.19362,0.051497, + 0.711192,0.127662,0.69131,-3.75063,-0.191863,0.063305, + 0.518386,-0.029316,0.854644,-3.778908,-0.541975,0.064258, + 0.546619,0.025488,0.836993,-3.805688,-0.190106,0.051472, + 0.238843,0.101951,0.965691,-3.84599,-0.18882,0.019164, + 0.728068,-0.191899,-0.658097,-3.975337,-0.554961,-0.014407, + 0.166377,-0.157108,0.973466,-3.86074,-0.188349,-0.024962, + 0.077536,0.770695,0.632469,-3.845923,-0.188822,-0.06918, + -0.276108,-0.088023,0.957087,-3.921874,-0.538502,-0.145307, + 0.269003,0.86436,0.424875,-3.569386,-0.761644,-0.035893, + 0.267717,-0.172975,0.947844,-3.640457,-0.195379,-0.024909, + 0.274422,-0.24433,0.930051,-3.65524,-0.194907,0.019209 +}; +static const struct gllist frame={GL_N3F_V3F,GL_TRIANGLES,459,data,NULL}; +const struct gllist *cow_tail=&frame; diff --git a/hacks/glx/cow_udder.c b/hacks/glx/cow_udder.c new file mode 100644 index 00000000..46df87c4 --- /dev/null +++ b/hacks/glx/cow_udder.c @@ -0,0 +1,1520 @@ +#include "gllist.h" +static const float data[]={ + 0.058723,-0.195869,-0.97887,-2.033406,-0.91003,-0.96422, + -0.977902,-0.171036,-0.12023,-2.119856,-1.1288,-0.97096, + 0.07657,0.16758,-0.982881,-2.306662,-1.116976,-0.961238, + -0.977902,-0.171036,-0.12023,-2.119856,-1.1288,-0.97096, + 0.058723,-0.195869,-0.97887,-2.033406,-0.91003,-0.96422, + -0.964119,-0.189683,-0.18573,-2.031698,-1.097344,-0.966701, + -0.964119,-0.189683,-0.18573,-2.031698,-1.097344,-0.966701, + 0.058723,-0.195869,-0.97887,-2.033406,-0.91003,-0.96422, + -0.30296,-0.137183,-0.943078,-1.782298,-1.020581,-0.943381, + -0.955382,-0.23808,-0.174826,-2.462835,-1.3055,-0.966395, + 0.07657,0.16758,-0.982881,-2.306662,-1.116976,-0.961238, + -0.843742,-0.096326,-0.528036,-2.337617,-1.334842,-0.966761, + -0.843742,-0.096326,-0.528036,-2.337617,-1.334842,-0.966761, + 0.07657,0.16758,-0.982881,-2.306662,-1.116976,-0.961238, + -0.977902,-0.171036,-0.12023,-2.119856,-1.1288,-0.97096, + -0.843742,-0.096326,-0.528036,-2.337617,-1.334842,-0.966761, + -0.977902,-0.171036,-0.12023,-2.119856,-1.1288,-0.97096, + 0.028952,-0.016247,-0.999449,-2.161843,-1.325837,-0.957465, + 0.028952,-0.016247,-0.999449,-2.161843,-1.325837,-0.957465, + -0.977902,-0.171036,-0.12023,-2.119856,-1.1288,-0.97096, + -0.964119,-0.189683,-0.18573,-2.031698,-1.097344,-0.966701, + 0.028952,-0.016247,-0.999449,-2.161843,-1.325837,-0.957465, + -0.964119,-0.189683,-0.18573,-2.031698,-1.097344,-0.966701, + 0.093953,-0.049433,-0.994349,-2.042059,-1.312976,-0.940911, + 0.093953,-0.049433,-0.994349,-2.042059,-1.312976,-0.940911, + -0.964119,-0.189683,-0.18573,-2.031698,-1.097344,-0.966701, + -0.30296,-0.137183,-0.943078,-1.782298,-1.020581,-0.943381, + 0.093953,-0.049433,-0.994349,-2.042059,-1.312976,-0.940911, + -0.30296,-0.137183,-0.943078,-1.782298,-1.020581,-0.943381, + 0.335613,-0.388493,-0.858159,-1.776785,-1.275107,-0.914703, + 0.335613,-0.388493,-0.858159,-1.776785,-1.275107,-0.914703, + -0.30296,-0.137183,-0.943078,-1.782298,-1.020581,-0.943381, + -0.004413,-0.170526,-0.985343,-1.709172,-1.283232,-0.897427, + -0.004413,-0.170526,-0.985343,-1.709172,-1.283232,-0.897427, + -0.30296,-0.137183,-0.943078,-1.782298,-1.020581,-0.943381, + 0.095733,-0.224552,-0.969748,-1.456655,-1.295527,-0.89424, + 0.137764,-0.289893,-0.947092,-2.591357,-1.510845,-0.88547, + -0.955382,-0.23808,-0.174826,-2.462835,-1.3055,-0.966395, + -0.843742,-0.096326,-0.528036,-2.337617,-1.334842,-0.966761, + 0.137764,-0.289893,-0.947092,-2.591357,-1.510845,-0.88547, + -0.843742,-0.096326,-0.528036,-2.337617,-1.334842,-0.966761, + 0.137206,-0.207537,-0.968557,-2.417777,-1.553136,-0.887222, + 0.137206,-0.207537,-0.968557,-2.417777,-1.553136,-0.887222, + -0.843742,-0.096326,-0.528036,-2.337617,-1.334842,-0.966761, + 0.028952,-0.016247,-0.999449,-2.161843,-1.325837,-0.957465, + 0.137206,-0.207537,-0.968557,-2.417777,-1.553136,-0.887222, + 0.028952,-0.016247,-0.999449,-2.161843,-1.325837,-0.957465, + 0.094371,-0.230057,-0.968591,-2.223917,-1.541268,-0.87926, + 0.094371,-0.230057,-0.968591,-2.223917,-1.541268,-0.87926, + 0.028952,-0.016247,-0.999449,-2.161843,-1.325837,-0.957465, + 0.093953,-0.049433,-0.994349,-2.042059,-1.312976,-0.940911, + 0.094371,-0.230057,-0.968591,-2.223917,-1.541268,-0.87926, + 0.093953,-0.049433,-0.994349,-2.042059,-1.312976,-0.940911, + -0.201818,-0.568242,-0.797728,-2.049879,-1.562369,-0.829319, + -0.201818,-0.568242,-0.797728,-2.049879,-1.562369,-0.829319, + 0.093953,-0.049433,-0.994349,-2.042059,-1.312976,-0.940911, + 0.357021,-0.590654,-0.723646,-1.777628,-1.473076,-0.845827, + -0.201818,-0.568242,-0.797728,-2.049879,-1.562369,-0.829319, + 0.357021,-0.590654,-0.723646,-1.777628,-1.473076,-0.845827, + 0.008663,-0.516082,-0.856495,-1.778934,-1.550199,-0.776454, + 0.357021,-0.590654,-0.723646,-1.777628,-1.473076,-0.845827, + 0.093953,-0.049433,-0.994349,-2.042059,-1.312976,-0.940911, + 0.335613,-0.388493,-0.858159,-1.776785,-1.275107,-0.914703, + 0.357021,-0.590654,-0.723646,-1.777628,-1.473076,-0.845827, + 0.335613,-0.388493,-0.858159,-1.776785,-1.275107,-0.914703, + -0.004413,-0.170526,-0.985343,-1.709172,-1.283232,-0.897427, + 0.357021,-0.590654,-0.723646,-1.777628,-1.473076,-0.845827, + -0.004413,-0.170526,-0.985343,-1.709172,-1.283232,-0.897427, + 0.106237,-0.558927,-0.822383,-1.686329,-1.414405,-0.869373, + 0.106237,-0.558927,-0.822383,-1.686329,-1.414405,-0.869373, + -0.004413,-0.170526,-0.985343,-1.709172,-1.283232,-0.897427, + 0.095733,-0.224552,-0.969748,-1.456655,-1.295527,-0.89424, + 0.106237,-0.558927,-0.822383,-1.686329,-1.414405,-0.869373, + 0.095733,-0.224552,-0.969748,-1.456655,-1.295527,-0.89424, + 0.155794,-0.590112,-0.792146,-1.592146,-1.408592,-0.838483, + 0.155794,-0.590112,-0.792146,-1.592146,-1.408592,-0.838483, + 0.095733,-0.224552,-0.969748,-1.456655,-1.295527,-0.89424, + 0.08565,-0.422547,-0.902285,-1.552229,-1.555077,-0.735708, + 0.08565,-0.422547,-0.902285,-1.552229,-1.555077,-0.735708, + 0.161064,-0.731195,-0.662882,-1.659758,-1.544361,-0.788181, + 0.155794,-0.590112,-0.792146,-1.592146,-1.408592,-0.838483, + 0.155794,-0.590112,-0.792146,-1.592146,-1.408592,-0.838483, + 0.161064,-0.731195,-0.662882,-1.659758,-1.544361,-0.788181, + 0.106237,-0.558927,-0.822383,-1.686329,-1.414405,-0.869373, + 0.106237,-0.558927,-0.822383,-1.686329,-1.414405,-0.869373, + 0.161064,-0.731195,-0.662882,-1.659758,-1.544361,-0.788181, + 0.008663,-0.516082,-0.856495,-1.778934,-1.550199,-0.776454, + 0.106237,-0.558927,-0.822383,-1.686329,-1.414405,-0.869373, + 0.008663,-0.516082,-0.856495,-1.778934,-1.550199,-0.776454, + 0.357021,-0.590654,-0.723646,-1.777628,-1.473076,-0.845827, + 0.08565,-0.422547,-0.902285,-1.552229,-1.555077,-0.735708, + 0.095733,-0.224552,-0.969748,-1.456655,-1.295527,-0.89424, + -0.422758,-0.178302,-0.888529,-1.366873,-1.340211,-0.907567, + 0.08565,-0.422547,-0.902285,-1.552229,-1.555077,-0.735708, + -0.422758,-0.178302,-0.888529,-1.366873,-1.340211,-0.907567, + -0.504483,-0.438591,-0.743731,-1.376186,-1.661988,-0.718954, + -0.504483,-0.438591,-0.743731,-1.376186,-1.661988,-0.718954, + -0.422758,-0.178302,-0.888529,-1.366873,-1.340211,-0.907567, + 0.121987,-0.426326,-0.896306,-1.198513,-1.456102,-0.885435, + -0.504483,-0.438591,-0.743731,-1.376186,-1.661988,-0.718954, + 0.121987,-0.426326,-0.896306,-1.198513,-1.456102,-0.885435, + 0.215155,-0.464575,-0.858999,-1.200688,-1.577575,-0.799188, + 0.215155,-0.464575,-0.858999,-1.200688,-1.577575,-0.799188, + 0.121987,-0.426326,-0.896306,-1.198513,-1.456102,-0.885435, + -0.218261,-0.26262,-0.93989,-0.953236,-1.545941,-0.89918, + -0.094238,-0.851252,-0.516225,-1.397474,-1.693815,-0.570541, + 0.152347,-0.821467,-0.549529,-1.480217,-1.6566,-0.606638, + -0.504483,-0.438591,-0.743731,-1.376186,-1.661988,-0.718954, + -0.504483,-0.438591,-0.743731,-1.376186,-1.661988,-0.718954, + 0.152347,-0.821467,-0.549529,-1.480217,-1.6566,-0.606638, + 0.08565,-0.422547,-0.902285,-1.552229,-1.555077,-0.735708, + 0.08565,-0.422547,-0.902285,-1.552229,-1.555077,-0.735708, + 0.152347,-0.821467,-0.549529,-1.480217,-1.6566,-0.606638, + -0.279342,-0.940234,-0.19475,-1.601625,-1.593321,-0.605607, + -0.279342,-0.940234,-0.19475,-1.601625,-1.593321,-0.605607, + 0.152347,-0.821467,-0.549529,-1.480217,-1.6566,-0.606638, + -0.198045,-0.959194,-0.201804,-1.519339,-1.653776,-0.501741, + -0.198045,-0.959194,-0.201804,-1.519339,-1.653776,-0.501741, + 0.152347,-0.821467,-0.549529,-1.480217,-1.6566,-0.606638, + -0.094238,-0.851252,-0.516225,-1.397474,-1.693815,-0.570541, + -0.198045,-0.959194,-0.201804,-1.519339,-1.653776,-0.501741, + -0.094238,-0.851252,-0.516225,-1.397474,-1.693815,-0.570541, + -0.171647,-0.971664,-0.162499,-1.406693,-1.697325,-0.450399, + -0.279342,-0.940234,-0.19475,-1.601625,-1.593321,-0.605607, + -0.198045,-0.959194,-0.201804,-1.519339,-1.653776,-0.501741, + -0.403877,-0.879274,-0.252509,-1.576196,-1.696317,-0.358146, + -0.403877,-0.879274,-0.252509,-1.576196,-1.696317,-0.358146, + -0.198045,-0.959194,-0.201804,-1.519339,-1.653776,-0.501741, + -0.171647,-0.971664,-0.162499,-1.406693,-1.697325,-0.450399, + -0.403877,-0.879274,-0.252509,-1.576196,-1.696317,-0.358146, + -0.171647,-0.971664,-0.162499,-1.406693,-1.697325,-0.450399, + -0.53858,-0.616299,-0.57455,-1.386502,-1.718441,-0.350823, + -0.53858,-0.616299,-0.57455,-1.386502,-1.718441,-0.350823, + 0.011286,0.999936,0,-1.395728,-1.723811,0, + 0.106808,0.99428,0,-1.610025,-1.711571,0, + -0.53858,-0.616299,-0.57455,-1.386502,-1.718441,-0.350823, + 0.106808,0.99428,0,-1.610025,-1.711571,0, + -0.403877,-0.879274,-0.252509,-1.576196,-1.696317,-0.358146, + -0.403877,-0.879274,-0.252509,-1.576196,-1.696317,-0.358146, + 0.106808,0.99428,0,-1.610025,-1.711571,0, + -0.160087,-0.987103,0,-1.799827,-1.753136,0, + -0.403877,-0.879274,-0.252509,-1.576196,-1.696317,-0.358146, + -0.160087,-0.987103,0,-1.799827,-1.753136,0, + -0.299215,-0.929389,-0.216116,-1.764045,-1.764987,-0.406586, + -0.299215,-0.929389,-0.216116,-1.764045,-1.764987,-0.406586, + -0.18119,-0.970212,-0.160805,-1.74779,-1.667608,-0.60634, + -0.279342,-0.940234,-0.19475,-1.601625,-1.593321,-0.605607, + -0.299215,-0.929389,-0.216116,-1.764045,-1.764987,-0.406586, + -0.279342,-0.940234,-0.19475,-1.601625,-1.593321,-0.605607, + -0.403877,-0.879274,-0.252509,-1.576196,-1.696317,-0.358146, + -0.279342,-0.940234,-0.19475,-1.601625,-1.593321,-0.605607, + -0.18119,-0.970212,-0.160805,-1.74779,-1.667608,-0.60634, + 0.008663,-0.516082,-0.856495,-1.778934,-1.550199,-0.776454, + 0.008663,-0.516082,-0.856495,-1.778934,-1.550199,-0.776454, + 0.161064,-0.731195,-0.662882,-1.659758,-1.544361,-0.788181, + -0.279342,-0.940234,-0.19475,-1.601625,-1.593321,-0.605607, + -0.279342,-0.940234,-0.19475,-1.601625,-1.593321,-0.605607, + 0.161064,-0.731195,-0.662882,-1.659758,-1.544361,-0.788181, + 0.08565,-0.422547,-0.902285,-1.552229,-1.555077,-0.735708, + 0.048753,-0.975535,-0.21437,-2.734184,-1.717948,-0.749581, + 0.137764,-0.289893,-0.947092,-2.591357,-1.510845,-0.88547, + 0.137206,-0.207537,-0.968557,-2.417777,-1.553136,-0.887222, + 0.048753,-0.975535,-0.21437,-2.734184,-1.717948,-0.749581, + 0.137206,-0.207537,-0.968557,-2.417777,-1.553136,-0.887222, + -0.177142,-0.976279,-0.124502,-2.508885,-1.719933,-0.721675, + -0.177142,-0.976279,-0.124502,-2.508885,-1.719933,-0.721675, + 0.137206,-0.207537,-0.968557,-2.417777,-1.553136,-0.887222, + 0.094371,-0.230057,-0.968591,-2.223917,-1.541268,-0.87926, + -0.177142,-0.976279,-0.124502,-2.508885,-1.719933,-0.721675, + 0.094371,-0.230057,-0.968591,-2.223917,-1.541268,-0.87926, + 0.430742,-0.887318,-0.164704,-2.267049,-1.753901,-0.662106, + 0.430742,-0.887318,-0.164704,-2.267049,-1.753901,-0.662106, + 0.094371,-0.230057,-0.968591,-2.223917,-1.541268,-0.87926, + -0.201818,-0.568242,-0.797728,-2.049879,-1.562369,-0.829319, + 0.430742,-0.887318,-0.164704,-2.267049,-1.753901,-0.662106, + -0.201818,-0.568242,-0.797728,-2.049879,-1.562369,-0.829319, + 0.35682,-0.781398,-0.511953,-2.037371,-1.73636,-0.656787, + 0.35682,-0.781398,-0.511953,-2.037371,-1.73636,-0.656787, + -0.201818,-0.568242,-0.797728,-2.049879,-1.562369,-0.829319, + 0.008663,-0.516082,-0.856495,-1.778934,-1.550199,-0.776454, + 0.35682,-0.781398,-0.511953,-2.037371,-1.73636,-0.656787, + 0.008663,-0.516082,-0.856495,-1.778934,-1.550199,-0.776454, + -0.18119,-0.970212,-0.160805,-1.74779,-1.667608,-0.60634, + -0.18119,-0.970212,-0.160805,-1.74779,-1.667608,-0.60634, + -0.299215,-0.929389,-0.216116,-1.764045,-1.764987,-0.406586, + 0.493535,-0.729115,-0.474147,-1.88316,-1.829718,-0.401567, + -0.18119,-0.970212,-0.160805,-1.74779,-1.667608,-0.60634, + 0.493535,-0.729115,-0.474147,-1.88316,-1.829718,-0.401567, + 0.04422,-0.704109,-0.708714,-1.936032,-1.829617,-0.488916, + 0.04422,-0.704109,-0.708714,-1.936032,-1.829617,-0.488916, + 0.083262,-0.787311,-0.610907,-2.027242,-1.813012,-0.555232, + 0.35682,-0.781398,-0.511953,-2.037371,-1.73636,-0.656787, + 0.04422,-0.704109,-0.708714,-1.936032,-1.829617,-0.488916, + 0.35682,-0.781398,-0.511953,-2.037371,-1.73636,-0.656787, + -0.18119,-0.970212,-0.160805,-1.74779,-1.667608,-0.60634, + 0.35682,-0.781398,-0.511953,-2.037371,-1.73636,-0.656787, + 0.083262,-0.787311,-0.610907,-2.027242,-1.813012,-0.555232, + 0.170756,-0.748007,-0.641349,-2.126375,-1.866497,-0.502895, + 0.35682,-0.781398,-0.511953,-2.037371,-1.73636,-0.656787, + 0.170756,-0.748007,-0.641349,-2.126375,-1.866497,-0.502895, + 0.430742,-0.887318,-0.164704,-2.267049,-1.753901,-0.662106, + 0.430742,-0.887318,-0.164704,-2.267049,-1.753901,-0.662106, + 0.170756,-0.748007,-0.641349,-2.126375,-1.866497,-0.502895, + 0.64791,-0.754869,0.101909,-2.176551,-1.873816,-0.445782, + 0.430742,-0.887318,-0.164704,-2.267049,-1.753901,-0.662106, + 0.64791,-0.754869,0.101909,-2.176551,-1.873816,-0.445782, + 0.381337,-0.795981,-0.470102,-2.317557,-1.8742,-0.470587, + 0.381337,-0.795981,-0.470102,-2.317557,-1.8742,-0.470587, + 0.183908,-0.773381,-0.606679,-2.446375,-1.893261,-0.49411, + 0.018755,-0.837462,-0.546174,-2.466779,-1.857679,-0.570461, + 0.381337,-0.795981,-0.470102,-2.317557,-1.8742,-0.470587, + 0.018755,-0.837462,-0.546174,-2.466779,-1.857679,-0.570461, + 0.430742,-0.887318,-0.164704,-2.267049,-1.753901,-0.662106, + 0.430742,-0.887318,-0.164704,-2.267049,-1.753901,-0.662106, + 0.018755,-0.837462,-0.546174,-2.466779,-1.857679,-0.570461, + -0.094688,-0.959937,-0.263734,-2.547737,-1.833025,-0.609321, + 0.430742,-0.887318,-0.164704,-2.267049,-1.753901,-0.662106, + -0.094688,-0.959937,-0.263734,-2.547737,-1.833025,-0.609321, + -0.177142,-0.976279,-0.124502,-2.508885,-1.719933,-0.721675, + -0.177142,-0.976279,-0.124502,-2.508885,-1.719933,-0.721675, + -0.094688,-0.959937,-0.263734,-2.547737,-1.833025,-0.609321, + 0.059023,-0.965365,-0.25414,-2.64722,-1.84401,-0.594347, + -0.177142,-0.976279,-0.124502,-2.508885,-1.719933,-0.721675, + 0.059023,-0.965365,-0.25414,-2.64722,-1.84401,-0.594347, + 0.048753,-0.975535,-0.21437,-2.734184,-1.717948,-0.749581, + 0.048753,-0.975535,-0.21437,-2.734184,-1.717948,-0.749581, + 0.059023,-0.965365,-0.25414,-2.64722,-1.84401,-0.594347, + 0.49176,-0.810764,-0.317543,-2.699966,-1.850397,-0.57007, + 0.048753,-0.975535,-0.21437,-2.734184,-1.717948,-0.749581, + 0.49176,-0.810764,-0.317543,-2.699966,-1.850397,-0.57007, + 0.43907,-0.579988,-0.686171,-2.811581,-1.79821,-0.712737, + -0.073547,-0.481419,-0.8734,-2.941731,-1.787431,-0.442574, + 0.099157,-0.476834,-0.873383,-2.709403,-1.879947,-0.508775, + -0.147229,-0.706225,-0.69251,-2.684452,-1.891207,-0.447388, + -0.073547,-0.481419,-0.8734,-2.941731,-1.787431,-0.442574, + -0.147229,-0.706225,-0.69251,-2.684452,-1.891207,-0.447388, + 0.0787,0.996898,0,-2.892162,-1.781087,0, + 0.0787,0.996898,0,-2.892162,-1.781087,0, + -0.147229,-0.706225,-0.69251,-2.684452,-1.891207,-0.447388, + 0.328486,-0.940918,0.082286,-2.614084,-1.905005,-0.404925, + 0.0787,0.996898,0,-2.892162,-1.781087,0, + 0.328486,-0.940918,0.082286,-2.614084,-1.905005,-0.404925, + 0.058013,0.998316,0,-2.656867,-1.853045,0, + 0.058013,0.998316,0,-2.656867,-1.853045,0, + 0.328486,-0.940918,0.082286,-2.614084,-1.905005,-0.404925, + -0.319475,-0.944225,-0.079844,-2.503818,-1.909806,-0.431456, + 0.058013,0.998316,0,-2.656867,-1.853045,0, + -0.319475,-0.944225,-0.079844,-2.503818,-1.909806,-0.431456, + 0.093777,0.995593,0,-2.348005,-1.869142,0, + 0.093777,0.995593,0,-2.348005,-1.869142,0, + -0.319475,-0.944225,-0.079844,-2.503818,-1.909806,-0.431456, + 0.183908,-0.773381,-0.606679,-2.446375,-1.893261,-0.49411, + 0.093777,0.995593,0,-2.348005,-1.869142,0, + 0.183908,-0.773381,-0.606679,-2.446375,-1.893261,-0.49411, + 0.381337,-0.795981,-0.470102,-2.317557,-1.8742,-0.470587, + 0.381337,-0.795981,-0.470102,-2.317557,-1.8742,-0.470587, + 0.64791,-0.754869,0.101909,-2.176551,-1.873816,-0.445782, + -0.393694,-0.919049,0.018795,-2.147113,-1.903198,-0.362462, + 0.381337,-0.795981,-0.470102,-2.317557,-1.8742,-0.470587, + -0.393694,-0.919049,0.018795,-2.147113,-1.903198,-0.362462, + 0.093777,0.995593,0,-2.348005,-1.869142,0, + 0.093777,0.995593,0,-2.348005,-1.869142,0, + -0.393694,-0.919049,0.018795,-2.147113,-1.903198,-0.362462, + -0.327707,-0.94199,0.072547,-2.062725,-1.884246,-0.307336, + 0.093777,0.995593,0,-2.348005,-1.869142,0, + -0.327707,-0.94199,0.072547,-2.062725,-1.884246,-0.307336, + 0.149455,0.988769,0,-2.092921,-1.839622,0, + 0.149455,0.988769,0,-2.092921,-1.839622,0, + -0.327707,-0.94199,0.072547,-2.062725,-1.884246,-0.307336, + -0.163041,-0.980692,0.107986,-1.946306,-1.872735,-0.344251, + 0.149455,0.988769,0,-2.092921,-1.839622,0, + -0.163041,-0.980692,0.107986,-1.946306,-1.872735,-0.344251, + -0.160087,-0.987103,0,-1.799827,-1.753136,0, + -0.160087,-0.987103,0,-1.799827,-1.753136,0, + -0.163041,-0.980692,0.107986,-1.946306,-1.872735,-0.344251, + 0.493535,-0.729115,-0.474147,-1.88316,-1.829718,-0.401567, + -0.160087,-0.987103,0,-1.799827,-1.753136,0, + 0.493535,-0.729115,-0.474147,-1.88316,-1.829718,-0.401567, + -0.299215,-0.929389,-0.216116,-1.764045,-1.764987,-0.406586, + -0.012978,-0.998326,0.056357,-3.139394,-1.687482,-0.638546, + 0.074429,-0.99521,0.063385,-3.120907,-1.707924,-0.431829, + 0.249604,-0.855993,0.452741,-3.314868,-1.599081,-0.439626, + -0.012978,-0.998326,0.056357,-3.139394,-1.687482,-0.638546, + 0.249604,-0.855993,0.452741,-3.314868,-1.599081,-0.439626, + 0.515412,-0.714946,0.472444,-3.304804,-1.582192,-0.643445, + 0.515412,-0.714946,0.472444,-3.304804,-1.582192,-0.643445, + 0.249604,-0.855993,0.452741,-3.314868,-1.599081,-0.439626, + -0.454242,-0.890878,0.000928,-3.442085,-1.48412,-0.406377, + 0.515412,-0.714946,0.472444,-3.304804,-1.582192,-0.643445, + -0.454242,-0.890878,0.000928,-3.442085,-1.48412,-0.406377, + -0.354058,-0.732075,0.581987,-3.387254,-1.486027,-0.672861, + -0.354058,-0.732075,0.581987,-3.387254,-1.486027,-0.672861, + -0.454242,-0.890878,0.000928,-3.442085,-1.48412,-0.406377, + -0.587869,-0.808404,-0.029894,-3.557869,-1.325941,-0.37803, + -0.354058,-0.732075,0.581987,-3.387254,-1.486027,-0.672861, + -0.587869,-0.808404,-0.029894,-3.557869,-1.325941,-0.37803, + -0.581301,-0.608503,0.540197,-3.53391,-1.330455,-0.568246, + -0.581301,-0.608503,0.540197,-3.53391,-1.330455,-0.568246, + -0.587869,-0.808404,-0.029894,-3.557869,-1.325941,-0.37803, + -0.736087,-0.675142,-0.048562,-3.639586,-1.140102,-0.3338, + -0.581301,-0.608503,0.540197,-3.53391,-1.330455,-0.568246, + -0.736087,-0.675142,-0.048562,-3.639586,-1.140102,-0.3338, + -0.98615,-0.150918,-0.068783,-3.631179,-1.157838,-0.50561, + -0.98615,-0.150918,-0.068783,-3.631179,-1.157838,-0.50561, + -0.736087,-0.675142,-0.048562,-3.639586,-1.140102,-0.3338, + -0.84728,-0.52968,-0.039439,-3.686518,-0.955181,-0.320349, + -0.98615,-0.150918,-0.068783,-3.631179,-1.157838,-0.50561, + -0.84728,-0.52968,-0.039439,-3.686518,-0.955181,-0.320349, + -0.815087,-0.388053,-0.430171,-3.667859,-0.964867,-0.464702, + -0.815087,-0.388053,-0.430171,-3.667859,-0.964867,-0.464702, + -0.84728,-0.52968,-0.039439,-3.686518,-0.955181,-0.320349, + -0.945906,-0.323169,-0.028687,-3.676599,-0.729578,-0.330724, + -0.815087,-0.388053,-0.430171,-3.667859,-0.964867,-0.464702, + -0.945906,-0.323169,-0.028687,-3.676599,-0.729578,-0.330724, + -0.896964,-0.287307,-0.336022,-3.665774,-0.73408,-0.446286, + -0.896964,-0.287307,-0.336022,-3.665774,-0.73408,-0.446286, + -0.945906,-0.323169,-0.028687,-3.676599,-0.729578,-0.330724, + -0.99574,-0.082547,-0.041071,-3.616627,-0.350374,-0.338492, + -0.896964,-0.287307,-0.336022,-3.665774,-0.73408,-0.446286, + -0.99574,-0.082547,-0.041071,-3.616627,-0.350374,-0.338492, + -0.950882,-0.075567,-0.300188,-3.595973,-0.346391,-0.426453, + -0.950882,-0.075567,-0.300188,-3.595973,-0.346391,-0.426453, + -0.99574,-0.082547,-0.041071,-3.616627,-0.350374,-0.338492, + -0.993498,0.089934,-0.06981,-3.570243,-0.060093,-0.344854, + -0.950882,-0.075567,-0.300188,-3.595973,-0.346391,-0.426453, + -0.993498,0.089934,-0.06981,-3.570243,-0.060093,-0.344854, + -0.951862,0.098243,-0.290356,-3.529709,-0.065998,-0.437217, + -0.951862,0.098243,-0.290356,-3.529709,-0.065998,-0.437217, + -0.993498,0.089934,-0.06981,-3.570243,-0.060093,-0.344854, + -0.9775,0.159844,-0.137638,-3.535416,0.191408,-0.338478, + -0.951862,0.098243,-0.290356,-3.529709,-0.065998,-0.437217, + -0.9775,0.159844,-0.137638,-3.535416,0.191408,-0.338478, + -0.923845,0.18432,-0.335466,-3.51684,0.149002,-0.430359, + -0.923845,0.18432,-0.335466,-3.51684,0.149002,-0.430359, + -0.9775,0.159844,-0.137638,-3.535416,0.191408,-0.338478, + -0.971344,0.144305,-0.188856,-3.536654,0.442277,-0.322, + -0.971344,0.144305,-0.188856,-3.536654,0.442277,-0.322, + -0.9775,0.159844,-0.137638,-3.535416,0.191408,-0.338478, + 0.170833,0.9853,0,-3.55232,0.219613,0, + -0.971344,0.144305,-0.188856,-3.536654,0.442277,-0.322, + 0.170833,0.9853,0,-3.55232,0.219613,0, + -0.57342,0.819261,0,-3.544507,0.467147,0, + 0.170833,0.9853,0,-3.55232,0.219613,0, + -0.9775,0.159844,-0.137638,-3.535416,0.191408,-0.338478, + -0.993498,0.089934,-0.06981,-3.570243,-0.060093,-0.344854, + 0.170833,0.9853,0,-3.55232,0.219613,0, + -0.993498,0.089934,-0.06981,-3.570243,-0.060093,-0.344854, + 0.614301,0.789071,-0.000581,-3.583763,-0.052271,0, + 0.098463,-0.995141,0,-3.637643,-0.356271,0, + -0.99574,-0.082547,-0.041071,-3.616627,-0.350374,-0.338492, + -0.945906,-0.323169,-0.028687,-3.676599,-0.729578,-0.330724, + 0.098463,-0.995141,0,-3.637643,-0.356271,0, + -0.945906,-0.323169,-0.028687,-3.676599,-0.729578,-0.330724, + 0.353735,-0.935346,0,-3.673607,-0.720796,0, + 0.353735,-0.935346,0,-3.673607,-0.720796,0, + -0.945906,-0.323169,-0.028687,-3.676599,-0.729578,-0.330724, + -0.84728,-0.52968,-0.039439,-3.686518,-0.955181,-0.320349, + 0.353735,-0.935346,0,-3.673607,-0.720796,0, + -0.84728,-0.52968,-0.039439,-3.686518,-0.955181,-0.320349, + -0.34926,-0.937026,0,-3.678793,-0.926816,0, + -0.34926,-0.937026,0,-3.678793,-0.926816,0, + -0.84728,-0.52968,-0.039439,-3.686518,-0.955181,-0.320349, + -0.736087,-0.675142,-0.048562,-3.639586,-1.140102,-0.3338, + -0.34926,-0.937026,0,-3.678793,-0.926816,0, + -0.736087,-0.675142,-0.048562,-3.639586,-1.140102,-0.3338, + -0.164,-0.98646,0,-3.650579,-1.142448,0, + -0.164,-0.98646,0,-3.650579,-1.142448,0, + -0.736087,-0.675142,-0.048562,-3.639586,-1.140102,-0.3338, + -0.587869,-0.808404,-0.029894,-3.557869,-1.325941,-0.37803, + -0.164,-0.98646,0,-3.650579,-1.142448,0, + -0.587869,-0.808404,-0.029894,-3.557869,-1.325941,-0.37803, + 0.030921,-0.999522,0,-3.522115,-1.366623,0, + 0.030921,-0.999522,0,-3.522115,-1.366623,0, + -0.587869,-0.808404,-0.029894,-3.557869,-1.325941,-0.37803, + -0.454242,-0.890878,0.000928,-3.442085,-1.48412,-0.406377, + 0.030921,-0.999522,0,-3.522115,-1.366623,0, + -0.454242,-0.890878,0.000928,-3.442085,-1.48412,-0.406377, + 0.183204,-0.983075,0,-3.417689,-1.494416,0, + 0.183204,-0.983075,0,-3.417689,-1.494416,0, + -0.454242,-0.890878,0.000928,-3.442085,-1.48412,-0.406377, + 0.249604,-0.855993,0.452741,-3.314868,-1.599081,-0.439626, + 0.183204,-0.983075,0,-3.417689,-1.494416,0, + 0.249604,-0.855993,0.452741,-3.314868,-1.599081,-0.439626, + -0.997516,0.070442,0,-3.271035,-1.609292,0, + -0.997516,0.070442,0,-3.271035,-1.609292,0, + 0.249604,-0.855993,0.452741,-3.314868,-1.599081,-0.439626, + 0.074429,-0.99521,0.063385,-3.120907,-1.707924,-0.431829, + -0.997516,0.070442,0,-3.271035,-1.609292,0, + 0.074429,-0.99521,0.063385,-3.120907,-1.707924,-0.431829, + -0.99928,-0.037933,0,-3.1103,-1.69172,0, + -0.99928,-0.037933,0,-3.1103,-1.69172,0, + 0.074429,-0.99521,0.063385,-3.120907,-1.707924,-0.431829, + -0.073547,-0.481419,-0.8734,-2.941731,-1.787431,-0.442574, + -0.99928,-0.037933,0,-3.1103,-1.69172,0, + -0.073547,-0.481419,-0.8734,-2.941731,-1.787431,-0.442574, + 0.0787,0.996898,0,-2.892162,-1.781087,0, + 0.614301,0.789071,-0.000581,-3.583763,-0.052271,0, + -0.993498,0.089934,-0.06981,-3.570243,-0.060093,-0.344854, + -0.99574,-0.082547,-0.041071,-3.616627,-0.350374,-0.338492, + 0.614301,0.789071,-0.000581,-3.583763,-0.052271,0, + -0.99574,-0.082547,-0.041071,-3.616627,-0.350374,-0.338492, + 0.098463,-0.995141,0,-3.637643,-0.356271,0, + -0.923845,0.18432,-0.335466,-3.51684,0.149002,-0.430359, + -0.908258,0.139498,-0.394471,-3.470778,-0.078218,-0.546398, + -0.951862,0.098243,-0.290356,-3.529709,-0.065998,-0.437217, + -0.951862,0.098243,-0.290356,-3.529709,-0.065998,-0.437217, + -0.908258,0.139498,-0.394471,-3.470778,-0.078218,-0.546398, + -0.985615,0.064121,-0.156369,-3.526766,-0.317542,-0.560837, + -0.951862,0.098243,-0.290356,-3.529709,-0.065998,-0.437217, + -0.985615,0.064121,-0.156369,-3.526766,-0.317542,-0.560837, + -0.950882,-0.075567,-0.300188,-3.595973,-0.346391,-0.426453, + -0.950882,-0.075567,-0.300188,-3.595973,-0.346391,-0.426453, + -0.985615,0.064121,-0.156369,-3.526766,-0.317542,-0.560837, + -0.982334,-0.04331,-0.182057,-3.569993,-0.731989,-0.649435, + -0.950882,-0.075567,-0.300188,-3.595973,-0.346391,-0.426453, + -0.982334,-0.04331,-0.182057,-3.569993,-0.731989,-0.649435, + -0.896964,-0.287307,-0.336022,-3.665774,-0.73408,-0.446286, + -0.896964,-0.287307,-0.336022,-3.665774,-0.73408,-0.446286, + -0.982334,-0.04331,-0.182057,-3.569993,-0.731989,-0.649435, + -0.995081,-0.092251,0.036114,-3.55012,-0.984868,-0.675228, + -0.896964,-0.287307,-0.336022,-3.665774,-0.73408,-0.446286, + -0.995081,-0.092251,0.036114,-3.55012,-0.984868,-0.675228, + -0.815087,-0.388053,-0.430171,-3.667859,-0.964867,-0.464702, + -0.815087,-0.388053,-0.430171,-3.667859,-0.964867,-0.464702, + -0.995081,-0.092251,0.036114,-3.55012,-0.984868,-0.675228, + -0.938884,0.007108,-0.344159,-3.492599,-1.180646,-0.692282, + -0.815087,-0.388053,-0.430171,-3.667859,-0.964867,-0.464702, + -0.938884,0.007108,-0.344159,-3.492599,-1.180646,-0.692282, + -0.98615,-0.150918,-0.068783,-3.631179,-1.157838,-0.50561, + -0.98615,-0.150918,-0.068783,-3.631179,-1.157838,-0.50561, + -0.938884,0.007108,-0.344159,-3.492599,-1.180646,-0.692282, + -0.782249,0.198377,-0.590536,-3.335942,-1.365685,-0.72459, + -0.98615,-0.150918,-0.068783,-3.631179,-1.157838,-0.50561, + -0.782249,0.198377,-0.590536,-3.335942,-1.365685,-0.72459, + -0.581301,-0.608503,0.540197,-3.53391,-1.330455,-0.568246, + -0.581301,-0.608503,0.540197,-3.53391,-1.330455,-0.568246, + -0.782249,0.198377,-0.590536,-3.335942,-1.365685,-0.72459, + -0.354058,-0.732075,0.581987,-3.387254,-1.486027,-0.672861, + -0.743901,0.102645,-0.66036,-3.415655,-0.308965,-0.671045, + -0.984416,-0.175855,-0.000915,-3.283698,-0.730967,-0.793898, + -0.681141,-0.040116,-0.731052,-3.438226,-0.721479,-0.728141, + -0.908258,0.139498,-0.394471,-3.470778,-0.078218,-0.546398, + -0.743901,0.102645,-0.66036,-3.415655,-0.308965,-0.671045, + -0.985615,0.064121,-0.156369,-3.526766,-0.317542,-0.560837, + -0.985615,0.064121,-0.156369,-3.526766,-0.317542,-0.560837, + -0.743901,0.102645,-0.66036,-3.415655,-0.308965,-0.671045, + -0.681141,-0.040116,-0.731052,-3.438226,-0.721479,-0.728141, + -0.985615,0.064121,-0.156369,-3.526766,-0.317542,-0.560837, + -0.681141,-0.040116,-0.731052,-3.438226,-0.721479,-0.728141, + -0.982334,-0.04331,-0.182057,-3.569993,-0.731989,-0.649435, + -0.982334,-0.04331,-0.182057,-3.569993,-0.731989,-0.649435, + -0.681141,-0.040116,-0.731052,-3.438226,-0.721479,-0.728141, + -0.605564,-0.17532,-0.776244,-3.355398,-0.969157,-0.766213, + -0.982334,-0.04331,-0.182057,-3.569993,-0.731989,-0.649435, + -0.605564,-0.17532,-0.776244,-3.355398,-0.969157,-0.766213, + -0.995081,-0.092251,0.036114,-3.55012,-0.984868,-0.675228, + -0.995081,-0.092251,0.036114,-3.55012,-0.984868,-0.675228, + -0.605564,-0.17532,-0.776244,-3.355398,-0.969157,-0.766213, + -0.823768,0.005745,-0.566899,-3.27979,-1.162072,-0.784602, + -0.995081,-0.092251,0.036114,-3.55012,-0.984868,-0.675228, + -0.823768,0.005745,-0.566899,-3.27979,-1.162072,-0.784602, + -0.938884,0.007108,-0.344159,-3.492599,-1.180646,-0.692282, + -0.938884,0.007108,-0.344159,-3.492599,-1.180646,-0.692282, + -0.823768,0.005745,-0.566899,-3.27979,-1.162072,-0.784602, + -0.782249,0.198377,-0.590536,-3.335942,-1.365685,-0.72459, + -0.823768,0.005745,-0.566899,-3.27979,-1.162072,-0.784602, + -0.605564,-0.17532,-0.776244,-3.355398,-0.969157,-0.766213, + -0.838192,0.000365,-0.545375,-3.25121,-0.948205,-0.819868, + -0.971344,0.144305,-0.188856,-3.536654,0.442277,-0.322, + -0.57342,0.819261,0,-3.544507,0.467147,0, + -0.989276,0.146061,0,-3.566995,0.656967,0, + -0.971344,0.144305,-0.188856,-3.536654,0.442277,-0.322, + -0.989276,0.146061,0,-3.566995,0.656967,0, + -0.472479,0.093412,-0.876377,-3.556552,0.704883,-0.28063, + -0.472479,0.093412,-0.876377,-3.556552,0.704883,-0.28063, + -0.989276,0.146061,0,-3.566995,0.656967,0, + -0.989171,0.146765,0,-3.599077,0.796217,0, + -0.472479,0.093412,-0.876377,-3.556552,0.704883,-0.28063, + -0.989171,0.146765,0,-3.599077,0.796217,0, + -0.43302,-0.02622,-0.901003,-3.57817,0.837714,-0.288502, + -0.838192,0.000365,-0.545375,-3.25121,-0.948205,-0.819868, + -0.605564,-0.17532,-0.776244,-3.355398,-0.969157,-0.766213, + -0.681141,-0.040116,-0.731052,-3.438226,-0.721479,-0.728141, + -0.838192,0.000365,-0.545375,-3.25121,-0.948205,-0.819868, + -0.681141,-0.040116,-0.731052,-3.438226,-0.721479,-0.728141, + -0.984416,-0.175855,-0.000915,-3.283698,-0.730967,-0.793898, + 0.493535,-0.729115,-0.474147,-1.88316,-1.829718,-0.401567, + 0.728068,-0.191899,0.658097,-1.933565,-1.993029,-0.438902, + 0.313565,-0.18353,0.931662,-1.971059,-1.992958,-0.500845, + 0.493535,-0.729115,-0.474147,-1.88316,-1.829718,-0.401567, + 0.313565,-0.18353,0.931662,-1.971059,-1.992958,-0.500845, + 0.04422,-0.704109,-0.708714,-1.936032,-1.829617,-0.488916, + 0.04422,-0.704109,-0.708714,-1.936032,-1.829617,-0.488916, + 0.313565,-0.18353,0.931662,-1.971059,-1.992958,-0.500845, + 0.537835,-0.193789,0.820475,-2.03574,-1.981182,-0.547873, + 0.04422,-0.704109,-0.708714,-1.936032,-1.829617,-0.488916, + 0.537835,-0.193789,0.820475,-2.03574,-1.981182,-0.547873, + 0.083262,-0.787311,-0.610907,-2.027242,-1.813012,-0.555232, + 0.083262,-0.787311,-0.610907,-2.027242,-1.813012,-0.555232, + 0.537835,-0.193789,0.820475,-2.03574,-1.981182,-0.547873, + 0.908243,-0.229695,-0.349765,-2.106039,-2.019111,-0.510759, + 0.083262,-0.787311,-0.610907,-2.027242,-1.813012,-0.555232, + 0.908243,-0.229695,-0.349765,-2.106039,-2.019111,-0.510759, + 0.170756,-0.748007,-0.641349,-2.126375,-1.866497,-0.502895, + 0.170756,-0.748007,-0.641349,-2.126375,-1.866497,-0.502895, + 0.908243,-0.229695,-0.349765,-2.106039,-2.019111,-0.510759, + 0.701057,-0.210559,-0.68131,-2.141621,-2.024301,-0.470257, + 0.170756,-0.748007,-0.641349,-2.126375,-1.866497,-0.502895, + 0.701057,-0.210559,-0.68131,-2.141621,-2.024301,-0.470257, + 0.64791,-0.754869,0.101909,-2.176551,-1.873816,-0.445782, + 0.64791,-0.754869,0.101909,-2.176551,-1.873816,-0.445782, + 0.701057,-0.210559,-0.68131,-2.141621,-2.024301,-0.470257, + 0.129519,-0.132707,-0.982656,-2.120746,-2.045137,-0.411171, + 0.64791,-0.754869,0.101909,-2.176551,-1.873816,-0.445782, + 0.129519,-0.132707,-0.982656,-2.120746,-2.045137,-0.411171, + -0.393694,-0.919049,0.018795,-2.147113,-1.903198,-0.362462, + -0.393694,-0.919049,0.018795,-2.147113,-1.903198,-0.362462, + 0.129519,-0.132707,-0.982656,-2.120746,-2.045137,-0.411171, + -0.276108,-0.088024,-0.957087,-2.060902,-2.031698,-0.372079, + -0.393694,-0.919049,0.018795,-2.147113,-1.903198,-0.362462, + -0.276108,-0.088024,-0.957087,-2.060902,-2.031698,-0.372079, + -0.327707,-0.94199,0.072547,-2.062725,-1.884246,-0.307336, + -0.327707,-0.94199,0.072547,-2.062725,-1.884246,-0.307336, + -0.276108,-0.088024,-0.957087,-2.060902,-2.031698,-0.372079, + -0.40904,-0.077842,-0.90919,-1.978344,-2.023535,-0.398257, + -0.327707,-0.94199,0.072547,-2.062725,-1.884246,-0.307336, + -0.40904,-0.077842,-0.90919,-1.978344,-2.023535,-0.398257, + -0.163041,-0.980692,0.107986,-1.946306,-1.872735,-0.344251, + -0.163041,-0.980692,0.107986,-1.946306,-1.872735,-0.344251, + -0.40904,-0.077842,-0.90919,-1.978344,-2.023535,-0.398257, + 0.728068,-0.191899,0.658097,-1.933565,-1.993029,-0.438902, + -0.163041,-0.980692,0.107986,-1.946306,-1.872735,-0.344251, + 0.728068,-0.191899,0.658097,-1.933565,-1.993029,-0.438902, + 0.493535,-0.729115,-0.474147,-1.88316,-1.829718,-0.401567, + 0.183908,-0.773381,-0.606679,-2.446375,-1.893261,-0.49411, + 0.50178,0.000639,0.864995,-2.499138,-2.03809,-0.504529, + 0.300485,0.019099,0.953595,-2.513608,-2.012858,-0.558673, + 0.183908,-0.773381,-0.606679,-2.446375,-1.893261,-0.49411, + 0.300485,0.019099,0.953595,-2.513608,-2.012858,-0.558673, + 0.018755,-0.837462,-0.546174,-2.466779,-1.857679,-0.570461, + 0.018755,-0.837462,-0.546174,-2.466779,-1.857679,-0.570461, + 0.300485,0.019099,0.953595,-2.513608,-2.012858,-0.558673, + 0.678632,-0.017853,0.734261,-2.571019,-1.995375,-0.58623, + 0.018755,-0.837462,-0.546174,-2.466779,-1.857679,-0.570461, + 0.678632,-0.017853,0.734261,-2.571019,-1.995375,-0.58623, + -0.094688,-0.959937,-0.263734,-2.547737,-1.833025,-0.609321, + -0.094688,-0.959937,-0.263734,-2.547737,-1.833025,-0.609321, + 0.678632,-0.017853,0.734261,-2.571019,-1.995375,-0.58623, + 0.687126,-0.68509,-0.241887,-2.641567,-2.003164,-0.575611, + -0.094688,-0.959937,-0.263734,-2.547737,-1.833025,-0.609321, + 0.687126,-0.68509,-0.241887,-2.641567,-2.003164,-0.575611, + 0.059023,-0.965365,-0.25414,-2.64722,-1.84401,-0.594347, + 0.059023,-0.965365,-0.25414,-2.64722,-1.84401,-0.594347, + 0.687126,-0.68509,-0.241887,-2.641567,-2.003164,-0.575611, + 0.260319,-0.908993,0.325523,-2.678971,-2.007694,-0.558395, + 0.059023,-0.965365,-0.25414,-2.64722,-1.84401,-0.594347, + 0.260319,-0.908993,0.325523,-2.678971,-2.007694,-0.558395, + 0.49176,-0.810764,-0.317543,-2.699966,-1.850397,-0.57007, + 0.49176,-0.810764,-0.317543,-2.699966,-1.850397,-0.57007, + 0.260319,-0.908993,0.325523,-2.678971,-2.007694,-0.558395, + -0.148191,-0.901516,0.40658,-2.685663,-2.028649,-0.514928, + 0.49176,-0.810764,-0.317543,-2.699966,-1.850397,-0.57007, + -0.148191,-0.901516,0.40658,-2.685663,-2.028649,-0.514928, + 0.099157,-0.476834,-0.873383,-2.709403,-1.879947,-0.508775, + 0.099157,-0.476834,-0.873383,-2.709403,-1.879947,-0.508775, + -0.148191,-0.901516,0.40658,-2.685663,-2.028649,-0.514928, + -0.443612,-0.876487,0.187028,-2.667969,-2.036634,-0.471396, + 0.099157,-0.476834,-0.873383,-2.709403,-1.879947,-0.508775, + -0.443612,-0.876487,0.187028,-2.667969,-2.036634,-0.471396, + -0.147229,-0.706225,-0.69251,-2.684452,-1.891207,-0.447388, + -0.147229,-0.706225,-0.69251,-2.684452,-1.891207,-0.447388, + -0.443612,-0.876487,0.187028,-2.667969,-2.036634,-0.471396, + -0.508388,-0.837291,-0.20121,-2.618068,-2.046419,-0.441284, + -0.147229,-0.706225,-0.69251,-2.684452,-1.891207,-0.447388, + -0.508388,-0.837291,-0.20121,-2.618068,-2.046419,-0.441284, + 0.328486,-0.940918,0.082286,-2.614084,-1.905005,-0.404925, + 0.328486,-0.940918,0.082286,-2.614084,-1.905005,-0.404925, + -0.508388,-0.837291,-0.20121,-2.618068,-2.046419,-0.441284, + -0.409829,-0.525605,-0.745506,-2.539874,-2.049824,-0.460098, + 0.328486,-0.940918,0.082286,-2.614084,-1.905005,-0.404925, + -0.409829,-0.525605,-0.745506,-2.539874,-2.049824,-0.460098, + -0.319475,-0.944225,-0.079844,-2.503818,-1.909806,-0.431456, + -0.319475,-0.944225,-0.079844,-2.503818,-1.909806,-0.431456, + -0.409829,-0.525605,-0.745506,-2.539874,-2.049824,-0.460098, + 0.50178,0.000639,0.864995,-2.499138,-2.03809,-0.504529, + -0.319475,-0.944225,-0.079844,-2.503818,-1.909806,-0.431456, + 0.50178,0.000639,0.864995,-2.499138,-2.03809,-0.504529, + 0.183908,-0.773381,-0.606679,-2.446375,-1.893261,-0.49411, + -0.276108,-0.088024,-0.957087,-2.060902,-2.031698,-0.372079, + 0.10009,-0.380026,-0.919545,-2.065655,-2.124623,-0.36872, + -0.227573,-0.361149,-0.904313,-1.985123,-2.116661,-0.394256, + -0.276108,-0.088024,-0.957087,-2.060902,-2.031698,-0.372079, + -0.227573,-0.361149,-0.904313,-1.985123,-2.116661,-0.394256, + -0.40904,-0.077842,-0.90919,-1.978344,-2.023535,-0.398257, + 0.129519,-0.132707,-0.982656,-2.120746,-2.045137,-0.411171, + 0.547733,-0.470267,-0.691981,-2.12403,-2.137733,-0.406853, + 0.10009,-0.380026,-0.919545,-2.065655,-2.124623,-0.36872, + 0.129519,-0.132707,-0.982656,-2.120746,-2.045137,-0.411171, + 0.10009,-0.380026,-0.919545,-2.065655,-2.124623,-0.36872, + -0.276108,-0.088024,-0.957087,-2.060902,-2.031698,-0.372079, + 0.701057,-0.210559,-0.68131,-2.141621,-2.024301,-0.470257, + -0.071182,-0.950841,-0.301389,-2.144393,-2.117408,-0.464489, + 0.547733,-0.470267,-0.691981,-2.12403,-2.137733,-0.406853, + 0.701057,-0.210559,-0.68131,-2.141621,-2.024301,-0.470257, + 0.547733,-0.470267,-0.691981,-2.12403,-2.137733,-0.406853, + 0.129519,-0.132707,-0.982656,-2.120746,-2.045137,-0.411171, + 0.908243,-0.229695,-0.349765,-2.106039,-2.019111,-0.510759, + 0.216748,0.039315,-0.975436,-2.109684,-2.112345,-0.503997, + -0.071182,-0.950841,-0.301389,-2.144393,-2.117408,-0.464489, + 0.908243,-0.229695,-0.349765,-2.106039,-2.019111,-0.510759, + -0.071182,-0.950841,-0.301389,-2.144393,-2.117408,-0.464489, + 0.701057,-0.210559,-0.68131,-2.141621,-2.024301,-0.470257, + 0.537835,-0.193789,0.820475,-2.03574,-1.981182,-0.547873, + 0.555949,0.246865,-0.793712,-2.04111,-2.075348,-0.540201, + 0.216748,0.039315,-0.975436,-2.109684,-2.112345,-0.503997, + 0.537835,-0.193789,0.820475,-2.03574,-1.981182,-0.547873, + 0.216748,0.039315,-0.975436,-2.109684,-2.112345,-0.503997, + 0.908243,-0.229695,-0.349765,-2.106039,-2.019111,-0.510759, + 0.313565,-0.18353,0.931662,-1.971059,-1.992958,-0.500845, + 0.768311,0.202351,-0.60725,-1.978016,-2.086834,-0.494327, + 0.555949,0.246865,-0.793712,-2.04111,-2.075348,-0.540201, + 0.313565,-0.18353,0.931662,-1.971059,-1.992958,-0.500845, + 0.555949,0.246865,-0.793712,-2.04111,-2.075348,-0.540201, + 0.537835,-0.193789,0.820475,-2.03574,-1.981182,-0.547873, + 0.728068,-0.191899,0.658097,-1.933565,-1.993029,-0.438902, + 0.833232,0.046883,-0.550932,-1.941442,-2.086904,-0.433904, + 0.768311,0.202351,-0.60725,-1.978016,-2.086834,-0.494327, + 0.728068,-0.191899,0.658097,-1.933565,-1.993029,-0.438902, + 0.768311,0.202351,-0.60725,-1.978016,-2.086834,-0.494327, + 0.313565,-0.18353,0.931662,-1.971059,-1.992958,-0.500845, + -0.40904,-0.077842,-0.90919,-1.978344,-2.023535,-0.398257, + -0.227573,-0.361149,-0.904313,-1.985123,-2.116661,-0.394256, + 0.833232,0.046883,-0.550932,-1.941442,-2.086904,-0.433904, + -0.40904,-0.077842,-0.90919,-1.978344,-2.023535,-0.398257, + 0.833232,0.046883,-0.550932,-1.941442,-2.086904,-0.433904, + 0.728068,-0.191899,0.658097,-1.933565,-1.993029,-0.438902, + -0.409829,-0.525605,-0.745506,-2.539874,-2.049824,-0.460098, + 0.213243,-0.278119,-0.936578,-2.552923,-2.142304,-0.454579, + 0.587809,-0.328911,-0.73912,-2.513187,-2.130859,-0.49792, + -0.409829,-0.525605,-0.745506,-2.539874,-2.049824,-0.460098, + 0.587809,-0.328911,-0.73912,-2.513187,-2.130859,-0.49792, + 0.50178,0.000639,0.864995,-2.499138,-2.03809,-0.504529, + -0.508388,-0.837291,-0.20121,-2.618068,-2.046419,-0.441284, + 0.794828,0.083381,-0.601079,-2.629199,-2.138983,-0.436227, + 0.213243,-0.278119,-0.936578,-2.552923,-2.142304,-0.454579, + -0.508388,-0.837291,-0.20121,-2.618068,-2.046419,-0.441284, + 0.213243,-0.278119,-0.936578,-2.552923,-2.142304,-0.454579, + -0.409829,-0.525605,-0.745506,-2.539874,-2.049824,-0.460098, + -0.443612,-0.876487,0.187028,-2.667969,-2.036634,-0.471396, + 0.873201,-0.04546,-0.485236,-2.677875,-2.129439,-0.4656, + 0.794828,0.083381,-0.601079,-2.629199,-2.138983,-0.436227, + -0.443612,-0.876487,0.187028,-2.667969,-2.036634,-0.471396, + 0.794828,0.083381,-0.601079,-2.629199,-2.138983,-0.436227, + -0.508388,-0.837291,-0.20121,-2.618068,-2.046419,-0.441284, + -0.148191,-0.901516,0.40658,-2.685663,-2.028649,-0.514928, + 0.829377,-0.173624,-0.531026,-2.695135,-2.12165,-0.508064, + 0.873201,-0.04546,-0.485236,-2.677875,-2.129439,-0.4656, + -0.148191,-0.901516,0.40658,-2.685663,-2.028649,-0.514928, + 0.873201,-0.04546,-0.485236,-2.677875,-2.129439,-0.4656, + -0.443612,-0.876487,0.187028,-2.667969,-2.036634,-0.471396, + 0.260319,-0.908993,0.325523,-2.678971,-2.007694,-0.558395, + 0.506864,-0.193035,-0.840135,-2.688607,-2.101208,-0.550465, + 0.829377,-0.173624,-0.531026,-2.695135,-2.12165,-0.508064, + 0.260319,-0.908993,0.325523,-2.678971,-2.007694,-0.558395, + 0.829377,-0.173624,-0.531026,-2.695135,-2.12165,-0.508064, + -0.148191,-0.901516,0.40658,-2.685663,-2.028649,-0.514928, + 0.687126,-0.68509,-0.241887,-2.641567,-2.003164,-0.575611, + 0.166377,-0.157108,-0.973466,-2.65212,-2.09679,-0.567258, + 0.506864,-0.193035,-0.840135,-2.688607,-2.101208,-0.550465, + 0.687126,-0.68509,-0.241887,-2.641567,-2.003164,-0.575611, + 0.506864,-0.193035,-0.840135,-2.688607,-2.101208,-0.550465, + 0.260319,-0.908993,0.325523,-2.678971,-2.007694,-0.558395, + 0.678632,-0.017853,0.734261,-2.571019,-1.995375,-0.58623, + 0.054863,-0.132815,-0.989621,-2.583303,-2.089191,-0.577616, + 0.166377,-0.157108,-0.973466,-2.65212,-2.09679,-0.567258, + 0.678632,-0.017853,0.734261,-2.571019,-1.995375,-0.58623, + 0.166377,-0.157108,-0.973466,-2.65212,-2.09679,-0.567258, + 0.687126,-0.68509,-0.241887,-2.641567,-2.003164,-0.575611, + 0.300485,0.019099,0.953595,-2.513608,-2.012858,-0.558673, + 0.238844,0.101951,-0.965691,-2.527301,-2.106246,-0.550735, + 0.054863,-0.132815,-0.989621,-2.583303,-2.089191,-0.577616, + 0.300485,0.019099,0.953595,-2.513608,-2.012858,-0.558673, + 0.054863,-0.132815,-0.989621,-2.583303,-2.089191,-0.577616, + 0.678632,-0.017853,0.734261,-2.571019,-1.995375,-0.58623, + 0.50178,0.000639,0.864995,-2.499138,-2.03809,-0.504529, + 0.587809,-0.328911,-0.73912,-2.513187,-2.130859,-0.49792, + 0.238844,0.101951,-0.965691,-2.527301,-2.106246,-0.550735, + 0.50178,0.000639,0.864995,-2.499138,-2.03809,-0.504529, + 0.238844,0.101951,-0.965691,-2.527301,-2.106246,-0.550735, + 0.300485,0.019099,0.953595,-2.513608,-2.012858,-0.558673, + 0.768311,0.202351,-0.60725,-1.978016,-2.086834,-0.494327, + 0.833232,0.046883,-0.550932,-1.941442,-2.086904,-0.433904, + 0.604307,0.204357,-0.770098,-2.048681,-2.165282,-0.450843, + 0.555949,0.246865,-0.793712,-2.04111,-2.075348,-0.540201, + 0.768311,0.202351,-0.60725,-1.978016,-2.086834,-0.494327, + 0.604307,0.204357,-0.770098,-2.048681,-2.165282,-0.450843, + 0.216748,0.039315,-0.975436,-2.109684,-2.112345,-0.503997, + 0.555949,0.246865,-0.793712,-2.04111,-2.075348,-0.540201, + 0.604307,0.204357,-0.770098,-2.048681,-2.165282,-0.450843, + -0.071182,-0.950841,-0.301389,-2.144393,-2.117408,-0.464489, + 0.216748,0.039315,-0.975436,-2.109684,-2.112345,-0.503997, + 0.604307,0.204357,-0.770098,-2.048681,-2.165282,-0.450843, + 0.547733,-0.470267,-0.691981,-2.12403,-2.137733,-0.406853, + -0.071182,-0.950841,-0.301389,-2.144393,-2.117408,-0.464489, + 0.604307,0.204357,-0.770098,-2.048681,-2.165282,-0.450843, + 0.10009,-0.380026,-0.919545,-2.065655,-2.124623,-0.36872, + 0.547733,-0.470267,-0.691981,-2.12403,-2.137733,-0.406853, + 0.604307,0.204357,-0.770098,-2.048681,-2.165282,-0.450843, + -0.227573,-0.361149,-0.904313,-1.985123,-2.116661,-0.394256, + 0.10009,-0.380026,-0.919545,-2.065655,-2.124623,-0.36872, + 0.604307,0.204357,-0.770098,-2.048681,-2.165282,-0.450843, + 0.833232,0.046883,-0.550932,-1.941442,-2.086904,-0.433904, + -0.227573,-0.361149,-0.904313,-1.985123,-2.116661,-0.394256, + 0.604307,0.204357,-0.770098,-2.048681,-2.165282,-0.450843, + 0.238844,0.101951,-0.965691,-2.527301,-2.106246,-0.550735, + 0.587809,-0.328911,-0.73912,-2.513187,-2.130859,-0.49792, + 0.02054,-0.128179,-0.991538,-2.603284,-2.176802,-0.510638, + 0.054863,-0.132815,-0.989621,-2.583303,-2.089191,-0.577616, + 0.238844,0.101951,-0.965691,-2.527301,-2.106246,-0.550735, + 0.02054,-0.128179,-0.991538,-2.603284,-2.176802,-0.510638, + 0.166377,-0.157108,-0.973466,-2.65212,-2.09679,-0.567258, + 0.054863,-0.132815,-0.989621,-2.583303,-2.089191,-0.577616, + 0.02054,-0.128179,-0.991538,-2.603284,-2.176802,-0.510638, + 0.506864,-0.193035,-0.840135,-2.688607,-2.101208,-0.550465, + 0.166377,-0.157108,-0.973466,-2.65212,-2.09679,-0.567258, + 0.02054,-0.128179,-0.991538,-2.603284,-2.176802,-0.510638, + 0.829377,-0.173624,-0.531026,-2.695135,-2.12165,-0.508064, + 0.506864,-0.193035,-0.840135,-2.688607,-2.101208,-0.550465, + 0.02054,-0.128179,-0.991538,-2.603284,-2.176802,-0.510638, + 0.873201,-0.04546,-0.485236,-2.677875,-2.129439,-0.4656, + 0.829377,-0.173624,-0.531026,-2.695135,-2.12165,-0.508064, + 0.02054,-0.128179,-0.991538,-2.603284,-2.176802,-0.510638, + 0.794828,0.083381,-0.601079,-2.629199,-2.138983,-0.436227, + 0.873201,-0.04546,-0.485236,-2.677875,-2.129439,-0.4656, + 0.02054,-0.128179,-0.991538,-2.603284,-2.176802,-0.510638, + 0.213243,-0.278119,-0.936578,-2.552923,-2.142304,-0.454579, + 0.794828,0.083381,-0.601079,-2.629199,-2.138983,-0.436227, + 0.02054,-0.128179,-0.991538,-2.603284,-2.176802,-0.510638, + 0.587809,-0.328911,-0.73912,-2.513187,-2.130859,-0.49792, + 0.213243,-0.278119,-0.936578,-2.552923,-2.142304,-0.454579, + 0.02054,-0.128179,-0.991538,-2.603284,-2.176802,-0.510638, + -0.012978,-0.998326,0.056357,-3.139394,-1.687482,-0.638546, + 0.579344,-0.339433,0.741044,-3.008323,-1.759271,-0.655672, + -0.073547,-0.481419,-0.8734,-2.941731,-1.787431,-0.442574, + -0.012978,-0.998326,0.056357,-3.139394,-1.687482,-0.638546, + -0.073547,-0.481419,-0.8734,-2.941731,-1.787431,-0.442574, + 0.074429,-0.99521,0.063385,-3.120907,-1.707924,-0.431829, + 0.579344,-0.339433,0.741044,-3.008323,-1.759271,-0.655672, + 0.099157,-0.476834,-0.873383,-2.709403,-1.879947,-0.508775, + -0.073547,-0.481419,-0.8734,-2.941731,-1.787431,-0.442574, + 0.579344,-0.339433,0.741044,-3.008323,-1.759271,-0.655672, + 0.43907,-0.579988,-0.686171,-2.811581,-1.79821,-0.712737, + 0.49176,-0.810764,-0.317543,-2.699966,-1.850397,-0.57007, + 0.579344,-0.339433,0.741044,-3.008323,-1.759271,-0.655672, + 0.49176,-0.810764,-0.317543,-2.699966,-1.850397,-0.57007, + 0.099157,-0.476834,-0.873383,-2.709403,-1.879947,-0.508775, + -0.822733,0.223687,0.522565,-2.306662,-1.116976,0.961238, + -0.950882,-0.075567,0.300188,-2.119856,-1.1288,0.97096, + -0.619245,-0.050391,0.783579,-2.033406,-0.91003,0.96422, + -0.993498,0.089934,0.06981,-2.031698,-1.097344,0.966701, + -0.619245,-0.050391,0.783579,-2.033406,-0.91003,0.96422, + -0.950882,-0.075567,0.300188,-2.119856,-1.1288,0.97096, + -0.379807,-0.084066,0.921238,-1.782298,-1.020581,0.943381, + -0.619245,-0.050391,0.783579,-2.033406,-0.91003,0.96422, + -0.993498,0.089934,0.06981,-2.031698,-1.097344,0.966701, + -0.9775,0.159844,0.137638,-2.337617,-1.334842,0.966761, + -0.822733,0.223687,0.522565,-2.306662,-1.116976,0.961238, + -0.951862,0.098243,0.290356,-2.462835,-1.3055,0.966395, + -0.923845,0.18432,0.335466,-2.161843,-1.325837,0.957465, + -0.950882,-0.075567,0.300188,-2.119856,-1.1288,0.97096, + -0.822733,0.223687,0.522565,-2.306662,-1.116976,0.961238, + -0.923845,0.18432,0.335466,-2.161843,-1.325837,0.957465, + -0.822733,0.223687,0.522565,-2.306662,-1.116976,0.961238, + -0.9775,0.159844,0.137638,-2.337617,-1.334842,0.966761, + -0.971344,0.144305,0.188856,-2.042059,-1.312976,0.940911, + -0.993498,0.089934,0.06981,-2.031698,-1.097344,0.966701, + -0.950882,-0.075567,0.300188,-2.119856,-1.1288,0.97096, + -0.971344,0.144305,0.188856,-2.042059,-1.312976,0.940911, + -0.950882,-0.075567,0.300188,-2.119856,-1.1288,0.97096, + -0.923845,0.18432,0.335466,-2.161843,-1.325837,0.957465, + -0.908258,0.139498,0.394471,-1.776785,-1.275107,0.914703, + -0.379807,-0.084066,0.921238,-1.782298,-1.020581,0.943381, + -0.993498,0.089934,0.06981,-2.031698,-1.097344,0.966701, + -0.908258,0.139498,0.394471,-1.776785,-1.275107,0.914703, + -0.993498,0.089934,0.06981,-2.031698,-1.097344,0.966701, + -0.971344,0.144305,0.188856,-2.042059,-1.312976,0.940911, + -0.985615,0.064121,0.156369,-1.709172,-1.283232,0.897427, + -0.379807,-0.084066,0.921238,-1.782298,-1.020581,0.943381, + -0.908258,0.139498,0.394471,-1.776785,-1.275107,0.914703, + -0.982334,-0.04331,0.182057,-1.456655,-1.295527,0.89424, + -0.379807,-0.084066,0.921238,-1.782298,-1.020581,0.943381, + -0.985615,0.064121,0.156369,-1.709172,-1.283232,0.897427, + -0.938884,0.007108,0.344159,-2.417777,-1.553136,0.887222, + -0.9775,0.159844,0.137638,-2.337617,-1.334842,0.966761, + -0.951862,0.098243,0.290356,-2.462835,-1.3055,0.966395, + -0.938884,0.007108,0.344159,-2.417777,-1.553136,0.887222, + -0.951862,0.098243,0.290356,-2.462835,-1.3055,0.966395, + -0.995081,-0.092251,-0.036114,-2.591357,-1.510845,0.88547, + -0.782249,0.198377,0.590536,-2.223917,-1.541268,0.87926, + -0.923845,0.18432,0.335466,-2.161843,-1.325837,0.957465, + -0.9775,0.159844,0.137638,-2.337617,-1.334842,0.966761, + -0.782249,0.198377,0.590536,-2.223917,-1.541268,0.87926, + -0.9775,0.159844,0.137638,-2.337617,-1.334842,0.966761, + -0.938884,0.007108,0.344159,-2.417777,-1.553136,0.887222, + -0.743901,0.102645,0.66036,-2.049879,-1.562369,0.829319, + -0.971344,0.144305,0.188856,-2.042059,-1.312976,0.940911, + -0.923845,0.18432,0.335466,-2.161843,-1.325837,0.957465, + -0.743901,0.102645,0.66036,-2.049879,-1.562369,0.829319, + -0.923845,0.18432,0.335466,-2.161843,-1.325837,0.957465, + -0.782249,0.198377,0.590536,-2.223917,-1.541268,0.87926, + -0.605564,-0.17532,0.776244,-1.778934,-1.550199,0.776454, + -0.681141,-0.040116,0.731052,-1.777628,-1.473076,0.845827, + -0.971344,0.144305,0.188856,-2.042059,-1.312976,0.940911, + -0.605564,-0.17532,0.776244,-1.778934,-1.550199,0.776454, + -0.971344,0.144305,0.188856,-2.042059,-1.312976,0.940911, + -0.743901,0.102645,0.66036,-2.049879,-1.562369,0.829319, + -0.908258,0.139498,0.394471,-1.776785,-1.275107,0.914703, + -0.971344,0.144305,0.188856,-2.042059,-1.312976,0.940911, + -0.681141,-0.040116,0.731052,-1.777628,-1.473076,0.845827, + -0.823768,0.005745,0.566899,-1.686329,-1.414405,0.869373, + -0.985615,0.064121,0.156369,-1.709172,-1.283232,0.897427, + -0.908258,0.139498,0.394471,-1.776785,-1.275107,0.914703, + -0.823768,0.005745,0.566899,-1.686329,-1.414405,0.869373, + -0.908258,0.139498,0.394471,-1.776785,-1.275107,0.914703, + -0.681141,-0.040116,0.731052,-1.777628,-1.473076,0.845827, + -0.838192,0.000364,0.545375,-1.592146,-1.408592,0.838483, + -0.982334,-0.04331,0.182057,-1.456655,-1.295527,0.89424, + -0.985615,0.064121,0.156369,-1.709172,-1.283232,0.897427, + -0.838192,0.000364,0.545375,-1.592146,-1.408592,0.838483, + -0.985615,0.064121,0.156369,-1.709172,-1.283232,0.897427, + -0.823768,0.005745,0.566899,-1.686329,-1.414405,0.869373, + -0.472479,0.093413,0.876377,-1.552229,-1.555077,0.735708, + -0.982334,-0.04331,0.182057,-1.456655,-1.295527,0.89424, + -0.838192,0.000364,0.545375,-1.592146,-1.408592,0.838483, + -0.838192,0.000364,0.545375,-1.592146,-1.408592,0.838483, + -0.43302,-0.02622,0.901003,-1.659758,-1.544361,0.788181, + -0.472479,0.093413,0.876377,-1.552229,-1.555077,0.735708, + -0.823768,0.005745,0.566899,-1.686329,-1.414405,0.869373, + -0.43302,-0.02622,0.901003,-1.659758,-1.544361,0.788181, + -0.838192,0.000364,0.545375,-1.592146,-1.408592,0.838483, + -0.681141,-0.040116,0.731052,-1.777628,-1.473076,0.845827, + -0.605564,-0.17532,0.776244,-1.778934,-1.550199,0.776454, + -0.43302,-0.02622,0.901003,-1.659758,-1.544361,0.788181, + -0.681141,-0.040116,0.731052,-1.777628,-1.473076,0.845827, + -0.43302,-0.02622,0.901003,-1.659758,-1.544361,0.788181, + -0.823768,0.005745,0.566899,-1.686329,-1.414405,0.869373, + -0.285709,0.130064,0.949449,-1.376186,-1.661988,0.718954, + -0.311485,0.082882,0.94663,-1.366873,-1.340211,0.907567, + -0.982334,-0.04331,0.182057,-1.456655,-1.295527,0.89424, + -0.285709,0.130064,0.949449,-1.376186,-1.661988,0.718954, + -0.982334,-0.04331,0.182057,-1.456655,-1.295527,0.89424, + -0.472479,0.093413,0.876377,-1.552229,-1.555077,0.735708, + -0.809154,0.004832,0.587577,-1.200688,-1.577575,0.799188, + -0.742985,0.015712,0.669123,-1.198513,-1.456102,0.885435, + -0.311485,0.082882,0.94663,-1.366873,-1.340211,0.907567, + -0.809154,0.004832,0.587577,-1.200688,-1.577575,0.799188, + -0.311485,0.082882,0.94663,-1.366873,-1.340211,0.907567, + -0.285709,0.130064,0.949449,-1.376186,-1.661988,0.718954, + -0.02449,0.224062,0.974267,-0.953236,-1.545941,0.89918, + -0.742985,0.015712,0.669123,-1.198513,-1.456102,0.885435, + -0.809154,0.004832,0.587577,-1.200688,-1.577575,0.799188, + -0.285709,0.130064,0.949449,-1.376186,-1.661988,0.718954, + 0.924702,-0.311563,0.218757,-1.480217,-1.6566,0.606638, + -0.587909,-0.233166,0.774594,-1.397474,-1.693815,0.570541, + -0.472479,0.093413,0.876377,-1.552229,-1.555077,0.735708, + 0.924702,-0.311563,0.218757,-1.480217,-1.6566,0.606638, + -0.285709,0.130064,0.949449,-1.376186,-1.661988,0.718954, + 0.73827,-0.277136,0.614942,-1.601625,-1.593321,0.605607, + 0.924702,-0.311563,0.218757,-1.480217,-1.6566,0.606638, + -0.472479,0.093413,0.876377,-1.552229,-1.555077,0.735708, + 0.366416,-0.175098,0.913827,-1.519339,-1.653776,0.501741, + 0.924702,-0.311563,0.218757,-1.480217,-1.6566,0.606638, + 0.73827,-0.277136,0.614942,-1.601625,-1.593321,0.605607, + 0.023392,-0.110333,0.993619,-1.406693,-1.697325,0.450399, + -0.587909,-0.233166,0.774594,-1.397474,-1.693815,0.570541, + 0.924702,-0.311563,0.218757,-1.480217,-1.6566,0.606638, + 0.023392,-0.110333,0.993619,-1.406693,-1.697325,0.450399, + 0.924702,-0.311563,0.218757,-1.480217,-1.6566,0.606638, + 0.366416,-0.175098,0.913827,-1.519339,-1.653776,0.501741, + -0.157802,-0.148625,0.976222,-1.576196,-1.696317,0.358146, + 0.366416,-0.175098,0.913827,-1.519339,-1.653776,0.501741, + 0.73827,-0.277136,0.614942,-1.601625,-1.593321,0.605607, + -0.279485,0.127803,0.951606,-1.386502,-1.718441,0.350823, + 0.023392,-0.110333,0.993619,-1.406693,-1.697325,0.450399, + 0.366416,-0.175098,0.913827,-1.519339,-1.653776,0.501741, + -0.279485,0.127803,0.951606,-1.386502,-1.718441,0.350823, + 0.366416,-0.175098,0.913827,-1.519339,-1.653776,0.501741, + -0.157802,-0.148625,0.976222,-1.576196,-1.696317,0.358146, + -0.157802,-0.148625,0.976222,-1.576196,-1.696317,0.358146, + 0.106808,0.99428,0,-1.610025,-1.711571,0, + 0.011286,0.999936,0,-1.395728,-1.723811,0, + -0.157802,-0.148625,0.976222,-1.576196,-1.696317,0.358146, + 0.011286,0.999936,0,-1.395728,-1.723811,0, + -0.279485,0.127803,0.951606,-1.386502,-1.718441,0.350823, + -0.661097,-0.258238,0.70446,-1.764045,-1.764987,0.406586, + -0.160087,-0.987103,0,-1.799827,-1.753136,0, + 0.106808,0.99428,0,-1.610025,-1.711571,0, + -0.661097,-0.258238,0.70446,-1.764045,-1.764987,0.406586, + 0.106808,0.99428,0,-1.610025,-1.711571,0, + -0.157802,-0.148625,0.976222,-1.576196,-1.696317,0.358146, + -0.157802,-0.148625,0.976222,-1.576196,-1.696317,0.358146, + 0.73827,-0.277136,0.614942,-1.601625,-1.593321,0.605607, + -0.632119,-0.359381,0.686492,-1.74779,-1.667608,0.60634, + -0.157802,-0.148625,0.976222,-1.576196,-1.696317,0.358146, + -0.632119,-0.359381,0.686492,-1.74779,-1.667608,0.60634, + -0.661097,-0.258238,0.70446,-1.764045,-1.764987,0.406586, + -0.605564,-0.17532,0.776244,-1.778934,-1.550199,0.776454, + -0.632119,-0.359381,0.686492,-1.74779,-1.667608,0.60634, + 0.73827,-0.277136,0.614942,-1.601625,-1.593321,0.605607, + 0.73827,-0.277136,0.614942,-1.601625,-1.593321,0.605607, + -0.43302,-0.02622,0.901003,-1.659758,-1.544361,0.788181, + -0.605564,-0.17532,0.776244,-1.778934,-1.550199,0.776454, + -0.472479,0.093413,0.876377,-1.552229,-1.555077,0.735708, + -0.43302,-0.02622,0.901003,-1.659758,-1.544361,0.788181, + 0.73827,-0.277136,0.614942,-1.601625,-1.593321,0.605607, + 0.772916,-0.305378,0.556188,-2.508885,-1.719933,0.721675, + -0.938884,0.007108,0.344159,-2.417777,-1.553136,0.887222, + -0.995081,-0.092251,-0.036114,-2.591357,-1.510845,0.88547, + 0.772916,-0.305378,0.556188,-2.508885,-1.719933,0.721675, + -0.995081,-0.092251,-0.036114,-2.591357,-1.510845,0.88547, + 0.942117,-0.292664,0.163592,-2.734184,-1.717948,0.749581, + 0.38578,-0.259547,0.88533,-2.267049,-1.753901,0.662106, + -0.782249,0.198377,0.590536,-2.223917,-1.541268,0.87926, + -0.938884,0.007108,0.344159,-2.417777,-1.553136,0.887222, + 0.38578,-0.259547,0.88533,-2.267049,-1.753901,0.662106, + -0.938884,0.007108,0.344159,-2.417777,-1.553136,0.887222, + 0.772916,-0.305378,0.556188,-2.508885,-1.719933,0.721675, + 0.02992,-0.202031,0.978922,-2.037371,-1.73636,0.656787, + -0.743901,0.102645,0.66036,-2.049879,-1.562369,0.829319, + -0.782249,0.198377,0.590536,-2.223917,-1.541268,0.87926, + 0.02992,-0.202031,0.978922,-2.037371,-1.73636,0.656787, + -0.782249,0.198377,0.590536,-2.223917,-1.541268,0.87926, + 0.38578,-0.259547,0.88533,-2.267049,-1.753901,0.662106, + -0.632119,-0.359381,0.686492,-1.74779,-1.667608,0.60634, + -0.605564,-0.17532,0.776244,-1.778934,-1.550199,0.776454, + -0.743901,0.102645,0.66036,-2.049879,-1.562369,0.829319, + -0.632119,-0.359381,0.686492,-1.74779,-1.667608,0.60634, + -0.743901,0.102645,0.66036,-2.049879,-1.562369,0.829319, + 0.02992,-0.202031,0.978922,-2.037371,-1.73636,0.656787, + -0.498756,-0.224101,0.83727,-1.936032,-1.829617,0.488916, + -0.239734,-0.173966,0.955125,-1.88316,-1.829718,0.401567, + -0.661097,-0.258238,0.70446,-1.764045,-1.764987,0.406586, + -0.498756,-0.224101,0.83727,-1.936032,-1.829617,0.488916, + -0.661097,-0.258238,0.70446,-1.764045,-1.764987,0.406586, + -0.632119,-0.359381,0.686492,-1.74779,-1.667608,0.60634, + -0.632119,-0.359381,0.686492,-1.74779,-1.667608,0.60634, + 0.02992,-0.202031,0.978922,-2.037371,-1.73636,0.656787, + -0.759627,-0.28527,0.584455,-2.027242,-1.813012,0.555232, + -0.632119,-0.359381,0.686492,-1.74779,-1.667608,0.60634, + -0.759627,-0.28527,0.584455,-2.027242,-1.813012,0.555232, + -0.498756,-0.224101,0.83727,-1.936032,-1.829617,0.488916, + 0.38578,-0.259547,0.88533,-2.267049,-1.753901,0.662106, + -0.672688,-0.442616,0.592944,-2.126375,-1.866497,0.502895, + -0.759627,-0.28527,0.584455,-2.027242,-1.813012,0.555232, + 0.38578,-0.259547,0.88533,-2.267049,-1.753901,0.662106, + -0.759627,-0.28527,0.584455,-2.027242,-1.813012,0.555232, + 0.02992,-0.202031,0.978922,-2.037371,-1.73636,0.656787, + 0.80128,-0.303744,0.515451,-2.317557,-1.8742,0.470587, + 0.954473,-0.270031,0.126745,-2.176551,-1.873816,0.445782, + -0.672688,-0.442616,0.592944,-2.126375,-1.866497,0.502895, + 0.80128,-0.303744,0.515451,-2.317557,-1.8742,0.470587, + -0.672688,-0.442616,0.592944,-2.126375,-1.866497,0.502895, + 0.38578,-0.259547,0.88533,-2.267049,-1.753901,0.662106, + 0.38578,-0.259547,0.88533,-2.267049,-1.753901,0.662106, + 0.080262,-0.270606,0.959339,-2.466779,-1.857679,0.570461, + 0.441315,-0.29978,0.845797,-2.446375,-1.893261,0.49411, + 0.38578,-0.259547,0.88533,-2.267049,-1.753901,0.662106, + 0.441315,-0.29978,0.845797,-2.446375,-1.893261,0.49411, + 0.80128,-0.303744,0.515451,-2.317557,-1.8742,0.470587, + 0.772916,-0.305378,0.556188,-2.508885,-1.719933,0.721675, + -0.247433,-0.24804,0.936618,-2.547737,-1.833025,0.609321, + 0.080262,-0.270606,0.959339,-2.466779,-1.857679,0.570461, + 0.772916,-0.305378,0.556188,-2.508885,-1.719933,0.721675, + 0.080262,-0.270606,0.959339,-2.466779,-1.857679,0.570461, + 0.38578,-0.259547,0.88533,-2.267049,-1.753901,0.662106, + 0.942117,-0.292664,0.163592,-2.734184,-1.717948,0.749581, + -0.587844,-0.244917,0.771009,-2.64722,-1.84401,0.594347, + -0.247433,-0.24804,0.936618,-2.547737,-1.833025,0.609321, + 0.942117,-0.292664,0.163592,-2.734184,-1.717948,0.749581, + -0.247433,-0.24804,0.936618,-2.547737,-1.833025,0.609321, + 0.772916,-0.305378,0.556188,-2.508885,-1.719933,0.721675, + -0.732521,-0.474279,0.488336,-2.811581,-1.79821,0.712737, + -0.845196,-0.27877,0.455994,-2.699966,-1.850397,0.57007, + -0.587844,-0.244917,0.771009,-2.64722,-1.84401,0.594347, + -0.732521,-0.474279,0.488336,-2.811581,-1.79821,0.712737, + -0.587844,-0.244917,0.771009,-2.64722,-1.84401,0.594347, + 0.942117,-0.292664,0.163592,-2.734184,-1.717948,0.749581, + 0.0787,0.996898,0,-2.892162,-1.781087,0, + 0.975634,-0.187231,-0.114377,-2.684452,-1.891207,0.447388, + 0.972392,0.232654,0.018037,-2.709403,-1.879947,0.508775, + 0.0787,0.996898,0,-2.892162,-1.781087,0, + 0.972392,0.232654,0.018037,-2.709403,-1.879947,0.508775, + 0.999491,-0.02584,0.01873,-2.941731,-1.787431,0.442574, + 0.058013,0.998316,0,-2.656867,-1.853045,0, + 0.985192,-0.12583,-0.116459,-2.614084,-1.905005,0.404925, + 0.975634,-0.187231,-0.114377,-2.684452,-1.891207,0.447388, + 0.058013,0.998316,0,-2.656867,-1.853045,0, + 0.975634,-0.187231,-0.114377,-2.684452,-1.891207,0.447388, + 0.0787,0.996898,0,-2.892162,-1.781087,0, + 0.093777,0.995593,0,-2.348005,-1.869142,0, + 0.996811,-0.048518,-0.063355,-2.503818,-1.909806,0.431456, + 0.985192,-0.12583,-0.116459,-2.614084,-1.905005,0.404925, + 0.093777,0.995593,0,-2.348005,-1.869142,0, + 0.985192,-0.12583,-0.116459,-2.614084,-1.905005,0.404925, + 0.058013,0.998316,0,-2.656867,-1.853045,0, + 0.80128,-0.303744,0.515451,-2.317557,-1.8742,0.470587, + 0.441315,-0.29978,0.845797,-2.446375,-1.893261,0.49411, + 0.996811,-0.048518,-0.063355,-2.503818,-1.909806,0.431456, + 0.80128,-0.303744,0.515451,-2.317557,-1.8742,0.470587, + 0.996811,-0.048518,-0.063355,-2.503818,-1.909806,0.431456, + 0.093777,0.995593,0,-2.348005,-1.869142,0, + 0.093777,0.995593,0,-2.348005,-1.869142,0, + 0.957938,-0.285979,0.023877,-2.147113,-1.903198,0.362462, + 0.954473,-0.270031,0.126745,-2.176551,-1.873816,0.445782, + 0.093777,0.995593,0,-2.348005,-1.869142,0, + 0.954473,-0.270031,0.126745,-2.176551,-1.873816,0.445782, + 0.80128,-0.303744,0.515451,-2.317557,-1.8742,0.470587, + 0.149455,0.988769,0,-2.092921,-1.839622,0, + -0.274087,0.000043,-0.961705,-2.062725,-1.884246,0.307336, + 0.957938,-0.285979,0.023877,-2.147113,-1.903198,0.362462, + 0.149455,0.988769,0,-2.092921,-1.839622,0, + 0.957938,-0.285979,0.023877,-2.147113,-1.903198,0.362462, + 0.093777,0.995593,0,-2.348005,-1.869142,0, + -0.160087,-0.987103,0,-1.799827,-1.753136,0, + 0.74023,-0.090866,0.666185,-1.946306,-1.872735,0.344251, + -0.274087,0.000043,-0.961705,-2.062725,-1.884246,0.307336, + -0.160087,-0.987103,0,-1.799827,-1.753136,0, + -0.274087,0.000043,-0.961705,-2.062725,-1.884246,0.307336, + 0.149455,0.988769,0,-2.092921,-1.839622,0, + -0.661097,-0.258238,0.70446,-1.764045,-1.764987,0.406586, + -0.239734,-0.173966,0.955125,-1.88316,-1.829718,0.401567, + 0.74023,-0.090866,0.666185,-1.946306,-1.872735,0.344251, + -0.661097,-0.258238,0.70446,-1.764045,-1.764987,0.406586, + 0.74023,-0.090866,0.666185,-1.946306,-1.872735,0.344251, + -0.160087,-0.987103,0,-1.799827,-1.753136,0, + 0.830793,-0.244757,0.499877,-3.304804,-1.582192,0.643445, + 0.846555,-0.103662,0.52211,-3.314868,-1.599081,0.439626, + 0.820312,-0.193024,0.538358,-3.120907,-1.707924,0.431829, + 0.830793,-0.244757,0.499877,-3.304804,-1.582192,0.643445, + 0.820312,-0.193024,0.538358,-3.120907,-1.707924,0.431829, + 0.843062,-0.10517,0.527433,-3.139394,-1.687482,0.638546, + 0.290478,-0.146424,0.945612,-3.387254,-1.486027,0.672861, + 0.159615,0.129847,0.978602,-3.442085,-1.48412,0.406377, + 0.846555,-0.103662,0.52211,-3.314868,-1.599081,0.439626, + 0.290478,-0.146424,0.945612,-3.387254,-1.486027,0.672861, + 0.846555,-0.103662,0.52211,-3.314868,-1.599081,0.439626, + 0.830793,-0.244757,0.499877,-3.304804,-1.582192,0.643445, + 0.431429,-0.109339,0.895497,-3.53391,-1.330455,0.568246, + 0.407719,-0.190267,0.893064,-3.557869,-1.325941,0.37803, + 0.159615,0.129847,0.978602,-3.442085,-1.48412,0.406377, + 0.431429,-0.109339,0.895497,-3.53391,-1.330455,0.568246, + 0.159615,0.129847,0.978602,-3.442085,-1.48412,0.406377, + 0.290478,-0.146424,0.945612,-3.387254,-1.486027,0.672861, + 0.473622,-0.284001,0.833682,-3.631179,-1.157838,0.50561, + 0.459595,-0.144347,0.87632,-3.639586,-1.140102,0.3338, + 0.407719,-0.190267,0.893064,-3.557869,-1.325941,0.37803, + 0.473622,-0.284001,0.833682,-3.631179,-1.157838,0.50561, + 0.407719,-0.190267,0.893064,-3.557869,-1.325941,0.37803, + 0.431429,-0.109339,0.895497,-3.53391,-1.330455,0.568246, + -0.069043,-0.157333,0.985129,-3.667859,-0.964867,0.464702, + 0.051664,-0.122235,0.991156,-3.686518,-0.955181,0.320349, + 0.459595,-0.144347,0.87632,-3.639586,-1.140102,0.3338, + -0.069043,-0.157333,0.985129,-3.667859,-0.964867,0.464702, + 0.459595,-0.144347,0.87632,-3.639586,-1.140102,0.3338, + 0.473622,-0.284001,0.833682,-3.631179,-1.157838,0.50561, + 0.039,-0.185675,0.981837,-3.665774,-0.73408,0.446286, + -0.051713,-0.100833,0.993559,-3.676599,-0.729578,0.330724, + 0.051664,-0.122235,0.991156,-3.686518,-0.955181,0.320349, + 0.039,-0.185675,0.981837,-3.665774,-0.73408,0.446286, + 0.051664,-0.122235,0.991156,-3.686518,-0.955181,0.320349, + -0.069043,-0.157333,0.985129,-3.667859,-0.964867,0.464702, + -0.09542,0.162222,0.98213,-3.595973,-0.346391,0.426453, + 0.109483,-0.310605,0.944213,-3.616627,-0.350374,0.338492, + -0.051713,-0.100833,0.993559,-3.676599,-0.729578,0.330724, + -0.09542,0.162222,0.98213,-3.595973,-0.346391,0.426453, + -0.051713,-0.100833,0.993559,-3.676599,-0.729578,0.330724, + 0.039,-0.185675,0.981837,-3.665774,-0.73408,0.446286, + -0.246054,-0.154918,0.956796,-3.529709,-0.065998,0.437217, + -0.211092,-0.082708,0.973961,-3.570243,-0.060093,0.344854, + 0.109483,-0.310605,0.944213,-3.616627,-0.350374,0.338492, + -0.246054,-0.154918,0.956796,-3.529709,-0.065998,0.437217, + 0.109483,-0.310605,0.944213,-3.616627,-0.350374,0.338492, + -0.09542,0.162222,0.98213,-3.595973,-0.346391,0.426453, + -0.136917,-0.20176,0.969818,-3.51684,0.149002,0.430359, + -0.176356,-0.113876,0.977717,-3.535416,0.191408,0.338478, + -0.211092,-0.082708,0.973961,-3.570243,-0.060093,0.344854, + -0.136917,-0.20176,0.969818,-3.51684,0.149002,0.430359, + -0.211092,-0.082708,0.973961,-3.570243,-0.060093,0.344854, + -0.246054,-0.154918,0.956796,-3.529709,-0.065998,0.437217, + -0.17902,-0.308668,0.934171,-3.536654,0.442277,0.322, + -0.176356,-0.113876,0.977717,-3.535416,0.191408,0.338478, + -0.136917,-0.20176,0.969818,-3.51684,0.149002,0.430359, + -0.57342,0.819261,0,-3.544507,0.467147,0, + 0.170833,0.9853,0,-3.55232,0.219613,0, + -0.176356,-0.113876,0.977717,-3.535416,0.191408,0.338478, + -0.57342,0.819261,0,-3.544507,0.467147,0, + -0.176356,-0.113876,0.977717,-3.535416,0.191408,0.338478, + -0.17902,-0.308668,0.934171,-3.536654,0.442277,0.322, + 0.614301,0.789071,-0.000581,-3.583763,-0.052271,0, + -0.211092,-0.082708,0.973961,-3.570243,-0.060093,0.344854, + -0.176356,-0.113876,0.977717,-3.535416,0.191408,0.338478, + 0.614301,0.789071,-0.000581,-3.583763,-0.052271,0, + -0.176356,-0.113876,0.977717,-3.535416,0.191408,0.338478, + 0.170833,0.9853,0,-3.55232,0.219613,0, + 0.353735,-0.935346,0,-3.673607,-0.720796,0, + -0.051713,-0.100833,0.993559,-3.676599,-0.729578,0.330724, + 0.109483,-0.310605,0.944213,-3.616627,-0.350374,0.338492, + 0.353735,-0.935346,0,-3.673607,-0.720796,0, + 0.109483,-0.310605,0.944213,-3.616627,-0.350374,0.338492, + 0.098463,-0.995141,0,-3.637643,-0.356271,0, + -0.34926,-0.937026,0,-3.678793,-0.926816,0, + 0.051664,-0.122235,0.991156,-3.686518,-0.955181,0.320349, + -0.051713,-0.100833,0.993559,-3.676599,-0.729578,0.330724, + -0.34926,-0.937026,0,-3.678793,-0.926816,0, + -0.051713,-0.100833,0.993559,-3.676599,-0.729578,0.330724, + 0.353735,-0.935346,0,-3.673607,-0.720796,0, + -0.164,-0.98646,0,-3.650579,-1.142448,0, + 0.459595,-0.144347,0.87632,-3.639586,-1.140102,0.3338, + 0.051664,-0.122235,0.991156,-3.686518,-0.955181,0.320349, + -0.164,-0.98646,0,-3.650579,-1.142448,0, + 0.051664,-0.122235,0.991156,-3.686518,-0.955181,0.320349, + -0.34926,-0.937026,0,-3.678793,-0.926816,0, + 0.030921,-0.999522,0,-3.522115,-1.366623,0, + 0.407719,-0.190267,0.893064,-3.557869,-1.325941,0.37803, + 0.459595,-0.144347,0.87632,-3.639586,-1.140102,0.3338, + 0.030921,-0.999522,0,-3.522115,-1.366623,0, + 0.459595,-0.144347,0.87632,-3.639586,-1.140102,0.3338, + -0.164,-0.98646,0,-3.650579,-1.142448,0, + 0.183204,-0.983075,0,-3.417689,-1.494416,0, + 0.159615,0.129847,0.978602,-3.442085,-1.48412,0.406377, + 0.407719,-0.190267,0.893064,-3.557869,-1.325941,0.37803, + 0.183204,-0.983075,0,-3.417689,-1.494416,0, + 0.407719,-0.190267,0.893064,-3.557869,-1.325941,0.37803, + 0.030921,-0.999522,0,-3.522115,-1.366623,0, + -0.997516,0.070442,0,-3.271035,-1.609292,0, + 0.846555,-0.103662,0.52211,-3.314868,-1.599081,0.439626, + 0.159615,0.129847,0.978602,-3.442085,-1.48412,0.406377, + -0.997516,0.070442,0,-3.271035,-1.609292,0, + 0.159615,0.129847,0.978602,-3.442085,-1.48412,0.406377, + 0.183204,-0.983075,0,-3.417689,-1.494416,0, + -0.99928,-0.037933,0,-3.1103,-1.69172,0, + 0.820312,-0.193024,0.538358,-3.120907,-1.707924,0.431829, + 0.846555,-0.103662,0.52211,-3.314868,-1.599081,0.439626, + -0.99928,-0.037933,0,-3.1103,-1.69172,0, + 0.846555,-0.103662,0.52211,-3.314868,-1.599081,0.439626, + -0.997516,0.070442,0,-3.271035,-1.609292,0, + 0.0787,0.996898,0,-2.892162,-1.781087,0, + 0.999491,-0.02584,0.01873,-2.941731,-1.787431,0.442574, + 0.820312,-0.193024,0.538358,-3.120907,-1.707924,0.431829, + 0.0787,0.996898,0,-2.892162,-1.781087,0, + 0.820312,-0.193024,0.538358,-3.120907,-1.707924,0.431829, + -0.99928,-0.037933,0,-3.1103,-1.69172,0, + 0.098463,-0.995141,0,-3.637643,-0.356271,0, + 0.109483,-0.310605,0.944213,-3.616627,-0.350374,0.338492, + -0.211092,-0.082708,0.973961,-3.570243,-0.060093,0.344854, + 0.098463,-0.995141,0,-3.637643,-0.356271,0, + -0.211092,-0.082708,0.973961,-3.570243,-0.060093,0.344854, + 0.614301,0.789071,-0.000581,-3.583763,-0.052271,0, + -0.246054,-0.154918,0.956796,-3.529709,-0.065998,0.437217, + -0.739347,0.031953,0.672566,-3.470778,-0.078218,0.546398, + -0.136917,-0.20176,0.969818,-3.51684,0.149002,0.430359, + -0.09542,0.162222,0.98213,-3.595973,-0.346391,0.426453, + -0.652584,-0.147678,0.743186,-3.526766,-0.317542,0.560837, + -0.739347,0.031953,0.672566,-3.470778,-0.078218,0.546398, + -0.09542,0.162222,0.98213,-3.595973,-0.346391,0.426453, + -0.739347,0.031953,0.672566,-3.470778,-0.078218,0.546398, + -0.246054,-0.154918,0.956796,-3.529709,-0.065998,0.437217, + 0.039,-0.185675,0.981837,-3.665774,-0.73408,0.446286, + -0.483189,-0.207332,0.850613,-3.569993,-0.731989,0.649435, + -0.652584,-0.147678,0.743186,-3.526766,-0.317542,0.560837, + 0.039,-0.185675,0.981837,-3.665774,-0.73408,0.446286, + -0.652584,-0.147678,0.743186,-3.526766,-0.317542,0.560837, + -0.09542,0.162222,0.98213,-3.595973,-0.346391,0.426453, + -0.069043,-0.157333,0.985129,-3.667859,-0.964867,0.464702, + -0.4008,-0.167777,0.900672,-3.55012,-0.984868,0.675228, + -0.483189,-0.207332,0.850613,-3.569993,-0.731989,0.649435, + -0.069043,-0.157333,0.985129,-3.667859,-0.964867,0.464702, + -0.483189,-0.207332,0.850613,-3.569993,-0.731989,0.649435, + 0.039,-0.185675,0.981837,-3.665774,-0.73408,0.446286, + 0.473622,-0.284001,0.833682,-3.631179,-1.157838,0.50561, + -0.417424,-0.199203,0.886609,-3.492599,-1.180646,0.692282, + -0.4008,-0.167777,0.900672,-3.55012,-0.984868,0.675228, + 0.473622,-0.284001,0.833682,-3.631179,-1.157838,0.50561, + -0.4008,-0.167777,0.900672,-3.55012,-0.984868,0.675228, + -0.069043,-0.157333,0.985129,-3.667859,-0.964867,0.464702, + 0.431429,-0.109339,0.895497,-3.53391,-1.330455,0.568246, + -0.521685,-0.261319,0.812131,-3.335942,-1.365685,0.72459, + -0.417424,-0.199203,0.886609,-3.492599,-1.180646,0.692282, + 0.431429,-0.109339,0.895497,-3.53391,-1.330455,0.568246, + -0.417424,-0.199203,0.886609,-3.492599,-1.180646,0.692282, + 0.473622,-0.284001,0.833682,-3.631179,-1.157838,0.50561, + 0.290478,-0.146424,0.945612,-3.387254,-1.486027,0.672861, + -0.521685,-0.261319,0.812131,-3.335942,-1.365685,0.72459, + 0.431429,-0.109339,0.895497,-3.53391,-1.330455,0.568246, + -0.912869,-0.285577,0.291747,-3.438226,-0.721479,0.728141, + -0.99574,-0.082547,0.041071,-3.283698,-0.730967,0.793898, + -0.970971,-0.219011,0.096178,-3.415655,-0.308965,0.671045, + -0.652584,-0.147678,0.743186,-3.526766,-0.317542,0.560837, + -0.970971,-0.219011,0.096178,-3.415655,-0.308965,0.671045, + -0.739347,0.031953,0.672566,-3.470778,-0.078218,0.546398, + -0.483189,-0.207332,0.850613,-3.569993,-0.731989,0.649435, + -0.912869,-0.285577,0.291747,-3.438226,-0.721479,0.728141, + -0.970971,-0.219011,0.096178,-3.415655,-0.308965,0.671045, + -0.483189,-0.207332,0.850613,-3.569993,-0.731989,0.649435, + -0.970971,-0.219011,0.096178,-3.415655,-0.308965,0.671045, + -0.652584,-0.147678,0.743186,-3.526766,-0.317542,0.560837, + -0.4008,-0.167777,0.900672,-3.55012,-0.984868,0.675228, + -0.883057,-0.239959,0.403273,-3.355398,-0.969157,0.766213, + -0.912869,-0.285577,0.291747,-3.438226,-0.721479,0.728141, + -0.4008,-0.167777,0.900672,-3.55012,-0.984868,0.675228, + -0.912869,-0.285577,0.291747,-3.438226,-0.721479,0.728141, + -0.483189,-0.207332,0.850613,-3.569993,-0.731989,0.649435, + -0.417424,-0.199203,0.886609,-3.492599,-1.180646,0.692282, + -0.872722,-0.174901,0.455813,-3.27979,-1.162072,0.784602, + -0.883057,-0.239959,0.403273,-3.355398,-0.969157,0.766213, + -0.417424,-0.199203,0.886609,-3.492599,-1.180646,0.692282, + -0.883057,-0.239959,0.403273,-3.355398,-0.969157,0.766213, + -0.4008,-0.167777,0.900672,-3.55012,-0.984868,0.675228, + -0.521685,-0.261319,0.812131,-3.335942,-1.365685,0.72459, + -0.872722,-0.174901,0.455813,-3.27979,-1.162072,0.784602, + -0.417424,-0.199203,0.886609,-3.492599,-1.180646,0.692282, + -0.874358,-0.225285,0.429819,-3.25121,-0.948205,0.819868, + -0.883057,-0.239959,0.403273,-3.355398,-0.969157,0.766213, + -0.872722,-0.174901,0.455813,-3.27979,-1.162072,0.784602, + -0.794709,-0.185222,-0.57804,-3.556552,0.704883,0.28063, + -0.989276,0.146061,0,-3.566995,0.656967,0, + -0.57342,0.819261,0,-3.544507,0.467147,0, + -0.794709,-0.185222,-0.57804,-3.556552,0.704883,0.28063, + -0.57342,0.819261,0,-3.544507,0.467147,0, + -0.17902,-0.308668,0.934171,-3.536654,0.442277,0.322, + -0.845931,-0.255219,-0.468256,-3.57817,0.837714,0.288502, + -0.989171,0.146765,0,-3.599077,0.796217,0, + -0.989276,0.146061,0,-3.566995,0.656967,0, + -0.845931,-0.255219,-0.468256,-3.57817,0.837714,0.288502, + -0.989276,0.146061,0,-3.566995,0.656967,0, + -0.794709,-0.185222,-0.57804,-3.556552,0.704883,0.28063, + -0.99574,-0.082547,0.041071,-3.283698,-0.730967,0.793898, + -0.912869,-0.285577,0.291747,-3.438226,-0.721479,0.728141, + -0.883057,-0.239959,0.403273,-3.355398,-0.969157,0.766213, + -0.99574,-0.082547,0.041071,-3.283698,-0.730967,0.793898, + -0.883057,-0.239959,0.403273,-3.355398,-0.969157,0.766213, + -0.874358,-0.225285,0.429819,-3.25121,-0.948205,0.819868, + -0.498756,-0.224101,0.83727,-1.936032,-1.829617,0.488916, + 0.722741,0.690989,-0.01339,-1.971059,-1.992958,0.500845, + 0.532717,0.840798,0.09629,-1.933565,-1.993029,0.438902, + -0.498756,-0.224101,0.83727,-1.936032,-1.829617,0.488916, + 0.532717,0.840798,0.09629,-1.933565,-1.993029,0.438902, + -0.239734,-0.173966,0.955125,-1.88316,-1.829718,0.401567, + -0.759627,-0.28527,0.584455,-2.027242,-1.813012,0.555232, + 0.870384,0.492056,0.017698,-2.03574,-1.981182,0.547873, + 0.722741,0.690989,-0.01339,-1.971059,-1.992958,0.500845, + -0.759627,-0.28527,0.584455,-2.027242,-1.813012,0.555232, + 0.722741,0.690989,-0.01339,-1.971059,-1.992958,0.500845, + -0.498756,-0.224101,0.83727,-1.936032,-1.829617,0.488916, + -0.672688,-0.442616,0.592944,-2.126375,-1.866497,0.502895, + 0.947044,0.280641,0.156039,-2.106039,-2.019111,0.510759, + 0.870384,0.492056,0.017698,-2.03574,-1.981182,0.547873, + -0.672688,-0.442616,0.592944,-2.126375,-1.866497,0.502895, + 0.870384,0.492056,0.017698,-2.03574,-1.981182,0.547873, + -0.759627,-0.28527,0.584455,-2.027242,-1.813012,0.555232, + 0.954473,-0.270031,0.126745,-2.176551,-1.873816,0.445782, + 0.925586,0.050829,0.375109,-2.141621,-2.024301,0.470257, + 0.947044,0.280641,0.156039,-2.106039,-2.019111,0.510759, + 0.954473,-0.270031,0.126745,-2.176551,-1.873816,0.445782, + 0.947044,0.280641,0.156039,-2.106039,-2.019111,0.510759, + -0.672688,-0.442616,0.592944,-2.126375,-1.866497,0.502895, + 0.957938,-0.285979,0.023877,-2.147113,-1.903198,0.362462, + -0.212651,-0.104685,0.971504,-2.120746,-2.045137,0.411171, + 0.925586,0.050829,0.375109,-2.141621,-2.024301,0.470257, + 0.957938,-0.285979,0.023877,-2.147113,-1.903198,0.362462, + 0.925586,0.050829,0.375109,-2.141621,-2.024301,0.470257, + 0.954473,-0.270031,0.126745,-2.176551,-1.873816,0.445782, + -0.274087,0.000043,-0.961705,-2.062725,-1.884246,0.307336, + 0.332529,0.910491,0.245827,-2.060902,-2.031698,0.372079, + -0.212651,-0.104685,0.971504,-2.120746,-2.045137,0.411171, + -0.274087,0.000043,-0.961705,-2.062725,-1.884246,0.307336, + -0.212651,-0.104685,0.971504,-2.120746,-2.045137,0.411171, + 0.957938,-0.285979,0.023877,-2.147113,-1.903198,0.362462, + 0.74023,-0.090866,0.666185,-1.946306,-1.872735,0.344251, + 0.530834,0.847416,-0.010102,-1.978344,-2.023535,0.398257, + 0.332529,0.910491,0.245827,-2.060902,-2.031698,0.372079, + 0.74023,-0.090866,0.666185,-1.946306,-1.872735,0.344251, + 0.332529,0.910491,0.245827,-2.060902,-2.031698,0.372079, + -0.274087,0.000043,-0.961705,-2.062725,-1.884246,0.307336, + -0.239734,-0.173966,0.955125,-1.88316,-1.829718,0.401567, + 0.532717,0.840798,0.09629,-1.933565,-1.993029,0.438902, + 0.530834,0.847416,-0.010102,-1.978344,-2.023535,0.398257, + -0.239734,-0.173966,0.955125,-1.88316,-1.829718,0.401567, + 0.530834,0.847416,-0.010102,-1.978344,-2.023535,0.398257, + 0.74023,-0.090866,0.666185,-1.946306,-1.872735,0.344251, + 0.080262,-0.270606,0.959339,-2.466779,-1.857679,0.570461, + 0.78715,0.616449,-0.019656,-2.513608,-2.012858,0.558673, + 0.66813,0.738233,-0.092817,-2.499138,-2.03809,0.504529, + 0.080262,-0.270606,0.959339,-2.466779,-1.857679,0.570461, + 0.66813,0.738233,-0.092817,-2.499138,-2.03809,0.504529, + 0.441315,-0.29978,0.845797,-2.446375,-1.893261,0.49411, + -0.247433,-0.24804,0.936618,-2.547737,-1.833025,0.609321, + 0.856604,0.474875,0.201802,-2.571019,-1.995375,0.58623, + 0.78715,0.616449,-0.019656,-2.513608,-2.012858,0.558673, + -0.247433,-0.24804,0.936618,-2.547737,-1.833025,0.609321, + 0.78715,0.616449,-0.019656,-2.513608,-2.012858,0.558673, + 0.080262,-0.270606,0.959339,-2.466779,-1.857679,0.570461, + -0.587844,-0.244917,0.771009,-2.64722,-1.84401,0.594347, + 0.827569,0.284291,0.484054,-2.641567,-2.003164,0.575611, + 0.856604,0.474875,0.201802,-2.571019,-1.995375,0.58623, + -0.587844,-0.244917,0.771009,-2.64722,-1.84401,0.594347, + 0.856604,0.474875,0.201802,-2.571019,-1.995375,0.58623, + -0.247433,-0.24804,0.936618,-2.547737,-1.833025,0.609321, + -0.845196,-0.27877,0.455994,-2.699966,-1.850397,0.57007, + 0.754806,0.216246,0.619279,-2.678971,-2.007694,0.558395, + 0.827569,0.284291,0.484054,-2.641567,-2.003164,0.575611, + -0.845196,-0.27877,0.455994,-2.699966,-1.850397,0.57007, + 0.827569,0.284291,0.484054,-2.641567,-2.003164,0.575611, + -0.587844,-0.244917,0.771009,-2.64722,-1.84401,0.594347, + 0.972392,0.232654,0.018037,-2.709403,-1.879947,0.508775, + 0.512523,0.043999,0.857545,-2.685663,-2.028649,0.514928, + 0.754806,0.216246,0.619279,-2.678971,-2.007694,0.558395, + 0.972392,0.232654,0.018037,-2.709403,-1.879947,0.508775, + 0.754806,0.216246,0.619279,-2.678971,-2.007694,0.558395, + -0.845196,-0.27877,0.455994,-2.699966,-1.850397,0.57007, + 0.975634,-0.187231,-0.114377,-2.684452,-1.891207,0.447388, + 0.45571,-0.00339,0.890122,-2.667969,-2.036634,0.471396, + 0.512523,0.043999,0.857545,-2.685663,-2.028649,0.514928, + 0.975634,-0.187231,-0.114377,-2.684452,-1.891207,0.447388, + 0.512523,0.043999,0.857545,-2.685663,-2.028649,0.514928, + 0.972392,0.232654,0.018037,-2.709403,-1.879947,0.508775, + 0.985192,-0.12583,-0.116459,-2.614084,-1.905005,0.404925, + 0.373808,-0.059429,0.9256,-2.618068,-2.046419,0.441284, + 0.45571,-0.00339,0.890122,-2.667969,-2.036634,0.471396, + 0.985192,-0.12583,-0.116459,-2.614084,-1.905005,0.404925, + 0.45571,-0.00339,0.890122,-2.667969,-2.036634,0.471396, + 0.975634,-0.187231,-0.114377,-2.684452,-1.891207,0.447388, + 0.996811,-0.048518,-0.063355,-2.503818,-1.909806,0.431456, + 0.276212,-0.065585,0.958856,-2.539874,-2.049824,0.460098, + 0.373808,-0.059429,0.9256,-2.618068,-2.046419,0.441284, + 0.996811,-0.048518,-0.063355,-2.503818,-1.909806,0.431456, + 0.373808,-0.059429,0.9256,-2.618068,-2.046419,0.441284, + 0.985192,-0.12583,-0.116459,-2.614084,-1.905005,0.404925, + 0.441315,-0.29978,0.845797,-2.446375,-1.893261,0.49411, + 0.66813,0.738233,-0.092817,-2.499138,-2.03809,0.504529, + 0.276212,-0.065585,0.958856,-2.539874,-2.049824,0.460098, + 0.441315,-0.29978,0.845797,-2.446375,-1.893261,0.49411, + 0.276212,-0.065585,0.958856,-2.539874,-2.049824,0.460098, + 0.996811,-0.048518,-0.063355,-2.503818,-1.909806,0.431456, + 0.530834,0.847416,-0.010102,-1.978344,-2.023535,0.398257, + 0.122987,-0.006582,0.992387,-1.985123,-2.116661,0.394256, + 0.041586,0.068165,0.996807,-2.065655,-2.124623,0.36872, + 0.530834,0.847416,-0.010102,-1.978344,-2.023535,0.398257, + 0.041586,0.068165,0.996807,-2.065655,-2.124623,0.36872, + 0.332529,0.910491,0.245827,-2.060902,-2.031698,0.372079, + 0.332529,0.910491,0.245827,-2.060902,-2.031698,0.372079, + 0.041586,0.068165,0.996807,-2.065655,-2.124623,0.36872, + 0.035084,0.005692,0.999368,-2.12403,-2.137733,0.406853, + 0.332529,0.910491,0.245827,-2.060902,-2.031698,0.372079, + 0.035084,0.005692,0.999368,-2.12403,-2.137733,0.406853, + -0.212651,-0.104685,0.971504,-2.120746,-2.045137,0.411171, + -0.212651,-0.104685,0.971504,-2.120746,-2.045137,0.411171, + 0.035084,0.005692,0.999368,-2.12403,-2.137733,0.406853, + -0.01346,-0.014478,0.999805,-2.144393,-2.117408,0.464489, + -0.212651,-0.104685,0.971504,-2.120746,-2.045137,0.411171, + -0.01346,-0.014478,0.999805,-2.144393,-2.117408,0.464489, + 0.925586,0.050829,0.375109,-2.141621,-2.024301,0.470257, + 0.925586,0.050829,0.375109,-2.141621,-2.024301,0.470257, + -0.01346,-0.014478,0.999805,-2.144393,-2.117408,0.464489, + -0.114527,0.103064,0.988059,-2.109684,-2.112345,0.503997, + 0.925586,0.050829,0.375109,-2.141621,-2.024301,0.470257, + -0.114527,0.103064,0.988059,-2.109684,-2.112345,0.503997, + 0.947044,0.280641,0.156039,-2.106039,-2.019111,0.510759, + 0.947044,0.280641,0.156039,-2.106039,-2.019111,0.510759, + -0.114527,0.103064,0.988059,-2.109684,-2.112345,0.503997, + 0.2189,0.87846,0.424724,-2.04111,-2.075348,0.540201, + 0.947044,0.280641,0.156039,-2.106039,-2.019111,0.510759, + 0.2189,0.87846,0.424724,-2.04111,-2.075348,0.540201, + 0.870384,0.492056,0.017698,-2.03574,-1.981182,0.547873, + 0.870384,0.492056,0.017698,-2.03574,-1.981182,0.547873, + 0.2189,0.87846,0.424724,-2.04111,-2.075348,0.540201, + -0.194126,0.280848,0.939914,-1.978016,-2.086834,0.494327, + 0.870384,0.492056,0.017698,-2.03574,-1.981182,0.547873, + -0.194126,0.280848,0.939914,-1.978016,-2.086834,0.494327, + 0.722741,0.690989,-0.01339,-1.971059,-1.992958,0.500845, + 0.722741,0.690989,-0.01339,-1.971059,-1.992958,0.500845, + -0.194126,0.280848,0.939914,-1.978016,-2.086834,0.494327, + 0.742615,0.656803,0.130894,-1.941442,-2.086904,0.433904, + 0.722741,0.690989,-0.01339,-1.971059,-1.992958,0.500845, + 0.742615,0.656803,0.130894,-1.941442,-2.086904,0.433904, + 0.532717,0.840798,0.09629,-1.933565,-1.993029,0.438902, + 0.532717,0.840798,0.09629,-1.933565,-1.993029,0.438902, + 0.742615,0.656803,0.130894,-1.941442,-2.086904,0.433904, + 0.122987,-0.006582,0.992387,-1.985123,-2.116661,0.394256, + 0.532717,0.840798,0.09629,-1.933565,-1.993029,0.438902, + 0.122987,-0.006582,0.992387,-1.985123,-2.116661,0.394256, + 0.530834,0.847416,-0.010102,-1.978344,-2.023535,0.398257, + 0.66813,0.738233,-0.092817,-2.499138,-2.03809,0.504529, + 0.681964,0.386261,0.621069,-2.513187,-2.130859,0.49792, + 0.584509,0.341142,0.736187,-2.552923,-2.142304,0.454579, + 0.66813,0.738233,-0.092817,-2.499138,-2.03809,0.504529, + 0.584509,0.341142,0.736187,-2.552923,-2.142304,0.454579, + 0.276212,-0.065585,0.958856,-2.539874,-2.049824,0.460098, + 0.276212,-0.065585,0.958856,-2.539874,-2.049824,0.460098, + 0.584509,0.341142,0.736187,-2.552923,-2.142304,0.454579, + 0.519595,0.25029,0.816931,-2.629199,-2.138983,0.436227, + 0.276212,-0.065585,0.958856,-2.539874,-2.049824,0.460098, + 0.519595,0.25029,0.816931,-2.629199,-2.138983,0.436227, + 0.373808,-0.059429,0.9256,-2.618068,-2.046419,0.441284, + 0.373808,-0.059429,0.9256,-2.618068,-2.046419,0.441284, + 0.519595,0.25029,0.816931,-2.629199,-2.138983,0.436227, + 0.237937,0.08172,0.967837,-2.677875,-2.129439,0.4656, + 0.373808,-0.059429,0.9256,-2.618068,-2.046419,0.441284, + 0.237937,0.08172,0.967837,-2.677875,-2.129439,0.4656, + 0.45571,-0.00339,0.890122,-2.667969,-2.036634,0.471396, + 0.45571,-0.00339,0.890122,-2.667969,-2.036634,0.471396, + 0.237937,0.08172,0.967837,-2.677875,-2.129439,0.4656, + 0.198142,0.152918,0.968171,-2.695135,-2.12165,0.508064, + 0.45571,-0.00339,0.890122,-2.667969,-2.036634,0.471396, + 0.198142,0.152918,0.968171,-2.695135,-2.12165,0.508064, + 0.512523,0.043999,0.857545,-2.685663,-2.028649,0.514928, + 0.512523,0.043999,0.857545,-2.685663,-2.028649,0.514928, + 0.198142,0.152918,0.968171,-2.695135,-2.12165,0.508064, + 0.198441,0.172024,0.964898,-2.688607,-2.101208,0.550465, + 0.512523,0.043999,0.857545,-2.685663,-2.028649,0.514928, + 0.198441,0.172024,0.964898,-2.688607,-2.101208,0.550465, + 0.754806,0.216246,0.619279,-2.678971,-2.007694,0.558395, + 0.754806,0.216246,0.619279,-2.678971,-2.007694,0.558395, + 0.198441,0.172024,0.964898,-2.688607,-2.101208,0.550465, + 0.204819,0.130792,0.970022,-2.65212,-2.09679,0.567258, + 0.754806,0.216246,0.619279,-2.678971,-2.007694,0.558395, + 0.204819,0.130792,0.970022,-2.65212,-2.09679,0.567258, + 0.827569,0.284291,0.484054,-2.641567,-2.003164,0.575611, + 0.827569,0.284291,0.484054,-2.641567,-2.003164,0.575611, + 0.204819,0.130792,0.970022,-2.65212,-2.09679,0.567258, + 0.154029,0.078449,0.984947,-2.583303,-2.089191,0.577616, + 0.827569,0.284291,0.484054,-2.641567,-2.003164,0.575611, + 0.154029,0.078449,0.984947,-2.583303,-2.089191,0.577616, + 0.856604,0.474875,0.201802,-2.571019,-1.995375,0.58623, + 0.856604,0.474875,0.201802,-2.571019,-1.995375,0.58623, + 0.154029,0.078449,0.984947,-2.583303,-2.089191,0.577616, + 0.032152,0.123743,0.991793,-2.527301,-2.106246,0.550735, + 0.856604,0.474875,0.201802,-2.571019,-1.995375,0.58623, + 0.032152,0.123743,0.991793,-2.527301,-2.106246,0.550735, + 0.78715,0.616449,-0.019656,-2.513608,-2.012858,0.558673, + 0.78715,0.616449,-0.019656,-2.513608,-2.012858,0.558673, + 0.032152,0.123743,0.991793,-2.527301,-2.106246,0.550735, + 0.681964,0.386261,0.621069,-2.513187,-2.130859,0.49792, + 0.78715,0.616449,-0.019656,-2.513608,-2.012858,0.558673, + 0.681964,0.386261,0.621069,-2.513187,-2.130859,0.49792, + 0.66813,0.738233,-0.092817,-2.499138,-2.03809,0.504529, + -0.077208,0.343417,0.936004,-2.048681,-2.165282,0.450843, + 0.742615,0.656803,0.130894,-1.941442,-2.086904,0.433904, + -0.194126,0.280848,0.939914,-1.978016,-2.086834,0.494327, + -0.077208,0.343417,0.936004,-2.048681,-2.165282,0.450843, + -0.194126,0.280848,0.939914,-1.978016,-2.086834,0.494327, + 0.2189,0.87846,0.424724,-2.04111,-2.075348,0.540201, + -0.077208,0.343417,0.936004,-2.048681,-2.165282,0.450843, + 0.2189,0.87846,0.424724,-2.04111,-2.075348,0.540201, + -0.114527,0.103064,0.988059,-2.109684,-2.112345,0.503997, + -0.077208,0.343417,0.936004,-2.048681,-2.165282,0.450843, + -0.114527,0.103064,0.988059,-2.109684,-2.112345,0.503997, + -0.01346,-0.014478,0.999805,-2.144393,-2.117408,0.464489, + -0.077208,0.343417,0.936004,-2.048681,-2.165282,0.450843, + -0.01346,-0.014478,0.999805,-2.144393,-2.117408,0.464489, + 0.035084,0.005692,0.999368,-2.12403,-2.137733,0.406853, + -0.077208,0.343417,0.936004,-2.048681,-2.165282,0.450843, + 0.035084,0.005692,0.999368,-2.12403,-2.137733,0.406853, + 0.041586,0.068165,0.996807,-2.065655,-2.124623,0.36872, + -0.077208,0.343417,0.936004,-2.048681,-2.165282,0.450843, + 0.041586,0.068165,0.996807,-2.065655,-2.124623,0.36872, + 0.122987,-0.006582,0.992387,-1.985123,-2.116661,0.394256, + -0.077208,0.343417,0.936004,-2.048681,-2.165282,0.450843, + 0.122987,-0.006582,0.992387,-1.985123,-2.116661,0.394256, + 0.742615,0.656803,0.130894,-1.941442,-2.086904,0.433904, + 0.510285,0.851048,0.1238,-2.603284,-2.176802,0.510638, + 0.681964,0.386261,0.621069,-2.513187,-2.130859,0.49792, + 0.032152,0.123743,0.991793,-2.527301,-2.106246,0.550735, + 0.510285,0.851048,0.1238,-2.603284,-2.176802,0.510638, + 0.032152,0.123743,0.991793,-2.527301,-2.106246,0.550735, + 0.154029,0.078449,0.984947,-2.583303,-2.089191,0.577616, + 0.510285,0.851048,0.1238,-2.603284,-2.176802,0.510638, + 0.154029,0.078449,0.984947,-2.583303,-2.089191,0.577616, + 0.204819,0.130792,0.970022,-2.65212,-2.09679,0.567258, + 0.510285,0.851048,0.1238,-2.603284,-2.176802,0.510638, + 0.204819,0.130792,0.970022,-2.65212,-2.09679,0.567258, + 0.198441,0.172024,0.964898,-2.688607,-2.101208,0.550465, + 0.510285,0.851048,0.1238,-2.603284,-2.176802,0.510638, + 0.198441,0.172024,0.964898,-2.688607,-2.101208,0.550465, + 0.198142,0.152918,0.968171,-2.695135,-2.12165,0.508064, + 0.510285,0.851048,0.1238,-2.603284,-2.176802,0.510638, + 0.198142,0.152918,0.968171,-2.695135,-2.12165,0.508064, + 0.237937,0.08172,0.967837,-2.677875,-2.129439,0.4656, + 0.510285,0.851048,0.1238,-2.603284,-2.176802,0.510638, + 0.237937,0.08172,0.967837,-2.677875,-2.129439,0.4656, + 0.519595,0.25029,0.816931,-2.629199,-2.138983,0.436227, + 0.510285,0.851048,0.1238,-2.603284,-2.176802,0.510638, + 0.519595,0.25029,0.816931,-2.629199,-2.138983,0.436227, + 0.584509,0.341142,0.736187,-2.552923,-2.142304,0.454579, + 0.510285,0.851048,0.1238,-2.603284,-2.176802,0.510638, + 0.584509,0.341142,0.736187,-2.552923,-2.142304,0.454579, + 0.681964,0.386261,0.621069,-2.513187,-2.130859,0.49792, + 0.820312,-0.193024,0.538358,-3.120907,-1.707924,0.431829, + 0.999491,-0.02584,0.01873,-2.941731,-1.787431,0.442574, + 0.713401,0.39471,-0.579019,-3.008323,-1.759271,0.655672, + 0.820312,-0.193024,0.538358,-3.120907,-1.707924,0.431829, + 0.713401,0.39471,-0.579019,-3.008323,-1.759271,0.655672, + 0.843062,-0.10517,0.527433,-3.139394,-1.687482,0.638546, + 0.999491,-0.02584,0.01873,-2.941731,-1.787431,0.442574, + 0.972392,0.232654,0.018037,-2.709403,-1.879947,0.508775, + 0.713401,0.39471,-0.579019,-3.008323,-1.759271,0.655672, + 0.972392,0.232654,0.018037,-2.709403,-1.879947,0.508775, + -0.845196,-0.27877,0.455994,-2.699966,-1.850397,0.57007, + -0.732521,-0.474279,0.488336,-2.811581,-1.79821,0.712737, + 0.972392,0.232654,0.018037,-2.709403,-1.879947,0.508775, + -0.732521,-0.474279,0.488336,-2.811581,-1.79821,0.712737, + 0.713401,0.39471,-0.579019,-3.008323,-1.759271,0.655672, + -0.530021,0.13773,0.836724,-3.697889,-0.951955,0.098793, + -0.54555,-0.056478,0.836173,-3.67645,-0.551317,0.077574, + -0.548359,-0.017804,0.836053,-3.699784,-0.759901,0.088664 +}; +static const struct gllist frame={GL_N3F_V3F,GL_TRIANGLES,1515,data,NULL}; +const struct gllist *cow_udder=&frame; diff --git a/hacks/glx/crackberg.c b/hacks/glx/crackberg.c new file mode 100644 index 00000000..6e4b7b49 --- /dev/null +++ b/hacks/glx/crackberg.c @@ -0,0 +1,1463 @@ +/*************************** + ** crackberg; Matus Telgarsky [ catachresis@cmu.edu ] 2005 + ** */ +#ifndef HAVE_COCOA +# define XK_MISCELLANY +# include +#endif + +#define DEFAULTS "*delay: 20000 \n" \ + "*showFPS: False \n" \ + "*wireframe: False \n" \ + +# define refresh_crackberg 0 +#undef countof +#define countof(x) (sizeof((x))/sizeof((*x))) + +#include "xlockmore.h" +#ifdef USE_GL /* whole file */ + +#define DEF_NSUBDIVS "4" +#define DEF_BORING "False" +#define DEF_CRACK "True" +#define DEF_WATER "True" +#define DEF_FLAT "True" +#define DEF_COLOR "random" +#define DEF_LIT "True" +#define DEF_VISIBILITY "0.6" +#define DEF_LETTERBOX "False" + + +/*************************** + ** macros + ** */ + +#define M_RAD7_4 0.661437827766148 +#define M_SQRT3_2 0.866025403784439 +#define M_PI_180 0.0174532925199433 +#define M_180_PI 57.2957795130823 +#define MSPEED_SCALE 1.1 +#define AVE3(a,b,c) ( ((a) + (b) + (c)) / 3.0 ) +#define MAX_ZDELTA 0.35 +#define DISPLACE(h,d) (h+(random()/(double)RAND_MAX-0.5)*2*MAX_ZDELTA/(1<heights[(cberg->epoints * (y) - ((y)-1)*(y)/2 + (x))]) +#define sNCOORD(x,y,p) (cberg->norms[3 * (cberg->epoints * (y) - ((y)-1)*(y)/2 + (x)) + (p)]) +#define SET_sNCOORD(x,y, down, a,b,c,d,e,f) \ + sNCOORD(x,y,0) = AVE3(a-d, 0.5 * (b-e), -0.5 * (c-f)); \ + sNCOORD(x,y,1) = ((down) ? -1 : +1) * AVE3(0.0, M_SQRT3_2 * (b-e), M_SQRT3_2 * (c-f)); \ + sNCOORD(x,y,2) = (2*dx) +#define fNCOORD(x,y,w,p) \ + (cberg->norms[3 * (2*(y)*cberg->epoints-((y)+1)*((y)+1) + 1 + 2 * ((x)-1) + (w)) + (p)]) +#define SET_fNCOORDa(x,y, down, dz00,dz01) \ + fNCOORD(x,y,0,0) = (down) * (dy) * (dz01); \ + fNCOORD(x,y,0,1) = (down) * ((dz01) * (dx) / 2 - (dx) * (dz00)); \ + fNCOORD(x,y,0,2) = (down) * (dx) * (dy) +#define SET_fNCOORDb(x,y, down, dz10,dz11) \ + fNCOORD(x,y,1,0) = (down) * (dy) * (dz10); \ + fNCOORD(x,y,1,1) = (down) * ((dz11) * (dx) - (dx) * (dz10) / 2); \ + fNCOORD(x,y,1,2) = (down) * (dx) * (dy) + + +/*************************** + ** types + ** */ + + +typedef struct _cberg_state cberg_state; +typedef struct _Trile Trile; + +typedef struct { + void (*init)(Trile *); + void (*free)(Trile *); + void (*draw)(Trile *); + void (*init_iter)(Trile *, cberg_state *); + void (*dying_iter)(Trile *, cberg_state *); +} Morph; + +typedef struct { + char *id; + void (*land)(cberg_state *, double); + void (*water)(cberg_state *, double); + double bg[4]; +} Color; + +enum { TRILE_NEW, TRILE_INIT, TRILE_STABLE, TRILE_DYING, TRILE_DELETE }; + +struct _Trile { + int x,y; /*center coords; points up if (x+y)%2 == 0, else down*/ + short state; + short visible; + double *l,*r,*v; /*only edges need saving*/ + GLuint call_list; + + void *morph_data; + const Morph *morph; + + struct _Trile *left, *right, *parent; /* for bst, NOT spatial */ + struct _Trile *next_free; /* for memory allocation */ +}; + +enum { MOTION_AUTO = 0, MOTION_MANUAL = 1, MOTION_LROT= 2, MOTION_RROT = 4, + MOTION_FORW = 8, MOTION_BACK = 16, MOTION_DEC = 32, MOTION_INC = 64, + MOTION_LEFT = 128, MOTION_RIGHT = 256 }; + +struct _cberg_state { + GLXContext *glx_context; + Trile *trile_head; + + double x,y,z, yaw,roll,pitch, dx,dy,dz, dyaw,droll,dpitch, elapsed; + double prev_frame; + int motion_state; + double mspeed; + + double fovy, aspect, zNear, zFar; + + const Color *color; + + int count; + + unsigned int epoints, /*number of points to one edge*/ + tpoints, /*number points total*/ + ntris, /*number triangles per trile*/ + tnorms; /*number of normals*/ + + double *heights, *norms; + Trile *free_head; /* for trile_[alloc|free] */ + + double draw_elapsed; + + double dx0; + + double vs0r,vs0g,vs0b, vs1r, vs1g, vs1b, + vf0r,vf0g,vf0b, vf1r, vf1g, vf1b; + + Bool button_down_p; + int mouse_x, mouse_y; + struct timeval paused; +}; + + + +/*************************** + ** globals + ** */ + +static unsigned int nsubdivs; +static Bool crack, boring, do_water, flat, lit, letterbox; +static float visibility; +static char *color; + +static cberg_state *cbergs = NULL; + +static XrmOptionDescRec opts[] = { + {"-nsubdivs", ".nsubdivs", XrmoptionSepArg, 0}, + {"-boring", ".boring", XrmoptionNoArg, "True"}, + {"-crack", ".crack", XrmoptionNoArg, "True"}, + {"-no-crack", ".crack", XrmoptionNoArg, "False"}, + {"-water", ".water", XrmoptionNoArg, "True"}, + {"-no-water", ".water", XrmoptionNoArg, "False"}, + {"-flat", ".flat", XrmoptionNoArg, "True"}, + {"-no-flat", ".flat", XrmoptionNoArg, "False"}, + {"-color", ".color", XrmoptionSepArg, 0}, + {"-lit", ".lit", XrmoptionNoArg, "True"}, + {"-no-lit", ".lit", XrmoptionNoArg, "False"}, + {"-visibility", ".visibility", XrmoptionSepArg, 0}, + {"-letterbox", ".letterbox", XrmoptionNoArg, "True"} +}; + +static argtype vars[] = { + {&nsubdivs, "nsubdivs", "nsubdivs", DEF_NSUBDIVS, t_Int}, + {&boring, "boring", "boring", DEF_BORING, t_Bool}, + {&crack, "crack", "crack", DEF_CRACK, t_Bool}, + {&do_water, "water", "water", DEF_WATER, t_Bool}, + {&flat, "flat", "flat", DEF_FLAT, t_Bool}, + {&color, "color", "color", DEF_COLOR, t_String}, + {&lit, "lit", "lit", DEF_LIT, t_Bool}, + {&visibility, "visibility", "visibility", DEF_VISIBILITY, t_Float}, + {&letterbox, "letterbox", "letterbox", DEF_LETTERBOX, t_Bool} +}; + +ENTRYPOINT ModeSpecOpt crackberg_opts = {countof(opts), opts, countof(vars), vars, NULL}; + + +/*************************** + ** Trile functions. + ** first come all are regular trile functions + ** */ + + +/* forward decls for trile_new */ +static Trile *triles_find(Trile *tr, int x, int y); +static Trile *trile_alloc(cberg_state *cberg); +static const Morph *select_morph(void); +static const Color *select_color(cberg_state *); + +static void trile_calc_sides(cberg_state *cberg, + Trile *new, int x, int y, Trile *root) +{ + unsigned int i,j,k; + int dv = ( (x + y) % 2 ? +1 : -1); /* we are pointing down or up*/ + Trile *l, *r, *v; /* v_ertical */ + + + if (root) { + l = triles_find(root, x-1, y); + r = triles_find(root, x+1, y); + v = triles_find(root, x,y+dv); + } else + l = r = v = NULL; + + if (v) { + for (i = 0; i != cberg->epoints; ++i) + new->v[i] = v->v[i]; + } else { + if (l) new->v[0] = l->l[0]; + else if (!root) new->v[0] = DISPLACE(0,0); + else { + Trile *tr; /* all of these tests needed.. */ + if ( (tr = triles_find(root, x-1, y + dv)) ) + new->v[0] = tr->l[0]; + else if ( (tr = triles_find(root, x-2, y)) ) + new->v[0] = tr->r[0]; + else if ( (tr = triles_find(root, x-2, y + dv)) ) + new->v[0] = tr->r[0]; + else + new->v[0] = DISPLACE(0,0); + } + + if (r) new->v[cberg->epoints-1] = r->l[0]; + else if (!root) new->v[cberg->epoints-1] = DISPLACE(0,0); + else { + Trile *tr; + if ( (tr = triles_find(root, x+1, y + dv)) ) + new->v[cberg->epoints-1] = tr->l[0]; + else if ( (tr = triles_find(root, x+2, y)) ) + new->v[cberg->epoints-1] = tr->v[0]; + else if ( (tr = triles_find(root, x+2, y + dv)) ) + new->v[cberg->epoints-1] = tr->v[0]; + else + new->v[cberg->epoints-1] = DISPLACE(0,0); + } + + for (i = ((1 << nsubdivs) >> 1), k =1; i; i >>= 1, ++k) + for (j = i; j < cberg->epoints; j += i * 2) + new->v[j] = DISPLACE(MEAN(new->v[j-i], new->v[j+i]), k); + } + + if (l) { + for (i = 0; i != cberg->epoints; ++i) + new->l[i] = l->r[i]; + } else { + if (r) new->l[0] = r->v[0]; + else if (!root) new->l[0] = DISPLACE(0,0); + else { + Trile *tr; + if ( (tr = triles_find(root, x-1, y-dv)) ) + new->l[0] = tr->r[0]; + else if ( (tr = triles_find(root, x+1, y-dv)) ) + new->l[0] = tr->v[0]; + else if ( (tr = triles_find(root, x, y-dv)) ) + new->l[0] = tr->l[0]; + else + new->l[0] = DISPLACE(0,0); + } + + new->l[cberg->epoints - 1] = new->v[0]; + + for (i = ((1 << nsubdivs) >> 1), k =1; i; i >>= 1, ++k) + for (j = i; j < cberg->epoints; j += i * 2) + new->l[j] = DISPLACE(MEAN(new->l[j-i], new->l[j+i]), k); + } + + if (r) { + for (i = 0; i != cberg->epoints; ++i) + new->r[i] = r->l[i]; + } else { + new->r[0] = new->v[cberg->epoints - 1]; + new->r[cberg->epoints - 1] = new->l[0]; + + for (i = ((1 << nsubdivs) >> 1), k =1; i; i >>= 1, ++k) + for (j = i; j < cberg->epoints; j += i * 2) + new->r[j] = DISPLACE(MEAN(new->r[j-i], new->r[j+i]), k); + } +} + +static void trile_calc_heights(cberg_state *cberg, Trile *new) +{ + unsigned int i, j, k, h; + + for (i = 0; i < cberg->epoints - 1; ++i) { /* copy in sides */ + TCOORD(i,0) = new->v[i]; + TCOORD(cberg->epoints - 1 - i, i) = new->r[i]; + TCOORD(0, cberg->epoints - 1 - i) = new->l[i]; + } + + for (i = ((1 << nsubdivs) >> 2), k =1; i; i >>= 1, ++k) + for (j = 1; j < (1 << k); ++j) + for (h = 1; h <= (1<x + new->y) % 2) ? -1 : +1); + double dz00,dz01,dz10,dz11, a,b,c,d; + double dy = down * M_SQRT3_2 / (1 << nsubdivs); + double dx = cberg->dx0; + + for (y = 0; y < cberg->epoints - 1; ++y) { + a = TCOORD(0,y); + b = TCOORD(0,y+1); + for (x = 1; x < cberg->epoints - 1 - y; ++x) { + c = TCOORD(x,y); + d = TCOORD(x,y+1); + + dz00 = b-c; + dz01 = a-c; + dz10 = b-d; + dz11 = c-d; + + SET_fNCOORDa(x,y, down, dz00,dz01); + SET_fNCOORDb(x,y, down, dz10,dz11); + + a = c; + b = d; + } + + c = TCOORD(x,y); + dz00 = b-c; + dz01 = a-c; + SET_fNCOORDa(x,y, down, dz00, dz01); + } +} + +static void trile_calc_smooth_norms(cberg_state *cberg, Trile *new) +{ + unsigned int i,j, down = (new->x + new->y) % 2; + double prev, cur, next; + double dx = cberg->dx0; + + /** corners -- assume level (bah) **/ + cur = TCOORD(0,0); + SET_sNCOORD(0,0, down, + cur,cur,TCOORD(0,1),TCOORD(1,0),cur,cur); + cur = TCOORD(cberg->epoints-1,0); + SET_sNCOORD(cberg->epoints-1,0, down, + TCOORD(cberg->epoints-2,0),TCOORD(cberg->epoints-2,1),cur,cur,cur,cur); + cur = TCOORD(0,cberg->epoints-1); + SET_sNCOORD(0,cberg->epoints-1, down, + cur,cur,cur,cur,TCOORD(1,cberg->epoints-2),TCOORD(0,cberg->epoints-2)); + + + /** sides **/ + /* vert */ + prev = TCOORD(0,0); + cur = TCOORD(1,0); + for (i = 1; i < cberg->epoints - 1; ++i) { + next = TCOORD(i+1,0); + SET_sNCOORD(i,0, down, prev,TCOORD(i-1,1),TCOORD(i,1), next,cur,cur); + prev = cur; + cur = next; + } + + /* right */ + prev = TCOORD(cberg->epoints-1,0); + cur = TCOORD(cberg->epoints-2,0); + for (i = 1; i < cberg->epoints - 1; ++i) { + next = TCOORD(cberg->epoints-i-2,i+1); + SET_sNCOORD(cberg->epoints-i-1,i, down, TCOORD(cberg->epoints-i-2,i),next,cur, + cur,prev,TCOORD(cberg->epoints-i-1,i-1)); + prev = cur; + cur = next; + } + + /* left */ + prev = TCOORD(0,0); + cur = TCOORD(0,1); + for (i = 1; i < cberg->epoints - 1; ++i) { + next = TCOORD(0,i+1); + SET_sNCOORD(0,i, down, cur,cur,next,TCOORD(1,i),TCOORD(1,i-1),prev); + prev = cur; + cur = next; + } + + + /** fill in **/ + for (i = 1; i < cberg->epoints - 2; ++i) { + prev = TCOORD(0,i); + cur = TCOORD(1,i); + for (j = 1; j < cberg->epoints - i - 1; ++j) { + next = TCOORD(j+1,i); + SET_sNCOORD(j,i, down, prev,TCOORD(j-1,i+1),TCOORD(j,i+1), + next,TCOORD(j+1,i-1),TCOORD(j,i-1)); + prev = cur; + cur = next; + } + } +} + +static inline void trile_light(cberg_state *cberg, + unsigned int x, unsigned int y, + unsigned int which) +{ + if (flat) { + if (x) { + glNormal3d(fNCOORD(x,y,which,0), + fNCOORD(x,y,which,1), + fNCOORD(x,y,which,2)); + } else { /* I get mesa errors and bizarre glitches without this!! */ + glNormal3d(fNCOORD(1,y,0,0), + fNCOORD(1,y,0,1), + fNCOORD(1,y,0,2)); + } + } else { + glNormal3d(sNCOORD(x,y+which,0), + sNCOORD(x,y+which,1), + sNCOORD(x,y+which,2)); + } +} + +static inline void trile_draw_vertex(cberg_state *cberg, unsigned int ix, + unsigned int iy, unsigned int which, double x,double y, + double zcur, double z1, double z2) +{ + glColor3d(0.0, 0.0, 0.0); /* don't ask. my card breaks otherwise. */ + + if (do_water && zcur <= 0.0) { + cberg->color->water(cberg, zcur); /* XXX use average-of-3 for color when flat?*/ + if (lit) glNormal3d(0.0,0.0,1.0); + glVertex3d(x, y, 0.0); + } else { + cberg->color->land(cberg, zcur); + if (lit) trile_light(cberg,ix,iy,which); + glVertex3d(x, y, zcur); + } +} + +static void trile_render(cberg_state *cberg, Trile *new) +{ + double cornerx = 0.5 * new->x - 0.5, cornery; + double dy = M_SQRT3_2 / (1 << nsubdivs); + double z0,z1,z2; + int x,y; + + new->call_list = glGenLists(1); + glNewList(new->call_list, GL_COMPILE); + + if ((new->x + new->y) % 2) { /*point down*/ + cornery = (new->y + 0.5)*M_SQRT3_2; + glFrontFace(GL_CW); + dy = -dy; + } else + cornery = (new->y - 0.5) * M_SQRT3_2; + + for (y = 0; y < cberg->epoints - 1; ++y) { + double dx = cberg->dx0; + glBegin(GL_TRIANGLE_STRIP); + /* first three points all part of the same triangle.. */ + z0 = TCOORD(0,y); + z1 = TCOORD(0,y+1); + z2 = TCOORD(1,y); + trile_draw_vertex(cberg, 0,y,0, + cornerx,cornery, z0, z1, z2); + trile_draw_vertex(cberg, 0,y,1, + cornerx+0.5*dx,cornery+dy, z1, z0, z2); + + for (x = 1; x < cberg->epoints - 1 - y; ++x) { + trile_draw_vertex(cberg, x,y,0, + cornerx+x*dx,cornery, z2, z1, z0); + + z0 = TCOORD(x, y+1); + + trile_draw_vertex(cberg, x,y,1, + cornerx+(x+0.5)*dx,cornery+dy, z0, z2, z1); + + z1 = z0; + z0 = z2; + z2 = TCOORD(x+1,y); + } + trile_draw_vertex(cberg, x,y,0, + cornerx + x*dx, cornery, z2, z1, z0); + glEnd(); + + cornerx += dx/2; + cornery += dy; + } + + if ((new->x + new->y) % 2) /*point down*/ + glFrontFace(GL_CCW); + glEndList(); +} + +static Trile *trile_new(cberg_state *cberg, int x,int y,Trile *parent,Trile *root) +{ + Trile *new; + + new = trile_alloc(cberg); + + new->x = x; + new->y = y; + new->state = TRILE_NEW; + new->parent = parent; + new->left = new->right = NULL; + new->visible = 1; + + new->morph = select_morph(); + new->morph->init(new); + + trile_calc_sides(cberg, new, x, y, root); + trile_calc_heights(cberg, new); + + if (lit) { + if (flat) trile_calc_flat_norms(cberg, new); + else trile_calc_smooth_norms(cberg, new); + } + + trile_render(cberg, new); + return new; +} + +static Trile *trile_alloc(cberg_state *cberg) +{ + Trile *new; + + if (cberg->free_head) { + new = cberg->free_head; + cberg->free_head = cberg->free_head->next_free; + } else { + ++cberg->count; + if (!(new = malloc(sizeof(Trile))) + || !(new->l = (double *) malloc(sizeof(double) * cberg->epoints * 3))) { + perror(progname); + exit(1); + } + new->r = new->l + cberg->epoints; + new->v = new->r + cberg->epoints; +#ifdef DEBUG + printf("needed to alloc; [%d]\n", cberg->count); +#endif + } + return new; +} + +static void trile_free(cberg_state *cberg, Trile *tr) +{ + glDeleteLists(tr->call_list, 1); + tr->morph->free(tr); + tr->next_free = cberg->free_head; + cberg->free_head = tr; +} + + +static void trile_draw_vanilla(Trile *tr) +{ glCallList(tr->call_list); } + +static void trile_draw(Trile *tr, void *ignore) +{ + if (tr->state == TRILE_STABLE) + trile_draw_vanilla(tr); + else + tr->morph->draw(tr); +} + + +/*************************** + ** Trile morph functions. + ** select function at bottom (forward decls sucls) + ** */ + + +/*** first the basic growing morph */ + +static void grow_init(Trile *tr) +{ + tr->morph_data = (void *) malloc(sizeof(double)); + *((double *)tr->morph_data) = 0.02; /* not 0; avoid normals crapping */ +} + +static void grow_free(Trile *tr) +{ + free(tr->morph_data); +} + +static void grow_draw(Trile *tr) +{ + glPushMatrix(); + glScaled(1.0,1.0, *((double *)tr->morph_data)); + trile_draw_vanilla(tr); + glPopMatrix(); +} + +static void grow_init_iter(Trile *tr, cberg_state *cberg) +{ + *((double *)(tr->morph_data)) = *((double *)tr->morph_data) + cberg->elapsed; + if (*((double *)tr->morph_data) >= 1.0) + tr->state = TRILE_STABLE; +} + +static void grow_dying_iter(Trile *tr, cberg_state *cberg) +{ + *((double *)tr->morph_data) = *((double *)tr->morph_data) - cberg->elapsed; + if (*((double *)tr->morph_data) <= 0.02) /* XXX avoid fast del/cons? */ + tr->state = TRILE_DELETE; +} + +/**** falling morph ****/ + +static void fall_init(Trile *tr) +{ + tr->morph_data = (void *) malloc(sizeof(double)); + *((double *)tr->morph_data) = 0.0; +} + +static void fall_free(Trile *tr) +{ + free(tr->morph_data); +} + +static void fall_draw(Trile *tr) +{ + glPushMatrix(); + glTranslated(0.0,0.0,(0.5 - *((double *)tr->morph_data)) * 8); + trile_draw_vanilla(tr); + glPopMatrix(); +} + +static void fall_init_iter(Trile *tr, cberg_state *cberg) +{ + *((double *)(tr->morph_data)) = *((double *)tr->morph_data) + cberg->elapsed; + if (*((double *)tr->morph_data) >= 0.5) + tr->state = TRILE_STABLE; +} + +static void fall_dying_iter(Trile *tr, cberg_state *cberg) +{ + *((double *)tr->morph_data) = *((double *)tr->morph_data) - cberg->elapsed; + if (*((double *)tr->morph_data) <= 0.0) /* XXX avoid fast del/cons? */ + tr->state = TRILE_DELETE; +} + +/**** yeast morph ****/ + +static void yeast_init(Trile *tr) +{ + tr->morph_data = (void *) malloc(sizeof(double)); + *((double *)tr->morph_data) = 0.02; +} + +static void yeast_free(Trile *tr) +{ + free(tr->morph_data); +} + +static void yeast_draw(Trile *tr) +{ + double x = tr->x * 0.5, + y = tr->y * M_SQRT3_2, + z = *((double *)tr->morph_data); + + glPushMatrix(); + glTranslated(x, y, 0); + glRotated(z*360, 0,0,1); + glScaled(z,z,z); + glTranslated(-x, -y, 0); + trile_draw_vanilla(tr); + glPopMatrix(); +} + +static void yeast_init_iter(Trile *tr, cberg_state *cberg) +{ + *((double *)(tr->morph_data)) = *((double *)tr->morph_data) + cberg->elapsed; + if (*((double *)tr->morph_data) >= 1.0) + tr->state = TRILE_STABLE; +} + +static void yeast_dying_iter(Trile *tr, cberg_state *cberg) +{ + *((double *)tr->morph_data) = *((double *)tr->morph_data) - cberg->elapsed; + if (*((double *)tr->morph_data) <= 0.02) /* XXX avoid fast del/cons? */ + tr->state = TRILE_DELETE; +} + +/**** identity morph ****/ + +static void identity_init(Trile *tr) +{ tr->state = TRILE_STABLE; } + +static void identity_free(Trile *tr) +{} + +static void identity_draw(Trile *tr) +{ trile_draw_vanilla(tr); } + +static void identity_init_iter(Trile *tr, cberg_state *cberg) +{} + +static void identity_dying_iter(Trile *tr, cberg_state *cberg) +{ tr->state = TRILE_DELETE; } + +/** now to handle selection **/ + +static const Morph morphs[] = { + {grow_init, grow_free, grow_draw, grow_init_iter, grow_dying_iter}, + {fall_init, fall_free, fall_draw, fall_init_iter, fall_dying_iter}, + {yeast_init, yeast_free, yeast_draw, yeast_init_iter, yeast_dying_iter}, + {identity_init, /*always put identity last to skip it..*/ + identity_free, identity_draw, identity_init_iter, identity_dying_iter} +}; + +static const Morph *select_morph() +{ + int nmorphs = countof(morphs); + if (crack) + return &morphs[random() % (nmorphs-1)]; + else if (boring) + return &morphs[nmorphs-1]; + else + return morphs; +} + + +/*************************** + ** Trile superstructure functions. + ** */ + + +static void triles_set_visible(cberg_state *cberg, Trile **root, int x, int y) +{ + Trile *parent = NULL, + *iter = *root; + int goleft=0; + + while (iter != NULL) { + parent = iter; + goleft = (iter->x > x || (iter->x == x && iter->y > y)); + if (goleft) + iter = iter->left; + else if (iter->x == x && iter->y == y) { + iter->visible = 1; + return; + } else + iter = iter->right; + } + + if (parent == NULL) + *root = trile_new(cberg, x,y, NULL, NULL); + else if (goleft) + parent->left = trile_new(cberg, x,y, parent, *root); + else + parent->right = trile_new(cberg, x,y, parent, *root); +} + +static unsigned int triles_foreach(Trile *root, void (*f)(Trile *, void *), + void *data) +{ + if (root == NULL) + return 0; + + f(root, data); + return 1 + triles_foreach(root->left, f, data) + + triles_foreach(root->right, f, data); +} + +static void triles_update_state(Trile **root, cberg_state *cberg) +{ + int process_current = 1; + if (*root == NULL) + return; + + while (process_current) { + if ( (*root)->visible ) { + if ( (*root)->state == TRILE_INIT ) + (*root)->morph->init_iter(*root, cberg); + else if ( (*root)->state == TRILE_DYING ) { + (*root)->state = TRILE_INIT; + (*root)->morph->init_iter(*root, cberg); + } else if ( (*root)->state == TRILE_NEW ) + (*root)->state = TRILE_INIT; + + (*root)->visible = 0; + } else { + if ( (*root)->state == TRILE_STABLE ) + (*root)->state = TRILE_DYING; + else if ( (*root)->state == TRILE_INIT ) { + (*root)->state = TRILE_DYING; + (*root)->morph->dying_iter(*root, cberg); + } else if ( (*root)->state == TRILE_DYING ) + (*root)->morph->dying_iter(*root, cberg); + } + + if ( (*root)->state == TRILE_DELETE ) { + Trile *splice_me; + process_current = 1; + + if ((*root)->left == NULL) { + splice_me = (*root)->right; + if (splice_me) + splice_me->parent = (*root)->parent; + else + process_current = 0; + } else if ((*root)->right == NULL) { + splice_me = (*root)->left; + splice_me->parent = (*root)->parent; + } else { + Trile *tmp; + for (splice_me = (*root)->right; splice_me->left != NULL; ) + splice_me = splice_me->left; + tmp = splice_me->right; + + if (tmp) tmp->parent = splice_me->parent; + + if (splice_me == splice_me->parent->left) + splice_me->parent->left = tmp; + else + splice_me->parent->right = tmp; + + splice_me->parent = (*root)->parent; + splice_me->left = (*root)->left; + (*root)->left->parent = splice_me; + splice_me->right = (*root)->right; + if ((*root)->right) + (*root)->right->parent = splice_me; + } + trile_free(cberg, *root); + *root = splice_me; + } else + process_current = 0; + } + + if (*root) { + triles_update_state(&((*root)->left), cberg); + triles_update_state(&((*root)->right), cberg); + } +} + +static Trile *triles_find(Trile *tr, int x, int y) +{ + while (tr && !(tr->x == x && tr->y == y)) + if (x < tr->x || (x == tr->x && y < tr->y)) + tr = tr->left; + else + tr = tr->right; + return tr; +} + + +/*************************** + ** Trile superstructure visibility functions. + ** strategy fine, implementation lazy&retarded =/ + ** */ + +#ifdef DEBUG +static double x_shit, y_shit; +#endif + +static void calc_points(cberg_state *cberg, double *x1,double *y1, + double *x2,double *y2, double *x3,double *y3, double *x4,double *y4) +{ + double zNear, x_nearcenter, y_nearcenter, nhalfwidth, x_center, y_center; + + + /* could cache these.. bahhhhhhhhhhhhhh */ + double halfheight = tan(cberg->fovy / 2 * M_PI_180) * cberg->zNear; + double fovx_2 = atan(halfheight * cberg->aspect / cberg->zNear) * M_180_PI; + double zFar = cberg->zFar + M_RAD7_4; + double fhalfwidth = zFar * tan(fovx_2 * M_PI_180) + + M_RAD7_4 / cos(fovx_2 * M_PI_180); + double x_farcenter = cberg->x + zFar * cos(cberg->yaw * M_PI_180); + double y_farcenter = cberg->y + zFar * sin(cberg->yaw * M_PI_180); + *x1 = x_farcenter + fhalfwidth * cos((cberg->yaw - 90) * M_PI_180); + *y1 = y_farcenter + fhalfwidth * sin((cberg->yaw - 90) * M_PI_180); + *x2 = x_farcenter - fhalfwidth * cos((cberg->yaw - 90) * M_PI_180); + *y2 = y_farcenter - fhalfwidth * sin((cberg->yaw - 90) * M_PI_180); + +#ifdef DEBUG + printf("pos (%.3f,%.3f) @ %.3f || fovx: %f || fovy: %f\n", + cberg->x, cberg->y, cberg->yaw, fovx_2 * 2, cberg->fovy); + printf("\tfarcenter: (%.3f,%.3f) || fhalfwidth: %.3f \n" + "\tp1: (%.3f,%.3f) || p2: (%.3f,%.3f)\n", + x_farcenter, y_farcenter, fhalfwidth, *x1, *y1, *x2, *y2); +#endif + + if (cberg->z - halfheight <= 0) /* near view plane hits xy */ + zNear = cberg->zNear - M_RAD7_4; + else /* use bottom of frustum */ + zNear = cberg->z / tan(cberg->fovy / 2 * M_PI_180) - M_RAD7_4; + nhalfwidth = zNear * tan(fovx_2 * M_PI_180) + + M_RAD7_4 / cos(fovx_2 * M_PI_180); + x_nearcenter = cberg->x + zNear * cos(cberg->yaw * M_PI_180); + y_nearcenter = cberg->y + zNear * sin(cberg->yaw * M_PI_180); + *x3 = x_nearcenter - nhalfwidth * cos((cberg->yaw - 90) * M_PI_180); + *y3 = y_nearcenter - nhalfwidth * sin((cberg->yaw - 90) * M_PI_180); + *x4 = x_nearcenter + nhalfwidth * cos((cberg->yaw - 90) * M_PI_180); + *y4 = y_nearcenter + nhalfwidth * sin((cberg->yaw - 90) * M_PI_180); + +#ifdef DEBUG + printf("\tnearcenter: (%.3f,%.3f) || nhalfwidth: %.3f\n" + "\tp3: (%.3f,%.3f) || p4: (%.3f,%.3f)\n", + x_nearcenter, y_nearcenter, nhalfwidth, *x3, *y3, *x4, *y4); +#endif + + + /* center can be average or the intersection of diagonals.. */ +#if 0 + { + double c = nhalfwidth * (zFar -zNear) / (fhalfwidth + nhalfwidth); + x_center = x_nearcenter + c * cos(cberg->yaw * M_PI_180); + y_center = y_nearcenter + c * sin(cberg->yaw * M_PI_180); + } +#else + x_center = (x_nearcenter + x_farcenter) / 2; + y_center = (y_nearcenter + y_farcenter) / 2; +#endif +#ifdef DEBUG + x_shit = x_center; + y_shit = y_center; +#endif + +#define VSCALE(p) *x##p = visibility * *x##p + (1-visibility) * x_center; \ + *y##p = visibility * *y##p + (1-visibility) * y_center + + VSCALE(1); + VSCALE(2); + VSCALE(3); + VSCALE(4); +#undef VSCALE +} + +/* this is pretty stupid.. */ +static inline void minmax4(double a, double b, double c, double d, + double *min, double *max) +{ + *min = *max = a; + + if (b > *max) *max = b; + else if (b < *min) *min = b; + if (c > *max) *max = c; + else if (c < *min) *min = c; + if (d > *max) *max = d; + else if (d < *min) *min = d; +} + +typedef struct { + double min, max, start, dx; +} LS; + +#define check_line(a, b) \ + if (fabs(y##a-y##b) > 0.001) { \ + ls[count].dx = (x##b-x##a)/(y##b-y##a); \ + if (y##b > y##a) { \ + ls[count].start = x##a; \ + ls[count].min = y##a; \ + ls[count].max = y##b; \ + } else { \ + ls[count].start = x##b; \ + ls[count].min = y##b; \ + ls[count].max = y##a; \ + } \ + ++count; \ + } + +static unsigned int build_ls(cberg_state *cberg, + double x1, double y1, double x2, double y2, + double x3, double y3, double x4, double y4, LS *ls, + double *trough, double *peak) +{ + unsigned int count = 0; + + check_line(1, 2); + check_line(2, 3); + check_line(3, 4); + check_line(4, 1); + + minmax4(y1, y2, y3, y4, trough, peak); + return count; +} + +#undef check_line + +/*needs bullshit to avoid double counts on corners.*/ +static void find_bounds(double y, double *left, double *right, LS *ls, + unsigned int nls) +{ + double x; + unsigned int i, set = 0; + + for (i = 0; i != nls; ++i) + if (ls[i].min <= y && ls[i].max >= y) { + x = (y - ls[i].min) * ls[i].dx + ls[i].start; + if (!set) { + *left = x; + ++set; + } else if (fabs(x - *left) > 0.001) { + if (*left < x) + *right = x; + else { + *right = *left; + *left = x; + } + return; + } + } + + /* just in case we somehow blew up */ + *left = 3.0; + *right = -3.0; +} + +static void mark_visible(cberg_state *cberg) +{ + double trough, peak, yval, left=0, right=0; + double x1,y1, x2,y2, x3,y3, x4,y4; + int start, stop, x, y; + LS ls[4]; + unsigned int nls; + + calc_points(cberg, &x1,&y1, &x2,&y2, &x3,&y3, &x4,&y4); + nls = build_ls(cberg, x1,y1, x2,y2, x3,y3, x4,y4, ls, &trough, &peak); + + start = (int) ceil(trough / M_SQRT3_2); + stop = (int) floor(peak / M_SQRT3_2); + + for (y = start; y <= stop; ++y) { + yval = y * M_SQRT3_2; + find_bounds(yval, &left, &right, ls, nls); + for (x = (int) ceil(left*2-1); x <= (int) floor(right*2); ++x) + triles_set_visible(cberg, &(cberg->trile_head), x, y); + } +} + + +/*************************** + ** color schemes + ** */ + +static void plain_land(cberg_state *cberg, double z) +{ glColor3f(pow((z/0.35),4), z/0.35, pow((z/0.35),4)); } +static void plain_water(cberg_state *cberg, double z) +{ glColor3f(0.0, (z+0.35)*1.6, 0.8); } + +static void ice_land(cberg_state *cberg, double z) +{ glColor3f((0.35 - z)/0.35, (0.35 - z)/0.35, 1.0); } +static void ice_water(cberg_state *cberg, double z) +{ glColor3f(0.0, (z+0.35)*1.6, 0.8); } + + +static void magma_land(cberg_state *cberg, double z) +{ glColor3f(z/0.35, z/0.2,0); } +static void magma_lava(cberg_state *cberg, double z) +{ glColor3f((z+0.35)*1.6, (z+0.35), 0.0); } + +static void vomit_solid(cberg_state *cberg, double z) +{ + double norm = fabs(z) / 0.35; + glColor3f( + (1-norm) * cberg->vs0r + norm * cberg->vs1r, + (1-norm) * cberg->vs0g + norm * cberg->vs1g, + (1-norm) * cberg->vs0b + norm * cberg->vs1b + ); +} +static void vomit_fluid(cberg_state *cberg, double z) +{ + double norm = z / -0.35; + glColor3f( + (1-norm) * cberg->vf0r + norm * cberg->vf1r, + (1-norm) * cberg->vf0g + norm * cberg->vf1g, + (1-norm) * cberg->vf0b + norm * cberg->vf1b + ); +} + + +static const Color colors[] = { + {"plain", plain_land, plain_water, {0.0, 0.0, 0.0, 1.0}}, + {"ice", ice_land, ice_water, {0.0, 0.0, 0.0, 1.0}}, + {"magma", magma_land, magma_lava, {0.3, 0.3, 0.0, 1.0}}, + {"vomit", vomit_solid, vomit_fluid, {0.3, 0.3, 0.0, 1.0}}, /* no error! */ +}; + +static const Color *select_color(cberg_state *cberg) +{ + unsigned int ncolors = countof(colors); + int idx = -1; + if ( ! strcmp(color, "random") ) + idx = random() % ncolors; + else { + unsigned int i; + for (i = 0; i != ncolors; ++i) + if ( ! strcmp(colors[i].id, color) ) { + idx = i; + break; + } + + if (idx == -1) { + printf("invalid color scheme selected; valid choices are:\n"); + for (i = 0; i != ncolors; ++i) + printf("\t%s\n", colors[i].id); + printf("\t%s\n", "random"); + idx = 0; + } + } + + if ( ! strcmp(colors[idx].id, "vomit") ) { /* need to create it (ghetto) */ + cberg->vs0r = random()/(double)RAND_MAX; + cberg->vs0g = random()/(double)RAND_MAX; + cberg->vs0b = random()/(double)RAND_MAX; + cberg->vs1r = random()/(double)RAND_MAX; + cberg->vs1g = random()/(double)RAND_MAX; + cberg->vs1b = random()/(double)RAND_MAX; + cberg->vf0r = random()/(double)RAND_MAX; + cberg->vf0g = random()/(double)RAND_MAX; + cberg->vf0b = random()/(double)RAND_MAX; + cberg->vf1r = random()/(double)RAND_MAX; + cberg->vf1g = random()/(double)RAND_MAX; + cberg->vf1b = random()/(double)RAND_MAX; + + glClearColor(random()/(double)RAND_MAX, + random()/(double)RAND_MAX, + random()/(double)RAND_MAX, + 1.0); + } else { + glClearColor(colors[idx].bg[0], + colors[idx].bg[1], + colors[idx].bg[2], + colors[idx].bg[3]); + } + return colors + idx; +} + + +/*************************** + ** misc helper functions + ** */ + + +/* simple one for now.. */ +static inline double drunken_rando(double cur_val, double max, double width) +{ + double r = random() / (double) RAND_MAX * 2; + if (cur_val > 0) + if (r >= 1) + return cur_val + (r-1) * width * (1-cur_val/max); + else + return cur_val - r * width; + else + if (r >= 1) + return cur_val - (r-1) * width * (1+cur_val/max); + else + return cur_val + r * width; +} + + +/*************************** + ** core crackberg routines + ** */ + +ENTRYPOINT void reshape_crackberg (ModeInfo *mi, int w, int h); + +ENTRYPOINT void init_crackberg (ModeInfo *mi) +{ + cberg_state *cberg; + + if (!cbergs) { + nsubdivs %= 16; /* just in case.. */ + + if ( !(cbergs = calloc(MI_NUM_SCREENS(mi), sizeof(cberg_state)))) { + perror(progname); + exit(1); + } + + if (visibility > 1.0 || visibility < 0.2) { + printf("visibility must be in range [0.2 .. 1.0]\n"); + visibility = 1.0; + } + } + + cberg = &cbergs[MI_SCREEN(mi)]; + + cberg->epoints = 1 + (1 << nsubdivs); + cberg->tpoints = cberg->epoints * (cberg->epoints + 1) / 2; + cberg->ntris = (1 << (nsubdivs << 1)); + cberg->tnorms = ( (flat) ? cberg->ntris : cberg->tpoints); + cberg->dx0 = 1.0 / (1 << nsubdivs); + + cberg->heights = malloc(cberg->tpoints * sizeof(double)); + cberg->norms = malloc(3 * cberg->tnorms * sizeof(double)); + + cberg->glx_context = init_GL(mi); + cberg->motion_state = MOTION_AUTO; + cberg->mspeed = 1.0; + cberg->z = 0.5; + + cberg->fovy = 60.0; + cberg->zNear = 0.5; + cberg->zFar = 5.0; + + cberg->draw_elapsed = 1.0; + + glEnable(GL_DEPTH_TEST); + glEnable(GL_BLEND); + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + glShadeModel((flat) ? GL_FLAT : GL_SMOOTH); +# ifndef HAVE_JWZGLES /* #### glPolygonMode other than GL_FILL unimplemented */ + glPolygonMode(GL_FRONT_AND_BACK, (MI_IS_WIREFRAME(mi)) ? GL_LINE : GL_FILL); +# endif + + if (lit) { + glEnable(GL_LIGHTING); + glEnable(GL_LIGHT0); + glEnable(GL_COLOR_MATERIAL); + glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, GL_TRUE); + glColorMaterial(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE); + glEnable(GL_NORMALIZE); + glEnable(GL_RESCALE_NORMAL); + } + + cberg->color = select_color(cberg); + + reshape_crackberg(mi, MI_WIDTH(mi), MI_HEIGHT(mi)); +} + +ENTRYPOINT void reshape_crackberg (ModeInfo *mi, int w, int h) +{ + int h2; + cberg_state *cberg = &cbergs[MI_SCREEN(mi)]; + + if (letterbox && (h2 = w * 9 / 16) < h) { + glViewport(0, (h-h2)/2, w, h2); + cberg->aspect = w/(double)h2; + } else { + glViewport (0, 0, w, h); + cberg->aspect = w/(double)h; + } + + glMatrixMode(GL_PROJECTION); + glLoadIdentity(); + gluPerspective(cberg->fovy, cberg->aspect, cberg->zNear, cberg->zFar); + glMatrixMode(GL_MODELVIEW); +} + +ENTRYPOINT Bool crackberg_handle_event (ModeInfo *mi, XEvent *ev) +{ + cberg_state *cberg = &cbergs[MI_SCREEN(mi)]; + KeySym keysym = 0; + char c = 0; + if (ev->xany.type == KeyPress || ev->xany.type == KeyRelease) + XLookupString (&ev->xkey, &c, 1, &keysym, 0); + + if (ev->xany.type == KeyPress) { + switch (keysym) { + case XK_Left: cberg->motion_state |= MOTION_LROT; break; + case XK_Right: cberg->motion_state |= MOTION_RROT; break; + case XK_Down: cberg->motion_state |= MOTION_BACK; break; + case XK_Up: cberg->motion_state |= MOTION_FORW; break; + case '1': cberg->motion_state |= MOTION_DEC; break; + case '2': cberg->motion_state |= MOTION_INC; break; + case 'a': cberg->motion_state |= MOTION_LEFT; break; + case 'd': cberg->motion_state |= MOTION_RIGHT; break; + case 's': cberg->motion_state |= MOTION_BACK; break; + case 'w': cberg->motion_state |= MOTION_FORW; break; + default: return False; + } + cberg->motion_state |= MOTION_MANUAL; + } else if (ev->xany.type == KeyRelease) { +#if 0 + XEvent peek_ev; + if (XPending(mi->dpy)) { + XPeekEvent(mi->dpy, &peek_ev); + if (peek_ev.type == KeyPress + && peek_ev.xkey.keycode == ev->xkey.keycode + && peek_ev.xkey.time - ev->xkey.time < 2) { + XNextEvent(mi->dpy, &peek_ev); /* drop bullshit repeat events */ + return False; + } + } +#endif + + switch (keysym) { + case XK_Left: cberg->motion_state &= ~MOTION_LROT; break; + case XK_Right: cberg->motion_state &= ~MOTION_RROT; break; + case XK_Down: cberg->motion_state &= ~MOTION_BACK; break; + case XK_Up: cberg->motion_state &= ~MOTION_FORW; break; + case '1': cberg->motion_state &= ~MOTION_DEC; break; + case '2': cberg->motion_state &= ~MOTION_INC; break; + case 'a': cberg->motion_state &= ~MOTION_LEFT; break; + case 'd': cberg->motion_state &= ~MOTION_RIGHT; break; + case 's': cberg->motion_state &= ~MOTION_BACK; break; + case 'w': cberg->motion_state &= ~MOTION_FORW; break; + case ' ': + if (cberg->motion_state == MOTION_MANUAL) + cberg->motion_state = MOTION_AUTO; + break; + default: return False; + } + } else if (ev->xany.type == ButtonPress && + ev->xbutton.button == Button1) { + cberg->button_down_p = True; + cberg->mouse_x = ev->xbutton.x; + cberg->mouse_y = ev->xbutton.y; + cberg->motion_state = MOTION_MANUAL; + cberg->paused.tv_sec = 0; + } else if (ev->xany.type == ButtonRelease && + ev->xbutton.button == Button1) { + cberg->button_down_p = False; + cberg->motion_state = MOTION_AUTO; + /* After mouse-up, don't go back into auto-motion mode for a second, so + that repeated click-and-drag gestures don't fight with auto-motion. */ + gettimeofday(&cberg->paused, NULL); + } else if (ev->xany.type == MotionNotify && + cberg->button_down_p) { + int dx = ev->xmotion.x - cberg->mouse_x; + int dy = ev->xmotion.y - cberg->mouse_y; + cberg->mouse_x = ev->xmotion.x; + cberg->mouse_y = ev->xmotion.y; + cberg->motion_state = MOTION_MANUAL; + + /* Take the larger dimension, since motion_state doesn't scale */ + if (dx > 0 && dx > dy) dy = 0; + if (dx < 0 && dx < dy) dy = 0; + if (dy > 0 && dy > dx) dx = 0; + if (dy < 0 && dy < dx) dx = 0; + + if (dx > 0) cberg->motion_state |= MOTION_LEFT; + else if (dx < 0) cberg->motion_state |= MOTION_RIGHT; + else if (dy > 0) cberg->motion_state |= MOTION_FORW; + else if (dy < 0) cberg->motion_state |= MOTION_BACK; + } else + return False; + return True; +} + +ENTRYPOINT void draw_crackberg (ModeInfo *mi) +{ + cberg_state *cberg = &cbergs[MI_SCREEN(mi)]; + struct timeval cur_frame_t; + double cur_frame; + static const float lpos[] = {2.0,0.0,-0.3,0.0}; + + if (!cberg->glx_context) /*XXX does this get externally tweaked? it kinda*/ + return; /*XXX can't.. check it in crackberg_init*/ + + glXMakeCurrent(MI_DISPLAY(mi), MI_WINDOW(mi), *(cberg->glx_context)); + + gettimeofday(&cur_frame_t, NULL); + cur_frame = cur_frame_t.tv_sec + cur_frame_t.tv_usec / 1.0E6; + if ( cberg->prev_frame ) { /*not first run */ + + cberg->elapsed = cur_frame - cberg->prev_frame; + + if (cberg->motion_state == MOTION_AUTO && + cberg->paused.tv_sec < cur_frame_t.tv_sec) { + cberg->x += cberg->dx * cberg->elapsed; + cberg->y += cberg->dy * cberg->elapsed; + /* cberg->z */ + /* cberg->pitch */ + /* cberg->roll */ + cberg->yaw += cberg->dyaw * cberg->elapsed; + + cberg->draw_elapsed += cberg->elapsed; + if (cberg->draw_elapsed >= 0.8) { + cberg->draw_elapsed = 0.0; + cberg->dx = drunken_rando(cberg->dx, 2.5, 0.8); + cberg->dy = drunken_rando(cberg->dy, 2.5, 0.8); + /* cberg->dz */ + /* cberg->dpitch */ + /* cberg->droll */ + cberg->dyaw = drunken_rando(cberg->dyaw, 40.0, 8.0); + } + } else { + double scale = cberg->elapsed * cberg->mspeed; + if (cberg->motion_state & MOTION_BACK) { + cberg->x -= cos(cberg->yaw * M_PI_180) * scale; + cberg->y -= sin(cberg->yaw * M_PI_180) * scale; + } + if (cberg->motion_state & MOTION_FORW) { + cberg->x += cos(cberg->yaw * M_PI_180) * scale; + cberg->y += sin(cberg->yaw * M_PI_180) * scale; + } + + if (cberg->motion_state & MOTION_LEFT) { + cberg->x -= sin(cberg->yaw * M_PI_180) * scale; + cberg->y += cos(cberg->yaw * M_PI_180) * scale; + } + if (cberg->motion_state & MOTION_RIGHT) { + cberg->x += sin(cberg->yaw * M_PI_180) * scale; + cberg->y -= cos(cberg->yaw * M_PI_180) * scale; + } + + if (cberg->motion_state & MOTION_LROT) + cberg->yaw += 45 * scale; + if (cberg->motion_state & MOTION_RROT) + cberg->yaw -= 45 * scale; + + if (cberg->motion_state & MOTION_DEC) + cberg->mspeed /= pow(MSPEED_SCALE, cberg->draw_elapsed); + if (cberg->motion_state & MOTION_INC) + cberg->mspeed *= pow(MSPEED_SCALE, cberg->draw_elapsed); + + } + } + cberg->prev_frame = cur_frame; + + mark_visible(cberg); + triles_update_state(&(cberg->trile_head), cberg); + + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + glLoadIdentity(); + glRotatef(current_device_rotation(), 0, 0, 1); + gluLookAt(0,0,0, 1,0,0, 0,0,1); + glLightfv(GL_LIGHT0, GL_POSITION, lpos); + /*glRotated(cberg->roll, 1,0,0); / * XXX blah broken and unused for now..* / + glRotated(cberg->pitch, 0,1,0); */ + glRotated(-cberg->yaw, 0,0,1); /* camera sees ->yaw over */ + glTranslated(-cberg->x, -cberg->y, -cberg->z); + + mi->polygon_count = cberg->ntris * + triles_foreach(cberg->trile_head, trile_draw,(void *) cberg); + + if (mi->fps_p) + do_fps(mi); + +#ifdef DEBUG + glBegin(GL_LINES); + glColor3f(1.0,0.0,0.0); + glVertex3d(x_shit, y_shit, 0.0); + glVertex3d(x_shit, y_shit, 1.0); + glEnd(); +#endif + + glFinish(); + glXSwapBuffers(MI_DISPLAY(mi), MI_WINDOW(mi)); +} + +/* uh */ +ENTRYPOINT void release_crackberg (ModeInfo *mi) +{ + if (cbergs) { + int screen; + for (screen = 0; screen < MI_NUM_SCREENS(mi); screen++) { + cberg_state *cberg = &cbergs[screen]; + if (cberg->norms) + free(cberg->norms); + free(cberg->heights); + } + free (cbergs); + cbergs = 0; + } +} + +XSCREENSAVER_MODULE ("Crackberg", crackberg) + +#endif /* USE_GL */ diff --git a/hacks/glx/crackberg.man b/hacks/glx/crackberg.man new file mode 100644 index 00000000..5183baa3 --- /dev/null +++ b/hacks/glx/crackberg.man @@ -0,0 +1,123 @@ +.TH XScreenSaver 1 "" "X Version 11" +.SH NAME +crackberg - Lose your way wandering some height fields, and enjoy candy. +.SH SYNOPSIS +.B crackberg +[\-root] +[\-window] +[\-install] +[\-display \fIhost:display.screen\fP] +[\-visual \fIvisual\fP] +[\-window-id \fIid\fP] +[\-delay \fIusecs\fP] +[\-fps] +[\-crack] +[\-lit] +[\-boring] +[\-letterbox] +[\-flat] +[\-wire] +[\-nowater] +[\-visibility \fIfloat\fP] +[\-color \fIstring\fP] +[\-nsubdivs \fIinteger\fP] +.SH DESCRIPTION +Flies through height maps, optionally animating the instantiation and +destruction of generated tiles; by default, tiles 'grow' into place (height +gradually increased up to correct value). In windowed mode the following key +controls are available: +.TP 8 +.B left, right +Turn left and right. +.TP 8 +.B a,w,s,d +Move left, forwards, backwards, and to the right, respectively. +.TP 8 +.B 1,2 +Decrease and increase manual speed, respectively. +.TP 8 +.B Spacebar +Return to automatic control. +.SH OPTIONS +.I crackberg +accepts the following options: +.TP 8 +.B \-root +Draw on the root window. +.TP 8 +.B \-window +Draw on a newly-created window. This is the default. +.TP 8 +.B \-install +Install a private colormap for the window. +.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 \-delay \fImicroseconds\fP +Delay between frames; default 20000 (1/50th of a second). +.TP 8 +.B \-fps +Display the current frame rate, CPU load, and polygon count. +.TP 8 +.B \-crack +Use all possible methods to animate tile instantiation. +.TP 8 +.B \-boring +Do not animate instatiation at all; use this to get standard landscape +generator behavior. +.TP 8 +.B \-letterbox +Drawable window region has a 16:9 aspect ratio, regardless of actual +window size. +.TP 8 +.B \-lit +Enable lighting. +.TP 8 +.B \-flat +Flat shading (OpenGL will use one color per primitive, rather than +interpolating betwixt vertices). +.TP 8 +.B \-wire +Wireframe. +.TP 8 +.B \-nowater +Do not display 'water' (forces negative values to zero, and selects a +different coloring method). +.TP 8 +.B \-visibility \fIfloat\fP +Value in range [0.2,1.0] (default 0.6) specifying proportion of viewable +XY plane which is to be drawn upon. +.TP 8 +.B \-color \fIstring\fP +Selects color scheme. Use with no or bogus argument for current list. +.TP 8 +.B \-nsubdivs \fIinteger\fP +Number of times to recursively subdivide each triangular tile. Each +increment increases total triangles by a factor of 4; for instance the default +setting 4 results in 256 triangles per tile. + +.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 2005 by Matus Telgarsky. 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 +Matus Telgarsky , 2005. diff --git a/hacks/glx/cube21.c b/hacks/glx/cube21.c new file mode 100644 index 00000000..7e2ae172 --- /dev/null +++ b/hacks/glx/cube21.c @@ -0,0 +1,968 @@ +/*- + * Permission to use, copy, modify, and distribute this software and its + * documentation for any purpose and without fee is hereby granted, + * provided that the above copyright notice appear in all copies and that + * both that copyright notice and this permission notice appear in + * supporting documentation. + * + * This file is provided AS IS with no warranties of any kind. The author + * shall have no liability with respect to the infringement of copyrights, + * trade secrets or any patents by this file or any part thereof. In no + * event will the author be liable for any lost revenue or profits or + * other special, indirect and consequential damages. + * + * Cube 21 - a Rubik-like puzzle. It changes its shape and has more than + * 200 configurations. It is known better as Square-1, but it is called + * Cube 21 in the Czech republic, where it was invented in 1992. + * + * This file is derived from cage.c, + * "cage --- the Impossible Cage, an Escher like scene", + * by Marcelo F. Vienna, + * parts from gltext.c by Jamie Zawinski + * + * Vaclav (Vasek) Potocek + * vasek.potocek@post.cz + */ + +/* TODO: + * some simple "solve mode" + * use rotator + */ + +/*- + * Texture mapping is only available on RGBA contexts, Mono and color index + * visuals DO NOT support texture mapping in OpenGL. + * + * BUT Mesa do implements RGBA contexts in pseudo color visuals, so texture + * mapping should work on PseudoColor, DirectColor, TrueColor using Mesa. Mono + * is not officially supported for both OpenGL and Mesa, but seems to not crash + * Mesa. + * + * In real OpenGL, PseudoColor DO NOT support texture map (as far as I know). + */ + +#define DEFAULTS "*delay: 20000 \n" \ + "*showFPS: False \n" \ + "*wireframe: False \n" + +# define refresh_cube21 0 +#include "xlockmore.h" + +#include "gltrackball.h" + +#ifdef USE_GL + +#define DEF_SPIN "True" +#define DEF_WANDER "True" +#define DEF_TEXTURE "True" +#define DEF_RANDOMIZE "True" +#define DEF_SPINSPEED "1.0" +#define DEF_ROTSPEED "3.0" +#define DEF_WANDERSPEED "0.02" +#define DEF_WAIT "40.0" +#define DEF_CUBESIZE "0.7" +#define DEF_COLORMODE "six" + +#ifdef Pi +#undef Pi +#endif +#define Pi M_PI + +#define SHUFFLE 100 + +#define COS15 0.9659258263 +#define SIN15 0.2588190451 +#define COS30 0.8660254038 +#define SIN30 0.5000000000 + +#define TEX_WIDTH 128 +#define TEX_HEIGHT 128 +#define TEX_GRAY 0.7, 0.7 +#define BORDER 3 +#define BORDER2 9 + +#undef countof +#define countof(x) (sizeof((x))/sizeof((*x))) + +#define rnd01() (random()%2) +#define rndcolor() (frand(0.5)+0.3) + +/*************************************************************************/ + +static Bool spin, wander, rndstart, tex; +static float spinspeed, tspeed, wspeed, twait, size; +static char *colmode_s; +static int colmode; + +static argtype vars[] = { + { &spin, "spin", "Spin", DEF_SPIN, t_Bool}, + { &wander, "wander", "Wander", DEF_WANDER, t_Bool}, + { &rndstart, "randomize", "Randomize", DEF_RANDOMIZE, t_Bool}, + { &tex, "texture", "Texture", DEF_TEXTURE, t_Bool}, + { &spinspeed, "spinspeed", "SpinSpeed", DEF_SPINSPEED, t_Float}, + { &tspeed, "rotspeed", "RotSpeed", DEF_ROTSPEED, t_Float}, + { &wspeed, "wanderspeed", "WanderSpeed", DEF_WANDERSPEED, t_Float}, + { &twait, "wait", "Wait", DEF_WAIT, t_Float}, + { &size, "cubesize", "CubeSize", DEF_CUBESIZE, t_Float}, + { &colmode_s, "colormode", "ColorMode", DEF_COLORMODE, t_String} +}; + +static XrmOptionDescRec opts[] = { + { "-spin", ".spin", XrmoptionNoArg, "True" }, + { "+spin", ".spin", XrmoptionNoArg, "False" }, + { "-wander", ".wander", XrmoptionNoArg, "True" }, + { "+wander", ".wander", XrmoptionNoArg, "False" }, + { "-randomize", ".randomize", XrmoptionNoArg, "True" }, + { "+randomize", ".randomize", XrmoptionNoArg, "False" }, + { "-texture", ".texture", XrmoptionNoArg, "True" }, + { "+texture", ".texture", XrmoptionNoArg, "False" }, + { "-spinspeed", ".spinspeed", XrmoptionSepArg, 0 }, + { "-wanderspeed", ".wanderspeed", XrmoptionSepArg, 0 }, + { "-rotspeed", ".rotspeed", XrmoptionSepArg, 0 }, + { "-wait", ".wait", XrmoptionSepArg, 0 }, + { "-cubesize", ".cubesize", XrmoptionSepArg, 0 }, + { "-colormode", ".colormode", XrmoptionSepArg, 0 } +}; + +ENTRYPOINT ModeSpecOpt cube21_opts = {countof(opts), opts, countof(vars), vars, NULL}; + +#ifdef USE_MODULES +ModStruct cube21_description = +{ "cube21", "init_cube21", "draw_cube21", "release_cube21", + "draw_cube21", "change_cube21", NULL, &cube21_opts, + 25000, 1, 1, 1, 1.0, 4, "", + "Shows randomly shuffling Cube 21", 0, NULL +}; +#endif + +typedef enum { + CUBE21_STATE_BASIC, + CUBE21_PAUSE1 = CUBE21_STATE_BASIC, + CUBE21_ROT_BASE, + CUBE21_ROT_TOP = CUBE21_ROT_BASE, + CUBE21_ROT_BOTTOM, + CUBE21_PAUSE2, + CUBE21_HALF_BASE, + CUBE21_HALF1 = CUBE21_HALF_BASE, + CUBE21_HALF2 +} cube21_state; + +typedef enum { + CUBE21_COLOR_WHITE, + CUBE21_COLOR_RANDOM, + CUBE21_COLOR_SILVER, + CUBE21_COLOR_TWORND, + CUBE21_COLOR_CLASSIC, + CUBE21_COLOR_SIXRND +} cube21_cmode; + +typedef int pieces_t[2][13]; +typedef int cind_t[5][12]; +typedef GLfloat col_t[6][3]; + +typedef struct { + GLXContext *glx_context; + GLfloat ratio; + cube21_state state; /* type of "rotation" - shuffling */ + GLfloat xrot, yrot; /* "spin" - object rotation around axis */ + GLfloat posarg; /* position argument (for sine function) */ + GLfloat t, tmax; /* rotation clock */ + int hf[2], fr[2]; /* half flipped / face rotated flags */ + int rface, ramount; /* selected face and amount of rotation in multiplies of 30deg */ + int pieces[2][13]; /* locations of "narrow" and "wide" pieces */ + int cind[5][12]; /* color indices */ + GLfloat colors[6][3]; /* color map */ + + Bool wire, cmat; + unsigned char texture[TEX_HEIGHT][TEX_WIDTH]; + + GLfloat texp, texq, posc[6]; + GLfloat color_inner[4]; + + Bool button_down_p; + trackball_state *trackball; + +} cube21_conf; + +static cube21_conf *cube21 = NULL; + +static const GLfloat shininess = 20.0; +static const GLfloat ambient[] = {0.0, 0.0, 0.0, 1.0}; +static const GLfloat diffuse[] = {1.0, 1.0, 1.0, 1.0}; +static const GLfloat position0[] = {1.0, 1.0, 1.0, 0.0}; +static const GLfloat position1[] = {-1.0, -1.0, 1.0, 0.0}; +static const GLfloat lmodel_ambient[] = {0.1, 0.1, 0.1, 1.0}; +static const GLfloat material_ambient[] = {0.7, 0.7, 0.7, 1.0}; +static const GLfloat material_diffuse[] = {0.7, 0.7, 0.7, 1.0}; +static const GLfloat material_specular[] = {0.2, 0.2, 0.2, 1.0}; +static const GLfloat zpos = -18.0; + +/*************************************************************************/ + +static void find_matches(pieces_t pieces, int matches[12], int s) +{ + int i, j = 1; + for(i = 1; i<6; i++) { + if(pieces[s][i] && pieces[s][i+6]) { + matches[j++] = i; + } + } + matches[0] = j; + for(i = 1; ipieces, matches, s); + j = matches[0]-1; + j = random()%j; + j = matches[j+1]; + rot_face(cp->pieces, cp->cind, s, j); + s = rnd01(); + rot_halves(cp->pieces, cp->cind, cp->hf, s); + } +} + +static void finish(cube21_conf *cp) +{ + int j, s; + int matches[12]; + switch(cp->state) { + case CUBE21_PAUSE1: + s = rnd01(); + find_matches(cp->pieces, matches, s); + j = matches[0]-1; + j = random()%j; + j = matches[j+1]; + if(j==6 && rnd01()) j = -6; + cp->state = CUBE21_ROT_BASE+s; + cp->tmax = 30.0*abs(j); + cp->fr[0] = cp->fr[1] = 0; + cp->rface = s; + cp->ramount = j; + break; + case CUBE21_ROT_TOP: + case CUBE21_ROT_BOTTOM: + rot_face(cp->pieces, cp->cind, s = cp->rface, cp->ramount); + cp->fr[s] = 1; + s ^= 1; + if(!cp->fr[s] && rnd01()) { + find_matches(cp->pieces, matches, s); + j = matches[0]-1; + j = random()%j; + j = matches[j+1]; + if(j==6 && rnd01()) j = -6; + cp->state = CUBE21_ROT_BASE+s; + cp->tmax = 30.0*abs(j); + cp->rface = s; + cp->ramount = j; + break; + } else { + cp->state = CUBE21_PAUSE2; + cp->tmax = twait; + break; + } + case CUBE21_PAUSE2: + s = rnd01(); + cp->ramount = -rnd01(); /* 0 or -1, only sign is significant in this case */ + cp->state = CUBE21_HALF_BASE+s; + cp->tmax = 180.0; + cp->rface = s; + break; + case CUBE21_HALF1: + case CUBE21_HALF2: + rot_halves(cp->pieces, cp->cind, cp->hf, cp->rface); + cp->state = CUBE21_PAUSE1; + cp->tmax = twait; + break; + } + cp->t = 0; +} + +static void draw_narrow_piece(ModeInfo *mi, cube21_conf *cp, GLfloat s, int c1, int c2, col_t colors) +{ + GLfloat s1 = cp->posc[0]*s; + glBegin(GL_TRIANGLES); + glNormal3f(0.0, 0.0, s); + if(cp->cmat) glColor3fv(colors[c1]); + glTexCoord2f(0.5, 0.5); glVertex3f(0.0, 0.0, s); + glTexCoord2f(cp->texq, 0.0); glVertex3f(cp->posc[1], 0.0, s); + glTexCoord2f(cp->texp, 0.0); glVertex3f(cp->posc[2], cp->posc[3], s); + mi->polygon_count++; + glNormal3f(0.0, 0.0, -s); + if(cp->cmat) glColor3fv(cp->color_inner); + glTexCoord2f(TEX_GRAY); + glVertex3f(0.0, 0.0, s1); + glVertex3f(cp->posc[1], 0.0, s1); + glVertex3f(cp->posc[2], cp->posc[3], s1); + mi->polygon_count++; + glEnd(); + glBegin(GL_QUADS); + glNormal3f(0.0, -1.0, 0.0); + if(cp->cmat) glColor3fv(cp->color_inner); + glTexCoord2f(TEX_GRAY); + glVertex3f(0.0, 0.0, s); + glVertex3f(cp->posc[1], 0.0, s); + glVertex3f(cp->posc[1], 0.0, s1); + glVertex3f(0.0, 0.0, s1); + mi->polygon_count++; + glNormal3f(COS15, SIN15, 0.0); + if(cp->cmat) glColor3fv(colors[c2]); + glTexCoord2f(cp->texq, cp->texq); glVertex3f(cp->posc[1], 0.0, s); + glTexCoord2f(cp->texq, cp->texp); glVertex3f(cp->posc[2], cp->posc[3], s); + glTexCoord2f(1.0, cp->texp); glVertex3f(cp->posc[2], cp->posc[3], s1); + glTexCoord2f(1.0, cp->texq); glVertex3f(cp->posc[1], 0.0, s1); + mi->polygon_count++; + glNormal3f(-SIN30, COS30, 0.0); + if(cp->cmat) glColor3fv(cp->color_inner); + glTexCoord2f(TEX_GRAY); + glVertex3f(0.0, 0.0, s); + glVertex3f(cp->posc[2], cp->posc[3], s); + glVertex3f(cp->posc[2], cp->posc[3], s1); + glVertex3f(0.0, 0.0, s1); + mi->polygon_count++; + glEnd(); + glRotatef(30.0, 0.0, 0.0, 1.0); +} + +static void draw_wide_piece(ModeInfo *mi, cube21_conf *cp, GLfloat s, int c1, int c2, int c3, col_t colors) +{ + GLfloat s1 = cp->posc[0]*s; + glBegin(GL_TRIANGLES); + glNormal3f(0.0, 0.0, s); + if(cp->cmat) glColor3fv(colors[c1]); + glTexCoord2f(0.5, 0.5); glVertex3f(0.0, 0.0, s); + glTexCoord2f(cp->texp, 0.0); glVertex3f(cp->posc[1], 0.0, s); + glTexCoord2f(0.0, 0.0); glVertex3f(cp->posc[4], cp->posc[5], s); + glTexCoord2f(0.0, 0.0); glVertex3f(cp->posc[4], cp->posc[5], s); + glTexCoord2f(0.0, cp->texp); glVertex3f(cp->posc[3], cp->posc[2], s); + glTexCoord2f(0.5, 0.5); glVertex3f(0.0, 0.0, s); + glNormal3f(0.0, 0.0, -s); + if(cp->cmat) glColor3fv(cp->color_inner); + glTexCoord2f(TEX_GRAY); + glVertex3f(0.0, 0.0, s1); + glVertex3f(cp->posc[1], 0.0, s1); + glVertex3f(cp->posc[4], cp->posc[5], s1); + glVertex3f(cp->posc[4], cp->posc[5], s1); + glVertex3f(cp->posc[3], cp->posc[2], s1); + glVertex3f(0.0, 0.0, s1); + glEnd(); + glBegin(GL_QUADS); + glNormal3f(0.0, -1.0, 0); + if(cp->cmat) glColor3fv(cp->color_inner); + glTexCoord2f(TEX_GRAY); + glVertex3f(0.0, 0.0, s); + glVertex3f(cp->posc[1], 0.0, s); + glVertex3f(cp->posc[1], 0.0, s1); + glVertex3f(0.0, 0.0, s1); + glNormal3f(COS15, -SIN15, 0.0); + if(cp->cmat) glColor3fv(colors[c2]); + glTexCoord2f(cp->texq, cp->texp); glVertex3f(cp->posc[1], 0.0, s); + glTexCoord2f(cp->texq, 0.0); glVertex3f(cp->posc[4], cp->posc[5], s); + glTexCoord2f(1.0, 0.0); glVertex3f(cp->posc[4], cp->posc[5], s1); + glTexCoord2f(1.0, cp->texp); glVertex3f(cp->posc[1], 0.0, s1); + glNormal3f(SIN15, COS15, 0.0); + if(cp->cmat) glColor3fv(colors[c3]); + glTexCoord2f(cp->texq, cp->texp); glVertex3f(cp->posc[4], cp->posc[5], s); + glTexCoord2f(cp->texq, 0.0); glVertex3f(cp->posc[3], cp->posc[2], s); + glTexCoord2f(1.0, 0.0); glVertex3f(cp->posc[3], cp->posc[2], s1); + glTexCoord2f(1.0, cp->texp); glVertex3f(cp->posc[4], cp->posc[5], s1); + glNormal3f(-COS30, SIN30, 0.0); + if(cp->cmat) glColor3fv(cp->color_inner); + glTexCoord2f(TEX_GRAY); + glVertex3f(0.0, 0.0, s); + glVertex3f(cp->posc[3], cp->posc[2], s); + glVertex3f(cp->posc[3], cp->posc[2], s1); + glVertex3f(0.0, 0.0, s1); + glEnd(); + glRotatef(60.0, 0.0, 0.0, 1.0); +} + +static void draw_middle_piece(cube21_conf *cp, int s, cind_t cind, col_t colors) +{ + s *= 6; + glBegin(GL_QUADS); + if(cp->cmat) glColor3fv(cp->color_inner); + glNormal3f(0.0, 0.0, 1.0); + glTexCoord2f(TEX_GRAY); + glVertex3f(cp->posc[1], 0.0, cp->posc[0]); + glVertex3f(cp->posc[4], cp->posc[5], cp->posc[0]); + glVertex3f(-cp->posc[5], cp->posc[4], cp->posc[0]); + glVertex3f(-cp->posc[1], 0.0, cp->posc[0]); + glNormal3f(0.0, 0.0, -1.0); + glTexCoord2f(TEX_GRAY); + glVertex3f(cp->posc[1], 0.0, -cp->posc[0]); + glVertex3f(cp->posc[4], cp->posc[5], -cp->posc[0]); + glVertex3f(-cp->posc[5], cp->posc[4], -cp->posc[0]); + glVertex3f(-cp->posc[1], 0.0, -cp->posc[0]); + glNormal3f(0.0, -1.0, 0.0); + glTexCoord2f(TEX_GRAY); + glVertex3f(-cp->posc[1], 0.0, cp->posc[0]); + glVertex3f(cp->posc[1], 0.0, cp->posc[0]); + glVertex3f(cp->posc[1], 0.0, -cp->posc[0]); + glVertex3f(-cp->posc[1], 0.0, -cp->posc[0]); + glNormal3f(COS15, -SIN15, 0.0); + if(cp->cmat) glColor3fv(colors[cind[4][s]]); + glTexCoord2f(cp->texq, cp->texp); glVertex3f(cp->posc[1], 0.0, cp->posc[0]); + glTexCoord2f(1.0, cp->texp); glVertex3f(cp->posc[4], cp->posc[5], cp->posc[0]); + glTexCoord2f(1.0, cp->texq); glVertex3f(cp->posc[4], cp->posc[5], -cp->posc[0]); + glTexCoord2f(cp->texq, cp->texq); glVertex3f(cp->posc[1], 0.0, -cp->posc[0]); + glNormal3f(SIN15, COS15, 0.0); + if(cp->cmat) glColor3fv(colors[cind[4][s+1]]); + glTexCoord2f(0.0, 0.5); glVertex3f(cp->posc[4], cp->posc[5], cp->posc[0]); + glTexCoord2f(cp->texq, 0.5); glVertex3f(-cp->posc[5], cp->posc[4], cp->posc[0]); + glTexCoord2f(cp->texq, 0.75); glVertex3f(-cp->posc[5], cp->posc[4], -cp->posc[0]); + glTexCoord2f(0.0, 0.75); glVertex3f(cp->posc[4], cp->posc[5], -cp->posc[0]); + glNormal3f(-COS15, SIN15, 0.0); + if(cp->cmat) glColor3fv(colors[cind[4][s+4]]); + glTexCoord2f(0.0, 0.75); glVertex3f(-cp->posc[5], cp->posc[4], cp->posc[0]); + glTexCoord2f(1.0, 0.75); glVertex3f(-cp->posc[1], 0.0, cp->posc[0]); + glTexCoord2f(1.0, 1.0); glVertex3f(-cp->posc[1], 0.0, -cp->posc[0]); + glTexCoord2f(0.0, 1.0); glVertex3f(-cp->posc[5], cp->posc[4], -cp->posc[0]); + glEnd(); +} + +static void draw_middle(cube21_conf *cp) +{ + if(cp->hf[0]) glRotatef(180.0, 0.0, 1.0, 0.0); + draw_middle_piece(cp, 0, cp->cind, cp->colors); + if(cp->hf[0]) glRotatef(180.0, 0.0, 1.0, 0.0); + glRotatef(180.0, 0.0, 0.0, 1.0); + if(cp->hf[1]) glRotatef(180.0, 0.0, 1.0, 0.0); + draw_middle_piece(cp, 1, cp->cind, cp->colors); + if(cp->hf[1]) glRotatef(180.0, 0.0, 1.0, 0.0); +} + +static void draw_half_face(ModeInfo *mi, cube21_conf *cp, int s, int o) +{ + int i, s1 = 1-s*2, s2 = s*2; + for(i = o; ipieces[s][i+1]) + draw_narrow_piece(mi, cp, s1, cp->cind[s2][i], cp->cind[s2+1][i], cp->colors); + else { + draw_wide_piece(mi, cp, s1, cp->cind[s2][i], cp->cind[s2+1][i], cp->cind[s2+1][i+1], cp->colors); + i++; + } + } +} + +static void draw_top_face(ModeInfo *mi, cube21_conf *cp) +{ + draw_half_face(mi, cp, 0, 0); + draw_half_face(mi, cp, 0, 6); +} + +static void draw_bottom_face(ModeInfo *mi, cube21_conf *cp) +{ + draw_half_face(mi, cp, 1, 0); + draw_half_face(mi, cp, 1, 6); +} + +static Bool draw_main(ModeInfo *mi, cube21_conf *cp) +{ + GLfloat theta = cp->ramount<0?cp->t:-cp->t; + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + glLoadIdentity(); + if(wander) + glTranslatef(3.0*cp->ratio*sin(13.0*cp->posarg), 3.0*sin(17.0*cp->posarg), zpos); + else + glTranslatef(0, 0, zpos); + glScalef(size, size, size); + + /* Do it twice because we don't track the device's orientation. */ + glRotatef( current_device_rotation(), 0, 0, 1); + gltrackball_rotate (cp->trackball); + glRotatef(-current_device_rotation(), 0, 0, 1); + + glRotatef(cp->xrot, 1.0, 0.0, 0.0); + glRotatef(cp->yrot, 0.0, 1.0, 0.0); + if(cp->wire) glColor3f(0.7, 0.7, 0.7); + switch(cp->state) { + case CUBE21_PAUSE1: + case CUBE21_PAUSE2: + draw_top_face(mi, cp); + draw_bottom_face(mi, cp); + draw_middle(cp); + break; + case CUBE21_ROT_TOP: + glRotatef(theta, 0.0, 0.0, 1.0); + draw_top_face(mi, cp); + glRotatef(-theta, 0.0, 0.0, 1.0); + draw_bottom_face(mi, cp); + draw_middle(cp); + break; + case CUBE21_ROT_BOTTOM: + draw_top_face(mi, cp); + glRotatef(theta, 0.0, 0.0, 1.0); + draw_bottom_face(mi, cp); + glRotatef(-theta, 0.0, 0.0, 1.0); + draw_middle(cp); + break; + case CUBE21_HALF1: + glRotatef(theta, 0.0, 1.0, 0.0); + case CUBE21_HALF2: + draw_half_face(mi, cp, 0, 0); + glRotatef(-180.0, 0.0, 0.0, 1.0); + draw_half_face(mi, cp, 1, 0); + glRotatef(-180.0, 0.0, 0.0, 1.0); + if(cp->hf[0]) glRotatef(180.0, 0.0, 1.0, 0.0); + draw_middle_piece(cp, 0, cp->cind, cp->colors); + if(cp->hf[0]) glRotatef(180.0, 0.0, 1.0, 0.0); + if(cp->state==CUBE21_HALF1) + glRotatef(-theta, 0.0, 1.0, 0.0); + else + glRotatef(theta, 0.0, 1.0, 0.0); + glRotatef(180.0, 0.0, 0.0, 1.0); + draw_half_face(mi, cp, 0, 6); + glRotatef(-180.0, 0.0, 0.0, 1.0); + draw_half_face(mi, cp, 1, 6); + glRotatef(-180.0, 0.0, 0.0, 1.0); + if(cp->hf[1]) glRotatef(180.0, 0.0, 1.0, 0.0); + draw_middle_piece(cp, 1, cp->cind, cp->colors); + break; + } + if(spin) { + if((cp->xrot += spinspeed)>360.0) cp->xrot -= 360.0; + if((cp->yrot += spinspeed)>360.0) cp->yrot -= 360.0; + } + if(wander) + if((cp->posarg += wspeed/1000.0)>360.0) cp->posarg -= 360.0; + if((cp->t += tspeed)>cp->tmax) finish(cp); + return True; +} + +static void parse_colmode(void) +{ + if(!colmode_s) { + colmode = CUBE21_COLOR_WHITE; + return; + } + if(strstr(colmode_s, "se") || strstr(colmode_s, "sil")) colmode = CUBE21_COLOR_SILVER; + else if(strstr(colmode_s, "ce") || strstr(colmode_s, "cla")) colmode = CUBE21_COLOR_CLASSIC; + else if(strstr(colmode_s, "2") || strstr(colmode_s, "two")) colmode = CUBE21_COLOR_TWORND; + else if(strstr(colmode_s, "6") || strstr(colmode_s, "six")) colmode = CUBE21_COLOR_SIXRND; + else if(strstr(colmode_s, "1") || strstr(colmode_s, "ran") || strstr(colmode_s, "rnd")) colmode = CUBE21_COLOR_RANDOM; + else colmode = CUBE21_COLOR_WHITE; +} + +static void init_posc(cube21_conf *cp) +{ + cp->texp = (1.0-tan(Pi/12.0))/2.0; + cp->texq = 1.0-cp->texp; + /* Some significant non-trivial coordinates + * of the object. We need them exactly at GLfloat precision + * for the edges to line up perfectly. */ + cp->posc[0] = tan(Pi/12); /* 0.268 */ + cp->posc[1] = 1.0/cos(Pi/12); /* 1.035 */ + cp->posc[2] = cos(Pi/6)/cos(Pi/12); /* 0.897 */ + cp->posc[3] = sin(Pi/6)/cos(Pi/12); /* 0.518 */ + cp->posc[4] = sqrt(2)*cos(Pi/6); /* 1.225 */ + cp->posc[5] = sqrt(2)*sin(Pi/6); /* 0.707 = 1/sqrt(2) */ +} + +static void draw_horz_line(cube21_conf *cp, int x1, int x2, int y) +{ + int x, y0 = y, w; + if(y=TEX_HEIGHT) break; + w = y*y*255/BORDER2; + for(x=x1; x<=x2; x++) + if(cp->texture[y0+y][x]>w) cp->texture[y0+y][x] = w; + } +} + +static void draw_vert_line(cube21_conf *cp, int x, int y1, int y2) +{ + int x0 = x, y, w; + if(x=TEX_WIDTH) break; + w = x*x*255/BORDER2; + for(y=y1; y<=y2; y++) + if(cp->texture[y][x0+x]>w) cp->texture[y][x0+x] = w; + } +} + +static void draw_slanted_horz(cube21_conf *cp, int x1, int y1, int x2, int y2) +{ + int x, y, dx = x2-x1, dy = y2-y1, y0, w; + for(x=x1; x<=x2; x++) { + y0 = y1+(y2-y1)*(x-x1)/(x2-x1); + for(y=-1-BORDER; y<2+BORDER; y++) { + w = dx*(y0+y-y1)-dy*(x-x1); + w = w*w/(dx*dx+dy*dy); + w = w*255/BORDER2; + if(cp->texture[y0+y][x]>w) cp->texture[y0+y][x] = w; + } + } +} + +static void draw_slanted_vert(cube21_conf *cp, int x1, int y1, int x2, int y2) +{ + int x, y, dx = x2-x1, dy = y2-y1, x0, w; + for(y=y1; y<=y2; y++) { + x0 = x1+(x2-x1)*(y-y1)/(y2-y1); + for(x=-1-BORDER; x<2+BORDER; x++) { + w = dy*(x0+x-x1)-dx*(y-y1); + w = w*w/(dy*dy+dx*dx); + w = w*255/BORDER2; + if(cp->texture[y][x0+x]>w) cp->texture[y][x0+x] = w; + } + } +} + +static void make_texture(cube21_conf *cp) +{ + int x, y, x0, y0; + float grayp[2] = {TEX_GRAY}; + for(y=0; ytexture[y][x] = 255; + draw_horz_line(cp, 0, TEX_WIDTH-1, 0); + draw_horz_line(cp, cp->texq*TEX_WIDTH, TEX_WIDTH-1, cp->texp*TEX_HEIGHT); + draw_horz_line(cp, cp->texq*TEX_WIDTH, TEX_WIDTH-1, cp->texq*TEX_HEIGHT); + draw_horz_line(cp, 0, cp->texq*TEX_WIDTH, TEX_HEIGHT/2); + draw_horz_line(cp, 0, TEX_WIDTH-1, TEX_HEIGHT*3/4); + draw_horz_line(cp, 0, TEX_WIDTH-1, TEX_HEIGHT-1); + draw_vert_line(cp, 0, 0, TEX_HEIGHT-1); + draw_vert_line(cp, cp->texq*TEX_WIDTH, 0, TEX_HEIGHT*3/4); + draw_vert_line(cp, TEX_WIDTH-1, 0, TEX_HEIGHT-1); + draw_slanted_horz(cp, 0, cp->texp*TEX_HEIGHT, TEX_WIDTH/2, TEX_HEIGHT/2); + draw_slanted_vert(cp, cp->texp*TEX_WIDTH, 0, TEX_WIDTH/2, TEX_HEIGHT/2); + draw_slanted_vert(cp, cp->texq*TEX_WIDTH, 0, TEX_WIDTH/2, TEX_HEIGHT/2); + x0 = grayp[0]*TEX_WIDTH; + y0 = grayp[1]*TEX_HEIGHT; + for(y=-1; y<=1; y++) + for(x=-1; x<=1; x++) + cp->texture[y0+y][x0+x] = 100; +} + +/* It doesn't look good */ +/*#define MIPMAP*/ + +static void init_gl(ModeInfo *mi) +{ + cube21_conf *cp = &cube21[MI_SCREEN(mi)]; +#ifdef MIPMAP + int status; +#endif + parse_colmode(); + cp->wire = MI_IS_WIREFRAME(mi); + cp->cmat = !cp->wire && (colmode != CUBE21_COLOR_WHITE); + if(MI_IS_MONO(mi)) { + tex = False; + cp->cmat = False; + } + +# ifdef HAVE_JWZGLES /* #### glPolygonMode other than GL_FILL unimplemented */ + cp->wire = 0; +# endif + + if(cp->wire) { + glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); + return; + } + if(!tex) + cp->color_inner[0] = cp->color_inner[1] = cp->color_inner[2] = 0.4; + else + cp->color_inner[0] = cp->color_inner[1] = cp->color_inner[2] = 1.0; + + glClearDepth(1.0); + glDrawBuffer(GL_BACK); + glPixelStorei(GL_UNPACK_ALIGNMENT, 1); + glShadeModel(GL_FLAT); + glDepthFunc(GL_LESS); + glLightfv(GL_LIGHT0, GL_AMBIENT, ambient); + glLightfv(GL_LIGHT0, GL_DIFFUSE, diffuse); + glLightfv(GL_LIGHT0, GL_POSITION, position0); + glLightfv(GL_LIGHT1, GL_AMBIENT, ambient); + glLightfv(GL_LIGHT1, GL_DIFFUSE, diffuse); + glLightfv(GL_LIGHT1, GL_POSITION, position1); + glLightModelfv(GL_LIGHT_MODEL_AMBIENT, lmodel_ambient); + glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, GL_FALSE); + glEnable(GL_DEPTH_TEST); + glEnable(GL_LIGHT0); + glEnable(GL_LIGHT1); + glEnable(GL_LIGHTING); + glEnable(GL_NORMALIZE); + glEnable(GL_COLOR_MATERIAL); + glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, material_ambient); + glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, material_diffuse); + glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, material_specular); + glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, shininess); + if(!tex) return; + glEnable(GL_TEXTURE_2D); +#ifdef MIPMAP + clear_gl_error(); + status = gluBuild2DMipmaps(GL_TEXTURE_2D, 1, TEX_WIDTH, TEX_HEIGHT, + GL_LUMINANCE, GL_UNSIGNED_BYTE, texture); + if (status) { + const char *s = gluErrorString(status); + fprintf (stderr, "%s: error mipmapping texture: %s\n", progname, (s?s:"(unknown)")); + exit (1); + } + check_gl_error("mipmapping"); +#else + glTexImage2D(GL_TEXTURE_2D, 0, 1, TEX_WIDTH, TEX_HEIGHT, + 0, GL_LUMINANCE, GL_UNSIGNED_BYTE, cp->texture); +#endif + glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); + glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP); + glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP); + glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); +#ifdef MIPMAP + glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR); +#else + glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); +#endif +} + +static void init_cp(cube21_conf *cp) +{ + int i, j; + GLfloat ce_colors[6][3] = { + {1.0, 1.0, 1.0}, + {1.0, 0.5, 0.0}, + {0.0, 0.9, 0.0}, + {0.8, 0.0, 0.0}, + {0.1, 0.1, 1.0}, + {0.9, 0.9, 0.0} + }; + cp->state = CUBE21_STATE_BASIC; + cp->xrot = -65.0; cp->yrot = 185.0; + cp->posarg = (wspeed?random()%360:0.0); + cp->t = 0.0; cp->tmax = twait; + cp->hf[0] = cp->hf[1] = 0; + cp->fr[0] = cp->fr[1] = 0; + for(i=0;i<13;i++) + cp->pieces[0][i] = cp->pieces[1][i] = (i%3==1?0:1); + switch(colmode) { + case CUBE21_COLOR_RANDOM: + case CUBE21_COLOR_TWORND: + case CUBE21_COLOR_SIXRND: + for(i=0; i<6; i++) + for(j=0; j<3; j++) + cp->colors[i][j] = rndcolor(); + break; + case CUBE21_COLOR_SILVER: + cp->colors[0][0] = 1.0; + cp->colors[0][1] = 1.0; + cp->colors[0][2] = 1.0; + cp->colors[1][0] = rndcolor(); + cp->colors[1][1] = rndcolor(); + cp->colors[1][2] = rndcolor(); + break; + case CUBE21_COLOR_CLASSIC: + for(i=0; i<6; i++) + for(j=0; j<3; j++) + cp->colors[i][j] = 0.2+0.7*ce_colors[i][j]; + break; + } + switch(colmode) { + case CUBE21_COLOR_SILVER: + case CUBE21_COLOR_TWORND: + for(i=0; i<5; i++) + for(j=0; j<12; j++) + if(i==0) cp->cind[i][j] = 0; + else if(i==2) cp->cind[i][j] = 1; + else cp->cind[i][j] = ((j+5)%12)>=6?1:0; + break; + case CUBE21_COLOR_CLASSIC: + case CUBE21_COLOR_SIXRND: + for(i=0; i<5; i++) + for(j=0; j<12; j++) + if(i==0) cp->cind[i][j] = 4; + else if(i==2) cp->cind[i][j] = 5; + else cp->cind[i][j] = ((j+5)%12)/3; + break; + case CUBE21_COLOR_RANDOM: + for(i=0; i<5; i++) + for(j=0; j<12; j++) + cp->cind[i][j] = 0; + break; + } + if(rndstart) randomize(cp); +} + +/*************************************************************************/ + +ENTRYPOINT void reshape_cube21(ModeInfo *mi, int width, int height) +{ + cube21_conf *cp = &cube21[MI_SCREEN(mi)]; + if(!height) height = 1; + cp->ratio = (GLfloat)width/(GLfloat)height; + glViewport(0, 0, (GLint) width, (GLint) height); + glMatrixMode(GL_PROJECTION); + glLoadIdentity(); + gluPerspective(30.0, cp->ratio, 1.0, 100.0); + glMatrixMode(GL_MODELVIEW); + glClear(GL_COLOR_BUFFER_BIT); +} + +ENTRYPOINT Bool +cube21_handle_event (ModeInfo *mi, XEvent *event) +{ + cube21_conf *cp = &cube21[MI_SCREEN(mi)]; + + if (event->xany.type == ButtonPress && + event->xbutton.button == Button1) + { + cp->button_down_p = True; + gltrackball_start (cp->trackball, + event->xbutton.x, event->xbutton.y, + MI_WIDTH (mi), MI_HEIGHT (mi)); + return True; + } + else if (event->xany.type == ButtonRelease && + event->xbutton.button == Button1) + { + cp->button_down_p = False; + return True; + } + else if (event->xany.type == ButtonPress && + (event->xbutton.button == Button4 || + event->xbutton.button == Button5 || + event->xbutton.button == Button6 || + event->xbutton.button == Button7)) + { + gltrackball_mousewheel (cp->trackball, event->xbutton.button, 10, + !!event->xbutton.state); + return True; + } + else if (event->xany.type == MotionNotify && + cp->button_down_p) + { + gltrackball_track (cp->trackball, + event->xmotion.x, event->xmotion.y, + MI_WIDTH (mi), MI_HEIGHT (mi)); + return True; + } + + return False; +} + + +ENTRYPOINT void release_cube21(ModeInfo *mi) +{ + if (cube21 != NULL) { + int screen; + for (screen = 0; screen < MI_NUM_SCREENS(mi); screen++) { + cube21_conf *cp = &cube21[screen]; + if (cp->glx_context) { + cp->glx_context = NULL; + } + } + free((void *)cube21); + cube21 = NULL; + } + FreeAllGL(mi); +} + +ENTRYPOINT void init_cube21(ModeInfo *mi) +{ + cube21_conf *cp; + if(!cube21) { + cube21 = (cube21_conf *)calloc(MI_NUM_SCREENS(mi), sizeof(cube21_conf)); + if(!cube21) return; + } + cp = &cube21[MI_SCREEN(mi)]; + + cp->trackball = gltrackball_init (); + + if(!cp->texp) { + init_posc(cp); + make_texture(cp); + } + + if ((cp->glx_context = init_GL(mi)) != NULL) { + init_gl(mi); + init_cp(cp); + reshape_cube21(mi, MI_WIDTH(mi), MI_HEIGHT(mi)); + } else { + MI_CLEARWINDOW(mi); + } +} + +ENTRYPOINT void draw_cube21(ModeInfo * mi) +{ + Display *display = MI_DISPLAY(mi); + Window window = MI_WINDOW(mi); + cube21_conf *cp; + if (!cube21) return; + cp = &cube21[MI_SCREEN(mi)]; + MI_IS_DRAWN(mi) = True; + if (!cp->glx_context) return; + mi->polygon_count = 0; + glXMakeCurrent(display, window, *(cp->glx_context)); + if (!draw_main(mi, cp)) { + release_cube21(mi); + return; + } + if (MI_IS_FPS(mi)) do_fps (mi); + glFlush(); + glXSwapBuffers(display, window); +} + +#ifndef STANDALONE +ENTRYPOINT void change_cube21(ModeInfo * mi) +{ + cube21_conf *cp = &cube21[MI_SCREEN(mi)]; + if (!cp->glx_context) return; + glXMakeCurrent(MI_DISPLAY(mi), MI_WINDOW(mi), *(cp->glx_context)); + init_gl(mi); +} +#endif /* !STANDALONE */ + + +XSCREENSAVER_MODULE ("Cube21", cube21) + +#endif diff --git a/hacks/glx/cube21.man b/hacks/glx/cube21.man new file mode 100644 index 00000000..d90c0fba --- /dev/null +++ b/hacks/glx/cube21.man @@ -0,0 +1,147 @@ +.TH XScreenSaver 1 "30-Aug-05" "X Version 11" +.SH NAME +cube21 - animates the Cube 21 puzzle +.SH SYNOPSIS +.B cube21 +[\-display \fIhost:display.screen\fP] +[\-visual \fIvisual\fP] +[\-window] +[\-root] +[\-install] +[\-delay \fImicroseconds\fP] +[\-texture] [\-no\-texture] +[\-mono] +[\-wireframe] +[\-spin] [\-no\-spin] +[\-wander] [\-no\-wander] +[\-randomize] [\-no\-randomize] +[\-spinspeed \fInumber\fP] +[\-rotspeed \fInumber\fP] +[\-wanderspeed \fInumber\fP] +[\-wait \fInumber\fP] +[\-cubesize \fInumber\fP] +[\-colormode \fIarg\fP] +[\-fps] +.SH DESCRIPTION +This program animates a puzzle known as Cube 21 or Square-1. +Its moves are chosen randomly. +.P +Cube 21 is a Rubik-like puzzle invented in 1992. Its specialities are that +it can change its shape and even the number of possible moves. It can have +more than 200 different shapes and the total number of configurations +(assuming colors) is several tens of billions. +.SH OPTIONS +.I cube21 +accepts the following options: +.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 \-install +Install a private colormap for the window. +.TP 8 +.B \-visual \fIvisual\fP\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 \-delay \fImicroseconds\fP +How long to pause between frames. Default is 20000, or 0.02 second. +.TP 8 +.B \-texture +Use texture maps. This is the default. +.TP 8 +.B \-no\-texture +Use solid colors. +.TP 8 +.B \-mono +Disable both texture maps and colors. +.TP 8 +.B \-wireframe +Only draw outlines. Outlines of all pieces, not only the whole object, are drawn. +.TP 8 +.B \-spin +Spin the whole object around X, Y and Z axes. This is the default. +.TP 8 +.B \-no\-spin +Do not spin, showing the same three faces all the time. +.TP 8 +.B \-wander +Move the object around the screen. This is the default. +.TP 8 +.B \-no\-wander +Keep the object centered on the screen. +.TP 8 +.B \-randomize +Shuffle the puzzle randomly at startup. This is the default. +.TP 8 +.B \-no\-randomize +Do not shuffle at startup, begin at the shape of cube. +.TP 8 +.B \-spinspeed \fInumber\fP +The relative speed of spinning. Default is 1.0. +.TP 8 +.B \-rotspeed \fInumber\fP +The relative speed of the moves. Default is 3.0. Setting to \(<= 0.0 +makes the object stay at one configuration. +.TP 8 +.B \-wanderspeed \fInumber\fP +The relative speed of wandering around the screen. Default is 1.0. +.TP 8 +.B \-wait \fInumber\fP +How long to stay at ending position after each move. The meaning of +the argument is again relative. Default is 40.0. +.TP 8 +.B \-cubesize \fInumber\fP +Size of the object. Value of 3.0 fills roughly all the screen (its height). Default is 0.7. +.TP 8 +.B \-colormode \fIargument\fP +How many and which colors should the object have. The colors are put on the piece +faces so that the puzzle is solvable. The inner faces are not influenced. +.RS +.TP 8 +.BR se " or " silver +Simulate the "Silver Edition" \- white and one random color. +.TP 8 +.BR 2 " or " two +Two random colors. +.TP 8 +.BR ce " or " classic +Simulate the "Classic Edition" \- white, yellow, orange, red, green and blue. +.TP 8 +.BR 6 " or " six +Six random colors. +.TP 8 +.BR 1 " or " random " or " rnd +One random color. +.TP 8 +Anything else +All faces white. +.RE +.TP 8 +.B \-fps +Display the current frame rate, CPU load, and polygon count. +.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 2005 by Vaclav Potocek. 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 +Vaclav (Vasek) Potocek , 30-Aug-05. diff --git a/hacks/glx/cubenetic.c b/hacks/glx/cubenetic.c new file mode 100644 index 00000000..8ae8143f --- /dev/null +++ b/hacks/glx/cubenetic.c @@ -0,0 +1,610 @@ +/* cubenetic, Copyright (c) 2002-2008 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. + */ + +#define DEFAULTS "*delay: 20000 \n" \ + "*count: 5 \n" \ + "*showFPS: False \n" \ + "*wireframe: False \n" \ + +# define refresh_cube 0 +# define release_cube 0 +#undef countof +#define countof(x) (sizeof((x))/sizeof((*x))) + +#include "xlockmore.h" +#include "colors.h" +#include "rotator.h" +#include "gltrackball.h" +#include + +#ifdef USE_GL /* whole file */ + + +#define DEF_SPIN "XYZ" +#define DEF_WANDER "True" +#define DEF_TEXTURE "True" + +#define DEF_WAVES "3" +#define DEF_WAVE_SPEED "80" +#define DEF_WAVE_RADIUS "512" + +typedef struct { + int color; + GLfloat x, y, z; + GLfloat w, h, d; + int frame; + GLfloat dx, dy, dz; + GLfloat dw, dh, dd; +} cube; + +typedef struct { + int x, y; + double xth, yth; +} wave_src; + +typedef struct { + int nwaves; + int radius; + int speed; + wave_src *srcs; + int *heights; +} waves; + + +typedef struct { + GLXContext *glx_context; + rotator *rot; + trackball_state *trackball; + Bool button_down_p; + + GLuint cube_list; + GLuint texture_id; + int cube_polys; + int ncubes; + cube *cubes; + waves *waves; + + int texture_width, texture_height; + unsigned char *texture; + + int ncolors; + XColor *cube_colors; + XColor *texture_colors; + +} cube_configuration; + +static cube_configuration *ccs = NULL; + +static char *do_spin; +static Bool do_wander; +static Bool do_texture; + +static int wave_count; +static int wave_speed; +static int wave_radius; +static int texture_size = 256; + +static XrmOptionDescRec opts[] = { + { "-spin", ".spin", XrmoptionSepArg, 0 }, + { "+spin", ".spin", XrmoptionNoArg, "" }, + { "-wander", ".wander", XrmoptionNoArg, "True" }, + { "+wander", ".wander", XrmoptionNoArg, "False" }, + {"-texture", ".texture", XrmoptionNoArg, "true" }, + {"+texture", ".texture", XrmoptionNoArg, "false" }, + {"-waves", ".waves", XrmoptionSepArg, 0 }, + {"-wave-speed", ".waveSpeed", XrmoptionSepArg, 0 }, + {"-wave-radius", ".waveRadius", XrmoptionSepArg, 0 }, +}; + +static argtype vars[] = { + {&do_spin, "spin", "Spin", DEF_SPIN, t_String}, + {&do_wander, "wander", "Wander", DEF_WANDER, t_Bool}, + {&do_texture, "texture", "Texture", DEF_TEXTURE, t_Bool}, + {&wave_count, "waves", "Waves", DEF_WAVES, t_Int}, + {&wave_speed, "waveSpeed", "WaveSpeed", DEF_WAVE_SPEED, t_Int}, + {&wave_radius,"waveRadius","WaveRadius", DEF_WAVE_RADIUS,t_Int}, +}; + +ENTRYPOINT ModeSpecOpt cube_opts = {countof(opts), opts, countof(vars), vars, NULL}; + + +static int +unit_cube (Bool wire) +{ + int polys = 0; + glBegin (wire ? GL_LINE_LOOP : GL_QUADS); /* front */ + glNormal3f (0, 0, 1); + glTexCoord2f(1, 0); glVertex3f ( 0.5, -0.5, 0.5); + glTexCoord2f(0, 0); glVertex3f ( 0.5, 0.5, 0.5); + glTexCoord2f(0, 1); glVertex3f (-0.5, 0.5, 0.5); + glTexCoord2f(1, 1); glVertex3f (-0.5, -0.5, 0.5); + polys++; + glEnd(); + + glBegin (wire ? GL_LINE_LOOP : GL_QUADS); /* back */ + glNormal3f (0, 0, -1); + glTexCoord2f(0, 0); glVertex3f (-0.5, -0.5, -0.5); + glTexCoord2f(0, 1); glVertex3f (-0.5, 0.5, -0.5); + glTexCoord2f(1, 1); glVertex3f ( 0.5, 0.5, -0.5); + glTexCoord2f(1, 0); glVertex3f ( 0.5, -0.5, -0.5); + polys++; + glEnd(); + + glBegin (wire ? GL_LINE_LOOP : GL_QUADS); /* left */ + glNormal3f (-1, 0, 0); + glTexCoord2f(1, 1); glVertex3f (-0.5, 0.5, 0.5); + glTexCoord2f(1, 0); glVertex3f (-0.5, 0.5, -0.5); + glTexCoord2f(0, 0); glVertex3f (-0.5, -0.5, -0.5); + glTexCoord2f(0, 1); glVertex3f (-0.5, -0.5, 0.5); + polys++; + glEnd(); + + glBegin (wire ? GL_LINE_LOOP : GL_QUADS); /* right */ + glNormal3f (1, 0, 0); + glTexCoord2f(1, 1); glVertex3f ( 0.5, -0.5, -0.5); + glTexCoord2f(1, 0); glVertex3f ( 0.5, 0.5, -0.5); + glTexCoord2f(0, 0); glVertex3f ( 0.5, 0.5, 0.5); + glTexCoord2f(0, 1); glVertex3f ( 0.5, -0.5, 0.5); + polys++; + glEnd(); + + if (wire) return polys; + + glBegin (wire ? GL_LINE_LOOP : GL_QUADS); /* top */ + glNormal3f (0, 1, 0); + glTexCoord2f(0, 0); glVertex3f ( 0.5, 0.5, 0.5); + glTexCoord2f(0, 1); glVertex3f ( 0.5, 0.5, -0.5); + glTexCoord2f(1, 1); glVertex3f (-0.5, 0.5, -0.5); + glTexCoord2f(1, 0); glVertex3f (-0.5, 0.5, 0.5); + polys++; + glEnd(); + + glBegin (wire ? GL_LINE_LOOP : GL_QUADS); /* bottom */ + glNormal3f (0, -1, 0); + glTexCoord2f(1, 0); glVertex3f (-0.5, -0.5, 0.5); + glTexCoord2f(0, 0); glVertex3f (-0.5, -0.5, -0.5); + glTexCoord2f(0, 1); glVertex3f ( 0.5, -0.5, -0.5); + glTexCoord2f(1, 1); glVertex3f ( 0.5, -0.5, 0.5); + polys++; + glEnd(); + return polys; +} + + + +/* Window management, etc + */ +ENTRYPOINT void +reshape_cube (ModeInfo *mi, int width, int height) +{ + GLfloat h = (GLfloat) height / (GLfloat) width; + + glViewport (0, 0, (GLint) width, (GLint) height); + + glMatrixMode(GL_PROJECTION); + glLoadIdentity(); + + gluPerspective (30.0, 1/h, 1.0, 100.0); + glMatrixMode(GL_MODELVIEW); + glLoadIdentity(); + gluLookAt( 0.0, 0.0, 30.0, + 0.0, 0.0, 0.0, + 0.0, 1.0, 0.0); + + glClear(GL_COLOR_BUFFER_BIT); +} + + + +/* Waves. + Adapted from ../hacks/interference.c by Hannu Mallat. + */ + +static void +init_wave (ModeInfo *mi) +{ + cube_configuration *cc = &ccs[MI_SCREEN(mi)]; + waves *ww; + int i; + cc->waves = ww = (waves *) calloc (sizeof(*cc->waves), 1); + ww->nwaves = wave_count; + ww->radius = wave_radius; + ww->speed = wave_speed; + ww->heights = (int *) calloc (sizeof(*ww->heights), ww->radius); + ww->srcs = (wave_src *) calloc (sizeof(*ww->srcs), ww->nwaves); + + for (i = 0; i < ww->radius; i++) + { + float max = (cc->ncolors * (ww->radius - i) / (float) ww->radius); + ww->heights[i] = ((max + max * cos(i / 50.0)) / 2.0); + } + + for (i = 0; i < ww->nwaves; i++) + { + ww->srcs[i].xth = frand(2.0) * M_PI; + ww->srcs[i].yth = frand(2.0) * M_PI; + } +} + +static void +interference (ModeInfo *mi) +{ + cube_configuration *cc = &ccs[MI_SCREEN(mi)]; + waves *ww = cc->waves; + int x, y, i; + + /* Move the wave origins around + */ + for (i = 0; i < ww->nwaves; i++) + { + ww->srcs[i].xth += (ww->speed / 1000.0); + if (ww->srcs[i].xth > 2*M_PI) + ww->srcs[i].xth -= 2*M_PI; + ww->srcs[i].yth += (ww->speed / 1000.0); + if (ww->srcs[i].yth > 2*M_PI) + ww->srcs[i].yth -= 2*M_PI; + + ww->srcs[i].x = (cc->texture_width/2 + + (cos (ww->srcs[i].xth) * + cc->texture_width / 2)); + ww->srcs[i].y = (cc->texture_height/2 + + (cos (ww->srcs[i].yth) * + cc->texture_height / 2)); + } + + /* Compute the effect of the waves on each pixel, + and generate the output map. + */ + for (y = 0; y < cc->texture_height; y++) + for (x = 0; x < cc->texture_width; x++) + { + int result = 0; + unsigned char *o; + for (i = 0; i < ww->nwaves; i++) + { + int dx = x - ww->srcs[i].x; + int dy = y - ww->srcs[i].y; + int dist = sqrt (dx*dx + dy*dy); + result += (dist > ww->radius ? 0 : ww->heights[dist]); + } + result %= cc->ncolors; + + o = cc->texture + (((y * cc->texture_width) + x) << 2); + o[0] = (cc->texture_colors[result].red >> 8); + o[1] = (cc->texture_colors[result].green >> 8); + o[2] = (cc->texture_colors[result].blue >> 8); + /* o[3] = 0xFF; */ + } +} + + +/* Textures + */ + +static void +init_texture (ModeInfo *mi) +{ + cube_configuration *cc = &ccs[MI_SCREEN(mi)]; + int i; + + glEnable(GL_TEXTURE_2D); + + clear_gl_error(); + glPixelStorei (GL_UNPACK_ALIGNMENT, 1); + glGenTextures (1, &cc->texture_id); + glBindTexture (GL_TEXTURE_2D, cc->texture_id); + check_gl_error("texture binding"); + + glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); + glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); + glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + glTexEnvf (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); + check_gl_error("texture initialization"); + + cc->texture_width = texture_size; + cc->texture_height = texture_size; + + i = texture_size * texture_size * 4; + cc->texture = (unsigned char *) malloc (i); + memset (cc->texture, 0xFF, i); +} + + +static void +shuffle_texture (ModeInfo *mi) +{ + cube_configuration *cc = &ccs[MI_SCREEN(mi)]; + interference (mi); + clear_gl_error(); + glTexImage2D (GL_TEXTURE_2D, 0, GL_RGBA, + cc->texture_width, cc->texture_height, 0, + GL_RGBA, GL_UNSIGNED_BYTE, + cc->texture); + check_gl_error("texture"); +} + + +ENTRYPOINT Bool +cube_handle_event (ModeInfo *mi, XEvent *event) +{ + cube_configuration *cc = &ccs[MI_SCREEN(mi)]; + + if (event->xany.type == ButtonPress && + event->xbutton.button == Button1) + { + cc->button_down_p = True; + gltrackball_start (cc->trackball, + event->xbutton.x, event->xbutton.y, + MI_WIDTH (mi), MI_HEIGHT (mi)); + return True; + } + else if (event->xany.type == ButtonRelease && + event->xbutton.button == Button1) + { + cc->button_down_p = False; + return True; + } + else if (event->xany.type == ButtonPress && + (event->xbutton.button == Button4 || + event->xbutton.button == Button5 || + event->xbutton.button == Button6 || + event->xbutton.button == Button7)) + { + gltrackball_mousewheel (cc->trackball, event->xbutton.button, 10, + !!event->xbutton.state); + return True; + } + else if (event->xany.type == MotionNotify && + cc->button_down_p) + { + gltrackball_track (cc->trackball, + event->xmotion.x, event->xmotion.y, + MI_WIDTH (mi), MI_HEIGHT (mi)); + return True; + } + + return False; +} + + +ENTRYPOINT void +init_cube (ModeInfo *mi) +{ + int i; + cube_configuration *cc; + int wire = MI_IS_WIREFRAME(mi); + + if (!ccs) { + ccs = (cube_configuration *) + calloc (MI_NUM_SCREENS(mi), sizeof (cube_configuration)); + if (!ccs) { + fprintf(stderr, "%s: out of memory\n", progname); + exit(1); + } + } + + cc = &ccs[MI_SCREEN(mi)]; + + if ((cc->glx_context = init_GL(mi)) != NULL) { + reshape_cube (mi, MI_WIDTH(mi), MI_HEIGHT(mi)); + } + + if (!wire) + { + static const GLfloat pos[4] = {1.0, 0.5, 1.0, 0.0}; + static const GLfloat amb[4] = {0.2, 0.2, 0.2, 1.0}; + static const GLfloat dif[4] = {1.0, 1.0, 1.0, 1.0}; + + glLightfv(GL_LIGHT0, GL_POSITION, pos); + glLightfv(GL_LIGHT0, GL_AMBIENT, amb); + glLightfv(GL_LIGHT0, GL_DIFFUSE, dif); + + glEnable(GL_LIGHTING); + glEnable(GL_LIGHT0); + glEnable(GL_DEPTH_TEST); + glEnable(GL_CULL_FACE); + } + + + { + Bool spinx=False, spiny=False, spinz=False; + double spin_speed = 1.0; + double wander_speed = 0.05; + + char *s = do_spin; + while (*s) + { + if (*s == 'x' || *s == 'X') spinx = True; + else if (*s == 'y' || *s == 'Y') spiny = True; + else if (*s == 'z' || *s == 'Z') spinz = True; + else if (*s == '0') ; + else + { + fprintf (stderr, + "%s: spin must contain only the characters X, Y, or Z (not \"%s\")\n", + progname, do_spin); + exit (1); + } + s++; + } + + cc->rot = make_rotator (spinx ? spin_speed : 0, + spiny ? spin_speed : 0, + spinz ? spin_speed : 0, + 1.0, + do_wander ? wander_speed : 0, + (spinx && spiny && spinz)); + cc->trackball = gltrackball_init (); + } + + cc->ncolors = 256; + cc->texture_colors = (XColor *) calloc(cc->ncolors, sizeof(XColor)); + cc->cube_colors = (XColor *) calloc(cc->ncolors, sizeof(XColor)); + + { + double H[3], S[3], V[3]; + int shift = 60; + H[0] = frand(360.0); + H[1] = ((H[0] + shift) < 360) ? (H[0]+shift) : (H[0] + shift - 360); + H[2] = ((H[1] + shift) < 360) ? (H[1]+shift) : (H[1] + shift - 360); + S[0] = S[1] = S[2] = 1.0; + V[0] = V[1] = V[2] = 1.0; + make_color_loop(0, 0, + H[0], S[0], V[0], + H[1], S[1], V[1], + H[2], S[2], V[2], + cc->texture_colors, &cc->ncolors, + False, False); + + make_smooth_colormap (0, 0, 0, + cc->cube_colors, &cc->ncolors, + False, 0, False); + } + + cc->ncubes = MI_COUNT (mi); + cc->cubes = (cube *) calloc (sizeof(cube), cc->ncubes); + for (i = 0; i < cc->ncubes; i++) + { + cube *cube = &cc->cubes[i]; + cube->color = random() % cc->ncolors; + cube->w = 1.0; + cube->h = 1.0; + cube->d = 1.0; + cube->dx = frand(0.1); + cube->dy = frand(0.1); + cube->dz = frand(0.1); + cube->dw = frand(0.1); + cube->dh = frand(0.1); + cube->dd = frand(0.1); + } + + if (wire) + do_texture = False; + + if (do_texture) + { + init_texture (mi); + init_wave (mi); + shuffle_texture (mi); + } + + cc->cube_list = glGenLists (1); + glNewList (cc->cube_list, GL_COMPILE); + cc->cube_polys = unit_cube (wire); + glEndList (); +} + + +static void +shuffle_cubes (ModeInfo *mi) +{ + cube_configuration *cc = &ccs[MI_SCREEN(mi)]; + int i; + for (i = 0; i < cc->ncubes; i++) + { +# define SINOID(SCALE,FRAME,SIZE) \ + ((((1 + sin((FRAME * (SCALE)) / 2 * M_PI)) / 2.0) * (SIZE)) - (SIZE)/2) + + cube *cube = &cc->cubes[i]; + cube->x = SINOID(cube->dx, cube->frame, 0.5); + cube->y = SINOID(cube->dy, cube->frame, 0.5); + cube->z = SINOID(cube->dz, cube->frame, 0.5); + cube->w = SINOID(cube->dw, cube->frame, 0.9) + 1.0; + cube->h = SINOID(cube->dh, cube->frame, 0.9) + 1.0; + cube->d = SINOID(cube->dd, cube->frame, 0.9) + 1.0; + cube->frame++; +# undef SINOID + } +} + + +ENTRYPOINT void +draw_cube (ModeInfo *mi) +{ + cube_configuration *cc = &ccs[MI_SCREEN(mi)]; + Display *dpy = MI_DISPLAY(mi); + Window window = MI_WINDOW(mi); + int i; + + if (!cc->glx_context) + return; + + mi->polygon_count = 0; + glXMakeCurrent(MI_DISPLAY(mi), MI_WINDOW(mi), *(cc->glx_context)); + + glShadeModel(GL_FLAT); + + glEnable(GL_DEPTH_TEST); + glEnable(GL_NORMALIZE); + glEnable(GL_CULL_FACE); + + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + + glPushMatrix (); + + glScalef(1.1, 1.1, 1.1); + + { + double x, y, z; + get_position (cc->rot, &x, &y, &z, !cc->button_down_p); + glTranslatef((x - 0.5) * 8, + (y - 0.5) * 6, + (z - 0.5) * 15); + + /* Do it twice because we don't track the device's orientation. */ + glRotatef( current_device_rotation(), 0, 0, 1); + gltrackball_rotate (cc->trackball); + glRotatef(-current_device_rotation(), 0, 0, 1); + + get_rotation (cc->rot, &x, &y, &z, !cc->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 (2.5, 2.5, 2.5); + + for (i = 0; i < cc->ncubes; i++) + { + cube *cube = &cc->cubes[i]; + GLfloat color[4]; + color[0] = cc->cube_colors[cube->color].red / 65536.0; + color[1] = cc->cube_colors[cube->color].green / 65536.0; + color[2] = cc->cube_colors[cube->color].blue / 65536.0; + color[3] = 1.0; + cube->color++; + if (cube->color >= cc->ncolors) cube->color = 0; + + glPushMatrix (); + glTranslatef (cube->x, cube->y, cube->z); + glScalef (cube->w, cube->h, cube->d); + glMaterialfv (GL_FRONT, GL_AMBIENT_AND_DIFFUSE, color); + glCallList (cc->cube_list); + mi->polygon_count += cc->cube_polys; + glPopMatrix (); + } + + shuffle_cubes (mi); + if (do_texture) + shuffle_texture (mi); + + glPopMatrix(); + + if (mi->fps_p) do_fps (mi); + glFinish(); + + glXSwapBuffers(dpy, window); +} + +XSCREENSAVER_MODULE_2 ("Cubenetic", cubenetic, cube) + +#endif /* USE_GL */ diff --git a/hacks/glx/cubenetic.man b/hacks/glx/cubenetic.man new file mode 100644 index 00000000..e11d479e --- /dev/null +++ b/hacks/glx/cubenetic.man @@ -0,0 +1,89 @@ +.TH XScreenSaver 1 "" "X Version 11" +.SH NAME +cubenetic - cubist 3D undulating blob. +.SH SYNOPSIS +.B cubenetic +[\-display \fIhost:display.screen\fP] +[\-visual \fIvisual\fP] +[\-window] +[\-root] +[\-delay \fInumber\fP] +[\-count \fInumber\fP] +[\-no-wander] +[\-no-spin] +[\-spin \fI[XYZ]\fP] +[\-wireframe] +[\-no-texture] +[\-wave-speed \fInumber\fP] +[\-wave-radius \fInumber\fP] +[\-waves \fInumber\fP] +[\-fps] +.SH DESCRIPTION +Draws a pulsating set of overlapping boxes with ever-chaning blobby +patterns undulating across their surfaces. +.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: 20000 (0.02 seconds.). +.TP 8 +.B \-count \fInumber\fP +How many boxes make up the object. Default: 5. +.TP 8 +.B \-wander | \-no-wander +Whether the object should wander around the screen. +.TP 8 +.B \-spin \fI[XYZ]\fP +Around which axes should the object spin? +.TP 8 +.B \-no-spin +Don't spin. +.TP 8 +.B \-wireframe +Render in wireframe instead of solid. +.TP 8 +.B \-texture | \-no-texture +Display Solid Colors. +.TP 8 +.B \-wave-speed \fInumber\fP +Surface Pattern Speed. 5 - 150. Default: 80. +.TP 8 +.B \-wave-radius \fInumber\fP +Surface Pattern Overlap. 5 - 600. Default: 512. +.TP 8 +.B \-waves \fInumber\fP +Surface Pattern Complexity. 1 - 20. Default: 3. +.TP 8 +.B \-fps +Display the current frame rate, CPU load, and polygon count. +.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 2002 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/glx/cubestorm.c b/hacks/glx/cubestorm.c new file mode 100644 index 00000000..d7931112 --- /dev/null +++ b/hacks/glx/cubestorm.c @@ -0,0 +1,429 @@ +/* cubestorm, Copyright (c) 2003-2008 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. + */ + +#define DEFAULTS "*delay: 30000 \n" \ + "*count: " DEF_COUNT "\n" \ + "*showFPS: False \n" \ + "*fpsSolid: True \n" \ + "*wireframe: False \n" \ + + +# define refresh_cube 0 +# define release_cube 0 +#undef countof +#define countof(x) (sizeof((x))/sizeof((*x))) + +#include "xlockmore.h" +#include "colors.h" +#include "rotator.h" +#include "gltrackball.h" +#include + +#ifdef USE_GL /* whole file */ + +#define DEF_SPIN "True" +#define DEF_WANDER "True" +#define DEF_SPEED "1.0" +#define DEF_THICKNESS "0.06" +#define DEF_COUNT "4" +#define DEF_DBUF "False" + +typedef struct { + rotator *rot; + int ccolor; +} subcube; + +typedef struct { + GLXContext *glx_context; + trackball_state *trackball; + Bool button_down_p; + Bool clear_p; + + GLuint cube_list; + + int ncolors; + XColor *colors; + + subcube *subcubes; + +} cube_configuration; + +static cube_configuration *bps = NULL; + +static Bool do_spin; +static Bool do_wander; +static GLfloat speed; +static GLfloat thickness; +static Bool dbuf_p; + +static XrmOptionDescRec opts[] = { + { "-spin", ".spin", XrmoptionNoArg, "True" }, + { "+spin", ".spin", XrmoptionNoArg, "False" }, + { "-wander", ".wander", XrmoptionNoArg, "True" }, + { "+wander", ".wander", XrmoptionNoArg, "False" }, + { "-speed", ".speed", XrmoptionSepArg, 0 }, + { "-db", ".doubleBuffer", XrmoptionNoArg, "True"}, + { "+db", ".doubleBuffer", XrmoptionNoArg, "False"}, + { "-thickness", ".thickness", 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}, +}; + +ENTRYPOINT ModeSpecOpt cube_opts = {countof(opts), opts, countof(vars), vars, NULL}; + + +static void +draw_face (ModeInfo *mi) +{ + int wire = MI_IS_WIREFRAME(mi); + + int i; + GLfloat t = thickness / 2; + GLfloat a = -0.5; + GLfloat b = 0.5; + + if (t <= 0) t = 0.001; + else if (t > 0.5) t = 0.5; + + glPushMatrix(); + glFrontFace(GL_CW); + + for (i = 0; i < 4; i++) + { + glNormal3f (0, 0, -1); + glBegin (wire ? GL_LINE_LOOP : GL_QUADS); + glVertex3f (a, a, a); + glVertex3f (b, a, a); + glVertex3f (b-t, a+t, a); + glVertex3f (a+t, a+t, a); + glEnd(); + + glNormal3f (0, 1, 0); + glBegin (wire ? GL_LINE_LOOP : GL_QUADS); + glVertex3f (b-t, a+t, a); + glVertex3f (b-t, a+t, a+t); + glVertex3f (a+t, a+t, a+t); + glVertex3f (a+t, a+t, a); + glEnd(); + + glRotatef(90, 0, 0, 1); + } + glPopMatrix(); +} + +static void +draw_faces (ModeInfo *mi) +{ + glPushMatrix(); + draw_face (mi); + glRotatef (90, 0, 1, 0); draw_face (mi); + glRotatef (90, 0, 1, 0); draw_face (mi); + glRotatef (90, 0, 1, 0); draw_face (mi); + glRotatef (90, 1, 0, 0); draw_face (mi); + glRotatef (180, 1, 0, 0); draw_face (mi); + glPopMatrix(); +} + + +static void +new_cube_colors (ModeInfo *mi) +{ + cube_configuration *bp = &bps[MI_SCREEN(mi)]; + int i; + bp->ncolors = 128; + if (bp->colors) free (bp->colors); + bp->colors = (XColor *) calloc(bp->ncolors, sizeof(XColor)); + make_smooth_colormap (0, 0, 0, + bp->colors, &bp->ncolors, + False, 0, False); + for (i = 0; i < MI_COUNT(mi); i++) + bp->subcubes[i].ccolor = random() % bp->ncolors; +} + + +/* Window management, etc + */ +ENTRYPOINT void +reshape_cube (ModeInfo *mi, int width, int height) +{ + GLfloat h = (GLfloat) height / (GLfloat) width; + + glViewport (0, 0, (GLint) width, (GLint) height); + + glMatrixMode(GL_PROJECTION); + glLoadIdentity(); + gluPerspective (30.0, 1/h, 1.0, 100.0); + + glMatrixMode(GL_MODELVIEW); + glLoadIdentity(); + gluLookAt( 0.0, 0.0, 45.0, + 0.0, 0.0, 0.0, + 0.0, 1.0, 0.0); + + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); +} + + +ENTRYPOINT Bool +cube_handle_event (ModeInfo *mi, XEvent *event) +{ + cube_configuration *bp = &bps[MI_SCREEN(mi)]; + + if (event->xany.type == ButtonPress && + event->xbutton.button == Button1) + { + bp->button_down_p = True; + gltrackball_start (bp->trackball, + event->xbutton.x, event->xbutton.y, + MI_WIDTH (mi), MI_HEIGHT (mi)); + return True; + } + else if (event->xany.type == ButtonRelease && + event->xbutton.button == Button1) + { + bp->button_down_p = False; + return True; + } + else if (event->xany.type == ButtonPress && + (event->xbutton.button == Button4 || + event->xbutton.button == Button5 || + event->xbutton.button == Button6 || + event->xbutton.button == Button7)) + { + gltrackball_mousewheel (bp->trackball, event->xbutton.button, 10, + !!event->xbutton.state); + return True; + } + else if (event->xany.type == MotionNotify && + bp->button_down_p) + { + gltrackball_track (bp->trackball, + event->xmotion.x, event->xmotion.y, + MI_WIDTH (mi), MI_HEIGHT (mi)); + return True; + } + else if (event->xany.type == KeyPress) + { + KeySym keysym; + char c = 0; + XLookupString (&event->xkey, &c, 1, &keysym, 0); + if (c == ' ') + { + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + return True; + } + else if (c == '\r' || c == '\n') + { + new_cube_colors (mi); + return True; + } + } + return False; +} + + +ENTRYPOINT void +init_cube (ModeInfo *mi) +{ + cube_configuration *bp; + int wire = MI_IS_WIREFRAME(mi); + int i; + + if (!bps) { + bps = (cube_configuration *) + calloc (MI_NUM_SCREENS(mi), sizeof (cube_configuration)); + if (!bps) { + fprintf(stderr, "%s: out of memory\n", progname); + exit(1); + } + } + +# ifdef HAVE_JWZGLES + dbuf_p = True; +# endif + + bp = &bps[MI_SCREEN(mi)]; + + bp->glx_context = init_GL(mi); + + if (MI_COUNT(mi) <= 0) MI_COUNT(mi) = 1; + + bp->trackball = gltrackball_init (); + bp->subcubes = (subcube *) calloc (MI_COUNT(mi), sizeof(subcube)); + for (i = 0; i < MI_COUNT(mi); i++) + { + double wander_speed, spin_speed, spin_accel; + + if (i == 0) + { + wander_speed = 0.05 * speed; + spin_speed = 10.0 * speed; + spin_accel = 4.0 * speed; + } + else + { + wander_speed = 0; + spin_speed = 4.0 * speed; + spin_accel = 2.0 * speed; + } + + bp->subcubes[i].rot = make_rotator (do_spin ? spin_speed : 0, + do_spin ? spin_speed : 0, + do_spin ? spin_speed : 0, + spin_accel, + do_wander ? wander_speed : 0, + True); + } + + bp->colors = 0; + new_cube_colors (mi); + + reshape_cube (mi, MI_WIDTH(mi), MI_HEIGHT(mi)); + + if (!wire) + { + GLfloat pos[4] = {1.0, 1.0, 1.0, 0.0}; + GLfloat amb[4] = {0.0, 0.0, 0.0, 1.0}; + GLfloat dif[4] = {1.0, 1.0, 1.0, 1.0}; + GLfloat spc[4] = {0.0, 1.0, 1.0, 1.0}; + + glEnable(GL_LIGHTING); + glEnable(GL_LIGHT0); + glEnable(GL_DEPTH_TEST); + glEnable(GL_CULL_FACE); + + glLightfv(GL_LIGHT0, GL_POSITION, pos); + glLightfv(GL_LIGHT0, GL_AMBIENT, amb); + glLightfv(GL_LIGHT0, GL_DIFFUSE, dif); + glLightfv(GL_LIGHT0, GL_SPECULAR, spc); + } + + bp->cube_list = glGenLists (1); + glNewList (bp->cube_list, GL_COMPILE); + draw_faces (mi); + glEndList (); + + glDrawBuffer(dbuf_p ? GL_BACK : GL_FRONT); + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); +} + + +ENTRYPOINT void +draw_cube (ModeInfo *mi) +{ + cube_configuration *bp = &bps[MI_SCREEN(mi)]; + Display *dpy = MI_DISPLAY(mi); + Window window = MI_WINDOW(mi); + int wire = MI_IS_WIREFRAME(mi); + int i; + double x, y, z; + + if (!bp->glx_context) + return; + + glXMakeCurrent(MI_DISPLAY(mi), MI_WINDOW(mi), *(bp->glx_context)); + + glShadeModel(GL_SMOOTH); + + glEnable(GL_DEPTH_TEST); + glEnable(GL_NORMALIZE); + glEnable(GL_CULL_FACE); + + if (bp->clear_p) /* we're in "no vapor trails" mode */ + { + glClear(GL_DEPTH_BUFFER_BIT|GL_COLOR_BUFFER_BIT); + if (! (random() % (int) (25 / speed))) + bp->clear_p = False; + } + else + { + if (! (random() % (int) (200 / speed))) + { + bp->clear_p = True; + new_cube_colors (mi); + } + } + + glPushMatrix (); + + glScalef(1.1, 1.1, 1.1); + + 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++) + { + 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; + + glPushMatrix(); + + 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); + } + + 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); + + 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; + + if (wire) + glColor3f (bcolor[0], bcolor[1], bcolor[2]); + else + { + glMaterialfv (GL_FRONT, GL_SPECULAR, bspec); + glMateriali (GL_FRONT, GL_SHININESS, bshiny); + glMaterialfv (GL_FRONT, GL_AMBIENT_AND_DIFFUSE, bcolor); + } + + glCallList (bp->cube_list); + mi->polygon_count += (4 * 2 * 6); + + glPopMatrix(); + } + + glPopMatrix (); + + if (mi->fps_p) do_fps (mi); + glFinish(); + + if (dbuf_p) + glXSwapBuffers(dpy, window); +} + +XSCREENSAVER_MODULE_2 ("CubeStorm", cubestorm, cube) + +#endif /* USE_GL */ diff --git a/hacks/glx/cubestorm.man b/hacks/glx/cubestorm.man new file mode 100644 index 00000000..9d912fd8 --- /dev/null +++ b/hacks/glx/cubestorm.man @@ -0,0 +1,77 @@ +.TH XScreenSaver 1 "" "X Version 11" +.SH NAME +cubestorm - a series of 3D boxes that fill space +.SH SYNOPSIS +.B cubestorm +[\-display \fIhost:display.screen\fP] +[\-visual \fIvisual\fP] +[\-window] +[\-root] +[\-delay \fInumber\fP] +[\-speed \fIfloat\fP] +[\-count \fIint\fP] +[\-thickness \fIfloat\fP] +[\-no-wander] +[\-no-spin] +[\-wireframe] +[\-fps] +.SH DESCRIPTION +Draws a series of rotating 3D boxes that intersect each other and +eventually fill space. +.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 \-speed \fInumber\fP +Larger numbers mean run faster. Default: 1.0. +.TP 8 +.B \-count \fInumber\fP +Number of cubes. Default 4. +.TP 8 +.B \-thickness \fIfloat\fP +How thick the struts making up the cubes should be (0.0-1.0). Default 0.06. +.TP 8 +.B \-wander | \-no-wander +Whether the cubes should wander around the screen. +.TP 8 +.B \-spin | \-no-spin +Whether the cubes should spin. +.TP 8 +.B \-wireframe | \-no-wireframe +Render in wireframe instead of solid. +.TP 8 +.B \-fps +Display the current frame rate, CPU load, and polygon count. +.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 2003 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/glx/cubicgrid.c b/hacks/glx/cubicgrid.c new file mode 100644 index 00000000..400af743 --- /dev/null +++ b/hacks/glx/cubicgrid.c @@ -0,0 +1,295 @@ +/*- + * Permission to use, copy, modify, and distribute this software and its + * documentation for any purpose and without fee is hereby granted, + * provided that the above copyright notice appear in all copies and that + * both that copyright notice and this permission notice appear in + * supporting documentation. + * + * This file is provided AS IS with no warranties of any kind. The author + * shall have no liability with respect to the infringement of copyrights, + * trade secrets or any patents by this file or any part thereof. In no + * event will the author be liable for any lost revenue or profits or + * other special, indirect and consequential damages. + * + * Cubic Grid - a 3D lattice. The observer is located in the centre of + * a spinning finite lattice. As it rotates, various view-throughs appear and + * evolve. A simple idea with interesting results. + * + * Vasek Potocek (Dec-28-2007) + * vasek.potocek@post.cz + */ + +#define DEFAULTS "*delay: 20000 \n" \ + "*showFPS: False \n" \ + "*wireframe: False \n" + +# define refresh_cubicgrid 0 +#include "xlockmore.h" + +#ifdef USE_GL + +#define DEF_SPEED "1.0" +#define DEF_DIV "30" +#define DEF_ZOOM "20" +#define DEF_BIGDOTS "True" + +#undef countof +#define countof(x) (sizeof((x))/sizeof((*x))) + +#include "rotator.h" +#include "gltrackball.h" + +/*************************************************************************/ + +static int ticks; +static float size; +static float speed; +static Bool bigdots; + +static argtype vars[] = { + { &speed, "speed", "Speed", DEF_SPEED, t_Float }, + { &size, "zoom", "Zoom", DEF_ZOOM, t_Float }, + { &ticks, "ticks", "Ticks", DEF_DIV, t_Int }, + { &bigdots, "bigdots", "BigDots", DEF_BIGDOTS, t_Bool }, +}; + +static XrmOptionDescRec opts[] = { + { "-speed", ".speed", XrmoptionSepArg, 0 }, + { "-zoom", ".zoom", XrmoptionSepArg, 0 }, + { "-ticks", ".ticks", XrmoptionSepArg, 0 }, + { "-bigdots", ".bigdots", XrmoptionNoArg, "True" }, + { "+bigdots", ".bigdots", XrmoptionNoArg, "False" }, +}; + +ENTRYPOINT ModeSpecOpt cubicgrid_opts = {countof(opts), opts, countof(vars), vars, NULL}; + +#ifdef USE_MODULES +ModStruct cubicgrid_description = +{ "cubicgrid", "init_cubicgrid", "draw_cubicgrid", "release_cubicgrid", + "draw_cubicgrid", "change_cubicgrid", NULL, &cubicgrid_opts, + 25000, 1, 1, 1, 1.0, 4, "", + "Shows a rotating 3D lattice from inside", 0, NULL +}; +#endif + +typedef struct { + GLXContext *glx_context; + GLfloat ratio; + GLint list; + + rotator *rot; + trackball_state *trackball; + Bool button_down_p; + int npoints; +} cubicgrid_conf; + +static cubicgrid_conf *cubicgrid = NULL; + +static const GLfloat zpos = -18.0; + +/*************************************************************************/ + +ENTRYPOINT Bool +cubicgrid_handle_event (ModeInfo *mi, XEvent *event) +{ + cubicgrid_conf *cp = &cubicgrid[MI_SCREEN(mi)]; + + if (event->xany.type == ButtonPress && + event->xbutton.button == Button1) + { + cp->button_down_p = True; + gltrackball_start (cp->trackball, + event->xbutton.x, event->xbutton.y, + MI_WIDTH (mi), MI_HEIGHT (mi)); + return True; + } + else if (event->xany.type == ButtonRelease && + event->xbutton.button == Button1) + { + cp->button_down_p = False; + return True; + } + else if (event->xany.type == ButtonPress && + (event->xbutton.button == Button4 || + event->xbutton.button == Button5 || + event->xbutton.button == Button6 || + event->xbutton.button == Button7)) + { + gltrackball_mousewheel (cp->trackball, event->xbutton.button, 2, + !!event->xbutton.state); + return True; + } + else if (event->xany.type == MotionNotify && + cp->button_down_p) + { + gltrackball_track (cp->trackball, + event->xmotion.x, event->xmotion.y, + MI_WIDTH (mi), MI_HEIGHT (mi)); + return True; + } + + return False; +} + + +static Bool draw_main(cubicgrid_conf *cp) +{ + double x, y, z; + + glClear(GL_COLOR_BUFFER_BIT); + glLoadIdentity(); + glTranslatef(0, 0, zpos); + + glScalef(size/ticks, size/ticks, size/ticks); + + /* Do it twice because we don't track the device's orientation. */ + glRotatef( current_device_rotation(), 0, 0, 1); + gltrackball_rotate (cp->trackball); + glRotatef(-current_device_rotation(), 0, 0, 1); + + get_rotation (cp->rot, &x, &y, &z, !cp->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); + + glTranslatef(-ticks/2.0, -ticks/2.0, -ticks/2.0); + glCallList(cp->list); + return True; +} + +static void init_gl(ModeInfo *mi) +{ + cubicgrid_conf *cp = &cubicgrid[MI_SCREEN(mi)]; + int x, y, z; + float tf = ticks; + + glDrawBuffer(GL_BACK); + if(bigdots) { + glPointSize(2.0); + } + glPixelStorei(GL_UNPACK_ALIGNMENT, 1); + glShadeModel(GL_FLAT); + + cp->list = glGenLists(1); + glNewList(cp->list, GL_COMPILE); + if(MI_IS_MONO(mi)) { + glColor3f(1.0, 1.0, 1.0); + glBegin(GL_POINTS); + for(x = 0; x < ticks; x++) { + for(y = 0; y < ticks; y++) { + for(z = 0; z < ticks; z++) { + glVertex3f(x, y, z); + cp->npoints++; + } + } + } + glEnd(); + } + else + { + glBegin(GL_POINTS); + for(x = 0; x < ticks; x++) { + for(y = 0; y < ticks; y++) { + for(z = 0; z < ticks; z++) { + glColor3f(x/tf, y/tf, z/tf); + glVertex3f(x, y, z); + cp->npoints++; + } + } + } + glEnd(); + } + glEndList(); +} + +/*************************************************************************/ + +ENTRYPOINT void reshape_cubicgrid(ModeInfo *mi, int width, int height) +{ + cubicgrid_conf *cp = &cubicgrid[MI_SCREEN(mi)]; + if(!height) height = 1; + cp->ratio = (GLfloat)width/(GLfloat)height; + glViewport(0, 0, (GLint) width, (GLint) height); + glMatrixMode(GL_PROJECTION); + glLoadIdentity(); + gluPerspective(30.0, cp->ratio, 1.0, 100.0); + glMatrixMode(GL_MODELVIEW); + glClear(GL_COLOR_BUFFER_BIT); +} + +ENTRYPOINT void release_cubicgrid(ModeInfo *mi) +{ + if (cubicgrid != NULL) { + int screen; + for (screen = 0; screen < MI_NUM_SCREENS(mi); screen++) { + cubicgrid_conf *cp = &cubicgrid[screen]; + if (cp->glx_context) { + cp->glx_context = NULL; + } + } + free((void *)cubicgrid); + cubicgrid = NULL; + } + FreeAllGL(mi); +} + +ENTRYPOINT void init_cubicgrid(ModeInfo *mi) +{ + cubicgrid_conf *cp; + if(!cubicgrid) { + cubicgrid = (cubicgrid_conf *)calloc(MI_NUM_SCREENS(mi), sizeof(cubicgrid_conf)); + if(!cubicgrid) return; + } + cp = &cubicgrid[MI_SCREEN(mi)]; + + if ((cp->glx_context = init_GL(mi)) != NULL) { + init_gl(mi); + reshape_cubicgrid(mi, MI_WIDTH(mi), MI_HEIGHT(mi)); + } else { + MI_CLEARWINDOW(mi); + } + + { + double spin_speed = 0.045 * speed; + double spin_accel = 0.005 * speed; + + cp->rot = make_rotator (spin_speed, spin_speed, spin_speed, + spin_accel, 0, True); + cp->trackball = gltrackball_init (); + } +} + +ENTRYPOINT void draw_cubicgrid(ModeInfo * mi) +{ + Display *display = MI_DISPLAY(mi); + Window window = MI_WINDOW(mi); + cubicgrid_conf *cp; + if (!cubicgrid) return; + cp = &cubicgrid[MI_SCREEN(mi)]; + MI_IS_DRAWN(mi) = True; + if (!cp->glx_context) return; + glXMakeCurrent(display, window, *(cp->glx_context)); + if (!draw_main(cp)) { + release_cubicgrid(mi); + return; + } + mi->polygon_count = cp->npoints; + if (MI_IS_FPS(mi)) do_fps (mi); + glFlush(); + glXSwapBuffers(display, window); +} + +#ifndef STANDALONE +ENTRYPOINT void change_cubicgrid(ModeInfo * mi) +{ + cubicgrid_conf *cp = &cubicgrid[MI_SCREEN(mi)]; + if (!cp->glx_context) return; + glXMakeCurrent(MI_DISPLAY(mi), MI_WINDOW(mi), *(cp->glx_context)); + init_gl(mi); +} +#endif /* !STANDALONE */ + + +XSCREENSAVER_MODULE ("CubicGrid", cubicgrid) + +#endif diff --git a/hacks/glx/cubicgrid.man b/hacks/glx/cubicgrid.man new file mode 100644 index 00000000..d267bc3c --- /dev/null +++ b/hacks/glx/cubicgrid.man @@ -0,0 +1,83 @@ +.TH XScreenSaver 1 "Dec-28-07" "X Version 11" +.SH NAME +cubicgrid - rotating 3D lattice seen from inside +.SH SYNOPSIS +.B cubicgrid +[\-display \fIhost:display.screen\fP] +[\-visual \fIvisual\fP] +[\-window] +[\-root] +[\-install] +[\-delay \fImicroseconds\fP] +[\-mono] +[\-speed \fInumber\fP] +[\-zoom \fInumber\fP] +[\-ticks \fInumber\fP] +[\-bigdots] +[\-fps] +.SH DESCRIPTION +This program shows the view of an observer located inside a set of points +arranged to a 3D lattice. As the lattice rotates, various view-throughs appear +and evolve. A simple idea with interesting results. +.SH OPTIONS +.I cubicgrid +accepts the following options: +.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 \-install +Install a private colormap for the window. +.TP 8 +.B \-visual \fIvisual\fP\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 \-delay \fImicroseconds\fP +How long to pause between frames. Default is 20000, or 0.02 second. +.TP 8 +.B \-mono +Draw in black and white. If not used, a fixed all-color scheme is chosen. +.TP 8 +.B \-speed \fInumber\fP +The maximum speed of the rotation. The actual speed and axis change smoothly +for better effect. 0.5 - 10. The default is 1.0. +.TP 8 +.B \-zoom \fInumber\fP +Size of the lattice. Ideally it should fill all the screen, but one may find +other values also interesting. 5 - 50. The default of 20 should do for common +screen aspect ratios. +.TP 8 +.B \-ticks \fInumber\fP +The count of points drawn along every axis. 10 - 100. The default is 30. +.TP 8 +.B \-bigdots +Draw the points twice as big. +.TP 8 +.B \-fps +Display the current frame rate, CPU load, and polygon count. +.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 2007 by Vasek Potocek. 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 +Vasek Potocek , Dec-28-07. diff --git a/hacks/glx/dangerball.c b/hacks/glx/dangerball.c new file mode 100644 index 00000000..7b709092 --- /dev/null +++ b/hacks/glx/dangerball.c @@ -0,0 +1,388 @@ +/* dangerball, Copyright (c) 2001-2008 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. + */ + +#define DEFAULTS "*delay: 30000 \n" \ + "*count: 30 \n" \ + "*showFPS: False \n" \ + "*wireframe: False \n" \ + +# define refresh_ball 0 +# define release_ball 0 +#undef countof +#define countof(x) (sizeof((x))/sizeof((*x))) + +#include "xlockmore.h" +#include "colors.h" +#include "sphere.h" +#include "tube.h" +#include "rotator.h" +#include "gltrackball.h" +#include + +#ifdef USE_GL /* whole file */ + + +#define DEF_SPIN "True" +#define DEF_WANDER "True" +#define DEF_SPEED "0.05" + +#define SPIKE_FACES 12 /* how densely to render spikes */ +#define SMOOTH_SPIKES True +#define SPHERE_SLICES 32 /* how densely to render spheres */ +#define SPHERE_STACKS 16 + + +typedef struct { + GLXContext *glx_context; + rotator *rot; + trackball_state *trackball; + Bool button_down_p; + + GLuint ball_list; + GLuint spike_list; + + GLfloat pos; + int *spikes; + + int ncolors; + XColor *colors; + int ccolor; + int color_shift; + +} ball_configuration; + +static ball_configuration *bps = NULL; + +static Bool do_spin; +static GLfloat speed; +static Bool do_wander; + +static XrmOptionDescRec opts[] = { + { "-spin", ".spin", XrmoptionNoArg, "True" }, + { "+spin", ".spin", XrmoptionNoArg, "False" }, + { "-speed", ".speed", XrmoptionSepArg, 0 }, + { "-wander", ".wander", XrmoptionNoArg, "True" }, + { "+wander", ".wander", XrmoptionNoArg, "False" } +}; + +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}, +}; + +ENTRYPOINT ModeSpecOpt ball_opts = {countof(opts), opts, countof(vars), vars, NULL}; + + +/* Window management, etc + */ +ENTRYPOINT void +reshape_ball (ModeInfo *mi, int width, int height) +{ + GLfloat h = (GLfloat) height / (GLfloat) width; + + glViewport (0, 0, (GLint) width, (GLint) height); + + glMatrixMode(GL_PROJECTION); + glLoadIdentity(); + gluPerspective (30.0, 1/h, 1.0, 100.0); + + glMatrixMode(GL_MODELVIEW); + glLoadIdentity(); + gluLookAt( 0.0, 0.0, 30.0, + 0.0, 0.0, 0.0, + 0.0, 1.0, 0.0); + + glClear(GL_COLOR_BUFFER_BIT); +} + + +static void +randomize_spikes (ModeInfo *mi) +{ + ball_configuration *bp = &bps[MI_SCREEN(mi)]; + int i; + bp->pos = 0; + for (i = 0; i < MI_COUNT(mi); i++) + { + bp->spikes[i*2] = (random() % 360) - 180; + bp->spikes[i*2+1] = (random() % 180) - 90; + } + +# define ROT_SCALE 22 + for (i = 0; i < MI_COUNT(mi) * 2; i++) + bp->spikes[i] = (bp->spikes[i] / ROT_SCALE) * ROT_SCALE; + + if ((random() % 3) == 0) + bp->color_shift = random() % (bp->ncolors / 2); + else + bp->color_shift = 0; +} + +static void +draw_spikes (ModeInfo *mi) +{ + ball_configuration *bp = &bps[MI_SCREEN(mi)]; + GLfloat diam = 0.2; + GLfloat pos = bp->pos; + int i; + + if (pos < 0) pos = -pos; + + pos = (asin (0.5 + pos/2) - 0.5) * 2; + + for (i = 0; i < MI_COUNT(mi); i++) + { + glPushMatrix(); + glRotatef(bp->spikes[i*2], 0, 1, 0); + glRotatef(bp->spikes[i*2+1], 0, 0, 1); + glTranslatef(0.7, 0, 0); + glRotatef(-90, 0, 0, 1); + glScalef (diam, pos, diam); + glCallList (bp->spike_list); + glPopMatrix(); + + mi->polygon_count += (SPIKE_FACES + 1); + } +} + + +static void +move_spikes (ModeInfo *mi) +{ + ball_configuration *bp = &bps[MI_SCREEN(mi)]; + + if (bp->pos >= 0) /* moving outward */ + { + bp->pos += speed; + if (bp->pos >= 1) /* reverse gears at apex */ + bp->pos = -1; + } + else /* moving inward */ + { + bp->pos += speed; + if (bp->pos >= 0) /* stop at end */ + randomize_spikes (mi); + } +} + + +ENTRYPOINT Bool +ball_handle_event (ModeInfo *mi, XEvent *event) +{ + ball_configuration *bp = &bps[MI_SCREEN(mi)]; + + if (event->xany.type == ButtonPress && + event->xbutton.button == Button1) + { + bp->button_down_p = True; + gltrackball_start (bp->trackball, + event->xbutton.x, event->xbutton.y, + MI_WIDTH (mi), MI_HEIGHT (mi)); + return True; + } + else if (event->xany.type == ButtonRelease && + event->xbutton.button == Button1) + { + bp->button_down_p = False; + return True; + } + else if (event->xany.type == ButtonPress && + (event->xbutton.button == Button4 || + event->xbutton.button == Button5 || + event->xbutton.button == Button6 || + event->xbutton.button == Button7)) + { + gltrackball_mousewheel (bp->trackball, event->xbutton.button, 10, + !!event->xbutton.state); + return True; + } + else if (event->xany.type == MotionNotify && + bp->button_down_p) + { + gltrackball_track (bp->trackball, + event->xmotion.x, event->xmotion.y, + MI_WIDTH (mi), MI_HEIGHT (mi)); + return True; + } + + return False; +} + + +ENTRYPOINT void +init_ball (ModeInfo *mi) +{ + ball_configuration *bp; + int wire = MI_IS_WIREFRAME(mi); + + if (!bps) { + bps = (ball_configuration *) + calloc (MI_NUM_SCREENS(mi), sizeof (ball_configuration)); + if (!bps) { + fprintf(stderr, "%s: out of memory\n", progname); + exit(1); + } + } + + bp = &bps[MI_SCREEN(mi)]; + + bp->glx_context = init_GL(mi); + + reshape_ball (mi, MI_WIDTH(mi), MI_HEIGHT(mi)); + + if (!wire) + { + GLfloat pos[4] = {1.0, 1.0, 1.0, 0.0}; + GLfloat amb[4] = {0.0, 0.0, 0.0, 1.0}; + GLfloat dif[4] = {1.0, 1.0, 1.0, 1.0}; + GLfloat spc[4] = {0.0, 1.0, 1.0, 1.0}; + + glEnable(GL_LIGHTING); + glEnable(GL_LIGHT0); + glEnable(GL_DEPTH_TEST); + glEnable(GL_CULL_FACE); + + glLightfv(GL_LIGHT0, GL_POSITION, pos); + glLightfv(GL_LIGHT0, GL_AMBIENT, amb); + glLightfv(GL_LIGHT0, GL_DIFFUSE, dif); + glLightfv(GL_LIGHT0, GL_SPECULAR, spc); + } + + { + double spin_speed = 10.0; + double wander_speed = 0.12; + double spin_accel = 2.0; + + bp->rot = make_rotator (do_spin ? spin_speed : 0, + do_spin ? spin_speed : 0, + do_spin ? spin_speed : 0, + spin_accel, + do_wander ? wander_speed : 0, + True); + bp->trackball = gltrackball_init (); + } + + bp->ncolors = 128; + bp->colors = (XColor *) calloc(bp->ncolors, sizeof(XColor)); + make_smooth_colormap (0, 0, 0, + bp->colors, &bp->ncolors, + False, 0, False); + + bp->spikes = (int *) calloc(MI_COUNT(mi), sizeof(*bp->spikes) * 2); + + bp->ball_list = glGenLists (1); + bp->spike_list = glGenLists (1); + + glNewList (bp->ball_list, GL_COMPILE); + unit_sphere (SPHERE_STACKS, SPHERE_SLICES, wire); + glEndList (); + + glNewList (bp->spike_list, GL_COMPILE); + cone (0, 0, 0, + 0, 1, 0, + 1, 0, SPIKE_FACES, SMOOTH_SPIKES, False, wire); + glEndList (); + + randomize_spikes (mi); +} + + +ENTRYPOINT void +draw_ball (ModeInfo *mi) +{ + ball_configuration *bp = &bps[MI_SCREEN(mi)]; + Display *dpy = MI_DISPLAY(mi); + Window window = MI_WINDOW(mi); + int c2; + + static const GLfloat bspec[4] = {1.0, 1.0, 1.0, 1.0}; + static const GLfloat sspec[4] = {0.0, 0.0, 0.0, 1.0}; + static const GLfloat bshiny = 128.0; + static const GLfloat sshiny = 0.0; + + GLfloat bcolor[4] = {0.0, 0.0, 0.0, 1.0}; + GLfloat scolor[4] = {0.0, 0.0, 0.0, 1.0}; + + if (!bp->glx_context) + return; + + glXMakeCurrent(MI_DISPLAY(mi), MI_WINDOW(mi), *(bp->glx_context)); + + glShadeModel(GL_SMOOTH); + + glEnable(GL_DEPTH_TEST); + glEnable(GL_NORMALIZE); + glEnable(GL_CULL_FACE); + + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + + glPushMatrix (); + + glScalef(1.1, 1.1, 1.1); + + { + double x, y, z; + get_position (bp->rot, &x, &y, &z, !bp->button_down_p); + glTranslatef((x - 0.5) * 8, + (y - 0.5) * 8, + (z - 0.5) * 15); + + /* Do it twice because we don't track the device's orientation. */ + glRotatef( current_device_rotation(), 0, 0, 1); + gltrackball_rotate (bp->trackball); + glRotatef(-current_device_rotation(), 0, 0, 1); + + get_rotation (bp->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); + } + + bcolor[0] = bp->colors[bp->ccolor].red / 65536.0; + bcolor[1] = bp->colors[bp->ccolor].green / 65536.0; + bcolor[2] = bp->colors[bp->ccolor].blue / 65536.0; + + c2 = (bp->ccolor + bp->color_shift) % bp->ncolors; + scolor[0] = bp->colors[c2].red / 65536.0; + scolor[1] = bp->colors[c2].green / 65536.0; + scolor[2] = bp->colors[c2].blue / 65536.0; + + bp->ccolor++; + if (bp->ccolor >= bp->ncolors) bp->ccolor = 0; + + mi->polygon_count = 0; + + glScalef (2.0, 2.0, 2.0); + + move_spikes (mi); + + glMaterialfv (GL_FRONT, GL_SPECULAR, bspec); + glMateriali (GL_FRONT, GL_SHININESS, bshiny); + glMaterialfv (GL_FRONT, GL_AMBIENT_AND_DIFFUSE, bcolor); + glCallList (bp->ball_list); + mi->polygon_count += (SPHERE_SLICES * SPHERE_STACKS); + + glMaterialfv (GL_FRONT, GL_SPECULAR, sspec); + glMaterialf (GL_FRONT, GL_SHININESS, sshiny); + glMaterialfv (GL_FRONT, GL_AMBIENT_AND_DIFFUSE, scolor); + draw_spikes (mi); + glPopMatrix (); + + if (mi->fps_p) do_fps (mi); + glFinish(); + + glXSwapBuffers(dpy, window); +} + +XSCREENSAVER_MODULE_2 ("DangerBall", dangerball, ball) + +#endif /* USE_GL */ diff --git a/hacks/glx/dangerball.man b/hacks/glx/dangerball.man new file mode 100644 index 00000000..3e33f827 --- /dev/null +++ b/hacks/glx/dangerball.man @@ -0,0 +1,72 @@ +.TH XScreenSaver 1 "" "X Version 11" +.SH NAME +dangerball - a 3D ball that periodically extrudes spikes. Ouch! +.SH SYNOPSIS +.B dangerball +[\-display \fIhost:display.screen\fP] +[\-visual \fIvisual\fP] +[\-window] +[\-root] +[\-delay \fInumber\fP] +[\-speed \fInumber\fP] +[\-count \fInumber\fP] +[\-no-wander] +[\-no-spin] +[\-wireframe] +[\-fps] +.SH DESCRIPTION +Draws a ball that periodically extrudes many random spikes. Ouch! +.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 \-speed \fInumber\fP +Spike growth frequency. 0.0 - 0.25. Default: 0.05. +.TP 8 +.B \-count \fInumber\fP +Number o spikes. Default: 30. +.TP 8 +.B \-wander | \-no-wander +Whether the object should wander around the screen. +.TP 8 +.B \-spin | \-no-spin +Whether the object should spin. +.TP 8 +.B \-wireframe | \-no-wireframe +Render in wireframe instead of solid. +.TP 8 +.B \-fps +Display the current frame rate, CPU load, and polygon count. +.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 2002 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/glx/dnalogo.c b/hacks/glx/dnalogo.c new file mode 100644 index 00000000..1b192428 --- /dev/null +++ b/hacks/glx/dnalogo.c @@ -0,0 +1,2467 @@ +/* DNA Logo, Copyright (c) 2001-2011 Jamie Zawinski + * + * DNA Lounge + * + * Restaurant -- Bar -- Nightclub -- Cafe -- Est. 1985. + * + * 375 Eleventh Street + * San Francisco, CA + * 94103 + * + * http://www.dnalounge.com/ + * http://www.dnapizza.com/ + * + * 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. + */ + +#define DEFAULTS __extension__ \ + "*delay: 25000 \n" \ + "*showFPS: False \n" \ + "*wireframe: False \n" \ + "*doGasket: True \n" \ + "*doHelix: True \n" \ + "*doLadder: True \n" \ + "*doFrame: True \n" \ + "*wallFacets: 360 \n" \ + "*barFacets: 90 \n" \ + "*clockwise: False \n" \ + "*turns: 0.69 \n" \ + "*turnSpacing: 2.2 \n" \ + "*barSpacing: 0.24 \n" \ + "*wallHeight: 0.45 \n" \ + "*wallThickness: 0.12 \n" \ + "*barThickness: 0.058 \n" \ + "*wallTaper: 0.95 \n" \ + "*gasketSize: 1.88 \n" \ + "*gasketDepth: 0.15 \n" \ + "*gasketThickness: 0.4 \n" \ + "*frameSize: 1.20 \n" \ + "*frameDepth: 0.01 \n" \ + "*frameThickness: 0.03 \n" \ + "*triangleSize: 0.045 \n" \ + "*speed: 1.0 \n" \ + "*mode: both" "\n" \ + ".foreground: #00AA00 \n" \ + "*geometry: =640x640\n" \ + +# define refresh_logo 0 +# define release_logo 0 +#undef countof +#define countof(x) (sizeof((x))/sizeof((*x))) + +#ifdef DXF_OUTPUT_HACK /* When this is defined, instead of rendering + to the screen, we write a DXF CAD file to stdout. + This is a kludge of shocking magnitude... + Maybe there's some other way to intercept all + glVertex3f calls than with a #define? */ +# define unit_tube dxf_unit_tube +# define unit_cone dxf_unit_cone +# define tube_1 dxf_tube_1 +# define tube dxf_tube +# define cone dxf_cone +#endif /* DXF_OUTPUT_HACK */ + +#include "xlockmore.h" +#include "normals.h" +#include "tube.h" +#include "rotator.h" +#include "gltrackball.h" + +#ifdef USE_GL /* whole file */ + +#ifdef HAVE_JWZGLES +# include "dnapizza.h" +#else +# define HAVE_TESS +#endif + +typedef enum { + HELIX_IN, HELIX, HELIX_OUT, + PIZZA_IN, PIZZA, PIZZA_OUT, + BOTH +} glyph_mode; + +typedef struct { + Bool spinning_p; + GLfloat position; /* 0.0 - 1.0 */ + GLfloat speed; /* how far along the path (may be negative) */ + GLfloat probability; /* relative likelyhood to start spinning */ +} spinner; + +typedef struct { + GLXContext *glx_context; + + GLuint helix_list, helix_list_wire, helix_list_facetted; + GLuint pizza_list, pizza_list_wire, pizza_list_facetted; + GLuint gasket_list, gasket_list_wire; + GLuint frame_list, frame_list_wire; + int polys[7]; + + int wall_facets; + int bar_facets; + Bool clockwise; + GLfloat color[4]; + + GLfloat turns; + GLfloat turn_spacing; + GLfloat bar_spacing; + GLfloat wall_height; + GLfloat wall_thickness; + GLfloat bar_thickness; + GLfloat wall_taper; + + GLfloat gasket_size; + GLfloat gasket_depth; + GLfloat gasket_thickness; + + GLfloat frame_size; + GLfloat frame_depth; + GLfloat frame_thickness; + GLfloat triangle_size; + + GLfloat speed; + glyph_mode mode; + glyph_mode anim_state; + GLfloat anim_ratio; + + spinner gasket_spinnerx, gasket_spinnery, gasket_spinnerz; + spinner scene_spinnerx, scene_spinnery; + spinner helix_spinnerz; + spinner pizza_spinnery, pizza_spinnerz; + spinner frame_spinner; + + trackball_state *trackball; + Bool button_down_p; + + int wire_overlay; /* frame countdown */ + +} logo_configuration; + +static logo_configuration *dcs = NULL; + +static XrmOptionDescRec opts[] = { + { "-speed", ".speed", XrmoptionSepArg, 0 }, + { "-mode", ".mode", XrmoptionSepArg, 0 }, + { "-pizza", ".mode", XrmoptionNoArg, "pizza" }, + { "-helix", ".mode", XrmoptionNoArg, "helix" }, + { "-both", ".mode", XrmoptionNoArg, "both" }, +}; + +ENTRYPOINT ModeSpecOpt logo_opts = {countof(opts), opts, 0, NULL, NULL}; + +#define PROBABILITY_SCALE 600 + + +#ifdef DXF_OUTPUT_HACK + +# define glBegin dxf_glBegin +# define glVertex3f dxf_glVertex3f +# define glVertex3dv dxf_glVertex3dv +# define glEnd dxf_glEnd +# define glVertexPointer dxf_glVertexPointer +# define glDrawArrays dxf_glDrawArrays + +static int dxf_type, dxf_point, dxf_point_total, dxf_layer, dxf_color; +static GLfloat dxf_quads[4*4]; + +static void +dxf_glBegin (int type) +{ + dxf_type = type; + dxf_point = 0; + dxf_point_total = 0; +} + +static void +dxf_glVertex3f (GLfloat ox, GLfloat oy, GLfloat oz) +{ + int i = 0; + GLfloat m[4*4]; + GLfloat x, y, z; + + /* Transform the point into modelview space. */ + glGetFloatv (GL_MODELVIEW_MATRIX, m); + x = ox * m[0] + oy * m[4] + oz * m[8] + m[12]; + y = ox * m[1] + oy * m[5] + oz * m[9] + m[13]; + z = ox * m[2] + oy * m[6] + oz * m[10] + m[14]; + + dxf_quads[dxf_point*3+0] = x; + dxf_quads[dxf_point*3+1] = y; + dxf_quads[dxf_point*3+2] = z; + dxf_point++; + dxf_point_total++; + + switch (dxf_type) { + case GL_QUADS: + if (dxf_point < 4) return; + + fprintf (stdout, "0\n3DFACE\n8\n%d\n62\n%d\n", dxf_layer, dxf_color); + fprintf (stdout, "10\n%.6f\n", dxf_quads[i++]); + fprintf (stdout, "20\n%.6f\n", dxf_quads[i++]); + fprintf (stdout, "30\n%.6f\n", dxf_quads[i++]); + + fprintf (stdout, "11\n%.6f\n", dxf_quads[i++]); + fprintf (stdout, "21\n%.6f\n", dxf_quads[i++]); + fprintf (stdout, "31\n%.6f\n", dxf_quads[i++]); + + fprintf (stdout, "12\n%.6f\n", dxf_quads[i++]); + fprintf (stdout, "22\n%.6f\n", dxf_quads[i++]); + fprintf (stdout, "32\n%.6f\n", dxf_quads[i++]); + + fprintf (stdout, "13\n%.6f\n", dxf_quads[i++]); + fprintf (stdout, "23\n%.6f\n", dxf_quads[i++]); + fprintf (stdout, "33\n%.6f\n", dxf_quads[i++]); + dxf_point = 0; + break; + + case GL_QUAD_STRIP: + if (dxf_point < 4) return; + + fprintf (stdout, "0\n3DFACE\n8\n%d\n62\n%d\n", dxf_layer, dxf_color); + fprintf (stdout, "10\n%.6f\n", dxf_quads[i++]); + fprintf (stdout, "20\n%.6f\n", dxf_quads[i++]); + fprintf (stdout, "30\n%.6f\n", dxf_quads[i++]); + + fprintf (stdout, "11\n%.6f\n", dxf_quads[i++]); + fprintf (stdout, "21\n%.6f\n", dxf_quads[i++]); + fprintf (stdout, "31\n%.6f\n", dxf_quads[i++]); + + fprintf (stdout, "12\n%.6f\n", dxf_quads[i+3]); /* funky quad strip */ + fprintf (stdout, "22\n%.6f\n", dxf_quads[i+4]); /* vert order: 1243. */ + fprintf (stdout, "32\n%.6f\n", dxf_quads[i+5]); + + fprintf (stdout, "13\n%.6f\n", dxf_quads[i]); + fprintf (stdout, "23\n%.6f\n", dxf_quads[i+1]); + fprintf (stdout, "33\n%.6f\n", dxf_quads[i+2]); + i += 6; + + dxf_quads[0] = dxf_quads[6]; /* copy point 3 to pos 1 */ + dxf_quads[1] = dxf_quads[7]; + dxf_quads[2] = dxf_quads[8]; + dxf_quads[3] = dxf_quads[9]; /* copy point 4 to pos 2 */ + dxf_quads[4] = dxf_quads[10]; + dxf_quads[5] = dxf_quads[11]; + dxf_point = 2; /* leave those two points in queue */ + break; + + case GL_TRIANGLES: + case GL_TRIANGLE_FAN: + if (dxf_point < 3) return; + + fprintf (stdout, "0\n3DFACE\n8\n%d\n62\n%d\n", dxf_layer, dxf_color); + fprintf (stdout, "10\n%.6f\n", dxf_quads[i++]); + fprintf (stdout, "20\n%.6f\n", dxf_quads[i++]); + fprintf (stdout, "30\n%.6f\n", dxf_quads[i++]); + + fprintf (stdout, "11\n%.6f\n", dxf_quads[i++]); + fprintf (stdout, "21\n%.6f\n", dxf_quads[i++]); + fprintf (stdout, "31\n%.6f\n", dxf_quads[i++]); + + fprintf (stdout, "12\n%.6f\n", dxf_quads[i++]); + fprintf (stdout, "22\n%.6f\n", dxf_quads[i++]); + fprintf (stdout, "32\n%.6f\n", dxf_quads[i++]); + + i -= 3; + fprintf (stdout, "13\n%.6f\n", dxf_quads[i++]); /* dup pt 4 as pt 3. */ + fprintf (stdout, "23\n%.6f\n", dxf_quads[i++]); + fprintf (stdout, "33\n%.6f\n", dxf_quads[i++]); + + dxf_point = 0; + if (dxf_type == GL_TRIANGLE_FAN) + { + dxf_quads[3] = dxf_quads[6]; /* copy point 3 to point 2 */ + dxf_quads[4] = dxf_quads[7]; + dxf_quads[5] = dxf_quads[8]; + dxf_point = 2; /* leave two points in queue */ + } + break; + + case GL_TRIANGLE_STRIP: + if (dxf_point < 3) return; + + fprintf (stdout, "0\n3DFACE\n8\n%d\n62\n%d\n", dxf_layer, dxf_color); + + fprintf (stdout, "10\n%.6f\n", dxf_quads[i++]); + fprintf (stdout, "20\n%.6f\n", dxf_quads[i++]); + fprintf (stdout, "30\n%.6f\n", dxf_quads[i++]); + + fprintf (stdout, "11\n%.6f\n", dxf_quads[i++]); + fprintf (stdout, "21\n%.6f\n", dxf_quads[i++]); + fprintf (stdout, "31\n%.6f\n", dxf_quads[i++]); + + fprintf (stdout, "12\n%.6f\n", dxf_quads[i++]); + fprintf (stdout, "22\n%.6f\n", dxf_quads[i++]); + fprintf (stdout, "32\n%.6f\n", dxf_quads[i++]); + + i -= 3; + fprintf (stdout, "13\n%.6f\n", dxf_quads[i++]); /* dup pt 4 as pt 3. */ + fprintf (stdout, "23\n%.6f\n", dxf_quads[i++]); + fprintf (stdout, "33\n%.6f\n", dxf_quads[i++]); + + dxf_quads[0] = dxf_quads[3]; /* copy point 2 to pos 1 */ + dxf_quads[1] = dxf_quads[4]; + dxf_quads[2] = dxf_quads[5]; + dxf_quads[3] = dxf_quads[6]; /* copy point 3 to pos 2 */ + dxf_quads[4] = dxf_quads[7]; + dxf_quads[5] = dxf_quads[8]; + dxf_point = 2; /* leave those two points in queue */ + break; + + case GL_LINES: + case GL_LINE_STRIP: + case GL_LINE_LOOP: + + if (dxf_point_total == 1) + { + dxf_quads[6] = ox; + dxf_quads[7] = oy; + dxf_quads[8] = oz; + } + + if (dxf_point < 2) return; + + fprintf (stdout, "0\nLINE\n8\n%d\n62\n%d\n", dxf_layer, dxf_color); + + fprintf (stdout, "10\n%.6f\n", dxf_quads[i++]); + fprintf (stdout, "20\n%.6f\n", dxf_quads[i++]); + fprintf (stdout, "30\n%.6f\n", dxf_quads[i++]); + + fprintf (stdout, "11\n%.6f\n", dxf_quads[i++]); + fprintf (stdout, "21\n%.6f\n", dxf_quads[i++]); + fprintf (stdout, "31\n%.6f\n", dxf_quads[i++]); + + dxf_point = 0; + if (dxf_type != GL_LINES) + { + dxf_quads[0] = dxf_quads[3]; + dxf_quads[1] = dxf_quads[4]; + dxf_quads[2] = dxf_quads[5]; + dxf_point = 1; + } + break; + + default: + abort(); + break; + } +} + + +static void +dxf_glVertex3dv (const GLdouble *v) +{ + glVertex3f (v[0], v[1], v[2]); +} + + +static void +dxf_glEnd(void) +{ + if (dxf_type == GL_LINE_LOOP) /* close loop */ + glVertex3f (dxf_quads[6], dxf_quads[7], dxf_quads[8]); + dxf_type = -1; + dxf_point = 0; + dxf_point_total = 0; +} + + +static void +dxf_start (void) +{ + fprintf (stdout, "0\nSECTION\n2\nHEADER\n0\nENDSEC\n"); + fprintf (stdout, "0\nSECTION\n2\nENTITIES\n"); +} + +static void +dxf_end (void) +{ + fprintf (stdout, "0\nENDSEC\n0\nEOF\n"); + exit (0); +} + + +static const GLvoid *dxf_vp; +static GLsizei dxf_vp_size; +static GLsizei dxf_vp_stride; + +static void +dxf_glVertexPointer (GLint size, GLenum type, GLsizei stride, + const GLvoid *pointer) +{ + if (type != GL_FLOAT) abort(); + if (stride <= 0) abort(); + dxf_vp = pointer; + dxf_vp_size = size; + dxf_vp_stride = stride; +} + +static void +dxf_glDrawArrays (GLenum mode, GLint first, GLsizei count) +{ + int i; + unsigned char *a = (unsigned char *) dxf_vp; + dxf_glBegin (mode); + for (i = first; i < first+count; i++) + { + GLfloat *fa = (GLfloat *) a; + dxf_glVertex3f (fa[0], fa[1], fa[2]); + a += dxf_vp_stride; + } + dxf_glEnd(); +} + + +# define XYZ tube_XYZ /* avoid conflict with normals.h */ +# include "tube.c" /* Yes, I really am including a C file. */ +# undef XYZ + +#endif /* DXF_OUTPUT_HACK */ + + + +/* Calculate the angle (in degrees) between two vectors. + */ +static GLfloat +vector_angle (double ax, double ay, double az, + double bx, double by, double bz) +{ + double La = sqrt (ax*ax + ay*ay + az*az); + double Lb = sqrt (bx*bx + by*by + bz*bz); + double cc, angle; + + if (La == 0 || Lb == 0) return 0; + if (ax == bx && ay == by && az == bz) 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)); + */ + cc = (ax*bx + ay*by + az*bz) / (La * Lb); + if (cc > 1) cc = 1; /* avoid fp rounding error (1.000001 => sqrt error) */ + angle = acos (cc); + + return (angle * M_PI / 180); +} + + +/* Make the helix + */ + +static int +make_helix (logo_configuration *dc, int facetted, int wire) +{ + int polys = 0; + int wall_facets = dc->wall_facets / (facetted ? 10 : 1); + GLfloat th; + GLfloat max_th = M_PI * 2 * dc->turns; + GLfloat th_inc = M_PI * 2 / wall_facets; + + GLfloat x1=0, y1=0, x2=0, y2=0; + GLfloat x1b=0, y1b=0, x2b=0, y2b=0; + GLfloat z1=0, z2=0; + GLfloat h1=0, h2=0; + GLfloat h1off=0, h2off=0; + GLfloat z_inc = dc->turn_spacing / wall_facets; + + th = 0; + x1 = 1; + y1 = 0; + x1b = 1 - dc->wall_thickness; + y1b = 0; + + z1 = -(dc->turn_spacing * dc->turns / 2); + + h1 = (dc->wall_taper > 0 ? 0 : dc->wall_height / 2); + h1off = (dc->wall_taper > 0 ? -dc->wall_height / 2 : 0); + + if (!dc->clockwise) + z1 = -z1, z_inc = -z_inc, h1off = -h1off; + + /* Leading end-cap + */ + if (!wire && h1 > 0) + { + GLfloat nx, ny; + glFrontFace(GL_CCW); + glBegin(GL_QUADS); + nx = cos (th + M_PI/2); + ny = sin (th + M_PI/2); + glNormal3f(nx, ny, 0); + glVertex3f( x1, y1, z1 - h1 + h1off); + glVertex3f( x1, y1, z1 + h1 + h1off); + glVertex3f(x1b, y1b, z1 + h1 + h1off); + glVertex3f(x1b, y1b, z1 - h1 + h1off); + polys++; + glEnd(); + } + + while (th + th_inc <= max_th) + { + 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; + + if (dc->wall_taper > 0) + { + h2off = 0; + if (th < dc->wall_taper) + { + h2 = dc->wall_height/2 * cos (M_PI / 2 + * (1 - (th / dc->wall_taper))); + if (dc->clockwise) + h2off = h2 - dc->wall_height/2; + else + h2off = dc->wall_height/2 - h2; + } + else if (th >= max_th - dc->wall_taper) + { + if (th + th_inc > max_th) /* edge case: always come to a point */ + h2 = 0; + else + h2 = dc->wall_height/2 * cos (M_PI / 2 + * (1 - ((max_th - th) + / dc->wall_taper))); + if (dc->clockwise) + h2off = dc->wall_height/2 - h2; + else + h2off = h2 - dc->wall_height/2; + } + } + + /* outer face + */ + glFrontFace(GL_CW); + glBegin(wire ? GL_LINES : GL_QUADS); + glNormal3f(x1, y1, 0); + glVertex3f(x1, y1, z1 - h1 + h1off); + glVertex3f(x1, y1, z1 + h1 + h1off); + glNormal3f(x2, y2, 0); + glVertex3f(x2, y2, z2 + h2 + h2off); + glVertex3f(x2, y2, z2 - h2 + h2off); + polys++; + glEnd(); + + /* inner face + */ + glFrontFace(GL_CCW); + glBegin(wire ? GL_LINES : GL_QUADS); + glNormal3f(-x1b, -y1b, 0); + glVertex3f( x1b, y1b, z1 - h1 + h1off); + glVertex3f( x1b, y1b, z1 + h1 + h1off); + glNormal3f(-x2b, -y2b, 0); + glVertex3f( x2b, y2b, z2 + h2 + h2off); + glVertex3f( x2b, y2b, z2 - h2 + h2off); + polys++; + glEnd(); + + /* top face + */ + glFrontFace(GL_CCW); + /* glNormal3f(0, 0, 1);*/ + do_normal (x2, y2, z2 + h2 + h2off, + x2b, y2b, z2 + h2 + h2off, + x1b, y1b, z1 + h1 + h1off); + glBegin(wire ? GL_LINE_LOOP : GL_QUADS); + glVertex3f( x2, y2, z2 + h2 + h2off); + glVertex3f( x2b, y2b, z2 + h2 + h2off); + glVertex3f( x1b, y1b, z1 + h1 + h1off); + glVertex3f( x1, y1, z1 + h1 + h1off); + polys++; + glEnd(); + + /* bottom face + */ + glFrontFace(GL_CCW); + do_normal ( x1, y1, z1 - h1 + h1off, + x1b, y1b, z1 - h1 + h1off, + x2b, y2b, z2 - h2 + h2off); + glBegin(wire ? GL_LINE_LOOP : GL_QUADS); + glNormal3f(0, 0, -1); + glVertex3f( x1, y1, z1 - h1 + h1off); + glVertex3f( x1b, y1b, z1 - h1 + h1off); + glVertex3f( x2b, y2b, z2 - h2 + h2off); + glVertex3f( x2, y2, z2 - h2 + h2off); + polys++; + glEnd(); + + x1 = x2; + y1 = y2; + x1b = x2b; + y1b = y2b; + z1 += z_inc; + h1 = h2; + h1off = h2off; + } + + /* Trailing end-cap + */ + if (!wire && h2 > 0) + { + GLfloat nx, ny; + glFrontFace(GL_CW); + glBegin(GL_QUADS); + nx = cos (th + M_PI/2); + ny = sin (th + M_PI/2); + glNormal3f(nx, ny, 0); + glVertex3f(x2, y2, z1 - h2 + h2off); + glVertex3f(x2, y2, z1 + h2 + h2off); + glVertex3f(x2b, y2b, z1 + h2 + h2off); + glVertex3f(x2b, y2b, z1 - h2 + h2off); + polys++; + glEnd(); + } + return polys; +} + + +static int +make_ladder (logo_configuration *dc, int facetted, int wire) +{ + int polys = 0; + GLfloat th; + GLfloat max_th = dc->turns * M_PI * 2; + GLfloat max_z = dc->turns * dc->turn_spacing; + GLfloat z_inc = dc->bar_spacing; + GLfloat th_inc = M_PI * 2 * (dc->bar_spacing / dc->turn_spacing); + GLfloat x, y, z; + + /* skip forward to center the bars in the helix... */ + int i; + GLfloat usable_th = max_th - dc->wall_taper; + GLfloat usable_z = max_z / (max_th / usable_th); + int nbars = usable_z / dc->bar_spacing; + GLfloat used_z, pad_z, pad_ratio; + + if (! (nbars & 1)) nbars--; /* always an odd number of bars */ + + used_z = (nbars - 1) * dc->bar_spacing; + pad_z = max_z - used_z; + pad_ratio = pad_z / max_z; + + th = (max_th * pad_ratio/2); + z = -(max_z / 2) + (max_z * pad_ratio/2); + + if (!dc->clockwise) + z = -z, z_inc = -z_inc; + + glFrontFace(GL_CCW); + for (i = 0; i < nbars; i++) + { + int facets = dc->bar_facets / (facetted ? 14 : 1); + if (facets <= 3) facets = 3; + x = cos (th) * (1 - dc->wall_thickness); + y = sin (th) * (1 - dc->wall_thickness); + polys += tube ( x, y, z, + -x, -y, z, + dc->bar_thickness, 0, facets, + True, True, wire); + z += z_inc; + th += th_inc; + } + return polys; +} + + + +/* Make the gasket + */ + + +static int +make_gasket (logo_configuration *dc, int wire) +{ + int polys = 0; + int i; + int points_size; + int npoints = 0; + int nctrls = 0; + int res = 360/8; + GLfloat d2r = M_PI / 180; + + GLfloat thick2 = (dc->gasket_thickness / dc->gasket_size) / 2; + + GLfloat *pointsx0, *pointsy0, *pointsx1, *pointsy1, *normals; + + GLfloat r0 = 0.750; /* 395 */ + GLfloat r1a = 0.825; /* bottom of wall below upper left hole */ + GLfloat r1b = 0.867; /* center of upper left hole */ + GLfloat r1c = 0.909; /* top of wall above hole */ + GLfloat r1 = 0.916; /* 471 */ + GLfloat r2 = 0.963; /* 490 */ + GLfloat r3 = 0.960; /* 499 */ + GLfloat r4 = 1.000; /* 507 */ + GLfloat r5 = 1.080; /* 553 */ + + GLfloat ctrl_r[100], ctrl_th[100]; + + glPushMatrix(); + +# ifdef DXF_OUTPUT_HACK + if (! wire) res *= 8; +# endif + +# define POINT(r,th) \ + ctrl_r [nctrls] = r, \ + ctrl_th[nctrls] = (th * d2r), \ + nctrls++ + + POINT (0.829, 0); /* top indentation, right half */ + POINT (0.831, 0.85); + POINT (0.835, 1.81); + POINT (0.841, 2.65); + POINT (0.851, 3.30); + POINT (0.862, 3.81); + POINT (0.872, 3.95); + + POINT (r4, 4.0); /* moving clockwise... */ + POINT (r4, 47.0); + POINT (r1, 47.0); + POINT (r1, 53.0); + POINT (r2, 55.5); + POINT (r2, 72.3); + POINT (r1, 74.0); + POINT (r1, 100.0); + POINT (r3, 102.5); + POINT (r3, 132.0); + POINT (r1, 133.0); + + POINT (r1, 180.7); + POINT (r2, 183.6); + POINT (r2, 210.0); + POINT (r1, 212.0); + POINT (r1, 223.2); + POINT (r5, 223.2); + POINT (r5, 225.0); + POINT (r4, 225.0); + + POINT (r4, 316.8); /* upper left indentation */ + POINT (0.990, 316.87); + POINT (0.880, 317.21); + POINT (0.872, 317.45); + POINT (0.869, 317.80); + POINT (0.867, 318.10); + + POINT (0.867, 318.85); + POINT (0.869, 319.15); + POINT (0.872, 319.50); + POINT (0.880, 319.74); + POINT (0.990, 320.08); + + POINT (r4, 338.0); + if (! wire) + { + POINT (r1a, 338.0); /* cut-out disc */ + POINT (r1a, 344.0); + } + POINT (r4, 344.0); + POINT (r4, 356.0); + + POINT (0.872, 356.05); /* top indentation, left half */ + POINT (0.862, 356.19); + POINT (0.851, 356.70); + POINT (0.841, 357.35); + POINT (0.835, 358.19); + POINT (0.831, 359.15); + POINT (0.829, 360); +# undef POINT + + points_size = res + (nctrls * 2); + pointsx0 = (GLfloat *) malloc (points_size * sizeof(GLfloat)); + pointsy0 = (GLfloat *) malloc (points_size * sizeof(GLfloat)); + pointsx1 = (GLfloat *) malloc (points_size * sizeof(GLfloat)); + pointsy1 = (GLfloat *) malloc (points_size * sizeof(GLfloat)); + normals = (GLfloat *) malloc (points_size * sizeof(GLfloat) * 2); + + npoints = 0; + for (i = 1; i < nctrls; i++) + { + GLfloat from_r = ctrl_r [i-1]; + GLfloat from_th = ctrl_th[i-1]; + GLfloat to_r = ctrl_r [i]; + GLfloat to_th = ctrl_th[i]; + + GLfloat step = 2*M_PI / res; + int nsteps = 1 + ((to_th - from_th) / step); + int j; + + for (j = 0; j < nsteps + (i == nctrls-1); j++) + { + GLfloat r = from_r + (j * (to_r - from_r) / nsteps); + GLfloat th = from_th + (j * (to_th - from_th) / nsteps); + + GLfloat cth = cos(th) * dc->gasket_size; + GLfloat sth = sin(th) * dc->gasket_size; + + pointsx0[npoints] = r0 * cth; /* inner ring */ + pointsy0[npoints] = r0 * sth; + pointsx1[npoints] = r * cth; /* outer ring */ + pointsy1[npoints] = r * sth; + npoints++; + + if (npoints >= points_size) abort(); + } + } + + /* normals for the outer ring */ + for (i = 1; i < npoints; i++) + { + XYZ a, b, c, n; + a.x = pointsx1[i-1]; + a.y = pointsy1[i-1]; + a.z = 0; + b.x = pointsx1[i]; + b.y = pointsy1[i]; + b.z = 0; + c = b; + c.z = 1; + n = calc_normal (a, b, c); + normals[(i-1)*2 ] = n.x; + normals[(i-1)*2+1] = n.y; + } + + glRotatef(-90, 0, 1, 0); + glRotatef(180, 0, 0, 1); + + if (wire) + { + GLfloat z; + for (z = -thick2; z <= thick2; z += thick2*2) + { +# if 1 + /* inside edge */ + glBegin (GL_LINE_LOOP); + for (i = 0; i < npoints; i++) + glVertex3f (pointsx0[i], pointsy0[i], z); + polys += npoints; + glEnd(); + + /* outside edge */ + glBegin (GL_LINE_LOOP); + for (i = 0; i < npoints; i++) + glVertex3f (pointsx1[i], pointsy1[i], z); + polys += npoints; + glEnd(); +# else + for (i = 1; i < npoints; i++) + { + glBegin (GL_LINE_STRIP); + glVertex3f (pointsx0[i-1], pointsy0[i-1], z); + glVertex3f (pointsx0[i ], pointsy0[i ], z); + glVertex3f (pointsx1[i ], pointsy1[i ], z); + glVertex3f (pointsx1[i-1], pointsy1[i-1], z); + glEnd(); + } + polys += npoints; +# endif + } +#if 1 + glBegin (GL_LINES); + for (i = 0; i < npoints; i++) + { + /* inside rim */ + glVertex3f (pointsx0[i], pointsy0[i], -thick2); + glVertex3f (pointsx0[i], pointsy0[i], thick2); + /* outside rim */ + glVertex3f (pointsx1[i], pointsy1[i], -thick2); + glVertex3f (pointsx1[i], pointsy1[i], thick2); + } + polys += npoints; + glEnd(); +#endif + } + else + { + /* top */ + glFrontFace(GL_CW); + glNormal3f(0, 0, -1); + glBegin (GL_QUAD_STRIP); + for (i = 0; i < npoints; i++) + { + glVertex3f (pointsx0[i], pointsy0[i], -thick2); + glVertex3f (pointsx1[i], pointsy1[i], -thick2); + } + polys += npoints; + glEnd(); + + /* bottom */ + glFrontFace(GL_CCW); + glNormal3f(0, 0, 1); + glBegin (GL_QUAD_STRIP); + for (i = 0; i < npoints; i++) + { + glVertex3f (pointsx0[i], pointsy0[i], thick2); + glVertex3f (pointsx1[i], pointsy1[i], thick2); + } + polys += npoints; + glEnd(); + + /* inside edge */ + glFrontFace(GL_CW); + glBegin (GL_QUAD_STRIP); + for (i = 0; i < npoints; i++) + { + glNormal3f (-pointsx0[i], -pointsy0[i], 0); + glVertex3f ( pointsx0[i], pointsy0[i], thick2); + glVertex3f ( pointsx0[i], pointsy0[i], -thick2); + } + polys += npoints; + glEnd(); + + /* outside edge */ + glFrontFace(GL_CCW); + glBegin (GL_QUADS); + { + for (i = 0; i < npoints-1; i++) + { + int ia = (i == 0 ? npoints-2 : i-1); + int iz = (i == npoints-2 ? 0 : i+1); + GLfloat x = pointsx1[i]; + GLfloat y = pointsy1[i]; + GLfloat xz = pointsx1[iz]; + GLfloat yz = pointsy1[iz]; + + GLfloat nxa = normals[ia*2]; /* normal of [i-1 - i] face */ + GLfloat nya = normals[ia*2+1]; + GLfloat nx = normals[i*2]; /* normal of [i - i+1] face */ + GLfloat ny = normals[i*2+1]; + GLfloat nxz = normals[iz*2]; /* normal of [i+1 - i+2] face */ + GLfloat nyz = normals[iz*2+1]; + + GLfloat anglea = vector_angle (nx, ny, 0, nxa, nya, 0); + GLfloat anglez = vector_angle (nx, ny, 0, nxz, nyz, 0); + GLfloat pointy = 0.005; + + if (anglea > pointy) + { + glNormal3f (nx, ny, 0); + glVertex3f (x, y, thick2); + glVertex3f (x, y, -thick2); + } + else + { + glNormal3f ((nxa + nx) / 2, (nya + ny) / 2, 0); + glVertex3f (x, y, thick2); + glVertex3f (x, y, -thick2); + } + + if (anglez > pointy) + { + glNormal3f (nx, ny, 0); + glVertex3f (xz, yz, -thick2); + glVertex3f (xz, yz, thick2); + } + else + { + glNormal3f ((nx + nxz) / 2, (ny + nyz) / 2, 0); + glVertex3f (xz, yz, -thick2); + glVertex3f (xz, yz, thick2); + } + } + polys += npoints; + } + glEnd(); + } + + /* Fill in the upper left hole... + */ + { + GLfloat th; + npoints = 0; + + th = 338.0 * d2r; + pointsx0[npoints] = r1c * cos(th) * dc->gasket_size; + pointsy0[npoints] = r1c * sin(th) * dc->gasket_size; + npoints++; + pointsx0[npoints] = r4 * cos(th) * dc->gasket_size; + pointsy0[npoints] = r4 * sin(th) * dc->gasket_size; + npoints++; + + th = 344.0 * d2r; + pointsx0[npoints] = r1c * cos(th) * dc->gasket_size; + pointsy0[npoints] = r1c * sin(th) * dc->gasket_size; + npoints++; + pointsx0[npoints] = r4 * cos(th) * dc->gasket_size; + pointsy0[npoints] = r4 * sin(th) * dc->gasket_size; + + if (! wire) + { + /* front wall */ + glNormal3f (0, 0, -1); + glFrontFace(GL_CW); + glBegin (wire ? GL_LINE_LOOP : GL_QUADS); + glVertex3f (pointsx0[0], pointsy0[0], -thick2); + glVertex3f (pointsx0[1], pointsy0[1], -thick2); + glVertex3f (pointsx0[3], pointsy0[3], -thick2); + glVertex3f (pointsx0[2], pointsy0[2], -thick2); + glEnd(); + polys++; + + /* back wall */ + glNormal3f (0, 0, 1); + glFrontFace(GL_CCW); + glBegin (wire ? GL_LINE_LOOP : GL_QUADS); + glVertex3f (pointsx0[0], pointsy0[0], thick2); + glVertex3f (pointsx0[1], pointsy0[1], thick2); + glVertex3f (pointsx0[3], pointsy0[3], thick2); + glVertex3f (pointsx0[2], pointsy0[2], thick2); + glEnd(); + polys++; + } + + /* top wall */ + glFrontFace(GL_CW); + glBegin (wire ? GL_LINE_LOOP : GL_QUADS); + glNormal3f (pointsx0[1], pointsy0[1], 0); + glVertex3f (pointsx0[1], pointsy0[1], thick2); + glNormal3f (pointsx0[3], pointsy0[3], 0); + glVertex3f (pointsx0[3], pointsy0[3], thick2); + glVertex3f (pointsx0[3], pointsy0[3], -thick2); + glNormal3f (pointsx0[1], pointsy0[1], 0); + glVertex3f (pointsx0[1], pointsy0[1], -thick2); + glEnd(); + polys++; + + + /* Now make a donut. + */ + { + int nsteps = (wire ? 12 : 64); + GLfloat r0 = 0.04; + GLfloat r1 = 0.070; + GLfloat th, cth, sth; + + glPushMatrix (); + + th = ((339.0 + 343.0) / 2) * d2r; + + glTranslatef (r1b * cos(th) * dc->gasket_size, + r1b * sin(th) * dc->gasket_size, + 0); + + npoints = 0; + for (i = 0; i < nsteps; i++) + { + th = 2 * M_PI * i / nsteps; + cth = cos (th) * dc->gasket_size; + sth = sin (th) * dc->gasket_size; + pointsx0[npoints] = r0 * cth; + pointsy0[npoints] = r0 * sth; + pointsx1[npoints] = r1 * cth; + pointsy1[npoints] = r1 * sth; + npoints++; + polys++; + } + + pointsx0[npoints] = pointsx0[0]; + pointsy0[npoints] = pointsy0[0]; + pointsx1[npoints] = pointsx1[0]; + pointsy1[npoints] = pointsy1[0]; + npoints++; + + if (wire) + { + glBegin (GL_LINE_LOOP); + for (i = 0; i < npoints; i++) + glVertex3f (pointsx0[i], pointsy0[i], -thick2); + polys += npoints; + glEnd(); + glBegin (GL_LINE_LOOP); + for (i = 0; i < npoints; i++) + glVertex3f (pointsx0[i], pointsy0[i], thick2); + polys += npoints; + glEnd(); +# if 0 + glBegin (GL_LINE_LOOP); + for (i = 0; i < npoints; i++) + glVertex3f (pointsx1[i], pointsy1[i], -thick2); + polys += npoints; + glEnd(); + glBegin (GL_LINE_LOOP); + for (i = 0; i < npoints; i++) + glVertex3f (pointsx1[i], pointsy1[i], thick2); + polys += npoints; + glEnd(); +# endif + } + else + { + /* top */ + glFrontFace(GL_CW); + glNormal3f(0, 0, -1); + glBegin (GL_QUAD_STRIP); + for (i = 0; i < npoints; i++) + { + glVertex3f (pointsx0[i], pointsy0[i], -thick2); + glVertex3f (pointsx1[i], pointsy1[i], -thick2); + } + polys += npoints; + glEnd(); + + /* bottom */ + glFrontFace(GL_CCW); + glNormal3f(0, 0, 1); + glBegin (GL_QUAD_STRIP); + for (i = 0; i < npoints; i++) + { + glVertex3f (pointsx0[i], pointsy0[i], thick2); + glVertex3f (pointsx1[i], pointsy1[i], thick2); + } + polys += npoints; + glEnd(); + } + + /* inside edge */ + glFrontFace(GL_CW); + glBegin (wire ? GL_LINES : GL_QUAD_STRIP); + for (i = 0; i < npoints; i++) + { + glNormal3f (-pointsx0[i], -pointsy0[i], 0); + glVertex3f ( pointsx0[i], pointsy0[i], thick2); + glVertex3f ( pointsx0[i], pointsy0[i], -thick2); + } + polys += npoints; + glEnd(); + + glPopMatrix(); + } + } + + + /* Attach the bottom-right dingus... + */ + { + GLfloat w = 0.05; + GLfloat h = 0.19; + GLfloat th; + + glRotatef (49.5, 0, 0, 1); + glScalef (dc->gasket_size, dc->gasket_size, 1); + glTranslatef (0, (r0+r1)/2, 0); + + /* buried box */ + if (! wire) + { + glFrontFace(GL_CCW); + glBegin (wire ? GL_LINE_STRIP : GL_QUADS); + glNormal3f (0, 0, -1); + glVertex3f (-w/2, -h/2, -thick2); glVertex3f (-w/2, h/2, -thick2); + glVertex3f ( w/2, h/2, -thick2); glVertex3f ( w/2, -h/2, -thick2); + glNormal3f (1, 0, 0); + glVertex3f ( w/2, -h/2, -thick2); glVertex3f ( w/2, h/2, -thick2); + glVertex3f ( w/2, h/2, thick2); glVertex3f ( w/2, -h/2, thick2); + glNormal3f (0, 0, 1); + glVertex3f ( w/2, -h/2, thick2); glVertex3f ( w/2, h/2, thick2); + glVertex3f (-w/2, h/2, thick2); glVertex3f (-w/2, -h/2, thick2); + glNormal3f (-1, 0, 0); + glVertex3f (-w/2, -h/2, thick2); glVertex3f (-w/2, h/2, thick2); + glVertex3f (-w/2, h/2, -thick2); glVertex3f (-w/2, -h/2, -thick2); + polys++; + glEnd(); + } + + npoints = 0; + for (th = (wire ? 0 : -0.1); + th <= M_PI + 0.1; + th += (M_PI / (wire ? 5 : 32))) + { + pointsx0[npoints] = w/2 * cos(th); + pointsy0[npoints] = w/2 * sin(th); + npoints++; + polys++; + } + + /* front inside curve */ + glNormal3f (0, 0, -1); + glFrontFace(GL_CW); + glBegin (wire ? GL_LINE_STRIP : GL_TRIANGLE_FAN); + if (! wire) glVertex3f (0, h/2, -thick2); + for (i = 0; i < npoints; i++) + glVertex3f (pointsx0[i], h/2 + pointsy0[i], -thick2); + polys += npoints; + glEnd(); + + /* front outside curve */ + glFrontFace(GL_CCW); + glBegin (wire ? GL_LINE_STRIP : GL_TRIANGLE_FAN); + if (! wire) glVertex3f (0, -h/2, -thick2); + for (i = 0; i < npoints; i++) + glVertex3f (pointsx0[i], -h/2 - pointsy0[i], -thick2); + polys += npoints; + glEnd(); + + /* back inside curve */ + glNormal3f (0, 0, 1); + glFrontFace(GL_CCW); + glBegin (wire ? GL_LINE_STRIP : GL_TRIANGLE_FAN); + if (! wire) glVertex3f (0, h/2, thick2); + for (i = 0; i < npoints; i++) + glVertex3f (pointsx0[i], h/2 + pointsy0[i], thick2); + polys += npoints; + glEnd(); + + /* back outside curve */ + glFrontFace(GL_CW); + glBegin (wire ? GL_LINE_STRIP : GL_TRIANGLE_FAN); + if (! wire) glVertex3f (0, -h/2, thick2); + for (i = 0; i < npoints; i++) + glVertex3f (pointsx0[i], -h/2 - pointsy0[i], thick2); + polys += npoints; + glEnd(); + + /* inside curve */ + glFrontFace(GL_CCW); + glBegin (wire ? GL_LINES : GL_QUAD_STRIP); + for (i = 0; i < npoints; i++) + { + glNormal3f (pointsx0[i], pointsy0[i], 0); + glVertex3f (pointsx0[i], h/2 + pointsy0[i], thick2); + glVertex3f (pointsx0[i], h/2 + pointsy0[i], -thick2); + } + polys += npoints; + glEnd(); + + /* outside curve */ + glFrontFace(GL_CW); + glBegin (wire ? GL_LINES : GL_QUAD_STRIP); + for (i = 0; i < npoints; i++) + { + glNormal3f (pointsx0[i], -pointsy0[i], 0); + glVertex3f (pointsx0[i], -h/2 - pointsy0[i], thick2); + glVertex3f (pointsx0[i], -h/2 - pointsy0[i], -thick2); + } + polys += npoints; + glEnd(); + } + + free (pointsx0); + free (pointsy0); + free (pointsx1); + free (pointsy1); + free (normals); + + glPopMatrix(); + return polys; +} + +static int +make_frame (logo_configuration *dc, int wire) +{ + int polys = 0; + int i, j; + GLfloat x[20], y[20]; + GLfloat corner_cut = 0.5; + + glPushMatrix(); + glRotatef (90, 0, 1, 0); + glScalef (4 * dc->frame_size, + 4 * dc->frame_size, + 4 * dc->frame_size); + + x[0] = -dc->frame_thickness; + x[1] = -dc->frame_thickness * corner_cut; + x[2] = 0; + x[3] = 0.5 - dc->triangle_size; + x[4] = 0.5; + x[5] = 0.5 + dc->triangle_size; + x[6] = 1; + x[7] = 1 + dc->frame_thickness * corner_cut; + x[8] = 1 + dc->frame_thickness; + + y[0] = -dc->frame_thickness; + y[1] = -dc->frame_thickness * corner_cut; + y[2] = 0; + y[3] = dc->triangle_size; + + /* front and back + */ + glTranslatef (-0.5, -0.5, dc->frame_depth / 4); + if (! wire) + for (j = 0; j <= 1; j++) + { + if (j) glTranslatef (0, 0, -dc->frame_depth / 2); + glFrontFace (j ? GL_CCW : GL_CW); + for (i = 0; i < 4; i++) + { + glNormal3f (0, 0, (j ? -1 : 1)); + glBegin (wire ? GL_LINES : GL_QUAD_STRIP); + glVertex3f (x[0], y[1], 0); glVertex3f (x[0], y[2], 0); + glVertex3f (x[1], y[0], 0); glVertex3f (x[1], y[2], 0); + glVertex3f (x[3], y[0], 0); glVertex3f (x[3], y[2], 0); + glVertex3f (x[4], y[0], 0); glVertex3f (x[4], y[3], 0); + glVertex3f (x[5], y[0], 0); glVertex3f (x[5], y[2], 0); + glVertex3f (x[7], y[0], 0); glVertex3f (x[7], y[2], 0); + glVertex3f (x[8], y[1], 0); glVertex3f (x[8], y[2], 0); + polys += 6; + glEnd (); + glTranslatef (0.5, 0.5, 0); + glRotatef (90, 0, 0, 1); + glTranslatef (-0.5, -0.5, 0); + } + } + + /* ledges + */ + glFrontFace (GL_CCW); + for (i = 0; i < 4; i++) + { + glNormal3f (0, 1, 0); + glBegin (wire ? GL_LINES : GL_QUAD_STRIP); + glVertex3f (x[2], y[2], 0); glVertex3f (x[2], y[2], dc->frame_depth/2); + glVertex3f (x[3], y[2], 0); glVertex3f (x[3], y[2], dc->frame_depth/2); + glVertex3f (x[4], y[3], 0); glVertex3f (x[4], y[3], dc->frame_depth/2); + glVertex3f (x[5], y[2], 0); glVertex3f (x[5], y[2], dc->frame_depth/2); + glVertex3f (x[6], y[2], 0); glVertex3f (x[6], y[2], dc->frame_depth/2); + polys += 4; + glEnd (); + + glNormal3f (0, -1, 0); + glBegin (wire ? GL_LINE_LOOP : GL_QUADS); + glVertex3f (x[7], y[0], 0); + glVertex3f (x[7], y[0], dc->frame_depth/2); + glVertex3f (x[1], y[0], dc->frame_depth/2); + glVertex3f (x[1], y[0], 0); + polys++; + glEnd (); + + glNormal3f (1, -1, 0); + glBegin (wire ? GL_LINE_LOOP : GL_QUADS); + glVertex3f (x[8], y[1], 0); + glVertex3f (x[8], y[1], dc->frame_depth/2); + glVertex3f (x[7], y[0], dc->frame_depth/2); + glVertex3f (x[7], y[0], 0); + polys++; + glEnd (); + + if (wire) + { + glNormal3f (0, 1, 0); + for (j = 0; j <= 1; j++) + { + glBegin (GL_LINE_STRIP); + glVertex3f (x[2], y[2], j*dc->frame_depth/2); + glVertex3f (x[3], y[2], j*dc->frame_depth/2); + glVertex3f (x[4], y[3], j*dc->frame_depth/2); + glVertex3f (x[5], y[2], j*dc->frame_depth/2); + glVertex3f (x[6], y[2], j*dc->frame_depth/2); + polys += 4; + glEnd (); + } + } + + glTranslatef (0.5, 0.5, 0); + glRotatef (90, 0, 0, 1); + glTranslatef (-0.5, -0.5, 0); + } + + glPopMatrix(); + return polys; +} + + +/* Make some pizza. + */ + +#ifdef HAVE_TESS + +typedef struct { + GLdouble *points; + int i; +} tess_out; + + +static void +tess_error_cb (GLenum errorCode) +{ + fprintf (stderr, "%s: tesselation error: %s\n", + progname, gluErrorString(errorCode)); + exit (0); +} + +static void +tess_combine_cb (GLdouble coords[3], GLdouble *d[4], GLfloat w[4], + GLdouble **data_out) +{ + GLdouble *new = (GLdouble *) malloc (3 * sizeof(*new)); + new[0] = coords[0]; + new[1] = coords[1]; + new[2] = coords[2]; + *data_out = new; +} + + +#if 0 +static void +tess_vertex_cb (void *vertex_data, void *closure) +{ + tess_out *to = (tess_out *) closure; + GLdouble *v = (GLdouble *) vertex_data; + to->points[to->i++] = v[0]; + to->points[to->i++] = v[1]; + to->points[to->i++] = v[2]; +} +#endif + +static void +tess_begin_cb (GLenum which) +{ + glBegin(which); +} + +static void +tess_end_cb (void) +{ + glEnd(); +} + +#endif /* HAVE_TESS */ + + +static int +make_pizza (logo_configuration *dc, int facetted, int wire) +{ + int polys = 0; + int topfaces = (facetted ? 48 : 120); + int discfaces = (facetted ? 12 : 120); + int npoints = topfaces * 2 + 100; + GLdouble *points = (GLdouble *) calloc (npoints * 3, sizeof(GLdouble)); + int nholes = 3; + GLdouble *holes = (GLdouble *) calloc (topfaces*nholes*3, sizeof(GLdouble)); + + GLfloat step = M_PI * 2 / 6 / topfaces; + GLfloat thick2 = (dc->gasket_thickness / dc->gasket_size) / 4; + GLfloat th, x, y, s; + int i, j, k; + int endpoints; + int endedge1; + +# ifdef HAVE_TESS + tess_out TO, *to = &TO; + GLUtesselator *tess = gluNewTess(); + + to->points = (GLdouble *) calloc (topfaces * 20, sizeof(GLdouble)); + to->i = 0; + +# ifndef _GLUfuncptr +# define _GLUfuncptr void(*)(void) +# endif + + gluTessCallback(tess,GLU_TESS_BEGIN, (_GLUfuncptr)tess_begin_cb); + gluTessCallback(tess,GLU_TESS_VERTEX, (_GLUfuncptr)glVertex3dv); + gluTessCallback(tess,GLU_TESS_END, (_GLUfuncptr)tess_end_cb); + gluTessCallback(tess,GLU_TESS_COMBINE, (_GLUfuncptr)tess_combine_cb); + gluTessCallback(tess,GLU_TESS_ERROR, (_GLUfuncptr)tess_error_cb); + + gluTessProperty (tess, GLU_TESS_BOUNDARY_ONLY, wire); + gluTessProperty (tess,GLU_TESS_WINDING_RULE, GLU_TESS_WINDING_ODD); + +# endif /* HAVE_TESS */ + + glPushMatrix(); + + s = 1.9; + glRotatef (180, 0, 0, 1); + glScalef (s, s, s); + glRotatef (90, 0, 1, 0); + glTranslatef (-0.53, 0, 0); + glRotatef (-30, 0, 0, 1); + + /* Compute the wedge */ + th = 0; + j = 0; + + /* Edge 1 */ + { + GLfloat edge[] = { + 0.000, 0.000, + 0.000, 0.210, + 0.042, 0.230, + 0.042, 0.616, + 0.000, 0.641, + }; + for (i = 0; i < countof(edge)/2; i++) + { + points[j++] = edge[i*2+1]; + points[j++] = edge[i*2]; + points[j++] = 0; + } + endedge1 = i; + } + + s = 0.798; /* radius of end of slice, before crust gap */ + for (i = 0; i < topfaces; i++) + { + points[j++] = cos(th) * s; + points[j++] = sin(th) * s; + points[j++] = 0; + th += step; + } + + /* Edge 2 */ + { + GLfloat edge[] = { + 0.613, 0.353, + 0.572, 0.376, + 0.455, 0.309, + 0.452, 0.260, + 0.332, 0.192, + 0.293, 0.216, + 0.178, 0.149, + 0.178, 0.102, + }; + for (i = 0; i < countof(edge)/2; i++) + { + points[j++] = edge[i*2+1]; + points[j++] = edge[i*2]; + points[j++] = 0; + } + endpoints = j/3; + } + + + /* Draw the rim of the slice */ + glBegin (wire ? GL_LINES : GL_QUADS); + x = points[0]; + y = points[1]; + for (i = (wire ? 0 : 1); i < endpoints; i++) + { + GLdouble *p = points + (i*3); + + do_normal (p[0], p[1], -thick2, + p[0], p[1], thick2, + x, y, thick2); + if (!wire) + { + glVertex3f (x, y, -thick2); + glVertex3f (x, y, thick2); + } + glVertex3f (p[0], p[1], thick2); + glVertex3f (p[0], p[1], -thick2); + x = p[0]; + y = p[1]; + polys++; + } + + do_normal (points[0], points[1], -thick2, + points[0], points[1], thick2, + x, y, thick2); + glVertex3f (x, y, -thick2); + glVertex3f (x, y, thick2); + glVertex3f (points[0], points[1], thick2); + glVertex3f (points[0], points[1], -thick2); + polys++; + glEnd(); + +# ifndef HAVE_TESS + if (wire) + { + /* Outline of slice */ + glBegin (GL_LINE_LOOP); + for (i = 0; i < endpoints; i++) + glVertex3f (points[i*3], points[i*3+1], -thick2); + glEnd(); + glBegin (GL_LINE_LOOP); + for (i = 0; i < endpoints; i++) + glVertex3f (points[i*3], points[i*3+1], thick2); + glEnd(); + } +# endif /* HAVE_TESS */ + + /* Compute the holes */ + step = M_PI * 2 / discfaces; + for (k = 0; k < nholes; k++) + { + GLdouble *p = holes + (discfaces * 3 * k); + th = 0; + j = 0; + switch (k) { + case 0: x = 0.34; y = 0.17; s = 0.05; break; + case 1: x = 0.54; y = 0.17; s = 0.06; break; + case 2: x = 0.55; y = 0.36; s = 0.06; break; + default: abort(); break; + } + for (i = 0; i < discfaces; i++) + { + p[j++] = x + cos(M_PI*2 - th) * s; + p[j++] = y + sin(M_PI*2 - th) * s; + p[j++] = 0; + th += step; + } + } + + + /* Draw the inside rim of the holes */ + for (k = 0; k < nholes; k++) + { + GLdouble *p = holes + (discfaces * 3 * k); + + glBegin (wire ? GL_LINES : GL_QUAD_STRIP); + for (i = 0; i < discfaces; i++) + { + GLdouble *p2 = p + (i*3); + if (i > 0) + do_normal (p2[0], p2[1], -thick2, + p2[0], p2[1], thick2, + p2[-3], p2[-2], thick2); + glVertex3f (p2[0], p2[1], -thick2); + glVertex3f (p2[0], p2[1], thick2); + polys++; + } + glVertex3f (p[0], p[1], -thick2); + glVertex3f (p[0], p[1], thick2); + polys++; + glEnd(); +# ifndef HAVE_TESS + if (wire) + { + /* Outline of holes */ + glBegin (GL_LINE_LOOP); + for (i = 0; i < discfaces; i++) + glVertex3f (p[i*3], p[i*3+1], -thick2); + glEnd(); + glBegin (GL_LINE_LOOP); + for (i = 0; i < discfaces; i++) + glVertex3f (p[i*3], p[i*3+1], thick2); + glEnd(); + } +# endif /* !HAVE_TESS */ + } + +# ifdef HAVE_TESS + glTranslatef (0, 0, -thick2); + for (y = 0; y <= 1; y++) + { + if (y) glTranslatef (0, 0, thick2*2); + + /* A non-convex polygon */ + gluTessBeginPolygon (tess, to); + + glNormal3f (0, 0, (y > 0 ? 1 : -1)); + gluTessNormal (tess, 0, 0, (y > 0 ? 1 : -1)); + glFrontFace (GL_CCW); + + /* Tess the wedge */ + gluTessBeginContour (tess); + for (i = 0; i < endpoints; i++) + { + GLdouble *p = points + (i*3); + gluTessVertex (tess, p, p); + polys++; + } + gluTessVertex (tess, points, points); + gluTessEndContour (tess); + + /* Tess the holes */ + for (k = 0; k < nholes; k++) + { + GLdouble *p = holes + (discfaces * 3 * k); + gluTessBeginContour (tess); + for (i = 0; i < discfaces; i++) + { + GLdouble *p2 = p + (i*3); + gluTessVertex (tess, p2, p2); + polys++; + } + gluTessEndContour (tess); + } + + gluTessEndPolygon (tess); + } + + glTranslatef (0, 0, -thick2); + +# else /* !HAVE_TESS */ + if (! wire) + { + glDisableClientState (GL_COLOR_ARRAY); + glDisableClientState (GL_NORMAL_ARRAY); + glDisableClientState (GL_TEXTURE_COORD_ARRAY); + glEnableClientState (GL_VERTEX_ARRAY); + glVertexPointer (3, GL_FLOAT, 0, dnapizza_triangles); + + glTranslatef(0, 0, thick2); + glNormal3f (0, 0, 1); + glFrontFace (GL_CW); + glDrawArrays (GL_TRIANGLES, 0, countof (dnapizza_triangles) / 3); + + glTranslatef(0, 0, -thick2*2); + glNormal3f (0, 0, -1); + glFrontFace (GL_CCW); + glDrawArrays (GL_TRIANGLES, 0, countof (dnapizza_triangles) / 3); + + glTranslatef(0, 0, thick2); + } +# endif /* !HAVE_TESS */ + + + /* Compute the crust */ + + s = 0.861; /* radius of inside of crust */ + step = M_PI * 2 / 6 / topfaces; + th = 0; + j = 0; + for (i = 0; i < topfaces; i++) + { + points[j++] = cos(th) * s; + points[j++] = sin(th) * s; + points[j++] = 0; + th += step; + } + + s = 1; + for (i = 0; i < topfaces; i++) + { + points[j++] = cos(th) * s; + points[j++] = sin(th) * s; + points[j++] = 0; + th -= step; + } + + /* Draw the rim of the crust */ + glFrontFace (GL_CCW); + glBegin (wire ? GL_LINES : GL_QUAD_STRIP); + for (i = 0; i < topfaces * 2; i++) + { + GLdouble *p = points + (i*3); + if (i == 0 || i == (topfaces*2)-1) + glNormal3f (0, -1, 0); + else if (i == topfaces-1 || i == topfaces) + glNormal3f (0, 1, 0); + else + do_normal (p[-3], p[-2], thick2, + p[0], p[1], thick2, + p[0], p[1], -thick2); + glVertex3f (p[0], p[1], -thick2); + glVertex3f (p[0], p[1], thick2); + polys++; + } + glVertex3f (points[0], points[1], -thick2); + glVertex3f (points[0], points[1], thick2); + polys++; + glEnd(); + + if (wire) + { + glBegin (GL_LINE_STRIP); + for (i = 0; i < topfaces * 2; i++) + { + GLdouble *p = points + (i*3); + glVertex3f (p[0], p[1], -thick2); + polys++; + } + glVertex3f (points[0], points[1], -thick2); + glEnd(); + + glBegin (GL_LINE_STRIP); + for (i = 0; i < topfaces * 2; i++) + { + GLdouble *p = points + (i*3); + glVertex3f (p[0], p[1], thick2); + polys++; + } + glVertex3f (points[0], points[1], thick2); + glEnd(); + } + + /* Draw the top of the crust */ + if (! wire) + { + glFrontFace (GL_CW); + glBegin (wire ? GL_LINE_STRIP : GL_QUAD_STRIP); + glNormal3f (0, 0, -1); + if (!wire) + for (i = 0; i < topfaces; i++) + { + int ii = topfaces + (topfaces - i - 1); + GLdouble *p1 = points + (i*3); + GLdouble *p2 = points + (ii*3); + glVertex3f (p1[0], p1[1], -thick2); + glVertex3f (p2[0], p2[1], -thick2); + polys++; + } + polys++; + glEnd(); + + /* Draw the bottom of the crust */ + glFrontFace (GL_CCW); + glBegin (wire ? GL_LINES : GL_QUAD_STRIP); + glNormal3f (0, 0, 1); + for (i = 0; i < topfaces; i++) + { + int ii = topfaces + (topfaces - i - 1); + GLdouble *p1 = points + (i*3); + GLdouble *p2 = points + (ii*3); + glVertex3f (p1[0], p1[1], thick2); + glVertex3f (p2[0], p2[1], thick2); + polys++; + } + polys++; + glEnd(); + } + +# ifdef HAVE_TESS + gluDeleteTess (tess); + free (to->points); +# endif /* HAVE_TESS */ + + free (points); + free (holes); + + glPopMatrix(); + + return polys; +} + + + + +/* Window management, etc + */ +ENTRYPOINT void +reshape_logo (ModeInfo *mi, int width, int height) +{ + GLfloat h = (GLfloat) height / (GLfloat) width; + + glViewport (0, 0, (GLint) width, (GLint) height); + + glMatrixMode(GL_PROJECTION); + glLoadIdentity(); + gluPerspective (30.0, 1/h, 1.0, 100.0); + + glMatrixMode(GL_MODELVIEW); + glLoadIdentity(); + gluLookAt( 0.0, 0.0, 30.0, + 0.0, 0.0, 0.0, + 0.0, 1.0, 0.0); + + glClear(GL_COLOR_BUFFER_BIT); +} + + +static void +gl_init (ModeInfo *mi) +{ +/* logo_configuration *dc = &dcs[MI_SCREEN(mi)]; */ + int wire = MI_IS_WIREFRAME(mi); + + GLfloat position[] = {0, 0, 0, 0}; + GLfloat direction[] = {3, -1, -3}; + + position[0] = -direction[0]; + position[1] = -direction[1]; + position[2] = -direction[2]; + + if (!wire) + { + glLightfv(GL_LIGHT0, GL_POSITION, position); + glLightfv(GL_LIGHT0, GL_SPOT_DIRECTION, direction); + glShadeModel(GL_SMOOTH); + glEnable(GL_NORMALIZE); + glEnable(GL_CULL_FACE); + glEnable(GL_LIGHTING); + glEnable(GL_LIGHT0); + glEnable(GL_DEPTH_TEST); + } +} + + +ENTRYPOINT void +init_logo (ModeInfo *mi) +{ + logo_configuration *dc; + int do_gasket = get_boolean_resource(mi->dpy, "doGasket", "Boolean"); + int do_helix = get_boolean_resource(mi->dpy, "doHelix", "Boolean"); + int do_ladder = (do_helix && + get_boolean_resource(mi->dpy, "doLadder", "Boolean")); + int do_frame = get_boolean_resource(mi->dpy, "doFrame", "Boolean"); + GLfloat helix_rot = 147.0; + + if (!do_gasket && !do_helix) + { + fprintf (stderr, "%s: no helix or gasket?\n", progname); + exit (1); + } + + if (!dcs) { + dcs = (logo_configuration *) + calloc (MI_NUM_SCREENS(mi), sizeof (logo_configuration)); + if (!dcs) { + fprintf(stderr, "%s: out of memory\n", progname); + exit(1); + } + } + + dc = &dcs[MI_SCREEN(mi)]; + + if ((dc->glx_context = init_GL(mi)) != NULL) { + gl_init(mi); + reshape_logo (mi, MI_WIDTH(mi), MI_HEIGHT(mi)); + } + + dc->wall_facets = get_integer_resource(mi->dpy, "wallFacets", "Integer"); + dc->bar_facets = get_integer_resource(mi->dpy, "barFacets", "Integer"); + dc->clockwise = get_boolean_resource(mi->dpy, "clockwise", "Boolean"); + dc->turns = get_float_resource(mi->dpy, "turns", "Float"); + dc->turn_spacing = get_float_resource(mi->dpy, "turnSpacing", "Float"); + dc->bar_spacing = get_float_resource(mi->dpy, "barSpacing", "Float"); + dc->wall_height = get_float_resource(mi->dpy, "wallHeight", "Float"); + dc->wall_thickness = get_float_resource(mi->dpy, "wallThickness", "Float"); + dc->bar_thickness = get_float_resource(mi->dpy, "barThickness", "Float"); + dc->wall_taper = get_float_resource(mi->dpy, "wallTaper", "Float"); + + dc->gasket_size = get_float_resource(mi->dpy,"gasketSize", "Float"); + dc->gasket_depth = get_float_resource(mi->dpy,"gasketDepth", "Float"); + dc->gasket_thickness = get_float_resource(mi->dpy,"gasketThickness","Float"); + + dc->frame_size = get_float_resource(mi->dpy, "frameSize", "Float"); + dc->frame_depth = get_float_resource(mi->dpy, "frameDepth", "Float"); + dc->frame_thickness = get_float_resource(mi->dpy, "frameThickness", "Float"); + dc->triangle_size = get_float_resource(mi->dpy, "triangleSize", "Float"); + + dc->speed = get_float_resource(mi->dpy, "speed", "Float"); + + { + char *s = get_string_resource (MI_DISPLAY (mi), "mode", "String"); + if (!s || !*s || !strcasecmp (s, "helix")) + dc->mode = HELIX; + else if (!strcasecmp (s, "pizza")) + dc->mode = PIZZA; + else if (!strcasecmp (s, "both")) + dc->mode = BOTH; + else + { + fprintf (stderr, "%s: mode must be helix, pizza or both, not \"%s\"\n", + progname, s); + exit (1); + } + if (s) free (s); + + dc->anim_state = (dc->mode == BOTH + ? ((random() & 1) ? HELIX : PIZZA) + : dc->mode); + dc->anim_ratio = 0; + } + + { + XColor xcolor; + + char *color_name = get_string_resource (mi->dpy, "foreground", "Foreground"); + char *s2; + for (s2 = color_name + strlen(color_name) - 1; s2 > color_name; s2--) + if (*s2 == ' ' || *s2 == '\t') + *s2 = 0; + else + break; + + if (! XParseColor (MI_DISPLAY(mi), mi->xgwa.colormap, color_name, &xcolor)) + { + fprintf (stderr, "%s: can't parse color %s\n", progname, color_name); + exit (1); + } + + dc->color[0] = xcolor.red / 65535.0; + dc->color[1] = xcolor.green / 65535.0; + dc->color[2] = xcolor.blue / 65535.0; + dc->color[3] = 1.0; + } + + dc->trackball = gltrackball_init (); + + dc->gasket_spinnerx.probability = 0.1; + dc->gasket_spinnery.probability = 0.1; + dc->gasket_spinnerz.probability = 1.0; + + dc->helix_spinnerz.probability = 0.6; + + dc->pizza_spinnerz.probability = 0.6; + dc->pizza_spinnery.probability = 0.6; + + dc->scene_spinnerx.probability = 0.1; + dc->scene_spinnery.probability = 0.0; + + dc->frame_spinner.probability = 5.0; + + /* start the frame off-screen */ + dc->frame_spinner.spinning_p = True; + dc->frame_spinner.position = 0.3; + dc->frame_spinner.speed = 0.001; + + if (dc->speed > 0) /* start off with the gasket in motion */ + { + dc->gasket_spinnerz.spinning_p = True; + dc->gasket_spinnerz.speed = (0.002 + * ((random() & 1) ? 1 : -1) + * dc->speed); + } + +# ifdef DXF_OUTPUT_HACK + { + dc->frame_depth = dc->gasket_depth; + dxf_layer = 1; + dxf_color = 3; + dxf_start(); + glPushMatrix(); + glRotatef(90, 1, 0, 0); + glRotatef(90, 0, 0, 1); + make_pizza (dc, 0, 0); + + glPushMatrix(); + glRotatef(helix_rot, 0, 0, 1); + make_ladder (dc, 0, 0); + make_helix (dc, 0, 0); + glRotatef (180, 0, 0, 1); + make_helix (dc, 0, 0); + glPopMatrix(); + + dxf_layer++; + make_gasket (dc, 0); + dxf_layer++; + make_frame (dc, 0); + glPopMatrix(); + dxf_end(); + } +# endif + + glPushMatrix(); + dc->helix_list = glGenLists (1); + glNewList (dc->helix_list, GL_COMPILE); + glRotatef(helix_rot, 0, 0, 1); + if (do_ladder) dc->polys[0] += make_ladder (dc, 0, 0); + if (do_helix) dc->polys[0] += make_helix (dc, 0, 0); + glRotatef(180, 0, 0, 1); + if (do_helix) dc->polys[0] += make_helix (dc, 0, 0); + glEndList (); + glPopMatrix(); + + glPushMatrix(); + dc->helix_list_wire = glGenLists (1); + glNewList (dc->helix_list_wire, GL_COMPILE); +/* glRotatef(helix_rot, 0, 0, 1); wtf? */ + if (do_ladder) dc->polys[1] += make_ladder (dc, 1, 1); + if (do_helix) dc->polys[1] += make_helix (dc, 1, 1); + glRotatef(180, 0, 0, 1); + if (do_helix) dc->polys[1] += make_helix (dc, 1, 1); + glEndList (); + glPopMatrix(); + + glPushMatrix(); + dc->helix_list_facetted = glGenLists (1); + glNewList (dc->helix_list_facetted, GL_COMPILE); + glRotatef(helix_rot, 0, 0, 1); + if (do_ladder) dc->polys[2] += make_ladder (dc, 1, 0); + if (do_helix) dc->polys[2] += make_helix (dc, 1, 0); + glRotatef(180, 0, 0, 1); + if (do_helix) dc->polys[2] += make_helix (dc, 1, 0); + glEndList (); + glPopMatrix(); + + dc->pizza_list = glGenLists (1); + glNewList (dc->pizza_list, GL_COMPILE); + if (do_frame) dc->polys[5] += make_pizza (dc, 0, 0); + glEndList (); + + dc->pizza_list_wire = glGenLists (1); + glNewList (dc->pizza_list_wire, GL_COMPILE); + if (do_frame) dc->polys[6] += make_pizza (dc, 1, 1); + glEndList (); + + dc->pizza_list_facetted = glGenLists (1); + glNewList (dc->pizza_list_facetted, GL_COMPILE); + if (do_frame) dc->polys[6] += make_pizza (dc, 1, 0); + glEndList (); + + dc->gasket_list = glGenLists (1); + glNewList (dc->gasket_list, GL_COMPILE); + if (do_gasket) dc->polys[3] += make_gasket (dc, 0); + glEndList (); + + dc->gasket_list_wire = glGenLists (1); + glNewList (dc->gasket_list_wire, GL_COMPILE); + if (do_gasket) dc->polys[4] += make_gasket (dc, 1); + glEndList (); + + dc->frame_list = glGenLists (1); + glNewList (dc->frame_list, GL_COMPILE); + if (do_frame) dc->polys[5] += make_frame (dc, 0); + glEndList (); + + dc->frame_list_wire = glGenLists (1); + glNewList (dc->frame_list_wire, GL_COMPILE); + if (do_frame) dc->polys[6] += make_frame (dc, 1); + glEndList (); + + /* When drawing both solid and wireframe objects, + make sure the wireframe actually shows up! */ + glEnable (GL_POLYGON_OFFSET_FILL); + glPolygonOffset (1.0, 1.0); +} + + +ENTRYPOINT Bool +logo_handle_event (ModeInfo *mi, XEvent *event) +{ + logo_configuration *dc = &dcs[MI_SCREEN(mi)]; + + if (event->xany.type == ButtonPress && + event->xbutton.button == Button1) + { + dc->button_down_p = True; + gltrackball_start (dc->trackball, + event->xbutton.x, event->xbutton.y, + MI_WIDTH (mi), MI_HEIGHT (mi)); + return True; + } + else if (event->xany.type == ButtonRelease && + event->xbutton.button == Button1) + { + dc->button_down_p = False; + return True; + } + else if (event->xany.type == ButtonPress && + (event->xbutton.button == Button4 || + event->xbutton.button == Button5 || + event->xbutton.button == Button6 || + event->xbutton.button == Button7)) + { + gltrackball_mousewheel (dc->trackball, event->xbutton.button, 10, + !!event->xbutton.state); + return True; + } + else if (event->xany.type == MotionNotify && + dc->button_down_p) + { + gltrackball_track (dc->trackball, + event->xmotion.x, event->xmotion.y, + MI_WIDTH (mi), MI_HEIGHT (mi)); + return True; + } + + return False; +} + + +static void +tick_spinner (ModeInfo *mi, spinner *s) +{ + logo_configuration *dc = &dcs[MI_SCREEN(mi)]; + + if (dc->speed == 0) return; + if (dc->button_down_p) return; + + if (s->spinning_p) + { + s->position += s->speed; + if (s->position >= 1.0 || s->position <= -1.0) + + { + s->position = 0; + s->spinning_p = False; + } + } + else if (s->probability && + (random() % (int) (PROBABILITY_SCALE / s->probability)) == 0) + { + GLfloat ss = 0.004; + s->spinning_p = True; + s->position = 0; + do { + s->speed = dc->speed * (frand(ss/3) + frand(ss/3) + frand(ss/3)); + } while (s->speed <= 0); + if (random() & 1) + s->speed = -s->speed; + } +} + + +static void +link_spinners (ModeInfo *mi, spinner *s0, spinner *s1) +{ + if (s0->spinning_p && !s1->spinning_p) + { + GLfloat op = s1->probability; + s1->probability = PROBABILITY_SCALE; + tick_spinner (mi, s1); + s1->probability = op; + } +} + + +ENTRYPOINT void +draw_logo (ModeInfo *mi) +{ + logo_configuration *dc = &dcs[MI_SCREEN(mi)]; + Display *dpy = MI_DISPLAY(mi); + Window window = MI_WINDOW(mi); + int wire = MI_IS_WIREFRAME(mi); + GLfloat gcolor[4]; + GLfloat specular[] = {0.8, 0.8, 0.8, 1.0}; + GLfloat shininess = 50.0; + Bool pizza_p; + + if (!dc->glx_context) + return; + + mi->polygon_count = 0; + glXMakeCurrent(MI_DISPLAY(mi), MI_WINDOW(mi), *(dc->glx_context)); + + if (!wire && + dc->wire_overlay == 0 && + (random() % (int) (PROBABILITY_SCALE / 0.2)) == 0) + dc->wire_overlay = ((random() % 200) + + (random() % 200) + + (random() % 200)); + + tick_spinner (mi, &dc->gasket_spinnerx); + tick_spinner (mi, &dc->gasket_spinnery); + tick_spinner (mi, &dc->gasket_spinnerz); + tick_spinner (mi, &dc->helix_spinnerz); + tick_spinner (mi, &dc->pizza_spinnery); + tick_spinner (mi, &dc->pizza_spinnerz); + tick_spinner (mi, &dc->scene_spinnerx); + tick_spinner (mi, &dc->scene_spinnery); + tick_spinner (mi, &dc->frame_spinner); + link_spinners (mi, &dc->scene_spinnerx, &dc->scene_spinnery); + + switch (dc->anim_state) + { + case HELIX: + if (dc->mode == BOTH && + (random() % (int) (PROBABILITY_SCALE / 0.2)) == 0) + dc->anim_state = HELIX_OUT; + break; + + case HELIX_OUT: + dc->anim_ratio += 0.1 * dc->speed; + if (dc->anim_ratio >= 1.0) + { + dc->anim_ratio = 0.0; + dc->anim_state = PIZZA_IN; + } + break; + + case PIZZA_IN: + dc->anim_ratio += 0.1 * dc->speed; + if (dc->anim_ratio >= 1.0) + { + dc->anim_ratio = 0.0; + dc->anim_state = PIZZA; + } + break; + + case PIZZA: + if (dc->mode == BOTH && + (random() % (int) (PROBABILITY_SCALE / 0.2)) == 0) + dc->anim_state = PIZZA_OUT; + break; + + case PIZZA_OUT: + dc->anim_ratio += 0.1 * dc->speed; + if (dc->anim_ratio >= 1.0) + { + dc->anim_ratio = 0.0; + dc->anim_state = HELIX_IN; + } + break; + + case HELIX_IN: + dc->anim_ratio += 0.1 * dc->speed; + if (dc->anim_ratio >= 1.0) + { + dc->anim_ratio = 0.0; + dc->anim_state = HELIX; + } + break; + + default: + abort(); + break; + } + + pizza_p = (dc->anim_state == PIZZA || + dc->anim_state == PIZZA_IN || + dc->anim_state == PIZZA_OUT); + + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + + glPushMatrix (); + glRotatef(current_device_rotation(), 0, 0, 1); + { + GLfloat scale = 0; + glScalef(3, 3, 3); + +# ifdef USE_IPHONE + glScalef (0.7, 0.7, 0.7); /* make room for the frame */ +# endif + + glColor3f(dc->color[0], dc->color[1], dc->color[2]); + + /* Draw frame before trackball rotation */ + { + GLfloat p = (dc->frame_spinner.position >= 0 + ? dc->frame_spinner.position + : -dc->frame_spinner.position); + GLfloat size = (p > 0.5 ? 1-p : p); + scale = 1 + (size * 10); + glPushMatrix(); + /* gltrackball_rotate (dc->trackball); */ + glRotatef(90, 1, 0, 0); + glRotatef(90, 0, 0, 1); + + glScalef (1, scale, scale); + if (wire) + { + glDisable (GL_LIGHTING); + glCallList (dc->frame_list_wire); + mi->polygon_count += dc->polys[6]; + } + else if (dc->wire_overlay != 0) + { + glCallList (dc->frame_list); + glDisable (GL_LIGHTING); + glColor3fv (dc->color); + glCallList (dc->frame_list_wire); + mi->polygon_count += dc->polys[6]; + if (!wire) glEnable (GL_LIGHTING); + } + else + { + glCallList (dc->frame_list); + mi->polygon_count += dc->polys[5]; + } + glPopMatrix(); + } + + gltrackball_rotate (dc->trackball); + + glRotatef(90, 1, 0, 0); + glRotatef(90, 0, 0, 1); + + glRotatef (360 * sin (M_PI/2 * dc->scene_spinnerx.position), 0, 1, 0); + glRotatef (360 * sin (M_PI/2 * dc->scene_spinnery.position), 0, 0, 1); + + glPushMatrix(); + { + glRotatef (360 * sin (M_PI/2 * dc->gasket_spinnerx.position), 0, 1, 0); + glRotatef (360 * sin (M_PI/2 * dc->gasket_spinnery.position), 0, 0, 1); + glRotatef (360 * sin (M_PI/2 * dc->gasket_spinnerz.position), 1, 0, 0); + + memcpy (gcolor, dc->color, sizeof (dc->color)); + if (dc->wire_overlay != 0) + { + gcolor[0] = gcolor[1] = gcolor[2] = 0; + specular[0] = specular[1] = specular[2] = 0; + shininess = 0; + } + glMaterialfv (GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, gcolor); + glMaterialfv (GL_FRONT_AND_BACK, GL_SPECULAR, specular); + glMaterialf (GL_FRONT_AND_BACK, GL_SHININESS, shininess); + + if (wire) + { + glDisable (GL_LIGHTING); + glCallList (dc->gasket_list_wire); + mi->polygon_count += dc->polys[4]; + } + else if (dc->wire_overlay != 0) + { + glCallList (dc->gasket_list); + glDisable (GL_LIGHTING); + glColor3fv (dc->color); + glCallList (dc->gasket_list_wire); + mi->polygon_count += dc->polys[4]; + if (!wire) glEnable (GL_LIGHTING); + glMaterialfv (GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, gcolor); + } + else + { + glCallList (dc->gasket_list); + mi->polygon_count += dc->polys[3]; + } + } + glPopMatrix(); + + if (pizza_p) + { + glRotatef (360 * sin (M_PI/2 * dc->pizza_spinnery.position), 1, 0, 0); + glRotatef (360 * sin (M_PI/2 * dc->pizza_spinnerz.position), 0, 0, 1); + } + else + { + glRotatef (360 * sin (M_PI/2 * dc->helix_spinnerz.position), 0, 0, 1); + } + + scale = ((dc->anim_state == PIZZA_IN || dc->anim_state == HELIX_IN) + ? dc->anim_ratio + : ((dc->anim_state == PIZZA_OUT || dc->anim_state == HELIX_OUT) + ? 1.0 - dc->anim_ratio + : 1.0)); + if (scale <= 0) scale = 0.001; + glScalef (scale, scale, scale); + + if (wire) + { + glDisable (GL_LIGHTING); + if (pizza_p) + glCallList (dc->pizza_list_wire); + else + glCallList (dc->helix_list_wire); + mi->polygon_count += dc->polys[1]; + } + else if (dc->wire_overlay != 0) + { + if (pizza_p) + glCallList (dc->pizza_list_facetted); + else + glCallList (dc->helix_list_facetted); + + glDisable (GL_LIGHTING); + glColor3fv (dc->color); + + if (pizza_p) + glCallList (dc->pizza_list_wire); + else + glCallList (dc->helix_list_wire); + + mi->polygon_count += dc->polys[2]; + if (!wire) glEnable (GL_LIGHTING); + } + else + { + if (pizza_p) + glCallList (dc->pizza_list); + else + glCallList (dc->helix_list); + mi->polygon_count += dc->polys[0]; + } + } + glPopMatrix(); + + if (dc->wire_overlay > 0) + dc->wire_overlay--; + + if (mi->fps_p) do_fps (mi); + glFinish(); + + glXSwapBuffers(dpy, window); +} + +XSCREENSAVER_MODULE_2 ("DNALogo", dnalogo, logo) + +#endif /* USE_GL */ diff --git a/hacks/glx/dnapizza.h b/hacks/glx/dnapizza.h new file mode 100644 index 00000000..6dd48b96 --- /dev/null +++ b/hacks/glx/dnapizza.h @@ -0,0 +1,122 @@ +/* DNA Pizza Logo, Copyright (c) 2011-2012 Jamie Zawinski + + Since GLUtesselator doesn't exist in the iOS build, the slice shape + of the DNA Pizza logo is hardcoded there, instead of being generated. + (These vertexes were generated by GLUtesselator and saved.) + */ + +static const GLfloat dnapizza_triangles[]={ + 0.315,0.213301,0, 0.296699,0.195,0, 0.309,0.455,0, + 0.296699,0.195,0, 0.29,0.17,0, 0.309,0.455,0, + 0.309,0.455,0, 0.29,0.17,0, 0.26,0.452,0, + 0.29,0.17,0, 0.23,0.042,0, 0.26,0.452,0, + 0.26,0.452,0, 0.23,0.042,0, 0.216,0.293,0, + 0.23,0.042,0, 0.21,0,0, 0.216,0.293,0, + 0.216,0.293,0, 0.21,0,0, 0.149,0.178,0, + 0.21,0,0, 0.102,0.178,0, 0.149,0.178,0, + 0.376,0.572,0, 0.353,0.613,0, 0.411,0.68402,0, + 0.376,0.572,0, 0.411,0.68402,0, 0.383301,0.195,0, + 0.376,0.572,0, 0.383301,0.195,0, 0.365,0.213301,0, + 0.376,0.572,0, 0.365,0.213301,0, 0.34,0.22,0, + 0.376,0.572,0, 0.34,0.22,0, 0.315,0.213301,0, + 0.376,0.572,0, 0.315,0.213301,0, 0.309,0.455,0, + 0.39,0.17,0, 0.383301,0.195,0, 0.411,0.68402,0, + 0.39,0.17,0, 0.411,0.68402,0, 0.48,0.17,0, + 0.39,0.17,0, 0.48,0.17,0, 0.488039,0.14,0, + 0.39,0.17,0, 0.488039,0.14,0, 0.51,0.118038,0, + 0.39,0.17,0, 0.51,0.118038,0, 0.616,0.042,0, + 0.39,0.17,0, 0.616,0.042,0, 0.383301,0.145,0, + 0.798,0,0, 0.641,0,0, 0.645595,0.469053,0, + 0.798,0,0, 0.645595,0.469053,0, 0.653683,0.457714,0, + 0.798,0,0, 0.653683,0.457714,0, 0.661572,0.446236,0, + 0.798,0,0, 0.661572,0.446236,0, 0.669259,0.434622,0, + 0.798,0,0, 0.669259,0.434622,0, 0.676742,0.422876,0, + 0.798,0,0, 0.676742,0.422876,0, 0.68402,0.411,0, + 0.798,0,0, 0.68402,0.411,0, 0.691088,0.399,0, + 0.798,0,0, 0.691088,0.399,0, 0.697947,0.386878,0, + 0.798,0,0, 0.697947,0.386878,0, 0.704592,0.374638,0, + 0.798,0,0, 0.704592,0.374638,0, 0.711023,0.362284,0, + 0.798,0,0, 0.711023,0.362284,0, 0.717238,0.34982,0, + 0.798,0,0, 0.717238,0.34982,0, 0.723234,0.337249,0, + 0.798,0,0, 0.723234,0.337249,0, 0.729009,0.324576,0, + 0.798,0,0, 0.729009,0.324576,0, 0.734563,0.311803,0, + 0.798,0,0, 0.734563,0.311803,0, 0.739893,0.298936,0, + 0.798,0,0, 0.739893,0.298936,0, 0.744997,0.285978,0, + 0.798,0,0, 0.744997,0.285978,0, 0.749875,0.272932,0, + 0.798,0,0, 0.749875,0.272932,0, 0.754524,0.259803,0, + 0.798,0,0, 0.754524,0.259803,0, 0.758943,0.246596,0, + 0.798,0,0, 0.758943,0.246596,0, 0.763131,0.233313,0, + 0.798,0,0, 0.763131,0.233313,0, 0.767087,0.219959,0, + 0.798,0,0, 0.767087,0.219959,0, 0.770809,0.206538,0, + 0.798,0,0, 0.770809,0.206538,0, 0.774296,0.193054,0, + 0.798,0,0, 0.774296,0.193054,0, 0.777547,0.179511,0, + 0.798,0,0, 0.777547,0.179511,0, 0.780562,0.165914,0, + 0.798,0,0, 0.780562,0.165914,0, 0.783338,0.152266,0, + 0.798,0,0, 0.783338,0.152266,0, 0.785877,0.138571,0, + 0.798,0,0, 0.785877,0.138571,0, 0.788175,0.124835,0, + 0.798,0,0, 0.788175,0.124835,0, 0.790234,0.11106,0, + 0.798,0,0, 0.790234,0.11106,0, 0.792052,0.097252,0, + 0.798,0,0, 0.792052,0.097252,0, 0.793628,0.083414,0, + 0.798,0,0, 0.793628,0.083414,0, 0.794963,0.06955,0, + 0.798,0,0, 0.794963,0.06955,0, 0.796056,0.055666,0, + 0.798,0,0, 0.796056,0.055666,0, 0.796906,0.041764,0, + 0.798,0,0, 0.796906,0.041764,0, 0.797514,0.02785,0, + 0.798,0,0, 0.797514,0.02785,0, 0.797878,0.013927,0, + 0.641,0,0, 0.616,0.042,0, 0.620162,0.502198,0, + 0.641,0,0, 0.620162,0.502198,0, 0.628833,0.491298,0, + 0.641,0,0, 0.628833,0.491298,0, 0.637311,0.480248,0, + 0.641,0,0, 0.637311,0.480248,0, 0.645595,0.469053,0, + 0.616,0.042,0, 0.51,0.118038,0, 0.54,0.11,0, + 0.616,0.042,0, 0.54,0.11,0, 0.57,0.118038,0, + 0.616,0.042,0, 0.57,0.118038,0, 0.591962,0.14,0, + 0.616,0.042,0, 0.591962,0.14,0, 0.6,0.17,0, + 0.616,0.042,0, 0.6,0.17,0, 0.601962,0.33,0, + 0.616,0.042,0, 0.601962,0.33,0, 0.61,0.36,0, + 0.616,0.042,0, 0.61,0.36,0, 0.611303,0.512945,0, + 0.616,0.042,0, 0.611303,0.512945,0, 0.620162,0.502198,0, + 0.48,0.17,0, 0.411,0.68402,0, 0.422875,0.676743,0, + 0.48,0.17,0, 0.422875,0.676743,0, 0.434622,0.669259,0, + 0.48,0.17,0, 0.434622,0.669259,0, 0.446236,0.661572,0, + 0.48,0.17,0, 0.446236,0.661572,0, 0.457714,0.653684,0, + 0.48,0.17,0, 0.457714,0.653684,0, 0.469052,0.645596,0, + 0.48,0.17,0, 0.469052,0.645596,0, 0.480248,0.637311,0, + 0.48,0.17,0, 0.480248,0.637311,0, 0.488038,0.2,0, + 0.616,0.042,0, 0.23,0.042,0, 0.315,0.126699,0, + 0.616,0.042,0, 0.315,0.126699,0, 0.34,0.12,0, + 0.616,0.042,0, 0.34,0.12,0, 0.365,0.126699,0, + 0.616,0.042,0, 0.365,0.126699,0, 0.383301,0.145,0, + 0.23,0.042,0, 0.29,0.17,0, 0.296699,0.145,0, + 0.23,0.042,0, 0.296699,0.145,0, 0.315,0.126699,0, + 0.58362,0.544235,0, 0.593029,0.533966,0, 0.601961,0.39,0, + 0.593029,0.533966,0, 0.602258,0.523535,0, 0.601961,0.39,0, + 0.601961,0.39,0, 0.602258,0.523535,0, 0.61,0.36,0, + 0.602258,0.523535,0, 0.611303,0.512945,0, 0.61,0.36,0, + 0.58,0.411962,0, 0.55,0.42,0, 0.554337,0.574033,0, + 0.58,0.411962,0, 0.554337,0.574033,0, 0.564271,0.564271,0, + 0.58,0.411962,0, 0.564271,0.564271,0, 0.574033,0.554338,0, + 0.58,0.411962,0, 0.574033,0.554338,0, 0.58362,0.544235,0, + 0.58,0.411962,0, 0.58362,0.544235,0, 0.601961,0.39,0, + 0.55,0.42,0, 0.52,0.411962,0, 0.523535,0.602258,0, + 0.55,0.42,0, 0.523535,0.602258,0, 0.533966,0.59303,0, + 0.55,0.42,0, 0.533966,0.59303,0, 0.544235,0.58362,0, + 0.55,0.42,0, 0.544235,0.58362,0, 0.554337,0.574033,0, + 0.51,0.221962,0, 0.488038,0.2,0, 0.49,0.36,0, + 0.488038,0.2,0, 0.491298,0.628833,0, 0.49,0.36,0, + 0.49,0.36,0, 0.491298,0.628833,0, 0.498038,0.39,0, + 0.491298,0.628833,0, 0.502197,0.620163,0, 0.498038,0.39,0, + 0.498038,0.39,0, 0.502197,0.620163,0, 0.52,0.411962,0, + 0.502197,0.620163,0, 0.512944,0.611304,0, 0.52,0.411962,0, + 0.52,0.411962,0, 0.512944,0.611304,0, 0.523535,0.602258,0, + 0.49,0.36,0, 0.498039,0.33,0, 0.51,0.221962,0, + 0.498039,0.33,0, 0.52,0.308039,0, 0.51,0.221962,0, + 0.51,0.221962,0, 0.52,0.308039,0, 0.54,0.23,0, + 0.52,0.308039,0, 0.55,0.3,0, 0.54,0.23,0, + 0.54,0.23,0, 0.55,0.3,0, 0.57,0.221962,0, + 0.55,0.3,0, 0.58,0.308039,0, 0.57,0.221962,0, + 0.57,0.221962,0, 0.58,0.308039,0, 0.591962,0.2,0, + 0.58,0.308039,0, 0.601962,0.33,0, 0.591962,0.2,0, + 0.591962,0.2,0, 0.601962,0.33,0, 0.6,0.17,0, + 0.488038,0.2,0, 0.480248,0.637311,0, 0.491298,0.628833,0, + 0.26,0.452,0, 0.216,0.293,0, 0.192,0.332,0, + 0.102,0.178,0, 0.21,0,0, 0,0,0, +}; diff --git a/hacks/glx/dolphin.c b/hacks/glx/dolphin.c new file mode 100644 index 00000000..2ef4e338 --- /dev/null +++ b/hacks/glx/dolphin.c @@ -0,0 +1,2061 @@ +/* atlantis --- Shows moving 3D sea animals */ + +#if 0 +static const char sccsid[] = "@(#)dolphin.c 1.2 98/06/16 xlockmore"; +#endif + +/* Copyright (c) E. Lassauge, 1998. */ + +/* + * Permission to use, copy, modify, and distribute this software and its + * documentation for any purpose and without fee is hereby granted, + * provided that the above copyright notice appear in all copies and that + * both that copyright notice and this permission notice appear in + * supporting documentation. + * + * This file is provided AS IS with no warranties of any kind. The author + * shall have no liability with respect to the infringement of copyrights, + * trade secrets or any patents by this file or any part thereof. In no + * event will the author be liable for any lost revenue or profits or + * other special, indirect and consequential damages. + * + * The original code for this mode was written by Mark J. Kilgard + * as a demo for openGL programming. + * + * Porting it to xlock was possible by comparing the original Mesa's morph3d + * demo with it's ported version to xlock, so thanks for Marcelo F. Vianna + * (look at morph3d.c) for his indirect help. + * + * Thanks goes also to Brian Paul for making it possible and inexpensive + * to use OpenGL at home. + * + * My e-mail address is lassauge@sagem.fr + * + * Eric Lassauge (May-13-1998) + * + */ + +/** + * (c) Copyright 1993, 1994, Silicon Graphics, Inc. + * ALL RIGHTS RESERVED + * Permission to use, copy, modify, and distribute this software for + * any purpose and without fee is hereby granted, provided that the above + * copyright notice appear in all copies and that both the copyright notice + * and this permission notice appear in supporting documentation, and that + * the name of Silicon Graphics, Inc. not be used in advertising + * or publicity pertaining to distribution of the software without specific, + * written prior permission. + * + * THE MATERIAL EMBODIED ON THIS SOFTWARE IS PROVIDED TO YOU "AS-IS" + * AND WITHOUT WARRANTY OF ANY KIND, EXPRESS, IMPLIED OR OTHERWISE, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTY OF MERCHANTABILITY OR + * FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL SILICON + * GRAPHICS, INC. BE LIABLE TO YOU OR ANYONE ELSE FOR ANY DIRECT, + * SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY + * KIND, OR ANY DAMAGES WHATSOEVER, INCLUDING WITHOUT LIMITATION, + * LOSS OF PROFIT, LOSS OF USE, SAVINGS OR REVENUE, OR THE CLAIMS OF + * THIRD PARTIES, WHETHER OR NOT SILICON GRAPHICS, INC. HAS BEEN + * ADVISED OF THE POSSIBILITY OF SUCH LOSS, HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE + * POSSESSION, USE OR PERFORMANCE OF THIS SOFTWARE. + * + * US Government Users Restricted Rights + * Use, duplication, or disclosure by the Government is subject to + * restrictions set forth in FAR 52.227.19(c)(2) or subparagraph + * (c)(1)(ii) of the Rights in Technical Data and Computer Software + * clause at DFARS 252.227-7013 and/or in similar or successor + * clauses in the FAR or the DOD or NASA FAR Supplement. + * Unpublished-- rights reserved under the copyright laws of the + * United States. Contractor/manufacturer is Silicon Graphics, + * Inc., 2011 N. Shoreline Blvd., Mountain View, CA 94039-7311. + * + * OpenGL(TM) is a trademark of Silicon Graphics, Inc. + */ + +#ifdef USE_GL + +#include "atlantis.h" + +/* *INDENT-OFF* */ +static const float N001[3] = {-0.005937, -0.101998, -0.994767}; +static const float N002[3] = {0.93678, -0.200803, 0.286569}; +static const float N003[3] = {-0.233062, 0.972058, 0.028007}; +#if 0 +static const float N004[3] = {0, 1, 0}; +#endif +static const float N005[3] = {0.898117, 0.360171, 0.252315}; +static const float N006[3] = {-0.915437, 0.348456, 0.201378}; +static const float N007[3] = {0.602263, -0.777527, 0.18092}; +static const float N008[3] = {-0.906912, -0.412015, 0.088061}; +#if 0 +static const float N009[3] = {-0.015623, 0.999878, 0}; +static const float N010[3] = {0, -0.992278, 0.124035}; +static const float N011[3] = {0, -0.936329, -0.351123}; +#endif +static const float N012[3] = {0.884408, -0.429417, -0.182821}; +static const float N013[3] = {0.921121, 0.311084, -0.234016}; +static const float N014[3] = {0.382635, 0.877882, -0.287948}; +static const float N015[3] = {-0.380046, 0.888166, -0.258316}; +static const float N016[3] = {-0.891515, 0.392238, -0.226607}; +static const float N017[3] = {-0.901419, -0.382002, -0.203763}; +static const float N018[3] = {-0.367225, -0.911091, -0.187243}; +static const float N019[3] = {0.339539, -0.924846, -0.171388}; +static const float N020[3] = {0.914706, -0.378617, -0.14129}; +static const float N021[3] = {0.950662, 0.262713, -0.164994}; +static const float N022[3] = {0.546359, 0.80146, -0.243218}; +static const float N023[3] = {-0.315796, 0.917068, -0.243431}; +static const float N024[3] = {-0.825687, 0.532277, -0.186875}; +static const float N025[3] = {-0.974763, -0.155232, -0.160435}; +static const float N026[3] = {-0.560596, -0.816658, -0.137119}; +static const float N027[3] = {0.38021, -0.910817, -0.160786}; +static const float N028[3] = {0.923772, -0.358322, -0.135093}; +static const float N029[3] = {0.951202, 0.275053, -0.139859}; +static const float N030[3] = {0.686099, 0.702548, -0.188932}; +static const float N031[3] = {-0.521865, 0.826719, -0.21022}; +static const float N032[3] = {-0.92382, 0.346739, -0.162258}; +static const float N033[3] = {-0.902095, -0.409995, -0.134646}; +static const float N034[3] = {-0.509115, -0.848498, -0.144404}; +static const float N035[3] = {0.456469, -0.880293, -0.129305}; +static const float N036[3] = {0.873401, -0.475489, -0.105266}; +static const float N037[3] = {0.970825, 0.179861, -0.158584}; +static const float N038[3] = {0.675609, 0.714187, -0.183004}; +static const float N039[3] = {-0.523574, 0.830212, -0.19136}; +static const float N040[3] = {-0.958895, 0.230808, -0.165071}; +static const float N041[3] = {-0.918285, -0.376803, -0.121542}; +static const float N042[3] = {-0.622467, -0.774167, -0.114888}; +static const float N043[3] = {0.404497, -0.908807, -0.102231}; +static const float N044[3] = {0.930538, -0.365155, -0.027588}; +static const float N045[3] = {0.92192, 0.374157, -0.100345}; +static const float N046[3] = {0.507346, 0.860739, 0.041562}; +static const float N047[3] = {-0.394646, 0.918815, -0.00573}; +static const float N048[3] = {-0.925411, 0.373024, -0.066837}; +static const float N049[3] = {-0.945337, -0.322309, -0.049551}; +static const float N050[3] = {-0.660437, -0.750557, -0.022072}; +static const float N051[3] = {0.488835, -0.87195, -0.027261}; +static const float N052[3] = {0.902599, -0.421397, 0.087969}; +static const float N053[3] = {0.938636, 0.322606, 0.12202}; +static const float N054[3] = {0.484605, 0.871078, 0.079878}; +static const float N055[3] = {-0.353607, 0.931559, 0.084619}; +static const float N056[3] = {-0.867759, 0.478564, 0.134054}; +static const float N057[3] = {-0.951583, -0.29603, 0.082794}; +static const float N058[3] = {-0.672355, -0.730209, 0.121384}; +static const float N059[3] = {0.528336, -0.842452, 0.105525}; +static const float N060[3] = {0.786913, -0.56476, 0.248627}; +#if 0 +static const float N061[3] = {0, 1, 0}; +#endif +static const float N062[3] = {0.622098, 0.76523, 0.165584}; +static const float N063[3] = {-0.631711, 0.767816, 0.106773}; +static const float N064[3] = {-0.687886, 0.606351, 0.398938}; +static const float N065[3] = {-0.946327, -0.281623, 0.158598}; +static const float N066[3] = {-0.509549, -0.860437, 0.002776}; +static const float N067[3] = {0.462594, -0.876692, 0.131977}; +#if 0 +static const float N068[3] = {0, -0.992278, 0.124035}; +static const float N069[3] = {0, -0.970143, -0.242536}; +static const float N070[3] = {0.015502, 0.992159, -0.12402}; +#endif +static const float N071[3] = {0, 1, 0}; +#if 0 +static const float N072[3] = {0, 1, 0}; +static const float N073[3] = {0, 1, 0}; +static const float N074[3] = {0, -1, 0}; +static const float N075[3] = {-0.242536, 0, -0.970143}; +static const float N076[3] = {-0.010336, -0.992225, -0.124028}; +#endif +static const float N077[3] = {-0.88077, 0.461448, 0.106351}; +static const float N078[3] = {-0.88077, 0.461448, 0.106351}; +static const float N079[3] = {-0.88077, 0.461448, 0.106351}; +static const float N080[3] = {-0.88077, 0.461448, 0.106351}; +static const float N081[3] = {-0.571197, 0.816173, 0.087152}; +static const float N082[3] = {-0.88077, 0.461448, 0.106351}; +static const float N083[3] = {-0.571197, 0.816173, 0.087152}; +static const float N084[3] = {-0.571197, 0.816173, 0.087152}; +static const float N085[3] = {-0.88077, 0.461448, 0.106351}; +static const float N086[3] = {-0.571197, 0.816173, 0.087152}; +static const float N087[3] = {-0.88077, 0.461448, 0.106351}; +static const float N088[3] = {-0.88077, 0.461448, 0.106351}; +static const float N089[3] = {-0.88077, 0.461448, 0.106351}; +static const float N090[3] = {-0.88077, 0.461448, 0.106351}; +static const float N091[3] = {0, 1, 0}; +static const float N092[3] = {0, 1, 0}; +static const float N093[3] = {0, 1, 0}; +static const float N094[3] = {1, 0, 0}; +static const float N095[3] = {-1, 0, 0}; +#if 0 +static const float N096[3] = {0, 1, 0}; +#endif +static const float N097[3] = {-0.697296, 0.702881, 0.140491}; +static const float N098[3] = {0.918864, 0.340821, 0.198819}; +static const float N099[3] = {-0.932737, 0.201195, 0.299202}; +static const float N100[3] = {0.029517, 0.981679, 0.188244}; +#if 0 +static const float N101[3] = {0, 1, 0}; +#endif +static const float N102[3] = {0.813521, -0.204936, 0.544229}; +#if 0 +static const float N103[3] = {0, 1, 0}; +static const float N104[3] = {0, 1, 0}; +static const float N105[3] = {0, 1, 0}; +static const float N106[3] = {0, 1, 0}; +static const float N107[3] = {0, 1, 0}; +static const float N108[3] = {0, 1, 0}; +static const float N109[3] = {0, 1, 0}; +#endif +static const float N110[3] = {-0.78148, -0.384779, 0.491155}; +static const float N111[3] = {-0.722243, 0.384927, 0.574627}; +static const float N112[3] = {-0.752278, 0.502679, 0.425901}; +static const float N113[3] = {0.547257, 0.36791, 0.751766}; +static const float N114[3] = {0.725949, -0.232568, 0.647233}; +static const float N115[3] = {-0.747182, -0.660786, 0.07128}; +static const float N116[3] = {0.931519, 0.200748, 0.30327}; +static const float N117[3] = {-0.828928, 0.313757, 0.463071}; +static const float N118[3] = {0.902554, -0.370967, 0.218587}; +static const float N119[3] = {-0.879257, -0.441851, 0.177973}; +static const float N120[3] = {0.642327, 0.611901, 0.461512}; +static const float N121[3] = {0.964817, -0.202322, 0.16791}; +static const float N122[3] = {0, 1, 0}; +#if 0 +static const float N123[3] = {-0.980734, 0.041447, 0.1909}; +static const float N124[3] = {-0.980734, 0.041447, 0.1909}; +static const float N125[3] = {-0.980734, 0.041447, 0.1909}; +static const float N126[3] = {0, 1, 0}; +static const float N127[3] = {0, 1, 0}; +static const float N128[3] = {0, 1, 0}; +static const float N129[3] = {0.96325, 0.004839, 0.268565}; +static const float N130[3] = {0.96325, 0.004839, 0.268565}; +static const float N131[3] = {0.96325, 0.004839, 0.268565}; +static const float N132[3] = {0, 1, 0}; +static const float N133[3] = {0, 1, 0}; +static const float N134[3] = {0, 1, 0}; +#endif +static float P001[3] = {5.68, -300.95, 1324.7}; +static const float P002[3] = {338.69, -219.63, 9677.03}; +static const float P003[3] = {12.18, 474.59, 9138.14}; +#if 0 +static const float P004[3] = {-7.49, -388.91, 10896.74}; +#endif +static const float P005[3] = {487.51, 198.05, 9350.78}; +static const float P006[3] = {-457.61, 68.74, 9427.85}; +static const float P007[3] = {156.52, -266.72, 10311.68}; +static const float P008[3] = {-185.56, -266.51, 10310.47}; +static float P009[3] = {124.39, -261.46, 1942.34}; +static float P010[3] = {-130.05, -261.46, 1946.03}; +static float P011[3] = {141.07, -320.11, 1239.38}; +static float P012[3] = {156.48, -360.12, 2073.41}; +static float P013[3] = {162, -175.88, 2064.44}; +static float P014[3] = {88.16, -87.72, 2064.02}; +static float P015[3] = {-65.21, -96.13, 2064.02}; +static float P016[3] = {-156.48, -180.96, 2064.44}; +static float P017[3] = {-162, -368.93, 2082.39}; +static float P018[3] = {-88.16, -439.22, 2082.39}; +static float P019[3] = {65.21, -440.32, 2083.39}; +static float P020[3] = {246.87, -356.02, 2576.95}; +static float P021[3] = {253.17, -111.15, 2567.15}; +static float P022[3] = {132.34, 51.41, 2559.84}; +static float P023[3] = {-97.88, 40.44, 2567.15}; +static float P024[3] = {-222.97, -117.49, 2567.15}; +static float P025[3] = {-252.22, -371.53, 2569.92}; +static float P026[3] = {-108.44, -518.19, 2586.75}; +static float P027[3] = {97.88, -524.79, 2586.75}; +static float P028[3] = {370.03, -421.19, 3419.7}; +static float P029[3] = {351.15, -16.98, 3423.17}; +static float P030[3] = {200.66, 248.46, 3430.37}; +static float P031[3] = {-148.42, 235.02, 3417.91}; +static float P032[3] = {-360.21, -30.27, 3416.84}; +static float P033[3] = {-357.9, -414.89, 3407.04}; +static float P034[3] = {-148.88, -631.35, 3409.9}; +static float P035[3] = {156.38, -632.59, 3419.7}; +static float P036[3] = {462.61, -469.21, 4431.51}; +static float P037[3] = {466.6, 102.25, 4434.98}; +static float P038[3] = {243.05, 474.34, 4562.02}; +static float P039[3] = {-191.23, 474.4, 4554.42}; +static float P040[3] = {-476.12, 111.05, 4451.11}; +static float P041[3] = {-473.36, -470.74, 4444.78}; +static float P042[3] = {-266.95, -748.41, 4447.78}; +static float P043[3] = {211.14, -749.91, 4429.73}; +static float P044[3] = {680.57, -370.27, 5943.46}; +static float P045[3] = {834.01, 363.09, 6360.63}; +static float P046[3] = {371.29, 804.51, 6486.26}; +static float P047[3] = {-291.43, 797.22, 6494.28}; +static float P048[3] = {-784.13, 370.75, 6378.01}; +static float P049[3] = {-743.29, -325.82, 5943.46}; +static float P050[3] = {-383.24, -804.77, 5943.46}; +static float P051[3] = {283.47, -846.09, 5943.46}; +static const float iP001[3] = {5.68, -300.95, 1324.7}; +#if 0 +static const float iP002[3] = {338.69, -219.63, 9677.03}; +static const float iP003[3] = {12.18, 624.93, 8956.39}; +static const float iP004[3] = {-7.49, -388.91, 10896.74}; +static const float iP005[3] = {487.51, 198.05, 9350.78}; +static const float iP006[3] = {-457.61, 199.04, 9353.01}; +static const float iP007[3] = {156.52, -266.72, 10311.68}; +static const float iP008[3] = {-185.56, -266.51, 10310.47}; +#endif +static const float iP009[3] = {124.39, -261.46, 1942.34}; +static const float iP010[3] = {-130.05, -261.46, 1946.03}; +static const float iP011[3] = {141.07, -320.11, 1239.38}; +static const float iP012[3] = {156.48, -360.12, 2073.41}; +static const float iP013[3] = {162, -175.88, 2064.44}; +static const float iP014[3] = {88.16, -87.72, 2064.02}; +static const float iP015[3] = {-65.21, -96.13, 2064.02}; +static const float iP016[3] = {-156.48, -180.96, 2064.44}; +static const float iP017[3] = {-162, -368.93, 2082.39}; +static const float iP018[3] = {-88.16, -439.22, 2082.39}; +static const float iP019[3] = {65.21, -440.32, 2083.39}; +static const float iP020[3] = {246.87, -356.02, 2576.95}; +static const float iP021[3] = {253.17, -111.15, 2567.15}; +static const float iP022[3] = {132.34, 51.41, 2559.84}; +static const float iP023[3] = {-97.88, 40.44, 2567.15}; +static const float iP024[3] = {-222.97, -117.49, 2567.15}; +static const float iP025[3] = {-252.22, -371.53, 2569.92}; +static const float iP026[3] = {-108.44, -518.19, 2586.75}; +static const float iP027[3] = {97.88, -524.79, 2586.75}; +static const float iP028[3] = {370.03, -421.19, 3419.7}; +static const float iP029[3] = {351.15, -16.98, 3423.17}; +static const float iP030[3] = {200.66, 248.46, 3430.37}; +static const float iP031[3] = {-148.42, 235.02, 3417.91}; +static const float iP032[3] = {-360.21, -30.27, 3416.84}; +static const float iP033[3] = {-357.9, -414.89, 3407.04}; +static const float iP034[3] = {-148.88, -631.35, 3409.9}; +static const float iP035[3] = {156.38, -632.59, 3419.7}; +static const float iP036[3] = {462.61, -469.21, 4431.51}; +static const float iP037[3] = {466.6, 102.25, 4434.98}; +static const float iP038[3] = {243.05, 474.34, 4562.02}; +static const float iP039[3] = {-191.23, 474.4, 4554.42}; +static const float iP040[3] = {-476.12, 111.05, 4451.11}; +static const float iP041[3] = {-473.36, -470.74, 4444.78}; +static const float iP042[3] = {-266.95, -748.41, 4447.78}; +static const float iP043[3] = {211.14, -749.91, 4429.73}; +static const float iP044[3] = {680.57, -370.27, 5943.46}; +static const float iP045[3] = {834.01, 363.09, 6360.63}; +static const float iP046[3] = {371.29, 804.51, 6486.26}; +static const float iP047[3] = {-291.43, 797.22, 6494.28}; +static const float iP048[3] = {-784.13, 370.75, 6378.01}; +static const float iP049[3] = {-743.29, -325.82, 5943.46}; +static const float iP050[3] = {-383.24, -804.77, 5943.46}; +static const float iP051[3] = {283.47, -846.09, 5943.46}; +static const float P052[3] = {599.09, -300.15, 7894.03}; +static const float P053[3] = {735.48, 306.26, 7911.92}; +static const float P054[3] = {246.22, 558.53, 8460.5}; +static const float P055[3] = {-230.41, 559.84, 8473.23}; +static const float P056[3] = {-698.66, 320.83, 7902.59}; +static const float P057[3] = {-643.29, -299.16, 7902.59}; +static const float P058[3] = {-341.47, -719.3, 7902.59}; +static const float P059[3] = {252.57, -756.12, 7902.59}; +static const float P060[3] = {458.39, -265.31, 9355.44}; +#if 0 +static const float P061[3] = {433.38, -161.9, 9503.03}; +#endif +static const float P062[3] = {224.04, 338.75, 9450.3}; +static const float P063[3] = {-165.71, 341.04, 9462.35}; +static const float P064[3] = {-298.11, 110.13, 10180.37}; +static const float P065[3] = {-473.99, -219.71, 9355.44}; +static const float P066[3] = {-211.97, -479.87, 9355.44}; +static const float P067[3] = {192.86, -491.45, 9348.73}; +static float P068[3] = {-136.29, -319.84, 1228.73}; +static float P069[3] = {1111.17, -314.14, 1314.19}; +static float P070[3] = {-1167.34, -321.61, 1319.45}; +static float P071[3] = {1404.86, -306.66, 1235.45}; +static float P072[3] = {-1409.73, -314.14, 1247.66}; +static float P073[3] = {1254.01, -296.87, 1544.58}; +static float P074[3] = {-1262.09, -291.7, 1504.26}; +static float P075[3] = {965.71, -269.26, 1742.65}; +static float P076[3] = {-900.97, -276.74, 1726.07}; +static const float iP068[3] = {-136.29, -319.84, 1228.73}; +static const float iP069[3] = {1111.17, -314.14, 1314.19}; +static const float iP070[3] = {-1167.34, -321.61, 1319.45}; +static const float iP071[3] = {1404.86, -306.66, 1235.45}; +static const float iP072[3] = {-1409.73, -314.14, 1247.66}; +static const float iP073[3] = {1254.01, -296.87, 1544.58}; +static const float iP074[3] = {-1262.09, -291.7, 1504.26}; +static const float iP075[3] = {965.71, -269.26, 1742.65}; +static const float iP076[3] = {-900.97, -276.74, 1726.07}; +static const float P077[3] = {1058, -448.81, 8194.66}; +static const float P078[3] = {-1016.51, -456.43, 8190.62}; +static const float P079[3] = {-1515.96, -676.45, 7754.93}; +static const float P080[3] = {1856.75, -830.34, 7296.56}; +static const float P081[3] = {1472.16, -497.38, 7399.68}; +static const float P082[3] = {-1775.26, -829.51, 7298.46}; +static const float P083[3] = {911.09, -252.51, 7510.99}; +static const float P084[3] = {-1451.94, -495.62, 7384.3}; +static const float P085[3] = {1598.75, -669.26, 7769.9}; +static const float P086[3] = {-836.53, -250.08, 7463.25}; +static const float P087[3] = {722.87, -158.18, 8006.41}; +static const float P088[3] = {-688.86, -162.28, 7993.89}; +static const float P089[3] = {-626.92, -185.3, 8364.98}; +static const float P090[3] = {647.72, -189.46, 8354.99}; +static float P091[3] = {0, 835.01, 5555.62}; +static float P092[3] = {0, 1350.18, 5220.86}; +static float P093[3] = {0, 1422.94, 5285.27}; +static float P094[3] = {0, 1296.75, 5650.19}; +static float P095[3] = {0, 795.63, 6493.88}; +static const float iP091[3] = {0, 835.01, 5555.62}; +static const float iP092[3] = {0, 1350.18, 5220.86}; +static const float iP093[3] = {0, 1422.94, 5285.27}; +static const float iP094[3] = {0, 1296.75, 5650.19}; +static const float iP095[3] = {0, 795.63, 6493.88}; +#if 0 +static const float P096[3] = {-447.38, -165.99, 9499.6}; +#endif +static float P097[3] = {-194.91, -357.14, 10313.32}; +static float P098[3] = {135.35, -357.66, 10307.94}; +static const float iP097[3] = {-194.91, -357.14, 10313.32}; +static const float iP098[3] = {135.35, -357.66, 10307.94}; +static const float P099[3] = {-380.53, -221.14, 9677.98}; +static const float P100[3] = {0, 412.99, 9629.33}; +#if 0 +static const float P101[3] = {5.7, 567, 7862.98}; +#endif +static float P102[3] = {59.51, -412.55, 10677.58}; +static const float iP102[3] = {59.51, -412.55, 10677.58}; +static const float P103[3] = {6.5, 484.74, 9009.94}; +#if 0 +static const float P104[3] = {-9.86, 567.62, 7858.65}; +#endif +static const float P105[3] = {-41.86, 476.51, 9078.17}; +#if 0 +static const float P106[3] = {22.75, 568.13, 7782.83}; +static const float P107[3] = {58.93, 568.42, 7775.94}; +#endif +static const float P108[3] = {49.2, 476.83, 9078.24}; +#if 0 +static const float P109[3] = {99.21, 566, 7858.65}; +#endif +static float P110[3] = {-187.62, -410.04, 10674.12}; +static const float iP110[3] = {-187.62, -410.04, 10674.12}; +static float P111[3] = {-184.25, -318.7, 10723.88}; +static const float iP111[3] = {-184.25, -318.7, 10723.88}; +static const float P112[3] = {-179.61, -142.81, 10670.26}; +static const float P113[3] = {57.43, -147.94, 10675.26}; +static const float P114[3] = {54.06, -218.9, 10712.44}; +static const float P115[3] = {-186.35, -212.09, 10713.76}; +static const float P116[3] = {205.9, -84.61, 10275.97}; +static const float P117[3] = {-230.96, -83.26, 10280.09}; +static const float iP118[3] = {216.78, -509.17, 10098.94}; +static const float iP119[3] = {-313.21, -510.79, 10102.62}; +static float P118[3] = {216.78, -509.17, 10098.94}; +static float P119[3] = {-313.21, -510.79, 10102.62}; +static const float P120[3] = {217.95, 96.34, 10161.62}; +static float P121[3] = {71.99, -319.74, 10717.7}; +static const float iP121[3] = {71.99, -319.74, 10717.7}; +static float P122[3] = {0, 602.74, 5375.84}; +static const float iP122[3] = {0, 602.74, 5375.84}; +static const float P123[3] = {-448.94, -203.14, 9499.6}; +static const float P124[3] = {-442.64, -185.2, 9528.07}; +static const float P125[3] = {-441.07, -148.05, 9528.07}; +static const float P126[3] = {-443.43, -128.84, 9499.6}; +static const float P127[3] = {-456.87, -146.78, 9466.67}; +static const float P128[3] = {-453.68, -183.93, 9466.67}; +static const float P129[3] = {428.43, -124.08, 9503.03}; +static const float P130[3] = {419.73, -142.14, 9534.56}; +static const float P131[3] = {419.92, -179.96, 9534.56}; +static const float P132[3] = {431.2, -199.73, 9505.26}; +static const float P133[3] = {442.28, -181.67, 9475.96}; +static const float P134[3] = {442.08, -143.84, 9475.96}; +/* *INDENT-ON* */ + + + +static void +Dolphin001(GLenum cap) +{ + glNormal3fv(N071); + glBegin(cap); + glVertex3fv(P001); + glVertex3fv(P068); + glVertex3fv(P010); + glEnd(); + glBegin(cap); + glVertex3fv(P068); + glVertex3fv(P076); + glVertex3fv(P010); + glEnd(); + glBegin(cap); + glVertex3fv(P068); + glVertex3fv(P070); + glVertex3fv(P076); + glEnd(); + glBegin(cap); + glVertex3fv(P076); + glVertex3fv(P070); + glVertex3fv(P074); + glEnd(); + glBegin(cap); + glVertex3fv(P070); + glVertex3fv(P072); + glVertex3fv(P074); + glEnd(); + glNormal3fv(N119); + glBegin(cap); + glVertex3fv(P072); + glVertex3fv(P070); + glVertex3fv(P074); + glEnd(); + glBegin(cap); + glVertex3fv(P074); + glVertex3fv(P070); + glVertex3fv(P076); + glEnd(); + glBegin(cap); + glVertex3fv(P070); + glVertex3fv(P068); + glVertex3fv(P076); + glEnd(); + glBegin(cap); + glVertex3fv(P076); + glVertex3fv(P068); + glVertex3fv(P010); + glEnd(); + glBegin(cap); + glVertex3fv(P068); + glVertex3fv(P001); + glVertex3fv(P010); + glEnd(); +} + +static void +Dolphin002(GLenum cap) +{ + glNormal3fv(N071); + glBegin(cap); + glVertex3fv(P011); + glVertex3fv(P001); + glVertex3fv(P009); + glEnd(); + glBegin(cap); + glVertex3fv(P075); + glVertex3fv(P011); + glVertex3fv(P009); + glEnd(); + glBegin(cap); + glVertex3fv(P069); + glVertex3fv(P011); + glVertex3fv(P075); + glEnd(); + glBegin(cap); + glVertex3fv(P069); + glVertex3fv(P075); + glVertex3fv(P073); + glEnd(); + glBegin(cap); + glVertex3fv(P071); + glVertex3fv(P069); + glVertex3fv(P073); + glEnd(); + glNormal3fv(N119); + glBegin(cap); + glVertex3fv(P001); + glVertex3fv(P011); + glVertex3fv(P009); + glEnd(); + glBegin(cap); + glVertex3fv(P009); + glVertex3fv(P011); + glVertex3fv(P075); + glEnd(); + glBegin(cap); + glVertex3fv(P011); + glVertex3fv(P069); + glVertex3fv(P075); + glEnd(); + glBegin(cap); + glVertex3fv(P069); + glVertex3fv(P073); + glVertex3fv(P075); + glEnd(); + glBegin(cap); + glVertex3fv(P069); + glVertex3fv(P071); + glVertex3fv(P073); + glEnd(); +} + +static void +Dolphin003(GLenum cap) +{ + glBegin(cap); + glNormal3fv(N018); + glVertex3fv(P018); + glNormal3fv(N001); + glVertex3fv(P001); + glNormal3fv(N019); + glVertex3fv(P019); + glEnd(); + glBegin(cap); + glNormal3fv(N019); + glVertex3fv(P019); + glNormal3fv(N001); + glVertex3fv(P001); + glNormal3fv(N012); + glVertex3fv(P012); + glEnd(); + glBegin(cap); + glNormal3fv(N017); + glVertex3fv(P017); + glNormal3fv(N001); + glVertex3fv(P001); + glNormal3fv(N018); + glVertex3fv(P018); + glEnd(); + glBegin(cap); + glNormal3fv(N001); + glVertex3fv(P001); + glNormal3fv(N017); + glVertex3fv(P017); + glNormal3fv(N016); + glVertex3fv(P016); + glEnd(); + glBegin(cap); + glNormal3fv(N001); + glVertex3fv(P001); + glNormal3fv(N013); + glVertex3fv(P013); + glNormal3fv(N012); + glVertex3fv(P012); + glEnd(); + glBegin(cap); + glNormal3fv(N001); + glVertex3fv(P001); + glNormal3fv(N016); + glVertex3fv(P016); + glNormal3fv(N015); + glVertex3fv(P015); + glEnd(); + glBegin(cap); + glNormal3fv(N001); + glVertex3fv(P001); + glNormal3fv(N014); + glVertex3fv(P014); + glNormal3fv(N013); + glVertex3fv(P013); + glEnd(); + glBegin(cap); + glNormal3fv(N001); + glVertex3fv(P001); + glNormal3fv(N015); + glVertex3fv(P015); + glNormal3fv(N014); + glVertex3fv(P014); + glEnd(); +} + +static void +Dolphin004(GLenum cap) +{ + glBegin(cap); + glNormal3fv(N014); + glVertex3fv(P014); + glNormal3fv(N015); + glVertex3fv(P015); + glNormal3fv(N023); + glVertex3fv(P023); + glNormal3fv(N022); + glVertex3fv(P022); + glEnd(); + glBegin(cap); + glNormal3fv(N015); + glVertex3fv(P015); + glNormal3fv(N016); + glVertex3fv(P016); + glNormal3fv(N024); + glVertex3fv(P024); + glNormal3fv(N023); + glVertex3fv(P023); + glEnd(); + glBegin(cap); + glNormal3fv(N016); + glVertex3fv(P016); + glNormal3fv(N017); + glVertex3fv(P017); + glNormal3fv(N025); + glVertex3fv(P025); + glNormal3fv(N024); + glVertex3fv(P024); + glEnd(); + glBegin(cap); + glNormal3fv(N017); + glVertex3fv(P017); + glNormal3fv(N018); + glVertex3fv(P018); + glNormal3fv(N026); + glVertex3fv(P026); + glNormal3fv(N025); + glVertex3fv(P025); + glEnd(); + glBegin(cap); + glNormal3fv(N013); + glVertex3fv(P013); + glNormal3fv(N014); + glVertex3fv(P014); + glNormal3fv(N022); + glVertex3fv(P022); + glNormal3fv(N021); + glVertex3fv(P021); + glEnd(); + glBegin(cap); + glNormal3fv(N012); + glVertex3fv(P012); + glNormal3fv(N013); + glVertex3fv(P013); + glNormal3fv(N021); + glVertex3fv(P021); + glNormal3fv(N020); + glVertex3fv(P020); + glEnd(); + glBegin(cap); + glNormal3fv(N018); + glVertex3fv(P018); + glNormal3fv(N019); + glVertex3fv(P019); + glNormal3fv(N027); + glVertex3fv(P027); + glNormal3fv(N026); + glVertex3fv(P026); + glEnd(); + glBegin(cap); + glNormal3fv(N019); + glVertex3fv(P019); + glNormal3fv(N012); + glVertex3fv(P012); + glNormal3fv(N020); + glVertex3fv(P020); + glNormal3fv(N027); + glVertex3fv(P027); + glEnd(); +} + +static void +Dolphin005(GLenum cap) +{ + glBegin(cap); + glNormal3fv(N022); + glVertex3fv(P022); + glNormal3fv(N023); + glVertex3fv(P023); + glNormal3fv(N031); + glVertex3fv(P031); + glNormal3fv(N030); + glVertex3fv(P030); + glEnd(); + glBegin(cap); + glNormal3fv(N021); + glVertex3fv(P021); + glNormal3fv(N022); + glVertex3fv(P022); + glNormal3fv(N030); + glVertex3fv(P030); + glEnd(); + glBegin(cap); + glNormal3fv(N021); + glVertex3fv(P021); + glNormal3fv(N030); + glVertex3fv(P030); + glNormal3fv(N029); + glVertex3fv(P029); + glEnd(); + glBegin(cap); + glNormal3fv(N023); + glVertex3fv(P023); + glNormal3fv(N024); + glVertex3fv(P024); + glNormal3fv(N031); + glVertex3fv(P031); + glEnd(); + glBegin(cap); + glNormal3fv(N024); + glVertex3fv(P024); + glNormal3fv(N032); + glVertex3fv(P032); + glNormal3fv(N031); + glVertex3fv(P031); + glEnd(); + glBegin(cap); + glNormal3fv(N024); + glVertex3fv(P024); + glNormal3fv(N025); + glVertex3fv(P025); + glNormal3fv(N032); + glVertex3fv(P032); + glEnd(); + glBegin(cap); + glNormal3fv(N025); + glVertex3fv(P025); + glNormal3fv(N033); + glVertex3fv(P033); + glNormal3fv(N032); + glVertex3fv(P032); + glEnd(); + glBegin(cap); + glNormal3fv(N020); + glVertex3fv(P020); + glNormal3fv(N021); + glVertex3fv(P021); + glNormal3fv(N029); + glVertex3fv(P029); + glEnd(); + glBegin(cap); + glNormal3fv(N020); + glVertex3fv(P020); + glNormal3fv(N029); + glVertex3fv(P029); + glNormal3fv(N028); + glVertex3fv(P028); + glEnd(); + glBegin(cap); + glNormal3fv(N027); + glVertex3fv(P027); + glNormal3fv(N020); + glVertex3fv(P020); + glNormal3fv(N028); + glVertex3fv(P028); + glEnd(); + glBegin(cap); + glNormal3fv(N027); + glVertex3fv(P027); + glNormal3fv(N028); + glVertex3fv(P028); + glNormal3fv(N035); + glVertex3fv(P035); + glEnd(); + glBegin(cap); + glNormal3fv(N025); + glVertex3fv(P025); + glNormal3fv(N026); + glVertex3fv(P026); + glNormal3fv(N033); + glVertex3fv(P033); + glEnd(); + glBegin(cap); + glNormal3fv(N033); + glVertex3fv(P033); + glNormal3fv(N026); + glVertex3fv(P026); + glNormal3fv(N034); + glVertex3fv(P034); + glEnd(); + glBegin(cap); + glNormal3fv(N026); + glVertex3fv(P026); + glNormal3fv(N027); + glVertex3fv(P027); + glNormal3fv(N035); + glVertex3fv(P035); + glNormal3fv(N034); + glVertex3fv(P034); + glEnd(); +} + +static void +Dolphin006(GLenum cap) +{ + glBegin(cap); + glNormal3fv(N092); + glVertex3fv(P092); + glNormal3fv(N093); + glVertex3fv(P093); + glNormal3fv(N094); + glVertex3fv(P094); + glEnd(); + glBegin(cap); + glNormal3fv(N093); + glVertex3fv(P093); + glNormal3fv(N092); + glVertex3fv(P092); + glNormal3fv(N094); + glVertex3fv(P094); + glEnd(); + glBegin(cap); + glNormal3fv(N092); + glVertex3fv(P092); + glNormal3fv(N091); + glVertex3fv(P091); + glNormal3fv(N095); + glVertex3fv(P095); + glNormal3fv(N094); + glVertex3fv(P094); + glEnd(); + glBegin(cap); + glNormal3fv(N091); + glVertex3fv(P091); + glNormal3fv(N092); + glVertex3fv(P092); + glNormal3fv(N094); + glVertex3fv(P094); + glNormal3fv(N095); + glVertex3fv(P095); + glEnd(); + glBegin(cap); + glNormal3fv(N122); + glVertex3fv(P122); + glNormal3fv(N095); + glVertex3fv(P095); + glNormal3fv(N091); + glVertex3fv(P091); + glEnd(); + glBegin(cap); + glNormal3fv(N122); + glVertex3fv(P122); + glNormal3fv(N091); + glVertex3fv(P091); + glNormal3fv(N095); + glVertex3fv(P095); + glEnd(); +} + +static void +Dolphin007(GLenum cap) +{ + glBegin(cap); + glNormal3fv(N030); + glVertex3fv(P030); + glNormal3fv(N031); + glVertex3fv(P031); + glNormal3fv(N039); + glVertex3fv(P039); + glNormal3fv(N038); + glVertex3fv(P038); + glEnd(); + glBegin(cap); + glNormal3fv(N029); + glVertex3fv(P029); + glNormal3fv(N030); + glVertex3fv(P030); + glNormal3fv(N038); + glVertex3fv(P038); + glEnd(); + glBegin(cap); + glNormal3fv(N029); + glVertex3fv(P029); + glNormal3fv(N038); + glVertex3fv(P038); + glNormal3fv(N037); + glVertex3fv(P037); + glEnd(); + glBegin(cap); + glNormal3fv(N028); + glVertex3fv(P028); + glNormal3fv(N029); + glVertex3fv(P029); + glNormal3fv(N037); + glVertex3fv(P037); + glEnd(); + glBegin(cap); + glNormal3fv(N028); + glVertex3fv(P028); + glNormal3fv(N037); + glVertex3fv(P037); + glNormal3fv(N036); + glVertex3fv(P036); + glEnd(); + glBegin(cap); + glNormal3fv(N035); + glVertex3fv(P035); + glNormal3fv(N028); + glVertex3fv(P028); + glNormal3fv(N036); + glVertex3fv(P036); + glEnd(); + glBegin(cap); + glNormal3fv(N035); + glVertex3fv(P035); + glNormal3fv(N036); + glVertex3fv(P036); + glNormal3fv(N043); + glVertex3fv(P043); + glEnd(); + glBegin(cap); + glNormal3fv(N034); + glVertex3fv(P034); + glNormal3fv(N035); + glVertex3fv(P035); + glNormal3fv(N043); + glVertex3fv(P043); + glNormal3fv(N042); + glVertex3fv(P042); + glEnd(); + glBegin(cap); + glNormal3fv(N033); + glVertex3fv(P033); + glNormal3fv(N034); + glVertex3fv(P034); + glNormal3fv(N042); + glVertex3fv(P042); + glEnd(); + glBegin(cap); + glNormal3fv(N033); + glVertex3fv(P033); + glNormal3fv(N042); + glVertex3fv(P042); + glNormal3fv(N041); + glVertex3fv(P041); + glEnd(); + glBegin(cap); + glNormal3fv(N031); + glVertex3fv(P031); + glNormal3fv(N032); + glVertex3fv(P032); + glNormal3fv(N039); + glVertex3fv(P039); + glEnd(); + glBegin(cap); + glNormal3fv(N039); + glVertex3fv(P039); + glNormal3fv(N032); + glVertex3fv(P032); + glNormal3fv(N040); + glVertex3fv(P040); + glEnd(); + glBegin(cap); + glNormal3fv(N032); + glVertex3fv(P032); + glNormal3fv(N033); + glVertex3fv(P033); + glNormal3fv(N040); + glVertex3fv(P040); + glEnd(); + glBegin(cap); + glNormal3fv(N040); + glVertex3fv(P040); + glNormal3fv(N033); + glVertex3fv(P033); + glNormal3fv(N041); + glVertex3fv(P041); + glEnd(); +} + +static void +Dolphin008(GLenum cap) +{ + glBegin(cap); + glNormal3fv(N042); + glVertex3fv(P042); + glNormal3fv(N043); + glVertex3fv(P043); + glNormal3fv(N051); + glVertex3fv(P051); + glNormal3fv(N050); + glVertex3fv(P050); + glEnd(); + glBegin(cap); + glNormal3fv(N043); + glVertex3fv(P043); + glNormal3fv(N036); + glVertex3fv(P036); + glNormal3fv(N051); + glVertex3fv(P051); + glEnd(); + glBegin(cap); + glNormal3fv(N051); + glVertex3fv(P051); + glNormal3fv(N036); + glVertex3fv(P036); + glNormal3fv(N044); + glVertex3fv(P044); + glEnd(); + glBegin(cap); + glNormal3fv(N041); + glVertex3fv(P041); + glNormal3fv(N042); + glVertex3fv(P042); + glNormal3fv(N050); + glVertex3fv(P050); + glEnd(); + glBegin(cap); + glNormal3fv(N041); + glVertex3fv(P041); + glNormal3fv(N050); + glVertex3fv(P050); + glNormal3fv(N049); + glVertex3fv(P049); + glEnd(); + glBegin(cap); + glNormal3fv(N036); + glVertex3fv(P036); + glNormal3fv(N037); + glVertex3fv(P037); + glNormal3fv(N044); + glVertex3fv(P044); + glEnd(); + glBegin(cap); + glNormal3fv(N044); + glVertex3fv(P044); + glNormal3fv(N037); + glVertex3fv(P037); + glNormal3fv(N045); + glVertex3fv(P045); + glEnd(); + glBegin(cap); + glNormal3fv(N040); + glVertex3fv(P040); + glNormal3fv(N041); + glVertex3fv(P041); + glNormal3fv(N049); + glVertex3fv(P049); + glEnd(); + glBegin(cap); + glNormal3fv(N040); + glVertex3fv(P040); + glNormal3fv(N049); + glVertex3fv(P049); + glNormal3fv(N048); + glVertex3fv(P048); + glEnd(); + glBegin(cap); + glNormal3fv(N039); + glVertex3fv(P039); + glNormal3fv(N040); + glVertex3fv(P040); + glNormal3fv(N048); + glVertex3fv(P048); + glEnd(); + glBegin(cap); + glNormal3fv(N039); + glVertex3fv(P039); + glNormal3fv(N048); + glVertex3fv(P048); + glNormal3fv(N047); + glVertex3fv(P047); + glEnd(); + glBegin(cap); + glNormal3fv(N037); + glVertex3fv(P037); + glNormal3fv(N038); + glVertex3fv(P038); + glNormal3fv(N045); + glVertex3fv(P045); + glEnd(); + glBegin(cap); + glNormal3fv(N038); + glVertex3fv(P038); + glNormal3fv(N046); + glVertex3fv(P046); + glNormal3fv(N045); + glVertex3fv(P045); + glEnd(); + glBegin(cap); + glNormal3fv(N038); + glVertex3fv(P038); + glNormal3fv(N039); + glVertex3fv(P039); + glNormal3fv(N047); + glVertex3fv(P047); + glNormal3fv(N046); + glVertex3fv(P046); + glEnd(); +} + +static void +Dolphin009(GLenum cap) +{ + glBegin(cap); + glNormal3fv(N050); + glVertex3fv(P050); + glNormal3fv(N051); + glVertex3fv(P051); + glNormal3fv(N059); + glVertex3fv(P059); + glNormal3fv(N058); + glVertex3fv(P058); + glEnd(); + glBegin(cap); + glNormal3fv(N051); + glVertex3fv(P051); + glNormal3fv(N044); + glVertex3fv(P044); + glNormal3fv(N059); + glVertex3fv(P059); + glEnd(); + glBegin(cap); + glNormal3fv(N059); + glVertex3fv(P059); + glNormal3fv(N044); + glVertex3fv(P044); + glNormal3fv(N052); + glVertex3fv(P052); + glEnd(); + glBegin(cap); + glNormal3fv(N044); + glVertex3fv(P044); + glNormal3fv(N045); + glVertex3fv(P045); + glNormal3fv(N053); + glVertex3fv(P053); + glEnd(); + glBegin(cap); + glNormal3fv(N044); + glVertex3fv(P044); + glNormal3fv(N053); + glVertex3fv(P053); + glNormal3fv(N052); + glVertex3fv(P052); + glEnd(); + glBegin(cap); + glNormal3fv(N049); + glVertex3fv(P049); + glNormal3fv(N050); + glVertex3fv(P050); + glNormal3fv(N058); + glVertex3fv(P058); + glEnd(); + glBegin(cap); + glNormal3fv(N049); + glVertex3fv(P049); + glNormal3fv(N058); + glVertex3fv(P058); + glNormal3fv(N057); + glVertex3fv(P057); + glEnd(); + glBegin(cap); + glNormal3fv(N048); + glVertex3fv(P048); + glNormal3fv(N049); + glVertex3fv(P049); + glNormal3fv(N057); + glVertex3fv(P057); + glEnd(); + glBegin(cap); + glNormal3fv(N048); + glVertex3fv(P048); + glNormal3fv(N057); + glVertex3fv(P057); + glNormal3fv(N056); + glVertex3fv(P056); + glEnd(); + glBegin(cap); + glNormal3fv(N047); + glVertex3fv(P047); + glNormal3fv(N048); + glVertex3fv(P048); + glNormal3fv(N056); + glVertex3fv(P056); + glEnd(); + glBegin(cap); + glNormal3fv(N047); + glVertex3fv(P047); + glNormal3fv(N056); + glVertex3fv(P056); + glNormal3fv(N055); + glVertex3fv(P055); + glEnd(); + glBegin(cap); + glNormal3fv(N045); + glVertex3fv(P045); + glNormal3fv(N046); + glVertex3fv(P046); + glNormal3fv(N053); + glVertex3fv(P053); + glEnd(); + glBegin(cap); + glNormal3fv(N046); + glVertex3fv(P046); + glNormal3fv(N054); + glVertex3fv(P054); + glNormal3fv(N053); + glVertex3fv(P053); + glEnd(); + glBegin(cap); + glNormal3fv(N046); + glVertex3fv(P046); + glNormal3fv(N047); + glVertex3fv(P047); + glNormal3fv(N055); + glVertex3fv(P055); + glNormal3fv(N054); + glVertex3fv(P054); + glEnd(); +} + +static void +Dolphin010(GLenum cap) +{ + glBegin(cap); + glNormal3fv(N080); + glVertex3fv(P080); + glNormal3fv(N081); + glVertex3fv(P081); + glNormal3fv(N085); + glVertex3fv(P085); + glEnd(); + glBegin(cap); + glNormal3fv(N081); + glVertex3fv(P081); + glNormal3fv(N083); + glVertex3fv(P083); + glNormal3fv(N085); + glVertex3fv(P085); + glEnd(); + glBegin(cap); + glNormal3fv(N085); + glVertex3fv(P085); + glNormal3fv(N083); + glVertex3fv(P083); + glNormal3fv(N077); + glVertex3fv(P077); + glEnd(); + glBegin(cap); + glNormal3fv(N083); + glVertex3fv(P083); + glNormal3fv(N087); + glVertex3fv(P087); + glNormal3fv(N077); + glVertex3fv(P077); + glEnd(); + glBegin(cap); + glNormal3fv(N077); + glVertex3fv(P077); + glNormal3fv(N087); + glVertex3fv(P087); + glNormal3fv(N090); + glVertex3fv(P090); + glEnd(); + glBegin(cap); + glNormal3fv(N081); + glVertex3fv(P081); + glNormal3fv(N080); + glVertex3fv(P080); + glNormal3fv(N085); + glVertex3fv(P085); + glEnd(); + glBegin(cap); + glNormal3fv(N083); + glVertex3fv(P083); + glNormal3fv(N081); + glVertex3fv(P081); + glNormal3fv(N085); + glVertex3fv(P085); + glEnd(); + glBegin(cap); + glNormal3fv(N083); + glVertex3fv(P083); + glNormal3fv(N085); + glVertex3fv(P085); + glNormal3fv(N077); + glVertex3fv(P077); + glEnd(); + glBegin(cap); + glNormal3fv(N087); + glVertex3fv(P087); + glNormal3fv(N083); + glVertex3fv(P083); + glNormal3fv(N077); + glVertex3fv(P077); + glEnd(); + glBegin(cap); + glNormal3fv(N087); + glVertex3fv(P087); + glNormal3fv(N077); + glVertex3fv(P077); + glNormal3fv(N090); + glVertex3fv(P090); + glEnd(); +} + +static void +Dolphin011(GLenum cap) +{ + glBegin(cap); + glNormal3fv(N082); + glVertex3fv(P082); + glNormal3fv(N084); + glVertex3fv(P084); + glNormal3fv(N079); + glVertex3fv(P079); + glEnd(); + glBegin(cap); + glNormal3fv(N084); + glVertex3fv(P084); + glNormal3fv(N086); + glVertex3fv(P086); + glNormal3fv(N079); + glVertex3fv(P079); + glEnd(); + glBegin(cap); + glNormal3fv(N079); + glVertex3fv(P079); + glNormal3fv(N086); + glVertex3fv(P086); + glNormal3fv(N078); + glVertex3fv(P078); + glEnd(); + glBegin(cap); + glNormal3fv(N086); + glVertex3fv(P086); + glNormal3fv(N088); + glVertex3fv(P088); + glNormal3fv(N078); + glVertex3fv(P078); + glEnd(); + glBegin(cap); + glNormal3fv(N078); + glVertex3fv(P078); + glNormal3fv(N088); + glVertex3fv(P088); + glNormal3fv(N089); + glVertex3fv(P089); + glEnd(); + glBegin(cap); + glNormal3fv(N088); + glVertex3fv(P088); + glNormal3fv(N086); + glVertex3fv(P086); + glNormal3fv(N089); + glVertex3fv(P089); + glEnd(); + glBegin(cap); + glNormal3fv(N089); + glVertex3fv(P089); + glNormal3fv(N086); + glVertex3fv(P086); + glNormal3fv(N078); + glVertex3fv(P078); + glEnd(); + glBegin(cap); + glNormal3fv(N086); + glVertex3fv(P086); + glNormal3fv(N084); + glVertex3fv(P084); + glNormal3fv(N078); + glVertex3fv(P078); + glEnd(); + glBegin(cap); + glNormal3fv(N078); + glVertex3fv(P078); + glNormal3fv(N084); + glVertex3fv(P084); + glNormal3fv(N079); + glVertex3fv(P079); + glEnd(); + glBegin(cap); + glNormal3fv(N084); + glVertex3fv(P084); + glNormal3fv(N082); + glVertex3fv(P082); + glNormal3fv(N079); + glVertex3fv(P079); + glEnd(); +} + +static void +Dolphin012(GLenum cap) +{ + glBegin(cap); + glNormal3fv(N058); + glVertex3fv(P058); + glNormal3fv(N059); + glVertex3fv(P059); + glNormal3fv(N067); + glVertex3fv(P067); + glNormal3fv(N066); + glVertex3fv(P066); + glEnd(); + glBegin(cap); + glNormal3fv(N059); + glVertex3fv(P059); + glNormal3fv(N052); + glVertex3fv(P052); + glNormal3fv(N060); + glVertex3fv(P060); + glEnd(); + glBegin(cap); + glNormal3fv(N059); + glVertex3fv(P059); + glNormal3fv(N060); + glVertex3fv(P060); + glNormal3fv(N067); + glVertex3fv(P067); + glEnd(); + glBegin(cap); + glNormal3fv(N058); + glVertex3fv(P058); + glNormal3fv(N066); + glVertex3fv(P066); + glNormal3fv(N065); + glVertex3fv(P065); + glEnd(); + glBegin(cap); + glNormal3fv(N058); + glVertex3fv(P058); + glNormal3fv(N065); + glVertex3fv(P065); + glNormal3fv(N057); + glVertex3fv(P057); + glEnd(); + glBegin(cap); + glNormal3fv(N056); + glVertex3fv(P056); + glNormal3fv(N057); + glVertex3fv(P057); + glNormal3fv(N065); + glVertex3fv(P065); + glEnd(); + glBegin(cap); + glNormal3fv(N056); + glVertex3fv(P056); + glNormal3fv(N065); + glVertex3fv(P065); + glNormal3fv(N006); + glVertex3fv(P006); + glEnd(); + glBegin(cap); + glNormal3fv(N056); + glVertex3fv(P056); + glNormal3fv(N006); + glVertex3fv(P006); + glNormal3fv(N063); + glVertex3fv(P063); + glEnd(); + glBegin(cap); + glNormal3fv(N056); + glVertex3fv(P056); + glNormal3fv(N063); + glVertex3fv(P063); + glNormal3fv(N055); + glVertex3fv(P055); + glEnd(); + glBegin(cap); + glNormal3fv(N054); + glVertex3fv(P054); + glNormal3fv(N062); + glVertex3fv(P062); + glNormal3fv(N005); + glVertex3fv(P005); + glEnd(); + glBegin(cap); + glNormal3fv(N054); + glVertex3fv(P054); + glNormal3fv(N005); + glVertex3fv(P005); + glNormal3fv(N053); + glVertex3fv(P053); + glEnd(); + glBegin(cap); + glNormal3fv(N052); + glVertex3fv(P052); + glNormal3fv(N053); + glVertex3fv(P053); + glNormal3fv(N005); + glVertex3fv(P005); + glNormal3fv(N060); + glVertex3fv(P060); + glEnd(); +} + +static void +Dolphin013(GLenum cap) +{ + glBegin(cap); + glNormal3fv(N116); + glVertex3fv(P116); + glNormal3fv(N117); + glVertex3fv(P117); + glNormal3fv(N112); + glVertex3fv(P112); + glNormal3fv(N113); + glVertex3fv(P113); + glEnd(); + glBegin(cap); + glNormal3fv(N114); + glVertex3fv(P114); + glNormal3fv(N113); + glVertex3fv(P113); + glNormal3fv(N112); + glVertex3fv(P112); + glNormal3fv(N115); + glVertex3fv(P115); + glEnd(); + glBegin(cap); + glNormal3fv(N114); + glVertex3fv(P114); + glNormal3fv(N116); + glVertex3fv(P116); + glNormal3fv(N113); + glVertex3fv(P113); + glEnd(); + glBegin(cap); + glNormal3fv(N114); + glVertex3fv(P114); + glNormal3fv(N007); + glVertex3fv(P007); + glNormal3fv(N116); + glVertex3fv(P116); + glEnd(); + glBegin(cap); + glNormal3fv(N007); + glVertex3fv(P007); + glNormal3fv(N002); + glVertex3fv(P002); + glNormal3fv(N116); + glVertex3fv(P116); + glEnd(); + glBegin(cap); + glVertex3fv(P002); + glVertex3fv(P007); + glVertex3fv(P008); + glVertex3fv(P099); + glEnd(); + glBegin(cap); + glVertex3fv(P007); + glVertex3fv(P114); + glVertex3fv(P115); + glVertex3fv(P008); + glEnd(); + glBegin(cap); + glNormal3fv(N117); + glVertex3fv(P117); + glNormal3fv(N099); + glVertex3fv(P099); + glNormal3fv(N008); + glVertex3fv(P008); + glEnd(); + glBegin(cap); + glNormal3fv(N117); + glVertex3fv(P117); + glNormal3fv(N008); + glVertex3fv(P008); + glNormal3fv(N112); + glVertex3fv(P112); + glEnd(); + glBegin(cap); + glNormal3fv(N112); + glVertex3fv(P112); + glNormal3fv(N008); + glVertex3fv(P008); + glNormal3fv(N115); + glVertex3fv(P115); + glEnd(); +} + +static void +Dolphin014(GLenum cap) +{ + glBegin(cap); + glNormal3fv(N111); + glVertex3fv(P111); + glNormal3fv(N110); + glVertex3fv(P110); + glNormal3fv(N102); + glVertex3fv(P102); + glNormal3fv(N121); + glVertex3fv(P121); + glEnd(); + glBegin(cap); + glNormal3fv(N111); + glVertex3fv(P111); + glNormal3fv(N097); + glVertex3fv(P097); + glNormal3fv(N110); + glVertex3fv(P110); + glEnd(); + glBegin(cap); + glNormal3fv(N097); + glVertex3fv(P097); + glNormal3fv(N119); + glVertex3fv(P119); + glNormal3fv(N110); + glVertex3fv(P110); + glEnd(); + glBegin(cap); + glNormal3fv(N097); + glVertex3fv(P097); + glNormal3fv(N099); + glVertex3fv(P099); + glNormal3fv(N119); + glVertex3fv(P119); + glEnd(); + glBegin(cap); + glNormal3fv(N099); + glVertex3fv(P099); + glNormal3fv(N065); + glVertex3fv(P065); + glNormal3fv(N119); + glVertex3fv(P119); + glEnd(); + glBegin(cap); + glNormal3fv(N065); + glVertex3fv(P065); + glNormal3fv(N066); + glVertex3fv(P066); + glNormal3fv(N119); + glVertex3fv(P119); + glEnd(); + glBegin(cap); + glVertex3fv(P098); + glVertex3fv(P097); + glVertex3fv(P111); + glVertex3fv(P121); + glEnd(); + glBegin(cap); + glVertex3fv(P002); + glVertex3fv(P099); + glVertex3fv(P097); + glVertex3fv(P098); + glEnd(); + glBegin(cap); + glNormal3fv(N110); + glVertex3fv(P110); + glNormal3fv(N119); + glVertex3fv(P119); + glNormal3fv(N118); + glVertex3fv(P118); + glNormal3fv(N102); + glVertex3fv(P102); + glEnd(); + glBegin(cap); + glNormal3fv(N119); + glVertex3fv(P119); + glNormal3fv(N066); + glVertex3fv(P066); + glNormal3fv(N067); + glVertex3fv(P067); + glNormal3fv(N118); + glVertex3fv(P118); + glEnd(); + glBegin(cap); + glNormal3fv(N067); + glVertex3fv(P067); + glNormal3fv(N060); + glVertex3fv(P060); + glNormal3fv(N002); + glVertex3fv(P002); + glEnd(); + glBegin(cap); + glNormal3fv(N067); + glVertex3fv(P067); + glNormal3fv(N002); + glVertex3fv(P002); + glNormal3fv(N118); + glVertex3fv(P118); + glEnd(); + glBegin(cap); + glNormal3fv(N118); + glVertex3fv(P118); + glNormal3fv(N002); + glVertex3fv(P002); + glNormal3fv(N098); + glVertex3fv(P098); + glEnd(); + glBegin(cap); + glNormal3fv(N118); + glVertex3fv(P118); + glNormal3fv(N098); + glVertex3fv(P098); + glNormal3fv(N102); + glVertex3fv(P102); + glEnd(); + glBegin(cap); + glNormal3fv(N102); + glVertex3fv(P102); + glNormal3fv(N098); + glVertex3fv(P098); + glNormal3fv(N121); + glVertex3fv(P121); + glEnd(); +} + +static void +Dolphin015(GLenum cap) +{ + glBegin(cap); + glNormal3fv(N055); + glVertex3fv(P055); + glNormal3fv(N003); + glVertex3fv(P003); + glNormal3fv(N054); + glVertex3fv(P054); + glEnd(); + glBegin(cap); + glNormal3fv(N003); + glVertex3fv(P003); + glNormal3fv(N055); + glVertex3fv(P055); + glNormal3fv(N063); + glVertex3fv(P063); + glEnd(); + glBegin(cap); + glNormal3fv(N003); + glVertex3fv(P003); + glNormal3fv(N063); + glVertex3fv(P063); + glNormal3fv(N100); + glVertex3fv(P100); + glEnd(); + glBegin(cap); + glNormal3fv(N003); + glVertex3fv(P003); + glNormal3fv(N100); + glVertex3fv(P100); + glNormal3fv(N054); + glVertex3fv(P054); + glEnd(); + glBegin(cap); + glNormal3fv(N054); + glVertex3fv(P054); + glNormal3fv(N100); + glVertex3fv(P100); + glNormal3fv(N062); + glVertex3fv(P062); + glEnd(); + glBegin(cap); + glNormal3fv(N100); + glVertex3fv(P100); + glNormal3fv(N064); + glVertex3fv(P064); + glNormal3fv(N120); + glVertex3fv(P120); + glEnd(); + glBegin(cap); + glNormal3fv(N100); + glVertex3fv(P100); + glNormal3fv(N063); + glVertex3fv(P063); + glNormal3fv(N064); + glVertex3fv(P064); + glEnd(); + glBegin(cap); + glNormal3fv(N063); + glVertex3fv(P063); + glNormal3fv(N006); + glVertex3fv(P006); + glNormal3fv(N064); + glVertex3fv(P064); + glEnd(); + glBegin(cap); + glNormal3fv(N064); + glVertex3fv(P064); + glNormal3fv(N006); + glVertex3fv(P006); + glNormal3fv(N099); + glVertex3fv(P099); + glEnd(); + glBegin(cap); + glNormal3fv(N064); + glVertex3fv(P064); + glNormal3fv(N099); + glVertex3fv(P099); + glNormal3fv(N117); + glVertex3fv(P117); + glEnd(); + glBegin(cap); + glNormal3fv(N120); + glVertex3fv(P120); + glNormal3fv(N064); + glVertex3fv(P064); + glNormal3fv(N117); + glVertex3fv(P117); + glNormal3fv(N116); + glVertex3fv(P116); + glEnd(); + glBegin(cap); + glNormal3fv(N006); + glVertex3fv(P006); + glNormal3fv(N065); + glVertex3fv(P065); + glNormal3fv(N099); + glVertex3fv(P099); + glEnd(); + glBegin(cap); + glNormal3fv(N062); + glVertex3fv(P062); + glNormal3fv(N100); + glVertex3fv(P100); + glNormal3fv(N120); + glVertex3fv(P120); + glEnd(); + glBegin(cap); + glNormal3fv(N005); + glVertex3fv(P005); + glNormal3fv(N062); + glVertex3fv(P062); + glNormal3fv(N120); + glVertex3fv(P120); + glEnd(); + glBegin(cap); + glNormal3fv(N005); + glVertex3fv(P005); + glNormal3fv(N120); + glVertex3fv(P120); + glNormal3fv(N002); + glVertex3fv(P002); + glEnd(); + glBegin(cap); + glNormal3fv(N002); + glVertex3fv(P002); + glNormal3fv(N120); + glVertex3fv(P120); + glNormal3fv(N116); + glVertex3fv(P116); + glEnd(); + glBegin(cap); + glNormal3fv(N060); + glVertex3fv(P060); + glNormal3fv(N005); + glVertex3fv(P005); + glNormal3fv(N002); + glVertex3fv(P002); + glEnd(); +} + +static void +Dolphin016(GLenum cap) +{ + + glDisable(GL_DEPTH_TEST); + glBegin(cap); + glVertex3fv(P123); + glVertex3fv(P124); + glVertex3fv(P125); + glVertex3fv(P126); + glVertex3fv(P127); + glVertex3fv(P128); + glEnd(); + glBegin(cap); + glVertex3fv(P129); + glVertex3fv(P130); + glVertex3fv(P131); + glVertex3fv(P132); + glVertex3fv(P133); + glVertex3fv(P134); + glEnd(); + glBegin(cap); + glVertex3fv(P103); + glVertex3fv(P105); + glVertex3fv(P108); + glEnd(); + glEnable(GL_DEPTH_TEST); +} + +void +DrawDolphin(fishRec * fish, int wire) +{ + float seg0, seg1, seg2, seg3, seg4, seg5, seg6, seg7; + float pitch, thrash, chomp; + GLenum cap; + + fish->htail = (int) (fish->htail - (int) (10 * fish->v)) % 360; + + thrash = 70 * fish->v; + + seg0 = 1 * thrash * sin((fish->htail) * RRAD); + seg3 = 1 * thrash * sin((fish->htail) * RRAD); + seg1 = 2 * thrash * sin((fish->htail + 4) * RRAD); + seg2 = 3 * thrash * sin((fish->htail + 6) * RRAD); + seg4 = 4 * thrash * sin((fish->htail + 10) * RRAD); + seg5 = 4.5 * thrash * sin((fish->htail + 15) * RRAD); + seg6 = 5 * thrash * sin((fish->htail + 20) * RRAD); + seg7 = 6 * thrash * sin((fish->htail + 30) * RRAD); + + pitch = fish->v * sin((fish->htail + 180) * RRAD); + +/* if (fish->v > 2) { + chomp = -(fish->v - 2) * 200; + }*/ + chomp = 100; + + P012[1] = iP012[1] + seg5; + P013[1] = iP013[1] + seg5; + P014[1] = iP014[1] + seg5; + P015[1] = iP015[1] + seg5; + P016[1] = iP016[1] + seg5; + P017[1] = iP017[1] + seg5; + P018[1] = iP018[1] + seg5; + P019[1] = iP019[1] + seg5; + + P020[1] = iP020[1] + seg4; + P021[1] = iP021[1] + seg4; + P022[1] = iP022[1] + seg4; + P023[1] = iP023[1] + seg4; + P024[1] = iP024[1] + seg4; + P025[1] = iP025[1] + seg4; + P026[1] = iP026[1] + seg4; + P027[1] = iP027[1] + seg4; + + P028[1] = iP028[1] + seg2; + P029[1] = iP029[1] + seg2; + P030[1] = iP030[1] + seg2; + P031[1] = iP031[1] + seg2; + P032[1] = iP032[1] + seg2; + P033[1] = iP033[1] + seg2; + P034[1] = iP034[1] + seg2; + P035[1] = iP035[1] + seg2; + + P036[1] = iP036[1] + seg1; + P037[1] = iP037[1] + seg1; + P038[1] = iP038[1] + seg1; + P039[1] = iP039[1] + seg1; + P040[1] = iP040[1] + seg1; + P041[1] = iP041[1] + seg1; + P042[1] = iP042[1] + seg1; + P043[1] = iP043[1] + seg1; + + P044[1] = iP044[1] + seg0; + P045[1] = iP045[1] + seg0; + P046[1] = iP046[1] + seg0; + P047[1] = iP047[1] + seg0; + P048[1] = iP048[1] + seg0; + P049[1] = iP049[1] + seg0; + P050[1] = iP050[1] + seg0; + P051[1] = iP051[1] + seg0; + + P009[1] = iP009[1] + seg6; + P010[1] = iP010[1] + seg6; + P075[1] = iP075[1] + seg6; + P076[1] = iP076[1] + seg6; + + P001[1] = iP001[1] + seg7; + P011[1] = iP011[1] + seg7; + P068[1] = iP068[1] + seg7; + P069[1] = iP069[1] + seg7; + P070[1] = iP070[1] + seg7; + P071[1] = iP071[1] + seg7; + P072[1] = iP072[1] + seg7; + P073[1] = iP073[1] + seg7; + P074[1] = iP074[1] + seg7; + + P091[1] = iP091[1] + seg3; + P092[1] = iP092[1] + seg3; + P093[1] = iP093[1] + seg3; + P094[1] = iP094[1] + seg3; + P095[1] = iP095[1] + seg3; + P122[1] = iP122[1] + seg3 * 1.5; + + P097[1] = iP097[1] + chomp; + P098[1] = iP098[1] + chomp; + P102[1] = iP102[1] + chomp; + P110[1] = iP110[1] + chomp; + P111[1] = iP111[1] + chomp; + P121[1] = iP121[1] + chomp; + P118[1] = iP118[1] + chomp; + P119[1] = iP119[1] + chomp; + + glPushMatrix(); + + glRotatef(pitch, 1, 0, 0); + + glTranslatef(0, 0, 7000); + + glRotatef(180, 0, 1, 0); + + glEnable(GL_CULL_FACE); + cap = wire ? GL_LINE_LOOP : GL_POLYGON; + Dolphin014(cap); + Dolphin010(cap); + Dolphin009(cap); + Dolphin012(cap); + Dolphin013(cap); + Dolphin006(cap); + Dolphin002(cap); + Dolphin001(cap); + Dolphin003(cap); + Dolphin015(cap); + Dolphin004(cap); + Dolphin005(cap); + Dolphin007(cap); + Dolphin008(cap); + Dolphin011(cap); + Dolphin016(cap); + glDisable(GL_CULL_FACE); + + glPopMatrix(); +} +#endif diff --git a/hacks/glx/dropshadow.c b/hacks/glx/dropshadow.c new file mode 100644 index 00000000..0a5855cc --- /dev/null +++ b/hacks/glx/dropshadow.c @@ -0,0 +1,181 @@ +/* dropshadow.c, Copyright (c) 2009 Jens Kilian + * + * 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. + */ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif /* HAVE_CONFIG_H */ + +#include + +#include "dropshadow.h" + +/* (Alpha) texture data for drop shadow. + */ +static int drop_shadow_width = 32; +static int drop_shadow_height = 32; +static unsigned char drop_shadow_data[] = +{ + 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, 1, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 1, 1, 1, 3, 3, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 3, 3, 1, 1, 1, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 1, 1, 3, 4, 6, 7, 9, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 9, 7, 6, 4, 3, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 3, 5, 9, 13, 16, 19, 19, 21, 21, 22, 22, + 22, 22, 21, 21, 19, 19, 16, 13, 9, 5, 3, 1, 1, 0, 0, 0, + 0, 0, 1, 1, 3, 5, 10, 16, 22, 28, 32, 35, 37, 37, 38, 38, + 38, 38, 37, 37, 35, 32, 28, 22, 16, 10, 5, 3, 1, 1, 0, 0, + 0, 0, 1, 1, 4, 9, 16, 25, 34, 43, 50, 55, 58, 59, 60, 60, + 60, 60, 59, 58, 55, 50, 43, 34, 25, 16, 9, 4, 1, 1, 0, 0, + 0, 0, 1, 3, 6, 13, 22, 34, 48, 61, 70, 77, 80, 82, 83, 84, + 84, 83, 82, 80, 77, 70, 61, 48, 34, 22, 13, 6, 3, 1, 0, 0, + 0, 0, 1, 3, 7, 16, 28, 43, 61, 76, 88, 97, 102, 103, 104, 104, + 104, 104, 103, 102, 97, 88, 76, 61, 43, 28, 16, 7, 3, 1, 0, 0, + 0, 1, 1, 4, 9, 19, 32, 51, 70, 88, 103, 112, 117, 120, 121, 121, + 121, 121, 120, 117, 112, 103, 88, 70, 51, 32, 19, 9, 4, 1, 1, 0, + 0, 1, 1, 4, 10, 20, 35, 55, 77, 97, 112, 122, 128, 130, 132, 133, + 133, 132, 130, 128, 122, 112, 97, 77, 55, 35, 20, 10, 4, 1, 1, 0, + 0, 1, 1, 4, 10, 21, 37, 58, 80, 101, 117, 128, 134, 137, 138, 139, + 139, 138, 137, 134, 128, 117, 101, 80, 58, 37, 21, 10, 4, 1, 0, 0, + 0, 0, 1, 4, 10, 21, 38, 59, 82, 103, 119, 130, 137, 139, 141, 142, + 142, 141, 139, 137, 130, 119, 103, 82, 59, 38, 21, 10, 4, 1, 0, 0, + 0, 0, 1, 4, 10, 22, 38, 59, 83, 104, 121, 132, 139, 141, 142, 142, + 142, 142, 141, 139, 132, 121, 104, 83, 59, 38, 22, 10, 4, 1, 0, 0, + 0, 0, 1, 4, 10, 22, 38, 60, 84, 104, 121, 133, 139, 142, 142, 142, + 142, 142, 142, 139, 133, 121, 104, 84, 60, 38, 22, 10, 4, 1, 0, 0, + 0, 0, 1, 4, 10, 22, 38, 60, 84, 104, 121, 133, 139, 142, 142, 142, + 142, 142, 142, 139, 133, 121, 104, 84, 60, 38, 22, 10, 4, 1, 0, 0, + 0, 0, 1, 4, 10, 22, 38, 59, 83, 104, 121, 132, 139, 141, 142, 142, + 142, 142, 141, 139, 132, 121, 104, 83, 59, 38, 22, 10, 4, 1, 0, 0, + 0, 0, 1, 4, 10, 21, 38, 59, 82, 103, 119, 130, 137, 139, 141, 142, + 142, 141, 139, 137, 130, 119, 103, 82, 59, 38, 21, 10, 4, 1, 0, 0, + 0, 1, 1, 4, 10, 21, 37, 58, 80, 101, 118, 128, 134, 137, 139, 139, + 139, 139, 137, 134, 128, 117, 102, 80, 58, 37, 21, 10, 4, 1, 0, 0, + 0, 1, 1, 4, 10, 20, 35, 55, 77, 97, 112, 122, 128, 130, 132, 133, + 133, 132, 130, 128, 122, 112, 97, 77, 55, 35, 20, 10, 4, 1, 1, 0, + 0, 1, 1, 4, 9, 19, 32, 51, 70, 88, 103, 112, 117, 120, 121, 121, + 121, 121, 120, 117, 112, 103, 88, 70, 51, 32, 19, 9, 4, 1, 1, 0, + 0, 0, 1, 3, 7, 16, 28, 43, 61, 76, 88, 97, 102, 103, 104, 104, + 104, 104, 103, 102, 97, 88, 76, 61, 43, 28, 16, 7, 3, 1, 0, 0, + 0, 0, 1, 3, 6, 13, 22, 34, 48, 61, 70, 77, 80, 82, 83, 84, + 84, 83, 82, 80, 77, 70, 61, 48, 34, 22, 13, 6, 3, 1, 0, 0, + 0, 0, 1, 1, 4, 9, 16, 25, 34, 43, 50, 55, 58, 59, 60, 60, + 60, 60, 59, 58, 55, 50, 43, 34, 25, 16, 9, 4, 1, 1, 0, 0, + 0, 0, 1, 1, 3, 5, 10, 16, 22, 28, 32, 35, 37, 37, 38, 38, + 38, 38, 37, 37, 35, 32, 28, 22, 16, 10, 5, 3, 1, 1, 0, 0, + 0, 0, 0, 1, 1, 3, 5, 9, 13, 16, 19, 19, 21, 21, 22, 22, + 22, 22, 21, 21, 19, 19, 16, 13, 9, 5, 3, 1, 1, 0, 0, 0, + 0, 0, 0, 0, 1, 1, 3, 4, 6, 7, 9, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 9, 7, 6, 4, 3, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 1, 1, 1, 3, 3, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 3, 3, 1, 1, 1, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 1, 1, 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 +}; + +GLuint +init_drop_shadow(void) +{ + GLuint t; + + glGenTextures (1, &t); + if (t <= 0) abort(); + + glBindTexture (GL_TEXTURE_2D, t); +#if 0 + glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR); + gluBuild2DMipmaps (GL_TEXTURE_2D, GL_ALPHA, + drop_shadow_width, drop_shadow_height, + GL_ALPHA, GL_UNSIGNED_BYTE, + drop_shadow_data); +#else + glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexImage2D (GL_TEXTURE_2D, 0, GL_ALPHA, + drop_shadow_width, drop_shadow_height, 0, + GL_ALPHA, GL_UNSIGNED_BYTE, + drop_shadow_data); +#endif + + return t; +} + +void +draw_drop_shadow (GLuint t, + GLfloat x, GLfloat y, GLfloat z, GLfloat w, GLfloat h, + GLfloat r) +{ + /* Inner and outer boundaries of shadow. */ + const GLfloat li = x, lo = li - r; + const GLfloat ri = x + w, ro = ri + r; + const GLfloat bi = y, bo = bi - r; + const GLfloat ti = y + h, to = ti + r; + + glEnable (GL_BLEND); + glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + + glEnable (GL_TEXTURE_2D); + glBindTexture (GL_TEXTURE_2D, t); + + glBegin (GL_QUADS); + + /* There's likely a better way to do this... */ + glTexCoord2f (0.0, 0.0); glVertex3f (lo, bo, z); + glTexCoord2f (0.5, 0.0); glVertex3f (li, bo, z); + glTexCoord2f (0.5, 0.5); glVertex3f (li, bi, z); + glTexCoord2f (0.0, 0.5); glVertex3f (lo, bi, z); + + glTexCoord2f (0.5, 0.0); glVertex3f (li, bo, z); + glTexCoord2f (0.5, 0.0); glVertex3f (ri, bo, z); + glTexCoord2f (0.5, 0.5); glVertex3f (ri, bi, z); + glTexCoord2f (0.5, 0.5); glVertex3f (li, bi, z); + + glTexCoord2f (0.5, 0.0); glVertex3f (ri, bo, z); + glTexCoord2f (1.0, 0.0); glVertex3f (ro, bo, z); + glTexCoord2f (1.0, 0.5); glVertex3f (ro, bi, z); + glTexCoord2f (0.5, 0.5); glVertex3f (ri, bi, z); + + glTexCoord2f (0.5, 0.5); glVertex3f (ri, bi, z); + glTexCoord2f (1.0, 0.5); glVertex3f (ro, bi, z); + glTexCoord2f (1.0, 0.5); glVertex3f (ro, ti, z); + glTexCoord2f (0.5, 0.5); glVertex3f (ri, ti, z); + + glTexCoord2f (0.5, 0.5); glVertex3f (ri, ti, z); + glTexCoord2f (1.0, 0.5); glVertex3f (ro, ti, z); + glTexCoord2f (1.0, 1.0); glVertex3f (ro, to, z); + glTexCoord2f (0.5, 1.0); glVertex3f (ri, to, z); + + glTexCoord2f (0.5, 0.5); glVertex3f (li, ti, z); + glTexCoord2f (0.5, 0.5); glVertex3f (ri, ti, z); + glTexCoord2f (0.5, 1.0); glVertex3f (ri, to, z); + glTexCoord2f (0.5, 1.0); glVertex3f (li, to, z); + + glTexCoord2f (0.0, 0.5); glVertex3f (lo, ti, z); + glTexCoord2f (0.5, 0.5); glVertex3f (li, ti, z); + glTexCoord2f (0.5, 1.0); glVertex3f (li, to, z); + glTexCoord2f (0.0, 1.0); glVertex3f (lo, to, z); + + glTexCoord2f (0.0, 0.5); glVertex3f (lo, bi, z); + glTexCoord2f (0.5, 0.5); glVertex3f (li, bi, z); + glTexCoord2f (0.5, 0.5); glVertex3f (li, ti, z); + glTexCoord2f (0.0, 0.5); glVertex3f (lo, ti, z); + + glEnd(); +} diff --git a/hacks/glx/dropshadow.h b/hacks/glx/dropshadow.h new file mode 100644 index 00000000..212a0c65 --- /dev/null +++ b/hacks/glx/dropshadow.h @@ -0,0 +1,51 @@ +/* dropshadow.h, Copyright (c) 2009 Jens Kilian + * + * 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. + */ + +#ifndef __DROPSHADOW_H__ +#define __DROPSHADOW_H__ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif /* HAVE_CONFIG_H */ + +#ifdef HAVE_COCOA +# ifndef HAVE_JWZGLES +# include +# endif +#else /* !HAVE_COCOA */ +# include +# include +#endif /* !HAVE_COCOA */ + +#ifdef HAVE_JWZGLES +# include "jwzgles.h" +#endif /* HAVE_JWZGLES */ + +/* Initialize drop shadow texture, return a texture ID. + */ +GLuint +init_drop_shadow(void); + +/* Draw a drop shadow around a rectangle. + + t Texture ID (as returned by init_drop_shadow()). + x, y, z; w, h Position (left bottom), depth and size of rectangle. + r Radius of drop shadow. + + The shadow will be drawn using the current color. + */ + +void +draw_drop_shadow (GLuint t, + GLfloat x, GLfloat y, GLfloat z, GLfloat w, GLfloat h, + GLfloat r); + +#endif /* __DROPSHADOW_H__ */ diff --git a/hacks/glx/dxf2gl.pl b/hacks/glx/dxf2gl.pl new file mode 100755 index 00000000..b2d334bd --- /dev/null +++ b/hacks/glx/dxf2gl.pl @@ -0,0 +1,501 @@ +#!/usr/bin/perl -w +# Copyright © 2003 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. +# +# Reads a DXF file, and emits C data suitable for use with OpenGL's +# glInterleavedArrays() and glDrawArrays() routines. +# +# Options: +# +# --normalize Compute the bounding box of the object, and scale all +# coordinates so that the object fits inside a unit cube. +# +# --smooth When computing normals for the vertexes, average the +# normals at any edge which is less than 90 degrees. +# If this option is not specified, planar normals will be +# used, resulting in a "faceted" object. +# +# Created: 8-Mar-2003. + +require 5; +use diagnostics; +use strict; + +my $progname = $0; $progname =~ s@.*/@@g; +my $version = q{ $Revision: 1.2 $ }; $version =~ s/^[^0-9]+([0-9.]+).*$/$1/; + +my $verbose = 0; + + +# convert a vector to a unit vector +sub normalize { + my ($x, $y, $z) = @_; + my $L = sqrt (($x * $x) + ($y * $y) + ($z * $z)); + if ($L != 0) { + $x /= $L; + $y /= $L; + $z /= $L; + } else { + $x = $y = $z = 0; + } + return ($x, $y, $z); +} + + +# Calculate the unit normal at p0 given two other points p1,p2 on the +# surface. The normal points in the direction of p1 crossproduct p2. +# +sub face_normal { + my ($p0x, $p0y, $p0z, + $p1x, $p1y, $p1z, + $p2x, $p2y, $p2z) = @_; + + my ($nx, $ny, $nz); + my ($pax, $pay, $paz); + my ($pbx, $pby, $pbz); + + $pax = $p1x - $p0x; + $pay = $p1y - $p0y; + $paz = $p1z - $p0z; + $pbx = $p2x - $p0x; + $pby = $p2y - $p0y; + $pbz = $p2z - $p0z; + $nx = $pay * $pbz - $paz * $pby; + $ny = $paz * $pbx - $pax * $pbz; + $nz = $pax * $pby - $pay * $pbx; + + return (normalize ($nx, $ny, $nz)); +} + + +# why this isn't in perlfunc, I don't know. +sub acos { atan2( sqrt(1 - $_[0] * $_[0]), $_[0] ) } +my $pi = 3.141592653589793; +my $radians_to_degrees = 180.0 / $pi; + +# Calculate the angle (in degrees) between two vectors. +# +sub vector_angle { + my ($x1, $y1, $z1, + $x2, $y2, $z2) = @_; + + my $L1 = sqrt ($x1*$x1 + $y1*$y1 + $z1*$z1); + my $L2 = sqrt ($x2*$x2 + $y2*$y2 + $z2*$z2); + + return 0 if ($L1 == 0 || $L2 == 0); + return 0 if ($x1 == $x2 && $y1 == $y2 && $z1 == $z2); + + # dot product of two vectors is defined as: + # $L1 * $L1 * cos(angle between vectors) + # and is also defined as: + # $x1*$x2 + $y1*$y2 + $z1*$z2 + # so: + # $L1 * $L1 * cos($angle) = $x1*$x2 + $y1*$y2 + $z1*$z2 + # cos($angle) = ($x1*$x2 + $y1*$y2 + $z1*$z2) / ($L1 * $L2) + # $angle = acos (($x1*$x2 + $y1*$y2 + $z1*$z2) / ($L1 * $L2)); + # + my $cos = ($x1*$x2 + $y1*$y2 + $z1*$z2) / ($L1 * $L2); + $cos = 1 if ($cos > 1); # avoid fp rounding error (1.000001 => sqrt error) + my $angle = acos ($cos); + + return ($angle * $radians_to_degrees); +} + +# given a list of triangles ( [ X1, Y1, Z1, X2, Y2, Z2, X3, Y3, Z3, ]+ ) +# returns a list of the normals for each vertex. +# +sub compute_vertex_normals { + my (@points) = @_; + my $npoints = ($#points+1) / 3; + my $nfaces = $npoints / 3; + + my @face_normals = (); + my %point_faces; + + for (my $i = 0; $i < $nfaces; $i++) { + my ($ax, $ay, $az, $bx, $by, $bz, $cx, $cy, $cz) = + @points[($i*9) .. ($i*9)+8]; + + # store the normal for each face in the $face_normals array + # indexed by face number. + # + my @norm = face_normal ($ax, $ay, $az, + $bx, $by, $bz, + $cx, $cy, $cz); + $face_normals[$i] = \@norm; + + # store in the %point_faces hash table a list of every face number + # in which a point participates + + my $p; + my @flist; + + $p = "$ax $ay $az"; + @flist = (defined($point_faces{$p}) ? @{$point_faces{$p}} : ()); + push @flist, $i; + $point_faces{$p} = \@flist; + + $p = "$bx $by $bz"; + @flist = (defined($point_faces{$p}) ? @{$point_faces{$p}} : ()); + push @flist, $i; + $point_faces{$p} = \@flist; + + $p = "$cx $cy $cz"; + @flist = (defined($point_faces{$p}) ? @{$point_faces{$p}} : ()); + push @flist, $i; + $point_faces{$p} = \@flist; + } + + + # compute the normal for each vertex of each face. + # (these points are not unique -- because there might be multiple + # normals associated with the same vertex for different faces, + # in the case where it's a sharp angle.) + # + my @normals = (); + for (my $i = 0; $i < $nfaces; $i++) { + my @verts = @points[($i*9) .. ($i*9)+8]; + error ("overshot in points?") unless defined($verts[8]); + + my @norm = @{$face_normals[$i]}; + error ("no normal $i?") unless defined($norm[2]); + + # iterate over the (three) vertexes in this face. + # + for (my $j = 0; $j < 3; $j++) { + my ($x, $y, $z) = @verts[($j*3) .. ($j*3)+2]; + error ("overshot in verts?") unless defined($z); + + # Iterate over the faces in which this point participates. + # This face's normal is the average of the normals of those faces. + # Except, faces are ignored if any point in them is at more than + # a 90 degree angle from the zeroth face (arbitrarily.) + # + my ($nx, $ny, $nz) = (0, 0, 0); + my @faces = @{$point_faces{"$x $y $z"}}; + foreach my $fn (@faces) { + my ($ax, $ay, $az, $bx, $by, $bz, $cx, $cy, $cz) = + @points[($fn*9) .. ($fn*9)+8]; + my @fnorm = @{$face_normals[$fn]}; + + # ignore any adjascent faces that are more than 90 degrees off. + my $angle = vector_angle (@norm, @fnorm); + next if ($angle >= 90); + + $nx += $fnorm[0]; + $ny += $fnorm[1]; + $nz += $fnorm[2]; + } + + push @normals, normalize ($nx, $ny, $nz); + } + } + + return @normals; +} + + + +sub parse_dxf { + my ($filename, $dxf, $normalize_p) = @_; + + $_ = $dxf; + my ($points_txt, $coords_txt); + my $vvers; + + $dxf =~ s/([^\n]*)\n([^\n]*)\n/$1\t$2\n/g; # join even and odd lines + + my @triangles = (); + + my @items = split (/\n/, $dxf); + while ($#items >= 0) { + + $_ = shift @items; + + if (m/^\s* 0 \s+ SECTION \b/x) { + } elsif (m/^\s* 2 \s+ HEADER \b/x) { + } elsif (m/^\s* 0 \s+ ENDSEC \b/x) { + } elsif (m/^\s* 2 \s+ ENTITIES \b/x) { + } elsif (m/^\s* 0 \s+ EOF \b/x) { + } elsif (m/^\s* 0 \s+ 3DFACE \b/x) { + + my @points = (); + my $pc = 0; + + while ($#items >= 0) { + $_ = shift @items; # get next line + + my $d = '(-?\d+\.?\d+)'; + if (m/^\s* 8 \b/x) { # layer name + } elsif (m/^\s* 62 \b/x) { # color number + + } elsif (m/^\s* 10 \s+ $d/xo) { $pc++; $points[ 0] = $1; # X1 + } elsif (m/^\s* 20 \s+ $d/xo) { $pc++; $points[ 1] = $1; # Y1 + } elsif (m/^\s* 30 \s+ $d/xo) { $pc++; $points[ 2] = $1; # Z1 + + } elsif (m/^\s* 11 \s+ $d/xo) { $pc++; $points[ 3] = $1; # X2 + } elsif (m/^\s* 21 \s+ $d/xo) { $pc++; $points[ 4] = $1; # Y2 + } elsif (m/^\s* 31 \s+ $d/xo) { $pc++; $points[ 5] = $1; # Z2 + + } elsif (m/^\s* 12 \s+ $d/xo) { $pc++; $points[ 6] = $1; # X3 + } elsif (m/^\s* 22 \s+ $d/xo) { $pc++; $points[ 7] = $1; # Y3 + } elsif (m/^\s* 32 \s+ $d/xo) { $pc++; $points[ 8] = $1; # Z3 + + } elsif (m/^\s* 13 \s+ $d/xo) { $pc++; $points[ 9] = $1; # X4 + } elsif (m/^\s* 23 \s+ $d/xo) { $pc++; $points[10] = $1; # Y4 + } elsif (m/^\s* 33 \s+ $d/xo) { $pc++; $points[11] = $1; # Z4 + } else { + error ("$filename: unknown 3DFACE entry: $_\n"); + } + + last if ($pc >= 12); + } + + if ($points[6] != $points[9] || + $points[7] != $points[10] || + $points[8] != $points[11]) { + error ("$filename: got a quad, not a triangle\n"); + } else { + @points = @points[0 .. 8]; + } + + foreach (@points) { $_ += 0; } # convert strings to numbers + + push @triangles, @points; + + } else { + error ("$filename: unknown: $_\n"); + } + } + + + my $npoints = ($#triangles+1) / 3; + + + # find bounding box, and normalize + # + if ($normalize_p || $verbose) { + my $minx = 999999999; + my $miny = 999999999; + my $minz = 999999999; + my $maxx = -999999999; + my $maxy = -999999999; + my $maxz = -999999999; + my $i = 0; + foreach my $n (@triangles) { + if ($i == 0) { $minx = $n if ($n < $minx); + $maxx = $n if ($n > $maxx); } + elsif ($i == 1) { $miny = $n if ($n < $miny); + $maxy = $n if ($n > $maxy); } + else { $minz = $n if ($n < $minz); + $maxz = $n if ($n > $maxz); } + $i = 0 if (++$i == 3); + } + + my $w = ($maxx - $minx); + my $h = ($maxy - $miny); + my $d = ($maxz - $minz); + my $sizea = ($w > $h ? $w : $h); + my $sizeb = ($w > $d ? $w : $d); + my $size = ($sizea > $sizeb ? $sizea : $sizeb); + + print STDERR "$progname: $filename: bbox is " . + sprintf("%.2f x %.2f x %.2f\n", $w, $h, $d) + if ($verbose); + + if ($normalize_p) { + $w /= $size; + $h /= $size; + $d /= $size; + print STDERR "$progname: $filename: dividing by $size for bbox of " . + sprintf("%.2f x %.2f x %.2f\n", $w, $h, $d) + if ($verbose); + foreach my $n (@triangles) { + $n /= $size; + } + } + } + + return (@triangles); +} + + +sub generate_c { + my ($filename, $smooth_p, @points) = @_; + + my $ccw_p = 1; # counter-clockwise winding rule for computing normals + + my $code = ''; + + $code .= "#include \"gllist.h\"\n"; + $code .= "static const float data[]={\n"; + + my $npoints = ($#points + 1) / 3; + my $nfaces = $npoints / 3; + + my @normals; + if ($smooth_p) { + @normals = compute_vertex_normals (@points); + + if ($#normals != $#points) { + error ("computed " . (($#normals+1)/3) . " normals for " . + (($#points+1)/3) . " points?"); + } + } + + for (my $i = 0; $i < $nfaces; $i++) { + my $ax = $points[$i*9]; + my $ay = $points[$i*9+1]; + my $az = $points[$i*9+2]; + + my $bx = $points[$i*9+3]; + my $by = $points[$i*9+4]; + my $bz = $points[$i*9+5]; + + my $cx = $points[$i*9+6]; + my $cy = $points[$i*9+7]; + my $cz = $points[$i*9+8]; + + my ($nax, $nay, $naz, + $nbx, $nby, $nbz, + $ncx, $ncy, $ncz); + + if ($smooth_p) { + $nax = $normals[$i*9]; + $nay = $normals[$i*9+1]; + $naz = $normals[$i*9+2]; + + $nbx = $normals[$i*9+3]; + $nby = $normals[$i*9+4]; + $nbz = $normals[$i*9+5]; + + $ncx = $normals[$i*9+6]; + $ncy = $normals[$i*9+7]; + $ncz = $normals[$i*9+8]; + + } else { + if ($ccw_p) { + ($nax, $nay, $naz) = face_normal ($ax, $ay, $az, + $bx, $by, $bz, + $cx, $cy, $cz); + } else { + ($nax, $nay, $naz) = face_normal ($ax, $ay, $az, + $cx, $cy, $cz, + $bx, $by, $bz); + } + ($nbx, $nby, $nbz) = ($nax, $nay, $naz); + ($ncx, $ncy, $ncz) = ($nax, $nay, $naz); + } + + my $lines = sprintf("\t" . "%.6f,%.6f,%.6f," . "%.6f,%.6f,%.6f,\n" . + "\t" . "%.6f,%.6f,%.6f," . "%.6f,%.6f,%.6f,\n" . + "\t" . "%.6f,%.6f,%.6f," . "%.6f,%.6f,%.6f,\n", + $nax, $nay, $naz, $ax, $ay, $az, + $nbx, $nby, $nbz, $bx, $by, $bz, + $ncx, $ncy, $ncz, $cx, $cy, $cz); + $lines =~ s/([.\d])0+,/$1,/g; # lose trailing insignificant zeroes + $lines =~ s/\.,/,/g; + + $code .= $lines; + } + + my $token = $filename; # guess at a C token from the filename + $token =~ s/\<[^<>]*\>//; + $token =~ s@^.*/@@; + $token =~ s/\.[^.]*$//; + $token =~ s/[^a-z\d]/_/gi; + $token =~ s/__+/_/g; + $token =~ s/^_//g; + $token =~ s/_$//g; + $token =~ tr [A-Z] [a-z]; + $token = 'foo' if ($token eq ''); + + my $format = 'GL_N3F_V3F'; + my $primitive = 'GL_TRIANGLES'; + + $code =~ s/,\n$//s; + $code .= "\n};\n"; + $code .= "static const struct gllist frame={"; + $code .= "$format,$primitive,$npoints,data,NULL};\n"; + $code .= "const struct gllist *$token=&frame;\n"; + + print STDERR "$progname: $filename: " . + (($#points+1)/3) . " points, " . + (($#points+1)/9) . " faces.\n" + if ($verbose); + + return $code; +} + + +sub dxf_to_gl { + my ($infile, $outfile, $smooth_p, $normalize_p) = @_; + local *IN; + my $dxf = ''; + open (IN, "<$infile") || error ("$infile: $!"); + my $filename = ($infile eq '-' ? "" : $infile); + print STDERR "$progname: reading $filename...\n" + if ($verbose); + while () { $dxf .= $_; } + close IN; + + $dxf =~ s/\r\n/\n/g; # CRLF -> LF + $dxf =~ s/\r/\n/g; # CR -> LF + + my @data = parse_dxf ($filename, $dxf, $normalize_p); + + $filename = ($outfile eq '-' ? "" : $outfile); + my $code = generate_c ($filename, $smooth_p, @data); + + local *OUT; + open (OUT, ">$outfile") || error ("$outfile: $!"); + print OUT $code || error ("$filename: $!"); + close OUT || error ("$filename: $!"); + + print STDERR "$progname: wrote $filename\n" + if ($verbose || $outfile ne '-'); +} + + +sub error { + ($_) = @_; + print STDERR "$progname: $_\n"; + exit 1; +} + +sub usage { + print STDERR "usage: $progname [--verbose] [--smooth] [infile [outfile]]\n"; + exit 1; +} + +sub main { + my ($infile, $outfile); + my $normalize_p = 0; + my $smooth_p = 0; + while ($_ = $ARGV[0]) { + shift @ARGV; + if ($_ eq "--verbose") { $verbose++; } + elsif (m/^-v+$/) { $verbose += length($_)-1; } + elsif ($_ eq "--normalize") { $normalize_p = 1; } + elsif ($_ eq "--smooth") { $smooth_p = 1; } + elsif (m/^-./) { usage; } + elsif (!defined($infile)) { $infile = $_; } + elsif (!defined($outfile)) { $outfile = $_; } + else { usage; } + } + + $infile = "-" unless defined ($infile); + $outfile = "-" unless defined ($outfile); + + dxf_to_gl ($infile, $outfile, $smooth_p, $normalize_p); +} + +main; +exit 0; diff --git a/hacks/glx/e_textures.h b/hacks/glx/e_textures.h new file mode 100644 index 00000000..7f9457e3 --- /dev/null +++ b/hacks/glx/e_textures.h @@ -0,0 +1,1478 @@ +static unsigned char WoodTextureWidth = 199; +static unsigned char WoodTextureHeight = 37; +static unsigned char WoodTextureData[] = +{ + 84, 30, 12, 84, 26, 12, 108, 42, 28, 100, 38, 28, 108, 42, 28, + 108, 46, 28, 100, 38, 28, 108, 46, 28, 108, 42, 28, 108, 42, 20, + 108, 42, 28, 108, 38, 20, 108, 42, 20, 108, 42, 28, 116, 42, 28, + 108, 42, 20, 108, 46, 28, 100, 34, 12, 108, 42, 20, 108, 42, 20, + 108, 42, 20, 108, 38, 20, 100, 38, 20, 100, 38, 20, 108, 42, 20, + 108, 42, 20, 108, 38, 20, 100, 38, 20, 108, 38, 20, 100, 38, 20, + 108, 42, 20, 108, 42, 20, 108, 42, 28, 108, 42, 20, 108, 42, 20, + 100, 38, 20, 100, 38, 20, 100, 38, 20, 108, 38, 20, 116, 50, 28, + 108, 42, 28, 108, 42, 20, 100, 38, 20, 108, 42, 20, 108, 42, 20, + 108, 46, 28, 108, 42, 20, 108, 42, 20, 108, 42, 20, 100, 38, 20, + 108, 38, 20, 100, 38, 20, 108, 38, 20, 100, 38, 20, 100, 38, 20, + 108, 38, 20, 100, 38, 20, 108, 38, 20, 100, 42, 20, 108, 42, 20, + 108, 42, 28, 108, 42, 20, 100, 38, 20, 108, 42, 20, 100, 38, 20, + 100, 34, 12, 100, 38, 20, 108, 38, 20, 100, 38, 20, 108, 42, 20, + 108, 42, 20, 108, 42, 20, 100, 38, 20, 108, 38, 20, 100, 38, 20, + 100, 34, 12, 100, 38, 20, 108, 38, 20, 100, 38, 20, 108, 42, 20, + 100, 38, 20, 100, 34, 12, 100, 34, 12, 100, 38, 20, 108, 38, 20, + 100, 38, 20, 108, 38, 20, 108, 42, 20, 100, 38, 20, 108, 42, 20, + 108, 42, 28, 108, 46, 20, 108, 38, 20, 108, 42, 20, 108, 46, 28, + 108, 46, 28, 108, 42, 20, 108, 42, 20, 108, 42, 20, 100, 38, 20, + 108, 42, 20, 100, 38, 20, 108, 38, 20, 100, 38, 20, 108, 38, 20, + 108, 42, 20, 108, 46, 28, 116, 50, 28, 116, 54, 36, 116, 54, 36, + 116, 54, 28, 108, 46, 28, 108, 42, 20, 108, 42, 28, 108, 42, 20, + 108, 42, 20, 108, 46, 28, 116, 50, 28, 116, 50, 28, 116, 50, 28, + 116, 46, 28, 108, 42, 28, 116, 50, 36, 116, 50, 36, 100, 38, 20, + 108, 42, 28, 108, 38, 20, 100, 38, 20, 108, 38, 20, 108, 42, 28, + 108, 46, 28, 116, 46, 28, 108, 42, 28, 108, 42, 28, 108, 42, 20, + 108, 46, 28, 116, 50, 28, 116, 50, 28, 116, 50, 28, 116, 50, 28, + 108, 42, 28, 108, 42, 20, 100, 38, 20, 116, 50, 28, 108, 46, 28, + 108, 42, 20, 108, 42, 20, 108, 46, 28, 116, 46, 28, 108, 46, 28, + 108, 46, 28, 108, 46, 20, 108, 46, 28, 116, 46, 28, 108, 46, 28, + 116, 50, 28, 108, 46, 28, 108, 46, 28, 108, 42, 20, 116, 46, 28, + 108, 46, 28, 108, 42, 20, 108, 42, 28, 108, 46, 28, 116, 50, 28, + 116, 50, 28, 116, 50, 36, 124, 54, 36, 116, 54, 36, 116, 54, 28, + 116, 50, 28, 116, 50, 28, 108, 46, 28, 116, 46, 28, 108, 46, 28, + 116, 50, 28, 116, 46, 28, 116, 50, 28, 116, 50, 28, 116, 50, 28, + 116, 50, 28, 108, 46, 28, 108, 46, 20, 124, 50, 36, 116, 54, 28, + 124, 54, 28, 116, 54, 28, 116, 54, 28, 116, 54, 28, 124, 54, 36, + 124, 58, 36, 124, 50, 36, 116, 46, 28, 116, 46, 28, 116, 42, 28, + 116, 50, 36, 124, 66, 44, 108, 58, 36, 84, 30, 12, 100, 42, 20, + 116, 54, 36, 140, 82, 68, 148, 86, 68, 148, 86, 68, 156, 90, 76, + 148, 86, 68, 156, 86, 76, 156, 86, 68, 148, 86, 68, 156, 86, 68, + 156, 86, 68, 156, 86, 68, 156, 86, 68, 156, 90, 68, 156, 86, 68, + 156, 90, 68, 164, 94, 76, 164, 98, 84, 164, 102, 84, 164, 102, 84, + 164, 98, 76, 156, 94, 68, 164, 94, 76, 156, 94, 76, 164, 98, 84, + 164, 98, 76, 164, 98, 76, 156, 94, 76, 164, 98, 76, 164, 98, 76, + 164, 102, 84, 164, 102, 84, 172, 106, 84, 172, 106, 84, 164, 98, 76, + 164, 94, 68, 164, 94, 68, 164, 98, 76, 172, 106, 84, 164, 98, 76, + 164, 98, 76, 164, 94, 68, 164, 94, 76, 164, 98, 76, 164, 98, 76, + 164, 98, 76, 164, 102, 84, 172, 102, 84, 172, 106, 84, 172, 106, 84, + 172, 106, 84, 172, 106, 76, 164, 98, 76, 164, 98, 76, 164, 98, 76, + 164, 98, 76, 164, 94, 68, 164, 98, 76, 164, 98, 76, 164, 102, 76, + 164, 94, 76, 156, 94, 68, 172, 102, 84, 172, 106, 84, 172, 102, 84, + 164, 98, 76, 164, 102, 76, 172, 102, 84, 172, 106, 84, 172, 106, 84, + 172, 106, 84, 172, 102, 84, 164, 102, 76, 164, 98, 76, 164, 98, 76, + 164, 98, 76, 164, 98, 76, 164, 98, 76, 172, 102, 76, 164, 98, 76, + 164, 94, 76, 156, 94, 68, 164, 98, 76, 164, 102, 76, 164, 98, 76, + 164, 98, 76, 164, 94, 76, 156, 94, 68, 164, 94, 76, 164, 102, 76, + 172, 106, 84, 164, 98, 76, 164, 98, 76, 164, 98, 76, 164, 98, 76, + 164, 98, 76, 164, 98, 76, 164, 98, 76, 164, 102, 76, 172, 102, 84, + 172, 106, 84, 172, 110, 84, 180, 110, 92, 172, 110, 84, 172, 110, 84, + 180, 114, 92, 188, 122, 100, 188, 122, 100, 188, 122, 100, 188, 118, 92, + 180, 110, 92, 172, 106, 84, 172, 106, 84, 172, 106, 84, 180, 114, 92, + 188, 118, 100, 188, 118, 100, 180, 118, 100, 188, 122, 108, 188, 126, 108, + 188, 118, 100, 196, 130, 108, 204, 134, 116, 188, 126, 108, 196, 122, 108, + 180, 118, 100, 180, 110, 92, 180, 114, 100, 180, 118, 100, 188, 118, 100, + 188, 122, 108, 188, 118, 100, 188, 118, 100, 180, 118, 100, 188, 118, 100, + 180, 118, 100, 180, 118, 100, 180, 118, 100, 180, 114, 92, 180, 114, 92, + 172, 110, 92, 172, 106, 84, 180, 114, 92, 172, 106, 92, 172, 102, 84, + 172, 106, 84, 172, 110, 92, 180, 110, 84, 172, 110, 92, 172, 106, 84, + 172, 102, 84, 172, 102, 84, 172, 106, 84, 172, 106, 84, 172, 106, 84, + 172, 106, 84, 172, 106, 84, 172, 106, 84, 172, 106, 84, 172, 102, 84, + 164, 102, 84, 164, 102, 76, 172, 106, 84, 172, 110, 92, 180, 110, 92, + 172, 110, 84, 172, 114, 92, 180, 114, 92, 180, 110, 92, 172, 110, 92, + 172, 106, 92, 172, 106, 84, 172, 106, 84, 164, 102, 84, 180, 114, 100, + 180, 114, 92, 180, 118, 100, 180, 118, 100, 180, 114, 92, 172, 110, 92, + 172, 106, 84, 172, 106, 84, 180, 110, 92, 180, 114, 92, 180, 114, 92, + 172, 110, 92, 172, 110, 84, 172, 110, 92, 180, 114, 92, 180, 118, 100, + 196, 126, 100, 196, 122, 108, 196, 126, 108, 196, 130, 116, 196, 134, 116, + 204, 142, 124, 164, 106, 84, 100, 42, 20, 84, 26, 4, 132, 78, 68, + 188, 122, 108, 188, 122, 108, 188, 126, 116, 196, 134, 116, 188, 122, 108, + 188, 126, 108, 188, 126, 108, 188, 122, 108, 196, 126, 108, 196, 130, 108, + 188, 126, 108, 188, 122, 100, 196, 126, 108, 196, 126, 108, 188, 126, 108, + 196, 130, 108, 196, 130, 108, 196, 134, 116, 196, 130, 108, 196, 130, 108, + 188, 126, 108, 196, 126, 108, 188, 126, 108, 196, 130, 108, 188, 126, 108, + 188, 126, 108, 196, 126, 108, 188, 126, 108, 196, 130, 108, 196, 130, 108, + 196, 134, 116, 204, 142, 116, 204, 134, 116, 196, 130, 108, 196, 130, 108, + 188, 126, 108, 196, 126, 100, 196, 134, 108, 196, 130, 108, 188, 126, 100, + 188, 122, 100, 188, 126, 108, 196, 126, 100, 188, 126, 108, 196, 126, 100, + 188, 126, 100, 196, 130, 108, 204, 134, 108, 196, 134, 116, 196, 134, 108, + 196, 130, 108, 196, 126, 108, 196, 130, 108, 196, 130, 108, 196, 130, 108, + 188, 126, 108, 196, 126, 108, 196, 134, 108, 196, 130, 108, 196, 130, 108, + 188, 122, 100, 196, 130, 108, 196, 130, 108, 196, 134, 108, 196, 130, 108, + 188, 126, 100, 196, 130, 108, 196, 134, 108, 204, 134, 116, 204, 138, 116, + 204, 138, 116, 204, 134, 116, 196, 130, 108, 196, 130, 108, 196, 134, 108, + 204, 134, 116, 196, 134, 116, 196, 134, 108, 196, 130, 108, 196, 130, 108, + 204, 134, 116, 204, 138, 116, 204, 138, 116, 196, 130, 108, 196, 130, 108, + 188, 122, 100, 180, 118, 92, 188, 118, 100, 196, 130, 108, 196, 130, 108, + 188, 126, 100, 188, 122, 100, 188, 122, 100, 204, 134, 108, 196, 134, 116, + 204, 134, 116, 196, 134, 108, 196, 130, 108, 204, 134, 108, 204, 138, 116, + 204, 138, 116, 212, 142, 124, 204, 142, 116, 204, 134, 116, 204, 138, 116, + 204, 138, 116, 204, 138, 116, 204, 134, 108, 188, 126, 108, 196, 130, 108, + 196, 126, 100, 188, 122, 100, 196, 130, 108, 204, 138, 116, 212, 146, 124, + 204, 142, 116, 204, 138, 116, 212, 146, 124, 212, 142, 124, 204, 138, 124, + 204, 138, 124, 204, 138, 124, 204, 138, 116, 212, 142, 124, 204, 138, 124, + 196, 130, 116, 204, 134, 116, 204, 138, 116, 204, 138, 124, 204, 138, 116, + 204, 138, 124, 204, 134, 116, 204, 138, 124, 212, 142, 124, 204, 138, 116, + 196, 134, 116, 196, 130, 108, 196, 134, 116, 204, 138, 116, 204, 142, 124, + 212, 142, 124, 204, 138, 116, 204, 138, 116, 204, 138, 116, 204, 138, 116, + 204, 138, 124, 204, 142, 124, 204, 142, 116, 204, 138, 124, 196, 134, 108, + 196, 134, 116, 196, 134, 116, 196, 130, 116, 196, 130, 108, 188, 126, 108, + 196, 126, 108, 188, 130, 108, 188, 126, 108, 188, 122, 100, 180, 118, 100, + 188, 118, 100, 188, 126, 108, 196, 130, 108, 196, 126, 108, 188, 126, 108, + 188, 122, 100, 188, 122, 108, 188, 126, 108, 196, 126, 108, 196, 130, 108, + 188, 126, 108, 196, 126, 108, 188, 126, 108, 196, 134, 108, 196, 134, 116, + 196, 134, 108, 196, 130, 108, 196, 126, 108, 188, 122, 108, 188, 122, 100, + 188, 122, 100, 196, 130, 108, 196, 130, 100, 196, 130, 108, 196, 130, 100, + 188, 130, 108, 196, 130, 108, 196, 134, 108, 204, 138, 116, 204, 130, 108, + 204, 134, 116, 204, 134, 116, 204, 134, 116, 204, 138, 124, 204, 146, 124, + 156, 102, 84, 84, 26, 4, 84, 26, 4, 116, 58, 36, 164, 106, 92, + 164, 102, 84, 164, 106, 92, 172, 110, 92, 156, 98, 84, 172, 102, 84, + 172, 102, 84, 180, 110, 92, 180, 118, 100, 180, 118, 100, 180, 110, 92, + 180, 110, 92, 180, 114, 92, 180, 114, 92, 180, 114, 92, 172, 106, 92, + 172, 106, 84, 172, 106, 84, 172, 106, 92, 172, 110, 92, 172, 110, 92, + 172, 106, 84, 172, 106, 84, 164, 102, 84, 164, 102, 84, 172, 102, 76, + 164, 102, 84, 172, 106, 84, 172, 106, 84, 172, 110, 92, 172, 110, 84, + 180, 110, 92, 172, 110, 84, 180, 110, 92, 172, 110, 84, 172, 106, 84, + 172, 110, 84, 180, 110, 92, 172, 106, 84, 172, 102, 84, 164, 102, 84, + 172, 102, 76, 172, 102, 84, 172, 102, 84, 164, 102, 76, 164, 94, 76, + 172, 102, 84, 172, 110, 92, 172, 110, 84, 172, 102, 84, 164, 98, 76, + 172, 102, 76, 172, 106, 84, 172, 110, 84, 172, 106, 84, 172, 106, 84, + 172, 106, 84, 180, 114, 92, 180, 114, 92, 172, 110, 84, 172, 106, 84, + 172, 102, 76, 172, 110, 84, 172, 110, 84, 172, 102, 84, 172, 102, 84, + 172, 106, 84, 180, 110, 92, 172, 110, 84, 180, 118, 92, 180, 114, 92, + 180, 110, 92, 172, 110, 84, 180, 110, 92, 180, 114, 92, 180, 118, 92, + 188, 122, 100, 188, 118, 100, 180, 114, 92, 180, 118, 92, 180, 114, 92, + 180, 118, 92, 188, 118, 100, 180, 118, 92, 180, 114, 92, 180, 118, 92, + 180, 110, 84, 180, 110, 92, 180, 118, 92, 188, 122, 100, 188, 114, 100, + 180, 114, 92, 180, 114, 92, 196, 126, 108, 188, 126, 100, 188, 122, 100, + 188, 118, 100, 180, 118, 100, 180, 114, 92, 188, 118, 100, 188, 122, 100, + 180, 110, 92, 172, 110, 84, 180, 110, 92, 180, 114, 92, 188, 122, 100, + 188, 126, 100, 188, 118, 100, 180, 114, 92, 172, 110, 84, 172, 110, 92, + 180, 114, 92, 180, 114, 92, 180, 118, 92, 188, 118, 100, 188, 122, 100, + 188, 122, 100, 180, 106, 92, 172, 110, 92, 172, 102, 84, 172, 102, 84, + 164, 94, 76, 164, 94, 76, 164, 98, 76, 164, 102, 84, 172, 102, 84, + 172, 106, 84, 180, 110, 92, 180, 110, 92, 180, 110, 92, 172, 106, 92, + 172, 106, 84, 172, 106, 92, 172, 110, 84, 164, 102, 84, 164, 98, 76, + 164, 94, 76, 164, 98, 76, 172, 110, 92, 180, 114, 92, 180, 118, 100, + 180, 118, 100, 188, 122, 100, 180, 122, 108, 188, 122, 100, 188, 122, 100, + 188, 122, 100, 188, 122, 100, 188, 126, 108, 188, 122, 100, 188, 126, 108, + 188, 122, 100, 188, 122, 100, 180, 118, 100, 180, 114, 92, 180, 114, 92, + 180, 118, 100, 180, 110, 92, 172, 110, 92, 172, 106, 84, 180, 110, 92, + 180, 118, 92, 180, 118, 100, 180, 114, 92, 180, 110, 92, 172, 110, 84, + 172, 110, 92, 180, 114, 92, 180, 114, 92, 180, 118, 92, 180, 118, 92, + 180, 114, 92, 180, 118, 92, 180, 110, 92, 180, 110, 92, 180, 114, 92, + 172, 110, 92, 172, 106, 84, 172, 106, 84, 172, 106, 92, 172, 110, 84, + 180, 110, 92, 180, 114, 92, 180, 118, 92, 180, 118, 92, 180, 118, 92, + 180, 118, 92, 188, 118, 100, 188, 122, 100, 180, 114, 100, 180, 110, 92, + 188, 114, 100, 180, 110, 92, 172, 110, 92, 180, 126, 108, 148, 98, 76, + 84, 26, 4, 84, 26, 12, 108, 50, 36, 164, 102, 84, 164, 98, 84, + 156, 94, 76, 164, 98, 84, 148, 86, 68, 156, 90, 76, 156, 94, 84, + 164, 90, 76, 164, 98, 84, 172, 102, 84, 164, 94, 76, 156, 90, 68, + 164, 94, 76, 164, 98, 84, 164, 94, 76, 164, 98, 76, 164, 98, 84, + 164, 98, 76, 172, 102, 84, 172, 106, 84, 172, 106, 84, 172, 106, 84, + 164, 102, 84, 164, 94, 68, 164, 94, 76, 156, 98, 76, 164, 98, 76, + 164, 98, 76, 164, 98, 84, 164, 102, 84, 172, 102, 84, 164, 98, 76, + 164, 98, 76, 172, 102, 84, 172, 106, 84, 172, 106, 84, 180, 106, 84, + 172, 110, 84, 172, 106, 84, 164, 102, 76, 164, 98, 76, 164, 98, 76, + 164, 102, 76, 164, 102, 76, 164, 98, 76, 164, 98, 76, 172, 106, 84, + 180, 110, 84, 172, 106, 84, 164, 98, 76, 164, 98, 76, 172, 106, 84, + 180, 114, 92, 172, 106, 84, 164, 102, 76, 164, 98, 76, 172, 106, 84, + 180, 110, 92, 180, 114, 92, 180, 110, 92, 172, 106, 84, 172, 106, 84, + 180, 114, 92, 188, 118, 100, 180, 114, 92, 172, 110, 84, 180, 114, 92, + 180, 114, 92, 180, 114, 92, 172, 110, 92, 172, 106, 84, 164, 102, 76, + 172, 102, 76, 164, 102, 84, 180, 110, 84, 180, 118, 92, 188, 118, 100, + 188, 122, 100, 180, 118, 92, 180, 110, 92, 180, 110, 84, 172, 106, 92, + 180, 114, 84, 180, 114, 100, 188, 122, 100, 188, 122, 100, 180, 114, 92, + 172, 110, 92, 180, 114, 92, 188, 118, 92, 180, 114, 92, 180, 114, 92, + 180, 118, 92, 164, 102, 84, 172, 102, 84, 172, 106, 84, 172, 102, 76, + 164, 102, 76, 172, 102, 84, 172, 110, 84, 180, 114, 92, 172, 110, 84, + 172, 102, 84, 172, 106, 84, 180, 110, 84, 180, 118, 100, 188, 118, 92, + 180, 110, 92, 172, 106, 84, 172, 106, 84, 180, 110, 92, 188, 118, 92, + 180, 118, 100, 180, 114, 92, 180, 114, 92, 180, 114, 92, 180, 118, 100, + 180, 114, 92, 188, 122, 100, 188, 126, 108, 188, 118, 100, 172, 110, 92, + 172, 102, 84, 172, 106, 84, 180, 106, 92, 164, 98, 76, 172, 102, 84, + 172, 106, 92, 172, 106, 84, 172, 106, 84, 172, 102, 84, 172, 102, 84, + 172, 102, 84, 172, 106, 84, 164, 102, 84, 164, 98, 76, 164, 98, 76, + 172, 106, 84, 172, 110, 92, 180, 114, 92, 180, 114, 92, 180, 118, 100, + 188, 122, 100, 188, 122, 100, 188, 126, 108, 188, 122, 100, 188, 122, 100, + 188, 122, 108, 196, 126, 108, 180, 118, 92, 188, 118, 100, 180, 118, 100, + 180, 118, 100, 180, 114, 92, 180, 110, 92, 180, 114, 92, 180, 118, 100, + 180, 110, 92, 172, 110, 84, 172, 106, 92, 172, 110, 92, 188, 118, 100, + 180, 118, 100, 180, 114, 92, 172, 106, 84, 180, 110, 92, 180, 114, 92, + 172, 110, 92, 180, 114, 92, 180, 114, 100, 180, 114, 92, 172, 110, 92, + 172, 110, 92, 180, 114, 92, 180, 114, 92, 180, 114, 100, 180, 110, 92, + 172, 110, 92, 172, 110, 92, 180, 114, 92, 180, 118, 92, 172, 106, 84, + 180, 110, 84, 180, 118, 92, 188, 122, 100, 180, 118, 100, 180, 118, 92, + 180, 118, 92, 180, 114, 92, 180, 110, 92, 180, 110, 92, 188, 118, 108, + 188, 118, 100, 188, 122, 100, 188, 130, 108, 156, 102, 84, 84, 26, 12, + 84, 30, 12, 108, 46, 28, 140, 82, 68, 156, 90, 76, 156, 94, 84, + 156, 94, 84, 156, 94, 76, 164, 94, 76, 156, 90, 76, 164, 94, 76, + 156, 94, 76, 156, 90, 68, 156, 90, 68, 164, 90, 76, 156, 90, 68, + 148, 82, 60, 148, 78, 60, 164, 98, 76, 164, 94, 76, 156, 90, 68, + 156, 90, 68, 156, 94, 76, 164, 98, 76, 164, 98, 76, 164, 98, 76, + 156, 90, 68, 148, 86, 68, 156, 90, 68, 156, 90, 68, 156, 90, 76, + 164, 94, 68, 156, 94, 76, 156, 94, 68, 156, 90, 68, 156, 90, 68, + 172, 102, 76, 180, 114, 92, 188, 118, 92, 172, 106, 84, 180, 106, 84, + 172, 106, 84, 164, 98, 76, 164, 94, 68, 164, 98, 76, 172, 102, 84, + 172, 106, 84, 172, 102, 76, 164, 98, 76, 172, 106, 84, 180, 110, 92, + 172, 110, 84, 172, 98, 76, 164, 98, 76, 172, 106, 84, 180, 118, 92, + 180, 106, 84, 180, 106, 84, 172, 106, 84, 172, 110, 84, 180, 110, 92, + 180, 110, 84, 172, 102, 76, 164, 98, 76, 164, 94, 68, 172, 106, 84, + 180, 114, 92, 172, 106, 84, 164, 98, 76, 172, 98, 76, 172, 106, 84, + 172, 106, 84, 180, 106, 84, 180, 110, 84, 172, 110, 84, 180, 110, 92, + 180, 110, 84, 180, 110, 92, 180, 110, 84, 172, 106, 84, 188, 118, 92, + 188, 114, 92, 172, 106, 84, 172, 102, 76, 172, 106, 84, 188, 118, 92, + 188, 122, 100, 188, 118, 100, 188, 118, 92, 180, 110, 92, 180, 114, 84, + 180, 114, 92, 180, 110, 92, 172, 106, 84, 164, 98, 76, 172, 102, 76, + 180, 106, 84, 180, 114, 84, 172, 102, 76, 164, 94, 76, 172, 106, 84, + 180, 110, 84, 172, 106, 84, 172, 106, 84, 188, 122, 100, 188, 118, 92, + 180, 118, 92, 188, 118, 100, 196, 122, 100, 188, 122, 100, 180, 118, 92, + 180, 110, 84, 188, 114, 92, 172, 110, 84, 172, 106, 84, 180, 114, 92, + 188, 114, 92, 180, 114, 92, 180, 114, 84, 180, 114, 92, 180, 110, 92, + 180, 110, 92, 180, 110, 92, 172, 106, 84, 164, 98, 76, 172, 110, 92, + 188, 118, 100, 180, 118, 92, 180, 110, 92, 180, 114, 100, 180, 118, 100, + 172, 106, 84, 164, 94, 76, 164, 98, 76, 172, 102, 76, 164, 102, 84, + 164, 102, 84, 172, 102, 84, 172, 106, 84, 172, 106, 84, 172, 106, 84, + 172, 106, 84, 172, 106, 84, 172, 106, 92, 180, 118, 92, 180, 118, 100, + 180, 114, 92, 180, 110, 92, 180, 114, 92, 180, 114, 100, 180, 118, 92, + 180, 118, 100, 188, 122, 108, 188, 122, 100, 188, 118, 100, 180, 114, 92, + 180, 114, 92, 172, 110, 92, 172, 110, 92, 172, 106, 84, 188, 122, 100, + 180, 114, 100, 172, 106, 84, 172, 110, 84, 180, 114, 92, 180, 114, 92, + 180, 110, 92, 172, 110, 92, 172, 106, 84, 172, 110, 92, 180, 114, 92, + 180, 118, 100, 180, 114, 92, 172, 110, 92, 172, 110, 92, 180, 110, 92, + 164, 106, 84, 172, 106, 84, 172, 110, 84, 172, 110, 92, 172, 110, 92, + 180, 110, 84, 172, 110, 92, 172, 110, 84, 180, 110, 92, 180, 110, 92, + 180, 114, 92, 180, 118, 92, 180, 118, 92, 180, 118, 100, 188, 118, 92, + 188, 118, 100, 180, 110, 92, 180, 110, 92, 188, 118, 100, 188, 118, 100, + 180, 118, 100, 180, 122, 108, 148, 90, 68, 84, 30, 12, 92, 34, 12, + 116, 58, 44, 156, 90, 76, 156, 94, 76, 156, 94, 76, 156, 90, 76, + 148, 86, 68, 156, 90, 76, 148, 86, 68, 156, 86, 68, 156, 86, 68, + 156, 90, 68, 156, 90, 76, 156, 90, 68, 156, 86, 68, 148, 78, 60, + 140, 74, 52, 148, 82, 68, 148, 82, 60, 148, 86, 68, 156, 90, 68, + 156, 94, 76, 164, 98, 76, 164, 98, 84, 164, 98, 76, 148, 86, 68, + 156, 86, 68, 156, 90, 68, 156, 90, 76, 156, 94, 68, 156, 94, 76, + 164, 94, 76, 164, 98, 76, 172, 102, 76, 164, 98, 76, 172, 102, 76, + 172, 106, 84, 180, 110, 92, 172, 106, 84, 164, 98, 76, 172, 102, 76, + 172, 102, 84, 164, 94, 68, 164, 94, 76, 172, 102, 76, 180, 110, 84, + 180, 110, 92, 164, 98, 76, 172, 102, 76, 172, 106, 84, 172, 102, 76, + 164, 98, 76, 164, 98, 76, 172, 102, 76, 180, 110, 92, 180, 110, 92, + 172, 110, 84, 172, 106, 84, 180, 106, 84, 180, 114, 84, 180, 110, 92, + 172, 102, 84, 164, 98, 76, 156, 94, 68, 172, 106, 84, 188, 114, 92, + 180, 110, 84, 172, 106, 84, 172, 102, 76, 172, 106, 84, 180, 110, 84, + 172, 106, 84, 172, 106, 84, 180, 110, 84, 180, 110, 92, 180, 114, 84, + 172, 110, 84, 172, 106, 84, 172, 106, 84, 164, 98, 76, 164, 98, 76, + 164, 98, 76, 164, 90, 68, 164, 98, 76, 172, 102, 84, 172, 106, 76, + 172, 102, 76, 172, 106, 84, 172, 106, 84, 180, 110, 84, 180, 114, 92, + 188, 114, 92, 180, 110, 84, 180, 110, 92, 180, 114, 92, 172, 106, 84, + 180, 114, 92, 172, 106, 84, 164, 94, 68, 172, 106, 84, 180, 114, 92, + 188, 118, 92, 196, 126, 100, 188, 122, 100, 188, 122, 100, 188, 118, 92, + 180, 118, 92, 188, 118, 100, 188, 118, 92, 180, 114, 92, 172, 106, 84, + 180, 114, 92, 180, 106, 84, 172, 102, 76, 172, 102, 76, 172, 106, 84, + 172, 102, 84, 172, 106, 84, 180, 110, 84, 172, 102, 84, 164, 102, 84, + 172, 102, 84, 164, 94, 76, 156, 90, 68, 164, 94, 76, 180, 106, 92, + 172, 102, 84, 164, 98, 84, 180, 110, 84, 180, 110, 92, 164, 98, 84, + 164, 94, 76, 164, 98, 76, 164, 98, 84, 172, 98, 76, 164, 102, 84, + 164, 102, 84, 172, 102, 84, 164, 106, 84, 172, 106, 92, 172, 106, 92, + 172, 110, 92, 180, 110, 84, 180, 118, 100, 188, 118, 100, 180, 118, 100, + 180, 114, 92, 172, 114, 92, 180, 110, 92, 180, 110, 92, 180, 114, 92, + 180, 118, 100, 180, 118, 92, 180, 114, 100, 180, 114, 92, 180, 110, 92, + 172, 110, 92, 180, 110, 92, 172, 114, 92, 188, 118, 100, 180, 114, 92, + 172, 110, 92, 172, 106, 84, 172, 110, 92, 172, 110, 92, 172, 110, 84, + 164, 102, 84, 172, 102, 84, 172, 110, 92, 180, 114, 92, 180, 114, 92, + 180, 114, 92, 180, 110, 92, 172, 106, 84, 172, 106, 84, 172, 110, 92, + 180, 110, 92, 180, 114, 92, 180, 114, 92, 180, 118, 100, 180, 114, 92, + 180, 114, 100, 180, 114, 92, 180, 114, 92, 180, 118, 92, 188, 118, 92, + 188, 122, 92, 180, 122, 100, 188, 122, 100, 180, 122, 100, 188, 118, 100, + 196, 122, 100, 188, 118, 100, 196, 122, 108, 180, 114, 100, 180, 114, 100, + 180, 126, 108, 148, 98, 76, 92, 34, 12, 84, 26, 12, 116, 58, 36, + 148, 90, 76, 148, 90, 76, 140, 82, 68, 148, 82, 68, 140, 78, 60, + 156, 86, 68, 148, 86, 68, 156, 90, 68, 156, 90, 76, 164, 94, 76, + 156, 90, 76, 156, 90, 68, 148, 82, 68, 148, 78, 60, 140, 78, 60, + 156, 86, 68, 148, 86, 68, 156, 86, 68, 156, 90, 68, 156, 94, 76, + 164, 94, 76, 156, 94, 76, 148, 86, 68, 148, 82, 60, 148, 86, 68, + 156, 90, 68, 156, 90, 76, 156, 90, 68, 156, 90, 68, 156, 94, 76, + 164, 102, 76, 172, 102, 84, 172, 102, 76, 172, 106, 84, 180, 110, 84, + 180, 114, 84, 180, 110, 84, 172, 102, 76, 180, 106, 84, 172, 106, 76, + 172, 98, 76, 164, 98, 68, 172, 106, 76, 172, 106, 84, 180, 110, 84, + 172, 98, 76, 180, 106, 84, 180, 110, 84, 180, 110, 84, 172, 98, 76, + 172, 98, 76, 180, 106, 84, 180, 114, 84, 188, 114, 92, 180, 110, 84, + 180, 110, 84, 180, 110, 84, 180, 114, 92, 180, 110, 84, 172, 106, 84, + 164, 98, 68, 164, 94, 68, 180, 106, 84, 188, 118, 92, 180, 114, 92, + 180, 110, 84, 180, 110, 84, 180, 110, 92, 180, 110, 84, 172, 106, 76, + 180, 106, 84, 180, 110, 84, 180, 114, 92, 188, 114, 92, 180, 110, 84, + 180, 106, 84, 172, 106, 76, 180, 106, 84, 188, 114, 92, 180, 114, 84, + 180, 110, 84, 180, 114, 92, 188, 118, 92, 188, 118, 92, 180, 110, 84, + 180, 106, 84, 172, 106, 76, 180, 106, 84, 188, 114, 92, 188, 118, 92, + 180, 118, 92, 188, 118, 92, 196, 122, 100, 172, 106, 84, 188, 114, 84, + 172, 106, 84, 164, 98, 68, 172, 102, 76, 180, 106, 84, 180, 110, 84, + 188, 118, 92, 188, 122, 92, 188, 114, 92, 180, 110, 92, 180, 114, 84, + 188, 118, 92, 188, 118, 92, 180, 110, 84, 172, 102, 84, 188, 122, 92, + 180, 110, 84, 164, 102, 76, 172, 102, 76, 172, 98, 76, 172, 102, 76, + 172, 102, 76, 180, 106, 84, 180, 110, 92, 180, 106, 84, 180, 106, 84, + 172, 102, 76, 164, 90, 76, 172, 98, 76, 180, 110, 92, 172, 102, 76, + 172, 102, 84, 180, 106, 84, 180, 110, 84, 172, 102, 84, 172, 98, 76, + 164, 94, 76, 164, 98, 76, 164, 98, 76, 172, 98, 84, 164, 98, 76, + 164, 102, 84, 172, 106, 84, 172, 106, 84, 172, 110, 92, 180, 114, 92, + 180, 114, 92, 188, 122, 100, 188, 122, 100, 188, 122, 100, 180, 118, 100, + 172, 106, 92, 172, 106, 84, 164, 106, 84, 172, 106, 84, 180, 114, 92, + 180, 110, 92, 172, 110, 84, 172, 110, 92, 180, 110, 92, 172, 110, 92, + 180, 114, 92, 180, 114, 92, 180, 118, 92, 172, 110, 92, 172, 106, 84, + 172, 106, 84, 172, 110, 92, 172, 106, 84, 164, 102, 84, 164, 94, 76, + 164, 98, 76, 172, 110, 92, 180, 114, 92, 172, 106, 92, 172, 106, 92, + 172, 110, 84, 172, 106, 92, 164, 102, 84, 172, 110, 92, 180, 110, 92, + 172, 110, 92, 180, 114, 92, 180, 114, 92, 180, 118, 100, 180, 114, 92, + 180, 118, 92, 180, 114, 92, 188, 114, 92, 180, 118, 92, 180, 118, 100, + 180, 118, 92, 180, 118, 100, 188, 118, 92, 180, 118, 92, 180, 110, 92, + 180, 106, 92, 180, 110, 92, 172, 106, 92, 172, 106, 84, 172, 114, 92, + 140, 90, 68, 84, 26, 12, 84, 30, 12, 116, 58, 44, 156, 90, 76, + 156, 90, 76, 148, 86, 68, 148, 86, 76, 148, 86, 68, 156, 90, 76, + 156, 90, 76, 164, 94, 84, 164, 98, 76, 164, 94, 76, 156, 90, 68, + 156, 86, 68, 156, 86, 60, 156, 90, 68, 156, 90, 76, 164, 94, 76, + 156, 94, 68, 156, 94, 76, 164, 98, 76, 164, 98, 76, 164, 98, 76, + 156, 94, 76, 156, 94, 68, 148, 78, 60, 148, 86, 68, 156, 90, 68, + 156, 90, 68, 148, 86, 68, 156, 86, 68, 156, 90, 68, 164, 98, 76, + 164, 94, 68, 172, 98, 76, 180, 106, 84, 188, 118, 92, 188, 118, 92, + 188, 118, 100, 180, 114, 92, 180, 114, 84, 180, 106, 84, 172, 102, 76, + 172, 98, 76, 172, 106, 84, 180, 106, 84, 164, 98, 68, 172, 102, 76, + 180, 114, 84, 196, 122, 100, 188, 118, 92, 172, 106, 76, 172, 102, 76, + 180, 110, 84, 188, 122, 92, 188, 118, 92, 188, 114, 92, 180, 110, 84, + 188, 114, 84, 188, 114, 92, 180, 114, 84, 180, 106, 84, 172, 102, 76, + 164, 94, 68, 180, 110, 84, 188, 118, 92, 188, 118, 92, 188, 114, 92, + 180, 114, 92, 188, 114, 84, 180, 114, 92, 180, 106, 84, 180, 110, 84, + 180, 114, 84, 188, 114, 92, 180, 114, 84, 180, 110, 92, 180, 110, 84, + 180, 106, 84, 180, 114, 84, 188, 114, 92, 188, 114, 92, 180, 114, 92, + 188, 118, 92, 196, 122, 100, 188, 122, 92, 180, 114, 92, 188, 114, 92, + 180, 110, 84, 180, 114, 84, 188, 118, 92, 188, 122, 92, 188, 118, 92, + 188, 118, 92, 188, 122, 92, 188, 118, 92, 196, 122, 100, 188, 118, 92, + 188, 114, 92, 188, 122, 100, 196, 126, 100, 188, 118, 92, 188, 114, 92, + 188, 114, 92, 180, 114, 84, 180, 110, 84, 180, 110, 84, 188, 118, 92, + 188, 118, 92, 188, 118, 92, 180, 114, 84, 196, 126, 100, 188, 114, 92, + 180, 106, 84, 172, 106, 76, 172, 102, 76, 172, 102, 76, 172, 106, 76, + 180, 110, 84, 188, 118, 92, 180, 110, 92, 180, 114, 92, 180, 106, 92, + 164, 98, 76, 180, 106, 84, 188, 114, 100, 180, 106, 84, 180, 110, 92, + 180, 110, 92, 188, 114, 92, 180, 110, 92, 172, 106, 84, 172, 98, 76, + 172, 98, 76, 164, 98, 76, 164, 102, 76, 164, 102, 84, 172, 102, 84, + 172, 106, 84, 172, 110, 92, 180, 118, 92, 180, 114, 100, 180, 118, 100, + 188, 122, 108, 188, 126, 100, 188, 118, 100, 180, 114, 92, 172, 106, 84, + 164, 102, 84, 172, 102, 84, 172, 110, 92, 172, 110, 92, 172, 110, 84, + 172, 106, 92, 172, 106, 84, 172, 110, 84, 172, 110, 92, 180, 110, 92, + 180, 114, 92, 180, 110, 92, 172, 110, 92, 172, 110, 92, 180, 110, 92, + 172, 110, 92, 180, 110, 84, 164, 102, 84, 164, 98, 76, 156, 94, 76, + 172, 106, 84, 180, 114, 92, 172, 106, 84, 164, 102, 84, 172, 110, 84, + 172, 106, 84, 164, 98, 76, 172, 102, 84, 164, 106, 84, 172, 106, 84, + 172, 106, 92, 172, 110, 92, 180, 110, 92, 180, 110, 92, 172, 110, 92, + 180, 106, 84, 172, 110, 84, 172, 110, 84, 180, 110, 84, 172, 110, 84, + 172, 110, 84, 172, 106, 84, 172, 106, 84, 180, 106, 92, 180, 106, 84, + 188, 114, 100, 188, 118, 100, 180, 114, 100, 180, 126, 108, 148, 90, 68, + 84, 30, 12, 92, 34, 12, 124, 66, 44, 156, 98, 84, 164, 102, 84, + 164, 98, 84, 164, 98, 84, 156, 94, 76, 164, 98, 84, 164, 98, 76, + 156, 90, 76, 156, 94, 76, 164, 94, 76, 156, 90, 76, 156, 90, 68, + 156, 86, 68, 156, 86, 68, 164, 94, 68, 156, 90, 76, 156, 94, 68, + 156, 90, 76, 164, 98, 76, 164, 102, 84, 172, 106, 84, 172, 106, 84, + 172, 102, 84, 148, 82, 60, 148, 86, 68, 156, 90, 68, 156, 90, 68, + 148, 86, 68, 148, 82, 60, 156, 86, 68, 156, 94, 68, 156, 86, 68, + 164, 98, 68, 180, 110, 84, 188, 118, 92, 196, 122, 92, 196, 122, 100, + 188, 118, 92, 188, 118, 92, 180, 110, 92, 172, 106, 76, 172, 106, 76, + 180, 106, 84, 180, 106, 84, 172, 102, 76, 180, 110, 84, 188, 118, 92, + 196, 126, 100, 188, 118, 100, 180, 110, 84, 172, 106, 84, 188, 114, 84, + 188, 122, 100, 196, 122, 100, 188, 118, 92, 180, 114, 84, 180, 114, 92, + 188, 118, 92, 188, 118, 92, 180, 110, 84, 180, 106, 84, 172, 102, 76, + 180, 110, 84, 196, 122, 100, 188, 122, 92, 188, 118, 92, 188, 118, 92, + 188, 122, 92, 188, 114, 92, 188, 114, 84, 180, 114, 92, 188, 114, 84, + 180, 110, 92, 180, 114, 84, 188, 114, 92, 180, 114, 84, 188, 114, 92, + 180, 114, 92, 188, 114, 92, 180, 114, 84, 180, 110, 84, 180, 110, 84, + 188, 118, 92, 188, 114, 92, 180, 114, 84, 188, 118, 92, 180, 114, 92, + 188, 114, 92, 188, 122, 92, 188, 118, 100, 188, 118, 92, 188, 118, 92, + 196, 122, 100, 180, 114, 92, 188, 118, 92, 180, 110, 84, 180, 110, 84, + 196, 130, 100, 204, 134, 108, 196, 126, 100, 188, 118, 100, 188, 122, 92, + 188, 114, 92, 188, 114, 92, 188, 114, 92, 188, 122, 100, 196, 122, 100, + 196, 122, 100, 188, 118, 92, 188, 118, 100, 188, 118, 92, 180, 110, 84, + 180, 110, 84, 180, 110, 84, 172, 102, 76, 172, 102, 76, 180, 110, 84, + 180, 110, 92, 172, 106, 84, 180, 106, 84, 172, 98, 76, 164, 94, 68, + 172, 106, 84, 180, 110, 92, 172, 106, 84, 180, 110, 84, 180, 110, 84, + 180, 114, 92, 180, 110, 92, 180, 110, 92, 172, 106, 84, 180, 106, 84, + 172, 106, 84, 172, 102, 84, 172, 102, 76, 164, 102, 84, 172, 110, 92, + 180, 114, 92, 188, 118, 100, 188, 122, 100, 188, 118, 92, 188, 126, 108, + 188, 122, 100, 180, 118, 100, 172, 110, 92, 164, 106, 84, 172, 102, 84, + 172, 106, 84, 180, 114, 92, 180, 110, 92, 172, 110, 92, 172, 106, 84, + 172, 106, 84, 172, 102, 84, 172, 106, 84, 172, 106, 84, 172, 110, 92, + 172, 110, 92, 172, 110, 92, 172, 110, 84, 180, 110, 92, 172, 114, 92, + 180, 110, 92, 172, 106, 92, 172, 106, 84, 156, 94, 68, 172, 106, 92, + 180, 114, 92, 172, 102, 84, 164, 102, 84, 180, 110, 92, 172, 106, 92, + 164, 98, 76, 164, 102, 84, 172, 102, 84, 164, 102, 84, 172, 106, 84, + 172, 106, 84, 172, 106, 84, 172, 106, 84, 172, 110, 84, 172, 102, 84, + 172, 106, 84, 172, 106, 84, 172, 110, 84, 172, 106, 84, 164, 106, 84, + 172, 106, 84, 172, 102, 84, 172, 102, 84, 172, 102, 84, 180, 114, 100, + 188, 118, 100, 180, 118, 100, 188, 126, 100, 148, 94, 76, 92, 34, 12, + 92, 34, 12, 116, 62, 44, 156, 94, 76, 164, 94, 84, 156, 94, 76, + 156, 94, 76, 148, 86, 68, 148, 86, 76, 148, 82, 68, 148, 78, 60, + 148, 82, 68, 156, 90, 68, 156, 94, 76, 164, 90, 76, 156, 90, 68, + 148, 82, 68, 148, 82, 60, 164, 94, 76, 156, 94, 76, 156, 94, 68, + 164, 94, 76, 164, 102, 84, 164, 102, 84, 172, 102, 84, 164, 102, 84, + 156, 90, 68, 156, 90, 68, 156, 94, 76, 156, 90, 68, 148, 86, 68, + 148, 86, 68, 156, 90, 68, 156, 90, 68, 164, 98, 76, 172, 106, 84, + 180, 110, 84, 180, 110, 84, 180, 114, 92, 188, 118, 92, 180, 110, 84, + 188, 118, 92, 188, 118, 92, 180, 110, 84, 180, 106, 84, 180, 114, 84, + 180, 114, 84, 180, 114, 92, 188, 114, 84, 180, 114, 92, 188, 114, 84, + 188, 118, 92, 188, 114, 92, 180, 114, 92, 188, 114, 84, 180, 110, 84, + 196, 122, 100, 188, 118, 92, 188, 114, 92, 188, 114, 92, 188, 118, 92, + 188, 118, 92, 188, 118, 92, 180, 110, 84, 172, 106, 84, 188, 114, 92, + 196, 122, 100, 188, 122, 100, 196, 122, 92, 196, 122, 100, 188, 122, 100, + 188, 118, 92, 188, 122, 100, 188, 118, 92, 188, 118, 92, 188, 114, 92, + 188, 118, 92, 188, 114, 92, 188, 118, 92, 188, 122, 92, 196, 122, 100, + 188, 126, 100, 188, 118, 92, 180, 110, 84, 188, 114, 92, 188, 122, 100, + 196, 126, 100, 188, 118, 100, 196, 122, 92, 188, 114, 92, 180, 114, 92, + 196, 122, 92, 188, 122, 100, 188, 118, 92, 196, 122, 100, 196, 126, 100, + 188, 118, 92, 188, 118, 92, 172, 98, 76, 164, 94, 68, 180, 110, 92, + 188, 122, 92, 188, 114, 92, 180, 114, 84, 204, 130, 108, 196, 126, 100, + 188, 118, 92, 188, 122, 92, 196, 122, 100, 188, 122, 92, 188, 122, 92, + 188, 114, 92, 180, 114, 84, 180, 110, 84, 180, 110, 84, 180, 114, 92, + 180, 110, 84, 172, 102, 76, 172, 102, 76, 180, 106, 84, 180, 110, 92, + 180, 106, 84, 172, 102, 76, 172, 98, 76, 164, 94, 76, 180, 106, 84, + 180, 110, 92, 180, 106, 84, 172, 102, 76, 172, 98, 84, 172, 102, 76, + 180, 110, 84, 180, 110, 84, 180, 106, 84, 180, 110, 92, 180, 114, 92, + 172, 110, 92, 172, 106, 92, 172, 106, 84, 180, 110, 92, 180, 118, 100, + 188, 122, 100, 180, 122, 100, 188, 118, 100, 188, 126, 108, 188, 118, 100, + 180, 114, 92, 172, 106, 84, 172, 106, 84, 172, 110, 92, 180, 114, 92, + 180, 114, 92, 172, 114, 92, 180, 110, 92, 172, 106, 84, 164, 102, 84, + 164, 102, 84, 172, 106, 84, 172, 106, 84, 172, 106, 92, 180, 110, 84, + 172, 110, 92, 180, 110, 92, 172, 110, 92, 180, 110, 92, 180, 114, 92, + 172, 114, 92, 180, 110, 92, 164, 98, 76, 172, 110, 92, 180, 114, 92, + 172, 106, 84, 172, 106, 84, 172, 110, 92, 172, 106, 84, 164, 102, 84, + 172, 106, 84, 172, 110, 84, 172, 106, 92, 172, 106, 84, 172, 106, 84, + 172, 110, 92, 172, 110, 92, 180, 110, 84, 172, 106, 84, 172, 106, 84, + 180, 110, 84, 172, 110, 84, 172, 114, 92, 172, 110, 92, 172, 110, 84, + 172, 110, 84, 180, 106, 92, 172, 102, 84, 180, 106, 92, 172, 106, 92, + 172, 106, 92, 180, 122, 100, 148, 98, 76, 92, 34, 12, 100, 42, 28, + 116, 54, 36, 148, 86, 68, 148, 90, 76, 148, 86, 76, 148, 86, 76, + 140, 78, 60, 148, 78, 60, 140, 78, 60, 148, 78, 60, 148, 78, 60, + 148, 82, 60, 156, 86, 68, 156, 90, 68, 156, 90, 68, 156, 90, 68, + 148, 86, 68, 172, 102, 84, 164, 102, 84, 172, 102, 84, 164, 102, 84, + 172, 106, 84, 172, 106, 84, 164, 102, 84, 164, 98, 76, 156, 94, 76, + 164, 98, 76, 156, 94, 76, 164, 98, 76, 164, 94, 76, 164, 94, 76, + 156, 94, 76, 164, 98, 76, 180, 110, 84, 188, 114, 84, 188, 114, 92, + 180, 106, 84, 188, 114, 84, 188, 118, 92, 188, 114, 92, 188, 118, 92, + 188, 118, 92, 188, 114, 92, 180, 110, 84, 188, 114, 92, 188, 118, 92, + 188, 114, 92, 188, 118, 92, 188, 118, 92, 188, 114, 92, 188, 118, 92, + 188, 118, 92, 188, 118, 92, 188, 114, 92, 180, 110, 84, 196, 122, 100, + 188, 118, 92, 180, 114, 84, 188, 114, 92, 188, 122, 92, 196, 122, 100, + 188, 118, 92, 188, 114, 92, 180, 110, 84, 188, 118, 92, 196, 122, 100, + 196, 122, 92, 188, 118, 92, 188, 118, 100, 196, 122, 92, 188, 118, 92, + 196, 122, 100, 196, 122, 92, 196, 122, 100, 188, 122, 92, 196, 122, 100, + 188, 122, 92, 196, 122, 100, 196, 122, 100, 196, 122, 100, 196, 122, 92, + 188, 114, 92, 180, 110, 84, 188, 114, 84, 188, 118, 92, 196, 122, 92, + 188, 118, 92, 188, 122, 92, 188, 118, 92, 188, 114, 92, 188, 118, 92, + 196, 122, 92, 188, 118, 92, 188, 118, 92, 196, 126, 100, 204, 130, 108, + 204, 134, 108, 188, 122, 92, 180, 106, 84, 188, 114, 92, 188, 118, 92, + 188, 118, 92, 196, 122, 100, 204, 134, 108, 196, 130, 100, 196, 122, 100, + 188, 122, 92, 196, 122, 100, 196, 122, 100, 188, 118, 92, 188, 114, 92, + 188, 114, 84, 180, 110, 84, 180, 110, 84, 188, 114, 92, 180, 110, 84, + 180, 106, 84, 180, 106, 84, 188, 114, 92, 188, 118, 92, 188, 114, 92, + 180, 110, 92, 180, 106, 84, 172, 102, 84, 180, 110, 84, 188, 118, 92, + 180, 106, 84, 180, 106, 84, 172, 106, 84, 180, 106, 84, 180, 106, 92, + 188, 114, 92, 180, 110, 92, 180, 110, 84, 188, 114, 92, 188, 114, 100, + 180, 114, 92, 172, 110, 92, 180, 114, 92, 188, 122, 100, 188, 122, 108, + 188, 122, 100, 180, 118, 100, 188, 122, 100, 180, 118, 100, 180, 114, 92, + 180, 110, 92, 180, 114, 92, 180, 114, 92, 180, 114, 92, 172, 110, 92, + 180, 110, 92, 172, 110, 84, 172, 106, 84, 164, 102, 84, 172, 102, 84, + 164, 106, 84, 172, 106, 84, 180, 110, 92, 172, 114, 92, 180, 110, 92, + 172, 110, 92, 180, 110, 92, 172, 110, 84, 172, 110, 92, 172, 110, 84, + 180, 110, 92, 164, 102, 84, 172, 110, 92, 180, 114, 92, 180, 114, 92, + 180, 110, 92, 172, 110, 84, 172, 110, 92, 172, 106, 84, 180, 114, 92, + 180, 110, 92, 180, 110, 92, 172, 110, 92, 172, 110, 92, 172, 110, 84, + 172, 110, 92, 180, 110, 92, 172, 110, 92, 180, 110, 84, 180, 114, 92, + 180, 114, 92, 180, 114, 92, 180, 118, 92, 180, 114, 92, 180, 114, 92, + 188, 118, 100, 188, 114, 92, 196, 122, 108, 188, 118, 100, 180, 118, 100, + 188, 130, 108, 156, 106, 84, 100, 42, 28, 84, 30, 12, 116, 54, 36, + 156, 90, 76, 156, 90, 76, 156, 90, 68, 156, 94, 76, 148, 86, 68, + 164, 94, 84, 156, 94, 76, 156, 90, 76, 148, 86, 68, 148, 78, 60, + 148, 78, 60, 148, 86, 68, 164, 94, 76, 164, 94, 76, 172, 98, 84, + 164, 98, 76, 164, 102, 76, 172, 106, 84, 180, 110, 92, 180, 118, 100, + 180, 118, 100, 180, 110, 92, 172, 110, 92, 164, 98, 76, 164, 94, 76, + 164, 98, 76, 164, 98, 84, 164, 102, 76, 164, 102, 84, 172, 102, 84, + 164, 102, 76, 188, 118, 92, 188, 122, 100, 196, 122, 100, 188, 114, 92, + 180, 114, 92, 188, 114, 92, 196, 122, 100, 196, 122, 100, 188, 118, 92, + 188, 114, 92, 188, 118, 92, 188, 118, 92, 188, 118, 92, 180, 110, 84, + 196, 122, 100, 196, 122, 100, 188, 122, 92, 196, 122, 100, 196, 126, 100, + 196, 122, 100, 188, 118, 92, 188, 118, 92, 196, 122, 100, 188, 118, 92, + 188, 114, 92, 188, 118, 92, 196, 122, 100, 196, 126, 100, 196, 122, 100, + 188, 118, 92, 188, 114, 84, 188, 122, 92, 196, 122, 100, 188, 122, 92, + 188, 118, 92, 196, 122, 100, 196, 122, 92, 188, 118, 92, 196, 122, 100, + 196, 126, 100, 196, 122, 100, 196, 126, 100, 196, 126, 100, 196, 126, 100, + 196, 122, 100, 196, 126, 100, 196, 122, 100, 196, 126, 100, 196, 122, 100, + 188, 118, 92, 188, 118, 100, 196, 126, 100, 196, 126, 100, 196, 122, 100, + 196, 126, 100, 196, 122, 100, 188, 118, 92, 188, 122, 100, 196, 122, 92, + 188, 114, 92, 188, 114, 92, 188, 122, 92, 188, 114, 92, 204, 130, 108, + 196, 126, 100, 188, 118, 92, 188, 118, 92, 188, 118, 92, 196, 122, 100, + 196, 126, 100, 204, 130, 108, 196, 126, 100, 196, 122, 100, 188, 118, 92, + 196, 122, 100, 196, 126, 100, 196, 122, 100, 188, 118, 92, 188, 114, 92, + 188, 114, 92, 188, 118, 92, 188, 118, 92, 188, 118, 92, 180, 114, 84, + 188, 114, 92, 196, 126, 100, 196, 122, 100, 188, 114, 92, 180, 110, 84, + 180, 106, 84, 172, 98, 76, 180, 110, 92, 188, 114, 92, 172, 102, 84, + 196, 126, 100, 188, 114, 92, 188, 114, 92, 188, 114, 92, 188, 114, 92, + 180, 110, 84, 188, 114, 92, 188, 114, 92, 188, 122, 100, 180, 118, 100, + 180, 114, 92, 180, 118, 100, 188, 122, 100, 188, 126, 108, 188, 122, 100, + 180, 118, 100, 188, 122, 100, 180, 118, 100, 180, 110, 92, 180, 114, 100, + 180, 118, 100, 188, 118, 100, 172, 114, 92, 172, 106, 84, 172, 110, 92, + 172, 106, 92, 172, 102, 84, 164, 102, 84, 172, 102, 76, 172, 106, 84, + 172, 106, 92, 180, 114, 92, 180, 110, 92, 180, 114, 92, 172, 110, 92, + 172, 110, 84, 172, 106, 84, 172, 106, 84, 172, 106, 92, 172, 110, 84, + 172, 106, 84, 180, 110, 92, 180, 114, 92, 180, 118, 100, 180, 118, 100, + 180, 110, 92, 172, 110, 92, 180, 110, 92, 180, 114, 92, 172, 114, 92, + 172, 110, 92, 172, 106, 84, 172, 106, 84, 172, 106, 92, 172, 110, 84, + 172, 106, 84, 180, 110, 84, 172, 110, 92, 180, 114, 92, 180, 114, 92, + 180, 118, 92, 180, 118, 92, 180, 114, 92, 180, 118, 92, 188, 114, 100, + 180, 110, 92, 188, 122, 108, 188, 122, 100, 180, 118, 108, 188, 126, 108, + 148, 90, 76, 84, 30, 12, 92, 38, 28, 140, 78, 60, 156, 90, 68, + 156, 90, 76, 156, 90, 68, 156, 94, 76, 164, 98, 76, 156, 94, 76, + 164, 94, 76, 156, 94, 68, 156, 94, 76, 156, 90, 68, 156, 86, 68, + 148, 86, 68, 156, 86, 68, 156, 94, 76, 164, 102, 76, 180, 110, 92, + 172, 102, 84, 172, 98, 84, 172, 106, 84, 180, 114, 92, 188, 122, 100, + 188, 114, 92, 172, 110, 92, 172, 102, 84, 164, 98, 76, 156, 90, 68, + 156, 86, 68, 164, 94, 76, 172, 102, 84, 172, 106, 84, 180, 110, 92, + 188, 114, 92, 196, 126, 100, 196, 126, 100, 188, 118, 92, 180, 110, 92, + 188, 118, 92, 196, 130, 108, 196, 126, 100, 196, 122, 100, 188, 126, 100, + 196, 126, 108, 196, 126, 100, 196, 122, 100, 180, 118, 92, 188, 114, 92, + 188, 118, 92, 196, 122, 100, 188, 122, 100, 188, 122, 100, 188, 118, 92, + 188, 118, 92, 188, 118, 92, 196, 126, 100, 188, 122, 100, 196, 122, 100, + 188, 122, 100, 196, 126, 100, 196, 130, 100, 196, 126, 108, 196, 130, 100, + 196, 122, 100, 188, 122, 100, 196, 126, 108, 196, 126, 100, 204, 130, 108, + 196, 130, 100, 196, 130, 108, 196, 130, 108, 188, 122, 100, 196, 126, 100, + 188, 122, 100, 196, 122, 100, 188, 122, 100, 196, 126, 100, 196, 126, 100, + 196, 130, 100, 196, 130, 108, 196, 130, 100, 196, 126, 100, 196, 126, 100, + 204, 130, 108, 196, 130, 100, 196, 126, 108, 188, 126, 100, 196, 122, 100, + 196, 126, 100, 196, 130, 108, 204, 130, 108, 196, 126, 108, 196, 130, 100, + 196, 122, 100, 188, 122, 100, 196, 126, 100, 204, 134, 108, 204, 134, 108, + 196, 126, 100, 188, 114, 92, 188, 118, 92, 188, 122, 100, 196, 126, 100, + 196, 130, 108, 196, 126, 108, 196, 126, 100, 196, 126, 100, 196, 126, 100, + 188, 122, 92, 188, 122, 100, 188, 122, 100, 196, 122, 100, 188, 122, 100, + 196, 122, 100, 188, 122, 100, 196, 122, 100, 188, 122, 100, 188, 118, 92, + 188, 118, 100, 196, 126, 100, 188, 122, 100, 188, 122, 100, 188, 118, 100, + 188, 118, 92, 188, 118, 92, 188, 114, 92, 188, 118, 92, 188, 122, 100, + 188, 114, 92, 180, 114, 92, 180, 114, 84, 172, 102, 84, 172, 106, 84, + 188, 118, 92, 188, 118, 100, 188, 122, 100, 188, 122, 100, 180, 118, 100, + 188, 118, 100, 188, 122, 100, 188, 122, 100, 188, 118, 100, 180, 118, 100, + 196, 130, 108, 180, 114, 92, 172, 106, 84, 172, 110, 92, 180, 114, 92, + 172, 110, 92, 172, 106, 84, 172, 106, 84, 180, 110, 92, 180, 114, 92, + 180, 114, 92, 180, 110, 92, 164, 102, 84, 164, 98, 84, 172, 102, 84, + 172, 106, 84, 172, 106, 92, 172, 106, 84, 172, 106, 84, 180, 106, 92, + 172, 106, 92, 180, 110, 92, 180, 110, 92, 172, 110, 92, 172, 102, 84, + 172, 110, 92, 180, 114, 92, 180, 114, 100, 180, 114, 92, 172, 110, 92, + 180, 114, 92, 172, 110, 92, 180, 114, 92, 180, 114, 92, 180, 110, 92, + 180, 110, 92, 172, 110, 92, 180, 110, 84, 172, 110, 92, 172, 110, 92, + 180, 110, 92, 180, 110, 92, 180, 114, 92, 180, 114, 92, 180, 118, 100, + 180, 118, 100, 180, 114, 92, 180, 114, 92, 172, 102, 84, 172, 102, 84, + 180, 106, 92, 164, 94, 84, 156, 94, 76, 172, 110, 100, 140, 82, 68, + 92, 38, 28, 92, 34, 20, 124, 58, 44, 140, 78, 60, 148, 86, 68, + 156, 90, 68, 156, 94, 76, 164, 94, 76, 148, 90, 68, 156, 90, 68, + 164, 94, 76, 156, 94, 76, 156, 94, 76, 156, 90, 68, 148, 86, 60, + 148, 86, 68, 156, 90, 68, 164, 94, 76, 164, 98, 76, 156, 94, 76, + 156, 94, 76, 172, 98, 84, 180, 110, 92, 180, 118, 100, 188, 114, 100, + 180, 114, 92, 172, 102, 84, 164, 98, 84, 164, 94, 76, 156, 94, 76, + 156, 90, 68, 164, 94, 76, 164, 94, 76, 164, 94, 76, 164, 98, 76, + 180, 110, 92, 196, 126, 100, 196, 126, 108, 204, 130, 100, 196, 126, 108, + 196, 130, 108, 196, 126, 100, 188, 122, 100, 196, 122, 100, 196, 126, 100, + 196, 126, 100, 188, 122, 100, 188, 118, 92, 196, 130, 108, 196, 134, 108, + 204, 134, 108, 204, 134, 108, 196, 130, 108, 196, 130, 108, 196, 126, 108, + 196, 130, 108, 196, 126, 100, 188, 126, 100, 188, 122, 100, 196, 126, 100, + 196, 126, 100, 196, 126, 108, 196, 126, 100, 188, 126, 100, 188, 122, 100, + 196, 126, 100, 188, 122, 100, 188, 122, 100, 188, 122, 100, 196, 122, 100, + 196, 126, 100, 196, 126, 108, 204, 130, 108, 196, 130, 108, 196, 130, 108, + 196, 130, 108, 196, 130, 108, 204, 130, 108, 196, 130, 108, 204, 130, 108, + 196, 130, 108, 196, 126, 100, 188, 126, 108, 196, 126, 100, 196, 126, 108, + 196, 130, 108, 196, 126, 100, 196, 126, 100, 196, 126, 100, 188, 126, 100, + 196, 126, 100, 196, 126, 108, 196, 130, 100, 196, 126, 108, 188, 126, 100, + 196, 122, 100, 188, 126, 100, 196, 130, 108, 196, 130, 108, 188, 122, 100, + 180, 114, 92, 188, 118, 92, 188, 122, 100, 188, 122, 100, 188, 118, 92, + 188, 122, 100, 188, 118, 100, 188, 122, 100, 188, 118, 92, 188, 118, 100, + 188, 118, 92, 188, 122, 100, 188, 118, 92, 188, 122, 92, 188, 118, 100, + 188, 118, 92, 188, 118, 92, 188, 118, 92, 188, 118, 100, 180, 118, 92, + 188, 122, 100, 188, 122, 100, 188, 118, 92, 188, 118, 92, 180, 114, 92, + 180, 114, 92, 180, 114, 92, 188, 118, 92, 196, 126, 100, 188, 118, 100, + 188, 122, 100, 188, 118, 92, 180, 110, 84, 180, 114, 92, 188, 122, 100, + 188, 122, 100, 180, 114, 92, 180, 114, 92, 180, 114, 92, 180, 114, 92, + 180, 118, 100, 180, 118, 100, 180, 114, 92, 172, 110, 92, 172, 106, 84, + 164, 94, 76, 164, 102, 84, 180, 114, 92, 180, 118, 100, 172, 106, 84, + 164, 98, 76, 164, 98, 84, 164, 98, 76, 164, 98, 84, 172, 102, 84, + 172, 102, 84, 164, 98, 76, 172, 102, 84, 172, 106, 84, 180, 110, 92, + 180, 110, 92, 180, 110, 92, 180, 110, 92, 180, 110, 92, 180, 110, 92, + 180, 110, 92, 172, 110, 92, 180, 110, 92, 172, 106, 84, 172, 110, 92, + 180, 118, 92, 188, 118, 100, 180, 114, 92, 180, 114, 92, 180, 114, 92, + 180, 114, 92, 180, 118, 100, 180, 118, 100, 180, 118, 100, 180, 118, 100, + 188, 118, 92, 180, 118, 100, 180, 118, 100, 188, 118, 100, 180, 110, 92, + 172, 110, 100, 180, 114, 100, 180, 118, 100, 180, 118, 100, 180, 118, 100, + 188, 122, 100, 188, 118, 100, 180, 106, 84, 172, 102, 84, 188, 114, 100, + 164, 98, 76, 164, 98, 84, 172, 110, 100, 132, 78, 68, 92, 34, 20, + 92, 34, 20, 132, 70, 52, 156, 90, 68, 164, 102, 76, 164, 98, 76, + 164, 98, 84, 164, 98, 76, 156, 90, 68, 156, 94, 76, 148, 82, 60, + 148, 86, 68, 148, 82, 60, 148, 82, 60, 148, 82, 60, 148, 78, 60, + 148, 82, 60, 148, 86, 68, 148, 82, 68, 148, 82, 60, 156, 82, 68, + 156, 90, 68, 164, 98, 76, 172, 102, 84, 172, 106, 84, 172, 106, 84, + 164, 102, 76, 172, 98, 84, 164, 98, 76, 156, 90, 76, 156, 82, 60, + 140, 78, 60, 140, 70, 52, 132, 70, 52, 156, 82, 60, 172, 98, 76, + 188, 114, 92, 196, 122, 100, 196, 126, 100, 196, 126, 108, 196, 130, 108, + 196, 130, 108, 196, 126, 100, 188, 126, 100, 196, 126, 100, 188, 126, 100, + 196, 126, 100, 188, 122, 100, 196, 130, 108, 204, 130, 108, 196, 130, 108, + 196, 130, 108, 196, 122, 100, 188, 122, 100, 196, 122, 100, 188, 126, 100, + 196, 126, 100, 196, 122, 100, 188, 122, 100, 188, 122, 100, 196, 122, 100, + 188, 126, 100, 188, 122, 100, 188, 122, 100, 196, 122, 100, 188, 122, 100, + 196, 126, 100, 188, 122, 100, 188, 118, 100, 188, 118, 92, 188, 122, 100, + 188, 126, 100, 196, 126, 100, 196, 126, 100, 196, 130, 108, 196, 126, 100, + 196, 126, 100, 196, 126, 108, 196, 126, 100, 188, 122, 100, 196, 130, 108, + 196, 130, 100, 196, 126, 108, 196, 126, 100, 196, 130, 108, 204, 130, 108, + 196, 130, 108, 196, 126, 108, 196, 130, 108, 204, 134, 108, 196, 130, 108, + 196, 130, 108, 196, 130, 108, 196, 130, 108, 204, 130, 108, 196, 134, 108, + 204, 130, 108, 204, 134, 116, 196, 130, 108, 196, 122, 100, 188, 122, 100, + 196, 126, 108, 196, 126, 100, 196, 126, 100, 188, 118, 100, 188, 118, 92, + 188, 118, 92, 188, 122, 92, 188, 118, 100, 188, 122, 100, 188, 122, 100, + 188, 122, 100, 188, 122, 100, 188, 118, 100, 188, 122, 92, 188, 118, 100, + 188, 122, 100, 188, 122, 100, 188, 122, 100, 188, 122, 100, 188, 118, 92, + 188, 122, 100, 188, 122, 100, 188, 118, 100, 188, 118, 92, 188, 114, 92, + 188, 122, 100, 188, 122, 100, 188, 122, 100, 188, 118, 92, 188, 122, 100, + 188, 122, 100, 180, 110, 92, 180, 114, 92, 188, 122, 100, 188, 122, 100, + 188, 118, 100, 180, 118, 100, 180, 118, 100, 188, 122, 100, 188, 122, 100, + 188, 122, 100, 180, 114, 92, 180, 110, 92, 172, 110, 92, 164, 102, 76, + 164, 102, 84, 188, 118, 100, 180, 118, 100, 172, 106, 84, 164, 102, 84, + 172, 110, 92, 180, 110, 92, 180, 110, 92, 180, 110, 92, 180, 110, 92, + 172, 106, 84, 180, 110, 92, 172, 110, 92, 180, 110, 92, 180, 110, 92, + 180, 114, 92, 180, 110, 92, 180, 114, 92, 172, 110, 92, 180, 110, 84, + 180, 110, 92, 180, 110, 92, 172, 102, 84, 172, 106, 84, 172, 110, 92, + 180, 110, 92, 172, 110, 92, 172, 110, 92, 172, 106, 92, 172, 110, 92, + 180, 114, 92, 180, 114, 92, 180, 114, 92, 180, 114, 92, 180, 114, 100, + 180, 114, 92, 180, 114, 92, 180, 114, 92, 180, 110, 100, 180, 114, 92, + 180, 114, 92, 180, 114, 100, 180, 118, 92, 180, 122, 100, 188, 122, 100, + 188, 122, 100, 188, 118, 100, 180, 110, 92, 188, 114, 100, 172, 102, 92, + 172, 106, 92, 180, 118, 100, 132, 78, 68, 92, 34, 20, 92, 34, 20, + 132, 74, 60, 156, 90, 68, 164, 94, 76, 148, 90, 68, 156, 86, 68, + 156, 90, 68, 156, 90, 68, 164, 98, 84, 156, 90, 68, 156, 90, 68, + 156, 90, 76, 156, 94, 76, 164, 98, 76, 164, 98, 84, 164, 102, 76, + 172, 102, 84, 172, 102, 84, 172, 106, 84, 172, 106, 84, 180, 110, 92, + 180, 110, 92, 180, 110, 92, 180, 114, 100, 180, 114, 92, 180, 110, 92, + 180, 114, 92, 180, 114, 92, 180, 110, 92, 164, 98, 84, 164, 94, 76, + 156, 90, 68, 156, 90, 68, 172, 102, 84, 180, 110, 92, 188, 118, 92, + 196, 122, 100, 196, 122, 100, 188, 122, 100, 188, 122, 100, 188, 118, 92, + 188, 118, 100, 188, 118, 100, 180, 114, 92, 188, 114, 92, 188, 118, 100, + 188, 118, 92, 196, 126, 100, 188, 126, 100, 196, 122, 100, 188, 122, 100, + 180, 118, 92, 188, 118, 92, 188, 122, 100, 196, 122, 100, 196, 126, 108, + 188, 126, 100, 188, 122, 100, 196, 122, 100, 188, 126, 100, 196, 122, 100, + 188, 122, 100, 188, 118, 92, 180, 110, 92, 180, 114, 92, 188, 118, 92, + 180, 114, 92, 180, 110, 84, 172, 110, 84, 180, 114, 92, 188, 114, 92, + 188, 126, 100, 196, 126, 108, 196, 126, 100, 196, 130, 108, 196, 126, 108, + 188, 126, 100, 188, 126, 100, 196, 122, 100, 188, 122, 100, 188, 122, 100, + 188, 118, 92, 188, 122, 100, 188, 122, 100, 188, 126, 100, 188, 122, 100, + 188, 118, 92, 196, 130, 108, 196, 130, 108, 196, 126, 108, 196, 126, 100, + 196, 130, 108, 196, 130, 108, 196, 130, 108, 204, 130, 108, 196, 130, 108, + 196, 130, 100, 196, 122, 100, 180, 118, 92, 188, 118, 92, 188, 122, 100, + 196, 126, 100, 180, 118, 100, 188, 118, 92, 180, 118, 92, 180, 114, 92, + 188, 118, 92, 180, 114, 92, 188, 118, 92, 180, 114, 92, 188, 114, 92, + 180, 114, 92, 180, 114, 92, 180, 114, 92, 180, 114, 92, 188, 118, 92, + 180, 114, 92, 188, 118, 92, 188, 118, 92, 180, 110, 92, 188, 114, 92, + 188, 122, 92, 180, 118, 92, 180, 110, 92, 180, 110, 92, 180, 118, 92, + 196, 122, 100, 188, 118, 100, 180, 114, 92, 188, 122, 100, 188, 118, 92, + 180, 110, 92, 180, 114, 84, 188, 118, 100, 180, 118, 92, 188, 118, 100, + 188, 122, 100, 188, 122, 100, 188, 122, 108, 188, 122, 100, 188, 122, 100, + 180, 114, 92, 172, 106, 84, 164, 98, 84, 156, 94, 76, 164, 94, 76, + 164, 102, 76, 172, 102, 84, 164, 98, 76, 172, 106, 84, 188, 122, 100, + 188, 118, 100, 188, 118, 100, 180, 114, 92, 180, 114, 92, 180, 110, 92, + 180, 110, 92, 180, 110, 92, 172, 110, 92, 180, 110, 92, 172, 110, 92, + 180, 110, 84, 172, 110, 92, 180, 110, 92, 172, 106, 92, 172, 110, 84, + 172, 106, 92, 172, 102, 84, 172, 106, 84, 172, 110, 92, 172, 110, 84, + 172, 106, 84, 172, 106, 84, 172, 106, 84, 172, 106, 84, 172, 102, 84, + 164, 102, 84, 172, 106, 84, 172, 106, 84, 172, 106, 84, 172, 106, 92, + 172, 106, 84, 172, 106, 92, 180, 110, 92, 172, 110, 92, 180, 106, 92, + 172, 110, 92, 172, 110, 92, 180, 114, 92, 180, 118, 92, 180, 118, 92, + 188, 118, 100, 188, 114, 100, 188, 118, 100, 180, 110, 92, 180, 118, 108, + 180, 122, 108, 132, 78, 68, 92, 34, 20, 92, 34, 20, 108, 50, 28, + 132, 66, 52, 140, 74, 52, 132, 70, 52, 140, 74, 52, 140, 78, 60, + 148, 86, 60, 164, 94, 76, 156, 94, 68, 156, 94, 76, 164, 98, 76, + 164, 102, 84, 172, 106, 84, 172, 106, 84, 172, 110, 92, 172, 106, 84, + 180, 110, 92, 180, 110, 92, 180, 114, 92, 180, 110, 92, 180, 110, 92, + 180, 114, 92, 180, 110, 92, 180, 114, 92, 172, 106, 92, 180, 110, 92, + 180, 114, 92, 180, 114, 92, 180, 110, 92, 180, 114, 92, 188, 114, 100, + 188, 122, 100, 180, 110, 84, 188, 114, 92, 180, 114, 92, 188, 114, 92, + 180, 110, 92, 180, 110, 92, 180, 110, 92, 180, 114, 92, 180, 114, 84, + 180, 114, 92, 180, 110, 84, 180, 110, 92, 172, 110, 84, 180, 110, 92, + 180, 114, 92, 180, 114, 92, 180, 114, 92, 180, 110, 92, 180, 110, 84, + 180, 110, 92, 188, 118, 92, 188, 122, 100, 180, 114, 84, 180, 110, 92, + 180, 110, 84, 180, 110, 84, 180, 110, 92, 180, 114, 92, 180, 106, 84, + 172, 106, 84, 164, 102, 76, 172, 102, 84, 180, 110, 84, 180, 110, 84, + 172, 110, 92, 180, 106, 84, 180, 110, 84, 180, 110, 92, 180, 118, 92, + 188, 118, 92, 188, 118, 100, 188, 122, 100, 188, 122, 92, 188, 118, 100, + 188, 118, 92, 180, 114, 92, 188, 118, 92, 180, 114, 92, 180, 110, 92, + 180, 114, 92, 180, 114, 92, 188, 114, 92, 180, 114, 92, 180, 114, 92, + 188, 114, 92, 188, 118, 92, 188, 122, 92, 188, 118, 100, 196, 122, 92, + 188, 122, 100, 188, 118, 100, 188, 122, 92, 188, 118, 100, 188, 118, 92, + 180, 114, 92, 172, 106, 84, 180, 110, 92, 180, 118, 92, 188, 114, 92, + 172, 110, 84, 180, 110, 84, 180, 110, 92, 180, 110, 92, 180, 110, 84, + 172, 110, 84, 180, 106, 84, 172, 106, 84, 172, 106, 84, 172, 102, 84, + 172, 106, 76, 172, 106, 84, 172, 106, 84, 172, 106, 84, 172, 106, 84, + 180, 110, 84, 172, 106, 84, 172, 102, 76, 172, 106, 84, 180, 110, 84, + 172, 106, 84, 172, 102, 84, 172, 102, 76, 180, 106, 84, 180, 114, 92, + 188, 118, 92, 180, 114, 92, 188, 118, 92, 188, 122, 100, 180, 110, 84, + 180, 110, 92, 188, 118, 92, 180, 114, 92, 180, 114, 92, 172, 114, 92, + 180, 114, 92, 180, 114, 92, 180, 114, 92, 172, 110, 84, 164, 98, 84, + 156, 94, 76, 140, 74, 52, 140, 78, 60, 148, 86, 68, 156, 90, 68, + 156, 94, 76, 156, 98, 76, 172, 102, 84, 172, 110, 92, 172, 106, 92, + 172, 106, 84, 172, 106, 84, 172, 102, 84, 172, 106, 84, 172, 106, 84, + 172, 106, 84, 180, 106, 84, 172, 106, 84, 172, 102, 84, 172, 106, 84, + 172, 102, 84, 172, 106, 84, 180, 106, 84, 172, 106, 84, 172, 106, 84, + 172, 106, 84, 172, 110, 92, 180, 110, 92, 180, 110, 92, 172, 106, 92, + 172, 106, 84, 172, 106, 84, 172, 110, 92, 164, 102, 84, 172, 102, 84, + 164, 106, 84, 172, 106, 84, 172, 106, 92, 172, 106, 84, 172, 106, 84, + 172, 106, 84, 172, 106, 92, 172, 106, 92, 164, 102, 84, 172, 102, 84, + 164, 106, 84, 164, 102, 84, 172, 106, 84, 172, 106, 84, 180, 110, 92, + 180, 106, 92, 180, 110, 92, 172, 102, 92, 172, 114, 100, 180, 118, 100, + 132, 74, 60, 92, 34, 20, 92, 34, 12, 124, 58, 44, 148, 78, 60, + 148, 90, 68, 156, 86, 68, 156, 94, 76, 156, 94, 76, 156, 90, 68, + 164, 98, 76, 156, 94, 76, 164, 94, 76, 156, 94, 68, 164, 94, 76, + 164, 98, 76, 164, 98, 84, 164, 98, 76, 156, 98, 76, 164, 94, 76, + 164, 98, 76, 164, 98, 84, 164, 98, 84, 172, 102, 76, 164, 102, 84, + 172, 102, 84, 172, 102, 84, 172, 106, 84, 172, 106, 92, 180, 106, 84, + 172, 106, 92, 172, 106, 84, 180, 110, 92, 180, 110, 92, 180, 114, 92, + 180, 110, 92, 180, 106, 84, 180, 114, 92, 188, 118, 92, 188, 118, 92, + 188, 114, 92, 188, 118, 92, 188, 118, 92, 188, 118, 100, 188, 118, 92, + 188, 122, 100, 188, 122, 100, 188, 118, 92, 180, 118, 92, 188, 118, 92, + 188, 118, 100, 188, 118, 92, 180, 118, 92, 188, 114, 92, 180, 118, 92, + 188, 122, 100, 196, 130, 108, 188, 114, 92, 180, 114, 92, 180, 118, 92, + 188, 118, 92, 188, 118, 100, 188, 118, 92, 180, 114, 92, 180, 110, 84, + 180, 110, 92, 180, 114, 84, 180, 114, 92, 180, 114, 92, 188, 118, 92, + 188, 118, 100, 188, 118, 92, 188, 118, 100, 188, 118, 92, 188, 118, 100, + 188, 122, 92, 188, 122, 100, 188, 122, 100, 188, 122, 100, 188, 122, 100, + 196, 122, 100, 188, 126, 100, 188, 122, 100, 188, 122, 92, 188, 122, 100, + 196, 122, 100, 188, 126, 100, 196, 122, 100, 188, 118, 92, 180, 118, 92, + 188, 118, 100, 188, 118, 92, 188, 122, 100, 188, 122, 100, 188, 122, 100, + 188, 122, 100, 188, 122, 100, 188, 118, 92, 188, 118, 100, 180, 114, 92, + 180, 110, 84, 180, 110, 92, 188, 118, 92, 180, 114, 92, 180, 110, 92, + 188, 118, 92, 180, 118, 92, 188, 114, 92, 180, 114, 92, 180, 110, 92, + 180, 110, 84, 180, 110, 84, 180, 110, 84, 180, 110, 84, 180, 110, 84, + 180, 106, 84, 180, 110, 84, 180, 110, 92, 180, 110, 84, 180, 110, 92, + 180, 110, 92, 172, 106, 84, 180, 110, 84, 180, 114, 92, 180, 110, 92, + 172, 110, 84, 172, 110, 84, 180, 110, 92, 188, 118, 92, 188, 118, 92, + 180, 114, 92, 188, 118, 100, 188, 118, 92, 180, 110, 92, 180, 114, 84, + 188, 118, 100, 180, 114, 92, 180, 110, 92, 172, 110, 92, 172, 110, 92, + 172, 110, 92, 172, 110, 92, 172, 102, 84, 164, 98, 76, 156, 94, 76, + 156, 94, 68, 172, 102, 76, 172, 110, 92, 172, 110, 84, 172, 106, 92, + 172, 110, 84, 172, 106, 84, 172, 106, 84, 172, 106, 84, 180, 106, 92, + 172, 106, 84, 172, 106, 92, 172, 102, 84, 172, 102, 84, 172, 106, 92, + 172, 106, 84, 172, 102, 84, 172, 102, 84, 172, 102, 84, 172, 102, 84, + 172, 106, 84, 172, 102, 84, 172, 106, 92, 172, 102, 84, 164, 98, 76, + 164, 102, 84, 164, 102, 84, 164, 102, 76, 164, 98, 76, 164, 98, 76, + 164, 98, 84, 164, 98, 76, 164, 98, 76, 164, 98, 76, 164, 102, 84, + 172, 102, 84, 164, 102, 84, 164, 102, 84, 164, 102, 84, 164, 98, 76, + 172, 102, 84, 172, 102, 84, 172, 102, 84, 164, 98, 84, 164, 102, 76, + 164, 98, 76, 164, 98, 76, 164, 98, 76, 172, 98, 84, 172, 98, 76, + 172, 98, 84, 164, 94, 84, 172, 110, 92, 172, 110, 100, 116, 62, 52, + 92, 34, 12, 92, 34, 20, 148, 90, 68, 172, 106, 84, 172, 110, 92, + 172, 106, 84, 172, 110, 84, 180, 110, 92, 164, 102, 84, 172, 106, 84, + 172, 106, 84, 172, 106, 84, 164, 102, 84, 172, 106, 84, 172, 106, 84, + 172, 110, 92, 172, 106, 84, 172, 106, 92, 172, 106, 84, 172, 102, 84, + 172, 106, 84, 172, 106, 84, 180, 110, 92, 180, 110, 92, 180, 110, 92, + 180, 110, 92, 188, 118, 100, 188, 114, 100, 180, 114, 92, 180, 110, 92, + 180, 110, 92, 172, 110, 92, 180, 110, 92, 172, 106, 84, 188, 118, 100, + 188, 118, 92, 196, 122, 100, 196, 126, 108, 204, 130, 108, 188, 122, 100, + 188, 118, 100, 180, 118, 92, 180, 114, 92, 188, 122, 100, 196, 122, 100, + 188, 122, 100, 188, 118, 92, 180, 110, 92, 196, 122, 100, 188, 126, 100, + 196, 126, 100, 188, 122, 100, 188, 122, 100, 196, 126, 100, 196, 126, 108, + 196, 130, 108, 196, 130, 108, 196, 126, 100, 196, 126, 108, 196, 130, 108, + 196, 134, 108, 204, 134, 108, 196, 130, 108, 188, 126, 108, 188, 118, 92, + 180, 114, 92, 180, 106, 84, 180, 110, 84, 180, 114, 92, 180, 118, 92, + 188, 118, 92, 180, 118, 92, 188, 126, 100, 188, 122, 100, 196, 126, 100, + 196, 126, 100, 196, 126, 100, 196, 130, 108, 204, 130, 108, 196, 130, 108, + 196, 122, 100, 188, 122, 100, 188, 118, 100, 188, 118, 92, 188, 122, 100, + 188, 122, 100, 188, 122, 100, 188, 118, 100, 180, 118, 100, 188, 118, 92, + 180, 114, 92, 188, 118, 92, 188, 118, 100, 188, 122, 92, 188, 122, 100, + 196, 122, 100, 180, 118, 92, 188, 118, 92, 180, 114, 92, 172, 110, 84, + 180, 110, 84, 180, 114, 92, 188, 118, 92, 180, 114, 92, 180, 118, 92, + 188, 114, 92, 180, 114, 92, 180, 114, 92, 180, 114, 92, 180, 114, 92, + 180, 114, 92, 180, 110, 92, 180, 114, 92, 180, 110, 92, 180, 114, 92, + 180, 110, 92, 180, 114, 84, 180, 110, 92, 180, 110, 84, 180, 114, 84, + 180, 110, 92, 180, 114, 92, 180, 114, 92, 180, 110, 84, 180, 110, 92, + 180, 114, 84, 180, 114, 92, 180, 118, 92, 180, 110, 92, 172, 106, 84, + 180, 110, 84, 180, 110, 84, 164, 102, 76, 172, 102, 84, 180, 110, 84, + 172, 110, 84, 172, 106, 84, 172, 106, 84, 172, 102, 84, 172, 106, 84, + 172, 110, 84, 172, 106, 92, 172, 106, 84, 164, 98, 76, 180, 118, 100, + 188, 122, 100, 188, 118, 100, 188, 118, 100, 180, 114, 92, 172, 106, 92, + 172, 106, 84, 164, 102, 84, 180, 106, 84, 172, 106, 92, 180, 110, 92, + 172, 106, 84, 172, 102, 84, 172, 102, 84, 172, 102, 84, 172, 106, 92, + 172, 98, 84, 164, 102, 84, 172, 102, 84, 172, 102, 84, 172, 106, 92, + 180, 106, 84, 172, 110, 92, 180, 106, 92, 164, 98, 76, 164, 98, 76, + 164, 98, 76, 164, 98, 76, 156, 94, 76, 156, 94, 76, 156, 94, 76, + 164, 98, 76, 164, 98, 84, 164, 98, 76, 172, 102, 84, 164, 102, 84, + 172, 102, 84, 164, 102, 84, 164, 98, 76, 156, 94, 76, 172, 102, 84, + 172, 102, 92, 164, 102, 84, 172, 102, 84, 164, 106, 84, 164, 106, 84, + 164, 102, 76, 172, 102, 84, 164, 98, 76, 172, 102, 84, 172, 102, 84, + 164, 94, 84, 172, 106, 92, 164, 106, 92, 116, 62, 52, 92, 34, 20, + 100, 46, 28, 148, 86, 76, 164, 98, 76, 164, 98, 76, 156, 90, 76, + 164, 98, 76, 164, 102, 84, 172, 102, 84, 172, 106, 84, 164, 102, 84, + 164, 102, 84, 164, 98, 76, 164, 98, 84, 172, 106, 84, 172, 110, 92, + 180, 110, 92, 172, 110, 84, 180, 110, 92, 180, 106, 92, 172, 106, 84, + 180, 110, 92, 180, 110, 92, 180, 114, 92, 180, 110, 92, 172, 110, 92, + 172, 106, 84, 172, 102, 84, 164, 102, 84, 172, 106, 84, 180, 106, 92, + 180, 110, 84, 172, 106, 84, 172, 102, 84, 180, 110, 92, 172, 102, 76, + 172, 98, 76, 172, 106, 84, 180, 106, 84, 172, 98, 76, 164, 98, 76, + 164, 94, 76, 164, 98, 76, 172, 102, 76, 172, 110, 84, 172, 106, 84, + 172, 98, 76, 156, 94, 68, 164, 94, 68, 164, 94, 76, 164, 98, 76, + 164, 94, 68, 164, 94, 68, 156, 90, 68, 164, 94, 68, 164, 98, 76, + 164, 98, 76, 164, 98, 76, 164, 98, 76, 172, 102, 76, 172, 106, 84, + 172, 106, 84, 172, 102, 76, 164, 98, 76, 172, 106, 84, 164, 98, 76, + 148, 86, 60, 148, 82, 60, 156, 90, 68, 164, 94, 76, 164, 98, 76, + 164, 94, 76, 172, 98, 76, 164, 98, 76, 164, 98, 76, 172, 102, 84, + 172, 102, 76, 172, 106, 84, 172, 106, 84, 180, 110, 84, 172, 106, 84, + 172, 102, 76, 172, 102, 76, 172, 102, 76, 172, 106, 84, 172, 106, 84, + 172, 102, 76, 172, 102, 76, 172, 106, 84, 172, 102, 84, 172, 102, 76, + 164, 102, 84, 172, 102, 76, 172, 106, 84, 180, 110, 84, 180, 114, 92, + 172, 102, 76, 172, 106, 84, 172, 102, 84, 164, 94, 76, 164, 98, 76, + 172, 102, 76, 172, 102, 84, 172, 102, 76, 164, 98, 76, 172, 98, 76, + 164, 102, 76, 172, 102, 76, 164, 98, 76, 172, 102, 76, 164, 102, 76, + 172, 102, 76, 172, 102, 76, 164, 102, 76, 172, 102, 76, 164, 102, 76, + 172, 98, 76, 164, 98, 76, 164, 102, 76, 164, 98, 76, 172, 102, 84, + 172, 102, 76, 172, 102, 76, 164, 98, 76, 172, 102, 76, 172, 102, 84, + 172, 102, 76, 172, 102, 84, 172, 102, 76, 164, 98, 76, 164, 98, 76, + 164, 102, 76, 156, 90, 68, 164, 94, 68, 164, 98, 76, 164, 98, 76, + 164, 94, 76, 156, 94, 76, 156, 94, 76, 164, 94, 76, 164, 98, 76, + 164, 102, 84, 164, 102, 76, 164, 98, 84, 164, 94, 76, 156, 90, 68, + 156, 90, 76, 156, 94, 68, 156, 94, 76, 156, 90, 68, 156, 90, 68, + 156, 94, 76, 156, 86, 68, 156, 90, 68, 164, 98, 76, 164, 94, 76, + 164, 94, 76, 164, 98, 76, 172, 102, 84, 180, 114, 92, 164, 102, 76, + 172, 102, 84, 172, 102, 84, 172, 106, 84, 172, 106, 84, 180, 110, 92, + 180, 110, 92, 180, 114, 92, 172, 106, 92, 180, 110, 92, 172, 110, 92, + 180, 110, 92, 172, 106, 84, 172, 106, 84, 172, 106, 84, 172, 110, 92, + 172, 110, 84, 172, 110, 92, 180, 114, 92, 180, 114, 92, 180, 114, 92, + 172, 110, 92, 172, 110, 84, 172, 106, 84, 172, 102, 92, 172, 106, 84, + 172, 106, 92, 172, 110, 92, 172, 110, 92, 172, 110, 92, 180, 106, 84, + 172, 106, 84, 180, 106, 92, 180, 110, 92, 180, 110, 100, 172, 102, 84, + 180, 114, 100, 172, 110, 100, 124, 66, 52, 100, 46, 28, 100, 42, 28, + 148, 78, 68, 156, 90, 68, 156, 94, 76, 164, 98, 76, 164, 98, 76, + 164, 98, 76, 156, 90, 68, 148, 82, 60, 148, 82, 68, 148, 86, 60, + 148, 82, 68, 148, 86, 60, 148, 86, 68, 156, 90, 68, 148, 86, 68, + 156, 90, 68, 156, 90, 68, 164, 94, 76, 164, 98, 84, 164, 98, 76, + 156, 94, 76, 164, 94, 76, 164, 98, 76, 164, 98, 76, 172, 102, 84, + 156, 90, 68, 164, 94, 76, 164, 98, 76, 164, 94, 76, 156, 86, 68, + 156, 94, 76, 180, 110, 92, 172, 98, 76, 172, 102, 76, 172, 102, 84, + 164, 98, 76, 172, 98, 76, 180, 110, 84, 188, 122, 100, 188, 118, 92, + 180, 114, 92, 188, 118, 100, 188, 118, 92, 188, 122, 100, 180, 114, 92, + 180, 110, 92, 172, 102, 76, 172, 106, 84, 188, 118, 92, 188, 122, 100, + 188, 122, 100, 188, 118, 92, 188, 118, 100, 188, 118, 92, 172, 102, 76, + 172, 102, 76, 180, 106, 84, 180, 110, 92, 180, 114, 92, 188, 118, 92, + 188, 114, 92, 180, 114, 92, 188, 114, 92, 188, 118, 100, 188, 118, 92, + 180, 114, 92, 172, 102, 76, 164, 98, 76, 172, 102, 76, 172, 106, 84, + 180, 110, 84, 172, 110, 84, 172, 102, 84, 172, 102, 76, 164, 98, 76, + 172, 102, 76, 172, 106, 76, 172, 102, 84, 172, 102, 76, 172, 106, 84, + 180, 110, 92, 180, 114, 92, 180, 110, 84, 172, 110, 84, 180, 106, 84, + 180, 110, 92, 172, 106, 76, 172, 110, 84, 180, 110, 92, 180, 110, 84, + 180, 106, 84, 172, 106, 84, 180, 106, 84, 172, 110, 84, 180, 110, 84, + 172, 102, 84, 172, 102, 76, 172, 102, 76, 164, 94, 68, 164, 98, 76, + 172, 102, 76, 164, 94, 76, 172, 102, 76, 164, 98, 76, 164, 94, 76, + 164, 98, 76, 172, 102, 76, 172, 102, 84, 172, 102, 76, 164, 98, 76, + 164, 102, 84, 172, 98, 76, 164, 98, 76, 172, 102, 76, 164, 98, 76, + 156, 90, 68, 156, 90, 68, 164, 94, 76, 172, 102, 76, 172, 106, 84, + 172, 106, 84, 164, 98, 76, 164, 98, 76, 172, 102, 76, 172, 102, 76, + 164, 98, 76, 164, 102, 76, 164, 98, 76, 172, 102, 76, 172, 102, 84, + 164, 94, 68, 164, 94, 76, 172, 102, 76, 164, 98, 76, 164, 102, 76, + 164, 94, 76, 156, 90, 68, 156, 94, 76, 164, 98, 76, 156, 94, 76, + 156, 90, 68, 156, 94, 76, 156, 90, 68, 156, 94, 76, 164, 98, 76, + 164, 98, 76, 156, 94, 76, 156, 86, 68, 148, 86, 68, 148, 82, 60, + 156, 86, 68, 156, 86, 68, 156, 86, 68, 156, 86, 68, 156, 82, 60, + 148, 86, 68, 156, 86, 68, 156, 90, 76, 156, 90, 68, 156, 86, 68, + 148, 78, 60, 148, 82, 60, 156, 86, 68, 156, 90, 76, 156, 90, 68, + 156, 86, 68, 148, 86, 60, 156, 86, 68, 148, 86, 68, 148, 86, 68, + 156, 90, 68, 156, 90, 68, 164, 94, 76, 156, 94, 76, 156, 86, 68, + 156, 90, 68, 156, 90, 68, 156, 90, 76, 156, 90, 68, 156, 90, 68, + 156, 86, 68, 148, 86, 68, 156, 86, 68, 156, 86, 68, 156, 90, 68, + 156, 90, 76, 164, 98, 76, 164, 102, 76, 164, 102, 84, 172, 106, 84, + 172, 102, 84, 164, 90, 76, 172, 102, 84, 172, 102, 84, 164, 102, 92, + 164, 102, 92, 124, 70, 60, 100, 42, 28, 84, 30, 12, 132, 70, 52, + 140, 74, 60, 148, 78, 60, 140, 74, 52, 140, 74, 60, 140, 78, 60, + 140, 78, 60, 140, 74, 52, 148, 78, 60, 148, 82, 60, 148, 82, 60, + 148, 82, 68, 156, 86, 60, 156, 90, 68, 156, 90, 68, 156, 90, 76, + 148, 82, 68, 156, 90, 68, 156, 90, 68, 164, 90, 68, 156, 90, 68, + 156, 86, 68, 156, 90, 68, 164, 90, 76, 172, 102, 84, 156, 94, 76, + 156, 90, 68, 172, 98, 84, 164, 102, 84, 164, 94, 76, 164, 94, 76, + 172, 102, 84, 180, 110, 84, 180, 110, 92, 188, 114, 92, 180, 110, 84, + 180, 110, 92, 188, 114, 92, 188, 118, 92, 188, 118, 92, 180, 118, 92, + 188, 114, 92, 188, 118, 92, 180, 118, 92, 180, 114, 92, 180, 110, 84, + 180, 114, 92, 180, 118, 92, 188, 118, 100, 180, 114, 92, 180, 114, 92, + 180, 114, 92, 188, 118, 92, 188, 122, 100, 180, 114, 92, 180, 114, 92, + 180, 110, 84, 180, 114, 92, 180, 114, 92, 180, 114, 92, 172, 110, 84, + 172, 102, 84, 172, 106, 76, 180, 110, 92, 188, 118, 92, 188, 118, 100, + 188, 118, 92, 180, 114, 92, 180, 110, 92, 180, 114, 92, 180, 110, 84, + 180, 106, 84, 180, 110, 92, 180, 114, 92, 180, 114, 92, 180, 110, 92, + 180, 110, 84, 172, 110, 84, 172, 102, 84, 172, 106, 84, 180, 110, 84, + 180, 114, 92, 180, 110, 92, 180, 114, 92, 180, 110, 84, 180, 110, 92, + 172, 106, 84, 180, 106, 84, 180, 110, 84, 172, 110, 84, 172, 106, 84, + 172, 106, 84, 180, 106, 84, 180, 110, 92, 180, 110, 92, 172, 106, 76, + 172, 106, 84, 172, 106, 84, 164, 94, 76, 164, 98, 76, 172, 106, 84, + 172, 102, 76, 172, 102, 76, 164, 102, 76, 172, 98, 76, 164, 102, 76, + 172, 102, 84, 172, 106, 76, 172, 102, 84, 172, 102, 76, 172, 102, 76, + 164, 102, 84, 172, 102, 76, 172, 102, 84, 172, 102, 76, 164, 94, 68, + 164, 94, 76, 172, 102, 76, 172, 106, 84, 180, 106, 84, 172, 106, 84, + 172, 102, 76, 172, 102, 76, 172, 106, 84, 172, 106, 84, 172, 102, 76, + 172, 102, 76, 164, 98, 76, 172, 102, 84, 172, 106, 76, 164, 94, 76, + 164, 98, 76, 172, 102, 76, 164, 98, 76, 172, 102, 84, 164, 98, 76, + 156, 94, 76, 164, 102, 84, 172, 102, 84, 164, 98, 76, 164, 98, 76, + 164, 98, 76, 156, 94, 76, 164, 94, 76, 164, 98, 76, 164, 102, 84, + 164, 98, 76, 164, 98, 76, 164, 98, 76, 164, 102, 84, 164, 94, 76, + 156, 94, 76, 164, 94, 76, 156, 94, 76, 156, 90, 68, 156, 86, 68, + 156, 90, 68, 164, 94, 76, 164, 94, 76, 156, 90, 68, 156, 86, 68, + 156, 86, 68, 156, 94, 76, 164, 98, 76, 164, 94, 76, 156, 90, 76, + 156, 86, 68, 148, 90, 68, 156, 90, 68, 156, 94, 68, 156, 94, 76, + 156, 94, 76, 156, 94, 76, 156, 94, 68, 156, 94, 76, 156, 94, 76, + 164, 94, 76, 156, 98, 76, 164, 94, 76, 156, 94, 76, 156, 90, 68, + 156, 90, 68, 164, 94, 84, 156, 94, 76, 164, 98, 84, 164, 98, 76, + 164, 102, 76, 156, 98, 76, 164, 98, 76, 164, 94, 68, 156, 82, 68, + 132, 66, 44, 140, 70, 52, 148, 78, 68, 156, 90, 76, 156, 102, 84, + 124, 66, 52, 84, 30, 12, 92, 38, 28, 132, 66, 52, 140, 74, 52, + 132, 74, 60, 132, 66, 44, 124, 66, 44, 140, 70, 52, 140, 78, 60, + 148, 82, 60, 148, 82, 68, 148, 86, 60, 148, 86, 68, 156, 86, 68, + 148, 90, 68, 156, 90, 76, 156, 94, 68, 156, 94, 76, 164, 90, 68, + 164, 94, 76, 164, 98, 76, 164, 98, 84, 172, 98, 84, 164, 98, 84, + 172, 98, 76, 164, 102, 84, 172, 102, 84, 172, 98, 84, 164, 98, 76, + 172, 102, 84, 180, 110, 84, 180, 110, 92, 172, 110, 92, 172, 102, 76, + 180, 106, 92, 180, 110, 84, 180, 110, 84, 180, 110, 92, 180, 106, 84, + 172, 102, 84, 180, 118, 92, 188, 114, 92, 180, 114, 92, 180, 114, 92, + 180, 114, 92, 188, 114, 92, 180, 110, 92, 172, 110, 84, 188, 118, 100, + 188, 118, 92, 188, 114, 92, 180, 114, 92, 180, 110, 84, 180, 110, 92, + 180, 114, 92, 188, 118, 92, 188, 114, 92, 180, 114, 92, 180, 114, 92, + 180, 114, 92, 180, 114, 92, 180, 110, 84, 172, 102, 84, 172, 102, 76, + 172, 102, 76, 172, 110, 84, 188, 118, 100, 188, 122, 100, 188, 118, 92, + 188, 118, 100, 188, 122, 92, 188, 122, 100, 172, 110, 84, 180, 110, 92, + 180, 114, 84, 180, 114, 92, 188, 114, 92, 180, 118, 92, 188, 114, 92, + 180, 118, 92, 180, 106, 84, 172, 106, 84, 180, 106, 84, 180, 114, 84, + 180, 114, 92, 188, 114, 92, 180, 114, 92, 180, 114, 84, 172, 106, 84, + 180, 106, 84, 172, 110, 92, 180, 110, 84, 180, 106, 84, 172, 106, 84, + 172, 106, 84, 172, 110, 84, 180, 110, 84, 172, 106, 84, 172, 106, 84, + 172, 106, 84, 164, 94, 68, 164, 98, 76, 180, 106, 84, 172, 110, 84, + 172, 102, 84, 172, 102, 84, 164, 102, 76, 172, 102, 76, 172, 106, 84, + 172, 106, 84, 172, 106, 84, 172, 102, 84, 172, 102, 84, 172, 102, 76, + 172, 106, 84, 172, 106, 84, 172, 102, 84, 164, 98, 76, 172, 102, 76, + 172, 106, 84, 180, 110, 84, 180, 114, 92, 180, 110, 84, 172, 106, 84, + 172, 106, 84, 180, 110, 92, 180, 110, 84, 172, 110, 84, 172, 102, 84, + 172, 102, 76, 172, 106, 84, 180, 110, 84, 164, 98, 76, 164, 98, 76, + 172, 106, 84, 164, 102, 76, 172, 102, 84, 164, 98, 84, 164, 98, 76, + 172, 106, 84, 172, 110, 84, 172, 102, 84, 164, 102, 84, 164, 102, 84, + 172, 106, 84, 164, 102, 84, 164, 102, 84, 172, 102, 84, 164, 102, 84, + 156, 94, 76, 164, 98, 76, 172, 106, 84, 172, 102, 76, 164, 98, 84, + 172, 102, 84, 164, 98, 76, 164, 94, 76, 164, 94, 76, 164, 98, 76, + 164, 98, 84, 164, 98, 76, 164, 94, 76, 156, 94, 76, 164, 94, 76, + 172, 102, 84, 172, 102, 84, 164, 98, 76, 164, 94, 76, 156, 86, 68, + 156, 90, 68, 164, 94, 76, 164, 98, 84, 164, 98, 76, 164, 98, 76, + 164, 94, 76, 164, 94, 76, 164, 98, 84, 164, 102, 76, 164, 98, 76, + 164, 102, 84, 164, 98, 76, 164, 98, 76, 164, 98, 76, 164, 94, 76, + 164, 98, 84, 172, 102, 84, 172, 102, 84, 172, 106, 92, 164, 102, 84, + 164, 98, 76, 156, 94, 68, 156, 90, 68, 156, 86, 68, 132, 62, 44, + 140, 66, 52, 140, 74, 60, 156, 94, 84, 172, 110, 100, 132, 74, 60, + 92, 38, 28, 116, 58, 44, 164, 106, 84, 180, 114, 92, 180, 114, 92, + 172, 106, 84, 172, 106, 84, 172, 110, 92, 188, 122, 100, 188, 126, 100, + 180, 114, 92, 180, 114, 100, 180, 114, 92, 180, 114, 92, 180, 114, 92, + 180, 110, 92, 172, 110, 92, 180, 110, 92, 164, 102, 84, 172, 106, 84, + 180, 106, 92, 180, 110, 92, 180, 114, 92, 180, 110, 92, 180, 114, 92, + 180, 110, 92, 172, 110, 84, 180, 114, 92, 180, 114, 100, 180, 114, 92, + 180, 114, 100, 188, 122, 100, 188, 122, 100, 188, 114, 92, 180, 114, 92, + 188, 114, 92, 188, 114, 92, 188, 122, 100, 188, 114, 92, 180, 110, 84, + 180, 110, 92, 180, 110, 84, 180, 110, 92, 180, 114, 92, 180, 114, 92, + 180, 110, 84, 180, 110, 92, 180, 110, 84, 180, 114, 92, 180, 114, 92, + 180, 114, 92, 180, 114, 92, 180, 110, 84, 180, 110, 92, 180, 110, 84, + 180, 110, 92, 172, 110, 84, 172, 106, 84, 180, 106, 84, 180, 110, 84, + 180, 110, 84, 180, 110, 84, 172, 106, 84, 172, 102, 76, 180, 110, 92, + 180, 114, 92, 180, 114, 92, 180, 114, 92, 180, 110, 84, 180, 114, 92, + 188, 118, 92, 188, 122, 100, 188, 114, 92, 180, 110, 84, 172, 106, 84, + 172, 106, 84, 172, 106, 84, 180, 110, 84, 180, 114, 92, 188, 118, 92, + 180, 110, 92, 180, 114, 84, 180, 110, 92, 180, 114, 92, 180, 114, 92, + 180, 114, 92, 180, 110, 84, 172, 106, 84, 172, 102, 84, 172, 106, 76, + 172, 106, 84, 172, 106, 84, 172, 102, 76, 172, 102, 76, 172, 106, 84, + 180, 106, 84, 172, 110, 84, 172, 102, 84, 180, 110, 84, 172, 106, 84, + 164, 94, 68, 164, 98, 76, 172, 106, 84, 180, 110, 84, 172, 106, 84, + 172, 102, 76, 172, 102, 76, 172, 102, 84, 172, 106, 84, 172, 106, 84, + 172, 106, 76, 172, 102, 76, 172, 102, 84, 164, 102, 76, 172, 102, 84, + 172, 106, 84, 172, 106, 84, 172, 102, 76, 172, 102, 84, 180, 110, 84, + 180, 110, 92, 180, 114, 84, 180, 110, 92, 172, 106, 84, 180, 106, 84, + 172, 110, 84, 180, 106, 84, 172, 110, 92, 180, 106, 84, 172, 106, 84, + 180, 110, 84, 172, 106, 84, 164, 98, 76, 172, 98, 76, 180, 110, 84, + 172, 106, 84, 172, 102, 84, 164, 98, 76, 164, 102, 84, 172, 106, 84, + 172, 110, 92, 172, 106, 84, 172, 102, 84, 164, 102, 84, 172, 106, 84, + 164, 98, 76, 164, 98, 76, 164, 102, 84, 164, 98, 76, 156, 90, 68, + 156, 90, 68, 164, 98, 84, 164, 98, 84, 172, 102, 76, 172, 102, 84, + 164, 102, 84, 164, 98, 76, 164, 98, 84, 172, 102, 84, 172, 106, 84, + 172, 98, 84, 164, 98, 76, 164, 98, 76, 172, 98, 84, 172, 106, 84, + 172, 106, 84, 164, 98, 84, 164, 94, 76, 156, 94, 76, 164, 98, 76, + 164, 98, 76, 164, 102, 76, 164, 102, 84, 164, 98, 76, 164, 98, 76, + 156, 94, 76, 164, 102, 76, 172, 102, 84, 164, 102, 84, 164, 102, 76, + 164, 102, 84, 164, 98, 84, 164, 98, 76, 164, 98, 84, 164, 98, 84, + 164, 98, 84, 172, 102, 84, 164, 102, 84, 172, 106, 84, 164, 102, 84, + 164, 98, 76, 164, 98, 76, 172, 102, 84, 164, 90, 68, 164, 90, 76, + 164, 94, 76, 164, 102, 92, 172, 114, 100, 140, 82, 68, 116, 58, 44, + 116, 62, 52, 148, 86, 68, 164, 98, 76, 164, 102, 84, 164, 98, 76, + 156, 94, 76, 164, 98, 76, 164, 102, 84, 172, 102, 84, 164, 102, 84, + 164, 102, 76, 164, 102, 84, 164, 98, 84, 164, 98, 76, 164, 102, 84, + 164, 98, 76, 164, 98, 76, 172, 102, 84, 172, 102, 84, 172, 106, 84, + 180, 110, 84, 172, 110, 92, 180, 110, 84, 172, 106, 92, 172, 106, 84, + 164, 90, 76, 172, 106, 84, 180, 110, 92, 172, 98, 84, 164, 98, 76, + 172, 106, 84, 180, 110, 92, 180, 114, 92, 180, 110, 92, 180, 110, 84, + 188, 114, 92, 188, 118, 100, 188, 114, 92, 180, 110, 84, 172, 106, 84, + 172, 106, 84, 172, 106, 84, 180, 110, 84, 180, 110, 84, 180, 114, 92, + 180, 110, 84, 180, 114, 92, 180, 106, 84, 172, 110, 84, 180, 106, 84, + 172, 106, 84, 180, 110, 84, 172, 110, 84, 180, 110, 84, 172, 110, 84, + 172, 102, 76, 172, 102, 76, 172, 102, 76, 172, 102, 84, 172, 110, 92, + 180, 110, 84, 172, 106, 84, 172, 102, 84, 172, 110, 84, 180, 110, 84, + 180, 110, 84, 180, 110, 84, 172, 106, 84, 172, 106, 84, 180, 110, 84, + 180, 110, 92, 180, 114, 92, 180, 114, 92, 172, 106, 84, 172, 102, 84, + 172, 102, 76, 172, 106, 84, 180, 106, 84, 180, 114, 92, 180, 114, 92, + 180, 114, 92, 180, 110, 84, 180, 110, 84, 180, 110, 92, 180, 114, 84, + 172, 106, 84, 172, 106, 84, 172, 102, 76, 172, 102, 76, 172, 102, 84, + 172, 102, 76, 164, 98, 76, 164, 98, 76, 172, 102, 76, 172, 106, 84, + 172, 102, 84, 172, 102, 76, 172, 106, 84, 172, 102, 76, 156, 90, 68, + 164, 94, 68, 172, 106, 84, 172, 106, 84, 172, 102, 76, 172, 98, 76, + 164, 98, 76, 164, 98, 76, 172, 102, 76, 172, 102, 76, 172, 102, 84, + 164, 102, 76, 172, 102, 76, 164, 98, 76, 172, 102, 76, 180, 106, 84, + 172, 106, 84, 164, 102, 76, 172, 102, 76, 172, 110, 92, 180, 110, 84, + 172, 110, 84, 172, 106, 84, 172, 106, 84, 172, 106, 84, 172, 106, 84, + 172, 106, 84, 172, 106, 84, 180, 114, 84, 172, 106, 84, 180, 106, 84, + 172, 106, 84, 164, 94, 68, 164, 98, 76, 180, 110, 84, 180, 114, 92, + 164, 98, 84, 156, 98, 76, 164, 98, 76, 172, 106, 84, 172, 110, 92, + 172, 106, 84, 164, 102, 76, 164, 102, 84, 156, 90, 68, 156, 90, 68, + 156, 94, 76, 164, 102, 76, 164, 98, 76, 156, 94, 76, 164, 98, 76, + 164, 102, 84, 164, 98, 76, 164, 98, 76, 164, 98, 84, 172, 98, 76, + 164, 98, 84, 172, 98, 76, 172, 102, 84, 172, 106, 92, 164, 98, 76, + 164, 94, 76, 164, 98, 76, 164, 98, 84, 172, 106, 84, 172, 102, 84, + 164, 98, 76, 156, 90, 68, 164, 98, 76, 164, 98, 76, 164, 98, 84, + 164, 98, 76, 164, 98, 84, 164, 102, 76, 164, 98, 84, 164, 102, 76, + 172, 102, 84, 164, 102, 84, 164, 98, 76, 164, 98, 84, 164, 98, 76, + 164, 98, 76, 164, 102, 76, 164, 98, 76, 164, 98, 84, 172, 98, 84, + 164, 102, 84, 164, 102, 84, 164, 102, 84, 164, 106, 84, 172, 102, 84, + 172, 106, 84, 172, 102, 84, 172, 102, 84, 172, 102, 92, 164, 98, 84, + 164, 102, 92, 156, 98, 84, 132, 74, 60, 116, 62, 52, 116, 58, 44, + 148, 86, 68, 164, 94, 76, 164, 102, 84, 164, 102, 76, 164, 98, 76, + 164, 98, 76, 164, 102, 84, 164, 98, 76, 172, 106, 84, 172, 106, 84, + 172, 106, 92, 172, 110, 84, 172, 110, 92, 180, 110, 92, 180, 114, 92, + 180, 114, 92, 164, 102, 84, 172, 102, 84, 172, 106, 84, 172, 106, 92, + 180, 110, 92, 180, 110, 92, 172, 106, 84, 172, 102, 84, 164, 98, 84, + 180, 114, 92, 188, 122, 100, 180, 114, 92, 172, 102, 84, 180, 106, 92, + 188, 118, 100, 188, 122, 100, 172, 102, 84, 172, 106, 84, 180, 106, 84, + 180, 110, 84, 180, 110, 84, 180, 106, 92, 172, 102, 76, 172, 102, 84, + 180, 110, 84, 180, 110, 84, 180, 110, 92, 180, 110, 84, 180, 114, 92, + 180, 114, 92, 180, 110, 84, 172, 106, 84, 172, 102, 76, 164, 98, 76, + 172, 102, 84, 172, 106, 84, 180, 110, 92, 180, 114, 92, 172, 102, 84, + 172, 102, 84, 172, 106, 84, 172, 106, 84, 180, 106, 84, 172, 106, 84, + 172, 102, 76, 164, 98, 76, 172, 102, 76, 172, 102, 84, 172, 106, 84, + 180, 110, 92, 180, 110, 84, 180, 110, 84, 172, 106, 84, 172, 106, 84, + 180, 110, 84, 180, 114, 92, 180, 114, 92, 188, 114, 92, 180, 114, 92, + 180, 110, 92, 172, 110, 84, 172, 106, 84, 180, 114, 92, 180, 110, 92, + 180, 110, 84, 172, 110, 84, 180, 110, 84, 172, 106, 84, 172, 106, 84, + 172, 102, 76, 172, 102, 84, 172, 102, 84, 172, 106, 76, 164, 98, 76, + 164, 98, 76, 172, 98, 76, 172, 102, 84, 172, 106, 84, 172, 106, 76, + 164, 98, 76, 172, 106, 84, 172, 102, 84, 164, 94, 68, 164, 94, 76, + 172, 102, 76, 172, 102, 76, 164, 102, 84, 172, 102, 76, 164, 98, 76, + 172, 102, 76, 172, 102, 84, 172, 106, 84, 172, 102, 76, 172, 102, 84, + 164, 102, 76, 172, 98, 76, 164, 102, 76, 172, 106, 84, 172, 102, 76, + 172, 102, 76, 172, 102, 84, 180, 110, 84, 180, 110, 84, 172, 102, 84, + 172, 102, 76, 172, 106, 84, 172, 106, 76, 172, 102, 76, 172, 102, 84, + 172, 106, 84, 180, 110, 84, 172, 106, 84, 180, 110, 84, 172, 102, 84, + 156, 90, 68, 164, 94, 68, 172, 110, 84, 180, 114, 92, 172, 102, 76, + 164, 94, 76, 164, 98, 76, 164, 102, 84, 172, 106, 84, 164, 102, 84, + 164, 98, 76, 164, 98, 84, 156, 94, 76, 164, 98, 76, 164, 98, 84, + 164, 102, 84, 164, 98, 76, 164, 98, 84, 164, 102, 76, 164, 102, 84, + 164, 94, 76, 164, 94, 76, 164, 98, 76, 164, 98, 84, 164, 98, 76, + 164, 98, 76, 172, 102, 84, 172, 106, 84, 164, 98, 76, 164, 98, 76, + 164, 94, 76, 164, 98, 76, 172, 102, 84, 172, 102, 84, 164, 94, 76, + 156, 90, 68, 164, 98, 84, 164, 98, 76, 164, 98, 76, 164, 98, 76, + 164, 98, 76, 164, 98, 84, 164, 102, 84, 172, 102, 84, 164, 102, 84, + 164, 98, 76, 164, 98, 84, 164, 98, 76, 164, 98, 76, 164, 98, 84, + 164, 98, 76, 164, 98, 84, 172, 102, 84, 164, 102, 84, 172, 102, 84, + 164, 98, 84, 164, 102, 76, 164, 98, 76, 164, 102, 76, 164, 98, 76, + 172, 98, 84, 164, 98, 76, 172, 98, 84, 164, 94, 76, 164, 98, 84, + 156, 98, 84, 124, 70, 60, 116, 58, 44, 116, 62, 44, 164, 98, 76, + 164, 102, 84, 172, 106, 84, 164, 98, 84, 164, 102, 84, 172, 102, 84, + 172, 106, 84, 164, 102, 84, 164, 98, 84, 164, 98, 76, 164, 102, 84, + 172, 102, 84, 172, 106, 84, 172, 110, 84, 172, 110, 92, 180, 110, 92, + 172, 110, 92, 180, 110, 92, 180, 110, 92, 180, 114, 92, 180, 114, 92, + 180, 114, 92, 180, 106, 92, 164, 102, 84, 180, 106, 84, 180, 114, 100, + 188, 118, 100, 188, 118, 100, 180, 114, 92, 180, 110, 92, 180, 118, 100, + 188, 118, 100, 188, 114, 92, 188, 118, 100, 188, 118, 92, 188, 118, 100, + 188, 114, 92, 188, 122, 100, 172, 106, 84, 172, 106, 84, 180, 110, 84, + 172, 110, 92, 180, 110, 84, 172, 106, 84, 172, 110, 84, 180, 110, 84, + 180, 114, 92, 172, 106, 84, 172, 102, 84, 172, 102, 76, 172, 106, 84, + 180, 110, 84, 180, 114, 92, 180, 114, 92, 180, 110, 84, 172, 110, 84, + 172, 106, 84, 180, 110, 84, 180, 114, 92, 180, 110, 84, 172, 106, 84, + 172, 102, 76, 172, 106, 84, 172, 106, 84, 180, 110, 84, 180, 114, 92, + 180, 114, 92, 180, 114, 92, 180, 106, 84, 172, 106, 84, 172, 106, 84, + 180, 110, 84, 180, 114, 92, 188, 118, 92, 188, 118, 92, 180, 114, 92, + 180, 110, 84, 172, 106, 84, 180, 106, 84, 172, 106, 84, 180, 106, 84, + 172, 106, 84, 172, 106, 84, 172, 102, 84, 172, 102, 76, 172, 106, 84, + 172, 106, 84, 172, 106, 84, 172, 106, 84, 172, 102, 76, 172, 102, 84, + 172, 102, 76, 172, 106, 84, 180, 110, 84, 180, 106, 84, 172, 102, 76, + 172, 106, 84, 172, 106, 84, 164, 98, 76, 164, 98, 76, 172, 102, 84, + 164, 98, 76, 172, 106, 76, 172, 102, 84, 164, 98, 76, 172, 102, 76, + 172, 106, 84, 172, 106, 84, 172, 106, 84, 172, 102, 76, 172, 102, 84, + 172, 102, 76, 172, 102, 84, 172, 106, 84, 172, 106, 84, 172, 98, 76, + 164, 102, 84, 180, 110, 84, 172, 110, 84, 172, 102, 84, 172, 102, 76, + 172, 106, 84, 172, 106, 84, 172, 98, 76, 172, 102, 76, 172, 106, 84, + 172, 106, 84, 172, 102, 84, 180, 110, 84, 172, 106, 84, 156, 94, 68, + 164, 90, 68, 172, 106, 84, 180, 110, 84, 164, 102, 84, 164, 98, 76, + 164, 98, 76, 164, 102, 84, 172, 106, 84, 164, 98, 84, 164, 98, 76, + 164, 98, 76, 164, 98, 76, 172, 106, 84, 172, 106, 84, 164, 98, 76, + 164, 94, 76, 164, 98, 76, 164, 98, 84, 164, 98, 76, 164, 98, 76, + 164, 98, 84, 172, 102, 84, 172, 98, 76, 164, 98, 76, 164, 94, 76, + 164, 98, 76, 172, 102, 84, 164, 98, 84, 164, 94, 76, 164, 94, 76, + 164, 94, 76, 164, 98, 84, 164, 98, 76, 164, 94, 76, 156, 86, 68, + 164, 94, 76, 156, 94, 76, 164, 98, 76, 164, 98, 76, 164, 102, 84, + 172, 102, 76, 164, 102, 84, 164, 102, 76, 172, 102, 84, 164, 102, 76, + 164, 102, 84, 164, 98, 76, 164, 98, 76, 164, 98, 76, 164, 98, 84, + 164, 102, 76, 164, 102, 84, 172, 98, 84, 164, 102, 84, 164, 98, 76, + 164, 102, 84, 156, 98, 76, 164, 98, 76, 164, 94, 76, 164, 98, 76, + 172, 98, 84, 172, 98, 84, 164, 90, 76, 172, 106, 92, 164, 106, 92, + 132, 70, 60, 116, 62, 44, 116, 58, 44, 164, 98, 84, 164, 98, 76, + 164, 98, 76, 156, 90, 68, 156, 90, 68, 164, 98, 76, 164, 102, 84, + 164, 98, 76, 172, 106, 84, 172, 102, 84, 172, 106, 84, 172, 106, 84, + 172, 106, 92, 172, 106, 84, 172, 110, 92, 172, 106, 84, 180, 110, 92, + 172, 106, 84, 180, 110, 92, 180, 110, 92, 180, 114, 100, 180, 110, 92, + 172, 106, 84, 164, 98, 76, 180, 110, 92, 180, 110, 92, 180, 114, 92, + 188, 118, 100, 188, 118, 100, 180, 114, 92, 180, 110, 92, 180, 110, 92, + 180, 114, 92, 188, 118, 92, 188, 118, 100, 180, 110, 84, 180, 110, 92, + 188, 118, 92, 172, 106, 84, 180, 110, 84, 180, 114, 92, 180, 110, 92, + 180, 110, 84, 172, 106, 84, 172, 106, 84, 180, 106, 84, 180, 110, 92, + 172, 106, 84, 180, 110, 84, 180, 110, 92, 180, 114, 92, 180, 114, 92, + 180, 110, 92, 180, 106, 84, 172, 110, 84, 180, 106, 84, 180, 110, 92, + 180, 110, 84, 180, 118, 100, 188, 114, 92, 180, 114, 92, 180, 110, 92, + 188, 122, 100, 188, 118, 92, 180, 114, 100, 180, 114, 84, 180, 110, 92, + 180, 110, 84, 180, 110, 92, 180, 110, 84, 172, 106, 84, 172, 110, 84, + 180, 110, 84, 180, 110, 92, 180, 110, 84, 180, 110, 92, 180, 110, 84, + 180, 110, 92, 164, 98, 76, 172, 102, 76, 172, 106, 84, 172, 102, 76, + 172, 102, 76, 172, 102, 76, 172, 106, 84, 180, 106, 84, 180, 110, 84, + 180, 110, 84, 180, 110, 92, 172, 106, 84, 172, 106, 84, 172, 106, 84, + 172, 110, 84, 180, 114, 92, 180, 110, 92, 172, 106, 84, 180, 106, 84, + 180, 110, 84, 172, 102, 76, 172, 102, 76, 172, 102, 76, 164, 94, 76, + 172, 106, 84, 172, 102, 84, 172, 106, 84, 172, 102, 84, 172, 106, 84, + 180, 110, 84, 172, 106, 84, 172, 106, 84, 172, 106, 84, 172, 106, 84, + 172, 106, 84, 180, 110, 84, 172, 106, 84, 172, 102, 76, 172, 102, 84, + 180, 110, 84, 180, 110, 92, 172, 106, 76, 172, 102, 84, 172, 106, 84, + 172, 106, 84, 172, 102, 76, 164, 102, 76, 180, 106, 84, 164, 98, 76, + 164, 102, 76, 180, 110, 84, 172, 110, 84, 164, 94, 76, 156, 94, 68, + 172, 102, 84, 172, 106, 84, 172, 106, 92, 164, 102, 84, 164, 98, 76, + 164, 102, 84, 172, 102, 84, 164, 98, 76, 164, 98, 84, 164, 102, 84, + 156, 90, 68, 164, 102, 84, 164, 102, 84, 156, 86, 68, 148, 86, 68, + 172, 102, 84, 172, 110, 84, 172, 102, 84, 172, 102, 84, 172, 102, 84, + 172, 102, 84, 164, 98, 76, 164, 94, 76, 156, 94, 76, 164, 94, 76, + 164, 98, 76, 172, 98, 84, 164, 98, 76, 156, 90, 76, 164, 94, 76, + 172, 98, 76, 164, 98, 84, 164, 94, 76, 156, 90, 68, 148, 90, 68, + 156, 94, 76, 164, 94, 76, 164, 102, 84, 164, 102, 84, 164, 102, 84, + 164, 98, 76, 164, 98, 84, 172, 106, 84, 164, 102, 84, 172, 102, 84, + 164, 98, 76, 164, 98, 84, 164, 98, 76, 164, 102, 76, 164, 98, 84, + 164, 94, 76, 164, 94, 76, 164, 98, 84, 164, 102, 84, 164, 102, 84, + 164, 98, 76, 164, 94, 76, 156, 94, 76, 164, 98, 76, 164, 94, 84, + 164, 98, 84, 156, 94, 76, 164, 106, 92, 164, 102, 92, 124, 66, 52, + 116, 58, 44, 116, 58, 36, 164, 106, 92, 172, 106, 84, 164, 106, 84, + 172, 102, 84, 164, 102, 84, 164, 102, 84, 164, 102, 76, 164, 98, 84, + 172, 106, 84, 172, 106, 84, 172, 110, 92, 172, 110, 84, 172, 106, 92, + 172, 106, 84, 172, 110, 92, 180, 114, 92, 180, 110, 92, 180, 110, 92, + 172, 110, 92, 180, 110, 92, 188, 118, 92, 188, 118, 100, 180, 114, 100, + 180, 114, 92, 180, 114, 92, 180, 114, 92, 188, 118, 100, 180, 114, 100, + 180, 114, 92, 180, 114, 92, 180, 110, 92, 172, 106, 84, 188, 118, 100, + 188, 118, 92, 188, 118, 100, 188, 118, 92, 188, 118, 92, 180, 114, 92, + 180, 106, 92, 180, 114, 92, 188, 118, 100, 180, 114, 100, 180, 110, 92, + 172, 106, 84, 180, 110, 92, 180, 114, 92, 180, 114, 92, 180, 110, 92, + 172, 106, 84, 172, 106, 84, 180, 114, 92, 188, 122, 100, 188, 118, 100, + 180, 118, 92, 188, 114, 100, 180, 118, 92, 188, 118, 100, 188, 118, 100, + 188, 118, 100, 180, 114, 92, 180, 118, 92, 188, 118, 100, 188, 122, 100, + 188, 118, 100, 180, 114, 92, 188, 114, 92, 180, 114, 100, 180, 114, 92, + 180, 110, 92, 172, 106, 84, 188, 118, 92, 180, 114, 92, 172, 110, 84, + 172, 110, 84, 172, 110, 84, 172, 110, 84, 180, 110, 84, 172, 106, 84, + 172, 110, 84, 172, 106, 84, 180, 106, 84, 172, 106, 84, 180, 106, 84, + 172, 102, 84, 180, 106, 84, 172, 106, 84, 172, 106, 84, 172, 106, 84, + 180, 110, 84, 180, 114, 84, 180, 110, 92, 180, 110, 84, 180, 110, 92, + 180, 110, 84, 172, 106, 84, 172, 106, 76, 172, 102, 84, 164, 102, 76, + 164, 102, 76, 172, 102, 84, 172, 106, 84, 172, 106, 84, 172, 102, 76, + 172, 102, 84, 172, 106, 84, 180, 110, 84, 180, 110, 92, 172, 106, 84, + 172, 106, 84, 172, 102, 84, 180, 106, 84, 172, 106, 84, 180, 106, 92, + 172, 106, 84, 180, 106, 92, 172, 106, 84, 172, 106, 84, 172, 106, 84, + 172, 106, 84, 172, 110, 84, 180, 110, 84, 172, 110, 84, 172, 98, 76, + 164, 102, 76, 172, 110, 84, 180, 118, 92, 172, 106, 84, 172, 110, 84, + 172, 102, 84, 172, 102, 76, 164, 102, 76, 164, 98, 76, 164, 98, 76, + 164, 98, 68, 164, 102, 84, 164, 102, 76, 164, 98, 84, 164, 98, 76, + 164, 98, 76, 164, 98, 76, 164, 102, 76, 164, 102, 84, 164, 98, 76, + 164, 98, 76, 156, 98, 76, 164, 94, 76, 156, 94, 76, 164, 98, 76, + 164, 98, 84, 164, 106, 84, 164, 98, 76, 164, 98, 76, 156, 94, 76, + 156, 94, 76, 164, 94, 76, 164, 98, 76, 172, 102, 84, 164, 102, 84, + 164, 94, 76, 156, 98, 76, 164, 94, 76, 164, 98, 76, 164, 98, 76, + 164, 102, 76, 164, 94, 76, 156, 94, 76, 148, 86, 68, 164, 94, 76, + 164, 102, 84, 164, 102, 76, 164, 94, 76, 156, 94, 76, 164, 98, 76, + 164, 98, 76, 164, 98, 76, 164, 98, 76, 164, 98, 76, 164, 98, 76, + 164, 98, 76, 164, 98, 84, 164, 98, 76, 164, 98, 76, 164, 98, 84, + 164, 94, 84, 164, 90, 76, 164, 94, 76, 164, 98, 84, 164, 98, 84, + 164, 94, 76, 164, 94, 76, 172, 102, 84, 164, 98, 76, 172, 98, 84, + 164, 98, 84, 172, 110, 92, 164, 102, 84, 124, 66, 52, 116, 58, 36, + 108, 46, 28, 180, 110, 92, 180, 110, 92, 172, 110, 92, 172, 110, 84, + 172, 106, 84, 172, 106, 84, 172, 106, 84, 172, 106, 84, 172, 110, 92, + 172, 110, 92, 180, 110, 92, 172, 110, 92, 172, 110, 84, 172, 110, 92, + 180, 114, 92, 180, 118, 100, 180, 110, 92, 172, 106, 84, 180, 110, 92, + 180, 110, 92, 180, 114, 100, 188, 118, 100, 180, 114, 92, 180, 114, 92, + 180, 114, 100, 180, 114, 92, 180, 114, 100, 180, 114, 92, 180, 110, 92, + 180, 110, 92, 172, 106, 92, 180, 106, 84, 180, 114, 92, 180, 110, 92, + 180, 114, 92, 180, 114, 92, 180, 114, 92, 180, 114, 92, 172, 110, 92, + 180, 110, 92, 188, 118, 100, 180, 114, 92, 180, 110, 92, 172, 106, 84, + 180, 106, 92, 180, 110, 92, 180, 114, 92, 172, 106, 92, 172, 106, 84, + 180, 106, 92, 180, 114, 92, 188, 118, 100, 188, 118, 100, 180, 114, 92, + 180, 110, 92, 180, 114, 100, 188, 118, 100, 188, 118, 100, 180, 118, 100, + 188, 118, 100, 188, 118, 100, 188, 118, 100, 196, 126, 108, 188, 122, 100, + 188, 118, 100, 188, 118, 100, 188, 122, 100, 188, 118, 100, 180, 118, 100, + 180, 114, 92, 188, 118, 100, 180, 118, 92, 180, 110, 84, 180, 110, 92, + 180, 114, 84, 180, 114, 92, 180, 110, 92, 180, 110, 84, 180, 110, 92, + 180, 110, 84, 180, 110, 92, 180, 110, 92, 188, 114, 84, 180, 110, 92, + 180, 110, 84, 188, 114, 92, 188, 114, 92, 180, 118, 92, 188, 118, 100, + 188, 118, 92, 188, 122, 100, 188, 118, 92, 188, 118, 100, 180, 118, 92, + 180, 106, 84, 172, 106, 84, 172, 102, 76, 172, 102, 76, 172, 102, 84, + 172, 102, 76, 172, 106, 84, 172, 106, 84, 172, 102, 84, 164, 102, 84, + 172, 102, 84, 172, 106, 84, 172, 106, 84, 172, 102, 84, 172, 102, 84, + 164, 98, 84, 172, 106, 84, 172, 110, 92, 172, 106, 84, 180, 110, 92, + 172, 106, 84, 172, 110, 92, 180, 106, 92, 172, 110, 92, 180, 110, 84, + 172, 114, 92, 180, 114, 92, 172, 110, 84, 172, 106, 84, 172, 106, 84, + 180, 114, 84, 180, 118, 92, 180, 110, 84, 172, 110, 84, 172, 110, 84, + 172, 106, 84, 164, 102, 76, 172, 102, 76, 164, 102, 76, 164, 102, 84, + 172, 102, 76, 164, 102, 84, 164, 98, 76, 164, 98, 84, 164, 98, 76, + 164, 102, 84, 164, 102, 84, 172, 98, 76, 164, 98, 84, 164, 98, 76, + 164, 94, 76, 156, 94, 68, 164, 94, 76, 164, 98, 76, 164, 98, 76, + 164, 102, 84, 172, 102, 84, 164, 102, 84, 164, 98, 76, 164, 98, 76, + 156, 94, 76, 164, 98, 76, 164, 98, 76, 164, 102, 76, 164, 98, 76, + 164, 98, 76, 156, 94, 76, 164, 98, 76, 164, 102, 84, 164, 98, 84, + 164, 98, 76, 164, 94, 76, 156, 94, 68, 164, 102, 84, 172, 106, 84, + 172, 110, 92, 172, 102, 84, 164, 102, 76, 172, 102, 84, 164, 106, 84, + 164, 98, 84, 164, 98, 76, 164, 98, 84, 156, 98, 76, 164, 98, 76, + 164, 98, 76, 164, 98, 76, 164, 98, 84, 164, 98, 84, 164, 94, 76, + 164, 94, 76, 164, 94, 76, 164, 98, 84, 164, 98, 84, 164, 98, 84, + 164, 94, 76, 156, 94, 84, 156, 94, 76, 156, 94, 76, 156, 90, 76, + 164, 98, 84, 156, 90, 76, 116, 54, 36, 108, 46, 28, 116, 54, 36, + 172, 110, 92, 172, 110, 92, 180, 110, 92, 172, 110, 92, 172, 106, 84, + 172, 106, 92, 164, 106, 84, 172, 106, 84, 172, 106, 84, 172, 106, 84, + 172, 110, 84, 172, 106, 92, 172, 106, 84, 172, 106, 84, 172, 106, 84, + 180, 110, 92, 172, 106, 84, 172, 106, 84, 172, 106, 84, 180, 110, 92, + 180, 114, 92, 180, 114, 92, 188, 114, 100, 180, 114, 92, 180, 110, 92, + 180, 110, 92, 180, 110, 92, 180, 110, 92, 172, 106, 84, 180, 106, 92, + 172, 110, 84, 172, 106, 92, 180, 110, 84, 180, 110, 92, 180, 110, 92, + 180, 110, 84, 180, 110, 92, 180, 106, 84, 180, 106, 84, 180, 114, 92, + 180, 114, 100, 180, 114, 92, 172, 106, 92, 172, 106, 84, 172, 106, 84, + 172, 106, 92, 180, 110, 92, 172, 106, 84, 172, 102, 84, 172, 106, 84, + 180, 114, 92, 180, 114, 100, 180, 114, 92, 180, 114, 92, 180, 110, 92, + 180, 114, 92, 188, 122, 100, 188, 118, 100, 188, 118, 100, 180, 114, 92, + 180, 114, 92, 180, 114, 92, 180, 110, 92, 172, 106, 92, 172, 106, 84, + 172, 106, 84, 172, 106, 92, 172, 106, 84, 180, 110, 92, 172, 110, 84, + 180, 114, 92, 180, 114, 92, 172, 110, 84, 172, 110, 84, 172, 110, 84, + 180, 110, 92, 180, 114, 84, 172, 110, 84, 172, 102, 84, 172, 106, 76, + 172, 106, 84, 180, 106, 84, 172, 106, 84, 180, 106, 84, 180, 106, 84, + 172, 106, 84, 180, 106, 84, 180, 110, 84, 172, 110, 92, 180, 110, 84, + 180, 110, 92, 172, 110, 84, 180, 110, 84, 172, 106, 84, 172, 106, 84, + 172, 106, 84, 164, 102, 84, 172, 102, 76, 164, 102, 76, 172, 102, 84, + 172, 106, 76, 172, 106, 84, 172, 102, 84, 172, 102, 84, 172, 106, 84, + 180, 106, 84, 172, 106, 92, 172, 106, 84, 172, 102, 84, 172, 102, 84, + 172, 102, 84, 172, 106, 84, 172, 102, 84, 172, 106, 84, 172, 106, 92, + 180, 106, 84, 172, 106, 92, 172, 110, 84, 180, 110, 92, 180, 110, 92, + 172, 114, 92, 180, 110, 84, 172, 114, 92, 180, 110, 84, 172, 114, 92, + 180, 110, 92, 172, 114, 92, 180, 110, 92, 172, 106, 84, 172, 106, 84, + 164, 106, 84, 172, 106, 84, 164, 102, 84, 172, 106, 84, 164, 98, 76, + 164, 98, 76, 164, 98, 84, 164, 102, 76, 164, 102, 84, 164, 98, 76, + 164, 98, 84, 164, 98, 76, 164, 98, 76, 164, 98, 76, 156, 94, 76, + 156, 90, 76, 156, 94, 68, 156, 94, 76, 156, 94, 76, 164, 98, 76, + 164, 102, 84, 164, 102, 76, 164, 98, 76, 156, 94, 76, 156, 94, 76, + 156, 94, 68, 156, 90, 76, 156, 94, 76, 164, 98, 76, 164, 98, 76, + 156, 94, 76, 164, 98, 76, 164, 98, 76, 164, 98, 76, 164, 98, 76, + 156, 94, 76, 156, 86, 68, 156, 94, 68, 164, 98, 76, 164, 98, 76, + 156, 94, 76, 156, 90, 68, 156, 94, 76, 164, 94, 76, 156, 98, 76, + 164, 94, 76, 156, 98, 76, 164, 94, 76, 164, 98, 76, 156, 94, 76, + 164, 98, 76, 156, 94, 76, 164, 94, 76, 156, 90, 76, 156, 90, 76, + 156, 90, 76, 156, 94, 76, 164, 94, 76, 156, 90, 76, 156, 94, 76, + 164, 98, 84, 164, 94, 76, 164, 98, 84, 156, 94, 76, 164, 102, 84, + 156, 94, 76, 116, 58, 36, 116, 54, 36, 116, 58, 36, 180, 114, 100, + 180, 118, 92, 180, 114, 92, 180, 114, 92, 180, 114, 92, 180, 114, 92, + 180, 110, 92, 172, 110, 92, 180, 114, 92, 180, 114, 100, 180, 114, 92, + 180, 114, 92, 172, 110, 92, 172, 110, 92, 180, 114, 92, 180, 118, 100, + 180, 114, 92, 180, 114, 100, 188, 118, 100, 188, 118, 100, 188, 122, 100, + 196, 126, 108, 188, 122, 108, 196, 126, 100, 188, 122, 108, 188, 122, 100, + 188, 118, 100, 180, 118, 100, 188, 114, 100, 180, 118, 100, 188, 118, 100, + 188, 118, 100, 196, 126, 108, 188, 126, 100, 196, 126, 108, 188, 122, 100, + 180, 114, 100, 180, 114, 92, 188, 122, 100, 196, 122, 108, 196, 126, 108, + 196, 126, 100, 188, 118, 100, 180, 114, 100, 188, 114, 92, 180, 118, 100, + 188, 122, 100, 188, 118, 100, 188, 114, 100, 188, 118, 100, 188, 122, 100, + 196, 122, 108, 188, 126, 108, 188, 122, 100, 196, 126, 108, 196, 130, 108, + 196, 130, 116, 196, 130, 108, 196, 126, 108, 188, 118, 100, 180, 114, 100, + 180, 110, 92, 172, 106, 84, 172, 106, 84, 172, 102, 84, 172, 102, 84, + 172, 106, 84, 180, 106, 92, 180, 114, 92, 180, 114, 92, 180, 118, 92, + 180, 118, 92, 180, 118, 92, 180, 118, 92, 188, 118, 92, 180, 118, 92, + 180, 118, 92, 188, 118, 100, 180, 114, 84, 180, 110, 92, 188, 114, 92, + 180, 110, 92, 188, 114, 92, 188, 118, 92, 188, 118, 100, 188, 118, 92, + 180, 114, 92, 180, 114, 92, 180, 114, 92, 180, 114, 92, 180, 110, 84, + 180, 110, 92, 180, 110, 84, 180, 110, 84, 188, 118, 92, 180, 114, 92, + 180, 114, 92, 180, 110, 84, 180, 110, 92, 180, 114, 92, 180, 114, 92, + 188, 118, 92, 188, 118, 100, 188, 122, 100, 188, 122, 100, 188, 122, 108, + 188, 122, 100, 188, 122, 100, 188, 122, 100, 188, 118, 100, 180, 114, 92, + 180, 114, 92, 180, 114, 100, 188, 114, 92, 180, 118, 100, 188, 118, 100, + 188, 118, 100, 188, 118, 100, 188, 122, 100, 180, 122, 100, 188, 118, 100, + 188, 122, 100, 188, 122, 100, 188, 126, 108, 188, 122, 100, 180, 118, 92, + 172, 106, 84, 172, 110, 84, 172, 106, 84, 164, 102, 84, 172, 102, 76, + 164, 102, 76, 164, 102, 84, 172, 102, 76, 156, 94, 76, 164, 98, 76, + 164, 98, 76, 164, 102, 84, 164, 98, 76, 164, 102, 76, 164, 98, 76, + 156, 98, 76, 164, 98, 84, 164, 98, 76, 156, 94, 76, 164, 94, 68, + 156, 94, 76, 156, 94, 68, 164, 94, 76, 156, 94, 76, 164, 98, 76, + 164, 98, 84, 164, 98, 76, 156, 94, 76, 156, 90, 68, 156, 94, 76, + 156, 90, 68, 156, 94, 76, 164, 94, 76, 156, 94, 76, 164, 94, 76, + 156, 98, 76, 164, 98, 76, 164, 98, 84, 156, 98, 76, 156, 94, 68, + 164, 94, 76, 164, 98, 76, 164, 102, 84, 164, 102, 84, 164, 98, 76, + 164, 98, 76, 164, 98, 76, 164, 98, 76, 156, 94, 76, 156, 94, 68, + 156, 94, 76, 156, 94, 76, 156, 94, 76, 156, 94, 76, 156, 94, 68, + 156, 94, 76, 172, 98, 84, 164, 98, 84, 172, 98, 76, 164, 94, 84, + 172, 98, 84, 164, 98, 84, 164, 98, 84, 172, 98, 84, 164, 98, 84, + 164, 98, 84, 164, 106, 84, 164, 102, 84, 172, 110, 92, 164, 98, 84, + 124, 66, 44, 116, 58, 36, 116, 50, 36, 172, 106, 84, 164, 102, 84, + 172, 102, 84, 164, 102, 84, 172, 102, 84, 164, 102, 84, 164, 102, 84, + 172, 102, 84, 164, 102, 84, 172, 106, 84, 164, 106, 84, 172, 102, 84, + 164, 102, 76, 172, 102, 84, 164, 102, 84, 172, 106, 84, 172, 102, 84, + 180, 106, 84, 172, 110, 92, 180, 114, 92, 180, 110, 92, 180, 114, 92, + 180, 114, 92, 180, 114, 100, 180, 114, 92, 180, 110, 92, 180, 110, 92, + 172, 106, 84, 180, 110, 84, 172, 106, 84, 180, 110, 92, 180, 110, 92, + 180, 118, 92, 180, 114, 100, 180, 110, 92, 180, 110, 92, 180, 106, 92, + 172, 102, 84, 180, 114, 92, 180, 114, 92, 180, 114, 100, 180, 114, 92, + 180, 110, 92, 180, 106, 92, 172, 106, 84, 172, 106, 84, 180, 106, 92, + 172, 110, 92, 172, 106, 84, 180, 110, 92, 180, 110, 92, 180, 114, 92, + 180, 110, 92, 180, 110, 92, 180, 110, 92, 188, 114, 100, 188, 122, 100, + 188, 118, 100, 180, 110, 92, 172, 106, 84, 172, 102, 84, 164, 98, 76, + 172, 102, 84, 172, 102, 84, 164, 102, 84, 172, 98, 76, 164, 98, 84, + 172, 106, 84, 180, 106, 92, 180, 110, 92, 172, 106, 92, 172, 110, 84, + 172, 106, 84, 172, 110, 92, 172, 106, 84, 172, 110, 92, 180, 106, 84, + 172, 110, 92, 180, 110, 84, 172, 110, 92, 180, 110, 84, 180, 110, 92, + 180, 114, 92, 180, 114, 92, 188, 114, 92, 188, 114, 92, 180, 110, 92, + 180, 110, 92, 180, 110, 92, 180, 110, 84, 180, 110, 92, 172, 110, 84, + 172, 106, 84, 172, 106, 92, 172, 106, 84, 180, 106, 84, 172, 106, 84, + 172, 102, 84, 172, 106, 84, 172, 106, 84, 172, 106, 84, 172, 106, 84, + 180, 110, 92, 180, 110, 92, 180, 110, 92, 180, 114, 92, 180, 114, 100, + 180, 114, 92, 180, 110, 92, 180, 110, 92, 172, 102, 84, 172, 102, 84, + 172, 106, 84, 172, 106, 84, 172, 106, 92, 180, 110, 84, 172, 110, 92, + 180, 110, 92, 172, 106, 92, 172, 106, 84, 172, 106, 84, 172, 110, 92, + 180, 114, 92, 180, 110, 92, 172, 110, 92, 172, 102, 84, 172, 106, 92, + 164, 102, 84, 172, 102, 84, 164, 102, 84, 164, 98, 84, 164, 102, 76, + 164, 98, 84, 164, 102, 84, 164, 98, 76, 164, 98, 76, 164, 98, 84, + 172, 102, 76, 164, 102, 84, 164, 98, 84, 164, 98, 84, 164, 98, 76, + 172, 102, 76, 164, 102, 84, 164, 102, 76, 164, 98, 84, 164, 98, 76, + 164, 98, 76, 164, 98, 76, 164, 98, 76, 164, 98, 76, 164, 98, 76, + 164, 98, 76, 164, 94, 76, 164, 98, 76, 164, 94, 76, 164, 98, 76, + 164, 98, 76, 164, 98, 76, 164, 98, 76, 164, 98, 76, 164, 98, 76, + 164, 102, 84, 164, 102, 84, 164, 98, 76, 156, 94, 76, 164, 98, 76, + 164, 98, 84, 172, 102, 84, 164, 102, 76, 164, 98, 84, 164, 98, 76, + 164, 98, 84, 164, 98, 76, 164, 94, 76, 164, 94, 76, 164, 94, 76, + 156, 94, 76, 164, 94, 68, 164, 94, 76, 164, 94, 76, 156, 94, 76, + 164, 94, 76, 164, 90, 76, 156, 94, 76, 164, 94, 76, 164, 94, 76, + 156, 94, 76, 164, 94, 76, 164, 94, 76, 156, 94, 76, 164, 94, 76, + 164, 102, 84, 164, 102, 84, 172, 106, 92, 156, 94, 76, 124, 62, 44, + 116, 50, 36, 108, 50, 28, 156, 86, 68, 156, 90, 68, 148, 86, 68, + 156, 90, 68, 148, 86, 68, 156, 90, 68, 156, 86, 68, 148, 90, 68, + 156, 90, 68, 156, 90, 76, 156, 94, 76, 156, 90, 68, 148, 86, 68, + 156, 86, 68, 156, 90, 68, 156, 90, 76, 148, 86, 68, 156, 86, 68, + 156, 90, 68, 164, 90, 76, 156, 90, 68, 156, 90, 76, 164, 90, 68, + 156, 90, 76, 164, 90, 68, 156, 90, 76, 156, 90, 68, 156, 90, 68, + 156, 90, 76, 156, 90, 68, 156, 90, 68, 156, 90, 68, 156, 86, 76, + 156, 86, 68, 156, 90, 76, 156, 90, 68, 156, 90, 76, 156, 90, 68, + 164, 90, 76, 164, 94, 76, 164, 94, 76, 156, 94, 76, 156, 90, 68, + 156, 90, 68, 156, 86, 68, 156, 86, 68, 156, 86, 68, 156, 86, 68, + 156, 90, 68, 156, 90, 68, 156, 90, 76, 164, 90, 68, 156, 90, 76, + 156, 90, 68, 148, 86, 68, 156, 86, 68, 164, 94, 76, 164, 94, 76, + 156, 90, 68, 156, 90, 68, 156, 86, 68, 156, 86, 68, 156, 86, 68, + 156, 86, 68, 156, 86, 68, 156, 86, 68, 156, 86, 68, 156, 86, 68, + 156, 90, 68, 164, 94, 76, 156, 90, 68, 156, 94, 76, 164, 98, 76, + 164, 94, 76, 156, 94, 68, 156, 90, 68, 156, 94, 68, 164, 94, 68, + 156, 86, 68, 156, 86, 68, 156, 90, 68, 156, 90, 68, 164, 90, 68, + 164, 90, 76, 164, 90, 68, 164, 90, 76, 164, 94, 76, 156, 94, 68, + 164, 94, 68, 156, 90, 68, 156, 90, 68, 164, 90, 68, 164, 94, 76, + 156, 90, 68, 156, 90, 68, 156, 90, 68, 156, 90, 68, 164, 90, 68, + 156, 90, 68, 156, 90, 68, 164, 90, 68, 156, 90, 68, 156, 90, 76, + 156, 90, 68, 156, 90, 76, 164, 90, 68, 156, 90, 68, 156, 90, 76, + 156, 90, 68, 156, 90, 76, 156, 90, 68, 156, 90, 76, 156, 86, 68, + 164, 90, 76, 156, 90, 68, 164, 90, 76, 156, 94, 68, 164, 94, 76, + 156, 90, 68, 156, 90, 76, 156, 90, 68, 156, 90, 76, 156, 94, 76, + 156, 94, 76, 156, 90, 76, 148, 86, 68, 164, 98, 84, 164, 98, 76, + 164, 98, 76, 156, 94, 76, 164, 94, 76, 156, 94, 76, 164, 94, 76, + 156, 94, 76, 164, 94, 76, 156, 98, 76, 164, 98, 76, 164, 98, 76, + 164, 94, 76, 164, 98, 76, 156, 94, 76, 156, 94, 76, 164, 98, 76, + 164, 98, 76, 164, 98, 76, 164, 98, 76, 164, 98, 76, 164, 98, 76, + 164, 98, 76, 156, 94, 76, 156, 94, 76, 156, 90, 68, 156, 94, 76, + 156, 94, 76, 164, 94, 76, 156, 98, 76, 164, 98, 76, 164, 98, 84, + 156, 94, 76, 156, 94, 76, 156, 94, 76, 164, 94, 76, 164, 98, 76, + 164, 98, 76, 164, 94, 76, 156, 90, 76, 156, 90, 68, 156, 90, 68, + 156, 94, 76, 156, 90, 68, 156, 90, 68, 156, 90, 68, 148, 90, 68, + 156, 90, 68, 156, 90, 76, 156, 94, 68, 156, 90, 68, 156, 94, 76, + 156, 90, 68, 156, 94, 76, 156, 90, 68, 156, 94, 68, 156, 82, 68, + 156, 86, 76, 156, 90, 76, 156, 86, 76, 148, 86, 68, 156, 86, 68, + 156, 86, 76, 156, 90, 68, 156, 94, 76, 164, 94, 84, 164, 98, 84, + 156, 94, 76, 156, 98, 76, 148, 86, 68, 116, 54, 36, 108, 50, 28, + 108, 50, 36, 140, 78, 60, 140, 78, 60, 148, 78, 60, 140, 78, 60, + 140, 78, 60, 140, 78, 60, 140, 78, 60, 140, 78, 60, 148, 82, 60, + 148, 82, 60, 148, 82, 60, 148, 78, 60, 140, 74, 52, 140, 74, 52, + 140, 78, 60, 148, 82, 60, 140, 70, 52, 140, 74, 52, 148, 74, 60, + 140, 78, 60, 148, 74, 60, 140, 74, 52, 140, 74, 52, 140, 78, 60, + 140, 74, 52, 148, 78, 60, 140, 74, 60, 148, 78, 60, 148, 74, 60, + 148, 78, 60, 148, 74, 60, 148, 78, 60, 140, 70, 52, 140, 70, 52, + 148, 74, 60, 140, 74, 60, 148, 78, 60, 148, 78, 68, 140, 78, 60, + 148, 78, 60, 140, 78, 60, 148, 78, 60, 148, 78, 60, 148, 74, 60, + 140, 74, 52, 140, 74, 52, 140, 74, 52, 140, 74, 52, 140, 74, 52, + 148, 74, 60, 148, 78, 60, 140, 78, 60, 148, 74, 60, 140, 74, 52, + 140, 70, 52, 140, 74, 52, 140, 78, 60, 148, 78, 60, 148, 78, 60, + 148, 78, 60, 148, 78, 60, 148, 82, 60, 140, 74, 52, 140, 74, 52, + 140, 78, 60, 140, 74, 52, 140, 74, 52, 140, 74, 52, 140, 74, 52, + 140, 78, 60, 140, 82, 60, 148, 82, 60, 148, 86, 68, 148, 86, 60, + 140, 82, 60, 148, 78, 60, 140, 78, 60, 140, 78, 60, 140, 70, 52, + 140, 70, 52, 140, 74, 52, 140, 70, 52, 140, 74, 52, 140, 70, 52, + 140, 74, 52, 140, 74, 52, 140, 78, 60, 148, 74, 60, 140, 74, 52, + 140, 74, 60, 140, 74, 52, 140, 74, 60, 140, 78, 60, 148, 78, 60, + 156, 82, 60, 148, 82, 68, 156, 82, 60, 148, 82, 68, 148, 82, 60, + 156, 82, 68, 148, 82, 60, 148, 82, 68, 148, 82, 60, 148, 82, 60, + 148, 82, 60, 148, 82, 68, 148, 78, 60, 156, 82, 60, 148, 82, 68, + 148, 82, 60, 156, 82, 60, 148, 82, 60, 156, 82, 68, 148, 82, 60, + 156, 86, 68, 148, 82, 60, 156, 82, 68, 148, 82, 60, 148, 82, 68, + 148, 82, 68, 148, 82, 68, 148, 86, 68, 148, 82, 68, 156, 86, 68, + 148, 82, 68, 148, 82, 60, 148, 82, 68, 140, 78, 60, 148, 78, 68, + 140, 78, 60, 148, 78, 60, 140, 78, 60, 148, 78, 60, 140, 78, 60, + 148, 82, 60, 148, 78, 60, 140, 78, 60, 140, 78, 60, 140, 78, 60, + 140, 78, 60, 148, 78, 60, 148, 82, 60, 140, 78, 60, 148, 78, 60, + 140, 78, 60, 148, 78, 60, 140, 78, 60, 140, 78, 60, 148, 78, 60, + 148, 82, 60, 140, 74, 52, 140, 78, 60, 148, 78, 60, 140, 78, 60, + 148, 82, 60, 148, 82, 60, 148, 82, 60, 148, 82, 60, 148, 78, 60, + 148, 78, 60, 140, 78, 60, 140, 78, 60, 148, 82, 60, 148, 82, 60, + 148, 78, 60, 140, 78, 60, 148, 86, 60, 148, 82, 68, 148, 82, 60, + 148, 82, 60, 140, 78, 60, 148, 82, 60, 148, 78, 60, 148, 78, 60, + 140, 78, 60, 140, 78, 60, 140, 78, 60, 140, 78, 60, 140, 78, 60, + 140, 78, 60, 148, 78, 60, 140, 78, 60, 148, 82, 68, 148, 82, 68, + 148, 86, 68, 156, 82, 68, 148, 82, 68, 148, 82, 68, 148, 82, 68, + 148, 86, 68, 148, 82, 68, 148, 78, 60, 140, 82, 60, 140, 74, 60, + 140, 78, 60, 140, 74, 60, 116, 50, 36, 108, 50, 36, 108, 50, 28, + 108, 42, 28, 108, 42, 20, 108, 42, 20, 108, 42, 20, 116, 46, 28, + 108, 42, 20, 116, 46, 28, 108, 42, 20, 108, 46, 28, 108, 46, 28, + 116, 46, 28, 108, 46, 20, 108, 42, 20, 100, 42, 20, 108, 42, 20, + 108, 42, 28, 108, 42, 20, 116, 46, 28, 116, 46, 28, 116, 46, 28, + 108, 42, 20, 108, 38, 20, 108, 42, 28, 116, 42, 28, 108, 42, 20, + 116, 46, 28, 116, 46, 28, 116, 46, 28, 116, 50, 28, 108, 46, 28, + 116, 46, 28, 108, 42, 20, 108, 42, 28, 116, 42, 28, 108, 46, 28, + 116, 46, 28, 116, 46, 28, 108, 46, 28, 116, 42, 28, 108, 42, 20, + 116, 46, 28, 108, 42, 20, 116, 46, 28, 108, 46, 28, 108, 42, 20, + 116, 42, 28, 108, 38, 20, 108, 42, 28, 116, 46, 28, 108, 46, 28, + 116, 46, 28, 108, 42, 20, 108, 42, 20, 116, 42, 28, 116, 46, 28, + 116, 50, 28, 116, 50, 28, 116, 50, 28, 116, 46, 28, 116, 46, 28, + 116, 46, 28, 116, 50, 28, 116, 46, 28, 116, 50, 36, 124, 50, 36, + 116, 50, 28, 116, 46, 28, 116, 46, 28, 116, 46, 28, 116, 46, 28, + 108, 46, 20, 108, 50, 28, 116, 50, 28, 116, 54, 28, 108, 46, 28, + 108, 46, 20, 108, 42, 20, 108, 42, 20, 116, 50, 28, 116, 46, 28, + 116, 46, 28, 116, 46, 28, 116, 46, 28, 108, 46, 28, 116, 46, 28, + 116, 46, 28, 116, 46, 28, 116, 46, 28, 116, 46, 28, 116, 42, 28, + 116, 46, 28, 116, 46, 28, 116, 50, 28, 124, 50, 36, 124, 58, 36, + 124, 58, 36, 124, 58, 36, 124, 58, 36, 124, 58, 44, 124, 58, 36, + 124, 58, 36, 124, 54, 36, 132, 62, 44, 124, 54, 36, 124, 58, 36, + 124, 58, 36, 124, 58, 36, 124, 54, 44, 124, 58, 36, 132, 62, 44, + 124, 54, 36, 124, 58, 36, 124, 58, 36, 124, 58, 36, 124, 58, 36, + 124, 54, 36, 124, 58, 36, 124, 58, 36, 124, 58, 44, 124, 58, 36, + 124, 58, 44, 124, 54, 36, 124, 58, 44, 124, 58, 36, 124, 58, 44, + 124, 58, 44, 132, 62, 44, 124, 62, 44, 132, 62, 44, 124, 58, 44, + 124, 58, 44, 124, 58, 44, 132, 62, 44, 124, 62, 44, 132, 62, 44, + 124, 62, 44, 124, 62, 44, 124, 58, 36, 124, 58, 36, 124, 62, 44, + 124, 62, 44, 132, 62, 44, 116, 58, 36, 124, 58, 36, 124, 58, 44, + 124, 62, 44, 124, 62, 44, 124, 62, 44, 124, 62, 44, 124, 58, 36, + 124, 62, 44, 124, 58, 36, 124, 62, 44, 132, 62, 44, 124, 62, 44, + 132, 62, 44, 124, 66, 44, 132, 62, 44, 124, 62, 44, 124, 58, 36, + 124, 58, 36, 124, 62, 44, 132, 62, 44, 124, 62, 44, 124, 62, 44, + 124, 58, 36, 124, 62, 44, 124, 58, 36, 124, 58, 36, 124, 58, 44, + 124, 58, 36, 124, 58, 36, 116, 58, 36, 124, 58, 36, 124, 58, 36, + 124, 58, 36, 124, 58, 36, 124, 58, 36, 124, 58, 36, 124, 58, 36, + 124, 58, 36, 124, 58, 36, 124, 50, 36, 124, 54, 36, 124, 54, 36, + 124, 54, 36, 116, 54, 36, 116, 50, 36, 124, 54, 36, 124, 54, 44, + 124, 54, 36, 116, 54, 36, 116, 54, 36, 108, 46, 28, 124, 58, 44, + 124, 58, 44, 100, 42, 20, 108, 50, 28 +}; diff --git a/hacks/glx/endgame.c b/hacks/glx/endgame.c new file mode 100644 index 00000000..b4811da4 --- /dev/null +++ b/hacks/glx/endgame.c @@ -0,0 +1,993 @@ +/* + * endgame.c + * plays through a chess game ending. enjoy. + * + * version 1.0 - June 6, 2002 + * + * Copyright (C) 2002-2008 Blair Tennessy (tennessb@unbc.ca) + * + * 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. + */ + +#ifdef STANDALONE +#define DEFAULTS "*delay: 20000 \n" \ + "*showFPS: False \n" \ + "*wireframe: False \n" \ + +# define refresh_chess 0 +# include "xlockmore.h" + +#else +# include "xlock.h" +#endif + +#ifdef USE_GL + +#define BOARDSIZE 8 +#define WHITES 5 + +#include "gltrackball.h" +#include "chessmodels.h" +#include "chessgames.h" + +#undef countof +#define countof(x) (sizeof((x))/sizeof((*x))) + +#define DEF_ROTATE "True" +#define DEF_REFLECTIONS "True" +#define DEF_SHADOWS "True" +#define DEF_SMOOTH "True" +#define DEF_CLASSIC "False" + + +static XrmOptionDescRec opts[] = { + {"+rotate", ".chess.rotate", XrmoptionNoArg, "false" }, + {"-rotate", ".chess.rotate", XrmoptionNoArg, "true" }, + {"+reflections", ".chess.reflections", XrmoptionNoArg, "false" }, + {"-reflections", ".chess.reflections", XrmoptionNoArg, "true" }, + {"+shadows", ".chess.shadows", XrmoptionNoArg, "false" }, + {"-shadows", ".chess.shadows", XrmoptionNoArg, "true" }, + {"+smooth", ".chess.smooth", XrmoptionNoArg, "false" }, + {"-smooth", ".chess.smooth", XrmoptionNoArg, "true" }, + {"+classic", ".chess.classic", XrmoptionNoArg, "false" }, + {"-classic", ".chess.classic", XrmoptionNoArg, "true" }, +}; + +static int rotate, reflections, smooth, shadows, classic; + +static argtype vars[] = { + {&rotate, "rotate", "Rotate", DEF_ROTATE, t_Bool}, + {&reflections, "reflections", "Reflections", DEF_REFLECTIONS, t_Bool}, + {&shadows, "shadows", "Shadows", DEF_SHADOWS, t_Bool}, + {&smooth, "smooth", "Smooth", DEF_SMOOTH, t_Bool}, + {&classic, "classic", "Classic", DEF_CLASSIC, t_Bool}, +}; + +ENTRYPOINT ModeSpecOpt chess_opts = {countof(opts), opts, countof(vars), vars, NULL}; + +#ifdef USE_MODULES +ModStruct chess_description = +{"chess", "init_chess", "draw_chess", "release_chess", + "draw_chess", "init_chess", NULL, &chess_opts, + 1000, 1, 2, 1, 4, 1.0, "", + "Chess", 0, NULL}; + +#endif + +#define checkImageWidth 16 +#define checkImageHeight 16 + +typedef struct { + GLXContext *glx_context; + Window window; + trackball_state *trackball; + Bool button_down_p; + + ChessGame game; + int oldwhite; + + /** definition of white/black (orange/gray) colors */ + GLfloat colors[2][3]; + + GLubyte checkImage[checkImageWidth][checkImageHeight][3]; + GLuint piecetexture, boardtexture; + + int mpiece, tpiece, steps, done; + double from[2], to[2]; + double dx, dz; + int moving, take, mc, count, wire; + double theta; + + GLfloat position[4]; + GLfloat position2[4]; + + GLfloat mod; + + GLfloat ground[4]; + + int oldgame; + + int poly_counts[PIECES]; /* polygon count of each type of piece */ + + +} Chesscreen; + +static Chesscreen *qs = NULL; + +static const GLfloat MaterialShadow[] = {0.0, 0.0, 0.0, 0.3}; + + +/* i prefer silvertip */ +static const GLfloat whites[WHITES][3] = + { + {1.0, 0.55, 0.1}, + {0.8, 0.52, 0.8}, + {0.43, 0.54, 0.76}, + {0.2, 0.2, 0.2}, + {0.35, 0.60, 0.35}, + }; + +static void build_colors(Chesscreen *cs) +{ + + /* find new white */ + int newwhite = cs->oldwhite; + while(newwhite == cs->oldwhite) + newwhite = random()%WHITES; + cs->oldwhite = newwhite; + + cs->colors[0][0] = whites[cs->oldwhite][0]; + cs->colors[0][1] = whites[cs->oldwhite][1]; + cs->colors[0][2] = whites[cs->oldwhite][2]; +} + +/* build piece texture */ +static void make_piece_texture(Chesscreen *cs) +{ + int i, j, c; + + for (i = 0; i < checkImageWidth; i++) { + for (j = 0; j < checkImageHeight; j++) { + c = ((j%2) == 0 || i%2 == 0) ? 240 : 180+random()%16; + cs->checkImage[i][j][0] = (GLubyte) c; + cs->checkImage[i][j][1] = (GLubyte) c; + cs->checkImage[i][j][2] = (GLubyte) c; + } + } + + glGenTextures(1, &cs->piecetexture); + glBindTexture(GL_TEXTURE_2D, cs->piecetexture); + + glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_S,GL_REPEAT); + glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_T,GL_REPEAT); + glTexImage2D(GL_TEXTURE_2D, 0, 3, checkImageWidth, + checkImageHeight, 0, GL_RGB, GL_UNSIGNED_BYTE, + &cs->checkImage[0][0]); +} + +/* build board texture (uniform noise in [180,180+50]) */ +static void make_board_texture(Chesscreen *cs) +{ + int i, j, c; + + for (i = 0; i < checkImageWidth; i++) { + for (j = 0; j < checkImageHeight; j++) { + c = 180 + random()%51; + cs->checkImage[i][j][0] = (GLubyte) c; + cs->checkImage[i][j][1] = (GLubyte) c; + cs->checkImage[i][j][2] = (GLubyte) c; + } + } + + glGenTextures(1, &cs->boardtexture); + glBindTexture(GL_TEXTURE_2D, cs->boardtexture); + + glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_S,GL_REPEAT); + glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_T,GL_REPEAT); + glTexImage2D(GL_TEXTURE_2D, 0, 3, checkImageWidth, + checkImageHeight, 0, GL_RGB, GL_UNSIGNED_BYTE, + &cs->checkImage[0][0]); +} + +/** handle X event (trackball) */ +ENTRYPOINT Bool chess_handle_event (ModeInfo *mi, XEvent *event) +{ + Chesscreen *cs = &qs[MI_SCREEN(mi)]; + + if(event->xany.type == ButtonPress && event->xbutton.button == Button1) { + cs->button_down_p = True; + gltrackball_start (cs->trackball, + event->xbutton.x, event->xbutton.y, + MI_WIDTH (mi), MI_HEIGHT (mi)); + return True; + } + else if(event->xany.type == ButtonRelease + && event->xbutton.button == Button1) { + cs->button_down_p = False; + return True; + } + else if (event->xany.type == ButtonPress && + (event->xbutton.button == Button4 || + event->xbutton.button == Button5 || + event->xbutton.button == Button6 || + event->xbutton.button == Button7)) + { + gltrackball_mousewheel (cs->trackball, event->xbutton.button, 5, + !event->xbutton.state); + return True; + } + else if(event->xany.type == MotionNotify && cs->button_down_p) { + gltrackball_track (cs->trackball, + event->xmotion.x, event->xmotion.y, + MI_WIDTH (mi), MI_HEIGHT (mi)); + return True; + } + + return False; +} + +static const GLfloat diffuse2[] = {1.0, 1.0, 1.0, 1.0}; +/*static const GLfloat ambient2[] = {0.7, 0.7, 0.7, 1.0};*/ +static const GLfloat shininess[] = {60.0}; +static const GLfloat specular[] = {0.4, 0.4, 0.4, 1.0}; + +/* configure lighting */ +static void setup_lights(Chesscreen *cs) +{ + glEnable(GL_LIGHTING); + glLightfv(GL_LIGHT0, GL_POSITION, cs->position); + glLightfv(GL_LIGHT0, GL_DIFFUSE, diffuse2); + glEnable(GL_LIGHT0); + +/* glLightModelfv(GL_LIGHT_MODEL_AMBIENT, ambient2); */ + + glMaterialfv(GL_FRONT_AND_BACK, GL_SHININESS, shininess); + glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, specular); + + glLightfv(GL_LIGHT1, GL_SPECULAR, diffuse2); + glLightfv(GL_LIGHT1, GL_DIFFUSE, diffuse2); + glEnable(GL_LIGHT1); +} + +/* draw pieces */ +static void drawPieces(ModeInfo *mi, Chesscreen *cs) +{ + int i, j; + + for(i = 0; i < BOARDSIZE; ++i) { + for(j = 0; j < BOARDSIZE; ++j) { + if(cs->game.board[i][j]) { + int c = cs->game.board[i][j]/PIECES; + glColor3fv(cs->colors[c]); + glCallList(cs->game.board[i][j]%PIECES); + mi->polygon_count += cs->poly_counts[cs->game.board[i][j]%PIECES]; + } + + glTranslatef(1.0, 0.0, 0.0); + } + + glTranslatef(-1.0*BOARDSIZE, 0.0, 1.0); + } + + glTranslatef(0.0, 0.0, -1.0*BOARDSIZE); +} + +/* draw pieces */ +static void drawPiecesShadow(ModeInfo *mi, Chesscreen *cs) +{ + int i, j; + + for(i = 0; i < BOARDSIZE; ++i) { + for(j = 0; j < BOARDSIZE; ++j) { + if(cs->game.board[i][j]) { + glColor4f(0.0, 0.0, 0.0, 0.4); + glCallList(cs->game.board[i][j]%PIECES); + mi->polygon_count += cs->poly_counts[cs->game.board[i][j]%PIECES]; + } + + glTranslatef(1.0, 0.0, 0.0); + } + + glTranslatef(-1.0*BOARDSIZE, 0.0, 1.0); + } + + glTranslatef(0.0, 0.0, -1.0*BOARDSIZE); +} + +/* draw a moving piece */ +static void drawMovingPiece(ModeInfo *mi, Chesscreen *cs, int shadow) +{ + int piece = cs->mpiece % PIECES; + + if (piece == NONE) return; + + glPushMatrix(); + + if(shadow) glColor4fv(MaterialShadow); + else glColor3fv(cs->colors[cs->mpiece/PIECES]); + + /** assume a queening. should be more general */ + if((cs->mpiece == PAWN && fabs(cs->to[0]) < 0.01) || + (cs->mpiece == BPAWN && fabs(cs->to[0]-7.0) < 0.01)) { + glTranslatef(cs->from[1]+cs->steps*cs->dx, 0.0, cs->from[0]+cs->steps*cs->dz); + + glColor4f(shadow ? MaterialShadow[0] : cs->colors[cs->mpiece/7][0], + shadow ? MaterialShadow[1] : cs->colors[cs->mpiece/7][1], + shadow ? MaterialShadow[2] : cs->colors[cs->mpiece/7][2], + (fabs(50.0-cs->steps))/50.0); + + piece = cs->steps < 50 ? PAWN : QUEEN; + + /* what a kludge */ + if(cs->steps == 99) + cs->mpiece = cs->mpiece == PAWN ? QUEEN : BQUEEN; + } + else if(cs->mpiece % PIECES == KNIGHT) { + /* If there is nothing in the path of a knight, move it by sliding, + just like the other pieces. But if there are any pieces on the + middle two squares in its path, the knight would intersect them, + so in that case, move it in an airborne arc. */ + GLfloat y; + int i, j; + Bool blocked_p = False; + int fromx = MIN(cs->from[1], cs->to[1]); + int fromy = MIN(cs->from[0], cs->to[0]); + int tox = MAX(cs->from[1], cs->to[1]); + int toy = MAX(cs->from[0], cs->to[0]); + if (fromx == tox-2) fromx = tox = fromx+1; + if (fromy == toy-2) fromy = toy = fromy+1; + for (i = fromy; i <= toy; i++) { + for (j = fromx; j <= tox; j++) { + if (cs->game.board[i][j]) { + blocked_p = True; + break; + } + } + } + + if (!blocked_p) + goto SLIDE; + + /* Move by hopping. */ + y = 1.5 * sin (M_PI * cs->steps / 100.0); + glTranslatef(cs->from[1]+cs->steps*cs->dx, y, + cs->from[0]+cs->steps*cs->dz); + + } else { + SLIDE: + /* Move by sliding. */ + glTranslatef(cs->from[1]+cs->steps*cs->dx, 0.0, cs->from[0]+cs->steps*cs->dz); + } + + + if(!cs->wire) + glEnable(GL_BLEND); + + glCallList(piece); + mi->polygon_count += cs->poly_counts[cs->mpiece % PIECES]; + + glMaterialfv(GL_FRONT_AND_BACK, GL_SHININESS, shininess); + glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, specular); + + glPopMatrix(); + + if(!cs->wire) + glDisable(GL_BLEND); +} + +/** code to squish a taken piece */ +static void drawTakePiece(ModeInfo *mi, Chesscreen *cs, int shadow) +{ + if(!cs->wire) + glEnable(GL_BLEND); + + glColor4f(shadow ? MaterialShadow[0] : cs->colors[cs->tpiece/7][0], + shadow ? MaterialShadow[1] : cs->colors[cs->tpiece/7][1], + shadow ? MaterialShadow[2] : cs->colors[cs->tpiece/7][2], + (100-1.6*cs->steps)/100.0); + + glTranslatef(cs->to[1], 0.0, cs->to[0]); + + if(cs->mpiece % PIECES == KNIGHT) + glScalef(1.0+cs->steps/100.0, 1.0, 1.0+cs->steps/100.0); + else + glScalef(1.0, 1 - cs->steps/50.0 > 0.01 ? 1 - cs->steps/50.0 : 0.01, 1.0); + glCallList(cs->tpiece % 7); + mi->polygon_count += cs->poly_counts[cs->tpiece % PIECES]; + + if(!cs->wire) + glDisable(GL_BLEND); +} + +/** draw board */ +static void drawBoard(ModeInfo *mi, Chesscreen *cs) +{ + int i, j; + + glBegin(GL_QUADS); + + for(i = 0; i < BOARDSIZE; ++i) + for(j = 0; j < BOARDSIZE; ++j) { + double ma1 = (i+j)%2 == 0 ? cs->mod*i : 0.0; + double mb1 = (i+j)%2 == 0 ? cs->mod*j : 0.0; + double ma2 = (i+j)%2 == 0 ? cs->mod*(i+1.0) : 0.01; + double mb2 = (i+j)%2 == 0 ? cs->mod*(j+1.0) : 0.01; + + /*glColor3fv(colors[(i+j)%2]);*/ + glColor4f(cs->colors[(i+j)%2][0], cs->colors[(i+j)%2][1], + cs->colors[(i+j)%2][2], 0.65); + + glNormal3f(0.0, 1.0, 0.0); +/* glTexCoord2f(mod*i, mod*(j+1.0)); */ + glTexCoord2f(ma1, mb2); + glVertex3f(i, 0.0, j + 1.0); +/* glTexCoord2f(mod*(i+1.0), mod*(j+1.0)); */ + glTexCoord2f(ma2, mb2); + glVertex3f(i + 1.0, 0.0, j + 1.0); + glTexCoord2f(ma2, mb1); +/* glTexCoord2f(mod*(i+1.0), mod*j); */ + glVertex3f(i + 1.0, 0.0, j); + glTexCoord2f(ma1, mb1); +/* glTexCoord2f(mod*i, mod*j); */ + glVertex3f(i, 0.0, j); + + mi->polygon_count++; + } + glEnd(); + + { + GLfloat off = 0.01; + GLfloat w = BOARDSIZE; + GLfloat h = 0.1; + + /* Give the board a slight lip. */ + /* #### oops, normals are wrong here, but you can't tell */ + + glColor3f(0.3, 0.3, 0.3); + glBegin (GL_QUADS); + glVertex3f (0, 0, 0); + glVertex3f (0, -h, 0); + glVertex3f (0, -h, w); + glVertex3f (0, 0, w); + + glVertex3f (0, 0, w); + glVertex3f (0, -h, w); + glVertex3f (w, -h, w); + glVertex3f (w, 0, w); + + glVertex3f (w, 0, w); + glVertex3f (w, -h, w); + glVertex3f (w, -h, 0); + glVertex3f (w, 0, 0); + + glVertex3f (w, 0, 0); + glVertex3f (w, -h, 0); + glVertex3f (0, -h, 0); + glVertex3f (0, 0, 0); + + glVertex3f (0, -h, 0); + glVertex3f (w, -h, 0); + glVertex3f (w, -h, w); + glVertex3f (0, -h, w); + glEnd(); + mi->polygon_count += 4; + + /* Fill in the underside of the board with an invisible black box + to hide the reflections that are not on tiles. Probably there's + a way to do this with stencils instead. + */ + w -= off*2; + h = 5; + + glPushMatrix(); + glTranslatef (off, 0, off); + glDisable(GL_LIGHTING); + glColor3f(0,0,0); + glBegin (GL_QUADS); + glVertex3f (0, 0, 0); + glVertex3f (0, -h, 0); + glVertex3f (0, -h, w); + glVertex3f (0, 0, w); + + glVertex3f (0, 0, w); + glVertex3f (0, -h, w); + glVertex3f (w, -h, w); + glVertex3f (w, 0, w); + + glVertex3f (w, 0, w); + glVertex3f (w, -h, w); + glVertex3f (w, -h, 0); + glVertex3f (w, 0, 0); + + glVertex3f (w, 0, 0); + glVertex3f (w, -h, 0); + glVertex3f (0, -h, 0); + glVertex3f (0, 0, 0); + + glVertex3f (0, -h, 0); + glVertex3f (w, -h, 0); + glVertex3f (w, -h, w); + glVertex3f (0, -h, w); + glEnd(); + mi->polygon_count += 4; + glPopMatrix(); + if (!cs->wire) + glEnable(GL_LIGHTING); + } +} + +static void draw_pieces(ModeInfo *mi, Chesscreen *cs, int wire) +{ + if (!cs->wire) { + glEnable(GL_TEXTURE_2D); + glBindTexture(GL_TEXTURE_2D, cs->piecetexture); + glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); + + glColor4f(0.5, 0.5, 0.5, 1.0); + glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, MaterialShadow); + } + + drawPieces(mi, cs); + if(cs->moving) drawMovingPiece(mi, cs, 0); + if(cs->take) drawTakePiece(mi, cs, 0); + glDisable(GL_TEXTURE_2D); +} + +static void draw_shadow_pieces(ModeInfo *mi, Chesscreen *cs, int wire) +{ + if (!cs->wire) { + glEnable(GL_TEXTURE_2D); + glBindTexture(GL_TEXTURE_2D, cs->piecetexture); + glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); + } + + /* use the stencil */ + glDisable(GL_LIGHTING); + glDisable(GL_COLOR_MATERIAL); + glDisable(GL_DEPTH_TEST); + glDisable(GL_TEXTURE_2D); + glDisable(GL_BLEND); + + glClear(GL_STENCIL_BUFFER_BIT); + glColorMask(0,0,0,0); + glEnable(GL_STENCIL_TEST); + + glStencilFunc(GL_ALWAYS, 1, 0xFFFFFFFFL); + glStencilOp(GL_KEEP, GL_KEEP, GL_INCR); + + + glPushMatrix(); + glTranslatef(0.0, 0.001, 0.0); + + /* draw the pieces */ + drawPiecesShadow(mi, cs); + if(cs->moving) drawMovingPiece(mi, cs, shadows); + if(cs->take) drawTakePiece(mi, cs, shadows); + + glPopMatrix(); + + + /* turn on drawing into colour buffer */ + glColorMask(1,1,1,1); + + /* programming with effect */ + glDisable(GL_LIGHTING); + glDisable(GL_COLOR_MATERIAL); + glDisable(GL_TEXTURE_2D); + + /* now draw the union of the shadows */ + + /* + + want to keep alpha values (alpha is involved in transition + effects of the active pieces). + + */ + glStencilFunc(GL_NOTEQUAL, 0, 0xFFFFFFFFL); + glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE); + + glEnable(GL_BLEND); + + glColor4fv(MaterialShadow); + + /* draw the board generously to fill the shadows */ + glBegin(GL_QUADS); + + glVertex3f(-1.0, 0.0, -1.0); + glVertex3f(-1.0, 0.0, BOARDSIZE + 1.0); + glVertex3f(1.0 + BOARDSIZE, 0.0, BOARDSIZE + 1.0); + glVertex3f(1.0 + BOARDSIZE, 0.0, -1.0); + + glEnd(); + + glDisable(GL_STENCIL_TEST); + + /* "pop" attributes */ + glEnable(GL_TEXTURE_2D); + glEnable(GL_COLOR_MATERIAL); + glEnable(GL_LIGHTING); + glEnable(GL_CULL_FACE); + + + +} + +enum {X, Y, Z, W}; +enum {A, B, C, D}; + +/* create a matrix that will project the desired shadow */ +static void shadowmatrix(GLfloat shadowMat[4][4], + GLfloat groundplane[4], + GLfloat lightpos[4]) +{ + GLfloat dot; + + /* find dot product between light position vector and ground plane normal */ + dot = groundplane[X] * lightpos[X] + + groundplane[Y] * lightpos[Y] + + groundplane[Z] * lightpos[Z] + + groundplane[W] * lightpos[W]; + + shadowMat[0][0] = dot - lightpos[X] * groundplane[X]; + shadowMat[1][0] = 0.f - lightpos[X] * groundplane[Y]; + shadowMat[2][0] = 0.f - lightpos[X] * groundplane[Z]; + shadowMat[3][0] = 0.f - lightpos[X] * groundplane[W]; + + shadowMat[X][1] = 0.f - lightpos[Y] * groundplane[X]; + shadowMat[1][1] = dot - lightpos[Y] * groundplane[Y]; + shadowMat[2][1] = 0.f - lightpos[Y] * groundplane[Z]; + shadowMat[3][1] = 0.f - lightpos[Y] * groundplane[W]; + + shadowMat[X][2] = 0.f - lightpos[Z] * groundplane[X]; + shadowMat[1][2] = 0.f - lightpos[Z] * groundplane[Y]; + shadowMat[2][2] = dot - lightpos[Z] * groundplane[Z]; + shadowMat[3][2] = 0.f - lightpos[Z] * groundplane[W]; + + shadowMat[X][3] = 0.f - lightpos[W] * groundplane[X]; + shadowMat[1][3] = 0.f - lightpos[W] * groundplane[Y]; + shadowMat[2][3] = 0.f - lightpos[W] * groundplane[Z]; + shadowMat[3][3] = dot - lightpos[W] * groundplane[W]; +} + +/** reflectionboard */ +static void draw_reflections(ModeInfo *mi, Chesscreen *cs) +{ + int i, j; + + glEnable(GL_STENCIL_TEST); + glStencilFunc(GL_ALWAYS, 1, 1); + glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE); + glColorMask(0,0,0,0); + glDisable(GL_CULL_FACE); + + glDisable(GL_DEPTH_TEST); + glBegin(GL_QUADS); + + /* only draw white squares */ + for(i = 0; i < BOARDSIZE; ++i) { + for(j = (BOARDSIZE+i) % 2; j < BOARDSIZE; j += 2) { + glVertex3f(i, 0.0, j + 1.0); + glVertex3f(i + 1.0, 0.0, j + 1.0); + glVertex3f(i + 1.0, 0.0, j); + glVertex3f(i, 0.0, j); + mi->polygon_count++; + } + } + glEnd(); + glEnable(GL_DEPTH_TEST); + + glColorMask(1, 1, 1, 1); + glStencilFunc(GL_EQUAL, 1, 1); + glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP); + + glPushMatrix(); + glScalef(1.0, -1.0, 1.0); + glTranslatef(0.5, 0.0, 0.5); + + glLightfv(GL_LIGHT0, GL_POSITION, cs->position); + draw_pieces(mi, cs, cs->wire); + glPopMatrix(); + + glDisable(GL_STENCIL_TEST); + glLightfv(GL_LIGHT0, GL_POSITION, cs->position); + + glEnable(GL_CULL_FACE); + glCullFace(GL_BACK); + glColorMask(1,1,1,1); +} + +/** draws the scene */ +static void display(ModeInfo *mi, Chesscreen *cs) +{ + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); + + mi->polygon_count = 0; + + glMatrixMode(GL_MODELVIEW); + glLoadIdentity(); + glRotatef(current_device_rotation(), 0, 0, 1); + + /** setup perspectiv */ + glTranslatef(0.0, 0.0, -1.5*BOARDSIZE); + glRotatef(30.0, 1.0, 0.0, 0.0); + gltrackball_rotate (cs->trackball); + + if (rotate) + glRotatef(cs->theta*100, 0.0, 1.0, 0.0); + glTranslatef(-0.5*BOARDSIZE, 0.0, -0.5*BOARDSIZE); + +/* cs->position[0] = 4.0 + 1.0*-sin(cs->theta*100*M_PI/180.0); */ +/* cs->position[2] = 4.0 + 1.0* cos(cs->theta*100*M_PI/180.0); */ +/* cs->position[1] = 5.0; */ + + /* this is the lone light that the shadow matrix is generated from */ + cs->position[0] = 1.0; + cs->position[2] = 1.0; + cs->position[1] = 16.0; + + cs->position2[0] = 4.0 + 8.0*-sin(cs->theta*100*M_PI/180.0); + cs->position2[2] = 4.0 + 8.0* cos(cs->theta*100*M_PI/180.0); + + if (!cs->wire) { + glEnable(GL_LIGHTING); + glLightfv(GL_LIGHT0, GL_POSITION, cs->position); + glLightfv(GL_LIGHT1, GL_POSITION, cs->position2); + glEnable(GL_LIGHT0); + } + + /** draw board, pieces */ + if(!cs->wire) { + glEnable(GL_LIGHTING); + glEnable(GL_COLOR_MATERIAL); + + if(reflections && !cs->wire) { + draw_reflections(mi, cs); + glEnable(GL_BLEND); + } + + glEnable(GL_TEXTURE_2D); + glBindTexture(GL_TEXTURE_2D, cs->boardtexture); + drawBoard(mi, cs); + glDisable(GL_TEXTURE_2D); + + if(shadows) { + /* render shadows */ + GLfloat m[4][4]; + shadowmatrix(m, cs->ground, cs->position); + + glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, MaterialShadow); + glEnable(GL_BLEND); + glDisable(GL_LIGHTING); + glDisable(GL_DEPTH_TEST); + + /* display ant shadow */ + glPushMatrix(); + glTranslatef(0.0, 0.001, 0.0); + glMultMatrixf(m[0]); + glTranslatef(0.5, 0.01, 0.5); + draw_shadow_pieces(mi, cs, cs->wire); + glPopMatrix(); + + glEnable(GL_LIGHTING); + glDisable(GL_BLEND); + glEnable(GL_DEPTH_TEST); + } + + if(reflections) + glDisable(GL_BLEND); + } + else + drawBoard(mi, cs); + + glTranslatef(0.5, 0.0, 0.5); + draw_pieces(mi, cs, cs->wire); + + if(!cs->wire) { + glDisable(GL_COLOR_MATERIAL); + glDisable(GL_LIGHTING); + } + + if (!cs->button_down_p) + cs->theta += .002; +} + +/** reshape handler */ +ENTRYPOINT void reshape_chess(ModeInfo *mi, int width, int height) +{ + GLfloat h = (GLfloat) height / (GLfloat) width; + glViewport(0,0, width, height); + glMatrixMode(GL_PROJECTION); + glLoadIdentity(); + gluPerspective(45, 1/h, 2.0, 30.0); + glMatrixMode(GL_MODELVIEW); +} + +/** initialization handler */ +ENTRYPOINT void init_chess(ModeInfo *mi) +{ + Chesscreen *cs; + int screen = MI_SCREEN(mi); + + if(!qs && + !(qs = (Chesscreen *) calloc(MI_NUM_SCREENS(mi), sizeof(Chesscreen)))) + return; + + cs = &qs[screen]; + cs->window = MI_WINDOW(mi); + cs->wire = MI_IS_WIREFRAME(mi); + cs->trackball = gltrackball_init (); + + cs->oldwhite = -1; + + cs->colors[0][0] = 1.0; + cs->colors[0][1] = 0.5; + cs->colors[0][2] = 0.0; + + cs->colors[1][0] = 0.6; + cs->colors[1][1] = 0.6; + cs->colors[1][2] = 0.6; + + cs->done = 1; + cs->count = 99; + cs->mod = 1.4; + +/* cs->position[0] = 0.0; */ +/* cs->position[1] = 5.0; */ +/* cs->position[2] = 5.0; */ +/* cs->position[3] = 1.0; */ + + cs->position[0] = 0.0; + cs->position[1] = 24.0; + cs->position[2] = 2.0; + cs->position[3] = 1.0; + + + cs->position2[0] = 5.0; + cs->position2[1] = 5.0; + cs->position2[2] = 5.0; + cs->position2[3] = 1.0; + + cs->ground[0] = 0.0; + cs->ground[1] = 1.0; + cs->ground[2] = 0.0; + cs->ground[3] = -0.00001; + + cs->oldgame = -1; + + + if((cs->glx_context = init_GL(mi))) + reshape_chess(mi, MI_WIDTH(mi), MI_HEIGHT(mi)); + else + MI_CLEARWINDOW(mi); + + if (!cs->wire) { + glDepthFunc(GL_LEQUAL); + glClearStencil(0); + glEnable(GL_CULL_FACE); + glCullFace(GL_BACK); + + make_piece_texture(cs); + make_board_texture(cs); + } + chessmodels_gen_lists( classic, cs->poly_counts); + +# ifdef HAVE_JWZGLES /* #### glPolygonMode other than GL_FILL unimplemented */ + cs->wire = 0; +# endif + + if(!cs->wire) { + setup_lights(cs); + glColorMaterial(GL_FRONT, GL_DIFFUSE); + glShadeModel(smooth ? GL_SMOOTH : GL_FLAT); + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + glEnable(GL_DEPTH_TEST); + } + else + glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); +} + +/** does dirty work drawing scene, moving pieces */ +ENTRYPOINT void draw_chess(ModeInfo *mi) +{ + Chesscreen *cs = &qs[MI_SCREEN(mi)]; + Window w = MI_WINDOW(mi); + Display *disp = MI_DISPLAY(mi); + + if(!cs->glx_context) + return; + + glXMakeCurrent(disp, w, *(cs->glx_context)); + + /** code for moving a piece */ + if(cs->moving && ++cs->steps == 100) { + cs->moving = cs->count = cs->steps = cs->take = 0; + cs->game.board[cs->game.moves[cs->mc][2]][cs->game.moves[cs->mc][3]] = cs->mpiece; + ++cs->mc; + + if(cs->mc == cs->game.movecount) { + cs->done = 1; + cs->mc = 0; + } + } + + if(++cs->count == 100) { + if(!cs->done) { + cs->mpiece = cs->game.board[cs->game.moves[cs->mc][0]][cs->game.moves[cs->mc][1]]; + cs->game.board[cs->game.moves[cs->mc][0]][cs->game.moves[cs->mc][1]] = NONE; + + if((cs->tpiece = cs->game.board[cs->game.moves[cs->mc][2]][cs->game.moves[cs->mc][3]])) { + cs->game.board[cs->game.moves[cs->mc][2]][cs->game.moves[cs->mc][3]] = NONE; + cs->take = 1; + } + + cs->from[0] = cs->game.moves[cs->mc][0]; + cs->from[1] = cs->game.moves[cs->mc][1]; + cs->to[0] = cs->game.moves[cs->mc][2]; + cs->to[1] = cs->game.moves[cs->mc][3]; + + cs->dz = (cs->to[0] - cs->from[0]) / 100; + cs->dx = (cs->to[1] - cs->from[1]) / 100; + cs->steps = 0; + cs->moving = 1; + } + else if(cs->done == 1) { + int newgame = cs->oldgame; + while(newgame == cs->oldgame) + newgame = random()%GAMES; + + /* mod the mod */ + cs->mod = 0.6 + (random()%20)/10.0; + + /* same old game */ + cs->oldgame = newgame; + cs->game = games[cs->oldgame]; + build_colors(cs); + cs->done = 2; + cs->count = 0; + } + else { + cs->done = 0; + cs->count = 0; + } + } + + /* set lighting */ + if(cs->done) { + glLightf(GL_LIGHT0, GL_CONSTANT_ATTENUATION, + cs->done == 1 ? 1.0+0.1*cs->count : 100.0/cs->count); + glLightf(GL_LIGHT1, GL_CONSTANT_ATTENUATION, + cs->done == 1 ? 1.0+0.1*cs->count : 100.0/cs->count); + glLightf(GL_LIGHT1, GL_LINEAR_ATTENUATION, 0.14); + glLightf(GL_LIGHT0, GL_LINEAR_ATTENUATION, 0.14); + } + + display(mi, cs); + + if(mi->fps_p) do_fps(mi); + glFinish(); + glXSwapBuffers(disp, w); +} + +/** bust it */ +ENTRYPOINT void release_chess(ModeInfo *mi) +{ + if(qs) + free((void *) qs); + qs = 0; + + FreeAllGL(mi); +} + +XSCREENSAVER_MODULE_2 ("Endgame", endgame, chess) + +#endif diff --git a/hacks/glx/endgame.man b/hacks/glx/endgame.man new file mode 100644 index 00000000..93ca5c39 --- /dev/null +++ b/hacks/glx/endgame.man @@ -0,0 +1,72 @@ +.TH XScreenSaver 1 "5-May-2004" +.SH NAME +endgame \- endgame chess screensaver +.SH SYNOPSIS +.B endgame +[\-display \fIhost:display.screen\fP] +[\-window] +[\-root] +[\-install] +[\-visual \fIvisual\fP] +[\-delay \fImicroseconds\fP] +[\-wireframe] +[\-fps] +.SH DESCRIPTION +endgame replays a brilliant chess ending +.SH OPTIONS +.I endgame +accepts the following options: +.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 \-install +Install a private colormap for the window. +.TP 8 +.B \-shadows +Project pieces against the board with dark blend. +.TP 8 +.B \-reflections +Reflect pieces in light board squares. +.TP 8 +.B \-classic +Use the original low-polygon piece models. +.TP 8 +.B \-visual \fIvisual\fP\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 \-wireframe +Render in wireframe instead of solid. +.B \-fps +Display the current frame rate, CPU load, and polygon count. +.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 BUGS +It's not unknown for this and other OpenGL hacks to fail under hardware accelaration (UtahGLX) and take the X server with them. Texture images must be 16x16 or 32x32 or 64x64 etc. +.SH SEE ALSO +.BR X (1), +.BR xscreensaver (1) +.BR xscreensaver\-demo (1), +.BR xscreensaver\-getimage (1) +.SH COPYRIGHT +Copyright \(co 2002 by Blair Tennessy. 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 +Blair Tennessy , 20-April-2002. + diff --git a/hacks/glx/engine.c b/hacks/glx/engine.c new file mode 100644 index 00000000..8c44bff3 --- /dev/null +++ b/hacks/glx/engine.c @@ -0,0 +1,1022 @@ +/* + * engine.c - GL representation of a 4 stroke engine + * + * version 2.00 + * + * Copyright (C) 2001 Ben Buxton (bb@cactii.net) + * modified by Ed Beroset (beroset@mindspring.com) + * new to 2.0 version is: + * - command line argument to specify number of cylinders + * - command line argument to specify included angle of engine + * - removed broken command line argument to specify rotation speed + * - included crankshaft shapes and firing orders for real engines + * verified using the Bosch _Automotive Handbook_, 5th edition, pp 402,403 + * + * 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. + */ + +#ifdef STANDALONE +#define DEFAULTS "*delay: 30000 \n" \ + "*showFPS: False \n" \ + "*titleFont: -*-helvetica-medium-r-normal-*-180-*\n" \ + +# define refresh_engine 0 +# include "xlockmore.h" /* from the xscreensaver distribution */ +#else /* !STANDALONE */ +# include "xlock.h" /* from the xlockmore distribution */ +#endif /* !STANDALONE */ + +#include "glxfonts.h" +#include "rotator.h" +#include "gltrackball.h" + +/* lifted from lament.c */ +#define RAND(n) ((long) ((random() & 0x7fffffff) % ((long) (n)))) +#define RANDSIGN() ((random() & 1) ? 1 : -1) + + +#ifdef USE_GL + +#define DEF_ENGINE "(none)" +#define DEF_TITLES "False" +#define DEF_SPIN "True" +#define DEF_MOVE "True" + +#undef countof +#define countof(x) (sizeof((x))/sizeof((*x))) + +static char *which_engine; +static int move; +static int spin; +static Bool do_titles; + +static XrmOptionDescRec opts[] = { + {"-engine", ".engine.engine", XrmoptionSepArg, DEF_ENGINE }, + {"-move", ".engine.move", XrmoptionNoArg, "True" }, + {"+move", ".engine.move", XrmoptionNoArg, "False" }, + {"-spin", ".engine.spin", XrmoptionNoArg, "True" }, + {"+spin", ".engine.spin", XrmoptionNoArg, "False" }, + { "-titles", ".engine.titles", XrmoptionNoArg, "True" }, + { "+titles", ".engine.titles", XrmoptionNoArg, "False" }, +}; + +static argtype vars[] = { + {&which_engine, "engine", "Engine", DEF_ENGINE, t_String}, + {&move, "move", "Move", DEF_MOVE, t_Bool}, + {&spin, "spin", "Spin", DEF_SPIN, t_Bool}, + {&do_titles, "titles", "Titles", DEF_TITLES, t_Bool}, +}; + +ENTRYPOINT ModeSpecOpt engine_opts = {countof(opts), opts, countof(vars), vars, NULL}; + +#ifdef USE_MODULES +ModStruct engine_description = +{"engine", "init_engine", "draw_engine", "release_engine", + "draw_engine", "init_engine", NULL, &engine_opts, + 1000, 1, 2, 1, 4, 1.0, "", + "A four stroke engine", 0, NULL}; + +#endif + +/* these defines are used to provide symbolic means + * by which to refer to various portions or multiples + * of a cyle in degrees + */ +#define HALFREV 180 +#define ONEREV 360 +#define TWOREV 720 + +#define MOVE_MULT 0.05 + +#define RAND_RANGE(min, max) ((min) + (max - min) * f_rand()) + + +typedef struct { + GLXContext *glx_context; + Window window; + GLfloat x, y, z; /* position */ + GLfloat dx, dy, dz; /* position */ + GLfloat an1, an2, an3; /* internal angle */ + GLfloat nx, ny, nz; /* spin vector */ + GLfloat a; /* spin angle */ + GLfloat da; /* spin speed */ + rotator *rot; + trackball_state *trackball; + Bool button_down_p; +# ifdef HAVE_GLBITMAP + XFontStruct *xfont; + GLuint font_dlist; +# else + texture_font_data *font_data; +# endif + char *engine_name; + int engineType; + int movepaused; + + float crankOffset; + float crankWidth; + + int win_w, win_h; + + float sin_table[TWOREV]; + float cos_table[TWOREV]; + float tan_table[TWOREV]; + + GLfloat boom_red[4]; + GLfloat boom_lpos[4]; + GLfloat boom_d, boom_wd; + int boom_time; + + GLfloat viewer[3], lookat[3]; + + int display_a; + GLfloat ln[730], yp[730], ang[730]; + int ln_init; + int lastPlug; + + GLuint shaft_list, piston_list; + int shaft_polys, piston_polys; + +} Engine; + +static Engine *engine = NULL; + +static const GLfloat lightpos[] = {7.0, 7.0, 12, 1.0}; +static const GLfloat light_sp[] = {0.8, 0.8, 0.8, 0.5}; +static const GLfloat red[] = {1.0, 0, 0, 1.0}; +static const GLfloat green[] = {0.0, 1, 0, 1.0}; +static const GLfloat blue[] = {0, 0, 1, 1.0}; +static const GLfloat white[] = {1.0, 1, 1, 1.0}; +static const GLfloat yellow_t[] = {1, 1, 0, 0.4}; + +static GLvoid normal(GLfloat [], GLfloat [], GLfloat [], + GLfloat *, GLfloat *, GLfloat *); + +/* + * this table represents both the firing order and included angle of engine. + * To simplify things, we always number from 0 starting at the flywheel and + * moving down the crankshaft toward the back of the engine. This doesn't + * always match manufacturer's schemes. For example, the Porsche 911 engine + * is a flat six with the following configuration (Porsche's numbering): + * + * 3 2 1 + * |= firing order is 1-6-2-4-3-5 in this diagram + * 6 5 4 + * + * We renumber these using our scheme but preserve the effective firing order: + * + * 0 2 4 + * |= firing order is 4-1-2-5-0-3 in this diagram + * 1 3 5 + * + * To avoid going completely insane, we also reorder these so the newly + * renumbered cylinder 0 is always first: 0-3-4-1-2-5 + * + * For a flat 6, the included angle is 180 degrees (0 would be a inline + * engine). Because these are all four-stroke engines, each piston goes + * through 720 degrees of rotation for each time the spark plug sparks, + * so in this case, we would use the following angles: + * + * cylinder firing order angle + * -------- ------------ ----- + * 0 0 0 + * 1 3 360 + * 2 4 240 + * 3 1 600 + * 4 2 480 + * 5 5 120 + * + */ + +typedef struct +{ + int cylinders; + int includedAngle; + int pistonAngle[12]; /* twelve cylinders should suffice... */ + int speed; /* step size in degrees for engine speed */ + const char *engineName; /* currently unused */ +} engine_type; + +static const engine_type engines[] = { + { 3, 0, { 0, 240, 480, 0, 0, 0, + 0, 0, 0, 0, 0, 0 }, 12, + "Honda Insight" }, + { 4, 0, { 0, 180, 540, 360, 0, 0, + 0, 0, 0, 0, 0, 0 }, 12, + "BMW M3" }, + { 4, 180, { 0, 360, 180, 540, 0, 0, + 0, 0, 0, 0, 0, 0 }, 12, + "VW Beetle" }, + { 5, 0, { 0, 576, 144, 432, 288, 0, + 0, 0, 0, 0, 0, 0 }, 12, + "Audi Quattro" }, + { 6, 0, { 0, 240, 480, 120, 600, 360, + 0, 0, 0, 0, 0, 0 }, 12, + "BMW M5" }, + { 6, 90, { 0, 360, 480, 120, 240, 600, + 0, 0, 0, 0, 0, 0 }, 12, + "Subaru XT" }, + { 6, 180, { 0, 360, 240, 600, 480, 120, + 0, 0, 0, 0, 0, 0 }, 12, + "Porsche 911" }, + { 8, 90, { 0, 450, 90, 180, 270, 360, + 540, 630, 0, 0, 0, 0 }, 15, + "Corvette Z06" }, + {10, 90, { 0, 72, 432, 504, 288, 360, + 144, 216, 576, 648, 0, 0 }, 12, + "Dodge Viper" }, + {12, 60, { 0, 300, 240, 540, 480, 60, + 120, 420, 600, 180, 360, 660 }, 12, + "Jaguar XKE" }, +}; + +/* this define is just a little shorter way of referring to members of the + * table above + */ +#define ENG engines[e->engineType] + +/* given a number of cylinders and an included angle, finds matching engine */ +static int +find_engine(char *name) +{ + unsigned int i; + char *s; + + if (!name || !*name || !strcasecmp (name, "(none)")) + return (random() % countof(engines)); + + for (s = name; *s; s++) + if (*s == '-' || *s == '_') *s = ' '; + + for (i = 0; i < countof(engines); i++) { + if (!strcasecmp(name, engines[i].engineName)) + return i; + } + + fprintf (stderr, "%s: unknown engine type \"%s\"\n", progname, name); + fprintf (stderr, "%s: available models are:\n", progname); + for (i = 0; i < countof(engines); i++) { + fprintf (stderr, "\t %-13s (%d cylinders", + engines[i].engineName, engines[i].cylinders); + if (engines[i].includedAngle == 0) + fprintf (stderr, ")\n"); + else if (engines[i].includedAngle == 180) + fprintf (stderr, ", flat)\n"); + else + fprintf (stderr, ", V)\n"); + } + exit(1); +} + +/* we use trig tables to speed things up - 200 calls to sin() + in one frame can be a bit harsh.. +*/ + +static void make_tables(Engine *e) +{ + int i; + float f; + + f = ONEREV / (M_PI * 2); + for (i = 0 ; i <= TWOREV ; i++) { + e->sin_table[i] = sin(i/f); + } + for (i = 0 ; i <= TWOREV ; i++) { + e->cos_table[i] = cos(i/f); + } + for (i = 0 ; i <= TWOREV ; i++) { + e->tan_table[i] = tan(i/f); + } +} + +/* if inner and outer are the same, we draw a cylinder, not a tube */ +/* for a tube, endcaps is 0 (none), 1 (left), 2 (right) or 3(both) */ +/* angle is how far around the axis to go (up to 360) */ + +static int cylinder (Engine *e, GLfloat x, GLfloat y, GLfloat z, + float length, float outer, float inner, int endcaps, int sang, int eang) +{ + int polys = 0; + int a; /* current angle around cylinder */ + int b = 0; /* previous */ + int angle, norm, step, sangle; + float z1, y1, z2, y2, ex=0; + float Z1, Y1, Z2, Y2, xl; + GLfloat y2c[TWOREV], z2c[TWOREV]; + int nsegs, tube = 0; + + glPushMatrix(); + nsegs = outer*(MAX(e->win_w, e->win_h)/200); + nsegs = MAX(nsegs, 6); + nsegs = MAX(nsegs, 40); + if (nsegs % 2) + nsegs += 1; + sangle = sang; + angle = eang; + z1 = e->cos_table[sangle]*outer+z; y1 = e->sin_table[sangle] * outer+y; + Z1 = e->cos_table[sangle] * inner+z; Y1 = e->sin_table[sangle]*inner+y ; + Z2 = z; + Y2 = y; + xl = x + length; + if (inner < outer && endcaps < 3) tube = 1; + step = ONEREV/nsegs; + + glBegin(GL_QUADS); + for (a = sangle ; a <= angle || b <= angle ; a+= step) { + y2=outer*(float)e->sin_table[a]+y; + z2=outer*(float)e->cos_table[a]+z; + if (endcaps) + y2c[a] = y2; z2c[a] = z2; /* cache for later */ + if (tube) { + Y2=inner*(float)e->sin_table[a]+y; + Z2=inner*(float)e->cos_table[a]+z; + } + glNormal3f(0, y1, z1); + glVertex3f(x,y1,z1); + glVertex3f(xl,y1,z1); + glNormal3f(0, y2, z2); + glVertex3f(xl,y2,z2); + glVertex3f(x,y2,z2); + polys++; + if (a == sangle && angle - sangle < ONEREV) { + if (tube) + glVertex3f(x, Y1, Z1); + else + glVertex3f(x, y, z); + glVertex3f(x, y1, z1); + glVertex3f(xl, y1, z1); + if (tube) + glVertex3f(xl, Z1, Z1); + else + glVertex3f(xl, y, z); + polys++; + } + if (tube) { + if (endcaps != 1) { + glNormal3f(-1, 0, 0); /* left end */ + glVertex3f(x, y1, z1); + glVertex3f(x, y2, z2); + glVertex3f(x, Y2, Z2); + glVertex3f(x, Y1, Z1); + polys++; + } + + glNormal3f(0, -Y1, -Z1); /* inner surface */ + glVertex3f(x, Y1, Z1); + glVertex3f(xl, Y1, Z1); + glNormal3f(0, -Y2, -Z2); + glVertex3f(xl, Y2, Z2); + glVertex3f(x, Y2, Z2); + polys++; + + if (endcaps != 2) { + glNormal3f(1, 0, 0); /* right end */ + glVertex3f(xl, y1, z1); + glVertex3f(xl, y2, z2); + glVertex3f(xl, Y2, Z2); + glVertex3f(xl, Y1, Z1); + polys++; + } + } + + z1=z2; y1=y2; + Z1=Z2; Y1=Y2; + b = a; + } + glEnd(); + + if (angle - sangle < ONEREV) { + GLfloat nx, ny, nz; + GLfloat v1[3], v2[3], v3[3]; + v1[0] = x; v1[1] = y; v1[2] = z; + v2[0] = x; v2[1] = y1; v2[2] = z1; + v3[0] = xl; v3[1] = y1; v3[2] = z1; + normal(&v2[0], &v1[0], &v3[0], &nx, &ny, &nz); + glBegin(GL_QUADS); + glNormal3f(nx, ny, nz); + glVertex3f(x, y, z); + glVertex3f(x, y1, z1); + glVertex3f(xl, y1, z1); + glVertex3f(xl, y, z); + polys++; + glEnd(); + } + if (endcaps) { + GLfloat end, start; + if (tube) { + if (endcaps == 1) { + end = 0; + start = 0; + } else if (endcaps == 2) { + start = end = length+0.01; + } else { + end = length+0.02; start = -0.01; + } + norm = (ex == length+0.01) ? -1 : 1; + } else { + end = length; + start = 0; + norm = -1; + } + + for(ex = start ; ex <= end ; ex += length) { + z1 = outer*e->cos_table[sangle]+z; + y1 = y+e->sin_table[sangle]*outer; + step = ONEREV/nsegs; + glBegin(GL_TRIANGLES); + b = 0; + for (a = sangle ; a <= angle || b <= angle; a+= step) { + glNormal3f(norm, 0, 0); + glVertex3f(x+ex,y, z); + glVertex3f(x+ex,y1,z1); + glVertex3f(x+ex,y2c[a],z2c[a]); + polys++; + y1 = y2c[a]; z1 = z2c[a]; + b = a; + } + if (!tube) norm = 1; + glEnd(); + } + } + glPopMatrix(); + return polys; +} + +/* this is just a convenience function to make a solid rod */ +static int rod (Engine *e, GLfloat x, GLfloat y, GLfloat z, float length, float diameter) +{ + return cylinder(e, x, y, z, length, diameter, diameter, 3, 0, ONEREV); +} + +static GLvoid normal(GLfloat v1[], GLfloat v2[], GLfloat v3[], + GLfloat *nx, GLfloat *ny, GLfloat *nz) +{ + GLfloat x, y, z, X, Y, Z; + + x = v2[0]-v1[0]; + y = v2[1]-v1[1]; + z = v2[2]-v1[2]; + X = v3[0]-v1[0]; + Y = v3[1]-v1[1]; + Z = v3[2]-v1[2]; + + *nx = Y*z - Z*y; + *ny = Z*x - X*z; + *nz = X*y - Y*x; + +} + + + +static int Rect(GLfloat x, GLfloat y, GLfloat z, GLfloat w, GLfloat h, + GLfloat t) +{ + int polys = 0; + GLfloat yh; + GLfloat xw; + GLfloat zt; + + yh = y+h; xw = x+w; zt = z - t; + + glBegin(GL_QUADS); /* front */ + glNormal3f(0, 0, 1); + glVertex3f(x, y, z); + glVertex3f(x, yh, z); + glVertex3f(xw, yh, z); + glVertex3f(xw, y, z); + polys++; + /* back */ + glNormal3f(0, 0, -1); + glVertex3f(x, y, zt); + glVertex3f(x, yh, zt); + glVertex3f(xw, yh, zt); + glVertex3f(xw, y, zt); + polys++; + /* top */ + glNormal3f(0, 1, 0); + glVertex3f(x, yh, z); + glVertex3f(x, yh, zt); + glVertex3f(xw, yh, zt); + glVertex3f(xw, yh, z); + polys++; + /* bottom */ + glNormal3f(0, -1, 0); + glVertex3f(x, y, z); + glVertex3f(x, y, zt); + glVertex3f(xw, y, zt); + glVertex3f(xw, y, z); + polys++; + /* left */ + glNormal3f(-1, 0, 0); + glVertex3f(x, y, z); + glVertex3f(x, y, zt); + glVertex3f(x, yh, zt); + glVertex3f(x, yh, z); + polys++; + /* right */ + glNormal3f(1, 0, 0); + glVertex3f(xw, y, z); + glVertex3f(xw, y, zt); + glVertex3f(xw, yh, zt); + glVertex3f(xw, yh, z); + polys++; + glEnd(); + return polys; +} + +static int makepiston(Engine *e) +{ + int polys = 0; + GLfloat colour[] = {0.6, 0.6, 0.6, 1.0}; + + e->piston_list = glGenLists(1); + glNewList(e->piston_list, GL_COMPILE); + glRotatef(90, 0, 0, 1); + glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, colour); + glMaterialfv(GL_FRONT, GL_SPECULAR, colour); + glMateriali(GL_FRONT, GL_SHININESS, 20); + polys += cylinder(e, 0, 0, 0, 2, 1, 0.7, 2, 0, ONEREV); /* body */ + colour[0] = colour[1] = colour[2] = 0.2; + glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, colour); + polys += cylinder(e, 1.6, 0, 0, 0.1, 1.05, 1.05, 0, 0, ONEREV); /* ring */ + polys += cylinder(e, 1.8, 0, 0, 0.1, 1.05, 1.05, 0, 0, ONEREV); /* ring */ + glEndList(); + return polys; +} + +static int CrankBit(Engine *e, GLfloat x) +{ + int polys = 0; + polys += Rect(x, -1.4, 0.5, 0.2, 1.8, 1); + polys += cylinder(e, x, -0.5, 0, 0.2, 2, 2, 1, 60, 120); + return polys; +} + +static int boom(Engine *e, GLfloat x, GLfloat y, int s) +{ + int polys = 0; + int flameOut = 720/ENG.speed/ENG.cylinders; + + if (e->boom_time == 0 && s) { + e->boom_red[0] = e->boom_red[1] = 0; + e->boom_d = 0.05; + e->boom_time++; + glEnable(GL_LIGHT1); + } else if (e->boom_time == 0 && !s) { + return polys; + } else if (e->boom_time >= 8 && e->boom_time < flameOut && !s) { + e->boom_time++; + e->boom_red[0] -= 0.2; e->boom_red[1] -= 0.1; + e->boom_d-= 0.04; + } else if (e->boom_time >= flameOut) { + e->boom_time = 0; + glDisable(GL_LIGHT1); + return polys; + } else { + e->boom_red[0] += 0.2; e->boom_red[1] += 0.1; + e->boom_d += 0.04; + e->boom_time++; + } + e->boom_lpos[0] = x-e->boom_d; e->boom_lpos[1] = y; + glLightfv(GL_LIGHT1, GL_POSITION, e->boom_lpos); + glLightfv(GL_LIGHT1, GL_DIFFUSE, e->boom_red); + glLightfv(GL_LIGHT1, GL_SPECULAR, e->boom_red); + glLightf(GL_LIGHT1, GL_LINEAR_ATTENUATION, 1.3); + glLighti(GL_LIGHT1, GL_CONSTANT_ATTENUATION, 0); + + glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, e->boom_red); + e->boom_wd = e->boom_d*3; + if (e->boom_wd > 0.7) e->boom_wd = 0.7; + glEnable(GL_BLEND); + glDepthMask(GL_FALSE); + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + polys += rod(e, x, y, 0, e->boom_d, e->boom_wd); + glDepthMask(GL_TRUE); + glDisable(GL_BLEND); + return polys; +} + +static int display(Engine *e) +{ + int polys = 0; + GLfloat zb, yb; + float rightSide; + int half; + int sides; + int j, b; + + glEnable(GL_LIGHTING); + glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT); + glLoadIdentity(); + gluLookAt(e->viewer[0], e->viewer[1], e->viewer[2], + e->lookat[0], e->lookat[1], e->lookat[2], + 0.0, 1.0, 0.0); + glPushMatrix(); + + glLightfv(GL_LIGHT0, GL_POSITION, lightpos); + glLightfv(GL_LIGHT0, GL_SPECULAR, light_sp); + glLightfv(GL_LIGHT0, GL_DIFFUSE, light_sp); + + if (move) { + double x, y, z; + get_position (e->rot, &x, &y, &z, !e->button_down_p); + glTranslatef(x*16-9, y*14-7, z*16-10); + } + + if (spin) { + double x, y, z; + + /* Do it twice because we don't track the device's orientation. */ + glRotatef( current_device_rotation(), 0, 0, 1); + gltrackball_rotate (e->trackball); + glRotatef(-current_device_rotation(), 0, 0, 1); + + get_rotation(e->rot, &x, &y, &z, !e->button_down_p); + glRotatef(x*ONEREV, 1.0, 0.0, 0.0); + glRotatef(y*ONEREV, 0.0, 1.0, 0.0); + glRotatef(x*ONEREV, 0.0, 0.0, 1.0); + } + +/* So the rotation appears around the centre of the engine */ + glTranslatef(-5, 0, 0); + +/* crankshaft */ + glPushMatrix(); + glRotatef(e->display_a, 1, 0, 0); + glCallList(e->shaft_list); + polys += e->shaft_polys; + glPopMatrix(); + + /* init the ln[] matrix for speed */ + if (e->ln_init == 0) { + for (e->ln_init = 0 ; e->ln_init < 730 ; e->ln_init++) { + zb = e->sin_table[e->ln_init]; + yb = e->cos_table[e->ln_init]; + /* y ordinate of piston */ + e->yp[e->ln_init] = yb + sqrt(25 - (zb*zb)); + /* length of rod */ + e->ln[e->ln_init] = sqrt(zb*zb + (yb-e->yp[e->ln_init])*(yb-e->yp[e->ln_init])); + /* angle of connecting rod */ + e->ang[e->ln_init] = asin(zb/5)*57; + e->ang[e->ln_init] *= -1; + } + } + + glPushMatrix(); + sides = (ENG.includedAngle == 0) ? 1 : 2; + for (half = 0; half < sides; half++, glRotatef(ENG.includedAngle,1,0,0)) + { + /* pistons */ + /* glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, white); */ + for (j = 0; j < ENG.cylinders; j += sides) + { + b = (e->display_a + ENG.pistonAngle[j+half]) % ONEREV; + glPushMatrix(); + glTranslatef(e->crankWidth/2 + e->crankOffset*(j+half), e->yp[b]-0.3, 0); + glCallList(e->piston_list); + polys += e->piston_polys; + glPopMatrix(); + } + /* spark plugs */ + glPushMatrix(); + glRotatef(90, 0, 0, 1); + glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, red); + for (j = 0; j < ENG.cylinders; j += sides) + { + polys += cylinder(e, 8.5, -e->crankWidth/2-e->crankOffset*(j+half), 0, + 0.5, 0.4, 0.3, 1, 0, ONEREV); + } + glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, white); + for (j = 0; j < ENG.cylinders; j += sides) + { + polys += rod(e, 8, -e->crankWidth/2-e->crankOffset*(j+half), 0, 0.5, 0.2); + polys += rod(e, 9, -e->crankWidth/2-e->crankOffset*(j+half), 0, 1, 0.15); + } + + /* rod */ + glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, blue); + for (j = 0; j < ENG.cylinders; j += sides) + { + b = (e->display_a+HALFREV+ENG.pistonAngle[j+half]) % TWOREV; + glPushMatrix(); + glRotatef(e->ang[b], 0, 1, 0); + polys += rod(e, + -e->cos_table[b], + -e->crankWidth/2-e->crankOffset*(j+half), + -e->sin_table[b], + e->ln[b], 0.2); + glPopMatrix(); + } + glPopMatrix(); + + /* engine block */ + glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, yellow_t); + glEnable(GL_BLEND); + glDepthMask(GL_FALSE); + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + rightSide = (sides > 1) ? 0 : 1.6; + /* left plate */ + polys += Rect(-e->crankWidth/2, -0.5, 1, 0.2, 9, 2); + /* right plate */ + polys += Rect(0.3+e->crankOffset*ENG.cylinders-rightSide, -0.5, 1, 0.2, 9, 2); + /* head plate */ + polys += Rect(-e->crankWidth/2+0.2, 8.3, 1, + e->crankWidth/2+0.1+e->crankOffset*ENG.cylinders-rightSide, 0.2, 2); + /* front rail */ + polys += Rect(-e->crankWidth/2+0.2, 3, 1, + e->crankWidth/2+0.1+e->crankOffset*ENG.cylinders-rightSide, 0.2, 0.2); + /* back rail */ + polys += Rect(-e->crankWidth/2+0.2, 3, -1+0.2, + e->crankWidth/2+0.1+e->crankOffset*ENG.cylinders-rightSide, 0.2, 0.2); + /* plates between cylinders */ + for (j=0; j < ENG.cylinders - (sides == 1); j += sides) + polys += Rect(0.4+e->crankWidth+e->crankOffset*(j-half), 3, 1, 1, 5.3, 2); + glDepthMask(GL_TRUE); + } + glPopMatrix(); + + /* see which of our plugs should fire now, if any */ + for (j = 0; j < ENG.cylinders; j++) + { + if (0 == ((e->display_a + ENG.pistonAngle[j]) % TWOREV)) + { + glPushMatrix(); + if (j & 1) + glRotatef(ENG.includedAngle,1,0,0); + glRotatef(90, 0, 0, 1); + polys += boom(e, 8, -e->crankWidth/2-e->crankOffset*j, 1); + e->lastPlug = j; + glPopMatrix(); + } + } + + if (e->lastPlug != j) + { + /* this code causes the last plug explosion to dim gradually */ + if (e->lastPlug & 1) + glRotatef(ENG.includedAngle, 1, 0, 0); + glRotatef(90, 0, 0, 1); + polys += boom(e, 8, -e->crankWidth/2-e->crankOffset*e->lastPlug, 0); + } + glDisable(GL_BLEND); + + e->display_a += ENG.speed; + if (e->display_a >= TWOREV) + e->display_a = 0; + glPopMatrix(); + glFlush(); + return polys; +} + +static int makeshaft (Engine *e) +{ + int polys = 0; + int j; + float crankThick = 0.2; + float crankDiam = 0.3; + + e->shaft_list = glGenLists(1); + glNewList(e->shaft_list, GL_COMPILE); + + glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, blue); + /* draw the flywheel */ + polys += cylinder(e, -2.5, 0, 0, 1, 3, 2.5, 0, 0, ONEREV); + polys += Rect(-2, -0.3, 2.8, 0.5, 0.6, 5.6); + polys += Rect(-2, -2.8, 0.3, 0.5, 5.6, 0.6); + + /* now make each of the shaft bits between the cranks, + * starting from the flywheel end which is at X-coord 0. + * the first cranskhaft bit is always 2 units long + */ + polys += rod(e, -2, 0, 0, 2, crankDiam); + + /* Each crank is crankWidth units wide and the total width of a + * cylinder assembly is 3.3 units. For inline engines, there is just + * a single crank per cylinder width. For other engine + * configurations, there is a crank between each pair of adjacent + * cylinders on one side of the engine, so the crankOffset length is + * halved. + */ + e->crankOffset = 3.3; + if (ENG.includedAngle != 0) + e->crankOffset /= 2; + for (j = 0; j < ENG.cylinders - 1; j++) + polys += rod(e, + e->crankWidth - crankThick + e->crankOffset*j, 0, 0, + e->crankOffset - e->crankWidth + 2 * crankThick, crankDiam); + /* the last bit connects to the engine wall on the non-flywheel end */ + polys += rod(e, e->crankWidth - crankThick + e->crankOffset*j, 0, 0, 0.9, crankDiam); + + + for (j = 0; j < ENG.cylinders; j++) + { + glPushMatrix(); + if (j & 1) + glRotatef(HALFREV+ENG.pistonAngle[j]+ENG.includedAngle,1,0,0); + else + glRotatef(HALFREV+ENG.pistonAngle[j],1,0,0); + /* draw wrist pin */ + glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, blue); + polys += rod(e, e->crankOffset*j, -1.0, 0.0, e->crankWidth, crankDiam); + glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, green); + /* draw right part of crank */ + polys += CrankBit(e, e->crankOffset*j); + /* draw left part of crank */ + polys += CrankBit(e, e->crankWidth-crankThick+e->crankOffset*j); + glPopMatrix(); + } + glEndList(); + return polys; +} + + +ENTRYPOINT void reshape_engine(ModeInfo *mi, int width, int height) +{ + Engine *e = &engine[MI_SCREEN(mi)]; + glViewport(0,0,(GLint)width, (GLint) height); + glMatrixMode(GL_PROJECTION); + glLoadIdentity(); + glFrustum(-1.0,1.0,-1.0,1.0,1.5,70.0); + glMatrixMode(GL_MODELVIEW); + e->win_h = height; + e->win_w = width; +} + + +ENTRYPOINT void init_engine(ModeInfo *mi) +{ + int screen = MI_SCREEN(mi); + Engine *e; + + if (engine == NULL) { + if ((engine = (Engine *) calloc(MI_NUM_SCREENS(mi), + sizeof(Engine))) == NULL) + return; + } + e = &engine[screen]; + e->window = MI_WINDOW(mi); + + e->x = e->y = e->z = e->a = e->an1 = e->nx = e->ny = e->nz = + e->dx = e->dy = e->dz = e->da = 0; + + if (move) { + e->dx = (float)(random() % 1000)/30000; + e->dy = (float)(random() % 1000)/30000; + e->dz = (float)(random() % 1000)/30000; + } else { + e->viewer[0] = 0; e->viewer[1] = 2; e->viewer[2] = 18; + e->lookat[0] = 0; e->lookat[1] = 0; e->lookat[2] = 0; + + } + if (spin) { + e->da = (float)(random() % 1000)/125 - 4; + e->nx = (float)(random() % 100) / 100; + e->ny = (float)(random() % 100) / 100; + e->nz = (float)(random() % 100) / 100; + } + + { + double spin_speed = 0.5; + double wander_speed = 0.01; + + e->crankWidth = 1.5; + e->boom_red[3] = 0.9; + e->boom_lpos[3] = 1; + + e->viewer[2] = 30; + + e->rot = make_rotator (spin ? spin_speed : 0, + spin ? spin_speed : 0, + spin ? spin_speed : 0, + 1.0, + move ? wander_speed : 0, + True); + + e->trackball = gltrackball_init (); + } + + if ((e->glx_context = init_GL(mi)) != NULL) { + reshape_engine(mi, MI_WIDTH(mi), MI_HEIGHT(mi)); + } else { + MI_CLEARWINDOW(mi); + } + glShadeModel(GL_SMOOTH); + glPolygonMode(GL_FRONT_AND_BACK,GL_FILL); + glEnable(GL_DEPTH_TEST); + glEnable(GL_LIGHTING); + glEnable(GL_LIGHT0); + glEnable(GL_NORMALIZE); + make_tables(e); + e->engineType = find_engine(which_engine); + + e->engine_name = malloc(200); + sprintf (e->engine_name, + "%s\n%s%d%s", + engines[e->engineType].engineName, + (engines[e->engineType].includedAngle == 0 ? "" : + engines[e->engineType].includedAngle == 180 ? "Flat " : "V"), + engines[e->engineType].cylinders, + (engines[e->engineType].includedAngle == 0 ? " Cylinder" : "") + ); + + e->shaft_polys = makeshaft(e); + e->piston_polys = makepiston(e); + +#ifdef HAVE_GLBITMAP + load_font (mi->dpy, "titleFont", &e->xfont, &e->font_dlist); +#else + e->font_data = load_texture_font (mi->dpy, "Font"); +#endif +} + +ENTRYPOINT Bool +engine_handle_event (ModeInfo *mi, XEvent *event) +{ + Engine *e = &engine[MI_SCREEN(mi)]; + + if (event->xany.type == ButtonPress && + event->xbutton.button == Button1) + { + e->button_down_p = True; + gltrackball_start (e->trackball, + event->xbutton.x, event->xbutton.y, + MI_WIDTH (mi), MI_HEIGHT (mi)); + e->movepaused = 1; + return True; + } + else if (event->xany.type == ButtonRelease && + event->xbutton.button == Button1) { + e->button_down_p = False; + e->movepaused = 0; + return True; + } + else if (event->xany.type == ButtonPress && + (event->xbutton.button == Button4 || + event->xbutton.button == Button5 || + event->xbutton.button == Button6 || + event->xbutton.button == Button7)) + { + gltrackball_mousewheel (e->trackball, event->xbutton.button, 10, + !!event->xbutton.state); + return True; + } + else if (event->xany.type == MotionNotify && + e->button_down_p) { + gltrackball_track (e->trackball, + event->xmotion.x, event->xmotion.y, + MI_WIDTH (mi), MI_HEIGHT (mi)); + return True; + } + return False; +} + +ENTRYPOINT void draw_engine(ModeInfo *mi) +{ + Engine *e = &engine[MI_SCREEN(mi)]; + Window w = MI_WINDOW(mi); + Display *disp = MI_DISPLAY(mi); + + if (!e->glx_context) + return; + + glXMakeCurrent(disp, w, *(e->glx_context)); + + + mi->polygon_count = display(e); + + glColor3f (1, 1, 0); + if (do_titles) + print_gl_string (mi->dpy, +# ifdef HAVE_GLBITMAP + e->xfont, e->font_dlist, +# else + e->font_data, +# endif + mi->xgwa.width, mi->xgwa.height, + 10, mi->xgwa.height - 10, + e->engine_name, False); + + if(mi->fps_p) do_fps(mi); + glFinish(); + glXSwapBuffers(disp, w); +} + +ENTRYPOINT void +release_engine(ModeInfo *mi) +{ + if (engine != NULL) { + (void) free((void *) engine); + engine = NULL; + } + FreeAllGL(mi); +} + +XSCREENSAVER_MODULE ("Engine", engine) + +#endif diff --git a/hacks/glx/engine.man b/hacks/glx/engine.man new file mode 100644 index 00000000..af794e5e --- /dev/null +++ b/hacks/glx/engine.man @@ -0,0 +1,80 @@ +.TH XScreenSaver 1 "" "X Version 11" +.SH NAME +engine - draws a 3D four-stroke engine. +.SH SYNOPSIS +.B engine +[\-display \fIhost:display.screen\fP] +[\-visual \fIvisual\fP] +[\-window] +[\-root] +[\-engine \fIname\fP] +[\-delay \fInumber\fP] +[\-no-move] +[\-no-spin] +[\-no-title] +[\-fps] +.SH DESCRIPTION +Draws a simple four-stroke engine that floats around the screen. +.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 \-engine \fIname\fP +What kind of engine to draw. Default: random. +Known models are: +"Honda Insight" (3), +"BMW M3" (4), +"VW Beetle" (flat 4), +"Audi Quattro" (5), +"BMW M5" (6), +"Subaru XT" (V6), +"Porsche 911" (flat 6), +"Corvette Z06" (V8), +"Dodge Viper" (V10), +and +"Jaguar XKE" (V12). +.TP 8 +.B \-delay \fInumber\fP +Per-frame delay, in microseconds. Default: 10000 (0.01 seconds.). +.TP 8 +.B \-move | \-no-move +Whether the object should wander around the screen. +.TP 8 +.B \-spin | \-no-spin +Whether the object should spin. +.TP 8 +.B \-fps +Display the current frame rate, CPU load, and polygon count. +.TP 8 +.B \-title | \-no-title +Whether to display the name of the engine being rendered. +.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 2002 by Ben Buxton. 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 +Ben Buxton. diff --git a/hacks/glx/extrusion-helix2.c b/hacks/glx/extrusion-helix2.c new file mode 100644 index 00000000..7a7152ff --- /dev/null +++ b/hacks/glx/extrusion-helix2.c @@ -0,0 +1,47 @@ + +/* + * helicoid (gernalized torus) demo + * + * FUNCTION: + * This code provides a very simple example of the helicoid primitive. + * Most of this code is required to set up OpenGL and GLUT, and very + * very little to set up the helix drawer. Don't blink! + * + * =======> MOUSE HOOKED UP TO RADIUS, DELTA-RADIUS < ======== + * + * HISTORY: + * Written by Linas Vepstas, March 1995 + */ + +#include "extrusion.h" + +/* controls shape of object */ +extern float lastx; +extern float lasty; + +void InitStuff_helix2 (void) +{ +} + +/* draw the helix shape */ +void DrawStuff_helix2 (void) +{ + glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + glColor3f (0.6, 0.3, 0.8); + + /* set up some matrices so that the object spins with the mouse */ + glPushMatrix (); +/* glTranslatef (0.0, 0.0, -80.0); */ +/* glRotatef (220.0, 0.0, 1.0, 0.0); */ +/* glRotatef (65.0, 1.0, 0.0, 0.0); */ + + /* Phew. FINALLY, Draw the helix -- */ + gleSetJoinStyle (TUBE_NORM_EDGE | TUBE_JN_ANGLE | TUBE_JN_CAP); + gleHelicoid (0.01*lastx, + 6.0, (0.01*lasty - 2.0), + -3.0, 4.0, 0x0, 0x0, 0.0, 1080.0); + + glPopMatrix (); + +} +/* ------------------------- end of file ----------------- */ diff --git a/hacks/glx/extrusion-helix3.c b/hacks/glx/extrusion-helix3.c new file mode 100644 index 00000000..7650f463 --- /dev/null +++ b/hacks/glx/extrusion-helix3.c @@ -0,0 +1,46 @@ + +/* + * helicoid (gernalized torus) demo + * + * FUNCTION: + * This code provides a very simple example of the helicoid primitive. + * Most of this code is required to set up OpenGL and GLUT, and very + * very little to set up the helix drawer. Don't blink! + * + * =======> MOUSE HOOKED UP TO SWEEP, HEIGHT < ======== + * + * HISTORY: + * Written by Linas Vepstas, March 1995 + */ + +#include "extrusion.h" + +/* controls shape of object */ +extern float lastx; +extern float lasty; + +void InitStuff_helix3 (void) +{ +} + +/* draw the helix shape */ +void DrawStuff_helix3 (void) +{ + glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + glColor3f (0.8, 0.3, 0.6); + + /* set up some matrices so that the object spins with the mouse */ + glPushMatrix (); +/* glTranslatef (0.0, 0.0, -80.0); */ +/* glRotatef (220.0, 0.0, 1.0, 0.0); */ +/* glRotatef (65.0, 1.0, 0.0, 0.0); */ + + /* Phew. FINALLY, Draw the helix -- */ + gleSetJoinStyle (TUBE_NORM_EDGE | TUBE_JN_ANGLE | TUBE_JN_CAP); + gleHelicoid (1.0, 6.0, -1.0, + 0.0, (0.02*lasty-2.0), 0x0, 0x0, 0.0, 6.0*lastx); + + glPopMatrix (); + +} +/* ------------------------- end of file ----------------- */ diff --git a/hacks/glx/extrusion-helix4.c b/hacks/glx/extrusion-helix4.c new file mode 100644 index 00000000..fbf16020 --- /dev/null +++ b/hacks/glx/extrusion-helix4.c @@ -0,0 +1,63 @@ + +/* + * helicoid (gernalized torus) demo + * + * FUNCTION: + * This code provides a very simple example of the helicoid primitive. + * Most of this code is required to set up OpenGL and GLUT, and very + * very little to set up the helix drawer. Don't blink! + * + * =======> MOUSE HOOKED UP TO AFFINE < ======== + * + * HISTORY: + * Written by Linas Vepstas, March 1995 + */ + +#include "extrusion.h" + +/* controls shape of object */ +extern float lastx; +extern float lasty; + +void InitStuff_helix4 (void) +{ +} + +/* draw the helix shape */ +void DrawStuff_helix4 (void) +{ + double affine[2][3]; + double delta_affine[2][3]; + + glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + glColor3f (0.7, 0.5, 0.3); + + /* set up some matrices so that the object spins with the mouse */ + glPushMatrix (); +/* glTranslatef (0.0, 0.0, -80.0); */ +/* glRotatef (220.0, 0.0, 1.0, 0.0); */ +/* glRotatef (65.0, 1.0, 0.0, 0.0); */ + + /* Phew. FINALLY, Draw the helix -- */ + affine [0][0] = 1.0/ (0.01*lastx); + affine [1][0] = 0.0; + affine [0][1] = 0.0; + affine [1][1] = 0.01*lastx; + affine [0][2] = 0.0; + affine [1][2] = 0.0; + + delta_affine [0][0] = 0.0; + delta_affine [1][0] = 0.03*lasty; + delta_affine [0][1] = -0.03*lasty; + delta_affine [1][1] = 0.0; + delta_affine [0][2] = 0.0; + delta_affine [1][2] = 0.0; + + gleSetJoinStyle (TUBE_NORM_EDGE | TUBE_JN_ANGLE | TUBE_JN_CAP); + gleHelicoid (1.0, 7.0, -1.0, + -4.0, 6.0, affine, delta_affine, 0.0, 980.0); + + glPopMatrix (); + +} +/* ------------------------- end of file ----------------- */ diff --git a/hacks/glx/extrusion-joinoffset.c b/hacks/glx/extrusion-joinoffset.c new file mode 100644 index 00000000..89a60e2c --- /dev/null +++ b/hacks/glx/extrusion-joinoffset.c @@ -0,0 +1,148 @@ + +/* cylinder drawing demo */ +/* this demo demonstrates the various join styles */ + +#include "extrusion.h" + +/* ------------------------------------------------------- */ + +/* the arrays in which we will store the polyline */ +#define NPTS 100 +static double points [NPTS][3]; +static float colors [NPTS][3]; +static int idx = 0; + +/* some utilities for filling that array */ +#define PSCALE 0.5 +#define PNT(x,y,z) { \ + points[idx][0] = PSCALE * x; \ + points[idx][1] = PSCALE * y; \ + points[idx][2] = PSCALE * z; \ + idx ++; \ +} + +#define COL(r,g,b) { \ + colors[idx][0] = r; \ + colors[idx][1] = g; \ + colors[idx][2] = b; \ +} + +/* the arrays in which we will store the contour */ +#define NCONTOUR 100 +static double contour_points [NCONTOUR][2]; +static int cidx = 0; + +/* some utilities for filling that array */ +#define C_PNT(x,y) { \ + contour_points[cidx][0] = x; \ + contour_points[cidx][1] = y; \ + cidx ++; \ +} + + +/* ------------------------------------------------------- */ +/* + * Initialize a bent shape with three segments. + * The data format is a polyline. + * + * NOTE that neither the first, nor the last segment are drawn. + * The first & last segment serve only to determine that angle + * at which the endcaps are drawn. + */ + +void InitStuff_joinoffset (void) +{ + COL (0.0, 0.0, 0.0); + PNT (16.0, 0.0, 0.0); + + COL (0.2, 0.8, 0.5); + PNT (0.0, -16.0, 0.0); + + COL (0.0, 0.8, 0.3); + PNT (-16.0, 0.0, 0.0); + + COL (0.8, 0.3, 0.0); + PNT (0.0, 16.0, 0.0); + + COL (0.2, 0.3, 0.9); + PNT (16.0, 0.0, 0.0); + + COL (0.2, 0.8, 0.5); + PNT (0.0, -16.0, 0.0); + + COL (0.0, 0.0, 0.0); + PNT (-16.0, 0.0, 0.0); + + C_PNT (-0.8, -0.5); + C_PNT (-1.8, 0.0); + C_PNT (-1.2, 0.3); + C_PNT (-0.7, 0.8); + C_PNT (-0.2, 1.3); + C_PNT (0.0, 1.6); + C_PNT (0.2, 1.3); + C_PNT (0.7, 0.8); + C_PNT (1.2, 0.3); + C_PNT (1.8, 0.0); + C_PNT (0.8, -0.5); + + gleSetJoinStyle (TUBE_JN_ANGLE | TUBE_CONTOUR_CLOSED | TUBE_JN_CAP); +} + +static double up_vector[3] = {1.0, 0.0, 0.0}; + +/* controls shape of object */ +extern float lastx; +extern float lasty; + +/* ------------------------------------------------------- */ +/* draw the extrusion */ + +void DrawStuff_joinoffset (void) +{ + double moved_contour [NCONTOUR][2]; + int style, save_style; + int i; + + for (i=0; i +#include + +/* =========================================================== */ + +#define SCALE 1.3 +#define CONTOUR(x,y) { \ + double ax, ay, alen; \ + contour[i][0] = SCALE * (x); \ + contour[i][1] = SCALE * (y); \ + if (i!=0) { \ + ax = contour[i][0] - contour[i-1][0]; \ + ay = contour[i][1] - contour[i-1][1]; \ + alen = 1.0 / sqrt (ax*ax + ay*ay); \ + ax *= alen; ay *= alen; \ + norms [i-1][0] = ay; \ + norms [i-1][1] = -ax; \ + } \ + i++; \ +} + +#define NUM_PTS (25) + +static double contour [NUM_PTS][2]; +static double norms [NUM_PTS][2]; + +static void init_contour (void) +{ + int i; + + /* outline of extrusion */ + i=0; + CONTOUR (1.0, 1.0); + CONTOUR (1.0, 2.9); + CONTOUR (0.9, 3.0); + CONTOUR (-0.9, 3.0); + CONTOUR (-1.0, 2.9); + + CONTOUR (-1.0, 1.0); + CONTOUR (-2.9, 1.0); + CONTOUR (-3.0, 0.9); + CONTOUR (-3.0, -0.9); + CONTOUR (-2.9, -1.0); + + CONTOUR (-1.0, -1.0); + CONTOUR (-1.0, -2.9); + CONTOUR (-0.9, -3.0); + CONTOUR (0.9, -3.0); + CONTOUR (1.0, -2.9); + + CONTOUR (1.0, -1.0); + CONTOUR (2.9, -1.0); + CONTOUR (3.0, -0.9); + CONTOUR (3.0, 0.9); + CONTOUR (2.9, 1.0); + + CONTOUR (1.0, 1.0); /* repeat so that last normal is computed */ +} + +/* =========================================================== */ + +/* controls shape of object */ +extern float lastx; +extern float lasty; + +void InitStuff_screw (void) +{ + int style; + + /* configure the pipeline */ + style = TUBE_JN_CAP; + style |= TUBE_CONTOUR_CLOSED; + style |= TUBE_NORM_FACET; + style |= TUBE_JN_ANGLE; + gleSetJoinStyle (style); + + init_contour(); +} + +/* =========================================================== */ + +void DrawStuff_screw (void) { + + glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + glColor3f (0.5, 0.6, 0.6); + + /* set up some matrices so that the object spins with the mouse */ + glPushMatrix (); + /* glTranslatef (0.0, 0.0, -80.0); */ + /* glRotatef (130.0, 0.0, 1.0, 0.0); */ + /* glRotatef (65.0, 1.0, 0.0, 0.0); */ + + /* draw the brand and the handle */ + gleScrew (20, contour, norms, + NULL, -6.0, 9.0, lasty); + + glPopMatrix (); +} + +/* ===================== END OF FILE ================== */ diff --git a/hacks/glx/extrusion-taper.c b/hacks/glx/extrusion-taper.c new file mode 100644 index 00000000..d2d05a15 --- /dev/null +++ b/hacks/glx/extrusion-taper.c @@ -0,0 +1,218 @@ +/* + * taper.c + * + * FUNCTION: + * Draws a tapered screw shape. + * + * HISTORY: + * -- created by Linas Vepstas October 1991 + * -- heavily modified to draw more texas shapes, Feb 1993, Linas + * -- converted to use GLUT -- December 1995, Linas + * + */ + +#include "extrusion.h" + +#include +#include + +#ifndef NULL +#define NULL ((void *) 0x0) +#endif /* NULL */ + +/* Some files do not define M_PI... */ +#ifndef M_PI +#define M_PI 3.14159265358979323846 +#endif + +/* =========================================================== */ + +#define SCALE 3.33333 +#define CONTOUR(x,y) { \ + double ax, ay, alen; \ + contour[i][0] = SCALE * (x); \ + contour[i][1] = SCALE * (y); \ + if (i!=0) { \ + ax = contour[i][0] - contour[i-1][0]; \ + ay = contour[i][1] - contour[i-1][1]; \ + alen = 1.0 / sqrt (ax*ax + ay*ay); \ + ax *= alen; ay *= alen; \ + norms [i-1][0] = ay; \ + norms [i-1][1] = -ax; \ + } \ + i++; \ +} + +#define NUM_PTS (25) + +static double contour [NUM_PTS][2]; +static double norms [NUM_PTS][2]; + +static void init_contour (void) +{ + int i; + + /* outline of extrusion */ + i=0; + CONTOUR (1.0, 1.0); + CONTOUR (1.0, 2.9); + CONTOUR (0.9, 3.0); + CONTOUR (-0.9, 3.0); + CONTOUR (-1.0, 2.9); + + CONTOUR (-1.0, 1.0); + CONTOUR (-2.9, 1.0); + CONTOUR (-3.0, 0.9); + CONTOUR (-3.0, -0.9); + CONTOUR (-2.9, -1.0); + + CONTOUR (-1.0, -1.0); + CONTOUR (-1.0, -2.9); + CONTOUR (-0.9, -3.0); + CONTOUR (0.9, -3.0); + CONTOUR (1.0, -2.9); + + CONTOUR (1.0, -1.0); + CONTOUR (2.9, -1.0); + CONTOUR (3.0, -0.9); + CONTOUR (3.0, 0.9); + CONTOUR (2.9, 1.0); + + CONTOUR (1.0, 1.0); /* repeat so that last normal is computed */ +} + +/* =========================================================== */ + +#define PSIZE 40 +static double path[PSIZE][3]; +static double twist[PSIZE]; +static double taper[PSIZE]; + +static void init_taper (void) { + int j; + double z, deltaz; + double ang, dang; + + z = -10.0; + deltaz = 0.5; + + ang = 0.0; + dang = 20.0; + for (j=0; j<40; j++) { + path[j][0] = 0x0; + path[j][1] = 0x0; + path[j][2] = z; + + twist[j] = ang; + ang += dang; + + taper[j] = 0.1 * sqrt (9.51*9.51 - z*z); + + z += deltaz; + } + + taper[0] = taper[1]; + taper[39] = taper[38]; + +} + +/* =========================================================== */ + +/* controls shape of object */ +extern float lastx; +extern float lasty; + +void InitStuff_taper (void) +{ + int style; + + /* configure the pipeline */ + style = TUBE_JN_CAP; + style |= TUBE_CONTOUR_CLOSED; + style |= TUBE_NORM_FACET; + style |= TUBE_JN_ANGLE; + gleSetJoinStyle (style); + + init_contour(); + init_taper(); +} + +/* =========================================================== */ + +static void gleTaper (int ncp, + gleDouble contour[][2], + gleDouble cont_normal[][2], + gleDouble up[3], + int npoints, + gleDouble point_array[][3], + float color_array[][3], + gleDouble taper[], + gleDouble twist[]) +{ + int j; + gleAffine *xforms; + double co, si, angle; + + /* malloc the extrusion array and the twist array */ + xforms = (gleAffine *) malloc (npoints * sizeof(gleAffine)); + + for (j=0; j +#include + +/* Some files do not define M_PI... */ +#ifndef M_PI +#define M_PI 3.14159265358979323846 +#endif + +/* controls shape of object */ +extern float lastx; +extern float lasty; + +#define OPENGL_10 +/* =========================================================== */ + +#define NUM_TOID1_PTS 5 +static double toid1_points[NUM_TOID1_PTS][3]; +static float toid1_colors [NUM_TOID1_PTS][3]; +static double toid1_twists [NUM_TOID1_PTS]; + +#define TSCALE (6.0) + +#define TPTS(x,y) { \ + toid1_points[i][0] = TSCALE * (x); \ + toid1_points[i][1] = TSCALE * (y); \ + toid1_points[i][2] = TSCALE * (0.0); \ + i++; \ +} + +#define TCOLS(r,g,b) { \ + toid1_colors[i][0] = (r); \ + toid1_colors[i][1] = (g); \ + toid1_colors[i][2] = (b); \ + i++; \ +} + +#define TXZERO() { \ + toid1_twists[i] = 0.0; \ + i++; \ +} + +static void init_toid1_line (void) +{ + int i; + + i=0; + TPTS (-1.1, 0.0); + TPTS (-1.0, 0.0); + TPTS (0.0, 0.0); + TPTS (1.0, 0.0); + TPTS (1.1, 0.0); + + i=0; + TCOLS (0.8, 0.8, 0.5); + TCOLS (0.8, 0.4, 0.5); + TCOLS (0.8, 0.8, 0.3); + TCOLS (0.4, 0.4, 0.5); + TCOLS (0.8, 0.8, 0.5); + + i=0; + TXZERO (); + TXZERO (); + TXZERO (); + TXZERO (); + TXZERO (); +} + +/* =========================================================== */ + +#define SCALE 0.6 +#define TWIST(x,y) { \ + double ax, ay, alen; \ + twistation[i][0] = SCALE * (x); \ + twistation[i][1] = SCALE * (y); \ + if (i!=0) { \ + ax = twistation[i][0] - twistation[i-1][0]; \ + ay = twistation[i][1] - twistation[i-1][1]; \ + alen = 1.0 / sqrt (ax*ax + ay*ay); \ + ax *= alen; ay *= alen; \ + twist_normal [i-1][0] = - ay; \ + twist_normal [i-1][1] = ax; \ + } \ + i++; \ +} + +#define NUM_TWIS_PTS (20) + +static double twistation [NUM_TWIS_PTS][2]; +static double twist_normal [NUM_TWIS_PTS][2]; + +static void init_tripples (void) +{ + int i; + double angle; + double co, si; + + /* outline of extrusion */ + i=0; + /* first, draw a semi-curcular "hump" */ + while (i< 11) { + angle = M_PI * ((double) i) / 10.0; + co = cos (angle); + si = sin (angle); + TWIST ((-7.0 -3.0*co), 1.8*si); + } + + /* now, a zig-zag corrugation */ + while (i< NUM_TWIS_PTS) { + TWIST ((-10.0 +(double) i), 0.0); + TWIST ((-9.5 +(double) i), 1.0); + } +} + + +/* =========================================================== */ + +#define V3F(x,y,z) { \ + float vvv[3]; \ + vvv[0] = x; vvv[1] = y; vvv[2] = z; v3f (vvv); \ +} + +#define N3F(x,y,z) { \ + float nnn[3]; \ + nnn[0] = x; nnn[1] = y; nnn[2] = z; n3f (nnn); \ +} + +/* =========================================================== */ + +void DrawStuff_twistoid (void) { + int i; + + toid1_twists[2] = (lastx-121.0) / 8.0; + + i=3; +/* + TPTS (1.0, lasty /400.0); + TPTS (1.1, 1.1 * lasty / 400.0); +*/ + TPTS (1.0, -(lasty-121.0) /200.0); + TPTS (1.1, -1.1 * (lasty-121.0) / 200.0); + +#ifdef IBM_GL_32 + rotate (230, 'x'); + rotate (230, 'y'); + scale (1.8, 1.8, 1.8); + + if (mono_color) { + RGBcolor (178, 178, 204); + twist_extrusion (NUM_TWIS_PTS, twistation, twist_normal, + NULL, NUM_TOID1_PTS, toid1_points, NULL, toid1_twists); + } else { + twist_extrusion (NUM_TWIS_PTS, twistation, twist_normal, + NULL, NUM_TOID1_PTS, toid1_points, toid1_colors, toid1_twists); + } +#endif + +#ifdef OPENGL_10 + glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + + glFrontFace(GL_CW); /* jwz */ + + /* set up some matrices so that the object spins with the mouse */ + glPushMatrix (); +/* glTranslatef (0.0, 0.0, -80.0); */ +/* glRotated (43.0, 1.0, 0.0, 0.0); */ +/* glRotated (43.0, 0.0, 1.0, 0.0); */ + glScaled (1.8, 1.8, 1.8); + gleTwistExtrusion (NUM_TWIS_PTS, twistation, twist_normal, + NULL, NUM_TOID1_PTS, toid1_points, NULL, toid1_twists); + glPopMatrix (); +#endif + +} + +/* =========================================================== */ + +void InitStuff_twistoid (void) +{ + int js; + + init_toid1_line (); + init_tripples (); + +#ifdef IBM_GL_32 + js = getjoinstyle (); + js &= ~TUBE_CONTOUR_CLOSED; + setjoinstyle (js); +#endif + +#ifdef OPENGL_10 + js = gleGetJoinStyle (); + js &= ~TUBE_CONTOUR_CLOSED; + gleSetJoinStyle (js); +#endif + +} + +/* ------------------ end of file -------------------- */ diff --git a/hacks/glx/extrusion.c b/hacks/glx/extrusion.c new file mode 100644 index 00000000..b05c3298 --- /dev/null +++ b/hacks/glx/extrusion.c @@ -0,0 +1,560 @@ +/* -*- Mode: C; tab-width: 4 -*- */ +/* extrusion --- extrusion module for xscreensaver */ +/*- + * Permission to use, copy, modify, and distribute this software and its + * documentation for any purpose and without fee is hereby granted, + * provided that the above copyright notice appear in all copies and that + * both that copyright notice and this permission notice appear in + * supporting documentation. + * + * This file is provided AS IS with no warranties of any kind. The author + * shall have no liability with respect to the infringement of copyrights, + * trade secrets or any patents by this file or any part thereof. In no + * event will the author be liable for any lost revenue or profits or + * other special, indirect and consequential damages. + + * Revision History: + * Tue Oct 19 22:24:47 PDT 1999 Initial creation by David Konerding + * + * + * Notes: + * This screensaver requires the GLE ("OpenGL Tubing and Extrusion Library") + * which can be obtained from http://www.linas.org/gle/index.html + */ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#ifdef STANDALONE +#define DEFAULTS "*delay: 20000 \n" \ + "*showFPS: False \n" \ + "*wireframe: False \n" + +# define refresh_extrusion 0 +# define release_extrusion 0 +# include "xlockmore.h" /* from the xscreensaver distribution */ +#else /* !STANDALONE */ +# include "xlock.h" /* from the xlockmore distribution */ +#endif /* !STANDALONE */ + +#ifdef USE_GL /* whole file */ + +#ifdef HAVE_XMU +# ifndef VMS +# include +#else /* VMS */ +# include +# endif /* VMS */ +#endif + +#undef countof +#define countof(x) (sizeof((x))/sizeof((*x))) + +#include "xpm-ximage.h" +#include "rotator.h" +#include "gltrackball.h" +#include "extrusion.h" + +#define checkImageWidth 64 +#define checkImageHeight 64 + + +#define WIDTH 640 +#define HEIGHT 480 + +#define DEF_LIGHT "True" +#define DEF_TEXTURE "False" +#define DEF_TEX_QUAL "False" +#define DEF_MIPMAP "False" +#define DEF_NAME "RANDOM" +#define DEF_IMAGE "BUILTIN" + +static int do_light; +static int do_texture; +static int do_tex_qual; +static int do_mipmap; +static char *which_name; +static char *which_image; + +static XrmOptionDescRec opts[] = { + {"-light", ".extrusion.light", XrmoptionNoArg, "true" }, + {"+light", ".extrusion.light", XrmoptionNoArg, "false" }, + {"-texture", ".extrusion.texture", XrmoptionNoArg, "true" }, + {"+texture", ".extrusion.texture", XrmoptionNoArg, "false" }, + {"-texture", ".extrusion.texture", XrmoptionNoArg, "true" }, + {"+texture_quality", ".extrusion.texture", XrmoptionNoArg, "false" }, + {"-texture_quality", ".extrusion.texture", XrmoptionNoArg, "true" }, + {"+mipmap", ".extrusion.mipmap", XrmoptionNoArg, "false" }, + {"-mipmap", ".extrusion.mipmap", XrmoptionNoArg, "true" }, + {"-name", ".extrusion.name", XrmoptionSepArg, 0 }, + {"-image", ".extrusion.image", XrmoptionSepArg, 0 }, +}; + + +static argtype vars[] = { + {&do_light, "light", "Light", DEF_LIGHT, t_Bool}, + {&do_texture, "texture", "Texture", DEF_TEXTURE, t_Bool}, + {&do_tex_qual, "texture_quality", "Texture_Quality", DEF_TEX_QUAL, t_Bool}, + {&do_mipmap, "mipmap", "Mipmap", DEF_MIPMAP, t_Bool}, + {&which_name, "name", "Name", DEF_NAME, t_String}, + {&which_image, "image", "Image", DEF_IMAGE, t_String}, +}; + + +static OptionStruct desc[] = +{ + {"-name num", "example 'name' to draw (helix2, helix3, helix4, joinoffset, screw, taper, twistoid)"}, + {"-/+ light", "whether to do enable lighting (slower)"}, + {"-/+ texture", "whether to apply a texture (slower)"}, + {"-image ", "texture image to load"}, + {"-/+ texture_quality", "whether to use texture smoothing (slower)"}, + {"-/+ mipmap", "whether to use texture mipmap (slower)"}, +}; + +ENTRYPOINT ModeSpecOpt extrusion_opts = {countof(opts), opts, countof(vars), vars, desc}; + +#ifdef USE_MODULES +ModStruct extrusion_description = +{"extrusion", "init_extrusion", "draw_extrusion", "release_extrusion", + "draw_extrusion", "init_extrusion", NULL, &extrusion_opts, + 1000, 1, 2, 1, 4, 1.0, "", + "OpenGL extrusion", 0, NULL}; +#endif + + +/* structure for holding the extrusion data */ +typedef struct { + int screen_width, screen_height; + GLXContext *glx_context; + rotator *rot; + trackball_state *trackball; + Bool button_down_p; + Bool button2_down_p; + int mouse_start_x, mouse_start_y; + int mouse_x, mouse_y; + int mouse_dx, mouse_dy; + Window window; + XColor fg, bg; + int extrusion_number; +} extrusionstruct; + +static extrusionstruct *Extrusion = NULL; + + + +/* set up a light */ +static const GLfloat lightOnePosition[] = {40.0, 40, 100.0, 0.0}; +static const GLfloat lightOneColor[] = {0.99, 0.99, 0.00, 1.0}; + +static const GLfloat lightTwoPosition[] = {-40.0, 40, 100.0, 0.0}; +static const GLfloat lightTwoColor[] = {0.00, 0.99, 0.99, 1.0}; + +float rot_x=0, rot_y=0, rot_z=0; +float lastx=0, lasty=0; + +static float max_lastx=400, max_lasty=400; +static float min_lastx=-400, min_lasty=-400; + +struct functions { + void (*InitStuff)(void); + void (*DrawStuff)(void); + char *name; +}; + +/* currently joinoffset and twistoid look funny- + like we're looking at them from the back or something +*/ + +static const struct functions funcs_ptr[] = { + {InitStuff_helix2, DrawStuff_helix2, "helix2"}, + {InitStuff_helix3, DrawStuff_helix3, "helix3"}, + {InitStuff_helix4, DrawStuff_helix4, "helix4"}, + {InitStuff_joinoffset, DrawStuff_joinoffset, "joinoffset"}, + {InitStuff_screw, DrawStuff_screw, "screw"}, + {InitStuff_taper, DrawStuff_taper, "taper"}, + {InitStuff_twistoid, DrawStuff_twistoid, "twistoid"}, +}; + +static int num_extrusions = countof(funcs_ptr); + + +/* BEGINNING OF FUNCTIONS */ + + +static GLubyte * +Generate_Image(int *width, int *height, int *format) +{ + GLubyte *result; + int i, j, c; + int counter=0; + + *width = checkImageWidth; + *height = checkImageHeight; + result = (GLubyte *)malloc(4 * (*width) * (*height)); + + counter = 0; + for (i = 0; i < checkImageWidth; i++) { + for (j = 0; j < checkImageHeight; j++) { + c = (((((i&0x8)==0))^(((j&0x8))==0)))*255; + result[counter++] = (GLubyte) c; + result[counter++] = (GLubyte) c; + result[counter++] = (GLubyte) c; + result[counter++] = (GLubyte) 255; + } + } + + *format = GL_RGBA; + return result; +} + + +/* Create a texture in OpenGL. First an image is loaded + and stored in a raster buffer, then it's */ +static void Create_Texture(ModeInfo *mi, const char *filename) +{ + int height, width; + GLubyte *image; + int format; + + if ( !strncmp(filename, "BUILTIN", 7)) + image = Generate_Image(&width, &height, &format); + else + { + XImage *ximage = xpm_file_to_ximage (MI_DISPLAY (mi), MI_VISUAL (mi), + MI_COLORMAP (mi), filename); + image = (GLubyte *) ximage->data; + width = ximage->width; + height = ximage->height; + format = GL_RGBA; + } + + /* GL_MODULATE or GL_DECAL depending on what you want */ + 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); + glPixelStorei(GL_UNPACK_ALIGNMENT, 1); + /* perhaps we can edge a bit more speed at the expense of quality */ + glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_FASTEST); + + if (do_tex_qual) { + /* with texture_quality, the min and mag filters look *much* nice but are *much* slower */ + glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR); + } + else { + /* default is to do it quick and dirty */ + /* if you have mipmaps turned on, but not texture quality, nothing will happen! */ + glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + } + + /* mipmaps make the image look much nicer */ + if (do_mipmap) + { + int status; + clear_gl_error(); + status = gluBuild2DMipmaps(GL_TEXTURE_2D, 3, width, height, format, + GL_UNSIGNED_BYTE, image); + if (status) + { + const char *s = (char *) gluErrorString (status); + fprintf (stderr, "%s: error mipmapping %dx%d texture: %s\n", + progname, width, height, + (s ? s : "(unknown)")); + exit (1); + } + check_gl_error("mipmapping"); + } + else + { + clear_gl_error(); + glTexImage2D(GL_TEXTURE_2D, 0, format, width, height, 0, + format, GL_UNSIGNED_BYTE, image); + check_gl_error("texture"); + } +} + + +static void +init_rotation (ModeInfo *mi) +{ + extrusionstruct *gp = &Extrusion[MI_SCREEN(mi)]; + double spin_speed = 0.5; + gp->rot = make_rotator (spin_speed, spin_speed, spin_speed, + 0.2, + 0.005, + True); + gp->trackball = gltrackball_init (); + + lastx = (random() % (int) (max_lastx - min_lastx)) + min_lastx; + lasty = (random() % (int) (max_lasty - min_lasty)) + min_lasty; +} + + +/* draw the extrusion once */ +ENTRYPOINT void +draw_extrusion(ModeInfo * mi) +{ + extrusionstruct *gp = &Extrusion[MI_SCREEN(mi)]; + Display *display = MI_DISPLAY(mi); + Window window = MI_WINDOW(mi); + + static const GLfloat color[4] = {0.6, 0.6, 0.4, 1.0}; + /* static const GLfloat spec[4] = {0.6, 0.6, 0.6, 1.0}; */ + /* static const GLfloat shiny = 40.0; */ + + double x, y, z; + + if (!gp->glx_context) + return; + + glXMakeCurrent(MI_DISPLAY(mi), MI_WINDOW(mi), *(gp->glx_context)); + + glPushMatrix(); + + gltrackball_rotate (gp->trackball); + + get_rotation (gp->rot, &x, &y, &z, + !(gp->button_down_p || gp->button2_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); + + /* track the mouse only if a button is down. */ + if (gp->button2_down_p) + { + gp->mouse_dx += gp->mouse_x - gp->mouse_start_x; + gp->mouse_dy += gp->mouse_y - gp->mouse_start_y; + gp->mouse_start_x = gp->mouse_x; + gp->mouse_start_y = gp->mouse_y; + } + + { + float scale = (max_lastx - min_lastx); + get_position (gp->rot, &x, &y, &z, + !(gp->button_down_p || gp->button2_down_p)); + lastx = x * scale + min_lastx + gp->mouse_dx; + lasty = y * scale + min_lasty + gp->mouse_dy; + } + + glScalef(0.5, 0.5, 0.5); + + /* glMaterialfv (GL_FRONT_AND_BACK, GL_SPECULAR, spec); */ + /* glMateriali (GL_FRONT_AND_BACK, GL_SHININESS, shiny); */ + + glMaterialfv (GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, color); + glFrontFace(GL_CCW); + + funcs_ptr[gp->extrusion_number].DrawStuff(); + + glPopMatrix(); + + if (mi->fps_p) do_fps (mi); + glXSwapBuffers(display, window); +} + + +/* set up lighting conditions */ +static void +SetupLight(void) +{ + glLightfv (GL_LIGHT0, GL_POSITION, lightOnePosition); + glLightfv (GL_LIGHT0, GL_DIFFUSE, lightOneColor); + glLightfv (GL_LIGHT1, GL_POSITION, lightTwoPosition); + glLightfv (GL_LIGHT1, GL_DIFFUSE, lightTwoColor); + + glEnable (GL_LIGHT0); + glEnable (GL_LIGHT1); + glEnable (GL_LIGHTING); + + glColorMaterial (GL_FRONT, GL_DIFFUSE); + glColorMaterial (GL_BACK, GL_DIFFUSE); + glEnable (GL_COLOR_MATERIAL); +} + +/* Standard reshape function */ +ENTRYPOINT void +reshape_extrusion (ModeInfo *mi, int width, int height) +{ + GLfloat h = (GLfloat) height / (GLfloat) width; + + glViewport (0, 0, (GLint) width, (GLint) height); + + glMatrixMode(GL_PROJECTION); + glLoadIdentity(); + gluPerspective (30.0, 1/h, 1.0, 100.0); + + glMatrixMode(GL_MODELVIEW); + glLoadIdentity(); + gluLookAt( 0.0, 0.0, 30.0, + 0.0, 0.0, 0.0, + 0.0, 1.0, 0.0); + + glClear(GL_COLOR_BUFFER_BIT); +} + + +/* decide which extrusion example to run */ +static void +chooseExtrusionExample (ModeInfo *mi) +{ + extrusionstruct *gp = &Extrusion[MI_SCREEN(mi)]; + int i; + /* call the extrusion init routine */ + + if (!strncmp(which_name, "RANDOM", strlen(which_name))) { + gp->extrusion_number = random() % num_extrusions; + } + else { + gp->extrusion_number=-1; + for (i=0; i < num_extrusions; i++) { + if (!strncmp(which_name, funcs_ptr[i].name, strlen(which_name))) { + gp->extrusion_number = i; + } + } + } + + if (gp->extrusion_number < 0 || gp->extrusion_number >= num_extrusions) { + fprintf(stderr, "%s: invalid extrusion example number!\n", progname); + fprintf(stderr, "%s: known extrusions:\n", progname); + for (i=0; i < num_extrusions; i++) + fprintf(stderr,"\t%s\n", funcs_ptr[i].name); + exit(1); + } + init_rotation(mi); + funcs_ptr[gp->extrusion_number].InitStuff(); +} + + +/* main OpenGL initialization routine */ +static void +initializeGL(ModeInfo *mi, GLsizei width, GLsizei height) +{ + int style; + int mode; + + reshape_extrusion(mi, width, height); + glViewport( 0, 0, width, height ); + + glEnable(GL_DEPTH_TEST); + glDisable (GL_CULL_FACE); + glLightModeli (GL_LIGHT_MODEL_TWO_SIDE, True); + glShadeModel(GL_SMOOTH); + +# ifdef HAVE_JWZGLES /* #### glPolygonMode other than GL_FILL unimplemented */ + MI_IS_WIREFRAME(mi) = 0; +# endif + + if (do_light) + SetupLight(); + if (MI_IS_WIREFRAME(mi)) { + glPolygonMode(GL_FRONT,GL_LINE); + glPolygonMode(GL_BACK,GL_LINE); + } + if (do_texture) { + Create_Texture(mi, which_image); + glEnable(GL_TEXTURE_2D); + + /* configure the pipeline */ + style = TUBE_JN_CAP; + style |= TUBE_CONTOUR_CLOSED; + style |= TUBE_NORM_FACET; + style |= TUBE_JN_ANGLE; + gleSetJoinStyle (style); + + if (do_texture) { + mode = GLE_TEXTURE_ENABLE | GLE_TEXTURE_VERTEX_MODEL_FLAT; + glMatrixMode (GL_TEXTURE); glLoadIdentity (); + glScalef (0.25, 0.1, 1); glMatrixMode (GL_MODELVIEW); + gleTextureMode (mode); + } + } + +} + +ENTRYPOINT Bool +extrusion_handle_event (ModeInfo *mi, XEvent *event) +{ + extrusionstruct *gp = &Extrusion[MI_SCREEN(mi)]; + + if (event->xany.type == ButtonPress && + (event->xbutton.button == Button4 || + event->xbutton.button == Button5 || + event->xbutton.button == Button6 || + event->xbutton.button == Button7)) + { + gltrackball_mousewheel (gp->trackball, event->xbutton.button, 10, + !!event->xbutton.state); + return True; + } + else if (event->xany.type == ButtonPress && /* rotate with left button */ + !event->xbutton.state) /* if no modifier keys */ + { + gp->button_down_p = True; + gltrackball_start (gp->trackball, + event->xbutton.x, event->xbutton.y, + MI_WIDTH (mi), MI_HEIGHT (mi)); + return True; + } + else if (event->xany.type == ButtonPress) /* deform with other buttons */ + { /* or with modifier keys */ + gp->button2_down_p = True; + gp->mouse_start_x = gp->mouse_x = event->xbutton.x; + gp->mouse_start_y = gp->mouse_y = event->xbutton.y; + return True; + } + else if (event->xany.type == ButtonRelease) + { + gp->button_down_p = False; + gp->button2_down_p = False; + return True; + } + else if (event->xany.type == MotionNotify) + { + if (gp->button_down_p) + gltrackball_track (gp->trackball, + event->xmotion.x, event->xmotion.y, + MI_WIDTH (mi), MI_HEIGHT (mi)); + if (gp->button2_down_p) + { + gp->mouse_x = event->xmotion.x; + gp->mouse_y = event->xmotion.y; + } + return True; + } + + return False; +} + + +/* xextrusion initialization routine */ +ENTRYPOINT void +init_extrusion (ModeInfo * mi) +{ + int screen = MI_SCREEN(mi); + extrusionstruct *gp; + + if (MI_IS_WIREFRAME(mi)) do_light = 0; + + if (Extrusion == NULL) { + if ((Extrusion = (extrusionstruct *) + calloc(MI_NUM_SCREENS(mi), sizeof (extrusionstruct))) == NULL) + return; + } + gp = &Extrusion[screen]; + + gp->window = MI_WINDOW(mi); + if ((gp->glx_context = init_GL(mi)) != NULL) { + reshape_extrusion(mi, MI_WIDTH(mi), MI_HEIGHT(mi)); + initializeGL(mi, MI_WIDTH(mi), MI_HEIGHT(mi)); + chooseExtrusionExample(mi); + } else { + MI_CLEARWINDOW(mi); + } + +} + +XSCREENSAVER_MODULE ("Extrusion", extrusion) + +#endif /* USE_GL */ diff --git a/hacks/glx/extrusion.h b/hacks/glx/extrusion.h new file mode 100644 index 00000000..226a4428 --- /dev/null +++ b/hacks/glx/extrusion.h @@ -0,0 +1,55 @@ +/* -*- Mode: C; tab-width: 4 -*- */ +/* extrusion --- extrusion module for xscreensaver */ +/*- + * Permission to use, copy, modify, and distribute this software and its + * documentation for any purpose and without fee is hereby granted, + * provided that the above copyright notice appear in all copies and that + * both that copyright notice and this permission notice appear in + * supporting documentation. + * + * This file is provided AS IS with no warranties of any kind. The author + * shall have no liability with respect to the infringement of copyrights, + * trade secrets or any patents by this file or any part thereof. In no + * event will the author be liable for any lost revenue or profits or + * other special, indirect and consequential damages. + */ + +#ifndef __XSCREENSAVER_EXTRUSION_H__ +#define __XSCREENSAVER_EXTRUSION_H__ + +#ifdef HAVE_CONFIG_H +# include +#endif + +#ifdef HAVE_COCOA +# include /* gle is included with GLUT on OSX */ +#else /* !HAVE_COCOA */ +# include +# include +# ifdef HAVE_GLE3 +# include +# else +# include +# endif +#endif /* !HAVE_COCOA */ + +#ifdef HAVE_JWZGLES +# include "jwzgles.h" +#endif /* HAVE_JWZGLES */ + +extern void InitStuff_helix2(void); +extern void DrawStuff_helix2(void); +extern void InitStuff_helix3(void); +extern void DrawStuff_helix3(void); +extern void InitStuff_helix4(void); +extern void DrawStuff_helix4(void); +extern void InitStuff_joinoffset(void); +extern void DrawStuff_joinoffset(void); +extern void InitStuff_screw(void); +extern void DrawStuff_screw(void); +extern void InitStuff_taper(void); +extern void DrawStuff_taper(void); +extern void InitStuff_twistoid(void); +extern void DrawStuff_twistoid(void); + +#endif /* __XSCREENSAVER_EXTRUSION_H__ */ diff --git a/hacks/glx/extrusion.man b/hacks/glx/extrusion.man new file mode 100644 index 00000000..e01d5736 --- /dev/null +++ b/hacks/glx/extrusion.man @@ -0,0 +1,71 @@ +.TH XScreenSaver 1 "" "X Version 11" +.SH NAME +extrusion - various rotating extruded shapes. +.SH SYNOPSIS +.B extrusion +[\-display \fIhost:display.screen\fP] +[\-visual \fIvisual\fP] +[\-window] +[\-root] +[\-delay \fInumber\fP] +[\-name \fIwhich\fP] +[\-no-light] +[\-wireframe] +[\-fps] +.SH DESCRIPTION +Draws various rotating extruded shapes that twist around, lengthen, and +turn inside out. +.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: 10000 (0.01 seconds.). +.TP 8 +.B \-name \fIwhich\fP +Which object to draw. Choices are: helix2, helix3, helix4, joinoffset, +screw, taper, and twistoid. +.TP 8 +.B \-light | \-no-light +Whether to light the scene, or use flat coloring. +.TP 8 +.B \-bitmap \fIfile\fP +The texture map to use. +.TP 8 +.B \-wireframe +Render in wireframe instead of solid. +.TP 8 +.B \-fps +Display the current frame rate, CPU load, and polygon count. +.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 2002 by Linas Vepstas and 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. +.SH AUTHOR +This screensaver was created by David Konerding from the samples that +come with the GL Extrusion library by Linas Vepstas. diff --git a/hacks/glx/flipflop.c b/hacks/glx/flipflop.c new file mode 100644 index 00000000..640f21f7 --- /dev/null +++ b/hacks/glx/flipflop.c @@ -0,0 +1,874 @@ +/* flipflop, Copyright (c) 2003 Kevin Ogden + * (c) 2006 Sergio Gutiérrez "Sergut" + * (c) 2008 Andrew Galante + * + * 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. + * + * + * 2003 Kevin Odgen First version + * 2006 Sergio Gutiérrez "Sergut" Made several parameters dynamic and selectable + * from the command line: size of the board, + * rotation speed and number of free squares; also + * added the "sticks" mode. + * 2008 Andrew Galante Added -textured option: textures the board with + * an image which gets scrambled as the tiles move + * + */ + +#define DEF_MODE "tiles" /* Default mode (options: "tiles", "sticks") */ +#define DEF_SIZEX "9" /* Default width of the board */ +#define DEF_SIZEY "9" /* Default length of the board */ + +#define DEF_BOARD_SIZE "0" /* "0" means "no value selected by user". It is changed */ +#define DEF_NUMSQUARES "0" /* in function init_flipflop() to its correct value (that */ +#define DEF_FREESQUARES "0" /* is a function of the size of the board and the mode)*/ + +#define DEF_SPIN "0.1" /* Default angular velocity: PI/10 rads/s */ + +#define DEF_TEXTURED "False" /* Default: do not grab an image for texturing */ + +#define DEF_STICK_THICK 54 /* Thickness for the sticks mode (over 100) */ +#define DEF_STICK_RATIO 80 /* Ratio of sticks/total squares (over 100) */ +#define DEF_TILE_THICK 4 /* Thickness for the tiles mode (over 100) */ +#define DEF_TILE_RATIO 95 /* Ratio of tiles/total squares (over 100) */ + +#ifdef STANDALONE +#define DEFAULTS "*delay: 20000 \n" \ + "*showFPS: False \n" \ + "*wireframe: False \n" + +# define refresh_flipflop 0 +# include "xlockmore.h" + +#else +# include "xlock.h" +#endif /* STANDALONE */ + +#ifdef USE_GL + +#include "gltrackball.h" + +#undef countof +#define countof(x) (sizeof((x))/sizeof((*x))) + +static XrmOptionDescRec opts[] = { + {"-sticks", ".mode", XrmoptionNoArg, "sticks"}, + {"-tiles", ".mode", XrmoptionNoArg, "tiles" }, + {"-mode", ".mode", XrmoptionSepArg, 0 }, + {"-size", ".size", XrmoptionSepArg, 0 }, + {"-size-x", ".sizex", XrmoptionSepArg, 0 }, + {"-size-y", ".sizey", XrmoptionSepArg, 0 }, + {"-count", ".numsquares", XrmoptionSepArg, 0 }, + {"-free", ".freesquares", XrmoptionSepArg, 0 }, + {"-spin", ".spin", XrmoptionSepArg, 0 }, + {"-texture", ".textured", XrmoptionNoArg, "True" }, + {"+texture", ".textured", XrmoptionNoArg, "False" }, +}; + +static int wire, clearbits; +static int board_x_size, board_y_size, board_avg_size; +static int numsquares, freesquares; +static float half_thick; +static float spin; +static char* flipflopmode_str="tiles"; +static int textured; + +static argtype vars[] = { + { &flipflopmode_str, "mode", "Mode", DEF_MODE, t_String}, + { &board_avg_size, "size", "Integer", DEF_BOARD_SIZE, t_Int}, + { &board_x_size, "sizex", "Integer", DEF_SIZEX, t_Int}, + { &board_y_size, "sizey", "Integer", DEF_SIZEY, t_Int}, + { &numsquares, "numsquares", "Integer", DEF_NUMSQUARES, t_Int}, + { &freesquares, "freesquares", "Integer", DEF_NUMSQUARES, t_Int}, + { &spin, "spin", "Float", DEF_SPIN, t_Float}, + { &textured, "textured", "Bool", DEF_TEXTURED, t_Bool}, +}; + +ENTRYPOINT ModeSpecOpt flipflop_opts = {countof(opts), opts, countof(vars), vars, NULL}; + +#ifdef USE_MODULES +ModStruct flipflop_description = + {"flipflop", "init_flipflop", "draw_flipflop", "release_flipflop", + "draw_flipflop", "init_flipflop", NULL, &flipflop_opts, + 1000, 1, 2, 1, 4, 1.0, "", + "Flipflop", 0, NULL}; + +#endif /* USE_MODULES */ + +typedef struct { + /* array specifying which squares are where (to avoid collisions) */ + /* -1 means empty otherwise integer represents square index 0 - n-1 */ + /* occupied[x*board_y_size+y] is the tile [x][y] (i.e. that starts at column x and row y)*/ + int *occupied; /* size: size_x * size_y */ + /* an array of xpositions of the squares */ + int *xpos; /* size: numsquares */ + /* array of y positions of the squares */ + int *ypos; /* size: numsquares */ + /* integer representing the direction of movement of a square */ + int *direction; /* 0 not, 1 x+, 2 y+, 3 x-, 4 y-*/ /* size: numsquares */ + /* angle of moving square (during a flip) */ + float *angle; /* size: numsquares */ + /* array of colors for a square (RGB) */ + /* eg. color[ 3*3 + 0 ] is the red component of square 3 */ + /* eg. color[ 4*3 + 1 ] is the green component of square 4 */ + /* eg. color[ 5*3 + 2 ] is the blue component of square 5 */ + /* ^-- n is the number of square */ + float *color; /* size: numsquares * 3 */ + /* array of texcoords for each square */ + /* tex[ n*4 + 0 ] is x texture coordinate of square n's left side */ + /* tex[ n*4 + 1 ] is y texture coordinate of square n's top side */ + /* tex[ n*4 + 2 ] is x texture coordinate of square n's right side */ + /* tex[ n*4 + 3 ] is y texture coordinate of square n's bottom side */ + float *tex; /* size: numsquares * 4 */ +} randsheet; + +typedef struct { + GLXContext *glx_context; + Window window; + trackball_state *trackball; + Bool button_down_p; + + randsheet *sheet; + + float theta; /* angle of rotation of the board */ + float flipspeed; /* amount of flip; 1 is a entire flip */ + float reldist; /* relative distace of camera from center */ + float energy; /* likelyhood that a square will attempt to move */ + + /* texture rectangle */ + float tex_x; + float tex_y; + float tex_width; + float tex_height; + + /* id of texture in use */ + GLuint texid; + + Bool mipmap; + Bool got_texture; + + GLfloat anisotropic; + +} Flipflopcreen; + +static Flipflopcreen *qs = NULL; + +#include "grab-ximage.h" + +static void randsheet_create( randsheet *rs ); +static void randsheet_initialize( randsheet *rs ); +static void randsheet_free( randsheet *rs ); +static int randsheet_new_move( randsheet* rs ); +static void randsheet_move( randsheet *rs, float rot ); +static int randsheet_draw( randsheet *rs ); +static void setup_lights(void); +static int drawBoard(Flipflopcreen *); +static int display(Flipflopcreen *c); +static int draw_sheet(float *tex); + + +/* configure lighting */ +static void +setup_lights(void) +{ + /* GLfloat position0[] = { board_avg_size*0.5, board_avg_size*0.1, board_avg_size*0.5, 1.0 }; */ + + /* GLfloat position0[] = { -board_avg_size*0.5, 0.2*board_avg_size, -board_avg_size*0.5, 1.0 }; */ + GLfloat position0[4]; + position0[0] = 0; + position0[1] = board_avg_size*0.3; + position0[2] = 0; + position0[3] = 1; + + if (wire) return; + + glEnable(GL_LIGHTING); + glLightfv(GL_LIGHT0, GL_POSITION, position0); + glEnable(GL_LIGHT0); +} + +ENTRYPOINT Bool +flipflop_handle_event (ModeInfo *mi, XEvent *event) +{ + Flipflopcreen *c = &qs[MI_SCREEN(mi)]; + + if (event->xany.type == ButtonPress && + event->xbutton.button == Button1) + { + c->button_down_p = True; + gltrackball_start (c->trackball, + event->xbutton.x, event->xbutton.y, + MI_WIDTH (mi), MI_HEIGHT (mi)); + return True; + } + else if (event->xany.type == ButtonRelease && + event->xbutton.button == Button1) + { + c->button_down_p = False; + return True; + } + else if (event->xany.type == ButtonPress && + (event->xbutton.button == Button4 || + event->xbutton.button == Button5 || + event->xbutton.button == Button6 || + event->xbutton.button == Button7)) + { + gltrackball_mousewheel (c->trackball, event->xbutton.button, 5, + !event->xbutton.state); + return True; + } + else if (event->xany.type == MotionNotify && + c->button_down_p) + { + gltrackball_track (c->trackball, + event->xmotion.x, event->xmotion.y, + MI_WIDTH (mi), MI_HEIGHT (mi)); + return True; + } + + return False; +} + +/* draw board */ +static int +drawBoard(Flipflopcreen *c) +{ + int i; + for( i=0; i < (c->energy) ; i++ ) { + randsheet_new_move( c->sheet ); + } + randsheet_move( c->sheet, c->flipspeed * 3.14159 ); + return randsheet_draw( c->sheet ); +} + + +static int +display(Flipflopcreen *c) +{ + GLfloat amb[] = { 0.8, 0.8, 0.8, 1.0 }; + int polys = 0; + + + glClear(clearbits); + glMatrixMode(GL_MODELVIEW); + glLoadIdentity(); + + glLightf(GL_LIGHT0, GL_CONSTANT_ATTENUATION, 1.2); + glLightf(GL_LIGHT0, GL_LINEAR_ATTENUATION, 0.15/board_avg_size ); + glLightf(GL_LIGHT0, GL_QUADRATIC_ATTENUATION, 0.15/board_avg_size ); + glLightfv(GL_LIGHT0, GL_AMBIENT, amb); + + + glRotatef(current_device_rotation(), 0, 0, 1); + + /** setup perspectif */ + glTranslatef(0.0, 0.0, -c->reldist*board_avg_size); + glRotatef(22.5, 1.0, 0.0, 0.0); + gltrackball_rotate (c->trackball); + glRotatef(c->theta*100, 0.0, 1.0, 0.0); + glTranslatef(-0.5*board_x_size, 0.0, -0.5*board_y_size); /* Center the board */ + + /* set texture */ + if(textured) + glBindTexture(GL_TEXTURE_2D, c->texid); + + polys = drawBoard(c); + + if (!c->button_down_p) { + c->theta += .01 * spin; + } + + return polys; +} + +ENTRYPOINT void +reshape_flipflop(ModeInfo *mi, int width, int height) +{ + GLfloat h = (GLfloat) height / (GLfloat) width; + glViewport(0,0, width, height); + glMatrixMode(GL_PROJECTION); + glLoadIdentity(); + gluPerspective(45, 1/h, 1.0, 300.0); + glMatrixMode(GL_MODELVIEW); +} + +static void +image_loaded_cb (const char *filename, XRectangle *geometry, + int image_width, int image_height, + int texture_width, int texture_height, + void *closure) +{ + Flipflopcreen *c = (Flipflopcreen *)closure; + int i, j; + int index = 0; + randsheet *rs = c->sheet; + + c->tex_x = (float)geometry->x / (float)texture_width; + c->tex_y = (float)geometry->y / (float)texture_height; + c->tex_width = (float)geometry->width / (float)texture_width; + c->tex_height = (float)geometry->height / (float)texture_height; + + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, + (c->mipmap ? GL_LINEAR_MIPMAP_LINEAR : GL_LINEAR)); + + if(c->anisotropic >= 1) + glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, c->anisotropic); + + glEnable(GL_TEXTURE_2D); + glEnable(GL_BLEND); + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + + for(i = 0; i < board_x_size && index < numsquares; i++) + for(j = 0; j < board_y_size && index < numsquares; j++) + { + /* arrange squares to form loaded image */ + rs->tex[ index*4 + 0 ] = c->tex_x + c->tex_width / board_x_size * (i + 0); + rs->tex[ index*4 + 1 ] = c->tex_y + c->tex_height / board_y_size * (j + 1); + rs->tex[ index*4 + 2 ] = c->tex_x + c->tex_width / board_x_size * (i + 1); + rs->tex[ index*4 + 3 ] = c->tex_y + c->tex_height / board_y_size * (j + 0); + rs->color[ index*3 + 0 ] = 1; + rs->color[ index*3 + 1 ] = 1; + rs->color[ index*3 + 2 ] = 1; + index++; + } + + c->got_texture = True; +} + +static void +get_texture(ModeInfo *modeinfo) +{ + Flipflopcreen *c = &qs[MI_SCREEN(modeinfo)]; + + c->got_texture = False; + c->mipmap = True; + load_texture_async (modeinfo->xgwa.screen, modeinfo->window, + *c->glx_context, 0, 0, c->mipmap, c->texid, + image_loaded_cb, c); +} + +ENTRYPOINT void +init_flipflop(ModeInfo *mi) +{ + int screen; + Flipflopcreen *c; + + if (MI_IS_WIREFRAME(mi)) textured = 0; + + /* Set all constants to their correct values */ + if (board_avg_size != 0) { /* general size specified by user */ + board_x_size = board_avg_size; + board_y_size = board_avg_size; + } else { + board_avg_size = (board_x_size + board_y_size) / 2; + } + if ((numsquares == 0) && (freesquares != 0)) { + numsquares = board_x_size * board_y_size - freesquares; + } + if (strcmp(flipflopmode_str, "tiles")) { + textured = 0; /* textures look dumb in stick mode */ + half_thick = 1.0 * DEF_STICK_THICK / 100.0; + if (numsquares == 0) { /* No value defined by user */ + numsquares = board_x_size * board_y_size * DEF_STICK_RATIO / 100; + } + } else { + half_thick = 1.0 * DEF_TILE_THICK / 100.0; + if (numsquares == 0) { /* No value defined by user */ + numsquares = board_x_size * board_y_size * DEF_TILE_RATIO/ 100;; + } + } + if (board_avg_size < 2) { + fprintf (stderr,"%s: the board must be at least 2x2.\n", progname); + exit(1); + } + if ((board_x_size < 1) || (board_y_size < 1) || (numsquares < 1)) { + fprintf (stderr,"%s: the number of elements ('-count') and the dimensions of the board ('-size-x', '-size-y') must be positive integers.\n", progname); + exit(1); + } + if (board_x_size * board_y_size <= numsquares) { + fprintf (stderr,"%s: the number of elements ('-count') that you specified is too big \n for the dimensions of the board ('-size-x', '-size-y'). Nothing will move.\n", progname); + } + + screen = MI_SCREEN(mi); + wire = MI_IS_WIREFRAME(mi); + + if(!qs && + !(qs = (Flipflopcreen *) calloc(MI_NUM_SCREENS(mi), sizeof(Flipflopcreen)))) + return; + + c = &qs[screen]; + c->window = MI_WINDOW(mi); + c->trackball = gltrackball_init (); + + c->flipspeed = 0.03; + c->reldist = 1; + c->energy = 40; + + if((c->glx_context = init_GL(mi))) + reshape_flipflop(mi, MI_WIDTH(mi), MI_HEIGHT(mi)); + else + MI_CLEARWINDOW(mi); + + /* At this point, all the constants have already been set, */ + /* so we can create the board */ + c->sheet = (randsheet*) malloc(sizeof(randsheet)); + randsheet_create( c->sheet ); + + clearbits = GL_COLOR_BUFFER_BIT; + + glColorMaterial(GL_FRONT, GL_AMBIENT_AND_DIFFUSE); + glEnable(GL_COLOR_MATERIAL); + setup_lights(); + + glEnable(GL_DEPTH_TEST); + clearbits |= GL_DEPTH_BUFFER_BIT; + glEnable(GL_CULL_FACE); + glCullFace(GL_BACK); + + randsheet_initialize( c->sheet ); + if( textured ){ + /* check for anisotropic filtering */ + if(strstr((char *)glGetString(GL_EXTENSIONS), + "GL_EXT_texture_filter_anisotropic")) + glGetFloatv(GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, &c->anisotropic); + else + c->anisotropic = 0; + + /* allocate a new texture and get it */ + glGenTextures(1, &c->texid); + get_texture(mi); + } +} + +ENTRYPOINT void +draw_flipflop(ModeInfo *mi) +{ + Flipflopcreen *c = &qs[MI_SCREEN(mi)]; + Window w = MI_WINDOW(mi); + Display *disp = MI_DISPLAY(mi); + + if(!c->glx_context || (textured && !c->got_texture)) + return; + + glXMakeCurrent(disp, w, *(c->glx_context)); + + mi->polygon_count = display(c); + + if(mi->fps_p){ + do_fps(mi); + } + + glFinish(); + glXSwapBuffers(disp, w); + + +} + +ENTRYPOINT void +release_flipflop(ModeInfo *mi) +{ + if(qs) { + int screen; + + for (screen = 0; screen < MI_NUM_SCREENS(mi); screen++) + { + Flipflopcreen *c = &qs[MI_SCREEN(mi)]; + if (c->glx_context) + c->glx_context = 0; + if (c->sheet) { + randsheet_free(c->sheet); + free (c->sheet); + c->sheet = 0; + } + } + free(qs); + qs = 0; + } + + FreeAllGL(mi); +} + +/*** ADDED RANDSHEET FUNCTIONS ***/ + +static int +draw_sheet(float *tex) +{ + int polys = 0; + glBegin( wire ? GL_LINE_LOOP : GL_QUADS ); + + glNormal3f( 0, -1, 0 ); + glTexCoord2f(tex[0], tex[3]); + glVertex3f( half_thick, -half_thick, half_thick ); + glTexCoord2f(tex[2], tex[3]); + glVertex3f( 1-half_thick, -half_thick, half_thick ); + glTexCoord2f(tex[2], tex[1]); + glVertex3f( 1-half_thick, -half_thick, 1-half_thick); + glTexCoord2f(tex[0], tex[1]); + glVertex3f( half_thick, -half_thick, 1-half_thick ); + polys++; + + if (wire) { glEnd(); glBegin (GL_LINE_LOOP); } + + /* back */ + glNormal3f( 0, 1, 0 ); + glTexCoord2f(tex[0], tex[1]); + glVertex3f( half_thick, half_thick, 1-half_thick ); + glTexCoord2f(tex[2], tex[1]); + glVertex3f( 1-half_thick, half_thick, 1-half_thick); + glTexCoord2f(tex[2], tex[3]); + glVertex3f( 1-half_thick, half_thick, half_thick ); + glTexCoord2f(tex[0], tex[3]); + glVertex3f( half_thick, half_thick, half_thick ); + polys++; + + if (wire) { glEnd(); return polys; } + + /* 4 edges!!! weee.... */ + glNormal3f( 0, 0, -1 ); + glTexCoord2f(tex[0], tex[3]); + glVertex3f( half_thick, half_thick, half_thick ); + glTexCoord2f(tex[2], tex[3]); + glVertex3f( 1-half_thick, half_thick, half_thick ); + glTexCoord2f(tex[2], tex[3]); + glVertex3f( 1-half_thick, -half_thick, half_thick ); + glTexCoord2f(tex[0], tex[3]); + glVertex3f( half_thick, -half_thick, half_thick ); + polys++; + glNormal3f( 0, 0, 1 ); + glTexCoord2f(tex[0], tex[1]); + glVertex3f( half_thick, half_thick, 1-half_thick ); + glTexCoord2f(tex[0], tex[1]); + glVertex3f( half_thick, -half_thick, 1-half_thick ); + glTexCoord2f(tex[2], tex[1]); + glVertex3f( 1-half_thick, -half_thick, 1-half_thick ); + glTexCoord2f(tex[2], tex[1]); + glVertex3f( 1-half_thick, half_thick, 1-half_thick ); + polys++; + glNormal3f( 1, 0, 0 ); + glTexCoord2f(tex[2], tex[1]); + glVertex3f( 1-half_thick, half_thick, 1-half_thick ); + glTexCoord2f(tex[2], tex[1]); + glVertex3f( 1-half_thick, -half_thick, 1-half_thick ); + glTexCoord2f(tex[2], tex[3]); + glVertex3f( 1-half_thick, -half_thick, half_thick ); + glTexCoord2f(tex[2], tex[3]); + glVertex3f( 1-half_thick, half_thick, half_thick ); + polys++; + glNormal3f( -1, 0, 0 ); + glTexCoord2f(tex[0], tex[1]); + glVertex3f( half_thick, half_thick, 1-half_thick ); + glTexCoord2f(tex[0], tex[3]); + glVertex3f( half_thick, half_thick, half_thick ); + glTexCoord2f(tex[0], tex[3]); + glVertex3f( half_thick, -half_thick, half_thick ); + glTexCoord2f(tex[0], tex[1]); + glVertex3f( half_thick, -half_thick, 1-half_thick ); + polys++; + glEnd(); + + return polys; +} + +/* Reserve memory for the randsheet */ +static void +randsheet_create( randsheet *rs ) +{ + rs -> occupied = (int*) malloc(board_x_size*board_y_size * sizeof(int)); + rs -> xpos = (int*) malloc(numsquares * sizeof(int)); + rs -> ypos = (int*) malloc(numsquares * sizeof(int)); + rs -> direction = (int*) malloc(numsquares * sizeof(int)); + rs -> angle = (float*) malloc(numsquares * sizeof(float)); + rs -> color = (float*) malloc(numsquares*3 * sizeof(float)); + rs -> tex = (float*) malloc(numsquares*4 * sizeof(float)); +} + +/* Free reserved memory for the randsheet */ +static void +randsheet_free( randsheet *rs ) +{ + free(rs->occupied); + free(rs->xpos); + free(rs->ypos); + free(rs->direction); + free(rs->angle); + free(rs->color); + free(rs->tex); +} + +static void +randsheet_initialize( randsheet *rs ) +{ + int i, j, index; + index = 0; + /* put the moving sheets on the board */ + for( i = 0; i < board_x_size; i++ ) + { + for( j = 0; j < board_y_size; j++ ) + { + /* initially fill up a corner with the moving squares */ + if( index < numsquares ) + { + rs->occupied[ i * board_y_size + j ] = index; + rs->xpos[ index ] = i; + rs->ypos[ index ] = j; + /* have the square colors start out as a pattern */ + rs->color[ index*3 + 0 ] = ((i+j)%3 == 0)||((i+j+1)%3 == 0); + rs->color[ index*3 + 1 ] = ((i+j+1)%3 == 0); + rs->color[ index*3 + 2 ] = ((i+j+2)%3 == 0); + index++; + } + /* leave everything else empty*/ + else + { + rs->occupied[ i * board_y_size + j ] = -1; + } + } + } + /* initially everything is at rest */ + for( i=0; idirection[ i ] = 0; + rs->angle[ i ] = 0; + } +} + +/* Pick and random square and direction and try to move it. */ +/* May not actually move anything, just attempt a random move. */ +/* Returns true if move was sucessful. */ +/* This could probably be implemented faster in a dequeue */ +/* to avoid trying to move a square which is already moving */ +/* but speed is most likely bottlenecked by rendering anyway... */ +static int +randsheet_new_move( randsheet* rs ) +{ + int i, j; + int num, dir; + /* pick a random square */ + num = random( ) % numsquares; + i = rs->xpos[ num ]; + j = rs->ypos[ num ]; + /* pick a random direction */ + dir = ( random( )% 4 ) + 1; + + if( rs->direction[ num ] == 0 ) + { + switch( dir ) + { + case 1: + /* move up in x */ + if( ( i + 1 ) < board_x_size ) + { + if( rs->occupied[ (i + 1) * board_y_size + j ] == -1 ) + { + rs->direction[ num ] = dir; + rs->occupied[ (i + 1) * board_y_size + j ] = num; + rs->occupied[ i * board_y_size + j ] = -1; + return 1; + } + } + return 0; + break; + case 2: + /* move up in y */ + if( ( j + 1 ) < board_y_size ) + { + if( rs->occupied[ i * board_y_size + (j + 1) ] == -1 ) + { + rs->direction[ num ] = dir; + rs->occupied[ i * board_y_size + (j + 1) ] = num; + rs->occupied[ i * board_y_size + j ] = -1; + return 1; + } + } + return 0; + break; + case 3: + /* move down in x */ + if( ( i - 1 ) >= 0 ) + { + if( rs->occupied[ (i - 1) * board_y_size + j ] == -1 ) + { + rs->direction[ num ] = dir; + rs->occupied[ (i - 1) * board_y_size + j ] = num; + rs->occupied[ i * board_y_size + j ] = -1; + return 1; + } + } + return 0; + break; + case 4: + /* move down in y */ + if( ( j - 1 ) >= 0 ) + { + if( rs->occupied[ i * board_y_size + (j - 1) ] == -1 ) + { + rs->direction[ num ] = dir; + rs->occupied[ i * board_y_size + (j - 1) ] = num; + rs->occupied[ i * board_y_size + j ] = -1; + return 1; + } + } + return 0; + break; + default: + break; + } + } + return 0; +} + +/* move a single frame. */ +/* Pass in the angle in rads the square rotates in a frame. */ +static void +randsheet_move( randsheet *rs, float rot ) +{ + int index; + float tmp; + for( index = 0 ; index < numsquares; index++ ) + { + switch( rs->direction[ index ] ) + { + case 0: + /* not moving */ + break; + case 1: + /* move up in x */ + if( textured && rs->angle[ index ] == 0 ) + { + tmp = rs->tex[ index * 4 + 0 ]; + rs->tex[ index * 4 + 0 ] = rs->tex[ index * 4 + 2 ]; + rs->tex[ index * 4 + 2 ] = tmp; + } + rs->angle[ index ] += rot; + /* check to see if we have finished moving */ + if( rs->angle[ index ] >= M_PI ) + { + rs->xpos[ index ] += 1; + rs->direction[ index ] = 0; + rs->angle[ index ] = 0; + } + break; + case 2: + /* move up in y */ + if( textured && rs->angle[ index ] == 0 ) + { + tmp = rs->tex[ index * 4 + 1 ]; + rs->tex[ index * 4 + 1 ] = rs->tex[ index * 4 + 3 ]; + rs->tex[ index * 4 + 3 ] = tmp; + } + rs->angle[ index ] += rot; + /* check to see if we have finished moving */ + if( rs->angle[ index ] >= M_PI ) + { + rs->ypos[ index ] += 1; + rs->direction[ index ] = 0; + rs->angle[ index ] = 0; + } + break; + case 3: + /* down in x */ + rs->angle[ index ] += rot; + /* check to see if we have finished moving */ + if( rs->angle[ index ] >= M_PI ) + { + rs->xpos[ index ] -= 1; + rs->direction[ index ] = 0; + rs->angle[ index ] = 0; + if( textured ) + { + tmp = rs->tex[ index * 4 + 0 ]; + rs->tex[ index * 4 + 0 ] = rs->tex[ index * 4 + 2 ]; + rs->tex[ index * 4 + 2 ] = tmp; + } + } + break; + case 4: + /* down in y */ + rs->angle[ index ] += rot; + /* check to see if we have finished moving */ + if( rs->angle[ index ] >= M_PI ) + { + rs->ypos[ index ] -= 1; + rs->direction[ index ] = 0; + rs->angle[ index ] = 0; + if( textured ) + { + tmp = rs->tex[ index * 4 + 1 ]; + rs->tex[ index * 4 + 1 ] = rs->tex[ index * 4 + 3 ]; + rs->tex[ index * 4 + 3 ] = tmp; + } + } + break; + default: + break; + } + } +} + + +/* draw all the moving squares */ +static int +randsheet_draw( randsheet *rs ) +{ + int i, j, polys = 0; + int index; + + /* for all moving squares ... */ + for( index = 0; index < numsquares; index++ ) + { + /* set color */ + glColor3f( rs->color[ index*3 + 0 ], + rs->color[ index*3 + 1 ], + rs->color[ index*3 + 2 ] ); + /* find x and y position */ + i = rs->xpos[ index ]; + j = rs->ypos[ index ]; + glPushMatrix(); + switch( rs->direction[ index ] ) + { + case 0: + + /* not moving */ + /* front */ + glTranslatef( i, 0, j ); + break; + case 1: + glTranslatef( i+1, 0, j ); + glRotatef( 180 - rs->angle[ index ]*180/M_PI, 0, 0, 1 ); + + break; + case 2: + glTranslatef( i, 0, j+1 ); + glRotatef( 180 - rs->angle[ index ]*180/M_PI, -1, 0, 0 ); + + break; + case 3: + glTranslatef( i, 0, j ); + glRotatef( rs->angle[ index ]*180/M_PI, 0, 0, 1 ); + break; + case 4: + glTranslatef( i, 0, j ); + glRotatef( rs->angle[ index ]*180/M_PI, -1, 0, 0 ); + break; + default: + break; + } + polys += draw_sheet( rs->tex + index*4 ); + glPopMatrix(); + + } + return polys; +} + +/**** END RANDSHEET_BAK FUNCTIONS ***/ + +XSCREENSAVER_MODULE ("FlipFlop", flipflop) + +#endif /* USE_GL */ diff --git a/hacks/glx/flipflop.man b/hacks/glx/flipflop.man new file mode 100644 index 00000000..17691bce --- /dev/null +++ b/hacks/glx/flipflop.man @@ -0,0 +1,95 @@ +.TH XScreenSaver 1 "" "X Version 11" +.SH NAME +flipflop - draws a grid of 3D squares that change positions +.SH SYNOPSIS +.B flipflop +[\-display \fIhost:display.screen\fP] +[\-visual \fIvisual\fP] +[\-window] +[\-count \fInumber\fP | \-free \fInumber\fP] +[\-size \fInumber\fP] +[\-size-x \fInumber\fP] +[\-size-y \fInumber\fP] +[\-spin \fInumber\fP] +[\-mode sticks | tiles] +[\-delay \fInumber\fP] +[\-wireframe] +[\-fps] +[\-texture] +.SH DESCRIPTION +Flipflop draws a grid of 3D colored tiles that change positions with +each other. +.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 \-count \fInumber\fP +Number of tiles on the board. A value of "0" means "default". The +default number of tiles depends on the size of the board and the mode: +95% of total tiles for "tiles" mode and 80% of total sticks for +"sticks" mode (e.g. 76 tiles or 64 sticks for a 9x9 board). +.TP 8 +.B \-free \fInumber\fP +Number of tiles missing from the board. See -count. +.TP 8 +.B \-size \fInumber\fP +Number of tiles on each side of the board. Takes precedence over +-size-x and -size-y. Default: 9. +.TP 8 +.B \-size-x \fInumber\fP +Width (in tiles) of the board. Default: 9. +.TP 8 +.B \-size-y \fInumber\fP +Length (in tiles) of the board. Default: 9. +.TP 8 +.B \-spin \fInumber\fP +Angular velocity for the rotation of the board. +.TP 8 +.B \-mode sticks +Draw hopping sticks instead of flipping tiles. +.TP 8 +.B \-mode tiles +Draw flipping tiles. This is the default. +.TP 8 +.B \-delay \fInumber\fP +Per-frame delay, in microseconds. Default: 20000 (0.02 seconds.). +.TP 8 +.B \-fps | \-no\-fps +Display the current frame rate, CPU load, and polygon count. +.TP 8 +.B \-wireframe +Only draw outlines. +.TP 8 +.B \-texture | \-no\-texture +Whether to texture the tiles with a screen grab or an image. +.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 2003 by Kevin Ogden. 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 +Kevin Ogden . Some additional code by Sergio +Gutierrez . diff --git a/hacks/glx/flipscreen3d.c b/hacks/glx/flipscreen3d.c new file mode 100644 index 00000000..7217de96 --- /dev/null +++ b/hacks/glx/flipscreen3d.c @@ -0,0 +1,545 @@ +/* + * flipscreen3d - takes snapshots of the screen and flips it around + * + * version 1.0 - Oct 24, 2001 + * + * Copyright (C) 2001 Ben Buxton (bb@cactii.net) + * + * 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. + */ + +#ifdef STANDALONE +#define DEFAULTS "*delay: 20000 \n" \ + "*showFPS: False \n" \ + "*wireframe: False \n" \ + "*useSHM: True \n" + +# define refresh_screenflip 0 +# include "xlockmore.h" /* from the xscreensaver distribution */ +# include "gltrackball.h" +#else /* !STANDALONE */ +# include "xlock.h" /* from the xlockmore distribution */ +#endif /* !STANDALONE */ + +/* lifted from lament.c */ +#define RAND(n) ((long) ((random() & 0x7fffffff) % ((long) (n)))) +#define RANDSIGN() ((random() & 1) ? 1 : -1) + + +#ifdef USE_GL + +/* Should be in */ +# ifndef GL_TEXTURE_MAX_ANISOTROPY_EXT +# define GL_TEXTURE_MAX_ANISOTROPY_EXT 0x84FE +# endif +# ifndef GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT +# define GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT 0x84FF +# endif + +#define DEF_ROTATE "True" +static int rotate; + +#define QW 12 +#define QH 12 + +#undef countof +#define countof(x) (sizeof((x))/sizeof((*x))) + + +static XrmOptionDescRec opts[] = { + {"+rotate", ".screenflip.rotate", XrmoptionNoArg, "false" }, + {"-rotate", ".screenflip.rotate", XrmoptionNoArg, "true" }, +}; + + +static argtype vars[] = { + {&rotate, "rotate", "Rotate", DEF_ROTATE, t_Bool}, +}; + + + +ENTRYPOINT ModeSpecOpt screenflip_opts = {countof(opts), opts, countof(vars), vars, NULL}; + + +#ifdef USE_MODULES +ModStruct screenflip_description = +{"screenflip", "init_screenflip", "draw_screenflip", "release_screenflip", + "draw_screenflip", "init_screenflip", NULL, &screenflip_opts, + 1000, 1, 2, 1, 4, 1.0, "", + "Screenflips", 0, NULL}; + +#endif + + +typedef struct { + GLXContext *glx_context; + Window window; + + int winw, winh; + int tw, th; /* texture width, height */ + GLfloat min_tx, min_ty; + GLfloat max_tx, max_ty; + GLfloat qx, qy, qw, qh; /* the quad we'll draw */ + + int regrab; + int fadetime; /* fade before regrab */ + + trackball_state *trackball; + Bool button_down_p; + + GLfloat show_colors[4]; + GLfloat stretch_val_x, stretch_val_y; + GLfloat stretch_val_dx, stretch_val_dy; + + GLfloat curx, cury, curz; + + GLfloat rx, ry, rz; + GLfloat rot, drot, odrot, ddrot, orot; + float theta, rho, dtheta, drho, gamma, dgamma; + + GLuint texid; + Bool mipmap_p; + Bool waiting_for_image_p; + Bool first_image_p; + + GLfloat anisotropic; + +} Screenflip; + +static Screenflip *screenflip = NULL; + +#include "grab-ximage.h" + +static const GLfloat viewer[] = {0.0, 0.0, 15.0}; + + +ENTRYPOINT Bool +screenflip_handle_event (ModeInfo *mi, XEvent *event) +{ + Screenflip *c = &screenflip[MI_SCREEN(mi)]; + + if (event->xany.type == ButtonPress && + event->xbutton.button == Button1) + { + c->button_down_p = True; + gltrackball_start (c->trackball, + event->xbutton.x, event->xbutton.y, + MI_WIDTH (mi), MI_HEIGHT (mi)); + return True; + } + else if (event->xany.type == ButtonRelease && + event->xbutton.button == Button1) + { + c->button_down_p = False; + return True; + } + else if (event->xany.type == ButtonPress && + (event->xbutton.button == Button4 || + event->xbutton.button == Button5 || + event->xbutton.button == Button6 || + event->xbutton.button == Button7)) + { + gltrackball_mousewheel (c->trackball, event->xbutton.button, 10, + !!event->xbutton.state); + return True; + } + else if (event->xany.type == MotionNotify && + c->button_down_p) + { + gltrackball_track (c->trackball, + event->xmotion.x, event->xmotion.y, + MI_WIDTH (mi), MI_HEIGHT (mi)); + return True; + } + + return False; +} + + +/* draw the texture mapped quad (actually two back to back)*/ +static void showscreen(Screenflip *c, int frozen, int wire) +{ + GLfloat x, y, w, h; + + if (c->fadetime) { +/* r -= 0.02; g -= 0.02; b -= 0.02; */ + c->show_colors[3] -= 0.02; + if (c->show_colors[3] < 0) { + c->regrab = 1; + c->fadetime = 0; + } + } else if (c->show_colors[3] < 0) { + c->show_colors[0] = c->show_colors[1] = + c->show_colors[2] = c->show_colors[3] = 1; + c->stretch_val_x = c->stretch_val_y = + c->stretch_val_dx = c->stretch_val_dy = 0; + } + if (c->stretch_val_dx == 0 && !frozen && !(random() % 25)) + c->stretch_val_dx = (float)(random() % 100) / 5000; + if (c->stretch_val_dy == 0 && !frozen && !(random() % 25)) + c->stretch_val_dy = (float)(random() % 100) / 5000; + + x = c->qx; + y = c->qy; + w = c->qx+c->qw; + h = c->qy-c->qh; + + if (!frozen) { + w *= sin (c->stretch_val_x) + 1; + x *= sin (c->stretch_val_x) + 1; + if (!c->button_down_p) { + if (!c->fadetime) c->stretch_val_x += c->stretch_val_dx; + if (c->stretch_val_x > 2*M_PI && !(random() % 5)) + c->stretch_val_dx = (float)(random() % 100) / 5000; + else + c->stretch_val_x -= 2*M_PI; + } + + if (!c->button_down_p && !c->fadetime) c->stretch_val_y += c->stretch_val_dy; + h *= sin (c->stretch_val_y) / 2 + 1; + y *= sin (c->stretch_val_y) / 2 + 1; + if (!c->button_down_p) { + if (c->stretch_val_y > 2*M_PI && !(random() % 5)) + c->stretch_val_dy = (float)(random() % 100) / 5000; + else + c->stretch_val_y -= 2*M_PI; + } + } + + glColor4f(c->show_colors[0], c->show_colors[1], + c->show_colors[2], c->show_colors[3]); + + if (!wire) + { + glEnable(GL_TEXTURE_2D); + glEnable(GL_BLEND); + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + glDepthMask(GL_FALSE); + } + + glBegin(wire ? GL_LINE_LOOP : GL_QUADS); + + glNormal3f(0, 0, 1); + glTexCoord2f(c->max_tx, c->max_ty); glVertex3f(w, h, 0); + glTexCoord2f(c->max_tx, c->min_ty); glVertex3f(w, y, 0); + glTexCoord2f(c->min_tx, c->min_ty); glVertex3f(x, y, 0); + glTexCoord2f(c->min_tx, c->max_ty); glVertex3f(x, h, 0); + + glNormal3f(0, 0, -1); + glTexCoord2f(c->min_tx, c->min_ty); glVertex3f(x, y, -0.05); + glTexCoord2f(c->max_tx, c->min_ty); glVertex3f(w, y, -0.05); + glTexCoord2f(c->max_tx, c->max_ty); glVertex3f(w, h, -0.05); + glTexCoord2f(c->min_tx, c->max_ty); glVertex3f(x, h, -0.05); + glEnd(); + + + glDisable(GL_TEXTURE_2D); + glDepthMask(GL_TRUE); + + glBegin(GL_LINE_LOOP); + glVertex3f(x, y, 0); + glVertex3f(x, h, 0); + glVertex3f(w, h, 0); + glVertex3f(w, y, 0); + glEnd(); + glDisable(GL_BLEND); + +} + +/* This function is responsible for 'zooming back' the square after + * a new chunk has been grabbed with getSnapshot(), and positioning + * it suitably on the screen. Once positioned (where we begin to rotate), + * it just does a glTranslatef() and returns 1 + */ + +static int inposition(Screenflip *c) +{ + GLfloat wx; + GLfloat wy; + wx = 0 - (c->qw/2); + wy = (c->qh/2); + + if (c->curx == 0) c->curx = c->qx; + if (c->cury == 0) c->cury = c->qy; + if (c->regrab) { + c->curz = 0; + c->curx = c->qx; + c->cury = c->qy; + c->regrab = 0; + } + if (c->curz > -10 || c->curx > wx + 0.1 || c->curx < wx - 0.1 || + c->cury > wy + 0.1 || c->cury < wy - 0.1) { + if (c->curz > -10) + c->curz -= 0.05; + if (c->curx > wx) { + c->qx -= 0.02; + c->curx -= 0.02; + } + if (c->curx < wx) { + c->qx += 0.02; + c->curx += 0.02; + } + if (c->cury > wy) { + c->qy -= 0.02; + c->cury -= 0.02; + } + if (c->cury < wy) { + c->qy += 0.02; + c->cury += 0.02; + } + glTranslatef(0, 0, c->curz); + return 0; + } + glTranslatef(0, 0, c->curz); + return 1; + +} + +#if 0 +static void drawgrid(void) +{ + int i; + + glColor3f(0, 0.7, 0); + glBegin(GL_LINES); + for (i = 0 ; i <= 50; i+=2) { + glVertex3f( -25, -15, i-70); + glVertex3f( 25, -15, i-70); + glVertex3f( i-25, -15, -70); + glVertex3f( i-25, -15, -20); + } + glEnd(); +} +#endif + + +static void display(Screenflip *c, int wire) +{ + int frozen; + GLfloat rot = current_device_rotation(); + + glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT); + glLoadIdentity(); + gluLookAt(viewer[0], viewer[1], viewer[2], 0.0, 0.0, 0.0, 0.0, 1.0, 0.0); + glPushMatrix(); + + glRotatef(rot, 0, 0, 1); + if ((rot > 45 && rot < 135) || + (rot < -45 && rot > -135)) + { + GLfloat s = c->winw / (GLfloat) c->winh; + glScalef (s, 1/s, 1); + } + + if (inposition(c)) { + frozen = 0; + glTranslatef(5 * sin(c->theta), 5 * sin(c->rho), 10 * cos(c->gamma) - 10); +/* randomly change the speed */ + if (!c->button_down_p && !(random() % 300)) { + if (random() % 2) + c->drho = 1/60 - (float)(random() % 100)/3000; + if (random() % 2) + c->dtheta = 1/60 - (float)(random() % 100)/3000; + if (random() % 2) + c->dgamma = 1/60 - (float)(random() % 100)/3000; + } + glRotatef(-rot, 0, 0, 1); + gltrackball_rotate (c->trackball); + glRotatef(rot, 0, 0, 1); + if (rotate) glRotatef(c->rot, c->rx, c->ry, c->rz); +/* update variables with each frame */ + if(!c->button_down_p && !c->fadetime) { + c->theta += c->dtheta; + c->rho += c->drho; + c->gamma += c->dgamma; + c->rot += c->drot; + c->drot += c->ddrot; + } +/* dont let our rotation speed get too high */ + if (c->drot > 5 && c->ddrot > 0) + c->ddrot = 0 - (GLfloat)(random() % 100) / 1000; + else if (c->drot < -5 && c->ddrot < 0) + c->ddrot = (GLfloat)(random() % 100) / 1000; + } else { /* reset some paramaters */ + c->ddrot = 0.05 - (GLfloat)(random() % 100) / 1000; + c->theta = c->rho = c->gamma = 0; + c->rot = 0; + frozen = 1; + } + if (!c->button_down_p && !c->fadetime && (c->rot >= 360 || c->rot <= -360) && !(random() % 7)) { /* rotate change */ + c->rx = (GLfloat)(random() % 100) / 100; + c->ry = (GLfloat)(random() % 100) / 100; + c->rz = (GLfloat)(random() % 100) / 100; + } + if (c->odrot * c->drot < 0 && c->tw < c->winw && !(random() % 10)) { + c->fadetime = 1; /* randomly fade and get new snapshot */ + } + c->orot = c->rot; + c->odrot = c->drot; + if (c->rot > 360 || c->rot < -360) /* dont overflow rotation! */ + c->rot -= c->rot; + showscreen(c, frozen, wire); + glPopMatrix(); + glFlush(); +} + +ENTRYPOINT void reshape_screenflip(ModeInfo *mi, int width, int height) +{ + Screenflip *c = &screenflip[MI_SCREEN(mi)]; + glViewport(0,0,(GLint)width, (GLint) height); + glMatrixMode(GL_PROJECTION); + glLoadIdentity(); + gluPerspective(45, 1, 2.0, 85); + glMatrixMode(GL_MODELVIEW); + c->winw = width; + c->winh = height; +} + +static void +image_loaded_cb (const char *filename, XRectangle *geometry, + int image_width, int image_height, + int texture_width, int texture_height, + void *closure) +{ + Screenflip *c = (Screenflip *) closure; + + c->tw = texture_width; + c->th = texture_height; + c->min_tx = (GLfloat) geometry->x / c->tw; + c->min_ty = (GLfloat) geometry->y / c->th; + c->max_tx = (GLfloat) (geometry->x + geometry->width) / c->tw; + c->max_ty = (GLfloat) (geometry->y + geometry->height) / c->th; + + c->qx = -QW/2 + ((GLfloat) geometry->x * QW / image_width); + c->qy = QH/2 - ((GLfloat) geometry->y * QH / image_height); + c->qw = QW * ((GLfloat) geometry->width / image_width); + c->qh = QH * ((GLfloat) geometry->height / image_height); + + glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, + (c->mipmap_p ? GL_LINEAR_MIPMAP_LINEAR : GL_LINEAR)); + + if (c->anisotropic >= 1.0) + glTexParameterf (GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, + c->anisotropic); + + c->waiting_for_image_p = False; + c->first_image_p = False; +} + + +static void getSnapshot (ModeInfo *modeinfo) +{ + Screenflip *c = &screenflip[MI_SCREEN(modeinfo)]; + + if (MI_IS_WIREFRAME(modeinfo)) + return; + + c->waiting_for_image_p = True; + c->mipmap_p = True; + load_texture_async (modeinfo->xgwa.screen, modeinfo->window, + *c->glx_context, 0, 0, c->mipmap_p, c->texid, + image_loaded_cb, c); +} + +ENTRYPOINT void init_screenflip(ModeInfo *mi) +{ + int screen = MI_SCREEN(mi); + Screenflip *c; + + if (screenflip == NULL) { + if ((screenflip = (Screenflip *) calloc(MI_NUM_SCREENS(mi), + sizeof(Screenflip))) == NULL) + return; + } + c = &screenflip[screen]; + c->window = MI_WINDOW(mi); + + c->trackball = gltrackball_init (); + + if ((c->glx_context = init_GL(mi)) != NULL) { + reshape_screenflip(mi, MI_WIDTH(mi), MI_HEIGHT(mi)); + } else { + MI_CLEARWINDOW(mi); + } + c->winh = MI_WIN_HEIGHT(mi); + c->winw = MI_WIN_WIDTH(mi); + c->qw = QW; + c->qh = QH; + c->qx = -6; + c->qy = 6; + + c->rx = c->ry = 1; + c->odrot = 1; + + c->show_colors[0] = c->show_colors[1] = + c->show_colors[2] = c->show_colors[3] = 1; + + if (! MI_IS_WIREFRAME(mi)) + { + glShadeModel(GL_SMOOTH); + glPolygonMode(GL_FRONT_AND_BACK,GL_FILL); + glEnable(GL_DEPTH_TEST); + glEnable(GL_CULL_FACE); + glCullFace(GL_BACK); + glDisable(GL_LIGHTING); + } + + if (strstr ((char *) glGetString(GL_EXTENSIONS), + "GL_EXT_texture_filter_anisotropic")) + glGetFloatv (GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, &c->anisotropic); + else + c->anisotropic = 0.0; + + glGenTextures(1, &c->texid); + + c->first_image_p = True; + getSnapshot(mi); +} + +ENTRYPOINT void draw_screenflip(ModeInfo *mi) +{ + Screenflip *c = &screenflip[MI_SCREEN(mi)]; + Window w = MI_WINDOW(mi); + Display *disp = MI_DISPLAY(mi); + + if (!c->glx_context) + return; + + /* Wait for the first image; for subsequent images, load them in the + background while animating. */ + if (c->waiting_for_image_p && c->first_image_p) + return; + + glXMakeCurrent(disp, w, *(c->glx_context)); + + glBindTexture(GL_TEXTURE_2D, c->texid); + + if (c->regrab) + getSnapshot(mi); + + display(c, MI_IS_WIREFRAME(mi)); + + if(mi->fps_p) do_fps(mi); + glFinish(); + glXSwapBuffers(disp, w); +} + +ENTRYPOINT void release_screenflip(ModeInfo *mi) +{ + if (screenflip != NULL) { + (void) free((void *) screenflip); + screenflip = NULL; + } + FreeAllGL(mi); +} + +XSCREENSAVER_MODULE_2 ("FlipScreen3D", flipscreen3d, screenflip) + +#endif diff --git a/hacks/glx/flipscreen3d.man b/hacks/glx/flipscreen3d.man new file mode 100644 index 00000000..fecd005b --- /dev/null +++ b/hacks/glx/flipscreen3d.man @@ -0,0 +1,61 @@ +.TH XScreenSaver 1 "" "X Version 11" +.SH NAME +flipscreen3d - rotates an image of the screen through 3 dimensions. +.SH SYNOPSIS +.B flipscreen3d +[\-display \fIhost:display.screen\fP] +[\-visual \fIvisual\fP] +[\-window] +[\-root] +[\-delay \fInumber\fP] +[\-no-rotate] +[\-wireframe] +[\-fps] +.SH DESCRIPTION +Grabs an image of the desktop, turns it into a GL texture map, and spins it +around and deforms it in various ways. +.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: 20000 (0.02 seconds.). +.TP 8 +.B \-rotate | \-no-rotate +Whether to rotate. +.TP 8 +.B \-wireframe +Just render boxes instead of textures (for debugging). +.TP 8 +.B \-fps +Display the current frame rate, CPU load, and polygon count. +.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 2002 by Ben Buxton. 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 +Ben Buxton. diff --git a/hacks/glx/fliptext.c b/hacks/glx/fliptext.c new file mode 100644 index 00000000..536a2240 --- /dev/null +++ b/hacks/glx/fliptext.c @@ -0,0 +1,1008 @@ +/* + * fliptext, Copyright (c) 2005-2011 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. + */ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif /* HAVE_CONFIG_H */ + +/* Utopia 800 needs 64 512x512 textures (4096x4096 bitmap). + Utopia 720 needs 16 512x512 textures (2048x2048 bitmap). + Utopia 480 needs 16 512x512 textures (2048x2048 bitmap). + Utopia 400 needs 4 512x512 textures (1024x1024 bitmap). + Utopia 180 needs 1 512x512 texture. + Times 240 needs 1 512x512 texture. + */ +#define DEF_FONT "-*-utopia-bold-r-normal-*-*-720-*-*-*-*-iso8859-1" +#define DEF_COLOR "#00CCFF" + +#define DEFAULTS "*delay: 10000 \n" \ + "*showFPS: False \n" \ + "*wireframe: False \n" \ + "*usePty: False \n" \ + "*font: " DEF_FONT "\n" \ + ".foreground: " DEF_COLOR "\n" \ + +# define refresh_fliptext 0 +# define fliptext_handle_event 0 +#undef countof +#define countof(x) (sizeof((x))/sizeof((*x))) + +#undef BELLRAND +#define BELLRAND(n) ((frand((n)) + frand((n)) + frand((n))) / 3) + +#include "xlockmore.h" +#include "texfont.h" +#include "textclient.h" + +#ifdef USE_GL /* whole file */ + +/* Should be in */ +# ifndef GL_TEXTURE_MAX_ANISOTROPY_EXT +# define GL_TEXTURE_MAX_ANISOTROPY_EXT 0x84FE +# endif +# ifndef GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT +# define GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT 0x84FF +# endif + + +#define DEF_PROGRAM "xscreensaver-text --cols 0" /* don't wrap */ +#define DEF_LINES "8" +#define DEF_FONT_SIZE "20" +#define DEF_COLUMNS "80" +#define DEF_ALIGNMENT "random" +#define DEF_SPEED "1.0" +#define TAB_WIDTH 8 + +#define FONT_WEIGHT 14 +#define KEEP_ASPECT + +typedef enum { NEW, HESITATE, IN, LINGER, OUT, DEAD } line_state; +typedef enum { SCROLL_BOTTOM, SCROLL_TOP, SPIN } line_anim_type; + +typedef struct { GLfloat x, y, z; } XYZ; + +typedef struct { + char *text; + GLfloat width, height; /* size */ + XYZ from, to, current; /* start, end, and current position */ + GLfloat fth, tth, cth; /* rotation around Z */ + + int cluster_size; /* how many lines in this cluster */ + int cluster_pos; /* position of this line in the cluster */ + + line_state state; /* current motion model */ + int step, steps; /* progress along this path */ + GLfloat color[4]; + +} line; + + +typedef struct { + Display *dpy; + GLXContext *glx_context; + + texture_font_data *texfont; + text_data *tc; + + char *buf; + int buf_size; + int buf_tail; + + int char_width; /* in font units */ + int line_height; /* in font units */ + double font_scale; /* convert font units to display units */ + + int font_wrap_pixels; /* in font units (for wrapping text) */ + + int top_margin, bottom_margin; + int left_margin, right_margin; + + int nlines; + int lines_size; + line **lines; + + line_anim_type anim_type; + XYZ in, mid, out; + XYZ rotation; + GLfloat color[4]; + +} fliptext_configuration; + + +static fliptext_configuration *scs = NULL; + +static char *program; +static int max_lines, min_lines; +static float font_size; +static int target_columns; +static char *alignment_str; +static int alignment, alignment_random_p; +static GLfloat speed; + +static XrmOptionDescRec opts[] = { + {"-program", ".program", XrmoptionSepArg, 0 }, + {"-lines", ".lines", XrmoptionSepArg, 0 }, + {"-size", ".fontSize", XrmoptionSepArg, 0 }, + {"-columns", ".columns", XrmoptionSepArg, 0 }, + {"-speed", ".speed", XrmoptionSepArg, 0 }, +/*{"-font", ".font", XrmoptionSepArg, 0 },*/ + {"-alignment", ".alignment", XrmoptionSepArg, 0 }, + {"-left", ".alignment", XrmoptionNoArg, "Left" }, + {"-right", ".alignment", XrmoptionNoArg, "Right" }, + {"-center", ".alignment", XrmoptionNoArg, "Center" }, +}; + +static argtype vars[] = { + {&program, "program", "Program", DEF_PROGRAM, t_String}, + {&max_lines, "lines", "Integer", DEF_LINES, t_Int}, + {&font_size, "fontSize", "Float", DEF_FONT_SIZE, t_Float}, + {&target_columns, "columns", "Integer", DEF_COLUMNS, t_Int}, + {&alignment_str, "alignment", "Alignment", DEF_ALIGNMENT, t_String}, + {&speed, "speed", "Speed", DEF_SPEED, t_Float}, +}; + +ENTRYPOINT ModeSpecOpt fliptext_opts = {countof(opts), opts, countof(vars), vars, NULL}; + + + +/* Tabs are bad, mmmkay? */ + +static char * +untabify (const char *string) +{ + const char *ostring = string; + char *result = (char *) malloc ((strlen(string) * 8) + 1); + char *out = result; + int col = 0; + while (*string) + { + if (*string == '\t') + { + do { + col++; + *out++ = ' '; + } while (col % TAB_WIDTH); + string++; + } + else if (*string == '\r' || *string == '\n') + { + *out++ = *string++; + col = 0; + } + else if (*string == '\010') /* backspace */ + { + if (string > ostring) + out--, string++; + } + else + { + *out++ = *string++; + col++; + } + } + *out = 0; + + return result; +} + +static void +strip (char *s, Bool leading, Bool trailing) +{ + int L = strlen(s); + if (trailing) + while (L > 0 && (s[L-1] == ' ' || s[L-1] == '\t')) + s[L--] = 0; + if (leading) + { + char *s2 = s; + while (*s2 == ' ' || *s2 == '\t') + s2++; + if (s == s2) + return; + while (*s2) + *s++ = *s2++; + *s = 0; + } +} + + +static int +char_width (fliptext_configuration *sc, char c) +{ + char s[2]; + s[0] = c; + s[1] = 0; + return texture_string_width (sc->texfont, s, 0); +} + + +/* Returns a single line of text from the output buffer of the subprocess, + taking into account wrapping, centering, etc. Returns 0 if no complete + line is currently available. + */ +static char * +get_one_line (fliptext_configuration *sc) +{ + char *result = 0; + int wrap_pix = sc->font_wrap_pixels; + int col = 0; + int col_pix = 0; + char *s = sc->buf; + int target = sc->buf_size - sc->buf_tail - 2; + + /* Fill as much as we can into sc->buf, but stop at newline. + */ + while (target > 0) + { + char c = textclient_getc (sc->tc); + if (c <= 0) + break; + sc->buf[sc->buf_tail++] = c; + sc->buf[sc->buf_tail] = 0; + target--; + if (c == '\r' || c == '\n') + break; + } + + while (!result) + { + int cw; + + if (s >= sc->buf + sc->buf_tail) + /* Reached end of buffer before end of line. Bail. */ + return 0; + + cw = char_width (sc, *s); + + if (*s == '\r' || *s == '\n' || + col_pix + cw >= wrap_pix) + { + int L = s - sc->buf; + + if (*s == '\r' || *s == '\n') + { + if (*s == '\r' && s[1] == '\n') /* swallow CRLF too */ + *s++ = 0; + + *s++ = 0; + } + else + { + /* We wrapped -- try to back up to the previous word boundary. */ + char *s2 = s; + int n = 0; + while (s2 > sc->buf && *s2 != ' ' && *s2 != '\t') + s2--, n++; + if (s2 > sc->buf) + { + s = s2; + *s++ = 0; + L = s - sc->buf; + } + } + + if (result) abort(); + result = (char *) malloc (L+1); + memcpy (result, sc->buf, L); + result[L] = 0; + + { + char *t = result; + char *ut = untabify (t); + strip (ut, (alignment == 0), 1); /* if centering, strip + leading whitespace too */ + result = ut; + free (t); + } + + if (sc->buf_tail > (s - sc->buf)) + { + int i = sc->buf_tail - (s - sc->buf); + memmove (sc->buf, s, i); + sc->buf_tail = i; + sc->buf[sc->buf_tail] = 0; + } + else + { + sc->buf_tail = 0; + } + + sc->buf[sc->buf_tail] = 0; + s = sc->buf; + col = 0; + col_pix = 0; + } + else + { + col++; + col_pix += cw; + if (*s == '\t') + { + int tab_pix = TAB_WIDTH * sc->char_width; + col = TAB_WIDTH * ((col / TAB_WIDTH) + 1); + col_pix = tab_pix * ((col / tab_pix) + 1); + } + s++; + } + } + + return result; +} + + +static Bool +blank_p (const char *s) +{ + for (; *s; s++) + if (*s != ' ' && *s != '\t' && *s != '\r' && *s != '\n') + return False; + return True; +} + +/* Reads some text from the subprocess, and creates and returns a `line' + object. Adds that object to the lines list. Returns 0 if no text + available yet. + + If skip_blanks_p, then keep trying for new lines of text until we + get one that is not empty. + */ +static line * +make_line (fliptext_configuration *sc, Bool skip_blanks_p) +{ + line *ln; + char *s; + + AGAIN: + s = get_one_line (sc); + if (s && skip_blanks_p && blank_p (s)) + { + free (s); + goto AGAIN; + } + + if (!s) return 0; + + ln = (line *) calloc (1, sizeof(*ln)); + ln->text = s; + ln->state = NEW; + ln->width = sc->font_scale * texture_string_width (sc->texfont, s, 0); + ln->height = sc->font_scale * sc->line_height; + + memcpy (ln->color, sc->color, sizeof(ln->color)); + + sc->nlines++; + if (sc->lines_size <= sc->nlines) + { + sc->lines_size = (sc->lines_size * 1.2) + sc->nlines; + sc->lines = (line **) + realloc (sc->lines, sc->lines_size * sizeof(*sc->lines)); + if (! sc->lines) + { + fprintf (stderr, "%s: out of memory (%d lines)\n", + progname, sc->lines_size); + exit (1); + } + } + + sc->lines[sc->nlines-1] = ln; + return ln; +} + + +/* frees the object and removes it from the list. + */ +static void +free_line (fliptext_configuration *sc, line *line) +{ + int i; + for (i = 0; i < sc->nlines; i++) + if (sc->lines[i] == line) + break; + if (i == sc->nlines) abort(); + for (; i < sc->nlines-1; i++) + sc->lines[i] = sc->lines[i+1]; + sc->lines[i] = 0; + sc->nlines--; + + free (line->text); + free (line); +} + + +static void +draw_line (ModeInfo *mi, line *line) +{ + int wire = MI_IS_WIREFRAME(mi); + fliptext_configuration *sc = &scs[MI_SCREEN(mi)]; + + if (! line->text || !*line->text || + line->state == NEW || line->state == HESITATE || line->state == DEAD) + return; + + glPushMatrix(); + glTranslatef (line->current.x, line->current.y, line->current.z); + + glRotatef (line->cth, 0, 1, 0); + + if (alignment == 1) + glTranslatef (-line->width, 0, 0); + else if (alignment == 0) + glTranslatef (-line->width/2, 0, 0); + + glScalef (sc->font_scale, sc->font_scale, sc->font_scale); + + glColor4f (line->color[0], line->color[1], line->color[2], line->color[3]); + + if (!wire) + print_texture_string (sc->texfont, line->text); + else + { + int w, h; + char *s = line->text; + char c[2]; + c[1]=0; + glDisable (GL_TEXTURE_2D); + glColor3f (0.4, 0.4, 0.4); + while (*s) + { + *c = *s++; + w = texture_string_width (sc->texfont, c, &h); + glBegin (GL_LINE_LOOP); + glVertex3f (0, 0, 0); + glVertex3f (w, 0, 0); + glVertex3f (w, h, 0); + glVertex3f (0, h, 0); + glEnd(); + glTranslatef (w, 0, 0); + } + } + +#if 0 + glDisable (GL_TEXTURE_2D); + glColor3f (0.4, 0.4, 0.4); + glBegin (GL_LINE_LOOP); + glVertex3f (0, 0, 0); + glVertex3f (line->width/sc->font_scale, 0, 0); + glVertex3f (line->width/sc->font_scale, line->height/sc->font_scale, 0); + glVertex3f (0, line->height/sc->font_scale, 0); + glEnd(); + if (!wire) glEnable (GL_TEXTURE_2D); +#endif + + glPopMatrix(); + + mi->polygon_count += strlen (line->text); +} + +static void +tick_line (fliptext_configuration *sc, line *line) +{ + int stagger = 30; /* frames of delay between line spin-outs */ + int slide = 600; /* frames in a slide in/out */ + int linger = 0; /* frames to pause with no motion */ + double i, ii; + + if (line->state >= DEAD) abort(); + if (++line->step >= line->steps) + { + line->state++; + line->step = 0; + + if (linger == 0 && line->state == LINGER) + line->state++; + + if (sc->anim_type != SPIN) + stagger *= 2; + + switch (line->state) + { + case HESITATE: /* entering state HESITATE */ + switch (sc->anim_type) + { + case SPIN: + line->steps = (line->cluster_pos * stagger); + break; + case SCROLL_TOP: + line->steps = stagger * (line->cluster_size - line->cluster_pos); + break; + case SCROLL_BOTTOM: + line->steps = stagger * line->cluster_pos; + break; + default: + abort(); + } + break; + + case IN: + line->color[3] = 0; + switch (sc->anim_type) + { + case SCROLL_BOTTOM: /* entering state BOTTOM IN */ + line->from = sc->in; + line->to = sc->mid; + line->from.y = (sc->bottom_margin - + (line->height * + (line->cluster_pos + 1))); + line->to.y += (line->height * + ((line->cluster_size/2.0) - line->cluster_pos)); + line->steps = slide; + break; + + case SCROLL_TOP: /* entering state TOP IN */ + line->from = sc->in; + line->to = sc->mid; + line->from.y = (sc->top_margin + + (line->height * + (line->cluster_size - line->cluster_pos))); + line->to.y += (line->height * + ((line->cluster_size/2.0) - line->cluster_pos)); + line->steps = slide; + break; + + case SPIN: /* entering state SPIN IN */ + line->from = sc->in; + line->to = sc->mid; + line->to.y += (line->height * + ((line->cluster_size/2.0) - line->cluster_pos)); + line->from.y += (line->height * + ((line->cluster_size/2.0) - line->cluster_pos)); + + line->fth = 270; + line->tth = 0; + line->steps = slide; + break; + + default: + abort(); + } + break; + + case OUT: + switch (sc->anim_type) + { + case SCROLL_BOTTOM: /* entering state BOTTOM OUT */ + line->from = line->to; + line->to = sc->out; + line->to.y = (sc->top_margin + + (line->height * + (line->cluster_size - line->cluster_pos))); + line->steps = slide; + break; + + case SCROLL_TOP: /* entering state TOP OUT */ + line->from = line->to; + line->to = sc->out; + line->to.y = (sc->bottom_margin - + (line->height * + (line->cluster_pos + 1))); + line->steps = slide; + break; + + case SPIN: /* entering state SPIN OUT */ + line->from = line->to; + line->to = sc->out; + line->to.y += (line->height * + ((line->cluster_size/2.0) - line->cluster_pos)); + + line->fth = line->tth; + line->tth = -270; + line->steps = slide; + break; + + default: + abort(); + } + break; + + case LINGER: + line->from = line->to; + line->steps = linger; + break; + + default: + break; + } + + line->steps /= speed; + } + + switch (line->state) + { + case IN: + case OUT: + i = (double) line->step / line->steps; + + /* Move along the path exponentially, slow side towards the middle. */ + if (line->state == OUT) + ii = i * i; + else + ii = 1 - ((1-i) * (1-i)); + + line->current.x = line->from.x + (ii * (line->to.x - line->from.x)); + line->current.y = line->from.y + (ii * (line->to.y - line->from.y)); + line->current.z = line->from.z + (ii * (line->to.z - line->from.z)); + line->cth = line->fth + (ii * (line->tth - line->fth)); + + if (line->state == OUT) ii = 1-ii; + line->color[3] = sc->color[3] * ii; + break; + + case HESITATE: + case LINGER: + case DEAD: + break; + default: + abort(); + } +} + + +/* Start a new cluster of lines going. + Pick their anim type, and in, mid, and out positions. + */ +static void +reset_lines (ModeInfo *mi) +{ + fliptext_configuration *sc = &scs[MI_SCREEN(mi)]; + int i; + line *prev = 0; + GLfloat minx, maxx, miny, maxy, minz, maxz, maxw, maxh; + + sc->rotation.x = 5 - BELLRAND(10); + sc->rotation.y = 5 - BELLRAND(10); + sc->rotation.z = 5 - BELLRAND(10); + + switch (random() % 8) + { + case 0: sc->anim_type = SCROLL_TOP; break; + case 1: sc->anim_type = SCROLL_BOTTOM; break; + default: sc->anim_type = SPIN; break; + } + + minx = sc->left_margin * 0.9; + maxx = sc->right_margin * 0.9; + + miny = sc->bottom_margin * 0.9; + maxy = sc->top_margin * 0.9; + + minz = sc->left_margin * 5; + maxz = sc->right_margin * 2; + + maxw = sc->font_wrap_pixels * sc->font_scale; + maxh = max_lines * sc->line_height * sc->font_scale; + + if (maxw > maxx - minx) + maxw = maxx - minx; + if (maxh > maxy - miny) + maxh = maxy - miny; + + if (alignment_random_p) + alignment = (random() % 3) - 1; + + if (alignment == -1) maxx -= maxw; + else if (alignment == 1) minx += maxw; + else minx += maxw/2, maxx -= maxw/2; + + miny += maxh/2; + maxy -= maxh/2; + + sc->mid.x = minx + frand (maxx - minx); + if (sc->anim_type == SPIN) + sc->mid.y = miny + BELLRAND (maxy - miny); + else + sc->mid.y = miny + frand (maxy - miny); + + sc->in.x = BELLRAND(sc->right_margin * 2) - sc->right_margin; + sc->out.x = BELLRAND(sc->right_margin * 2) - sc->right_margin; + + sc->in.y = miny + frand(maxy - miny); + sc->out.y = miny + frand(maxy - miny); + + sc->in.z = minz + frand(maxz - minz); + sc->out.z = minz + frand(maxz - minz); + + sc->mid.z = 0; + + if (sc->anim_type == SPIN && sc->in.z > 0) sc->in.z /= 4; + if (sc->anim_type == SPIN && sc->out.z > 0) sc->out.z /= 4; + + for (i = 0; i < max_lines; i++) + { + line *line = make_line (sc, (i == 0)); + if (!line) break; /* no text available */ + if (i >= min_lines && + (!line->text || !*line->text)) /* blank after min */ + break; + } + + for (i = 0; i < sc->nlines; i++) + { + line *line = sc->lines[i]; + if (!prev) + { + line->from.y = sc->bottom_margin; + line->to.y = 0; + } + else + { + line->from.y = prev->from.y - prev->height; + line->to.y = prev->to.y - prev->height; + } + line->cluster_pos = i; + line->cluster_size = sc->nlines; + prev = line; + } +} + + +static void +parse_color (ModeInfo *mi, const char *name, const char *s, GLfloat *a) +{ + XColor c; + if (! XParseColor (MI_DISPLAY(mi), MI_COLORMAP(mi), s, &c)) + { + fprintf (stderr, "%s: can't parse %s color %s", progname, name, s); + exit (1); + } + a[0] = c.red / 65536.0; + a[1] = c.green / 65536.0; + a[2] = c.blue / 65536.0; + a[3] = 1.0; +} + + +/* Window management, etc + */ +ENTRYPOINT void +reshape_fliptext (ModeInfo *mi, int width, int height) +{ + fliptext_configuration *sc = &scs[MI_SCREEN(mi)]; + GLfloat h = (GLfloat) height / (GLfloat) width; + + glViewport (0, 0, (GLint) width, (GLint) height); + + glMatrixMode(GL_PROJECTION); + glLoadIdentity(); + gluPerspective (60.0, 1/h, 0.01, 100.0); + + glMatrixMode(GL_MODELVIEW); + glLoadIdentity(); + gluLookAt( 0.0, 0.0, 2.6, + 0.0, 0.0, 0.0, + 0.0, 1.0, 0.0); + + glClear(GL_COLOR_BUFFER_BIT); + + sc->right_margin = sc->top_margin / h; + sc->left_margin = -sc->right_margin; +} + + +ENTRYPOINT void +init_fliptext (ModeInfo *mi) +{ + int wire = MI_IS_WIREFRAME(mi); + + fliptext_configuration *sc; + + if (!scs) { + scs = (fliptext_configuration *) + calloc (MI_NUM_SCREENS(mi), sizeof (fliptext_configuration)); + if (!scs) { + fprintf(stderr, "%s: out of memory\n", progname); + exit(1); + } + + sc = &scs[MI_SCREEN(mi)]; + sc->lines = (line **) calloc (max_lines+1, sizeof(char *)); + } + + sc = &scs[MI_SCREEN(mi)]; + sc->dpy = MI_DISPLAY(mi); + + if ((sc->glx_context = init_GL(mi)) != NULL) { + reshape_fliptext (mi, MI_WIDTH(mi), MI_HEIGHT(mi)); + clear_gl_error(); /* WTF? sometimes "invalid op" from glViewport! */ + } + + program = get_string_resource (mi->dpy, "program", "Program"); + + { + int cw, lh; + sc->texfont = load_texture_font (MI_DISPLAY(mi), "font"); + check_gl_error ("loading font"); + cw = texture_string_width (sc->texfont, "n", &lh); + sc->char_width = cw; + sc->line_height = lh; + } + + if (!wire) + { + glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + glEnable (GL_BLEND); + glEnable (GL_ALPHA_TEST); + glEnable (GL_TEXTURE_2D); + + /* "Anistropic filtering helps for quadrilateral-angled textures. + A sharper image is accomplished by interpolating and filtering + multiple samples from one or more mipmaps to better approximate + very distorted textures. This is the next level of filtering + after trilinear filtering." */ + if (strstr ((char *) glGetString(GL_EXTENSIONS), + "GL_EXT_texture_filter_anisotropic")) + { + GLfloat anisotropic = 0.0; + glGetFloatv (GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, &anisotropic); + if (anisotropic >= 1.0) + glTexParameterf (GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, + anisotropic); + } + } + + /* The default font is (by fiat) "18 points". + Interpret the user's font size request relative to that. + */ + sc->font_scale = 3 * (font_size / 18.0); + + if (target_columns <= 2) target_columns = 2; + + /* Figure out what the wrap column should be, in font-coordinate pixels. + Compute it from the given -columns value, but don't let it be wider + than the screen. + */ + { + GLfloat maxw = 110 * sc->line_height / sc->font_scale; /* magic... */ + sc->font_wrap_pixels = target_columns * sc->char_width; + if (sc->font_wrap_pixels > maxw || + sc->font_wrap_pixels <= 0) + sc->font_wrap_pixels = maxw; + } + + sc->buf_size = target_columns * max_lines; + sc->buf = (char *) calloc (1, sc->buf_size); + + alignment_random_p = False; + if (!alignment_str || !*alignment_str || + !strcasecmp(alignment_str, "left")) + alignment = -1; + else if (!strcasecmp(alignment_str, "center") || + !strcasecmp(alignment_str, "middle")) + alignment = 0; + else if (!strcasecmp(alignment_str, "right")) + alignment = 1; + else if (!strcasecmp(alignment_str, "random")) + alignment = -1, alignment_random_p = True; + + else + { + fprintf (stderr, + "%s: alignment must be left/center/right/random, not \"%s\"\n", + progname, alignment_str); + exit (1); + } + + sc->tc = textclient_open (sc->dpy); + + if (max_lines < 1) max_lines = 1; + min_lines = max_lines * 0.66; + if (min_lines > max_lines - 3) min_lines = max_lines - 4; + if (min_lines < 1) min_lines = 1; + + parse_color (mi, "foreground", + get_string_resource(mi->dpy, "foreground", "Foreground"), + sc->color); + + sc->top_margin = (sc->char_width * 100); + sc->bottom_margin = -sc->top_margin; + reshape_fliptext (mi, MI_WIDTH(mi), MI_HEIGHT(mi)); /* compute left/right */ +} + + +ENTRYPOINT void +draw_fliptext (ModeInfo *mi) +{ + fliptext_configuration *sc = &scs[MI_SCREEN(mi)]; +/* XtAppContext app = XtDisplayToApplicationContext (sc->dpy);*/ + Display *dpy = MI_DISPLAY(mi); + Window window = MI_WINDOW(mi); + int i; + + if (!sc->glx_context) + return; + + glXMakeCurrent(MI_DISPLAY(mi), MI_WINDOW(mi), *(sc->glx_context)); + +#if 0 + if (XtAppPending (app) & (XtIMTimer|XtIMAlternateInput)) + XtAppProcessEvent (app, XtIMTimer|XtIMAlternateInput); +#endif + + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + + mi->polygon_count = 0; + + glPushMatrix(); + glRotatef(current_device_rotation(), 0, 0, 1); + { + GLfloat s = 3.0 / (sc->top_margin - sc->bottom_margin); + glScalef(s, s, s); + } + + glRotatef (sc->rotation.x, 1, 0, 0); + glRotatef (sc->rotation.y, 0, 1, 0); + glRotatef (sc->rotation.z, 0, 0, 1); + +#if 0 + glDisable (GL_TEXTURE_2D); + glColor3f (1,1,1); + glBegin (GL_LINE_LOOP); + glVertex3f (sc->left_margin, sc->top_margin, 0); + glVertex3f (sc->right_margin, sc->top_margin, 0); + glVertex3f (sc->right_margin, sc->bottom_margin, 0); + glVertex3f (sc->left_margin, sc->bottom_margin, 0); + glEnd(); + glBegin (GL_LINES); + glVertex3f (sc->in.x, sc->top_margin, sc->in.z); + glVertex3f (sc->in.x, sc->bottom_margin, sc->in.z); + glVertex3f (sc->mid.x, sc->top_margin, sc->mid.z); + glVertex3f (sc->mid.x, sc->bottom_margin, sc->mid.z); + glVertex3f (sc->out.x, sc->top_margin, sc->out.z); + glVertex3f (sc->out.x, sc->bottom_margin, sc->out.z); + glEnd(); + glEnable (GL_TEXTURE_2D); +#endif + + for (i = 0; i < sc->nlines; i++) + { + line *line = sc->lines[i]; + draw_line (mi, line); + tick_line (sc, line); + } + + for (i = sc->nlines-1; i >= 0; i--) + { + line *line = sc->lines[i]; + if (line->state == DEAD) + free_line (sc, line); + } + + if (sc->nlines == 0) + reset_lines (mi); + + glPopMatrix(); + + if (mi->fps_p) do_fps (mi); + glFinish(); + glXSwapBuffers(dpy, window); +} + +ENTRYPOINT void +release_fliptext (ModeInfo *mi) +{ + if (scs) { + int screen; + for (screen = 0; screen < MI_NUM_SCREENS(mi); screen++) { + fliptext_configuration *sc = &scs[screen]; + if (sc->tc) + textclient_close (sc->tc); + + /* #### there's more to free here */ + } + free (scs); + scs = 0; + } + FreeAllGL(mi); +} + +XSCREENSAVER_MODULE ("FlipText", fliptext) + +#endif /* USE_GL */ diff --git a/hacks/glx/fliptext.man b/hacks/glx/fliptext.man new file mode 100644 index 00000000..8d2915ef --- /dev/null +++ b/hacks/glx/fliptext.man @@ -0,0 +1,114 @@ +.TH XScreenSaver 1 "20-Mar-2005" "X Version 11" +.SH NAME +fliptext - draws pages of text whose lines transparently flip around +.SH SYNOPSIS +.B fliptext +[\-display \fIhost:display.screen\fP] [\-window] [\-root] +[\-visual \fIvisual\fP] +[\-delay \fImicroseconds\fP] +[\-program \fIcommand\fP] +[\-size \fIinteger\fP ] +[\-columns \fIinteger\fP] +[\-left | \-center | \-right] +[\-lines \fIinteger\fP] +[\-speed \fIfloat\fP] +[\-delay \fIusecs\fP] +[\-font \fIxlfd\fP] +[\-wireframe] +[\-fps] +.SH DESCRIPTION +The \fIfliptext\fP program runs another program to generate a stream of +text, then animates the lines of that text transparently flipping in +and out in 3D. +.SH OPTIONS +.I fliptext +accepts the following options: +.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 \-install +Install a private colormap for the window. +.TP 8 +.B \-visual \fIvisual\fP\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 \-program \fIsh-command\fP +This program will be run periodically, and its output will be the text +that is displayed. Default \fIxscreensaver\-text\fP. + +You can configure the text printed through the "Advanced" tab of +.BR xscreensaver\-demo (1), +or by editing your ~/.xscreensaver file. +.TP 8 +.B \-size \fIinteger\fP +How large a font to use, in points. (Well, in some arbitrary unit +we're calling "points" for the sake of argument.) Default: 20. +.TP 8 +.B \-columns \fIinteger\fP +At (approximately) what column to wrap lines. Default 80. Wrapping is +done by pixels, not characters, and lines will always wrap at the +edge of the screen regardless. +.TP 8 +.B \-left | \-center | \-right +Whether to align the text flush left, centered, or flush right. +The default is to choose randomly each time a new screen of text +is displayed. +.TP 8 +.B \-lines \fIinteger\fP +How many lines of text should be shown at once. Default 8. +.TP 8 +.B \-speed \fIratio\fP +Change the animation speed; 0.5 to go half as fast, 2.0 to go twice as fast. +.TP 8 +.B \-delay \fIusecs\fP +The delay between frames of the animation; default is 10000 (1/10th second.) +.TP 8 +.B \-font \fIfont-name\fP +The name of the font to use. For best effect, this should be a large +font (at least 36 points.) The bigger the font, the better looking the +characters will be. Note that the size of this font affects only the +clarity of the characters, not their size on the screen: for that, use +the \fI\-size\fP or \fI\-columns\fP options. + +Default: -*-utopia-bold-r-normal-*-*-720-*-*-*-*-iso8859-1 +.TP 8 +.B \-fps +Display the current frame rate, CPU load, and polygon count. +.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 xscreensaver (1), +.BR xscreensaver-text (1), +.BR fortune (1), +.BR phosphor (MANSUFFIX), +.BR apple2 (MANSUFFIX), +.BR fontglide (MANSUFFIX), +.BR ljlatest (MANSUFFIX), +.BR dadadodo (1), +.BR webcollage (MANSUFFIX), +.BR driftnet (1) +.BR EtherPEG , +.BR EtherPeek +.SH COPYRIGHT +Copyright \(co 2005 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/glx/flurry-smoke.c b/hacks/glx/flurry-smoke.c new file mode 100644 index 00000000..a7786215 --- /dev/null +++ b/hacks/glx/flurry-smoke.c @@ -0,0 +1,1442 @@ +/* + +Copyright (c) 2002, Calum Robinson +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +* Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + +* Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + +* Neither the name of the author nor the names of its contributors may be used + to endorse or promote products derived from this software without specific + prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +*/ + +/* Smoke.cpp: implementation of the Smoke class. */ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include "flurry.h" + +#define MAXANGLES 16384 +#define NOT_QUITE_DEAD 3 + +#define intensity 75000.0f; + +void InitSmoke(SmokeV *s) +{ + int i; + s->nextParticle = 0; + s->nextSubParticle = 0; + s->lastParticleTime = 0.25f; + s->firstTime = 1; + s->frame = 0; + for (i=0;i<3;i++) { + s->old[i] = RandFlt(-100.0, 100.0); + } +} + +void UpdateSmoke_ScalarBase(global_info_t *global, flurry_info_t *flurry, SmokeV *s) +{ + int i,j,k; + float sx = flurry->star->position[0]; + float sy = flurry->star->position[1]; + float sz = flurry->star->position[2]; + double frameRate; + double frameRateModifier; + + + s->frame++; + + if(!s->firstTime) { + /* release 12 puffs every frame */ + if(flurry->fTime - s->lastParticleTime >= 1.0f / 121.0f) { + float dx,dy,dz,deltax,deltay,deltaz; + float f; + float rsquared; + float mag; + + dx = s->old[0] - sx; + dy = s->old[1] - sy; + dz = s->old[2] - sz; + mag = 5.0f; + deltax = (dx * mag); + deltay = (dy * mag); + deltaz = (dz * mag); + for(i=0;inumStreams;i++) { + float streamSpeedCoherenceFactor; + + s->p[s->nextParticle].delta[0].f[s->nextSubParticle] = deltax; + s->p[s->nextParticle].delta[1].f[s->nextSubParticle] = deltay; + s->p[s->nextParticle].delta[2].f[s->nextSubParticle] = deltaz; + s->p[s->nextParticle].position[0].f[s->nextSubParticle] = sx; + s->p[s->nextParticle].position[1].f[s->nextSubParticle] = sy; + s->p[s->nextParticle].position[2].f[s->nextSubParticle] = sz; + s->p[s->nextParticle].oldposition[0].f[s->nextSubParticle] = sx; + s->p[s->nextParticle].oldposition[1].f[s->nextSubParticle] = sy; + s->p[s->nextParticle].oldposition[2].f[s->nextSubParticle] = sz; + streamSpeedCoherenceFactor = MAX_(0.0f,1.0f + RandBell(0.25f*incohesion)); + dx = s->p[s->nextParticle].position[0].f[s->nextSubParticle] - flurry->spark[i]->position[0]; + dy = s->p[s->nextParticle].position[1].f[s->nextSubParticle] - flurry->spark[i]->position[1]; + dz = s->p[s->nextParticle].position[2].f[s->nextSubParticle] - flurry->spark[i]->position[2]; + rsquared = (dx*dx+dy*dy+dz*dz); + f = streamSpeed * streamSpeedCoherenceFactor; + + mag = f / (float) sqrt(rsquared); + + s->p[s->nextParticle].delta[0].f[s->nextSubParticle] -= (dx * mag); + s->p[s->nextParticle].delta[1].f[s->nextSubParticle] -= (dy * mag); + s->p[s->nextParticle].delta[2].f[s->nextSubParticle] -= (dz * mag); + s->p[s->nextParticle].color[0].f[s->nextSubParticle] = flurry->spark[i]->color[0] * (1.0f + RandBell(colorIncoherence)); + s->p[s->nextParticle].color[1].f[s->nextSubParticle] = flurry->spark[i]->color[1] * (1.0f + RandBell(colorIncoherence)); + s->p[s->nextParticle].color[2].f[s->nextSubParticle] = flurry->spark[i]->color[2] * (1.0f + RandBell(colorIncoherence)); + s->p[s->nextParticle].color[3].f[s->nextSubParticle] = 0.85f * (1.0f + RandBell(0.5f*colorIncoherence)); + s->p[s->nextParticle].time.f[s->nextSubParticle] = flurry->fTime; + s->p[s->nextParticle].dead.i[s->nextSubParticle] = 0; + s->p[s->nextParticle].animFrame.i[s->nextSubParticle] = random()&63; + s->nextSubParticle++; + if (s->nextSubParticle==4) { + s->nextParticle++; + s->nextSubParticle=0; + } + if (s->nextParticle >= NUMSMOKEPARTICLES/4) { + s->nextParticle = 0; + s->nextSubParticle = 0; + } + } + + s->lastParticleTime = flurry->fTime; + } + } else { + s->lastParticleTime = flurry->fTime; + s->firstTime = 0; + } + + for(i=0;i<3;i++) { + s->old[i] = flurry->star->position[i]; + } + + frameRate = ((double) flurry->dframe)/(flurry->fTime); + frameRateModifier = 42.5f / frameRate; + + for(i=0;ip[i].dead.i[k]) { + continue; + } + + deltax = s->p[i].delta[0].f[k]; + deltay = s->p[i].delta[1].f[k]; + deltaz = s->p[i].delta[2].f[k]; + + for(j=0;jnumStreams;j++) { + dx = s->p[i].position[0].f[k] - flurry->spark[j]->position[0]; + dy = s->p[i].position[1].f[k] - flurry->spark[j]->position[1]; + dz = s->p[i].position[2].f[k] - flurry->spark[j]->position[2]; + rsquared = (dx*dx+dy*dy+dz*dz); + + f = (gravity/rsquared) * frameRateModifier; + + if ((((i*4)+k) % flurry->numStreams) == j) { + f *= 1.0f + streamBias; + } + + mag = f / (float) sqrt(rsquared); + + deltax -= (dx * mag); + deltay -= (dy * mag); + deltaz -= (dz * mag); + } + + /* slow this particle down by flurry->drag */ + deltax *= flurry->drag; + deltay *= flurry->drag; + deltaz *= flurry->drag; + + if((deltax*deltax+deltay*deltay+deltaz*deltaz) >= 25000000.0f) { + s->p[i].dead.i[k] = 1; + continue; + } + + /* update the position */ + s->p[i].delta[0].f[k] = deltax; + s->p[i].delta[1].f[k] = deltay; + s->p[i].delta[2].f[k] = deltaz; + for(j=0;j<3;j++) { + s->p[i].oldposition[j].f[k] = s->p[i].position[j].f[k]; + s->p[i].position[j].f[k] += (s->p[i].delta[j].f[k])*flurry->fDeltaTime; + } + } + } +} + +#if 0 +#ifdef __ppc__ + +void UpdateSmoke_ScalarFrsqrte(global_info_t *global, flurry_info_t *flurry, SmokeV *s) +{ + int i,j,k; + float sx = flurry->star->position[0]; + float sy = flurry->star->position[1]; + float sz = flurry->star->position[2]; + double frameRate; + double frameRateModifier; + + + s->frame++; + + if(!s->firstTime) { + /* release 12 puffs every frame */ + if(flurry->fTime - s->lastParticleTime >= 1.0f / 121.0f) { + float dx,dy,dz,deltax,deltay,deltaz; + float f; + float rsquared; + float mag; + + dx = s->old[0] - sx; + dy = s->old[1] - sy; + dz = s->old[2] - sz; + mag = 5.0f; + deltax = (dx * mag); + deltay = (dy * mag); + deltaz = (dz * mag); + for(i=0;inumStreams;i++) { + float streamSpeedCoherenceFactor; + + s->p[s->nextParticle].delta[0].f[s->nextSubParticle] = deltax; + s->p[s->nextParticle].delta[1].f[s->nextSubParticle] = deltay; + s->p[s->nextParticle].delta[2].f[s->nextSubParticle] = deltaz; + s->p[s->nextParticle].position[0].f[s->nextSubParticle] = sx; + s->p[s->nextParticle].position[1].f[s->nextSubParticle] = sy; + s->p[s->nextParticle].position[2].f[s->nextSubParticle] = sz; + s->p[s->nextParticle].oldposition[0].f[s->nextSubParticle] = sx; + s->p[s->nextParticle].oldposition[1].f[s->nextSubParticle] = sy; + s->p[s->nextParticle].oldposition[2].f[s->nextSubParticle] = sz; + streamSpeedCoherenceFactor = MAX_(0.0f,1.0f + RandBell(0.25f*incohesion)); + dx = s->p[s->nextParticle].position[0].f[s->nextSubParticle] - flurry->spark[i]->position[0]; + dy = s->p[s->nextParticle].position[1].f[s->nextSubParticle] - flurry->spark[i]->position[1]; + dz = s->p[s->nextParticle].position[2].f[s->nextSubParticle] - flurry->spark[i]->position[2]; + rsquared = (dx*dx+dy*dy+dz*dz); + f = streamSpeed * streamSpeedCoherenceFactor; + + mag = f / (float) sqrt(rsquared); + /* + reciprocal square-root estimate replaced above divide and call to system sqrt() + + asm("frsqrte %0, %1" : "=f" (mag) : "f" (rsquared)); + mag *= f; + */ + + s->p[s->nextParticle].delta[0].f[s->nextSubParticle] -= (dx * mag); + s->p[s->nextParticle].delta[1].f[s->nextSubParticle] -= (dy * mag); + s->p[s->nextParticle].delta[2].f[s->nextSubParticle] -= (dz * mag); + s->p[s->nextParticle].color[0].f[s->nextSubParticle] = flurry->spark[i]->color[0] * (1.0f + RandBell(colorIncoherence)); + s->p[s->nextParticle].color[1].f[s->nextSubParticle] = flurry->spark[i]->color[1] * (1.0f + RandBell(colorIncoherence)); + s->p[s->nextParticle].color[2].f[s->nextSubParticle] = flurry->spark[i]->color[2] * (1.0f + RandBell(colorIncoherence)); + s->p[s->nextParticle].color[3].f[s->nextSubParticle] = 0.85f * (1.0f + RandBell(0.5f*colorIncoherence)); + s->p[s->nextParticle].time.f[s->nextSubParticle] = flurry->fTime; + s->p[s->nextParticle].dead.i[s->nextSubParticle] = 0; + s->p[s->nextParticle].animFrame.i[s->nextSubParticle] = random()&63; + s->nextSubParticle++; + if (s->nextSubParticle==4) { + s->nextParticle++; + s->nextSubParticle=0; + } + if (s->nextParticle >= NUMSMOKEPARTICLES/4) { + s->nextParticle = 0; + s->nextSubParticle = 0; + } + } + + s->lastParticleTime = flurry->fTime; + } + } else { + s->lastParticleTime = flurry->fTime; + s->firstTime = 0; + } + + for(i=0;i<3;i++) { + s->old[i] = flurry->star->position[i]; + } + + frameRate = ((double) flurry->dframe)/(flurry->fTime); + frameRateModifier = 42.5f / frameRate; + + for(i=0;ip[i].dead.i[k]) { + continue; + } + + deltax = s->p[i].delta[0].f[k]; + deltay = s->p[i].delta[1].f[k]; + deltaz = s->p[i].delta[2].f[k]; + + for(j=0;jnumStreams;j++) { + dx = s->p[i].position[0].f[k] - flurry->spark[j]->position[0]; + dy = s->p[i].position[1].f[k] - flurry->spark[j]->position[1]; + dz = s->p[i].position[2].f[k] - flurry->spark[j]->position[2]; + rsquared = (dx*dx+dy*dy+dz*dz); + + /* + asm("fres %0, %1" : "=f" (f) : "f" (rsquared)); + f *= gravity*frameRateModifier; + */ + f = ( gravity * frameRateModifier ) / rsquared; + + if((((i*4)+k) % flurry->numStreams) == j) { + f *= 1.0f + streamBias; + } + + mag = f / (float) sqrt(rsquared); + + /* reciprocal square-root estimate replaced above divide and call to system sqrt() */ + + deltax -= (dx * mag); + deltay -= (dy * mag); + deltaz -= (dz * mag); + } + + /* slow this particle down by flurry->drag */ + deltax *= flurry->drag; + deltay *= flurry->drag; + deltaz *= flurry->drag; + + if((deltax*deltax+deltay*deltay+deltaz*deltaz) >= 25000000.0f) { + s->p[i].dead.i[k] = 1; + continue; + } + + /* update the position */ + s->p[i].delta[0].f[k] = deltax; + s->p[i].delta[1].f[k] = deltay; + s->p[i].delta[2].f[k] = deltaz; + for(j=0;j<3;j++) { + s->p[i].oldposition[j].f[k] = s->p[i].position[j].f[k]; + s->p[i].position[j].f[k] += (s->p[i].delta[j].f[k])*flurry->fDeltaTime; + } + } + } +} + +#endif + +#ifdef __VEC__ + +void UpdateSmoke_VectorBase(global_info_t *global, flurry_info_t *flurry, SmokeV *s) +{ + unsigned int i,j; + float sx = flurry->star->position[0]; + float sy = flurry->star->position[1]; + float sz = flurry->star->position[2]; + double frameRate; + floatToVector frameRateModifier; + floatToVector gravityV; + floatToVector dragV; + floatToVector deltaTimeV; + const vector float deadConst = (vector float) (25000000.0,25000000.0,25000000.0,25000000.0); + const vector float zero = (vector float)(0.0, 0.0, 0.0, 0.0); + const vector float biasConst = (vector float)(streamBias); + + gravityV.f[0] = gravity; + gravityV.v = (vector float) vec_splat((vector unsigned int)gravityV.v, 0); + + dragV.f[0] = flurry->drag; + dragV.v = (vector float) vec_splat((vector unsigned int)dragV.v, 0); + + deltaTimeV.f[0] = flurry->fDeltaTime; + deltaTimeV.v = (vector float) vec_splat((vector unsigned int)deltaTimeV.v, 0); + + s->frame++; + + if(!s->firstTime) { + /* release 12 puffs every frame */ + if(flurry->fTime - s->lastParticleTime >= 1.0f / 121.0f) { + float dx,dy,dz,deltax,deltay,deltaz; + float f; + float rsquared; + float mag; + + dx = s->old[0] - sx; + dy = s->old[1] - sy; + dz = s->old[2] - sz; + mag = 5.0f; + deltax = (dx * mag); + deltay = (dy * mag); + deltaz = (dz * mag); + for(i=0;inumStreams;i++) { + float streamSpeedCoherenceFactor; + + s->p[s->nextParticle].delta[0].f[s->nextSubParticle] = deltax; + s->p[s->nextParticle].delta[1].f[s->nextSubParticle] = deltay; + s->p[s->nextParticle].delta[2].f[s->nextSubParticle] = deltaz; + s->p[s->nextParticle].position[0].f[s->nextSubParticle] = sx; + s->p[s->nextParticle].position[1].f[s->nextSubParticle] = sy; + s->p[s->nextParticle].position[2].f[s->nextSubParticle] = sz; + s->p[s->nextParticle].oldposition[0].f[s->nextSubParticle] = sx; + s->p[s->nextParticle].oldposition[1].f[s->nextSubParticle] = sy; + s->p[s->nextParticle].oldposition[2].f[s->nextSubParticle] = sz; + streamSpeedCoherenceFactor = MAX_(0.0f,1.0f + RandBell(0.25f*incohesion)); + dx = s->p[s->nextParticle].position[0].f[s->nextSubParticle] - flurry->spark[i]->position[0]; + dy = s->p[s->nextParticle].position[1].f[s->nextSubParticle] - flurry->spark[i]->position[1]; + dz = s->p[s->nextParticle].position[2].f[s->nextSubParticle] - flurry->spark[i]->position[2]; + rsquared = (dx*dx+dy*dy+dz*dz); + f = streamSpeed * streamSpeedCoherenceFactor; + + mag = f / (float) sqrt(rsquared); + /* + asm("frsqrte %0, %1" : "=f" (mag) : "f" (rsquared)); + mag *= f; + */ + + s->p[s->nextParticle].delta[0].f[s->nextSubParticle] -= (dx * mag); + s->p[s->nextParticle].delta[1].f[s->nextSubParticle] -= (dy * mag); + s->p[s->nextParticle].delta[2].f[s->nextSubParticle] -= (dz * mag); + s->p[s->nextParticle].color[0].f[s->nextSubParticle] = flurry->spark[i]->color[0] * (1.0f + RandBell(colorIncoherence)); + s->p[s->nextParticle].color[1].f[s->nextSubParticle] = flurry->spark[i]->color[1] * (1.0f + RandBell(colorIncoherence)); + s->p[s->nextParticle].color[2].f[s->nextSubParticle] = flurry->spark[i]->color[2] * (1.0f + RandBell(colorIncoherence)); + s->p[s->nextParticle].color[3].f[s->nextSubParticle] = 0.85f * (1.0f + RandBell(0.5f*colorIncoherence)); + s->p[s->nextParticle].time.f[s->nextSubParticle] = flurry->fTime; + s->p[s->nextParticle].dead.i[s->nextSubParticle] = 0; + s->p[s->nextParticle].animFrame.i[s->nextSubParticle] = random()&63; + s->nextSubParticle++; + if (s->nextSubParticle==4) { + s->nextParticle++; + s->nextSubParticle=0; + } + if (s->nextParticle >= NUMSMOKEPARTICLES/4) { + s->nextParticle = 0; + s->nextSubParticle = 0; + } + } + + s->lastParticleTime = flurry->fTime; + } + } else { + s->lastParticleTime = flurry->fTime; + s->firstTime = 0; + } + + for(i=0;i<3;i++) { + s->old[i] = flurry->star->position[i]; + } + + frameRate = ((double) flurry->dframe)/(flurry->fTime); + frameRateModifier.f[0] = 42.5f / frameRate; + frameRateModifier.v = (vector float) vec_splat((vector unsigned int)frameRateModifier.v, 0); + + frameRateModifier.v = vec_madd(frameRateModifier.v, gravityV.v, zero); + + for(i=0;ip[i+4])), 0x00020200, 3); + + if (vec_all_ne(s->p[i].dead.v, (vector unsigned int)(0))) { + continue; + } + + deltax = s->p[i].delta[0].v; + deltay = s->p[i].delta[1].v; + deltaz = s->p[i].delta[2].v; + + mod.i[0] = (i<<2 + 0) % flurry->numStreams; + if(mod.i[0]+1 == flurry->numStreams) { + mod.i[1] = 0; + } else { + mod.i[1] = mod.i[0]+1; + } + if(mod.i[1]+1 == flurry->numStreams) { + mod.i[2] = 0; + } else { + mod.i[2] = mod.i[1]+1; + } + if(mod.i[2]+1 == flurry->numStreams) { + mod.i[3] = 0; + } else { + mod.i[3] = mod.i[2]+1; + } + + jVec = vec_xor(jVec, jVec); + + vec_dst( &flurry->spark[0]->position[0], 0x16020160, 3 ); + for(j=0; jnumStreams;j++) { + vector float ip0, ip1 = (vector float)(0.0), ip2; + vector float dx, dy, dz; + vector float rsquared, f; + vector float one_over_rsquared; + vector float biasTemp; + vector float mag; + vector bool int biasOr; + + ip0 = vec_ld(0, flurry->spark[j]->position); + if(((int)(flurry->spark[j]->position) & 0xF)>=8) { + ip1 = vec_ld(16, flurry->spark[j]->position); + } + + ip0 = vec_perm(ip0, ip1, vec_lvsl(0, flurry->spark[j]->position)); + ip1 = (vector float) vec_splat((vector unsigned int)ip0, 1); + ip2 = (vector float) vec_splat((vector unsigned int)ip0, 2); + ip0 = (vector float) vec_splat((vector unsigned int)ip0, 0); + + dx = vec_sub(s->p[i].position[0].v, ip0); + dy = vec_sub(s->p[i].position[1].v, ip1); + dz = vec_sub(s->p[i].position[2].v, ip2); + + rsquared = vec_madd(dx, dx, zero); + rsquared = vec_madd(dy, dy, rsquared); + rsquared = vec_madd(dz, dz, rsquared); + + biasOr = vec_cmpeq(jVec, mod.v); + biasTemp = vec_add(vec_and(biasOr, biasConst), (vector float)(1.0)); + + f = vec_madd(biasTemp, frameRateModifier.v, zero); + one_over_rsquared = vec_re(rsquared); + f = vec_madd(f, one_over_rsquared, zero); + + mag = vec_rsqrte(rsquared); + mag = vec_madd(mag, f, zero); + + deltax = vec_nmsub(dx, mag, deltax); + deltay = vec_nmsub(dy, mag, deltay); + deltaz = vec_nmsub(dz, mag, deltaz); + + jVec = vec_add(jVec, (vector unsigned int)(1)); + } + + /* slow this particle down by flurry->drag */ + deltax = vec_madd(deltax, dragV.v, zero); + deltay = vec_madd(deltay, dragV.v, zero); + deltaz = vec_madd(deltaz, dragV.v, zero); + + distTemp = vec_madd(deltax, deltax, zero); + distTemp = vec_madd(deltay, deltay, distTemp); + distTemp = vec_madd(deltaz, deltaz, distTemp); + + deadTemp = (vector unsigned int) vec_cmpge(distTemp, deadConst); + deadTemp = vec_and((vector unsigned int)vec_splat_u32(1), deadTemp); + s->p[i].dead.v = vec_or(s->p[i].dead.v, deadTemp); + if (vec_all_ne(s->p[i].dead.v, (vector unsigned int)(0))) { + continue; + } + + /* update the position */ + s->p[i].delta[0].v = deltax; + s->p[i].delta[1].v = deltay; + s->p[i].delta[2].v = deltaz; + for(j=0;j<3;j++) { + s->p[i].oldposition[j].v = s->p[i].position[j].v; + s->p[i].position[j].v = vec_madd(s->p[i].delta[j].v, deltaTimeV.v, s->p[i].position[j].v); + } + } +} + +void UpdateSmoke_VectorUnrolled(global_info_t *info, SmokeV *s) +{ + unsigned int i,j; + float sx = flurry->star->position[0]; + float sy = flurry->star->position[1]; + float sz = flurry->star->position[2]; + double frameRate; + floatToVector frameRateModifier; + floatToVector gravityV; + floatToVector dragV; + floatToVector deltaTimeV; + const vector float deadConst = (vector float) (25000000.0,25000000.0,25000000.0,25000000.0); + const vector float zero = (vector float)(0.0, 0.0, 0.0, 0.0); + const vector float biasConst = (vector float)(streamBias); + + gravityV.f[0] = gravity; + gravityV.v = (vector float) vec_splat((vector unsigned int)gravityV.v, 0); + + dragV.f[0] = flurry->drag; + dragV.v = (vector float) vec_splat((vector unsigned int)dragV.v, 0); + + deltaTimeV.f[0] = flurry->fDeltaTime; + deltaTimeV.v = (vector float) vec_splat((vector unsigned int)deltaTimeV.v, 0); + + s->frame++; + + if(!s->firstTime) { + /* release 12 puffs every frame */ + if(flurry->fTime - s->lastParticleTime >= 1.0f / 121.0f) { + float dx,dy,dz,deltax,deltay,deltaz; + float f; + float rsquared; + float mag; + + dx = s->old[0] - sx; + dy = s->old[1] - sy; + dz = s->old[2] - sz; + mag = 5.0f; + deltax = (dx * mag); + deltay = (dy * mag); + deltaz = (dz * mag); + for(i=0;inumStreams;i++) { + float streamSpeedCoherenceFactor; + + s->p[s->nextParticle].delta[0].f[s->nextSubParticle] = deltax; + s->p[s->nextParticle].delta[1].f[s->nextSubParticle] = deltay; + s->p[s->nextParticle].delta[2].f[s->nextSubParticle] = deltaz; + s->p[s->nextParticle].position[0].f[s->nextSubParticle] = sx; + s->p[s->nextParticle].position[1].f[s->nextSubParticle] = sy; + s->p[s->nextParticle].position[2].f[s->nextSubParticle] = sz; + s->p[s->nextParticle].oldposition[0].f[s->nextSubParticle] = sx; + s->p[s->nextParticle].oldposition[1].f[s->nextSubParticle] = sy; + s->p[s->nextParticle].oldposition[2].f[s->nextSubParticle] = sz; + streamSpeedCoherenceFactor = MAX_(0.0f,1.0f + RandBell(0.25f*incohesion)); + dx = s->p[s->nextParticle].position[0].f[s->nextSubParticle] - flurry->spark[i]->position[0]; + dy = s->p[s->nextParticle].position[1].f[s->nextSubParticle] - flurry->spark[i]->position[1]; + dz = s->p[s->nextParticle].position[2].f[s->nextSubParticle] - flurry->spark[i]->position[2]; + rsquared = (dx*dx+dy*dy+dz*dz); + f = streamSpeed * streamSpeedCoherenceFactor; + + mag = f / (float) sqrt(rsquared); + /* + asm("frsqrte %0, %1" : "=f" (mag) : "f" (rsquared)); + mag *= f; + */ + + s->p[s->nextParticle].delta[0].f[s->nextSubParticle] -= (dx * mag); + s->p[s->nextParticle].delta[1].f[s->nextSubParticle] -= (dy * mag); + s->p[s->nextParticle].delta[2].f[s->nextSubParticle] -= (dz * mag); + s->p[s->nextParticle].color[0].f[s->nextSubParticle] = flurry->spark[i]->color[0] * (1.0f + RandBell(colorIncoherence)); + s->p[s->nextParticle].color[1].f[s->nextSubParticle] = flurry->spark[i]->color[1] * (1.0f + RandBell(colorIncoherence)); + s->p[s->nextParticle].color[2].f[s->nextSubParticle] = flurry->spark[i]->color[2] * (1.0f + RandBell(colorIncoherence)); + s->p[s->nextParticle].color[3].f[s->nextSubParticle] = 0.85f * (1.0f + RandBell(0.5f*colorIncoherence)); + s->p[s->nextParticle].time.f[s->nextSubParticle] = flurry->fTime; + s->p[s->nextParticle].dead.i[s->nextSubParticle] = 0; + s->p[s->nextParticle].animFrame.i[s->nextSubParticle] = random()&63; + s->nextSubParticle++; + if (s->nextSubParticle==4) { + s->nextParticle++; + s->nextSubParticle=0; + } + if (s->nextParticle >= NUMSMOKEPARTICLES/4) { + s->nextParticle = 0; + s->nextSubParticle = 0; + } + } + + s->lastParticleTime = flurry->fTime; + } + } else { + s->lastParticleTime = flurry->fTime; + s->firstTime = 0; + } + + for(i=0;i<3;i++) { + s->old[i] = flurry->star->position[i]; + } + + frameRate = ((double) flurry->dframe)/(flurry->fTime); + frameRateModifier.f[0] = 42.5f / frameRate; + frameRateModifier.v = (vector float) vec_splat((vector unsigned int)frameRateModifier.v, 0); + + frameRateModifier.v = vec_madd(frameRateModifier.v, gravityV.v, zero); + + for(i=0;ip[i+4])), 0x00020200, 3); + + if (vec_all_ne(s->p[i].dead.v, (vector unsigned int)(0))) { + continue; + } + + deltax = s->p[i].delta[0].v; + deltay = s->p[i].delta[1].v; + deltaz = s->p[i].delta[2].v; + + mod.i[0] = (i<<2 + 0) % flurry->numStreams; + if(mod.i[0]+1 == flurry->numStreams) { + mod.i[1] = 0; + } else { + mod.i[1] = mod.i[0]+1; + } + if(mod.i[1]+1 == flurry->numStreams) { + mod.i[2] = 0; + } else { + mod.i[2] = mod.i[1]+1; + } + if(mod.i[2]+1 == flurry->numStreams) { + mod.i[3] = 0; + } else { + mod.i[3] = mod.i[2]+1; + } + + jVec = vec_xor(jVec, jVec); + + vec_dst( &flurry->spark[0]->position[0], 0x16020160, 3 ); + for(j=0; j + 3 < flurry->numStreams;j+=4) + { + vector float dxa, dya, dza; + vector float dxb, dyb, dzb; + vector float dxc, dyc, dzc; + vector float dxd, dyd, dzd; + vector float ip0a, ip1a; + vector float ip0b, ip1b; + vector float ip0c, ip1c; + vector float ip0d, ip1d; + vector float rsquaredA; + vector float rsquaredB; + vector float rsquaredC; + vector float rsquaredD; + vector float fA, fB, fC, fD; + vector float biasTempA; + vector float biasTempB; + vector float biasTempC; + vector float biasTempD; + vector float magA; + vector float magB; + vector float magC; + vector float magD; + + vector float one_over_rsquaredA; + vector float one_over_rsquaredB; + vector float one_over_rsquaredC; + vector float one_over_rsquaredD; + vector bool int biasOrA,biasOrB,biasOrC,biasOrD; + + /* load vectors */ + ip0a = vec_ld(0, flurry->spark[j]->position); + ip0b = vec_ld(0, flurry->spark[j+1]->position); + ip0c = vec_ld(0, flurry->spark[j+2]->position); + ip0d = vec_ld(0, flurry->spark[j+3]->position); + ip1a = vec_ld( 12, flurry->spark[j]->position ); + ip1b = vec_ld( 12, flurry->spark[j+1]->position ); + ip1c = vec_ld( 12, flurry->spark[j+2]->position ); + ip1d = vec_ld( 12, flurry->spark[j+3]->position ); + + /* align them */ + ip0a = vec_perm(ip0a, ip1a, vec_lvsl(0, flurry->spark[j]->position)); + ip0b = vec_perm(ip0b, ip1b, vec_lvsl(0, flurry->spark[j+1]->position)); + ip0c = vec_perm(ip0c, ip1c, vec_lvsl(0, flurry->spark[j+2]->position)); + ip0d = vec_perm(ip0d, ip1d, vec_lvsl(0, flurry->spark[j+3]->position)); + + dxa = vec_splat( ip0a, 0 ); + dxb = vec_splat( ip0b, 0 ); + dxc = vec_splat( ip0c, 0 ); + dxd = vec_splat( ip0d, 0 ); + dxa = vec_sub( s->p[i].position[0].v, dxa ); + dxb = vec_sub( s->p[i].position[0].v, dxb ); + dxc = vec_sub( s->p[i].position[0].v, dxc ); + dxd = vec_sub( s->p[i].position[0].v, dxd ); + + dya = vec_splat( ip0a, 1 ); + dyb = vec_splat( ip0b, 1 ); + dyc = vec_splat( ip0c, 1 ); + dyd = vec_splat( ip0d, 1 ); + dya = vec_sub( s->p[i].position[1].v, dya ); + dyb = vec_sub( s->p[i].position[1].v, dyb ); + dyc = vec_sub( s->p[i].position[1].v, dyc ); + dyd = vec_sub( s->p[i].position[1].v, dyd ); + + dza = vec_splat( ip0a, 2 ); + dzb = vec_splat( ip0b, 2 ); + dzc = vec_splat( ip0c, 2 ); + dzd = vec_splat( ip0d, 2 ); + dza = vec_sub( s->p[i].position[2].v, dza ); + dzb = vec_sub( s->p[i].position[2].v, dzb ); + dzc = vec_sub( s->p[i].position[2].v, dzc ); + dzd = vec_sub( s->p[i].position[2].v, dzd ); + + rsquaredA = vec_madd( dxa, dxa, zero ); + rsquaredB = vec_madd( dxb, dxb, zero ); + rsquaredC = vec_madd( dxc, dxc, zero ); + rsquaredD = vec_madd( dxd, dxd, zero ); + + rsquaredA = vec_madd( dya, dya, rsquaredA ); + rsquaredB = vec_madd( dyb, dyb, rsquaredB ); + rsquaredC = vec_madd( dyc, dyc, rsquaredC ); + rsquaredD = vec_madd( dyd, dyd, rsquaredD ); + + rsquaredA = vec_madd( dza, dza, rsquaredA ); + rsquaredB = vec_madd( dzb, dzb, rsquaredB ); + rsquaredC = vec_madd( dzc, dzc, rsquaredC ); + rsquaredD = vec_madd( dzd, dzd, rsquaredD ); + + biasOrA = vec_cmpeq( jVec, mod.v ); + jVec = vec_add(jVec, intOne); + biasOrB = vec_cmpeq( jVec, mod.v ); + jVec = vec_add(jVec, intOne); + biasOrC = vec_cmpeq( jVec, mod.v ); + jVec = vec_add(jVec, intOne); + biasOrD = vec_cmpeq( jVec, mod.v ); + jVec = vec_add(jVec, intOne); + + biasTempA = vec_add( vec_and( biasOrA, biasConst), floatOne); + biasTempB = vec_add( vec_and( biasOrB, biasConst), floatOne); + biasTempC = vec_add( vec_and( biasOrC, biasConst), floatOne); + biasTempD = vec_add( vec_and( biasOrD, biasConst), floatOne); + + fA = vec_madd( biasTempA, frameRateModifier.v, zero); + fB = vec_madd( biasTempB, frameRateModifier.v, zero); + fC = vec_madd( biasTempC, frameRateModifier.v, zero); + fD = vec_madd( biasTempD, frameRateModifier.v, zero); + one_over_rsquaredA = vec_re( rsquaredA ); + one_over_rsquaredB = vec_re( rsquaredB ); + one_over_rsquaredC = vec_re( rsquaredC ); + one_over_rsquaredD = vec_re( rsquaredD ); + fA = vec_madd( fA, one_over_rsquaredA, zero); + fB = vec_madd( fB, one_over_rsquaredB, zero); + fC = vec_madd( fC, one_over_rsquaredC, zero); + fD = vec_madd( fD, one_over_rsquaredD, zero); + magA = vec_rsqrte( rsquaredA ); + magB = vec_rsqrte( rsquaredB ); + magC = vec_rsqrte( rsquaredC ); + magD = vec_rsqrte( rsquaredD ); + magA = vec_madd( magA, fA, zero ); + magB = vec_madd( magB, fB, zero ); + magC = vec_madd( magC, fC, zero ); + magD = vec_madd( magD, fD, zero ); + deltax = vec_nmsub( dxa, magA, deltax ); + deltay = vec_nmsub( dya, magA, deltay ); + deltaz = vec_nmsub( dza, magA, deltaz ); + + deltax = vec_nmsub( dxb, magB, deltax ); + deltay = vec_nmsub( dyb, magB, deltay ); + deltaz = vec_nmsub( dzb, magB, deltaz ); + + deltax = vec_nmsub( dxc, magC, deltax ); + deltay = vec_nmsub( dyc, magC, deltay ); + deltaz = vec_nmsub( dzc, magC, deltaz ); + + deltax = vec_nmsub( dxd, magD, deltax ); + deltay = vec_nmsub( dyd, magD, deltay ); + deltaz = vec_nmsub( dzd, magD, deltaz ); + } + + + for(;jnumStreams;j++) { + vector float ip0, ip1 = (vector float)(0.0), ip2; + vector float dx, dy, dz; + vector float rsquared, f; + vector float one_over_rsquared; + vector float biasTemp; + vector float mag; + vector bool int biasOr; + + ip0 = vec_ld(0, flurry->spark[j]->position); + if(((int)(flurry->spark[j]->position) & 0xF)>=8) { + ip1 = vec_ld(16, flurry->spark[j]->position); + } + + ip0 = vec_perm(ip0, ip1, vec_lvsl(0, flurry->spark[j]->position)); + ip1 = (vector float) vec_splat((vector unsigned int)ip0, 1); + ip2 = (vector float) vec_splat((vector unsigned int)ip0, 2); + ip0 = (vector float) vec_splat((vector unsigned int)ip0, 0); + + dx = vec_sub(s->p[i].position[0].v, ip0); + dy = vec_sub(s->p[i].position[1].v, ip1); + dz = vec_sub(s->p[i].position[2].v, ip2); + + rsquared = vec_madd(dx, dx, zero); + rsquared = vec_madd(dy, dy, rsquared); + rsquared = vec_madd(dz, dz, rsquared); + + biasOr = vec_cmpeq(jVec, mod.v); + biasTemp = vec_add(vec_and(biasOr, biasConst), (vector float)(1.0)); + + f = vec_madd(biasTemp, frameRateModifier.v, zero); + one_over_rsquared = vec_re(rsquared); + f = vec_madd(f, one_over_rsquared, zero); + + mag = vec_rsqrte(rsquared); + mag = vec_madd(mag, f, zero); + + deltax = vec_nmsub(dx, mag, deltax); + deltay = vec_nmsub(dy, mag, deltay); + deltaz = vec_nmsub(dz, mag, deltaz); + + jVec = vec_add(jVec, (vector unsigned int)(1)); + } + + /* slow this particle down by flurry->drag */ + deltax = vec_madd(deltax, dragV.v, zero); + deltay = vec_madd(deltay, dragV.v, zero); + deltaz = vec_madd(deltaz, dragV.v, zero); + + distTemp = vec_madd(deltax, deltax, zero); + distTemp = vec_madd(deltay, deltay, distTemp); + distTemp = vec_madd(deltaz, deltaz, distTemp); + + deadTemp = (vector unsigned int) vec_cmpge(distTemp, deadConst); + deadTemp = vec_and((vector unsigned int)vec_splat_u32(1), deadTemp); + s->p[i].dead.v = vec_or(s->p[i].dead.v, deadTemp); + if (vec_all_ne(s->p[i].dead.v, (vector unsigned int)(0))) { + continue; + } + + /* update the position */ + s->p[i].delta[0].v = deltax; + s->p[i].delta[1].v = deltay; + s->p[i].delta[2].v = deltaz; + for(j=0;j<3;j++) { + s->p[i].oldposition[j].v = s->p[i].position[j].v; + s->p[i].position[j].v = vec_madd(s->p[i].delta[j].v, deltaTimeV.v, s->p[i].position[j].v); + } + } +} + +#endif +#endif /* 0 */ + +void DrawSmoke_Scalar(global_info_t *global, flurry_info_t *flurry, SmokeV *s, float brightness) +{ + int svi = 0; + int sci = 0; + int sti = 0; + int si = 0; + float width; + float sx,sy; + float u0,v0,u1,v1; + float w,z; + float screenRatio = global->sys_glWidth / 1024.0f; + float hslash2 = global->sys_glHeight * 0.5f; + float wslash2 = global->sys_glWidth * 0.5f; + int i,k; + + width = (streamSize+2.5f*flurry->streamExpansion) * screenRatio; + + for (i=0;ip[i].dead.i[k]) { + continue; + } + thisWidth = (streamSize + (flurry->fTime - s->p[i].time.f[k])*flurry->streamExpansion) * screenRatio; + if (thisWidth >= width) + { + s->p[i].dead.i[k] = 1; + continue; + } + z = s->p[i].position[2].f[k]; + sx = s->p[i].position[0].f[k] * global->sys_glWidth / z + wslash2; + sy = s->p[i].position[1].f[k] * global->sys_glWidth / z + hslash2; + oldz = s->p[i].oldposition[2].f[k]; + if (sx > global->sys_glWidth+50.0f || sx < -50.0f || sy > global->sys_glHeight+50.0f || sy < -50.0f || z < 25.0f || oldz < 25.0f) + { + continue; + } + + w = MAX_(1.0f,thisWidth/z); + { + float oldx = s->p[i].oldposition[0].f[k]; + float oldy = s->p[i].oldposition[1].f[k]; + float oldscreenx = (oldx * global->sys_glWidth / oldz) + wslash2; + float oldscreeny = (oldy * global->sys_glWidth / oldz) + hslash2; + float dx = (sx-oldscreenx); + float dy = (sy-oldscreeny); + + float d = FastDistance2D(dx, dy); + + float sm, os, ow; + if (d) + { + sm = w/d; + } + else + { + sm = 0.0f; + } + ow = MAX_(1.0f,thisWidth/oldz); + if (d) + { + os = ow/d; + } + else + { + os = 0.0f; + } + + { + floatToVector cmv; + float cm; + float m = 1.0f + sm; + + float dxs = dx*sm; + float dys = dy*sm; + float dxos = dx*os; + float dyos = dy*os; + float dxm = dx*m; + float dym = dy*m; + + s->p[i].animFrame.i[k]++; + if (s->p[i].animFrame.i[k] >= 64) + { + s->p[i].animFrame.i[k] = 0; + } + + u0 = (s->p[i].animFrame.i[k]& 7) * 0.125f; + v0 = (s->p[i].animFrame.i[k]>>3) * 0.125f; + u1 = u0 + 0.125f; + v1 = v0 + 0.125f; + cm = (1.375f - thisWidth/width); + if (s->p[i].dead.i[k] == 3) + { + cm *= 0.125f; + s->p[i].dead.i[k] = 1; + } + si++; + cm *= brightness; + cmv.f[0] = s->p[i].color[0].f[k]*cm; + cmv.f[1] = s->p[i].color[1].f[k]*cm; + cmv.f[2] = s->p[i].color[2].f[k]*cm; + cmv.f[3] = s->p[i].color[3].f[k]*cm; + +#if 0 + /* MDT we can't use vectors in the Scalar routine */ + s->seraphimColors[sci++].v = cmv.v; + s->seraphimColors[sci++].v = cmv.v; + s->seraphimColors[sci++].v = cmv.v; + s->seraphimColors[sci++].v = cmv.v; +#else + { + int ii, jj; + for (jj = 0; jj < 4; jj++) { + for (ii = 0; ii < 4; ii++) { + s->seraphimColors[sci].f[ii] = cmv.f[ii]; + } + sci += 1; + } + } +#endif + + s->seraphimTextures[sti++] = u0; + s->seraphimTextures[sti++] = v0; + s->seraphimTextures[sti++] = u0; + s->seraphimTextures[sti++] = v1; + + s->seraphimTextures[sti++] = u1; + s->seraphimTextures[sti++] = v1; + s->seraphimTextures[sti++] = u1; + s->seraphimTextures[sti++] = v0; + + s->seraphimVertices[svi].f[0] = sx+dxm-dys; + s->seraphimVertices[svi].f[1] = sy+dym+dxs; + s->seraphimVertices[svi].f[2] = sx+dxm+dys; + s->seraphimVertices[svi].f[3] = sy+dym-dxs; + svi++; + + s->seraphimVertices[svi].f[0] = oldscreenx-dxm+dyos; + s->seraphimVertices[svi].f[1] = oldscreeny-dym-dxos; + s->seraphimVertices[svi].f[2] = oldscreenx-dxm-dyos; + s->seraphimVertices[svi].f[3] = oldscreeny-dym+dxos; + svi++; + } + } + } + } + glColorPointer(4,GL_FLOAT,0,s->seraphimColors); + glVertexPointer(2,GL_FLOAT,0,s->seraphimVertices); + glTexCoordPointer(2,GL_FLOAT,0,s->seraphimTextures); + glDrawArrays(GL_QUADS,0,si*4); +} + +#if 0 +#ifdef __VEC__ + +void DrawSmoke_Vector(global_info_t *global, flurry_info_t *flurry, SmokeV *s, float brightness) +{ + const vector float zero = (vector float)(0.0); + int svi = 0; + int sci = 0; + int sti = 0; + int si = 0; + floatToVector width; + vector float sx,sy; + floatToVector u0,v0,u1,v1; + vector float one_over_z; + vector float w; + floatToVector z; + float screenRatio = global->sys_glWidth / 1024.0f; + float hslash2 = global->sys_glHeight * 0.5f; + float wslash2 = global->sys_glWidth * 0.5f; + int i,kk; + floatToVector briteV, fTimeV, expansionV, screenRatioV, hslash2V, wslash2V, streamSizeV; + floatToVector glWidthV; + floatToVector cm; + vector float cmv[4]; + vector float svec[4], ovec[4]; + vector float oldscreenx, oldscreeny; + vector float sm; + vector float frameAnd7; + vector float frameShift3; + vector float one_over_width; + vector float dx, dy; + vector float os; + vector unsigned int vSi = vec_splat_u32(0); + const vector float eighth = (vector float)(0.125); + float glWidth50 = global->sys_glWidth + 50.0f; + float glHeight50 = global->sys_glHeight + 50.0f; + vector float vGLWidth50, vGLHeight50; + unsigned int blitBool; + + vec_dst((int *)(&(s->p[0])), 0x00020200, 2); + + { + vector unsigned char permute1 = vec_lvsl( 0, &glWidth50 ); + vector unsigned char permute2 = vec_lvsl( 0, &glHeight50 ); + permute1 = (vector unsigned char) vec_splat( (vector unsigned int) permute1, 0 ); + permute2 = (vector unsigned char) vec_splat( (vector unsigned int) permute2, 0 ); + vGLWidth50 = vec_lde( 0, &glWidth50 ); + vGLHeight50 = vec_lde( 0, &glHeight50 ); + vGLWidth50 = vec_perm( vGLWidth50, vGLWidth50, permute1 ); + vGLHeight50 = vec_perm( vGLHeight50, vGLHeight50, permute2 ); + } + + width.f[0] = (streamSize+2.5f*flurry->streamExpansion) * screenRatio; + width.v = (vector float) vec_splat((vector unsigned int)width.v, 0); + + briteV.f[0] = brightness; + briteV.v = (vector float) vec_splat((vector unsigned int)briteV.v, 0); + + fTimeV.f[0] = (float) flurry->fTime; + fTimeV.v = (vector float) vec_splat((vector unsigned int)fTimeV.v, 0); + + expansionV.f[0] = flurry->streamExpansion; + expansionV.v = (vector float) vec_splat((vector unsigned int)expansionV.v, 0); + + screenRatioV.f[0] = screenRatio; + screenRatioV.v = (vector float) vec_splat((vector unsigned int)screenRatioV.v, 0); + + hslash2V.f[0] = hslash2; + hslash2V.v = (vector float) vec_splat((vector unsigned int)hslash2V.v, 0); + + wslash2V.f[0] = wslash2; + wslash2V.v = (vector float) vec_splat((vector unsigned int)wslash2V.v, 0); + + streamSizeV.f[0] = streamSize; + streamSizeV.v = (vector float) vec_splat((vector unsigned int)streamSizeV.v, 0); + + glWidthV.f[0] = global->sys_glWidth; + glWidthV.v = (vector float) vec_splat((vector unsigned int)glWidthV.v, 0); + + for (i=0;ip[i+4])), 0x00020200, 2); + + if (vec_all_eq(s->p[i].dead.v, (vector unsigned int)(1))) continue; + + blitBool = 0; /* keep track of particles that actually need to be drawn */ + + thisWidth = vec_sub(fTimeV.v, s->p[i].time.v); + thisWidth = vec_madd(thisWidth, expansionV.v, streamSizeV.v); + thisWidth = vec_madd(thisWidth, screenRatioV.v, zero); + + z.v = s->p[i].position[2].v; + one_over_z = vec_re(z.v); + + sx = vec_madd(s->p[i].position[0].v, glWidthV.v, zero); + sx = vec_madd(sx, one_over_z, wslash2V.v); + sy = vec_madd(s->p[i].position[1].v, glWidthV.v, zero); + sy = vec_madd(sy, one_over_z, hslash2V.v); + + oldz = s->p[i].oldposition[2].v; + + w = vec_max((vector float)(1.0), vec_madd(thisWidth, one_over_z, zero)); + + oldx = s->p[i].oldposition[0].v; + oldy = s->p[i].oldposition[1].v; + one_over_oldz = vec_re(oldz); + oldscreenx = vec_madd(oldx, glWidthV.v, zero); + oldscreenx = vec_madd(oldscreenx, one_over_oldz, wslash2V.v); + oldscreeny = vec_madd(oldy, glWidthV.v, zero); + oldscreeny = vec_madd(oldscreeny, one_over_oldz, hslash2V.v); + dx = vec_sub(sx,oldscreenx); + dy = vec_sub(sy,oldscreeny); + + xabs = vec_abs(dx); + yabs = vec_abs(dy); + mn = vec_min(xabs,yabs); + d = vec_add(xabs,yabs); + d = vec_madd(mn, (vector float)(-0.6875), d); + + ow = vec_max((vector float)(1.0), vec_madd(thisWidth, one_over_oldz, zero)); + one_over_d = vec_re(d); + dnz = vec_cmpgt(d, zero); + sm = vec_madd(w, one_over_d, zero); + sm = vec_and(sm, dnz); + os = vec_madd(ow, one_over_d, zero); + os = vec_and(os, dnz); + + { + intToVector tempMask; + vector bool int mask = vec_cmpeq( s->p[i].dead.v, vec_splat_u32(1) ); /* -1 where true */ + vector bool int gtMask = vec_cmpge( thisWidth, width.v ); /* -1 where true */ + vector bool int glWidth50Test = vec_cmpgt( sx, (vector float)(vGLWidth50) ); /* -1 where true */ + vector bool int glHeight50Test = vec_cmpgt( sy, (vector float)(vGLHeight50) ); /* -1 where true */ + vector bool int test50x = vec_cmplt( sx, (vector float) (-50.0) ); + vector bool int test50y = vec_cmplt( sy, (vector float) (-50.0) ); + vector bool int testz = vec_cmplt( z.v, (vector float) (25.0) ); + vector bool int testoldz = vec_cmplt( oldz, (vector float) (25.0) ); + mask = vec_or( mask, gtMask ); + s->p[i].dead.v = vec_and( mask, vec_splat_u32( 1 ) ); + mask = vec_or( mask, glWidth50Test ); + mask = vec_or( mask, glHeight50Test ); + mask = vec_or( mask, test50x ); + mask = vec_or( mask, test50y ); + mask = vec_or( mask, testz ); + mask = vec_or( mask, testoldz ); + tempMask.v = (vector unsigned int)mask; + + s->p[i].animFrame.v = vec_sub( s->p[i].animFrame.v, vec_nor( mask, mask ) ); + s->p[i].animFrame.v = vec_and( s->p[i].animFrame.v, (vector unsigned int)(63) ); + + frameAnd7 = vec_ctf(vec_and(s->p[i].animFrame.v, (vector unsigned int)(7)),0); + u0.v = vec_madd(frameAnd7, eighth, zero); + + frameShift3 = vec_ctf(vec_sr(s->p[i].animFrame.v, (vector unsigned int)(3)),0); + v0.v = vec_madd(frameAnd7, eighth, zero); + + u1.v = vec_add(u0.v, eighth); + v1.v = vec_add(v0.v, eighth); + + one_over_width = vec_re(width.v); + cm.v = vec_sel( vec_nmsub(thisWidth, one_over_width, (vector float)(1.375)), cm.v, mask ); + cm.v = vec_madd(cm.v, briteV.v, zero); + + vSi = vec_sub( vSi, vec_nor( mask, mask ) ); + { + vector unsigned int blitMask = (vector unsigned int) (1, 2, 4, 8); + vector unsigned int temp = (vector unsigned int)mask; + temp = vec_andc( blitMask, temp ); + temp = vec_add( temp, vec_sld( temp, temp, 8 ) ); + temp = vec_add( temp, vec_sld( temp, temp, 4 ) ); + vec_ste( temp, 0, &blitBool ); + + } + + { + vector float temp1, temp2, temp3, temp4; + vector float result1a, result1b, result2a, result2b, result3a, result3b, result4a, result4b; + + temp1 = vec_mergeh( u0.v, u0.v ); + temp2 = vec_mergel( u0.v, u0.v ); + temp3 = vec_mergeh( v0.v, v1.v ); + temp4 = vec_mergel( v0.v, v1.v ); + + result1a = vec_mergeh( temp1, temp3 ); + result1b = vec_mergel( temp1, temp3 ); + result2a = vec_mergeh( temp2, temp4 ); + result2b = vec_mergel( temp2, temp4 ); + + temp1 = vec_mergeh( u1.v, u1.v ); + temp2 = vec_mergel( u1.v, u1.v ); + temp3 = vec_mergeh( v1.v, v0.v ); + temp4 = vec_mergel( v1.v, v0.v ); + + result3a = vec_mergeh( temp1, temp3 ); + result3b = vec_mergel( temp1, temp3 ); + result4a = vec_mergeh( temp2, temp4 ); + result4b = vec_mergel( temp2, temp4 ); + + if( blitBool & 1 ) + { + vec_st( result1a, 0, &s->seraphimTextures[sti] ); + vec_st( result3a, 16, &s->seraphimTextures[sti]); + sti+= 8; + } + if( blitBool & 2 ) + { + vec_st( result1b, 0, &s->seraphimTextures[sti]); + vec_st( result3b, 16, &s->seraphimTextures[sti]); + sti+= 8; + } + if( blitBool & 4 ) + { + vec_st( result2a, 0, &s->seraphimTextures[sti]); + vec_st( result4a, 16, &s->seraphimTextures[sti]); + sti+= 8; + } + if( blitBool & 8 ) + { + vec_st( result2b, 0, &s->seraphimTextures[sti]); + vec_st( result4b, 16, &s->seraphimTextures[sti]); + sti+= 8; + } + } + } + + cmv[0] = vec_madd(s->p[i].color[0].v, cm.v, zero); + cmv[1] = vec_madd(s->p[i].color[1].v, cm.v, zero); + cmv[2] = vec_madd(s->p[i].color[2].v, cm.v, zero); + cmv[3] = vec_madd(s->p[i].color[3].v, cm.v, zero); + { + vector float vI0, vI1, vI2, vI3; + + vI0 = vec_mergeh ( cmv[0], cmv[2] ); + vI1 = vec_mergeh ( cmv[1], cmv[3] ); + vI2 = vec_mergel ( cmv[0], cmv[2] ); + vI3 = vec_mergel ( cmv[1], cmv[3] ); + + cmv[0] = vec_mergeh ( vI0, vI1 ); + cmv[1] = vec_mergel ( vI0, vI1 ); + cmv[2] = vec_mergeh ( vI2, vI3 ); + cmv[3] = vec_mergel ( vI2, vI3 ); + } + + vec_dst( cmv, 0x0D0100D0, 1 ); + + { + vector float sxd, syd; + vector float sxdm, sxdp, sydm, sydp; + vector float oxd, oyd; + vector float oxdm, oxdp, oydm, oydp; + vector float vI0, vI1, vI2, vI3; + vector float dxs, dys; + vector float dxos, dyos; + vector float dxm, dym; + vector float m; + + m = vec_add((vector float)(1.0), sm); + + dxs = vec_madd(dx, sm, zero); + dys = vec_madd(dy, sm, zero); + dxos = vec_madd(dx, os, zero); + dyos = vec_madd(dy, os, zero); + dxm = vec_madd(dx, m, zero); + dym = vec_madd(dy, m, zero); + + sxd = vec_add(sx, dxm); + sxdm = vec_sub(sxd, dys); + sxdp = vec_add(sxd, dys); + + syd = vec_add(sy, dym); + sydm = vec_sub(syd, dxs); + sydp = vec_add(syd, dxs); + + oxd = vec_sub(oldscreenx, dxm); + oxdm = vec_sub(oxd, dyos); + oxdp = vec_add(oxd, dyos); + + oyd = vec_sub(oldscreeny, dym); + oydm = vec_sub(oyd, dxos); + oydp = vec_add(oyd, dxos); + + vI0 = vec_mergeh ( sxdm, sxdp ); + vI1 = vec_mergeh ( sydp, sydm ); + vI2 = vec_mergel ( sxdm, sxdp ); + vI3 = vec_mergel ( sydp, sydm ); + + svec[0] = vec_mergeh ( vI0, vI1 ); + svec[1] = vec_mergel ( vI0, vI1 ); + svec[2] = vec_mergeh ( vI2, vI3 ); + svec[3] = vec_mergel ( vI2, vI3 ); + + vI0 = vec_mergeh ( oxdp, oxdm ); + vI1 = vec_mergeh ( oydm, oydp ); + vI2 = vec_mergel ( oxdp, oxdm ); + vI3 = vec_mergel ( oydm, oydp ); + + ovec[0] = vec_mergeh ( vI0, vI1 ); + ovec[1] = vec_mergel ( vI0, vI1 ); + ovec[2] = vec_mergeh ( vI2, vI3 ); + ovec[3] = vec_mergel ( vI2, vI3 ); + } + + { + int offset0 = (sci + 0) * sizeof( vector float ); + int offset1 = (sci + 1) * sizeof( vector float ); + int offset2 = (sci + 2) * sizeof( vector float ); + int offset3 = (sci + 3) * sizeof( vector float ); + int offset4 = (svi + 0) * sizeof( vector float ); + int offset5 = (svi + 1) * sizeof( vector float ); + vector float *colors = (vector float *)s->seraphimColors; + vector float *vertices = (vector float *)s->seraphimVertices; + for (kk=0; kk<4; kk++) { + if (blitBool>>kk & 1) { + vector float vcmv = cmv[kk]; + vector float vsvec = svec[kk]; + vector float vovec = ovec[kk]; + + vec_st( vcmv, offset0, colors ); + vec_st( vcmv, offset1, colors ); + vec_st( vcmv, offset2, colors ); + vec_st( vcmv, offset3, colors ); + vec_st( vsvec, offset4, vertices ); + vec_st( vovec, offset5, vertices ); + colors += 4; + vertices += 2; + sci += 4; + svi += 2; + } + } + } + } + vSi = vec_add( vSi, vec_sld( vSi, vSi, 8 ) ); + vSi = vec_add( vSi, vec_sld( vSi, vSi, 4 ) ); + vec_ste( (vector signed int) vSi, 0, &si ); + + glColorPointer(4,GL_FLOAT,0,s->seraphimColors); + glVertexPointer(2,GL_FLOAT,0,s->seraphimVertices); + glTexCoordPointer(2,GL_FLOAT,0,s->seraphimTextures); + glDrawArrays(GL_QUADS,0,si*4); +} + +#endif +#endif /* 0 */ diff --git a/hacks/glx/flurry-spark.c b/hacks/glx/flurry-spark.c new file mode 100644 index 00000000..5b58b569 --- /dev/null +++ b/hacks/glx/flurry-spark.c @@ -0,0 +1,285 @@ +/* + +Copyright (c) 2002, Calum Robinson +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +* Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + +* Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + +* Neither the name of the author nor the names of its contributors may be used + to endorse or promote products derived from this software without specific + prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +*/ + +/* Spark.cpp: implementation of the Spark class. */ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include "flurry.h" + +void InitSpark(Spark *s) +{ + int i; + for (i=0;i<3;i++) + { + s->position[i] = RandFlt(-100.0, 100.0); + } +} + +void DrawSpark(global_info_t *global, flurry_info_t *flurry, Spark *s) +{ + const float black[4] = {0.0f,0.0f,0.0f,1.0f}; + float width,sx,sy; + float a; + float c = 0.0625f; + float screenx; + float screeny; + float w,z, scale; + int k; + width = 60000.0f * global->sys_glWidth / 1024.0f; + + z = s->position[2]; + sx = s->position[0] * global->sys_glWidth / z + global->sys_glWidth * 0.5f; + sy = s->position[1] * global->sys_glWidth / z + global->sys_glHeight * 0.5f; + w = width*4.0f / z; + + screenx = sx; + screeny = sy; + + glPushMatrix(); + glTranslatef(screenx,screeny,0.0f); + scale = w/50.0f; + glScalef(scale,scale,0.0f); + for (k=0;k<12;k++) + { + a = ((float) (random() % 3600)) / 10.0f; + glRotatef(a,0.0f,0.0f,1.0f); + glBegin(GL_QUAD_STRIP); + glColor4fv(black); + glVertex2f(-3.0f,0.0f); + a = 2.0f + (float) (random() & 255) * c; + glVertex2f(-3.0f,a); + glColor4fv(s->color); + glVertex2f(0.0f,0.0f); + glColor4fv(black); + glVertex2f(0.0f,a); + glVertex2f(3.0f,0.0f); + glVertex2f(3.0f,a); + glEnd(); + } + glPopMatrix(); +} + +#define BIGMYSTERY 1800.0 +#define MAXANGLES 16384 + +void UpdateSparkColour(global_info_t *global, flurry_info_t *flurry, Spark *s) +{ + const float rotationsPerSecond = (float) (2.0*PI*fieldSpeed/MAXANGLES); + double thisPointInRadians; + double thisAngle = flurry->fTime*rotationsPerSecond; + float cf; + float cycleTime = 20.0f; + float colorRot; + float redPhaseShift; + float greenPhaseShift; + float bluePhaseShift; + float baseRed; + float baseGreen; + float baseBlue; + float colorTime; + + if (flurry->currentColorMode == rainbowColorMode) + { + cycleTime = 1.5f; + } + else if (flurry->currentColorMode == tiedyeColorMode) + { + cycleTime = 4.5f; + } + else if (flurry->currentColorMode == cyclicColorMode) + { + cycleTime = 20.0f; + } + else if (flurry->currentColorMode == slowCyclicColorMode) + { + cycleTime = 120.0f; + } + colorRot = (float) (2.0*PI/cycleTime); + redPhaseShift = 0.0f; /* cycleTime * 0.0f / 3.0f */ + greenPhaseShift = cycleTime / 3.0f; + bluePhaseShift = cycleTime * 2.0f / 3.0f ; + colorTime = flurry->fTime; + if (flurry->currentColorMode == whiteColorMode) + { + baseRed = 0.1875f; + baseGreen = 0.1875f; + baseBlue = 0.1875f; + } + else if (flurry->currentColorMode == multiColorMode) + { + baseRed = 0.0625f; + baseGreen = 0.0625f; + baseBlue = 0.0625f; + } + else if (flurry->currentColorMode == darkColorMode) + { + baseRed = 0.0f; + baseGreen = 0.0f; + baseBlue = 0.0f; + } + else + { + if (flurry->currentColorMode < slowCyclicColorMode) + { + colorTime = (flurry->currentColorMode / 6.0f) * cycleTime; + } + else + { + colorTime = flurry->fTime + flurry->flurryRandomSeed; + } + baseRed = 0.109375f * ((float) cos((colorTime+redPhaseShift)*colorRot)+1.0f); + baseGreen = 0.109375f * ((float) cos((colorTime+greenPhaseShift)*colorRot)+1.0f); + baseBlue = 0.109375f * ((float) cos((colorTime+bluePhaseShift)*colorRot)+1.0f); + } + + cf = ((float) (cos(7.0*((flurry->fTime)*rotationsPerSecond))+cos(3.0*((flurry->fTime)*rotationsPerSecond))+cos(13.0*((flurry->fTime)*rotationsPerSecond)))); + cf /= 6.0f; + cf += 2.0f; + thisPointInRadians = 2.0 * PI * (double) s->mystery / (double) BIGMYSTERY; + + s->color[0] = baseRed + 0.0625f * (0.5f + (float) cos((15.0 * (thisPointInRadians + 3.0*thisAngle))) + (float) sin((7.0 * (thisPointInRadians + thisAngle)))); + s->color[1] = baseGreen + 0.0625f * (0.5f + (float) sin(((thisPointInRadians) + thisAngle))); + s->color[2] = baseBlue + 0.0625f * (0.5f + (float) cos((37.0 * (thisPointInRadians + thisAngle)))); +} + +void UpdateSpark(global_info_t *global, flurry_info_t *flurry, Spark *s) +{ + const float rotationsPerSecond = (float) (2.0*PI*fieldSpeed/MAXANGLES); + double thisPointInRadians; + double thisAngle = flurry->fTime*rotationsPerSecond; + float cf; + int i; + double tmpX1,tmpY1,tmpZ1; + double tmpX2,tmpY2,tmpZ2; + double tmpX3,tmpY3,tmpZ3; + double tmpX4,tmpY4,tmpZ4; + double rotation; + double cr; + double sr; + float cycleTime = 20.0f; + float colorRot; + float redPhaseShift; + float greenPhaseShift; + float bluePhaseShift; + float baseRed; + float baseGreen; + float baseBlue; + float colorTime; + + float old[3]; + + if (flurry->currentColorMode == rainbowColorMode) { + cycleTime = 1.5f; + } else if (flurry->currentColorMode == tiedyeColorMode) { + cycleTime = 4.5f; + } else if (flurry->currentColorMode == cyclicColorMode) { + cycleTime = 20.0f; + } else if (flurry->currentColorMode == slowCyclicColorMode) { + cycleTime = 120.0f; + } + colorRot = (float) (2.0*PI/cycleTime); + redPhaseShift = 0.0f; /* cycleTime * 0.0f / 3.0f */ + greenPhaseShift = cycleTime / 3.0f; + bluePhaseShift = cycleTime * 2.0f / 3.0f ; + colorTime = flurry->fTime; + if (flurry->currentColorMode == whiteColorMode) { + baseRed = 0.1875f; + baseGreen = 0.1875f; + baseBlue = 0.1875f; + } else if (flurry->currentColorMode == multiColorMode) { + baseRed = 0.0625f; + baseGreen = 0.0625f; + baseBlue = 0.0625f; + } else if (flurry->currentColorMode == darkColorMode) { + baseRed = 0.0f; + baseGreen = 0.0f; + baseBlue = 0.0f; + } else { + if(flurry->currentColorMode < slowCyclicColorMode) { + colorTime = (flurry->currentColorMode / 6.0f) * cycleTime; + } else { + colorTime = flurry->fTime + flurry->flurryRandomSeed; + } + baseRed = 0.109375f * ((float) cos((colorTime+redPhaseShift)*colorRot)+1.0f); + baseGreen = 0.109375f * ((float) cos((colorTime+greenPhaseShift)*colorRot)+1.0f); + baseBlue = 0.109375f * ((float) cos((colorTime+bluePhaseShift)*colorRot)+1.0f); + } + + for (i=0;i<3;i++) { + old[i] = s->position[i]; + } + + cf = ((float) (cos(7.0*((flurry->fTime)*rotationsPerSecond))+cos(3.0*((flurry->fTime)*rotationsPerSecond))+cos(13.0*((flurry->fTime)*rotationsPerSecond)))); + cf /= 6.0f; + cf += 2.0f; + thisPointInRadians = 2.0 * PI * (double) s->mystery / (double) BIGMYSTERY; + + s->color[0] = baseRed + 0.0625f * (0.5f + (float) cos((15.0 * (thisPointInRadians + 3.0*thisAngle))) + (float) sin((7.0 * (thisPointInRadians + thisAngle)))); + s->color[1] = baseGreen + 0.0625f * (0.5f + (float) sin(((thisPointInRadians) + thisAngle))); + s->color[2] = baseBlue + 0.0625f * (0.5f + (float) cos((37.0 * (thisPointInRadians + thisAngle)))); + s->position[0] = fieldRange * cf * (float) cos(11.0 * (thisPointInRadians + (3.0*thisAngle))); + s->position[1] = fieldRange * cf * (float) sin(12.0 * (thisPointInRadians + (4.0*thisAngle))); + s->position[2] = fieldRange * (float) cos((23.0 * (thisPointInRadians + (12.0*thisAngle)))); + + rotation = thisAngle*0.501 + 5.01 * (double) s->mystery / (double) BIGMYSTERY; + cr = cos(rotation); + sr = sin(rotation); + tmpX1 = s->position[0] * cr - s->position[1] * sr; + tmpY1 = s->position[1] * cr + s->position[0] * sr; + tmpZ1 = s->position[2]; + + tmpX2 = tmpX1 * cr - tmpZ1 * sr; + tmpY2 = tmpY1; + tmpZ2 = tmpZ1 * cr + tmpX1 * sr; + + tmpX3 = tmpX2; + tmpY3 = tmpY2 * cr - tmpZ2 * sr; + tmpZ3 = tmpZ2 * cr + tmpY2 * sr + seraphDistance; + + rotation = thisAngle*2.501 + 85.01 * (double) s->mystery / (double) BIGMYSTERY; + cr = cos(rotation); + sr = sin(rotation); + tmpX4 = tmpX3 * cr - tmpY3 * sr; + tmpY4 = tmpY3 * cr + tmpX3 * sr; + tmpZ4 = tmpZ3; + + s->position[0] = (float) tmpX4 + RandBell(5.0f*fieldCoherence); + s->position[1] = (float) tmpY4 + RandBell(5.0f*fieldCoherence); + s->position[2] = (float) tmpZ4 + RandBell(5.0f*fieldCoherence); + + for (i=0;i<3;i++) { + s->delta[i] = (s->position[i] - old[i])/flurry->fDeltaTime; + } +} diff --git a/hacks/glx/flurry-star.c b/hacks/glx/flurry-star.c new file mode 100644 index 00000000..8d9cc41b --- /dev/null +++ b/hacks/glx/flurry-star.c @@ -0,0 +1,106 @@ +/* + +Copyright (c) 2002, Calum Robinson +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +* Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + +* Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + +* Neither the name of the author nor the names of its contributors may be used + to endorse or promote products derived from this software without specific + prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +*/ + +/* Star.c: implementation of the Star class. */ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include "flurry.h" + +/* Construction/Destruction */ + +void InitStar(Star *s) +{ + int i; + for (i=0;i<3;i++) { + s->position[i] = RandFlt(-10000.0, 10000.0); + } + s->rotSpeed = RandFlt(0.4, 0.9); + s->mystery = RandFlt(0.0, 10.0); +} + +#define BIGMYSTERY 1800.0 +#define MAXANGLES 16384 + +void UpdateStar(global_info_t *global, flurry_info_t *flurry, Star *s) +{ + float rotationsPerSecond = (float) (2.0*PI*12.0/MAXANGLES) * s->rotSpeed /* speed control */; + double thisPointInRadians; + double thisAngle = flurry->fTime*rotationsPerSecond; + float cf; + double tmpX1,tmpY1,tmpZ1; + double tmpX2,tmpY2,tmpZ2; + double tmpX3,tmpY3,tmpZ3; + double tmpX4,tmpY4,tmpZ4; + double rotation; + double cr; + double sr; + + s->ate = 0; + + cf = ((float) (cos(7.0*((flurry->fTime)*rotationsPerSecond))+cos(3.0*((flurry->fTime)*rotationsPerSecond))+cos(13.0*((flurry->fTime)*rotationsPerSecond)))); + cf /= 6.0f; + cf += 0.75f; + thisPointInRadians = 2.0 * PI * (double) s->mystery / (double) BIGMYSTERY; + + s->position[0] = 250.0f * cf * (float) cos(11.0 * (thisPointInRadians + (3.0*thisAngle))); + s->position[1] = 250.0f * cf * (float) sin(12.0 * (thisPointInRadians + (4.0*thisAngle))); + s->position[2] = 250.0f * (float) cos((23.0 * (thisPointInRadians + (12.0*thisAngle)))); + + rotation = thisAngle*0.501 + 5.01 * (double) s->mystery / (double) BIGMYSTERY; + cr = cos(rotation); + sr = sin(rotation); + tmpX1 = s->position[0] * cr - s->position[1] * sr; + tmpY1 = s->position[1] * cr + s->position[0] * sr; + tmpZ1 = s->position[2]; + + tmpX2 = tmpX1 * cr - tmpZ1 * sr; + tmpY2 = tmpY1; + tmpZ2 = tmpZ1 * cr + tmpX1 * sr; + + tmpX3 = tmpX2; + tmpY3 = tmpY2 * cr - tmpZ2 * sr; + tmpZ3 = tmpZ2 * cr + tmpY2 * sr + seraphDistance; + + rotation = thisAngle*2.501 + 85.01 * (double) s->mystery / (double) BIGMYSTERY; + cr = cos(rotation); + sr = sin(rotation); + tmpX4 = tmpX3 * cr - tmpY3 * sr; + tmpY4 = tmpY3 * cr + tmpX3 * sr; + tmpZ4 = tmpZ3; + + s->position[0] = (float) tmpX4; + s->position[1] = (float) tmpY4; + s->position[2] = (float) tmpZ4; +} diff --git a/hacks/glx/flurry-texture.c b/hacks/glx/flurry-texture.c new file mode 100644 index 00000000..c787f59a --- /dev/null +++ b/hacks/glx/flurry-texture.c @@ -0,0 +1,224 @@ +/* + +Copyright (c) 2002, Calum Robinson +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +* Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + +* Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + +* Neither the name of the author nor the names of its contributors may be used + to endorse or promote products derived from this software without specific + prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +*/ + +/* + * Texture.c + * AppleFlurry + * + * Created by calumr on Sat Jul 07 2001. + * Copyright (c) 2001 __CompanyName__. All rights reserved. + * + */ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include "flurry.h" + +#include +#include + +#include +#include + +static GLubyte smallTextureArray[32][32]; +static GLubyte bigTextureArray[256][256][2]; +GLuint theTexture = 0; + +/* simple smoothing routine */ +static void SmoothTexture(void) +{ + GLubyte filter[32][32]; + int i,j; + float t; + for (i=1;i<31;i++) + { + for (j=1;j<31;j++) + { + t = (float) smallTextureArray[i][j]*4; + t += (float) smallTextureArray[i-1][j]; + t += (float) smallTextureArray[i+1][j]; + t += (float) smallTextureArray[i][j-1]; + t += (float) smallTextureArray[i][j+1]; + t /= 8.0f; + filter[i][j] = (GLubyte) t; + } + } + for (i=1;i<31;i++) + { + for (j=1;j<31;j++) + { + smallTextureArray[i][j] = filter[i][j]; + } + } +} + +/* add some randomness to texture data */ +static void SpeckleTexture(void) +{ + int i,j; + int speck; + float t; + for (i=2;i<30;i++) + { + for (j=2;j<30;j++) + { + speck = 1; + while (speck <= 32 && random() % 2) + { + t = (float) MIN_(255,smallTextureArray[i][j]+speck); + smallTextureArray[i][j] = (GLubyte) t; + speck+=speck; + } + speck = 1; + while (speck <= 32 && random() % 2) + { + t = (float) MAX_(0,smallTextureArray[i][j]-speck); + smallTextureArray[i][j] = (GLubyte) t; + speck+=speck; + } + } + } +} + +static void MakeSmallTexture(void) +{ + static int firstTime = 1; + int i,j; + float r,t; + if (firstTime) + { + firstTime = 0; + for (i=0;i<32;i++) + { + for (j=0;j<32;j++) + { + r = (float) sqrt((i-15.5)*(i-15.5)+(j-15.5)*(j-15.5)); + if (r > 15.0f) + { + smallTextureArray[i][j] = 0; + } + else + { + t = 255.0f * (float) cos(r*M_PI/31.0); + smallTextureArray[i][j] = (GLubyte) t; + } + } + } + } + else + { + for (i=0;i<32;i++) + { + for (j=0;j<32;j++) + { + r = (float) sqrt((i-15.5)*(i-15.5)+(j-15.5)*(j-15.5)); + if (r > 15.0f) + { + t = 0.0f; + } + else + { + t = 255.0f * (float) cos(r*M_PI/31.0); + } + smallTextureArray[i][j] = (GLubyte) MIN_(255,(t+smallTextureArray[i][j]+smallTextureArray[i][j])/3); + } + } + } + SpeckleTexture(); + SmoothTexture(); + SmoothTexture(); +} + +static void CopySmallTextureToBigTexture(int k, int l) +{ + int i,j; + for (i=0;i<32;i++) + { + for (j=0;j<32;j++) + { + bigTextureArray[i+k][j+l][0] = smallTextureArray[i][j]; + bigTextureArray[i+k][j+l][1] = smallTextureArray[i][j]; + } + } +} + +static void AverageLastAndFirstTextures(void) +{ + int i,j; + int t; + for (i=0;i<32;i++) + { + for (j=0;j<32;j++) + { + t = (smallTextureArray[i][j] + bigTextureArray[i][j][0]) / 2; + smallTextureArray[i][j] = (GLubyte) MIN_(255,t); + } + } +} + +void MakeTexture() +{ + int i,j; + for (i=0;i<8;i++) + { + for (j=0;j<8;j++) + { + if (i==7 && j==7) + { + AverageLastAndFirstTextures(); + } + else + { + MakeSmallTexture(); + } + CopySmallTextureToBigTexture(i*32,j*32); + } + } + + glPixelStorei(GL_UNPACK_ALIGNMENT,1); + + glGenTextures(1, &theTexture); + glBindTexture(GL_TEXTURE_2D, theTexture); + + /* Set the tiling mode (this is generally always GL_REPEAT). */ + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); + + /* Set the filtering. */ + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_NEAREST); + + gluBuild2DMipmaps(GL_TEXTURE_2D, 2, 256, 256, GL_LUMINANCE_ALPHA, GL_UNSIGNED_BYTE, bigTextureArray); + glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); +} diff --git a/hacks/glx/flurry.c b/hacks/glx/flurry.c new file mode 100644 index 00000000..346c1151 --- /dev/null +++ b/hacks/glx/flurry.c @@ -0,0 +1,567 @@ +/* -*- Mode: C; tab-width: 4 c-basic-offset: 4 indent-tabs-mode: t -*- */ +/* + * vim: ts=8 sw=4 noet + */ + +/* + +Copyright (c) 2002, Calum Robinson +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +* Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + +* Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + +* Neither the name of the author nor the names of its contributors may be used + to endorse or promote products derived from this software without specific + prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +*/ + +/* flurry */ + +#if 0 +static const char sccsid[] = "@(#)flurry.c 4.07 97/11/24 xlockmore"; +#endif + +#define DEF_PRESET "random" +#define DEF_BRIGHTNESS "8" + +# define DEFAULTS "*delay: 10000 \n" \ + "*showFPS: False \n" + +# define refresh_flurry 0 +# define flurry_handle_event 0 +# include "xlockmore.h" /* from the xscreensaver distribution */ + +#ifdef USE_GL + +static char *preset_str; + +static XrmOptionDescRec opts[] = { + { "-preset", ".preset", XrmoptionSepArg, 0 } +}; + +static argtype vars[] = { + {&preset_str, "preset", "Preset", DEF_PRESET, t_String}, +}; + +#define countof(x) (sizeof((x))/sizeof((*x))) + +ENTRYPOINT ModeSpecOpt flurry_opts = {countof(opts), opts, countof(vars), vars, NULL}; + +#ifdef USE_MODULES +ModStruct flurry_description = { + "flurry", + "init_flurry", + "draw_flurry", + "release_flurry", + "draw_flurry", + "init_flurry", + NULL, + &flurry_opts, + 1000, 1, 2, 1, 4, 1.0, + "", + "Flurry", + 0, + NULL +}; + +#endif + +#include "flurry.h" + +global_info_t *flurry_info = NULL; + +static double gTimeCounter = 0.0; + +static +double currentTime(void) { + struct timeval tv; +# ifdef GETTIMEOFDAY_TWO_ARGS + struct timezone tzp; + gettimeofday(&tv, &tzp); +# else + gettimeofday(&tv); +# endif + + return (double)tv.tv_sec + (double)tv.tv_usec / 1000000.0; +} + +void OTSetup (void) { + if (gTimeCounter == 0.0) { + gTimeCounter = currentTime(); + } +} + +double TimeInSecondsSinceStart (void) { + return currentTime() - gTimeCounter; +} + +#if 0 +#ifdef __ppc__ +static int IsAltiVecAvailable(void) +{ + return 0; +} +#endif +#endif + + +static +void delete_flurry_info(flurry_info_t *flurry) +{ + int i; + + free(flurry->s); + free(flurry->star); + for (i=0;ispark[i]); + } + /* free(flurry); */ +} + +static +flurry_info_t *new_flurry_info(global_info_t *global, int streams, ColorModes colour, float thickness, float speed, double bf) +{ + int i,k; + flurry_info_t *flurry = (flurry_info_t *)malloc(sizeof(flurry_info_t)); + + if (!flurry) return NULL; + + flurry->flurryRandomSeed = RandFlt(0.0, 300.0); + + flurry->fOldTime = 0; + flurry->fTime = TimeInSecondsSinceStart() + flurry->flurryRandomSeed; + flurry->fDeltaTime = flurry->fTime - flurry->fOldTime; + + flurry->numStreams = streams; + flurry->streamExpansion = thickness; + flurry->currentColorMode = colour; + flurry->briteFactor = bf; + + flurry->s = malloc(sizeof(SmokeV)); + InitSmoke(flurry->s); + + flurry->star = malloc(sizeof(Star)); + InitStar(flurry->star); + flurry->star->rotSpeed = speed; + + for (i = 0;i < MAX_SPARKS; i++) + { + flurry->spark[i] = malloc(sizeof(Spark)); + InitSpark(flurry->spark[i]); + flurry->spark[i]->mystery = 1800 * (i + 1) / 13; /* 100 * (i + 1) / (flurry->numStreams + 1); */ + UpdateSpark(global, flurry, flurry->spark[i]); + } + + for (i=0;is->p[i].dead.i[k] = 1; + } + } + + flurry->next = NULL; + + return flurry; +} + +static +void GLSetupRC(global_info_t *global) +{ + /* setup the defaults for OpenGL */ + glDisable(GL_DEPTH_TEST); + glAlphaFunc(GL_GREATER,0.0f); + glEnable(GL_ALPHA_TEST); + glShadeModel(GL_FLAT); + glDisable(GL_LIGHTING); + glDisable(GL_CULL_FACE); + glEnable(GL_BLEND); + + glViewport(0,0,(int) global->sys_glWidth,(int) global->sys_glHeight); + glMatrixMode(GL_PROJECTION); + glLoadIdentity(); + glOrtho(0,global->sys_glWidth,0,global->sys_glHeight,-1,1); + glMatrixMode(GL_MODELVIEW); + glLoadIdentity(); + + glClear(GL_COLOR_BUFFER_BIT); + + glEnableClientState(GL_COLOR_ARRAY); + glEnableClientState(GL_VERTEX_ARRAY); + glEnableClientState(GL_TEXTURE_COORD_ARRAY); + +#if 0 +#ifdef __ppc__ + global->optMode = OPT_MODE_SCALAR_FRSQRTE; + +#ifdef __VEC__ + if (IsAltiVecAvailable()) global->optMode = OPT_MODE_VECTOR_UNROLLED; +#endif + +#else + global->optMode = OPT_MODE_SCALAR_BASE; +#endif +#endif /* 0 */ +} + +static +void GLRenderScene(global_info_t *global, flurry_info_t *flurry, double b) +{ + int i; + + flurry->dframe++; + + flurry->fOldTime = flurry->fTime; + flurry->fTime = TimeInSecondsSinceStart() + flurry->flurryRandomSeed; + flurry->fDeltaTime = flurry->fTime - flurry->fOldTime; + + flurry->drag = (float) pow(0.9965,flurry->fDeltaTime*85.0); + + UpdateStar(global, flurry, flurry->star); + +#ifdef DRAW_SPARKS + glShadeModel(GL_SMOOTH); + glEnable(GL_BLEND); + glBlendFunc(GL_SRC_ALPHA,GL_ONE); +#endif + + for (i=0;inumStreams;i++) { + flurry->spark[i]->color[0]=1.0; + flurry->spark[i]->color[1]=1.0; + flurry->spark[i]->color[2]=1.0; + flurry->spark[i]->color[2]=1.0; + UpdateSpark(global, flurry, flurry->spark[i]); +#ifdef DRAW_SPARKS + DrawSpark(global, flurry, flurry->spark[i]); +#endif + } + + switch(global->optMode) { + case OPT_MODE_SCALAR_BASE: + UpdateSmoke_ScalarBase(global, flurry, flurry->s); + break; +#if 0 +#ifdef __ppc__ + case OPT_MODE_SCALAR_FRSQRTE: + UpdateSmoke_ScalarFrsqrte(global, flurry, flurry->s); + break; +#endif +#ifdef __VEC__ + case OPT_MODE_VECTOR_SIMPLE: + UpdateSmoke_VectorBase(global, flurry, flurry->s); + break; + case OPT_MODE_VECTOR_UNROLLED: + UpdateSmoke_VectorUnrolled(global, flurry, flurry->s); + break; +#endif +#endif /* 0 */ + + default: + break; + } + + /* glDisable(GL_BLEND); */ + glEnable(GL_BLEND); + glBlendFunc(GL_SRC_ALPHA,GL_ONE); + glEnable(GL_TEXTURE_2D); + + switch(global->optMode) { + case OPT_MODE_SCALAR_BASE: +#if 0 +#ifdef __ppc__ + case OPT_MODE_SCALAR_FRSQRTE: +#endif +#endif /* 0 */ + DrawSmoke_Scalar(global, flurry, flurry->s, b); + break; +#if 0 +#ifdef __VEC__ + case OPT_MODE_VECTOR_SIMPLE: + case OPT_MODE_VECTOR_UNROLLED: + DrawSmoke_Vector(global, flurry, flurry->s, b); + break; +#endif +#endif /* 0 */ + default: + break; + } + + glDisable(GL_TEXTURE_2D); +} + +static +void GLResize(global_info_t *global, float w, float h) +{ + global->sys_glWidth = w; + global->sys_glHeight = h; +} + +/* new window size or exposure */ +ENTRYPOINT void reshape_flurry(ModeInfo *mi, int width, int height) +{ + global_info_t *global = flurry_info + MI_SCREEN(mi); + + glXMakeCurrent(MI_DISPLAY(mi), global->window, *(global->glx_context)); + + glViewport(0.0, 0.0, width, height); + glMatrixMode(GL_PROJECTION); + glLoadIdentity(); + glOrtho(0, width, 0, height,-1,1); + glMatrixMode(GL_MODELVIEW); + glClear(GL_COLOR_BUFFER_BIT); + glFlush(); + GLResize(global, (float)width, (float)height); +} + +ENTRYPOINT void +init_flurry(ModeInfo * mi) +{ + int screen = MI_SCREEN(mi); + int i; + global_info_t *global; + enum { + PRESET_INSANE = -1, + PRESET_WATER = 0, + PRESET_FIRE, + PRESET_PSYCHEDELIC, + PRESET_RGB, + PRESET_BINARY, + PRESET_CLASSIC, + PRESET_MAX + } preset_num; + + if (flurry_info == NULL) { + OTSetup(); + if ((flurry_info = (global_info_t *) calloc(MI_NUM_SCREENS(mi), + sizeof (global_info_t))) == NULL) + return; + } + + global = &flurry_info[screen]; + + global->window = MI_WINDOW(mi); + + global->flurry = NULL; + + if (!preset_str || !*preset_str) preset_str = DEF_PRESET; + if (!strcmp(preset_str, "random")) { + preset_num = random() % PRESET_MAX; + } else if (!strcmp(preset_str, "water")) { + preset_num = PRESET_WATER; + } else if (!strcmp(preset_str, "fire")) { + preset_num = PRESET_FIRE; + } else if (!strcmp(preset_str, "psychedelic")) { + preset_num = PRESET_PSYCHEDELIC; + } else if (!strcmp(preset_str, "rgb")) { + preset_num = PRESET_RGB; + } else if (!strcmp(preset_str, "binary")) { + preset_num = PRESET_BINARY; + } else if (!strcmp(preset_str, "classic")) { + preset_num = PRESET_CLASSIC; + } else if (!strcmp(preset_str, "insane")) { + preset_num = PRESET_INSANE; + } else { + fprintf(stderr, "%s: unknown preset %s\n", progname, preset_str); + exit(1); + } + + switch (preset_num) { + case PRESET_WATER: { + for (i = 0; i < 9; i++) { + flurry_info_t *flurry; + + flurry = new_flurry_info(global, 1, blueColorMode, 100.0, 2.0, 2.0); + flurry->next = global->flurry; + global->flurry = flurry; + } + break; + } + case PRESET_FIRE: { + flurry_info_t *flurry; + + flurry = new_flurry_info(global, 12, slowCyclicColorMode, 10000.0, 0.2, 1.0); + flurry->next = global->flurry; + global->flurry = flurry; + break; + } + case PRESET_PSYCHEDELIC: { + flurry_info_t *flurry; + + flurry = new_flurry_info(global, 10, rainbowColorMode, 200.0, 2.0, 1.0); + flurry->next = global->flurry; + global->flurry = flurry; + break; + } + case PRESET_RGB: { + flurry_info_t *flurry; + + flurry = new_flurry_info(global, 3, redColorMode, 100.0, 0.8, 1.0); + flurry->next = global->flurry; + global->flurry = flurry; + + flurry = new_flurry_info(global, 3, greenColorMode, 100.0, 0.8, 1.0); + flurry->next = global->flurry; + global->flurry = flurry; + + flurry = new_flurry_info(global, 3, blueColorMode, 100.0, 0.8, 1.0); + flurry->next = global->flurry; + global->flurry = flurry; + break; + } + case PRESET_BINARY: { + flurry_info_t *flurry; + + flurry = new_flurry_info(global, 16, tiedyeColorMode, 1000.0, 0.5, 1.0); + flurry->next = global->flurry; + global->flurry = flurry; + + flurry = new_flurry_info(global, 16, tiedyeColorMode, 1000.0, 1.5, 1.0); + flurry->next = global->flurry; + global->flurry = flurry; + break; + } + case PRESET_CLASSIC: { + flurry_info_t *flurry; + + flurry = new_flurry_info(global, 5, tiedyeColorMode, 10000.0, 1.0, 1.0); + flurry->next = global->flurry; + global->flurry = flurry; + break; + } + case PRESET_INSANE: { + flurry_info_t *flurry; + + flurry = new_flurry_info(global, 64, tiedyeColorMode, 1000.0, 0.5, 0.5); + flurry->next = global->flurry; + global->flurry = flurry; + + break; + } + default: { + fprintf(stderr, "%s: unknown preset %s\n", progname, preset_str); + exit(1); + } + } + + if ((global->glx_context = init_GL(mi)) != NULL) { + reshape_flurry(mi, MI_WIDTH(mi), MI_HEIGHT(mi)); + GLSetupRC(global); + } else { + MI_CLEARWINDOW(mi); + } +} + +ENTRYPOINT void +draw_flurry(ModeInfo * mi) +{ + static int first = 1; + static double oldFrameTime = -1; + double newFrameTime; + double deltaFrameTime = 0; + double brite; + GLfloat alpha; + + global_info_t *global = flurry_info + MI_SCREEN(mi); + flurry_info_t *flurry; + Display *display = MI_DISPLAY(mi); + Window window = MI_WINDOW(mi); + + newFrameTime = currentTime(); + if (oldFrameTime == -1) { + /* special case the first frame -- clear to black */ + alpha = 1.0; + } else { + /* + * this clamps the speed at below 60fps and, here + * at least, produces a reasonably accurate 50fps. + * (probably part CPU speed and part scheduler). + * + * Flurry is designed to run at this speed; much higher + * than that and the blending causes the display to + * saturate, which looks really ugly. + */ + if (newFrameTime - oldFrameTime < 1/60.0) { + usleep(MAX_(1,(int)(20000 * (newFrameTime - oldFrameTime)))); + return; + + } + deltaFrameTime = newFrameTime - oldFrameTime; + alpha = 5.0 * deltaFrameTime; + } + oldFrameTime = newFrameTime; + + if (alpha > 0.2) alpha = 0.2; + + if (!global->glx_context) + return; + + if (first) { + MakeTexture(); + first = 0; + } + glDrawBuffer(GL_BACK); + glXMakeCurrent(display, window, *(global->glx_context)); + + glEnable(GL_BLEND); + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + + glColor4f(0.0, 0.0, 0.0, alpha); + glRectd(0, 0, global->sys_glWidth, global->sys_glHeight); + + brite = pow(deltaFrameTime,0.75) * 10; + for (flurry = global->flurry; flurry; flurry=flurry->next) { + GLRenderScene(global, flurry, brite * flurry->briteFactor); + } + + if (mi->fps_p) do_fps (mi); + + glFinish(); + glXSwapBuffers(display, window); +} + +ENTRYPOINT void +release_flurry(ModeInfo * mi) +{ + if (flurry_info != NULL) { + int screen; + + for (screen = 0; screen < MI_NUM_SCREENS(mi); screen++) { + global_info_t *global = &flurry_info[screen]; + flurry_info_t *flurry; + + if (global->glx_context) { + glXMakeCurrent(MI_DISPLAY(mi), global->window, *(global->glx_context)); + } + + for (flurry = global->flurry; flurry; flurry=flurry->next) { + delete_flurry_info(flurry); + } + } + (void) free((void *) flurry_info); + flurry_info = NULL; + } + FreeAllGL(mi); +} + +XSCREENSAVER_MODULE ("Flurry", flurry) + +#endif diff --git a/hacks/glx/flurry.h b/hacks/glx/flurry.h new file mode 100644 index 00000000..a304ac6d --- /dev/null +++ b/hacks/glx/flurry.h @@ -0,0 +1,296 @@ +/* + +Copyright (c) 2002, Calum Robinson +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +* Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + +* Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + +* Neither the name of the author nor the names of its contributors may be used + to endorse or promote products derived from this software without specific + prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +*/ + +/* -*- Mode: C; tab-width: 4 c-basic-offset: 4 indent-tabs-mode: t -*- */ +/* flurry */ +#ifndef __GLCODE__ +#define __GLCODE__ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif /* HAVE_CONFIG_H */ + +#ifndef HAVE_COCOA +# include +# include +# include +#endif + +#ifdef HAVE_JWZGLES +# include "jwzgles.h" +#endif /* HAVE_JWZGLES */ + + +#include +#include + +#include "yarandom.h" +#include "rotator.h" +#include "gltrackball.h" + +typedef struct _global_info_t global_info_t; +typedef struct _flurry_info_t flurry_info_t; + +#define sqr(X) ((X) * (X)) +#define PI 3.14159265358979323846f +#define DEG2RAD(X) (PI*(X)/180.0) +#define RAD2DEG(X) ((X)*180.0/PI) +#define rnd() (frand(1.0)) + +/* fabs: Absolute function. */ +/* #undef abs */ +/* #define abs(a) ( (a) > 0 ? (a) : -(a) ) */ + +/* Force sign clamping to (-1;0;1) */ +#define sgn(a) ((a)<0?-1:((a)?1:0)) + +/* used to compute the min and max of two expresions */ +#define MIN_(a, b) (((a) < (b)) ? (a) : (b)) +#define MAX_(a, b) (((a) > (b)) ? (a) : (b)) + +typedef union { + float f[4]; +#if 0 +#if __VEC__ + vector float v; +#endif +#endif /* 0 */ +} floatToVector; + +typedef union { + unsigned int i[4]; +#if 0 +#if __VEC__ + vector unsigned int v; +#endif +#endif /* 0 */ +} intToVector; + +typedef struct SmokeParticleV +{ + floatToVector color[4]; + floatToVector position[3]; + floatToVector oldposition[3]; + floatToVector delta[3]; + intToVector dead; + floatToVector time; + intToVector animFrame; +} SmokeParticleV; + +#define NUMSMOKEPARTICLES 3600 + +typedef struct SmokeV +{ + SmokeParticleV p[NUMSMOKEPARTICLES/4]; + int nextParticle; + int nextSubParticle; + float lastParticleTime; + int firstTime; + long frame; + float old[3]; + floatToVector seraphimVertices[NUMSMOKEPARTICLES*2+1]; + floatToVector seraphimColors[NUMSMOKEPARTICLES*4+1]; + float seraphimTextures[NUMSMOKEPARTICLES*2*4]; +} SmokeV; + +void InitSmoke(SmokeV *s); + +void UpdateSmoke_ScalarBase(global_info_t *global, flurry_info_t *flurry, SmokeV *s); +#if 0 +#ifdef __ppc__ +void UpdateSmoke_ScalarFrsqrte(global_info_t *global, flurry_info_t *flurry, SmokeV *s); +#endif +#ifdef __VEC__ +void UpdateSmoke_VectorBase(global_info_t *global, flurry_info_t *flurry, SmokeV *s); +void UpdateSmoke_VectorUnrolled(global_info_t *global, flurry_info_t *flurry, SmokeV *s); +#endif +#endif /* 0 */ + +void DrawSmoke_Scalar(global_info_t *global, flurry_info_t *flurry, SmokeV *s, float); +void DrawSmoke_Vector(global_info_t *global, flurry_info_t *flurry, SmokeV *s, float); + +typedef struct Star +{ + float position[3]; + float mystery; + float rotSpeed; + int ate; +} Star; + +void UpdateStar(global_info_t *global, flurry_info_t *flurry, Star *s); +void InitStar(Star *s); + +typedef struct Spark +{ + float position[3]; + int mystery; + float delta[3]; + float color[4]; +} Spark; + +void UpdateSparkColour(global_info_t *info, flurry_info_t *flurry, Spark *s); +void InitSpark(Spark *s); +void UpdateSpark(global_info_t *info, flurry_info_t *flurry, Spark *s); +void DrawSpark(global_info_t *info, flurry_info_t *flurry, Spark *s); + +/* #define FastDistance2D(x,y) hypot(x,y) */ + +/* UInt8 sys_glBPP=32; */ +/* int SSMODE = FALSE; */ +/* int currentVideoMode = 0; */ +/* int cohesiveness = 7; */ +/* int fieldStrength; */ +/* int colorCoherence = 7; */ +/* int fieldIncoherence = 0; */ +/* int ifieldSpeed = 120; */ + +static inline float FastDistance2D(float x, float y) +{ + /* this function computes the distance from 0,0 to x,y with ~3.5% error */ + float mn; + /* first compute the absolute value of x,y */ + x = (x < 0.0f) ? -x : x; + y = (y < 0.0f) ? -y : y; + + /* compute the minimum of x,y */ + mn = x] +[\-fps] +.SH DESCRIPTION +This is a port of the OSX screensaver flurry. +.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 \-preset +Select a preset (classic, fire, water, psychedelic, rgb, binary, random, insane) + +(Insane will never be selected at random, because it requires lots of CPU/GPU +power) + +.TP 8 +.B \-fps +Display the current frame rate, CPU load, and polygon count. +.TP 8 +.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 AUTHORS +OSX screensaver by Calum Robinson + +http://homepage.mac.com/calumr + +xscreensaver port by Tobias Sargeant + +.SH POSTCARDS + +If you really like it, send me a postcard (after all, you're getting this for +free!). Please check this address by downloading the latest version of Flurry +just before you send me a postcard - I may have moved. + +.PD 0 +Calum Robinson +.P +133 Sydenham Avenue +.P +Belfast +.P +Northern Ireland +.P +BT4 2DQ +.PD 0 + +.SH SEE ALSO +.BR X (1), +.BR xscreensaver (1) +.SH COPYRIGHT diff --git a/hacks/glx/flyingtoasters.c b/hacks/glx/flyingtoasters.c new file mode 100644 index 00000000..23217f03 --- /dev/null +++ b/hacks/glx/flyingtoasters.c @@ -0,0 +1,874 @@ +/* flyingtoasters, Copyright (c) 2003-2006 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. + * + * Draws 3D flying toasters, and toast. Inspired by the ancient + * Berkeley Systems / After Dark hack, but now updated to the wide + * wonderful workd of OpenGL and 3D! + * + * Code by jwz; object models by Baconmonkey. + * + * The original After Dark flying toasters, with the fluffy white wings, + * were a trademark of Berkeley Systems. Berkeley Systems ceased to exist + * some time in 1998, having been gobbled up by Sierra Online, who were + * subsequently gobbled up by Flipside and/or Vivendi (it's hard to tell + * exactly what happened when.) + * + * I doubt anyone even cares any more, but if they do, hopefully this homage, + * with the space-age 3D jet-plane toasters, will be considered different + * enough that whoever still owns the trademark to the fluffy-winged 2D + * bitmapped toasters won't get all huffy at us. + */ + +#define DEFAULTS "*delay: 30000 \n" \ + "*showFPS: False \n" \ + "*wireframe: False \n" \ + +/* #define DEBUG */ + +# define refresh_toasters 0 +# define release_toasters 0 +#undef countof +#define countof(x) (sizeof((x))/sizeof((*x))) + +#define DEF_SPEED "1.0" +#define DEF_NTOASTERS "20" +#define DEF_NSLICES "25" +#define DEF_TEXTURE "True" + +#undef BELLRAND +#define BELLRAND(n) ((frand((n)) + frand((n)) + frand((n))) / 3) + +#include "xlockmore.h" +#include "gltrackball.h" +#include "xpm-ximage.h" +#include + +#include "../images/chromesphere.xpm" +#include "../images/toast.xpm" + +#ifdef USE_GL /* whole file */ + +#include "gllist.h" + +extern const struct gllist + *toaster, *toaster_base, *toaster_handle, *toaster_handle2, *toaster_jet, + *toaster_knob, *toaster_slots, *toaster_wing, *toast, *toast2; + +static const struct gllist * const *all_objs[] = { + &toaster, &toaster_base, &toaster_handle, &toaster_handle2, &toaster_jet, + &toaster_knob, &toaster_slots, &toaster_wing, &toast, &toast2 +}; + +#define BASE_TOASTER 0 +#define BASE 1 +#define HANDLE 2 +#define HANDLE_SLOT 3 +#define JET 4 +#define KNOB 5 +#define SLOTS 6 +#define JET_WING 7 +#define TOAST 8 +#define TOAST_BITTEN 9 + +#define GRID_SIZE 60 +#define GRID_DEPTH 500 + + +static const struct { GLfloat x, y; } nice_views[] = { + { 0, 120 }, + { 0, -120 }, + { 12, 28 }, /* this is a list of viewer rotations that look nice. */ + { 12, -28 }, /* every now and then we switch to a new one. */ + {-10, -28 }, /* (but we only use the first two at start-up.) */ + { 40, -60 }, + {-40, -60 }, + { 40, 60 }, + {-40, 60 }, + { 30, 0 }, + {-30, 0 }, +}; + + +typedef struct { + GLfloat x, y, z; + GLfloat dx, dy, dz; + Bool toaster_p; + int toast_type; /* 0, 1 */ + GLfloat handle_pos; /* 0.0 - 1.0 */ + GLfloat knob_pos; /* degrees */ + int loaded; /* 2 bits */ +} floater; + +typedef struct { + GLXContext *glx_context; + trackball_state *user_trackball; + Bool button_down_p; + + int last_view, target_view; + GLfloat view_x, view_y; + int view_steps, view_tick; + Bool auto_tracking_p; + int track_tick; + + GLuint *dlists; + GLuint chrome_texture; + GLuint toast_texture; + + int nfloaters; + floater *floaters; + +} toaster_configuration; + +static toaster_configuration *bps = NULL; + +static GLfloat speed; +static int ntoasters; +static int nslices; +static int do_texture; + +static XrmOptionDescRec opts[] = { + { "-speed", ".speed", XrmoptionSepArg, 0 }, + { "-ntoasters", ".ntoasters", XrmoptionSepArg, 0 }, + { "-nslices", ".nslices", XrmoptionSepArg, 0 }, + {"-texture", ".texture", XrmoptionNoArg, "True" }, + {"+texture", ".texture", XrmoptionNoArg, "False" }, +}; + +static argtype vars[] = { + {&speed, "speed", "Speed", DEF_SPEED, t_Float}, + {&ntoasters, "ntoasters", "Count", DEF_NTOASTERS, t_Int}, + {&nslices, "nslices", "Count", DEF_NSLICES, t_Int}, + {&do_texture, "texture", "Texture", DEF_TEXTURE, t_Bool}, +}; + +ENTRYPOINT ModeSpecOpt toasters_opts = {countof(opts), opts, countof(vars), vars, NULL}; + + +static void +reset_floater (ModeInfo *mi, floater *f) +{ +/* toaster_configuration *bp = &bps[MI_SCREEN(mi)]; */ + + GLfloat n = GRID_SIZE/2.0; + GLfloat n2 = GRID_DEPTH/2.0; + GLfloat delta = GRID_SIZE * speed / 200.0; + + f->dx = 0; + f->dy = 0; + f->dz = delta; + + f->dz += BELLRAND(delta) - delta/3; + + if (! (random() % 5)) { + f->dx += (BELLRAND(delta*2) - delta); + f->dy += (BELLRAND(delta*2) - delta); + } + + if (! (random() % 40)) f->dz *= 10; /* occasional speedy one */ + + f->x = frand(n) - n/2; + f->y = frand(n) - n/2; + f->z = -n2 - frand(delta * 4); + + if (f->toaster_p) + { + f->loaded = 0; + f->knob_pos = frand(180) - 90; + f->handle_pos = ((random() & 1) ? 0.0 : 1.0); + + if (f->handle_pos > 0.8 && (! (random() % 5))) + f->loaded = (random() & 3); /* let's toast! */ + } + else + { + if (! (random() % 10)) + f->toast_type = 1; /* toast_bitten */ + } +} + + +static void +tick_floater (ModeInfo *mi, floater *f) +{ + toaster_configuration *bp = &bps[MI_SCREEN(mi)]; + + GLfloat n1 = GRID_DEPTH/2.0; + GLfloat n2 = GRID_SIZE*4; + + if (bp->button_down_p) return; + + f->x += f->dx; + f->y += f->dy; + f->z += f->dz; + + if (! (random() % 50000)) /* sudden gust of gravity */ + f->dy -= 2.8; + + if (f->x < -n2 || f->x > n2 || + f->y < -n2 || f->y > n2 || + f->z > n1) + reset_floater (mi, f); +} + + +static void +auto_track_init (ModeInfo *mi) +{ + toaster_configuration *bp = &bps[MI_SCREEN(mi)]; + bp->last_view = (random() % 2); + bp->target_view = bp->last_view + 2; + bp->view_x = nice_views[bp->last_view].x; + bp->view_y = nice_views[bp->last_view].y; + bp->view_steps = 100; + bp->view_tick = 0; + bp->auto_tracking_p = True; +} + + +static void +auto_track (ModeInfo *mi) +{ + toaster_configuration *bp = &bps[MI_SCREEN(mi)]; + + if (bp->button_down_p) + return; + + /* if we're not moving, maybe start moving. Otherwise, do nothing. */ + if (! bp->auto_tracking_p) + { + if (++bp->track_tick < 200/speed) return; + bp->track_tick = 0; + if (! (random() % 5)) + bp->auto_tracking_p = True; + else + return; + } + + + { + GLfloat ox = nice_views[bp->last_view].x; + GLfloat oy = nice_views[bp->last_view].y; + GLfloat tx = nice_views[bp->target_view].x; + GLfloat ty = nice_views[bp->target_view].y; + + /* move from A to B with sinusoidal deltas, so that it doesn't jerk + to a stop. */ + GLfloat th = sin ((M_PI / 2) * (double) bp->view_tick / bp->view_steps); + + bp->view_x = (ox + ((tx - ox) * th)); + bp->view_y = (oy + ((ty - oy) * th)); + bp->view_tick++; + + if (bp->view_tick >= bp->view_steps) + { + bp->view_tick = 0; + bp->view_steps = (350.0 / speed); + bp->last_view = bp->target_view; + bp->target_view = (random() % (countof(nice_views) - 2)) + 2; + bp->auto_tracking_p = False; + } + } +} + + +/* Window management, etc + */ +ENTRYPOINT void +reshape_toasters (ModeInfo *mi, int width, int height) +{ + GLfloat h = (GLfloat) height / (GLfloat) width; + + glViewport (0, 0, (GLint) width, (GLint) height); + + glMatrixMode(GL_PROJECTION); + glLoadIdentity(); + gluPerspective (40.0, 1/h, 1.0, 250); + + glMatrixMode(GL_MODELVIEW); + glLoadIdentity(); + gluLookAt( 0.0, 2.0, 30.0, + 0.0, 0.0, 0.0, + 0.0, 1.0, 0.0); + + glClear(GL_COLOR_BUFFER_BIT); +} + + +ENTRYPOINT Bool +toasters_handle_event (ModeInfo *mi, XEvent *event) +{ + toaster_configuration *bp = &bps[MI_SCREEN(mi)]; + + if (event->xany.type == ButtonPress && + event->xbutton.button == Button1) + { + bp->button_down_p = True; + gltrackball_start (bp->user_trackball, + event->xbutton.x, event->xbutton.y, + MI_WIDTH (mi), MI_HEIGHT (mi)); + return True; + } + else if (event->xany.type == ButtonRelease && + event->xbutton.button == Button1) + { + bp->button_down_p = False; + return True; + } + else if (event->xany.type == ButtonPress && + (event->xbutton.button == Button4 || + event->xbutton.button == Button5 || + event->xbutton.button == Button6 || + event->xbutton.button == Button7)) + { + gltrackball_mousewheel (bp->user_trackball, event->xbutton.button, 5, + !event->xbutton.state); + return True; + } + else if (event->xany.type == MotionNotify && + bp->button_down_p) + { + gltrackball_track (bp->user_trackball, + event->xmotion.x, event->xmotion.y, + MI_WIDTH (mi), MI_HEIGHT (mi)); + return True; + } + + return False; +} + + +static void +load_textures (ModeInfo *mi) +{ + toaster_configuration *bp = &bps[MI_SCREEN(mi)]; + XImage *xi; + + xi = xpm_to_ximage (mi->dpy, mi->xgwa.visual, mi->xgwa.colormap, + chromesphere_xpm); + clear_gl_error(); + + glGenTextures (1, &bp->chrome_texture); + glBindTexture (GL_TEXTURE_2D, bp->chrome_texture); + glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + glPixelStorei (GL_UNPACK_ALIGNMENT, 1); + glTexImage2D (GL_TEXTURE_2D, 0, GL_RGBA, + xi->width, xi->height, 0, + GL_RGBA, +# ifndef USE_IPHONE + GL_UNSIGNED_INT_8_8_8_8_REV, +# else + GL_UNSIGNED_BYTE, +# endif + xi->data); + check_gl_error("texture"); + + xi = xpm_to_ximage (mi->dpy, mi->xgwa.visual, mi->xgwa.colormap, + toast_xpm); + + glGenTextures (1, &bp->toast_texture); + glBindTexture (GL_TEXTURE_2D, bp->toast_texture); + glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); +# ifndef HAVE_JWZGLES + glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP); + glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP); +# endif + glPixelStorei (GL_UNPACK_ALIGNMENT, 1); + glTexImage2D (GL_TEXTURE_2D, 0, GL_RGBA, + xi->width, xi->height, 0, + GL_RGBA, +# ifndef USE_IPHONE + GL_UNSIGNED_INT_8_8_8_8_REV, +# else + GL_UNSIGNED_BYTE, +# endif + xi->data); + check_gl_error("texture"); + + glEnable(GL_TEXTURE_GEN_S); + glEnable(GL_TEXTURE_GEN_T); + glEnable(GL_TEXTURE_2D); +} + + +ENTRYPOINT void +init_toasters (ModeInfo *mi) +{ + toaster_configuration *bp; + int wire = MI_IS_WIREFRAME(mi); + int i; + + if (!bps) { + bps = (toaster_configuration *) + calloc (MI_NUM_SCREENS(mi), sizeof (toaster_configuration)); + if (!bps) { + fprintf(stderr, "%s: out of memory\n", progname); + exit(1); + } + } + + bp = &bps[MI_SCREEN(mi)]; + + bp->glx_context = init_GL(mi); + + reshape_toasters (mi, MI_WIDTH(mi), MI_HEIGHT(mi)); + + glShadeModel(GL_SMOOTH); + + glEnable(GL_DEPTH_TEST); + glEnable(GL_NORMALIZE); + glEnable(GL_CULL_FACE); + + if (!wire) + { + GLfloat pos[4] = {0.4, 0.2, 0.4, 0.0}; +/* GLfloat amb[4] = {0.0, 0.0, 0.0, 1.0};*/ + GLfloat amb[4] = {0.2, 0.2, 0.2, 1.0}; + GLfloat dif[4] = {1.0, 1.0, 1.0, 1.0}; + GLfloat spc[4] = {1.0, 1.0, 1.0, 1.0}; + + glEnable(GL_LIGHTING); + glEnable(GL_LIGHT0); + glEnable(GL_DEPTH_TEST); + glEnable(GL_CULL_FACE); + + 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) + load_textures (mi); + + bp->user_trackball = gltrackball_init (); + auto_track_init (mi); + + bp->dlists = (GLuint *) calloc (countof(all_objs)+1, sizeof(GLuint)); + for (i = 0; i < countof(all_objs); i++) + bp->dlists[i] = glGenLists (1); + + for (i = 0; i < countof(all_objs); i++) + { + const struct gllist *gll = *all_objs[i]; + + glNewList (bp->dlists[i], GL_COMPILE); + + glMatrixMode(GL_MODELVIEW); + glPushMatrix(); + glMatrixMode(GL_TEXTURE); + glPushMatrix(); + glMatrixMode(GL_MODELVIEW); + + glRotatef (-90, 1, 0, 0); + glRotatef (180, 0, 0, 1); + glScalef (6, 6, 6); + + glBindTexture (GL_TEXTURE_2D, 0); + + if (i == BASE_TOASTER) + { + GLfloat color[4] = {1.00, 1.00, 1.00, 1.00}; + GLfloat spec[4] = {1.00, 1.00, 1.00, 1.0}; + GLfloat shiny = 20.0; + glMaterialfv (GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, color); + glMaterialfv (GL_FRONT_AND_BACK, GL_SPECULAR, spec); + glMaterialf (GL_FRONT_AND_BACK, GL_SHININESS, shiny); + if (do_texture) + glBindTexture (GL_TEXTURE_2D, bp->chrome_texture); +# ifndef HAVE_JWZGLES + glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_SPHERE_MAP); + glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_SPHERE_MAP); +# endif + } + else if (i == TOAST || i == TOAST_BITTEN) + { + GLfloat color[4] = {0.80, 0.80, 0.00, 1.0}; + GLfloat spec[4] = {0.00, 0.00, 0.00, 1.0}; + GLfloat shiny = 0.0; + glMaterialfv (GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, color); + glMaterialfv (GL_FRONT_AND_BACK, GL_SPECULAR, spec); + glMaterialf (GL_FRONT_AND_BACK, GL_SHININESS, shiny); + if (do_texture) + glBindTexture (GL_TEXTURE_2D, bp->toast_texture); +# ifndef HAVE_JWZGLES + glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR); + glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR); +# endif + + glMatrixMode(GL_TEXTURE); + glTranslatef(0.5, 0.5, 0); + glMatrixMode(GL_MODELVIEW); + } + else if (i == SLOTS || i == HANDLE_SLOT) + { + GLfloat color[4] = {0.30, 0.30, 0.40, 1.0}; + GLfloat spec[4] = {0.40, 0.40, 0.70, 1.0}; + GLfloat shiny = 128.0; + glMaterialfv (GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, color); + glMaterialfv (GL_FRONT_AND_BACK, GL_SPECULAR, spec); + glMaterialf (GL_FRONT_AND_BACK, GL_SHININESS, shiny); + } + else if (i == HANDLE) + { + GLfloat color[4] = {0.80, 0.10, 0.10, 1.0}; + GLfloat spec[4] = {1.00, 1.00, 1.00, 1.0}; + GLfloat shiny = 20.0; + glMaterialfv (GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, color); + glMaterialfv (GL_FRONT_AND_BACK, GL_SPECULAR, spec); + glMaterialf (GL_FRONT_AND_BACK, GL_SHININESS, shiny); + } + else if (i == KNOB) + { + GLfloat color[4] = {0.80, 0.10, 0.10, 1.0}; + GLfloat spec[4] = {0.00, 0.00, 0.00, 1.0}; + GLfloat shiny = 0.0; + glMaterialfv (GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, color); + glMaterialfv (GL_FRONT_AND_BACK, GL_SPECULAR, spec); + glMaterialf (GL_FRONT_AND_BACK, GL_SHININESS, shiny); + } + else if (i == JET || i == JET_WING) + { + GLfloat color[4] = {0.70, 0.70, 0.70, 1.0}; + GLfloat spec[4] = {1.00, 1.00, 1.00, 1.0}; + GLfloat shiny = 20.0; + glMaterialfv (GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, color); + glMaterialfv (GL_FRONT_AND_BACK, GL_SPECULAR, spec); + glMaterialf (GL_FRONT_AND_BACK, GL_SHININESS, shiny); + } + else if (i == BASE) + { + GLfloat color[4] = {0.50, 0.50, 0.50, 1.0}; + GLfloat spec[4] = {1.00, 1.00, 1.00, 1.0}; + GLfloat shiny = 20.0; + glMaterialfv (GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, color); + glMaterialfv (GL_FRONT_AND_BACK, GL_SPECULAR, spec); + glMaterialf (GL_FRONT_AND_BACK, GL_SHININESS, shiny); + } + else + { + GLfloat color[4] = {1.00, 1.00, 1.00, 1.00}; + GLfloat spec[4] = {1.00, 1.00, 1.00, 1.0}; + GLfloat shiny = 128.0; + glMaterialfv (GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, color); + glMaterialfv (GL_FRONT_AND_BACK, GL_SPECULAR, spec); + glMaterialf (GL_FRONT_AND_BACK, GL_SHININESS, shiny); + } + + renderList (gll, wire); + + glMatrixMode(GL_TEXTURE); + glPopMatrix(); + glMatrixMode(GL_MODELVIEW); + glPopMatrix(); + + glEndList (); + } + + bp->nfloaters = ntoasters + nslices; + bp->floaters = (floater *) calloc (bp->nfloaters, sizeof (floater)); + + for (i = 0; i < bp->nfloaters; i++) + { + floater *f = &bp->floaters[i]; + /* arrange the list so that half the toasters are in front of bread, + and half are behind. */ + f->toaster_p = ((i < ntoasters / 2) || + (i >= (nslices + (ntoasters / 2)))); + reset_floater (mi, f); + + /* Position the first generation randomly, but make sure they aren't + on screen yet (until we rotate the view into position.) + */ + { + GLfloat min = -GRID_DEPTH/2; + GLfloat max = GRID_DEPTH/3.5; + f->z = frand (max - min) + min; + } + } +} + + +static void +draw_origin (ModeInfo *mi) +{ +# ifdef DEBUG +/* toaster_configuration *bp = &bps[MI_SCREEN(mi)];*/ + + if (!MI_IS_WIREFRAME(mi)) glDisable(GL_LIGHTING); + if (!MI_IS_WIREFRAME(mi) && do_texture) glDisable(GL_TEXTURE_2D); + + glPushMatrix(); + glScalef (5, 5, 5); + glBegin(GL_LINES); + glVertex3f(-1, 0, 0); glVertex3f(1, 0, 0); + glVertex3f(0, -1, 0); glVertex3f(0, 1, 0); + glVertex3f(0, 0, -1); glVertex3f(0, 0, 1); + glEnd(); + glPopMatrix(); + + if (!MI_IS_WIREFRAME(mi)) glEnable(GL_LIGHTING); + if (!MI_IS_WIREFRAME(mi) && do_texture) glEnable(GL_TEXTURE_2D); +# endif /* DEBUG */ +} + + +static void +draw_grid (ModeInfo *mi) +{ +# ifdef DEBUG +/* toaster_configuration *bp = &bps[MI_SCREEN(mi)];*/ + + if (!MI_IS_WIREFRAME(mi)) glDisable(GL_LIGHTING); + if (!MI_IS_WIREFRAME(mi) && do_texture) glDisable(GL_TEXTURE_2D); + glPushMatrix(); + glBegin(GL_LINE_LOOP); + glVertex3f(-GRID_SIZE/2, -GRID_SIZE/2, 0); + glVertex3f(-GRID_SIZE/2, GRID_SIZE/2, 0); + glVertex3f( GRID_SIZE/2, GRID_SIZE/2, 0); + glVertex3f( GRID_SIZE/2, -GRID_SIZE/2, 0); + glEnd(); + glBegin(GL_LINE_LOOP); + glVertex3f(-GRID_SIZE/2, GRID_SIZE/2, -GRID_DEPTH/2); + glVertex3f(-GRID_SIZE/2, GRID_SIZE/2, GRID_DEPTH/2); + glVertex3f( GRID_SIZE/2, GRID_SIZE/2, GRID_DEPTH/2); + glVertex3f( GRID_SIZE/2, GRID_SIZE/2, -GRID_DEPTH/2); + glEnd(); + glBegin(GL_LINE_LOOP); + glVertex3f(-GRID_SIZE/2, -GRID_SIZE/2, -GRID_DEPTH/2); + glVertex3f(-GRID_SIZE/2, -GRID_SIZE/2, GRID_DEPTH/2); + glVertex3f( GRID_SIZE/2, -GRID_SIZE/2, GRID_DEPTH/2); + glVertex3f( GRID_SIZE/2, -GRID_SIZE/2, -GRID_DEPTH/2); + glEnd(); + glBegin(GL_LINES); + glVertex3f(-GRID_SIZE/2, -GRID_SIZE/2, -GRID_DEPTH/2); + glVertex3f(-GRID_SIZE/2, GRID_SIZE/2, -GRID_DEPTH/2); + glVertex3f(-GRID_SIZE/2, -GRID_SIZE/2, GRID_DEPTH/2); + glVertex3f(-GRID_SIZE/2, GRID_SIZE/2, GRID_DEPTH/2); + glVertex3f( GRID_SIZE/2, -GRID_SIZE/2, -GRID_DEPTH/2); + glVertex3f( GRID_SIZE/2, GRID_SIZE/2, -GRID_DEPTH/2); + glVertex3f( GRID_SIZE/2, -GRID_SIZE/2, GRID_DEPTH/2); + glVertex3f( GRID_SIZE/2, GRID_SIZE/2, GRID_DEPTH/2); + glEnd(); + glPopMatrix(); + + if (!MI_IS_WIREFRAME(mi)) glEnable(GL_LIGHTING); + if (!MI_IS_WIREFRAME(mi) && do_texture) glEnable(GL_TEXTURE_2D); +# endif /* DEBUG */ +} + + +static void +draw_floater (ModeInfo *mi, floater *f) +{ + toaster_configuration *bp = &bps[MI_SCREEN(mi)]; + GLfloat n; + + glFrontFace(GL_CCW); + + glPushMatrix(); + glTranslatef (f->x, f->y, f->z); + if (f->toaster_p) + { + glPushMatrix(); + glRotatef (180, 0, 1, 0); + + glCallList (bp->dlists[BASE_TOASTER]); + mi->polygon_count += (*all_objs[BASE_TOASTER])->points / 3; + glPopMatrix(); + + glPushMatrix(); + glTranslatef(0, 1.01, 0); + n = 0.91; glScalef(n,n,n); + glCallList (bp->dlists[SLOTS]); + mi->polygon_count += (*all_objs[SLOTS])->points / 3; + glPopMatrix(); + + glPushMatrix(); + glRotatef (180, 0, 1, 0); + glTranslatef(0, -0.4, -2.38); + n = 0.33; glScalef(n,n,n); + glCallList (bp->dlists[HANDLE_SLOT]); + mi->polygon_count += (*all_objs[HANDLE_SLOT])->points / 3; + glPopMatrix(); + + glPushMatrix(); + glTranslatef(0, -1.1, 3); + n = 0.3; glScalef (n,n,n); + glTranslatef(0, f->handle_pos * 4.8, 0); + glCallList (bp->dlists[HANDLE]); + mi->polygon_count += (*all_objs[HANDLE])->points / 3; + glPopMatrix(); + + glPushMatrix(); + glRotatef (180, 0, 1, 0); + glTranslatef(0, -1.1, -3); /* where the handle is */ + glTranslatef (1, -0.4, 0); /* down and to the left */ + n = 0.08; glScalef (n,n,n); + glRotatef (f->knob_pos, 0, 0, 1); + glCallList (bp->dlists[KNOB]); + mi->polygon_count += (*all_objs[KNOB])->points / 3; + glPopMatrix(); + + glPushMatrix(); + glRotatef (180, 0, 1, 0); + glTranslatef (0, -2.3, 0); + glCallList (bp->dlists[BASE]); + mi->polygon_count += (*all_objs[BASE])->points / 3; + glPopMatrix(); + + glPushMatrix(); + glTranslatef(-4.8, 0, 0); + glCallList (bp->dlists[JET_WING]); + mi->polygon_count += (*all_objs[JET_WING])->points / 3; + glScalef (0.5, 0.5, 0.5); + glTranslatef (-2, -1, 0); + glCallList (bp->dlists[JET]); + mi->polygon_count += (*all_objs[JET])->points / 3; + glPopMatrix(); + + glPushMatrix(); + glTranslatef(4.8, 0, 0); + glScalef(-1, 1, 1); + glFrontFace(GL_CW); + glCallList (bp->dlists[JET_WING]); + mi->polygon_count += (*all_objs[JET_WING])->points / 3; + glScalef (0.5, 0.5, 0.5); + glTranslatef (-2, -1, 0); + glCallList (bp->dlists[JET]); + mi->polygon_count += (*all_objs[JET])->points / 3; + glFrontFace(GL_CCW); + glPopMatrix(); + + if (f->loaded) + { + glPushMatrix(); + glTranslatef(0, 1.01, 0); + n = 0.91; glScalef(n,n,n); + glRotatef (90, 0, 0, 1); + glRotatef (90, 0, 1, 0); + glTranslatef(0, 0, -0.95); + glTranslatef(0, 0.72, 0); + if (f->loaded & 1) + { + glCallList (bp->dlists[TOAST]); + mi->polygon_count += (*all_objs[TOAST])->points / 3; + } + glTranslatef(0, -1.46, 0); + if (f->loaded & 2) + { + glCallList (bp->dlists[TOAST]); + mi->polygon_count += (*all_objs[TOAST])->points / 3; + } + glPopMatrix(); + } + } + else + { + glScalef (0.7, 0.7, 0.7); + if (f->toast_type == 0) + { + glCallList (bp->dlists[TOAST]); + mi->polygon_count += (*all_objs[TOAST])->points / 3; + } + else + { + glCallList (bp->dlists[TOAST_BITTEN]); + mi->polygon_count += (*all_objs[TOAST_BITTEN])->points / 3; + } + } + + glPopMatrix(); +} + + + +ENTRYPOINT void +draw_toasters (ModeInfo *mi) +{ + toaster_configuration *bp = &bps[MI_SCREEN(mi)]; + Display *dpy = MI_DISPLAY(mi); + Window window = MI_WINDOW(mi); + int i; + + if (!bp->glx_context) + return; + + glXMakeCurrent(MI_DISPLAY(mi), MI_WINDOW(mi), *(bp->glx_context)); + + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + + glPushMatrix (); + glRotatef(current_device_rotation(), 0, 0, 1); + glRotatef(bp->view_x, 1, 0, 0); + glRotatef(bp->view_y, 0, 1, 0); + + /* Rotate the scene around a point that's a little deeper in. */ + glTranslatef (0, 0, -50); + gltrackball_rotate (bp->user_trackball); + glTranslatef (0, 0, 50); + +#if 0 + { + floater F; + F.toaster_p = 0; + F.toast_type = 1; + F.handle_pos = 0; + F.knob_pos = -90; + F.loaded = 3; + F.x = F.y = F.z = 0; + F.dx = F.dy = F.dz = 0; + + glScalef(2,2,2); + if (!MI_IS_WIREFRAME(mi)) glDisable(GL_LIGHTING); + if (!MI_IS_WIREFRAME(mi) && do_texture) glDisable(GL_TEXTURE_2D); + glBegin(GL_LINES); + glVertex3f(-10, 0, 0); glVertex3f(10, 0, 0); + glVertex3f(0, -10, 0); glVertex3f(0, 10, 0); + glVertex3f(0, 0, -10); glVertex3f(0, 0, 10); + glEnd(); + if (!MI_IS_WIREFRAME(mi)) glEnable(GL_LIGHTING); + if (!MI_IS_WIREFRAME(mi) && do_texture) glEnable(GL_TEXTURE_2D); + + draw_floater (mi, &F); + glPopMatrix (); + if (mi->fps_p) do_fps (mi); + glFinish(); + glXSwapBuffers(dpy, window); + return; + } +#endif + + glScalef (0.5, 0.5, 0.5); + draw_origin (mi); + glTranslatef (0, 0, -GRID_DEPTH/2.5); + draw_grid (mi); + + mi->polygon_count = 0; + for (i = 0; i < bp->nfloaters; i++) + { + floater *f = &bp->floaters[i]; + draw_floater (mi, f); + tick_floater (mi, f); + } + auto_track (mi); + + glPopMatrix (); + + if (mi->fps_p) do_fps (mi); + glFinish(); + + glXSwapBuffers(dpy, window); +} + +XSCREENSAVER_MODULE_2 ("FlyingToasters", flyingtoasters, toasters) + +#endif /* USE_GL */ diff --git a/hacks/glx/flyingtoasters.man b/hacks/glx/flyingtoasters.man new file mode 100644 index 00000000..dbe5d5a9 --- /dev/null +++ b/hacks/glx/flyingtoasters.man @@ -0,0 +1,86 @@ +.TH XScreenSaver 1 "" "X Version 11" +.SH NAME +flyingtoasters - 3d space-age jet-powered flying toasters (and toast) +.SH SYNOPSIS +.B flyingtoasters +[\-display \fIhost:display.screen\fP] +[\-visual \fIvisual\fP] +[\-window] +[\-root] +[\-delay \fInumber\fP] +[\-speed \fInumber\fP] +[\-ntoasters \fInumber\fP] +[\-nslices \fInumber\fP] +[\-no-texture] +[\-wireframe] +[\-fps] +.SH DESCRIPTION +Draws a squadron of shiny 3D space-age jet-powered flying toasters, and +associated toast, flying across your screen. +.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 \-speed \fInumber\fP +How fast the toasters fly. Larger for faster. Default: 1.0. +.TP 8 +.B \-ntoasters \fInumber\fP +How many toasters to draw. Default 20. +.TP 8 +.B \-nslices \fInumber\fP +How many slices of toast to draw. Default 25. +.TP 8 +.B \-no-texture +Turn off texture mapping (for slow machines.) +.TP 8 +.B \-wireframe +Render in wireframe instead of solid. +.TP 8 +.B \-fps +Display the current frame rate, CPU load, and polygon count. +.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) +.BR After Dark +.SH COPYRIGHT +Copyright \(co 2003 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. + +The original After Dark flying toasters, with the fluffy white wings, +were a trademark of Berkeley Systems. Berkeley Systems ceased to exist +some time in 1998, having been gobbled up by Sierra Online, who were +subsequently gobbled up by Flipside and/or Vivendi (it's hard to tell +exactly what happened when.) + +I doubt anyone even cares any more, but if they do, hopefully this +homage, with the space-age 3D jet-plane toasters, will be considered +different enough that whoever still owns the trademark to the +fluffy-winged 2D bitmapped toasters won't get all huffy at us. +.SH AUTHOR +Code by Jamie Zawinski. Object models by Baconmonkey. diff --git a/hacks/glx/font-ximage.c b/hacks/glx/font-ximage.c new file mode 100644 index 00000000..25ceb422 --- /dev/null +++ b/hacks/glx/font-ximage.c @@ -0,0 +1,254 @@ +/* font-ximage.c --- renders text to an XImage for use with OpenGL. + * xscreensaver, Copyright (c) 2001, 2003 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. + */ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include +#include +#include + +#ifdef HAVE_COCOA +# include "jwxyz.h" +#else /* !HAVE_COCOA */ +# include +# include +# include /* only for GLfloat */ +#endif /* !HAVE_COCOA */ + +#ifdef HAVE_JWZGLES +# include "jwzgles.h" +#endif /* HAVE_JWZGLES */ + +extern char *progname; + +#include "font-ximage.h" + +#undef MAX +#define MAX(a,b) ((a)>(b)?(a):(b)) + +#undef countof +#define countof(x) (sizeof((x))/sizeof((*x))) + +#if 0 +static Bool +bigendian (void) +{ + union { int i; char c[sizeof(int)]; } u; + u.i = 1; + return !u.c[0]; +} +#endif + +/* return the next larger power of 2. */ +static int +to_pow2 (int i) +{ + static const unsigned int pow2[] = { + 1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024, + 2048, 4096, 8192, 16384, 32768, 65536 }; + int j; + for (j = 0; j < countof(pow2); j++) + if (pow2[j] >= i) return pow2[j]; + abort(); /* too big! */ +} + + +/* Returns an XImage structure containing the string rendered in the font. + This XImage will be 32 bits per pixel, 8 each per R, G, and B, with the + extra byte set to 0xFF. + + Foregroune and background are GL-style color specifiers: 4 floats from + 0.0-1.0. + */ +XImage * +text_to_ximage (Screen *screen, Visual *visual, + const char *font, + const char *text_lines, + GLfloat *texture_fg, + GLfloat *texture_bg) +{ + Display *dpy = DisplayOfScreen (screen); + int width, height; + XFontStruct *f; + Pixmap bitmap; + + f = XLoadQueryFont(dpy, font); + if (!f) + { + f = XLoadQueryFont(dpy, "fixed"); + if (f) + fprintf (stderr, "%s: unable to load font \"%s\"; using \"fixed\".\n", + progname, font); + else + { + fprintf (stderr, "%s: unable to load fonts \"%s\" or \"fixed\"!\n", + progname, font); + exit (1); + } + } + + /* Parse the text, and render it to `bitmap' + */ + { + char *text, *text2, *line, *token; + int lines; + XCharStruct overall; + XGCValues gcv; + GC gc; + + int margin = 2; + int fg = 1; + int bg = 0; + int xoff, yoff; + + text = strdup (text_lines); + while (*text && + (text[strlen(text)-1] == '\r' || + text[strlen(text)-1] == '\n')) + text[strlen(text)-1] = 0; + + text2 = strdup (text); + + memset(&overall, 0, sizeof(overall)); + token = text; + lines = 0; + while ((line = strtok (token, "\r\n"))) + { + XCharStruct o2; + int ascent, descent, direction; + token = 0; + XTextExtents (f, line, strlen(line), + &direction, &ascent, &descent, &o2); + overall.lbearing = MAX(overall.lbearing, o2.lbearing); + overall.rbearing = MAX(overall.rbearing, o2.rbearing); + lines++; + } + + width = overall.lbearing + overall.rbearing + margin + margin + 1; + height = ((f->ascent + f->descent) * lines) + margin + margin; + + /* GL texture sizes must be powers of two. */ + { + int w2 = to_pow2(width); + int h2 = to_pow2(height); + xoff = (w2 - width) / 2; + yoff = (h2 - height) / 2; + width = w2; + height = h2; + } + + bitmap = XCreatePixmap(dpy, RootWindowOfScreen (screen), width, height, 1); + + gcv.font = f->fid; + gcv.foreground = bg; + gc = XCreateGC (dpy, bitmap, (GCFont | GCForeground), &gcv); + XFillRectangle(dpy, bitmap, gc, 0, 0, width, height); + XSetForeground(dpy, gc, fg); + + token = text2; + lines = 0; + while ((line = strtok(token, "\r\n"))) + { + XCharStruct o2; + int ascent, descent, direction; + token = 0; + + XTextExtents(f, line, strlen(line), + &direction, &ascent, &descent, &o2); + XDrawString(dpy, bitmap, gc, + overall.lbearing + margin + xoff, + ((f->ascent * (lines + 1)) + + (f->descent * lines) + + margin + + yoff), + line, strlen(line)); + lines++; + } + free(text2); + + XUnloadFont(dpy, f->fid); + XFree((XPointer) f); + XFreeGC(dpy, gc); + } + + /* Convert the server-side Pixmap to a client-side GL-ordered XImage. + */ + { + XImage *ximage1, *ximage2; + unsigned long fg, bg; + int x, y; + + ximage1 = XGetImage (dpy, bitmap, 0, 0, width, height, ~0L, ZPixmap); + XFreePixmap(dpy, bitmap); + ximage2 = XCreateImage (dpy, visual, 32, ZPixmap, 0, 0, + width, height, 32, 0); + + ximage2->data = (char *) malloc (height * ximage2->bytes_per_line); + + /* Translate the 1-bit image to a deep image: + first figure out what the colors are. + */ + { + int rpos, gpos, bpos, apos; /* bitfield positions */ + + /* Note that unlike X, which is endianness-agnostic (since any XImage + can have its own specific bit ordering, with the server reversing + things as necessary) OpenGL pretends everything is client-side, so + we need to pack things in the right order for the client machine. + */ +#if 0 + /* #### Cherub says that the little-endian case must be taken on MacOSX, + or else the colors/alpha are the wrong way around. How can + that be the case? + */ + if (bigendian()) + rpos = 24, gpos = 16, bpos = 8, apos = 0; + else +#endif + rpos = 0, gpos = 8, bpos = 16, apos = 24; + + fg = (((unsigned long) (texture_fg[0] * 255.0) << rpos) | + ((unsigned long) (texture_fg[1] * 255.0) << gpos) | + ((unsigned long) (texture_fg[2] * 255.0) << bpos) | + ((unsigned long) (texture_fg[3] * 255.0) << apos)); + bg = (((unsigned long) (texture_bg[0] * 255.0) << rpos) | + ((unsigned long) (texture_bg[1] * 255.0) << gpos) | + ((unsigned long) (texture_bg[2] * 255.0) << bpos) | + ((unsigned long) (texture_bg[3] * 255.0) << apos)); + } + + for (y = 0; y < height; y++) + { + int y2 = (height-1-y); /* Texture maps are upside down. */ + for (x = 0; x < width; x++) + XPutPixel (ximage2, x, y, + XGetPixel (ximage1, x, y2) ? fg : bg); + } + + XDestroyImage (ximage1); + +#if 0 + for (y = 0; y < height; y++) + { + int y2 = (height-1-y); /* Texture maps are upside down. */ + for (x = 0; x < width; x++) + fputc ((XGetPixel (ximage2, x, y2) == fg ? '#' : ' '), stdout); + fputc ('\n', stdout); + } + fputc ('\n', stdout); +#endif /* 0 */ + + return ximage2; + } +} diff --git a/hacks/glx/font-ximage.h b/hacks/glx/font-ximage.h new file mode 100644 index 00000000..cd9d56e8 --- /dev/null +++ b/hacks/glx/font-ximage.h @@ -0,0 +1,30 @@ +/* font-ximage.c --- renders text to an XImage for use with OpenGL. + * xscreensaver, Copyright (c) 2001 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. + */ + +#ifndef __FONT_XIMAGE_H__ +# define __FONT_XIMAGE_H__ + +/* Returns an XImage structure containing the string rendered in the font. + This XImage will be 32 bits per pixel, 8 each per R, G, and B, with the + extra byte set to 0xFF. + + Foregroune and background are GL-style color specifiers: 4 floats from + 0.0-1.0. + */ +XImage *text_to_ximage (Screen *screen, Visual *visual, + const char *font, + const char *text_lines, + GLfloat *texture_fg, + GLfloat *texture_bg); + + +#endif /* __FONT_XIMAGE_H__ */ diff --git a/hacks/glx/fps-gl.c b/hacks/glx/fps-gl.c new file mode 100644 index 00000000..070ae6fb --- /dev/null +++ b/hacks/glx/fps-gl.c @@ -0,0 +1,113 @@ +/* fps, Copyright (c) 2001-2012 Jamie Zawinski + * Draw a frames-per-second display (Xlib and OpenGL). + * + * 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. + */ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif /* HAVE_CONFIG_H */ + +#ifdef HAVE_COCOA +# include "jwxyz.h" +#else /* !HAVE_COCOA -- real Xlib */ +# include +# include +#endif /* !HAVE_COCOA */ + +#ifdef HAVE_JWZGLES +# include "jwzgles.h" +#endif /* HAVE_JWZGLES */ + +#include "xlockmoreI.h" +#include "fpsI.h" +#include "glxfonts.h" + +/* These are in xlock-gl.c */ +extern void clear_gl_error (void); +extern void check_gl_error (const char *type); + + +static void +xlockmore_gl_fps_init (fps_state *st) +{ +#ifdef HAVE_GLBITMAP + + XFontStruct *f = st->font; + int first = f->min_char_or_byte2; + int last = f->max_char_or_byte2; + + clear_gl_error (); + st->font_dlist = glGenLists ((GLuint) last+1); + check_gl_error ("glGenLists"); + + xscreensaver_glXUseXFont (st->dpy, f->fid, + first, last-first+1, st->font_dlist + first); + check_gl_error ("xscreensaver_glXUseXFont"); + +#else /* !HAVE_GLBITMAP */ + + clear_gl_error(); /* screw it */ + st->gl_fps_data = load_texture_font (st->dpy, "fpsFont"); + +#endif /* !HAVE_GLBITMAP */ +} + + + +/* Callback in xscreensaver_function_table, via xlockmore.c. + */ +void +xlockmore_gl_compute_fps (Display *dpy, Window w, fps_state *fpst, + void *closure) +{ + ModeInfo *mi = (ModeInfo *) closure; + if (! mi->fpst) + { + mi->fpst = fpst; + xlockmore_gl_fps_init (fpst); + } + + fps_compute (fpst, mi->polygon_count, mi->recursion_depth); +} + + +/* Called directly from GL programs (as `do_fps') before swapping buffers. + */ +void +xlockmore_gl_draw_fps (ModeInfo *mi) +{ + fps_state *st = mi->fpst; + if (st) /* might be too early */ + { + XWindowAttributes xgwa; + int lines = 1; + const char *s; + int lh = st->font->ascent + st->font->descent; + int y = st->y; + + XGetWindowAttributes (st->dpy, st->window, &xgwa); + for (s = st->string; *s; s++) + if (*s == '\n') lines++; + + if (y < 0) + y = xgwa.height + y - lines*lh; + y += lines*lh + st->font->descent; + + glColor3f (1, 1, 1); + print_gl_string (st->dpy, +# ifdef HAVE_GLBITMAP + st->font, st->font_dlist, +# else /* !HAVE_GLBITMAP */ + st->gl_fps_data, +# endif /* !HAVE_GLBITMAP */ + xgwa.width, xgwa.height, + st->x, y, st->string, st->clear_p); + } +} diff --git a/hacks/glx/gears.c b/hacks/glx/gears.c new file mode 100644 index 00000000..bc925dd5 --- /dev/null +++ b/hacks/glx/gears.c @@ -0,0 +1,946 @@ +/* gears, Copyright (c) 2007-2008 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. + * + * Originally written by Brian Paul in 1996 or earlier; + * rewritten by jwz in Nov 2007. + */ + +#define DEFAULTS "*delay: 30000 \n" \ + "*count: 0 \n" \ + "*showFPS: False \n" \ + "*wireframe: False \n" \ + +# define refresh_gears 0 +# define release_gears 0 +#undef countof +#define countof(x) (sizeof((x))/sizeof((*x))) + +#include "xlockmore.h" +#include "involute.h" +#include "normals.h" +#include "tube.h" +#include "rotator.h" +#include "gltrackball.h" +#include + +#ifdef USE_GL /* whole file */ + +#undef BELLRAND +#define BELLRAND(n) ((frand((n)) + frand((n)) + frand((n))) / 3) + +#define DEF_SPIN "True" +#define DEF_WANDER "True" +#define DEF_SPEED "1.0" + +typedef struct { + GLXContext *glx_context; + rotator *rot; + trackball_state *trackball; + Bool button_down_p; + Bool planetary_p; + + int ngears; + gear **gears; + + GLuint armature_dlist; + int armature_polygons; + + struct { GLfloat x1, y1, x2, y2; } bbox; + +} gears_configuration; + +static gears_configuration *bps = NULL; + +static Bool do_spin; +static GLfloat speed; +static Bool do_wander; + +static XrmOptionDescRec opts[] = { + { "-spin", ".spin", XrmoptionNoArg, "True" }, + { "+spin", ".spin", XrmoptionNoArg, "False" }, + { "-speed", ".speed", XrmoptionSepArg, 0 }, + { "-wander", ".wander", XrmoptionNoArg, "True" }, + { "+wander", ".wander", XrmoptionNoArg, "False" }, +}; + +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}, +}; + +ENTRYPOINT ModeSpecOpt gears_opts = {countof(opts), opts, countof(vars), vars, NULL}; + + +/* Window management, etc + */ +ENTRYPOINT void +reshape_gears (ModeInfo *mi, int width, int height) +{ + GLfloat h = (GLfloat) height / (GLfloat) width; + + glViewport (0, 0, (GLint) width, (GLint) height); + + glMatrixMode(GL_PROJECTION); + glLoadIdentity(); + gluPerspective (30.0, 1/h, 1.0, 100.0); + + glMatrixMode(GL_MODELVIEW); + glLoadIdentity(); + gluLookAt( 0.0, 0.0, 30.0, + 0.0, 0.0, 0.0, + 0.0, 1.0, 0.0); + + glClear(GL_COLOR_BUFFER_BIT); +} + + +ENTRYPOINT Bool +gears_handle_event (ModeInfo *mi, XEvent *event) +{ + gears_configuration *bp = &bps[MI_SCREEN(mi)]; + + if (event->xany.type == ButtonPress && + event->xbutton.button == Button1) + { + bp->button_down_p = True; + gltrackball_start (bp->trackball, + event->xbutton.x, event->xbutton.y, + MI_WIDTH (mi), MI_HEIGHT (mi)); + return True; + } + else if (event->xany.type == ButtonRelease && + event->xbutton.button == Button1) + { + bp->button_down_p = False; + return True; + } + else if (event->xany.type == ButtonPress && + (event->xbutton.button == Button4 || + event->xbutton.button == Button5 || + event->xbutton.button == Button6 || + event->xbutton.button == Button7)) + { + gltrackball_mousewheel (bp->trackball, event->xbutton.button, 10, + !!event->xbutton.state); + return True; + } + else if (event->xany.type == MotionNotify && + bp->button_down_p) + { + gltrackball_track (bp->trackball, + event->xmotion.x, event->xmotion.y, + MI_WIDTH (mi), MI_HEIGHT (mi)); + return True; + } + + return False; +} + + + +static void +free_gear (gear *g) +{ + if (g->dlist) + glDeleteLists (g->dlist, 1); + free (g); +} + + +/* Create and return a new gear sized for placement next to or on top of + the given parent gear (if any.) Returns 0 if out of memory. + [Mostly lifted from pinion.c] + */ +static gear * +new_gear (ModeInfo *mi, gear *parent) +{ + gears_configuration *bp = &bps[MI_SCREEN(mi)]; + gear *g = (gear *) calloc (1, sizeof (*g)); + static unsigned long id = 0; /* only used in debugging output */ + + if (!g) return 0; + g->id = ++id; + + /* Pick the size of the teeth. + */ + if (parent) /* adjascent gears need matching teeth */ + { + g->tooth_w = parent->tooth_w; + g->tooth_h = parent->tooth_h; + g->tooth_slope = -parent->tooth_slope; + } + else /* gears that begin trains get any size they want */ + { + g->tooth_w = 0.007 * (1.0 + BELLRAND(4.0)); + g->tooth_h = 0.005 * (1.0 + BELLRAND(8.0)); +/* + g->tooth_slope = ((random() % 8) + ? 0 + : 0.5 + BELLRAND(1)); + */ + } + + /* Pick the number of teeth, and thus, the radius. + */ + { + double c; + + if (!parent || bp->ngears > 4) + g->nteeth = 5 + BELLRAND (20); + else + g->nteeth = parent->nteeth * (0.5 + BELLRAND(2)); + + c = g->nteeth * g->tooth_w * 2; /* circumference = teeth + gaps */ + g->r = c / (M_PI * 2); /* c = 2 pi r */ + } + + g->thickness = g->tooth_w + frand (g->r); + g->thickness2 = g->thickness * 0.7; + g->thickness3 = g->thickness; + + /* Colorize + */ + g->color[0] = 0.5 + frand(0.5); + g->color[1] = 0.5 + frand(0.5); + g->color[2] = 0.5 + frand(0.5); + g->color[3] = 1.0; + + g->color2[0] = g->color[0] * 0.85; + g->color2[1] = g->color[1] * 0.85; + g->color2[2] = g->color[2] * 0.85; + g->color2[3] = g->color[3]; + + + /* Decide on shape of gear interior: + - just a ring with teeth; + - that, plus a thinner in-set "plate" in the middle; + - that, plus a thin raised "lip" on the inner plate; + - or, a wide lip (really, a thicker third inner plate.) + */ + if ((random() % 10) == 0) + { + /* inner_r can go all the way in; there's no inset disc. */ + g->inner_r = (g->r * 0.1) + frand((g->r - g->tooth_h/2) * 0.8); + g->inner_r2 = 0; + g->inner_r3 = 0; + } + else + { + /* inner_r doesn't go in very far; inner_r2 is an inset disc. */ + g->inner_r = (g->r * 0.5) + frand((g->r - g->tooth_h) * 0.4); + g->inner_r2 = (g->r * 0.1) + frand(g->inner_r * 0.5); + g->inner_r3 = 0; + + if (g->inner_r2 > (g->r * 0.2)) + { + int nn = (random() % 10); + if (nn <= 2) + g->inner_r3 = (g->r * 0.1) + frand(g->inner_r2 * 0.2); + else if (nn <= 7 && g->inner_r2 >= 0.1) + g->inner_r3 = g->inner_r2 - 0.01; + } + } + + /* If we have three discs, sometimes make the middle disc be spokes. + */ + if (g->inner_r3 && ((random() % 5) == 0)) + { + g->spokes = 2 + BELLRAND (5); + g->spoke_thickness = 1 + frand(7.0); + if (g->spokes == 2 && g->spoke_thickness < 2) + g->spoke_thickness += 1; + } + + /* Sometimes add little nubbly bits, if there is room. + */ + if (g->nteeth > 5) + { + double size = 0; + involute_biggest_ring (g, 0, &size, 0); + if (size > g->r * 0.2 && (random() % 5) == 0) + { + g->nubs = 1 + (random() % 16); + if (g->nubs > 8) g->nubs = 1; + } + } + + if (g->inner_r3 > g->inner_r2) abort(); + if (g->inner_r2 > g->inner_r) abort(); + if (g->inner_r > g->r) abort(); + + /* Decide how complex the polygon model should be. + */ + { + double pix = g->tooth_h * MI_HEIGHT(mi); /* approx. tooth size in pixels */ + if (pix <= 2.5) g->size = INVOLUTE_SMALL; + else if (pix <= 3.5) g->size = INVOLUTE_MEDIUM; + else g->size = INVOLUTE_LARGE; + } + + g->base_p = !parent; + + return g; +} + + +/* Given a newly-created gear, place it next to its parent in the scene, + with its teeth meshed and the proper velocity. Returns False if it + didn't work. (Call this a bunch of times until either it works, or + you decide it's probably not going to.) + [Mostly lifted from pinion.c] + */ +static Bool +place_gear (ModeInfo *mi, gear *g, gear *parent) +{ + gears_configuration *bp = &bps[MI_SCREEN(mi)]; + + /* Compute this gear's velocity. + */ + if (! parent) + { + g->ratio = 0.8 + BELLRAND(0.4); /* 0.8-1.2 = 8-12rpm @ 60fps */ + g->th = 1; /* not 0 */ + } + else + { + /* Gearing ratio is the ratio of the number of teeth to previous gear + (which is also the ratio of the circumferences.) + */ + g->ratio = (double) parent->nteeth / (double) g->nteeth; + + /* Set our initial rotation to match that of the previous gear, + multiplied by the gearing ratio. (This is finessed later, + once we know the exact position of the gear relative to its + parent.) + */ + g->th = -(parent->th * g->ratio); + + if (g->nteeth & 1) /* rotate 1/2 tooth-size if odd number of teeth */ + { + double off = (180.0 / g->nteeth); + if (g->th > 0) + g->th += off; + else + g->th -= off; + } + + /* ratios are cumulative for all gears in the train. */ + g->ratio *= parent->ratio; + } + + + if (parent) /* Place the gear next to the parent. */ + { + double r_off = parent->r + g->r; + int angle; + + angle = (random() % 360) - 180; /* -180 to +180 degrees */ + + g->x = parent->x + (cos ((double) angle * (M_PI / 180)) * r_off); + g->y = parent->y + (sin ((double) angle * (M_PI / 180)) * r_off); + g->z = parent->z; + + /* avoid accidentally changing sign of "th" in the math below. */ + g->th += (g->th > 0 ? 360 : -360); + + /* Adjust the rotation of the gear so that its teeth line up with its + parent, based on the position of the gear and the current rotation + of the parent. + */ + { + double p_c = 2 * M_PI * parent->r; /* circumference of parent */ + double g_c = 2 * M_PI * g->r; /* circumference of g */ + + double p_t = p_c * (angle/360.0); /* distance travelled along + circumference of parent when + moving "angle" degrees along + parent. */ + double g_rat = p_t / g_c; /* if travelling that distance + along circumference of g, + ratio of g's circumference + travelled. */ + double g_th = 360.0 * g_rat; /* that ratio in degrees */ + + g->th += angle + g_th; + } + } + + /* If the position we picked for this gear causes it to overlap + with any earlier gear in the train, give up. + */ + { + int i; + + for (i = bp->ngears-1; i >= 0; i--) + { + gear *og = bp->gears[i]; + + if (og == g) continue; + if (og == parent) continue; + if (g->z != og->z) continue; /* Ignore unless on same layer */ + + /* Collision detection without sqrt: + d = sqrt(a^2 + b^2) d^2 = a^2 + b^2 + d < r1 + r2 d^2 < (r1 + r2)^2 + */ + if (((g->x - og->x) * (g->x - og->x) + + (g->y - og->y) * (g->y - og->y)) < + ((g->r + g->tooth_h + og->r + og->tooth_h) * + (g->r + g->tooth_h + og->r + og->tooth_h))) + return False; + } + } + + return True; +} + + +/* Make a new gear, place it next to its parent in the scene, + with its teeth meshed and the proper velocity. Returns the gear; + or 0 if it didn't work. (Call this a bunch of times until either + it works, or you decide it's probably not going to.) + [Mostly lifted from pinion.c] + */ +static gear * +place_new_gear (ModeInfo *mi, gear *parent) +{ + gears_configuration *bp = &bps[MI_SCREEN(mi)]; + int loop_count = 0; + gear *g = 0; + + while (1) + { + loop_count++; + if (loop_count >= 100) + { + if (g) + free_gear (g); + g = 0; + break; + } + + g = new_gear (mi, parent); + if (!g) return 0; /* out of memory? */ + + if (place_gear (mi, g, parent)) + break; + } + + if (! g) return 0; + + /* We got a gear, and it is properly positioned. + Insert it in the scene. + */ + bp->gears[bp->ngears++] = g; + return g; +} + + +static int +arm (GLfloat length, + GLfloat width1, GLfloat height1, + GLfloat width2, GLfloat height2, + Bool wire) +{ + int polys = 0; + glShadeModel(GL_FLAT); + +#if 0 /* don't need these - they're embedded in other objects */ + /* draw end 1 */ + glFrontFace(GL_CW); + glNormal3f(-1, 0, 0); + glBegin(wire ? GL_LINE_LOOP : GL_QUADS); + glVertex3f(-length/2, -width1/2, -height1/2); + glVertex3f(-length/2, width1/2, -height1/2); + glVertex3f(-length/2, width1/2, height1/2); + glVertex3f(-length/2, -width1/2, height1/2); + polys++; + glEnd(); + + /* draw end 2 */ + glFrontFace(GL_CCW); + glNormal3f(1, 0, 0); + glBegin(wire ? GL_LINE_LOOP : GL_QUADS); + glVertex3f(length/2, -width2/2, -height2/2); + glVertex3f(length/2, width2/2, -height2/2); + glVertex3f(length/2, width2/2, height2/2); + glVertex3f(length/2, -width2/2, height2/2); + polys++; + glEnd(); +#endif + + /* draw top */ + glFrontFace(GL_CCW); + glNormal3f(0, 0, -1); + glBegin(wire ? GL_LINE_LOOP : GL_QUADS); + glVertex3f(-length/2, -width1/2, -height1/2); + glVertex3f(-length/2, width1/2, -height1/2); + glVertex3f( length/2, width2/2, -height2/2); + glVertex3f( length/2, -width2/2, -height2/2); + polys++; + glEnd(); + + /* draw bottom */ + glFrontFace(GL_CW); + glNormal3f(0, 0, 1); + glBegin(wire ? GL_LINE_LOOP : GL_QUADS); + glVertex3f(-length/2, -width1/2, height1/2); + glVertex3f(-length/2, width1/2, height1/2); + glVertex3f( length/2, width2/2, height2/2); + glVertex3f( length/2, -width2/2, height2/2); + polys++; + glEnd(); + + /* draw left */ + glFrontFace(GL_CW); + glNormal3f(0, -1, 0); + glBegin(wire ? GL_LINE_LOOP : GL_QUADS); + glVertex3f(-length/2, -width1/2, -height1/2); + glVertex3f(-length/2, -width1/2, height1/2); + glVertex3f( length/2, -width2/2, height2/2); + glVertex3f( length/2, -width2/2, -height2/2); + polys++; + glEnd(); + + /* draw right */ + glFrontFace(GL_CCW); + glNormal3f(0, 1, 0); + glBegin(wire ? GL_LINE_LOOP : GL_QUADS); + glVertex3f(-length/2, width1/2, -height1/2); + glVertex3f(-length/2, width1/2, height1/2); + glVertex3f( length/2, width2/2, height2/2); + glVertex3f( length/2, width2/2, -height2/2); + polys++; + glEnd(); + + glFrontFace(GL_CCW); + + return polys; +} + + +static int +ctube (GLfloat diameter, GLfloat width, Bool wire) +{ + tube (0, 0, width/2, + 0, 0, -width/2, + diameter, 0, + 32, True, True, wire); + return 0; /* #### */ +} + +static void +armature (ModeInfo *mi) +{ + gears_configuration *bp = &bps[MI_SCREEN(mi)]; + int wire = MI_IS_WIREFRAME(mi); + + static const GLfloat spec[4] = {1.0, 1.0, 1.0, 1.0}; + GLfloat shiny = 128.0; + GLfloat color[4]; + + color[0] = 0.5 + frand(0.5); + color[1] = 0.5 + frand(0.5); + color[2] = 0.5 + frand(0.5); + color[3] = 1.0; + + bp->armature_polygons = 0; + + bp->armature_dlist = glGenLists (1); + if (! bp->armature_dlist) + { + check_gl_error ("glGenLists"); + abort(); + } + + glNewList (bp->armature_dlist, GL_COMPILE); + + glMaterialfv (GL_FRONT, GL_SPECULAR, spec); + glMateriali (GL_FRONT, GL_SHININESS, shiny); + glMaterialfv (GL_FRONT, GL_AMBIENT_AND_DIFFUSE, color); + glColor3f (color[0], color[1], color[2]); + + glPushMatrix(); + + { + GLfloat s = bp->gears[0]->r * 2.7; + s = s/5.6; + glScalef (s, s, s); + } + + glTranslatef (0, 0, 1.4 + bp->gears[0]->thickness); + glRotatef (30, 0, 0, 1); + + bp->armature_polygons += ctube (0.5, 10, wire); /* center axle */ + + glPushMatrix(); + glTranslatef(0.0, 4.2, -1); + bp->armature_polygons += ctube (0.5, 3, wire); /* axle 1 */ + glTranslatef(0, 0, 1.8); + bp->armature_polygons += ctube (0.7, 0.7, wire); + glPopMatrix(); + + glPushMatrix(); + glRotatef(120, 0.0, 0.0, 1.0); + glTranslatef(0.0, 4.2, -1); + bp->armature_polygons += ctube (0.5, 3, wire); /* axle 2 */ + glTranslatef(0, 0, 1.8); + bp->armature_polygons += ctube (0.7, 0.7, wire); + glPopMatrix(); + + glPushMatrix(); + glRotatef(240, 0.0, 0.0, 1.0); + glTranslatef(0.0, 4.2, -1); + bp->armature_polygons += ctube (0.5, 3, wire); /* axle 3 */ + glTranslatef(0, 0, 1.8); + bp->armature_polygons += ctube (0.7, 0.7, wire); + glPopMatrix(); + + glTranslatef(0, 0, 1.5); /* center disk */ + bp->armature_polygons += ctube (1.5, 2, wire); + + glPushMatrix(); + glRotatef(270, 0, 0, 1); + glRotatef(-10, 0, 1, 0); + glTranslatef(-2.2, 0, 0); + bp->armature_polygons += arm (4.0, 1.0, 0.5, + 2.0, 1.0, wire); /* arm 1 */ + glPopMatrix(); + + glPushMatrix(); + glRotatef(30, 0, 0, 1); + glRotatef(-10, 0, 1, 0); + glTranslatef(-2.2, 0, 0); + bp->armature_polygons += arm (4.0, 1.0, 0.5, + 2.0, 1.0, wire); /* arm 2 */ + glPopMatrix(); + + glPushMatrix(); + glRotatef(150, 0, 0, 1); + glRotatef(-10, 0, 1, 0); + glTranslatef(-2.2, 0, 0); + bp->armature_polygons += arm (4.0, 1.0, 0.5, + 2.0, 1.0, wire); /* arm 3 */ + glPopMatrix(); + + glPopMatrix(); + + glEndList (); +} + + +static void +planetary_gears (ModeInfo *mi) +{ + gears_configuration *bp = &bps[MI_SCREEN(mi)]; + gear *g0, *g1, *g2, *g3, *g4; + GLfloat distance = 2.02; + + bp->planetary_p = True; + + g0 = new_gear (mi, 0); + g1 = new_gear (mi, 0); + g2 = new_gear (mi, 0); + g3 = new_gear (mi, 0); + g4 = new_gear (mi, 0); + + if (! place_gear (mi, g0, 0)) abort(); + if (! place_gear (mi, g1, 0)) abort(); + if (! place_gear (mi, g2, 0)) abort(); + if (! place_gear (mi, g3, 0)) abort(); + if (! place_gear (mi, g4, 0)) abort(); + + g0->nteeth = 12 + (3 * (random() % 10)); /* must be multiple of 3 */ + g0->tooth_w = g0->r / g0->nteeth; + g0->tooth_h = g0->tooth_w * 2.8; + +# define COPY(F) g4->F = g3->F = g2->F = g1->F = g0->F + COPY(r); + COPY(th); + COPY(nteeth); + COPY(tooth_w); + COPY(tooth_h); + COPY(tooth_slope); + COPY(inner_r); + COPY(inner_r2); + COPY(inner_r3); + COPY(thickness); + COPY(thickness2); + COPY(thickness3); + COPY(ratio); + COPY(size); +# undef COPY + + g1->x = cos (M_PI * 2 / 3) * g1->r * distance; + g1->y = sin (M_PI * 2 / 3) * g1->r * distance; + + g2->x = cos (M_PI * 4 / 3) * g2->r * distance; + g2->y = sin (M_PI * 4 / 3) * g2->r * distance; + + g3->x = cos (M_PI * 6 / 3) * g3->r * distance; + g3->y = sin (M_PI * 6 / 3) * g3->r * distance; + + g4->x = 0; + g4->y = 0; + g4->th = -g3->th; + + /* rotate central gear 1/2 tooth-size if odd number of teeth */ + if (g4->nteeth & 1) + g4->th -= (180.0 / g4->nteeth); + + g0->inverted_p = True; + g0->x = 0; + g0->y = 0; + g0->nteeth = g1->nteeth * 3; + g0->r = g1->r * 3.05; + g0->inner_r = g0->r * 0.8; + g0->inner_r2 = 0; + g0->inner_r3 = 0; + g0->th = g1->th + (180 / g0->nteeth); + g0->ratio = g1->ratio / 3; + + g0->tooth_slope = 0; + g0->nubs = 3; + g0->spokes = 0; + g0->size = INVOLUTE_LARGE; + + bp->gears = (gear **) calloc (6, sizeof(**bp->gears)); + bp->ngears = 0; + + bp->gears[bp->ngears++] = g1; + bp->gears[bp->ngears++] = g2; + bp->gears[bp->ngears++] = g3; + bp->gears[bp->ngears++] = g4; + bp->gears[bp->ngears++] = g0; +} + + + + +ENTRYPOINT void +init_gears (ModeInfo *mi) +{ + gears_configuration *bp; + int wire = MI_IS_WIREFRAME(mi); + int i; + + if (!bps) { + bps = (gears_configuration *) + calloc (MI_NUM_SCREENS(mi), sizeof (gears_configuration)); + if (!bps) { + fprintf(stderr, "%s: out of memory\n", progname); + exit(1); + } + } + + bp = &bps[MI_SCREEN(mi)]; + + bp->glx_context = init_GL(mi); + + reshape_gears (mi, MI_WIDTH(mi), MI_HEIGHT(mi)); + + if (!wire) + { + GLfloat pos[4] = {1.0, 1.0, 1.0, 0.0}; + GLfloat amb[4] = {0.0, 0.0, 0.0, 1.0}; + GLfloat dif[4] = {1.0, 1.0, 1.0, 1.0}; + GLfloat spc[4] = {0.0, 1.0, 1.0, 1.0}; + + glEnable(GL_LIGHTING); + glEnable(GL_LIGHT0); + glEnable(GL_DEPTH_TEST); + glEnable(GL_CULL_FACE); + + glLightfv(GL_LIGHT0, GL_POSITION, pos); + glLightfv(GL_LIGHT0, GL_AMBIENT, amb); + glLightfv(GL_LIGHT0, GL_DIFFUSE, dif); + glLightfv(GL_LIGHT0, GL_SPECULAR, spc); + } + + { + double spin_speed = 0.5; + double wander_speed = 0.01; + double spin_accel = 0.25; + + bp->rot = make_rotator (do_spin ? spin_speed : 0, + do_spin ? spin_speed : 0, + do_spin ? spin_speed : 0, + spin_accel, + do_wander ? wander_speed : 0, + True + ); + bp->trackball = gltrackball_init (); + } + + if (!(random() % 8)) + { + planetary_gears (mi); + } + else + { + gear *g = 0; + int total_gears = MI_COUNT (mi); + int i; + if (total_gears <= 0) + total_gears = 3 + abs (BELLRAND (8) - 4); /* 3 - 7, mostly 3. */ + + bp->gears = (gear **) calloc (total_gears+2, sizeof(**bp->gears)); + bp->ngears = 0; + + for (i = 0; i < total_gears; i++) + g = place_new_gear (mi, g); + } + + + /* Center gears in scene. */ + { + GLfloat minx=99999, miny=99999, maxx=-99999, maxy=-99999; + int i; + for (i = 0; i < bp->ngears; i++) + { + gear *g = bp->gears[i]; + if (g->x - g->r < minx) minx = g->x - g->r; + if (g->x + g->r > maxx) maxx = g->x + g->r; + if (g->y - g->r < miny) miny = g->y - g->r; + if (g->y + g->r > maxy) maxy = g->y + g->r; + } + bp->bbox.x1 = minx; + bp->bbox.y1 = miny; + bp->bbox.x2 = maxx; + bp->bbox.y2 = maxy; + } + + /* Now render each gear into its display list. + */ + for (i = 0; i < bp->ngears; i++) + { + gear *g = bp->gears[i]; + g->dlist = glGenLists (1); + if (! g->dlist) + { + check_gl_error ("glGenLists"); + abort(); + } + + glNewList (g->dlist, GL_COMPILE); + g->polygons += draw_involute_gear (g, wire); + glEndList (); + } + if (bp->planetary_p) + armature (mi); +} + + +ENTRYPOINT void +draw_gears (ModeInfo *mi) +{ + gears_configuration *bp = &bps[MI_SCREEN(mi)]; + Display *dpy = MI_DISPLAY(mi); + Window window = MI_WINDOW(mi); + int i; + + if (!bp->glx_context) + return; + + glXMakeCurrent(MI_DISPLAY(mi), MI_WINDOW(mi), *(bp->glx_context)); + + glShadeModel(GL_SMOOTH); + + glEnable(GL_DEPTH_TEST); + glEnable(GL_NORMALIZE); + glEnable(GL_CULL_FACE); + + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + + glPushMatrix (); + + { + double x, y, z; + get_position (bp->rot, &x, &y, &z, !bp->button_down_p); + glTranslatef ((x - 0.5) * 4, + (y - 0.5) * 4, + (z - 0.5) * 7); + + /* Do it twice because we don't track the device's orientation. */ + glRotatef( current_device_rotation(), 0, 0, 1); + gltrackball_rotate (bp->trackball); + glRotatef(-current_device_rotation(), 0, 0, 1); + + get_rotation (bp->rot, &x, &y, &z, !bp->button_down_p); + + /* add a little rotation for -no-spin mode */ + x -= 0.14; + y -= 0.06; + + 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); + } + + /* Center the scene's bounding box in the window, + and scale it to fit. + */ + { + GLfloat w = bp->bbox.x2 - bp->bbox.x1; + GLfloat h = bp->bbox.y2 - bp->bbox.y1; + GLfloat s = 10.0 / (w > h ? w : h); + glScalef (s, s, s); + glTranslatef (-(bp->bbox.x1 + w/2), + -(bp->bbox.y1 + h/2), + 0); + } + + mi->polygon_count = 0; + + for (i = 0; i < bp->ngears; i++) + { + gear *g = bp->gears[i]; + + glPushMatrix(); + + glTranslatef (g->x, g->y, g->z); + glRotatef (g->th, 0, 0, 1); + + glCallList (g->dlist); + mi->polygon_count += g->polygons; + + glPopMatrix (); + } + + if (bp->planetary_p) + { + glCallList (bp->armature_dlist); + mi->polygon_count += bp->armature_polygons; + } + + glPopMatrix (); + + /* spin gears */ + if (!bp->button_down_p) + for (i = 0; i < bp->ngears; i++) + { + gear *g = bp->gears[i]; + double off = g->ratio * 5 * speed; + if (g->th > 0) + g->th += off; + else + g->th -= off; + } + + if (mi->fps_p) do_fps (mi); + glFinish(); + + glXSwapBuffers(dpy, window); +} + +XSCREENSAVER_MODULE ("Gears", gears) + +#endif /* USE_GL */ diff --git a/hacks/glx/gears.man b/hacks/glx/gears.man new file mode 100644 index 00000000..a54a6afc --- /dev/null +++ b/hacks/glx/gears.man @@ -0,0 +1,79 @@ +.TH XScreenSaver 1 "" "X Version 11" +.SH NAME +gears - draw interlocking gears, for xscreensaver. +.SH SYNOPSIS +.B gears +[\-display \fIhost:display.screen\fP] [\-window] [\-root] [\-install] +[\-visual \fIvisual\fP] +[\-delay \fIusecs\fP] +[\-speed \fIfloat\fP] +[\-no\-spin] +[\-no\-wander] +[-count \fIinteger\fP] +[-wireframe] +[-fps] +.SH DESCRIPTION +This draws a set of rotating gears. +.SH OPTIONS +.I gears +accepts the following options: +.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 \-install +Install a private colormap for the window. +.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 \-delay \fIusecs\fP +The delay between frames of the animation, in microseconds. +Default: 30000 (0.03 seconds.) +.TP 8 +.B \-speed \fIfloat\fP +Larger numbers mean run faster. Default: 1.0. +.TP 8 +.B \-no\-spin +Don't rotate the object. +.TP 8 +.B \-no\-wander +Don't wander the object around the screen. +.TP 8 +.B \-count \fIinteger\fP +How many gears to draw. Default: 0 for random. +.TP 8 +.B \-wireframe +Render in wireframe instead of solid. +.TP 8 +.B \-fps +Display the current frame rate, CPU load, and polygon count. +.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 2007 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. + +An earlier version of this program by Brian Paul was written in 1997; +this version was rewritten from scratch by jwz in 2007. diff --git a/hacks/glx/gflux.c b/hacks/glx/gflux.c new file mode 100644 index 00000000..f3829b59 --- /dev/null +++ b/hacks/glx/gflux.c @@ -0,0 +1,838 @@ +/* -*- Mode: C; tab-width: 4 -*- emacs friendly */ +/* gflux - creates a fluctuating 3D grid + * requires OpenGL or MesaGL + * + * Copyright (c) Josiah Pease, 2000, 2003 + * 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. + * + * Thanks go to all those who worked on... + * MesaGL, OpenGL, UtahGLX, XFree86, gcc, vim, rxvt, the PNM (anymap) format + * xscreensaver and the thousands of other tools, apps and daemons that make + * linux usable + * Personal thanks to Kevin Moss, Paul Sheahee and Jamie Zawinski + * + * some xscreensaver code lifted from superquadrics. Most other glx hacks + * used as reference at some time. + * + * This hack and others can cause UtahGLX to crash my X server + * wireframe looks good with software only rendering anyway + * If anyone can work out why and supply a fix I'd love to hear from them + * + * Josiah Pease 21 July 2000 + * + * History + * 10 June 2000 : wireframe rippling grid standalone written + * 18 June 2000 : xscreensaver code added + * 25 June 2000 : solid and light added + * 04 July 2000 : majour bug hunt, xscreensaver code rewritten + * 08 July 2000 : texture mapping, rotation and zoom added + * 21 July 2000 : cleaned up code from bug hunts, manpage written + * 24 November 2000 : fixed x co-ord calculation in solid - textured + * 05 March 2001 : put back non pnmlib code with #ifdefs + * 11 May 2002 : fixed image problems with large images + */ + + +#ifdef STANDALONE +#define DEFAULTS "*delay: 20000\n" \ + "*showFPS: False\n" \ + "*mode: light\n" \ + "*useSHM: True \n" + + +# define refresh_gflux 0 +# include "xlockmore.h" /* from the xscreensaver distribution */ +#else /* !STANDALONE */ +# include "xlock.h" /* from the xlockmore distribution */ +#endif /* !STANDALONE */ + +#ifdef USE_GL /* whole file */ + +#ifdef HAVE_XMU +# ifndef VMS +# include +#else /* VMS */ +# include +# endif /* VMS */ +#endif + +#undef countof +#define countof(x) (sizeof((x))/sizeof((*x))) + +#include +#include + +#include + +#include "grab-ximage.h" +#include "gltrackball.h" + + +static enum {wire=0,solid,light,checker,grab} _draw; + +# define DEF_SQUARES "19" +# define DEF_RESOLUTION "4" +# define DEF_DRAW "2" +# define DEF_FLAT "0" +# define DEF_SPEED "0.05" +# define DEF_ROTATIONX "0.01" +# define DEF_ROTATIONY "0.0" +# define DEF_ROTATIONZ "0.1" +# define DEF_WAVES "3" +# define DEF_WAVE_CHANGE "50" +# define DEF_WAVE_HEIGHT "1.0" +# define DEF_WAVE_FREQ "3.0" +# define DEF_ZOOM "1.0" + + + +static int _squares; /* grid size */ +static int _resolution; /* wireframe resolution */ +static int _flat; + +static float _speed; +static float _rotationx; +static float _rotationy; +static float _rotationz; +static float _zoom; + +static int _waves; +static int _waveChange; +static float _waveHeight; +static float _waveFreq; + + +#define WIDTH 320 +#define HEIGHT 240 + +static XrmOptionDescRec opts[] = { + {"-squares", ".gflux.squares", XrmoptionSepArg, 0}, + {"-resolution", ".gflux.resolution", XrmoptionSepArg, 0}, +/* {"-draw", ".gflux.draw", XrmoptionSepArg, 0},*/ + {"-mode", ".gflux.mode", XrmoptionSepArg, 0}, + {"-wireframe", ".gflux.mode", XrmoptionNoArg, "wire"}, + {"-flat", ".gflux.flat", XrmoptionSepArg, 0}, + {"-speed", ".gflux.speed", XrmoptionSepArg, 0}, + {"-rotationx", ".gflux.rotationx", XrmoptionSepArg, 0}, + {"-rotationy", ".gflux.rotationy", XrmoptionSepArg, 0}, + {"-rotationz", ".gflux.rotationz", XrmoptionSepArg, 0}, + {"-waves", ".gflux.waves", XrmoptionSepArg, 0}, + {"-waveChange", ".gflux.waveChange", XrmoptionSepArg, 0}, + {"-waveHeight", ".gflux.waveHeight", XrmoptionSepArg, 0}, + {"-waveFreq", ".gflux.waveFreq", XrmoptionSepArg, 0}, + {"-zoom", ".gflux.zoom", XrmoptionSepArg, 0}, +}; + + +static argtype vars[] = { + {&_squares, "squares", "Squares", DEF_SQUARES, t_Int}, + {&_resolution, "resolution", "Resolution", DEF_RESOLUTION, t_Int}, +/* {&_draw, "draw", "Draw", DEF_DRAW, t_Int},*/ + {&_flat, "flat", "Flat", DEF_FLAT, t_Int}, + {&_speed, "speed", "Speed", DEF_SPEED, t_Float}, + {&_rotationx, "rotationx", "Rotationx", DEF_ROTATIONX, t_Float}, + {&_rotationy, "rotationy", "Rotationy", DEF_ROTATIONY, t_Float}, + {&_rotationz, "rotationz", "Rotationz", DEF_ROTATIONZ, t_Float}, + {&_waves, "waves", "Waves", DEF_WAVES, t_Int}, + {&_waveChange, "waveChange", "WaveChange", DEF_WAVE_CHANGE, t_Int}, + {&_waveHeight, "waveHeight", "WaveHeight", DEF_WAVE_HEIGHT, t_Float}, + {&_waveFreq, "waveFreq", "WaveFreq", DEF_WAVE_FREQ, t_Float}, + {&_zoom, "zoom", "Zoom", DEF_ZOOM, t_Float}, +}; + + +static OptionStruct desc[] = +{ + {"-squares num", "size of grid in squares (19)"}, + {"-resolution num", "detail of lines making grid, wireframe only (4)"}, +/* {"-draw num", "draw method to use: 0=wireframe 1=solid 2=lit (0)"},*/ + {"-flat num", "shading method, not wireframe: 0=smooth 1=flat (0)"}, + {"-speed num", "speed of waves (0.05)"}, + {"-rotationx num", "speed of xrotation (0.01)"}, + {"-rotationy num", "speed of yrotation (0.00)"}, + {"-rotationz num", "speed of zrotation (0.10)"}, + {"-waves num", "number of simultanious waves (3)"}, + {"-waveChange num", "number of cyles for a wave to change (50)"}, + {"-waveHeight num", "height of waves (1.0)"}, + {"-waveFreq num", "max frequency of a wave (3.0)"}, + {"-zoom num", "camera control (1.0)"}, +}; + +ENTRYPOINT ModeSpecOpt gflux_opts = {countof(opts), opts, countof(vars), vars, desc}; + +#ifdef USE_MODULES +ModStruct gflux_description = +{"gflux", "init_gflux", "draw_gflux", "release_gflux", + "draw_gflux", "init_gflux", NULL, &gflux_opts, + 1000, 1, 2, 1, 4, 1.0, "", + "GFlux: an OpenGL gflux", 0, NULL}; +#endif + +/* structure for holding the gflux data */ +typedef struct gfluxstruct { + ModeInfo *modeinfo; + int screen_width, screen_height; + GLXContext *glx_context; + Window window; + XColor fg, bg; +#define MAXWAVES 10 /* should be dynamic */ + double wa[MAXWAVES]; + double freq[MAXWAVES]; + double dispy[MAXWAVES]; + double dispx[MAXWAVES]; + GLfloat colour[3]; + GLuint texName; + GLfloat tex_xscale; + GLfloat tex_yscale; + XRectangle img_geom; + int img_width, img_height; + int (*drawFunc)(struct gfluxstruct *); + + trackball_state *trackball; + Bool button_down_p; + + double time; + double anglex; + double angley; + double anglez; + + int counter; + int newWave; + + Bool mipmap_p; + Bool waiting_for_image_p; + +} gfluxstruct; +static gfluxstruct *gfluxes = NULL; + +/* prototypes */ +static void initLighting(void); +static void grabTexture(gfluxstruct *); +static void createTexture(gfluxstruct *); +static int displaySolid(gfluxstruct *); /* drawFunc implementations */ +static int displayLight(gfluxstruct *); +static int displayTexture(gfluxstruct *); +static int displayWire(gfluxstruct *); +static void calcGrid(gfluxstruct *); +static double getGrid(gfluxstruct *,double,double,double); + +/* as macro for speed */ +/* could do with colour cycling here */ +/* void genColour(double);*/ +#define genColour(X) \ +{\ + gp->colour[0] = 0.0;\ + gp->colour[1] = 0.5+0.5*(X);\ + gp->colour[2] = 0.5-0.5*(X);\ +} + +/* BEGINNING OF FUNCTIONS */ + + +ENTRYPOINT Bool +gflux_handle_event (ModeInfo *mi, XEvent *event) +{ + gfluxstruct *gp = &gfluxes[MI_SCREEN(mi)]; + + if (event->xany.type == ButtonPress && + event->xbutton.button == Button1) + { + gp->button_down_p = True; + gltrackball_start (gp->trackball, + event->xbutton.x, event->xbutton.y, + MI_WIDTH (mi), MI_HEIGHT (mi)); + return True; + } + else if (event->xany.type == ButtonRelease && + event->xbutton.button == Button1) + { + gp->button_down_p = False; + return True; + } + else if (event->xany.type == ButtonPress && + (event->xbutton.button == Button4 || + event->xbutton.button == Button5 || + event->xbutton.button == Button6 || + event->xbutton.button == Button7)) + { + gltrackball_mousewheel (gp->trackball, event->xbutton.button, 10, + !!event->xbutton.state); + return True; + } + else if (event->xany.type == MotionNotify && + gp->button_down_p) + { + gltrackball_track (gp->trackball, + event->xmotion.x, event->xmotion.y, + MI_WIDTH (mi), MI_HEIGHT (mi)); + return True; + } + + return False; +} + + +static void +userRot(gfluxstruct *gp) +{ + /* Do it twice because we don't track the device's orientation. */ + glRotatef( current_device_rotation(), 0, 0, 1); + gltrackball_rotate (gp->trackball); + glRotatef(-current_device_rotation(), 0, 0, 1); +} + +/* draw the gflux once */ +ENTRYPOINT void draw_gflux(ModeInfo * mi) +{ + gfluxstruct *gp = &gfluxes[MI_SCREEN(mi)]; + Display *display = MI_DISPLAY(mi); + Window window = MI_WINDOW(mi); + + if (!gp->glx_context) return; + + /* Just keep running before the texture has come in. */ + /* if (gp->waiting_for_image_p) return; */ + + glXMakeCurrent(display, window, *(gp->glx_context)); + + calcGrid(gp); + mi->polygon_count = gp->drawFunc(gp); + if (mi->fps_p) do_fps (mi); + glXSwapBuffers(display, window); +} + + +/* reset the projection matrix */ +static void resetProjection(void) +{ + glMatrixMode(GL_PROJECTION); + glLoadIdentity(); + glFrustum(-_zoom,_zoom,-0.8*_zoom,0.8*_zoom,2,6); + glTranslatef(0.0,0.0,-4.0); + glMatrixMode(GL_MODELVIEW); + glLoadIdentity(); +} + +/* Standard reshape function */ +ENTRYPOINT void +reshape_gflux(ModeInfo *mi, int width, int height) +{ + glViewport( 0, 0, width, height ); + resetProjection(); +} + + +/* main OpenGL initialization routine */ +static void initializeGL(ModeInfo *mi, GLsizei width, GLsizei height) +{ + gfluxstruct *gp = &gfluxes[MI_SCREEN(mi)]; + + reshape_gflux(mi, width, height); + glViewport( 0, 0, width, height ); + + gp->tex_xscale = 1.0; /* maybe changed later */ + gp->tex_yscale = 1.0; + + switch(_draw) { + case solid : + gp->drawFunc = (displaySolid); + glEnable(GL_DEPTH_TEST); + break; + case light : + gp->drawFunc = (displayLight); + glEnable(GL_DEPTH_TEST); + initLighting(); + break; + case checker : + gp->drawFunc = (displayTexture); + glEnable(GL_DEPTH_TEST); + createTexture(gp); + initLighting(); + break; + case grab : + gp->drawFunc = (displayTexture); + glEnable(GL_DEPTH_TEST); + grabTexture(gp); + initLighting(); + break; + case wire : + default : + gp->drawFunc = (displayWire); + glDisable(GL_DEPTH_TEST); + break; + } + + if(_flat) glShadeModel(GL_FLAT); + else glShadeModel(GL_SMOOTH); + +} + + +/* xgflux initialization routine */ +ENTRYPOINT void init_gflux(ModeInfo * mi) +{ + int screen = MI_SCREEN(mi); + gfluxstruct *gp; + + if (gfluxes == NULL) { + if ((gfluxes = (gfluxstruct *) + calloc(MI_NUM_SCREENS(mi), sizeof (gfluxstruct))) == NULL) + return; + } + gp = &gfluxes[screen]; + + gp->trackball = gltrackball_init (); + + gp->time = frand(1000.0); /* don't run two screens in lockstep */ + + { + char *s = get_string_resource (mi->dpy, "mode", "Mode"); + if (!s || !*s) _draw = wire; + else if (!strcasecmp (s, "wire")) _draw = wire; + else if (!strcasecmp (s, "solid")) _draw = solid; + else if (!strcasecmp (s, "light")) _draw = light; + else if (!strcasecmp (s, "checker")) _draw = checker; + else if (!strcasecmp (s, "grab")) _draw = grab; + else + { + fprintf (stderr, + "%s: mode must be one of: wire, solid, " + "light, checker, or grab; not \"%s\"\n", + progname, s); + exit (1); + } + } + + gp->modeinfo = mi; + gp->window = MI_WINDOW(mi); + if ((gp->glx_context = init_GL(mi)) != NULL) { + reshape_gflux(mi, MI_WIDTH(mi), MI_HEIGHT(mi)); + initializeGL(mi, MI_WIDTH(mi), MI_HEIGHT(mi)); + } else { + MI_CLEARWINDOW(mi); + } +} + +/* cleanup code */ +ENTRYPOINT void release_gflux(ModeInfo * mi) +{ + if (gfluxes != NULL) { + free((void *) gfluxes); + gfluxes = NULL; + } + FreeAllGL(mi); +} + + +static void createTexture(gfluxstruct *gp) +{ + int size = 4; + unsigned int data[] = { 0xFFFFFFFF, 0xAAAAAAAA, 0xFFFFFFFF, 0xAAAAAAAA, + 0xAAAAAAAA, 0xFFFFFFFF, 0xAAAAAAAA, 0xFFFFFFFF, + 0xFFFFFFFF, 0xAAAAAAAA, 0xFFFFFFFF, 0xAAAAAAAA, + 0xAAAAAAAA, 0xFFFFFFFF, 0xAAAAAAAA, 0xFFFFFFFF }; + + gp->tex_xscale = size; + gp->tex_yscale = size; + + glGenTextures (1, &gp->texName); + glBindTexture (GL_TEXTURE_2D, gp->texName); + + glTexImage2D (GL_TEXTURE_2D, 0, 3, size, size, 0, + GL_RGBA, GL_UNSIGNED_BYTE, data); + + glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); +} + + +static void +image_loaded_cb (const char *filename, XRectangle *geometry, + int image_width, int image_height, + int texture_width, int texture_height, + void *closure) +{ + gfluxstruct *gp = (gfluxstruct *) closure; + gp->img_geom = *geometry; + + gp->tex_xscale = (GLfloat) image_width / texture_width; + gp->tex_yscale = -(GLfloat) image_height / texture_height; + gp->img_width = image_width; + gp->img_height = image_height; + + glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, + (gp->mipmap_p ? GL_LINEAR_MIPMAP_LINEAR : GL_LINEAR)); + + gp->waiting_for_image_p = False; +} + +static void +grabTexture(gfluxstruct *gp) +{ + if (MI_IS_WIREFRAME(gp->modeinfo)) + return; + + gp->waiting_for_image_p = True; + gp->mipmap_p = True; + load_texture_async (gp->modeinfo->xgwa.screen, gp->modeinfo->window, + *gp->glx_context, 0, 0, gp->mipmap_p, gp->texName, + image_loaded_cb, gp); +} + + +static void initLighting(void) +{ + static const float ambientA[] = {0.0, 0.0, 0.0, 1.0}; + static const float diffuseA[] = {1.0, 1.0, 1.0, 1.0}; + static const float positionA[] = {5.0, 5.0, 15.0, 1.0}; + + static const float front_mat_shininess[] = {30.0}; + static const float front_mat_specular[] = {0.5, 0.5, 0.5, 1.0}; + + static const float mat_diffuse[] = {0.5, 0.5, 0.5, 1.0}; + + glMaterialfv(GL_FRONT, GL_SHININESS, front_mat_shininess); + glMaterialfv(GL_FRONT, GL_SPECULAR, front_mat_specular); + + glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, mat_diffuse); + + glLightfv(GL_LIGHT0, GL_AMBIENT, ambientA); + glLightfv(GL_LIGHT0, GL_DIFFUSE, diffuseA); + glLightfv(GL_LIGHT0, GL_POSITION, positionA); + glEnable(GL_LIGHTING); + glEnable(GL_LIGHT0); + glLightModelf(GL_LIGHT_MODEL_TWO_SIDE,1); + + glEnable(GL_NORMALIZE); /* would it be faster ... */ + glEnable(GL_COLOR_MATERIAL); + glColorMaterial(GL_FRONT_AND_BACK,GL_AMBIENT_AND_DIFFUSE); +} + +/************************************/ +/* draw implementations */ +/* somewhat inefficient since they */ +/* all calculate previously */ +/* calculated values again */ +/* storing the values in an array */ +/* is a posibility */ +/************************************/ +static int displayTexture(gfluxstruct *gp) +{ + int polys = 0; + double x,y,u,v; + double z; + double dx = 2.0/((double)_squares); + double dy = 2.0/((double)_squares); + + double du = 2.0/((double)_squares); + double dv = 2.0/((double)_squares); + + double xs = gp->tex_xscale; + double ys = gp->tex_yscale; + + double minx, miny, maxx, maxy; + double minu, minv; + +#if 0 + minx = (GLfloat) gp->img_geom.x / gp->img_width; + miny = (GLfloat) gp->img_geom.y / gp->img_height; + maxx = ((GLfloat) (gp->img_geom.x + gp->img_geom.width) / + gp->img_width); + maxy = ((GLfloat) (gp->img_geom.y + gp->img_geom.height) / + gp->img_height); + minu = minx; + minv = miny; + minx = (minx * 2) - 1; + miny = (miny * 2) - 1; + maxx = (maxx * 2) - 1; + maxy = (maxy * 2) - 1; +#else + minx = -1; + miny = -1; + maxx = 1; + maxy = 1; + minv = 0; + minu = 0; +#endif + + glMatrixMode (GL_TEXTURE); + glLoadIdentity (); + glTranslatef(-1,-1,0); + glScalef(0.5,0.5,1); + glMatrixMode (GL_MODELVIEW); + + glLoadIdentity(); + userRot(gp); + glRotatef(gp->anglex,1,0,0); + glRotatef(gp->angley,0,1,0); + glRotatef(gp->anglez,0,0,1); + glScalef(1,1,(GLfloat)_waveHeight); + glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT); + glEnable(GL_TEXTURE_2D); + + clear_gl_error(); + glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); + glBindTexture(GL_TEXTURE_2D, gp->texName); + check_gl_error("texture binding"); + + glColor3f(0.5,0.5,0.5); + + for(x = minx, u = minu; x < maxx - 0.01; x += dx, u += du) { + glBegin(GL_QUAD_STRIP); + for (y = miny, v = minv; y <= maxy + 0.01; y += dy, v += dv) { + z = getGrid(gp,x,y,gp->time); + glTexCoord2f(u*xs,v*ys); + glNormal3f( + getGrid(gp,x+dx,y,gp->time)-getGrid(gp, x-dx,y,gp->time), + getGrid(gp,x,y+dy,gp->time)-getGrid(gp, x,y-dy,gp->time), + 1 + ); + glVertex3f(x,y,z); + + z = getGrid(gp,x+dx,y,gp->time); + glTexCoord2f((u+du)*xs,v*ys); + glNormal3f( + getGrid(gp,x+dx+dx,y,gp->time)-getGrid(gp, x,y,gp->time), + getGrid(gp,x+dx,y+dy,gp->time)-getGrid(gp, x+dx,y-dy,gp->time), + 1 + ); + glVertex3f(x+dx,y,z); + polys++; + } + glEnd(); + } + + /* Draw a border around the grid. + */ + glColor3f(0.4, 0.4, 0.4); + glDisable(GL_TEXTURE_2D); + glEnable (GL_LINE_SMOOTH); + + glBegin(GL_LINE_LOOP); + y = miny; + for (x = minx; x <= maxx; x += dx) { + glVertex3f (x, y, getGrid (gp, x, y, gp->time)); + polys++; + } + x = maxx; + for (y = miny; y <= maxy; y += dy) { + glVertex3f (x, y, getGrid (gp, x, y, gp->time)); + polys++; + } + y = maxy; + for (x = maxx; x >= minx; x -= dx) { + glVertex3f (x, y, getGrid (gp, x, y, gp->time)); + polys++; + } + x = minx; + for (y = maxy; y >= miny; y -= dy) { + glVertex3f (x, y, getGrid (gp, x, y, gp->time)); + polys++; + } + glEnd(); + glEnable(GL_TEXTURE_2D); + + if (! gp->button_down_p) { + gp->time -= _speed; + gp->anglex -= _rotationx; + gp->angley -= _rotationy; + gp->anglez -= _rotationz; + } + return polys; +} + +static int displaySolid(gfluxstruct *gp) +{ + int polys = 0; + double x,y; + double z; + double dx = 2.0/((double)_squares); + double dy = 2.0/((double)_squares); + + glLoadIdentity(); + glRotatef(gp->anglex,1,0,0); + glRotatef(gp->angley,0,1,0); + glRotatef(gp->anglez,0,0,1); + userRot(gp); + glScalef(1,1,(GLfloat)_waveHeight); + glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT); + + for(x=-1;x<0.9999;x+=dx) { + glBegin(GL_QUAD_STRIP); + for(y=-1;y<=1;y+=dy) { + z = getGrid(gp, x,y,gp->time); + genColour(z); + glColor3fv(gp->colour); + glVertex3f(x,y,z); + + z = getGrid(gp, x+dx,y,gp->time); + genColour(z); + glColor3fv(gp->colour); + glVertex3f(x+dx,y,z); + polys++; + } + glEnd(); + } + + if (! gp->button_down_p) { + gp->time -= _speed; + gp->anglex -= _rotationx; + gp->angley -= _rotationy; + gp->anglez -= _rotationz; + } + + return polys; +} + +static int displayLight(gfluxstruct *gp) +{ + int polys = 0; + double x,y; + double z; + double dx = 2.0/((double)_squares); + double dy = 2.0/((double)_squares); + + glLoadIdentity(); + glRotatef(gp->anglex,1,0,0); + glRotatef(gp->angley,0,1,0); + glRotatef(gp->anglez,0,0,1); + userRot(gp); + glScalef(1,1,(GLfloat)_waveHeight); + glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT); + + for(x=-1;x<0.9999;x+=dx) { + glBegin(GL_QUAD_STRIP); + for(y=-1;y<=1;y+=dy) { + z = getGrid(gp, x,y,gp->time); + genColour(z); + glColor3fv(gp->colour); + glNormal3f( + getGrid(gp, x+dx,y,gp->time)-getGrid(gp, x-dx,y,gp->time), + getGrid(gp, x,y+dy,gp->time)-getGrid(gp, x,y-dy,gp->time), + 1 + ); + glVertex3f(x,y,z); + + z = getGrid(gp, x+dx,y,gp->time); + genColour(z); + glColor3fv(gp->colour); + glNormal3f( + getGrid(gp, x+dx+dx,y,gp->time)-getGrid(gp, x,y,gp->time), + getGrid(gp, x+dx,y+dy,gp->time)-getGrid(gp, x+dx,y-dy,gp->time), + 1 + ); + glVertex3f(x+dx,y,z); + polys++; + } + glEnd(); + } + + if (! gp->button_down_p) { + gp->time -= _speed; + gp->anglex -= _rotationx; + gp->angley -= _rotationy; + gp->anglez -= _rotationz; + } + return polys; +} + +static int displayWire(gfluxstruct *gp) +{ + int polys = 0; + double x,y; + double z; + double dx1 = 2.0/((double)(_squares*_resolution)) - 0.00001; + double dy1 = 2.0/((double)(_squares*_resolution)) - 0.00001; + double dx2 = 2.0/((double)_squares) - 0.00001; + double dy2 = 2.0/((double)_squares) - 0.00001; + + glLoadIdentity(); + glRotatef(gp->anglex,1,0,0); + glRotatef(gp->angley,0,1,0); + glRotatef(gp->anglez,0,0,1); + userRot(gp); + glScalef(1,1,(GLfloat)_waveHeight); + glClear(GL_COLOR_BUFFER_BIT); + + for(x=-1;x<=1;x+=dx2) { + glBegin(GL_LINE_STRIP); + for(y=-1;y<=1;y+=dy1) { + z = getGrid(gp, x,y,gp->time); + genColour(z); + glColor3fv(gp->colour); + glVertex3f(x,y,z); + polys++; + } + glEnd(); + } + for(y=-1;y<=1;y+=dy2) { + glBegin(GL_LINE_STRIP); + for(x=-1;x<=1;x+=dx1) { + z = getGrid(gp, x,y,gp->time); + genColour(z); + glColor3fv(gp->colour); + glVertex3f(x,y,z); + polys++; + } + glEnd(); + } + + if (! gp->button_down_p) { + gp->time -= _speed; + gp->anglex -= _rotationx; + gp->angley -= _rotationy; + gp->anglez -= _rotationz; + } + return polys; +} + +/* generates new ripples */ +static void calcGrid(gfluxstruct *gp) +{ + double tmp; + + if (gp->button_down_p) return; + + tmp = 1.0/((double)_waveChange); + if(!(gp->counter%_waveChange)) { + gp->newWave = ((int)(gp->counter*tmp))%_waves; + gp->dispx[gp->newWave] = -frand(1.0); + gp->dispy[gp->newWave] = -frand(1.0); + gp->freq[gp->newWave] = _waveFreq * frand(1.0); + gp->wa[gp->newWave] = 0.0; + } + gp->counter++; + gp->wa[gp->newWave] += tmp; + gp->wa[(gp->newWave+1)%_waves] -= tmp; +} + +/* returns a height for the grid given time and x,y space co-ords */ +static double getGrid(gfluxstruct *gp, double x, double y, double a) +{ + register int i; + double retval=0.0; + double tmp; + + tmp = 1.0/((float)_waves); + for(i=0;i<_waves;i++) { + retval += gp->wa[i] * tmp * sin( gp->freq[i] + * ( (x+gp->dispx[i]) * (x+gp->dispx[i]) + + (y+gp->dispy[i]) * (y+gp->dispy[i]) +a ) ); + } + return(retval); +} + + +XSCREENSAVER_MODULE ("GFlux", gflux) + +#endif diff --git a/hacks/glx/gflux.man b/hacks/glx/gflux.man new file mode 100644 index 00000000..654aeb46 --- /dev/null +++ b/hacks/glx/gflux.man @@ -0,0 +1,111 @@ +.TH XScreenSaver 1 "May 2004" +.SH NAME +gflux \- rippling surface graphics hack +.SH SYNOPSIS +.B gflux +[\-display \fIhost:display.screen\fP] [\-window] [\-root] [\-install] +[\-visual \fIvisual\fP] [\-delay \fImicroseconds\fP] +[\-squares \fInum\fP] [\-resolution \fInum\fP] [\-mode \fImode\fP] +[\-flat \fInum\fP] [\-speed \fInum\fP] +[\-rotationx \fInum\fP] [\-rotationy \fInum\fP] [\-rotationz \fInum\fP] +[\-waves \fInum\fP] [\-waveChange \fInum\fP] [\-waveHeight \fInum\fP] +[\-waveFreq \fInum\fP] [\-zoom \fInum\fP] +[\-wireframe] +[\-fps] +.SH DESCRIPTION +The \fIgflux\fP program draws a colourfull animated rippling square rotating in 3D space. +.SH OPTIONS +.I gflux +accepts the following options: +.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 \-install +Install a private colormap for the window. +.TP 8 +.B \-visual \fIvisual\fP\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 \-squares \fInum\fP\fP +Specifies the size of the grid in squares. default 19 +.TP 8 +.B \-resolution \fInum\fP\fP +Specifies the wireframe detail of the squares. default 4 +.TP 8 +.B \-mode \fImode\fP\fP +Specifies the draw method: wireframe; solid (meaning a solid colored +surface); light (same as solid, but with lighting effects); +checker (a texture-mapped checkerboard pattern); or grab (meaning +grab an image to manipulate.) + +When grabbing images, the image will be grabbed from the portion of +the screen underlying the window, or from the system's video input, +or from a random file on disk, as indicated by +the \fIgrabDesktopImages\fP, \fIgrabVideoFrames\fP, +and \fIchooseRandomImages\fP options in the \fI~/.xscreensaver\fP +file; see +.BR xscreensaver-demo (1) +for more details. +.TP 8 +.B \-wireframe +Same as "-mode wire". +.TP 8 +.B \-flat \fInum\fP\fP +0 for smooth shading 1 for flat. default 0 +.TP 8 +.B \-speed \fInum\fP\fP +Specifies speed of ripples flowing over the surface. default 0.05 +.TP 8 +.B \-rotationx \fInum\fP \-rotationy \fInum\fP \-rotationz \fInum\fP\fP +Specifies the speed of rotation of the surface in these axis +.TP 8 +.B \-waves \fInum\fP\fP +Specifies the number of ripple centres at any one time. Values should be greater than 1. default 3 +.TP 8 +.B \-waveChange \fInum\fP\fP +Specifies the duration of a ripple centre. after this they fade away to be reborn elsewhere with a different frequency. default 50 +.TP 8 +.B \-waveHeight \fInum\fP\fP +Specifies the height of ripples on the surface. default 1.0 +.TP 8 +.B \-waveFreq \fInum\fP\fP +Specifies the maximum frequency of ripples. default 3.0 +.TP 8 +.B \-zoom \fInum\fP\fP +Specifies the size of the viewport. Smaller values fill the screen with rippling surface. default 1.0 +.TP 8 +.B \-delay \fImicroseconds\fP +How long to pause between frames. Default is 20000, or 0.02 second. +.TP 8 +.B \-fps +Display the current frame rate, CPU load, and polygon count. +.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) +.BR xscreensaver\-demo (1), +.BR xscreensaver\-getimage (1) +.SH COPYRIGHT +Copyright \(co 2000 by Josiah Pease. 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 +Josiah Pease , 10-Jun-2000. + diff --git a/hacks/glx/glblur.c b/hacks/glx/glblur.c new file mode 100644 index 00000000..d65fdacf --- /dev/null +++ b/hacks/glx/glblur.c @@ -0,0 +1,640 @@ +/* glblur --- radial blur using GL textures + * Copyright (c) 2002-2011 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. + * + * This program draws a box and a few line segments, and generates a flowing + * radial blur outward from it -- this causes flowing field effects. + * It does this by rendering the scene into a small texture, then repeatedly + * rendering increasingly-enlarged and increasingly-transparent versions of + * that texture onto the frame buffer. + * + * As such, it's quite graphics intensive -- don't bother trying to run this + * if you don't have hardware-accelerated texture support. + * + * Inspired by Dario Corno's Radial Blur tutorial: + * http://nehe.gamedev.net/tutorials/lesson.asp?l=36 + */ + +#define DEFAULTS "*delay: 10000 \n" \ + "*showFPS: False \n" \ + "*fpsSolid: True \n" + +# define refresh_glblur 0 +# define release_glblur 0 +#undef countof +#define countof(x) (sizeof((x))/sizeof((*x))) + +#undef ABS +#define ABS(n) ((n)<0?-(n):(n)) +#undef SIGNOF +#define SIGNOF(n) ((n)<0?-1:1) + +#include "xlockmore.h" +#include "colors.h" +#include "rotator.h" +#include "gltrackball.h" +#include + +#ifdef USE_GL /* whole file */ + +#define DEF_SPIN "XYZ" +#define DEF_WANDER "True" +#define DEF_BLUR_SIZE "15" + +typedef struct metaball metaball; + + +typedef struct { + GLXContext *glx_context; + rotator *rot; + trackball_state *trackball; + Bool button_down_p; + + GLuint obj_dlist0; /* east-west cube faces */ + GLuint obj_dlist1; /* north-south cube faces */ + GLuint obj_dlist2; /* up-down cube faces */ + GLuint obj_dlist3; /* spikes coming out of the cube's corners */ + GLuint scene_dlist1; /* the cube, rotated and translated */ + GLuint scene_dlist2; /* the spikes, rotated and translated */ + int scene_polys1; /* polygons in scene, not counting texture overlay */ + int scene_polys2; /* polygons in scene, not counting texture overlay */ + + GLuint texture; + unsigned int *tex_data; + int tex_w, tex_h; + + int ncolors; + XColor *colors0; + XColor *colors1; + XColor *colors2; + XColor *colors3; + int ccolor; + + Bool show_cube_p; + Bool show_spikes_p; + +} glblur_configuration; + +static glblur_configuration *bps = NULL; + +static char *do_spin; +static Bool do_wander; +static int blursize; + +static XrmOptionDescRec opts[] = { + { "-spin", ".spin", XrmoptionSepArg, 0 }, + { "+spin", ".spin", XrmoptionNoArg, "" }, + { "-blursize", ".blurSize", XrmoptionSepArg, 0 }, + { "-wander", ".wander", XrmoptionNoArg, "True" }, + { "+wander", ".wander", XrmoptionNoArg, "False" }, +}; + +static argtype vars[] = { + {&do_spin, "spin", "Spin", DEF_SPIN, t_String}, + {&do_wander, "wander", "Wander", DEF_WANDER, t_Bool}, + {&blursize, "blurSize","BlurSize", DEF_BLUR_SIZE, t_Int}, +}; + +ENTRYPOINT ModeSpecOpt glblur_opts = {countof(opts), opts, countof(vars), vars, NULL}; + + +/* Window management, etc + */ +ENTRYPOINT void +reshape_glblur (ModeInfo *mi, int width, int height) +{ + GLfloat h = (GLfloat) height / (GLfloat) width; + + glViewport (0, 0, (GLint) width, (GLint) height); + + glMatrixMode(GL_PROJECTION); + glLoadIdentity(); + gluPerspective (30.0, 1/h, 1.0, 100.0); + + glMatrixMode(GL_MODELVIEW); + glLoadIdentity(); + gluLookAt( 0.0, 0.0, 8.0, + 0.0, 0.0, 0.0, + 0.0, 1.0, 0.0); + + glClear(GL_COLOR_BUFFER_BIT); +} + + + +/* Objects in the scene + */ + +static void +generate_object (ModeInfo *mi) +{ + glblur_configuration *bp = &bps[MI_SCREEN(mi)]; + Bool wire = MI_IS_WIREFRAME (mi); + int s = 10; + + bp->scene_polys1 = 0; + bp->scene_polys2 = 0; + + glNewList (bp->obj_dlist0, GL_COMPILE); + glBegin (wire ? GL_LINE_LOOP : GL_QUADS); /* front */ + glNormal3f (0, 0, 1); + glTexCoord2f(1, 0); glVertex3f ( 0.5, -0.5, 0.5); + glTexCoord2f(0, 0); glVertex3f ( 0.5, 0.5, 0.5); + glTexCoord2f(0, 1); glVertex3f (-0.5, 0.5, 0.5); + glTexCoord2f(1, 1); glVertex3f (-0.5, -0.5, 0.5); + bp->scene_polys1++; + glEnd(); + + glBegin (wire ? GL_LINE_LOOP : GL_QUADS); /* back */ + glNormal3f (0, 0, -1); + glTexCoord2f(0, 0); glVertex3f (-0.5, -0.5, -0.5); + glTexCoord2f(0, 1); glVertex3f (-0.5, 0.5, -0.5); + glTexCoord2f(1, 1); glVertex3f ( 0.5, 0.5, -0.5); + glTexCoord2f(1, 0); glVertex3f ( 0.5, -0.5, -0.5); + bp->scene_polys1++; + glEnd(); + glEndList(); + + glNewList (bp->obj_dlist1, GL_COMPILE); + glBegin (wire ? GL_LINE_LOOP : GL_QUADS); /* left */ + glNormal3f (-1, 0, 0); + glTexCoord2f(1, 1); glVertex3f (-0.5, 0.5, 0.5); + glTexCoord2f(1, 0); glVertex3f (-0.5, 0.5, -0.5); + glTexCoord2f(0, 0); glVertex3f (-0.5, -0.5, -0.5); + glTexCoord2f(0, 1); glVertex3f (-0.5, -0.5, 0.5); + bp->scene_polys1++; + glEnd(); + + glBegin (wire ? GL_LINE_LOOP : GL_QUADS); /* right */ + glNormal3f (1, 0, 0); + glTexCoord2f(1, 1); glVertex3f ( 0.5, -0.5, -0.5); + glTexCoord2f(1, 0); glVertex3f ( 0.5, 0.5, -0.5); + glTexCoord2f(0, 0); glVertex3f ( 0.5, 0.5, 0.5); + glTexCoord2f(0, 1); glVertex3f ( 0.5, -0.5, 0.5); + bp->scene_polys1++; + glEnd(); + glEndList(); + + glNewList (bp->obj_dlist2, GL_COMPILE); + glBegin (wire ? GL_LINE_LOOP : GL_QUADS); /* top */ + glNormal3f (0, 1, 0); + glTexCoord2f(0, 0); glVertex3f ( 0.5, 0.5, 0.5); + glTexCoord2f(0, 1); glVertex3f ( 0.5, 0.5, -0.5); + glTexCoord2f(1, 1); glVertex3f (-0.5, 0.5, -0.5); + glTexCoord2f(1, 0); glVertex3f (-0.5, 0.5, 0.5); + bp->scene_polys1++; + glEnd(); + + glBegin (wire ? GL_LINE_LOOP : GL_QUADS); /* bottom */ + glNormal3f (0, -1, 0); + glTexCoord2f(1, 0); glVertex3f (-0.5, -0.5, 0.5); + glTexCoord2f(0, 0); glVertex3f (-0.5, -0.5, -0.5); + glTexCoord2f(0, 1); glVertex3f ( 0.5, -0.5, -0.5); + glTexCoord2f(1, 1); glVertex3f ( 0.5, -0.5, 0.5); + bp->scene_polys1++; + glEnd(); + glEndList(); + + glNewList (bp->obj_dlist3, GL_COMPILE); + glLineWidth (1); + glBegin(GL_LINES); + glVertex3f(-s, 0, 0); glVertex3f(s, 0, 0); /* face spikes */ + glVertex3f(0, -s, 0); glVertex3f(0, s, 0); + glVertex3f(0, 0, -s); glVertex3f(0, 0, s); + bp->scene_polys2 += 3; + glEnd(); + + glLineWidth (8); + glBegin(GL_LINES); + glVertex3f(-s, -s, -s); glVertex3f( s, s, s); /* corner spikes */ + glVertex3f(-s, -s, s); glVertex3f( s, s, -s); + glVertex3f(-s, s, -s); glVertex3f( s, -s, s); + glVertex3f( s, -s, -s); glVertex3f(-s, s, s); + bp->scene_polys2 += 4; + glEnd(); + glEndList (); + + check_gl_error ("object generation"); +} + + +static void +init_texture (ModeInfo *mi) +{ + glblur_configuration *bp = &bps[MI_SCREEN(mi)]; + + if (bp->tex_data) free (bp->tex_data); + + bp->tex_w = 128; + bp->tex_h = 128; + bp->tex_data = (unsigned int *) + malloc (bp->tex_w * bp->tex_h * 4 * sizeof (unsigned int)); + + glGenTextures (1, &bp->texture); + glBindTexture (GL_TEXTURE_2D, bp->texture); + glTexImage2D (GL_TEXTURE_2D, 0, GL_RGBA, + bp->tex_w, bp->tex_h, 0, + GL_RGBA, + /* GL_UNSIGNED_BYTE, */ + GL_UNSIGNED_INT_8_8_8_8_REV, + bp->tex_data); + check_gl_error ("texture generation"); + glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); +} + + +static void +render_scene_to_texture (ModeInfo *mi) +{ + glblur_configuration *bp = &bps[MI_SCREEN(mi)]; + + glViewport (0, 0, bp->tex_w, bp->tex_h); + + glCallList (bp->scene_dlist1); + glCallList (bp->scene_dlist2); + + glBindTexture (GL_TEXTURE_2D, bp->texture); + glCopyTexImage2D (GL_TEXTURE_2D, 0, GL_LUMINANCE, 0, 0, + bp->tex_w, bp->tex_h, 0); + check_gl_error ("texture2D"); + + glViewport (0, 0, MI_WIDTH(mi), MI_HEIGHT(mi)); +} + +static void +overlay_blur_texture (ModeInfo *mi) +{ + glblur_configuration *bp = &bps[MI_SCREEN(mi)]; + int w = MI_WIDTH (mi); + int h = MI_HEIGHT (mi); + int times = blursize; + int i; + GLfloat inc = 0.02 * (25.0 / times); + + GLfloat spost = 0; /* starting texture coordinate offset */ + GLfloat alpha_inc; /* transparency fade factor */ + GLfloat alpha = 0.2; /* initial transparency */ + + glEnable (GL_TEXTURE_2D); + glDisable (GL_DEPTH_TEST); + glBlendFunc (GL_SRC_ALPHA,GL_ONE); + glEnable (GL_BLEND); + glBindTexture (GL_TEXTURE_2D, bp->texture); + + + /* switch to orthographic projection, saving both previous matrixes + on their respective stacks. + */ + glMatrixMode (GL_PROJECTION); + glPushMatrix(); + glLoadIdentity(); + glOrtho (0, w, h, 0, -1, 1); + glMatrixMode (GL_MODELVIEW); + glPushMatrix(); + glLoadIdentity(); + + + alpha_inc = alpha / times; + + mi->polygon_count = bp->scene_polys1 + bp->scene_polys2; + + glBegin (GL_QUADS); + for (i = 0; i < times; i++) + { + glColor4f (1, 1, 1, alpha); + glTexCoord2f (0+spost, 1-spost); glVertex2f (0, 0); + glTexCoord2f (0+spost, 0+spost); glVertex2f (0, h); + glTexCoord2f (1-spost, 0+spost); glVertex2f (w, h); + glTexCoord2f (1-spost, 1-spost); glVertex2f (w, 0); + spost += inc; + alpha -= alpha_inc; + mi->polygon_count++; + } + glEnd(); + + /* Switch back to perspective projection, restoring the saved matrixes + */ + glMatrixMode (GL_PROJECTION); + glPopMatrix(); + glMatrixMode (GL_MODELVIEW); + glPopMatrix(); + + glEnable (GL_DEPTH_TEST); + glDisable (GL_BLEND); + glDisable (GL_TEXTURE_2D); + glBindTexture (GL_TEXTURE_2D, 0); +} + + + +/* Startup initialization + */ + +ENTRYPOINT Bool +glblur_handle_event (ModeInfo *mi, XEvent *event) +{ + glblur_configuration *bp = &bps[MI_SCREEN(mi)]; + + if (event->xany.type == ButtonPress && + event->xbutton.button == Button1) + { + bp->button_down_p = True; + gltrackball_start (bp->trackball, + event->xbutton.x, event->xbutton.y, + MI_WIDTH (mi), MI_HEIGHT (mi)); + return True; + } + else if (event->xany.type == ButtonRelease && + event->xbutton.button == Button1) + { + bp->button_down_p = False; + return True; + } + else if (event->xany.type == ButtonPress && + (event->xbutton.button == Button4 || + event->xbutton.button == Button5 || + event->xbutton.button == Button6 || + event->xbutton.button == Button7)) + { + gltrackball_mousewheel (bp->trackball, event->xbutton.button, 10, + !!event->xbutton.state); + return True; + } + else if (event->xany.type == MotionNotify && + bp->button_down_p) + { + gltrackball_track (bp->trackball, + event->xmotion.x, event->xmotion.y, + MI_WIDTH (mi), MI_HEIGHT (mi)); + return True; + } + + return False; +} + + +ENTRYPOINT void +init_glblur (ModeInfo *mi) +{ + glblur_configuration *bp; + int wire = MI_IS_WIREFRAME(mi); + + if (!bps) { + bps = (glblur_configuration *) + calloc (MI_NUM_SCREENS(mi), sizeof (glblur_configuration)); + if (!bps) { + fprintf(stderr, "%s: out of memory\n", progname); + exit(1); + } + } + + bp = &bps[MI_SCREEN(mi)]; + + bp->glx_context = init_GL(mi); + + reshape_glblur (mi, MI_WIDTH(mi), MI_HEIGHT(mi)); + clear_gl_error(); /* WTF? sometimes "invalid op" from glViewport! */ + + if (!wire) + { + GLfloat gamb[4]= {0.2, 0.2, 0.2, 1.0}; + GLfloat pos[4] = {0.0, 5.0, 10.0, 1.0}; + GLfloat amb[4] = {0.2, 0.2, 0.2, 1.0}; + GLfloat dif[4] = {0.3, 0.3, 0.3, 1.0}; + GLfloat spc[4] = {0.8, 0.8, 0.8, 1.0}; + GLfloat shiny = 128; + + glEnable(GL_LIGHTING); + glEnable(GL_LIGHT0); + + glEnable(GL_DEPTH_TEST); + glEnable(GL_CULL_FACE); + glEnable(GL_NORMALIZE); + glShadeModel(GL_SMOOTH); + + glLightModelfv (GL_LIGHT_MODEL_AMBIENT, gamb); + + glLightfv(GL_LIGHT0, GL_POSITION, pos); + glLightfv(GL_LIGHT0, GL_AMBIENT, amb); + glLightfv(GL_LIGHT0, GL_DIFFUSE, dif); + glLightfv(GL_LIGHT0, GL_SPECULAR, spc); + + glEnable(GL_LIGHTING); + glEnable(GL_LIGHT0); + + glMaterialf(GL_FRONT, GL_SHININESS, shiny); + } + + { + Bool spinx=False, spiny=False, spinz=False; + double spin_speed = 0.9; + double wander_speed = 0.06; + + char *s = do_spin; + while (*s) + { + if (*s == 'x' || *s == 'X') spinx = True; + else if (*s == 'y' || *s == 'Y') spiny = True; + else if (*s == 'z' || *s == 'Z') spinz = True; + else if (*s == '0') ; + else + { + fprintf (stderr, + "%s: spin must contain only the characters X, Y, or Z (not \"%s\")\n", + progname, do_spin); + exit (1); + } + s++; + } + + bp->rot = make_rotator (spinx ? spin_speed : 0, + spiny ? spin_speed : 0, + spinz ? spin_speed : 0, + 1.0, + do_wander ? wander_speed : 0, + False); + bp->trackball = gltrackball_init (); + } + + if (blursize < 0) blursize = 0; + if (blursize > 200) blursize = 200; + + bp->ncolors = 128; + bp->colors0 = (XColor *) calloc(bp->ncolors, sizeof(XColor)); + bp->colors1 = (XColor *) calloc(bp->ncolors, sizeof(XColor)); + bp->colors2 = (XColor *) calloc(bp->ncolors, sizeof(XColor)); + bp->colors3 = (XColor *) calloc(bp->ncolors, sizeof(XColor)); + make_smooth_colormap (0, 0, 0, bp->colors0, &bp->ncolors, False, 0, False); + make_smooth_colormap (0, 0, 0, bp->colors1, &bp->ncolors, False, 0, False); + make_smooth_colormap (0, 0, 0, bp->colors2, &bp->ncolors, False, 0, False); + make_smooth_colormap (0, 0, 0, bp->colors3, &bp->ncolors, False, 0, False); + bp->ccolor = 0; + + bp->obj_dlist0 = glGenLists (1); + bp->obj_dlist1 = glGenLists (1); + bp->obj_dlist2 = glGenLists (1); + bp->obj_dlist3 = glGenLists (1); + bp->scene_dlist1 = glGenLists (1); + bp->scene_dlist2 = glGenLists (1); + + init_texture (mi); + + generate_object (mi); +} + + +/* Render one frame + */ +ENTRYPOINT void +draw_glblur (ModeInfo *mi) +{ + glblur_configuration *bp = &bps[MI_SCREEN(mi)]; + Display *dpy = MI_DISPLAY(mi); + Window window = MI_WINDOW(mi); + + GLfloat color0[4] = {0.0, 0.0, 0.0, 1.0}; + GLfloat color1[4] = {0.0, 0.0, 0.0, 1.0}; + GLfloat color2[4] = {0.0, 0.0, 0.0, 1.0}; + GLfloat color3[4] = {0.0, 0.0, 0.0, 1.0}; + GLfloat spec[4] = {1.0, 1.0, 1.0, 1.0}; + + double rx, ry, rz; + double px, py, pz; + int extra_polys = 0; + + if (!bp->glx_context) + return; + + glXMakeCurrent(MI_DISPLAY(mi), MI_WINDOW(mi), *(bp->glx_context)); + + /* Decide what we're drawing + */ + if (0 == (random() % 30)) + { + bp->show_cube_p = (0 == (random() % 10)); + bp->show_spikes_p = (0 == (random() % 20)); + } + + /* Select new colors for the various objects + */ + color0[0] = bp->colors0[bp->ccolor].red / 65536.0; + color0[1] = bp->colors0[bp->ccolor].green / 65536.0; + color0[2] = bp->colors0[bp->ccolor].blue / 65536.0; + + color1[0] = bp->colors1[bp->ccolor].red / 65536.0; + color1[1] = bp->colors1[bp->ccolor].green / 65536.0; + color1[2] = bp->colors1[bp->ccolor].blue / 65536.0; + + color2[0] = bp->colors2[bp->ccolor].red / 65536.0; + color2[1] = bp->colors2[bp->ccolor].green / 65536.0; + color2[2] = bp->colors2[bp->ccolor].blue / 65536.0; + + color3[0] = bp->colors3[bp->ccolor].red / 65536.0; + color3[1] = bp->colors3[bp->ccolor].green / 65536.0; + color3[2] = bp->colors3[bp->ccolor].blue / 65536.0; + + bp->ccolor++; + if (bp->ccolor >= bp->ncolors) bp->ccolor = 0; + + + get_position (bp->rot, &px, &py, &pz, !bp->button_down_p); + get_rotation (bp->rot, &rx, &ry, &rz, !bp->button_down_p); + + px = (px - 0.5) * 2; + py = (py - 0.5) * 2; + pz = (pz - 0.5) * 8; + rx *= 360; + ry *= 360; + rz *= 360; + + /* Generate scene_dlist1, which contains the box (not spikes), + rotated into position. + */ + glNewList (bp->scene_dlist1, GL_COMPILE); + { + glMatrixMode (GL_MODELVIEW); + glPushMatrix (); + glTranslatef (px, py, pz); + gltrackball_rotate (bp->trackball); + glRotatef (rx, 1.0, 0.0, 0.0); + glRotatef (ry, 0.0, 1.0, 0.0); + glRotatef (rz, 0.0, 0.0, 1.0); + + glMaterialfv (GL_FRONT_AND_BACK, GL_SPECULAR, spec); + + glMaterialfv (GL_FRONT, GL_AMBIENT_AND_DIFFUSE, color0); + glCallList (bp->obj_dlist0); + + glMaterialfv (GL_FRONT, GL_AMBIENT_AND_DIFFUSE, color1); + glCallList (bp->obj_dlist1); + + glMaterialfv (GL_FRONT, GL_AMBIENT_AND_DIFFUSE, color2); + glCallList (bp->obj_dlist2); + + glMatrixMode (GL_MODELVIEW); + glPopMatrix (); + } + glEndList (); + + + /* Generate scene_dlist2, which contains the spikes (not box), + rotated into position. + */ + glNewList (bp->scene_dlist2, GL_COMPILE); + { + glMatrixMode (GL_MODELVIEW); + glPushMatrix (); + glTranslatef (px, py, pz); + gltrackball_rotate (bp->trackball); + glRotatef (rx, 1.0, 0.0, 0.0); + glRotatef (ry, 0.0, 1.0, 0.0); + glRotatef (rz, 0.0, 0.0, 1.0); + + glMaterialfv (GL_FRONT, GL_AMBIENT_AND_DIFFUSE, color3); + glCallList (bp->obj_dlist3); + + glMatrixMode (GL_MODELVIEW); + glPopMatrix (); + } + glEndList (); + + + glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + + render_scene_to_texture (mi); + + glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + + if (bp->show_cube_p || bp->button_down_p) + { + glCallList (bp->scene_dlist1); + extra_polys += bp->scene_polys1; + } + if (bp->show_spikes_p || bp->button_down_p) + { + glCallList (bp->scene_dlist2); + extra_polys += bp->scene_polys2; + } + + overlay_blur_texture (mi); + mi->polygon_count += extra_polys; + + glFlush (); + + if (mi->fps_p) do_fps (mi); + glFinish(); + + glXSwapBuffers(dpy, window); +} + +XSCREENSAVER_MODULE ("GLBlur", glblur) + +#endif /* USE_GL */ diff --git a/hacks/glx/glblur.man b/hacks/glx/glblur.man new file mode 100644 index 00000000..968f42f2 --- /dev/null +++ b/hacks/glx/glblur.man @@ -0,0 +1,76 @@ +.TH XScreenSaver 1 "" "X Version 11" +.SH NAME +glblur - 3D radial blur texture fields +.SH SYNOPSIS +.B glblur +[\-display \fIhost:display.screen\fP] +[\-visual \fIvisual\fP] +[\-window] +[\-root] +[\-delay \fInumber\fP] +[\-blursize \fInumber\fP] +[\-no-wander] +[\-no-spin] +[\-spin \fI[XYZ]\fP] +[\-fps] +.SH DESCRIPTION +This program draws a box and a few line segments, and generates a +radial blur outward from it. This creates flowing field effects. + +This is done by rendering the scene into a small texture, then +repeatedly rendering increasingly-enlarged and increasingly-transparent +versions of that texture onto the frame buffer. As such, it's quite +graphics intensive: don't bother trying to run this if you don't have +hardware-accelerated texture support. It will hurt your machine bad. +.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: 10000 (0.01 seconds.). +.TP 8 +.B \-blursize \fInumber\fP +How many copies of the scene should be laid down to make the vapor trail. +Default: 15. Larger numbers create smoother fields, but are slower. +.TP 8 +.B \-wander | \-no-wander +Whether the object should wander around the screen. +.TP 8 +.B \-spin [XYZ] +Around which axes should the object spin? +.TP 8 +.B \-no-spin +None. +.TP 8 +.B \-fps +Display the current frame rate, CPU load, and polygon count. +.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 2002 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, with inspiration from a tutorial by Dario Corno. diff --git a/hacks/glx/glcells.c b/hacks/glx/glcells.c new file mode 100644 index 00000000..c312f0c2 --- /dev/null +++ b/hacks/glx/glcells.c @@ -0,0 +1,1328 @@ +/* -*- Mode: C; tab-width: 2 -*- */ +/* glcells --- Cells growing on your screen */ + +/*- + * Cells growing on your screen + * + * Copyright (c) 2007 by Matthias Toussaint + * + * Permission to use, copy, modify, and distribute this software and its + * documentation for any purpose and without fee is hereby granted, + * provided that the above copyright notice appear in all copies and that + * both that copyright notice and this permission notice appear in + * supporting documentation. + * + * This file is provided AS IS with no warranties of any kind. The author + * shall have no liability with respect to the infringement of copyrights, + * trade secrets or any patents by this file or any part thereof. In no + * event will the author be liable for any lost revenue or profits or + * other special, indirect and consequential damages. + * + * 2007: Written by Matthias Toussaint + * 0.1 Initial version + * 0.2 Bugfixes (threading) and code cleanup by Jamie Zawinski + * Window scaling bug + performance bug in tick() + */ + +#include /* gettimeofday */ + +#include "xlockmore.h" +#include + +/********************************** + DEFINES + **********************************/ + +#define INDEX_OFFSET 100000 +#define NUM_CELL_SHAPES 10 + +#define refresh_glcells 0 +#define glcells_handle_event 0 + +#define DEF_DELAY "20000" +#define DEF_MAXCELLS "800" +#define DEF_RADIUS "40" +#define DEF_SEEDS "1" +#define DEF_QUALITY "3" +#define DEF_KEEPOLD "False" +#define DEF_MINFOOD "5" +#define DEF_MAXFOOD "20" +#define DEF_DIVIDEAGE "20" +#define DEF_MINDIST "1.4" +#define DEF_PAUSE "50" + +#define DEFAULTS "*delay: 30000 \n" \ + "*showFPS: False \n" \ + "*wireframe: False \n" \ + +#undef countof +#define countof(x) (sizeof((x))/sizeof((*x))) + +#ifndef HAVE_JWZGLES /* glDrawElements unimplemented... */ +# define USE_VERTEX_ARRAY +#endif + +#define TEX_SIZE 64 + +/********************************** + TYPEDEFS + **********************************/ + +typedef struct /* a 3-D vector */ +{ + double x, y, z; /* 3-D coordinates (we don't need w here) */ +} Vector; + +typedef struct /* a triangle (indexes of vertexes in some list) */ +{ + int i[3]; /* the three indexes for the triangle corners */ +} Triangle; + +typedef struct +{ + float *vertex; + float *normal; + unsigned *index; + int num_index; +} VertexArray; + +typedef struct /* an 3-D object without normal vectors */ +{ + Vector *vertex; /* the vertexes */ + Triangle *triangle; /* triangle list */ + int num_vertex; /* number of vertexes */ + int num_triangle; /* number of triangles */ +} Object; + +typedef struct /* an 3-D object with smooth normal vectors */ +{ + Vector *vertex; /* the vertexes */ + Vector *normal; /* the vertex normal vectors */ + Triangle *triangle; /* triangle list */ + int num_vertex; /* number of vertexes */ + int num_triangle; /* number of triangles */ +} ObjectSmooth; + +typedef struct /* Cell */ +{ + double x, y; /* position */ + double vx, vy; /* movement vector */ + int age; /* cells age */ + double min_dist; /* minimum distance to other cells */ + int energy; /* health */ + double rotation; /* random rot, so they don't look all the same */ + double radius; /* current size of cell */ + double growth; /* current growth rate. might be <1.0 while dividing, + >1.0 when finished dividing and food is available + and 1.0 when grown up */ +} Cell; + +typedef struct /* hacks state */ +{ + GLXContext *glx_context; + int width, height; /* current size of viewport */ + double screen_scale; /* we scale content with window size */ + int num_cells; /* current number of cell in list */ + Cell *cell; /* array of cells */ + int cell_polys; + GLfloat color[4]; /* current cell color */ + double radius; /* cell radius */ + int move_dist; /* min distance from neighbours for forking */ + int max_cells; /* maximum number of cells */ + int num_seeds; /* number of initial seeds */ + int keep_old_cells; /* draw dead cells? */ + int divide_age; /* min age for division */ + /* display lists for the cell stages */ + int cell_list[NUM_CELL_SHAPES]; + int nucleus_list; + int minfood; /* minimum amount of food per area unit */ + int maxfood; /* maximum amount of food per area unit */ + int pause; /* pause at end (all cells dead) */ + int pause_counter; + int wire; /* draw wireframe? */ + Object *sphere; /* the raw undisturbed sphere */ + double *disturbance; /* disturbance values for the vertexes */ + int *food; /* our petri dish (e.g. screen) */ + GLubyte *texture; /* texture data for nucleus */ + GLuint texture_name; /* texture name for binding */ +} State; + +/********************************** + STATIC STUFF + **********************************/ + +static State *sstate = NULL; + +static XrmOptionDescRec opts[] = { + { "-maxcells", ".maxcells", XrmoptionSepArg, 0 }, + { "-radius", ".radius", XrmoptionSepArg, 0 }, + { "-seeds", ".seeds", XrmoptionSepArg, 0 }, + { "-quality", ".quality", XrmoptionSepArg, 0 }, + { "-minfood", ".minfood", XrmoptionSepArg, 0 }, + { "-maxfood", ".maxfood", XrmoptionSepArg, 0 }, + { "-divideage", ".divideage", XrmoptionSepArg, 0 }, + { "-mindist", ".mindist", XrmoptionSepArg, 0 }, + { "-pause", ".pause", XrmoptionSepArg, 0 }, + { "-keepold", ".keepold", XrmoptionNoArg, "True" } +}; + +static int s_maxcells; +static int s_radius; +static int s_seeds; +static int s_quality; +static int s_minfood; +static int s_maxfood; +static int s_divideage; +static int s_pause; +static float s_min_dist; +static Bool s_keepold; + +static argtype vars[] = { + {&s_maxcells, "maxcells", "Max Cells", DEF_MAXCELLS, t_Int}, + {&s_radius, "radius", "Radius", DEF_RADIUS, t_Int}, + {&s_seeds, "seeds", "Seeds", DEF_SEEDS, t_Int}, + {&s_quality, "quality", "Quality", DEF_QUALITY, t_Int}, + {&s_minfood, "minfood", "Min Food", DEF_MINFOOD, t_Int}, + {&s_maxfood, "maxfood", "Max Food", DEF_MAXFOOD, t_Int}, + {&s_pause, "pause", "Pause at end", DEF_PAUSE, t_Int}, + {&s_divideage, "divideage", "Age for duplication (Ticks)", DEF_DIVIDEAGE, t_Int}, + {&s_min_dist, "mindist", "Minimum preferred distance to other cells", DEF_MINDIST, t_Float}, + {&s_keepold, "keepold", "Keep old cells", DEF_KEEPOLD, t_Bool} +}; + +/********************************** + PROTOTYPES + **********************************/ + +/* render scene */ +static int render( State *st ); +/* create initial cells and fill petri dish with food */ +static void create_cells( State * ); +/* do one animation step */ +static void tick( State *st ); +/* draw a single cell */ +static void draw_cell( State *st, int shape ); +/* draw cells nucleus */ +static void draw_nucleus( State *st ); +/* return randum number in the interval min-max */ +static int random_interval( int min, int max ); +/* retunr random number in the interval 0-max */ +static int random_max( int max ); +/* create display list for given disturbance weighting factor */ +static int create_list( State *st, double fac ); +/* return length of vector */ +static double vector_length( Vector * ); +/* normalize vector */ +static void vector_normalize( Vector * ); +/* a += b */ +static void vector_add( Vector *a, Vector *b ); +/* a -= b */ +static void vector_sub( Vector *a, Vector *b ); +/* a *= fac */ +static void vector_mul( Vector *a, double fac ); +/* a.x = a.y = a.z = 0 */ +static void vector_clear( Vector *a ); +/* return crossproduct a*b in out */ +static void vector_crossprod( Vector *a, Vector *b, Vector *out ); +/* return 1 if vectors are equal (epsilon compare) otherwise 0 */ +static int vector_compare( Vector *a, Vector *b ); +/* compute normal vector of given triangle and return in out */ +static void triangle_normal( Vector *a, Vector *b, Vector *c, Vector *out ); +/* take an Object and create an ObjectSmooth out of it */ +static ObjectSmooth *create_ObjectSmooth( Object * ); +/* Subdivide the Object once (assuming it's supposed to be a shpere */ +static Object *subdivide( Object *obj ); +/* free an Object */ +static void free_Object( Object * ); +/* free an ObjectSmooth */ +static void free_ObjectSmooth( ObjectSmooth * ); +/* scale an Object. return pointer to the object */ +/*static Object *scale_Object( Object *obj, double scale );*/ +/* create a perfect sphere refining with divisions */ +static Object *create_sphere( State *st, int divisions ); +/* make a copy of the given Object */ +static Object *clone_Object( Object * ); +/* return 1 if cell is capable to divide */ +static int can_divide( State *st, Cell *cell ); +#ifdef USE_VERTEX_ARRAY +static VertexArray *array_from_ObjectSmooth( ObjectSmooth * ); +#endif +static void create_nucleus_texture( State *st ); + +ENTRYPOINT ModeSpecOpt glcells_opts = { countof(opts), opts, countof(vars), vars, + NULL }; + + +/********************************** + INLINE FUNCTIONS + **********************************/ +/* create random numbers +*/ +static inline int random_interval( int min, int max ) +{ + int n = max - min; + if (n == 0) n = 1; + return min+(random()%n); +} + +static inline int random_max( int max ) +{ + return random()%max; +} + +/* Vector stuff +*/ + +/* a += b */ +static inline void vector_add( Vector *a, Vector *b ) +{ + a->x += b->x; + a->y += b->y; + a->z += b->z; +} + +/* a -= b */ +static inline void vector_sub( Vector *a, Vector *b ) +{ + a->x -= b->x; + a->y -= b->y; + a->z -= b->z; +} + +/* a *= v */ +static inline void vector_mul( Vector *a, double v ) +{ + a->x *= v; + a->y *= v; + a->z *= v; +} + +/* set to 0 */ +static inline void vector_clear( Vector *vec ) +{ + vec->x = vec->y = vec->z = 0; +} + +/* return vector length */ +static inline double vector_length( Vector *vec ) +{ + return sqrt( vec->x*vec->x + vec->y*vec->y + vec->z*vec->z ); +} + +/* normalize vector */ +static inline void vector_normalize( Vector *vec ) +{ + double len = vector_length( vec ); + + if (len != 0.0) { + vector_mul( vec, 1.0 / len ); + } +} + +/* crossproduct */ +static inline void vector_crossprod( Vector *a, Vector *b, Vector *out ) +{ + out->x = a->y*b->z - a->z*b->y; + out->y = a->z*b->x - a->x*b->z; + out->z = a->x*b->y - a->y*b->x; +} + +/* epsilon compare of two vectors */ +static inline int vector_compare( Vector *a, Vector *b ) +{ + const double epsilon = 0.0000001; + Vector delta = *a; + + vector_sub( &delta, b ); + if (fabs(delta.x) < epsilon && + fabs(delta.y) < epsilon && + fabs(delta.z) < epsilon) { + return 1; + } + + return 0; +} + +/* check if given cell is capable of dividing + needs space, must be old enough, grown up and healthy +*/ +static inline int can_divide( State *st, Cell *cell ) +{ + if (cell->min_dist > st->move_dist && + cell->age >= st->divide_age && + cell->radius > 0.99 * st->radius && + cell->energy > 0) { + return 1; + } + + return 0; +} + +/********************************** + FUNCTIONS + **********************************/ + +/* compute normal vector of given + triangle spanned by the points a, b, c +*/ +static void triangle_normal( Vector *a, Vector *b, Vector *c, Vector *out ) +{ + Vector v1 = *a; + Vector v2 = *a; + + vector_sub( &v1, b ); + vector_sub( &v2, c ); + vector_crossprod( &v1, &v2, out ); +} + +/* free */ +static void free_Object( Object *obj ) +{ + free( obj->vertex ); + free( obj->triangle ); + free( obj ); +} + +static void free_ObjectSmooth( ObjectSmooth *obj ) +{ + free( obj->vertex ); + free( obj->triangle ); + free( obj->normal ); + free( obj ); +} + +/* scale the given Object */ +#if 0 +static Object *scale_Object( Object *obj, double scale ) +{ + int v; + + for (v=0; vnum_vertex; ++v) { + vector_mul( &obj->vertex[v], scale ); + } + + return obj; +} +#endif + +/* create a copy of the given Object */ +static Object *clone_Object( Object *obj ) +{ + /* alloc */ + Object *ret = (Object *) malloc( sizeof( Object ) ); + + ret->vertex = + (Vector *) malloc( obj->num_vertex*sizeof(Vector) ); + ret->triangle = + (Triangle *) malloc( obj->num_triangle*sizeof(Triangle) ); + ret->num_vertex = obj->num_vertex; + ret->num_triangle = obj->num_triangle; + /* copy */ + memcpy( ret->vertex, obj->vertex, + obj->num_vertex*sizeof(Vector) ); + memcpy( ret->triangle, obj->triangle, + obj->num_triangle*sizeof(Triangle) ); + + return ret; +} + +#ifdef USE_VERTEX_ARRAY +static VertexArray *array_from_ObjectSmooth( ObjectSmooth *obj ) +{ + int i, j; + VertexArray *array = (VertexArray *) malloc( sizeof( VertexArray ) ); + + array->vertex = (float *) malloc( 3*sizeof(float)*obj->num_vertex ); + array->normal = (float *) malloc( 3*sizeof(float)*obj->num_vertex ); + array->index = (unsigned *) malloc( 3*sizeof(unsigned)*obj->num_triangle ); + array->num_index = obj->num_triangle*3; + + for (i=0, j=0; inum_vertex; ++i) { + array->vertex[j] = obj->vertex[i].x; + array->normal[j++] = obj->normal[i].x; + array->vertex[j] = obj->vertex[i].y; + array->normal[j++] = obj->normal[i].y; + array->vertex[j] = obj->vertex[i].z; + array->normal[j++] = obj->normal[i].z; + } + + for (i=0, j=0; inum_triangle; ++i) { + array->index[j++] = obj->triangle[i].i[0]; + array->index[j++] = obj->triangle[i].i[1]; + array->index[j++] = obj->triangle[i].i[2]; + } + + return array; +} +#endif /* USE_VERTEX_ARRAY */ + + +/* create a smoothed version of the given Object + by computing average normal vectors for the vertexes +*/ +static ObjectSmooth *create_ObjectSmooth( Object *obj ) +{ + int t, v, i; + Vector *t_normal = + (Vector *) malloc( obj->num_triangle*sizeof(Vector) ); + ObjectSmooth *ret = + (ObjectSmooth *) malloc( sizeof( ObjectSmooth ) ); + + /* fill in vertexes and triangles */ + ret->num_vertex = obj->num_vertex; + ret->num_triangle = obj->num_triangle; + ret->vertex = + (Vector *) malloc( obj->num_vertex * sizeof( Vector ) ); + ret->normal = + (Vector *) malloc( obj->num_vertex * sizeof( Vector ) ); + ret->triangle = + (Triangle *) malloc( obj->num_triangle * sizeof( Triangle ) ); + + for (v=0; vnum_vertex; ++v) { + ret->vertex[v] = obj->vertex[v]; + } + + for (t=0; tnum_triangle; ++t) { + ret->triangle[t] = obj->triangle[t]; + } + + /* create normals (triangles) */ + for (t=0; tnum_triangle; ++t) { + triangle_normal( &ret->vertex[ret->triangle[t].i[0]], + &ret->vertex[ret->triangle[t].i[1]], + &ret->vertex[ret->triangle[t].i[2]], + &t_normal[t] ); + } + + /* create normals (vertex) by averaging triangle + normals at vertex + */ + for (v=0; vnum_vertex; ++v) { + vector_clear( &ret->normal[v] ); + for (t=0; tnum_triangle; ++t) { + for (i=0; i<3; ++i) { + if (ret->triangle[t].i[i] == v) { + vector_add( &ret->normal[v], &t_normal[t] ); + } + } + } + /* as we have only a half sphere we force the + normals at the bortder to be perpendicular to z. + the simple algorithm above makes an error here. + */ + if (fabs(ret->vertex[v].z) < 0.0001) { + ret->normal[v].z = 0.0; + } + + vector_normalize( &ret->normal[v] ); + } + + free( t_normal ); + + return ret; +} + +/* subdivide the triangles of the object once + The order of this algorithm is probably something like O(n^42) :) + but I can't think of something smarter at the moment +*/ +static Object *subdivide( Object *obj ) +{ + /* create for worst case (which I dont't know) */ + int start, t, i, v; + int index_list[1000]; + int index_cnt, index_found; + Object *tmp = (Object *)malloc( sizeof(Object) ); + Object *ret = (Object *)malloc( sizeof(Object) ); + Object *c_ret; + + tmp->vertex = + (Vector *)malloc( 100*obj->num_vertex*sizeof( Vector ) ); + tmp->triangle = + (Triangle *)malloc( 4*obj->num_triangle*sizeof( Triangle ) ); + tmp->num_vertex = 0; + tmp->num_triangle = 0; + ret->vertex = + (Vector *)malloc( 100*obj->num_vertex*sizeof( Vector ) ); + ret->triangle = + (Triangle *)malloc( 4*obj->num_triangle*sizeof( Triangle ) ); + ret->num_vertex = 0; + ret->num_triangle = 0; +#ifdef PRINT_STAT + fprintf( stderr, "in v=%d t=%d\n", + obj->num_vertex, obj->num_triangle ); +#endif + /* for each triangle create 3 new vertexes and the 4 + corresponding triangles + */ + for (t=0; tnum_triangle; ++t) { + /* copy the three original vertexes */ + for (i=0; i<3; ++i) { + tmp->vertex[tmp->num_vertex++] = + obj->vertex[obj->triangle[t].i[i]]; + } + + /* create 3 new */ + tmp->vertex[tmp->num_vertex] = + obj->vertex[obj->triangle[t].i[0]]; + vector_add( &tmp->vertex[tmp->num_vertex], + &obj->vertex[obj->triangle[t].i[1]] ); + vector_mul( &tmp->vertex[tmp->num_vertex++], 0.5 ); + + tmp->vertex[tmp->num_vertex] = + obj->vertex[obj->triangle[t].i[1]]; + vector_add( &tmp->vertex[tmp->num_vertex], + &obj->vertex[obj->triangle[t].i[2]] ); + vector_mul( &tmp->vertex[tmp->num_vertex++], 0.5 ); + + tmp->vertex[tmp->num_vertex] = + obj->vertex[obj->triangle[t].i[2]]; + vector_add( &tmp->vertex[tmp->num_vertex], + &obj->vertex[obj->triangle[t].i[0]] ); + vector_mul( &tmp->vertex[tmp->num_vertex++], 0.5 ); + + /* create triangles */ + start = tmp->num_vertex-6; + + tmp->triangle[tmp->num_triangle].i[0] = start; + tmp->triangle[tmp->num_triangle].i[1] = start+3; + tmp->triangle[tmp->num_triangle++].i[2] = start+5; + + tmp->triangle[tmp->num_triangle].i[0] = start+3; + tmp->triangle[tmp->num_triangle].i[1] = start+1; + tmp->triangle[tmp->num_triangle++].i[2] = start+4; + + tmp->triangle[tmp->num_triangle].i[0] = start+5; + tmp->triangle[tmp->num_triangle].i[1] = start+4; + tmp->triangle[tmp->num_triangle++].i[2] = start+2; + + tmp->triangle[tmp->num_triangle].i[0] = start+3; + tmp->triangle[tmp->num_triangle].i[1] = start+4; + tmp->triangle[tmp->num_triangle++].i[2] = start+5; + } + + /* compress object eliminating double vertexes + (welcome to the not so smart section) + */ + /* copy original triangle list */ + for (t=0; tnum_triangle; ++t) { + ret->triangle[t] = tmp->triangle[t]; + } + ret->num_triangle = tmp->num_triangle; + + /* copy unique vertexes and correct triangle list */ + for (v=0; vnum_vertex; ++v) { + /* create list of vertexes that are the same */ + index_cnt = 0; + for (i=0; inum_vertex; ++i) { + /* check if i and v are the same + first in the list is the smallest index + */ + if (vector_compare( &tmp->vertex[v], &tmp->vertex[i] )) { + index_list[index_cnt++] = i; + } + } + + /* check if vertex unknown so far */ + index_found = 0; + for (i=0; inum_vertex; ++i) { + if (vector_compare( &ret->vertex[i], + &tmp->vertex[index_list[0]] )) { + index_found = 1; + break; + } + } + + if (!index_found) { + ret->vertex[ret->num_vertex] = tmp->vertex[index_list[0]]; + + /* correct triangles + (we add an offset to the index, so we can tell them apart) + */ + for (t=0; tnum_triangle; ++t) { + for (i=0; itriangle[t].i[0] == index_list[i]) { + ret->triangle[t].i[0] = ret->num_vertex+INDEX_OFFSET; + } + if (ret->triangle[t].i[1] == index_list[i]) { + ret->triangle[t].i[1] = ret->num_vertex+INDEX_OFFSET; + } + if (ret->triangle[t].i[2] == index_list[i]) { + ret->triangle[t].i[2] = ret->num_vertex+INDEX_OFFSET; + } + } + } + ret->num_vertex++; + } + } + + free_Object( tmp ); + + /* correct index offset */ + for (t=0; tnum_triangle; ++t) { + ret->triangle[t].i[0] -= INDEX_OFFSET; + ret->triangle[t].i[1] -= INDEX_OFFSET; + ret->triangle[t].i[2] -= INDEX_OFFSET; + } + + /* normalize vertexes */ + for (v=0; vnum_vertex; ++v) { + vector_normalize( &ret->vertex[v] ); + } +#ifdef PRINT_STAT + fprintf( stderr, "out v=%d t=%d\n", + ret->num_vertex, ret->num_triangle ); +#endif + /* shrink the arrays by cloning */ + c_ret = clone_Object( ret ); + free_Object( ret ); + + return c_ret; +} + +static int render( State *st ) +{ +#ifdef PRINT_STAT + struct timeval tv1, tv2; + int usec; +#endif + GLfloat LightAmbient[]= { 0.1f, 0.1f, 0.1f, 1.0f }; + GLfloat LightPosition[]= { -20.0f, -10.0f, -100.0f, 0.0f }; + int b; + int num_paint = 0; + + if (0 == st->food) return 0; +#ifdef PRINT_STAT + gettimeofday( &tv1, NULL ); +#endif + /* life goes on... */ + tick( st ); +#ifdef PRINT_STAT + gettimeofday( &tv2, NULL ); + usec = (tv2.tv_sec-tv1.tv_sec)*1000000+(tv2.tv_usec-tv1.tv_usec); + fprintf( stderr, "tick %d\n", usec ); + gettimeofday( &tv1, NULL ); +#endif + + glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT ); + glDepthFunc(GL_LESS); + glEnable(GL_DEPTH_TEST); + glLightfv( GL_LIGHT0, GL_AMBIENT, LightAmbient ); + glLightfv( GL_LIGHT0, GL_DIFFUSE, st->color ); + glLightfv( GL_LIGHT0, GL_POSITION, LightPosition ); + + /* prepare lighting vs. wireframe */ + if (!st->wire) { + glEnable( GL_LIGHT0 ); + glEnable( GL_LIGHTING ); + glEnable( GL_NORMALIZE ); + glPolygonMode( GL_FRONT, GL_FILL ); + } else { + glPolygonMode( GL_FRONT, GL_LINE ); + } + + /* draw the dead cells if choosen */ + if (st->keep_old_cells) { + for (b=0; bnum_cells; ++b) { + if (st->cell[b].energy <= 0) { + num_paint++; + glPushMatrix(); + glTranslatef( st->cell[b].x, st->cell[b].y, 0.0 ); + glRotatef( st->cell[b].rotation, 0.0, 0.0, 1.0 ); + glScalef( st->cell[b].radius, st->cell[b].radius, st->cell[b].radius ); + draw_cell( st, 9 ); + glPopMatrix(); + } + } + } + + /* draw the living cells */ + for (b=0; bnum_cells; ++b) { + if (st->cell[b].energy >0) { + double fac = (double)st->cell[b].energy / 50.0; + int shape; + if (fac < 0.0) fac = 0.0; + if (fac > 1.0) fac = 1.0; + + shape = (int)(9.0*fac); + num_paint++; + /*glColor3f( fac, fac, fac );*/ + + glPushMatrix(); + glTranslatef( st->cell[b].x, st->cell[b].y, 0.0 ); + glRotatef( st->cell[b].rotation, 0.0, 0.0, 1.0 ); + glScalef( st->cell[b].radius, st->cell[b].radius, st->cell[b].radius ); + draw_cell( st, 9-shape ); + glPopMatrix(); + } + } + + /* draw cell nuclei */ + if (!st->wire) + { + glDisable( GL_LIGHT0 ); + glDisable( GL_LIGHTING ); + + glEnable( GL_BLEND ); + glDisable( GL_DEPTH_TEST ); + glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA ); + glEnable( GL_TEXTURE_2D ); + glTexEnvf( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE ); + glBindTexture( GL_TEXTURE_2D, st->texture_name ); + + for (b=0; bnum_cells; ++b) { + if (st->cell[b].energy>0 || st->keep_old_cells) { + glPushMatrix(); + glTranslatef( st->cell[b].x, st->cell[b].y, 0.0 ); + glScalef( st->cell[b].radius, st->cell[b].radius, st->cell[b].radius ); + draw_nucleus( st ); + glPopMatrix(); + } + } + + glDisable( GL_TEXTURE_2D ); + glDisable( GL_BLEND ); + } + +#ifdef PRINT_STAT + gettimeofday( &tv2, NULL ); + usec = (tv2.tv_sec-tv1.tv_sec)*1000000+(tv2.tv_usec-tv1.tv_usec); + fprintf( stderr, "OpenGL %d\n", usec ); +#endif + return num_paint * st->cell_polys; +} + +/* this creates the initial subdivided half-dodecaedron */ +static Object *create_sphere( State *st, int divisions ) +{ + int num_vertex = 9; + int num_triangle = 10; + int i, v, t; + double a, aStep = (double)M_PI / 3.0; + double e; + int vi[30] = { 0, 7, 1, 1, 7, 2, 2, 8, 3, 3, 8, 4, 4, 6, 5, + 5, 6, 0, 0, 6, 7, 2, 7, 8, 4, 8, 6, 6, 8, 7 }; + Object *obj = (Object *)malloc( sizeof( Object ) ); + + obj->vertex = (Vector *)malloc( num_vertex*sizeof( Vector ) ); + obj->triangle = + (Triangle *)malloc( num_triangle*sizeof( Triangle ) ); + obj->num_vertex = num_vertex; + obj->num_triangle = num_triangle; + + /* create vertexes for dodecaedron */ + a = 0.0; + for (v=0; v<6; ++v) { + obj->vertex[v].x = sin( a ); + obj->vertex[v].y = -cos( a ); + obj->vertex[v].z = 0.0; + + a += aStep; + } + + a = -60.0/180.0*(double)M_PI; + e = 58.2825/180.0 * (double)M_PI; + for (;v<9; ++v) { + obj->vertex[v].x = sin( a )*cos( e ); + obj->vertex[v].y = -cos( a )*cos( e ); + obj->vertex[v].z = -sin( e ); + + a += 2.0*aStep; + } + + /* create triangles */ + for (t=0; tnum_triangle; ++t) { + obj->triangle[t].i[0] = vi[3*t]; + obj->triangle[t].i[1] = vi[3*t+1]; + obj->triangle[t].i[2] = vi[3*t+2]; + } + + /* subdivide as specified */ + for (i=0; icell_polys = obj->num_triangle; + + return obj; +} + +static int create_list( State *st, double fac ) +{ + int v; + Object *obj = clone_Object( st->sphere ); + ObjectSmooth *smooth; +#ifdef USE_VERTEX_ARRAY + VertexArray *vertex_array; +#else + int t, i; +#endif + int list = glGenLists(1); + + /* apply wrinckle factor */ + for (v=0; vnum_vertex; ++v) { + vector_mul( &obj->vertex[v], 1.0+fac*st->disturbance[v] ); + } + + /* compute normals */ + smooth = create_ObjectSmooth( obj ); + free_Object( obj ); + + /* Create display list */ + glNewList( list, GL_COMPILE ); +#ifdef USE_VERTEX_ARRAY + vertex_array = array_from_ObjectSmooth( smooth ); + glEnableClientState( GL_VERTEX_ARRAY ); + glEnableClientState( GL_NORMAL_ARRAY ); + glVertexPointer( 3, GL_FLOAT, 0, vertex_array->vertex ); + glNormalPointer( GL_FLOAT, 0, vertex_array->normal ); + glDrawElements( GL_TRIANGLES, vertex_array->num_index, + GL_UNSIGNED_INT, vertex_array->index ); + free( vertex_array ); +#else + glBegin( GL_TRIANGLES ); + + for (t=0; tnum_triangle; ++t) { + for (i=0; i<3; ++i) { + glNormal3f( smooth->normal[smooth->triangle[t].i[i]].x, + smooth->normal[smooth->triangle[t].i[i]].y, + smooth->normal[smooth->triangle[t].i[i]].z ); + glVertex3f( smooth->vertex[smooth->triangle[t].i[i]].x, + smooth->vertex[smooth->triangle[t].i[i]].y, + smooth->vertex[smooth->triangle[t].i[i]].z ); + } + } + + glEnd(); +#endif + glEndList(); + + free_ObjectSmooth( smooth ); + + return list; +} + +static void draw_cell( State *st, int shape ) +{ + if (-1 == st->cell_list[shape]) { + st->cell_list[shape] = create_list( st, (double)shape/10.0 ); + } + + glCallList( st->cell_list[shape] ); +} + +static void create_nucleus_texture( State *st ) +{ + int x, y; + int w2 = TEX_SIZE/2; + float s = w2*w2/4.0; + + st->texture = (GLubyte *) malloc( 4*TEX_SIZE*TEX_SIZE ); + + for (y=0; ytexture[4*(x+y*TEX_SIZE)] = (GLubyte)0; + st->texture[4*(x+y*TEX_SIZE)+1] = (GLubyte)0; + st->texture[4*(x+y*TEX_SIZE)+2] = (GLubyte)0; + st->texture[4*(x+y*TEX_SIZE)+3] = (GLubyte)v; + } + } + + glPixelStorei( GL_UNPACK_ALIGNMENT, 1 ); + glGenTextures( 1, &st->texture_name ); + glBindTexture( GL_TEXTURE_2D, st->texture_name ); + + glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT ); + glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT ); + glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR ); + glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR ); + glTexImage2D( GL_TEXTURE_2D, 0, GL_RGBA, TEX_SIZE, TEX_SIZE, 0, + GL_RGBA, GL_UNSIGNED_BYTE, st->texture ); +} + +static void draw_nucleus( State *st ) +{ + if (-1 == st->nucleus_list) { + float z = -1.2f; + float r=1.0/2.0f; + st->nucleus_list = glGenLists( 1 ); + glNewList( st->nucleus_list, GL_COMPILE ); + glBegin( GL_QUADS ); + glTexCoord2f( 0.0f, 0.0f ); glVertex3f( -r, -r, z ); + glTexCoord2f( 0.0f, 1.0f ); glVertex3f( -r, r, z ); + glTexCoord2f( 1.0f, 1.0f ); glVertex3f( r, r, z ); + glTexCoord2f( 1.0f, 0.0f ); glVertex3f( r, -r, z ); + glEnd(); + glEndList(); + } + + glCallList( st->nucleus_list ); +} + +static void create_cells( State *st ) +{ + int border = (int)(200.0 * st->screen_scale); + int i, foodcnt; + int w = st->width-2*border; + int h = st->height-2*border; + + st->color[0] = 0.5 + random_max( 1000 ) * 0.0005; + st->color[1] = 0.5 + random_max( 1000 ) * 0.0005; + st->color[2] = 0.5 + random_max( 1000 ) * 0.0005; + st->color[3] = 1.0f; + + /* allocate if startup */ + if (!st->cell) { + st->cell = (Cell *) malloc( st->max_cells * sizeof(Cell)); + } + + /* fill the screen with random food for our little critters */ + foodcnt = (st->width*st->height)/16; + for (i=0; ifood[i] = random_interval( st->minfood, st->maxfood ); + } + + /* create the requested seed-cells */ + st->num_cells = st->num_seeds; + + for (i=0; inum_cells; ++i) { + st->cell[i].x = border + random_max( w ); + st->cell[i].y = border + random_max( h ); + st->cell[i].vx = 0.0; + st->cell[i].vy = 0.0; + st->cell[i].age = random_max( 0x0f ); + st->cell[i].min_dist = 500.0; + st->cell[i].energy = random_interval( 5, 5+0x3f ); + st->cell[i].rotation = ((double)random()/(double)RAND_MAX)*360.0; + st->cell[i].radius = st->radius; + st->cell[i].growth = 1.0; + } +} + +/* all this is rather expensive :( */ +static void tick( State *st ) +{ + int new_num_cells, num_cells=0; + int b, j; + int x, y, w4=st->width/4, h4=st->height/4, offset; + double min_dist; + int min_index; + int num_living = 0; + const double check_dist = 0.75*st->move_dist; + const double grow_dist = 0.75*st->radius; + const double adult_radius = st->radius; + + /* find number of cells capable of division + and count living cells + */ + for (b=0; bnum_cells; ++b) { + if (st->cell[b].energy > 0) num_living++; + if (can_divide( st, &st->cell[b] )) num_cells++; + } + new_num_cells = st->num_cells + num_cells; + + /* end of simulation ? */ + if (0 == num_living || new_num_cells >= st->max_cells) { + if (st->pause_counter > 0) st->pause_counter--; + if (st->pause_counter > 0) return; + create_cells( st ); + st->pause_counter = st->pause; + } else if (num_cells) { /* any fertile candidates ? */ + for (b=0, j=st->num_cells; bnum_cells; ++b) { + if (can_divide( st, &st->cell[b] )) { + st->cell[b].vx = random_interval( -50, 50 ) * 0.01; + st->cell[b].vy = random_interval( -50, 50 ) * 0.01; + st->cell[b].age = random_max( 0x0f ); + /* half energy for both plus some bonus for forking */ + st->cell[b].energy = + st->cell[b].energy/2 + random_max( 0x0f ); + /* forking makes me shrink */ + st->cell[b].growth = 0.995; + + /* this one initially goes into the oposite direction */ + st->cell[j].vx = -st->cell[b].vx; + st->cell[j].vy = -st->cell[b].vy; + /* same center */ + st->cell[j].x = st->cell[b].x; + st->cell[j].y = st->cell[b].y; + st->cell[j].age = random_max( 0x0f ); + st->cell[j].energy = (st->cell[b].energy); + st->cell[j].rotation = + ((double)random()/(double)RAND_MAX)*360.0; + st->cell[j].growth = st->cell[b].growth; + st->cell[j].radius = st->cell[b].radius; + ++j; + } else { + st->cell[b].vx = 0.0; + st->cell[b].vy = 0.0; + } + } + + st->num_cells = new_num_cells; + } + + /* for each find a direction to escape */ + if (st->num_cells > 1) { + for (b=0; bnum_cells; ++b) { + if (st->cell[b].energy > 0) { + double vx; + double vy; + double len; + + /* grow or shrink */ + st->cell[b].radius *= st->cell[b].growth; + /* find closest neighbour */ + min_dist = 100000.0; + min_index = 0; + for (j=0; jnum_cells; ++j) { + if (j!=b) { + const double dx = st->cell[b].x - st->cell[j].x; + const double dy = st->cell[b].y - st->cell[j].y; + + if (fabs(dx) < check_dist || fabs(dy) < check_dist) { + const double dist = dx*dx+dy*dy; + /*const double dist = sqrt( dx*dx+dy*dy );*/ + if (distcell[b].x - st->cell[min_index].x; + vy = st->cell[b].y - st->cell[min_index].y; + len = sqrt( vx*vx + vy*vy ); + if (len > 0.0001) { + st->cell[b].vx = vx/len; + st->cell[b].vy = vy/len; + } + st->cell[b].min_dist = len; + /* if not adult (radius too small) */ + if (st->cell[b].radius < adult_radius) { + /* if too small 60% stop shrinking */ + if (st->cell[b].radius < adult_radius * 0.6) { + st->cell[b].growth = 1.0; + } + /* at safe distance we start growing again */ + if (len > grow_dist) { + if (st->cell[b].energy > 30) { + st->cell[b].growth = 1.005; + } + } + } else { /* else keep size */ + st->cell[b].growth = 1.0; + } + } + } + } else { + st->cell[0].min_dist = 2*st->move_dist; + } + + /* now move em, snack and burn energy */ + for (b=0; bnum_cells; ++b) { + /* if still alive */ + if (st->cell[b].energy > 0) { + /* agility depends on amount of energy */ + double fac = (double)st->cell[b].energy / 50.0; + if (fac < 0.0) fac = 0.0; + if (fac > 1.0) fac = 1.0; + + st->cell[b].x += fac*(2.0 - + (4.0*(double)random() / (double)RAND_MAX) + + st->cell[b].vx); + st->cell[b].y += fac*(2.0 - + (4.0*(double)random() / (double)RAND_MAX) + + st->cell[b].vy); + + /* get older and burn energy */ + if (st->cell[b].energy > 0) { + st->cell[b].age++; + st->cell[b].energy--; + } + + /* have a snack */ + x = ((int)st->cell[b].x)/4; + if (x<0) x=0; if (x>=w4) x = w4-1; + y = ((int)st->cell[b].y)/4; + if (y<0) y=0; if (y>=h4) y = h4-1; + + offset = x+y*w4; + + /* don't eat if already satisfied */ + if (st->cell[b].energy < 100 && + st->food[offset] > 0) { + st->food[offset]--; + st->cell[b].energy++; + /* if you are hungry, eat more */ + if (st->cell[b].energy < 50 && + st->food[offset] > 0) { + st->food[offset]--; + st->cell[b].energy++; + } + } + } + } +} + +ENTRYPOINT void +reshape_glcells( ModeInfo *mi, int width, int height ) +{ + State *st = &sstate[MI_SCREEN(mi)]; + st->height = height; + st->width = width; + st->screen_scale = (double)width / 1600.0; + + st->radius = s_radius; + if (st->radius < 5) st->radius = 5; + if (st->radius > 200) st->radius = 200; + st->radius *= st->screen_scale; + + st->move_dist = s_min_dist; + if (st->move_dist < 1.0) st->move_dist = 1.0; + if (st->move_dist > 3.0) st->move_dist = 3.0; + st->move_dist *= st->radius; + + glViewport (0, 0, (GLint) width, (GLint) height); + + glMatrixMode(GL_PROJECTION); + glLoadIdentity(); + glOrtho( 0, width, height, 0, 200, 0 ); + glMatrixMode(GL_MODELVIEW); + glLoadIdentity(); + + if (st->food) free( st->food ); + st->food = (int *)malloc( ((width*height)/16)*sizeof(int) ); + /* create_cells( st );*/ +} + +ENTRYPOINT void +init_glcells( ModeInfo *mi ) +{ + int i, divisions; + State *st=0; + + if (!sstate) { + sstate = (State *) + calloc( MI_NUM_SCREENS(mi), sizeof(State) ); + if (!sstate) { + fprintf( stderr, "%s: out of memory\n", progname ); + exit(1); + } + } + st = &sstate[MI_SCREEN(mi)]; + + st->glx_context = init_GL(mi); + st->cell = 0; + st->num_cells = 0; + st->wire = MI_IS_WIREFRAME(mi); + +# ifdef HAVE_JWZGLES /* #### glPolygonMode other than GL_FILL unimplemented */ + st->wire = 0; +# endif + + /* get settings */ + st->max_cells = s_maxcells;; + if (st->max_cells < 50) st->max_cells = 50; + if (st->max_cells > 10000) st->max_cells = 10000; + + st->pause = s_pause; + if (st->pause < 0) st->pause = 0; + if (st->pause > 400) st->pause = 400; + st->pause_counter = st->pause; + + st->radius = s_radius; + if (st->radius < 5) st->radius = 5; + if (st->radius > 200) st->radius = 200; + + divisions = s_quality; + if (divisions < 0) divisions = 0; + if (divisions > 5) divisions = 5; + + st->num_seeds = s_seeds; + if (st->num_seeds < 1) st->num_seeds = 1; + if (st->num_seeds > 16) st->num_seeds = 16; + + st->minfood = s_minfood; + if (st->minfood < 0) st->minfood = 0; + if (st->minfood > 1000) st->minfood = 1000; + + st->maxfood = s_maxfood; + if (st->maxfood < 0) st->maxfood = 0; + if (st->maxfood > 1000) st->maxfood = 1000; + + if (st->maxfood < st->minfood) st->maxfood = st->minfood+1; + + st->keep_old_cells = s_keepold; + + st->divide_age = s_divideage; + if (st->divide_age < 1) st->divide_age = 1; + if (st->divide_age > 1000) st->divide_age = 1000; + + st->move_dist = s_min_dist; + if (st->move_dist < 1.0) st->move_dist = 1.0; + if (st->move_dist > 3.0) st->move_dist = 3.0; + st->move_dist *= st->radius; + + for (i=0; icell_list[i] = -1; + st->nucleus_list = -1; + st->food = 0; + + st->sphere = create_sphere( st, divisions ); + st->disturbance = + (double *) malloc( st->sphere->num_vertex*sizeof(double) ); + for (i=0; isphere->num_vertex; ++i) { + st->disturbance[i] = + 0.05-((double)random()/(double)RAND_MAX*0.1); + } + + create_nucleus_texture( st ); + + reshape_glcells (mi, MI_WIDTH(mi), MI_HEIGHT(mi)); +} + +ENTRYPOINT void +draw_glcells( ModeInfo *mi ) +{ + State *st = &sstate[MI_SCREEN(mi)]; + Display *dpy = MI_DISPLAY(mi); + Window window = MI_WINDOW(mi); + + if (!st->glx_context) return; + + glXMakeCurrent( MI_DISPLAY(mi), MI_WINDOW(mi), + *(st->glx_context) ); + + mi->polygon_count = render( st ); + + if (mi->fps_p) do_fps (mi); + + glFinish(); + glXSwapBuffers( dpy, window ); +} + +ENTRYPOINT void +release_glcells( ModeInfo *mi ) +{ + int i; + State *st = &sstate[MI_SCREEN(mi)]; + + /* nuke everything before exit */ + if (st->sphere) free_Object( st->sphere ); + if (st->food) free( st->food ); + for (i=0; icell_list[i] != -1) { + glDeleteLists( st->cell_list[i], 1 ); + } + } + if (st->cell) free( st->cell ); + free( st->disturbance ); + glDeleteTextures( 1, &st->texture_name ); + free( st->texture ); +} + +XSCREENSAVER_MODULE( "GLCells", glcells ) diff --git a/hacks/glx/glcells.man b/hacks/glx/glcells.man new file mode 100644 index 00000000..6c1e7e9b --- /dev/null +++ b/hacks/glx/glcells.man @@ -0,0 +1,97 @@ +.TH XScreenSaver 1 "June 2007" +.SH NAME +glcells \- growing cells graphics hack +.SH SYNOPSIS +.B glcells +[\-display \fIhost:display.screen\fP] [\-window] [\-root] [\-install] +[\-visual \fIvisual\fP] +[\-delay \fInum\fP] [\-pause \fInum\fP] [\-maxcells \fInum\fP] +[\-radius \fInum\fP] [\-seeds \fInum\fP] [\-quality \fInum\fP] +[\-minfood \fInum\fP] [\-maxfood \fInum\fP] [\-divideage \fInum\fP] +[\-mindist \fInum\fP] +[\-keepold] +[\-wireframe] +[\-fps] +.SH DESCRIPTION +The \fIglcells\fP program draws cells that divide exponentially, eat and eventually die. +.SH OPTIONS +.I glcells +accepts the following options: +.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 \-install +Install a private colormap for the window. +.TP 8 +.B \-visual \fIvisual\fP\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 \-pause \fInum\fP\fP +Specifies the pause at the end of the animation (all cells dead or maximum amount of cells reached). Unit is in frames, default 20. +.TP 8 +.B \-maxcells \fInum\fP\fP +Specifies the maximum number of cells on screen (dead cells also count, even if invisible). Default is 800. +.TP 8 +.B \-radius \fInum\fP\fP +Specifies the radius of the cells. Default is 40. +.TP 8 +.B \-seeds \fInum\fP\fP +Specifies the number of cells when animation starts. Default is 1. +.TP 8 +.B \-quality \fInum\fP\fP +Specifies subdivision quality of the spheres used to draw the cells [0...5]. Default is 3. +.TP 8 +.B \-minfood \fInum\fP\fP +Food is ditributed randomly on the screen (Yes, the cells need to eat). This parameter specifies the +minimum amount of food per pixel. Default is 5. +.TP 8 +.B \-maxfood \fInum\fP\fP +Food is ditributed randomly on the screen (Yes, the cells need to eat). This parameter specifies the +maximum amount of food per pixel. Default is 20. +.TP 8 +.B \-divideage \fInum\fP\fP +Specifies the minimum age in frames a cell needs to have before beeing able to divide. Default is 20 +.TP 8 +.B \-mindist \fInum\fP\fP +Specifies the minimum distance between cells. Default 1.4 +.TP 8 +.B \-delay \fInum\fP +How long to pause between frames. Default is 20000, or 0.02 second. +.TP 8 +.B \-fps +Display the current frame rate, CPU load, and polygon count. +.TP 8 +.B \-wireframe +Draw wireframe only. +.TP 8 +.B \-keepold +Dead cells stay on 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) +.BR xscreensaver\-demo (1), +.SH COPYRIGHT +Copyright \(co 2007 by Matthias Toussaint. 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 +Matthias Toussaint , 17-Jun-2007, http://www.mtoussaint.de/bits.html. + diff --git a/hacks/glx/gleidescope.c b/hacks/glx/gleidescope.c new file mode 100644 index 00000000..54074e65 --- /dev/null +++ b/hacks/glx/gleidescope.c @@ -0,0 +1,1630 @@ +/* -*- Mode: C; tab-width: 4 -*- */ +/* vim: set ai ts=4 sw=4: */ + +#if !defined( lint ) && !defined( SABER ) +/*static const char sccsid[] = "@(#)gleidescope.c 1.0 03/06/27 xlockmore";*/ +#endif + +/* enable -grab switch for animations */ +#undef GRAB + +#undef DISPLAY_TEXTURE + +/*- + * Permission to use, copy, modify, and distribute this software and its + * documentation for any purpose and without fee is hereby granted, + * provided that the above copyright notice appear in all copies and that + * both that copyright notice and this permission notice appear in + * supporting documentation. + * + * This file is provided AS IS with no warranties of any kind. The author + * shall have no liability with respect to the infringement of copyrights, + * trade secrets or any patents by this file or any part thereof. In no + * event will the author be liable for any lost revenue or profits or + * other special, indirect and consequential damages. + * + * Revision History: + * + * 20030627 1.0 acd First Release. + * Texture loading code from 'glplanet' + * by Jamie Zawinski + * 20030810 1.1 acd Added size flag. + * Now grabs screen / video / picture + * (uses code from 'glslideshow' by + * Mike Oliphant, Ben Buxton, Jamie Zawinski). + * Added -duration. + * Added mouse code. + * Added fade code (also from glslideshow). + * 20031013 1.2 acd Migrated to compile without warnings under + * xscreensaver 4.13. + * 20031023 1.3 acd Better code to limit twisting speeds. + * Tweaked initial rotation values. + * Move, Rotate, Zoom now chosen at random if + * no preference is given. + * Made grid slightly bigger so you can't see + * the edge when zooming and moving. + * 20061226 1.4 acd Now uses GL Display Lists. + * 20070318 1.5 acd Generates textures. + * Fixed texture size problem (and introduced another). + * 20070412 1.6 acd Textures now have independant sizes. + * 20070413 1.7 acd Added Lissajous movement pattern. + * 20070414 1.8 acd Added corners movement pattern. + * 20080319 1.9 acd Changes to arguments for saner gleidescope.xml. + * + * TODO + * generate textures myself - render random shapes to 256x256 texture. (done) + * lower res for checks and random - use 256 and 4x4 or 8x8 pixels. (disabled for now) + * gnome-saver doesn't let you specify source directory so add that to this. + * image loading routine is too slow - rotation grinds to a halt - stop using it. (better in version 5) + * image loading also looks bad for non-square images - edges are black. (fixed) + * possible to see edge of the world on widescreen terminals - use larger grid and hidden hex removal? + * fading textures may have different max_tx - use two sets. (done) + * choice of movement patterns. (3 implemented, chooseable at compile time) + * look into rangle and tangle. + */ + +/* +**---------------------------------------------------------------------------- +** Defines +**---------------------------------------------------------------------------- +*/ + +#ifdef STANDALONE +# define DEFAULTS \ + "*delay: 20000 \n" \ + "*showFPS: False \n" \ + "*size: 0 \n" \ + "*useSHM: True \n" + +# define refresh_gleidescope 0 +# include "xlockmore.h" /* from the xscreensaver distribution */ +#else /* !STANDALONE */ +# include "xlock.h" /* from the xlockmore distribution */ +#endif /* !STANDALONE */ + +#ifdef USE_GL + +#include "colors.h" +#include "xpm-ximage.h" +#include "grab-ximage.h" + +#ifdef GRAB +void grab_frame(Display *display, Window window); +#endif + +/* acd TODO should all these be in gleidestruct? */ +/* they can't be, because of the idiotic way the xlockmore "argtype vars" + interface works. -jwz */ +#ifdef GRAB +static Bool grab; /* grab images */ +#endif +static Bool move; /* moving camera */ +static Bool nomove; /* no moving camera */ +static Bool rotate; /* rotate in place */ +static Bool norotate; /* no rotate in place */ +static Bool zoom; /* zooming camera */ +static Bool nozoom; /* no zooming camera */ +static char *image; /* name of texture to load */ +static int duration; /* length of time to display grabbed image */ + +#define MAX_CAM_SPEED 1.0 +#define MAX_ANGLE_VEL 1.0 +#define INITIAL_ANGLE_VEL 0.2 +#define INITIAL_ANGLE_ACC 0.001 +#define TWISTING_PROBABILITY 1000 /* 1 in ... of change of acceleration */ + +#define RADIANS (M_PI / 180) +#define ANGLE_120 (M_PI * 2 / 3) +#define ANGLE_240 (M_PI * 4 / 3) + +#define DEF_GRAB "False" +#define DEF_MOVE "False" +#define DEF_NOMOVE "False" +#define DEF_ROTATE "False" +#define DEF_NOROTATE "False" +#define DEF_ZOOM "False" +#define DEF_NOZOOM "False" +#define DEF_IMAGE "DEFAULT" +#define DEF_DURATION "30" + + +static XrmOptionDescRec opts[] = +{ +#ifdef GRAB + {"-grab", ".gleidescope.grab", XrmoptionNoArg, "true"}, +#endif + {"-move", ".gleidescope.move", XrmoptionNoArg, "true"}, + {"-no-move", ".gleidescope.nomove", XrmoptionNoArg, "true"}, + {"-rotate", ".gleidescope.rotate", XrmoptionNoArg, "true"}, + {"-no-rotate", ".gleidescope.norotate", XrmoptionNoArg, "true"}, + {"-zoom", ".gleidescope.zoom", XrmoptionNoArg, "true"}, + {"-no-zoom", ".gleidescope.nozoom", XrmoptionNoArg, "true"}, + {"-image", ".gleidescope.image", XrmoptionSepArg, "DEFAULT"}, + {"-duration", ".gleidescope.duration", XrmoptionSepArg, "30"}, +}; + + +static argtype vars[] = { +#ifdef GRAB + {&grab, "grab", "Grab", DEF_GRAB, t_Bool}, +#endif + {&move, "move", "Move", DEF_MOVE, t_Bool}, + {&nomove, "nomove", "noMove", DEF_NOMOVE, t_Bool}, + {&rotate, "rotate", "Rotate", DEF_ROTATE, t_Bool}, + {&norotate, "norotate", "noRotate", DEF_NOROTATE, t_Bool}, + {&zoom, "zoom", "Zoom", DEF_ZOOM, t_Bool}, + {&nozoom, "nozoom", "noZoom", DEF_NOZOOM, t_Bool}, + {&image, "image", "Image", DEF_IMAGE, t_String}, + {&duration, "duration", "Duration", DEF_DURATION, t_Int}, +}; + +static OptionStruct desc[] = { +#ifdef GRAB + {"-grab", "grab images to create animation"}, +#endif + {"-move", "camera will move"}, + {"-no-move", "camera won't move"}, + {"-rotate", "camera will rotate"}, + {"-no-rotate", "camera won't rotate"}, + {"-zoom", "camera will zoom"}, + {"-no-zoom", "camera won't zoom"}, + {"-image", "xpm / xbm image file to use for texture"}, + {"-duration", "length of time texture will be used"}, +}; + +ENTRYPOINT ModeSpecOpt gleidescope_opts = { + sizeof opts / sizeof opts[0], opts, + sizeof vars / sizeof vars[0], vars, + desc +}; + +#ifdef USE_MODULES +ModStruct gleidescope_description = { + "gleidescope", "init_gleidescope", "draw_gleidescope", "release_gleidescope", + "draw_gleidescope", "init_gleidescope", NULL, &gleidescope_opts, + 1000, 1, 2, 1, 4, 1.0, "", + "GL Kaleidescope", 0, NULL}; +#endif + +/* +**----------------------------------------------------------------------------- +** Typedefs +**----------------------------------------------------------------------------- +*/ + +typedef struct hex_s { + GLfloat x, y, z; /* position */ +} hex_t; + +typedef struct { + GLfloat x; + GLfloat y; + GLfloat z; +} vectorf; + +typedef struct { + GLfloat x; + GLfloat y; +} vector2f; + +typedef struct { + GLuint id; /* opengl texture id */ + GLfloat width, height; /* texture width and height */ + GLfloat min_tx, min_ty; /* minimum texture sizes */ + GLfloat max_tx, max_ty; /* maximum texture sizes */ + time_t start_time; + Bool button_down_p; + Bool mipmap_p; + Bool waiting_for_image_p; + /* r_phase is for triangle rotation speed */ + GLfloat x_period, y_period, r_period; + GLfloat x_phase, y_phase, r_phase; +} texture; + +#define MAX_FADE 500 /* number of fade cycles */ + +typedef struct { + float cam_x_speed, cam_z_speed, cam_y_speed; + int cam_x_phase, cam_z_phase, cam_y_phase; + float tic; + GLXContext *glx_context; + Window window; + texture textures[2]; /* texture handles */ + GLuint visible; /* index for current texture */ + GLint fade; + time_t start_time; + Bool button_down_p; + + int size; + int list; + + float tangle; /* texture angle (degrees) */ + float tangle_vel; /* texture velocity */ + float tangle_acc; /* texture acceleration */ + + float rangle; /* rotate angle */ + float rangle_vel; /* rotate velocity */ + float rangle_acc; /* rotate acceleration */ + + /* mouse */ + int xstart; + int ystart; + double xmouse; + double ymouse; + + Bool mipmap_p; + Bool waiting_for_image_p; + +} gleidestruct; + +#define frandrange(x, y) (x + frand(y - x)) + +#define XOFFSET (0.8660254f) /* sin 60' */ +#define YOFFSET (1.5000000f) /* cos 60' + 1 */ + +#if 0 + +#define SIZE 3 + +/* generates a grid with edges of given size */ +/* acd TODO - replace hex[] with this and allow size and distance as parameters */ + +int +generate_grid(int size) + + int i, x, y; + + gp->size--; + + i = gp->size; + for (y = -size ; y <= size ; y++) { + for (x = -i ; x <= i ; x += 2) { + printf("{XOFFSET * %d, YOFFSET * %d, 0},\n", x, y); + } + printf("\n"); + if (y < 0) { + i++; + } else { + i--; + } + } + return 0; +} +#endif + +/* acd - this is terrible - 120+ hexes */ +static const hex_t hex[] = { + /* edges of size 7 */ + /* number of hexagons required to cover screen depends on camera distance */ + /* at a distance of 10 this is just about enough. */ + {XOFFSET * -6, YOFFSET * -6, 0}, + {XOFFSET * -4, YOFFSET * -6, 0}, + {XOFFSET * -2, YOFFSET * -6, 0}, + {XOFFSET * 0, YOFFSET * -6, 0}, + {XOFFSET * 2, YOFFSET * -6, 0}, + {XOFFSET * 4, YOFFSET * -6, 0}, + {XOFFSET * 6, YOFFSET * -6, 0}, + + {XOFFSET * -7, YOFFSET * -5, 0}, + {XOFFSET * -5, YOFFSET * -5, 0}, + {XOFFSET * -3, YOFFSET * -5, 0}, + {XOFFSET * -1, YOFFSET * -5, 0}, + {XOFFSET * 1, YOFFSET * -5, 0}, + {XOFFSET * 3, YOFFSET * -5, 0}, + {XOFFSET * 5, YOFFSET * -5, 0}, + {XOFFSET * 7, YOFFSET * -5, 0}, + + {XOFFSET * -8, YOFFSET * -4, 0}, + {XOFFSET * -6, YOFFSET * -4, 0}, + {XOFFSET * -4, YOFFSET * -4, 0}, + {XOFFSET * -2, YOFFSET * -4, 0}, + {XOFFSET * 0, YOFFSET * -4, 0}, + {XOFFSET * 2, YOFFSET * -4, 0}, + {XOFFSET * 4, YOFFSET * -4, 0}, + {XOFFSET * 6, YOFFSET * -4, 0}, + {XOFFSET * 8, YOFFSET * -4, 0}, + + {XOFFSET * -9, YOFFSET * -3, 0}, + {XOFFSET * -7, YOFFSET * -3, 0}, + {XOFFSET * -5, YOFFSET * -3, 0}, + {XOFFSET * -3, YOFFSET * -3, 0}, + {XOFFSET * -1, YOFFSET * -3, 0}, + {XOFFSET * 1, YOFFSET * -3, 0}, + {XOFFSET * 3, YOFFSET * -3, 0}, + {XOFFSET * 5, YOFFSET * -3, 0}, + {XOFFSET * 7, YOFFSET * -3, 0}, + {XOFFSET * 9, YOFFSET * -3, 0}, + + {XOFFSET * -10, YOFFSET * -2, 0}, + {XOFFSET * -8, YOFFSET * -2, 0}, + {XOFFSET * -6, YOFFSET * -2, 0}, + {XOFFSET * -4, YOFFSET * -2, 0}, + {XOFFSET * -2, YOFFSET * -2, 0}, + {XOFFSET * 0, YOFFSET * -2, 0}, + {XOFFSET * 2, YOFFSET * -2, 0}, + {XOFFSET * 4, YOFFSET * -2, 0}, + {XOFFSET * 6, YOFFSET * -2, 0}, + {XOFFSET * 8, YOFFSET * -2, 0}, + {XOFFSET * 10, YOFFSET * -2, 0}, + + {XOFFSET * -11, YOFFSET * -1, 0}, + {XOFFSET * -9, YOFFSET * -1, 0}, + {XOFFSET * -7, YOFFSET * -1, 0}, + {XOFFSET * -5, YOFFSET * -1, 0}, + {XOFFSET * -3, YOFFSET * -1, 0}, + {XOFFSET * -1, YOFFSET * -1, 0}, + {XOFFSET * 1, YOFFSET * -1, 0}, + {XOFFSET * 3, YOFFSET * -1, 0}, + {XOFFSET * 5, YOFFSET * -1, 0}, + {XOFFSET * 7, YOFFSET * -1, 0}, + {XOFFSET * 9, YOFFSET * -1, 0}, + {XOFFSET * 11, YOFFSET * -1, 0}, + + {XOFFSET * -12, YOFFSET * 0, 0}, + {XOFFSET * -10, YOFFSET * 0, 0}, + {XOFFSET * -8, YOFFSET * 0, 0}, + {XOFFSET * -6, YOFFSET * 0, 0}, + {XOFFSET * -4, YOFFSET * 0, 0}, + {XOFFSET * -2, YOFFSET * 0, 0}, + {XOFFSET * 0, YOFFSET * 0, 0}, + {XOFFSET * 2, YOFFSET * 0, 0}, + {XOFFSET * 4, YOFFSET * 0, 0}, + {XOFFSET * 6, YOFFSET * 0, 0}, + {XOFFSET * 8, YOFFSET * 0, 0}, + {XOFFSET * 10, YOFFSET * 0, 0}, + {XOFFSET * 12, YOFFSET * 0, 0}, + + {XOFFSET * -11, YOFFSET * 1, 0}, + {XOFFSET * -9, YOFFSET * 1, 0}, + {XOFFSET * -7, YOFFSET * 1, 0}, + {XOFFSET * -5, YOFFSET * 1, 0}, + {XOFFSET * -3, YOFFSET * 1, 0}, + {XOFFSET * -1, YOFFSET * 1, 0}, + {XOFFSET * 1, YOFFSET * 1, 0}, + {XOFFSET * 3, YOFFSET * 1, 0}, + {XOFFSET * 5, YOFFSET * 1, 0}, + {XOFFSET * 7, YOFFSET * 1, 0}, + {XOFFSET * 9, YOFFSET * 1, 0}, + {XOFFSET * 11, YOFFSET * 1, 0}, + + {XOFFSET * -10, YOFFSET * 2, 0}, + {XOFFSET * -8, YOFFSET * 2, 0}, + {XOFFSET * -6, YOFFSET * 2, 0}, + {XOFFSET * -4, YOFFSET * 2, 0}, + {XOFFSET * -2, YOFFSET * 2, 0}, + {XOFFSET * 0, YOFFSET * 2, 0}, + {XOFFSET * 2, YOFFSET * 2, 0}, + {XOFFSET * 4, YOFFSET * 2, 0}, + {XOFFSET * 6, YOFFSET * 2, 0}, + {XOFFSET * 8, YOFFSET * 2, 0}, + {XOFFSET * 10, YOFFSET * 2, 0}, + + {XOFFSET * -9, YOFFSET * 3, 0}, + {XOFFSET * -7, YOFFSET * 3, 0}, + {XOFFSET * -5, YOFFSET * 3, 0}, + {XOFFSET * -3, YOFFSET * 3, 0}, + {XOFFSET * -1, YOFFSET * 3, 0}, + {XOFFSET * 1, YOFFSET * 3, 0}, + {XOFFSET * 3, YOFFSET * 3, 0}, + {XOFFSET * 5, YOFFSET * 3, 0}, + {XOFFSET * 7, YOFFSET * 3, 0}, + {XOFFSET * 9, YOFFSET * 3, 0}, + + {XOFFSET * -8, YOFFSET * 4, 0}, + {XOFFSET * -6, YOFFSET * 4, 0}, + {XOFFSET * -4, YOFFSET * 4, 0}, + {XOFFSET * -2, YOFFSET * 4, 0}, + {XOFFSET * 0, YOFFSET * 4, 0}, + {XOFFSET * 2, YOFFSET * 4, 0}, + {XOFFSET * 4, YOFFSET * 4, 0}, + {XOFFSET * 6, YOFFSET * 4, 0}, + {XOFFSET * 8, YOFFSET * 4, 0}, + + {XOFFSET * -7, YOFFSET * 5, 0}, + {XOFFSET * -5, YOFFSET * 5, 0}, + {XOFFSET * -3, YOFFSET * 5, 0}, + {XOFFSET * -1, YOFFSET * 5, 0}, + {XOFFSET * 1, YOFFSET * 5, 0}, + {XOFFSET * 3, YOFFSET * 5, 0}, + {XOFFSET * 5, YOFFSET * 5, 0}, + {XOFFSET * 7, YOFFSET * 5, 0}, + + {XOFFSET * -6, YOFFSET * 6, 0}, + {XOFFSET * -4, YOFFSET * 6, 0}, + {XOFFSET * -2, YOFFSET * 6, 0}, + {XOFFSET * 0, YOFFSET * 6, 0}, + {XOFFSET * 2, YOFFSET * 6, 0}, + {XOFFSET * 4, YOFFSET * 6, 0}, + {XOFFSET * 6, YOFFSET * 6, 0}, +}; + +/* +**---------------------------------------------------------------------------- +** Local Variables +**---------------------------------------------------------------------------- +*/ + +static gleidestruct *gleidescope = NULL; + +#if 0 +/* + *load defaults in config structure + */ +static void setdefaultconfig(void) +{ +#ifdef GRAB + grab = False; +#endif + move = False; + rotate = False; + zoom = False; + image = NULL; +} +#endif + +ENTRYPOINT Bool +gleidescope_handle_event(ModeInfo *mi, XEvent *event) +{ + gleidestruct *gp = &gleidescope[MI_SCREEN(mi)]; + + /* + printf("event:%d\n", event->xany.type); + printf("button:%d\n", event->xbutton.button); + */ + switch(event->xany.type) + { + case ButtonPress: + + if (event->xbutton.button == Button1 || + event->xbutton.button == Button3) + { + /* store initial values of mouse */ + gp->xstart = event->xbutton.x; + gp->ystart = event->xbutton.y; + + /* button is down */ + gp->button_down_p = True; + return True; + } +#if 0 /* TODO */ + else if (event->xbutton.button == Button4) + { + /* zoom in */ + return True; + } + else if (event->xbutton.button == Button5) + { + /* zoom out */ + return True; + } +#endif + break; + + case ButtonRelease: + + if (event->xbutton.button == Button1 || + event->xbutton.button == Button3) + { + /* button is up */ + gp->button_down_p = False; + return True; + } + break; + + case MotionNotify: + + if (gp->button_down_p) + { + /* update mouse position */ + gp->xmouse += (double)(event->xmotion.x - gp->xstart) / MI_WIDTH(mi); + gp->ymouse += (double)(event->xmotion.y - gp->ystart) / MI_HEIGHT(mi); + gp->xstart = event->xmotion.x; + gp->ystart = event->xmotion.y; + + return True; + } + break; + } + + return False; +} + + +static void +image_loaded_cb (const char *filename, XRectangle *geometry, + int image_width, int image_height, + int texture_width, int texture_height, + void *closure) +{ + texture *tp = (texture *) closure; + +#if 0 + gp->max_tx = (GLfloat) image_width / texture_width; + gp->max_ty = (GLfloat) image_height / texture_height; +#endif + + /* new - taken from flipscreen */ + tp->width = texture_width; + tp->height = texture_height; + tp->min_tx = (GLfloat) geometry->x / tp->width; + tp->min_ty = (GLfloat) geometry->y / tp->height; + tp->max_tx = (GLfloat) (geometry->x + geometry->width) / tp->width; + tp->max_ty = (GLfloat) (geometry->y + geometry->height) / tp->height; + +#ifdef DEBUG + printf("Image w,h: (%d, %d)\n", image_width, image_height); + printf("Texture w,h: (%d, %d)\n", texture_width, texture_height); + printf("Geom x,y: (%d, %d)\n", geometry->x, geometry->y); + printf("Geom w,h: (%d, %d)\n", geometry->width, geometry->height); + printf("Max Tx,Ty: (%f, %f)\n", tp->max_tx, tp->max_ty); +#endif + + glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, + (tp->mipmap_p ? GL_LINEAR_MIPMAP_LINEAR : GL_LINEAR)); + + tp->waiting_for_image_p = False; + tp->start_time = time ((time_t *) 0); +} + +static void +getSnapshot(ModeInfo *mi, texture *texture) +{ + gleidestruct *gp = &gleidescope[MI_SCREEN(mi)]; + +#ifdef DEBUG + printf("getSnapshot"); +#endif + + if (MI_IS_WIREFRAME(mi)) + return; + + gp->mipmap_p = True; + load_texture_async (mi->xgwa.screen, mi->window, + *gp->glx_context, 0, 0, gp->mipmap_p, + texture->id, image_loaded_cb, texture); + texture->start_time = time((time_t *)0); +} + +#define TEXTURE_SIZE 256 + +static void +plot(unsigned char *buffer, int x, int y, int r, int g, int b, int a) { + int c; + if (x < 0 || x >= TEXTURE_SIZE || y < 0 || y >= TEXTURE_SIZE) { + return; + } + c = ((x * TEXTURE_SIZE) + y) * 4; + /*printf("(%d,%d)[%d]\n", x, y, c);*/ + buffer[c + 0] = r; + buffer[c + 1] = g; + buffer[c + 2] = b; + buffer[c + 3] = a; +} + +#if 0 +static void +plot2(unsigned char *buffer, int x, int y, int r, int g, int b, int a) { + int c; + if (x < 0 || x >= TEXTURE_SIZE || y < 0 || y >= TEXTURE_SIZE) { + return; + } + c = ((x * TEXTURE_SIZE) + y) * 4; + /*printf("(%d,%d)[%d]\n", x, y, c);*/ + buffer[c + 0] = r; + buffer[c + 1] = g; + buffer[c + 2] = b; + buffer[c + 3] = a; + + if (y + 1 < TEXTURE_SIZE) { + buffer[c + 4] = r; + buffer[c + 5] = g; + buffer[c + 6] = b; + buffer[c + 7] = a; + } + + if (x + 1 < TEXTURE_SIZE) { + c += (TEXTURE_SIZE * 4); + buffer[c + 0] = r; + buffer[c + 1] = g; + buffer[c + 2] = b; + buffer[c + 3] = a; + if (y + 1 < TEXTURE_SIZE) { + buffer[c + 4] = r; + buffer[c + 5] = g; + buffer[c + 6] = b; + buffer[c + 7] = a; + } + } +} +#endif + +/* draw geometric shapes to texture */ +/* modifies passed in buffer */ +static void +draw_shapes (unsigned char *buffer) { + int a = 0xff; + int x, y, w, h; + int i, j; + int s; + float left, right; + + for (i = 0 ; i < TEXTURE_SIZE * TEXTURE_SIZE * 4 ; i += 4) { + buffer[i + 0] = 0x00; + buffer[i + 1] = 0x00; + buffer[i + 2] = 0x00; + buffer[i + 3] = 0xff; + } + + for (s = 0 ; s < 25 ; s++) { + int shape = random() % 3; + + /* 8 bits */ + int r = (random() & 0xff); + int g = (random() & 0xff); + int b = (random() & 0xff); + + switch (shape) { + case 0: + /* rectangle */ + x = (random() % TEXTURE_SIZE) - (TEXTURE_SIZE / 4); /* top left */ + y = (random() % TEXTURE_SIZE) - (TEXTURE_SIZE / 4); + w = 10 + random() % (TEXTURE_SIZE / 4); /* size */ + h = 10 + random() % (TEXTURE_SIZE / 4); +#ifdef DEBUG + printf("Rectangle: (%d, %d)(%d, %d)\n", x, y, w, h); +#endif + if (x < 0) { + x = 0; + } + if (y < 0) { + y = 0; + } + for (i = x ; i < x + w && i < TEXTURE_SIZE; i++) { + for (j = y ; j < y + h && j < TEXTURE_SIZE; j++) { + plot(buffer, i, j, r, g, b, a); + } + } + break; + + case 1: + /* circle */ + x = random() % TEXTURE_SIZE; /* centre */ + y = random() % TEXTURE_SIZE; + h = 10 + random() % (TEXTURE_SIZE / 8); /* radius */ +#ifdef DEBUG + printf("Circle: %d, %d, %d\n", x, y, h); +#endif + for (i = 0 ; i < h ; i++) { + int xdist = i * i; + for (j = 0 ; j < h ; j++) { + int ydist = j * j; + /* + printf("xdist: %d\n", xdist); + printf("ydist: %d\n", ydist); + printf("radius: %d\n", h * h); + */ + if ((xdist + ydist) < (h * h)) { + plot(buffer, x + i, y + j, r, b, g, a); + /* check we haven't already done these */ + if (j != 0) { + plot(buffer, x + i, y - j, r, b, g, a); + } + if (i != 0) { + plot(buffer, x - i, y + j, r, b, g, a); + if (j != 0) { + plot(buffer, x - i, y - j, r, b, g, a); + } + } + } + } + } + break; + + case 2: + /* triangle */ + x = random() % TEXTURE_SIZE; /* top */ + y = random() % TEXTURE_SIZE; + h = 10 + random() % (TEXTURE_SIZE / 4); /* height */ +#ifdef DEBUG + printf("Triangle: %d, %d, %d\n", x, y, h); +#endif + left = x; + right = x; + for (i = 0 ; i < h ; i++) { + for (j = left ; j < right ; j++) { + plot(buffer, j, y + i, r, g, b, a); + } + left -= .5; + right += .5; + } + break; + } + } +} + +static void +setup_random_texture (ModeInfo *mi, texture *texture) +{ + int width = 0, height = 0; + char buf[1024]; + unsigned char *my_data = NULL; +#if 0 + int i, j, c; + int style; + int r0, g0, b0, a0, r1, g1, b1, a1; +#endif + +#ifdef DEBUG + printf("RandomTexture\n"); +#endif + + /* use this texture */ + glBindTexture(GL_TEXTURE_2D, texture->id); + + clear_gl_error(); + + /* + * code for various generated patterns - noise, stripes, checks etc. + * random geometric shapes looked the best. + */ + +#if 0 + style = random() & 0x3; + r0 = random() & 0xff; + g0 = random() & 0xff; + b0 = random() & 0xff; + a0 = 0xff; + r1 = random() & 0xff; + g1 = random() & 0xff; + b1 = random() & 0xff; + a1 = 0xff; + + switch (style) { + case 0: /* random */ + printf("Random0\n"); + height = width = TEXTURE_SIZE; + my_data = (void *)malloc(width * height * 4); + for (i = 0 ; i < width ; i += 2) { + for (j = 0 ; j < height ; j += 2) { + r0 = random() & 0xff; + g0 = random() & 0xff; + b0 = random() & 0xff; + a0 = 0xff; + plot2(my_data, i, j, r0, g0, b0, a0); + } + } + break; + + case 1: /* shapes */ +#endif +#ifdef DEBUG + printf("Shapes\n"); +#endif + height = width = TEXTURE_SIZE; + my_data = (void *)malloc(width * height * 4); + draw_shapes(my_data); +#if 0 + break; + + case 2: /* check */ + printf("Check\n"); + height = width = TEXTURE_SIZE; + my_data = (void *)malloc(width * height * 4); + for (i = 0 ; i < height ; i += 2) { + for (j = 0 ; j < width ; j += 2) { + if (((i + j) & 0x3) == 0) { + plot2(my_data, i, j, r0, g0, b0, a0); + } else { + plot2(my_data, i, j, r1, g1, b1, a1); + } + } + } + break; + + case 3: /* random stripes */ + printf("Stripes 2\n"); + height = width = TEXTURE_SIZE; + my_data = (void *)malloc(width * height * 4); + for (i = 0 ; i < height ; i += 2) { + r0 = random() & 0xff; + g0 = random() & 0xff; + b0 = random() & 0xff; + a0 = 0xff; + for (j = 0 ; j < width ; j += 2) { + plot2(my_data, i, j, r0, g0, b0, a0); + } + } + break; + } +#endif + + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, + width, height, 0, + GL_RGBA, GL_UNSIGNED_BYTE, my_data); + sprintf (buf, "random texture: (%dx%d)", + width, height); + check_gl_error(buf); + + /* setup parameters for texturing */ + glPixelStorei(GL_UNPACK_ALIGNMENT, 4); + glPixelStorei(GL_UNPACK_ROW_LENGTH, width); + + 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); + if (random() & 0x1) { + glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + } else { + glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + } + + if (my_data != NULL) { + free(my_data); + my_data = NULL; + } + + /* use full texture */ + /* acd - was 1.0 */ + texture->min_tx = 0.0; + texture->max_tx = 2.0; + texture->min_ty = 0.0; + texture->max_ty = 2.0; + texture->start_time = time((time_t *)0); +} + +static void +setup_file_texture (ModeInfo *mi, char *filename, texture *texture) +{ + Display *dpy = mi->dpy; + Visual *visual = mi->xgwa.visual; + char buf[1024]; + + Colormap cmap = mi->xgwa.colormap; + XImage *image = xpm_file_to_ximage (dpy, visual, cmap, filename); + +#ifdef DEBUG + printf("FileTexture\n"); +#endif + + /* use this texture */ + glBindTexture(GL_TEXTURE_2D, texture->id); + + clear_gl_error(); + 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); + + /* setup parameters for texturing */ + glPixelStorei(GL_UNPACK_ALIGNMENT, 4); + glPixelStorei(GL_UNPACK_ROW_LENGTH, image->width); + + 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); + + /* use full texture */ + texture->min_tx = 0.0; + texture->max_tx = 1.0; + texture->min_ty = 0.0; + texture->max_ty = 1.0; + texture->start_time = time((time_t *)0); +} + +static void +setup_texture(ModeInfo * mi, texture *texture) +{ + gleidestruct *gp = &gleidescope[MI_SCREEN(mi)]; + + if (!image || !*image || !strcmp(image, "DEFAULT")) { + /* no image specified - use system settings */ +#ifdef DEBUG + printf("SetupTexture: get_snapshot\n"); +#endif + getSnapshot(mi, texture); + } else { + if (strcmp(image, "GENERATE") == 0) { +#ifdef DEBUG + printf("SetupTexture: random_texture\n"); +#endif + setup_random_texture(mi, texture); + } else { + /* use supplied image file */ +#ifdef DEBUG + printf("SetupTexture: file_texture\n"); +#endif + setup_file_texture(mi, image, texture); + } + } + /* copy start time from texture */ + gp->start_time = texture->start_time; + + check_gl_error("texture initialization"); + + /* acd + * resultant loaded image is upside down BUT + * it's a kaledescope and half of the hexagon is backwards anyway... + */ + + /* TODO: values for lissajous movement */ + texture->x_period = frandrange(-2.0, 2.0); + texture->y_period = frandrange(-2.0, 2.0); + texture->r_period = frandrange(-2.0, 2.0); + texture->x_phase = frand(M_PI * 2); + texture->y_phase = frand(M_PI * 2); + texture->r_phase = frand(M_PI * 2); +#ifdef DEBUG + printf("XPeriod %f XPhase %f\n", texture->x_period, texture->x_phase); + printf("YPeriod %f YPhase %f\n", texture->y_period, texture->y_phase); + printf("RPeriod %f RPhase %f\n", texture->r_period, texture->r_phase); +#endif +} + +#define VERTEX0 glVertex3f( 0.0000f, 0.000f, 0.0f); +#define VERTEX1 glVertex3f( 0.0000f, 1.000f, 0.0f); +#define VERTEX2 glVertex3f( XOFFSET, 0.500f, 0.0f); +#define VERTEX3 glVertex3f( XOFFSET, -0.500f, 0.0f); +#define VERTEX4 glVertex3f( 0.0000f, -1.000f, 0.0f); +#define VERTEX5 glVertex3f(-XOFFSET, -0.500f, 0.0f); +#define VERTEX6 glVertex3f(-XOFFSET, 0.500f, 0.0f); + +/* +** Three different functions for calculating texture coordinates +** which modify how the texture triangle moves over the source image. +** Choose one. +*/ + +#if 0 +/* the classic equilateral triangle rotating around centre */ +static void +calculate_texture_coords(ModeInfo *mi, texture *texture, vector2f t[3]) { + + gleidestruct *gp = &gleidescope[MI_SCREEN(mi)]; + GLfloat centre_x = 0.5; + GLfloat centre_y = 0.5; + GLfloat radius_x = (texture->max_tx - texture->min_tx) / 2; + GLfloat radius_y = (texture->max_ty - texture->min_ty) / 2; + GLfloat tangle2; + t[0].x = centre_x; + t[0].y = centre_y; + + /* t[1] */ + t[1].x = centre_x + .95 * radius_x * cos((gp->ymouse * 2 * M_PI) + (gp->tangle * RADIANS)); + t[1].y = centre_y + .95 * radius_y * sin((gp->ymouse * 2 * M_PI) + (gp->tangle * RADIANS)); + + /* t[2] is always 60' further around than t2 */ + tangle2 = (gp->ymouse * 2 * M_PI) + (gp->tangle * RADIANS) + (M_PI * 2 / 6); + t[2].x = centre_x + .95 * radius_x * cos(tangle2); + t[2].y = centre_y + .95 * radius_y * sin(tangle2); +#if 0 + printf("texcoords:[%f,%f]->[%f,%f](%f,%f)\n", t[0].x, t[0].y, t[1].x, t[1].y, texture->max_tx, texture->max_ty); +#endif +} +#endif + +#if 1 +/* new lissajous movement pattern */ +static void +calculate_texture_coords(ModeInfo *mi, texture *texture, vector2f t[3]) { + + /* equilateral triangle rotating around centre */ + gleidestruct *gp = &gleidescope[MI_SCREEN(mi)]; + GLfloat width = texture->max_tx - texture->min_tx; + GLfloat height = texture->max_ty - texture->min_ty; + /* centre */ + GLfloat centre_x = texture->min_tx + (width * .5); + GLfloat centre_y = texture->min_ty + (height * .5); + /* m radius and t radius should be = .5 */ + /* triangle radius is 30% available space */ + GLfloat t_radius_x = width * .3; + GLfloat t_radius_y = height * .3; + /* movement radius is 30% available space */ + GLfloat m_radius_x = width * .2; + GLfloat m_radius_y = height * .2; + GLfloat angle2; + + /* centre of triangle */ + GLfloat angle = (gp->ymouse * 2 * M_PI) + (gp->tangle * RADIANS); /* to radians */ + GLfloat t_centre_x = centre_x + m_radius_x * cos(texture->x_period * angle + texture->x_phase); + GLfloat t_centre_y = centre_y + m_radius_y * sin(texture->y_period * angle + texture->y_phase); + +#if 0 + printf("WH: %f, %f - tWH: %f, %f\n", width, height, texture->width, texture->height); + printf("size: (%f, %f)\n", width, height); + printf("centre: (%f, %f)\n", centre_x, centre_y); +#endif + + angle2 = texture->r_period * angle + texture->r_phase; + t[0].x = t_centre_x + t_radius_x * cos(angle2); + t[0].y = t_centre_y + t_radius_y * sin(angle2); + t[1].x = t_centre_x + t_radius_x * cos(angle2 + ANGLE_120); + t[1].y = t_centre_y + t_radius_y * sin(angle2 + ANGLE_120); + t[2].x = t_centre_x + t_radius_x * cos(angle2 + ANGLE_240); + t[2].y = t_centre_y + t_radius_y * sin(angle2 + ANGLE_240); + +#if 0 + printf("texcoords:[%f,%f]->[%f,%f](%f,%f)\n", t[0].x, t[0].y, t[1].x, t[1].y, texture->max_tx, texture->max_ty); +#endif +} +#endif + +#if 0 +/* corners into corners - meant to maximise coverage */ +static void +calculate_texture_coords(ModeInfo *mi, texture *texture, vector2f t[3]) { + + /* equilateral triangle rotating around centre */ + gleidestruct *gp = &gleidescope[MI_SCREEN(mi)]; + GLfloat width = texture->max_tx - texture->min_tx; + GLfloat height = texture->max_ty - texture->min_ty; + /* centre */ + GLfloat centre_x = texture->min_tx + (width * .5); + GLfloat centre_y = texture->min_ty + (height * .5); + /* m radius and t radius should be = .5 */ + /* triangle radius calculated using maths 8) */ +#define TRADIUS (M_SQRT2 - 1.0) +#define MRADIUS (1.0 - (M_SQRT2 / 2.0)) + GLfloat t_radius_x = width * TRADIUS * .95; + GLfloat t_radius_y = height * TRADIUS * .95; + /* movement radius also calculated using maths */ + GLfloat m_radius_x = width * MRADIUS * .95; + GLfloat m_radius_y = height * MRADIUS * .95; + GLfloat angle, angle2; + GLfloat t_centre_x, t_centre_y; + + /* centre of triangle */ + angle = gp->tangle * RADIANS; /* to radians */ + t_centre_x = centre_x + m_radius_x * cos(angle); + t_centre_y = centre_y + m_radius_y * sin(angle); +#if 0 + printf("angle: %f, %f\n", angle, gp->tangle); + printf("tcentre: %f,%f\n", t_centre_x, t_centre_y); + printf("tradius: %f,%f\n", t_radius_x, t_radius_y); + + printf("size: (%f, %f)\n", width, height); + printf("centre: (%f, %f)\n", centre_x, centre_y); + printf("centre: (%f, %f)\n", centre_x, centre_y); + printf("TRADIUS: %f\n", TRADIUS); + printf("MRADIUS: %f\n", MRADIUS); +#endif + + /* angle2 is tied to tangle */ + angle2 = (180.0 - ((30.0 / 90.0) * gp->tangle)) * RADIANS; +#if 0 + printf("Angle1: %f\tAngle2: %f\n", angle / RADIANS, angle2 / RADIANS); +#endif + t[0].x = t_centre_x + t_radius_x * cos(angle2); + t[0].y = t_centre_y + t_radius_y * sin(angle2); + t[1].x = t_centre_x + t_radius_x * cos(angle2 + ANGLE_120); + t[1].y = t_centre_y + t_radius_y * sin(angle2 + ANGLE_120); + t[2].x = t_centre_x + t_radius_x * cos(angle2 + ANGLE_240); + t[2].y = t_centre_y + t_radius_y * sin(angle2 + ANGLE_240); + +#if 0 + printf("texcoords:[%f,%f][%f,%f][%f,%f]\n", t[0].x, t[0].y, t[1].x, t[1].y, t[2].x, t[2].y); +#endif +} +#endif + +static int +draw_hexagons(ModeInfo *mi, int translucency, texture *texture) +{ + int polys = 0; + int i; + GLfloat col[4]; + vector2f t[3]; + gleidestruct *gp = &gleidescope[MI_SCREEN(mi)]; + + col[0] = 1.0; + col[1] = 1.0; + col[2] = 1.0; + col[3] = (float)translucency / MAX_FADE; + + calculate_texture_coords(mi, texture, t); + + glColor4f(1.0, 1.0, 1.0, (float)translucency / MAX_FADE); + glEnable(GL_TEXTURE_2D); + glEnable(GL_BLEND); + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + glDepthMask(GL_FALSE); + glBindTexture(GL_TEXTURE_2D, texture->id); + + if (gp->list == -1) { + gp->list = glGenLists(1); + } + + /* compile new list */ + glNewList(gp->list, GL_COMPILE); + glBegin(GL_TRIANGLES); + + /* + ** six triangles to each hexagon + */ + + glTexCoord2f(t[0].x, t[0].y); + VERTEX0; + glTexCoord2f(t[1].x, t[1].y); + VERTEX1; + glTexCoord2f(t[2].x, t[2].y); + VERTEX6; + + glTexCoord2f(t[0].x, t[0].y); + VERTEX0; + glTexCoord2f(t[2].x, t[2].y); + VERTEX6; + glTexCoord2f(t[1].x, t[1].y); + VERTEX5; + + glTexCoord2f(t[0].x, t[0].y); + VERTEX0; + glTexCoord2f(t[1].x, t[1].y); + VERTEX5; + glTexCoord2f(t[2].x, t[2].y); + VERTEX4; + + glTexCoord2f(t[0].x, t[0].y); + VERTEX0; + glTexCoord2f(t[2].x, t[2].y); + VERTEX4; + glTexCoord2f(t[1].x, t[1].y); + VERTEX3; + + glTexCoord2f(t[0].x, t[0].y); + VERTEX0; + glTexCoord2f(t[1].x, t[1].y); + VERTEX3; + glTexCoord2f(t[2].x, t[2].y); + VERTEX2; + + glTexCoord2f(t[0].x, t[0].y); + VERTEX0; + glTexCoord2f(t[2].x, t[2].y); + VERTEX2; + glTexCoord2f(t[1].x, t[1].y); + VERTEX1; + + glEnd(); + glEndList(); + + /* call the list n times */ + for (i = 0 ; i < sizeof(hex) / sizeof(hex[0]) ; i++) { + + glPushMatrix(); + + glTranslatef(hex[i].x, hex[i].y, 0.0); + glCallList(gp->list); + polys += 6; + + glPopMatrix(); + } + +#ifdef DISPLAY_TEXTURE + glPushMatrix(); + /* acd debug - display (bigger, centred) texture */ + glScalef(2.0, 2.0, 2.0); + glTranslatef(-0.5, -0.5, 0.0); + glBegin(GL_QUADS); + glTexCoord2f(0.0, 0.0); + glVertex3f(0.0, 0.0, -0.1); + glTexCoord2f(1.0, 0.0); + glVertex3f(1.0, 0.0, -0.1); + glTexCoord2f(1.0, 1.0); + glVertex3f(1.0, 1.0, -0.1); + glTexCoord2f(0.0, 1.0); + glVertex3f(0.0, 1.0, -0.1); + polys++; + glEnd(); + /* acd debug - display texture triangle */ + glColor4f(1.0, 0.5, 1.0, 1.0); + glBegin(GL_LINE_LOOP); + glVertex3f(t[0].x, t[0].y, -0.11); + glVertex3f(t[1].x, t[1].y, -0.11); + glVertex3f(t[2].x, t[2].y, -0.11); + polys++; + glEnd(); + glPopMatrix(); +#endif + + glDisable(GL_TEXTURE_2D); + glDepthMask(GL_TRUE); + glDisable(GL_BLEND); + return polys; +} + +/* + * main rendering loop + */ +static void +draw(ModeInfo * mi) +{ + GLfloat x_angle, y_angle, z_angle; + gleidestruct *gp = &gleidescope[MI_SCREEN(mi)]; + vectorf v1; + GLfloat pos[4]; + + mi->polygon_count = 0; + + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + glLoadIdentity(); + + gp->tic += 0.005f; + + x_angle = gp->cam_x_phase + gp->tic * gp->cam_x_speed; + y_angle = gp->cam_y_phase + gp->tic * gp->cam_y_speed; + z_angle = gp->cam_z_phase + gp->tic * gp->cam_z_speed; + + if (move) { + v1.x = 1 * sin(x_angle); + v1.y = 1 * sin(y_angle); + } else { + v1.x = 0; + v1.y = 0; + } + + /* size is changed in pinit() to be distance from plane */ + gp->size = MI_SIZE(mi); + if (gp->size > 10) { + gp->size = 10; + } + if (gp->size <= 0) { + gp->size = 0; + } + if (gp->size > 0) { + /* user defined size */ + v1.z = gp->size; + } else if (zoom) { + /* max distance given by adding the constant and the multiplier */ + v1.z = 5.0 + 3.0 * sin(z_angle); + } else { + /* default */ + v1.z = 7.0; + } + + /* update rotation angle (but not if mouse button down) */ + if (rotate && !gp->button_down_p) + { + float new_rangle_vel = 0.0; + + /* update camera rotation angle and velocity */ + gp->rangle += gp->rangle_vel; + new_rangle_vel = gp->rangle_vel + gp->rangle_acc; + if (new_rangle_vel > -MAX_ANGLE_VEL && new_rangle_vel < MAX_ANGLE_VEL) + { + /* new velocity is within limits */ + gp->rangle_vel = new_rangle_vel; + } + + /* randomly change twisting speed - 3ff = 1024 */ + if ((random() % TWISTING_PROBABILITY) < 1.0) { + gp->rangle_acc = INITIAL_ANGLE_ACC * frand(1.0); + if (gp->rangle_vel > 0.0) { + gp->rangle_acc = -gp->rangle_acc; + } + } + } +#if 0 + printf("Rangle: %f : %f : %f\n", gp->rangle, gp->rangle_vel, gp->rangle_acc); + printf("Tangle: %f : %f : %f\n", gp->tangle, gp->tangle_vel, gp->tangle_acc); +#endif + +#ifdef WOBBLE + /* this makes the image wobble - requires -move and a larger grid */ + gluLookAt(0, 0, v1.z, v1.x, v1.y, 0.0, 0.0, 1.0, 0.0); +#else + /* no wobble - camera always perpendicular to grid */ + + /* rotating camera rather than entire space - smoother */ + gluLookAt( + v1.x, v1.y, v1.z, + v1.x, v1.y, 0.0, + sin((gp->xmouse * M_PI * 2) + gp->rangle * RADIANS), + cos((gp->xmouse * M_PI * 2) + gp->rangle * RADIANS), + 0.0); +#endif + + /* light position same as camera */ + pos[0] = v1.x; + pos[1] = v1.y; + pos[2] = v1.z; + pos[3] = 0; + + if (gp->fade == 0) + { + /* not fading */ + mi->polygon_count += + draw_hexagons(mi, MAX_FADE, &gp->textures[gp->visible]); + } + else + { + /* fading - show both textures with alpha + NB first is always max alpha */ + mi->polygon_count += + draw_hexagons(mi, MAX_FADE, &gp->textures[1 - gp->visible]); + mi->polygon_count += + draw_hexagons(mi, MAX_FADE - gp->fade, &gp->textures[gp->visible]); + + /* fade some more */ + gp->fade++; + + /* have we faded enough? */ + if (gp->fade > MAX_FADE) + { + /* stop fading */ + gp->fade = 0; + gp->visible = 1 - gp->visible; + } + } + + /* increment texture angle based on time, velocity etc */ + /* but only if button is not down */ + if (!gp->button_down_p) + { + float new_tangle_vel = 0.0; + + gp->tangle += gp->tangle_vel; + + /* work out new texture angle velocity */ + new_tangle_vel = gp->tangle_vel + gp->tangle_acc; + if (new_tangle_vel > -MAX_ANGLE_VEL && new_tangle_vel < MAX_ANGLE_VEL) + { + /* new velocity is inside limits */ + gp->tangle_vel = new_tangle_vel; + } + + /* randomly change twisting speed - 3ff = 1024 */ + if ((random() % TWISTING_PROBABILITY) < 1.0) { + gp->tangle_acc = INITIAL_ANGLE_ACC * frand(1.0); + if (gp->tangle_vel > 0.0) { + gp->tangle_acc = -gp->tangle_acc; + } + } + } + + glFlush(); +} + +/* + * new window size or exposure + */ +ENTRYPOINT void reshape_gleidescope(ModeInfo *mi, int width, int height) +{ + GLfloat h = (GLfloat) height / (GLfloat) width; + + glViewport(0, 0, (GLint) width, (GLint) height); + glMatrixMode(GL_PROJECTION); + glLoadIdentity(); + gluPerspective(50.0, 1/h, 0.1, 2000.0); + glMatrixMode (GL_MODELVIEW); + + glLineWidth(1); + glPointSize(1); +} + +static void +pinit(ModeInfo * mi) +{ + gleidestruct *gp = &gleidescope[MI_SCREEN(mi)]; + + /* set start time - star_time = 0 implies non-dynamic texture */ + gp->start_time = (time_t)0; + + /* set the texture size to default */ + /* + gp->max_tx = 1.0; + gp->max_ty = 1.0; + */ + + /* no fading */ + gp->fade = 0; + + glShadeModel(GL_SMOOTH); + glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); + glEnable(GL_DEPTH_TEST); + glEnable(GL_CULL_FACE); + glDisable(GL_LIGHTING); + + /* space for textures */ + glGenTextures(1, &gp->textures[0].id); + glGenTextures(1, &gp->textures[1].id); + gp->visible = 0; + + setup_texture(mi, &gp->textures[gp->visible]); + + /* + ** want to choose a value for arg randomly if neither -arg nor -no-arg + ** is specified. xscreensaver libraries don't seem to let you do this - + ** if something isn't true then it is false (pesky two-state boolean values). + ** so, i've defined both -arg and -no-arg to arguments and added the + ** following logic. + ** (btw if both -arg and -no-arg are defined then arg is set to False) + */ + if (zoom == False && nozoom == False) + { + /* no zoom preference - randomise */ + zoom = (((random() & 0x1) == 0x1) ? True : False); + } + else if (nozoom == True) + { + /* definately no zoom */ + zoom = False; + } + + if (move == False && nomove == False) + { + /* no move preference - randomise */ + move = (((random() & 0x1) == 0x1) ? True : False); + } + else if (nomove == True) + { + /* definately no move */ + move = False; + } + + if (rotate == False && norotate == False) + { + /* no rotate preference - randomise */ + rotate = (((random() & 0x1) == 0x1) ? True : False); + } + else if (norotate == True) + { + /* definately no rotate */ + rotate = False; + } + + /* define cam variables */ + gp->cam_x_speed = MAX_CAM_SPEED * frandrange(-.5, 0.5); + gp->cam_x_phase = random() % 360; + gp->cam_y_speed = MAX_CAM_SPEED * frandrange(-.5, 0.5); + gp->cam_y_phase = random() % 360; + gp->cam_z_speed = MAX_CAM_SPEED * frandrange(-.5, 0.5); + gp->cam_z_phase = random() % 360; + + /* initial angular speeds */ + gp->rangle_vel = INITIAL_ANGLE_VEL * frandrange(-.5, 0.5); + gp->tangle_vel = INITIAL_ANGLE_VEL * frandrange(-.5, 0.5); + gp->rangle_acc = INITIAL_ANGLE_ACC * frandrange(-.5, 0.5); + gp->tangle_acc = INITIAL_ANGLE_ACC * frandrange(-.5, 0.5); + + /* jwz */ +#if 0 + { + GLfloat speed = 15; + gp->rangle_vel *= speed; + gp->tangle_vel *= speed; + gp->rangle_acc *= speed; + gp->tangle_acc *= speed; + } +#endif + + /* distance is 11 - size */ + if (gp->size != -1) { + if (zoom) { + fprintf(stderr, "-size given. ignoring -zoom.\n"); + zoom = False; + } + if (gp->size < 1) { + gp->size = 1; + } else if (gp->size >= 10) { + gp->size = 10; + } + gp->size = 11 - gp->size; + } + +#ifdef DEBUG +printf("phases [%d, %d, %d]\n", gp->cam_x_phase, gp->cam_y_phase, gp->cam_z_phase); +#endif +} + +ENTRYPOINT void +init_gleidescope(ModeInfo * mi) +{ + gleidestruct *gp; + int screen = MI_SCREEN(mi); + + if (gleidescope == NULL) { + gleidescope = (gleidestruct *) calloc(MI_NUM_SCREENS(mi), sizeof (gleidestruct)); + if (gleidescope == NULL) { + return; + } + } + gp = &gleidescope[screen]; + gp->window = MI_WINDOW(mi); + gp->size = -1; + gp->list = -1; + + if ((gp->glx_context = init_GL(mi)) != NULL) { + + reshape_gleidescope(mi, MI_WIDTH(mi), MI_HEIGHT(mi)); + clear_gl_error(); /* WTF? sometimes "invalid op" from glViewport! */ + + glDrawBuffer(GL_BACK); + + /* do initialisation */ + pinit(mi); + + } else { + MI_CLEARWINDOW(mi); + } +} + +ENTRYPOINT void +draw_gleidescope(ModeInfo * mi) +{ + gleidestruct *gp = &gleidescope[MI_SCREEN(mi)]; + Display *display = MI_DISPLAY(mi); + Window window = MI_WINDOW(mi); + + + if (!gp->glx_context) + return; + + /* Just keep running before the texture has come in. */ + /* if (gp->waiting_for_image_p) return; */ + + glDrawBuffer(GL_BACK); + + glXMakeCurrent(display, window, *(gp->glx_context)); + draw(mi); + + if (mi->fps_p) { + do_fps (mi); + } + + glFinish(); + glXSwapBuffers(display, window); + +#ifdef GRAB + if (grab) { + grab_frame(display, window); + } +#endif + + /* need to change texture? */ + if ((gp->start_time != 0) && (duration != -1) && gp->fade == 0) { + if (gp->start_time + duration <= time((time_t *)0)) { +#ifdef DEBUG + printf("Start Time: %lu - Current Time: %lu\n", (unsigned long)gp->start_time, (unsigned long)time((time_t *)0)); + printf("Changing Texture\n"); +#endif + /* get new snapshot (into back buffer) and start fade count */ + setup_texture(mi, &gp->textures[1 - gp->visible]); + /* restart fading */ + gp->fade = 1; + } + } +} + +ENTRYPOINT void +release_gleidescope(ModeInfo * mi) +{ + if (gleidescope != NULL) { + int screen; + + for (screen = 0; screen < MI_NUM_SCREENS(mi); screen++) { + gleidestruct *gp = &gleidescope[screen]; + + /* acd - is this needed? */ + if (gp->glx_context) { + /* Display lists MUST be freed while their glXContext is current. */ + glXMakeCurrent(MI_DISPLAY(mi), gp->window, *(gp->glx_context)); + + /* acd - was code here for freeing things that are no longer in struct */ + } + } + (void) free((void *) gleidescope); + gleidescope = NULL; + } + + FreeAllGL(mi); +} + +XSCREENSAVER_MODULE ("Gleidescope", gleidescope) + +#endif diff --git a/hacks/glx/gleidescope.man b/hacks/glx/gleidescope.man new file mode 100644 index 00000000..c0b9b158 --- /dev/null +++ b/hacks/glx/gleidescope.man @@ -0,0 +1,77 @@ +.TH XScreenSaver 1 "" "X Version 11" +.SH NAME +gleidescope - a tiled OpenGL kaleidescope +.SH SYNOPSIS +.B gleidescope +[\-display \fIhost:display.screen\fP] +[\-visual \fIvisual\fP] +[\-window] +[\-root] +[-delay \fInumber\fP] +[-move] +[-rotate] +[-zoom] +[-image \fIfile\fP] +[-fps] +[-size \fInumber\fP] +[-duration \fInumber\fP] +.SH DESCRIPTION +A tiled kaleidescope using OpenGL. +.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: 20000 (0.02 seconds.). +.TP 8 +.B \-move +Move the camera. +.TP 8 +.B \-rotate +Rotate the camera. +.TP 8 +.B \-zoom +Zoom the camera in and out. +.TP 8 +.B \-image \fIfile\fP +The texture map to use at the end of the kaleidescope. +.TP 8 +.B \-fps +Display the current frame rate, CPU load, and polygon count. +.TP 8 +.B \-size \fInumber\fP +The size of the hexagons being displayed [1(small)-10(large)] +.TP 8 +.B \-duration \fInumber\fP +The time in seconds before another image is chosen. +.TP 8 +.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 2003 by Andrew Dean 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 +Andrew Dean. diff --git a/hacks/glx/glforestfire.c b/hacks/glx/glforestfire.c new file mode 100644 index 00000000..da237573 --- /dev/null +++ b/hacks/glx/glforestfire.c @@ -0,0 +1,1147 @@ +/* -*- Mode: C; tab-width: 4 -*- */ +/* fire --- 3D fire or rain landscape */ + +#if 0 +static const char sccsid[] = "@(#)fire.c 5.02 2001/09/26 xlockmore"; +#endif + +/* Copyright (c) E. Lassauge, 2001. */ + +/* + * Permission to use, copy, modify, and distribute this software and its + * documentation for any purpose and without fee is hereby granted, + * provided that the above copyright notice appear in all copies and that + * both that copyright notice and this permission notice appear in + * supporting documentation. + * + * This file is provided AS IS with no warranties of any kind. The author + * shall have no liability with respect to the infringement of copyrights, + * trade secrets or any patents by this file or any part thereof. In no + * event will the author be liable for any lost revenue or profits or + * other special, indirect and consequential damages. + * + * The original code for this mode was written by David Bucciarelli + * (tech.hmw@plus.it) and could be found in the demo package + * of Mesa (Mesa-3.2/3Dfx/demos/). This mode is the result of the merge of + * two of the David's demos (fire and rain). + * + * Eric Lassauge (October-10-2000) + * http://lassauge.free.fr/linux.html + * + * REVISION HISTORY: + * + * E.Lassauge - 26-Sep-2001: + * - add wander option and code + * - cleanups for xscreensaver + * + * E.Lassauge - 09-Mar-2001: + * - get rid of my framerate options to use showfps + * + * E.Lassauge - 12-Jan-2001: + * - add rain particules, selected if count=0 (no fire means rain !) + * + * E.Lassauge - 28-Nov-2000: + * - modified release part to add freeing of GL objects + * + * E.Lassauge - 14-Nov-2000: + * - use new common xpm_to_ximage function + * + * E.Lassauge - 25-Oct-2000: + * - add the trees (with a new resource '-trees') + * - corrected handling of color (textured vs untextured) + * - corrected handling of endiannes for the xpm files + * - inverted ground pixmap file + * - use malloc-ed tree array + * + * TSchmidt - 23-Oct-2000: + * - added size option like used in sproingies mode + * + * E.Lassauge - 13-Oct-2000: + * - when trackmouse and window is iconified (login screen): stop tracking + * - add pure GLX handling of framerate display (erased GLUT stuff) + * - made count a per screen variable and update it only if framemode + * - changes for no_texture an wireframe modes + * - change no_texture color for the ground + * - add freeing of texture image + * - misc comments and little tweakings + * + * TODO: + * - perhaps use a user supplied xpm for ground image (or a whatever image + * file using ImageMagick ?) + * - random number of trees ? change trees at change_fire ? + * - fix wireframe mode: it's too CPU intensive. + * - look how we can get the Wheel events (Button4&5). + */ + + +#ifdef STANDALONE /* xscreensaver mode */ +#define DEFAULTS "*delay: 10000 \n" \ + "*count: 800 \n" \ + "*size: 0 \n" \ + "*showFPS: False \n" \ + "*wireframe: False \n" \ + +# define refresh_fire 0 +#define MODE_fire +#include "xlockmore.h" /* from the xscreensaver distribution */ +#include "gltrackball.h" +#else /* !STANDALONE */ +#include "xlock.h" /* from the xlockmore distribution */ +#include "visgl.h" +#endif /* !STANDALONE */ + +#ifdef MODE_fire + +#define MINSIZE 32 + +#if defined( USE_XPM ) || defined( USE_XPMINC ) || defined(STANDALONE) +/* USE_XPM & USE_XPMINC in xlock mode ; HAVE_XPM in xscreensaver mode */ +#include "xpm-ximage.h" +#define I_HAVE_XPM + +#ifdef STANDALONE +#include "../images/ground.xpm" +#include "../images/tree.xpm" +#else /* !STANDALONE */ +#include "pixmaps/ground.xpm" +#include "pixmaps/tree.xpm" +#endif /* !STANDALONE */ +#endif /* HAVE_XPM */ + +/* vector utility macros */ +#define vinit(a,i,j,k) {\ + (a)[0]=i;\ + (a)[1]=j;\ + (a)[2]=k;\ +} + +#define vinit4(a,i,j,k,w) {\ + (a)[0]=i;\ + (a)[1]=j;\ + (a)[2]=k;\ + (a)[3]=w;\ +} + +#define vadds(a,dt,b) {\ + (a)[0]+=(dt)*(b)[0];\ + (a)[1]+=(dt)*(b)[1];\ + (a)[2]+=(dt)*(b)[2];\ +} + +#define vequ(a,b) {\ + (a)[0]=(b)[0];\ + (a)[1]=(b)[1];\ + (a)[2]=(b)[2];\ +} + +#define vinter(a,dt,b,c) {\ + (a)[0]=(dt)*(b)[0]+(1.0-dt)*(c)[0];\ + (a)[1]=(dt)*(b)[1]+(1.0-dt)*(c)[1];\ + (a)[2]=(dt)*(b)[2]+(1.0-dt)*(c)[2];\ +} + +#define clamp(a) ((a) < 0.0 ? 0.0 : ((a) < 1.0 ? (a) : 1.0)) + +#define vclamp(v) {\ + (v)[0]=clamp((v)[0]);\ + (v)[1]=clamp((v)[1]);\ + (v)[2]=clamp((v)[2]);\ +} + +/* Manage option vars */ +#define DEF_TEXTURE "True" +#define DEF_FOG "False" +#define DEF_SHADOWS "True" +#define DEF_FRAMERATE "False" +#define DEF_WANDER "True" +#define DEF_TREES "5" +#define MAX_TREES 20 +static Bool do_texture; +static Bool do_fog; +static Bool do_shadows; +static Bool do_wander; +static int num_trees; +static XFontStruct *mode_font = None; + +static XrmOptionDescRec opts[] = { + {"-texture", ".fire.texture", XrmoptionNoArg, "on"}, + {"+texture", ".fire.texture", XrmoptionNoArg, "off"}, + {"-fog", ".fire.fog", XrmoptionNoArg, "on"}, + {"+fog", ".fire.fog", XrmoptionNoArg, "off"}, + {"-shadows", ".fire.shadows", XrmoptionNoArg, "on"}, + {"+shadows", ".fire.shadows", XrmoptionNoArg, "off"}, + {"-wander", ".fire.wander", XrmoptionNoArg, "on"}, + {"+wander", ".fire.wander", XrmoptionNoArg, "off"}, + {"-trees", ".fire.trees", XrmoptionSepArg, 0}, + {"-rain", ".fire.count", XrmoptionNoArg, "0"}, + +}; + +static argtype vars[] = { + {&do_texture, "texture", "Texture", DEF_TEXTURE, t_Bool}, + {&do_fog, "fog", "Fog", DEF_FOG, t_Bool}, + {&do_shadows, "shadows", "Shadows", DEF_SHADOWS, t_Bool}, + {&do_wander, "wander", "Wander", DEF_WANDER, t_Bool}, + {&num_trees, "trees", "Trees", DEF_TREES, t_Int}, +}; + +static OptionStruct desc[] = { + {"-/+texture", "turn on/off texturing"}, + {"-/+fog", "turn on/off fog"}, + {"-/+shadows", "turn on/off shadows"}, + {"-/+wander", "turn on/off wandering"}, + {"-trees num", "number of trees (0 disables)"}, +}; + +ENTRYPOINT ModeSpecOpt fire_opts = + { sizeof opts / sizeof opts[0], opts, sizeof vars / sizeof vars[0], vars, desc }; + +#ifdef USE_MODULES +ModStruct fire_description = + { "fire", "init_fire", "draw_fire", "release_fire", + "draw_fire", "change_fire", (char *) NULL, &fire_opts, + 10000, 800, 1, 400, 64, 1.0, "", + "Shows a 3D fire-like image", 0, NULL +}; +#endif /* USE_MODULES */ + +/* misc defines */ +#define TREEINR 2.5 /* tree min distance */ +#define TREEOUTR 8.0 /* tree max distance */ +#define FRAME 50 /* frame count interval */ +#define DIMP 20.0 /* dimension of ground */ +#define DIMTP 16.0 /* dimension of ground texture */ + +#define RIDCOL 0.4 /* factor for color blending */ + +#define AGRAV -9.8 /* gravity */ + +#define NUMPART 7500 /* rain particles */ + +/* fire particle struct */ +typedef struct { + int age; + float p[3][3]; + float v[3]; + float c[3][4]; +} part; + +/* rain particle struct */ +typedef struct { + float age; + float acc[3]; + float vel[3]; + float pos[3]; + float partLength; + float oldpos[3]; +} rain; + +/* colors */ +static const GLfloat black[3] = { 0.0, 0.0, 0.0 }; /* shadow color */ +static const GLfloat partcol1[3] = { 1.0, 0.2, 0.0 }; /* initial color: red-ish */ +static const GLfloat partcol2[3] = { 1.0, 1.0, 0.0 }; /* blending color: yellow-ish */ +static const GLfloat fogcolor[4] = { 0.9, 0.9, 1.0, 1.0 }; + +/* ground */ +static const float q[4][3] = { + {-DIMP, 0.0, -DIMP}, + {DIMP, 0.0, -DIMP}, + {DIMP, 0.0, DIMP}, + {-DIMP, 0.0, DIMP} +}; + +/* ground texture */ +static const float qt[4][2] = { + {-DIMTP, -DIMTP}, + {DIMTP, -DIMTP}, + {DIMTP, DIMTP}, + {-DIMTP, DIMTP} +}; + +/* default values for observer */ +static const float DEF_OBS[3] = { 2.0f, 1.0f, 0.0f }; +#define DEV_V 0.0 +#define DEF_ALPHA -90.0 +#define DEF_BETA 90.0 + +/* tree struct */ +typedef struct { + float x,y,z; +} treestruct; + +/* the mode struct, contains all per screen variables */ +typedef struct { + GLint WIDTH, HEIGHT; /* display dimensions */ + GLXContext *glx_context; + + int np; /* number of fire particles : set it through 'count' resource */ + float eject_r; /* emission radius */ + float dt, maxage, eject_vy, eject_vl; + float ridtri; /* fire particle size */ + Bool shadows; /* misc booleans: set them through specific resources */ + Bool fog; + + part *p; /* fire particles array */ + rain *r; /* rain particles array */ + + XImage *gtexture; /* ground texture image bits */ + XImage *ttexture; /* tree texture image bits */ + GLuint groundid; /* ground texture id: GL world */ + GLuint treeid; /* tree texture id: GL world */ + GLuint fontbase; /* fontbase id: GL world */ + + int num_trees; /* number of trees: set it through 'trees' resource */ + treestruct *treepos; /* trees positions: float treepos[num_trees][3] */ + + float min[3]; /* raining area */ + float max[3]; + + float obs[3]; /* observer coordinates */ + float dir[3]; /* view direction */ + float v; /* observer velocity */ + float alpha; /* observer angles */ + float beta; + + trackball_state *trackball; + Bool button_down_p; + int frame; + +} firestruct; + +/* array of firestruct indexed by screen number */ +static firestruct *fire = (firestruct *) NULL; + +/* + *----------------------------------------------------------------------------- + *----------------------------------------------------------------------------- + * Misc funcs. + *----------------------------------------------------------------------------- + *----------------------------------------------------------------------------- + */ + +/* utility function for the rain particles */ +static float gettimerain(void) +{ +#if 0 + /* Oh yeah, *that's* portable! WTF. */ + /* + * I really thought clock() was standard ... EL + * I found this on the net: + * The clock() function conforms to ISO/IEC 9899:1990 (``ISO C89'') + * */ + + static clock_t told= (clock_t)0; + clock_t tnew,ris; + + tnew=clock(); + + ris=tnew-told; + + told=tnew; + + return (0.0125 + ris/(float)CLOCKS_PER_SEC); +#else + return 0.0150; +#endif +} + +/* my RAND */ +static float vrnd(void) +{ + return ((float) LRAND() / (float) MAXRAND); +} + +/* initialise new fire particle */ +static void setnewpart(firestruct * fs, part * p) +{ + float a, vi[3]; + const float *c; + + p->age = 0; + + a = vrnd() * M_PI * 2.0; + + vinit(vi, sin(a) * fs->eject_r * vrnd(), 0.15, cos(a) * fs->eject_r * vrnd()); + vinit(p->p[0], vi[0] + vrnd() * fs->ridtri, vi[1] + vrnd() * fs->ridtri, vi[2] + vrnd() * fs->ridtri); + vinit(p->p[1], vi[0] + vrnd() * fs->ridtri, vi[1] + vrnd() * fs->ridtri, vi[2] + vrnd() * fs->ridtri); + vinit(p->p[2], vi[0] + vrnd() * fs->ridtri, vi[1] + vrnd() * fs->ridtri, vi[2] + vrnd() * fs->ridtri); + + vinit(p->v, vi[0] * fs->eject_vl / (fs->eject_r / 2), + vrnd() * fs->eject_vy + fs->eject_vy / 2, + vi[2] * fs->eject_vl / (fs->eject_r / 2)); + + c = partcol1; + + vinit4(p->c[0], c[0] * ((1.0 - RIDCOL) + vrnd() * RIDCOL), + c[1] * ((1.0 - RIDCOL) + vrnd() * RIDCOL), + c[2] * ((1.0 - RIDCOL) + vrnd() * RIDCOL), 1.0); + vinit4(p->c[1], c[0] * ((1.0 - RIDCOL) + vrnd() * RIDCOL), + c[1] * ((1.0 - RIDCOL) + vrnd() * RIDCOL), + c[2] * ((1.0 - RIDCOL) + vrnd() * RIDCOL), 1.0); + vinit4(p->c[2], c[0] * ((1.0 - RIDCOL) + vrnd() * RIDCOL), + c[1] * ((1.0 - RIDCOL) + vrnd() * RIDCOL), + c[2] * ((1.0 - RIDCOL) + vrnd() * RIDCOL), 1.0); +} + +/* initialise new rain particle */ +static void setnewrain(firestruct * fs, rain * r) +{ + r->age=0.0f; + + vinit(r->acc,0.0f,-0.98f,0.0f); + vinit(r->vel,0.0f,0.0f,0.0f); + + r->partLength=0.2f; + + vinit(r->oldpos,fs->min[0]+(fs->max[0]-fs->min[0])*vrnd(), + fs->max[1]+0.2f*fs->max[1]*vrnd(), + fs->min[2]+(fs->max[2]-fs->min[2])*vrnd()); + vequ(r->pos,r->oldpos); + vadds(r->oldpos,-(r->partLength),r->vel); + + r->pos[1]=(fs->max[1]-fs->min[1])*vrnd()+fs->min[1]; + r->oldpos[1]=r->pos[1]-r->partLength*r->vel[1]; +} + +/* set fire particle values */ +static void setpart(firestruct * fs, part * p) +{ + float fact; + + if (p->p[0][1] < 0.1) { + setnewpart(fs, p); + return; + } + + p->v[1] += AGRAV * fs->dt; + + vadds(p->p[0], fs->dt, p->v); + vadds(p->p[1], fs->dt, p->v); + vadds(p->p[2], fs->dt, p->v); + + p->age++; + + if ((p->age) > fs->maxage) { + vequ(p->c[0], partcol2); + vequ(p->c[1], partcol2); + vequ(p->c[2], partcol2); + } else { + fact = 1.0 / fs->maxage; + vadds(p->c[0], fact, partcol2); + vclamp(p->c[0]); + p->c[0][3] = fact * (fs->maxage - p->age); + + vadds(p->c[1], fact, partcol2); + vclamp(p->c[1]); + p->c[1][3] = fact * (fs->maxage - p->age); + + vadds(p->c[2], fact, partcol2); + vclamp(p->c[2]); + p->c[2][3] = fact * (fs->maxage - p->age); + } +} + +/* set rain particle values */ +static void setpartrain(firestruct * fs, rain * r, float dt) +{ + r->age += dt; + + vadds(r->vel,dt,r->acc); + vadds(r->pos,dt,r->vel); + + if(r->pos[0]min[0]) + r->pos[0]=fs->max[0]-(fs->min[0]-r->pos[0]); + if(r->pos[2]min[2]) + r->pos[2]=fs->max[2]-(fs->min[2]-r->pos[2]); + + if(r->pos[0]>fs->max[0]) + r->pos[0]=fs->min[0]+(r->pos[0]-fs->max[0]); + if(r->pos[2]>fs->max[2]) + r->pos[2]=fs->min[2]+(r->pos[2]-fs->max[2]); + + vequ(r->oldpos,r->pos); + vadds(r->oldpos,-(r->partLength),r->vel); + if(r->pos[1]min[1]) + setnewrain(fs, r); +} + +/* draw a tree */ +static int drawtree(float x, float y, float z) +{ + int polys = 0; + glBegin(GL_QUADS); + glTexCoord2f(0.0,0.0); + glVertex3f(x-1.5,y+0.0,z); + + glTexCoord2f(1.0,0.0); + glVertex3f(x+1.5,y+0.0,z); + + glTexCoord2f(1.0,1.0); + glVertex3f(x+1.5,y+3.0,z); + + glTexCoord2f(0.0,1.0); + glVertex3f(x-1.5,y+3.0,z); + polys++; + + + glTexCoord2f(0.0,0.0); + glVertex3f(x,y+0.0,z-1.5); + + glTexCoord2f(1.0,0.0); + glVertex3f(x,y+0.0,z+1.5); + + glTexCoord2f(1.0,1.0); + glVertex3f(x,y+3.0,z+1.5); + + glTexCoord2f(0.0,1.0); + glVertex3f(x,y+3.0,z-1.5); + polys++; + + glEnd(); + + return polys; +} + +/* calculate observer position : modified only if trackmouse is used */ +static void calcposobs(firestruct * fs) +{ + fs->dir[0] = sin(fs->alpha * M_PI / 180.0); + fs->dir[2] = + cos(fs->alpha * M_PI / 180.0) * sin(fs->beta * M_PI / 180.0); + fs->dir[1] = cos(fs->beta * M_PI / 180.0); + + fs->obs[0] += fs->v * fs->dir[0]; + fs->obs[1] += fs->v * fs->dir[1]; + fs->obs[2] += fs->v * fs->dir[2]; + + if (!fs->np) + { + vinit(fs->min,fs->obs[0]-7.0f,-0.2f,fs->obs[2]-7.0f); + vinit(fs->max,fs->obs[0]+7.0f,8.0f,fs->obs[2]+7.0f); + } +} + + +/* initialise textures */ +static void inittextures(ModeInfo * mi) +{ + firestruct *fs = &fire[MI_SCREEN(mi)]; + +#if defined( I_HAVE_XPM ) + if (do_texture) { + + glGenTextures(1, &fs->groundid); +#ifdef HAVE_GLBINDTEXTURE + glBindTexture(GL_TEXTURE_2D, fs->groundid); +#endif /* HAVE_GLBINDTEXTURE */ + + if ((fs->gtexture = xpm_to_ximage(MI_DISPLAY(mi), MI_VISUAL(mi), + MI_COLORMAP(mi), ground)) == None) { + (void) fprintf(stderr, "Error reading the ground texture.\n"); + glDeleteTextures(1, &fs->groundid); + do_texture = False; + fs->groundid = 0; + fs->treeid = 0; + return; + } + + glPixelStorei(GL_UNPACK_ALIGNMENT, 4); + clear_gl_error(); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, + fs->gtexture->width, fs->gtexture->height, 0, + GL_RGBA, + /* GL_UNSIGNED_BYTE, */ + GL_UNSIGNED_INT_8_8_8_8_REV, + fs->gtexture->data); + check_gl_error("texture"); + + glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); + glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); + + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + + glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_DECAL); + + if (fs->num_trees) + { + glGenTextures(1, &fs->treeid); +#ifdef HAVE_GLBINDTEXTURE + glBindTexture(GL_TEXTURE_2D,fs->treeid); +#endif /* HAVE_GLBINDTEXTURE */ + if ((fs->ttexture = xpm_to_ximage(MI_DISPLAY(mi), MI_VISUAL(mi), + MI_COLORMAP(mi), tree)) == None) { + (void)fprintf(stderr,"Error reading tree texture.\n"); + glDeleteTextures(1, &fs->treeid); + fs->treeid = 0; + fs->num_trees = 0; + return; + } + + clear_gl_error(); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, + fs->ttexture->width, fs->ttexture->height, 0, + GL_RGBA, + /* GL_UNSIGNED_BYTE, */ + GL_UNSIGNED_INT_8_8_8_8_REV, + fs->ttexture->data); + check_gl_error("texture"); + + 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_MIN_FILTER,GL_NEAREST); + glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_NEAREST); + + glTexEnvf(GL_TEXTURE_ENV,GL_TEXTURE_ENV_MODE,GL_MODULATE); + } + } + else + { + fs->groundid = 0; /* default textures */ + fs->treeid = 0; + } +#else /* !I_HAVE_XPM */ + do_texture = False; + fs->groundid = 0; /* default textures */ + fs->treeid = 0; +#endif /* !I_HAVE_XPM */ +} + +/* init tree array and positions */ +static Bool inittree(ModeInfo * mi) +{ + firestruct *fs = &fire[MI_SCREEN(mi)]; + int i; + float dist; + + /* allocate treepos array */ + if ((fs->treepos = (treestruct *) malloc(fs->num_trees * + sizeof(treestruct))) == NULL) { + return False; + } + /* initialise positions */ + for(i=0;inum_trees;i++) + do { + fs->treepos[i].x =vrnd()*TREEOUTR*2.0-TREEOUTR; + fs->treepos[i].y =0.0; + fs->treepos[i].z =vrnd()*TREEOUTR*2.0-TREEOUTR; + dist=sqrt(fs->treepos[i].x *fs->treepos[i].x +fs->treepos[i].z *fs->treepos[i].z ); + } while((distTREEOUTR)); + return True; +} + +/* + *----------------------------------------------------------------------------- + *----------------------------------------------------------------------------- + * GL funcs. + *----------------------------------------------------------------------------- + *----------------------------------------------------------------------------- + */ + +ENTRYPOINT void reshape_fire(ModeInfo * mi, int width, int height) +{ + + firestruct *fs = &fire[MI_SCREEN(mi)]; + int size = MI_SIZE(mi); + + /* Viewport is specified size if size >= MINSIZE && size < screensize */ + if (size <= 1) { + fs->WIDTH = MI_WIDTH(mi); + fs->HEIGHT = MI_HEIGHT(mi); + } else if (size < MINSIZE) { + fs->WIDTH = MINSIZE; + fs->HEIGHT = MINSIZE; + } else { + fs->WIDTH = (size > MI_WIDTH(mi)) ? MI_WIDTH(mi) : size; + fs->HEIGHT = (size > MI_HEIGHT(mi)) ? MI_HEIGHT(mi) : size; + } + glViewport((MI_WIDTH(mi) - fs->WIDTH) / 2, (MI_HEIGHT(mi) - fs->HEIGHT) / 2, fs->WIDTH, fs->HEIGHT); + glMatrixMode(GL_PROJECTION); + glLoadIdentity(); + gluPerspective(70.0, fs->WIDTH / (float) fs->HEIGHT, 0.1, 30.0); + + glMatrixMode(GL_MODELVIEW); + +} + +static void DrawFire(ModeInfo * mi) +{ + int j; + firestruct *fs = &fire[MI_SCREEN(mi)]; + Bool wire = MI_IS_WIREFRAME(mi); + + mi->polygon_count = 0; + + if (do_wander && !fs->button_down_p) + { + GLfloat x, y, z; + +# define SINOID(SCALE,SIZE) \ + ((((1 + sin((fs->frame * (SCALE)) / 2 * M_PI)) / 2.0) * (SIZE)) - (SIZE)/2) + + x = SINOID(0.031, 0.85); + y = SINOID(0.017, 0.25); + z = SINOID(0.023, 0.85); + fs->frame++; + fs->obs[0] = x + DEF_OBS[0]; + fs->obs[1] = y + DEF_OBS[1]; + fs->obs[2] = z + DEF_OBS[2]; + fs->dir[1] = y; + fs->dir[2] = z; + } + + glEnable(GL_DEPTH_TEST); + + if (fs->fog) + glEnable(GL_FOG); + else + glDisable(GL_FOG); + + glDepthMask(GL_TRUE); + glClearColor(0.5, 0.5, 0.8, 1.0); /* sky in the distance */ + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + + glPushMatrix(); + + calcposobs(fs); + + gltrackball_rotate (fs->trackball); + + gluLookAt(fs->obs[0], fs->obs[1], fs->obs[2], + fs->obs[0] + fs->dir[0], + fs->obs[1] + fs->dir[1], + fs->obs[2] + fs->dir[2], + 0.0, 1.0, 0.0); + + glEnable(GL_TEXTURE_2D); + + /* draw ground using the computed texture */ + if (do_texture) { + glColor4f(1.0,1.0,1.0,1.0); /* white to get texture in it's true color */ +#ifdef HAVE_GLBINDTEXTURE + glBindTexture(GL_TEXTURE_2D, fs->groundid); +#endif /* HAVE_GLBINDTEXTURE */ + } + else + glColor4f(0.54, 0.27, 0.07, 1.0); /* untextured ground color */ + glBegin(GL_QUADS); + glTexCoord2fv(qt[0]); + glVertex3fv(q[0]); + glTexCoord2fv(qt[1]); + glVertex3fv(q[1]); + glTexCoord2fv(qt[2]); + glVertex3fv(q[2]); + glTexCoord2fv(qt[3]); + glVertex3fv(q[3]); + mi->polygon_count++; + glEnd(); + + glAlphaFunc(GL_GEQUAL, 0.9); + if (fs->num_trees) + { + /* here do_texture IS True - and color used is white */ + glEnable(GL_ALPHA_TEST); +#ifdef HAVE_GLBINDTEXTURE + glBindTexture(GL_TEXTURE_2D,fs->treeid); +#endif /* HAVE_GLBINDTEXTURE */ + for(j=0;jnum_trees;j++) + mi->polygon_count += drawtree(fs->treepos[j].x ,fs->treepos[j].y ,fs->treepos[j].z ); + glDisable(GL_ALPHA_TEST); + } + glDisable(GL_TEXTURE_2D); + glDepthMask(GL_FALSE); + + if (fs->shadows) { + /* draw shadows with black color */ + glBegin(wire ? GL_LINE_STRIP : GL_TRIANGLES); + for (j = 0; j < fs->np; j++) { + glColor4f(black[0], black[1], black[2], fs->p[j].c[0][3]); + glVertex3f(fs->p[j].p[0][0], 0.1, fs->p[j].p[0][2]); + + glColor4f(black[0], black[1], black[2], fs->p[j].c[1][3]); + glVertex3f(fs->p[j].p[1][0], 0.1, fs->p[j].p[1][2]); + + glColor4f(black[0], black[1], black[2], fs->p[j].c[2][3]); + glVertex3f(fs->p[j].p[2][0], 0.1, fs->p[j].p[2][2]); + mi->polygon_count++; + } + glEnd(); + } + + glBegin(wire ? GL_LINE_STRIP : GL_TRIANGLES); + for (j = 0; j < fs->np; j++) { + /* draw particles: colors are computed in setpart */ + glColor4fv(fs->p[j].c[0]); + glVertex3fv(fs->p[j].p[0]); + + glColor4fv(fs->p[j].c[1]); + glVertex3fv(fs->p[j].p[1]); + + glColor4fv(fs->p[j].c[2]); + glVertex3fv(fs->p[j].p[2]); + mi->polygon_count++; + + setpart(fs, &fs->p[j]); + } + glEnd(); + + /* draw rain particles if no fire particles */ + if (!fs->np) + { + float timeused = gettimerain(); + glDisable(GL_TEXTURE_2D); + glShadeModel(GL_SMOOTH); + glBegin(GL_LINES); + for (j = 0; j < NUMPART; j++) { + glColor4f(0.7f,0.95f,1.0f,0.0f); + glVertex3fv(fs->r[j].oldpos); + glColor4f(0.3f,0.7f,1.0f,1.0f); + glVertex3fv(fs->r[j].pos); + setpartrain(fs, &fs->r[j],timeused); + mi->polygon_count++; + } + glEnd(); + glShadeModel(GL_FLAT); + } + + glDisable(GL_TEXTURE_2D); + glDisable(GL_ALPHA_TEST); + glDisable(GL_DEPTH_TEST); + glDisable(GL_FOG); + + /* manage framerate display */ + if (MI_IS_FPS(mi)) do_fps (mi); + glPopMatrix(); +} + + +static Bool Init(ModeInfo * mi) +{ + int i; + firestruct *fs = &fire[MI_SCREEN(mi)]; + + /* default settings */ + fs->eject_r = 0.1 + NRAND(10) * 0.03; + fs->dt = 0.015; + fs->eject_vy = 4; + fs->eject_vl = 1; + fs->ridtri = 0.1 + NRAND(10) * 0.005; + fs->maxage = 1.0 / fs->dt; + vinit(fs->obs, DEF_OBS[0], DEF_OBS[1], DEF_OBS[2]); + fs->v = 0.0; + fs->alpha = DEF_ALPHA; + fs->beta = DEF_BETA; + + /* initialise texture stuff */ + if (do_texture) + inittextures(mi); + else + { + fs->ttexture = (XImage*) NULL; + fs->gtexture = (XImage*) NULL; + } + + if (MI_IS_DEBUG(mi)) { + (void) fprintf(stderr, + "%s:\n\tnum_part=%d\n\ttrees=%d\n\tfog=%s\n\tshadows=%s\n\teject_r=%.3f\n\tridtri=%.3f\n", + MI_NAME(mi), + fs->np, + fs->num_trees, + fs->fog ? "on" : "off", + fs->shadows ? "on" : "off", + fs->eject_r, fs->ridtri); + } + + /* initialise particles and trees */ + for (i = 0; i < fs->np; i++) { + setnewpart(fs, &(fs->p[i])); + } + + if (fs->num_trees) + if (!inittree(mi)) { + return False; + } + + /* if no fire particles then initialise rain particles */ + if (!fs->np) + { + vinit(fs->min,-7.0f,-0.2f,-7.0f); + vinit(fs->max,7.0f,8.0f,7.0f); + for (i = 0; i < NUMPART; i++) { + setnewrain(fs, &(fs->r[i])); + } + } + + return True; +} + +/* + *----------------------------------------------------------------------------- + *----------------------------------------------------------------------------- + * Xlock hooks. + *----------------------------------------------------------------------------- + *----------------------------------------------------------------------------- + */ + + +static void +free_fire(firestruct *fs) +{ + if (mode_font != None && fs->fontbase != None) { + glDeleteLists(fs->fontbase, mode_font->max_char_or_byte2 - + mode_font->min_char_or_byte2 + 1); + fs->fontbase = None; + } + + if (fs->p != NULL) { + (void) free((void *) fs->p); + fs->p = (part *) NULL; + } + if (fs->r != NULL) { + (void) free((void *) fs->r); + fs->r = (rain *) NULL; + } + if (fs->treepos != NULL) { + (void) free((void *) fs->treepos); + fs->treepos = (treestruct *) NULL; + } + if (fs->ttexture != None) { + glDeleteTextures(1, &fs->treeid); + XDestroyImage(fs->ttexture); + fs->ttexture = None; + } + if (fs->gtexture != None) { + glDeleteTextures(1, &fs->groundid); + XDestroyImage(fs->gtexture); + fs->gtexture = None; + } +} + +/* + *----------------------------------------------------------------------------- + * Initialize fire. Called each time the window changes. + *----------------------------------------------------------------------------- + */ + +ENTRYPOINT void +init_fire(ModeInfo * mi) +{ + firestruct *fs; + + /* allocate the main fire table if needed */ + if (fire == NULL) { + if ((fire = (firestruct *) calloc(MI_NUM_SCREENS(mi), + sizeof(firestruct))) == NULL) + return; + } + + /* initialise the per screen fire structure */ + fs = &fire[MI_SCREEN(mi)]; + fs->np = MI_COUNT(mi); + fs->fog = do_fog; + fs->shadows = do_shadows; + /* initialise fire particles if any */ + if ((fs->np)&&(fs->p == NULL)) { + if ((fs->p = (part *) calloc(fs->np, sizeof(part))) == NULL) { + free_fire(fs); + return; + } + } + else if (fs->r == NULL) { + /* initialise rain particles if no fire particles */ + if ((fs->r = (rain *) calloc(NUMPART, sizeof(part))) == NULL) { + free_fire(fs); + return; + } + } + + /* check tree number */ + if (do_texture) + fs->num_trees = (num_treesnum_trees = 0; + + fs->trackball = gltrackball_init (); + + /* xlock GL stuff */ + if ((fs->glx_context = init_GL(mi)) != NULL) { + +#ifndef STANDALONE + Reshape(mi); /* xlock mode */ +#else + reshape_fire(mi,MI_WIDTH(mi),MI_HEIGHT(mi)); /* xscreensaver mode */ +#endif + glDrawBuffer(GL_BACK); + if (!Init(mi)) { + free_fire(fs); + return; + } + } else { + MI_CLEARWINDOW(mi); + } +} + +/* + *----------------------------------------------------------------------------- + * Called by the mainline code periodically to update the display. + *----------------------------------------------------------------------------- + */ +ENTRYPOINT void draw_fire(ModeInfo * mi) +{ + firestruct *fs = &fire[MI_SCREEN(mi)]; + + Display *display = MI_DISPLAY(mi); + Window window = MI_WINDOW(mi); + + MI_IS_DRAWN(mi) = True; + + if (!fs->glx_context) + return; + + glXMakeCurrent(display, window, *(fs->glx_context)); + + glShadeModel(GL_FLAT); + glEnable(GL_DEPTH_TEST); + + /* makes particles blend with background */ + if (!MI_IS_WIREFRAME(mi)||(!fs->np)) + { + glEnable(GL_BLEND); + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + } + + /* fog stuff */ + glEnable(GL_FOG); + glFogi(GL_FOG_MODE, GL_EXP); + glFogfv(GL_FOG_COLOR, fogcolor); + glFogf(GL_FOG_DENSITY, 0.03); + glHint(GL_FOG_HINT, GL_NICEST); + + glPushMatrix(); + glRotatef(current_device_rotation(), 0, 0, 1); + DrawFire(mi); + glPopMatrix(); +#ifndef STANDALONE + Reshape(mi); /* xlock mode */ +#else + reshape_fire(mi,MI_WIDTH(mi),MI_HEIGHT(mi)); /* xscreensaver mode */ +#endif + + glFinish(); + glXSwapBuffers(display, window); +} + + +/* + *----------------------------------------------------------------------------- + * The display is being taken away from us. Free up malloc'ed + * memory and X resources that we've alloc'ed. Only called + * once, we must zap everything for every screen. + *----------------------------------------------------------------------------- + */ + +ENTRYPOINT void release_fire(ModeInfo * mi) +{ + if (fire != NULL) { + int screen; + for (screen = 0; screen < MI_NUM_SCREENS(mi); screen++) + free_fire(&fire[screen]); + (void) free((void *) fire); + fire = (firestruct *) NULL; + } + if (mode_font != None) + { + /* only free-ed when there are no more screens used */ + XFreeFont(MI_DISPLAY(mi), mode_font); + mode_font = None; + } + FreeAllGL(mi); +} + +ENTRYPOINT Bool +fire_handle_event (ModeInfo *mi, XEvent *event) +{ + firestruct *fs = &fire[MI_SCREEN(mi)]; + + if (event->xany.type == ButtonPress && + event->xbutton.button == Button1) + { + fs->button_down_p = True; + event->xbutton.x = MI_WIDTH(mi) - event->xbutton.x; /* kludge! */ + event->xbutton.y = MI_HEIGHT(mi) - event->xbutton.y; + gltrackball_start (fs->trackball, + event->xbutton.x, event->xbutton.y, + MI_WIDTH (mi), MI_HEIGHT (mi)); + return True; + } + else if (event->xany.type == ButtonRelease && + event->xbutton.button == Button1) + { + fs->button_down_p = False; + return True; + } + else if (event->xany.type == ButtonPress && + (event->xbutton.button == Button4 || + event->xbutton.button == Button5 || + event->xbutton.button == Button6 || + event->xbutton.button == Button7)) + { + gltrackball_mousewheel (fs->trackball, event->xbutton.button, 5, + !!event->xbutton.state); + return True; + } + else if (event->xany.type == MotionNotify && + fs->button_down_p) + { + event->xmotion.x = MI_WIDTH(mi) - event->xmotion.x; /* kludge! */ + event->xmotion.y = MI_HEIGHT(mi) - event->xmotion.y; + gltrackball_track (fs->trackball, + event->xmotion.x, event->xmotion.y, + MI_WIDTH (mi), MI_HEIGHT (mi)); + return True; + } + + return False; +} + + +#ifndef STANDALONE +ENTRYPOINT void change_fire(ModeInfo * mi) +{ + firestruct *fs = &fire[MI_SCREEN(mi)]; + + if (!fs->glx_context) + return; + + glXMakeCurrent(MI_DISPLAY(mi), MI_WINDOW(mi), *(fs->glx_context)); + + /* if available, randomly change some values */ + if (do_fog) + fs->fog = LRAND() & 1; + if (do_shadows) + fs->shadows = LRAND() & 1; + /* reset observer position */ + frame = 0; + vinit(fs->obs, DEF_OBS[0], DEF_OBS[1], DEF_OBS[2]); + fs->v = 0.0; + /* particle randomisation */ + fs->eject_r = 0.1 + NRAND(10) * 0.03; + fs->ridtri = 0.1 + NRAND(10) * 0.005; + + if (MI_IS_DEBUG(mi)) { + (void) fprintf(stderr, + "%s:\n\tnum_part=%d\n\ttrees=%d\n\tfog=%s\n\tshadows=%s\n\teject_r=%.3f\n\tridtri=%.3f\n", + MI_NAME(mi), + fs->np, + fs->num_trees, + fs->fog ? "on" : "off", + fs->shadows ? "on" : "off", + fs->eject_r, fs->ridtri); + } +} +#endif /* !STANDALONE */ + +XSCREENSAVER_MODULE_2 ("GLForestFire", glforestfire, fire) + +#endif /* MODE_fire */ diff --git a/hacks/glx/glforestfire.man b/hacks/glx/glforestfire.man new file mode 100644 index 00000000..aae3a25e --- /dev/null +++ b/hacks/glx/glforestfire.man @@ -0,0 +1,130 @@ +.de EX \"Begin example +.ne 5 +.if n .sp 1 +.if t .sp .5 +.nf +.in +.5i +.. +.de EE +.fi +.in -.5i +.if n .sp 1 +.if t .sp .5 +.. +.TH XScreenSaver 1 "03-Oct-01" "X Version 11" +.SH NAME +glforestfire - draws a GL animation of sprinkling fire-like 3D triangles +.SH SYNOPSIS +.B glforestfire +[\-display \fIhost:display.screen\fP] [\-window] [\-root] +[\-visual \fIvisual\fP] [\-delay \fImicroseconds\fP] +[\-count \fInumber_of_particles\fP] +[\-trees \fInumber_of_trees\fP] +[\-size \fIviewport_size\fP] +[\-texture] [\-no-texture] +[\-shadows] [\-no-shadows] +[\-fog] [\-no-fog] +[\-wireframe] [\-no-wireframe] +[\-wander] [\-no-wander] +[\-trackmouse] [\-no-trackmouse] +[\-fps] +.SH DESCRIPTION +The \fIglforestfire\fP program draws an animation of sprinkling fire-like 3D triangles in +a landscape filled with trees. +.SH OPTIONS +.I glforestfire +accepts the following options: +.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 \-install +Install a private colormap for the window. +.TP 8 +.B \-visual \fIvisual\fP\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 \-fps +Display the current frame rate, CPU load, and polygon count. +.TP 8 +.B \-trees \fInumber_of_trees\fP\fP +Specify how much trees are drawn in the landscape. +.TP 8 +.B \-count \fInumber_of_particles\fP\fP +Specify how much fire particles are drawn. A very special case is 0 +wich means that you get +.B rain +! +.TP 8 +.B \-size \fIviewport_size\fP\fP +Viewport of GL scene is specified size if greater than 32 and less than screensize. Default value is 0, meaning full screensize. +.TP 8 +.B \-texture +Show a textured ground and the trees. This is the default. +.TP 8 +.B \-no\-texture +Disables texturing the landscape. This implies that no trees are drawn. +.TP 8 +.B \-shadows +Show a shadow for each particle on the ground. This is the default. +.TP 8 +.B \-no\-shadows +Disables the drawing of the shadows. +.TP 8 +.B \-fog +Show a fog in the distance. +.TP 8 +.B \-no\-fog +Disables the fog. This is the default. +.TP 8 +.B \-wander +Move the observer around the landscape. This is the default. +.TP 8 +.B \-no\-wander +Keep the fire centered on the screen. +.TP 8 +.B \-trackmouse +Let the mouse be a joystick to change the view of the landscape. +This implies +.I \-no\-wander. +.TP 8 +.B \-no\-trackmouse +Disables mouse tracking. This is the default. +.TP 8 +.B \-wire +Draw a wireframe rendition of the fire: this will consist only of +single-pixel lines for the triangles. +.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 2001 by Eric Lassauge. +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. + +The original code for this hack was written by David Bucciarelli +(tech.hmw@plus.it) and could be found in the demo package +of Mesa (Mesa-3.2/3Dfx/demos/). This hack is the result of the merge of +two of the David's demos (fire and rain). + +.SH AUTHOR +David Bucciarelli +Eric Lassauge diff --git a/hacks/glx/glhanoi.c b/hacks/glx/glhanoi.c new file mode 100644 index 00000000..a9269eef --- /dev/null +++ b/hacks/glx/glhanoi.c @@ -0,0 +1,2065 @@ +/* -*- Mode: C; tab-width: 4 -*- */ +/* glhanoi, Copyright (c) 2005, 2009 Dave Atkinson + * except noise function code Copyright (c) 2002 Ken Perlin + * Modified by Lars Huttar (c) 2010, to generalize to 4 or more poles + * + * 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. + */ + +#include + +#include "rotator.h" + +#define DEF_LIGHT "True" +#define DEF_FOG "False" +#define DEF_TEXTURE "True" +#define DEF_POLES "0" /* choose random value */ +#define DEF_SPEED "1" +#define DEF_TRAILS "2" + +#define DEFAULTS "*delay: 15000\n" \ + "*count: 0\n" \ + "*showFPS: False\n" \ + "*wireframe: False\n" + +# define refresh_glhanoi 0 + +/* polygon resolution of poles and disks */ +#define NSLICE 32 +#define NLOOPS 1 + +/* How long to wait at start and finish (seconds). */ +#define START_DURATION 1.0 +#define FINISH_DURATION 1.0 +#define BASE_LENGTH 30.0 +#define BOARD_SQUARES 8 + +/* Don't draw trail lines till they're this old (sec). + Helps trails not be "attached" to the disks. */ +#define TRAIL_START_DELAY 0.1 + +#define MAX_CAMERA_RADIUS 250.0 +#define MIN_CAMERA_RADIUS 75.0 + +#define MARBLE_SCALE 1.01 + +#undef BELLRAND +/* Return a double precision number in [0...n], with bell curve distribution. */ +#define BELLRAND(n) ((frand((n)) + frand((n)) + frand((n))) / 3) + +enum { + MARBLE_TEXURE, + N_TEXTURES +}; + +#define MARBLE_TEXTURE_SIZE 256 + +#undef countof +#define countof(x) (sizeof((x))/sizeof((*x))) + +#include +#include "xlockmore.h" + +#ifdef USE_GL /* whole file */ + +typedef struct timeval glhtime; + +static double getTime(void) +{ + struct timeval t; +#ifdef GETTIMEOFDAY_TWO_ARGS + gettimeofday(&t, NULL); +#else /* !GETTIMEOFDAY_TWO_ARGS */ + gettimeofday(&t); +#endif /* !GETTIMEOFDAY_TWO_ARGS */ + return t.tv_sec + t.tv_usec / 1000000.0; +} + +typedef enum { + START, + MOVE_DISK, + MOVE_FINISHED, + FINISHED, + MONEY_SHOT, + INVALID = -1 +} State; + +typedef struct { + int id; + GLuint displayList; + GLfloat position[3]; + GLfloat rotation[3]; + GLfloat color[4]; + GLfloat base0; + GLfloat base1; + GLfloat height; + GLfloat xmin, xmax, ymin, zmin, zmax; + GLfloat u1, u2; + GLfloat t1, t2; + GLfloat ucostheta, usintheta; + GLfloat dx, dz; + GLdouble rotAngle; /* degree of "flipping" so far, during travel */ + GLdouble phi; /* angle of motion in xz plane */ + GLfloat speed; + int polys; +} Disk; + +typedef struct { + Disk **data; + int count; + int size; + GLfloat position[3]; +} Pole; + +/* A SubProblem is a recursive subdivision of the problem, and means + "Move nDisks disks from src pole to dst pole, using the poles indicated in 'available'." */ +typedef struct { + int nDisks; + int src, dst; + unsigned long available; /* a bitmask of poles that have no smaller disks on them */ +} SubProblem; + +typedef struct { + GLfloat position[3]; + double startTime, endTime; + Bool isEnd; +} TrailPoint; + +typedef struct { + GLXContext *glx_context; + State state; + Bool wire; + Bool fog; + Bool light; + Bool layoutLinear; + GLfloat trailDuration; + double startTime; + double lastTime; + double duration; + int numberOfDisks; + int numberOfPoles; + int numberOfMoves; + int maxDiskIdx; + int magicNumber; + Disk *currentDisk; + int move; + /* src, tmp, dst: index of pole that is source / storage / destination for + current move */ + int src; + int tmp; + int dst; + int oldsrc; + int oldtmp; + int olddst; + GLfloat speed; /* coefficient for how fast the disks move */ + SubProblem *solveStack; + int solveStackSize, solveStackIdx; + Pole *pole; + float boardSize; + float baseLength; + float baseWidth; + float baseHeight; + float poleRadius; + float poleHeight; + float poleOffset; + float poleDist; /* distance of poles from center, for round layout */ + float diskHeight; + float maxDiskRadius; + float *diskPos; /* pre-computed disk positions on rods */ + Disk *disk; + GLint floorList; + GLint baseList; + GLint poleList; + int floorpolys, basepolys, polepolys; + int trailQSize; + TrailPoint *trailQ; + int trailQFront, trailQBack; + GLfloat camera[3]; + GLfloat centre[3]; + rotator *the_rotator; + Bool button_down_p; + Bool texture; + GLuint textureNames[N_TEXTURES]; + int drag_x; + int drag_y; + int noise_initted; + int p[512]; +} glhcfg; + +static glhcfg *glhanoi_cfg = NULL; +static Bool fog; +static Bool light; +static Bool texture; +static GLfloat trails; +static int poles; +static GLfloat speed; + +static XrmOptionDescRec opts[] = { + {"-light", ".glhanoi.light", XrmoptionNoArg, "true"}, + {"+light", ".glhanoi.light", XrmoptionNoArg, "false"}, + {"-fog", ".glhanoi.fog", XrmoptionNoArg, "true"}, + {"+fog", ".glhanoi.fog", XrmoptionNoArg, "false"}, + {"-texture", ".glhanoi.texture", XrmoptionNoArg, "true"}, + {"+texture", ".glhanoi.texture", XrmoptionNoArg, "false"}, + {"-trails", ".glhanoi.trails", XrmoptionSepArg, 0}, + {"-poles", ".glhanoi.poles", XrmoptionSepArg, 0 }, + {"-speed", ".glhanoi.speed", XrmoptionSepArg, 0 } +}; + +static argtype vars[] = { + {&light, "light", "Light", DEF_LIGHT, t_Bool}, + {&fog, "fog", "Fog", DEF_FOG, t_Bool}, + {&texture, "texture", "Texture", DEF_TEXTURE, t_Bool}, + {&trails, "trails", "Trails", DEF_TRAILS, t_Float}, + {&poles, "poles", "Poles", DEF_POLES, t_Int}, + {&speed, "speed", "Speed", DEF_SPEED, t_Float} +}; + +static OptionStruct desc[] = { + {"+/-light", "whether to light the scene"}, + {"+/-fog", "whether to apply fog to the scene"}, + {"+/-texture", "whether to apply texture to the scene"}, + {"-trails t", "how long of disk trails to show (sec.)"}, + {"-poles r", "number of poles to move disks between"}, + {"-speed s", "speed multiplier"} +}; + +ENTRYPOINT ModeSpecOpt glhanoi_opts = { countof(opts), opts, countof(vars), vars, desc }; + +#ifdef USE_MODULES + +ModStruct glhanoi_description = { + "glhanoi", "init_glhanoi", "draw_glhanoi", "release_glhanoi", + "draw_glhanoi", "init_glhanoi", NULL, &glhanoi_opts, + 1000, 1, 2, 1, 4, 1.0, "", + "Towers of Hanoi", 0, NULL +}; + +#endif + +static const GLfloat cBlack[] = { 0.0, 0.0, 0.0, 1.0 }; +static const GLfloat cWhite[] = { 1.0, 1.0, 1.0, 1.0 }; +static const GLfloat poleColor[] = { 0.545, 0.137, 0.137 }; +static const GLfloat baseColor[] = { 0.34, 0.34, 0.48 }; +/* static const GLfloat baseColor[] = { 0.545, 0.137, 0.137 }; */ +static const GLfloat fogcolor[] = { 0.5, 0.5, 0.5 }; +static GLfloat trailColor[] = { 1.0, 1.0, 1.0, 0.5 }; + +static const float left[] = { 1.0, 0.0, 0.0 }; +static const float up[] = { 0.0, 1.0, 0.0 }; +static const float front[] = { 0.0, 0.0, 1.0 }; +static const float right[] = { -1.0, 0.0, 0.0 }; +static const float down[] = { 0.0, -1.0, 0.0 }; +static const float back[] = { 0.0, 0.0, -1.0 }; + +static const GLfloat pos0[4] = { 50.0, 50.0, 50.0, 0.0 }; +static const GLfloat amb0[4] = { 0.0, 0.0, 0.0, 1.0 }; +static const GLfloat dif0[4] = { 1.0, 1.0, 1.0, 1.0 }; +static const GLfloat spc0[4] = { 0.0, 1.0, 1.0, 1.0 }; + +static const GLfloat pos1[4] = { -50.0, 50.0, -50.0, 0.0 }; +static const GLfloat amb1[4] = { 0.0, 0.0, 0.0, 1.0 }; +static const GLfloat dif1[4] = { 1.0, 1.0, 1.0, 1.0 }; +static const GLfloat spc1[4] = { 1.0, 1.0, 1.0, 1.0 }; + +static float g = 3.0 * 9.80665; /* hmm, looks like we need more gravity, Scotty... */ + +static void checkAllocAndExit(Bool item, char *descr) { + if (!item) { + fprintf(stderr, "%s: unable to allocate memory for %s\n", + progname, descr); + exit(EXIT_FAILURE); + } +} + +#define DOPUSH(X, Y) (((X)->count) >= ((X)->size)) ? NULL : ((X)->data[(X)->count++] = (Y)) +#define DOPOP(X) (X)->count <= 0 ? NULL : ((X)->data[--((X)->count)]) + +/* push disk d onto pole idx */ +static Disk *push(glhcfg *glhanoi, int idx, Disk * d) +{ + return DOPUSH(&glhanoi->pole[idx], d); +} + +/* pop the top disk from pole idx */ +static Disk *pop(glhcfg *glhanoi, int idx) +{ + return DOPOP(&glhanoi->pole[idx]); +} + +static inline void swap(int *x, int *y) +{ + *x = *x ^ *y; + *y = *x ^ *y; + *x = *x ^ *y; +} + +/* + * magic - it's magic... + * Return 1 if the number of trailing zeroes on i is even, unless i is 1 or 0. + */ +static int magic(int i) +{ + int count = 0; + if(i <= 1) + return 0; + while((i & 0x01) == 0) { + i >>= 1; + count++; + } + return count % 2 == 0; +} + +static float distance(float *p0, float *p1) +{ + float x, y, z; + x = p1[0] - p0[0]; + y = p1[1] - p0[1]; + z = p1[2] - p0[2]; + return (float)sqrt(x * x + y * y + z * z); +} + +/* What is this for? + = c / (a b - 0.25 (a^2 + 2 a b + b^2) ) + = c / (-0.25 (a^2 - 2 a b + b^2) ) + = c / (-0.25 ((a - b)(a - b))) + = -4 c / (a - b)^2 +static GLfloat A(GLfloat a, GLfloat b, GLfloat c) +{ + GLfloat sum = a + b; + return c / (a * b - 0.25 * sum * sum); +} +*/ + +static void moveSetup(glhcfg *glhanoi, Disk * disk) +{ + float h, ymax; + float u; + int src = glhanoi->src; + int dst = glhanoi->dst; + GLfloat theta; + GLfloat sintheta, costheta; + double absx, dh; + double dx, dz; /* total x and z distances from src to dst */ + Pole *poleSrc, *poleDst; + + poleSrc = &(glhanoi->pole[src]); + poleDst = &(glhanoi->pole[dst]); + + disk->xmin = poleSrc->position[0]; + /* glhanoi->poleOffset * (src - (glhanoi->numberOfPoles - 1.0f) * 0.5); */ + disk->xmax = poleDst->position[0]; + /* disk->xmax = glhanoi->poleOffset * (dst - (glhanoi->numberOfPoles - 1.0f) * 0.5); */ + disk->ymin = glhanoi->poleHeight; + disk->zmin = poleSrc->position[2]; + disk->zmax = poleDst->position[2]; + + dx = disk->xmax - disk->xmin; + dz = disk->zmax - disk->zmin; + + if(glhanoi->state != FINISHED) { + double xxx = ((dx < 0) ? 180.0 : -180.0); + if(random() % 6 == 0) { + disk->rotAngle = xxx * (2 - 2 * random() % 2) * (random() % 3 + 1); + } else { + disk->rotAngle = xxx; + } + if(random() % 4 == 0) { + /* Backflip */ + disk->rotAngle = -disk->rotAngle; + } + } else { + disk->rotAngle = -180.0; + } + + disk->base0 = glhanoi->diskPos[poleSrc->count]; + disk->base1 = (glhanoi->state == FINISHED) ? + disk->base0 : glhanoi->diskPos[poleDst->count]; + + /* horizontal distance to travel? */ + /* was: absx = sqrt(disk->xmax - disk->xmin); */ + dh = distance(poleSrc->position, poleDst->position); + absx = sqrt(dh); + ymax = glhanoi->poleHeight + dh; + if(glhanoi->state == FINISHED) { + ymax += dh * (double)(glhanoi->numberOfDisks - disk->id); + } + h = ymax - disk->ymin; + /* A(a, b, c) = -4 c / (a - b)^2 */ + /* theta = atan(4 h / (b - a)) */ + theta = atan(4 * h / dh); + if(theta < 0.0) + theta += M_PI; + costheta = cos(theta); + sintheta = sin(theta); + u = (float) + sqrt(fabs + (-g / + /* (2.0 * A(disk->xmin, disk->xmax, h) * costheta * costheta))); */ + (2.0 * -4 * h / (dh * dh) * costheta * costheta))); + disk->usintheta = u * sintheta; + disk->ucostheta = u * costheta; + /* Not to be confused: disk->dx is the per-time-unit portion of dx */ + disk->dx = disk->ucostheta * dx / dh; + disk->dz = disk->ucostheta * dz / dh; + disk->t1 = + (-u + sqrt(u * u + 2.0 * g * fabs(disk->ymin - disk->base0))) / g; + disk->u1 = u + g * disk->t1; + disk->t2 = 2.0 * disk->usintheta / g; + disk->u2 = disk->usintheta - g * disk->t2; + + /* Compute direction of travel, in the XZ plane. */ + disk->phi = atan(dz / dx); + disk->phi *= 180.0 / M_PI; /* convert radians to degrees */ +} + +/* For debugging: show a value as a string of ones and zeroes +static const char *byteToBinary(int x) { + static char b[9]; + int i, z; + + for (z = 128, i = 0; z > 0; z >>= 1, i++) { + b[i] = ((x & z) == z) ? '1' : '0'; + } + b[i] = '\0'; + + return b; +} +*/ + +static void pushMove(glhcfg *glhanoi, int n, int src, int dst, int avail) { + SubProblem *sp = &(glhanoi->solveStack[glhanoi->solveStackIdx++]); + + if (glhanoi->solveStackIdx > glhanoi->solveStackSize) { + fprintf(stderr, "solveStack overflow: pushed index %d: %d from %d to %d, using %d\n", + glhanoi->solveStackIdx, n, src, dst, avail); + exit(EXIT_FAILURE); + } + + sp->nDisks = n; + sp->src = src; + sp->dst = dst; + sp->available = avail & ~((unsigned long)(1 << src)) + & ~((unsigned long)(1 << dst)); + /* + fprintf(stderr, "Debug: > pushed solveStack %d: %d from %d to %d, using %s\n", + glhanoi->solveStackIdx - 1, n, src, dst, byteToBinary(sp->available)); + */ +} + +static Bool solveStackEmpty(glhcfg *glhanoi) { + return (glhanoi->solveStackIdx < 1); +} + +static SubProblem *popMove(glhcfg *glhanoi) { + SubProblem *sp; + if (solveStackEmpty(glhanoi)) return (SubProblem *)NULL; + sp = &(glhanoi->solveStack[--glhanoi->solveStackIdx]); + /* fprintf(stderr, "Debug: < popped solveStack %d: %d from %d to %d, using %s\n", + glhanoi->solveStackIdx, sp->nDisks, sp->src, sp->dst, byteToBinary(sp->available)); */ + return sp; +} + +/* Return number of bits set in b */ +static int numBits(unsigned long b) { + int count = 0; + while (b) { + count += b & 0x1u; + b >>= 1; + } + return count; +} + +/* Return index (power of 2) of least significant 1 bit. */ +static int bitScan(unsigned long b) { + int count; + for (count = 0; b; count++, b >>= 1) { + if (b & 0x1u) return count; + } + return -1; +} + +/* A bit pattern representing all poles */ +#define ALL_POLES ((1 << glhanoi->numberOfPoles) - 1) + +#define REMOVE_BIT(a, b) ((a) & ~(1 << (b))) +#define ADD_BIT(a, b) ((a) | (1 << (b))) + +static void makeMove(glhcfg *glhanoi) +{ + if (glhanoi->numberOfPoles == 3) { + int fudge = glhanoi->move + 2; + int magicNumber = magic(fudge); + + + glhanoi->currentDisk = pop(glhanoi, glhanoi->src); + moveSetup(glhanoi, glhanoi->currentDisk); + push(glhanoi, glhanoi->dst, glhanoi->currentDisk); + + fudge = fudge % 2; + + if(fudge == 1 || magicNumber) { + swap(&glhanoi->src, &glhanoi->tmp); + } + if(fudge == 0 || glhanoi->magicNumber) { + swap(&glhanoi->dst, &glhanoi->tmp); + } + glhanoi->magicNumber = magicNumber; + } else { + SubProblem sp; + int tmp = 0; + + if (glhanoi->move == 0) { + /* Initialize the solution stack. Original problem: + move all disks from pole 0 to furthest pole, + using all other poles. */ + pushMove(glhanoi, glhanoi->numberOfDisks, 0, + glhanoi->numberOfPoles - 1, + REMOVE_BIT(REMOVE_BIT(ALL_POLES, 0), glhanoi->numberOfPoles - 1)); + } + + while (!solveStackEmpty(glhanoi)) { + int k, numAvail; + sp = *popMove(glhanoi); + + if (sp.nDisks == 1) { + /* We have a single, concrete move to do. */ + /* moveSetup uses glhanoi->src, dst. */ + glhanoi->src = sp.src; + glhanoi->dst = sp.dst; + glhanoi->tmp = tmp; /* Probably unnecessary */ + + glhanoi->currentDisk = pop(glhanoi, sp.src); + moveSetup(glhanoi, glhanoi->currentDisk); + push(glhanoi, sp.dst, glhanoi->currentDisk); + + return; + } else { + /* Divide and conquer, using Frame-Stewart algorithm, until we get to base case */ + if (sp.nDisks == 1) break; + + numAvail = numBits(sp.available); + if (numAvail < 2) k = sp.nDisks - 1; + else if(numAvail >= sp.nDisks - 2) k = 1; + /* heuristic for optimal k: sqrt(2n) (see http://www.cs.wm.edu/~pkstoc/boca.pdf) */ + else k = (int)(sqrt(2 * sp.nDisks)); + + if (k >= sp.nDisks) k = sp.nDisks - 1; + else if (k < 1) k = 1; + + tmp = bitScan(sp.available); + /* fprintf(stderr, "Debug: k is %d, tmp is %d\n", k, tmp); */ + if (tmp == -1) { + fprintf(stderr, "Error: n > 1 (%d) and no poles available\n", + sp.nDisks); + } + + /* Push on moves in reverse order, since this is a stack. */ + pushMove(glhanoi, k, tmp, sp.dst, + REMOVE_BIT(ADD_BIT(sp.available, sp.src), tmp)); + pushMove(glhanoi, sp.nDisks - k, sp.src, sp.dst, + REMOVE_BIT(sp.available, tmp)); + pushMove(glhanoi, k, sp.src, tmp, + REMOVE_BIT(ADD_BIT(sp.available, sp.dst), tmp)); + + /* Repeat until we've found a move we can make. */ + } + } + } +} + +static double lerp(double alpha, double start, double end) +{ + return start + alpha * (end - start); +} + +static void upfunc(GLdouble t, Disk * d) +{ + d->position[0] = d->xmin; + d->position[1] = d->base0 + (d->u1 - 0.5 * g * t) * t; + d->position[2] = d->zmin; + + d->rotation[1] = 0.0; +} + +static void parafunc(GLdouble t, Disk * d) +{ + /* ##was: d->position[0] = d->xmin + d->ucostheta * t; */ + d->position[0] = d->xmin + d->dx * t; + d->position[2] = d->zmin + d->dz * t; + d->position[1] = d->ymin + (d->usintheta - 0.5 * g * t) * t; + + d->rotation[1] = d->rotAngle * t / d->t2; + /* d->rotAngle * (d->position[0] - d->xmin) / (d->xmax - d->xmin); */ +} + +static void downfunc(GLdouble t, Disk * d) +{ + d->position[0] = d->xmax; + d->position[1] = d->ymin + (d->u2 - 0.5 * g * t) * t; + d->position[2] = d->zmax; + + d->rotation[1] = 0.0; +} + +#define normalizeQ(i) ((i) >= glhanoi->trailQSize ? (i) - glhanoi->trailQSize : (i)) +#define normalizeQNeg(i) ((i) < 0 ? (i) + glhanoi->trailQSize : (i)) + +/* Add trail point at position posn at time t onto back of trail queue. + Removes old trails if necessary to make room. */ +static void enQTrail(glhcfg *glhanoi, GLfloat *posn) +{ + if (glhanoi->trailQSize && glhanoi->state != MONEY_SHOT) { + TrailPoint *tp = &(glhanoi->trailQ[glhanoi->trailQBack]); + double t = getTime(); + + tp->position[0] = posn[0]; + tp->position[1] = posn[1] + glhanoi->diskHeight; + /* Slight jitter to prevent clashing with other trails */ + tp->position[2] = posn[2] + (glhanoi->move % 23) * 0.01; + tp->startTime = t + TRAIL_START_DELAY; + tp->endTime = t + TRAIL_START_DELAY + glhanoi->trailDuration; + tp->isEnd = False; + + /* Update queue back/front indices */ + glhanoi->trailQBack = normalizeQ(glhanoi->trailQBack + 1); + if (glhanoi->trailQBack == glhanoi->trailQFront) + glhanoi->trailQFront = normalizeQ(glhanoi->trailQFront + 1); + } +} + +/* Mark last trailpoint in queue as the end of a trail. */ +/* was: #define endTrail(glh) ((glh)->trailQ[(glh)->trailQBack].isEnd = True) */ +static void endTrail(glhcfg *glhanoi) { + if (glhanoi->trailQSize) + glhanoi->trailQ[normalizeQNeg(glhanoi->trailQBack - 1)].isEnd = True; +} + +/* Update disk d's position and rotation based on time t. + Returns true iff move is finished. */ +static Bool computePosition(glhcfg *glhanoi, GLfloat t, Disk * d) +{ + Bool finished = False; + + if(t < d->t1) { + upfunc(t, d); + } else if(t < d->t1 + d->t2) { + parafunc(t - d->t1, d); + enQTrail(glhanoi, d->position); + } else { + downfunc(t - d->t1 - d->t2, d); + if(d->position[1] <= d->base1) { + d->position[1] = d->base1; + finished = True; + endTrail(glhanoi); + } + } + return finished; +} + +static void updateView(glhcfg *glhanoi) +{ + double longitude, latitude, radius; + double a, b, c, A, B; + + get_position(glhanoi->the_rotator, NULL, NULL, &radius, + !glhanoi->button_down_p); + get_rotation(glhanoi->the_rotator, &longitude, &latitude, NULL, + !glhanoi->button_down_p); + longitude += glhanoi->camera[0]; + latitude += glhanoi->camera[1]; + radius += glhanoi->camera[2]; + /* FUTURE: tweak this to be smooth: */ + longitude = longitude - floor(longitude); + latitude = latitude - floor(latitude); + radius = radius - floor(radius); + if(latitude > 0.5) { + latitude = 1.0 - latitude; + } + if(radius > 0.5) { + radius = 1.0 - radius; + } + + b = glhanoi->centre[1]; + c = (MIN_CAMERA_RADIUS + + radius * (MAX_CAMERA_RADIUS - MIN_CAMERA_RADIUS)); + A = M_PI / 4.0 * (1.0 - latitude); + a = sqrt(b * b + c * c - 2.0 * b * c * cos(A)); + B = asin(sin(A) * b / a); + glRotatef(-B * 180 / M_PI, 1.0, 0.0, 0.0); + + glTranslatef(0.0f, 0.0f, + -(MIN_CAMERA_RADIUS + + radius * (MAX_CAMERA_RADIUS - MIN_CAMERA_RADIUS))); + glRotatef(longitude * 360.0, 0.0f, 1.0f, 0.0f); + glRotatef(latitude * 180.0, cos(longitude * 2.0 * M_PI), 0.0, + sin(longitude * 2.0 * M_PI)); +} + +static void changeState(glhcfg *glhanoi, State state) +{ + glhanoi->state = state; + glhanoi->startTime = getTime(); +} + +static Bool finishedHanoi(glhcfg *glhanoi) { + /* use different criteria depending on algorithm */ + return (glhanoi->numberOfPoles == 3 ? + glhanoi->move >= glhanoi->numberOfMoves : + solveStackEmpty(glhanoi)); +} + +static void update_glhanoi(glhcfg *glhanoi) +{ + double t = getTime() - glhanoi->startTime; + int i; + Bool done; + + switch (glhanoi->state) { + case START: + if(t < glhanoi->duration) { + break; + } + glhanoi->move = 0; + if(glhanoi->numberOfDisks % 2 == 0) { + swap(&glhanoi->tmp, &glhanoi->dst); + } + glhanoi->magicNumber = 1; + makeMove(glhanoi); + changeState(glhanoi, MOVE_DISK); + break; + + case MOVE_DISK: + if(computePosition(glhanoi, t * glhanoi->currentDisk->speed, glhanoi->currentDisk)) { + changeState(glhanoi, MOVE_FINISHED); + } + break; + + case MOVE_FINISHED: + ++glhanoi->move; + if(!finishedHanoi(glhanoi)) { + makeMove(glhanoi); + changeState(glhanoi, MOVE_DISK); + } else { + glhanoi->duration = FINISH_DURATION; + changeState(glhanoi, FINISHED); + } + break; + + case FINISHED: + if (t < glhanoi->duration) + break; + glhanoi->src = glhanoi->olddst; + glhanoi->dst = glhanoi->oldsrc; + for(i = 0; i < glhanoi->numberOfDisks; ++i) { + Disk *disk = pop(glhanoi, glhanoi->src); + assert(disk != NULL); + moveSetup(glhanoi, disk); + } + for(i = glhanoi->maxDiskIdx; i >= 0; --i) { + push(glhanoi, glhanoi->dst, &glhanoi->disk[i]); + } + changeState(glhanoi, MONEY_SHOT); + break; + + case MONEY_SHOT: + done = True; + for(i = glhanoi->maxDiskIdx; i >= 0; --i) { + double delay = 0.25 * i; + int finished; + + if(t - delay < 0) { + done = False; + continue; + } + + finished = computePosition(glhanoi, t - delay, &glhanoi->disk[i]); + glhanoi->disk[i].rotation[1] = 0.0; + + if(!finished) { + done = False; + } + } + if(done) { + glhanoi->src = glhanoi->oldsrc; + glhanoi->tmp = glhanoi->oldtmp; + glhanoi->dst = glhanoi->olddst; + changeState(glhanoi, START); + } + break; + + case INVALID: + default: + fprintf(stderr, "Invalid state\n"); + break; + } +} + +static void HSVtoRGBf(GLfloat h, GLfloat s, GLfloat v, + GLfloat * r, GLfloat * g, GLfloat * b) +{ + if(s == 0.0) { + *r = v; + *g = v; + *b = v; + } else { + GLfloat i, f, p, q, t; + if(h >= 360.0) { + h = 0.0; + } + h /= 60.0; /* h now in [0,6). */ + i = floor((double)h); /* i now largest integer <= h */ + f = h - i; /* f is no fractional part of h */ + p = v * (1.0 - s); + q = v * (1.0 - (s * f)); + t = v * (1.0 - (s * (1.0 - f))); + switch ((int)i) { + case 0: + *r = v; + *g = t; + *b = p; + break; + case 1: + *r = q; + *g = v; + *b = p; + break; + case 2: + *r = p; + *g = v; + *b = t; + break; + case 3: + *r = p; + *g = q; + *b = v; + break; + case 4: + *r = t; + *g = p; + *b = v; + break; + case 5: + *r = v; + *g = p; + *b = q; + break; + } + } +} + +static void HSVtoRGBv(GLfloat * hsv, GLfloat * rgb) +{ + HSVtoRGBf(hsv[0], hsv[1], hsv[2], &rgb[0], &rgb[1], &rgb[2]); +} + +static void setMaterial(const GLfloat color[3], const GLfloat hlite[3], int shininess) +{ + glColor3fv(color); + glMaterialfv(GL_FRONT, GL_SPECULAR, hlite); + glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, color); + glMateriali(GL_FRONT, GL_SHININESS, shininess); /* [0,128] */ +} + +/* + * drawTube: I know all this stuff is available in gluQuadrics + * but I'd originally intended to texture the poles with a 3D wood + * texture, but I was having difficulty getting wood... what? Why + * are all you Amercians laughing..? Anyway, I don't know if enough + * people's hardware supports 3D textures, so I didn't bother (xorg + * ATI server doesn't :-( ) + */ +static int drawTube(GLdouble bottomRadius, GLdouble topRadius, + GLdouble bottomThickness, GLdouble topThickness, + GLdouble height, GLuint nSlice, GLuint nLoop) +{ + int polys = 0; + GLfloat y; + GLfloat *cosCache = malloc(sizeof(GLfloat) * nSlice); + GLfloat *sinCache = malloc(sizeof(GLfloat) * nSlice); + GLint slice; + GLuint loop; + GLint lastSlice = nSlice - 1; + GLfloat radius; + GLfloat innerRadius; + GLfloat maxRadius; + + if(bottomThickness > bottomRadius) { + bottomThickness = bottomRadius; + } + if(topThickness > topRadius) { + topThickness = topRadius; + } + if(bottomThickness < 0.0) { + bottomThickness = 0.0; + } + if(topThickness < 0.0) { + topThickness = 0.0; + } + if(topRadius >= bottomRadius) { + maxRadius = topRadius; + } else { + maxRadius = bottomRadius; + } + + /* bottom */ + y = 0.0; + radius = bottomRadius; + innerRadius = bottomRadius - bottomThickness; + /* innerTexCoordSize = texCoordSize * innerRadius / maxRadius; */ + /* outerTexCoordSize = texCoordSize * radius / maxRadius; */ + /* yTexCoord = minTexCoord; */ + + glBegin(GL_QUAD_STRIP); + + glNormal3f(0.0, -1.0, 0.0); + + /* glTexCoord3f(midTexCoord, yTexCoord, midTexCoord + innerTexCoordSize); */ + glVertex3f(0.0, y, innerRadius); + + /* glTexCoord3f(midTexCoord, yTexCoord, midTexCoord + outerTexCoordSize); */ + glVertex3f(0.0, y, radius); + + for(slice = lastSlice; slice >= 0; --slice) { + GLfloat theta = 2.0 * M_PI * (double)slice / nSlice; + + cosCache[slice] = cos(theta); + sinCache[slice] = sin(theta); + + /* glTexCoord3f(midTexCoord + sinCache[slice] * innerTexCoordSize, */ + /* yTexCoord, */ + /* midTexCoord + cosCache[slice] * innerTexCoordSize); */ + glVertex3f(innerRadius * sinCache[slice], y, + innerRadius * cosCache[slice]); + /* glTexCoord3f(midTexCoord + sinCache[slice] * outerTexCoordSize, */ + /* yTexCoord, */ + /* midTexCoord + cosCache[slice] * outerTexCoordSize); */ + glVertex3f(radius * sinCache[slice], y, radius * cosCache[slice]); + polys++; + } + glEnd(); + + /* middle */ + for(loop = 0; loop < nLoop; ++loop) { + GLfloat lowerRadius = + bottomRadius + (topRadius - + bottomRadius) * (float)loop / (nLoop); + GLfloat upperRadius = + bottomRadius + (topRadius - bottomRadius) * (float)(loop + + 1) / + (nLoop); + GLfloat lowerY = height * (float)loop / (nLoop); + GLfloat upperY = height * (float)(loop + 1) / (nLoop); + GLfloat factor = (topRadius - topThickness) - + (bottomRadius - bottomThickness); + + /* outside */ + glBegin(GL_QUAD_STRIP); + for(slice = 0; slice < nSlice; ++slice) { + glNormal3f(sinCache[slice], 0.0, cosCache[slice]); + glVertex3f(upperRadius * sinCache[slice], upperY, + upperRadius * cosCache[slice]); + glVertex3f(lowerRadius * sinCache[slice], lowerY, + lowerRadius * cosCache[slice]); + polys++; + } + glNormal3f(0.0, 0.0, 1.0); + glVertex3f(0.0, upperY, upperRadius); + glVertex3f(0.0, lowerY, lowerRadius); + polys++; + glEnd(); + + /* inside */ + lowerRadius = bottomRadius - bottomThickness + + factor * (float)loop / (nLoop); + upperRadius = bottomRadius - bottomThickness + + factor * (float)(loop + 1) / (nLoop); + + glBegin(GL_QUAD_STRIP); + glNormal3f(0.0, 0.0, -1.0); + glVertex3f(0.0, upperY, upperRadius); + glVertex3f(0.0, lowerY, lowerRadius); + for(slice = lastSlice; slice >= 0; --slice) { + glNormal3f(-sinCache[slice], 0.0, -cosCache[slice]); + glVertex3f(upperRadius * sinCache[slice], upperY, + upperRadius * cosCache[slice]); + glVertex3f(lowerRadius * sinCache[slice], lowerY, + lowerRadius * cosCache[slice]); + polys++; + } + glEnd(); + } + + /* top */ + y = height; + radius = topRadius; + innerRadius = topRadius - topThickness; + + glBegin(GL_QUAD_STRIP); + glNormal3f(0.0, 1.0, 0.0); + for(slice = 0; slice < nSlice; ++slice) { + glVertex3f(innerRadius * sinCache[slice], y, + innerRadius * cosCache[slice]); + + glVertex3f(radius * sinCache[slice], y, radius * cosCache[slice]); + polys++; + } + glVertex3f(0.0, y, innerRadius); + glVertex3f(0.0, y, radius); + glEnd(); + return polys; +} + +static int drawPole(GLfloat radius, GLfloat length) +{ + return drawTube(radius, radius, radius, radius, length, NSLICE, NLOOPS); +} + +static int drawDisk3D(GLdouble inner_radius, GLdouble outer_radius, + GLdouble height) +{ + return drawTube(outer_radius, outer_radius, outer_radius - inner_radius, + outer_radius - inner_radius, height, NSLICE, NLOOPS); +} + +/* used for drawing base */ +static int drawCuboid(GLfloat length, GLfloat width, GLfloat height) +{ + GLfloat xmin = -length / 2.0f; + GLfloat xmax = length / 2.0f; + GLfloat zmin = -width / 2.0f; + GLfloat zmax = width / 2.0f; + GLfloat ymin = 0.0f; + GLfloat ymax = height; + int polys = 0; + + glBegin(GL_QUADS); + /* front */ + glNormal3fv(front); + glVertex3f(xmin, ymin, zmax); /* 0 */ + glVertex3f(xmax, ymin, zmax); /* 1 */ + glVertex3f(xmax, ymax, zmax); /* 2 */ + glVertex3f(xmin, ymax, zmax); /* 3 */ + polys++; + /* right */ + glNormal3fv(right); + glVertex3f(xmax, ymin, zmax); /* 1 */ + glVertex3f(xmax, ymin, zmin); /* 5 */ + glVertex3f(xmax, ymax, zmin); /* 6 */ + glVertex3f(xmax, ymax, zmax); /* 2 */ + polys++; + /* back */ + glNormal3fv(back); + glVertex3f(xmax, ymin, zmin); /* 5 */ + glVertex3f(xmin, ymin, zmin); /* 4 */ + glVertex3f(xmin, ymax, zmin); /* 7 */ + glVertex3f(xmax, ymax, zmin); /* 6 */ + polys++; + /* left */ + glNormal3fv(left); + glVertex3f(xmin, ymin, zmin); /* 4 */ + glVertex3f(xmin, ymin, zmax); /* 0 */ + glVertex3f(xmin, ymax, zmax); /* 3 */ + glVertex3f(xmin, ymax, zmin); /* 7 */ + polys++; + /* top */ + glNormal3fv(up); + glVertex3f(xmin, ymax, zmax); /* 3 */ + glVertex3f(xmax, ymax, zmax); /* 2 */ + glVertex3f(xmax, ymax, zmin); /* 6 */ + glVertex3f(xmin, ymax, zmin); /* 7 */ + polys++; + /* bottom */ + glNormal3fv(down); + glVertex3f(xmin, ymin, zmin); /* 4 */ + glVertex3f(xmax, ymin, zmin); /* 5 */ + glVertex3f(xmax, ymin, zmax); /* 1 */ + glVertex3f(xmin, ymin, zmax); /* 0 */ + polys++; + glEnd(); + return polys; +} + +/* Set normal vector in xz plane, based on rotation around center. */ +static void setNormalV(glhcfg *glhanoi, GLfloat theta, int y1, int y2, int r1) { + if (y1 == y2) /* up/down */ + glNormal3f(0.0, y1 ? 1.0 : -1.0, 0.0); + else if (!r1) /* inward */ + glNormal3f(-cos(theta), 0.0, -sin(theta)); + else /* outward */ + glNormal3f(cos(theta), 0.0, sin(theta)); +} + +/* y1, r1, y2, r2 are indices into y, r, beg, end */ +static int drawBaseStrip(glhcfg *glhanoi, int y1, int r1, int y2, int r2, + GLfloat y[2], GLfloat r[2], GLfloat beg[2][2], GLfloat end[2][2]) { + int i; + GLfloat theta, costh, sinth, x[2], z[2]; + GLfloat theta1 = (M_PI * 2) / (glhanoi->numberOfPoles + 1); + + glBegin(GL_QUAD_STRIP); + + /* beginning edge */ + glVertex3f(beg[r1][0], y[y1], beg[r1][1]); + glVertex3f(beg[r2][0], y[y2], beg[r2][1]); + setNormalV(glhanoi, theta1, y1, y2, r1); + + for (i = 1; i < glhanoi->numberOfPoles; i++) { + theta = theta1 * (i + 0.5); + costh = cos(theta); + sinth = sin(theta); + x[0] = costh * r[0]; + x[1] = costh * r[1]; + z[0] = sinth * r[0]; + z[1] = sinth * r[1]; + + glVertex3f(x[r1], y[y1], z[r1]); + glVertex3f(x[r2], y[y2], z[r2]); + + setNormalV(glhanoi, theta1 * (i + 1), y1, y2, r1); + } + + /* end edge */ + glVertex3f(end[r1][0], y[y1], end[r1][1]); + glVertex3f(end[r2][0], y[y2], end[r2][1]); + setNormalV(glhanoi, glhanoi->numberOfPoles, y1, y2, r1); + + glEnd(); + return glhanoi->numberOfPoles; +} + +/* Draw base such that poles are distributed around a regular polygon. */ +static int drawRoundBase(glhcfg *glhanoi) { + int polys = 0; + GLfloat theta, sinth, costh; + + /* + r[0] = (minimum) inner radius of base at vertices + r[1] = (minimum) outer radius of base at vertices + y[0] = bottom of base + y[1] = top of base */ + GLfloat r[2], y[2]; + /* positions of end points: beginning, end. + beg[0] is inner corner of beginning of base, beg[1] is outer corner. + beg[i][0] is x, [i][1] is z. */ + GLfloat beg[2][2], end[2][2], begNorm, endNorm; + /* ratio of radius at base vertices to ratio at poles */ + GLfloat longer = 1.0 / cos(M_PI / (glhanoi->numberOfPoles + 1)); + + r[0] = (glhanoi->poleDist - glhanoi->maxDiskRadius) * longer; + r[1] = (glhanoi->poleDist + glhanoi->maxDiskRadius) * longer; + y[0] = 0; + y[1] = glhanoi->baseHeight; + + /* compute beg, end. Make the ends square. */ + theta = M_PI * 2 / (glhanoi->numberOfPoles + 1); + + costh = cos(theta); + sinth = sin(theta); + beg[0][0] = (glhanoi->poleDist - glhanoi->maxDiskRadius) * costh + + glhanoi->maxDiskRadius * sinth; + beg[1][0] = (glhanoi->poleDist + glhanoi->maxDiskRadius) * costh + + glhanoi->maxDiskRadius * sinth; + beg[0][1] = (glhanoi->poleDist - glhanoi->maxDiskRadius) * sinth - + glhanoi->maxDiskRadius * costh; + beg[1][1] = (glhanoi->poleDist + glhanoi->maxDiskRadius) * sinth - + glhanoi->maxDiskRadius * costh; + begNorm = theta - M_PI * 0.5; + + theta = M_PI * 2 * glhanoi->numberOfPoles / (glhanoi->numberOfPoles + 1); + + costh = cos(theta); + sinth = sin(theta); + end[0][0] = (glhanoi->poleDist - glhanoi->maxDiskRadius) * costh - + glhanoi->maxDiskRadius * sinth; + end[1][0] = (glhanoi->poleDist + glhanoi->maxDiskRadius) * costh - + glhanoi->maxDiskRadius * sinth; + end[0][1] = (glhanoi->poleDist - glhanoi->maxDiskRadius) * sinth + + glhanoi->maxDiskRadius * costh; + end[1][1] = (glhanoi->poleDist + glhanoi->maxDiskRadius) * sinth + + glhanoi->maxDiskRadius * costh; + endNorm = theta + M_PI * 0.5; + + /* bottom: never seen + polys = drawBaseStrip(glhanoi, 0, 0, 0, 1, y, r, beg, end); */ + /* outside edge */ + polys += drawBaseStrip(glhanoi, 0, 1, 1, 1, y, r, beg, end); + /* top */ + polys += drawBaseStrip(glhanoi, 1, 1, 1, 0, y, r, beg, end); + /* inside edge */ + polys += drawBaseStrip(glhanoi, 1, 0, 0, 0, y, r, beg, end); + + /* Draw ends */ + glBegin(GL_QUADS); + + glVertex3f(beg[0][0], y[1], beg[0][1]); + glVertex3f(beg[1][0], y[1], beg[1][1]); + glVertex3f(beg[1][0], y[0], beg[1][1]); + glVertex3f(beg[0][0], y[0], beg[0][1]); + glNormal3f(cos(begNorm), 0, sin(begNorm)); + + glVertex3f(end[0][0], y[0], end[0][1]); + glVertex3f(end[1][0], y[0], end[1][1]); + glVertex3f(end[1][0], y[1], end[1][1]); + glVertex3f(end[0][0], y[1], end[0][1]); + glNormal3f(cos(endNorm), 0, sin(endNorm)); + + polys += 2; + + glEnd(); + + return polys; +} + +static int drawDisks(glhcfg *glhanoi) +{ + int i; + int polys = 0; + + glPushMatrix(); + glTranslatef(0.0f, glhanoi->baseHeight, 0.0f); + for(i = glhanoi->maxDiskIdx; i >= 0; i--) { + Disk *disk = &glhanoi->disk[i]; + GLfloat *pos = disk->position; + GLfloat *rot = disk->rotation; + + glPushMatrix(); + glTranslatef(pos[0], pos[1], pos[2]); + if(rot[1] != 0.0) { + glTranslatef(0.0, glhanoi->diskHeight / 2.0, 0.0); + /* rotate around different axis depending on phi */ + if (disk->phi != 0.0) + glRotatef(-disk->phi, 0.0, 1.0, 0.0); + glRotatef(rot[1], 0.0, 0.0, 1.0); + if (disk->phi != 0.0) + glRotatef(disk->phi, 0.0, 1.0, 0.0); + glTranslatef(0.0, -glhanoi->diskHeight / 2.0, 0.0); + } + glCallList(disk->displayList); + polys += disk->polys; + glPopMatrix(); + } + glPopMatrix(); + return polys; +} + +static GLfloat getDiskRadius(glhcfg *glhanoi, int i) +{ + GLfloat retVal = glhanoi->maxDiskRadius * + ((GLfloat) i + 3.0) / (glhanoi->numberOfDisks + 3.0); + return retVal; +} + +static void initData(glhcfg *glhanoi) +{ + int i; + GLfloat sinPiOverNP; + + glhanoi->baseLength = BASE_LENGTH; + if (glhanoi->layoutLinear) { + glhanoi->maxDiskRadius = glhanoi->baseLength / + (2 * 0.95 * glhanoi->numberOfPoles); + } else { + sinPiOverNP = sin(M_PI / (glhanoi->numberOfPoles + 1)); + glhanoi->maxDiskRadius = (sinPiOverNP * glhanoi->baseLength * 0.5 * 0.95) / (1 + sinPiOverNP); + } + + glhanoi->poleDist = glhanoi->baseLength * 0.5 - glhanoi->maxDiskRadius; + glhanoi->poleRadius = glhanoi->maxDiskRadius / (glhanoi->numberOfDisks + 3.0); + /* fprintf(stderr, "Debug: baseL = %f, maxDiskR = %f, poleR = %f\n", + glhanoi->baseLength, glhanoi->maxDiskRadius, glhanoi->poleRadius); */ + glhanoi->baseWidth = 2.0 * glhanoi->maxDiskRadius; + glhanoi->poleOffset = 2.0 * getDiskRadius(glhanoi, glhanoi->maxDiskIdx); + glhanoi->diskHeight = 2.0 * glhanoi->poleRadius; + glhanoi->baseHeight = 2.0 * glhanoi->poleRadius; + glhanoi->poleHeight = glhanoi->numberOfDisks * + glhanoi->diskHeight + glhanoi->poleRadius; + /* numberOfMoves only applies if numberOfPoles = 3 */ + glhanoi->numberOfMoves = (1 << glhanoi->numberOfDisks) - 1; + /* use golden ratio */ + glhanoi->boardSize = glhanoi->baseLength * 0.5 * (1.0 + sqrt(5.0)); + + glhanoi->pole = (Pole *)calloc(glhanoi->numberOfPoles, sizeof(Pole)); + checkAllocAndExit(!!glhanoi->pole, "poles"); + + for(i = 0; i < glhanoi->numberOfPoles; i++) { + checkAllocAndExit( + !!(glhanoi->pole[i].data = calloc(glhanoi->numberOfDisks, sizeof(Disk *))), + "disk stack"); + glhanoi->pole[i].size = glhanoi->numberOfDisks; + } + checkAllocAndExit( + !!(glhanoi->diskPos = calloc(glhanoi->numberOfDisks, sizeof(double))), + "diskPos"); + + if (glhanoi->trailQSize) { + glhanoi->trailQ = (TrailPoint *)calloc(glhanoi->trailQSize, sizeof(TrailPoint)); + checkAllocAndExit(!!glhanoi->trailQ, "trail queue"); + } else glhanoi->trailQ = (TrailPoint *)NULL; + glhanoi->trailQFront = glhanoi->trailQBack = 0; + + glhanoi->the_rotator = make_rotator(0.1, 0.025, 0, 1, 0.005, False); + /* or glhanoi->the_rotator = make_rotator(0.025, 0.025, 0.025, 0.5, 0.005, False); */ + glhanoi->button_down_p = False; + + glhanoi->src = glhanoi->oldsrc = 0; + glhanoi->tmp = glhanoi->oldtmp = 1; + glhanoi->dst = glhanoi->olddst = glhanoi->numberOfPoles - 1; + + if (glhanoi->numberOfPoles > 3) { + glhanoi->solveStackSize = glhanoi->numberOfDisks + 2; + glhanoi->solveStack = (SubProblem *)calloc(glhanoi->solveStackSize, sizeof(SubProblem)); + checkAllocAndExit(!!glhanoi->solveStack, "solving stack"); + glhanoi->solveStackIdx = 0; + } +} + +static void initView(glhcfg *glhanoi) +{ + glhanoi->camera[0] = 0.0; + glhanoi->camera[1] = 0.0; + glhanoi->camera[2] = 0.0; + glhanoi->centre[0] = 0.0; + glhanoi->centre[1] = glhanoi->poleHeight * 3.0; + glhanoi->centre[2] = 0.0; +} + +/* + * noise_improved.c - based on ImprovedNoise.java + * JAVA REFERENCE IMPLEMENTATION OF IMPROVED NOISE - COPYRIGHT 2002 KEN PERLIN. + */ +static double fade(double t) +{ + return t * t * t * (t * (t * 6 - 15) + 10); +} + +static double grad(int hash, double x, double y, double z) +{ + int h = hash & 15; /* CONVERT LO 4 BITS OF HASH CODE */ + double u = h < 8 ? x : y, /* INTO 12 GRADIENT DIRECTIONS. */ + v = h < 4 ? y : h == 12 || h == 14 ? x : z; + return ((h & 1) == 0 ? u : -u) + ((h & 2) == 0 ? v : -v); +} + +static const int permutation[] = { 151, 160, 137, 91, 90, 15, + 131, 13, 201, 95, 96, 53, 194, 233, 7, 225, 140, 36, 103, 30, 69, 142, + 8, 99, 37, 240, 21, 10, 23, 190, 6, 148, 247, 120, 234, 75, 0, 26, + 197, 62, 94, 252, 219, 203, 117, 35, 11, 32, 57, 177, 33, 88, 237, + 149, 56, 87, 174, 20, 125, 136, 171, 168, 68, 175, 74, 165, 71, + 134, 139, 48, 27, 166, 77, 146, 158, 231, 83, 111, 229, 122, 60, + 211, 133, 230, 220, 105, 92, 41, 55, 46, 245, 40, 244, 102, 143, + 54, 65, 25, 63, 161, 1, 216, 80, 73, 209, 76, 132, 187, 208, 89, + 18, 169, 200, 196, 135, 130, 116, 188, 159, 86, 164, 100, 109, 198, + 173, 186, 3, 64, 52, 217, 226, 250, 124, 123, 5, 202, 38, 147, 118, + 126, 255, 82, 85, 212, 207, 206, 59, 227, 47, 16, 58, 17, 182, 189, + 28, 42, 223, 183, 170, 213, 119, 248, 152, 2, 44, 154, 163, 70, + 221, 153, 101, 155, 167, 43, 172, 9, 129, 22, 39, 253, 19, 98, 108, + 110, 79, 113, 224, 232, 178, 185, 112, 104, 218, 246, 97, 228, 251, + 34, 242, 193, 238, 210, 144, 12, 191, 179, 162, 241, 81, 51, 145, + 235, 249, 14, 239, 107, 49, 192, 214, 31, 181, 199, 106, 157, 184, + 84, 204, 176, 115, 121, 50, 45, 127, 4, 150, 254, 138, 236, 205, + 93, 222, 114, 67, 29, 24, 72, 243, 141, 128, 195, 78, 66, 215, 61, + 156, 180 +}; + +static void initNoise(glhcfg *glhanoi) +{ + int i; + for(i = 0; i < 256; i++) + glhanoi->p[256 + i] = glhanoi->p[i] = permutation[i]; +} + +static double improved_noise(glhcfg *glhanoi, double x, double y, double z) +{ + double u, v, w; + int A, AA, AB, B, BA, BB; + int X = (int)floor(x) & 255, /* FIND UNIT CUBE THAT */ + Y = (int)floor(y) & 255, /* CONTAINS POINT. */ + Z = (int)floor(z) & 255; + if(!glhanoi->noise_initted) { + initNoise(glhanoi); + glhanoi->noise_initted = 1; + } + x -= floor(x); /* FIND RELATIVE X,Y,Z */ + y -= floor(y); /* OF POINT IN CUBE. */ + z -= floor(z); + u = fade(x), /* COMPUTE FADE CURVES */ + v = fade(y), /* FOR EACH OF X,Y,Z. */ + w = fade(z); + A = glhanoi->p[X] + Y; + AA = glhanoi->p[A] + Z; + AB = glhanoi->p[A + 1] + Z, /* HASH COORDINATES OF */ + B = glhanoi->p[X + 1] + Y; + BA = glhanoi->p[B] + Z; + BB = glhanoi->p[B + 1] + Z; /* THE 8 CUBE CORNERS, */ + return lerp(w, lerp(v, lerp(u, grad(glhanoi->p[AA], x, y, z),/* AND ADD */ + grad(glhanoi->p[BA], x - 1, y, z)),/* BLENDED */ + lerp(u, grad(glhanoi->p[AB], x, y - 1, z),/* RESULTS */ + grad(glhanoi->p[BB], x - 1, y - 1, z))),/* FROM 8 CORNERS */ + lerp(v, lerp(u, grad(glhanoi->p[AA + 1], x, y, z - 1), grad(glhanoi->p[BA + 1], x - 1, y, z - 1)), /* OF CUBE */ + lerp(u, grad(glhanoi->p[AB + 1], x, y - 1, z - 1), + grad(glhanoi->p[BB + 1], x - 1, y - 1, z - 1)))); +} + +/* + * end noise_improved.c - based on ImprovedNoise.java + */ + +struct tex_col_t { + GLuint *colours; + /* GLfloat *points; */ + unsigned int ncols; +}; +typedef struct tex_col_t tex_col_t; + +static GLubyte *makeTexture(glhcfg *glhanoi, int x_size, int y_size, int z_size, + GLuint(*texFunc) (glhcfg *, double, double, double, + tex_col_t *), tex_col_t * colours) +{ + int i, j, k; + GLubyte *textureData; + GLuint *texturePtr; + double x, y, z; + double xi, yi, zi; + + if((textureData = + calloc(x_size * y_size * z_size, sizeof(GLuint))) == NULL) { + return NULL; + } + + xi = 1.0 / x_size; + yi = 1.0 / y_size; + zi = 1.0 / z_size; + + z = 0.0; + texturePtr = (void *)textureData; + for(k = 0; k < z_size; k++, z += zi) { + y = 0.0; + for(j = 0; j < y_size; j++, y += yi) { + x = 0.0; + for(i = 0; i < x_size; i++, x += xi) { + *texturePtr = texFunc(glhanoi, x, y, z, colours); + ++texturePtr; + } + } + } + return textureData; +} + +static void freeTexCols(tex_col_t*p) +{ + free(p->colours); + free(p); +} + +static tex_col_t *makeMarbleColours(void) +{ + tex_col_t *marbleColours; + int ncols = 2; + + marbleColours = malloc(sizeof(tex_col_t)); + if(marbleColours == NULL) return NULL; + marbleColours->colours = calloc(sizeof(GLuint), ncols); + if(marbleColours->colours == NULL) return NULL; + marbleColours->ncols = ncols; + + marbleColours->colours[0] = 0x3f3f3f3f; + marbleColours->colours[1] = 0xffffffff; + + return marbleColours; +} + +static double turb(glhcfg *glhanoi, double x, double y, double z, int octaves) +{ + int oct, freq = 1; + double r = 0.0; + + for(oct = 0; oct < octaves; ++oct) { + r += fabs(improved_noise(glhanoi, freq * x, freq * y, freq * z)) / freq; + freq <<= 1; + } + return r / 2.0; +} + +static void perturb(glhcfg *glhanoi, double *x, double *y, double *z, double scale) +{ + double t = scale * turb(glhanoi, *x, *y, *z, 4); + *x += t; + *y += t; + *z += t; +} + +static double f_m(double x, double y, double z) +{ + return sin(3.0 * M_PI * x); +} + +static GLuint C_m(double x, const tex_col_t * tex_cols) +{ + int r = tex_cols->colours[0] & 0xff; + int g = tex_cols->colours[0] >> 8 & 0xff; + int b = tex_cols->colours[0] >> 16 & 0xff; + double factor; + int r1, g1, b1; + x = x - floor(x); + + factor = (1.0 + sin(2.0 * M_PI * x)) / 2.0; + + r1 = (tex_cols->colours[1] & 0xff); + g1 = (tex_cols->colours[1] >> 8 & 0xff); + b1 = (tex_cols->colours[1] >> 16 & 0xff); + + r += (int)(factor * (r1 - r)); + g += (int)(factor * (g1 - g)); + b += (int)(factor * (b1 - b)); + + return 0xff000000 | (b << 16) | (g << 8) | r; +} + + +static GLuint makeMarbleTexture(glhcfg *glhanoi, double x, double y, double z, tex_col_t * colours) +{ + perturb(glhanoi, &x, &y, &z, MARBLE_SCALE); + return C_m(f_m(x, y, z), colours); +} + +static void setTexture(glhcfg *glhanoi, int n) +{ + glBindTexture(GL_TEXTURE_2D, glhanoi->textureNames[n]); +} + +/* returns 1 on failure, 0 on success */ +static int makeTextures(glhcfg *glhanoi) +{ + GLubyte *marbleTexture; + tex_col_t *marbleColours; + + glGenTextures(N_TEXTURES, glhanoi->textureNames); + + if((marbleColours = makeMarbleColours()) == NULL) { + return 1; + } + if((marbleTexture = + makeTexture(glhanoi, MARBLE_TEXTURE_SIZE, MARBLE_TEXTURE_SIZE, 1, + makeMarbleTexture, marbleColours)) == NULL) { + return 1; + } + + glBindTexture(GL_TEXTURE_2D, glhanoi->textureNames[0]); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, + MARBLE_TEXTURE_SIZE, MARBLE_TEXTURE_SIZE, 0, + GL_RGBA, GL_UNSIGNED_BYTE, marbleTexture); + free(marbleTexture); + freeTexCols(marbleColours); + + return 0; +} + +static void initFloor(glhcfg *glhanoi) +{ + int i, j; + float tileSize = glhanoi->boardSize / BOARD_SQUARES; + float x0, x1, z0, z1; + float tx0, tx1, tz0, tz1; + const float *col = cWhite; + float texIncr = 1.0 / BOARD_SQUARES; + + glhanoi->floorpolys = 0; + checkAllocAndExit(!!(glhanoi->floorList = glGenLists(1)), "floor display list"); + glNewList(glhanoi->floorList, GL_COMPILE); + x0 = -glhanoi->boardSize / 2.0; + tx0 = 0.0f; + setMaterial(col, cWhite, 128); + setTexture(glhanoi, 0); + glNormal3fv(up); + for(i = 0; i < BOARD_SQUARES; i++, x0 += tileSize, tx0 += texIncr) { + x1 = x0 + tileSize; + tx1 = tx0 + texIncr; + z0 = -glhanoi->boardSize / 2.0; + tz0 = 0.0f; + for(j = 0; j < BOARD_SQUARES; j++, z0 += tileSize, tz0 += texIncr) { + int colIndex = (i + j) & 0x1; + + z1 = z0 + tileSize; + tz1 = tz0 + texIncr; + + if(colIndex) + col = cWhite; + else + col = cBlack; + + setMaterial(col, cWhite, 100); + + glBegin(GL_QUADS); + + glTexCoord2d(tx0, tz0); + glVertex3f(x0, 0.0, z0); + + glTexCoord2d(tx0, tz1); + glVertex3f(x0, 0.0, z1); + + glTexCoord2d(tx1, tz1); + glVertex3f(x1, 0.0, z1); + + glTexCoord2d(tx1, tz0); + glVertex3f(x1, 0.0, z0); + glhanoi->floorpolys++; + glEnd(); + } + } + glEndList(); +} + +static void initBase(glhcfg *glhanoi) +{ + checkAllocAndExit(!!(glhanoi->baseList = glGenLists(1)), "tower bases display list"); + + glNewList(glhanoi->baseList, GL_COMPILE); + setMaterial(baseColor, cWhite, 50); + if (glhanoi->layoutLinear) { + glhanoi->basepolys = drawCuboid(glhanoi->baseLength, glhanoi->baseWidth, + glhanoi->baseHeight); + } else { + glhanoi->basepolys = drawRoundBase(glhanoi); + } + glEndList(); +} + +static void initTowers(glhcfg *glhanoi) +{ + int i; + + checkAllocAndExit(!!(glhanoi->poleList = glGenLists(1)), "poles display list\n"); + + glNewList(glhanoi->poleList, GL_COMPILE); + /* glTranslatef(-glhanoi->poleOffset * (glhanoi->numberOfPoles - 1.0f) * 0.5f, glhanoi->baseHeight, 0.0f); */ + setMaterial(poleColor, cWhite, 50); + for (i = 0; i < glhanoi->numberOfPoles; i++) { + GLfloat *p = glhanoi->pole[i].position; + GLfloat rad = (M_PI * 2.0 * (i + 1)) / (glhanoi->numberOfPoles + 1); + + p[1] = glhanoi->baseHeight; + + if (glhanoi->layoutLinear) { + /* Linear: */ + p[0] = -glhanoi->poleOffset * ((glhanoi->numberOfPoles - 1) * 0.5f - i); + p[2] = 0.0f; + } else { + /* Circular layout: */ + p[0] = cos(rad) * glhanoi->poleDist; + p[2] = sin(rad) * glhanoi->poleDist; + } + + glPushMatrix(); + glTranslatef(p[0], p[1], p[2]); + glhanoi->polepolys = drawPole(glhanoi->poleRadius, glhanoi->poleHeight); + glPopMatrix(); + + } + glEndList(); +} + +/* Parameterized hue based on input 0.0 - 1.0. */ +static double cfunc(double x) +{ +#define COMP < + if(x < 2.0 / 7.0) { + return (1.0 / 12.0) / (1.0 / 7.0) * x; + } + if(x < 3.0 / 7.0) { + /* (7x - 1) / 6 */ + return (1.0 + 1.0 / 6.0) * x - 1.0 / 6.0; + } + if(x < 4.0 / 7.0) { + return (2.0 + 1.0 / 3.0) * x - 2.0 / 3.0; + } + if(x < 5.0 / 7.0) { + return (1.0 / 12.0) / (1.0 / 7.0) * x + 1.0 / 3.0; + } + return (1.0 / 12.0) / (1.0 / 7.0) * x + 1.0 / 3.0; +} + +static void initDisks(glhcfg *glhanoi) +{ + int i; + glhanoi->disk = (Disk *) calloc(glhanoi->numberOfDisks, sizeof(Disk)); + checkAllocAndExit(!!glhanoi->disk, "disks"); + + for(i = glhanoi->maxDiskIdx; i >= 0; i--) { + GLfloat height = (GLfloat) (glhanoi->maxDiskIdx - i); + double f = cfunc((GLfloat) i / (GLfloat) glhanoi->numberOfDisks); + GLfloat diskColor = f * 360.0; + GLfloat color[3]; + Disk *disk = &glhanoi->disk[i]; + + disk->id = i; + disk->position[0] = glhanoi->pole[0].position[0]; /* -glhanoi->poleOffset * (glhanoi->numberOfPoles - 1.0f) * 0.5; */ + disk->position[1] = glhanoi->diskHeight * height; + disk->position[2] = glhanoi->pole[0].position[2]; + disk->rotation[0] = 0.0; + disk->rotation[1] = 0.0; + disk->rotation[2] = 0.0; + disk->polys = 0; + + /* make smaller disks move faster */ + disk->speed = lerp(((double)glhanoi->numberOfDisks - i) / glhanoi->numberOfDisks, + 1.0, glhanoi->speed); + /* fprintf(stderr, "disk id: %d, alpha: %0.2f, speed: %0.2f\n", disk->id, + ((double)(glhanoi->maxDiskIdx - i)) / glhanoi->numberOfDisks, disk->speed); */ + + color[0] = diskColor; + color[1] = 1.0f; + color[2] = 1.0f; + HSVtoRGBv(color, color); + + checkAllocAndExit(!!(disk->displayList = glGenLists(1)), "disk display list"); + glNewList(disk->displayList, GL_COMPILE); + setMaterial(color, cWhite, 100.0); + disk->polys += drawDisk3D(glhanoi->poleRadius, + getDiskRadius(glhanoi, i), + glhanoi->diskHeight); + /*fprintf(stderr, "Debug: disk %d has radius %f\n", i, + getDiskRadius(glhanoi, i)); */ + glEndList(); + } + for(i = glhanoi->maxDiskIdx; i >= 0; --i) { + GLfloat height = (GLfloat) (glhanoi->maxDiskIdx - i); + int h = glhanoi->maxDiskIdx - i; + glhanoi->diskPos[h] = glhanoi->diskHeight * height; + push(glhanoi, glhanoi->src, &glhanoi->disk[i]); + } +} + +static void initLights(Bool state) +{ + if(state) { + glLightfv(GL_LIGHT0, GL_POSITION, pos0); + glLightfv(GL_LIGHT0, GL_AMBIENT, amb0); + glLightfv(GL_LIGHT0, GL_DIFFUSE, dif0); + glLightfv(GL_LIGHT0, GL_SPECULAR, spc0); + + glLightfv(GL_LIGHT1, GL_POSITION, pos1); + glLightfv(GL_LIGHT1, GL_AMBIENT, amb1); + glLightfv(GL_LIGHT1, GL_DIFFUSE, dif1); + glLightfv(GL_LIGHT1, GL_SPECULAR, spc1); + + glEnable(GL_LIGHTING); + glEnable(GL_LIGHT0); + glEnable(GL_LIGHT1); + } else { + glDisable(GL_LIGHTING); + } +} + +static int drawFloor(glhcfg *glhanoi) +{ + glCallList(glhanoi->floorList); + return glhanoi->floorpolys; +} + +static int drawTowers(glhcfg *glhanoi) +{ + glCallList(glhanoi->baseList); + glCallList(glhanoi->poleList); + return glhanoi->basepolys + glhanoi->polepolys; +} + +static int drawTrails1(glhcfg *glhanoi, double t, double thickness, double alpha) { + int i, prev = -1, lines = 0; + Bool fresh = False; + GLfloat trailDurInv = 1.0f / glhanoi->trailDuration; + + glLineWidth(thickness); + + glBegin(GL_LINES); + + for (i = glhanoi->trailQFront; + i != glhanoi->trailQBack; + i = normalizeQ(i + 1)) { + TrailPoint *tqi = &(glhanoi->trailQ[i]); + + if (!fresh && t > tqi->endTime) { + glhanoi->trailQFront = normalizeQ(i + 1); + } else { + if (tqi->startTime > t) break; + /* Found trails that haven't timed out. */ + if (!fresh) fresh = True; + if (prev > -1) { + /* Fade to invisible with age */ + trailColor[3] = alpha * (tqi->endTime - t) * trailDurInv; + /* Can't use setMaterial(trailColor, cBlack, 0) because our color needs an alpha value. */ + glColor4fv(trailColor); + glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, trailColor); + /* FUTURE: to really do this right, trails should be drawn in back-to-front + order, so that blending is done correctly. + Currently it looks poor when a faded trail is in front of, or coincident with, + a bright trail but is drawn first. + I think for now it's good enough to recommend shorter trails so they + never/rarely overlap. + A jitter per trail arc would also mitigate this problem, to a lesser degree. */ + glVertex3fv(glhanoi->trailQ[prev].position); + glVertex3fv(glhanoi->trailQ[i].position); + lines++; + } + if (glhanoi->trailQ[i].isEnd) + prev = -1; + else + prev = i; + } + } + + glEnd(); + + return lines; +} + +static int drawTrails(glhcfg *glhanoi) { + int lines = 0; + double t = getTime(); + + glEnable (GL_BLEND); + glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + glMaterialfv(GL_FRONT, GL_SPECULAR, cBlack); + glMateriali(GL_FRONT, GL_SHININESS, 0); + + /* Draw them twice, with different widths and opacities, to make them smoother. */ + lines = drawTrails1(glhanoi, t, 1.0, 0.75); + lines += drawTrails1(glhanoi, t, 2.5, 0.5); + + glDisable (GL_BLEND); + + /* fprintf(stderr, "Drew trails: %d lines\n", lines); */ + return lines; +} + +/* Window management, etc + */ +ENTRYPOINT void reshape_glhanoi(ModeInfo * mi, int width, int height) +{ + glViewport(0, 0, (GLint) width, (GLint) height); + + glMatrixMode(GL_PROJECTION); + glLoadIdentity(); + gluPerspective(30.0, (GLdouble) width / (GLdouble) height, 1.0, + 2 * MAX_CAMERA_RADIUS); + + glMatrixMode(GL_MODELVIEW); + glLoadIdentity(); + + glClear(GL_COLOR_BUFFER_BIT); +} + +ENTRYPOINT void init_glhanoi(ModeInfo * mi) +{ + glhcfg *glhanoi; + if(!glhanoi_cfg) { + glhanoi_cfg = + (glhcfg *) calloc(MI_NUM_SCREENS(mi), sizeof(glhcfg)); + checkAllocAndExit(!!glhanoi_cfg, "configuration"); + } + + glhanoi = &glhanoi_cfg[MI_SCREEN(mi)]; + glhanoi->glx_context = init_GL(mi); + glhanoi->numberOfDisks = MI_BATCHCOUNT(mi); + + if (glhanoi->numberOfDisks <= 1) + glhanoi->numberOfDisks = 3 + (int) BELLRAND(9); + + /* magicnumber is a bitfield, so we can't have more than 31 discs + on a system with 4-byte ints. */ + if (glhanoi->numberOfDisks >= 8 * sizeof(int)) + glhanoi->numberOfDisks = (8 * sizeof(int)) - 1; + + glhanoi->maxDiskIdx = glhanoi->numberOfDisks - 1; + + glhanoi->numberOfPoles = get_integer_resource(MI_DISPLAY(mi), "poles", "Integer"); + /* Set a number of poles from 3 to numberOfDisks + 1, biased toward lower values, + with probability decreasing linearly. */ + if (glhanoi->numberOfPoles <= 2) + glhanoi->numberOfPoles = 3 + + (int)((1 - sqrt(frand(1.0))) * (glhanoi->numberOfDisks - 1)); + + glhanoi->wire = MI_IS_WIREFRAME(mi); + +# ifdef HAVE_JWZGLES /* #### glPolygonMode other than GL_FILL unimplemented */ + glhanoi->wire = 0; +# endif + + glhanoi->light = light; + glhanoi->fog = fog; + glhanoi->texture = texture; + glhanoi->speed = speed; + glhanoi->trailDuration = trails; + /* set trailQSize based on 60 fps (a maximum, more or less) */ + /* FUTURE: Should clamp framerate to 60 fps? See flurry.c's draw_flurry(). + The only bad effect if we don't is that trail-ends could + show "unnatural" pauses at high fps. */ + glhanoi->trailQSize = (int)(trails * 60.0); + + reshape_glhanoi(mi, MI_WIDTH(mi), MI_HEIGHT(mi)); + + if(glhanoi->wire) { + glhanoi->light = False; + glhanoi->fog = False; + glhanoi->texture = False; + } + + initLights(!glhanoi->wire && glhanoi->light); + checkAllocAndExit(!makeTextures(glhanoi), "textures\n"); + + /* Choose linear or circular layout. Could make this a user option. */ + glhanoi->layoutLinear = (glhanoi->numberOfPoles == 3); + + initData(glhanoi); + initView(glhanoi); + initFloor(glhanoi); + initBase(glhanoi); + initTowers(glhanoi); + initDisks(glhanoi); + + glEnable(GL_DEPTH_TEST); + glEnable(GL_NORMALIZE); + glEnable(GL_CULL_FACE); + glShadeModel(GL_SMOOTH); + if(glhanoi->fog) { + glClearColor(fogcolor[0], fogcolor[1], fogcolor[2], 1.0); + glFogi(GL_FOG_MODE, GL_LINEAR); + glFogfv(GL_FOG_COLOR, fogcolor); + glFogf(GL_FOG_DENSITY, 0.35f); + glHint(GL_FOG_HINT, GL_NICEST); + glFogf(GL_FOG_START, MIN_CAMERA_RADIUS); + glFogf(GL_FOG_END, MAX_CAMERA_RADIUS / 1.9); + glEnable(GL_FOG); + } + + glhanoi->duration = START_DURATION; + changeState(glhanoi, START); +} + +ENTRYPOINT void draw_glhanoi(ModeInfo * mi) +{ + glhcfg *glhanoi = &glhanoi_cfg[MI_SCREEN(mi)]; + Display *dpy = MI_DISPLAY(mi); + Window window = MI_WINDOW(mi); + + if(!glhanoi->glx_context) + return; + + glXMakeCurrent(MI_DISPLAY(mi), MI_WINDOW(mi), *(glhanoi->glx_context)); + + glPolygonMode(GL_FRONT, glhanoi->wire ? GL_LINE : GL_FILL); + + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + mi->polygon_count = 0; + + glLoadIdentity(); + glRotatef(current_device_rotation(), 0, 0, 1); + + update_glhanoi(glhanoi); + updateView(glhanoi); + + if(!glhanoi->wire && glhanoi->texture) { + glEnable(GL_TEXTURE_2D); + } + mi->polygon_count += drawFloor(glhanoi); + glDisable(GL_TEXTURE_2D); + + mi->polygon_count += drawTowers(glhanoi); + mi->polygon_count += drawDisks(glhanoi); + + if (glhanoi->trailQSize) { + /* No polygons, just lines. So ignore the return count. */ + (void)drawTrails(glhanoi); + } + + if(mi->fps_p) { + do_fps(mi); + } + glFinish(); + + glXSwapBuffers(dpy, window); +} + +ENTRYPOINT Bool glhanoi_handle_event(ModeInfo * mi, XEvent * event) +{ + glhcfg *glhanoi = &glhanoi_cfg[MI_SCREEN(mi)]; + + if(event->xany.type == ButtonPress && event->xbutton.button == Button1) { + glhanoi->button_down_p = True; + glhanoi->drag_x = event->xbutton.x; + glhanoi->drag_y = event->xbutton.y; + return True; + } else if(event->xany.type == ButtonRelease + && event->xbutton.button == Button1) { + glhanoi->button_down_p = False; + return True; + } else if(event->xany.type == ButtonPress && + (event->xbutton.button == Button4 + || event->xbutton.button == Button5)) { + switch (event->xbutton.button) { + case Button4: + glhanoi->camera[2] += 0.01; + break; + case Button5: + glhanoi->camera[2] -= 0.01; + break; + default: + fprintf(stderr, + "glhanoi: unknown button in mousewheel handler\n"); + } + return True; + } else if(event->xany.type == MotionNotify + && glhanoi_cfg->button_down_p) { + int x_diff, y_diff; + + x_diff = event->xbutton.x - glhanoi->drag_x; + y_diff = event->xbutton.y - glhanoi->drag_y; + + glhanoi->camera[0] = (float)x_diff / (float)MI_WIDTH(mi); + glhanoi->camera[1] = (float)y_diff / (float)MI_HEIGHT(mi); + + return True; + } + return False; +} + +ENTRYPOINT void release_glhanoi(ModeInfo * mi) +{ + if(glhanoi_cfg != NULL) { + int screen; + for(screen = 0; screen < MI_NUM_SCREENS(mi); screen++) { + int i; + int j; + glhcfg *glh = &glhanoi_cfg[screen]; + glDeleteLists(glh->floorList, 1); + glDeleteLists(glh->baseList, 1); + glDeleteLists(glh->poleList, 1); + glDeleteLists(glh->textureNames[0], 2); + for(j = 0; j < glh->numberOfDisks; ++j) { + glDeleteLists(glh->disk[j].displayList, 1); + } + free(glh->disk); + for(i = 0; i < glh->numberOfPoles; i++) { + if(glh->pole[i].data != NULL) { + free(glh->pole[i].data); + } + } + } + } + free(glhanoi_cfg); + glhanoi_cfg = NULL; +} + +XSCREENSAVER_MODULE ("GLHanoi", glhanoi) + +#endif /* USE_GL */ diff --git a/hacks/glx/glhanoi.man b/hacks/glx/glhanoi.man new file mode 100644 index 00000000..2060cde9 --- /dev/null +++ b/hacks/glx/glhanoi.man @@ -0,0 +1,83 @@ +.TH XScreenSaver 1 "" "X Version 11" +.SH NAME +glhanoi - OpenGL Towers of Hanoi +.SH SYNOPSIS +.B glhanoi +[\-display \fIhost:display.screen\fP] +[\-visual \fIvisual\fP] +[\-window] +[\-root] +[\-delay \fInumber\fP] +[\-count \fInumber\fP] +[\-poles \fInumber\fP] +[\-speed \fInumber\fP] +[\-wireframe] +[\-light] +[\-texture] +[\-fog] +[\-fps] +.SH DESCRIPTION +Implementation of Towers of Hanoi in OpenGL +.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 \-count \fInumber\fP +Number of disks. Default: 7. +.TP 8 +.B \-poles \fInumber\fP +Number of poles. Default: random from 3 to disks+1. +.TP 8 +.B \-speed \fInumber\fP +Speed multiplier (for smallest disks). Default: 1. +.TP 8 +.B \-trails \fInumber\fP +Length of disk trails, in seconds. Default: 2. +.TP 8 +.B \-wireframe | \-no-wireframe +Render in wireframe instead of solid. +.TP 8 +.B \-fog | \-no-fog +Render in fog. +.TP 8 +.B \-fps +Display the current frame rate, CPU load, and polygon count. +.TP 8 +.B \-light | -no-light +Whether the scene is lit. +.TP 8 +.B \-texture | \-no-texture +Render with textures instead of solid. +.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 2004 by Dave Atkinson. 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 +Dave Atkinson. diff --git a/hacks/glx/glknots.c b/hacks/glx/glknots.c new file mode 100644 index 00000000..6bf5ccd9 --- /dev/null +++ b/hacks/glx/glknots.c @@ -0,0 +1,463 @@ +/* glknots, Copyright (c) 2003-2008 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. + * + * Generates some 3D knots (closed loops). + * Inspired by Paul Bourke at + * http://astronomy.swin.edu.au/~pbourke/curves/knot/ + */ + +#define DEFAULTS "*delay: 30000 \n" \ + "*showFPS: False \n" \ + "*wireframe: False \n" \ + +# define refresh_knot 0 +# define release_knot 0 +#undef countof +#define countof(x) (sizeof((x))/sizeof((*x))) + +#include "xlockmore.h" +#include "colors.h" +#include "tube.h" +#include "rotator.h" +#include "gltrackball.h" +#include + +#ifdef USE_GL /* whole file */ + +#define DEF_SPIN "XYZ" +#define DEF_WANDER "True" +#define DEF_SPEED "1.0" +#define DEF_THICKNESS "0.3" +#define DEF_SEGMENTS "800" +#define DEF_DURATION "8" + +typedef struct { + GLXContext *glx_context; + rotator *rot; + trackball_state *trackball; + Bool button_down_p; + + GLuint knot_list; + + int ncolors; + XColor *colors; + int ccolor; + + int mode; /* 0 = normal, 1 = out, 2 = in */ + int mode_tick; + Bool clear_p; + + time_t last_time; + int draw_tick; + +} knot_configuration; + +static knot_configuration *bps = NULL; + +static char *do_spin; +static GLfloat speed; +static Bool do_wander; +static GLfloat thickness; +static unsigned int segments; +static int duration; + +static XrmOptionDescRec opts[] = { + { "-spin", ".spin", XrmoptionSepArg, 0 }, + { "+spin", ".spin", XrmoptionNoArg, "" }, + { "-wander", ".wander", XrmoptionNoArg, "True" }, + { "+wander", ".wander", XrmoptionNoArg, "False" }, + { "-speed", ".speed", XrmoptionSepArg, 0 }, + { "-thickness", ".thickness", XrmoptionSepArg, 0 }, + { "-segments", ".segments", XrmoptionSepArg, 0 }, + { "-duration", ".duration", XrmoptionSepArg, 0 }, +}; + +static argtype vars[] = { + {&do_spin, "spin", "Spin", DEF_SPIN, t_String}, + {&do_wander, "wander", "Wander", DEF_WANDER, t_Bool}, + {&speed, "speed", "Speed", DEF_SPEED, t_Float}, + {&thickness, "thickness", "Thickness", DEF_THICKNESS, t_Float}, + {&segments, "segments", "Segments", DEF_SEGMENTS, t_Int}, + {&duration, "duration", "Duration", DEF_DURATION, t_Int}, +}; + +ENTRYPOINT ModeSpecOpt knot_opts = {countof(opts), opts, countof(vars), vars, NULL}; + + +static void +make_knot (ModeInfo *mi) +{ + int wire = MI_IS_WIREFRAME(mi); + + GLfloat diam = (4 * thickness); + int faces = (wire ? 3 : 6); + + unsigned int i; + double x, y, z, ox=0, oy=0, oz=0; + double mu; + + double p[9]; + + Bool blobby_p = (0 == (random() % 5)); + Bool type = (random() % 2); + + for (i = 0; i < countof(p); i++) + { + p[i] = 1 + (random() % 4); + if (! (random() % 3)) + p[i] += (random() % 5); + } + + if (type == 1) + { + p[0] += 4; + p[1] *= ((p[0] + p[0]) / 10); + blobby_p = False; + } + + mi->polygon_count = 0; + + for (i = 0; i <= segments; i++) + { + if (type == 0) + { + mu = i * (M_PI * 2) / segments; + x = 10 * (cos(mu) + cos(p[0]*mu)) + cos(p[1]*mu) + cos(p[2]*mu); + y = 6 * sin(mu) + 10 * sin(p[3]*mu); + z = 16 * sin(p[4]*mu) * sin(p[5]*mu/2) + p[6]*sin(p[7]*mu) - + 2 * sin(p[8]*mu); + } + else if (type == 1) + { + mu = i * (M_PI * 2) * p[0] / (double) segments; + x = 10 * cos(mu) * (1 + cos(p[1] * mu/ p[0]) / 2.0); + y = 25 * sin(p[1] * mu / p[0]) / 2.0; + z = 10 * sin(mu) * (1 + cos(p[1] * mu/ p[0]) / 2.0); + } + else + abort(); + + if (i != 0) + { + GLfloat dist = sqrt ((x-ox)*(x-ox) + + (y-oy)*(y-oy) + + (z-oz)*(z-oz)); + GLfloat di; + if (!blobby_p) + di = diam; + else + { + di = dist * (segments / 500.0); + di = (di * di * 3); + } + + mi->polygon_count += tube (ox, oy, oz, + x, y, z, + di, dist/3, + faces, True, wire, wire); + } + + ox = x; + oy = y; + oz = z; + } +} + + +/* Window management, etc + */ +ENTRYPOINT void +reshape_knot (ModeInfo *mi, int width, int height) +{ + GLfloat h = (GLfloat) height / (GLfloat) width; + + glViewport (0, 0, (GLint) width, (GLint) height); + + glMatrixMode(GL_PROJECTION); + glLoadIdentity(); + gluPerspective (30.0, 1/h, 1.0, 100.0); + + glMatrixMode(GL_MODELVIEW); + glLoadIdentity(); + gluLookAt( 0.0, 0.0, 30.0, + 0.0, 0.0, 0.0, + 0.0, 1.0, 0.0); + + glClear(GL_COLOR_BUFFER_BIT); +} + + +static void +new_knot (ModeInfo *mi) +{ + knot_configuration *bp = &bps[MI_SCREEN(mi)]; + int i; + + bp->clear_p = !!(random() % 15); + + bp->ncolors = 128; + bp->colors = (XColor *) calloc(bp->ncolors, sizeof(XColor)); + make_smooth_colormap (0, 0, 0, + bp->colors, &bp->ncolors, + False, 0, False); + + for (i = 0; i < bp->ncolors; i++) + { + /* make colors twice as bright */ + bp->colors[i].red = (bp->colors[i].red >> 2) + 0x7FFF; + bp->colors[i].green = (bp->colors[i].green >> 2) + 0x7FFF; + bp->colors[i].blue = (bp->colors[i].blue >> 2) + 0x7FFF; + } + + glNewList (bp->knot_list, GL_COMPILE); + make_knot (mi); + glEndList (); +} + + +ENTRYPOINT Bool +knot_handle_event (ModeInfo *mi, XEvent *event) +{ + knot_configuration *bp = &bps[MI_SCREEN(mi)]; + + if (event->xany.type == ButtonPress && + event->xbutton.button == Button1) + { + bp->button_down_p = True; + gltrackball_start (bp->trackball, + event->xbutton.x, event->xbutton.y, + MI_WIDTH (mi), MI_HEIGHT (mi)); + return True; + } + else if (event->xany.type == ButtonRelease && + event->xbutton.button == Button1) + { + bp->button_down_p = False; + return True; + } + else if (event->xany.type == ButtonPress && + (event->xbutton.button == Button4 || + event->xbutton.button == Button5 || + event->xbutton.button == Button6 || + event->xbutton.button == Button7)) + { + gltrackball_mousewheel (bp->trackball, event->xbutton.button, 5, + !!event->xbutton.state); + return True; + } + else if (event->xany.type == MotionNotify && + bp->button_down_p) + { + gltrackball_track (bp->trackball, + event->xmotion.x, event->xmotion.y, + MI_WIDTH (mi), MI_HEIGHT (mi)); + return True; + } + + return False; +} + + + +ENTRYPOINT void +init_knot (ModeInfo *mi) +{ + knot_configuration *bp; + int wire = MI_IS_WIREFRAME(mi); + + if (!bps) { + bps = (knot_configuration *) + calloc (MI_NUM_SCREENS(mi), sizeof (knot_configuration)); + if (!bps) { + fprintf(stderr, "%s: out of memory\n", progname); + exit(1); + } + } + + bp = &bps[MI_SCREEN(mi)]; + + bp->glx_context = init_GL(mi); + + if (thickness <= 0) thickness = 0.001; + else if (thickness > 1) thickness = 1; + + if (segments < 10) segments = 10; + + reshape_knot (mi, MI_WIDTH(mi), MI_HEIGHT(mi)); + + if (!wire) + { + GLfloat pos[4] = {1.0, 1.0, 1.0, 0.0}; + GLfloat amb[4] = {0.0, 0.0, 0.0, 1.0}; + GLfloat dif[4] = {1.0, 1.0, 1.0, 1.0}; + GLfloat spc[4] = {0.0, 1.0, 1.0, 1.0}; + + glEnable(GL_LIGHTING); + glEnable(GL_LIGHT0); + glEnable(GL_DEPTH_TEST); + glEnable(GL_CULL_FACE); + + glLightfv(GL_LIGHT0, GL_POSITION, pos); + glLightfv(GL_LIGHT0, GL_AMBIENT, amb); + glLightfv(GL_LIGHT0, GL_DIFFUSE, dif); + glLightfv(GL_LIGHT0, GL_SPECULAR, spc); + } + + { + Bool spinx=False, spiny=False, spinz=False; + double spin_speed = 2.0; + double wander_speed = 0.05; + double spin_accel = 0.2; + + char *s = do_spin; + while (*s) + { + if (*s == 'x' || *s == 'X') spinx = True; + else if (*s == 'y' || *s == 'Y') spiny = True; + else if (*s == 'z' || *s == 'Z') spinz = True; + else if (*s == '0') ; + else + { + fprintf (stderr, + "%s: spin must contain only the characters X, Y, or Z (not \"%s\")\n", + progname, do_spin); + exit (1); + } + s++; + } + + bp->rot = make_rotator (spinx ? spin_speed : 0, + spiny ? spin_speed : 0, + spinz ? spin_speed : 0, + spin_accel, + do_wander ? wander_speed : 0, + (spinx && spiny && spinz)); + bp->trackball = gltrackball_init (); + } + + bp->knot_list = glGenLists (1); + new_knot(mi); + + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); +} + + +ENTRYPOINT void +draw_knot (ModeInfo *mi) +{ + knot_configuration *bp = &bps[MI_SCREEN(mi)]; + Display *dpy = MI_DISPLAY(mi); + Window window = MI_WINDOW(mi); + + 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; + + if (!bp->glx_context) + return; + + glXMakeCurrent(MI_DISPLAY(mi), MI_WINDOW(mi), *(bp->glx_context)); + + if (bp->mode == 0) + { + if (bp->draw_tick++ > 10) + { + time_t now = time((time_t *) 0); + if (bp->last_time == 0) bp->last_time = now; + bp->draw_tick = 0; + if (!bp->button_down_p && + now - bp->last_time >= duration) + { + bp->mode = 1; /* go out */ + bp->mode_tick = 10 * speed; + bp->last_time = now; + } + } + } + else if (bp->mode == 1) /* out */ + { + if (--bp->mode_tick <= 0) + { + new_knot (mi); + bp->mode_tick = 10 * speed; + bp->mode = 2; /* go in */ + } + } + else if (bp->mode == 2) /* in */ + { + if (--bp->mode_tick <= 0) + bp->mode = 0; /* normal */ + } + else + abort(); + + glShadeModel(GL_SMOOTH); + + glEnable(GL_DEPTH_TEST); + glEnable(GL_NORMALIZE); + glEnable(GL_CULL_FACE); + + if (bp->clear_p) + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + + glPushMatrix (); + + { + double x, y, z; + get_position (bp->rot, &x, &y, &z, !bp->button_down_p); + glTranslatef((x - 0.5) * 8, + (y - 0.5) * 8, + (z - 0.5) * 15); + + /* Do it twice because we don't track the device's orientation. */ + glRotatef( current_device_rotation(), 0, 0, 1); + gltrackball_rotate (bp->trackball); + glRotatef(-current_device_rotation(), 0, 0, 1); + + get_rotation (bp->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); + } + + bcolor[0] = bp->colors[bp->ccolor].red / 65536.0; + bcolor[1] = bp->colors[bp->ccolor].green / 65536.0; + bcolor[2] = bp->colors[bp->ccolor].blue / 65536.0; + bp->ccolor++; + if (bp->ccolor >= bp->ncolors) bp->ccolor = 0; + + glMaterialfv (GL_FRONT, GL_SPECULAR, bspec); + glMateriali (GL_FRONT, GL_SHININESS, bshiny); + glMaterialfv (GL_FRONT, GL_AMBIENT_AND_DIFFUSE, bcolor); + + glScalef(0.25, 0.25, 0.25); + + if (bp->mode != 0) + { + GLfloat s = (bp->mode == 1 + ? bp->mode_tick / (10 * speed) + : ((10 * speed) - bp->mode_tick + 1) / (10 * speed)); + glScalef (s, s, s); + } + + glCallList (bp->knot_list); + + glPopMatrix (); + + if (mi->fps_p) do_fps (mi); + glFinish(); + + glXSwapBuffers(dpy, window); +} + +XSCREENSAVER_MODULE_2 ("GLKnots", glknots, knot) + +#endif /* USE_GL */ diff --git a/hacks/glx/glknots.man b/hacks/glx/glknots.man new file mode 100644 index 00000000..c4f1d1ae --- /dev/null +++ b/hacks/glx/glknots.man @@ -0,0 +1,81 @@ +.TH XScreenSaver 1 "" "X Version 11" +.SH NAME +glknots - generates some twisting 3d knot patterns +.SH SYNOPSIS +.B glknots +[\-display \fIhost:display.screen\fP] +[\-visual \fIvisual\fP] +[\-window] +[\-root] +[\-delay \fInumber\fP] +[\-speed \fIfloat\fP] +[\-segments \fIint\fP] +[\-thickness \fIfloat\fP] +[\-duration \fIseconds\fP] +[\-no-wander] +[\-spin \fIXYZ\fP] +[\-wireframe] +[\-fps] +.SH DESCRIPTION +Generates some twisting 3d knot patterns. Spins 'em around. +.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 \-speed \fInumber\fP +Larger numbers mean run faster. Default: 1.0. +.TP 8 +.B \-segments \fInumber\fP +Number of segments in each path. Default 800. Larger numbers make the +curves smoother, at the expense of a higher polygon count. +.TP 8 +.B \-thickness \fIfloat\fP +How thick the tubes should be. Default 0.3. +.TP 8 +.B \-duration \fIseconds\fP +How long to leave each knot up. Default 8 seconds. +.TP 8 +.B \-wander | \-no-wander +Whether the cubes should wander around the screen. +.TP 8 +.B \-spin [XYZ] | \-no-spin +Which axes, if any, to spin around on. +.TP 8 +.B \-wireframe | \-no-wireframe +Render in wireframe instead of solid. +.TP 8 +.B \-fps +Display the current frame rate, CPU load, and polygon count. +.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 2003 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/glx/gllist.c b/hacks/glx/gllist.c new file mode 100644 index 00000000..d404d6be --- /dev/null +++ b/hacks/glx/gllist.c @@ -0,0 +1,9 @@ +#include "gllist.h" + +void renderList(const struct gllist *list, int wire_p){ + for(;list!=NULL;list=list->next){ + glInterleavedArrays(list->format,0,list->data); + glDrawArrays((wire_p ? GL_LINE_LOOP : list->primitive), + 0,list->points); + } +} diff --git a/hacks/glx/gllist.h b/hacks/glx/gllist.h new file mode 100644 index 00000000..dacc89c4 --- /dev/null +++ b/hacks/glx/gllist.h @@ -0,0 +1,28 @@ +#ifndef __GLLIST_H__ +#define __GLLIST_H__ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif /* HAVE_CONFIG_H */ + +#include + +#ifndef HAVE_COCOA +# include +#endif + +#ifdef HAVE_JWZGLES +# include "jwzgles.h" +#endif /* HAVE_JWZGLES */ + +struct gllist{ + GLenum format; + GLenum primitive; + int points; + const void *data; + struct gllist *next; +}; + +void renderList(const struct gllist *list, int wire_p); + +#endif diff --git a/hacks/glx/glmatrix.c b/hacks/glx/glmatrix.c new file mode 100644 index 00000000..1975182b --- /dev/null +++ b/hacks/glx/glmatrix.c @@ -0,0 +1,1069 @@ +/* glmatrix, Copyright (c) 2003, 2004 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. + * + * GLMatrix -- simulate the text scrolls from the movie "The Matrix". + * + * This program does a 3D rendering of the dropping characters that + * appeared in the title sequences of the movies. See also `xmatrix' + * for a simulation of what the computer monitors actually *in* the + * movie did. + */ + +#define DEFAULTS "*delay: 30000 \n" \ + "*showFPS: False \n" \ + "*wireframe: False \n" \ + +# define refresh_matrix 0 +# define release_matrix 0 +#undef countof +#define countof(x) (sizeof((x))/sizeof((*x))) + +#undef BELLRAND +#define BELLRAND(n) ((frand((n)) + frand((n)) + frand((n))) / 3) + +#include "xlockmore.h" +#include "xpm-ximage.h" + +#ifdef __GNUC__ + __extension__ /* don't warn about "string length is greater than the length + ISO C89 compilers are required to support" when including + the following XPM file... */ +#endif +#include "../images/matrix3.xpm" + +#ifdef USE_GL /* whole file */ + + +#define DEF_SPEED "1.0" +#define DEF_DENSITY "20" +#define DEF_CLOCK "False" +#define DEF_FOG "True" +#define DEF_WAVES "True" +#define DEF_ROTATE "True" +#define DEF_TEXTURE "True" +#define DEF_MODE "Matrix" +#define DEF_TIMEFMT " %l%M%p " + + +#define CHAR_COLS 16 +#define CHAR_ROWS 13 + +static const int matrix_encoding[] = { + 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, +# if 0 + 192, 193, 194, 195, 196, 197, 198, 199, + 200, 201, 202, 203, 204, 205, 206, 207 +# else + 160, 161, 162, 163, 164, 165, 166, 167, + 168, 169, 170, 171, 172, 173, 174, 175 +# endif + }; +static const int decimal_encoding[] = { + 16, 17, 18, 19, 20, 21, 22, 23, 24, 25 }; +static const int hex_encoding[] = { + 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 33, 34, 35, 36, 37, 38 }; +static const int binary_encoding[] = { 16, 17 }; +static const int dna_encoding[] = { 33, 35, 39, 52 }; + +static const unsigned char char_map[256] = { + 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, /* 0 */ + 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, /* 16 */ + 0, 1, 2, 96, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, /* 32 */ + 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, /* 48 */ + 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, /* 64 */ + 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, /* 80 */ + 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, /* 96 */ + 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, /* 112 */ + 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, /* 128 */ + 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, /* 144 */ + 96, 97, 98, 99,100,101,102,103,104,105,106,107,108,109,110,111, /* 160 */ + 112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127, /* 176 */ + 128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143, /* 192 */ + 144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159, /* 208 */ +#if 0 + 160,161,162,163,164,165,166,167,168,169,170,171,172,173,174,175, /* 224 */ + 176,177,178,195,180,181,182,183,184,185,186,187,188,189,190,191 /* 240 */ +#else /* see spank_image() */ + 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, /* 224 */ + 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, /* 240 */ +#endif +}; + +#define CURSOR_GLYPH 97 + +/* #define DEBUG */ + +#define GRID_SIZE 70 /* width and height of the arena */ +#define GRID_DEPTH 35 /* depth of the arena */ +#define WAVE_SIZE 22 /* periodicity of color (brightness) waves */ +#define SPLASH_RATIO 0.7 /* ratio of GRID_DEPTH where chars hit the screen */ + +static const struct { GLfloat x, y; } nice_views[] = { + { 0, 0 }, + { 0, -20 }, /* this is a list of viewer rotations that look nice. */ + { 0, 20 }, /* every now and then we switch to a new one. */ + { 25, 0 }, /* (but we only use the first one at start-up.) */ + {-25, 0 }, + { 25, 20 }, + {-25, 20 }, + { 25, -20 }, + {-25, -20 }, + + { 10, 0 }, + {-10, 0 }, + { 0, 0 }, /* prefer these */ + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, +}; + + +typedef struct { + GLfloat x, y, z; /* position of strip */ + GLfloat dx, dy, dz; /* velocity of strip */ + + Bool erasing_p; /* Whether this strip is on its way out. */ + + int spinner_glyph; /* the bottommost glyph -- the feeder */ + GLfloat spinner_y; /* where on the strip the bottom glyph is */ + GLfloat spinner_speed; /* how fast the bottom glyph drops */ + + int glyphs[GRID_SIZE]; /* the other glyphs on the strip, which will be + revealed by the dropping spinner. + 0 means no glyph; negative means "spinner". + If non-zero, real value is abs(G)-1. */ + + Bool highlight[GRID_SIZE]; + /* some glyphs may be highlighted */ + + int spin_speed; /* Rotate all spinners every this-many frames */ + int spin_tick; /* frame counter */ + + int wave_position; /* Waves of brightness wash down the strip. */ + int wave_speed; /* every this-many frames. */ + int wave_tick; /* frame counter. */ + +} strip; + + +typedef struct { + GLXContext *glx_context; + Bool button_down_p; + GLuint texture; + int nstrips; + strip *strips; + const int *glyph_map; + int nglyphs; + GLfloat tex_char_width, tex_char_height; + + /* auto-tracking direction of view */ + int last_view, target_view; + GLfloat view_x, view_y; + int view_steps, view_tick; + Bool auto_tracking_p; + int track_tick; + + int real_char_rows; + GLfloat brightness_ramp[WAVE_SIZE]; + +} matrix_configuration; + +static matrix_configuration *mps = NULL; + +static GLfloat speed; +static GLfloat density; +static Bool do_clock; +static char *timefmt; +static Bool do_fog; +static Bool do_waves; +static Bool do_rotate; +static Bool do_texture; +static char *mode_str; + +static XrmOptionDescRec opts[] = { + { "-speed", ".speed", XrmoptionSepArg, 0 }, + { "-density", ".density", XrmoptionSepArg, 0 }, + { "-mode", ".mode", XrmoptionSepArg, 0 }, + { "-binary", ".mode", XrmoptionNoArg, "binary" }, + { "-hexadecimal", ".mode", XrmoptionNoArg, "hexadecimal" }, + { "-decimal", ".mode", XrmoptionNoArg, "decimal" }, + { "-dna", ".mode", XrmoptionNoArg, "dna" }, + { "-clock", ".clock", XrmoptionNoArg, "True" }, + { "+clock", ".clock", XrmoptionNoArg, "False" }, + { "-timefmt", ".timefmt", XrmoptionSepArg, 0 }, + { "-fog", ".fog", XrmoptionNoArg, "True" }, + { "+fog", ".fog", XrmoptionNoArg, "False" }, + { "-waves", ".waves", XrmoptionNoArg, "True" }, + { "+waves", ".waves", XrmoptionNoArg, "False" }, + { "-rotate", ".rotate", XrmoptionNoArg, "True" }, + { "+rotate", ".rotate", XrmoptionNoArg, "False" }, + {"-texture", ".texture", XrmoptionNoArg, "True" }, + {"+texture", ".texture", XrmoptionNoArg, "False" }, +}; + +static argtype vars[] = { + {&mode_str, "mode", "Mode", DEF_MODE, t_String}, + {&speed, "speed", "Speed", DEF_SPEED, t_Float}, + {&density, "density", "Density", DEF_DENSITY, t_Float}, + {&do_clock, "clock", "Clock", DEF_CLOCK, t_Bool}, + {&timefmt, "timefmt", "Timefmt", DEF_TIMEFMT, t_String}, + {&do_fog, "fog", "Fog", DEF_FOG, t_Bool}, + {&do_waves, "waves", "Waves", DEF_WAVES, t_Bool}, + {&do_rotate, "rotate", "Rotate", DEF_ROTATE, t_Bool}, + {&do_texture, "texture", "Texture", DEF_TEXTURE, t_Bool}, +}; + +ENTRYPOINT ModeSpecOpt matrix_opts = {countof(opts), opts, countof(vars), vars, NULL}; + + +/* Re-randomize the state of one strip. + */ +static void +reset_strip (ModeInfo *mi, strip *s) +{ + matrix_configuration *mp = &mps[MI_SCREEN(mi)]; + int i; + Bool time_displayed_p = False; /* never display time twice in one strip */ + + memset (s, 0, sizeof(*s)); + s->x = (GLfloat) (frand(GRID_SIZE) - (GRID_SIZE/2)); + s->y = (GLfloat) (GRID_SIZE/2 + BELLRAND(0.5)); /* shift top slightly */ + s->z = (GLfloat) (GRID_DEPTH * 0.2) - frand (GRID_DEPTH * 0.7); + s->spinner_y = 0; + + s->dx = 0; +/* s->dx = ((BELLRAND(0.01) - 0.005) * speed); */ + s->dy = 0; + s->dz = (BELLRAND(0.02) * speed); + + s->spinner_speed = (BELLRAND(0.3) * speed); + + s->spin_speed = (int) BELLRAND(2.0 / speed) + 1; + s->spin_tick = 0; + + s->wave_position = 0; + s->wave_speed = (int) BELLRAND(3.0 / speed) + 1; + s->wave_tick = 0; + + for (i = 0; i < GRID_SIZE; i++) + if (do_clock && + !time_displayed_p && + (i < GRID_SIZE-5) && /* display approx. once per 5 strips */ + !(random() % (GRID_SIZE-5)*5)) + { + int j; + char text[80]; + time_t now = time ((time_t *) 0); + struct tm *tm = localtime (&now); + strftime (text, sizeof(text)-1, timefmt, tm); + + /* render time into the strip */ + for (j = 0; j < strlen(text) && i < GRID_SIZE; j++, i++) + { + s->glyphs[i] = char_map [((unsigned char *) text)[j]] + 1; + s->highlight[i] = True; + } + + time_displayed_p = True; + } + else + { + int draw_p = (random() % 7); + int spin_p = (draw_p && !(random() % 20)); + int g = (draw_p + ? mp->glyph_map[(random() % mp->nglyphs)] + 1 + : 0); + if (spin_p) g = -g; + s->glyphs[i] = g; + s->highlight[i] = False; + } + + s->spinner_glyph = - (mp->glyph_map[(random() % mp->nglyphs)] + 1); +} + + +/* Animate the strip one step. Reset if it has reached the bottom. + */ +static void +tick_strip (ModeInfo *mi, strip *s) +{ + matrix_configuration *mp = &mps[MI_SCREEN(mi)]; + int i; + + if (mp->button_down_p) + return; + + s->x += s->dx; + s->y += s->dy; + s->z += s->dz; + + if (s->z > GRID_DEPTH * SPLASH_RATIO) /* splashed into screen */ + { + reset_strip (mi, s); + return; + } + + s->spinner_y += s->spinner_speed; + if (s->spinner_y >= GRID_SIZE) + { + if (s->erasing_p) + { + reset_strip (mi, s); + return; + } + else + { + s->erasing_p = True; + s->spinner_y = 0; + s->spinner_speed /= 2; /* erase it slower than we drew it */ + } + } + + /* Spin the spinners. */ + s->spin_tick++; + if (s->spin_tick > s->spin_speed) + { + s->spin_tick = 0; + s->spinner_glyph = - (mp->glyph_map[(random() % mp->nglyphs)] + 1); + for (i = 0; i < GRID_SIZE; i++) + if (s->glyphs[i] < 0) + { + s->glyphs[i] = -(mp->glyph_map[(random() % mp->nglyphs)] + 1); + if (! (random() % 800)) /* sometimes they stop spinning */ + s->glyphs[i] = -s->glyphs[i]; + } + } + + /* Move the color (brightness) wave. */ + s->wave_tick++; + if (s->wave_tick > s->wave_speed) + { + s->wave_tick = 0; + s->wave_position++; + if (s->wave_position >= WAVE_SIZE) + s->wave_position = 0; + } +} + + +/* Draw a single character at the given position and brightness. + */ +static void +draw_glyph (ModeInfo *mi, int glyph, Bool highlight, + GLfloat x, GLfloat y, GLfloat z, + GLfloat brightness) +{ + matrix_configuration *mp = &mps[MI_SCREEN(mi)]; + int wire = MI_IS_WIREFRAME(mi); + GLfloat w = mp->tex_char_width; + GLfloat h = mp->tex_char_height; + GLfloat cx = 0, cy = 0; + GLfloat S = 1; + Bool spinner_p = (glyph < 0); + + if (glyph == 0) abort(); + if (glyph < 0) glyph = -glyph; + + if (spinner_p) + brightness *= 1.5; + + if (!do_texture) + { + S = 0.8; + x += 0.1; + y += 0.1; + } + else + { + int ccx = ((glyph - 1) % CHAR_COLS); + int ccy = ((glyph - 1) / CHAR_COLS); + + cx = ccx * w; + cy = (mp->real_char_rows - ccy - 1) * h; + + if (do_fog) + { + GLfloat depth; + depth = (z / GRID_DEPTH) + 0.5; /* z ratio from back/front */ + depth = 0.2 + (depth * 0.8); /* scale to range [0.2 - 1.0] */ + brightness *= depth; /* so no row goes all black. */ + } + } + + { + GLfloat r, g, b, a; + + if (highlight) + brightness *= 2; + + if (!do_texture && !spinner_p) + r = b = 0, g = 1; + else + r = g = b = 1; + + a = brightness; + + /* If the glyph is very close to the screen (meaning it is very large, + and is about to splash into the screen and vanish) then start fading + it out, proportional to how close to the glass it is. + */ + if (z > GRID_DEPTH/2) + { + GLfloat ratio = ((z - GRID_DEPTH/2) / + ((GRID_DEPTH * SPLASH_RATIO) - GRID_DEPTH/2)); + int i = ratio * WAVE_SIZE; + + if (i < 0) i = 0; + else if (i >= WAVE_SIZE) i = WAVE_SIZE-1; + + a *= mp->brightness_ramp[i]; + } + + glColor4f (r,g,b,a); + } + + glBegin (wire ? GL_LINE_LOOP : GL_QUADS); + glNormal3f (0, 0, 1); + glTexCoord2f (cx, cy); glVertex3f (x, y, z); + glTexCoord2f (cx+w, cy); glVertex3f (x+S, y, z); + glTexCoord2f (cx+w, cy+h); glVertex3f (x+S, y+S, z); + glTexCoord2f (cx, cy+h); glVertex3f (x, y+S, z); + glEnd (); + + if (wire && spinner_p) + { + glBegin (GL_LINES); + glVertex3f (x, y, z); + glVertex3f (x+S, y+S, z); + glVertex3f (x, y+S, z); + glVertex3f (x+S, y, z); + glEnd(); + } + + mi->polygon_count++; +} + + +/* Draw all the visible glyphs in the strip. + */ +static void +draw_strip (ModeInfo *mi, strip *s) +{ + matrix_configuration *mp = &mps[MI_SCREEN(mi)]; + int i; + for (i = 0; i < GRID_SIZE; i++) + { + int g = s->glyphs[i]; + Bool below_p = (s->spinner_y >= i); + + if (s->erasing_p) + below_p = !below_p; + + if (g && below_p) /* don't draw cells below the spinner */ + { + GLfloat brightness; + if (!do_waves) + brightness = 1.0; + else + { + int j = WAVE_SIZE - ((i + (GRID_SIZE - s->wave_position)) + % WAVE_SIZE); + brightness = mp->brightness_ramp[j]; + } + + draw_glyph (mi, g, s->highlight[i], + s->x, s->y - i, s->z, brightness); + } + } + + if (!s->erasing_p) + draw_glyph (mi, s->spinner_glyph, False, + s->x, s->y - s->spinner_y, s->z, 1.0); +} + + +/* qsort comparator for sorting strips by z position */ +static int +cmp_strips (const void *aa, const void *bb) +{ + const strip *a = *(strip **) aa; + const strip *b = *(strip **) bb; + return ((int) (a->z * 10000) - + (int) (b->z * 10000)); +} + + +/* Auto-tracking + */ + +static void +auto_track_init (ModeInfo *mi) +{ + matrix_configuration *mp = &mps[MI_SCREEN(mi)]; + mp->last_view = 0; + mp->target_view = 0; + mp->view_x = nice_views[mp->last_view].x; + mp->view_y = nice_views[mp->last_view].y; + mp->view_steps = 100; + mp->view_tick = 0; + mp->auto_tracking_p = False; +} + + +static void +auto_track (ModeInfo *mi) +{ + matrix_configuration *mp = &mps[MI_SCREEN(mi)]; + + if (! do_rotate) + return; + if (mp->button_down_p) + return; + + /* if we're not moving, maybe start moving. Otherwise, do nothing. */ + if (! mp->auto_tracking_p) + { + if (++mp->track_tick < 20/speed) return; + mp->track_tick = 0; + if (! (random() % 20)) + mp->auto_tracking_p = True; + else + return; + } + + + { + GLfloat ox = nice_views[mp->last_view].x; + GLfloat oy = nice_views[mp->last_view].y; + GLfloat tx = nice_views[mp->target_view].x; + GLfloat ty = nice_views[mp->target_view].y; + + /* move from A to B with sinusoidal deltas, so that it doesn't jerk + to a stop. */ + GLfloat th = sin ((M_PI / 2) * (double) mp->view_tick / mp->view_steps); + + mp->view_x = (ox + ((tx - ox) * th)); + mp->view_y = (oy + ((ty - oy) * th)); + mp->view_tick++; + + if (mp->view_tick >= mp->view_steps) + { + mp->view_tick = 0; + mp->view_steps = (350.0 / speed); + mp->last_view = mp->target_view; + mp->target_view = (random() % (countof(nice_views) - 1)) + 1; + mp->auto_tracking_p = False; + } + } +} + + +/* Window management, etc + */ +ENTRYPOINT void +reshape_matrix (ModeInfo *mi, int width, int height) +{ + GLfloat h = (GLfloat) height / (GLfloat) width; + + glViewport (0, 0, (GLint) width, (GLint) height); + + glMatrixMode(GL_PROJECTION); + glLoadIdentity(); + gluPerspective (80.0, 1/h, 1.0, 100); + + glMatrixMode(GL_MODELVIEW); + glLoadIdentity(); + gluLookAt( 0.0, 0.0, 25.0, + 0.0, 0.0, 0.0, + 0.0, 1.0, 0.0); + + glClear(GL_COLOR_BUFFER_BIT); +} + + +ENTRYPOINT Bool +matrix_handle_event (ModeInfo *mi, XEvent *event) +{ + matrix_configuration *mp = &mps[MI_SCREEN(mi)]; + + if (event->xany.type == ButtonPress && + event->xbutton.button == Button1) + { + mp->button_down_p = True; + return True; + } + else if (event->xany.type == ButtonRelease && + event->xbutton.button == Button1) + { + mp->button_down_p = False; + return True; + } + + return False; +} + + +#if 0 +static Bool +bigendian (void) +{ + union { int i; char c[sizeof(int)]; } u; + u.i = 1; + return !u.c[0]; +} +#endif + + +/* The image with the characters in it is 512x598, meaning that it needs to + be copied into a 512x1024 texture. But some machines can't handle textures + that large... And it turns out that we aren't using most of the characters + in that image anyway, since this program doesn't do anything that makes use + of the full range of Latin1 characters. So... this function tosses out the + last 32 of the Latin1 characters, resulting in a 512x506 image, which we + can then stuff in a 512x512 texture. Voila. + + If this hack ever grows into something that displays full Latin1 text, + well then, Something Else Will Need To Be Done. + */ +static void +spank_image (matrix_configuration *mp, XImage *xi) +{ + int ch = xi->height / CHAR_ROWS; + int cut = 2; + unsigned char *bits = (unsigned char *) xi->data; + unsigned char *from, *to, *s, *end; + int L = xi->bytes_per_line * ch; +/* int i;*/ + + /* Copy row 12 into 10 (which really means, copy 2 into 0, + since texture data is upside down.). + */ + to = bits + (L * cut); + from = bits; + end = from + L; + s = from; + while (s < end) + *to++ = *s++; + + /* Then, pull all the bits down by 2 rows. + */ + to = bits; + from = bits + (L * cut); + end = bits + (L * CHAR_ROWS); + s = from; + while (s < end) + *to++ = *s++; + + /* And clear out the rest, for good measure. + */ + from = bits + (L * (CHAR_ROWS - cut)); + end = bits + (L * CHAR_ROWS); + s = from; + while (s < end) + *s++ = 0; + + xi->height -= (cut * ch); + mp->real_char_rows -= cut; + +# if 0 + /* Finally, pull the map indexes back to match the new bits. + */ + for (i = 0; i < countof(matrix_encoding); i++) + if (matrix_encoding[i] > (CHAR_COLS * (CHAR_ROWS - cut))) + matrix_encoding[i] -= (cut * CHAR_COLS); +# endif +} + + +static void +load_textures (ModeInfo *mi, Bool flip_p) +{ + matrix_configuration *mp = &mps[MI_SCREEN(mi)]; + XImage *xi; + int x, y; + int cw, ch; + int orig_w, orig_h; + + /* The Matrix XPM is 512x598 -- but GL texture sizes must be powers of 2. + So we waste some padding rows to round up. + */ + xi = xpm_to_ximage (mi->dpy, mi->xgwa.visual, mi->xgwa.colormap, + matrix3_xpm); + orig_w = xi->width; + orig_h = xi->height; + mp->real_char_rows = CHAR_ROWS; + spank_image (mp, xi); + + if (xi->height != 512 && xi->height != 1024) + { + xi->height = (xi->height < 512 ? 512 : 1024); + xi->data = realloc (xi->data, xi->height * xi->bytes_per_line); + if (!xi->data) + { + fprintf(stderr, "%s: out of memory\n", progname); + exit(1); + } + } + + if (xi->width != 512) abort(); + if (xi->height != 512 && xi->height != 1024) abort(); + + /* char size in pixels */ + cw = orig_w / CHAR_COLS; + ch = orig_h / CHAR_ROWS; + + /* char size in ratio of final (padded) texture size */ + mp->tex_char_width = (GLfloat) cw / xi->width; + mp->tex_char_height = (GLfloat) ch / xi->height; + + /* Flip each character's bits horizontally -- we could also just do this + by reversing the texture coordinates on the quads, but on some systems + that slows things down a lot. + */ + if (flip_p) + { + int xx, col; + unsigned long buf[100]; + for (y = 0; y < xi->height; y++) + for (col = 0, xx = 0; col < CHAR_COLS; col++, xx += cw) + { + for (x = 0; x < cw; x++) + buf[x] = XGetPixel (xi, xx+x, y); + for (x = 0; x < cw; x++) + XPutPixel (xi, xx+x, y, buf[cw-x-1]); + } + } + + /* The pixmap is a color image with no transparency. Set the texture's + alpha to be the green channel, and set the green channel to be 100%. + */ + { + int rpos, gpos, bpos, apos; /* bitfield positions */ +#if 0 + /* #### Cherub says that the little-endian case must be taken on MacOSX, + or else the colors/alpha are the wrong way around. How can + that be the case? + */ + if (bigendian()) + rpos = 24, gpos = 16, bpos = 8, apos = 0; + else +#endif + rpos = 0, gpos = 8, bpos = 16, apos = 24; + + for (y = 0; y < xi->height; y++) + for (x = 0; x < xi->width; x++) + { + unsigned long p = XGetPixel (xi, x, y); + unsigned char r = (p >> rpos) & 0xFF; + unsigned char g = (p >> gpos) & 0xFF; + unsigned char b = (p >> bpos) & 0xFF; + unsigned char a = g; + g = 0xFF; + p = (r << rpos) | (g << gpos) | (b << bpos) | (a << apos); + XPutPixel (xi, x, y, p); + } + } + + /* Now load the texture into GL. + */ + clear_gl_error(); + glGenTextures (1, &mp->texture); + + glPixelStorei (GL_UNPACK_ALIGNMENT, 4); + /* messes up -fps */ + /* glPixelStorei (GL_UNPACK_ROW_LENGTH, xi->width);*/ + glBindTexture (GL_TEXTURE_2D, mp->texture); + check_gl_error ("texture init"); + glTexImage2D (GL_TEXTURE_2D, 0, GL_RGBA, xi->width, xi->height, 0, GL_RGBA, + GL_UNSIGNED_INT_8_8_8_8_REV, xi->data); + { + char buf[255]; + sprintf (buf, "creating %dx%d texture:", xi->width, xi->height); + check_gl_error (buf); + } + + glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + + /* I'd expect CLAMP to be the thing to do here, but oddly, we get a + faint solid green border around the texture if it is *not* REPEAT! + */ + glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); + glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); + + glTexEnvi (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); + glPixelStorei (GL_UNPACK_ALIGNMENT, 1); + check_gl_error ("texture param"); + + XDestroyImage (xi); +} + + +ENTRYPOINT void +init_matrix (ModeInfo *mi) +{ + matrix_configuration *mp; + int wire = MI_IS_WIREFRAME(mi); + Bool flip_p = 0; + int i; + + if (wire) + do_texture = False; + + if (!mps) { + mps = (matrix_configuration *) + calloc (MI_NUM_SCREENS(mi), sizeof (matrix_configuration)); + if (!mps) { + fprintf(stderr, "%s: out of memory\n", progname); + exit(1); + } + } + + mp = &mps[MI_SCREEN(mi)]; + mp->glx_context = init_GL(mi); + + if (!mode_str || !*mode_str || !strcasecmp(mode_str, "matrix")) + { + flip_p = 1; + mp->glyph_map = matrix_encoding; + mp->nglyphs = countof(matrix_encoding); + } + else if (!strcasecmp (mode_str, "dna")) + { + flip_p = 0; + mp->glyph_map = dna_encoding; + mp->nglyphs = countof(dna_encoding); + } + else if (!strcasecmp (mode_str, "bin") || + !strcasecmp (mode_str, "binary")) + { + flip_p = 0; + mp->glyph_map = binary_encoding; + mp->nglyphs = countof(binary_encoding); + } + else if (!strcasecmp (mode_str, "hex") || + !strcasecmp (mode_str, "hexadecimal")) + { + flip_p = 0; + mp->glyph_map = hex_encoding; + mp->nglyphs = countof(hex_encoding); + } + else if (!strcasecmp (mode_str, "dec") || + !strcasecmp (mode_str, "decimal")) + { + flip_p = 0; + mp->glyph_map = decimal_encoding; + mp->nglyphs = countof(decimal_encoding); + } + else + { + fprintf (stderr, + "%s: `mode' must be matrix, dna, binary, or hex: not `%s'\n", + progname, mode_str); + exit (1); + } + + reshape_matrix (mi, MI_WIDTH(mi), MI_HEIGHT(mi)); + + glShadeModel(GL_SMOOTH); + + glDisable(GL_DEPTH_TEST); + glDisable(GL_CULL_FACE); + glEnable(GL_NORMALIZE); + + if (do_texture) + load_textures (mi, flip_p); + + /* to scale coverage-percent to strips, this number looks about right... */ + mp->nstrips = (int) (density * 2.2); + if (mp->nstrips < 1) mp->nstrips = 1; + else if (mp->nstrips > 2000) mp->nstrips = 2000; + + + mp->strips = calloc (mp->nstrips, sizeof(strip)); + for (i = 0; i < mp->nstrips; i++) + { + strip *s = &mp->strips[i]; + reset_strip (mi, s); + + /* If we start all strips from zero at once, then the first few seconds + of the animation are much denser than normal. So instead, set all + the initial strips to erase-mode with random starting positions. + As these die off at random speeds and are re-created, we'll get a + more consistent density. */ + s->erasing_p = True; + s->spinner_y = frand(GRID_SIZE); + memset (s->glyphs, 0, sizeof(s->glyphs)); /* no visible glyphs */ + } + + /* Compute the brightness ramp. + */ + for (i = 0; i < WAVE_SIZE; i++) + { + GLfloat j = ((WAVE_SIZE - i) / (GLfloat) (WAVE_SIZE - 1)); + j *= (M_PI / 2); /* j ranges from 0.0 - PI/2 */ + j = sin (j); /* j ranges from 0.0 - 1.0 */ + j = 0.2 + (j * 0.8); /* j ranges from 0.2 - 1.0 */ + mp->brightness_ramp[i] = j; + /* printf("%2d %8.2f\n", i, j); */ + } + + + auto_track_init (mi); +} + + +#ifdef DEBUG + +static void +draw_grid (ModeInfo *mi) +{ + if (!MI_IS_WIREFRAME(mi)) + { + glDisable(GL_TEXTURE_2D); + glDisable(GL_BLEND); + } + glPushMatrix(); + + glColor3f(1, 1, 1); + glBegin(GL_LINES); + glVertex3f(-GRID_SIZE, 0, 0); glVertex3f(GRID_SIZE, 0, 0); + glVertex3f(0, -GRID_SIZE, 0); glVertex3f(0, GRID_SIZE, 0); + glEnd(); + glBegin(GL_LINE_LOOP); + glVertex3f(-GRID_SIZE/2, -GRID_SIZE/2, 0); + glVertex3f(-GRID_SIZE/2, GRID_SIZE/2, 0); + glVertex3f( GRID_SIZE/2, GRID_SIZE/2, 0); + glVertex3f( GRID_SIZE/2, -GRID_SIZE/2, 0); + glEnd(); + glBegin(GL_LINE_LOOP); + glVertex3f(-GRID_SIZE/2, GRID_SIZE/2, -GRID_DEPTH/2); + glVertex3f(-GRID_SIZE/2, GRID_SIZE/2, GRID_DEPTH/2); + glVertex3f( GRID_SIZE/2, GRID_SIZE/2, GRID_DEPTH/2); + glVertex3f( GRID_SIZE/2, GRID_SIZE/2, -GRID_DEPTH/2); + glEnd(); + glBegin(GL_LINE_LOOP); + glVertex3f(-GRID_SIZE/2, -GRID_SIZE/2, -GRID_DEPTH/2); + glVertex3f(-GRID_SIZE/2, -GRID_SIZE/2, GRID_DEPTH/2); + glVertex3f( GRID_SIZE/2, -GRID_SIZE/2, GRID_DEPTH/2); + glVertex3f( GRID_SIZE/2, -GRID_SIZE/2, -GRID_DEPTH/2); + glEnd(); + glBegin(GL_LINES); + glVertex3f(-GRID_SIZE/2, -GRID_SIZE/2, -GRID_DEPTH/2); + glVertex3f(-GRID_SIZE/2, GRID_SIZE/2, -GRID_DEPTH/2); + glVertex3f(-GRID_SIZE/2, -GRID_SIZE/2, GRID_DEPTH/2); + glVertex3f(-GRID_SIZE/2, GRID_SIZE/2, GRID_DEPTH/2); + glVertex3f( GRID_SIZE/2, -GRID_SIZE/2, -GRID_DEPTH/2); + glVertex3f( GRID_SIZE/2, GRID_SIZE/2, -GRID_DEPTH/2); + glVertex3f( GRID_SIZE/2, -GRID_SIZE/2, GRID_DEPTH/2); + glVertex3f( GRID_SIZE/2, GRID_SIZE/2, GRID_DEPTH/2); + glEnd(); + glPopMatrix(); + if (!MI_IS_WIREFRAME(mi)) + { + glEnable(GL_TEXTURE_2D); + glEnable(GL_BLEND); + } +} +#endif /* DEBUG */ + + +ENTRYPOINT void +draw_matrix (ModeInfo *mi) +{ + matrix_configuration *mp = &mps[MI_SCREEN(mi)]; + Display *dpy = MI_DISPLAY(mi); + Window window = MI_WINDOW(mi); + int i; + + if (!mp->glx_context) + return; + + glXMakeCurrent(MI_DISPLAY(mi), MI_WINDOW(mi), *(mp->glx_context)); + + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + + glPushMatrix (); + glRotatef(current_device_rotation(), 0, 0, 1); + + if (do_texture) + { + glEnable(GL_TEXTURE_2D); + glEnable(GL_BLEND); + + /* Jeff Epler points out: + By using GL_ONE instead of GL_SRC_ONE_MINUS_ALPHA, glyphs are + added to each other, so that a bright glyph with a darker one + in front is a little brighter than the bright glyph alone. + */ + glBlendFunc (GL_SRC_ALPHA, GL_ONE); + } + + if (do_rotate) + { + glRotatef (mp->view_x, 1, 0, 0); + glRotatef (mp->view_y, 0, 1, 0); + } + +#ifdef DEBUG +# if 0 + glScalef(0.5, 0.5, 0.5); +# endif +# if 0 + glRotatef(-30, 0, 1, 0); +# endif + draw_grid (mi); +#endif + + mi->polygon_count = 0; + + /* Render (and tick) each strip, starting at the back + (draw the ones farthest from the camera first, to make + the alpha transparency work out right.) + */ + { + strip **sorted = malloc (mp->nstrips * sizeof(*sorted)); + for (i = 0; i < mp->nstrips; i++) + sorted[i] = &mp->strips[i]; + qsort (sorted, i, sizeof(*sorted), cmp_strips); + + for (i = 0; i < mp->nstrips; i++) + { + strip *s = sorted[i]; + tick_strip (mi, s); + draw_strip (mi, s); + } + free (sorted); + } + + auto_track (mi); + +#if 0 + glBegin(GL_QUADS); + glColor3f(1,1,1); + glTexCoord2f (0,0); glVertex3f(-15,-15,0); + glTexCoord2f (0,1); glVertex3f(-15,15,0); + glTexCoord2f (1,1); glVertex3f(15,15,0); + glTexCoord2f (1,0); glVertex3f(15,-15,0); + glEnd(); +#endif + + glPopMatrix (); + + if (mi->fps_p) do_fps (mi); + glFinish(); + + glXSwapBuffers(dpy, window); +} + +XSCREENSAVER_MODULE_2 ("GLMatrix", glmatrix, matrix) + +#endif /* USE_GL */ diff --git a/hacks/glx/glmatrix.man b/hacks/glx/glmatrix.man new file mode 100644 index 00000000..92902907 --- /dev/null +++ b/hacks/glx/glmatrix.man @@ -0,0 +1,116 @@ +.TH XScreenSaver 1 "30-Oct-99" "X Version 11" +.SH NAME +glmatrix - simulates the title sequence effect of the movie +.SH SYNOPSIS +.B glmatrix +[\-display \fIhost:display.screen\fP] [\-window] [\-root] [\-install] +[\-visual \fIvisual\fP] +[\-delay \fIusecs\fP] +[\-speed \fIratio\fP] +[\-density \fIpct\fP] +[\-no\-fog] +[\-no\-waves] +[\-no\-rotate] +[\-binary] +[\-hexadecimal] +[\-dna] +[\-clock] +[\-timefmt \fIfmt\fP] +[\-wireframe] +[\-fps] +.SH DESCRIPTION +The \fIglmatrix\fP program draws the 3D "digital rain" effect, as seen +in the title sequence of the Wachowski brothers' film, "The Matrix". + +Also see +.BR xmatrix (MANSUFFIX) +for a 2D rendering of the similar effect that appeared on the +computer monitors actually \fIin\fP the movie. +.SH OPTIONS +.I glmatrix +accepts the following options: +.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 \-install +Install a private colormap for the window. +.TP 8 +.B \-visual \fIvisual\fP\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 \-delay \fIusecs\fP +The delay between frames of the animation, in microseconds: default 30000. +.TP 8 +.B \-speed \fIratio\fP +How fast the glyphs should move; default 1.0. 2.0 means twice as fast, +0.5 means half as fast. +.TP 8 +.B \-density \fIpercentage\fP +The approximate percentage of the screen that should be filled with +characters at any given time. Default 20%. +.TP 8 +.B \-no\-fog +By default, glyphs are dimmer the farther away they are. This +argument disables that. +.TP 8 +.B \-no\-waves +By default, waves of color roll down the columns of glyphs. This +argument disables that. +.TP 8 +.B \-no-rotate\fP +By default, the scene slowly tilts and rotates. This +argument disables that. +.TP 8 +.B \-binary\fP +Instead of displaying Matrix glyphs, only display ones and zeros. +.TP 8 +.B \-hexadecimal\fP +Instead of displaying Matrix glyphs, display hexadecimal digits. +.TP 8 +.B \-dna\fP +Instead of displaying Matrix glyphs, display genetic code +(guanine, adenine, thymine, and cytosine.) +.TP 8 +.B \-clock\fP +Hide a clock displaying the current time somewhere in the glyphs. +.TP 8 +.B \-timefmt\fP \fIstrftime-string\fP +How to format the clock when \fI\-clock\fP is specified. +Default "\ %l%M%p\ ". +.TP 8 +.B \-speed \fIratio\fP +Less than 1 for slower, greater than 1 for faster. Default 1. +.TP 8 +.B \-wireframe +Just draw boxes instead of textured characters. +.TP 8 +.B \-fps +Display the current frame rate, CPU load, and polygon count. +.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 xmatrix (MANSUFFIX), +.BR X (1), +.BR xscreensaver (1) +.SH COPYRIGHT +Copyright \(co 1999-2003 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 , 8-Jun-2003. diff --git a/hacks/glx/glplanet.c b/hacks/glx/glplanet.c new file mode 100644 index 00000000..98e13e8d --- /dev/null +++ b/hacks/glx/glplanet.c @@ -0,0 +1,662 @@ +/* -*- Mode: C; tab-width: 4 -*- */ +/* glplanet --- 3D rotating planet, e.g., Earth. + * + * Permission to use, copy, modify, and distribute this software and its + * documentation for any purpose and without fee is hereby granted, + * provided that the above copyright notice appear in all copies and that + * both that copyright notice and this permission notice appear in + * supporting documentation. + * + * This file is provided AS IS with no warranties of any kind. The author + * shall have no liability with respect to the infringement of copyrights, + * trade secrets or any patents by this file or any part thereof. In no + * event will the author be liable for any lost revenue or profits or + * other special, indirect and consequential damages. + * + * Revision History: + * + * 16-Jan-02: jwz@jwz.org gdk_pixbuf support. + * 21-Mar-01: jwz@jwz.org Broke sphere routine out into its own file. + * + * 9-Oct-98: dek@cgl.ucsf.edu Added stars. + * + * 8-Oct-98: jwz@jwz.org Made the 512x512x1 xearth image be built in. + * Made it possible to load XPM or XBM files. + * Made the planet bounce and roll around. + * + * 8-Oct-98: Released initial version of "glplanet" + * (David Konerding, dek@cgl.ucsf.edu) + * + * BUGS: + * -bounce is broken + * + * For even more spectacular results, grab the images from the "SSystem" + * package (http://www.msu.edu/user/kamelkev/) and use its JPEGs! + */ + + +#ifdef STANDALONE +#define DEFAULTS "*delay: 20000 \n" \ + "*showFPS: False \n" \ + "*wireframe: False \n" \ + "*imageForeground: Green \n" \ + "*imageBackground: Blue \n" +# define refresh_planet 0 +# include "xlockmore.h" /* from the xscreensaver distribution */ +#else /* !STANDALONE */ +# include "xlock.h" /* from the xlockmore distribution */ +#endif /* !STANDALONE */ + +#ifdef USE_GL /* whole file */ + +#include "sphere.h" + +#ifdef HAVE_XMU +# ifndef VMS +# include +#else /* VMS */ +# include +# endif /* VMS */ +#endif + +#define DEF_ROTATE "True" +#define DEF_ROLL "True" +#define DEF_WANDER "True" +#define DEF_SPIN "0.03" +#define DEF_TEXTURE "True" +#define DEF_STARS "True" +#define DEF_LIGHT "True" +#define DEF_RESOLUTION "128" +#define DEF_IMAGE "BUILTIN" + +#undef countof +#define countof(x) (sizeof((x))/sizeof((*x))) + +static int do_rotate; +static int do_roll; +static int do_wander; +static int do_texture; +static int do_stars; +static int do_light; +static char *which_image; +static int resolution; +static float star_spin; + +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 }, + {"-light", ".glplanet.light", XrmoptionNoArg, "true" }, + {"+light", ".glplanet.light", XrmoptionNoArg, "false" }, + {"-image", ".glplanet.image", XrmoptionSepArg, 0 }, + {"-resolution", ".glplanet.resolution", XrmoptionSepArg, 0 }, +}; + +static argtype vars[] = { + {&do_rotate, "rotate", "Rotate", DEF_ROTATE, t_Bool}, + {&do_roll, "roll", "Roll", DEF_ROLL, t_Bool}, + {&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_light, "light", "Light", DEF_LIGHT, t_Bool}, + {&which_image, "image", "Image", DEF_IMAGE, t_String}, + {&resolution, "resolution","Resolution", DEF_RESOLUTION, t_Int}, + {&star_spin, "spin", "Float", DEF_SPIN, t_Float}, +}; + +ENTRYPOINT ModeSpecOpt planet_opts = {countof(opts), opts, countof(vars), vars, NULL}; + +#ifdef USE_MODULES +ModStruct planet_description = +{"planet", "init_planet", "draw_planet", "release_planet", + "draw_planet", "init_planet", NULL, &planet_opts, + 1000, 1, 2, 1, 4, 1.0, "", + "Animates texture mapped sphere (planet)", 0, NULL}; +#endif + +# ifdef __GNUC__ + __extension__ /* don't warn about "string length is greater than the length + ISO C89 compilers are required to support" when including + the following XPM file... */ +# endif +#include "../images/earth.xpm" + +#include "xpm-ximage.h" +#include "rotator.h" +#include "gltrackball.h" + + +/*- + * slices and stacks are used in the sphere parameterization routine. + * more slices and stacks will increase the quality of the sphere, + * at the expense of rendering speed + */ + +#define NUM_STARS 1000 + +/* radius of the sphere- fairly arbitrary */ +#define RADIUS 4 + +/* distance away from the sphere model */ +#define DIST 40 + + + +/* structure for holding the planet data */ +typedef struct { + GLuint platelist; + GLuint latlonglist; + GLuint starlist; + int screen_width, screen_height; + GLXContext *glx_context; + Window window; + XColor fg, bg; + GLfloat sunpos[4]; + double z; + rotator *rot; + trackball_state *trackball; + double star_theta; + Bool button_down_p; +} planetstruct; + + +static planetstruct *planets = NULL; + + +/* Set up and enable texturing on our object */ +static void +setup_xpm_texture (ModeInfo *mi, char **xpm_data) +{ + XImage *image = xpm_to_ximage (MI_DISPLAY (mi), MI_VISUAL (mi), + MI_COLORMAP (mi), xpm_data); + char buf[1024]; + clear_gl_error(); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, + image->width, image->height, 0, + GL_RGBA, + /* GL_UNSIGNED_BYTE, */ + GL_UNSIGNED_INT_8_8_8_8_REV, + image->data); + sprintf (buf, "builtin texture (%dx%d)", image->width, image->height); + check_gl_error(buf); + + /* setup parameters for texturing */ + glPixelStorei(GL_UNPACK_ALIGNMENT, 1); + 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); +} + + +static void +setup_file_texture (ModeInfo *mi, char *filename) +{ + Display *dpy = mi->dpy; + Visual *visual = mi->xgwa.visual; + char buf[1024]; + + Colormap cmap = mi->xgwa.colormap; + XImage *image = xpm_file_to_ximage (dpy, visual, cmap, filename); + + clear_gl_error(); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, + image->width, image->height, 0, + GL_RGBA, + /* GL_UNSIGNED_BYTE, */ + GL_UNSIGNED_INT_8_8_8_8_REV, + image->data); + sprintf (buf, "texture: %.100s (%dx%d)", + filename, image->width, image->height); + check_gl_error(buf); + + /* setup parameters for texturing */ + glPixelStorei(GL_UNPACK_ALIGNMENT, 4); + glPixelStorei(GL_UNPACK_ROW_LENGTH, image->width); + + 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); +} + + +static void +setup_texture(ModeInfo * mi) +{ +/* planetstruct *gp = &planets[MI_SCREEN(mi)];*/ + + glEnable(GL_TEXTURE_2D); + + if (!which_image || + !*which_image || + !strcmp(which_image, "BUILTIN")) + setup_xpm_texture (mi, earth_xpm); + else + setup_file_texture (mi, which_image); + + 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); +} + + +static void +init_stars (ModeInfo *mi) +{ + planetstruct *gp = &planets[MI_SCREEN(mi)]; + int i, j; + int width = MI_WIDTH(mi); + int height = MI_HEIGHT(mi); + int size = (width > height ? width : height); + int nstars = size * size / 320; + int max_size = 3; + GLfloat inc = 0.5; + int steps = max_size / inc; + + gp->starlist = glGenLists(1); + glNewList(gp->starlist, GL_COMPILE); + + glEnable(GL_POINT_SMOOTH); + + for (j = 1; j <= steps; j++) + { + glPointSize(inc * j); + glBegin (GL_POINTS); + for (i = 0; i < nstars / steps; i++) + { + glColor3f (0.6 + frand(0.3), + 0.6 + frand(0.3), + 0.6 + frand(0.3)); + glVertex2f (2 * size * (0.5 - frand(1.0)), + 2 * size * (0.5 - frand(1.0))); + } + glEnd (); + } + glEndList (); + + check_gl_error("stars initialization"); +} + + +static void +draw_stars (ModeInfo *mi) +{ + planetstruct *gp = &planets[MI_SCREEN(mi)]; + + glDisable(GL_TEXTURE_2D); + glDisable(GL_LIGHTING); + glDisable(GL_DEPTH_TEST); + + glMatrixMode (GL_PROJECTION); + glPushMatrix (); + { + glLoadIdentity (); + + glMatrixMode (GL_MODELVIEW); + glPushMatrix (); + { + glLoadIdentity (); + glOrtho (-0.5 * MI_WIDTH(mi), 0.5 * MI_WIDTH(mi), + -0.5 * MI_HEIGHT(mi), 0.5 * MI_HEIGHT(mi), + -100.0, 100.0); + glRotatef (gp->star_theta, 0.0, 0.0, 1.0); + glCallList (gp->starlist); + } + glPopMatrix (); + } + glMatrixMode (GL_PROJECTION); + glPopMatrix (); + + glMatrixMode (GL_MODELVIEW); +} + + + +/* Set up lighting */ +static void +init_sun (ModeInfo * mi) +{ + planetstruct *gp = &planets[MI_SCREEN(mi)]; + + GLfloat lamb[4] = { 0.1, 0.1, 0.1, 1.0 }; + GLfloat ldif[4] = { 1.0, 1.0, 1.0, 1.0 }; + GLfloat spec[4] = { 1.0, 1.0, 1.0, 1.0 }; + + GLfloat mamb[4] = { 0.5, 0.5, 0.5, 1.0 }; + GLfloat mdif[4] = { 1.0, 1.0, 1.0, 1.0 }; + GLfloat mpec[4] = { 1.0, 1.0, 1.0, 1.0 }; + GLfloat shiny = .4; + + { + double h = 0.1 + frand(0.8); /* east-west position - screen-side. */ + double v = -0.3 + frand(0.6); /* north-south position */ + + if (h > 0.3 && h < 0.8) /* avoid having the sun at the camera */ + h += (h > 0.5 ? 0.2 : -0.2); + + gp->sunpos[0] = cos(h * M_PI); + gp->sunpos[1] = sin(h * M_PI); + gp->sunpos[2] = sin(v * M_PI); + gp->sunpos[3] = 0.00; + } + + glEnable(GL_LIGHTING); + glEnable(GL_LIGHT0); + + glLightfv (GL_LIGHT0, GL_POSITION, gp->sunpos); + glLightfv (GL_LIGHT0, GL_AMBIENT, lamb); + glLightfv (GL_LIGHT0, GL_DIFFUSE, ldif); + glLightfv (GL_LIGHT0, GL_SPECULAR, spec); + + check_gl_error("sun"); + glMaterialfv (GL_FRONT, GL_AMBIENT, mamb); + glMaterialfv (GL_FRONT, GL_DIFFUSE, mdif); + glMaterialfv (GL_FRONT, GL_SPECULAR, mpec); + glMaterialf (GL_FRONT, GL_SHININESS, shiny); + + +/* glEnable(GL_BLEND);*/ +/* glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);*/ + glShadeModel(GL_SMOOTH); + + check_gl_error("lighting"); +} + + +#define RANDSIGN() ((random() & 1) ? 1 : -1) + +ENTRYPOINT void +reshape_planet (ModeInfo *mi, int width, int height) +{ + GLfloat h = (GLfloat) height / (GLfloat) width; + + glViewport(0, 0, (GLint) width, (GLint) height); + glMatrixMode(GL_PROJECTION); + glLoadIdentity(); + glFrustum(-1.0, 1.0, -h, h, 5.0, 100.0); + glMatrixMode(GL_MODELVIEW); + glLoadIdentity(); + glTranslatef(0.0, 0.0, -DIST); + + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); +} + + +ENTRYPOINT Bool +planet_handle_event (ModeInfo *mi, XEvent *event) +{ + planetstruct *gp = &planets[MI_SCREEN(mi)]; + + if (event->xany.type == ButtonPress && + event->xbutton.button == Button1) + { + gp->button_down_p = True; + gltrackball_start (gp->trackball, + event->xbutton.x, event->xbutton.y, + MI_WIDTH (mi), MI_HEIGHT (mi)); + return True; + } + else if (event->xany.type == ButtonRelease && + event->xbutton.button == Button1) + { + gp->button_down_p = False; + return True; + } + else if (event->xany.type == ButtonPress && + (event->xbutton.button == Button4 || + event->xbutton.button == Button5 || + event->xbutton.button == Button6 || + event->xbutton.button == Button7)) + { + gltrackball_mousewheel (gp->trackball, event->xbutton.button, 10, + !!event->xbutton.state); + return True; + } + else if (event->xany.type == MotionNotify && + gp->button_down_p) + { + gltrackball_track (gp->trackball, + event->xmotion.x, event->xmotion.y, + MI_WIDTH (mi), MI_HEIGHT (mi)); + return True; + } + + return False; +} + + +ENTRYPOINT void +init_planet (ModeInfo * mi) +{ + planetstruct *gp; + int screen = MI_SCREEN(mi); + Bool wire = MI_IS_WIREFRAME(mi); + + if (planets == NULL) { + if ((planets = (planetstruct *) calloc(MI_NUM_SCREENS(mi), + sizeof (planetstruct))) == NULL) + return; + } + gp = &planets[screen]; + + if ((gp->glx_context = init_GL(mi)) != NULL) { + reshape_planet(mi, MI_WIDTH(mi), MI_HEIGHT(mi)); + } + + { + char *f = get_string_resource(mi->dpy, "imageForeground", "Foreground"); + char *b = get_string_resource(mi->dpy, "imageBackground", "Background"); + char *s; + if (!f) f = strdup("white"); + if (!b) b = strdup("black"); + + for (s = f + strlen(f)-1; s > f; s--) + if (*s == ' ' || *s == '\t') + *s = 0; + for (s = b + strlen(b)-1; s > b; s--) + 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); + } + + { + double spin_speed = 0.5; + double wander_speed = 0.02; + gp->rot = make_rotator (do_roll ? spin_speed : 0, + do_roll ? spin_speed : 0, + 0, 1, + do_wander ? wander_speed : 0, + True); + gp->z = frand (1.0); + gp->trackball = gltrackball_init (); + } + + if (wire) + { + do_texture = False; + do_light = False; + } + + if (do_texture) + setup_texture (mi); + + if (do_light) + init_sun (mi); + + if (do_stars) + init_stars (mi); + + if (random() & 1) + star_spin = -star_spin; + + /* construct the polygons of the planet + */ + gp->platelist = glGenLists(1); + glNewList (gp->platelist, GL_COMPILE); + glColor3f (1,1,1); + glPushMatrix (); + glScalef (RADIUS, RADIUS, RADIUS); + glRotatef (90, 1, 0, 0); + glFrontFace(GL_CCW); + unit_sphere (resolution, resolution, wire); + glPopMatrix (); + glEndList(); + + /* construct the polygons of the latitude/longitude/axis lines. + */ + gp->latlonglist = glGenLists(1); + glNewList (gp->latlonglist, GL_COMPILE); + glPushMatrix (); + glDisable (GL_TEXTURE_2D); + glDisable (GL_LIGHTING); + glDisable (GL_LINE_SMOOTH); + glColor3f (0.1, 0.3, 0.1); + glScalef (RADIUS, RADIUS, RADIUS); + glScalef (1.01, 1.01, 1.01); + glRotatef (90, 1, 0, 0); + unit_sphere (12, 24, 1); + glBegin(GL_LINES); + glVertex3f(0, -2, 0); + glVertex3f(0, 2, 0); + glEnd(); + glPopMatrix (); + glEndList(); +} + +ENTRYPOINT void +draw_planet (ModeInfo * mi) +{ + planetstruct *gp = &planets[MI_SCREEN(mi)]; + Display *display = MI_DISPLAY(mi); + Window window = MI_WINDOW(mi); + double x, y, z; + + if (!gp->glx_context) + return; + + glDrawBuffer(GL_BACK); + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + + glXMakeCurrent (display, window, *(gp->glx_context)); + + mi->polygon_count = 0; + + if (do_stars) + { + draw_stars (mi); + mi->polygon_count += NUM_STARS; + } + + if (do_light) glEnable(GL_LIGHTING); + if (do_texture) glEnable(GL_TEXTURE_2D); + + glEnable (GL_LINE_SMOOTH); + glEnable(GL_DEPTH_TEST); + glEnable(GL_CULL_FACE); + glCullFace(GL_BACK); + + glPushMatrix(); + + get_position (gp->rot, &x, &y, &z, !gp->button_down_p); + glTranslatef((x - 0.5) * 15, + (y - 0.5) * 15, + (z - 0.5) * 8); + + /* Do it twice because we don't track the device's orientation. */ + glRotatef( current_device_rotation(), 0, 0, 1); + gltrackball_rotate (gp->trackball); + glRotatef(-current_device_rotation(), 0, 0, 1); + + glRotatef (90,1,0,0); + + if (do_roll) + { + 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); + } + + glLightfv (GL_LIGHT0, GL_POSITION, gp->sunpos); + + glRotatef (gp->z * 360, 0.0, 0.0, 1.0); + if (do_rotate && !gp->button_down_p) + { + gp->z -= 0.005; /* the sun sets in the west */ + if (gp->z < 0) gp->z += 1; + } + + glCallList (gp->platelist); + mi->polygon_count += resolution*resolution; + + if (gp->button_down_p) + { + glCallList (gp->latlonglist); + mi->polygon_count += 24*24; + } + glPopMatrix(); + + if (mi->fps_p) do_fps (mi); + glFinish(); + glXSwapBuffers(display, window); + + gp->star_theta += star_spin; +} + + +ENTRYPOINT void +release_planet (ModeInfo * mi) +{ + if (planets != NULL) { + int screen; + + for (screen = 0; screen < MI_NUM_SCREENS(mi); screen++) { + planetstruct *gp = &planets[screen]; + + if (gp->glx_context) { + /* Display lists MUST be freed while their glXContext is current. */ + /* but this gets a BadMatch error. -jwz */ + /*glXMakeCurrent(MI_DISPLAY(mi), gp->window, *(gp->glx_context));*/ + + if (glIsList(gp->platelist)) + glDeleteLists(gp->platelist, 1); + if (glIsList(gp->starlist)) + glDeleteLists(gp->starlist, 1); + } + } + (void) free((void *) planets); + planets = NULL; + } + FreeAllGL(mi); +} + + +XSCREENSAVER_MODULE_2 ("GLPlanet", glplanet, planet) + +#endif diff --git a/hacks/glx/glplanet.man b/hacks/glx/glplanet.man new file mode 100644 index 00000000..a01358ee --- /dev/null +++ b/hacks/glx/glplanet.man @@ -0,0 +1,70 @@ +.TH XScreenSaver 1 "" "X Version 11" +.SH NAME +glplanet - rotating 3d texture-mapped planet. +.SH SYNOPSIS +.B glplanet +[\-display \fIhost:display.screen\fP] +[\-visual \fIvisual\fP] +[\-window] +[\-root] +[\-no-light] +[\-delay \fInumber\fP] +[\-image \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'. +.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 \-light | \-no-light +Use Flat Coloring. +.TP 8 +.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. +.TP 8 +.B \-resolution +The resolution of the planet. Default: 128. +.TP 8 +.B \-wireframe +Render in wireframe instead of solid. +.TP 8 +.B \-fps +Display the current frame rate, CPU load, and polygon count. +.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 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. +.SH AUTHOR +David Konerding. diff --git a/hacks/glx/glschool.c b/hacks/glx/glschool.c new file mode 100644 index 00000000..eb522a03 --- /dev/null +++ b/hacks/glx/glschool.c @@ -0,0 +1,222 @@ +/* glschool.c, Copyright (c) 2005-2006 David C. Lambert + * + * 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. + */ +#include "xlockmore.h" +#include "glschool.h" + +#define sws_opts xlockmore_opts +#define DEFAULTS "*delay: 20000 \n" \ + "*showFPS: False \n" \ + "*wireframe: False \n" \ + +#define refresh_glschool (0) +#define release_glschool (0) +#define glschool_handle_event (0) + +#undef countof +#define countof(x) (sizeof((x))/sizeof((*x))) + +#define DEF_NFISH "100" +#define DEF_FOG "False" +#define DEF_DRAWBBOX "True" +#define DEF_DRAWGOAL "False" +#define DEF_GOALCHGF "50" +#define DEF_MAXVEL "7.0" +#define DEF_MINVEL "1.0" +#define DEF_ACCLIMIT "8.0" +#define DEF_DISTEXP "2.2" +#define DEF_AVOIDFACT "1.5" +#define DEF_MATCHFACT "0.15" +#define DEF_CENTERFACT "0.1" +#define DEF_TARGETFACT "80" +#define DEF_MINRADIUS "30.0" +#define DEF_MOMENTUM "0.9" +#define DEF_DISTCOMP "10.0" + +static int NFish; +static Bool DoFog; +static Bool DoDrawBBox; +static Bool DoDrawGoal; +static int GoalChgFreq; +static float MinVel; +static float MaxVel; +static float DistExp; +static float AccLimit; +static float AvoidFact; +static float MatchFact; +static float TargetFact; +static float CenterFact; +static float MinRadius; +static float Momentum; +static float DistComp; + +static XrmOptionDescRec opts[] = { + { "-nfish", ".nfish", XrmoptionSepArg, 0 }, + { "-fog", ".fog", XrmoptionNoArg, "True" }, + { "+fog", ".fog", XrmoptionNoArg, "False" }, + { "-drawgoal", ".drawgoal", XrmoptionNoArg, "True" }, + { "+drawgoal", ".drawgoal", XrmoptionNoArg, "False" }, + { "-drawbbox", ".drawbbox", XrmoptionNoArg, "True" }, + { "+drawbbox", ".drawbbox", XrmoptionNoArg, "False" }, + { "-goalchgf", ".goalchgf", XrmoptionSepArg, 0 }, + { "-maxvel", ".maxvel", XrmoptionSepArg, 0 }, + { "-minvel", ".minvel", XrmoptionSepArg, 0 }, + { "-acclimit", ".acclimit", XrmoptionSepArg, 0 }, + { "-distexp", ".distexp", XrmoptionSepArg, 0 }, + { "-avoidfact", ".avoidfact", XrmoptionSepArg, 0 }, + { "-matchfact", ".matchfact", XrmoptionSepArg, 0 }, + { "-centerfact",".centerfact", XrmoptionSepArg, 0 }, + { "-targetfact",".targetfact", XrmoptionSepArg, 0 }, + { "-minradius", ".minradius", XrmoptionSepArg, 0 }, + { "-distcomp", ".distcomp", XrmoptionSepArg, 0 }, + { "-momentum", ".momentum", XrmoptionSepArg, 0 }, +}; + +static argtype vars[] = { + {&NFish, "nfish", "NFish", DEF_NFISH, t_Int}, + {&DoFog, "fog", "DoFog", DEF_FOG, t_Bool}, + {&DoDrawBBox, "drawbbox", "DoDrawBBox", DEF_DRAWBBOX, t_Bool}, + {&DoDrawGoal, "drawgoal", "DoDrawGoal", DEF_DRAWGOAL, t_Bool}, + {&GoalChgFreq, "goalchgf", "GoalChgFreq", DEF_GOALCHGF, t_Int}, + {&MaxVel, "maxvel", "MaxVel", DEF_MAXVEL, t_Float}, + {&MinVel, "minvel", "MinVel", DEF_MINVEL, t_Float}, + {&AccLimit, "acclimit", "AccLimit", DEF_ACCLIMIT, t_Float}, + {&DistExp, "distexp", "DistExp", DEF_DISTEXP, t_Float}, + {&AvoidFact, "avoidfact", "AvoidFact", DEF_AVOIDFACT, t_Float}, + {&MatchFact, "matchfact", "MatchFact", DEF_MATCHFACT, t_Float}, + {&CenterFact, "centerfact", "CenterFact", DEF_CENTERFACT, t_Float}, + {&TargetFact, "targetfact", "TargetFact", DEF_TARGETFACT, t_Float}, + {&MinRadius, "minradius", "MinRadius", DEF_MINRADIUS, t_Float}, + {&Momentum, "momentum", "Momentum", DEF_MOMENTUM, t_Float}, + {&DistComp, "distcomp", "DistComp", DEF_DISTCOMP, t_Float}, +}; + +ENTRYPOINT ModeSpecOpt glschool_opts = {countof(opts), opts, countof(vars), vars, NULL}; + +typedef struct { + int nColors; + int rotCounter; + int goalCounter; + Bool drawGoal; + Bool drawBBox; + GLuint bboxList; + GLuint goalList; + GLuint fishList; + int fish_polys, box_polys; + XColor *colors; + School *school; + GLXContext *context; +} glschool_configuration; + +static glschool_configuration *scs = NULL; + +ENTRYPOINT void +reshape_glschool(ModeInfo *mi, int width, int height) +{ + Bool wire = MI_IS_WIREFRAME(mi); + double aspect = (double)width/(double)height; + glschool_configuration *sc = &scs[MI_SCREEN(mi)]; + + glXMakeCurrent(MI_DISPLAY(mi), MI_WINDOW(mi), *(sc->context)); + if (sc->school != (School *)0) { + glschool_setBBox(sc->school, -aspect*160, aspect*160, -130, 130, -450, -50.0); + glDeleteLists(sc->bboxList, 1); + glschool_createBBoxList(&SCHOOL_BBOX(sc->school), + &sc->bboxList, wire); + } + glschool_reshape(width, height); +} + +ENTRYPOINT void +init_glschool(ModeInfo *mi) +{ + int width = MI_WIDTH(mi); + int height = MI_HEIGHT(mi); + Bool wire = MI_IS_WIREFRAME(mi); + glschool_configuration *sc; + + if (!scs) { + scs = (glschool_configuration *)calloc(MI_NUM_SCREENS(mi), sizeof(glschool_configuration)); + if (!scs) { + perror("init_glschool: "); + exit(1); + } + } + sc = &scs[MI_SCREEN(mi)]; + + sc->drawGoal = DoDrawGoal; + sc->drawBBox = DoDrawBBox; + + sc->nColors = 360; + sc->context = init_GL(mi); + sc->colors = (XColor *)calloc(sc->nColors, sizeof(XColor)); + make_color_ramp(0, 0, + 0.0, 1.0, 1.0, + 359.0, 1.0, 1.0, + sc->colors, &sc->nColors, + False, 0, False); + + sc->school = glschool_initSchool(NFish, AccLimit, MaxVel, MinVel, DistExp, Momentum, + MinRadius, AvoidFact, MatchFact, CenterFact, TargetFact, + DistComp); + if (sc->school == (School *)0) { + fprintf(stderr, "couldn't initialize TheSchool, exiting\n"); + exit(1); + } + + reshape_glschool(mi, width, height); + + glschool_initGLEnv(DoFog); + glschool_initFishes(sc->school); + glschool_createDrawLists(&SCHOOL_BBOX(sc->school), + &sc->bboxList, &sc->goalList, &sc->fishList, + &sc->fish_polys, &sc->box_polys, wire); + glschool_computeAccelerations(sc->school); +} + +ENTRYPOINT void +draw_glschool(ModeInfo *mi) +{ + Window window = MI_WINDOW(mi); + Display *dpy = MI_DISPLAY(mi); + glschool_configuration *sc = &scs[MI_SCREEN(mi)]; + + if (!sc->context) { + fprintf(stderr, "no context\n"); + return; + } + + glXMakeCurrent(MI_DISPLAY(mi), MI_WINDOW(mi), *(sc->context)); + + mi->polygon_count = 0; + + if ((sc->goalCounter % GoalChgFreq) == 0) + glschool_newGoal(sc->school); + sc->goalCounter++; + + sc->rotCounter++; + sc->rotCounter = (sc->rotCounter%360); + + glschool_applyMovements(sc->school); + glschool_drawSchool(sc->colors, sc->school, sc->bboxList, + sc->goalList, sc->fishList, sc->rotCounter, + sc->drawGoal, sc->drawBBox, + sc->fish_polys, sc->box_polys, + &mi->polygon_count); + glschool_computeAccelerations(sc->school); + + if (mi->fps_p) + do_fps(mi); + + glFinish(); + glXSwapBuffers(dpy, window); +} + +XSCREENSAVER_MODULE("GLSchool", glschool) diff --git a/hacks/glx/glschool.h b/hacks/glx/glschool.h new file mode 100644 index 00000000..b6ce7d53 --- /dev/null +++ b/hacks/glx/glschool.h @@ -0,0 +1,17 @@ +/* glschool.h, Copyright (c) 2005-2006 David C. Lambert + * + * 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. + */ +#ifndef __GLSCHOOL_H__ +#define __GLSCHOOL_H__ + +#include "glschool_alg.h" +#include "glschool_gl.h" + +#endif /* __GLSCHOOL_H__ */ diff --git a/hacks/glx/glschool.man b/hacks/glx/glschool.man new file mode 100644 index 00000000..8de00c41 --- /dev/null +++ b/hacks/glx/glschool.man @@ -0,0 +1,126 @@ +.TH XScreenSaver 1 "" "X Version 11" +.SH NAME +glschool - a 3D schooling simulation +.SH SYNOPSIS +.B glschool +[\-display \fIhost:display.screen\fP] +[\-visual \fIvisual\fP] +[\-window] +[\-root] +[\-wireframe] +[\-fps] +[\-delay \fInumber\fP] +[\-nfish \fInumber\fP] +[\-maxvel \fInumber\fP] +[\-minvel \fInumber\fP] +[\-acclimit \fInumber\fP] +[\-avoidfact \fInumber\fP] +[\-matchfact \fInumber\fP] +[\-centerfact \fInumber\fP] +[\-targetfact \fInumber\fP] +[\-minradius \fInumber\fP] +[\-momentum \fInumber\fP] +[\-distexp \fInumber\fP] +[\-goalchgf \fInumber\fP] +[\-fog] +[\-drawgoal] +[\-drawbbox] +.SH DESCRIPTION +Uses Craig Reynolds Boids algorithm to simulate a 3d school of +fish. See for a description +of the algorithm and the original paper. This is a lightly modified +version of the algorithm that supports goal attraction. + +Many different behaviors are possible by tweaking the parameters. No sanity checking is performed +on the command line params, so if you want to use negative accelerations or minimum velocity that is +larger than maximum velocity or that sort of thing, the simulation will try to digest it. + +It looks best with the highest number of fish that will give you an FPS of > 25 or so. + +.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: 20000 (0.020 seconds.). +.TP 8 +.B \-wireframe | \-no-wireframe +Render in wireframe instead of solid. +.TP 8 +.B \-fps +Display the current frame rate, CPU load, and polygon count. +.TP 8 +.B \-fog | \-no-fog + Whether to show foggy (cloudy) water. +.TP 8 +.B \-drawgoal | \-no-drawgoal + Whether to show the school's attraction goal. +.TP 8 +.B \-drawbbox | \-no-drawbbox + Whether to show the bounding box. +.TP 8 +.B \-fog | \-no-fog + Whether to show foggy (cloudy) water. +.TP 8 +.B \-nfish \fInumber\fP +Number of fish. Defaults to 100 +.TP 8 +.B \-acclimit \fInumber\fP +Acceleration limit. Defaults to 8.0 +.TP 8 +.B \-minvel \fInumber\fP +Minimum velocity. Defaults to 1.0 +.TP 8 +.B \-maxvel \fInumber\fP +Minimum velocity. Defaults to 7.0 +.TP 8 +.B \-goalchgf \fInumber\fP +Goal change frequency. Defaults to 50 (frames) +.TP 8 +.B \-avoidfact \fInumber\fP +Avoidance acceleration factor. Defaults to 1.5 +.TP 8 +.B \-matchfact \fInumber\fP +Match avg velocity acceleration factor. Defaults to 0.15 +.TP 8 +.B \-centerfact \fInumber\fP +School centering acceleration factor. Defaults to 0.1 +.TP 8 +.B \-targetfact \fInumber\fP +Target attraction acceleration factor. Defaults to 80 +.TP 8 +.B \-distexp \fInumber\fP +Distance weighting exponent. Defaults to 2.2 +.TP 8 +.B \-momentum \fInumber\fP +Momentum. Defaults to 0.9 +.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 2005-2006 by David C. Lambert. 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 C. Lambert diff --git a/hacks/glx/glschool_alg.c b/hacks/glx/glschool_alg.c new file mode 100644 index 00000000..32b4a5f4 --- /dev/null +++ b/hacks/glx/glschool_alg.c @@ -0,0 +1,364 @@ +/* school_alg.c, Copyright (c) 2005-2006 David C. Lambert + * + * 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. + */ +#include +#include +#include + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include "yarandom.h" +#include "glschool_alg.h" + +/* for xscreensaver */ +#undef drand48 +#define drand48() frand(1.0) + +#define RAD2DEG (180.0/3.1415926535) + + +static inline double +norm(double *dv) +{ + return sqrt(dv[0]*dv[0] + dv[1]*dv[1] + dv[2]*dv[2]); +} + + +static inline void +addVector(double *v, double *d) +{ + v[0] += d[0]; + v[1] += d[1]; + v[2] += d[2]; +} + + +static inline void +clearVector(double *v) +{ + v[0] = v[1] = v[2] = 0.0; +} + + +static inline void +scaleVector(double *v, double s) +{ + v[0] *= s; + v[1] *= s; + v[2] *= s; +} + + +static inline void +addScaledVector(double *v, double *d, double s) +{ + v[0] += d[0]*s; + v[1] += d[1]*s; + v[2] += d[2]*s; +} + + +static inline void +getDifferenceVector(double *v0, double *v1, double *diff) +{ + diff[0] = v0[0] - v1[0]; + diff[1] = v0[1] - v1[1]; + diff[2] = v0[2] - v1[2]; +} + + +void +glschool_initFish(Fish *f, double *mins, double *ranges) +{ + int i; + + for(i = 0; i < 3; i++) { + FISH_IPOS(f, i) = mins[i] + drand48()*ranges[i]; + FISH_IACC(f, i) = 0.0; + FISH_IVEL(f, i) = drand48(); + FISH_IMAGIC(f, i) = 0.70 + 0.60*drand48(); + FISH_IOLDVEL(f, i) = 0.0; + } +} + + +void +glschool_initFishes(School *s) +{ + int i; + Fish *f = (Fish *)0; + int nFish = SCHOOL_NFISH(s); + BBox *bbox = &SCHOOL_BBOX(s); + double *mins = BBOX_MINS(bbox); + double *ranges = SCHOOL_BBRANGES(s); + Fish *theFishes = SCHOOL_FISHES(s); + + for(i = 0, f = theFishes; i < nFish; i++, f++) + glschool_initFish(f, mins, ranges); +} + + +static void +applyFishMovements(Fish *f, BBox *bbox, double minVel, double maxVel, double momentum) +{ + int i; + int oob = 0; + double vMag = 0.0; + + for(i = 0; i < 3; i++) { + double pos = FISH_IPOS(f, i); + oob = (pos > BBOX_IMAX(bbox, i) || pos < BBOX_IMIN(bbox, i)); + if (oob == 0) FISH_IVEL(f, i) += FISH_IACC(f, i) * FISH_IMAGIC(f, i); + vMag += (FISH_IVEL(f, i) * FISH_IVEL(f, i)); + } + vMag = sqrt(vMag); + + if (vMag > maxVel) + scaleVector(FISH_VEL(f), maxVel/vMag); + else if (vMag < minVel) + scaleVector(FISH_VEL(f), minVel/vMag); + + for(i = 0; i < 3; i++) { + FISH_IVEL(f, i) = momentum * FISH_IOLDVEL(f, i) + (1.0-momentum) * FISH_IVEL(f, i); + FISH_IPOS(f, i) += FISH_IVEL(f, i); + FISH_IOLDVEL(f, i) = FISH_IVEL(f, i); + + if (FISH_IPOS(f, i) < BBOX_IMIN(bbox, i)) + FISH_IPOS(f, i) = BBOX_IMAX(bbox, i); + else if (FISH_IPOS(f, i) > BBOX_IMAX(bbox, i)) + FISH_IPOS(f, i) = BBOX_IMIN(bbox, i); + } +} + + +void +glschool_applyMovements(School *s) +{ + int i = 0; + Fish *f = (Fish *)0; + int nFish = SCHOOL_NFISH(s); + double minVel = SCHOOL_MINVEL(s); + double maxVel = SCHOOL_MAXVEL(s); + double momentum = SCHOOL_MOMENTUM(s); + BBox *bbox = &SCHOOL_BBOX(s); + Fish *theFishes = SCHOOL_FISHES(s); + + for(i = 0, f = theFishes; i < nFish; i++, f++) + applyFishMovements(f, bbox, minVel, maxVel, momentum); +} + + +School * +glschool_initSchool(int nFish, double accLimit, double maxV, double minV, double distExp, double momentum, + double minRadius, double avoidFact, double matchFact, double centerFact, double targetFact, + double distComp) +{ + School *s = (School *)0; + + if ((s = (School *)malloc(sizeof(School))) == (School *)0) { + perror("initSchool School allocation failed: "); + return s; + } + + if ((SCHOOL_FISHES(s) = (Fish *)malloc(sizeof(Fish)*nFish)) == (Fish *)0) { + perror("initSchool Fish array allocation failed: "); + free(s); + return (School *)0; + } + + SCHOOL_NFISH(s) = nFish; + SCHOOL_ACCLIMIT(s) = accLimit; + SCHOOL_MAXVEL(s) = maxV; + SCHOOL_MINVEL(s) = minV; + SCHOOL_DISTEXP(s) = distExp; + SCHOOL_MOMENTUM(s) = momentum; + SCHOOL_MINRADIUS(s) = minRadius; + SCHOOL_MINRADIUSEXP(s) = pow(minRadius, distExp); + SCHOOL_MATCHFACT(s) = matchFact; + SCHOOL_AVOIDFACT(s) = avoidFact; + SCHOOL_CENTERFACT(s) = centerFact; + SCHOOL_TARGETFACT(s) = targetFact; + SCHOOL_DISTCOMP(s) = distComp; + + return s; +} + +void +glschool_freeSchool(School *s) +{ + free(SCHOOL_FISHES(s)); + free(s); +} + +void +glschool_setBBox(School *s, double xMin, double xMax, double yMin, double yMax, double zMin, double zMax) +{ + int i; + BBox *bbox = &SCHOOL_BBOX(s); + + BBOX_XMIN(bbox) = xMin; BBOX_XMAX(bbox) = xMax; + BBOX_YMIN(bbox) = yMin; BBOX_YMAX(bbox) = yMax; + BBOX_ZMIN(bbox) = zMin; BBOX_ZMAX(bbox) = zMax; + + for(i = 0; i < 3; i++) { + SCHOOL_IMID(s, i) = BBOX_IMID(bbox, i); + SCHOOL_IRANGE(s, i) = BBOX_IRANGE(bbox, i); + } +} + + +void +glschool_newGoal(School *s) +{ + SCHOOL_IGOAL(s,0) = 0.85*(drand48()-0.5)*SCHOOL_IRANGE(s,0) + SCHOOL_IMID(s,0); + SCHOOL_IGOAL(s,1) = 0.40*(drand48()-0.5)*SCHOOL_IRANGE(s,1) + SCHOOL_IMID(s,1); + SCHOOL_IGOAL(s,2) = 0.85*(drand48()-0.5)*SCHOOL_IRANGE(s,2) + SCHOOL_IMID(s,2); +} + + +double +glschool_computeNormalAndThetaToPlusZ(double *v, double *xV) +{ + double x1 = 0.0; + double y1 = 0.0; + double z1 = 1.0; + double x2 = v[0]; + double y2 = v[1]; + double z2 = v[2]; + double theta = 0.0; + double xVNorm = 0.0; + double sinTheta = 0.0; + double v2Norm = norm(v); + + if (v2Norm == 0.0) { + xV[1] = 1.0; + xV[0] = xV[2] = 0.0; + return theta; + } + xV[0] = (y1*z2 - z1*y2); + xV[1] = -(x1*z2 - z1*x2); + xV[2] = (x1*y2 - y1*x2); + xVNorm = norm(xV); + + sinTheta = xVNorm/v2Norm; + return (asin(sinTheta) * RAD2DEG); +} + + +int +glschool_computeGroupVectors(School *s, Fish *ref, double *avoidance, double *centroid, double *avgVel) +{ + int i; + double dist; + double adjDist; + double diffVect[3]; + int neighborCount = 0; + Fish *test = (Fish *)0; + int nFish = SCHOOL_NFISH(s); + double distExp = SCHOOL_DISTEXP(s); + double distComp = SCHOOL_DISTCOMP(s); + double minRadiusExp = SCHOOL_MINRADIUSEXP(s); + Fish *fishes = SCHOOL_FISHES(s); + + for(i = 0, test = fishes; i < nFish; i++, test++) { + if (test == ref) continue; + + getDifferenceVector(FISH_POS(ref), FISH_POS(test), diffVect); + + dist = norm(diffVect) - distComp; + if (dist < 0.0) dist = 0.1; + + adjDist = pow(dist, distExp); + if (adjDist > minRadiusExp) continue; + + neighborCount++; + + addVector(avgVel, FISH_VEL(test)); + addVector(centroid, FISH_POS(test)); + + addScaledVector(avoidance, diffVect, 1.0/adjDist); + } + if (neighborCount > 0) { + scaleVector(avgVel, 1.0/neighborCount); + scaleVector(centroid, 1.0/neighborCount); + } + return neighborCount; +} + + +void +glschool_computeAccelerations(School *s) +{ + int i; + int j; + int neighborCount; + double dist; + double adjDist; + double accMag; + double avgVel[3]; + double diffVect[3]; + double centroid[3]; + double avoidance[3]; + Fish *ref = (Fish *)0; + int nFish = SCHOOL_NFISH(s); + double *goal = SCHOOL_GOAL(s); + double distExp = SCHOOL_DISTEXP(s); + double distComp = SCHOOL_DISTCOMP(s); + double avoidFact = SCHOOL_AVOIDFACT(s); + double matchFact = SCHOOL_MATCHFACT(s); + double centerFact = SCHOOL_CENTERFACT(s); + double targetFact = SCHOOL_TARGETFACT(s); + double accLimit = SCHOOL_ACCLIMIT(s); + double minRadius = SCHOOL_MINRADIUS(s); + Fish *fishes = SCHOOL_FISHES(s); + + for(i = 0, ref = fishes; i < nFish; i++, ref++) { + clearVector(avgVel); + clearVector(centroid); + clearVector(avoidance); + clearVector(FISH_ACC(ref)); + neighborCount = glschool_computeGroupVectors(s, ref, avoidance, centroid, avgVel); + + /* avoidanceAccel[] = avoidance[] * AvoidFact */ + scaleVector(avoidance, avoidFact); + addVector(FISH_ACC(ref), avoidance); + + accMag = norm(FISH_ACC(ref)); + if (neighborCount > 0 && accMag < accLimit) { + for(j = 0; j < 3; j++) { + FISH_IAVGVEL(ref, j) = avgVel[j]; + FISH_IACC(ref, j) += ((avgVel[j] - FISH_IVEL(ref, j)) * matchFact); + } + + accMag = norm(FISH_ACC(ref)); + if (accMag < accLimit) { + for(j = 0; j < 3; j++) + FISH_IACC(ref, j) += ((centroid[j] - FISH_IPOS(ref, j)) * centerFact); + } + } + + accMag = norm(FISH_ACC(ref)); + if (accMag < accLimit) { + getDifferenceVector(goal, FISH_POS(ref), diffVect); + + dist = norm(diffVect) - distComp; + if (dist < 0.0) dist = 0.1; + + /*adjDist = pow(dist, distExp);*/ + if (dist > minRadius) { + adjDist = pow(dist, distExp); + for(j = 0; j < 3; j++) + FISH_IACC(ref, j) += (diffVect[j]*targetFact/adjDist); + } + } + } +} diff --git a/hacks/glx/glschool_alg.h b/hacks/glx/glschool_alg.h new file mode 100644 index 00000000..339e778f --- /dev/null +++ b/hacks/glx/glschool_alg.h @@ -0,0 +1,126 @@ +/* glschool_alg.h, Copyright (c) 2005-2006 David C. Lambert + * + * 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. + */ +#ifndef __GLSCHOOL_ALG_H__ +#define __GLSCHOOL_ALG_H__ + +typedef struct { + double mins[3]; + double maxs[3]; +} BBox; + +#define BBOX_XMIN(b) ((b)->mins[0]) +#define BBOX_YMIN(b) ((b)->mins[1]) +#define BBOX_ZMIN(b) ((b)->mins[2]) +#define BBOX_MINS(b) ((b)->mins) +#define BBOX_IMIN(b, i) ((b)->mins[(i)]) + +#define BBOX_XMAX(b) ((b)->maxs[0]) +#define BBOX_YMAX(b) ((b)->maxs[1]) +#define BBOX_ZMAX(b) ((b)->maxs[2]) +#define BBOX_MAXS(b) ((b)->maxs) +#define BBOX_IMAX(b, i) ((b)->maxs[(i)]) + +#define BBOX_IMID(b, i) (((b)->maxs[(i)] + (b)->mins[(i)])/2.0) +#define BBOX_IRANGE(b, i) ((b)->maxs[(i)] - (b)->mins[(i)]) + +typedef struct { + double pos[3]; + double vel[3]; + double accel[3]; + double oldVel[3]; + double magic[3]; + double avgVel[3]; +} Fish; + +#define FISH_POS(f) ((f)->pos) +#define FISH_X(f) ((f)->pos[0]) +#define FISH_Y(f) ((f)->pos[1]) +#define FISH_Z(f) ((f)->pos[2]) + +#define FISH_VEL(f) ((f)->vel) +#define FISH_VX(f) ((f)->vel[0]) +#define FISH_VY(f) ((f)->vel[1]) +#define FISH_VZ(f) ((f)->vel[2]) + +#define FISH_ACC(f) ((f)->accel) +#define FISH_MAGIC(f) ((f)->magic) +#define FISH_OLDVEL(f) ((f)->oldVel) +#define FISH_AVGVEL(f) ((f)->avgVel) +#define FISH_IPOS(f, i) ((f)->pos[(i)]) +#define FISH_IVEL(f, i) ((f)->vel[(i)]) +#define FISH_IACC(f, i) ((f)->accel[(i)]) +#define FISH_IMAGIC(f, i) ((f)->magic[(i)]) +#define FISH_IOLDVEL(f, i) ((f)->oldVel[(i)]) +#define FISH_IAVGVEL(f, i) ((f)->avgVel[(i)]) + +typedef struct { + int nFish; + double maxVel; + double minVel; + double distExp; + double momentum; + double accLimit; + double minRadius; + double minRadiusExp; + double avoidFact; + double matchFact; + double centerFact; + double targetFact; + double distComp; + double goal[3]; + double boxMids[3]; + double boxRanges[3]; + BBox theBox; + Fish *theFish; +} School; + +#define SCHOOL_NFISH(s) ((s)->nFish) +#define SCHOOL_MAXVEL(s) ((s)->maxVel) +#define SCHOOL_MINVEL(s) ((s)->minVel) +#define SCHOOL_DISTEXP(s) ((s)->distExp) +#define SCHOOL_MOMENTUM(s) ((s)->momentum) +#define SCHOOL_ACCLIMIT(s) ((s)->accLimit) +#define SCHOOL_MINRADIUS(s) ((s)->minRadius) +#define SCHOOL_MINRADIUSEXP(s) ((s)->minRadiusExp) +#define SCHOOL_MATCHFACT(s) ((s)->matchFact) +#define SCHOOL_AVOIDFACT(s) ((s)->avoidFact) +#define SCHOOL_CENTERFACT(s) ((s)->centerFact) +#define SCHOOL_TARGETFACT(s) ((s)->targetFact) +#define SCHOOL_DISTCOMP(s) ((s)->distComp) +#define SCHOOL_GOAL(s) ((s)->goal) +#define SCHOOL_IGOAL(s,i) ((s)->goal[(i)]) +#define SCHOOL_BBMINS(s) ((s)->bbox.mins) +#define SCHOOL_BBMAXS(s) ((s)->bbox.maxs) +#define SCHOOL_BBMIDS(s) ((s)->boxMids) +#define SCHOOL_IMID(s,i) ((s)->boxMids[(i)]) +#define SCHOOL_BBRANGES(s) ((s)->boxRanges) +#define SCHOOL_IRANGE(s,i) ((s)->boxRanges[(i)]) +#define SCHOOL_BBOX(s) ((s)->theBox) +#define SCHOOL_FISHES(s) ((s)->theFish) +#define SCHOOL_IFISH(s,i) ((s)->theFish[i]) + +extern void glschool_initFishes(School *); +extern void glschool_initFish(Fish *, double *, double *); + +extern void glschool_applyMovements(School *); +/* extern void applyFishMovements(Fish *, BBox *, double, double, double); */ + +extern void glschool_freeSchool(School *); +extern School *glschool_initSchool(int, double, double, double, double, double, double, double, double, double, double, double); + +extern void glschool_newGoal(School *); +extern void glschool_setBBox(School *, double, double, double, double, double, double); + +extern void glschool_computeAccelerations(School *); +extern double glschool_computeNormalAndThetaToPlusZ(double *, double *); +int glschool_computeGroupVectors(School *, Fish *, double *, double *, double *); + +#endif /* __GLSCHOOL_ALG_H__ */ diff --git a/hacks/glx/glschool_gl.c b/hacks/glx/glschool_gl.c new file mode 100644 index 00000000..660580b9 --- /dev/null +++ b/hacks/glx/glschool_gl.c @@ -0,0 +1,274 @@ +/* glschool_gl.c, Copyright (c) 2005-2012 David C. Lambert + * + * 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. + */ + +#include "sphere.h" +#include "glschool_gl.h" +#include "sphere.h" +#include "tube.h" + +void +glschool_drawGoal(double *goal, GLuint goalList) +{ + glColor3f(1.0, 0.0, 0.0); + glPushMatrix(); + { + glTranslatef(goal[0], goal[1], goal[2]); + glColor3f(1.0, 0.0, 0.0); + glCallList(goalList); + } + glPopMatrix(); +} + +int +glschool_drawBoundingBox(BBox *bbox, Bool wire) +{ + int polys = 0; + double xMin = BBOX_XMIN(bbox); + double yMin = BBOX_YMIN(bbox); + double zMin = BBOX_ZMIN(bbox); + + double xMax = BBOX_XMAX(bbox); + double yMax = BBOX_YMAX(bbox); + double zMax = BBOX_ZMAX(bbox); + + glFrontFace(GL_CCW); + if (wire) glLineWidth(5.0); + + /* back */ + glBegin(wire ? GL_LINE_LOOP : GL_QUADS); + glColor3f(0.0, 0.0, .15); + glVertex3f(xMin, yMin, zMin); + glVertex3f(xMax, yMin, zMin); + glVertex3f(xMax, yMax, zMin); + glVertex3f(xMin, yMax, zMin); + polys++; + glEnd(); + + /* left */ + glBegin(wire ? GL_LINE_LOOP : GL_QUADS); + glColor3f(0.0, 0.0, .2); + glVertex3f(xMin, yMin, zMax); + glVertex3f(xMin, yMin, zMin); + glVertex3f(xMin, yMax, zMin); + glVertex3f(xMin, yMax, zMax); + polys++; + glEnd(); + + /* right */ + glBegin(wire ? GL_LINE_LOOP : GL_QUADS); + glColor3f(0.0, 0.0, .2); + glVertex3f(xMax, yMin, zMin); + glVertex3f(xMax, yMin, zMax); + glVertex3f(xMax, yMax, zMax); + glVertex3f(xMax, yMax, zMin); + polys++; + glEnd(); + + /* top */ + glBegin(wire ? GL_LINE_LOOP : GL_QUADS); + glColor3f(0.0, 0.0, .1); + glVertex3f(xMax, yMax, zMax); + glVertex3f(xMin, yMax, zMax); + glVertex3f(xMin, yMax, zMin); + glVertex3f(xMax, yMax, zMin); + polys++; + glEnd(); + + /* bottom */ + glBegin(wire ? GL_LINE_LOOP : GL_QUADS); + glColor3f(0.0, 0.0, .3); + glVertex3f(xMin, yMin, zMax); + glVertex3f(xMax, yMin, zMax); + glVertex3f(xMax, yMin, zMin); + glVertex3f(xMin, yMin, zMin); + polys++; + glEnd(); + + if (wire) glLineWidth(1.0); + + return polys; +} + +int +glschool_createBBoxList(BBox *bbox, GLuint *bboxList, int wire) +{ + int polys = 0; + *bboxList = glGenLists(1); + glNewList(*bboxList, GL_COMPILE); + polys = glschool_drawBoundingBox(bbox, wire); + glEndList(); + return polys; +} + +void +glschool_createDrawLists(BBox *bbox, GLuint *bboxList, GLuint *goalList, GLuint *fishList, int *fish_polys, int *box_polys, int wire) +{ + + int faces = 16; + + *box_polys = 0; + *fish_polys = 0; + + *box_polys += glschool_createBBoxList(bbox, bboxList, wire); + + *box_polys = 0; + *fish_polys = 0; + + *goalList = glGenLists(1); + glNewList(*goalList, GL_COMPILE); + glScalef (5, 5, 5); + *box_polys += unit_sphere (10, 10, wire); + glEndList(); + + *fishList = glGenLists(1); + glNewList(*fishList, GL_COMPILE); + *fish_polys += cone (0, 0, 0, + 0, 0, 10, + 2, 0, + faces, True, (faces <= 3), /* cap */ + wire); + glTranslatef (0, 0, -0.3); + glScalef (2, 2, 2); + glRotatef (90, 1, 0, 0); + if (faces > 3) + *fish_polys += unit_sphere (faces, faces, wire); + glEndList(); +} + + +void +glschool_initLights(void) +{ + GLfloat amb[4] = {0.1, 0.1, 0.1, 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] = {0.0, 50.0, -50.0, 1.0}; + + glMatrixMode(GL_MODELVIEW); + glLoadIdentity(); + + glLightfv(GL_LIGHT0, GL_POSITION, pos); + glLightfv(GL_LIGHT0, GL_AMBIENT, amb); + glLightfv(GL_LIGHT0, GL_DIFFUSE, dif); + glLightfv(GL_LIGHT0, GL_SPECULAR, spc); + + glEnable(GL_LIGHT0); + glEnable(GL_LIGHTING); +} + +void +glschool_initFog(void) +{ + GLfloat fog[4] = {0.0, 0.0, 0.15, 1.0}; + + glEnable(GL_FOG); + glFogi(GL_FOG_MODE, GL_EXP2); + glFogfv(GL_FOG_COLOR, fog); + glFogf(GL_FOG_DENSITY, .0025); + glFogf(GL_FOG_START, -100); +} + +void +glschool_initGLEnv(Bool doFog) +{ + GLfloat spc[4] = {1.0, 1.0, 1.0, 1.0}; + + glClearDepth(1.0); + glDepthFunc(GL_LESS); + + glEnable(GL_COLOR_MATERIAL); + glMateriali(GL_FRONT, GL_SHININESS, 128); + glMaterialfv(GL_FRONT, GL_SPECULAR, spc); + glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, spc); + + glEnable(GL_NORMALIZE); + glEnable(GL_DEPTH_TEST); + glShadeModel(GL_SMOOTH); + glEnable(GL_CULL_FACE); + + glschool_initLights(); + if (doFog) glschool_initFog(); +} + +void +glschool_reshape(int width, int height) +{ + GLfloat h = (GLfloat) width / (GLfloat) height; + + glViewport (0, 0, (GLint) width, (GLint) height); + + glMatrixMode(GL_PROJECTION); + glLoadIdentity(); + gluPerspective(60.0, h, 0.1, 451.0); + + glMatrixMode(GL_MODELVIEW); + glLoadIdentity(); +} + +void +glschool_getColorVect(XColor *colors, int index, double *colorVect) +{ + colorVect[0] = colors[index].red / 65535.0; + colorVect[1] = colors[index].green / 65535.0; + colorVect[2] = colors[index].blue / 65535.0; +} + +void +glschool_drawSchool(XColor *colors, School *s, + GLuint bboxList, GLuint goalList, GLuint fishList, + int rotCounter, Bool drawGoal_p, Bool drawBBox_p, + int fish_polys, int box_polys, unsigned long *polys) +{ + double xVect[3]; + double colorVect[3]; + int i = 0; + double rotTheta = 0.0; + double colTheta = 0.0; + Fish *f = (Fish *)0; + int nFish = SCHOOL_NFISH(s); + Fish *theFishes = SCHOOL_FISHES(s); + + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + + glMatrixMode(GL_MODELVIEW); + glLoadIdentity(); + + if (drawBBox_p) { + glDisable(GL_LIGHTING); + glCallList(bboxList); + glEnable(GL_LIGHTING); + *polys += box_polys; + } + + if (drawGoal_p) glschool_drawGoal(SCHOOL_GOAL(s), goalList); + + for(i = 0, f = theFishes; i < nFish; i++, f++) { + colTheta = glschool_computeNormalAndThetaToPlusZ(FISH_AVGVEL(f), xVect); + rotTheta = glschool_computeNormalAndThetaToPlusZ(FISH_VEL(f), xVect); + + if (FISH_IAVGVEL(f,2) < 0.0) colTheta = 180.0 - colTheta; + if (FISH_VZ(f) < 0.0) rotTheta = 180.0 - rotTheta; + + glschool_getColorVect(colors, (int)(colTheta+240)%360, colorVect); + glColor3f(colorVect[0], colorVect[1], colorVect[2]); + + glPushMatrix(); + { + glTranslatef(FISH_X(f), FISH_Y(f), FISH_Z(f)); + glRotatef(180.0+rotTheta, xVect[0], xVect[1], xVect[2]); + glCallList(fishList); + *polys += fish_polys; + } + glPopMatrix(); + } + + glFinish(); +} diff --git a/hacks/glx/glschool_gl.h b/hacks/glx/glschool_gl.h new file mode 100644 index 00000000..ac311f7d --- /dev/null +++ b/hacks/glx/glschool_gl.h @@ -0,0 +1,47 @@ +/* glschool_gl.h, Copyright (c) 2005-2006 David C. Lambert + * + * 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. + */ +#ifndef __GLSCHOOL_GL_H__ +#define __GLSCHOOL_GL_H__ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif /* HAVE_CONFIG_H */ + +#ifdef HAVE_COCOA +# include "jwxyz.h" +# ifndef HAVE_JWZGLES +# include +# endif +#else +# include +# include +# include +#endif + +#ifdef HAVE_JWZGLES +# include "jwzgles.h" +#endif /* HAVE_JWZGLES */ + +#include "glschool_alg.h" + +extern void glschool_initFog(void); +extern void glschool_initGLEnv(Bool); +extern void glschool_initLights(void); +extern void glschool_reshape(int, int); +extern void glschool_drawGoal(double *, GLuint); +extern void glschool_getColorVect(XColor *, int, double *); +extern int glschool_drawBoundingBox(BBox *, Bool); +extern int glschool_createBBoxList(BBox *, GLuint *, int); +extern void glschool_createDrawLists(BBox *, GLuint *, GLuint *, GLuint *, int *, int *, Bool); +extern void glschool_drawSchool(XColor *, School *, GLuint, GLuint, GLuint, int, Bool, Bool, + int, int, unsigned long *); + +#endif /* __GLSCHOOL_GL_H__ */ diff --git a/hacks/glx/glslideshow.c b/hacks/glx/glslideshow.c new file mode 100644 index 00000000..5b48a383 --- /dev/null +++ b/hacks/glx/glslideshow.c @@ -0,0 +1,1260 @@ +/* glslideshow, Copyright (c) 2003-2012 Jamie Zawinski + * Loads a sequence of images and smoothly pans around them; crossfades + * when loading new images. + * + * Originally written by Mike Oliphant (c) 2002, 2003. + * Rewritten by jwz, 21-Jun-2003. + * Rewritten by jwz again, 6-Feb-2005. + * + * 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. + * + ***************************************************************************** + * + * TODO: + * + * - When a new image is loaded, there is a glitch: animation pauses during + * the period when we're loading the image-to-fade-in. On fast (2GHz) + * machines, this stutter is short but noticable (usually around 1/10th + * second.) On slower machines, it can be much more pronounced. + * This turns out to be hard to fix... + * + * Image loading happens in three stages: + * + * 1: Fork a process and run xscreensaver-getimage in the background. + * This writes image data to a server-side X pixmap. + * + * 2: When that completes, a callback informs us that the pixmap is ready. + * We must then download the pixmap data from the server with XGetImage + * (or XShmGetImage.) + * + * 3: Once we have the bits, we must convert them from server-native bitmap + * layout to 32 bit RGBA in client-endianness, to make them usable as + * OpenGL textures. + * + * 4: We must actually construct a texture. + * + * So, the speed of step 1 doesn't really matter, since that happens in + * the background. But steps 2, 3, and 4 happen in *this* process, and + * cause the visible glitch. + * + * Step 2 can't be moved to another process without opening a second + * connection to the X server, which is pretty heavy-weight. (That would + * be possible, though; the other process could open an X connection, + * retrieve the pixmap, and feed it back to us through a pipe or + * something.) + * + * Step 3 might be able to be optimized by coding tuned versions of + * grab-ximage.c:copy_ximage() for the most common depths and bit orders. + * (Or by moving it into the other process along with step 2.) + * + * Step 4 is the hard one, though. It might be possible to speed up this + * step if there is some way to allow two GL processes share texture + * data. Unless, of course, all the time being consumed by step 4 is + * because the graphics pipeline is flooded, in which case, that other + * process would starve the screen anyway. + * + * Is it possible to use a single GLX context in a multithreaded way? + * Or use a second GLX context, but allow the two contexts to share data? + * I can't find any documentation about this. + * + * How does Apple do this with their MacOSX slideshow screen saver? + * Perhaps it's easier for them because their OpenGL libraries have + * thread support at a lower level? + */ + +#define DEFAULTS "*delay: 20000 \n" \ + "*wireframe: False \n" \ + "*showFPS: False \n" \ + "*fpsSolid: True \n" \ + "*useSHM: True \n" \ + "*titleFont: -*-helvetica-medium-r-normal-*-180-*\n" \ + "*desktopGrabber: xscreensaver-getimage -no-desktop %s\n" \ + "*grabDesktopImages: False \n" \ + "*chooseRandomImages: True \n" + +# define refresh_slideshow 0 +# define release_slideshow 0 +# include "xlockmore.h" + +#undef countof +#define countof(x) (sizeof((x))/sizeof((*x))) + +#ifdef USE_GL + + +# define DEF_FADE_DURATION "2" +# define DEF_PAN_DURATION "6" +# define DEF_IMAGE_DURATION "30" +# define DEF_ZOOM "75" +# define DEF_FPS_CUTOFF "5" +# define DEF_TITLES "False" +# define DEF_LETTERBOX "True" +# define DEF_DEBUG "False" +# define DEF_MIPMAP "True" + +#include "grab-ximage.h" +#include "glxfonts.h" + +typedef struct { + double x, y, w, h; +} rect; + +typedef struct { + ModeInfo *mi; + int id; /* unique number for debugging */ + char *title; /* the filename of this image */ + int w, h; /* size in pixels of the image */ + int tw, th; /* size in pixels of the texture */ + XRectangle geom; /* where in the image the bits are */ + Bool loaded_p; /* whether the image has finished loading */ + Bool used_p; /* whether the image has yet appeared + on screen */ + GLuint texid; /* which texture contains the image */ + int refcount; /* how many sprites refer to this image */ +} image; + + +typedef enum { NEW, IN, FULL, OUT, DEAD } sprite_state; + +typedef struct { + int id; /* unique number for debugging */ + image *img; /* which image this animation displays */ + GLfloat opacity; /* how to render it */ + double start_time; /* when this animation began */ + rect from, to, current; /* the journey this image is taking */ + sprite_state state; /* the state we're in right now */ + sprite_state prev_state; /* the state we were in previously */ + double state_time; /* time of last state change */ + int frame_count; /* frames since last state change */ +} sprite; + + +typedef struct { + GLXContext *glx_context; + int nimages; /* how many images are loaded or loading now */ + image *images[10]; /* pointers to the images */ + + int nsprites; /* how many sprites are animating right now */ + sprite *sprites[10]; /* pointers to the live sprites */ + + double now; /* current time in seconds */ + double dawn_of_time; /* when the program launched */ + double image_load_time; /* time when we last loaded a new image */ + double prev_frame_time; /* time when we last drew a frame */ + + Bool awaiting_first_image_p; /* Early in startup: nothing to display yet */ + Bool redisplay_needed_p; /* Sometimes we can get away with not + re-painting. Tick this if a redisplay + is required. */ + Bool change_now_p; /* Set when the user clicks to ask for a new + image right now. */ + + GLfloat fps; /* approximate frame rate we're achieving */ + GLfloat theoretical_fps; /* maximum frame rate that might be possible */ + Bool checked_fps_p; /* Whether we have checked for a low + frame rate. */ + +# ifdef HAVE_GLBITMAP + XFontStruct *xfont; /* for printing image file names */ + GLuint font_dlist; +# else + texture_font_data *font_data; +# endif + + int sprite_id, image_id; /* debugging id counters */ + + double time_elapsed; + int frames_elapsed; + +} slideshow_state; + +static slideshow_state *sss = NULL; + + +/* Command-line arguments + */ +static int fade_seconds; /* Duration in seconds of fade transitions. + If 0, jump-cut instead of fading. */ +static int pan_seconds; /* Duration of each pan through an image. */ +static int image_seconds; /* How many seconds until loading a new image. */ +static int zoom; /* How far in to zoom when panning, in percent of + image size: that is, 75 means "when zoomed all + the way in, 75% of the image will be visible." + */ +static int fps_cutoff; /* If the frame-rate falls below this, turn off + zooming.*/ +static Bool letterbox_p; /* When a loaded image is not the same aspect + ratio as the window, whether to display black + bars. + */ +static Bool mipmap_p; /* Use mipmaps instead of single textures. */ +static Bool do_titles; /* Display image titles. */ +static Bool debug_p; /* Be loud and do weird things. */ + + +static XrmOptionDescRec opts[] = { + {"-fade", ".fadeDuration", XrmoptionSepArg, 0 }, + {"-pan", ".panDuration", XrmoptionSepArg, 0 }, + {"-duration", ".imageDuration", XrmoptionSepArg, 0 }, + {"-zoom", ".zoom", XrmoptionSepArg, 0 }, + {"-cutoff", ".FPScutoff", XrmoptionSepArg, 0 }, + {"-titles", ".titles", XrmoptionNoArg, "True" }, + {"-letterbox", ".letterbox", XrmoptionNoArg, "True" }, + {"-no-letterbox", ".letterbox", XrmoptionNoArg, "False" }, + {"-clip", ".letterbox", XrmoptionNoArg, "False" }, + {"-mipmaps", ".mipmap", XrmoptionNoArg, "True" }, + {"-no-mipmaps", ".mipmap", XrmoptionNoArg, "False" }, + {"-debug", ".debug", XrmoptionNoArg, "True" }, +}; + +static argtype vars[] = { + { &fade_seconds, "fadeDuration", "FadeDuration", DEF_FADE_DURATION, t_Int}, + { &pan_seconds, "panDuration", "PanDuration", DEF_PAN_DURATION, t_Int}, + { &image_seconds, "imageDuration","ImageDuration",DEF_IMAGE_DURATION, t_Int}, + { &zoom, "zoom", "Zoom", DEF_ZOOM, t_Int}, + { &mipmap_p, "mipmap", "Mipmap", DEF_MIPMAP, t_Bool}, + { &letterbox_p, "letterbox", "Letterbox", DEF_LETTERBOX, t_Bool}, + { &fps_cutoff, "FPScutoff", "FPSCutoff", DEF_FPS_CUTOFF, t_Int}, + { &debug_p, "debug", "Debug", DEF_DEBUG, t_Bool}, + { &do_titles, "titles", "Titles", DEF_TITLES, t_Bool}, +}; + +ENTRYPOINT ModeSpecOpt slideshow_opts = {countof(opts), opts, countof(vars), vars, NULL}; + + +static const char * +blurb (void) +{ +# ifdef HAVE_COCOA + return "GLSlideshow"; +# else + static char buf[255]; + time_t now = time ((time_t *) 0); + char *ct = (char *) ctime (&now); + int n = strlen(progname); + if (n > 100) n = 99; + strncpy(buf, progname, n); + buf[n++] = ':'; + buf[n++] = ' '; + strncpy(buf+n, ct+11, 8); + strcpy(buf+n+9, ": "); + return buf; +# endif +} + + +/* Returns the current time in seconds as a double. + */ +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 void image_loaded_cb (const char *filename, XRectangle *geom, + int image_width, int image_height, + int texture_width, int texture_height, + void *closure); + + +/* Allocate an image structure and start a file loading in the background. + */ +static image * +alloc_image (ModeInfo *mi) +{ + slideshow_state *ss = &sss[MI_SCREEN(mi)]; + int wire = MI_IS_WIREFRAME(mi); + image *img = (image *) calloc (1, sizeof (*img)); + + img->id = ++ss->image_id; + img->loaded_p = False; + img->used_p = False; + img->mi = mi; + + glGenTextures (1, &img->texid); + if (img->texid <= 0) abort(); + + ss->image_load_time = ss->now; + + if (wire) + image_loaded_cb (0, 0, 0, 0, 0, 0, img); + else + load_texture_async (mi->xgwa.screen, mi->window, *ss->glx_context, + 0, 0, mipmap_p, img->texid, image_loaded_cb, img); + + ss->images[ss->nimages++] = img; + if (ss->nimages >= countof(ss->images)) abort(); + + return img; +} + + +/* Callback that tells us that the texture has been loaded. + */ +static void +image_loaded_cb (const char *filename, XRectangle *geom, + int image_width, int image_height, + int texture_width, int texture_height, + void *closure) +{ + image *img = (image *) closure; + ModeInfo *mi = img->mi; + /* slideshow_state *ss = &sss[MI_SCREEN(mi)]; */ + + int wire = MI_IS_WIREFRAME(mi); + + if (wire) + { + img->w = MI_WIDTH (mi) * (0.5 + frand (1.0)); + img->h = MI_HEIGHT (mi); + img->geom.width = img->w; + img->geom.height = img->h; + goto DONE; + } + + if (image_width == 0 || image_height == 0) + exit (1); + + glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, + mipmap_p ? GL_LINEAR_MIPMAP_LINEAR : GL_LINEAR); + + glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); + glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); + + img->w = image_width; + img->h = image_height; + img->tw = texture_width; + img->th = texture_height; + img->geom = *geom; + img->title = (filename ? strdup (filename) : 0); + + /* If the image's width doesn't come back as the width of the screen, + then the image must have been scaled down (due to insufficient + texture memory.) Scale up the coordinates to stretch the image + to fill the window. + */ + if (img->w != MI_WIDTH(mi)) + { + double scale = (double) MI_WIDTH(mi) / img->w; + img->w *= scale; + img->h *= scale; + img->tw *= scale; + img->th *= scale; + img->geom.x *= scale; + img->geom.y *= scale; + img->geom.width *= scale; + img->geom.height *= scale; + } + + /* xscreensaver-getimage returns paths relative to the image directory + now, so leave the sub-directory part in. Unless it's an absolute path. + */ + if (img->title && img->title[0] == '/') + { + /* strip filename to part between last "/" and last ".". */ + char *s = strrchr (img->title, '/'); + if (s) strcpy (img->title, s+1); + s = strrchr (img->title, '.'); + if (s) *s = 0; + } + + if (debug_p) + fprintf (stderr, "%s: loaded img %2d: \"%s\"\n", + blurb(), img->id, (img->title ? img->title : "(null)")); + DONE: + + img->loaded_p = True; +} + + + +/* Free the image and texture, after nobody is referencing it. + */ +static void +destroy_image (ModeInfo *mi, image *img) +{ + slideshow_state *ss = &sss[MI_SCREEN(mi)]; + Bool freed_p = False; + int i; + + if (!img) abort(); + if (!img->loaded_p) abort(); + if (!img->used_p) abort(); + if (img->texid <= 0) abort(); + if (img->refcount != 0) abort(); + + for (i = 0; i < ss->nimages; i++) /* unlink it from the list */ + if (ss->images[i] == img) + { + int j; + for (j = i; j < ss->nimages-1; j++) /* pull remainder forward */ + ss->images[j] = ss->images[j+1]; + ss->images[j] = 0; + ss->nimages--; + freed_p = True; + break; + } + + if (!freed_p) abort(); + + if (debug_p) + fprintf (stderr, "%s: unloaded img %2d: \"%s\"\n", + blurb(), img->id, (img->title ? img->title : "(null)")); + + if (img->title) free (img->title); + glDeleteTextures (1, &img->texid); + free (img); +} + + +/* Return an image to use for a sprite. + If it's time for a new one, get a new one. + Otherwise, use an old one. + Might return 0 if the machine is really slow. + */ +static image * +get_image (ModeInfo *mi) +{ + slideshow_state *ss = &sss[MI_SCREEN(mi)]; + image *img = 0; + double now = ss->now; + Bool want_new_p = (ss->change_now_p || + ss->image_load_time + image_seconds <= now); + image *new_img = 0; + image *old_img = 0; + image *loading_img = 0; + int i; + + for (i = 0; i < ss->nimages; i++) + { + image *img2 = ss->images[i]; + if (!img2) abort(); + if (!img2->loaded_p) + loading_img = img2; + else if (!img2->used_p) + new_img = img2; + else + old_img = img2; + } + + if (want_new_p && new_img) + img = new_img, new_img = 0, ss->change_now_p = False; + else if (old_img) + img = old_img, old_img = 0; + else if (new_img) + img = new_img, new_img = 0, ss->change_now_p = False; + + /* Make sure that there is always one unused image in the pipe. + */ + if (!new_img && !loading_img) + alloc_image (mi); + + return img; +} + + +/* Pick random starting and ending positions for the given sprite. + */ +static void +randomize_sprite (ModeInfo *mi, sprite *sp) +{ + int vp_w = MI_WIDTH(mi); + int vp_h = MI_HEIGHT(mi); + int img_w = sp->img->geom.width; + int img_h = sp->img->geom.height; + int min_w, max_w; + double ratio = (double) img_h / img_w; + + if (letterbox_p) + { + min_w = img_w; + } + else + { + if (img_w < vp_w) + min_w = vp_w; + else + min_w = img_w * (float) vp_h / img_h; + } + + max_w = min_w * 100 / zoom; + + sp->from.w = min_w + frand ((max_w - min_w) * 0.4); + sp->to.w = max_w - frand ((max_w - min_w) * 0.4); + sp->from.h = sp->from.w * ratio; + sp->to.h = sp->to.w * ratio; + + if (zoom == 100) /* only one box, and it is centered */ + { + sp->from.x = (sp->from.w > vp_w + ? -(sp->from.w - vp_w) / 2 + : (vp_w - sp->from.w) / 2); + sp->from.y = (sp->from.h > vp_h + ? -(sp->from.h - vp_h) / 2 + : (vp_h - sp->from.h) / 2); + sp->to = sp->from; + } + else /* position both boxes randomly */ + { + sp->from.x = (sp->from.w > vp_w + ? -frand (sp->from.w - vp_w) + : frand (vp_w - sp->from.w)); + sp->from.y = (sp->from.h > vp_h + ? -frand (sp->from.h - vp_h) + : frand (vp_h - sp->from.h)); + sp->to.x = (sp->to.w > vp_w + ? -frand (sp->to.w - vp_w) + : frand (vp_w - sp->to.w)); + sp->to.y = (sp->to.h > vp_h + ? -frand (sp->to.h - vp_h) + : frand (vp_h - sp->to.h)); + } + + if (random() & 1) + { + rect swap = sp->to; + sp->to = sp->from; + sp->from = swap; + } + + /* Make sure the aspect ratios are within 0.001 of each other. + */ + { + int r1 = 0.5 + (sp->from.w * 1000 / sp->from.h); + int r2 = 0.5 + (sp->to.w * 1000 / sp->to.h); + if (r1 < r2-1 || r1 > r2+1) + { + fprintf (stderr, + "%s: botched aspect: %f x %f (%d) vs %f x %f (%d): %s\n", + progname, + sp->from.w, sp->from.h, r1, + sp->to.w, sp->to.h, r2, + (sp->img->title ? sp->img->title : "[null]")); + abort(); + } + } + + sp->from.x /= vp_w; + sp->from.y /= vp_h; + sp->from.w /= vp_w; + sp->from.h /= vp_h; + sp->to.x /= vp_w; + sp->to.y /= vp_h; + sp->to.w /= vp_w; + sp->to.h /= vp_h; +} + + +/* Allocate a new sprite and start its animation going. + */ +static sprite * +new_sprite (ModeInfo *mi) +{ + slideshow_state *ss = &sss[MI_SCREEN(mi)]; + image *img = get_image (mi); + sprite *sp; + + if (!img) + { + /* Oops, no images yet! The machine is probably hurting bad. + Let's give it some time before thrashing again. */ + usleep (250000); + return 0; + } + + sp = (sprite *) calloc (1, sizeof (*sp)); + sp->id = ++ss->sprite_id; + sp->start_time = ss->now; + sp->state_time = sp->start_time; + sp->state = sp->prev_state = NEW; + sp->img = img; + + sp->img->refcount++; + sp->img->used_p = True; + + ss->sprites[ss->nsprites++] = sp; + if (ss->nsprites >= countof(ss->sprites)) abort(); + + randomize_sprite (mi, sp); + + return sp; +} + + +/* Free the given sprite, and decrement the reference count on its image. + */ +static void +destroy_sprite (ModeInfo *mi, sprite *sp) +{ + slideshow_state *ss = &sss[MI_SCREEN(mi)]; + Bool freed_p = False; + image *img; + int i; + + if (!sp) abort(); + if (sp->state != DEAD) abort(); + img = sp->img; + if (!img) abort(); + if (!img->loaded_p) abort(); + if (!img->used_p) abort(); + if (img->refcount <= 0) abort(); + + for (i = 0; i < ss->nsprites; i++) /* unlink it from the list */ + if (ss->sprites[i] == sp) + { + int j; + for (j = i; j < ss->nsprites-1; j++) /* pull remainder forward */ + ss->sprites[j] = ss->sprites[j+1]; + ss->sprites[j] = 0; + ss->nsprites--; + freed_p = True; + break; + } + + if (!freed_p) abort(); + free (sp); + sp = 0; + + img->refcount--; + if (img->refcount < 0) abort(); + if (img->refcount == 0) + destroy_image (mi, img); +} + + +/* Updates the sprite for the current frame of the animation based on + its creation time compared to the current wall clock. + */ +static void +tick_sprite (ModeInfo *mi, sprite *sp) +{ + slideshow_state *ss = &sss[MI_SCREEN(mi)]; + image *img = sp->img; + double now = ss->now; + double secs; + double ratio; + rect prev_rect = sp->current; + GLfloat prev_opacity = sp->opacity; + + if (! sp->img) abort(); + if (! img->loaded_p) abort(); + + secs = now - sp->start_time; + ratio = secs / (pan_seconds + fade_seconds); + if (ratio > 1) ratio = 1; + + sp->current.x = sp->from.x + ratio * (sp->to.x - sp->from.x); + sp->current.y = sp->from.y + ratio * (sp->to.y - sp->from.y); + sp->current.w = sp->from.w + ratio * (sp->to.w - sp->from.w); + sp->current.h = sp->from.h + ratio * (sp->to.h - sp->from.h); + + sp->prev_state = sp->state; + + if (secs < fade_seconds) + { + sp->state = IN; + sp->opacity = secs / (GLfloat) fade_seconds; + } + else if (secs < pan_seconds) + { + sp->state = FULL; + sp->opacity = 1; + } + else if (secs < pan_seconds + fade_seconds) + { + sp->state = OUT; + sp->opacity = 1 - ((secs - pan_seconds) / (GLfloat) fade_seconds); + } + else + { + sp->state = DEAD; + sp->opacity = 0; + } + + if (sp->state != sp->prev_state && + (sp->prev_state == IN || + sp->prev_state == FULL)) + { + double secs = now - sp->state_time; + + if (debug_p) + fprintf (stderr, + "%s: %s %3d frames %2.0f sec %5.1f fps (%.1f fps?)\n", + blurb(), + (sp->prev_state == IN ? "fade" : "pan "), + sp->frame_count, + secs, + sp->frame_count / secs, + ss->theoretical_fps); + + sp->state_time = now; + sp->frame_count = 0; + } + + sp->frame_count++; + + if (sp->state != DEAD && + (prev_rect.x != sp->current.x || + prev_rect.y != sp->current.y || + prev_rect.w != sp->current.w || + prev_rect.h != sp->current.h || + prev_opacity != sp->opacity)) + ss->redisplay_needed_p = True; +} + + +/* Draw the given sprite at the phase of its animation dictated by + its creation time compared to the current wall clock. + */ +static void +draw_sprite (ModeInfo *mi, sprite *sp) +{ + slideshow_state *ss = &sss[MI_SCREEN(mi)]; + int wire = MI_IS_WIREFRAME(mi); + image *img = sp->img; + + if (! sp->img) abort(); + if (! img->loaded_p) abort(); + + glPushMatrix(); + { + glTranslatef (sp->current.x, sp->current.y, 0); + glScalef (sp->current.w, sp->current.h, 1); + + if (wire) /* Draw a grid inside the box */ + { + GLfloat dy = 0.1; + GLfloat dx = dy * img->w / img->h; + GLfloat x, y; + + if (sp->id & 1) + glColor4f (sp->opacity, 0, 0, 1); + else + glColor4f (0, 0, sp->opacity, 1); + + glBegin(GL_LINES); + glVertex3f (0, 0, 0); glVertex3f (1, 1, 0); + glVertex3f (1, 0, 0); glVertex3f (0, 1, 0); + + for (y = 0; y < 1+dy; y += dy) + { + GLfloat yy = (y > 1 ? 1 : y); + for (x = 0.5; x < 1+dx; x += dx) + { + GLfloat xx = (x > 1 ? 1 : x); + glVertex3f (0, xx, 0); glVertex3f (1, xx, 0); + glVertex3f (yy, 0, 0); glVertex3f (yy, 1, 0); + } + for (x = 0.5; x > -dx; x -= dx) + { + GLfloat xx = (x < 0 ? 0 : x); + glVertex3f (0, xx, 0); glVertex3f (1, xx, 0); + glVertex3f (yy, 0, 0); glVertex3f (yy, 1, 0); + } + } + glEnd(); + } + else /* Draw the texture quad */ + { + GLfloat texw = img->geom.width / (GLfloat) img->tw; + GLfloat texh = img->geom.height / (GLfloat) img->th; + GLfloat texx1 = img->geom.x / (GLfloat) img->tw; + GLfloat texy1 = img->geom.y / (GLfloat) img->th; + GLfloat texx2 = texx1 + texw; + GLfloat texy2 = texy1 + texh; + + glBindTexture (GL_TEXTURE_2D, img->texid); + glColor4f (1, 1, 1, sp->opacity); + glNormal3f (0, 0, 1); + glBegin (GL_QUADS); + glTexCoord2f (texx1, texy2); glVertex3f (0, 0, 0); + glTexCoord2f (texx2, texy2); glVertex3f (1, 0, 0); + glTexCoord2f (texx2, texy1); glVertex3f (1, 1, 0); + glTexCoord2f (texx1, texy1); glVertex3f (0, 1, 0); + glEnd(); + + if (debug_p) /* Draw a border around the image */ + { + if (!wire) glDisable (GL_TEXTURE_2D); + + if (sp->id & 1) + glColor4f (sp->opacity, 0, 0, 1); + else + glColor4f (0, 0, sp->opacity, 1); + + glBegin (GL_LINE_LOOP); + glVertex3f (0, 0, 0); + glVertex3f (0, 1, 0); + glVertex3f (1, 1, 0); + glVertex3f (1, 0, 0); + glEnd(); + + if (!wire) glEnable (GL_TEXTURE_2D); + } + } + + + if (do_titles && + img->title && *img->title) + { + int x = 10; + int y = mi->xgwa.height - 10; + glColor4f (0, 0, 0, sp->opacity); /* cheap-assed dropshadow */ + print_gl_string (mi->dpy, +# ifdef HAVE_GLBITMAP + ss->xfont, ss->font_dlist, +# else + ss->font_data, +# endif + mi->xgwa.width, mi->xgwa.height, x, y, + img->title, False); + x++; y++; + glColor4f (1, 1, 1, sp->opacity); + print_gl_string (mi->dpy, +# ifdef HAVE_GLBITMAP + ss->xfont, ss->font_dlist, +# else + ss->font_data, +# endif + mi->xgwa.width, mi->xgwa.height, x, y, + img->title, False); + } + } + glPopMatrix(); + + if (debug_p) + { + if (!wire) glDisable (GL_TEXTURE_2D); + + if (sp->id & 1) + glColor4f (1, 0, 0, 1); + else + glColor4f (0, 0, 1, 1); + + /* Draw the "from" and "to" boxes + */ + glBegin (GL_LINE_LOOP); + glVertex3f (sp->from.x, sp->from.y, 0); + glVertex3f (sp->from.x + sp->from.w, sp->from.y, 0); + glVertex3f (sp->from.x + sp->from.w, sp->from.y + sp->from.h, 0); + glVertex3f (sp->from.x, sp->from.y + sp->from.h, 0); + glEnd(); + + glBegin (GL_LINE_LOOP); + glVertex3f (sp->to.x, sp->to.y, 0); + glVertex3f (sp->to.x + sp->to.w, sp->to.y, 0); + glVertex3f (sp->to.x + sp->to.w, sp->to.y + sp->to.h, 0); + glVertex3f (sp->to.x, sp->to.y + sp->to.h, 0); + glEnd(); + + if (!wire) glEnable (GL_TEXTURE_2D); + } +} + + +static void +tick_sprites (ModeInfo *mi) +{ + slideshow_state *ss = &sss[MI_SCREEN(mi)]; + int i; + for (i = 0; i < ss->nsprites; i++) + tick_sprite (mi, ss->sprites[i]); +} + + +static void +draw_sprites (ModeInfo *mi) +{ + slideshow_state *ss = &sss[MI_SCREEN(mi)]; + int i; + + glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + + glPushMatrix(); + + { + GLfloat rot = current_device_rotation(); + glTranslatef (0.5, 0.5, 0); + glRotatef(rot, 0, 0, 1); + if ((rot > 45 && rot < 135) || + (rot < -45 && rot > -135)) + { + GLfloat s = MI_WIDTH(mi) / (GLfloat) MI_HEIGHT(mi); + glScalef (s, 1/s, 1); + } + glTranslatef (-0.5, -0.5, 0); + } + + for (i = 0; i < ss->nsprites; i++) + draw_sprite (mi, ss->sprites[i]); + glPopMatrix(); + + if (debug_p) /* draw a white box (the "screen") */ + { + int wire = MI_IS_WIREFRAME(mi); + + if (!wire) glDisable (GL_TEXTURE_2D); + + glColor4f (1, 1, 1, 1); + glBegin (GL_LINE_LOOP); + glVertex3f (0, 0, 0); + glVertex3f (0, 1, 0); + glVertex3f (1, 1, 0); + glVertex3f (1, 0, 0); + glEnd(); + + if (!wire) glEnable (GL_TEXTURE_2D); + } +} + + +ENTRYPOINT void +reshape_slideshow (ModeInfo *mi, int width, int height) +{ + slideshow_state *ss = &sss[MI_SCREEN(mi)]; + GLfloat s; + glViewport (0, 0, width, height); + glMatrixMode (GL_PROJECTION); + glLoadIdentity(); + glMatrixMode (GL_MODELVIEW); + glLoadIdentity(); + + s = 2; + + if (debug_p) + { + s *= (zoom / 100.0) * 0.75; + if (s < 0.1) s = 0.1; + } + + glScalef (s, s, s); + glTranslatef (-0.5, -0.5, 0); + + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + + ss->redisplay_needed_p = True; +} + + +ENTRYPOINT Bool +slideshow_handle_event (ModeInfo *mi, XEvent *event) +{ + slideshow_state *ss = &sss[MI_SCREEN(mi)]; + + if (event->xany.type == ButtonPress && + event->xbutton.button == Button1) + { + ss->change_now_p = True; + return True; + } + else if (event->xany.type == KeyPress) + { + KeySym keysym; + char c = 0; + XLookupString (&event->xkey, &c, 1, &keysym, 0); + if (c == ' ' || c == '\r' || c == '\n' || c == '\t') + { + ss->change_now_p = True; + return True; + } + } + else if (event->xany.type == Expose || + event->xany.type == GraphicsExpose || + event->xany.type == VisibilityNotify) + { + ss->redisplay_needed_p = True; + if (debug_p) + fprintf (stderr, "%s: exposure\n", blurb()); + return False; + } + + return False; +} + + +/* Do some sanity checking on various user-supplied values, and make + sure they are all internally consistent. + */ +static void +sanity_check (ModeInfo *mi) +{ + if (zoom < 1) zoom = 1; /* zoom is a positive percentage */ + else if (zoom > 100) zoom = 100; + + if (zoom == 100) /* with no zooming, there is no panning */ + pan_seconds = 0; + + if (pan_seconds < fade_seconds) /* pan is inclusive of fade */ + pan_seconds = fade_seconds; + + if (pan_seconds == 0) /* no zero-length cycles, please... */ + pan_seconds = 1; + + if (image_seconds < pan_seconds) /* we only change images at fade-time */ + image_seconds = pan_seconds; + + /* If we're not panning/zooming within the image, then there's no point + in crossfading the image with itself -- only do crossfades when changing + to a new image. */ + if (zoom == 100 && pan_seconds < image_seconds) + pan_seconds = image_seconds; + + /* No need to use mipmaps if we're not changing the image size much */ + if (zoom >= 80) mipmap_p = False; + + if (fps_cutoff < 0) fps_cutoff = 0; + else if (fps_cutoff > 30) fps_cutoff = 30; +} + + +static void +check_fps (ModeInfo *mi) +{ +#ifndef HAVE_COCOA /* always assume Cocoa is fast enough */ + + slideshow_state *ss = &sss[MI_SCREEN(mi)]; + + double start_time, end_time, wall_elapsed, frame_duration, fps; + int i; + + start_time = ss->now; + end_time = double_time(); + frame_duration = end_time - start_time; /* time spent drawing this frame */ + ss->time_elapsed += frame_duration; /* time spent drawing all frames */ + ss->frames_elapsed++; + + wall_elapsed = end_time - ss->dawn_of_time; + fps = ss->frames_elapsed / ss->time_elapsed; + ss->theoretical_fps = fps; + + if (ss->checked_fps_p) return; + + if (wall_elapsed <= 8) /* too early to be sure */ + return; + + ss->checked_fps_p = True; + + if (fps >= fps_cutoff) + { + if (debug_p) + fprintf (stderr, + "%s: %.1f fps is fast enough (with %d frames in %.1f secs)\n", + blurb(), fps, ss->frames_elapsed, wall_elapsed); + return; + } + + fprintf (stderr, + "%s: only %.1f fps! Turning off pan/fade to compensate...\n", + blurb(), fps); + zoom = 100; + fade_seconds = 0; + + sanity_check (mi); + + for (i = 0; i < ss->nsprites; i++) + { + sprite *sp = ss->sprites[i]; + randomize_sprite (mi, sp); + sp->state = FULL; + } + + ss->redisplay_needed_p = True; + + /* Need this in case zoom changed. */ + reshape_slideshow (mi, mi->xgwa.width, mi->xgwa.height); +#endif /* HAVE_COCOA */ +} + + +/* Kludge to add "-v" to invocation of "xscreensaver-getimage" in -debug mode + */ +static void +hack_resources (void) +{ +#if 0 + char *res = "desktopGrabber"; + char *val = get_string_resource (res, "DesktopGrabber"); + char buf1[255]; + char buf2[255]; + XrmValue value; + sprintf (buf1, "%.100s.%.100s", progclass, res); + sprintf (buf2, "%.200s -v", val); + value.addr = buf2; + value.size = strlen(buf2); + XrmPutResource (&db, buf1, "String", &value); +#endif +} + + +ENTRYPOINT void +init_slideshow (ModeInfo *mi) +{ + int screen = MI_SCREEN(mi); + slideshow_state *ss; + int wire = MI_IS_WIREFRAME(mi); + + if (sss == NULL) { + if ((sss = (slideshow_state *) + calloc (MI_NUM_SCREENS(mi), sizeof(slideshow_state))) == NULL) + return; + } + ss = &sss[screen]; + + if ((ss->glx_context = init_GL(mi)) != NULL) { + reshape_slideshow (mi, MI_WIDTH(mi), MI_HEIGHT(mi)); + } else { + MI_CLEARWINDOW(mi); + } + + if (debug_p) + fprintf (stderr, "%s: pan: %d; fade: %d; img: %d; zoom: %d%%\n", + blurb(), pan_seconds, fade_seconds, image_seconds, zoom); + + sanity_check(mi); + + if (debug_p) + fprintf (stderr, "%s: pan: %d; fade: %d; img: %d; zoom: %d%%\n\n", + blurb(), pan_seconds, fade_seconds, image_seconds, zoom); + + glDisable (GL_LIGHTING); + glDisable (GL_DEPTH_TEST); + glDepthMask (GL_FALSE); + glEnable (GL_CULL_FACE); + glCullFace (GL_BACK); + + if (! wire) + { + glEnable (GL_TEXTURE_2D); + glShadeModel (GL_SMOOTH); + glEnable (GL_BLEND); + glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + } + + if (debug_p) glLineWidth (3); + +#ifdef HAVE_GLBITMAP + load_font (mi->dpy, "titleFont", &ss->xfont, &ss->font_dlist); +#else + ss->font_data = load_texture_font (mi->dpy, "Font"); +#endif + + if (debug_p) + hack_resources(); + + ss->now = double_time(); + ss->dawn_of_time = ss->now; + ss->prev_frame_time = ss->now; + + ss->awaiting_first_image_p = True; + alloc_image (mi); +} + + +ENTRYPOINT void +draw_slideshow (ModeInfo *mi) +{ + slideshow_state *ss = &sss[MI_SCREEN(mi)]; + int i; + + if (!ss->glx_context) + return; + + glXMakeCurrent(MI_DISPLAY(mi), MI_WINDOW(mi), *(ss->glx_context)); + + if (ss->awaiting_first_image_p) + { + image *img = ss->images[0]; + if (!img) abort(); + if (!img->loaded_p) + return; + + ss->awaiting_first_image_p = False; + ss->dawn_of_time = double_time(); + + /* start the very first sprite fading in */ + new_sprite (mi); + } + + ss->now = double_time(); + + /* Each sprite has three states: fading in, full, fading out. + The in/out states overlap like this: + + iiiiiiFFFFFFFFFFFFoooooo . . . . . . . . . . . . . . . . . + . . . . . . . . . iiiiiiFFFFFFFFFFFFoooooo . . . . . . . . + . . . . . . . . . . . . . . . . . . iiiiiiFFFFFFFFFFFFooooo + + So as soon as a sprite goes into the "out" state, we create + a new sprite (in the "in" state.) + */ + + if (ss->nsprites > 2) abort(); + + /* If a sprite is just entering the fade-out state, + then add a new sprite in the fade-in state. + */ + for (i = 0; i < ss->nsprites; i++) + { + sprite *sp = ss->sprites[i]; + if (sp->state != sp->prev_state && + sp->state == (fade_seconds == 0 ? DEAD : OUT)) + new_sprite (mi); + } + + tick_sprites (mi); + + /* Now garbage collect the dead sprites. + */ + for (i = 0; i < ss->nsprites; i++) + { + sprite *sp = ss->sprites[i]; + if (sp->state == DEAD) + { + destroy_sprite (mi, sp); + i--; + } + } + + /* We can only ever end up with no sprites at all if the machine is + being really slow and we hopped states directly from FULL to DEAD + without passing OUT... */ + if (ss->nsprites == 0) + new_sprite (mi); + + if (!ss->redisplay_needed_p) + return; + + if (debug_p && ss->now - ss->prev_frame_time > 1) + fprintf (stderr, "%s: static screen for %.1f secs\n", + blurb(), ss->now - ss->prev_frame_time); + + draw_sprites (mi); + + if (mi->fps_p) do_fps (mi); + + glFinish(); + glXSwapBuffers (MI_DISPLAY (mi), MI_WINDOW(mi)); + ss->prev_frame_time = ss->now; + ss->redisplay_needed_p = False; + check_fps (mi); +} + +XSCREENSAVER_MODULE_2 ("GLSlideshow", glslideshow, slideshow) + +#endif /* USE_GL */ diff --git a/hacks/glx/glslideshow.man b/hacks/glx/glslideshow.man new file mode 100644 index 00000000..4ce46724 --- /dev/null +++ b/hacks/glx/glslideshow.man @@ -0,0 +1,131 @@ +.TH XScreenSaver 1 "" "X Version 11" +.SH NAME +glslideshow - slideshow of images using smooth zooming and fades +.SH SYNOPSIS +.B glslideshow +[\-display \fIhost:display.screen\fP] +[\-visual \fIvisual\fP] +[\-window] +[\-root] +[\-duration \fIseconds\fP] +[\-zoom \fIpercent\fP] +[\-pan \fIseconds\fP] +[\-fade \fIseconds\fP] +[\-titles] +[\-letterbox | \-clip] +[\-delay \fIusecs\fP] +[\-fps] +[\-debug] +[\-wireframe] +[\-cutoff \fIint\fP] +.SH DESCRIPTION +Loads a random sequence of images and smoothly scans and zooms around +in each, fading from pan to pan. + +This program requires a good video card capable of supporting large +textures. + +To specify the directory that images are loaded from, run +.BR xscreensaver-demo (1) +and click on the "Advanced" tab. +.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 \-duration \fIseconds\fP +How long each image will be displayed before loading a new one. +Default 30 seconds. +.TP 8 +.B \-pan \fIseconds\fP +How long each pan-and-zoom should last. Default 6 seconds. + +With the default settings of \fI\-pan 6 \-duration 30\fP, each image +will be displayed five times (30/6), and then a new image will be loaded. +If you want a new image to be loaded at each fade, then set \fI\-pan\fP +and \fI\-duration\fP to the same value. +.TP 8 +.B \-fade \fIseconds\fP +How long each cross-fade between images should last. Default 2 seconds. +If set to 0, then no cross-fading will be done (all transitions +will be jump-cuts.) + +Note that fades are included in the pan time, so \fI\-fade\fP cannot +be larger than \fI\-pan\fP. +.TP 8 +.B \-zoom \fInumber\fP +Amount to zoom and pan as a percentage. Default: 75, meaning that +75% or more of each image will always be visible. If set to 100%, +then the images will always fill the screen, and no panning or +zooming will occur. (Images will still smoothly fade from one +to another if \fI\-fade\fP is non-zero.) +.TP 8 +.B \-titles +Whether to print the file name of the current image in the upper left corner. +.TP 8 +.B \-letterbox +In "letterbox" mode, when an image is not the same aspect ratio as the screen, +black bars will appear at the top/bottom or left/right so that the whole +image can be displayed. This is the default. +.TP 8 +.B \-clip +In "clip" mode, when an image is not the same aspect ratio as the screen, +we will zoom in further until the image takes up the whole screen. +This is the opposite of \fI\-letterbox\fP. +.TP 8 +.B \-delay \fInumber\fP +Per-frame delay, in microseconds. Default: 20000 (0.02 seconds.). +.TP 8 +.B \-fps +Display the current frame rate, CPU load, and polygon count. +.TP 8 +.B \-cutoff \fInumber\fP +If the frame rate we are achieving is lower than this, then panning, +fading, and zooming will be disabled. Default 5 FPS. + +The idea here is that if your machine can't maintain a decent frame +rate, then it must not have fast 3D hardware, so we might as well +behave in a simpler manner. Set this to 0 to disable this check. +.TP 8 +.B \-debug +Prints debugging info to stderr. +.TP 8 +.B \-wireframe +Another debug mode. +.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-demo (1), +.BR xscreensaver-getimage (1), +.BR xscreensaver (1), +.BR carousel (MANSUFFIX) +.BR photopile (MANSUFFIX) +.SH COPYRIGHT +Copyright \(co 2003-2005 by Jamie Zawinski, based on an earlier version +that was +Copyright \(co 2002 by Mike Oliphant. + +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 and Mike Oliphant. diff --git a/hacks/glx/glsnake.c b/hacks/glx/glsnake.c new file mode 100644 index 00000000..4d13a932 --- /dev/null +++ b/hacks/glx/glsnake.c @@ -0,0 +1,2694 @@ +/* glsnake.c - OpenGL imitation of Rubik's Snake + * + * (c) 2001-2005 Jamie Wilkinson + * (c) 2001-2003 Andrew Bennetts + * (c) 2001-2003 Peter Aylett + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +/* HAVE_GLUT defined if we're building a standalone glsnake, + * and not defined if we're building as an xscreensaver hack */ +#ifdef HAVE_GLUT +# include +#else +# ifdef HAVE_COCOA +# define HAVE_GETTIMEOFDAY +# else +# include +# include +# endif +#endif + +#ifdef HAVE_JWZGLES +# include "jwzgles.h" +#endif /* HAVE_JWZGLES */ + +#ifdef STANDALONE +# include "xlockmoreI.h" +#endif + +#include +#include +#include +#include + +/* angles */ +#define ZERO 0.0 +#define LEFT 90.0 +#define PIN 180.0 +#define RIGHT 270.0 + +#ifdef HAVE_GETTIMEOFDAY +# ifdef GETTIMEOFDAY_TWO_ARGS + +# include +# include + typedef struct timeval snaketime; +# define GETSECS(t) ((t).tv_sec) +# define GETMSECS(t) ((t).tv_usec/1000) + +# else /* !GETTIMEOFDAY_TWO_ARGS */ + +# include +# include + typedef struct timeval snaketime; +# define GETSECS(t) ((t).tv_sec) +# define GETMSECS(t) ((t).tv_usec/1000) + +# endif /* GETTIMEOFDAY_TWO_ARGS */ + +#else /* !HAVE_GETTIMEOFDAY */ +# ifdef HAVE_FTIME + +# include + typedef struct timeb snaketime; +# define GETSECS(t) ((long)(t).time) +# define GETMSECS(t) ((t).millitm/1000) + +# endif /* HAVE_FTIME */ +#endif /* HAVE_GETTIMEOFDAY */ + +#include + +#ifndef M_SQRT1_2 /* Win32 doesn't have this constant */ +#define M_SQRT1_2 0.70710678118654752440084436210485 +#endif + +#define NODE_COUNT 24 + +#ifdef HAVE_GLUT +#define DEF_YANGVEL 0.10 +#define DEF_ZANGVEL 0.14 +#define DEF_EXPLODE 0.03 +#define DEF_ANGVEL 1.0 +#define DEF_STATICTIME 5000 +#define DEF_ALTCOLOUR 0 +#define DEF_TITLES 0 +#define DEF_INTERACTIVE 0 +#define DEF_ZOOM 25.0 +#define DEF_WIREFRAME 0 +#define DEF_TRANSPARENT 1 +#else +/* xscreensaver options doobies prefer strings */ +#define DEF_YANGVEL "0.10" +#define DEF_ZANGVEL "0.14" +#define DEF_EXPLODE "0.03" +#define DEF_ANGVEL "1.0" +#define DEF_STATICTIME "5000" +#define DEF_ALTCOLOUR "False" +#define DEF_TITLES "False" +#define DEF_INTERACTIVE "False" +#define DEF_ZOOM "25.0" +#define DEF_WIREFRAME "False" +#define DEF_TRANSPARENT "True" +#endif + +/* static variables */ + +static GLfloat explode; +static long statictime; +static GLfloat yspin = 60.0; +static GLfloat zspin = -45.0; +static GLfloat yangvel; +static GLfloat zangvel; +static Bool altcolour; +static Bool titles; +static Bool interactive; +static Bool wireframe; +static Bool transparent; +static GLfloat zoom; +static GLfloat angvel; + +#ifndef HAVE_GLUT + +#define glsnake_init init_glsnake +#define glsnake_display draw_glsnake +#define glsnake_reshape reshape_glsnake +#define refresh_glsnake 0 +#define release_glsnake 0 +#define glsnake_handle_event 0 + +/* xscreensaver defaults */ +#define DEFAULTS "*delay: 30000 \n" \ + "*count: 30 \n" \ + "*showFPS: False \n" \ + "*labelfont: -*-helvetica-medium-r-normal-*-180-*\n" \ + + + +#undef countof +#define countof(x) (sizeof((x))/sizeof((*x))) + +#include "xlockmore.h" +#include "glxfonts.h" + +static XrmOptionDescRec opts[] = { + { "-explode", ".explode", XrmoptionSepArg, DEF_EXPLODE }, + { "-angvel", ".angvel", XrmoptionSepArg, DEF_ANGVEL }, + { "-statictime", ".statictime", XrmoptionSepArg, DEF_STATICTIME }, + { "-yangvel", ".yangvel", XrmoptionSepArg, DEF_YANGVEL }, + { "-zangvel", ".zangvel", XrmoptionSepArg, DEF_ZANGVEL }, + { "-altcolour", ".altcolour", XrmoptionNoArg, "True" }, + { "-no-altcolour", ".altcolour", XrmoptionNoArg, "False" }, + { "-titles", ".titles", XrmoptionNoArg, "True" }, + { "-no-titles", ".titles", XrmoptionNoArg, "False" }, + { "-zoom", ".zoom", XrmoptionSepArg, DEF_ZOOM }, + { "-wireframe", ".wireframe", XrmoptionNoArg, "true" }, + { "-no-wireframe", ".wireframe", XrmoptionNoArg, "false" }, + { "-transparent", ".transparent", XrmoptionNoArg, "true" }, + { "-no-transparent", ".transparent", XrmoptionNoArg, "false" }, +}; + +static argtype vars[] = { + {&explode, "explode", "Explode", DEF_EXPLODE, t_Float}, + {&angvel, "angvel", "Angular Velocity", DEF_ANGVEL, t_Float}, + {&statictime, "statictime", "Static Time", DEF_STATICTIME, t_Int}, + {&yangvel, "yangvel", "Angular Velocity about Y axis", DEF_YANGVEL, t_Float}, + {&zangvel, "zangvel", "Angular Velocity about X axis", DEF_ZANGVEL, t_Float}, + {&interactive, "interactive", "Interactive", DEF_INTERACTIVE, t_Bool}, + {&altcolour, "altcolour", "Alternate Colour Scheme", DEF_ALTCOLOUR, t_Bool}, + {&titles, "titles", "Titles", DEF_TITLES, t_Bool}, + {&zoom, "zoom", "Zoom", DEF_ZOOM, t_Float}, + {&wireframe, "wireframe", "Wireframe", DEF_WIREFRAME, t_Bool}, + {&transparent, "transparent", "Transparent!", DEF_TRANSPARENT, t_Bool}, +}; + +ENTRYPOINT ModeSpecOpt glsnake_opts = {countof(opts), opts, countof(vars), vars, NULL}; +#endif + +struct model_s { + const char * name; + float node[NODE_COUNT]; +}; + +struct glsnake_cfg { +#ifndef HAVE_GLUT + GLXContext * glx_context; +# ifdef HAVE_GLBITMAP + XFontStruct * font; + GLuint font_list; +# else + texture_font_data *font_data; +# endif +#else + /* font list number */ + int font; +#endif + + /* window id */ + int window; + + /* is a morph in progress? */ + int morphing; + + /* has the model been paused? */ + int paused; + + /* snake metrics */ + int is_cyclic; + int is_legal; + float last_turn; + int debug; + + /* the shape of the model */ + float node[NODE_COUNT]; + + /* currently selected node for interactive mode */ + int selected; + + /* models */ + unsigned int prev_model; + unsigned int next_model; + + /* model morphing */ + int new_morph; + + /* colours */ + float colour[2][4]; + int next_colour; + int prev_colour; + + /* timing variables */ + snaketime last_iteration; + snaketime last_morph; + + /* window size */ + int width, height; + int old_width, old_height; + + /* the id of the display lists for drawing a node */ + GLuint node_solid, node_wire; + int node_polys; + + /* is the window fullscreen? */ + int fullscreen; +}; + +#define COLOUR_CYCLIC 0 +#define COLOUR_ACYCLIC 1 +#define COLOUR_INVALID 2 +#define COLOUR_AUTHENTIC 3 +#define COLOUR_ORIGLOGO 4 + +static const float colour[][2][4] = { + /* cyclic - green */ + { { 0.4, 0.8, 0.2, 0.6 }, + { 1.0, 1.0, 1.0, 0.6 } }, + /* acyclic - blue */ + { { 0.3, 0.1, 0.9, 0.6 }, + { 1.0, 1.0, 1.0, 0.6 } }, + /* invalid - grey */ + { { 0.3, 0.1, 0.9, 0.6 }, + { 1.0, 1.0, 1.0, 0.6 } }, + /* authentic - purple and green */ + { { 0.38, 0.0, 0.55, 0.7 }, + { 0.0, 0.5, 0.34, 0.7 } }, + /* old "authentic" colours from the logo */ + { { 171/255.0, 0, 1.0, 1.0 }, + { 46/255.0, 205/255.0, 227/255.0, 1.0 } } +}; + +static const struct model_s model[] = { +#define STRAIGHT_MODEL 0 + { "straight", + { ZERO, ZERO, ZERO, ZERO, ZERO, ZERO, ZERO, ZERO, ZERO, ZERO, + ZERO, ZERO, ZERO, ZERO, ZERO, ZERO, ZERO, ZERO, ZERO, ZERO, ZERO, + ZERO, ZERO, ZERO } + }, + /* the models in the Rubik's snake manual */ + { "ball", + { RIGHT, RIGHT, LEFT, LEFT, RIGHT, LEFT, RIGHT, RIGHT, LEFT, + RIGHT, LEFT, LEFT, RIGHT, RIGHT, LEFT, LEFT, RIGHT, LEFT, RIGHT, + RIGHT, LEFT, RIGHT, LEFT, ZERO } + }, +#define START_MODEL 2 + { "snow", + { RIGHT, RIGHT, RIGHT, RIGHT, LEFT, LEFT, LEFT, LEFT, RIGHT, + RIGHT, RIGHT, RIGHT, LEFT, LEFT, LEFT, LEFT, RIGHT, RIGHT, RIGHT, + RIGHT, LEFT, LEFT, LEFT, ZERO } + }, + { "propellor", + { ZERO, ZERO, ZERO, RIGHT, LEFT, RIGHT, ZERO, LEFT, ZERO, ZERO, + ZERO, RIGHT, LEFT, RIGHT, ZERO, LEFT, ZERO, ZERO, ZERO, RIGHT, + LEFT, RIGHT, ZERO, LEFT } + }, + { "flamingo", + { ZERO, PIN, ZERO, ZERO, ZERO, ZERO, ZERO, PIN, RIGHT, RIGHT, PIN, + RIGHT, LEFT, PIN, LEFT, RIGHT, PIN, RIGHT, RIGHT, ZERO, ZERO, + ZERO, PIN, ZERO } + }, + { "cat", + { ZERO, PIN, PIN, ZERO, PIN, PIN, ZERO, RIGHT, ZERO, PIN, PIN, + ZERO, PIN, PIN, ZERO, PIN, PIN, ZERO, ZERO, ZERO, ZERO, ZERO, + ZERO, ZERO } + }, + { "rooster", + { ZERO, ZERO, PIN, PIN, ZERO, LEFT, ZERO, LEFT, RIGHT, PIN, RIGHT, + ZERO, PIN, PIN, ZERO, RIGHT, PIN, RIGHT, LEFT, ZERO, LEFT, ZERO, + PIN, ZERO } + }, + /* These models were taken from Andrew and Peter's original snake.c + * as well as some newer ones made up by Jamie, Andrew and Peter. */ + { "half balls", + { LEFT, LEFT, RIGHT, LEFT, RIGHT, RIGHT, LEFT, RIGHT, LEFT, + LEFT, LEFT, LEFT, LEFT, LEFT, RIGHT, LEFT, RIGHT, RIGHT, LEFT, + RIGHT, LEFT, LEFT, LEFT, ZERO } + }, + { "zigzag1", + { RIGHT, RIGHT, RIGHT, LEFT, LEFT, LEFT, RIGHT, RIGHT, RIGHT, + LEFT, LEFT, LEFT, RIGHT, RIGHT, RIGHT, LEFT, LEFT, LEFT, RIGHT, + RIGHT, RIGHT, LEFT, LEFT, ZERO } + }, + { "zigzag2", + { PIN, ZERO, PIN, ZERO, PIN, ZERO, PIN, ZERO, PIN, ZERO, PIN, + ZERO, PIN, ZERO, PIN, ZERO, PIN, ZERO, PIN, ZERO, PIN, ZERO, PIN, + ZERO } + }, + { "zigzag3", + { PIN, LEFT, PIN, LEFT, PIN, LEFT, PIN, LEFT, PIN, LEFT, PIN, + LEFT, PIN, LEFT, PIN, LEFT, PIN, LEFT, PIN, LEFT, PIN, LEFT, PIN, + ZERO } + }, + { "caterpillar", + { RIGHT, RIGHT, PIN, LEFT, LEFT, PIN, RIGHT, RIGHT, PIN, LEFT, + LEFT, PIN, RIGHT, RIGHT, PIN, LEFT, LEFT, PIN, RIGHT, RIGHT, PIN, + LEFT, LEFT, ZERO } + }, + { "bow", + { RIGHT, LEFT, RIGHT, RIGHT, RIGHT, LEFT, LEFT, LEFT, RIGHT, + LEFT, RIGHT, RIGHT, RIGHT, LEFT, LEFT, LEFT, RIGHT, LEFT, RIGHT, + RIGHT, RIGHT, LEFT, LEFT, ZERO } + }, + { "turtle", + { ZERO, RIGHT, LEFT, ZERO, ZERO, RIGHT, LEFT, PIN, RIGHT, RIGHT, + LEFT, RIGHT, LEFT, LEFT, PIN, LEFT, LEFT, LEFT, RIGHT, LEFT, + RIGHT, RIGHT, RIGHT, ZERO } + }, + { "basket", + { RIGHT, PIN, ZERO, ZERO, PIN, LEFT, ZERO, LEFT, LEFT, ZERO, + LEFT, PIN, ZERO, ZERO, PIN, RIGHT, PIN, LEFT, PIN, ZERO, ZERO, + PIN, LEFT, ZERO } + }, + { "thing", + { PIN, RIGHT, LEFT, RIGHT, RIGHT, LEFT, PIN, LEFT, RIGHT, LEFT, + LEFT, RIGHT, PIN, RIGHT, LEFT, RIGHT, RIGHT, LEFT, PIN, LEFT, + RIGHT, LEFT, LEFT, ZERO } + }, + { "hexagon", + { ZERO, ZERO, ZERO, ZERO, LEFT, ZERO, ZERO, RIGHT, ZERO, ZERO, + ZERO, ZERO, LEFT, ZERO, ZERO, RIGHT, ZERO, ZERO, ZERO, ZERO, + LEFT, ZERO, ZERO, RIGHT } + }, + { "tri1", + { ZERO, ZERO, LEFT, RIGHT, ZERO, LEFT, ZERO, RIGHT, ZERO, ZERO, + LEFT, RIGHT, ZERO, LEFT, ZERO, RIGHT, ZERO, ZERO, LEFT, RIGHT, + ZERO, LEFT, ZERO, RIGHT } + }, + { "triangle", + { ZERO, ZERO, ZERO, ZERO, ZERO, ZERO, LEFT, RIGHT, ZERO, ZERO, + ZERO, ZERO, ZERO, ZERO, LEFT, RIGHT, ZERO, ZERO, ZERO, ZERO, + ZERO, ZERO, LEFT, RIGHT } + }, + { "flower", + { ZERO, LEFT, PIN, RIGHT, RIGHT, PIN, ZERO, LEFT, PIN, RIGHT, + RIGHT, PIN, ZERO, LEFT, PIN, RIGHT, RIGHT, PIN, ZERO, LEFT, PIN, + RIGHT, RIGHT, PIN } + }, + { "crucifix", + { ZERO, PIN, PIN, ZERO, PIN, ZERO, PIN, PIN, ZERO, PIN, ZERO, PIN, + PIN, ZERO, PIN, ZERO, ZERO, ZERO, PIN, PIN, ZERO, ZERO, ZERO, PIN } + }, + { "kayak", + { PIN, RIGHT, LEFT, PIN, LEFT, PIN, ZERO, ZERO, RIGHT, PIN, LEFT, + ZERO, ZERO, ZERO, ZERO, ZERO, ZERO, RIGHT, PIN, LEFT, ZERO, ZERO, + PIN, RIGHT } + }, + { "bird", + { ZERO, ZERO, ZERO, ZERO, RIGHT, RIGHT, ZERO, LEFT, PIN, RIGHT, + ZERO, RIGHT, ZERO, RIGHT, ZERO, RIGHT, PIN, LEFT, ZERO, RIGHT, + LEFT, ZERO, PIN, ZERO } + }, + { "seal", + { RIGHT, LEFT, LEFT, PIN, RIGHT, LEFT, ZERO, PIN, PIN, ZERO, + LEFT, ZERO, LEFT, PIN, RIGHT, ZERO, LEFT, LEFT, LEFT, PIN, RIGHT, + RIGHT, LEFT, ZERO } + }, + { "dog", + { ZERO, ZERO, ZERO, ZERO, PIN, PIN, ZERO, PIN, ZERO, ZERO, PIN, + ZERO, PIN, PIN, ZERO, ZERO, ZERO, PIN, ZERO, PIN, PIN, ZERO, PIN, ZERO } + }, + { "frog", + { RIGHT, RIGHT, LEFT, LEFT, RIGHT, PIN, RIGHT, PIN, LEFT, PIN, + RIGHT, ZERO, LEFT, ZERO, LEFT, PIN, RIGHT, ZERO, LEFT, LEFT, + RIGHT, LEFT, LEFT, ZERO } + }, + { "quavers", + { LEFT, LEFT, RIGHT, LEFT, RIGHT, RIGHT, ZERO, ZERO, ZERO, + RIGHT, ZERO, ZERO, LEFT, RIGHT, ZERO, ZERO, ZERO, LEFT, LEFT, + RIGHT, LEFT, RIGHT, RIGHT, ZERO } + }, + { "fly", + { LEFT, LEFT, RIGHT, LEFT, RIGHT, RIGHT, ZERO, PIN, ZERO, ZERO, + LEFT, PIN, RIGHT, ZERO, ZERO, PIN, ZERO, LEFT, LEFT, RIGHT, LEFT, + RIGHT, RIGHT, ZERO } + }, + { "puppy", + { ZERO, PIN, ZERO, PIN, PIN, ZERO, PIN, PIN, ZERO, ZERO, ZERO, + RIGHT, RIGHT, PIN, RIGHT, LEFT, PIN, LEFT, RIGHT, PIN, RIGHT, + LEFT, ZERO, ZERO } + }, + { "stars", + { LEFT, RIGHT, PIN, RIGHT, LEFT, PIN, LEFT, RIGHT, PIN, RIGHT, + ZERO, ZERO, ZERO, RIGHT, PIN, RIGHT, LEFT, PIN, LEFT, RIGHT, PIN, + RIGHT, LEFT, ZERO } + }, + { "mountains", + { RIGHT, PIN, RIGHT, PIN, RIGHT, PIN, LEFT, PIN, LEFT, PIN, + LEFT, PIN, RIGHT, PIN, RIGHT, PIN, RIGHT, PIN, LEFT, PIN, LEFT, + PIN, LEFT, PIN } + }, + { "quad1", + { RIGHT, PIN, RIGHT, RIGHT, RIGHT, PIN, LEFT, LEFT, LEFT, PIN, + LEFT, PIN, RIGHT, PIN, RIGHT, RIGHT, RIGHT, PIN, LEFT, LEFT, + LEFT, PIN, LEFT, PIN } + }, + { "quad2", + { ZERO, PIN, RIGHT, RIGHT, RIGHT, PIN, LEFT, LEFT, LEFT, PIN, + ZERO, PIN, ZERO, PIN, RIGHT, RIGHT, RIGHT, PIN, LEFT, LEFT, LEFT, + PIN, ZERO, PIN } + }, + { "glasses", + { ZERO, PIN, ZERO, RIGHT, RIGHT, PIN, LEFT, LEFT, ZERO, PIN, + ZERO, PIN, ZERO, PIN, ZERO, RIGHT, RIGHT, PIN, LEFT, LEFT, ZERO, + PIN, ZERO, PIN } + }, + { "em", + { ZERO, PIN, ZERO, ZERO, RIGHT, PIN, LEFT, ZERO, ZERO, PIN, + ZERO, PIN, ZERO, PIN, ZERO, ZERO, RIGHT, PIN, LEFT, ZERO, ZERO, + PIN, ZERO, PIN } + }, + { "quad3", + { ZERO, RIGHT, ZERO, ZERO, RIGHT, PIN, LEFT, ZERO, ZERO, LEFT, + ZERO, PIN, ZERO, RIGHT, ZERO, ZERO, RIGHT, PIN, LEFT, ZERO, ZERO, + LEFT, ZERO, PIN } + }, + { "vee", + { ZERO, ZERO, ZERO, ZERO, RIGHT, PIN, LEFT, ZERO, ZERO, ZERO, + ZERO, PIN, ZERO, ZERO, ZERO, ZERO, RIGHT, PIN, LEFT, ZERO, ZERO, + ZERO, ZERO, PIN } + }, + { "square", + { ZERO, ZERO, ZERO, RIGHT, RIGHT, PIN, LEFT, LEFT, ZERO, ZERO, + ZERO, PIN, ZERO, ZERO, ZERO, RIGHT, RIGHT, PIN, LEFT, LEFT, ZERO, + ZERO, ZERO, PIN } + }, + { "eagle", + { RIGHT, ZERO, ZERO, RIGHT, RIGHT, PIN, LEFT, LEFT, ZERO, ZERO, + LEFT, PIN, RIGHT, ZERO, ZERO, RIGHT, RIGHT, PIN, LEFT, LEFT, + ZERO, ZERO, LEFT, PIN } + }, + { "volcano", + { RIGHT, ZERO, LEFT, RIGHT, RIGHT, PIN, LEFT, LEFT, RIGHT, + ZERO, LEFT, PIN, RIGHT, ZERO, LEFT, RIGHT, RIGHT, PIN, LEFT, + LEFT, RIGHT, ZERO, LEFT, PIN } + }, + { "saddle", + { RIGHT, ZERO, LEFT, ZERO, RIGHT, PIN, LEFT, ZERO, RIGHT, ZERO, + LEFT, PIN, RIGHT, ZERO, LEFT, ZERO, RIGHT, PIN, LEFT, ZERO, RIGHT, + ZERO, LEFT, PIN } + }, + { "c3d", + { ZERO, ZERO, RIGHT, ZERO, ZERO, PIN, ZERO, ZERO, LEFT, ZERO, + ZERO, PIN, ZERO, ZERO, RIGHT, ZERO, ZERO, PIN, ZERO, ZERO, LEFT, + ZERO, ZERO, PIN } + }, + { "block", + { ZERO, ZERO, PIN, PIN, ZERO, RIGHT, PIN, LEFT, PIN, RIGHT, PIN, + RIGHT, PIN, LEFT, PIN, RIGHT, ZERO, ZERO, PIN, ZERO, ZERO, LEFT, + PIN, RIGHT } + }, + { "duck", + { LEFT, PIN, LEFT, PIN, ZERO, PIN, PIN, ZERO, PIN, ZERO, LEFT, + PIN, RIGHT, ZERO, PIN, ZERO, PIN, PIN, ZERO, ZERO, LEFT, PIN, + LEFT, ZERO } + }, + { "prayer", + { RIGHT, RIGHT, RIGHT, LEFT, RIGHT, LEFT, LEFT, ZERO, ZERO, + ZERO, RIGHT, PIN, LEFT, ZERO, ZERO, ZERO, RIGHT, RIGHT, LEFT, + RIGHT, LEFT, LEFT, LEFT, PIN } + }, + { "giraffe", + { ZERO, ZERO, ZERO, RIGHT, PIN, LEFT, ZERO, ZERO, ZERO, RIGHT, + RIGHT, RIGHT, PIN, LEFT, RIGHT, ZERO, PIN, ZERO, LEFT, RIGHT, + PIN, LEFT, LEFT, LEFT } + }, + { "tie fighter", + { PIN, LEFT, RIGHT, LEFT, LEFT, PIN, RIGHT, ZERO, RIGHT, LEFT, + ZERO, PIN, LEFT, LEFT, RIGHT, RIGHT, RIGHT, PIN, LEFT, ZERO, + LEFT, RIGHT, ZERO, ZERO } + }, + { "Strong Arms", + { PIN, PIN, ZERO, ZERO, PIN, ZERO, ZERO, RIGHT, ZERO, RIGHT, + RIGHT, PIN, RIGHT, RIGHT, ZERO, RIGHT, ZERO, ZERO, PIN, ZERO, + ZERO, PIN, PIN, ZERO } + }, + + /* the following modesl were created during the slug/compsoc codefest + * febrray 2003 */ + { "cool looking gegl", + { PIN, PIN, ZERO, ZERO, RIGHT, ZERO, ZERO, PIN, PIN, ZERO, LEFT, + ZERO, ZERO, PIN, ZERO, PIN, PIN, ZERO, LEFT, RIGHT, PIN, ZERO, + ZERO, ZERO } + }, + { "knuckledusters", + { ZERO, ZERO, ZERO, ZERO, PIN, RIGHT, ZERO, PIN, PIN, ZERO, PIN, + PIN, ZERO, RIGHT, RIGHT, ZERO, PIN, PIN, ZERO, PIN, PIN, ZERO, + RIGHT, ZERO } + }, + { "k's turd", + { RIGHT, RIGHT, PIN, RIGHT, LEFT, RIGHT, PIN, RIGHT, LEFT, + RIGHT, PIN, RIGHT, LEFT, RIGHT, PIN, RIGHT, LEFT, RIGHT, PIN, + RIGHT, LEFT, RIGHT, PIN, ZERO } + }, + { "lightsabre", + { ZERO, ZERO, ZERO, ZERO, ZERO, PIN, PIN, ZERO, ZERO, ZERO, ZERO, + ZERO, ZERO, ZERO, ZERO, ZERO, ZERO, ZERO, ZERO, ZERO, ZERO, ZERO, + ZERO, ZERO } + }, + { "not a stairway", + { LEFT, ZERO, RIGHT, LEFT, RIGHT, ZERO, LEFT, RIGHT, LEFT, ZERO, + RIGHT, LEFT, RIGHT, ZERO, LEFT, RIGHT, LEFT, ZERO, RIGHT, LEFT, + RIGHT, ZERO, LEFT, ZERO } + }, + { "not very good (but accurate) gegl", + { ZERO, PIN, PIN, ZERO, ZERO, ZERO, PIN, PIN, ZERO, LEFT, ZERO, + PIN, PIN, ZERO, RIGHT, LEFT, ZERO, PIN, ZERO, PIN, PIN, ZERO, + PIN, ZERO } + }, + { "box", + { ZERO, ZERO, ZERO, ZERO, PIN, ZERO, ZERO, ZERO, ZERO, ZERO, + ZERO, PIN, ZERO, ZERO, ZERO, ZERO, PIN, ZERO, ZERO, ZERO, ZERO, + ZERO, ZERO, ZERO } + }, + { "kissy box", + { PIN, ZERO, ZERO, ZERO, PIN, ZERO, ZERO, ZERO, ZERO, ZERO, + ZERO, PIN, ZERO, ZERO, ZERO, ZERO, PIN, ZERO, ZERO, ZERO, ZERO, + ZERO, PIN, ZERO } + }, + { "erect penis", /* thanks benno */ + { PIN, ZERO, PIN, PIN, ZERO, ZERO, PIN, ZERO, ZERO, ZERO, PIN, + PIN, ZERO, ZERO, ZERO, RIGHT, ZERO, ZERO, ZERO, ZERO, ZERO, ZERO, + ZERO, ZERO } + }, + { "flaccid penis", + { PIN, ZERO, PIN, PIN, ZERO, ZERO, PIN, ZERO, ZERO, ZERO, PIN, + PIN, ZERO, ZERO, ZERO, RIGHT, PIN, ZERO, ZERO, ZERO, ZERO, ZERO, + ZERO, ZERO } + }, + { "vagina", + { RIGHT, ZERO, ZERO, ZERO, RIGHT, ZERO, ZERO, PIN, ZERO, ZERO, + LEFT, ZERO, ZERO, ZERO, LEFT, ZERO, LEFT, PIN, LEFT, PIN, RIGHT, + PIN, RIGHT, ZERO } + }, + { "mask", + { ZERO, RIGHT, LEFT, PIN, RIGHT, RIGHT, PIN, ZERO, ZERO, PIN, + ZERO, ZERO, PIN, ZERO, PIN, ZERO, PIN, ZERO, ZERO, PIN, ZERO, + ZERO, ZERO, ZERO } + }, + { "poles or columns or something", + { LEFT, RIGHT, LEFT, ZERO, ZERO, ZERO, PIN, PIN, ZERO, ZERO, + ZERO, LEFT, RIGHT, LEFT, ZERO, ZERO, ZERO, PIN, PIN, ZERO, ZERO, + ZERO, LEFT, ZERO } + }, + { "crooked v", + { ZERO, LEFT, ZERO, ZERO, ZERO, ZERO, PIN, PIN, ZERO, ZERO, + ZERO, LEFT, ZERO, LEFT, ZERO, ZERO, ZERO, PIN, PIN, ZERO, ZERO, + ZERO, ZERO, ZERO } + }, + { "dog leg", + { ZERO, LEFT, ZERO, ZERO, ZERO, ZERO, PIN, PIN, ZERO, ZERO, ZERO, + LEFT, ZERO, RIGHT, ZERO, ZERO, ZERO, ZERO, PIN, PIN, ZERO, ZERO, + ZERO, ZERO } + }, + { "scrubby", + { ZERO, ZERO, ZERO, ZERO, ZERO, LEFT, ZERO, ZERO, ZERO, ZERO, + LEFT, RIGHT, ZERO, ZERO, ZERO, ZERO, LEFT, RIGHT, ZERO, ZERO, + LEFT, PIN, ZERO, ZERO } + }, + { "voltron's eyes", + { ZERO, ZERO, PIN, RIGHT, ZERO, LEFT, ZERO, ZERO, RIGHT, ZERO, + LEFT, PIN, ZERO, ZERO, PIN, ZERO, LEFT, ZERO, RIGHT, LEFT, ZERO, + RIGHT, ZERO, ZERO } + }, + { "flying toaster", + { PIN, ZERO, ZERO, PIN, PIN, ZERO, RIGHT, ZERO, PIN, PIN, ZERO, + RIGHT, ZERO, PIN, PIN, ZERO, RIGHT, ZERO, PIN, PIN, ZERO, ZERO, + PIN, ZERO } + }, + { "dubbya", + { PIN, ZERO, ZERO, PIN, PIN, ZERO, RIGHT, ZERO, PIN, PIN, ZERO, + ZERO, ZERO, PIN, PIN, ZERO, RIGHT, ZERO, PIN, PIN, ZERO, ZERO, + PIN, ZERO } + }, + { "tap handle", + { PIN, ZERO, ZERO, PIN, PIN, ZERO, RIGHT, ZERO, PIN, PIN, ZERO, + LEFT, ZERO, PIN, PIN, ZERO, RIGHT, ZERO, PIN, PIN, ZERO, ZERO, + PIN, ZERO } + }, + { "wingnut", + { PIN, ZERO, ZERO, PIN, PIN, ZERO, RIGHT, ZERO, PIN, PIN, ZERO, + PIN, ZERO, PIN, PIN, ZERO, RIGHT, ZERO, PIN, PIN, ZERO, ZERO, + PIN, ZERO } + }, + { "tight twist", + { RIGHT, ZERO, ZERO, LEFT, ZERO, LEFT, RIGHT, ZERO, RIGHT, LEFT, + RIGHT, PIN, RIGHT, LEFT, RIGHT, ZERO, RIGHT, LEFT, ZERO, LEFT, + ZERO, ZERO, RIGHT, ZERO } + }, + { "double helix", + { RIGHT, ZERO, RIGHT, ZERO, RIGHT, ZERO, RIGHT, ZERO, RIGHT, + ZERO, RIGHT, ZERO, RIGHT, LEFT, RIGHT, PIN, ZERO, RIGHT, ZERO, + RIGHT, ZERO, RIGHT, ZERO, ZERO } + }, + + /* These models come from the website at + * http://www.geocities.com/stigeide/snake */ +#if 0 + { "Abstract", + { RIGHT, LEFT, RIGHT, ZERO, PIN, ZERO, LEFT, RIGHT, LEFT, PIN, ZERO, ZERO, PIN, LEFT, RIGHT, LEFT, ZERO, PIN, ZERO, RIGHT, LEFT, RIGHT, ZERO, ZERO } + }, +#endif + { "toadstool", + { LEFT, RIGHT, ZERO, RIGHT, LEFT, ZERO, ZERO, RIGHT, LEFT, PIN, RIGHT, RIGHT, LEFT, RIGHT, LEFT, LEFT, RIGHT, RIGHT, RIGHT, PIN, RIGHT, LEFT, PIN, ZERO } + }, + { "AlanH2", + { LEFT, RIGHT, ZERO, RIGHT, LEFT, ZERO, ZERO, RIGHT, LEFT, PIN, RIGHT, RIGHT, LEFT, RIGHT, LEFT, LEFT, RIGHT, RIGHT, LEFT, LEFT, RIGHT, LEFT, RIGHT, ZERO } + }, + { "AlanH3", + { LEFT, RIGHT, ZERO, RIGHT, LEFT, ZERO, ZERO, RIGHT, LEFT, PIN, RIGHT, RIGHT, LEFT, RIGHT, LEFT, LEFT, RIGHT, RIGHT, LEFT, PIN, LEFT, RIGHT, PIN, ZERO } + }, + { "AlanH4", + { ZERO, ZERO, PIN, LEFT, RIGHT, LEFT, ZERO, RIGHT, LEFT, RIGHT, ZERO, PIN, ZERO, LEFT, RIGHT, LEFT, ZERO, RIGHT, LEFT, RIGHT, PIN, ZERO, ZERO, ZERO } + }, + { "Alien", + { RIGHT, LEFT, RIGHT, PIN, ZERO, ZERO, PIN, RIGHT, LEFT, RIGHT, ZERO, PIN, PIN, ZERO, LEFT, LEFT, RIGHT, RIGHT, LEFT, LEFT, ZERO, PIN, PIN, ZERO } + }, + { "Angel", + { ZERO, RIGHT, LEFT, PIN, RIGHT, RIGHT, RIGHT, LEFT, LEFT, RIGHT, LEFT, RIGHT, RIGHT, LEFT, LEFT, LEFT, PIN, RIGHT, LEFT, ZERO, ZERO, RIGHT, LEFT, ZERO } + }, + { "AnotherFigure", + { LEFT, PIN, RIGHT, ZERO, ZERO, PIN, RIGHT, LEFT, LEFT, PIN, RIGHT, LEFT, ZERO, PIN, ZERO, RIGHT, LEFT, PIN, RIGHT, RIGHT, LEFT, PIN, ZERO, ZERO } + }, + { "Ball", + { LEFT, RIGHT, LEFT, RIGHT, RIGHT, LEFT, RIGHT, LEFT, LEFT, RIGHT, LEFT, RIGHT, RIGHT, LEFT, RIGHT, LEFT, LEFT, RIGHT, LEFT, RIGHT, RIGHT, LEFT, RIGHT , ZERO } + }, + { "Basket", + { ZERO, RIGHT, RIGHT, ZERO, RIGHT, RIGHT, ZERO, RIGHT, LEFT, ZERO, LEFT, LEFT, PIN, RIGHT, LEFT, ZERO, LEFT, RIGHT, PIN, LEFT, LEFT, ZERO, LEFT , ZERO } + }, + { "Beetle", + { PIN, LEFT, RIGHT, ZERO, LEFT, LEFT, RIGHT, LEFT, RIGHT, RIGHT, LEFT, RIGHT, LEFT, LEFT, RIGHT, LEFT, RIGHT, RIGHT, ZERO, LEFT, RIGHT, PIN, RIGHT , ZERO } + }, + { "bone", + { PIN, PIN, LEFT, ZERO, PIN, PIN, ZERO, LEFT, ZERO, ZERO, ZERO, ZERO, ZERO, ZERO, ZERO, RIGHT, ZERO, PIN, PIN, ZERO, RIGHT, PIN, PIN , ZERO } + }, + { "Bow", + { LEFT, LEFT, LEFT, RIGHT, LEFT, RIGHT, RIGHT, RIGHT, LEFT, LEFT, LEFT, RIGHT, LEFT, RIGHT, RIGHT, RIGHT, LEFT, LEFT, LEFT, RIGHT, LEFT, RIGHT, RIGHT , ZERO } + }, + { "bra", + { RIGHT, RIGHT, LEFT, LEFT, RIGHT, LEFT, RIGHT, RIGHT, LEFT, LEFT, LEFT, RIGHT, RIGHT, RIGHT, LEFT, LEFT, RIGHT, LEFT, RIGHT, RIGHT, LEFT, LEFT, LEFT , ZERO } + }, + { "bronchosaurus", + { ZERO, PIN, ZERO, PIN, PIN, ZERO, PIN, ZERO, ZERO, PIN, ZERO, PIN, PIN, ZERO, ZERO, ZERO, ZERO, ZERO, ZERO, ZERO, ZERO, ZERO, PIN , ZERO } + }, + { "Cactus", + { PIN, LEFT, ZERO, PIN, PIN, ZERO, RIGHT, PIN, LEFT, ZERO, ZERO, PIN, RIGHT, PIN, LEFT, ZERO, ZERO, RIGHT, PIN, LEFT, PIN, ZERO, ZERO , ZERO } + }, + { "Camel", + { RIGHT, ZERO, PIN, RIGHT, PIN, RIGHT, ZERO, RIGHT, PIN, RIGHT, LEFT, PIN, LEFT, RIGHT, PIN, RIGHT, ZERO, RIGHT, PIN, RIGHT, ZERO, ZERO, LEFT , ZERO } + }, + { "Candlestick", + { LEFT, PIN, LEFT, ZERO, RIGHT, PIN, LEFT, ZERO, RIGHT, PIN, RIGHT, PIN, LEFT, PIN, LEFT, ZERO, RIGHT, PIN, LEFT, ZERO, RIGHT, PIN, RIGHT , ZERO } + }, + { "Cat", + { ZERO, PIN, PIN, ZERO, PIN, PIN, ZERO, RIGHT, ZERO, PIN, PIN, ZERO, PIN, PIN, ZERO, PIN, PIN, ZERO, ZERO, ZERO, ZERO, ZERO, ZERO , ZERO } + }, + { "Cave", + { RIGHT, ZERO, ZERO, PIN, LEFT, ZERO, PIN, PIN, ZERO, RIGHT, LEFT, PIN, RIGHT, RIGHT, LEFT, LEFT, PIN, RIGHT, RIGHT, LEFT, PIN, ZERO, ZERO , ZERO } + }, + { "Chains", + { PIN, ZERO, ZERO, PIN, LEFT, LEFT, PIN, RIGHT, RIGHT, PIN, ZERO, ZERO, PIN, ZERO, ZERO, PIN, LEFT, LEFT, PIN, RIGHT, RIGHT, PIN, ZERO , ZERO } + }, + { "Chair", + { RIGHT, LEFT, RIGHT, RIGHT, RIGHT, LEFT, RIGHT, ZERO, ZERO, PIN, PIN, ZERO, PIN, PIN, ZERO, PIN, PIN, ZERO, ZERO, LEFT, RIGHT, LEFT, LEFT , ZERO } + }, + { "Chick", + { RIGHT, RIGHT, RIGHT, PIN, LEFT, PIN, LEFT, PIN, RIGHT, RIGHT, RIGHT, PIN, LEFT, LEFT, LEFT, PIN, RIGHT, PIN, RIGHT, PIN, LEFT, LEFT, LEFT , ZERO } + }, + { "Clockwise", + { RIGHT, RIGHT, RIGHT, RIGHT, RIGHT, RIGHT, RIGHT, RIGHT, RIGHT, RIGHT, RIGHT, RIGHT, RIGHT, RIGHT, RIGHT, RIGHT, RIGHT, RIGHT, RIGHT, RIGHT, RIGHT, RIGHT, RIGHT , ZERO } + }, + { "cobra", + { ZERO, RIGHT, LEFT, LEFT, RIGHT, LEFT, RIGHT, RIGHT, LEFT, RIGHT, LEFT, LEFT, LEFT, LEFT, ZERO, LEFT, RIGHT, ZERO, ZERO, PIN, ZERO, ZERO, RIGHT , ZERO } + }, +#if 0 + { "Cobra2", + { LEFT, ZERO, PIN, ZERO, PIN, LEFT, ZERO, PIN, ZERO, LEFT, LEFT, PIN, RIGHT, RIGHT, ZERO, PIN, ZERO, RIGHT, PIN, ZERO, PIN, ZERO, RIGHT , ZERO } + }, +#endif + { "Cobra3", + { ZERO, LEFT, ZERO, PIN, PIN, ZERO, PIN, PIN, ZERO, RIGHT, ZERO, PIN, ZERO, ZERO, LEFT, ZERO, ZERO, ZERO, PIN, ZERO, ZERO, ZERO, LEFT , ZERO } + }, + { "Compact1", + { ZERO, ZERO, PIN, ZERO, ZERO, LEFT, PIN, RIGHT, PIN, LEFT, PIN, LEFT, PIN, RIGHT, PIN, LEFT, ZERO, PIN, PIN, ZERO, ZERO, LEFT, PIN , ZERO } + }, + { "Compact2", + { LEFT, PIN, RIGHT, ZERO, ZERO, PIN, PIN, ZERO, RIGHT, PIN, LEFT, ZERO, ZERO, RIGHT, PIN, RIGHT, PIN, LEFT, PIN, RIGHT, ZERO, ZERO, ZERO , ZERO } + }, + { "Compact3", + { ZERO, PIN, ZERO, PIN, PIN, ZERO, LEFT, PIN, RIGHT, ZERO, PIN, PIN, ZERO, PIN, ZERO, PIN, PIN, ZERO, LEFT, PIN, RIGHT, ZERO, PIN , ZERO } + }, + { "Compact4", + { PIN, RIGHT, ZERO, ZERO, PIN, ZERO, ZERO, PIN, PIN, ZERO, PIN, RIGHT, PIN, LEFT, PIN, ZERO, PIN, PIN, ZERO, ZERO, PIN, ZERO, ZERO , ZERO } + }, + { "Compact5", + { LEFT, ZERO, LEFT, PIN, RIGHT, PIN, LEFT, PIN, LEFT, PIN, RIGHT, PIN, RIGHT, PIN, LEFT, PIN, RIGHT, ZERO, RIGHT, PIN, RIGHT, PIN, LEFT , ZERO } + }, + { "Contact", + { PIN, ZERO, ZERO, PIN, LEFT, LEFT, PIN, LEFT, RIGHT, RIGHT, PIN, LEFT, LEFT, RIGHT, PIN, RIGHT, RIGHT, PIN, ZERO, ZERO, PIN, RIGHT, PIN , ZERO } + }, + { "Contact2", + { RIGHT, PIN, ZERO, LEFT, LEFT, PIN, RIGHT, RIGHT, ZERO, PIN, LEFT, PIN, RIGHT, PIN, ZERO, LEFT, LEFT, PIN, RIGHT, RIGHT, ZERO, PIN, LEFT , ZERO } + }, + { "Cook", + { ZERO, ZERO, PIN, PIN, ZERO, RIGHT, ZERO, RIGHT, LEFT, PIN, LEFT, ZERO, PIN, PIN, ZERO, LEFT, PIN, LEFT, RIGHT, ZERO, RIGHT, ZERO, PIN , ZERO } + }, + { "Counterclockwise", + { LEFT, LEFT, LEFT, LEFT, LEFT, LEFT, LEFT, LEFT, LEFT, LEFT, LEFT, LEFT, LEFT, LEFT, LEFT, LEFT, LEFT, LEFT, LEFT, LEFT, LEFT, LEFT, LEFT , ZERO } + }, + { "Cradle", + { LEFT, LEFT, ZERO, PIN, LEFT, RIGHT, LEFT, LEFT, RIGHT, LEFT, RIGHT, RIGHT, LEFT, RIGHT, PIN, ZERO, RIGHT, RIGHT, LEFT, LEFT, ZERO, ZERO, RIGHT , ZERO } + }, + { "Crankshaft", + { ZERO, PIN, PIN, ZERO, PIN, PIN, ZERO, PIN, LEFT, LEFT, PIN, RIGHT, LEFT, ZERO, PIN, LEFT, PIN, RIGHT, ZERO, ZERO, ZERO, PIN, RIGHT , ZERO } + }, + { "Cross", + { ZERO, PIN, ZERO, PIN, PIN, ZERO, PIN, ZERO, ZERO, ZERO, PIN, PIN, ZERO, ZERO, ZERO, PIN, ZERO, PIN, PIN, ZERO, PIN, ZERO, PIN , ZERO } + }, + { "Cross2", + { ZERO, ZERO, PIN, PIN, ZERO, LEFT, ZERO, ZERO, PIN, PIN, ZERO, RIGHT, ZERO, ZERO, PIN, PIN, ZERO, LEFT, ZERO, ZERO, PIN, PIN, ZERO , ZERO } + }, + { "Cross3", + { ZERO, ZERO, PIN, PIN, ZERO, LEFT, ZERO, ZERO, PIN, PIN, ZERO, RIGHT, ZERO, ZERO, PIN, PIN, ZERO, LEFT, ZERO, ZERO, PIN, PIN, ZERO, ZERO } + }, + { "CrossVersion1", + { PIN, ZERO, RIGHT, PIN, LEFT, PIN, RIGHT, PIN, RIGHT, PIN, LEFT, PIN, RIGHT, ZERO, PIN, RIGHT, PIN, RIGHT, LEFT, PIN, LEFT, RIGHT, PIN, ZERO } + }, + { "CrossVersion2", + { RIGHT, LEFT, PIN, LEFT, LEFT, ZERO, RIGHT, LEFT, PIN, RIGHT, RIGHT, PIN, LEFT, LEFT, PIN, RIGHT, LEFT, ZERO, LEFT, LEFT, PIN, LEFT, RIGHT, ZERO } + }, + { "Crown", + { LEFT, ZERO, PIN, ZERO, RIGHT, ZERO, ZERO, LEFT, ZERO, PIN, ZERO, RIGHT, LEFT, ZERO, PIN, ZERO, RIGHT, ZERO, ZERO, LEFT, ZERO, PIN, ZERO, ZERO } + }, + { "DNAStrand", + { RIGHT, PIN, RIGHT, PIN, RIGHT, PIN, RIGHT, PIN, RIGHT, PIN, RIGHT, PIN, RIGHT, PIN, RIGHT, PIN, RIGHT, PIN, RIGHT, PIN, RIGHT, PIN, RIGHT, ZERO } + }, + { "Diamond", + { ZERO, RIGHT, ZERO, ZERO, LEFT, ZERO, ZERO, RIGHT, PIN, LEFT, LEFT, RIGHT, LEFT, RIGHT, RIGHT, PIN, LEFT, ZERO, ZERO, RIGHT, ZERO, ZERO, LEFT, ZERO } + }, + { "Dog", + { RIGHT, RIGHT, LEFT, RIGHT, LEFT, LEFT, LEFT, RIGHT, RIGHT, LEFT, RIGHT, LEFT, LEFT, RIGHT, RIGHT, RIGHT, LEFT, RIGHT, LEFT, LEFT, ZERO, LEFT, RIGHT, ZERO } + }, + { "DogFace", + { ZERO, ZERO, PIN, PIN, ZERO, LEFT, LEFT, RIGHT, PIN, ZERO, PIN, PIN, ZERO, PIN, LEFT, RIGHT, RIGHT, ZERO, PIN, PIN, ZERO, ZERO, PIN, ZERO } + }, + { "DoublePeak", + { ZERO, ZERO, PIN, ZERO, ZERO, RIGHT, LEFT, PIN, LEFT, RIGHT, PIN, RIGHT, LEFT, LEFT, ZERO, PIN, ZERO, RIGHT, RIGHT, LEFT, PIN, LEFT, RIGHT, ZERO } + }, + { "DoubleRoof", + { ZERO, LEFT, LEFT, RIGHT, RIGHT, LEFT, RIGHT, LEFT, LEFT, RIGHT, LEFT, RIGHT, RIGHT, LEFT, LEFT, ZERO, LEFT, RIGHT, PIN, LEFT, LEFT, PIN, RIGHT, ZERO } + }, + { "txoboggan", + { ZERO, ZERO, ZERO, RIGHT, PIN, LEFT, ZERO, ZERO, ZERO, PIN, PIN, ZERO, ZERO, ZERO, ZERO, LEFT, PIN, RIGHT, ZERO, ZERO, ZERO, ZERO, PIN, ZERO } + }, + { "Doubled", + { LEFT, PIN, LEFT, RIGHT, PIN, RIGHT, LEFT, PIN, LEFT, RIGHT, LEFT, ZERO, LEFT, PIN, LEFT, PIN, LEFT, RIGHT, PIN, RIGHT, LEFT, PIN, LEFT, ZERO } + }, + { "Doubled1", + { LEFT, PIN, LEFT, RIGHT, PIN, RIGHT, LEFT, PIN, LEFT, ZERO, RIGHT, ZERO, RIGHT, ZERO, LEFT, PIN, LEFT, RIGHT, PIN, RIGHT, LEFT, PIN, LEFT, ZERO } + }, + { "Doubled2", + { LEFT, PIN, LEFT, RIGHT, PIN, RIGHT, LEFT, PIN, LEFT, LEFT, RIGHT, ZERO, RIGHT, LEFT, LEFT, PIN, LEFT, RIGHT, PIN, RIGHT, LEFT, PIN, LEFT, ZERO } + }, + { "DumblingSpoon", + { PIN, PIN, ZERO, ZERO, ZERO, ZERO, ZERO, LEFT, ZERO, ZERO, LEFT, RIGHT, ZERO, ZERO, LEFT, RIGHT, ZERO, ZERO, RIGHT, ZERO, ZERO, ZERO, ZERO, ZERO } + }, + { "Embrace", + { PIN, ZERO, ZERO, PIN, RIGHT, PIN, LEFT, PIN, ZERO, RIGHT, PIN, RIGHT, PIN, LEFT, PIN, LEFT, ZERO, PIN, RIGHT, PIN, LEFT, PIN, ZERO, ZERO } + }, + { "EndlessBelt", + { ZERO, RIGHT, LEFT, ZERO, ZERO, ZERO, LEFT, RIGHT, ZERO, PIN, RIGHT, LEFT, ZERO, LEFT, RIGHT, LEFT, PIN, LEFT, RIGHT, LEFT, ZERO, LEFT, RIGHT, ZERO } + }, + { "Entrance", + { LEFT, LEFT, RIGHT, RIGHT, RIGHT, LEFT, LEFT, RIGHT, LEFT, RIGHT, RIGHT, RIGHT, LEFT, LEFT, LEFT, RIGHT, LEFT, RIGHT, RIGHT, LEFT, LEFT, LEFT, RIGHT, ZERO } + }, + { "Esthetic", + { LEFT, LEFT, PIN, RIGHT, RIGHT, ZERO, LEFT, PIN, RIGHT, PIN, LEFT, PIN, LEFT, PIN, RIGHT, PIN, LEFT, ZERO, RIGHT, LEFT, PIN, RIGHT, RIGHT, ZERO } + }, + { "Explosion", + { RIGHT, RIGHT, RIGHT, RIGHT, LEFT, RIGHT, LEFT, LEFT, RIGHT, RIGHT, RIGHT, LEFT, RIGHT, LEFT, LEFT, LEFT, RIGHT, RIGHT, LEFT, RIGHT, LEFT, LEFT, LEFT, ZERO } + }, + { "F-ZeroXCar", + { RIGHT, RIGHT, LEFT, RIGHT, LEFT, LEFT, PIN, RIGHT, LEFT, ZERO, ZERO, RIGHT, LEFT, ZERO, ZERO, LEFT, RIGHT, PIN, RIGHT, LEFT, PIN, LEFT, RIGHT, ZERO } + }, + { "Face", + { ZERO, RIGHT, PIN, RIGHT, LEFT, PIN, LEFT, LEFT, PIN, RIGHT, RIGHT, PIN, RIGHT, LEFT, PIN, LEFT, PIN, LEFT, PIN, LEFT, RIGHT, PIN, RIGHT, ZERO } + }, + { "Fantasy", + { LEFT, LEFT, RIGHT, PIN, ZERO, RIGHT, ZERO, LEFT, PIN, LEFT, PIN, RIGHT, PIN, RIGHT, ZERO, LEFT, ZERO, PIN, LEFT, RIGHT, RIGHT, RIGHT, PIN, ZERO } + }, + { "Fantasy1", + { PIN, ZERO, ZERO, PIN, PIN, ZERO, PIN, RIGHT, LEFT, RIGHT, RIGHT, PIN, LEFT, LEFT, RIGHT, LEFT, PIN, ZERO, PIN, PIN, ZERO, ZERO, PIN, ZERO } + }, + { "FaserGun", + { ZERO, ZERO, LEFT, RIGHT, PIN, RIGHT, ZERO, RIGHT, PIN, RIGHT, LEFT, PIN, LEFT, RIGHT, PIN, RIGHT, ZERO, RIGHT, PIN, RIGHT, RIGHT, ZERO, PIN, ZERO } + }, + { "FelixW", + { ZERO, RIGHT, ZERO, PIN, LEFT, ZERO, LEFT, RIGHT, ZERO, ZERO, RIGHT, PIN, LEFT, ZERO, ZERO, LEFT, RIGHT, ZERO, RIGHT, PIN, ZERO, LEFT, ZERO, ZERO } + }, + { "Flamingo", + { ZERO, PIN, ZERO, ZERO, ZERO, ZERO, ZERO, PIN, LEFT, LEFT, PIN, LEFT, RIGHT, PIN, RIGHT, LEFT, PIN, LEFT, LEFT, ZERO, ZERO, ZERO, PIN, ZERO } + }, + { "FlatOnTheTop", + { ZERO, PIN, PIN, ZERO, PIN, RIGHT, ZERO, RIGHT, LEFT, PIN, RIGHT, RIGHT, PIN, LEFT, RIGHT, ZERO, RIGHT, ZERO, ZERO, PIN, ZERO, ZERO, PIN, ZERO } + }, + { "Fly", + { ZERO, LEFT, PIN, RIGHT, ZERO, PIN, LEFT, PIN, LEFT, RIGHT, PIN, RIGHT, PIN, RIGHT, PIN, LEFT, PIN, LEFT, PIN, LEFT, RIGHT, PIN, RIGHT, ZERO } + }, + { "Fountain", + { LEFT, RIGHT, LEFT, RIGHT, RIGHT, PIN, LEFT, PIN, LEFT, RIGHT, RIGHT, PIN, LEFT, LEFT, RIGHT, RIGHT, PIN, LEFT, LEFT, RIGHT, PIN, RIGHT, PIN, ZERO } + }, + { "Frog", + { LEFT, LEFT, RIGHT, RIGHT, LEFT, PIN, LEFT, PIN, RIGHT, PIN, LEFT, ZERO, RIGHT, ZERO, RIGHT, PIN, LEFT, ZERO, RIGHT, RIGHT, LEFT, RIGHT, RIGHT, ZERO } + }, + { "Frog2", + { LEFT, ZERO, LEFT, RIGHT, RIGHT, PIN, LEFT, RIGHT, ZERO, ZERO, RIGHT, PIN, LEFT, ZERO, ZERO, LEFT, RIGHT, PIN, LEFT, LEFT, RIGHT, ZERO, RIGHT, ZERO } + }, + { "Furby", + { PIN, ZERO, LEFT, PIN, RIGHT, ZERO, PIN, PIN, ZERO, PIN, PIN, ZERO, ZERO, PIN, ZERO, RIGHT, PIN, LEFT, ZERO, PIN, ZERO, ZERO, PIN, ZERO } + }, + { "Gate", + { ZERO, ZERO, PIN, ZERO, ZERO, RIGHT, ZERO, PIN, PIN, ZERO, LEFT, PIN, LEFT, LEFT, PIN, RIGHT, RIGHT, PIN, RIGHT, ZERO, PIN, PIN, ZERO, ZERO } + }, + { "Ghost", + { LEFT, LEFT, LEFT, RIGHT, RIGHT, LEFT, RIGHT, LEFT, LEFT, RIGHT, RIGHT, RIGHT, PIN, LEFT, RIGHT, ZERO, ZERO, LEFT, RIGHT, ZERO, ZERO, LEFT, RIGHT, ZERO } + }, + { "Globus", + { RIGHT, LEFT, ZERO, PIN, LEFT, LEFT, RIGHT, RIGHT, LEFT, RIGHT, LEFT, LEFT, RIGHT, LEFT, RIGHT, RIGHT, LEFT, RIGHT, PIN, ZERO, RIGHT, LEFT, ZERO, ZERO } + }, + { "Grotto", + { PIN, PIN, ZERO, LEFT, RIGHT, LEFT, ZERO, PIN, RIGHT, PIN, LEFT, ZERO, ZERO, ZERO, ZERO, RIGHT, PIN, LEFT, PIN, ZERO, RIGHT, LEFT, RIGHT, ZERO } + }, + { "H", + { PIN, ZERO, PIN, PIN, ZERO, ZERO, ZERO, ZERO, PIN, PIN, ZERO, PIN, LEFT, ZERO, PIN, PIN, ZERO, ZERO, ZERO, ZERO, PIN, PIN, ZERO, ZERO } + }, + { "HeadOfDevil", + { PIN, ZERO, RIGHT, ZERO, RIGHT, PIN, LEFT, ZERO, RIGHT, PIN, RIGHT, LEFT, PIN, LEFT, LEFT, PIN, RIGHT, RIGHT, PIN, RIGHT, LEFT, ZERO, ZERO, ZERO } + }, + { "Heart", + { RIGHT, ZERO, ZERO, ZERO, PIN, LEFT, PIN, LEFT, RIGHT, RIGHT, ZERO, PIN, ZERO, LEFT, LEFT, RIGHT, PIN, RIGHT, PIN, ZERO, ZERO, ZERO, LEFT, ZERO } + }, + { "Heart2", + { ZERO, PIN, ZERO, ZERO, LEFT, ZERO, LEFT, ZERO, ZERO, ZERO, ZERO, PIN, ZERO, ZERO, ZERO, ZERO, RIGHT, ZERO, RIGHT, ZERO, ZERO, PIN, ZERO, ZERO } + }, + { "Hexagon", + { ZERO, ZERO, ZERO, ZERO, LEFT, ZERO, ZERO, RIGHT, ZERO, ZERO, ZERO, ZERO, LEFT, ZERO, ZERO, RIGHT, ZERO, ZERO, ZERO, ZERO, LEFT, ZERO, ZERO, ZERO } + }, + { "HoleInTheMiddle1", + { ZERO, LEFT, RIGHT, PIN, LEFT, LEFT, PIN, RIGHT, LEFT, ZERO, LEFT, RIGHT, ZERO, RIGHT, LEFT, PIN, RIGHT, RIGHT, PIN, LEFT, RIGHT, ZERO, RIGHT, ZERO } + }, + { "HoleInTheMiddle2", + { ZERO, LEFT, RIGHT, ZERO, RIGHT, RIGHT, PIN, LEFT, RIGHT, ZERO, RIGHT, LEFT, ZERO, LEFT, RIGHT, ZERO, RIGHT, RIGHT, PIN, LEFT, RIGHT, ZERO, RIGHT, ZERO } + }, + { "HouseBoat", + { RIGHT, RIGHT, PIN, LEFT, LEFT, LEFT, PIN, RIGHT, RIGHT, RIGHT, PIN, LEFT, RIGHT, ZERO, LEFT, PIN, RIGHT, PIN, LEFT, PIN, LEFT, RIGHT, PIN, ZERO } + }, + { "HouseByHouse", + { LEFT, PIN, LEFT, PIN, LEFT, PIN, RIGHT, PIN, RIGHT, PIN, RIGHT, PIN, LEFT, PIN, LEFT, PIN, LEFT, PIN, RIGHT, PIN, RIGHT, PIN, RIGHT, ZERO } + }, + { "Infinity", + { LEFT, LEFT, LEFT, RIGHT, RIGHT, LEFT, LEFT, RIGHT, RIGHT, LEFT, LEFT, LEFT, LEFT, LEFT, LEFT, RIGHT, RIGHT, LEFT, LEFT, RIGHT, RIGHT, LEFT, LEFT, ZERO } + }, + { "Integral", + { RIGHT, RIGHT, RIGHT, RIGHT, RIGHT, LEFT, LEFT, RIGHT, LEFT, RIGHT, RIGHT, LEFT, LEFT, LEFT, LEFT, LEFT, LEFT, RIGHT, RIGHT, LEFT, RIGHT, LEFT, LEFT, ZERO } + }, + { "Iron", + { ZERO, ZERO, ZERO, ZERO, PIN, RIGHT, ZERO, RIGHT, ZERO, ZERO, LEFT, PIN, RIGHT, ZERO, ZERO, RIGHT, PIN, LEFT, ZERO, ZERO, RIGHT, ZERO, RIGHT, ZERO } + }, + { "just squares", + { RIGHT, RIGHT, LEFT, PIN, LEFT, PIN, RIGHT, PIN, RIGHT, LEFT, LEFT, PIN, RIGHT, RIGHT, LEFT, PIN, LEFT, PIN, RIGHT, PIN, RIGHT, LEFT, LEFT, ZERO } + }, + { "Kink", + { ZERO, PIN, PIN, ZERO, PIN, ZERO, PIN, PIN, ZERO, ZERO, RIGHT, PIN, LEFT, ZERO, ZERO, PIN, PIN, ZERO, PIN, ZERO, PIN, PIN, ZERO, ZERO } + }, + { "Knot", + { LEFT, LEFT, PIN, LEFT, ZERO, LEFT, RIGHT, LEFT, PIN, LEFT, LEFT, RIGHT, RIGHT, PIN, RIGHT, LEFT, RIGHT, ZERO, RIGHT, PIN, RIGHT, RIGHT, LEFT, ZERO } + }, + { "Leaf", + { ZERO, PIN, PIN, ZERO, ZERO, LEFT, ZERO, LEFT, ZERO, ZERO, PIN, ZERO, ZERO, RIGHT, ZERO, RIGHT, PIN, LEFT, ZERO, RIGHT, PIN, LEFT, ZERO, ZERO } + }, + { "LeftAsRight", + { RIGHT, PIN, LEFT, RIGHT, LEFT, ZERO, RIGHT, LEFT, PIN, RIGHT, RIGHT, PIN, LEFT, LEFT, PIN, RIGHT, LEFT, ZERO, RIGHT, LEFT, RIGHT, PIN, LEFT, ZERO } + }, + { "Long-necked", + { PIN, ZERO, LEFT, PIN, LEFT, PIN, RIGHT, PIN, RIGHT, ZERO, PIN, ZERO, LEFT, PIN, LEFT, PIN, RIGHT, PIN, LEFT, ZERO, PIN, PIN, ZERO, ZERO } + }, + { "lunar module", + { PIN, LEFT, LEFT, RIGHT, LEFT, RIGHT, RIGHT, LEFT, RIGHT, LEFT, LEFT, RIGHT, LEFT, RIGHT, RIGHT, PIN, LEFT, RIGHT, ZERO, RIGHT, LEFT, ZERO, LEFT, ZERO } + }, + { "magnifying glass", + { ZERO, ZERO, PIN, ZERO, LEFT, ZERO, PIN, PIN, ZERO, ZERO, RIGHT, PIN, LEFT, ZERO, ZERO, PIN, PIN, ZERO, RIGHT, ZERO, PIN, ZERO, ZERO, ZERO } + }, + { "Mask", + { ZERO, ZERO, ZERO, RIGHT, ZERO, RIGHT, LEFT, ZERO, LEFT, PIN, ZERO, PIN, ZERO, ZERO, PIN, ZERO, PIN, RIGHT, ZERO, RIGHT, LEFT, ZERO, LEFT, ZERO } + }, + { "Microscope", + { PIN, PIN, ZERO, ZERO, PIN, ZERO, RIGHT, PIN, ZERO, ZERO, RIGHT, PIN, LEFT, ZERO, ZERO, PIN, LEFT, ZERO, PIN, PIN, ZERO, PIN, PIN, ZERO } + }, + { "Mirror", + { PIN, RIGHT, LEFT, ZERO, PIN, PIN, ZERO, ZERO, LEFT, RIGHT, ZERO, ZERO, PIN, ZERO, ZERO, LEFT, RIGHT, PIN, RIGHT, ZERO, PIN, PIN, ZERO, ZERO } + }, + { "MissPiggy", + { ZERO, LEFT, LEFT, PIN, RIGHT, ZERO, RIGHT, RIGHT, PIN, LEFT, LEFT, RIGHT, RIGHT, PIN, LEFT, LEFT, ZERO, LEFT, PIN, RIGHT, RIGHT, ZERO, RIGHT, ZERO } + }, + { "Mole", + { ZERO, RIGHT, ZERO, RIGHT, LEFT, RIGHT, PIN, ZERO, LEFT, PIN, RIGHT, ZERO, PIN, LEFT, RIGHT, LEFT, ZERO, LEFT, ZERO, RIGHT, RIGHT, PIN, LEFT, ZERO } + }, + { "Monk", + { LEFT, ZERO, PIN, PIN, ZERO, LEFT, ZERO, PIN, PIN, ZERO, RIGHT, ZERO, PIN, PIN, ZERO, RIGHT, LEFT, RIGHT, RIGHT, LEFT, RIGHT, LEFT, LEFT, ZERO } + }, + { "Mountain", + { ZERO, RIGHT, LEFT, PIN, RIGHT, RIGHT, PIN, LEFT, RIGHT, ZERO, LEFT, PIN, LEFT, ZERO, RIGHT, LEFT, PIN, RIGHT, RIGHT, PIN, LEFT, RIGHT, ZERO, ZERO } + }, + { "mountains", + { ZERO, PIN, ZERO, LEFT, PIN, LEFT, RIGHT, PIN, RIGHT, PIN, RIGHT, PIN, LEFT, PIN, LEFT, PIN, LEFT, RIGHT, PIN, RIGHT, ZERO, PIN, ZERO, ZERO } + }, + { "MouseWithoutTail", + { ZERO, PIN, PIN, ZERO, LEFT, ZERO, PIN, PIN, ZERO, ZERO, RIGHT, PIN, LEFT, ZERO, ZERO, PIN, PIN, ZERO, RIGHT, ZERO, PIN, PIN, ZERO, ZERO } + }, + { "mushroom", + { PIN, LEFT, LEFT, RIGHT, LEFT, RIGHT, RIGHT, PIN, LEFT, RIGHT, ZERO, ZERO, LEFT, PIN, ZERO, RIGHT, ZERO, PIN, PIN, ZERO, LEFT, ZERO, PIN, ZERO } + }, + { "necklace", + { ZERO, ZERO, LEFT, ZERO, ZERO, ZERO, LEFT, ZERO, ZERO, ZERO, ZERO, PIN, ZERO, ZERO, ZERO, ZERO, RIGHT, ZERO, ZERO, ZERO, RIGHT, ZERO, ZERO, ZERO } + }, + { "NestledAgainst", + { LEFT, ZERO, PIN, LEFT, LEFT, RIGHT, RIGHT, PIN, ZERO, RIGHT, PIN, LEFT, ZERO, RIGHT, LEFT, PIN, RIGHT, RIGHT, LEFT, RIGHT, LEFT, LEFT, LEFT, ZERO } + }, + { "NoClue", + { ZERO, RIGHT, PIN, LEFT, LEFT, LEFT, ZERO, LEFT, PIN, RIGHT, RIGHT, PIN, LEFT, LEFT, PIN, RIGHT, ZERO, RIGHT, RIGHT, RIGHT, PIN, LEFT, ZERO, ZERO } + }, + { "Noname", + { LEFT, PIN, RIGHT, PIN, RIGHT, ZERO, PIN, ZERO, ZERO, PIN, PIN, ZERO, PIN, PIN, ZERO, RIGHT, PIN, LEFT, PIN, RIGHT, PIN, RIGHT, LEFT, ZERO } + }, + { "Obelisk", + { PIN, ZERO, ZERO, ZERO, PIN, RIGHT, PIN, LEFT, PIN, LEFT, PIN, LEFT, RIGHT, PIN, RIGHT, PIN, RIGHT, PIN, LEFT, PIN, ZERO, ZERO, ZERO, ZERO } + }, + { "Ostrich", + { ZERO, ZERO, PIN, PIN, ZERO, LEFT, ZERO, PIN, PIN, ZERO, PIN, PIN, ZERO, RIGHT, ZERO, PIN, PIN, ZERO, ZERO, ZERO, ZERO, ZERO, PIN, ZERO } + }, + { "Ostrich2", + { PIN, PIN, ZERO, PIN, LEFT, LEFT, LEFT, RIGHT, LEFT, RIGHT, RIGHT, LEFT, RIGHT, LEFT, LEFT, RIGHT, PIN, ZERO, PIN, ZERO, ZERO, PIN, ZERO, ZERO } + }, + { "pair of glasses", + { ZERO, PIN, ZERO, ZERO, PIN, ZERO, ZERO, PIN, ZERO, LEFT, ZERO, PIN, ZERO, RIGHT, ZERO, PIN, ZERO, ZERO, PIN, ZERO, ZERO, PIN, ZERO, ZERO } + }, + { "Parrot", + { ZERO, ZERO, ZERO, ZERO, RIGHT, RIGHT, ZERO, LEFT, PIN, RIGHT, ZERO, RIGHT, ZERO, RIGHT, ZERO, RIGHT, PIN, LEFT, ZERO, RIGHT, LEFT, ZERO, PIN, ZERO } + }, + { "Penis", + { PIN, PIN, RIGHT, ZERO, PIN, PIN, ZERO, PIN, ZERO, ZERO, RIGHT, PIN, LEFT, ZERO, ZERO, PIN, ZERO, PIN, PIN, ZERO, LEFT, PIN, PIN, ZERO } + }, + { "PictureComingSoon", + { LEFT, LEFT, ZERO, RIGHT, LEFT, PIN, RIGHT, RIGHT, PIN, RIGHT, LEFT, PIN, LEFT, RIGHT, PIN, RIGHT, RIGHT, PIN, RIGHT, LEFT, ZERO, RIGHT, RIGHT, ZERO } + }, + { "Pitti", + { LEFT, PIN, ZERO, ZERO, PIN, ZERO, ZERO, PIN, ZERO, ZERO, RIGHT, PIN, LEFT, ZERO, ZERO, PIN, ZERO, ZERO, PIN, ZERO, ZERO, PIN, RIGHT, ZERO } + }, + { "Plait", + { LEFT, LEFT, LEFT, LEFT, LEFT, LEFT, LEFT, LEFT, LEFT, LEFT, RIGHT, LEFT, RIGHT, RIGHT, RIGHT, RIGHT, RIGHT, RIGHT, RIGHT, RIGHT, RIGHT, RIGHT, LEFT, ZERO } + }, + { "Platform", + { RIGHT, PIN, ZERO, ZERO, ZERO, ZERO, PIN, ZERO, ZERO, PIN, PIN, ZERO, PIN, LEFT, ZERO, RIGHT, LEFT, PIN, RIGHT, RIGHT, PIN, LEFT, RIGHT, ZERO } + }, + { "PodRacer", + { ZERO, PIN, ZERO, PIN, RIGHT, PIN, ZERO, RIGHT, PIN, LEFT, LEFT, PIN, RIGHT, LEFT, ZERO, PIN, PIN, ZERO, ZERO, LEFT, ZERO, PIN, LEFT, ZERO } + }, +#if 0 + { "Pokemon", + { LEFT, LEFT, RIGHT, LEFT, RIGHT, RIGHT, LEFT, LEFT, LEFT, RIGHT, LEFT, RIGHT, RIGHT, LEFT, LEFT, RIGHT, RIGHT, LEFT, LEFT, RIGHT, LEFT, RIGHT, RIGHT, ZERO } + }, +#endif + { "Prawn", + { RIGHT, PIN, ZERO, PIN, RIGHT, ZERO, PIN, PIN, ZERO, ZERO, LEFT, PIN, RIGHT, ZERO, ZERO, PIN, PIN, ZERO, LEFT, PIN, ZERO, PIN, LEFT, ZERO } + }, + { "Propeller", + { ZERO, ZERO, ZERO, RIGHT, ZERO, LEFT, RIGHT, LEFT, ZERO, ZERO, ZERO, RIGHT, ZERO, LEFT, RIGHT, LEFT, ZERO, ZERO, ZERO, RIGHT, ZERO, LEFT, RIGHT, ZERO } + }, + { "Pyramid", + { ZERO, LEFT, PIN, RIGHT, ZERO, LEFT, PIN, RIGHT, ZERO, LEFT, PIN, RIGHT, ZERO, PIN, RIGHT, LEFT, LEFT, LEFT, PIN, RIGHT, RIGHT, RIGHT, LEFT, ZERO } + }, + { "QuarterbackTiltedAndReadyToHut", + { PIN, ZERO, RIGHT, RIGHT, LEFT, RIGHT, PIN, RIGHT, LEFT, RIGHT, ZERO, PIN, ZERO, LEFT, RIGHT, LEFT, PIN, LEFT, RIGHT, LEFT, LEFT, ZERO, PIN, ZERO } + }, + { "Ra", + { PIN, LEFT, LEFT, LEFT, RIGHT, LEFT, RIGHT, RIGHT, LEFT, RIGHT, LEFT, LEFT, ZERO, LEFT, LEFT, RIGHT, LEFT, RIGHT, RIGHT, LEFT, RIGHT, LEFT, LEFT, ZERO } + }, + { "Rattlesnake", + { LEFT, ZERO, LEFT, ZERO, LEFT, ZERO, LEFT, LEFT, ZERO, LEFT, ZERO, LEFT, ZERO, LEFT, RIGHT, ZERO, PIN, RIGHT, RIGHT, RIGHT, RIGHT, RIGHT, RIGHT, ZERO } + }, + { "Revelation", + { ZERO, ZERO, ZERO, PIN, ZERO, ZERO, PIN, RIGHT, LEFT, LEFT, LEFT, RIGHT, RIGHT, LEFT, LEFT, RIGHT, RIGHT, RIGHT, LEFT, PIN, ZERO, ZERO, PIN, ZERO } + }, + { "Revolution1", + { LEFT, LEFT, PIN, RIGHT, ZERO, PIN, ZERO, LEFT, PIN, RIGHT, RIGHT, PIN, LEFT, LEFT, PIN, RIGHT, ZERO, PIN, ZERO, LEFT, PIN, RIGHT, RIGHT, ZERO } + }, + { "Ribbon", + { RIGHT, RIGHT, LEFT, RIGHT, LEFT, LEFT, PIN, ZERO, PIN, PIN, ZERO, PIN, ZERO, PIN, PIN, ZERO, PIN, RIGHT, RIGHT, LEFT, RIGHT, LEFT, LEFT, ZERO } + }, + { "Rocket", + { RIGHT, ZERO, LEFT, PIN, RIGHT, ZERO, RIGHT, ZERO, LEFT, ZERO, RIGHT, PIN, LEFT, ZERO, RIGHT, ZERO, LEFT, ZERO, LEFT, PIN, RIGHT, ZERO, LEFT, ZERO } + }, + { "Roofed", + { ZERO, LEFT, PIN, RIGHT, ZERO, PIN, LEFT, ZERO, PIN, ZERO, RIGHT, PIN, ZERO, LEFT, PIN, RIGHT, ZERO, PIN, LEFT, ZERO, PIN, ZERO, RIGHT, ZERO } + }, + { "Roofs", + { PIN, PIN, RIGHT, ZERO, LEFT, PIN, RIGHT, PIN, LEFT, PIN, LEFT, PIN, RIGHT, PIN, RIGHT, PIN, LEFT, PIN, RIGHT, ZERO, LEFT, PIN, PIN, ZERO } + }, + { "RowHouses", + { RIGHT, PIN, LEFT, PIN, RIGHT, PIN, RIGHT, PIN, LEFT, PIN, LEFT, PIN, RIGHT, PIN, RIGHT, PIN, LEFT, PIN, LEFT, PIN, RIGHT, PIN, LEFT, ZERO } + }, + { "Sculpture", + { RIGHT, LEFT, PIN, ZERO, ZERO, ZERO, LEFT, RIGHT, LEFT, PIN, ZERO, ZERO, PIN, LEFT, RIGHT, LEFT, ZERO, ZERO, ZERO, PIN, LEFT, RIGHT, LEFT, ZERO } + }, + { "Seal", + { LEFT, LEFT, LEFT, PIN, RIGHT, RIGHT, RIGHT, ZERO, LEFT, PIN, RIGHT, ZERO, LEFT, LEFT, LEFT, PIN, RIGHT, LEFT, ZERO, PIN, PIN, ZERO, LEFT, ZERO } + }, + { "Seal2", + { RIGHT, PIN, ZERO, LEFT, LEFT, LEFT, RIGHT, LEFT, RIGHT, RIGHT, RIGHT, PIN, RIGHT, RIGHT, PIN, LEFT, RIGHT, ZERO, ZERO, LEFT, RIGHT, ZERO, ZERO, ZERO } + }, + { "Sheep", + { RIGHT, LEFT, LEFT, RIGHT, RIGHT, LEFT, LEFT, RIGHT, LEFT, RIGHT, RIGHT, RIGHT, RIGHT, RIGHT, LEFT, RIGHT, LEFT, LEFT, LEFT, LEFT, LEFT, RIGHT, LEFT, ZERO } + }, + { "Shelter", + { LEFT, RIGHT, LEFT, RIGHT, RIGHT, LEFT, RIGHT, LEFT, LEFT, RIGHT, ZERO, ZERO, ZERO, ZERO, PIN, ZERO, ZERO, PIN, ZERO, ZERO, ZERO, ZERO, RIGHT, ZERO } + }, + { "Ship", + { PIN, RIGHT, LEFT, LEFT, LEFT, LEFT, PIN, RIGHT, RIGHT, RIGHT, RIGHT, LEFT, ZERO, LEFT, ZERO, RIGHT, PIN, LEFT, ZERO, LEFT, ZERO, PIN, PIN, ZERO } + }, + { "Shpongle", + { LEFT, RIGHT, ZERO, RIGHT, LEFT, RIGHT, ZERO, RIGHT, LEFT, RIGHT, ZERO, RIGHT, LEFT, RIGHT, ZERO, RIGHT, LEFT, RIGHT, ZERO, RIGHT, LEFT, RIGHT, ZERO, ZERO } + }, + { "Slide", + { LEFT, RIGHT, LEFT, RIGHT, ZERO, LEFT, RIGHT, LEFT, PIN, ZERO, ZERO, PIN, ZERO, ZERO, PIN, RIGHT, LEFT, ZERO, ZERO, RIGHT, LEFT, RIGHT, LEFT, ZERO } + }, + { "SmallShip", + { ZERO, LEFT, RIGHT, ZERO, RIGHT, LEFT, ZERO, LEFT, RIGHT, ZERO, LEFT, RIGHT, ZERO, LEFT, RIGHT, ZERO, RIGHT, LEFT, ZERO, LEFT, RIGHT, ZERO, LEFT, ZERO } + }, + { "SnakeReadyToStrike", + { LEFT, ZERO, LEFT, ZERO, LEFT, ZERO, LEFT, RIGHT, ZERO, RIGHT, ZERO, RIGHT, ZERO, LEFT, ZERO, ZERO, ZERO, PIN, ZERO, ZERO, ZERO, ZERO, LEFT, ZERO } + }, + { "Snakes14", + { RIGHT, RIGHT, PIN, ZERO, RIGHT, LEFT, RIGHT, ZERO, ZERO, ZERO, RIGHT, PIN, LEFT, PIN, ZERO, PIN, LEFT, PIN, RIGHT, ZERO, ZERO, LEFT, RIGHT, ZERO } + }, + { "Snakes15", + { ZERO, PIN, PIN, ZERO, PIN, PIN, ZERO, PIN, LEFT, LEFT, PIN, RIGHT, LEFT, ZERO, PIN, LEFT, PIN, RIGHT, ZERO, ZERO, ZERO, PIN, RIGHT, ZERO } + }, + { "Snakes18", + { PIN, PIN, LEFT, PIN, LEFT, PIN, RIGHT, ZERO, RIGHT, PIN, RIGHT, ZERO, RIGHT, PIN, LEFT, PIN, RIGHT, ZERO, PIN, PIN, ZERO, ZERO, PIN, ZERO } + }, + { "Snowflake", + { LEFT, LEFT, LEFT, RIGHT, RIGHT, RIGHT, RIGHT, LEFT, LEFT, LEFT, LEFT, RIGHT, RIGHT, RIGHT, RIGHT, LEFT, LEFT, LEFT, LEFT, RIGHT, RIGHT, RIGHT, RIGHT, ZERO } + }, + { "Snowman", + { ZERO, PIN, PIN, ZERO, PIN, PIN, ZERO, ZERO, ZERO, PIN, PIN, ZERO, PIN, PIN, ZERO, ZERO, ZERO, PIN, PIN, ZERO, PIN, PIN, ZERO, ZERO } + }, + { "Source", + { PIN, RIGHT, ZERO, PIN, ZERO, LEFT, PIN, RIGHT, PIN, LEFT, LEFT, RIGHT, LEFT, RIGHT, RIGHT, PIN, LEFT, LEFT, RIGHT, LEFT, RIGHT, RIGHT, PIN, ZERO } + }, + { "Spaceship", + { PIN, PIN, RIGHT, RIGHT, PIN, RIGHT, LEFT, PIN, LEFT, PIN, RIGHT, PIN, RIGHT, LEFT, PIN, LEFT, RIGHT, PIN, RIGHT, PIN, RIGHT, PIN, PIN, ZERO } + }, + { "Spaceship2", + { PIN, PIN, LEFT, PIN, LEFT, PIN, RIGHT, ZERO, PIN, PIN, ZERO, LEFT, PIN, RIGHT, ZERO, PIN, ZERO, LEFT, PIN, LEFT, LEFT, PIN, PIN, ZERO } + }, + { "Speedboat", + { LEFT, ZERO, ZERO, LEFT, PIN, RIGHT, ZERO, ZERO, LEFT, ZERO, ZERO, PIN, ZERO, ZERO, RIGHT, ZERO, ZERO, LEFT, PIN, RIGHT, ZERO, ZERO, RIGHT, ZERO } + }, + { "Speedboat2", + { PIN, RIGHT, LEFT, LEFT, RIGHT, RIGHT, RIGHT, ZERO, LEFT, PIN, RIGHT, ZERO, LEFT, LEFT, LEFT, RIGHT, RIGHT, LEFT, PIN, ZERO, RIGHT, PIN, LEFT, ZERO } + }, + { "Spider", + { RIGHT, RIGHT, ZERO, ZERO, LEFT, RIGHT, LEFT, PIN, ZERO, LEFT, ZERO, PIN, PIN, ZERO, RIGHT, ZERO, PIN, RIGHT, LEFT, RIGHT, ZERO, ZERO, LEFT, ZERO } + }, + { "Spitzbergen", + { PIN, LEFT, ZERO, RIGHT, RIGHT, LEFT, PIN, ZERO, LEFT, PIN, RIGHT, RIGHT, PIN, LEFT, LEFT, PIN, RIGHT, ZERO, PIN, RIGHT, LEFT, LEFT, ZERO, ZERO } + }, + { "Square", + { ZERO, ZERO, LEFT, LEFT, PIN, RIGHT, RIGHT, ZERO, ZERO, LEFT, LEFT, PIN, RIGHT, RIGHT, ZERO, ZERO, LEFT, LEFT, PIN, RIGHT, RIGHT, ZERO, ZERO, ZERO } + }, + { "SquareHole", + { PIN, ZERO, PIN, ZERO, ZERO, PIN, PIN, ZERO, PIN, ZERO, ZERO, PIN, ZERO, ZERO, PIN, ZERO, PIN, PIN, ZERO, ZERO, PIN, ZERO, PIN, ZERO } + }, + { "Stage", + { RIGHT, ZERO, LEFT, PIN, LEFT, RIGHT, PIN, RIGHT, LEFT, RIGHT, PIN, RIGHT, LEFT, PIN, LEFT, RIGHT, LEFT, PIN, LEFT, RIGHT, PIN, RIGHT, ZERO, ZERO } + }, + { "Stairs", + { ZERO, PIN, ZERO, PIN, ZERO, PIN, ZERO, PIN, ZERO, PIN, ZERO, PIN, ZERO, PIN, ZERO, PIN, ZERO, PIN, ZERO, PIN, ZERO, PIN, ZERO, ZERO } + }, + { "Stairs2", + { ZERO, PIN, ZERO, PIN, ZERO, PIN, PIN, ZERO, ZERO, PIN, ZERO, PIN, ZERO, PIN, ZERO, PIN, ZERO, PIN, PIN, ZERO, ZERO, PIN, ZERO, ZERO } + }, + { "Straight", + { ZERO, ZERO, ZERO, ZERO, ZERO, ZERO, ZERO, ZERO, ZERO, ZERO, ZERO, ZERO, ZERO, ZERO, ZERO, ZERO, ZERO, ZERO, ZERO, ZERO, ZERO, ZERO, ZERO, ZERO } + }, + { "Swan", + { ZERO, PIN, ZERO, PIN, LEFT, LEFT, PIN, LEFT, PIN, RIGHT, PIN, RIGHT, LEFT, PIN, LEFT, RIGHT, PIN, RIGHT, PIN, LEFT, PIN, LEFT, RIGHT, ZERO } + }, + { "Swan2", + { PIN, ZERO, PIN, RIGHT, RIGHT, RIGHT, LEFT, RIGHT, LEFT, LEFT, RIGHT, LEFT, RIGHT, RIGHT, RIGHT, PIN, ZERO, ZERO, ZERO, ZERO, ZERO, PIN, PIN, ZERO } + }, + { "Swan3", + { PIN, PIN, ZERO, ZERO, ZERO, RIGHT, ZERO, RIGHT, ZERO, ZERO, LEFT, PIN, RIGHT, ZERO, ZERO, RIGHT, PIN, LEFT, ZERO, ZERO, RIGHT, ZERO, RIGHT, ZERO } + }, + { "Symbol", + { RIGHT, RIGHT, PIN, ZERO, PIN, PIN, ZERO, PIN, LEFT, LEFT, RIGHT, LEFT, RIGHT, RIGHT, PIN, ZERO, PIN, PIN, ZERO, PIN, LEFT, LEFT, RIGHT, ZERO } + }, + { "Symmetry", + { RIGHT, ZERO, LEFT, RIGHT, LEFT, ZERO, LEFT, RIGHT, LEFT, ZERO, RIGHT, PIN, LEFT, ZERO, RIGHT, LEFT, RIGHT, ZERO, RIGHT, LEFT, RIGHT, ZERO, LEFT, ZERO } + }, + { "Symmetry2", + { ZERO, PIN, LEFT, LEFT, PIN, ZERO, ZERO, LEFT, PIN, RIGHT, PIN, LEFT, LEFT, PIN, RIGHT, RIGHT, PIN, LEFT, LEFT, PIN, RIGHT, PIN, LEFT, ZERO } + }, + { "TableFireworks", + { ZERO, RIGHT, LEFT, PIN, RIGHT, RIGHT, RIGHT, PIN, LEFT, RIGHT, ZERO, RIGHT, LEFT, PIN, RIGHT, RIGHT, RIGHT, PIN, RIGHT, LEFT, ZERO, RIGHT, PIN, ZERO } + }, + { "Tapering", + { ZERO, ZERO, RIGHT, LEFT, PIN, LEFT, ZERO, PIN, PIN, ZERO, LEFT, PIN, RIGHT, ZERO, PIN, PIN, ZERO, RIGHT, PIN, RIGHT, LEFT, ZERO, ZERO, ZERO } + }, + { "TaperingTurned", + { ZERO, ZERO, RIGHT, LEFT, PIN, LEFT, ZERO, PIN, PIN, ZERO, LEFT, ZERO, RIGHT, ZERO, PIN, PIN, ZERO, RIGHT, PIN, RIGHT, LEFT, ZERO, ZERO, ZERO } + }, + { "TeaLightStick", + { RIGHT, ZERO, PIN, PIN, ZERO, LEFT, RIGHT, PIN, LEFT, LEFT, RIGHT, RIGHT, PIN, LEFT, LEFT, RIGHT, RIGHT, PIN, LEFT, LEFT, RIGHT, RIGHT, PIN, ZERO } + }, + { "thighmaster", + { RIGHT, ZERO, ZERO, RIGHT, LEFT, ZERO, ZERO, RIGHT, LEFT, ZERO, ZERO, LEFT, RIGHT, ZERO, ZERO, RIGHT, LEFT, ZERO, ZERO, RIGHT, LEFT, ZERO, ZERO, ZERO } + }, + { "Terraces", + { RIGHT, LEFT, ZERO, RIGHT, LEFT, PIN, LEFT, LEFT, PIN, LEFT, RIGHT, RIGHT, RIGHT, LEFT, LEFT, LEFT, RIGHT, PIN, RIGHT, RIGHT, PIN, RIGHT, LEFT, ZERO } + }, + { "Terrier", + { PIN, ZERO, PIN, PIN, ZERO, PIN, ZERO, ZERO, ZERO, PIN, PIN, ZERO, PIN, ZERO, ZERO, PIN, ZERO, PIN, PIN, ZERO, ZERO, ZERO, ZERO, ZERO } + }, + { "Three-Legged", + { RIGHT, ZERO, LEFT, RIGHT, ZERO, LEFT, PIN, RIGHT, ZERO, RIGHT, ZERO, PIN, ZERO, LEFT, ZERO, LEFT, PIN, RIGHT, ZERO, LEFT, RIGHT, ZERO, LEFT, ZERO } + }, + { "ThreePeaks", + { RIGHT, ZERO, ZERO, RIGHT, PIN, LEFT, PIN, RIGHT, PIN, RIGHT, RIGHT, PIN, LEFT, LEFT, PIN, LEFT, PIN, RIGHT, PIN, LEFT, ZERO, ZERO, LEFT, ZERO } + }, + { "ToTheFront", + { ZERO, PIN, RIGHT, LEFT, LEFT, LEFT, PIN, RIGHT, LEFT, ZERO, PIN, PIN, ZERO, LEFT, LEFT, PIN, ZERO, LEFT, RIGHT, ZERO, PIN, ZERO, LEFT, ZERO } + }, + { "Top", + { PIN, LEFT, LEFT, PIN, LEFT, ZERO, ZERO, RIGHT, LEFT, PIN, RIGHT, RIGHT, LEFT, RIGHT, LEFT, LEFT, PIN, RIGHT, PIN, RIGHT, RIGHT, PIN, ZERO, ZERO } + }, + { "Transport", + { PIN, ZERO, ZERO, PIN, PIN, ZERO, PIN, PIN, ZERO, PIN, PIN, ZERO, PIN, PIN, ZERO, PIN, PIN, ZERO, ZERO, PIN, ZERO, ZERO, ZERO, ZERO } + }, + { "Triangle", + { ZERO, ZERO, ZERO, ZERO, ZERO, ZERO, RIGHT, LEFT, ZERO, ZERO, ZERO, ZERO, ZERO, ZERO, RIGHT, LEFT, ZERO, ZERO, ZERO, ZERO, ZERO, ZERO, RIGHT, ZERO } + }, + { "Tripple", + { PIN, ZERO, PIN, LEFT, PIN, RIGHT, PIN, RIGHT, PIN, ZERO, PIN, LEFT, PIN, RIGHT, PIN, ZERO, PIN, LEFT, PIN, LEFT, PIN, RIGHT, PIN, ZERO } + }, +#if 0 + { "Turtle", + { RIGHT, RIGHT, RIGHT, LEFT, RIGHT, LEFT, LEFT, LEFT, PIN, LEFT, LEFT, RIGHT, LEFT, RIGHT, RIGHT, PIN, LEFT, RIGHT, ZERO, ZERO, LEFT, RIGHT, ZERO, ZERO } + }, +#endif + { "Twins", + { ZERO, PIN, ZERO, LEFT, PIN, LEFT, RIGHT, PIN, RIGHT, PIN, ZERO, ZERO, PIN, LEFT, PIN, LEFT, RIGHT, PIN, RIGHT, ZERO, PIN, ZERO, ZERO, ZERO } + }, + { "TwoSlants", + { ZERO, PIN, ZERO, ZERO, PIN, PIN, ZERO, PIN, ZERO, RIGHT, PIN, RIGHT, LEFT, PIN, LEFT, PIN, RIGHT, PIN, LEFT, ZERO, ZERO, RIGHT, PIN, ZERO } + }, + { "TwoWings", + { PIN, LEFT, ZERO, RIGHT, ZERO, PIN, PIN, ZERO, PIN, PIN, ZERO, PIN, PIN, ZERO, LEFT, ZERO, RIGHT, PIN, LEFT, ZERO, RIGHT, LEFT, ZERO, ZERO } + }, + { "UFO", + { LEFT, LEFT, RIGHT, LEFT, RIGHT, RIGHT, LEFT, RIGHT, LEFT, LEFT, LEFT, PIN, LEFT, LEFT, LEFT, RIGHT, LEFT, RIGHT, RIGHT, LEFT, RIGHT, LEFT, LEFT, ZERO } + }, + { "USS Enterprise", + { LEFT, PIN, RIGHT, PIN, RIGHT, LEFT, ZERO, PIN, PIN, ZERO, RIGHT, LEFT, ZERO, PIN, PIN, ZERO, RIGHT, LEFT, PIN, LEFT, PIN, RIGHT, ZERO, ZERO } + }, + { "UpAndDown", + { ZERO, PIN, ZERO, PIN, ZERO, PIN, LEFT, PIN, RIGHT, PIN, ZERO, PIN, ZERO, PIN, ZERO, PIN, ZERO, PIN, LEFT, PIN, RIGHT, PIN, ZERO, ZERO } + }, + { "Upright", + { ZERO, RIGHT, RIGHT, LEFT, RIGHT, LEFT, LEFT, PIN, ZERO, ZERO, LEFT, PIN, RIGHT, ZERO, ZERO, PIN, RIGHT, RIGHT, LEFT, RIGHT, LEFT, LEFT, ZERO, ZERO } + }, + { "Upside-down", + { PIN, ZERO, ZERO, ZERO, PIN, PIN, ZERO, RIGHT, RIGHT, LEFT, LEFT, PIN, RIGHT, RIGHT, LEFT, LEFT, ZERO, PIN, PIN, ZERO, ZERO, ZERO, PIN, ZERO } + }, + { "Valley", + { ZERO, RIGHT, PIN, LEFT, PIN, RIGHT, PIN, RIGHT, LEFT, RIGHT, ZERO, PIN, ZERO, LEFT, RIGHT, LEFT, PIN, LEFT, PIN, RIGHT, PIN, LEFT, ZERO, ZERO } + }, + { "Viaduct", + { PIN, RIGHT, PIN, LEFT, PIN, ZERO, ZERO, PIN, RIGHT, ZERO, RIGHT, RIGHT, ZERO, RIGHT, PIN, ZERO, ZERO, PIN, LEFT, PIN, RIGHT, PIN, ZERO, ZERO } + }, + { "View", + { ZERO, RIGHT, PIN, LEFT, PIN, RIGHT, ZERO, ZERO, RIGHT, PIN, LEFT, LEFT, RIGHT, RIGHT, PIN, LEFT, ZERO, ZERO, LEFT, PIN, RIGHT, PIN, LEFT, ZERO } + }, + { "Waterfall", + { LEFT, ZERO, RIGHT, PIN, LEFT, ZERO, RIGHT, PIN, LEFT, ZERO, RIGHT, PIN, LEFT, ZERO, RIGHT, PIN, LEFT, ZERO, RIGHT, PIN, LEFT, ZERO, RIGHT, ZERO } + }, + { "windwheel", + { PIN, RIGHT, RIGHT, PIN, ZERO, LEFT, PIN, RIGHT, RIGHT, PIN, ZERO, LEFT, PIN, RIGHT, RIGHT, PIN, ZERO, LEFT, PIN, RIGHT, RIGHT, PIN, ZERO, ZERO } + }, + { "Window", + { PIN, ZERO, PIN, PIN, ZERO, ZERO, PIN, ZERO, PIN, ZERO, PIN, ZERO, ZERO, PIN, ZERO, PIN, ZERO, PIN, PIN, ZERO, ZERO, ZERO, ZERO, ZERO } + }, + { "WindowToTheWorld", + { PIN, LEFT, ZERO, PIN, ZERO, ZERO, PIN, ZERO, ZERO, PIN, ZERO, RIGHT, PIN, LEFT, ZERO, PIN, ZERO, ZERO, PIN, ZERO, ZERO, PIN, ZERO, ZERO } + }, + { "Windshield", + { PIN, PIN, ZERO, RIGHT, PIN, LEFT, LEFT, PIN, RIGHT, ZERO, PIN, ZERO, LEFT, PIN, RIGHT, RIGHT, PIN, LEFT, ZERO, PIN, PIN, ZERO, PIN, ZERO } + }, + { "WingNut", + { ZERO, ZERO, ZERO, ZERO, PIN, RIGHT, RIGHT, RIGHT, PIN, RIGHT, LEFT, PIN, LEFT, RIGHT, PIN, RIGHT, RIGHT, RIGHT, PIN, ZERO, ZERO, ZERO, ZERO, ZERO } + }, + { "Wings2", + { RIGHT, ZERO, PIN, ZERO, LEFT, PIN, RIGHT, PIN, RIGHT, LEFT, RIGHT, RIGHT, LEFT, LEFT, RIGHT, LEFT, PIN, LEFT, PIN, RIGHT, ZERO, PIN, ZERO, ZERO } + }, + { "WithoutName", + { PIN, RIGHT, PIN, RIGHT, RIGHT, PIN, LEFT, LEFT, PIN, ZERO, PIN, RIGHT, PIN, LEFT, PIN, ZERO, PIN, RIGHT, RIGHT, PIN, LEFT, LEFT, PIN, ZERO } + }, + { "Wolf", + { ZERO, ZERO, PIN, PIN, ZERO, PIN, ZERO, ZERO, PIN, ZERO, PIN, PIN, ZERO, PIN, ZERO, ZERO, ZERO, PIN, PIN, ZERO, ZERO, ZERO, PIN, ZERO } + }, + { "X", + { LEFT, ZERO, ZERO, PIN, LEFT, RIGHT, RIGHT, PIN, LEFT, RIGHT, ZERO, PIN, PIN, ZERO, LEFT, RIGHT, PIN, LEFT, LEFT, RIGHT, PIN, ZERO, ZERO, ZERO } + }, +}; + +static size_t models = sizeof(model) / sizeof(struct model_s); + +#define VOFFSET 0.045 + +#define X_MASK 1 +#define Y_MASK 2 +#define Z_MASK 4 + +/* the connecting string that holds the snake together */ +#define MAGICAL_RED_STRING 0 + +#define GETSCALAR(vec,mask) ((vec)==(mask) ? 1 : ((vec)==-(mask) ? -1 : 0 )) + +#ifndef MAX +# define MAX(x, y) ((x) > (y) ? (x) : (y)) +#endif +#ifndef MIN +# define MIN(x, y) ((x) < (y) ? (x) : (y)) +#endif + +#define RAND(n) ((random() & 0x7fffffff) % ((long) (n))) +#define RANDSIGN() ((random() & 1) ? 1 : -1) + +/* the triangular prism what makes up the basic unit */ +static const float solid_prism_v[][3] = { + /* first corner, bottom left front */ + { VOFFSET, VOFFSET, 1.0 }, + { VOFFSET, 0.00, 1.0 - VOFFSET }, + { 0.00, VOFFSET, 1.0 - VOFFSET }, + /* second corner, rear */ + { VOFFSET, VOFFSET, 0.00 }, + { VOFFSET, 0.00, VOFFSET }, + { 0.00, VOFFSET, VOFFSET }, + /* third, right front */ + { 1.0 - VOFFSET / M_SQRT1_2, VOFFSET, 1.0 }, + { 1.0 - VOFFSET / M_SQRT1_2, 0.0, 1.0 - VOFFSET }, + { 1.0 - VOFFSET * M_SQRT1_2, VOFFSET, 1.0 - VOFFSET }, + /* fourth, right rear */ + { 1.0 - VOFFSET / M_SQRT1_2, VOFFSET, 0.0 }, + { 1.0 - VOFFSET / M_SQRT1_2, 0.0, VOFFSET }, + { 1.0 - VOFFSET * M_SQRT1_2, VOFFSET, VOFFSET }, + /* fifth, upper front */ + { VOFFSET, 1.0 - VOFFSET / M_SQRT1_2, 1.0 }, + { VOFFSET / M_SQRT1_2, 1.0 - VOFFSET * M_SQRT1_2, 1.0 - VOFFSET }, + { 0.0, 1.0 - VOFFSET / M_SQRT1_2, 1.0 - VOFFSET}, + /* sixth, upper rear */ + { VOFFSET, 1.0 - VOFFSET / M_SQRT1_2, 0.0 }, + { VOFFSET / M_SQRT1_2, 1.0 - VOFFSET * M_SQRT1_2, VOFFSET }, + { 0.0, 1.0 - VOFFSET / M_SQRT1_2, VOFFSET }}; + +static const float solid_prism_n[][3] = {/* corners */ + { -VOFFSET, -VOFFSET, VOFFSET }, + { VOFFSET, -VOFFSET, VOFFSET }, + { -VOFFSET, VOFFSET, VOFFSET }, + { -VOFFSET, -VOFFSET, -VOFFSET }, + { VOFFSET, -VOFFSET, -VOFFSET }, + { -VOFFSET, VOFFSET, -VOFFSET }, + /* edges */ + { -VOFFSET, 0.0, VOFFSET }, + { 0.0, -VOFFSET, VOFFSET }, + { VOFFSET, VOFFSET, VOFFSET }, + { -VOFFSET, 0.0, -VOFFSET }, + { 0.0, -VOFFSET, -VOFFSET }, + { VOFFSET, VOFFSET, -VOFFSET }, + { -VOFFSET, -VOFFSET, 0.0 }, + { VOFFSET, -VOFFSET, 0.0 }, + { -VOFFSET, VOFFSET, 0.0 }, + /* faces */ + { 0.0, 0.0, 1.0 }, + { 0.0, -1.0, 0.0 }, + { M_SQRT1_2, M_SQRT1_2, 0.0 }, + { -1.0, 0.0, 0.0 }, + { 0.0, 0.0, -1.0 }}; + +static const float wire_prism_v[][3] = {{ 0.0, 0.0, 1.0 }, + { 1.0, 0.0, 1.0 }, + { 0.0, 1.0, 1.0 }, + { 0.0, 0.0, 0.0 }, + { 1.0, 0.0, 0.0 }, + { 0.0, 1.0, 0.0 }}; + +/* +static const float wire_prism_n[][3] = {{ 0.0, 0.0, 1.0}, + { 0.0,-1.0, 0.0}, + { M_SQRT1_2, M_SQRT1_2, 0.0}, + {-1.0, 0.0, 0.0}, + { 0.0, 0.0,-1.0}}; +*/ + +static struct glsnake_cfg * glc = NULL; +#ifdef HAVE_GLUT +# define bp glc +#endif + +typedef float (*morphFunc)(long); + +#ifdef HAVE_GLUT +/* forward definitions for GLUT functions */ +static void calc_rotation(); +static inline void ui_mousedrag(); +#endif + +static const GLfloat white_light[] = { 1.0, 1.0, 1.0, 1.0 }; +static const GLfloat lmodel_ambient[] = { 0.2, 0.2, 0.2, 1.0 }; +static const GLfloat mat_specular[] = { 0.1, 0.1, 0.1, 1.0 }; +static const GLfloat mat_shininess[] = { 20.0 }; + +static void gl_init( +#ifndef HAVE_GLUT + ModeInfo * mi +#endif + ) +{ + float light_pos[][3] = {{0.0, 10.0, 20.0}, {0.0, 20.0, -1.0}}; + float light_dir[][3] = {{0.0, -10.0,-20.0}, {0.0,-20.0, 1.0}}; + + glEnable(GL_DEPTH_TEST); + glShadeModel(GL_SMOOTH); + glCullFace(GL_BACK); + /*glEnable(GL_CULL_FACE);*/ + glEnable(GL_NORMALIZE); + if (transparent) { + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + glEnable(GL_BLEND); + } + + if (!wireframe) { + /*glColor4f(1.0, 1.0, 1.0, 1.0);*/ + glLightfv(GL_LIGHT0, GL_POSITION, light_pos[0]); + glLightfv(GL_LIGHT0, GL_SPOT_DIRECTION, light_dir[0]); + glLightfv(GL_LIGHT0, GL_DIFFUSE, white_light); + /*glLightfv(GL_LIGHT0, GL_SPECULAR, white_light);*/ +#if 1 + glLightfv(GL_LIGHT1, GL_POSITION, light_pos[1]); + glLightfv(GL_LIGHT1, GL_SPOT_DIRECTION, light_dir[1]); + glLightfv(GL_LIGHT1, GL_DIFFUSE, white_light); + glLightfv(GL_LIGHT1, GL_SPECULAR, white_light); +#endif + glLightModelfv(GL_LIGHT_MODEL_AMBIENT, lmodel_ambient); + glMaterialfv(GL_FRONT, GL_SPECULAR, mat_specular); + glMaterialfv(GL_FRONT, GL_SHININESS, mat_shininess); + glEnable(GL_LIGHTING); + glEnable(GL_LIGHT0); + glEnable(GL_LIGHT1); + /*glEnable(GL_COLOR_MATERIAL);*/ + } +} + +static void gettime(snaketime *t) +{ +#ifdef HAVE_GETTIMEOFDAY +#ifdef GETTIMEOFDAY_TWO_ARGS + struct timezone tzp; + gettimeofday(t, &tzp); +#else /* !GETTIMEOFDAY_TWO_ARGS */ + gettimeofday(t); +#endif /* !GETTIMEOFDAY_TWO_ARGS */ +#else /* !HAVE_GETTIMEOFDAY */ +#ifdef HAVE_FTIME + ftime(t); +#endif /* HAVE_FTIME */ +#endif /* !HAVE_GETTIMEOFDAY */ +} + + +ENTRYPOINT void glsnake_reshape( +#ifndef HAVE_GLUT + ModeInfo * mi, +#endif + int w, int h); + +static void start_morph(struct glsnake_cfg *, + unsigned int model_index, int immediate); + +/* wot initialises it */ +ENTRYPOINT void glsnake_init( +#ifndef HAVE_GLUT +ModeInfo * mi +#endif +) +{ +#ifndef HAVE_GLUT + struct glsnake_cfg * bp; + + /* set up the conf struct and glx contexts */ + if (!glc) { + glc = (struct glsnake_cfg *) calloc(MI_NUM_SCREENS(mi), sizeof(struct glsnake_cfg)); + if (!glc) { + fprintf(stderr, "%s: out of memory\n", progname); + exit(1); + } + } + bp = &glc[MI_SCREEN(mi)]; + + if ((bp->glx_context = init_GL(mi)) != NULL) { + gl_init(mi); + glsnake_reshape(mi, MI_WIDTH(mi), MI_HEIGHT(mi)); + } +#else + gl_init(); +#endif + + /* initialise conf struct */ + memset(&bp->node, 0, sizeof(float) * NODE_COUNT); + + bp->selected = 11; + bp->is_cyclic = 0; + bp->is_legal = 1; + bp->last_turn = -1; + bp->morphing = 0; + bp->paused = 0; + bp->new_morph = 0; + + gettime(&bp->last_iteration); + memcpy(&bp->last_morph, &bp->last_iteration, sizeof(bp->last_morph)); + + bp->prev_colour = bp->next_colour = COLOUR_ACYCLIC; + bp->next_model = RAND(models); + bp->prev_model = START_MODEL; + start_morph(bp, bp->prev_model, 1); + + /* set up a font for the labels */ +#ifndef HAVE_GLUT + if (titles) +# ifdef HAVE_GLBITMAP + load_font(mi->dpy, "labelfont", &bp->font, &bp->font_list); +# else + bp->font_data = load_texture_font (mi->dpy, "labelFont"); +# endif +#endif + + /* build a solid display list */ + bp->node_solid = glGenLists(1); + glNewList(bp->node_solid, GL_COMPILE); + /* corners */ + glBegin(GL_TRIANGLES); + glNormal3fv(solid_prism_n[0]); + glVertex3fv(solid_prism_v[0]); + glVertex3fv(solid_prism_v[2]); + glVertex3fv(solid_prism_v[1]); + bp->node_polys++; + + glNormal3fv(solid_prism_n[1]); + glVertex3fv(solid_prism_v[6]); + glVertex3fv(solid_prism_v[7]); + glVertex3fv(solid_prism_v[8]); + bp->node_polys++; + + glNormal3fv(solid_prism_n[2]); + glVertex3fv(solid_prism_v[12]); + glVertex3fv(solid_prism_v[13]); + glVertex3fv(solid_prism_v[14]); + bp->node_polys++; + + glNormal3fv(solid_prism_n[3]); + glVertex3fv(solid_prism_v[3]); + glVertex3fv(solid_prism_v[4]); + glVertex3fv(solid_prism_v[5]); + bp->node_polys++; + + glNormal3fv(solid_prism_n[4]); + glVertex3fv(solid_prism_v[9]); + glVertex3fv(solid_prism_v[11]); + glVertex3fv(solid_prism_v[10]); + bp->node_polys++; + + glNormal3fv(solid_prism_n[5]); + glVertex3fv(solid_prism_v[16]); + glVertex3fv(solid_prism_v[15]); + glVertex3fv(solid_prism_v[17]); + bp->node_polys++; + glEnd(); + + /* edges */ + glBegin(GL_QUADS); + glNormal3fv(solid_prism_n[6]); + glVertex3fv(solid_prism_v[0]); + glVertex3fv(solid_prism_v[12]); + glVertex3fv(solid_prism_v[14]); + glVertex3fv(solid_prism_v[2]); + bp->node_polys++; + + glNormal3fv(solid_prism_n[7]); + glVertex3fv(solid_prism_v[0]); + glVertex3fv(solid_prism_v[1]); + glVertex3fv(solid_prism_v[7]); + glVertex3fv(solid_prism_v[6]); + bp->node_polys++; + + glNormal3fv(solid_prism_n[8]); + glVertex3fv(solid_prism_v[6]); + glVertex3fv(solid_prism_v[8]); + glVertex3fv(solid_prism_v[13]); + glVertex3fv(solid_prism_v[12]); + bp->node_polys++; + + glNormal3fv(solid_prism_n[9]); + glVertex3fv(solid_prism_v[3]); + glVertex3fv(solid_prism_v[5]); + glVertex3fv(solid_prism_v[17]); + glVertex3fv(solid_prism_v[15]); + bp->node_polys++; + + glNormal3fv(solid_prism_n[10]); + glVertex3fv(solid_prism_v[3]); + glVertex3fv(solid_prism_v[9]); + glVertex3fv(solid_prism_v[10]); + glVertex3fv(solid_prism_v[4]); + bp->node_polys++; + + glNormal3fv(solid_prism_n[11]); + glVertex3fv(solid_prism_v[15]); + glVertex3fv(solid_prism_v[16]); + glVertex3fv(solid_prism_v[11]); + glVertex3fv(solid_prism_v[9]); + bp->node_polys++; + + glNormal3fv(solid_prism_n[12]); + glVertex3fv(solid_prism_v[1]); + glVertex3fv(solid_prism_v[2]); + glVertex3fv(solid_prism_v[5]); + glVertex3fv(solid_prism_v[4]); + bp->node_polys++; + + glNormal3fv(solid_prism_n[13]); + glVertex3fv(solid_prism_v[8]); + glVertex3fv(solid_prism_v[7]); + glVertex3fv(solid_prism_v[10]); + glVertex3fv(solid_prism_v[11]); + bp->node_polys++; + + glNormal3fv(solid_prism_n[14]); + glVertex3fv(solid_prism_v[13]); + glVertex3fv(solid_prism_v[16]); + glVertex3fv(solid_prism_v[17]); + glVertex3fv(solid_prism_v[14]); + bp->node_polys++; + glEnd(); + + /* faces */ + glBegin(GL_TRIANGLES); + glNormal3fv(solid_prism_n[15]); + glVertex3fv(solid_prism_v[0]); + glVertex3fv(solid_prism_v[6]); + glVertex3fv(solid_prism_v[12]); + bp->node_polys++; + + glNormal3fv(solid_prism_n[19]); + glVertex3fv(solid_prism_v[3]); + glVertex3fv(solid_prism_v[15]); + glVertex3fv(solid_prism_v[9]); + bp->node_polys++; + glEnd(); + + glBegin(GL_QUADS); + glNormal3fv(solid_prism_n[16]); + glVertex3fv(solid_prism_v[1]); + glVertex3fv(solid_prism_v[4]); + glVertex3fv(solid_prism_v[10]); + glVertex3fv(solid_prism_v[7]); + bp->node_polys++; + + glNormal3fv(solid_prism_n[17]); + glVertex3fv(solid_prism_v[8]); + glVertex3fv(solid_prism_v[11]); + glVertex3fv(solid_prism_v[16]); + glVertex3fv(solid_prism_v[13]); + bp->node_polys++; + + glNormal3fv(solid_prism_n[18]); + glVertex3fv(solid_prism_v[2]); + glVertex3fv(solid_prism_v[14]); + glVertex3fv(solid_prism_v[17]); + glVertex3fv(solid_prism_v[5]); + bp->node_polys++; + glEnd(); + glEndList(); + + /* build wire display list */ + bp->node_wire = glGenLists(1); + glNewList(bp->node_wire, GL_COMPILE); + glBegin(GL_LINE_STRIP); + glVertex3fv(wire_prism_v[0]); + glVertex3fv(wire_prism_v[1]); + bp->node_polys++; + glVertex3fv(wire_prism_v[2]); + glVertex3fv(wire_prism_v[0]); + bp->node_polys++; + glVertex3fv(wire_prism_v[3]); + glVertex3fv(wire_prism_v[4]); + bp->node_polys++; + glVertex3fv(wire_prism_v[5]); + glVertex3fv(wire_prism_v[3]); + bp->node_polys++; + glEnd(); + glBegin(GL_LINES); + glVertex3fv(wire_prism_v[1]); + glVertex3fv(wire_prism_v[4]); + bp->node_polys++; + glVertex3fv(wire_prism_v[2]); + glVertex3fv(wire_prism_v[5]); + bp->node_polys++; + glEnd(); + glEndList(); + +#ifdef HAVE_GLUT + /* initialise the rotation */ + calc_rotation(); +#endif +} + +static void draw_title( +#ifndef HAVE_GLUT + ModeInfo * mi +#endif + ) +{ +#ifndef HAVE_GLUT + struct glsnake_cfg * bp = &glc[MI_SCREEN(mi)]; +#endif + + /* draw some text */ + +/* glPushAttrib((GLbitfield) GL_TRANSFORM_BIT | GL_ENABLE_BIT);*/ + glDisable(GL_LIGHTING); + glDisable(GL_DEPTH_TEST); + if (transparent) { + glDisable(GL_BLEND); + } + glMatrixMode(GL_PROJECTION); + glPushMatrix(); + glLoadIdentity(); + glMatrixMode(GL_MODELVIEW); + glPushMatrix(); + glLoadIdentity(); +#ifdef HAVE_GLUT + glOrtho((GLdouble) 0., (GLdouble) bp->width, (GLdouble) 0., (GLdouble) bp->height, -1, 1); +#else + glOrtho((GLdouble) 0., (GLdouble) mi->xgwa.width, (GLdouble) 0., (GLdouble) mi->xgwa.height, -1, 1); +#endif + + glColor4f(1.0, 1.0, 1.0, 1.0); + { + char interactstr[] = "interactive"; + const char * s; +#ifdef HAVE_GLUT + int w; +#endif + + if (interactive) + s = interactstr; + else + s = model[bp->next_model].name; + +#ifdef HAVE_GLUT + { + unsigned int i = 0; + + w = glutBitmapLength(GLUT_BITMAP_HELVETICA_12, (const unsigned char *) s); + glRasterPos2f((GLfloat) (bp->width - w - 3), 4.0); + while (s[i] != '\0') + glutBitmapCharacter(GLUT_BITMAP_HELVETICA_12, s[i++]); + } +#else + print_gl_string(mi->dpy, +# ifdef HAVE_GLBITMAP + bp->font, bp->font_list, +# else + bp->font_data, +# endif + mi->xgwa.width, mi->xgwa.height, + 10.0, (float) mi->xgwa.height - 10.0, + s, False); +#endif + } + glPopMatrix(); + glMatrixMode(GL_PROJECTION); + glPopMatrix(); + + +/* glPopAttrib();*/ +} + +/* apply the matrix to the origin and stick it in vec */ +static void matmult_origin(float rotmat[16], float vec[4]) +{ +#if 1 + vec[0] = 0.5 * rotmat[0] + 0.5 * rotmat[4] + 0.5 * rotmat [8] + 1 * rotmat[12]; + vec[1] = 0.5 * rotmat[1] + 0.5 * rotmat[5] + 0.5 * rotmat [9] + 1 * rotmat[13]; + vec[2] = 0.5 * rotmat[2] + 0.5 * rotmat[6] + 0.5 * rotmat[10] + 1 * rotmat[14]; + vec[3] = 0.5 * rotmat[3] + 0.5 * rotmat[7] + 0.5 * rotmat[11] + 1 * rotmat[15]; +#else + vec[0] = 0 * rotmat [0] + 0 * rotmat [1] + 0 * rotmat [2] + 1 * rotmat [3]; + vec[1] = 0 * rotmat [4] + 0 * rotmat [5] + 0 * rotmat [6] + 1 * rotmat [7]; + vec[2] = 0 * rotmat [8] + 0 * rotmat [9] + 0 * rotmat[10] + 1 * rotmat[11]; + vec[3] = 0 * rotmat[12] + 0 * rotmat[13] + 0 * rotmat[14] + 1 * rotmat[15]; +#endif + vec[0] /= vec[3]; + vec[1] /= vec[3]; + vec[2] /= vec[3]; + vec[3] = 1.0; +} + +/* wot gets called when the winder is resized */ +ENTRYPOINT void glsnake_reshape( +#ifndef HAVE_GLUT + ModeInfo * mi, +#endif + int w, int h) +{ + glViewport(0, 0, (GLint) w, (GLint) h); + glMatrixMode(GL_PROJECTION); + glLoadIdentity(); + /* jwz: 0.05 was too close (left black rectangles) */ + gluPerspective(zoom, (GLdouble) w / (GLdouble) h, 1.0, 100.0); + gluLookAt(0.0, 0.0, 20.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0); + glMatrixMode(GL_MODELVIEW); + /*gluLookAt(0.0, 0.0, 20.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0);*/ + glLoadIdentity(); +#ifdef HAVE_GLUT + bp->width = w; + bp->height = h; +#endif +} + +/* Returns the new dst_dir for the given src_dir and dst_dir */ +static int cross_product(int src_dir, int dst_dir) +{ + return X_MASK*(GETSCALAR(src_dir,Y_MASK) * GETSCALAR(dst_dir,Z_MASK) - + GETSCALAR(src_dir,Z_MASK) * GETSCALAR(dst_dir,Y_MASK))+ + Y_MASK*(GETSCALAR(src_dir,Z_MASK) * GETSCALAR(dst_dir,X_MASK) - + GETSCALAR(src_dir,X_MASK) * GETSCALAR(dst_dir,Z_MASK))+ + Z_MASK*(GETSCALAR(src_dir,X_MASK) * GETSCALAR(dst_dir,Y_MASK) - + GETSCALAR(src_dir,Y_MASK) * GETSCALAR(dst_dir,X_MASK)); +} + +/* calculate orthogonal snake metrics + * is_legal = true if model does not pass through itself + * is_cyclic = true if last node connects back to first node + * last_turn = for cyclic snakes, specifes what the 24th turn would be + */ +static void calc_snake_metrics(struct glsnake_cfg *bp) +{ + int srcDir, dstDir; + int i, x, y, z; + int prevSrcDir = -Y_MASK; + int prevDstDir = Z_MASK; + int grid[25][25][25]; + + /* zero the grid */ + memset(&grid, 0, sizeof(int) * 25*25*25); + + bp->is_legal = 1; + x = y = z = 12; + + /* trace path of snake - and keep record for is_legal */ + for (i = 0; i < NODE_COUNT - 1; i++) { + /*int ang_card;*/ /* cardinal direction of node angle */ + /* establish new state vars */ + srcDir = -prevDstDir; + x += GETSCALAR(prevDstDir, X_MASK); + y += GETSCALAR(prevDstDir, Y_MASK); + z += GETSCALAR(prevDstDir, Z_MASK); + + switch ((int) model[bp->next_model].node[i]) { + case (int) (ZERO): + dstDir = -prevSrcDir; + break; + case (int) (PIN): + dstDir = prevSrcDir; + break; + case (int) (RIGHT): + case (int) (LEFT): + dstDir = cross_product(prevSrcDir, prevDstDir); + if (model[bp->next_model].node[i] == (int) (RIGHT)) + dstDir = -dstDir; + break; + default: + /* Prevent spurious "might be used + * uninitialised" warnings when compiling + * with -O2 */ + dstDir = 0; + break; + } + + if (grid[x][y][z] == 0) + grid[x][y][z] = srcDir + dstDir; + else if (grid[x][y][z] + srcDir + dstDir == 0) + grid[x][y][z] = 8; + else + bp->is_legal = 0; + + prevSrcDir = srcDir; + prevDstDir = dstDir; + } + + /* determine if the snake is cyclic */ + bp->is_cyclic = (dstDir == Y_MASK && x == 12 && y == 11 && z == 12); + + /* determine last_turn */ + bp->last_turn = -1; + if (bp->is_cyclic) + switch (srcDir) { + case -Z_MASK: bp->last_turn = ZERO; break; + case Z_MASK: bp->last_turn = PIN; break; + case X_MASK: bp->last_turn = LEFT; break; + case -X_MASK: bp->last_turn = RIGHT; break; + } +} + +/* work out how far through the current morph we are */ +static float morph_percent(struct glsnake_cfg *bp) +{ + float retval; + int i; + + /* extend this function later with a case statement for each of the + * morph schemes */ + + /* when morphing all nodes at once, the longest morph will be the node + * that needs to rotate 180 degrees. For each node, work out how far it + * has to go, and store the maximum rotation and current largest angular + * difference, returning the angular difference over the maximum. */ + { + float rot_max = 0.0, ang_diff_max = 0.0; + + for (i = 0; i < NODE_COUNT - 1; i++) { + float rot, ang_diff; + + /* work out the maximum rotation this node has to go through + * from the previous to the next model, taking into account that + * the snake always morphs through the smaller angle */ + rot = fabs(model[bp->prev_model].node[i] - + model[bp->next_model].node[i]); + if (rot > 180.0) rot = 180.0 - rot; + /* work out the difference between the current position and the + * target */ + ang_diff = fabs(bp->node[i] - + model[bp->next_model].node[i]); + if (ang_diff > 180.0) ang_diff = 180.0 - ang_diff; + /* if it's the biggest so far, record it */ + if (rot > rot_max) rot_max = rot; + if (ang_diff > ang_diff_max) ang_diff_max = ang_diff; + } + + /* ang_diff / rot approaches 0, we want the complement */ + retval = 1.0 - (ang_diff_max / rot_max); + /* protect against naan */ + +/* Apparently some systems (Solaris) don't have isinf() */ +#undef isinf +#define isinf(x) (((x) > 999999999999.9) || ((x) < -999999999999.9)) + + if (isnan(retval) || isinf(retval)) retval = 1.0; + } + /*printf("morph_pct = %f\n", retval);*/ + return retval; +} + +static void morph_colour(struct glsnake_cfg *bp) +{ + float percent, compct; /* complement of percentage */ + + percent = morph_percent(bp); + compct = 1.0 - percent; + + bp->colour[0][0] = colour[bp->prev_colour][0][0] * compct + colour[bp->next_colour][0][0] * percent; + bp->colour[0][1] = colour[bp->prev_colour][0][1] * compct + colour[bp->next_colour][0][1] * percent; + bp->colour[0][2] = colour[bp->prev_colour][0][2] * compct + colour[bp->next_colour][0][2] * percent; + bp->colour[0][3] = colour[bp->prev_colour][0][3] * compct + colour[bp->next_colour][0][3] * percent; + + bp->colour[1][0] = colour[bp->prev_colour][1][0] * compct + colour[bp->next_colour][1][0] * percent; + bp->colour[1][1] = colour[bp->prev_colour][1][1] * compct + colour[bp->next_colour][1][1] * percent; + bp->colour[1][2] = colour[bp->prev_colour][1][2] * compct + colour[bp->next_colour][1][2] * percent; + bp->colour[1][3] = colour[bp->prev_colour][1][3] * compct + colour[bp->next_colour][1][3] * percent; +} + +/* Start morph process to this model */ +static void start_morph(struct glsnake_cfg *bp, + unsigned int model_index, int immediate) +{ + /* if immediate, don't bother morphing, go straight to the next model */ + if (immediate) { + int i; + + for (i = 0; i < NODE_COUNT; i++) + bp->node[i] = model[model_index].node[i]; + } + + bp->prev_model = bp->next_model; + bp->next_model = model_index; + bp->prev_colour = bp->next_colour; + + calc_snake_metrics(bp); + if (!bp->is_legal) + bp->next_colour = COLOUR_INVALID; + else if (altcolour) + bp->next_colour = COLOUR_AUTHENTIC; + else if (bp->is_cyclic) + bp->next_colour = COLOUR_CYCLIC; + else + bp->next_colour = COLOUR_ACYCLIC; + + if (immediate) { + bp->colour[0][0] = colour[bp->next_colour][0][0]; + bp->colour[0][1] = colour[bp->next_colour][0][1]; + bp->colour[0][2] = colour[bp->next_colour][0][2]; + bp->colour[0][3] = colour[bp->next_colour][0][3]; + bp->colour[1][0] = colour[bp->next_colour][1][0]; + bp->colour[1][1] = colour[bp->next_colour][1][1]; + bp->colour[1][2] = colour[bp->next_colour][1][2]; + bp->colour[1][3] = colour[bp->next_colour][1][3]; + } + bp->morphing = 1; + + morph_colour(bp); +} + +#if 0 +/* Returns morph progress */ +static float morph(long iter_msec) +{ + /* work out the maximum angle for this iteration */ + int still_morphing; + float iter_angle_max, largest_diff, largest_progress; + int i; + + if (bp->new_morph) + bp->new_morph = 0; + + iter_angle_max = 90.0 * (angvel/1000.0) * iter_msec; + + still_morphing = 0; + largest_diff = largest_progress = 0.0; + for (i = 0; i < NODE_COUNT; i++) { + float curAngle = bp->node[i]; + float destAngle = model[bp->next_model].node[i]; + if (curAngle != destAngle) { + still_morphing = 1; + if (fabs(curAngle-destAngle) <= iter_angle_max) + bp->node[i] = destAngle; + else if (fmod(curAngle-destAngle+360,360) > 180) + bp->node[i] = fmod(curAngle + iter_angle_max, 360); + else + bp->node[i] = fmod(curAngle+360 - iter_angle_max, 360); + largest_diff = MAX(largest_diff, fabs(destAngle-bp->node[i])); + largest_progress = MAX(largest_diff, fabs(bp->node[i] - model[bp->prev_model].node[i])); + } + } + + return MIN(largest_diff / largest_progress, 1.0); +} +#endif + + +#ifdef HAVE_GLUT +static void glsnake_idle(); + +static restore_idle(int v __attribute__((__unused__))) +{ + glutIdleFunc(glsnake_idle); +} +#endif + +static void quick_sleep(void) +{ +#ifdef HAVE_GLUT + /* By using glutTimerFunc we can keep responding to + * mouse and keyboard events, unlike using something like + * usleep. */ + glutIdleFunc(NULL); + glutTimerFunc(1, restore_idle, 0); +#else + usleep(1); +#endif +} + +static void glsnake_idle( +#ifndef HAVE_GLUT + struct glsnake_cfg * bp +#endif + ) +{ + /* time since last iteration */ + long iter_msec; + /* time since the beginning of last morph */ + long morf_msec; + float iter_angle_max; + snaketime current_time; + /* morphFunc transition; */ + int still_morphing; + int i; + + /* Do nothing to the model if we are paused */ + if (bp->paused) { + /* Avoid busy waiting when nothing is changing */ + quick_sleep(); +#ifdef HAVE_GLUT + glutSwapBuffers(); + glutPostRedisplay(); +#endif + return; + } + + /* Well, ftime gives time with millisecond resolution. + * (or worse, perhaps... who knows what the OS will do) + * So if no discernable amount of time has passed: + * a) There's no point updating the screen, because + * it would be the same + * b) The code will divide by zero + */ + gettime(¤t_time); + + iter_msec = (long) GETMSECS(current_time) - GETMSECS(bp->last_iteration) + + ((long) GETSECS(current_time) - GETSECS(bp->last_iteration)) * 1000L; + + if (iter_msec) { + /* save the current time */ + memcpy(&bp->last_iteration, ¤t_time, sizeof(snaketime)); + + /* work out if we have to switch models */ + morf_msec = GETMSECS(bp->last_iteration) - GETMSECS(bp->last_morph) + + ((long) (GETSECS(bp->last_iteration)-GETSECS(bp->last_morph)) * 1000L); + + if ((morf_msec > statictime) && !interactive && !bp->morphing) { + /*printf("starting morph\n");*/ + memcpy(&bp->last_morph, &(bp->last_iteration), sizeof(bp->last_morph)); + start_morph(bp, RAND(models), 0); + } + + if (interactive && !bp->morphing) { + quick_sleep(); + return; + } + + /* if (!bp->dragging && !bp->interactive) { */ + if (!interactive) { + + yspin += 360/((1000/yangvel)/iter_msec); + zspin += 360/((1000/zangvel)/iter_msec); + /* + yspin += 360 * (yangvel/1000.0) * iter_msec; + zspin += 360 * (zangvel/1000.0) * iter_msec; + */ + + /*printf("yspin: %f, zspin: %f\n", yspin, zspin);*/ + + } + + /* work out the maximum angle we could turn this node in this + * timeslice, iter_msec milliseconds long */ + iter_angle_max = 90.0 * (angvel/1000.0) * iter_msec; + + still_morphing = 0; + for (i = 0; i < NODE_COUNT; i++) { + float cur_angle = bp->node[i]; + float dest_angle = model[bp->next_model].node[i]; + if (cur_angle != dest_angle) { + still_morphing = 1; + if (fabs(cur_angle - dest_angle) <= iter_angle_max) + bp->node[i] = dest_angle; + else if (fmod(cur_angle - dest_angle + 360, 360) > 180) + bp->node[i] = fmod(cur_angle + iter_angle_max, 360); + else + bp->node[i] = fmod(cur_angle + 360 - iter_angle_max, 360); + } + } + + if (!still_morphing) + bp->morphing = 0; + + /* colour cycling */ + morph_colour(bp); + +#ifdef HAVE_GLUT + glutSwapBuffers(); + glutPostRedisplay(); +#endif + } else { + /* We are going too fast, so we may as well let the + * cpu relax a little by sleeping for a millisecond. */ + quick_sleep(); + } +} + +/* wot draws it */ +ENTRYPOINT void glsnake_display( +#ifndef HAVE_GLUT + ModeInfo * mi +#endif + ) +{ +#ifndef HAVE_GLUT + struct glsnake_cfg * bp = &glc[MI_SCREEN(mi)]; + Display * dpy = MI_DISPLAY(mi); + Window window = MI_WINDOW(mi); +#endif + + int i; + float ang; + float positions[NODE_COUNT][4]; /* origin points for each node */ + float com[4]; /* it's the CENTRE of MASS */ + +#ifndef HAVE_GLUT + if (!bp->glx_context) + return; + + glXMakeCurrent(MI_DISPLAY(mi), MI_WINDOW(mi), *(bp->glx_context)); +#endif + + gl_init(mi); + + /* clear the buffer */ + glClear((GLbitfield) GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + + /* go into the modelview stack */ + glMatrixMode(GL_MODELVIEW); + glLoadIdentity(); + + /* get the centre of each node, by moving through the snake and + * performing the rotations, then grabbing the matrix at each point + * and applying it to the origin */ + glPushMatrix(); + +#ifdef HAVE_GLUT + /* apply the mouse drag rotation */ + ui_mousedrag(); +#endif + + /* apply the continuous rotation */ + glRotatef(yspin, 0.0, 1.0, 0.0); + glRotatef(zspin, 0.0, 0.0, 1.0); + + com[0] = 0.0; + com[1] = 0.0; + com[2] = 0.0; + com[3] = 0.0; + for (i = 0; i < NODE_COUNT; i++) { + float rotmat[16]; + + ang = bp->node[i]; + + /*printf("ang = %f\n", ang);*/ + + glTranslatef(0.5, 0.5, 0.5); /* move to center */ + glRotatef(90.0, 0.0, 0.0, -1.0); /* reorient */ + glTranslatef(1.0 + explode, 0.0, 0.0); /* move to new pos. */ + glRotatef(180.0 + ang, 1.0, 0.0, 0.0); /* pivot to new angle */ + glTranslatef(-0.5, -0.5, -0.5); /* return from center */ + + glGetFloatv(GL_MODELVIEW_MATRIX, rotmat); + + matmult_origin(rotmat, positions[i]); + + /*printf("positions %f %f %f %f\n", positions[i][0], positions[i][1], positions[i][2], positions[i][3]);*/ + + com[0] += positions[i][0]; + com[1] += positions[i][1]; + com[2] += positions[i][2]; + com[3] += positions[i][3]; + } + glPopMatrix(); + com[0] /= NODE_COUNT; + com[1] /= NODE_COUNT; + com[2] /= NODE_COUNT; + com[3] /= NODE_COUNT; + + com[0] /= com[3]; + com[1] /= com[3]; + com[2] /= com[3]; + + /*printf("com: %f, %f, %f, %f\n", com[0], com[1], com[2], com[3]);*/ + +#if MAGICAL_RED_STRING + glPushMatrix(); + glTranslatef(-com[0], -com[1], -com[2]); + + glDisable(GL_LIGHTING); + glColor4f(1.0, 0.0, 0.0, 1.0); + glBegin(GL_LINE_STRIP); + for (i = 0; i < NODE_COUNT - 1; i++) { + glVertex3fv(positions[i]); + } + glEnd(); + glEnable(GL_LIGHTING); + /*glTranslatef(com[0], com[1], com[2]);*/ + glPopMatrix(); +#endif + + glPushMatrix(); + glTranslatef(-com[0], -com[1], -com[2]); + +#ifdef HAVE_GLUT + /* apply the mouse drag rotation */ + ui_mousedrag(); +#endif + + /* apply the continuous rotation */ + glRotatef(yspin, 0.0, 1.0, 0.0); + glRotatef(zspin, 0.0, 0.0, 1.0); + + /* now draw each node along the snake -- this is quite ugly :p */ + mi->polygon_count = 0; + for (i = 0; i < NODE_COUNT; i++) { + /* choose a colour for this node */ + if ((i == bp->selected || i == bp->selected+1) && interactive) + /* yellow */ + glColor4f(1.0, 1.0, 0.0, 1.0); + else { + /*glColor4fv(bp->colour[(i+1)%2]);*/ + glMaterialfv(GL_FRONT, GL_AMBIENT, bp->colour[(i+1)%2]); + glMaterialfv(GL_FRONT, GL_DIFFUSE, bp->colour[(i+1)%2]); + /*glMaterialfv(GL_FRONT, GL_SPECULAR, bp->colour[(i+1)%2]);*/ + } + + /* draw the node */ + if (wireframe) + glCallList(bp->node_wire); + else + glCallList(bp->node_solid); + mi->polygon_count += bp->node_polys; + + /* now work out where to draw the next one */ + + /* Interpolate between models */ + ang = bp->node[i]; + + glTranslatef(0.5, 0.5, 0.5); /* move to center */ + glRotatef(90.0, 0.0, 0.0, -1.0); /* reorient */ + glTranslatef(1.0 + explode, 0.0, 0.0); /* move to new pos. */ + glRotatef(180.0 + ang, 1.0, 0.0, 0.0); /* pivot to new angle */ + glTranslatef(-0.5, -0.5, -0.5); /* return from center */ + } + + glPopMatrix(); + + if (titles) +#ifdef HAVE_GLUT + draw_title(); +#else + draw_title(mi); +#endif + +#ifndef HAVE_GLUT + glsnake_idle(bp); + if (mi->fps_p) do_fps(mi); +#endif + + glFlush(); +#ifdef HAVE_GLUT + glutSwapBuffers(); +#else + glXSwapBuffers(dpy, window); +#endif +} + +#ifdef HAVE_GLUT +/* anything that needs to be cleaned up goes here */ +static void unmain() +{ + glutDestroyWindow(bp->window); + free(bp); +} + +static void ui_init(int *, char **); + +int main(int argc, char ** argv) +{ + bp = malloc(sizeof(struct glsnake_cfg)); + memset(bp, 0, sizeof(struct glsnake_cfg)); + + bp->width = 640; + bp->height = 480; + + ui_init(&argc, argv); + + gettime(&bp->last_iteration); + memcpy(&bp->last_morph, &bp->last_iteration, sizeof(snaketime)); + srand((unsigned int)GETSECS(bp->last_iteration)); + + bp->prev_colour = bp->next_colour = COLOUR_ACYCLIC; + bp->next_model = RAND(models); + bp->prev_model = 0; + start_morph(bp->prev_model, 1); + + glsnake_init(); + + atexit(unmain); + glutSwapBuffers(); + glutMainLoop(); + + return 0; +} +#endif + +/* + * GLUT FUNCTIONS + */ + +#ifdef HAVE_GLUT + +/* trackball quaternions */ +static float cumquat[4] = {0.0,0.0,0.0,0.0}, oldquat[4] = {0.0,0.0,0.0,0.1}; + +/* rotation matrix */ +static float rotation[16]; + +/* mouse drag vectors: start and end */ +static float mouse_start[3], mouse_end[3]; + +/* dragging boolean */ +static int dragging = 0; + +/* this function calculates the rotation matrix based on the quaternions + * generated from the mouse drag vectors */ +static void calc_rotation() +{ + double Nq, s; + double xs, ys, zs, wx, wy, wz, xx, xy, xz, yy, yz, zz; + + /* this bit ripped from Shoemake's quaternion notes from SIGGRAPH */ + Nq = cumquat[0] * cumquat[0] + cumquat[1] * cumquat[1] + + cumquat[2] * cumquat[2] + cumquat[3] * cumquat[3]; + s = (Nq > 0.0) ? (2.0 / Nq) : 0.0; + xs = cumquat[0] * s; ys = cumquat[1] * s; zs = cumquat[2] * s; + wx = cumquat[3] * xs; wy = cumquat[3] * ys; wz = cumquat[3] * zs; + xx = cumquat[0] * xs; xy = cumquat[0] * ys; xz = cumquat[0] * zs; + yy = cumquat[1] * ys; yz = cumquat[1] * zs; zz = cumquat[2] * zs; + + rotation[0] = 1.0 - (yy + zz); + rotation[1] = xy + wz; + rotation[2] = xz - wy; + rotation[4] = xy - wz; + rotation[5] = 1.0 - (xx + zz); + rotation[6] = yz + wx; + rotation[8] = xz + wy; + rotation[9] = yz - wx; + rotation[10] = 1.0 - (xx + yy); + rotation[3] = rotation[7] = rotation[11] = 0.0; + rotation[12] = rotation[13] = rotation[14] = 0.0; + rotation[15] = 1.0; +} + +static inline void ui_mousedrag() +{ + glMultMatrixf(rotation); +} + +static void ui_keyboard(unsigned char c, int x__attribute__((__unused__)), int y __attribute__((__unused__))) +{ + int i; + + switch (c) { + case 27: /* ESC */ + case 'q': + exit(0); + break; + case 'e': + explode += DEF_EXPLODE; + glutPostRedisplay(); + break; + case 'E': + explode -= DEF_EXPLODE; + if (explode < 0.0) explode = 0.0; + glutPostRedisplay(); + break; + case '.': + /* next model */ + bp->next_model++; + bp->next_model %= models; + start_morph(bp->next_model, 0); + + /* Reset last_morph time */ + gettime(&bp->last_morph); + break; + case ',': + /* previous model */ + bp->next_model = (bp->next_model + (int)models - 1) % (int)models; + start_morph(bp->next_model, 0); + + /* Reset bp->last_morph time */ + gettime(&bp->last_morph); + break; + case '+': + angvel += DEF_ANGVEL; + break; + case '-': + if (angvel > DEF_ANGVEL) + angvel -= DEF_ANGVEL; + break; + case 'i': + if (interactive) { + /* Reset last_iteration and last_morph time */ + gettime(&bp->last_iteration); + gettime(&bp->last_morph); + } + interactive = 1 - interactive; + glutPostRedisplay(); + break; + case 'w': + wireframe = 1 - wireframe; + if (wireframe) + glDisable(GL_LIGHTING); + else + glEnable(GL_LIGHTING); + glutPostRedisplay(); + break; + case 'a': + transparent = 1 - transparent; + if (transparent) { + glEnable(GL_BLEND); + } else { + glDisable(GL_BLEND); + } + break; + case 'p': + if (bp->paused) { + /* unpausing, reset last_iteration and last_morph time */ + gettime(&bp->last_iteration); + gettime(&bp->last_morph); + } + bp->paused = 1 - bp->paused; + break; + case 'd': + /* dump the current model so we can add it! */ + printf("# %s\nnoname:\t", model[bp->next_model].name); + { + int i; + + for (i = 0; i < NODE_COUNT; i++) { + if (bp->node[i] == ZERO) + printf("Z"); + else if (bp->node[i] == LEFT) + printf("L"); + else if (bp->node[i] == PIN) + printf("P"); + else if (bp->node[i] == RIGHT) + printf("R"); + /* + else + printf("%f", node[i].curAngle); + */ + if (i < NODE_COUNT - 1) + printf(" "); + } + } + printf("\n"); + break; + case 'f': + bp->fullscreen = 1 - bp->fullscreen; + if (bp->fullscreen) { + bp->old_width = bp->width; + bp->old_height = bp->height; + glutFullScreen(); + } else { + glutReshapeWindow(bp->old_width, bp->old_height); + glutPositionWindow(50,50); + } + break; + case 't': + titles = 1 - titles; + if (interactive || bp->paused) + glutPostRedisplay(); + break; + case 'c': + altcolour = 1 - altcolour; + break; + case 'z': + zoom += 1.0; + glsnake_reshape(bp->width, bp->height); + break; + case 'Z': + zoom -= 1.0; + glsnake_reshape(bp->width, bp->height); + break; + default: + break; + } +} + +static void ui_special(int key, int x__attribute__((__unused__)), int y __attribute__((__unused__))) +{ + float *destAngle = &(model[bp->next_model].node[bp->selected]); + int unknown_key = 0; + + if (interactive) { + switch (key) { + case GLUT_KEY_UP: + bp->selected = (bp->selected + (NODE_COUNT - 2)) % (NODE_COUNT - 1); + break; + case GLUT_KEY_DOWN: + bp->selected = (bp->selected + 1) % (NODE_COUNT - 1); + break; + case GLUT_KEY_LEFT: + *destAngle = fmod(*destAngle+(LEFT), 360); + bp->morphing = bp->new_morph = 1; + break; + case GLUT_KEY_RIGHT: + *destAngle = fmod(*destAngle+(RIGHT), 360); + bp->morphing = bp->new_morph = 1; + break; + case GLUT_KEY_HOME: + start_morph(STRAIGHT_MODEL, 0); + break; + default: + unknown_key = 1; + break; + } + } + calc_snake_metrics(); + + if (!unknown_key) + glutPostRedisplay(); +} + +static void ui_mouse(int button, int state, int x, int y) +{ + if (button==0) { + switch (state) { + case GLUT_DOWN: + dragging = 1; + mouse_start[0] = M_SQRT1_2 * + (x - (bp->width / 2.0)) / (bp->width / 2.0); + mouse_start[1] = M_SQRT1_2 * + ((bp->height / 2.0) - y) / (bp->height / 2.0); + mouse_start[2] = sqrt((double)(1-(mouse_start[0]*mouse_start[0]+mouse_start[1]*mouse_start[1]))); + break; + case GLUT_UP: + dragging = 0; + oldquat[0] = cumquat[0]; + oldquat[1] = cumquat[1]; + oldquat[2] = cumquat[2]; + oldquat[3] = cumquat[3]; + break; + default: + break; + } + } + glutPostRedisplay(); +} + +static void ui_motion(int x, int y) +{ + double norm; + float q[4]; + + if (dragging) { + /* construct the motion end vector from the x,y position on the + * window */ + mouse_end[0] = M_SQRT1_2 * (x - (bp->width/ 2.0)) / (bp->width / 2.0); + mouse_end[1] = M_SQRT1_2 * ((bp->height / 2.0) - y) / (bp->height / 2.0); + /* calculate the normal of the vector... */ + norm = mouse_end[0] * mouse_end[0] + mouse_end[1] * mouse_end[1]; + /* check if norm is outside the sphere and wraparound if necessary */ + if (norm > 1.0) { + mouse_end[0] = -mouse_end[0]; + mouse_end[1] = -mouse_end[1]; + mouse_end[2] = sqrt(norm - 1); + } else { + /* the z value comes from projecting onto an elliptical spheroid */ + mouse_end[2] = sqrt(1 - norm); + } + + /* now here, build a quaternion from mouse_start and mouse_end */ + q[0] = mouse_start[1] * mouse_end[2] - mouse_start[2] * mouse_end[1]; + q[1] = mouse_start[2] * mouse_end[0] - mouse_start[0] * mouse_end[2]; + q[2] = mouse_start[0] * mouse_end[1] - mouse_start[1] * mouse_end[0]; + q[3] = mouse_start[0] * mouse_end[0] + mouse_start[1] * mouse_end[1] + mouse_start[2] * mouse_end[2]; + + /* new rotation is the product of the new one and the old one */ + cumquat[0] = q[3] * oldquat[0] + q[0] * oldquat[3] + + q[1] * oldquat[2] - q[2] * oldquat[1]; + cumquat[1] = q[3] * oldquat[1] + q[1] * oldquat[3] + + q[2] * oldquat[0] - q[0] * oldquat[2]; + cumquat[2] = q[3] * oldquat[2] + q[2] * oldquat[3] + + q[0] * oldquat[1] - q[1] * oldquat[0]; + cumquat[3] = q[3] * oldquat[3] - q[0] * oldquat[0] - + q[1] * oldquat[1] - q[2] * oldquat[2]; + + calc_rotation(); + } + glutPostRedisplay(); +} + +static void ui_init(int * argc, char ** argv) +{ + glutInit(argc, argv); + glutInitDisplayMode(GLUT_RGBA | GLUT_DOUBLE | GLUT_DEPTH); + glutInitWindowSize(bp->width, bp->height); + bp->window = glutCreateWindow("glsnake"); + + glutDisplayFunc(glsnake_display); + glutReshapeFunc(glsnake_reshape); + glutIdleFunc(glsnake_idle); + glutKeyboardFunc(ui_keyboard); + glutSpecialFunc(ui_special); + glutMouseFunc(ui_mouse); + glutMotionFunc(ui_motion); + + yangvel = DEF_YANGVEL; + zangvel = DEF_ZANGVEL; + explode = DEF_EXPLODE; + angvel = DEF_ANGVEL; + statictime = DEF_STATICTIME; + altcolour = DEF_ALTCOLOUR; + titles = DEF_TITLES; + interactive = DEF_INTERACTIVE; + zoom = DEF_ZOOM; + wireframe = DEF_WIREFRAME; + transparent = DEF_TRANSPARENT; +} +#endif /* HAVE_GLUT */ + +XSCREENSAVER_MODULE ("GLSnake", glsnake) diff --git a/hacks/glx/glsnake.man b/hacks/glx/glsnake.man new file mode 100644 index 00000000..217be2f8 --- /dev/null +++ b/hacks/glx/glsnake.man @@ -0,0 +1,98 @@ +.\" Hey, EMACS: -*- nroff -*- +.TH XScreenSaver 1 "January 15, 2001" "X Version 11" +.SH NAME +glsnake \- OpenGL enhanced Rubik's Snake cyclewaster. +.SH SYNOPSIS +.B glsnake +[\-display \fIhost:display.screen\fP] [\-window] [\-root] +[\-visual \fIvisual\fP] [\-delay \fImicroseconds\fP] [\-fps] +[\-wireframe] [\-altcolour] +[\-angvel \fIangular\fP] +[\-explode \fIdistance\fP] +[\-statictime \fImilliseconds\fP] +[\-yangvel \fIangle\fP] +[\-zangvel \fIangle\fP] +.SH DESCRIPTION +.PP +.B glsnake +is an imitation of Rubiks\' Snake, using OpenGL. +.SH OPTIONS +.I glsnake +accepts the following options: +.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 \-install +Install a private colormap for the window. +.TP 8 +.B \-visual \fIvisual\fP\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 \-fps +Display the current frame rate, CPU load, and polygon count. +.TP 8 +.B \-wireframe +Display the snake in wireframe mode, rather than the default solid mode. +.TP 8 +.B \-altcolour +Use the alternate colour scheme for the snake. Shape identification using +colour will be disabled. +.TP 8 +.B -angvel \fIangular\fP +Change the speed at which the snake morphs to a new shape. +.TP 8 +.B -explode \fIdistance\fP +Change the distance between the nodes of a snake. +.TP 8 +.B \-statictime \fImilliseconds\fP +Change the time between morphs. +.TP 8 +.B \-yangvel \fIangle\fP +Change the angle of rotation around the Y axis per frame. +.TP 8 +.B \-zangvel \fIangle\fP +Change the angle of rotation around the Z axis per frame. +.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 FILES +.TP +\fB/usr/share/glsnake/*.glsnake\fP +This XScreenSaver will attempt to read model files installed with the interactive \fBglsnake\fP. +.SH SEE ALSO +.BR X (1), +.BR xscreensaver (1), +.BR glsnake (MANSUFFIX) +.PP +.EX +http://spacepants.org/src/glsnake/ +.EE +.SH BUGS +The snake will happily intersect itself while morphing (this is not a bug). +.PP +The rotation/camera position sucks. +.SH COPYRIGHT +Copyright \(co 2001,2002 by Jamie Wilkinson, Andrew Bennetts, and Peter Aylett. +.PP +This program is free software; you can redistribute it and/or modify it under +the terms of the GNU General Public License as published by the Free Software +Foundation; either version 2 of the License, or (at your option) any later +version. +.PP +This program is distributed in the hope that it will be useful, but WITHOUT +ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. +.SH AUTHOR +Jamie Wilkinson , Andrew Bennetts , +and Peter Aylett . Ported to XScreenSaver by Jamie Wilkinson. diff --git a/hacks/glx/gltext.c b/hacks/glx/gltext.c new file mode 100644 index 00000000..43d50fb9 --- /dev/null +++ b/hacks/glx/gltext.c @@ -0,0 +1,678 @@ +/* gltext, Copyright (c) 2001-2012 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. + */ + +#define DEFAULTS "*delay: 20000 \n" \ + "*showFPS: False \n" \ + "*wireframe: False \n" \ + "*usePty: False \n" \ + +# define refresh_text 0 +#define SMOOTH_TUBE /* whether to have smooth or faceted tubes */ + +#ifdef SMOOTH_TUBE +# define TUBE_FACES 12 /* how densely to render tubes */ +#else +# define TUBE_FACES 8 +#endif + + +#undef countof +#define countof(x) (sizeof((x))/sizeof((*x))) + +#include "xlockmore.h" +#include "colors.h" +#include "tube.h" +#include "sphere.h" +#include "rotator.h" +#include "gltrackball.h" +#include "textclient.h" + +#include + +#ifdef USE_GL /* whole file */ + +#define DEF_TEXT "(default)" +#define DEF_PROGRAM "(default)" +#define DEF_SPIN "XYZ" +#define DEF_WANDER "True" +#define DEF_FACE_FRONT "True" + +#ifdef HAVE_UNAME +# include +#endif /* HAVE_UNAME */ + +#include "glutstroke.h" +#include "glut_roman.h" +#define GLUT_FONT (&glutStrokeRoman) + + +typedef struct { + GLXContext *glx_context; + rotator *rot, *rot2; + trackball_state *trackball; + Bool button_down_p; + Bool spinx, spiny, spinz; + + GLuint text_list; + + int ncolors; + XColor *colors; + int ccolor; + + char *text; + int reload; + + time_t last_update; + text_data *tc; + +} text_configuration; + +static text_configuration *tps = NULL; + +static char *text_fmt; +static char *program_str; +static char *do_spin; +static Bool do_wander; +static Bool face_front_p; + +static XrmOptionDescRec opts[] = { + { "-text", ".text", XrmoptionSepArg, 0 }, + { "-program", ".program", XrmoptionSepArg, 0 }, + { "-spin", ".spin", XrmoptionSepArg, 0 }, + { "+spin", ".spin", XrmoptionNoArg, "" }, + { "-wander", ".wander", XrmoptionNoArg, "True" }, + { "+wander", ".wander", XrmoptionNoArg, "False" }, + { "-front", ".faceFront", XrmoptionNoArg, "True" }, + { "+front", ".faceFront", XrmoptionNoArg, "False" } +}; + +static argtype vars[] = { + {&text_fmt, "text", "Text", DEF_TEXT, t_String}, + {&program_str, "program", "Program", DEF_PROGRAM, t_String}, + {&do_spin, "spin", "Spin", DEF_SPIN, t_String}, + {&do_wander, "wander", "Wander", DEF_WANDER, t_Bool}, + {&face_front_p, "faceFront", "FaceFront", DEF_FACE_FRONT, t_Bool}, +}; + +ENTRYPOINT ModeSpecOpt text_opts = {countof(opts), opts, countof(vars), vars, NULL}; + + +/* Window management, etc + */ +ENTRYPOINT void +reshape_text (ModeInfo *mi, int width, int height) +{ + GLfloat h = (GLfloat) height / (GLfloat) width; + + glViewport (0, 0, (GLint) width, (GLint) height); + + glMatrixMode(GL_PROJECTION); + glLoadIdentity(); + gluPerspective (30.0, 1/h, 1.0, 100.0); + + glMatrixMode(GL_MODELVIEW); + glLoadIdentity(); + gluLookAt( 0.0, 0.0, 30.0, + 0.0, 0.0, 0.0, + 0.0, 1.0, 0.0); + + glClear(GL_COLOR_BUFFER_BIT); +} + + +static void +gl_init (ModeInfo *mi) +{ + text_configuration *tp = &tps[MI_SCREEN(mi)]; + int wire = MI_IS_WIREFRAME(mi); + + static const GLfloat pos[4] = {5.0, 5.0, 10.0, 1.0}; + + if (!wire) + { + glLightfv(GL_LIGHT0, GL_POSITION, pos); + glEnable(GL_CULL_FACE); + glEnable(GL_LIGHTING); + glEnable(GL_LIGHT0); + glEnable(GL_DEPTH_TEST); + } + + tp->text_list = glGenLists (1); + glNewList (tp->text_list, GL_COMPILE); + glEndList (); +} + + +/* The GLUT font only has ASCII characters in them, so do what we can to + convert Latin1 characters to the nearest ASCII equivalent... + */ +static void +latin1_to_ascii (char *s) +{ + unsigned char *us = (unsigned char *) s; + const unsigned char ascii[95] = { + '!', 'C', '#', '#', 'Y', '|', 'S', '_', 'C', '?', '<', '=', '-', 'R', '_', + '?', '?', '2', '3', '\'','u', 'P', '.', ',', '1', 'o', '>', '?', '?', '?', + '?', 'A', 'A', 'A', 'A', 'A', 'A', 'E', 'C', 'E', 'E', 'E', 'E', 'I', 'I', + 'I', 'I', 'D', 'N', 'O', 'O', 'O', 'O', 'O', 'x', '0', 'U', 'U', 'U', 'U', + 'Y', 'p', 'S', 'a', 'a', 'a', 'a', 'a', 'a', 'e', 'c', 'e', 'e', 'e', 'e', + 'i', 'i', 'i', 'i', 'o', 'n', 'o', 'o', 'o', 'o', 'o', '/', 'o', 'u', 'u', + 'u', 'u', 'y', 'p', 'y' }; + while (*us) + { + if (*us >= 161) + *us = ascii[*us - 161]; + else if (*us > 127) + *us = '?'; + us++; + } +} + + +static void +parse_text (ModeInfo *mi) +{ + text_configuration *tp = &tps[MI_SCREEN(mi)]; + + if (tp->text) free (tp->text); + tp->text = 0; + + if (program_str && *program_str && !!strcmp(program_str, "(default)")) + { + int max_lines = 20; + char buf[1024]; + char *p = buf; + int lines = 0; + + if (! tp->tc) + tp->tc = textclient_open (mi->dpy); + + while (p < buf + sizeof(buf) - 1 && + lines < max_lines) + { + char c = textclient_getc (tp->tc); + if (c == '\n') + lines++; + if (c > 0) + *p++ = c; + else + break; + } + *p = 0; + if (lines == 0 && buf[0]) + lines++; + + tp->text = strdup (buf); + tp->reload = 1; + } + else if (!text_fmt || !*text_fmt || !strcmp(text_fmt, "(default)")) + { +# ifdef HAVE_UNAME + struct utsname uts; + + if (uname (&uts) < 0) + { + tp->text = strdup("uname() failed"); + } + else + { + char *s; + if ((s = strchr(uts.nodename, '.'))) + *s = 0; + tp->text = (char *) malloc(strlen(uts.nodename) + + strlen(uts.sysname) + + strlen(uts.version) + + strlen(uts.release) + 10); +# if defined(_AIX) + sprintf(tp->text, "%s\n%s %s.%s", + uts.nodename, uts.sysname, uts.version, uts.release); +# elif defined(USE_IPHONE) + /* "My iPhone\n iPhone4,1\n Darwin 11.0.0" */ + sprintf(tp->text, "%s\n%s\n%s %s", + uts.nodename, uts.machine, uts.sysname, uts.release); +# elif defined(__APPLE__) /* MacOS X + XDarwin */ + { + const char *file = + "/System/Library/CoreServices/SystemVersion.plist"; + FILE *f = fopen (file, "r"); + char *pbv = 0, *pn = 0, *puvv = 0; + if (f) { + char *s, buf[255]; + + while (fgets (buf, sizeof(buf)-1, f)) { +# define GRAB(S,V) \ + if (strstr(buf, S)) { \ + fgets (buf, sizeof(buf)-1, f); \ + if ((s = strchr (buf, '>'))) V = strdup(s+1); \ + if ((s = strchr (V, '<'))) *s = 0; \ + } + GRAB ("ProductName", pn) + GRAB ("ProductBuildVersion", pbv) + GRAB ("ProductUserVisibleVersion", puvv) +# undef GRAB + } + } + if (pbv) + sprintf (tp->text, "%s\n%s\n%s\n%s", + uts.nodename, pn, puvv, uts.machine); + else + sprintf(tp->text, "%s\n%s %s\n%s", + uts.nodename, uts.sysname, uts.release, uts.machine); + } +# else + sprintf(tp->text, "%s\n%s %s", + uts.nodename, uts.sysname, uts.release); +# endif /* special system types */ + } +# else /* !HAVE_UNAME */ +# ifdef VMS + tp->text = strdup(getenv("SYS$NODE")); +# else + tp->text = strdup("* *\n* * *\nxscreensaver\n* * *\n* *"); +# endif +# endif /* !HAVE_UNAME */ + } + else if (!strchr (text_fmt, '%')) + { + tp->text = strdup (text_fmt); + } + else + { + time_t now = time ((time_t *) 0); + struct tm *tm = localtime (&now); + int L = strlen(text_fmt) + 100; + tp->text = (char *) malloc (L); + *tp->text = 0; + strftime (tp->text, L-1, text_fmt, tm); + if (!*tp->text) + sprintf (tp->text, "strftime error:\n%s", text_fmt); + tp->reload = 1; + } + + latin1_to_ascii (tp->text); +} + + +ENTRYPOINT Bool +text_handle_event (ModeInfo *mi, XEvent *event) +{ + text_configuration *tp = &tps[MI_SCREEN(mi)]; + + if (event->xany.type == ButtonPress && + event->xbutton.button == Button1) + { + tp->button_down_p = True; + gltrackball_start (tp->trackball, + event->xbutton.x, event->xbutton.y, + MI_WIDTH (mi), MI_HEIGHT (mi)); + return True; + } + else if (event->xany.type == ButtonRelease && + event->xbutton.button == Button1) + { + tp->button_down_p = False; + return True; + } + else if (event->xany.type == ButtonPress && + (event->xbutton.button == Button4 || + event->xbutton.button == Button5 || + event->xbutton.button == Button6 || + event->xbutton.button == Button7)) + { + gltrackball_mousewheel (tp->trackball, event->xbutton.button, 10, + !!event->xbutton.state); + return True; + } + else if (event->xany.type == MotionNotify && + tp->button_down_p) + { + gltrackball_track (tp->trackball, + event->xmotion.x, event->xmotion.y, + MI_WIDTH (mi), MI_HEIGHT (mi)); + return True; + } + + return False; +} + + +ENTRYPOINT void +init_text (ModeInfo *mi) +{ + text_configuration *tp; + int i; + + if (!tps) { + tps = (text_configuration *) + calloc (MI_NUM_SCREENS(mi), sizeof (text_configuration)); + if (!tps) { + fprintf(stderr, "%s: out of memory\n", progname); + exit(1); + } + } + + tp = &tps[MI_SCREEN(mi)]; + + if ((tp->glx_context = init_GL(mi)) != NULL) { + gl_init(mi); + reshape_text (mi, MI_WIDTH(mi), MI_HEIGHT(mi)); + } + + { + double spin_speed = 0.5; + double wander_speed = 0.02; + double tilt_speed = 0.03; + double spin_accel = 0.5; + + char *s = do_spin; + while (*s) + { + if (*s == 'x' || *s == 'X') tp->spinx = True; + else if (*s == 'y' || *s == 'Y') tp->spiny = True; + else if (*s == 'z' || *s == 'Z') tp->spinz = True; + else if (*s == '0') ; + else + { + fprintf (stderr, + "%s: spin must contain only the characters X, Y, or Z (not \"%s\")\n", + progname, do_spin); + exit (1); + } + s++; + } + + tp->rot = make_rotator (tp->spinx ? spin_speed : 0, + tp->spiny ? spin_speed : 0, + tp->spinz ? spin_speed : 0, + spin_accel, + do_wander ? wander_speed : 0, + False); + tp->rot2 = (face_front_p + ? make_rotator (0, 0, 0, 0, tilt_speed, True) + : 0); + tp->trackball = gltrackball_init (); + } + + tp->ncolors = 255; + tp->colors = (XColor *) calloc(tp->ncolors, sizeof(XColor)); + make_smooth_colormap (0, 0, 0, + tp->colors, &tp->ncolors, + False, 0, False); + + /* brighter colors, please... */ + for (i = 0; i < tp->ncolors; i++) + { + tp->colors[i].red = (tp->colors[i].red / 2) + 32767; + tp->colors[i].green = (tp->colors[i].green / 2) + 32767; + tp->colors[i].blue = (tp->colors[i].blue / 2) + 32767; + } + + parse_text (mi); + +} + + +static int +fill_character (GLUTstrokeFont font, int c, Bool wire, int *polysP) +{ + GLfloat tube_width = 10; + + const StrokeCharRec *ch; + const StrokeRec *stroke; + const CoordRec *coord; + StrokeFontPtr fontinfo; + int i, j; + + fontinfo = (StrokeFontPtr) font; + + if (c < 0 || c >= fontinfo->num_chars) + return 0; + ch = &(fontinfo->ch[c]); + if (ch) + { + GLfloat lx=0, ly=0; + for (i = ch->num_strokes, stroke = ch->stroke; + i > 0; i--, stroke++) { + for (j = stroke->num_coords, coord = stroke->coord; + j > 0; j--, coord++) + { +# ifdef SMOOTH_TUBE + int smooth = True; +# else + int smooth = False; +# endif + + if (j != stroke->num_coords) + *polysP += tube (lx, ly, 0, + coord->x, coord->y, 0, + tube_width, + tube_width * 0.15, + TUBE_FACES, smooth, False, wire); + lx = coord->x; + ly = coord->y; + + /* Put a sphere at the endpoint of every line segment. Wasteful + on curves like "0" but necessary on corners like "4". */ + if (! wire) + { + glPushMatrix(); + glTranslatef (lx, ly, 0); + glScalef (tube_width, tube_width, tube_width); + *polysP += unit_sphere (TUBE_FACES, TUBE_FACES, wire); + glPopMatrix(); + } + } + } + return (int) (ch->right + tube_width); + } + return 0; +} + + +static int +text_extents (const char *string, int *wP, int *hP) +{ + const char *s, *start; + int line_height = GLUT_FONT->top - GLUT_FONT->bottom; + int lines = 0; + *wP = 0; + *hP = 0; + start = string; + s = start; + while (1) + if (*s == '\n' || *s == 0) + { + int w = 0; + while (start < s) + { + w += glutStrokeWidth(GLUT_FONT, *start); + start++; + } + start = s+1; + + if (w > *wP) *wP = w; + *hP += line_height; + lines++; + if (*s == 0) break; + s++; + } + else + s++; + + return lines; +} + + +static unsigned long +fill_string (const char *string, Bool wire) +{ + int polys = 0; + const char *s, *start; + int line_height = GLUT_FONT->top - GLUT_FONT->bottom; + int off; + GLfloat x = 0, y = 0; + + int ow, oh; + text_extents (string, &ow, &oh); + + y = oh / 2 - line_height; + + start = string; + s = start; + while (1) + if (*s == '\n' || *s == 0) + { + int line_w = 0; + const char *s2; + const char *lstart = start; + const char *lend = s; + + /* strip off whitespace at beginning and end of line + (since we're centering.) */ + while (lend > lstart && isspace(lend[-1])) + lend--; + while (lstart < lend && isspace(*lstart)) + lstart++; + + for (s2 = lstart; s2 < lend; s2++) + line_w += glutStrokeWidth (GLUT_FONT, *s2); + + x = (-ow/2) + ((ow-line_w)/2); + for (s2 = lstart; s2 < lend; s2++) + { + glPushMatrix(); + glTranslatef(x, y, 0); + off = fill_character (GLUT_FONT, *s2, wire, &polys); + x += off; + glPopMatrix(); + } + + start = s+1; + + y -= line_height; + if (*s == 0) break; + s++; + } + else + s++; + return polys; +} + + +ENTRYPOINT void +draw_text (ModeInfo *mi) +{ + text_configuration *tp = &tps[MI_SCREEN(mi)]; + Display *dpy = MI_DISPLAY(mi); + Window window = MI_WINDOW(mi); + int wire = MI_IS_WIREFRAME(mi); + + GLfloat white[4] = {1.0, 1.0, 1.0, 1.0}; + GLfloat color[4] = {0.0, 0.0, 0.0, 1.0}; + + if (!tp->glx_context) + return; + + glXMakeCurrent(MI_DISPLAY(mi), MI_WINDOW(mi), *(tp->glx_context)); + + if (tp->reload) + { + if (time ((time_t *) 0) >= tp->last_update + tp->reload) + { + parse_text (mi); + tp->last_update = time ((time_t *) 0); + } + } + + glShadeModel(GL_SMOOTH); + + glEnable(GL_DEPTH_TEST); + glEnable(GL_NORMALIZE); + glEnable(GL_CULL_FACE); + + + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + + glPushMatrix (); + glScalef(1.1, 1.1, 1.1); + glRotatef(current_device_rotation(), 0, 0, 1); + + { + double x, y, z; + get_position (tp->rot, &x, &y, &z, !tp->button_down_p); + glTranslatef((x - 0.5) * 8, + (y - 0.5) * 8, + (z - 0.5) * 8); + + gltrackball_rotate (tp->trackball); + + if (face_front_p) + { + double max = 90; + get_position (tp->rot2, &x, &y, &z, !tp->button_down_p); + if (tp->spinx) glRotatef (max/2 - x*max, 1, 0, 0); + if (tp->spiny) glRotatef (max/2 - y*max, 0, 1, 0); + if (tp->spinz) glRotatef (max/2 - z*max, 0, 0, 1); + } + else + { + get_rotation (tp->rot, &x, &y, &z, !tp->button_down_p); + glRotatef (x * 360, 1, 0, 0); + glRotatef (y * 360, 0, 1, 0); + glRotatef (z * 360, 0, 0, 1); + } + } + + + glColor4fv (white); + + color[0] = tp->colors[tp->ccolor].red / 65536.0; + color[1] = tp->colors[tp->ccolor].green / 65536.0; + color[2] = tp->colors[tp->ccolor].blue / 65536.0; + tp->ccolor++; + if (tp->ccolor >= tp->ncolors) tp->ccolor = 0; + + glMaterialfv (GL_FRONT, GL_AMBIENT_AND_DIFFUSE, color); + + glScalef(0.01, 0.01, 0.01); + + mi->polygon_count = fill_string(tp->text, wire); + + glPopMatrix (); + + if (mi->fps_p) do_fps (mi); + glFinish(); + + glXSwapBuffers(dpy, window); +} + +ENTRYPOINT void +release_text(ModeInfo * mi) +{ + if (tps) + { + int screen; + for (screen = 0; screen < MI_NUM_SCREENS(mi); screen++) + { + text_configuration *tp = &tps[MI_SCREEN(mi)]; + if (tp->tc) + textclient_close (tp->tc); + } + } + (void) free(tps); + tps = 0; + FreeAllGL(mi); +} + + +XSCREENSAVER_MODULE_2 ("GLText", gltext, text) + +#endif /* USE_GL */ diff --git a/hacks/glx/gltext.man b/hacks/glx/gltext.man new file mode 100644 index 00000000..0af1d0a3 --- /dev/null +++ b/hacks/glx/gltext.man @@ -0,0 +1,123 @@ +.de EX \"Begin example +.ne 5 +.if n .sp 1 +.if t .sp .5 +.nf +.in +.5i +.. +.de EE +.fi +.in -.5i +.if n .sp 1 +.if t .sp .5 +.. +.TH XScreenSaver 1 "25-Jul-98" "X Version 11" +.SH NAME +gltext - draws text spinning around in 3D +.SH SYNOPSIS +.B gltext +[\-display \fIhost:display.screen\fP] [\-window] [\-root] +[\-visual \fIvisual\fP] [\-delay \fImicroseconds\fP] +[\-text \fIstring\fP] +[\-program \fIcommand\fP] +[\-wander] [\-no-wander] +[\-spin \fIaxes\fP] +[\-no-spin] +[\-front] [\-no\-front] +[\-wireframe] +[\-fps] +.SH DESCRIPTION +The \fIgltext\fP program draws some text spinning around in 3D, using +a font that appears to be made of solid tubes. +.SH OPTIONS +.I gltext +accepts the following options: +.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 \-install +Install a private colormap for the window. +.TP 8 +.B \-visual \fIvisual\fP\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 \-text \fIstring\fP +The text to display. This may contain newlines, but it shouldn't be +very long. The default is to display the machine name and OS version. + +This may also be a format string acceptable to +.BR date (1) +and +.BR strftime (3) , +in which case, it will be updated once a second. So to make this +program display a spinning digital clock, you could do this: +.EX +gltext -text "%A%n%d %b %Y%n%l:%M:%S %p" +.EE +To include a literal `%', you must double it: `%%'. + +See the man page for +.BR strftime (3) +for more details. +.TP 8 +.B \-program \fIcommand\fP +The given program is run, and its output is displayed. +If specified, this overrides \fI\-text\fP. +The program will be re-run every 5 seconds to re-generate the text. +It should run quickly, and shouldn't generate too much text. +.TP 8 +.B \-wander +Move the text around the screen. This is the default. +.TP 8 +.B \-no\-wander +Keep the text centered on the screen. +.TP 8 +.B \-spin +Which axes around which the text should spin. The default is "XYZ", +meaning rotate it freely in space. "\fB\-spin Z\fP" would rotate the +text in the plane of the screen while not rotating it into or out +of the screen; etc. +.TP 8 +.B \-no\-spin +Don't spin the text at all: the same as \fB\-spin ""\fP. +.TP 8 +.B \-front +When spinning, never spin all the way around or upside down: +always face mostly forward so that the text is easily readable. +.TP 8 +.B \-no\-front +Allow spins to go all the way around or upside down. This is the default. +.TP 8 +.B \-wireframe +Render in wireframe instead of solid. +.TP 8 +.B \-fps +Display the current frame rate, CPU load, and polygon count. +.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 2001-2005 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/glx/gltrackball.c b/hacks/glx/gltrackball.c new file mode 100644 index 00000000..93d4c542 --- /dev/null +++ b/hacks/glx/gltrackball.c @@ -0,0 +1,157 @@ +/* gltrackball, Copyright (c) 2002-2012 Jamie Zawinski + * GL-flavored wrapper for trackball.c + * + * 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. + */ + +#include +#include +#include + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#ifndef HAVE_COCOA +# include +#endif + +#ifdef HAVE_JWZGLES +# include "jwzgles.h" +#endif /* HAVE_JWZGLES */ + +#include "trackball.h" +#include "gltrackball.h" + +extern double current_device_rotation (void); /* Bah, it's in fps.h */ + +struct trackball_state { + int x, y; + GLfloat q[4]; +}; + +/* Returns a trackball_state object, which encapsulates the stuff necessary + to make dragging the mouse on the window of a GL program do the right thing. + */ +trackball_state * +gltrackball_init (void) +{ + trackball_state *ts = (trackball_state *) calloc (1, sizeof (*ts)); + if (!ts) return 0; + trackball (ts->q, 0, 0, 0, 0); + return ts; +} + +/* Reset the trackball to the default unrotated state. + */ +void +gltrackball_reset (trackball_state *ts) +{ + memset (ts, 0, sizeof(*ts)); + trackball (ts->q, 0, 0, 0, 0); +} + + +/* Begin tracking the mouse: Call this when the mouse button goes down. + x and y are the mouse position relative to the window. + w and h are the size of the window. + */ +void +gltrackball_start (trackball_state *ts, int x, int y, int w, int h) +{ + ts->x = x; + ts->y = y; +} + +/* Track the mouse: Call this each time the mouse moves with the button down. + x and y are the new mouse position relative to the window. + w and h are the size of the window. + */ +void +gltrackball_track (trackball_state *ts, int x, int y, int w, int h) +{ + float q2[4]; + trackball (q2, + (2.0 * ts->x - w) / w, + (h - 2.0 * ts->y) / h, + (2.0 * x - w) / w, + (h - 2.0 * y) / h); + ts->x = x; + ts->y = y; + add_quats (q2, ts->q, ts->q); +} + +/* Execute the rotations current encapsulated in the trackball_state: + this does something analagous to glRotatef(). + */ +void +gltrackball_rotate (trackball_state *ts) +{ + GLfloat m[4][4]; + build_rotmatrix (m, ts->q); + glMultMatrixf (&m[0][0]); +} + + +# define Button4 4 /* X11/Xlib.h */ +# define Button5 5 +# define Button6 6 +# define Button7 7 + +/* Call this when a mouse-wheel click is detected. + Clicks act like horizontal or vertical drags. + Percent is the length of the drag as a percentage of the screen size. + Button is 'Button4' or 'Button5' (for the vertical wheel) + or 'Button5' or 'Button6' (for the horizontal wheel). + If `flip_p' is true, swap the horizontal and vertical axes. + */ +void +gltrackball_mousewheel (trackball_state *ts, + int button, int percent, int flip_p) +{ + int up_p; + double move; + int horizontal_p; + +#ifdef HAVE_COCOA + flip_p = 0; /* MacOS has already handled this. */ +#endif + + switch (button) { + case Button4: up_p = 1; horizontal_p = 0; break; + case Button5: up_p = 0; horizontal_p = 0; break; + case Button6: up_p = 1; horizontal_p = 1; break; + case Button7: up_p = 0; horizontal_p = 1; break; + default: abort(); break; + } + + if (flip_p) + { + horizontal_p = !horizontal_p; + up_p = !up_p; + } + + move = (up_p + ? 1.0 - (percent / 100.0) + : 1.0 + (percent / 100.0)); + + gltrackball_start (ts, 50, 50, 100, 100); + if (horizontal_p) + gltrackball_track (ts, 50*move, 50, 100, 100); + else + gltrackball_track (ts, 50, 50*move, 100, 100); +} + +void +gltrackball_get_quaternion (trackball_state *ts, float q[4]) +{ + int i; + for (i=0; i<4; i++) + q[i] = ts->q[i]; +} diff --git a/hacks/glx/gltrackball.h b/hacks/glx/gltrackball.h new file mode 100644 index 00000000..33de09d5 --- /dev/null +++ b/hacks/glx/gltrackball.h @@ -0,0 +1,59 @@ +/* gltrackball, Copyright (c) 2002-2008 Jamie Zawinski + * GL-flavored wrapper for trackball.c + * + * 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. + */ + +#ifndef __GLTRACKBALL_H__ +#define __GLTRACKBALL_H__ + +typedef struct trackball_state trackball_state; + +/* Returns a trackball_state object, which encapsulates the stuff necessary + to make dragging the mouse on the window of a GL program do the right thing. + */ +extern trackball_state *gltrackball_init (void); + +/* Begin tracking the mouse: Call this when the mouse button goes down. + x and y are the mouse position relative to the window. + w and h are the size of the window. + */ +extern void gltrackball_start (trackball_state *, int x, int y, int w, int h); + +/* Track the mouse: Call this each time the mouse moves with the button down. + x and y are the new mouse position relative to the window. + w and h are the size of the window. + */ +extern void gltrackball_track (trackball_state *, int x, int y, int w, int h); + +/* Execute the rotations current encapsulated in the trackball_state: + this does something analagous to glRotatef(). + */ +extern void gltrackball_rotate (trackball_state *); + +/* Call this when a mouse-wheel click is detected. + Clicks act like horizontal or vertical drags. + Percent is the length of the drag as a percentage of the screen size. + Button is 'Button4' or 'Button5' (for the vertical wheel) + or 'Button5' or 'Button6' (for the horizontal wheel). + If `flip_p' is true, swap the horizontal and vertical axes. + */ +void gltrackball_mousewheel (trackball_state *ts, + int button, int percent, int flip_p); + +/* Return the quaternion encapsulated by the trackball state. + */ +extern void gltrackball_get_quaternion (trackball_state *ts, float q[4]); + +/* Reset the trackball to the default unrotated state. + */ +extern void gltrackball_reset (trackball_state *ts); + +#endif /* __GLTRACKBALL_H__ */ + diff --git a/hacks/glx/glut_roman.h b/hacks/glx/glut_roman.h new file mode 100644 index 00000000..93f95328 --- /dev/null +++ b/hacks/glx/glut_roman.h @@ -0,0 +1,2455 @@ +/* Roman simplex stroke font copyright (c) 1989, 1990, 1991 + * by Sun Microsystems, Inc. and the X Consortium. + * Originally part of the GLUT library by Mark J. Kilgard. + */ + +#include "glutstroke.h" + +/* char: 33 '!' */ + +static const CoordRec char33_stroke0[] = { + { 13.3819, 100 }, + { 13.3819, 33.3333 }, +}; + +static const CoordRec char33_stroke1[] = { + { 13.3819, 9.5238 }, + { 8.62, 4.7619 }, + { 13.3819, 0 }, + { 18.1438, 4.7619 }, + { 13.3819, 9.5238 }, +}; + +static const StrokeRec char33[] = { + { 2, char33_stroke0 }, + { 5, char33_stroke1 }, +}; + +/* char: 34 '"' */ + +static const CoordRec char34_stroke0[] = { + { 4.02, 100 }, + { 4.02, 66.6667 }, +}; + +static const CoordRec char34_stroke1[] = { + { 42.1152, 100 }, + { 42.1152, 66.6667 }, +}; + +static const StrokeRec char34[] = { + { 2, char34_stroke0 }, + { 2, char34_stroke1 }, +}; + +/* char: 35 '#' */ + +static const CoordRec char35_stroke0[] = { + { 41.2952, 119.048 }, + { 7.9619, -33.3333 }, +}; + +static const CoordRec char35_stroke1[] = { + { 69.8667, 119.048 }, + { 36.5333, -33.3333 }, +}; + +static const CoordRec char35_stroke2[] = { + { 7.9619, 57.1429 }, + { 74.6286, 57.1429 }, +}; + +static const CoordRec char35_stroke3[] = { + { 3.2, 28.5714 }, + { 69.8667, 28.5714 }, +}; + +static const StrokeRec char35[] = { + { 2, char35_stroke0 }, + { 2, char35_stroke1 }, + { 2, char35_stroke2 }, + { 2, char35_stroke3 }, +}; + +/* char: 36 '$' */ + +static const CoordRec char36_stroke0[] = { + { 28.6295, 119.048 }, + { 28.6295, -19.0476 }, +}; + +static const CoordRec char36_stroke1[] = { + { 47.6771, 119.048 }, + { 47.6771, -19.0476 }, +}; + +static const CoordRec char36_stroke2[] = { + { 71.4867, 85.7143 }, + { 61.9629, 95.2381 }, + { 47.6771, 100 }, + { 28.6295, 100 }, + { 14.3438, 95.2381 }, + { 4.82, 85.7143 }, + { 4.82, 76.1905 }, + { 9.5819, 66.6667 }, + { 14.3438, 61.9048 }, + { 23.8676, 57.1429 }, + { 52.439, 47.619 }, + { 61.9629, 42.8571 }, + { 66.7248, 38.0952 }, + { 71.4867, 28.5714 }, + { 71.4867, 14.2857 }, + { 61.9629, 4.7619 }, + { 47.6771, 0 }, + { 28.6295, 0 }, + { 14.3438, 4.7619 }, + { 4.82, 14.2857 }, +}; + +static const StrokeRec char36[] = { + { 2, char36_stroke0 }, + { 2, char36_stroke1 }, + { 20, char36_stroke2 }, +}; + +/* char: 37 '%' */ + +static const CoordRec char37_stroke0[] = { + { 92.0743, 100 }, + { 6.36, 0 }, +}; + +static const CoordRec char37_stroke1[] = { + { 30.1695, 100 }, + { 39.6933, 90.4762 }, + { 39.6933, 80.9524 }, + { 34.9314, 71.4286 }, + { 25.4076, 66.6667 }, + { 15.8838, 66.6667 }, + { 6.36, 76.1905 }, + { 6.36, 85.7143 }, + { 11.1219, 95.2381 }, + { 20.6457, 100 }, + { 30.1695, 100 }, + { 39.6933, 95.2381 }, + { 53.979, 90.4762 }, + { 68.2648, 90.4762 }, + { 82.5505, 95.2381 }, + { 92.0743, 100 }, +}; + +static const CoordRec char37_stroke2[] = { + { 73.0267, 33.3333 }, + { 63.5029, 28.5714 }, + { 58.741, 19.0476 }, + { 58.741, 9.5238 }, + { 68.2648, 0 }, + { 77.7886, 0 }, + { 87.3124, 4.7619 }, + { 92.0743, 14.2857 }, + { 92.0743, 23.8095 }, + { 82.5505, 33.3333 }, + { 73.0267, 33.3333 }, +}; + +static const StrokeRec char37[] = { + { 2, char37_stroke0 }, + { 16, char37_stroke1 }, + { 11, char37_stroke2 }, +}; + +/* char: 38 '&' */ + +static const CoordRec char38_stroke0[] = { + { 101.218, 57.1429 }, + { 101.218, 61.9048 }, + { 96.4562, 66.6667 }, + { 91.6943, 66.6667 }, + { 86.9324, 61.9048 }, + { 82.1705, 52.381 }, + { 72.6467, 28.5714 }, + { 63.1229, 14.2857 }, + { 53.599, 4.7619 }, + { 44.0752, 0 }, + { 25.0276, 0 }, + { 15.5038, 4.7619 }, + { 10.7419, 9.5238 }, + { 5.98, 19.0476 }, + { 5.98, 28.5714 }, + { 10.7419, 38.0952 }, + { 15.5038, 42.8571 }, + { 48.8371, 61.9048 }, + { 53.599, 66.6667 }, + { 58.361, 76.1905 }, + { 58.361, 85.7143 }, + { 53.599, 95.2381 }, + { 44.0752, 100 }, + { 34.5514, 95.2381 }, + { 29.7895, 85.7143 }, + { 29.7895, 76.1905 }, + { 34.5514, 61.9048 }, + { 44.0752, 47.619 }, + { 67.8848, 14.2857 }, + { 77.4086, 4.7619 }, + { 86.9324, 0 }, + { 96.4562, 0 }, + { 101.218, 4.7619 }, + { 101.218, 9.5238 }, +}; + +static const StrokeRec char38[] = { + { 34, char38_stroke0 }, +}; + +/* char: 39 ''' */ + +static const CoordRec char39_stroke0[] = { + { 4.44, 100 }, + { 4.44, 66.6667 }, +}; + +static const StrokeRec char39[] = { + { 2, char39_stroke0 }, +}; + +/* char: 40 '(' */ + +static const CoordRec char40_stroke0[] = { + { 40.9133, 119.048 }, + { 31.3895, 109.524 }, + { 21.8657, 95.2381 }, + { 12.3419, 76.1905 }, + { 7.58, 52.381 }, + { 7.58, 33.3333 }, + { 12.3419, 9.5238 }, + { 21.8657, -9.5238 }, + { 31.3895, -23.8095 }, + { 40.9133, -33.3333 }, +}; + +static const StrokeRec char40[] = { + { 10, char40_stroke0 }, +}; + +/* char: 41 ')' */ + +static const CoordRec char41_stroke0[] = { + { 5.28, 119.048 }, + { 14.8038, 109.524 }, + { 24.3276, 95.2381 }, + { 33.8514, 76.1905 }, + { 38.6133, 52.381 }, + { 38.6133, 33.3333 }, + { 33.8514, 9.5238 }, + { 24.3276, -9.5238 }, + { 14.8038, -23.8095 }, + { 5.28, -33.3333 }, +}; + +static const StrokeRec char41[] = { + { 10, char41_stroke0 }, +}; + +/* char: 42 '*' */ + +static const CoordRec char42_stroke0[] = { + { 30.7695, 71.4286 }, + { 30.7695, 14.2857 }, +}; + +static const CoordRec char42_stroke1[] = { + { 6.96, 57.1429 }, + { 54.579, 28.5714 }, +}; + +static const CoordRec char42_stroke2[] = { + { 54.579, 57.1429 }, + { 6.96, 28.5714 }, +}; + +static const StrokeRec char42[] = { + { 2, char42_stroke0 }, + { 2, char42_stroke1 }, + { 2, char42_stroke2 }, +}; + +/* char: 43 '+' */ + +static const CoordRec char43_stroke0[] = { + { 48.8371, 85.7143 }, + { 48.8371, 0 }, +}; + +static const CoordRec char43_stroke1[] = { + { 5.98, 42.8571 }, + { 91.6943, 42.8571 }, +}; + +static const StrokeRec char43[] = { + { 2, char43_stroke0 }, + { 2, char43_stroke1 }, +}; + +/* char: 44 ',' */ + +static const CoordRec char44_stroke0[] = { + { 18.2838, 4.7619 }, + { 13.5219, 0 }, + { 8.76, 4.7619 }, + { 13.5219, 9.5238 }, + { 18.2838, 4.7619 }, + { 18.2838, -4.7619 }, + { 13.5219, -14.2857 }, + { 8.76, -19.0476 }, +}; + +static const StrokeRec char44[] = { + { 8, char44_stroke0 }, +}; + +/* char: 45 '-' */ + +static const CoordRec char45_stroke0[] = { + { 7.38, 42.8571 }, + { 93.0943, 42.8571 }, +}; + +static const StrokeRec char45[] = { + { 2, char45_stroke0 }, +}; + +/* char: 46 '.' */ + +static const CoordRec char46_stroke0[] = { + { 13.1019, 9.5238 }, + { 8.34, 4.7619 }, + { 13.1019, 0 }, + { 17.8638, 4.7619 }, + { 13.1019, 9.5238 }, +}; + +static const StrokeRec char46[] = { + { 5, char46_stroke0 }, +}; + +/* char: 47 '/' */ + +static const CoordRec char47_stroke0[] = { + { 7.24, -14.2857 }, + { 73.9067, 100 }, +}; + +static const StrokeRec char47[] = { + { 2, char47_stroke0 }, +}; + +/* char: 48 '0' */ + +static const CoordRec char48_stroke0[] = { + { 33.5514, 100 }, + { 19.2657, 95.2381 }, + { 9.7419, 80.9524 }, + { 4.98, 57.1429 }, + { 4.98, 42.8571 }, + { 9.7419, 19.0476 }, + { 19.2657, 4.7619 }, + { 33.5514, 0 }, + { 43.0752, 0 }, + { 57.361, 4.7619 }, + { 66.8848, 19.0476 }, + { 71.6467, 42.8571 }, + { 71.6467, 57.1429 }, + { 66.8848, 80.9524 }, + { 57.361, 95.2381 }, + { 43.0752, 100 }, + { 33.5514, 100 }, +}; + +static const StrokeRec char48[] = { + { 17, char48_stroke0 }, +}; + +/* char: 49 '1' */ + +static const CoordRec char49_stroke0[] = { + { 11.82, 80.9524 }, + { 21.3438, 85.7143 }, + { 35.6295, 100 }, + { 35.6295, 0 }, +}; + +static const StrokeRec char49[] = { + { 4, char49_stroke0 }, +}; + +/* char: 50 '2' */ + +static const CoordRec char50_stroke0[] = { + { 10.1819, 76.1905 }, + { 10.1819, 80.9524 }, + { 14.9438, 90.4762 }, + { 19.7057, 95.2381 }, + { 29.2295, 100 }, + { 48.2771, 100 }, + { 57.801, 95.2381 }, + { 62.5629, 90.4762 }, + { 67.3248, 80.9524 }, + { 67.3248, 71.4286 }, + { 62.5629, 61.9048 }, + { 53.039, 47.619 }, + { 5.42, 0 }, + { 72.0867, 0 }, +}; + +static const StrokeRec char50[] = { + { 14, char50_stroke0 }, +}; + +/* char: 51 '3' */ + +static const CoordRec char51_stroke0[] = { + { 14.5238, 100 }, + { 66.9048, 100 }, + { 38.3333, 61.9048 }, + { 52.619, 61.9048 }, + { 62.1429, 57.1429 }, + { 66.9048, 52.381 }, + { 71.6667, 38.0952 }, + { 71.6667, 28.5714 }, + { 66.9048, 14.2857 }, + { 57.381, 4.7619 }, + { 43.0952, 0 }, + { 28.8095, 0 }, + { 14.5238, 4.7619 }, + { 9.7619, 9.5238 }, + { 5, 19.0476 }, +}; + +static const StrokeRec char51[] = { + { 15, char51_stroke0 }, +}; + +/* char: 52 '4' */ + +static const CoordRec char52_stroke0[] = { + { 51.499, 100 }, + { 3.88, 33.3333 }, + { 75.3086, 33.3333 }, +}; + +static const CoordRec char52_stroke1[] = { + { 51.499, 100 }, + { 51.499, 0 }, +}; + +static const StrokeRec char52[] = { + { 3, char52_stroke0 }, + { 2, char52_stroke1 }, +}; + +/* char: 53 '5' */ + +static const CoordRec char53_stroke0[] = { + { 62.0029, 100 }, + { 14.3838, 100 }, + { 9.6219, 57.1429 }, + { 14.3838, 61.9048 }, + { 28.6695, 66.6667 }, + { 42.9552, 66.6667 }, + { 57.241, 61.9048 }, + { 66.7648, 52.381 }, + { 71.5267, 38.0952 }, + { 71.5267, 28.5714 }, + { 66.7648, 14.2857 }, + { 57.241, 4.7619 }, + { 42.9552, 0 }, + { 28.6695, 0 }, + { 14.3838, 4.7619 }, + { 9.6219, 9.5238 }, + { 4.86, 19.0476 }, +}; + +static const StrokeRec char53[] = { + { 17, char53_stroke0 }, +}; + +/* char: 54 '6' */ + +static const CoordRec char54_stroke0[] = { + { 62.7229, 85.7143 }, + { 57.961, 95.2381 }, + { 43.6752, 100 }, + { 34.1514, 100 }, + { 19.8657, 95.2381 }, + { 10.3419, 80.9524 }, + { 5.58, 57.1429 }, + { 5.58, 33.3333 }, + { 10.3419, 14.2857 }, + { 19.8657, 4.7619 }, + { 34.1514, 0 }, + { 38.9133, 0 }, + { 53.199, 4.7619 }, + { 62.7229, 14.2857 }, + { 67.4848, 28.5714 }, + { 67.4848, 33.3333 }, + { 62.7229, 47.619 }, + { 53.199, 57.1429 }, + { 38.9133, 61.9048 }, + { 34.1514, 61.9048 }, + { 19.8657, 57.1429 }, + { 10.3419, 47.619 }, + { 5.58, 33.3333 }, +}; + +static const StrokeRec char54[] = { + { 23, char54_stroke0 }, +}; + +/* char: 55 '7' */ + +static const CoordRec char55_stroke0[] = { + { 72.2267, 100 }, + { 24.6076, 0 }, +}; + +static const CoordRec char55_stroke1[] = { + { 5.56, 100 }, + { 72.2267, 100 }, +}; + +static const StrokeRec char55[] = { + { 2, char55_stroke0 }, + { 2, char55_stroke1 }, +}; + +/* char: 56 '8' */ + +static const CoordRec char56_stroke0[] = { + { 29.4095, 100 }, + { 15.1238, 95.2381 }, + { 10.3619, 85.7143 }, + { 10.3619, 76.1905 }, + { 15.1238, 66.6667 }, + { 24.6476, 61.9048 }, + { 43.6952, 57.1429 }, + { 57.981, 52.381 }, + { 67.5048, 42.8571 }, + { 72.2667, 33.3333 }, + { 72.2667, 19.0476 }, + { 67.5048, 9.5238 }, + { 62.7429, 4.7619 }, + { 48.4571, 0 }, + { 29.4095, 0 }, + { 15.1238, 4.7619 }, + { 10.3619, 9.5238 }, + { 5.6, 19.0476 }, + { 5.6, 33.3333 }, + { 10.3619, 42.8571 }, + { 19.8857, 52.381 }, + { 34.1714, 57.1429 }, + { 53.219, 61.9048 }, + { 62.7429, 66.6667 }, + { 67.5048, 76.1905 }, + { 67.5048, 85.7143 }, + { 62.7429, 95.2381 }, + { 48.4571, 100 }, + { 29.4095, 100 }, +}; + +static const StrokeRec char56[] = { + { 29, char56_stroke0 }, +}; + +/* char: 57 '9' */ + +static const CoordRec char57_stroke0[] = { + { 68.5048, 66.6667 }, + { 63.7429, 52.381 }, + { 54.219, 42.8571 }, + { 39.9333, 38.0952 }, + { 35.1714, 38.0952 }, + { 20.8857, 42.8571 }, + { 11.3619, 52.381 }, + { 6.6, 66.6667 }, + { 6.6, 71.4286 }, + { 11.3619, 85.7143 }, + { 20.8857, 95.2381 }, + { 35.1714, 100 }, + { 39.9333, 100 }, + { 54.219, 95.2381 }, + { 63.7429, 85.7143 }, + { 68.5048, 66.6667 }, + { 68.5048, 42.8571 }, + { 63.7429, 19.0476 }, + { 54.219, 4.7619 }, + { 39.9333, 0 }, + { 30.4095, 0 }, + { 16.1238, 4.7619 }, + { 11.3619, 14.2857 }, +}; + +static const StrokeRec char57[] = { + { 23, char57_stroke0 }, +}; + +/* char: 58 ':' */ + +static const CoordRec char58_stroke0[] = { + { 14.0819, 66.6667 }, + { 9.32, 61.9048 }, + { 14.0819, 57.1429 }, + { 18.8438, 61.9048 }, + { 14.0819, 66.6667 }, +}; + +static const CoordRec char58_stroke1[] = { + { 14.0819, 9.5238 }, + { 9.32, 4.7619 }, + { 14.0819, 0 }, + { 18.8438, 4.7619 }, + { 14.0819, 9.5238 }, +}; + +static const StrokeRec char58[] = { + { 5, char58_stroke0 }, + { 5, char58_stroke1 }, +}; + +/* char: 59 ';' */ + +static const CoordRec char59_stroke0[] = { + { 12.9619, 66.6667 }, + { 8.2, 61.9048 }, + { 12.9619, 57.1429 }, + { 17.7238, 61.9048 }, + { 12.9619, 66.6667 }, +}; + +static const CoordRec char59_stroke1[] = { + { 17.7238, 4.7619 }, + { 12.9619, 0 }, + { 8.2, 4.7619 }, + { 12.9619, 9.5238 }, + { 17.7238, 4.7619 }, + { 17.7238, -4.7619 }, + { 12.9619, -14.2857 }, + { 8.2, -19.0476 }, +}; + +static const StrokeRec char59[] = { + { 5, char59_stroke0 }, + { 8, char59_stroke1 }, +}; + +/* char: 60 '<' */ + +static const CoordRec char60_stroke0[] = { + { 79.2505, 85.7143 }, + { 3.06, 42.8571 }, + { 79.2505, 0 }, +}; + +static const StrokeRec char60[] = { + { 3, char60_stroke0 }, +}; + +/* char: 61 '=' */ + +static const CoordRec char61_stroke0[] = { + { 5.7, 57.1429 }, + { 91.4143, 57.1429 }, +}; + +static const CoordRec char61_stroke1[] = { + { 5.7, 28.5714 }, + { 91.4143, 28.5714 }, +}; + +static const StrokeRec char61[] = { + { 2, char61_stroke0 }, + { 2, char61_stroke1 }, +}; + +/* char: 62 '>' */ + +static const CoordRec char62_stroke0[] = { + { 2.78, 85.7143 }, + { 78.9705, 42.8571 }, + { 2.78, 0 }, +}; + +static const StrokeRec char62[] = { + { 3, char62_stroke0 }, +}; + +/* char: 63 '?' */ + +static const CoordRec char63_stroke0[] = { + { 8.42, 76.1905 }, + { 8.42, 80.9524 }, + { 13.1819, 90.4762 }, + { 17.9438, 95.2381 }, + { 27.4676, 100 }, + { 46.5152, 100 }, + { 56.039, 95.2381 }, + { 60.801, 90.4762 }, + { 65.5629, 80.9524 }, + { 65.5629, 71.4286 }, + { 60.801, 61.9048 }, + { 56.039, 57.1429 }, + { 36.9914, 47.619 }, + { 36.9914, 33.3333 }, +}; + +static const CoordRec char63_stroke1[] = { + { 36.9914, 9.5238 }, + { 32.2295, 4.7619 }, + { 36.9914, 0 }, + { 41.7533, 4.7619 }, + { 36.9914, 9.5238 }, +}; + +static const StrokeRec char63[] = { + { 14, char63_stroke0 }, + { 5, char63_stroke1 }, +}; + +/* char: 64 '@' */ + +static const CoordRec char64_stroke0[] = { + { 49.2171, 52.381 }, + { 39.6933, 57.1429 }, + { 30.1695, 57.1429 }, + { 25.4076, 47.619 }, + { 25.4076, 42.8571 }, + { 30.1695, 33.3333 }, + { 39.6933, 33.3333 }, + { 49.2171, 38.0952 }, +}; + +static const CoordRec char64_stroke1[] = { + { 49.2171, 57.1429 }, + { 49.2171, 38.0952 }, + { 53.979, 33.3333 }, + { 63.5029, 33.3333 }, + { 68.2648, 42.8571 }, + { 68.2648, 47.619 }, + { 63.5029, 61.9048 }, + { 53.979, 71.4286 }, + { 39.6933, 76.1905 }, + { 34.9314, 76.1905 }, + { 20.6457, 71.4286 }, + { 11.1219, 61.9048 }, + { 6.36, 47.619 }, + { 6.36, 42.8571 }, + { 11.1219, 28.5714 }, + { 20.6457, 19.0476 }, + { 34.9314, 14.2857 }, + { 39.6933, 14.2857 }, + { 53.979, 19.0476 }, +}; + +static const StrokeRec char64[] = { + { 8, char64_stroke0 }, + { 19, char64_stroke1 }, +}; + +/* char: 65 'A' */ + +static const CoordRec char65_stroke0[] = { + { 40.5952, 100 }, + { 2.5, 0 }, +}; + +static const CoordRec char65_stroke1[] = { + { 40.5952, 100 }, + { 78.6905, 0 }, +}; + +static const CoordRec char65_stroke2[] = { + { 16.7857, 33.3333 }, + { 64.4048, 33.3333 }, +}; + +static const StrokeRec char65[] = { + { 2, char65_stroke0 }, + { 2, char65_stroke1 }, + { 2, char65_stroke2 }, +}; + +/* char: 66 'B' */ + +static const CoordRec char66_stroke0[] = { + { 11.42, 100 }, + { 11.42, 0 }, +}; + +static const CoordRec char66_stroke1[] = { + { 11.42, 100 }, + { 54.2771, 100 }, + { 68.5629, 95.2381 }, + { 73.3248, 90.4762 }, + { 78.0867, 80.9524 }, + { 78.0867, 71.4286 }, + { 73.3248, 61.9048 }, + { 68.5629, 57.1429 }, + { 54.2771, 52.381 }, +}; + +static const CoordRec char66_stroke2[] = { + { 11.42, 52.381 }, + { 54.2771, 52.381 }, + { 68.5629, 47.619 }, + { 73.3248, 42.8571 }, + { 78.0867, 33.3333 }, + { 78.0867, 19.0476 }, + { 73.3248, 9.5238 }, + { 68.5629, 4.7619 }, + { 54.2771, 0 }, + { 11.42, 0 }, +}; + +static const StrokeRec char66[] = { + { 2, char66_stroke0 }, + { 9, char66_stroke1 }, + { 10, char66_stroke2 }, +}; + +/* char: 67 'C' */ + +static const CoordRec char67_stroke0[] = { + { 78.0886, 76.1905 }, + { 73.3267, 85.7143 }, + { 63.8029, 95.2381 }, + { 54.279, 100 }, + { 35.2314, 100 }, + { 25.7076, 95.2381 }, + { 16.1838, 85.7143 }, + { 11.4219, 76.1905 }, + { 6.66, 61.9048 }, + { 6.66, 38.0952 }, + { 11.4219, 23.8095 }, + { 16.1838, 14.2857 }, + { 25.7076, 4.7619 }, + { 35.2314, 0 }, + { 54.279, 0 }, + { 63.8029, 4.7619 }, + { 73.3267, 14.2857 }, + { 78.0886, 23.8095 }, +}; + +static const StrokeRec char67[] = { + { 18, char67_stroke0 }, +}; + +/* char: 68 'D' */ + +static const CoordRec char68_stroke0[] = { + { 11.96, 100 }, + { 11.96, 0 }, +}; + +static const CoordRec char68_stroke1[] = { + { 11.96, 100 }, + { 45.2933, 100 }, + { 59.579, 95.2381 }, + { 69.1029, 85.7143 }, + { 73.8648, 76.1905 }, + { 78.6267, 61.9048 }, + { 78.6267, 38.0952 }, + { 73.8648, 23.8095 }, + { 69.1029, 14.2857 }, + { 59.579, 4.7619 }, + { 45.2933, 0 }, + { 11.96, 0 }, +}; + +static const StrokeRec char68[] = { + { 2, char68_stroke0 }, + { 12, char68_stroke1 }, +}; + +/* char: 69 'E' */ + +static const CoordRec char69_stroke0[] = { + { 11.42, 100 }, + { 11.42, 0 }, +}; + +static const CoordRec char69_stroke1[] = { + { 11.42, 100 }, + { 73.3248, 100 }, +}; + +static const CoordRec char69_stroke2[] = { + { 11.42, 52.381 }, + { 49.5152, 52.381 }, +}; + +static const CoordRec char69_stroke3[] = { + { 11.42, 0 }, + { 73.3248, 0 }, +}; + +static const StrokeRec char69[] = { + { 2, char69_stroke0 }, + { 2, char69_stroke1 }, + { 2, char69_stroke2 }, + { 2, char69_stroke3 }, +}; + +/* char: 70 'F' */ + +static const CoordRec char70_stroke0[] = { + { 11.42, 100 }, + { 11.42, 0 }, +}; + +static const CoordRec char70_stroke1[] = { + { 11.42, 100 }, + { 73.3248, 100 }, +}; + +static const CoordRec char70_stroke2[] = { + { 11.42, 52.381 }, + { 49.5152, 52.381 }, +}; + +static const StrokeRec char70[] = { + { 2, char70_stroke0 }, + { 2, char70_stroke1 }, + { 2, char70_stroke2 }, +}; + +/* char: 71 'G' */ + +static const CoordRec char71_stroke0[] = { + { 78.4886, 76.1905 }, + { 73.7267, 85.7143 }, + { 64.2029, 95.2381 }, + { 54.679, 100 }, + { 35.6314, 100 }, + { 26.1076, 95.2381 }, + { 16.5838, 85.7143 }, + { 11.8219, 76.1905 }, + { 7.06, 61.9048 }, + { 7.06, 38.0952 }, + { 11.8219, 23.8095 }, + { 16.5838, 14.2857 }, + { 26.1076, 4.7619 }, + { 35.6314, 0 }, + { 54.679, 0 }, + { 64.2029, 4.7619 }, + { 73.7267, 14.2857 }, + { 78.4886, 23.8095 }, + { 78.4886, 38.0952 }, +}; + +static const CoordRec char71_stroke1[] = { + { 54.679, 38.0952 }, + { 78.4886, 38.0952 }, +}; + +static const StrokeRec char71[] = { + { 19, char71_stroke0 }, + { 2, char71_stroke1 }, +}; + +/* char: 72 'H' */ + +static const CoordRec char72_stroke0[] = { + { 11.42, 100 }, + { 11.42, 0 }, +}; + +static const CoordRec char72_stroke1[] = { + { 78.0867, 100 }, + { 78.0867, 0 }, +}; + +static const CoordRec char72_stroke2[] = { + { 11.42, 52.381 }, + { 78.0867, 52.381 }, +}; + +static const StrokeRec char72[] = { + { 2, char72_stroke0 }, + { 2, char72_stroke1 }, + { 2, char72_stroke2 }, +}; + +/* char: 73 'I' */ + +static const CoordRec char73_stroke0[] = { + { 10.86, 100 }, + { 10.86, 0 }, +}; + +static const StrokeRec char73[] = { + { 2, char73_stroke0 }, +}; + +/* char: 74 'J' */ + +static const CoordRec char74_stroke0[] = { + { 50.119, 100 }, + { 50.119, 23.8095 }, + { 45.3571, 9.5238 }, + { 40.5952, 4.7619 }, + { 31.0714, 0 }, + { 21.5476, 0 }, + { 12.0238, 4.7619 }, + { 7.2619, 9.5238 }, + { 2.5, 23.8095 }, + { 2.5, 33.3333 }, +}; + +static const StrokeRec char74[] = { + { 10, char74_stroke0 }, +}; + +/* char: 75 'K' */ + +static const CoordRec char75_stroke0[] = { + { 11.28, 100 }, + { 11.28, 0 }, +}; + +static const CoordRec char75_stroke1[] = { + { 77.9467, 100 }, + { 11.28, 33.3333 }, +}; + +static const CoordRec char75_stroke2[] = { + { 35.0895, 57.1429 }, + { 77.9467, 0 }, +}; + +static const StrokeRec char75[] = { + { 2, char75_stroke0 }, + { 2, char75_stroke1 }, + { 2, char75_stroke2 }, +}; + +/* char: 76 'L' */ + +static const CoordRec char76_stroke0[] = { + { 11.68, 100 }, + { 11.68, 0 }, +}; + +static const CoordRec char76_stroke1[] = { + { 11.68, 0 }, + { 68.8229, 0 }, +}; + +static const StrokeRec char76[] = { + { 2, char76_stroke0 }, + { 2, char76_stroke1 }, +}; + +/* char: 77 'M' */ + +static const CoordRec char77_stroke0[] = { + { 10.86, 100 }, + { 10.86, 0 }, +}; + +static const CoordRec char77_stroke1[] = { + { 10.86, 100 }, + { 48.9552, 0 }, +}; + +static const CoordRec char77_stroke2[] = { + { 87.0505, 100 }, + { 48.9552, 0 }, +}; + +static const CoordRec char77_stroke3[] = { + { 87.0505, 100 }, + { 87.0505, 0 }, +}; + +static const StrokeRec char77[] = { + { 2, char77_stroke0 }, + { 2, char77_stroke1 }, + { 2, char77_stroke2 }, + { 2, char77_stroke3 }, +}; + +/* char: 78 'N' */ + +static const CoordRec char78_stroke0[] = { + { 11.14, 100 }, + { 11.14, 0 }, +}; + +static const CoordRec char78_stroke1[] = { + { 11.14, 100 }, + { 77.8067, 0 }, +}; + +static const CoordRec char78_stroke2[] = { + { 77.8067, 100 }, + { 77.8067, 0 }, +}; + +static const StrokeRec char78[] = { + { 2, char78_stroke0 }, + { 2, char78_stroke1 }, + { 2, char78_stroke2 }, +}; + +/* char: 79 'O' */ + +static const CoordRec char79_stroke0[] = { + { 34.8114, 100 }, + { 25.2876, 95.2381 }, + { 15.7638, 85.7143 }, + { 11.0019, 76.1905 }, + { 6.24, 61.9048 }, + { 6.24, 38.0952 }, + { 11.0019, 23.8095 }, + { 15.7638, 14.2857 }, + { 25.2876, 4.7619 }, + { 34.8114, 0 }, + { 53.859, 0 }, + { 63.3829, 4.7619 }, + { 72.9067, 14.2857 }, + { 77.6686, 23.8095 }, + { 82.4305, 38.0952 }, + { 82.4305, 61.9048 }, + { 77.6686, 76.1905 }, + { 72.9067, 85.7143 }, + { 63.3829, 95.2381 }, + { 53.859, 100 }, + { 34.8114, 100 }, +}; + +static const StrokeRec char79[] = { + { 21, char79_stroke0 }, +}; + +/* char: 80 'P' */ + +static const CoordRec char80_stroke0[] = { + { 12.1, 100 }, + { 12.1, 0 }, +}; + +static const CoordRec char80_stroke1[] = { + { 12.1, 100 }, + { 54.9571, 100 }, + { 69.2429, 95.2381 }, + { 74.0048, 90.4762 }, + { 78.7667, 80.9524 }, + { 78.7667, 66.6667 }, + { 74.0048, 57.1429 }, + { 69.2429, 52.381 }, + { 54.9571, 47.619 }, + { 12.1, 47.619 }, +}; + +static const StrokeRec char80[] = { + { 2, char80_stroke0 }, + { 10, char80_stroke1 }, +}; + +/* char: 81 'Q' */ + +static const CoordRec char81_stroke0[] = { + { 33.8714, 100 }, + { 24.3476, 95.2381 }, + { 14.8238, 85.7143 }, + { 10.0619, 76.1905 }, + { 5.3, 61.9048 }, + { 5.3, 38.0952 }, + { 10.0619, 23.8095 }, + { 14.8238, 14.2857 }, + { 24.3476, 4.7619 }, + { 33.8714, 0 }, + { 52.919, 0 }, + { 62.4429, 4.7619 }, + { 71.9667, 14.2857 }, + { 76.7286, 23.8095 }, + { 81.4905, 38.0952 }, + { 81.4905, 61.9048 }, + { 76.7286, 76.1905 }, + { 71.9667, 85.7143 }, + { 62.4429, 95.2381 }, + { 52.919, 100 }, + { 33.8714, 100 }, +}; + +static const CoordRec char81_stroke1[] = { + { 48.1571, 19.0476 }, + { 76.7286, -9.5238 }, +}; + +static const StrokeRec char81[] = { + { 21, char81_stroke0 }, + { 2, char81_stroke1 }, +}; + +/* char: 82 'R' */ + +static const CoordRec char82_stroke0[] = { + { 11.68, 100 }, + { 11.68, 0 }, +}; + +static const CoordRec char82_stroke1[] = { + { 11.68, 100 }, + { 54.5371, 100 }, + { 68.8229, 95.2381 }, + { 73.5848, 90.4762 }, + { 78.3467, 80.9524 }, + { 78.3467, 71.4286 }, + { 73.5848, 61.9048 }, + { 68.8229, 57.1429 }, + { 54.5371, 52.381 }, + { 11.68, 52.381 }, +}; + +static const CoordRec char82_stroke2[] = { + { 45.0133, 52.381 }, + { 78.3467, 0 }, +}; + +static const StrokeRec char82[] = { + { 2, char82_stroke0 }, + { 10, char82_stroke1 }, + { 2, char82_stroke2 }, +}; + +/* char: 83 'S' */ + +static const CoordRec char83_stroke0[] = { + { 74.6667, 85.7143 }, + { 65.1429, 95.2381 }, + { 50.8571, 100 }, + { 31.8095, 100 }, + { 17.5238, 95.2381 }, + { 8, 85.7143 }, + { 8, 76.1905 }, + { 12.7619, 66.6667 }, + { 17.5238, 61.9048 }, + { 27.0476, 57.1429 }, + { 55.619, 47.619 }, + { 65.1429, 42.8571 }, + { 69.9048, 38.0952 }, + { 74.6667, 28.5714 }, + { 74.6667, 14.2857 }, + { 65.1429, 4.7619 }, + { 50.8571, 0 }, + { 31.8095, 0 }, + { 17.5238, 4.7619 }, + { 8, 14.2857 }, +}; + +static const StrokeRec char83[] = { + { 20, char83_stroke0 }, +}; + +/* char: 84 'T' */ + +static const CoordRec char84_stroke0[] = { + { 35.6933, 100 }, + { 35.6933, 0 }, +}; + +static const CoordRec char84_stroke1[] = { + { 2.36, 100 }, + { 69.0267, 100 }, +}; + +static const StrokeRec char84[] = { + { 2, char84_stroke0 }, + { 2, char84_stroke1 }, +}; + +/* char: 85 'U' */ + +static const CoordRec char85_stroke0[] = { + { 11.54, 100 }, + { 11.54, 28.5714 }, + { 16.3019, 14.2857 }, + { 25.8257, 4.7619 }, + { 40.1114, 0 }, + { 49.6352, 0 }, + { 63.921, 4.7619 }, + { 73.4448, 14.2857 }, + { 78.2067, 28.5714 }, + { 78.2067, 100 }, +}; + +static const StrokeRec char85[] = { + { 10, char85_stroke0 }, +}; + +/* char: 86 'V' */ + +static const CoordRec char86_stroke0[] = { + { 2.36, 100 }, + { 40.4552, 0 }, +}; + +static const CoordRec char86_stroke1[] = { + { 78.5505, 100 }, + { 40.4552, 0 }, +}; + +static const StrokeRec char86[] = { + { 2, char86_stroke0 }, + { 2, char86_stroke1 }, +}; + +/* char: 87 'W' */ + +static const CoordRec char87_stroke0[] = { + { 2.22, 100 }, + { 26.0295, 0 }, +}; + +static const CoordRec char87_stroke1[] = { + { 49.839, 100 }, + { 26.0295, 0 }, +}; + +static const CoordRec char87_stroke2[] = { + { 49.839, 100 }, + { 73.6486, 0 }, +}; + +static const CoordRec char87_stroke3[] = { + { 97.4581, 100 }, + { 73.6486, 0 }, +}; + +static const StrokeRec char87[] = { + { 2, char87_stroke0 }, + { 2, char87_stroke1 }, + { 2, char87_stroke2 }, + { 2, char87_stroke3 }, +}; + +/* char: 88 'X' */ + +static const CoordRec char88_stroke0[] = { + { 2.5, 100 }, + { 69.1667, 0 }, +}; + +static const CoordRec char88_stroke1[] = { + { 69.1667, 100 }, + { 2.5, 0 }, +}; + +static const StrokeRec char88[] = { + { 2, char88_stroke0 }, + { 2, char88_stroke1 }, +}; + +/* char: 89 'Y' */ + +static const CoordRec char89_stroke0[] = { + { 1.52, 100 }, + { 39.6152, 52.381 }, + { 39.6152, 0 }, +}; + +static const CoordRec char89_stroke1[] = { + { 77.7105, 100 }, + { 39.6152, 52.381 }, +}; + +static const StrokeRec char89[] = { + { 3, char89_stroke0 }, + { 2, char89_stroke1 }, +}; + +/* char: 90 'Z' */ + +static const CoordRec char90_stroke0[] = { + { 69.1667, 100 }, + { 2.5, 0 }, +}; + +static const CoordRec char90_stroke1[] = { + { 2.5, 100 }, + { 69.1667, 100 }, +}; + +static const CoordRec char90_stroke2[] = { + { 2.5, 0 }, + { 69.1667, 0 }, +}; + +static const StrokeRec char90[] = { + { 2, char90_stroke0 }, + { 2, char90_stroke1 }, + { 2, char90_stroke2 }, +}; + +/* char: 91 '[' */ + +static const CoordRec char91_stroke0[] = { + { 7.78, 119.048 }, + { 7.78, -33.3333 }, +}; + +static const CoordRec char91_stroke1[] = { + { 12.5419, 119.048 }, + { 12.5419, -33.3333 }, +}; + +static const CoordRec char91_stroke2[] = { + { 7.78, 119.048 }, + { 41.1133, 119.048 }, +}; + +static const CoordRec char91_stroke3[] = { + { 7.78, -33.3333 }, + { 41.1133, -33.3333 }, +}; + +static const StrokeRec char91[] = { + { 2, char91_stroke0 }, + { 2, char91_stroke1 }, + { 2, char91_stroke2 }, + { 2, char91_stroke3 }, +}; + +/* char: 92 '\' */ + +static const CoordRec char92_stroke0[] = { + { 5.84, 100 }, + { 72.5067, -14.2857 }, +}; + +static const StrokeRec char92[] = { + { 2, char92_stroke0 }, +}; + +/* char: 93 ']' */ + +static const CoordRec char93_stroke0[] = { + { 33.0114, 119.048 }, + { 33.0114, -33.3333 }, +}; + +static const CoordRec char93_stroke1[] = { + { 37.7733, 119.048 }, + { 37.7733, -33.3333 }, +}; + +static const CoordRec char93_stroke2[] = { + { 4.44, 119.048 }, + { 37.7733, 119.048 }, +}; + +static const CoordRec char93_stroke3[] = { + { 4.44, -33.3333 }, + { 37.7733, -33.3333 }, +}; + +static const StrokeRec char93[] = { + { 2, char93_stroke0 }, + { 2, char93_stroke1 }, + { 2, char93_stroke2 }, + { 2, char93_stroke3 }, +}; + +/* char: 94 '^' */ + +static const CoordRec char94_stroke0[] = { + { 44.0752, 109.524 }, + { 5.98, 42.8571 }, +}; + +static const CoordRec char94_stroke1[] = { + { 44.0752, 109.524 }, + { 82.1705, 42.8571 }, +}; + +static const StrokeRec char94[] = { + { 2, char94_stroke0 }, + { 2, char94_stroke1 }, +}; + +/* char: 95 '_' */ + +static const CoordRec char95_stroke0[] = { + { -1.1, -33.3333 }, + { 103.662, -33.3333 }, + { 103.662, -28.5714 }, + { -1.1, -28.5714 }, + { -1.1, -33.3333 }, +}; + +static const StrokeRec char95[] = { + { 5, char95_stroke0 }, +}; + +/* char: 96 '`' */ + +static const CoordRec char96_stroke0[] = { + { 33.0219, 100 }, + { 56.8314, 71.4286 }, +}; + +static const CoordRec char96_stroke1[] = { + { 33.0219, 100 }, + { 28.26, 95.2381 }, + { 56.8314, 71.4286 }, +}; + +static const StrokeRec char96[] = { + { 2, char96_stroke0 }, + { 3, char96_stroke1 }, +}; + +/* char: 97 'a' */ + +static const CoordRec char97_stroke0[] = { + { 63.8229, 66.6667 }, + { 63.8229, 0 }, +}; + +static const CoordRec char97_stroke1[] = { + { 63.8229, 52.381 }, + { 54.299, 61.9048 }, + { 44.7752, 66.6667 }, + { 30.4895, 66.6667 }, + { 20.9657, 61.9048 }, + { 11.4419, 52.381 }, + { 6.68, 38.0952 }, + { 6.68, 28.5714 }, + { 11.4419, 14.2857 }, + { 20.9657, 4.7619 }, + { 30.4895, 0 }, + { 44.7752, 0 }, + { 54.299, 4.7619 }, + { 63.8229, 14.2857 }, +}; + +static const StrokeRec char97[] = { + { 2, char97_stroke0 }, + { 14, char97_stroke1 }, +}; + +/* char: 98 'b' */ + +static const CoordRec char98_stroke0[] = { + { 8.76, 100 }, + { 8.76, 0 }, +}; + +static const CoordRec char98_stroke1[] = { + { 8.76, 52.381 }, + { 18.2838, 61.9048 }, + { 27.8076, 66.6667 }, + { 42.0933, 66.6667 }, + { 51.6171, 61.9048 }, + { 61.141, 52.381 }, + { 65.9029, 38.0952 }, + { 65.9029, 28.5714 }, + { 61.141, 14.2857 }, + { 51.6171, 4.7619 }, + { 42.0933, 0 }, + { 27.8076, 0 }, + { 18.2838, 4.7619 }, + { 8.76, 14.2857 }, +}; + +static const StrokeRec char98[] = { + { 2, char98_stroke0 }, + { 14, char98_stroke1 }, +}; + +/* char: 99 'c' */ + +static const CoordRec char99_stroke0[] = { + { 62.6629, 52.381 }, + { 53.139, 61.9048 }, + { 43.6152, 66.6667 }, + { 29.3295, 66.6667 }, + { 19.8057, 61.9048 }, + { 10.2819, 52.381 }, + { 5.52, 38.0952 }, + { 5.52, 28.5714 }, + { 10.2819, 14.2857 }, + { 19.8057, 4.7619 }, + { 29.3295, 0 }, + { 43.6152, 0 }, + { 53.139, 4.7619 }, + { 62.6629, 14.2857 }, +}; + +static const StrokeRec char99[] = { + { 14, char99_stroke0 }, +}; + +/* char: 100 'd' */ + +static const CoordRec char100_stroke0[] = { + { 61.7829, 100 }, + { 61.7829, 0 }, +}; + +static const CoordRec char100_stroke1[] = { + { 61.7829, 52.381 }, + { 52.259, 61.9048 }, + { 42.7352, 66.6667 }, + { 28.4495, 66.6667 }, + { 18.9257, 61.9048 }, + { 9.4019, 52.381 }, + { 4.64, 38.0952 }, + { 4.64, 28.5714 }, + { 9.4019, 14.2857 }, + { 18.9257, 4.7619 }, + { 28.4495, 0 }, + { 42.7352, 0 }, + { 52.259, 4.7619 }, + { 61.7829, 14.2857 }, +}; + +static const StrokeRec char100[] = { + { 2, char100_stroke0 }, + { 14, char100_stroke1 }, +}; + +/* char: 101 'e' */ + +static const CoordRec char101_stroke0[] = { + { 5.72, 38.0952 }, + { 62.8629, 38.0952 }, + { 62.8629, 47.619 }, + { 58.101, 57.1429 }, + { 53.339, 61.9048 }, + { 43.8152, 66.6667 }, + { 29.5295, 66.6667 }, + { 20.0057, 61.9048 }, + { 10.4819, 52.381 }, + { 5.72, 38.0952 }, + { 5.72, 28.5714 }, + { 10.4819, 14.2857 }, + { 20.0057, 4.7619 }, + { 29.5295, 0 }, + { 43.8152, 0 }, + { 53.339, 4.7619 }, + { 62.8629, 14.2857 }, +}; + +static const StrokeRec char101[] = { + { 17, char101_stroke0 }, +}; + +/* char: 102 'f' */ + +static const CoordRec char102_stroke0[] = { + { 38.7752, 100 }, + { 29.2514, 100 }, + { 19.7276, 95.2381 }, + { 14.9657, 80.9524 }, + { 14.9657, 0 }, +}; + +static const CoordRec char102_stroke1[] = { + { 0.68, 66.6667 }, + { 34.0133, 66.6667 }, +}; + +static const StrokeRec char102[] = { + { 5, char102_stroke0 }, + { 2, char102_stroke1 }, +}; + +/* char: 103 'g' */ + +static const CoordRec char103_stroke0[] = { + { 62.5029, 66.6667 }, + { 62.5029, -9.5238 }, + { 57.741, -23.8095 }, + { 52.979, -28.5714 }, + { 43.4552, -33.3333 }, + { 29.1695, -33.3333 }, + { 19.6457, -28.5714 }, +}; + +static const CoordRec char103_stroke1[] = { + { 62.5029, 52.381 }, + { 52.979, 61.9048 }, + { 43.4552, 66.6667 }, + { 29.1695, 66.6667 }, + { 19.6457, 61.9048 }, + { 10.1219, 52.381 }, + { 5.36, 38.0952 }, + { 5.36, 28.5714 }, + { 10.1219, 14.2857 }, + { 19.6457, 4.7619 }, + { 29.1695, 0 }, + { 43.4552, 0 }, + { 52.979, 4.7619 }, + { 62.5029, 14.2857 }, +}; + +static const StrokeRec char103[] = { + { 7, char103_stroke0 }, + { 14, char103_stroke1 }, +}; + +/* char: 104 'h' */ + +static const CoordRec char104_stroke0[] = { + { 9.6, 100 }, + { 9.6, 0 }, +}; + +static const CoordRec char104_stroke1[] = { + { 9.6, 47.619 }, + { 23.8857, 61.9048 }, + { 33.4095, 66.6667 }, + { 47.6952, 66.6667 }, + { 57.219, 61.9048 }, + { 61.981, 47.619 }, + { 61.981, 0 }, +}; + +static const StrokeRec char104[] = { + { 2, char104_stroke0 }, + { 7, char104_stroke1 }, +}; + +/* char: 105 'i' */ + +static const CoordRec char105_stroke0[] = { + { 10.02, 100 }, + { 14.7819, 95.2381 }, + { 19.5438, 100 }, + { 14.7819, 104.762 }, + { 10.02, 100 }, +}; + +static const CoordRec char105_stroke1[] = { + { 14.7819, 66.6667 }, + { 14.7819, 0 }, +}; + +static const StrokeRec char105[] = { + { 5, char105_stroke0 }, + { 2, char105_stroke1 }, +}; + +/* char: 106 'j' */ + +static const CoordRec char106_stroke0[] = { + { 17.3876, 100 }, + { 22.1495, 95.2381 }, + { 26.9114, 100 }, + { 22.1495, 104.762 }, + { 17.3876, 100 }, +}; + +static const CoordRec char106_stroke1[] = { + { 22.1495, 66.6667 }, + { 22.1495, -14.2857 }, + { 17.3876, -28.5714 }, + { 7.8638, -33.3333 }, + { -1.66, -33.3333 }, +}; + +static const StrokeRec char106[] = { + { 5, char106_stroke0 }, + { 5, char106_stroke1 }, +}; + +/* char: 107 'k' */ + +static const CoordRec char107_stroke0[] = { + { 9.6, 100 }, + { 9.6, 0 }, +}; + +static const CoordRec char107_stroke1[] = { + { 57.219, 66.6667 }, + { 9.6, 19.0476 }, +}; + +static const CoordRec char107_stroke2[] = { + { 28.6476, 38.0952 }, + { 61.981, 0 }, +}; + +static const StrokeRec char107[] = { + { 2, char107_stroke0 }, + { 2, char107_stroke1 }, + { 2, char107_stroke2 }, +}; + +/* char: 108 'l' */ + +static const CoordRec char108_stroke0[] = { + { 10.02, 100 }, + { 10.02, 0 }, +}; + +static const StrokeRec char108[] = { + { 2, char108_stroke0 }, +}; + +/* char: 109 'm' */ + +static const CoordRec char109_stroke0[] = { + { 9.6, 66.6667 }, + { 9.6, 0 }, +}; + +static const CoordRec char109_stroke1[] = { + { 9.6, 47.619 }, + { 23.8857, 61.9048 }, + { 33.4095, 66.6667 }, + { 47.6952, 66.6667 }, + { 57.219, 61.9048 }, + { 61.981, 47.619 }, + { 61.981, 0 }, +}; + +static const CoordRec char109_stroke2[] = { + { 61.981, 47.619 }, + { 76.2667, 61.9048 }, + { 85.7905, 66.6667 }, + { 100.076, 66.6667 }, + { 109.6, 61.9048 }, + { 114.362, 47.619 }, + { 114.362, 0 }, +}; + +static const StrokeRec char109[] = { + { 2, char109_stroke0 }, + { 7, char109_stroke1 }, + { 7, char109_stroke2 }, +}; + +/* char: 110 'n' */ + +static const CoordRec char110_stroke0[] = { + { 9.18, 66.6667 }, + { 9.18, 0 }, +}; + +static const CoordRec char110_stroke1[] = { + { 9.18, 47.619 }, + { 23.4657, 61.9048 }, + { 32.9895, 66.6667 }, + { 47.2752, 66.6667 }, + { 56.799, 61.9048 }, + { 61.561, 47.619 }, + { 61.561, 0 }, +}; + +static const StrokeRec char110[] = { + { 2, char110_stroke0 }, + { 7, char110_stroke1 }, +}; + +/* char: 111 'o' */ + +static const CoordRec char111_stroke0[] = { + { 28.7895, 66.6667 }, + { 19.2657, 61.9048 }, + { 9.7419, 52.381 }, + { 4.98, 38.0952 }, + { 4.98, 28.5714 }, + { 9.7419, 14.2857 }, + { 19.2657, 4.7619 }, + { 28.7895, 0 }, + { 43.0752, 0 }, + { 52.599, 4.7619 }, + { 62.1229, 14.2857 }, + { 66.8848, 28.5714 }, + { 66.8848, 38.0952 }, + { 62.1229, 52.381 }, + { 52.599, 61.9048 }, + { 43.0752, 66.6667 }, + { 28.7895, 66.6667 }, +}; + +static const StrokeRec char111[] = { + { 17, char111_stroke0 }, +}; + +/* char: 112 'p' */ + +static const CoordRec char112_stroke0[] = { + { 9.46, 66.6667 }, + { 9.46, -33.3333 }, +}; + +static const CoordRec char112_stroke1[] = { + { 9.46, 52.381 }, + { 18.9838, 61.9048 }, + { 28.5076, 66.6667 }, + { 42.7933, 66.6667 }, + { 52.3171, 61.9048 }, + { 61.841, 52.381 }, + { 66.6029, 38.0952 }, + { 66.6029, 28.5714 }, + { 61.841, 14.2857 }, + { 52.3171, 4.7619 }, + { 42.7933, 0 }, + { 28.5076, 0 }, + { 18.9838, 4.7619 }, + { 9.46, 14.2857 }, +}; + +static const StrokeRec char112[] = { + { 2, char112_stroke0 }, + { 14, char112_stroke1 }, +}; + +/* char: 113 'q' */ + +static const CoordRec char113_stroke0[] = { + { 61.9829, 66.6667 }, + { 61.9829, -33.3333 }, +}; + +static const CoordRec char113_stroke1[] = { + { 61.9829, 52.381 }, + { 52.459, 61.9048 }, + { 42.9352, 66.6667 }, + { 28.6495, 66.6667 }, + { 19.1257, 61.9048 }, + { 9.6019, 52.381 }, + { 4.84, 38.0952 }, + { 4.84, 28.5714 }, + { 9.6019, 14.2857 }, + { 19.1257, 4.7619 }, + { 28.6495, 0 }, + { 42.9352, 0 }, + { 52.459, 4.7619 }, + { 61.9829, 14.2857 }, +}; + +static const StrokeRec char113[] = { + { 2, char113_stroke0 }, + { 14, char113_stroke1 }, +}; + +/* char: 114 'r' */ + +static const CoordRec char114_stroke0[] = { + { 9.46, 66.6667 }, + { 9.46, 0 }, +}; + +static const CoordRec char114_stroke1[] = { + { 9.46, 38.0952 }, + { 14.2219, 52.381 }, + { 23.7457, 61.9048 }, + { 33.2695, 66.6667 }, + { 47.5552, 66.6667 }, +}; + +static const StrokeRec char114[] = { + { 2, char114_stroke0 }, + { 5, char114_stroke1 }, +}; + +/* char: 115 's' */ + +static const CoordRec char115_stroke0[] = { + { 57.081, 52.381 }, + { 52.319, 61.9048 }, + { 38.0333, 66.6667 }, + { 23.7476, 66.6667 }, + { 9.4619, 61.9048 }, + { 4.7, 52.381 }, + { 9.4619, 42.8571 }, + { 18.9857, 38.0952 }, + { 42.7952, 33.3333 }, + { 52.319, 28.5714 }, + { 57.081, 19.0476 }, + { 57.081, 14.2857 }, + { 52.319, 4.7619 }, + { 38.0333, 0 }, + { 23.7476, 0 }, + { 9.4619, 4.7619 }, + { 4.7, 14.2857 }, +}; + +static const StrokeRec char115[] = { + { 17, char115_stroke0 }, +}; + +/* char: 116 't' */ + +static const CoordRec char116_stroke0[] = { + { 14.8257, 100 }, + { 14.8257, 19.0476 }, + { 19.5876, 4.7619 }, + { 29.1114, 0 }, + { 38.6352, 0 }, +}; + +static const CoordRec char116_stroke1[] = { + { 0.54, 66.6667 }, + { 33.8733, 66.6667 }, +}; + +static const StrokeRec char116[] = { + { 5, char116_stroke0 }, + { 2, char116_stroke1 }, +}; + +/* char: 117 'u' */ + +static const CoordRec char117_stroke0[] = { + { 9.46, 66.6667 }, + { 9.46, 19.0476 }, + { 14.2219, 4.7619 }, + { 23.7457, 0 }, + { 38.0314, 0 }, + { 47.5552, 4.7619 }, + { 61.841, 19.0476 }, +}; + +static const CoordRec char117_stroke1[] = { + { 61.841, 66.6667 }, + { 61.841, 0 }, +}; + +static const StrokeRec char117[] = { + { 7, char117_stroke0 }, + { 2, char117_stroke1 }, +}; + +/* char: 118 'v' */ + +static const CoordRec char118_stroke0[] = { + { 1.8, 66.6667 }, + { 30.3714, 0 }, +}; + +static const CoordRec char118_stroke1[] = { + { 58.9429, 66.6667 }, + { 30.3714, 0 }, +}; + +static const StrokeRec char118[] = { + { 2, char118_stroke0 }, + { 2, char118_stroke1 }, +}; + +/* char: 119 'w' */ + +static const CoordRec char119_stroke0[] = { + { 2.5, 66.6667 }, + { 21.5476, 0 }, +}; + +static const CoordRec char119_stroke1[] = { + { 40.5952, 66.6667 }, + { 21.5476, 0 }, +}; + +static const CoordRec char119_stroke2[] = { + { 40.5952, 66.6667 }, + { 59.6429, 0 }, +}; + +static const CoordRec char119_stroke3[] = { + { 78.6905, 66.6667 }, + { 59.6429, 0 }, +}; + +static const StrokeRec char119[] = { + { 2, char119_stroke0 }, + { 2, char119_stroke1 }, + { 2, char119_stroke2 }, + { 2, char119_stroke3 }, +}; + +/* char: 120 'x' */ + +static const CoordRec char120_stroke0[] = { + { 1.66, 66.6667 }, + { 54.041, 0 }, +}; + +static const CoordRec char120_stroke1[] = { + { 54.041, 66.6667 }, + { 1.66, 0 }, +}; + +static const StrokeRec char120[] = { + { 2, char120_stroke0 }, + { 2, char120_stroke1 }, +}; + +/* char: 121 'y' */ + +static const CoordRec char121_stroke0[] = { + { 6.5619, 66.6667 }, + { 35.1333, 0 }, +}; + +static const CoordRec char121_stroke1[] = { + { 63.7048, 66.6667 }, + { 35.1333, 0 }, + { 25.6095, -19.0476 }, + { 16.0857, -28.5714 }, + { 6.5619, -33.3333 }, + { 1.8, -33.3333 }, +}; + +static const StrokeRec char121[] = { + { 2, char121_stroke0 }, + { 6, char121_stroke1 }, +}; + +/* char: 122 'z' */ + +static const CoordRec char122_stroke0[] = { + { 56.821, 66.6667 }, + { 4.44, 0 }, +}; + +static const CoordRec char122_stroke1[] = { + { 4.44, 66.6667 }, + { 56.821, 66.6667 }, +}; + +static const CoordRec char122_stroke2[] = { + { 4.44, 0 }, + { 56.821, 0 }, +}; + +static const StrokeRec char122[] = { + { 2, char122_stroke0 }, + { 2, char122_stroke1 }, + { 2, char122_stroke2 }, +}; + +/* char: 123 '{' */ + +static const CoordRec char123_stroke0[] = { + { 31.1895, 119.048 }, + { 21.6657, 114.286 }, + { 16.9038, 109.524 }, + { 12.1419, 100 }, + { 12.1419, 90.4762 }, + { 16.9038, 80.9524 }, + { 21.6657, 76.1905 }, + { 26.4276, 66.6667 }, + { 26.4276, 57.1429 }, + { 16.9038, 47.619 }, +}; + +static const CoordRec char123_stroke1[] = { + { 21.6657, 114.286 }, + { 16.9038, 104.762 }, + { 16.9038, 95.2381 }, + { 21.6657, 85.7143 }, + { 26.4276, 80.9524 }, + { 31.1895, 71.4286 }, + { 31.1895, 61.9048 }, + { 26.4276, 52.381 }, + { 7.38, 42.8571 }, + { 26.4276, 33.3333 }, + { 31.1895, 23.8095 }, + { 31.1895, 14.2857 }, + { 26.4276, 4.7619 }, + { 21.6657, 0 }, + { 16.9038, -9.5238 }, + { 16.9038, -19.0476 }, + { 21.6657, -28.5714 }, +}; + +static const CoordRec char123_stroke2[] = { + { 16.9038, 38.0952 }, + { 26.4276, 28.5714 }, + { 26.4276, 19.0476 }, + { 21.6657, 9.5238 }, + { 16.9038, 4.7619 }, + { 12.1419, -4.7619 }, + { 12.1419, -14.2857 }, + { 16.9038, -23.8095 }, + { 21.6657, -28.5714 }, + { 31.1895, -33.3333 }, +}; + +static const StrokeRec char123[] = { + { 10, char123_stroke0 }, + { 17, char123_stroke1 }, + { 10, char123_stroke2 }, +}; + +/* char: 124 '|' */ + +static const CoordRec char124_stroke0[] = { + { 11.54, 119.048 }, + { 11.54, -33.3333 }, +}; + +static const StrokeRec char124[] = { + { 2, char124_stroke0 }, +}; + +/* char: 125 '}' */ + +static const CoordRec char125_stroke0[] = { + { 9.18, 119.048 }, + { 18.7038, 114.286 }, + { 23.4657, 109.524 }, + { 28.2276, 100 }, + { 28.2276, 90.4762 }, + { 23.4657, 80.9524 }, + { 18.7038, 76.1905 }, + { 13.9419, 66.6667 }, + { 13.9419, 57.1429 }, + { 23.4657, 47.619 }, +}; + +static const CoordRec char125_stroke1[] = { + { 18.7038, 114.286 }, + { 23.4657, 104.762 }, + { 23.4657, 95.2381 }, + { 18.7038, 85.7143 }, + { 13.9419, 80.9524 }, + { 9.18, 71.4286 }, + { 9.18, 61.9048 }, + { 13.9419, 52.381 }, + { 32.9895, 42.8571 }, + { 13.9419, 33.3333 }, + { 9.18, 23.8095 }, + { 9.18, 14.2857 }, + { 13.9419, 4.7619 }, + { 18.7038, 0 }, + { 23.4657, -9.5238 }, + { 23.4657, -19.0476 }, + { 18.7038, -28.5714 }, +}; + +static const CoordRec char125_stroke2[] = { + { 23.4657, 38.0952 }, + { 13.9419, 28.5714 }, + { 13.9419, 19.0476 }, + { 18.7038, 9.5238 }, + { 23.4657, 4.7619 }, + { 28.2276, -4.7619 }, + { 28.2276, -14.2857 }, + { 23.4657, -23.8095 }, + { 18.7038, -28.5714 }, + { 9.18, -33.3333 }, +}; + +static const StrokeRec char125[] = { + { 10, char125_stroke0 }, + { 17, char125_stroke1 }, + { 10, char125_stroke2 }, +}; + +/* char: 126 '~' */ + +static const CoordRec char126_stroke0[] = { + { 2.92, 28.5714 }, + { 2.92, 38.0952 }, + { 7.6819, 52.381 }, + { 17.2057, 57.1429 }, + { 26.7295, 57.1429 }, + { 36.2533, 52.381 }, + { 55.301, 38.0952 }, + { 64.8248, 33.3333 }, + { 74.3486, 33.3333 }, + { 83.8724, 38.0952 }, + { 88.6343, 47.619 }, +}; + +static const CoordRec char126_stroke1[] = { + { 2.92, 38.0952 }, + { 7.6819, 47.619 }, + { 17.2057, 52.381 }, + { 26.7295, 52.381 }, + { 36.2533, 47.619 }, + { 55.301, 33.3333 }, + { 64.8248, 28.5714 }, + { 74.3486, 28.5714 }, + { 83.8724, 33.3333 }, + { 88.6343, 47.619 }, + { 88.6343, 57.1429 }, +}; + +static const StrokeRec char126[] = { + { 11, char126_stroke0 }, + { 11, char126_stroke1 }, +}; + +/* char: 127 */ + +static const CoordRec char127_stroke0[] = { + { 52.381, 100 }, + { 14.2857, -33.3333 }, +}; + +static const CoordRec char127_stroke1[] = { + { 28.5714, 66.6667 }, + { 14.2857, 61.9048 }, + { 4.7619, 52.381 }, + { 0, 38.0952 }, + { 0, 23.8095 }, + { 4.7619, 14.2857 }, + { 14.2857, 4.7619 }, + { 28.5714, 0 }, + { 38.0952, 0 }, + { 52.381, 4.7619 }, + { 61.9048, 14.2857 }, + { 66.6667, 28.5714 }, + { 66.6667, 42.8571 }, + { 61.9048, 52.381 }, + { 52.381, 61.9048 }, + { 38.0952, 66.6667 }, + { 28.5714, 66.6667 }, +}; + +static const StrokeRec char127[] = { + { 2, char127_stroke0 }, + { 17, char127_stroke1 }, +}; + +static const StrokeCharRec chars[] = { + { 0, /* char0 */ 0, 0, 0 }, + { 0, /* char1 */ 0, 0, 0 }, + { 0, /* char2 */ 0, 0, 0 }, + { 0, /* char3 */ 0, 0, 0 }, + { 0, /* char4 */ 0, 0, 0 }, + { 0, /* char5 */ 0, 0, 0 }, + { 0, /* char6 */ 0, 0, 0 }, + { 0, /* char7 */ 0, 0, 0 }, + { 0, /* char8 */ 0, 0, 0 }, + { 0, /* char9 */ 0, 0, 0 }, + { 0, /* char10 */ 0, 0, 0 }, + { 0, /* char11 */ 0, 0, 0 }, + { 0, /* char12 */ 0, 0, 0 }, + { 0, /* char13 */ 0, 0, 0 }, + { 0, /* char14 */ 0, 0, 0 }, + { 0, /* char15 */ 0, 0, 0 }, + { 0, /* char16 */ 0, 0, 0 }, + { 0, /* char17 */ 0, 0, 0 }, + { 0, /* char18 */ 0, 0, 0 }, + { 0, /* char19 */ 0, 0, 0 }, + { 0, /* char20 */ 0, 0, 0 }, + { 0, /* char21 */ 0, 0, 0 }, + { 0, /* char22 */ 0, 0, 0 }, + { 0, /* char23 */ 0, 0, 0 }, + { 0, /* char24 */ 0, 0, 0 }, + { 0, /* char25 */ 0, 0, 0 }, + { 0, /* char26 */ 0, 0, 0 }, + { 0, /* char27 */ 0, 0, 0 }, + { 0, /* char28 */ 0, 0, 0 }, + { 0, /* char29 */ 0, 0, 0 }, + { 0, /* char30 */ 0, 0, 0 }, + { 0, /* char31 */ 0, 0, 0 }, + { 0, /* char32 */ 0, 35, 70 }, /* jwz: changed this to be 'n' width. + (it was 52.381, 104.762) */ + { 2, char33, 13.3819, 26.6238 }, + { 2, char34, 23.0676, 51.4352 }, + { 4, char35, 36.5333, 79.4886 }, + { 3, char36, 38.1533, 76.2067 }, + { 3, char37, 49.2171, 96.5743 }, + { 1, char38, 53.599, 101.758 }, + { 1, char39, 4.44, 13.62 }, + { 1, char40, 21.8657, 47.1733 }, + { 1, char41, 24.3276, 47.5333 }, + { 3, char42, 30.7695, 59.439 }, + { 2, char43, 48.8371, 97.2543 }, + { 1, char44, 13.5219, 26.0638 }, + { 1, char45, 50.2371, 100.754 }, + { 1, char46, 13.1019, 26.4838 }, + { 1, char47, 40.5733, 82.1067 }, + { 1, char48, 38.3133, 77.0667 }, + { 1, char49, 30.8676, 66.5295 }, + { 1, char50, 38.7533, 77.6467 }, + { 1, char51, 38.3333, 77.0467 }, + { 2, char52, 37.2133, 80.1686 }, + { 1, char53, 38.1933, 77.6867 }, + { 1, char54, 34.1514, 73.8048 }, + { 2, char55, 38.8933, 77.2267 }, + { 1, char56, 38.9333, 77.6667 }, + { 1, char57, 39.9333, 74.0648 }, + { 2, char58, 14.0819, 26.2238 }, + { 2, char59, 12.9619, 26.3038 }, + { 1, char60, 41.1552, 81.6105 }, + { 2, char61, 48.5571, 97.2543 }, + { 1, char62, 40.8752, 81.6105 }, + { 2, char63, 36.9914, 73.9029 }, + { 2, char64, 34.9314, 74.3648 }, + { 3, char65, 40.5952, 80.4905 }, + { 3, char66, 44.7533, 83.6267 }, + { 1, char67, 39.9933, 84.4886 }, + { 2, char68, 45.2933, 85.2867 }, + { 4, char69, 39.9914, 78.1848 }, + { 3, char70, 39.9914, 78.7448 }, + { 2, char71, 40.3933, 89.7686 }, + { 3, char72, 44.7533, 89.0867 }, + { 1, char73, 10.86, 21.3 }, + { 1, char74, 31.0714, 59.999 }, + { 3, char75, 44.6133, 79.3267 }, + { 2, char76, 40.2514, 71.3229 }, + { 4, char77, 48.9552, 97.2105 }, + { 3, char78, 44.4733, 88.8067 }, + { 1, char79, 44.3352, 88.8305 }, + { 2, char80, 45.4333, 85.6667 }, + { 2, char81, 43.3952, 88.0905 }, + { 3, char82, 45.0133, 82.3667 }, + { 1, char83, 41.3333, 80.8267 }, + { 2, char84, 35.6933, 71.9467 }, + { 1, char85, 44.8733, 89.4867 }, + { 2, char86, 40.4552, 81.6105 }, + { 4, char87, 49.839, 100.518 }, + { 2, char88, 35.8333, 72.3667 }, + { 2, char89, 39.6152, 79.6505 }, + { 3, char90, 35.8333, 73.7467 }, + { 4, char91, 22.0657, 46.1133 }, + { 1, char92, 39.1733, 78.2067 }, + { 4, char93, 23.4876, 46.3933 }, + { 2, char94, 44.0752, 90.2305 }, + { 1, char95, 51.281, 104.062 }, + { 2, char96, 42.5457, 83.5714 }, + { 2, char97, 35.2514, 66.6029 }, + { 2, char98, 37.3314, 70.4629 }, + { 1, char99, 34.0914, 68.9229 }, + { 2, char100, 33.2114, 70.2629 }, + { 1, char101, 34.2914, 68.5229 }, + { 2, char102, 14.9657, 38.6552 }, + { 2, char103, 33.9314, 70.9829 }, + { 2, char104, 33.4095, 71.021 }, + { 2, char105, 14.7819, 28.8638 }, + { 2, char106, 17.3876, 36.2314 }, + { 3, char107, 33.4095, 62.521 }, + { 1, char108, 10.02, 19.34 }, + { 3, char109, 61.981, 123.962 }, + { 2, char110, 32.9895, 70.881 }, + { 1, char111, 33.5514, 71.7448 }, + { 2, char112, 38.0314, 70.8029 }, + { 2, char113, 33.4114, 70.7429 }, + { 2, char114, 23.7457, 49.4952 }, + { 1, char115, 28.5095, 62.321 }, + { 2, char116, 14.8257, 39.3152 }, + { 2, char117, 33.2695, 71.161 }, + { 2, char118, 30.3714, 60.6029 }, + { 4, char119, 40.5952, 80.4905 }, + { 2, char120, 25.4695, 56.401 }, + { 2, char121, 35.1333, 66.0648 }, + { 3, char122, 28.2495, 61.821 }, + { 3, char123, 21.6657, 41.6295 }, + { 1, char124, 11.54, 23.78 }, + { 3, char125, 18.7038, 41.4695 }, + { 2, char126, 45.7771, 91.2743 }, + { 2, char127, 33.3333, 66.6667 }, +}; + +static +StrokeFontRec glutStrokeRoman = { "Roman", 128, chars, 119.048, -33.3333 }; + diff --git a/hacks/glx/glut_stroke.c b/hacks/glx/glut_stroke.c new file mode 100644 index 00000000..455e3db0 --- /dev/null +++ b/hacks/glx/glut_stroke.c @@ -0,0 +1,57 @@ + +/* Copyright (c) Mark J. Kilgard, 1994. */ + +/* This program is freely distributable without licensing fees + and is provided without guarantee or warrantee expressed or + implied. This program is -not- in the public domain. */ + +#if 0 /* for Mesa */ +# include "glutint.h" +#else /* for xscreensaver */ +# ifdef HAVE_CONFIG_H +# include "config.h" +# endif +# ifndef HAVE_COCOA +# include +# endif +# ifdef HAVE_JWZGLES +# include "jwzgles.h" +# endif /* HAVE_JWZGLES */ +# undef APIENTRY +# define APIENTRY /**/ +#endif + +#include "glutstroke.h" + +void APIENTRY +glutStrokeCharacter(GLUTstrokeFont font, int c) +{ + const StrokeCharRec *ch; + const StrokeRec *stroke; + const CoordRec *coord; + StrokeFontPtr fontinfo; + int i, j; + + +#if defined(_WIN32) + fontinfo = (StrokeFontPtr) __glutFont(font); +#else + fontinfo = (StrokeFontPtr) font; +#endif + + if (c < 0 || c >= fontinfo->num_chars) + return; + ch = &(fontinfo->ch[c]); + if (ch) { + for (i = ch->num_strokes, stroke = ch->stroke; + i > 0; i--, stroke++) { + glBegin(GL_LINE_STRIP); + for (j = stroke->num_coords, coord = stroke->coord; + j > 0; j--, coord++) { + glVertex2f(coord->x, coord->y); + } + glEnd(); + } + glTranslatef(ch->right, 0.0, 0.0); + } +} diff --git a/hacks/glx/glut_swidth.c b/hacks/glx/glut_swidth.c new file mode 100644 index 00000000..185571d1 --- /dev/null +++ b/hacks/glx/glut_swidth.c @@ -0,0 +1,73 @@ + +/* Copyright (c) Mark J. Kilgard, 1995. */ + +/* This program is freely distributable without licensing fees + and is provided without guarantee or warrantee expressed or + implied. This program is -not- in the public domain. */ + +#if 0 /* for Mesa */ +# include "glutint.h" +#else /* for xscreensaver */ +# ifdef HAVE_CONFIG_H +# include "config.h" +# endif +# ifndef HAVE_COCOA +# include +# endif +# ifdef HAVE_JWZGLES +# include "jwzgles.h" +# endif /* HAVE_JWZGLES */ +# undef APIENTRY +# define APIENTRY /**/ +#endif + +#include "glutstroke.h" + +/* CENTRY */ +int APIENTRY +glutStrokeWidth(GLUTstrokeFont font, int c) +{ + StrokeFontPtr fontinfo; + const StrokeCharRec *ch; + +#if defined(_WIN32) + fontinfo = (StrokeFontPtr) __glutFont(font); +#else + fontinfo = (StrokeFontPtr) font; +#endif + + if (c < 0 || c >= fontinfo->num_chars) + return 0; + ch = &(fontinfo->ch[c]); + if (ch) + return ch->right; + else + return 0; +} + +int APIENTRY +glutStrokeLength(GLUTstrokeFont font, const unsigned char *string) +{ + int c, length; + StrokeFontPtr fontinfo; + const StrokeCharRec *ch; + +#if defined(_WIN32) + fontinfo = (StrokeFontPtr) __glutFont(font); +#else + fontinfo = (StrokeFontPtr) font; +#endif + + length = 0; + for (; *string != '\0'; string++) { + c = *string; + if (c >= 0 && c < fontinfo->num_chars) { + ch = &(fontinfo->ch[c]); + if (ch) + length += ch->right; + } + } + return length; +} + +/* ENDCENTRY */ diff --git a/hacks/glx/glutstroke.h b/hacks/glx/glutstroke.h new file mode 100644 index 00000000..43a645bf --- /dev/null +++ b/hacks/glx/glutstroke.h @@ -0,0 +1,47 @@ +#ifndef __glutstroke_h__ +#define __glutstroke_h__ + +/* Copyright (c) Mark J. Kilgard, 1994. */ + +/* This program is freely distributable without licensing fees + and is provided without guarantee or warrantee expressed or + implied. This program is -not- in the public domain. */ + +#if defined(_WIN32) +#pragma warning (disable:4244) /* disable bogus conversion warnings */ +#pragma warning (disable:4305) /* VC++ 5.0 version of above warning. */ +#endif + +typedef struct { + float x; + float y; +} CoordRec, *CoordPtr; + +typedef struct { + int num_coords; + const CoordRec *coord; +} StrokeRec, *StrokePtr; + +typedef struct { + int num_strokes; + const StrokeRec *stroke; + float center; + float right; +} StrokeCharRec, *StrokeCharPtr; + +typedef struct { + const char *name; + int num_chars; + const StrokeCharRec *ch; + float top; + float bottom; +} StrokeFontRec, *StrokeFontPtr; + +typedef void *GLUTstrokeFont; + +/* for xscreensaver */ +extern void glutStrokeCharacter (GLUTstrokeFont font, int c); +extern int glutStrokeWidth (GLUTstrokeFont font, int c); +extern int glutStrokeLength (GLUTstrokeFont font, const unsigned char *string); + +#endif /* __glutstroke_h__ */ diff --git a/hacks/glx/glxfonts.c b/hacks/glx/glxfonts.c new file mode 100644 index 00000000..db068d77 --- /dev/null +++ b/hacks/glx/glxfonts.c @@ -0,0 +1,671 @@ +/* glxfonts, Copyright (c) 2001-2012 Jamie Zawinski + * Loads X11 fonts for use with OpenGL. + * + * 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. + * + * Draws 2D text over the GL scene, e.g., the FPS displays. + * + * There are two implementations here: one using glBitmap (the OpenGL 1.1 way) + * and one using textures via texfont.c (since OpenGLES doesn't have glBitmap). + */ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include +#include +#include +#include + +#ifdef HAVE_COCOA +# include "jwxyz.h" +/*# include */ +#else +# include +# include +#endif + +#ifdef HAVE_JWZGLES +# include "jwzgles.h" +#endif /* HAVE_JWZGLES */ + +#include "resources.h" +#include "glxfonts.h" +#include "fps.h" + +#ifndef HAVE_GLBITMAP +# include "texfont.h" +#endif /* HAVE_GLBITMAP */ + + +/* These are in xlock-gl.c */ +extern void clear_gl_error (void); +extern void check_gl_error (const char *type); + +/* screenhack.h */ +extern char *progname; + + +#undef DEBUG /* Defining this causes check_gl_error() to be called inside + time-critical sections, which could slow things down (since + it might result in a round-trip, and stall of the pipeline.) + */ + + +#undef countof +#define countof(x) (sizeof((x))/sizeof((*x))) + + +/* Width (and optionally height) of the string in pixels. + */ +int +string_width (XFontStruct *f, const char *c, int *height_ret) +{ + int x = 0; + int max_w = 0; + int h = f->ascent + f->descent; + while (*c) + { + int cc = *((unsigned char *) c); + if (*c == '\n') + { + if (x > max_w) max_w = x; + x = 0; + h += f->ascent + f->descent; + } + else + x += (f->per_char + ? f->per_char[cc-f->min_char_or_byte2].width + : f->min_bounds.rbearing); + c++; + } + if (x > max_w) max_w = x; + if (height_ret) *height_ret = h; + + return max_w; +} + + +#ifdef HAVE_GLBITMAP + +/* Mostly lifted from the Mesa implementation of glXUseXFont(), since + Mac OS 10.6 no longer supports aglUseFont() which was their analog + of that. This code could be in libjwxyz instead, but we might as + well use the same text-drawing code on both X11 and Cocoa. + */ +static void +fill_bitmap (Display *dpy, Window win, GC gc, + unsigned int width, unsigned int height, + int x0, int y0, char c, GLubyte *bitmap) +{ + XImage *image; + int x, y; + Pixmap pixmap; + + pixmap = XCreatePixmap (dpy, win, 8*width, height, 1); + XSetForeground(dpy, gc, 0); + XFillRectangle (dpy, pixmap, gc, 0, 0, 8*width, height); + XSetForeground(dpy, gc, 1); + XDrawString (dpy, pixmap, gc, x0, y0, &c, 1); + + image = XGetImage (dpy, pixmap, 0, 0, 8*width, height, 1, XYPixmap); + + /* Fill the bitmap (X11 and OpenGL are upside down wrt each other). */ + for (y = 0; y < height; y++) + for (x = 0; x < 8*width; x++) + if (XGetPixel (image, x, y)) + bitmap[width*(height - y - 1) + x/8] |= (1 << (7 - (x % 8))); + + XFreePixmap (dpy, pixmap); + XDestroyImage (image); +} + + +#if 0 +static void +dump_bitmap (unsigned int width, unsigned int height, GLubyte *bitmap) +{ + int x, y; + + printf (" "); + for (x = 0; x < 8*width; x++) + printf ("%o", 7 - (x % 8)); + putchar ('\n'); + for (y = 0; y < height; y++) + { + printf ("%3o:", y); + for (x = 0; x < 8*width; x++) + putchar ((bitmap[width*(height - y - 1) + x/8] & (1 << (7 - (x % 8)))) + ? '#' : '.'); + printf (" "); + for (x = 0; x < width; x++) + printf ("0x%02x, ", bitmap[width*(height - y - 1) + x]); + putchar ('\n'); + } +} +#endif + + +void +xscreensaver_glXUseXFont (Display *dpy, Font font, + int first, int count, int listbase) +{ + Window win = RootWindowOfScreen (DefaultScreenOfDisplay (dpy)); + Pixmap pixmap; + GC gc; + XGCValues values; + unsigned long valuemask; + + XFontStruct *fs; + + GLint swapbytes, lsbfirst, rowlength; + GLint skiprows, skippixels, alignment; + + unsigned int max_width, max_height, max_bm_width, max_bm_height; + GLubyte *bm; + + int i; + + clear_gl_error (); + + fs = XQueryFont (dpy, font); + if (!fs) + { + /*gl_error (CC->gl_ctx, GL_INVALID_VALUE, + "Couldn't get font structure information");*/ + abort(); + return; + } + + /* Allocate a bitmap that can fit all characters. */ + max_width = fs->max_bounds.rbearing - fs->min_bounds.lbearing; + max_height = fs->max_bounds.ascent + fs->max_bounds.descent; + max_bm_width = (max_width + 7) / 8; + max_bm_height = max_height; + + bm = (GLubyte *) malloc ((max_bm_width * max_bm_height) * sizeof (GLubyte)); + if (!bm) + { + /*gl_error (CC->gl_ctx, GL_OUT_OF_MEMORY, + "Couldn't allocate bitmap in glXUseXFont()");*/ + abort(); + return; + } + + /* Save the current packing mode for bitmaps. */ + glGetIntegerv (GL_UNPACK_SWAP_BYTES, &swapbytes); + glGetIntegerv (GL_UNPACK_LSB_FIRST, &lsbfirst); + glGetIntegerv (GL_UNPACK_ROW_LENGTH, &rowlength); + glGetIntegerv (GL_UNPACK_SKIP_ROWS, &skiprows); + glGetIntegerv (GL_UNPACK_SKIP_PIXELS, &skippixels); + glGetIntegerv (GL_UNPACK_ALIGNMENT, &alignment); + + /* Enforce a standard packing mode which is compatible with + fill_bitmap() from above. This is actually the default mode, + except for the (non)alignment. */ + glPixelStorei (GL_UNPACK_SWAP_BYTES, GL_FALSE); + glPixelStorei (GL_UNPACK_LSB_FIRST, GL_FALSE); + glPixelStorei (GL_UNPACK_ROW_LENGTH, 0); + glPixelStorei (GL_UNPACK_SKIP_ROWS, 0); + glPixelStorei (GL_UNPACK_SKIP_PIXELS, 0); + glPixelStorei (GL_UNPACK_ALIGNMENT, 1); + + clear_gl_error(); /* WTF? sometimes "invalid op" from glPixelStorei! */ + + + pixmap = XCreatePixmap (dpy, win, 10, 10, 1); + values.foreground = 0; + values.background = 1; + values.font = fs->fid; + valuemask = GCForeground | GCBackground | GCFont; + gc = XCreateGC (dpy, pixmap, valuemask, &values); + XFreePixmap (dpy, pixmap); + +# ifdef HAVE_COCOA + /* Anti-aliasing of fonts looks like crap with 1-bit bitmaps. + It would be nice if we were using full-depth bitmaps, so + that the text showed up anti-aliased on screen, but + glBitmap() doesn't work that way. */ + jwxyz_XSetAntiAliasing (dpy, gc, False); +# endif + + for (i = 0; i < count; i++) + { + unsigned int width, height, bm_width, bm_height; + GLfloat x0, y0, dx, dy; + XCharStruct *ch; + int x, y; + int c = first + i; + int list = listbase + i; + + if (fs->per_char + && (c >= fs->min_char_or_byte2) && (c <= fs->max_char_or_byte2)) + ch = &fs->per_char[c-fs->min_char_or_byte2]; + else + ch = &fs->max_bounds; + + /* I'm not entirely clear on why this is necessary on OSX, but + without it, the characters are clipped. And it does not hurt + under real X11. -- jwz. */ + ch->lbearing--; + ch->ascent++; + + /* glBitmap()'s parameters: + "Bitmap parameters xorig, yorig, width, and height are + computed from font metrics as descent-1, -lbearing, + rbearing-lbearing, and ascent+descent, respectively. + xmove is taken from the glyph's width metric, and + ymove is set to zero. Finally, the glyph's image is + converted to the appropriate format for glBitmap." + */ + width = ch->rbearing - ch->lbearing; + height = ch->ascent + ch->descent; + x0 = - ch->lbearing; + y0 = ch->descent - 1; + dx = ch->width; + dy = 0; + + /* X11's starting point. */ + x = - ch->lbearing; + y = ch->ascent; + + /* Round the width to a multiple of eight. We will use this also + for the pixmap for capturing the X11 font. This is slightly + inefficient, but it makes the OpenGL part real easy. */ + bm_width = (width + 7) / 8; + bm_height = height; + + glNewList (list, GL_COMPILE); + if ((c >= fs->min_char_or_byte2) && (c <= fs->max_char_or_byte2) + && (bm_width > 0) && (bm_height > 0)) + { + memset (bm, '\0', bm_width * bm_height); + fill_bitmap (dpy, win, gc, bm_width, bm_height, x, y, c, bm); + glBitmap (width, height, x0, y0, dx, dy, bm); +#if 0 + printf ("width/height = %d/%d\n", width, height); + printf ("bm_width/bm_height = %d/%d\n", bm_width, bm_height); + dump_bitmap (bm_width, bm_height, bm); +#endif + } + else + glBitmap (0, 0, 0.0, 0.0, dx, dy, NULL); + glEndList (); + } + + free (bm); + XFreeFontInfo( NULL, fs, 0 ); + XFreeGC (dpy, gc); + + /* Restore saved packing modes. */ + glPixelStorei(GL_UNPACK_SWAP_BYTES, swapbytes); + glPixelStorei(GL_UNPACK_LSB_FIRST, lsbfirst); + glPixelStorei(GL_UNPACK_ROW_LENGTH, rowlength); + glPixelStorei(GL_UNPACK_SKIP_ROWS, skiprows); + glPixelStorei(GL_UNPACK_SKIP_PIXELS, skippixels); + glPixelStorei(GL_UNPACK_ALIGNMENT, alignment); + + check_gl_error ("xscreensaver_glXUseXFont"); +} + + + +/* Loads the font named by the X resource "res". + Returns an XFontStruct. + Also converts the font to a set of GL lists and returns the first list. +*/ +void +load_font (Display *dpy, char *res, XFontStruct **font_ret, GLuint *dlist_ret) +{ + XFontStruct *f; + + const char *font = get_string_resource (dpy, res, "Font"); + const char *def1 = "-*-helvetica-medium-r-normal-*-180-*"; + const char *def2 = "fixed"; + Font id; + int first, last; + + if (!res || !*res) abort(); + if (!font_ret && !dlist_ret) abort(); + + if (!font) font = def1; + + f = XLoadQueryFont(dpy, font); + if (!f && !!strcmp (font, def1)) + { + fprintf (stderr, "%s: unable to load font \"%s\", using \"%s\"\n", + progname, font, def1); + font = def1; + f = XLoadQueryFont(dpy, font); + } + + if (!f && !!strcmp (font, def2)) + { + fprintf (stderr, "%s: unable to load font \"%s\", using \"%s\"\n", + progname, font, def2); + font = def2; + f = XLoadQueryFont(dpy, font); + } + + if (!f) + { + fprintf (stderr, "%s: unable to load fallback font \"%s\" either!\n", + progname, font); + exit (1); + } + + id = f->fid; + first = f->min_char_or_byte2; + last = f->max_char_or_byte2; + + + if (dlist_ret) + { + clear_gl_error (); + *dlist_ret = glGenLists ((GLuint) last+1); + check_gl_error ("glGenLists"); + xscreensaver_glXUseXFont (dpy, id, first, last-first+1, + *dlist_ret + first); + } + + if (font_ret) + *font_ret = f; +} + +#endif /* HAVE_GLBITMAP */ + + +/* Draws the string on the window at the given pixel position. + Newlines and tab stops are honored. + Any text inside [] will be rendered as a subscript. + Assumes the font has been loaded as with load_font(). + */ +void +print_gl_string (Display *dpy, +# ifdef HAVE_GLBITMAP + XFontStruct *font, GLuint font_dlist, +# else + texture_font_data *font_data, +# endif + int window_width, int window_height, + GLfloat x, GLfloat y, + const char *string, + Bool clear_background_p) +{ + + /* If window_width was specified, we're drawing ortho in pixel coordinates. + Otherwise, we're just dropping the text at the current position in the + scene, billboarded. */ + Bool in_scene_p = (window_width == 0); + +# ifdef HAVE_GLBITMAP + GLfloat line_height = font->ascent + font->descent; + int cw = string_width (font, "m", 0); +# else /* !HAVE_GLBITMAP */ + int line_height = 0; + int cw = texture_string_width (font_data, "m", &line_height); +# endif /* !HAVE_GLBITMAP */ + + GLfloat sub_shift = (line_height * 0.3); + int tabs = cw * 7; + int lines = 0; + const char *c; + GLfloat color[4]; + +# ifdef HAVE_GLBITMAP + /* Sadly, this causes a stall of the graphics pipeline (as would the + equivalent calls to glGet*.) But there's no way around this, short + of having each caller set up the specific display matrix we need + here, which would kind of defeat the purpose of centralizing this + code in one file. + */ + glPushAttrib (GL_TRANSFORM_BIT | /* for matrix contents */ + GL_ENABLE_BIT | /* for various glDisable calls */ + GL_CURRENT_BIT | /* for glColor3f() */ + GL_LIST_BIT); /* for glListBase() */ +# ifdef DEBUG + check_gl_error ("glPushAttrib"); +# endif +# else /* !HAVE_GLBITMAP */ + Bool tex_p = glIsEnabled (GL_TEXTURE_2D); + Bool texs_p = glIsEnabled (GL_TEXTURE_GEN_S); + Bool text_p = glIsEnabled (GL_TEXTURE_GEN_T); + Bool light_p = glIsEnabled (GL_LIGHTING); + Bool blend_p = glIsEnabled (GL_BLEND); + Bool depth_p = glIsEnabled (GL_DEPTH_TEST); + Bool cull_p = glIsEnabled (GL_CULL_FACE); + Bool fog_p = glIsEnabled (GL_FOG); + GLint oblend; +# ifndef HAVE_JWZGLES + GLint opoly[2]; + glGetIntegerv (GL_POLYGON_MODE, opoly); +# endif + glGetIntegerv (GL_BLEND_DST, &oblend); +# endif /* !HAVE_GLBITMAP */ + + glGetFloatv (GL_CURRENT_COLOR, color); + + for (c = string; *c; c++) + if (*c == '\n') lines++; + + y -= line_height; + + { + + /* disable lighting and texturing when drawing bitmaps! + (glPopAttrib() restores these.) + */ +# ifdef HAVE_GLBITMAP + glDisable (GL_TEXTURE_2D); +# else /* !HAVE_GLBITMAP */ + glEnable (GL_TEXTURE_2D); + glDisable (GL_TEXTURE_GEN_S); + glDisable (GL_TEXTURE_GEN_T); + glPolygonMode (GL_FRONT, GL_FILL); + glEnable (GL_BLEND); + glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); +# endif /* !HAVE_GLBITMAP */ + + glDisable (GL_LIGHTING); + + + if (!in_scene_p) + glDisable (GL_DEPTH_TEST); + glDisable (GL_CULL_FACE); + glDisable (GL_FOG); + + /* glPopAttrib() does not restore matrix changes, so we must + push/pop the matrix stacks to be non-intrusive there. + */ + glMatrixMode(GL_PROJECTION); + glPushMatrix(); + { +# ifdef DEBUG + check_gl_error ("glPushMatrix"); +# endif + if (!in_scene_p) + glLoadIdentity(); + + /* Each matrix mode has its own stack, so we need to push/pop + them separately. */ + glMatrixMode(GL_MODELVIEW); + glPushMatrix(); + { + unsigned int i; + int x2 = x; + Bool sub_p = False; + +# ifdef DEBUG + check_gl_error ("glPushMatrix"); +# endif + + if (!in_scene_p) + { + double rot = current_device_rotation(); + + glLoadIdentity(); + glOrtho (0, window_width, 0, window_height, -1, 1); + + if (rot > 135 || rot < -135) + { + glTranslatef (window_width, window_height, 0); + glRotatef (180, 0, 0, 1); + } + else if (rot > 45) + { + glTranslatef (window_width, 0, 0); + glRotatef (90, 0, 0, 1); + y -= (window_height - window_width); + if (y < line_height * lines + 10) + y = line_height * lines + 10; + } + else if (rot < -45) + { + glTranslatef(0, window_height, 0); + glRotatef (-90, 0, 0, 1); + y -= (window_height - window_width); + if (y < line_height * lines + 10) + y = line_height * lines + 10; + } + } +# ifdef DEBUG + check_gl_error ("glOrtho"); +# endif + + /* Let's always dropshadow the FPS and Title text. */ + if (! in_scene_p) + clear_background_p = True; + +#if 0 + if (clear_background_p) + { + int w, h; + glColor3f (0, 0, 0); +# ifdef HAVE_GLBITMAP + w = string_width (font, string, &h); + glRecti (x - font->descent, + y + line_height, + x + w + 2*font->descent, + y + line_height - h - font->descent); +# else /* !HAVE_GLBITMAP */ + { + int descent = line_height * 0.2; + if (descent < 2) descent = 2; + w = texture_string_width (font_data, string, &h); + glRecti (x - descent, + y + line_height, + x + w + 2*descent, + y + line_height - h - descent); + } +# endif /* !HAVE_GLBITMAP */ + glColor3f (1, 1, 1); + } +#endif /* 0 */ + + + /* draw the text */ + + for (i = 0; i < strlen(string); i++) + { + unsigned char c = (unsigned char) string[i]; + if (c == '\n') + { + y -= line_height; + x2 = x; + } + else if (c == '\t') + { + x2 -= x; + x2 = ((x2 + tabs) / tabs) * tabs; /* tab to tab stop */ + x2 += x; + } + else if (c == '[' && (isdigit (string[i+1]))) + { + sub_p = True; + y -= sub_shift; + } + else if (c == ']' && sub_p) + { + sub_p = False; + y += sub_shift; + } + else + { + /* outline font in black */ + const XPoint offsets[] = {{ -1, -1 }, + { -1, 1 }, + { 1, 1 }, + { 1, -1 }, + { 0, 0 }}; + int j; +# ifndef HAVE_GLBITMAP + char s[2]; + s[0] = c; + s[1] = 0; +# endif /* !HAVE_GLBITMAP */ + + glColor3f (0, 0, 0); + for (j = 0; j < countof(offsets); j++) + { + if (! clear_background_p) + j = countof(offsets)-1; + if (offsets[j].x == 0) + glColor4fv (color); + +# ifdef HAVE_GLBITMAP + glRasterPos2f (x2 + offsets[j].x, y + offsets[j].y); + glCallList (font_dlist + (int)(c)); +# else /* !HAVE_GLBITMAP */ + glPushMatrix(); + glTranslatef (x2 + offsets[j].x, y + offsets[j].y, 0); + print_texture_string (font_data, s); + glPopMatrix(); +# endif /* !HAVE_GLBITMAP */ + } +# ifdef HAVE_GLBITMAP + x2 += (font->per_char + ? font->per_char[c - font->min_char_or_byte2].width + : font->min_bounds.width); +# else /* !HAVE_GLBITMAP */ + x2 += texture_string_width (font_data, s, 0); +# endif /* !HAVE_GLBITMAP */ + } + } +# ifdef DEBUG + check_gl_error ("print_gl_string"); +# endif + } + glPopMatrix(); + } + glMatrixMode(GL_PROJECTION); + glPopMatrix(); + } +# ifdef HAVE_GLBITMAP + glPopAttrib(); +# ifdef DEBUG + check_gl_error ("glPopAttrib"); +# endif +# else /* !HAVE_GLBITMAP */ + if (tex_p) glEnable (GL_TEXTURE_2D); else glDisable (GL_TEXTURE_2D); + if (texs_p) glEnable (GL_TEXTURE_GEN_S);/*else glDisable (GL_TEXTURE_GEN_S);*/ + if (text_p) glEnable (GL_TEXTURE_GEN_T);/*else glDisable (GL_TEXTURE_GEN_T);*/ + if (blend_p) glEnable (GL_BLEND); else glDisable (GL_BLEND); + if (light_p) glEnable (GL_LIGHTING); /*else glDisable (GL_LIGHTING);*/ + if (depth_p) glEnable (GL_DEPTH_TEST); else glDisable (GL_DEPTH_TEST); + if (cull_p) glEnable (GL_CULL_FACE); /*else glDisable (GL_CULL_FACE);*/ + if (fog_p) glEnable (GL_FOG); /*else glDisable (GL_FOG);*/ +# ifndef HAVE_JWZGLES + glPolygonMode (GL_FRONT, opoly[0]); +# endif + glBlendFunc (GL_SRC_ALPHA, oblend); +# endif /* !HAVE_GLBITMAP */ + + glMatrixMode(GL_MODELVIEW); +} diff --git a/hacks/glx/glxfonts.h b/hacks/glx/glxfonts.h new file mode 100644 index 00000000..46868046 --- /dev/null +++ b/hacks/glx/glxfonts.h @@ -0,0 +1,58 @@ +/* glxfonts, Copyright (c) 2001-2012 Jamie Zawinski + * Loads X11 fonts for use with OpenGL. + * + * 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. + * + * Loads X11 fonts for use with OpenGL. + */ + +#ifndef __GLXFONTS_H__ +#define __GLXFONTS_H__ + +#ifndef HAVE_GLBITMAP +# include "texfont.h" +#endif /* !HAVE_GLBITMAP */ + +#ifdef HAVE_GLBITMAP +/* This is basically the same as glXUseXFont(). + We have our own version of it for portability. + */ +extern void xscreensaver_glXUseXFont (Display *dpy, Font font, + int first, int count, int listbase); +#endif /* HAVE_GLBITMAP */ + +/* Loads the font named by the X resource "res". + Returns an XFontStruct. + Also converts the font to a set of GL lists and returns the first list. +*/ +extern void load_font (Display *, char *resource, + XFontStruct **font_ret, + GLuint *dlist_ret); + +/* Bounding box of the string in pixels. + */ +extern int string_width (XFontStruct *f, const char *c, int *height_ret); + +/* Draws the string on the window at the given pixel position. + Newlines and tab stops are honored. + Any text inside [] will be rendered as a subscript. + Assumes the font has been loaded as with load_font(). */ +void print_gl_string (Display *dpy, +# ifdef HAVE_GLBITMAP + XFontStruct *font, + GLuint font_dlist, +# else /* !HAVE_GLBITMAP */ + texture_font_data *font_data, +# endif /* !HAVE_GLBITMAP */ + int window_width, int window_height, + GLfloat x, GLfloat y, + const char *string, + Bool clear_background_p); + +#endif /* __GLXFONTS_H__ */ diff --git a/hacks/glx/grab-ximage.c b/hacks/glx/grab-ximage.c new file mode 100644 index 00000000..58063329 --- /dev/null +++ b/hacks/glx/grab-ximage.c @@ -0,0 +1,839 @@ +/* grab-ximage.c --- grab the screen to an XImage for use with OpenGL. + * xscreensaver, Copyright (c) 2001-2008 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. + */ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include +#include +#include + +#ifdef HAVE_COCOA +# include "jwxyz.h" +# ifndef HAVE_JWZGLES +# include +# endif +#else +# include +# include +# include /* only for GLfloat */ +# include /* for gluBuild2DMipmaps */ +# include /* for glXMakeCurrent() */ +#endif + +#ifdef HAVE_JWZGLES +# include "jwzgles.h" +#endif /* HAVE_JWZGLES */ + +#include "grab-ximage.h" +#include "grabscreen.h" +#include "visual.h" + +/* If REFORMAT_IMAGE_DATA is defined, then we convert Pixmaps to textures + like this: + + - get Pixmap as an XImage in whatever form the server hands us; + - convert that XImage to 32-bit RGBA in client-local endianness; + - make the texture using RGBA, UNSIGNED_BYTE. + + If undefined, we do this: + + - get Pixmap as an XImage in whatever form the server hands us; + - figure out what OpenGL texture packing parameters correspond to + the image data that the server sent us and use that, e.g., + BGRA, INT_8_8_8_8_REV. + + You might expect the second method to be faster, since we're not making + a second copy of the data and iterating each pixel before we hand it + to GL. But, you'd be wrong. The first method is almost 6x faster. + I guess GL is reformatting it *again*, and doing it very inefficiently! +*/ +#define REFORMAT_IMAGE_DATA + + +#ifdef HAVE_XSHM_EXTENSION +# include "resources.h" +# include "xshm.h" +#endif /* HAVE_XSHM_EXTENSION */ + +extern char *progname; + +#include + +#ifdef HAVE_COCOA +# include "jwxyz.h" +#else +# include +#endif + +#undef MAX +#define MAX(a,b) ((a)>(b)?(a):(b)) + +#undef countof +#define countof(x) (sizeof((x))/sizeof((*x))) + + +static int debug_p = 0; + +static Bool +bigendian (void) +{ + union { int i; char c[sizeof(int)]; } u; + u.i = 1; + return !u.c[0]; +} + + +#ifdef REFORMAT_IMAGE_DATA + +/* Given a bitmask, returns the position and width of the field. + */ +static void +decode_mask (unsigned int mask, unsigned int *pos_ret, unsigned int *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; + } +} + + +/* Given a value and a field-width, expands the field to fill out 8 bits. + */ +static unsigned char +spread_bits (unsigned char value, unsigned char width) +{ + switch (width) + { + case 8: return value; + case 7: return (value << 1) | (value >> 6); + case 6: return (value << 2) | (value >> 4); + case 5: return (value << 3) | (value >> 2); + case 4: return (value << 4) | (value); + case 3: return (value << 5) | (value << 2) | (value >> 2); + case 2: return (value << 6) | (value << 4) | (value); + default: abort(); break; + } +} + + +static XImage * +convert_ximage_to_rgba32 (Screen *screen, XImage *image) +{ + Display *dpy = DisplayOfScreen (screen); + Visual *visual = DefaultVisualOfScreen (screen); + + int x, y; + unsigned int crpos=0, cgpos=0, cbpos=0, capos=0; /* bitfield positions */ + unsigned int srpos=0, sgpos=0, sbpos=0; + unsigned int srmsk=0, sgmsk=0, sbmsk=0; + unsigned int srsiz=0, sgsiz=0, sbsiz=0; + XColor *colors = 0; + unsigned char spread_map[3][256]; + + /* Note: height+2 in "to" to work around an array bounds overrun + in gluBuild2DMipmaps / gluScaleImage. + */ + XImage *from = image; + XImage *to = XCreateImage (dpy, visual, 32, /* depth */ + ZPixmap, 0, 0, from->width, from->height + 2, + 32, /* bitmap pad */ + 0); + to->data = (char *) calloc (to->height, to->bytes_per_line); + + /* Set the bit order in the XImage structure to whatever the + local host's native bit order is. + */ + to->bitmap_bit_order = + to->byte_order = + (bigendian() ? MSBFirst : LSBFirst); + + if (visual_class (screen, visual) == PseudoColor || + visual_class (screen, visual) == GrayScale) + { + Colormap cmap = DefaultColormapOfScreen (screen); + int ncolors = visual_cells (screen, visual); + int i; + colors = (XColor *) calloc (sizeof (*colors), ncolors+1); + for (i = 0; i < ncolors; i++) + colors[i].pixel = i; + XQueryColors (dpy, cmap, colors, ncolors); + } + + if (colors == 0) /* truecolor */ + { + srmsk = to->red_mask; + sgmsk = to->green_mask; + sbmsk = to->blue_mask; + + decode_mask (srmsk, &srpos, &srsiz); + decode_mask (sgmsk, &sgpos, &sgsiz); + decode_mask (sbmsk, &sbpos, &sbsiz); + } + + /* Pack things in "RGBA" order in client endianness. */ + if (bigendian()) + crpos = 24, cgpos = 16, cbpos = 8, capos = 0; + else + crpos = 0, cgpos = 8, cbpos = 16, capos = 24; + + if (colors == 0) /* truecolor */ + { + int i; + for (i = 0; i < 256; i++) + { + spread_map[0][i] = spread_bits (i, srsiz); + spread_map[1][i] = spread_bits (i, sgsiz); + spread_map[2][i] = spread_bits (i, sbsiz); + } + } + + /* trying to track down an intermittent crash in ximage_putpixel_32 */ + if (to->width < from->width) abort(); + if (to->height < from->height) abort(); + + for (y = 0; y < from->height; y++) + for (x = 0; x < from->width; x++) + { + unsigned long sp = XGetPixel (from, x, y); + unsigned char sr, sg, sb; + unsigned long cp; + + if (colors) + { + sr = colors[sp].red & 0xFF; + sg = colors[sp].green & 0xFF; + sb = colors[sp].blue & 0xFF; + } + else + { + sr = (sp & srmsk) >> srpos; + sg = (sp & sgmsk) >> sgpos; + sb = (sp & sbmsk) >> sbpos; + + sr = spread_map[0][sr]; + sg = spread_map[1][sg]; + sb = spread_map[2][sb]; + } + + cp = ((sr << crpos) | + (sg << cgpos) | + (sb << cbpos) | + (0xFF << capos)); + + XPutPixel (to, x, y, cp); + } + + if (colors) free (colors); + + return to; +} + +#endif /* REFORMAT_IMAGE_DATA */ + +/* Shrinks the XImage by a factor of two. + We use this when mipmapping fails on large textures. + */ +static void +halve_image (XImage *ximage, XRectangle *geom) +{ + int w2 = ximage->width/2; + int h2 = ximage->height/2; + int x, y; + XImage *ximage2; + + if (w2 <= 32 || h2 <= 32) /* let's not go crazy here, man. */ + return; + + if (debug_p) + fprintf (stderr, "%s: shrinking image %dx%d -> %dx%d\n", + progname, ximage->width, ximage->height, w2, h2); + + ximage2 = (XImage *) calloc (1, sizeof (*ximage2)); + *ximage2 = *ximage; + ximage2->width = w2; + ximage2->height = h2; + ximage2->bytes_per_line = 0; + ximage2->data = 0; + XInitImage (ximage2); + + ximage2->data = (char *) calloc (h2, ximage2->bytes_per_line); + if (!ximage2->data) + { + fprintf (stderr, "%s: out of memory (scaling %dx%d image to %dx%d)\n", + progname, ximage->width, ximage->height, w2, h2); + exit (1); + } + + for (y = 0; y < h2; y++) + for (x = 0; x < w2; x++) + XPutPixel (ximage2, x, y, XGetPixel (ximage, x*2, y*2)); + + free (ximage->data); + *ximage = *ximage2; + ximage2->data = 0; + XFree (ximage2); + + if (geom) + { + geom->x /= 2; + geom->y /= 2; + geom->width /= 2; + geom->height /= 2; + } +} + + +#ifdef REFORMAT_IMAGE_DATA + +/* Pulls the Pixmap bits from the server and returns an XImage + in some format acceptable to OpenGL. + */ +static XImage * +pixmap_to_gl_ximage (Screen *screen, Window window, Pixmap pixmap) +{ + Display *dpy = DisplayOfScreen (screen); + unsigned int width, height, depth; + +# ifdef HAVE_XSHM_EXTENSION + Bool use_shm = get_boolean_resource (dpy, "useSHM", "Boolean"); + XShmSegmentInfo shm_info; +# endif /* HAVE_XSHM_EXTENSION */ + + XImage *server_ximage = 0; + XImage *client_ximage = 0; + + { + Window root; + int x, y; + unsigned int bw; + XGetGeometry (dpy, pixmap, &root, &x, &y, &width, &height, &bw, &depth); + } + + if (width < 5 || height < 5) /* something's gone wrong somewhere... */ + return 0; + + /* Convert the server-side Pixmap to a client-side GL-ordered XImage. + */ +# ifdef HAVE_XSHM_EXTENSION + if (use_shm) + { + Visual *visual = DefaultVisualOfScreen (screen); + server_ximage = create_xshm_image (dpy, visual, depth, + ZPixmap, 0, &shm_info, + width, height); + if (server_ximage) + XShmGetImage (dpy, pixmap, server_ximage, 0, 0, ~0L); + else + use_shm = False; + } +# endif /* HAVE_XSHM_EXTENSION */ + + if (!server_ximage) + server_ximage = XGetImage (dpy, pixmap, 0, 0, width, height, ~0L, ZPixmap); + + client_ximage = convert_ximage_to_rgba32 (screen, server_ximage); + +# ifdef HAVE_XSHM_EXTENSION + if (use_shm) + destroy_xshm_image (dpy, server_ximage, &shm_info); + else +# endif /* HAVE_XSHM_EXTENSION */ + XDestroyImage (server_ximage); + + return client_ximage; +} + + +# else /* ! REFORMAT_IMAGE_DATA */ + +typedef struct { + unsigned int depth, red_mask, green_mask, blue_mask; /* when this... */ + GLint type, format; /* ...use this. */ +} conversion_table; + +/* Abbreviate these so that the table entries all fit on one line... + */ +#define BYTE GL_UNSIGNED_BYTE +#define BYTE_2_3_3_REV GL_UNSIGNED_BYTE_2_3_3_REV +#define BYTE_3_3_2 GL_UNSIGNED_BYTE_3_3_2 +#define INT_10_10_10_2 GL_UNSIGNED_INT_10_10_10_2 +#define INT_2_10_10_10_REV GL_UNSIGNED_INT_2_10_10_10_REV +#define INT_8_8_8_8 GL_UNSIGNED_INT_8_8_8_8 +#define INT_8_8_8_8_REV GL_UNSIGNED_INT_8_8_8_8_REV +#define SHORT_1_5_5_5_REV GL_UNSIGNED_SHORT_1_5_5_5_REV +#define SHORT_4_4_4_4 GL_UNSIGNED_SHORT_4_4_4_4 +#define SHORT_4_4_4_4_REV GL_UNSIGNED_SHORT_4_4_4_4_REV +#define SHORT_5_5_5_1 GL_UNSIGNED_SHORT_5_5_5_1 +#define SHORT_5_6_5 GL_UNSIGNED_SHORT_5_6_5 +#define SHORT_5_6_5_REV GL_UNSIGNED_SHORT_5_6_5_REV + +static const conversion_table ctable[] = { + { 8, 0x000000E0, 0x0000001C, 0x00000003, BYTE_3_3_2, GL_RGB }, + { 8, 0x00000007, 0x00000038, 0x000000C0, BYTE_2_3_3_REV, GL_RGB }, + { 16, 0x0000F800, 0x000007E0, 0x0000001F, SHORT_5_6_5, GL_RGB }, + { 16, 0x0000001F, 0x000007E0, 0x0000F800, SHORT_5_6_5_REV, GL_RGB }, + { 16, 0x0000F000, 0x00000F00, 0x000000F0, SHORT_4_4_4_4, GL_RGBA }, + { 16, 0x000000F0, 0x00000F00, 0x0000F000, SHORT_4_4_4_4, GL_BGRA }, + { 16, 0x0000000F, 0x000000F0, 0x00000F00, SHORT_4_4_4_4, GL_ABGR_EXT }, + { 16, 0x0000000F, 0x000000F0, 0x00000F00, SHORT_4_4_4_4_REV, GL_RGBA }, + { 16, 0x00000F00, 0x000000F0, 0x0000000F, SHORT_4_4_4_4_REV, GL_BGRA }, + { 16, 0x0000F800, 0x000007C0, 0x0000003E, SHORT_5_5_5_1, GL_RGBA }, + { 16, 0x0000003E, 0x000007C0, 0x0000F800, SHORT_5_5_5_1, GL_BGRA }, + { 16, 0x00000001, 0x0000003E, 0x000007C0, SHORT_5_5_5_1, GL_ABGR_EXT }, + { 16, 0x0000001F, 0x000003E0, 0x00007C00, SHORT_1_5_5_5_REV, GL_RGBA }, + { 16, 0x00007C00, 0x000003E0, 0x0000001F, SHORT_1_5_5_5_REV, GL_BGRA }, + { 32, 0xFF000000, 0x00FF0000, 0x0000FF00, INT_8_8_8_8, GL_RGBA }, + { 32, 0x0000FF00, 0x00FF0000, 0xFF000000, INT_8_8_8_8, GL_BGRA }, + { 32, 0x000000FF, 0x0000FF00, 0x00FF0000, INT_8_8_8_8, GL_ABGR_EXT }, + { 32, 0x000000FF, 0x0000FF00, 0x00FF0000, INT_8_8_8_8_REV, GL_RGBA }, + { 32, 0x00FF0000, 0x0000FF00, 0x000000FF, INT_8_8_8_8_REV, GL_BGRA }, + { 32, 0xFFC00000, 0x003FF000, 0x00000FFC, INT_10_10_10_2, GL_RGBA }, + { 32, 0x00000FFC, 0x003FF000, 0xFFC00000, INT_10_10_10_2, GL_BGRA }, + { 32, 0x00000003, 0x00000FFC, 0x003FF000, INT_10_10_10_2, GL_ABGR_EXT }, + { 32, 0x000003FF, 0x000FFC00, 0x3FF00000, INT_2_10_10_10_REV, GL_RGBA }, + { 32, 0x3FF00000, 0x000FFC00, 0x000003FF, INT_2_10_10_10_REV, GL_BGRA }, + { 24, 0x000000FF, 0x0000FF00, 0x00FF0000, BYTE, GL_RGB }, + { 24, 0x00FF0000, 0x0000FF00, 0x000000FF, BYTE, GL_BGR }, +}; + + +/* Given an XImage, returns the GL settings to use its data as a texture. + */ +static void +gl_settings_for_ximage (XImage *image, + GLint *type_ret, GLint *format_ret, GLint *swap_ret) +{ + int i; + for (i = 0; i < countof(ctable); ++i) + { + if (image->bits_per_pixel == ctable[i].depth && + image->red_mask == ctable[i].red_mask && + image->green_mask == ctable[i].green_mask && + image->blue_mask == ctable[i].blue_mask) + { + *type_ret = ctable[i].type; + *format_ret = ctable[i].format; + + if (image->bits_per_pixel == 24) + { + /* don't know how to test this... */ + *type_ret = (ctable[i].type == GL_RGB) ? GL_BGR : GL_RGB; + *swap_ret = 0; + } + else + { + *swap_ret = !!(image->byte_order == MSBFirst) ^ !!bigendian(); + } + + if (debug_p) + { + fprintf (stderr, "%s: using %s %s %d for %d %08lX %08lX %08lX\n", + progname, + (*format_ret == GL_RGB ? "RGB" : + *format_ret == GL_BGR ? "BGR" : + *format_ret == GL_RGBA ? "RGBA" : + *format_ret == GL_BGRA ? "BGRA" : + *format_ret == GL_ABGR_EXT ? "ABGR_EXT" : + "???"), + (*type_ret == BYTE ? "BYTE" : + *type_ret == BYTE_3_3_2 ? "BYTE_3_3_2" : + *type_ret == BYTE_2_3_3_REV ? "BYTE_2_3_3_REV" : + *type_ret == INT_8_8_8_8 ? "INT_8_8_8_8" : + *type_ret == INT_8_8_8_8_REV ? "INT_8_8_8_8_REV" : + *type_ret == INT_10_10_10_2 ? "INT_10_10_10_2" : + *type_ret == INT_2_10_10_10_REV ? "INT_2_10_10_10_REV": + *type_ret == SHORT_4_4_4_4 ? "SHORT_4_4_4_4" : + *type_ret == SHORT_4_4_4_4_REV ? "SHORT_4_4_4_4_REV" : + *type_ret == SHORT_5_5_5_1 ? "SHORT_5_5_5_1" : + *type_ret == SHORT_1_5_5_5_REV ? "SHORT_1_5_5_5_REV" : + *type_ret == SHORT_5_6_5 ? "SHORT_5_6_5" : + *type_ret == SHORT_5_6_5_REV ? "SHORT_5_6_5_REV" : + "???"), + *swap_ret, + image->bits_per_pixel, + image->red_mask, image->green_mask, image->blue_mask); + } + + return; + } + } + + /* Unknown RGB fields? */ + abort(); +} + +#endif /* ! REFORMAT_IMAGE_DATA */ + +typedef struct { + GLXContext glx_context; + Pixmap pixmap; + int pix_width, pix_height, pix_depth; + int texid; + Bool mipmap_p; + double load_time; + + /* Used in async mode + */ + void (*callback) (const char *filename, XRectangle *geometry, + int iw, int ih, int tw, int th, + void *closure); + void *closure; + + /* Used in sync mode + */ + char **filename_return; + XRectangle *geometry_return; + int *image_width_return; + int *image_height_return; + int *texture_width_return; + int *texture_height_return; + +} img_closure; + + +/* Returns the current time in seconds as a double. + */ +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)); +} + + +/* return the next larger power of 2. */ +static int +to_pow2 (int value) +{ + int i = 1; + while (i < value) i <<= 1; + return i; +} + + +/* Loads the given XImage into GL's texture memory. + The image may be of any size. + If mipmap_p is true, then make mipmaps instead of just a single texture. + Writes to stderr and returns False on error. + */ +static Bool +ximage_to_texture (XImage *ximage, + GLint type, GLint format, + int *width_return, + int *height_return, + XRectangle *geometry, + Bool mipmap_p) +{ + int max_reduction = 7; + int err_count = 0; + GLenum err = 0; + int orig_width = ximage->width; + int orig_height = ximage->height; + int tex_width = 0; + int tex_height = 0; + + AGAIN: + + if (mipmap_p) + { + /* gluBuild2DMipmaps doesn't require textures to be a power of 2. */ + tex_width = ximage->width; + tex_height = ximage->height; + + if (debug_p) + fprintf (stderr, "%s: mipmap %d x %d\n", + progname, ximage->width, ximage->height); + + gluBuild2DMipmaps (GL_TEXTURE_2D, 3, ximage->width, ximage->height, + format, type, ximage->data); + err = glGetError(); + } + else + { + /* glTexImage2D() requires the texture sizes to be powers of 2. + So first, create a texture of that size (but don't write any + data into it.) + */ + tex_width = to_pow2 (ximage->width); + tex_height = to_pow2 (ximage->height); + + if (debug_p) + fprintf (stderr, "%s: texture %d x %d (%d x %d)\n", + progname, ximage->width, ximage->height, + tex_width, tex_height); + + glTexImage2D (GL_TEXTURE_2D, 0, GL_RGBA, tex_width, tex_height, 0, + format, type, 0); + err = glGetError(); + + /* Now load our non-power-of-2 image data into the existing texture. */ + if (!err) + { + glTexSubImage2D (GL_TEXTURE_2D, 0, 0, 0, + ximage->width, ximage->height, + GL_RGBA, GL_UNSIGNED_BYTE, ximage->data); + err = glGetError(); + } + } + + if (err) + { + char buf[100]; + const char *s = (char *) gluErrorString (err); + + if (!s || !*s) + { + sprintf (buf, "unknown error %d", (int) err); + s = buf; + } + + while (glGetError() != GL_NO_ERROR) + ; /* clear any lingering errors */ + + if (++err_count > max_reduction) + { + fprintf (stderr, + "\n" + "%s: %dx%d texture failed, even after reducing to %dx%d:\n" + "%s: The error was: \"%s\".\n" + "%s: probably this means " + "\"your video card is worthless and weak\"?\n\n", + progname, orig_width, orig_height, + ximage->width, ximage->height, + progname, s, + progname); + return False; + } + else + { + if (debug_p) + fprintf (stderr, "%s: mipmap error (%dx%d): %s\n", + progname, ximage->width, ximage->height, s); + halve_image (ximage, geometry); + goto AGAIN; + } + } + + if (width_return) *width_return = tex_width; + if (height_return) *height_return = tex_height; + return True; +} + + +static void load_texture_async_cb (Screen *screen, + Window window, Drawable drawable, + const char *name, XRectangle *geometry, + void *closure); + + +/* Grabs an image of the desktop (or another random image file) and + loads the image into GL's texture memory. + When the callback is called, the image data will have been loaded + into texture number `texid' (via glBindTexture.) + + If an error occurred, width/height will be 0. + */ +void +load_texture_async (Screen *screen, Window window, + GLXContext glx_context, + int desired_width, int desired_height, + Bool mipmap_p, + GLuint texid, + void (*callback) (const char *filename, + XRectangle *geometry, + int image_width, + int image_height, + int texture_width, + int texture_height, + void *closure), + void *closure) +{ + Display *dpy = DisplayOfScreen (screen); + XWindowAttributes xgwa; + img_closure *data = (img_closure *) calloc (1, sizeof(*data)); + + if (debug_p) + data->load_time = double_time(); + + data->texid = texid; + data->mipmap_p = mipmap_p; + data->glx_context = glx_context; + data->callback = callback; + data->closure = closure; + + XGetWindowAttributes (dpy, window, &xgwa); + data->pix_width = xgwa.width; + data->pix_height = xgwa.height; + data->pix_depth = xgwa.depth; + + if (desired_width && desired_width < xgwa.width) + data->pix_width = desired_width; + if (desired_height && desired_height < xgwa.height) + data->pix_height = desired_height; + + data->pixmap = XCreatePixmap (dpy, window, data->pix_width, data->pix_height, + data->pix_depth); + load_image_async (screen, window, data->pixmap, + load_texture_async_cb, data); +} + + +/* Once we have an XImage, this loads it into GL. + This is used in both synchronous and asynchronous mode. + */ +static void +load_texture_async_cb (Screen *screen, Window window, Drawable drawable, + const char *name, XRectangle *geometry, void *closure) +{ + Display *dpy = DisplayOfScreen (screen); + Bool ok; + XImage *ximage; + GLint type, format; + int iw=0, ih=0, tw=0, th=0; + double cvt_time=0, tex_time=0, done_time=0; + img_closure *data = (img_closure *) closure; + /* copy closure data to stack and free the original before running cb */ + img_closure dd = *data; + memset (data, 0, sizeof (*data)); + free (data); + data = 0; + + if (dd.glx_context) + glXMakeCurrent (dpy, window, dd.glx_context); + + if (geometry->width <= 0 || geometry->height <= 0) + { + /* This can happen if an old version of xscreensaver-getimage + is installed. */ + geometry->x = 0; + geometry->y = 0; + geometry->width = dd.pix_width; + geometry->height = dd.pix_height; + } + + if (geometry->width <= 0 || geometry->height <= 0) + abort(); + + if (debug_p) + cvt_time = double_time(); + +# ifdef REFORMAT_IMAGE_DATA + ximage = pixmap_to_gl_ximage (screen, window, dd.pixmap); + format = GL_RGBA; + type = GL_UNSIGNED_BYTE; + +#else /* ! REFORMAT_IMAGE_DATA */ + { + Visual *visual = DefaultVisualOfScreen (screen); + GLint swap; + + ximage = XCreateImage (dpy, visual, dd.pix_depth, ZPixmap, 0, 0, + dd.pix_width, dd.pix_height, 32, 0); + + /* Note: height+2 in "to" to be to work around an array bounds overrun + in gluBuild2DMipmaps / gluScaleImage. */ + ximage->data = (char *) calloc (ximage->height+2, ximage->bytes_per_line); + + if (!ximage->data || + !XGetSubImage (dpy, dd.pixmap, 0, 0, ximage->width, ximage->height, + ~0L, ximage->format, ximage, 0, 0)) + { + XDestroyImage (ximage); + ximage = 0; + } + + gl_settings_for_ximage (ximage, &type, &format, &swap); + glPixelStorei (GL_UNPACK_SWAP_BYTES, !swap); + } +#endif /* REFORMAT_IMAGE_DATA */ + + XFreePixmap (dpy, dd.pixmap); + dd.pixmap = 0; + + if (debug_p) + tex_time = double_time(); + + if (! ximage) + ok = False; + else + { + iw = ximage->width; + ih = ximage->height; + if (dd.texid != -1) + glBindTexture (GL_TEXTURE_2D, dd.texid); + + glPixelStorei (GL_UNPACK_ALIGNMENT, ximage->bitmap_pad / 8); + ok = ximage_to_texture (ximage, type, format, &tw, &th, geometry, + dd.mipmap_p); + if (ok) + { + iw = ximage->width; /* in case the image was shrunk */ + ih = ximage->height; + } + } + + if (ximage) XDestroyImage (ximage); + + if (! ok) + iw = ih = tw = th = 0; + + if (debug_p) + done_time = double_time(); + + if (debug_p) + fprintf (stderr, + /* prints: A + B + C = D + A = file I/O time (happens in background) + B = time to pull bits from server (this process) + C = time to convert bits to GL textures (this process) + D = total elapsed time from "want image" to "see image" + + B+C is responsible for any frame-rate glitches. + */ + "%s: loading elapsed: %.2f + %.2f + %.2f = %.2f sec\n", + progname, + cvt_time - dd.load_time, + tex_time - cvt_time, + done_time - tex_time, + done_time - dd.load_time); + + if (dd.callback) + /* asynchronous mode */ + dd.callback (name, geometry, iw, ih, tw, th, dd.closure); + else + { + /* synchronous mode */ + if (dd.filename_return) *dd.filename_return = (char *) name; + if (dd.geometry_return) *dd.geometry_return = *geometry; + if (dd.image_width_return) *dd.image_width_return = iw; + if (dd.image_height_return) *dd.image_height_return = ih; + if (dd.texture_width_return) *dd.texture_width_return = tw; + if (dd.texture_height_return) *dd.texture_height_return = th; + } +} diff --git a/hacks/glx/grab-ximage.h b/hacks/glx/grab-ximage.h new file mode 100644 index 00000000..2fd589f5 --- /dev/null +++ b/hacks/glx/grab-ximage.h @@ -0,0 +1,76 @@ +/* grab-ximage.c --- grab the screen to an XImage for use with OpenGL. + * xscreensaver, Copyright (c) 2001-2006 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. + */ + +#ifndef __GRAB_XIMAGE_H__ +#define __GRAB_XIMAGE_H__ + +/* Grabs an image of the desktop (or another random image file) and + loads the image into GL's texture memory. Most of the work is done + in the background; when the image has been loaded, a callback is run. + + As a side-effect, that image *may* be painted onto the given Window. + + If mipmap_p is true, then make mipmaps instead of just a single texture. + + If desired_width/height are non-zero, then (if possible) the image + will be scaled to fit in that rectangle. If they are 0, then the size + of the window is used. These parameters are so that you can hint to + the image loader that smaller images are acceptable (if you will never + be displaying the texture at 100% magnification, you can get away with + smaller textures.) + + Returns the sizes of various things: + + texture_width/height: The size of the texture itself, in pixels. + This will often be larger than the grabbed + image, since OpenGL sometimes requires texture + dimensions to be a power of 2. + + image_width/height: The size of the image: this will usually be the + same as the desired_width/height you passed in + (but may be the size of the Window instead.) + + geometry: The position in the texture of the image bits. + When image files are loaded, they are scaled up + to the size of the window, but if the image does + not have the same aspect ratio as the window, + there will be black bars on the top/bottom or + left/right. This geometry specification tells + you where the "real" image bits are. + + So, don't use texture coordinates from 0.0 to 1.0. Instead use: + + [0.0 - iw/tw] If you want to display a quad that is the same + [0.0 - ih/th] size as the window; or + + [gx/tw - (gx+gw)/tw] If you want to display a quad that is the same + [gy/th - (gy+gh)/th] size as the loaded image file. + + When the callback is called, the image data will have been loaded + into texture number `texid' (via glBindTexture.) + + If an error occurred, width/height will be 0. + */ +void load_texture_async (Screen *, Window, GLXContext, + int desired_width, int desired_height, + Bool mipmap_p, + GLuint texid, + void (*callback) (const char *filename, + XRectangle *geometry, + int image_width, + int image_height, + int texture_width, + int texture_height, + void *closure), + void *closure); + +#endif /* __GRAB_XIMAGE_H__ */ diff --git a/hacks/glx/hilbert.c b/hacks/glx/hilbert.c new file mode 100644 index 00000000..d8966f45 --- /dev/null +++ b/hacks/glx/hilbert.c @@ -0,0 +1,1150 @@ +/* hilbert, Copyright (c) 2011 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. + * + * 2D and 3D Hilbert space-filling curves. + * + * Inspired by "Visualizing Hilbert Curves" by Nelson Max, 1998: + * https://e-reports-ext.llnl.gov/pdf/234149.pdf + */ + +#define DEFAULTS "*delay: 30000 \n" \ + "*count: 30 \n" \ + "*showFPS: False \n" \ + "*wireframe: False \n" \ + "*geometry: 800x800\n" + +# define refresh_hilbert 0 +# define release_hilbert 0 +#undef countof +#define countof(x) (sizeof((x))/sizeof((*x))) + +#include "xlockmore.h" +#include "colors.h" +#include "sphere.h" +#include "tube.h" +#include "rotator.h" +#include "gltrackball.h" +#include + +#ifdef USE_GL /* whole file */ + + +#define DEF_SPIN "True" +#define DEF_WANDER "False" +#define DEF_SPEED "1.0" +#define DEF_MODE "random" +#define DEF_ENDS "random" +#define DEF_MAX_DEPTH "5" +#define DEF_THICKNESS "0.25" + +#define PAUSE_TICKS 180 + +typedef struct { + double x,y,z; +} XYZ; + +typedef struct { + unsigned short x,y,z; +} XYZb; + +typedef struct { + int size; + XYZb *values; /* assume max depth of 20 (2^16 on each side) */ +} hilbert_cache; + + +static int dlist_faces[] = { 20, 10, 8, 4, 3 }; + + +typedef struct { + GLXContext *glx_context; + rotator *rot, *rot2; + trackball_state *trackball; + Bool button_down_p; + Bool twodee_p; + Bool closed_p; + int ncolors; + XColor *colors; + + int depth; + int depth_tick; + + GLfloat path_start, path_end; + int path_tick; + int pause; + GLfloat diam; + + hilbert_cache **caches; /* filled lazily */ + + GLuint dlists [40][2]; /* we don't actually alloc all of these */ + int dlist_polys [40][2]; + +} hilbert_configuration; + +static hilbert_configuration *bps = NULL; + +static Bool do_spin; +static GLfloat speed; +static Bool do_wander; +static char *mode_str; +static char *ends_str; +static int max_depth; +static GLfloat thickness; + +static XrmOptionDescRec opts[] = { + { "-spin", ".spin", XrmoptionNoArg, "True" }, + { "+spin", ".spin", XrmoptionNoArg, "False" }, + { "-speed", ".speed", XrmoptionSepArg, 0 }, + { "-wander", ".wander", XrmoptionNoArg, "True" }, + { "+wander", ".wander", XrmoptionNoArg, "False" }, + { "-mode", ".mode", XrmoptionSepArg, 0 }, + { "-2d", ".mode", XrmoptionNoArg, "2D" }, + { "-3d", ".mode", XrmoptionNoArg, "3D" }, + { "-ends", ".ends", XrmoptionSepArg, 0 }, + { "-closed", ".ends", XrmoptionNoArg, "closed" }, + { "-open", ".ends", XrmoptionNoArg, "open" }, + { "-max-depth", ".maxDepth", XrmoptionSepArg, 0 }, + { "-thickness", ".thickness",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}, + {&mode_str, "mode", "Mode", DEF_MODE, t_String}, + {&ends_str, "ends", "Ends", DEF_ENDS, t_String}, + {&max_depth, "maxDepth", "MaxDepth", DEF_MAX_DEPTH, t_Int}, + {&thickness, "thickness","Thickness",DEF_THICKNESS, t_Float}, +}; + +ENTRYPOINT ModeSpecOpt hilbert_opts = {countof(opts), opts, countof(vars), vars, NULL}; + + +/* 2D Hilbert, and closed-loop variant. + */ + +/* These arrays specify which bits of the T index contribute to the + X, Y and Z values. Higher order bits are defined recursively. + */ +static const int xbit2d[4] = { 0, 0, 1, 1 }; +static const int ybit2d[4] = { 0, 1, 1, 0 }; + +static const int xbit3d[8] = { 0,0,0,0,1,1,1,1 }; +static const int ybit3d[8] = { 0,1,1,0,0,1,1,0 }; +static const int zbit3d[8] = { 0,0,1,1,1,1,0,0 }; + +/* These matrixes encapsulate the necessary reflection and translation + of each 4 sub-squares or 8 sub-cubes. The r2d and r3d arrays are + the normal Hilbert descent, and the s2d and s3d arrays are the + modified curve used for only level 0 of a closed-form path. + */ + +static int r2d[4][2][2] = { + /* _ _ + | |..| | + :_ _: + _| |_ + + */ + {{ 0, 1}, + { 1, 0}}, + {{ 1, 0}, + { 0, 1}}, + {{ 1, 0}, + { 0, 1}}, + {{ 0,-1}, + {-1, 0}}, +}; + +static int s2d[4][2][2] = { + /* __ __ + | |..| | Used for outermost iteration only, in "closed" mode + : .. : + |__| |__| + + */ + {{-1, 0}, + { 0,-1}}, + {{ 1, 0}, + { 0, 1}}, + {{ 1, 0}, + { 0, 1}}, + {{-1, 0}, + { 0,-1}}, +}; + + +static int r3d[8][3][3] = { + /* + /| /| + / | / | + /__|____/ | + | | + / / + / / + */ + {{ 0, 1, 0}, + { 1, 0, 0}, + { 0, 0, 1}}, + {{ 0, 0, 1}, + { 0, 1, 0}, + { 1, 0, 0}}, + {{ 1, 0, 0}, + { 0, 1, 0}, + { 0, 0, 1}}, + {{ 0, 0,-1}, + {-1, 0, 0}, + { 0, 1, 0}}, + {{ 0, 0, 1}, + { 1, 0, 0}, + { 0, 1, 0}}, + {{ 1, 0, 0}, + { 0, 1, 0}, + { 0, 0, 1}}, + {{ 0, 0,-1}, + { 0, 1, 0}, + {-1, 0, 0}}, + {{ 0,-1, 0}, + {-1, 0, 0}, + { 0, 0, 1}}, +}; + + +static int s3d[8][3][3] = { + /* + /| /| Used for outermost iteration only, in "closed" mode + / | / | + /__|____/ | + | | + / / + /_______/ + */ + {{-1, 0, 0}, + { 0, 0,-1}, + { 0, 1, 0}}, + {{ 0, 0, 1}, + { 0, 1, 0}, + { 1, 0, 0}}, + {{ 1, 0, 0}, + { 0, 1, 0}, + { 0, 0, 1}}, + {{ 0, 0,-1}, + {-1, 0, 0}, + { 0, 1, 0}}, + {{ 0, 0, 1}, + { 1, 0, 0}, + { 0, 1, 0}}, + {{ 1, 0, 0}, + { 0, 1, 0}, + { 0, 0, 1}}, + {{ 0, 0,-1}, + { 0, 1, 0}, + {-1, 0, 0}}, + + {{-1, 0, 0}, + { 0, 0,-1}, + { 0, 1, 0}}, +}; + + + +/* Matrix utilities + */ + +static void +matrix_times_vector2d (int m[2][2], int v[2], int dest[2]) +{ + dest[0] = m[0][0]*v[0] + m[0][1]*v[1]; + dest[1] = m[1][0]*v[0] + m[1][1]*v[1]; +} + +static void +matrix_times_vector3d (int m[3][3], int v[3], int dest[3]) +{ + dest[0] = m[0][0]*v[0] + m[0][1]*v[1] + m[0][2]*v[2]; + dest[1] = m[1][0]*v[0] + m[1][1]*v[1] + m[1][2]*v[2]; + dest[2] = m[2][0]*v[0] + m[2][1]*v[1] + m[2][2]*v[2]; +} + + +static void +matrix_multiply2d (int m1[2][2], int m2[2][2], int dest[2][2]) +{ + dest[0][0] = m1[0][0] * m2[0][0] + m1[0][1] * m2[1][0]; + dest[0][1] = m1[0][0] * m2[0][1] + m1[0][1] * m2[1][1]; + dest[1][0] = m1[1][0] * m2[0][0] + m1[1][1] * m2[1][0]; + dest[1][1] = m1[1][0] * m2[0][1] + m1[1][1] * m2[1][1]; +} + +static void +matrix_multiply3d (int m1[3][3], int m2[3][3], int dest[3][3]) +{ + int i, j, k; + for (i = 0; i < 3; i++) + for (j = 0; j < 3; j++) + { + dest[i][j] = 0; + for (k = 0; k < 3; k++) + dest[i][j] += m1[i][k] * m2[k][j]; + } +} + +static void +identity_matrix2d (int m[2][2]) +{ + m[0][0] = m[1][1] = 1; + m[0][1] = m[1][0] = 0; +} + +static void +identity_matrix3d (int m[3][3]) +{ + m[0][0] = m[1][1] = m[2][2] = 1; + m[0][1] = m[0][2] = m[1][0] = m[1][2] = m[2][0] = m[2][1] = 0; +} + + +static void +matrix_copy2d (int src[2][2], int dest[2][2]) +{ + int i, j; + for (i = 0; i < 2; i++) + for (j = 0; j < 2; j++) + dest[i][j] = src[i][j]; +} + + +static void +matrix_copy3d (int src[3][3], int dest[3][3]) +{ + int i, j; + for (i = 0; i < 3; i++) + for (j = 0; j < 3; j++) + dest[i][j] = src[i][j]; +} + + +/* 2D and 3D Hilbert: + Given an index T along the curve, return the XY or XYZ coordinates. + N is depth of the curve. + */ + +static void +t_to_xy (int n, int t, int *x, int *y, Bool closed_p) +{ + int k, rt[2][2], rq[2][2], va[2], vb[2]; + identity_matrix2d(rt); + *x = *y = 0; + + for (k = n-1; k >= 0; k--) + { + int j = 3 & (t >> (2*k)); + va[0] = 2 * xbit2d[j] - 1; + va[1] = 2 * ybit2d[j] - 1; + matrix_times_vector2d (rt, va, vb); + *x += ((vb[0] + 1) / 2) << k; + *y += ((vb[1] + 1) / 2) << k; + if (k > 0) + { + matrix_copy2d (rt, rq); + if (k == n-1 && closed_p) + matrix_multiply2d (rq, s2d[j], rt); + else + matrix_multiply2d (rq, r2d[j], rt); + } + } +} + + +static void +t_to_xyz (int n, int t, int *x, int *y, int *z, Bool closed_p) +{ + int k, rt[3][3], rq[3][3], va[3], vb[3]; + identity_matrix3d(rt); + *x = *y = *z = 0; + + for (k = n-1; k >= 0; k--) + { + int j = 7 & (t >> (3*k)); + va[0] = 2 * xbit3d[j] - 1; + va[1] = 2 * ybit3d[j] - 1; + va[2] = 2 * zbit3d[j] - 1; + matrix_times_vector3d (rt, va, vb); + *x += ((vb[0] + 1) / 2) << k; + *y += ((vb[1] + 1) / 2) << k; + *z += ((vb[2] + 1) / 2) << k; + if (k > 0) + { + matrix_copy3d (rt, rq); + if (k == n-1 && closed_p) + matrix_multiply3d (rq, s3d[j], rt); + else + matrix_multiply3d (rq, r3d[j], rt); + } + } +} + + +/* Rendering the curve + */ + + +/* Draw a sphere at the intersection of two tubes, to round off + the connection between them. Use one of our cache display lists + of unit spheres in various sizes. + */ +static int +draw_joint (ModeInfo *mi, XYZ p, GLfloat diam, int faces, int wire) +{ + hilbert_configuration *bp = &bps[MI_SCREEN(mi)]; + int i; + diam *= 0.99; /* try to clean up the edges a bit */ + + if (faces <= 4) return 0; /* too small to see */ + + glPushMatrix(); + glTranslatef (p.x, p.y, p.z); + glScalef (diam, diam, diam); + + /* i = unit_sphere (faces, faces, wire);*/ + + /* if (!bp->dlists[faces][0]) abort(); */ + /* if (!bp->dlist_polys[faces][0]) abort(); */ + + glCallList (bp->dlists[faces][0]); + i = bp->dlist_polys[faces][0]; + glPopMatrix(); + return i; +} + + +/* Draw a tube, and associated end caps. Use one of our cache display lists + of unit tubes in various sizes. Pick the resolution of the tube based + on how large it's being drawn. It's ok to get chunkier if the thing is + only a few pixels wide on the screen. + */ +static Bool +draw_segment (ModeInfo *mi, + XYZ p0, XYZ p1, /* from, to */ + int t, int end_t, /* value and range */ + GLfloat path_start, GLfloat path_end, /* clipping */ + Bool head_cap_p, + int *last_colorP) +{ + hilbert_configuration *bp = &bps[MI_SCREEN(mi)]; + + double t0 = (double) (t-1) / end_t; /* ratio of p[01] along curve */ + double t1 = (double) t / end_t; + + int wire = MI_IS_WIREFRAME(mi); + int owire = wire; + GLfloat dd = bp->diam; + int faces; + + if (path_start >= t1) /* whole segment is before clipping region */ + return False; + if (path_end < t0) /* whole segment is after clipping region */ + return False; + + + if (bp->twodee_p) dd *= 2; /* more polys in 2D mode */ + + faces = (dd > 0.040 ? dlist_faces[0] : + dd > 0.020 ? dlist_faces[1] : + dd > 0.010 ? dlist_faces[2] : + dd > 0.005 ? dlist_faces[3] : + dd > 0.002 ? dlist_faces[4] : + 1); + + /* In 2d mode, we can drop into wireframe mode and it still looks ok... */ + if (faces == 1) + { + if (bp->twodee_p) + wire = True; + else + faces = 3; + } + + if (wire && !owire) + { + glDisable (GL_DEPTH_TEST); + glDisable (GL_CULL_FACE); + glDisable (GL_LIGHTING); + } + + if (t0 < path_start) + { + XYZ p; + GLfloat seg_range = t1 - t0; + GLfloat clip_range = path_start - t0; + GLfloat ratio = clip_range / seg_range; + p.x = p0.x + ((p1.x - p0.x) * ratio); + p.y = p0.y + ((p1.y - p0.y) * ratio); + p.z = p0.z + ((p1.z - p0.z) * ratio); + p0 = p; + } + + if (t1 > path_end) + { + XYZ p; + GLfloat seg_range = t1 - t0; + GLfloat clip_range = path_end - t0; + GLfloat ratio = clip_range / seg_range; + p.x = p0.x + ((p1.x - p0.x) * ratio); + p.y = p0.y + ((p1.y - p0.y) * ratio); + p.z = p0.z + ((p1.z - p0.z) * ratio); + p1 = p; + } + + if (p0.x == p1.x && + p0.y == p1.y && + p0.z == p1.z) + return False; + + { + int segs = bp->ncolors * (t1 - t0); + int i; + XYZ p0b, p1b; + + if (segs < 1) segs = 1; + + for (i = 0; i < segs; i++) + { + int j = i + 1; + GLfloat color[4] = {0.0, 0.0, 0.0, 1.0}; + GLfloat t0b; + int c; + + p0b.x = p0.x + i * ((p1.x - p0.x) / segs); + p0b.y = p0.y + i * ((p1.y - p0.y) / segs); + p0b.z = p0.z + i * ((p1.z - p0.z) / segs); + + p1b.x = p0.x + j * ((p1.x - p0.x) / segs); + p1b.y = p0.y + j * ((p1.y - p0.y) / segs); + p1b.z = p0.z + j * ((p1.z - p0.z) / segs); + + + + /* #### this isn't quite right */ + t0b = t0 + i * (t1 - t0) / segs; + + c = bp->ncolors * t0b; + if (c >= bp->ncolors) c = bp->ncolors-1; + + /* Above depth 6, was spending 5% of the time in glMateralfv, + so only set the color if it's different. */ + + if (c != *last_colorP) + { + color[0] = bp->colors[c].red / 65536.0; + color[1] = bp->colors[c].green / 65536.0; + color[2] = bp->colors[c].blue / 65536.0; + if (wire) + glColor3fv (color); + else + glMaterialfv (GL_FRONT, GL_AMBIENT_AND_DIFFUSE, color); + *last_colorP = c; + } + + + if (wire) + { + glBegin (GL_LINES); + glVertex3f (p0b.x, p0b.y, p0b.z); + glVertex3f (p1b.x, p1b.y, p1b.z); + glEnd (); + mi->polygon_count++; + } + else + { + /* mi->polygon_count += tube (p0b.x, p0b.y, p0b.z, + p1b.x, p1b.y, p1b.z, + bp->diam, 0, faces, True, + 0, wire); + */ + + /* Render a rotated and scaled prefab unit tube. + + There's probably a slightly more concise way to do this, + but since they're all at right angles at least we don't + have to use atan(). + */ + GLfloat s; + glPushMatrix(); + glTranslatef (p0b.x, p0b.y, p0b.z); + + if (p1b.x > p0b.x) + { + s = p1b.x - p0b.x; + } + else if (p1b.x < p0b.x) + { + glRotatef (180, 0, 0, 1); + s = p0b.x - p1b.x; + } + else if (p1b.y > p0b.y) { + glRotatef (90, 0, 0, 1); + s = p1b.y - p0b.y; + } + else if (p1b.y < p0b.y) + { + glRotatef (-90, 0, 0, 1); + s = p0b.y - p1b.y; + } + else if (p1b.z > p0b.z) + { + glRotatef (-90, 0, 1, 0); + s = p1b.z - p0b.z; + } + else /* (p1b.z < p0b.z) */ + { + glRotatef (90, 0, 1, 0); + s = p0b.z - p1b.z; + } + + glScalef (s, bp->diam, bp->diam); + glCallList (bp->dlists[faces][1]); + mi->polygon_count += bp->dlist_polys[faces][1]; + glPopMatrix(); + + + /* If this is the bleeding edge, cap it too. */ + if (head_cap_p) { + mi->polygon_count += draw_joint (mi, p0b, bp->diam, faces, wire); + head_cap_p = False; + } + } + } + + /* If the path is closed, close it. This segment doesn't animate + like the others, but, oh well. + */ + if (! wire) + mi->polygon_count += draw_joint (mi, p1b, bp->diam, faces, wire); + } + + return True; +} + + +static void +mem(void) +{ + fprintf (stderr, "%s: out of memory\n", progname); + exit (1); +} + + +/* Render the whole thing, but omit segments that lie outside of + the path_start and path_end ratios. + */ +static void +hilbert (ModeInfo *mi, int size, GLfloat path_start, GLfloat path_end) +{ + hilbert_configuration *bp = &bps[MI_SCREEN(mi)]; + int wire = MI_IS_WIREFRAME(mi); + + GLfloat w = pow(2, size); + int end_t = (bp->twodee_p ? w * w : w * w * w); + + XYZ prev = { 0, }; + XYZ first = { 0, }; + Bool first_p = False; + Bool any_p = False; + int t; + Bool fill_cache_p = False; + hilbert_cache *cc; + int last_color = -1; + + /* Do this here since at higher resolutions, we turn wireframe on + and off. */ + + if (! wire) + { + glEnable (GL_NORMALIZE); + glEnable (GL_DEPTH_TEST); + glEnable (GL_CULL_FACE); + glEnable (GL_LIGHTING); + glEnable (GL_POLYGON_OFFSET_FILL); + } + + + if (!bp->caches) + { + bp->caches = (hilbert_cache **) + calloc (max_depth + 2, sizeof (*bp->caches)); + if (!bp->caches) mem(); + fill_cache_p = True; + } + + cc = bp->caches[size]; + if (! cc) + { + cc = (hilbert_cache *) calloc (1, sizeof (*cc)); + cc->values = (XYZb *) calloc (end_t + 1, sizeof (*cc->values)); + if (!cc->values) mem(); + cc->size = end_t; + bp->caches[size] = cc; + fill_cache_p = True; + } + + for (t = 0; t < end_t; t++) + { + int x, y, z; + XYZ c; + XYZb *cb; + + if (!fill_cache_p) + { + cb = &cc->values[t]; + x = cb->x; + y = cb->y; + z = cb->z; + } + else + { + if (!bp->twodee_p) + t_to_xyz (size, t, &x, &y, &z, bp->closed_p); + else + { + t_to_xy (size, t, &x, &y, bp->closed_p); + z = w/2; + } + cb = &cc->values[t]; + cb->x = x; + cb->y = y; + cb->z = z; + } + + c.x = (GLfloat) x / w - 0.5; + c.y = (GLfloat) y / w - 0.5; + c.z = (GLfloat) z / w - 0.5; + + /* #### We could save some polygons by not drawing the spheres + between colinear segments. */ + + if (t > 0) { + if (draw_segment (mi, prev, c, t, end_t, path_start, path_end, !any_p, + &last_color)) + any_p = True; + } + prev = c; + if (! first_p) { + first = c; + first_p = True; + } + } + + if (bp->closed_p && path_end >= 1.0) { + draw_segment (mi, prev, first, t, end_t, path_start, path_end, !any_p, + &last_color); + } +} + + + +/* Window management, etc + */ +ENTRYPOINT void +reshape_hilbert (ModeInfo *mi, int width, int height) +{ + GLfloat h = (GLfloat) height / (GLfloat) width; + + glViewport (0, 0, (GLint) width, (GLint) height); + + glMatrixMode(GL_PROJECTION); + glLoadIdentity(); + gluPerspective (30.0, 1/h, 1.0, 100.0); + + glMatrixMode(GL_MODELVIEW); + glLoadIdentity(); + gluLookAt( 0.0, 0.0, 30.0, + 0.0, 0.0, 0.0, + 0.0, 1.0, 0.0); + + glClear(GL_COLOR_BUFFER_BIT); +} + + +ENTRYPOINT Bool +hilbert_handle_event (ModeInfo *mi, XEvent *event) +{ + hilbert_configuration *bp = &bps[MI_SCREEN(mi)]; + + if (event->xany.type == ButtonPress && + event->xbutton.button == Button1) + { + bp->button_down_p = True; + gltrackball_start (bp->trackball, + event->xbutton.x, event->xbutton.y, + MI_WIDTH (mi), MI_HEIGHT (mi)); + return True; + } + else if (event->xany.type == ButtonRelease && + event->xbutton.button == Button1) + { + bp->button_down_p = False; + return True; + } + else if (event->xany.type == ButtonPress && + (event->xbutton.button == Button4 || + event->xbutton.button == Button5 || + event->xbutton.button == Button6 || + event->xbutton.button == Button7)) + { + gltrackball_mousewheel (bp->trackball, event->xbutton.button, 10, + !!event->xbutton.state); + return True; + } + else if (event->xany.type == MotionNotify && + bp->button_down_p) + { + gltrackball_track (bp->trackball, + event->xmotion.x, event->xmotion.y, + MI_WIDTH (mi), MI_HEIGHT (mi)); + return True; + } + else if (event->xany.type == KeyPress) + { + KeySym keysym; + char c = 0; + XLookupString (&event->xkey, &c, 1, &keysym, 0); + if (c == '+' || c == '=') + { + bp->depth++; + if (bp->depth > max_depth) bp->depth = max_depth; + return True; + } + else if (c == '-' || c == '_') + { + bp->depth--; + if (bp->depth < 1) bp->depth = 1; + return True; + } + } + + return False; +} + + +ENTRYPOINT void +init_hilbert (ModeInfo *mi) +{ + hilbert_configuration *bp; + int wire = MI_IS_WIREFRAME(mi); + int i; + + if (!bps) { + bps = (hilbert_configuration *) + calloc (MI_NUM_SCREENS(mi), sizeof (hilbert_configuration)); + if (!bps) { + fprintf(stderr, "%s: out of memory\n", progname); + exit(1); + } + } + + bp = &bps[MI_SCREEN(mi)]; + + bp->depth = 2; + bp->depth_tick = 1; + bp->path_start = 0.0; + bp->path_end = 0.0; + bp->path_tick = 1; + + if (thickness < 0.01) thickness = 0.01; + if (thickness > 1.0) thickness = 1.0; + + if (speed <= 0) speed = 0.0001; + if (max_depth < 2) max_depth = 2; + if (max_depth > 20) max_depth = 20; /* hard limit due to hilbert_cache */ + + if (bp->depth > max_depth-1) bp->depth = max_depth-1; + + bp->glx_context = init_GL(mi); + + reshape_hilbert (mi, MI_WIDTH(mi), MI_HEIGHT(mi)); + + if (!wire) + { + GLfloat pos[4] = {1.0, 1.0, 1.0, 0.0}; + GLfloat amb[4] = {0.0, 0.0, 0.0, 1.0}; + GLfloat dif[4] = {1.0, 1.0, 1.0, 1.0}; + GLfloat spc[4] = {0.0, 1.0, 1.0, 1.0}; + + 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); + } + + { + double spin_speed = 0.04; + double tilt_speed = spin_speed / 10; + double wander_speed = 0.008; + double spin_accel = 0.01; + + bp->rot = make_rotator (do_spin ? spin_speed : 0, + do_spin ? spin_speed : 0, + do_spin ? spin_speed : 0, + spin_accel, + do_wander ? wander_speed : 0, + do_spin); + bp->rot2 = make_rotator (0, 0, 0, 0, tilt_speed, True); + bp->trackball = gltrackball_init (); + } + + if (mode_str && !strcasecmp(mode_str, "2d")) + bp->twodee_p = True; + else if (mode_str && (!strcasecmp(mode_str, "3d"))) + bp->twodee_p = False; + else + { + if (! (mode_str && !strcasecmp(mode_str, "random"))) + fprintf (stderr, "%s: 'mode' must be '2d', '3d', or 'random'\n", + progname); + bp->twodee_p = ((random() % 3) == 0); + } + + + if (ends_str && (!strcasecmp(ends_str, "closed"))) + bp->closed_p = True; + else if (ends_str && (!strcasecmp(ends_str, "open"))) + bp->closed_p = False; + else + { + if (! (ends_str && !strcasecmp(ends_str, "random"))) + fprintf (stderr, "%s: 'ends' must be 'open', 'closed', or 'random'\n", + progname); + bp->closed_p = ((random() % 3) != 0); + } + + + /* More colors results in more polygons (more tube segments) so keeping + this small is worthwhile. */ + bp->ncolors = (bp->twodee_p ? 1024 : 128); + + if (bp->closed_p) + { + /* Since the path is closed, colors must also be a closed loop */ + bp->colors = (XColor *) calloc(bp->ncolors, sizeof(XColor)); + make_smooth_colormap (0, 0, 0, + bp->colors, &bp->ncolors, + False, 0, False); + } + else + { + /* Since the path is open, first and last colors should differ. */ + bp->ncolors *= 2; + bp->colors = (XColor *) calloc(bp->ncolors, sizeof(XColor)); + make_uniform_colormap (0, 0, 0, + bp->colors, &bp->ncolors, + False, 0, False); + bp->ncolors /= 2; + } + + /* Generate display lists for several different resolutions of + a unit tube and a unit sphere. + */ + for (i = 0; i < countof(dlist_faces); i++) + { + int faces = dlist_faces[i]; + bp->dlists[faces][0] = glGenLists (1); + + glNewList (bp->dlists[faces][0], GL_COMPILE); + bp->dlist_polys[faces][0] = unit_sphere (faces, faces, wire); + glEndList (); + + bp->dlists[faces][1] = glGenLists (1); + + glNewList (bp->dlists[faces][1], GL_COMPILE); + bp->dlist_polys[faces][1] = + tube (0, 0, 0, 1, 0, 0, + 1, 0, faces, True, 0, wire); + glEndList (); + } +} + + +ENTRYPOINT void +draw_hilbert (ModeInfo *mi) +{ + hilbert_configuration *bp = &bps[MI_SCREEN(mi)]; + Display *dpy = MI_DISPLAY(mi); + Window window = MI_WINDOW(mi); + int wire = MI_IS_WIREFRAME(mi); + + static const GLfloat bspec[4] = {1.0, 1.0, 1.0, 1.0}; + static const GLfloat bshiny = 128.0; + GLfloat bcolor[4] = {1.0, 1.0, 1.0, 1.0}; + + if (!bp->glx_context) + return; + + glXMakeCurrent(MI_DISPLAY(mi), MI_WINDOW(mi), *(bp->glx_context)); + + glShadeModel(GL_SMOOTH); + + if (! wire) + { + glEnable (GL_NORMALIZE); + glEnable (GL_DEPTH_TEST); + glEnable (GL_CULL_FACE); + glEnable (GL_LIGHTING); + glEnable (GL_LIGHT0); + glEnable (GL_POLYGON_OFFSET_FILL); + } + + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + + glPushMatrix (); + + glScalef(1.1, 1.1, 1.1); + + { + double x, y, z, z2; + get_position (bp->rot, &x, &y, &z, !bp->button_down_p); + glTranslatef((x - 0.5) * 8, + (y - 0.5) * 8, + (z - 0.5) * 15); + + /* Do it twice because we don't track the device's orientation. */ + glRotatef( current_device_rotation(), 0, 0, 1); + gltrackball_rotate (bp->trackball); + glRotatef(-current_device_rotation(), 0, 0, 1); + + get_rotation (bp->rot, &x, &y, &z, !bp->button_down_p); + + if (bp->twodee_p && do_spin) /* face front */ + { + double max = 70; + get_position (bp->rot2, &x, &y, &z2, !bp->button_down_p); + glRotatef (max/2 - x*max, 1, 0, 0); + glRotatef (max/2 - y*max, 0, 1, 0); + glRotatef (z * 360, 0, 0, 1); /* but upside down is ok */ + } + else + { + glRotatef (x * 360, 1, 0, 0); + glRotatef (y * 360, 0, 1, 0); + glRotatef (z * 360, 0, 0, 1); + } + } + + mi->polygon_count = 0; + + glMaterialfv (GL_FRONT, GL_SPECULAR, bspec); + glMateriali (GL_FRONT, GL_SHININESS, bshiny); + glMaterialfv (GL_FRONT, GL_AMBIENT_AND_DIFFUSE, bcolor); + + glScalef (8,8,8); + glTranslatef (0.1, 0.1, 0); + + if (!do_spin && !bp->twodee_p) + { + /* tilt the cube a little, and make the start and end visible */ + glTranslatef (-0.1, 0, 0); + glRotatef (140, 0, 1, 0); + glRotatef (30, 1, 0, 0); + } + + if (wire) + glLineWidth (bp->depth > 4 ? 1.0 : + bp->depth > 3 ? 2.0 : + 3.0); + + if (bp->path_tick > 0) /* advancing the end point, [0 - N) */ + { /* drawing 1 partial path, 1st time only. */ + + if (!bp->button_down_p) + bp->path_end += 0.01 * speed; + + if (bp->path_end >= 1.0) + { + bp->path_start = 0.0; + bp->path_end = 1.0; + bp->path_tick = -1; + bp->pause = PAUSE_TICKS; + } + + bp->diam = thickness / pow (2, bp->depth); + hilbert (mi, bp->depth, bp->path_start, bp->path_end); + mi->recursion_depth = bp->depth + bp->path_start; + } + + else /* advancing the start point, (N - 1] */ + { /* drawing 2 paths at different rez. */ + if (bp->pause) + { + bp->pause--; + } + else + { + if (!bp->button_down_p) + bp->path_start += 0.01 * speed; + + if (bp->path_start > 1.0) + { + bp->path_start = 0.0; + bp->depth += bp->depth_tick; + bp->pause = PAUSE_TICKS; + if (bp->depth > max_depth-1) + { + bp->depth = max_depth; + bp->depth_tick = -1; + } + else if (bp->depth <= 1) + { + bp->depth = 1; + bp->depth_tick = 1; + } + } + } + + { + GLfloat d1 = thickness / pow (2, bp->depth); + GLfloat d2 = thickness / pow (2, bp->depth + bp->depth_tick); + bp->diam = (d1 * (1 - bp->path_start) + + d2 * bp->path_start); + } + + /* First time around, start is 0, and end animates forward. + Then, to display the next higher resolution, we render + depth=N while increasing start and leaving end=1.0; + and simultaneously animationg depth=N+1 with start=0 and + end increasing by the same amount. + + The two paths aren't actually connected together at the + resolution-change interface, and sometimes they overlap, + but things go fast enough that it's hard to spot those + glitches, so it looks ok. + */ + glPolygonOffset (0, 0); + hilbert (mi, bp->depth, bp->path_start, bp->path_end); + + glPolygonOffset (1.0, 1.0); + hilbert (mi, bp->depth + bp->depth_tick, 0.0, bp->path_start); + + mi->recursion_depth = bp->depth + (bp->depth_tick * bp->path_start); + } + + glPopMatrix (); + + if (mi->fps_p) do_fps (mi); + glFinish(); + + glXSwapBuffers(dpy, window); +} + +XSCREENSAVER_MODULE ("Hilbert", hilbert) + +#endif /* USE_GL */ diff --git a/hacks/glx/hilbert.man b/hacks/glx/hilbert.man new file mode 100644 index 00000000..8693dce6 --- /dev/null +++ b/hacks/glx/hilbert.man @@ -0,0 +1,103 @@ +.TH XScreenSaver 1 "" "X Version 11" +.SH NAME +hilbert - 3D Hilbert fractal. +.SH SYNOPSIS +.B hilbert +[\-display \fIhost:display.screen\fP] +[\-visual \fIvisual\fP] +[\-window] +[\-root] +[\-delay \fInumber\fP] +[\-speed \fIratio\fP] +[\-depth \fInumber\fP] +[\-spin] +[\-wander] +[\-2d] +[\-3d] +[\-closed] +[\-open] +[\-max\-depth \fInumber\fP] +[\-thickness \fIratio\fP] +[\-wireframe] +[\-fps] +.SH DESCRIPTION +This draws the recursive Hilbert space-filling curve, in both 2D and +3D variants. It incrementally animates the growth and recursion to +the maximum depth, then unwinds it back. + +The Hilbert path is a single contiguous line that can fill a volume +without crossing itself. As a data structure, Hilbert paths are +useful because ordering along the curve preserves locality: points +that close together along the curve are also close together in space. +The converse is often, but not always, true. The coloration +reflects this. +.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 \-speed \fInumber\fP +How fast the animation should run. +Less than 1 for slower, greater than 1 for faster. +.TP 8 +.B \-max\-depth \fInumber\fP +Max depth to descend. Default: 5, which peaks at around half a +million polygons. +.TP 8 +.B \-spin +.B \-no\-spin +Whether to rotate the object. Default: true. +.TP 8 +.B \-wander +.B \-no\-wander +Whether to wander the object around on the screen. Default: false; +.TP 8 +.B \-2d +.B \-3d +Whether to draw the 2D or 3D variant. Default: random. +.TP 8 +.B \-closed +.B \-open +Whether to draw the open or closed-path variant. Default: random. +.TP 8 +.B \-thickness \fIratio\fP +How thick the lines should be. Default: 0.25. +.TP 8 +.B \-wireframe +Render in wireframe instead of solid. +.TP 8 +.B \-fps +Display the current frame rate, CPU load, and polygon count. +.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 2011 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/glx/hypertorus.c b/hacks/glx/hypertorus.c new file mode 100644 index 00000000..908f612e --- /dev/null +++ b/hacks/glx/hypertorus.c @@ -0,0 +1,1031 @@ +/* hypertorus --- Shows a hypertorus that rotates in 4d */ + +#if 0 +static const char sccsid[] = "@(#)hypertorus.c 1.2 05/09/28 xlockmore"; +#endif + +/* Copyright (c) 2003-2009 Carsten Steger . */ + +/* + * Permission to use, copy, modify, and distribute this software and its + * documentation for any purpose and without fee is hereby granted, + * provided that the above copyright notice appear in all copies and that + * both that copyright notice and this permission notice appear in + * supporting documentation. + * + * This file is provided AS IS with no warranties of any kind. The author + * shall have no liability with respect to the infringement of copyrights, + * trade secrets or any patents by this file or any part thereof. In no + * event will the author be liable for any lost revenue or profits or + * other special, indirect and consequential damages. + * + * REVISION HISTORY: + * C. Steger - 03/05/18: Initial version + * C. Steger - 05/09/28: Added the spirals appearance mode + * and trackball support + * C. Steger - 07/01/23: Improved 4d trackball support + * C. Steger - 09/08/22: Removed check-config.pl warnings + */ + +/* + * This program shows the Clifford torus as it rotates in 4d. The Clifford + * torus is a torus lies on the "surface" of the hypersphere in 4d. The + * program projects the 4d torus to 3d using either a perspective or an + * orthographic projection. Of the two alternatives, the perspecitve + * projection looks much more appealing. In orthographic projections the + * torus degenerates into a doubly covered cylinder for some angles. The + * projected 3d torus can then be projected to the screen either perspectively + * or orthographically. There are three display modes for the torus: mesh + * (wireframe), solid, or transparent. Furthermore, the appearance of the + * torus can be as a solid object or as a set of see-through bands or + * see-through spirals. Finally, the colors with with the torus is drawn can + * be set to either two-sided or to colorwheel. In the first case, the torus + * is drawn with red on the outside and green on the inside. This mode + * enables you to see that the torus turns inside-out as it rotates in 4d. + * The second mode draws the torus in a fully saturated color wheel. This + * gives a very nice effect when combined with the see-through bands or + * see-through spirals mode. The rotation speed for each of the six planes + * around which the torus rotates can be chosen. This program is very much + * inspired by Thomas Banchoff's book "Beyond the Third Dimension: Geometry, + * Computer Graphics, and Higher Dimensions", Scientific American Library, + * 1990. + */ + +#ifndef M_PI +#define M_PI 3.14159265358979323846 +#endif + +#define DISP_WIREFRAME 0 +#define DISP_SURFACE 1 +#define DISP_TRANSPARENT 2 + +#define APPEARANCE_SOLID 0 +#define APPEARANCE_BANDS 1 +#define APPEARANCE_SPIRALS 2 + +#define COLORS_TWOSIDED 0 +#define COLORS_COLORWHEEL 1 + +#define DISP_3D_PERSPECTIVE 0 +#define DISP_3D_ORTHOGRAPHIC 1 + +#define DISP_4D_PERSPECTIVE 0 +#define DISP_4D_ORTHOGRAPHIC 1 + +#define DEF_DISPLAY_MODE "surface" +#define DEF_APPEARANCE "bands" +#define DEF_COLORS "colorwheel" +#define DEF_PROJECTION_3D "perspective" +#define DEF_PROJECTION_4D "perspective" +#define DEF_SPEEDWX "1.1" +#define DEF_SPEEDWY "1.3" +#define DEF_SPEEDWZ "1.5" +#define DEF_SPEEDXY "1.7" +#define DEF_SPEEDXZ "1.9" +#define DEF_SPEEDYZ "2.1" + +#ifdef STANDALONE +# define DEFAULTS "*delay: 25000 \n" \ + "*showFPS: False \n" \ + +# define refresh_hypertorus 0 +# include "xlockmore.h" /* from the xscreensaver distribution */ +#else /* !STANDALONE */ +# include "xlock.h" /* from the xlockmore distribution */ +#endif /* !STANDALONE */ + +#ifdef USE_GL +#ifndef HAVE_COCOA +# include +#endif + +#include "gltrackball.h" + + +#ifdef USE_MODULES +ModStruct hypertorus_description = +{"hypertorus", "init_hypertorus", "draw_hypertorus", "release_hypertorus", + "draw_hypertorus", "change_hypertorus", NULL, &hypertorus_opts, + 25000, 1, 1, 1, 1.0, 4, "", + "Shows a hypertorus rotating in 4d", 0, NULL}; + +#endif + + +static char *mode; +static int display_mode; +static char *appear; +static int appearance; +static int num_spirals; +static char *color_mode; +static int colors; +static char *proj_3d; +static int projection_3d; +static char *proj_4d; +static int projection_4d; +static float speed_wx; +static float speed_wy; +static float speed_wz; +static float speed_xy; +static float speed_xz; +static float speed_yz; + +static const float offset4d[4] = { 0.0, 0.0, 0.0, 2.0 }; +static const float offset3d[4] = { 0.0, 0.0, -2.0, 0.0 }; + + +static XrmOptionDescRec opts[] = +{ + {"-mode", ".displayMode", XrmoptionSepArg, 0 }, + {"-wireframe", ".displayMode", XrmoptionNoArg, "wireframe" }, + {"-surface", ".displayMode", XrmoptionNoArg, "surface" }, + {"-transparent", ".displayMode", XrmoptionNoArg, "transparent" }, + {"-appearance", ".appearance", XrmoptionSepArg, 0 }, + {"-solid", ".appearance", XrmoptionNoArg, "solid" }, + {"-bands", ".appearance", XrmoptionNoArg, "bands" }, + {"-spirals-1", ".appearance", XrmoptionNoArg, "spirals-1" }, + {"-spirals-2", ".appearance", XrmoptionNoArg, "spirals-2" }, + {"-spirals-4", ".appearance", XrmoptionNoArg, "spirals-4" }, + {"-spirals-8", ".appearance", XrmoptionNoArg, "spirals-8" }, + {"-spirals-16", ".appearance", XrmoptionNoArg, "spirals-16" }, + {"-twosided", ".colors", XrmoptionNoArg, "twosided" }, + {"-colorwheel", ".colors", XrmoptionNoArg, "colorwheel" }, + {"-perspective-3d", ".projection3d", XrmoptionNoArg, "perspective" }, + {"-orthographic-3d", ".projection3d", XrmoptionNoArg, "orthographic" }, + {"-perspective-4d", ".projection4d", XrmoptionNoArg, "perspective" }, + {"-orthographic-4d", ".projection4d", XrmoptionNoArg, "orthographic" }, + {"-speed-wx", ".speedwx", XrmoptionSepArg, 0 }, + {"-speed-wy", ".speedwy", XrmoptionSepArg, 0 }, + {"-speed-wz", ".speedwz", XrmoptionSepArg, 0 }, + {"-speed-xy", ".speedxy", XrmoptionSepArg, 0 }, + {"-speed-xz", ".speedxz", XrmoptionSepArg, 0 }, + {"-speed-yz", ".speedyz", XrmoptionSepArg, 0 } +}; + +static argtype vars[] = +{ + { &mode, "displayMode", "DisplayMode", DEF_DISPLAY_MODE, t_String }, + { &appear, "appearance", "Appearance", DEF_APPEARANCE, t_String }, + { &color_mode, "colors", "Colors", DEF_COLORS, t_String }, + { &proj_3d, "projection3d", "Projection3d", DEF_PROJECTION_3D, t_String }, + { &proj_4d, "projection4d", "Projection4d", DEF_PROJECTION_4D, t_String }, + { &speed_wx, "speedwx", "Speedwx", DEF_SPEEDWX, t_Float}, + { &speed_wy, "speedwy", "Speedwy", DEF_SPEEDWY, t_Float}, + { &speed_wz, "speedwz", "Speedwz", DEF_SPEEDWZ, t_Float}, + { &speed_xy, "speedxy", "Speedxy", DEF_SPEEDXY, t_Float}, + { &speed_xz, "speedxz", "Speedxz", DEF_SPEEDXZ, t_Float}, + { &speed_yz, "speedyz", "Speedyz", DEF_SPEEDYZ, t_Float} +}; + +static OptionStruct desc[] = +{ + { "-wireframe", "display the torus as a wireframe mesh" }, + { "-surface", "display the torus as a solid surface" }, + { "-transparent", "display the torus as a transparent surface" }, + { "-solid", "display the torus as a solid object" }, + { "-bands", "display the torus as see-through bands" }, + { "-spirals-{1,2,4,8,16}", "display the torus as see-through spirals" }, + { "-twosided", "display the torus with two colors" }, + { "-colorwheel", "display the torus with a smooth color wheel" }, + { "-perspective-3d", "project the torus perspectively from 3d to 2d" }, + { "-orthographic-3d", "project the torus orthographically from 3d to 2d" }, + { "-perspective-4d", "project the torus perspectively from 4d to 3d" }, + { "-orthographic-4d", "project the torus orthographically from 4d to 3d" }, + { "-speed-wx ", "rotation speed around the wx plane" }, + { "-speed-wy ", "rotation speed around the wy plane" }, + { "-speed-wz ", "rotation speed around the wz plane" }, + { "-speed-xy ", "rotation speed around the xy plane" }, + { "-speed-xz ", "rotation speed around the xz plane" }, + { "-speed-yz ", "rotation speed around the yz plane" } +}; + +ENTRYPOINT ModeSpecOpt hypertorus_opts = +{sizeof opts / sizeof opts[0], opts, sizeof vars / sizeof vars[0], vars, desc}; + + +typedef struct { + GLint WindH, WindW; + GLXContext *glx_context; + /* 4D rotation angles */ + float alpha, beta, delta, zeta, eta, theta; + /* Aspect ratio of the current window */ + float aspect; + /* Trackball states */ + trackball_state *trackballs[2]; + int current_trackball; + Bool button_pressed; + + float speed_scale; + +} hypertorusstruct; + +static hypertorusstruct *hyper = (hypertorusstruct *) NULL; + + +/* Add a rotation around the wx-plane to the matrix m. */ +static void rotatewx(float m[4][4], float phi) +{ + float c, s, u, v; + int i; + + phi *= M_PI/180.0; + c = cos(phi); + s = sin(phi); + for (i=0; i<4; i++) + { + u = m[i][1]; + v = m[i][2]; + m[i][1] = c*u+s*v; + m[i][2] = -s*u+c*v; + } +} + + +/* Add a rotation around the wy-plane to the matrix m. */ +static void rotatewy(float m[4][4], float phi) +{ + float c, s, u, v; + int i; + + phi *= M_PI/180.0; + c = cos(phi); + s = sin(phi); + for (i=0; i<4; i++) + { + u = m[i][0]; + v = m[i][2]; + m[i][0] = c*u-s*v; + m[i][2] = s*u+c*v; + } +} + + +/* Add a rotation around the wz-plane to the matrix m. */ +static void rotatewz(float m[4][4], float phi) +{ + float c, s, u, v; + int i; + + phi *= M_PI/180.0; + c = cos(phi); + s = sin(phi); + for (i=0; i<4; i++) + { + u = m[i][0]; + v = m[i][1]; + m[i][0] = c*u+s*v; + m[i][1] = -s*u+c*v; + } +} + + +/* Add a rotation around the xy-plane to the matrix m. */ +static void rotatexy(float m[4][4], float phi) +{ + float c, s, u, v; + int i; + + phi *= M_PI/180.0; + c = cos(phi); + s = sin(phi); + for (i=0; i<4; i++) + { + u = m[i][2]; + v = m[i][3]; + m[i][2] = c*u+s*v; + m[i][3] = -s*u+c*v; + } +} + + +/* Add a rotation around the xz-plane to the matrix m. */ +static void rotatexz(float m[4][4], float phi) +{ + float c, s, u, v; + int i; + + phi *= M_PI/180.0; + c = cos(phi); + s = sin(phi); + for (i=0; i<4; i++) + { + u = m[i][1]; + v = m[i][3]; + m[i][1] = c*u-s*v; + m[i][3] = s*u+c*v; + } +} + + +/* Add a rotation around the yz-plane to the matrix m. */ +static void rotateyz(float m[4][4], float phi) +{ + float c, s, u, v; + int i; + + phi *= M_PI/180.0; + c = cos(phi); + s = sin(phi); + for (i=0; i<4; i++) + { + u = m[i][0]; + v = m[i][3]; + m[i][0] = c*u-s*v; + m[i][3] = s*u+c*v; + } +} + + +/* Compute the rotation matrix m from the rotation angles. */ +static void rotateall(float al, float be, float de, float ze, float et, + float th, float m[4][4]) +{ + int i, j; + + for (i=0; i<4; i++) + for (j=0; j<4; j++) + m[i][j] = (i==j); + rotatewx(m,al); + rotatewy(m,be); + rotatewz(m,de); + rotatexz(m,et); + rotatexy(m,ze); + rotateyz(m,th); +} + + +/* Multiply two rotation matrices: o=m*n. */ +static void mult_rotmat(float m[4][4], float n[4][4], float o[4][4]) +{ + int i, j, k; + + for (i=0; i<4; i++) + { + for (j=0; j<4; j++) + { + o[i][j] = 0.0; + for (k=0; k<4; k++) + o[i][j] += m[i][k]*n[k][j]; + } + } +} + + +/* Compute a 4D rotation matrix from two unit quaternions. */ +static void quats_to_rotmat(float p[4], float q[4], float m[4][4]) +{ + double al, be, de, ze, et, th; + double r00, r01, r02, r12, r22; + + r00 = 1.0-2.0*(p[1]*p[1]+p[2]*p[2]); + r01 = 2.0*(p[0]*p[1]+p[2]*p[3]); + r02 = 2.0*(p[2]*p[0]-p[1]*p[3]); + r12 = 2.0*(p[1]*p[2]+p[0]*p[3]); + r22 = 1.0-2.0*(p[1]*p[1]+p[0]*p[0]); + + al = atan2(-r12,r22)*180.0/M_PI; + be = atan2(r02,sqrt(r00*r00+r01*r01))*180.0/M_PI; + de = atan2(-r01,r00)*180.0/M_PI; + + r00 = 1.0-2.0*(q[1]*q[1]+q[2]*q[2]); + r01 = 2.0*(q[0]*q[1]+q[2]*q[3]); + r02 = 2.0*(q[2]*q[0]-q[1]*q[3]); + r12 = 2.0*(q[1]*q[2]+q[0]*q[3]); + r22 = 1.0-2.0*(q[1]*q[1]+q[0]*q[0]); + + et = atan2(-r12,r22)*180.0/M_PI; + th = atan2(r02,sqrt(r00*r00+r01*r01))*180.0/M_PI; + ze = atan2(-r01,r00)*180.0/M_PI; + + rotateall(al,be,de,ze,et,-th,m); +} + + +/* Compute a fully saturated and bright color based on an angle. */ +static void color(double angle) +{ + int s; + double t; + float color[4]; + + if (colors != COLORS_COLORWHEEL) + return; + + if (angle >= 0.0) + angle = fmod(angle,2*M_PI); + else + angle = fmod(angle,-2*M_PI); + s = floor(angle/(M_PI/3)); + t = angle/(M_PI/3)-s; + if (s >= 6) + s = 0; + switch (s) + { + case 0: + color[0] = 1.0; + color[1] = t; + color[2] = 0.0; + break; + case 1: + color[0] = 1.0-t; + color[1] = 1.0; + color[2] = 0.0; + break; + case 2: + color[0] = 0.0; + color[1] = 1.0; + color[2] = t; + break; + case 3: + color[0] = 0.0; + color[1] = 1.0-t; + color[2] = 1.0; + break; + case 4: + color[0] = t; + color[1] = 0.0; + color[2] = 1.0; + break; + case 5: + color[0] = 1.0; + color[1] = 0.0; + color[2] = 1.0-t; + break; + } + if (display_mode == DISP_TRANSPARENT) + color[3] = 0.7; + else + color[3] = 1.0; + glColor3fv(color); + glMaterialfv(GL_FRONT_AND_BACK,GL_AMBIENT_AND_DIFFUSE,color); +} + + +/* Draw a hypertorus projected into 3D. Note that the spirals appearance + will only work correctly if numu and numv are set to 64 or any higher + power of 2. Similarly, the banded appearance will only work correctly + if numu and numv are divisible by 4. */ +static int hypertorus(ModeInfo *mi, double umin, double umax, double vmin, + double vmax, int numu, int numv) +{ + int polys = 0; + static const GLfloat mat_diff_red[] = { 1.0, 0.0, 0.0, 1.0 }; + static const GLfloat mat_diff_green[] = { 0.0, 1.0, 0.0, 1.0 }; + static const GLfloat mat_diff_trans_red[] = { 1.0, 0.0, 0.0, 0.7 }; + static const GLfloat mat_diff_trans_green[] = { 0.0, 1.0, 0.0, 0.7 }; + float p[3], pu[3], pv[3], n[3], mat[4][4]; + int i, j, k, l, m, b, skew; + double u, v, ur, vr; + double cu, su, cv, sv; + double xx[4], xxu[4], xxv[4], x[4], xu[4], xv[4]; + double r, s, t; + float q1[4], q2[4], r1[4][4], r2[4][4]; + hypertorusstruct *hp = &hyper[MI_SCREEN(mi)]; + + rotateall(hp->alpha,hp->beta,hp->delta,hp->zeta,hp->eta,hp->theta,r1); + + gltrackball_get_quaternion(hp->trackballs[0],q1); + gltrackball_get_quaternion(hp->trackballs[1],q2); + quats_to_rotmat(q1,q2,r2); + + mult_rotmat(r2,r1,mat); + + if (colors != COLORS_COLORWHEEL) + { + glColor3fv(mat_diff_red); + if (display_mode == DISP_TRANSPARENT) + { + glMaterialfv(GL_FRONT,GL_AMBIENT_AND_DIFFUSE,mat_diff_trans_red); + glMaterialfv(GL_BACK,GL_AMBIENT_AND_DIFFUSE,mat_diff_trans_green); + } + else + { + glMaterialfv(GL_FRONT,GL_AMBIENT_AND_DIFFUSE,mat_diff_red); + glMaterialfv(GL_BACK,GL_AMBIENT_AND_DIFFUSE,mat_diff_green); + } + } + + skew = num_spirals; + ur = umax-umin; + vr = vmax-vmin; + for (i=0; i= 2)) + continue; + if (display_mode == DISP_WIREFRAME) + glBegin(GL_QUAD_STRIP); + else + glBegin(GL_TRIANGLE_STRIP); + for (j=0; j<=numv; j++) + { + for (k=0; k<=1; k++) + { + l = (i+k); + m = j; + u = ur*l/numu+umin; + v = vr*m/numv+vmin; + if (appearance == APPEARANCE_SPIRALS) + { + u += 4.0*skew/numv*v; + b = ((i/4)&(skew-1))*(numu/(4*skew)); + color(ur*4*b/numu+umin); + } + else + { + color(u); + } + cu = cos(u); + su = sin(u); + cv = cos(v); + sv = sin(v); + xx[0] = cu; + xx[1] = su; + xx[2] = cv; + xx[3] = sv; + xxu[0] = -su; + xxu[1] = cu; + xxu[2] = 0.0; + xxu[3] = 0.0; + xxv[0] = 0.0; + xxv[1] = 0.0; + xxv[2] = -sv; + xxv[3] = cv; + for (l=0; l<4; l++) + { + r = 0.0; + s = 0.0; + t = 0.0; + for (m=0; m<4; m++) + { + r += mat[l][m]*xx[m]; + s += mat[l][m]*xxu[m]; + t += mat[l][m]*xxv[m]; + } + x[l] = r; + xu[l] = s; + xv[l] = t; + } + if (projection_4d == DISP_4D_ORTHOGRAPHIC) + { + for (l=0; l<3; l++) + { + p[l] = (x[l]+offset4d[l])/1.5+offset3d[l]; + pu[l] = xu[l]; + pv[l] = xv[l]; + } + } + else + { + s = x[3]+offset4d[3]; + t = s*s; + for (l=0; l<3; l++) + { + r = x[l]+offset4d[l]; + p[l] = r/s+offset3d[l]; + pu[l] = (xu[l]*s-r*xu[3])/t; + pv[l] = (xv[l]*s-r*xv[3])/t; + } + } + n[0] = pu[1]*pv[2]-pu[2]*pv[1]; + n[1] = pu[2]*pv[0]-pu[0]*pv[2]; + n[2] = pu[0]*pv[1]-pu[1]*pv[0]; + t = sqrt(n[0]*n[0]+n[1]*n[1]+n[2]*n[2]); + n[0] /= t; + n[1] /= t; + n[2] /= t; + glNormal3fv(n); + glVertex3fv(p); + polys++; + } + } + glEnd(); + } + polys /= 2; + return polys; +} + + +static void init(ModeInfo *mi) +{ + static const GLfloat light_ambient[] = { 0.0, 0.0, 0.0, 1.0 }; + static const GLfloat light_diffuse[] = { 1.0, 1.0, 1.0, 1.0 }; + static const GLfloat light_specular[] = { 1.0, 1.0, 1.0, 1.0 }; + static const GLfloat light_position[] = { 1.0, 1.0, 1.0, 0.0 }; + static const GLfloat mat_specular[] = { 1.0, 1.0, 1.0, 1.0 }; + hypertorusstruct *hp = &hyper[MI_SCREEN(mi)]; + + hp->alpha = 0.0; + hp->beta = 0.0; + hp->delta = 0.0; + hp->zeta = 0.0; + hp->eta = 0.0; + hp->theta = 0.0; + + glMatrixMode(GL_PROJECTION); + glLoadIdentity(); + if (projection_3d == DISP_3D_PERSPECTIVE) + gluPerspective(60.0,1.0,0.1,100.0); + else + glOrtho(-1.0,1.0,-1.0,1.0,0.1,100.0);; + glMatrixMode(GL_MODELVIEW); + glLoadIdentity(); + +# ifdef HAVE_JWZGLES /* #### glPolygonMode other than GL_FILL unimplemented */ + if (display_mode == DISP_WIREFRAME) + display_mode = DISP_SURFACE; +# endif + + if (display_mode == DISP_SURFACE) + { + glEnable(GL_DEPTH_TEST); + glDepthFunc(GL_LESS); + glShadeModel(GL_SMOOTH); + glPolygonMode(GL_FRONT_AND_BACK,GL_FILL); + glLightModeli(GL_LIGHT_MODEL_TWO_SIDE,GL_TRUE); + glEnable(GL_LIGHTING); + glEnable(GL_LIGHT0); + glLightfv(GL_LIGHT0,GL_AMBIENT,light_ambient); + glLightfv(GL_LIGHT0,GL_DIFFUSE,light_diffuse); + glLightfv(GL_LIGHT0,GL_SPECULAR,light_specular); + glLightfv(GL_LIGHT0,GL_POSITION,light_position); + glMaterialfv(GL_FRONT_AND_BACK,GL_SPECULAR,mat_specular); + glMaterialf(GL_FRONT_AND_BACK,GL_SHININESS,50.0); + glDepthMask(GL_TRUE); + glDisable(GL_BLEND); + } + else if (display_mode == DISP_TRANSPARENT) + { + glDisable(GL_DEPTH_TEST); + glShadeModel(GL_SMOOTH); + glPolygonMode(GL_FRONT_AND_BACK,GL_FILL); + glLightModeli(GL_LIGHT_MODEL_TWO_SIDE,GL_TRUE); + glEnable(GL_LIGHTING); + glEnable(GL_LIGHT0); + glLightfv(GL_LIGHT0,GL_AMBIENT,light_ambient); + glLightfv(GL_LIGHT0,GL_DIFFUSE,light_diffuse); + glLightfv(GL_LIGHT0,GL_SPECULAR,light_specular); + glLightfv(GL_LIGHT0,GL_POSITION,light_position); + glMaterialfv(GL_FRONT_AND_BACK,GL_SPECULAR,mat_specular); + glMaterialf(GL_FRONT_AND_BACK,GL_SHININESS,50.0); + glDepthMask(GL_FALSE); + glEnable(GL_BLEND); + glBlendFunc(GL_SRC_ALPHA,GL_ONE); + } + else /* display_mode == DISP_WIREFRAME */ + { + glDisable(GL_DEPTH_TEST); + glShadeModel(GL_FLAT); + glPolygonMode(GL_FRONT_AND_BACK,GL_LINE); + glDisable(GL_LIGHTING); + glDisable(GL_LIGHT0); + glDisable(GL_BLEND); + } +} + + +/* Redisplay the hypertorus. */ +static void display_hypertorus(ModeInfo *mi) +{ + hypertorusstruct *hp = &hyper[MI_SCREEN(mi)]; + + if (!hp->button_pressed) + { + hp->alpha += speed_wx * hp->speed_scale; + if (hp->alpha >= 360.0) + hp->alpha -= 360.0; + hp->beta += speed_wy * hp->speed_scale; + if (hp->beta >= 360.0) + hp->beta -= 360.0; + hp->delta += speed_wz * hp->speed_scale; + if (hp->delta >= 360.0) + hp->delta -= 360.0; + hp->zeta += speed_xy * hp->speed_scale; + if (hp->zeta >= 360.0) + hp->zeta -= 360.0; + hp->eta += speed_xz * hp->speed_scale; + if (hp->eta >= 360.0) + hp->eta -= 360.0; + hp->theta += speed_yz * hp->speed_scale; + if (hp->theta >= 360.0) + hp->theta -= 360.0; + } + + glMatrixMode(GL_PROJECTION); + glLoadIdentity(); + if (projection_3d == DISP_3D_ORTHOGRAPHIC) + { + if (hp->aspect >= 1.0) + glOrtho(-hp->aspect,hp->aspect,-1.0,1.0,0.1,100.0); + else + glOrtho(-1.0,1.0,-1.0/hp->aspect,1.0/hp->aspect,0.1,100.0); + } + else + { + gluPerspective(60.0,hp->aspect,0.1,100.0); + } + glMatrixMode(GL_MODELVIEW); + glLoadIdentity(); + + mi->polygon_count = hypertorus(mi,0.0,2.0*M_PI,0.0,2.0*M_PI,64,64); +} + + +ENTRYPOINT void reshape_hypertorus(ModeInfo *mi, int width, int height) +{ + hypertorusstruct *hp = &hyper[MI_SCREEN(mi)]; + + hp->WindW = (GLint)width; + hp->WindH = (GLint)height; + glViewport(0,0,width,height); + hp->aspect = (GLfloat)width/(GLfloat)height; +} + + +ENTRYPOINT Bool hypertorus_handle_event(ModeInfo *mi, XEvent *event) +{ + hypertorusstruct *hp = &hyper[MI_SCREEN(mi)]; + KeySym sym = 0; + char c = 0; + + if (event->xany.type == KeyPress || event->xany.type == KeyRelease) + XLookupString (&event->xkey, &c, 1, &sym, 0); + + if (event->xany.type == ButtonPress && + event->xbutton.button == Button1) + { + hp->button_pressed = True; + gltrackball_start(hp->trackballs[hp->current_trackball], + event->xbutton.x, event->xbutton.y, + MI_WIDTH(mi), MI_HEIGHT(mi)); + return True; + } + else if (event->xany.type == ButtonRelease && + event->xbutton.button == Button1) + { + hp->button_pressed = False; + return True; + } + else if (event->xany.type == KeyPress) + { + if (sym == XK_Shift_L || sym == XK_Shift_R) + { + hp->current_trackball = 1; + if (hp->button_pressed) + gltrackball_start(hp->trackballs[hp->current_trackball], + event->xbutton.x, event->xbutton.y, + MI_WIDTH(mi), MI_HEIGHT(mi)); + return True; + } + } + else if (event->xany.type == KeyRelease) + { + if (sym == XK_Shift_L || sym == XK_Shift_R) + { + hp->current_trackball = 0; + if (hp->button_pressed) + gltrackball_start(hp->trackballs[hp->current_trackball], + event->xbutton.x, event->xbutton.y, + MI_WIDTH(mi), MI_HEIGHT(mi)); + return True; + } + } + else if (event->xany.type == MotionNotify && hp->button_pressed) + { + gltrackball_track(hp->trackballs[hp->current_trackball], + event->xmotion.x, event->xmotion.y, + MI_WIDTH(mi), MI_HEIGHT(mi)); + return True; + } + + return False; +} + + +/* + *----------------------------------------------------------------------------- + *----------------------------------------------------------------------------- + * Xlock hooks. + *----------------------------------------------------------------------------- + *----------------------------------------------------------------------------- + */ + +/* + *----------------------------------------------------------------------------- + * Initialize hypertorus. Called each time the window changes. + *----------------------------------------------------------------------------- + */ + +ENTRYPOINT void init_hypertorus(ModeInfo *mi) +{ + hypertorusstruct *hp; + + if (hyper == NULL) + { + hyper = (hypertorusstruct *)calloc(MI_NUM_SCREENS(mi), + sizeof(hypertorusstruct)); + if (hyper == NULL) + return; + } + hp = &hyper[MI_SCREEN(mi)]; + + + hp->trackballs[0] = gltrackball_init(); + hp->trackballs[1] = gltrackball_init(); + hp->current_trackball = 0; + hp->button_pressed = False; + + /* Set the display mode. */ + if (!strcasecmp(mode,"wireframe") || !strcasecmp(mode,"0")) + { + display_mode = DISP_WIREFRAME; + } + else if (!strcasecmp(mode,"surface") || !strcasecmp(mode,"1")) + { + display_mode = DISP_SURFACE; + } + else if (!strcasecmp(mode,"transparent") || !strcasecmp(mode,"2")) + { + display_mode = DISP_TRANSPARENT; + } + else + { + display_mode = DISP_SURFACE; + } + + /* Set the appearance. */ + if (!strcasecmp(appear,"solid") || !strcasecmp(appear,"0")) + { + appearance = APPEARANCE_SOLID; + } + else if (!strcasecmp(appear,"bands") || !strcasecmp(appear,"1")) + { + appearance = APPEARANCE_BANDS; + num_spirals = 0; + } + else if (!strcasecmp(appear,"spirals-1") || !strcasecmp(appear,"3")) + { + appearance = APPEARANCE_SPIRALS; + num_spirals = 1; + } + else if (!strcasecmp(appear,"spirals-2") || !strcasecmp(appear,"4")) + { + appearance = APPEARANCE_SPIRALS; + num_spirals = 2; + } + else if (!strcasecmp(appear,"spirals-4") || !strcasecmp(appear,"5")) + { + appearance = APPEARANCE_SPIRALS; + num_spirals = 4; + } + else if (!strcasecmp(appear,"spirals-8") || !strcasecmp(appear,"6")) + { + appearance = APPEARANCE_SPIRALS; + num_spirals = 8; + } + else if (!strcasecmp(appear,"spirals-16") || !strcasecmp(appear,"7")) + { + appearance = APPEARANCE_SPIRALS; + num_spirals = 16; + } + else + { + appearance = APPEARANCE_BANDS; + num_spirals = 0; + } + + /* Set the color mode. */ + if (!strcasecmp(color_mode,"twosided")) + { + colors = COLORS_TWOSIDED; + } + else if (!strcasecmp(color_mode,"colorwheel")) + { + colors = COLORS_COLORWHEEL; + } + else + { + colors = COLORS_COLORWHEEL; + } + + /* Set the 3d projection mode. */ + if (!strcasecmp(proj_3d,"perspective") || !strcasecmp(proj_3d,"0")) + { + projection_3d = DISP_3D_PERSPECTIVE; + } + else if (!strcasecmp(proj_3d,"orthographic") || !strcasecmp(proj_3d,"1")) + { + projection_3d = DISP_3D_ORTHOGRAPHIC; + } + else + { + projection_3d = DISP_3D_PERSPECTIVE; + } + + /* Set the 4d projection mode. */ + if (!strcasecmp(proj_4d,"perspective") || !strcasecmp(proj_4d,"0")) + { + projection_4d = DISP_4D_PERSPECTIVE; + } + else if (!strcasecmp(proj_4d,"orthographic") || !strcasecmp(proj_4d,"1")) + { + projection_4d = DISP_4D_ORTHOGRAPHIC; + } + else + { + projection_4d = DISP_4D_PERSPECTIVE; + } + + /* make multiple screens rotate at slightly different rates. */ + hp->speed_scale = 0.9 + frand(0.3); + + if ((hp->glx_context = init_GL(mi)) != NULL) + { + reshape_hypertorus(mi,MI_WIDTH(mi),MI_HEIGHT(mi)); + glDrawBuffer(GL_BACK); + init(mi); + } + else + { + MI_CLEARWINDOW(mi); + } +} + +/* + *----------------------------------------------------------------------------- + * Called by the mainline code periodically to update the display. + *----------------------------------------------------------------------------- + */ +ENTRYPOINT void draw_hypertorus(ModeInfo *mi) +{ + Display *display = MI_DISPLAY(mi); + Window window = MI_WINDOW(mi); + hypertorusstruct *hp; + + if (hyper == NULL) + return; + hp = &hyper[MI_SCREEN(mi)]; + + MI_IS_DRAWN(mi) = True; + if (!hp->glx_context) + return; + + glXMakeCurrent(display,window,*(hp->glx_context)); + + glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT); + glLoadIdentity(); + + display_hypertorus(mi); + + if (MI_IS_FPS(mi)) + do_fps (mi); + + glFlush(); + + glXSwapBuffers(display,window); +} + + +/* + *----------------------------------------------------------------------------- + * The display is being taken away from us. Free up malloc'ed + * memory and X resources that we've alloc'ed. Only called + * once, we must zap everything for every screen. + *----------------------------------------------------------------------------- + */ + +ENTRYPOINT void release_hypertorus(ModeInfo *mi) +{ + if (hyper != NULL) + { + int screen; + + for (screen = 0; screen < MI_NUM_SCREENS(mi); screen++) + { + hypertorusstruct *hp = &hyper[screen]; + + if (hp->glx_context) + hp->glx_context = (GLXContext *)NULL; + } + (void) free((void *)hyper); + hyper = (hypertorusstruct *)NULL; + } + FreeAllGL(mi); +} + +#ifndef STANDALONE +ENTRYPOINT void change_hypertorus(ModeInfo *mi) +{ + hypertorusstruct *hp = &hyper[MI_SCREEN(mi)]; + + if (!hp->glx_context) + return; + + glXMakeCurrent(MI_DISPLAY(mi),MI_WINDOW(mi),*(hp->glx_context)); + init(mi); +} +#endif /* !STANDALONE */ + +XSCREENSAVER_MODULE ("Hypertorus", hypertorus) + +#endif /* USE_GL */ diff --git a/hacks/glx/hypertorus.man b/hacks/glx/hypertorus.man new file mode 100644 index 00000000..8c7075f7 --- /dev/null +++ b/hacks/glx/hypertorus.man @@ -0,0 +1,188 @@ +.TH XScreenSaver 1 "" "X Version 11" +.SH NAME +hypertorus - Draws a hypertorus that rotates in 4d +.SH SYNOPSIS +.B hypertorus +[\-display \fIhost:display.screen\fP] +[\-install] +[\-visual \fIvisual\fP] +[\-window] +[\-root] +[\-delay \fIusecs\fP] +[\-fps] +[\-wireframe] +[\-surface] +[\-transparent] +[\-solid] +[\-bands] +[\-spirals-{1,2,4,8,16}] +[\-twosided] +[\-colorwheel] +[\-perspective-3d] +[\-orthographic-3d] +[\-perspective-4d] +[\-orthographic-4d] +[\-speed-wx \fIfloat\fP] +[\-speed-wy \fIfloat\fP] +[\-speed-wz \fIfloat\fP] +[\-speed-xy \fIfloat\fP] +[\-speed-xz \fIfloat\fP] +[\-speed-yz \fIfloat\fP] +.SH DESCRIPTION +The \fIhypertorus\fP program shows the Clifford torus as it rotates in +4d. The Clifford torus is a torus lies on the "surface" of the +hypersphere in 4d. The program projects the 4d torus to 3d using +either a perspective or an orthographic projection. Of the two +alternatives, the perspective projection looks much more appealing. +In orthographic projections the torus degenerates into a doubly +covered cylinder for some angles. The projected 3d torus can then be +projected to the screen either perspectively or orthographically. +There are three display modes for the torus: mesh (wireframe), solid, +or transparent. Furthermore, the appearance of the torus can be as a +solid object or as a set of see-through bands or see-through spirals. +Finally, the colors with with the torus is drawn can be set to either +two-sided or to a color wheel. In the first case, the torus is drawn +with red on the outside and green on the inside. This mode enables +you to see that the torus turns inside-out as it rotates in 4d. The +second mode draws the torus with a fully saturated color wheel. This +gives a very nice effect when combined with the see-through bands or +see-through spirals mode. The rotation speed for each of the six +planes around which the torus rotates can be chosen. This program is +very much inspired by Thomas Banchoff's book "Beyond the Third +Dimension: Geometry, Computer Graphics, and Higher Dimensions", +Scientific American Library, 1990. +.SH OPTIONS +.I hypertorus +accepts the following options: +.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 \-install +Install a private colormap for the window. +.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 \-delay \fImicroseconds\fP +How much of a delay should be introduced between steps of the +animation. Default 25000, or 1/40th second. +.PP +The following three options are mutually exclusive. They determine +how the torus is displayed. +.TP 8 +.B \-wireframe +Display the torus as a wireframe mesh. +.TP 8 +.B \-surface +Display the torus as a solid surface (default). +.TP 8 +.B \-transparent +Display the torus as a transparent surface. +.PP +The following seven options are mutually exclusive. They determine the +appearance of the torus. +.TP 8 +.B \-solid +Display the torus as a solid object. +.TP 8 +.B \-bands +Display the torus as see-through bands (default). +.TP 8 +.B \-spirals-1, \-spirals-2, \-spirals-4, \-spirals-8, \-spirals-16 +Display the torus as see-through spirals with the indicated number of +spirals. +.PP +The following two options are mutually exclusive. They determine how +to color the torus. +.TP 8 +.B \-twosided +Display the torus with two colors: red on the outside and green on +the inside. +.TP 8 +.B \-colorwheel +Display the torus with a fully saturated color wheel (default). If +the torus is displayed as see-through bands each band will be +displayed with a different color. Likewise, if the torus is displayed +as see-through spirals each spiral will receive a different color. +.PP +The following two options are mutually exclusive. They determine how +the torus is projected from 3d to 2d (i.e., to the screen). +.TP 8 +.B \-perspective-3d +Project the torus from 3d to 2d using a perspective projection +(default). +.TP 8 +.B \-orthographic-3d +Project the torus from 3d to 2d using an orthographic projection. +.PP +The following two options are mutually exclusive. They determine how +the torus is projected from 4d to 3d. +.TP 8 +.B \-perspective-4d +Project the torus from 4d to 3d using a perspective projection +(default). +.TP 8 +.B \-orthographic-4d +Project the torus from 4d to 3d using an orthographic projection. +.PP +The following six options determine the rotation speed of the torus +around the six possible hyperplanes. The rotation speed is measured +in degrees per frame. The speeds should be set to relatively small +values, e.g., less than 4 in magnitude. +.TP 8 +.B \-speed-wx \fIfloat\fP +Rotation speed around the wx plane (default: 1.1). +.TP 8 +.B \-speed-wy \fIfloat\fP +Rotation speed around the wy plane (default: 1.3). +.TP 8 +.B \-speed-wz \fIfloat\fP +Rotation speed around the wz plane (default: 1.5). +.TP 8 +.B \-speed-xy \fIfloat\fP +Rotation speed around the xy plane (default: 1.7). +.TP 8 +.B \-speed-xz \fIfloat\fP +Rotation speed around the xz plane (default: 1.9). +.TP 8 +.B \-speed-yz \fIfloat\fP +Rotation speed around the yz plane (default: 2.1). +.TP 8 +.B \-fps +Display the current frame rate, CPU load, and polygon count. +.SH INTERACTION +If you run this program in standalone mode you can rotate the +hypertorus by dragging the mouse while pressing the left mouse button. +This rotates the hypertorus in 3D, i.e., around the wx, wy, and wz +planes. If you press the shift key while dragging the mouse with the +left button pressed the hypertorus is rotated in 4D, i.e., around the +xy, xz, and yz planes. To examine the hypertorus at your leisure, it +is best to set all speeds to 0. Otherwise, the hypertorus will rotate +while the left mouse button is not pressed. +.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 2003-2005 by Carsten Steger. 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 +Carsten Steger , 28-sep-2005. diff --git a/hacks/glx/hypnowheel.c b/hacks/glx/hypnowheel.c new file mode 100644 index 00000000..3131a9fc --- /dev/null +++ b/hacks/glx/hypnowheel.c @@ -0,0 +1,298 @@ +/* hypnowheel, Copyright (c) 2008 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. + * + * Draws overlapping spirals, where the tightness of the spirals changes. + * Nice settings: + * + * -layers 7 -wander + * -count 3 -layers 50 + * -twistiness 0.2 -layers 20 + * -count 3 -layers 2 -speed 20 -twist 10 -wander + */ + +#define DEFAULTS "*delay: 20000 \n" \ + "*count: 13 \n" \ + "*showFPS: False \n" \ + "*fpsSolid: True \n" \ + "*wireframe: False \n" \ + +# define refresh_hypnowheel 0 +# define release_hypnowheel 0 +# define hypnowheel_handle_event 0 +#undef countof +#define countof(x) (sizeof((x))/sizeof((*x))) + +#include "xlockmore.h" +#include "colors.h" +#include "rotator.h" +#include + +#ifdef USE_GL /* whole file */ + + +#define DEF_WANDER "False" +#define DEF_SYMMETRIC "False" +#define DEF_SPEED "1.0" +#define DEF_TWISTINESS "4.0" +#define DEF_LAYERS "4" + +typedef struct { + int color; + GLfloat twist; + GLfloat alpha; + rotator *rot; +} disc; + +typedef struct { + GLXContext *glx_context; + rotator *rot; + disc *discs; + int ncolors; + XColor *colors; + +} hypnowheel_configuration; + +static hypnowheel_configuration *bps = NULL; + +static GLfloat speed; +static GLfloat twistiness; +static GLint nlayers; +static Bool do_wander; +static Bool do_symmetric; + +static XrmOptionDescRec opts[] = { + { "-speed", ".speed", XrmoptionSepArg, 0 }, + { "-twistiness", ".twistiness", XrmoptionSepArg, 0 }, + { "-layers", ".layers", XrmoptionSepArg, 0 }, + { "-wander", ".wander", XrmoptionNoArg, "True" }, + { "+wander", ".wander", XrmoptionNoArg, "False" }, + { "-symmetric", ".symmetric", XrmoptionNoArg, "True" }, + { "+symmetric", ".symmetric", XrmoptionNoArg, "False" }, +}; + +static argtype vars[] = { + {&do_wander, "wander", "Wander", DEF_WANDER, t_Bool}, + {&do_symmetric, "symmetric", "Symmetric", DEF_SYMMETRIC, t_Bool}, + {&speed, "speed", "Speed", DEF_SPEED, t_Float}, + {&twistiness, "twistiness", "Twistiness", DEF_TWISTINESS, t_Float}, + {&nlayers, "layers", "Layers", DEF_LAYERS, t_Int}, +}; + +ENTRYPOINT ModeSpecOpt hypnowheel_opts = { + countof(opts), opts, countof(vars), vars, NULL}; + + +static void +draw_spiral (ModeInfo *mi, disc *d) +{ + int wire = MI_IS_WIREFRAME(mi); + hypnowheel_configuration *bp = &bps[MI_SCREEN(mi)]; + GLfloat rr = 0.5; + int n = MI_COUNT(mi); + int steps = n * (wire ? 3 : (n < 5 ? 60 : n < 10 ? 20 : 10)); + GLfloat dth = M_PI*2 / n; + GLfloat dr = rr / steps; + GLfloat th; + GLfloat twist = d->twist; + GLfloat dtwist = M_PI * 2 * twist / steps; + double cscale = 65536.0; + + if (nlayers > 3 && !wire) + cscale *= (nlayers-2); /* don't wash out to white */ + + glColor4f (bp->colors[d->color].red / cscale, + bp->colors[d->color].green / cscale, + bp->colors[d->color].blue / cscale, + d->alpha); + for (th = 0; th < M_PI*2; th += dth) + { + GLfloat th1 = th; + GLfloat r; + glBegin (wire ? GL_LINE_STRIP : GL_QUAD_STRIP); + for (r = 0; r <= rr; r += dr) + { + GLfloat th2 = th1 + dth/2 + dtwist; + th1 += dtwist; + glVertex3f (r * cos(th1), r * sin(th1), 0); + if (! wire) + glVertex3f (r * cos(th2), r * sin(th2), 0); + mi->polygon_count++; + } + glEnd(); + } +} + + + +/* Window management, etc + */ +ENTRYPOINT void +reshape_hypnowheel (ModeInfo *mi, int width, int height) +{ + GLfloat h = (GLfloat) height / (GLfloat) width; + + glViewport (0, 0, (GLint) width, (GLint) height); + + glMatrixMode(GL_PROJECTION); + glLoadIdentity(); + gluPerspective (30.0, 1/h, 1.0, 100.0); + + glMatrixMode(GL_MODELVIEW); + glLoadIdentity(); + gluLookAt( 0.0, 0.0, 30.0, + 0.0, 0.0, 0.0, + 0.0, 1.0, 0.0); + + glClear(GL_COLOR_BUFFER_BIT); +} + + +ENTRYPOINT void +init_hypnowheel (ModeInfo *mi) +{ + hypnowheel_configuration *bp; + int wire = MI_IS_WIREFRAME(mi); + int i; + + if (!bps) { + bps = (hypnowheel_configuration *) + calloc (MI_NUM_SCREENS(mi), sizeof (hypnowheel_configuration)); + if (!bps) { + fprintf(stderr, "%s: out of memory\n", progname); + exit(1); + } + } + + bp = &bps[MI_SCREEN(mi)]; + + bp->glx_context = init_GL(mi); + + reshape_hypnowheel (mi, MI_WIDTH(mi), MI_HEIGHT(mi)); + + bp->rot = make_rotator (0, 0, 0, 0, speed * 0.0025, False); + + bp->ncolors = 1024; + bp->colors = (XColor *) calloc(bp->ncolors, sizeof(XColor)); + make_smooth_colormap (0, 0, 0, + bp->colors, &bp->ncolors, + False, 0, False); + + if (MI_COUNT(mi) < 2) MI_COUNT(mi) = 2; + if (nlayers < 1) nlayers = 1; + bp->discs = (disc *) calloc (nlayers, sizeof (disc)); + + for (i = 0; i < nlayers; i++) + { + double spin_speed = speed * 0.2; + double wander_speed = speed * 0.0012; + double spin_accel = 0.2; + + bp->discs[i].twist = 0; + bp->discs[i].alpha = 1; + bp->discs[i].color = i * bp->ncolors / nlayers; + + spin_speed += frand (spin_speed / 5); + wander_speed += frand (wander_speed * 3); + + bp->discs[i].rot = make_rotator (spin_speed, spin_speed, spin_speed, + spin_accel, + (do_wander ? wander_speed : 0), + True); + } + + glDisable (GL_LIGHTING); + glDisable (GL_DEPTH_TEST); + glDepthMask (GL_FALSE); + glDisable (GL_CULL_FACE); + + if (! wire) + { + glEnable (GL_BLEND); + glBlendFunc (GL_ONE, GL_ONE); + } +} + + +ENTRYPOINT void +draw_hypnowheel (ModeInfo *mi) +{ + hypnowheel_configuration *bp = &bps[MI_SCREEN(mi)]; + Display *dpy = MI_DISPLAY(mi); + Window window = MI_WINDOW(mi); + int i; + + if (!bp->glx_context) + return; + + glXMakeCurrent(MI_DISPLAY(mi), MI_WINDOW(mi), *(bp->glx_context)); + + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + + glPushMatrix (); + + { + double x, y, z; + get_position (bp->rot, &x, &y, &z, True); + glTranslatef((x - 0.5) * 8, + (y - 0.5) * 8, + 0); + + get_rotation (bp->rot, &x, &y, &z, True); + 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); + } + + mi->polygon_count = 0; + + glScalef (45, 45, 45); + + for (i = 0; i < nlayers; i++) + { + disc *d = &bp->discs[i]; + double x, y, z; + rotator *rot = (do_symmetric ? bp->discs[(i & ~0x1)].rot : d->rot); + Bool tick = (!do_symmetric || i == 0); + + glPushMatrix(); + + d->color++; + if (d->color >= bp->ncolors) + d->color = 0; + + get_position (rot, &x, &y, &z, tick); + x -= 0.5; + y -= 0.5; + x *= 0.1; + y *= 0.1; + + glTranslatef (x, y, 0); + d->twist = (z * twistiness * + ((i & 1) ? 1 : -1)); + + get_rotation (rot, &x, &y, &z, tick); + + glRotatef (360 * z, 0, 0, 1); /* rotation of this disc */ + + draw_spiral (mi, &bp->discs[i]); + glPopMatrix(); + } + + glPopMatrix (); + + if (mi->fps_p) do_fps (mi); + glFinish(); + + glXSwapBuffers(dpy, window); +} + +XSCREENSAVER_MODULE ("Hypnowheel", hypnowheel) + +#endif /* USE_GL */ diff --git a/hacks/glx/hypnowheel.man b/hacks/glx/hypnowheel.man new file mode 100644 index 00000000..233c9453 --- /dev/null +++ b/hacks/glx/hypnowheel.man @@ -0,0 +1,80 @@ +.TH XScreenSaver 1 "" "X Version 11" +.SH NAME +hypnowheel - draws overlapping, translucent spiral patterns +.SH SYNOPSIS +.B hypnowheel +[\-display \fIhost:display.screen\fP] +[\-visual \fIvisual\fP] +[\-window] +[\-root] +[\-delay \fIint\fP] +[\-layers \fIint\fP] +[\-count \fIint\fP] +[\-twistiness \fIfloat\fP] +[\-speed \fIfloat\fP] +[\-wander\fP] +[\-symmetric\fP] +[\-fps] +.SH DESCRIPTION +Draws a series of overlapping, translucent spiral patterns. +The tightness of their spirals fluctuates in and out. +.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 \fIint\fP +Delay between frames, in microseconds. Default 20000. +.TP 8 +.B \-layers \fIint\fP +How many different spirals to draw at once. Default 4. +.TP 8 +.B \-count \fIint\fP +How many arms each spiral should have. Default 11. +.TP 8 +.B \-twistiness \fIfloat\fP +How tightly wound the spirals can become, measured in rotations. +Default 4.0 (four times around). +.TP 8 +.B \-speed \fIratio\fP +Less than 1 for slower, greater than 1 for faster. Default 1. +.TP 8 +.B \-wander +If specified, then the centers of the spirals will wander around, +rather than them all having the same origin. +.TP 8 +.B \-symmetric +If specified, then each pair of left-wrapping and right-wrapping +spirals will be mirror images of each other. +.TP 8 +.B \-fps +Display the current frame rate, CPU load, and polygon count. +.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 2008 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/glx/involute.c b/hacks/glx/involute.c new file mode 100644 index 00000000..a7c415e9 --- /dev/null +++ b/hacks/glx/involute.c @@ -0,0 +1,968 @@ +/* involute, Copyright (c) 2004-2007 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. + * + * Utilities for rendering OpenGL gears with involute teeth. + */ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif /* HAVE_CONFIG_H */ + +#include "screenhackI.h" + +#ifndef HAVE_COCOA +# include +# include +#endif /* !HAVE_COCOA */ + +#ifdef HAVE_JWZGLES +# include "jwzgles.h" +#endif /* HAVE_JWZGLES */ + +#include "involute.h" +#include "normals.h" + +#undef countof +#define countof(x) (sizeof((x))/sizeof((*x))) + + +/* For debugging: if true then in wireframe, do not abbreviate. */ +static Bool wire_all_p = False; +static Bool show_normals_p = False; + + +/* Draws an uncapped tube of the given radius extending from top to bottom, + with faces pointing either in or out. + */ +static int +draw_ring (int segments, + GLfloat r, GLfloat top, GLfloat bottom, + Bool in_p, Bool wire_p) +{ + int i; + int polys = 0; + GLfloat width = M_PI * 2 / segments; + + if (top != bottom) + { + glFrontFace (in_p ? GL_CCW : GL_CW); + glBegin (wire_p ? GL_LINES : GL_QUAD_STRIP); + for (i = 0; i < segments + (wire_p ? 0 : 1); i++) + { + GLfloat th = i * width; + GLfloat cth = cos(th); + GLfloat sth = sin(th); + if (in_p) + glNormal3f (-cth, -sth, 0); + else + glNormal3f (cth, sth, 0); + glVertex3f (cth * r, sth * r, top); + glVertex3f (cth * r, sth * r, bottom); + } + polys += segments; + glEnd(); + } + + if (wire_p) + { + glBegin (GL_LINE_LOOP); + for (i = 0; i < segments; i++) + { + GLfloat th = i * width; + glVertex3f (cos(th) * r, sin(th) * r, top); + } + glEnd(); + glBegin (GL_LINE_LOOP); + for (i = 0; i < segments; i++) + { + GLfloat th = i * width; + glVertex3f (cos(th) * r, sin(th) * r, bottom); + } + glEnd(); + } + + return polys; +} + + +/* Draws a donut-shaped disc between the given radii, + with faces pointing either up or down. + The first radius may be 0, in which case, a filled disc is drawn. + */ +static int +draw_disc (int segments, + GLfloat ra, GLfloat rb, GLfloat z, + Bool up_p, Bool wire_p) +{ + int i; + int polys = 0; + GLfloat width = M_PI * 2 / segments; + + if (ra < 0) abort(); + if (rb <= 0) abort(); + + if (ra == 0) + glFrontFace (up_p ? GL_CW : GL_CCW); + else + glFrontFace (up_p ? GL_CCW : GL_CW); + + if (ra == 0) + glBegin (wire_p ? GL_LINES : GL_TRIANGLE_FAN); + else + glBegin (wire_p ? GL_LINES : GL_QUAD_STRIP); + + glNormal3f (0, 0, (up_p ? -1 : 1)); + + if (ra == 0 && !wire_p) + glVertex3f (0, 0, z); + + for (i = 0; i < segments + (wire_p ? 0 : 1); i++) + { + GLfloat th = i * width; + GLfloat cth = cos(th); + GLfloat sth = sin(th); + if (wire_p || ra != 0) + glVertex3f (cth * ra, sth * ra, z); + glVertex3f (cth * rb, sth * rb, z); + } + polys += segments; + glEnd(); + return polys; +} + + +/* Draws N thick radial lines between the given radii, + with faces pointing either up or down. + */ +static int +draw_spokes (int n, GLfloat thickness, int segments, + GLfloat ra, GLfloat rb, GLfloat z1, GLfloat z2, + Bool wire_p) +{ + int i; + int polys = 0; + GLfloat width; + int segments2 = 0; + int insegs, outsegs; + int tick; + int state; + + if (ra <= 0 || rb <= 0) abort(); + + segments *= 3; + + while (segments2 < segments) /* need a multiple of N >= segments */ + segments2 += n; /* (yes, this is a moronic way to find that) */ + + insegs = ((float) (segments2 / n) + 0.5) / thickness; + outsegs = (segments2 / n) - insegs; + if (insegs <= 0) insegs = 1; + if (outsegs <= 0) outsegs = 1; + + segments2 = (insegs + outsegs) * n; + width = M_PI * 2 / segments2; + + tick = 0; + state = 0; + for (i = 0; i < segments2; i++, tick++) + { + GLfloat th1 = i * width; + GLfloat th2 = th1 + width; + GLfloat cth1 = cos(th1); + GLfloat sth1 = sin(th1); + GLfloat cth2 = cos(th2); + GLfloat sth2 = sin(th2); + GLfloat orb = rb; + + int changed = (i == 0); + + if (state == 0 && tick == insegs) + tick = 0, state = 1, changed = 1; + else if (state == 1 && tick == outsegs) + tick = 0, state = 0, changed = 1; + + if ((state == 1 || /* in */ + (state == 0 && changed)) && + (!wire_p || wire_all_p)) + { + /* top */ + glFrontFace (GL_CCW); + glBegin (wire_p ? GL_LINES : GL_QUADS); + glNormal3f (0, 0, -1); + glVertex3f (cth1 * ra, sth1 * ra, z1); + glVertex3f (cth1 * rb, sth1 * rb, z1); + glVertex3f (cth2 * rb, sth2 * rb, z1); + glVertex3f (cth2 * ra, sth2 * ra, z1); + polys++; + glEnd(); + + /* bottom */ + glFrontFace (GL_CW); + glBegin (wire_p ? GL_LINES : GL_QUADS); + glNormal3f (0, 0, 1); + glVertex3f (cth1 * ra, sth1 * ra, z2); + glVertex3f (cth1 * rb, sth1 * rb, z2); + glVertex3f (cth2 * rb, sth2 * rb, z2); + glVertex3f (cth2 * ra, sth2 * ra, z2); + polys++; + glEnd(); + } + + if (state == 1 && changed) /* entering "in" state */ + { + /* left */ + glFrontFace (GL_CW); + glBegin (wire_p ? GL_LINES : GL_QUADS); + do_normal (cth1 * rb, sth1 * rb, z1, + cth1 * ra, sth1 * ra, z1, + cth1 * rb, sth1 * rb, z2); + glVertex3f (cth1 * ra, sth1 * ra, z1); + glVertex3f (cth1 * rb, sth1 * rb, z1); + glVertex3f (cth1 * rb, sth1 * rb, z2); + glVertex3f (cth1 * ra, sth1 * ra, z2); + polys++; + glEnd(); + } + + if (state == 0 && changed) /* entering "out" state */ + { + /* right */ + glFrontFace (GL_CCW); + glBegin (wire_p ? GL_LINES : GL_QUADS); + do_normal (cth2 * ra, sth2 * ra, z1, + cth2 * rb, sth2 * rb, z1, + cth2 * rb, sth2 * rb, z2); + glVertex3f (cth2 * ra, sth2 * ra, z1); + glVertex3f (cth2 * rb, sth2 * rb, z1); + glVertex3f (cth2 * rb, sth2 * rb, z2); + glVertex3f (cth2 * ra, sth2 * ra, z2); + polys++; + glEnd(); + } + + rb = orb; + } + return polys; +} + + +/* Draws some bumps (embedded cylinders) on the gear. + */ +static int +draw_gear_nubs (gear *g, Bool wire_p) +{ + int polys = 0; + int i; + int steps = (g->size != INVOLUTE_LARGE ? 5 : 20); + double r, size, height; + GLfloat *cc; + int which; + GLfloat width, off; + + if (! g->nubs) return 0; + + which = involute_biggest_ring (g, &r, &size, &height); + size /= 5; + height *= 0.7; + + cc = (which == 1 ? g->color : g->color2); + glMaterialfv (GL_FRONT, GL_AMBIENT_AND_DIFFUSE, cc); + + if (g->inverted_p) + r = g->r + size + g->tooth_h; + + width = M_PI * 2 / g->nubs; + off = M_PI / (g->nteeth * 2); /* align first nub with a tooth */ + + for (i = 0; i < g->nubs; i++) + { + GLfloat th = (i * width) + off; + glPushMatrix(); + + glRotatef (th * 180 / M_PI, 0, 0, 1); + glTranslatef (r, 0, 0); + + if (g->inverted_p) /* nubs go on the outside rim */ + { + size = g->thickness / 3; + height = (g->r - g->inner_r)/2; + glTranslatef (height, 0, 0); + glRotatef (90, 0, 1, 0); + } + + if (wire_p && !wire_all_p) + polys += draw_ring ((g->size == INVOLUTE_LARGE ? steps/2 : steps), + size, 0, 0, False, wire_p); + else + { + polys += draw_disc (steps, 0, size, -height, True, wire_p); + polys += draw_disc (steps, 0, size, height, False, wire_p); + polys += draw_ring (steps, size, -height, height, False, wire_p); + } + glPopMatrix(); + } + return polys; +} + + + +/* Draws a much simpler representation of a gear. + Returns the number of polygons. + */ +int +draw_involute_schematic (gear *g, Bool wire_p) +{ + int polys = 0; + int i; + GLfloat width = M_PI * 2 / g->nteeth; + + if (!wire_p) glDisable(GL_LIGHTING); + glColor3f (g->color[0] * 0.6, g->color[1] * 0.6, g->color[2] * 0.6); + + glBegin (GL_LINES); + for (i = 0; i < g->nteeth; i++) + { + GLfloat th = (i * width) + (width/4); + glVertex3f (0, 0, -g->thickness/2); + glVertex3f (cos(th) * g->r, sin(th) * g->r, -g->thickness/2); + } + polys += g->nteeth; + glEnd(); + + glBegin (GL_LINE_LOOP); + for (i = 0; i < g->nteeth; i++) + { + GLfloat th = (i * width) + (width/4); + glVertex3f (cos(th) * g->r, sin(th) * g->r, -g->thickness/2); + } + polys += g->nteeth; + glEnd(); + + if (!wire_p) glEnable(GL_LIGHTING); + return polys; +} + + +/* Renders all the interior (non-toothy) parts of a gear: + the discs, axles, etc. + */ +static int +draw_gear_interior (gear *g, Bool wire_p) +{ + int polys = 0; + + int steps = g->nteeth * 2; + if (steps < 10) steps = 10; + if ((wire_p && !wire_all_p) || g->size != INVOLUTE_LARGE) steps /= 2; + if (g->size != INVOLUTE_LARGE && steps > 16) steps = 16; + + /* ring 1 (facing in) is done in draw_gear_teeth */ + + /* ring 2 (facing in) and disc 2 + */ + if (g->inner_r2) + { + GLfloat ra = g->inner_r * 1.04; /* slightly larger than inner_r */ + GLfloat rb = g->inner_r2; /* since the points don't line up */ + GLfloat za = -g->thickness2/2; + GLfloat zb = g->thickness2/2; + + glMaterialfv (GL_FRONT, GL_AMBIENT_AND_DIFFUSE, g->color2); + + if ((g->coax_p != 1 && !g->inner_r3) || + (wire_p && wire_all_p)) + polys += + draw_ring (steps, rb, za, zb, True, wire_p); /* ring facing in*/ + + if (wire_p && wire_all_p) + polys += + draw_ring (steps, ra, za, zb, True, wire_p); /* ring facing in*/ + + if (g->spokes) + polys += draw_spokes (g->spokes, g->spoke_thickness, + steps, ra, rb, za, zb, wire_p); + else if (!wire_p || wire_all_p) + { + polys += + draw_disc (steps, ra, rb, za, True, wire_p); /* top plate */ + polys += + draw_disc (steps, ra, rb, zb, False, wire_p); /* bottom plate*/ + } + } + + /* ring 3 (facing in and out) and disc 3 + */ + if (g->inner_r3) + { + GLfloat ra = g->inner_r2; + GLfloat rb = g->inner_r3; + GLfloat za = -g->thickness3/2; + GLfloat zb = g->thickness3/2; + + glMaterialfv (GL_FRONT, GL_AMBIENT_AND_DIFFUSE, g->color); + + polys += + draw_ring (steps, ra, za, zb, False, wire_p); /* ring facing out */ + + if (g->coax_p != 1 || (wire_p && wire_all_p)) + polys += + draw_ring (steps, rb, za, zb, True, wire_p); /* ring facing in */ + + if (!wire_p || wire_all_p) + { + polys += + draw_disc (steps, ra, rb, za, True, wire_p); /* top plate */ + polys += + draw_disc (steps, ra, rb, zb, False, wire_p); /* bottom plate */ + } + } + + /* axle tube + */ + if (g->coax_p == 1) + { + GLfloat cap_height = g->coax_thickness/3; + + GLfloat ra = (g->inner_r3 ? g->inner_r3 : + g->inner_r2 ? g->inner_r2 : + g->inner_r); + GLfloat za = -(g->thickness/2 + cap_height); + GLfloat zb = g->coax_thickness/2 + g->coax_displacement + cap_height; + + glMaterialfv (GL_FRONT, GL_AMBIENT_AND_DIFFUSE, g->color); + + if (wire_p && !wire_all_p) steps /= 2; + + polys += + draw_ring (steps, ra, za, zb, False, wire_p); /* ring facing out */ + + if (!wire_p || wire_all_p) + { + polys += + draw_disc (steps, 0, ra, za, True, wire_p); /* top plate */ + polys + += draw_disc (steps, 0, ra, zb, False, wire_p); /* bottom plate */ + } + } + return polys; +} + + +/* gear_teeth_geometry computes the vertices and normals of the teeth + of a gear. This is the heavy lifting: there are a ton of polygons + around the perimiter of a gear, and the normals are difficult (not + radial or right angles.) + + It would be nice if we could cache this, but the numbers are + different for essentially every gear: + + - Every gear has a different inner_r, so the vertices of the + inner ring (and thus, the triangle fans on the top and bottom + faces) are different in a non-scalable way. + + - If the ratio between tooth_w and tooth_h changes, the normals + on the outside edges of the teeth are invalid (this can happen + every time we start a new train.) + + So instead, we rely on OpenGL display lists to do the cacheing for + us -- we only compute all these normals once per gear, instead of + once per gear per frame. + */ + +typedef struct { + int npoints; + XYZ *points; + XYZ *fnormals; /* face normals */ + XYZ *pnormals; /* point normals */ +} tooth_face; + + +static void +tooth_normals (tooth_face *f, GLfloat tooth_slope) +{ + int i; + + /* Compute the face normals for each facet. */ + for (i = 0; i < f->npoints; i++) + { + XYZ p1, p2, p3; + int a = i; + int b = (i == f->npoints-1 ? 0 : i+1); + p1 = f->points[a]; + p2 = f->points[b]; + p3 = p1; + p3.x -= (p3.x * tooth_slope); + p3.y -= (p3.y * tooth_slope); + p3.z++; + f->fnormals[i] = calc_normal (p1, p2, p3); + } + + /* From the face normals, compute the vertex normals + (by averaging the normals of adjascent faces.) + */ + for (i = 0; i < f->npoints; i++) + { + int a = (i == 0 ? f->npoints-1 : i-1); + int b = i; + XYZ n1 = f->fnormals[a]; /* normal of [i-1 - i] face */ + XYZ n2 = f->fnormals[b]; /* normal of [i - i+1] face */ + f->pnormals[i].x = (n1.x + n2.x) / 2; + f->pnormals[i].y = (n1.y + n2.y) / 2; + f->pnormals[i].z = (n1.z + n2.z) / 2; + } +} + + +static void +gear_teeth_geometry (gear *g, + tooth_face *orim, /* outer rim (the teeth) */ + tooth_face *irim) /* inner rim (the hole) */ +{ + int i; + int ppt = 9; /* max points per tooth */ + GLfloat width = M_PI * 2 / g->nteeth; + GLfloat rh = g->tooth_h; + GLfloat tw = width; + + /* Approximate shape of an "involute" gear tooth. + + (TH) + th0 th1 th2 th3 th4 th5 th6 th7 th8 th9 th10 + : : : : : : : : : : : + : : : : : : : : : : : + r0 ........:..:..:...___________...:..:..:......:......:.. + : : : /: : :\ : : : : : + : : : / : : : \ : : : : : + : : :/ : : : \: : : : : + r1 ........:.....@...:....:....:...@..:..:......:......:.. + : : @: : : : :@ : : : : + (R) ...........:...@.:...:....:....:...:.@..........:......:...... + : :@ : : : : : @: : : : + r2 ........:..@..:...:....:....:...:..@:........:......:.. + : /: : : : : : :\ : : : + :/ : : : : : : : \: : : / + r3 ......__/..:..:...:....:....:...:..:..\______________/ + : : : : : : : : : : : + | : : : : : : : | : : + : : : : : : : : : : : + | : : : : : : : | : : + r4 ......__:_____________________________:________________ + */ + + GLfloat r[20]; + GLfloat th[20]; + GLfloat R = g->r; + + r[0] = R + (rh * 0.5); + r[1] = R + (rh * 0.25); + r[2] = R - (r[1]-R); + r[3] = R - (r[0]-R); + r[4] = g->inner_r; + + th[0] = -tw * (g->size == INVOLUTE_SMALL ? 0.5 : + g->size == INVOLUTE_MEDIUM ? 0.41 : 0.45); + th[1] = -tw * 0.30; + th[2] = -tw * (g->nteeth >= 5 ? 0.16 : 0.12); + th[3] = -tw * (g->size == INVOLUTE_MEDIUM ? 0.1 : 0.04); + th[4] = 0; + th[5] = -th[3]; + th[6] = -th[2]; + th[7] = -th[1]; + th[8] = -th[0]; + th[9] = width / 2; + th[10]= th[0] + width; + + if (g->inverted_p) /* put the teeth on the inside */ + { + for (i = 0; i < countof(th); i++) + th[i] = -th[i]; + for (i = 0; i < countof(r); i++) + r[i] = R - (r[i] - R); + } + +#if 0 + if (g->inverted_p) /* put the teeth on the inside */ + { + GLfloat swap[countof(th)]; + + for (i = 0; i < maxr; i++) + swap[maxr-i-1] = R - (r[i] - R); + for (i = 0; i < maxr; i++) + r[i] = swap[i]; + + for (i = 0; i < maxth; i++) + swap[maxth-i-1] = -th[i]; + for (i = 0; i < maxth; i++) + th[i] = swap[i]; + } +#endif + + orim->npoints = 0; + orim->points = (XYZ *) calloc(ppt * g->nteeth+1, sizeof(*orim->points)); + orim->fnormals = (XYZ *) calloc(ppt * g->nteeth+1, sizeof(*orim->fnormals)); + orim->pnormals = (XYZ *) calloc(ppt * g->nteeth+1, sizeof(*orim->pnormals)); + + irim->npoints = 0; + irim->points = (XYZ *) calloc(ppt * g->nteeth+1, sizeof(*irim->points)); + irim->fnormals = (XYZ *) calloc(ppt * g->nteeth+1, sizeof(*irim->fnormals)); + irim->pnormals = (XYZ *) calloc(ppt * g->nteeth+1, sizeof(*irim->pnormals)); + + if (!orim->points || !orim->pnormals || !orim->fnormals || + !irim->points || !irim->pnormals || !irim->fnormals) + { + fprintf (stderr, "%s: out of memory\n", progname); + exit (1); + } + + /* First, compute the coordinates of every point used for every tooth. + */ + for (i = 0; i < g->nteeth; i++) + { + GLfloat TH = (i * width) + (width/4); + int oon = orim->npoints; + int oin = irim->npoints; + +# undef PUSH +# define PUSH(OPR,IPR,PTH) \ + orim->points[orim->npoints].x = cos(TH+th[(PTH)]) * r[(OPR)]; \ + orim->points[orim->npoints].y = sin(TH+th[(PTH)]) * r[(OPR)]; \ + orim->npoints++; \ + irim->points[irim->npoints].x = cos(TH+th[(PTH)]) * r[(IPR)]; \ + irim->points[irim->npoints].y = sin(TH+th[(PTH)]) * r[(IPR)]; \ + irim->npoints++ + + if (g->size == INVOLUTE_SMALL) + { + PUSH(3, 4, 0); /* tooth left 1 */ + PUSH(0, 4, 4); /* tooth top middle */ + } + else if (g->size == INVOLUTE_MEDIUM) + { + PUSH(3, 4, 0); /* tooth left 1 */ + PUSH(0, 4, 3); /* tooth top left */ + PUSH(0, 4, 5); /* tooth top right */ + PUSH(3, 4, 8); /* tooth right 3 */ + } + else if (g->size == INVOLUTE_LARGE) + { + PUSH(3, 4, 0); /* tooth left 1 */ + PUSH(2, 4, 1); /* tooth left 2 */ + PUSH(1, 4, 2); /* tooth left 3 */ + PUSH(0, 4, 3); /* tooth top left */ + PUSH(0, 4, 5); /* tooth top right */ + PUSH(1, 4, 6); /* tooth right 1 */ + PUSH(2, 4, 7); /* tooth right 2 */ + PUSH(3, 4, 8); /* tooth right 3 */ + PUSH(3, 4, 9); /* gap top */ + } + else + abort(); +# undef PUSH + + if (i == 0 && orim->npoints > ppt) abort(); /* go update "ppt"! */ + + if (g->inverted_p) + { + int start, end, j; + start = oon; + end = orim->npoints; + for (j = 0; j < (end-start)/2; j++) + { + XYZ swap = orim->points[end-j-1]; + orim->points[end-j-1] = orim->points[start+j]; + orim->points[start+j] = swap; + } + + start = oin; + end = irim->npoints; + for (j = 0; j < (end-start)/2; j++) + { + XYZ swap = irim->points[end-j-1]; + irim->points[end-j-1] = irim->points[start+j]; + irim->points[start+j] = swap; + } + } + } + + tooth_normals (orim, g->tooth_slope); + tooth_normals (irim, 0); + + if (g->inverted_p) /* flip the normals */ + { + for (i = 0; i < orim->npoints; i++) + { + orim->fnormals[i].x = -orim->fnormals[i].x; + orim->fnormals[i].y = -orim->fnormals[i].y; + orim->fnormals[i].z = -orim->fnormals[i].z; + + orim->pnormals[i].x = -orim->pnormals[i].x; + orim->pnormals[i].y = -orim->pnormals[i].y; + orim->pnormals[i].z = -orim->pnormals[i].z; + } + + for (i = 0; i < irim->npoints; i++) + { + irim->fnormals[i].x = -irim->fnormals[i].x; + irim->fnormals[i].y = -irim->fnormals[i].y; + irim->fnormals[i].z = -irim->fnormals[i].z; + + irim->pnormals[i].x = -irim->pnormals[i].x; + irim->pnormals[i].y = -irim->pnormals[i].y; + irim->pnormals[i].z = -irim->pnormals[i].z; + } + } +} + + +/* Which of the gear's inside rings is the biggest? + */ +int +involute_biggest_ring (gear *g, double *posP, double *sizeP, double *heightP) +{ + double r0 = (g->r - g->tooth_h/2); + double r1 = g->inner_r; + double r2 = g->inner_r2; + double r3 = g->inner_r3; + double w1 = (r1 ? r0 - r1 : r0); + double w2 = (r2 ? r1 - r2 : 0); + double w3 = (r3 ? r2 - r3 : 0); + double h1 = g->thickness; + double h2 = g->thickness2; + double h3 = g->thickness3; + + if (g->spokes) w2 = 0; + + if (w1 > w2 && w1 > w3) + { + if (posP) *posP = (r0+r1)/2; + if (sizeP) *sizeP = w1; + if (heightP) *heightP = h1; + return 0; + } + else if (w2 > w1 && w2 > w3) + { + if (posP) *posP = (r1+r2)/2; + if (sizeP) *sizeP = w2; + if (heightP) *heightP = h2; + return 1; + } + else + { + if (posP) *posP = (r2+r3)/2; + if (sizeP) *sizeP = w3; + if (heightP) *heightP = h3; + return 1; + } +} + + +/* Renders all teeth of a gear. + */ +static int +draw_gear_teeth (gear *g, Bool wire_p) +{ + int polys = 0; + int i; + + GLfloat z1 = -g->thickness/2; + GLfloat z2 = g->thickness/2; + GLfloat s1 = 1 + (g->thickness * g->tooth_slope / 2); + GLfloat s2 = 1 - (g->thickness * g->tooth_slope / 2); + + tooth_face orim, irim; + gear_teeth_geometry (g, &orim, &irim); + + glMaterialfv (GL_FRONT, GL_AMBIENT_AND_DIFFUSE, g->color); + + /* Draw the outer rim (the teeth) + (In wire mode, this draws just the upright lines.) + */ + glFrontFace (g->inverted_p ? GL_CCW : GL_CW); + glBegin (wire_p ? GL_LINES : GL_QUAD_STRIP); + for (i = 0; i < orim.npoints; i++) + { + glNormal3f (orim.pnormals[i].x, orim.pnormals[i].y, orim.pnormals[i].z); + glVertex3f (s1*orim.points[i].x, s1*orim.points[i].y, z1); + glVertex3f (s2*orim.points[i].x, s2*orim.points[i].y, z2); + + /* Show the face normal vectors */ + if (wire_p && show_normals_p) + { + XYZ n = orim.fnormals[i]; + int a = i; + int b = (i == orim.npoints-1 ? 0 : i+1); + GLfloat x = (orim.points[a].x + orim.points[b].x) / 2; + GLfloat y = (orim.points[a].y + orim.points[b].y) / 2; + GLfloat z = (z1 + z2) / 2; + glVertex3f (x, y, z); + glVertex3f (x + n.x, y + n.y, z + n.z); + } + + /* Show the vertex normal vectors */ + if (wire_p && show_normals_p) + { + XYZ n = orim.pnormals[i]; + GLfloat x = orim.points[i].x; + GLfloat y = orim.points[i].y; + GLfloat z = (z1 + z2) / 2; + glVertex3f (x, y, z); + glVertex3f (x + n.x, y + n.y, z + n.z); + } + } + + if (!wire_p) /* close the quad loop */ + { + glNormal3f (orim.pnormals[0].x, orim.pnormals[0].y, orim.pnormals[0].z); + glVertex3f (s1*orim.points[0].x, s1*orim.points[0].y, z1); + glVertex3f (s2*orim.points[0].x, s2*orim.points[0].y, z2); + } + polys += orim.npoints; + glEnd(); + + /* Draw the outer rim circles, in wire mode */ + if (wire_p) + { + glBegin (GL_LINE_LOOP); + for (i = 0; i < orim.npoints; i++) + glVertex3f (s1*orim.points[i].x, s1*orim.points[i].y, z1); + glEnd(); + glBegin (GL_LINE_LOOP); + for (i = 0; i < orim.npoints; i++) + glVertex3f (s2*orim.points[i].x, s2*orim.points[i].y, z2); + glEnd(); + } + + /* Draw the inner rim (the hole) + (In wire mode, this draws just the upright lines.) + */ + glFrontFace (g->inverted_p ? GL_CW : GL_CCW); + glBegin (wire_p ? GL_LINES : GL_QUAD_STRIP); + for (i = 0; i < irim.npoints; i++) + { + glNormal3f(-irim.pnormals[i].x, -irim.pnormals[i].y,-irim.pnormals[i].z); + glVertex3f (irim.points[i].x, irim.points[i].y, z1); + glVertex3f (irim.points[i].x, irim.points[i].y, z2); + + /* Show the face normal vectors */ + if (wire_p && show_normals_p) + { + XYZ n = irim.fnormals[i]; + int a = i; + int b = (i == irim.npoints-1 ? 0 : i+1); + GLfloat x = (irim.points[a].x + irim.points[b].x) / 2; + GLfloat y = (irim.points[a].y + irim.points[b].y) / 2; + GLfloat z = (z1 + z2) / 2; + glVertex3f (x, y, z); + glVertex3f (x - n.x, y - n.y, z); + } + + /* Show the vertex normal vectors */ + if (wire_p && show_normals_p) + { + XYZ n = irim.pnormals[i]; + GLfloat x = irim.points[i].x; + GLfloat y = irim.points[i].y; + GLfloat z = (z1 + z2) / 2; + glVertex3f (x, y, z); + glVertex3f (x - n.x, y - n.y, z); + } + } + + if (!wire_p) /* close the quad loop */ + { + glNormal3f (-irim.pnormals[0].x,-irim.pnormals[0].y,-irim.pnormals[0].z); + glVertex3f (irim.points[0].x, irim.points[0].y, z1); + glVertex3f (irim.points[0].x, irim.points[0].y, z2); + } + polys += irim.npoints; + glEnd(); + + /* Draw the inner rim circles, in wire mode + */ + if (wire_p) + { + glBegin (GL_LINE_LOOP); + for (i = 0; i < irim.npoints; i++) + glVertex3f (irim.points[i].x, irim.points[i].y, z1); + glEnd(); + glBegin (GL_LINE_LOOP); + for (i = 0; i < irim.npoints; i++) + glVertex3f (irim.points[i].x, irim.points[i].y, z2); + glEnd(); + } + + /* Draw the side (the flat bit) + */ + if (!wire_p || wire_all_p) + { + GLfloat z; + if (irim.npoints != orim.npoints) abort(); + for (z = z1; z <= z2; z += z2-z1) + { + GLfloat s = (z == z1 ? s1 : s2); + glFrontFace (((z == z1) ^ g->inverted_p) ? GL_CCW : GL_CW); + glNormal3f (0, 0, z); + glBegin (wire_p ? GL_LINES : GL_QUAD_STRIP); + for (i = 0; i < orim.npoints; i++) + { + glVertex3f (s*orim.points[i].x, s*orim.points[i].y, z); + glVertex3f ( irim.points[i].x, irim.points[i].y, z); + } + if (!wire_p) /* close the quad loop */ + { + glVertex3f (s*orim.points[0].x, s*orim.points[0].y, z); + glVertex3f ( irim.points[0].x, irim.points[0].y, z); + } + polys += orim.npoints; + glEnd(); + } + } + + free (irim.points); + free (irim.fnormals); + free (irim.pnormals); + + free (orim.points); + free (orim.fnormals); + free (orim.pnormals); + + return polys; +} + + +/* Render one gear, unrotated at 0,0. + Returns the number of polygons. + */ +int +draw_involute_gear (gear *g, Bool wire_p) +{ + int polys = 0; + + static const GLfloat spec[4] = {1.0, 1.0, 1.0, 1.0}; + GLfloat shiny = 128.0; + + glMaterialfv (GL_FRONT, GL_SPECULAR, spec); + glMateriali (GL_FRONT, GL_SHININESS, shiny); + glMaterialfv (GL_FRONT, GL_AMBIENT_AND_DIFFUSE, g->color); + glColor3f (g->color[0], g->color[1], g->color[2]); + + if (wire_p > 1) + polys += draw_involute_schematic (g, wire_p); + else + { + glPushMatrix(); + glRotatef (g->wobble, 1, 0, 0); + polys += draw_gear_teeth (g, wire_p); + polys += draw_gear_interior (g, wire_p); + polys += draw_gear_nubs (g, wire_p); + glPopMatrix(); + } + return polys; +} diff --git a/hacks/glx/involute.h b/hacks/glx/involute.h new file mode 100644 index 00000000..34144425 --- /dev/null +++ b/hacks/glx/involute.h @@ -0,0 +1,77 @@ +/* involute, Copyright (c) 2004-2007 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. + * + * Utilities for rendering OpenGL gears with involute teeth. + */ + +#ifndef __GEAR_INVOLUTE_H__ +#define __GEAR_INVOLUTE_H__ + +typedef struct { + unsigned long id; /* unique name */ + double x, y, z; /* position */ + double r; /* radius of the gear, at middle of teeth */ + double th; /* rotation (degrees) */ + + GLint nteeth; /* how many teeth */ + double tooth_w, tooth_h; /* size of teeth */ + + double tooth_slope; /* 0 for normal right-angle gear; 1 = 45 deg. */ + double inner_r; /* radius of the (larger) inside hole */ + double inner_r2; /* radius of the (smaller) inside hole, if any */ + double inner_r3; /* yet another */ + + double thickness; /* height of the edge */ + double thickness2; /* height of the (smaller) inside disc if any */ + double thickness3; /* yet another */ + int spokes; /* how many spokes inside, if any */ + int nubs; /* how many little nubbly bits, if any */ + double spoke_thickness; /* spoke versus hole */ + double wobble; /* factory defect! */ + int motion_blur_p; /* whether it's spinning too fast to draw */ + int polygons; /* how many polys in this gear */ + + double ratio; /* gearing ratio with previous gears */ + double rpm; /* approximate revolutions per minute */ + + Bool inverted_p; /* whether this gear has teeth on the inside */ + Bool base_p; /* whether this gear begins a new train */ + int coax_p; /* whether this is one of a pair of bound gears. + 1 for first, 2 for second. */ + double coax_displacement; /* distance between gear planes */ + + double coax_thickness; /* thickness of the other gear in the pair */ + + enum { INVOLUTE_SMALL, + INVOLUTE_MEDIUM, + INVOLUTE_LARGE } size; /* Controls complexity of mesh. */ + GLfloat color[4]; + GLfloat color2[4]; + + GLuint dlist; +} gear; + +/* Render one gear, unrotated at 0,0. + Returns the number of polygons. + */ +extern int draw_involute_gear (gear *g, Bool wire_p); + +/* Draws a much simpler representation of a gear. + Returns the number of polygons. + */ +extern int draw_involute_schematic (gear *g, Bool wire_p); + +/* Which of the gear's inside rings is the biggest? + */ +extern int involute_biggest_ring (gear *g, + double *posP, double *sizeP, + double *heightP); + +#endif /* __GEAR_INVOLUTE_H__ */ diff --git a/hacks/glx/jigglypuff.c b/hacks/glx/jigglypuff.c new file mode 100644 index 00000000..a0f6b76b --- /dev/null +++ b/hacks/glx/jigglypuff.c @@ -0,0 +1,1089 @@ +/* jigglypuff - a most, most, unfortunate screensaver. + * + * Copyright (c) 2003 Keith Macleod (kmacleod@primus.ca) + * + * 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. + * + * Draws all varieties of obscene, spastic, puffy balls + * orbiting lazily about the screen. More of an accident + * than anything else. + * + * Apologies to anyone who thought they were getting a Pokemon + * out of this. + * + * Of course, if you modify it to do something interesting and/or + * funny, I'd appreciate receiving a copy. + * + * 04/06/2003 - Oops, figured out what was wrong with the sphere + * mapping. I had assumed it was done in model space, + * but of course I was totally wrong... Eye space you + * say? Yup. km + * + * 03/31/2003 - Added chrome to the color options. The mapping + * is anything but 'correct', but it's a pretty good + * effect anyways, as long as the surface is jiggling + * enough that you can't tell. Sure, it seems kind of odd + * that it's reflecting a sky that's obviously not there, + * but who has time to worry about silly details like + * that? Not me, ah rekkin'. km + * + */ + +#ifdef STANDALONE +# define DEFAULTS "*delay: 20000\n" \ + "*showFPS: False\n" \ + "*wireframe: False\n" \ + +# define refresh_jigglypuff 0 +# define release_jigglypuff 0 +# include "xlockmore.h" +#else +# include "xlock.h" +#endif + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include "xpm-ximage.h" +#include "gltrackball.h" +#include "../images/jigglymap.xpm" + +#ifdef USE_GL + + +#define DEF_COLOR "cycle" +#define DEF_SHININESS "100" +#define DEF_COMPLEXITY "2" +#define DEF_SPEED "500" +#define DEF_DISTANCE "100" +#define DEF_HOLD "800" +#define DEF_SPHERISM "75" +#define DEF_DAMPING "500" +#define DEF_RANDOM "True" +#define DEF_TETRA "False" +#define DEF_SPOOKY "0" + +#ifndef max +#define max(a,b) (((a)>(b))?(a):(b)) +#define min(a,b) (((a)<(b))?(a):(b)) +#endif + +/* Why isn't RAND_MAX correct in the first place? */ +#define REAL_RAND_MAX (2.0*(float)RAND_MAX) + +static int spherism; +static int hold; +static int distance; +static int damping; + +static int complexity; +static int speed; + +static int do_tetrahedron; +static int spooky; +static char *color; +static int shininess; + +static int random_parms; + +typedef struct solid solid; + +typedef struct { + float stable_distance; + float hold_strength; + float spherify_strength; + float damping_velocity; + float damping_factor; + + int do_wireframe; + int spooky; + int color_style; + GLint shininess; + GLfloat jiggly_color[4]; + GLfloat color_dir[3]; + + solid *shape; + + trackball_state *trackball; + int button_down; + + float angle; + float axis; + float speed; + + GLXContext *glx_context; +} jigglystruct; + +static jigglystruct *jss = NULL; + +static XrmOptionDescRec opts[] = { + {"-random", ".Jigglypuff.random", XrmoptionNoArg, "true"}, + {"+random", ".Jigglypuff.random", XrmoptionNoArg, "false"}, + {"-tetra", ".Jigglypuff.tetra", XrmoptionNoArg, "true"}, + {"+tetra", ".Jigglypuff.tetra", XrmoptionNoArg, "false"}, + {"-spooky", ".Jigglypuff.spooky", XrmoptionSepArg, "0"}, + {"-color", ".Jigglypuff.color", XrmoptionSepArg, DEF_COLOR}, + {"-shininess", ".Jigglypuff.shininess", XrmoptionSepArg, DEF_SHININESS}, + {"-complexity", ".Jigglypuff.complexity", XrmoptionSepArg, DEF_COMPLEXITY}, + {"-speed", ".Jigglypuff.speed", XrmoptionSepArg, DEF_SPEED}, + {"-spherism", ".Jigglypuff.spherism", XrmoptionSepArg, DEF_SPHERISM}, + {"-hold", ".Jigglypuff.hold", XrmoptionSepArg, DEF_HOLD}, + {"-distance", "Jigglypuff.distance", XrmoptionSepArg, DEF_DISTANCE}, + {"-damping", "Jigglypuff.damping", XrmoptionSepArg, DEF_DAMPING} +}; + +static argtype vars[] = { + {&random_parms, "random", "Random", DEF_RANDOM, t_Bool}, + {&do_tetrahedron, "tetra", "Tetra", DEF_TETRA, t_Bool}, + {&spooky, "spooky", "Spooky", DEF_SPOOKY, t_Int}, + {&color, "color", "Color", DEF_COLOR, t_String}, + {&shininess, "shininess", "Shininess", DEF_SHININESS, t_Int}, + {&complexity, "complexity", "Complexity", DEF_COMPLEXITY, t_Int}, + {&speed, "speed", "Speed", DEF_SPEED, t_Int}, + {&spherism, "spherism", "Spherism", DEF_SPHERISM, t_Int}, + {&hold, "hold", "Hold", DEF_HOLD, t_Int}, + {&distance, "distance", "Distance", DEF_DISTANCE, t_Int}, + {&damping, "damping", "Damping", DEF_DAMPING, t_Int} +}; + +#undef countof +#define countof(x) ((int)(sizeof(x)/sizeof(*(x)))) + +ENTRYPOINT ModeSpecOpt jigglypuff_opts = {countof(opts), opts, countof(vars), vars, NULL}; + +#define COLOR_STYLE_NORMAL 0 +#define COLOR_STYLE_CYCLE 1 +#define COLOR_STYLE_CLOWNBARF 2 +#define COLOR_STYLE_FLOWERBOX 3 +#define COLOR_STYLE_CHROME 4 + +#define CLOWNBARF_NCOLORS 5 + +static const GLfloat clownbarf_colors[CLOWNBARF_NCOLORS][4] = { + {0.7, 0.7, 0.0, 1.0}, + {0.8, 0.1, 0.1, 1.0}, + {0.1, 0.1, 0.8, 1.0}, + {0.9, 0.9, 0.9, 1.0}, + {0.0, 0.0, 0.0, 1.0} +}; + +static const GLfloat flowerbox_colors[4][4] = { + {0.7, 0.7, 0.0, 1.0}, + {0.9, 0.0, 0.0, 1.0}, + {0.0, 0.9, 0.0, 1.0}, + {0.0, 0.0, 0.9, 1.0}, +}; + +# if 0 /* I am not even going to *try* and make this bullshit compile + without warning under gcc -std=c89 -pedantic. -jwz. */ +#ifdef DEBUG +# ifdef __GNUC__ /* GCC style */ +#define _DEBUG(msg, args...) do { \ + fprintf(stderr, "%s : %d : " msg ,__FILE__,__LINE__ ,##args); \ +} while(0) +# else /* C99 standard style */ +#define _DEBUG(msg, ...) do { \ + fprintf(stderr, "%s : %d : " msg ,__FILE__,__LINE__,__VA_ARGS__); \ +} while(0) +# endif +#else +# ifdef __GNUC__ /* GCC style */ +#define _DEBUG(msg, args...) +# else /* C99 standard style */ +#define _DEBUG(msg, ...) +# endif +#endif +#endif /* 0 */ + +/* This is all the half-edge b-rep code (as well as basic geometry) */ +typedef struct face face; +typedef struct edge edge; +typedef struct hedge hedge; +typedef struct vertex vertex; +typedef GLfloat coord; +typedef coord vector[3]; + +struct solid { + face *faces; + edge *edges; + vertex *vertices; +}; + +struct face { + solid *s; + hedge *start; + const GLfloat *color; + face *next; +}; + +struct edge { + solid *s; + hedge *left; + hedge *right; + edge *next; +}; + +struct hedge { + face *f; + edge *e; + vertex *vtx; + hedge *next; + hedge *prev; +}; + +struct vertex { + solid *s; + hedge *h; + vector v; + vector n; + vector f; + vector vel; + vertex *next; +}; + +static inline void vector_init(vector v, coord x, coord y, coord z) +{ + v[0] = x; + v[1] = y; + v[2] = z; +} + +static inline void vector_copy(vector d, vector s) +{ + d[0] = s[0]; + d[1] = s[1]; + d[2] = s[2]; +} + +static inline void vector_add(vector v1, vector v2, vector v) +{ + vector_init(v, v1[0]+v2[0], v1[1]+v2[1], v1[2]+v2[2]); +} + +static inline void vector_add_to(vector v1, vector v2) +{ + v1[0] += v2[0]; + v1[1] += v2[1]; + v1[2] += v2[2]; +} + +static inline void vector_sub(vector v1, vector v2, vector v) +{ + vector_init(v, v1[0]-v2[0], v1[1]-v2[1], v1[2]-v2[2]); +} + +static inline void vector_scale(vector v, coord s) +{ + v[0] *= s; + v[1] *= s; + v[2] *= s; +} + +static inline coord dot(vector v1, vector v2) +{ + return v1[0]*v2[0] + v1[1]*v2[1] + v1[2]*v2[2]; +} + +static inline void cross(vector v1, vector v2, vector v) +{ + vector_init(v, + v1[1]*v2[2] - v2[1]*v1[2], + v1[2]*v2[0] - v2[2]*v1[0], + v1[0]*v2[1] - v2[0]*v1[1]); +} + +static inline coord magnitude2(vector v) +{ + return v[0]*v[0] + v[1]*v[1] + v[2]*v[2]; +} + +static inline coord magnitude(vector v) +{ + return sqrt(v[0]*v[0] + v[1]*v[1] + v[2]*v[2]); +} + +static inline void normalize(vector v) +{ + coord mag = 1.0/sqrt(v[0]*v[0]+v[1]*v[1]+v[2]*v[2]); + + v[0] *= mag; + v[1] *= mag; + v[2] *= mag; +} + +static inline void normalize_to(vector v, coord m) +{ + coord mag = 1.0/sqrt(v[0]*v[0]+v[1]*v[1]+v[2]*v[2])/m; + + v[0] *= mag; + v[1] *= mag; + v[2] *= mag; +} + +static inline void midpoint(vector v1, vector v2, vector v) +{ + vector_init(v, + v1[0] + 0.5 * (v2[0] - v1[0]), + v1[1] + 0.5 * (v2[1] - v1[1]), + v1[2] + 0.5 * (v2[2] - v1[2])); +} + +static inline hedge *partner(hedge *h) { + if(!h->e) + return NULL; + if(h == h->e->left) { + return h->e->right; + } + else if(h == h->e->right) { + return h->e->left; + } + else { +/* _DEBUG("Inconsistent edge detected. Presumably, this is a bug. Exiting.\n", NULL); */ + exit(-1); + } +} + +static vertex *vertex_new(solid *s, vector v) +{ + vertex *vtx = (vertex*)malloc(sizeof(vertex)); + + if(!vtx) + return NULL; + vtx->s = s; + vtx->next = s->vertices; + s->vertices = vtx; + vector_copy(vtx->v, v); + vector_init(vtx->f, 0, 0, 0); + vector_init(vtx->vel, 0, 0, 0); + return vtx; +} + +/* insert a new halfedge after hafter. this is low-level, + * i.e. it is a helper for the split_* functions, which + * maintain the consistency of the solid. + */ +static hedge *hedge_new(hedge *hafter, vertex *vtx) +{ + hedge *h = (hedge*)malloc(sizeof(hedge)); + + if(!h) { +/* _DEBUG("Out of memory in hedge_new()\n",NULL); */ + return NULL; + } + h->f = hafter->f; + h->vtx = vtx; + h->e = NULL; + h->prev = hafter; + h->next = hafter->next; + hafter->next = h; + h->next->prev = h; + return h; +} + +static edge *edge_new(solid *s) +{ + edge *e = (edge*)malloc(sizeof(edge)); + if(!e) { +/* _DEBUG("Out of memory in edge_new()\n",NULL);*/ + exit(-1); + } + e->next = s->edges; + s->edges = e; + e-> s = s; + e->left = e->right = NULL; + return e; +} + +static face *face_new(solid *s, hedge *h) +{ + face *f = (face*)malloc(sizeof(face)); + if(!f) { +/* _DEBUG("Out of memory in face_new()",NULL);*/ + exit(-1); + } + f->s = s; + f->start = h; + f->next = s->faces; + s->faces = f; + return f; +} + +/* split vertex vtx, creating a new edge after v on f + * that goes to a new vertex at v, adjoining whatever + * face is on the other side of the halfedge attached to + * v on f. + * Assumptions: + * there are at least 2 faces. + * partner(h)->next->vtx == vtx + * Post-assumptions: + * the new halfedge will be inserted AFTER the indicated + * halfedge. This means that f->start is guaranteed not to + * change. + * the vertex returned will have h==. + */ + +static vertex *vertex_split(hedge *h, vector v) +{ + hedge *h2, *hn1, *hn2; + vertex *vtxn; + edge *en; + face *f1; + + f1 = h->f; + h2 = partner(h); + + vtxn = vertex_new(f1->s, v); + hn1 = hedge_new(h, vtxn); + vtxn->h = hn1; + hn2 = hedge_new(h2, vtxn); + hn2->e = h->e; + + if(h2->e->left == h2) + h2->e->left = hn2; + else + h2->e->right = hn2; + + en = edge_new(f1->s); + en->left = hn1; + en->right = h2; + hn1->e = en; + h2->e = en; + return vtxn; +} + +static face *face_split(face *f, hedge *h1, hedge *h2) +{ + hedge *hn1, *hn2, *tmp; + edge *en; + face *fn; + + if(h1->f != f || h2->f != f) { +/* _DEBUG("Whoah, cap'n, yer usin' a bad halfedge!\n",NULL);*/ + exit(-1); + } + if(h1 == h2) { +/* _DEBUG("Trying to split a face at a single vertex\n",NULL);*/ + exit(-1); + } + /* close the loops */ + h1->prev->next = h2; + h2->prev->next = h1; + tmp = h1->prev; + h1->prev = h2->prev; + h2->prev = tmp; + /* insert halfedges & create edge */ + hn1 = hedge_new(h2->prev, h1->vtx); + hn2 = hedge_new(h1->prev, h2->vtx); + en = edge_new(f->s); + en->left = hn1; + en->right = hn2; + hn1->e = en; + hn2->e = en; + + /* make the new face, first find out which hedge is contained + * in the original face, then start the new face at the other */ + tmp = f->start; + while(tmp != h1 && tmp != h2) + tmp = tmp->next; + tmp = (tmp == h1) ? h2 : h1 ; + fn = face_new(f->s, tmp); + do { + tmp->f = fn; + tmp = tmp->next; + } while(tmp != fn->start); + fn->color = f->color; + return fn; +} + +static solid *solid_new(vector where) +{ + solid *s = (solid*)malloc(sizeof(solid)); + face *f1, *f2; + edge *e; + vertex *vtx; + hedge *h1,*h2; + + s->faces = NULL; + s->edges = NULL; + s->vertices = NULL; + + h1 = (hedge*)malloc(sizeof(hedge)); + h2 = (hedge*)malloc(sizeof(hedge)); + h1->next = h1->prev = h1; + h2->next = h2->prev = h2; + + vtx = vertex_new(s, where); + vtx->h = h1; + h1->vtx = vtx; + h2->vtx = vtx; + + e = edge_new(s); + e->left = h1; + e->right = h2; + h1->e = e; + h2->e = e; + + f1 = face_new(s, h1); + f2 = face_new(s, h2); + h1->f = f1; + h2->f = f2; + + return s; +} + +/* This is all the code directly related to constructing the jigglypuff */ +static void face_tessel2(face *f) +{ + hedge *h1=f->start->prev, *h2=f->start->next; + + if(h1->next == h1) + return; + while(h2 != h1 && h2->next != h1) { + f = face_split(f, h1, h2); + h1 = f->start; + h2 = f->start->next->next; + } +} + +/* This will only work with solids composed entirely of + * triangular faces. It first add a vertex to the middle + * of each edge, then walks the faces, connecting the + * dots. + * I'm abusing the fact that new faces and edges are always + * added at the head of the list. If that ever changes, + * this is borked. + */ +static void solid_tesselate(solid *s) +{ + edge *e = s->edges; + face *f = s->faces; + + while(e) { + vector v; + midpoint(e->left->vtx->v, e->right->vtx->v, v); + vertex_split(e->left, v); + e = e->next; + } + while(f) { + face_tessel2(f); + f=f->next; + } +} + +static void solid_spherify(solid * s, coord size) +{ + vertex *vtx = s->vertices; + + while(vtx) { + normalize_to(vtx->v, size); + vtx = vtx->next; + } +} + +static solid *tetrahedron(jigglystruct *js) +{ + solid *s; + vertex *vtx; + vector v; + hedge *h; + face *f; + int i; + + vector_init(v, 1, 1, 1); + s = solid_new(v); + vector_init(v, -1, -1, 1); + h = s->faces->start; + vtx = vertex_split(h, v); + vector_init(v, -1, 1, -1); + vtx = vertex_split(vtx->h, v); + h = vtx->h; + f = face_split(s->faces, h, h->prev); + vector_init(v, 1, -1, -1); + vertex_split(f->start, v); + f = s->faces->next->next; + h = f->start; + face_split(f, h, h->next->next); + + if(js->color_style == COLOR_STYLE_FLOWERBOX) { + f = s->faces; + for(i=0; i<4; i++) { + f->color = flowerbox_colors[i]; + f = f->next; + } + } + + return s; +} + +static solid *tesselated_tetrahedron(coord size, int iter, jigglystruct *js) { + solid *s = tetrahedron(js); + int i; + + for(i=0; ifaces; + while(f) { + f->color = clownbarf_colors[random() % CLOWNBARF_NCOLORS]; + f = f->next; + } +} + +/* Here be the rendering code */ + +static inline void vertex_calcnormal(vertex *vtx, jigglystruct *js) +{ + hedge *start = vtx->h, *h=start; + + vector_init(vtx->n, 0, 0, 0); + do { + vector u, v, norm; + vector_sub(h->prev->vtx->v, vtx->v, u); + vector_sub(h->next->vtx->v, vtx->v, v); + cross(u, v, norm); + vector_add_to(vtx->n, norm); + h = partner(h)->next; + } while(h != start); + if(!js->spooky) + normalize(vtx->n); + else + vector_scale(vtx->n, js->spooky); +} + +static inline void vertex_render(vertex *vtx, jigglystruct *js) +{ + glNormal3fv(vtx->n); + glVertex3fv(vtx->v); +} + +/* This can be optimized somewhat due to the fact that all + * the faces are triangles. I haven't actually tested to + * see what the cost is of calling glBegin/glEnd for each + * triangle. + */ +static inline int face_render(face *f, jigglystruct *js) +{ + hedge *h1, *h2, *hend; + int polys = 0; + + h1 = f->start; + hend = h1->prev; + h2 = h1->next; + + if(js->color_style == COLOR_STYLE_FLOWERBOX || + js->color_style == COLOR_STYLE_CLOWNBARF) + glColor4fv(f->color); + glBegin(GL_TRIANGLES); + while(h1 != hend && h2 !=hend) { + vertex_render(h1->vtx, js); + vertex_render(h2->vtx, js); + vertex_render(hend->vtx, js); + h1 = h2; + h2 = h1->next; + polys++; + } + glEnd(); + return polys; +} + +static int jigglypuff_render(jigglystruct *js) +{ + int polys = 0; + face *f = js->shape->faces; + vertex *vtx = js->shape->vertices; + + while(vtx) { + vertex_calcnormal(vtx, js); + vtx = vtx->next; + } + while(f) { + polys += face_render(f, js); + f=f->next; + } + return polys; +} + +/* This is the jiggling code */ + +/* stable distance when subdivs == 4 */ +#define STABLE_DISTANCE 0.088388347648 + +static void update_shape(jigglystruct *js) +{ + vertex *vtx = js->shape->vertices; + edge *e = js->shape->edges; + vector zero; + + vector_init(zero, 0, 0, 0); + + /* sum all the vertex-vertex forces */ + while(e) { + vector f; + coord mag; + vector_sub(e->left->vtx->v, e->right->vtx->v, f); + mag = js->stable_distance - magnitude(f); + vector_scale(f, mag); + vector_add_to(e->left->vtx->f, f); + vector_sub(zero, f, f); + vector_add_to(e->right->vtx->f, f); + e = e->next; + } + + /* scale back the v-v force and add the spherical force + * then add the result to the vertex velocity, damping + * if necessary. Finally, move the vertex */ + while(vtx) { + coord mag; + vector to_sphere; + vector_scale(vtx->f, js->hold_strength); + vector_copy(to_sphere, vtx->v); + mag = 1 - magnitude(to_sphere); + vector_scale(to_sphere, mag * js->spherify_strength); + vector_add_to(vtx->f, to_sphere); + vector_add_to(vtx->vel, vtx->f); + vector_init(vtx->f, 0, 0, 0); + mag = magnitude2(vtx->vel); + if(mag > js->damping_velocity) + vector_scale(vtx->vel, js->damping_factor); + vector_add_to(vtx->v, vtx->vel); + vtx = vtx->next; + } +} + +/* These are the various initialization routines */ + +static void init_texture(ModeInfo *mi) +{ + XImage *img = xpm_to_ximage(mi->dpy, mi->xgwa.visual, + mi->xgwa.colormap, jigglymap_xpm); + + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, + img->width, img->height, 0, GL_RGBA, + GL_UNSIGNED_BYTE, img->data); + + XDestroyImage(img); +} + +static void setup_opengl(ModeInfo *mi, jigglystruct *js) +{ + const GLfloat lpos0[4] = {-12, 8, 12, 0}; + const GLfloat lpos1[4] = {7, -5, 0, 0}; + const GLfloat lcol0[4] = {0.7f, 0.7f, 0.65f, 1}; + const GLfloat lcol1[4] = {0.3f, 0.2f, 0.1f, 1}; + const GLfloat scolor[4]= {0.9f, 0.9f, 0.9f, 0.5f}; + + glDrawBuffer(GL_BACK); + glShadeModel(GL_SMOOTH); + glEnable(GL_DEPTH_TEST); + + if(js->do_wireframe) { + glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); + } + else { + glCullFace(GL_BACK); + glFrontFace(GL_CW); + glEnable(GL_CULL_FACE); + } + + if(js->color_style != COLOR_STYLE_CHROME) { + glEnable(GL_LIGHTING); + glEnable(GL_LIGHT0); + glEnable(GL_LIGHT1); + + glLightfv(GL_LIGHT0, GL_POSITION, lpos0); + glLightfv(GL_LIGHT1, GL_POSITION, lpos1); + glLightfv(GL_LIGHT0, GL_DIFFUSE, lcol0); + glLightfv(GL_LIGHT1, GL_DIFFUSE, lcol1); + + glEnable(GL_COLOR_MATERIAL); + glColor4fv(js->jiggly_color); + + glMaterialfv(GL_FRONT, GL_SPECULAR, scolor); + glMateriali(GL_FRONT, GL_SHININESS, js->shininess); + } + else { /* chrome */ + init_texture(mi); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_SPHERE_MAP); + glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_SPHERE_MAP); + glEnable(GL_TEXTURE_GEN_S); + glEnable(GL_TEXTURE_GEN_T); + glEnable(GL_TEXTURE_2D); + glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_DECAL); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); + } +} + +static int parse_color(jigglystruct *js) +{ + unsigned int r, g, b; + if(!strcmp(color, "clownbarf")) { + js->color_style = COLOR_STYLE_CLOWNBARF; + return 1; + } + else if(!strcmp(color, "flowerbox")) { + js->color_style = COLOR_STYLE_FLOWERBOX; + return 1; + } +# ifndef HAVE_JWZGLES /* SPHERE_MAP unimplemented */ + else if(!strcmp(color, "chrome")) { + js->color_style = COLOR_STYLE_CHROME; + return 1; + } +# endif + else if(!strcmp(color, "cycle")) { + js->color_style = COLOR_STYLE_CYCLE; + js->jiggly_color[0] = ((float)random()) / REAL_RAND_MAX * 0.7 + 0.3; + js->jiggly_color[1] = ((float)random()) / REAL_RAND_MAX * 0.7 + 0.3; + js->jiggly_color[2] = ((float)random()) / REAL_RAND_MAX * 0.7 + 0.3; + js->jiggly_color[3] = 1.0f; + js->color_dir[0] = ((float)random()) / REAL_RAND_MAX / 100.0; + js->color_dir[1] = ((float)random()) / REAL_RAND_MAX / 100.0; + js->color_dir[2] = ((float)random()) / REAL_RAND_MAX / 100.0; + return 1; + } + else + js->color_style = 0; + if(strlen(color) != 7) + return 0; + if(sscanf(color,"#%02x%02x%02x", &r, &g, &b) != 3) { + return 0; + } + js->jiggly_color[0] = ((float)r)/255; + js->jiggly_color[1] = ((float)g)/255; + js->jiggly_color[2] = ((float)b)/255; + js->jiggly_color[3] = 1.0f; + + return 1; +} + +static void randomize_parameters(jigglystruct *js) { + do_tetrahedron = random() & 1; +# ifndef HAVE_JWZGLES /* #### glPolygonMode other than GL_FILL unimplemented */ + js->do_wireframe = !(random() & 3); +# endif + js->color_style = random() % 5; +# ifdef HAVE_JWZGLES /* #### SPHERE_MAP unimplemented */ + while (js->color_style == COLOR_STYLE_CHROME) + js->color_style = random() % 5;; +# endif + if(js->color_style == COLOR_STYLE_NORMAL + || js->color_style == COLOR_STYLE_CYCLE) { + js->jiggly_color[0] = ((float)random()) / REAL_RAND_MAX * 0.5 + 0.5; + js->jiggly_color[1] = ((float)random()) / REAL_RAND_MAX * 0.5 + 0.5; + js->jiggly_color[2] = ((float)random()) / REAL_RAND_MAX * 0.5 + 0.5; + js->jiggly_color[3] = 1.0f; + if(js->color_style == COLOR_STYLE_CYCLE) { + js->color_dir[0] = ((float)random()) / REAL_RAND_MAX / 100.0; + js->color_dir[1] = ((float)random()) / REAL_RAND_MAX / 100.0; + js->color_dir[2] = ((float)random()) / REAL_RAND_MAX / 100.0; + } + } + if((js->color_style != COLOR_STYLE_CHROME) && (random() & 1)) + js->spooky = (random() % 6) + 4; + else + js->spooky = 0; + js->shininess = random() % 200; + speed = (random() % 700) + 50; + /* It' kind of dull if this is too high when it starts as a sphere */ + spherism = do_tetrahedron ? (random() % 500) + 20 : (random() % 100) + 10; + hold = (random() % 800) + 100; + distance = (random() % 500) + 100; + damping = (random() % 800) + 50; +} + +static void calculate_parameters(jigglystruct *js, int subdivs) { + /* try to compensate for the inherent instability at + * low complexity. */ + float dist_factor = (subdivs == 6) ? 2 : (subdivs == 5) ? 1 : 0.5; + + js->stable_distance = ((float)distance / 500.0) + * (STABLE_DISTANCE / dist_factor); + js->hold_strength = (float)hold / 10000.0; + js->spherify_strength = (float)spherism / 10000.0; + js->damping_velocity = (float)damping / 100000.0; + js->damping_factor = + 0.001/max(js->hold_strength, js->spherify_strength); + + js->speed = (float)speed / 1000.0; +} + +/* The screenhack related functions begin here */ + +ENTRYPOINT Bool jigglypuff_handle_event(ModeInfo *mi, XEvent *event) +{ + jigglystruct *js = &jss[MI_SCREEN(mi)]; + + if(event->xany.type == ButtonPress && + event->xbutton.button == Button1) { + js->button_down = 1; + gltrackball_start(js->trackball, event->xbutton.x, event->xbutton.y, + MI_WIDTH(mi), MI_HEIGHT(mi)); + return True; + } + else if(event->xany.type == ButtonRelease && + event->xbutton.button == Button1) { + js->button_down = 0; + return True; + } + else if (event->xany.type == ButtonPress && + (event->xbutton.button == Button4 || + event->xbutton.button == Button5 || + event->xbutton.button == Button6 || + event->xbutton.button == Button7)) + { + gltrackball_mousewheel (js->trackball, event->xbutton.button, 10, + !!event->xbutton.state); + return True; + } + else if(event->xany.type == MotionNotify && js->button_down) { + gltrackball_track(js->trackball, event->xmotion.x, event->xmotion.y, + MI_WIDTH(mi), MI_HEIGHT(mi)); + return True; + } + return False; +} + +ENTRYPOINT void reshape_jigglypuff(ModeInfo *mi, int width, int height) +{ + GLfloat aspect = (GLfloat)width / (GLfloat)height; + + glViewport(0, 0, width, height); + glMatrixMode(GL_PROJECTION); + glLoadIdentity(); + glFrustum(-0.5*aspect, 0.5*aspect, -0.5, 0.5, 1, 20); +/* glTranslatef(0, 0, -10);*/ +} + +ENTRYPOINT void draw_jigglypuff(ModeInfo *mi) +{ + jigglystruct *js = &jss[MI_SCREEN(mi)]; + + glXMakeCurrent(MI_DISPLAY(mi), MI_WINDOW(mi), *(js->glx_context)); + + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + + glMatrixMode(GL_MODELVIEW); + glLoadIdentity(); + glTranslatef(0,0,-10); + + glRotatef(js->angle, sin(js->axis), cos(js->axis), -sin(js->axis)); + glTranslatef(0, 0, 5); + if(!(js->button_down)) { + if((js->angle += js->speed) >= 360.0f ) { + js->angle -= 360.0f; + } + if((js->axis+=0.01f) >= 2*M_PI ) { + js->axis -= 2*M_PI; + } + } + + /* Do it twice because we don't track the device's orientation. */ + glRotatef( current_device_rotation(), 0, 0, 1); + gltrackball_rotate(js->trackball); + glRotatef(-current_device_rotation(), 0, 0, 1); + + if(js->color_style == COLOR_STYLE_CYCLE) { + int i; + vector_add(js->jiggly_color, js->color_dir, js->jiggly_color); + + for(i=0; i<3; i++) { + if(js->jiggly_color[i] > 1.0 || js->jiggly_color[i] < 0.3) { + js->color_dir[i] = (-js->color_dir[i]); + js->jiggly_color[i] += js->color_dir[i]; + } + } + glColor4fv(js->jiggly_color); + } + + mi->polygon_count = jigglypuff_render(js); + if(MI_IS_FPS(mi)) + do_fps(mi); + glFinish(); + update_shape(js); + glXSwapBuffers(MI_DISPLAY(mi), MI_WINDOW(mi)); +} + +ENTRYPOINT void init_jigglypuff(ModeInfo *mi) +{ + jigglystruct *js; + int subdivs; + + if(!jss) { + jss = (jigglystruct*) + calloc(MI_NUM_SCREENS(mi), sizeof(jigglystruct)); + if(!jss) { + fprintf(stderr, "%s: No..memory...must...abort..\n", progname); + exit(1); + } + } + + js = &jss[MI_SCREEN(mi)]; + + js->do_wireframe = MI_IS_WIREFRAME(mi); +# ifdef HAVE_JWZGLES + js->do_wireframe = 0; /* GL_LINE unimplemented */ +# endif + + js->shininess = shininess; + + subdivs = (complexity==1) ? 4 : (complexity==2) ? 5 + : (complexity==3) ? 6 : 5; + + js->spooky = spooky << (subdivs-3); + + if(!parse_color(js)) { + fprintf(stderr, "%s: Bad color specification: '%s'.\n", progname, color); + exit(-1); + } + + if(random_parms) + randomize_parameters(js); + + js->angle = frand(180); + js->axis = frand(M_PI); + + js->shape = tesselated_tetrahedron(1, subdivs, js); + + if(!do_tetrahedron) + solid_spherify(js->shape, 1); + + if(js->color_style == COLOR_STYLE_CLOWNBARF) + clownbarf_colorize(js->shape); + + calculate_parameters(js, subdivs); + + if((js->glx_context = init_GL(mi)) != NULL) { + glXMakeCurrent(MI_DISPLAY(mi), MI_WINDOW(mi), *(js->glx_context)); + setup_opengl(mi, js); + reshape_jigglypuff(mi, MI_WIDTH(mi), MI_HEIGHT(mi)); + } + else { + MI_CLEARWINDOW(mi); + } + js->trackball = gltrackball_init(); +/* _DEBUG("distance : %f\nhold : %f\nspherify : %f\ndamping : %f\ndfact : %f\n", + js->stable_distance, js->hold_strength, js->spherify_strength, + js->damping_velocity, js->damping_factor); + _DEBUG("wire : %d\nspooky : %d\nstyle : %d\nshininess : %d\n", + js->do_wireframe, js->spooky, js->color_style, js->shininess);*/ +} + +XSCREENSAVER_MODULE ("JigglyPuff", jigglypuff) + +#endif /* USE_GL */ + +/* This is the end of the file */ diff --git a/hacks/glx/jigglypuff.man b/hacks/glx/jigglypuff.man new file mode 100644 index 00000000..4a5f8bf5 --- /dev/null +++ b/hacks/glx/jigglypuff.man @@ -0,0 +1,121 @@ +.TH XScreenSaver 1 "" "X Version 11" +.SH NAME +jigglypuff - save your screen by tormenting your eyes. +.SH SYNOPSIS +.B jigglypuff +[\-display \fIhost:display.screen\fP] +[\-visual \fIvisual\fP] +[\-window] +[\-root] +[-delay \fInumber\fP] +[-cycles \fInumber\fP] +[-wireframe] +[-fps] +[-color \fIcolorspec\fP] +[-spooky] +[-complexity \fIn\fP] +[-speed \fIn\fP] +[-spherism \fIn\fP] +[-hold \fIn\fP] +[-distance \fIn\fP] +[-damping \fIn\fP] +.SH DESCRIPTION +This draws all manners of obscene, spastic, puffy, vaguely ball-shaped +objects orbiting lazily about the screen, with a dizzying array of +mostly pointless options. +.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: 20000 (0.02 seconds.). +.TP 8 +.B \-wireframe +Render in wireframe instead of solid. Default: render solid. +.TP 8 +.B \-fps +Display the current frame rate, CPU load, and polygon count. +.TP 8 +.B -tetra | -no-tetra +Whether to start the shape in the form of a tetrahedron. The default +is to start as a sphere. +.TP 8 +.B -color \fIcolorspec\fP +Available options for colorspec are: cycle, flowerbox, clownpuke, chrome +and #xxxxxx (i.e an (old-style) X color specification.) Default: cycle +.TP 8 +.B -spooky \fIn\fP +This option controls a kind of interesting effect obtained by +using unnormalized normal vectors (how's that for an oxymoron?) in OpenGL. +A value of zero disables the effect. Other values vary the lengths of +the normals proportionally. +Okay, so it's not very spooky. Sue me. +Default: 0 +.TP 8 +.B -complexity \fIn\fP +Valid options are 1, 2, and 3. Everything else is treated as though it +were 2, which is the default. This controls the number of polygons in +the 'thing'. A value of 1 yields 1024, and the values go up in powers +of 4. (i.e. 4096, 16384.) + note: There is an inherent lack of stability +at lower complexity, which can cause the shape to devolve into a 'flying +snotrag'. +.TP 8 +.B -speed \fIn\fP +Controls how fast the blob moves around the screen. Default: 500. +.TP 8 +.B -spherism, -hold, -distance, -damping +These options control the 'jigglyness'. The best way to explain these is +to explain how jigglypuff works. Basically, the shape is a tetrahedron +whose faces are subdivided into a number of triangles, forming a mesh. +Each of the vertices of the mesh has two different forces applied to it: +one proportional to its distance from the surface of a sphere, and one +proportional to the difference of the distance to each of its neighbors +in the mesh to a given ideal distance. In short, one tries to move the +points into the configuration of a sphere, and the other tries to push +them back into a tetrahedron. The catch is that the points have inertia, +so they always overshoot their target, and hence they oscillate. The +magnitudes of the two forces is controlled by the options 'spherism' and +\'hold'; 'distance' specifies the distance the vertices seek to keep from +their neighbors, with 500 corresponding to the size of the start tetrahedron. +e.g. if you were to give the options '-tetra -spherism 0 -distance 500', you +would end up with a stable tetrahedron. The 'damping' option can help to +keep the blob from collapsing or flying apart. The option specifies the +speed at which damping starts, hence lower values mean more damping. +Defaults: spherism: 75; hold: 800; distance: 100; damping: 500. +.TP 8 +.B -random +Probably the only parameter you'l ever need. Overrides almost all of the +parameters with random values. The values affected are: speed, spherism, +hold, distance, damping, spooky, color, wireframe and tetra. +Default: off +.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 2003 by Keith Macleod. 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 +By Keith Macleod diff --git a/hacks/glx/jigsaw.c b/hacks/glx/jigsaw.c new file mode 100644 index 00000000..32ea54f4 --- /dev/null +++ b/hacks/glx/jigsaw.c @@ -0,0 +1,1534 @@ +/* xscreensaver, Copyright (c) 1997-2012 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. + * + * Written as an Xlib program some time in 1997. + * Rewritten as an OpenGL program 24-Aug-2008. + */ + +/* + Currently, we do this: + + - start pieces off screen and move them in. + - when they land, they fill the puzzle grid with a shuffled + puzzle (pieces are rotated, too). + - swap random pairs of pieces until the puzzle is solved. + - scatter the pieces off screen (resulting in black). + - load new image and repeat. + + Another idea would be to show the puzzle being solved the way + a person would do it: + + - start off with black screen. + - assume knowledge of size of grid (position of corners). + - find a corner piece, and place it. + - while puzzle unsolved: + - pick a random piece; + - if it is the correct piece for any open edge, place it; + - if it fits physically in any rotation at any open edge, + place it, then toss it back (show the fake-out). + - if it doesn't fit at all, don't animate it at all. + + This would take a long time to solve, I think... + + An even harder idea would involve building up completed "clumps" + and sliding them around (a coral growth / accretion approach) + */ + +#define DEF_SPEED "1.0" +#define DEF_COMPLEXITY "1.0" +#define DEF_RESOLUTION "100" +#define DEF_THICKNESS "0.06" +#define DEF_WOBBLE "True" +#define DEF_DEBUG "False" + +#define DEF_FONT "-*-helvetica-bold-r-normal-*-240-*" +#define DEFAULTS "*delay: 20000 \n" \ + "*showFPS: False \n" \ + "*font: " DEF_FONT"\n" \ + "*wireframe: False \n" \ + "*desktopGrabber: xscreensaver-getimage -no-desktop %s\n" \ + "*grabDesktopImages: False \n" \ + "*chooseRandomImages: True \n" + + +# define refresh_jigsaw 0 +# define release_jigsaw 0 +#undef countof +#define countof(x) (sizeof((x))/sizeof((*x))) + +#ifdef HAVE_COCOA +# include "jwxyz.h" +#else +# include +# include +# include +#endif + +#include "xlockmore.h" +#include "rotator.h" +#include "gltrackball.h" +#include "spline.h" +#include "normals.h" +#include "grab-ximage.h" +#include "texfont.h" + +#ifdef HAVE_JWZGLES +# include "jwzgles.h" +#else /* !HAVE_JWZGLES */ +# define HAVE_TESS +#endif /* !HAVE_JWZGLES */ + +#undef BELLRAND +#define BELLRAND(n) ((frand((n)) + frand((n)) + frand((n))) / 3) + +#ifdef USE_GL /* whole file */ + +#define TOP 0 +#define RIGHT 1 +#define BOTTOM 2 +#define LEFT 3 + +#define IN -1 +#define FLAT 0 +#define OUT 1 + +typedef struct jigsaw_configuration jigsaw_configuration; + +typedef struct { + double x,y,z,r; /* position and Z rotation (in degrees) */ +} XYZR; + + +typedef struct { + jigsaw_configuration *jc; + int edge[4]; + GLuint dlist; + int polys; + + XYZR home; /* correct position in puzzle */ + XYZR current; /* where it is right now */ + XYZR from, to; /* in transit from A to B */ + double tick; /* 0-1.0, how far from A to B */ + double arc_height; /* height of apex of curved path from A to B */ + double tilt, max_tilt; + +} puzzle_piece; + + +struct jigsaw_configuration { + GLXContext *glx_context; + trackball_state *trackball; + rotator *rot; + Bool button_down_p; + texture_font_data *texfont; + GLuint loading_dlist; + + int puzzle_width; + int puzzle_height; + puzzle_piece *puzzle; + + enum { PUZZLE_LOADING_MSG, + PUZZLE_LOADING, + PUZZLE_UNSCATTER, + PUZZLE_SOLVE, + PUZZLE_SCATTER } state; + double pausing; + double tick_speed; + + GLuint texid; + GLfloat tex_x, tex_y, tex_width, tex_height, aspect; + + GLuint line_thickness; +}; + +static jigsaw_configuration *sps = NULL; + +static GLfloat speed; +static GLfloat complexity_arg; +static int resolution_arg; +static GLfloat thickness_arg; +static Bool wobble_p; +static Bool debug_p; + +static XrmOptionDescRec opts[] = { + { "-speed", ".speed", XrmoptionSepArg, 0 }, + { "-complexity", ".complexity", XrmoptionSepArg, 0 }, + { "-resolution", ".resolution", XrmoptionSepArg, 0 }, + { "-thickness", ".thickness", XrmoptionSepArg, 0 }, + { "-wobble", ".wobble", XrmoptionNoArg, "True" }, + { "+wobble", ".wobble", XrmoptionNoArg, "False" }, + { "-debug", ".debug", XrmoptionNoArg, "True" }, +}; + +static argtype vars[] = { + {&speed, "speed", "Speed", DEF_SPEED, t_Float}, + {&complexity_arg, "complexity", "Complexity", DEF_COMPLEXITY, t_Float}, + {&resolution_arg, "resolution", "Resolution", DEF_RESOLUTION, t_Int}, + {&thickness_arg, "thickness", "Thickness", DEF_THICKNESS, t_Float}, + {&wobble_p, "wobble", "Wobble", DEF_WOBBLE, t_Bool}, + {&debug_p, "debug", "Debug", DEF_DEBUG, t_Bool}, +}; + +ENTRYPOINT ModeSpecOpt jigsaw_opts = {countof(opts), opts, countof(vars), vars, NULL}; + + +/* Returns a spline describing one edge of a puzzle piece of the given length. + */ +static spline * +make_puzzle_curve (int pixels) +{ + double x0 = 0.0000, y0 = 0.0000; + double x1 = 0.3333, y1 = 0.1000; + double x2 = 0.4333, y2 = 0.0333; + double x3 = 0.4666, y3 = -0.0666; + double x4 = 0.3333, y4 = -0.1666; + double x5 = 0.3666, y5 = -0.2900; + double x6 = 0.5000, y6 = -0.3333; + + spline *s = make_spline(20); + s->n_controls = 0; + +# define PT(x,y) \ + s->control_x[s->n_controls] = pixels * (x); \ + s->control_y[s->n_controls] = pixels * (y); \ + s->n_controls++ + PT ( x0, y0); + PT ( x1, y1); + PT ( x2, y2); + PT ( x3, y3); + PT ( x4, y4); + PT ( x5, y5); + PT ( x6, y6); + PT (1-x5, y5); + PT (1-x4, y4); + PT (1-x3, y3); + PT (1-x2, y2); + PT (1-x1, y1); + PT (1-x0, y0); +# undef PT + + compute_spline (s); + return s; +} + + +#ifdef HAVE_TESS + +static void +tess_error_cb (GLenum errorCode) +{ + fprintf (stderr, "%s: tesselation error: %s\n", + progname, gluErrorString(errorCode)); + exit (0); +} + + +static void +tess_combine_cb (GLdouble coords[3], GLdouble *d[4], GLfloat w[4], + GLdouble **dataOut) +{ + GLdouble *new = (GLdouble *) malloc (3 * sizeof(*new)); + new[0] = coords[0]; + new[1] = coords[1]; + new[2] = coords[2]; + *dataOut = new; +} + + +static void +tess_vertex_cb (void *vertex_data, void *closure) +{ + puzzle_piece *p = (puzzle_piece *) closure; + GLdouble *v = (GLdouble *) vertex_data; + GLdouble x = v[0]; + GLdouble y = v[1]; + GLdouble z = v[2]; + + if (p) + { + GLfloat pw = p->jc->puzzle_width; + GLfloat ph = p->jc->puzzle_height; + + GLfloat xx = x / (GLfloat) resolution_arg; /* 0-1 from piece origin */ + GLfloat yy = y / (GLfloat) resolution_arg; + GLdouble tx = (p->home.x + xx) / pw; /* 0-1 from puzzle origin */ + GLdouble ty = (ph - p->home.y - yy) / ph; + + tx = p->jc->tex_x + (tx * p->jc->tex_width); + ty = p->jc->tex_y + (ty * p->jc->tex_height); + + glTexCoord2d (tx, ty); + } + + glVertex3d (x, y, z); +} + +#else /* HAVE_TESS */ + +/* Writes triangles into the array of floats. + Returns the number of floats written (triangles * 9). + */ +static int +make_piece_eighth (jigsaw_configuration *jc, const spline *s, + int resolution, int type, GLfloat *out, + Bool flip_x, Bool flip_y, Bool rotate_p) +{ + GLfloat *oout = out; + int cx = resolution/2; + int cy = resolution/2; + int np = (s->n_points / 2) + 1; + int last_x = -999999, last_y = -999999; + Bool inflected = False; + int i; + + if (type == FLAT) + { + *out++ = cx; + *out++ = 0; + *out++ = 0; + + *out++ = cx; + *out++ = cy; + *out++ = 0; + + *out++ = 0; + *out++ = 0; + *out++ = 0; + + goto END; + } + + for (i = (type == IN ? np-1 : 0); + (type == IN ? i >= 0 : i < np); + i += (type == IN ? -1 : 1)) + { + int x = s->points[i].x; + int y = s->points[i].y; + + if (type == IN) + y = -y; + + if (last_x != -999999) + { + if (!inflected && + (type == IN + ? x >= last_x + : x < last_x)) + { + inflected = True; + + *out++ = cx; + *out++ = cy; + *out++ = 0; + + *out++ = last_x; + *out++ = last_y; + *out++ = 0; + + if (type == IN) + { + cx = 0; + cy = 0; + } + else + { + cy = y; + } + + *out++ = cx; + *out++ = cy; + *out++ = 0; + } + + *out++ = cx; + *out++ = cy; + *out++ = 0; + + *out++ = last_x; + *out++ = last_y; + *out++ = 0; + + *out++ = x; + *out++ = y; + *out++ = 0; + } + + last_x = x; + last_y = y; + } + END: + + { + int count = out - oout; + Bool cw_p; + + if (flip_x) + for (i = 0; i < count; i += 3) + oout[i] = resolution - oout[i]; + + if (flip_y) + for (i = 0; i < count; i += 3) + oout[i+1] = resolution - oout[i+1]; + + cw_p = (type == IN); + if (flip_x) cw_p = !cw_p; + if (flip_y) cw_p = !cw_p; + + if (cw_p) + for (i = 0; i < count; i += 9) + { + GLfloat x1 = oout[i+0]; + GLfloat y1 = oout[i+1]; + GLfloat x2 = oout[i+3]; + GLfloat y2 = oout[i+4]; + GLfloat x3 = oout[i+6]; + GLfloat y3 = oout[i+7]; + oout[i+0] = x2; + oout[i+1] = y2; + oout[i+3] = x1; + oout[i+4] = y1; + oout[i+6] = x3; + oout[i+7] = y3; + } + + if (rotate_p) + for (i = 0; i < count; i += 3) + { + GLfloat x = oout[i]; + GLfloat y = oout[i+1]; + oout[i] = resolution - y; + oout[i+1] = x; + } + + return count; + } +} + +#endif /* !HAVE_TESS */ + + + +/* Draws a puzzle piece. The top/right/bottom/left_type args + indicate the direction the tabs point: 1 for out, -1 for in, 0 for flat. + */ +static int +draw_piece (jigsaw_configuration *jc, puzzle_piece *p, + int resolution, GLfloat thickness, + int top_type, int right_type, + int bottom_type, int left_type, + Bool wire) +{ + spline *s = make_puzzle_curve (resolution); + GLdouble *pts = (GLdouble *) malloc (s->n_points * 4 * 3 * sizeof(*pts)); + int polys = 0; + int i, o; + GLdouble z = resolution * thickness; + + o = 0; + if (top_type == 0) { + pts[o++] = 0; + pts[o++] = 0; + pts[o++] = z; + + pts[o++] = resolution; + pts[o++] = 0; + pts[o++] = z; + } else { + for (i = 0; i < s->n_points; i++) { + pts[o++] = s->points[i].x; + pts[o++] = s->points[i].y * top_type; + pts[o++] = z; + } + } + + if (right_type == 0) { + pts[o++] = resolution; + pts[o++] = resolution; + pts[o++] = z; + } else { + for (i = 1; i < s->n_points; i++) { + pts[o++] = resolution + s->points[i].y * (-right_type); + pts[o++] = s->points[i].x; + pts[o++] = z; + } + } + + if (bottom_type == 0) { + pts[o++] = 0; + pts[o++] = resolution; + pts[o++] = z; + } else { + for (i = 1; i < s->n_points; i++) { + pts[o++] = s->points[s->n_points-i-1].x; + pts[o++] = resolution + s->points[s->n_points-i-1].y * (-bottom_type); + pts[o++] = z; + } + } + + if (left_type == 0) { + pts[o++] = 0; + pts[o++] = 0; + pts[o++] = z; + } else { + for (i = 1; i < s->n_points; i++) { + pts[o++] = s->points[s->n_points-i-1].y * left_type; + pts[o++] = s->points[s->n_points-i-1].x; + pts[o++] = z; + } + } + + { GLfloat ss = 1.0 / resolution; glScalef (ss, ss, ss); } + +# ifndef HAVE_JWZGLES /* #### glPolygonMode other than GL_FILL unimplemented */ + glPolygonMode (GL_FRONT_AND_BACK, wire ? GL_LINE : GL_FILL); +# endif + + if (wire) + { + glDisable (GL_TEXTURE_2D); + glDisable (GL_BLEND); + glDisable (GL_LIGHTING); + } + else + { +# ifdef HAVE_TESS + +# ifndef _GLUfuncptr +# define _GLUfuncptr void(*)(void) +# endif + GLUtesselator *tess = gluNewTess(); + gluTessCallback(tess, GLU_TESS_BEGIN, (_GLUfuncptr)glBegin); + gluTessCallback(tess, GLU_TESS_VERTEX_DATA,(_GLUfuncptr)tess_vertex_cb); + gluTessCallback(tess, GLU_TESS_END, (_GLUfuncptr)glEnd); + gluTessCallback(tess, GLU_TESS_COMBINE, (_GLUfuncptr)tess_combine_cb); + gluTessCallback(tess, GLU_TESS_ERROR, (_GLUfuncptr)tess_error_cb); + + /* front face */ + glEnable (GL_TEXTURE_2D); + glEnable (GL_BLEND); + glEnable (GL_LIGHTING); + glBindTexture(GL_TEXTURE_2D, jc->texid); + glFrontFace (GL_CCW); + glNormal3f (0, 0, 1); + gluTessBeginPolygon (tess, p); + gluTessBeginContour (tess); + for (i = 0; i < o; i += 3) + { + GLdouble *p = pts + i; + gluTessVertex (tess, p, p); + polys++; /* not quite right but close */ + } + gluTessEndContour(tess); + gluTessEndPolygon(tess); + + /* back face */ + glDisable (GL_TEXTURE_2D); + glFrontFace (GL_CW); + glNormal3f (0, 0, -1); + gluTessBeginPolygon (tess, 0); + gluTessBeginContour (tess); + for (i = 0; i < o; i += 3) + { + GLdouble *p = pts + i; + p[2] = -p[2]; + gluTessVertex (tess, p, p); + polys++; /* not quite right but close */ + } + gluTessEndContour(tess); + gluTessEndPolygon(tess); + gluDeleteTess(tess); + + /* Put it back */ + for (i = 0; i < o; i += 3) + { + GLdouble *p = pts + i; + p[2] = -p[2]; + } + +# else /* !HAVE_TESS */ + + GLfloat *tri = (GLfloat *) + (GLfloat *) malloc (s->n_points * 4 * 3 * 3 * sizeof(*pts)); + GLfloat *otri = tri; + int count; + GLdouble zz; + + tri += make_piece_eighth (jc, s, resolution, top_type, tri, 0, 0, 0); + tri += make_piece_eighth (jc, s, resolution, top_type, tri, 1, 0, 0); + tri += make_piece_eighth (jc, s, resolution, left_type, tri, 0, 1, 1); + tri += make_piece_eighth (jc, s, resolution, left_type, tri, 1, 1, 1); + tri += make_piece_eighth (jc, s, resolution, bottom_type, tri, 0, 1, 0); + tri += make_piece_eighth (jc, s, resolution, bottom_type, tri, 1, 1, 0); + tri += make_piece_eighth (jc, s, resolution, right_type, tri, 0, 0, 1); + tri += make_piece_eighth (jc, s, resolution, right_type, tri, 1, 0, 1); + count = (tri - otri) / 9; + + if (! wire) + { + glEnable (GL_TEXTURE_2D); + glEnable (GL_BLEND); + glEnable (GL_LIGHTING); + glBindTexture(GL_TEXTURE_2D, jc->texid); + } + + for (zz = z; zz >= -z; zz -= 2*z) + { + int i; + glFrontFace (zz > 0 ? GL_CCW : GL_CW); + glNormal3f (0, 0, (zz > 0 ? 1 : -1)); + + if (zz < 0) + glDisable (GL_TEXTURE_2D); /* back face */ + + glPushMatrix(); + glTranslatef (0, 0, zz); + + tri = otri; + if (wire) + { + for (i = 0; i < count; i++) + { + glBegin (GL_LINE_LOOP); + glVertex3f (tri[0], tri[1], tri[2]); tri += 3; + glVertex3f (tri[0], tri[1], tri[2]); tri += 3; + glVertex3f (tri[0], tri[1], tri[2]); tri += 3; + glEnd(); + } + } + else + { + GLfloat pw = p->jc->puzzle_width; + GLfloat ph = p->jc->puzzle_height; + GLfloat r = resolution; + + glBegin (GL_TRIANGLES); + for (i = 0; i < count * 3; i++) + { + GLfloat x = *tri++; + GLfloat y = *tri++; + GLfloat z = *tri++; + + /* 0-1 from piece origin */ + GLfloat xx = x / r; + GLfloat yy = y / r; + + /* 0-1 from puzzle origin */ + GLfloat tx = (p->home.x + xx) / pw; + GLfloat ty = (ph - p->home.y - yy) / ph; + + tx = p->jc->tex_x + (tx * p->jc->tex_width); + ty = p->jc->tex_y + (ty * p->jc->tex_height); + + glTexCoord2f (tx, ty); + glVertex3f (x, y, z); + } + glEnd(); + } + + polys += count; + glPopMatrix(); + } + + free (otri); +# endif /* !HAVE_TESS */ + } + + /* side faces */ + + glFrontFace (GL_CCW); + glBegin (wire ? GL_LINES : GL_QUAD_STRIP); + for (i = 0; i < o; i += 3) + { + int j = (i+o-3) % o; + int k = (i+3) % o; + GLdouble *p = pts + i; + GLdouble *pj = pts + j; + GLdouble *pk = pts + k; + + do_normal (pj[0], pj[1], pj[2], + pj[0], pj[1], -pj[2], + pk[0], pk[1], pk[2]); + + glVertex3f (p[0], p[1], p[2]); + glVertex3f (p[0], p[1], -p[2]); + polys++; + } + glEnd(); + + if (! wire) + glColor3f (0.3, 0.3, 0.3); + + /* outline the edges in gray */ + + glDisable (GL_TEXTURE_2D); + glDisable (GL_LIGHTING); + glLineWidth (jc->line_thickness); + + glBegin (GL_LINE_LOOP); + for (i = 0; i < o; i += 3) + glVertex3f (pts[i], pts[i+1], pts[i+2]); + glEnd(); + polys += o/3; + + glBegin (GL_LINE_LOOP); + for (i = 0; i < o; i += 3) + glVertex3f (pts[i], pts[i+1], -pts[i+2]); + glEnd(); + polys += o/3; + + free_spline (s); + free (pts); + + return polys; +} + + +static void +free_puzzle_grid (jigsaw_configuration *jc) +{ + int i; + for (i = 0; i < jc->puzzle_width * jc->puzzle_height; i++) + glDeleteLists (jc->puzzle[i].dlist, 1); + free (jc->puzzle); + jc->puzzle = 0; + jc->puzzle_width = 0; + jc->puzzle_height = 0; +} + + +static void +make_puzzle_grid (ModeInfo *mi) +{ + jigsaw_configuration *jc = &sps[MI_SCREEN(mi)]; + int wire = MI_IS_WIREFRAME(mi); + int x, y; + GLfloat size = (8 + (random() % 8)) * complexity_arg; + + if (jc->puzzle) + free_puzzle_grid (jc); + + if (wire) + jc->aspect = MI_WIDTH(mi) / (float) MI_HEIGHT(mi); + + if (jc->aspect >= 1.0) + { + jc->puzzle_width = size; + jc->puzzle_height = (size + 0.5) / jc->aspect; + } + else + { + jc->puzzle_width = (size + 0.5) * jc->aspect; + jc->puzzle_height = size; + } + + if (jc->puzzle_width < 1) jc->puzzle_width = 1; + if (jc->puzzle_height < 1) jc->puzzle_height = 1; + + if (debug_p) + fprintf (stderr, "%s: grid %4d x %-4d (%.2f)\n", progname, + jc->puzzle_width, jc->puzzle_height, + ((float) jc->puzzle_width / jc->puzzle_height)); + + jc->puzzle = (puzzle_piece *) + calloc (jc->puzzle_width * (jc->puzzle_height+1), sizeof(*jc->puzzle)); + + /* Randomize the right and bottom edge of each piece. + Match the left edge of the piece to the right to our right edge. + Match the top edge of the piece to the bottom to our bottom edge. + */ + for (y = 0; y < jc->puzzle_height; y++) + for (x = 0; x < jc->puzzle_width; x++) + { + puzzle_piece *p = &jc->puzzle [y * jc->puzzle_width + x]; + puzzle_piece *r = &jc->puzzle [y * jc->puzzle_width + x+1]; + puzzle_piece *b = &jc->puzzle [(y+1) * jc->puzzle_width + x]; + p->edge[RIGHT] = (random() & 1) ? IN : OUT; + p->edge[BOTTOM] = (random() & 1) ? IN : OUT; + r->edge[LEFT] = p->edge[RIGHT] == IN ? OUT : IN; + b->edge[TOP] = p->edge[BOTTOM] == IN ? OUT : IN; + } + + /* tell each piece where it belongs. */ + for (y = 0; y < jc->puzzle_height; y++) + for (x = 0; x < jc->puzzle_width; x++) + { + puzzle_piece *p = &jc->puzzle [y * jc->puzzle_width + x]; + p->jc = jc; + p->home.x = x; + p->home.y = y; + p->current = p->home; + + /* make sure the outer border is flat */ + if (p->home.x == 0) p->edge[LEFT] = FLAT; + if (p->home.y == 0) p->edge[TOP] = FLAT; + if (p->home.x == jc->puzzle_width-1) p->edge[RIGHT] = FLAT; + if (p->home.y == jc->puzzle_height-1) p->edge[BOTTOM] = FLAT; + + /* generate the polygons */ + p->dlist = glGenLists (1); + check_gl_error ("generating lists"); + if (p->dlist <= 0) abort(); + + glNewList (p->dlist, GL_COMPILE); + p->polys += draw_piece (jc, p, + resolution_arg, thickness_arg, + p->edge[TOP], p->edge[RIGHT], + p->edge[BOTTOM], p->edge[LEFT], + wire); + glEndList(); + } +} + + +static void shuffle_grid (ModeInfo *mi); + + +static void +image_loaded_cb (const char *filename, XRectangle *geometry, + int image_width, int image_height, + int texture_width, int texture_height, + void *closure) +{ + ModeInfo *mi = (ModeInfo *) closure; + jigsaw_configuration *jc = &sps[MI_SCREEN(mi)]; + + jc->tex_x = geometry->x / (float) texture_width; + jc->tex_y = geometry->y / (float) texture_height; + jc->tex_width = geometry->width / (float) texture_width; + jc->tex_height = geometry->height / (float) texture_height; + jc->aspect = geometry->width / (float) geometry->height; + + if (debug_p) + { + fprintf (stderr, "%s: image %s\n", progname, + (filename ? filename : "(null)")); + fprintf (stderr, "%s: image %4d x %-4d + %4d + %-4d (%.2f)\n", progname, + geometry->width, geometry->height, geometry->x, geometry->y, + (float) geometry->width / geometry->height); + fprintf (stderr, "%s: tex %4d x %-4d\n", progname, + texture_width, texture_height); + fprintf (stderr, "%s: tex %4.2f x %4.2f + %4.2f + %4.2f (%.2f)\n", + progname, + jc->tex_width, jc->tex_height, jc->tex_x, jc->tex_y, + (jc->tex_width / jc->tex_height) * + (texture_width / texture_height)); + } + + glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP); + glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP); + + make_puzzle_grid (mi); +} + + +static void +load_image (ModeInfo *mi) +{ + jigsaw_configuration *jc = &sps[MI_SCREEN(mi)]; + load_texture_async (mi->xgwa.screen, mi->window, + *jc->glx_context, 0, 0, + False, jc->texid, + image_loaded_cb, mi); +} + + +/* Whether the two pieces are the same shape, when the second piece + is rotated by the given degrees. + */ +static Bool +same_shape (puzzle_piece *p0, puzzle_piece *p1, int rotated_by) +{ + switch (rotated_by) + { + case 0: + return (p0->edge[0] == p1->edge[0] && + p0->edge[1] == p1->edge[1] && + p0->edge[2] == p1->edge[2] && + p0->edge[3] == p1->edge[3]); + case 90: + return (p0->edge[0] == p1->edge[1] && + p0->edge[1] == p1->edge[2] && + p0->edge[2] == p1->edge[3] && + p0->edge[3] == p1->edge[0]); + case 180: + return (p0->edge[0] == p1->edge[2] && + p0->edge[1] == p1->edge[3] && + p0->edge[2] == p1->edge[0] && + p0->edge[3] == p1->edge[1]); + case 270: + return (p0->edge[0] == p1->edge[3] && + p0->edge[1] == p1->edge[0] && + p0->edge[2] == p1->edge[1] && + p0->edge[3] == p1->edge[2]); + default: + abort(); + } +} + + +/* Returns the proper rotation for the piece at the given position. + */ +static int +proper_rotation (jigsaw_configuration *jc, puzzle_piece *p, + double x, double y) +{ + puzzle_piece *p1; + int cx = x; + int cy = y; + if (cx != x) abort(); /* must be in integral position! */ + if (cy != y) abort(); + p1 = &jc->puzzle [cy * jc->puzzle_width + cx]; + if (same_shape (p, p1, 0)) return 0; + if (same_shape (p, p1, 90)) return 90; + if (same_shape (p, p1, 180)) return 180; + if (same_shape (p, p1, 270)) return 270; + abort(); /* these two pieces don't match in any rotation! */ +} + + +/* Returns the piece currently at the given position. + */ +static puzzle_piece * +piece_at (jigsaw_configuration *jc, double x, double y) +{ + int npieces = jc->puzzle_width * jc->puzzle_height; + int i; + int cx = x; + int cy = y; + if (cx != x) abort(); /* must be in integral position! */ + if (cy != y) abort(); + + for (i = 0; i < npieces; i++) + { + puzzle_piece *p = &jc->puzzle [i]; + if (p->current.x == cx && + p->current.y == cy) + return p; + } + abort(); /* no piece at that position? */ +} + + +static void +shuffle_grid (ModeInfo *mi) +{ + jigsaw_configuration *jc = &sps[MI_SCREEN(mi)]; + int max_tries = jc->puzzle_width * jc->puzzle_height; + int npieces = jc->puzzle_width * jc->puzzle_height; + int i; + + for (i = 0; i < npieces; i++) + { + puzzle_piece *p0 = &jc->puzzle [i]; + puzzle_piece *p1 = 0; + int k; + + for (k = 0; k < max_tries; k++) + { + p1 = &jc->puzzle [random() % npieces]; + if (same_shape (p0, p1, 0)) break; + if (same_shape (p0, p1, 90)) break; + if (same_shape (p0, p1, 180)) break; + if (same_shape (p0, p1, 270)) break; + p1 = 0; /* mismatch */ + } + if (p1 && p0 != p1) + { + XYZR s; + s = p0->current; p0->current = p1->current; p1->current = s; + p0->current.r = + proper_rotation (jc, p0, p0->current.x, p0->current.y); + p1->current.r = + proper_rotation (jc, p1, p1->current.x, p1->current.y); + } + } +} + + +/* We tend to accumulate floating point errors, e.g., z being 0.000001 + after a move. This makes sure float values that should be integral are. + */ +static void +smooth_grid (ModeInfo *mi) +{ + jigsaw_configuration *jc = &sps[MI_SCREEN(mi)]; + int npieces = jc->puzzle_width * jc->puzzle_height; + int i; + + for (i = 0; i < npieces; i++) + { + puzzle_piece *p = &jc->puzzle [i]; +# define SMOOTH(P) \ + P.x = (int) (P.x + 0.5); \ + P.y = (int) (P.y + 0.5); \ + P.z = (int) (P.z + 0.5); \ + P.r = (int) (P.r + 0.5) + SMOOTH(p->home); + SMOOTH(p->current); + SMOOTH(p->from); + SMOOTH(p->to); + if (p->tick <= 0.0001) p->tick = 0.0; + if (p->tick >= 0.9999) p->tick = 1.0; + } +} + + +static void +begin_scatter (ModeInfo *mi, Bool unscatter_p) +{ + jigsaw_configuration *jc = &sps[MI_SCREEN(mi)]; + int npieces = jc->puzzle_width * jc->puzzle_height; + int i; + XYZR ctr = { 0, }; + ctr.x = jc->puzzle_width / 2; + ctr.y = jc->puzzle_height / 2; + + for (i = 0; i < npieces; i++) + { + puzzle_piece *p = &jc->puzzle [i]; + XYZ a; + double d, r, th; + p->tick = -frand(1.0); + p->from = p->current; + + a.x = p->from.x - ctr.x; /* position relative to center */ + a.y = p->from.y - ctr.y; + + r = sqrt (a.x*a.x + a.y*a.y); + th = atan2 (a.x, a.y); + + d = MAX (jc->puzzle_width, jc->puzzle_height) * 2; + r = r*r + d; + + p->to.x = ctr.x + (r * sin (th)); + p->to.y = ctr.y + (r * cos (th)); + p->to.z = p->from.z; + p->to.r = ((int) p->from.r + (random() % 180)) % 360; + p->arc_height = frand(10.0); + + if (unscatter_p) + { + XYZR s = p->to; p->to = p->from; p->from = s; + p->current = p->from; + } + } +} + + +static Bool +solved_p (ModeInfo *mi) +{ + jigsaw_configuration *jc = &sps[MI_SCREEN(mi)]; + int npieces = jc->puzzle_width * jc->puzzle_height; + int i; + + for (i = 0; i < npieces; i++) + { + puzzle_piece *p = &jc->puzzle [i]; + if (p->current.x != p->home.x || + p->current.y != p->home.y || + p->current.z != p->home.z) + return False; + } + return True; +} + + +static void +move_one_piece (ModeInfo *mi) +{ + jigsaw_configuration *jc = &sps[MI_SCREEN(mi)]; + int npieces = jc->puzzle_width * jc->puzzle_height; + int i; + + for (i = 0; i < npieces * 100; i++) /* shouldn't take that long */ + { + int i = random() % npieces; + puzzle_piece *p0 = &jc->puzzle [i]; + puzzle_piece *p1; + + if (p0->current.x == p0->home.x && + p0->current.y == p0->home.y && + p0->current.z == p0->home.z) + continue; /* piece already solved - try again */ + + /* swap with the piece occupying p0's home cell. */ + p1 = piece_at (jc, p0->home.x, p0->home.y); + + if (p0 == p1) abort(); /* should have caught this above */ + + p0->tick = 0; + p0->from = p0->current; + p0->to = p1->current; + p0->to.r = proper_rotation (jc, p0, p0->to.x, p0->to.y); + + p1->tick = 0; + p1->from = p1->current; + p1->to = p0->current; + p1->to.r = proper_rotation (jc, p1, p1->to.x, p1->to.y); + + /* Try to avoid having them intersect each other in the air. */ + p0->arc_height = 0; + p1->arc_height = 0; + while (fabs (p0->arc_height - p1->arc_height) < 1.5) + { + p0->arc_height = 0.5 + frand(3.0); + p1->arc_height = 1.0 + frand(3.0); + } + +# define RTILT(V) \ + V = 90 - BELLRAND(180); \ + if (! (random() % 5)) V *= 2; \ + if (! (random() % 5)) V *= 2; \ + if (! (random() % 5)) V *= 2 + RTILT (p0->max_tilt); + RTILT (p1->max_tilt); +# undef RTILT + + if (debug_p) + fprintf (stderr, "%s: swapping %2d,%-2d with %2d,%d\n", progname, + (int) p0->from.x, (int) p0->from.y, + (int) p1->from.x, (int) p1->from.y); + return; + } + + abort(); /* infinite loop! */ +} + + +static Bool +anim_tick (ModeInfo *mi) +{ + jigsaw_configuration *jc = &sps[MI_SCREEN(mi)]; + int npieces = jc->puzzle_width * jc->puzzle_height; + int i; + Bool finished_p = True; + + if (jc->pausing > 0) + { + jc->pausing -= jc->tick_speed * speed; + if (debug_p && jc->pausing <= 0) + fprintf (stderr, "%s: (done pausing)\n", progname); + return False; + } + + for (i = 0; i < npieces; i++) + { + puzzle_piece *p = &jc->puzzle [i]; + double tt; + + if (p->tick >= 1.0) continue; /* this piece is done */ + finished_p = False; /* not done */ + + p->tick += jc->tick_speed * speed; + if (p->tick > 1.0) p->tick = 1.0; + + if (p->tick < 0.0) continue; /* not yet started */ + + tt = 1 - sin (M_PI/2 - p->tick * M_PI/2); + + p->current.x = p->from.x + ((p->to.x - p->from.x) * tt); + p->current.y = p->from.y + ((p->to.y - p->from.y) * tt); + p->current.z = p->from.z + ((p->to.z - p->from.z) * tt); + p->current.r = p->from.r + ((p->to.r - p->from.r) * tt); + + p->current.z += p->arc_height * sin (p->tick * M_PI); + + p->tilt = p->max_tilt * sin (p->tick * M_PI); + + } + + return finished_p; +} + + +static void +loading_msg (ModeInfo *mi) +{ + jigsaw_configuration *jc = &sps[MI_SCREEN(mi)]; + int wire = MI_IS_WIREFRAME(mi); + const char *text = "Loading..."; + int h; + int w = texture_string_width (jc->texfont, text, &h); + + if (wire) return; + + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + + if (! jc->loading_dlist) + { + GLfloat othick = jc->line_thickness; + puzzle_piece P = { 0, }; + P.jc = jc; + jc->loading_dlist = glGenLists (1); + glNewList (jc->loading_dlist, GL_COMPILE); + jc->line_thickness = 1; + draw_piece (jc, &P, + resolution_arg, thickness_arg, + OUT, OUT, IN, OUT, True); + jc->line_thickness = othick; + glEndList(); + } + + glColor3f (0.2, 0.2, 0.4); + + glPushMatrix(); + { + double x, y, z; + get_position (jc->rot, &x, &y, &z, True); + glRotatef (x * 360, 1, 0, 0); + glRotatef (y * 360, 0, 1, 0); + glRotatef (z * 360, 0, 0, 1); + glScalef (5, 5, 5); + glTranslatef (-0.5, -0.5, 0); + glCallList (jc->loading_dlist); + } + glPopMatrix(); + + glColor3f (0.7, 0.7, 1); + + + glMatrixMode(GL_PROJECTION); + glPushMatrix(); + glLoadIdentity(); + + glMatrixMode(GL_MODELVIEW); + glPushMatrix(); + glLoadIdentity(); + + { + double rot = current_device_rotation(); + glRotatef(rot, 0, 0, 1); + if ((rot > 45 && rot < 135) || + (rot < -45 && rot > -135)) + { + GLfloat s = MI_WIDTH(mi) / (GLfloat) MI_HEIGHT(mi); + glScalef (s, 1/s, 1); + } + } + + glOrtho(0, MI_WIDTH(mi), 0, MI_HEIGHT(mi), -1, 1); + glTranslatef ((MI_WIDTH(mi) - w) / 2, + (MI_HEIGHT(mi) - h) / 2, + 0); + glEnable (GL_TEXTURE_2D); + glPolygonMode (GL_FRONT, GL_FILL); + glDisable (GL_LIGHTING); + glEnable (GL_BLEND); + glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + print_texture_string (jc->texfont, text); + glEnable (GL_DEPTH_TEST); + glPopMatrix(); + + glMatrixMode(GL_PROJECTION); + glPopMatrix(); + + glMatrixMode(GL_MODELVIEW); +} + + +static void +animate (ModeInfo *mi) +{ + jigsaw_configuration *jc = &sps[MI_SCREEN(mi)]; + double slow = 0.01; + double fast = 0.04; + + if (jc->button_down_p && jc->state != PUZZLE_LOADING_MSG) + return; + + switch (jc->state) + { + case PUZZLE_LOADING_MSG: + if (! jc->puzzle) + loading_msg (mi); + /* fall through */ + + case PUZZLE_LOADING: + if (!jc->puzzle) break; /* still loading */ + jc->tick_speed = slow; + shuffle_grid (mi); + smooth_grid (mi); + begin_scatter (mi, True); + jc->pausing = 0; + jc->state = PUZZLE_UNSCATTER; + if (debug_p) fprintf (stderr, "%s: unscattering\n", progname); + break; + + case PUZZLE_UNSCATTER: + jc->tick_speed = slow; + if (anim_tick (mi)) + { + smooth_grid (mi); + jc->pausing = 1.0; + jc->state = PUZZLE_SOLVE; + if (debug_p) fprintf (stderr, "%s: solving\n", progname); + } + break; + + case PUZZLE_SOLVE: + jc->tick_speed = fast; + if (anim_tick (mi)) + { + smooth_grid (mi); + if (solved_p (mi)) + { + if (debug_p) fprintf (stderr, "%s: solved!\n", progname); + begin_scatter (mi, False); + jc->state = PUZZLE_SCATTER; + jc->pausing = 3.0; + if (debug_p) fprintf (stderr, "%s: scattering\n", progname); + } + else + { + move_one_piece (mi); + jc->pausing = 0.3; + } + } + break; + + case PUZZLE_SCATTER: + jc->tick_speed = slow; + if (anim_tick (mi)) + { + free_puzzle_grid (jc); + load_image (mi); + jc->state = PUZZLE_LOADING; + jc->pausing = 1.0; + if (debug_p) fprintf (stderr, "%s: loading\n", progname); + } + break; + + default: + abort(); + } +} + + +/* Window management, etc + */ +ENTRYPOINT void +reshape_jigsaw (ModeInfo *mi, int width, int height) +{ + jigsaw_configuration *jc = &sps[MI_SCREEN(mi)]; + GLfloat h = (GLfloat) height / (GLfloat) width; + + glViewport (0, 0, (GLint) width, (GLint) height); + + glMatrixMode(GL_PROJECTION); + glLoadIdentity(); + gluPerspective (30.0, 1/h, 1.0, 100.0); + + glMatrixMode(GL_MODELVIEW); + glLoadIdentity(); + gluLookAt( 0.0, 0.0, 30.0, + 0.0, 0.0, 0.0, + 0.0, 1.0, 0.0); + + glClear(GL_COLOR_BUFFER_BIT); + + jc->line_thickness = (MI_IS_WIREFRAME (mi) ? 1 : MAX (1, height / 300.0)); +} + + +ENTRYPOINT Bool +jigsaw_handle_event (ModeInfo *mi, XEvent *event) +{ + jigsaw_configuration *jc = &sps[MI_SCREEN(mi)]; + + if (event->xany.type == ButtonPress && + event->xbutton.button == Button1) + { + jc->button_down_p = True; + gltrackball_start (jc->trackball, + event->xbutton.x, event->xbutton.y, + MI_WIDTH (mi), MI_HEIGHT (mi)); + return True; + } + else if (event->xany.type == ButtonRelease && + event->xbutton.button == Button1) + { + jc->button_down_p = False; + return True; + } + else if (event->xany.type == ButtonPress && + (event->xbutton.button == Button4 || + event->xbutton.button == Button5 || + event->xbutton.button == Button6 || + event->xbutton.button == Button7)) + { + gltrackball_mousewheel (jc->trackball, event->xbutton.button, 10, + !!event->xbutton.state); + return True; + } + else if (event->xany.type == MotionNotify && + jc->button_down_p) + { + gltrackball_track (jc->trackball, + event->xmotion.x, event->xmotion.y, + MI_WIDTH (mi), MI_HEIGHT (mi)); + return True; + } + else if (event->xany.type == KeyPress) + { + KeySym keysym; + char c = 0; + XLookupString (&event->xkey, &c, 1, &keysym, 0); + + if (c == ' ' || c == '\t' || c == '\r' || c == '\n') + { + begin_scatter (mi, False); + jc->state = PUZZLE_SCATTER; + return True; + } + } + + + return False; +} + + +ENTRYPOINT void +init_jigsaw (ModeInfo *mi) +{ + jigsaw_configuration *jc; + int wire = MI_IS_WIREFRAME(mi); + + if (!sps) { + sps = (jigsaw_configuration *) + calloc (MI_NUM_SCREENS(mi), sizeof (jigsaw_configuration)); + if (!sps) { + fprintf(stderr, "%s: out of memory\n", progname); + exit(1); + } + } + jc = &sps[MI_SCREEN(mi)]; + jc->glx_context = init_GL(mi); + + reshape_jigsaw (mi, MI_WIDTH(mi), MI_HEIGHT(mi)); + + if (!wire) + { + GLfloat pos[4] = {0.05, 0.07, 1.00, 0.0}; + GLfloat amb[4] = {0.2, 0.2, 0.2, 1.0}; + GLfloat dif[4] = {1.0, 1.0, 1.0, 1.0}; + GLfloat spc[4] = {0.0, 1.0, 1.0, 1.0}; + + glLightfv(GL_LIGHT0, GL_POSITION, pos); + glLightfv(GL_LIGHT0, GL_AMBIENT, amb); + glLightfv(GL_LIGHT0, GL_DIFFUSE, dif); + glLightfv(GL_LIGHT0, GL_SPECULAR, spc); + } + + jc->trackball = gltrackball_init (); + jc->rot = make_rotator (0, 0, 0, 0, speed * 0.002, True); + jc->texfont = load_texture_font (MI_DISPLAY(mi), "font"); + + jc->state = PUZZLE_LOADING_MSG; + + resolution_arg /= complexity_arg; + +# ifndef HAVE_TESS + /* If it's not even, we get crosses. */ + if (resolution_arg & 1) + resolution_arg++; +# endif /* !HAVE_TESS */ + + if (wire) + make_puzzle_grid (mi); + else + load_image (mi); +} + + +ENTRYPOINT void +draw_jigsaw (ModeInfo *mi) +{ + jigsaw_configuration *jc = &sps[MI_SCREEN(mi)]; + Display *dpy = MI_DISPLAY(mi); + Window window = MI_WINDOW(mi); + int wire = MI_IS_WIREFRAME(mi); + + if (!jc->glx_context) + return; + + glXMakeCurrent(MI_DISPLAY(mi), MI_WINDOW(mi), *(jc->glx_context)); + + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + + mi->polygon_count = 0; + + glPushMatrix (); + glRotatef(current_device_rotation(), 0, 0, 1); + gltrackball_rotate (jc->trackball); + + animate (mi); + + if (wobble_p && jc->puzzle) + { + double x, y, z; + double max = 60; + get_position (jc->rot, &x, &y, &z, !jc->button_down_p); + x = 1; /* always lean back */ + glRotatef (max/2 - x*max, 1, 0, 0); + glRotatef (max/2 - z*max, 0, 1, 0); + } + + if (jc->puzzle) + { + GLfloat s = 14.0 / jc->puzzle_height; + int x, y; + + glEnable(GL_CULL_FACE); + glEnable(GL_DEPTH_TEST); + glEnable(GL_NORMALIZE); + glEnable(GL_LINE_SMOOTH); + + glScalef (s, s, s); + glTranslatef (-jc->puzzle_width / 2.0, -jc->puzzle_height / 2.0, 0); + + if (! wire) + { + glEnable (GL_TEXTURE_2D); + glEnable (GL_BLEND); + glEnable (GL_LIGHTING); + glEnable (GL_LIGHT0); + glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + } + + for (y = 0; y < jc->puzzle_height; y++) + for (x = 0; x < jc->puzzle_width; x++) + { + puzzle_piece *p = &jc->puzzle [y * jc->puzzle_width + x]; + glPushMatrix(); + glTranslatef (p->current.x, p->current.y, p->current.z); + glTranslatef (0.5, 0.5, 0); + glRotatef (p->current.r, 0, 0, 1); + glRotatef (p->tilt, 0, 1, 0); + glTranslatef (-0.5, -0.5, 0); + glCallList(p->dlist); + mi->polygon_count += p->polys; + glPopMatrix(); + } + } + + glPopMatrix (); + + if (mi->fps_p) do_fps (mi); + glFinish(); + + glXSwapBuffers(dpy, window); +} + +XSCREENSAVER_MODULE ("Jigsaw", jigsaw) + +#endif /* USE_GL */ diff --git a/hacks/glx/jigsaw.man b/hacks/glx/jigsaw.man new file mode 100644 index 00000000..c7d34933 --- /dev/null +++ b/hacks/glx/jigsaw.man @@ -0,0 +1,90 @@ +.TH XScreenSaver 1 "25-Aug-2008" "X Version 11" +.SH NAME +jigsaw - permute an image like a jigsaw puzzle +.SH SYNOPSIS +.B jigsaw +[\-display \fIhost:display.screen\fP] +[\-delay \fIusecs\fP] +[\-speed \fIratio\fP] +[\-complexity \fIratio\fP] +[\-resolution \fIint\fP] +[\-thickness \fIfloat\fP] +[\-no\-wobble] +[\-fps] +.SH DESCRIPTION +The \fIjigsaw\fP program loads an image, carves it up into +a jigsaw puzzle, shuffles it, and then solves it. + +The image that it manipulates will be grabbed from the portion of +the screen underlying the window, or from the system's video input, +or from a random file on disk, as indicated by +the \fIgrabDesktopImages\fP, \fIgrabVideoFrames\fP, +and \fIchooseRandomImages\fP options in the \fI~/.xscreensaver\fP +file; see +.BR xscreensaver-demo (1) +for more details. +.SH OPTIONS +.I jigsaw +accepts the following options: +.TP 8 +.B \-delay \fImicroseconds\fP +How long to wait between animation frames; default 20000. +.TP 8 +.B \-speed \fIratio\fP +Less than 1 for slower, greater than 1 for faster. Default 1. +.TP 8 +.B \-complexity \fIratio\fP +Less than 1 for simpler puzzles (fewer pieces), greater than 1 for +more complex puzzles (more pieces). Default 1. +.TP 8 +.B \-resolution \fIratio\fP +Smoothness of the edges of the pieces. Less than 1 for rougher pieces +(fewer polygons), greater than 1 for more smoother pieces (more polygons). +Default 1. +.TP 8 +.B \-thickness \fIfloat\fP +Thickness of the puzzle pieces (relative to their width). +Default 0.06. +.TP 8 +.B \-no\-wobble +Keep the display stationary instead of very slowly wobbling back and forth. +.TP 8 +.B \-fps +Display the current frame rate, polygon count, and CPU load. +.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 \-install +Install a private colormap for the window. +.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. +.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), +.BR xscreensaver\-demo (1), +.BR xscreensaver\-getimage (1) +.SH COPYRIGHT +Copyright \(co 1997 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 , 25-Nov-97. diff --git a/hacks/glx/juggler3d.c b/hacks/glx/juggler3d.c new file mode 100644 index 00000000..1a7fe36b --- /dev/null +++ b/hacks/glx/juggler3d.c @@ -0,0 +1,3097 @@ +/* juggle, Copyright (c) 1996-2009 Tim Auckland + * and Jamie Zawinski + * + * Permission to use, copy, modify, and distribute this software and its + * documentation for any purpose and without fee is hereby granted, + * provided that the above copyright notice appear in all copies and that + * both that copyright notice and this permission notice appear in + * supporting documentation. + * + * This file is provided AS IS with no warranties of any kind. The author + * shall have no liability with respect to the infringement of copyrights, + * trade secrets or any patents by this file or any part thereof. In no + * event will the author be liable for any lost revenue or profits or + * other special, indirect and consequential damages. + * + * NOTE: this program was originally called "juggle" and was 2D Xlib. + * There was another program called "juggler3d" that was OpenGL. + * In 2009, jwz converted "juggle" to OpenGL and renamed + * "juggle" to "juggler3d". The old "juggler3d" hack is gone. + * + * Revision History + * 09-Aug-2009: jwz: converted from Xlib to OpenGL. + * 13-Dec-2004: [TDA] Use -cycles and -count in a rational manner. + * Add -rings, -bballs. Add -describe. Finally made + * live pattern updates possible. Add refill_juggle(), + * change_juggle() and reshape_juggle(). Make + * init_juggle() non-destructive. Reorder erase/draw + * operations. Update xscreensaver xml and manpage. + * 15-Nov-2004: [TDA] Fix all memory leaks. + * 12-Nov-2004: [TDA] Add -torches and another new trail + * implementation, so that different objects can have + * different length trails. + * 11-Nov-2004: [TDA] Clap when all the balls are in the air. + * 10-Nov-2004: [TDA] Display pattern name converted to hight + * notation. + * 31-Oct-2004: [TDA] Add -clubs and new trail implementation. + * 02-Sep-2003: Non-real time to see what is happening without a + * strobe effect for slow machines. + * 01-Nov-2000: Allocation checks + * 1996: Written + */ + +/*- + * TODO + * Implement the anonymously promised -uni option. + */ + + +/* + * Notes on Adam Chalcraft Juggling Notation (used by permission) + * a-> Adam's notation s-> Site swap (Cambridge) notation + * + * To define a map from a-notation to s-notation ("site-swap"), both + * of which look like doubly infinite sequences of natural numbers. In + * s-notation, there is a restriction on what is allowed, namely for + * the sequence s_n, the associated function f(n)=n+s_n must be a + * bijection. In a-notation, there is no restriction. + * + * To go from a-notation to s-notation, you start by mapping each a_n + * to a permutation of N, the natural numbers. + * + * 0 -> the identity + * 1 -> (10) [i.e. f(1)=0, f(0)=1] + * 2 -> (210) [i.e. f(2)=1, f(1)=0, f(0)=2] + * 3 -> (3210) [i.e. f(3)=2, f(2)=1, f(1)=0, f(0)=3] + * etc. + * + * Then for each n, you look at how long 0 takes to get back to 0 + * again and you call this t_n. If a_n=0, for example, then since the + * identity leaves 0 alone, it gets back to 0 in 1 step, so t_n=1. If + * a_n=1, then f(0)=1. Now any further a_n=0 leave 1 alone, but the + * next a_n>0 sends 1 back to 0. Hence t_n is 2 + the number of 0's + * following the 1. Finally, set s_n = t_n - 1. + * + * To give some examples, it helps to have a notation for cyclic + * sequences. By (123), for example, I mean ...123123123123... . Now + * under the a-notation -> s-notation mapping we have some familiar + * examples: + * + * (0)->(0), (1)->(1), (2)->(2) etc. + * (21)->(31), (31)->(51), (41)->(71) etc. + * (10)->(20), (20)->(40), (30)->(60) etc. + * (331)->(441), (312)->(612), (303)->(504), (321)->(531) + * (43)->(53), (434)->(534), (433)->(633) + * (552)->(672) + * + * In general, the number of balls is the *average* of the s-notation, + * and the *maximum* of the a-notation. Another theorem is that the + * minimum values in the a-notation and the s-notation and equal, and + * preserved in the same positions. + * + * The usefulness of a-notation is the fact that there are no + * restrictions on what is allowed. This makes random juggle + * generation much easier. It also makes enumeration very + * easy. Another handy feature is computing changes. Suppose you can + * do (5) and want a neat change up to (771) in s-notation [Mike Day + * actually needed this example!]. Write them both in a-notation, + * which gives (5) and (551). Now concatenate them (in general, there + * may be more than one way to do this, but not in this example), to + * get + * + * ...55555555551551551551551... + * + * Now convert back to s-notation, to get + * + * ...55555566771771771771771... + * + * So the answer is to do two 6 throws and then go straight into + * (771). Coming back down of course, + * + * ...5515515515515515555555555... + * + * converts to + * + * ...7717717717716615555555555... + * + * so the answer is to do a single 661 and then drop straight down to + * (5). + * + * [The number of balls in the generated pattern occasionally changes. + * In order to decrease the number of balls I had to introduce a new + * symbol into the Adam notation, [*] which means 'lose the current + * ball'.] + */ + +/* This code uses so many linked lists it's worth having a built-in + * leak-checker */ +#undef MEMTEST + +# define DEFAULTS "*delay: 10000 \n" \ + "*count: 200 \n" \ + "*cycles: 1000 \n" \ + "*ncolors: 32 \n" \ + "*titleFont: -*-helvetica-bold-r-normal-*-180-*\n" \ + "*showFPS: False \n" \ + "*wireframe: False \n" \ + +# define refresh_juggle 0 +#undef countof +#define countof(x) (sizeof((x))/sizeof((*x))) + +#include "xlockmore.h" +#include "sphere.h" +#include "tube.h" +#include "rotator.h" +#include "gltrackball.h" +#include "glxfonts.h" +#include + +#ifdef USE_GL /* whole file */ + +#define DEF_PATTERN "random" /* All patterns */ +#define DEF_TAIL "1" /* No trace */ +#ifdef UNI +/* Maybe a ROLA BOLA would be at a better angle for viewing */ +#define DEF_UNI "False" /* No unicycle */ /* Not implemented yet */ +#endif +#define DEF_REAL "True" +#define DEF_DESCRIBE "True" + +#define DEF_BALLS "True" /* Use Balls */ +#define DEF_CLUBS "True" /* Use Clubs */ +#define DEF_TORCHES "True" /* Use Torches */ +#define DEF_KNIVES "True" /* Use Knives */ +#define DEF_RINGS "True" /* Use Rings */ +#define DEF_BBALLS "True" /* Use Bowling Balls */ + +static char *pattern; +static int tail; +#ifdef UNI +static Bool uni; +#endif +static Bool real; +static Bool describe; +static Bool balls; +static Bool clubs; +static Bool torches; +static Bool knives; +static Bool rings; +static Bool bballs; +static char *only; + +static XrmOptionDescRec opts[] = { + {"-pattern", ".juggle.pattern", XrmoptionSepArg, NULL }, + {"-tail", ".juggle.tail", XrmoptionSepArg, NULL }, +#ifdef UNI + {"-uni", ".juggle.uni", XrmoptionNoArg, "on" }, + {"+uni", ".juggle.uni", XrmoptionNoArg, "off" }, +#endif + {"-real", ".juggle.real", XrmoptionNoArg, "on" }, + {"+real", ".juggle.real", XrmoptionNoArg, "off" }, + {"-describe", ".juggle.describe", XrmoptionNoArg, "on" }, + {"+describe", ".juggle.describe", XrmoptionNoArg, "off" }, + {"-balls", ".juggle.balls", XrmoptionNoArg, "on" }, + {"+balls", ".juggle.balls", XrmoptionNoArg, "off" }, + {"-clubs", ".juggle.clubs", XrmoptionNoArg, "on" }, + {"+clubs", ".juggle.clubs", XrmoptionNoArg, "off" }, + {"-torches", ".juggle.torches", XrmoptionNoArg, "on" }, + {"+torches", ".juggle.torches", XrmoptionNoArg, "off" }, + {"-knives", ".juggle.knives", XrmoptionNoArg, "on" }, + {"+knives", ".juggle.knives", XrmoptionNoArg, "off" }, + {"-rings", ".juggle.rings", XrmoptionNoArg, "on" }, + {"+rings", ".juggle.rings", XrmoptionNoArg, "off" }, + {"-bballs", ".juggle.bballs", XrmoptionNoArg, "on" }, + {"+bballs", ".juggle.bballs", XrmoptionNoArg, "off" }, + {"-only", ".juggle.only", XrmoptionSepArg, NULL }, +}; + +static argtype vars[] = { + { &pattern, "pattern", "Pattern", DEF_PATTERN, t_String }, + { &tail, "tail", "Tail", DEF_TAIL, t_Int }, +#ifdef UNI + { &uni, "uni", "Uni", DEF_UNI, t_Bool }, +#endif + { &real, "real", "Real", DEF_REAL, t_Bool }, + { &describe, "describe", "Describe", DEF_DESCRIBE, t_Bool }, + { &balls, "balls", "Clubs", DEF_BALLS, t_Bool }, + { &clubs, "clubs", "Clubs", DEF_CLUBS, t_Bool }, + { &torches, "torches", "Torches", DEF_TORCHES, t_Bool }, + { &knives, "knives", "Knives", DEF_KNIVES, t_Bool }, + { &rings, "rings", "Rings", DEF_RINGS, t_Bool }, + { &bballs, "bballs", "BBalls", DEF_BBALLS, t_Bool }, + { &only, "only", "BBalls", " ", t_String }, +}; + +static OptionStruct desc[] = +{ + { "-pattern string", "Cambridge Juggling Pattern" }, + { "-tail num", "Trace Juggling Patterns" }, +#ifdef UNI + { "-/+uni", "Unicycle" }, +#endif + { "-/+real", "Real-time" }, + { "-/+describe", "turn on/off pattern descriptions." }, + { "-/+balls", "turn on/off Balls." }, + { "-/+clubs", "turn on/off Clubs." }, + { "-/+torches", "turn on/off Flaming Torches." }, + { "-/+knives", "turn on/off Knives." }, + { "-/+rings", "turn on/off Rings." }, + { "-/+bballs", "turn on/off Bowling Balls." }, + { "-only", "Turn off all objects but the named one." }, +}; + +ENTRYPOINT ModeSpecOpt juggle_opts = + {countof(opts), opts, countof(vars), vars, desc}; + + +/* Note: All "lengths" are scaled by sp->scale = MI_HEIGHT/480. All + "thicknesses" are scaled by sqrt(sp->scale) so that they are + proportionally thicker for smaller windows. Objects spinning out + of the plane (such as clubs) fake perspective by compressing their + horizontal coordinates by PERSPEC */ + +/* Figure */ +#define ARMLENGTH 50 +#define ARMWIDTH ((int) (8.0 * sqrt(sp->scale))) +#define POSE 10 +#define BALLRADIUS ARMWIDTH + +/* build all the models assuming a 480px high scene */ +#define SCENE_HEIGHT 480 +#define SCENE_WIDTH ((int)(SCENE_HEIGHT*(MI_WIDTH(mi)/(float)MI_HEIGHT(mi)))) + +/*#define PERSPEC 0.4*/ + +/* macros */ +#define GRAVITY(h, t) 4*(double)(h)/((t)*(t)) + +/* Timing based on count. Units are milliseconds. Juggles per second + is: 2000 / THROW_CATCH_INTERVAL + CATCH_THROW_INTERVAL */ + +#define THROW_CATCH_INTERVAL (sp->count) +#define THROW_NULL_INTERVAL (sp->count * 0.5) +#define CATCH_THROW_INTERVAL (sp->count * 0.2) + +/******************************************************************** + * Trace Definitions * + * * + * These record rendering data so that a drawn object can be erased * + * later. Each object has its own Trace list. * + * * + ********************************************************************/ + +typedef struct {double x, y; } DXPoint; +typedef struct trace *TracePtr; +typedef struct trace { + TracePtr next, prev; + double x, y; + double angle; + int divisions; + DXPoint dlast; +#ifdef MEMTEST + char pad[1024]; +#endif +} Trace; + +/******************************************************************* + * Object Definitions * + * * + * These describe the various types of Object that can be juggled * + * * + *******************************************************************/ +typedef int (DrawProc)(ModeInfo*, unsigned long, Trace *); + +static DrawProc show_ball, show_europeanclub, show_torch, show_knife; +static DrawProc show_ring, show_bball; + +typedef enum {BALL, CLUB, TORCH, KNIFE, RING, BBALLS, + NUM_OBJECT_TYPES} ObjType; + +#define OBJMIXPROB 20 /* inverse of the chances of using an odd + object in the pattern */ + +static const GLfloat body_color_1[4] = { 0.9, 0.7, 0.5, 1 }; +static const GLfloat body_color_2[4] = { 0.6, 0.4, 0.2, 1 }; + +static const struct { + DrawProc *draw; /* Object Rendering function */ + int handle; /* Length of object's handle */ + int mintrail; /* Minimum trail length */ + double cor; /* Coefficient of Restitution. perfect bounce = 1 */ + double weight; /* Heavier objects don't get thrown as high */ +} ObjectDefs[] = { + { /* Ball */ + show_ball, + 0, + 1, + 0.9, + 1.0, + }, + { /* Club */ + show_europeanclub, + 15, + 1, + 0.55, /* Clubs don't bounce too well */ + 1.0, + }, + { /* Torch */ + show_torch, + 15, + 20, /* Torches need flames */ + 0, /* Torches don't bounce -- fire risk! */ + 1.0, + }, + { /* Knife */ + show_knife, + 15, + 1, + 0, /* Knives don't bounce */ + 1.0, + }, + { /* Ring */ + show_ring, + 15, + 1, + 0.8, + 1.0, + }, + { /* Bowling Ball */ + show_bball, + 0, + 1, + 0.2, + 5.0, + }, +}; + +/************************** + * Trajectory definitions * + **************************/ + +typedef enum {HEIGHT, ADAM} Notation; +typedef enum {Empty, Full, Ball} Throwable; +typedef enum {LEFT, RIGHT} Hand; +typedef enum {THROW, CATCH} Action; +typedef enum {HAND, ELBOW, SHOULDER} Joint; +typedef enum {ATCH, THRATCH, ACTION, LINKEDACTION, + PTHRATCH, BPREDICTOR, PREDICTOR} TrajectoryStatus; +typedef struct {double a, b, c, d; } Spline; +typedef DXPoint Arm[3]; + + +/* Object is an arbitrary object being juggled. Each Trajectory + * references an Object ("count" tracks this), and each Object is also + * linked into a global Objects list. Objects may include a Trace + * list for tracking erasures. */ +typedef struct object *ObjectPtr; +typedef struct object { + ObjectPtr next, prev; + + ObjType type; + int color; + int count; /* reference count */ + Bool active; /* Object is in use */ + + Trace *trace; + int tracelen; + int tail; +#ifdef MEMTEST + char pad[1024]; +#endif +} Object; + +/* Trajectory is a segment of juggling action. A list of Trajectories + * defines the juggling performance. The Trajectory list goes through + * multiple processing steps to convert it from basic juggling + * notation into rendering data. */ + +typedef struct trajectory *TrajectoryPtr; +typedef struct trajectory { + TrajectoryPtr prev, next; /* for building list */ + TrajectoryStatus status; + + /* Throw */ + char posn; + int height; + int adam; + char *pattern; + char *name; + + /* Action */ + Hand hand; + Action action; + + /* LinkedAction */ + int color; + Object *object; + int divisions; + double angle, spin; + TrajectoryPtr balllink; + TrajectoryPtr handlink; + + /* PThratch */ + double cx; /* Moving juggler */ + double x, y; /* current position */ + double dx, dy; /* initial velocity */ + + /* Predictor */ + Throwable type; + unsigned long start, finish; + Spline xp, yp; + +#ifdef MEMTEST + char pad[1024]; +#endif +} Trajectory; + + +/******************* + * Pattern Library * + *******************/ + +typedef struct { + const char * pattern; + const char * name; +} patternstruct; + +/* List of popular patterns, in any order */ +/* Patterns should be given in Adam notation so the generator can + concatenate them safely. Null descriptions are ok. Height + notation will be displayed automatically. */ +/* Can't const this because it is qsorted. This *should* be reentrant, + I think... */ +static /*const*/ patternstruct portfolio[] = { + {"[+2 1]", /* +3 1 */ "Typical 2 ball juggler"}, + {"[2 0]", /* 4 0 */ "2 in 1 hand"}, + {"[2 0 1]", /* 5 0 1 */}, + {"[+2 0 +2 0 0]" /* +5 0 +5 0 0 */}, + {"[+2 0 1 2 2]", /* +4 0 1 2 3 */}, + {"[2 0 1 1]", /* 6 0 1 1 */}, + + {"[3]", /* 3 */ "3 cascade"}, + {"[+3]", /* +3 */ "reverse 3 cascade"}, + {"[=3]", /* =3 */ "cascade 3 under arm"}, + {"[&3]", /* &3 */ "cascade 3 catching under arm"}, + {"[_3]", /* _3 */ "bouncing 3 cascade"}, + {"[+3 x3 =3]", /* +3 x3 =3 */ "Mill's mess"}, + {"[3 2 1]", /* 5 3 1" */}, + {"[3 3 1]", /* 4 4 1" */}, + {"[3 1 2]", /* 6 1 2 */ "See-saw"}, + {"[=3 3 1 2]", /* =4 5 1 2 */}, + {"[=3 2 2 3 1 2]", /* =6 2 2 5 1 2 */ "=4 5 1 2 stretched"}, + {"[+3 3 1 3]", /* +4 4 1 3 */ "anemic shower box"}, + {"[3 3 1]", /* 4 4 1 */}, + {"[+3 2 3]", /* +4 2 3 */}, + {"[+3 1]", /* +5 1 */ "3 shower"}, + {"[_3 1]", /* _5 1 */ "bouncing 3 shower"}, + {"[3 0 3 0 3]", /* 5 0 5 0 5 */ "shake 3 out of 5"}, + {"[3 3 3 0 0]", /* 5 5 5 0 0 */ "flash 3 out of 5"}, + {"[3 3 0]", /* 4 5 0 */ "complete waste of a 5 ball juggler"}, + {"[3 3 3 0 0 0 0]", /* 7 7 7 0 0 0 0 */ "3 flash"}, + {"[+3 0 +3 0 +3 0 0]", /* +7 0 +7 0 +7 0 0 */}, + {"[3 2 2 0 3 2 0 2 3 0 2 2 0]", /* 7 3 3 0 7 3 0 3 7 0 3 3 0 */}, + {"[3 0 2 0]", /* 8 0 4 0 */}, + {"[_3 2 1]", /* _5 3 1 */}, + {"[_3 0 1]", /* _8 0 1 */}, + {"[1 _3 1 _3 0 1 _3 0]", /* 1 _7 1 _7 0 1 _7 0 */}, + {"[_3 2 1 _3 1 2 1]", /* _6 3 1 _6 1 3 1 */}, + + {"[4]", /* 4 */ "4 cascade"}, + {"[+4 3]", /* +5 3 */ "4 ball half shower"}, + {"[4 4 2]", /* 5 5 2 */}, + {"[+4 4 4 +4]", /* +4 4 4 +4 */ "4 columns"}, + {"[+4 3 +4]", /* +5 3 +4 */}, + {"[4 3 4 4]", /* 5 3 4 4 */}, + {"[4 3 3 4]", /* 6 3 3 4 */}, + {"[4 3 2 4", /* 6 4 2 4 */}, + {"[+4 1]", /* +7 1 */ "4 shower"}, + {"[4 4 4 4 0]", /* 5 5 5 5 0 */ "learning 5"}, + {"[+4 x4 =4]", /* +4 x4 =4 */ "Mill's mess for 4"}, + {"[+4 2 1 3]", /* +9 3 1 3 */}, + {"[4 4 1 4 1 4]", /* 6 6 1 5 1 5, by Allen Knutson */}, + {"[_4 _4 _4 1 _4 1]", /* _5 _6 _6 1 _5 1 */}, + {"[_4 3 3]", /* _6 3 3 */}, + {"[_4 3 1]", /* _7 4 1 */}, + {"[_4 2 1]", /* _8 3 1 */}, + {"[_4 3 3 3 0]", /* _8 4 4 4 0 */}, + {"[_4 1 3 1]", /* _9 1 5 1 */}, + {"[_4 1 3 1 2]", /* _10 1 6 1 2 */}, + + {"[5]", /* 5 */ "5 cascade"}, + {"[_5 _5 _5 _5 _5 5 5 5 5 5]", /* _5 _5 _5 _5 _5 5 5 5 5 5 */}, + {"[+5 x5 =5]", /* +5 x5 =5 */ "Mill's mess for 5"}, + {"[5 4 4]", /* 7 4 4 */}, + {"[_5 4 4]", /* _7 4 4 */}, + {"[1 2 3 4 5 5 5 5 5]", /* 1 2 3 4 5 6 7 8 9 */ "5 ramp"}, + {"[5 4 5 3 1]", /* 8 5 7 4 1, by Allen Knutson */}, + {"[_5 4 1 +4]", /* _9 5 1 5 */}, + {"[_5 4 +4 +4]", /* _8 4 +4 +4 */}, + {"[_5 4 4 4 1]", /* _9 5 5 5 1 */}, + {"[_5 4 4 5 1]",}, + {"[_5 4 4 +4 4 0]", /*_10 5 5 +5 5 0 */}, + + {"[6]", /* 6 */ "6 cascade"}, + {"[+6 5]", /* +7 5 */}, + {"[6 4]", /* 8 4 */}, + {"[+6 3]", /* +9 3 */}, + {"[6 5 4 4]", /* 9 7 4 4 */}, + {"[+6 5 5 5]", /* +9 5 5 5 */}, + {"[6 0 6]", /* 9 0 9 */}, + {"[_6 0 _6]", /* _9 0 _9 */}, + + {"[_7]", /* _7 */ "bouncing 7 cascade"}, + {"[7]", /* 7 */ "7 cascade"}, + {"[7 6 6 6 6]", /* 11 6 6 6 6 */ "Gatto's High Throw"}, + +}; + + + +typedef struct { int start; int number; } PatternIndex; + +struct patternindex { + int minballs; + int maxballs; + PatternIndex index[countof(portfolio)]; +}; + + +/* Jugglestruct: per-screen global data. The master Object + * and Trajectory lists are anchored here. */ +typedef struct { + GLXContext *glx_context; + rotator *rot; + trackball_state *trackball; + Bool button_down_p; + + double scale; + double cx; + double Gr; + Trajectory *head; + Arm arm[2][2]; + char *pattern; + int count; + int num_balls; + time_t begintime; /* should make 'time' usable for at least 48 days + on a 32-bit machine */ + unsigned long time; /* millisecond timer*/ + ObjType objtypes; + Object *objects; + struct patternindex patternindex; + +# ifdef HAVE_GLBITMAP + XFontStruct *mode_font; + GLuint font_dlist; +# else + texture_font_data *font_data; +# endif +} jugglestruct; + +static jugglestruct *juggles = (jugglestruct *) NULL; + +/******************* + * list management * + *******************/ + +#define DUP_OBJECT(n, t) { \ + (n)->object = (t)->object; \ + if((n)->object != NULL) (n)->object->count++; \ +} + +/* t must point to an existing element. t must not be an + expression ending ->next or ->prev */ +#define REMOVE(t) { \ + (t)->next->prev = (t)->prev; \ + (t)->prev->next = (t)->next; \ + free(t); \ +} + +/* t receives element to be created and added to the list. ot must + point to an existing element or be identical to t to start a new + list. Applicable to Trajectories, Objects and Traces. */ +#define ADD_ELEMENT(type, t, ot) \ + if (((t) = (type*)calloc(1,sizeof(type))) != NULL) { \ + (t)->next = (ot)->next; \ + (t)->prev = (ot); \ + (ot)->next = (t); \ + (t)->next->prev = (t); \ + } + +static void +object_destroy(Object* o) +{ + if(o->trace != NULL) { + while(o->trace->next != o->trace) { + Trace *s = o->trace->next; + REMOVE(s); /* Don't eliminate 's' */ + } + free(o->trace); + } + REMOVE(o); +} + +static void +trajectory_destroy(Trajectory *t) { + if(t->name != NULL) free(t->name); + if(t->pattern != NULL) free(t->pattern); + /* Reduce object link count and call destructor if necessary */ + if(t->object != NULL && --t->object->count < 1 && t->object->tracelen == 0) { + object_destroy(t->object); + } + REMOVE(t); /* Unlink and free */ +} + +static void +free_juggle(jugglestruct *sp) { + if (sp->head != NULL) { + while (sp->head->next != sp->head) { + trajectory_destroy(sp->head->next); + } + free(sp->head); + sp->head = (Trajectory *) NULL; + } + if(sp->objects != NULL) { + while (sp->objects->next != sp->objects) { + object_destroy(sp->objects->next); + } + free(sp->objects); + sp->objects = (Object*)NULL; + } + if(sp->pattern != NULL) { + free(sp->pattern); + sp->pattern = NULL; + } +# ifdef HAVE_GLBITMAP + if (sp->mode_font!=None) { + XFreeFontInfo(NULL,sp->mode_font,1); + sp->mode_font = None; + } +# endif /* HAVE_GLBITMAP */ +} + +static Bool +add_throw(jugglestruct *sp, char type, int h, Notation n, const char* name) +{ + Trajectory *t; + + ADD_ELEMENT(Trajectory, t, sp->head->prev); + if(t == NULL){ /* Out of Memory */ + free_juggle(sp); + return False; + } + t->object = NULL; + if(name != NULL) + t->name = strdup(name); + t->posn = type; + if (n == ADAM) { + t->adam = h; + t->height = 0; + t->status = ATCH; + } else { + t->height = h; + t->status = THRATCH; + } + return True; +} + +/* add a Thratch to the performance */ +static Bool +program(ModeInfo *mi, const char *patn, const char *name, int cycles) +{ + jugglestruct *sp = &juggles[MI_SCREEN(mi)]; + const char *p; + int w, h, i, seen; + Notation notation; + char type; + + if (MI_IS_VERBOSE(mi)) { + (void) fprintf(stderr, "juggle[%d]: Programmed: %s x %d\n", + MI_SCREEN(mi), (name == NULL) ? patn : name, cycles); + } + + for(w=i=0; i < cycles; i++, w++) { /* repeat until at least "cycles" throws + have been programmed */ + /* title is the pattern name to be supplied to the first throw of + a sequence. If no name if given, use an empty title so that + the sequences are still delimited. */ + const char *title = (name != NULL)? name : ""; + type=' '; + h = 0; + seen = 0; + notation = HEIGHT; + for(p=patn; *p; p++) { + if (*p >= '0' && *p <='9') { + seen = 1; + h = 10*h + (*p - '0'); + } else { + Notation nn = notation; + switch (*p) { + case '[': /* begin Adam notation */ + notation = ADAM; + break; + case '-': /* Inside throw */ + type = ' '; + break; + case '+': /* Outside throw */ + case '=': /* Cross throw */ + case '&': /* Cross catch */ + case 'x': /* Cross throw and catch */ + case '_': /* Bounce */ + case 'k': /* Kickup */ + type = *p; + break; + case '*': /* Lose ball */ + seen = 1; + h = -1; + /* fall through */ + case ']': /* end Adam notation */ + nn = HEIGHT; + /* fall through */ + case ' ': + if (seen) { + i++; + if (!add_throw(sp, type, h, notation, title)) + return False; + title = NULL; + type=' '; + h = 0; + seen = 0; + } + notation = nn; + break; + default: + if(w == 0) { /* Only warn on first pass */ + (void) fprintf(stderr, + "juggle[%d]: Unexpected pattern instruction: '%c'\n", + MI_SCREEN(mi), *p); + } + break; + } + } + } + if (seen) { /* end of sequence */ + if (!add_throw(sp, type, h, notation, title)) + return False; + title = NULL; + } + } + return True; +} + +/* + ~~~~\~~~~~\~~~ + \\~\\~\~\\\~~~ + \\~\\\\~\\\~\~ + \\\\\\\\\\\~\\ + +[ 3 3 1 3 4 2 3 1 3 3 4 0 2 1 ] + +4 4 1 3 12 2 4 1 4 4 13 0 3 1 + +*/ +#define BOUNCEOVER 10 +#define KICKMIN 7 +#define THROWMAX 20 + +/* Convert Adam notation into heights */ +static void +adam(jugglestruct *sp) +{ + Trajectory *t, *p; + for(t = sp->head->next; t != sp->head; t = t->next) { + if (t->status == ATCH) { + int a = t->adam; + t->height = 0; + for(p = t->next; a > 0; p = p->next) { + if(p == sp->head) { + t->height = -9; /* Indicate end of processing for name() */ + return; + } + if (p->status != ATCH || p->adam < 0 || p->adam>= a) { + a--; + } + t->height++; + } + if(t->height > BOUNCEOVER && t->posn == ' '){ + t->posn = '_'; /* high defaults can be bounced */ + } else if(t->height < 3 && t->posn == '_') { + t->posn = ' '; /* Can't bounce short throws. */ + } + if(t->height < KICKMIN && t->posn == 'k'){ + t->posn = ' '; /* Can't kick short throws */ + } + if(t->height > THROWMAX){ + t->posn = 'k'; /* Use kicks for ridiculously high throws */ + } + t->status = THRATCH; + } + } +} + +/* Discover converted heights and update the sequence title */ +static void +name(jugglestruct *sp) +{ + Trajectory *t, *p; + char buffer[BUFSIZ]; + char *b; + for(t = sp->head->next; t != sp->head; t = t->next) { + if (t->status == THRATCH && t->name != NULL) { + b = buffer; + for(p = t; p == t || p->name == NULL; p = p->next) { + if(p == sp->head || p->height < 0) { /* end of reliable data */ + return; + } + if(p->posn == ' ') { + b += sprintf(b, " %d", p->height); + } else { + b += sprintf(b, " %c%d", p->posn, p->height); + } + if(b - buffer > 500) break; /* otherwise this could eventually + overflow. It'll be too big to + display anyway. */ + } + if(*t->name != 0) { + (void) sprintf(b, ", %s", t->name); + } + free(t->name); /* Don't need name any more, it's been converted + to pattern */ + t->name = NULL; + if(t->pattern != NULL) free(t->pattern); + t->pattern = strdup(buffer); + } + } +} + +/* Split Thratch notation into explicit throws and catches. + Usually Catch follows Throw in same hand, but take care of special + cases. */ + +/* ..n1.. -> .. LTn RT1 LC RC .. */ +/* ..nm.. -> .. LTn LC RTm RC .. */ + +static Bool +part(jugglestruct *sp) +{ + Trajectory *t, *nt, *p; + Hand hand = (LRAND() & 1) ? RIGHT : LEFT; + + for (t = sp->head->next; t != sp->head; t = t->next) { + if (t->status > THRATCH) { + hand = t->hand; + } else if (t->status == THRATCH) { + char posn = '='; + + /* plausibility check */ + if (t->height <= 2 && t->posn == '_') { + t->posn = ' '; /* no short bounces */ + } + if (t->height <= 1 && (t->posn == '=' || t->posn == '&')) { + t->posn = ' '; /* 1's need close catches */ + } + + switch (t->posn) { + /* throw catch */ + case ' ': posn = '-'; t->posn = '+'; break; + case '+': posn = '+'; t->posn = '-'; break; + case '=': posn = '='; t->posn = '+'; break; + case '&': posn = '+'; t->posn = '='; break; + case 'x': posn = '='; t->posn = '='; break; + case '_': posn = '_'; t->posn = '-'; break; + case 'k': posn = 'k'; t->posn = 'k'; break; + default: + (void) fprintf(stderr, "juggle: unexpected posn %c\n", t->posn); + break; + } + hand = (Hand) ((hand + 1) % 2); + t->status = ACTION; + t->hand = hand; + p = t->prev; + + if (t->height == 1 && p != sp->head) { + p = p->prev; /* '1's are thrown earlier than usual */ + } + + + + t->action = CATCH; + ADD_ELEMENT(Trajectory, nt, p); + if(nt == NULL){ + free_juggle(sp); + return False; + } + nt->object = NULL; + nt->status = ACTION; + nt->action = THROW; + nt->height = t->height; + nt->hand = hand; + nt->posn = posn; + + } + } + return True; +} + +static ObjType +choose_object(void) { + ObjType o; + for (;;) { + o = (ObjType)NRAND((ObjType)NUM_OBJECT_TYPES); + if(balls && o == BALL) break; + if(clubs && o == CLUB) break; + if(torches && o == TORCH) break; + if(knives && o == KNIFE) break; + if(rings && o == RING) break; + if(bballs && o == BBALLS) break; + } + return o; +} + +/* Connnect up throws and catches to figure out which ball goes where. + Do the same with the juggler's hands. */ + +static void +lob(ModeInfo *mi) +{ + jugglestruct *sp = &juggles[MI_SCREEN(mi)]; + Trajectory *t, *p; + int h; + for (t = sp->head->next; t != sp->head; t = t->next) { + if (t->status == ACTION) { + if (t->action == THROW) { + if (t->type == Empty) { + /* Create new Object */ + ADD_ELEMENT(Object, t->object, sp->objects); + t->object->count = 1; + t->object->tracelen = 0; + t->object->active = False; + /* Initialise object's circular trace list */ + ADD_ELEMENT(Trace, t->object->trace, t->object->trace); + + if (MI_NPIXELS(mi) > 2) { + t->object->color = 1 + NRAND(MI_NPIXELS(mi) - 2); + } else { +#ifdef STANDALONE + t->object->color = 1; +#else + t->object->color = 0; +#endif + } + + /* Small chance of picking a random object instead of the + current theme. */ + if(NRAND(OBJMIXPROB) == 0) { + t->object->type = choose_object(); + } else { + t->object->type = sp->objtypes; + } + + /* Check to see if we need trails for this object */ + if(tail < ObjectDefs[t->object->type].mintrail) { + t->object->tail = ObjectDefs[t->object->type].mintrail; + } else { + t->object->tail = tail; + } + } + + /* Balls can change divisions at each throw */ + /* no, that looks stupid. -jwz */ + if (t->divisions < 1) + t->divisions = 2 * (NRAND(2) + 1); + + /* search forward for next catch in this hand */ + for (p = t->next; t->handlink == NULL; p = p->next) { + if(p->status < ACTION || p == sp->head) return; + if (p->action == CATCH) { + if (t->handlink == NULL && p->hand == t->hand) { + t->handlink = p; + } + } + } + + if (t->height > 0) { + h = t->height - 1; + + /* search forward for next ball catch */ + for (p = t->next; t->balllink == NULL; p = p->next) { + if(p->status < ACTION || p == sp->head) { + t->handlink = NULL; + return; + } + if (p->action == CATCH) { + if (t->balllink == NULL && --h < 1) { /* caught */ + t->balllink = p; /* complete trajectory */ +# if 0 + if (p->type == Full) { + (void) fprintf(stderr, "juggle[%d]: Dropped %d\n", + MI_SCREEN(mi), t->object->color); + } +#endif + p->type = Full; + DUP_OBJECT(p, t); /* accept catch */ + p->angle = t->angle; + p->divisions = t->divisions; + } + } + } + } + t->type = Empty; /* thrown */ + } else if (t->action == CATCH) { + /* search forward for next throw from this hand */ + for (p = t->next; t->handlink == NULL; p = p->next) { + if(p->status < ACTION || p == sp->head) return; + if (p->action == THROW && p->hand == t->hand) { + p->type = t->type; /* pass ball */ + DUP_OBJECT(p, t); /* pass object */ + p->divisions = t->divisions; + t->handlink = p; + } + } + } + t->status = LINKEDACTION; + } + } +} + +/* Clap when both hands are empty */ +static void +clap(jugglestruct *sp) +{ + Trajectory *t, *p; + for (t = sp->head->next; t != sp->head; t = t->next) { + if (t->status == LINKEDACTION && + t->action == CATCH && + t->type == Empty && + t->handlink != NULL && + t->handlink->height == 0) { /* Completely idle hand */ + + for (p = t->next; p != sp->head; p = p->next) { + if (p->status == LINKEDACTION && + p->action == CATCH && + p->hand != t->hand) { /* Next catch other hand */ + if(p->type == Empty && + p->handlink != NULL && + p->handlink->height == 0) { /* Also completely idle */ + + t->handlink->posn = '^'; /* Move first hand's empty throw */ + p->posn = '^'; /* to meet second hand's empty + catch */ + + } + break; /* Only need first catch */ + } + } + } + } +} + +#define CUBIC(s, t) ((((s).a * (t) + (s).b) * (t) + (s).c) * (t) + (s).d) + +/* Compute single spline from x0 with velocity dx0 at time t0 to x1 + with velocity dx1 at time t1 */ +static Spline +makeSpline(double x0, double dx0, int t0, double x1, double dx1, int t1) +{ + Spline s; + double a, b, c, d; + double x10; + double t10; + + x10 = x1 - x0; + t10 = t1 - t0; + a = ((dx0 + dx1)*t10 - 2*x10) / (t10*t10*t10); + b = (3*x10 - (2*dx0 + dx1)*t10) / (t10*t10); + c = dx0; + d = x0; + s.a = a; + s.b = -3*a*t0 + b; + s.c = (3*a*t0 - 2*b)*t0 + c; + s.d = ((-a*t0 + b)*t0 - c)*t0 +d; + return s; +} + +/* Compute a pair of splines. s1 goes from x0 vith velocity dx0 at + time t0 to x1 at time t1. s2 goes from x1 at time t1 to x2 with + velocity dx2 at time t2. The arrival and departure velocities at + x1, t1 must be the same. */ +static double +makeSplinePair(Spline *s1, Spline *s2, + double x0, double dx0, int t0, + double x1, int t1, + double x2, double dx2, int t2) +{ + double x10, x21, t21, t10, t20, dx1; + x10 = x1 - x0; + x21 = x2 - x1; + t21 = t2 - t1; + t10 = t1 - t0; + t20 = t2 - t0; + dx1 = (3*x10*t21*t21 + 3*x21*t10*t10 + 3*dx0*t10*t21*t21 + - dx2*t10*t10*t21 - 4*dx0*t10*t21*t21) / + (2*t10*t21*t20); + *s1 = makeSpline(x0, dx0, t0, x1, dx1, t1); + *s2 = makeSpline(x1, dx1, t1, x2, dx2, t2); + return dx1; +} + +/* Compute a Ballistic path in a pair of degenerate splines. sx goes + from x at time t at constant velocity dx. sy goes from y at time t + with velocity dy and constant acceleration g. */ +static void +makeParabola(Trajectory *n, + double x, double dx, double y, double dy, double g) +{ + double t = (double)n->start; + n->xp.a = 0; + n->xp.b = 0; + n->xp.c = dx; + n->xp.d = -dx*t + x; + n->yp.a = 0; + n->yp.b = g/2; + n->yp.c = -g*t + dy; + n->yp.d = g/2*t*t - dy*t + y; +} + + + + +#define SX 25 /* Shoulder Width */ + +/* Convert hand position symbols into actual time/space coordinates */ +static void +positions(jugglestruct *sp) +{ + Trajectory *t; + unsigned long now = sp->time; /* Make sure we're not lost in the past */ + for (t = sp->head->next; t != sp->head; t = t->next) { + if (t->status >= PTHRATCH) { + now = t->start; + } else if (t->status == ACTION || t->status == LINKEDACTION) { + /* Allow ACTIONs to be annotated, but we won't mark them ready + for the next stage */ + + double xo = 0, yo; + double sx = SX; + double pose = SX/2; + + /* time */ + if (t->action == CATCH) { /* Throw-to-catch */ + if (t->type == Empty) { + now += (int) THROW_NULL_INTERVAL; /* failed catch is short */ + } else { /* successful catch */ + now += (int)(THROW_CATCH_INTERVAL); + } + } else { /* Catch-to-throw */ + if(t->object != NULL) { + now += (int) (CATCH_THROW_INTERVAL * + ObjectDefs[t->object->type].weight); + } else { + now += (int) (CATCH_THROW_INTERVAL); + } + } + + if(t->start == 0) + t->start = now; + else /* Concatenated performances may need clock resync */ + now = t->start; + + t->cx = 0; + + /* space */ + yo = 90; + + /* Add room for the handle */ + if(t->action == CATCH && t->object != NULL) + yo -= ObjectDefs[t->object->type].handle; + + switch (t->posn) { + case '-': xo = sx - pose; break; + case '_': + case 'k': + case '+': xo = sx + pose; break; + case '~': + case '=': xo = - sx - pose; yo += pose; break; + case '^': xo = 0; yo += pose*2; break; /* clap */ + default: + (void) fprintf(stderr, "juggle: unexpected posn %c\n", t->posn); + break; + } + +#ifdef _2DSpinsDontWorkIn3D + t->angle = (((t->hand == LEFT) ^ + (t->posn == '+' || t->posn == '_' || t->posn == 'k' ))? + -1 : 1) * M_PI/2; +#else + t->angle = -M_PI/2; +#endif + + t->x = t->cx + ((t->hand == LEFT) ? xo : -xo); + t->y = yo; + + /* Only mark complete if it was already linked */ + if(t->status == LINKEDACTION) { + t->status = PTHRATCH; + } + } + } +} + + +/* Private physics functions */ + +/* Compute the spin-rate for a trajectory. Different types of throw + (eg, regular thows, bounces, kicks, etc) have different spin + requirements. + + type = type of object + h = trajectory of throwing hand (throws), or next throwing hand (catches) + old = earlier spin to consider + dt = time span of this trajectory + height = height of ball throw or 0 if based on old spin + turns = full club turns required during this operation + togo = partial club turns required to match hands +*/ +static double +spinrate(ObjType type, Trajectory *h, double old, double dt, + int height, int turns, double togo) +{ +#ifdef _2DSpinsDontWorkIn3D + const int dir = (h->hand == LEFT) ^ (h->posn == '+')? -1 : 1; +#else + const int dir = 1; +#endif + + if(ObjectDefs[type].handle != 0) { /* Clubs */ + return (dir * turns * 2 * M_PI + togo) / dt; + } else if(height == 0) { /* Balls already spinning */ + return old/2; + } else { /* Balls */ + return dir * NRAND(height*10)/20/ObjectDefs[type].weight * 2 * M_PI / dt; + } +} + + +/* compute the angle at the end of a spinning trajectory */ +static double +end_spin(Trajectory *t) +{ + return t->angle + t->spin * (t->finish - t->start); +} + +/* Sets the initial angle of the catch following hand movement t to + the final angle of the throw n. Also sets the angle of the + subsequent throw to the same angle plus half a turn. */ +static void +match_spins_on_catch(Trajectory *t, Trajectory *n) +{ + if(ObjectDefs[t->balllink->object->type].handle == 0) { + t->balllink->angle = end_spin(n); + if(t->balllink->handlink != NULL) { +#ifdef _2DSpinsDontWorkIn3D + t->balllink->handlink->angle = t->balllink->angle + M_PI; +#else + t->balllink->handlink->angle = t->balllink->angle; +#endif + } + } +} + +static double +find_bounce(jugglestruct *sp, + double yo, double yf, double yc, double tc, double cor) +{ + double tb, i, dy = 0; + const double e = 1; /* permissible error in yc */ + + /* + tb = time to bounce + yt = height at catch time after one bounce + one or three roots according to timing + find one by interval bisection + */ + tb = tc; + for(i = tc / 2; i > 0.0001; i/=2){ + double dt, yt; + if(tb == 0){ + (void) fprintf(stderr, "juggle: bounce div by zero!\n"); + break; + } + dy = (yf - yo)/tb + sp->Gr/2*tb; + dt = tc - tb; + yt = -cor*dy*dt + sp->Gr/2*dt*dt + yf; + if(yt < yc + e){ + tb-=i; + }else if(yt > yc - e){ + tb+=i; + }else{ + break; + } + } + if(dy*THROW_CATCH_INTERVAL < -200) { /* bounce too hard */ + tb = -1; + } + return tb; +} + +static Trajectory* +new_predictor(const Trajectory *t, int start, int finish, double angle) +{ + Trajectory *n; + ADD_ELEMENT(Trajectory, n, t->prev); + if(n == NULL){ + return NULL; + } + DUP_OBJECT(n, t); + n->divisions = t->divisions; + n->type = Ball; + n->status = PREDICTOR; + + n->start = start; + n->finish = finish; + n->angle = angle; + return n; +} + +/* Turn abstract timings into physically appropriate object trajectories. */ +static Bool +projectile(jugglestruct *sp) +{ + Trajectory *t; + const int yf = 0; /* Floor height */ + + for (t = sp->head->next; t != sp->head; t = t->next) { + if (t->status != PTHRATCH || t->action != THROW) { + continue; + } else if (t->balllink == NULL) { /* Zero Throw */ + t->status = BPREDICTOR; + } else if (t->balllink->handlink == NULL) { /* Incomplete */ + return True; + } else if(t->balllink == t->handlink) { + /* '2' height - hold on to ball. Don't need to consider + flourishes, 'hands' will do that automatically anyway */ + + t->type = Full; + /* Zero spin to avoid wrist injuries */ + t->spin = 0; + match_spins_on_catch(t, t); + t->dx = t->dy = 0; + t->status = BPREDICTOR; + continue; + } else { + if (t->posn == '_') { /* Bounce once */ + + const int tb = t->start + + find_bounce(sp, t->y, (double) yf, t->balllink->y, + (double) (t->balllink->start - t->start), + ObjectDefs[t->object->type].cor); + + if(tb < t->start) { /* bounce too hard */ + t->posn = '+'; /* Use regular throw */ + } else { + Trajectory *n; /* First (throw) trajectory. */ + double dt; /* Time span of a trajectory */ + double dy; /* Distance span of a follow-on trajectory. + First trajectory uses t->dy */ + /* dx is constant across both trajectories */ + t->dx = (t->balllink->x - t->x) / (t->balllink->start - t->start); + + { /* ball follows parabola down */ + n = new_predictor(t, t->start, tb, t->angle); + if(n == NULL) return False; + dt = n->finish - n->start; + /* Ball rate 4, no flight or matching club turns */ + n->spin = spinrate(t->object->type, t, 0.0, dt, 4, 0, 0.0); + t->dy = (yf - t->y)/dt - sp->Gr/2*dt; + makeParabola(n, t->x, t->dx, t->y, t->dy, sp->Gr); + } + + { /* ball follows parabola up */ + Trajectory *m = new_predictor(t, n->finish, t->balllink->start, + end_spin(n)); + if(m == NULL) return False; + dt = m->finish - m->start; + /* Use previous ball rate, no flight club turns */ + m->spin = spinrate(t->object->type, t, n->spin, dt, 0, 0, + t->balllink->angle - m->angle); + match_spins_on_catch(t, m); + dy = (t->balllink->y - yf)/dt - sp->Gr/2 * dt; + makeParabola(m, t->balllink->x - t->dx * dt, + t->dx, (double) yf, dy, sp->Gr); + } + + t->status = BPREDICTOR; + continue; + } + } else if (t->posn == 'k') { /* Drop & Kick */ + Trajectory *n; /* First (drop) trajectory. */ + Trajectory *o; /* Second (rest) trajectory */ + Trajectory *m; /* Third (kick) trajectory */ + const int td = t->start + 2*THROW_CATCH_INTERVAL; /* Drop time */ + const int tk = t->balllink->start - 5*THROW_CATCH_INTERVAL; /* Kick */ + double dt, dy; + + { /* Fall to ground */ + n = new_predictor(t, t->start, td, t->angle); + if(n == NULL) return False; + dt = n->finish - n->start; + /* Ball spin rate 4, no flight club turns */ + n->spin = spinrate(t->object->type, t, 0.0, dt, 4, 0, + t->balllink->angle - n->angle); + t->dx = (t->balllink->x - t->x) / dt; + t->dy = (yf - t->y)/dt - sp->Gr/2*dt; + makeParabola(n, t->x, t->dx, t->y, t->dy, sp->Gr); + } + + { /* Rest on ground */ + o = new_predictor(t, n->finish, tk, end_spin(n)); + if(o == NULL) return False; + o->spin = 0; + makeParabola(o, t->balllink->x, 0.0, (double) yf, 0.0, 0.0); + } + + /* Kick up */ + { + m = new_predictor(t, o->finish, t->balllink->start, end_spin(o)); + if(m == NULL) return False; + dt = m->finish - m->start; + /* Match receiving hand, ball rate 4, one flight club turn */ + m->spin = spinrate(t->object->type, t->balllink->handlink, 0.0, dt, + 4, 1, t->balllink->angle - m->angle); + match_spins_on_catch(t, m); + dy = (t->balllink->y - yf)/dt - sp->Gr/2 * dt; + makeParabola(m, t->balllink->x, 0.0, (double) yf, dy, sp->Gr); + } + + t->status = BPREDICTOR; + continue; + } + + /* Regular flight, no bounce */ + { /* ball follows parabola */ + double dt; + Trajectory *n = new_predictor(t, t->start, + t->balllink->start, t->angle); + if(n == NULL) return False; + dt = t->balllink->start - t->start; + /* Regular spin */ + n->spin = spinrate(t->object->type, t, 0.0, dt, t->height, t->height/2, + t->balllink->angle - n->angle); + match_spins_on_catch(t, n); + t->dx = (t->balllink->x - t->x) / dt; + t->dy = (t->balllink->y - t->y) / dt - sp->Gr/2 * dt; + makeParabola(n, t->x, t->dx, t->y, t->dy, sp->Gr); + } + + t->status = BPREDICTOR; + } + } + return True; +} + +/* Turn abstract hand motions into cubic splines. */ +static void +hands(jugglestruct *sp) +{ + Trajectory *t, *u, *v; + + for (t = sp->head->next; t != sp->head; t = t->next) { + /* no throw => no velocity */ + if (t->status != BPREDICTOR) { + continue; + } + + u = t->handlink; + if (u == NULL) { /* no next catch */ + continue; + } + v = u->handlink; + if (v == NULL) { /* no next throw */ + continue; + } + + /* double spline takes hand from throw, thru catch, to + next throw */ + + t->finish = u->start; + t->status = PREDICTOR; + + u->finish = v->start; + u->status = PREDICTOR; + + + /* FIXME: These adjustments leave a small glitch when alternating + balls and clubs. Just hope no-one notices. :-) */ + + /* make sure empty hand spin matches the thrown object in case it + had a handle */ + + t->spin = ((t->hand == LEFT)? -1 : 1 ) * + fabs((u->angle - t->angle)/(u->start - t->start)); + + u->spin = ((v->hand == LEFT) ^ (v->posn == '+')? -1 : 1 ) * + fabs((v->angle - u->angle)/(v->start - u->start)); + + (void) makeSplinePair(&t->xp, &u->xp, + t->x, t->dx, t->start, + u->x, u->start, + v->x, v->dx, v->start); + (void) makeSplinePair(&t->yp, &u->yp, + t->y, t->dy, t->start, + u->y, u->start, + v->y, v->dy, v->start); + + t->status = PREDICTOR; + } +} + +/* Given target x, y find_elbow puts hand at target if possible, + * otherwise makes hand point to the target */ +static void +find_elbow(int armlength, DXPoint *h, DXPoint *e, DXPoint *p, DXPoint *s, + int z) +{ + double r, h2, t; + double x = p->x - s->x; + double y = p->y - s->y; + h2 = x*x + y*y + z*z; + if (h2 > 4 * armlength * armlength) { + t = armlength/sqrt(h2); + e->x = t*x + s->x; + e->y = t*y + s->y; + h->x = 2 * t * x + s->x; + h->y = 2 * t * y + s->y; + } else { + r = sqrt((double)(x*x + z*z)); + t = sqrt(4 * armlength * armlength / h2 - 1); + e->x = x*(1 + y*t/r)/2 + s->x; + e->y = (y - r*t)/2 + s->y; + h->x = x + s->x; + h->y = y + s->y; + } +} + + +/* NOTE: returned x, y adjusted for arm reach */ +static void +reach_arm(ModeInfo * mi, Hand side, DXPoint *p) +{ + jugglestruct *sp = &juggles[MI_SCREEN(mi)]; + DXPoint h, e; + find_elbow(40, &h, &e, p, &sp->arm[1][side][SHOULDER], 25); + *p = sp->arm[1][side][HAND] = h; + sp->arm[1][side][ELBOW] = e; +} + +#if DEBUG +/* dumps a human-readable rendition of the current state of the juggle + pipeline to stderr for debugging */ +static void +dump(jugglestruct *sp) +{ + Trajectory *t; + for (t = sp->head->next; t != sp->head; t = t->next) { + switch (t->status) { + case ATCH: + (void) fprintf(stderr, "%p a %c%d\n", (void*)t, t->posn, t->adam); + break; + case THRATCH: + (void) fprintf(stderr, "%p T %c%d %s\n", (void*)t, t->posn, t->height, + t->pattern == NULL?"":t->pattern); + break; + case ACTION: + if (t->action == CATCH) + (void) fprintf(stderr, "%p A %c%cC\n", + (void*)t, t->posn, + t->hand ? 'R' : 'L'); + else + (void) fprintf(stderr, "%p A %c%c%c%d\n", + (void*)t, t->posn, + t->hand ? 'R' : 'L', + (t->action == THROW)?'T':'N', + t->height); + break; + case LINKEDACTION: + (void) fprintf(stderr, "%p L %c%c%c%d %d %p %p\n", + (void*)t, t->posn, + t->hand?'R':'L', + (t->action == THROW)?'T':(t->action == CATCH?'C':'N'), + t->height, t->object == NULL?0:t->object->color, + (void*)t->handlink, (void*)t->balllink); + break; + case PTHRATCH: + (void) fprintf(stderr, "%p O %c%c%c%d %d %2d %6lu %6lu\n", + (void*)t, t->posn, + t->hand?'R':'L', + (t->action == THROW)?'T':(t->action == CATCH?'C':'N'), + t->height, t->type, t->object == NULL?0:t->object->color, + t->start, t->finish); + break; + case BPREDICTOR: + (void) fprintf(stderr, "%p B %c %2d %6lu %6lu %g\n", + (void*)t, t->type == Ball?'b':t->type == Empty?'e':'f', + t->object == NULL?0:t->object->color, + t->start, t->finish, t->yp.c); + break; + case PREDICTOR: + (void) fprintf(stderr, "%p P %c %2d %6lu %6lu %g\n", + (void*)t, t->type == Ball?'b':t->type == Empty?'e':'f', + t->object == NULL?0:t->object->color, + t->start, t->finish, t->yp.c); + break; + default: + (void) fprintf(stderr, "%p: status %d not implemented\n", + (void*)t, t->status); + break; + } + } + (void) fprintf(stderr, "---\n"); +} +#endif + +static int get_num_balls(const char *j) +{ + int balls = 0; + const char *p; + int h = 0; + if (!j) abort(); + for (p = j; *p; p++) { + if (*p >= '0' && *p <='9') { /* digit */ + h = 10*h + (*p - '0'); + } else { + if (h > balls) { + balls = h; + } + h = 0; + } + } + return balls; +} + +static int +compare_num_balls(const void *p1, const void *p2) +{ + int i, j; + i = get_num_balls(((patternstruct*)p1)->pattern); + j = get_num_balls(((patternstruct*)p2)->pattern); + if (i > j) { + return (1); + } else if (i < j) { + return (-1); + } else { + return (0); + } +} + + +/************************************************************************** + * Rendering Functions * + * * + **************************************************************************/ + +static int +show_arms(ModeInfo * mi) +{ + int polys = 0; + jugglestruct *sp = &juggles[MI_SCREEN(mi)]; + unsigned int i, j; + Hand side; + XPoint a[countof(sp->arm[0][0])]; + int slices = 12; + int thickness = 7; + int soffx = 10; + int soffy = 11; + + glFrontFace(GL_CCW); + + j = 1; + for(side = LEFT; side <= RIGHT; side = (Hand)((int)side + 1)) { + /* Translate into device coords */ + for(i = 0; i < countof(a); i++) { + a[i].x = (short)(SCENE_WIDTH/2 + sp->arm[j][side][i].x*sp->scale); + a[i].y = (short)(SCENE_HEIGHT - sp->arm[j][side][i].y*sp->scale); + if(j == 1) + sp->arm[0][side][i] = sp->arm[1][side][i]; + } + + glMaterialfv (GL_FRONT, GL_AMBIENT_AND_DIFFUSE, body_color_1); + + /* Upper arm */ + polys += tube (a[2].x - (side == LEFT ? soffx : -soffx), a[2].y + soffy, 0, + a[1].x, a[1].y, ARMLENGTH/2, + thickness, 0, slices, + True, True, MI_IS_WIREFRAME(mi)); + + /* Lower arm */ + polys += tube (a[1].x, a[1].y, ARMLENGTH/2, + a[0].x, a[0].y, ARMLENGTH, + thickness * 0.8, 0, slices, + True, True, MI_IS_WIREFRAME(mi)); + + glMaterialfv (GL_FRONT, GL_AMBIENT_AND_DIFFUSE, body_color_2); + + /* Shoulder */ + glPushMatrix(); + glTranslatef (a[2].x - (side == LEFT ? soffx : -soffx), + a[2].y + soffy, + 0); + glScalef(9, 9, 9); + polys += unit_sphere(slices, slices, MI_IS_WIREFRAME(mi)); + glPopMatrix(); + + /* Elbow */ + glPushMatrix(); + glTranslatef (a[1].x, a[1].y, ARMLENGTH/2); + glScalef(4, 4, 4); + polys += unit_sphere(slices, slices, MI_IS_WIREFRAME(mi)); + glPopMatrix(); + + /* Hand */ + glPushMatrix(); + glTranslatef (a[0].x, a[0].y, ARMLENGTH); + glScalef(8, 8, 8); + polys += unit_sphere(slices, slices, MI_IS_WIREFRAME(mi)); + glPopMatrix(); + + } + return polys; +} + +static int +show_figure(ModeInfo * mi, Bool init) +{ + int polys = 0; + jugglestruct *sp = &juggles[MI_SCREEN(mi)]; + /*XPoint p[7];*/ + int i; + + /* +-----+ 9 + | 6 | + 10 +--+--+ + 2 +---+---+ 3 + \ 5 / + \ / + \ / + 1 + + / \ + / \ + 0 +-----+ 4 + | | + | | + | | + 7 + + 8 + */ + + /* #### most of this is unused now */ + static const XPoint figure[] = { + { 15, 70}, /* 0 Left Hip */ + { 0, 90}, /* 1 Waist */ + { SX, 130}, /* 2 Left Shoulder */ + {-SX, 130}, /* 3 Right Shoulder */ + {-15, 70}, /* 4 Right Hip */ + { 0, 130}, /* 5 Neck */ + { 0, 140}, /* 6 Chin */ + { SX, 0}, /* 7 Left Foot */ + {-SX, 0}, /* 8 Right Foot */ + {-17, 174}, /* 9 Head1 */ + { 17, 140}, /* 10 Head2 */ + }; + XPoint a[countof(figure)]; + GLfloat gcolor[4] = { 1, 1, 1, 1 }; + + /* Translate into device coords */ + for(i = 0; i < countof(figure); i++) { + a[i].x = (short)(SCENE_WIDTH/2 + (sp->cx + figure[i].x)*sp->scale); + a[i].y = (short)(SCENE_HEIGHT - figure[i].y*sp->scale); + } + + glMaterialfv (GL_FRONT, GL_AMBIENT_AND_DIFFUSE, gcolor); + + glFrontFace(GL_CCW); + + { + GLfloat scale = ((GLfloat) a[10].x - a[9].x) / 2; + int slices = 12; + + glPushMatrix(); + { + glTranslatef(a[6].x, a[6].y - scale, 0); + glScalef(scale, scale, scale); + + /* Head */ + glMaterialfv (GL_FRONT, GL_AMBIENT_AND_DIFFUSE, body_color_1); + glPushMatrix(); + scale = 0.75; + glScalef(scale, scale, scale); + glTranslatef(0, 0.3, 0); + glPushMatrix(); + glTranslatef(0, 0, 0.35); + polys += tube (0, 0, 0, + 0, 1.1, 0, + 0.64, 0, + slices, True, True, MI_IS_WIREFRAME(mi)); + glPopMatrix(); + glScalef(0.9, 0.9, 1); + polys += unit_sphere(2*slices, 2*slices, MI_IS_WIREFRAME(mi)); + glPopMatrix(); + + /* Neck */ + glMaterialfv (GL_FRONT, GL_AMBIENT_AND_DIFFUSE, body_color_2); + glTranslatef(0, 1.1, 0); + glPushMatrix(); + scale = 0.35; + glScalef(scale, scale, scale); + polys += unit_sphere(slices, slices, MI_IS_WIREFRAME(mi)); + glPopMatrix(); + + /* Torso */ + glMaterialfv (GL_FRONT, GL_AMBIENT_AND_DIFFUSE, body_color_1); + glTranslatef(0, 1.1, 0); + glPushMatrix(); + glScalef(0.9, 1.0, 0.9); + polys += unit_sphere(slices, slices, MI_IS_WIREFRAME(mi)); + glPopMatrix(); + + /* Belly */ + glMaterialfv (GL_FRONT, GL_AMBIENT_AND_DIFFUSE, body_color_2); + glTranslatef(0, 1.0, 0); + glPushMatrix(); + scale = 0.6; + glScalef(scale, scale, scale); + polys += unit_sphere(slices, slices, MI_IS_WIREFRAME(mi)); + glPopMatrix(); + + /* Hips */ + glMaterialfv (GL_FRONT, GL_AMBIENT_AND_DIFFUSE, body_color_1); + glTranslatef(0, 0.8, 0); + glPushMatrix(); + scale = 0.85; + glScalef(scale, scale, scale); + polys += unit_sphere(slices, slices, MI_IS_WIREFRAME(mi)); + glPopMatrix(); + + + /* Legs */ + glTranslatef(0, 0.7, 0); + + for (i = -1; i <= 1; i += 2) { + glPushMatrix(); + + glRotatef (i*10, 0, 0, 1); + glTranslatef(-i*0.65, 0, 0); + + /* Hip socket */ + glMaterialfv (GL_FRONT, GL_AMBIENT_AND_DIFFUSE, body_color_2); + scale = 0.45; + glScalef(scale, scale, scale); + polys += unit_sphere(slices, slices, MI_IS_WIREFRAME(mi)); + + /* Thigh */ + glMaterialfv (GL_FRONT, GL_AMBIENT_AND_DIFFUSE, body_color_1); + glPushMatrix(); + glTranslatef(0, 0.6, 0); + polys += tube (0, 0, 0, + 0, 3.5, 0, + 1, 0, + slices, True, True, MI_IS_WIREFRAME(mi)); + glPopMatrix(); + + /* Knee */ + glMaterialfv (GL_FRONT, GL_AMBIENT_AND_DIFFUSE, body_color_2); + glPushMatrix(); + glTranslatef(0, 4.4, 0); + scale = 0.7; + glScalef(scale, scale, scale); + polys += unit_sphere(slices, slices, MI_IS_WIREFRAME(mi)); + glPopMatrix(); + + /* Calf */ + glMaterialfv (GL_FRONT, GL_AMBIENT_AND_DIFFUSE, body_color_1); + glPushMatrix(); + glTranslatef(0, 4.7, 0); + polys += tube (0, 0, 0, + 0, 4.7, 0, + 0.8, 0, + slices, True, True, MI_IS_WIREFRAME(mi)); + glPopMatrix(); + + /* Ankle */ + glMaterialfv (GL_FRONT, GL_AMBIENT_AND_DIFFUSE, body_color_2); + glPushMatrix(); + glTranslatef(0, 9.7, 0); + scale = 0.5; + glScalef(scale, scale, scale); + polys += unit_sphere(slices, slices, MI_IS_WIREFRAME(mi)); + glPopMatrix(); + + /* Foot */ + glMaterialfv (GL_FRONT, GL_AMBIENT_AND_DIFFUSE, body_color_1); + glPushMatrix(); + glRotatef (-i*10, 0, 0, 1); + glTranslatef(-i*1.75, 9.7, 0.9); + + glScalef (0.4, 1, 1); + polys += tube (0, 0, 0, + 0, 0.6, 0, + 1.9, 0, + slices*4, True, True, MI_IS_WIREFRAME(mi)); + glPopMatrix(); + + glPopMatrix(); + } + } + glPopMatrix(); + } + + sp->arm[1][LEFT][SHOULDER].x = sp->cx + figure[2].x; + sp->arm[1][RIGHT][SHOULDER].x = sp->cx + figure[3].x; + if(init) { + /* Initialise arms */ + unsigned int i; + for(i = 0; i < 2; i++){ + sp->arm[i][LEFT][SHOULDER].y = figure[2].y; + sp->arm[i][LEFT][ELBOW].x = figure[2].x; + sp->arm[i][LEFT][ELBOW].y = figure[1].y; + sp->arm[i][LEFT][HAND].x = figure[0].x; + sp->arm[i][LEFT][HAND].y = figure[1].y; + sp->arm[i][RIGHT][SHOULDER].y = figure[3].y; + sp->arm[i][RIGHT][ELBOW].x = figure[3].x; + sp->arm[i][RIGHT][ELBOW].y = figure[1].y; + sp->arm[i][RIGHT][HAND].x = figure[4].x; + sp->arm[i][RIGHT][HAND].y = figure[1].y; + } + } + return polys; +} + +typedef struct { GLfloat x, y, z; } XYZ; + +/* lifted from sphere.c */ +static int +striped_unit_sphere (int stacks, int slices, + int stripes, + GLfloat *color1, GLfloat *color2, + int wire_p) +{ + int polys = 0; + int i,j; + double theta1, theta2, theta3; + XYZ e, p; + XYZ la = { 0, 0, 0 }, lb = { 0, 0, 0 }; + XYZ c = {0, 0, 0}; /* center */ + double r = 1.0; /* radius */ + int stacks2 = stacks * 2; + + if (r < 0) + r = -r; + if (slices < 0) + slices = -slices; + + if (slices < 4 || stacks < 2 || r <= 0) + { + glBegin (GL_POINTS); + glVertex3f (c.x, c.y, c.z); + glEnd(); + return 1; + } + + glFrontFace(GL_CW); + + for (j = 0; j < stacks; j++) + { + theta1 = j * (M_PI+M_PI) / stacks2 - M_PI_2; + theta2 = (j + 1) * (M_PI+M_PI) / stacks2 - M_PI_2; + + glMaterialfv (GL_FRONT, GL_AMBIENT_AND_DIFFUSE, + ((j == 0 || j == stacks-1 || + j % (stacks / (stripes+1))) + ? color1 : color2)); + + glBegin (wire_p ? GL_LINE_LOOP : GL_TRIANGLE_STRIP); + for (i = 0; i <= slices; i++) + { + theta3 = i * (M_PI+M_PI) / slices; + + if (wire_p && i != 0) + { + glVertex3f (lb.x, lb.y, lb.z); + glVertex3f (la.x, la.y, la.z); + } + + e.x = cos (theta2) * cos(theta3); + e.y = sin (theta2); + e.z = cos (theta2) * sin(theta3); + p.x = c.x + r * e.x; + p.y = c.y + r * e.y; + p.z = c.z + r * e.z; + + glNormal3f (e.x, e.y, e.z); + glTexCoord2f (i / (double)slices, + 2*(j+1) / (double)stacks2); + glVertex3f (p.x, p.y, p.z); + if (wire_p) la = p; + + e.x = cos(theta1) * cos(theta3); + e.y = sin(theta1); + e.z = cos(theta1) * sin(theta3); + p.x = c.x + r * e.x; + p.y = c.y + r * e.y; + p.z = c.z + r * e.z; + + glNormal3f (e.x, e.y, e.z); + glTexCoord2f (i / (double)slices, + 2*j / (double)stacks2); + glVertex3f (p.x, p.y, p.z); + if (wire_p) lb = p; + polys++; + } + glEnd(); + } + return polys; +} + + + +static int +show_ball(ModeInfo *mi, unsigned long color, Trace *s) +{ + int polys = 0; + jugglestruct *sp = &juggles[MI_SCREEN(mi)]; + /*int offset = (int)(s->angle*64*180/M_PI);*/ + short x = (short)(SCENE_WIDTH/2 + s->x * sp->scale); + short y = (short)(SCENE_HEIGHT - s->y * sp->scale); + GLfloat gcolor1[4] = { 0, 0, 0, 1 }; + GLfloat gcolor2[4] = { 0, 0, 0, 1 }; + int slices = 24; + + /* Avoid wrapping */ + if(s->y*sp->scale > SCENE_HEIGHT * 2) return 0; + + gcolor1[0] = mi->colors[color].red / 65536.0; + gcolor1[1] = mi->colors[color].green / 65536.0; + gcolor1[2] = mi->colors[color].blue / 65536.0; + + gcolor2[0] = gcolor1[0] / 3; + gcolor2[1] = gcolor1[1] / 3; + gcolor2[2] = gcolor1[2] / 3; + + glFrontFace(GL_CCW); + + { + GLfloat scale = BALLRADIUS; + glPushMatrix(); + glTranslatef(x, y, 0); + glScalef(scale, scale, scale); + + glRotatef (s->angle / M_PI*180, 1, 1, 0); + + polys += striped_unit_sphere (slices, slices, s->divisions, + gcolor1, gcolor2, MI_IS_WIREFRAME(mi)); + glPopMatrix(); + } + return polys; +} + +static int +show_europeanclub(ModeInfo *mi, unsigned long color, Trace *s) +{ + int polys = 0; + jugglestruct *sp = &juggles[MI_SCREEN(mi)]; + /*int offset = (int)(s->angle*64*180/M_PI);*/ + short x = (short)(SCENE_WIDTH/2 + s->x * sp->scale); + short y = (short)(SCENE_HEIGHT - s->y * sp->scale); + double radius = 12 * sp->scale; + GLfloat gcolor1[4] = { 0, 0, 0, 1 }; + GLfloat gcolor2[4] = { 1, 1, 1, 1 }; + int slices = 16; + int divs = s->divisions; + divs = 4; + + /* 6 6 + +-+ + / \ + 4 +-----+ 7 + ////////\ + 3 +---------+ 8 + 2 +---------+ 9 + |///////| + 1 +-------+ 10 + | | + | | + | | + | | + | | + | | + +-+ + 0 11 */ + + /* Avoid wrapping */ + if(s->y*sp->scale > SCENE_HEIGHT * 2) return 0; + + gcolor1[0] = mi->colors[color].red / 65536.0; + gcolor1[1] = mi->colors[color].green / 65536.0; + gcolor1[2] = mi->colors[color].blue / 65536.0; + + glFrontFace(GL_CCW); + + { + GLfloat scale = radius; + glPushMatrix(); + glTranslatef(x, y, 0); + glScalef(scale, scale, scale); + + glTranslatef (0, 0, 2); /* put end of handle in hand */ + + glRotatef (s->angle / M_PI*180, 1, 0, 0); + + glPushMatrix(); + glScalef (0.5, 1, 0.5); + polys += striped_unit_sphere (slices, slices, divs, gcolor2, gcolor1, + MI_IS_WIREFRAME(mi)); + glPopMatrix(); + glMaterialfv (GL_FRONT, GL_AMBIENT_AND_DIFFUSE, gcolor2); + polys += tube (0, 0, 0, + 0, 2, 0, + 0.2, 0, + slices, True, True, MI_IS_WIREFRAME(mi)); + + glTranslatef (0, 2, 0); + glScalef (0.25, 0.25, 0.25); + polys += unit_sphere(slices, slices, MI_IS_WIREFRAME(mi)); + + glPopMatrix(); + } + return polys; +} + + +static int +show_torch(ModeInfo *mi, unsigned long color, Trace *s) +{ + int polys = 0; +#if 0 + jugglestruct *sp = &juggles[MI_SCREEN(mi)]; + XPoint head, tail, last; + DXPoint dhead, dlast; + const double sa = sin(s->angle); + const double ca = cos(s->angle); + + const double TailLen = -24; + const double HeadLen = 16; + const short Width = (short)(5 * sqrt(sp->scale)); + + /* + +///+ head + last | + | + | + | + | + + tail + */ + + dhead.x = s->x + HeadLen * PERSPEC * sa; + dhead.y = s->y - HeadLen * ca; + + if(color == MI_BLACK_PIXEL(mi)) { /* Use 'last' when erasing */ + dlast = s->dlast; + } else { /* Store 'last' so we can use it later when s->prev has + gone */ + if(s->prev != s->next) { + dlast.x = s->prev->x + HeadLen * PERSPEC * sin(s->prev->angle); + dlast.y = s->prev->y - HeadLen * cos(s->prev->angle); + } else { + dlast = dhead; + } + s->dlast = dlast; + } + + /* Avoid wrapping (after last is stored) */ + if(s->y*sp->scale > SCENE_HEIGHT * 2) return 0; + + head.x = (short)(SCENE_WIDTH/2 + dhead.x*sp->scale); + head.y = (short)(SCENE_HEIGHT - dhead.y*sp->scale); + + last.x = (short)(SCENE_WIDTH/2 + dlast.x*sp->scale); + last.y = (short)(SCENE_HEIGHT - dlast.y*sp->scale); + + tail.x = (short)(SCENE_WIDTH/2 + + (s->x + TailLen * PERSPEC * sa)*sp->scale ); + tail.y = (short)(SCENE_HEIGHT - (s->y - TailLen * ca)*sp->scale ); + + if(color != MI_BLACK_PIXEL(mi)) { + XSetForeground(MI_DISPLAY(mi), MI_GC(mi), MI_BLACK_PIXEL(mi)); + XSetLineAttributes(MI_DISPLAY(mi), MI_GC(mi), + Width, LineSolid, CapRound, JoinRound); + draw_line(mi, head.x, head.y, tail.x, tail.y); + } + XSetForeground(MI_DISPLAY(mi), MI_GC(mi), color); + XSetLineAttributes(MI_DISPLAY(mi), MI_GC(mi), + Width * 2, LineSolid, CapRound, JoinRound); + + draw_line(mi, head.x, head.y, last.x, last.y); + +#endif /* 0 */ + return polys; +} + + +static int +show_knife(ModeInfo *mi, unsigned long color, Trace *s) +{ + int polys = 0; + jugglestruct *sp = &juggles[MI_SCREEN(mi)]; + /*int offset = (int)(s->angle*64*180/M_PI);*/ + short x = (short)(SCENE_WIDTH/2 + s->x * sp->scale); + short y = (short)(SCENE_HEIGHT - s->y * sp->scale); + GLfloat gcolor1[4] = { 0, 0, 0, 1 }; + GLfloat gcolor2[4] = { 1, 1, 1, 1 }; + int slices = 8; + + /* Avoid wrapping */ + if(s->y*sp->scale > SCENE_HEIGHT * 2) return 0; + + gcolor1[0] = mi->colors[color].red / 65536.0; + gcolor1[1] = mi->colors[color].green / 65536.0; + gcolor1[2] = mi->colors[color].blue / 65536.0; + + glFrontFace(GL_CCW); + + glPushMatrix(); + glTranslatef(x, y, 0); + glScalef (2, 2, 2); + + glTranslatef (0, 0, 2); /* put end of handle in hand */ + glRotatef (s->angle / M_PI*180, 1, 0, 0); + + glScalef (0.3, 1, 1); /* flatten blade */ + + glTranslatef(0, 6, 0); + glRotatef (180, 1, 0, 0); + + glMaterialfv (GL_FRONT, GL_AMBIENT_AND_DIFFUSE, gcolor1); + polys += tube (0, 0, 0, + 0, 10, 0, + 1, 0, + slices, True, True, MI_IS_WIREFRAME(mi)); + + glTranslatef (0, 12, 0); + glScalef (0.7, 10, 0.7); + glMaterialfv (GL_FRONT, GL_AMBIENT_AND_DIFFUSE, gcolor2); + polys += unit_sphere (slices, slices, MI_IS_WIREFRAME(mi)); + + glPopMatrix(); + return polys; +} + + +static int +show_ring(ModeInfo *mi, unsigned long color, Trace *s) +{ + int polys = 0; + jugglestruct *sp = &juggles[MI_SCREEN(mi)]; + /*int offset = (int)(s->angle*64*180/M_PI);*/ + short x = (short)(SCENE_WIDTH/2 + s->x * sp->scale); + short y = (short)(SCENE_HEIGHT - s->y * sp->scale); + double radius = 12 * sp->scale; + GLfloat gcolor1[4] = { 0, 0, 0, 1 }; + GLfloat gcolor2[4] = { 0, 0, 0, 1 }; + int slices = 24; + int i, j; + int wire_p = MI_IS_WIREFRAME(mi); + GLfloat width = M_PI * 2 / slices; + GLfloat ra = 1.0; + GLfloat rb = 0.7; + GLfloat thickness = 0.15; + + /* Avoid wrapping */ + if(s->y*sp->scale > SCENE_HEIGHT * 2) return 0; + + gcolor1[0] = mi->colors[color].red / 65536.0; + gcolor1[1] = mi->colors[color].green / 65536.0; + gcolor1[2] = mi->colors[color].blue / 65536.0; + + gcolor2[0] = gcolor1[0] / 3; + gcolor2[1] = gcolor1[1] / 3; + gcolor2[2] = gcolor1[2] / 3; + + glFrontFace(GL_CCW); + + glPushMatrix(); + glTranslatef(0, 0, 12); /* back of ring in hand */ + + glTranslatef(x, y, 0); + glScalef(radius, radius, radius); + + glRotatef (90, 0, 1, 0); + glRotatef (s->angle / M_PI*180, 0, 0, 1); + + glMaterialfv (GL_FRONT, GL_AMBIENT_AND_DIFFUSE, gcolor1); + + /* discs */ + for (j = -1; j <= 1; j += 2) + { + GLfloat z = j * thickness/2; + glFrontFace (j < 0 ? GL_CCW : GL_CW); + glNormal3f (0, 0, j*1); + glBegin (wire_p ? GL_LINES : GL_QUAD_STRIP); + for (i = 0; i < slices + (wire_p ? 0 : 1); i++) { + GLfloat th, cth, sth; + glMaterialfv (GL_FRONT, GL_AMBIENT_AND_DIFFUSE, + (i % (slices/3) ? gcolor1 : gcolor2)); + th = i * width; + cth = cos(th); + sth = sin(th); + glVertex3f (cth * ra, sth * ra, z); + glVertex3f (cth * rb, sth * rb, z); + polys++; + } + glEnd(); + } + + /* outer ring */ + glFrontFace (GL_CCW); + glBegin (wire_p ? GL_LINES : GL_QUAD_STRIP); + for (i = 0; i < slices + (wire_p ? 0 : 1); i++) + { + GLfloat th = i * width; + GLfloat cth = cos(th); + GLfloat sth = sin(th); + glNormal3f (cth, sth, 0); + glVertex3f (cth * ra, sth * ra, thickness/2); + glVertex3f (cth * ra, sth * ra, -thickness/2); + polys++; + } + glEnd(); + + /* inner ring */ + glFrontFace (GL_CW); + glBegin (wire_p ? GL_LINES : GL_QUAD_STRIP); + for (i = 0; i < slices + (wire_p ? 0 : 1); i++) + { + GLfloat th = i * width; + GLfloat cth = cos(th); + GLfloat sth = sin(th); + glNormal3f (-cth, -sth, 0); + glVertex3f (cth * rb, sth * ra, thickness/2); + glVertex3f (cth * rb, sth * ra, -thickness/2); + polys++; + } + glEnd(); + + glFrontFace (GL_CCW); + glPopMatrix(); + return polys; +} + + +static int +show_bball(ModeInfo *mi, unsigned long color, Trace *s) +{ + int polys = 0; + jugglestruct *sp = &juggles[MI_SCREEN(mi)]; + /*int offset = (int)(s->angle*64*180/M_PI);*/ + short x = (short)(SCENE_WIDTH/2 + s->x * sp->scale); + short y = (short)(SCENE_HEIGHT - s->y * sp->scale); + double radius = 12 * sp->scale; + GLfloat gcolor1[4] = { 0, 0, 0, 1 }; + GLfloat gcolor2[4] = { 0, 0, 0, 1 }; + int slices = 16; + int i, j; + + /* Avoid wrapping */ + if(s->y*sp->scale > SCENE_HEIGHT * 2) return 0; + + gcolor1[0] = mi->colors[color].red / 65536.0; + gcolor1[1] = mi->colors[color].green / 65536.0; + gcolor1[2] = mi->colors[color].blue / 65536.0; + + glFrontFace(GL_CCW); + + { + GLfloat scale = radius; + glPushMatrix(); + + glTranslatef(0, -6, 5); /* position on top of hand */ + + glTranslatef(x, y, 0); + glScalef(scale, scale, scale); + glRotatef (s->angle / M_PI*180, 1, 0, 1); + + glMaterialfv (GL_FRONT, GL_AMBIENT_AND_DIFFUSE, gcolor1); + polys += unit_sphere (slices, slices, MI_IS_WIREFRAME(mi)); + + glRotatef (90, 0, 0, 1); + glTranslatef (0, 0, 0.81); + glScalef(0.15, 0.15, 0.15); + glMaterialfv (GL_FRONT, GL_AMBIENT_AND_DIFFUSE, gcolor2); + for (i = 0; i < 3; i++) { + glPushMatrix(); + glTranslatef (0, 0, 1); + glRotatef (360 * i / 3, 0, 0, 1); + glTranslatef (2, 0, 0); + glRotatef (18, 0, 1, 0); + glBegin (MI_IS_WIREFRAME(mi) ? GL_LINE_LOOP : GL_TRIANGLE_FAN); + glVertex3f (0, 0, 0); + for (j = slices; j >= 0; j--) { + GLfloat th = j * M_PI*2 / slices; + glVertex3f (cos(th), sin(th), 0); + polys++; + } + glEnd(); + glPopMatrix(); + } + + glPopMatrix(); + } + return polys; +} + + +/************************************************************************** + * Public Functions * + * * + **************************************************************************/ + + +ENTRYPOINT void +release_juggle (ModeInfo * mi) +{ + if (juggles != NULL) { + int screen; + + for (screen = 0; screen < MI_NUM_SCREENS(mi); screen++) + free_juggle(&juggles[screen]); + free(juggles); + juggles = (jugglestruct *) NULL; + } +} + +/* FIXME: refill_juggle currently just appends new throws to the + * programme. This is fine if the programme is empty, but if there + * are still some trajectories left then it really should take these + * into account */ + +static void +refill_juggle(ModeInfo * mi) +{ + jugglestruct *sp = NULL; + int i; + + if (juggles == NULL) + return; + sp = &juggles[MI_SCREEN(mi)]; + + /* generate pattern */ + + if (pattern == NULL) { + +#define MAXPAT 10 +#define MAXREPEAT 300 +#define CHANGE_BIAS 8 /* larger makes num_ball changes less likely */ +#define POSITION_BIAS 20 /* larger makes hand movements less likely */ + + int count = 0; + while (count < MI_CYCLES(mi)) { + char buf[MAXPAT * 3 + 3], *b = buf; + int maxseen = 0; + int l = NRAND(MAXPAT) + 1; + int t = NRAND(MIN(MAXREPEAT, (MI_CYCLES(mi) - count))) + 1; + + { /* vary number of balls */ + int new_balls = sp->num_balls; + int change; + + if (new_balls == 2) /* Do not juggle 2 that often */ + change = NRAND(2 + CHANGE_BIAS / 4); + else + change = NRAND(2 + CHANGE_BIAS); + switch (change) { + case 0: + new_balls++; + break; + case 1: + new_balls--; + break; + default: + break; /* NO-OP */ + } + if (new_balls < sp->patternindex.minballs) { + new_balls += 2; + } + if (new_balls > sp->patternindex.maxballs) { + new_balls -= 2; + } + if (new_balls < sp->num_balls) { + if (!program(mi, "[*]", NULL, 1)) /* lose ball */ + return; + } + sp->num_balls = new_balls; + } + + count += t; + if (NRAND(2) && sp->patternindex.index[sp->num_balls].number) { + /* Pick from PortFolio */ + int p = sp->patternindex.index[sp->num_balls].start + + NRAND(sp->patternindex.index[sp->num_balls].number); + if (!program(mi, portfolio[p].pattern, portfolio[p].name, t)) + return; + } else { + /* Invent a new pattern */ + *b++='['; + for(i = 0; i < l; i++){ + int n, m; + do { /* Triangular Distribution => high values more likely */ + m = NRAND(sp->num_balls + 1); + n = NRAND(sp->num_balls + 1); + } while(m >= n); + if (n == sp->num_balls) { + maxseen = 1; + } + switch(NRAND(5 + POSITION_BIAS)){ + case 0: /* Outside throw */ + *b++ = '+'; break; + case 1: /* Cross throw */ + *b++ = '='; break; + case 2: /* Cross catch */ + *b++ = '&'; break; + case 3: /* Cross throw and catch */ + *b++ = 'x'; break; + case 4: /* Bounce */ + *b++ = '_'; break; + default: + break; /* Inside throw (default) */ + } + + *b++ = n + '0'; + *b++ = ' '; + } + *b++ = ']'; + *b = '\0'; + if (maxseen) { + if (!program(mi, buf, NULL, t)) + return; + } + } + } + } else { /* pattern supplied in height or 'a' notation */ + if (!program(mi, pattern, NULL, MI_CYCLES(mi))) + return; + } + + adam(sp); + + name(sp); + + if (!part(sp)) + return; + + lob(mi); + + clap(sp); + + positions(sp); + + if (!projectile(sp)) { + free_juggle(sp); + return; + } + + hands(sp); +#ifdef DEBUG + if(MI_IS_DEBUG(mi)) dump(sp); +#endif +} + +static void +change_juggle(ModeInfo * mi) +{ + jugglestruct *sp = NULL; + Trajectory *t; + + if (juggles == NULL) + return; + sp = &juggles[MI_SCREEN(mi)]; + + /* Strip pending trajectories */ + for (t = sp->head->next; t != sp->head; t = t->next) { + if(t->start > sp->time || t->finish < sp->time) { + Trajectory *n = t; + t=t->prev; + trajectory_destroy(n); + } + } + + /* Pick the current object theme */ + sp->objtypes = choose_object(); + + refill_juggle(mi); + + mi->polygon_count += show_figure(mi, True); +} + + +ENTRYPOINT void +reshape_juggle (ModeInfo *mi, int width, int height) +{ + GLfloat h = (GLfloat) height / (GLfloat) width; + + glViewport (0, 0, (GLint) width, (GLint) height); + + glMatrixMode(GL_PROJECTION); + glLoadIdentity(); + gluPerspective (30.0, 1/h, 1.0, 100.0); + + glMatrixMode(GL_MODELVIEW); + glLoadIdentity(); + gluLookAt( 0.0, 0.0, 30.0, + 0.0, 0.0, 0.0, + 0.0, 1.0, 0.0); + + glClear(GL_COLOR_BUFFER_BIT); +} + + +ENTRYPOINT void +init_juggle (ModeInfo * mi) +{ + jugglestruct *sp = 0; + int wire = MI_IS_WIREFRAME(mi); + + if (!juggles) { + juggles = (jugglestruct *) + calloc (MI_NUM_SCREENS(mi), sizeof (jugglestruct)); + if (!juggles) { + fprintf(stderr, "%s: out of memory\n", progname); + exit(1); + } + } + + sp = &juggles[MI_SCREEN(mi)]; + + sp->glx_context = init_GL(mi); + +# ifdef HAVE_GLBITMAP + load_font (mi->dpy, "titleFont", &sp->mode_font, &sp->font_dlist); +# else /* !HAVE_GLBITMAP */ + sp->font_data = load_texture_font (mi->dpy, "titleFont"); +# endif /* !HAVE_GLBITMAP */ + + reshape_juggle (mi, MI_WIDTH(mi), MI_HEIGHT(mi)); + clear_gl_error(); /* WTF? sometimes "invalid op" from glViewport! */ + + if (!wire) + { + GLfloat pos[4] = {1.0, 1.0, 1.0, 0.0}; + GLfloat amb[4] = {0.0, 0.0, 0.0, 1.0}; + GLfloat dif[4] = {1.0, 1.0, 1.0, 1.0}; + GLfloat spc[4] = {0.0, 1.0, 1.0, 1.0}; + + glEnable(GL_LIGHTING); + glEnable(GL_LIGHT0); + glEnable(GL_DEPTH_TEST); + glEnable(GL_CULL_FACE); + + glLightfv(GL_LIGHT0, GL_POSITION, pos); + glLightfv(GL_LIGHT0, GL_AMBIENT, amb); + glLightfv(GL_LIGHT0, GL_DIFFUSE, dif); + glLightfv(GL_LIGHT0, GL_SPECULAR, spc); + } + + make_random_colormap (0, 0, 0, + mi->colors, &MI_NPIXELS(mi), + True, False, 0, False); + + { + double spin_speed = 0.05; + double wander_speed = 0.001; + double spin_accel = 0.05; + sp->rot = make_rotator (0, spin_speed, 0, + spin_accel, wander_speed, False); + sp->trackball = gltrackball_init (); + } + + if (only && *only && strcmp(only, " ")) { + balls = clubs = torches = knives = rings = bballs = False; + if (!strcasecmp (only, "balls")) balls = True; + else if (!strcasecmp (only, "clubs")) clubs = True; + else if (!strcasecmp (only, "torches")) torches = True; + else if (!strcasecmp (only, "knives")) knives = True; + else if (!strcasecmp (only, "rings")) rings = True; + else if (!strcasecmp (only, "bballs")) bballs = True; + else { + (void) fprintf (stderr, + "Juggle: -only must be one of: balls, clubs, torches, knives,\n" + "\t rings, or bballs (not \"%s\")\n", only); +#ifdef STANDALONE /* xlock mustn't exit merely because of a bad argument */ + exit (1); +#endif + } + } + + /* #### hard to make this look good in OpenGL... */ + torches = False; + + + if (sp->head == 0) { /* first time initializing this juggler */ + + sp->count = ABS(MI_COUNT(mi)); + if (sp->count == 0) + sp->count = 200; + + /* record start time */ + sp->begintime = time(NULL); + if(sp->patternindex.maxballs > 0) { + sp->num_balls = sp->patternindex.minballs + + NRAND(sp->patternindex.maxballs - sp->patternindex.minballs); + } + + mi->polygon_count += + show_figure(mi, True); /* Draw figure. Also discovers + information about the juggler's + proportions */ + + /* "7" should be about three times the height of the juggler's + shoulders */ + sp->Gr = -GRAVITY(3 * sp->arm[0][RIGHT][SHOULDER].y, + 7 * THROW_CATCH_INTERVAL); + + if(!balls && !clubs && !torches && !knives && !rings && !bballs) + balls = True; /* Have to juggle something! */ + + /* create circular trajectory list */ + ADD_ELEMENT(Trajectory, sp->head, sp->head); + if(sp->head == NULL){ + free_juggle(sp); + return; + } + + /* create circular object list */ + ADD_ELEMENT(Object, sp->objects, sp->objects); + if(sp->objects == NULL){ + free_juggle(sp); + return; + } + + sp->pattern = strdup(""); /* Initialise saved pattern with + free-able memory */ + } + + sp = &juggles[MI_SCREEN(mi)]; + + if (pattern && + (!*pattern || + !strcasecmp (pattern, ".") || + !strcasecmp (pattern, "random"))) + pattern = NULL; + + if (pattern == NULL && sp->patternindex.maxballs == 0) { + /* pattern list needs indexing */ + int nelements = countof(portfolio); + int numpat = 0; + int i; + + /* sort according to number of balls */ + qsort((void*)portfolio, nelements, + sizeof(portfolio[1]), compare_num_balls); + + /* last pattern has most balls */ + sp->patternindex.maxballs = get_num_balls(portfolio[nelements - 1].pattern); + /* run through sorted list, indexing start of each group + and number in group */ + sp->patternindex.maxballs = 1; + for (i = 0; i < nelements; i++) { + int b = get_num_balls(portfolio[i].pattern); + if (b > sp->patternindex.maxballs) { + sp->patternindex.index[sp->patternindex.maxballs].number = numpat; + if(numpat == 0) sp->patternindex.minballs = b; + sp->patternindex.maxballs = b; + numpat = 1; + sp->patternindex.index[sp->patternindex.maxballs].start = i; + } else { + numpat++; + } + } + sp->patternindex.index[sp->patternindex.maxballs].number = numpat; + } + + /* Set up programme */ + change_juggle(mi); + + /* Only put things here that won't interrupt the programme during + a window resize */ + + /* Use MIN so that users can resize in interesting ways, eg + narrow windows for tall patterns, etc */ + sp->scale = MIN(SCENE_HEIGHT/480.0, SCENE_WIDTH/160.0); + +} + +ENTRYPOINT Bool +juggle_handle_event (ModeInfo *mi, XEvent *event) +{ + jugglestruct *sp = &juggles[MI_SCREEN(mi)]; + + if (event->xany.type == ButtonPress && + event->xbutton.button == Button1) + { + sp->button_down_p = True; + gltrackball_start (sp->trackball, + event->xbutton.x, event->xbutton.y, + MI_WIDTH (mi), MI_HEIGHT (mi)); + return True; + } + else if (event->xany.type == ButtonRelease && + event->xbutton.button == Button1) + { + sp->button_down_p = False; + return True; + } + else if (event->xany.type == ButtonPress && + (event->xbutton.button == Button4 || + event->xbutton.button == Button5 || + event->xbutton.button == Button6 || + event->xbutton.button == Button7)) + { + gltrackball_mousewheel (sp->trackball, event->xbutton.button, 10, + !!event->xbutton.state); + return True; + } + else if (event->xany.type == MotionNotify && + sp->button_down_p) + { + gltrackball_track (sp->trackball, + event->xmotion.x, event->xmotion.y, + MI_WIDTH (mi), MI_HEIGHT (mi)); + return True; + } + else if (event->xany.type == KeyPress) + { + KeySym keysym; + char c = 0; + XLookupString (&event->xkey, &c, 1, &keysym, 0); + if (c == ' ' || c == '\n' || c == '\r' || c == '\t') + { + change_juggle (mi); + return True; + } + } + + + return False; +} + + +ENTRYPOINT void +draw_juggle (ModeInfo *mi) +{ + jugglestruct *sp = &juggles[MI_SCREEN(mi)]; + Display *dpy = MI_DISPLAY(mi); + Window window = MI_WINDOW(mi); + + Trajectory *traj = NULL; + Object *o = NULL; + unsigned long future = 0; + char *pattern = NULL; + + if (!sp->glx_context) + return; + + glXMakeCurrent(MI_DISPLAY(mi), MI_WINDOW(mi), *(sp->glx_context)); + + glShadeModel(GL_SMOOTH); + + glEnable(GL_DEPTH_TEST); + glEnable(GL_NORMALIZE); + glEnable(GL_CULL_FACE); + + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + + glPushMatrix (); + glRotatef(current_device_rotation(), 0, 0, 1); + + glTranslatef(0,-3,0); + + { + double x, y, z; + get_position (sp->rot, &x, &y, &z, !sp->button_down_p); + glTranslatef((x - 0.5) * 8, + (y - 0.5) * 3, + (z - 0.5) * 15); + + gltrackball_rotate (sp->trackball); + + get_rotation (sp->rot, &x, &y, &z, !sp->button_down_p); + + if (y < 0.8) y = 0.8 - (y - 0.8); /* always face forward */ + if (y > 1.2) y = 1.2 - (y - 1.2); + + 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); + } + + { + GLfloat scale = 20.0 / SCENE_HEIGHT; + glScalef(scale, scale, scale); + } + + glRotatef (180, 0, 0, 1); + glTranslatef(-SCENE_WIDTH/2, -SCENE_HEIGHT/2, 0); + glTranslatef(0, -150, 0); + + mi->polygon_count = 0; + + /* Update timer */ + if (real) { + struct timeval tv; + (void)gettimeofday(&tv, NULL); + sp->time = (int) ((tv.tv_sec - sp->begintime)*1000 + tv.tv_usec/1000); + } else { + sp->time += MI_DELAY(mi) / 1000; + } + + /* First pass: Move arms and strip out expired elements */ + for (traj = sp->head->next; traj != sp->head; traj = traj->next) { + if (traj->status != PREDICTOR) { + /* Skip any elements that need further processing */ + /* We could remove them, but there shoudn't be many and they + would be needed if we ever got the pattern refiller + working */ + continue; + } + if (traj->start > future) { /* Lookahead to the end of the show */ + future = traj->start; + } + if (sp->time < traj->start) { /* early */ + continue; + } else if (sp->time < traj->finish) { /* working */ + + /* Look for pattern name */ + if(traj->pattern != NULL) { + pattern=traj->pattern; + } + + if (traj->type == Empty || traj->type == Full) { + /* Only interested in hands on this pass */ +/* double angle = traj->angle + traj->spin * (sp->time - traj->start);*/ + double xd = 0, yd = 0; + DXPoint p; + + /* Find the catching offset */ + if(traj->object != NULL) { +#if 0 + /* #### not sure what this is doing, but I'm guessing + that the use of PERSPEC means this isn't needed + in the OpenGL version? -jwz + */ + if(ObjectDefs[traj->object->type].handle > 0) { + /* Handles Need to be oriented */ + xd = ObjectDefs[traj->object->type].handle * + PERSPEC * sin(angle); + yd = ObjectDefs[traj->object->type].handle * + cos(angle); + } else +#endif + { + /* Balls are always caught at the bottom */ + xd = 0; + yd = -4; + } + } + p.x = (CUBIC(traj->xp, sp->time) - xd); + p.y = (CUBIC(traj->yp, sp->time) + yd); + reach_arm(mi, traj->hand, &p); + + /* Store updated hand position */ + traj->x = p.x + xd; + traj->y = p.y - yd; + } + if (traj->type == Ball || traj->type == Full) { + /* Only interested in objects on this pass */ + double x, y; + Trace *s; + + if(traj->type == Full) { + /* Adjusted these in the first pass */ + x = traj->x; + y = traj->y; + } else { + x = CUBIC(traj->xp, sp->time); + y = CUBIC(traj->yp, sp->time); + } + + ADD_ELEMENT(Trace, s, traj->object->trace->prev); + s->x = x; + s->y = y; + s->angle = traj->angle + traj->spin * (sp->time - traj->start); + s->divisions = traj->divisions; + traj->object->tracelen++; + traj->object->active = True; + } + } else { /* expired */ + Trajectory *n = traj; + traj=traj->prev; + trajectory_destroy(n); + } + } + + + mi->polygon_count += show_figure(mi, False); + mi->polygon_count += show_arms(mi); + + /* Draw Objects */ + glTranslatef(0, 0, ARMLENGTH); + for (o = sp->objects->next; o != sp->objects; o = o->next) { + if(o->active) { + mi->polygon_count += ObjectDefs[o->type].draw(mi, o->color, + o->trace->prev); + o->active = False; + } + } + + + /* Save pattern name so we can erase it when it changes */ + if(pattern != NULL && strcmp(sp->pattern, pattern) != 0 ) { + free(sp->pattern); + sp->pattern = strdup(pattern); + + if (MI_IS_VERBOSE(mi)) { + (void) fprintf(stderr, "Juggle[%d]: Running: %s\n", + MI_SCREEN(mi), sp->pattern); + } + } + + print_gl_string (mi->dpy, +# ifdef HAVE_GLBITMAP + sp->mode_font, sp->font_dlist, +# else /* !HAVE_GLBITMAP */ + sp->font_data, +# endif /* !HAVE_GLBITMAP */ + mi->xgwa.width, mi->xgwa.height, + 10, mi->xgwa.height - 10, + sp->pattern, False); + +#ifdef MEMTEST + if((int)(sp->time/10) % 1000 == 0) + (void) fprintf(stderr, "sbrk: %d\n", (int)sbrk(0)); +#endif + + if (future < sp->time + 100 * THROW_CATCH_INTERVAL) { + refill_juggle(mi); + } else if (sp->time > 1<<30) { /* Hard Reset before the clock wraps */ + release_juggle(mi); + init_juggle(mi); + } + + glPopMatrix (); + + if (mi->fps_p) do_fps (mi); + glFinish(); + + glXSwapBuffers(dpy, window); +} + +XSCREENSAVER_MODULE_2 ("Juggler3D", juggler3d, juggle) + +#endif /* USE_GL */ diff --git a/hacks/glx/juggler3d.man b/hacks/glx/juggler3d.man new file mode 100644 index 00000000..48d47160 --- /dev/null +++ b/hacks/glx/juggler3d.man @@ -0,0 +1,183 @@ +'\" t +.\" ** The above line should force tbl to be used as a preprocessor ** +.TH XScreenSaver 1 "" "X Version 11" +.SH NAME +juggler3d - juggling man screen saver. +.SH SYNOPSIS +.B juggler3d +[\-display host:display.screen ] +[\-root ] +[\-window ] +[\-mono ] +[\-install | \-noinstall ] +[\-visual visual ] +[\-window\-id id ] +[\-pattern pattern ] +[\-tail number ] +[\-real | \-no\-real ] +[\-describe | \-no\-describe ] +[\-balls | \-no\-balls ] +[\-clubs | \-no\-clubs ] +[\-torches | \-no\-torches ] +[\-knives | \-no\-knives ] +[\-rings | \-no\-rings ] +[\-bballs | \-no\-bballs ] +[\-count count ] +[\-cycles cycles ] +[\-delay delay ] +[\-ncolors ncolors ] +[\-fps] +.SH DESCRIPTION +Draws a stick-man juggling various collections of objects. +.SH OPTIONS +.I juggler3d +accepts the following options: +.TP 8 +.B \-display host:display.screen +X11 display to use. Overrides +.B DISPLAY +environment variable. +.TP 8 +.B \-root +Draw on the root window. +.TP 8 +.B \-window +Draw on a newly-created X window. This is the default. +.TP 8 +.B \-mono +Draw in monochrome. +.TP 8 +.B \-install | \-noinstall +Turn on/off installing colormap. +.TP 8 +.B \-visual visual +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\-id id +Draw on an already existing X window. +.TP 8 +.B \-pattern\ \(dq pattern \(dq +Specify juggling pattern in annotated +.B site-swap +notation. In +.B site-swap +notation, the "height" of each throw is given. E.g., "3" is the height +needed to juggle a 3\-Cascade. Note that these sequences need to be +chosen carefully, to avoid collisions. + +Annotations indicate relative hand movements or tricks: +.TS +cb l. +\&\- Inside throw (default) ++ Outside throw +\&= Cross Throw +& Cross Catch +x Cross Throw and Catch +\&_ Bounce +.TE +.TP 8 +.B \-pattern\ \(dq[ pattern ]\(dq +Specify juggling pattern in annotated +.B Adam +notation. Adam notation is a little harder to visualize. Each +integer +.B n +represents a cyclic permutation of (0...n). The equivalent +.B site-swap +value is determined by calculating how many of the permutations it +takes to get back to the identity. The largest number used is the +same as the number of objects in the pattern. The advantage of Adam +notation is that these sequences do not need to be chosen carefully, +since all possible sequences are juggle-able. Annotations are the same +as in +.B site-swap +notation. + +For example, both of these describe a 3\-Shower: +.IP +.B \-pattern\ "+5 1" +.IP +.B \-pattern\ "[+3 1]" + +For further examples, see the +.B portfolio +list in the source code. +.TP 8 +.B \-tail number +Minimum Trail Length. 0 \- 100. Default: 1. Objects may override +this, for example flaming torches always leave a trail. +.TP 8 +.BR \-real | \-no\-real +Turn on/off real-time juggling. +.B Deprecated. +There should be no need to turn off real-time juggling, even on slow +systems. Adjust speed using +.B \-count +above. +.TP 8 +.BR \-describe | \-no\-describe +Turn on/off pattern descriptions. +.TP 8 +.BR \-balls | \-no\-balls +Turn on/off Balls. +.TP 8 +.BR \-clubs | \-no\-clubs +Turn on/off Clubs. +.TP 8 +.BR \-torches | \-no\-torches +Turn on/off Flaming Torches. +.TP 8 +.BR \-knives | \-no\-knives +Turn on/off Knives. +.TP 8 +.BR \-rings | \-no\-rings +Turn on/off Rings. +.TP 8 +.BR \-bballs | \-no\-bballs +Turn on/off Bowling Balls. +.TP 8 +.B \-count number +Speed. 50 \- 1000. Default: 200. This determines the expected time +interval between a throw and the next catch, in milliseconds. +.TP 8 +.B \-cycles number +Performance Length. 50 \- 1000. Default: 1000. Setting this smaller +will force the juggler to switch patterns (and objects) more often. +.TP 8 +.B \-delay delay +Additional delay between frames, in microseconds. Default: 10000. +.B Deprecated. +Adjust speed using +.BR \-count . +.TP 8 +.B \-ncolors ncolors +Maximum number of colors to use. Default: 32. +.TP 8 +.B \-fps +Display the current frame rate and CPU load. +.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 1996,2000,2002,2004 by Tim Auckland. 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 +Tim Auckland. + +Converted to OpenGL by Jamie Zawinski, 2009. diff --git a/hacks/glx/jwzgles.c b/hacks/glx/jwzgles.c new file mode 100644 index 00000000..f70b120b --- /dev/null +++ b/hacks/glx/jwzgles.c @@ -0,0 +1,3807 @@ +/* xscreensaver, Copyright (c) 2012 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. + */ + +/* A compatibility shim to allow OpenGL 1.3 source code to work in an + OpenGLES environment, where almost every OpenGL 1.3 function has + been "deprecated". + + There are two major operations going on here: + + - Converting calls to glBegin + glVertex3f + glEnd to glDrawArrays + - Implementing display lists. + + + From an API point of view, OpenGL 1.3 and earlier code looks like this: + + glLightfv (GL_LIGHT0, GL_POSITION, ...); + glLightfv (GL_LIGHT0, GL_AMBIENT, ...); + + glMatrixMode (GL_PROJECTION); + glLoadIdentity (); + gluPerspective (...); + + glMatrixMode (GL_MODELVIEW); + glLoadIdentity (); + gluLookAt (...); + + glPushMatrix (); + + glRotatef (...); + + glColor3f (...); + + glBegin (GL_TRIANGLES); + glNormal3f (...); + glVertex3f (...); + glVertex3f (...); + glVertex3f (...); + glEnd (); + + glPopMatrix (); + + glFinish (); + + + OpenGLES broke that model by eliminating glBegin(). Instead of + iterating a sequence of vertexes, you need to pack your points into + an array first, e.g.: + + GLfloat coords[] = { + 0, 0, 0, + 0, 1, 0, + ... + }; + + glDrawArrays (GL_TRIANGLES, 0, 3); + + The projection model (glRotatef, etc.) works the same, but glColor() + is missing. You're expected to encode that into your arrays. + + Also, OpenGLES doesn't support display lists at all. + + + So this code shadows all of the functions that are allowed within + glBegin, builds up an array, and calls glDrawArrays at the end. + + Likewise, it shadows all of the functions that are allowed within + glNewList and records those calls for later playback. + + + This code only handles OpenGLES 1.x, not 2.x. + + OpenGLES 2.0 broke things further by eliminating the whole OpenGL + lighting model. Instead of specifying the positions and properties + of your lights using the glLight* API, now you are expected to + implement it all yourself by downloading C-like code into the GPU + directly. This is more flexible, in that if you wanted a completely + different lighting model than what OpenGL provides, you could do + that, but it leaves you needing to download boilerplate to reproduce + what used to be built in. + + + Incidentally, the OpenGL numbering scheme goes something like this: + + OpenGL 1.0 1992 + OpenGL 1.1 1997 (improved texture support) + OpenGL 1.2 1998 (nothing interesting) + OpenGL 1.3 2001 (multisampling, cubemaps) + OpenGL 1.4 2002 (added auto-mipmapping) + OpenGLES 1.0 2003 (deprecated 80% of the language; fork of OpenGL 1.3) + OpenGL 1.5 2003 (added VBOs) + OpenGLES 1.1 2004 (fork of OpenGL 1.5) + OpenGL 2.0 2004 (a political quagmire) + OpenGLES 2.0 2007 (deprecated 95% of the language; fork of OpenGL 2.0) + OpenGL 3.0 2008 (added FBOs, VAOs, deprecated 60% of the language) + + + Some things that are missing: + + - glTexGeni, meaning no spherical environment-mapping textures. + + - gluNewTess, meaning no tesselation of complex objects. + + - glMap2f mesh evaluators, meaning no Utah Teapot. + + - glPolygonMode with GL_LINE or GL_POINT, meaning no wireframe modes + that do hidden-surface removal. + + - glSelectBuffer, meaning no mouse-hit detection on rendered objects. + + - gluNewQuadric, gluCylinder, etc: rewrite your code to use tube.c, etc. + + - Putting verts in a display list without a wrapping glBegin. + (I didn't realize that even worked!) + + - Not every function is implemented; just the ones that I needed for + xscreensaver. However, the trivial ones are trivial to enable + as they come up. Harder ones will be harder. + + As a result of that, these savers look wrong: + + blocktube Uses SPHERE_MAP. + bouncingcow Uses OBJECT_LINEAR (when run with -texture) + dnalogo Uses GLUtesselator. + extrusion Uses all kinds of GLUT crap. + flyingtoasters Uses SPHERE_MAP and OBJECT_LINEAR. + jigglypuff Uses SPHERE_MAP (in chrome mode), GL_LINE (in wireframe) + jigsaw Uses GLUtesselator. + lockward Puts verts in lists without glBegin! + pinion Uses glSelectBuffer and gluPickMatrix for mouse-clicks. + pipes Uses glMap2f for the Utah Teapot. + polyhedra Uses GLUtesselator (concave objects); also Utah Teapot. + skytentacles Uses GL_LINE in -cel mode. + timetunnel Uses GL_CONSTANT_ALPHA and all kinds of other stuff. + +*/ + + +#undef DEBUG + + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif /* HAVE_CONFIG_H */ + +#ifdef HAVE_JWZGLES /* whole file */ + +#include +#include +#include +#include +#include +#ifdef HAVE_UNISTD_H +# include +#endif /* HAVE_UNISTD_H */ + +#if defined(USE_IPHONE) +# include +# include +#elif defined(HAVE_COCOA) +# include +# include +#else /* X11 */ +# ifndef GL_GLEXT_PROTOTYPES +# define GL_GLEXT_PROTOTYPES /* for glBindBuffer */ +# endif +# include +# include +#endif + +#include "jwzglesI.h" + +#define STRINGIFY(X) #X + +#undef countof +#define countof(x) (sizeof((x))/sizeof((*x))) + +#undef Assert + +#ifdef HAVE_COCOA + extern void jwxyz_abort (const char *fmt, ...) __dead2; +# define Assert(C,S) do { if (!(C)) { jwxyz_abort ("%s",S); }} while(0) +#else +# define Assert(C,S) do { \ + if (!(C)) { \ + fprintf (stderr, "jwzgles: %s\n", S); \ + abort(); \ + }} while(0) +#endif + + +typedef struct { GLfloat x, y, z; } XYZ; +typedef struct { GLfloat x, y, z, w; } XYZW; +typedef struct { GLfloat s, t, r, q; } STRQ; +typedef struct { GLfloat r, g, b, a; } RGBA; + + +/* Used to record all calls to glVertex3f, glNormal3f, etc. + while inside glBegin / glEnd so that we can convert that + to a single call to glDrawArrays. + */ +typedef struct { + int mode; + int count, size; /* size of each array */ + + XYZW *verts; /* Arrays being built */ + XYZ *norms; + STRQ *tex; + RGBA *color; + + int ncount; /* How many normals, tex coords and colors were */ + int tcount; /* used. We optimize based on "0, 1, or many". */ + int ccount; + int materialistic; /* Whether glMaterial was called inside glBegin */ + + XYZ cnorm; /* Prevailing normal/texture/color while building */ + STRQ ctex; + RGBA ccolor; + +} vert_set; + + +typedef void (*list_fn_cb) (void); + + +/* We need this nonsense because you can't cast a double to a void* + or vice versa. They tend to be passed in different registers, + and you need to know about that because it's still 1972 here. + */ +typedef union { const void *v; GLfloat f; GLuint i; } void_int; + +typedef struct { /* saved args for glDrawArrays */ + int binding, size, type, stride, bytes; + void *data; +} draw_array; + +typedef enum { /* shorthand describing arglist signature */ + PROTO_VOID, /* no args */ + PROTO_I, /* 1 int arg */ + PROTO_F, /* 1 float arg */ + PROTO_II, /* int, int */ + PROTO_FF, /* float, float */ + PROTO_IF, /* int, float */ + PROTO_III, /* int, int, int */ + PROTO_FFF, /* float, float, float */ + PROTO_IIF, /* int, int, float */ + PROTO_IIII, /* int, int, int, int */ + PROTO_FFFF, /* float, float, float, float */ + PROTO_IIV, /* int, int[4] */ + PROTO_IFV, /* int, float[4] */ + PROTO_IIIV, /* int, int, int[4] */ + PROTO_IIFV, /* int, int, float[4] */ + PROTO_FV16, /* float[16] */ + PROTO_ARRAYS /* glDrawArrays */ +} fn_proto; + +typedef struct { /* A single element of a display list */ + const char *name; + list_fn_cb fn; /* saved function pointer */ + fn_proto proto; /* arglist prototype */ + draw_array *arrays; /* args for glDrawArrays */ + void_int argv[16]; /* args for everything else */ +} list_fn; + + +typedef struct { /* a display list: saved activity within glNewList */ + int id; + int size, count; + list_fn *fns; + + /* Named buffer that should be freed when this display list is deleted. */ + GLuint buffer; + +} list; + + +typedef struct { /* All display lists */ + list *lists; + int count, size; +} list_set; + + +#define ISENABLED_TEXTURE_2D (1<<0) +#define ISENABLED_TEXTURE_GEN_S (1<<1) +#define ISENABLED_TEXTURE_GEN_T (1<<2) +#define ISENABLED_LIGHTING (1<<3) +#define ISENABLED_BLEND (1<<4) +#define ISENABLED_DEPTH_TEST (1<<5) +#define ISENABLED_CULL_FACE (1<<6) +#define ISENABLED_NORMALIZE (1<<7) +#define ISENABLED_FOG (1<<8) +#define ISENABLED_COLMAT (1<<9) +#define ISENABLED_VERT_ARRAY (1<<10) +#define ISENABLED_NORM_ARRAY (1<<11) +#define ISENABLED_TEX_ARRAY (1<<12) +#define ISENABLED_COLOR_ARRAY (1<<13) + + +typedef struct { /* global state */ + + vert_set set; /* set being built */ + + int compiling_list; /* list id if inside glNewList; 0 means immediate */ + int replaying_list; /* depth of call stack to glCallList */ + int compiling_verts; /* inside glBegin */ + + list_set lists; /* saved lists */ + unsigned long enabled; + +} jwzgles_state; + + +static jwzgles_state global_state = { { 0, }, 0, 0, 0, { 0, }, 0, }; +static jwzgles_state *state = &global_state; + + +#ifdef DEBUG +# define LOG(A) fprintf(stderr,"jwzgles: " A "\n") +# define LOG1(A,B) fprintf(stderr,"jwzgles: " A "\n",B) +# define LOG2(A,B,C) fprintf(stderr,"jwzgles: " A "\n",B,C) +# define LOG3(A,B,C,D) fprintf(stderr,"jwzgles: " A "\n",B,C,D) +# define LOG4(A,B,C,D,E) fprintf(stderr,"jwzgles: " A "\n",B,C,D,E) +# define LOG5(A,B,C,D,E,F) fprintf(stderr,"jwzgles: " A "\n",B,C,D,E,F) +# define LOG6(A,B,C,D,E,F,G) fprintf(stderr,"jwzgles: " A "\n",B,C,D,E,F,G) +# define LOG7(A,B,C,D,E,F,G,H) fprintf(stderr,"jwzgles: " A "\n",B,C,D,E,F,G,H) +# define LOG8(A,B,C,D,E,F,G,H,I)\ + fprintf(stderr,"jwzgles: "A "\n",B,C,D,E,F,G,H,I) +# define LOG9(A,B,C,D,E,F,G,H,I,J)\ + fprintf(stderr,"jwzgles: "A "\n",B,C,D,E,F,G,H,I,J) +# define LOG10(A,B,C,D,E,F,G,H,I,J,K)\ + fprintf(stderr,"jwzgles: "A "\n",B,C,D,E,F,G,H,I,J,K) +# define LOG17(A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R)\ + fprintf(stderr,"jwzgles: "A "\n",B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R) +# define CHECK(S) check_gl_error(S) +#else +# define LOG(A) /* */ +# define LOG1(A,B) /* */ +# define LOG2(A,B,C) /* */ +# define LOG3(A,B,C,D) /* */ +# define LOG4(A,B,C,D,E) /* */ +# define LOG5(A,B,C,D,E,F) /* */ +# define LOG6(A,B,C,D,E,F,G) /* */ +# define LOG7(A,B,C,D,E,F,G,H) /* */ +# define LOG8(A,B,C,D,E,F,G,H,I) /* */ +# define LOG9(A,B,C,D,E,F,G,H,I,J) /* */ +# define LOG10(A,B,C,D,E,F,G,H,I,J,K) /* */ +# define LOG17(A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R) /* */ +# define CHECK(S) /* */ +#endif + +#ifdef DEBUG +static const char * +mode_desc (int mode) /* for debugging messages */ +{ + switch (mode) { +# define SS(X) case GL_##X: return STRINGIFY(X); + SS(ALPHA) + SS(ALPHA_TEST) + SS(AMBIENT) + SS(AMBIENT_AND_DIFFUSE) + SS(ARRAY_BUFFER) + SS(AUTO_NORMAL) + SS(BACK) + SS(BLEND) + SS(BLEND_DST) + SS(BLEND_SRC) + SS(BLEND_SRC_ALPHA) + SS(BYTE) + SS(C3F_V3F) + SS(C4F_N3F_V3F) + SS(C4UB_V2F) + SS(C4UB_V3F) + SS(CCW) + SS(CLAMP) + SS(COLOR_ARRAY) + SS(COLOR_ARRAY_BUFFER_BINDING); + SS(COLOR_MATERIAL) + SS(COLOR_MATERIAL_FACE) + SS(COLOR_MATERIAL_PARAMETER) + SS(COMPILE) + SS(CULL_FACE) + SS(CW) + SS(DECAL) + SS(DEPTH_BUFFER_BIT) + SS(DEPTH_TEST) + SS(DIFFUSE) + SS(DOUBLEBUFFER) + SS(DST_ALPHA) + SS(DST_COLOR) + SS(DYNAMIC_DRAW) + SS(ELEMENT_ARRAY_BUFFER) + SS(EYE_LINEAR) + SS(EYE_PLANE) + SS(FEEDBACK) + SS(FILL) + SS(FLAT) + SS(FLOAT) + SS(FOG) + SS(FRONT) + SS(FRONT_AND_BACK) + SS(GREATER) + SS(INTENSITY) + SS(INVALID_ENUM) + SS(INVALID_OPERATION) + SS(INVALID_VALUE) + SS(LESS) + SS(LIGHT0) + SS(LIGHT1) + SS(LIGHT2) + SS(LIGHT3) + SS(LIGHTING) + SS(LIGHT_MODEL_AMBIENT) + SS(LIGHT_MODEL_COLOR_CONTROL) + SS(LIGHT_MODEL_LOCAL_VIEWER) + SS(LIGHT_MODEL_TWO_SIDE) + SS(LINE) + SS(LINEAR) + SS(LINEAR_MIPMAP_LINEAR) + SS(LINEAR_MIPMAP_NEAREST) + SS(LINES) + SS(LINE_LOOP) + SS(LINE_STRIP) + SS(LUMINANCE) + SS(LUMINANCE_ALPHA) + SS(MATRIX_MODE) + SS(MODELVIEW) + SS(MODULATE) + SS(N3F_V3F) + SS(NEAREST) + SS(NEAREST_MIPMAP_LINEAR) + SS(NEAREST_MIPMAP_NEAREST) + SS(NORMALIZE) + SS(NORMAL_ARRAY) + SS(NORMAL_ARRAY_BUFFER_BINDING); + SS(OBJECT_LINEAR) + SS(OBJECT_PLANE) + SS(ONE_MINUS_DST_ALPHA) + SS(ONE_MINUS_DST_COLOR) + SS(ONE_MINUS_SRC_ALPHA) + SS(ONE_MINUS_SRC_COLOR) + SS(OUT_OF_MEMORY) + SS(PACK_ALIGNMENT) + SS(POINTS) + SS(POLYGON) + SS(POLYGON_OFFSET_FILL) + SS(POLYGON_SMOOTH) + SS(POLYGON_STIPPLE) + SS(POSITION) + SS(PROJECTION) + SS(Q) + SS(QUADS) + SS(QUAD_STRIP) + SS(R) + SS(RENDER) + SS(REPEAT) + SS(RGB) + SS(RGBA) + SS(RGBA_MODE) + SS(S) + SS(SELECT) + SS(SEPARATE_SPECULAR_COLOR) + SS(SHADE_MODEL) + SS(SHININESS) + SS(SHORT) + SS(SINGLE_COLOR) + SS(SMOOTH) + SS(SPECULAR) + SS(SPHERE_MAP) + SS(SRC_ALPHA) + SS(SRC_ALPHA_SATURATE) + SS(SRC_COLOR) + SS(STACK_OVERFLOW) + SS(STACK_UNDERFLOW) + SS(STATIC_DRAW) + SS(STENCIL_BUFFER_BIT) + SS(T) + SS(T2F_C3F_V3F) + SS(T2F_C4F_N3F_V3F) + SS(T2F_C4UB_V3F) + SS(T2F_N3F_V3F) + SS(T2F_V3F) + SS(T4F_C4F_N3F_V4F) + SS(T4F_V4F) + SS(TEXTURE) + SS(TEXTURE_1D) + SS(TEXTURE_2D) + SS(TEXTURE_ALPHA_SIZE) + SS(TEXTURE_BINDING_2D) + SS(TEXTURE_BLUE_SIZE) + SS(TEXTURE_BORDER) + SS(TEXTURE_BORDER_COLOR) + SS(TEXTURE_COMPONENTS) + SS(TEXTURE_COORD_ARRAY) + SS(TEXTURE_COORD_ARRAY_BUFFER_BINDING); + SS(TEXTURE_ENV) + SS(TEXTURE_ENV_COLOR) + SS(TEXTURE_ENV_MODE) + SS(TEXTURE_GEN_MODE) + SS(TEXTURE_GEN_Q) + SS(TEXTURE_GEN_R) + SS(TEXTURE_GEN_S) + SS(TEXTURE_GEN_T) + SS(TEXTURE_GREEN_SIZE) + SS(TEXTURE_HEIGHT) + SS(TEXTURE_INTENSITY_SIZE) + SS(TEXTURE_LUMINANCE_SIZE) + SS(TEXTURE_MAG_FILTER) + SS(TEXTURE_MIN_FILTER) + SS(TEXTURE_RED_SIZE) + SS(TEXTURE_WRAP_S) + SS(TEXTURE_WRAP_T) + SS(TRIANGLES) + SS(TRIANGLE_FAN) + SS(TRIANGLE_STRIP) + SS(UNPACK_ALIGNMENT) + SS(UNPACK_ROW_LENGTH) + SS(UNSIGNED_BYTE) + SS(UNSIGNED_INT_8_8_8_8_REV) + SS(UNSIGNED_SHORT) + SS(V2F) + SS(V3F) + SS(VERTEX_ARRAY) + SS(VERTEX_ARRAY_BUFFER_BINDING); +/*SS(COLOR_BUFFER_BIT) -- same value as GL_LIGHT0 */ +# undef SS + case (GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT): + return "DEPTH_BUFFER_BIT | COLOR_BUFFER_BIT"; +/* Oops, same as INVALID_ENUM. + case (GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT): + return "DEPTH_BUFFER_BIT | STENCIL_BUFFER_BIT"; +*/ + case (GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT): + return "COLOR_BUFFER_BIT | STENCIL_BUFFER_BIT"; + case (GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT): + return "DEPTH_BUFFER_BIT | COLOR_BUFFER_BIT | STENCIL_BUFFER_BIT"; + default: + { + static char buf[255]; + sprintf (buf, "0x%04X", mode); + return buf; + } + } +} + +static void +check_gl_error (const char *s) +{ + GLenum i = glGetError(); + if (i == GL_NO_ERROR) return; + fprintf (stderr, "jwzgles: GL ERROR: %s: %s\n", s, mode_desc(i)); +} + +#endif /* DEBUG */ + + +static void +make_room (const char *name, void **array, int span, int *count, int *size) +{ + if (*count + 1 >= *size) + { + int new_size = (*count + 20) * 1.2; /* mildly exponential */ + *array = realloc (*array, new_size * span); + Assert (*array, "out of memory"); + /* LOG3("%s: grew %d -> %d", name, *size, new_size); */ + *size = new_size; + } +} + + +int +jwzgles_glGenLists (int n) +{ + int i; + int ret = 0; + + Assert (!state->compiling_verts, "glGenLists not allowed inside glBegin"); + + /* Ensure space in state->lists, clear the one at the end, and tick counter + Note that lists are never really deleted, and we can never re-use elements + of this array. glDeleteLists zeroes out the contents of the list, but + the list ID is still valid for use with glNewList forever. + #### So maybe this should be a linked list instead of an array. + */ + for (i = 0; i < n; i++) + { + list *L; + int id = 0; + make_room ("glGenLists", + (void **) &state->lists.lists, + sizeof (*state->lists.lists), + &state->lists.count, &state->lists.size); + state->lists.count++; + id = state->lists.count; + L = &state->lists.lists[id-1]; + + memset (L, 0, sizeof (*L)); + L->id = id; + if (ret == 0) ret = id; + LOG1("glGenLists -> %d", L->id); + } + + /* Return the ID of the first list allocated */ + + return ret; +} + + +void +jwzgles_glNewList (int id, int mode) +{ + list *L; + Assert (id > 0 && id <= state->lists.count, "glNewList: bogus ID"); + Assert (mode == GL_COMPILE, "glNewList: bad mode"); + Assert (!state->compiling_verts, "glNewList not allowed inside glBegin"); + Assert (!state->compiling_list, "nested glNewList"); + Assert (state->set.count == 0, "missing glEnd"); + + L = &state->lists.lists[id-1]; + Assert (L->id == id, "glNewList corrupted"); + + if (L->count != 0) jwzgles_glDeleteLists (L->id, 1); /* Overwriting */ + Assert (L->count == 0, "glNewList corrupted"); + + state->compiling_list = id; + + LOG1("glNewList -> %d", id); +} + + +static void save_arrays (list_fn *, int); +static void restore_arrays (list_fn *, int); +static void copy_array_data (draw_array *, int, const char *); +static void optimize_arrays (void); + +void +jwzgles_glEndList (void) +{ + Assert (state->compiling_list, "extra glEndList"); + Assert (state->set.count == 0, "missing glEnd"); + Assert (!state->compiling_verts, "glEndList not allowed inside glBegin"); + LOG1("glEndList %d", state->compiling_list); + optimize_arrays(); + state->compiling_list = 0; +} + + +static void +list_push (const char * const name, + list_fn_cb fn, fn_proto proto, void_int *av) +{ + list *L; + list_fn *F; + int i; + + Assert (state->compiling_list > 0, "not inside glNewList"); + Assert (state->compiling_list <= state->lists.count, "glNewList corrupted"); + + L = &state->lists.lists[state->compiling_list-1]; + Assert (L, "glNewList: no list"); + + make_room ("glNewLists", + (void **) &L->fns, sizeof (*L->fns), + &L->count, &L->size); + memset (&L->fns[L->count], 0, sizeof (*L->fns)); + F = L->fns + L->count; + + F->name = name; + F->fn = fn; + F->proto = proto; + if (proto != PROTO_VOID) + for (i = 0; i < countof(F->argv); i++) + F->argv[i] = av[i]; + +# ifdef DEBUG + switch (proto) { + case PROTO_VOID: + LOG1 (" push %-12s", name); + break; + case PROTO_I: + if (fn == (list_fn_cb) &jwzgles_glBegin || + fn == (list_fn_cb) &jwzgles_glFrontFace || + fn == (list_fn_cb) &jwzgles_glEnable || + fn == (list_fn_cb) &jwzgles_glDisable || + fn == (list_fn_cb) &jwzgles_glEnableClientState || + fn == (list_fn_cb) &jwzgles_glDisableClientState || + fn == (list_fn_cb) &jwzgles_glShadeModel || + fn == (list_fn_cb) &jwzgles_glMatrixMode) + LOG2 (" push %-12s %s", name, mode_desc (av[0].i)); + else + LOG2 (" push %-12s %d", name, av[0].i); + break; + case PROTO_F: + LOG2 (" push %-12s %7.3f", name, av[0].f); + break; + case PROTO_II: + if (fn == (list_fn_cb) &jwzgles_glBindTexture || + fn == (list_fn_cb) &jwzgles_glBindBuffer) + LOG3 (" push %-12s %s %d", name, mode_desc (av[0].i), av[1].i); + else + LOG3 (" push %-12s %d %d", name, av[0].i, av[1].i); + break; + case PROTO_FF: + LOG3 (" push %-12s %7.3f %7.3f", name, av[0].f, av[1].f); + break; + case PROTO_IF: + LOG3 (" push %-12s %s %7.3f", name, mode_desc (av[0].i), av[1].f); + break; + case PROTO_III: + case PROTO_ARRAYS: + if (fn == (list_fn_cb) &jwzgles_glDrawArrays || + fn == (list_fn_cb) &jwzgles_glTexParameteri) + LOG4 (" push %-12s %s %d %d", name, mode_desc (av[0].i), + av[1].i, av[2].i); + else + LOG4 (" push %-12s %d %d %d", name, av[0].i, av[1].i, av[2].i); + break; + case PROTO_FFF: + LOG4 (" push %-12s %7.3f %7.3f %7.3f", name, av[0].f, av[1].f, av[2].f); + break; + case PROTO_IIF: + LOG4 (" push %-12s %s %s %7.3f", name, + mode_desc(av[0].i), mode_desc(av[1].i), av[2].f); + break; + case PROTO_IIII: + LOG5 (" push %-12s %d %d %d %d", name, + av[0].i, av[1].i, av[2].i, av[3].i); + break; + case PROTO_FFFF: + LOG5 (" push %-12s %7.3f %7.3f %7.3f %7.3f", name, + av[0].f, av[1].f, av[2].f, av[3].f); + break; + case PROTO_IFV: + LOG6 (" push %-12s %s %3.1f %3.1f %3.1f %3.1f", name, mode_desc (av[0].i), + av[1].f, av[2].f, av[3].f, av[4].f); + break; + case PROTO_IIV: + LOG6 (" push %-12s %s %d %d %d %d", name, mode_desc (av[0].i), + av[1].i, av[2].i, av[3].i, av[4].i); + break; + case PROTO_IIFV: + LOG7 (" push %-12s %s %-8s %3.1f %3.1f %3.1f %3.1f", name, + mode_desc (av[0].i), mode_desc (av[1].i), + av[2].f, av[3].f, av[4].f, av[5].f); + break; + case PROTO_IIIV: + LOG7 (" push %-12s %s %-8s %3d %3d %3d %3d", name, + mode_desc (av[0].i), mode_desc (av[1].i), + av[2].i, av[3].i, av[4].i, av[5].i); + break; + case PROTO_FV16: + LOG17 (" push %-12s [" + "%8.3f %8.3f %8.3f %8.3f " "\n\t\t\t " + "%8.3f %8.3f %8.3f %8.3f " "\n\t\t\t " + "%8.3f %8.3f %8.3f %8.3f " "\n\t\t\t " + "%8.3f %8.3f %8.3f %8.3f ]", + name, + av[0].f, av[1].f, av[2].f, av[3].f, + av[4].f, av[5].f, av[6].f, av[7].f, + av[8].f, av[9].f, av[10].f, av[11].f, + av[12].f, av[13].f, av[14].f, av[15].f); + break; + default: + Assert (0, "bogus prototype"); + break; + } +# endif /* DEBUG */ + + if (proto == PROTO_ARRAYS) /* glDrawArrays */ + save_arrays (F, av[1].i + av[2].i); + + L->count++; +} + + +void +jwzgles_glBegin (int mode) +{ + Assert (!state->compiling_verts, "nested glBegin"); + state->compiling_verts++; + + /* Only these commands are allowed inside glBegin: + + glVertex -- not allowed outside + glColor + glSecondaryColor + glIndex + glNormal + glFogCoord + glTexCoord + glMultiTexCoord + glVertexAttrib + glEvalCoord + glEvalPoint + glArrayElement -- not allowed outside + glMaterial + glEdgeFlag + glCallList + glCallLists + */ + + if (!state->replaying_list) + LOG2 ("%sglBegin %s", + (state->compiling_list || state->replaying_list ? " " : ""), + mode_desc (mode)); + + Assert (state->set.count == 0, "glBegin corrupted"); + state->set.mode = mode; + state->set.count = 0; + state->set.ncount = 0; + state->set.tcount = 0; + state->set.ccount = 0; +} + + +void +jwzgles_glDeleteLists (int id0, int range) +{ + Assert (!state->compiling_verts, "glDeleteLists not allowed inside glBegin"); + + if (state->compiling_list) + { + void_int vv[2]; + vv[0].i = id0; + vv[1].i = range; + list_push ("glDeleteLists", (list_fn_cb) &jwzgles_glDeleteLists, + PROTO_II, vv); + } + else + { + int id; + + if (!state->replaying_list) + LOG2 ("glDeleteLists %d %d", id0, range); + + for (id = id0 + range - 1; id >= id0; id--) + { + int i; + list *L; + if (id == 0) continue; /* People do this stupid thing */ + if (id > state->lists.count) break; /* this too */ + Assert (id > 0 && id <= state->lists.count, + "glDeleteLists: bogus ID"); + L = &state->lists.lists[id-1]; + Assert (L->id == id, "glDeleteLists corrupted"); + + for (i = 0; i < L->count; i++) + { + list_fn *lf = &L->fns[i]; + if (lf->arrays) + { + int j; + for (j = 0; j < 4; j++) + /* If there's a binding, 'data' is an index, not a ptr. */ + if (!lf->arrays[j].binding && + lf->arrays[j].data) + free (lf->arrays[j].data); + free (lf->arrays); + } + } + if (L->fns) + free (L->fns); + if (L->buffer) + glDeleteBuffers (1, &L->buffer); + + memset (L, 0, sizeof (*L)); + L->id = id; + } + } +} + + +extern GLboolean +jwzgles_glIsList (GLuint id) +{ + return (id > 0 && id < state->lists.count); +} + + + +void +jwzgles_glNormal3fv (const GLfloat *v) +{ + if (state->compiling_list && !state->compiling_verts) + { + void_int vv[3]; + vv[0].f = v[0]; + vv[1].f = v[1]; + vv[2].f = v[2]; + list_push ("glNormal3f", (list_fn_cb) &jwzgles_glNormal3f, + PROTO_FFF, vv); + } + else + { + if (!state->replaying_list) + LOG5 ("%s%sglNormal3f %7.3f %7.3f %7.3f", + (state->compiling_list || state->replaying_list ? " " : ""), + (state->compiling_verts ? " rec " : ""), + v[0], v[1], v[2]); + + if (state->compiling_verts) /* inside glBegin */ + { + state->set.cnorm.x = v[0]; + state->set.cnorm.y = v[1]; + state->set.cnorm.z = v[2]; + state->set.ncount++; + if (state->set.count > 0 && state->set.ncount == 1) /* not first! */ + state->set.ncount++; + } + else /* outside glBegin */ + { + glNormal3f (v[0], v[1], v[2]); + CHECK("glNormal3f"); + } + } +} + + +void +jwzgles_glNormal3f (GLfloat x, GLfloat y, GLfloat z) +{ + GLfloat v[3]; + v[0] = x; + v[1] = y; + v[2] = z; + jwzgles_glNormal3fv (v); +} + + +void +jwzgles_glTexCoord4fv (const GLfloat *v) +{ + if (state->compiling_list && !state->compiling_verts) + { + void_int vv[4]; + vv[0].f = v[0]; + vv[1].f = v[1]; + vv[2].f = v[2]; + vv[3].f = v[3]; + list_push ("glTexCoord4f", (list_fn_cb) &jwzgles_glTexCoord4f, + PROTO_FFFF, vv); + } + else + { + if (!state->replaying_list) + LOG6 ("%s%sglTexCoord4f %7.3f %7.3f %7.3f %7.3f", + (state->compiling_list || state->replaying_list ? " " : ""), + (state->compiling_verts ? " rec " : ""), + v[0], v[1], v[2], v[3]); + + Assert (state->compiling_verts, "glTexCoord4fv outside glBegin"); + + if (state->compiling_verts) /* inside glBegin */ + { + state->set.ctex.s = v[0]; + state->set.ctex.t = v[1]; + state->set.ctex.r = v[2]; + state->set.ctex.q = v[3]; + state->set.tcount++; + if (state->set.count > 0 && state->set.tcount == 1) /* not first! */ + state->set.tcount++; + } + } +} + + +void +jwzgles_glTexCoord4f (GLfloat s, GLfloat t, GLfloat r, GLfloat q) +{ + GLfloat v[4]; + v[0] = s; + v[1] = t; + v[2] = r; + v[3] = q; + jwzgles_glTexCoord4fv (v); +} + + +void +jwzgles_glTexCoord3fv (const GLfloat *v) +{ + GLfloat vv[4]; + vv[0] = v[0]; + vv[1] = v[1]; + vv[2] = v[2]; + vv[3] = 1; + jwzgles_glTexCoord4fv (vv); +} + + +void +jwzgles_glTexCoord2fv (const GLfloat *v) +{ + GLfloat vv[4]; + vv[0] = v[0]; + vv[1] = v[1]; + vv[2] = 0; + vv[3] = 1; + jwzgles_glTexCoord4fv (vv); +} + + +void +jwzgles_glTexCoord3f (GLfloat s, GLfloat t, GLfloat r) +{ + jwzgles_glTexCoord4f (s, t, r, 1); +} + + +void +jwzgles_glTexCoord2f (GLfloat s, GLfloat t) +{ + jwzgles_glTexCoord4f (s, t, 0, 1); +} + + +void +jwzgles_glTexCoord1f (GLfloat s) +{ + jwzgles_glTexCoord4f (s, 0, 0, 1); +} + + + +void +jwzgles_glColor4fv (const GLfloat *v) +{ + if (state->compiling_list && !state->compiling_verts) + { + void_int vv[4]; + vv[0].f = v[0]; + vv[1].f = v[1]; + vv[2].f = v[2]; + vv[3].f = v[3]; + list_push ("glColor4f", (list_fn_cb) &jwzgles_glColor4f, + PROTO_FFFF, vv); + } + else + { + if (!state->replaying_list) + LOG6 ("%s%sglColor4f %7.3f %7.3f %7.3f %7.3f", + (state->compiling_list || state->replaying_list ? " " : ""), + (state->compiling_verts ? " rec " : ""), + v[0], v[1], v[2], v[3]); + + if (state->compiling_verts) /* inside glBegin */ + { + state->set.ccolor.r = v[0]; + state->set.ccolor.g = v[1]; + state->set.ccolor.b = v[2]; + state->set.ccolor.a = v[3]; + state->set.ccount++; + if (state->set.count > 0 && state->set.ccount == 1) /* not first! */ + state->set.ccount++; + } + else /* outside glBegin */ + { + glColor4f (v[0], v[1], v[2], v[3]); + CHECK("glColor4"); + } + } +} + + +void +jwzgles_glColor4f (GLfloat r, GLfloat g, GLfloat b, GLfloat a) +{ + GLfloat v[4]; + v[0] = r; + v[1] = g; + v[2] = b; + v[3] = a; + jwzgles_glColor4fv (v); +} + + +void +jwzgles_glColor3f (GLfloat r, GLfloat g, GLfloat b) +{ + jwzgles_glColor4f (r, g, b, 1); +} + + +void +jwzgles_glColor3fv (const GLfloat *v) +{ + GLfloat vv[4]; + vv[0] = v[0]; + vv[1] = v[1]; + vv[2] = v[2]; + vv[3] = 1; + jwzgles_glColor4fv (vv); +} + + +void +jwzgles_glColor4i (GLuint r, GLuint g, GLuint b, GLuint a) +{ + jwzgles_glColor4f (r, g, b, a); +} + + +void +jwzgles_glColor3i (GLuint r, GLuint g, GLuint b) +{ + jwzgles_glColor4f (r, g, b, 1); +} + + +void +jwzgles_glColor4iv (const GLint *v) +{ + GLfloat vv[4]; + vv[0] = v[0]; + vv[1] = v[1]; + vv[2] = v[2]; + vv[3] = v[3]; + jwzgles_glColor4fv (vv); +} + + +void +jwzgles_glColor3iv (const GLint *v) +{ + GLfloat vv[4]; + vv[0] = v[0]; + vv[1] = v[1]; + vv[2] = v[2]; + vv[3] = 1; + jwzgles_glColor4fv (vv); +} + + +void +jwzgles_glColor4ub (GLubyte r, GLubyte g, GLubyte b, GLubyte a) +{ + jwzgles_glColor4f (r, g, b, a); +} + + +void +jwzgles_glColor3ub (GLubyte r, GLubyte g, GLubyte b) +{ + jwzgles_glColor4f (r, g, b, 1); +} + + +void +jwzgles_glMaterialfv (GLenum face, GLenum pname, const GLfloat *color) +{ + /* If this is called inside glBegin/glEnd with a front ambient color, + then treat it the same as glColor: set the color of the upcoming + vertex. + + Other faces or lighting types within glBegin are ignored. + */ + + if (state->compiling_verts) + { + if ((face == GL_FRONT || + face == GL_FRONT_AND_BACK) && + (pname == GL_AMBIENT || + pname == GL_DIFFUSE || + pname == GL_AMBIENT_AND_DIFFUSE)) + { + jwzgles_glColor4f (color[0], color[1], color[2], color[3]); + state->set.materialistic++; + } + else + LOG2 (" IGNORING glMaterialfv %s %s", + mode_desc(face), mode_desc(pname)); + } + else if (state->compiling_list) + { + void_int vv[6]; + vv[0].i = face; + vv[1].i = pname; + vv[2].f = color[0]; + vv[3].f = color[1]; + vv[4].f = color[2]; + vv[5].f = color[3]; + list_push ("glMaterialfv", (list_fn_cb) &jwzgles_glMaterialfv, + PROTO_IIFV, vv); + } + else + { + /* If this is called outside of glBegin/glEnd with a front + ambient color, then the intent is presumably for that color + to apply to the upcoming vertexes (which may be played back + from a list that does not have vertex colors in it). In that + case, the only way to make the colors show up is to call + glColor() with GL_COLOR_MATERIAL enabled. + + I'm not sure if this will have other inappropriate side effects... + */ + if ((face == GL_FRONT || + face == GL_FRONT_AND_BACK) && + (pname == GL_AMBIENT || + pname == GL_DIFFUSE || + pname == GL_AMBIENT_AND_DIFFUSE)) + { + jwzgles_glEnable (GL_COLOR_MATERIAL); + jwzgles_glColor4f (color[0], color[1], color[2], color[3]); + } + + /* OpenGLES seems to throw "invalid enum" for GL_FRONT -- but it + goes ahead and sets the material anyway! No error if we just + always use GL_FRONT_AND_BACK. + */ + if (face == GL_FRONT) + face = GL_FRONT_AND_BACK; + if (! state->replaying_list) + LOG7 ("direct %-12s %s %s %7.3f %7.3f %7.3f %7.3f", "glMaterialfv", + mode_desc(face), mode_desc(pname), + color[0], color[1], color[2], color[3]); + glMaterialfv (face, pname, color); /* the real one */ + CHECK("glMaterialfv"); + } +} + + +void +jwzgles_glMaterialiv (GLenum face, GLenum pname, const GLint *v) +{ + GLfloat vv[4]; + vv[0] = v[0]; + vv[1] = v[1]; + vv[2] = v[2]; + vv[3] = 1; + jwzgles_glMaterialfv (face, pname, vv); +} + +void +jwzgles_glMaterialf (GLenum face, GLenum pname, const GLfloat c) +{ + GLfloat vv[4]; + vv[0] = c; + vv[1] = c; + vv[2] = c; + vv[3] = 1; + jwzgles_glMaterialfv (face, pname, vv); +} + + +void +jwzgles_glMateriali (GLenum face, GLenum pname, const GLuint c) +{ + jwzgles_glMaterialf (face, pname, c); +} + + +void +jwzgles_glColorMaterial (GLenum face, GLenum mode) +{ + Assert (!state->compiling_verts, + "glColorMaterial not allowed inside glBegin"); +#if 0 + if (state->compiling_list) + { + void_int vv[2]; + vv[0].i = face; + vv[1].i = mode; + list_push ("glColorMaterial", (list_fn_cb) &jwzgles_glColorMaterial, + PROTO_II, vv); + } + else + { + /* No real analog to this distinction in OpenGLES, since color + arrays don't distinguish between "color" and "material", */ + Assert (0, "glColorMaterial: unimplemented mode"); + } +#endif +} + + + + +void +jwzgles_glVertex4fv (const GLfloat *v) +{ + vert_set *s = &state->set; + int count = s->count; + + Assert (state->compiling_verts, "glVertex4fv not inside glBegin"); + + LOG5("%s rec glVertex4f %7.3f %7.3f %7.3f %7.3f", + (state->compiling_list || state->replaying_list ? " " : ""), + v[0], v[1], v[2], v[3]); + + if (count >= s->size - 1) + { + int new_size = 20 + (s->size * 1.2); + + /* 4 arrays, different element sizes... + We allocate all 4 arrays just in case we need them, + but we might not end up using them all at the end. + */ + + s->verts = (XYZW *) realloc (s->verts, new_size * sizeof (*s->verts)); + Assert (s->verts, "out of memory"); + + s->norms = (XYZ *) realloc (s->norms, new_size * sizeof (*s->norms)); + Assert (s->norms, "out of memory"); + + s->tex = (STRQ *) realloc (s->tex, new_size * sizeof (*s->tex)); + Assert (s->tex, "out of memory"); + + s->color = (RGBA *) realloc (s->color, new_size * sizeof (*s->color)); + Assert (s->color, "out of memory"); + + s->size = new_size; + } + + s->verts [count].x = v[0]; + s->verts [count].y = v[1]; + s->verts [count].z = v[2]; + s->verts [count].w = v[3]; + s->norms [count] = s->cnorm; + s->tex [count] = s->ctex; + s->color [count] = s->ccolor; + s->count++; +} + + +void +jwzgles_glVertex4f (GLfloat x, GLfloat y, GLfloat z, GLfloat w) +{ + GLfloat v[4]; + v[0] = x; + v[1] = y; + v[2] = z; + v[3] = w; + jwzgles_glVertex4fv (v); +} + +void +jwzgles_glVertex4i (GLint x, GLint y, GLint z, GLint w) +{ + jwzgles_glVertex4f (x, y, z, w); +} + +void +jwzgles_glVertex3f (GLfloat x, GLfloat y, GLfloat z) +{ + GLfloat v[4]; + v[0] = x; + v[1] = y; + v[2] = z; + v[3] = 1; + jwzgles_glVertex4fv (v); +} + +void +jwzgles_glVertex3i (GLint x, GLint y, GLint z) +{ + jwzgles_glVertex3f (x, y, z); +} + +void +jwzgles_glVertex3fv (const GLfloat *v) +{ + jwzgles_glVertex3f (v[0], v[1], v[2]); +} + +void +jwzgles_glVertex3dv (const GLdouble *v) +{ + jwzgles_glVertex3f (v[0], v[1], v[2]); +} + + +void +jwzgles_glVertex2f (GLfloat x, GLfloat y) +{ + GLfloat v[3]; + v[0] = x; + v[1] = y; + v[2] = 0; + jwzgles_glVertex3fv (v); +} + +void +jwzgles_glVertex2fv (const GLfloat *v) +{ + jwzgles_glVertex2f (v[0], v[1]); +} + +void +jwzgles_glVertex2i (GLint x, GLint y) +{ + jwzgles_glVertex2f (x, y); +} + + +void +jwzgles_glLightiv (GLenum light, GLenum pname, const GLint *params) +{ + GLfloat v[4]; + v[0] = params[0]; + v[1] = params[1]; + v[2] = params[2]; + v[3] = params[3]; + jwzgles_glLightfv (light, pname, v); +} + +void +jwzgles_glLightModeliv (GLenum pname, const GLint *params) +{ + GLfloat v[4]; + v[0] = params[0]; + v[1] = params[1]; + v[2] = params[2]; + v[3] = params[3]; + jwzgles_glLightModelfv (pname, v); +} + +void +jwzgles_glFogiv (GLenum pname, const GLint *params) +{ + GLfloat v[4]; + v[0] = params[0]; + v[1] = params[1]; + v[2] = params[2]; + v[3] = params[3]; + jwzgles_glFogfv (pname, v); +} + +void +jwzgles_glLighti (GLenum light, GLenum pname, GLint param) +{ + jwzgles_glLightf (light, pname, param); +} + +void +jwzgles_glLightModeli (GLenum pname, GLint param) +{ + jwzgles_glLightModelf (pname, param); +} + +void +jwzgles_glFogi (GLenum pname, GLint param) +{ + jwzgles_glFogf (pname, param); +} + + +void +jwzgles_glRotated (GLdouble angle, GLdouble x, GLdouble y, GLdouble z) +{ + jwzgles_glRotatef (angle, x, y, z); +} + + +void +jwzgles_glClipPlane (GLenum plane, const GLdouble *equation) +{ + Assert (state->compiling_verts, "glClipPlane not inside glBegin"); + Assert (0, "glClipPlane unimplemented"); /* no GLES equivalent... */ +} + + +void +jwzgles_glPolygonMode (GLenum face, GLenum mode) +{ + Assert (!state->compiling_verts, "not inside glBegin"); + if (state->compiling_list) + { + void_int vv[2]; + vv[0].i = face; + vv[1].i = mode; + list_push ("glPolygonMode", (list_fn_cb) &jwzgles_glPolygonMode, + PROTO_II, vv); + } + else + { + /* POINT and LINE don't exist in GLES */ + Assert (mode == GL_FILL, "glPolygonMode: unimplemented mode"); + } +} + + +void +jwzgles_glDrawBuffer (GLenum buf) +{ + Assert (!state->compiling_verts, "not inside glBegin"); + if (state->compiling_list) + { + void_int vv[1]; + vv[0].i = buf; + list_push ("glDrawBuffer", (list_fn_cb) &jwzgles_glDrawBuffer, + PROTO_I, vv); + } + else + { +/* Assert (buf == GL_BACK, "glDrawBuffer: back buffer only"); */ +# ifndef GL_VERSION_ES_CM_1_0 /* not compiling against OpenGLES 1.x */ + if (! state->replaying_list) + LOG1 ("direct %-12s", "glDrawBuffer"); + glDrawBuffer (buf); /* the real one */ + CHECK("glDrawBuffer"); +# endif + } +} + + +/* Given an array of sets of 4 elements of arbitrary size, convert it + to an array of sets of 6 elements instead: ABCD becomes ABC BCD. + */ +static int +cq2t (unsigned char **arrayP, int stride, int count) +{ + int count2 = count * 6 / 4; + int size = stride * count; + int size2 = stride * count2; + const unsigned char *oarray, *in; + unsigned char *array2, *oarray2, *out; + int i; + + oarray = *arrayP; + if (!oarray || count == 0) + return count2; + + array2 = (unsigned char *) malloc (size2); + Assert (array2, "out of memory"); + oarray2 = array2; + + in = oarray; + out = oarray2; + for (i = 0; i < count / 4; i++) + { + const unsigned char *a, *b, *c, *d; /* the 4 corners */ + a = in; in += stride; + b = in; in += stride; + c = in; in += stride; + d = in; in += stride; + +# define PUSH(IN) do { \ + const unsigned char *ii = IN; \ + int j; \ + for (j = 0; j < stride; j++) { \ + *out++ = *ii++; \ + }} while(0) + + PUSH (a); PUSH (b); PUSH (d); /* the 2 triangles */ + PUSH (b); PUSH (c); PUSH (d); +# undef PUSH + } + + Assert (in == oarray + size, "convert_quads corrupted"); + Assert (out == oarray2 + size2, "convert_quads corrupted"); + + free (*arrayP); + *arrayP = oarray2; + return count2; +} + + +/* Convert all coordinates in a GL_QUADS vert_set to GL_TRIANGLES. + */ +static void +convert_quads_to_triangles (vert_set *s) +{ + int count2; + Assert (s->mode == GL_QUADS, "convert_quads bad mode"); + count2 = + cq2t ((unsigned char **) &s->verts, sizeof(*s->verts), s->count); + cq2t ((unsigned char **) &s->norms, sizeof(*s->norms), s->count); + cq2t ((unsigned char **) &s->tex, sizeof(*s->tex), s->count); + cq2t ((unsigned char **) &s->color, sizeof(*s->color), s->count); + s->count = count2; + s->size = count2; + s->mode = GL_TRIANGLES; +} + + +void +jwzgles_glEnd (void) +{ + vert_set *s = &state->set; + int was_norm, was_tex, was_color, was_mat; + int is_norm, is_tex, is_color, is_mat; + + Assert (state->compiling_verts == 1, "missing glBegin"); + state->compiling_verts--; + + Assert (!state->replaying_list, "how did glEnd get into a display list?"); + + if (!state->replaying_list) + { + LOG5 ("%s [V = %d, N = %d, T = %d, C = %d]", + (state->compiling_list || state->replaying_list ? " " : ""), + s->count, s->ncount, s->tcount, s->ccount); + LOG1 ("%sglEnd", + (state->compiling_list || state->replaying_list ? " " : "")); + } + + if (s->count == 0) return; + + if (s->mode == GL_QUADS) + convert_quads_to_triangles (s); + else if (s->mode == GL_QUAD_STRIP) + s->mode = GL_TRIANGLE_STRIP; /* They do the same thing! */ + else if (s->mode == GL_POLYGON) + s->mode = GL_TRIANGLE_FAN; /* They do the same thing! */ + + glVertexPointer (4, GL_FLOAT, sizeof(*s->verts), s->verts); /* XYZW */ + glNormalPointer ( GL_FLOAT, sizeof(*s->norms), s->norms); /* XYZ */ + glTexCoordPointer (4, GL_FLOAT, sizeof(*s->tex), s->tex); /* STRQ */ + glColorPointer (4, GL_FLOAT, sizeof(*s->color), s->color); /* RGBA */ + CHECK("glColorPointer"); + + /* If there were no calls to glNormal3f inside of glBegin/glEnd, + don't bother enabling the normals array. + + If there was exactly *one* call to glNormal3f inside of glBegin/glEnd, + and it was before the first glVertex3f, then also don't enable the + normals array, but do emit that call to glNormal3f before calling + glDrawArrays. + + Likewise for texture coordinates and colors. + + Be careful to leave the arrays' enabled/disabled state the same as + before, or a later caller might end up using one of our arrays by + mistake. #### Actually this isn't quite right: if glEnd is in a + list, it saves the trailing enable/disable calls in the list, instead + if restoring them to what their state was before the list was run. + */ + was_norm = jwzgles_glIsEnabled (GL_NORMAL_ARRAY); + was_tex = jwzgles_glIsEnabled (GL_TEXTURE_COORD_ARRAY); + was_color = jwzgles_glIsEnabled (GL_COLOR_ARRAY); + was_mat = jwzgles_glIsEnabled (GL_COLOR_MATERIAL); + + /* If we're executing glEnd in immediate mode, not from inside a display + list (which is the only way it happens, because glEnd doesn't go into + display lists), make sure we're not stomping on a saved buffer list: + in immediate mode, vertexes are client-side only. + */ + if (! state->compiling_list) + jwzgles_glBindBuffer (GL_ARRAY_BUFFER, 0); + + if (s->ncount > 1) + { + is_norm = 1; + jwzgles_glEnableClientState (GL_NORMAL_ARRAY); + } + else + { + is_norm = 0; + if (s->ncount == 1) + jwzgles_glNormal3f (s->cnorm.x, s->cnorm.y, s->cnorm.z); + jwzgles_glDisableClientState (GL_NORMAL_ARRAY); + } + + if (s->tcount > 1) + { + is_tex = 1; + jwzgles_glEnableClientState (GL_TEXTURE_COORD_ARRAY); + } + else + { + is_tex = 0; + if (s->tcount == 1) + jwzgles_glTexCoord4f (s->ctex.s, s->ctex.t, s->ctex.r, s->ctex.q); + jwzgles_glDisableClientState (GL_TEXTURE_COORD_ARRAY); + } + + if (s->ccount > 1) + { + is_color = 1; + jwzgles_glEnableClientState (GL_COLOR_ARRAY); + } + else + { + is_color = 0; + if (s->ccount == 1) + jwzgles_glColor4f (s->ccolor.r, s->ccolor.g, s->ccolor.b, s->ccolor.a); + jwzgles_glDisableClientState (GL_COLOR_ARRAY); + } + + jwzgles_glEnableClientState (GL_VERTEX_ARRAY); + + /* We translated the glMaterial calls to per-vertex colors, which are + of the glColor sort, not the glMaterial sort, so automatically + turn on material mapping. Maybe this is a bad idea. + */ + if (s->materialistic && !jwzgles_glIsEnabled (GL_COLOR_MATERIAL)) + { + is_mat = 1; + jwzgles_glEnable (GL_COLOR_MATERIAL); + } + else + is_mat = 0; + + glBindBuffer (GL_ARRAY_BUFFER, 0); /* This comes later. */ + jwzgles_glDrawArrays (s->mode, 0, s->count); + glBindBuffer (GL_ARRAY_BUFFER, 0); /* Keep out of others' hands */ + +# define RESET(VAR,FN,ARG) do { \ + if (is_##VAR != was_##VAR) { \ + if (was_##VAR) jwzgles_glEnable##FN (ARG); \ + else jwzgles_glDisable##FN (ARG); \ + }} while(0) + RESET (norm, ClientState, GL_NORMAL_ARRAY); + RESET (tex, ClientState, GL_TEXTURE_COORD_ARRAY); + RESET (color, ClientState, GL_COLOR_ARRAY); + RESET (mat, , GL_COLOR_MATERIAL); +# undef RESET + + s->count = 0; + s->ncount = 0; + s->tcount = 0; + s->ccount = 0; + s->materialistic = 0; +} + + +/* The display list is full of calls to glDrawArrays(), plus saved arrays + of the values we need to restore before calling it. "Restore" means + "ship them off to the GPU before each call". + + So instead, this function walks through the display list and + combines all of those vertex, normal, texture and color values into + a single VBO array; ships those values off to the GPU *once* at the + time of glEndList; and when running the list with glCallList, the + values are already on the GPU and don't need to be sent over again. + + The VBO persists in the GPU until the display list is deleted. + */ +static void +optimize_arrays (void) +{ + list *L = &state->lists.lists[state->compiling_list-1]; + int i, j; + GLfloat *combo = 0; + int combo_count = 0; + int combo_size = 0; + GLuint buf_name = 0; + + Assert (state->compiling_list, "not compiling a list"); + Assert (L, "no list"); + Assert (!L->buffer, "list already has a buffer"); + + glGenBuffers (1, &buf_name); + CHECK("glGenBuffers"); + if (! buf_name) return; + + L->buffer = buf_name; + + /* Go through the list and dump the contents of the various saved arrays + into one large array. + */ + for (i = 0; i < L->count; i++) + { + list_fn *F = &L->fns[i]; + int count; + if (! F->arrays) + continue; + count = F->argv[2].i; /* 3rd arg to glDrawArrays */ + + for (j = 0; j < 4; j++) + { + draw_array *A = &F->arrays[j]; + int ocount = combo_count; + + /* If some caller is using arrays that don't have floats in them, + we just leave them as-is and ship them over at each call. + Doubt this ever really happens. + */ + if (A->type != GL_FLOAT) + continue; + + if (! A->data) /* No array. */ + continue; + + Assert (A->bytes > 0, "no bytes in draw_array"); + Assert (((unsigned long) A->data > 0xFFFF), + "buffer data not a pointer"); + + combo_count += A->bytes / sizeof(*combo); + make_room ("optimize_arrays", + (void **) &combo, sizeof(*combo), + &combo_count, &combo_size); + memcpy (combo + ocount, A->data, A->bytes); + A->binding = buf_name; + free (A->data); + /* 'data' is now the byte offset into the VBO. */ + A->data = (void *) (ocount * sizeof(*combo)); + /* LOG3(" loaded %lu floats to pos %d of buffer %d", + A->bytes / sizeof(*combo), ocount, buf_name); */ + } + } + + if (combo_count == 0) /* Nothing to do! */ + { + if (combo) free (combo); + glDeleteBuffers (1, &buf_name); + L->buffer = 0; + return; + } + + glBindBuffer (GL_ARRAY_BUFFER, buf_name); + glBufferData (GL_ARRAY_BUFFER, + combo_count * sizeof (*combo), + combo, + GL_STATIC_DRAW); + glBindBuffer (GL_ARRAY_BUFFER, 0); /* Keep out of others' hands */ + + LOG3(" loaded %d floats of list %d into VBO %d", + combo_count, state->compiling_list, buf_name); + +# ifdef DEBUG +# if 0 + for (i = 0; i < combo_count; i++) + { + if (i % 4 == 0) + fprintf (stderr, "\njwzgles: %4d: ", i); + fprintf (stderr, " %7.3f", combo[i]); + } + fprintf (stderr, "\n"); +# endif +# endif /* DEBUG */ + + if (combo) free (combo); +} + + +void +jwzgles_glCallList (int id) +{ + if (state->compiling_list) + { + /* Yes, you can call lists inside of lists. + Yes, recursion would be a mistake. */ + void_int vv[1]; + vv[0].i = id; + list_push ("glCallList", (list_fn_cb) &jwzgles_glCallList, PROTO_I, vv); + } + else + { + list *L; + int i; + + state->replaying_list++; + +# ifdef DEBUG + fprintf (stderr, "\n"); + LOG1 ("glCallList %d", id); +# endif + + Assert (id > 0 && id <= state->lists.count, "glCallList: bogus ID"); + L = &state->lists.lists[id-1]; + Assert (id == L->id, "glCallList corrupted"); + + for (i = 0; i < L->count; i++) + { + list_fn *F = &L->fns[i]; + list_fn_cb fn = F->fn; + void_int *av = F->argv; + + switch (F->proto) { + case PROTO_VOID: + LOG1 (" call %-12s", F->name); + ((void (*) (void)) fn) (); + break; + + case PROTO_I: + if (fn == (list_fn_cb) &jwzgles_glBegin || + fn == (list_fn_cb) &jwzgles_glFrontFace || + fn == (list_fn_cb) &jwzgles_glEnable || + fn == (list_fn_cb) &jwzgles_glDisable || + fn == (list_fn_cb) &jwzgles_glEnableClientState || + fn == (list_fn_cb) &jwzgles_glDisableClientState || + fn == (list_fn_cb) &jwzgles_glShadeModel || + fn == (list_fn_cb) &jwzgles_glMatrixMode) + LOG2 (" call %-12s %s", F->name, mode_desc (av[0].i)); + else + LOG2 (" call %-12s %d", F->name, av[0].i); + ((void (*) (int)) fn) (av[0].i); + break; + + case PROTO_F: + LOG2 (" call %-12s %7.3f", F->name, av[0].f); + ((void (*) (GLfloat)) fn) (av[0].f); + break; + + case PROTO_II: + if (fn == (list_fn_cb) &jwzgles_glBindTexture || + fn == (list_fn_cb) &jwzgles_glBindBuffer) + LOG3 (" call %-12s %s %d", F->name, + mode_desc (av[0].i), av[1].i); + else + LOG3 (" call %-12s %d %d", F->name, av[0].i, av[1].i); + ((void (*) (int, int)) fn) (av[0].i, av[1].i); + break; + + case PROTO_FF: + LOG3 (" call %-12s %7.3f %7.3f", F->name, av[0].f, av[1].f); + ((void (*) (GLfloat, GLfloat)) fn) (av[0].f, av[1].f); + break; + + case PROTO_IF: + LOG3 (" call %-12s %s %7.3f", F->name, + mode_desc (av[0].f), av[1].f); + ((void (*) (GLint, GLfloat)) fn) (av[0].i, av[1].f); + break; + + case PROTO_III: III: + if (fn == (list_fn_cb) &jwzgles_glDrawArrays || + fn == (list_fn_cb) &jwzgles_glTexParameteri) + LOG4 (" call %-12s %s %d %d", F->name, + mode_desc (av[0].i), av[1].i, av[2].i); + else + LOG4 (" call %-12s %d %d %d", F->name, + av[0].i, av[1].i, av[2].i); + ((void (*) (int, int, int)) fn) (av[0].i, av[1].i, av[2].i); + break; + + case PROTO_FFF: + LOG4 (" call %-12s %7.3f %7.3f %7.3f", F->name, + av[0].f, av[1].f, av[2].f); + ((void (*) (GLfloat, GLfloat, GLfloat)) fn) + (av[0].f, av[1].f, av[2].f); + break; + + case PROTO_IIF: + LOG4 (" call %-12s %s %s %7.3f", F->name, + mode_desc (av[0].i), mode_desc (av[1].i), av[2].f); + ((void (*) (int, int, GLfloat)) fn) (av[0].i, av[1].i, av[2].f); + break; + + case PROTO_IIII: + LOG5 (" call %-12s %d %d %d %d", F->name, + av[0].i, av[1].i, av[2].i, av[3].i); + ((void (*) (int, int, int, int)) fn) + (av[0].i, av[1].i, av[2].i, av[3].i); + break; + + case PROTO_FFFF: + LOG5 (" call %-12s %7.3f %7.3f %7.3f %7.3f", F->name, + av[0].f, av[1].f, av[2].f, av[3].f); + ((void (*) (GLfloat, GLfloat, GLfloat, GLfloat)) fn) + (av[0].f, av[1].f, av[2].f, av[3].f); + break; + + case PROTO_IFV: + { + GLfloat v[4]; + v[0] = av[1].f; + v[1] = av[2].f; + v[2] = av[3].f; + v[3] = av[4].f; + LOG6 (" call %-12s %s %3.1f %3.1f %3.1f %3.1f", F->name, + mode_desc (av[0].i), + av[1].f, av[2].f, av[3].f, av[4].f); + ((void (*) (int, const GLfloat *)) fn) (av[0].i, v); + } + break; + + case PROTO_IIFV: + { + GLfloat v[4]; + v[0] = av[2].f; + v[1] = av[3].f; + v[2] = av[4].f; + v[3] = av[5].f; + LOG7 (" call %-12s %s %-8s %3.1f %3.1f %3.1f %3.1f", F->name, + mode_desc (av[0].i), mode_desc (av[1].i), + av[2].f, av[3].f, av[4].f, av[5].f); + ((void (*) (int, int, const GLfloat *)) fn) + (av[0].i, av[1].i, v); + } + break; + + case PROTO_IIV: + { + int v[4]; + v[0] = av[1].i; + v[1] = av[2].i; + v[2] = av[3].i; + v[3] = av[4].i; + LOG6 (" call %-12s %s %3d %3d %3d %3d", F->name, + mode_desc (av[0].i), + av[1].i, av[2].i, av[3].i, av[4].i); + ((void (*) (int, const int *)) fn) (av[0].i, v); + } + break; + + case PROTO_IIIV: + { + int v[4]; + v[0] = av[2].i; + v[1] = av[3].i; + v[2] = av[4].i; + v[3] = av[5].i; + LOG7 (" call %-12s %s %-8s %3d %3d %3d %3d", F->name, + mode_desc (av[0].i), mode_desc (av[1].i), + av[2].i, av[3].i, av[4].i, av[5].i); + ((void (*) (int, int, const int *)) fn) + (av[0].i, av[1].i, v); + } + break; + + case PROTO_ARRAYS: + restore_arrays (F, av[1].i + av[2].i); + goto III; + break; + + case PROTO_FV16: + { + GLfloat m[16]; + int i; + for (i = 0; i < countof(m); i++) + m[i] = av[i].f; + LOG17 (" call %-12s [" + "%8.3f %8.3f %8.3f %8.3f " "\n\t\t\t " + "%8.3f %8.3f %8.3f %8.3f " "\n\t\t\t " + "%8.3f %8.3f %8.3f %8.3f " "\n\t\t\t " + "%8.3f %8.3f %8.3f %8.3f ]", + F->name, + m[0], m[1], m[2], m[3], + m[4], m[5], m[6], m[7], + m[8], m[9], m[10], m[11], + m[12], m[13], m[14], m[15]); + ((void (*) (GLfloat *)) fn) (m); + } + break; + + default: + Assert (0, "bogus prototype"); + break; + } + } + + LOG1 ("glCallList %d done\n", id); + + state->replaying_list--; + Assert (state->replaying_list >= 0, "glCallList corrupted"); + } +} + + +/* When we save a call to glDrawArrays into a display list, we also need to + save the prevailing copy of the arrays that it will use, and restore them + later. + */ +static void +save_arrays (list_fn *F, int count) +{ + int i = 0; + draw_array *A = (draw_array *) calloc (4, sizeof (*A)); + Assert (A, "out of memory"); + +/* if (state->set.count > 0) */ + { + glGetIntegerv (GL_VERTEX_ARRAY_BUFFER_BINDING, &A[i].binding); + glGetIntegerv (GL_VERTEX_ARRAY_SIZE, &A[i].size); + glGetIntegerv (GL_VERTEX_ARRAY_TYPE, &A[i].type); + glGetIntegerv (GL_VERTEX_ARRAY_STRIDE, &A[i].stride); + glGetPointerv (GL_VERTEX_ARRAY_POINTER, &A[i].data); + CHECK("glGetPointerv"); + copy_array_data (&A[i], count, "vert"); + } + + i++; + if (state->set.ncount > 1) + { + A[i].size = 3; + glGetIntegerv (GL_NORMAL_ARRAY_BUFFER_BINDING, &A[i].binding); + glGetIntegerv (GL_NORMAL_ARRAY_TYPE, &A[i].type); + glGetIntegerv (GL_NORMAL_ARRAY_STRIDE, &A[i].stride); + glGetPointerv (GL_NORMAL_ARRAY_POINTER, &A[i].data); + CHECK("glGetPointerv"); + copy_array_data (&A[i], count, "norm"); + } + + i++; + if (state->set.tcount > 1) + { + glGetIntegerv (GL_TEXTURE_COORD_ARRAY_BUFFER_BINDING, &A[i].binding); + glGetIntegerv (GL_TEXTURE_COORD_ARRAY_SIZE, &A[i].size); + glGetIntegerv (GL_TEXTURE_COORD_ARRAY_TYPE, &A[i].type); + glGetIntegerv (GL_TEXTURE_COORD_ARRAY_STRIDE, &A[i].stride); + glGetPointerv (GL_TEXTURE_COORD_ARRAY_POINTER, &A[i].data); + CHECK("glGetPointerv"); + copy_array_data (&A[i], count, "tex "); + } + + i++; + if (state->set.ccount > 1) + { + glGetIntegerv (GL_COLOR_ARRAY_BUFFER_BINDING, &A[i].binding); + glGetIntegerv (GL_COLOR_ARRAY_SIZE, &A[i].size); + glGetIntegerv (GL_COLOR_ARRAY_TYPE, &A[i].type); + glGetIntegerv (GL_COLOR_ARRAY_STRIDE, &A[i].stride); + glGetPointerv (GL_COLOR_ARRAY_POINTER, &A[i].data); + CHECK("glGetPointerv"); + copy_array_data (&A[i], count, "col "); + } + + /* Freed by glDeleteLists. */ + + Assert (!F->arrays, "save_arrays corrupted"); + F->arrays = A; +} + + +#ifdef DEBUG + +static void +dump_array_data (draw_array *A, int count, + const char *action, const char *name, const void *old) +{ + int bytes = count * A->stride; + + if (A->binding) + { + fprintf (stderr, + "jwzgles: %s %s %d %s %2d, %4d = %5d bind %d @ %d\n", + action, name, + A->size, mode_desc(A->type), A->stride, + count, bytes, A->binding, (int) A->data); + } + else + { + Assert (bytes == A->bytes, "array data corrupted"); + + fprintf (stderr, "jwzgles: %s %s %d %s %2d, %4d = %5d @ %lX", + action, name, + A->size, mode_desc(A->type), A->stride, + count, bytes, (unsigned long) A->data); + if (old) + fprintf (stderr, " / %lX", (unsigned long) old); + fprintf (stderr, "\n"); + } + + if (A->binding) + { + Assert (((unsigned long) A->data < 0xFFFF), + "buffer binding should be a numeric index," + " but looks like a pointer"); + +# if 0 + /* glGetBufferSubData doesn't actually exist in OpenGLES, but this + was helpful for debugging on real OpenGL... */ + GLfloat *d; + int i; + fprintf (stderr, "jwzgles: read back:\n"); + d = (GLfloat *) malloc (A->bytes); + glGetBufferSubData (GL_ARRAY_BUFFER, (int) A->data, + count * A->stride, (void *) d); + CHECK("glGetBufferSubData"); + for (i = 0; i < count * A->size; i++) + { + if (i % 4 == 0) + fprintf (stderr, "\njwzgles: %4d: ", + i + (int) A->data / sizeof(GLfloat)); + fprintf (stderr, " %7.3f", d[i]); + } + fprintf (stderr, "\n"); + free (d); +# endif + } +# if 0 + else + { + unsigned char *b = (unsigned char *) A->data; + int i; + if ((unsigned long) A->data < 0xFFFF) + { + Assert (0, "buffer data not a pointer"); + return; + } + for (i = 0; i < count; i++) + { + int j; + GLfloat *f = (GLfloat *) b; + int s = A->size; + if (s == 0) s = 3; /* normals */ + fprintf (stderr, "jwzgles: "); + for (j = 0; j < s; j++) + fprintf (stderr, " %7.3f", f[j]); + fprintf (stderr, "\n"); + b += A->stride; + } + } +# endif +} + +static void +dump_direct_array_data (int count) +{ + draw_array A = { 0, }; + + if (jwzgles_glIsEnabled (GL_VERTEX_ARRAY)) + { + glGetIntegerv (GL_VERTEX_ARRAY_BUFFER_BINDING, &A.binding); + glGetIntegerv (GL_VERTEX_ARRAY_SIZE, &A.size); + glGetIntegerv (GL_VERTEX_ARRAY_TYPE, &A.type); + glGetIntegerv (GL_VERTEX_ARRAY_STRIDE, &A.stride); + glGetPointerv (GL_VERTEX_ARRAY_POINTER, &A.data); + A.bytes = count * A.stride; + dump_array_data (&A, count, "direct", "vertex ", 0); + } + if (jwzgles_glIsEnabled (GL_NORMAL_ARRAY)) + { + A.size = 0; + glGetIntegerv (GL_NORMAL_ARRAY_BUFFER_BINDING, &A.binding); + glGetIntegerv (GL_NORMAL_ARRAY_TYPE, &A.type); + glGetIntegerv (GL_NORMAL_ARRAY_STRIDE, &A.stride); + glGetPointerv (GL_NORMAL_ARRAY_POINTER, &A.data); + A.bytes = count * A.stride; + dump_array_data (&A, count, "direct", "normal ", 0); + } + if (jwzgles_glIsEnabled (GL_TEXTURE_COORD_ARRAY)) + { + glGetIntegerv (GL_TEXTURE_COORD_ARRAY_BUFFER_BINDING, &A.binding); + glGetIntegerv (GL_TEXTURE_COORD_ARRAY_SIZE, &A.size); + glGetIntegerv (GL_TEXTURE_COORD_ARRAY_TYPE, &A.type); + glGetIntegerv (GL_TEXTURE_COORD_ARRAY_STRIDE, &A.stride); + glGetPointerv (GL_TEXTURE_COORD_ARRAY_POINTER, &A.data); + A.bytes = count * A.stride; + dump_array_data (&A, count, "direct", "texture", 0); + } + if (jwzgles_glIsEnabled (GL_COLOR_ARRAY)) + { + glGetIntegerv (GL_COLOR_ARRAY_BUFFER_BINDING, &A.binding); + glGetIntegerv (GL_COLOR_ARRAY_SIZE, &A.size); + glGetIntegerv (GL_COLOR_ARRAY_TYPE, &A.type); + glGetIntegerv (GL_COLOR_ARRAY_STRIDE, &A.stride); + glGetPointerv (GL_COLOR_ARRAY_POINTER, &A.data); + A.bytes = count * A.stride; + dump_array_data (&A, count, "direct", "color ", 0); + } +} + +#endif /* DEBUG */ + + +static void +copy_array_data (draw_array *A, int count, const char *name) +{ + /* Instead of just memcopy'ing the whole array and obeying its previous + 'stride' value, we make up a more compact array. This is because if + the same array data is being used with multiple component types, + e.g. with glInterleavedArrays, we don't want to copy all of the + data multiple times. + */ + int stride2, bytes, i, j; + const void *old; + void *data2; + const GLfloat *IF; + GLfloat *OF; + const unsigned char *IB; + unsigned char *OB; + + if (((unsigned long) A->data) < 0xFFFF) + { + Assert (0, "buffer data not a pointer"); + return; + } + + Assert (A->size >= 2 && A->size <= 4, "bogus array size"); + + switch (A->type) { + case GL_FLOAT: stride2 = A->size * sizeof(GLfloat); break; + case GL_UNSIGNED_BYTE: stride2 = A->size; break; + default: Assert (0, "bogus array type"); break; + } + + bytes = count * stride2; + Assert (bytes > 0, "bogus array count or stride"); + Assert (A->data, "missing array data"); + data2 = (void *) malloc (bytes); + Assert (data2, "out of memory"); + + IB = (const unsigned char *) A->data; + OB = (unsigned char *) data2; + IF = (const GLfloat *) A->data; + OF = (GLfloat *) data2; + + switch (A->type) { + case GL_FLOAT: + for (i = 0; i < count; i++) + { + for (j = 0; j < A->size; j++) + *OF++ = IF[j]; + IF = (const GLfloat *) (((const unsigned char *) IF) + A->stride); + } + break; + case GL_UNSIGNED_BYTE: + for (i = 0; i < count; i++) + { + for (j = 0; j < A->size; j++) + *OB++ = IB[j]; + IB += A->stride; + } + break; + default: + Assert (0, "bogus array type"); + break; + } + + old = A->data; + A->data = data2; + A->bytes = bytes; + A->stride = stride2; + +# ifdef DEBUG + dump_array_data (A, count, "saved", name, old); +# endif +} + + +static void +restore_arrays (list_fn *F, int count) +{ + int i = 0; + draw_array *A = F->arrays; + Assert (A, "missing array"); + + for (i = 0; i < 4; i++) + { + const char *name = 0; + + if (!A[i].size) + continue; + + Assert ((A[i].binding || A[i].data), + "array has neither buffer binding nor data"); + + glBindBuffer (GL_ARRAY_BUFFER, A[i].binding); + CHECK("glBindBuffer"); + + switch (i) { + case 0: glVertexPointer (A[i].size, A[i].type, A[i].stride, A[i].data); + name = "vertex "; + CHECK("glVertexPointer"); + break; + case 1: glNormalPointer ( A[i].type, A[i].stride, A[i].data); + name = "normal "; + CHECK("glNormalPointer"); + break; + case 2: glTexCoordPointer(A[i].size, A[i].type, A[i].stride, A[i].data); + name = "texture"; + CHECK("glTexCoordPointer"); + break; + case 3: glColorPointer (A[i].size, A[i].type, A[i].stride, A[i].data); + name = "color "; + CHECK("glColorPointer"); + break; + default: Assert (0, "wat"); break; + } + +# ifdef DEBUG + dump_array_data (&A[i], count, "restored", name, 0); +# endif + } + + glBindBuffer (GL_ARRAY_BUFFER, 0); /* Keep out of others' hands */ +} + + +void +jwzgles_glDrawArrays (GLuint mode, GLuint first, GLuint count) +{ + if (state->compiling_list) + { + void_int vv[3]; + vv[0].i = mode; + vv[1].i = first; + vv[2].i = count; + list_push ("glDrawArrays", (list_fn_cb) &jwzgles_glDrawArrays, + PROTO_ARRAYS, vv); + } + else + { +# ifdef DEBUG + if (! state->replaying_list) { + LOG4("direct %-12s %d %d %d", "glDrawArrays", mode, first, count); + dump_direct_array_data (first + count); + } +# endif + glDrawArrays (mode, first, count); /* the real one */ + CHECK("glDrawArrays"); + } +} + + +void +jwzgles_glInterleavedArrays (GLenum format, GLsizei stride, const void *data) +{ + /* We can implement this by calling the various *Pointer functions + with offsets into the same data, taking advantage of stride. + */ + const unsigned char *c = (const unsigned char *) data; +# define B 1 +# define F sizeof(GLfloat) + + Assert (!state->compiling_verts, + "glInterleavedArrays not allowed inside glBegin"); + + jwzgles_glEnableClientState (GL_VERTEX_ARRAY); + + if (!state->replaying_list) + LOG4 ("%sglInterleavedArrays %s %d %lX", + (state->compiling_list || state->replaying_list ? " " : ""), + mode_desc (format), stride, (unsigned long) data); + + switch (format) { + case GL_V2F: + glVertexPointer (2, GL_FLOAT, stride, c); + CHECK("glVertexPointer"); + if (!state->replaying_list) + LOG3 ("%s -> glVertexPointer 2 FLOAT %d %lX", + (state->compiling_list || state->replaying_list ? " " : ""), + stride, (unsigned long) c); + break; + case GL_V3F: + glVertexPointer (3, GL_FLOAT, stride, c); + CHECK("glVertexPointer"); + if (!state->replaying_list) + LOG3 ("%s -> glVertexPointer 3 FLOAT %d %lX", + (state->compiling_list || state->replaying_list ? " " : ""), + stride, (unsigned long) c); + break; + case GL_C4UB_V2F: + if (stride == 0) + stride = 4*B + 2*F; + jwzgles_glEnableClientState (GL_COLOR_ARRAY); + glColorPointer (4, GL_UNSIGNED_BYTE, stride, c); + CHECK("glColorPointer"); + c += 4*B; /* #### might be incorrect float-aligned address */ + glVertexPointer (2, GL_FLOAT, stride, c); + break; + case GL_C4UB_V3F: + if (stride == 0) + stride = 4*B + 3*F; + jwzgles_glEnableClientState (GL_COLOR_ARRAY); + glColorPointer (4, GL_UNSIGNED_BYTE, stride, c); + CHECK("glColorPointer"); + c += 4*B; + glVertexPointer (3, GL_FLOAT, stride, c); + CHECK("glVertexPointer"); + break; + case GL_C3F_V3F: + if (stride == 0) + stride = 3*F + 3*F; + jwzgles_glEnableClientState (GL_COLOR_ARRAY); + glColorPointer (3, GL_FLOAT, stride, c); + CHECK("glColorPointer"); + c += 3*F; + glVertexPointer (3, GL_FLOAT, stride, c); + CHECK("glVertexPointer"); + break; + case GL_N3F_V3F: + if (stride == 0) + stride = 3*F + 3*F; + jwzgles_glEnableClientState (GL_NORMAL_ARRAY); + glNormalPointer (GL_FLOAT, stride, c); + CHECK("glNormalPointer"); + if (!state->replaying_list) + LOG3 ("%s -> glNormalPointer FLOAT %d %lX", + (state->compiling_list || state->replaying_list ? " " : ""), + stride, (unsigned long) c); + c += 3*F; + glVertexPointer (3, GL_FLOAT, stride, c); + CHECK("glVertexPointer"); + if (!state->replaying_list) + LOG3 ("%s -> glVertexPointer 3 FLOAT %d %lX", + (state->compiling_list || state->replaying_list ? " " : ""), + stride, (unsigned long) c); + break; + case GL_C4F_N3F_V3F: + if (stride == 0) + stride = 4*F + 3*F + 3*F; + jwzgles_glEnableClientState (GL_COLOR_ARRAY); + glColorPointer (4, GL_FLOAT, stride, c); + CHECK("glColorPointer"); + c += 4*F; + jwzgles_glEnableClientState (GL_NORMAL_ARRAY); + glNormalPointer (GL_FLOAT, stride, c); + CHECK("glNormalPointer"); + c += 3*F; + glVertexPointer (3, GL_FLOAT, stride, c); + CHECK("glVertexPointer"); + break; + case GL_T2F_V3F: + if (stride == 0) + stride = 2*F + 3*F; + jwzgles_glEnableClientState (GL_TEXTURE_COORD_ARRAY); + glTexCoordPointer (2, GL_FLOAT, stride, c); + CHECK("glTexCoordPointer"); + c += 2*F; + glVertexPointer (3, GL_FLOAT, stride, c); + CHECK("glVertexPointer"); + break; + case GL_T4F_V4F: + if (stride == 0) + stride = 4*F + 4*F; + jwzgles_glEnableClientState (GL_TEXTURE_COORD_ARRAY); + glTexCoordPointer (4, GL_FLOAT, stride, c); + CHECK("glTexCoordPointer"); + c += 4*F; + glVertexPointer (4, GL_FLOAT, stride, c); + CHECK("glVertexPointer"); + break; + case GL_T2F_C4UB_V3F: + if (stride == 0) + stride = 2*F + 4*B + 3*F; + jwzgles_glEnableClientState (GL_TEXTURE_COORD_ARRAY); + glTexCoordPointer (2, GL_FLOAT, stride, c); + CHECK("glTexCoordPointer"); + c += 2*F; + jwzgles_glEnableClientState (GL_COLOR_ARRAY); + glColorPointer (4, GL_UNSIGNED_BYTE, stride, c); + CHECK("glColorPointer"); + c += 4*B; + glVertexPointer (3, GL_FLOAT, stride, c); + CHECK("glVertexPointer"); + break; + case GL_T2F_C3F_V3F: + if (stride == 0) + stride = 2*F + 3*F + 3*F; + jwzgles_glEnableClientState (GL_TEXTURE_COORD_ARRAY); + glTexCoordPointer (2, GL_FLOAT, stride, c); + CHECK("glTexCoordPointer"); + c += 2*F; + jwzgles_glEnableClientState (GL_COLOR_ARRAY); + glColorPointer (3, GL_FLOAT, stride, c); + CHECK("glColorPointer"); + c += 3*F; + glVertexPointer (3, GL_FLOAT, stride, c); + CHECK("glVertexPointer"); + break; + case GL_T2F_N3F_V3F: + if (stride == 0) + stride = 2*F + 3*F + 3*F; + jwzgles_glEnableClientState (GL_TEXTURE_COORD_ARRAY); + glTexCoordPointer (2, GL_FLOAT, stride, c); + CHECK("glTexCoordPointer"); + c += 2*F; + jwzgles_glEnableClientState (GL_NORMAL_ARRAY); + glNormalPointer (GL_FLOAT, stride, c); + CHECK("glNormalPointer"); + c += 3*F; + glVertexPointer (3, GL_FLOAT, stride, c); + CHECK("glVertexPointer"); + break; + case GL_T2F_C4F_N3F_V3F: + if (stride == 0) + stride = 2*F + 4*F + 3*F + 3*F; + jwzgles_glEnableClientState (GL_TEXTURE_COORD_ARRAY); + glTexCoordPointer (2, GL_FLOAT, stride, c); + CHECK("glTexCoordPointer"); + c += 2*F; + jwzgles_glEnableClientState (GL_COLOR_ARRAY); + glColorPointer (3, GL_FLOAT, stride, c); + CHECK("glColorPointer"); + c += 3*F; + jwzgles_glEnableClientState (GL_NORMAL_ARRAY); + glNormalPointer (GL_FLOAT, stride, c); + CHECK("glNormalPointer"); + c += 3*F; + glVertexPointer (3, GL_FLOAT, stride, c); + CHECK("glVertexPointer"); + break; + case GL_T4F_C4F_N3F_V4F: + if (stride == 0) + stride = 4*F + 4*F + 3*F + 4*F; + jwzgles_glEnableClientState (GL_TEXTURE_COORD_ARRAY); + glTexCoordPointer (4, GL_FLOAT, stride, c); + CHECK("glTexCoordPointer"); + c += 4*F; + jwzgles_glEnableClientState (GL_COLOR_ARRAY); + glColorPointer (4, GL_FLOAT, stride, c); + CHECK("glColorPointer"); + c += 4*F; + jwzgles_glEnableClientState (GL_NORMAL_ARRAY); + glNormalPointer (GL_FLOAT, stride, c); + CHECK("glNormalPointer"); + c += 3*F; + glVertexPointer (3, GL_FLOAT, stride, c); + CHECK("glVertexPointer"); + break; + default: + Assert (0, "glInterleavedArrays: bogus format"); + break; + } + +# undef B +# undef F +} + + + +void +jwzgles_glEnableClientState (GLuint cap) +{ + if (state->compiling_list) + { + void_int vv[1]; + vv[0].i = cap; + list_push ("glEnableClientState", + (list_fn_cb) &jwzgles_glEnableClientState, + PROTO_I, vv); + } + else + { + if (! state->replaying_list) + LOG2 ("direct %-12s %s", "glEnableClientState", mode_desc(cap)); + glEnableClientState (cap); /* the real one */ + CHECK("glEnableClientState"); + } + + switch (cap) { + case GL_VERTEX_ARRAY: + state->enabled |= ISENABLED_VERT_ARRAY; + break; + case GL_NORMAL_ARRAY: + if (! state->compiling_verts) + state->set.ncount += 2; + state->enabled |= ISENABLED_NORM_ARRAY; + break; + case GL_TEXTURE_COORD_ARRAY: + if (! state->compiling_verts) + state->set.tcount += 2; + state->enabled |= ISENABLED_TEX_ARRAY; + break; + case GL_COLOR_ARRAY: + if (! state->compiling_verts) + state->set.ccount += 2; + state->enabled |= ISENABLED_COLOR_ARRAY; + break; + default: break; + } +} + + +void +jwzgles_glDisableClientState (GLuint cap) +{ + if (state->compiling_list) + { + void_int vv[1]; + vv[0].i = cap; + list_push ("glDisableClientState", + (list_fn_cb) &jwzgles_glDisableClientState, + PROTO_I, vv); + } + else + { + if (! state->replaying_list) + LOG2 ("direct %-12s %s", "glDisableClientState", mode_desc(cap)); + glDisableClientState (cap); /* the real one */ + CHECK("glDisableClientState"); + } + + switch (cap) { + case GL_VERTEX_ARRAY: + state->enabled &= ~ISENABLED_VERT_ARRAY; + break; + case GL_NORMAL_ARRAY: + if (! state->compiling_verts) + state->set.ncount = 0; + state->enabled &= ~ISENABLED_NORM_ARRAY; + break; + case GL_TEXTURE_COORD_ARRAY: + if (! state->compiling_verts) + state->set.tcount = 0; + state->enabled &= ~ISENABLED_TEX_ARRAY; + break; + case GL_COLOR_ARRAY: + if (! state->compiling_verts) + state->set.ccount = 0; + state->enabled &= ~ISENABLED_COLOR_ARRAY; + break; + default: + break; + } +} + + +void +jwzgles_glMultMatrixf (const GLfloat *m) +{ + Assert (!state->compiling_verts, + "glMultMatrixf not allowed inside glBegin"); + if (state->compiling_list) + { + void_int vv[16]; + int i; + for (i = 0; i < countof(vv); i++) + vv[i].f = m[i]; + list_push ("glMultMatrixf", (list_fn_cb) &jwzgles_glMultMatrixf, + PROTO_FV16, vv); + } + else + { + if (! state->replaying_list) + LOG1 ("direct %-12s", "glMultMatrixf"); + glMultMatrixf (m); /* the real one */ + CHECK("glMultMatrixf"); + } +} + + +void +jwzgles_glClearIndex(GLfloat c) +{ + /* Does GLES even do indexed color? */ + Assert (0, "glClearIndex unimplemented"); +} + + +void +jwzgles_glBitmap (GLsizei width, GLsizei height, GLfloat xorig, GLfloat yorig, + GLfloat xmove, GLfloat ymove, const GLubyte *bitmap) +{ + Assert (0, "glBitmap unimplemented"); +} + +void +jwzgles_glPushAttrib(int flags) +{ + Assert (0, "glPushAttrib unimplemented"); +} + +void +jwzgles_glPopAttrib(void) +{ + Assert (0, "glPopAttrib unimplemented"); +} + + +/* These are needed for object hit detection in pinion. + Might need to rewrite that code entirely. Punt for now. + */ +void +jwzgles_glInitNames (void) +{ +/* Assert (0, "glInitNames unimplemented");*/ +} + +void +jwzgles_glPushName (GLuint name) +{ +/* Assert (0, "glPushName unimplemented");*/ +} + +GLuint +jwzgles_glPopName (void) +{ +/* Assert (0, "glPopName unimplemented");*/ + return 0; +} + +GLuint +jwzgles_glRenderMode (GLuint mode) +{ +/* Assert (0, "glRenderMode unimplemented");*/ + return 0; +} + +void +jwzgles_glSelectBuffer (GLsizei size, GLuint *buf) +{ +/* Assert (0, "glSelectBuffer unimplemented");*/ +} + + +void +jwzgles_glGenTextures (GLuint n, GLuint *ret) +{ + Assert (!state->compiling_verts, + "glGenTextures not allowed inside glBegin"); + /* technically legal, but stupid! */ + Assert (!state->compiling_list, + "glGenTextures not allowed inside glNewList"); + if (! state->replaying_list) + LOG1 ("direct %-12s", "glGenTextures"); + glGenTextures (n, ret); /* the real one */ + CHECK("glGenTextures"); +} + + +/* return the next larger power of 2. */ +static int +to_pow2 (int value) +{ + int i = 1; + while (i < value) i <<= 1; + return i; +} + +void +jwzgles_glTexImage1D (GLenum target, GLint level, + GLint internalFormat, + GLsizei width, GLint border, + GLenum format, GLenum type, + const GLvoid *data) +{ + Assert (!state->compiling_verts, "glTexImage1D not allowed inside glBegin"); + /* technically legal, but stupid! */ + Assert (!state->compiling_list, "glTexImage1D inside glNewList"); + Assert (width == to_pow2(width), "width must be a power of 2"); + + if (target == GL_TEXTURE_1D) target = GL_TEXTURE_2D; + jwzgles_glTexImage2D (target, level, internalFormat, width, 1, + border, format, type, data); +} + +void +jwzgles_glTexImage2D (GLenum target, + GLint level, + GLint internalFormat, + GLsizei width, + GLsizei height, + GLint border, + GLenum format, + GLenum type, + const GLvoid *data) +{ + GLvoid *d2 = (GLvoid *) data; + Assert (!state->compiling_verts, "glTexImage2D not allowed inside glBegin"); + Assert (!state->compiling_list, /* technically legal, but stupid! */ + "glTexImage2D not allowed inside glNewList"); + + Assert (width == to_pow2(width), "width must be a power of 2"); + Assert (height == to_pow2(height), "height must be a power of 2"); + + /* OpenGLES no longer supports "4" as a synonym for "RGBA". */ + switch (internalFormat) { + case 1: internalFormat = GL_LUMINANCE; break; + case 2: internalFormat = GL_LUMINANCE_ALPHA; break; + case 3: internalFormat = GL_RGB; break; + case 4: internalFormat = GL_RGBA; break; + } + + /* GLES does not let us omit the data pointer to create a blank texture. */ + if (! data) + { + d2 = (GLvoid *) calloc (1, width * height * sizeof(GLfloat) * 4); + Assert (d2, "out of memory"); + } + + if (internalFormat == GL_RGB && format == GL_RGBA) + internalFormat = GL_RGBA; /* WTF */ + if (type == GL_UNSIGNED_INT_8_8_8_8_REV) + type = GL_UNSIGNED_BYTE; + + if (! state->replaying_list) + LOG10 ("direct %-12s %s %d %s %d %d %d %s %s 0x%lX", "glTexImage2D", + mode_desc(target), level, mode_desc(internalFormat), + width, height, border, mode_desc(format), mode_desc(type), + (unsigned long) d2); + glTexImage2D (target, level, internalFormat, width, height, border, + format, type, d2); /* the real one */ + CHECK("glTexImage2D"); + + if (d2 != data) free (d2); +} + +void +jwzgles_glTexSubImage2D (GLenum target, GLint level, + GLint xoffset, GLint yoffset, + GLsizei width, GLsizei height, + GLenum format, GLenum type, + const GLvoid *pixels) +{ + Assert (!state->compiling_verts, + "glTexSubImage2D not allowed inside glBegin"); + Assert (!state->compiling_list, /* technically legal, but stupid! */ + "glTexSubImage2D not allowed inside glNewList"); + + if (! state->replaying_list) + LOG10 ("direct %-12s %s %d %d %d %d %d %s %s 0x%lX", "glTexSubImage2D", + mode_desc(target), level, xoffset, yoffset, width, height, + mode_desc (format), mode_desc (type), (unsigned long) pixels); + glTexSubImage2D (target, level, xoffset, yoffset, width, height, + format, type, pixels); /* the real one */ + CHECK("glTexSubImage2D"); +} + +void +jwzgles_glCopyTexImage2D (GLenum target, GLint level, GLenum internalformat, + GLint x, GLint y, GLsizei width, GLsizei height, + GLint border) +{ + Assert (!state->compiling_verts, + "glCopyTexImage2D not allowed inside glBegin"); + Assert (!state->compiling_list, /* technically legal, but stupid! */ + "glCopyTexImage2D not allowed inside glNewList"); + if (! state->replaying_list) + LOG9 ("direct %-12s %s %d %s %d %d %d %d %d", "glCopyTexImage2D", + mode_desc(target), level, mode_desc(internalformat), + x, y, width, height, border); + glCopyTexImage2D (target, level, internalformat, x, y, width, height, + border); /* the real one */ + CHECK("glCopyTexImage2D"); +} + + +void +jwzgles_glTexGenfv (GLenum coord, GLenum pname, const GLfloat *params) +{ + /* OpenGLES doesn't have this at all! + "Oh, just rewrite that code to use GPU shaders", they say. + How fucking convenient. + + So, when this is enabled, we could emit a GL_TEXTURE_COORD_ARRAY + and compute coords for each vertex in the current GL_VERTEX_ARRAY + as per http://www.opengl.org/wiki/Mathematics_of_glTexGen + but holy shit, what a pain in the ass! + + For GL_OBJECT_LINEAR, we can just re-use the vertex array as + the texture array, using a proper stride. That's hardly worth + the effort, though, because bouncingcow is the only hack that + uses that, and not even by default. + */ + Assert (coord == GL_S || coord == GL_T, "glTexGenfv: unimplemented coord"); + + /* This is probably default-ish, so do nothing. */ + if (pname == GL_EYE_PLANE) return; + + Assert (pname == GL_TEXTURE_GEN_MODE, "glTexGenfv: unimplemented name"); + Assert (params[0] == GL_EYE_LINEAR, "glTexGenfv: unimplemented mode"); +} + +void +jwzgles_glTexGeni (GLenum coord, GLenum pname, GLint param) +{ + GLfloat v = param; + jwzgles_glTexGenfv (coord, pname, &v); +} + + +int +jwzgles_gluBuild2DMipmaps (GLenum target, + GLint internalFormat, + GLsizei width, + GLsizei height, + GLenum format, + GLenum type, + const GLvoid *data) +{ + /* Not really bothering with mipmapping; only making one level. + Note that this required a corresponding hack in glTexParameterf(). + */ + + int w2 = to_pow2(width); + int h2 = to_pow2(height); + + void *d2 = (void *) data; + + /* OpenGLES no longer supports "4" as a synonym for "RGBA". */ + switch (internalFormat) { + case 1: internalFormat = GL_LUMINANCE; break; + case 2: internalFormat = GL_LUMINANCE_ALPHA; break; + case 3: internalFormat = GL_RGB; break; + case 4: internalFormat = GL_RGBA; break; + } + +/* if (w2 < h2) w2 = h2; + if (h2 < w2) h2 = w2;*/ + + if (w2 != width || h2 != height) + { + /* Scale up the image bits to fit the power-of-2 texture. + We have to do this because the mipmap API assumes that + the texture bits go to texture coordinates 1.0 x 1.0. + This could be more efficient, but it doesn't happen often. + */ + int istride = (format == GL_RGBA ? 4 : 3); + int ostride = 4; + int ibpl = istride * width; + int obpl = ostride * w2; + int oy; + const unsigned char *in = (unsigned char *) data; + unsigned char *out = (void *) malloc (h2 * obpl); + Assert (out, "out of memory"); + d2 = out; + + for (oy = 0; oy < h2; oy++) + { + int iy = oy * height / h2; + const unsigned char *iline = in + (iy * ibpl); + unsigned char *oline = out + (oy * obpl); + int ox; + for (ox = 0; ox < w2; ox++) + { + int ix = ox * width / w2; + const unsigned char *i = iline + (ix * istride); + unsigned char *o = oline + (ox * ostride); + *o++ = *i++; /* R */ + *o++ = *i++; /* G */ + *o++ = *i++; /* B */ + *o++ = (istride == 4 ? *i : 0xFF); /* A */ + } + } + width = w2; + height = h2; + internalFormat = GL_RGBA; + format = GL_RGBA; + } + + jwzgles_glTexImage2D (target, 0, internalFormat, w2, h2, 0, + format, type, d2); + if (d2 != data) free (d2); + + return 0; +} + + +void +jwzgles_glRectf (GLfloat x1, GLfloat y1, GLfloat x2, GLfloat y2) +{ + jwzgles_glBegin (GL_POLYGON); + jwzgles_glVertex2f (x1, y1); + jwzgles_glVertex2f (x2, y1); + jwzgles_glVertex2f (x2, y2); + jwzgles_glVertex2f (x1, y2); + jwzgles_glEnd (); +} + +void +jwzgles_glRecti (GLint x1, GLint y1, GLint x2, GLint y2) +{ + jwzgles_glRectf (x1, y1, x2, y2); +} + +void +jwzgles_glClearDepth (GLfloat d) +{ + /* Not sure what to do here */ + Assert (d == 1.0, "glClearDepth unimplemented"); +} + + +void +jwzgles_glEnable (GLuint bit) +{ + Assert (!state->compiling_verts, "glEnable not allowed inside glBegin"); + if (state->compiling_list) + { + void_int vv[1]; + vv[0].i = bit; + list_push ("glEnable", (list_fn_cb) &jwzgles_glEnable, PROTO_I, vv); + } + else + { + if (! state->replaying_list) + LOG2 ("direct %-12s %s", "glEnable", mode_desc(bit)); + glEnable (bit); /* the real one */ + CHECK("glEnable"); + + switch (bit) { + case GL_TEXTURE_2D: state->enabled |= ISENABLED_TEXTURE_2D; break; + case GL_TEXTURE_GEN_S: state->enabled |= ISENABLED_TEXTURE_GEN_S; break; + case GL_TEXTURE_GEN_T: state->enabled |= ISENABLED_TEXTURE_GEN_T; break; + case GL_LIGHTING: state->enabled |= ISENABLED_LIGHTING; break; + case GL_BLEND: state->enabled |= ISENABLED_BLEND; break; + case GL_DEPTH_TEST: state->enabled |= ISENABLED_DEPTH_TEST; break; + case GL_CULL_FACE: state->enabled |= ISENABLED_CULL_FACE; break; + case GL_NORMALIZE: state->enabled |= ISENABLED_NORMALIZE; break; + case GL_FOG: state->enabled |= ISENABLED_FOG; break; + case GL_COLOR_MATERIAL: state->enabled |= ISENABLED_COLMAT; break; + + /* Do these work with glEnable or only with glEnableClientState? */ + case GL_VERTEX_ARRAY: state->enabled |= ISENABLED_VERT_ARRAY; break; + case GL_NORMAL_ARRAY: state->enabled |= ISENABLED_NORM_ARRAY; break; + case GL_TEXTURE_COORD_ARRAY: state->enabled |= ISENABLED_TEX_ARRAY;break; + case GL_COLOR_ARRAY: state->enabled |= ISENABLED_COLOR_ARRAY; break; + + default: break; + } + } +} + + +void +jwzgles_glDisable (GLuint bit) +{ + Assert (!state->compiling_verts, "glDisable not allowed inside glBegin"); + if (state->compiling_list) + { + void_int vv[1]; + vv[0].i = bit; + list_push ("glDisable", (list_fn_cb) &jwzgles_glDisable, PROTO_I, vv); + } + else + { + if (! state->replaying_list) + LOG2 ("direct %-12s %s", "glDisable", mode_desc(bit)); + glDisable (bit); /* the real one */ + CHECK("glDisable"); + + switch (bit) { + case GL_TEXTURE_2D: state->enabled &= ~ISENABLED_TEXTURE_2D; break; + case GL_TEXTURE_GEN_S: state->enabled &= ~ISENABLED_TEXTURE_GEN_S; break; + case GL_TEXTURE_GEN_T: state->enabled &= ~ISENABLED_TEXTURE_GEN_T; break; + case GL_LIGHTING: state->enabled &= ~ISENABLED_LIGHTING; break; + case GL_BLEND: state->enabled &= ~ISENABLED_BLEND; break; + case GL_DEPTH_TEST: state->enabled &= ~ISENABLED_DEPTH_TEST; break; + case GL_CULL_FACE: state->enabled &= ~ISENABLED_CULL_FACE; break; + case GL_NORMALIZE: state->enabled &= ~ISENABLED_NORMALIZE; break; + case GL_FOG: state->enabled &= ~ISENABLED_FOG; break; + case GL_COLOR_MATERIAL: state->enabled &= ~ISENABLED_COLMAT; break; + + /* Do these work with glEnable or only with glEnableClientState? */ + case GL_VERTEX_ARRAY: state->enabled &= ~ISENABLED_VERT_ARRAY; break; + case GL_NORMAL_ARRAY: state->enabled &= ~ISENABLED_NORM_ARRAY; break; + case GL_TEXTURE_COORD_ARRAY: state->enabled &= ~ISENABLED_TEX_ARRAY;break; + case GL_COLOR_ARRAY: state->enabled &= ~ISENABLED_COLOR_ARRAY; break; + + default: break; + } + } +} + + +GLboolean +jwzgles_glIsEnabled (GLuint bit) +{ + /* + Assert (!state->compiling_verts, "glIsEnabled not allowed inside glBegin"); + Assert (!state->compiling_list, "glIsEnabled not allowed inside glNewList"); + */ + switch (bit) { + case GL_TEXTURE_2D: return !!(state->enabled & ISENABLED_TEXTURE_2D); + case GL_TEXTURE_GEN_S: return !!(state->enabled & ISENABLED_TEXTURE_GEN_S); + case GL_TEXTURE_GEN_T: return !!(state->enabled & ISENABLED_TEXTURE_GEN_T); + case GL_LIGHTING: return !!(state->enabled & ISENABLED_LIGHTING); + case GL_BLEND: return !!(state->enabled & ISENABLED_BLEND); + case GL_DEPTH_TEST: return !!(state->enabled & ISENABLED_DEPTH_TEST); + case GL_CULL_FACE: return !!(state->enabled & ISENABLED_CULL_FACE); + case GL_NORMALIZE: return !!(state->enabled & ISENABLED_NORMALIZE); + case GL_FOG: return !!(state->enabled & ISENABLED_FOG); + case GL_COLOR_MATERIAL: return !!(state->enabled & ISENABLED_COLMAT); + + /* Do these work with glEnable or only with glEnableClientState? + We need to query them, and there is no glIsClientStateEnabled. + */ + case GL_VERTEX_ARRAY: return !!(state->enabled & ISENABLED_VERT_ARRAY); + case GL_NORMAL_ARRAY: return !!(state->enabled & ISENABLED_NORM_ARRAY); + case GL_TEXTURE_COORD_ARRAY: return !!(state->enabled & ISENABLED_TEX_ARRAY); + case GL_COLOR_ARRAY: return !!(state->enabled & ISENABLED_COLOR_ARRAY); + default: Assert (0, "glIsEnabled unimplemented bit"); break; + } +} + + +/* The spec says that OpenGLES 1.x doesn't implement glGetFloatv. + Were this true, it would suck, for it would mean that there was no + way to retrieve the prevailing matrixes. To implement this, we'd + have to keep track of them all on the client side by combining in + all the actions of glMultMatrixf, glRotatef, etc. + + However, Apple's iOS OpenGLES *does* provide glGetFloatv! + */ +void +jwzgles_glGetFloatv (GLenum pname, GLfloat *params) +{ + if (! state->replaying_list) + LOG2 ("direct %-12s %s", "glGetFloatv", mode_desc(pname)); + glGetFloatv (pname, params); /* the real one */ + CHECK("glGetFloatv"); +} + + +/* Likewise: not supposed to be there, but it is. */ +void +jwzgles_glGetPointerv (GLenum pname, GLvoid *params) +{ + if (! state->replaying_list) + LOG2 ("direct %-12s %s", "glGetPointerv", mode_desc(pname)); + glGetPointerv (pname, params); /* the real one */ + CHECK("glGetPointerv"); +} + + +/* How many cells are written into the *params array. + We need to know this to avoid smashing the caller's stack + if they asked for a single-value parameter. + */ +static int +glGet_ret_count (GLenum pname) +{ + switch (pname) { +/*case GL_COLOR_MATRIX: */ + case GL_MODELVIEW_MATRIX: + case GL_PROJECTION_MATRIX: + case GL_TEXTURE_MATRIX: +/*case GL_TRANSPOSE_COLOR_MATRIX: */ +/*case GL_TRANSPOSE_MODELVIEW_MATRIX: */ +/*case GL_TRANSPOSE_PROJECTION_MATRIX: */ +/*case GL_TRANSPOSE_TEXTURE_MATRIX: */ + return 16; +/*case GL_ACCUM_CLEAR_VALUE: */ +/*case GL_BLEND_COLOR: */ + case GL_COLOR_CLEAR_VALUE: + case GL_COLOR_WRITEMASK: + case GL_CURRENT_COLOR: +/*case GL_CURRENT_RASTER_COLOR: */ +/*case GL_CURRENT_RASTER_POSITION: */ +/*case GL_CURRENT_RASTER_SECONDARY_COLOR: */ +/*case GL_CURRENT_RASTER_TEXTURE_COORDS: */ +/*case GL_CURRENT_SECONDARY_COLOR: */ + case GL_CURRENT_TEXTURE_COORDS: + case GL_FOG_COLOR: + case GL_LIGHT_MODEL_AMBIENT: +/*case GL_MAP2_GRID_DOMAIN: */ + case GL_SCISSOR_BOX: + case GL_VIEWPORT: + return 4; + case GL_CURRENT_NORMAL: + case GL_POINT_DISTANCE_ATTENUATION: + return 3; + case GL_ALIASED_LINE_WIDTH_RANGE: + case GL_ALIASED_POINT_SIZE_RANGE: + case GL_DEPTH_RANGE: +/*case GL_LINE_WIDTH_RANGE: */ +/*case GL_MAP1_GRID_DOMAIN: */ +/*case GL_MAP2_GRID_SEGMENTS: */ + case GL_MAX_VIEWPORT_DIMS: +/*case GL_POINT_SIZE_RANGE: */ + case GL_POLYGON_MODE: + case GL_SMOOTH_LINE_WIDTH_RANGE: + case GL_SMOOTH_POINT_SIZE_RANGE: + return 2; + default: + return 1; + } +} + + +void +jwzgles_glGetDoublev (GLenum pname, GLdouble *params) +{ + GLfloat m[16]; + int i, j = glGet_ret_count (pname); + jwzgles_glGetFloatv (pname, m); + for (i = 0; i < j; i++) + params[i] = m[i]; +} + + +void +jwzgles_glGetIntegerv (GLenum pname, GLint *params) +{ + GLfloat m[16]; + int i, j = glGet_ret_count (pname); + jwzgles_glGetFloatv (pname, m); + for (i = 0; i < j; i++) + params[i] = m[i]; +} + + +void +jwzgles_glGetBooleanv (GLenum pname, GLboolean *params) +{ + GLfloat m[16]; + int i, j = glGet_ret_count (pname); + jwzgles_glGetFloatv (pname, m); + for (i = 0; i < j; i++) + params[i] = (m[i] != 0.0); +} + + +const char * +jwzgles_gluErrorString (GLenum error) +{ + static char s[20]; + sprintf (s, "0x%lX", (unsigned long) error); + return s; +} + + +/* These four *Pointer calls (plus glBindBuffer and glBufferData) can + be included inside glNewList, but they actually execute immediately + anyway, because their data is recorded in the list by the + subsequently-recorded call to glDrawArrays. This is a little weird. + */ +void +jwzgles_glVertexPointer (GLuint size, GLuint type, GLuint stride, + const GLvoid *ptr) +{ + if (! state->replaying_list) + LOG5 ("direct %-12s %d %s %d 0x%lX", "glVertexPointer", + size, mode_desc(type), stride, (unsigned long) ptr); + glVertexPointer (size, type, stride, ptr); /* the real one */ + CHECK("glVertexPointer"); +} + +void +jwzgles_glNormalPointer (GLuint type, GLuint stride, const GLvoid *ptr) +{ + if (! state->replaying_list) + LOG4 ("direct %-12s %s %d 0x%lX", "glNormalPointer", + mode_desc(type), stride, (unsigned long) ptr); + glNormalPointer (type, stride, ptr); /* the real one */ + CHECK("glNormalPointer"); +} + +void +jwzgles_glColorPointer (GLuint size, GLuint type, GLuint stride, + const GLvoid *ptr) +{ + if (! state->replaying_list) + LOG5 ("direct %-12s %d %s %d 0x%lX", "glColorPointer", + size, mode_desc(type), stride, (unsigned long) ptr); + glColorPointer (size, type, stride, ptr); /* the real one */ + CHECK("glColorPointer"); +} + +void +jwzgles_glTexCoordPointer (GLuint size, GLuint type, GLuint stride, + const GLvoid *ptr) +{ + if (! state->replaying_list) + LOG5 ("direct %-12s %d %s %d 0x%lX", "glTexCoordPointer", + size, mode_desc(type), stride, (unsigned long) ptr); + glTexCoordPointer (size, type, stride, ptr); /* the real one */ + CHECK("glTexCoordPointer"); +} + +void +jwzgles_glBindBuffer (GLuint target, GLuint buffer) +{ + if (! state->replaying_list) + LOG3 ("direct %-12s %s %d", "glBindBuffer", mode_desc(target), buffer); + glBindBuffer (target, buffer); /* the real one */ + CHECK("glBindBuffer"); +} + +void +jwzgles_glBufferData (GLenum target, GLsizeiptr size, const void *data, + GLenum usage) +{ + if (! state->replaying_list) + LOG5 ("direct %-12s %s %ld 0x%lX %s", "glBufferData", + mode_desc(target), size, (unsigned long) data, mode_desc(usage)); + glBufferData (target, size, data, usage); /* the real one */ + CHECK("glBufferData"); +} + + +void +jwzgles_glTexParameterf (GLuint target, GLuint pname, GLfloat param) +{ + Assert (!state->compiling_verts, + "glTexParameterf not allowed inside glBegin"); + + /* We don't *really* implement mipmaps, so just turn this off. */ + if (param == GL_LINEAR_MIPMAP_LINEAR) param = GL_LINEAR; + if (param == GL_NEAREST_MIPMAP_LINEAR) param = GL_LINEAR; + if (param == GL_LINEAR_MIPMAP_NEAREST) param = GL_NEAREST; + if (param == GL_NEAREST_MIPMAP_NEAREST) param = GL_NEAREST; + + /* We implement 1D textures as 2D textures. */ + if (target == GL_TEXTURE_1D) target = GL_TEXTURE_2D; + + /* Apparently this is another invalid enum. Just ignore it. */ + if ((pname == GL_TEXTURE_WRAP_S || pname == GL_TEXTURE_WRAP_T) && + param == GL_CLAMP) + return; + + if (state->compiling_list) + { + void_int vv[3]; + vv[0].i = target; + vv[1].i = pname; + vv[2].f = param; + list_push ("glTexParameterf", (list_fn_cb) &jwzgles_glTexParameterf, + PROTO_IIF, vv); + } + else + { + if (! state->replaying_list) + LOG4 ("direct %-12s %s %s %7.3f", "glTexParameterf", + mode_desc(target), mode_desc(pname), param); + glTexParameterf (target, pname, param); /* the real one */ + CHECK("glTexParameterf"); + } +} + +void +jwzgles_glTexParameteri (GLuint target, GLuint pname, GLuint param) +{ + jwzgles_glTexParameterf (target, pname, param); +} + + +void +jwzgles_glBindTexture (GLuint target, GLuint texture) +{ + Assert (!state->compiling_verts, + "glBindTexture not allowed inside glBegin"); + + /* We implement 1D textures as 2D textures. */ + if (target == GL_TEXTURE_1D) target = GL_TEXTURE_2D; + + if (state->compiling_list) + { + void_int vv[2]; + vv[0].i = target; + vv[1].i = texture; + list_push ("glBindTexture", (list_fn_cb) &jwzgles_glBindTexture, + PROTO_II, vv); + } + else + { + if (! state->replaying_list) + LOG3 ("direct %-12s %s %d", "glBindTexture", + mode_desc(target), texture); + glBindTexture (target, texture); /* the real one */ + CHECK("glBindTexture"); + } +} + + + +/* Matrix functions, mostly cribbed from Mesa. + */ + +void +jwzgles_glFrustum (GLfloat left, GLfloat right, + GLfloat bottom, GLfloat top, + GLfloat near, GLfloat far) +{ + GLfloat m[16]; + GLfloat x = (2 * near) / (right-left); + GLfloat y = (2 * near) / (top - bottom); + GLfloat a = (right + left) / (right - left); + GLfloat b = (top + bottom) / (top - bottom); + GLfloat c = -(far + near) / (far - near); + GLfloat d = -(2 * far * near) / (far - near); + +# define M(X,Y) m[Y * 4 + X] + M(0,0) = x; M(0,1) = 0; M(0,2) = a; M(0,3) = 0; + M(1,0) = 0; M(1,1) = y; M(1,2) = b; M(1,3) = 0; + M(2,0) = 0; M(2,1) = 0; M(2,2) = c; M(2,3) = d; + M(3,0) = 0; M(3,1) = 0; M(3,2) = -1; M(3,3) = 0; +# undef M + + jwzgles_glMultMatrixf (m); +} + + +void +jwzgles_glOrtho (GLfloat left, GLfloat right, + GLfloat bottom, GLfloat top, + GLfloat near, GLfloat far) +{ + GLfloat m[16]; + GLfloat a = 2 / (right - left); + GLfloat b = -(right + left) / (right - left); + GLfloat c = 2 / (top - bottom); + GLfloat d = -(top + bottom) / (top - bottom); + GLfloat e = -2 / (far - near); + GLfloat f = -(far + near) / (far - near); + +# define M(X,Y) m[Y * 4 + X] + M(0,0) = a; M(0,1) = 0; M(0,2) = 0; M(0,3) = b; + M(1,0) = 0; M(1,1) = c; M(1,2) = 0; M(1,3) = d; + M(2,0) = 0; M(2,1) = 0; M(2,2) = e; M(2,3) = f; + M(3,0) = 0; M(3,1) = 0; M(3,2) = 0; M(3,3) = 1; +# undef M + + jwzgles_glMultMatrixf (m); +} + + +void +jwzgles_gluPerspective (GLdouble fovy, GLdouble aspect, + GLdouble near, GLdouble far) +{ + GLfloat m[16]; + double si, co, dz; + double rad = fovy / 2 * M_PI / 180; + double a, b, c, d; + + dz = far - near; + si = sin(rad); + if (dz == 0 || si == 0 || aspect == 0) + return; + co = cos(rad) / si; + + a = co / aspect; + b = co; + c = -(far + near) / dz; + d = -2 * near * far / dz; + +# define M(X,Y) m[Y * 4 + X] + M(0,0) = a; M(0,1) = 0; M(0,2) = 0; M(0,3) = 0; + M(1,0) = 0; M(1,1) = b; M(1,2) = 0; M(1,3) = 0; + M(2,0) = 0; M(2,1) = 0; M(2,2) = c; M(2,3) = d; + M(3,0) = 0; M(3,1) = 0; M(3,2) = -1; M(3,3) = 0; +# undef M + + jwzgles_glMultMatrixf (m); +} + + +void +jwzgles_gluLookAt (GLfloat eyex, GLfloat eyey, GLfloat eyez, + GLfloat centerx, GLfloat centery, GLfloat centerz, + GLfloat upx, GLfloat upy, GLfloat upz) +{ + GLfloat m[16]; + GLfloat x[3], y[3], z[3]; + GLfloat mag; + + /* Make rotation matrix */ + + /* Z vector */ + z[0] = eyex - centerx; + z[1] = eyey - centery; + z[2] = eyez - centerz; + mag = sqrt(z[0] * z[0] + z[1] * z[1] + z[2] * z[2]); + if (mag) { /* mpichler, 19950515 */ + z[0] /= mag; + z[1] /= mag; + z[2] /= mag; + } + + /* Y vector */ + y[0] = upx; + y[1] = upy; + y[2] = upz; + + /* X vector = Y cross Z */ + x[0] = y[1] * z[2] - y[2] * z[1]; + x[1] = -y[0] * z[2] + y[2] * z[0]; + x[2] = y[0] * z[1] - y[1] * z[0]; + + /* Recompute Y = Z cross X */ + y[0] = z[1] * x[2] - z[2] * x[1]; + y[1] = -z[0] * x[2] + z[2] * x[0]; + y[2] = z[0] * x[1] - z[1] * x[0]; + + /* mpichler, 19950515 */ + /* cross product gives area of parallelogram, which is < 1.0 for + * non-perpendicular unit-length vectors; so normalize x, y here + */ + + mag = sqrt(x[0] * x[0] + x[1] * x[1] + x[2] * x[2]); + if (mag) { + x[0] /= mag; + x[1] /= mag; + x[2] /= mag; + } + + mag = sqrt(y[0] * y[0] + y[1] * y[1] + y[2] * y[2]); + if (mag) { + y[0] /= mag; + y[1] /= mag; + y[2] /= mag; + } + +#define M(row,col) m[col*4+row] + M(0, 0) = x[0]; M(0, 1) = x[1]; M(0, 2) = x[2]; M(0, 3) = 0.0; + M(1, 0) = y[0]; M(1, 1) = y[1]; M(1, 2) = y[2]; M(1, 3) = 0.0; + M(2, 0) = z[0]; M(2, 1) = z[1]; M(2, 2) = z[2]; M(2, 3) = 0.0; + M(3, 0) = 0.0; M(3, 1) = 0.0; M(3, 2) = 0.0; M(3, 3) = 1.0; +#undef M + + jwzgles_glMultMatrixf(m); + + /* Translate Eye to Origin */ + jwzgles_glTranslatef(-eyex, -eyey, -eyez); +} + + +static void __gluMultMatrixVecd (const GLdouble matrix[16], + const GLdouble in[4], + GLdouble out[4]) +{ + int i; + + for (i=0; i<4; i++) { + out[i] = + in[0] * matrix[0*4+i] + + in[1] * matrix[1*4+i] + + in[2] * matrix[2*4+i] + + in[3] * matrix[3*4+i]; + } +} + +GLint +jwzgles_gluProject (GLdouble objx, GLdouble objy, GLdouble objz, + const GLdouble modelMatrix[16], + const GLdouble projMatrix[16], + const GLint viewport[4], + GLdouble *winx, GLdouble *winy, GLdouble *winz) +{ + GLdouble in[4]; + GLdouble out[4]; + + /* #### I suspect this is not working right. I was seeing crazy values + in lament.c. Maybe there's some float-vs-double confusion going on? + */ + + in[0]=objx; + in[1]=objy; + in[2]=objz; + in[3]=1.0; + __gluMultMatrixVecd(modelMatrix, in, out); + __gluMultMatrixVecd(projMatrix, out, in); + if (in[3] == 0.0) return(GL_FALSE); + in[0] /= in[3]; + in[1] /= in[3]; + in[2] /= in[3]; + /* Map x, y and z to range 0-1 */ + in[0] = in[0] * 0.5 + 0.5; + in[1] = in[1] * 0.5 + 0.5; + in[2] = in[2] * 0.5 + 0.5; + + /* Map x,y to viewport */ + in[0] = in[0] * viewport[2] + viewport[0]; + in[1] = in[1] * viewport[3] + viewport[1]; + + *winx=in[0]; + *winy=in[1]; + *winz=in[2]; + return(GL_TRUE); +} + + +/* The following functions are present in both OpenGL 1.1 and in OpenGLES 1, + but are allowed within glNewList/glEndList, so we must wrap them to allow + them to either be recorded in lists, or run directly. + + All this CPP obscenity is me screaming in rage at all the ways that C is + not Lisp, as all I want to do here is DEFADVICE. + */ + +#define PROTO_V PROTO_VOID +#define TYPE_V GLuint +#define ARGS_V void +#define VARS_V /* */ +#define LOGS_V "\n" +#define FILL_V /* */ + +#define TYPE_I GLuint +#define TYPE_II TYPE_I +#define TYPE_III TYPE_I +#define TYPE_IIII TYPE_I +#define ARGS_I TYPE_I a +#define ARGS_II TYPE_I a, TYPE_I b +#define ARGS_III TYPE_I a, TYPE_I b, TYPE_I c +#define ARGS_IIII TYPE_I a, TYPE_I b, TYPE_I c, TYPE_I d +#define LOGS_I "%s\n", mode_desc(a) +#define LOGS_II "%s %d\n", mode_desc(a), b +#define LOGS_III "%s %s %s\n", mode_desc(a), mode_desc(b), mode_desc(c) +#define LOGS_IIII "%d %d %d %d\n", a, b, c, d +#define VARS_I a +#define VARS_II a, b +#define VARS_III a, b, c +#define VARS_IIII a, b, c, d +#define FILL_I vv[0].i = a; +#define FILL_II vv[0].i = a; vv[1].i = b; +#define FILL_III vv[0].i = a; vv[1].i = b; vv[2].i = c; +#define FILL_IIII vv[0].i = a; vv[1].i = b; vv[2].i = c; vv[3].i = d; + +#define TYPE_F GLfloat +#define TYPE_FF TYPE_F +#define TYPE_FFF TYPE_F +#define TYPE_FFFF TYPE_F +#define ARGS_F TYPE_F a +#define ARGS_FF TYPE_F a, TYPE_F b +#define ARGS_FFF TYPE_F a, TYPE_F b, TYPE_F c +#define ARGS_FFFF TYPE_F a, TYPE_F b, TYPE_F c, TYPE_F d +#define LOGS_F "%7.3f\n", a +#define LOGS_FF "%7.3f %7.3f\n", a, b +#define LOGS_FFF "%7.3f %7.3f %7.3f\n", a, b, c +#define LOGS_FFFF "%7.3f %7.3f %7.3f %7.3f\n", a, b, c, d +#define VARS_F VARS_I +#define VARS_FF VARS_II +#define VARS_FFF VARS_III +#define VARS_FFFF VARS_IIII +#define FILL_F vv[0].f = a; +#define FILL_FF vv[0].f = a; vv[1].f = b; +#define FILL_FFF vv[0].f = a; vv[1].f = b; vv[2].f = c; +#define FILL_FFFF vv[0].f = a; vv[1].f = b; vv[2].f = c; vv[3].f = d; + +#define ARGS_IF TYPE_I a, TYPE_F b +#define VARS_IF VARS_II +#define LOGS_IF "%s %7.3f\n", mode_desc(a), b +#define FILL_IF vv[0].i = a; vv[1].f = b; + +#define ARGS_IIF TYPE_I a, TYPE_I b, TYPE_F c +#define VARS_IIF VARS_III +#define LOGS_IIF "%s %s %7.3f\n", mode_desc(a), mode_desc(b), c +#define FILL_IIF vv[0].i = a; vv[1].i = b; vv[2].f = c; + +#define TYPE_IV GLint +#define ARGS_IIV TYPE_I a, const TYPE_IV *b +#define VARS_IIV VARS_II +#define LOGS_IIV "%s %d %d %d %d\n", mode_desc(a), b[0], b[1], b[2], b[3] +#define FILL_IIV vv[0].i = a; \ + vv[1].i = b[0]; vv[2].i = b[1]; \ + vv[3].i = b[2]; vv[4].i = b[3]; + +#define ARGS_IFV TYPE_I a, const TYPE_F *b +#define VARS_IFV VARS_II +#define LOGS_IFV "%s %7.3f %7.3f %7.3f %7.3f\n", mode_desc(a), \ + b[0], b[1], b[2], b[3] +#define FILL_IFV vv[0].i = a; \ + vv[1].f = b[0]; vv[2].f = b[1]; \ + vv[3].f = b[2]; vv[4].f = b[3]; + +#define ARGS_IIIV TYPE_I a, TYPE_I b, const TYPE_IV *c +#define VARS_IIIV VARS_III +#define LOGS_IIIV "%s %-8s %3d %3d %3d %3d\n", mode_desc(a), mode_desc(b), \ + c[0], c[1], c[2], c[3] +#define FILL_IIIV vv[0].i = a; vv[1].i = b; \ + vv[2].i = c[0]; vv[3].i = c[1]; \ + vv[4].i = c[2]; vv[5].i = c[3]; + +#define ARGS_IIFV TYPE_I a, TYPE_I b, const TYPE_F *c +#define VARS_IIFV VARS_III +#define LOGS_IIFV "%s %-8s %7.3f %7.3f %7.3f %7.3f\n", \ + mode_desc(a), mode_desc(b), \ + c[0], c[1], c[2], c[3] +#define FILL_IIFV vv[0].i = a; vv[1].i = b; \ + vv[2].f = c[0]; vv[3].f = c[1]; \ + vv[4].f = c[2]; vv[5].f = c[3]; + +#ifdef DEBUG +# define WLOG(NAME,ARGS) \ + fprintf (stderr, "jwzgles: direct %-12s ", NAME); \ + fprintf (stderr, ARGS) +#else +# define WLOG(NAME,ARGS) /* */ +#endif + +#define WRAP(NAME,SIG) \ +void jwzgles_##NAME (ARGS_##SIG) \ +{ \ + Assert (!state->compiling_verts, \ + STRINGIFY(NAME) " not allowed inside glBegin"); \ + if (state->compiling_list) { \ + void_int vv[10]; \ + FILL_##SIG \ + list_push (STRINGIFY(NAME), (list_fn_cb) &jwzgles_##NAME, \ + PROTO_##SIG, vv); \ + } else { \ + if (! state->replaying_list) { \ + WLOG (STRINGIFY(NAME), LOGS_##SIG); \ + } \ + NAME (VARS_##SIG); \ + CHECK(STRINGIFY(NAME)); \ + } \ +} + +WRAP (glActiveTexture, I) +WRAP (glAlphaFunc, IF) +WRAP (glBlendFunc, II) +WRAP (glClear, I) +WRAP (glClearColor, FFFF) +WRAP (glClearStencil, I) +WRAP (glColorMask, IIII) +WRAP (glCullFace, I) +WRAP (glDepthFunc, I) +WRAP (glDepthMask, I) +WRAP (glFinish, V) +WRAP (glFlush, V) +WRAP (glFogf, IF) +WRAP (glFogfv, IFV) +WRAP (glFrontFace, I) +WRAP (glHint, II) +WRAP (glLightModelf, IF) +WRAP (glLightModelfv, IFV) +WRAP (glLightf, IIF) +WRAP (glLightfv, IIFV) +WRAP (glLineWidth, F) +WRAP (glLoadIdentity, V) +WRAP (glLogicOp, I) +WRAP (glMatrixMode, I) +WRAP (glPixelStorei, II) +WRAP (glPointSize, F) +WRAP (glPolygonOffset, FF) +WRAP (glPopMatrix, V) +WRAP (glPushMatrix, V) +WRAP (glRotatef, FFFF) +WRAP (glScalef, FFF) +WRAP (glScissor, IIII) +WRAP (glShadeModel, I) +WRAP (glStencilFunc, III) +WRAP (glStencilMask, I) +WRAP (glStencilOp, III) +WRAP (glTexEnvf, IIF) +WRAP (glTexEnvi, III) +WRAP (glTranslatef, FFF) +WRAP (glViewport, IIII) +#undef TYPE_IV +#define TYPE_IV GLuint +WRAP (glDeleteTextures, IIV) + + +#endif /* HAVE_JWZGLES - whole file */ diff --git a/hacks/glx/jwzgles.h b/hacks/glx/jwzgles.h new file mode 100644 index 00000000..43b02c6c --- /dev/null +++ b/hacks/glx/jwzgles.h @@ -0,0 +1,519 @@ +/* xscreensaver, Copyright (c) 2012 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. + */ + +/* A compatibility shim to allow OpenGL 1.3 source code to work in an + OpenGLES environment, where almost every OpenGL 1.3 function has + been "deprecated". See jwzgles.c for details. + */ + +#ifndef __JWZGLES_H__ +#define __JWZGLES_H__ + +#ifndef HAVE_JWZGLES +# error: do not include this without HAVE_JWZGLES +#endif + + +#include "jwzglesI.h" + + +/* These are the OpenGL 1.3 functions that are not present in OpenGLES 1. + As you can see from the length of this list, OpenGL and OpenGLES have + almost nothing to do with each other. To claim that GLES is a dialect + of OpenGL is absurd -- English and Latin have more in common! + */ + +#define glAccum jwzgles_glAccum +#define glAntialiasing jwzgles_glAntialiasing +#define glAreTexturesResident jwzgles_glAreTexturesResident +#define glArrayElement jwzgles_glArrayElement +#define glBegin jwzgles_glBegin +#define glBitmap jwzgles_glBitmap +#define glBlendColor jwzgles_glBlendColor +#define glBlendEquation jwzgles_glBlendEquation +#define glCallList jwzgles_glCallList +#define glCallLists jwzgles_glCallLists +#define glClearAccum jwzgles_glClearAccum +#define glClearDepth jwzgles_glClearDepth +#define glClearIndex jwzgles_glClearIndex +#define glClipPlane jwzgles_glClipPlane +#define glColor3b jwzgles_glColor3b +#define glColor3bv jwzgles_glColor3bv +#define glColor3d jwzgles_glColor3f +#define glColor3dv jwzgles_glColor3dv +#define glColor3f jwzgles_glColor3f +#define glColor3fv jwzgles_glColor3fv +#define glColor3i jwzgles_glColor3i +#define glColor3iv jwzgles_glColor3iv +#define glColor3s jwzgles_glColor3s +#define glColor3sv jwzgles_glColor3sv +#define glColor3ub jwzgles_glColor3ub +#define glColor3ubv jwzgles_glColor3ubv +#define glColor3ui jwzgles_glColor3ui +#define glColor3uiv jwzgles_glColor3uiv +#define glColor3us jwzgles_glColor3us +#define glColor3usv jwzgles_glColor3usv +#define glColor4b jwzgles_glColor4b +#define glColor4bv jwzgles_glColor4bv +#define glColor4d jwzgles_glColor4d +#define glColor4dv jwzgles_glColor4dv +#define glColor4fv jwzgles_glColor4fv +#define glColor4i jwzgles_glColor4i +#define glColor4iv jwzgles_glColor4iv +#define glColor4s jwzgles_glColor4s +#define glColor4sv jwzgles_glColor4sv +#define glColor4ub jwzgles_glColor4ub +#define glColor4ubv jwzgles_glColor4ubv +#define glColor4ui jwzgles_glColor4ui +#define glColor4uiv jwzgles_glColor4uiv +#define glColor4us jwzgles_glColor4us +#define glColor4usv jwzgles_glColor4usv +#define glColorMaterial jwzgles_glColorMaterial +#define glColorSubTable jwzgles_glColorSubTable +#define glColorTable jwzgles_glColorTable +#define glColorTableParameter jwzgles_glColorTableParameter +#define glColorTableParameterfv jwzgles_glColorTableParameterfv +#define glColorub jwzgles_glColorub +#define glColorui jwzgles_glColorui +#define glColorus jwzgles_glColorus +#define glCompressedTexImage jwzgles_glCompressedTexImage +#define glCompressedTexImage1D jwzgles_glCompressedTexImage1D +#define glCompressedTexImage3D jwzgles_glCompressedTexImage3D +#define glCompressedTexSubImage1D jwzgles_glCompressedTexSubImage1D +#define glCompressedTexSubImage3D jwzgles_glCompressedTexSubImage3D +#define glConvolutionFilter1D jwzgles_glConvolutionFilter1D +#define glConvolutionFilter2D jwzgles_glConvolutionFilter2D +#define glConvolutionParameter jwzgles_glConvolutionParameter +#define glConvolutionParameterfv jwzgles_glConvolutionParameterfv +#define glConvolutionParameteriv jwzgles_glConvolutionParameteriv +#define glCopyColorSubTable jwzgles_glCopyColorSubTable +#define glCopyColorTable jwzgles_glCopyColorTable +#define glCopyConvolutionFilter1D jwzgles_glCopyConvolutionFilter1D +#define glCopyConvolutionFilter2D jwzgles_glCopyConvolutionFilter2D +#define glCopyPixels jwzgles_glCopyPixels +#define glCopyTexImage1D jwzgles_glCopyTexImage1D +#define glCopyTexImage3D jwzgles_glCopyTexImage3D +#define glCopyTexSubImage1D jwzgles_glCopyTexSubImage1D +#define glCopyTexSubImage3D jwzgles_glCopyTexSubImage3D +#define glDeleteLists jwzgles_glDeleteLists +#define glDepthRange jwzgles_glDepthRange +#define glDrawBuffer jwzgles_glDrawBuffer +#define glDrawPixels jwzgles_glDrawPixels +#define glDrawRangeElements jwzgles_glDrawRangeElements +#define glEdgeFlag jwzgles_glEdgeFlag +#define glEdgeFlagPointer jwzgles_glEdgeFlagPointer +#define glEdgeFlagv jwzgles_glEdgeFlagv +#define glEnd jwzgles_glEnd +#define glEndList jwzgles_glEndList +#define glEvalCoord1d jwzgles_glEvalCoord1d +#define glEvalCoord1dv jwzgles_glEvalCoord1dv +#define glEvalCoord1f jwzgles_glEvalCoord1f +#define glEvalCoord1fv jwzgles_glEvalCoord1fv +#define glEvalCoord2d jwzgles_glEvalCoord2d +#define glEvalCoord2dv jwzgles_glEvalCoord2dv +#define glEvalCoord2f jwzgles_glEvalCoord2f +#define glEvalCoord2fv jwzgles_glEvalCoord2fv +#define glEvalMesh1 jwzgles_glEvalMesh1 +#define glEvalMesh2 jwzgles_glEvalMesh2 +#define glEvalPoint1 jwzgles_glEvalPoint1 +#define glEvalPoint2 jwzgles_glEvalPoint2 +#define glFeedbackBuffer jwzgles_glFeedbackBuffer +#define glFogi jwzgles_glFogi +#define glFogiv jwzgles_glFogiv +#define glFrustum jwzgles_glFrustum +#define glGenLists jwzgles_glGenLists +#define glGet jwzgles_glGet +#define glGetBooleanv jwzgles_glGetBooleanv +#define glGetClipPlane jwzgles_glGetClipPlane +#define glGetColorTable jwzgles_glGetColorTable +#define glGetColorTableParameter jwzgles_glGetColorTableParameter +#define glGetCompressedTexImage jwzgles_glGetCompressedTexImage +#define glGetConvolutionFilter jwzgles_glGetConvolutionFilter +#define glGetConvolutionParameter jwzgles_glGetConvolutionParameter +#define glGetConvolutionParameteriv jwzgles_glGetConvolutionParameteriv +#define glGetDoublev jwzgles_glGetDoublev +#define glGetFloatv jwzgles_glGetFloatv +#define glGetHistogram jwzgles_glGetHistogram +#define glGetHistogramParameter jwzgles_glGetHistogramParameter +#define glGetLightfv jwzgles_glGetLightfv +#define glGetLightiv jwzgles_glGetLightiv +#define glGetMapdv jwzgles_glGetMapdv +#define glGetMapfv jwzgles_glGetMapfv +#define glGetMapiv jwzgles_glGetMapiv +#define glGetMaterialfv jwzgles_glGetMaterialfv +#define glGetMaterialiv jwzgles_glGetMaterialiv +#define glGetPixelMapfv jwzgles_glGetPixelMapfv +#define glGetPixelMapuiv jwzgles_glGetPixelMapuiv +#define glGetPixelMapusv jwzgles_glGetPixelMapusv +#define glGetPointerv jwzgles_glGetPointerv +#define glGetPolygonStipple jwzgles_glGetPolygonStipple +#define glGetSeparableFilter jwzgles_glGetSeparableFilter +#define glGetTexEnvfv jwzgles_glGetTexEnvfv +#define glGetTexEnviv jwzgles_glGetTexEnviv +#define glGetTexGendv jwzgles_glGetTexGendv +#define glGetTexGenfv jwzgles_glGetTexGenfv +#define glGetTexGeniv jwzgles_glGetTexGeniv +#define glGetTexImage jwzgles_glGetTexImage +#define glGetTexImage1D jwzgles_glGetTexImage1D +#define glGetTexImage2D jwzgles_glGetTexImage2D +#define glGetTexImage3D jwzgles_glGetTexImage3D +#define glGetTexLevelParameterfv jwzgles_glGetTexLevelParameterfv +#define glGetTexLevelParameteriv jwzgles_glGetTexLevelParameteriv +#define glGetTexParameterfv jwzgles_glGetTexParameterfv +#define glGetTexParameteriv jwzgles_glGetTexParameteriv +#define glHistogram jwzgles_glHistogram +#define glIndex jwzgles_glIndex +#define glIndexMask jwzgles_glIndexMask +#define glIndexPointer jwzgles_glIndexPointer +#define glIndexd jwzgles_glIndexd +#define glIndexdv jwzgles_glIndexdv +#define glIndexf jwzgles_glIndexf +#define glIndexfv jwzgles_glIndexfv +/*#define glIndexi jwzgles_glIndexi*/ +#define glIndexiv jwzgles_glIndexiv +#define glIndexs jwzgles_glIndexs +#define glIndexsv jwzgles_glIndexsv +#define glIndexub jwzgles_glIndexub +#define glIndexubv jwzgles_glIndexubv +#define glInitNames jwzgles_glInitNames +#define glInterleavedArrays jwzgles_glInterleavedArrays +#define glIsEnabled jwzgles_glIsEnabled +#define glIsList jwzgles_glIsList +#define glIsTexture jwzgles_glIsTexture +#define glLightModeli jwzgles_glLightModeli +#define glLightModeliv jwzgles_glLightModeliv +#define glLighti jwzgles_glLighti +#define glLightiv jwzgles_glLightiv +#define glLightf jwzgles_glLightf +#define glLightfv jwzgles_glLightfv +#define glLineStipple jwzgles_glLineStipple +#define glListBase jwzgles_glListBase +#define glLoadMatrix jwzgles_glLoadMatrix +#define glLoadMatrixd jwzgles_glLoadMatrixd +#define glLoadName jwzgles_glLoadName +#define glLoadTransposeMatrix jwzgles_glLoadTransposeMatrix +#define glLoadTransposeMatrixd jwzgles_glLoadTransposeMatrixd +#define glLoadTransposeMatrixf jwzgles_glLoadTransposeMatrixf +#define glMap1d jwzgles_glMap1d +#define glMap1f jwzgles_glMap1f +#define glMap2d jwzgles_glMap2d +#define glMap2f jwzgles_glMap2f +#define glMapGrid1d jwzgles_glMapGrid1d +#define glMapGrid1f jwzgles_glMapGrid1f +#define glMapGrid2d jwzgles_glMapGrid2d +#define glMapGrid2f jwzgles_glMapGrid2f +#define glMateriali jwzgles_glMateriali +#define glMaterialiv jwzgles_glMaterialiv +#define glMultMatrixd jwzgles_glMultMatrixd +#define glMultTransposeMatrix jwzgles_glMultTransposeMatrix +#define glMultTransposeMatrixd jwzgles_glMultTransposeMatrixd +#define glMultTransposeMatrixf jwzgles_glMultTransposeMatrixf +#define glMultiTexCoord jwzgles_glMultiTexCoord +#define glNewList jwzgles_glNewList +#define glNormal3b jwzgles_glNormal3b +#define glNormal3bv jwzgles_glNormal3bv +#define glNormal3d jwzgles_glNormal3f +#define glNormal3dv jwzgles_glNormal3dv +#define glNormal3fv jwzgles_glNormal3fv +#define glNormal3i jwzgles_glNormal3i +#define glNormal3iv jwzgles_glNormal3iv +#define glNormal3s jwzgles_glNormal3s +#define glNormal3sv jwzgles_glNormal3sv +#define glOrtho jwzgles_glOrtho +#define glPassThrough jwzgles_glPassThrough +#define glPixelMapfv jwzgles_glPixelMapfv +#define glPixelMapuiv jwzgles_glPixelMapuiv +#define glPixelMapusv jwzgles_glPixelMapusv +#define glPixelStoref jwzgles_glPixelStoref +#define glPixelTransferf jwzgles_glPixelTransferf +#define glPixelTransferi jwzgles_glPixelTransferi +#define glPixelZoom jwzgles_glPixelZoom +#define glPolygonMode jwzgles_glPolygonMode +#define glPolygonStipple jwzgles_glPolygonStipple +#define glPopAttrib jwzgles_glPopAttrib +#define glPopClientAttrib jwzgles_glPopClientAttrib +#define glPopName jwzgles_glPopName +#define glPrioritizeTextures jwzgles_glPrioritizeTextures +#define glPushAttrib jwzgles_glPushAttrib +#define glPushClientAttrib jwzgles_glPushClientAttrib +#define glPushName jwzgles_glPushName +#define glRasterPos2d jwzgles_glRasterPos2d +#define glRasterPos2dv jwzgles_glRasterPos2dv +#define glRasterPos2f jwzgles_glRasterPos2f +#define glRasterPos2fv jwzgles_glRasterPos2fv +#define glRasterPos2i jwzgles_glRasterPos2i +#define glRasterPos2iv jwzgles_glRasterPos2iv +#define glRasterPos2s jwzgles_glRasterPos2s +#define glRasterPos2sv jwzgles_glRasterPos2sv +#define glRasterPos3d jwzgles_glRasterPos3d +#define glRasterPos3dv jwzgles_glRasterPos3dv +#define glRasterPos3f jwzgles_glRasterPos3f +#define glRasterPos3fv jwzgles_glRasterPos3fv +#define glRasterPos3i jwzgles_glRasterPos3i +#define glRasterPos3iv jwzgles_glRasterPos3iv +#define glRasterPos3s jwzgles_glRasterPos3s +#define glRasterPos3sv jwzgles_glRasterPos3sv +#define glRasterPos4d jwzgles_glRasterPos4d +#define glRasterPos4dv jwzgles_glRasterPos4dv +#define glRasterPos4f jwzgles_glRasterPos4f +#define glRasterPos4fv jwzgles_glRasterPos4fv +#define glRasterPos4i jwzgles_glRasterPos4i +#define glRasterPos4iv jwzgles_glRasterPos4iv +#define glRasterPos4s jwzgles_glRasterPos4s +#define glRasterPos4sv jwzgles_glRasterPos4sv +#define glReadBuffer jwzgles_glReadBuffer +#define glRectd jwzgles_glRectf +#define glRectdv jwzgles_glRectdv +#define glRectf jwzgles_glRectf +#define glRectfv jwzgles_glRectfv +#define glRecti jwzgles_glRecti +#define glRectiv jwzgles_glRectiv +#define glRects jwzgles_glRects +#define glRectsv jwzgles_glRectsv +#define glRenderMode jwzgles_glRenderMode +#define glResetHistogram jwzgles_glResetHistogram +#define glResetMinmax jwzgles_glResetMinmax +#define glRotated jwzgles_glRotated +#define glScaled jwzgles_glScalef +#define glSelectBuffer jwzgles_glSelectBuffer +#define glSeparableFilter2D jwzgles_glSeparableFilter2D +#define glTexCoord1d jwzgles_glTexCoord1d +#define glTexCoord1dv jwzgles_glTexCoord1dv +#define glTexCoord1f jwzgles_glTexCoord1f +#define glTexCoord1fv jwzgles_glTexCoord1fv +#define glTexCoord1i jwzgles_glTexCoord1i +#define glTexCoord1iv jwzgles_glTexCoord1iv +#define glTexCoord1s jwzgles_glTexCoord1s +#define glTexCoord1sv jwzgles_glTexCoord1sv +#define glTexCoord2d jwzgles_glTexCoord2f +#define glTexCoord2dv jwzgles_glTexCoord2dv +#define glTexCoord2f jwzgles_glTexCoord2f +#define glTexCoord2fv jwzgles_glTexCoord2fv +#define glTexCoord2i jwzgles_glTexCoord2i +#define glTexCoord2iv jwzgles_glTexCoord2iv +#define glTexCoord2s jwzgles_glTexCoord2s +#define glTexCoord2sv jwzgles_glTexCoord2sv +#define glTexCoord3d jwzgles_glTexCoord3d +#define glTexCoord3dv jwzgles_glTexCoord3dv +#define glTexCoord3f jwzgles_glTexCoord3f +#define glTexCoord3fv jwzgles_glTexCoord3fv +#define glTexCoord3i jwzgles_glTexCoord3i +#define glTexCoord3iv jwzgles_glTexCoord3iv +#define glTexCoord3s jwzgles_glTexCoord3s +#define glTexCoord3sv jwzgles_glTexCoord3sv +#define glTexCoord4d jwzgles_glTexCoord4d +#define glTexCoord4dv jwzgles_glTexCoord4dv +#define glTexCoord4f jwzgles_glTexCoord4f +#define glTexCoord4fv jwzgles_glTexCoord4fv +#define glTexCoord4i jwzgles_glTexCoord4i +#define glTexCoord4iv jwzgles_glTexCoord4iv +#define glTexCoord4s jwzgles_glTexCoord4s +#define glTexCoord4sv jwzgles_glTexCoord4sv +#define glTexEnvi jwzgles_glTexEnvi +#define glTexEnviv jwzgles_glTexEnviv +#define glTexGend jwzgles_glTexGend +#define glTexGendv jwzgles_glTexGendv +#define glTexGenf jwzgles_glTexGenf +#define glTexGenfv jwzgles_glTexGenfv +#define glTexGeni jwzgles_glTexGeni +#define glTexGeniv jwzgles_glTexGeniv +#define glTexImage1D jwzgles_glTexImage1D +#define glTexImage3D jwzgles_glTexImage3D +#define glTexParameterfv jwzgles_glTexParameterfv +#define glTexParameteri jwzgles_glTexParameteri +#define glTexParameteriv jwzgles_glTexParameteriv +#define glTexSubImage1D jwzgles_glTexSubImage1D +#define glTexSubImage3D jwzgles_glTexSubImage3D +#define glTranslated jwzgles_glTranslatef +#define glVertex2d jwzgles_glVertex2d +#define glVertex2dv jwzgles_glVertex2dv +#define glVertex2f jwzgles_glVertex2f +#define glVertex2fv jwzgles_glVertex2fv +#define glVertex2i jwzgles_glVertex2i +#define glVertex2iv jwzgles_glVertex2iv +#define glVertex2s jwzgles_glVertex2s +#define glVertex2sv jwzgles_glVertex2sv +#define glVertex3d jwzgles_glVertex3f +#define glVertex3dv jwzgles_glVertex3dv +#define glVertex3f jwzgles_glVertex3f +#define glVertex3fv jwzgles_glVertex3fv +#define glVertex3i jwzgles_glVertex3i +#define glVertex3iv jwzgles_glVertex3iv +#define glVertex3s jwzgles_glVertex3s +#define glVertex3sv jwzgles_glVertex3sv +#define glVertex4d jwzgles_glVertex4d +#define glVertex4dv jwzgles_glVertex4dv +#define glVertex4f jwzgles_glVertex4f +#define glVertex4fv jwzgles_glVertex4fv +#define glVertex4i jwzgles_glVertex4i +#define glVertex4iv jwzgles_glVertex4iv +#define glVertex4s jwzgles_glVertex4s +#define glVertex4sv jwzgles_glVertex4sv + +#define gluOrtho2D(L,R,B,T) glOrtho(L,R,B,T,-1,1) +#define gluPerspective jwzgles_gluPerspective + +#define glXChooseVisual jwzgles_glXChooseVisual +#define glXCopyContext jwzgles_glXCopyContext +/*#define glXCreateContext jwzgles_glXCreateContext*/ +#define glXCreateGLXPixmap jwzgles_glXCreateGLXPixmap +#define glXDestroyContext jwzgles_glXDestroyContext +#define glXDestroyGLXPixmap jwzgles_glXDestroyGLXPixmap +#define glXFreeContextEXT jwzgles_glXFreeContextEXT +#define glXGetClientString jwzgles_glXGetClientString +#define glXGetConfig jwzgles_glXGetConfig +#define glXGetContextIDEXT jwzgles_glXGetContextIDEXT +#define glXGetCurrentContext jwzgles_glXGetCurrentContext +#define glXGetCurrentDisplay jwzgles_glXGetCurrentDisplay +#define glXGetCurrentDrawable jwzgles_glXGetCurrentDrawable +#define glXImportContextEXT jwzgles_glXImportContextEXT +#define glXIntro jwzgles_glXIntro +#define glXIsDirect jwzgles_glXIsDirect +/*#define glXMakeCurrent jwzgles_glXMakeCurrent*/ +#define glXQueryContextInfoEXT jwzgles_glXQueryContextInfoEXT +#define glXQueryExtension jwzgles_glXQueryExtension +#define glXQueryExtensionsString jwzgles_glXQueryExtensionsString +#define glXQueryServerString jwzgles_glXQueryServerString +#define glXQueryVersion jwzgles_glXQueryVersion +/*#define glXSwapBuffers jwzgles_glXSwapBuffers*/ +#define glXUseXFont jwzgles_glXUseXFont +#define glXWaitGL jwzgles_glXWaitGL +#define glXWaitX jwzgles_glXWaitX + +#define gluBeginCurve jwzgles_gluBeginCurve +#define gluBeginPolygon jwzgles_gluBeginPolygon +#define gluBeginSurface jwzgles_gluBeginSurface +#define gluBeginTrim jwzgles_gluBeginTrim +#define gluBuild1DMipmaps jwzgles_gluBuild1DMipmaps +#define gluBuild2DMipmaps jwzgles_gluBuild2DMipmaps +#define gluCylinder jwzgles_gluCylinder +#define gluDeleteNurbsRenderer jwzgles_gluDeleteNurbsRenderer +#define gluDeleteQuadric jwzgles_gluDeleteQuadric +#define gluDeleteTess jwzgles_gluDeleteTess +#define gluDisk jwzgles_gluDisk +#define gluEndCurve jwzgles_gluEndCurve +#define gluEndPolygon jwzgles_gluEndPolygon +#define gluEndSurface jwzgles_gluEndSurface +#define gluEndTrim jwzgles_gluEndTrim +#define gluErrorString jwzgles_gluErrorString +#define gluGetNurbsProperty jwzgles_gluGetNurbsProperty +#define gluGetString jwzgles_gluGetString +#define gluGetTessProperty jwzgles_gluGetTessProperty +#define gluLoadSamplingMatrices jwzgles_gluLoadSamplingMatrices +#define gluLookAt jwzgles_gluLookAt +#define gluNewNurbsRenderer jwzgles_gluNewNurbsRenderer +#define gluNewQuadric jwzgles_gluNewQuadric +#define gluNewTess jwzgles_gluNewTess +#define gluNextContour jwzgles_gluNextContour +#define gluNurbsCallback jwzgles_gluNurbsCallback +#define gluNurbsCurve jwzgles_gluNurbsCurve +#define gluNurbsProperty jwzgles_gluNurbsProperty +#define gluNurbsSurface jwzgles_gluNurbsSurface +#define gluPartialDisk jwzgles_gluPartialDisk +#define gluPickMatrix jwzgles_gluPickMatrix +#define gluProject jwzgles_gluProject +#define gluPwlCurve jwzgles_gluPwlCurve +#define gluQuadricCallback jwzgles_gluQuadricCallback +#define gluQuadricDrawStyle jwzgles_gluQuadricDrawStyle +#define gluQuadricNormals jwzgles_gluQuadricNormals +#define gluQuadricOrientation jwzgles_gluQuadricOrientation +#define gluQuadricTexture jwzgles_gluQuadricTexture +#define gluScaleImage jwzgles_gluScaleImage +#define gluSphere jwzgles_gluSphere +#define gluTessBeginContour jwzgles_gluTessBeginContour +#define gluTessBeginPolygon jwzgles_gluTessBeginPolygon +#define gluTessCallback jwzgles_gluTessCallback +#define gluTessEndPolygon jwzgles_gluTessEndPolygon +#define gluTessEndContour jwzgles_gluTessEndContour +#define gluTessNormal jwzgles_gluTessNormal +#define gluTessProperty jwzgles_gluTessProperty +#define gluTessVertex jwzgles_gluTessVertex +#define gluUnProject jwzgles_gluUnProject + + +/* These functions are present in both OpenGL 1.1 and in OpenGLES 1, + but are allowed within glNewList/glEndList, so we must wrap them + to allow them to be recorded. + */ +#define glActiveTexture jwzgles_glActiveTexture +#define glAlphaFunc jwzgles_glAlphaFunc +#define glBindTexture jwzgles_glBindTexture +#define glBlendFunc jwzgles_glBlendFunc +#define glClear jwzgles_glClear +#define glClearColor jwzgles_glClearColor +#define glClearStencil jwzgles_glClearStencil +#define glColor4f jwzgles_glColor4f +#define glColorMask jwzgles_glColorMask +#define glColorPointer jwzgles_glColorPointer +#define glCompressedTexImage2D jwzgles_glCompressedTexImage2D +#define glCompressedTexSubImage2D jwzgles_glCompressedTexSubImage2D +#define glCopyTexImage2D jwzgles_glCopyTexImage2D +#define glCopyTexSubImage2D jwzgles_glCopyTexSubImage2D +#define glCullFace jwzgles_glCullFace +#define glDeleteTextures jwzgles_glDeleteTextures +#define glDepthFunc jwzgles_glDepthFunc +#define glDepthMask jwzgles_glDepthMask +#define glDisable jwzgles_glDisable +#define glDrawArrays jwzgles_glDrawArrays +#define glDrawElements jwzgles_glDrawElements +#define glEnable jwzgles_glEnable +#define glFinish jwzgles_glFinish +#define glFlush jwzgles_glFlush +#define glFogf jwzgles_glFogf +#define glFogfv jwzgles_glFogfv +#define glFrontFace jwzgles_glFrontFace +#define glGenTextures jwzgles_glGenTextures +#define glGetIntegerv jwzgles_glGetIntegerv +#define glHint jwzgles_glHint +#define glLightModelf jwzgles_glLightModelf +#define glLightModelfv jwzgles_glLightModelfv +#define glLightf jwzgles_glLightf +#define glLightfv jwzgles_glLightfv +#define glLineWidth jwzgles_glLineWidth +#define glLoadIdentity jwzgles_glLoadIdentity +#define glLoadMatrixf jwzgles_glLoadMatrixf +#define glLogicOp jwzgles_glLogicOp +#define glMaterialf jwzgles_glMaterialf +#define glMateriali jwzgles_glMateriali +#define glMaterialfv jwzgles_glMaterialfv +#define glMaterialiv jwzgles_glMaterialiv +#define glMatrixMode jwzgles_glMatrixMode +#define glMultMatrixf jwzgles_glMultMatrixf +#define glNormal3f jwzgles_glNormal3f +#define glNormalPointer jwzgles_glNormalPointer +#define glPixelStorei jwzgles_glPixelStorei +#define glPointSize jwzgles_glPointSize +#define glPolygonOffset jwzgles_glPolygonOffset +#define glPopMatrix jwzgles_glPopMatrix +#define glPushMatrix jwzgles_glPushMatrix +#define glReadPixels jwzgles_glReadPixels +#define glRotatef jwzgles_glRotatef +#define glScalef jwzgles_glScalef +#define glSampleCoverage jwzgles_glSampleCoverage +#define glScissor jwzgles_glScissor +#define glShadeModel jwzgles_glShadeModel +#define glStencilFunc jwzgles_glStencilFunc +#define glStencilMask jwzgles_glStencilMask +#define glStencilOp jwzgles_glStencilOp +#define glTexCoordPointer jwzgles_glTexCoordPointer +#define glTexEnvf jwzgles_glTexEnvf +#define glTexEnvfv jwzgles_glTexEnvfv +#define glTexImage2D jwzgles_glTexImage2D +#define glTexParameterf jwzgles_glTexParameterf +#define glTexSubImage2D jwzgles_glTexSubImage2D +#define glTranslatef jwzgles_glTranslatef +#define glVertexPointer jwzgles_glVertexPointer +#define glViewport jwzgles_glViewport +#define glEnableClientState jwzgles_glEnableClientState +#define glDisableClientState jwzgles_glDisableClientState +#define glClipPlane jwzgles_glClipPlane + +#endif /* __JWZGLES_H__ */ diff --git a/hacks/glx/jwzglesI.h b/hacks/glx/jwzglesI.h new file mode 100644 index 00000000..faa26efd --- /dev/null +++ b/hacks/glx/jwzglesI.h @@ -0,0 +1,313 @@ +/* xscreensaver, Copyright (c) 2012 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. + */ + +/* A compatibility shim to allow OpenGL 1.3 source code to work in an + OpenGLES environment, where almost every OpenGL 1.3 function has + been "deprecated". See jwzgles.c for details. + */ + +#ifndef __JWZGLES_I_H__ +#define __JWZGLES_I_H__ + +#ifdef GL_VERSION_ES_CM_1_0 /* compiling against OpenGLES 1.x */ + +/* These OpenGL 1.3 constants are not present in OpenGLES 1. + Fortunately, it looks like they didn't re-use any of the numbers, + so we can just keep using the OpenGL 1.3 values. I'm actually + kind of shocked that the GLES folks passed up that opportunity + for further clusterfuckery. + */ +# define GLdouble double + +# define GL_ACCUM_BUFFER_BIT 0x00000200 +# define GL_ALL_ATTRIB_BITS 0x000FFFFF +# define GL_AUTO_NORMAL 0x0D80 +# define GL_BLEND_SRC_ALPHA 0x80CB +# define GL_C3F_V3F 0x2A24 +# define GL_C4F_N3F_V3F 0x2A26 +# define GL_C4UB_V2F 0x2A22 +# define GL_C4UB_V3F 0x2A23 +# define GL_CLAMP 0x2900 +# define GL_COLOR_BUFFER_BIT 0x00004000 +# define GL_COLOR_MATERIAL_FACE 0x0B55 +# define GL_COLOR_MATERIAL_PARAMETER 0x0B56 +# define GL_COMPILE 0x1300 +# define GL_CURRENT_BIT 0x00000001 +# define GL_DEPTH_BUFFER_BIT 0x00000100 +# define GL_DOUBLEBUFFER 0x0C32 +# define GL_ENABLE_BIT 0x00002000 +# define GL_EVAL_BIT 0x00010000 +# define GL_EYE_LINEAR 0x2400 +# define GL_EYE_PLANE 0x2502 +# define GL_FEEDBACK 0x1C01 +# define GL_FILL 0x1B02 +# define GL_FOG_BIT 0x00000080 +# define GL_HINT_BIT 0x00008000 +# define GL_INTENSITY 0x8049 +# define GL_LIGHTING_BIT 0x00000040 +# define GL_LIGHT_MODEL_COLOR_CONTROL 0x81F8 +# define GL_LIGHT_MODEL_LOCAL_VIEWER 0x0B51 +# define GL_LINE 0x1B01 +# define GL_LINE_BIT 0x00000004 +# define GL_LIST_BIT 0x00020000 +# define GL_N3F_V3F 0x2A25 +# define GL_OBJECT_LINEAR 0x2401 +# define GL_OBJECT_PLANE 0x2501 +# define GL_PIXEL_MODE_BIT 0x00000020 +# define GL_POINT_BIT 0x00000002 +# define GL_POLYGON 0x0009 +# define GL_POLYGON_BIT 0x00000008 +# define GL_POLYGON_MODE 0x0B40 +# define GL_POLYGON_SMOOTH 0x0B41 +# define GL_POLYGON_STIPPLE 0x0B42 +# define GL_POLYGON_STIPPLE_BIT 0x00000010 +# define GL_Q 0x2003 +# define GL_QUADS 0x0007 +# define GL_QUAD_STRIP 0x0008 +# define GL_R 0x2002 +# define GL_RENDER 0x1C00 +# define GL_RGBA_MODE 0x0C31 +# define GL_S 0x2000 +# define GL_SCISSOR_BIT 0x00080000 +# define GL_SELECT 0x1C02 +# define GL_SEPARATE_SPECULAR_COLOR 0x81FA +# define GL_SINGLE_COLOR 0x81F9 +# define GL_SPHERE_MAP 0x2402 +# define GL_STENCIL_BUFFER_BIT 0x00000400 +# define GL_T 0x2001 +# define GL_T2F_C3F_V3F 0x2A2A +# define GL_T2F_C4F_N3F_V3F 0x2A2C +# define GL_T2F_C4UB_V3F 0x2A29 +# define GL_T2F_N3F_V3F 0x2A2B +# define GL_T2F_V3F 0x2A27 +# define GL_T4F_C4F_N3F_V4F 0x2A2D +# define GL_T4F_V4F 0x2A28 +# define GL_TEXTURE_1D 0x0DE0 +# define GL_TEXTURE_ALPHA_SIZE 0x805F +# define GL_TEXTURE_BIT 0x00040000 +# define GL_TEXTURE_BLUE_SIZE 0x805E +# define GL_TEXTURE_BORDER 0x1005 +# define GL_TEXTURE_BORDER_COLOR 0x1004 +# define GL_TEXTURE_COMPONENTS 0x1003 +# define GL_TEXTURE_GEN_MODE 0x2500 +# define GL_TEXTURE_GEN_Q 0x0C63 +# define GL_TEXTURE_GEN_R 0x0C62 +# define GL_TEXTURE_GEN_S 0x0C60 +# define GL_TEXTURE_GEN_T 0x0C61 +# define GL_TEXTURE_GREEN_SIZE 0x805D +# define GL_TEXTURE_HEIGHT 0x1001 +# define GL_TEXTURE_INTENSITY_SIZE 0x8061 +# define GL_TEXTURE_LUMINANCE_SIZE 0x8060 +# define GL_TEXTURE_RED_SIZE 0x805C +# define GL_TEXTURE_WIDTH 0x1000 +# define GL_TRANSFORM_BIT 0x00001000 +# define GL_UNPACK_ROW_LENGTH 0x0CF2 +# define GL_UNSIGNED_INT_8_8_8_8_REV 0x8367 +# define GL_V2F 0x2A20 +# define GL_V3F 0x2A21 +# define GL_VIEWPORT_BIT 0x00000800 + +#endif + + +/* Prototypes for the things re-implemented in jwzgles.c + */ + +extern int jwzgles_glGenLists (int n); +extern void jwzgles_glNewList (int id, int mode); +extern void jwzgles_glEndList (void); +extern void jwzgles_glDeleteLists (int list, int range); +extern void jwzgles_glBegin (int mode); +extern void jwzgles_glNormal3fv (const GLfloat *); +extern void jwzgles_glNormal3f (GLfloat x, GLfloat y, GLfloat z); +extern void jwzgles_glTexCoord1f (GLfloat s); +extern void jwzgles_glTexCoord2fv (const GLfloat *); +extern void jwzgles_glTexCoord2f (GLfloat s, GLfloat t); +extern void jwzgles_glTexCoord3fv (const GLfloat *); +extern void jwzgles_glTexCoord3f (GLfloat s, GLfloat t, GLfloat r); +extern void jwzgles_glTexCoord4fv (const GLfloat *); +extern void jwzgles_glTexCoord4f (GLfloat s, GLfloat t, GLfloat r, GLfloat q); +extern void jwzgles_glVertex2f (GLfloat x, GLfloat y); +extern void jwzgles_glVertex2fv (const GLfloat *); +extern void jwzgles_glVertex2i (GLint x, GLint y); +extern void jwzgles_glVertex3f (GLfloat x, GLfloat y, GLfloat z); +extern void jwzgles_glVertex3dv (const GLdouble *); +extern void jwzgles_glVertex3fv (const GLfloat *); +extern void jwzgles_glVertex3i (GLint x, GLint y, GLint z); +extern void jwzgles_glVertex4f (GLfloat x, GLfloat y, GLfloat z, GLfloat w); +extern void jwzgles_glVertex4fv (const GLfloat *); +extern void jwzgles_glVertex4i (GLint x, GLint y, GLint z, GLint w); +extern void jwzgles_glEnd (void); +extern void jwzgles_glCallList (int id); +extern void jwzgles_glClearIndex(GLfloat c); +extern void jwzgles_glBitmap (GLsizei, GLsizei, GLfloat, GLfloat, GLfloat, + GLfloat, const GLubyte *); +extern void jwzgles_glPushAttrib(int); +extern void jwzgles_glPopAttrib(void); + + +/* These functions are present in both OpenGL 1.3 and in OpenGLES 1, + but are allowed within glNewList/glEndList, so we must wrap them + to allow them to be recorded. + */ +extern void jwzgles_glActiveTexture (GLuint); +extern void jwzgles_glBindTexture (GLuint, GLuint); +extern void jwzgles_glBlendFunc (GLuint, GLuint); +extern void jwzgles_glClear (GLuint); +extern void jwzgles_glClearColor (GLclampf, GLclampf, GLclampf, GLclampf); +extern void jwzgles_glClearStencil (GLuint); +extern void jwzgles_glColorMask (GLuint, GLuint, GLuint, GLuint); +extern void jwzgles_glCullFace (GLuint); +extern void jwzgles_glDepthFunc (GLuint); +extern void jwzgles_glDepthMask (GLuint); +extern void jwzgles_glDisable (GLuint); +extern void jwzgles_glDrawArrays (GLuint, GLuint, GLuint); +extern GLboolean jwzgles_glIsEnabled (GLuint); +extern void jwzgles_glEnable (GLuint); +extern void jwzgles_glFrontFace (GLuint); +extern void jwzgles_glHint (GLuint, GLuint); +extern void jwzgles_glLineWidth (GLfloat); +extern void jwzgles_glLoadIdentity (void); +extern void jwzgles_glLogicOp (GLuint); +extern void jwzgles_glMatrixMode (GLuint); +extern void jwzgles_glMultMatrixf (const GLfloat *); +extern void jwzgles_glPointSize (GLfloat); +extern void jwzgles_glPolygonOffset (GLfloat, GLfloat); +extern void jwzgles_glPopMatrix (void); +extern void jwzgles_glPushMatrix (void); +extern void jwzgles_glScissor (GLuint, GLuint, GLuint, GLuint); +extern void jwzgles_glShadeModel (GLuint); +extern void jwzgles_glStencilFunc (GLuint, GLuint, GLuint); +extern void jwzgles_glStencilMask (GLuint); +extern void jwzgles_glStencilOp (GLuint, GLuint, GLuint); +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_glScalef (GLfloat, GLfloat, GLfloat); +extern void jwzgles_glColor3f (GLfloat, GLfloat, GLfloat); +extern void jwzgles_glColor4f (GLfloat, GLfloat, GLfloat, GLfloat); +extern void jwzgles_glColor3fv (const GLfloat *); +extern void jwzgles_glColor4fv (const GLfloat *); +extern void jwzgles_glColor4i (GLuint, GLuint, GLuint, GLuint); +extern void jwzgles_glColor3i (GLuint, GLuint, GLuint); +extern void jwzgles_glColor3iv (const GLint *); +extern void jwzgles_glColor4iv (const GLint *); +extern void jwzgles_glColor4ub (GLubyte, GLubyte, GLubyte, GLubyte); +extern void jwzgles_glColor3ub (GLubyte, GLubyte, GLubyte); +extern void jwzgles_glMaterialf (GLuint, GLuint, GLfloat); +extern void jwzgles_glMateriali (GLuint, GLuint, GLuint); +extern void jwzgles_glMaterialfv (GLuint, GLuint, const GLfloat *); +extern void jwzgles_glMaterialiv (GLuint, GLuint, const GLint *); +extern void jwzgles_glFinish (void); +extern void jwzgles_glFlush (void); +extern void jwzgles_glPixelStorei (GLuint, GLuint); +extern void jwzgles_glEnableClientState (GLuint); +extern void jwzgles_glDisableClientState (GLuint); + +extern void jwzgles_glInitNames (void); +extern void jwzgles_glPushName (GLuint); +extern GLuint jwzgles_glPopName (void); +extern GLuint jwzgles_glRenderMode (GLuint); +extern void jwzgles_glSelectBuffer (GLsizei, GLuint *); +extern void jwzgles_glLightf (GLenum, GLenum, GLfloat); +extern void jwzgles_glLighti (GLenum, GLenum, GLint); +extern void jwzgles_glLightfv (GLenum, GLenum, const GLfloat *); +extern void jwzgles_glLightiv (GLenum, GLenum, const GLint *); +extern void jwzgles_glLightModelf (GLenum, GLfloat); +extern void jwzgles_glLightModeli (GLenum, GLint); +extern void jwzgles_glLightModelfv (GLenum, const GLfloat *); +extern void jwzgles_glLightModeliv (GLenum, const GLint *); +extern void jwzgles_glGenTextures (GLuint, GLuint *); +extern void jwzgles_glFrustum (GLfloat, GLfloat, GLfloat, GLfloat, + GLfloat, GLfloat); +extern void jwzgles_glOrtho (GLfloat, GLfloat, GLfloat, GLfloat, + GLfloat, GLfloat); +extern void jwzgles_glTexImage1D (GLenum target, GLint level, + GLint internalFormat, + GLsizei width, GLint border, + GLenum format, GLenum type, + const GLvoid *pixels); +extern void jwzgles_glTexImage2D (GLenum target, + GLint level, + GLint internalFormat, + GLsizei width, + GLsizei height, + GLint border, + GLenum format, + GLenum type, + const GLvoid *data); +extern void jwzgles_glTexSubImage2D (GLenum target, GLint level, + GLint xoffset, GLint yoffset, + GLsizei width, GLsizei height, + GLenum format, GLenum type, + const GLvoid *pixels); +extern void jwzgles_glCopyTexImage2D (GLenum target, GLint level, + GLenum internalformat, + GLint x, GLint y, + GLsizei width, GLsizei height, + GLint border); +extern void jwzgles_glInterleavedArrays (GLenum, GLsizei, const GLvoid *); +extern void jwzgles_glTexEnvf (GLuint, GLuint, GLfloat); +extern void jwzgles_glTexEnvi (GLuint, GLuint, GLuint); +extern void jwzgles_glTexParameterf (GLuint, GLuint, GLfloat); +extern void jwzgles_glTexParameteri (GLuint, GLuint, GLuint); +extern void jwzgles_glTexGeni (GLenum, GLenum, GLint); +extern void jwzgles_glTexGenfv (GLenum, GLenum, const GLfloat *); +extern void jwzgles_glRectf (GLfloat, GLfloat, GLfloat, GLfloat); +extern void jwzgles_glRecti (GLint, GLint, GLint, GLint); +extern void jwzgles_glLightModelfv (GLenum, const GLfloat *); +extern void jwzgles_glClearDepth (GLfloat); +extern GLboolean jwzgles_glIsList (GLuint); +extern void jwzgles_glColorMaterial (GLenum, GLenum); +extern void jwzgles_glPolygonMode (GLenum, GLenum); +extern void jwzgles_glFogf (GLenum, GLfloat); +extern void jwzgles_glFogi (GLenum, GLint); +extern void jwzgles_glFogfv (GLenum, const GLfloat *); +extern void jwzgles_glFogiv (GLenum, const GLint *); +extern void jwzgles_glAlphaFunc (GLenum, GLfloat); +extern void jwzgles_glClipPlane (GLenum, const GLdouble *); +extern void jwzgles_glDrawBuffer (GLenum); +extern void jwzgles_glDeleteTextures (GLuint, const GLuint *); + +extern void jwzgles_gluPerspective (GLdouble fovy, GLdouble aspect, + GLdouble near, GLdouble far); +extern void jwzgles_gluLookAt (GLfloat eyex, GLfloat eyey, GLfloat eyez, + GLfloat centerx, GLfloat centery, + GLfloat centerz, + GLfloat upx, GLfloat upy, GLfloat upz); +extern GLint jwzgles_gluProject (GLdouble objx, GLdouble objy, GLdouble objz, + const GLdouble modelMatrix[16], + const GLdouble projMatrix[16], + const GLint viewport[4], + GLdouble *winx, GLdouble *winy, + GLdouble *winz); +extern int jwzgles_gluBuild2DMipmaps (GLenum target, + GLint internalFormat, + GLsizei width, + GLsizei height, + GLenum format, + GLenum type, + const GLvoid *data); +extern void jwzgles_glGetFloatv (GLenum pname, GLfloat *params); +extern void jwzgles_glGetPointerv (GLenum pname, GLvoid *params); +extern void jwzgles_glGetDoublev (GLenum pname, GLdouble *params); +extern void jwzgles_glGetIntegerv (GLenum pname, GLint *params); +extern void jwzgles_glGetBooleanv (GLenum pname, GLboolean *params); +extern void jwzgles_glVertexPointer (GLuint, GLuint, GLuint, const void *); +extern void jwzgles_glNormalPointer (GLenum, GLuint, const void *); +extern void jwzgles_glColorPointer (GLuint, GLuint, GLuint, const void *); +extern void jwzgles_glTexCoordPointer (GLuint, GLuint, GLuint, const void *); +extern void jwzgles_glBindBuffer (GLuint, GLuint); +extern void jwzgles_glBufferData (GLenum, GLsizeiptr, const void *, GLenum); +extern const char *jwzgles_gluErrorString (GLenum error); + +#endif /* __JWZGLES_I_H__ */ diff --git a/hacks/glx/klein.c b/hacks/glx/klein.c new file mode 100644 index 00000000..ac6b5d16 --- /dev/null +++ b/hacks/glx/klein.c @@ -0,0 +1,2044 @@ +/* klein --- Shows a Klein bottle that rotates in 4d or on which you + can walk */ + +#if 0 +static const char sccsid[] = "@(#)klein.c 1.1 08/10/04 xlockmore"; +#endif + +/* Copyright (c) 2005-2009 Carsten Steger . */ + +/* + * Permission to use, copy, modify, and distribute this software and its + * documentation for any purpose and without fee is hereby granted, + * provided that the above copyright notice appear in all copies and that + * both that copyright notice and this permission notice appear in + * supporting documentation. + * + * This file is provided AS IS with no warranties of any kind. The author + * shall have no liability with respect to the infringement of copyrights, + * trade secrets or any patents by this file or any part thereof. In no + * event will the author be liable for any lost revenue or profits or + * other special, indirect and consequential damages. + * + * REVISION HISTORY: + * C. Steger - 08/10/04: Initial version + * C. Steger - 09/08/03: Changes to the parameter handling + */ + +/* + * This program shows two different Klein bottles in 4d: the figure-8 Klein + * bottle or the Lawson Klein bottle. You can walk on the Klein bottle, see + * it turn in 4d, or walk on it while it turns in 4d. The figure-8 Klein + * bottle is well known in its 3d form. The 4d form used in this program is + * an extension of the 3d form to 4d that does not intersect itself in 4d + * (which can be seen in the depth colors mode). The Lawson Klein bottle, + * on the other hand, does intersect itself in 4d. Its primary use is that + * it has a nice appearance for walking and for turning in 3d. The Klein + * bottle is a non-orientable surface. To make this apparent, the two-sided + * color mode can be used. Alternatively, orientation markers (curling + * arrows) can be drawn as a texture map on the surface of the Klein bottle. + * While walking on the Klein bottle, you will notice that the orientation + * of the curling arrows changes (which it must because the Klein bottle is + * non-orientable). The program projects the 4d Klein bottle to 3d using + * either a perspective or an orthographic projection. Which of the two + * alternatives looks more appealing depends on the viewing mode and the + * Klein bottle. For example, the Lawson Klein bottle looks nicest when + * projected perspectively. The figure-8 Klein bottle, on the other + * hand, looks nicer while walking when projected orthographically from 4d. + * The projected Klein bottle can then be projected to the screen either + * perspectively or orthographically. When using the walking modes, + * perspective projection to the screen should be used. There are three + * display modes for the Klein bottle: mesh (wireframe), solid, or + * transparent. Furthermore, the appearance of the Klein bottle can be as + * a solid object or as a set of see-through bands. Finally, the colors + * with with the Klein bottle is drawn can be set to two-sided, rainbow, or + * depth. In the first case, the Klein bottle is drawn with red on one + * "side" and green on the "other side". Of course, the Klein bottle only + * has one side, so the color jumps from red to green along a curve on the + * surface of the Klein bottle. This mode enables you to see that the Klein + * bottle is non-orientable. The second mode draws the Klein bottle with + * fully saturated rainbow colors. This gives a very nice effect when + * combined with the see-through bands mode or with the orientation markers + * drawn. The third mode draws the Klein bottle with colors that are chosen + * according to the 4d "depth" of the points. This mode enables you to see + * that the figure-8 Klein bottle does not intersect itself in 4d, while the + * Lawson Klein bottle does intersect itself. The rotation speed for each + * of the six planes around which the Klein bottle rotates can be chosen. + * For the walk-and-turn more, only the rotation speeds around the true 4d + * planes are used (the xy, xz, and yz planes). Furthermore, in the walking + * modes the walking direction in the 2d base square of the Klein bottle and + * the walking speed can be chosen. This program is somewhat inspired by + * Thomas Banchoff's book "Beyond the Third Dimension: Geometry, Computer + * Graphics, and Higher Dimensions", Scientific American Library, 1990. + */ + +#ifndef M_PI +#define M_PI 3.14159265358979323846 +#endif + +#define KLEIN_BOTTLE_FIGURE_8 0 +#define KLEIN_BOTTLE_LAWSON 1 +#define NUM_KLEIN_BOTTLES 2 + +#define DISP_WIREFRAME 0 +#define DISP_SURFACE 1 +#define DISP_TRANSPARENT 2 +#define NUM_DISPLAY_MODES 3 + +#define APPEARANCE_SOLID 0 +#define APPEARANCE_BANDS 1 +#define NUM_APPEARANCES 2 + +#define COLORS_TWOSIDED 0 +#define COLORS_RAINBOW 1 +#define COLORS_DEPTH 2 +#define NUM_COLORS 3 + +#define VIEW_WALK 0 +#define VIEW_TURN 1 +#define VIEW_WALKTURN 2 +#define NUM_VIEW_MODES 3 + +#define DISP_3D_PERSPECTIVE 0 +#define DISP_3D_ORTHOGRAPHIC 1 +#define NUM_DISP_3D_MODES 2 + +#define DISP_4D_PERSPECTIVE 0 +#define DISP_4D_ORTHOGRAPHIC 1 +#define NUM_DISP_4D_MODES 2 + +#define DEF_KLEIN_BOTTLE "random" +#define DEF_DISPLAY_MODE "random" +#define DEF_APPEARANCE "random" +#define DEF_COLORS "random" +#define DEF_VIEW_MODE "random" +#define DEF_MARKS "False" +#define DEF_PROJECTION_3D "random" +#define DEF_PROJECTION_4D "random" +#define DEF_SPEEDWX "1.1" +#define DEF_SPEEDWY "1.3" +#define DEF_SPEEDWZ "1.5" +#define DEF_SPEEDXY "1.7" +#define DEF_SPEEDXZ "1.9" +#define DEF_SPEEDYZ "2.1" +#define DEF_WALK_DIRECTION "7.0" +#define DEF_WALK_SPEED "20.0" + +#ifdef STANDALONE +# define DEFAULTS "*delay: 10000 \n" \ + "*showFPS: False \n" \ + +# define refresh_klein 0 +# include "xlockmore.h" /* from the xscreensaver distribution */ +#else /* !STANDALONE */ +# include "xlock.h" /* from the xlockmore distribution */ +#endif /* !STANDALONE */ + +#ifdef USE_GL + +#ifndef HAVE_COCOA +# include +#endif + +#include "gltrackball.h" + + +#ifdef USE_MODULES +ModStruct klein_description = +{"klein", "init_klein", "draw_klein", "release_klein", + "draw_klein", "change_klein", NULL, &klein_opts, + 25000, 1, 1, 1, 1.0, 4, "", + "Rotate a Klein bottle in 4d or walk on it", 0, NULL}; + +#endif + + +static char *klein_bottle; +static int bottle_type; +static char *mode; +static int display_mode; +static char *appear; +static int appearance; +static char *color_mode; +static int colors; +static char *view_mode; +static int view; +static Bool marks; +static char *proj_3d; +static int projection_3d; +static char *proj_4d; +static int projection_4d; +static float speed_wx; +static float speed_wy; +static float speed_wz; +static float speed_xy; +static float speed_xz; +static float speed_yz; +static float walk_direction; +static float walk_speed; + + +static XrmOptionDescRec opts[] = +{ + {"-klein-bottle", ".kleinBottle", XrmoptionSepArg, 0 }, + {"-figure-8", ".kleinBottle", XrmoptionNoArg, "figure-8" }, + {"-lawson", ".kleinBottle", XrmoptionNoArg, "lawson" }, + {"-mode", ".displayMode", XrmoptionSepArg, 0 }, + {"-wireframe", ".displayMode", XrmoptionNoArg, "wireframe" }, + {"-surface", ".displayMode", XrmoptionNoArg, "surface" }, + {"-transparent", ".displayMode", XrmoptionNoArg, "transparent" }, + {"-appearance", ".appearance", XrmoptionSepArg, 0 }, + {"-solid", ".appearance", XrmoptionNoArg, "solid" }, + {"-bands", ".appearance", XrmoptionNoArg, "bands" }, + {"-colors", ".colors", XrmoptionSepArg, 0 }, + {"-twosided", ".colors", XrmoptionNoArg, "two-sided" }, + {"-rainbow", ".colors", XrmoptionNoArg, "rainbow" }, + {"-depth", ".colors", XrmoptionNoArg, "depth" }, + {"-view-mode", ".viewMode", XrmoptionSepArg, 0 }, + {"-walk", ".viewMode", XrmoptionNoArg, "walk" }, + {"-turn", ".viewMode", XrmoptionNoArg, "turn" }, + {"-walk-turn", ".viewMode", XrmoptionNoArg, "walk-turn" }, + {"-orientation-marks", ".marks", XrmoptionNoArg, "on"}, + {"+orientation-marks", ".marks", XrmoptionNoArg, "off"}, + {"-projection-3d", ".projection3d", XrmoptionSepArg, 0 }, + {"-perspective-3d", ".projection3d", XrmoptionNoArg, "perspective" }, + {"-orthographic-3d", ".projection3d", XrmoptionNoArg, "orthographic" }, + {"-projection-4d", ".projection4d", XrmoptionSepArg, 0 }, + {"-perspective-4d", ".projection4d", XrmoptionNoArg, "perspective" }, + {"-orthographic-4d", ".projection4d", XrmoptionNoArg, "orthographic" }, + {"-speed-wx", ".speedwx", XrmoptionSepArg, 0 }, + {"-speed-wy", ".speedwy", XrmoptionSepArg, 0 }, + {"-speed-wz", ".speedwz", XrmoptionSepArg, 0 }, + {"-speed-xy", ".speedxy", XrmoptionSepArg, 0 }, + {"-speed-xz", ".speedxz", XrmoptionSepArg, 0 }, + {"-speed-yz", ".speedyz", XrmoptionSepArg, 0 }, + {"-walk-direction", ".walkDirection", XrmoptionSepArg, 0 }, + {"-walk-speed", ".walkSpeed", XrmoptionSepArg, 0 } +}; + +static argtype vars[] = +{ + { &klein_bottle, "kleinBottle", "KleinBottle", DEF_KLEIN_BOTTLE, t_String }, + { &mode, "displayMode", "DisplayMode", DEF_DISPLAY_MODE, t_String }, + { &appear, "appearance", "Appearance", DEF_APPEARANCE, t_String }, + { &color_mode, "colors", "Colors", DEF_COLORS, t_String }, + { &view_mode, "viewMode", "ViewMode", DEF_VIEW_MODE, t_String }, + { &marks, "marks", "Marks", DEF_MARKS, t_Bool }, + { &proj_3d, "projection3d", "Projection3d", DEF_PROJECTION_3D, t_String }, + { &proj_4d, "projection4d", "Projection4d", DEF_PROJECTION_4D, t_String }, + { &speed_wx, "speedwx", "Speedwx", DEF_SPEEDWX, t_Float}, + { &speed_wy, "speedwy", "Speedwy", DEF_SPEEDWY, t_Float}, + { &speed_wz, "speedwz", "Speedwz", DEF_SPEEDWZ, t_Float}, + { &speed_xy, "speedxy", "Speedxy", DEF_SPEEDXY, t_Float}, + { &speed_xz, "speedxz", "Speedxz", DEF_SPEEDXZ, t_Float}, + { &speed_yz, "speedyz", "Speedyz", DEF_SPEEDYZ, t_Float}, + { &walk_direction, "walkDirection", "WalkDirection", DEF_WALK_DIRECTION, t_Float}, + { &walk_speed, "walkSpeed", "WalkSpeed", DEF_WALK_SPEED, t_Float} +}; + +ENTRYPOINT ModeSpecOpt klein_opts = +{sizeof opts / sizeof opts[0], opts, sizeof vars / sizeof vars[0], vars, NULL}; + + +/* Radius of the Figure 8 Klein bottle */ +#define FIGURE_8_RADIUS 2.0 + +/* Offset by which we walk above the Klein bottle */ +#define DELTAY 0.02 + +/* Number of subdivisions of the Klein bottle */ +#define NUMU 128 +#define NUMV 128 + +/* Number of subdivisions per band */ +#define NUMB 8 + + +typedef struct { + GLint WindH, WindW; + GLXContext *glx_context; + /* 4D rotation angles */ + float alpha, beta, delta, zeta, eta, theta; + /* Movement parameters */ + float umove, vmove, dumove, dvmove; + int side; + /* The viewing offset in 4d */ + float offset4d[4]; + /* The viewing offset in 3d */ + float offset3d[4]; + /* The 4d coordinates of the Klein bottle and their derivatives */ + float x[(NUMU+1)*(NUMV+1)][4]; + float xu[(NUMU+1)*(NUMV+1)][4]; + float xv[(NUMU+1)*(NUMV+1)][4]; + float pp[(NUMU+1)*(NUMV+1)][3]; + float pn[(NUMU+1)*(NUMV+1)][3]; + /* The precomputed colors of the Klein bottle */ + float col[(NUMU+1)*(NUMV+1)][4]; + /* The precomputed texture coordinates of the Klein bottle */ + float tex[(NUMU+1)*(NUMV+1)][2]; + /* The "curlicue" texture */ + GLuint tex_name; + /* Aspect ratio of the current window */ + float aspect; + /* Trackball states */ + trackball_state *trackballs[2]; + int current_trackball; + Bool button_pressed; + /* A random factor to modify the rotation speeds */ + float speed_scale; +} kleinstruct; + +static kleinstruct *klein = (kleinstruct *) NULL; + + +/* A texture map containing a "curlicue" */ +#define TEX_DIMENSION 64 +static const unsigned char texture[TEX_DIMENSION*TEX_DIMENSION] = { + 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, + 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, + 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, + 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, + 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, + 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, + 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, + 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, + 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, + 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, + 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, + 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, + 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, + 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, + 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, + 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, + 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, + 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, + 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, + 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, + 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, + 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, + 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, + 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, + 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, + 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, + 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, + 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, + 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, + 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, + 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, + 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, + 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, + 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, + 255,255,255,255,255,255,255, 58, 43, 43, 43, 43, 45, 70, 70, 70, + 70, 70, 70, 70, 74, 98, 98, 98,100,194,255,255,255,255,255,255, + 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, + 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, + 255,255,255,255,255,255,255, 18, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 30,186,255,255,255,255,255,255,255, + 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, + 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, + 255,255,255,255,255,255,255, 18, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 1,111,244,255,255,255,255,255,255,255,255, + 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, + 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, + 255,255,255,255,255,255,255, 18, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 43,198,255,255,255,255,255,255,255,255,255,255, + 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, + 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, + 255,255,255,255,255,255,255, 18, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 5,123,248,255,255,255,255,255,255,255,255,255,255,255, + 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, + 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, + 255,255,255,255,255,255,255, 18, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 50,209,255,255,255,255,255,255,255,255,255,255,255,255,255, + 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,246, + 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, + 255,255,255,255,255,255,255, 18, 0, 0, 0, 0, 0, 0, 0, 0, + 74,252,255,255,255,255,255,255,255,255,255,255,255,255,255,255, + 255,255,255,255,255,255,255,255,255,255,255,255,255,255,138, 4, + 66,229,255,255,255,255,255,255,255,255,255,255,255,255,255,255, + 255,255,255,255,255,255,255, 18, 0, 0, 0, 0, 0, 0, 0, 0, + 1,170,255,255,255,255,255,255,255,255,255,255,255,255,255,255, + 255,255,255,255,255,255,255,255,255,255,255,255,255,153, 0, 0, + 0, 53,255,255,255,255,255,255,255,255,255,255,255,255,255,255, + 255,255,255,255,255,255,255, 18, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 6,188,255,255,255,255,255,255,255,255,255,255,255,255,255, + 255,255,255,255,255,255,255,255,255,255,255,255,213, 7, 0, 0, + 0, 0,226,255,255,255,255,255,255,255,255,255,255,255,255,255, + 255,255,255,255,255,255,255, 45, 0, 0, 0, 0, 0, 47, 0, 0, + 0, 0, 22,225,255,255,255,255,255,255,255,255,255,255,255,255, + 255,255,255,255,255,255,255,255,255,255,255,254, 54, 0, 0, 0, + 0, 81,254,255,255,255,255,255,255,255,255,255,255,255,255,255, + 255,255,255,255,255,255,255, 45, 0, 0, 0, 0, 56,247, 82, 0, + 0, 0, 0, 59,253,255,255,255,255,255,255,255,255,255,255,255, + 255,255,255,255,255,255,255,255,255,255,255,152, 0, 0, 0, 0, + 52,243,255,255,255,255,255,255,255,255,255,255,255,255,255,255, + 255,255,255,255,255,255,255, 45, 0, 0, 0, 8,215,255,250, 56, + 0, 0, 0, 0,142,255,255,255,255,255,255,255,255,255,255,255, + 255,255,255,255,255,255,255,255,255,255,241, 19, 0, 0, 0, 15, + 220,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, + 255,255,255,255,255,255,255, 45, 0, 0, 0,129,255,255,255,230, + 23, 0, 0, 0, 12,230,255,255,255,255,255,255,255,255,255,255, + 255,255,255,255,255,255,255,255,255,255,131, 0, 0, 0, 0,157, + 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, + 255,255,255,255,255,255,255, 45, 0, 0, 49,250,255,255,255,255, + 171, 0, 0, 0, 0,112,255,255,255,255,255,255,255,255,255,255, + 255,255,255,255,255,255,255,255,255,246, 19, 0, 0, 0, 54,253, + 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, + 255,255,255,255,255,255,255, 45, 0, 5,208,255,255,255,255,255, + 255, 77, 0, 0, 0, 9,231,255,255,255,255,255,255,255,255,255, + 255,255,255,255,255,255,255,255,255,163, 0, 0, 0, 0,186,255, + 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, + 255,255,255,255,255,255,255, 45, 0,121,255,255,255,255,255,255, + 255,211, 2, 0, 0, 0,134,255,255,255,255,255,255,255,255,255, + 255,255,255,255,255,255,255,255,255, 69, 0, 0, 0, 50,255,255, + 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, + 255,255,255,255,255,255,255, 45, 41,247,255,255,255,255,255,255, + 255,255, 73, 0, 0, 0, 38,254,255,255,255,255,255,255,255,255, + 255,255,255,255,255,255,255,255,237, 4, 0, 0, 0,145,255,255, + 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, + 255,255,255,255,255,255,255, 52,201,255,255,255,255,255,255,255, + 255,255,169, 0, 0, 0, 0,216,255,255,255,255,255,255,255,255, + 255,255,255,255,255,255,255,255,181, 0, 0, 0, 0,229,255,255, + 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, + 255,255,255,255,255,255,255,186,255,255,255,255,255,255,255,255, + 255,255,247, 7, 0, 0, 0,150,255,255,255,255,255,255,255,255, + 255,255,255,255,255,255,255,255,130, 0, 0, 0, 42,255,255,255, + 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, + 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, + 255,255,255, 67, 0, 0, 0, 91,255,255,255,255,255,255,255,255, + 255,255,255,255,255,255,255,255, 79, 0, 0, 0, 95,255,255,255, + 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, + 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, + 255,255,255,120, 0, 0, 0, 56,255,255,255,255,255,255,255,255, + 255,255,255,255,255,255,255,255, 55, 0, 0, 0,130,255,255,255, + 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, + 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, + 255,255,255,157, 0, 0, 0, 21,255,255,255,255,255,255,255,255, + 255,255,255,255,255,255,255,255, 34, 0, 0, 0,161,255,255,255, + 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, + 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, + 255,255,255,179, 0, 0, 0, 2,250,255,255,255,255,255,255,255, + 255,255,255,255,255,255,255,255, 27, 0, 0, 0,168,255,255,255, + 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, + 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, + 255,255,255,200, 0, 0, 0, 0,249,255,255,255,255,255,255,255, + 255,255,255,255,255,255,255,255, 27, 0, 0, 0,168,255,255,255, + 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, + 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, + 255,255,255,200, 0, 0, 0, 0,249,255,255,255,255,255,255,255, + 255,255,255,255,255,255,255,255, 27, 0, 0, 0,163,255,255,255, + 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, + 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, + 255,255,255,183, 0, 0, 0, 0,249,255,255,255,255,255,255,255, + 255,255,255,255,255,255,255,255, 42, 0, 0, 0,135,255,255,255, + 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, + 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, + 255,255,255,161, 0, 0, 0, 17,254,255,255,255,255,255,255,255, + 255,255,255,255,255,255,255,255, 76, 0, 0, 0,100,255,255,255, + 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, + 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, + 255,255,255,126, 0, 0, 0, 48,255,255,255,255,255,255,255,255, + 255,255,255,255,255,255,255,255,114, 0, 0, 0, 53,255,255,255, + 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, + 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, + 255,255,255, 78, 0, 0, 0, 84,255,255,255,255,255,255,255,255, + 255,255,255,255,255,255,255,255,165, 0, 0, 0, 3,241,255,255, + 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, + 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, + 255,255,252, 16, 0, 0, 0,139,255,255,255,255,255,255,255,255, + 255,255,255,255,255,255,255,255,228, 0, 0, 0, 0,161,255,255, + 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, + 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, + 255,255,192, 0, 0, 0, 0,198,255,255,255,255,255,255,255,255, + 255,255,255,255,255,255,255,255,255, 46, 0, 0, 0, 67,255,255, + 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, + 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, + 255,255, 93, 0, 0, 0, 21,250,255,255,255,255,255,255,255,255, + 255,255,255,255,255,255,255,255,255,139, 0, 0, 0, 1,211,255, + 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, + 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, + 255,226, 7, 0, 0, 0,108,255,255,255,255,255,255,255,255,255, + 255,255,255,255,255,255,255,255,255,230, 6, 0, 0, 0, 79,255, + 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, + 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, + 255,106, 0, 0, 0, 1,206,255,255,255,255,255,255,255,255,255, + 255,255,255,255,255,255,255,255,255,255, 97, 0, 0, 0, 0,183, + 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, + 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, + 202, 3, 0, 0, 0, 67,255,255,255,255,255,255,255,255,255,255, + 255,255,255,255,255,255,255,255,255,255,221, 8, 0, 0, 0, 27, + 235,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, + 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,243, + 40, 0, 0, 0, 0,198,255,255,255,255,255,255,255,255,255,255, + 255,255,255,255,255,255,255,255,255,255,255,126, 0, 0, 0, 0, + 71,252,255,255,255,255,255,255,255,255,255,255,255,255,255,255, + 255,255,255,255,255,255,255,255,255,255,255,255,255,255,253, 85, + 0, 0, 0, 0, 96,255,255,255,255,255,255,255,255,255,255,255, + 255,255,255,255,255,255,255,255,255,255,255,247, 44, 0, 0, 0, + 0, 91,255,255,255,255,255,255,255,255,255,255,255,255,255,255, + 255,255,255,255,255,255,255,255,255,255,255,255,255,255,116, 0, + 0, 0, 0, 25,233,255,255,255,255,255,255,255,255,255,255,255, + 255,255,255,255,255,255,255,255,255,255,255,255,216, 11, 0, 0, + 0, 0, 90,251,255,255,255,255,255,255,255,255,255,255,255,255, + 255,255,255,255,255,255,255,255,255,255,255,255,252,112, 0, 0, + 0, 0, 4,191,255,255,255,255,255,255,255,255,255,255,255,255, + 255,255,255,255,255,255,255,255,255,255,255,255,255,174, 4, 0, + 0, 0, 0, 72,235,255,255,255,255,255,255,255,255,255,255,255, + 255,255,255,255,255,255,255,255,255,255,255,242, 84, 0, 0, 0, + 0, 0,146,255,255,255,255,255,255,255,255,255,255,255,255,255, + 255,255,255,255,255,255,255,255,255,255,255,255,255,255,150, 1, + 0, 0, 0, 0, 27,181,255,255,255,255,255,255,255,255,255,255, + 255,255,255,255,255,255,255,255,255,255,194, 39, 0, 0, 0, 0, + 0,120,255,255,255,255,255,255,255,255,255,255,255,255,255,255, + 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,151, + 4, 0, 0, 0, 0, 0, 77,209,255,255,255,255,255,255,255,255, + 255,255,255,255,255,255,255,255,216, 92, 1, 0, 0, 0, 0, 0, + 125,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, + 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, + 175, 12, 0, 0, 0, 0, 0, 1, 70,164,241,255,255,255,255,255, + 255,255,255,255,255,242,171, 77, 2, 0, 0, 0, 0, 0, 4,150, + 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, + 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, + 255,214, 41, 0, 0, 0, 0, 0, 0, 0, 4, 48, 98,138,163,163, + 163,163,140,103, 55, 5, 0, 0, 0, 0, 0, 0, 0, 30,199,255, + 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, + 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, + 255,255,245,125, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3,105,240,255,255, + 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, + 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, + 255,255,255,255,222,100, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 83,210,255,255,255,255, + 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, + 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, + 255,255,255,255,255,255,228,136, 45, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 37,125,220,255,255,255,255,255,255, + 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, + 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, + 255,255,255,255,255,255,255,255,255,225,166,112, 74, 43, 32, 12, + 8, 32, 40, 71,105,162,218,255,255,255,255,255,255,255,255,255, + 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, + 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, + 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, + 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, + 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, + 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, + 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, + 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, + 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, + 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, + 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, + 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, + 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, + 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, + 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, + 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, + 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, + 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, + 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, + 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, + 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, + 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, + 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, + 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, + 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, + 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, + 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, + 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, + 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, + 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, + 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, + 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, + 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +}; + + +/* Add a rotation around the wx-plane to the matrix m. */ +static void rotatewx(float m[4][4], float phi) +{ + float c, s, u, v; + int i; + + phi *= M_PI/180.0; + c = cos(phi); + s = sin(phi); + for (i=0; i<4; i++) + { + u = m[i][1]; + v = m[i][2]; + m[i][1] = c*u+s*v; + m[i][2] = -s*u+c*v; + } +} + + +/* Add a rotation around the wy-plane to the matrix m. */ +static void rotatewy(float m[4][4], float phi) +{ + float c, s, u, v; + int i; + + phi *= M_PI/180.0; + c = cos(phi); + s = sin(phi); + for (i=0; i<4; i++) + { + u = m[i][0]; + v = m[i][2]; + m[i][0] = c*u-s*v; + m[i][2] = s*u+c*v; + } +} + + +/* Add a rotation around the wz-plane to the matrix m. */ +static void rotatewz(float m[4][4], float phi) +{ + float c, s, u, v; + int i; + + phi *= M_PI/180.0; + c = cos(phi); + s = sin(phi); + for (i=0; i<4; i++) + { + u = m[i][0]; + v = m[i][1]; + m[i][0] = c*u+s*v; + m[i][1] = -s*u+c*v; + } +} + + +/* Add a rotation around the xy-plane to the matrix m. */ +static void rotatexy(float m[4][4], float phi) +{ + float c, s, u, v; + int i; + + phi *= M_PI/180.0; + c = cos(phi); + s = sin(phi); + for (i=0; i<4; i++) + { + u = m[i][2]; + v = m[i][3]; + m[i][2] = c*u+s*v; + m[i][3] = -s*u+c*v; + } +} + + +/* Add a rotation around the xz-plane to the matrix m. */ +static void rotatexz(float m[4][4], float phi) +{ + float c, s, u, v; + int i; + + phi *= M_PI/180.0; + c = cos(phi); + s = sin(phi); + for (i=0; i<4; i++) + { + u = m[i][1]; + v = m[i][3]; + m[i][1] = c*u-s*v; + m[i][3] = s*u+c*v; + } +} + + +/* Add a rotation around the yz-plane to the matrix m. */ +static void rotateyz(float m[4][4], float phi) +{ + float c, s, u, v; + int i; + + phi *= M_PI/180.0; + c = cos(phi); + s = sin(phi); + for (i=0; i<4; i++) + { + u = m[i][0]; + v = m[i][3]; + m[i][0] = c*u-s*v; + m[i][3] = s*u+c*v; + } +} + + +/* Compute the rotation matrix m from the rotation angles. */ +static void rotateall(float al, float be, float de, float ze, float et, + float th, float m[4][4]) +{ + int i, j; + + for (i=0; i<4; i++) + for (j=0; j<4; j++) + m[i][j] = (i==j); + rotatewx(m,al); + rotatewy(m,be); + rotatewz(m,de); + rotatexy(m,ze); + rotatexz(m,et); + rotateyz(m,th); +} + + +/* Compute the rotation matrix m from the 4d rotation angles. */ +static void rotateall4d(float ze, float et, float th, float m[4][4]) +{ + int i, j; + + for (i=0; i<4; i++) + for (j=0; j<4; j++) + m[i][j] = (i==j); + rotatexy(m,ze); + rotatexz(m,et); + rotateyz(m,th); +} + + +/* Multiply two rotation matrices: o=m*n. */ +static void mult_rotmat(float m[4][4], float n[4][4], float o[4][4]) +{ + int i, j, k; + + for (i=0; i<4; i++) + { + for (j=0; j<4; j++) + { + o[i][j] = 0.0; + for (k=0; k<4; k++) + o[i][j] += m[i][k]*n[k][j]; + } + } +} + + +/* Compute a 4D rotation matrix from two unit quaternions. */ +static void quats_to_rotmat(float p[4], float q[4], float m[4][4]) +{ + double al, be, de, ze, et, th; + double r00, r01, r02, r12, r22; + + r00 = 1.0-2.0*(p[1]*p[1]+p[2]*p[2]); + r01 = 2.0*(p[0]*p[1]+p[2]*p[3]); + r02 = 2.0*(p[2]*p[0]-p[1]*p[3]); + r12 = 2.0*(p[1]*p[2]+p[0]*p[3]); + r22 = 1.0-2.0*(p[1]*p[1]+p[0]*p[0]); + + al = atan2(-r12,r22)*180.0/M_PI; + be = atan2(r02,sqrt(r00*r00+r01*r01))*180.0/M_PI; + de = atan2(-r01,r00)*180.0/M_PI; + + r00 = 1.0-2.0*(q[1]*q[1]+q[2]*q[2]); + r01 = 2.0*(q[0]*q[1]+q[2]*q[3]); + r02 = 2.0*(q[2]*q[0]-q[1]*q[3]); + r12 = 2.0*(q[1]*q[2]+q[0]*q[3]); + r22 = 1.0-2.0*(q[1]*q[1]+q[0]*q[0]); + + et = atan2(-r12,r22)*180.0/M_PI; + th = atan2(r02,sqrt(r00*r00+r01*r01))*180.0/M_PI; + ze = atan2(-r01,r00)*180.0/M_PI; + + rotateall(al,be,de,ze,et,-th,m); +} + + +/* Compute a fully saturated and bright color based on an angle. */ +static void color(double angle, float col[4]) +{ + int s; + double t; + + if (colors == COLORS_TWOSIDED) + return; + + if (angle >= 0.0) + angle = fmod(angle,2.0*M_PI); + else + angle = fmod(angle,-2.0*M_PI); + s = floor(angle/(M_PI/3)); + t = angle/(M_PI/3)-s; + if (s >= 6) + s = 0; + switch (s) + { + case 0: + col[0] = 1.0; + col[1] = t; + col[2] = 0.0; + break; + case 1: + col[0] = 1.0-t; + col[1] = 1.0; + col[2] = 0.0; + break; + case 2: + col[0] = 0.0; + col[1] = 1.0; + col[2] = t; + break; + case 3: + col[0] = 0.0; + col[1] = 1.0-t; + col[2] = 1.0; + break; + case 4: + col[0] = t; + col[1] = 0.0; + col[2] = 1.0; + break; + case 5: + col[0] = 1.0; + col[1] = 0.0; + col[2] = 1.0-t; + break; + } + if (display_mode == DISP_TRANSPARENT) + col[3] = 0.7; + else + col[3] = 1.0; +} + + +/* Set up the figure-8 Klein bottle coordinates, colors, and texture. */ +static void setup_figure8(ModeInfo *mi, double umin, double umax, double vmin, + double vmax) +{ + int i, j, k, l; + double u, v, ur, vr; + double cu, su, cv, sv, cv2, sv2, c2u, s2u; + kleinstruct *kb = &klein[MI_SCREEN(mi)]; + + ur = umax-umin; + vr = vmax-vmin; + for (i=0; i<=NUMU; i++) + { + for (j=0; j<=NUMV; j++) + { + k = i*(NUMV+1)+j; + u = -ur*j/NUMU+umin; + v = vr*i/NUMV+vmin; + if (colors == COLORS_DEPTH) + color((cos(u)+1.0)*M_PI*2.0/3.0,kb->col[k]); + else + color(v,kb->col[k]); + kb->tex[k][0] = -32*u/(2.0*M_PI); + kb->tex[k][1] = 32*v/(2.0*M_PI); + cu = cos(u); + su = sin(u); + cv = cos(v); + sv = sin(v); + cv2 = cos(0.5*v); + sv2 = sin(0.5*v); + c2u = cos(2.0*u); + s2u = sin(2.0*u); + kb->x[k][0] = (su*cv2-s2u*sv2+FIGURE_8_RADIUS)*cv; + kb->x[k][1] = (su*cv2-s2u*sv2+FIGURE_8_RADIUS)*sv; + kb->x[k][2] = su*sv2+s2u*cv2; + kb->x[k][3] = cu; + kb->xu[k][0] = (cu*cv2-2.0*c2u*sv2)*cv; + kb->xu[k][1] = (cu*cv2-2.0*c2u*sv2)*sv; + kb->xu[k][2] = cu*sv2+2.0*c2u*cv2; + kb->xu[k][3] = -su; + kb->xv[k][0] = ((-0.5*su*sv2-0.5*s2u*cv2)*cv- + (su*cv2-s2u*sv2+FIGURE_8_RADIUS)*sv); + kb->xv[k][1] = ((-0.5*su*sv2-0.5*s2u*cv2)*sv+ + (su*cv2-s2u*sv2+FIGURE_8_RADIUS)*cv); + kb->xv[k][2] = 0.5*su*cv2-0.5*s2u*sv2; + kb->xv[k][3] = 0.0; + for (l=0; l<4; l++) + { + kb->x[k][l] /= FIGURE_8_RADIUS+1.25; + kb->xu[k][l] /= FIGURE_8_RADIUS+1.25; + kb->xv[k][l] /= FIGURE_8_RADIUS+1.25; + } + } + } +} + + +/* Set up the Lawson Klein bottle coordinates, colors, and texture. */ +static void setup_lawson(ModeInfo *mi, double umin, double umax, double vmin, + double vmax) +{ + int i, j, k; + double u, v, ur, vr; + double cu, su, cv, sv, cv2, sv2; + kleinstruct *kb = &klein[MI_SCREEN(mi)]; + + ur = umax-umin; + vr = vmax-vmin; + for (i=0; i<=NUMV; i++) + { + for (j=0; j<=NUMU; j++) + { + k = i*(NUMU+1)+j; + u = -ur*j/NUMU+umin; + v = vr*i/NUMV+vmin; + if (colors == COLORS_DEPTH) + color((sin(u)*cos(0.5*v)+1.0)*M_PI*2.0/3.0,kb->col[k]); + else + color(v,kb->col[k]); + kb->tex[k][0] = -32*u/(2.0*M_PI); + kb->tex[k][1] = 32*v/(2.0*M_PI); + cu = cos(u); + su = sin(u); + cv = cos(v); + sv = sin(v); + cv2 = cos(0.5*v); + sv2 = sin(0.5*v); + kb->x[k][0] = cu*cv; + kb->x[k][1] = cu*sv; + kb->x[k][2] = su*sv2; + kb->x[k][3] = su*cv2; + kb->xu[k][0] = -su*cv; + kb->xu[k][1] = -su*sv; + kb->xu[k][2] = cu*sv2; + kb->xu[k][3] = cu*cv2; + kb->xv[k][0] = -cu*sv; + kb->xv[k][1] = cu*cv; + kb->xv[k][2] = su*cv2*0.5; + kb->xv[k][3] = -su*sv2*0.5; + } + } +} + + +/* Draw a figure-8 Klein bottle projected into 3D. */ +static int figure8(ModeInfo *mi, double umin, double umax, double vmin, + double vmax) +{ + int polys = 0; + static const GLfloat mat_diff_red[] = { 1.0, 0.0, 0.0, 1.0 }; + static const GLfloat mat_diff_green[] = { 0.0, 1.0, 0.0, 1.0 }; + static const GLfloat mat_diff_trans_red[] = { 1.0, 0.0, 0.0, 0.7 }; + static const GLfloat mat_diff_trans_green[] = { 0.0, 1.0, 0.0, 0.7 }; + float p[3], pu[3], pv[3], pm[3], n[3], b[3], mat[4][4]; + int i, j, k, l, m, o; + double u, v; + double xx[4], xxu[4], xxv[4], y[4], yu[4], yv[4]; + double q, r, s, t; + double cu, su, cv, sv, cv2, sv2, c2u, s2u; + float q1[4], q2[4], r1[4][4], r2[4][4]; + kleinstruct *kb = &klein[MI_SCREEN(mi)]; + + if (view == VIEW_WALK || view == VIEW_WALKTURN) + { + /* Compute the rotation that rotates the Klein bottle in 4D without the + trackball rotations. */ + rotateall4d(kb->zeta,kb->eta,kb->theta,mat); + + u = kb->umove; + v = kb->vmove; + cu = cos(u); + su = sin(u); + cv = cos(v); + sv = sin(v); + cv2 = cos(0.5*v); + sv2 = sin(0.5*v); + c2u = cos(2.0*u); + s2u = sin(2.0*u); + xx[0] = (su*cv2-s2u*sv2+FIGURE_8_RADIUS)*cv; + xx[1] = (su*cv2-s2u*sv2+FIGURE_8_RADIUS)*sv; + xx[2] = su*sv2+s2u*cv2; + xx[3] = cu; + xxu[0] = (cu*cv2-2.0*c2u*sv2)*cv; + xxu[1] = (cu*cv2-2.0*c2u*sv2)*sv; + xxu[2] = cu*sv2+2.0*c2u*cv2; + xxu[3] = -su; + xxv[0] = ((-0.5*su*sv2-0.5*s2u*cv2)*cv- + (su*cv2-s2u*sv2+FIGURE_8_RADIUS)*sv); + xxv[1] = ((-0.5*su*sv2-0.5*s2u*cv2)*sv+ + (su*cv2-s2u*sv2+FIGURE_8_RADIUS)*cv); + xxv[2] = 0.5*su*cv2-0.5*s2u*sv2; + xxv[3] = 0.0; + for (l=0; l<4; l++) + { + xx[l] /= FIGURE_8_RADIUS+1.25; + xxu[l] /= FIGURE_8_RADIUS+1.25; + xxv[l] /= FIGURE_8_RADIUS+1.25; + } + for (l=0; l<4; l++) + { + y[l] = (mat[l][0]*xx[0]+mat[l][1]*xx[1]+ + mat[l][2]*xx[2]+mat[l][3]*xx[3]); + yu[l] = (mat[l][0]*xxu[0]+mat[l][1]*xxu[1]+ + mat[l][2]*xxu[2]+mat[l][3]*xxu[3]); + yv[l] = (mat[l][0]*xxv[0]+mat[l][1]*xxv[1]+ + mat[l][2]*xxv[2]+mat[l][3]*xxv[3]); + } + if (projection_4d == DISP_4D_ORTHOGRAPHIC) + { + for (l=0; l<3; l++) + { + p[l] = y[l]+kb->offset4d[l]; + pu[l] = yu[l]; + pv[l] = yv[l]; + } + } + else + { + s = y[3]+kb->offset4d[3]; + q = 1.0/s; + t = q*q; + for (l=0; l<3; l++) + { + r = y[l]+kb->offset4d[l]; + p[l] = r*q; + pu[l] = (yu[l]*s-r*yu[3])*t; + pv[l] = (yv[l]*s-r*yv[3])*t; + } + } + n[0] = pu[1]*pv[2]-pu[2]*pv[1]; + n[1] = pu[2]*pv[0]-pu[0]*pv[2]; + n[2] = pu[0]*pv[1]-pu[1]*pv[0]; + t = 1.0/(kb->side*4.0*sqrt(n[0]*n[0]+n[1]*n[1]+n[2]*n[2])); + n[0] *= t; + n[1] *= t; + n[2] *= t; + pm[0] = pu[0]*kb->dumove+pv[0]*kb->dvmove; + pm[1] = pu[1]*kb->dumove+pv[1]*kb->dvmove; + pm[2] = pu[2]*kb->dumove+pv[2]*kb->dvmove; + t = 1.0/(4.0*sqrt(pm[0]*pm[0]+pm[1]*pm[1]+pm[2]*pm[2])); + pm[0] *= t; + pm[1] *= t; + pm[2] *= t; + b[0] = n[1]*pm[2]-n[2]*pm[1]; + b[1] = n[2]*pm[0]-n[0]*pm[2]; + b[2] = n[0]*pm[1]-n[1]*pm[0]; + t = 1.0/(4.0*sqrt(b[0]*b[0]+b[1]*b[1]+b[2]*b[2])); + b[0] *= t; + b[1] *= t; + b[2] *= t; + + /* Compute alpha, beta, delta from the three basis vectors. + | -b[0] -b[1] -b[2] | + m = | n[0] n[1] n[2] | + | -pm[0] -pm[1] -pm[2] | + */ + kb->alpha = atan2(-n[2],-pm[2])*180/M_PI; + kb->beta = atan2( -b[2],sqrt(b[0]*b[0]+b[1]*b[1]))*180/M_PI; + kb->delta = atan2(b[1],-b[0])*180/M_PI; + + /* Compute the rotation that rotates the Klein bottle in 4D. */ + rotateall(kb->alpha,kb->beta,kb->delta,kb->zeta,kb->eta,kb->theta,mat); + + u = kb->umove; + v = kb->vmove; + cu = cos(u); + su = sin(u); + cv = cos(v); + sv = sin(v); + cv2 = cos(0.5*v); + sv2 = sin(0.5*v); + /*c2u = cos(2.0*u);*/ + s2u = sin(2.0*u); + xx[0] = (su*cv2-s2u*sv2+FIGURE_8_RADIUS)*cv; + xx[1] = (su*cv2-s2u*sv2+FIGURE_8_RADIUS)*sv; + xx[2] = su*sv2+s2u*cv2; + xx[3] = cu; + for (l=0; l<4; l++) + xx[l] /= FIGURE_8_RADIUS+1.25; + for (l=0; l<4; l++) + { + r = 0.0; + for (m=0; m<4; m++) + r += mat[l][m]*xx[m]; + y[l] = r; + } + if (projection_4d == DISP_4D_ORTHOGRAPHIC) + { + for (l=0; l<3; l++) + p[l] = y[l]+kb->offset4d[l]; + } + else + { + s = y[3]+kb->offset4d[3]; + for (l=0; l<3; l++) + p[l] = (y[l]+kb->offset4d[l])/s; + } + + kb->offset3d[0] = -p[0]; + kb->offset3d[1] = -p[1]-DELTAY; + kb->offset3d[2] = -p[2]; + } + else + { + /* Compute the rotation that rotates the Klein bottle in 4D, including + the trackball rotations. */ + rotateall(kb->alpha,kb->beta,kb->delta,kb->zeta,kb->eta,kb->theta,r1); + + gltrackball_get_quaternion(kb->trackballs[0],q1); + gltrackball_get_quaternion(kb->trackballs[1],q2); + quats_to_rotmat(q1,q2,r2); + + mult_rotmat(r2,r1,mat); + } + + /* Project the points from 4D to 3D. */ + for (i=0; i<=NUMU; i++) + { + for (j=0; j<=NUMV; j++) + { + o = i*(NUMV+1)+j; + for (l=0; l<4; l++) + { + y[l] = (mat[l][0]*kb->x[o][0]+mat[l][1]*kb->x[o][1]+ + mat[l][2]*kb->x[o][2]+mat[l][3]*kb->x[o][3]); + yu[l] = (mat[l][0]*kb->xu[o][0]+mat[l][1]*kb->xu[o][1]+ + mat[l][2]*kb->xu[o][2]+mat[l][3]*kb->xu[o][3]); + yv[l] = (mat[l][0]*kb->xv[o][0]+mat[l][1]*kb->xv[o][1]+ + mat[l][2]*kb->xv[o][2]+mat[l][3]*kb->xv[o][3]); + } + if (projection_4d == DISP_4D_ORTHOGRAPHIC) + { + for (l=0; l<3; l++) + { + kb->pp[o][l] = (y[l]+kb->offset4d[l])+kb->offset3d[l]; + pu[l] = yu[l]; + pv[l] = yv[l]; + } + } + else + { + s = y[3]+kb->offset4d[3]; + q = 1.0/s; + t = q*q; + for (l=0; l<3; l++) + { + r = y[l]+kb->offset4d[l]; + kb->pp[o][l] = r*q+kb->offset3d[l]; + pu[l] = (yu[l]*s-r*yu[3])*t; + pv[l] = (yv[l]*s-r*yv[3])*t; + } + } + kb->pn[o][0] = pu[1]*pv[2]-pu[2]*pv[1]; + kb->pn[o][1] = pu[2]*pv[0]-pu[0]*pv[2]; + kb->pn[o][2] = pu[0]*pv[1]-pu[1]*pv[0]; + t = 1.0/sqrt(kb->pn[o][0]*kb->pn[o][0]+kb->pn[o][1]*kb->pn[o][1]+ + kb->pn[o][2]*kb->pn[o][2]); + kb->pn[o][0] *= t; + kb->pn[o][1] *= t; + kb->pn[o][2] *= t; + } + } + + if (colors == COLORS_TWOSIDED) + { + glColor3fv(mat_diff_red); + if (display_mode == DISP_TRANSPARENT) + { + glMaterialfv(GL_FRONT,GL_AMBIENT_AND_DIFFUSE,mat_diff_trans_red); + glMaterialfv(GL_BACK,GL_AMBIENT_AND_DIFFUSE,mat_diff_trans_green); + } + else + { + glMaterialfv(GL_FRONT,GL_AMBIENT_AND_DIFFUSE,mat_diff_red); + glMaterialfv(GL_BACK,GL_AMBIENT_AND_DIFFUSE,mat_diff_green); + } + } + glBindTexture(GL_TEXTURE_2D,kb->tex_name); + + for (i=0; i= NUMB/2)) + continue; + if (display_mode == DISP_WIREFRAME) + glBegin(GL_QUAD_STRIP); + else + glBegin(GL_TRIANGLE_STRIP); + for (j=0; j<=NUMV; j++) + { + for (k=0; k<=1; k++) + { + l = (i+k); + m = j; + o = l*(NUMV+1)+m; + glNormal3fv(kb->pn[o]); + glTexCoord2fv(kb->tex[o]); + if (colors != COLORS_TWOSIDED) + { + glColor3fv(kb->col[o]); + glMaterialfv(GL_FRONT_AND_BACK,GL_AMBIENT_AND_DIFFUSE,kb->col[o]); + } + glVertex3fv(kb->pp[o]); + polys++; + } + } + glEnd(); + } + polys /= 2; + return polys; +} + + +/* Draw a Lawson Klein bottle projected into 3D. */ +static int lawson(ModeInfo *mi, double umin, double umax, double vmin, + double vmax) +{ + int polys = 0; + static const GLfloat mat_diff_red[] = { 1.0, 0.0, 0.0, 1.0 }; + static const GLfloat mat_diff_green[] = { 0.0, 1.0, 0.0, 1.0 }; + static const GLfloat mat_diff_trans_red[] = { 1.0, 0.0, 0.0, 0.7 }; + static const GLfloat mat_diff_trans_green[] = { 0.0, 1.0, 0.0, 0.7 }; + float p[3], pu[3], pv[3], pm[3], n[3], b[3], mat[4][4]; + int i, j, k, l, m, o; + double u, v; + double cu, su, cv, sv, cv2, sv2; + double xx[4], xxu[4], xxv[4], y[4], yu[4], yv[4]; + double q, r, s, t; + float q1[4], q2[4], r1[4][4], r2[4][4]; + kleinstruct *kb = &klein[MI_SCREEN(mi)]; + + if (view == VIEW_WALK || view == VIEW_WALKTURN) + { + /* Compute the rotation that rotates the Klein bottle in 4D without the + trackball rotations. */ + rotateall4d(kb->zeta,kb->eta,kb->theta,mat); + + u = kb->umove; + v = kb->vmove; + cu = cos(u); + su = sin(u); + cv = cos(v); + sv = sin(v); + cv2 = cos(0.5*v); + sv2 = sin(0.5*v); + xx[0] = cu*cv; + xx[1] = cu*sv; + xx[2] = su*sv2; + xx[3] = su*cv2; + xxu[0] = -su*cv; + xxu[1] = -su*sv; + xxu[2] = cu*sv2; + xxu[3] = cu*cv2; + xxv[0] = -cu*sv; + xxv[1] = cu*cv; + xxv[2] = su*cv2*0.5; + xxv[3] = -su*sv2*0.5; + for (l=0; l<4; l++) + { + y[l] = (mat[l][0]*xx[0]+mat[l][1]*xx[1]+ + mat[l][2]*xx[2]+mat[l][3]*xx[3]); + yu[l] = (mat[l][0]*xxu[0]+mat[l][1]*xxu[1]+ + mat[l][2]*xxu[2]+mat[l][3]*xxu[3]); + yv[l] = (mat[l][0]*xxv[0]+mat[l][1]*xxv[1]+ + mat[l][2]*xxv[2]+mat[l][3]*xxv[3]); + } + if (projection_4d == DISP_4D_ORTHOGRAPHIC) + { + for (l=0; l<3; l++) + { + p[l] = y[l]+kb->offset4d[l]; + pu[l] = yu[l]; + pv[l] = yv[l]; + } + } + else + { + s = y[3]+kb->offset4d[3]; + q = 1.0/s; + t = q*q; + for (l=0; l<3; l++) + { + r = y[l]+kb->offset4d[l]; + p[l] = r*q; + pu[l] = (yu[l]*s-r*yu[3])*t; + pv[l] = (yv[l]*s-r*yv[3])*t; + } + } + n[0] = pu[1]*pv[2]-pu[2]*pv[1]; + n[1] = pu[2]*pv[0]-pu[0]*pv[2]; + n[2] = pu[0]*pv[1]-pu[1]*pv[0]; + t = 1.0/(kb->side*4.0*sqrt(n[0]*n[0]+n[1]*n[1]+n[2]*n[2])); + n[0] *= t; + n[1] *= t; + n[2] *= t; + pm[0] = pu[0]*kb->dumove+pv[0]*kb->dvmove; + pm[1] = pu[1]*kb->dumove+pv[1]*kb->dvmove; + pm[2] = pu[2]*kb->dumove+pv[2]*kb->dvmove; + t = 1.0/(4.0*sqrt(pm[0]*pm[0]+pm[1]*pm[1]+pm[2]*pm[2])); + pm[0] *= t; + pm[1] *= t; + pm[2] *= t; + b[0] = n[1]*pm[2]-n[2]*pm[1]; + b[1] = n[2]*pm[0]-n[0]*pm[2]; + b[2] = n[0]*pm[1]-n[1]*pm[0]; + t = 1.0/(4.0*sqrt(b[0]*b[0]+b[1]*b[1]+b[2]*b[2])); + b[0] *= t; + b[1] *= t; + b[2] *= t; + + /* Compute alpha, beta, delta from the three basis vectors. + | -b[0] -b[1] -b[2] | + m = | n[0] n[1] n[2] | + | -pm[0] -pm[1] -pm[2] | + */ + kb->alpha = atan2(-n[2],-pm[2])*180/M_PI; + kb->beta = atan2( -b[2],sqrt(b[0]*b[0]+b[1]*b[1]))*180/M_PI; + kb->delta = atan2(b[1],-b[0])*180/M_PI; + + /* Compute the rotation that rotates the Klein bottle in 4D. */ + rotateall(kb->alpha,kb->beta,kb->delta,kb->zeta,kb->eta,kb->theta,mat); + + u = kb->umove; + v = kb->vmove; + cu = cos(u); + su = sin(u); + cv = cos(v); + sv = sin(v); + cv2 = cos(0.5*v); + sv2 = sin(0.5*v); + xx[0] = cu*cv; + xx[1] = cu*sv; + xx[2] = su*sv2; + xx[3] = su*cv2; + for (l=0; l<4; l++) + { + r = 0.0; + for (m=0; m<4; m++) + r += mat[l][m]*xx[m]; + y[l] = r; + } + if (projection_4d == DISP_4D_ORTHOGRAPHIC) + { + for (l=0; l<3; l++) + p[l] = y[l]+kb->offset4d[l]; + } + else + { + s = y[3]+kb->offset4d[3]; + for (l=0; l<3; l++) + p[l] = (y[l]+kb->offset4d[l])/s; + } + + kb->offset3d[0] = -p[0]; + kb->offset3d[1] = -p[1]-DELTAY; + kb->offset3d[2] = -p[2]; + } + else + { + /* Compute the rotation that rotates the Klein bottle in 4D, including + the trackball rotations. */ + rotateall(kb->alpha,kb->beta,kb->delta,kb->zeta,kb->eta,kb->theta,r1); + + gltrackball_get_quaternion(kb->trackballs[0],q1); + gltrackball_get_quaternion(kb->trackballs[1],q2); + quats_to_rotmat(q1,q2,r2); + + mult_rotmat(r2,r1,mat); + } + + /* Project the points from 4D to 3D. */ + for (i=0; i<=NUMV; i++) + { + for (j=0; j<=NUMU; j++) + { + o = i*(NUMU+1)+j; + for (l=0; l<4; l++) + { + y[l] = (mat[l][0]*kb->x[o][0]+mat[l][1]*kb->x[o][1]+ + mat[l][2]*kb->x[o][2]+mat[l][3]*kb->x[o][3]); + yu[l] = (mat[l][0]*kb->xu[o][0]+mat[l][1]*kb->xu[o][1]+ + mat[l][2]*kb->xu[o][2]+mat[l][3]*kb->xu[o][3]); + yv[l] = (mat[l][0]*kb->xv[o][0]+mat[l][1]*kb->xv[o][1]+ + mat[l][2]*kb->xv[o][2]+mat[l][3]*kb->xv[o][3]); + } + if (projection_4d == DISP_4D_ORTHOGRAPHIC) + { + for (l=0; l<3; l++) + { + kb->pp[o][l] = (y[l]+kb->offset4d[l])+kb->offset3d[l]; + pu[l] = yu[l]; + pv[l] = yv[l]; + } + } + else + { + s = y[3]+kb->offset4d[3]; + q = 1.0/s; + t = q*q; + for (l=0; l<3; l++) + { + r = y[l]+kb->offset4d[l]; + kb->pp[o][l] = r*q+kb->offset3d[l]; + pu[l] = (yu[l]*s-r*yu[3])*t; + pv[l] = (yv[l]*s-r*yv[3])*t; + } + } + kb->pn[o][0] = pu[1]*pv[2]-pu[2]*pv[1]; + kb->pn[o][1] = pu[2]*pv[0]-pu[0]*pv[2]; + kb->pn[o][2] = pu[0]*pv[1]-pu[1]*pv[0]; + t = 1.0/sqrt(kb->pn[o][0]*kb->pn[o][0]+kb->pn[o][1]*kb->pn[o][1]+ + kb->pn[o][2]*kb->pn[o][2]); + kb->pn[o][0] *= t; + kb->pn[o][1] *= t; + kb->pn[o][2] *= t; + } + } + + if (colors == COLORS_TWOSIDED) + { + glColor3fv(mat_diff_red); + if (display_mode == DISP_TRANSPARENT) + { + glMaterialfv(GL_FRONT,GL_AMBIENT_AND_DIFFUSE,mat_diff_trans_red); + glMaterialfv(GL_BACK,GL_AMBIENT_AND_DIFFUSE,mat_diff_trans_green); + } + else + { + glMaterialfv(GL_FRONT,GL_AMBIENT_AND_DIFFUSE,mat_diff_red); + glMaterialfv(GL_BACK,GL_AMBIENT_AND_DIFFUSE,mat_diff_green); + } + } + glBindTexture(GL_TEXTURE_2D,kb->tex_name); + + for (i=0; i= NUMB/2)) + continue; + if (display_mode == DISP_WIREFRAME) + glBegin(GL_QUAD_STRIP); + else + glBegin(GL_TRIANGLE_STRIP); + for (j=0; j<=NUMU; j++) + { + for (k=0; k<=1; k++) + { + l = (i+k); + m = j; + o = l*(NUMU+1)+m; + glNormal3fv(kb->pn[o]); + glTexCoord2fv(kb->tex[o]); + if (colors != COLORS_TWOSIDED) + { + glColor3fv(kb->col[o]); + glMaterialfv(GL_FRONT_AND_BACK,GL_AMBIENT_AND_DIFFUSE,kb->col[o]); + } + glVertex3fv(kb->pp[o]); + polys++; + } + } + glEnd(); + } + polys /= 2; + return polys; +} + + +/* Generate a texture image that shows the orientation reversal. */ +static void gen_texture(ModeInfo *mi) +{ + kleinstruct *kb = &klein[MI_SCREEN(mi)]; + + glGenTextures(1,&kb->tex_name); + glBindTexture(GL_TEXTURE_2D,kb->tex_name); + glPixelStorei(GL_UNPACK_ALIGNMENT,1); + 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); + glTexEnvf(GL_TEXTURE_ENV,GL_TEXTURE_ENV_MODE,GL_MODULATE); + glTexImage2D(GL_TEXTURE_2D,0,GL_RGB,TEX_DIMENSION,TEX_DIMENSION,0, + GL_LUMINANCE,GL_UNSIGNED_BYTE,texture); +} + + +static void init(ModeInfo *mi) +{ + static const GLfloat light_ambient[] = { 0.0, 0.0, 0.0, 1.0 }; + static const GLfloat light_diffuse[] = { 1.0, 1.0, 1.0, 1.0 }; + static const GLfloat light_specular[] = { 1.0, 1.0, 1.0, 1.0 }; + static const GLfloat light_position[] = { 1.0, 1.0, 1.0, 0.0 }; + static const GLfloat mat_specular[] = { 1.0, 1.0, 1.0, 1.0 }; + kleinstruct *kb = &klein[MI_SCREEN(mi)]; + + if (walk_speed == 0.0) + walk_speed = 20.0; + + if (view == VIEW_TURN) + { + kb->alpha = frand(360.0); + kb->beta = frand(360.0); + kb->delta = frand(360.0); + } + else + { + kb->alpha = 0.0; + kb->beta = 0.0; + kb->delta = 0.0; + } + kb->zeta = 0.0; + if (bottle_type == KLEIN_BOTTLE_FIGURE_8) + kb->eta = 0.0; + else + kb->eta = 45.0; + kb->theta = 0.0; + kb->umove = frand(2.0*M_PI); + kb->vmove = frand(2.0*M_PI); + kb->dumove = 0.0; + kb->dvmove = 0.0; + kb->side = 1; + + if (bottle_type == KLEIN_BOTTLE_FIGURE_8) + { + kb->offset4d[0] = 0.0; + kb->offset4d[1] = 0.0; + kb->offset4d[2] = 0.0; + kb->offset4d[3] = 1.5; + kb->offset3d[0] = 0.0; + kb->offset3d[1] = 0.0; + if (projection_4d == DISP_4D_ORTHOGRAPHIC) + kb->offset3d[2] = -2.1; + else + kb->offset3d[2] = -1.9; + kb->offset3d[3] = 0.0; + } + else + { + kb->offset4d[0] = 0.0; + kb->offset4d[1] = 0.0; + kb->offset4d[2] = 0.0; + if (projection_4d == DISP_4D_PERSPECTIVE && + projection_3d == DISP_3D_ORTHOGRAPHIC) + kb->offset4d[3] = 1.5; + else + kb->offset4d[3] = 1.1; + kb->offset3d[0] = 0.0; + kb->offset3d[1] = 0.0; + if (projection_4d == DISP_4D_ORTHOGRAPHIC) + kb->offset3d[2] = -2.0; + else + kb->offset3d[2] = -5.0; + kb->offset3d[3] = 0.0; + } + + gen_texture(mi); + if (bottle_type == KLEIN_BOTTLE_FIGURE_8) + setup_figure8(mi,0.0,2.0*M_PI,0.0,2.0*M_PI); + else + setup_lawson(mi,0.0,2.0*M_PI,0.0,2.0*M_PI); + + if (marks) + glEnable(GL_TEXTURE_2D); + else + glDisable(GL_TEXTURE_2D); + + glMatrixMode(GL_PROJECTION); + glLoadIdentity(); + if (projection_3d == DISP_3D_PERSPECTIVE || + view == VIEW_WALK || view == VIEW_WALKTURN) + { + if (view == VIEW_WALK || view == VIEW_WALKTURN) + gluPerspective(60.0,1.0,0.01,10.0); + else + gluPerspective(60.0,1.0,0.1,10.0); + } + else + { + glOrtho(-1.0,1.0,-1.0,1.0,0.1,10.0); + } + glMatrixMode(GL_MODELVIEW); + glLoadIdentity(); + +# ifdef HAVE_JWZGLES /* #### glPolygonMode other than GL_FILL unimplemented */ + if (display_mode == DISP_WIREFRAME) + display_mode = DISP_SURFACE; +# endif + + if (display_mode == DISP_SURFACE) + { + glEnable(GL_DEPTH_TEST); + glDepthFunc(GL_LESS); + glShadeModel(GL_SMOOTH); + glPolygonMode(GL_FRONT_AND_BACK,GL_FILL); + glLightModeli(GL_LIGHT_MODEL_TWO_SIDE,GL_TRUE); + glEnable(GL_LIGHTING); + glEnable(GL_LIGHT0); + glLightfv(GL_LIGHT0,GL_AMBIENT,light_ambient); + glLightfv(GL_LIGHT0,GL_DIFFUSE,light_diffuse); + glLightfv(GL_LIGHT0,GL_SPECULAR,light_specular); + glLightfv(GL_LIGHT0,GL_POSITION,light_position); + glMaterialfv(GL_FRONT_AND_BACK,GL_SPECULAR,mat_specular); + glMaterialf(GL_FRONT_AND_BACK,GL_SHININESS,50.0); + glDepthMask(GL_TRUE); + glDisable(GL_BLEND); + } + else if (display_mode == DISP_TRANSPARENT) + { + glDisable(GL_DEPTH_TEST); + glShadeModel(GL_SMOOTH); + glPolygonMode(GL_FRONT_AND_BACK,GL_FILL); + glLightModeli(GL_LIGHT_MODEL_TWO_SIDE,GL_TRUE); + glEnable(GL_LIGHTING); + glEnable(GL_LIGHT0); + glLightfv(GL_LIGHT0,GL_AMBIENT,light_ambient); + glLightfv(GL_LIGHT0,GL_DIFFUSE,light_diffuse); + glLightfv(GL_LIGHT0,GL_SPECULAR,light_specular); + glLightfv(GL_LIGHT0,GL_POSITION,light_position); + glMaterialfv(GL_FRONT_AND_BACK,GL_SPECULAR,mat_specular); + glMaterialf(GL_FRONT_AND_BACK,GL_SHININESS,50.0); + glDepthMask(GL_FALSE); + glEnable(GL_BLEND); + glBlendFunc(GL_SRC_ALPHA,GL_ONE); + } + else /* display_mode == DISP_WIREFRAME */ + { + glDisable(GL_DEPTH_TEST); + glShadeModel(GL_FLAT); + glPolygonMode(GL_FRONT_AND_BACK,GL_LINE); + glDisable(GL_LIGHTING); + glDisable(GL_LIGHT0); + glDisable(GL_BLEND); + } +} + + +/* Redisplay the Klein bottle. */ +static void display_klein(ModeInfo *mi) +{ + kleinstruct *kb = &klein[MI_SCREEN(mi)]; + + if (!kb->button_pressed) + { + if (view == VIEW_TURN) + { + kb->alpha += speed_wx * kb->speed_scale; + if (kb->alpha >= 360.0) + kb->alpha -= 360.0; + kb->beta += speed_wy * kb->speed_scale; + if (kb->beta >= 360.0) + kb->beta -= 360.0; + kb->delta += speed_wz * kb->speed_scale; + if (kb->delta >= 360.0) + kb->delta -= 360.0; + kb->zeta += speed_xy * kb->speed_scale; + if (kb->zeta >= 360.0) + kb->zeta -= 360.0; + kb->eta += speed_xz * kb->speed_scale; + if (kb->eta >= 360.0) + kb->eta -= 360.0; + kb->theta += speed_yz * kb->speed_scale; + if (kb->theta >= 360.0) + kb->theta -= 360.0; + } + if (view == VIEW_WALKTURN) + { + kb->zeta += speed_xy * kb->speed_scale; + if (kb->zeta >= 360.0) + kb->zeta -= 360.0; + kb->eta += speed_xz * kb->speed_scale; + if (kb->eta >= 360.0) + kb->eta -= 360.0; + kb->theta += speed_yz * kb->speed_scale; + if (kb->theta >= 360.0) + kb->theta -= 360.0; + } + if (view == VIEW_WALK || view == VIEW_WALKTURN) + { + kb->dvmove = cos(walk_direction*M_PI/180.0)*walk_speed*M_PI/4096.0; + kb->vmove += kb->dvmove; + if (kb->vmove >= 2.0*M_PI) + { + kb->vmove -= 2.0*M_PI; + kb->umove = 2.0*M_PI-kb->umove; + kb->side = -kb->side; + } + kb->dumove = (kb->side*sin(walk_direction*M_PI/180.0)* + walk_speed*M_PI/4096.0); + kb->umove += kb->dumove; + if (kb->umove >= 2.0*M_PI) + kb->umove -= 2.0*M_PI; + if (kb->umove < 0.0) + kb->umove += 2.0*M_PI; + } + } + + glMatrixMode(GL_PROJECTION); + glLoadIdentity(); + if (projection_3d == DISP_3D_PERSPECTIVE || + view == VIEW_WALK || view == VIEW_WALKTURN) + { + if (view == VIEW_WALK || view == VIEW_WALKTURN) + gluPerspective(60.0,kb->aspect,0.01,10.0); + else + gluPerspective(60.0,kb->aspect,0.1,10.0); + } + else + { + if (kb->aspect >= 1.0) + glOrtho(-kb->aspect,kb->aspect,-1.0,1.0,0.1,10.0); + else + glOrtho(-1.0,1.0,-1.0/kb->aspect,1.0/kb->aspect,0.1,10.0); + } + glMatrixMode(GL_MODELVIEW); + glLoadIdentity(); + + if (bottle_type == KLEIN_BOTTLE_FIGURE_8) + mi->polygon_count = figure8(mi,0.0,2.0*M_PI,0.0,2.0*M_PI); + else + mi->polygon_count = lawson(mi,0.0,2.0*M_PI,0.0,2.0*M_PI); +} + + +ENTRYPOINT void reshape_klein(ModeInfo *mi, int width, int height) +{ + kleinstruct *kb = &klein[MI_SCREEN(mi)]; + + kb->WindW = (GLint)width; + kb->WindH = (GLint)height; + glViewport(0,0,width,height); + kb->aspect = (GLfloat)width/(GLfloat)height; +} + + +ENTRYPOINT Bool klein_handle_event(ModeInfo *mi, XEvent *event) +{ + kleinstruct *kb = &klein[MI_SCREEN(mi)]; + KeySym sym = 0; + char c = 0; + + if (event->xany.type == KeyPress || event->xany.type == KeyRelease) + XLookupString (&event->xkey, &c, 1, &sym, 0); + + if (event->xany.type == ButtonPress && + event->xbutton.button == Button1) + { + kb->button_pressed = True; + gltrackball_start(kb->trackballs[kb->current_trackball], + event->xbutton.x, event->xbutton.y, + MI_WIDTH(mi), MI_HEIGHT(mi)); + return True; + } + else if (event->xany.type == ButtonRelease && + event->xbutton.button == Button1) + { + kb->button_pressed = False; + return True; + } + else if (event->xany.type == KeyPress) + { + if (sym == XK_Shift_L || sym == XK_Shift_R) + { + kb->current_trackball = 1; + if (kb->button_pressed) + gltrackball_start(kb->trackballs[kb->current_trackball], + event->xbutton.x, event->xbutton.y, + MI_WIDTH(mi), MI_HEIGHT(mi)); + return True; + } + } + else if (event->xany.type == KeyRelease) + { + if (sym == XK_Shift_L || sym == XK_Shift_R) + { + kb->current_trackball = 0; + if (kb->button_pressed) + gltrackball_start(kb->trackballs[kb->current_trackball], + event->xbutton.x, event->xbutton.y, + MI_WIDTH(mi), MI_HEIGHT(mi)); + return True; + } + } + else if (event->xany.type == MotionNotify && kb->button_pressed) + { + gltrackball_track(kb->trackballs[kb->current_trackball], + event->xmotion.x, event->xmotion.y, + MI_WIDTH(mi), MI_HEIGHT(mi)); + return True; + } + + return False; +} + + +/* + *----------------------------------------------------------------------------- + *----------------------------------------------------------------------------- + * Xlock hooks. + *----------------------------------------------------------------------------- + *----------------------------------------------------------------------------- + */ + +/* + *----------------------------------------------------------------------------- + * Initialize klein. Called each time the window changes. + *----------------------------------------------------------------------------- + */ + +ENTRYPOINT void init_klein(ModeInfo *mi) +{ + kleinstruct *kb; + + if (klein == NULL) + { + klein = (kleinstruct *)calloc(MI_NUM_SCREENS(mi), + sizeof(kleinstruct)); + if (klein == NULL) + return; + } + kb = &klein[MI_SCREEN(mi)]; + + + kb->trackballs[0] = gltrackball_init(); + kb->trackballs[1] = gltrackball_init(); + kb->current_trackball = 0; + kb->button_pressed = False; + + /* Set the Klein bottle. */ + if (!strcasecmp(klein_bottle,"random")) + { + bottle_type = random() % NUM_KLEIN_BOTTLES; + } + else if (!strcasecmp(klein_bottle,"figure-8")) + { + bottle_type = KLEIN_BOTTLE_FIGURE_8; + } + else if (!strcasecmp(klein_bottle,"lawson")) + { + bottle_type = KLEIN_BOTTLE_LAWSON; + } + else + { + bottle_type = random() % NUM_KLEIN_BOTTLES; + } + + /* Set the display mode. */ + if (!strcasecmp(mode,"random")) + { + display_mode = random() % NUM_DISPLAY_MODES; + } + else if (!strcasecmp(mode,"wireframe")) + { + display_mode = DISP_WIREFRAME; + } + else if (!strcasecmp(mode,"surface")) + { + display_mode = DISP_SURFACE; + } + else if (!strcasecmp(mode,"transparent")) + { + display_mode = DISP_TRANSPARENT; + } + else + { + display_mode = random() % NUM_DISPLAY_MODES; + } + + /* Orientation marks don't make sense in wireframe mode. */ + if (display_mode == DISP_WIREFRAME) + marks = False; + + /* Set the appearance. */ + if (!strcasecmp(appear,"random")) + { + appearance = random() % NUM_APPEARANCES; + } + else if (!strcasecmp(appear,"solid")) + { + appearance = APPEARANCE_SOLID; + } + else if (!strcasecmp(appear,"bands")) + { + appearance = APPEARANCE_BANDS; + } + else + { + appearance = random() % NUM_APPEARANCES; + } + + /* Set the color mode. */ + if (!strcasecmp(color_mode,"random")) + { + colors = random() % NUM_COLORS; + } + else if (!strcasecmp(color_mode,"two-sided")) + { + colors = COLORS_TWOSIDED; + } + else if (!strcasecmp(color_mode,"rainbow")) + { + colors = COLORS_RAINBOW; + } + else if (!strcasecmp(color_mode,"depth")) + { + colors = COLORS_DEPTH; + } + else + { + colors = random() % NUM_COLORS; + } + + /* Set the view mode. */ + if (!strcasecmp(view_mode,"random")) + { + view = random() % NUM_VIEW_MODES; + } + else if (!strcasecmp(view_mode,"walk")) + { + view = VIEW_WALK; + } + else if (!strcasecmp(view_mode,"turn")) + { + view = VIEW_TURN; + } + else if (!strcasecmp(view_mode,"walk-turn")) + { + view = VIEW_WALKTURN; + } + else + { + view = random() % NUM_VIEW_MODES; + } + + /* Set the 3d projection mode. */ + if (!strcasecmp(proj_3d,"random")) + { + /* Orthographic projection only makes sense in turn mode. */ + if (view == VIEW_TURN) + projection_3d = random() % NUM_DISP_3D_MODES; + else + projection_3d = DISP_3D_PERSPECTIVE; + } + else if (!strcasecmp(proj_3d,"perspective")) + { + projection_3d = DISP_3D_PERSPECTIVE; + } + else if (!strcasecmp(proj_3d,"orthographic")) + { + projection_3d = DISP_3D_ORTHOGRAPHIC; + } + else + { + /* Orthographic projection only makes sense in turn mode. */ + if (view == VIEW_TURN) + projection_3d = random() % NUM_DISP_3D_MODES; + else + projection_3d = DISP_3D_PERSPECTIVE; + } + + /* Set the 4d projection mode. */ + if (!strcasecmp(proj_4d,"random")) + { + projection_4d = random() % NUM_DISP_4D_MODES; + } + else if (!strcasecmp(proj_4d,"perspective")) + { + projection_4d = DISP_4D_PERSPECTIVE; + } + else if (!strcasecmp(proj_4d,"orthographic")) + { + projection_4d = DISP_4D_ORTHOGRAPHIC; + } + else + { + projection_4d = random() % NUM_DISP_4D_MODES; + } + + /* Modify the speeds to a useful range in walk-and-turn mode. */ + if (view == VIEW_WALKTURN) + { + speed_wx *= 0.2; + speed_wy *= 0.2; + speed_wz *= 0.2; + speed_xy *= 0.2; + speed_xz *= 0.2; + speed_yz *= 0.2; + } + + /* make multiple screens rotate at slightly different rates. */ + kb->speed_scale = 0.9 + frand(0.3); + + if ((kb->glx_context = init_GL(mi)) != NULL) + { + reshape_klein(mi,MI_WIDTH(mi),MI_HEIGHT(mi)); + glDrawBuffer(GL_BACK); + init(mi); + } + else + { + MI_CLEARWINDOW(mi); + } +} + +/* + *----------------------------------------------------------------------------- + * Called by the mainline code periodically to update the display. + *----------------------------------------------------------------------------- + */ +ENTRYPOINT void draw_klein(ModeInfo *mi) +{ + Display *display = MI_DISPLAY(mi); + Window window = MI_WINDOW(mi); + kleinstruct *kb; + + if (klein == NULL) + return; + kb = &klein[MI_SCREEN(mi)]; + + MI_IS_DRAWN(mi) = True; + if (!kb->glx_context) + return; + + glXMakeCurrent(display,window,*(kb->glx_context)); + + glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT); + glLoadIdentity(); + + display_klein(mi); + + if (MI_IS_FPS(mi)) + do_fps (mi); + + glFlush(); + + glXSwapBuffers(display,window); +} + + +/* + *----------------------------------------------------------------------------- + * The display is being taken away from us. Free up malloc'ed + * memory and X resources that we've alloc'ed. Only called + * once, we must zap everything for every screen. + *----------------------------------------------------------------------------- + */ + +ENTRYPOINT void release_klein(ModeInfo *mi) +{ + if (klein != NULL) + { + int screen; + + for (screen = 0; screen < MI_NUM_SCREENS(mi); screen++) + { + kleinstruct *kb = &klein[screen]; + + if (kb->glx_context) + kb->glx_context = (GLXContext *)NULL; + } + (void) free((void *)klein); + klein = (kleinstruct *)NULL; + } + FreeAllGL(mi); +} + +#ifndef STANDALONE +ENTRYPOINT void change_klein(ModeInfo *mi) +{ + kleinstruct *kb = &klein[MI_SCREEN(mi)]; + + if (!kb->glx_context) + return; + + glXMakeCurrent(MI_DISPLAY(mi),MI_WINDOW(mi),*(kb->glx_context)); + init(mi); +} +#endif /* !STANDALONE */ + +XSCREENSAVER_MODULE ("Klein", klein) + +#endif /* USE_GL */ diff --git a/hacks/glx/klein.man b/hacks/glx/klein.man new file mode 100644 index 00000000..de4fd480 --- /dev/null +++ b/hacks/glx/klein.man @@ -0,0 +1,299 @@ +.TH XScreenSaver 1 "" "X Version 11" +.SH NAME +kleinbottle - Draws a 4d Klein bottle. +.SH SYNOPSIS +.B kleinbottle +[\-display \fIhost:display.screen\fP] +[\-install] +[\-visual \fIvisual\fP] +[\-window] +[\-root] +[\-delay \fIusecs\fP] +[\-fps] +[\-klein-bottle \fIbottle-name\fP] +[-figure-8] +[-lawson] +[\-mode \fIdisplay-mode\fP] +[\-wireframe] +[\-surface] +[\-transparent] +[\-appearance \fIappearance\fP] +[\-solid] +[\-bands] +[\-colors \fIcolor-scheme\fP] +[\-twosided] +[\-rainbow] +[\-depth] +[\-view-mode \fIview-mode\fP] +[\-walk] +[\-turn] +[\-walk-turn] +[\-orientation-marks] +[\-projection-3d \fImode\fP] +[\-perspective-3d] +[\-orthographic-3d] +[\-projection-4d \fImode\fP] +[\-perspective-4d] +[\-orthographic-4d] +[\-speed-wx \fIfloat\fP] +[\-speed-wy \fIfloat\fP] +[\-speed-wz \fIfloat\fP] +[\-speed-xy \fIfloat\fP] +[\-speed-xz \fIfloat\fP] +[\-speed-yz \fIfloat\fP] +[\-walk-direction \fIfloat\fP] +[\-walk-speed \fIfloat\fP] +.SH DESCRIPTION +The \fIkleinbottle\fP program shows two different Klein bottles in 4d: +the figure-8 Klein bottle or the Lawson Klein bottle. You can walk on +the Klein bottle, see it turn in 4d, or walk on it while it turns in +4d. The figure-8 Klein bottle is well known in its 3d form. The 4d +form used in this program is an extension of the 3d form to 4d that +does not intersect itself in 4d (which can be seen in the depth colors +mode). The Lawson Klein bottle, on the other hand, does intersect +itself in 4d. Its primary use is that it has a nice appearance for +walking and for turning in 3d. The Klein bottle is a non-orientable +surface. To make this apparent, the two-sided color mode can be used. +Alternatively, orientation markers (curling arrows) can be drawn as a +texture map on the surface of the Klein bottle. While walking on the +Klein bottle, you will notice that the orientation of the curling +arrows changes (which it must because the Klein bottle is +non-orientable). The program projects the 4d Klein bottle to 3d using +either a perspective or an orthographic projection. Which of the two +alternatives looks more appealing depends on the viewing mode and the +Klein bottle. For example, the Lawson Klein bottle looks nicest when +projected perspectively. The figure-8 Klein bottle, on the other +hand, looks nicer while walking when projected orthographically from +4d. The projected Klein bottle can then be projected to the screen +either perspectively or orthographically. When using the walking +modes, perspective projection to the screen should be used. There are +three display modes for the Klein bottle: mesh (wireframe), solid, or +transparent. Furthermore, the appearance of the Klein bottle can be +as a solid object or as a set of see-through bands. Finally, the +colors with with the Klein bottle is drawn can be set to two-sided, +rainbow, or depth. In the first case, the Klein bottle is drawn with +red on one "side" and green on the "other side". Of course, the Klein +bottle only has one side, so the color jumps from red to green along a +curve on the surface of the Klein bottle. This mode enables you to +see that the Klein bottle is non-orientable. The second mode draws +the Klein bottle with fully saturated rainbow colors. This gives a +very nice effect when combined with the see-through bands mode or with +the orientation markers drawn. The third mode draws the Klein bottle +with colors that are chosen according to the 4d "depth" of the points. +This mode enables you to see that the figure-8 Klein bottle does not +intersect itself in 4d, while the Lawson Klein bottle does intersect +itself. The rotation speed for each of the six planes around which +the Klein bottle rotates can be chosen. For the walk-and-turn more, +only the rotation speeds around the true 4d planes are used (the xy, +xz, and yz planes). Furthermore, in the walking modes the walking +direction in the 2d base square of the Klein bottle and the walking +speed can be chosen. This program is somewhat inspired by Thomas +Banchoff's book "Beyond the Third Dimension: Geometry, Computer +Graphics, and Higher Dimensions", Scientific American Library, 1990. +.SH OPTIONS +.I kleinbottle +accepts the following options: +.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 \-install +Install a private colormap for the window. +.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 \-delay \fImicroseconds\fP +How much of a delay should be introduced between steps of the +animation. Default 10000, or 1/100th second. +.TP 8 +.B \-fps +Display the current frame rate, CPU load, and polygon count. +.PP +The following three options are mutually exclusive. They determine +which Klein bottle is displayed. +.TP 8 +.B \-klein-bottle random +Display a random Klein bottle (default). +.TP 8 +.B \-klein-bottle figure-8 \fP(Shortcut: \fB\-figure-8\fP) +Display the figure-8 Klein bottle. +.TP 8 +.B \-klein-bottle lawson \fP(Shortcut: \fB\-lawson\fP) +Display the Lawson Klein bottle. +.PP +The following four options are mutually exclusive. They determine +how the Klein bottle is displayed. +.TP 8 +.B \-mode random +Display the Klein bottle in a random display mode (default). +.TP 8 +.B \-mode wireframe \fP(Shortcut: \fB\-wireframe\fP) +Display the Klein bottle as a wireframe mesh. +.TP 8 +.B \-mode surface \fP(Shortcut: \fB\-surface\fP) +Display the Klein bottle as a solid surface. +.TP 8 +.B \-mode transparent \fP(Shortcut: \fB\-transparent\fP) +Display the Klein bottle as a transparent surface. +.PP +The following three options are mutually exclusive. They determine the +appearance of the Klein bottle. +.TP 8 +.B \-appearance random +Display the Klein bottle with a random appearance (default). +.TP 8 +.B \-appearance solid \fP(Shortcut: \fB\-solid\fP) +Display the Klein bottle as a solid object. +.TP 8 +.B \-appearance bands \fP(Shortcut: \fB\-bands\fP) +Display the Klein bottle as see-through bands. +.PP +The following four options are mutually exclusive. They determine +how to color the Klein bottle. +.TP 8 +.B \-colors random +Display the Klein bottle with a random color scheme (default). +.TP 8 +.B \-colors twosided \fP(Shortcut: \fB\-twosided\fP) +Display the Klein bottle with two colors: red on one "side" and green +on the "other side". +.TP 8 +.B \-colors rainbow \fP(Shortcut: \fB\-rainbow\fP) +Display the Klein bottle with fully saturated rainbow colors. If the +Klein bottle is displayed as see-through bands, each band will be +displayed with a different color. +.TP 8 +.B \-colors depth \fP(Shortcut: \fB\-depth\fP) +Display the Klein bottle with colors chosen depending on the 4d +"depth" of the points. +.PP +The following four options are mutually exclusive. They determine +how to view the Klein bottle. +.TP 8 +.B \-view-mode random +View the Klein bottle in a random view mode (default). +.TP 8 +.B \-view-mode walk \fP(Shortcut: \fB\-walk\fP) +View the Klein bottle as if walking on its surface. +.TP 8 +.B \-view-mode turn \fP(Shortcut: \fB\-turn\fP) +View the Klein bottle while it turns in 4d. +.TP 8 +.B \-view-mode walk-turn \fP(Shortcut: \fB\-walk-turn\fP) +View the Klein bottle as if walking on its surface. Additionally, the +Klein bottle turns around the true 4d planes (the xy, xz, and yz +planes). +.PP +The following options determine whether orientation marks are shown on +the Klein bottle. +.TP 8 +.B \-orientation-marks +Display orientation marks on the Klein bottle. +.TP 8 +.B \-no-orientation-marks +Don't display orientation marks on the Klein bottle (default). +.PP +The following three options are mutually exclusive. They determine +how the Klein bottle is projected from 3d to 2d (i.e., to the screen). +.TP 8 +.B \-projection-3d random +Project the Klein bottle from 3d to 2d using a random projection mode +(default). +.TP 8 +.B \-projection-3d perspective \fP(Shortcut: \fB\-perspective-3d\fP) +Project the Klein bottle from 3d to 2d using a perspective projection. +.TP 8 +.B \-projection-3d orthographic \fP(Shortcut: \fB\-orthographic-3d\fP) +Project the Klein bottle from 3d to 2d using an orthographic +projection. +.PP +The following three options are mutually exclusive. They determine +how the Klein bottle is projected from 4d to 3d. +.TP 8 +.B \-projection-4d random +Project the Klein bottle from 4d to 3d using a random projection mode +(default). +.TP 8 +.B \-projection-4d perspective \fP(Shortcut: \fB\-perspective-4d\fP) +Project the Klein bottle from 4d to 3d using a perspective projection. +.TP 8 +.B \-projection-4d orthographic \fP(Shortcut: \fB\-orthographic-4d\fP) +Project the Klein bottle from 4d to 3d using an orthographic +projection. +.PP +The following six options determine the rotation speed of the Klein +bottle around the six possible hyperplanes. The rotation speed is +measured in degrees per frame. The speeds should be set to relatively +small values, e.g., less than 4 in magnitude. In walk mode, all +speeds are ignored. In walk-and-turn mode, the 3d rotation speeds are +ignored (i.e., the wx, wy, and wz speeds). In walk-and-turn mode, +smaller speeds must be used than in the turn mode to achieve a nice +visualization. Therefore, in walk-and-turn mode the speeds you have +selected are divided by 5 internally. +.TP 8 +.B \-speed-wx \fIfloat\fP +Rotation speed around the wx plane (default: 1.1). +.TP 8 +.B \-speed-wy \fIfloat\fP +Rotation speed around the wy plane (default: 1.3). +.TP 8 +.B \-speed-wz \fIfloat\fP +Rotation speed around the wz plane (default: 1.5). +.TP 8 +.B \-speed-xy \fIfloat\fP +Rotation speed around the xy plane (default: 1.7). +.TP 8 +.B \-speed-xz \fIfloat\fP +Rotation speed around the xz plane (default: 1.9). +.TP 8 +.B \-speed-yz \fIfloat\fP +Rotation speed around the yz plane (default: 2.1). +.PP +The following two options determine the walking speed and direction. +.TP 8 +.B \-walk-direction \fIfloat\fP +The walking direction is measured as an angle in degrees in the 2d +square that forms the coordinate system of the surface of the Klein +bottle (default: 7.0). +.TP 8 +.B \-walk-speed \fIfloat\fP +The walking speed is measured in percent of some sensible maximum +speed (default: 20.0). +.SH INTERACTION +If you run this program in standalone mode in its turn mode, you can +rotate the Klein bottle by dragging the mouse while pressing the left +mouse button. This rotates the Klein bottle in 3D, i.e., around the +wx, wy, and wz planes. If you press the shift key while dragging the +mouse with the left button pressed the Klein bottle is rotated in 4D, +i.e., around the xy, xz, and yz planes. To examine the Klein bottle +at your leisure, it is best to set all speeds to 0. Otherwise, the +Klein bottle will rotate while the left mouse button is not pressed. +This kind of interaction is not available in the two walk modes. +.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 2005-2009 by Carsten Steger. 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 +Carsten Steger , 03-aug-2009. diff --git a/hacks/glx/lament.c b/hacks/glx/lament.c new file mode 100644 index 00000000..97202c1d --- /dev/null +++ b/hacks/glx/lament.c @@ -0,0 +1,2062 @@ +/* xscreensaver, Copyright (c) 1998-2012 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. + */ + +/* Animates Lemarchand's Box, the Lament Configuration. By jwz, 25-Jul-98. + + TODO: + + * The "gold" color isn't quite right; it looks more like "yellow" than + "gold" to me. + + * For some reason, the interior surfaces are shinier than the exterior + surfaces. Not sure why. + + * Should use a dark wood-grain texture for the interior surfaces. + + * Building a face out of multiple adjacent triangles was a terrible + idea and leads to visible seams. Should re-do the face generation + to make all of them out of a single triangle strip instead. + + * The coordinates are slightly off from the image. lament512.gif is the + "right" one, and "lament512b.gif" is the image corrected to line up + with what the code is actually doing. + + * The "star" slices really don't line up well. + + * I want the gold leaf to seem to be raised up from the surface, but I + think this isn't possible with OpenGL. Supposedly, OpenGL only + supports Gouraud shading (interpolating edge normals from face normals, + and shading smoothly) but bump-maps only work with Phong shading + (computing a normal for each rendered pixel.) + + * There should be strange lighting effects playing across the surface: + electric sparks, or little glittery blobs of light. + http://reality.sgi.com/opengl/tips/lensflare/ might provide guidance. + + * Need to add some more modes, to effect the transition from the cube + shapes to the "spike" or "leviathan" shapes. I have extensive notes + on how these transformations occur, but unfortunately, due to camera + trickery, the transitions require dematerializations which do not + preserve object volume. But I suppose that's allowed, in + non-Euclidian or hyperdimensional spaces (since the extra mass could + simply be rotated along the axis to which one cannot point.) + + The other hard thing about this is that the "leviathan" shapes contain + a much larger number of facets, and I modelled this whole thing by + hand, since I don't have any 3d-object-editing tools that I know how + to use (or that look like they would take any less than several months + to become even marginally proficient with...) + + * Needs music. ("Hellraiser Themes" by Coil: TORSO CD161; also + duplicated on the "Unnatural History 2" compilation, WORLN M04699.) + */ + +#define DEFAULTS "*delay: 20000 \n" \ + "*showFPS: False \n" \ + "*wireframe: False \n" +# define refresh_lament 0 +# define release_lament 0 +#include "xlockmore.h" + +#ifdef USE_GL /* whole file */ + +#undef countof +#define countof(x) (sizeof((x))/sizeof((*x))) + +#define DEF_TEXTURE "True" + +static int do_texture; + +static XrmOptionDescRec opts[] = { + {"-texture", ".lament.texture", XrmoptionNoArg, "true" }, + {"+texture", ".lament.texture", XrmoptionNoArg, "false" }, +}; + +static argtype vars[] = { + {&do_texture, "texture", "Texture", DEF_TEXTURE, t_Bool}, +}; + +ENTRYPOINT ModeSpecOpt lament_opts = {countof(opts), opts, countof(vars), vars, NULL}; + +#include "normals.h" +#include "xpm-ximage.h" +#include "rotator.h" +#include "gltrackball.h" +#if 0 +# include "../images/lament128.xpm" +#else +# include "../images/lament512.xpm" +#endif + +#define RAND(n) ((long) ((random() & 0x7fffffff) % ((long) (n)))) +#define RANDSIGN() ((random() & 1) ? 1 : -1) + +typedef enum { + LAMENT_BOX, + + LAMENT_STAR_OUT, + LAMENT_STAR_ROT, + LAMENT_STAR_ROT_IN, + LAMENT_STAR_ROT_OUT, + LAMENT_STAR_UNROT, + LAMENT_STAR_IN, + + LAMENT_TETRA_UNE, + LAMENT_TETRA_USW, + LAMENT_TETRA_DWN, + LAMENT_TETRA_DSE, + + LAMENT_LID_OPEN, + LAMENT_LID_CLOSE, + LAMENT_LID_ZOOM, + + LAMENT_TASER_OUT, + LAMENT_TASER_SLIDE, + LAMENT_TASER_SLIDE_IN, + LAMENT_TASER_IN + +} lament_type; + +static const GLfloat exterior_color[] = + { 0.33, 0.22, 0.03, 1.00, /* ambient */ + 0.78, 0.57, 0.11, 1.00, /* specular */ + 0.99, 0.91, 0.81, 1.00, /* diffuse */ + 27.80 /* shininess */ + }; +static const GLfloat interior_color[] = + { 0.20, 0.20, 0.15, 1.00, /* ambient */ + 0.40, 0.40, 0.32, 1.00, /* specular */ + 0.99, 0.99, 0.81, 1.00, /* diffuse */ + 50.80 /* shininess */ + }; + + +typedef struct { + GLXContext *glx_context; + rotator *rot; + double rotx, roty, rotz; + trackball_state *trackball; + Bool button_down_p; + + GLuint box; /* display list IDs */ + GLuint star1, star2; + GLuint tetra_une, tetra_usw, tetra_dwn, tetra_dse, tetra_mid; + GLuint lid_0, lid_1, lid_2, lid_3, lid_4; + GLuint taser_base, taser_lifter, taser_slider; + + XImage *texture; /* image bits */ + GLuint texids[6]; /* texture map IDs */ + lament_type type; /* which mode of the object is current */ + + int anim_pause; /* countdown before animating again */ + GLfloat anim_r, anim_y, anim_z; /* relative position during anims */ + Bool facing_p; + + int state, nstates; + lament_type *states; + +} lament_configuration; + +static lament_configuration *lcs = NULL; + +#define FACE_N 3 +#define FACE_S 2 +#define FACE_E 0 +#define FACE_W 4 +#define FACE_U 5 +#define FACE_D 1 + +static void +parse_image_data(ModeInfo *mi) +{ + lament_configuration *lc = &lcs[MI_SCREEN(mi)]; + lc->texture = xpm_to_ximage (mi->dpy, + mi->xgwa.visual, + mi->xgwa.colormap, + lament_faces); +} + + +/* Shorthand utilities for making faces, with proper normals. + */ + +static void +set_colors (const GLfloat *color) +{ + glMaterialfv(GL_FRONT, GL_AMBIENT, color+0); + glMaterialfv(GL_FRONT, GL_DIFFUSE, color+4); + glMaterialfv(GL_FRONT, GL_SPECULAR, color+8); + glMaterialfv(GL_FRONT, GL_SHININESS, color+12); +} + +static void +face3(GLint texture, const GLfloat *color, Bool wire, + GLfloat s1, GLfloat t1, GLfloat x1, GLfloat y1, GLfloat z1, + GLfloat s2, GLfloat t2, GLfloat x2, GLfloat y2, GLfloat z2, + GLfloat s3, GLfloat t3, GLfloat x3, GLfloat y3, GLfloat z3) +{ +#ifdef HAVE_GLBINDTEXTURE + glBindTexture(GL_TEXTURE_2D, texture); +#endif /* HAVE_GLBINDTEXTURE */ + set_colors(color); + + do_normal(x1, y1, z1, x2, y2, z2, x3, y3, z3); + glBegin(wire ? GL_LINE_LOOP : GL_TRIANGLES); + glTexCoord2f(s1, t1); glVertex3f(x1, y1, z1); + glTexCoord2f(s2, t2); glVertex3f(x2, y2, z2); + glTexCoord2f(s3, t3); glVertex3f(x3, y3, z3); + glEnd(); +} + +static void +face4(GLint texture, const GLfloat *color, Bool wire, + GLfloat s1, GLfloat t1, GLfloat x1, GLfloat y1, GLfloat z1, + GLfloat s2, GLfloat t2, GLfloat x2, GLfloat y2, GLfloat z2, + GLfloat s3, GLfloat t3, GLfloat x3, GLfloat y3, GLfloat z3, + GLfloat s4, GLfloat t4, GLfloat x4, GLfloat y4, GLfloat z4) +{ +#ifdef HAVE_GLBINDTEXTURE + glBindTexture(GL_TEXTURE_2D, texture); +#endif /* HAVE_GLBINDTEXTURE */ + set_colors(color); + do_normal(x1, y1, z1, x2, y2, z2, x3, y3, z3); + glBegin(wire ? GL_LINE_LOOP : GL_QUADS); + glTexCoord2f(s1, t1); glVertex3f(x1, y1, z1); + glTexCoord2f(s2, t2); glVertex3f(x2, y2, z2); + glTexCoord2f(s3, t3); glVertex3f(x3, y3, z3); + glTexCoord2f(s4, t4); glVertex3f(x4, y4, z4); + glEnd(); +} + +static void +face5(GLint texture, const GLfloat *color, Bool wire, + GLfloat s1, GLfloat t1, GLfloat x1, GLfloat y1, GLfloat z1, + GLfloat s2, GLfloat t2, GLfloat x2, GLfloat y2, GLfloat z2, + GLfloat s3, GLfloat t3, GLfloat x3, GLfloat y3, GLfloat z3, + GLfloat s4, GLfloat t4, GLfloat x4, GLfloat y4, GLfloat z4, + GLfloat s5, GLfloat t5, GLfloat x5, GLfloat y5, GLfloat z5) +{ +#ifdef HAVE_GLBINDTEXTURE + glBindTexture(GL_TEXTURE_2D, texture); +#endif /* HAVE_GLBINDTEXTURE */ + set_colors(color); + do_normal(x1, y1, z1, x2, y2, z2, x3, y3, z3); + glBegin(wire ? GL_LINE_LOOP : GL_POLYGON); + glTexCoord2f(s1, t1); glVertex3f(x1, y1, z1); + glTexCoord2f(s2, t2); glVertex3f(x2, y2, z2); + glTexCoord2f(s3, t3); glVertex3f(x3, y3, z3); + glTexCoord2f(s4, t4); glVertex3f(x4, y4, z4); + glTexCoord2f(s5, t5); glVertex3f(x5, y5, z5); + glEnd(); +} + + + +/* Creating object models + */ + +static void +box(ModeInfo *mi, Bool wire) +{ + lament_configuration *lc = &lcs[MI_SCREEN(mi)]; + + glNewList(lc->box, GL_COMPILE); + glShadeModel(GL_SMOOTH); + + /* N */ + face4(lc->texids[FACE_N], exterior_color, wire, + 0.0, 0.0, -0.5, 0.5, 0.5, + 1.0, 0.0, 0.5, 0.5, 0.5, + 1.0, 1.0, 0.5, 0.5, -0.5, + 0.0, 1.0, -0.5, 0.5, -0.5); + + /* S */ + face4(lc->texids[FACE_S], exterior_color, wire, + 0.0, 0.0, -0.5, -0.5, -0.5, + 1.0, 0.0, 0.5, -0.5, -0.5, + 1.0, 1.0, 0.5, -0.5, 0.5, + 0.0, 1.0, -0.5, -0.5, 0.5); + + /* E */ + face4(lc->texids[FACE_E], exterior_color, wire, + 0.0, 0.0, 0.5, -0.5, -0.5, + 1.0, 0.0, 0.5, 0.5, -0.5, + 1.0, 1.0, 0.5, 0.5, 0.5, + 0.0, 1.0, 0.5, -0.5, 0.5); + + /* W */ + face4(lc->texids[FACE_W], exterior_color, wire, + 1.0, 1.0, -0.5, -0.5, 0.5, + 0.0, 1.0, -0.5, 0.5, 0.5, + 0.0, 0.0, -0.5, 0.5, -0.5, + 1.0, 0.0, -0.5, -0.5, -0.5); + + /* U */ + face4(lc->texids[FACE_U], exterior_color, wire, + 1.0, 0.0, 0.5, -0.5, 0.5, + 1.0, 1.0, 0.5, 0.5, 0.5, + 0.0, 1.0, -0.5, 0.5, 0.5, + 0.0, 0.0, -0.5, -0.5, 0.5); + + /* D */ + face4(lc->texids[FACE_D], exterior_color, wire, + 0.0, 1.0, -0.5, -0.5, -0.5, + 0.0, 0.0, -0.5, 0.5, -0.5, + 1.0, 0.0, 0.5, 0.5, -0.5, + 1.0, 1.0, 0.5, -0.5, -0.5); + + glEndList(); +} + + +static void +star(ModeInfo *mi, Bool top, Bool wire) +{ + lament_configuration *lc = &lcs[MI_SCREEN(mi)]; + int i; + + int points[][2] = { + { 77, 74 }, { 60, 99 }, { 0, 74 }, { 0, 0 }, /* L1 */ + { 60, 99 }, { 55, 127 }, { 0, 127 }, { 0, 74 }, /* L2 */ + { 55, 127 }, { 60, 154 }, { 0, 179 }, { 0, 127 }, /* L3 */ + { 60, 154 }, { 76, 176 }, { 0, 255 }, { 0, 179 }, /* L4 */ + { 76, 176 }, { 100, 193 }, { 74, 255 }, { 0, 255 }, /* B1 */ + { 100, 193 }, { 127, 198 }, { 127, 255 }, { 74, 255 }, /* B2 */ + { 127, 198 }, { 151, 193 }, { 180, 255 }, { 127, 255 }, /* B3 */ + { 151, 193 }, { 178, 177 }, { 255, 255 }, { 180, 255 }, /* B4 */ + { 178, 177 }, { 193, 155 }, { 255, 181 }, { 255, 255 }, /* R4 */ + { 193, 155 }, { 199, 127 }, { 255, 127 }, { 255, 181 }, /* R3 */ + { 199, 127 }, { 194, 99 }, { 255, 74 }, { 255, 127 }, /* R2 */ + { 194, 99 }, { 179, 76 }, { 255, 0 }, { 255, 74 }, /* R1 */ + { 179, 76 }, { 155, 60 }, { 180, 0 }, { 255, 0 }, /* T4 */ + { 155, 60 }, { 126, 55 }, { 126, 0 }, { 180, 0 }, /* T3 */ + { 126, 55 }, { 100, 60 }, { 75, 0 }, { 126, 0 }, /* T2 */ + { 100, 60 }, { 77, 74 }, { 0, 0 }, { 75, 0 }, /* T1 */ + }; + + for (i = 0; i < countof(points); i++) + points[i][1] = 255-points[i][1]; + + if (top) + glNewList(lc->star1, GL_COMPILE); + else + glNewList(lc->star2, GL_COMPILE); + + if (!top) + glRotatef(-180.0, 1.0, 0.0, 0.0); + + for (i = 0; i < countof(points)/4; i += 2) + { + int j, k; + + /* Top face. + */ + + GLfloat s[4], t[4], x[4], y[4], z[4]; + for (j = 3, k = 0; j >= 0; j--, k++) + { + GLfloat xx = points[(i*4)+j][0] / 255.0L; + GLfloat yy = points[(i*4)+j][1] / 255.0L; + s[k] = xx; + t[k] = yy; + x[k] = xx-0.5; + y[k] = yy-0.5; + z[k] = 0.5; + } + face4(lc->texids[top ? FACE_U : FACE_D], exterior_color, wire, + s[0], t[0], x[0], y[0], z[0], + s[1], t[1], x[1], y[1], z[1], + s[2], t[2], x[2], y[2], z[2], + s[3], t[3], x[3], y[3], z[3]); + + /* Bottom face. + */ + for (j = 0, k = 0; j < 4; j++, k++) + { + GLfloat xx = points[(i*4)+j][0] / 255.0L; + GLfloat yy = points[(i*4)+j][1] / 255.0L; + s[k] = xx; + t[k] = 1.0 - yy; + x[k] = xx-0.5; + y[k] = yy-0.5; + z[k] = -0.5; + } + face4(lc->texids[top ? FACE_U : FACE_D], exterior_color, wire, + s[0], t[0], x[0], y[0], z[0], + s[1], t[1], x[1], y[1], z[1], + s[2], t[2], x[2], y[2], z[2], + s[3], t[3], x[3], y[3], z[3]); + + /* Connecting faces. + */ + for (j = 3; j >= 0; j--) + { + int k = (j == 0 ? 3 : j-1); + Bool front_p = (j == 3); + GLfloat x1 = points[(i*4)+j][0] / 255.0L; + GLfloat y1 = points[(i*4)+j][1] / 255.0L; + GLfloat x2 = points[(i*4)+k][0] / 255.0L; + GLfloat y2 = points[(i*4)+k][1] / 255.0L; + + GLfloat tx1=0.0, tx2=1.0, ty1=0.0, ty2=1.0; + + int texture = 0; + int facing = i/4; + facing = (facing + j + 5) % 4; + + switch (facing) { + case 0: + texture = FACE_W; + if (top) { + tx1 = 1.0 - y1; tx2 = 1.0 - y2; + ty1 = 0.0; ty2 = 1.0; + } else { + tx1 = y1; tx2 = y2; + ty1 = 1.0; ty2 = 0.0; + } + break; + case 1: + texture = top ? FACE_S : FACE_N; + tx1 = x1; tx2 = x2; + ty1 = 0.0; ty2 = 1.0; + break; + case 2: + texture = FACE_E; + if (top) { + tx1 = y1; tx2 = y2; + ty1 = 0.0; ty2 = 1.0; + } else { + tx1 = 1.0 - y1; tx2 = 1.0 - y2; + ty1 = 1.0; ty2 = 0.0; + } + break; + case 3: + texture = top ? FACE_N : FACE_S; + tx1 = x1; tx2 = x2; + ty1 = 1.0; ty2 = 0.0; + break; + } + + x1 -= 0.5; x2 -= 0.5; + y1 -= 0.5; y2 -= 0.5; + + face4(front_p ? lc->texids[texture] : 0, + front_p ? exterior_color : interior_color, + wire, + tx1, ty2, x1, y1, 0.5, + tx1, ty1, x1, y1, -0.5, + tx2, ty1, x2, y2, -0.5, + tx2, ty2, x2, y2, 0.5); + } + } + + + /* Central core top cap. + */ +#ifdef HAVE_GLBINDTEXTURE + glBindTexture(GL_TEXTURE_2D, lc->texids[top ? FACE_U : FACE_D]); +#endif /* HAVE_GLBINDTEXTURE */ + set_colors(exterior_color); + + i = 1; + do_normal(points[i+0][0], points[i+0][1], 0, + points[i+4][0], points[i+4][1], 0, + points[i+8][0], points[i+8][1], 0); + glBegin(wire ? GL_LINE_LOOP : GL_POLYGON); + for (i = 1; i < countof(points); i += 4) + { + GLfloat x = points[i][0] / 255.0L; + GLfloat y = points[i][1] / 255.0L; + glTexCoord2f(x, y); + glVertex3f(x-0.5, y-0.5, 0.5); + } + glEnd(); + + + /* Central core bottom cap. + */ +#ifdef HAVE_GLBINDTEXTURE + glBindTexture(GL_TEXTURE_2D, 0); +#endif /* HAVE_GLBINDTEXTURE */ + set_colors(interior_color); + + i = countof(points) - 9; + do_normal(points[i+0][0], points[i+0][1], 0, + points[i+4][0], points[i+4][1], 0, + points[i+8][0], points[i+8][1], 0); + + glBegin(wire ? GL_LINE_LOOP : GL_POLYGON); + for (i = countof(points) - 3; i >= 0; i -= 4) + { + GLfloat x = points[i][0] / 255.0L; + GLfloat y = points[i][1] / 255.0L; + glVertex3f(x-0.5, y-0.5, 0); + } + glEnd(); + + + /* Central core walls. + */ + for (i = 1; i < countof(points); i += 4) + { + + GLfloat x1 = points[i-1][0] / 255.0L; + GLfloat y1 = points[i-1][1] / 255.0L; + GLfloat x2 = points[i][0] / 255.0L; + GLfloat y2 = points[i][1] / 255.0L; + face4(0, interior_color, wire, + 0.0, 0.0, x1-0.5, y1-0.5, 0.5, + 0.0, 0.0, x1-0.5, y1-0.5, 0.0, + 0.0, 0.0, x2-0.5, y2-0.5, 0.0, + 0.0, 0.0, x2-0.5, y2-0.5, 0.5); + } + + glEndList(); +} + + +static void +tetra(ModeInfo *mi, Bool wire) +{ + lament_configuration *lc = &lcs[MI_SCREEN(mi)]; + + glNewList(lc->tetra_une, GL_COMPILE); + { + glShadeModel(GL_SMOOTH); + + /* Ua */ + face3(lc->texids[FACE_U], exterior_color, wire, + 1.0, 0.0, 0.5, -0.5, 0.5, + 1.0, 1.0, 0.5, 0.5, 0.5, + 0.0, 1.0, -0.5, 0.5, 0.5); + + /* Na */ + face3(lc->texids[FACE_N], exterior_color, wire, + 0.0, 0.0, -0.5, 0.5, 0.5, + 1.0, 0.0, 0.5, 0.5, 0.5, + 1.0, 1.0, 0.5, 0.5, -0.5); + + /* Eb */ + face3(lc->texids[FACE_E], exterior_color, wire, + 1.0, 0.0, 0.5, 0.5, -0.5, + 1.0, 1.0, 0.5, 0.5, 0.5, + 0.0, 1.0, 0.5, -0.5, 0.5); + + face3(0, interior_color, wire, + 0.0, 0.0, 0.5, 0.5, -0.5, + 0.0, 0.0, 0.5, -0.5, 0.5, + 0.0, 0.0, -0.5, 0.5, 0.5); + } + glEndList(); + + glNewList(lc->tetra_usw, GL_COMPILE); + { + /* Ub */ + face3(lc->texids[FACE_U], exterior_color, wire, + 0.0, 1.0, -0.5, 0.5, 0.5, + 0.0, 0.0, -0.5, -0.5, 0.5, + 1.0, 0.0, 0.5, -0.5, 0.5); + + /* Sb */ + face3(lc->texids[FACE_S], exterior_color, wire, + 1.0, 1.0, 0.5, -0.5, 0.5, + 0.0, 1.0, -0.5, -0.5, 0.5, + 0.0, 0.0, -0.5, -0.5, -0.5); + + /* Wb */ + face3(lc->texids[FACE_W], exterior_color, wire, + 1.0, 0.0, -0.5, -0.5, -0.5, + 1.0, 1.0, -0.5, -0.5, 0.5, + 0.0, 1.0, -0.5, 0.5, 0.5); + + face3(0, interior_color, wire, + 0.0,0.0, -0.5, -0.5, -0.5, + 0.0,0.0, -0.5, 0.5, 0.5, + 0.0,0.0, 0.5, -0.5, 0.5); + } + glEndList(); + + glNewList(lc->tetra_dwn, GL_COMPILE); + { + /* Db */ + face3(lc->texids[FACE_D], exterior_color, wire, + 0.0, 1.0, -0.5, -0.5, -0.5, + 0.0, 0.0, -0.5, 0.5, -0.5, + 1.0, 0.0, 0.5, 0.5, -0.5); + + /* Wa */ + face3(lc->texids[FACE_W], exterior_color, wire, + 0.0, 1.0, -0.5, 0.5, 0.5, + 0.0, 0.0, -0.5, 0.5, -0.5, + 1.0, 0.0, -0.5, -0.5, -0.5); + + /* Nb */ + face3(lc->texids[FACE_N], exterior_color, wire, + 1.0, 1.0, 0.5, 0.5, -0.5, + 0.0, 1.0, -0.5, 0.5, -0.5, + 0.0, 0.0, -0.5, 0.5, 0.5); + + face3(0, interior_color, wire, + 0.0, 0.0, 0.5, 0.5, -0.5, + 0.0, 0.0, -0.5, 0.5, 0.5, + 0.0, 0.0, -0.5, -0.5, -0.5); + } + glEndList(); + + glNewList(lc->tetra_dse, GL_COMPILE); + { + /* Sa */ + face3(lc->texids[FACE_S], exterior_color, wire, + 0.0, 0.0, -0.5, -0.5, -0.5, + 1.0, 0.0, 0.5, -0.5, -0.5, + 1.0, 1.0, 0.5, -0.5, 0.5); + + /* Ea */ + face3(lc->texids[FACE_E], exterior_color, wire, + 0.0, 1.0, 0.5, -0.5, 0.5, + 0.0, 0.0, 0.5, -0.5, -0.5, + 1.0, 0.0, 0.5, 0.5, -0.5); + + /* Da */ + face3(lc->texids[FACE_D], exterior_color, wire, + 1.0, 0.0, 0.5, 0.5, -0.5, + 1.0, 1.0, 0.5, -0.5, -0.5, + 0.0, 1.0, -0.5, -0.5, -0.5); + + face3(0, interior_color, wire, + 0.0, 0.0, 0.5, -0.5, 0.5, + 0.0, 0.0, 0.5, 0.5, -0.5, + 0.0, 0.0, -0.5, -0.5, -0.5); + } + glEndList(); + + glNewList(lc->tetra_mid, GL_COMPILE); + { + face3(0, interior_color, wire, + 0.0, 0.0, 0.5, -0.5, 0.5, + 0.0, 0.0, 0.5, 0.5, -0.5, + 0.0, 0.0, -0.5, 0.5, 0.5); + + face3(0, interior_color, wire, + 0.0, 0.0, -0.5, 0.5, 0.5, + 0.0, 0.0, -0.5, -0.5, -0.5, + 0.0, 0.0, 0.5, -0.5, 0.5); + + face3(0, interior_color, wire, + 0.0, 0.0, -0.5, 0.5, 0.5, + 0.0, 0.0, 0.5, 0.5, -0.5, + 0.0, 0.0, -0.5, -0.5, -0.5); + + face3(0, interior_color, wire, + 0.0, 0.0, 0.5, 0.5, -0.5, + 0.0, 0.0, 0.5, -0.5, 0.5, + 0.0, 0.0, -0.5, -0.5, -0.5); + + face3(0, interior_color, wire, + 0.0, 0.0, 0.5, -0.5, 0.5, + 0.0, 0.0, 0.5, 0.5, -0.5, + 0.0, 0.0, -0.5, -0.5, -0.5); + } + glEndList(); + +} + +static void +lid(ModeInfo *mi, Bool wire) +{ + lament_configuration *lc = &lcs[MI_SCREEN(mi)]; + int i; + + int points[][2] = { + { 128, 20 },{ 21, 129 },{ 0, 129 },{ 0, 0 },{ 128, 0 }, /* L1 */ + { 21, 129 },{ 127, 234 },{ 127, 255 },{ 0, 255 },{ 0, 129 }, /* L2 */ + { 127, 234 },{ 233, 127 },{ 255, 127 },{ 255, 255 },{ 127, 255 }, /* R2 */ + { 233, 127 },{ 128, 20 },{ 128, 0 },{ 255, 0 },{ 255, 127 }, /* R1 */ + }; + + for (i = 0; i < countof(points); i++) + points[i][1] = 255-points[i][1]; + + glNewList(lc->lid_0, GL_COMPILE); + glShadeModel(GL_SMOOTH); + + /* N */ + face4(lc->texids[FACE_N], exterior_color, wire, + 0.0, 0.0, -0.5, 0.5, 0.5, + 1.0, 0.0, 0.5, 0.5, 0.5, + 1.0, 1.0, 0.5, 0.5, -0.5, + 0.0, 1.0, -0.5, 0.5, -0.5); + + /* S */ + face4(lc->texids[FACE_S], exterior_color, wire, + 0.0, 0.0, -0.5, -0.5, -0.5, + 1.0, 0.0, 0.5, -0.5, -0.5, + 1.0, 1.0, 0.5, -0.5, 0.5, + 0.0, 1.0, -0.5, -0.5, 0.5); + + /* E */ + face4(lc->texids[FACE_E], exterior_color, wire, + 0.0, 0.0, 0.5, -0.5, -0.5, + 1.0, 0.0, 0.5, 0.5, -0.5, + 1.0, 1.0, 0.5, 0.5, 0.5, + 0.0, 1.0, 0.5, -0.5, 0.5); + + /* U */ + face4(lc->texids[FACE_U], exterior_color, wire, + 1.0, 0.0, 0.5, -0.5, 0.5, + 1.0, 1.0, 0.5, 0.5, 0.5, + 0.0, 1.0, -0.5, 0.5, 0.5, + 0.0, 0.0, -0.5, -0.5, 0.5); + + /* D */ + face4(lc->texids[FACE_D], exterior_color, wire, + 0.0, 1.0, -0.5, -0.5, -0.5, + 0.0, 0.0, -0.5, 0.5, -0.5, + 1.0, 0.0, 0.5, 0.5, -0.5, + 1.0, 1.0, 0.5, -0.5, -0.5); + + /* W -- lid_0 */ + for (i = 0; i < countof(points)/5; i++) + { + int j; + GLfloat s[5], t[5], x[5], y[5], z[5]; + for (j = 0; j < 5; j++) + { + GLfloat xx = points[(i*5)+j][0] / 255.0L; + GLfloat yy = points[(i*5)+j][1] / 255.0L; + s[j] = 1.0-xx; + t[j] = yy; + x[j] = -0.5; + y[j] = xx-0.5; + z[j] = yy-0.5; + } + face5(lc->texids[FACE_W], exterior_color, wire, + s[0], t[0], x[0], y[0], z[0], + s[1], t[1], x[1], y[1], z[1], + s[2], t[2], x[2], y[2], z[2], + s[3], t[3], x[3], y[3], z[3], + s[4], t[4], x[4], y[4], z[4]); + } + glEndList(); + + + /* W -- lid_1 through lid_4 */ + for (i = 0; i < 4; i++) + { + GLfloat x1, y1, x2, y2, x3, y3; + + glNewList(lc->lid_1 + i, GL_COMPILE); + glShadeModel(GL_SMOOTH); + + x1 = points[(i*5)+1][0] / 255.0L; + y1 = points[(i*5)+1][1] / 255.0L; + x2 = points[(i*5)][0] / 255.0L; + y2 = points[(i*5)][1] / 255.0L; + x3 = 0.5; + y3 = 0.5; + + /* Outer surface */ + face3(lc->texids[FACE_W], exterior_color, wire, + 1.0-x1, y1, -0.5, x1-0.5, y1-0.5, + 1.0-x2, y2, -0.5, x2-0.5, y2-0.5, + 1.0-x3, y3, -0.5, x3-0.5, y3-0.5); + + /* Inner surface */ + face3(0, interior_color, wire, + 0.0, 0.0, -0.48, x2-0.5, y2-0.5, + 0.0, 0.0, -0.48, x1-0.5, y1-0.5, + 0.0, 0.0, -0.48, x3-0.5, y3-0.5); + + /* Lip 1 */ + face4(0, interior_color, wire, + 0.0, 0.0, -0.5, x1-0.5, y1-0.5, + 0.0, 0.0, -0.5, x3-0.5, y3-0.5, + 0.0, 0.0, -0.48, x3-0.5, y3-0.5, + 0.0, 0.0, -0.48, x1-0.5, y1-0.5); + + /* Lip 2 */ + face4(0, interior_color, wire, + 0.0, 0.0, -0.48, x2-0.5, y2-0.5, + 0.0, 0.0, -0.48, x3-0.5, y3-0.5, + 0.0, 0.0, -0.5, x3-0.5, y3-0.5, + 0.0, 0.0, -0.5, x2-0.5, y2-0.5); + + glEndList(); + } +} + +static void +taser(ModeInfo *mi, Bool wire) +{ + lament_configuration *lc = &lcs[MI_SCREEN(mi)]; + int i; + + int slider_face_points[][2] = { + { 86, 58 },{ 38, 106 },{ 70, 106 },{ 118, 58 },{ -1, -1 }, /* a */ + { 136, 58 },{ 184, 106 },{ 216, 106 },{ 168, 58 },{ -1, -1 }, /* b */ + { 38, 106 },{ 0, 144 },{ 0, 190 },{ 60, 190 },{ 108, 106 }, /* c */ + { 144, 106 },{ 194, 190 },{ 254, 190 },{ 254, 144 },{ 216, 106 }, /* d */ + { 98, 124 },{ 60, 190 },{ 92, 190 },{ 126, 158 },{ 126, 124 }, /* e */ + { 126, 124 },{ 126, 158 },{ 160, 190 },{ 194, 190 },{ 154, 124 }, /* f */ + { 22, 190 },{ 22, 254 },{ 60, 254 },{ 60, 190 },{ -1, -1 }, /* g */ + { 194, 190 },{ 194, 254 },{ 230, 254 },{ 230, 190 },{ -1, -1 }, /* h */ + { 60, 190 },{ 60, 210 },{ 92, 210 },{ 92, 190 },{ -1, -1 }, /* i */ + { 160, 190 },{ 160, 210 },{ 194, 210 },{ 194, 190 },{ -1, -1 }, /* j */ + { 110, 172 },{ 92, 190 },{ 110, 190 },{ -1, -1 },{ -1, -1 }, /* k */ + { 140, 172 },{ 140, 190 },{ 160, 190 },{ -1, -1 },{ -1, -1 }, /* l */ + { 110, 172 },{ 140, 172 },{ 126, 156 },{ -1, -1 },{ -1, -1 }, /* m */ + }; + + int body_face_points[][2] = { + { 0, 0 },{ 0, 58 },{ 254, 58 },{ 254, 0 },{ -1, -1 }, /* A */ + { 0, 58 },{ 0, 144 },{ 86, 58 },{ -1, -1 },{ -1, -1 }, /* B */ + { 168, 58 },{ 254, 144 },{ 254, 58 },{ -1, -1 },{ -1, -1 }, /* C */ + { 118, 58 },{ 70, 106 },{ 184, 106 },{ 136, 58 },{ -1, -1 }, /* F */ + { 108, 106 },{ 98, 124 },{ 154, 124 },{ 144, 106 },{ -1, -1 }, /* G */ + }; + + int lifter_face_points[][2] = { + { 0, 190 },{ 0, 254 },{ 22, 254 },{ 22, 190 },{ -1, -1 }, /* D */ + { 230, 190 },{ 230, 254 },{ 254, 254 },{ 254, 190 },{ -1, -1 }, /* E */ + { 60, 210 },{ 60, 254 },{ 194, 254 },{ 194, 210 },{ -1, -1 }, /* H */ + { 92, 190 },{ 92, 210 },{ 160, 210 },{ 160, 190 },{ -1, -1 }, /* I */ + { 110, 172 },{ 110, 190 },{ 140, 190 },{ 140, 172 },{ -1, -1 }, /* J */ + }; + + int body_perimiter_points[][2] = { + { 0, 144 },{ 86, 59 },{ 119, 58 },{ 71, 107 }, + { 108, 107 },{ 98, 124 },{ 155, 124 },{ 144, 107 }, + { 185, 106 },{ 136, 59 },{ 169, 59 },{ 255, 145 }, + { 255, 0 },{ 0, 0 }, + }; + + int slider_perimiter_points[][2] = { + { 86, 58 },{ 0, 144 },{ 0, 190 },{ 22, 190 },{ 22, 254 }, + { 60, 254 },{ 60, 210 },{ 92, 210 },{ 92, 190 },{ 110, 190 }, + { 110, 172 },{ 140, 172 },{ 140, 190 },{ 160, 190 },{ 160, 210 }, + { 194, 210 },{ 194, 254 },{ 230, 254 },{ 230, 190 },{ 254, 190 }, + { 254, 144 },{ 168, 58 },{ 136, 58 },{ 184, 106 },{ 144, 106 }, + { 154, 124 },{ 98, 124 },{ 108, 106 },{ 70, 106 },{ 118, 58 }, + }; + + int lifter_perimiter_points_1[][2] = { + { 0, 189 },{ 0, 254 },{ 22, 255 },{ 23, 190 }, + }; + + int lifter_perimiter_points_2[][2] = { + { 230, 254 },{ 255, 255 },{ 254, 190 },{ 230, 190 }, + }; + + int lifter_perimiter_points_3[][2] = { + { 60, 254 },{ 194, 254 },{ 194, 211 },{ 160, 210 }, + { 160, 190 },{ 140, 191 },{ 141, 172 },{ 111, 172 }, + { 110, 190 },{ 93, 190 },{ 92, 210 },{ 60, 211 }, + }; + + for (i = 0; i < countof(slider_face_points); i++) + slider_face_points[i][1] = 255-slider_face_points[i][1]; + for (i = 0; i < countof(body_face_points); i++) + body_face_points[i][1] = 255-body_face_points[i][1]; + for (i = 0; i < countof(lifter_face_points); i++) + lifter_face_points[i][1] = 255-lifter_face_points[i][1]; + for (i = 0; i < countof(body_perimiter_points); i++) + body_perimiter_points[i][1] = 255-body_perimiter_points[i][1]; + for (i = 0; i < countof(slider_perimiter_points); i++) + slider_perimiter_points[i][1] = 255-slider_perimiter_points[i][1]; + for (i = 0; i < countof(lifter_perimiter_points_1); i++) + lifter_perimiter_points_1[i][1] = 255-lifter_perimiter_points_1[i][1]; + for (i = 0; i < countof(lifter_perimiter_points_2); i++) + lifter_perimiter_points_2[i][1] = 255-lifter_perimiter_points_2[i][1]; + for (i = 0; i < countof(lifter_perimiter_points_3); i++) + lifter_perimiter_points_3[i][1] = 255-lifter_perimiter_points_3[i][1]; + + /* -------------------------------------------------------------------- */ + + glNewList(lc->taser_base, GL_COMPILE); + glShadeModel(GL_SMOOTH); + + /* N */ + face4(lc->texids[FACE_N], exterior_color, wire, + 0.0, 0.0, -0.5, 0.5, 0.5, + 0.75, 0.0, 0.25, 0.5, 0.5, + 0.75, 0.75, 0.25, 0.5, -0.25, + 0.0, 0.75, -0.5, 0.5, -0.25); + + /* S */ + face4(lc->texids[FACE_S], exterior_color, wire, + 0.0, 0.25, -0.5, -0.5, -0.25, + 0.75, 0.25, 0.25, -0.5, -0.25, + 0.75, 1.0, 0.25, -0.5, 0.5, + 0.0, 1.0, -0.5, -0.5, 0.5); + + /* interior E */ + face4(0, interior_color, wire, + 0.0, 0.0, 0.25, -0.5, -0.25, + 1.0, 0.0, 0.25, 0.5, -0.25, + 1.0, 1.0, 0.25, 0.5, 0.5, + 0.0, 1.0, 0.25, -0.5, 0.5); + + /* W */ + face4(lc->texids[FACE_W], exterior_color, wire, + 1.0, 1.0, -0.5, -0.5, 0.5, + 0.0, 1.0, -0.5, 0.5, 0.5, + 0.0, 0.25, -0.5, 0.5, -0.25, + 1.0, 0.25, -0.5, -0.5, -0.25); + + /* U */ + face4(lc->texids[FACE_U], exterior_color, wire, + 0.75, 0.0, 0.25, -0.5, 0.5, + 0.75, 1.0, 0.25, 0.5, 0.5, + 0.0, 1.0, -0.5, 0.5, 0.5, + 0.0, 0.0, -0.5, -0.5, 0.5); + + /* interior D */ + face4(0, interior_color, wire, + 0.0, 1.0, -0.5, -0.5, -0.25, + 0.0, 0.0, -0.5, 0.5, -0.25, + 1.0, 0.0, 0.25, 0.5, -0.25, + 1.0, 1.0, 0.25, -0.5, -0.25); + + /* Top face */ + for (i = 0; i < countof(body_face_points)/5; i++) + { + int j; +#ifdef HAVE_GLBINDTEXTURE + glBindTexture(GL_TEXTURE_2D, lc->texids[FACE_E]); +#endif /* HAVE_GLBINDTEXTURE */ + set_colors(exterior_color); + + do_normal(0, body_face_points[(i*5)+0][0], body_face_points[(i*5)+0][1], + 0, body_face_points[(i*5)+1][0], body_face_points[(i*5)+1][1], + 0, body_face_points[(i*5)+2][0], body_face_points[(i*5)+2][1] + ); + glBegin(wire ? GL_LINE_LOOP : GL_POLYGON); + for (j = 0; j < 5; j++) + { + int ix = body_face_points[(i*5)+j][0]; + int iy = body_face_points[(i*5)+j][1]; + GLfloat x, y; + if (ix == -1) /* these are padding: ignore them */ + continue; + x = ix / 255.0L; + y = iy / 255.0L; + glTexCoord2f(x, y); + glVertex3f(0.5, x-0.5, y-0.5); + } + glEnd(); + } + + /* Side walls */ + for (i = 0; i < countof(body_perimiter_points); i++) + { + int j = (i+1 >= countof(body_perimiter_points) ? 0 : i+1); + GLfloat x1 = body_perimiter_points[i][0] / 255.0; + GLfloat y1 = body_perimiter_points[i][1] / 255.0; + GLfloat x2 = body_perimiter_points[j][0] / 255.0; + GLfloat y2 = body_perimiter_points[j][1] / 255.0; + int texture = -1; + GLfloat s1=0, t1=0, s2=0, t2=0, s3=0, t3=0, s4=0, t4=0; + + if (i == 11) + { + texture = lc->texids[FACE_N]; + s1 = 1.0; t1 = 0.0; + s2 = 1.0; t2 = 0.568; + s3 = 0.75, t3 = 0.568; + s4 = 0.75; t4 = 0.0; + } + else if (i == 12) + { + texture = lc->texids[FACE_U]; + s1 = 1.0; t1 = 0.0; + s2 = 1.0; t2 = 1.0; + s3 = 0.75, t3 = 1.0; + s4 = 0.75; t4 = 0.0; + } + else if (i == 13) + { + texture = lc->texids[FACE_S]; + s1 = 1.0; t1 = 0.437; + s2 = 1.0; t2 = 1.0; + s3 = 0.75; t3 = 1.0; + s4 = 0.75; t4 = 0.437; + } + + face4((texture == -1 ? 0 : texture), + (texture == -1 ? interior_color : exterior_color), + wire, + s1, t1, 0.5, x2-0.5, y2-0.5, + s2, t2, 0.5, x1-0.5, y1-0.5, + s3, t3, 0.25, x1-0.5, y1-0.5, + s4, t4, 0.25, x2-0.5, y2-0.5); + } + + glEndList(); + + /* -------------------------------------------------------------------- */ + + glNewList(lc->taser_lifter, GL_COMPILE); + glShadeModel(GL_SMOOTH); + + /* N */ + face4(lc->texids[FACE_N], exterior_color, wire, + 0.0, 0.75, -0.5, 0.5, -0.25, + 0.75, 0.75, 0.25, 0.5, -0.25, + 0.75, 1.0, 0.25, 0.5, -0.5, + 0.0, 1.0, -0.5, 0.5, -0.5); + + /* S */ + face4(lc->texids[FACE_S], exterior_color, wire, + 0.0, 0.0, -0.5, -0.5, -0.5, + 0.75, 0.0, 0.25, -0.5, -0.5, + 0.75, 0.25, 0.25, -0.5, -0.25, + 0.0, 0.25, -0.5, -0.5, -0.25); + + /* interior E */ + face4(0, interior_color, wire, + 0.0, 1.0, 0.25, -0.5, -0.5, + 1.0, 1.0, 0.25, 0.5, -0.5, + 1.0, 0.0, 0.25, 0.5, -0.25, + 0.0, 0.0, 0.25, -0.5, -0.25); + + /* W */ + face4(lc->texids[FACE_W], exterior_color, wire, + 1.0, 0.25, -0.5, -0.5, -0.25, + 0.0, 0.25, -0.5, 0.5, -0.25, + 0.0, 0.0, -0.5, 0.5, -0.5, + 1.0, 0.0, -0.5, -0.5, -0.5); + + /* interior U */ + face4(0, interior_color, wire, + 1.0, 0.0, 0.25, -0.5, -0.25, + 1.0, 1.0, 0.25, 0.5, -0.25, + 0.0, 1.0, -0.5, 0.5, -0.25, + 0.0, 0.0, -0.5, -0.5, -0.25); + + /* D */ + face4(lc->texids[FACE_D], exterior_color, wire, + 0.0, 1.0, -0.5, -0.5, -0.5, + 0.0, 0.0, -0.5, 0.5, -0.5, + 0.75, 0.0, 0.25, 0.5, -0.5, + 0.75, 1.0, 0.25, -0.5, -0.5); + + + /* Top face */ + for (i = 0; i < countof(lifter_face_points)/5; i++) + { + int j; + +#ifdef HAVE_GLBINDTEXTURE + glBindTexture(GL_TEXTURE_2D, lc->texids[FACE_E]); +#endif /* HAVE_GLBINDTEXTURE */ + set_colors(exterior_color); + + do_normal( + 0, lifter_face_points[(i*5)+0][0], lifter_face_points[(i*5)+0][1], + 0, lifter_face_points[(i*5)+1][0], lifter_face_points[(i*5)+1][1], + 0, lifter_face_points[(i*5)+2][0], lifter_face_points[(i*5)+2][1]); + + glBegin(wire ? GL_LINE_LOOP : GL_POLYGON); + for (j = 0; j < 5; j++) + { + int ix = lifter_face_points[(i*5)+j][0]; + int iy = lifter_face_points[(i*5)+j][1]; + GLfloat x, y; + if (ix == -1) /* these are padding: ignore them */ + continue; + x = ix / 255.0L; + y = iy / 255.0L; + glTexCoord2f(x, y); + glVertex3f(0.5, x-0.5, y-0.5); + } + glEnd(); + } + + /* Side walls */ + for (i = 0; i < countof(lifter_perimiter_points_1); i++) + { + int j = (i+1 >= countof(lifter_perimiter_points_1) ? 0 : i+1); + GLfloat x1 = lifter_perimiter_points_1[i][0] / 255.0; + GLfloat y1 = lifter_perimiter_points_1[i][1] / 255.0; + GLfloat x2 = lifter_perimiter_points_1[j][0] / 255.0; + GLfloat y2 = lifter_perimiter_points_1[j][1] / 255.0; + int texture = -1; + GLfloat s1=0, t1=0, s2=0, t2=0, s3=0, t3=0, s4=0, t4=0; + + if (i == 0) + { + texture = lc->texids[FACE_S]; + s1 = 1.0; t1 = 0.0; + s2 = 1.0; t2 = 0.26; + s3 = 0.75, t3 = 0.26; + s4 = 0.75; t4 = 0.0; + } + else if (i == 1) + { + texture = lc->texids[FACE_D]; + s1 = 1.0; t1 = 0.914; + s2 = 1.0; t2 = 1.0; + s3 = 0.75; t3 = 1.0; + s4 = 0.75; t4 = 0.914; + } + + face4((texture == -1 ? 0 : texture), + (texture == -1 ? interior_color : exterior_color), + wire, + s1, t1, 0.5, x2-0.5, y2-0.5, + s2, t2, 0.5, x1-0.5, y1-0.5, + s3, t3, 0.25, x1-0.5, y1-0.5, + s4, t4, 0.25, x2-0.5, y2-0.5); + } + + for (i = 0; i < countof(lifter_perimiter_points_2); i++) + { + int j = (i+1 >= countof(lifter_perimiter_points_2) ? 0 : i+1); + GLfloat x1 = lifter_perimiter_points_2[i][0] / 255.0; + GLfloat y1 = lifter_perimiter_points_2[i][1] / 255.0; + GLfloat x2 = lifter_perimiter_points_2[j][0] / 255.0; + GLfloat y2 = lifter_perimiter_points_2[j][1] / 255.0; + int texture = -1; + GLfloat s1=0, t1=0, s2=0, t2=0, s3=0, t3=0, s4=0, t4=0; + + if (i == 0) + { + texture = lc->texids[FACE_D]; + s1 = 1.0; t1 = 0.0; + s2 = 1.0; t2 = 0.095; + s3 = 0.75; t3 = 0.095; + s4 = 0.75; t4 = 0.0; + } + else if (i == 1) + { + texture = lc->texids[FACE_N]; + s1 = 1.0; t1 = 0.745; + s2 = 1.0; t2 = 1.0; + s3 = 0.75; t3 = 1.0; + s4 = 0.75; t4 = 0.745; + } + + face4((texture == -1 ? 0 : texture), + (texture == -1 ? interior_color : exterior_color), + wire, + s1, t1, 0.5, x2-0.5, y2-0.5, + s2, t2, 0.5, x1-0.5, y1-0.5, + s3, t3, 0.25, x1-0.5, y1-0.5, + s4, t4, 0.25, x2-0.5, y2-0.5); + } + + for (i = 0; i < countof(lifter_perimiter_points_3); i++) + { + int j = (i+1 >= countof(lifter_perimiter_points_3) ? 0 : i+1); + GLfloat x1 = lifter_perimiter_points_3[i][0] / 255.0; + GLfloat y1 = lifter_perimiter_points_3[i][1] / 255.0; + GLfloat x2 = lifter_perimiter_points_3[j][0] / 255.0; + GLfloat y2 = lifter_perimiter_points_3[j][1] / 255.0; + int texture = -1; + GLfloat s1=0, t1=0, s2=0, t2=0, s3=0, t3=0, s4=0, t4=0; + + if (i == 0) + { + texture = lc->texids[FACE_D]; + s1 = 1.0; t1 = 0.235; + s2 = 1.0; t2 = 0.765; + s3 = 0.75; t3 = 0.765; + s4 = 0.75; t4 = 0.235; + } + + face4((texture == -1 ? 0 : texture), + (texture == -1 ? interior_color : exterior_color), + wire, + s1, t1, 0.5, x2-0.5, y2-0.5, + s2, t2, 0.5, x1-0.5, y1-0.5, + s3, t3, 0.25, x1-0.5, y1-0.5, + s4, t4, 0.25, x2-0.5, y2-0.5); + } + + glEndList(); + + /* -------------------------------------------------------------------- */ + + glNewList(lc->taser_slider, GL_COMPILE); + glShadeModel(GL_SMOOTH); + + /* Top face */ + for (i = 0; i < countof(slider_face_points)/5; i++) + { + int j; +#ifdef HAVE_GLBINDTEXTURE + glBindTexture(GL_TEXTURE_2D, lc->texids[FACE_E]); +#endif /* HAVE_GLBINDTEXTURE */ + set_colors(exterior_color); + + do_normal( + 0, slider_face_points[(i*5)+0][0], slider_face_points[(i*5)+0][1], + 0, slider_face_points[(i*5)+1][0], slider_face_points[(i*5)+1][1], + 0, slider_face_points[(i*5)+2][0], slider_face_points[(i*5)+2][1]); + glBegin(wire ? GL_LINE_LOOP : GL_POLYGON); + for (j = 0; j < 5; j++) + { + int ix = slider_face_points[(i*5)+j][0]; + int iy = slider_face_points[(i*5)+j][1]; + GLfloat x, y; + if (ix == -1) /* these are padding: ignore them */ + continue; + x = ix / 255.0L; + y = iy / 255.0L; + glTexCoord2f(x, y); + glVertex3f(0.5, x-0.5, y-0.5); + } + glEnd(); + } + + /* Bottom face */ + for (i = countof(slider_face_points)/5 - 1; i >= 0; i--) + { + int j; +#ifdef HAVE_GLBINDTEXTURE + glBindTexture(GL_TEXTURE_2D, 0); +#endif /* HAVE_GLBINDTEXTURE */ + set_colors(interior_color); + + do_normal( + 0, slider_face_points[(i*5)+2][0], slider_face_points[(i*5)+2][1], + 0, slider_face_points[(i*5)+1][0], slider_face_points[(i*5)+1][1], + 0, slider_face_points[(i*5)+0][0], slider_face_points[(i*5)+0][1]); + glBegin(wire ? GL_LINE_LOOP : GL_POLYGON); + for (j = 4; j >= 0; j--) + { + int ix = slider_face_points[(i*5)+j][0]; + int iy = slider_face_points[(i*5)+j][1]; + GLfloat x, y; + if (ix == -1) /* these are padding: ignore them */ + continue; + x = ix / 255.0L; + y = iy / 255.0L; + glTexCoord2f(x, y); + glVertex3f(0.25, x-0.5, y-0.5); + } + glEnd(); + } + + /* Side walls */ + for (i = 0; i < countof(slider_perimiter_points); i++) + { + int j = (i+1 >= countof(slider_perimiter_points) ? 0 : i+1); + GLfloat x1 = slider_perimiter_points[i][0] / 255.0; + GLfloat y1 = slider_perimiter_points[i][1] / 255.0; + GLfloat x2 = slider_perimiter_points[j][0] / 255.0; + GLfloat y2 = slider_perimiter_points[j][1] / 255.0; + int texture = -1; + GLfloat s1=0, t1=0, s2=0, t2=0, s3=0, t3=0, s4=0, t4=0; + + if (i == 1) + { + texture = lc->texids[FACE_S]; + s1 = 1.0; t1 = 0.255; + s2 = 1.0; t2 = 0.435; + s3 = 0.75; t3 = 0.435; + s4 = 0.75; t4 = 0.255; + } + else if (i == 4) + { + texture = lc->texids[FACE_D]; + s1 = 1.0; t1 = 0.758; + s2 = 1.0; t2 = 0.915; + s3 = 0.75; t3 = 0.915; + s4 = 0.75; t4 = 0.758; + } + else if (i == 16) + { + texture = lc->texids[FACE_D]; + s1 = 1.0; t1 = 0.095; + s2 = 1.0; t2 = 0.24; + s3 = 0.75; t3 = 0.24; + s4 = 0.75; t4 = 0.095; + } + else if (i == 19) + { + texture = lc->texids[FACE_N]; + s1 = 1.0; t1 = 0.568; + s2 = 1.0; t2 = 0.742; + s3 = 0.75; t3 = 0.742; + s4 = 0.75; t4 = 0.568; + } + + face4((texture == -1 ? 0 : texture), + (texture == -1 ? interior_color : exterior_color), + wire, + s1, t1, 0.5, x2-0.5, y2-0.5, + s2, t2, 0.5, x1-0.5, y1-0.5, + s3, t3, 0.25, x1-0.5, y1-0.5, + s4, t4, 0.25, x2-0.5, y2-0.5); + } + + glEndList(); +} + + + +/* Rendering and animating object models + */ + +ENTRYPOINT Bool +lament_handle_event (ModeInfo *mi, XEvent *event) +{ + lament_configuration *lc = &lcs[MI_SCREEN(mi)]; + + if (event->xany.type == ButtonPress && + event->xbutton.button == Button1) + { + lc->button_down_p = True; + gltrackball_start (lc->trackball, + event->xbutton.x, event->xbutton.y, + MI_WIDTH (mi), MI_HEIGHT (mi)); + return True; + } + else if (event->xany.type == ButtonRelease && + event->xbutton.button == Button1) + { + lc->button_down_p = False; + return True; + } + else if (event->xany.type == ButtonPress && + (event->xbutton.button == Button4 || + event->xbutton.button == Button5 || + event->xbutton.button == Button6 || + event->xbutton.button == Button7)) + { + gltrackball_mousewheel (lc->trackball, event->xbutton.button, 5, + !!event->xbutton.state); + return True; + } + else if (event->xany.type == MotionNotify && + lc->button_down_p) + { + gltrackball_track (lc->trackball, + event->xmotion.x, event->xmotion.y, + MI_WIDTH (mi), MI_HEIGHT (mi)); + return True; + } + + return False; +} + + +static void +check_facing(ModeInfo *mi) +{ + lament_configuration *lc = &lcs[MI_SCREEN(mi)]; + + GLdouble m[16], p[16], x, y, z; + GLint v[4]; + glGetDoublev (GL_MODELVIEW_MATRIX, m); + glGetDoublev (GL_PROJECTION_MATRIX, p); + glGetIntegerv (GL_VIEWPORT, v); + + /* See if a coordinate 5 units in front of the door is near the + center of the screen. */ + + gluProject (-5, 0, 0, m, p, v, &x, &y, &z); + x = (x / MI_WIDTH(mi)) - 0.5; + y = (y / MI_HEIGHT(mi)) - 0.5; + lc->facing_p = (z < 0.9 && + x > -0.02 && x < 0.02 && + y > -0.02 && y < 0.02); +} + + + +static void +scale_for_window(ModeInfo *mi) +{ + lament_configuration *lc = &lcs[MI_SCREEN(mi)]; + + /* No texture created in -wireframe or -no-texture, so guess. */ + int target_size = (lc->texture + ? lc->texture->width * 1.4 + : 340); + int win_size = (MI_WIDTH(mi) > MI_HEIGHT(mi) ? MI_HEIGHT(mi) : MI_WIDTH(mi)); + + /* This scale makes the box take up most of the window */ + glScalef(8, 8, 8); + + /* But if the window is more than a little larger than our target size, + scale the object back down, so that the bits drawn on the screen end + up rougly target_size across (actually it ends up a little larger.) + Note that the image-map bits we have are 128x128. Therefore, if the + image is magnified a lot, it looks pretty blocky. So it's better to + have a 128x128 animation on a 1280x1024 screen that looks good, than + a 1024x1024 animation that looks really pixelated. + */ + + { + int max = 340; /* Let's not go larger than life-sized. */ + if (target_size > max) + target_size = max; + } + + if (win_size > 640 && + win_size > target_size * 1.5) + { + GLfloat ratio = ((GLfloat) target_size / (GLfloat) win_size); + ratio *= 2.0; + glScalef(ratio, ratio, ratio); + } +} + + +static void +draw(ModeInfo *mi) +{ + lament_configuration *lc = &lcs[MI_SCREEN(mi)]; + Bool wire = MI_IS_WIREFRAME(mi); + + if (!wire) + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + else + glClear(GL_COLOR_BUFFER_BIT); + + glPushMatrix(); + + /* Do it twice because we don't track the device's orientation. */ + glRotatef( current_device_rotation(), 0, 0, 1); + gltrackball_rotate (lc->trackball); + glRotatef(-current_device_rotation(), 0, 0, 1); + + /* Make into the screen be +Y right be +X, and up be +Z. */ + glRotatef(-90.0, 1.0, 0.0, 0.0); + + scale_for_window (mi); + +#if 0 + glPushMatrix(); + { + /* Shift to the upper left, and draw the vanilla box. */ + glTranslatef(-0.6, 0.0, 0.6); + + /* Apply rotation to the object. */ + 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); + + /* Draw it. */ + glCallList(lc->box); + } + glPopMatrix(); + + /* Shift to the lower right, and draw the animated object. */ + glTranslatef(0.6, 0.0, -0.6); +#endif /* 0 */ + + + glPushMatrix(); + { + /* Apply rotation to the object. */ + if (lc->type != LAMENT_LID_ZOOM) + get_rotation (lc->rot, &lc->rotx, &lc->roty, &lc->rotz, + !lc->button_down_p); + glRotatef (lc->rotx * 360, 1.0, 0.0, 0.0); + glRotatef (lc->roty * 360, 0.0, 1.0, 0.0); + glRotatef (lc->rotz * 360, 0.0, 0.0, 1.0); + + check_facing(mi); + + switch (lc->type) + { + case LAMENT_BOX: + glCallList(lc->box); + break; + + case LAMENT_STAR_OUT: + case LAMENT_STAR_ROT: + case LAMENT_STAR_ROT_IN: + case LAMENT_STAR_ROT_OUT: + case LAMENT_STAR_UNROT: + case LAMENT_STAR_IN: + glTranslatef(0.0, 0.0, lc->anim_z/2); + glRotatef(lc->anim_r/2, 0.0, 0.0, 1.0); + glCallList(lc->star1); + + glTranslatef(0.0, 0.0, -lc->anim_z); + glRotatef(-lc->anim_r, 0.0, 0.0, 1.0); + glCallList(lc->star2); + break; + + case LAMENT_TETRA_UNE: + case LAMENT_TETRA_USW: + case LAMENT_TETRA_DWN: + case LAMENT_TETRA_DSE: + { + int magic; + GLfloat x, y, z; + switch (lc->type) { + case LAMENT_TETRA_UNE: magic = lc->tetra_une; + x = 1.0; y = 1.0; z = 1.0; break; + case LAMENT_TETRA_USW: magic = lc->tetra_usw; + x = 1.0; y = 1.0; z = -1.0; break; + case LAMENT_TETRA_DWN: magic = lc->tetra_dwn; + x = 1.0; y = -1.0; z = 1.0; break; + case LAMENT_TETRA_DSE: magic = lc->tetra_dse; + x = -1.0; y = 1.0; z = 1.0; break; + default: abort(); break; + } + glCallList(lc->tetra_mid); + if (magic != lc->tetra_une) glCallList(lc->tetra_une); + if (magic != lc->tetra_usw) glCallList(lc->tetra_usw); + if (magic != lc->tetra_dwn) glCallList(lc->tetra_dwn); + if (magic != lc->tetra_dse) glCallList(lc->tetra_dse); + glRotatef(lc->anim_r, x, y, z); + glCallList(magic); + } + break; + + case LAMENT_LID_OPEN: + case LAMENT_LID_CLOSE: + case LAMENT_LID_ZOOM: + { + GLfloat d = 0.417; + + glTranslatef(lc->anim_z, 0.0, 0.0); + + glCallList(lc->lid_0); + + glPushMatrix(); + glTranslatef(-0.5, -d, 0.0); + glRotatef(-lc->anim_r, 0.0, -1.0, -1.0); + glTranslatef( 0.5, d, 0.0); + glCallList(lc->lid_1); + glPopMatrix(); + glPushMatrix(); + glTranslatef(-0.5, -d, 0.0); + glRotatef( lc->anim_r, 0.0, -1.0, 1.0); + glTranslatef( 0.5, d, 0.0); + glCallList(lc->lid_2); + glPopMatrix(); + glPushMatrix(); + glTranslatef(-0.5, d, 0.0); + glRotatef( lc->anim_r, 0.0, -1.0, -1.0); + glTranslatef( 0.5, -d, 0.0); + glCallList(lc->lid_3); + glPopMatrix(); + glPushMatrix(); + glTranslatef(-0.5, d, 0.0); + glRotatef(-lc->anim_r, 0.0, -1.0, 1.0); + glTranslatef( 0.5, -d, 0.0); + glCallList(lc->lid_4); + glPopMatrix(); + } + break; + + case LAMENT_TASER_OUT: + case LAMENT_TASER_SLIDE: + case LAMENT_TASER_SLIDE_IN: + case LAMENT_TASER_IN: + + glTranslatef(-lc->anim_z/2, 0.0, 0.0); + glCallList(lc->taser_base); + + glTranslatef(lc->anim_z, 0.0, 0.0); + glCallList(lc->taser_lifter); + + glTranslatef(0.0, 0.0, lc->anim_y); + glCallList(lc->taser_slider); + break; + + default: + abort(); + break; + } + } + glPopMatrix(); + + glPopMatrix(); +} + + +/* Rather than just picking states randomly, pick an ordering randomly, do it, + and then re-randomize. That way one can be assured of seeing all states in + a short time period, though not always in the same order (it's frustrating + to see it pick the same state 5x in a row.) + */ +static void +shuffle_states (lament_configuration *lc) +{ + int i; + for (i = 0; i < lc->nstates; i++) + { + int a = random() % lc->nstates; + lament_type swap = lc->states[a]; + lc->states[a] = lc->states[i]; + lc->states[i] = swap; + } +} + + +static void +animate(ModeInfo *mi) +{ + lament_configuration *lc = &lcs[MI_SCREEN(mi)]; + int pause = 10; +/* int pause2 = 60;*/ + int pause3 = 120; + + switch (lc->type) + { + case LAMENT_BOX: + { + lc->state++; + if (lc->state >= lc->nstates) + { + shuffle_states (lc); + lc->state = 0; + } + lc->type = lc->states[lc->state]; + + if (lc->type == LAMENT_BOX) + lc->anim_pause = pause3; + + lc->anim_r = 0.0; + lc->anim_y = 0.0; + lc->anim_z = 0.0; + } + break; + + /* -------------------------------------------------------------- */ + + case LAMENT_STAR_OUT: + lc->anim_z += 0.01; + if (lc->anim_z >= 1.0) + { + lc->anim_z = 1.0; + lc->type = LAMENT_STAR_ROT; + lc->anim_pause = pause; + } + break; + + case LAMENT_STAR_ROT: + lc->anim_r += 1.0; + if (lc->anim_r >= 45.0) + { + lc->anim_r = 45.0; + lc->type = LAMENT_STAR_ROT_IN; + lc->anim_pause = pause; + } + break; + + case LAMENT_STAR_ROT_IN: + lc->anim_z -= 0.01; + if (lc->anim_z <= 0.0) + { + lc->anim_z = 0.0; + lc->type = LAMENT_STAR_ROT_OUT; + lc->anim_pause = pause3 * (1 + (random() % 4) + (random() % 4)); + } + break; + + case LAMENT_STAR_ROT_OUT: + lc->anim_z += 0.01; + if (lc->anim_z >= 1.0) + { + lc->anim_z = 1.0; + lc->type = LAMENT_STAR_UNROT; + lc->anim_pause = pause; + } + break; + + case LAMENT_STAR_UNROT: + lc->anim_r -= 1.0; + if (lc->anim_r <= 0.0) + { + lc->anim_r = 0.0; + lc->type = LAMENT_STAR_IN; + lc->anim_pause = pause; + } + break; + + case LAMENT_STAR_IN: + lc->anim_z -= 0.01; + if (lc->anim_z <= 0.0) + { + lc->anim_z = 0.0; + lc->type = LAMENT_BOX; + lc->anim_pause = pause3; + } + break; + + /* -------------------------------------------------------------- */ + + case LAMENT_TETRA_UNE: + case LAMENT_TETRA_USW: + case LAMENT_TETRA_DWN: + case LAMENT_TETRA_DSE: + + lc->anim_r += 1.0; + if (lc->anim_r >= 360.0) + { + lc->anim_r = 0.0; + lc->type = LAMENT_BOX; + lc->anim_pause = pause3; + } + else if (lc->anim_r > 119.0 && lc->anim_r <= 120.0) + { + lc->anim_r = 120.0; + lc->anim_pause = pause; + } + else if (lc->anim_r > 239.0 && lc->anim_r <= 240.0) + { + lc->anim_r = 240.0; + lc->anim_pause = pause; + } + break; + + /* -------------------------------------------------------------- */ + + case LAMENT_LID_OPEN: + lc->anim_r += 1.0; + + if (lc->anim_r >= 112.0) + { + lc->anim_r = 112.0; + lc->anim_z = 0.0; + lc->anim_pause = pause3; + lc->type = (lc->facing_p ? LAMENT_LID_ZOOM : LAMENT_LID_CLOSE); + } + break; + + case LAMENT_LID_CLOSE: + lc->anim_r -= 1.0; + if (lc->anim_r <= 0.0) + { + lc->anim_r = 0.0; + lc->type = LAMENT_BOX; + lc->anim_pause = pause3; + } + break; + + case LAMENT_LID_ZOOM: + lc->anim_z -= 0.1; + if (lc->anim_z < -50.0) + { + lc->anim_r = 0.0; + lc->anim_z = 0.0; + lc->type = LAMENT_BOX; + } + break; + + /* -------------------------------------------------------------- */ + + case LAMENT_TASER_OUT: + lc->anim_z += 0.0025; + if (lc->anim_z >= 0.25) + { + lc->anim_z = 0.25; + lc->type = LAMENT_TASER_SLIDE; + lc->anim_pause = pause * (1 + (random() % 5) + (random() % 5)); + } + break; + + case LAMENT_TASER_SLIDE: + lc->anim_y += 0.0025; + if (lc->anim_y >= 0.23) + { + lc->anim_y = 0.23; + lc->type = LAMENT_TASER_SLIDE_IN; + lc->anim_pause = pause3 * (1 + (random() % 5) + (random() % 5)); + } + break; + + case LAMENT_TASER_SLIDE_IN: + lc->anim_y -= 0.0025; + if (lc->anim_y <= 0.0) + { + lc->anim_y = 0.0; + lc->type = LAMENT_TASER_IN; + lc->anim_pause = pause; + } + break; + + case LAMENT_TASER_IN: + lc->anim_z -= 0.0025; + if (lc->anim_z <= 0.0) + { + lc->anim_z = 0.0; + lc->type = LAMENT_BOX; + lc->anim_pause = pause3; + } + break; + + default: + abort(); + break; + } +} + + + +/* Window management, etc + */ + +ENTRYPOINT void +reshape_lament(ModeInfo *mi, int width, int height) +{ + GLfloat h = (GLfloat) height / (GLfloat) width; + glViewport(0, 0, (GLint) width, (GLint) height); + + glMatrixMode(GL_PROJECTION); + glLoadIdentity(); + glFrustum(-1.0, 1.0, -h, h, 5.0, 60.0); + glMatrixMode(GL_MODELVIEW); + glLoadIdentity(); + glTranslatef(0.0, 0.0, -40.0); + glClear(GL_COLOR_BUFFER_BIT); +} + + +static void +gl_init(ModeInfo *mi) +{ + lament_configuration *lc = &lcs[MI_SCREEN(mi)]; + Bool wire = MI_IS_WIREFRAME(mi); + + if (wire) + do_texture = False; + + if (!wire) + { + static const GLfloat pos0[] = { -4.0, 2.0, 5.0, 1.0 }; + static const GLfloat pos1[] = { 6.0, -1.0, 3.0, 1.0 }; + + static const GLfloat amb0[] = { 0.7, 0.7, 0.7, 1.0 }; +/* static const GLfloat amb1[] = { 0.7, 0.0, 0.0, 1.0 }; */ + static const GLfloat dif0[] = { 1.0, 1.0, 1.0, 1.0 }; + static const GLfloat dif1[] = { 0.3, 0.1, 0.1, 1.0 }; + + glLightfv(GL_LIGHT0, GL_POSITION, pos0); + glLightfv(GL_LIGHT1, GL_POSITION, pos1); + + glLightfv(GL_LIGHT0, GL_AMBIENT, amb0); +/* glLightfv(GL_LIGHT1, GL_AMBIENT, amb1); */ + glLightfv(GL_LIGHT0, GL_DIFFUSE, dif0); + glLightfv(GL_LIGHT1, GL_DIFFUSE, dif1); + set_colors(exterior_color); + + glEnable(GL_LIGHTING); + glEnable(GL_LIGHT0); +/* glEnable(GL_LIGHT1); */ + + glEnable(GL_DEPTH_TEST); + glEnable(GL_TEXTURE_2D); + glEnable(GL_NORMALIZE); + glEnable(GL_CULL_FACE); + } + + if (do_texture) + { +#ifdef HAVE_GLBINDTEXTURE + int i; + for (i = 0; i < 6; i++) + glGenTextures(1, &lc->texids[i]); + + parse_image_data(mi); + + glPixelStorei(GL_UNPACK_ALIGNMENT, 4); + /* messes up -fps */ + /* glPixelStorei(GL_UNPACK_ROW_LENGTH, lc->texture->width); */ + + for (i = 0; i < 6; i++) + { + int height = lc->texture->width; /* assume square */ + glBindTexture(GL_TEXTURE_2D, lc->texids[i]); + set_colors(exterior_color); + + clear_gl_error(); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, + lc->texture->width, height, 0, + GL_RGBA, + /* GL_UNSIGNED_BYTE, */ + GL_UNSIGNED_INT_8_8_8_8_REV, + (lc->texture->data + + (lc->texture->bytes_per_line * height * i))); + check_gl_error("texture"); + + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + } + +#else /* !HAVE_GLBINDTEXTURE */ + fprintf(stderr, + "%s: this version of GL doesn't support multiple texture maps.\n" + "\tGet OpenGL 1.1.\n", + progname); + exit (1); +#endif /* !HAVE_GLBINDTEXTURE */ + } + + lc->box = glGenLists(16); + lc->star1 = lc->box+1; + lc->star2 = lc->box+2; + lc->tetra_une = lc->box+3; + lc->tetra_usw = lc->box+4; + lc->tetra_dwn = lc->box+5; + lc->tetra_dse = lc->box+6; + lc->tetra_mid = lc->box+7; + lc->lid_0 = lc->box+8; + lc->lid_1 = lc->box+9; + lc->lid_2 = lc->box+10; + lc->lid_3 = lc->box+11; + lc->lid_4 = lc->box+12; + lc->taser_base = lc->box+13; + lc->taser_lifter = lc->box+14; + lc->taser_slider = lc->box+15; + + box(mi, wire); + star(mi, True, wire); + star(mi, False, wire); + tetra(mi, wire); + lid(mi, wire); + taser(mi, wire); +} + + +# ifdef HAVE_MESA_GL + +# include + +static RETSIGTYPE +lament_signal_kludge (int sig) +{ + signal (sig, SIG_DFL); + fprintf (stderr, + "\n" + "%s: dying with signal %d (%s).\n" + "\n" + "\tThis is almost certainly a bug in the Mesa GL library,\n" + "\tespecially if the stack trace in the core file mentions\n" + "\t`lambda_textured_triangle' or `render_quad'.\n" + "\n" + "\tFirst make sure that you have the latest version of Mesa.\n" + "\tIf that doesn't fix it, then I encourage you to report this\n" + "\tbug to the Mesa maintainers at .\n" + "\n", + progname, + sig, + (sig == SIGILL ? "SIGILL" : + sig == SIGFPE ? "SIGFPE" : + sig == SIGBUS ? "SIGBUS" : + sig == SIGSEGV ? "SIGSEGV" : "???")); + fflush (stderr); + kill (getpid (), sig); +} + +static void +handle_signals (void) +{ + signal (SIGILL, lament_signal_kludge); + signal (SIGFPE, lament_signal_kludge); + signal (SIGBUS, lament_signal_kludge); + signal (SIGSEGV, lament_signal_kludge); +} +# endif /* HAVE_MESA_GL */ + + +ENTRYPOINT void +init_lament(ModeInfo *mi) +{ + lament_configuration *lc; + if (!lcs) + { + lcs = (lament_configuration *) + calloc(MI_NUM_SCREENS(mi), sizeof (lament_configuration)); + if (!lcs) + { + fprintf(stderr, "%s: out of memory\n", progname); + exit(1); + } + } + + lc = &lcs[MI_SCREEN(mi)]; + + { + double rot_speed = 0.5; + lc->rot = make_rotator (rot_speed, rot_speed, rot_speed, 1, 0, True); + lc->trackball = gltrackball_init (); + } + + lc->type = LAMENT_BOX; + lc->anim_pause = 300 + (random() % 100); + + if ((lc->glx_context = init_GL(mi)) != NULL) + { + reshape_lament(mi, MI_WIDTH(mi), MI_HEIGHT(mi)); + gl_init(mi); + } + + lc->states = (lament_type *) calloc (50, sizeof (*lc->states)); + lc->nstates = 0; + lc->states[lc->nstates++] = LAMENT_STAR_OUT; + lc->states[lc->nstates++] = LAMENT_STAR_OUT; + lc->states[lc->nstates++] = LAMENT_TETRA_UNE; + lc->states[lc->nstates++] = LAMENT_TETRA_USW; + lc->states[lc->nstates++] = LAMENT_TETRA_DWN; + lc->states[lc->nstates++] = LAMENT_TETRA_DSE; + lc->states[lc->nstates++] = LAMENT_LID_OPEN; + lc->states[lc->nstates++] = LAMENT_LID_OPEN; + lc->states[lc->nstates++] = LAMENT_LID_OPEN; + lc->states[lc->nstates++] = LAMENT_TASER_OUT; + lc->states[lc->nstates++] = LAMENT_TASER_OUT; + lc->states[lc->nstates++] = LAMENT_BOX; + lc->states[lc->nstates++] = LAMENT_BOX; + lc->states[lc->nstates++] = LAMENT_BOX; + lc->states[lc->nstates++] = LAMENT_BOX; + lc->states[lc->nstates++] = LAMENT_BOX; + lc->states[lc->nstates++] = LAMENT_BOX; + lc->states[lc->nstates++] = LAMENT_BOX; + lc->states[lc->nstates++] = LAMENT_BOX; + lc->states[lc->nstates++] = LAMENT_BOX; + lc->states[lc->nstates++] = LAMENT_BOX; + shuffle_states (lc); + +# ifdef HAVE_MESA_GL + handle_signals (); +# endif /* HAVE_MESA_GL */ +} + + +ENTRYPOINT void +draw_lament(ModeInfo *mi) +{ + lament_configuration *lc = &lcs[MI_SCREEN(mi)]; + Display *dpy = MI_DISPLAY(mi); + Window window = MI_WINDOW(mi); + + if (!lc->glx_context) + return; + + glDrawBuffer(GL_BACK); + + glXMakeCurrent(dpy, window, *(lc->glx_context)); + draw(mi); + if (mi->fps_p) do_fps (mi); + + glFinish(); + glXSwapBuffers(dpy, window); + + if (lc->anim_pause) + lc->anim_pause--; + else + animate(mi); +} + +XSCREENSAVER_MODULE ("Lament", lament) + +#endif /* USE_GL */ diff --git a/hacks/glx/lament.man b/hacks/glx/lament.man new file mode 100644 index 00000000..2077dd67 --- /dev/null +++ b/hacks/glx/lament.man @@ -0,0 +1,68 @@ +.TH XScreenSaver 1 "25-Jul-98" "X Version 11" +.SH NAME +lament - animates the Lament Configuration +.SH SYNOPSIS +.B lament +[\-display \fIhost:display.screen\fP] [\-window] [\-root] [\-install] +[\-visual \fIvisual\fP] [\-delay \fImicroseconds\fP] [\-fps] +[\-texture] [\-no\-texture] [\-wireframe] +.SH DESCRIPTION +The \fIlament\fP program draws an animation of a particular puzzle box +repeatedly solving itself. +.SH OPTIONS +.I lament +accepts the following options: +.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 \-install +Install a private colormap for the window. +.TP 8 +.B \-visual \fIvisual\fP\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 \-texture +Use texture maps. This is the default. +.TP 8 +.B \-no\-texture +Do not use texture maps. This is boring and wrong. +.TP 8 +.B \-wireframe +Only draw outlines. +.TP 8 +.B \-delay \fImicroseconds\fP +How long to pause between frames. Default is 20000, or 0.02 second. +.TP 8 +.B \-fps +Display the current frame rate, CPU load, and polygon count. +.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 BUGS +This hack is glacially slow on machines lacking hardware texture support. + +Occasionally opens doors, admitting theologians of the Order of the Gash. +.SH SEE ALSO +.BR X (1), +.BR xscreensaver (1) +.SH COPYRIGHT +Copyright \(co 1998 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 , 25-Jul-98. diff --git a/hacks/glx/lavalite.c b/hacks/glx/lavalite.c new file mode 100644 index 00000000..f80847f9 --- /dev/null +++ b/hacks/glx/lavalite.c @@ -0,0 +1,1569 @@ +/* lavalite --- 3D Simulation a Lava Lite, written by jwz. + * + * This software Copyright (c) 2002-2006 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. + * + * LAVA®, LAVA LITE®, LAVA WORLD INTERNATIONAL® and the configuration of the + * LAVA® brand motion lamp are registered trademarks of Haggerty Enterprises, + * Inc. The configuration of the globe and base of the motion lamp are + * registered trademarks of Haggerty Enterprises, Inc. in the U.S.A. and in + * other countries around the world. + * + * Official Lava Lite web site: http://www.lavaworld.com/ + * + * Implementation details: + * + * The blobs are generated using metaballs. For an explanation of what + * those are, see http://astronomy.swin.edu.au/~pbourke/modelling/implicitsurf/ + * or http://www.fifi.org/doc/povray-manual/pov30005.htm + * + * Basically, each bubble of lava is a few (4) overlapping spherical metaballs + * of various sizes following similar but slightly different steep, slow + * parabolic arcs from the bottom to the top and back. + * + * We then polygonize the surface of the lava using the marching squares + * algorithm implemented in marching.c. + * + * Like real lavalites, this program is very slow. + * + * Surprisingly, it's loading the CPU and not the graphics engine: the speed + * bottleneck is in *computing* the scene rather than *rendering* it. We + * actually don't use a huge number of polygons, but computing the mesh for + * the surface takes a lot of cycles. + * + * I eliminated all the square roots, but there is still a lot of + * floating-point multiplication in here. I tried optimizing away the + * fp divisions, but that didn't seem to make a difference. + * + * -style lamp shape: classic, giant, cone, rocket, or random. + * -speed frequency at which new blobs launch. + * -resolution density of the polygon mesh. + * -count max number of blobs allowed at once. + * -wander, -spin whether to roll the scene around the screen. + * -lava-color color of the blobbies + * -fluid-color color of the stuff the blobbies float in + * -base-color color of the base of the lamp + * -table-color color of the table under the lamp + * -impatient at startup, skip forward in the animation so + * that at least one blob is fully exposed. + * + * TODO: + * + * - make the table look better, somehow. + * - should the lava be emissive? should the one at the bottom be + * more brightly colored than the ones at the top? light distance? + * - is there some way to put a specular reflection on the front glass + * itself? Maybe render it twice with FRONT/BACK tweaked, or alpha + * with depth buffering turned off? + */ + +#define DEFAULTS "*delay: 30000 \n" \ + "*showFPS: False \n" \ + "*wireframe: False \n" \ + "*geometry: 600x900\n" \ + "*count: " DEF_COUNT " \n" \ + +# define refresh_lavalite 0 +# define release_lavalite 0 + + +#define BLOBS_PER_GROUP 4 + +#define GRAVITY 0.000013 /* odwnward acceleration */ +#define CONVECTION 0.005 /* initial upward velocity (bell curve) */ +#define TILT 0.00166666 /* horizontal velocity (bell curve) */ + +#undef countof +#define countof(x) (sizeof((x))/sizeof((*x))) + +#undef ABS +#define ABS(n) ((n)<0?-(n):(n)) +#undef SIGNOF +#define SIGNOF(n) ((n)<0?-1:1) + +#include "xlockmore.h" +#include "marching.h" +#include "rotator.h" +#include "gltrackball.h" +#include "xpm-ximage.h" +#include + +#ifdef USE_GL /* whole file */ + + +#define DEF_SPIN "Z" +#define DEF_WANDER "False" +#define DEF_SPEED "0.003" +#define DEF_RESOLUTION "40" +#define DEF_SMOOTH "True" +#define DEF_COUNT "3" +#define DEF_STYLE "random" +#define DEF_IMPATIENT "False" +#define DEF_LCOLOR "#FF0000" /* lava */ +#define DEF_FCOLOR "#00AAFF" /* fluid */ +#define DEF_BCOLOR "#666666" /* base */ +#define DEF_TCOLOR "#000000" /*"#00FF00"*/ /* table */ + +#define DEF_FTEX "(none)" +#define DEF_BTEX "(none)" +#define DEF_TTEX "(none)" + +typedef struct metaball metaball; + +struct metaball { + + Bool alive_p; + Bool static_p; + + double r; /* hard radius */ + double R; /* radius of field of influence */ + + double z; /* vertical position */ + double pos_r; /* position on horizontal circle */ + double pos_th; /* position on horizontal circle */ + double dr, dz; /* current velocity */ + + double x, y; /* h planar position - compused from the above */ + + metaball *leader; /* stay close to this other ball */ +}; + + +typedef enum { CLASSIC = 0, GIANT, CONE, ROCKET } lamp_style; +typedef enum { CAP = 100, BOTTLE, BASE } lamp_part; + +typedef struct { + lamp_part part; + GLfloat elevation; + GLfloat radius; + GLfloat texture_elevation; +} lamp_geometry; + +static const lamp_geometry classic_lamp[] = { + { CAP, 1.16, 0.089, 0.00 }, + { BOTTLE, 0.97, 0.120, 0.40 }, + { BOTTLE, 0.13, 0.300, 0.87 }, + { BOTTLE, 0.07, 0.300, 0.93 }, + { BASE, 0.00, 0.280, 0.00 }, + { BASE, -0.40, 0.120, 0.50 }, + { BASE, -0.80, 0.280, 1.00 }, + { 0, 0, 0, 0 }, +}; + +static const lamp_geometry giant_lamp[] = { + { CAP, 1.12, 0.105, 0.00 }, + { BOTTLE, 0.97, 0.130, 0.30 }, + { BOTTLE, 0.20, 0.300, 0.87 }, + { BOTTLE, 0.15, 0.300, 0.93 }, + { BASE, 0.00, 0.230, 0.00 }, + { BASE, -0.18, 0.140, 0.20 }, + { BASE, -0.80, 0.280, 1.00 }, + { 0, 0, 0, 0 }, +}; + +static const lamp_geometry cone_lamp[] = { + { CAP, 1.35, 0.001, 0.00 }, + { CAP, 1.35, 0.020, 0.00 }, + { CAP, 1.30, 0.055, 0.05 }, + { BOTTLE, 0.97, 0.120, 0.40 }, + { BOTTLE, 0.13, 0.300, 0.87 }, + { BASE, 0.00, 0.300, 0.00 }, + { BASE, -0.04, 0.320, 0.04 }, + { BASE, -0.60, 0.420, 0.50 }, + { 0, 0, 0, 0 }, +}; + +static const lamp_geometry rocket_lamp[] = { + { CAP, 1.35, 0.001, 0.00 }, + { CAP, 1.34, 0.020, 0.00 }, + { CAP, 1.30, 0.055, 0.05 }, + { BOTTLE, 0.97, 0.120, 0.40 }, + { BOTTLE, 0.13, 0.300, 0.87 }, + { BOTTLE, 0.07, 0.300, 0.93 }, + { BASE, 0.00, 0.280, 0.00 }, + { BASE, -0.50, 0.180, 0.50 }, + { BASE, -0.75, 0.080, 0.75 }, + { BASE, -0.80, 0.035, 0.80 }, + { BASE, -0.90, 0.035, 1.00 }, + { 0, 0, 0, 0 }, +}; + + + +typedef struct { + GLXContext *glx_context; + lamp_style style; + const lamp_geometry *model; + rotator *rot; + rotator *rot2; + trackball_state *trackball; + Bool button_down_p; + + GLfloat max_bottle_radius; /* radius of widest part of the bottle */ + + GLfloat launch_chance; /* how often to percolate */ + int blobs_per_group; /* how many metaballs we launch at once */ + Bool just_started_p; /* so we launch some goo right away */ + + int grid_size; /* resolution for marching-cubes */ + int nballs; + metaball *balls; + + GLuint bottle_list; + GLuint ball_list; + + int bottle_poly_count; /* polygons in the bottle only */ + +} lavalite_configuration; + +static lavalite_configuration *bps = NULL; + +static char *do_spin; +static char *do_style; +static GLfloat speed; +static Bool do_wander; +static int resolution; +static Bool do_smooth; +static Bool do_impatient; + +static char *lava_color_str, *fluid_color_str, *base_color_str, + *table_color_str; +static char *fluid_tex, *base_tex, *table_tex; + +static GLfloat lava_color[4], fluid_color[4], base_color[4], table_color[4]; + +static const GLfloat lava_spec[4] = {1.0, 1.0, 1.0, 1.0}; +static const GLfloat lava_shininess = 128.0; +static const GLfloat foot_color[4] = {0.2, 0.2, 0.2, 1.0}; + +static const GLfloat light0_pos[4] = {-0.6, 0.0, 1.0, 0.0}; +static const GLfloat light1_pos[4] = { 1.0, 0.0, 0.2, 0.0}; +static const GLfloat light2_pos[4] = { 0.6, 0.0, 1.0, 0.0}; + + + +static XrmOptionDescRec opts[] = { + { "-style", ".style", XrmoptionSepArg, 0 }, + { "-spin", ".spin", XrmoptionSepArg, 0 }, + { "+spin", ".spin", XrmoptionNoArg, "" }, + { "-speed", ".speed", XrmoptionSepArg, 0 }, + { "-wander", ".wander", XrmoptionNoArg, "True" }, + { "+wander", ".wander", XrmoptionNoArg, "False" }, + { "-resolution", ".resolution", XrmoptionSepArg, 0 }, + { "-smooth", ".smooth", XrmoptionNoArg, "True" }, + { "+smooth", ".smooth", XrmoptionNoArg, "False" }, + { "-impatient", ".impatient", XrmoptionNoArg, "True" }, + { "+impatient", ".impatient", XrmoptionNoArg, "False" }, + + { "-lava-color", ".lavaColor", XrmoptionSepArg, 0 }, + { "-fluid-color", ".fluidColor", XrmoptionSepArg, 0 }, + { "-base-color", ".baseColor", XrmoptionSepArg, 0 }, + { "-table-color", ".tableColor", XrmoptionSepArg, 0 }, + + { "-fluid-texture",".fluidTexture", XrmoptionSepArg, 0 }, + { "-base-texture", ".baseTexture", XrmoptionSepArg, 0 }, + { "-table-texture",".tableTexture", XrmoptionSepArg, 0 }, +}; + +static argtype vars[] = { + {&do_style, "style", "Style", DEF_STYLE, t_String}, + {&do_spin, "spin", "Spin", DEF_SPIN, t_String}, + {&do_wander, "wander", "Wander", DEF_WANDER, t_Bool}, + {&speed, "speed", "Speed", DEF_SPEED, t_Float}, + {&resolution, "resolution", "Resolution", DEF_RESOLUTION, t_Int}, + {&do_smooth, "smooth", "Smooth", DEF_SMOOTH, t_Bool}, + {&do_impatient, "impatient", "Impatient", DEF_IMPATIENT, t_Bool}, + + {&lava_color_str, "lavaColor", "LavaColor", DEF_LCOLOR, t_String}, + {&fluid_color_str, "fluidColor", "FluidColor", DEF_FCOLOR, t_String}, + {&base_color_str, "baseColor", "BaseColor", DEF_BCOLOR, t_String}, + {&table_color_str, "tableColor", "TableColor", DEF_TCOLOR, t_String}, + + {&fluid_tex, "fluidTexture", "FluidTexture", DEF_FTEX, t_String}, + {&base_tex, "baseTexture", "BaseTexture", DEF_BTEX, t_String}, + {&table_tex, "tableTexture", "BaseTexture", DEF_TTEX, t_String}, +}; + +ENTRYPOINT ModeSpecOpt lavalite_opts = {countof(opts), opts, countof(vars), vars, NULL}; + + +/* Window management, etc + */ +ENTRYPOINT void +reshape_lavalite (ModeInfo *mi, int width, int height) +{ + GLfloat h = (GLfloat) height / (GLfloat) width; + + glViewport (0, 0, (GLint) width, (GLint) height); + + glMatrixMode(GL_PROJECTION); + glLoadIdentity(); + gluPerspective (30.0, 1/h, 1.0, 100.0); + + glMatrixMode(GL_MODELVIEW); + glLoadIdentity(); + gluLookAt( 0.0, 0.0, 30.0, + 0.0, 0.0, 0.0, + 0.0, 1.0, 0.0); + + glClear(GL_COLOR_BUFFER_BIT); +} + + + +/* Textures + */ + +static Bool +load_texture (ModeInfo *mi, const char *filename) +{ + Display *dpy = mi->dpy; + Visual *visual = mi->xgwa.visual; + Colormap cmap = mi->xgwa.colormap; + char buf[1024]; + XImage *image; + + if (!filename || + !*filename || + !strcasecmp (filename, "(none)")) + { + glDisable (GL_TEXTURE_2D); + return False; + } + + image = xpm_file_to_ximage (dpy, visual, cmap, filename); + + clear_gl_error(); + 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); + + glPixelStorei (GL_UNPACK_ALIGNMENT, 4); + glPixelStorei (GL_UNPACK_ROW_LENGTH, image->width); + 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); + + glEnable (GL_TEXTURE_2D); + return True; +} + + + +/* Generating the lamp's bottle, caps, and base. + */ + +static int +draw_disc (GLfloat r, GLfloat z, int faces, Bool up_p, Bool wire) +{ + int j; + GLfloat th; + GLfloat step = M_PI * 2 / faces; + int polys = 0; + GLfloat x, y; + + glFrontFace (up_p ? GL_CW : GL_CCW); + glNormal3f (0, (up_p ? 1 : -1), 0); + glBegin (wire ? GL_LINE_LOOP : GL_TRIANGLES); + + x = r; + y = 0; + + for (j = 0, th = 0; j <= faces; j++) + { + glTexCoord2f (-j / (GLfloat) faces, 1); + glVertex3f (0, z, 0); + + glTexCoord2f (-j / (GLfloat) faces, 0); + glVertex3f (x, z, y); + + th += step; + x = r * cos (th); + y = r * sin (th); + + glTexCoord2f (-j / (GLfloat) faces, 0); + glVertex3f (x, z, y); + + polys++; + } + glEnd(); + + return polys; +} + + +static int +draw_tube (GLfloat r0, GLfloat r1, + GLfloat z0, GLfloat z1, + GLfloat t0, GLfloat t1, + int faces, Bool inside_out_p, Bool smooth_p, Bool wire) +{ + int polys = 0; + GLfloat th; + GLfloat x, y, x0=0, y0=0; + GLfloat step = M_PI * 2 / faces; + GLfloat s2 = step/2; + int i; + + glFrontFace (inside_out_p ? GL_CW : GL_CCW); + glBegin (wire ? GL_LINES : (smooth_p ? GL_QUAD_STRIP : GL_QUADS)); + + th = 0; + x = 1; + y = 0; + + if (!smooth_p) + { + x0 = cos (s2); + y0 = sin (s2); + } + + if (smooth_p) faces++; + + for (i = 0; i < faces; i++) + { + int nsign = (inside_out_p ? -1 : 1); + + if (smooth_p) + glNormal3f (x * nsign, z1, y * nsign); + else + glNormal3f (x0 * nsign, z1, y0 * nsign); + + glTexCoord2f (nsign * -i / (GLfloat) faces, 1-t1); + glVertex3f (x * r1, z1, y * r1); + + glTexCoord2f (nsign * -i / (GLfloat) faces, 1-t0); + glVertex3f (x * r0, z0, y * r0); + + th += step; + x = cos (th); + y = sin (th); + + if (!smooth_p) + { + x0 = cos (th + s2); + y0 = sin (th + s2); + + glTexCoord2f (nsign * -(i+1) / (double) faces, 1-t0); + glVertex3f (x * r0, z0, y * r0); + + glTexCoord2f (nsign * -(i+1) / (double) faces, 1-t1); + glVertex3f (x * r1, z1, y * r1); + } + + polys++; + } + glEnd(); + + return polys; +} + + +static int +draw_table (GLfloat z, Bool wire) +{ + GLfloat faces = 6; + GLfloat step = M_PI * 2 / faces; + GLfloat s = 8; + GLfloat th; + int j; + int polys = 0; + + glMaterialfv (GL_FRONT, GL_AMBIENT_AND_DIFFUSE, table_color); + + glFrontFace(GL_CW); + glNormal3f(0, 1, 0); + glBegin(wire ? GL_LINE_LOOP : GL_TRIANGLE_FAN); + + if (! wire) + { + glTexCoord2f (-0.5, 0.5); + glVertex3f(0, z, 0); + } + + for (j = 0, th = 0; j <= faces; j++) + { + GLfloat x = cos (th); + GLfloat y = sin (th); + glTexCoord2f (-(x+1)/2.0, (y+1)/2.0); + glVertex3f(x*s, z, y*s); + th += step; + polys++; + } + glEnd(); + return polys; +} + + +static int +draw_wing (GLfloat w, GLfloat h, GLfloat d, Bool wire) +{ + static const int coords[2][8][2] = { + { { 0, 0 }, + { 10, 10 }, + { 20, 23 }, + { 30, 41 }, + { 40, 64 }, + { 45, 81 }, + { 50, 103 }, + { 53, 134 } }, + { { 0, 54 }, + { 10, 57 }, + { 20, 64 }, + { 30, 75 }, + { 40, 92 }, + { 45, 104 }, + { 50, 127 }, + { 51, 134 } + } + }; + + int polys = 0; + int maxx = coords[0][countof(coords[0])-1][0]; + int maxy = coords[0][countof(coords[0])-1][1]; + unsigned int x; + + for (x = 1; x < countof(coords[0]); x++) + { + GLfloat px0 = (GLfloat) coords[0][x-1][0] / maxx * w; + GLfloat py0 = (GLfloat) coords[0][x-1][1] / maxy * h; + GLfloat px1 = (GLfloat) coords[1][x-1][0] / maxx * w; + GLfloat py1 = (GLfloat) coords[1][x-1][1] / maxy * h; + GLfloat px2 = (GLfloat) coords[0][x ][0] / maxx * w; + GLfloat py2 = (GLfloat) coords[0][x ][1] / maxy * h; + GLfloat px3 = (GLfloat) coords[1][x ][0] / maxx * w; + GLfloat py3 = (GLfloat) coords[1][x ][1] / maxy * h; + GLfloat zz = d/2; + + /* Left side + */ + glFrontFace (GL_CW); + glNormal3f (0, 0, -1); + glBegin (wire ? GL_LINE_LOOP : GL_QUADS); + + glTexCoord2f (px0, py0); glVertex3f (px0, -py0, -zz); + glTexCoord2f (px1, py1); glVertex3f (px1, -py1, -zz); + glTexCoord2f (px3, py3); glVertex3f (px3, -py3, -zz); + glTexCoord2f (px2, py2); glVertex3f (px2, -py2, -zz); + polys++; + glEnd(); + + /* Right side + */ + glFrontFace (GL_CCW); + glNormal3f (0, 0, -1); + glBegin (wire ? GL_LINE_LOOP : GL_QUADS); + glTexCoord2f(px0, py0); glVertex3f (px0, -py0, zz); + glTexCoord2f(px1, py1); glVertex3f (px1, -py1, zz); + glTexCoord2f(px3, py3); glVertex3f (px3, -py3, zz); + glTexCoord2f(px2, py2); glVertex3f (px2, -py2, zz); + polys++; + glEnd(); + + /* Top edge + */ + glFrontFace (GL_CCW); + glNormal3f (1, -1, 0); /* #### wrong */ + glBegin (wire ? GL_LINE_LOOP : GL_QUADS); + glTexCoord2f(px0, py0); glVertex3f (px0, -py0, -zz); + glTexCoord2f(px0, py0); glVertex3f (px0, -py0, zz); + glTexCoord2f(px2, py2); glVertex3f (px2, -py2, zz); + glTexCoord2f(px2, py2); glVertex3f (px2, -py2, -zz); + polys++; + glEnd(); + + /* Bottom edge + */ + glFrontFace (GL_CW); + glNormal3f (-1, 1, 0); /* #### wrong */ + glBegin (wire ? GL_LINE_LOOP : GL_QUADS); + glTexCoord2f(px1, py1); glVertex3f (px1, -py1, -zz); + glTexCoord2f(px1, py1); glVertex3f (px1, -py1, zz); + glTexCoord2f(px3, py3); glVertex3f (px3, -py3, zz); + glTexCoord2f(px3, py3); glVertex3f (px3, -py3, -zz); + polys++; + glEnd(); + + + } + + return polys; + +} + + +static void +generate_bottle (ModeInfo *mi) +{ + lavalite_configuration *bp = &bps[MI_SCREEN(mi)]; + int wire = MI_IS_WIREFRAME(mi); + int faces = resolution * 1.5; + Bool smooth = do_smooth; + + const lamp_geometry *top_slice = bp->model; + const char *current_texture = 0; + lamp_part last_part = 0; + + if (faces < 3) faces = 3; + else if (wire && faces > 20) faces = 20; + else if (faces > 60) faces = 60; + + bp->bottle_poly_count = 0; + + glNewList (bp->bottle_list, GL_COMPILE); + glPushMatrix(); + + glRotatef (90, 1, 0, 0); + glTranslatef (0, -0.5, 0); + + /* All parts of the lamp use the same specularity and shininess. */ + glMaterialfv (GL_FRONT, GL_SPECULAR, lava_spec); + glMateriali (GL_FRONT, GL_SHININESS, lava_shininess); + + while (1) + { + const lamp_geometry *bot_slice = top_slice + 1; + + const char *texture = 0; + GLfloat *color = 0; + GLfloat t0, t1; + + glDisable (GL_LIGHT2); + + switch (top_slice->part) + { + case CAP: + case BASE: + texture = base_tex; + color = base_color; + break; + case BOTTLE: + texture = fluid_tex; + color = fluid_color; + if (!wire) glEnable (GL_LIGHT2); /* light2 affects only fluid */ + break; + default: + abort(); + break; + } + + if (!wire && texture && texture != current_texture) + { + current_texture = texture; + load_texture (mi, current_texture); + } + + /* Color the discs darker than the tube walls. */ + glMaterialfv (GL_FRONT, GL_AMBIENT_AND_DIFFUSE, foot_color); + + /* Do a top disc if this is the first slice of the CAP or BASE. + */ + if ((top_slice->part == CAP && last_part == 0) || + (top_slice->part == BASE && last_part == BOTTLE)) + bp->bottle_poly_count += + draw_disc (top_slice->radius, top_slice->elevation, faces, + True, wire); + + /* Do a bottom disc if this is the last slice of the CAP or BASE. + */ + if ((top_slice->part == CAP && bot_slice->part == BOTTLE) || + (top_slice->part == BASE && bot_slice->part == 0)) + { + const lamp_geometry *sl = (bot_slice->part == 0 + ? top_slice : bot_slice); + bp->bottle_poly_count += + draw_disc (sl->radius, sl->elevation, faces, False, wire); + } + + if (bot_slice->part == 0) /* done! */ + break; + + /* Do a tube or cone + */ + glMaterialfv (GL_FRONT, GL_AMBIENT_AND_DIFFUSE, color); + + t0 = top_slice->texture_elevation; + t1 = bot_slice->texture_elevation; + + /* Restart the texture coordinates for the glass. + */ + if (top_slice->part == BOTTLE) + { + Bool first_p = (top_slice[-1].part != BOTTLE); + Bool last_p = (bot_slice->part != BOTTLE); + if (first_p) t0 = 0; + if (last_p) t1 = 1; + } + + bp->bottle_poly_count += + draw_tube (top_slice->radius, bot_slice->radius, + top_slice->elevation, bot_slice->elevation, + t0, t1, + faces, + (top_slice->part == BOTTLE), + smooth, wire); + + last_part = top_slice->part; + top_slice++; + } + + if (bp->style == ROCKET) + { + int i; + for (i = 0; i < 3; i++) + { + glPushMatrix(); + glRotatef (120 * i, 0, 1, 0); + glTranslatef (0.14, -0.05, 0); + bp->bottle_poly_count += draw_wing (0.4, 0.95, 0.02, wire); + glPopMatrix(); + } + glTranslatef (0, -0.1, 0); /* move floor down a little */ + } + + + if (!wire) load_texture (mi, table_tex); + glMaterialfv (GL_FRONT, GL_AMBIENT_AND_DIFFUSE, table_color); + bp->bottle_poly_count += draw_table (top_slice->elevation, wire); + + + glPopMatrix (); + glDisable (GL_TEXTURE_2D); /* done with textured objects */ + glEndList (); +} + + + + +/* Generating blobbies + */ + +static double +bellrand (double extent) /* like frand(), but a bell curve. */ +{ + return (((frand(extent) + frand(extent) + frand(extent)) / 3) + - (extent/2)); +} + + +static void move_ball (ModeInfo *mi, metaball *b); + +/* Bring a ball into play, and re-randomize its values. + */ +static void +reset_ball (ModeInfo *mi, metaball *b) +{ +/* lavalite_configuration *bp = &bps[MI_SCREEN(mi)]; */ + + b->r = 0.00001; + b->R = 0.12 + bellrand(0.10); + + b->pos_r = bellrand (0.9); + b->pos_th = frand(M_PI*2); + b->z = 0; + + b->dr = bellrand(TILT); + b->dz = CONVECTION; + + b->leader = 0; + + if (!b->alive_p) + b->alive_p = True; + + move_ball (mi, b); +} + + +/* returns the first metaball that is not in use, or 0. + */ +static metaball * +get_ball (ModeInfo *mi) +{ + lavalite_configuration *bp = &bps[MI_SCREEN(mi)]; + int i; + for (i = 0; i < bp->nballs; i++) + { + metaball *b = &bp->balls[i]; + if (!b->alive_p) + return b; + } + return 0; +} + + +/* Generate the blobs that don't move: the ones at teh top and bottom + that are part of the scenery. + */ +static void +generate_static_blobs (ModeInfo *mi) +{ + lavalite_configuration *bp = &bps[MI_SCREEN(mi)]; + metaball *b0, *b1; + int i; + + b0 = get_ball (mi); + if (!b0) abort(); + b0->static_p = True; + b0->alive_p = True; + b0->R = 0.6; + b0->r = 0.3; + + /* the giant blob at the bottom of the bottle. + */ + b0->pos_r = 0; + b0->pos_th = 0; + b0->dr = 0; + b0->dz = 0; + b0->x = 0; + b0->y = 0; + b0->z = -0.43; + + /* the small blob at the top of the bottle. + */ + b1 = get_ball (mi); + if (!b1) abort(); + + *b1 = *b0; + b1->R = 0.16; + b1->r = 0.135; + b1->z = 1.078; + + /* Some extra blobs at the bottom of the bottle, to jumble the surface. + */ + for (i = 0; i < bp->blobs_per_group; i++) + { + b1 = get_ball (mi); + if (!b1) abort(); + reset_ball (mi, b1); + b1->static_p = True; + b1->z = frand(0.04); + b1->dr = 0; + b1->dz = 0; + } +} + + +static GLfloat +max_bottle_radius (lavalite_configuration *bp) +{ + GLfloat r = 0; + const lamp_geometry *slice; + for (slice = bp->model; slice->part != 0; slice++) + { + if (slice->part == BOTTLE && slice->radius > r) + r = slice->radius; /* top */ + if (slice[1].radius > r) + r = slice[1].radius; /* bottom */ + } + return r; +} + + +static GLfloat +bottle_radius_at (lavalite_configuration *bp, GLfloat z) +{ + GLfloat topz = -999, botz = -999, topr = 0, botr = 0; + const lamp_geometry *slice; + GLfloat ratio; + + for (slice = bp->model; slice->part != 0; slice++) + if (z > slice->elevation) + { + slice--; + topz = slice->elevation; + topr = slice->radius; + break; + } + if (topz == -999) return 0; + + for (; slice->part != 0; slice++) + if (z > slice->elevation) + { + botz = slice->elevation; + botr = slice->radius; + break; + } + if (botz == -999) return 0; + + ratio = (z - botz) / (topz - botz); + + return (botr + ((topr - botr) * ratio)); +} + + +static void +move_ball (ModeInfo *mi, metaball *b) +{ + lavalite_configuration *bp = &bps[MI_SCREEN(mi)]; + double gravity = GRAVITY; + double real_r; + + if (b->static_p) return; + + b->pos_r += b->dr; + b->z += b->dz; + + b->dz -= gravity; + + if (b->pos_r > 0.9) + { + b->pos_r = 0.9; + b->dr = -b->dr; + } + else if (b->pos_r < 0) + { + b->pos_r = -b->pos_r; + b->dr = -b->dr; + } + + real_r = b->pos_r * bottle_radius_at (bp, b->z); + + b->x = cos (b->pos_th) * real_r; + b->y = sin (b->pos_th) * real_r; + + if (b->z < -b->R) /* dropped below bottom of glass - turn it off */ + b->alive_p = False; +} + + +/* This function makes sure that balls that are part of a group always stay + relatively close to each other. + */ +static void +clamp_balls (ModeInfo *mi) +{ + lavalite_configuration *bp = &bps[MI_SCREEN(mi)]; + int i; + for (i = 0; i < bp->nballs; i++) + { + metaball *b = &bp->balls[i]; + if (b->alive_p && b->leader) + { + double zslack = 0.1; + double minz = b->leader->z - zslack; + double maxz = b->leader->z + zslack; + + /* Try to keep the Z values near those of the leader. + Don't let it go out of range (above or below) and clamp it + if it does. If we've clamped it, make sure dz will be + moving it in the right direction (back toward the leader.) + + We aren't currently clamping r, only z -- doesn't seem to + be needed. + + This is kind of flaky, I think. Sometimes you can see + the blobbies "twitch". That's no good. + */ + + if (b->z < minz) + { + if (b->dz < 0) b->dz = -b->dz; + b->z = minz - b->dz; + } + + if (b->z > maxz) + { + if (b->dz > 0) b->dz = -b->dz; + b->z = maxz + b->dz; + } + } + } +} + + +static void +move_balls (ModeInfo *mi) /* for great justice */ +{ + lavalite_configuration *bp = &bps[MI_SCREEN(mi)]; + int i; + for (i = 0; i < bp->nballs; i++) + { + metaball *b = &bp->balls[i]; + if (b->alive_p) + move_ball (mi, b); + } + + clamp_balls (mi); +} + + + +/* Rendering blobbies using marching cubes. + */ + +static double +compute_metaball_influence (lavalite_configuration *bp, + double x, double y, double z, + int nballs, metaball *balls) +{ + double vv = 0; + int i; + + for (i = 0; i < nballs; i++) + { + metaball *b = &balls[i]; + double dx, dy, dz; + double d2, r, R, r2, R2; + + if (!b->alive_p) continue; + + dx = x - b->x; + dy = y - b->y; + dz = z - b->z; + R = b->R; + + if (dx > R || dx < -R || /* quick check before multiplying */ + dy > R || dy < -R || + dz > R || dz < -R) + continue; + + d2 = (dx*dx + dy*dy + dz*dz); + r = b->r; + + r2 = r*r; + R2 = R*R; + + if (d2 <= r2) /* (d <= r) inside the hard radius */ + vv += 1; + else if (d2 > R2) /* (d > R) outside the radius of influence */ + ; + else /* somewhere in between: linear drop-off from r=1 to R=0 */ + { + /* was: vv += 1 - ((d-r) / (R-r)); */ + vv += 1 - ((d2-r2) / (R2-r2)); + } + } + + return vv; +} + + +/* callback for marching_cubes() */ +static void * +obj_init (double grid_size, void *closure) +{ + lavalite_configuration *bp = (lavalite_configuration *) closure; + bp->grid_size = grid_size; + + return closure; +} + + +/* Returns True if the given point is outside of the glass tube. + */ +static double +clipped_by_glass_p (double x, double y, double z, + lavalite_configuration *bp) +{ + double d2, or, or2, ir2; + + or = bp->max_bottle_radius; + + if (x > or || x < -or || /* quick check before multiplying */ + y > or || y < -or) + return 0; + + d2 = (x*x + y*y); + or = bottle_radius_at (bp, z); + + or2 = or*or; + + if (d2 > or2) /* (sqrt(d) > or) */ + return 0; + + ir2 = or2 * 0.7; + + if (d2 > ir2) /* (sqrt(d) > ir) */ + { + double dr1 = or2; + double dr2 = ir2; + /* was: (1 - (d-ratio2) / (ratio1-ratio2)) */ + return (1 - (d2-dr2) / (dr1-dr2)); + } + + return 1; +} + + + +/* callback for marching_cubes() */ +static double +obj_compute (double x, double y, double z, void *closure) +{ + lavalite_configuration *bp = (lavalite_configuration *) closure; + double clip; + + x /= bp->grid_size; /* convert from 0-N to 0-1. */ + y /= bp->grid_size; + z /= bp->grid_size; + + x -= 0.5; /* X and Y range from -.5 to +.5; z ranges from 0-1. */ + y -= 0.5; + + clip = clipped_by_glass_p (x, y, z, bp); + if (clip == 0) return 0; + + return (clip * + compute_metaball_influence (bp, x, y, z, bp->nballs, bp->balls)); +} + + +/* callback for marching_cubes() */ +static void +obj_free (void *closure) +{ +} + + +/* Send a new blob travelling upward. + This blob will actually be composed of N metaballs that are near + each other. + */ +static void +launch_balls (ModeInfo *mi) +{ + lavalite_configuration *bp = &bps[MI_SCREEN(mi)]; + metaball *b0 = get_ball (mi); + int i; + + if (!b0) return; + reset_ball (mi, b0); + + for (i = 0; i < bp->blobs_per_group; i++) + { + metaball *b1 = get_ball (mi); + if (!b1) break; + *b1 = *b0; + + reset_ball (mi, b1); + b1->leader = b0; + +# define FROB(FIELD,AMT) \ + b1->FIELD += (bellrand(AMT) * b0->FIELD) + + /* FROB (pos_r, 0.7); */ + /* FROB (pos_th, 0.7); */ + FROB (dr, 0.8); + FROB (dz, 0.6); +# undef FROB + } + +} + + +static void +animate_lava (ModeInfo *mi) +{ + lavalite_configuration *bp = &bps[MI_SCREEN(mi)]; + int wire = MI_IS_WIREFRAME(mi); + Bool just_started_p = bp->just_started_p; + + double isolevel = 0.3; + + /* Maybe bubble a new blobby to the surface. + */ + if (just_started_p || + frand(1.0) < bp->launch_chance) + { + bp->just_started_p = False; + launch_balls (mi); + + if (do_impatient && just_started_p) + while (1) + { + int i; + move_balls (mi); + for (i = 0; i < bp->nballs; i++) + { + metaball *b = &bp->balls[i]; + if (b->alive_p && !b->static_p && !b->leader && + b->z > 0.5) + goto DONE; + } + } + DONE: ; + } + + move_balls (mi); + + glNewList (bp->ball_list, GL_COMPILE); + glPushMatrix(); + + glMaterialfv (GL_FRONT, GL_SPECULAR, lava_spec); + glMateriali (GL_FRONT, GL_SHININESS, lava_shininess); + glMaterialfv (GL_FRONT, GL_AMBIENT_AND_DIFFUSE, lava_color); + + /* For the blobbies, the origin is on the axis at the bottom of the + glass bottle; and the top of the bottle is +1 on Z. + */ + glTranslatef (0, 0, -0.5); + + mi->polygon_count = 0; + { + double s; + if (bp->grid_size == 0) bp->grid_size = 1; /* first time through */ + s = 1.0/bp->grid_size; + + glPushMatrix(); + glTranslatef (-0.5, -0.5, 0); + glScalef (s, s, s); + marching_cubes (resolution, isolevel, wire, do_smooth, + obj_init, obj_compute, obj_free, bp, + &mi->polygon_count); + glPopMatrix(); + } + + mi->polygon_count += bp->bottle_poly_count; + + glPopMatrix(); + glEndList (); +} + + + +/* Startup initialization + */ + +ENTRYPOINT Bool +lavalite_handle_event (ModeInfo *mi, XEvent *event) +{ + lavalite_configuration *bp = &bps[MI_SCREEN(mi)]; + + if (event->xany.type == ButtonPress && + event->xbutton.button == Button1) + { + bp->button_down_p = True; + gltrackball_start (bp->trackball, + event->xbutton.x, event->xbutton.y, + MI_WIDTH (mi), MI_HEIGHT (mi)); + return True; + } + else if (event->xany.type == ButtonRelease && + event->xbutton.button == Button1) + { + bp->button_down_p = False; + return True; + } + else if (event->xany.type == ButtonPress && + (event->xbutton.button == Button4 || + event->xbutton.button == Button5 || + event->xbutton.button == Button6 || + event->xbutton.button == Button7)) + { + gltrackball_mousewheel (bp->trackball, event->xbutton.button, 5, + !!event->xbutton.state); + return True; + } + else if (event->xany.type == MotionNotify && + bp->button_down_p) + { + gltrackball_track (bp->trackball, + event->xmotion.x, event->xmotion.y, + MI_WIDTH (mi), MI_HEIGHT (mi)); + return True; + } + + return False; +} + + +static void +parse_color (ModeInfo *mi, const char *name, const char *s, GLfloat *a) +{ + XColor c; + a[3] = 1.0; /* alpha */ + + if (! XParseColor (MI_DISPLAY(mi), MI_COLORMAP(mi), s, &c)) + { + fprintf (stderr, "%s: can't parse %s color %s", progname, name, s); + exit (1); + } + a[0] = c.red / 65536.0; + a[1] = c.green / 65536.0; + a[2] = c.blue / 65536.0; +} + + +ENTRYPOINT void +init_lavalite (ModeInfo *mi) +{ + lavalite_configuration *bp; + int wire = MI_IS_WIREFRAME(mi); + + if (!bps) { + bps = (lavalite_configuration *) + calloc (MI_NUM_SCREENS(mi), sizeof (lavalite_configuration)); + if (!bps) { + fprintf(stderr, "%s: out of memory\n", progname); + exit(1); + } + } + + bp = &bps[MI_SCREEN(mi)]; + + bp->glx_context = init_GL(mi); + + reshape_lavalite (mi, MI_WIDTH(mi), MI_HEIGHT(mi)); + + { + char *s = do_style; + if (!s || !*s || !strcasecmp (s, "classic")) bp->style = CLASSIC; + else if (!strcasecmp (s, "giant")) bp->style = GIANT; + else if (!strcasecmp (s, "cone")) bp->style = CONE; + else if (!strcasecmp (s, "rocket")) bp->style = ROCKET; + else if (!strcasecmp (s, "random")) + { + if (random() & 1) bp->style = CLASSIC; /* half the time */ + else bp->style = (random() % ((int) ROCKET+1)); + } + else + { + fprintf (stderr, + "%s: style must be Classic, Giant, Cone, or Rocket (not \"%s\")\n", + progname, s); + exit (1); + } + } + + parse_color (mi, "lava", lava_color_str, lava_color); + parse_color (mi, "fluid", fluid_color_str, fluid_color); + parse_color (mi, "base", base_color_str, base_color); + parse_color (mi, "table", table_color_str, table_color); + + if (!wire) + { + GLfloat amb[4] = {0.0, 0.0, 0.0, 1.0}; + GLfloat dif[4] = {1.0, 1.0, 1.0, 1.0}; + GLfloat spc0[4] = {0.0, 1.0, 1.0, 1.0}; + GLfloat spc1[4] = {1.0, 0.0, 1.0, 1.0}; + + glEnable(GL_LIGHTING); + glEnable(GL_LIGHT0); + glEnable(GL_LIGHT1); + glEnable(GL_DEPTH_TEST); + glEnable(GL_CULL_FACE); + glEnable(GL_NORMALIZE); + glShadeModel(GL_SMOOTH); + + glLightfv(GL_LIGHT0, GL_AMBIENT, amb); + glLightfv(GL_LIGHT0, GL_DIFFUSE, dif); + glLightfv(GL_LIGHT0, GL_SPECULAR, spc0); + + glLightfv(GL_LIGHT1, GL_AMBIENT, amb); + glLightfv(GL_LIGHT1, GL_DIFFUSE, dif); + glLightfv(GL_LIGHT1, GL_SPECULAR, spc1); + + glLightfv(GL_LIGHT2, GL_AMBIENT, amb); + glLightfv(GL_LIGHT2, GL_DIFFUSE, dif); + glLightfv(GL_LIGHT2, GL_SPECULAR, spc0); + } + + { + Bool spinx=False, spiny=False, spinz=False; + double spin_speed = 0.4; + double wander_speed = 0.03; + + char *s = do_spin; + while (*s) + { + if (*s == 'x' || *s == 'X') spinx = True; + else if (*s == 'y' || *s == 'Y') spiny = True; + else if (*s == 'z' || *s == 'Z') spinz = True; + else if (*s == '0') ; + else + { + fprintf (stderr, + "%s: spin must contain only the characters X, Y, or Z (not \"%s\")\n", + progname, do_spin); + exit (1); + } + s++; + } + + bp->rot = make_rotator (spinx ? spin_speed : 0, + spiny ? spin_speed : 0, + spinz ? spin_speed : 0, + 1.0, + do_wander ? wander_speed : 0, + False); + bp->rot2 = make_rotator (spin_speed, 0, 0, + 1, 0.1, + False); + bp->trackball = gltrackball_init (); + + /* move initial camera position up by around 15 degrees: + in other words, tilt the scene toward the viewer. */ + gltrackball_start (bp->trackball, 50, 50, 100, 100); + gltrackball_track (bp->trackball, 50, 5, 100, 100); + + /* Oh, but if it's the "Giant" model, tilt the scene away: make it + look like we're looking up at it instead of down at it! */ + if (bp->style == GIANT) + gltrackball_track (bp->trackball, 50, -12, 100, 100); + else if (bp->style == ROCKET) /* same for rocket, but not as much */ + gltrackball_track (bp->trackball, 50, -4, 100, 100); + } + + switch (bp->style) + { + case CLASSIC: bp->model = classic_lamp; break; + case GIANT: bp->model = giant_lamp; break; + case CONE: bp->model = cone_lamp; break; + case ROCKET: bp->model = rocket_lamp; break; + default: abort(); break; + } + + bp->max_bottle_radius = max_bottle_radius (bp); + + bp->launch_chance = speed; + bp->blobs_per_group = BLOBS_PER_GROUP; + bp->just_started_p = True; + + bp->nballs = (((MI_COUNT (mi) + 1) * bp->blobs_per_group) + + 2); + bp->balls = (metaball *) calloc (sizeof(*bp->balls), bp->nballs+1); + + bp->bottle_list = glGenLists (1); + bp->ball_list = glGenLists (1); + + generate_bottle (mi); + generate_static_blobs (mi); +} + + +/* Render one frame + */ + +ENTRYPOINT void +draw_lavalite (ModeInfo *mi) +{ + lavalite_configuration *bp = &bps[MI_SCREEN(mi)]; + Display *dpy = MI_DISPLAY(mi); + Window window = MI_WINDOW(mi); + + if (!bp->glx_context) + return; + + glXMakeCurrent(MI_DISPLAY(mi), MI_WINDOW(mi), *(bp->glx_context)); + + glMatrixMode (GL_MODELVIEW); + glPushMatrix (); + + { + double cx, cy, cz; /* camera position, 0-1. */ + double px, py, pz; /* object position, 0-1. */ + double rx, ry, rz; /* object rotation, 0-1. */ + + get_position (bp->rot2, 0, &cy, &cz, !bp->button_down_p); + get_rotation (bp->rot2, &cx, 0, 0, !bp->button_down_p); + + get_position (bp->rot, &px, &py, &pz, !bp->button_down_p); + get_rotation (bp->rot, &rx, &ry, &rz, !bp->button_down_p); + +#if 1 + cx = 0.5; + cy = 0.5; + cz = 1.0; + +#else /* #### this crud doesn't really work yet */ + + + /* We have c[xyz] parameters describing a camera position, but we don't + want to just map those to points in space: the lamp doesn't look very + good from the inside, or from underneath... + + Good observation points form a ring around the lamp: basically, a + torus ringing the lamp, parallel to the lamp's floor. + + We interpret cz as distance from the origin. + cy as elevation. + cx is then used as position in the torus (theta). + */ + + { + double cx2, cy2, cz2; + double d; + + cx2 = 0.5; + cy2 = 0.5; + cz2 = 1.0; + + cy2 = (cy * 0.4); /* cam elevation: 0.0 (table) - 0.4 up. */ + d = 0.9 + cz; /* cam distance: 0.9 - 1.9. */ + + cz2 = 0.5 + (d * cos (cx * M_PI * 2)); + cx2 = 0.5 + (d * sin (cx * M_PI * 2)); + + + cx = cx2; + cy = cy2; + cz = cz2; + } +#endif /* 0 */ + + glLoadIdentity(); + glRotatef(current_device_rotation(), 0, 0, 1); + + gluLookAt ((cx - 0.5) * 8, /* Position the camera */ + (cy - 0.5) * 8, + (cz - 0.5) * 8, + 0, 0, 0, + 0, 1, 0); + + gltrackball_rotate (bp->trackball); /* Apply mouse-based camera position */ + + /* Place the lights relative to the object, before the object has + been rotated or wandered within the scene. */ + glLightfv(GL_LIGHT0, GL_POSITION, light0_pos); + glLightfv(GL_LIGHT1, GL_POSITION, light1_pos); + glLightfv(GL_LIGHT2, GL_POSITION, light2_pos); + + + /* Position the lamp in the scene according to the "wander" settings */ + glTranslatef ((px - 0.5), (py - 0.5), (pz - 0.5)); + + /* Rotate the object according to the "spin" settings */ + glRotatef (rx * 360, 1.0, 0.0, 0.0); + glRotatef (ry * 360, 0.0, 1.0, 0.0); + glRotatef (rz * 360, 0.0, 0.0, 1.0); + + /* Move the lamp up slightly: make 0,0 be at its vertical center. */ + switch (bp->style) + { + case CLASSIC: glTranslatef (0, 0, 0.33); break; + case GIANT: glTranslatef (0, 0, 0.33); break; + case CONE: glTranslatef (0, 0, 0.16); break; + case ROCKET: glTranslatef (0, 0, 0.30); + glScalef (0.85,0.85,0.85); break; + default: abort(); break; + } + } + + animate_lava (mi); + + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + glCallList (bp->bottle_list); + glCallList (bp->ball_list); + glPopMatrix (); + + if (mi->fps_p) do_fps (mi); + glFinish(); + + glXSwapBuffers(dpy, window); +} + +XSCREENSAVER_MODULE ("Lavalite", lavalite) + +#endif /* USE_GL */ diff --git a/hacks/glx/lavalite.man b/hacks/glx/lavalite.man new file mode 100644 index 00000000..3d7aad5b --- /dev/null +++ b/hacks/glx/lavalite.man @@ -0,0 +1,160 @@ +.de EX \"Begin example +.ne 5 +.if n .sp 1 +.if t .sp .5 +.nf +.in +.5i +.. +.de EE +.fi +.in -.5i +.if n .sp 1 +.if t .sp .5 +.. +.TH XScreenSaver 1 "18-May-2002" "X Version 11" +.SH NAME +lavalite - 3D OpenGL simulation of a Lavalite. +.SH SYNOPSIS +.B lavalite +[\-display \fIhost:display.screen\fP] [\-window] [\-root] +[\-visual \fIvisual\fP] [\-delay \fImicroseconds\fP] [\-fps] +[\-style \fIstyle\fP ] +[\-spin \fIxyz\fP ] [\-no-spin ] +[\-speed \fIfloat\fP ] +[\-resolution \fIinteger\fP ] +[\-count \fIinteger\fP ] +[\-no-smooth ] +[\-wireframe ] +[\-impatient ] +[\-lava-color \fIcolor\fP ] +[\-fluid-color \fIcolor\fP ] +[\-base-color \fIcolor\fP ] +[\-table-color \fIcolor\fP ] +[\-fluid-texture \fIfilename\fP ] +[\-base-texture \fIfilename\fP ] +[\-table-texture \fIfilename\fP ] +.SH DESCRIPTION +The \fIlavalite\fP program displays a 3D simulation of the famous lamp +of the same name. It requires a fast computer with fast OpenGL support. +.SH OPTIONS +.I lavalite +accepts the following options: +.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 \-visual \fIvisual\fP\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 \-style \fIstyle\fP\fP +Specify which model of lamp to draw. Available models +are: \fBClassic\fP, \fBGiant\fP, \fBCone\fP, and \fBRocket\fP. +Default: random. +.TP 8 +.B \-spin \fIxyz\fP +Around which axes the model should auto-spin. Defaults to "Z", meaning +it rotates horizontally, but otherwise pitch or roll. +.TP 8 +.B \-no-spin +Same as \fB\-spin ''\fP. +.TP 8 +.B \-speed \fIfloat\fP +A number controlling the frequency at which new blobs launch: you can +think of this as being related to the the heat of the lightbulb in +the base. Default: 0.003. +.TP 8 +.B \-delay \fIusecs\fP +The delay between steps of the animation; default is 30000 (0.03 second.) +.TP 8 +.B \-resolution \fIinteger\fP +The size of the grid from which the mesh is created that is used +to polygonize the blobs. higher values will give very smooth looking +blobs, at the expense of speed. Default: 40. + +The options "-resolution 10 -no-smooth" look kind of interesting. +.TP 8 +.B \-fps +Display the current frame rate, CPU load, and polygon count. +.TP 8 +.B \-count \fIinteger\fP +The maximum number of blobs that can be in motion at once. +Default: 3. +.TP 8 +.B \-no-smooth +Turn off smoothing: the objects in the scene will be facetted. +.TP 8 +.B \-wireframe +Render all objects in wireframe instead of as solids. +.TP 8 +.B \-impatient +Provide this option if you are. This will pre-warm the lamp, so when it +starts up, the first frame will show a blob already halfway up the lamp. +.TP 8 +.B \-lava-color \fIcolor\fP +Specifies the color of the blobbies. Default: red. +.TP 8 +.B \-fluid-color \fIcolor\fP +Specifies the color of the fluid that the blobbies float in. +Default: light blue. +.TP 8 +.B \-base-color \fIcolor\fP +Specifies the color of the lamp base, and the cap on top of the bottle. +Default: very dark gray. +.TP 8 +.B \-table-color \fIcolor\fP +Specifies the color of the table that the lamp is sitting on. +Default: black (meaning it is invisible.) +.TP 8 +.B \-fluid-texture \fIfilename\fP +An image file to wrap around the glass. + +Note that on most systems, GL textures must have dimensions that are a +power of two. + +Note also that colors and textures are both applied: so, if you apply a +texture and it isn't showing up, try specifying the corresponding color +as "white". Otherwise, the combination of the two might be too dark to +see. +.TP 8 +.B \-base-texture \fIfilename\fP +An image file to wrap around the base of the lamp, and the cap on top +of the bottle. +.TP 8 +.B \-table-texture \fItexture\fP +An image file to spread across the table that the lamp is sitting on. +.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), + http://www.lavaworld.com/ + http://www.lavarnd.org/ +.SH COPYRIGHT +Copyright \(co 2002 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. + +LAVA LITE\(rg and the configuration of the LAVA\(rg brand motion lamp +are registered trademarks of Haggerty Enterprises, Inc. The +configuration of the globe and base of the motion lamp are registered +trademarks of Haggerty Enterprises, Inc. in the U.S.A. and in other +countries around the world. + +.SH AUTHOR +Jamie Zawinski diff --git a/hacks/glx/lockward.c b/hacks/glx/lockward.c new file mode 100644 index 00000000..9fb8c96c --- /dev/null +++ b/hacks/glx/lockward.c @@ -0,0 +1,934 @@ +/* + * lockward.c: First attempt at an Xscreensaver. + * + * Leo L. Schwab 2007.08.17 + **** + * Copyright (c) 2007 Leo L. Schwab + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to permit + * persons to whom the Software is furnished to do so, subject to the + * following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN + * NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR + * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE + * USE OR OTHER DEALINGS IN THE SOFTWARE. + */ +#include +#include + +#include "xlockmore.h" +#include "colors.h" + + +/*************************************************************************** + * #defines + */ +#ifdef USE_GL /* whole file */ + +#define DEFAULTS "*delay: 20000 \n"\ + "*showFPS: False \n" + +#define refresh_lockward 0 + + +#define NUMOF(x) (sizeof ((x)) / sizeof ((*x))) + +#define NBLADES 12 +#define NSPINNERS 4 +#define NRADII 8 +#define COLORIDX_SHF 4 + + +/*************************************************************************** + * Structure definitions. + */ +struct lockward_context; /* Forward declaration. */ + +#define int8_t char +#define int16_t short +#define int32_t int +#define uint8_t unsigned char +#define uint16_t unsigned short +#define uint32_t unsigned int + +typedef struct bladestate { + uint8_t outer, inner; /* Radii */ +} bladestate; + +typedef struct spinnerstate { + GLfloat rot; /* Terminal rotation after count expires */ + GLfloat rotinc; /* Per-frame increment to rot. */ + XColor *colors; + bladestate *bladeidx; + int ncolors; /* n.4 fixed-point */ + int ccolor; /* n.4 fixed-point */ + int colorinc; /* n.4 fixed-point */ + int rotcount; + uint8_t nblades; +} spinnerstate; + +typedef struct blinkstate { + int (*drawfunc) (struct lockward_context *ctx, + struct blinkstate *bs); + uint32_t *noise; /* For draw_blink_segment_scatter() */ + GLfloat color[4]; + uint32_t val; + int16_t dwell; /* <0: sharp >0: decay */ + int16_t dwellcnt; + uint8_t type; + int8_t counter; + int8_t direction; + int8_t radius; +} blinkstate; + +enum blinktype { + BTYPE_RADIAL_SINGLE = 0, + BTYPE_RADIAL_RANDOM, + BTYPE_RADIAL_SEQ, + BTYPE_RADIAL_DOUBLESEQ, + BTYPE_SEGMENT_SINGLE, + BTYPE_SEGMENT_RANDOM, + BTYPE_CONCENTRIC_SINGLE, + BTYPE_CONCENTRIC_RANDOM, + BTYPE_CONCENTRIC_SEQ, + BTYPE_SEGMENT_SCATTER, + MAX_BTYPE +}; + +typedef struct lockward_context { + GLXContext *glx_context; + + spinnerstate spinners[NSPINNERS]; + blinkstate blink; + + GLuint blades_outer, blades_inner; + GLuint rings; + Bool blendmode; + int nextblink; + int fps; +} lockward_context; + + +/*************************************************************************** + * Prototypes. + */ +static void free_lockward (lockward_context *ctx); + + +/*************************************************************************** + * Global variables. + */ +static lockward_context *g_ctx = NULL; +static Bool g_blink_p = True; +static int g_blades = NBLADES; +static int g_rotateidle_min, + g_rotateidle_max; +static int g_blinkidle_min, + g_blinkidle_max; +static int g_blinkdwell_min, + g_blinkdwell_max; + +#define DEF_BLINK "True" +#define DEF_ROTATEIDLEMIN "1000" +#define DEF_ROTATEIDLEMAX "6000" +#define DEF_BLINKIDLEMIN "1000" +#define DEF_BLINKIDLEMAX "9000" +#define DEF_BLINKDWELLMIN "100" +#define DEF_BLINKDWELLMAX "600" + + +static XrmOptionDescRec opts[] = { + { "-blink", ".blink", XrmoptionNoArg, "on" }, + { "+blink", ".blink", XrmoptionNoArg, "off" }, + { "-rotateidle-min", ".rotateidlemin", XrmoptionSepArg, 0 }, + { "-rotateidle-max", ".rotateidlemax", XrmoptionSepArg, 0 }, + { "-blinkidle-min", ".blinkidlemin", XrmoptionSepArg, 0 }, + { "-blinkidle-max", ".blinkidlemax", XrmoptionSepArg, 0 }, + { "-blinkdwell-min", ".blinkdwellmin", XrmoptionSepArg, 0 }, + { "-blinkdwell-max", ".blinkdwellmax", XrmoptionSepArg, 0 }, +}; + +static argtype vars[] = { + { &g_blink_p, "blink", "Blink", DEF_BLINK, t_Bool }, + { &g_rotateidle_min, "rotateidlemin", "Rotateidlemin", DEF_ROTATEIDLEMIN, t_Int }, + { &g_rotateidle_max, "rotateidlemax", "Rotateidlemax", DEF_ROTATEIDLEMAX, t_Int }, + { &g_blinkidle_min, "blinkidlemin", "Blinkidlemin", DEF_BLINKIDLEMIN, t_Int }, + { &g_blinkidle_max, "blinkidlemax", "Blinkidlemax", DEF_BLINKIDLEMAX, t_Int }, + { &g_blinkdwell_min, "blinkdwellmin", "Blinkdwellmin", DEF_BLINKDWELLMIN, t_Int }, + { &g_blinkdwell_max, "blinkdwellmax", "Blinkdwellmax", DEF_BLINKDWELLMAX, t_Int }, +}; + +static OptionStruct desc[] = { + { "-/+blink", "Turn on/off blinking effects." }, + { "-rotateidle-min", "Minimum idle time for rotators, in milliseconds." }, + { "-rotateidle-max", "Maximum idle time for rotators, in milliseconds." }, + { "-blinkidle-min", "Minimum idle time between blink effects, in milliseconds." }, + { "-blinkidle-max", "Maximum idle time between blink effects, in milliseconds." }, + { "-blinkdwell-min", "Minimum dwell time for blink effects, in milliseconds." }, + { "-blinkdwell-max", "Maximum dwell time for blink effects, in milliseconds." }, +}; + +ENTRYPOINT ModeSpecOpt lockward_opts = { + NUMOF(opts), opts, NUMOF(vars), vars, desc +}; + + +/*************************************************************************** + * Window management. + */ +ENTRYPOINT void +reshape_lockward (ModeInfo *mi, int width, int height) +{ + GLfloat h = (GLfloat) height / (GLfloat) width; + + glViewport (0, 0, (GLint) width, (GLint) height); + + glMatrixMode (GL_PROJECTION); + glLoadIdentity (); + if (height > width) + glOrtho (-8.0, 8.0, -8.0 * h, 8.0 * h, -1, 1); + else + glOrtho (-8.0 / h, 8.0 / h, -8.0, 8.0, -1, 1); + + glMatrixMode (GL_MODELVIEW); +} + +ENTRYPOINT Bool +lockward_handle_event (ModeInfo *mi, XEvent *event) +{ + lockward_context *ctx = &g_ctx[MI_SCREEN (mi)]; + + if (event->xany.type == KeyPress) { + KeySym keysym; + char c = 0; + + XLookupString (&event->xkey, &c, 1, &keysym, 0); + if (c == 'b') { + ctx->blendmode ^= 1; + return True; + } + } + + return False; +} + + +/*************************************************************************** + * "Blade" routines. + */ +static void +random_blade_rot (lockward_context *ctx, struct spinnerstate *ss) +{ + /* + * The circle is divided up in to g_blades divisions. The idea here + * is to rotate to an exact division point. + * + * The target rotation is computed via random numbers. + * + * The time it takes to get there is a maximum of six seconds per + * division, and a minimum of one second (no matter how far away it + * is), and is selected by random numbers. + * + * The time value is converted into frames, and a per-frame rotation + * is computed. + * + * During rendering, we approach the target rotation by subtracting + * from it the per-frame rotation times the number of outstanding + * ticks. Doing it this way means we'll hit the target rotation + * exactly, without low-order errors creeping in to the values (at + * least not nearly as quickly). + */ + GLfloat d; + int dist; + + dist = random() % g_blades + 1; + + ss->rotcount = random() % (6 * dist * ctx->fps - ctx->fps) + + ctx->fps; + + if (random() & 4) + dist = -dist; + d = dist * 360.0 / (GLfloat) g_blades; + ss->rot += d; + ss->rotinc = d / (GLfloat) ss->rotcount; +} + + +/* + * A "blade" is pie-wedge shaped flat thing that is rotated around where the + * apex is/would be. Initially envisioned as 1/12th of a circle, but that + * could be configurable. The inner and outer edges are rounded off using + * six subdivisions so that, when multiple blades are assembled, it looks + * more like a circle and less like a polygon. + * + * The blade is assembled as a tri-fan. It is oriented centered at 3 + * o'clock. The blade is composed of two display lists -- arcs, essentially + * -- the outer and the inner one. The outer one *must* be called before + * the inner one, or the blade clockwise-ness will be wrong, and become + * invisible. Arcs of various radii are compiled. + */ +#define SUBDIV 6 + +static void +gen_blade_arcs (lockward_context *ctx) +{ + GLfloat here, there, step; + int i, n; + + here = 0; + there = M_PI * 2.0 / g_blades; + step = there / SUBDIV; + here -= SUBDIV * step / 2.0; + + /* + * Build outer blade arcs. + * Start at left side of outer radius. Strike all its vertices. + */ + for (n = 0; n < NRADII; ++n) { + glNewList (ctx->blades_outer + n, GL_COMPILE); + for (i = SUBDIV; i >= 0; --i) + glVertex3f (cos (here + step * i) * (n + 1.0), + sin (here + step * i) * (n + 1.0), 0); + glEndList (); + } + + /* + * Build inner blade arcs. + * Move to inner radius, strike all vertices in opposite order. + */ + for (n = 0; n < NRADII; ++n) { + glNewList (ctx->blades_inner + n, GL_COMPILE); + for (i = 0; i <= SUBDIV; ++i) + glVertex3f (cos (here + step * i) * (n + 1.0), + sin (here + step * i) * (n + 1.0), 0); + glEndList (); + } +} + +static void +gen_rings (lockward_context *ctx) +{ + GLfloat step; + int i, n; + + step = M_PI * 2.0 / (g_blades * SUBDIV); + + for (n = 0; n < NRADII - 1; ++n) { + glNewList (ctx->rings + n, GL_COMPILE); + glBegin (GL_TRIANGLE_STRIP); + for (i = g_blades * SUBDIV; i >= 0; --i) { + glVertex3f (cos (step * i) * (n + 1.0), + sin (step * i) * (n + 1.0), 0); + glVertex3f (cos (step * i) * (n + 2.0), + sin (step * i) * (n + 2.0), 0); + } + glEnd(); + glEndList (); + } +} + + +/*************************************************************************** + * "Blink" routines. + */ +static int +calc_interval_frames (lockward_context *ctx, int min, int max) +{ + /* + * Compute random interval between min and max milliseconds. + * Returned value is in frames. + */ + register int i; + + i = min; + if (max > min) + i += random() % (max - min); + + return i * ctx->fps / 1000; +} + +static void +set_alpha_by_dwell (struct blinkstate *bs) +{ + if (bs->dwell > 0) + bs->color[3] = (GLfloat) bs->dwellcnt / (GLfloat) bs->dwell; + else + bs->color[3] = bs->dwellcnt > (-bs->dwell >> 2) ? 1.0 : 0.0; +} + +static void +draw_blink_blade (lockward_context *ctx, int inner, int outer) +{ + glBegin (GL_TRIANGLE_FAN); + glCallList (ctx->blades_outer + outer); + glCallList (ctx->blades_inner + inner); + glEnd (); +} + +static int +draw_blink_radial_random (lockward_context *ctx, struct blinkstate *bs) +{ + int i; + + /* + * There is no sense of direction in a random sweep, so re-use the + * 'direction' field to hold the current blade we're messing with. + */ + if (bs->dwellcnt < 0) { + if (bs->counter <= 0) { + bs->drawfunc = NULL; + return 0; + } + + /* + * Find available blade. Potentially very slow, depending on + * how unlucky we are. + */ + do { + i = random() % g_blades; + } while (bs->val & (1 << i)); + bs->val |= (1 << i); /* Mark as used. */ + bs->direction = i; + if ((bs->dwellcnt = bs->dwell) < 0) + bs->dwellcnt = -bs->dwellcnt; + + if ( bs->type == BTYPE_SEGMENT_SINGLE + || bs->type == BTYPE_SEGMENT_RANDOM) + bs->radius = random() % (NRADII - 1); + + --bs->counter; + } + + set_alpha_by_dwell (bs); + glBlendFunc (GL_DST_COLOR, GL_SRC_ALPHA); + glColor4fv (bs->color); + glRotatef (bs->direction * 360.0 / (GLfloat) g_blades, 0, 0, 1); + if (bs->radius >= 0) + draw_blink_blade (ctx, bs->radius, bs->radius + 1); + else + draw_blink_blade (ctx, 0, NRADII - 1); + + --bs->dwellcnt; + + return SUBDIV + SUBDIV; +} + +static int +draw_blink_radial_sequential (lockward_context *ctx, struct blinkstate *bs) +{ + if (bs->dwellcnt < 0) { + if (bs->counter <= 0) { + bs->drawfunc = NULL; + return 0; + } + if ((bs->dwellcnt = bs->dwell) < 0) + bs->dwellcnt = -bs->dwellcnt; + --bs->counter; + } + + set_alpha_by_dwell (bs); + glBlendFunc (GL_DST_COLOR, GL_SRC_ALPHA); + glColor4fv (bs->color); + glRotatef ((bs->counter * bs->direction + (int) bs->val) + * 360.0 / (GLfloat) g_blades, + 0, 0, 1); + draw_blink_blade (ctx, 0, NRADII - 1); + + --bs->dwellcnt; + + return SUBDIV + SUBDIV; +} + +static int +draw_blink_radial_doubleseq (lockward_context *ctx, struct blinkstate *bs) +{ + int polys; + + if (bs->dwellcnt < 0) { + if (bs->counter <= 0) { + bs->drawfunc = NULL; + return 0; + } + if ((bs->dwellcnt = bs->dwell) < 0) + bs->dwellcnt = -bs->dwellcnt; + --bs->counter; + } + + set_alpha_by_dwell (bs); + glBlendFunc (GL_DST_COLOR, GL_SRC_ALPHA); + glColor4fv (bs->color); + + glPushMatrix (); + glRotatef (((int) bs->val + bs->counter) * 360.0 / (GLfloat) g_blades, + 0, 0, 1); + draw_blink_blade (ctx, 0, NRADII - 1); + glPopMatrix (); + polys = SUBDIV + SUBDIV; + + if (bs->counter && bs->counter < g_blades / 2) { + glRotatef (((int) bs->val - bs->counter) + * 360.0 / (GLfloat) g_blades, + 0, 0, 1); + draw_blink_blade (ctx, 0, NRADII - 1); + polys += SUBDIV + SUBDIV; + } + + --bs->dwellcnt; + + return polys; +} + +static int +draw_blink_concentric_random (lockward_context *ctx, struct blinkstate *bs) +{ + int i; + + if (bs->dwellcnt < 0) { + if (bs->counter <= 0) { + bs->drawfunc = NULL; + return 0; + } + + do { + i = random() % (NRADII - 1); + } while (bs->val & (1 << i)); + bs->val |= (1 << i); + bs->direction = i; + if ((bs->dwellcnt = bs->dwell) < 0) + bs->dwellcnt = -bs->dwellcnt; + + --bs->counter; + } + + set_alpha_by_dwell (bs); + glBlendFunc (GL_DST_COLOR, GL_SRC_ALPHA); + glColor4fv (bs->color); + glCallList (ctx->rings + bs->direction); + + --bs->dwellcnt; + + return g_blades * SUBDIV * 2; +} + +static int +draw_blink_concentric_sequential (lockward_context *ctx, struct blinkstate *bs) +{ + if (bs->dwellcnt < 0) { + if (bs->counter <= 0) { + bs->drawfunc = NULL; + return 0; + } + if ((bs->dwellcnt = bs->dwell) < 0) + bs->dwellcnt = -bs->dwellcnt; + --bs->counter; + } + + set_alpha_by_dwell (bs); + glBlendFunc (GL_DST_COLOR, GL_SRC_ALPHA); + glColor4fv (bs->color); + if (bs->direction > 0) + glCallList (ctx->rings + (NRADII - 2) - bs->counter); + else + glCallList (ctx->rings + bs->counter); + + --bs->dwellcnt; + + return g_blades * SUBDIV * 2; +} + +static int +draw_blink_segment_scatter (lockward_context *ctx, struct blinkstate *bs) +{ + int i, polys = 0; + + if (bs->dwellcnt < 0) { + if (bs->counter <= 0) { + bs->drawfunc = NULL; + return 0; + } + + /* + * Init random noise array. On average, 1/4 of the bits will + * be set, which should look nice. (1/2 looks too busy.) + */ + for (i = g_blades; --i >= 0; ) + bs->noise[i] = random() & random() + & ((1 << (NRADII - 1)) - 1); + + if ((bs->dwellcnt = bs->dwell) < 0) + bs->dwellcnt = -bs->dwellcnt; + --bs->counter; + } + + set_alpha_by_dwell (bs); + glBlendFunc (GL_DST_COLOR, GL_SRC_ALPHA); + glColor4fv (bs->color); + + for (i = g_blades; --i >= 0; ) { + register uint32_t bits; + int inner, outer; + + /* + * Find consecutive runs of 1 bits. Keep going until we run + * out of them. + */ + for (bits = bs->noise[i]; bits; ) { + inner = ffs (bits) - 1; + bits = ~bits & ~((1 << inner) - 1); + outer = ffs (bits) - 1; + bits = ~bits & ~((1 << outer) - 1); + + glPushMatrix (); + glRotatef (i * 360.0 / (GLfloat) g_blades, 0, 0, 1); + draw_blink_blade (ctx, inner, outer); + glPopMatrix (); + + polys += SUBDIV + SUBDIV; + } + } + + --bs->dwellcnt; + + return polys; +} + +static void +random_blink (lockward_context *ctx, struct blinkstate *bs) +{ + bs->color[0] = + bs->color[1] = + bs->color[2] = + bs->color[3] = 1.0; + bs->dwellcnt = -1; + bs->radius = -1; + bs->dwell = calc_interval_frames + (ctx, g_blinkdwell_min, g_blinkdwell_max); + if (random() & 2) + bs->dwell = -bs->dwell; + + bs->type = random() % MAX_BTYPE; + + switch (bs->type) { + case BTYPE_RADIAL_SINGLE: + case BTYPE_SEGMENT_SINGLE: + bs->drawfunc = draw_blink_radial_random; + bs->val = 0; + bs->counter = 1; + break; + case BTYPE_RADIAL_RANDOM: + case BTYPE_SEGMENT_RANDOM: + bs->drawfunc = draw_blink_radial_random; + bs->val = 0; + bs->counter = g_blades; + break; + case BTYPE_RADIAL_SEQ: + bs->drawfunc = draw_blink_radial_sequential; + bs->val = random() % g_blades; /* Initial offset */ + bs->direction = random() & 8 ? 1 : -1; + bs->counter = g_blades; + break; + case BTYPE_RADIAL_DOUBLESEQ: + bs->drawfunc = draw_blink_radial_doubleseq; + bs->val = random() % g_blades; /* Initial offset */ + bs->counter = g_blades / 2 + 1; + break; + case BTYPE_CONCENTRIC_SINGLE: + bs->drawfunc = draw_blink_concentric_random; + bs->val = 0; + bs->counter = 1; + break; + case BTYPE_CONCENTRIC_RANDOM: + bs->drawfunc = draw_blink_concentric_random; + bs->val = 0; + bs->counter = NRADII - 1; + break; + case BTYPE_CONCENTRIC_SEQ: + bs->drawfunc = draw_blink_concentric_sequential; + bs->direction = random() & 8 ? 1 : -1; + bs->counter = NRADII - 1; + break; + case BTYPE_SEGMENT_SCATTER: + bs->drawfunc = draw_blink_segment_scatter; + bs->counter = random() % (g_blades / 2) + (g_blades / 2) + 1; + break; + } +} + + +/*************************************************************************** + * Main rendering routine. + */ +ENTRYPOINT void +draw_lockward (ModeInfo *mi) +{ + lockward_context *ctx = &g_ctx[MI_SCREEN (mi)]; + spinnerstate *ss; + Display *dpy = MI_DISPLAY(mi); + Window window = MI_WINDOW(mi); + int i, n; + + GLfloat scolor[4] = {0.0, 0.0, 0.0, 0.5}; + + if (!ctx->glx_context) + return; + + glXMakeCurrent (MI_DISPLAY (mi), MI_WINDOW (mi), *(ctx->glx_context)); + + + glClear (GL_COLOR_BUFFER_BIT); + + if (ctx->blendmode) + glBlendFunc (GL_ONE, GL_ONE); + else + glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + + glPushMatrix (); + glLoadIdentity (); + + mi->polygon_count = 0; + + for (n = NSPINNERS; --n >= 0; ) { + ss = &ctx->spinners[n]; + + /* Set color. */ + i = ss->ccolor >> COLORIDX_SHF; + scolor[0] = ss->colors[i].red / 65535.0; + scolor[1] = ss->colors[i].green / 65535.0; + scolor[2] = ss->colors[i].blue / 65535.0; + glColor4fv (scolor); + + glPushMatrix (); + glRotatef (ss->rot - ss->rotcount * ss->rotinc, 0, 0, 1); + for (i = ss->nblades; --i >= 0; ) { + glPushMatrix (); + glRotatef (360.0 * i / ss->nblades, 0, 0, 1); + + glBegin (GL_TRIANGLE_FAN); + glCallList (ctx->blades_outer + ss->bladeidx[i].outer); + glCallList (ctx->blades_inner + ss->bladeidx[i].inner); + glEnd (); + + glPopMatrix (); + mi->polygon_count += SUBDIV + SUBDIV; + } + glPopMatrix (); + + /* Advance rotation. */ + if (ss->rotcount) { + if (ss->rotcount > 0) + --ss->rotcount; + } else { + if (ss->rotinc == 0.0) + random_blade_rot (ctx, ss); + else { + /* Compute # of ticks to sit idle. */ + ss->rotinc = 0.0; + ss->rotcount = + calc_interval_frames (ctx, + g_rotateidle_min, + g_rotateidle_max); + } + } + + /* Advance colors. */ + if ((ss->ccolor += ss->colorinc) >= ss->ncolors) + ss->ccolor -= ss->ncolors; + else if (ss->ccolor < 0) + ss->ccolor += ss->ncolors; + } + + if (g_blink_p) { + if (ctx->blink.drawfunc) { + mi->polygon_count += + ctx->blink.drawfunc (ctx, &ctx->blink); + } else { + if (ctx->nextblink > 0) + --ctx->nextblink; + else { + /* Compute # of frames for blink idle time. */ + ctx->nextblink = + calc_interval_frames (ctx, + g_blinkidle_min, + g_blinkidle_max); + random_blink (ctx, &ctx->blink); + } + } + } + glPopMatrix (); + + if (MI_IS_FPS (mi)) do_fps (mi); + glFinish(); + + glXSwapBuffers (dpy, window); +} + + +/*************************************************************************** + * Initialization/teardown. + */ +ENTRYPOINT void +init_lockward (ModeInfo *mi) +{ + lockward_context *ctx; + int i, n; + + if (!g_ctx) { + g_ctx = (lockward_context *) calloc (MI_NUM_SCREENS (mi), + sizeof (lockward_context)); + if (!g_ctx) { + fprintf (stderr, "%s: can't allocate context.\n", + progname); + exit (1); + } + } + ctx = &g_ctx[MI_SCREEN (mi)]; + + ctx->glx_context = init_GL (mi); + + reshape_lockward (mi, MI_WIDTH (mi), MI_HEIGHT (mi)); + + glEnable (GL_CULL_FACE); + glEnable (GL_BLEND); + glDisable (GL_DEPTH_TEST); + + glShadeModel (GL_FLAT); + glFrontFace (GL_CW); + + ctx->blades_outer = glGenLists (NRADII); + ctx->blades_inner = glGenLists (NRADII); + ctx->rings = glGenLists (NRADII - 1); + ctx->blendmode = 0; + ctx->fps = 1000000 / MI_DELAY (mi); + ctx->nextblink = calc_interval_frames + (ctx, g_blinkidle_min, g_blinkidle_max); + ctx->blink.drawfunc = NULL; + ctx->blink.noise = malloc (sizeof (uint32_t) * g_blades); + if (!ctx->blink.noise) { + fprintf (stderr, "Can't allocate noise array.\n"); + exit (1); + } + + gen_blade_arcs (ctx); + gen_rings (ctx); + + for (i = NSPINNERS; --i >= 0; ) { + spinnerstate *ss = &ctx->spinners[i]; + + ss->rot = 0.0; + ss->rotcount = -1; + + /* Establish rotation */ + random_blade_rot (ctx, ss); + + /* + * Establish color cycling path and rate. Rate avoids zero. + */ + ss->ncolors = 128; + ss->colorinc = (random() & ((2 << COLORIDX_SHF) - 1)) + - (1 << COLORIDX_SHF); + if (ss->colorinc >= 0) + ++ss->colorinc; + + ss->colors = (XColor *) calloc (ss->ncolors, sizeof (XColor)); + if (!ss->colors) { + fprintf (stderr, + "Can't allocate XColors for spinner %d.\n", + i); + exit (1); + } + make_smooth_colormap (0, 0, 0, + ss->colors, &ss->ncolors, + False, 0, False); + ss->ncolors <<= COLORIDX_SHF; + + /* + * Create blades. + */ + ss->nblades = g_blades; + ss->bladeidx = malloc (sizeof (bladestate) * g_blades); + if (!ss->bladeidx) { + fprintf (stderr, "Can't allocate blades.\n"); + exit (1); + } + for (n = g_blades; --n >= 0; ) { + /* + * Establish blade radii. Can't be equal. Ensure + * outer > inner. + */ + do { + ss->bladeidx[n].outer = random() & 7; + ss->bladeidx[n].inner = random() & 7; + } while (ss->bladeidx[n].outer == + ss->bladeidx[n].inner); + + if (ss->bladeidx[n].outer < ss->bladeidx[n].inner) { + uint8_t tmp; + + tmp = ss->bladeidx[n].outer; + ss->bladeidx[n].outer = ss->bladeidx[n].inner; + ss->bladeidx[n].inner = tmp; + } + } + } +} + +static void +free_lockward (lockward_context *ctx) +{ + int i; + + if (ctx->blink.noise) + free (ctx->blink.noise); + if (glIsList (ctx->rings)) + glDeleteLists (ctx->rings, NRADII - 1); + if (glIsList (ctx->blades_outer)) + glDeleteLists (ctx->blades_outer, NRADII); + if (glIsList (ctx->blades_inner)) + glDeleteLists (ctx->blades_inner, NRADII); + + for (i = NSPINNERS; --i >= 0; ) { + spinnerstate *ss = &ctx->spinners[i]; + + if (ss->colors) + free (ss->colors); + if (ss->bladeidx) + free (ss->bladeidx); + } +} + +ENTRYPOINT void +release_lockward (ModeInfo *mi) +{ + int i; + + if (!g_ctx) + return; + + for (i = MI_NUM_SCREENS (mi); --i >= 0; ) { + if (g_ctx[i].glx_context) + glXMakeCurrent (MI_DISPLAY (mi), MI_WINDOW (mi), + *(g_ctx[i].glx_context)); + free_lockward (&g_ctx[i]); + } + + FreeAllGL (mi); + free (g_ctx); g_ctx = NULL; +} + + +XSCREENSAVER_MODULE ("Lockward", lockward) + +#endif /* USE_GL */ + +/* vim:se ts=8 sts=8 sw=8: */ diff --git a/hacks/glx/lockward.man b/hacks/glx/lockward.man new file mode 100644 index 00000000..f55e5be0 --- /dev/null +++ b/hacks/glx/lockward.man @@ -0,0 +1,79 @@ +.TH XScreenSaver 1 "" "X Version 11" +.SH NAME +lockward - Rotating spinning color-cycling things +.SH SYNOPSIS +.B lockward +[\-display \fIdisplayspec\fP] +[\-root] +[\-window] +[\-visual \fIarg\fP] +[\-window-id \fIarg\fP] +[\-delay \fIusec\fP] +[\-pair] +[\-fps] +[\-blink | \-no-blink] +[\-rotateidle-min \fImsec\fP] +[\-rotateidle-max \fImsec\fP] +[\-blinkidle-min \fImsec\fP] +[\-blinkidle-max \fImsec\fP] +[\-blinkdwell-min \fImsec\fP] +[\-blinkdwell-max \fImsec\fP] +.SH DESCRIPTION +.B lockward +draws a spinning, rotating set of notched wheels overlaid with some flashing +effects, using OpenGL. It's a sort of cross between the wards in a +combination lock and those old information displays that animated via +polarized light. +.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 (default). +.TP 8 +.B \-root +Draw on the root window. +.TP 8 +.B \-delay \fImicroseconds\fP +Per-frame delay, in microseconds. Default: 20000 (50 frames/sec). +.TP 8 +.B \-blink | \-no-blink +Enables/disables the blinking effects. Default: Enabled. +.TP 8 +.B \-fps +Display the current frame rate, CPU load, and polygon count. +.TP 8 +.B \-rotateidle-min \fImilliseconds +.TP 8 +.B \-rotateidle-max \fImilliseconds +The minimum and maximum time each spinner will sit idle, in milliseconds. +Defaults: Min 1000, max 6000. +.TP 8 +.B \-blinkidle-min \fImilliseconds +.TP 8 +.B \-blinkidle-max \fImilliseconds +The minimum and maximum time between blinking effects, in milliseconds. +Defaults: Min 1000, max 9000. +.TP 8 +.B \-blinkdwell-min \fImilliseconds +.TP 8 +.B \-blinkdwell-max \fImilliseconds +The minimum and maximum dwell time for the blinking effects, in +milliseconds. This affects how quickly the blinks actually happen. +Defaults: Min 100, max 600. +.SH ENVIRONMENT +.PP +.TP 8 +.B DISPLAY +Default host and display number. +.TP 8 +.B XENVIRONMENT +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 AUTHORS +Leo L. Schwab diff --git a/hacks/glx/marching.c b/hacks/glx/marching.c new file mode 100644 index 00000000..77230771 --- /dev/null +++ b/hacks/glx/marching.c @@ -0,0 +1,641 @@ +/* xscreensaver, Copyright (c) 2002 Jamie Zawinski + * Utility functions to create "marching cubes" meshes from 3d fields. + * + * 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. + * + * Marching cubes implementation by Paul Bourke + * http://astronomy.swin.edu.au/~pbourke/modelling/polygonise/ + */ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include +#include +#include + +#ifndef HAVE_COCOA +# include +#endif + +#ifdef HAVE_JWZGLES +# include "jwzgles.h" +#endif /* HAVE_JWZGLES */ + +#include "marching.h" +#include "normals.h" + +extern char *progname; + +#undef ABS +#define ABS(x) ((x)<0?(-(x)):(x)) + +typedef struct { + XYZ p[3]; +} TRIANGLE; + +typedef struct { + XYZ p[8]; + double val[8]; +} GRIDCELL; + + +/* Indexing convention: + + Vertices: Edges: + + 4 ______________ 5 ______________ + /| /| /| 4 /| + / | 6 / | 7 / |8 5 / | + 7 /_____________/ | /______________/ | 9 + | | | | | | 6 | | + | 0 |_________|___| 1 | |_________|10_| + | / | / 11 | 3/ 0 | / + | / | / | / | / 1 + 3 |/____________|/ 2 |/____________|/ + 2 + */ + +static const int edgeTable[256] = { + 0x0 , 0x109, 0x203, 0x30a, 0x406, 0x50f, 0x605, 0x70c, + 0x80c, 0x905, 0xa0f, 0xb06, 0xc0a, 0xd03, 0xe09, 0xf00, + 0x190, 0x99 , 0x393, 0x29a, 0x596, 0x49f, 0x795, 0x69c, + 0x99c, 0x895, 0xb9f, 0xa96, 0xd9a, 0xc93, 0xf99, 0xe90, + 0x230, 0x339, 0x33 , 0x13a, 0x636, 0x73f, 0x435, 0x53c, + 0xa3c, 0xb35, 0x83f, 0x936, 0xe3a, 0xf33, 0xc39, 0xd30, + 0x3a0, 0x2a9, 0x1a3, 0xaa , 0x7a6, 0x6af, 0x5a5, 0x4ac, + 0xbac, 0xaa5, 0x9af, 0x8a6, 0xfaa, 0xea3, 0xda9, 0xca0, + 0x460, 0x569, 0x663, 0x76a, 0x66 , 0x16f, 0x265, 0x36c, + 0xc6c, 0xd65, 0xe6f, 0xf66, 0x86a, 0x963, 0xa69, 0xb60, + 0x5f0, 0x4f9, 0x7f3, 0x6fa, 0x1f6, 0xff , 0x3f5, 0x2fc, + 0xdfc, 0xcf5, 0xfff, 0xef6, 0x9fa, 0x8f3, 0xbf9, 0xaf0, + 0x650, 0x759, 0x453, 0x55a, 0x256, 0x35f, 0x55 , 0x15c, + 0xe5c, 0xf55, 0xc5f, 0xd56, 0xa5a, 0xb53, 0x859, 0x950, + 0x7c0, 0x6c9, 0x5c3, 0x4ca, 0x3c6, 0x2cf, 0x1c5, 0xcc , + 0xfcc, 0xec5, 0xdcf, 0xcc6, 0xbca, 0xac3, 0x9c9, 0x8c0, + 0x8c0, 0x9c9, 0xac3, 0xbca, 0xcc6, 0xdcf, 0xec5, 0xfcc, + 0xcc , 0x1c5, 0x2cf, 0x3c6, 0x4ca, 0x5c3, 0x6c9, 0x7c0, + 0x950, 0x859, 0xb53, 0xa5a, 0xd56, 0xc5f, 0xf55, 0xe5c, + 0x15c, 0x55 , 0x35f, 0x256, 0x55a, 0x453, 0x759, 0x650, + 0xaf0, 0xbf9, 0x8f3, 0x9fa, 0xef6, 0xfff, 0xcf5, 0xdfc, + 0x2fc, 0x3f5, 0xff , 0x1f6, 0x6fa, 0x7f3, 0x4f9, 0x5f0, + 0xb60, 0xa69, 0x963, 0x86a, 0xf66, 0xe6f, 0xd65, 0xc6c, + 0x36c, 0x265, 0x16f, 0x66 , 0x76a, 0x663, 0x569, 0x460, + 0xca0, 0xda9, 0xea3, 0xfaa, 0x8a6, 0x9af, 0xaa5, 0xbac, + 0x4ac, 0x5a5, 0x6af, 0x7a6, 0xaa , 0x1a3, 0x2a9, 0x3a0, + 0xd30, 0xc39, 0xf33, 0xe3a, 0x936, 0x83f, 0xb35, 0xa3c, + 0x53c, 0x435, 0x73f, 0x636, 0x13a, 0x33 , 0x339, 0x230, + 0xe90, 0xf99, 0xc93, 0xd9a, 0xa96, 0xb9f, 0x895, 0x99c, + 0x69c, 0x795, 0x49f, 0x596, 0x29a, 0x393, 0x99 , 0x190, + 0xf00, 0xe09, 0xd03, 0xc0a, 0xb06, 0xa0f, 0x905, 0x80c, + 0x70c, 0x605, 0x50f, 0x406, 0x30a, 0x203, 0x109, 0x0 +}; + +static const int triTable[256][16] = { + {-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, + { 0, 8, 3, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, + { 0, 1, 9, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, + { 1, 8, 3, 9, 8, 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, + { 1, 2, 10, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, + { 0, 8, 3, 1, 2, 10, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, + { 9, 2, 10, 0, 2, 9, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, + { 2, 8, 3, 2, 10, 8, 10, 9, 8, -1, -1, -1, -1, -1, -1, -1}, + { 3, 11, 2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, + { 0, 11, 2, 8, 11, 0, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, + { 1, 9, 0, 2, 3, 11, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, + { 1, 11, 2, 1, 9, 11, 9, 8, 11, -1, -1, -1, -1, -1, -1, -1}, + { 3, 10, 1, 11, 10, 3, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, + { 0, 10, 1, 0, 8, 10, 8, 11, 10, -1, -1, -1, -1, -1, -1, -1}, + { 3, 9, 0, 3, 11, 9, 11, 10, 9, -1, -1, -1, -1, -1, -1, -1}, + { 9, 8, 10, 10, 8, 11, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, + { 4, 7, 8, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, + { 4, 3, 0, 7, 3, 4, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, + { 0, 1, 9, 8, 4, 7, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, + { 4, 1, 9, 4, 7, 1, 7, 3, 1, -1, -1, -1, -1, -1, -1, -1}, + { 1, 2, 10, 8, 4, 7, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, + { 3, 4, 7, 3, 0, 4, 1, 2, 10, -1, -1, -1, -1, -1, -1, -1}, + { 9, 2, 10, 9, 0, 2, 8, 4, 7, -1, -1, -1, -1, -1, -1, -1}, + { 2, 10, 9, 2, 9, 7, 2, 7, 3, 7, 9, 4, -1, -1, -1, -1}, + { 8, 4, 7, 3, 11, 2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, + {11, 4, 7, 11, 2, 4, 2, 0, 4, -1, -1, -1, -1, -1, -1, -1}, + { 9, 0, 1, 8, 4, 7, 2, 3, 11, -1, -1, -1, -1, -1, -1, -1}, + { 4, 7, 11, 9, 4, 11, 9, 11, 2, 9, 2, 1, -1, -1, -1, -1}, + { 3, 10, 1, 3, 11, 10, 7, 8, 4, -1, -1, -1, -1, -1, -1, -1}, + { 1, 11, 10, 1, 4, 11, 1, 0, 4, 7, 11, 4, -1, -1, -1, -1}, + { 4, 7, 8, 9, 0, 11, 9, 11, 10, 11, 0, 3, -1, -1, -1, -1}, + { 4, 7, 11, 4, 11, 9, 9, 11, 10, -1, -1, -1, -1, -1, -1, -1}, + { 9, 5, 4, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, + { 9, 5, 4, 0, 8, 3, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, + { 0, 5, 4, 1, 5, 0, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, + { 8, 5, 4, 8, 3, 5, 3, 1, 5, -1, -1, -1, -1, -1, -1, -1}, + { 1, 2, 10, 9, 5, 4, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, + { 3, 0, 8, 1, 2, 10, 4, 9, 5, -1, -1, -1, -1, -1, -1, -1}, + { 5, 2, 10, 5, 4, 2, 4, 0, 2, -1, -1, -1, -1, -1, -1, -1}, + { 2, 10, 5, 3, 2, 5, 3, 5, 4, 3, 4, 8, -1, -1, -1, -1}, + { 9, 5, 4, 2, 3, 11, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, + { 0, 11, 2, 0, 8, 11, 4, 9, 5, -1, -1, -1, -1, -1, -1, -1}, + { 0, 5, 4, 0, 1, 5, 2, 3, 11, -1, -1, -1, -1, -1, -1, -1}, + { 2, 1, 5, 2, 5, 8, 2, 8, 11, 4, 8, 5, -1, -1, -1, -1}, + {10, 3, 11, 10, 1, 3, 9, 5, 4, -1, -1, -1, -1, -1, -1, -1}, + { 4, 9, 5, 0, 8, 1, 8, 10, 1, 8, 11, 10, -1, -1, -1, -1}, + { 5, 4, 0, 5, 0, 11, 5, 11, 10, 11, 0, 3, -1, -1, -1, -1}, + { 5, 4, 8, 5, 8, 10, 10, 8, 11, -1, -1, -1, -1, -1, -1, -1}, + { 9, 7, 8, 5, 7, 9, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, + { 9, 3, 0, 9, 5, 3, 5, 7, 3, -1, -1, -1, -1, -1, -1, -1}, + { 0, 7, 8, 0, 1, 7, 1, 5, 7, -1, -1, -1, -1, -1, -1, -1}, + { 1, 5, 3, 3, 5, 7, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, + { 9, 7, 8, 9, 5, 7, 10, 1, 2, -1, -1, -1, -1, -1, -1, -1}, + {10, 1, 2, 9, 5, 0, 5, 3, 0, 5, 7, 3, -1, -1, -1, -1}, + { 8, 0, 2, 8, 2, 5, 8, 5, 7, 10, 5, 2, -1, -1, -1, -1}, + { 2, 10, 5, 2, 5, 3, 3, 5, 7, -1, -1, -1, -1, -1, -1, -1}, + { 7, 9, 5, 7, 8, 9, 3, 11, 2, -1, -1, -1, -1, -1, -1, -1}, + { 9, 5, 7, 9, 7, 2, 9, 2, 0, 2, 7, 11, -1, -1, -1, -1}, + { 2, 3, 11, 0, 1, 8, 1, 7, 8, 1, 5, 7, -1, -1, -1, -1}, + {11, 2, 1, 11, 1, 7, 7, 1, 5, -1, -1, -1, -1, -1, -1, -1}, + { 9, 5, 8, 8, 5, 7, 10, 1, 3, 10, 3, 11, -1, -1, -1, -1}, + { 5, 7, 0, 5, 0, 9, 7, 11, 0, 1, 0, 10, 11, 10, 0, -1}, + {11, 10, 0, 11, 0, 3, 10, 5, 0, 8, 0, 7, 5, 7, 0, -1}, + {11, 10, 5, 7, 11, 5, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, + {10, 6, 5, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, + { 0, 8, 3, 5, 10, 6, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, + { 9, 0, 1, 5, 10, 6, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, + { 1, 8, 3, 1, 9, 8, 5, 10, 6, -1, -1, -1, -1, -1, -1, -1}, + { 1, 6, 5, 2, 6, 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, + { 1, 6, 5, 1, 2, 6, 3, 0, 8, -1, -1, -1, -1, -1, -1, -1}, + { 9, 6, 5, 9, 0, 6, 0, 2, 6, -1, -1, -1, -1, -1, -1, -1}, + { 5, 9, 8, 5, 8, 2, 5, 2, 6, 3, 2, 8, -1, -1, -1, -1}, + { 2, 3, 11, 10, 6, 5, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, + {11, 0, 8, 11, 2, 0, 10, 6, 5, -1, -1, -1, -1, -1, -1, -1}, + { 0, 1, 9, 2, 3, 11, 5, 10, 6, -1, -1, -1, -1, -1, -1, -1}, + { 5, 10, 6, 1, 9, 2, 9, 11, 2, 9, 8, 11, -1, -1, -1, -1}, + { 6, 3, 11, 6, 5, 3, 5, 1, 3, -1, -1, -1, -1, -1, -1, -1}, + { 0, 8, 11, 0, 11, 5, 0, 5, 1, 5, 11, 6, -1, -1, -1, -1}, + { 3, 11, 6, 0, 3, 6, 0, 6, 5, 0, 5, 9, -1, -1, -1, -1}, + { 6, 5, 9, 6, 9, 11, 11, 9, 8, -1, -1, -1, -1, -1, -1, -1}, + { 5, 10, 6, 4, 7, 8, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, + { 4, 3, 0, 4, 7, 3, 6, 5, 10, -1, -1, -1, -1, -1, -1, -1}, + { 1, 9, 0, 5, 10, 6, 8, 4, 7, -1, -1, -1, -1, -1, -1, -1}, + {10, 6, 5, 1, 9, 7, 1, 7, 3, 7, 9, 4, -1, -1, -1, -1}, + { 6, 1, 2, 6, 5, 1, 4, 7, 8, -1, -1, -1, -1, -1, -1, -1}, + { 1, 2, 5, 5, 2, 6, 3, 0, 4, 3, 4, 7, -1, -1, -1, -1}, + { 8, 4, 7, 9, 0, 5, 0, 6, 5, 0, 2, 6, -1, -1, -1, -1}, + { 7, 3, 9, 7, 9, 4, 3, 2, 9, 5, 9, 6, 2, 6, 9, -1}, + { 3, 11, 2, 7, 8, 4, 10, 6, 5, -1, -1, -1, -1, -1, -1, -1}, + { 5, 10, 6, 4, 7, 2, 4, 2, 0, 2, 7, 11, -1, -1, -1, -1}, + { 0, 1, 9, 4, 7, 8, 2, 3, 11, 5, 10, 6, -1, -1, -1, -1}, + { 9, 2, 1, 9, 11, 2, 9, 4, 11, 7, 11, 4, 5, 10, 6, -1}, + { 8, 4, 7, 3, 11, 5, 3, 5, 1, 5, 11, 6, -1, -1, -1, -1}, + { 5, 1, 11, 5, 11, 6, 1, 0, 11, 7, 11, 4, 0, 4, 11, -1}, + { 0, 5, 9, 0, 6, 5, 0, 3, 6, 11, 6, 3, 8, 4, 7, -1}, + { 6, 5, 9, 6, 9, 11, 4, 7, 9, 7, 11, 9, -1, -1, -1, -1}, + {10, 4, 9, 6, 4, 10, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, + { 4, 10, 6, 4, 9, 10, 0, 8, 3, -1, -1, -1, -1, -1, -1, -1}, + {10, 0, 1, 10, 6, 0, 6, 4, 0, -1, -1, -1, -1, -1, -1, -1}, + { 8, 3, 1, 8, 1, 6, 8, 6, 4, 6, 1, 10, -1, -1, -1, -1}, + { 1, 4, 9, 1, 2, 4, 2, 6, 4, -1, -1, -1, -1, -1, -1, -1}, + { 3, 0, 8, 1, 2, 9, 2, 4, 9, 2, 6, 4, -1, -1, -1, -1}, + { 0, 2, 4, 4, 2, 6, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, + { 8, 3, 2, 8, 2, 4, 4, 2, 6, -1, -1, -1, -1, -1, -1, -1}, + {10, 4, 9, 10, 6, 4, 11, 2, 3, -1, -1, -1, -1, -1, -1, -1}, + { 0, 8, 2, 2, 8, 11, 4, 9, 10, 4, 10, 6, -1, -1, -1, -1}, + { 3, 11, 2, 0, 1, 6, 0, 6, 4, 6, 1, 10, -1, -1, -1, -1}, + { 6, 4, 1, 6, 1, 10, 4, 8, 1, 2, 1, 11, 8, 11, 1, -1}, + { 9, 6, 4, 9, 3, 6, 9, 1, 3, 11, 6, 3, -1, -1, -1, -1}, + { 8, 11, 1, 8, 1, 0, 11, 6, 1, 9, 1, 4, 6, 4, 1, -1}, + { 3, 11, 6, 3, 6, 0, 0, 6, 4, -1, -1, -1, -1, -1, -1, -1}, + { 6, 4, 8, 11, 6, 8, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, + { 7, 10, 6, 7, 8, 10, 8, 9, 10, -1, -1, -1, -1, -1, -1, -1}, + { 0, 7, 3, 0, 10, 7, 0, 9, 10, 6, 7, 10, -1, -1, -1, -1}, + {10, 6, 7, 1, 10, 7, 1, 7, 8, 1, 8, 0, -1, -1, -1, -1}, + {10, 6, 7, 10, 7, 1, 1, 7, 3, -1, -1, -1, -1, -1, -1, -1}, + { 1, 2, 6, 1, 6, 8, 1, 8, 9, 8, 6, 7, -1, -1, -1, -1}, + { 2, 6, 9, 2, 9, 1, 6, 7, 9, 0, 9, 3, 7, 3, 9, -1}, + { 7, 8, 0, 7, 0, 6, 6, 0, 2, -1, -1, -1, -1, -1, -1, -1}, + { 7, 3, 2, 6, 7, 2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, + { 2, 3, 11, 10, 6, 8, 10, 8, 9, 8, 6, 7, -1, -1, -1, -1}, + { 2, 0, 7, 2, 7, 11, 0, 9, 7, 6, 7, 10, 9, 10, 7, -1}, + { 1, 8, 0, 1, 7, 8, 1, 10, 7, 6, 7, 10, 2, 3, 11, -1}, + {11, 2, 1, 11, 1, 7, 10, 6, 1, 6, 7, 1, -1, -1, -1, -1}, + { 8, 9, 6, 8, 6, 7, 9, 1, 6, 11, 6, 3, 1, 3, 6, -1}, + { 0, 9, 1, 11, 6, 7, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, + { 7, 8, 0, 7, 0, 6, 3, 11, 0, 11, 6, 0, -1, -1, -1, -1}, + { 7, 11, 6, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, + { 7, 6, 11, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, + { 3, 0, 8, 11, 7, 6, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, + { 0, 1, 9, 11, 7, 6, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, + { 8, 1, 9, 8, 3, 1, 11, 7, 6, -1, -1, -1, -1, -1, -1, -1}, + {10, 1, 2, 6, 11, 7, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, + { 1, 2, 10, 3, 0, 8, 6, 11, 7, -1, -1, -1, -1, -1, -1, -1}, + { 2, 9, 0, 2, 10, 9, 6, 11, 7, -1, -1, -1, -1, -1, -1, -1}, + { 6, 11, 7, 2, 10, 3, 10, 8, 3, 10, 9, 8, -1, -1, -1, -1}, + { 7, 2, 3, 6, 2, 7, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, + { 7, 0, 8, 7, 6, 0, 6, 2, 0, -1, -1, -1, -1, -1, -1, -1}, + { 2, 7, 6, 2, 3, 7, 0, 1, 9, -1, -1, -1, -1, -1, -1, -1}, + { 1, 6, 2, 1, 8, 6, 1, 9, 8, 8, 7, 6, -1, -1, -1, -1}, + {10, 7, 6, 10, 1, 7, 1, 3, 7, -1, -1, -1, -1, -1, -1, -1}, + {10, 7, 6, 1, 7, 10, 1, 8, 7, 1, 0, 8, -1, -1, -1, -1}, + { 0, 3, 7, 0, 7, 10, 0, 10, 9, 6, 10, 7, -1, -1, -1, -1}, + { 7, 6, 10, 7, 10, 8, 8, 10, 9, -1, -1, -1, -1, -1, -1, -1}, + { 6, 8, 4, 11, 8, 6, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, + { 3, 6, 11, 3, 0, 6, 0, 4, 6, -1, -1, -1, -1, -1, -1, -1}, + { 8, 6, 11, 8, 4, 6, 9, 0, 1, -1, -1, -1, -1, -1, -1, -1}, + { 9, 4, 6, 9, 6, 3, 9, 3, 1, 11, 3, 6, -1, -1, -1, -1}, + { 6, 8, 4, 6, 11, 8, 2, 10, 1, -1, -1, -1, -1, -1, -1, -1}, + { 1, 2, 10, 3, 0, 11, 0, 6, 11, 0, 4, 6, -1, -1, -1, -1}, + { 4, 11, 8, 4, 6, 11, 0, 2, 9, 2, 10, 9, -1, -1, -1, -1}, + {10, 9, 3, 10, 3, 2, 9, 4, 3, 11, 3, 6, 4, 6, 3, -1}, + { 8, 2, 3, 8, 4, 2, 4, 6, 2, -1, -1, -1, -1, -1, -1, -1}, + { 0, 4, 2, 4, 6, 2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, + { 1, 9, 0, 2, 3, 4, 2, 4, 6, 4, 3, 8, -1, -1, -1, -1}, + { 1, 9, 4, 1, 4, 2, 2, 4, 6, -1, -1, -1, -1, -1, -1, -1}, + { 8, 1, 3, 8, 6, 1, 8, 4, 6, 6, 10, 1, -1, -1, -1, -1}, + {10, 1, 0, 10, 0, 6, 6, 0, 4, -1, -1, -1, -1, -1, -1, -1}, + { 4, 6, 3, 4, 3, 8, 6, 10, 3, 0, 3, 9, 10, 9, 3, -1}, + {10, 9, 4, 6, 10, 4, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, + { 4, 9, 5, 7, 6, 11, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, + { 0, 8, 3, 4, 9, 5, 11, 7, 6, -1, -1, -1, -1, -1, -1, -1}, + { 5, 0, 1, 5, 4, 0, 7, 6, 11, -1, -1, -1, -1, -1, -1, -1}, + {11, 7, 6, 8, 3, 4, 3, 5, 4, 3, 1, 5, -1, -1, -1, -1}, + { 9, 5, 4, 10, 1, 2, 7, 6, 11, -1, -1, -1, -1, -1, -1, -1}, + { 6, 11, 7, 1, 2, 10, 0, 8, 3, 4, 9, 5, -1, -1, -1, -1}, + { 7, 6, 11, 5, 4, 10, 4, 2, 10, 4, 0, 2, -1, -1, -1, -1}, + { 3, 4, 8, 3, 5, 4, 3, 2, 5, 10, 5, 2, 11, 7, 6, -1}, + { 7, 2, 3, 7, 6, 2, 5, 4, 9, -1, -1, -1, -1, -1, -1, -1}, + { 9, 5, 4, 0, 8, 6, 0, 6, 2, 6, 8, 7, -1, -1, -1, -1}, + { 3, 6, 2, 3, 7, 6, 1, 5, 0, 5, 4, 0, -1, -1, -1, -1}, + { 6, 2, 8, 6, 8, 7, 2, 1, 8, 4, 8, 5, 1, 5, 8, -1}, + { 9, 5, 4, 10, 1, 6, 1, 7, 6, 1, 3, 7, -1, -1, -1, -1}, + { 1, 6, 10, 1, 7, 6, 1, 0, 7, 8, 7, 0, 9, 5, 4, -1}, + { 4, 0, 10, 4, 10, 5, 0, 3, 10, 6, 10, 7, 3, 7, 10, -1}, + { 7, 6, 10, 7, 10, 8, 5, 4, 10, 4, 8, 10, -1, -1, -1, -1}, + { 6, 9, 5, 6, 11, 9, 11, 8, 9, -1, -1, -1, -1, -1, -1, -1}, + { 3, 6, 11, 0, 6, 3, 0, 5, 6, 0, 9, 5, -1, -1, -1, -1}, + { 0, 11, 8, 0, 5, 11, 0, 1, 5, 5, 6, 11, -1, -1, -1, -1}, + { 6, 11, 3, 6, 3, 5, 5, 3, 1, -1, -1, -1, -1, -1, -1, -1}, + { 1, 2, 10, 9, 5, 11, 9, 11, 8, 11, 5, 6, -1, -1, -1, -1}, + { 0, 11, 3, 0, 6, 11, 0, 9, 6, 5, 6, 9, 1, 2, 10, -1}, + {11, 8, 5, 11, 5, 6, 8, 0, 5, 10, 5, 2, 0, 2, 5, -1}, + { 6, 11, 3, 6, 3, 5, 2, 10, 3, 10, 5, 3, -1, -1, -1, -1}, + { 5, 8, 9, 5, 2, 8, 5, 6, 2, 3, 8, 2, -1, -1, -1, -1}, + { 9, 5, 6, 9, 6, 0, 0, 6, 2, -1, -1, -1, -1, -1, -1, -1}, + { 1, 5, 8, 1, 8, 0, 5, 6, 8, 3, 8, 2, 6, 2, 8, -1}, + { 1, 5, 6, 2, 1, 6, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, + { 1, 3, 6, 1, 6, 10, 3, 8, 6, 5, 6, 9, 8, 9, 6, -1}, + {10, 1, 0, 10, 0, 6, 9, 5, 0, 5, 6, 0, -1, -1, -1, -1}, + { 0, 3, 8, 5, 6, 10, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, + {10, 5, 6, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, + {11, 5, 10, 7, 5, 11, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, + {11, 5, 10, 11, 7, 5, 8, 3, 0, -1, -1, -1, -1, -1, -1, -1}, + { 5, 11, 7, 5, 10, 11, 1, 9, 0, -1, -1, -1, -1, -1, -1, -1}, + {10, 7, 5, 10, 11, 7, 9, 8, 1, 8, 3, 1, -1, -1, -1, -1}, + {11, 1, 2, 11, 7, 1, 7, 5, 1, -1, -1, -1, -1, -1, -1, -1}, + { 0, 8, 3, 1, 2, 7, 1, 7, 5, 7, 2, 11, -1, -1, -1, -1}, + { 9, 7, 5, 9, 2, 7, 9, 0, 2, 2, 11, 7, -1, -1, -1, -1}, + { 7, 5, 2, 7, 2, 11, 5, 9, 2, 3, 2, 8, 9, 8, 2, -1}, + { 2, 5, 10, 2, 3, 5, 3, 7, 5, -1, -1, -1, -1, -1, -1, -1}, + { 8, 2, 0, 8, 5, 2, 8, 7, 5, 10, 2, 5, -1, -1, -1, -1}, + { 9, 0, 1, 5, 10, 3, 5, 3, 7, 3, 10, 2, -1, -1, -1, -1}, + { 9, 8, 2, 9, 2, 1, 8, 7, 2, 10, 2, 5, 7, 5, 2, -1}, + { 1, 3, 5, 3, 7, 5, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, + { 0, 8, 7, 0, 7, 1, 1, 7, 5, -1, -1, -1, -1, -1, -1, -1}, + { 9, 0, 3, 9, 3, 5, 5, 3, 7, -1, -1, -1, -1, -1, -1, -1}, + { 9, 8, 7, 5, 9, 7, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, + { 5, 8, 4, 5, 10, 8, 10, 11, 8, -1, -1, -1, -1, -1, -1, -1}, + { 5, 0, 4, 5, 11, 0, 5, 10, 11, 11, 3, 0, -1, -1, -1, -1}, + { 0, 1, 9, 8, 4, 10, 8, 10, 11, 10, 4, 5, -1, -1, -1, -1}, + {10, 11, 4, 10, 4, 5, 11, 3, 4, 9, 4, 1, 3, 1, 4, -1}, + { 2, 5, 1, 2, 8, 5, 2, 11, 8, 4, 5, 8, -1, -1, -1, -1}, + { 0, 4, 11, 0, 11, 3, 4, 5, 11, 2, 11, 1, 5, 1, 11, -1}, + { 0, 2, 5, 0, 5, 9, 2, 11, 5, 4, 5, 8, 11, 8, 5, -1}, + { 9, 4, 5, 2, 11, 3, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, + { 2, 5, 10, 3, 5, 2, 3, 4, 5, 3, 8, 4, -1, -1, -1, -1}, + { 5, 10, 2, 5, 2, 4, 4, 2, 0, -1, -1, -1, -1, -1, -1, -1}, + { 3, 10, 2, 3, 5, 10, 3, 8, 5, 4, 5, 8, 0, 1, 9, -1}, + { 5, 10, 2, 5, 2, 4, 1, 9, 2, 9, 4, 2, -1, -1, -1, -1}, + { 8, 4, 5, 8, 5, 3, 3, 5, 1, -1, -1, -1, -1, -1, -1, -1}, + { 0, 4, 5, 1, 0, 5, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, + { 8, 4, 5, 8, 5, 3, 9, 0, 5, 0, 3, 5, -1, -1, -1, -1}, + { 9, 4, 5, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, + { 4, 11, 7, 4, 9, 11, 9, 10, 11, -1, -1, -1, -1, -1, -1, -1}, + { 0, 8, 3, 4, 9, 7, 9, 11, 7, 9, 10, 11, -1, -1, -1, -1}, + { 1, 10, 11, 1, 11, 4, 1, 4, 0, 7, 4, 11, -1, -1, -1, -1}, + { 3, 1, 4, 3, 4, 8, 1, 10, 4, 7, 4, 11, 10, 11, 4, -1}, + { 4, 11, 7, 9, 11, 4, 9, 2, 11, 9, 1, 2, -1, -1, -1, -1}, + { 9, 7, 4, 9, 11, 7, 9, 1, 11, 2, 11, 1, 0, 8, 3, -1}, + {11, 7, 4, 11, 4, 2, 2, 4, 0, -1, -1, -1, -1, -1, -1, -1}, + {11, 7, 4, 11, 4, 2, 8, 3, 4, 3, 2, 4, -1, -1, -1, -1}, + { 2, 9, 10, 2, 7, 9, 2, 3, 7, 7, 4, 9, -1, -1, -1, -1}, + { 9, 10, 7, 9, 7, 4, 10, 2, 7, 8, 7, 0, 2, 0, 7, -1}, + { 3, 7, 10, 3, 10, 2, 7, 4, 10, 1, 10, 0, 4, 0, 10, -1}, + { 1, 10, 2, 8, 7, 4, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, + { 4, 9, 1, 4, 1, 7, 7, 1, 3, -1, -1, -1, -1, -1, -1, -1}, + { 4, 9, 1, 4, 1, 7, 0, 8, 1, 8, 7, 1, -1, -1, -1, -1}, + { 4, 0, 3, 7, 4, 3, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, + { 4, 8, 7, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, + { 9, 10, 8, 10, 11, 8, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, + { 3, 0, 9, 3, 9, 11, 11, 9, 10, -1, -1, -1, -1, -1, -1, -1}, + { 0, 1, 10, 0, 10, 8, 8, 10, 11, -1, -1, -1, -1, -1, -1, -1}, + { 3, 1, 10, 11, 3, 10, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, + { 1, 2, 11, 1, 11, 9, 9, 11, 8, -1, -1, -1, -1, -1, -1, -1}, + { 3, 0, 9, 3, 9, 11, 1, 2, 9, 2, 11, 9, -1, -1, -1, -1}, + { 0, 2, 11, 8, 0, 11, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, + { 3, 2, 11, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, + { 2, 3, 8, 2, 8, 10, 10, 8, 9, -1, -1, -1, -1, -1, -1, -1}, + { 9, 10, 2, 0, 9, 2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, + { 2, 3, 8, 2, 8, 10, 0, 1, 8, 1, 10, 8, -1, -1, -1, -1}, + { 1, 10, 2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, + { 1, 3, 8, 9, 1, 8, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, + { 0, 9, 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, + { 0, 3, 8, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, + {-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1} +}; + + + +/* Linearly interpolate the position where an isosurface cuts + an edge between two vertices, each with their own scalar value +*/ +static XYZ +interp_vertex (double isolevel, XYZ p1, XYZ p2, double valp1, double valp2) +{ + double mu; + XYZ p; + + if (ABS(isolevel-valp1) < 0.00001) + return(p1); + if (ABS(isolevel-valp2) < 0.00001) + return(p2); + if (ABS(valp1-valp2) < 0.00001) + return(p1); + mu = (isolevel - valp1) / (valp2 - valp1); + p.x = p1.x + mu * (p2.x - p1.x); + p.y = p1.y + mu * (p2.y - p1.y); + p.z = p1.z + mu * (p2.z - p1.z); + + return(p); +} + + +/* Given a grid cell and an isolevel, calculate the triangular + facets required to represent the isosurface through the cell. + Return the number of triangular facets. + `triangles' will be loaded up with the vertices at most 5 triangular facets. + 0 will be returned if the grid cell is either totally above + of totally below the isolevel. + + By Paul Bourke +*/ +static int +march_one_cube (GRIDCELL grid, double isolevel, TRIANGLE *triangles) +{ + int i, ntriang; + int cubeindex; + XYZ vertlist[12]; + + /* + Determine the index into the edge table which + tells us which vertices are inside of the surface + */ + cubeindex = 0; + if (grid.val[0] < isolevel) cubeindex |= 1; + if (grid.val[1] < isolevel) cubeindex |= 2; + if (grid.val[2] < isolevel) cubeindex |= 4; + if (grid.val[3] < isolevel) cubeindex |= 8; + if (grid.val[4] < isolevel) cubeindex |= 16; + if (grid.val[5] < isolevel) cubeindex |= 32; + if (grid.val[6] < isolevel) cubeindex |= 64; + if (grid.val[7] < isolevel) cubeindex |= 128; + + /* Cube is entirely in/out of the surface */ + if (edgeTable[cubeindex] == 0) + return(0); + + /* Find the vertices where the surface intersects the cube */ + if (edgeTable[cubeindex] & 1) + vertlist[0] = + interp_vertex (isolevel,grid.p[0],grid.p[1],grid.val[0],grid.val[1]); + if (edgeTable[cubeindex] & 2) + vertlist[1] = + interp_vertex (isolevel,grid.p[1],grid.p[2],grid.val[1],grid.val[2]); + if (edgeTable[cubeindex] & 4) + vertlist[2] = + interp_vertex (isolevel,grid.p[2],grid.p[3],grid.val[2],grid.val[3]); + if (edgeTable[cubeindex] & 8) + vertlist[3] = + interp_vertex (isolevel,grid.p[3],grid.p[0],grid.val[3],grid.val[0]); + if (edgeTable[cubeindex] & 16) + vertlist[4] = + interp_vertex (isolevel,grid.p[4],grid.p[5],grid.val[4],grid.val[5]); + if (edgeTable[cubeindex] & 32) + vertlist[5] = + interp_vertex (isolevel,grid.p[5],grid.p[6],grid.val[5],grid.val[6]); + if (edgeTable[cubeindex] & 64) + vertlist[6] = + interp_vertex (isolevel,grid.p[6],grid.p[7],grid.val[6],grid.val[7]); + if (edgeTable[cubeindex] & 128) + vertlist[7] = + interp_vertex (isolevel,grid.p[7],grid.p[4],grid.val[7],grid.val[4]); + if (edgeTable[cubeindex] & 256) + vertlist[8] = + interp_vertex (isolevel,grid.p[0],grid.p[4],grid.val[0],grid.val[4]); + if (edgeTable[cubeindex] & 512) + vertlist[9] = + interp_vertex (isolevel,grid.p[1],grid.p[5],grid.val[1],grid.val[5]); + if (edgeTable[cubeindex] & 1024) + vertlist[10] = + interp_vertex (isolevel,grid.p[2],grid.p[6],grid.val[2],grid.val[6]); + if (edgeTable[cubeindex] & 2048) + vertlist[11] = + interp_vertex (isolevel,grid.p[3],grid.p[7],grid.val[3],grid.val[7]); + + /* Create the triangle */ + ntriang = 0; + for (i=0; triTable[cubeindex][i] != -1; i+=3) + { + triangles[ntriang].p[0] = vertlist[triTable[cubeindex][i ]]; + triangles[ntriang].p[1] = vertlist[triTable[cubeindex][i+1]]; + triangles[ntriang].p[2] = vertlist[triTable[cubeindex][i+2]]; + ntriang++; + } + + return(ntriang); +} + + +/* Walking the grid. By jwz. + */ + + +/* Computes the normal of the scalar field at the given point, + for vertex normals (as opposed to face normals.) + */ +static void +do_function_normal (double x, double y, double z, + double (*compute_fn) (double x, double y, double z, + void *closure), + void *c) +{ + XYZ n; + double off = 0.5; + n.x = compute_fn (x-off, y, z, c) - compute_fn (x+off, y, z, c); + n.y = compute_fn (x, y-off, z, c) - compute_fn (x, y+off, z, c); + n.z = compute_fn (x, y, z-off, c) - compute_fn (x, y, z+off, c); + /* normalize (&n); */ + glNormal3f (n.x, n.y, n.z); +} + + +/* Given a function capable of generating a value at any XYZ position, + creates OpenGL faces for the solids defined. + + init_fn is called at the beginning for initial, and returns an object. + free_fn is called at the end. + + compute_fn is called for each XYZ in the specified grid, and returns + the double value of that coordinate. If smoothing is on, then + compute_fn will also be called twice more for each emitted vertex, + in order to calculate vertex normals (so don't assume it will only + be called with values falling on the grid boundaries.) + + Points are inside an object if the are less than `isolevel', and + outside otherwise. +*/ +void +marching_cubes (int grid_size, /* density of the mesh */ + double isolevel, /* cutoff point for "in" versus "out" */ + int wireframe_p, /* wireframe, or solid */ + int smooth_p, /* smooth, or faceted */ + + void * (*init_fn) (double grid_size, void *closure1), + double (*compute_fn) (double x, double y, double z, + void *closure2), + void (*free_fn) (void *closure2), + void *closure1, + + unsigned long *polygon_count) +{ + int planesize = grid_size * grid_size; + int x, y, z; + void *closure2 = 0; + unsigned long polys = 0; + double *layers; + + layers = (double *) calloc (sizeof (*layers), planesize * 2); + if (!layers) + { + fprintf (stderr, "%s: out of memory for %dx%dx%d grid\n", + progname, grid_size, grid_size, 2); + exit (1); + } + + if (init_fn) + closure2 = init_fn (grid_size, closure1); + + glFrontFace(GL_CCW); + if (!wireframe_p) + glBegin (GL_TRIANGLES); + + for (z = 0; z < grid_size; z++) + { + double *layer0 = (z & 1 ? layers+planesize : layers); + double *layer1 = (z & 1 ? layers : layers+planesize); + double *row; + + /* Fill in the XY grid on the currently-bottommost layer. */ + row = layer1; + for (y = 0; y < grid_size; y++, row += grid_size) + { + double *cell = row; + for (x = 0; x < grid_size; x++, cell++) + *cell = compute_fn (x, y, z, closure2); + } + + /* Now we've completed one layer (an XY slice of Z.) Now we can + generate the polygons that fill the space between this layer + and the previous one (unless this is the first layer.) + */ + if (z == 0) continue; + + for (y = 1; y < grid_size; y += 1) + for (x = 1; x < grid_size; x += 1) + { + TRIANGLE tri[6]; + int i, ntri; + GRIDCELL cell; + + /* This is kinda hokey, there ought to be a more efficient + way to do this... */ + cell.p[0].x = x-1; cell.p[0].y = y-1; cell.p[0].z = z-1; + cell.p[1].x = x ; cell.p[1].y = y-1; cell.p[1].z = z-1; + cell.p[2].x = x ; cell.p[2].y = y ; cell.p[2].z = z-1; + cell.p[3].x = x-1; cell.p[3].y = y ; cell.p[3].z = z-1; + cell.p[4].x = x-1; cell.p[4].y = y-1; cell.p[4].z = z ; + cell.p[5].x = x ; cell.p[5].y = y-1; cell.p[5].z = z ; + cell.p[6].x = x ; cell.p[6].y = y ; cell.p[6].z = z ; + cell.p[7].x = x-1; cell.p[7].y = y ; cell.p[7].z = z ; + +# define GRID(X,Y,WHICH) ((WHICH) \ + ? layer1[((Y)*grid_size) + ((X))] \ + : layer0[((Y)*grid_size) + ((X))]) + + cell.val[0] = GRID (x-1, y-1, 0); + cell.val[1] = GRID (x , y-1, 0); + cell.val[2] = GRID (x , y , 0); + cell.val[3] = GRID (x-1, y , 0); + cell.val[4] = GRID (x-1, y-1, 1); + cell.val[5] = GRID (x , y-1, 1); + cell.val[6] = GRID (x , y , 1); + cell.val[7] = GRID (x-1, y , 1); +# undef GRID + + /* Now generate the triangles for this cubic segment, + and emit the GL faces. + */ + ntri = march_one_cube (cell, isolevel, tri); + polys += ntri; + for (i = 0; i < ntri; i++) + { + if (wireframe_p) glBegin (GL_LINE_LOOP); + + /* If we're smoothing, we need to call the field function + again for each vertex (via function_normal().) If we're + not smoothing, then we can just compute the normal from + this triangle. + */ + if (!smooth_p) + do_normal (tri[i].p[0].x, tri[i].p[0].y, tri[i].p[0].z, + tri[i].p[1].x, tri[i].p[1].y, tri[i].p[1].z, + tri[i].p[2].x, tri[i].p[2].y, tri[i].p[2].z); + +# define VERT(X,Y,Z) \ + if (smooth_p) \ + do_function_normal ((X), (Y), (Z), compute_fn, closure2); \ + glVertex3f ((X), (Y), (Z)) + + VERT (tri[i].p[0].x, tri[i].p[0].y, tri[i].p[0].z); + VERT (tri[i].p[1].x, tri[i].p[1].y, tri[i].p[1].z); + VERT (tri[i].p[2].x, tri[i].p[2].y, tri[i].p[2].z); +# undef VERT + if (wireframe_p) glEnd (); + } + } + } + + if (!wireframe_p) + glEnd (); + + free (layers); + + if (free_fn) + free_fn (closure2); + + if (polygon_count) + *polygon_count = polys; +} diff --git a/hacks/glx/marching.h b/hacks/glx/marching.h new file mode 100644 index 00000000..755545d5 --- /dev/null +++ b/hacks/glx/marching.h @@ -0,0 +1,48 @@ +/* xscreensaver, Copyright (c) 2002 Jamie Zawinski + * Utility functions to create "marching cubes" meshes from 3d fields. + * + * 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. + */ + +#ifndef __MARCHING_H__ +#define __MARCHING_H__ + +/* Given a function capable of generating a value at any XYZ position, + creates OpenGL faces for the solids defined. + + init_fn is called at the beginning for initial, and returns an object. + free_fn is called at the end. + + compute_fn is called for each XYZ in the specified grid, and returns + the double value of that coordinate. If smoothing is on, then + compute_fn will also be called twice more for each emitted vertex, + in order to calculate vertex normals (so don't assume it will only + be called with values falling on the grid boundaries.) + + Points are inside an object if the are less than `isolevel', and + outside otherwise. + + If polygon_count is specified, the number of faces generated will be + returned there. +*/ +extern void +marching_cubes (int grid_size, /* density of the mesh */ + double isolevel, /* cutoff point for "in" versus "out" */ + int wireframe_p, /* wireframe, or solid */ + int smooth_p, /* smooth, or faceted */ + + void * (*init_fn) (double grid_size, void *closure1), + double (*compute_fn) (double x, double y, double z, + void *closure2), + void (*free_fn) (void *closure2), + void *closure1, + + unsigned long *polygon_count); + +#endif /* __MARCHING_H__ */ diff --git a/hacks/glx/menger.c b/hacks/glx/menger.c new file mode 100644 index 00000000..2319af76 --- /dev/null +++ b/hacks/glx/menger.c @@ -0,0 +1,555 @@ +/* menger, Copyright (c) 2001-2006 Jamie Zawinski + * Copyright (c) 2002 Aurelien Jacobs + * + * 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. + * + * Generates a 3D Menger Sponge gasket: + * + * ___+._______ + * __-"" -- __"""----._____ + * __.--"" -- ___--+---_____. __ .+'| + * _.-'"" __ +:"__ | ._..+"" __ .+' F + * J"--.____ __ """""+" .+' .J F + * J """""---.___ -- .+'" F' F + * L """""--...+' .J F + * L F"9 --. | . F' J + * L -_J L_J F"9 | ;'J .+J .J J + * | L_J | F.' .'| J F' J + * | |"""--.__ | ' |"" J J + * J ._ J ;;; | "L | . |-___J | + * J L J J ;-' | L | .'J |_ .' . | + * J "" J .---_L F"9 | F.' | .' FJ | + * L J .-' __ | L_J | ' :' ' .+ + * L '--.___ | | .J .' + * | F"9 """' | . F' .' + * | -_J F"9 | .'J .' + * +__ -_J F"9 | F.' .' + * """--___ L_J | ' .' + * """---___ | .' + * ""---._|.' + * + * The straightforward way to generate this object creates way more polygons + * than are needed, since there end up being many buried, interior faces. + * So during the recursive building of the object we store which face of + * each unitary cube we need to draw. Doing this reduces the polygon count + * by 40% - 60%. + * + * Another optimization we could do to reduce the polygon count would be to + * merge adjascent coplanar squares together into rectangles. This would + * result in the outer faces being composed of 1xN strips. It's tricky to + * to find these adjascent faces in non-exponential time, though. + * + * We could actually simulate large depths with a texture map -- if the + * depth is such that the smallest holes are only a few pixels across, + * just draw them as spots on the surface! It would look the same. + */ + +#define DEFAULTS "*delay: 30000 \n" \ + "*showFPS: False \n" \ + "*wireframe: False \n" \ + + +# define refresh_sponge 0 +# define release_sponge 0 +#undef countof +#define countof(x) (sizeof((x))/sizeof((*x))) + +#include "xlockmore.h" +#include "colors.h" +#include "rotator.h" +#include "gltrackball.h" +#include + +#ifdef USE_GL /* whole file */ + +#define DEF_SPIN "True" +#define DEF_WANDER "True" +#define DEF_SPEED "150" +#define DEF_MAX_DEPTH "3" + +typedef struct { + GLXContext *glx_context; + rotator *rot; + trackball_state *trackball; + Bool button_down_p; + GLuint sponge_list0; /* we store X, Y, and Z-facing surfaces */ + GLuint sponge_list1; /* in their own lists, to make it easy */ + GLuint sponge_list2; /* to color them differently. */ + + unsigned long squares_fp; + + int current_depth; + + int ncolors; + XColor *colors; + int ccolor0; + int ccolor1; + int ccolor2; + + int draw_tick; + +} sponge_configuration; + +static sponge_configuration *sps = NULL; + +static Bool do_spin; +static Bool do_wander; +static int speed; +static int max_depth; + +static XrmOptionDescRec opts[] = { + { "-wander", ".wander", XrmoptionNoArg, "True" }, + { "+wander", ".wander", XrmoptionNoArg, "False" }, + { "-spin", ".spin", XrmoptionSepArg, 0 }, + { "-speed", ".speed", XrmoptionSepArg, 0 }, + { "-depth", ".maxDepth", 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_Int}, + {&max_depth, "maxDepth", "MaxDepth", DEF_MAX_DEPTH, t_Int}, +}; + +ENTRYPOINT ModeSpecOpt sponge_opts = {countof(opts), opts, countof(vars), vars, NULL}; + + +/* Window management, etc + */ +ENTRYPOINT void +reshape_sponge (ModeInfo *mi, int width, int height) +{ + GLfloat h = (GLfloat) height / (GLfloat) width; + + glViewport (0, 0, (GLint) width, (GLint) height); + + glMatrixMode(GL_PROJECTION); + glLoadIdentity(); + gluPerspective (30.0, 1/h, 1.0, 100.0); + + glMatrixMode(GL_MODELVIEW); + glLoadIdentity(); + gluLookAt( 0.0, 0.0, 30.0, + 0.0, 0.0, 0.0, + 0.0, 1.0, 0.0); + + glClear(GL_COLOR_BUFFER_BIT); +} + + +#define X0 0x01 +#define X1 0x02 +#define Y0 0x04 +#define Y1 0x08 +#define Z0 0x10 +#define Z1 0x20 + +static int +cube (float x0, float x1, float y0, float y1, float z0, float z1, + int faces, int wireframe) +{ + int n = 0; + + if (faces & X0) + { + glBegin (wireframe ? GL_LINE_LOOP : GL_POLYGON); + glNormal3f (-1.0, 0.0, 0.0); + glVertex3f (x0, y1, z0); + glVertex3f (x0, y0, z0); + glVertex3f (x0, y0, z1); + glVertex3f (x0, y1, z1); + glEnd (); + n++; + } + if (faces & X1) + { + glBegin (wireframe ? GL_LINE_LOOP : GL_POLYGON); + glNormal3f (1.0, 0.0, 0.0); + glVertex3f (x1, y1, z1); + glVertex3f (x1, y0, z1); + glVertex3f (x1, y0, z0); + glVertex3f (x1, y1, z0); + glEnd (); + n++; + } + if (faces & Y0) + { + glBegin (wireframe ? GL_LINE_LOOP : GL_POLYGON); + glNormal3f (0.0, -1.0, 0.0); + glVertex3f (x0, y0, z0); + glVertex3f (x0, y0, z1); + glVertex3f (x1, y0, z1); + glVertex3f (x1, y0, z0); + glEnd (); + n++; + } + if (faces & Y1) + { + glBegin (wireframe ? GL_LINE_LOOP : GL_POLYGON); + glNormal3f (0.0, 1.0, 0.0); + glVertex3f (x0, y1, z0); + glVertex3f (x0, y1, z1); + glVertex3f (x1, y1, z1); + glVertex3f (x1, y1, z0); + glEnd (); + n++; + } + if (faces & Z0) + { + glBegin (wireframe ? GL_LINE_LOOP : GL_POLYGON); + glNormal3f (0.0, 0.0, -1.0); + glVertex3f (x1, y1, z0); + glVertex3f (x1, y0, z0); + glVertex3f (x0, y0, z0); + glVertex3f (x0, y1, z0); + glEnd (); + n++; + } + if (faces & Z1) + { + glBegin (wireframe ? GL_LINE_LOOP : GL_POLYGON); + glNormal3f (0.0, 0.0, 1.0); + glVertex3f (x0, y1, z1); + glVertex3f (x0, y0, z1); + glVertex3f (x1, y0, z1); + glVertex3f (x1, y1, z1); + glEnd (); + n++; + } + + return n; +} + +static int +menger_recurs_1 (int level, float x0, float x1, float y0, float y1, + float z0, float z1, int faces, Bool wireframe, + int orig, int forig) +{ + float xi, yi, zi; + int f, x, y, z; + int n = 0; + + if (orig) + { + if (wireframe) + n += cube (x0, x1, y0, y1, z0, z1, + faces & (X0 | X1 | Y0 | Y1), wireframe); + } + + if (level == 0) + { + if (!wireframe) + n += cube (x0, x1, y0, y1, z0, z1, faces, wireframe); + } + else + { + xi = (x1 - x0) / 3; + yi = (y1 - y0) / 3; + zi = (z1 - z0) / 3; + + for (x = 0; x < 3; x++) + for (y = 0; y < 3; y++) + for (z = 0; z < 3; z++) + { + if ((x != 1 && y != 1) + || (y != 1 && z != 1) + || (x != 1 && z != 1)) + { + f = faces; + + if (x == 1 || (x == 2 && (y != 1 && z != 1))) + f &= ~X0; + if (x == 1 || (x == 0 && (y != 1 && z != 1))) + f &= ~X1; + if (forig & X0 && x == 2 && (y == 1 || z == 1)) + f |= X0; + if (forig & X1 && x == 0 && (y == 1 || z == 1)) + f |= X1; + + if (y == 1 || (y == 2 && (x != 1 && z != 1))) + f &= ~Y0; + if (y == 1 || (y == 0 && (x != 1 && z != 1))) + f &= ~Y1; + if (forig & Y0 && y == 2 && (x == 1 || z == 1)) + f |= Y0; + if (forig & Y1 && y == 0 && (x == 1 || z == 1)) + f |= Y1; + + if (z == 1 || (z == 2 && (x != 1 && y != 1))) + f &= ~Z0; + if (z == 1 || (z == 0 && (x != 1 && y != 1))) + f &= ~Z1; + if (forig & Z0 && z == 2 && (x == 1 || y == 1)) + f |= Z0; + if (forig & Z1 && z == 0 && (x == 1 || y == 1)) + f |= Z1; + + n += menger_recurs_1 (level-1, + x0+x*xi, x0+(x+1)*xi, + y0+y*yi, y0+(y+1)*yi, + z0+z*zi, z0+(z+1)*zi, f, wireframe, 0, + forig); + } + else if (wireframe && (x != 1 || y != 1 || z != 1)) + n += cube (x0+x*xi, x0+(x+1)*xi, + y0+y*yi, y0+(y+1)*yi, + z0+z*zi, z0+(z+1)*zi, + forig & (X0 | X1 | Y0 | Y1), wireframe); + } + } + + return n; +} + +static int +menger_recurs (int level, float x0, float x1, float y0, float y1, + float z0, float z1, int faces, Bool wireframe, + int orig) +{ + return menger_recurs_1 (level, x0, x1, y0, y1, z0, z1, faces, + wireframe, orig, faces); +} + + +static void +build_sponge (sponge_configuration *sp, Bool wireframe, int level) +{ + glDeleteLists (sp->sponge_list0, 1); + glNewList(sp->sponge_list0, GL_COMPILE); + sp->squares_fp = menger_recurs (level, -1.5, 1.5, -1.5, 1.5, -1.5, 1.5, + X0 | X1, wireframe,1); + glEndList(); + + glDeleteLists (sp->sponge_list1, 1); + glNewList(sp->sponge_list1, GL_COMPILE); + sp->squares_fp += menger_recurs (level, -1.5, 1.5, -1.5, 1.5, -1.5, 1.5, + Y0 | Y1, wireframe,1); + glEndList(); + + glDeleteLists (sp->sponge_list2, 1); + glNewList(sp->sponge_list2, GL_COMPILE); + sp->squares_fp += menger_recurs (level, -1.5, 1.5, -1.5, 1.5, -1.5, 1.5, + Z0 | Z1, wireframe,1); + glEndList(); +} + + +ENTRYPOINT Bool +sponge_handle_event (ModeInfo *mi, XEvent *event) +{ + sponge_configuration *sp = &sps[MI_SCREEN(mi)]; + + if (event->xany.type == ButtonPress && + event->xbutton.button == Button1) + { + sp->button_down_p = True; + gltrackball_start (sp->trackball, + event->xbutton.x, event->xbutton.y, + MI_WIDTH (mi), MI_HEIGHT (mi)); + return True; + } + else if (event->xany.type == ButtonRelease && + event->xbutton.button == Button1) + { + sp->button_down_p = False; + return True; + } + else if (event->xany.type == ButtonPress && + (event->xbutton.button == Button4 || + event->xbutton.button == Button5 || + event->xbutton.button == Button6 || + event->xbutton.button == Button7)) + { + gltrackball_mousewheel (sp->trackball, event->xbutton.button, 5, + !!event->xbutton.state); + return True; + } + else if (event->xany.type == MotionNotify && + sp->button_down_p) + { + gltrackball_track (sp->trackball, + event->xmotion.x, event->xmotion.y, + MI_WIDTH (mi), MI_HEIGHT (mi)); + return True; + } + + return False; +} + + + +ENTRYPOINT void +init_sponge (ModeInfo *mi) +{ + sponge_configuration *sp; + int wire = MI_IS_WIREFRAME(mi); + + if (!sps) { + sps = (sponge_configuration *) + calloc (MI_NUM_SCREENS(mi), sizeof (sponge_configuration)); + if (!sps) { + fprintf(stderr, "%s: out of memory\n", progname); + exit(1); + } + } + + sp = &sps[MI_SCREEN(mi)]; + + if ((sp->glx_context = init_GL(mi)) != NULL) { + reshape_sponge (mi, MI_WIDTH(mi), MI_HEIGHT(mi)); + } + + if (!wire) + { + static const GLfloat pos0[4] = {-1.0, -1.0, 1.0, 0.1}; + static const GLfloat pos1[4] = { 1.0, -0.2, 0.2, 0.1}; + static const GLfloat dif0[4] = {1.0, 1.0, 1.0, 1.0}; + static const GLfloat dif1[4] = {1.0, 1.0, 1.0, 1.0}; + + glLightfv(GL_LIGHT0, GL_POSITION, pos0); + glLightfv(GL_LIGHT1, GL_POSITION, pos1); + glLightfv(GL_LIGHT0, GL_DIFFUSE, dif0); + glLightfv(GL_LIGHT1, GL_DIFFUSE, dif1); + + glEnable(GL_LIGHTING); + glEnable(GL_LIGHT0); + glEnable(GL_LIGHT1); + + glEnable(GL_DEPTH_TEST); + glEnable(GL_NORMALIZE); + + glShadeModel(GL_SMOOTH); + } + + { + double spin_speed = 1.0; + double wander_speed = 0.03; + sp->rot = make_rotator (do_spin ? spin_speed : 0, + do_spin ? spin_speed : 0, + do_spin ? spin_speed : 0, + 1.0, + do_wander ? wander_speed : 0, + True); + sp->trackball = gltrackball_init (); + } + + sp->ncolors = 128; + sp->colors = (XColor *) calloc(sp->ncolors, sizeof(XColor)); + make_smooth_colormap (0, 0, 0, + sp->colors, &sp->ncolors, + False, 0, False); + sp->ccolor0 = 0; + sp->ccolor1 = sp->ncolors / 3; + sp->ccolor2 = sp->ccolor1 * 2; + + sp->sponge_list0 = glGenLists (1); + sp->sponge_list1 = glGenLists (1); + sp->sponge_list2 = glGenLists (1); + + sp->draw_tick = 9999999; +} + + +ENTRYPOINT void +draw_sponge (ModeInfo *mi) +{ + sponge_configuration *sp = &sps[MI_SCREEN(mi)]; + Display *dpy = MI_DISPLAY(mi); + Window window = MI_WINDOW(mi); + + GLfloat color0[4] = {0.0, 0.0, 0.0, 1.0}; + GLfloat color1[4] = {0.0, 0.0, 0.0, 1.0}; + GLfloat color2[4] = {0.0, 0.0, 0.0, 1.0}; + + if (!sp->glx_context) + return; + + glXMakeCurrent(MI_DISPLAY(mi), MI_WINDOW(mi), *(sp->glx_context)); + + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + + glPushMatrix (); + + glScalef(1.1, 1.1, 1.1); + + { + double x, y, z; + get_position (sp->rot, &x, &y, &z, !sp->button_down_p); + glTranslatef((x - 0.5) * 8, + (y - 0.5) * 6, + (z - 0.5) * 15); + + /* Do it twice because we don't track the device's orientation. */ + glRotatef( current_device_rotation(), 0, 0, 1); + gltrackball_rotate (sp->trackball); + glRotatef(-current_device_rotation(), 0, 0, 1); + + get_rotation (sp->rot, &x, &y, &z, !sp->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); + } + + color0[0] = sp->colors[sp->ccolor0].red / 65536.0; + color0[1] = sp->colors[sp->ccolor0].green / 65536.0; + color0[2] = sp->colors[sp->ccolor0].blue / 65536.0; + + color1[0] = sp->colors[sp->ccolor1].red / 65536.0; + color1[1] = sp->colors[sp->ccolor1].green / 65536.0; + color1[2] = sp->colors[sp->ccolor1].blue / 65536.0; + + color2[0] = sp->colors[sp->ccolor2].red / 65536.0; + color2[1] = sp->colors[sp->ccolor2].green / 65536.0; + color2[2] = sp->colors[sp->ccolor2].blue / 65536.0; + + + sp->ccolor0++; + sp->ccolor1++; + sp->ccolor2++; + if (sp->ccolor0 >= sp->ncolors) sp->ccolor0 = 0; + if (sp->ccolor1 >= sp->ncolors) sp->ccolor1 = 0; + if (sp->ccolor2 >= sp->ncolors) sp->ccolor2 = 0; + + if (sp->draw_tick++ >= speed) + { + sp->draw_tick = 0; + if (sp->current_depth >= max_depth) + sp->current_depth = -max_depth; + sp->current_depth++; + build_sponge (sp, + MI_IS_WIREFRAME(mi), + (sp->current_depth < 0 + ? -sp->current_depth : sp->current_depth)); + + mi->polygon_count = sp->squares_fp; /* for FPS display */ + mi->recursion_depth = (sp->current_depth < 0 + ? -sp->current_depth : sp->current_depth); + } + + glScalef (2.0, 2.0, 2.0); + + glMaterialfv (GL_FRONT, GL_AMBIENT_AND_DIFFUSE, color0); + glCallList (sp->sponge_list0); + glMaterialfv (GL_FRONT, GL_AMBIENT_AND_DIFFUSE, color1); + glCallList (sp->sponge_list1); + glMaterialfv (GL_FRONT, GL_AMBIENT_AND_DIFFUSE, color2); + glCallList (sp->sponge_list2); + + glPopMatrix (); + + if (mi->fps_p) do_fps (mi); + glFinish(); + + glXSwapBuffers(dpy, window); +} + +XSCREENSAVER_MODULE_2 ("Menger", menger, sponge) + +#endif /* USE_GL */ diff --git a/hacks/glx/menger.man b/hacks/glx/menger.man new file mode 100644 index 00000000..c2c21412 --- /dev/null +++ b/hacks/glx/menger.man @@ -0,0 +1,78 @@ +.TH XScreenSaver 1 "" "X Version 11" +.SH NAME +menger - 3D menger gasket fractal. +.SH SYNOPSIS +.B menger +[\-display \fIhost:display.screen\fP] +[\-visual \fIvisual\fP] +[\-window] +[\-root] +[\-delay \fInumber\fP] +[\-speed \fInumber\fP] +[\-depth \fInumber\fP] +[\-no-wander] +[\-no-spin] +[\-spin \fI[XYZ]\fP] +[\-wireframe] +[\-fps] +.SH DESCRIPTION +This draws the three-dimensional variant of the recursive Menger Gasket, a +cube-based fractal object analagous to the Sierpinski Tetrahedron. +.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 \-speed \fInumber\fP +Number of frames before changing shape. Default: 150. +.TP 8 +.B \-depth \fInumber\fP +Max depth to descend. Default: 3. You probably don't have enough +memory for 6. +.TP 8 +.B \-wander | \-no-wander +Whether the object should wander around the screen. +.TP 8 +.B \-spin [XYZ] +Around which axes should the object spin? +.TP 8 +.B \-no-spin +None. +.TP 8 +.B \-wireframe +Render in wireframe instead of solid. +.TP 8 +.B \-fps +Display the current frame rate, CPU load, and polygon count. +.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 2002 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/glx/mirrorblob.c b/hacks/glx/mirrorblob.c new file mode 100644 index 00000000..6daa372f --- /dev/null +++ b/hacks/glx/mirrorblob.c @@ -0,0 +1,1862 @@ +/* mirrorblob Copyright (c) 2003 Jon Dowdall */ +/* + * Permission to use, copy, modify, and distribute this software and its + * documentation for any purpose and without fee is hereby granted, + * provided that the above copyright notice appear in all copies and that + * both that copyright notice and this permission notice appear in + * supporting documentation. + * + * This file is provided AS IS with no warranties of any kind. The author + * shall have no liability with respect to the infringement of copyrights, + * trade secrets or any patents by this file or any part thereof. In no + * event will the author be liable for any lost revenue or profits or + * other special, indirect and consequential damages. + * + * Revision History: + * 23-Sep-2003: jon.dowdall@bigpond.com Created module "blob" + * 19-Oct-2003: jon.dowdall@bigpond.com Added texturing + * 21-Oct-2003: Renamed to mirrorblob + * 10-Feb-2004: jon.dowdall@bigpond.com Added motion blur + * 28-Jan-2006: jon.dowdall@bigpond.com Big clean up and bug fixes + * 13-Apr-2009: jon.dowdall@gmail.com Fixed Mac version + * + * The mirrorblob screensaver draws a pulsing blob on the screen. Options + * include adding a background (via screen_to_texture), texturing the blob, + * making the blob semi-transparent and varying the resolution of the blob + * tessellation. + * + * The blob was inspired by a lavalamp is in no way a simulation. The code is + * just an attempt to generate some eye-candy. + * + * Much of xmirrorblob code framework is taken from the pulsar module by David + * Konerding and the glslideshow by Mike Oliphant and Jamie Zawinski. + * + */ + +#include + +#ifdef STANDALONE +#define DEFAULTS "*delay: " DEF_DELAY "\n" \ + "*showFPS: " DEF_FPS "\n" \ + "*useSHM: True \n" \ + "*desktopGrabber: xscreensaver-getimage -no-desktop %s\n" \ + "*grabDesktopImages: True \n" \ + "*chooseRandomImages: True \n" + +# define refresh_mirrorblob 0 +/* +# define mirrorblob_handle_event 0 +*/ +# include "xlockmore.h" +#else /* !STANDALONE */ +# include "xlock.h" /* from the xlockmore distribution */ +#endif /* !STANDALONE */ + +#ifdef USE_GL /* whole file */ + + +#define DEF_DELAY "10000" +#define DEF_FPS "False" +#define DEF_WIRE "False" +#define DEF_BLEND "1.0" +#define DEF_FOG "False" +#define DEF_ANTIALIAS "False" +#define DEF_WALLS "False" +#define DEF_COLOUR "False" +#define DEF_ASYNC "True" +#define DEF_TEXTURE "True" +#define DEF_OFFSET_TEXTURE "False" +#define DEF_PAINT_BACKGROUND "True" +#define DEF_RESOLUTION "30" +#define DEF_BUMPS "10" +#define DEF_MOTION_BLUR "0.0" +#define DEF_INCREMENTAL "0" +#define DEF_HOLD_TIME "30.0" +#define DEF_FADE_TIME "5.0" +#define DEF_ZOOM "1.0" + +#ifdef HAVE_XMU +# ifndef VMS +# include +#else /* VMS */ +# include +# endif /* VMS */ +#endif + +#include "gltrackball.h" +#include "grab-ximage.h" + +#undef countof +#define countof(x) (sizeof((x)) / sizeof((*x))) + +#define PI 3.1415926535897 + +/* Options from command line */ +static GLfloat blend; +static Bool wireframe; +static Bool do_fog; +static Bool do_antialias; +static Bool do_walls; +static Bool do_texture; +static Bool do_paint_background; +static Bool do_colour; +static Bool offset_texture; +static int resolution; +static int bumps; +static float motion_blur; +static float fade_time; +static float hold_time; +static float zoom; + +/* Internal parameters based on supplied options */ +static Bool culling; +static Bool load_textures; + +static XrmOptionDescRec opts[] = { + {"-wire", ".blob.wire", XrmoptionNoArg, "true" }, + {"+wire", ".blob.wire", XrmoptionNoArg, "false" }, + {"-blend", ".blob.blend", XrmoptionSepArg, 0 }, + {"-fog", ".blob.fog", XrmoptionNoArg, "true" }, + {"+fog", ".blob.fog", XrmoptionNoArg, "false" }, + {"-antialias", ".blob.antialias", XrmoptionNoArg, "true" }, + {"+antialias", ".blob.antialias", XrmoptionNoArg, "false" }, + {"-walls", ".blob.walls", XrmoptionNoArg, "true" }, + {"+walls", ".blob.walls", XrmoptionNoArg, "false" }, + {"-texture", ".blob.texture", XrmoptionNoArg, "true" }, + {"+texture", ".blob.texture", XrmoptionNoArg, "false" }, + {"-colour", ".blob.colour", XrmoptionNoArg, "true" }, + {"+colour", ".blob.colour", XrmoptionNoArg, "false" }, + {"-offset-texture", ".blob.offsetTexture", XrmoptionNoArg, "true" }, + {"+offset-texture", ".blob.offsetTexture", XrmoptionNoArg, "false" }, + {"-paint-background", ".blob.paintBackground", XrmoptionNoArg, "true" }, + {"+paint-background", ".blob.paintBackground", XrmoptionNoArg, "false" }, + {"-resolution", ".blob.resolution", XrmoptionSepArg, NULL }, + {"-bumps", ".blob.bumps", XrmoptionSepArg, NULL }, + {"-motion-blur", ".blob.motionBlur", XrmoptionSepArg, 0 }, + {"-fade-time", ".blob.fadeTime", XrmoptionSepArg, 0 }, + {"-hold-time", ".blob.holdTime", XrmoptionSepArg, 0 }, + {"-zoom", ".blob.zoom", XrmoptionSepArg, 0 }, +}; + +static argtype vars[] = { + {&wireframe, "wire", "Wire", DEF_WIRE, t_Bool}, + {&blend, "blend", "Blend", DEF_BLEND, t_Float}, + {&do_fog, "fog", "Fog", DEF_FOG, t_Bool}, + {&do_antialias, "antialias", "Antialias", DEF_ANTIALIAS, t_Bool}, + {&do_walls, "walls", "Walls", DEF_WALLS, t_Bool}, + {&do_texture, "texture", "Texture", DEF_TEXTURE, t_Bool}, + {&do_colour, "colour", "Colour", DEF_COLOUR, t_Bool}, + {&offset_texture, "offsetTexture","OffsetTexture", DEF_OFFSET_TEXTURE, t_Bool}, + {&do_paint_background,"paintBackground","PaintBackground", DEF_PAINT_BACKGROUND, t_Bool}, + {&resolution, "resolution", "Resolution", DEF_RESOLUTION, t_Int}, + {&bumps, "bumps", "Bump", DEF_BUMPS, t_Int}, + {&motion_blur, "motionBlur", "MotionBlur", DEF_MOTION_BLUR, t_Float}, + {&fade_time, "fadeTime", "FadeTime", DEF_FADE_TIME, t_Float}, + {&hold_time, "holdTime", "HoldTime", DEF_HOLD_TIME, t_Float}, + {&zoom, "zoom", "Zoom", DEF_ZOOM, t_Float}, +}; + + +static OptionStruct desc[] = +{ + {"-/+ wire", "whether to do use wireframe instead of filled (faster)"}, + {"-/+ blend", "whether to do enable blending (slower)"}, + {"-/+ fog", "whether to do enable fog (slower)"}, + {"-/+ antialias", "whether to do enable antialiased lines (slower)"}, + {"-/+ walls", "whether to add walls to the blob space (slower)"}, + {"-/+ texture", "whether to add a texture to the blob (slower)"}, + {"-/+ colour", "whether to colour the blob"}, + {"-/+ offset_texture", "whether to offset texture co-ordinates"}, + {"-/+ paint_background", "whether to display a background texture (slower)"}, + {"-resolution", "Resolution of blob tesselation"}, + {"-bumps", "Number of bumps used to disturb blob"}, + {"-motion_blur", "Fade blob images (higher number = faster fade)"}, + {"-fade_time", "Number of frames to transistion to next image"}, + {"-hold_time", "Number of frames before next image"}, +}; + +ENTRYPOINT ModeSpecOpt mirrorblob_opts = {countof(opts), opts, countof(vars), vars, desc}; + +#ifdef USE_MODULES +ModStruct mirrorblob_description = +{"mirrorblob", "init_mirrorblob", "draw_mirrorblob", "release_mirrorblob", + "draw_mirrorblob", "init_mirrorblob", "handle_event", &mirrorblob_opts, + 1000, 1, 2, 1, 4, 1.0, "", + "OpenGL mirrorblob", 0, NULL}; +#endif + +/***************************************************************************** + * Types used in blob code + *****************************************************************************/ + +typedef struct +{ + GLfloat x, y; +} Vector2D; + +typedef struct +{ + GLfloat x, y, z; +} Vector3D; + +typedef struct +{ + GLfloat w; + GLfloat x; + GLfloat y; + GLfloat z; +} Quaternion; + +typedef struct +{ + GLubyte red, green, blue, alpha; +} Colour; + +typedef struct +{ + Vector3D initial_position; + Vector3D position; + Vector3D normal; +} Node_Data; + +typedef struct +{ + int node1, node2, node3; + Vector3D normal; + double length1, length2, length3; +} Face_Data; + +/* Structure to hold data about bumps used to distortion sphere */ +typedef struct +{ + double cx, cy, cpower, csize; + double ax, ay, power, size; + double mx, my, mpower, msize; + double vx, vy, vpower, vsize; + Vector3D pos; +} Bump_Data; + +/* Vertices of a tetrahedron */ +#define sqrt_3 0.5773502692 +/*#undef sqrt_3 +#define sqrt_3 1.0*/ +#define PPP { sqrt_3, sqrt_3, sqrt_3 } /* +X, +Y, +Z */ +#define MMP { -sqrt_3, -sqrt_3, sqrt_3 } /* -X, -Y, +Z */ +#define MPM { -sqrt_3, sqrt_3, -sqrt_3 } /* -X, +Y, -Z */ +#define PMM { sqrt_3, -sqrt_3, -sqrt_3 } /* +X, -Y, -Z */ + +/* Structure describing a tetrahedron */ +static Vector3D tetrahedron[4][3] = { + {PPP, MMP, MPM}, + {PMM, MPM, MMP}, + {PPP, MPM, PMM}, + {PPP, PMM, MMP} +}; + +/***************************************************************************** + * Static blob data + *****************************************************************************/ + +static const Vector3D zero_vector = { 0.0, 0.0, 0.0 }; + +/* Use 2 textures to allow a gradual fade between images */ +#define NUM_TEXTURES 2 +#define BUMP_ARRAY_SIZE 1024 + +typedef enum +{ + INITIALISING, + HOLDING, + LOADING, + TRANSITIONING +} Frame_State; + +/* structure for holding the mirrorblob data */ +typedef struct { + int screen_width, screen_height; + GLXContext *glx_context; + Window window; + XColor fg, bg; + + /* Parameters controlling the position of the blob as a whole */ + Vector3D blob_center; + Vector3D blob_anchor; + Vector3D blob_velocity; + Vector3D blob_force; + + /* Count of the total number of nodes and faces used to tesselate the blob */ + int num_nodes; + int num_faces; + + Node_Data *nodes; + Face_Data *faces; + + Vector3D *dots; + Vector3D *normals; + Colour *colours; + Vector2D *tex_coords; + + /* Pointer to the bump function results */ + double *bump_shape, *wall_shape; + + Bump_Data *bump_data; + + /* Use 2 textures to allow a gradual fade between images */ + int current_texture; + + /* Ratio of used texture size to total texture size */ + GLfloat tex_width[NUM_TEXTURES], tex_height[NUM_TEXTURES]; + GLuint textures[NUM_TEXTURES]; + + Frame_State state; + double state_start_time; + + int colour_cycle; + + Bool mipmap_p; + Bool waiting_for_image_p; + Bool first_image_p; + + trackball_state *trackball; + int button_down; + +} mirrorblobstruct; + +static mirrorblobstruct *Mirrorblob = NULL; + +/****************************************************************************** + * + * Returns the current time in seconds as a double. Shamelessly borrowed from + * glslideshow. + * + */ +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)); +} + +/****************************************************************************** + * + * Change to the projection matrix and set our viewing volume. + * + */ +static void +reset_projection(int width, int height) +{ + glMatrixMode (GL_PROJECTION); + glLoadIdentity (); + gluPerspective (60.0, 1.0, 1.0, 1024.0 ); + glMatrixMode (GL_MODELVIEW); + glLoadIdentity (); +} + +/****************************************************************************** + * + * Calculate the dot product of two vectors u and v + * Dot product u.v = |u||v|cos(theta) + * Where theta = angle between u and v + */ +static inline double +dot (const Vector3D u, const Vector3D v) +{ + return (u.x * v.x) + (u.y * v.y) + (u.z * v.z); +} + +/****************************************************************************** + * + * Calculate the cross product of two vectors. + * Gives a vector perpendicular to u and v with magnitude |u||v|sin(theta) + * Where theta = angle between u and v + */ +static inline Vector3D +cross (const Vector3D u, const Vector3D v) +{ + Vector3D result; + + result.x = (u.y * v.z - u.z * v.y); + result.y = (u.z * v.x - u.x * v.z); + result.z = (u.x * v.y - u.y * v.x); + + return result; +} + +/****************************************************************************** + * + * Add vector v to vector u + */ +static inline void +add (Vector3D *u, const Vector3D v) +{ + u->x = u->x + v.x; + u->y = u->y + v.y; + u->z = u->z + v.z; +} + +/****************************************************************************** + * + * Subtract vector v from vector u + */ +static inline Vector3D +subtract (const Vector3D u, const Vector3D v) +{ + Vector3D result; + + result.x = u.x - v.x; + result.y = u.y - v.y; + result.z = u.z - v.z; + + return result; +} + +/****************************************************************************** + * + * multiply vector v by scalar s + */ +static inline Vector3D +scale (const Vector3D v, const double s) +{ + Vector3D result; + + result.x = v.x * s; + result.y = v.y * s; + result.z = v.z * s; + return result; +} + +/****************************************************************************** + * + * normalise vector v + */ +static inline Vector3D +normalise (const Vector3D v) +{ + Vector3D result; + double magnitude; + + magnitude = sqrt (dot(v, v)); + + if (magnitude > 1e-300) + { + result = scale (v, 1.0 / magnitude); + } + else + { + printf("zero\n"); + result = zero_vector; + } + return result; +} + +/****************************************************************************** + * + * Calculate the transform matrix for the given quaternion + */ +static void +quaternion_transform (Quaternion q, GLfloat * transform) +{ + GLfloat x, y, z, w; + x = q.x; + y = q.y; + z = q.z; + w = q.w; + + transform[0] = (w * w) + (x * x) - (y * y) - (z * z); + transform[1] = (2.0 * x * y) + (2.0 * w * z); + transform[2] = (2.0 * x * z) - (2.0 * w * y); + transform[3] = 0.0; + + transform[4] = (2.0 * x * y) - (2.0 * w * z); + transform[5] = (w * w) - (x * x) + (y * y) - (z * z); + transform[6] = (2.0 * y * z) + (2.0 * w * x); + transform[7] = 0.0; + + transform[8] = (2.0 * x * z) + (2.0 * w * y); + transform[9] = (2.0 * y * z) - (2.0 * w * x); + transform[10] = (w * w) - (x * x) - (y * y) + (z * z); + transform[11] = 0.0; + + transform[12] = 0.0; + transform[13] = 0.0; + transform[14] = 0.0; + transform[15] = (w * w) + (x * x) + (y * y) + (z * z); +} + +/****************************************************************************** + * + * Apply a matrix transform to the given vector + */ +static inline Vector3D +vector_transform (Vector3D u, GLfloat * t) +{ + Vector3D result; + + result.x = (u.x * t[0] + u.y * t[4] + u.z * t[8] + 1.0 * t[12]); + result.y = (u.x * t[1] + u.y * t[5] + u.z * t[9] + 1.0 * t[13]); + result.z = (u.x * t[2] + u.y * t[6] + u.z * t[10] + 1.0 * t[14]); + + return result; +} + +/****************************************************************************** + * + * Return a node that is on an arc between node1 and node2, where distance + * is the proportion of the distance from node1 to the total arc. + */ +static Vector3D +partial (Vector3D node1, Vector3D node2, double distance) +{ + Vector3D result; + Vector3D rotation_axis; + GLfloat transformation[16]; + double angle; + Quaternion rotation; + + rotation_axis = normalise (cross (node1, node2)); + angle = acos (dot (node1, node2)) * distance; + + rotation.x = rotation_axis.x * sin (angle / 2.0); + rotation.y = rotation_axis.y * sin (angle / 2.0); + rotation.z = rotation_axis.z * sin (angle / 2.0); + rotation.w = cos (angle / 2.0); + + quaternion_transform (rotation, transformation); + + result = vector_transform (node1, transformation); + + return result; +} + +/**************************************************************************** + * + * Callback indicating a texture has loaded + */ +static void +image_loaded_cb (const char *filename, XRectangle *geometry, + int image_width, int image_height, + int texture_width, int texture_height, + void *closure) +{ + mirrorblobstruct *mp = (mirrorblobstruct *) closure; + GLint texid = -1; + int texture_index = -1; + int i; + + glGetIntegerv (GL_TEXTURE_BINDING_2D, &texid); + if (texid < 0) abort(); + + for (i = 0; i < NUM_TEXTURES; i++) { + if (mp->textures[i] == texid) { + texture_index = i; + break; + } + } + if (texture_index < 0) abort(); + + mp->tex_width [texture_index] = (GLfloat) image_width / texture_width; + mp->tex_height[texture_index] = -(GLfloat) image_height / texture_height; + + glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, + (mp->mipmap_p ? GL_LINEAR_MIPMAP_LINEAR : GL_LINEAR)); + glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); + glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); + glTexEnvf (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); + + mp->waiting_for_image_p = False; + mp->first_image_p = True; +} + +/* Load a new file into a texture + */ +static void +grab_texture(ModeInfo *mi, int texture_index) +{ + mirrorblobstruct *mp = &Mirrorblob[MI_SCREEN(mi)]; + + { + int w = (MI_WIDTH(mi) / 2) - 1; + int h = (MI_HEIGHT(mi) / 2) - 1; + if (w <= 10) w = 10; + if (h <= 10) h = 10; + + mp->waiting_for_image_p = True; + mp->mipmap_p = True; + load_texture_async (mi->xgwa.screen, mi->window, + *mp->glx_context, w, h, mp->mipmap_p, + mp->textures[texture_index], + image_loaded_cb, mp); + } +} + +/****************************************************************************** + * + * Generate internal parameters based on supplied options the parameters to + * ensure they are consistant. + */ +static void +set_parameters(void) +{ +# ifdef HAVE_JWZGLES /* #### glPolygonMode other than GL_FILL unimplemented */ + wireframe = 0; +# endif + + /* In wire frame mode do not draw a texture */ + if (wireframe) + { + do_texture = False; + blend = 1.0; + } + + /* Need to load textures if either the blob or the backgound has an image */ + if (do_texture || do_paint_background) + { + load_textures = True; + } + else + { + load_textures = False; + } + + /* If theres no texture don't calculate co-ordinates. */ + if (!do_texture) + { + offset_texture = False; + } + + culling = True; +} + +/****************************************************************************** + * + * Initialise the openGL state data. + */ +static void +initialize_gl(ModeInfo *mi, GLsizei width, GLsizei height) +{ + mirrorblobstruct *gp = &Mirrorblob[MI_SCREEN(mi)]; + + /* Lighting values */ + GLfloat ambientLight[] = { 0.2f, 0.2f, 0.2f, 1.0f }; + + GLfloat lightPos0[] = {500.0f, 100.0f, 200.0f, 1.0f }; + GLfloat whiteLight0[] = { 0.0f, 0.0f, 0.0f, 1.0f }; + GLfloat sourceLight0[] = { 0.6f, 0.6f, 0.6f, 1.0f }; + GLfloat specularLight0[] = { 0.8f, 0.8f, 0.9f, 1.0f }; + + GLfloat lightPos1[] = {-50.0f, -100.0f, 2500.0f, 1.0f }; + GLfloat whiteLight1[] = { 0.0f, 0.0f, 0.0f, 1.0f }; + GLfloat sourceLight1[] = { 0.6f, 0.6f, 0.6f, 1.0f }; + GLfloat specularLight1[] = { 0.7f, 0.7f, 0.7f, 1.0f }; + + GLfloat specref[] = { 1.0f, 1.0f, 1.0f, 1.0f }; + + GLfloat fogColor[4] = { 0.4, 0.4, 0.5, 0.1 }; + + /* Set the internal parameters based on the configuration settings */ + set_parameters(); + + /* Set the viewport to the width and heigh of the window */ + glViewport (0, 0, width, height ); + + if (do_antialias) + { + blend = 1.0; + glEnable(GL_LINE_SMOOTH); + glEnable(GL_POLYGON_SMOOTH); + } + + /* The blend function is used for trasitioning between two images even when + * blend is not selected. + */ + glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + + if (do_fog) + { + glEnable(GL_FOG); + glFogfv(GL_FOG_COLOR, fogColor); + glFogf(GL_FOG_DENSITY, 0.50); + glFogf(GL_FOG_START, 15.0); + glFogf(GL_FOG_END, 30.0); + } + + /* Set the shading model to smooth (Gouraud shading). */ + glShadeModel (GL_SMOOTH); + + glLightModelfv (GL_LIGHT_MODEL_AMBIENT, ambientLight); + glLightfv (GL_LIGHT0, GL_AMBIENT, whiteLight0); + glLightfv (GL_LIGHT0, GL_DIFFUSE, sourceLight0); + glLightfv (GL_LIGHT0, GL_SPECULAR, specularLight0); + glLightfv (GL_LIGHT0, GL_POSITION, lightPos0); + glEnable (GL_LIGHT0); + glLightfv (GL_LIGHT1, GL_AMBIENT, whiteLight1); + glLightfv (GL_LIGHT1, GL_DIFFUSE, sourceLight1); + glLightfv (GL_LIGHT1, GL_SPECULAR, specularLight1); + glLightfv (GL_LIGHT1, GL_POSITION, lightPos1); + glEnable (GL_LIGHT1); + glEnable (GL_LIGHTING); + + /* Enable color tracking */ + glEnable (GL_COLOR_MATERIAL); + + /* Set Material properties to follow glColor values */ + glColorMaterial (GL_FRONT, GL_AMBIENT_AND_DIFFUSE); + + /* Set all materials to have specular reflectivity */ + glMaterialfv (GL_FRONT, GL_SPECULAR, specref); + glMateriali (GL_FRONT, GL_SHININESS, 32); + + /* Let GL implementation scale normal vectors. */ + glEnable (GL_NORMALIZE); + + /* Enable Arrays */ + if (load_textures) + { + glLightModeli (GL_LIGHT_MODEL_COLOR_CONTROL, GL_SEPARATE_SPECULAR_COLOR); + glEnable (GL_TEXTURE_2D); + + gp->current_texture = 0; + glGenTextures(NUM_TEXTURES, gp->textures); + grab_texture(mi, gp->current_texture); + + glMatrixMode (GL_TEXTURE); + glRotated (180.0, 1.0, 0.0, 0.0); + glMatrixMode (GL_MODELVIEW); + } + + /* Clear the buffer since this is not done during a draw with motion blur */ + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); +} + +/****************************************************************************** + * + * Initialise the openGL state data. + */ +static void +set_blob_gl_state(GLfloat alpha) +{ + if (do_antialias) + { + glEnable(GL_LINE_SMOOTH); + glEnable(GL_POLYGON_SMOOTH); + } + + if (wireframe) + { + glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); + } + else + { + glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); + } + + /* The blend function is used for trasitioning between two images even when + * blend is not selected. + */ + glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + + /* Culling. */ + if (culling) + { + glCullFace (GL_BACK); + glEnable (GL_CULL_FACE); + glFrontFace (GL_CCW); + } + else + { + glDisable (GL_CULL_FACE); + } + + if (blend < 1.0) + { + glEnable (GL_BLEND); + glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + /* Set the default blob colour to off-white. */ + glColor4f (0.9, 0.9, 1.0, alpha); + } + else + { + glDisable(GL_BLEND); + glColor4f (0.9, 0.9, 1.0, 1.0); + } + + glEnable(GL_DEPTH_TEST); + glEnable(GL_LIGHTING); +} + +/****************************************************************************** + * + * Initialise the data required to draw the blob allocating the memory as + * necessary. + * + * Return 0 on success. + */ +static int +initialise_blob(mirrorblobstruct *gp, + int width, + int height, + int bump_array_size) +{ + /* Loop variables */ + int i, u, v, node, side, face, base, base2 = 0; + int nodes_on_edge = resolution; + Vector3D node1, node2, result; + + if (nodes_on_edge < 2) + return -1; + + gp->num_nodes = 2 * nodes_on_edge * nodes_on_edge - 4 * nodes_on_edge + 4; + gp->num_faces = 4 * (nodes_on_edge - 1) * (nodes_on_edge - 1); + + gp->nodes = (Node_Data *) malloc (gp->num_nodes * sizeof (Node_Data)); + if (!gp->nodes) + { + fprintf (stderr, "Couldn't allocate gp->nodes buffer\n"); + return -1; + } + + gp->faces = (Face_Data *) malloc (gp->num_faces * sizeof (Face_Data)); + if (!gp->faces) + { + fprintf (stderr, "Couldn't allocate faces data buffer\n"); + return -1; + } + + gp->bump_data = (Bump_Data *) malloc (bumps * sizeof (Bump_Data)); + if (!gp->bump_data) + { + fprintf(stderr, "Couldn't allocate bump data buffer\n"); + return -1; + } + + gp->bump_shape = (double *)malloc(bump_array_size * sizeof(double)); + if (!gp->bump_shape) + { + fprintf(stderr, "Couldn't allocate bump buffer\n"); + return -1; + } + + gp->wall_shape = (double *)malloc(bump_array_size * sizeof(double)); + if (!gp->wall_shape) + { + fprintf(stderr, "Couldn't allocate wall bump buffer\n"); + return -1; + } + + + gp->dots = (Vector3D *)malloc(gp->num_nodes * sizeof(Vector3D)); + if (!gp->dots) + { + fprintf(stderr, "Couldn't allocate nodes buffer\n"); + return -1; + } + + gp->normals = (Vector3D *)malloc(gp->num_nodes * sizeof(Vector3D)); + if (!gp->normals) + { + fprintf(stderr, "Couldn't allocate normals buffer\n"); + return -1; + } + + gp->colours = (Colour *)malloc(gp->num_nodes * sizeof(Colour)); + if (!gp->colours) + { + fprintf(stderr, "Couldn't allocate colours buffer\n"); + return -1; + } + + gp->tex_coords = (Vector2D *)malloc(gp->num_nodes * sizeof(Vector2D)); + if (!gp->tex_coords) + { + fprintf(stderr, "Couldn't allocate gp->tex_coords buffer\n"); + return -1; + } + + + /* Initialise bump data */ + for (i = 0; i < bumps; i++) + { + gp->bump_data[i].ax = 2.0 * (((double)random() / (double)RAND_MAX) - 0.5); + gp->bump_data[i].ay = 2.0 * (((double)random() / (double)RAND_MAX) - 0.5); + gp->bump_data[i].power = (5.0 / pow(bumps, 0.75)) * (((double)random() / (double)RAND_MAX) - 0.5); + gp->bump_data[i].size = 0.1 + 0.5 * (((double)random() / (double)RAND_MAX)); + + gp->bump_data[i].pos.x = 1.5 * sin(PI * gp->bump_data[i].ay) + * cos(PI * gp->bump_data[i].ax); + gp->bump_data[i].pos.y = 1.5 * cos(PI * gp->bump_data[i].ay); + gp->bump_data[i].pos.z = 1.5 * sin(PI * gp->bump_data[i].ay) + * sin(PI * gp->bump_data[i].ax); + + gp->bump_data[i].cx = 2.0 * (((double)random() / (double)RAND_MAX) - 0.5); + gp->bump_data[i].cy = 2.0 * (((double)random() / (double)RAND_MAX) - 0.5); + gp->bump_data[i].cpower = (5.0 / pow(bumps, 0.75)) * (((double)random() / (double)RAND_MAX) - 0.5); + gp->bump_data[i].csize = 0.35; /*0.1 + 0.25 * (((double)random() / (double)RAND_MAX));*/ + + gp->bump_data[i].vx = 0.0; + gp->bump_data[i].vy = 0.0; + gp->bump_data[i].vpower = 0.0; + gp->bump_data[i].vsize = 0.0; + + gp->bump_data[i].mx = 0.003 * ((double)random() / (double)RAND_MAX); + gp->bump_data[i].my = 0.003 * ((double)random() / (double)RAND_MAX); + gp->bump_data[i].mpower = 0.003 * ((double)random() / (double)RAND_MAX); + gp->bump_data[i].msize = 0.003 * ((double)random() / (double)RAND_MAX); + } + + /* Initialise lookup table of bump strength */ + for (i = 0; i < bump_array_size; i++) + { + double xd, xd2; + xd = i / (double)bump_array_size; + + xd2 = 48.0 * xd * xd; + gp->bump_shape[i] = 0.1 / (xd2 + 0.1); + + xd2 = 40.0 * xd * xd * xd * xd; + gp->wall_shape[i] = 0.4 / (xd2 + 0.1); + } + + node = 0; + face = 0; + for (side = 0; side < 4; side++) + { + base = node; + if (side == 2) + { + base2 = node; + } + /* + * The start and end of the for loops below are modified based on the + * side of the tetrahedron that is being calculated to avoid duplication + * of the gp->nodes that are on the edges of the tetrahedron. + */ + for (u = (side > 1); u < (nodes_on_edge - (side > 0)); u++) + { + node1 = partial (normalise (tetrahedron[side][0]), + normalise (tetrahedron[side][1]), + u / (double) (nodes_on_edge - 1)); + node2 = partial (normalise (tetrahedron[side][0]), + normalise (tetrahedron[side][2]), + u / (double) (nodes_on_edge - 1)); + + for (v = (side > 1); v <= (u - (side > 2)); v++) + { + if (u > 0) + result = partial (node1, node2, v / (double) u); + else + result = node1; + + gp->nodes[node].position = normalise (result); + gp->nodes[node].initial_position = gp->nodes[node].position; + gp->nodes[node].normal = zero_vector; + node++; + } + } + + /* + * Determine which nodes make up each face. The complexity is caused + * by having to determine the correct nodes for the edges of the + * tetrahedron since the common nodes on the edges are only calculated + * once (see above). + */ + for (u = 0; u < (nodes_on_edge - 1); u++) + { + for (v = 0; v <= u; v++) + { + { + if (side < 2) + { + gp->faces[face].node1 = base + ((u * (u + 1)) / 2) + v; + gp->faces[face].node2 = + base + ((u + 1) * (u + 2)) / 2 + v + 1; + gp->faces[face].node3 = + base + ((u + 1) * (u + 2)) / 2 + v; + + if ((side == 1) && (u == (nodes_on_edge - 2))) + { + gp->faces[face].node3 = + ((u + 1) * (u + 2)) / 2 + + nodes_on_edge - v - 1; + gp->faces[face].node2 = + ((u + 1) * (u + 2)) / 2 + + nodes_on_edge - v - 2; + } + } + else if (side < 3) + { + gp->faces[face].node1 = + base + (((u - 1) * u) / 2) + v - 1; + gp->faces[face].node2 = base + ((u) * (u + 1)) / 2 + v; + gp->faces[face].node3 = + base + ((u) * (u + 1)) / 2 + v - 1; + + if (u == (nodes_on_edge - 2)) + { + int n = nodes_on_edge - v - 1; + gp->faces[face].node2 = + ((nodes_on_edge * + (nodes_on_edge + 1)) / 2) + + ((n - 1) * (n + 0)) / 2; + gp->faces[face].node3 = + ((nodes_on_edge * + (nodes_on_edge + 1)) / 2) + + ((n + 0) * (n + 1)) / 2; + } + if (v == 0) + { + gp->faces[face].node1 = (((u + 1) * (u + 2)) / 2) - 1; + gp->faces[face].node3 = (((u + 2) * (u + 3)) / 2) - 1; + } + } + else + { + gp->faces[face].node1 = + base + (((u - 2) * (u - 1)) / 2) + v - 1; + gp->faces[face].node2 = base + ((u - 1) * u) / 2 + v; + gp->faces[face].node3 = base + ((u - 1) * u) / 2 + v - 1; + + if (v == 0) + { + gp->faces[face].node1 = + base2 + ((u * (u + 1)) / 2) - 1; + gp->faces[face].node3 = + base2 + ((u + 1) * (u + 2)) / 2 - 1; + } + if (u == (nodes_on_edge - 2)) + { + gp->faces[face].node3 = + ((nodes_on_edge * + (nodes_on_edge + 1)) / 2) + + ((v + 1) * (v + 2)) / 2 - 1; + gp->faces[face].node2 = + ((nodes_on_edge * + (nodes_on_edge + 1)) / 2) + + ((v + 2) * (v + 3)) / 2 - 1; + } + if (v == u) + { + gp->faces[face].node1 = (u * (u + 1)) / 2; + gp->faces[face].node2 = ((u + 1) * (u + 2)) / 2; + } + } + face++; + } + + if (v < u) + { + if (side < 2) + { + gp->faces[face].node1 = base + ((u * (u + 1)) / 2) + v; + gp->faces[face].node2 = + base + ((u * (u + 1)) / 2) + v + 1; + gp->faces[face].node3 = + base + (((u + 1) * (u + 2)) / 2) + v + 1; + + if ((side == 1) && (u == (nodes_on_edge - 2))) + { + gp->faces[face].node3 = + ((u + 1) * (u + 2)) / 2 + + nodes_on_edge - v - 2; + } + } + else if (side < 3) + { + gp->faces[face].node1 = + base + ((u * (u - 1)) / 2) + v - 1; + gp->faces[face].node2 = base + ((u * (u - 1)) / 2) + v; + gp->faces[face].node3 = base + ((u * (u + 1)) / 2) + v; + + if (u == (nodes_on_edge - 2)) + { + int n = nodes_on_edge - v - 1; + gp->faces[face].node3 = + ((nodes_on_edge * + (nodes_on_edge + 1)) / 2) + + ((n + 0) * (n - 1)) / 2; + } + if (v == 0) + { + gp->faces[face].node1 = (((u + 1) * (u + 2)) / 2) - 1; + } + } + else + { + gp->faces[face].node1 = + base + (((u - 2) * (u - 1)) / 2) + v - 1; + gp->faces[face].node2 = + base + (((u - 2) * (u - 1)) / 2) + v; + gp->faces[face].node3 = base + (((u - 1) * u) / 2) + v; + + if (v == 0) + { + gp->faces[face].node1 = base2 + (u * (u + 1)) / 2 - 1; + } + if (u == (nodes_on_edge - 2)) + { + gp->faces[face].node3 = + ((nodes_on_edge * (nodes_on_edge + 1)) / 2) + + ((v + 2) * (v + 3)) / 2 - 1; + } + if (v == (u - 1)) + { + gp->faces[face].node2 = (u * (u + 1)) / 2; + } + } + face++; + } + } + } + } + + return 0; +} + +/****************************************************************************** + * + * Return the magnitude of the given vector + */ +static inline double +length (Vector3D u) +{ + return sqrt (u.x * u.x + u.y * u.y + u.z * u.z); +} + +/****************************************************************************** + * + * Calculate the blob shape. + */ +static void +calc_blob(mirrorblobstruct *gp, + int width, + int height, + int bump_array_size, + float limit, + double fade) +{ + /* Loop variables */ + int i, index, face; + /* position of a node */ + Vector3D node; + Vector3D offset; + Vector3D bump_vector; + int dist; + + /* Update position and strength of bumps used to distort the blob */ + for (i = 0; i < bumps; i++) + { + gp->bump_data[i].vx += gp->bump_data[i].mx*(gp->bump_data[i].cx - gp->bump_data[i].ax); + gp->bump_data[i].vy += gp->bump_data[i].my*(gp->bump_data[i].cy - gp->bump_data[i].ay); + gp->bump_data[i].vpower += gp->bump_data[i].mpower + * (gp->bump_data[i].cpower - gp->bump_data[i].power); + gp->bump_data[i].vsize += gp->bump_data[i].msize + * (gp->bump_data[i].csize - gp->bump_data[i].size); + + gp->bump_data[i].ax += 0.1 * gp->bump_data[i].vx; + gp->bump_data[i].ay += 0.1 * gp->bump_data[i].vy; + gp->bump_data[i].power += 0.1 * gp->bump_data[i].vpower; + gp->bump_data[i].size += 0.1 * gp->bump_data[i].vsize; + + gp->bump_data[i].pos.x = 1.0 * sin(PI * gp->bump_data[i].ay) + * cos(PI * gp->bump_data[i].ax); + gp->bump_data[i].pos.y = 1.0 * cos(PI * gp->bump_data[i].ay); + gp->bump_data[i].pos.z = 1.0 * sin(PI * gp->bump_data[i].ay) + * sin(PI * gp->bump_data[i].ax); + } + + /* Update calculate new position for each vertex based on an offset from + * the initial position + */ + gp->blob_force = zero_vector; + for (index = 0; index < gp->num_nodes; ++index) + { + node = gp->nodes[index].initial_position; + gp->nodes[index].normal = node; + + offset = zero_vector; + for ( i = 0; i < bumps; i++) + { + bump_vector = subtract(gp->bump_data[i].pos, node); + + dist = bump_array_size * dot(bump_vector, bump_vector) * gp->bump_data[i].size; + + if (dist < bump_array_size) + { + add(&offset, scale(node, gp->bump_data[i].power * gp->bump_shape[dist])); + add(&gp->blob_force, scale(node, gp->bump_data[i].power * gp->bump_shape[dist])); + } + } + + add(&node, offset); + node = scale(node, zoom); + add(&node, gp->blob_center); + + if (do_walls) + { + if (node.z < -limit) node.z = -limit; + if (node.z > limit) node.z = limit; + + dist = bump_array_size * (node.z + limit) * (node.z + limit) * 0.5; + if (dist < bump_array_size) + { + node.x += (node.x - gp->blob_center.x) * gp->wall_shape[dist]; + node.y += (node.y - gp->blob_center.y) * gp->wall_shape[dist]; + gp->blob_force.z += (node.z + limit); + } + else + { + dist = bump_array_size * (node.z - limit) * (node.z - limit) * 0.5; + if (dist < bump_array_size) + { + node.x += (node.x - gp->blob_center.x) * gp->wall_shape[dist]; + node.y += (node.y - gp->blob_center.y) * gp->wall_shape[dist]; + gp->blob_force.z -= (node.z - limit); + } + + if (node.y < -limit) node.y = -limit; + if (node.y > limit) node.y = limit; + + dist = bump_array_size * (node.y + limit) * (node.y + limit) * 0.5; + if (dist < bump_array_size) + { + node.x += (node.x - gp->blob_center.x) * gp->wall_shape[dist]; + node.z += (node.z - gp->blob_center.z) * gp->wall_shape[dist]; + gp->blob_force.y += (node.y + limit); + } + else + { + dist = bump_array_size * (node.y - limit) * (node.y - limit) * 0.5; + if (dist < bump_array_size) + { + node.x += (node.x - gp->blob_center.x) * gp->wall_shape[dist]; + node.z += (node.z - gp->blob_center.z) * gp->wall_shape[dist]; + gp->blob_force.y -= (node.y - limit); + } + } + + if (node.x < -limit) node.x = -limit; + if (node.x > limit) node.x = limit; + + dist = bump_array_size * (node.x + limit) * (node.x + limit) * 0.5; + if (dist < bump_array_size) + { + node.y += (node.y - gp->blob_center.y) * gp->wall_shape[dist]; + node.z += (node.z - gp->blob_center.z) * gp->wall_shape[dist]; + gp->blob_force.x += (node.x + limit); + } + else + { + dist = bump_array_size * (node.x - limit) * (node.x - limit) * 0.5; + if (dist < bump_array_size) + { + node.y += (node.y - gp->blob_center.y) * gp->wall_shape[dist]; + node.z += (node.z - gp->blob_center.z) * gp->wall_shape[dist]; + gp->blob_force.x -= (node.x - limit); + } + } + + if (node.y < -limit) node.y = -limit; + if (node.y > limit) node.y = limit; + } + } + gp->dots[index] = node; + } + + /* Determine the normal for each face */ + for (face = 0; face < gp->num_faces; face++) + { + /* Use pointers to indexed nodes to help readability */ + int index1 = gp->faces[face].node1; + int index2 = gp->faces[face].node2; + int index3 = gp->faces[face].node3; + + gp->faces[face].normal = cross(subtract(gp->dots[index2], gp->dots[index1]), + subtract(gp->dots[index3], gp->dots[index1])); + + /* Add the normal for the face onto the normal for the verticies of + the face */ + add(&gp->nodes[index1].normal, gp->faces[face].normal); + add(&gp->nodes[index2].normal, gp->faces[face].normal); + add(&gp->nodes[index3].normal, gp->faces[face].normal); + } + + /* Use the normal to set the colour and texture */ + if (do_colour || do_texture) + { + for (index = 0; index < gp->num_nodes; ++index) + { + gp->normals[index] = normalise(gp->nodes[index].normal); + + if (do_colour) + { + gp->colours[index].red = (int)(255.0 * fabs(gp->normals[index].x)); + gp->colours[index].green = (int)(255.0 * fabs(gp->normals[index].y)); + gp->colours[index].blue = (int)(255.0 * fabs(gp->normals[index].z)); + gp->colours[index].alpha = (int)(255.0 * fade); + } + if (do_texture) + { + if (offset_texture) + { + const float cube_size = 100.0; + Vector3D eye = {0.0, 0.0, 50.0}; + Vector3D eye_r = normalise(subtract(gp->dots[index], eye)); + Vector3D reference = subtract(eye_r, scale(gp->normals[index], 2.0 * dot(eye_r, gp->normals[index]))); + double x = 0.0; + double y = 0.0; + double n, n_min = 10000.0, sign = 1.0; + if (fabs(reference.z) > 1e-9) + { + n = (cube_size - gp->dots[index].z) / reference.z; + if (n < 0.0) + { + n = (-cube_size - gp->dots[index].z) / reference.z; + sign = 3.0; + } + if (n > 0.0) + { + x = sign * (gp->dots[index].x + n * reference.x); + y = sign * (gp->dots[index].y + n * reference.y); + n_min = n; + } + } + if (fabs(reference.x) > 1e-9) + { + n = (cube_size - gp->dots[index].x) / reference.x; + sign = 1.0; + if (n < 0.0) + { + n = (-cube_size - gp->dots[index].x) / reference.x; + sign = -1.0; + } + if ((n > 0.0) && (n < n_min)) + { + x = sign * (2.0 * cube_size - (gp->dots[index].z + n * reference.z)); + y = sign * x * (gp->dots[index].y + n * reference.y) / cube_size; + n_min = n; + } + } + if (fabs(reference.y) > 1e-9) + { + n = (cube_size - gp->dots[index].y) / reference.y; + sign = 1.0; + if (n < 0.0) + { + n = (-cube_size - gp->dots[index].y) / reference.y; + sign = -1.0; + } + if ((n > 0.0) && (n < n_min)) + { + y = sign * (2.0 * cube_size -( gp->dots[index].z + n * reference.z)); + x = sign * y * (gp->dots[index].x + n * reference.x) / cube_size; + } + } + + gp->tex_coords[index].x = 0.5 + x / (cube_size * 6.0); + gp->tex_coords[index].y = 0.5 - y / (cube_size * 6.0); + } + else + { + gp->tex_coords[index].x = 0.5 + * (1.0 + asin(gp->normals[index].x) / (0.5 * PI)); + gp->tex_coords[index].y = -0.5 + * (1.0 + asin(gp->normals[index].y) / (0.5 * PI)); + } + /* Adjust the texture co-ordinates to from range 0..1 to + * 0..width or 0..height as appropriate + */ + gp->tex_coords[index].x *= gp->tex_width[gp->current_texture]; + gp->tex_coords[index].y *= gp->tex_height[gp->current_texture]; + } + } + } + + /* Update the center of the whole blob */ + add(&gp->blob_velocity, scale (subtract (gp->blob_anchor, gp->blob_center), 1.0 / 80.0)); + add(&gp->blob_velocity, scale (gp->blob_force, 0.01 / gp->num_nodes)); + + add(&gp->blob_center, scale(gp->blob_velocity, 0.5)); + + gp->blob_velocity = scale(gp->blob_velocity, 0.999); +} + +static void +draw_vertex(mirrorblobstruct *gp, int index) +{ + if (do_colour) + { + glColor3ub(gp->colours[index].red, + gp->colours[index].green, + gp->colours[index].blue); + } + if (load_textures) + { + glTexCoord2fv(&gp->tex_coords[index].x); + } + glNormal3fv(&gp->normals[index].x); + glVertex3fv(&gp->dots[index].x); +} + +/****************************************************************************** + * + * Draw the blob shape. + * + */ +static void +draw_blob (mirrorblobstruct *gp) +{ + int face; + + glMatrixMode(GL_MODELVIEW); + glLoadIdentity(); + glRotatef(current_device_rotation(), 0, 0, 1); + + /* Move down the z-axis. */ + glTranslatef (0.0, 0.0, -4.0); + + gltrackball_rotate (gp->trackball); + + /* glColor4ub (255, 0, 0, 128); */ + glBegin(GL_TRIANGLES); + for (face = 0; face < gp->num_faces; face++) + { + draw_vertex(gp, gp->faces[face].node1); + draw_vertex(gp, gp->faces[face].node2); + draw_vertex(gp, gp->faces[face].node3); + } + glEnd(); + +#if 0 + glBegin(GL_LINES); + for (face = 0; face < gp->num_faces; face++) + { + if (gp->normals[gp->faces[face].node1].z > 0.0) + { + Vector3D end = gp->dots[gp->faces[face].node1]; + glVertex3dv(&end); + add(&end, scale(gp->normals[gp->faces[face].node1], 0.25)); + glVertex3dv(&end); + } + } + glEnd(); +#endif + + glLoadIdentity(); +} + +/****************************************************************************** + * + * Draw the background image simply map a texture onto a full screen quad. + */ +static void +draw_background (ModeInfo *mi) +{ + mirrorblobstruct *gp = &Mirrorblob[MI_SCREEN(mi)]; + GLfloat rot = current_device_rotation(); + + glTexEnvf (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_DECAL); + glEnable (GL_TEXTURE_2D); + glDisable(GL_LIGHTING); + glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); + + /* Reset the projection matrix to make it easier to get the size of the quad + * correct + */ + glMatrixMode(GL_PROJECTION); + glPushMatrix(); + glLoadIdentity(); + + glRotatef (rot, 0, 0, 1); + if ((rot > 45 && rot < 135) || + (rot < -45 && rot > -135)) + { + GLfloat s = MI_WIDTH(mi) / (GLfloat) MI_HEIGHT(mi); + glScalef (s, 1/s, 1); + } + + glOrtho(0.0, MI_WIDTH(mi), MI_HEIGHT(mi), 0.0, -1000.0, 1000.0); + + glBegin (GL_QUADS); + + glTexCoord2f (0.0, 0.0); + glVertex2i (0, 0); + + glTexCoord2f (0.0, gp->tex_height[gp->current_texture]); + glVertex2i (0, MI_HEIGHT(mi)); + + glTexCoord2f (gp->tex_width[gp->current_texture], gp->tex_height[gp->current_texture]); + glVertex2i (MI_WIDTH(mi), MI_HEIGHT(mi)); + + glTexCoord2f (gp->tex_width[gp->current_texture], 0.0); + glVertex2i (MI_WIDTH(mi), 0); + glEnd(); + + glPopMatrix (); + glMatrixMode (GL_MODELVIEW); + glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); +} + +/****************************************************************************** + * + * Update the scene. + */ +static GLvoid +draw_scene(ModeInfo * mi) +{ + mirrorblobstruct *gp = &Mirrorblob[MI_SCREEN(mi)]; + + double fade = 0.0; + double current_time; + check_gl_error ("draw_scene"); + + mi->polygon_count = 0; + glColor4f (1.0, 1.0, 1.0, 1.0); + + current_time = double_time(); + switch (gp->state) + { + case INITIALISING: + glColor4f (0.0, 0.0, 0.0, 1.0); + fade = 1.0; + break; + + case TRANSITIONING: + fade = 1.0 - (current_time - gp->state_start_time) / fade_time; + break; + + case LOADING: /* FALL-THROUGH */ + case HOLDING: + fade = 1.0; + break; + } + + /* Set the correct texture, when transitioning this ensures that the first draw + * is the original texture (which has the new texture drawn over it with decreasing + * transparency) + */ + if (load_textures) + { + glBindTexture(GL_TEXTURE_2D, gp->textures[gp->current_texture]); + } + + glDisable (GL_DEPTH_TEST); + if (do_paint_background) + { + glEnable (GL_TEXTURE_2D); + if (motion_blur > 0.0) + { + glClear(GL_DEPTH_BUFFER_BIT); + glEnable (GL_BLEND); + glColor4f (1.0, 1.0, 1.0, motion_blur); + } + else + { + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + } + draw_background (mi); + mi->polygon_count++; + + /* When transitioning between two images paint the new image over the old + * image with a varying alpha value to get a smooth fade. + */ + if (gp->state == TRANSITIONING) + { + glEnable (GL_BLEND); + /* Select the texture to transition to */ + glBindTexture (GL_TEXTURE_2D, gp->textures[1 - gp->current_texture]); + glColor4f (1.0, 1.0, 1.0, 1.0 - fade); + + draw_background (mi); + mi->polygon_count++; + + /* Select the original texture to draw the blob */ + glBindTexture (GL_TEXTURE_2D, gp->textures[gp->current_texture]); + } + /* Clear the depth buffer bit so the backgound is behind the blob */ + glClear(GL_DEPTH_BUFFER_BIT); + } + else if (motion_blur > 0.0) + { + glEnable (GL_BLEND); + glColor4f (0.0, 0.0, 0.0, motion_blur); + glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); + glTranslatef (0.0, 0.0, -4.0); + glRectd (-10.0, -10.0, 10.0, 10.0); + if (wireframe) + { + glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); + } + glClear(GL_DEPTH_BUFFER_BIT); + } + else + { + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + } + + if (!do_texture) + { + fade = 1.0; + glDisable (GL_TEXTURE_2D); + } + + calc_blob(gp, MI_WIDTH(mi), MI_HEIGHT(mi), BUMP_ARRAY_SIZE, 2.5, fade * blend); + + set_blob_gl_state(fade * blend); + + if (blend < 1.0) + { + /* Disable the colour chanels so that only the depth buffer is updated */ + glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE); + draw_blob(gp); + mi->polygon_count += gp->num_faces; + glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); + } + + glDepthFunc(GL_LEQUAL); + draw_blob(gp); + mi->polygon_count += gp->num_faces; + + /* While transitioning between images draw a second blob with a modified + * alpha value. + */ + if (load_textures && (hold_time > 0)) + { + switch (gp->state) + { + case INITIALISING: + if (!gp->waiting_for_image_p) + { + gp->state = HOLDING; + } + break; + + case HOLDING: + if ((current_time - gp->state_start_time) > hold_time) + { + grab_texture(mi, 1 - gp->current_texture); + gp->state = LOADING; + } + break; + + case LOADING: + /* Once the image has loaded move to the TRANSITIONING STATE */ + if (!gp->waiting_for_image_p) + { + gp->state = TRANSITIONING; + /* Get the time again rather than using the current time so + * that the time taken by the grab_texture function is not part + * of the fade time + */ + gp->state_start_time = double_time(); + } + break; + + case TRANSITIONING: + + /* If the blob is textured draw over existing blob to fade between + * images + */ + if (do_texture) + { + /* Select the texture to transition to */ + glBindTexture (GL_TEXTURE_2D, gp->textures[1 - gp->current_texture]); + glEnable (GL_BLEND); + + /* If colour is enabled update the alpha data in the buffer and + * use that in the blending since the alpha of the incomming + * verticies will not be correct + */ + if (do_colour) + { + glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_TRUE); + glClearColor(0.0, 0.0, 0.0, (1.0 - fade) * blend); + glClear(GL_COLOR_BUFFER_BIT); + glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); + glBlendFunc(GL_DST_ALPHA, GL_ONE_MINUS_DST_ALPHA); + } + else + { + glColor4f (0.9, 0.9, 1.0, (1.0 - fade) * blend); + } + + draw_blob (gp); + mi->polygon_count += gp->num_faces; + + if (do_colour) + { + /* Restore the 'standard' blend functions. */ + glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + } + } + + if ((current_time - gp->state_start_time) > fade_time) + { + gp->state = HOLDING; + gp->state_start_time = current_time; + gp->current_texture = 1 - gp->current_texture; + } + break; + + } + } +} + +/****************************************************************************** + * + * XMirrorblob screen update entry + */ +ENTRYPOINT void +draw_mirrorblob(ModeInfo * mi) +{ + mirrorblobstruct *gp = &Mirrorblob[MI_SCREEN(mi)]; + Display *display = MI_DISPLAY(mi); + Window window = MI_WINDOW(mi); + + if (!gp->glx_context) + return; + + /* Wait for the first image; for subsequent images, load them in the + background while animating. */ + if (gp->waiting_for_image_p && gp->first_image_p) + return; + + glXMakeCurrent(display, window, *(gp->glx_context)); + draw_scene(mi); + if (mi->fps_p) do_fps (mi); + glFinish(); + glXSwapBuffers(display, window); +} + +/****************************************************************************** + * + * XMirrorblob screen resize entry + */ +ENTRYPOINT void +reshape_mirrorblob(ModeInfo *mi, int width, int height) +{ + glViewport( 0, 0, MI_WIDTH(mi), MI_HEIGHT(mi) ); + reset_projection(width, height); +} + +/**************************************************************************** + * + * Handle Mouse events + */ +ENTRYPOINT Bool +mirrorblob_handle_event (ModeInfo * mi, XEvent * event) +{ + mirrorblobstruct *gp = &Mirrorblob[MI_SCREEN (mi)]; + + if (event->xany.type == ButtonPress && + event->xbutton.button == Button1) + { + gp->button_down = 1; + gltrackball_start (gp->trackball, event->xbutton.x, + event->xbutton.y, MI_WIDTH (mi), MI_HEIGHT (mi)); + return True; + } + else if (event->xany.type == ButtonRelease && + event->xbutton.button == Button1) + { + gp->button_down = 0; + return True; + } + else if (event->xany.type == ButtonPress && + event->xbutton.button == Button4) + { + zoom *= 1.1; + return True; + } + else if (event->xany.type == ButtonPress && + event->xbutton.button == Button5) + { + + zoom *= 0.9; + return True; + } + else if (event->xany.type == MotionNotify && gp->button_down) + { + gltrackball_track (gp->trackball, event->xmotion.x, + event->xmotion.y, MI_WIDTH (mi), MI_HEIGHT (mi)); + return True; + } + return False; +} + +/****************************************************************************** + * + * XMirrorblob initialise entry + */ +ENTRYPOINT void +init_mirrorblob(ModeInfo * mi) +{ + int screen = MI_SCREEN(mi); + + mirrorblobstruct *gp; + + if (Mirrorblob == NULL) + { + if ((Mirrorblob = (mirrorblobstruct *) + calloc(MI_NUM_SCREENS(mi), sizeof (mirrorblobstruct))) == NULL) + { + return; + } + } + gp = &Mirrorblob[screen]; + + gp->window = MI_WINDOW(mi); + if ((gp->glx_context = init_GL(mi)) != NULL) + { + reshape_mirrorblob(mi, MI_WIDTH(mi), MI_HEIGHT(mi)); + initialize_gl(mi, MI_WIDTH(mi), MI_HEIGHT(mi)); + } + else + { + MI_CLEARWINDOW(mi); + } + gp->trackball = gltrackball_init(); + + initialise_blob(gp, MI_WIDTH(mi), MI_HEIGHT(mi), BUMP_ARRAY_SIZE); + gp->state = INITIALISING; + gp->state_start_time = double_time(); + + gp->first_image_p = True; +} + +/****************************************************************************** + * + * XMirrorblob cleanup entry + */ +ENTRYPOINT void +release_mirrorblob(ModeInfo * mi) +{ + if (Mirrorblob != NULL) { + int i; + for (i = 0; i < MI_NUM_SCREENS(mi); i++) { + mirrorblobstruct *gp = &Mirrorblob[i]; + if (gp->nodes) free(gp->nodes); + if (gp->faces) free(gp->faces); + if (gp->bump_data) free(gp->bump_data); + if (gp->colours) free(gp->colours); + if (gp->tex_coords) free(gp->tex_coords); + if (gp->dots) free(gp->dots); + if (gp->wall_shape) free(gp->wall_shape); + if (gp->bump_shape) free(gp->bump_shape); + } + + free(Mirrorblob); + Mirrorblob = NULL; + } + FreeAllGL(mi); +} + +XSCREENSAVER_MODULE ("MirrorBlob", mirrorblob) + +#endif diff --git a/hacks/glx/mirrorblob.man b/hacks/glx/mirrorblob.man new file mode 100644 index 00000000..c61f7a60 --- /dev/null +++ b/hacks/glx/mirrorblob.man @@ -0,0 +1,107 @@ +.TH XScreenSaver 1 "" "X Version 11" +.SH NAME +mirrorblob - Draws a wobbly blob that distorts the image behind it. +.SH SYNOPSIS +.B mirrorblob +[\-display \fIhost:display.screen\fP] +[\-visual \fIvisual\fP] +[\-window] +[\-root] +[\-wire] +[\-delay \fInumber\fP] +[\-fog] +[\-walls] +[\-colour] +[\-texture] +[\-offset-texture] +[\-blend] +[\-antialias] +[\-resolution \fInumber\fP] +[\-bumps \fInumber\fP] +[\-fade-time \fInumber\fP] +[\-hold-time \fInumber\fP] +[\-zoom \fInumber\fP] +[\-fps] +.SH DESCRIPTION +Draws a wobbling blob, making use of alpha blending, fog, +textures, and lighting, plus a ``frames per second'' meter so that you can +tell how fast your graphics card is... Requires OpenGL. +.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. +.B \-wire +Render in wireframe instead of solid. +.TP 8 +.B \-delay \fInumber\fP +Per-frame delay, in microseconds. Default: 10000 (0.01 seconds.). +.TP 8 +.B \-fog | \-no-fog +Whether to enable fog. +.TP 8 +.B \-walls | \-no-walls +Add walls for blob to hit. +.TP 8 +.B \-colour | \-no-colour +Draw coloured blob. If also textured, the texture will have color mixed in. +.TP 8 +.B \-texture | \-no-texture +Whether to wrap a texture image on the blob. +.TP 8 +.B \-offset_texture | \-no-offset_texture +Whether to ofset the texture calculations to only use a region of the image + under the blob. This works well with a semi-transparent blob. +.TP 8 +.B \-blend | \-no-blend +Whether to draw a transparent blob. (see also offset_texture above) +.TP 8 +.B \-antialias | \-no-antialias +Whether to antialias lines. +.TP 8 +.B \-resolution \fInumber\fP +Resolution of the tessellation used to calculate and draw the blob. Larger + numbers give a smoother blob but increase calculation times exponentially. +.TP 8 +.B \-bumps \fInumber\fP +Number of bumps used to distort the blob. +.TP 8 +.B \-hold-time \fInumber\fP +Time until loading a new image. +.TP 8 +.B \-fade-time \fInumber\fP +Time taken to transition between images. +.TP 8 +.B \-zoom \fInumber\fP +Size multiplier for blob. +.TP 8 +.B \-fps +Display the current frame rate, CPU load, and polygon count. +.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 2003 by Jon Dowdall. 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 +Jon Dowdall. diff --git a/hacks/glx/moebius.c b/hacks/glx/moebius.c new file mode 100644 index 00000000..b7b83f20 --- /dev/null +++ b/hacks/glx/moebius.c @@ -0,0 +1,816 @@ +/* -*- Mode: C; tab-width: 4 -*- */ +/* moebius --- Moebius Strip II, an Escher-like GL scene with ants. */ + +#if 0 +static const char sccsid[] = "@(#)moebius.c 5.01 2001/03/01 xlockmore"; +#endif + +/*- + * Permission to use, copy, modify, and distribute this software and its + * documentation for any purpose and without fee is hereby granted, + * provided that the above copyright notice appear in all copies and that + * both that copyright notice and this permission notice appear in + * supporting documentation. + * + * This file is provided AS IS with no warranties of any kind. The author + * shall have no liability with respect to the infringement of copyrights, + * trade secrets or any patents by this file or any part thereof. In no + * event will the author be liable for any lost revenue or profits or + * other special, indirect and consequential damages. + * + * The RotateAroundU() routine was adapted from the book + * "Computer Graphics Principles and Practice + * Foley - vanDam - Feiner - Hughes + * Second Edition" Pag. 227, exercise 5.15. + * + * This mode shows some interesting scenes that are impossible OR very + * wierd to build in the real universe. Much of the scenes are inspirated + * on Mauritz Cornelis Escher's works which derivated the mode's name. + * M.C. Escher (1898-1972) was a dutch artist and many people prefer to + * say he was a mathematician. + * + * Thanks goes to Brian Paul for making it possible and inexpensive to use + * OpenGL at home. + * + * Since I'm not a native English speaker, my apologies for any grammatical + * mistakes. + * + * My e-mail address is + * mfvianna@centroin.com.br + * + * Marcelo F. Vianna (Jun-01-1997) + * + * Revision History: + * 05-Apr-2002: Removed all gllist uses (fix some bug with nvidia driver) + * 01-Mar-2001: backported from xscreensaver by lassauge@mail.dotcom.fr + * Feb-2001: Made motion and rotation be smoother Jamie Zawinski + * + * 01-Nov-2000: Allocation checks + * 01-Jan-1998: Mode separated from escher and renamed + * 08-Jun-1997: New scene implemented: "Impossible Cage" based in a M.C. + * Escher's painting with the same name (quite similar). The + * first GL mode to use texture mapping. + * The "Impossible Cage" scene doesn't use DEPTH BUFFER, the + * wood planks are drawn consistently using GL_CULL_FACE, and + * the painter's algorithm is used to sort the planks. + * Marcelo F. Vianna. + * 07-Jun-1997: Speed ups in Moebius Strip using GL_CULL_FACE. + * Marcelo F. Vianna. + * 03-Jun-1997: Initial Release (Only one scene: "Moebius Strip") + * The Moebius Strip scene was inspirated in a M.C. Escher's + * painting named Moebius Strip II in wich ants walk across a + * Moebius Strip path, sometimes meeting each other and sometimes + * being in "opposite faces" (note that the moebius strip has + * only one face and one edge). + * Marcelo F. Vianna. + */ + +/*- + * Texture mapping is only available on RGBA contexts, Mono and color index + * visuals DO NOT support texture mapping in OpenGL. + * + * BUT Mesa do implements RGBA contexts in pseudo color visuals, so texture + * mapping shuld work on PseudoColor, DirectColor, TrueColor using Mesa. Mono + * is not officially supported for both OpenGL and Mesa, but seems to not crash + * Mesa. + * + * In real OpenGL, PseudoColor DO NOT support texture map (as far as I know). + */ + +#ifdef STANDALONE +# define MODE_moebius +# define refresh_moebius 0 +# define DEFAULTS "*delay: 20000 \n" \ + "*showFPS: False \n" + +# include "xlockmore.h" /* from the xscreensaver distribution */ +#else /* !STANDALONE */ +# include "xlock.h" /* from the xlockmore distribution */ +#endif /* !STANDALONE */ + +#ifdef HAVE_COCOA +# include "jwxyz.h" +#else +# include +# include +# include +#endif + +#ifdef HAVE_JWZGLES +# include "jwzgles.h" +#endif /* HAVE_JWZGLES */ + +#ifdef MODE_moebius + +#if 0 /* Hey, this never actually used the texture at all! */ +#if 0 +#include "e_textures.h" +#else +#include "xpm-ximage.h" +#include "../images/wood.xpm" +#endif +#endif /* 0 */ + +#include "sphere.h" +#include "tube.h" + +#include "rotator.h" +#include "gltrackball.h" + +#define DEF_SOLIDMOEBIUS "False" +#define DEF_DRAWANTS "True" + +static int solidmoebius; +static int drawants; + +static XrmOptionDescRec opts[] = +{ + {"-solidmoebius", ".moebius.solidmoebius", XrmoptionNoArg, "on"}, + {"+solidmoebius", ".moebius.solidmoebius", XrmoptionNoArg, "off"}, + {"-ants", ".moebius.drawants", XrmoptionNoArg, "on"}, + {"+ants", ".moebius.drawants", XrmoptionNoArg, "off"} +}; +static argtype vars[] = +{ + {&solidmoebius, "solidmoebius", "Solidmoebius", DEF_SOLIDMOEBIUS, t_Bool}, + {&drawants, "drawants", "Drawants", DEF_DRAWANTS, t_Bool} + +}; +static OptionStruct desc[] = +{ + {"-/+solidmoebius", "select between a SOLID or a NET Moebius Strip"}, + {"-/+drawants", "turn on/off walking ants"} +}; + +ENTRYPOINT ModeSpecOpt moebius_opts = +{sizeof opts / sizeof opts[0], opts, sizeof vars / sizeof vars[0], vars, desc}; + +#ifdef USE_MODULES +ModStruct moebius_description = +{"moebius", "init_moebius", "draw_moebius", "release_moebius", + "draw_moebius", "change_moebius", (char *) NULL, &moebius_opts, + 1000, 1, 1, 1, 4, 1.0, "", + "Shows Moebius Strip II, an Escher-like GL scene with ants", 0, NULL}; + +#endif + +#define Scale4Window 0.3 +#define Scale4Iconic 0.4 + +#define sqr(A) ((A)*(A)) + +#ifndef Pi +#define Pi M_PI +#endif + +#define ObjMoebiusStrip 0 +#define ObjAntBody 1 +#define MaxObj 2 + +/*************************************************************************/ + +typedef struct { + GLint WindH, WindW; + GLfloat step; + GLfloat ant_position; + float ant_step; + GLXContext *glx_context; + rotator *rot; + trackball_state *trackball; + Bool button_down_p; +} moebiusstruct; + +static const float front_shininess[] = {60.0}; +static const float front_specular[] = {0.7, 0.7, 0.7, 1.0}; +static const float ambient[] = {0.0, 0.0, 0.0, 1.0}; +static const float diffuse[] = {1.0, 1.0, 1.0, 1.0}; +static const float position0[] = {1.0, 1.0, 1.0, 0.0}; +static const float position1[] = {-1.0, -1.0, 1.0, 0.0}; +static const float lmodel_ambient[] = {0.5, 0.5, 0.5, 1.0}; +static const float lmodel_twoside[] = {GL_TRUE}; + +static const float MaterialRed[] = {0.7, 0.0, 0.0, 1.0}; +static const float MaterialGreen[] = {0.1, 0.5, 0.2, 1.0}; +static const float MaterialBlue[] = {0.0, 0.0, 0.7, 1.0}; +static const float MaterialCyan[] = {0.2, 0.5, 0.7, 1.0}; +static const float MaterialYellow[] = {0.7, 0.7, 0.0, 1.0}; +static const float MaterialMagenta[] = {0.6, 0.2, 0.5, 1.0}; +static const float MaterialWhite[] = {0.7, 0.7, 0.7, 1.0}; +static const float MaterialGray[] = {0.2, 0.2, 0.2, 1.0}; +static const float MaterialGray5[] = {0.5, 0.5, 0.5, 1.0}; +static const float MaterialGray6[] = {0.6, 0.6, 0.6, 1.0}; +static const float MaterialGray8[] = {0.8, 0.8, 0.8, 1.0}; + +static moebiusstruct *moebius = (moebiusstruct *) NULL; + +#define NUM_SCENES 2 + +static Bool +mySphere(float radius) +{ +#if 0 + GLUquadricObj *quadObj; + + if ((quadObj = gluNewQuadric()) == 0) + return False; + gluQuadricDrawStyle(quadObj, (GLenum) GLU_FILL); + gluSphere(quadObj, radius, 16, 16); + gluDeleteQuadric(quadObj); +#else + glPushMatrix(); + glScalef (radius, radius, radius); + unit_sphere (16, 16, False); + glPopMatrix(); +#endif + return True; +} + +static Bool +myCone(float radius) +{ +#if 0 + GLUquadricObj *quadObj; + + if ((quadObj = gluNewQuadric()) == 0) + return False; + gluQuadricDrawStyle(quadObj, (GLenum) GLU_FILL); + gluCylinder(quadObj, radius, 0, radius * 3, 8, 1); + gluDeleteQuadric(quadObj); +#else + cone (0, 0, 0, + 0, 0, radius * 3, + radius, 0, + 8, True, True, False); +#endif + return True; +} + +static Bool +draw_moebius_ant(moebiusstruct * mp, const float *Material, int mono) +{ + float cos1 = cos(mp->ant_step); + float cos2 = cos(mp->ant_step + 2 * Pi / 3); + float cos3 = cos(mp->ant_step + 4 * Pi / 3); + float sin1 = sin(mp->ant_step); + float sin2 = sin(mp->ant_step + 2 * Pi / 3); + float sin3 = sin(mp->ant_step + 4 * Pi / 3); + + if (mono) + glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, MaterialGray5); + else + glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, Material); + glEnable(GL_CULL_FACE); + glPushMatrix(); + glScalef(1, 1.3, 1); + if (!mySphere(0.18)) + return False; + glScalef(1, 1 / 1.3, 1); + glTranslatef(0.00, 0.30, 0.00); + if (!mySphere(0.2)) + return False; + + glTranslatef(-0.05, 0.17, 0.05); + glRotatef(-90, 1, 0, 0); + glRotatef(-25, 0, 1, 0); + if (!myCone(0.05)) + return False; + glTranslatef(0.00, 0.10, 0.00); + if (!myCone(0.05)) + return False; + glRotatef(25, 0, 1, 0); + glRotatef(90, 1, 0, 0); + + glScalef(1, 1.3, 1); + glTranslatef(0.15, -0.65, 0.05); + if (!mySphere(0.25)) + return False; + glScalef(1, 1 / 1.3, 1); + glPopMatrix(); + glDisable(GL_CULL_FACE); + + glDisable(GL_LIGHTING); + /* ANTENNAS */ + glBegin(GL_LINES); + if (mono) + glColor3fv(MaterialGray5); + else + glColor3fv(Material); + glVertex3f(0.00, 0.30, 0.00); + glColor3fv(MaterialGray); + glVertex3f(0.40, 0.70, 0.40); + if (mono) + glColor3fv(MaterialGray5); + else + glColor3fv(Material); + glVertex3f(0.00, 0.30, 0.00); + glColor3fv(MaterialGray); + glVertex3f(0.40, 0.70, -0.40); + glEnd(); + glBegin(GL_POINTS); + if (mono) + glColor3fv(MaterialGray6); + else + glColor3fv(MaterialRed); + glVertex3f(0.40, 0.70, 0.40); + glVertex3f(0.40, 0.70, -0.40); + glEnd(); + + /* LEFT-FRONT ARM */ + glBegin(GL_LINE_STRIP); + if (mono) + glColor3fv(MaterialGray5); + else + glColor3fv(Material); + glVertex3f(0.00, 0.05, 0.18); + glVertex3f(0.35 + 0.05 * cos1, 0.15, 0.25); + glColor3fv(MaterialGray); + glVertex3f(-0.20 + 0.05 * cos1, 0.25 + 0.1 * sin1, 0.45); + glEnd(); + + /* LEFT-CENTER ARM */ + glBegin(GL_LINE_STRIP); + if (mono) + glColor3fv(MaterialGray5); + else + glColor3fv(Material); + glVertex3f(0.00, 0.00, 0.18); + glVertex3f(0.35 + 0.05 * cos2, 0.00, 0.25); + glColor3fv(MaterialGray); + glVertex3f(-0.20 + 0.05 * cos2, 0.00 + 0.1 * sin2, 0.45); + glEnd(); + + /* LEFT-BACK ARM */ + glBegin(GL_LINE_STRIP); + if (mono) + glColor3fv(MaterialGray5); + else + glColor3fv(Material); + glVertex3f(0.00, -0.05, 0.18); + glVertex3f(0.35 + 0.05 * cos3, -0.15, 0.25); + glColor3fv(MaterialGray); + glVertex3f(-0.20 + 0.05 * cos3, -0.25 + 0.1 * sin3, 0.45); + glEnd(); + + /* RIGHT-FRONT ARM */ + glBegin(GL_LINE_STRIP); + if (mono) + glColor3fv(MaterialGray5); + else + glColor3fv(Material); + glVertex3f(0.00, 0.05, -0.18); + glVertex3f(0.35 - 0.05 * sin1, 0.15, -0.25); + glColor3fv(MaterialGray); + glVertex3f(-0.20 - 0.05 * sin1, 0.25 + 0.1 * cos1, -0.45); + glEnd(); + + /* RIGHT-CENTER ARM */ + glBegin(GL_LINE_STRIP); + if (mono) + glColor3fv(MaterialGray5); + else + glColor3fv(Material); + glVertex3f(0.00, 0.00, -0.18); + glVertex3f(0.35 - 0.05 * sin2, 0.00, -0.25); + glColor3fv(MaterialGray); + glVertex3f(-0.20 - 0.05 * sin2, 0.00 + 0.1 * cos2, -0.45); + glEnd(); + + /* RIGHT-BACK ARM */ + glBegin(GL_LINE_STRIP); + if (mono) + glColor3fv(MaterialGray5); + else + glColor3fv(Material); + glVertex3f(0.00, -0.05, -0.18); + glVertex3f(0.35 - 0.05 * sin3, -0.15, -0.25); + glColor3fv(MaterialGray); + glVertex3f(-0.20 - 0.05 * sin3, -0.25 + 0.1 * cos3, -0.45); + glEnd(); + + glBegin(GL_POINTS); + if (mono) + glColor3fv(MaterialGray8); + else + glColor3fv(MaterialMagenta); + glVertex3f(-0.20 + 0.05 * cos1, 0.25 + 0.1 * sin1, 0.45); + glVertex3f(-0.20 + 0.05 * cos2, 0.00 + 0.1 * sin2, 0.45); + glVertex3f(-0.20 + 0.05 * cos3, -0.25 + 0.1 * sin3, 0.45); + glVertex3f(-0.20 - 0.05 * sin1, 0.25 + 0.1 * cos1, -0.45); + glVertex3f(-0.20 - 0.05 * sin2, 0.00 + 0.1 * cos2, -0.45); + glVertex3f(-0.20 - 0.05 * sin3, -0.25 + 0.1 * cos3, -0.45); + glEnd(); + + glEnable(GL_LIGHTING); + + mp->ant_step += 0.3; + return True; +} + +static void +RotateAaroundU(float Ax, float Ay, float Az, + float Ux, float Uy, float Uz, + float *Cx, float *Cy, float *Cz, + float Theta) +{ + float cosO = cos(Theta); + float sinO = sin(Theta); + float one_cosO = 1 - cosO; + float Ux2 = sqr(Ux); + float Uy2 = sqr(Uy); + float Uz2 = sqr(Uz); + float UxUy = Ux * Uy; + float UxUz = Ux * Uz; + float UyUz = Uy * Uz; + + *Cx = (Ux2 + cosO * (1 - Ux2)) * Ax + (UxUy * one_cosO - Uz * sinO) * Ay + (UxUz * one_cosO + Uy * sinO) * Az; + *Cy = (UxUy * one_cosO + Uz * sinO) * Ax + (Uy2 + cosO * (1 - Uy2)) * Ay + (UyUz * one_cosO - Ux * sinO) * Az; + *Cz = (UxUz * one_cosO - Uy * sinO) * Ax + (UyUz * one_cosO + Ux * sinO) * Ay + (Uz2 + cosO * (1 - Uz2)) * Az; +} + +#define MoebiusDivisions 40 +#define MoebiusTransversals 4 +static Bool +draw_moebius_strip(ModeInfo * mi) +{ + GLfloat Phi, Theta; + GLfloat cPhi, sPhi; + moebiusstruct *mp = &moebius[MI_SCREEN(mi)]; + int i, j; + int mono = MI_IS_MONO(mi); + + float Cx, Cy, Cz; + +#ifdef HAVE_JWZGLES /* #### glPolygonMode other than GL_FILL unimplemented */ + solidmoebius = True; +#endif + + if (solidmoebius) { + glBegin(GL_QUAD_STRIP); + Phi = 0; + i = 0; + while (i < (MoebiusDivisions * 2 + 1)) { + Theta = Phi / 2; + cPhi = cos(Phi); + sPhi = sin(Phi); + + i++; + if (mono) + glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, MaterialWhite); + else if (i % 2) + glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, MaterialRed); + else + glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, MaterialGray); + + RotateAaroundU(cPhi, sPhi, 0, -sPhi, cPhi, 0, &Cx, &Cy, &Cz, Theta); + glNormal3f(Cx, Cy, Cz); + RotateAaroundU(0, 0, 1, -sPhi, cPhi, 0, &Cx, &Cy, &Cz, Theta); + glVertex3f(cPhi * 3 + Cx, sPhi * 3 + Cy, +Cz); + glVertex3f(cPhi * 3 - Cx, sPhi * 3 - Cy, -Cz); + + Phi += Pi / MoebiusDivisions; + } + glEnd(); + } else { + for (j = -MoebiusTransversals; j < MoebiusTransversals; j++) { + glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); + glBegin(GL_QUAD_STRIP); + Phi = 0; + i = 0; + while (i < (MoebiusDivisions * 2 + 1)) { + Theta = Phi / 2; + cPhi = cos(Phi); + sPhi = sin(Phi); + + RotateAaroundU(cPhi, sPhi, 0, -sPhi, cPhi, 0, &Cx, &Cy, &Cz, Theta); + glNormal3f(Cx, Cy, Cz); + RotateAaroundU(0, 0, 1, -sPhi, cPhi, 0, &Cx, &Cy, &Cz, Theta); + j++; + if (j == MoebiusTransversals || mono) + glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, MaterialWhite); + else if (i % 2) + glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, MaterialRed); + else + glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, MaterialGray); + glVertex3f(cPhi * 3 + Cx / MoebiusTransversals * j, sPhi * 3 + Cy / MoebiusTransversals * j, +Cz / MoebiusTransversals * j); + j--; + if (j == -MoebiusTransversals || mono) + glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, MaterialWhite); + else if (i % 2) + glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, MaterialRed); + else + glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, MaterialGray); + glVertex3f(cPhi * 3 + Cx / MoebiusTransversals * j, sPhi * 3 + Cy / MoebiusTransversals * j, +Cz / MoebiusTransversals * j); + + Phi += Pi / MoebiusDivisions; + i++; + } + glEnd(); + } + glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); + } + + if (drawants) { + /* DRAW BLUE ANT */ + glPushMatrix(); + glRotatef(mp->ant_position + 180, 0, 0, 1); + glTranslatef(3, 0, 0); + glRotatef(mp->ant_position / 2 + 90, 0, 1, 0); + glTranslatef(0.28, 0, -0.45); + if (!draw_moebius_ant(mp, MaterialYellow, mono)) + return False; + glPopMatrix(); + + /* DRAW YELLOW ANT */ + glPushMatrix(); + glRotatef(mp->ant_position, 0, 0, 1); + glTranslatef(3, 0, 0); + glRotatef(mp->ant_position / 2, 0, 1, 0); + glTranslatef(0.28, 0, -0.45); + if (!draw_moebius_ant(mp, MaterialBlue, mono)) + return False; + glPopMatrix(); + + /* DRAW GREEN ANT */ + glPushMatrix(); + glRotatef(-mp->ant_position, 0, 0, 1); + glTranslatef(3, 0, 0); + glRotatef(-mp->ant_position / 2, 0, 1, 0); + glTranslatef(0.28, 0, 0.45); + glRotatef(180, 1, 0, 0); + if (!draw_moebius_ant(mp, MaterialGreen, mono)) + return False; + glPopMatrix(); + + /* DRAW CYAN ANT */ + glPushMatrix(); + glRotatef(-mp->ant_position + 180, 0, 0, 1); + glTranslatef(3, 0, 0); + glRotatef(-mp->ant_position / 2 + 90, 0, 1, 0); + glTranslatef(0.28, 0, 0.45); + glRotatef(180, 1, 0, 0); + if (!draw_moebius_ant(mp, MaterialCyan, mono)) + return False; + glPopMatrix(); + } + mp->ant_position += 1; + return True; +} +#undef MoebiusDivisions +#undef MoebiusTransversals + +ENTRYPOINT void +reshape_moebius (ModeInfo * mi, int width, int height) +{ + moebiusstruct *mp = &moebius[MI_SCREEN(mi)]; + + glViewport(0, 0, mp->WindW = (GLint) width, mp->WindH = (GLint) height); + glMatrixMode(GL_PROJECTION); + glLoadIdentity(); + glFrustum(-1.0, 1.0, -1.0, 1.0, 5.0, 15.0); + glMatrixMode(GL_MODELVIEW); + if (width >= 1024) { + glLineWidth(3); + glPointSize(3); + } else if (width >= 512) { + glLineWidth(2); + glPointSize(2); + } else { + glLineWidth(1); + glPointSize(1); + } +} + +static void +pinit(ModeInfo *mi) +{ + /* int status; */ + glClearDepth(1.0); + glLightfv(GL_LIGHT0, GL_AMBIENT, ambient); + glLightfv(GL_LIGHT0, GL_DIFFUSE, diffuse); + glLightfv(GL_LIGHT0, GL_POSITION, position0); + glLightfv(GL_LIGHT1, GL_AMBIENT, ambient); + glLightfv(GL_LIGHT1, GL_DIFFUSE, diffuse); + glLightfv(GL_LIGHT1, GL_POSITION, position1); + glLightModelfv(GL_LIGHT_MODEL_AMBIENT, lmodel_ambient); + glLightModelfv(GL_LIGHT_MODEL_TWO_SIDE, lmodel_twoside); + glEnable(GL_LIGHTING); + glEnable(GL_LIGHT0); + glEnable(GL_LIGHT1); + glEnable(GL_NORMALIZE); + glFrontFace(GL_CCW); + glCullFace(GL_BACK); + + /* moebius */ + glShadeModel(GL_SMOOTH); + glEnable(GL_DEPTH_TEST); + glDisable(GL_CULL_FACE); + +#if 0 + glEnable(GL_TEXTURE_2D); + glPixelStorei(GL_UNPACK_ALIGNMENT, 1); + +#if 0 + clear_gl_error(); + status = gluBuild2DMipmaps(GL_TEXTURE_2D, 3, + WoodTextureWidth, WoodTextureHeight, + GL_RGB, GL_UNSIGNED_BYTE, WoodTextureData); + if (status) + { + const char *s = (char *) gluErrorString (status); + fprintf (stderr, "%s: error mipmapping %dx%d texture: %s\n", + progname, WoodTextureWidth, WoodTextureHeight, + (s ? s : "(unknown)")); + exit (1); + } + check_gl_error("mipmapping"); +#else + { + XImage *img = xpm_to_ximage (mi->dpy, + mi->xgwa.visual, + mi->xgwa.colormap, + wood_texture); + glTexImage2D (GL_TEXTURE_2D, 0, GL_RGBA, + img->width, img->height, 0, + GL_RGBA, + /* GL_UNSIGNED_BYTE, */ + GL_UNSIGNED_INT_8_8_8_8_REV, + img->data); + check_gl_error("texture"); + XDestroyImage (img); + } +#endif + + 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_NEAREST); + glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); +#endif + + glMaterialfv(GL_FRONT_AND_BACK, GL_SHININESS, front_shininess); + glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, front_specular); +} + + + +ENTRYPOINT void +release_moebius (ModeInfo * mi) +{ + if (moebius != NULL) { + (void) free((void *) moebius); + moebius = (moebiusstruct *) NULL; + } + FreeAllGL(mi); +} + +ENTRYPOINT Bool +moebius_handle_event (ModeInfo *mi, XEvent *event) +{ + moebiusstruct *mp = &moebius[MI_SCREEN(mi)]; + + if (event->xany.type == ButtonPress && + event->xbutton.button == Button1) + { + mp->button_down_p = True; + gltrackball_start (mp->trackball, + event->xbutton.x, event->xbutton.y, + MI_WIDTH (mi), MI_HEIGHT (mi)); + return True; + } + else if (event->xany.type == ButtonRelease && + event->xbutton.button == Button1) + { + mp->button_down_p = False; + return True; + } + else if (event->xany.type == ButtonPress && + (event->xbutton.button == Button4 || + event->xbutton.button == Button5 || + event->xbutton.button == Button6 || + event->xbutton.button == Button7)) + { + gltrackball_mousewheel (mp->trackball, event->xbutton.button, 10, + !!event->xbutton.state); + return True; + } + else if (event->xany.type == MotionNotify && + mp->button_down_p) + { + gltrackball_track (mp->trackball, + event->xmotion.x, event->xmotion.y, + MI_WIDTH (mi), MI_HEIGHT (mi)); + return True; + } + + return False; +} + + +ENTRYPOINT void +init_moebius (ModeInfo * mi) +{ + moebiusstruct *mp; + + if (moebius == NULL) { + if ((moebius = (moebiusstruct *) calloc(MI_NUM_SCREENS(mi), + sizeof (moebiusstruct))) == NULL) + return; + } + mp = &moebius[MI_SCREEN(mi)]; + mp->step = NRAND(90); + mp->ant_position = NRAND(90); + + { + double rot_speed = 0.3; + mp->rot = make_rotator (rot_speed, rot_speed, rot_speed, 1, 0, True); + mp->trackball = gltrackball_init (); + } + + if ((mp->glx_context = init_GL(mi)) != NULL) { + + reshape_moebius(mi, MI_WIDTH(mi), MI_HEIGHT(mi)); + glDrawBuffer(GL_BACK); + pinit(mi); + } else { + MI_CLEARWINDOW(mi); + } +} + +ENTRYPOINT void +draw_moebius (ModeInfo * mi) +{ + moebiusstruct *mp; + + Display *display = MI_DISPLAY(mi); + Window window = MI_WINDOW(mi); + + if (moebius == NULL) + return; + mp = &moebius[MI_SCREEN(mi)]; + + MI_IS_DRAWN(mi) = True; + + if (!mp->glx_context) + return; + + glXMakeCurrent(display, window, *(mp->glx_context)); + + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + + glPushMatrix(); + + glTranslatef(0.0, 0.0, -10.0); + + /* Do it twice because we don't track the device's orientation. */ + glRotatef( current_device_rotation(), 0, 0, 1); + gltrackball_rotate (mp->trackball); + glRotatef(-current_device_rotation(), 0, 0, 1); + + if (!MI_IS_ICONIC(mi)) { + glScalef(Scale4Window * mp->WindH / mp->WindW, Scale4Window, Scale4Window); + } else { + glScalef(Scale4Iconic * mp->WindH / mp->WindW, Scale4Iconic, Scale4Iconic); + } + + { + double x, y, z; + get_rotation (mp->rot, &x, &y, &z, !mp->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); + } + + /* moebius */ + if (!draw_moebius_strip(mi)) { + release_moebius(mi); + return; + } + + glPopMatrix(); + + if (MI_IS_FPS(mi)) do_fps (mi); + glFlush(); + + glXSwapBuffers(display, window); + + mp->step += 0.025; +} + +#ifndef STANDALONE +ENTRYPOINT void +change_moebius (ModeInfo * mi) +{ + moebiusstruct *mp = &moebius[MI_SCREEN(mi)]; + + if (!mp->glx_context) + return; + + glXMakeCurrent(MI_DISPLAY(mi), MI_WINDOW(mi), *(mp->glx_context)); + pinit(); +} +#endif /* !STANDALONE */ + + +XSCREENSAVER_MODULE ("Moebius", moebius) + +#endif diff --git a/hacks/glx/moebius.man b/hacks/glx/moebius.man new file mode 100644 index 00000000..696e0d69 --- /dev/null +++ b/hacks/glx/moebius.man @@ -0,0 +1,65 @@ +.TH XScreenSaver 1 "" "X Version 11" +.SH NAME +moebius - Escher's Moebuis Strip II, with ants. +.SH SYNOPSIS +.B moebius +[\-display \fIhost:display.screen\fP] +[\-visual \fIvisual\fP] +[\-window] +[\-root] +[-delay \fInumber\fP] +[-solidmoebius] +[-wireframe] +[-noants] +[-fps] +.SH DESCRIPTION +Another M. C. Escher hack by Marcelo Vianna, this one draws ``Moebius Strip +II,'' a GL image of ants walking along the surface of a moebius strip. +.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: 20000 (0.02 seconds.). +.TP 8 +.B \-solidmoebius +Solid Floor. +.TP 8 +.B \-wireframe +Render in wireframe instead of solid. +.TP 8 +.B \-noants | \-no-noants +Draw Ants. Boolean. +.TP 8 +.B \-fps +Display the current frame rate, CPU load, and polygon count. +.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 2002 by Marcelo Vianna. 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 +Marcelo Vianna. diff --git a/hacks/glx/moebiusgears.c b/hacks/glx/moebiusgears.c new file mode 100644 index 00000000..03381b70 --- /dev/null +++ b/hacks/glx/moebiusgears.c @@ -0,0 +1,414 @@ +/* moebiusgears, Copyright (c) 2007-2008 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. + */ + +#define DEFAULTS "*delay: 30000 \n" \ + "*count: 17 \n" \ + "*showFPS: False \n" \ + "*wireframe: False \n" \ + +# define refresh_mgears 0 +# define release_mgears 0 +#undef countof +#define countof(x) (sizeof((x))/sizeof((*x))) + +#include "xlockmore.h" +#include "involute.h" +#include "normals.h" +#include "rotator.h" +#include "gltrackball.h" +#include + +#ifdef USE_GL /* whole file */ + + +#define DEF_SPIN "True" +#define DEF_WANDER "True" +#define DEF_ROLL "True" +#define DEF_SPEED "1.0" +#define DEF_TEETH "15" + +typedef struct { + + gear g; + GLfloat pos_th; /* position on ring of gear system */ + GLfloat pos_thz; /* rotation out of plane of gear system */ +} mogear; + +typedef struct { + GLXContext *glx_context; + rotator *rot; + trackball_state *trackball; + Bool button_down_p; + + int ngears; + mogear *gears; + GLfloat ring_r; /* radius of gear system */ + GLfloat roll_th; + +} mgears_configuration; + +static mgears_configuration *bps = NULL; + +static Bool do_spin; +static GLfloat speed; +static Bool do_wander; +static Bool do_roll; +static int teeth_arg; + +static XrmOptionDescRec opts[] = { + { "-spin", ".spin", XrmoptionNoArg, "True" }, + { "+spin", ".spin", XrmoptionNoArg, "False" }, + { "-speed", ".speed", XrmoptionSepArg, 0 }, + { "-wander", ".wander", XrmoptionNoArg, "True" }, + { "+wander", ".wander", XrmoptionNoArg, "False" }, + { "-roll", ".roll", XrmoptionNoArg, "True" }, + { "+roll", ".roll", XrmoptionNoArg, "False" }, + { "-teeth", ".teeth", XrmoptionSepArg, 0 }, +}; + +static argtype vars[] = { + {&do_spin, "spin", "Spin", DEF_SPIN, t_Bool}, + {&do_wander, "wander", "Wander", DEF_WANDER, t_Bool}, + {&do_roll, "roll", "Roll", DEF_ROLL, t_Bool}, + {&speed, "speed", "Speed", DEF_SPEED, t_Float}, + {&teeth_arg, "teeth", "Teeth", DEF_TEETH, t_Int}, +}; + +ENTRYPOINT ModeSpecOpt mgears_opts = {countof(opts), opts, countof(vars), vars, NULL}; + + +/* Window management, etc + */ +ENTRYPOINT void +reshape_mgears (ModeInfo *mi, int width, int height) +{ + GLfloat h = (GLfloat) height / (GLfloat) width; + + glViewport (0, 0, (GLint) width, (GLint) height); + + glMatrixMode(GL_PROJECTION); + glLoadIdentity(); + gluPerspective (30.0, 1/h, 1.0, 100.0); + + glMatrixMode(GL_MODELVIEW); + glLoadIdentity(); + gluLookAt( 0.0, 0.0, 30.0, + 0.0, 0.0, 0.0, + 0.0, 1.0, 0.0); + + glClear(GL_COLOR_BUFFER_BIT); +} + + +ENTRYPOINT Bool +mgears_handle_event (ModeInfo *mi, XEvent *event) +{ + mgears_configuration *bp = &bps[MI_SCREEN(mi)]; + + if (event->xany.type == ButtonPress && + event->xbutton.button == Button1) + { + bp->button_down_p = True; + gltrackball_start (bp->trackball, + event->xbutton.x, event->xbutton.y, + MI_WIDTH (mi), MI_HEIGHT (mi)); + return True; + } + else if (event->xany.type == ButtonRelease && + event->xbutton.button == Button1) + { + bp->button_down_p = False; + return True; + } + else if (event->xany.type == ButtonPress && + (event->xbutton.button == Button4 || + event->xbutton.button == Button5 || + event->xbutton.button == Button6 || + event->xbutton.button == Button7)) + { + gltrackball_mousewheel (bp->trackball, event->xbutton.button, 10, + !!event->xbutton.state); + return True; + } + else if (event->xany.type == MotionNotify && + bp->button_down_p) + { + gltrackball_track (bp->trackball, + event->xmotion.x, event->xmotion.y, + MI_WIDTH (mi), MI_HEIGHT (mi)); + return True; + } + + return False; +} + + + +ENTRYPOINT void +init_mgears (ModeInfo *mi) +{ + mgears_configuration *bp; + int wire = MI_IS_WIREFRAME(mi); + int i; + + if (!bps) { + bps = (mgears_configuration *) + calloc (MI_NUM_SCREENS(mi), sizeof (mgears_configuration)); + if (!bps) { + fprintf(stderr, "%s: out of memory\n", progname); + exit(1); + } + } + + bp = &bps[MI_SCREEN(mi)]; + + bp->glx_context = init_GL(mi); + + reshape_mgears (mi, MI_WIDTH(mi), MI_HEIGHT(mi)); + + if (!wire) + { + GLfloat pos[4] = {1.0, 1.0, 1.0, 0.0}; + GLfloat amb[4] = {0.0, 0.0, 0.0, 1.0}; + GLfloat dif[4] = {1.0, 1.0, 1.0, 1.0}; + GLfloat spc[4] = {0.0, 1.0, 1.0, 1.0}; + + glEnable(GL_LIGHTING); + glEnable(GL_LIGHT0); + glEnable(GL_DEPTH_TEST); + glEnable(GL_CULL_FACE); + + glLightfv(GL_LIGHT0, GL_POSITION, pos); + glLightfv(GL_LIGHT0, GL_AMBIENT, amb); + glLightfv(GL_LIGHT0, GL_DIFFUSE, dif); + glLightfv(GL_LIGHT0, GL_SPECULAR, spc); + } + + { + double spin_speed = 0.5; + double wander_speed = 0.01; + double spin_accel = 2.0; + + bp->rot = make_rotator (do_spin ? spin_speed : 0, + do_spin ? spin_speed : 0, + do_spin ? spin_speed : 0, + spin_accel, + do_wander ? wander_speed : 0, + False /* don't randomize */ + ); + bp->trackball = gltrackball_init (); + } + + { + int total_gears = MI_COUNT(mi); + double gears_per_turn; + double gear_r, tw, th, thick, slope; + int nubs, size; + + if (! (total_gears & 1)) + total_gears++; /* must be odd or gears intersect */ + + /* Number of teeth must be odd if number of gears is odd, or teeth don't + mesh when the loop closes. And since number of gears must be odd... + */ + if (! (teeth_arg & 1)) teeth_arg++; + if (teeth_arg < 7) teeth_arg = 7; + + if (total_gears < 13) /* gear mesh angle is too steep with less */ + total_gears = 13; + + thick = 0.2; + nubs = (random() & 3) ? 0 : (random() % teeth_arg) / 2; + + slope = 0; + + /* Sloping gears are incompatible with "-roll" ... */ + /* slope= -M_PI * 2 / total_gears; */ + + gears_per_turn = total_gears / 2.0; + + bp->ring_r = 3; + gear_r = M_PI * bp->ring_r / gears_per_turn; + tw = 0; + th = gear_r * 2.5 / teeth_arg; + + /* If the gears are small, use a lower density mesh. */ + size = (gear_r > 0.32 ? INVOLUTE_LARGE : + gear_r > 0.13 ? INVOLUTE_MEDIUM : + INVOLUTE_SMALL); + + /* If there are lots of teeth, use a lower density mesh. */ + if (teeth_arg > 77) + size = INVOLUTE_SMALL; + if (teeth_arg > 45 && size == INVOLUTE_LARGE) + size = INVOLUTE_MEDIUM; + + bp->ngears = total_gears; + bp->gears = (mogear *) calloc (bp->ngears, sizeof(*bp->gears)); + for (i = 0; i < bp->ngears; i++) + { + mogear *mg = &bp->gears[i]; + gear *g = &mg->g; + + g->r = gear_r; + g->size = size; + g->nteeth = teeth_arg; + g->tooth_w = tw; + g->tooth_h = th; + g->tooth_slope = slope; + g->thickness = g->r * thick; + g->thickness2 = g->thickness * 0.1; + g->thickness3 = g->thickness; + g->inner_r = g->r * 0.80; + g->inner_r2 = g->r * 0.60; + g->inner_r3 = g->r * 0.55; + g->nubs = nubs; + mg->pos_th = (M_PI * 2 / gears_per_turn) * i; + mg->pos_thz = (M_PI / 2 / gears_per_turn) * i; + + g->th = ((i & 1) + ? (M_PI * 2 / g->nteeth) + : 0); + + /* Colorize + */ + g->color[0] = 0.7 + frand(0.3); + g->color[1] = 0.7 + frand(0.3); + g->color[2] = 0.7 + frand(0.3); + g->color[3] = 1.0; + + g->color2[0] = g->color[0] * 0.85; + g->color2[1] = g->color[1] * 0.85; + g->color2[2] = g->color[2] * 0.85; + g->color2[3] = g->color[3]; + + /* Now render the gear into its display list. + */ + g->dlist = glGenLists (1); + if (! g->dlist) + { + check_gl_error ("glGenLists"); + abort(); + } + + glNewList (g->dlist, GL_COMPILE); + g->polygons += draw_involute_gear (g, wire); + glEndList (); + } + } +} + + +ENTRYPOINT void +draw_mgears (ModeInfo *mi) +{ + mgears_configuration *bp = &bps[MI_SCREEN(mi)]; + Display *dpy = MI_DISPLAY(mi); + Window window = MI_WINDOW(mi); + int i; + + if (!bp->glx_context) + return; + + glXMakeCurrent(MI_DISPLAY(mi), MI_WINDOW(mi), *(bp->glx_context)); + + glShadeModel(GL_SMOOTH); + + glEnable(GL_DEPTH_TEST); + glEnable(GL_NORMALIZE); + glEnable(GL_CULL_FACE); + + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + + glPushMatrix (); + + glScalef(1.1, 1.1, 1.1); + + { + double x, y, z; + get_position (bp->rot, &x, &y, &z, !bp->button_down_p); + glTranslatef ((x - 0.5) * 4, + (y - 0.5) * 4, + (z - 0.5) * 7); + + /* Do it twice because we don't track the device's orientation. */ + glRotatef( current_device_rotation(), 0, 0, 1); + gltrackball_rotate (bp->trackball); + glRotatef(-current_device_rotation(), 0, 0, 1); + + get_rotation (bp->rot, &x, &y, &z, !bp->button_down_p); + + /* add a little rotation for -no-spin mode */ + x -= 0.14; + y -= 0.06; + + 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); + } + + mi->polygon_count = 0; + + glScalef (1.5, 1.5, 1.5); + +/*#define DEBUG*/ + +#ifdef DEBUG + glScalef (.5, .5, .5); + glTranslatef (0, -bp->gears[0].g.r * bp->ngears, 0); +#endif + + for (i = 0; i < bp->ngears; i++) + { + mogear *mg = &bp->gears[i]; + gear *g = &mg->g; + + glPushMatrix(); +#ifndef DEBUG + glRotatef (mg->pos_th * 180 / M_PI, 0, 0, 1); /* rotation on ring */ + glTranslatef (bp->ring_r, 0, 0); /* position on ring */ + glRotatef (mg->pos_thz * 180 / M_PI, 0, 1, 0); /* twist a bit */ + + if (do_roll) + { + glRotatef (bp->roll_th * 180 / M_PI, 0, 1, 0); + bp->roll_th += speed * 0.0005; + } +#else + glTranslatef (0, i * 2 * g->r, 0); +#endif + glRotatef (g->th * 180 / M_PI, 0, 0, 1); + + glCallList (g->dlist); + mi->polygon_count += g->polygons; + glPopMatrix (); + } + + glPopMatrix (); + +#ifndef DEBUG + /* spin gears */ + for (i = 0; i < bp->ngears; i++) + { + mogear *mg = &bp->gears[i]; + mg->g.th += speed * (M_PI / 100) * (i & 1 ? 1 : -1); + } +#endif + + if (mi->fps_p) do_fps (mi); + glFinish(); + + glXSwapBuffers(dpy, window); +} + +XSCREENSAVER_MODULE_2 ("MoebiusGears", moebiusgears, mgears) + +#endif /* USE_GL */ diff --git a/hacks/glx/moebiusgears.man b/hacks/glx/moebiusgears.man new file mode 100644 index 00000000..a45519a6 --- /dev/null +++ b/hacks/glx/moebiusgears.man @@ -0,0 +1,86 @@ +.TH XScreenSaver 1 "30-Oct-99" "X Version 11" +.SH NAME +moebiusgears - draw a moebius strip of interlocking gears. +.SH SYNOPSIS +.B moebiusgears +[\-display \fIhost:display.screen\fP] [\-window] [\-root] [\-install] +[\-visual \fIvisual\fP] +[\-delay \fIusecs\fP] +[\-speed \fIfloat\fP] +[\-no\-spin] +[\-no\-wander] +[\-no\-roll] +[-count \fIinteger\fP] +[-teeth \fIinteger\fP] +[-wireframe] +[-fps] +.SH DESCRIPTION +The \fImoebiusgears\fP program draws a closed, interlinked chain of +rotating gears. The layout of the gears follows the path of a +moebius strip. +.SH OPTIONS +.I moebiusgears +accepts the following options: +.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 \-install +Install a private colormap for the window. +.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 \-delay \fIusecs\fP +The delay between frames of the animation, in microseconds. +Default: 30000 (0.03 seconds.) +.TP 8 +.B \-speed \fIfloat\fP +Larger numbers mean run faster. Default: 1.0. +.TP 8 +.B \-no\-spin +Don't rotate the object. +.TP 8 +.B \-no\-wander +Don't wander the object around the screen. +.TP 8 +.B \-no\-roll +Don't slowly roll the moebius strip inside out. +.TP 8 +.B \-count \fIinteger\fP +How many gears to draw. Default: 17. Minimum 11, must be odd. +.TP 8 +.B \-teeth \fIinteger\fP +How many teeth to draw on each draw. Default: 15. Minimum 7, must be odd. +.TP 8 +.B \-wireframe +Render in wireframe instead of solid. +.TP 8 +.B \-fps +Display the current frame rate, CPU load, and polygon count. +.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 2007 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/glx/molecule.c b/hacks/glx/molecule.c new file mode 100644 index 00000000..3720294c --- /dev/null +++ b/hacks/glx/molecule.c @@ -0,0 +1,1735 @@ +/* molecule, Copyright (c) 2001-2012 Jamie Zawinski + * Draws molecules, based on coordinates from PDB (Protein Data Base) files. + * + * 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. + */ + + +/* Documentation on the PDB file format: + http://en.wikipedia.org/wiki/Protein_Data_Bank_%28file_format%29 + http://www.wwpdb.org/docs.html + http://www.wwpdb.org/documentation/format32/v3.2.html + http://www.wwpdb.org/documentation/format32/sect9.html + http://www.rcsb.org/pdb/file_formats/pdb/pdbguide2.2/guide2.2_frame.html + + Good source of PDB files: + http://www.sci.ouc.bc.ca/chem/molecule/molecule.html + http://www.umass.edu/microbio/rasmol/whereget.htm + http://www.wwpdb.org/docs.html + */ + +#ifdef HAVE_GLBITMAP +# define ATOM_FONT "-*-helvetica-medium-r-normal-*-180-*" +#else +# define ATOM_FONT "-*-helvetica-medium-r-normal-*-240-*" +#endif + +#define DEFAULTS "*delay: 10000 \n" \ + "*showFPS: False \n" \ + "*wireframe: False \n" \ + "*atomFont: " ATOM_FONT "\n" \ + "*atomFont2: -*-helvetica-bold-r-normal-*-80-*\n" \ + "*titleFont: -*-helvetica-medium-r-normal-*-180-*\n" \ + "*noLabelThreshold: 30 \n" \ + "*wireframeThreshold: 150 \n" \ + +# define refresh_molecule 0 +# define release_molecule 0 +#undef countof +#define countof(x) (sizeof((x))/sizeof((*x))) + +#include "xlockmore.h" +#include "colors.h" +#include "sphere.h" +#include "tube.h" +#include "glxfonts.h" +#include "rotator.h" +#include "gltrackball.h" + +#ifdef USE_GL /* whole file */ + +#include +#include +#include +#include + +#define DEF_TIMEOUT "20" +#define DEF_SPIN "XYZ" +#define DEF_WANDER "False" +#define DEF_LABELS "True" +#define DEF_TITLES "True" +#define DEF_ATOMS "True" +#define DEF_BONDS "True" +#define DEF_ESHELLS "True" +#define DEF_BBOX "False" +#define DEF_SHELL_ALPHA "0.3" +#define DEF_MOLECULE "(default)" +#define DEF_VERBOSE "False" + +#define SPHERE_SLICES 48 /* how densely to render spheres */ +#define SPHERE_STACKS 24 + +#define SMOOTH_TUBE /* whether to have smooth or faceted tubes */ + +#ifdef SMOOTH_TUBE +# define TUBE_FACES 12 /* how densely to render tubes */ +#else +# define TUBE_FACES 8 +#endif + +#define SPHERE_SLICES_2 14 +#define SPHERE_STACKS_2 8 +#define TUBE_FACES_2 6 + + +# ifdef __GNUC__ + __extension__ /* don't warn about "string length is greater than the length + ISO C89 compilers are required to support" when includng + the following data file... */ +# endif +static const char * const builtin_pdb_data[] = { +# include "molecules.h" +}; + + +#ifndef USE_IPHONE +# define LOAD_FILES +#endif + + +typedef struct { + const char *name; + GLfloat size, size2; + const char *color; + const char *text_color; + GLfloat gl_color[8]; +} atom_data; + + +/* These are the traditional colors used to render these atoms, + and their approximate size in angstroms. + */ +static const atom_data all_atom_data[] = { + { "H", 1.17, 0.40, "#FFFFFF", "#000000", { 0, }}, + { "C", 1.75, 0.58, "#999999", "#FFFFFF", { 0, }}, + { "CA", 1.80, 0.60, "#0000FF", "#ADD8E6", { 0, }}, + { "N", 1.55, 0.52, "#A2B5CD", "#EE99FF", { 0, }}, + { "O", 1.40, 0.47, "#FF0000", "#FFB6C1", { 0, }}, + { "P", 1.28, 0.43, "#9370DB", "#DB7093", { 0, }}, + { "S", 1.80, 0.60, "#8B8B00", "#FFFF00", { 0, }}, + { "bond", 0, 0, "#B3B3B3", "#FFFF00", { 0, }}, + { "*", 1.40, 0.47, "#008B00", "#90EE90", { 0, }} +}; + + +typedef struct { + int id; /* sequence number in the PDB file */ + const char *label; /* The atom name */ + GLfloat x, y, z; /* position in 3-space (angstroms) */ + const atom_data *data; /* computed: which style of atom this is */ +} molecule_atom; + +typedef struct { + int from, to; /* atom sequence numbers */ + int strength; /* how many bonds are between these two atoms */ +} molecule_bond; + + +typedef struct { + const char *label; /* description of this compound */ + int natoms, atoms_size; + int nbonds, bonds_size; + molecule_atom *atoms; + molecule_bond *bonds; +} molecule; + + +typedef struct { + GLXContext *glx_context; + rotator *rot; + trackball_state *trackball; + Bool button_down_p; + + GLfloat molecule_size; /* max dimension of molecule bounding box */ + + GLfloat no_label_threshold; /* Things happen when molecules are huge */ + GLfloat wireframe_threshold; + + int which; /* which of the molecules is being shown */ + int nmolecules; + molecule *molecules; + + int mode; /* 0 = normal, 1 = out, 2 = in */ + int mode_tick; + + GLuint molecule_dlist; + GLuint shell_dlist; + +# ifdef HAVE_GLBITMAP + XFontStruct *xfont1, *xfont2, *xfont3; + GLuint font1_dlist, font2_dlist, font3_dlist; +# else + texture_font_data *font1_data, *font2_data, *font3_data; +# endif + + + int polygon_count; + + time_t draw_time; + int draw_tick; + + int scale_down; + +} molecule_configuration; + + +static molecule_configuration *mcs = NULL; + +static int timeout; +static char *molecule_str; +static char *do_spin; +static Bool do_wander; +static Bool do_titles; +static Bool do_labels; +static Bool do_atoms; +static Bool do_bonds; +static Bool do_shells; +static Bool do_bbox; +static Bool verbose_p; +static GLfloat shell_alpha; + +/* saved to reset */ +static Bool orig_do_labels, orig_do_atoms, orig_do_bonds, orig_do_shells, + orig_wire; + + +static XrmOptionDescRec opts[] = { + { "-molecule", ".molecule", XrmoptionSepArg, 0 }, + { "-timeout", ".timeout", XrmoptionSepArg, 0 }, + { "-spin", ".spin", XrmoptionSepArg, 0 }, + { "+spin", ".spin", XrmoptionNoArg, "" }, + { "-wander", ".wander", XrmoptionNoArg, "True" }, + { "+wander", ".wander", XrmoptionNoArg, "False" }, + { "-labels", ".labels", XrmoptionNoArg, "True" }, + { "+labels", ".labels", XrmoptionNoArg, "False" }, + { "-titles", ".titles", XrmoptionNoArg, "True" }, + { "+titles", ".titles", XrmoptionNoArg, "False" }, + { "-atoms", ".atoms", XrmoptionNoArg, "True" }, + { "+atoms", ".atoms", XrmoptionNoArg, "False" }, + { "-bonds", ".bonds", XrmoptionNoArg, "True" }, + { "+bonds", ".bonds", XrmoptionNoArg, "False" }, + { "-shells", ".eshells", XrmoptionNoArg, "True" }, + { "+shells", ".eshells", XrmoptionNoArg, "False" }, + { "-shell-alpha", ".shellAlpha", XrmoptionSepArg, 0 }, + { "-bbox", ".bbox", XrmoptionNoArg, "True" }, + { "+bbox", ".bbox", XrmoptionNoArg, "False" }, + { "-verbose", ".verbose", XrmoptionNoArg, "True" }, +}; + +static argtype vars[] = { + {&molecule_str, "molecule", "Molecule", DEF_MOLECULE, t_String}, + {&timeout, "timeout", "Seconds", DEF_TIMEOUT, t_Int}, + {&do_spin, "spin", "Spin", DEF_SPIN, t_String}, + {&do_wander, "wander", "Wander", DEF_WANDER, t_Bool}, + {&do_atoms, "atoms", "Atoms", DEF_ATOMS, t_Bool}, + {&do_bonds, "bonds", "Bonds", DEF_BONDS, t_Bool}, + {&do_shells, "eshells", "EShells", DEF_ESHELLS, t_Bool}, + {&do_labels, "labels", "Labels", DEF_LABELS, t_Bool}, + {&do_titles, "titles", "Titles", DEF_TITLES, t_Bool}, + {&do_bbox, "bbox", "BBox", DEF_BBOX, t_Bool}, + {&shell_alpha, "shellAlpha", "ShellAlpha", DEF_SHELL_ALPHA, t_Float}, + {&verbose_p, "verbose", "Verbose", DEF_VERBOSE, t_Bool}, +}; + +ENTRYPOINT ModeSpecOpt molecule_opts = {countof(opts), opts, countof(vars), vars, NULL}; + + + + +/* shapes */ + +static int +sphere (molecule_configuration *mc, + GLfloat x, GLfloat y, GLfloat z, GLfloat diameter, Bool wire) +{ + int stacks = (mc->scale_down ? SPHERE_STACKS_2 : SPHERE_STACKS); + int slices = (mc->scale_down ? SPHERE_SLICES_2 : SPHERE_SLICES); + + glPushMatrix (); + glTranslatef (x, y, z); + glScalef (diameter, diameter, diameter); + unit_sphere (stacks, slices, wire); + glPopMatrix (); + + return stacks * slices; +} + + +static void +load_fonts (ModeInfo *mi) +{ + molecule_configuration *mc = &mcs[MI_SCREEN(mi)]; +# ifdef HAVE_GLBITMAP + load_font (mi->dpy, "atomFont", &mc->xfont1, &mc->font1_dlist); + load_font (mi->dpy, "atomFont2", &mc->xfont2, &mc->font2_dlist); + load_font (mi->dpy, "titleFont", &mc->xfont3, &mc->font3_dlist); +# else + mc->font1_data = load_texture_font (mi->dpy, "atomFont"); + mc->font2_data = load_texture_font (mi->dpy, "atomFont2"); + mc->font3_data = load_texture_font (mi->dpy, "titleFont"); +# endif +} + + +static const atom_data * +get_atom_data (const char *atom_name) +{ + int i; + const atom_data *d = 0; + char *n = strdup (atom_name); + char *n2 = n; + int L; + + while (!isalpha(*n)) n++; + L = strlen(n); + while (L > 0 && !isalpha(n[L-1])) + n[--L] = 0; + + for (i = 0; i < countof(all_atom_data); i++) + { + d = &all_atom_data[i]; + if (!strcasecmp (n, all_atom_data[i].name)) + break; + } + + free (n2); + return d; +} + + +static void +set_atom_color (ModeInfo *mi, const molecule_atom *a, + Bool font_p, GLfloat alpha) +{ + const atom_data *d; + GLfloat gl_color[4]; + + if (a) + d = a->data; + else + d = get_atom_data ("bond"); + + if (font_p) + { + gl_color[0] = d->gl_color[4]; + gl_color[1] = d->gl_color[5]; + gl_color[2] = d->gl_color[6]; + gl_color[3] = d->gl_color[7]; + } + else + { + gl_color[0] = d->gl_color[0]; + gl_color[1] = d->gl_color[1]; + gl_color[2] = d->gl_color[2]; + gl_color[3] = d->gl_color[3]; + } + + if (gl_color[3] == 0) + { + const char *string = !font_p ? d->color : d->text_color; + XColor xcolor; + if (!XParseColor (mi->dpy, mi->xgwa.colormap, string, &xcolor)) + { + fprintf (stderr, "%s: unparsable color in %s: %s\n", progname, + (a ? a->label : d->name), string); + exit (1); + } + + gl_color[0] = xcolor.red / 65536.0; + gl_color[1] = xcolor.green / 65536.0; + gl_color[2] = xcolor.blue / 65536.0; + } + + gl_color[3] = alpha; + + /* If we're not drawing atoms, and the color is black, use white instead. + This is a kludge so that H can have black text over its white ball, + but the text still shows up if balls are off. + */ + if (font_p && !do_atoms && + gl_color[0] == 0 && gl_color[1] == 0 && gl_color[2] == 0) + { + gl_color[0] = gl_color[1] = gl_color[2] = 1; + } + + if (font_p) + glColor4f (gl_color[0], gl_color[1], gl_color[2], gl_color[3]); + else + glMaterialfv (GL_FRONT, GL_AMBIENT_AND_DIFFUSE, gl_color); +} + + +static GLfloat +atom_size (const molecule_atom *a) +{ + if (do_bonds) + return a->data->size2; + else + return a->data->size; +} + + +static molecule_atom * +get_atom (molecule_atom *atoms, int natoms, int id) +{ + int i; + + /* quick short-circuit */ + if (id < natoms) + { + if (atoms[id].id == id) + return &atoms[id]; + if (id > 0 && atoms[id-1].id == id) + return &atoms[id-1]; + if (id < natoms-1 && atoms[id+1].id == id) + return &atoms[id+1]; + } + + for (i = 0; i < natoms; i++) + if (id == atoms[i].id) + return &atoms[i]; + + fprintf (stderr, "%s: no atom %d\n", progname, id); + abort(); +} + + +static void +molecule_bounding_box (ModeInfo *mi, + GLfloat *x1, GLfloat *y1, GLfloat *z1, + GLfloat *x2, GLfloat *y2, GLfloat *z2) +{ + molecule_configuration *mc = &mcs[MI_SCREEN(mi)]; + molecule *m = &mc->molecules[mc->which]; + int i; + + if (m->natoms == 0) + { + *x1 = *y1 = *z1 = *x2 = *y2 = *z2 = 0; + } + else + { + *x1 = *x2 = m->atoms[0].x; + *y1 = *y2 = m->atoms[0].y; + *z1 = *z2 = m->atoms[0].z; + } + + for (i = 1; i < m->natoms; i++) + { + if (m->atoms[i].x < *x1) *x1 = m->atoms[i].x; + if (m->atoms[i].y < *y1) *y1 = m->atoms[i].y; + if (m->atoms[i].z < *z1) *z1 = m->atoms[i].z; + + if (m->atoms[i].x > *x2) *x2 = m->atoms[i].x; + if (m->atoms[i].y > *y2) *y2 = m->atoms[i].y; + if (m->atoms[i].z > *z2) *z2 = m->atoms[i].z; + } + + *x1 -= 1.5; + *y1 -= 1.5; + *z1 -= 1.5; + *x2 += 1.5; + *y2 += 1.5; + *z2 += 1.5; +} + + +static void +draw_bounding_box (ModeInfo *mi) +{ + static const GLfloat c1[4] = { 0.2, 0.2, 0.4, 1.0 }; + static const GLfloat c2[4] = { 1.0, 0.0, 0.0, 1.0 }; + int wire = MI_IS_WIREFRAME(mi); + GLfloat x1, y1, z1, x2, y2, z2; + molecule_bounding_box (mi, &x1, &y1, &z1, &x2, &y2, &z2); + + glMaterialfv (GL_FRONT, GL_AMBIENT_AND_DIFFUSE, c1); + glFrontFace(GL_CCW); + + glBegin(wire ? GL_LINE_LOOP : GL_QUADS); + glNormal3f(0, 1, 0); + glVertex3f(x1, y1, z1); glVertex3f(x1, y1, z2); + glVertex3f(x2, y1, z2); glVertex3f(x2, y1, z1); + glEnd(); + glBegin(wire ? GL_LINE_LOOP : GL_QUADS); + glNormal3f(0, -1, 0); + glVertex3f(x2, y2, z1); glVertex3f(x2, y2, z2); + glVertex3f(x1, y2, z2); glVertex3f(x1, y2, z1); + glEnd(); + glBegin(wire ? GL_LINE_LOOP : GL_QUADS); + glNormal3f(0, 0, 1); + glVertex3f(x1, y1, z1); glVertex3f(x2, y1, z1); + glVertex3f(x2, y2, z1); glVertex3f(x1, y2, z1); + glEnd(); + glBegin(wire ? GL_LINE_LOOP : GL_QUADS); + glNormal3f(0, 0, -1); + glVertex3f(x1, y2, z2); glVertex3f(x2, y2, z2); + glVertex3f(x2, y1, z2); glVertex3f(x1, y1, z2); + glEnd(); + glBegin(wire ? GL_LINE_LOOP : GL_QUADS); + glNormal3f(1, 0, 0); + glVertex3f(x1, y2, z1); glVertex3f(x1, y2, z2); + glVertex3f(x1, y1, z2); glVertex3f(x1, y1, z1); + glEnd(); + glBegin(wire ? GL_LINE_LOOP : GL_QUADS); + glNormal3f(-1, 0, 0); + glVertex3f(x2, y1, z1); glVertex3f(x2, y1, z2); + glVertex3f(x2, y2, z2); glVertex3f(x2, y2, z1); + glEnd(); + + glDisable (GL_LIGHTING); + + glColor3f (c2[0], c2[1], c2[2]); + glBegin(GL_LINES); + if (x1 > 0) x1 = 0; if (x2 < 0) x2 = 0; + if (y1 > 0) y1 = 0; if (y2 < 0) y2 = 0; + if (z1 > 0) z1 = 0; if (z2 < 0) z2 = 0; + glVertex3f(x1, 0, 0); glVertex3f(x2, 0, 0); + glVertex3f(0 , y1, 0); glVertex3f(0, y2, 0); + glVertex3f(0, 0, z1); glVertex3f(0, 0, z2); + glEnd(); + + if (!wire) + glEnable (GL_LIGHTING); +} + + +/* Since PDB files don't always have the molecule centered around the + origin, and since some molecules are pretty large, scale and/or + translate so that the whole molecule is visible in the window. + */ +static void +ensure_bounding_box_visible (ModeInfo *mi) +{ + molecule_configuration *mc = &mcs[MI_SCREEN(mi)]; + + GLfloat x1, y1, z1, x2, y2, z2; + GLfloat w, h, d; + GLfloat size; + GLfloat max_size = 10; /* don't bother scaling down if the molecule + is already smaller than this */ + + molecule_bounding_box (mi, &x1, &y1, &z1, &x2, &y2, &z2); + w = x2-x1; + h = y2-y1; + d = z2-z1; + + size = (w > h ? w : h); + size = (size > d ? size : d); + + mc->molecule_size = size; + + mc->scale_down = 0; + + if (size > max_size) + { + GLfloat scale = max_size / size; + glScalef (scale, scale, scale); + + mc->scale_down = scale < 0.3; + } + + glTranslatef (-(x1 + w/2), + -(y1 + h/2), + -(z1 + d/2)); +} + + + +/* Constructs the GL shapes of the current molecule + */ +static void +build_molecule (ModeInfo *mi, Bool transparent_p) +{ + molecule_configuration *mc = &mcs[MI_SCREEN(mi)]; + int wire = MI_IS_WIREFRAME(mi); + int i; + GLfloat alpha = transparent_p ? shell_alpha : 1.0; + int polys = 0; + + molecule *m = &mc->molecules[mc->which]; + + if (wire) + { + glDisable(GL_CULL_FACE); + glDisable(GL_LIGHTING); + glDisable(GL_LIGHT0); + glDisable(GL_DEPTH_TEST); + glDisable(GL_NORMALIZE); + glDisable(GL_CULL_FACE); + } + else + { + glEnable(GL_CULL_FACE); + glEnable(GL_LIGHTING); + glEnable(GL_LIGHT0); + glEnable(GL_DEPTH_TEST); + glEnable(GL_NORMALIZE); + glEnable(GL_CULL_FACE); + } + + if (!wire) + set_atom_color (mi, 0, False, alpha); + + if (do_bonds) + for (i = 0; i < m->nbonds; i++) + { + const molecule_bond *b = &m->bonds[i]; + const molecule_atom *from = get_atom (m->atoms, m->natoms, b->from); + const molecule_atom *to = get_atom (m->atoms, m->natoms, b->to); + + if (wire) + { + glBegin(GL_LINES); + glVertex3f(from->x, from->y, from->z); + glVertex3f(to->x, to->y, to->z); + glEnd(); + polys++; + } + else + { + int faces = (mc->scale_down ? TUBE_FACES_2 : TUBE_FACES); +# ifdef SMOOTH_TUBE + int smooth = True; +# else + int smooth = False; +# endif + GLfloat thickness = 0.07 * b->strength; + GLfloat cap_size = 0.03; + if (thickness > 0.3) + thickness = 0.3; + + polys += tube (from->x, from->y, from->z, + to->x, to->y, to->z, + thickness, cap_size, + faces, smooth, (!do_atoms || do_shells), wire); + } + } + + if (!wire && do_atoms) + for (i = 0; i < m->natoms; i++) + { + const molecule_atom *a = &m->atoms[i]; + GLfloat size = atom_size (a); + set_atom_color (mi, a, False, alpha); + polys += sphere (mc, a->x, a->y, a->z, size, wire); + } + + if (do_bbox && !transparent_p) + { + draw_bounding_box (mi); + polys += 4; + } + + mc->polygon_count += polys; +} + + + +/* loading */ + +static void +push_atom (molecule *m, + int id, const char *label, + GLfloat x, GLfloat y, GLfloat z) +{ + m->natoms++; + if (m->atoms_size < m->natoms) + { + m->atoms_size += 20; + m->atoms = (molecule_atom *) realloc (m->atoms, + m->atoms_size * sizeof(*m->atoms)); + } + m->atoms[m->natoms-1].id = id; + m->atoms[m->natoms-1].label = label; + m->atoms[m->natoms-1].x = x; + m->atoms[m->natoms-1].y = y; + m->atoms[m->natoms-1].z = z; + m->atoms[m->natoms-1].data = get_atom_data (label); +} + + +static void +push_bond (molecule *m, int from, int to) +{ + int i; + + for (i = 0; i < m->nbonds; i++) + if ((m->bonds[i].from == from && m->bonds[i].to == to) || + (m->bonds[i].to == from && m->bonds[i].from == to)) + { + m->bonds[i].strength++; + return; + } + + m->nbonds++; + if (m->bonds_size < m->nbonds) + { + m->bonds_size += 20; + m->bonds = (molecule_bond *) realloc (m->bonds, + m->bonds_size * sizeof(*m->bonds)); + } + m->bonds[m->nbonds-1].from = from; + m->bonds[m->nbonds-1].to = to; + m->bonds[m->nbonds-1].strength = 1; +} + + +static void +parse_error (const char *file, int lineno, const char *line) +{ + fprintf (stderr, "%s: %s: parse error, line %d: %s\n", + progname, file, lineno, line); + exit (1); +} + + +/* This function is crap. + */ +static void +parse_pdb_data (molecule *m, const char *data, const char *filename, int line) +{ + const char *s = data; + char *ss; + while (*s) + { + if ((!m->label || !*m->label) && + (!strncmp (s, "HEADER", 6) || !strncmp (s, "COMPND", 6))) + { + char *name = calloc (1, 100); + char *n2 = name; + int L = strlen(s); + if (L > 99) L = 99; + + strncpy (n2, s, L); + n2 += 7; + while (isspace(*n2)) n2++; + + ss = strchr (n2, '\n'); + if (ss) *ss = 0; + ss = strchr (n2, '\r'); + if (ss) *ss = 0; + + ss = n2+strlen(n2)-1; + while (isspace(*ss) && ss > n2) + *ss-- = 0; + + if (strlen (n2) > 4 && + !strcmp (n2 + strlen(n2) - 4, ".pdb")) + n2[strlen(n2)-4] = 0; + + if (m->label) free ((char *) m->label); + m->label = strdup (n2); + free (name); + } + else if (!strncmp (s, "TITLE ", 6) || + !strncmp (s, "HEADER", 6) || + !strncmp (s, "COMPND", 6) || + !strncmp (s, "AUTHOR", 6) || + !strncmp (s, "REVDAT", 6) || + !strncmp (s, "SOURCE", 6) || + !strncmp (s, "EXPDTA", 6) || + !strncmp (s, "JRNL ", 6) || + !strncmp (s, "REMARK", 6) || + !strncmp (s, "SEQRES", 6) || + !strncmp (s, "HET ", 6) || + !strncmp (s, "FORMUL", 6) || + !strncmp (s, "CRYST1", 6) || + !strncmp (s, "ORIGX1", 6) || + !strncmp (s, "ORIGX2", 6) || + !strncmp (s, "ORIGX3", 6) || + !strncmp (s, "SCALE1", 6) || + !strncmp (s, "SCALE2", 6) || + !strncmp (s, "SCALE3", 6) || + !strncmp (s, "MASTER", 6) || + !strncmp (s, "KEYWDS", 6) || + !strncmp (s, "DBREF ", 6) || + !strncmp (s, "HETNAM", 6) || + !strncmp (s, "HETSYN", 6) || + !strncmp (s, "HELIX ", 6) || + !strncmp (s, "LINK ", 6) || + !strncmp (s, "MTRIX1", 6) || + !strncmp (s, "MTRIX2", 6) || + !strncmp (s, "MTRIX3", 6) || + !strncmp (s, "SHEET ", 6) || + !strncmp (s, "CISPEP", 6) || +/* + !strncmp (s, "SEQADV", 6) || + !strncmp (s, "SITE ", 5) || + !strncmp (s, "FTNOTE", 6) || + !strncmp (s, "MODEL ", 5) || + !strncmp (s, "ENDMDL", 6) || + !strncmp (s, "SPRSDE", 6) || + !strncmp (s, "MODRES", 6) || + */ + !strncmp (s, "GENERATED BY", 12) || + !strncmp (s, "TER ", 4) || + !strncmp (s, "END ", 4) || + !strncmp (s, "TER\n", 4) || + !strncmp (s, "END\n", 4) || + !strncmp (s, "\n", 1)) + /* ignored. */ + ; + else if (!strncmp (s, "ATOM ", 7)) + { + int id; + const char *end = strchr (s, '\n'); + int L = end - s; + char *name = (char *) calloc (1, 4); + GLfloat x = -999, y = -999, z = -999; + + if (1 != sscanf (s+7, " %d ", &id)) + parse_error (filename, line, s); + + /* Use the "atom name" field if that is all that is available. */ + strncpy (name, s+12, 3); + + /* But prefer the "element" field. */ + if (L > 77 && !isspace(s[77])) { + /* fprintf(stderr, " \"%s\" -> ", name); */ + name[0] = s[76]; + name[1] = s[77]; + name[2] = 0; + /* fprintf(stderr, "\"%s\"\n", name); */ + } + + while (isspace(*name)) name++; + ss = name + strlen(name)-1; + while (isspace(*ss) && ss > name) + *ss-- = 0; + ss = name + 1; + while(*ss) + { + *ss = tolower(*ss); + ss++; + } + if (3 != sscanf (s + 32, " %f %f %f ", &x, &y, &z)) + parse_error (filename, line, s); + +/* + fprintf (stderr, "%s: %s: %d: atom: %d \"%s\" %9.4f %9.4f %9.4f\n", + progname, filename, line, + id, name, x, y, z); +*/ + push_atom (m, id, name, x, y, z); + } + else if (!strncmp (s, "HETATM ", 7)) + { + int id; + char *name = (char *) calloc (1, 4); + GLfloat x = -999, y = -999, z = -999; + + if (1 != sscanf (s+7, " %d ", &id)) + parse_error (filename, line, s); + + strncpy (name, s+12, 3); + while (isspace(*name)) name++; + ss = name + strlen(name)-1; + while (isspace(*ss) && ss > name) + *ss-- = 0; + if (3 != sscanf (s + 30, " %f %f %f ", &x, &y, &z)) + parse_error (filename, line, s); +/* + fprintf (stderr, "%s: %s: %d: atom: %d \"%s\" %9.4f %9.4f %9.4f\n", + progname, filename, line, + id, name, x, y, z); +*/ + push_atom (m, id, name, x, y, z); + } + else if (!strncmp (s, "CONECT ", 7)) + { + int atoms[11]; + int i = sscanf (s + 8, " %d %d %d %d %d %d %d %d %d %d %d %d ", + &atoms[0], &atoms[1], &atoms[2], &atoms[3], + &atoms[4], &atoms[5], &atoms[6], &atoms[7], + &atoms[8], &atoms[9], &atoms[10], &atoms[11]); + int j; + for (j = 1; j < i; j++) + if (atoms[j] > 0) + { +/* + fprintf (stderr, "%s: %s: %d: bond: %d %d\n", + progname, filename, line, atoms[0], atoms[j]); +*/ + push_bond (m, atoms[0], atoms[j]); + } + } + else + { + char *s1 = strdup (s); + for (ss = s1; *ss && *ss != '\n'; ss++) + ; + *ss = 0; + fprintf (stderr, "%s: %s: %d: unrecognised line: %s\n", + progname, filename, line, s1); + } + + while (*s && *s != '\n') + s++; + if (*s == '\n') + s++; + line++; + } +} + + +#ifdef LOAD_FILES +static int +parse_pdb_file (molecule *m, const char *name) +{ + FILE *in; + int buf_size = 40960; + char *buf; + int line = 1; + + in = fopen(name, "r"); + if (!in) + { + char *buf = (char *) malloc(1024 + strlen(name)); + sprintf(buf, "%s: error reading \"%s\"", progname, name); + perror(buf); + return -1; + } + + buf = (char *) malloc (buf_size); + + while (fgets (buf, buf_size-1, in)) + { + char *s; + for (s = buf; *s; s++) + if (*s == '\r') *s = '\n'; + parse_pdb_data (m, buf, name, line++); + } + + free (buf); + fclose (in); + + if (!m->natoms) + { + fprintf (stderr, "%s: file %s contains no atomic coordinates!\n", + progname, name); + return -1; + } + + if (!m->nbonds && do_bonds) + { + fprintf (stderr, "%s: warning: file %s contains no atomic bond info.\n", + progname, name); + do_bonds = 0; + } + + return 0; +} +#endif /* LOAD_FILES */ + + +typedef struct { char *atom; int count; } atom_and_count; + +/* When listing the components of a molecule, the convention is to put the + carbon atoms first, the hydrogen atoms second, and the other atom types + sorted alphabetically after that (although for some molecules, the usual + order is different: we special-case a few of those.) + */ +static int +cmp_atoms (const void *aa, const void *bb) +{ + const atom_and_count *a = (atom_and_count *) aa; + const atom_and_count *b = (atom_and_count *) bb; + if (!a->atom) return 1; + if (!b->atom) return -1; + if (!strcmp(a->atom, "C")) return -1; + if (!strcmp(b->atom, "C")) return 1; + if (!strcmp(a->atom, "H")) return -1; + if (!strcmp(b->atom, "H")) return 1; + return strcmp (a->atom, b->atom); +} + +static void special_case_formula (char *f); + +static void +generate_molecule_formula (molecule *m) +{ + char *buf = (char *) malloc (m->natoms * 10); + char *s = buf; + int i; + atom_and_count counts[200]; + memset (counts, 0, sizeof(counts)); + *s = 0; + for (i = 0; i < m->natoms; i++) + { + int j = 0; + char *a = (char *) m->atoms[i].label; + char *e; + while (!isalpha(*a)) a++; + a = strdup (a); + for (e = a; isalpha(*e); e++); + *e = 0; + while (counts[j].atom && !!strcmp(a, counts[j].atom)) + j++; + if (counts[j].atom) + free (a); + else + counts[j].atom = a; + counts[j].count++; + } + + i = 0; + while (counts[i].atom) i++; + qsort (counts, i, sizeof(*counts), cmp_atoms); + + i = 0; + while (counts[i].atom) + { + strcat (s, counts[i].atom); + free (counts[i].atom); + s += strlen (s); + if (counts[i].count > 1) + sprintf (s, "[%d]", counts[i].count); /* use [] to get subscripts */ + s += strlen (s); + i++; + } + + special_case_formula (buf); + + if (!m->label) m->label = strdup(""); + s = (char *) malloc (strlen (m->label) + strlen (buf) + 2); + strcpy (s, m->label); + strcat (s, "\n"); + strcat (s, buf); + free ((char *) m->label); + free (buf); + m->label = s; +} + +/* thanks to Rene Uittenbogaard */ +static void +special_case_formula (char *f) +{ + if (!strcmp(f, "H[2]Be")) strcpy(f, "BeH[2]"); + else if (!strcmp(f, "H[3]B")) strcpy(f, "BH[3]"); + else if (!strcmp(f, "H[3]N")) strcpy(f, "NH[3]"); + else if (!strcmp(f, "CHN")) strcpy(f, "HCN"); + else if (!strcmp(f, "CKN")) strcpy(f, "KCN"); + else if (!strcmp(f, "H[4]N[2]")) strcpy(f, "N[2]H[4]"); + else if (!strcmp(f, "Cl[3]P")) strcpy(f, "PCl[3]"); + else if (!strcmp(f, "Cl[5]P")) strcpy(f, "PCl[5]"); +} + + +static void +insert_vertical_whitespace (char *string) +{ + while (*string) + { + if ((string[0] == ',' || + string[0] == ';' || + string[0] == ':') && + string[1] == ' ') + string[0] = ' ', string[1] = '\n'; + string++; + } +} + + +/* Construct the molecule data from either: the builtins; or from + the (one) .pdb file specified with -molecule. + */ +static void +load_molecules (ModeInfo *mi) +{ + molecule_configuration *mc = &mcs[MI_SCREEN(mi)]; + int i; + + mc->nmolecules = 0; +# ifdef LOAD_FILES + if (molecule_str && *molecule_str && + strcmp(molecule_str, "(default)")) /* try external PDB files */ + { + /* The -molecule option can point to a .pdb file, or to + a directory of them. + */ + int wire = MI_IS_WIREFRAME(mi); + struct stat st; + int nfiles = 0; + int list_size = 0; + char **files = 0; + int molecule_ctr; + + if (!stat (molecule_str, &st) && + S_ISDIR (st.st_mode)) + { + char buf [255]; + DIR *pdb_dir; + struct dirent *dentry; + + pdb_dir = opendir (molecule_str); + if (! pdb_dir) + { + sprintf (buf, "%.100s: %.100s", progname, molecule_str); + perror (buf); + exit (1); + } + + if (verbose_p) + fprintf (stderr, "%s: directory %s\n", progname, molecule_str); + + nfiles = 0; + list_size = 100; + files = (char **) calloc (sizeof(*files), list_size); + + while ((dentry = readdir (pdb_dir))) + { + int L = strlen (dentry->d_name); + if (L > 4 && !strcasecmp (dentry->d_name + L - 4, ".pdb")) + { + char *fn; + if (nfiles >= list_size-1) + { + list_size = (list_size + 10) * 1.2; + files = (char **) + realloc (files, list_size * sizeof(*files)); + if (!files) + { + OOM: + fprintf (stderr, "%s: out of memory (%d files)\n", + progname, nfiles); + exit (1); + } + } + + fn = (char *) malloc (strlen (molecule_str) + L + 10); + if (!fn) goto OOM; + strcpy (fn, molecule_str); + if (fn[strlen(fn)-1] != '/') strcat (fn, "/"); + strcat (fn, dentry->d_name); + files[nfiles++] = fn; + if (verbose_p) + fprintf (stderr, "%s: file %s\n", progname, fn); + } + } + closedir (pdb_dir); + + if (nfiles == 0) + fprintf (stderr, "%s: no .pdb files in directory %s\n", + progname, molecule_str); + } + else + { + files = (char **) malloc (sizeof (*files)); + nfiles = 1; + files[0] = strdup (molecule_str); + if (verbose_p) + fprintf (stderr, "%s: file %s\n", progname, molecule_str); + } + + mc->nmolecules = nfiles; + mc->molecules = (molecule *) calloc (sizeof (molecule), mc->nmolecules); + molecule_ctr = 0; + for (i = 0; i < mc->nmolecules; i++) + { + if (verbose_p) + fprintf (stderr, "%s: reading %s\n", progname, files[i]); + if (!parse_pdb_file (&mc->molecules[molecule_ctr], files[i])) + { + if ((wire || !do_atoms) && + !do_labels && + mc->molecules[molecule_ctr].nbonds == 0) + { + /* If we're not drawing atoms (e.g., wireframe mode), and + there is no bond info, then make sure labels are turned + on, or we'll be looking at a black screen... */ + fprintf (stderr, "%s: %s: no bonds: turning -label on.\n", + progname, files[i]); + do_labels = 1; + } + free (files[i]); + files[i] = 0; + molecule_ctr++; + } + } + + free (files); + files = 0; + mc->nmolecules = molecule_ctr; + } +# endif /* LOAD_FILES */ + + if (mc->nmolecules == 0) /* do the builtins if no files */ + { + mc->nmolecules = countof(builtin_pdb_data); + mc->molecules = (molecule *) calloc (sizeof (molecule), mc->nmolecules); + for (i = 0; i < mc->nmolecules; i++) + { + char name[100]; + sprintf (name, "", i); + if (verbose_p) fprintf (stderr, "%s: reading %s\n", progname, name); + parse_pdb_data (&mc->molecules[i], builtin_pdb_data[i], name, 1); + } + } + + for (i = 0; i < mc->nmolecules; i++) + { + generate_molecule_formula (&mc->molecules[i]); + insert_vertical_whitespace ((char *) mc->molecules[i].label); + } +} + + + +/* Window management, etc + */ +ENTRYPOINT void +reshape_molecule (ModeInfo *mi, int width, int height) +{ + GLfloat h = (GLfloat) height / (GLfloat) width; + + glViewport (0, 0, (GLint) width, (GLint) height); + + glMatrixMode(GL_PROJECTION); + glLoadIdentity(); + gluPerspective (30.0, 1/h, 20.0, 100.0); + + glMatrixMode(GL_MODELVIEW); + glLoadIdentity(); + gluLookAt( 0.0, 0.0, 30.0, + 0.0, 0.0, 0.0, + 0.0, 1.0, 0.0); + + glClear(GL_COLOR_BUFFER_BIT); +} + + +static void +gl_init (ModeInfo *mi) +{ + static const GLfloat pos[4] = {1.0, 0.4, 0.9, 0.0}; + static const GLfloat amb[4] = {0.0, 0.0, 0.0, 1.0}; + static const GLfloat dif[4] = {0.8, 0.8, 0.8, 1.0}; + static const GLfloat spc[4] = {1.0, 1.0, 1.0, 1.0}; + glLightfv(GL_LIGHT0, GL_POSITION, pos); + glLightfv(GL_LIGHT0, GL_AMBIENT, amb); + glLightfv(GL_LIGHT0, GL_DIFFUSE, dif); + glLightfv(GL_LIGHT0, GL_SPECULAR, spc); +} + + +static void +startup_blurb (ModeInfo *mi) +{ + molecule_configuration *mc = &mcs[MI_SCREEN(mi)]; + const char *s = "Constructing molecules..."; + print_gl_string (mi->dpy, +# ifdef HAVE_GLBITMAP + mc->xfont3, mc->font3_dlist, +# else + mc->font3_data, +# endif + mi->xgwa.width, mi->xgwa.height, + 10, mi->xgwa.height - 10, + s, False); + glFinish(); + glXSwapBuffers(MI_DISPLAY(mi), MI_WINDOW(mi)); +} + +ENTRYPOINT Bool +molecule_handle_event (ModeInfo *mi, XEvent *event) +{ + molecule_configuration *mc = &mcs[MI_SCREEN(mi)]; + + if (event->xany.type == ButtonPress && + event->xbutton.button == Button1) + { + mc->button_down_p = True; + gltrackball_start (mc->trackball, + event->xbutton.x, event->xbutton.y, + MI_WIDTH (mi), MI_HEIGHT (mi)); + return True; + } + else if (event->xany.type == ButtonRelease && + event->xbutton.button == Button1) + { + mc->button_down_p = False; + return True; + } + else if (event->xany.type == ButtonPress && + (event->xbutton.button == Button4 || + event->xbutton.button == Button5 || + event->xbutton.button == Button6 || + event->xbutton.button == Button7)) + { + gltrackball_mousewheel (mc->trackball, event->xbutton.button, 10, + !!event->xbutton.state); + return True; + } + else if (event->xany.type == KeyPress) + { + KeySym keysym; + char c = 0; + XLookupString (&event->xkey, &c, 1, &keysym, 0); + + if (c == ' ' || c == '\t' || c == '\r' || c == '\n') + { + GLfloat speed = 4.0; + mc->mode = 1; + mc->mode_tick = 10 * speed; + return True; + } + } + else if (event->xany.type == MotionNotify && + mc->button_down_p) + { + gltrackball_track (mc->trackball, + event->xmotion.x, event->xmotion.y, + MI_WIDTH (mi), MI_HEIGHT (mi)); + return True; + } + + return False; +} + + +ENTRYPOINT void +init_molecule (ModeInfo *mi) +{ + molecule_configuration *mc; + int wire; + + if (!mcs) { + mcs = (molecule_configuration *) + calloc (MI_NUM_SCREENS(mi), sizeof (molecule_configuration)); + if (!mcs) { + fprintf(stderr, "%s: out of memory\n", progname); + exit(1); + } + } + + mc = &mcs[MI_SCREEN(mi)]; + + if ((mc->glx_context = init_GL(mi)) != NULL) { + gl_init(mi); + reshape_molecule (mi, MI_WIDTH(mi), MI_HEIGHT(mi)); + } + + load_fonts (mi); + startup_blurb (mi); + + wire = MI_IS_WIREFRAME(mi); + + { + Bool spinx=False, spiny=False, spinz=False; + double spin_speed = 0.5; + double spin_accel = 0.3; + double wander_speed = 0.01; + + char *s = do_spin; + while (*s) + { + if (*s == 'x' || *s == 'X') spinx = True; + else if (*s == 'y' || *s == 'Y') spiny = True; + else if (*s == 'z' || *s == 'Z') spinz = True; + else if (*s == '0') ; + else + { + fprintf (stderr, + "%s: spin must contain only the characters X, Y, or Z (not \"%s\")\n", + progname, do_spin); + exit (1); + } + s++; + } + + mc->rot = make_rotator (spinx ? spin_speed : 0, + spiny ? spin_speed : 0, + spinz ? spin_speed : 0, + spin_accel, + do_wander ? wander_speed : 0, + (spinx && spiny && spinz)); + mc->trackball = gltrackball_init (); + } + + orig_do_labels = do_labels; + orig_do_atoms = do_atoms; + orig_do_bonds = do_bonds; + orig_do_shells = do_shells; + orig_wire = MI_IS_WIREFRAME(mi); + + mc->molecule_dlist = glGenLists(1); + if (do_shells) + mc->shell_dlist = glGenLists(1); + + load_molecules (mi); + mc->which = random() % mc->nmolecules; + + mc->no_label_threshold = get_float_resource (mi->dpy, "noLabelThreshold", + "NoLabelThreshold"); + mc->wireframe_threshold = get_float_resource (mi->dpy, "wireframeThreshold", + "WireframeThreshold"); + mc->mode = 0; + + if (wire) + do_bonds = 1; +} + + +/* Put the labels on the atoms. + This can't be a part of the display list because of the games + we play with the translation matrix. + */ +static void +draw_labels (ModeInfo *mi) +{ + molecule_configuration *mc = &mcs[MI_SCREEN(mi)]; + int wire = MI_IS_WIREFRAME(mi); + molecule *m = &mc->molecules[mc->which]; +# ifdef HAVE_GLBITMAP + XFontStruct *xfont = (mc->scale_down ? mc->xfont2 : mc->xfont1); + GLuint font_dlist = (mc->scale_down ? mc->font2_dlist : mc->font1_dlist); +# else + texture_font_data *font_data = mc->font1_data; /* don't scale down */ +# endif + int i; + + if (!do_labels) + return; + + if (!wire) + glDisable (GL_LIGHTING); /* don't light fonts */ + + for (i = 0; i < m->natoms; i++) + { + molecule_atom *a = &m->atoms[i]; + GLfloat size = atom_size (a); + GLfloat m[4][4]; + + glPushMatrix(); + + if (!wire) + set_atom_color (mi, a, True, 1); + + /* First, we translate the origin to the center of the atom. + + Then we retrieve the prevailing modelview matrix (which + includes any rotation, wandering, and user-trackball-rolling + of the scene. + + We set the top 3x3 cells of that matrix to be the identity + matrix. This removes all rotation from the matrix, while + leaving the translation alone. This has the effect of + leaving the prevailing coordinate system perpendicular to + the camera view: were we to draw a square face, it would + be in the plane of the screen. + + Now we translate by `size' toward the viewer -- so that the + origin is *just in front* of the ball. + + Then we draw the label text, allowing the depth buffer to + do its work: that way, labels on atoms will be occluded + properly when other atoms move in front of them. + + This technique (of neutralizing rotation relative to the + observer, after both rotations and translations have been + applied) is known as "billboarding". + */ + + glTranslatef(a->x, a->y, a->z); /* get matrix */ + glGetFloatv (GL_MODELVIEW_MATRIX, &m[0][0]); /* load rot. identity */ + m[0][0] = 1; m[1][0] = 0; m[2][0] = 0; + m[0][1] = 0; m[1][1] = 1; m[2][1] = 0; + m[0][2] = 0; m[1][2] = 0; m[2][2] = 1; + glLoadIdentity(); /* reset modelview */ + glMultMatrixf (&m[0][0]); /* replace with ours */ + + glTranslatef (0, 0, (size * 1.1)); /* move toward camera */ + + glRotatef (current_device_rotation(), 0, 0, 1); /* right side up */ + +# ifdef HAVE_GLBITMAP + glRasterPos3f (0, 0, 0); /* draw text here */ + + /* Before drawing the string, shift the origin to center + the text over the origin of the sphere. */ + glBitmap (0, 0, 0, 0, + -string_width (xfont, a->label, 0) / 2, + -xfont->descent, + NULL); + { + int j; + for (j = 0; j < strlen(a->label); j++) + glCallList (font_dlist + (int)(a->label[j])); + } +# else + { + int h; + int w = texture_string_width (font_data, a->label, &h); + GLfloat s = 1.0 / h; + GLfloat max = 18; /* max point size to avoid pixellated text */ + if (h > max) s *= max/h; + glScalef (s, s, 1); + glTranslatef (-w/2, h*2/3, 0); + print_gl_string (mi->dpy, +# ifdef HAVE_GLBITMAP + xfont, font_dlist, +# else + font_data, +# endif + 0, 0, 0, 0, + a->label, False); + } +# endif + + glPopMatrix(); + } + + /* More efficient to always call glEnable() with correct values + than to call glPushAttrib()/glPopAttrib(), since reading + attributes from GL does a round-trip and stalls the pipeline. + */ + if (!wire) + glEnable (GL_LIGHTING); +} + + +static void +pick_new_molecule (ModeInfo *mi, time_t last) +{ + molecule_configuration *mc = &mcs[MI_SCREEN(mi)]; + + if (mc->nmolecules == 1) + { + if (last != 0) return; + mc->which = 0; + } + else if (last == 0) + { + mc->which = random() % mc->nmolecules; + } + else + { + int n = mc->which; + while (n == mc->which) + n = random() % mc->nmolecules; + mc->which = n; + } + + if (verbose_p) + { + char *name = strdup (mc->molecules[mc->which].label); + char *s = strpbrk (name, "\r\n"); + if (s) *s = 0; + fprintf (stderr, "%s: drawing %s (%d)\n", progname, name, mc->which); + free (name); + } + + mc->polygon_count = 0; + + glNewList (mc->molecule_dlist, GL_COMPILE); + ensure_bounding_box_visible (mi); + + do_labels = orig_do_labels; + do_atoms = orig_do_atoms; + do_bonds = orig_do_bonds; + do_shells = orig_do_shells; + MI_IS_WIREFRAME(mi) = orig_wire; + + if (mc->molecule_size > mc->no_label_threshold) + do_labels = 0; + if (mc->molecule_size > mc->wireframe_threshold) + MI_IS_WIREFRAME(mi) = 1; + + if (MI_IS_WIREFRAME(mi)) + do_bonds = 1, do_shells = 0; + + if (!do_bonds) + do_shells = 0; + + if (! (do_bonds || do_atoms || do_labels)) + { + /* Make sure *something* shows up! */ + MI_IS_WIREFRAME(mi) = 1; + do_bonds = 1; + } + + build_molecule (mi, False); + glEndList(); + + if (do_shells) + { + glNewList (mc->shell_dlist, GL_COMPILE); + ensure_bounding_box_visible (mi); + + do_labels = 0; + do_atoms = 1; + do_bonds = 0; + + build_molecule (mi, True); + + glEndList(); + do_bonds = orig_do_bonds; + do_atoms = orig_do_atoms; + do_labels = orig_do_labels; + } +} + + +ENTRYPOINT void +draw_molecule (ModeInfo *mi) +{ + time_t now = time ((time_t *) 0); + GLfloat speed = 4.0; /* speed at which the zoom out/in happens */ + + molecule_configuration *mc = &mcs[MI_SCREEN(mi)]; + Display *dpy = MI_DISPLAY(mi); + Window window = MI_WINDOW(mi); + + if (!mc->glx_context) + return; + + glXMakeCurrent(MI_DISPLAY(mi), MI_WINDOW(mi), *(mc->glx_context)); + + if (mc->draw_time == 0) + { + pick_new_molecule (mi, mc->draw_time); + mc->draw_time = now; + } + else if (mc->mode == 0) + { + if (mc->draw_tick++ > 10) + { + time_t now = time((time_t *) 0); + if (mc->draw_time == 0) mc->draw_time = now; + mc->draw_tick = 0; + + if (!mc->button_down_p && + mc->nmolecules > 1 && + mc->draw_time + timeout <= now) + { + /* randomize molecules every -timeout seconds */ + mc->mode = 1; /* go out */ + mc->mode_tick = 10 * speed; + mc->draw_time = now; + } + } + } + else if (mc->mode == 1) /* out */ + { + if (--mc->mode_tick <= 0) + { + mc->mode_tick = 10 * speed; + mc->mode = 2; /* go in */ + pick_new_molecule (mi, mc->draw_time); + mc->draw_time = now; + } + } + else if (mc->mode == 2) /* in */ + { + if (--mc->mode_tick <= 0) + mc->mode = 0; /* normal */ + } + else + abort(); + + glPushMatrix (); + glScalef(1.1, 1.1, 1.1); + + { + double x, y, z; + get_position (mc->rot, &x, &y, &z, !mc->button_down_p); + glTranslatef((x - 0.5) * 9, + (y - 0.5) * 9, + (z - 0.5) * 9); + + /* Do it twice because we don't track the device's orientation. */ + glRotatef( current_device_rotation(), 0, 0, 1); + gltrackball_rotate (mc->trackball); + glRotatef(-current_device_rotation(), 0, 0, 1); + + get_rotation (mc->rot, &x, &y, &z, !mc->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); + } + + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + + if (mc->mode != 0) + { + GLfloat s = (mc->mode == 1 + ? mc->mode_tick / (10 * speed) + : ((10 * speed) - mc->mode_tick + 1) / (10 * speed)); + glScalef (s, s, s); + } + + glPushMatrix(); + glCallList (mc->molecule_dlist); + + if (mc->mode == 0) + { + molecule *m = &mc->molecules[mc->which]; + + draw_labels (mi); + + /* This can't go in the display list, or the characters are spaced + wrongly when the window is resized. */ + if (do_titles && m->label && *m->label) + { + set_atom_color (mi, 0, True, 1); + print_gl_string (mi->dpy, +# ifdef HAVE_GLBITMAP + mc->xfont3, mc->font3_dlist, +# else + mc->font3_data, +# endif + mi->xgwa.width, mi->xgwa.height, + 10, mi->xgwa.height - 10, + m->label, False); + } + } + glPopMatrix(); + + if (do_shells) + { + glColorMask (GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE); + glPushMatrix(); + glCallList (mc->shell_dlist); + glPopMatrix(); + glColorMask (GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); + + glDepthFunc (GL_EQUAL); + glEnable (GL_BLEND); + glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + glPushMatrix(); + glCallList (mc->shell_dlist); + glPopMatrix(); + glDepthFunc (GL_LESS); + glDisable (GL_BLEND); + } + + glPopMatrix (); + + mi->polygon_count = mc->polygon_count; + + if (mi->fps_p) do_fps (mi); + glFinish(); + + glXSwapBuffers(dpy, window); +} + +XSCREENSAVER_MODULE ("Molecule", molecule) + +#endif /* USE_GL */ diff --git a/hacks/glx/molecule.man b/hacks/glx/molecule.man new file mode 100644 index 00000000..6ec8328d --- /dev/null +++ b/hacks/glx/molecule.man @@ -0,0 +1,160 @@ +.TH XScreenSaver 1 "13-Mar-01" "X Version 11" +.SH NAME +molecule - draws 3D molecular structures +.SH SYNOPSIS +.B molecule +[\-display \fIhost:display.screen\fP] [\-window] [\-root] +[\-visual \fIvisual\fP] [\-delay \fImicroseconds\fP] +[\-wander] [\-no-wander] +[\-spin \fIaxes\fP] +[\-no-spin] +[\-timeout \fIseconds\fP] +[\-labels] [\-no-labels] +[\-titles] [\-no-titles] +[\-atoms] [\-no-atoms] +[\-bonds] [\-no-bonds] +[\-shells] [\-no-shells] +[\-molecule \fIfile-or-directory\fP] +[\-verbose] +[\-wireframe] +[\-fps] +.SH DESCRIPTION +The \fImolecule\fP program draws several different representations of +molecules. Some common molecules are built in, and it can read PDB +(Protein Data Base) files as input. +.SH OPTIONS +.I molecule +accepts the following options: +.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 \-install +Install a private colormap for the window. +.TP 8 +.B \-visual \fIvisual\fP\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 \-fps +Display the current frame rate, CPU load, and polygon count. +.TP 8 +.B \-verbose +Print debugging info on stderr about files being loaded, etc. +.TP 8 +.B \-wander +Move the molecules around the screen. +.TP 8 +.B \-no\-wander +Keep the molecule centered on the screen. This is the default. +.TP 8 +.B \-spin +Which axes around which the molecule should spin. The default is "XYZ", +meaning rotate it freely in space. "\fB\-spin Z\fP" would rotate the +molecule in the plane of the screen while not rotating it into or out +of the screen; etc. +.TP 8 +.B \-no\-spin +Don't spin it at all: the same as \fB\-spin ""\fP. +.TP 8 +.B \-labels +Draw labels on the atoms (or the spot where the atoms would be.) +This is the default. +.TP 8 +.B \-no\-labels +Do not draw labels on the atoms. +.TP 8 +.B \-titles +Print the name of the molecule and its chemical formula at the top of +the screen. +.TP 8 +.B \-no\-titles +Do not print the molecule name. +.TP 8 +.B \-atoms +Represent the atoms as shaded spheres of appropriate sizes. +This is the default. +.TP 8 +.B \-no\-atoms +Do not draw spheres for the atoms: only draw bond lines. +.TP 8 +.B \-bonds +Represent the atomic bonds as solid tubes of appropriate thicknesses. +This is the default. +.TP 8 +.B \-no\-bonds +Do not draw the bonds: instead, make the spheres for the atoms be +larger, for a "space-filling" representation of the molecule. +.TP 8 +.B \-shells +Draw transparent electron shells around the atoms. This only works +if bonds are also being drawn. +.TP 8 +.B \-no\-shells +Do not draw electron shells. This is the default. +.TP 8 +.B \-shell\-alpha +When drawing shells, how transparent to make them. Default 0.4. +.TP 8 +.B \-wireframe +Draw a wireframe rendition of the molecule: this will consist only of +single-pixel lines for the bonds, and text labels where the atoms go. +This will be very fast. +.TP 8 +.B \-timeout \fIseconds\fP +When using the built-in data set, change to a new molecule every +this-many seconds. Default is 20 seconds. +.TP 8 +.B \-molecule \fIfile-or-directory\fP +Instead of using the built-in molecules, read one from the given file. +This file must be in PDB (Protein Data Base) format. (Note that it's +not uncommon for PDB files to contain only the atoms, with no (or +little) information about the atomic bonds.) + +This can also be a directory, in which case, all of the .pdb files in +that directory will be loaded. A new one will be displayed at random +every few seconds (as per the \fI\-timeout\fP option.) +.PP +When the molecule is too large (bigger than about 30 angstroms from +side to side), the \fI\-label\fP option will be automatically turned +off, because otherwise, the labels would overlap and completely obscure +the display. + +When the molecule is around 150 angstroms from side to side, wireframe +mode will be turned on (because otherwise it would be too slow.) +.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) +.PP +Documentation on the PDB file format: + + http://www.wwpdb.org/docs.html + http://www.rcsb.org/pdb/docs/format/pdbguide2.2/guide2.2_frame.html + +A good source of PDB files: + + http://www.umass.edu/microbio/rasmol/whereget.htm + http://www.wwpdb.org/docs.html +.SH COPYRIGHT +Copyright \(co 2001-2005 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/glx/molecules.sh b/hacks/glx/molecules.sh new file mode 100755 index 00000000..9519d2f5 --- /dev/null +++ b/hacks/glx/molecules.sh @@ -0,0 +1,22 @@ +#!/bin/sh + +TARGET=$1 +shift +SRCS=$* + +TMP=molecules.h.$$ +rm -f $TMP + +if [ -z "$UTILS_SRC" ]; then UTILS_SRC="../../utils"; fi + +for f in $SRCS ; do + sh "$UTILS_SRC/ad2c" "$f" | + sed 's/",$/\\n"/' >> $TMP + echo ',' >> $TMP +done + +if cmp -s $TMP $TARGET ; then + rm $TMP +else + mv $TMP $TARGET +fi diff --git a/hacks/glx/morph3d.c b/hacks/glx/morph3d.c new file mode 100644 index 00000000..c1675aeb --- /dev/null +++ b/hacks/glx/morph3d.c @@ -0,0 +1,833 @@ +/* -*- Mode: C; tab-width: 4 -*- */ +/* morph3d --- Shows 3D morphing objects */ + +#if 0 +static const char sccsid[] = "@(#)morph3d.c 5.01 2001/03/01 xlockmore"; +#endif + +#undef DEBUG_CULL_FACE + +/*- + * Permission to use, copy, modify, and distribute this software and its + * documentation for any purpose and without fee is hereby granted, + * provided that the above copyright notice appear in all copies and that + * both that copyright notice and this permission notice appear in + * supporting documentation. + * + * This file is provided AS IS with no warranties of any kind. The author + * shall have no liability with respect to the infringement of copyrights, + * trade secrets or any patents by this file or any part thereof. In no + * event will the author be liable for any lost revenue or profits or + * other special, indirect and consequential damages. + * + * The original code for this mode was written by Marcelo Fernandes Vianna + * (me...) and was inspired on a WindowsNT(R)'s screen saver (Flower Box). + * It was written from scratch and it was not based on any other source code. + * + * Porting it to xlock (the final objective of this code since the moment I + * decided to create it) was possible by comparing the original Mesa's gear + * demo with it's ported version to xlock, so thanks for Danny Sung (look at + * gear.c) for his indirect help. + * + * Thanks goes also to Brian Paul for making it possible and inexpensive + * to use OpenGL at home. + * + * If you are interested in the original version of this program (not a xlock + * mode, please refer to the Mesa package (ftp iris.ssec.wisc.edu on /pub/Mesa) + * + * Since I'm not a native English speaker, my apologies for any grammatical + * mistakes. + * + * My e-mail address is + * mfvianna@centroin.com.br + * + * Marcelo F. Vianna (Feb-13-1997) + * + * Revision History: + * 05-Apr-2002: Removed all gllist uses (fix some bug with nvidia driver) + * 01-Mar-2001: Added FPS stuff E.Lassauge + * 27-Jul-1997: Speed ups by Marcelo F. Vianna. + * 08-May-1997: Speed ups by Marcelo F. Vianna. + * + */ + +#ifdef STANDALONE +# define MODE_moebius +# define DEFAULTS "*delay: 40000 \n" \ + "*showFPS: False \n" \ + "*count: 0 \n" +# define refresh_morph3d 0 +# define morph3d_handle_event 0 +# include "xlockmore.h" /* from the xscreensaver distribution */ +#else /* !STANDALONE */ +# include "xlock.h" /* from the xlockmore distribution */ +#endif /* !STANDALONE */ + +#ifdef MODE_moebius + +ENTRYPOINT ModeSpecOpt morph3d_opts = +{0, (XrmOptionDescRec *) NULL, 0, (argtype *) NULL, (OptionStruct *) NULL}; + +#ifdef USE_MODULES +ModStruct morph3d_description = +{"morph3d", "init_morph3d", "draw_morph3d", "release_morph3d", + "draw_morph3d", "change_morph3d", (char *) NULL, &morph3d_opts, + 1000, 0, 1, 1, 4, 1.0, "", + "Shows GL morphing polyhedra", 0, NULL}; + +#endif + +#define Scale4Window 0.3 +#define Scale4Iconic 1.0 + +#define VectMul(X1,Y1,Z1,X2,Y2,Z2) (Y1)*(Z2)-(Z1)*(Y2),(Z1)*(X2)-(X1)*(Z2),(X1)*(Y2)-(Y1)*(X2) +#define sqr(A) ((A)*(A)) + +/* Increasing this values produces better image quality, the price is speed. */ +#define tetradivisions 23 +#define cubedivisions 20 +#define octadivisions 21 +#define dodecadivisions 10 +#define icodivisions 15 + +#define tetraangle 109.47122063449069174 +#define cubeangle 90.000000000000000000 +#define octaangle 109.47122063449069174 +#define dodecaangle 63.434948822922009981 +#define icoangle 41.810314895778596167 + +#ifndef Pi +#define Pi M_PI +#endif +#define SQRT2 1.4142135623730951455 +#define SQRT3 1.7320508075688771932 +#define SQRT5 2.2360679774997898051 +#define SQRT6 2.4494897427831778813 +#define SQRT15 3.8729833462074170214 +#define cossec36_2 0.8506508083520399322 +#define cos72 0.3090169943749474241 +#define sin72 0.9510565162951535721 +#define cos36 0.8090169943749474241 +#define sin36 0.5877852522924731292 + +/*************************************************************************/ + +typedef struct { + GLint WindH, WindW; + GLfloat step; + GLfloat seno; + int object; + int edgedivisions; + int VisibleSpikes; + void (*draw_object) (ModeInfo * mi); + float Magnitude; + const float *MaterialColor[20]; + GLXContext *glx_context; + int arrayninit; + +} morph3dstruct; + +static const GLfloat front_shininess[] = {60.0}; +static const GLfloat front_specular[] = {0.7, 0.7, 0.7, 1.0}; +static const GLfloat ambient[] = {0.0, 0.0, 0.0, 1.0}; +static const GLfloat diffuse[] = {1.0, 1.0, 1.0, 1.0}; +static const GLfloat position0[] = {1.0, 1.0, 1.0, 0.0}; +static const GLfloat position1[] = {-1.0, -1.0, 1.0, 0.0}; +static const GLfloat lmodel_ambient[] = {0.5, 0.5, 0.5, 1.0}; +static const GLfloat lmodel_twoside[] = {GL_TRUE}; + +static const GLfloat MaterialRed[] = {0.7, 0.0, 0.0, 1.0}; +static const GLfloat MaterialGreen[] = {0.1, 0.5, 0.2, 1.0}; +static const GLfloat MaterialBlue[] = {0.0, 0.0, 0.7, 1.0}; +static const GLfloat MaterialCyan[] = {0.2, 0.5, 0.7, 1.0}; +static const GLfloat MaterialYellow[] = {0.7, 0.7, 0.0, 1.0}; +static const GLfloat MaterialMagenta[] = {0.6, 0.2, 0.5, 1.0}; +static const GLfloat MaterialWhite[] = {0.7, 0.7, 0.7, 1.0}; +static const GLfloat MaterialGray[] = {0.5, 0.5, 0.5, 1.0}; + +static morph3dstruct *morph3d = (morph3dstruct *) NULL; + +#define TRIANGLE(Edge, Amp, Divisions, Z, VS) \ +{ \ + GLfloat Xf,Yf,Xa,Yb=0.0,Xf2=0.0,Yf2=0.0,Yf_2=0.0,Yb2,Yb_2; \ + GLfloat Factor=0.0,Factor1,Factor2; \ + GLfloat VertX,VertY,VertZ,NeiAX,NeiAY,NeiAZ,NeiBX,NeiBY,NeiBZ; \ + GLfloat Ax,Ay; \ + int Ri,Ti; \ + GLfloat Vr=(Edge)*SQRT3/3; \ + GLfloat AmpVr2=(Amp)/sqr(Vr); \ + GLfloat Zf=(Edge)*(Z); \ + \ + Ax=(Edge)*(+0.5/(Divisions)), Ay=(Edge)*(-SQRT3/(2*Divisions)); \ + \ + Yf=Vr+Ay; Yb=Yf+0.001; \ + for (Ri=1; Ri<=(Divisions); Ri++) { \ + glBegin(GL_TRIANGLE_STRIP); \ + Xf=(float)Ri*Ax; Xa=Xf+0.001; \ + Yf2=sqr(Yf); Yf_2=sqr(Yf-Ay); \ + Yb2=sqr(Yb); Yb_2=sqr(Yb-Ay); \ + for (Ti=0; Tipolygon_count++; \ + \ + Xf-=Ax; Yf-=Ay; Xa-=Ax; Yb-=Ay; \ + \ + Factor=1-(((Xf2=sqr(Xf))+Yf_2)*AmpVr2); \ + Factor1=1-((sqr(Xa)+Yf_2)*AmpVr2); \ + Factor2=1-((Xf2+Yb_2)*AmpVr2); \ + VertX=Factor*Xf; VertY=Factor*Yf; VertZ=Factor*Zf; \ + NeiAX=Factor1*Xa-VertX; NeiAY=Factor1*Yf-VertY; NeiAZ=Factor1*Zf-VertZ; \ + NeiBX=Factor2*Xf-VertX; NeiBY=Factor2*Yb-VertY; NeiBZ=Factor2*Zf-VertZ; \ + glNormal3f(VectMul(NeiAX, NeiAY, NeiAZ, NeiBX, NeiBY, NeiBZ)); \ + glVertex3f(VertX, VertY, VertZ); \ + mi->polygon_count++; \ + \ + Xf-=Ax; Yf+=Ay; Xa-=Ax; Yb+=Ay; \ + } \ + Factor=1-(((Xf2=sqr(Xf))+(Yf2=sqr(Yf)))*AmpVr2); \ + Factor1=1-((sqr(Xa)+Yf2)*AmpVr2); \ + Factor2=1-((Xf2+sqr(Yb))*AmpVr2); \ + VertX=Factor*Xf; VertY=Factor*Yf; VertZ=Factor*Zf; \ + NeiAX=Factor1*Xa-VertX; NeiAY=Factor1*Yf-VertY; NeiAZ=Factor1*Zf-VertZ; \ + NeiBX=Factor2*Xf-VertX; NeiBY=Factor2*Yb-VertY; NeiBZ=Factor2*Zf-VertZ; \ + glNormal3f(VectMul(NeiAX, NeiAY, NeiAZ, NeiBX, NeiBY, NeiBZ)); \ + glVertex3f(VertX, VertY, VertZ); \ + Yf+=Ay; Yb+=Ay; \ + glEnd(); \ + } \ + VS=(Factor<0); \ +} + +#define SQUARE(Edge, Amp, Divisions, Z, VS) \ +{ \ + int Xi,Yi; \ + GLfloat Xf,Yf,Y,Xf2,Yf2,Y2,Xa,Xa2,Yb; \ + GLfloat Factor=0.0,Factor1,Factor2; \ + GLfloat VertX,VertY,VertZ,NeiAX,NeiAY,NeiAZ,NeiBX,NeiBY,NeiBZ; \ + GLfloat Zf=(Edge)*(Z); \ + GLfloat AmpVr2=(Amp)/sqr((Edge)*SQRT2/2); \ + \ + for (Yi=0; Yi<(Divisions); Yi++) { \ + Yf=-((Edge)/2.0) + ((float)Yi)/(Divisions)*(Edge); \ + Yf2=sqr(Yf); \ + Y=Yf+1.0/(Divisions)*(Edge); \ + Y2=sqr(Y); \ + glBegin(GL_QUAD_STRIP); \ + for (Xi=0; Xi<=(Divisions); Xi++) { \ + Xf=-((Edge)/2.0) + ((float)Xi)/(Divisions)*(Edge); \ + Xf2=sqr(Xf); \ + \ + Xa=Xf+0.001; Yb=Y+0.001; \ + Factor=1-((Xf2+Y2)*AmpVr2); \ + Factor1=1-(((Xa2=sqr(Xa))+Y2)*AmpVr2); \ + Factor2=1-((Xf2+sqr(Yb))*AmpVr2); \ + VertX=Factor*Xf; VertY=Factor*Y; VertZ=Factor*Zf; \ + NeiAX=Factor1*Xa-VertX; NeiAY=Factor1*Y-VertY; NeiAZ=Factor1*Zf-VertZ; \ + NeiBX=Factor2*Xf-VertX; NeiBY=Factor2*Yb-VertY; NeiBZ=Factor2*Zf-VertZ; \ + glNormal3f(VectMul(NeiAX, NeiAY, NeiAZ, NeiBX, NeiBY, NeiBZ)); \ + glVertex3f(VertX, VertY, VertZ); \ + \ + Yb=Yf+0.001; \ + Factor=1-((Xf2+Yf2)*AmpVr2); \ + Factor1=1-((Xa2+Yf2)*AmpVr2); \ + Factor2=1-((Xf2+sqr(Yb))*AmpVr2); \ + VertX=Factor*Xf; VertY=Factor*Yf; VertZ=Factor*Zf; \ + NeiAX=Factor1*Xa-VertX; NeiAY=Factor1*Yf-VertY; NeiAZ=Factor1*Zf-VertZ; \ + NeiBX=Factor2*Xf-VertX; NeiBY=Factor2*Yb-VertY; NeiBZ=Factor2*Zf-VertZ; \ + glNormal3f(VectMul(NeiAX, NeiAY, NeiAZ, NeiBX, NeiBY, NeiBZ)); \ + glVertex3f(VertX, VertY, VertZ); \ + mi->polygon_count++; \ + } \ + glEnd(); \ + } \ + VS=(Factor<0); \ +} + +#define PENTAGON(Edge, Amp, Divisions, Z, VS) \ +{ \ + int Ri,Ti,Fi; \ + GLfloat Xf,Yf,Xa,Yb,Xf2,Yf2; \ + GLfloat Factor=0.0,Factor1,Factor2; \ + GLfloat VertX,VertY,VertZ,NeiAX,NeiAY,NeiAZ,NeiBX,NeiBY,NeiBZ; \ + GLfloat Zf=(Edge)*(Z); \ + GLfloat AmpVr2=(Amp)/sqr((Edge)*cossec36_2); \ + \ + GLfloat x[6],y[6]; \ + \ + for(Fi=0;Fi<6;Fi++) { \ + x[Fi]=-cos( Fi*2*Pi/5 + Pi/10 )/(Divisions)*cossec36_2*(Edge); \ + y[Fi]=sin( Fi*2*Pi/5 + Pi/10 )/(Divisions)*cossec36_2*(Edge); \ + } \ + \ + for (Ri=1; Ri<=(Divisions); Ri++) { \ + for (Fi=0; Fi<5; Fi++) { \ + glBegin(GL_TRIANGLE_STRIP); \ + for (Ti=0; Tipolygon_count++; \ + \ + Xf-=x[Fi]; Yf-=y[Fi]; Xa-=x[Fi]; Yb-=y[Fi]; \ + \ + Factor=1-(((Xf2=sqr(Xf))+(Yf2=sqr(Yf)))*AmpVr2); \ + Factor1=1-((sqr(Xa)+Yf2)*AmpVr2); \ + Factor2=1-((Xf2+sqr(Yb))*AmpVr2); \ + VertX=Factor*Xf; VertY=Factor*Yf; VertZ=Factor*Zf; \ + NeiAX=Factor1*Xa-VertX; NeiAY=Factor1*Yf-VertY; NeiAZ=Factor1*Zf-VertZ; \ + NeiBX=Factor2*Xf-VertX; NeiBY=Factor2*Yb-VertY; NeiBZ=Factor2*Zf-VertZ; \ + glNormal3f(VectMul(NeiAX, NeiAY, NeiAZ, NeiBX, NeiBY, NeiBZ)); \ + glVertex3f(VertX, VertY, VertZ); \ + mi->polygon_count++; \ + \ + } \ + Xf=(float)Ri*x[Fi+1]; \ + Yf=(float)Ri*y[Fi+1]; \ + Xa=Xf+0.001; Yb=Yf+0.001; \ + Factor=1-(((Xf2=sqr(Xf))+(Yf2=sqr(Yf)))*AmpVr2); \ + Factor1=1-((sqr(Xa)+Yf2)*AmpVr2); \ + Factor2=1-((Xf2+sqr(Yb))*AmpVr2); \ + VertX=Factor*Xf; VertY=Factor*Yf; VertZ=Factor*Zf; \ + NeiAX=Factor1*Xa-VertX; NeiAY=Factor1*Yf-VertY; NeiAZ=Factor1*Zf-VertZ; \ + NeiBX=Factor2*Xf-VertX; NeiBY=Factor2*Yb-VertY; NeiBZ=Factor2*Zf-VertZ; \ + glNormal3f(VectMul(NeiAX, NeiAY, NeiAZ, NeiBX, NeiBY, NeiBZ)); \ + glVertex3f(VertX, VertY, VertZ); \ + glEnd(); \ + } \ + } \ + VS=(Factor<0); \ +} + +static void +draw_tetra(ModeInfo * mi) +{ + morph3dstruct *mp = &morph3d[MI_SCREEN(mi)]; + + glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, mp->MaterialColor[0]); + + TRIANGLE(2, mp->seno, mp->edgedivisions, 0.5 / SQRT6, mp->VisibleSpikes); + + glPushMatrix(); + glRotatef(180, 0, 0, 1); + glRotatef(-tetraangle, 1, 0, 0); + glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, mp->MaterialColor[1]); + TRIANGLE(2, mp->seno, mp->edgedivisions, 0.5 / SQRT6, mp->VisibleSpikes); + glPopMatrix(); + glPushMatrix(); + glRotatef(180, 0, 1, 0); + glRotatef(-180 + tetraangle, 0.5, SQRT3 / 2, 0); + glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, mp->MaterialColor[2]); + TRIANGLE(2, mp->seno, mp->edgedivisions, 0.5 / SQRT6, mp->VisibleSpikes); + glPopMatrix(); + glRotatef(180, 0, 1, 0); + glRotatef(-180 + tetraangle, 0.5, -SQRT3 / 2, 0); + glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, mp->MaterialColor[3]); + TRIANGLE(2, mp->seno, mp->edgedivisions, 0.5 / SQRT6, mp->VisibleSpikes); +} + +static void +draw_cube(ModeInfo * mi) +{ + morph3dstruct *mp = &morph3d[MI_SCREEN(mi)]; + + glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, mp->MaterialColor[0]); + + SQUARE(2, mp->seno, mp->edgedivisions, 0.5, mp->VisibleSpikes) + + glRotatef(cubeangle, 1, 0, 0); + glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, mp->MaterialColor[1]); + SQUARE(2, mp->seno, mp->edgedivisions, 0.5, mp->VisibleSpikes) + glRotatef(cubeangle, 1, 0, 0); + glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, mp->MaterialColor[2]); + SQUARE(2, mp->seno, mp->edgedivisions, 0.5, mp->VisibleSpikes) + glRotatef(cubeangle, 1, 0, 0); + glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, mp->MaterialColor[3]); + SQUARE(2, mp->seno, mp->edgedivisions, 0.5, mp->VisibleSpikes) + glRotatef(cubeangle, 0, 1, 0); + glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, mp->MaterialColor[4]); + SQUARE(2, mp->seno, mp->edgedivisions, 0.5, mp->VisibleSpikes) + glRotatef(2 * cubeangle, 0, 1, 0); + glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, mp->MaterialColor[5]); + SQUARE(2, mp->seno, mp->edgedivisions, 0.5, mp->VisibleSpikes) +} + +static void +draw_octa(ModeInfo * mi) +{ + morph3dstruct *mp = &morph3d[MI_SCREEN(mi)]; + + glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, mp->MaterialColor[0]); + TRIANGLE(2, mp->seno, mp->edgedivisions, 1 / SQRT6, mp->VisibleSpikes); + + glPushMatrix(); + glRotatef(180, 0, 0, 1); + glRotatef(-180 + octaangle, 1, 0, 0); + glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, mp->MaterialColor[1]); + TRIANGLE(2, mp->seno, mp->edgedivisions, 1 / SQRT6, mp->VisibleSpikes); + glPopMatrix(); + glPushMatrix(); + glRotatef(180, 0, 1, 0); + glRotatef(-octaangle, 0.5, SQRT3 / 2, 0); + glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, mp->MaterialColor[2]); + TRIANGLE(2, mp->seno, mp->edgedivisions, 1 / SQRT6, mp->VisibleSpikes); + glPopMatrix(); + glPushMatrix(); + glRotatef(180, 0, 1, 0); + glRotatef(-octaangle, 0.5, -SQRT3 / 2, 0); + glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, mp->MaterialColor[3]); + TRIANGLE(2, mp->seno, mp->edgedivisions, 1 / SQRT6, mp->VisibleSpikes); + glPopMatrix(); + glRotatef(180, 1, 0, 0); + glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, mp->MaterialColor[4]); + TRIANGLE(2, mp->seno, mp->edgedivisions, 1 / SQRT6, mp->VisibleSpikes); + glPushMatrix(); + glRotatef(180, 0, 0, 1); + glRotatef(-180 + octaangle, 1, 0, 0); + glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, mp->MaterialColor[5]); + TRIANGLE(2, mp->seno, mp->edgedivisions, 1 / SQRT6, mp->VisibleSpikes); + glPopMatrix(); + glPushMatrix(); + glRotatef(180, 0, 1, 0); + glRotatef(-octaangle, 0.5, SQRT3 / 2, 0); + glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, mp->MaterialColor[6]); + TRIANGLE(2, mp->seno, mp->edgedivisions, 1 / SQRT6, mp->VisibleSpikes); + glPopMatrix(); + glRotatef(180, 0, 1, 0); + glRotatef(-octaangle, 0.5, -SQRT3 / 2, 0); + glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, mp->MaterialColor[7]); + TRIANGLE(2, mp->seno, mp->edgedivisions, 1 / SQRT6, mp->VisibleSpikes); +} + +static void +draw_dodeca(ModeInfo * mi) +{ + morph3dstruct *mp = &morph3d[MI_SCREEN(mi)]; + +#define TAU ((SQRT5+1)/2) + + glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, mp->MaterialColor[0]); + + PENTAGON(1, mp->seno, mp->edgedivisions, sqr(TAU) * sqrt((TAU + 2) / 5) / 2, mp->VisibleSpikes); + + glPushMatrix(); + glRotatef(180, 0, 0, 1); + glPushMatrix(); + glRotatef(-dodecaangle, 1, 0, 0); + glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, mp->MaterialColor[1]); + PENTAGON(1, mp->seno, mp->edgedivisions, sqr(TAU) * sqrt((TAU + 2) / 5) / 2, mp->VisibleSpikes); + glPopMatrix(); + glPushMatrix(); + glRotatef(-dodecaangle, cos72, sin72, 0); + glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, mp->MaterialColor[2]); + PENTAGON(1, mp->seno, mp->edgedivisions, sqr(TAU) * sqrt((TAU + 2) / 5) / 2, mp->VisibleSpikes); + glPopMatrix(); + glPushMatrix(); + glRotatef(-dodecaangle, cos72, -sin72, 0); + glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, mp->MaterialColor[3]); + PENTAGON(1, mp->seno, mp->edgedivisions, sqr(TAU) * sqrt((TAU + 2) / 5) / 2, mp->VisibleSpikes); + glPopMatrix(); + glPushMatrix(); + glRotatef(dodecaangle, cos36, -sin36, 0); + glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, mp->MaterialColor[4]); + PENTAGON(1, mp->seno, mp->edgedivisions, sqr(TAU) * sqrt((TAU + 2) / 5) / 2, mp->VisibleSpikes); + glPopMatrix(); + glRotatef(dodecaangle, cos36, sin36, 0); + glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, mp->MaterialColor[5]); + PENTAGON(1, mp->seno, mp->edgedivisions, sqr(TAU) * sqrt((TAU + 2) / 5) / 2, mp->VisibleSpikes); + glPopMatrix(); + glRotatef(180, 1, 0, 0); + glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, mp->MaterialColor[6]); + PENTAGON(1, mp->seno, mp->edgedivisions, sqr(TAU) * sqrt((TAU + 2) / 5) / 2, mp->VisibleSpikes); + glRotatef(180, 0, 0, 1); + glPushMatrix(); + glRotatef(-dodecaangle, 1, 0, 0); + glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, mp->MaterialColor[7]); + PENTAGON(1, mp->seno, mp->edgedivisions, sqr(TAU) * sqrt((TAU + 2) / 5) / 2, mp->VisibleSpikes); + glPopMatrix(); + glPushMatrix(); + glRotatef(-dodecaangle, cos72, sin72, 0); + glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, mp->MaterialColor[8]); + PENTAGON(1, mp->seno, mp->edgedivisions, sqr(TAU) * sqrt((TAU + 2) / 5) / 2, mp->VisibleSpikes); + glPopMatrix(); + glPushMatrix(); + glRotatef(-dodecaangle, cos72, -sin72, 0); + glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, mp->MaterialColor[9]); + PENTAGON(1, mp->seno, mp->edgedivisions, sqr(TAU) * sqrt((TAU + 2) / 5) / 2, mp->VisibleSpikes); + glPopMatrix(); + glPushMatrix(); + glRotatef(dodecaangle, cos36, -sin36, 0); + glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, mp->MaterialColor[10]); + PENTAGON(1, mp->seno, mp->edgedivisions, sqr(TAU) * sqrt((TAU + 2) / 5) / 2, mp->VisibleSpikes); + glPopMatrix(); + glRotatef(dodecaangle, cos36, sin36, 0); + glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, mp->MaterialColor[11]); + PENTAGON(1, mp->seno, mp->edgedivisions, sqr(TAU) * sqrt((TAU + 2) / 5) / 2, mp->VisibleSpikes); +} + +static void +draw_icosa(ModeInfo * mi) +{ + morph3dstruct *mp = &morph3d[MI_SCREEN(mi)]; + + glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, mp->MaterialColor[0]); + + TRIANGLE(1.5, mp->seno, mp->edgedivisions, (3 * SQRT3 + SQRT15) / 12, mp->VisibleSpikes); + + glPushMatrix(); + + glPushMatrix(); + glRotatef(180, 0, 0, 1); + glRotatef(-icoangle, 1, 0, 0); + glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, mp->MaterialColor[1]); + TRIANGLE(1.5, mp->seno, mp->edgedivisions, (3 * SQRT3 + SQRT15) / 12, mp->VisibleSpikes); + glPushMatrix(); + glRotatef(180, 0, 1, 0); + glRotatef(-180 + icoangle, 0.5, SQRT3 / 2, 0); + glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, mp->MaterialColor[2]); + TRIANGLE(1.5, mp->seno, mp->edgedivisions, (3 * SQRT3 + SQRT15) / 12, mp->VisibleSpikes); + glPopMatrix(); + glRotatef(180, 0, 1, 0); + glRotatef(-180 + icoangle, 0.5, -SQRT3 / 2, 0); + glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, mp->MaterialColor[3]); + TRIANGLE(1.5, mp->seno, mp->edgedivisions, (3 * SQRT3 + SQRT15) / 12, mp->VisibleSpikes); + glPopMatrix(); + glPushMatrix(); + glRotatef(180, 0, 1, 0); + glRotatef(-180 + icoangle, 0.5, SQRT3 / 2, 0); + glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, mp->MaterialColor[4]); + TRIANGLE(1.5, mp->seno, mp->edgedivisions, (3 * SQRT3 + SQRT15) / 12, mp->VisibleSpikes); + glPushMatrix(); + glRotatef(180, 0, 1, 0); + glRotatef(-180 + icoangle, 0.5, SQRT3 / 2, 0); + glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, mp->MaterialColor[5]); + TRIANGLE(1.5, mp->seno, mp->edgedivisions, (3 * SQRT3 + SQRT15) / 12, mp->VisibleSpikes); + glPopMatrix(); + glRotatef(180, 0, 0, 1); + glRotatef(-icoangle, 1, 0, 0); + glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, mp->MaterialColor[6]); + TRIANGLE(1.5, mp->seno, mp->edgedivisions, (3 * SQRT3 + SQRT15) / 12, mp->VisibleSpikes); + glPopMatrix(); + glRotatef(180, 0, 1, 0); + glRotatef(-180 + icoangle, 0.5, -SQRT3 / 2, 0); + glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, mp->MaterialColor[7]); + TRIANGLE(1.5, mp->seno, mp->edgedivisions, (3 * SQRT3 + SQRT15) / 12, mp->VisibleSpikes); + glPushMatrix(); + glRotatef(180, 0, 1, 0); + glRotatef(-180 + icoangle, 0.5, -SQRT3 / 2, 0); + glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, mp->MaterialColor[8]); + TRIANGLE(1.5, mp->seno, mp->edgedivisions, (3 * SQRT3 + SQRT15) / 12, mp->VisibleSpikes); + glPopMatrix(); + glRotatef(180, 0, 0, 1); + glRotatef(-icoangle, 1, 0, 0); + glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, mp->MaterialColor[9]); + TRIANGLE(1.5, mp->seno, mp->edgedivisions, (3 * SQRT3 + SQRT15) / 12, mp->VisibleSpikes); + glPopMatrix(); + glRotatef(180, 1, 0, 0); + glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, mp->MaterialColor[10]); + TRIANGLE(1.5, mp->seno, mp->edgedivisions, (3 * SQRT3 + SQRT15) / 12, mp->VisibleSpikes); + glPushMatrix(); + glRotatef(180, 0, 0, 1); + glRotatef(-icoangle, 1, 0, 0); + glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, mp->MaterialColor[11]); + TRIANGLE(1.5, mp->seno, mp->edgedivisions, (3 * SQRT3 + SQRT15) / 12, mp->VisibleSpikes); + glPushMatrix(); + glRotatef(180, 0, 1, 0); + glRotatef(-180 + icoangle, 0.5, SQRT3 / 2, 0); + glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, mp->MaterialColor[12]); + TRIANGLE(1.5, mp->seno, mp->edgedivisions, (3 * SQRT3 + SQRT15) / 12, mp->VisibleSpikes); + glPopMatrix(); + glRotatef(180, 0, 1, 0); + glRotatef(-180 + icoangle, 0.5, -SQRT3 / 2, 0); + glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, mp->MaterialColor[13]); + TRIANGLE(1.5, mp->seno, mp->edgedivisions, (3 * SQRT3 + SQRT15) / 12, mp->VisibleSpikes); + glPopMatrix(); + glPushMatrix(); + glRotatef(180, 0, 1, 0); + glRotatef(-180 + icoangle, 0.5, SQRT3 / 2, 0); + glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, mp->MaterialColor[14]); + TRIANGLE(1.5, mp->seno, mp->edgedivisions, (3 * SQRT3 + SQRT15) / 12, mp->VisibleSpikes); + glPushMatrix(); + glRotatef(180, 0, 1, 0); + glRotatef(-180 + icoangle, 0.5, SQRT3 / 2, 0); + glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, mp->MaterialColor[15]); + TRIANGLE(1.5, mp->seno, mp->edgedivisions, (3 * SQRT3 + SQRT15) / 12, mp->VisibleSpikes); + glPopMatrix(); + glRotatef(180, 0, 0, 1); + glRotatef(-icoangle, 1, 0, 0); + glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, mp->MaterialColor[16]); + TRIANGLE(1.5, mp->seno, mp->edgedivisions, (3 * SQRT3 + SQRT15) / 12, mp->VisibleSpikes); + glPopMatrix(); + glRotatef(180, 0, 1, 0); + glRotatef(-180 + icoangle, 0.5, -SQRT3 / 2, 0); + glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, mp->MaterialColor[17]); + TRIANGLE(1.5, mp->seno, mp->edgedivisions, (3 * SQRT3 + SQRT15) / 12, mp->VisibleSpikes); + glPushMatrix(); + glRotatef(180, 0, 1, 0); + glRotatef(-180 + icoangle, 0.5, -SQRT3 / 2, 0); + glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, mp->MaterialColor[18]); + TRIANGLE(1.5, mp->seno, mp->edgedivisions, (3 * SQRT3 + SQRT15) / 12, mp->VisibleSpikes); + glPopMatrix(); + glRotatef(180, 0, 0, 1); + glRotatef(-icoangle, 1, 0, 0); + glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, mp->MaterialColor[19]); + TRIANGLE(1.5, mp->seno, mp->edgedivisions, (3 * SQRT3 + SQRT15) / 12, mp->VisibleSpikes); +} + +ENTRYPOINT void +reshape_morph3d(ModeInfo * mi, int width, int height) +{ + morph3dstruct *mp = &morph3d[MI_SCREEN(mi)]; + + glViewport(0, 0, mp->WindW = (GLint) width, mp->WindH = (GLint) height); + glMatrixMode(GL_PROJECTION); + glLoadIdentity(); + glFrustum(-1.0, 1.0, -1.0, 1.0, 5.0, 15.0); + glMatrixMode(GL_MODELVIEW); +} + +static void +pinit(ModeInfo * mi) +{ + morph3dstruct *mp = &morph3d[MI_SCREEN(mi)]; + + glClearDepth(1.0); + glColor3f(1.0, 1.0, 1.0); + + glLightfv(GL_LIGHT0, GL_AMBIENT, ambient); + glLightfv(GL_LIGHT0, GL_DIFFUSE, diffuse); + glLightfv(GL_LIGHT0, GL_POSITION, position0); + glLightfv(GL_LIGHT1, GL_AMBIENT, ambient); + glLightfv(GL_LIGHT1, GL_DIFFUSE, diffuse); + glLightfv(GL_LIGHT1, GL_POSITION, position1); + glLightModelfv(GL_LIGHT_MODEL_AMBIENT, lmodel_ambient); + glLightModelfv(GL_LIGHT_MODEL_TWO_SIDE, lmodel_twoside); + glEnable(GL_LIGHTING); + glEnable(GL_LIGHT0); + glEnable(GL_LIGHT1); + glEnable(GL_DEPTH_TEST); + glEnable(GL_NORMALIZE); + + glShadeModel(GL_SMOOTH); + glMaterialfv(GL_FRONT_AND_BACK, GL_SHININESS, front_shininess); + glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, front_specular); + + switch (mp->object) { + case 2: + mp->draw_object = draw_cube; + mp->MaterialColor[0] = MaterialRed; + mp->MaterialColor[1] = MaterialGreen; + mp->MaterialColor[2] = MaterialCyan; + mp->MaterialColor[3] = MaterialMagenta; + mp->MaterialColor[4] = MaterialYellow; + mp->MaterialColor[5] = MaterialBlue; + mp->edgedivisions = cubedivisions; + mp->Magnitude = 2.0; + break; + case 3: + mp->draw_object = draw_octa; + mp->MaterialColor[0] = MaterialRed; + mp->MaterialColor[1] = MaterialGreen; + mp->MaterialColor[2] = MaterialBlue; + mp->MaterialColor[3] = MaterialWhite; + mp->MaterialColor[4] = MaterialCyan; + mp->MaterialColor[5] = MaterialMagenta; + mp->MaterialColor[6] = MaterialGray; + mp->MaterialColor[7] = MaterialYellow; + mp->edgedivisions = octadivisions; + mp->Magnitude = 2.5; + break; + case 4: + mp->draw_object = draw_dodeca; + mp->MaterialColor[0] = MaterialRed; + mp->MaterialColor[1] = MaterialGreen; + mp->MaterialColor[2] = MaterialCyan; + mp->MaterialColor[3] = MaterialBlue; + mp->MaterialColor[4] = MaterialMagenta; + mp->MaterialColor[5] = MaterialYellow; + mp->MaterialColor[6] = MaterialGreen; + mp->MaterialColor[7] = MaterialCyan; + mp->MaterialColor[8] = MaterialRed; + mp->MaterialColor[9] = MaterialMagenta; + mp->MaterialColor[10] = MaterialBlue; + mp->MaterialColor[11] = MaterialYellow; + mp->edgedivisions = dodecadivisions; + mp->Magnitude = 2.0; + break; + case 5: + mp->draw_object = draw_icosa; + mp->MaterialColor[0] = MaterialRed; + mp->MaterialColor[1] = MaterialGreen; + mp->MaterialColor[2] = MaterialBlue; + mp->MaterialColor[3] = MaterialCyan; + mp->MaterialColor[4] = MaterialYellow; + mp->MaterialColor[5] = MaterialMagenta; + mp->MaterialColor[6] = MaterialRed; + mp->MaterialColor[7] = MaterialGreen; + mp->MaterialColor[8] = MaterialBlue; + mp->MaterialColor[9] = MaterialWhite; + mp->MaterialColor[10] = MaterialCyan; + mp->MaterialColor[11] = MaterialYellow; + mp->MaterialColor[12] = MaterialMagenta; + mp->MaterialColor[13] = MaterialRed; + mp->MaterialColor[14] = MaterialGreen; + mp->MaterialColor[15] = MaterialBlue; + mp->MaterialColor[16] = MaterialCyan; + mp->MaterialColor[17] = MaterialYellow; + mp->MaterialColor[18] = MaterialMagenta; + mp->MaterialColor[19] = MaterialGray; + mp->edgedivisions = icodivisions; + mp->Magnitude = 2.5; + break; + default: + mp->draw_object = draw_tetra; + mp->MaterialColor[0] = MaterialRed; + mp->MaterialColor[1] = MaterialGreen; + mp->MaterialColor[2] = MaterialBlue; + mp->MaterialColor[3] = MaterialWhite; + mp->edgedivisions = tetradivisions; + mp->Magnitude = 2.5; + break; + } + if (MI_IS_MONO(mi)) { + int loop; + + for (loop = 0; loop < 20; loop++) + mp->MaterialColor[loop] = MaterialGray; + } +} + +ENTRYPOINT void +init_morph3d(ModeInfo * mi) +{ + morph3dstruct *mp; + + if (morph3d == NULL) { + if ((morph3d = (morph3dstruct *) calloc(MI_NUM_SCREENS(mi), + sizeof (morph3dstruct))) == NULL) + return; + } + mp = &morph3d[MI_SCREEN(mi)]; + mp->step = NRAND(90); + mp->VisibleSpikes = 1; + + if ((mp->glx_context = init_GL(mi)) != NULL) { + + reshape_morph3d(mi, MI_WIDTH(mi), MI_HEIGHT(mi)); + glDrawBuffer(GL_BACK); + mp->object = MI_COUNT(mi); + if (mp->object <= 0 || mp->object > 5) + mp->object = NRAND(5) + 1; + pinit(mi); + } else { + MI_CLEARWINDOW(mi); + } +} + +ENTRYPOINT void +draw_morph3d(ModeInfo * mi) +{ + Display *display = MI_DISPLAY(mi); + Window window = MI_WINDOW(mi); + morph3dstruct *mp; + + if (morph3d == NULL) + return; + mp = &morph3d[MI_SCREEN(mi)]; + + MI_IS_DRAWN(mi) = True; + + if (!mp->glx_context) + return; + + mi->polygon_count = 0; + glXMakeCurrent(display, window, *(mp->glx_context)); + + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + + glPushMatrix(); + + glTranslatef(0.0, 0.0, -10.0); + + if (!MI_IS_ICONIC(mi)) { + glScalef(Scale4Window * mp->WindH / mp->WindW, Scale4Window, Scale4Window); + glTranslatef(2.5 * mp->WindW / mp->WindH * sin(mp->step * 1.11), 2.5 * cos(mp->step * 1.25 * 1.11), 0); + } else { + glScalef(Scale4Iconic * mp->WindH / mp->WindW, Scale4Iconic, Scale4Iconic); + } + + glRotatef(mp->step * 100, 1, 0, 0); + glRotatef(mp->step * 95, 0, 1, 0); + glRotatef(mp->step * 90, 0, 0, 1); + + mp->seno = (sin(mp->step) + 1.0 / 3.0) * (4.0 / 5.0) * mp->Magnitude; + + if (mp->VisibleSpikes) { +#ifdef DEBUG_CULL_FACE + int loop; + + for (loop = 0; loop < 20; loop++) + mp->MaterialColor[loop] = MaterialGray; +#endif + glDisable(GL_CULL_FACE); + } else { +#ifdef DEBUG_CULL_FACE + int loop; + + for (loop = 0; loop < 20; loop++) + mp->MaterialColor[loop] = MaterialWhite; +#endif + glEnable(GL_CULL_FACE); + } + + mp->draw_object(mi); + + glPopMatrix(); + + if (MI_IS_FPS(mi)) do_fps (mi); + glXSwapBuffers(display, window); + + mp->step += 0.05; +} + +#ifndef STANDALONE +ENTRYPOINT void +change_morph3d(ModeInfo * mi) +{ + morph3dstruct *mp = &morph3d[MI_SCREEN(mi)]; + + if (!mp->glx_context) + return; + + mp->object = (mp->object) % 5 + 1; + pinit(mi); +} +#endif /* !STANDALONE */ + +ENTRYPOINT void +release_morph3d(ModeInfo * mi) +{ + if (morph3d != NULL) { + (void) free((void *) morph3d); + morph3d = (morph3dstruct *) NULL; + } + FreeAllGL(mi); +} + +#endif + +XSCREENSAVER_MODULE ("Morph3D", morph3d) diff --git a/hacks/glx/morph3d.man b/hacks/glx/morph3d.man new file mode 100644 index 00000000..21af78c6 --- /dev/null +++ b/hacks/glx/morph3d.man @@ -0,0 +1,57 @@ +.TH XScreenSaver 1 "" "X Version 11" +.SH NAME +morph3d - 3d morphing objects. +.SH SYNOPSIS +.B morph3d +[\-display \fIhost:display.screen\fP] +[\-visual \fIvisual\fP] +[\-window] +[\-root] +[\-count \fInumber\fP] +[\-delay \fInumber\fP] +[\-fps] +.SH DESCRIPTION +Another 3d shape-changing GL hack. It has the same shiny-plastic feel +as Superquadrics, as many computer-generated objects do... +.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 \-count \fInumber\fP +0 - 20. Default: 0. +.TP 8 +.B \-delay \fInumber\fP +Per-frame delay, in microseconds. Default: 40000 (0.04 seconds.). +.TP 8 +.B \-fps +Display the current frame rate, CPU load, and polygon count. +.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 2002 by Marcelo Vianna. 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 +Marcelo Vianna. diff --git a/hacks/glx/noof.c b/hacks/glx/noof.c new file mode 100644 index 00000000..ee2810b3 --- /dev/null +++ b/hacks/glx/noof.c @@ -0,0 +1,477 @@ +/* noof, Copyright (c) 2004 Bill Torzewski + * + * 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. + * + * Originally a demo included with GLUT; + * (Apparently this was called "diatoms" on Irix.) + * ported to raw GL and xscreensaver by jwz, 12-Feb-2004. + */ + +#define DEFAULTS "*delay: 10000 \n" \ + "*showFPS: False \n" \ + "*fpsSolid: True \n" \ + "*doubleBuffer: False \n" \ + +# define refresh_noof 0 +# define release_noof 0 +# define noof_handle_event 0 +#include "xlockmore.h" + +#ifdef USE_GL /* whole file */ + +#define N_SHAPES 7 + +/* For some reason this hack screws up on Cocoa if we try to double-buffer it. + It looks fine single-buffered, so let's just do that. */ +static int dbuf_p = 0; + +ENTRYPOINT ModeSpecOpt noof_opts = {0, NULL, 0, NULL, NULL}; + +typedef struct { + GLXContext *glx_context; + + float pos[N_SHAPES * 3]; + float dir[N_SHAPES * 3]; + float acc[N_SHAPES * 3]; + float col[N_SHAPES * 3]; + float hsv[N_SHAPES * 3]; + float hpr[N_SHAPES * 3]; + float ang[N_SHAPES]; + float spn[N_SHAPES]; + float sca[N_SHAPES]; + float geep[N_SHAPES]; + float peep[N_SHAPES]; + float speedsq[N_SHAPES]; + int blad[N_SHAPES]; + + float ht, wd; + + int tko; + +} noof_configuration; + +static noof_configuration *bps = NULL; + + +static void +initshapes(noof_configuration *bp, int i) +{ + int k; + float f; + + /* random init of pos, dir, color */ + for (k = i * 3; k <= i * 3 + 2; k++) { + f = random() / (double) RAND_MAX; + bp->pos[k] = f; + f = random() / (double) RAND_MAX; + f = (f - 0.5) * 0.05; + bp->dir[k] = f; + f = random() / (double) RAND_MAX; + f = (f - 0.5) * 0.0002; + bp->acc[k] = f; + f = random() / (double) RAND_MAX; + bp->col[k] = f; + } + + bp->speedsq[i] = bp->dir[i * 3] * bp->dir[i * 3] + bp->dir[i * 3 + 1] * bp->dir[i * 3 + 1]; + f = random() / (double) RAND_MAX; + bp->blad[i] = 2 + (int) (f * 17.0); + f = random() / (double) RAND_MAX; + bp->ang[i] = f; + f = random() / (double) RAND_MAX; + bp->spn[i] = (f - 0.5) * 40.0 / (10 + bp->blad[i]); + f = random() / (double) RAND_MAX; + bp->sca[i] = (f * 0.1 + 0.08); + bp->dir[i * 3] *= bp->sca[i]; + bp->dir[i * 3 + 1] *= bp->sca[i]; + + f = random() / (double) RAND_MAX; + bp->hsv[i * 3] = f * 360.0; + + f = random() / (double) RAND_MAX; + bp->hsv[i * 3 + 1] = f * 0.6 + 0.4; + + f = random() / (double) RAND_MAX; + bp->hsv[i * 3 + 2] = f * 0.7 + 0.3; + + f = random() / (double) RAND_MAX; + bp->hpr[i * 3] = f * 0.005 * 360.0; + f = random() / (double) RAND_MAX; + bp->hpr[i * 3 + 1] = f * 0.03; + f = random() / (double) RAND_MAX; + bp->hpr[i * 3 + 2] = f * 0.02; + + bp->geep[i] = 0; + f = random() / (double) RAND_MAX; + bp->peep[i] = 0.01 + f * 0.2; +} + +static const float bladeratio[] = +{ + /* nblades = 2..7 */ + 0.0, 0.0, 3.00000, 1.73205, 1.00000, 0.72654, 0.57735, 0.48157, + /* 8..13 */ + 0.41421, 0.36397, 0.19076, 0.29363, 0.26795, 0.24648, + /* 14..19 */ + 0.22824, 0.21256, 0.19891, 0.18693, 0.17633, 0.16687, +}; + +static int +drawleaf(noof_configuration *bp, int l) +{ + int polys = 0; + int b, blades; + float x, y; + float wobble; + + blades = bp->blad[l]; + + y = 0.10 * sin(bp->geep[l] * M_PI / 180.0) + 0.099 * sin(bp->geep[l] * 5.12 * M_PI / 180.0); + if (y < 0) + y = -y; + x = 0.15 * cos(bp->geep[l] * M_PI / 180.0) + 0.149 * cos(bp->geep[l] * 5.12 * M_PI / 180.0); + if (x < 0.0) + x = 0.0 - x; + if (y < 0.001 && x > 0.000002 && ((bp->tko & 0x1) == 0)) { + initshapes(bp, l); /* let it become reborn as something + else */ + bp->tko++; + return polys; + } { + float w1 = sin(bp->geep[l] * 15.3 * M_PI / 180.0); + wobble = 3.0 + 2.00 * sin(bp->geep[l] * 0.4 * M_PI / 180.0) + 3.94261 * w1; + } + + /** + if(blades == 2) if (y > 3.000*x) y = x*3.000; + if(blades == 3) if (y > 1.732*x) y = x*1.732; + if(blades == 4) if (y > x) y = x; + if(blades == 5) if (y > 0.726*x) y = x*0.726; + if(blades == 6) if (y > 0.577*x) y = x*0.577; + if(blades == 7) if (y > 0.481*x) y = x*0.481; + if(blades == 8) if (y > 0.414*x) y = x*0.414; + */ + if (y > x * bladeratio[blades]) + y = x * bladeratio[blades]; + + for (b = 0; b < blades; b++) { + glPushMatrix(); + glTranslatef(bp->pos[l * 3], bp->pos[l * 3 + 1], bp->pos[l * 3 + 2]); + glRotatef(bp->ang[l] + b * (360.0 / blades), 0.0, 0.0, 1.0); + glScalef(wobble * bp->sca[l], wobble * bp->sca[l], wobble * bp->sca[l]); + /** + if(tko & 0x40000) glColor3f(col[l*3], col[l*3+1], col[l*3+2]); + else + */ + glColor4ub(0, 0, 0, 0x60); + + /* constrain geep cooridinates here XXX */ + glEnable(GL_BLEND); + + glBegin(GL_TRIANGLE_STRIP); + glVertex2f(x * bp->sca[l], 0.0); + glVertex2f(x, y); + glVertex2f(x, -y); /* C */ + glVertex2f(0.3, 0.0); /* D */ + polys += 2; + glEnd(); + + /** + if(tko++ & 0x40000) glColor3f(0,0,0); + else + */ + glColor3f(bp->col[l * 3], bp->col[l * 3 + 1], bp->col[l * 3 + 2]); + glBegin(GL_LINE_LOOP); + glVertex2f(x * bp->sca[l], 0.0); + glVertex2f(x, y); + glVertex2f(0.3, 0.0); /* D */ + glVertex2f(x, -y); /* C */ + polys += 3; + glEnd(); + glDisable(GL_BLEND); + + glPopMatrix(); + } + return polys; +} + +static void +motionUpdate(noof_configuration *bp, int t) +{ + if (bp->pos[t * 3] < -bp->sca[t] * bp->wd && bp->dir[t * 3] < 0.0) { + bp->dir[t * 3] = -bp->dir[t * 3]; + /** + acc[t*3+1] += 0.8*acc[t*3]; + acc[t*3] = -0.8*acc[t*3]; + */ + } else if (bp->pos[t * 3] > (1 + bp->sca[t]) * bp->wd && bp->dir[t * 3] > 0.0) { + bp->dir[t * 3] = -bp->dir[t * 3]; + /** + acc[t*3+1] += 0.8*acc[t*3]; + acc[t*3] = -0.8*acc[t*3]; + */ + } else if (bp->pos[t * 3 + 1] < -bp->sca[t] * bp->ht && bp->dir[t * 3 + 1] < 0.0) { + bp->dir[t * 3 + 1] = -bp->dir[t * 3 + 1]; + /** + acc[t*3] += 0.8*acc[t*3+1]; + acc[t*3+1] = -0.8*acc[t*3+1]; + */ + } else if (bp->pos[t * 3 + 1] > (1 + bp->sca[t]) * bp->ht && bp->dir[t * 3 + 1] > 0.0) { + bp->dir[t * 3 + 1] = -bp->dir[t * 3 + 1]; + /** + acc[t*3] += 0.8*acc[t*3+1]; + acc[t*3+1] = -0.8*acc[t*3+1]; + */ + } + + bp->pos[t * 3] += bp->dir[t * 3]; + bp->pos[t * 3 + 1] += bp->dir[t * 3 + 1]; + /** + dir[t*3] += acc[t*3]; + dir[t*3+1] += acc[t*3+1]; + */ + bp->ang[t] += bp->spn[t]; + bp->geep[t] += bp->peep[t]; + if (bp->geep[t] > 360 * 5.0) + bp->geep[t] -= 360 * 5.0; + if (bp->ang[t] < 0.0) { + bp->ang[t] += 360.0; + } + if (bp->ang[t] > 360.0) { + bp->ang[t] -= 360.0; + } +} + +static void +colorUpdate(noof_configuration *bp, int i) +{ + if (bp->hsv[i * 3 + 1] <= 0.5 && bp->hpr[i * 3 + 1] < 0.0) + bp->hpr[i * 3 + 1] = -bp->hpr[i * 3 + 1]; /* adjust s */ + if (bp->hsv[i * 3 + 1] >= 1.0 && bp->hpr[i * 3 + 1] > 0.0) + bp->hpr[i * 3 + 1] = -bp->hpr[i * 3 + 1]; /* adjust s */ + if (bp->hsv[i * 3 + 2] <= 0.4 && bp->hpr[i * 3 + 2] < 0.0) + bp->hpr[i * 3 + 2] = -bp->hpr[i * 3 + 2]; /* adjust s */ + if (bp->hsv[i * 3 + 2] >= 1.0 && bp->hpr[i * 3 + 2] > 0.0) + bp->hpr[i * 3 + 2] = -bp->hpr[i * 3 + 2]; /* adjust s */ + + bp->hsv[i * 3] += bp->hpr[i * 3]; + bp->hsv[i * 3 + 1] += bp->hpr[i * 3 + 1]; + bp->hsv[i * 3 + 2] += bp->hpr[i * 3 + 2]; + + /* --- hsv -> rgb --- */ +#define H(hhh) hhh[i*3 ] +#define S(hhh) hhh[i*3+1] +#define V(hhh) hhh[i*3+2] + +#define R(hhh) hhh[i*3 ] +#define G(hhh) hhh[i*3+1] +#define B(hhh) hhh[i*3+2] + + if (V(bp->hsv) < 0.0) + V(bp->hsv) = 0.0; + if (V(bp->hsv) > 1.0) + V(bp->hsv) = 1.0; + if (S(bp->hsv) <= 0.0) { + R(bp->col) = V(bp->hsv); + G(bp->col) = V(bp->hsv); + B(bp->col) = V(bp->hsv); + } else { + float f, h, p, q, t, v; + int hi; + + while (H(bp->hsv) < 0.0) + H(bp->hsv) += 360.0; + while (H(bp->hsv) >= 360.0) + H(bp->hsv) -= 360.0; + + if (S(bp->hsv) < 0.0) + S(bp->hsv) = 0.0; + if (S(bp->hsv) > 1.0) + S(bp->hsv) = 1.0; + + h = H(bp->hsv) / 60.0; + hi = (int) (h); + f = h - hi; + v = V(bp->hsv); + p = V(bp->hsv) * (1 - S(bp->hsv)); + q = V(bp->hsv) * (1 - S(bp->hsv) * f); + t = V(bp->hsv) * (1 - S(bp->hsv) * (1 - f)); + + if (hi <= 0) { + R(bp->col) = v; + G(bp->col) = t; + B(bp->col) = p; + } else if (hi == 1) { + R(bp->col) = q; + G(bp->col) = v; + B(bp->col) = p; + } else if (hi == 2) { + R(bp->col) = p; + G(bp->col) = v; + B(bp->col) = t; + } else if (hi == 3) { + R(bp->col) = p; + G(bp->col) = q; + B(bp->col) = v; + } else if (hi == 4) { + R(bp->col) = t; + G(bp->col) = p; + B(bp->col) = v; + } else { + R(bp->col) = v; + G(bp->col) = p; + B(bp->col) = q; + } + } +} + +static void +gravity(noof_configuration *bp, float fx) +{ + int a, b; + + for (a = 0; a < N_SHAPES; a++) { + for (b = 0; b < a; b++) { + float t, d2; + + t = bp->pos[b * 3] - bp->pos[a * 3]; + d2 = t * t; + t = bp->pos[b * 3 + 1] - bp->pos[a * 3 + 1]; + d2 += t * t; + if (d2 < 0.000001) + d2 = 0.00001; + if (d2 < 0.1) { + + float v0, v1, z; + v0 = bp->pos[b * 3] - bp->pos[a * 3]; + v1 = bp->pos[b * 3 + 1] - bp->pos[a * 3 + 1]; + + z = 0.00000001 * fx / (d2); + + bp->dir[a * 3] += v0 * z * bp->sca[b]; + bp->dir[b * 3] += -v0 * z * bp->sca[a]; + bp->dir[a * 3 + 1] += v1 * z * bp->sca[b]; + bp->dir[b * 3 + 1] += -v1 * z * bp->sca[a]; + + } + } + /** apply brakes + if(dir[a*3]*dir[a*3] + dir[a*3+1]*dir[a*3+1] + > 0.0001) { + dir[a*3] *= 0.9; + dir[a*3+1] *= 0.9; + } + */ + } +} + +ENTRYPOINT void +draw_noof (ModeInfo *mi) +{ + int i; + noof_configuration *bp = &bps[MI_SCREEN(mi)]; + + if (!bp->glx_context) + return; + glXMakeCurrent(MI_DISPLAY(mi), MI_WINDOW(mi), *(bp->glx_context)); + mi->polygon_count = 0; + + /** + if((random() & 0xff) == 0x34){ + glClear(GL_COLOR_BUFFER_BIT); + } + + if((tko & 0x1f) == 0x1f){ + glEnable(GL_BLEND); + glColor4f(0.0, 0.0, 0.0, 0.09); + glRectf(0.0, 0.0, wd, ht); + glDisable(GL_BLEND); +#ifdef __sgi + sginap(0); +#endif + } + */ + + gravity(bp, -2.0); + for (i = 0; i < N_SHAPES; i++) { + motionUpdate(bp, i); + colorUpdate(bp, i); + mi->polygon_count += drawleaf(bp, i); + } + + if (mi->fps_p) do_fps (mi); + glFinish(); + + if (dbuf_p) + glXSwapBuffers(MI_DISPLAY(mi), MI_WINDOW(mi)); +} + + +ENTRYPOINT void +reshape_noof(ModeInfo *mi, int w, int h) +{ + noof_configuration *bp = &bps[MI_SCREEN(mi)]; + glViewport(0, 0, w, h); + glMatrixMode(GL_PROJECTION); + glLoadIdentity(); + if (w <= h) { + bp->wd = 1.0; + bp->ht = (GLfloat) h / (GLfloat) w; + glOrtho(0.0, 1.0, + 0.0, 1.0 * (GLfloat) h / (GLfloat) w, + -16.0, 4.0); + } else { + bp->wd = (GLfloat) w / (GLfloat) h; + bp->ht = 1.0; + glOrtho(0.0, 1.0 * (GLfloat) w / (GLfloat) h, + 0.0, 1.0, + -16.0, 4.0); + } + glMatrixMode(GL_MODELVIEW); + glLoadIdentity(); + + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); +} + +ENTRYPOINT void +init_noof (ModeInfo *mi) +{ + int i; + noof_configuration *bp; + +#ifdef HAVE_JWZGLES + dbuf_p = 1; +#endif + + if (!bps) { + bps = (noof_configuration *) + calloc (MI_NUM_SCREENS(mi), sizeof (noof_configuration)); + if (!bps) { + fprintf(stderr, "%s: out of memory\n", progname); + exit(1); + } + } + + bp = &bps[MI_SCREEN(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)); +} + + +XSCREENSAVER_MODULE ("Noof", noof) + +#endif /* USE_GL */ diff --git a/hacks/glx/noof.man b/hacks/glx/noof.man new file mode 100644 index 00000000..f4145712 --- /dev/null +++ b/hacks/glx/noof.man @@ -0,0 +1,52 @@ +.TH XScreenSaver 1 "" "X Version 11" +.SH NAME +noof - draw rotatey patterns +.SH SYNOPSIS +.B dangerball +[\-display \fIhost:display.screen\fP] +[\-visual \fIvisual\fP] +[\-window] +[\-root] +[\-delay \fInumber\fP] +[\-fps] +.SH DESCRIPTION +Draws some rotatey patterns, using OpenGL. +.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: 10000 (0.01 seconds.). +.TP 8 +.B \-fps +Display the current frame rate, CPU load, and polygon count. +.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 2004 by Mark Kilgard. 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 +Mark Kilgard diff --git a/hacks/glx/normals.c b/hacks/glx/normals.c new file mode 100644 index 00000000..16b90401 --- /dev/null +++ b/hacks/glx/normals.c @@ -0,0 +1,52 @@ +/* normals, Copyright (c) 2002-2004 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. + * + * Compute normal vectors for arbitrary triangles. + */ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include "normals.h" + +/* Calculate the unit normal at p given two other points p1,p2 on the + surface. The normal points in the direction of p1 crossproduct p2 + */ +XYZ +calc_normal (XYZ p, XYZ p1, XYZ p2) +{ + XYZ n, pa, pb; + pa.x = p1.x - p.x; + pa.y = p1.y - p.y; + pa.z = p1.z - p.z; + pb.x = p2.x - p.x; + pb.y = p2.y - p.y; + pb.z = p2.z - p.z; + n.x = pa.y * pb.z - pa.z * pb.y; + n.y = pa.z * pb.x - pa.x * pb.z; + n.z = pa.x * pb.y - pa.y * pb.x; + return (n); +} + +/* Call glNormal3f() with a normal of the indicated triangle. + */ +void +do_normal(GLfloat x1, GLfloat y1, GLfloat z1, + GLfloat x2, GLfloat y2, GLfloat z2, + GLfloat x3, GLfloat y3, GLfloat z3) +{ + XYZ p1, p2, p3, p; + p1.x = x1; p1.y = y1; p1.z = z1; + p2.x = x2; p2.y = y2; p2.z = z2; + p3.x = x3; p3.y = y3; p3.z = z3; + p = calc_normal (p1, p2, p3); + glNormal3f (p.x, p.y, p.z); +} diff --git a/hacks/glx/normals.h b/hacks/glx/normals.h new file mode 100644 index 00000000..a707a0c9 --- /dev/null +++ b/hacks/glx/normals.h @@ -0,0 +1,44 @@ +/* normals, Copyright (c) 2002-2012 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. + * + * Compute normal vectors for arbitrary triangles. + */ + +#ifndef __NORMALS_H__ +#define __NORMALS_H__ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif /* HAVE_CONFIG_H */ + +#ifndef HAVE_COCOA +# include +#endif + +#ifdef HAVE_JWZGLES +# include "jwzgles.h" +#endif /* HAVE_JWZGLES */ + +typedef struct { + double x,y,z; +} XYZ; + +/* Calculate the unit normal at p given two other points p1,p2 on the + surface. The normal points in the direction of p1 crossproduct p2 + */ +extern XYZ calc_normal (XYZ p, XYZ p1, XYZ p2); + +/* Call glNormal3f() with a normal of the indicated triangle. + */ +extern void do_normal (GLfloat x1, GLfloat y1, GLfloat z1, + GLfloat x2, GLfloat y2, GLfloat z2, + GLfloat x3, GLfloat y3, GLfloat z3); + +#endif /* __NORMALS_H__ */ diff --git a/hacks/glx/photopile.c b/hacks/glx/photopile.c new file mode 100644 index 00000000..aa52d162 --- /dev/null +++ b/hacks/glx/photopile.c @@ -0,0 +1,785 @@ +/* photopile, Copyright (c) 2008-2012 Jens Kilian + * Based on carousel, Copyright (c) 2005-2008 Jamie Zawinski + * Loads a sequence of images and shuffles them into a pile. + * + * 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. + */ + +#define DEF_FONT "-*-helvetica-bold-r-normal-*-240-*" +#define DEFAULTS "*count: 7 \n" \ + "*delay: 10000 \n" \ + "*wireframe: False \n" \ + "*showFPS: False \n" \ + "*fpsSolid: True \n" \ + "*useSHM: True \n" \ + "*font: " DEF_FONT "\n" \ + "*desktopGrabber: xscreensaver-getimage -no-desktop %s\n" \ + "*grabDesktopImages: False \n" \ + "*chooseRandomImages: True \n" + +# define refresh_photopile 0 +# define release_photopile 0 +# define photopile_handle_event 0 + +#undef countof +#define countof(x) (sizeof((x))/sizeof((*x))) + +#ifndef HAVE_COCOA +# include /* for XrmDatabase in -debug mode */ +#endif +#include + +#include "xlockmore.h" +#include "grab-ximage.h" +#include "texfont.h" +#include "dropshadow.h" + +#ifdef USE_GL + +# define DEF_SCALE "0.4" +# define DEF_MAX_TILT "50" +# define DEF_SPEED "1.0" +# define DEF_DURATION "5" +# define DEF_MIPMAP "True" +# define DEF_TITLES "False" +# define DEF_POLAROID "True" +# define DEF_CLIP "True" +# define DEF_SHADOWS "True" +# define DEF_DEBUG "False" + +#define BELLRAND(n) ((frand((n)) + frand((n)) + frand((n))) / 3) + +typedef struct { + GLfloat x, y; /* position on screen */ + GLfloat angle; /* rotation angle */ + +} position; + +typedef struct { + Bool loaded_p; /* true if image can be drawn */ + + char *title; /* the filename of this image */ + int w, h; /* size in pixels of the image */ + int tw, th; /* size in pixels of the texture */ + XRectangle geom; /* where in the image the bits are */ + + position pos[4]; /* control points for calculating position */ + + GLuint texid; /* GL texture ID */ + +} image; + + +typedef enum { EARLY, SHUFFLE, NORMAL, LOADING } fade_mode; +static int fade_ticks = 60; + +typedef struct { + ModeInfo *mi; + GLXContext *glx_context; + + image *frames; /* pointer to array of images */ + int nframe; /* image being (resp. next to be) loaded */ + + GLuint shadow; + texture_font_data *texfont; + int loading_sw, loading_sh; + + time_t last_time, now; + int draw_tick; + fade_mode mode; + int mode_tick; + +} photopile_state; + +static photopile_state *sss = NULL; + + +/* Command-line arguments + */ +static GLfloat scale; /* Scale factor for loading images. */ +static GLfloat max_tilt; /* Maximum angle from vertical. */ +static GLfloat speed; /* Animation speed scale factor. */ +static int duration; /* Reload images after this long. */ +static Bool mipmap_p; /* Use mipmaps instead of single textures. */ +static Bool titles_p; /* Display image titles. */ +static Bool polaroid_p; /* Use instant-film look for images. */ +static Bool clip_p; /* Clip images instead of scaling for -polaroid. */ +static Bool shadows_p; /* Draw drop shadows. */ +static Bool debug_p; /* Be loud and do weird things. */ + + +static XrmOptionDescRec opts[] = { + {"-scale", ".scale", XrmoptionSepArg, 0 }, + {"-maxTilt", ".maxTilt", XrmoptionSepArg, 0 }, + {"-speed", ".speed", XrmoptionSepArg, 0 }, + {"-duration", ".duration", XrmoptionSepArg, 0 }, + {"-mipmaps", ".mipmap", XrmoptionNoArg, "True" }, + {"-no-mipmaps", ".mipmap", XrmoptionNoArg, "False" }, + {"-titles", ".titles", XrmoptionNoArg, "True" }, + {"-no-titles", ".titles", XrmoptionNoArg, "False" }, + {"-polaroid", ".polaroid", XrmoptionNoArg, "True" }, + {"-no-polaroid", ".polaroid", XrmoptionNoArg, "False" }, + {"-clip", ".clip", XrmoptionNoArg, "True" }, + {"-no-clip", ".clip", XrmoptionNoArg, "False" }, + {"-shadows", ".shadows", XrmoptionNoArg, "True" }, + {"-no-shadows", ".shadows", XrmoptionNoArg, "False" }, + {"-debug", ".debug", XrmoptionNoArg, "True" }, + {"-font", ".font", XrmoptionSepArg, 0 }, +}; + +static argtype vars[] = { + { &scale, "scale", "Scale", DEF_SCALE, t_Float}, + { &max_tilt, "maxTilt", "MaxTilt", DEF_MAX_TILT, t_Float}, + { &speed, "speed", "Speed", DEF_SPEED, t_Float}, + { &duration, "duration", "Duration", DEF_DURATION, t_Int}, + { &mipmap_p, "mipmap", "Mipmap", DEF_MIPMAP, t_Bool}, + { &titles_p, "titles", "Titles", DEF_TITLES, t_Bool}, + { &polaroid_p, "polaroid", "Polaroid", DEF_POLAROID, t_Bool}, + { &clip_p, "clip", "Clip", DEF_CLIP, t_Bool}, + { &shadows_p, "shadows", "Shadows", DEF_SHADOWS, t_Bool}, + { &debug_p, "debug", "Debug", DEF_DEBUG, t_Bool}, +}; + +ENTRYPOINT ModeSpecOpt photopile_opts = {countof(opts), opts, countof(vars), vars, NULL}; + + +/* Functions to interpolate between image positions. + */ +static position +add_pos(position p, position q) +{ + p.x += q.x; + p.y += q.y; + p.angle += q.angle; + return p; +} + +static position +scale_pos(GLfloat t, position p) +{ + p.x *= t; + p.y *= t; + p.angle *= t; + return p; +} + +static position +linear_combination(GLfloat t, position p, position q) +{ + return add_pos(scale_pos(1.0 - t, p), scale_pos(t, q)); +} + +static position +interpolate(GLfloat t, position p[4]) +{ + /* de Casteljau's algorithm, 4 control points */ + position p10 = linear_combination(t, p[0], p[1]); + position p11 = linear_combination(t, p[1], p[2]); + position p12 = linear_combination(t, p[2], p[3]); + + position p20 = linear_combination(t, p10, p11); + position p21 = linear_combination(t, p11, p12); + + return linear_combination(t, p20, p21); +} + +static position +offset_pos(position p, GLfloat th, GLfloat r) +{ + p.x += cos(th) * r; + p.y += sin(th) * r; + p.angle = (frand(2.0) - 1.0) * max_tilt; + return p; +} + +/* Calculate new positions for all images. + */ +static void +set_new_positions(photopile_state *ss) +{ + ModeInfo *mi = ss->mi; + int i; + + for (i = 0; i < MI_COUNT(mi)+1; ++i) + { + image *frame = ss->frames + i; + GLfloat w = frame->w; + GLfloat h = frame->h; + GLfloat d = sqrt(w*w + h*h); + GLfloat leave = frand(M_PI * 2.0); + GLfloat enter = frand(M_PI * 2.0); + + /* start position */ + frame->pos[0] = frame->pos[3]; + + /* end position */ + frame->pos[3].x = BELLRAND(MI_WIDTH(mi)); + frame->pos[3].y = BELLRAND(MI_HEIGHT(mi)); + frame->pos[3].angle = (frand(2.0) - 1.0) * max_tilt; + + /* Try to keep the images mostly inside the screen bounds */ + frame->pos[3].x = MAX(0.5*w, MIN(MI_WIDTH(mi)-0.5*w, frame->pos[3].x)); + frame->pos[3].y = MAX(0.5*h, MIN(MI_HEIGHT(mi)-0.5*h, frame->pos[3].y)); + + /* intermediate points */ + frame->pos[1] = offset_pos(frame->pos[0], leave, d * (0.5 + frand(1.0))); + frame->pos[2] = offset_pos(frame->pos[3], enter, d * (0.5 + frand(1.0))); + } +} + +/* Callback that tells us that the texture has been loaded. + */ +static void +image_loaded_cb (const char *filename, XRectangle *geom, + int image_width, int image_height, + int texture_width, int texture_height, + void *closure) +{ + photopile_state *ss = (photopile_state *) closure; + ModeInfo *mi = ss->mi; + int wire = MI_IS_WIREFRAME(mi); + image *frame = ss->frames + ss->nframe; + + if (wire) + { + if (random() % 2) + { + frame->w = (int)(MI_WIDTH(mi) * scale) - 1; + frame->h = (int)(MI_HEIGHT(mi) * scale) - 1; + } + else + { + frame->w = (int)(MI_HEIGHT(mi) * scale) - 1; + frame->h = (int)(MI_WIDTH(mi) * scale) - 1; + } + if (frame->w <= 10) frame->w = 10; + if (frame->h <= 10) frame->h = 10; + frame->geom.width = frame->w; + frame->geom.height = frame->h; + goto DONE; + } + + if (image_width == 0 || image_height == 0) + exit (1); + + glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, + mipmap_p ? GL_LINEAR_MIPMAP_LINEAR : GL_LINEAR); + + glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); + glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); + + frame->w = image_width; + frame->h = image_height; + frame->tw = texture_width; + frame->th = texture_height; + frame->geom = *geom; + + if (frame->title) + free (frame->title); + frame->title = (filename ? strdup (filename) : 0); + + /* xscreensaver-getimage returns paths relative to the image directory + now, so leave the sub-directory part in. Unless it's an absolute path. + */ + if (frame->title && frame->title[0] == '/') + { + /* strip filename to part after last /. */ + char *s = strrchr (frame->title, '/'); + if (s) strcpy (frame->title, s+1); + } + + if (debug_p) + fprintf (stderr, "%s: loaded %4d x %-4d %4d x %-4d \"%s\"\n", + progname, + frame->geom.width, + frame->geom.height, + frame->tw, frame->th, + (frame->title ? frame->title : "(null)")); + + DONE: + frame->loaded_p = True; +} + + +/* Load a new file. + */ +static void +load_image (ModeInfo *mi) +{ + photopile_state *ss = &sss[MI_SCREEN(mi)]; + int wire = MI_IS_WIREFRAME(mi); + image *frame = ss->frames + ss->nframe; + + if (debug_p && !wire && frame->w != 0) + fprintf (stderr, "%s: dropped %4d x %-4d %4d x %-4d \"%s\"\n", + progname, + frame->geom.width, + frame->geom.height, + frame->tw, frame->th, + (frame->title ? frame->title : "(null)")); + + frame->loaded_p = False; + + if (wire) + image_loaded_cb (0, 0, 0, 0, 0, 0, ss); + else + { + int w = MI_WIDTH(mi); + int h = MI_HEIGHT(mi); + int size = (int)((w > h ? w : h) * scale); + if (size <= 10) size = 10; + load_texture_async (mi->xgwa.screen, mi->window, *ss->glx_context, + size, size, + mipmap_p, frame->texid, + image_loaded_cb, ss); + } +} + + +static void +loading_msg (ModeInfo *mi) +{ + photopile_state *ss = &sss[MI_SCREEN(mi)]; + int wire = MI_IS_WIREFRAME(mi); + const char text[] = "Loading..."; + + if (wire) return; + + if (ss->loading_sw == 0) /* only do this once */ + ss->loading_sw = texture_string_width (ss->texfont, text, &ss->loading_sh); + + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + + glMatrixMode(GL_PROJECTION); + glPushMatrix(); + glLoadIdentity(); + + glMatrixMode(GL_MODELVIEW); + glPushMatrix(); + glLoadIdentity(); + glOrtho(0, MI_WIDTH(mi), 0, MI_HEIGHT(mi), -1, 1); + + glTranslatef ((MI_WIDTH(mi) - ss->loading_sw) / 2, + (MI_HEIGHT(mi) - ss->loading_sh) / 2, + 0); + glColor3f (1, 1, 0); + glEnable (GL_TEXTURE_2D); + glDisable (GL_DEPTH_TEST); + print_texture_string (ss->texfont, text); + glEnable (GL_DEPTH_TEST); + glPopMatrix(); + + glMatrixMode(GL_PROJECTION); + glPopMatrix(); + + glMatrixMode(GL_MODELVIEW); + + glFinish(); + glXSwapBuffers (MI_DISPLAY (mi), MI_WINDOW(mi)); +} + + +static Bool +loading_initial_image (ModeInfo *mi) +{ + photopile_state *ss = &sss[MI_SCREEN(mi)]; + + if (ss->frames[ss->nframe].loaded_p) + { + /* The initial image has been fully loaded, start fading it in. */ + int i; + + for (i = 0; i < ss->nframe; ++i) + { + ss->frames[i].pos[3].x = MI_WIDTH(mi) * 0.5; + ss->frames[i].pos[3].y = MI_HEIGHT(mi) * 0.5; + ss->frames[i].pos[3].angle = 0.0; + } + set_new_positions(ss); + + ss->mode = SHUFFLE; + ss->mode_tick = fade_ticks / speed; + } + else + { + loading_msg(mi); + } + + return (ss->mode == EARLY); +} + + +ENTRYPOINT void +reshape_photopile (ModeInfo *mi, int width, int height) +{ + glViewport (0, 0, (GLint) width, (GLint) height); + + glMatrixMode(GL_PROJECTION); + glLoadIdentity(); + + glMatrixMode(GL_MODELVIEW); + glLoadIdentity(); + glOrtho(0, MI_WIDTH(mi), 0, MI_HEIGHT(mi), -1, 1); + + glClear(GL_COLOR_BUFFER_BIT); +} + + +/* Kludge to add "-v" to invocation of "xscreensaver-getimage" in -debug mode + */ +static void +hack_resources (Display *dpy) +{ +# ifndef HAVE_COCOA + char *res = "desktopGrabber"; + char *val = get_string_resource (dpy, res, "DesktopGrabber"); + char buf1[255]; + char buf2[255]; + XrmValue value; + XrmDatabase db = XtDatabase (dpy); + sprintf (buf1, "%.100s.%.100s", progname, res); + sprintf (buf2, "%.200s -v", val); + value.addr = buf2; + value.size = strlen(buf2); + XrmPutResource (&db, buf1, "String", &value); +# endif /* !HAVE_COCOA */ +} + + +ENTRYPOINT void +init_photopile (ModeInfo *mi) +{ + int screen = MI_SCREEN(mi); + photopile_state *ss; + int wire = MI_IS_WIREFRAME(mi); + + if (sss == NULL) { + if ((sss = (photopile_state *) + calloc (MI_NUM_SCREENS(mi), sizeof(photopile_state))) == NULL) + return; + } + ss = &sss[screen]; + ss->mi = mi; + + if ((ss->glx_context = init_GL(mi)) != NULL) { + reshape_photopile (mi, MI_WIDTH(mi), MI_HEIGHT(mi)); + clear_gl_error(); /* WTF? sometimes "invalid op" from glViewport! */ + } else { + MI_CLEARWINDOW(mi); + } + + ss->shadow = init_drop_shadow(); + ss->texfont = load_texture_font (MI_DISPLAY(mi), "font"); + + if (debug_p) + hack_resources (MI_DISPLAY (mi)); + + ss->frames = (image *)calloc (MI_COUNT(mi) + 1, sizeof(image)); + ss->nframe = 0; + if (!wire) + { + int i; + for (i = 0; i < MI_COUNT(mi) + 1; ++i) + { + glGenTextures (1, &(ss->frames[i].texid)); + if (ss->frames[i].texid <= 0) abort(); + } + } + + ss->mode = EARLY; + load_image(mi); /* start loading the first image */ +} + + +static void +draw_image (ModeInfo *mi, int i, GLfloat t, GLfloat s, GLfloat z) +{ + int wire = MI_IS_WIREFRAME(mi); + photopile_state *ss = &sss[MI_SCREEN(mi)]; + image *frame = ss->frames + i; + + position pos = interpolate(t, frame->pos); + GLfloat w = frame->geom.width * 0.5; + GLfloat h = frame->geom.height * 0.5; + GLfloat z1 = z - 0.25 / (MI_COUNT(mi) + 1); + GLfloat z2 = z - 0.5 / (MI_COUNT(mi) + 1); + GLfloat w1 = w; + GLfloat h1 = h; + GLfloat h2 = h; + + if (polaroid_p) + { + GLfloat minSize = MIN(w, h); + GLfloat maxSize = MAX(w, h); + + /* Clip or scale image to fit in the frame. + */ + if (clip_p) + { + w = h = minSize; + } + else + { + GLfloat scale = minSize / maxSize; + w *= scale; + h *= scale; + } + + w1 = minSize * 1.16; /* enlarge frame border */ + h1 = minSize * 1.5; + h2 = w1; + s /= 1.5; /* compensate for border size */ + } + + glPushMatrix(); + + /* Position and scale this image. + */ + glTranslatef (pos.x, pos.y, 0); + glRotatef (pos.angle, 0, 0, 1); + glScalef (s, s, 1); + + /* Draw the drop shadow. */ + if (shadows_p && !wire) + { + glColor3f (0, 0, 0); + draw_drop_shadow(ss->shadow, -w1, -h1, z2, 2.0 * w1, h1 + h2, 20.0); + glDisable (GL_BLEND); + } + + glDisable (GL_LIGHTING); + glEnable (GL_DEPTH_TEST); + glDisable (GL_CULL_FACE); + + /* Draw the retro instant-film frame. + */ + if (polaroid_p) + { + if (! wire) + { + glShadeModel (GL_SMOOTH); + glEnable (GL_LINE_SMOOTH); + glHint (GL_LINE_SMOOTH_HINT, GL_NICEST); + + glColor3f (1, 1, 1); + glBegin (GL_QUADS); + glVertex3f (-w1, -h1, z2); + glVertex3f ( w1, -h1, z2); + glVertex3f ( w1, h2, z2); + glVertex3f (-w1, h2, z2); + glEnd(); + } + + glLineWidth (1.0); + glColor3f (0.5, 0.5, 0.5); + glBegin (GL_LINE_LOOP); + glVertex3f (-w1, -h1, z); + glVertex3f ( w1, -h1, z); + glVertex3f ( w1, h2, z); + glVertex3f (-w1, h2, z); + glEnd(); + } + + /* Draw the image quad. + */ + if (! wire) + { + GLfloat texw = w / frame->tw; + GLfloat texh = h / frame->th; + GLfloat texx = (frame->geom.x + 0.5 * frame->geom.width) / frame->tw; + GLfloat texy = (frame->geom.y + 0.5 * frame->geom.height) / frame->th; + + glBindTexture (GL_TEXTURE_2D, frame->texid); + glEnable (GL_TEXTURE_2D); + glColor3f (1, 1, 1); + glBegin (GL_QUADS); + glTexCoord2f (texx - texw, texy + texh); glVertex3f (-w, -h, z1); + glTexCoord2f (texx + texw, texy + texh); glVertex3f ( w, -h, z1); + glTexCoord2f (texx + texw, texy - texh); glVertex3f ( w, h, z1); + glTexCoord2f (texx - texw, texy - texh); glVertex3f (-w, h, z1); + glEnd(); + glDisable (GL_TEXTURE_2D); + } + + /* Draw a box around it. + */ + if (! wire) + { + glShadeModel (GL_SMOOTH); + glEnable (GL_LINE_SMOOTH); + glHint (GL_LINE_SMOOTH_HINT, GL_NICEST); + } + glLineWidth (1.0); + glColor3f (0.5, 0.5, 0.5); + glBegin (GL_LINE_LOOP); + glVertex3f (-w, -h, z); + glVertex3f ( w, -h, z); + glVertex3f ( w, h, z); + glVertex3f (-w, h, z); + glEnd(); + + /* Draw a title under the image. + */ + if (titles_p) + { + int sw, sh; + GLfloat scale = 0.6; + const char *title = frame->title ? frame->title : "(untitled)"; + + /* #### Highly approximate, but doing real clipping is harder... */ + int max = 35; + if (strlen(title) > max) + title += strlen(title) - max; + + sw = texture_string_width (ss->texfont, title, &sh); + + glTranslatef (-sw*scale*0.5, -h - sh*scale, z); + glScalef (scale, scale, 1); + + if (wire || !polaroid_p) + { + glColor3f (1, 1, 1); + } + else + { + glColor3f (0, 0, 0); + } + + if (!wire) + { + glEnable (GL_TEXTURE_2D); + glEnable (GL_BLEND); + print_texture_string (ss->texfont, title); + } + else + { + glBegin (GL_LINE_LOOP); + glVertex3f (0, 0, 0); + glVertex3f (sw, 0, 0); + glVertex3f (sw, sh, 0); + glVertex3f (0, sh, 0); + glEnd(); + } + } + + glPopMatrix(); +} + + +ENTRYPOINT void +draw_photopile (ModeInfo *mi) +{ + photopile_state *ss = &sss[MI_SCREEN(mi)]; + int i; + + if (!ss->glx_context) + return; + + glXMakeCurrent(MI_DISPLAY(mi), MI_WINDOW(mi), *(ss->glx_context)); + + if (ss->mode == EARLY) + if (loading_initial_image (mi)) + return; + + /* Only check the wall clock every 10 frames */ + if (ss->now == 0 || ss->draw_tick++ > 10) + { + ss->now = time((time_t *) 0); + if (ss->last_time == 0) ss->last_time = ss->now; + ss->draw_tick = 0; + } + + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + { + GLfloat t; + + glPushMatrix(); + glTranslatef (MI_WIDTH(mi)/2, MI_HEIGHT(mi)/2, 0); + glRotatef(current_device_rotation(), 0, 0, 1); + glTranslatef (-MI_WIDTH(mi)/2, -MI_HEIGHT(mi)/2, 0); + + /* Handle state transitions. */ + switch (ss->mode) + { + case SHUFFLE: + if (--ss->mode_tick <= 0) + { + ss->nframe = (ss->nframe+1) % (MI_COUNT(mi)+1); + + ss->mode = NORMAL; + ss->last_time = time((time_t *) 0); + } + break; + case NORMAL: + if (ss->now - ss->last_time > duration) + { + ss->mode = LOADING; + load_image(mi); + } + break; + case LOADING: + if (ss->frames[ss->nframe].loaded_p) + { + set_new_positions(ss); + ss->mode = SHUFFLE; + ss->mode_tick = fade_ticks / speed; + } + break; + default: + abort(); + } + + t = 1.0 - ss->mode_tick / (fade_ticks / speed); + t = 0.5 * (1.0 - cos(M_PI * t)); + + /* Draw the images. */ + for (i = 0; i < MI_COUNT(mi) + (ss->mode == SHUFFLE); ++i) + { + int j = (ss->nframe + i + 1) % (MI_COUNT(mi) + 1); + + if (ss->frames[j].loaded_p) + { + GLfloat s = 1.0; + GLfloat z = (GLfloat)i / (MI_COUNT(mi) + 1); + + switch (ss->mode) + { + case SHUFFLE: + if (i == MI_COUNT(mi)) + { + s *= t; + } + else if (i == 0) + { + s *= 1.0 - t; + } + break; + case NORMAL: + case LOADING: + t = 1.0; + break; + default: + abort(); + } + + draw_image(mi, j, t, s, z); + } + } + glPopMatrix(); + } + + if (mi->fps_p) do_fps (mi); + glFinish(); + glXSwapBuffers (MI_DISPLAY (mi), MI_WINDOW(mi)); +} + +XSCREENSAVER_MODULE ("Photopile", photopile) + +#endif /* USE_GL */ diff --git a/hacks/glx/photopile.man b/hacks/glx/photopile.man new file mode 100644 index 00000000..277f9ddc --- /dev/null +++ b/hacks/glx/photopile.man @@ -0,0 +1,113 @@ +.TH XScreenSaver 1 "" "X Version 11" +.SH NAME +photopile - displays multiple images in a periodically shuffled pile +.SH SYNOPSIS +.B photopile +[\-display \fIhost:display.screen\fP] +[\-visual \fIvisual\fP] +[\-window] +[\-root] +[\-count \fIint\fP] +[\-scale \fIfactor\fP] +[\-maxTilt \fIdegrees\fP] +[\-titles | \-no\-titles] +[\-polaroid | \-no\-polaroid] +[\-shadows | \-no\-shadows] +[\-font \fIfont\fP] +[\-speed \fIratio\fP] +[\-duration \fIseconds\fP] +[\-fps] +[\-debug] +[\-wireframe] +.SH DESCRIPTION +Loads several random images, and displays them as if lying in a random pile. +The pile is periodically reshuffled, with new images coming in and old ones +being thrown out. + +This program requires a good video card capable of supporting large +textures. + +To specify the directory that images are loaded from, run +.BR xscreensaver-demo (1) +and click on the "Advanced" tab. +.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 \-count \fIint\fP +How many images to display. Default 7. +.TP 8 +.B \-scale \fIfactor\fP +Size of images in relation to the size of the window. Default 0.4. +.TP 8 +.B \-maxTilt \fIdegrees\fP +Maximum deviation from vertical. Default 50 degrees. +.TP 8 +.B \-duration \fIseconds\fP +Every \fIduration\fP seconds, one of the images will be replaced +with a new one. Default 5 seconds. +.TP 8 +.B \-speed \fIratio\fP +Speed up or slow down the animation. 0.5 means half as fast as the +default; 2.0 means twice as fast. +.TP 8 +.B \-delay \fInumber\fP +Per-frame delay, in microseconds. Default: 10000 (0.01 seconds.). +.TP 8 +.B \-titles \fB| \-no\-titles\fP +Whether to display the file names of the images beneath them. Default: no. +.TP 8 +.B \-polaroid \fB| \-no\-polaroid\fP +Whether to simulate images taken by an instant camera. Default: yes. +.TP 8 +.B \-shadows \fB| \-no\-shadows\fP +Whether to draw images with drop shadows. Default: no. +.TP 8 +.B \-font \fIfont-name\fP +The font to use for the initial loading screen. +.TP 8 +.B \-fps +Display the current frame rate, CPU load, and polygon count. +.TP 8 +.B \-debug +Prints debugging info to stderr. +.TP 8 +.B \-wireframe +Another debug mode. +.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-demo (1) +.BR xscreensaver-getimage (1) +.BR xscreensaver (1) +.BR carousel (MANSUFFIX) +.BR glslideshow (MANSUFFIX) +.SH COPYRIGHT +Copyright \(co 2005 by Jamie Zawinski. +Copyright \(co 2008 by Jens Kilian. + +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 +Jens Kilian. diff --git a/hacks/glx/pinion.c b/hacks/glx/pinion.c new file mode 100644 index 00000000..4da81e39 --- /dev/null +++ b/hacks/glx/pinion.c @@ -0,0 +1,1534 @@ +/* pinion, Copyright (c) 2004-2012 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. + */ + +#define DEFAULTS "*delay: 15000 \n" \ + "*showFPS: False \n" \ + "*wireframe: False \n" \ + "*titleFont: -*-helvetica-medium-r-normal-*-180-*\n" \ + "*titleFont2: -*-helvetica-medium-r-normal-*-120-*\n" \ + "*titleFont3: -*-helvetica-medium-r-normal-*-80-*\n" \ + +# define refresh_pinion 0 +# define release_pinion 0 +#undef countof +#define countof(x) (sizeof((x))/sizeof((*x))) + +#undef BELLRAND +#define BELLRAND(n) ((frand((n)) + frand((n)) + frand((n))) / 3) + +#include "xlockmore.h" +#include "normals.h" +#include "gltrackball.h" +#include "glxfonts.h" +#include "involute.h" +#include + +#ifdef USE_GL /* whole file */ + +#define DEF_SPIN_SPEED "1.0" +#define DEF_SCROLL_SPEED "1.0" +#define DEF_GEAR_SIZE "1.0" +#define DEF_MAX_RPM "900" + +typedef struct { + GLXContext *glx_context; + GLfloat vp_left, vp_right, vp_top, vp_bottom; /* default visible area */ + GLfloat vp_width, vp_height; + GLfloat render_left, render_right; /* area in which gears are displayed */ + GLfloat layout_left, layout_right; /* layout region, on the right side */ + + int ngears; + int gears_size; + gear **gears; + + trackball_state *trackball; + Bool button_down_p; + unsigned long mouse_gear_id; + +# ifdef HAVE_GLBITMAP + XFontStruct *xfont1, *xfont2, *xfont3; + GLuint font1_dlist, font2_dlist, font3_dlist; +# else + texture_font_data *font1, *font2, *font3; +# endif + + GLuint title_list; + int draw_tick; + + GLfloat plane_displacement; /* distance between coaxial gears */ + + int debug_size_failures; /* for debugging messages */ + int debug_position_failures; + unsigned long current_length; /* gear count in current train */ + unsigned long current_blur_length; /* how long have we been blurring? */ + +} pinion_configuration; + + +static pinion_configuration *pps = NULL; + +/* command line arguments */ +static GLfloat spin_speed, scroll_speed, gear_size, max_rpm; + +static Bool verbose_p = False; /* print progress on stderr */ +static Bool debug_p = False; /* render as flat schematic */ + +/* internal debugging variables */ +static Bool debug_placement_p = False; /* extreme verbosity on stderr */ +static Bool debug_one_gear_p = False; /* draw one big stationary gear */ + + +static XrmOptionDescRec opts[] = { + { "-spin", ".spinSpeed", XrmoptionSepArg, 0 }, + { "-scroll", ".scrollSpeed", XrmoptionSepArg, 0 }, + { "-size", ".gearSize", XrmoptionSepArg, 0 }, + { "-max-rpm",".maxRPM", XrmoptionSepArg, 0 }, + { "-debug", ".debug", XrmoptionNoArg, "True" }, + { "-verbose",".verbose", XrmoptionNoArg, "True" }, +}; + +static argtype vars[] = { + {&spin_speed, "spinSpeed", "SpinSpeed", DEF_SPIN_SPEED, t_Float}, + {&scroll_speed, "scrollSpeed", "ScrollSpeed", DEF_SCROLL_SPEED, t_Float}, + {&gear_size, "gearSize", "GearSize", DEF_GEAR_SIZE, t_Float}, + {&max_rpm, "maxRPM", "MaxRPM", DEF_MAX_RPM, t_Float}, + {&debug_p, "debug", "Debug", "False", t_Bool}, + {&verbose_p, "verbose", "Verbose", "False", t_Bool}, +}; + +ENTRYPOINT ModeSpecOpt pinion_opts = {countof(opts), opts, countof(vars), vars, NULL}; + + +/* Font stuff + */ + +static void +load_fonts (ModeInfo *mi) +{ + pinion_configuration *pp = &pps[MI_SCREEN(mi)]; +# ifdef HAVE_GLBITMAP + load_font (mi->dpy, "titleFont", &pp->xfont1, &pp->font1_dlist); + load_font (mi->dpy, "titleFont2", &pp->xfont2, &pp->font2_dlist); + load_font (mi->dpy, "titleFont3", &pp->xfont3, &pp->font3_dlist); +# else + pp->font1 = load_texture_font (mi->dpy, "titleFont"); + pp->font2 = load_texture_font (mi->dpy, "titleFont2"); + pp->font3 = load_texture_font (mi->dpy, "titleFont3"); +# endif +} + + + +static void rpm_string (double rpm, char *s); + +static void +new_label (ModeInfo *mi) +{ + pinion_configuration *pp = &pps[MI_SCREEN(mi)]; + char label[1024]; + int i; + gear *g = 0; + + if (pp->mouse_gear_id) + for (i = 0; i < pp->ngears; i++) + if (pp->gears[i]->id == pp->mouse_gear_id) + { + g = pp->gears[i]; + break; + } + + if (!g) + *label = 0; + else + { + sprintf (label, "%d teeth\n", (int) g->nteeth); + rpm_string (g->rpm, label + strlen(label)); + if (debug_p) + sprintf (label + strlen (label), "\nPolys: %d\nModel: %s (%.2f)\n", + g->polygons, + (g->size == INVOLUTE_SMALL ? "small" : + g->size == INVOLUTE_MEDIUM ? "medium" + : "large"), + g->tooth_h * MI_HEIGHT(mi)); + } + + glNewList (pp->title_list, GL_COMPILE); + if (*label) + { +# ifdef HAVE_GLBITMAP + XFontStruct *f; + GLuint fl; +# else + texture_font_data *fd; +# endif + if (MI_WIDTH(mi) >= 500 && MI_HEIGHT(mi) >= 375) +# ifdef HAVE_GLBITMAP + f = pp->xfont1, fl = pp->font1_dlist; /* big font */ +# else + fd = pp->font1; +# endif + else if (MI_WIDTH(mi) >= 350 && MI_HEIGHT(mi) >= 260) +# ifdef HAVE_GLBITMAP + f = pp->xfont2, fl = pp->font2_dlist; /* small font */ +# else + fd = pp->font2; +# endif + else +# ifdef HAVE_GLBITMAP + f = pp->xfont3, fl = pp->font3_dlist; /* tiny font */ +# else + fd = pp->font3; +# endif + + glColor3f (0.8, 0.8, 0); + print_gl_string (mi->dpy, +# ifdef HAVE_GLBITMAP + f, fl, +# else + fd, +# endif + mi->xgwa.width, mi->xgwa.height, + 10, mi->xgwa.height - 10, + label, False); + } + glEndList (); +} + + +/* Some utilities + */ + + +/* Find the gear in the scene that is farthest to the right or left. + */ +static gear * +farthest_gear (ModeInfo *mi, Bool left_p) +{ + pinion_configuration *pp = &pps[MI_SCREEN(mi)]; + int i; + gear *rg = 0; + double x = (left_p ? 999999 : -999999); + for (i = 0; i < pp->ngears; i++) + { + gear *g = pp->gears[i]; + double gx = g->x + ((g->r + g->tooth_h) * (left_p ? -1 : 1)); + if (left_p ? (x > gx) : (x < gx)) + { + rg = g; + x = gx; + } + } + return rg; +} + + +/* Compute the revolutions per minute of a gear. + */ +static void +compute_rpm (ModeInfo *mi, gear *g) +{ + double fps, rpf, rps; + fps = (MI_PAUSE(mi) == 0 ? 999999 : 1000000.0 / MI_PAUSE(mi)); + + if (fps > 150) fps = 150; /* let's be reasonable... */ + if (fps < 10) fps = 10; + + rpf = (g->ratio * spin_speed) / 360.0; /* rotations per frame */ + rps = rpf * fps; /* rotations per second */ + g->rpm = rps * 60; +} + +/* Prints the RPM into a string, doing fancy float formatting. + */ +static void +rpm_string (double rpm, char *s) +{ + char buf[30]; + int L; + if (rpm >= 0.1) sprintf (buf, "%.2f", rpm); + else if (rpm >= 0.001) sprintf (buf, "%.4f", rpm); + else if (rpm >= 0.00001) sprintf (buf, "%.8f", rpm); + else sprintf (buf, "%.16f",rpm); + + L = strlen(buf); + while (buf[L-1] == '0') buf[--L] = 0; + if (buf[L-1] == '.') buf[--L] = 0; + strcpy (s, buf); + strcat (s, " RPM"); +} + + + +/* Layout and stuff. + */ + + +/* Create and return a new gear sized for placement next to or on top of + the given parent gear (if any.) Returns 0 if out of memory. + */ +static gear * +new_gear (ModeInfo *mi, gear *parent, Bool coaxial_p) +{ + pinion_configuration *pp = &pps[MI_SCREEN(mi)]; + gear *g = (gear *) calloc (1, sizeof (*g)); + int loop_count = 0; + static unsigned long id = 0; /* only used in debugging output */ + + if (!g) return 0; + if (coaxial_p && !parent) abort(); + g->id = ++id; + + g->coax_displacement = pp->plane_displacement; + + while (1) + { + loop_count++; + if (loop_count > 1000) + /* The only time we loop in here is when making a coaxial gear, and + trying to pick a radius that is either significantly larger or + smaller than its parent. That shouldn't be hard, so something + must be really wrong if we can't do that in only a few tries. + */ + abort(); + + /* Pick the size of the teeth. + */ + if (parent && !coaxial_p) /* adjascent gears need matching teeth */ + { + g->tooth_w = parent->tooth_w; + g->tooth_h = parent->tooth_h; + g->thickness = parent->thickness; + g->thickness2 = parent->thickness2; + g->thickness3 = parent->thickness3; + } + else /* gears that begin trains get any size they want */ + { + double scale = (1.0 + BELLRAND(4.0)) * gear_size; + g->tooth_w = 0.007 * scale; + g->tooth_h = 0.005 * scale; + g->thickness = g->tooth_h * (0.1 + BELLRAND(1.5)); + g->thickness2 = g->thickness / 4; + g->thickness3 = g->thickness; + } + + /* Pick the number of teeth, and thus, the radius. + */ + { + double c; + + AGAIN: + g->nteeth = 3 + (random() % 97); /* from 3 to 100 teeth */ + + if (g->nteeth < 7 && (random() % 5) != 0) + goto AGAIN; /* Let's make very small tooth-counts more rare */ + + c = g->nteeth * g->tooth_w * 2; /* circumference = teeth + gaps */ + g->r = c / (M_PI * 2); /* c = 2 pi r */ + } + + + /* Are we done now? + */ + if (! coaxial_p) break; /* yes */ + if (g->nteeth == parent->nteeth) continue; /* ugly */ + if (g->r < parent->r * 0.6) break; /* g much smaller than parent */ + if (parent->r < g->r * 0.6) break; /* g much larger than parent */ + } + + /* g->tooth_slope = (parent ? -parent->tooth_slope : 4); */ + + /* Colorize + */ + g->color[0] = 0.5 + frand(0.5); + g->color[1] = 0.5 + frand(0.5); + g->color[2] = 0.5 + frand(0.5); + g->color[3] = 1.0; + + g->color2[0] = g->color[0] * 0.85; + g->color2[1] = g->color[1] * 0.85; + g->color2[2] = g->color[2] * 0.85; + g->color2[3] = g->color[3]; + + + /* Decide on shape of gear interior: + - just a ring with teeth; + - that, plus a thinner in-set "plate" in the middle; + - that, plus a thin raised "lip" on the inner plate; + - or, a wide lip (really, a thicker third inner plate.) + */ + if ((random() % 10) == 0) + { + /* inner_r can go all the way in; there's no inset disc. */ + g->inner_r = (g->r * 0.1) + frand((g->r - g->tooth_h/2) * 0.8); + g->inner_r2 = 0; + g->inner_r3 = 0; + } + else + { + /* inner_r doesn't go in very far; inner_r2 is an inset disc. */ + g->inner_r = (g->r * 0.5) + frand((g->r - g->tooth_h) * 0.4); + g->inner_r2 = (g->r * 0.1) + frand(g->inner_r * 0.5); + g->inner_r3 = 0; + + if (g->inner_r2 > (g->r * 0.2)) + { + int nn = (random() % 10); + if (nn <= 2) + g->inner_r3 = (g->r * 0.1) + frand(g->inner_r2 * 0.2); + else if (nn <= 7 && g->inner_r2 >= 0.1) + g->inner_r3 = g->inner_r2 - 0.01; + } + } + + /* Coaxial gears need to have the same innermost hole size (for the axle.) + Use whichever of the two is smaller. (Modifies parent.) + */ + if (coaxial_p) + { + double hole1 = (g->inner_r3 ? g->inner_r3 : + g->inner_r2 ? g->inner_r2 : + g->inner_r); + double hole2 = (parent->inner_r3 ? parent->inner_r3 : + parent->inner_r2 ? parent->inner_r2 : + parent->inner_r); + double hole = (hole1 < hole2 ? hole1 : hole2); + if (hole <= 0) abort(); + + if (g->inner_r3) g->inner_r3 = hole; + else if (g->inner_r2) g->inner_r2 = hole; + else g->inner_r = hole; + + if (parent->inner_r3) parent->inner_r3 = hole; + else if (parent->inner_r2) parent->inner_r2 = hole; + else parent->inner_r = hole; + } + + /* If we have three discs, sometimes make the middle disc be spokes. + */ + if (g->inner_r3 && ((random() % 5) == 0)) + { + g->spokes = 2 + BELLRAND (5); + g->spoke_thickness = 1 + frand(7.0); + if (g->spokes == 2 && g->spoke_thickness < 2) + g->spoke_thickness += 1; + } + + /* Sometimes add little nubbly bits, if there is room. + */ + if (g->nteeth > 5) + { + double size = 0; + involute_biggest_ring (g, 0, &size, 0); + if (size > g->r * 0.2 && (random() % 5) == 0) + { + g->nubs = 1 + (random() % 16); + if (g->nubs > 8) g->nubs = 1; + } + } + + if (g->inner_r3 > g->inner_r2) abort(); + if (g->inner_r2 > g->inner_r) abort(); + if (g->inner_r > g->r) abort(); + + /* Decide how complex the polygon model should be. + */ + { + double pix = g->tooth_h * MI_HEIGHT(mi); /* approx. tooth size in pixels */ + if (pix <= 2.5) g->size = INVOLUTE_SMALL; + else if (pix <= 3.5) g->size = INVOLUTE_MEDIUM; + else g->size = INVOLUTE_LARGE; + } + + g->base_p = !parent; + + return g; +} + + +/* Given a newly-created gear, place it next to its parent in the scene, + with its teeth meshed and the proper velocity. Returns False if it + didn't work. (Call this a bunch of times until either it works, or + you decide it's probably not going to.) + */ +static Bool +place_gear (ModeInfo *mi, gear *g, gear *parent, Bool coaxial_p) +{ + pinion_configuration *pp = &pps[MI_SCREEN(mi)]; + + /* If this gear takes up more than 1/3rd of the screen, it's no good. + */ + if (((g->r + g->tooth_h) * (6 / gear_size)) >= pp->vp_width || + ((g->r + g->tooth_h) * (6 / gear_size)) >= pp->vp_height) + { + if (verbose_p && debug_placement_p && 0) + fprintf (stderr, + "%s: placement: too big: %.2f @ %.2f vs %.2f x %.2f\n", + progname, + (g->r + g->tooth_h), gear_size, + pp->vp_width, pp->vp_height); + pp->debug_size_failures++; + return False; + } + + /* Compute this gear's velocity. + */ + if (! parent) + { + g->ratio = 0.8 + BELLRAND(0.4); /* 0.8-1.2 = 8-12rpm @ 60fps */ + g->th = frand (90) * ((random() & 1) ? 1.0 : -1.0); + } + else if (coaxial_p) + { + g->ratio = parent->ratio; /* bound gears have the same ratio */ + g->th = parent->th; + g->rpm = parent->rpm; + g->wobble = parent->wobble; + } + else + { + /* Gearing ratio is the ratio of the number of teeth to previous gear + (which is also the ratio of the circumferences.) + */ + g->ratio = (double) parent->nteeth / (double) g->nteeth; + + /* Set our initial rotation to match that of the previous gear, + multiplied by the gearing ratio. (This is finessed later, + once we know the exact position of the gear relative to its + parent.) + */ + g->th = -(parent->th * g->ratio); + + if (g->nteeth & 1) /* rotate 1/2 tooth-size if odd number of teeth */ + { + double off = (180.0 / g->nteeth); + if (g->th > 0) + g->th += off; + else + g->th -= off; + } + + /* ratios are cumulative for all gears in the train. */ + g->ratio *= parent->ratio; + } + + + /* Place the gear relative to the parent. + */ + + if (! parent) + { + gear *rg = farthest_gear (mi, False); + double right = (rg ? rg->x + rg->r + rg->tooth_h : 0); + if (right < pp->layout_left) /* place off screen */ + right = pp->layout_left; + + g->x = right + g->r + g->tooth_h + (0.01 / gear_size); + g->y = 0; + g->z = 0; + + if (debug_one_gear_p) + g->x = 0; + } + else if (coaxial_p) + { + double off = pp->plane_displacement; + + g->x = parent->x; + g->y = parent->y; + g->z = parent->z + (g->r > parent->r /* small gear on top */ + ? -off : off); + + if (parent->r > g->r) /* mark which is top and which is bottom */ + { + parent->coax_p = 1; + g->coax_p = 2; + parent->wobble = 0; /* looks bad when axle moves */ + } + else + { + parent->coax_p = 2; + g->coax_p = 1; + g->wobble = 0; + } + + g->coax_thickness = parent->thickness; + parent->coax_thickness = g->thickness; + + /* Don't let the train get too close to or far from the screen. + If we're getting too close, give up on this gear. + (But getting very far away is fine.) + */ + if (g->z >= off * 4 || + g->z <= -off * 4) + { + if (verbose_p && debug_placement_p) + fprintf (stderr, "%s: placement: bad depth: %.2f\n", + progname, g->z); + pp->debug_position_failures++; + return False; + } + } + else /* position it somewhere next to the parent. */ + { + double r_off = parent->r + g->r; + int angle; + + if ((random() % 3) != 0) + angle = (random() % 240) - 120; /* mostly -120 to +120 degrees */ + else + angle = (random() % 360) - 180; /* sometimes -180 to +180 degrees */ + + g->x = parent->x + (cos ((double) angle * (M_PI / 180)) * r_off); + g->y = parent->y + (sin ((double) angle * (M_PI / 180)) * r_off); + g->z = parent->z; + + /* If the angle we picked would have positioned this gear + more than halfway off screen, that's no good. */ + if (g->y > pp->vp_top || + g->y < pp->vp_bottom) + { + if (verbose_p && debug_placement_p) + fprintf (stderr, "%s: placement: out of bounds: %s\n", + progname, (g->y > pp->vp_top ? "top" : "bottom")); + pp->debug_position_failures++; + return False; + } + + /* avoid accidentally changing sign of "th" in the math below. */ + g->th += (g->th > 0 ? 360 : -360); + + /* Adjust the rotation of the gear so that its teeth line up with its + parent, based on the position of the gear and the current rotation + of the parent. + */ + { + double p_c = 2 * M_PI * parent->r; /* circumference of parent */ + double g_c = 2 * M_PI * g->r; /* circumference of g */ + + double p_t = p_c * (angle/360.0); /* distance travelled along + circumference of parent when + moving "angle" degrees along + parent. */ + double g_rat = p_t / g_c; /* if travelling that distance + along circumference of g, + ratio of g's circumference + travelled. */ + double g_th = 360.0 * g_rat; /* that ratio in degrees */ + + g->th += angle + g_th; + } + } + + if (debug_one_gear_p) + { + compute_rpm (mi, g); + return True; + } + + /* If the position we picked for this gear would cause it to already + be visible on the screen, give up. This can happen when the train + is growing backwards, and we don't want to see gears flash into + existence. + */ + if (g->x - g->r - g->tooth_h < pp->render_right) + { + if (verbose_p && debug_placement_p) + fprintf (stderr, "%s: placement: out of bounds: left\n", progname); + pp->debug_position_failures++; + return False; + } + + /* If the position we picked for this gear causes it to overlap + with any earlier gear in the train, give up. + */ + { + int i; + + for (i = pp->ngears-1; i >= 0; i--) + { + gear *og = pp->gears[i]; + + if (og == g) continue; + if (og == parent) continue; + if (g->z != og->z) continue; /* Ignore unless on same layer */ + + /* Collision detection without sqrt: + d = sqrt(a^2 + b^2) d^2 = a^2 + b^2 + d < r1 + r2 d^2 < (r1 + r2)^2 + */ + if (((g->x - og->x) * (g->x - og->x) + + (g->y - og->y) * (g->y - og->y)) < + ((g->r + g->tooth_h + og->r + og->tooth_h) * + (g->r + g->tooth_h + og->r + og->tooth_h))) + { + if (verbose_p && debug_placement_p) + fprintf (stderr, "%s: placement: collision with %lu\n", + progname, og->id); + pp->debug_position_failures++; + return False; + } + } + } + + compute_rpm (mi, g); + + + /* Make deeper gears be darker. + */ + { + double depth = g->z / pp->plane_displacement; + double brightness = 1 + (depth / 6); + double limit = 0.4; + if (brightness < limit) brightness = limit; + if (brightness > 1/limit) brightness = 1/limit; + g->color[0] *= brightness; + g->color[1] *= brightness; + g->color[2] *= brightness; + g->color2[0] *= brightness; + g->color2[1] *= brightness; + g->color2[2] *= brightness; + } + + /* If a single frame of animation would cause the gear to rotate by + more than 1/2 the size of a single tooth, then it won't look right: + the gear will appear to be turning at some lower harmonic of its + actual speed. + */ + { + double ratio = g->ratio * spin_speed; + double blur_limit = 180.0 / g->nteeth; + + if (ratio > blur_limit) + g->motion_blur_p = 1; + + if (!coaxial_p) + { + /* ride until the wheels fall off... */ + if (ratio > blur_limit * 0.7) g->wobble += (random() % 2); + if (ratio > blur_limit * 0.9) g->wobble += (random() % 2); + if (ratio > blur_limit * 1.1) g->wobble += (random() % 2); + if (ratio > blur_limit * 1.3) g->wobble += (random() % 2); + if (ratio > blur_limit * 1.5) g->wobble += (random() % 2); + if (ratio > blur_limit * 1.7) g->wobble += (random() % 2); + } + } + + return True; +} + +static void +free_gear (gear *g) +{ + if (g->dlist) + glDeleteLists (g->dlist, 1); + free (g); +} + + +/* Make a new gear, place it next to its parent in the scene, + with its teeth meshed and the proper velocity. Returns the gear; + or 0 if it didn't work. (Call this a bunch of times until either + it works, or you decide it's probably not going to.) + */ +static gear * +place_new_gear (ModeInfo *mi, gear *parent, Bool coaxial_p) +{ + pinion_configuration *pp = &pps[MI_SCREEN(mi)]; + int loop_count = 0; + gear *g = 0; + + while (1) + { + loop_count++; + if (loop_count >= 100) + { + if (g) + free_gear (g); + g = 0; + break; + } + + g = new_gear (mi, parent, coaxial_p); + if (!g) return 0; /* out of memory? */ + + if (place_gear (mi, g, parent, coaxial_p)) + break; + } + + if (! g) return 0; + + /* We got a gear, and it is properly positioned. + Insert it in the scene. + */ + if (pp->ngears + 2 >= pp->gears_size) + { + pp->gears_size += 100; + pp->gears = (gear **) realloc (pp->gears, + pp->gears_size * sizeof (*pp->gears)); + if (! pp->gears) + { + fprintf (stderr, "%s: out of memory (%d gears)\n", + progname, pp->gears_size); + } + } + + pp->gears[pp->ngears++] = g; + return g; +} + + +static void delete_gear (ModeInfo *mi, gear *g); + +static void +push_gear (ModeInfo *mi) +{ + pinion_configuration *pp = &pps[MI_SCREEN(mi)]; + gear *g; + gear *parent = (pp->ngears <= 0 ? 0 : pp->gears[pp->ngears-1]); + + Bool tried_coaxial_p = False; + Bool coaxial_p = False; + Bool last_ditch_coax_p = False; + int loop_count = 0; + + pp->debug_size_failures = 0; + pp->debug_position_failures = 0; + + AGAIN: + loop_count++; + if (loop_count > 100) abort(); /* we're doomed! */ + + g = 0; + + /* If the gears are turning at LUDICROUS SPEED, unhook the train to + reset things to a sane velocity. + + 10,000 RPM at 30 FPS = 5.5 rotations per frame. + 1,000 RPM at 30 FPS = 0.5 rotations per frame. + 600 RPM at 30 FPS = 3 frames per rotation. + 200 RPM at 30 FPS = 9 frames per rotation. + 100 RPM at 30 FPS = 18 frames per rotation. + 50 RPM at 30 FPS = 36 frames per rotation. + 10 RPM at 30 FPS = 3 sec per rotation. + 1 RPM at 30 FPS = 30 sec per rotation. + .5 RPM at 30 FPS = 1 min per rotation. + .1 RPM at 30 FPS = 5 min per rotation. + */ + if (parent && parent->rpm > max_rpm) + { + if (verbose_p) + { + char buf[100]; + rpm_string (parent->rpm, buf); + fprintf (stderr, "%s: ludicrous speed! %s\n\n", progname, buf); + } + parent = 0; + } + + /* If the last N gears we've placed have all been motion-blurred, then + it's a safe guess that we've wandered off into the woods and aren't + coming back. Bail on this train. + */ + if (pp->current_blur_length >= 10) + { + if (verbose_p) + fprintf (stderr, "%s: it's a blurpocalypse!\n\n", progname); + parent = 0; + } + + + + /* Sometimes, try to make a coaxial gear. + */ + if (parent && !parent->coax_p && (random() % 40) == 0) + { + tried_coaxial_p = True; + coaxial_p = True; + g = place_new_gear (mi, parent, coaxial_p); + } + + /* Try to make a regular gear. + */ + if (!g) + { + coaxial_p = False; + g = place_new_gear (mi, parent, coaxial_p); + } + + /* If we couldn't make a regular gear, then try to make a coxial gear + (unless we already tried that.) + */ + if (!g && !tried_coaxial_p && parent && !parent->coax_p) + { + tried_coaxial_p = True; + coaxial_p = True; + g = place_new_gear (mi, parent, coaxial_p); + if (g) + last_ditch_coax_p = True; + } + + /* If we couldn't do that either, then the train has hit a dead end: + start a new train. + */ + if (!g) + { + coaxial_p = False; + if (verbose_p) + fprintf (stderr, "%s: dead end!\n\n", progname); + parent = 0; + g = place_new_gear (mi, parent, coaxial_p); + } + + if (! g) + { + /* Unable to make/place any gears at all! + This can happen if we've backed ourself into a corner very near + the top-right or bottom-right corner of the growth zone. + It's time to add a gear, but there's no room to add one! + In that case, let's just wipe all the gears that are in the + growth zone and try again. + */ + int i; + + if (verbose_p && debug_placement_p) + fprintf (stderr, + "%s: placement: resetting growth zone! " + "failed: %d size, %d pos\n", + progname, + pp->debug_size_failures, pp->debug_position_failures); + for (i = pp->ngears-1; i >= 0; i--) + { + gear *g = pp->gears[i]; + if (g->x - g->r - g->tooth_h < pp->render_left) + delete_gear (mi, g); + } + goto AGAIN; + } + + if (g->coax_p) + { + if (!parent) abort(); + if (g->x != parent->x) abort(); + if (g->y != parent->y) abort(); + if (g->z == parent->z) abort(); + if (g->r == parent->r) abort(); + if (g->th != parent->th) abort(); + if (g->ratio != parent->ratio) abort(); + if (g->rpm != parent->rpm) abort(); + } + + if (verbose_p) + { + fprintf (stderr, "%s: %5lu ", progname, g->id); + + fputc ((g->motion_blur_p ? '*' : ' '), stderr); + fputc (((g->coax_p && last_ditch_coax_p) ? '2' : + g->coax_p ? '1' : ' '), + stderr); + + fprintf (stderr, " %2d%%", + (int) (g->r * 2 * 100 / pp->vp_height)); + fprintf (stderr, " %2d teeth", (int) g->nteeth); + fprintf (stderr, " %3.0f rpm;", g->rpm); + + { + char buf1[50], buf2[50], buf3[100]; + *buf1 = 0; *buf2 = 0; *buf3 = 0; + if (pp->debug_size_failures) + sprintf (buf1, "%3d sz", pp->debug_size_failures); + if (pp->debug_position_failures) + sprintf (buf2, "%2d pos", pp->debug_position_failures); + if (*buf1 || *buf2) + sprintf (buf3, " tries: %-7s%s", buf1, buf2); + fprintf (stderr, "%-21s", buf3); + } + + if (g->base_p) fprintf (stderr, " RESET %lu", pp->current_length); + fprintf (stderr, "\n"); + } + + if (g->base_p) + pp->current_length = 1; + else + pp->current_length++; + + if (g->motion_blur_p) + pp->current_blur_length++; + else + pp->current_blur_length = 0; +} + + + +/* Remove the given gear from the scene and free it. + */ +static void +delete_gear (ModeInfo *mi, gear *g) +{ + pinion_configuration *pp = &pps[MI_SCREEN(mi)]; + int i; + + for (i = 0; i < pp->ngears; i++) /* find this gear in the list */ + if (pp->gears[i] == g) break; + if (pp->gears[i] != g) abort(); + + for (; i < pp->ngears-1; i++) /* pull later entries forward */ + pp->gears[i] = pp->gears[i+1]; + pp->gears[i] = 0; + pp->ngears--; + free_gear (g); +} + + +/* Update the position of each gear in the scene. + */ +static void +scroll_gears (ModeInfo *mi) +{ + pinion_configuration *pp = &pps[MI_SCREEN(mi)]; + int i; + + for (i = 0; i < pp->ngears; i++) + pp->gears[i]->x -= (scroll_speed * 0.002); + + /* if the right edge of any gear is off screen to the left, delete it. + */ + for (i = pp->ngears-1; i >= 0; i--) + { + gear *g = pp->gears[i]; + if (g->x + g->r + g->tooth_h < pp->render_left) + delete_gear (mi, g); + } + + /* if the right edge of the last-added gear is left of the right edge + of the layout area, add another gear. + */ + i = 0; + while (1) + { + gear *g = (pp->ngears <= 0 ? 0 : pp->gears[pp->ngears-1]); + if (!g || g->x + g->r + g->tooth_h < pp->layout_right) + push_gear (mi); + else + break; + i++; + if (debug_one_gear_p) break; + } + + /* + if (i > 1 && verbose_p) + fprintf (stderr, "%s: pushed %d gears\n", progname, i); + */ +} + + +/* Update the rotation of each gear in the scene. + */ +static void +spin_gears (ModeInfo *mi) +{ + pinion_configuration *pp = &pps[MI_SCREEN(mi)]; + int i; + + for (i = 0; i < pp->ngears; i++) + { + gear *g = pp->gears[i]; + double off = (g->ratio * spin_speed); + + if (g->th > 0) + g->th += off; + else + g->th -= off; + } +} + + +/* Run the animation fast (without displaying anything) until the first + gear is just about to come on screen. This is to avoid a big delay + with a blank screen when -scroll is low. + */ +static void +ffwd (ModeInfo *mi) +{ + pinion_configuration *pp = &pps[MI_SCREEN(mi)]; + if (debug_one_gear_p) return; + while (1) + { + gear *g = farthest_gear (mi, True); + if (g && g->x - g->r - g->tooth_h/2 <= pp->vp_right * 0.88) + break; + scroll_gears (mi); + } +} + + + +/* Render one gear in the proper position, creating the gear's + display list first if necessary. + */ +static void +draw_gear (ModeInfo *mi, int which) +{ + Bool wire_p = MI_IS_WIREFRAME(mi); + pinion_configuration *pp = &pps[MI_SCREEN(mi)]; + gear *g = pp->gears[which]; + GLfloat th; + + Bool visible_p = (g->x + g->r + g->tooth_h >= pp->render_left && + g->x - g->r - g->tooth_h <= pp->render_right); + + if (!visible_p && !debug_p) + return; + + if (! g->dlist) + { + g->dlist = glGenLists (1); + if (! g->dlist) + { + /* I don't know how many display lists a GL implementation + is supposed to provide, but hopefully it's more than + "a few hundred", or we'll be in trouble... + */ + check_gl_error ("glGenLists"); + abort(); + } + + glNewList (g->dlist, GL_COMPILE); + g->polygons = draw_involute_gear (g, (wire_p && debug_p ? 2 : wire_p)); + glEndList (); + } + + glPushMatrix(); + + glTranslatef (g->x, g->y, g->z); + + if (g->motion_blur_p && !pp->button_down_p) + { + /* If we're in motion-blur mode, then draw the gear so that each + frame rotates it by exactly one half tooth-width, so that it + looks flickery around the edges. But, revert to the normal + way when the mouse button is down lest the user see overlapping + polygons. + */ + th = g->motion_blur_p * 180.0 / g->nteeth * (g->th > 0 ? 1 : -1); + g->motion_blur_p++; + } + else + th = g->th; + + glRotatef (th, 0, 0, 1); + + glPushName (g->id); + + if (! visible_p) + mi->polygon_count += draw_involute_schematic (g, wire_p); + else + { + glCallList (g->dlist); + mi->polygon_count += g->polygons; + } + + glPopName(); + glPopMatrix(); +} + + +/* Render all gears. + */ +static void +draw_gears (ModeInfo *mi) +{ + pinion_configuration *pp = &pps[MI_SCREEN(mi)]; + Bool wire_p = MI_IS_WIREFRAME(mi); + int i; + + glColor4f (1, 1, 0.8, 1); + + glInitNames(); + + for (i = 0; i < pp->ngears; i++) + draw_gear (mi, i); + + /* draw a line connecting gears that are, uh, geared. */ + if (debug_p) + { + static const GLfloat color[4] = {1.0, 0.0, 0.0, 1.0}; + GLfloat off = 0.1; + GLfloat ox=0, oy=0, oz=0; + + if (!wire_p) glDisable(GL_LIGHTING); + glMaterialfv (GL_FRONT, GL_AMBIENT_AND_DIFFUSE, color); + glColor3f (color[0], color[1], color[2]); + + for (i = 0; i < pp->ngears; i++) + { + gear *g = pp->gears[i]; + glBegin(GL_LINE_STRIP); + glVertex3f (g->x, g->y, g->z - off); + glVertex3f (g->x, g->y, g->z + off); + if (i > 0 && !g->base_p) + glVertex3f (ox, oy, oz + off); + glEnd(); + ox = g->x; + oy = g->y; + oz = g->z; + } + if (!wire_p) glEnable(GL_LIGHTING); + } +} + + +/* Mouse hit detection + */ +static void +find_mouse_gear (ModeInfo *mi) +{ + pinion_configuration *pp = &pps[MI_SCREEN(mi)]; + +# ifndef HAVE_JWZGLES + + int screen_width = MI_WIDTH (mi); + int screen_height = MI_HEIGHT (mi); + GLfloat h = (GLfloat) screen_height / (GLfloat) screen_width; + int x, y; + int hits; + + pp->mouse_gear_id = 0; + + /* Poll mouse position */ + { + Window r, c; + int rx, ry; + unsigned int m; + XQueryPointer (MI_DISPLAY (mi), MI_WINDOW (mi), + &r, &c, &rx, &ry, &x, &y, &m); + } + + if (x < 0 || y < 0 || x > screen_width || y > screen_height) + return; /* out of window */ + + /* Run OpenGL hit detector */ + { + GLint vp[4]; + GLuint selbuf[512]; + + glSelectBuffer (sizeof(selbuf), selbuf); /* set up "select" mode */ + glRenderMode (GL_SELECT); + glMatrixMode (GL_PROJECTION); + glPushMatrix(); + glLoadIdentity(); + glGetIntegerv (GL_VIEWPORT, vp); /* save old vp */ + gluPickMatrix (x, vp[3]-y, 5, 5, vp); + gluPerspective (30.0, 1/h, 1.0, 100.0); /* must match reshape_pinion() */ + glMatrixMode (GL_MODELVIEW); + + draw_gears (mi); /* render into "select" buffer */ + + glMatrixMode (GL_PROJECTION); /* restore old vp */ + glPopMatrix (); + glMatrixMode (GL_MODELVIEW); + glFlush(); + hits = glRenderMode (GL_RENDER); /* done selecting */ + + if (hits > 0) + { + int i; + GLuint name_count = 0; + GLuint *p = (GLuint *) selbuf; + GLuint *pnames = 0; + GLuint min_z = ~0; + + for (i = 0; i < hits; i++) + { + int names = *p++; + if (*p < min_z) /* find match closest to screen */ + { + name_count = names; + min_z = *p; + pnames = p+2; + } + p += names+2; + } + + if (name_count > 0) /* take first hit */ + pp->mouse_gear_id = pnames[0]; + } + } + +#else /* HAVE_JWZGLES */ + /* #### not yet implemented */ + pp->mouse_gear_id = pp->gears[1]->id; + return; +#endif /* HAVE_JWZGLES */ + + +} + + +/* Window management, etc + */ +ENTRYPOINT void +reshape_pinion (ModeInfo *mi, int width, int height) +{ + GLfloat h = (GLfloat) height / (GLfloat) width; + pinion_configuration *pp = &pps[MI_SCREEN(mi)]; + + glViewport (0, 0, (GLint) width, (GLint) height); + + glMatrixMode(GL_PROJECTION); + glLoadIdentity(); + gluPerspective (30.0, 1/h, 1.0, 100.0); + + glMatrixMode(GL_MODELVIEW); + glLoadIdentity(); + gluLookAt( 0.0, 0.0, 30.0, + 0.0, 0.0, 0.0, + 0.0, 1.0, 0.0); + + glClear(GL_COLOR_BUFFER_BIT); + + { + GLfloat render_width, layout_width; + pp->vp_height = 1.0; + pp->vp_width = 1/h; + + pp->vp_left = -pp->vp_width/2; + pp->vp_right = pp->vp_width/2; + pp->vp_top = pp->vp_height/2; + pp->vp_bottom = -pp->vp_height/2; + + render_width = pp->vp_width * 2; + layout_width = pp->vp_width * 0.8 * gear_size; + + pp->render_left = -render_width/2; + pp->render_right = render_width/2; + + pp->layout_left = pp->render_right; + pp->layout_right = pp->layout_left + layout_width; + } +} + + +ENTRYPOINT Bool +pinion_handle_event (ModeInfo *mi, XEvent *event) +{ + pinion_configuration *pp = &pps[MI_SCREEN(mi)]; + + if (event->xany.type == ButtonPress && + event->xbutton.button == Button1) + { + pp->button_down_p = True; + gltrackball_start (pp->trackball, + event->xbutton.x, event->xbutton.y, + MI_WIDTH (mi), MI_HEIGHT (mi)); + return True; + } + else if (event->xany.type == ButtonRelease && + event->xbutton.button == Button1) + { + pp->button_down_p = False; + return True; + } + else if (event->xany.type == ButtonPress && + (event->xbutton.button == Button4 || + event->xbutton.button == Button5 || + event->xbutton.button == Button6 || + event->xbutton.button == Button7)) + { + gltrackball_mousewheel (pp->trackball, event->xbutton.button, 5, + !!event->xbutton.state); + return True; + } + else if (event->xany.type == MotionNotify && + pp->button_down_p) + { + gltrackball_track (pp->trackball, + event->xmotion.x, event->xmotion.y, + MI_WIDTH (mi), MI_HEIGHT (mi)); + return True; + } + else if (event->xany.type == KeyPress) + { + KeySym keysym; + char c = 0; + XLookupString (&event->xkey, &c, 1, &keysym, 0); + if (c == ' ' && debug_one_gear_p && pp->ngears) + { + delete_gear (mi, pp->gears[0]); + return True; + } + } + + return False; +} + + +ENTRYPOINT void +init_pinion (ModeInfo *mi) +{ + pinion_configuration *pp; + + if (!pps) { + pps = (pinion_configuration *) + calloc (MI_NUM_SCREENS(mi), sizeof (pinion_configuration)); + if (!pps) { + fprintf(stderr, "%s: out of memory\n", progname); + exit(1); + } + } + + pp = &pps[MI_SCREEN(mi)]; + + pp->glx_context = init_GL(mi); + + load_fonts (mi); + reshape_pinion (mi, MI_WIDTH(mi), MI_HEIGHT(mi)); + clear_gl_error(); /* WTF? sometimes "invalid op" from glViewport! */ + + pp->title_list = glGenLists (1); + + pp->ngears = 0; + pp->gears_size = 0; + pp->gears = 0; + + pp->plane_displacement = gear_size * 0.1; + + pp->trackball = gltrackball_init (); + + ffwd (mi); +} + + +ENTRYPOINT void +draw_pinion (ModeInfo *mi) +{ + pinion_configuration *pp = &pps[MI_SCREEN(mi)]; + Display *dpy = MI_DISPLAY(mi); + Window window = MI_WINDOW(mi); + Bool wire_p = MI_IS_WIREFRAME(mi); + + if (!pp->glx_context) + return; + + glXMakeCurrent(MI_DISPLAY(mi), MI_WINDOW(mi), *(pp->glx_context)); + + glPushMatrix(); + glRotatef(current_device_rotation(), 0, 0, 1); + + if (!wire_p) + { + GLfloat pos[4] = {-3.0, 1.0, 1.0, 0.0}; + GLfloat amb[4] = { 0.0, 0.0, 0.0, 1.0}; + GLfloat dif[4] = { 1.0, 1.0, 1.0, 1.0}; + GLfloat spc[4] = { 1.0, 1.0, 1.0, 1.0}; + + glEnable(GL_LIGHTING); + glEnable(GL_LIGHT0); + glEnable(GL_DEPTH_TEST); + glEnable(GL_CULL_FACE); + + 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 (!pp->button_down_p) + { + if (!debug_one_gear_p || pp->ngears == 0) + scroll_gears (mi); + spin_gears (mi); + } + + glShadeModel(GL_SMOOTH); + + glEnable(GL_DEPTH_TEST); + glEnable(GL_NORMALIZE); + glEnable(GL_CULL_FACE); + + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + + glPushMatrix (); + { + gltrackball_rotate (pp->trackball); + mi->polygon_count = 0; + + glScalef (16, 16, 16); /* map vp_width/height to the screen */ + + if (debug_one_gear_p) /* zoom in */ + glScalef (3, 3, 3); + else if (debug_p) /* show the "visible" and "layout" areas */ + { + GLfloat ow = pp->layout_right - pp->render_left; + GLfloat rw = pp->render_right - pp->render_left; + GLfloat s = (pp->vp_width / ow) * 0.85; + glScalef (s, s, s); + glTranslatef (-(ow - rw) / 2, 0, 0); + } + else + { + GLfloat s = 1.2; + glScalef (s, s, s); /* zoom in a little more */ + glRotatef (-35, 1, 0, 0); /* tilt back */ + glRotatef ( 8, 0, 1, 0); /* tilt left */ + glTranslatef (0.02, 0.1, 0); /* pan up */ + } + + draw_gears (mi); + + if (debug_p) + { + if (!wire_p) glDisable(GL_LIGHTING); + glColor3f (0.6, 0, 0); + glBegin(GL_LINE_LOOP); + glVertex3f (pp->render_left, pp->vp_top, 0); + glVertex3f (pp->render_right, pp->vp_top, 0); + glVertex3f (pp->render_right, pp->vp_bottom, 0); + glVertex3f (pp->render_left, pp->vp_bottom, 0); + glEnd(); + glColor3f (0.4, 0, 0); + glBegin(GL_LINES); + glVertex3f (pp->vp_left, pp->vp_top, 0); + glVertex3f (pp->vp_left, pp->vp_bottom, 0); + glVertex3f (pp->vp_right, pp->vp_top, 0); + glVertex3f (pp->vp_right, pp->vp_bottom, 0); + glEnd(); + glColor3f (0, 0.4, 0); + glBegin(GL_LINE_LOOP); + glVertex3f (pp->layout_left, pp->vp_top, 0); + glVertex3f (pp->layout_right, pp->vp_top, 0); + glVertex3f (pp->layout_right, pp->vp_bottom, 0); + glVertex3f (pp->layout_left, pp->vp_bottom, 0); + glEnd(); + if (!wire_p) glEnable(GL_LIGHTING); + } + + if (pp->draw_tick++ > 10) /* only do this every N frames */ + { + pp->draw_tick = 0; + find_mouse_gear (mi); + new_label (mi); + } + } + glPopMatrix (); + + glCallList (pp->title_list); + glPopMatrix (); + + if (mi->fps_p) do_fps (mi); + glFinish(); + + glXSwapBuffers(dpy, window); +} + +XSCREENSAVER_MODULE ("Pinion", pinion) + +#endif /* USE_GL */ diff --git a/hacks/glx/pinion.man b/hacks/glx/pinion.man new file mode 100644 index 00000000..3ae6eff5 --- /dev/null +++ b/hacks/glx/pinion.man @@ -0,0 +1,82 @@ +.TH XScreenSaver 1 "30-Oct-99" "X Version 11" +.SH NAME +pinion - draws a scrolling sequence of interconnected gears +.SH SYNOPSIS +.B pinion +[\-display \fIhost:display.screen\fP] [\-window] [\-root] [\-install] +[\-visual \fIvisual\fP] +[\-delay \fIusecs\fP] +[\-scroll \fIratio\fP] +[\-spin \fIratio\fP] +[\-size \fIratio\fP] +[\-max-rpm \fIint\fP] +[\-wireframe] +[\-fps] +.SH DESCRIPTION +The \fIpinion\fP program draws an interconnected set of gears moving +across the screen. +.SH OPTIONS +.I pinion +accepts the following options: +.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 \-install +Install a private colormap for the window. +.TP 8 +.B \-visual \fIvisual\fP\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 \-delay \fIusecs\fP +The delay between frames of the animation, in microseconds: default 15000. +.TP 8 +.B \-spin \fIratio\fP +How fast the gears should spin; default 1.0. 2.0 means twice as fast, +0.5 means half as fast. +.TP 8 +.B \-scroll \fIratio\fP +How fast the gears should scroll past the screen; default 1.0. +2.0 means twice as fast, 0.5 means half as fast. +.TP 8 +.B \-size \fIratio\fP +How big the gears should be, on average; default 1.0. +2.0 means twice as large, 0.5 means half as large. +.TP 8 +.B \-max\-rpm \fIinteger\fP +If any gear exceeds the maximum RPM, the current gear train is broken there, +and we start a new train. Default: 900 RPM. (At 30 FPS, that's about half +a rotation per frame.) +.TP 8 +.B \-wireframe +Render in wireframe instead of solid. +.TP 8 +.B \-fps +Display the current frame rate, CPU load, and polygon count. +.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 gears (MANSUFFIX), +.BR xscreensaver (1), +.BR X (1) +.SH COPYRIGHT +Copyright \(co 2004 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 , 12-Dec-2004. diff --git a/hacks/glx/pipeobjs.c b/hacks/glx/pipeobjs.c new file mode 100644 index 00000000..8874a04d --- /dev/null +++ b/hacks/glx/pipeobjs.c @@ -0,0 +1,3262 @@ +#if 0 +static const char sccsid[] = "@(#)pipeobjs.c 4.04 97/07/28 xlockmore"; +#endif + +/*- + * Points, polygons, and normal vectors to render objects for pipes. + * + * Generated by lw2ogl. + */ + +#ifndef STANDALONE +#include "xlock.h" +#endif + +#ifdef USE_GL + +#include "buildlwo.h" + +static const GLfloat BigValve_PNTS[] = +{ + 0.756788, 0.614672, 0, + 0.779498, 0.599497, 0, + 0.794672, 0.576788, 0, + 0.8, 0.55, 0, + 0.794672, 0.523212, 0, + 0.779498, 0.500503, 0, + 0.756788, 0.485328, 0, + 0.73, 0.48, 0, + 0.703212, 0.485328, 0, + 0.680503, 0.500503, 0, + 0.665328, 0.523212, 0, + 0.66, 0.55, 0, + 0.665328, 0.576788, 0, + 0.680503, 0.599497, 0, + 0.703212, 0.614672, 0, + 0.73, 0.62, 0, + 0.756788, 0.602861, 0.119916, + 0.779498, 0.587978, 0.116956, + 0.794672, 0.565705, 0.112526, + 0.8, 0.539432, 0.1073, + 0.794672, 0.513159, 0.102074, + 0.779498, 0.490886, 0.097643, + 0.756788, 0.476003, 0.094683, + 0.73, 0.470777, 0.093643, + 0.703212, 0.476003, 0.094683, + 0.680503, 0.490886, 0.097643, + 0.665328, 0.513159, 0.102074, + 0.66, 0.539432, 0.1073, + 0.665328, 0.565705, 0.112526, + 0.680503, 0.587978, 0.116956, + 0.703212, 0.602861, 0.119916, + 0.73, 0.608087, 0.120956, + 0.756788, 0.567882, 0.235225, + 0.779498, 0.553863, 0.229418, + 0.794672, 0.532882, 0.220727, + 0.8, 0.508134, 0.210476, + 0.794672, 0.483385, 0.200225, + 0.779498, 0.462404, 0.191534, + 0.756788, 0.448385, 0.185727, + 0.73, 0.443462, 0.183688, + 0.703212, 0.448385, 0.185727, + 0.680503, 0.462404, 0.191534, + 0.665328, 0.483385, 0.200225, + 0.66, 0.508134, 0.210476, + 0.665328, 0.532882, 0.220727, + 0.680503, 0.553863, 0.229418, + 0.703212, 0.567882, 0.235225, + 0.73, 0.572805, 0.237264, + 0.756788, 0.511081, 0.341493, + 0.779498, 0.498464, 0.333063, + 0.794672, 0.479582, 0.320446, + 0.8, 0.457308, 0.305564, + 0.794672, 0.435035, 0.290681, + 0.779498, 0.416153, 0.278064, + 0.756788, 0.403536, 0.269634, + 0.73, 0.399105, 0.266674, + 0.703212, 0.403536, 0.269634, + 0.680503, 0.416153, 0.278064, + 0.665328, 0.435035, 0.290681, + 0.66, 0.457308, 0.305564, + 0.665328, 0.479582, 0.320446, + 0.680503, 0.498464, 0.333063, + 0.703212, 0.511081, 0.341493, + 0.73, 0.515511, 0.344454, + 0.756788, 0.434638, 0.434638, + 0.779498, 0.423909, 0.423909, + 0.794672, 0.407851, 0.407851, + 0.8, 0.388909, 0.388909, + 0.794672, 0.369967, 0.369967, + 0.779498, 0.353909, 0.353909, + 0.756788, 0.343179, 0.343179, + 0.73, 0.339411, 0.339411, + 0.703212, 0.343179, 0.343179, + 0.680503, 0.353909, 0.353909, + 0.665328, 0.369967, 0.369967, + 0.66, 0.388909, 0.388909, + 0.665328, 0.407851, 0.407851, + 0.680503, 0.423909, 0.423909, + 0.703212, 0.434638, 0.434638, + 0.73, 0.438406, 0.438406, + 0.756788, 0.341493, 0.511081, + 0.779498, 0.333063, 0.498464, + 0.794672, 0.320446, 0.479582, + 0.8, 0.305564, 0.457308, + 0.794672, 0.290681, 0.435035, + 0.779498, 0.278064, 0.416153, + 0.756788, 0.269634, 0.403536, + 0.73, 0.266674, 0.399105, + 0.703212, 0.269634, 0.403536, + 0.680503, 0.278064, 0.416153, + 0.665328, 0.290681, 0.435035, + 0.66, 0.305564, 0.457308, + 0.665328, 0.320446, 0.479582, + 0.680503, 0.333063, 0.498464, + 0.703212, 0.341493, 0.511081, + 0.73, 0.344454, 0.515511, + 0.756788, 0.235225, 0.567882, + 0.779498, 0.229418, 0.553863, + 0.794672, 0.220727, 0.532882, + 0.8, 0.210476, 0.508134, + 0.794672, 0.200225, 0.483385, + 0.779498, 0.191534, 0.462404, + 0.756788, 0.185727, 0.448385, + 0.73, 0.183688, 0.443462, + 0.703212, 0.185727, 0.448385, + 0.680503, 0.191534, 0.462404, + 0.665328, 0.200225, 0.483385, + 0.66, 0.210476, 0.508134, + 0.665328, 0.220727, 0.532882, + 0.680503, 0.229418, 0.553863, + 0.703212, 0.235225, 0.567882, + 0.73, 0.237264, 0.572805, + 0.756788, 0.119916, 0.602861, + 0.779498, 0.116956, 0.587978, + 0.794672, 0.112526, 0.565705, + 0.8, 0.1073, 0.539432, + 0.794672, 0.102074, 0.513159, + 0.779498, 0.097643, 0.490886, + 0.756788, 0.094683, 0.476003, + 0.73, 0.093643, 0.470777, + 0.703212, 0.094683, 0.476003, + 0.680503, 0.097643, 0.490886, + 0.665328, 0.102074, 0.513159, + 0.66, 0.1073, 0.539432, + 0.665328, 0.112526, 0.565705, + 0.680503, 0.116956, 0.587978, + 0.703212, 0.119916, 0.602861, + 0.73, 0.120956, 0.608087, + 0.756788, 0, 0.614672, + 0.779498, 0, 0.599497, + 0.794672, 0, 0.576788, + 0.8, 0, 0.55, + 0.794672, 0, 0.523212, + 0.779498, 0, 0.500503, + 0.756788, 0, 0.485328, + 0.73, 0, 0.48, + 0.703212, 0, 0.485328, + 0.680503, 0, 0.500503, + 0.665328, 0, 0.523212, + 0.66, 0, 0.55, + 0.665328, 0, 0.576788, + 0.680503, 0, 0.599497, + 0.703212, 0, 0.614672, + 0.73, 0, 0.62, + 0.756788, -0.119916, 0.602861, + 0.779498, -0.116956, 0.587978, + 0.794672, -0.112526, 0.565705, + 0.8, -0.1073, 0.539432, + 0.794672, -0.102074, 0.513159, + 0.779498, -0.097643, 0.490886, + 0.756788, -0.094683, 0.476003, + 0.73, -0.093643, 0.470777, + 0.703212, -0.094683, 0.476003, + 0.680503, -0.097643, 0.490886, + 0.665328, -0.102074, 0.513159, + 0.66, -0.1073, 0.539432, + 0.665328, -0.112526, 0.565705, + 0.680503, -0.116956, 0.587978, + 0.703212, -0.119916, 0.602861, + 0.73, -0.120956, 0.608087, + 0.756788, -0.235225, 0.567882, + 0.779498, -0.229418, 0.553863, + 0.794672, -0.220727, 0.532882, + 0.8, -0.210476, 0.508134, + 0.794672, -0.200225, 0.483385, + 0.779498, -0.191534, 0.462404, + 0.756788, -0.185727, 0.448385, + 0.73, -0.183688, 0.443462, + 0.703212, -0.185727, 0.448385, + 0.680503, -0.191534, 0.462404, + 0.665328, -0.200225, 0.483385, + 0.66, -0.210476, 0.508134, + 0.665328, -0.220727, 0.532882, + 0.680503, -0.229418, 0.553863, + 0.703212, -0.235225, 0.567882, + 0.73, -0.237264, 0.572805, + 0.756788, -0.341493, 0.511081, + 0.779498, -0.333063, 0.498464, + 0.794672, -0.320446, 0.479582, + 0.8, -0.305564, 0.457308, + 0.794672, -0.290681, 0.435035, + 0.779498, -0.278064, 0.416153, + 0.756788, -0.269634, 0.403536, + 0.73, -0.266674, 0.399105, + 0.703212, -0.269634, 0.403536, + 0.680503, -0.278064, 0.416153, + 0.665328, -0.290681, 0.435035, + 0.66, -0.305564, 0.457308, + 0.665328, -0.320446, 0.479582, + 0.680503, -0.333063, 0.498464, + 0.703212, -0.341493, 0.511081, + 0.73, -0.344454, 0.515511, + 0.756788, -0.434638, 0.434638, + 0.779498, -0.423909, 0.423909, + 0.794672, -0.407851, 0.407851, + 0.8, -0.388909, 0.388909, + 0.794672, -0.369967, 0.369967, + 0.779498, -0.353909, 0.353909, + 0.756788, -0.343179, 0.343179, + 0.73, -0.339411, 0.339411, + 0.703212, -0.343179, 0.343179, + 0.680503, -0.353909, 0.353909, + 0.665328, -0.369967, 0.369967, + 0.66, -0.388909, 0.388909, + 0.665328, -0.407851, 0.407851, + 0.680503, -0.423909, 0.423909, + 0.703212, -0.434638, 0.434638, + 0.73, -0.438406, 0.438406, + 0.756788, -0.511081, 0.341493, + 0.779498, -0.498464, 0.333063, + 0.794672, -0.479582, 0.320446, + 0.8, -0.457308, 0.305564, + 0.794672, -0.435035, 0.290681, + 0.779498, -0.416153, 0.278064, + 0.756788, -0.403536, 0.269634, + 0.73, -0.399105, 0.266674, + 0.703212, -0.403536, 0.269634, + 0.680503, -0.416153, 0.278064, + 0.665328, -0.435035, 0.290681, + 0.66, -0.457308, 0.305564, + 0.665328, -0.479582, 0.320446, + 0.680503, -0.498464, 0.333063, + 0.703212, -0.511081, 0.341493, + 0.73, -0.515511, 0.344454, + 0.756788, -0.567882, 0.235225, + 0.779498, -0.553863, 0.229418, + 0.794672, -0.532882, 0.220727, + 0.8, -0.508134, 0.210476, + 0.794672, -0.483385, 0.200225, + 0.779498, -0.462404, 0.191534, + 0.756788, -0.448385, 0.185727, + 0.73, -0.443462, 0.183688, + 0.703212, -0.448385, 0.185727, + 0.680503, -0.462404, 0.191534, + 0.665328, -0.483385, 0.200225, + 0.66, -0.508134, 0.210476, + 0.665328, -0.532882, 0.220727, + 0.680503, -0.553863, 0.229418, + 0.703212, -0.567882, 0.235225, + 0.73, -0.572805, 0.237264, + 0.756788, -0.602861, 0.119916, + 0.779498, -0.587978, 0.116956, + 0.794672, -0.565705, 0.112526, + 0.8, -0.539432, 0.1073, + 0.794672, -0.513159, 0.102074, + 0.779498, -0.490886, 0.097643, + 0.756788, -0.476003, 0.094683, + 0.73, -0.470777, 0.093643, + 0.703212, -0.476003, 0.094683, + 0.680503, -0.490886, 0.097643, + 0.665328, -0.513159, 0.102074, + 0.66, -0.539432, 0.1073, + 0.665328, -0.565705, 0.112526, + 0.680503, -0.587978, 0.116956, + 0.703212, -0.602861, 0.119916, + 0.73, -0.608087, 0.120956, + 0.756788, -0.614672, 0, + 0.779498, -0.599497, 0, + 0.794672, -0.576788, 0, + 0.8, -0.55, 0, + 0.794672, -0.523212, 0, + 0.779498, -0.500503, 0, + 0.756788, -0.485328, 0, + 0.73, -0.48, 0, + 0.703212, -0.485328, 0, + 0.680503, -0.500503, 0, + 0.665328, -0.523212, 0, + 0.66, -0.55, 0, + 0.665328, -0.576788, 0, + 0.680503, -0.599497, 0, + 0.703212, -0.614672, 0, + 0.73, -0.62, 0, + 0.756788, -0.602861, -0.119916, + 0.779498, -0.587978, -0.116956, + 0.794672, -0.565705, -0.112526, + 0.8, -0.539432, -0.1073, + 0.794672, -0.513159, -0.102074, + 0.779498, -0.490886, -0.097643, + 0.756788, -0.476003, -0.094683, + 0.73, -0.470777, -0.093643, + 0.703212, -0.476003, -0.094683, + 0.680503, -0.490886, -0.097643, + 0.665328, -0.513159, -0.102074, + 0.66, -0.539432, -0.1073, + 0.665328, -0.565705, -0.112526, + 0.680503, -0.587978, -0.116956, + 0.703212, -0.602861, -0.119916, + 0.73, -0.608087, -0.120956, + 0.756788, -0.567882, -0.235225, + 0.779498, -0.553863, -0.229418, + 0.794672, -0.532882, -0.220727, + 0.8, -0.508134, -0.210476, + 0.794672, -0.483385, -0.200225, + 0.779498, -0.462404, -0.191534, + 0.756788, -0.448385, -0.185727, + 0.73, -0.443462, -0.183688, + 0.703212, -0.448385, -0.185727, + 0.680503, -0.462404, -0.191534, + 0.665328, -0.483385, -0.200225, + 0.66, -0.508134, -0.210476, + 0.665328, -0.532882, -0.220727, + 0.680503, -0.553863, -0.229418, + 0.703212, -0.567882, -0.235225, + 0.73, -0.572805, -0.237264, + 0.756788, -0.511081, -0.341493, + 0.779498, -0.498464, -0.333063, + 0.794672, -0.479582, -0.320446, + 0.8, -0.457308, -0.305564, + 0.794672, -0.435035, -0.290681, + 0.779498, -0.416153, -0.278064, + 0.756788, -0.403536, -0.269634, + 0.73, -0.399105, -0.266674, + 0.703212, -0.403536, -0.269634, + 0.680503, -0.416153, -0.278064, + 0.665328, -0.435035, -0.290681, + 0.66, -0.457308, -0.305564, + 0.665328, -0.479582, -0.320446, + 0.680503, -0.498464, -0.333063, + 0.703212, -0.511081, -0.341493, + 0.73, -0.515511, -0.344454, + 0.756788, -0.434638, -0.434638, + 0.779498, -0.423909, -0.423909, + 0.794672, -0.407851, -0.407851, + 0.8, -0.388909, -0.388909, + 0.794672, -0.369967, -0.369967, + 0.779498, -0.353909, -0.353909, + 0.756788, -0.343179, -0.343179, + 0.73, -0.339411, -0.339411, + 0.703212, -0.343179, -0.343179, + 0.680503, -0.353909, -0.353909, + 0.665328, -0.369967, -0.369967, + 0.66, -0.388909, -0.388909, + 0.665328, -0.407851, -0.407851, + 0.680503, -0.423909, -0.423909, + 0.703212, -0.434638, -0.434638, + 0.73, -0.438406, -0.438406, + 0.756788, -0.341493, -0.511081, + 0.779498, -0.333063, -0.498464, + 0.794672, -0.320446, -0.479582, + 0.8, -0.305564, -0.457308, + 0.794672, -0.290681, -0.435035, + 0.779498, -0.278064, -0.416153, + 0.756788, -0.269634, -0.403536, + 0.73, -0.266674, -0.399105, + 0.703212, -0.269634, -0.403536, + 0.680503, -0.278064, -0.416153, + 0.665328, -0.290681, -0.435035, + 0.66, -0.305564, -0.457308, + 0.665328, -0.320446, -0.479582, + 0.680503, -0.333063, -0.498464, + 0.703212, -0.341493, -0.511081, + 0.73, -0.344454, -0.515511, + 0.756788, -0.235225, -0.567882, + 0.779498, -0.229418, -0.553863, + 0.794672, -0.220727, -0.532882, + 0.8, -0.210476, -0.508134, + 0.794672, -0.200225, -0.483385, + 0.779498, -0.191534, -0.462404, + 0.756788, -0.185727, -0.448385, + 0.73, -0.183688, -0.443462, + 0.703212, -0.185727, -0.448385, + 0.680503, -0.191534, -0.462404, + 0.665328, -0.200225, -0.483385, + 0.66, -0.210476, -0.508134, + 0.665328, -0.220727, -0.532882, + 0.680503, -0.229418, -0.553863, + 0.703212, -0.235225, -0.567882, + 0.73, -0.237264, -0.572805, + 0.756788, -0.119916, -0.602861, + 0.779498, -0.116956, -0.587978, + 0.794672, -0.112526, -0.565705, + 0.8, -0.1073, -0.539432, + 0.794672, -0.102074, -0.513159, + 0.779498, -0.097643, -0.490885, + 0.756788, -0.094683, -0.476003, + 0.73, -0.093643, -0.470777, + 0.703212, -0.094683, -0.476003, + 0.680503, -0.097643, -0.490885, + 0.665328, -0.102074, -0.513159, + 0.66, -0.1073, -0.539432, + 0.665328, -0.112526, -0.565705, + 0.680503, -0.116956, -0.587978, + 0.703212, -0.119916, -0.602861, + 0.73, -0.120956, -0.608087, + 0.756788, 0, -0.614672, + 0.779498, 0, -0.599497, + 0.794672, 0, -0.576788, + 0.8, 0, -0.55, + 0.794672, 0, -0.523212, + 0.779498, 0, -0.500503, + 0.756788, 0, -0.485328, + 0.73, 0, -0.48, + 0.703212, 0, -0.485328, + 0.680503, 0, -0.500503, + 0.665328, 0, -0.523212, + 0.66, 0, -0.55, + 0.665328, 0, -0.576788, + 0.680503, 0, -0.599497, + 0.703212, 0, -0.614672, + 0.73, 0, -0.62, + 0.756788, 0.119916, -0.602861, + 0.779498, 0.116956, -0.587978, + 0.794672, 0.112526, -0.565705, + 0.8, 0.1073, -0.539432, + 0.794672, 0.102074, -0.513159, + 0.779498, 0.097643, -0.490886, + 0.756788, 0.094683, -0.476003, + 0.73, 0.093643, -0.470777, + 0.703212, 0.094683, -0.476003, + 0.680503, 0.097643, -0.490886, + 0.665328, 0.102074, -0.513159, + 0.66, 0.1073, -0.539432, + 0.665328, 0.112526, -0.565705, + 0.680503, 0.116956, -0.587978, + 0.703212, 0.119916, -0.602861, + 0.73, 0.120956, -0.608087, + 0.756788, 0.235225, -0.567882, + 0.779498, 0.229418, -0.553863, + 0.794672, 0.220727, -0.532882, + 0.8, 0.210476, -0.508134, + 0.794672, 0.200225, -0.483385, + 0.779498, 0.191534, -0.462404, + 0.756788, 0.185727, -0.448385, + 0.73, 0.183688, -0.443462, + 0.703212, 0.185727, -0.448385, + 0.680503, 0.191534, -0.462404, + 0.665328, 0.200225, -0.483385, + 0.66, 0.210476, -0.508134, + 0.665328, 0.220727, -0.532882, + 0.680503, 0.229418, -0.553863, + 0.703212, 0.235225, -0.567882, + 0.73, 0.237264, -0.572805, + 0.756788, 0.341493, -0.511081, + 0.779498, 0.333063, -0.498464, + 0.794672, 0.320446, -0.479582, + 0.8, 0.305564, -0.457308, + 0.794672, 0.290681, -0.435035, + 0.779498, 0.278064, -0.416153, + 0.756788, 0.269634, -0.403536, + 0.73, 0.266674, -0.399105, + 0.703212, 0.269634, -0.403536, + 0.680503, 0.278064, -0.416153, + 0.665328, 0.290681, -0.435035, + 0.66, 0.305564, -0.457308, + 0.665328, 0.320446, -0.479582, + 0.680503, 0.333063, -0.498464, + 0.703212, 0.341493, -0.511081, + 0.73, 0.344454, -0.515511, + 0.756788, 0.434638, -0.434638, + 0.779498, 0.423909, -0.423909, + 0.794672, 0.407851, -0.407851, + 0.8, 0.388909, -0.388909, + 0.794672, 0.369967, -0.369967, + 0.779498, 0.353909, -0.353909, + 0.756788, 0.343179, -0.343179, + 0.73, 0.339411, -0.339411, + 0.703212, 0.343179, -0.343179, + 0.680503, 0.353909, -0.353909, + 0.665328, 0.369967, -0.369967, + 0.66, 0.388909, -0.388909, + 0.665328, 0.407851, -0.407851, + 0.680503, 0.423909, -0.423909, + 0.703212, 0.434638, -0.434638, + 0.73, 0.438406, -0.438406, + 0.756788, 0.511081, -0.341493, + 0.779498, 0.498464, -0.333063, + 0.794672, 0.479582, -0.320446, + 0.8, 0.457308, -0.305564, + 0.794672, 0.435035, -0.290681, + 0.779498, 0.416153, -0.278064, + 0.756788, 0.403536, -0.269634, + 0.73, 0.399105, -0.266674, + 0.703212, 0.403536, -0.269634, + 0.680503, 0.416153, -0.278064, + 0.665328, 0.435035, -0.290681, + 0.66, 0.457308, -0.305564, + 0.665328, 0.479582, -0.320446, + 0.680503, 0.498464, -0.333063, + 0.703212, 0.511081, -0.341493, + 0.73, 0.515511, -0.344454, + 0.756788, 0.567882, -0.235225, + 0.779498, 0.553863, -0.229418, + 0.794672, 0.532882, -0.220727, + 0.8, 0.508134, -0.210476, + 0.794672, 0.483385, -0.200225, + 0.779498, 0.462404, -0.191534, + 0.756788, 0.448385, -0.185727, + 0.73, 0.443462, -0.183688, + 0.703212, 0.448385, -0.185727, + 0.680503, 0.462404, -0.191534, + 0.665328, 0.483385, -0.200225, + 0.66, 0.508134, -0.210476, + 0.665328, 0.532882, -0.220727, + 0.680503, 0.553863, -0.229418, + 0.703212, 0.567882, -0.235225, + 0.73, 0.572805, -0.237264, + 0.756788, 0.602861, -0.119916, + 0.779498, 0.587978, -0.116956, + 0.794672, 0.565705, -0.112526, + 0.8, 0.539432, -0.1073, + 0.794672, 0.513159, -0.102074, + 0.779498, 0.490885, -0.097643, + 0.756788, 0.476003, -0.094683, + 0.73, 0.470777, -0.093643, + 0.703212, 0.476003, -0.094683, + 0.680503, 0.490885, -0.097643, + 0.665328, 0.513159, -0.102074, + 0.66, 0.539432, -0.1073, + 0.665328, 0.565705, -0.112526, + 0.680503, 0.587978, -0.116956, + 0.703212, 0.602861, -0.119916, + 0.73, 0.608087, -0.120956, + 0.42, 0, -0.2, + 0.42, 0.051764, -0.193185, + 0.42, 0.1, -0.173205, + 0.42, 0.141421, -0.141421, + 0.42, 0.173205, -0.1, + 0.42, 0.193185, -0.051764, + 0.42, 0.2, 0, + 0.42, 0.193185, 0.051764, + 0.42, 0.173205, 0.1, + 0.42, 0.141421, 0.141421, + 0.42, 0.1, 0.173205, + 0.42, 0.051764, 0.193185, + 0.42, 0, 0.2, + 0.42, -0.051764, 0.193185, + 0.42, -0.1, 0.173205, + 0.42, -0.141421, 0.141421, + 0.42, -0.173205, 0.1, + 0.42, -0.193185, 0.051764, + 0.42, -0.2, 0, + 0.42, -0.193185, -0.051764, + 0.42, -0.173205, -0.1, + 0.42, -0.141421, -0.141421, + 0.42, -0.1, -0.173205, + 0.42, -0.051764, -0.193185, + 0.54, 0, -0.2, + 0.54, 0.051764, -0.193185, + 0.54, 0.1, -0.173205, + 0.54, 0.141421, -0.141421, + 0.54, 0.173205, -0.1, + 0.54, 0.193185, -0.051764, + 0.54, 0.2, 0, + 0.54, 0.193185, 0.051764, + 0.54, 0.173205, 0.1, + 0.54, 0.141421, 0.141421, + 0.54, 0.1, 0.173205, + 0.54, 0.051764, 0.193185, + 0.54, 0, 0.2, + 0.54, -0.051764, 0.193185, + 0.54, -0.1, 0.173205, + 0.54, -0.141421, 0.141421, + 0.54, -0.173205, 0.1, + 0.54, -0.193185, 0.051764, + 0.54, -0.2, 0, + 0.54, -0.193185, -0.051764, + 0.54, -0.173205, -0.1, + 0.54, -0.141421, -0.141421, + 0.54, -0.1, -0.173205, + 0.54, -0.051764, -0.193185, + 0.79, 0.06, 0, + 0.785433, 0.06, -0.022961, + 0.772426, 0.06, -0.042426, + 0.752961, 0.06, -0.055433, + 0.73, 0.06, -0.06, + 0.707039, 0.06, -0.055433, + 0.687574, 0.06, -0.042426, + 0.674567, 0.06, -0.022961, + 0.67, 0.06, 0, + 0.674567, 0.06, 0.022961, + 0.687574, 0.06, 0.042426, + 0.707039, 0.06, 0.055433, + 0.73, 0.06, 0.06, + 0.752961, 0.06, 0.055433, + 0.772426, 0.06, 0.042426, + 0.785433, 0.06, 0.022961, + 0.79, 0.55, 0, + 0.785433, 0.55, -0.022961, + 0.772426, 0.55, -0.042426, + 0.752961, 0.55, -0.055433, + 0.73, 0.55, -0.06, + 0.707039, 0.55, -0.055433, + 0.687574, 0.55, -0.042426, + 0.674567, 0.55, -0.022961, + 0.67, 0.55, 0, + 0.674567, 0.55, 0.022961, + 0.687574, 0.55, 0.042426, + 0.707039, 0.55, 0.055433, + 0.73, 0.55, 0.06, + 0.752961, 0.55, 0.055433, + 0.772426, 0.55, 0.042426, + 0.785433, 0.55, 0.022961, + 0.79, 0, 0.06, + 0.785433, 0.022961, 0.06, + 0.772426, 0.042426, 0.06, + 0.752961, 0.055433, 0.06, + 0.707039, 0.055433, 0.06, + 0.687574, 0.042426, 0.06, + 0.674567, 0.022961, 0.06, + 0.67, 0, 0.06, + 0.674567, -0.022961, 0.06, + 0.687574, -0.042426, 0.06, + 0.707039, -0.055433, 0.06, + 0.73, -0.06, 0.06, + 0.752961, -0.055433, 0.06, + 0.772426, -0.042426, 0.06, + 0.785433, -0.022961, 0.06, + 0.79, 0, 0.55, + 0.785433, 0.022961, 0.55, + 0.772426, 0.042426, 0.55, + 0.752961, 0.055433, 0.55, + 0.73, 0.06, 0.55, + 0.707039, 0.055433, 0.55, + 0.687574, 0.042426, 0.55, + 0.674567, 0.022961, 0.55, + 0.67, 0, 0.55, + 0.674567, -0.022961, 0.55, + 0.687574, -0.042426, 0.55, + 0.707039, -0.055433, 0.55, + 0.73, -0.06, 0.55, + 0.752961, -0.055433, 0.55, + 0.772426, -0.042426, 0.55, + 0.785433, -0.022961, 0.55, + 0.79, -0.06, 0, + 0.785433, -0.06, 0.022961, + 0.772426, -0.06, 0.042426, + 0.752961, -0.06, 0.055433, + 0.707039, -0.06, 0.055433, + 0.687574, -0.06, 0.042426, + 0.674567, -0.06, 0.022961, + 0.67, -0.06, 0, + 0.674567, -0.06, -0.022961, + 0.687574, -0.06, -0.042426, + 0.707039, -0.06, -0.055433, + 0.73, -0.06, -0.06, + 0.752961, -0.06, -0.055433, + 0.772426, -0.06, -0.042426, + 0.785433, -0.06, -0.022961, + 0.79, -0.55, 0, + 0.785433, -0.55, 0.022961, + 0.772426, -0.55, 0.042426, + 0.752961, -0.55, 0.055433, + 0.73, -0.55, 0.06, + 0.707039, -0.55, 0.055433, + 0.687574, -0.55, 0.042426, + 0.674567, -0.55, 0.022961, + 0.67, -0.55, 0, + 0.674567, -0.55, -0.022961, + 0.687574, -0.55, -0.042426, + 0.707039, -0.55, -0.055433, + 0.73, -0.55, -0.06, + 0.752961, -0.55, -0.055433, + 0.772426, -0.55, -0.042426, + 0.785433, -0.55, -0.022961, + 0.79, 0, -0.06, + 0.785433, -0.022961, -0.06, + 0.772426, -0.042426, -0.06, + 0.752961, -0.055433, -0.06, + 0.707039, -0.055433, -0.06, + 0.687574, -0.042426, -0.06, + 0.674567, -0.022961, -0.06, + 0.67, 0, -0.06, + 0.674567, 0.022961, -0.06, + 0.687574, 0.042426, -0.06, + 0.707039, 0.055433, -0.06, + 0.752961, 0.055433, -0.06, + 0.772426, 0.042426, -0.06, + 0.785433, 0.022961, -0.06, + 0.79, 0, -0.55, + 0.785433, -0.022961, -0.55, + 0.772426, -0.042426, -0.55, + 0.752961, -0.055433, -0.55, + 0.73, -0.06, -0.55, + 0.707039, -0.055433, -0.55, + 0.687574, -0.042426, -0.55, + 0.674567, -0.022961, -0.55, + 0.67, 0, -0.55, + 0.674567, 0.022961, -0.55, + 0.687574, 0.042426, -0.55, + 0.707039, 0.055433, -0.55, + 0.73, 0.06, -0.55, + 0.752961, 0.055433, -0.55, + 0.772426, 0.042426, -0.55, + 0.785433, 0.022961, -0.55, + 0.54, 0, -0.1, + 0.54, 0.038268, -0.092388, + 0.54, 0.070711, -0.070711, + 0.54, 0.092388, -0.038268, + 0.54, 0.1, 0, + 0.54, 0.092388, 0.038268, + 0.54, 0.070711, 0.070711, + 0.54, 0.038268, 0.092388, + 0.54, 0, 0.1, + 0.54, -0.038268, 0.092388, + 0.54, -0.070711, 0.070711, + 0.54, -0.092388, 0.038268, + 0.54, -0.1, 0, + 0.54, -0.092388, -0.038268, + 0.54, -0.070711, -0.070711, + 0.54, -0.038268, -0.092388, + 0.8, 0, -0.1, + 0.8, 0.038268, -0.092388, + 0.8, 0.070711, -0.070711, + 0.8, 0.092388, -0.038268, + 0.8, 0.1, 0, + 0.8, 0.092388, 0.038268, + 0.8, 0.070711, 0.070711, + 0.8, 0.038268, 0.092388, + 0.8, 0, 0.1, + 0.8, -0.038268, 0.092388, + 0.8, -0.070711, 0.070711, + 0.8, -0.092388, 0.038268, + 0.8, -0.1, 0, + 0.8, -0.092388, -0.038268, + 0.8, -0.070711, -0.070711, + 0.8, -0.038268, -0.092388, +}; + +static const GLfloat BigValve_normals[] = +{ + -1, 0, 0, + 0, 0.19509, -0.980785, + 0, 0.55557, -0.83147, + 0, 0.83147, -0.55557, + 0, 0.980785, -0.19509, + 0, 0.980785, 0.19509, + 0, 0.83147, 0.55557, + 0, 0.55557, 0.83147, + 0, 0.19509, 0.980785, + 0, -0.19509, 0.980785, + 0, -0.55557, 0.83147, + 0, -0.83147, 0.55557, + 0, -0.980785, 0.19509, + 0, -0.980785, -0.19509, + 0, -0.83147, -0.55557, + 0, -0.55557, -0.83147, + 0, -0.19509, -0.980785, + 1, 0, 0, + 0.980785, -0.195092, 0, + 0.83147, -0.555569, 0, + 0.555569, -0.83147, 0, + 0.195091, -0.980785, 0, + -0.19509, -0.980785, 0, + -0.55557, -0.831469, 0, + -0.831469, -0.555571, 0, + -0.980785, -0.195089, 0, + -0.980785, 0.195089, 0, + -0.831469, 0.555571, 0, + -0.55557, 0.831469, 0, + -0.19509, 0.980785, 0, + 0.195091, 0.980785, 0, + 0.555569, 0.83147, 0, + 0.83147, 0.555569, 0, + 0.980785, 0.195092, 0, + 0.980785, 0, 0.195092, + 0.83147, 0, 0.555569, + 0.555569, 0, 0.83147, + 0.195091, 0, 0.980785, + -0.19509, 0, 0.980785, + -0.55557, 0, 0.831469, + -0.831469, 0, 0.555571, + -0.980785, 0, 0.195089, + -0.980785, 0, -0.195089, + -0.831469, 0, -0.555571, + -0.55557, 0, -0.831469, + -0.19509, 0, -0.980785, + 0.195091, 0, -0.980785, + 0.555569, 0, -0.83147, + 0.83147, 0, -0.555569, + 0.980785, 0, -0.195092, + 0.980785, 0.195092, 0, + 0.83147, 0.555569, 0, + 0.555569, 0.83147, 0, + 0.195091, 0.980785, 0, + -0.19509, 0.980785, 0, + -0.55557, 0.831469, 0, + -0.831469, 0.555571, 0, + -0.980785, 0.195089, 0, + -0.980785, -0.195089, 0, + -0.831469, -0.555571, 0, + -0.55557, -0.831469, 0, + -0.19509, -0.980785, 0, + 0.195091, -0.980785, 0, + 0.555569, -0.83147, 0, + 0.83147, -0.555569, 0, + 0.980785, -0.195092, 0, + 0.980785, 0, -0.195092, + 0.83147, 0, -0.555569, + 0.555569, 0, -0.83147, + 0.195091, 0, -0.980785, + -0.19509, 0, -0.980785, + -0.55557, 0, -0.831469, + -0.831469, 0, -0.555571, + -0.980785, 0, -0.195089, + -0.980785, 0, 0.195089, + -0.831469, 0, 0.555571, + -0.55557, 0, 0.831469, + -0.19509, 0, 0.980785, + 0.195091, 0, 0.980785, + 0.555569, 0, 0.83147, + 0.83147, 0, 0.555569, + 0.980785, 0, 0.195092, + -1, 0, 0, + 0, 0.130526, -0.991445, + 0, 0.382684, -0.92388, + 0, 0.608761, -0.793353, + 0, 0.793353, -0.608761, + 0, 0.92388, -0.382684, + 0, 0.991445, -0.130526, + 0, 0.991445, 0.130526, + 0, 0.92388, 0.382684, + 0, 0.793353, 0.608761, + 0, 0.608761, 0.793353, + 0, 0.382684, 0.92388, + 0, 0.130526, 0.991445, + 0, -0.130526, 0.991445, + 0, -0.382684, 0.92388, + 0, -0.608761, 0.793353, + 0, -0.793353, 0.608761, + 0, -0.92388, 0.382684, + 0, -0.991445, 0.130526, + 0, -0.991445, -0.130526, + 0, -0.92388, -0.382684, + 0, -0.793353, -0.608761, + 0, -0.608761, -0.793353, + 0, -0.382684, -0.92388, + 0, -0.130526, -0.991445, + 1, 0, 0, + 0.194185, 0.976241, 0.096151, + -0.194185, 0.976241, 0.096151, + -0.553718, 0.828695, 0.081619, + -0.830228, 0.55474, 0.054637, + -0.980604, 0.195054, 0.019211, + -0.980605, -0.195053, -0.019211, + -0.830227, -0.554741, -0.054637, + -0.553717, -0.828695, -0.081619, + -0.194187, -0.976241, -0.096151, + 0.194188, -0.976241, -0.096151, + 0.553716, -0.828696, -0.081619, + 0.830227, -0.554741, -0.054637, + 0.980604, -0.195053, -0.019211, + 0.980604, 0.195054, 0.019211, + 0.830228, 0.55474, 0.054637, + 0.553717, 0.828695, 0.081619, + 0.194186, 0.938725, 0.284759, + -0.194185, 0.938725, 0.284759, + -0.553717, 0.796849, 0.241721, + -0.830228, 0.533421, 0.161812, + -0.980604, 0.187558, 0.056895, + -0.980604, -0.187558, -0.056895, + -0.830227, -0.533422, -0.161812, + -0.553717, -0.796849, -0.241722, + -0.194186, -0.938725, -0.284759, + 0.194187, -0.938724, -0.284759, + 0.553716, -0.796849, -0.241722, + 0.830227, -0.533422, -0.161812, + 0.980604, -0.187558, -0.056895, + 0.980604, 0.187558, 0.056895, + 0.830228, 0.533421, 0.161811, + 0.553716, 0.79685, 0.241722, + 0.194186, 0.865134, 0.462423, + -0.194185, 0.865134, 0.462424, + -0.553717, 0.73438, 0.392534, + -0.830228, 0.491604, 0.262768, + -0.980604, 0.172854, 0.092393, + -0.980604, -0.172854, -0.092393, + -0.830227, -0.491605, -0.262768, + -0.553717, -0.73438, -0.392534, + -0.194187, -0.865134, -0.462424, + 0.194187, -0.865134, -0.462423, + 0.553716, -0.734381, -0.392534, + 0.830227, -0.491605, -0.262768, + 0.980604, -0.172854, -0.092393, + 0.980604, 0.172854, 0.092393, + 0.830228, 0.491604, 0.262768, + 0.553716, 0.734381, 0.392535, + 0.194186, 0.758296, 0.622317, + -0.194186, 0.758296, 0.622318, + -0.553717, 0.64369, 0.528263, + -0.830228, 0.430895, 0.353626, + -0.980604, 0.151508, 0.12434, + -0.980604, -0.151508, -0.124339, + -0.830227, -0.430895, -0.353627, + -0.553717, -0.64369, -0.528263, + -0.194186, -0.758296, -0.622317, + 0.194186, -0.758296, -0.622318, + 0.553716, -0.64369, -0.528263, + 0.830227, -0.430895, -0.353627, + 0.980604, -0.151508, -0.124339, + 0.980604, 0.151508, 0.12434, + 0.830228, 0.430895, 0.353626, + 0.553716, 0.64369, 0.528263, + 0.194186, 0.622317, 0.758296, + -0.194185, 0.622318, 0.758296, + -0.553717, 0.528263, 0.64369, + -0.830228, 0.353626, 0.430895, + -0.980604, 0.124339, 0.151508, + -0.980604, -0.124339, -0.151508, + -0.830227, -0.353627, -0.430895, + -0.553717, -0.528262, -0.643689, + -0.194187, -0.622317, -0.758296, + 0.194187, -0.622317, -0.758296, + 0.553716, -0.528263, -0.64369, + 0.830227, -0.353627, -0.430895, + 0.980604, -0.124339, -0.151508, + 0.980604, 0.12434, 0.151508, + 0.830228, 0.353626, 0.430895, + 0.553716, 0.528263, 0.64369, + 0.194186, 0.462423, 0.865134, + -0.194185, 0.462424, 0.865134, + -0.553717, 0.392534, 0.73438, + -0.830228, 0.262768, 0.491604, + -0.980604, 0.092393, 0.172855, + -0.980604, -0.092392, -0.172854, + -0.830227, -0.262768, -0.491605, + -0.553717, -0.392534, -0.73438, + -0.194186, -0.462424, -0.865134, + 0.194187, -0.462423, -0.865134, + 0.553716, -0.392535, -0.734381, + 0.830227, -0.262768, -0.491605, + 0.980604, -0.092392, -0.172854, + 0.980604, 0.092393, 0.172855, + 0.830228, 0.262768, 0.491604, + 0.553716, 0.392535, 0.734381, + 0.194185, 0.284759, 0.938725, + -0.194185, 0.284759, 0.938725, + -0.553718, 0.241721, 0.796848, + -0.830228, 0.161812, 0.533422, + -0.980604, 0.056895, 0.187558, + -0.980604, -0.056895, -0.187558, + -0.830227, -0.161812, -0.533423, + -0.553717, -0.241722, -0.796849, + -0.194187, -0.284759, -0.938725, + 0.194188, -0.284759, -0.938724, + 0.553716, -0.241722, -0.796849, + 0.830227, -0.161812, -0.533423, + 0.980604, -0.056895, -0.187557, + 0.980604, 0.056895, 0.187558, + 0.830228, 0.161812, 0.533422, + 0.553717, 0.241722, 0.796849, + 0.194186, 0.096151, 0.976241, + -0.194186, 0.096151, 0.976241, + -0.553717, 0.081619, 0.828695, + -0.830228, 0.054637, 0.55474, + -0.980604, 0.019211, 0.195054, + -0.980604, -0.019211, -0.195054, + -0.830227, -0.054637, -0.554741, + -0.553717, -0.081619, -0.828695, + -0.194187, -0.096151, -0.976241, + 0.194187, -0.096151, -0.976241, + 0.553716, -0.081619, -0.828696, + 0.830227, -0.054637, -0.554741, + 0.980604, -0.019211, -0.195054, + 0.980604, 0.019211, 0.195054, + 0.830228, 0.054637, 0.55474, + 0.553716, 0.081619, 0.828696, + 0.194185, -0.096151, 0.976241, + -0.194185, -0.096151, 0.976241, + -0.553718, -0.081619, 0.828695, + -0.830228, -0.054637, 0.55474, + -0.980604, -0.019211, 0.195054, + -0.980605, 0.019211, -0.195053, + -0.830227, 0.054637, -0.554741, + -0.553717, 0.081619, -0.828695, + -0.194187, 0.096151, -0.976241, + 0.194188, 0.096151, -0.976241, + 0.553716, 0.081619, -0.828696, + 0.830227, 0.054637, -0.554741, + 0.980604, 0.019211, -0.195053, + 0.980604, -0.019211, 0.195054, + 0.830228, -0.054637, 0.55474, + 0.553717, -0.081619, 0.828695, + 0.194186, -0.284759, 0.938725, + -0.194185, -0.284759, 0.938725, + -0.553717, -0.241721, 0.796849, + -0.830228, -0.161812, 0.533421, + -0.980604, -0.056895, 0.187558, + -0.980604, 0.056895, -0.187558, + -0.830227, 0.161812, -0.533422, + -0.553717, 0.241722, -0.796849, + -0.194186, 0.284759, -0.938725, + 0.194187, 0.284759, -0.938724, + 0.553716, 0.241722, -0.796849, + 0.830227, 0.161812, -0.533422, + 0.980604, 0.056895, -0.187558, + 0.980604, -0.056895, 0.187558, + 0.830228, -0.161811, 0.533421, + 0.553716, -0.241722, 0.79685, + 0.194186, -0.462423, 0.865134, + -0.194185, -0.462424, 0.865134, + -0.553717, -0.392534, 0.73438, + -0.830228, -0.262768, 0.491604, + -0.980604, -0.092393, 0.172854, + -0.980604, 0.092393, -0.172854, + -0.830227, 0.262768, -0.491605, + -0.553717, 0.392534, -0.73438, + -0.194187, 0.462424, -0.865134, + 0.194187, 0.462423, -0.865134, + 0.553716, 0.392534, -0.734381, + 0.830227, 0.262768, -0.491605, + 0.980604, 0.092393, -0.172854, + 0.980604, -0.092393, 0.172854, + 0.830228, -0.262768, 0.491604, + 0.553716, -0.392535, 0.734381, + 0.194186, -0.622317, 0.758296, + -0.194186, -0.622318, 0.758296, + -0.553717, -0.528263, 0.64369, + -0.830228, -0.353626, 0.430895, + -0.980604, -0.12434, 0.151508, + -0.980604, 0.124339, -0.151508, + -0.830227, 0.353627, -0.430895, + -0.553717, 0.528263, -0.64369, + -0.194186, 0.622317, -0.758296, + 0.194186, 0.622318, -0.758296, + 0.553716, 0.528263, -0.64369, + 0.830227, 0.353627, -0.430895, + 0.980604, 0.124339, -0.151508, + 0.980604, -0.12434, 0.151508, + 0.830228, -0.353626, 0.430895, + 0.553716, -0.528263, 0.64369, + 0.194186, -0.758296, 0.622317, + -0.194185, -0.758296, 0.622318, + -0.553717, -0.64369, 0.528263, + -0.830228, -0.430895, 0.353626, + -0.980604, -0.151508, 0.124339, + -0.980604, 0.151508, -0.124339, + -0.830227, 0.430895, -0.353627, + -0.553717, 0.643689, -0.528262, + -0.194187, 0.758296, -0.622317, + 0.194187, 0.758296, -0.622317, + 0.553716, 0.64369, -0.528263, + 0.830227, 0.430895, -0.353627, + 0.980604, 0.151508, -0.124339, + 0.980604, -0.151508, 0.12434, + 0.830228, -0.430895, 0.353626, + 0.553716, -0.64369, 0.528263, + 0.194186, -0.865134, 0.462423, + -0.194185, -0.865134, 0.462424, + -0.553717, -0.73438, 0.392534, + -0.830228, -0.491604, 0.262768, + -0.980604, -0.172855, 0.092393, + -0.980604, 0.172854, -0.092393, + -0.830227, 0.491605, -0.262768, + -0.553717, 0.73438, -0.392534, + -0.194186, 0.865134, -0.462424, + 0.194187, 0.865134, -0.462423, + 0.553716, 0.734381, -0.392535, + 0.830228, 0.491605, -0.262768, + 0.980604, 0.172854, -0.092393, + 0.980604, -0.172855, 0.092393, + 0.830228, -0.491604, 0.262768, + 0.553716, -0.734381, 0.392535, + 0.194185, -0.938725, 0.284759, + -0.194185, -0.938725, 0.284759, + -0.553718, -0.796848, 0.241721, + -0.830228, -0.533422, 0.161812, + -0.980604, -0.187558, 0.056895, + -0.980605, 0.187557, -0.056895, + -0.830227, 0.533423, -0.161812, + -0.553717, 0.796849, -0.241722, + -0.194187, 0.938725, -0.284759, + 0.194188, 0.938724, -0.284759, + 0.553716, 0.796849, -0.241722, + 0.830227, 0.533423, -0.161812, + 0.980604, 0.187557, -0.056895, + 0.980604, -0.187558, 0.056895, + 0.830228, -0.533422, 0.161812, + 0.553717, -0.796849, 0.241722, + 0.194186, -0.976241, 0.096151, + -0.194186, -0.976241, 0.096151, + -0.553717, -0.828695, 0.081619, + -0.830228, -0.55474, 0.054637, + -0.980604, -0.195054, 0.019211, + -0.980604, 0.195054, -0.019211, + -0.830227, 0.554741, -0.054637, + -0.553717, 0.828695, -0.081619, + -0.194187, 0.976241, -0.096151, + 0.194187, 0.976241, -0.096151, + 0.553716, 0.828696, -0.081619, + 0.830227, 0.554741, -0.054637, + 0.980604, 0.195054, -0.019211, + 0.980604, -0.195054, 0.019211, + 0.830228, -0.55474, 0.054637, + 0.553716, -0.828696, 0.081619, + 0.194185, -0.976241, -0.096151, + -0.194185, -0.976241, -0.096151, + -0.553718, -0.828695, -0.081619, + -0.830228, -0.55474, -0.054637, + -0.980604, -0.195054, -0.019211, + -0.980605, 0.195053, 0.019211, + -0.830227, 0.554741, 0.054637, + -0.553717, 0.828695, 0.081619, + -0.194187, 0.976241, 0.096151, + 0.194188, 0.976241, 0.096151, + 0.553716, 0.828696, 0.081619, + 0.830227, 0.554741, 0.054637, + 0.980604, 0.195053, 0.019211, + 0.980604, -0.195054, -0.019211, + 0.830228, -0.55474, -0.054637, + 0.553717, -0.828695, -0.081619, + 0.194186, -0.938725, -0.284759, + -0.194185, -0.938725, -0.284759, + -0.553717, -0.796849, -0.241721, + -0.830228, -0.533421, -0.161812, + -0.980604, -0.187558, -0.056895, + -0.980604, 0.187558, 0.056895, + -0.830227, 0.533422, 0.161812, + -0.553717, 0.796849, 0.241722, + -0.194186, 0.938725, 0.284759, + 0.194187, 0.938724, 0.284759, + 0.553716, 0.796849, 0.241722, + 0.830227, 0.533422, 0.161812, + 0.980604, 0.187558, 0.056895, + 0.980604, -0.187558, -0.056895, + 0.830228, -0.533421, -0.161811, + 0.553716, -0.79685, -0.241722, + 0.194186, -0.865134, -0.462423, + -0.194185, -0.865134, -0.462424, + -0.553717, -0.73438, -0.392534, + -0.830228, -0.491604, -0.262768, + -0.980604, -0.172854, -0.092393, + -0.980604, 0.172854, 0.092393, + -0.830227, 0.491605, 0.262768, + -0.553717, 0.73438, 0.392534, + -0.194187, 0.865134, 0.462424, + 0.194187, 0.865134, 0.462423, + 0.553716, 0.734381, 0.392534, + 0.830227, 0.491605, 0.262768, + 0.980604, 0.172854, 0.092393, + 0.980604, -0.172854, -0.092393, + 0.830228, -0.491604, -0.262768, + 0.553716, -0.734381, -0.392535, + 0.194186, -0.758296, -0.622317, + -0.194186, -0.758296, -0.622318, + -0.553717, -0.64369, -0.528263, + -0.830228, -0.430895, -0.353626, + -0.980604, -0.151508, -0.12434, + -0.980604, 0.151508, 0.124339, + -0.830227, 0.430895, 0.353627, + -0.553717, 0.64369, 0.528263, + -0.194186, 0.758296, 0.622317, + 0.194186, 0.758296, 0.622318, + 0.553716, 0.64369, 0.528263, + 0.830227, 0.430895, 0.353627, + 0.980604, 0.151508, 0.124339, + 0.980604, -0.151508, -0.12434, + 0.830228, -0.430895, -0.353626, + 0.553716, -0.64369, -0.528263, + 0.194186, -0.622317, -0.758296, + -0.194185, -0.622318, -0.758296, + -0.553717, -0.528263, -0.64369, + -0.830228, -0.353626, -0.430895, + -0.980604, -0.124339, -0.151508, + -0.980604, 0.124339, 0.151508, + -0.830227, 0.353627, 0.430895, + -0.553717, 0.528262, 0.643689, + -0.194187, 0.622317, 0.758296, + 0.194187, 0.622317, 0.758296, + 0.553716, 0.528263, 0.64369, + 0.830227, 0.353627, 0.430895, + 0.980604, 0.124339, 0.151508, + 0.980604, -0.12434, -0.151508, + 0.830228, -0.353626, -0.430895, + 0.553716, -0.528263, -0.64369, + 0.194186, -0.462423, -0.865134, + -0.194185, -0.462424, -0.865134, + -0.553717, -0.392534, -0.73438, + -0.830228, -0.262768, -0.491604, + -0.980604, -0.092393, -0.172855, + -0.980604, 0.092393, 0.172854, + -0.830227, 0.262768, 0.491605, + -0.553717, 0.392534, 0.73438, + -0.194186, 0.462424, 0.865134, + 0.194187, 0.462423, 0.865134, + 0.553716, 0.392535, 0.734381, + 0.830228, 0.262768, 0.491605, + 0.980604, 0.092393, 0.172854, + 0.980604, -0.092393, -0.172855, + 0.830228, -0.262768, -0.491604, + 0.553716, -0.392535, -0.734381, + 0.194185, -0.284759, -0.938725, + -0.194185, -0.284759, -0.938725, + -0.553718, -0.241721, -0.796848, + -0.830228, -0.161812, -0.533422, + -0.980604, -0.056895, -0.187558, + -0.980605, 0.056895, 0.187557, + -0.830227, 0.161812, 0.533422, + -0.553716, 0.241722, 0.796849, + -0.194187, 0.284759, 0.938725, + 0.194188, 0.284759, 0.938724, + 0.553716, 0.241722, 0.79685, + 0.830227, 0.161812, 0.533423, + 0.980604, 0.056895, 0.187557, + 0.980604, -0.056895, -0.187558, + 0.830228, -0.161812, -0.533422, + 0.553717, -0.241722, -0.796849, + 0.194186, -0.096151, -0.976241, + -0.194186, -0.096151, -0.976241, + -0.553717, -0.081619, -0.828695, + -0.830228, -0.054637, -0.55474, + -0.980604, -0.019211, -0.195054, + -0.980604, 0.019211, 0.195054, + -0.830227, 0.054637, 0.554741, + -0.553717, 0.081619, 0.828695, + -0.194187, 0.096151, 0.976241, + 0.194187, 0.096151, 0.976241, + 0.553716, 0.08162, 0.828696, + 0.830227, 0.054637, 0.554741, + 0.980604, 0.019211, 0.195054, + 0.980604, -0.019211, -0.195054, + 0.830228, -0.054637, -0.55474, + 0.553716, -0.081619, -0.828696, + 0.194185, 0.096151, -0.976241, + -0.194185, 0.096151, -0.976241, + -0.553718, 0.081619, -0.828695, + -0.830228, 0.054637, -0.55474, + -0.980604, 0.019211, -0.195054, + -0.980605, -0.019211, 0.195053, + -0.830227, -0.054637, 0.554741, + -0.553717, -0.081619, 0.828695, + -0.194187, -0.096151, 0.976241, + 0.194188, -0.096151, 0.976241, + 0.553716, -0.081619, 0.828696, + 0.830227, -0.054637, 0.554741, + 0.980604, -0.019211, 0.195053, + 0.980604, 0.019211, -0.195054, + 0.830228, 0.054637, -0.55474, + 0.553717, 0.081619, -0.828695, + 0.194186, 0.284759, -0.938725, + -0.194185, 0.284759, -0.938725, + -0.553717, 0.241721, -0.796849, + -0.830228, 0.161812, -0.533421, + -0.980604, 0.056895, -0.187558, + -0.980604, -0.056895, 0.187558, + -0.830227, -0.161812, 0.533422, + -0.553717, -0.241722, 0.796849, + -0.194186, -0.284759, 0.938725, + 0.194187, -0.284759, 0.938724, + 0.553716, -0.241722, 0.796849, + 0.830227, -0.161812, 0.533422, + 0.980604, -0.056895, 0.187558, + 0.980604, 0.056895, -0.187558, + 0.830228, 0.161811, -0.533421, + 0.553716, 0.241722, -0.79685, + 0.194186, 0.462423, -0.865134, + -0.194185, 0.462424, -0.865134, + -0.553717, 0.392534, -0.73438, + -0.830228, 0.262768, -0.491604, + -0.980604, 0.092393, -0.172854, + -0.980604, -0.092393, 0.172854, + -0.830227, -0.262768, 0.491605, + -0.553717, -0.392534, 0.73438, + -0.194187, -0.462424, 0.865134, + 0.194187, -0.462423, 0.865134, + 0.553716, -0.392534, 0.734381, + 0.830227, -0.262768, 0.491605, + 0.980604, -0.092393, 0.172854, + 0.980604, 0.092393, -0.172854, + 0.830228, 0.262768, -0.491604, + 0.553716, 0.392535, -0.734381, + 0.194186, 0.622317, -0.758296, + -0.194186, 0.622318, -0.758296, + -0.553717, 0.528263, -0.64369, + -0.830228, 0.353626, -0.430895, + -0.980604, 0.12434, -0.151508, + -0.980604, -0.124339, 0.151508, + -0.830227, -0.353627, 0.430895, + -0.553717, -0.528263, 0.64369, + -0.194186, -0.622317, 0.758296, + 0.194186, -0.622318, 0.758296, + 0.553716, -0.528263, 0.64369, + 0.830227, -0.353627, 0.430895, + 0.980604, -0.124339, 0.151508, + 0.980604, 0.12434, -0.151508, + 0.830228, 0.353626, -0.430895, + 0.553716, 0.528263, -0.64369, + 0.194186, 0.758296, -0.622317, + -0.194185, 0.758296, -0.622318, + -0.553717, 0.64369, -0.528263, + -0.830228, 0.430895, -0.353626, + -0.980604, 0.151508, -0.124339, + -0.980604, -0.151508, 0.124339, + -0.830227, -0.430895, 0.353627, + -0.553717, -0.643689, 0.528262, + -0.194187, -0.758296, 0.622317, + 0.194187, -0.758296, 0.622317, + 0.553716, -0.64369, 0.528263, + 0.830227, -0.430895, 0.353627, + 0.980604, -0.151508, 0.124339, + 0.980604, 0.151508, -0.12434, + 0.830228, 0.430895, -0.353626, + 0.553716, 0.64369, -0.528263, + 0.194186, 0.865134, -0.462423, + -0.194185, 0.865134, -0.462424, + -0.553717, 0.73438, -0.392534, + -0.830228, 0.491604, -0.262768, + -0.980604, 0.172855, -0.092393, + -0.980604, -0.172854, 0.092393, + -0.830227, -0.491605, 0.262768, + -0.553717, -0.73438, 0.392534, + -0.194186, -0.865134, 0.462424, + 0.194187, -0.865134, 0.462423, + 0.553716, -0.734381, 0.392535, + 0.830228, -0.491605, 0.262768, + 0.980604, -0.172854, 0.092393, + 0.980604, 0.172855, -0.092393, + 0.830228, 0.491604, -0.262768, + 0.553716, 0.734381, -0.392535, + 0.194185, 0.938725, -0.284759, + -0.194185, 0.938725, -0.284759, + -0.553718, 0.796848, -0.241721, + -0.830228, 0.533422, -0.161812, + -0.980604, 0.187558, -0.056895, + -0.980605, -0.187557, 0.056895, + -0.830227, -0.533422, 0.161812, + -0.553716, -0.796849, 0.241722, + -0.194187, -0.938725, 0.284759, + 0.194188, -0.938724, 0.284759, + 0.553716, -0.79685, 0.241722, + 0.830227, -0.533423, 0.161812, + 0.980604, -0.187557, 0.056895, + 0.980604, 0.187558, -0.056895, + 0.830228, 0.533422, -0.161812, + 0.553717, 0.796849, -0.241722, + 0.194186, 0.976241, -0.096151, + -0.194186, 0.976241, -0.096151, + -0.553717, 0.828695, -0.081619, + -0.830228, 0.55474, -0.054637, + -0.980604, 0.195054, -0.019211, + -0.980604, -0.195054, 0.019211, + -0.830227, -0.554741, 0.054637, + -0.553717, -0.828695, 0.081619, + -0.194187, -0.976241, 0.096151, + 0.194187, -0.976241, 0.096151, + 0.553716, -0.828696, 0.08162, + 0.830227, -0.554741, 0.054637, + 0.980604, -0.195054, 0.019211, + 0.980604, 0.195054, -0.019211, + 0.830228, 0.55474, -0.054637, + 0.553716, 0.828696, -0.081619, +}; + +static const unsigned short int BigValve_POLS[] = +{ + 16, 684, 685, 686, 687, 688, 689, 690, 691, 692, 693, 694, 695, 696, 697, 698, 699, 1, 4, 700, + 701, 685, 684, 1, 4, 701, 702, 686, 685, 1, 4, 702, 703, 687, 686, 1, 4, 703, 704, 688, + 687, 1, 4, 704, 705, 689, 688, 1, 4, 705, 706, 690, 689, 1, 4, 706, 707, 691, 690, 1, + 4, 707, 708, 692, 691, 1, 4, 708, 709, 693, 692, 1, 4, 709, 710, 694, 693, 1, 4, 710, + 711, 695, 694, 1, 4, 711, 712, 696, 695, 1, 4, 712, 713, 697, 696, 1, 4, 713, 714, 698, + 697, 1, 4, 714, 715, 699, 698, 1, 4, 715, 700, 684, 699, 1, 16, 700, 715, 714, 713, 712, + 711, 710, 709, 708, 707, 706, 705, 704, 703, 702, 701, 1, 4, 668, 669, 655, 654, 1, 4, 669, + 670, 656, 655, 1, 4, 670, 671, 657, 656, 1, 4, 671, 672, 634, 657, 1, 4, 672, 673, 658, + 634, 1, 4, 673, 674, 659, 658, 1, 4, 674, 675, 660, 659, 1, 4, 675, 676, 661, 660, 1, + 4, 676, 677, 662, 661, 1, 4, 677, 678, 663, 662, 1, 4, 678, 679, 664, 663, 1, 4, 679, + 680, 564, 664, 1, 4, 680, 681, 665, 564, 1, 4, 681, 682, 666, 665, 1, 4, 682, 683, 667, + 666, 1, 4, 683, 668, 654, 667, 1, 4, 638, 639, 624, 623, 1, 4, 639, 640, 625, 624, 1, + 4, 640, 641, 626, 625, 1, 4, 641, 642, 603, 626, 1, 4, 642, 643, 627, 603, 1, 4, 643, + 644, 628, 627, 1, 4, 644, 645, 629, 628, 1, 4, 645, 646, 630, 629, 1, 4, 646, 647, 631, + 630, 1, 4, 647, 648, 632, 631, 1, 4, 648, 649, 633, 632, 1, 4, 649, 650, 634, 633, 1, + 4, 650, 651, 635, 634, 1, 4, 651, 652, 636, 635, 1, 4, 652, 653, 637, 636, 1, 4, 653, + 638, 623, 637, 1, 4, 607, 608, 593, 592, 1, 4, 608, 609, 594, 593, 1, 4, 609, 610, 595, + 594, 1, 4, 610, 611, 572, 595, 1, 4, 611, 612, 596, 572, 1, 4, 612, 613, 597, 596, 1, + 4, 613, 614, 598, 597, 1, 4, 614, 615, 599, 598, 1, 4, 615, 616, 600, 599, 1, 4, 616, + 617, 601, 600, 1, 4, 617, 618, 602, 601, 1, 4, 618, 619, 603, 602, 1, 4, 619, 620, 604, + 603, 1, 4, 620, 621, 605, 604, 1, 4, 621, 622, 606, 605, 1, 4, 622, 607, 592, 606, 1, + 4, 576, 577, 561, 560, 1, 4, 577, 578, 562, 561, 1, 4, 578, 579, 563, 562, 1, 4, 579, + 580, 564, 563, 1, 4, 580, 581, 565, 564, 1, 4, 581, 582, 566, 565, 1, 4, 582, 583, 567, + 566, 1, 4, 583, 584, 568, 567, 1, 4, 584, 585, 569, 568, 1, 4, 585, 586, 570, 569, 1, + 4, 586, 587, 571, 570, 1, 4, 587, 588, 572, 571, 1, 4, 588, 589, 573, 572, 1, 4, 589, + 590, 574, 573, 1, 4, 590, 591, 575, 574, 1, 4, 591, 576, 560, 575, 1, 24, 512, 513, 514, + 515, 516, 517, 518, 519, 520, 521, 522, 523, 524, 525, 526, 527, 528, 529, 530, 531, 532, 533, 534, + 535, 1, 4, 536, 537, 513, 512, 1, 4, 537, 538, 514, 513, 1, 4, 538, 539, 515, 514, 1, + 4, 539, 540, 516, 515, 1, 4, 540, 541, 517, 516, 1, 4, 541, 542, 518, 517, 1, 4, 542, + 543, 519, 518, 1, 4, 543, 544, 520, 519, 1, 4, 544, 545, 521, 520, 1, 4, 545, 546, 522, + 521, 1, 4, 546, 547, 523, 522, 1, 4, 547, 548, 524, 523, 1, 4, 548, 549, 525, 524, 1, + 4, 549, 550, 526, 525, 1, 4, 550, 551, 527, 526, 1, 4, 551, 552, 528, 527, 1, 4, 552, + 553, 529, 528, 1, 4, 553, 554, 530, 529, 1, 4, 554, 555, 531, 530, 1, 4, 555, 556, 532, + 531, 1, 4, 556, 557, 533, 532, 1, 4, 557, 558, 534, 533, 1, 4, 558, 559, 535, 534, 1, + 4, 559, 536, 512, 535, 1, 24, 536, 559, 558, 557, 556, 555, 554, 553, 552, 551, 550, 549, 548, + 547, 546, 545, 544, 543, 542, 541, 540, 539, 538, 537, 1, 4, 16, 31, 15, 0, 1, 4, 31, + 30, 14, 15, 1, 4, 30, 29, 13, 14, 1, 4, 29, 28, 12, 13, 1, 4, 28, 27, 11, + 12, 1, 4, 27, 26, 10, 11, 1, 4, 26, 25, 9, 10, 1, 4, 25, 24, 8, 9, 1, + 4, 24, 23, 7, 8, 1, 4, 23, 22, 6, 7, 1, 4, 22, 21, 5, 6, 1, 4, 21, + 20, 4, 5, 1, 4, 20, 19, 3, 4, 1, 4, 19, 18, 2, 3, 1, 4, 18, 17, 1, + 2, 1, 4, 17, 16, 0, 1, 1, 4, 32, 47, 31, 16, 1, 4, 47, 46, 30, 31, 1, + 4, 46, 45, 29, 30, 1, 4, 45, 44, 28, 29, 1, 4, 44, 43, 27, 28, 1, 4, 43, + 42, 26, 27, 1, 4, 42, 41, 25, 26, 1, 4, 41, 40, 24, 25, 1, 4, 40, 39, 23, + 24, 1, 4, 39, 38, 22, 23, 1, 4, 38, 37, 21, 22, 1, 4, 37, 36, 20, 21, 1, + 4, 36, 35, 19, 20, 1, 4, 35, 34, 18, 19, 1, 4, 34, 33, 17, 18, 1, 4, 33, + 32, 16, 17, 1, 4, 48, 63, 47, 32, 1, 4, 63, 62, 46, 47, 1, 4, 62, 61, 45, + 46, 1, 4, 61, 60, 44, 45, 1, 4, 60, 59, 43, 44, 1, 4, 59, 58, 42, 43, 1, + 4, 58, 57, 41, 42, 1, 4, 57, 56, 40, 41, 1, 4, 56, 55, 39, 40, 1, 4, 55, + 54, 38, 39, 1, 4, 54, 53, 37, 38, 1, 4, 53, 52, 36, 37, 1, 4, 52, 51, 35, + 36, 1, 4, 51, 50, 34, 35, 1, 4, 50, 49, 33, 34, 1, 4, 49, 48, 32, 33, 1, + 4, 64, 79, 63, 48, 1, 4, 79, 78, 62, 63, 1, 4, 78, 77, 61, 62, 1, 4, 77, + 76, 60, 61, 1, 4, 76, 75, 59, 60, 1, 4, 75, 74, 58, 59, 1, 4, 74, 73, 57, + 58, 1, 4, 73, 72, 56, 57, 1, 4, 72, 71, 55, 56, 1, 4, 71, 70, 54, 55, 1, + 4, 70, 69, 53, 54, 1, 4, 69, 68, 52, 53, 1, 4, 68, 67, 51, 52, 1, 4, 67, + 66, 50, 51, 1, 4, 66, 65, 49, 50, 1, 4, 65, 64, 48, 49, 1, 4, 80, 95, 79, + 64, 1, 4, 95, 94, 78, 79, 1, 4, 94, 93, 77, 78, 1, 4, 93, 92, 76, 77, 1, + 4, 92, 91, 75, 76, 1, 4, 91, 90, 74, 75, 1, 4, 90, 89, 73, 74, 1, 4, 89, + 88, 72, 73, 1, 4, 88, 87, 71, 72, 1, 4, 87, 86, 70, 71, 1, 4, 86, 85, 69, + 70, 1, 4, 85, 84, 68, 69, 1, 4, 84, 83, 67, 68, 1, 4, 83, 82, 66, 67, 1, + 4, 82, 81, 65, 66, 1, 4, 81, 80, 64, 65, 1, 4, 96, 111, 95, 80, 1, 4, 111, + 110, 94, 95, 1, 4, 110, 109, 93, 94, 1, 4, 109, 108, 92, 93, 1, 4, 108, 107, 91, +92, 1, 4, 107, 106, 90, 91, 1, 4, 106, 105, 89, 90, 1, 4, 105, 104, 88, 89, 1, + 4, 104, 103, 87, 88, 1, 4, 103, 102, 86, 87, 1, 4, 102, 101, 85, 86, 1, 4, 101, + 100, 84, 85, 1, 4, 100, 99, 83, 84, 1, 4, 99, 98, 82, 83, 1, 4, 98, 97, 81, + 82, 1, 4, 97, 96, 80, 81, 1, 4, 112, 127, 111, 96, 1, 4, 127, 126, 110, 111, 1, + 4, 126, 125, 109, 110, 1, 4, 125, 124, 108, 109, 1, 4, 124, 123, 107, 108, 1, 4, 123, + 122, 106, 107, 1, 4, 122, 121, 105, 106, 1, 4, 121, 120, 104, 105, 1, 4, 120, 119, 103, + 104, 1, 4, 119, 118, 102, 103, 1, 4, 118, 117, 101, 102, 1, 4, 117, 116, 100, 101, 1, + 4, 116, 115, 99, 100, 1, 4, 115, 114, 98, 99, 1, 4, 114, 113, 97, 98, 1, 4, 113, + 112, 96, 97, 1, 4, 128, 143, 127, 112, 1, 4, 143, 142, 126, 127, 1, 4, 142, 141, 125, + 126, 1, 4, 141, 140, 124, 125, 1, 4, 140, 139, 123, 124, 1, 4, 139, 138, 122, 123, 1, + 4, 138, 137, 121, 122, 1, 4, 137, 136, 120, 121, 1, 4, 136, 135, 119, 120, 1, 4, 135, + 134, 118, 119, 1, 4, 134, 133, 117, 118, 1, 4, 133, 132, 116, 117, 1, 4, 132, 131, 115, + 116, 1, 4, 131, 130, 114, 115, 1, 4, 130, 129, 113, 114, 1, 4, 129, 128, 112, 113, 1, + 4, 144, 159, 143, 128, 1, 4, 159, 158, 142, 143, 1, 4, 158, 157, 141, 142, 1, 4, 157, + 156, 140, 141, 1, 4, 156, 155, 139, 140, 1, 4, 155, 154, 138, 139, 1, 4, 154, 153, 137, + 138, 1, 4, 153, 152, 136, 137, 1, 4, 152, 151, 135, 136, 1, 4, 151, 150, 134, 135, 1, + 4, 150, 149, 133, 134, 1, 4, 149, 148, 132, 133, 1, 4, 148, 147, 131, 132, 1, 4, 147, + 146, 130, 131, 1, 4, 146, 145, 129, 130, 1, 4, 145, 144, 128, 129, 1, 4, 160, 175, 159, + 144, 1, 4, 175, 174, 158, 159, 1, 4, 174, 173, 157, 158, 1, 4, 173, 172, 156, 157, 1, + 4, 172, 171, 155, 156, 1, 4, 171, 170, 154, 155, 1, 4, 170, 169, 153, 154, 1, 4, 169, + 168, 152, 153, 1, 4, 168, 167, 151, 152, 1, 4, 167, 166, 150, 151, 1, 4, 166, 165, 149, + 150, 1, 4, 165, 164, 148, 149, 1, 4, 164, 163, 147, 148, 1, 4, 163, 162, 146, 147, 1, + 4, 162, 161, 145, 146, 1, 4, 161, 160, 144, 145, 1, 4, 176, 191, 175, 160, 1, 4, 191, + 190, 174, 175, 1, 4, 190, 189, 173, 174, 1, 4, 189, 188, 172, 173, 1, 4, 188, 187, 171, + 172, 1, 4, 187, 186, 170, 171, 1, 4, 186, 185, 169, 170, 1, 4, 185, 184, 168, 169, 1, + 4, 184, 183, 167, 168, 1, 4, 183, 182, 166, 167, 1, 4, 182, 181, 165, 166, 1, 4, 181, + 180, 164, 165, 1, 4, 180, 179, 163, 164, 1, 4, 179, 178, 162, 163, 1, 4, 178, 177, 161, + 162, 1, 4, 177, 176, 160, 161, 1, 4, 192, 207, 191, 176, 1, 4, 207, 206, 190, 191, 1, + 4, 206, 205, 189, 190, 1, 4, 205, 204, 188, 189, 1, 4, 204, 203, 187, 188, 1, 4, 203, + 202, 186, 187, 1, 4, 202, 201, 185, 186, 1, 4, 201, 200, 184, 185, 1, 4, 200, 199, 183, + 184, 1, 4, 199, 198, 182, 183, 1, 4, 198, 197, 181, 182, 1, 4, 197, 196, 180, 181, 1, + 4, 196, 195, 179, 180, 1, 4, 195, 194, 178, 179, 1, 4, 194, 193, 177, 178, 1, 4, 193, + 192, 176, 177, 1, 4, 208, 223, 207, 192, 1, 4, 223, 222, 206, 207, 1, 4, 222, 221, 205, + 206, 1, 4, 221, 220, 204, 205, 1, 4, 220, 219, 203, 204, 1, 4, 219, 218, 202, 203, 1, + 4, 218, 217, 201, 202, 1, 4, 217, 216, 200, 201, 1, 4, 216, 215, 199, 200, 1, 4, 215, + 214, 198, 199, 1, 4, 214, 213, 197, 198, 1, 4, 213, 212, 196, 197, 1, 4, 212, 211, 195, + 196, 1, 4, 211, 210, 194, 195, 1, 4, 210, 209, 193, 194, 1, 4, 209, 208, 192, 193, 1, + 4, 224, 239, 223, 208, 1, 4, 239, 238, 222, 223, 1, 4, 238, 237, 221, 222, 1, 4, 237, + 236, 220, 221, 1, 4, 236, 235, 219, 220, 1, 4, 235, 234, 218, 219, 1, 4, 234, 233, 217, + 218, 1, 4, 233, 232, 216, 217, 1, 4, 232, 231, 215, 216, 1, 4, 231, 230, 214, 215, 1, + 4, 230, 229, 213, 214, 1, 4, 229, 228, 212, 213, 1, 4, 228, 227, 211, 212, 1, 4, 227, + 226, 210, 211, 1, 4, 226, 225, 209, 210, 1, 4, 225, 224, 208, 209, 1, 4, 240, 255, 239, + 224, 1, 4, 255, 254, 238, 239, 1, 4, 254, 253, 237, 238, 1, 4, 253, 252, 236, 237, 1, + 4, 252, 251, 235, 236, 1, 4, 251, 250, 234, 235, 1, 4, 250, 249, 233, 234, 1, 4, 249, + 248, 232, 233, 1, 4, 248, 247, 231, 232, 1, 4, 247, 246, 230, 231, 1, 4, 246, 245, 229, + 230, 1, 4, 245, 244, 228, 229, 1, 4, 244, 243, 227, 228, 1, 4, 243, 242, 226, 227, 1, + 4, 242, 241, 225, 226, 1, 4, 241, 240, 224, 225, 1, 4, 256, 271, 255, 240, 1, 4, 271, + 270, 254, 255, 1, 4, 270, 269, 253, 254, 1, 4, 269, 268, 252, 253, 1, 4, 268, 267, 251, + 252, 1, 4, 267, 266, 250, 251, 1, 4, 266, 265, 249, 250, 1, 4, 265, 264, 248, 249, 1, + 4, 264, 263, 247, 248, 1, 4, 263, 262, 246, 247, 1, 4, 262, 261, 245, 246, 1, 4, 261, + 260, 244, 245, 1, 4, 260, 259, 243, 244, 1, 4, 259, 258, 242, 243, 1, 4, 258, 257, 241, + 242, 1, 4, 257, 256, 240, 241, 1, 4, 272, 287, 271, 256, 1, 4, 287, 286, 270, 271, 1, + 4, 286, 285, 269, 270, 1, 4, 285, 284, 268, 269, 1, 4, 284, 283, 267, 268, 1, 4, 283, + 282, 266, 267, 1, 4, 282, 281, 265, 266, 1, 4, 281, 280, 264, 265, 1, 4, 280, 279, 263, + 264, 1, 4, 279, 278, 262, 263, 1, 4, 278, 277, 261, 262, 1, 4, 277, 276, 260, 261, 1, + 4, 276, 275, 259, 260, 1, 4, 275, 274, 258, 259, 1, 4, 274, 273, 257, 258, 1, 4, 273, + 272, 256, 257, 1, 4, 288, 303, 287, 272, 1, 4, 303, 302, 286, 287, 1, 4, 302, 301, 285, + 286, 1, 4, 301, 300, 284, 285, 1, 4, 300, 299, 283, 284, 1, 4, 299, 298, 282, 283, 1, + 4, 298, 297, 281, 282, 1, 4, 297, 296, 280, 281, 1, 4, 296, 295, 279, 280, 1, 4, 295, + 294, 278, 279, 1, 4, 294, 293, 277, 278, 1, 4, 293, 292, 276, 277, 1, 4, 292, 291, 275, + 276, 1, 4, 291, 290, 274, 275, 1, 4, 290, 289, 273, 274, 1, 4, 289, 288, 272, 273, 1, + 4, 304, 319, 303, 288, 1, 4, 319, 318, 302, 303, 1, 4, 318, 317, 301, 302, 1, 4, 317, + 316, 300, 301, 1, 4, 316, 315, 299, 300, 1, 4, 315, 314, 298, 299, 1, 4, 314, 313, 297, + 298, 1, 4, 313, 312, 296, 297, 1, 4, 312, 311, 295, 296, 1, 4, 311, 310, 294, 295, 1, + 4, 310, 309, 293, 294, 1, 4, 309, 308, 292, 293, 1, 4, 308, 307, 291, 292, 1, 4, 307, + 306, 290, 291, 1, 4, 306, 305, 289, 290, 1, 4, 305, 304, 288, 289, 1, 4, 320, 335, 319, + 304, 1, 4, 335, 334, 318, 319, 1, 4, 334, 333, 317, 318, 1, 4, 333, 332, 316, 317, 1, + 4, 332, 331, 315, 316, 1, 4, 331, 330, 314, 315, 1, 4, 330, 329, 313, 314, 1, 4, 329, + 328, 312, 313, 1, 4, 328, 327, 311, 312, 1, 4, 327, 326, 310, 311, 1, 4, 326, 325, 309, + 310, 1, 4, 325, 324, 308, 309, 1, 4, 324, 323, 307, 308, 1, 4, 323, 322, 306, 307, 1, + 4, 322, 321, 305, 306, 1, 4, 321, 320, 304, 305, 1, 4, 336, 351, 335, 320, 1, 4, 351, + 350, 334, 335, 1, 4, 350, 349, 333, 334, 1, 4, 349, 348, 332, 333, 1, 4, 348, 347, 331, + 332, 1, 4, 347, 346, 330, 331, 1, 4, 346, 345, 329, 330, 1, 4, 345, 344, 328, 329, 1, + 4, 344, 343, 327, 328, 1, 4, 343, 342, 326, 327, 1, 4, 342, 341, 325, 326, 1, 4, 341, + 340, 324, 325, 1, 4, 340, 339, 323, 324, 1, 4, 339, 338, 322, 323, 1, 4, 338, 337, 321, + 322, 1, 4, 337, 336, 320, 321, 1, 4, 352, 367, 351, 336, 1, 4, 367, 366, 350, 351, 1, + 4, 366, 365, 349, 350, 1, 4, 365, 364, 348, 349, 1, 4, 364, 363, 347, 348, 1, 4, 363, + 362, 346, 347, 1, 4, 362, 361, 345, 346, 1, 4, 361, 360, 344, 345, 1, 4, 360, 359, 343, + 344, 1, 4, 359, 358, 342, 343, 1, 4, 358, 357, 341, 342, 1, 4, 357, 356, 340, 341, 1, + 4, 356, 355, 339, 340, 1, 4, 355, 354, 338, 339, 1, 4, 354, 353, 337, 338, 1, 4, 353, + 352, 336, 337, 1, 4, 368, 383, 367, 352, 1, 4, 383, 382, 366, 367, 1, 4, 382, 381, 365, + 366, 1, 4, 381, 380, 364, 365, 1, 4, 380, 379, 363, 364, 1, 4, 379, 378, 362, 363, 1, + 4, 378, 377, 361, 362, 1, 4, 377, 376, 360, 361, 1, 4, 376, 375, 359, 360, 1, 4, 375, + 374, 358, 359, 1, 4, 374, 373, 357, 358, 1, 4, 373, 372, 356, 357, 1, 4, 372, 371, 355, + 356, 1, 4, 371, 370, 354, 355, 1, 4, 370, 369, 353, 354, 1, 4, 369, 368, 352, 353, 1, + 4, 384, 399, 383, 368, 1, 4, 399, 398, 382, 383, 1, 4, 398, 397, 381, 382, 1, 4, 397, + 396, 380, 381, 1, 4, 396, 395, 379, 380, 1, 4, 395, 394, 378, 379, 1, 4, 394, 393, 377, + 378, 1, 4, 393, 392, 376, 377, 1, 4, 392, 391, 375, 376, 1, 4, 391, 390, 374, 375, 1, + 4, 390, 389, 373, 374, 1, 4, 389, 388, 372, 373, 1, 4, 388, 387, 371, 372, 1, 4, 387, + 386, 370, 371, 1, 4, 386, 385, 369, 370, 1, 4, 385, 384, 368, 369, 1, 4, 400, 415, 399, + 384, 1, 4, 415, 414, 398, 399, 1, 4, 414, 413, 397, 398, 1, 4, 413, 412, 396, 397, 1, + 4, 412, 411, 395, 396, 1, 4, 411, 410, 394, 395, 1, 4, 410, 409, 393, 394, 1, 4, 409, + 408, 392, 393, 1, 4, 408, 407, 391, 392, 1, 4, 407, 406, 390, 391, 1, 4, 406, 405, 389, + 390, 1, 4, 405, 404, 388, 389, 1, 4, 404, 403, 387, 388, 1, 4, 403, 402, 386, 387, 1, + 4, 402, 401, 385, 386, 1, 4, 401, 400, 384, 385, 1, 4, 416, 431, 415, 400, 1, 4, 431, + 430, 414, 415, 1, 4, 430, 429, 413, 414, 1, 4, 429, 428, 412, 413, 1, 4, 428, 427, 411, + 412, 1, 4, 427, 426, 410, 411, 1, 4, 426, 425, 409, 410, 1, 4, 425, 424, 408, 409, 1, + 4, 424, 423, 407, 408, 1, 4, 423, 422, 406, 407, 1, 4, 422, 421, 405, 406, 1, 4, 421, + 420, 404, 405, 1, 4, 420, 419, 403, 404, 1, 4, 419, 418, 402, 403, 1, 4, 418, 417, 401, + 402, 1, 4, 417, 416, 400, 401, 1, 4, 432, 447, 431, 416, 1, 4, 447, 446, 430, 431, 1, + 4, 446, 445, 429, 430, 1, 4, 445, 444, 428, 429, 1, 4, 444, 443, 427, 428, 1, 4, 443, + 442, 426, 427, 1, 4, 442, 441, 425, 426, 1, 4, 441, 440, 424, 425, 1, 4, 440, 439, 423, + 424, 1, 4, 439, 438, 422, 423, 1, 4, 438, 437, 421, 422, 1, 4, 437, 436, 420, 421, 1, + 4, 436, 435, 419, 420, 1, 4, 435, 434, 418, 419, 1, 4, 434, 433, 417, 418, 1, 4, 433, + 432, 416, 417, 1, 4, 448, 463, 447, 432, 1, 4, 463, 462, 446, 447, 1, 4, 462, 461, 445, + 446, 1, 4, 461, 460, 444, 445, 1, 4, 460, 459, 443, 444, 1, 4, 459, 458, 442, 443, 1, + 4, 458, 457, 441, 442, 1, 4, 457, 456, 440, 441, 1, 4, 456, 455, 439, 440, 1, 4, 455, + 454, 438, 439, 1, 4, 454, 453, 437, 438, 1, 4, 453, 452, 436, 437, 1, 4, 452, 451, 435, + 436, 1, 4, 451, 450, 434, 435, 1, 4, 450, 449, 433, 434, 1, 4, 449, 448, 432, 433, 1, + 4, 464, 479, 463, 448, 1, 4, 479, 478, 462, 463, 1, 4, 478, 477, 461, 462, 1, 4, 477, + 476, 460, 461, 1, 4, 476, 475, 459, 460, 1, 4, 475, 474, 458, 459, 1, 4, 474, 473, 457, + 458, 1, 4, 473, 472, 456, 457, 1, 4, 472, 471, 455, 456, 1, 4, 471, 470, 454, 455, 1, + 4, 470, 469, 453, 454, 1, 4, 469, 468, 452, 453, 1, 4, 468, 467, 451, 452, 1, 4, 467, + 466, 450, 451, 1, 4, 466, 465, 449, 450, 1, 4, 465, 464, 448, 449, 1, 4, 480, 495, 479, + 464, 1, 4, 495, 494, 478, 479, 1, 4, 494, 493, 477, 478, 1, 4, 493, 492, 476, 477, 1, + 4, 492, 491, 475, 476, 1, 4, 491, 490, 474, 475, 1, 4, 490, 489, 473, 474, 1, 4, 489, + 488, 472, 473, 1, 4, 488, 487, 471, 472, 1, 4, 487, 486, 470, 471, 1, 4, 486, 485, 469, + 470, 1, 4, 485, 484, 468, 469, 1, 4, 484, 483, 467, 468, 1, 4, 483, 482, 466, 467, 1, + 4, 482, 481, 465, 466, 1, 4, 481, 480, 464, 465, 1, 4, 496, 511, 495, 480, 1, 4, 511, + 510, 494, 495, 1, 4, 510, 509, 493, 494, 1, 4, 509, 508, 492, 493, 1, 4, 508, 507, 491, + 492, 1, 4, 507, 506, 490, 491, 1, 4, 506, 505, 489, 490, 1, 4, 505, 504, 488, 489, 1, + 4, 504, 503, 487, 488, 1, 4, 503, 502, 486, 487, 1, 4, 502, 501, 485, 486, 1, 4, 501, + 500, 484, 485, 1, 4, 500, 499, 483, 484, 1, 4, 499, 498, 482, 483, 1, 4, 498, 497, 481, + 482, 1, 4, 497, 496, 480, 481, 1, 4, 0, 15, 511, 496, 1, 4, 15, 14, 510, 511, 1, +4, 14, 13, 509, 510, 1, 4, 13, 12, 508, 509, 1, 4, 12, 11, 507, 508, 1, 4, 11, + 10, 506, 507, 1, 4, 10, 9, 505, 506, 1, 4, 9, 8, 504, 505, 1, 4, 8, 7, 503, + 504, 1, 4, 7, 6, 502, 503, 1, 4, 6, 5, 501, 502, 1, 4, 5, 4, 500, 501, 1, + 4, 4, 3, 499, 500, 1, 4, 3, 2, 498, 499, 1, 4, 2, 1, 497, 498, 1, 4, 1, + 0, 496, 497, 1, + 0 +}; + +struct lwo LWO_BigValve = +{ + 716, /* number of points */ + BigValve_PNTS, BigValve_normals, BigValve_POLS, 0L +}; + +static const GLfloat Bolts3D_PNTS[] = +{ + -0.160704, 0.399, 0.6, + -0.160704, 0.399, -0.5, + -0.4, 0.160257, 0.6, + -0.4, 0.160257, -0.5, + -0.4, -0.170369, 0.6, + -0.4, -0.170369, -0.5, + -0.153738, -0.4, 0.6, + -0.153738, -0.4, -0.5, + 0.176887, -0.4, 0.6, + 0.176887, -0.4, -0.5, + 0.4, -0.163403, 0.6, + 0.4, -0.163403, -0.5, + 0.4, 0.167223, 0.6, + 0.4, 0.167223, -0.5, + 0.169922, 0.399, 0.6, + 0.169922, 0.399, -0.5, + -0.160704, 0.399, 0.5, + -0.160704, 0.399, -0.6, + -0.4, 0.160257, -0.6, + -0.4, 0.160257, 0.5, + -0.4, -0.170369, -0.6, + -0.4, -0.170369, 0.5, + -0.153738, -0.4, -0.6, + -0.153738, -0.4, 0.5, + 0.176887, -0.4, 0.5, + 0.176887, -0.4, -0.6, + 0.4, -0.163403, 0.5, + 0.4, -0.163403, -0.6, + 0.4, 0.167223, -0.6, + 0.4, 0.167223, 0.5, + 0.169922, 0.399, -0.6, + 0.169922, 0.399, 0.5, +}; + +static const GLfloat Bolts3D_normals[] = +{ + 0, 1, 0, + 0.709703, 0.704502, 0, + 1, 0, 0, + 0.727535, -0.68607, 0, + 0, -1, 0, + -0.68198, -0.73137, 0, + -1, 0, 0, + -0.706289, 0.707924, 0, + 0, 0, 1, + 0, 1, 0, + 0.709703, 0.704502, 0, + 1, 0, 0, + 0.727535, -0.68607, 0, + 0, -1, 0, + -0.68198, -0.73137, 0, + -1, 0, 0, + -0.706289, 0.707924, 0, + 0, 0, -1, +}; + +static const unsigned short int Bolts3D_POLS[] = +{ + 4, 16, 31, 14, 0, 1, 4, 31, 29, 12, 14, 1, 4, 29, 26, 10, 12, 1, 4, 26, + 24, 8, 10, 1, 4, 24, 23, 6, 8, 1, 4, 23, 21, 4, 6, 1, 4, 21, 19, 2, + 4, 1, 4, 19, 16, 0, 2, 1, 8, 14, 12, 10, 8, 6, 4, 2, 0, 1, 4, 17, + 30, 15, 1, 1, 4, 30, 28, 13, 15, 1, 4, 28, 27, 11, 13, 1, 4, 27, 25, 9, + 11, 1, 4, 25, 22, 7, 9, 1, 4, 22, 20, 5, 7, 1, 4, 20, 18, 3, 5, 1, + 4, 18, 17, 1, 3, 1, 8, 30, 17, 18, 20, 22, 25, 27, 28, 1, + 0 +}; + +struct lwo LWO_Bolts3D = +{ + 32, /* number of points */ + Bolts3D_PNTS, Bolts3D_normals, Bolts3D_POLS, 0L +}; + +static const GLfloat GuageConnector_PNTS[] = +{ + 0.2, 0.4, 0, + 0.2, 0.8, 0, + 0.193185, 0.4, -0.051764, + 0.193185, 0.8, -0.051764, + 0.173205, 0.4, -0.1, + 0.173205, 0.8, -0.1, + 0.141421, 0.8, -0.141421, + 0.141421, 0.4, -0.141421, + 0.1, 0.4, -0.173205, + 0.1, 0.8, -0.173205, + 0.051764, 0.8, -0.193185, + 0.051764, 0.4, -0.193185, + 0, 0.8, -0.2, + 0, 0.4, -0.2, + -0.051764, 0.8, -0.193185, + -0.051764, 0.4, -0.193185, + -0.1, 0.8, -0.173205, + -0.1, 0.4, -0.173205, + -0.141421, 0.4, -0.141421, + -0.141421, 0.8, -0.141421, + -0.173205, 0.8, -0.1, + -0.173205, 0.4, -0.1, + -0.193185, 0.4, -0.051764, + -0.193185, 0.8, -0.051764, + -0.2, 0.4, 0, + -0.2, 0.8, 0, + -0.193185, 0.4, 0.051764, + -0.193185, 0.8, 0.051764, + -0.173205, 0.4, 0.1, + -0.173205, 0.8, 0.1, + -0.141421, 0.8, 0.141421, + -0.141421, 0.4, 0.141421, + -0.1, 0.8, 0.173205, + -0.1, 0.4, 0.173205, + -0.051764, 0.8, 0.193185, + -0.051764, 0.4, 0.193185, + 0, 0.8, 0.2, + 0, 0.4, 0.2, + 0.051764, 0.8, 0.193185, + 0.051764, 0.4, 0.193185, + 0.1, 0.4, 0.173205, + 0.1, 0.8, 0.173205, + 0.141421, 0.4, 0.141421, + 0.141421, 0.8, 0.141421, + 0.173205, 0.8, 0.1, + 0.173205, 0.4, 0.1, + 0.193185, 0.4, 0.051764, + 0.193185, 0.8, 0.051764, + 0.2, 0.55, 0, + 0.193185, 0.55, -0.051764, + 0.173205, 0.55, -0.1, + 0.141421, 0.55, -0.141421, + 0.1, 0.55, -0.173205, + 0.051764, 0.55, -0.193185, + 0, 0.55, -0.2, + -0.051764, 0.55, -0.193185, + -0.1, 0.55, -0.173205, + -0.141421, 0.55, -0.141421, + -0.173205, 0.55, -0.1, + -0.193185, 0.55, -0.051764, + -0.2, 0.55, 0, + -0.193185, 0.55, 0.051764, + -0.173205, 0.55, 0.1, + -0.141421, 0.55, 0.141421, + -0.1, 0.55, 0.173205, + -0.051764, 0.55, 0.193185, + 0, 0.55, 0.2, + 0.051764, 0.55, 0.193185, + 0.1, 0.55, 0.173205, + 0.141421, 0.55, 0.141421, + 0.173205, 0.55, 0.1, + 0.193185, 0.55, 0.051764, + 0.15, 0.55, 0, + 0.144889, 0.55, -0.038823, + 0.129904, 0.55, -0.075, + 0.106066, 0.55, -0.106066, + 0.075, 0.55, -0.129904, + 0.038823, 0.55, -0.144889, + 0, 0.55, -0.15, + -0.038823, 0.55, -0.144889, + -0.075, 0.55, -0.129904, + -0.106066, 0.55, -0.106066, + -0.129904, 0.55, -0.075, + -0.144889, 0.55, -0.038823, + -0.15, 0.55, 0, + -0.144889, 0.55, 0.038823, + -0.129904, 0.55, 0.075, + -0.106066, 0.55, 0.106066, + -0.075, 0.55, 0.129904, + -0.038823, 0.55, 0.144889, + 0, 0.55, 0.15, + 0.038823, 0.55, 0.144889, + 0.075, 0.55, 0.129904, + 0.106066, 0.55, 0.106066, + 0.129904, 0.55, 0.075, + 0.144889, 0.55, 0.038823, + 0.15, 0.8, 0, + 0.144889, 0.8, -0.038823, + 0.129904, 0.8, -0.075, + 0.106066, 0.8, -0.106066, + 0.075, 0.8, -0.129904, + 0.038823, 0.8, -0.144889, + 0, 0.8, -0.15, + -0.038823, 0.8, -0.144889, + -0.075, 0.8, -0.129904, + -0.106066, 0.8, -0.106066, + -0.129904, 0.8, -0.075, + -0.144889, 0.8, -0.038823, + -0.15, 0.8, 0, + -0.144889, 0.8, 0.038823, + -0.129904, 0.8, 0.075, + -0.106066, 0.8, 0.106066, + -0.075, 0.8, 0.129904, + -0.038823, 0.8, 0.144889, + 0, 0.8, 0.15, + 0.038823, 0.8, 0.144889, + 0.075, 0.8, 0.129904, + 0.106066, 0.8, 0.106066, + 0.129904, 0.8, 0.075, + 0.144889, 0.8, 0.038823, + 0.2, 0.875988, 0, + 0.193185, 0.872346, -0.051764, + 0.191342, 0.87136, -0.056214, + 0.173205, 0.865859, -0.1, + 0.141421, 0.856217, -0.141421, + 0.1, 0.843652, -0.173205, + 0.097545, 0.842907, -0.174222, + 0.051764, 0.838398, -0.193185, + 0, 0.8333, -0.2, + -0.051764, 0.838398, -0.193185, + -0.097545, 0.842907, -0.174222, + -0.1, 0.843652, -0.173205, + -0.141421, 0.856217, -0.141421, + -0.173205, 0.865859, -0.1, + -0.191342, 0.87136, -0.056214, + -0.193185, 0.872346, -0.051764, + -0.2, 0.875988, 0, + -0.193185, 0.872346, 0.051764, + -0.173205, 0.865859, 0.1, + -0.191342, 0.87136, 0.056214, + -0.141421, 0.856217, 0.141421, + -0.1, 0.843652, 0.173205, + -0.051764, 0.838398, 0.193185, + -0.097545, 0.842907, 0.174222, + 0, 0.8333, 0.2, + 0.051764, 0.838398, 0.193185, + 0.1, 0.843652, 0.173205, + 0.097545, 0.842907, 0.174222, + 0.141421, 0.856217, 0.141421, + 0.173205, 0.865859, 0.1, + 0.193185, 0.872346, 0.051764, + 0.191342, 0.87136, 0.056214, +}; + +static const GLfloat GuageConnector_normals[] = +{ + 0.991445, 0, -0.130526, + 0.92388, 0, -0.382683, + 0.793353, 0, -0.608761, + 0.608761, 0, -0.793353, + 0.382683, 0, -0.92388, + 0.130526, 0, -0.991445, + -0.130526, 0, -0.991445, + -0.382683, 0, -0.92388, + -0.608761, 0, -0.793353, + -0.793353, 0, -0.608761, + -0.92388, 0, -0.382683, + -0.991445, 0, -0.130526, + -0.991445, 0, 0.130526, + -0.92388, 0, 0.382683, + -0.793353, 0, 0.608761, + -0.608761, 0, 0.793353, + -0.382683, 0, 0.92388, + -0.130526, 0, 0.991445, + 0.130526, 0, 0.991445, + 0.382683, 0, 0.92388, + 0.608761, 0, 0.793353, + 0.793353, 0, 0.608761, + 0.92388, 0, 0.382683, + 0.991445, 0, 0.130526, + 0.991445, 0, -0.130526, + 0.92388, 0, -0.382684, + 0.793353, 0, -0.608761, + 0.608761, 0, -0.793353, + 0.382684, 0, -0.92388, + 0.130526, 0, -0.991445, + -0.130526, 0, -0.991445, + -0.382684, 0, -0.92388, + -0.608761, 0, -0.793353, + -0.793353, 0, -0.608761, + -0.92388, 0, -0.382684, + -0.991445, 0, -0.130526, + -0.991445, 0, 0.130526, + -0.92388, 0, 0.382684, + -0.793353, 0, 0.608761, + -0.608761, 0, 0.793353, + -0.382684, 0, 0.92388, + -0.130526, 0, 0.991445, + 0.130526, 0, 0.991445, + 0.382684, 0, 0.92388, + 0.608761, 0, 0.793353, + 0.793353, 0, 0.608761, + 0.92388, 0, 0.382684, + 0.991445, 0, 0.130526, + 0, -1, 0, + 0.991445, 0, -0.130526, + 0.92388, 0, -0.382684, + 0.793353, 0, -0.608761, + 0.608761, 0, -0.793353, + 0.382684, 0, -0.92388, + 0.130526, 0, -0.991445, + -0.130526, 0, -0.991445, + -0.382684, 0, -0.92388, + -0.608761, 0, -0.793353, + -0.793353, 0, -0.608761, + -0.92388, 0, -0.382684, + -0.991445, 0, -0.130526, + -0.991445, 0, 0.130526, + -0.92388, 0, 0.382684, + -0.793353, 0, 0.608761, + -0.608761, 0, 0.793353, + -0.382684, 0, 0.92388, + -0.130526, 0, 0.991445, + 0.130526, 0, 0.991445, + 0.382684, 0, 0.92388, + 0.608761, 0, 0.793353, + 0.793353, 0, 0.608761, + 0.92388, 0, 0.382684, + 0.991445, 0, 0.130526, + 0, 1, 0, +}; + +static const unsigned short int GuageConnector_POLS[] = +{ + 4, 1, 120, 121, 3, 1, 5, 3, 121, 122, 123, 5, 1, 4, 5, 123, 124, 6, 1, 4, +6, 124, 125, 9, 1, 5, 9, 125, 126, 127, 10, 1, 4, 10, 127, 128, 12, 1, 4, 14, + 12, 128, 129, 1, 5, 16, 14, 129, 130, 131, 1, 4, 19, 16, 131, 132, 1, 4, 20, 19, + 132, 133, 1, 5, 23, 20, 133, 134, 135, 1, 4, 25, 23, 135, 136, 1, 4, 25, 136, 137, + 27, 1, 5, 27, 137, 139, 138, 29, 1, 4, 29, 138, 140, 30, 1, 4, 30, 140, 141, 32, + 1, 5, 32, 141, 143, 142, 34, 1, 4, 34, 142, 144, 36, 1, 4, 38, 36, 144, 145, 1, + 5, 41, 38, 145, 147, 146, 1, 4, 43, 41, 146, 148, 1, 4, 44, 43, 148, 149, 1, 5, +47, 44, 149, 151, 150, 1, 4, 1, 47, 150, 120, 1, 4, 96, 97, 73, 72, 1, 4, 97, + 98, 74, 73, 1, 4, 98, 99, 75, 74, 1, 4, 99, 100, 76, 75, 1, 4, 100, 101, 77, +76, 1, 4, 101, 102, 78, 77, 1, 4, 102, 103, 79, 78, 1, 4, 103, 104, 80, 79, 1, + 4, 104, 105, 81, 80, 1, 4, 105, 106, 82, 81, 1, 4, 106, 107, 83, 82, 1, 4, 107, + 108, 84, 83, 1, 4, 108, 109, 85, 84, 1, 4, 109, 110, 86, 85, 1, 4, 110, 111, 87, +86, 1, 4, 111, 112, 88, 87, 1, 4, 112, 113, 89, 88, 1, 4, 113, 114, 90, 89, 1, + 4, 114, 115, 91, 90, 1, 4, 115, 116, 92, 91, 1, 4, 116, 117, 93, 92, 1, 4, 117, + 118, 94, 93, 1, 4, 118, 119, 95, 94, 1, 4, 119, 96, 72, 95, 1, 24, 1, 3, 5, +6, 9, 10, 12, 14, 16, 19, 20, 23, 25, 27, 29, 30, 32, 34, 36, 38, 41, 43, 44, + 47, 1, 4, 48, 49, 2, 0, 1, 4, 49, 50, 4, 2, 1, 4, 50, 51, 7, 4, 1, + 4, 51, 52, 8, 7, 1, 4, 52, 53, 11, 8, 1, 4, 53, 54, 13, 11, 1, 4, 54, + 55, 15, 13, 1, 4, 55, 56, 17, 15, 1, 4, 56, 57, 18, 17, 1, 4, 57, 58, 21, + 18, 1, 4, 58, 59, 22, 21, 1, 4, 59, 60, 24, 22, 1, 4, 60, 61, 26, 24, 1, + 4, 61, 62, 28, 26, 1, 4, 62, 63, 31, 28, 1, 4, 63, 64, 33, 31, 1, 4, 64, + 65, 35, 33, 1, 4, 65, 66, 37, 35, 1, 4, 66, 67, 39, 37, 1, 4, 67, 68, 40, + 39, 1, 4, 68, 69, 42, 40, 1, 4, 69, 70, 45, 42, 1, 4, 70, 71, 46, 45, 1, + 4, 71, 48, 0, 46, 1, 24, 48, 71, 70, 69, 68, 67, 66, 65, 64, 63, 62, 61, 60, + 59, 58, 57, 56, 55, 54, 53, 52, 51, 50, 49, 1, + 0 +}; + +struct lwo LWO_GuageConnector = +{ + 152, /* number of points */ + GuageConnector_PNTS, GuageConnector_normals, GuageConnector_POLS, 0L +}; + +static const GLfloat GuageDial_PNTS[] = +{ + 0, 0.05, 0.3, + 0.019134, 0.046194, 0.3, + 0.035355, 0.035355, 0.3, + 0.046194, 0.019134, 0.3, + 0.05, 0, 0.3, + 0.046194, -0.019134, 0.3, + 0.035355, -0.0354, 0.275, + 0.035355, -0.0354, 0.3, + 0.019134, -0.0462, 0.3, + 0, -0.05, 0.3, + -0.019134, -0.0462, 0.3, + -0.035355, -0.0354, 0.275, + -0.035355, -0.0354, 0.3, + -0.046194, -0.019134, 0.3, + -0.05, 0, 0.3, + -0.046194, 0.019134, 0.3, + -0.035355, 0.035355, 0.3, + -0.019134, 0.046194, 0.3, + 0, 0.05, 0.2, + 0.019134, 0.046194, 0.2, + 0.035355, 0.035355, 0.2, + 0.046194, 0.019134, 0.2, + 0.05, 0, 0.2, + 0.046194, -0.019134, 0.2, + 0.035355, -0.035355, 0.2, + 0.019134, -0.046194, 0.2, + 0, -0.05, 0.2, + -0.019134, -0.046194, 0.2, + -0.035355, -0.035355, 0.2, + -0.046194, -0.019134, 0.2, + -0.05, 0, 0.2, + -0.046194, 0.019134, 0.2, + -0.035355, 0.035355, 0.2, + -0.019134, 0.046194, 0.2, + 0, -0.3733, 0.275, +}; + +static const GLfloat GuageDial_normals[] = +{ + 0, 0, 1, + 0, 0, 1, + 0.195089, 0.980786, 0, + 0.55557, 0.83147, 0, + 0.83147, 0.55557, 0, + 0.980785, 0.19509, 0, + 0.980785, -0.19509, 0, + 0.83147, -0.55557, -0.000248, + 0.55557, -0.83147, -0.000051, + 0.195089, -0.980786, 0, + -0.195089, -0.980786, -0.00006, + -0.55557, -0.83147, -0.000371, + -0.83147, -0.55557, 0, + -0.980785, -0.19509, 0, + -0.980785, 0.19509, 0, + -0.83147, 0.55557, 0, + -0.55557, 0.83147, 0, + -0.195089, 0.980786, 0, +}; + +static const unsigned short int GuageDial_POLS[] = +{ + 3, 11, 6, 34, 1, 16, 0, 1, 2, 3, 4, 5, 7, 8, 9, 10, 12, 13, 14, 15, + 16, 17, 1, 4, 18, 19, 1, 0, 1, 4, 19, 20, 2, 1, 1, 4, 20, 21, 3, 2, + 1, 4, 21, 22, 4, 3, 1, 4, 22, 23, 5, 4, 1, 4, 23, 24, 7, 5, 1, 4, + 24, 25, 8, 7, 1, 4, 25, 26, 9, 8, 1, 4, 26, 27, 10, 9, 1, 4, 27, 28, + 12, 10, 1, 4, 28, 29, 13, 12, 1, 4, 29, 30, 14, 13, 1, 4, 30, 31, 15, 14, + 1, 4, 31, 32, 16, 15, 1, 4, 32, 33, 17, 16, 1, 4, 33, 18, 0, 17, 1, + 0 +}; + +struct lwo LWO_GuageDial = +{ + 35, /* number of points */ + GuageDial_PNTS, GuageDial_normals, GuageDial_POLS, 0L +}; + +static const GLfloat GuageFace_PNTS[] = +{ + 0, 1.7833, 0.2, + -0.087791, 1.774653, 0.2, + -0.172208, 1.749046, 0.2, + -0.250007, 1.707461, 0.2, + -0.318198, 1.651498, 0.2, + -0.374161, 1.583307, 0.2, + -0.415746, 1.505508, 0.2, + -0.441353, 1.421091, 0.2, + -0.45, 1.3333, 0.2, + -0.441353, 1.245509, 0.2, + -0.415746, 1.161092, 0.2, + -0.374161, 1.083293, 0.2, + -0.318198, 1.015102, 0.2, + -0.250007, 0.959139, 0.2, + -0.172208, 0.917554, 0.2, + -0.087791, 0.891947, 0.2, + 0, 0.8833, 0.2, + 0.087791, 0.891947, 0.2, + 0.172208, 0.917554, 0.2, + 0.250007, 0.959139, 0.2, + 0.318198, 1.015102, 0.2, + 0.374161, 1.083293, 0.2, + 0.415746, 1.161092, 0.2, + 0.441353, 1.245509, 0.2, + 0.45, 1.3333, 0.2, + 0.441353, 1.421091, 0.2, + 0.415746, 1.505508, 0.2, + 0.374161, 1.583307, 0.2, + 0.318198, 1.651498, 0.2, + 0.250007, 1.707461, 0.2, + 0.172208, 1.749046, 0.2, + 0.087791, 1.774653, 0.2, +}; + +static const GLfloat GuageFace_normals[] = +{ + 0, 0, 1, +}; + +static const unsigned short int GuageFace_POLS[] = +{ +32, 0, 31, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, + 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 1, + 0 +}; + +struct lwo LWO_GuageFace = +{ + 32, /* number of points */ + GuageFace_PNTS, GuageFace_normals, GuageFace_POLS, 0L +}; + +static const GLfloat GuageHead_PNTS[] = +{ + 0, 1.8333, 0.33333, + 0.097545, 1.823693, 0.33333, + 0.191342, 1.79524, 0.33333, + 0.277785, 1.749035, 0.33333, + 0.353553, 1.686853, 0.33333, + 0.415735, 1.611085, 0.33333, + 0.46194, 1.524642, 0.33333, + 0.490393, 1.430845, 0.33333, + 0.5, 1.3333, 0.33333, + 0.490393, 1.235755, 0.33333, + 0.46194, 1.141958, 0.33333, + 0.415735, 1.055515, 0.33333, + 0.353553, 0.979747, 0.33333, + 0.277785, 0.917565, 0.33333, + 0.191342, 0.87136, 0.33333, + 0.097545, 0.842907, 0.33333, + 0, 0.8333, 0.33333, + -0.097545, 0.842907, 0.33333, + -0.191342, 0.87136, 0.33333, + -0.277785, 0.917565, 0.33333, + -0.353553, 0.979747, 0.33333, + -0.415735, 1.055515, 0.33333, + -0.46194, 1.141958, 0.33333, + -0.490393, 1.235755, 0.33333, + -0.5, 1.3333, 0.33333, + -0.490393, 1.430845, 0.33333, + -0.46194, 1.524642, 0.33333, + -0.415735, 1.611085, 0.33333, + -0.353553, 1.686853, 0.33333, + -0.277785, 1.749035, 0.33333, + -0.191342, 1.79524, 0.33333, + -0.097545, 1.823693, 0.33333, + 0, 1.8333, -0.33333, + 0.097545, 1.823693, -0.33333, + 0.191342, 1.79524, -0.33333, + 0.277785, 1.749035, -0.33333, + 0.353553, 1.686853, -0.33333, + 0.415735, 1.611085, -0.33333, + 0.46194, 1.524642, -0.33333, + 0.490393, 1.430845, -0.33333, + 0.5, 1.3333, -0.33333, + 0.490393, 1.235755, -0.33333, + 0.46194, 1.141958, -0.33333, + 0.415735, 1.055515, -0.33333, + 0.353553, 0.979747, -0.33333, + 0.277785, 0.917565, -0.33333, + 0.191342, 0.87136, -0.33333, + 0.097545, 0.842907, -0.33333, + 0, 0.8333, -0.33333, + -0.097545, 0.842907, -0.33333, + -0.191342, 0.87136, -0.33333, + -0.277785, 0.917565, -0.33333, + -0.353553, 0.979747, -0.33333, + -0.415735, 1.055515, -0.33333, + -0.46194, 1.141958, -0.33333, + -0.490393, 1.235755, -0.33333, + -0.5, 1.3333, -0.33333, + -0.490393, 1.430845, -0.33333, + -0.46194, 1.524642, -0.33333, + -0.415735, 1.611085, -0.33333, + -0.353553, 1.686853, -0.33333, + -0.277785, 1.749035, -0.33333, + -0.191342, 1.79524, -0.33333, + -0.097545, 1.823693, -0.33333, + 0.087791, 1.774653, 0.33333, + 0, 1.7833, 0.33333, + 0.172208, 1.749046, 0.33333, + 0.250007, 1.707461, 0.33333, + 0.318198, 1.651498, 0.33333, + 0.374161, 1.583307, 0.33333, + 0.415746, 1.505508, 0.33333, + 0.441353, 1.421091, 0.33333, + 0.45, 1.3333, 0.33333, + 0.441353, 1.245509, 0.33333, + 0.415746, 1.161092, 0.33333, + 0.374161, 1.083293, 0.33333, + 0.318198, 1.015102, 0.33333, + 0.250007, 0.959139, 0.33333, + 0.172208, 0.917554, 0.33333, + 0.087791, 0.891947, 0.33333, + 0, 0.8833, 0.33333, + -0.087791, 0.891947, 0.33333, + -0.172208, 0.917554, 0.33333, + -0.250007, 0.959139, 0.33333, + -0.318198, 1.015102, 0.33333, + -0.374161, 1.083293, 0.33333, + -0.415746, 1.161092, 0.33333, + -0.441353, 1.245509, 0.33333, + -0.45, 1.3333, 0.33333, + -0.441353, 1.421091, 0.33333, + -0.415746, 1.505508, 0.33333, + -0.374161, 1.583307, 0.33333, + -0.318198, 1.651498, 0.33333, + -0.250007, 1.707461, 0.33333, + -0.172208, 1.749046, 0.33333, + -0.087791, 1.774653, 0.33333, + 0, 1.7833, 0.2, + -0.087791, 1.774653, 0.2, + -0.172208, 1.749046, 0.2, + -0.250007, 1.707461, 0.2, + -0.318198, 1.651498, 0.2, + -0.374161, 1.583307, 0.2, + -0.415746, 1.505508, 0.2, + -0.441353, 1.421091, 0.2, + -0.45, 1.3333, 0.2, + -0.441353, 1.245509, 0.2, + -0.415746, 1.161092, 0.2, + -0.374161, 1.083293, 0.2, + -0.318198, 1.015102, 0.2, + -0.250007, 0.959139, 0.2, + -0.172208, 0.917554, 0.2, + -0.087791, 0.891947, 0.2, + 0, 0.8833, 0.2, + 0.087791, 0.891947, 0.2, + 0.172208, 0.917554, 0.2, + 0.250007, 0.959139, 0.2, + 0.318198, 1.015102, 0.2, + 0.374161, 1.083293, 0.2, + 0.415746, 1.161092, 0.2, + 0.441353, 1.245509, 0.2, + 0.45, 1.3333, 0.2, + 0.441353, 1.421091, 0.2, + 0.415746, 1.505508, 0.2, + 0.374161, 1.583307, 0.2, + 0.318198, 1.651498, 0.2, + 0.250007, 1.707461, 0.2, + 0.172208, 1.749046, 0.2, + 0.087791, 1.774653, 0.2, +}; + +static const GLfloat GuageHead_normals[] = +{ + 0, 0, 1, + 0, 0, 1, + 0, 0, 1, + 0, 0, 1, + 0, 0, 1, + 0, 0, 1, + 0, 0, 1, + 0, 0, 1, + 0, 0, 1, + 0, 0, 1, + 0, 0, 1, + 0, 0, 1, + 0, 0, 1, + 0, 0, 1, + 0, 0, 1, + 0, 0, 1, + 0, 0, 1, + 0, 0, 1, + 0, 0, 1, + 0, 0, 1, + 0, 0, 1, + 0, 0, 1, + 0, 0, 1, + 0, 0, 1, + 0, 0, 1, + 0, 0, 1, + 0, 0, 1, + 0, 0, 1, + 0, 0, 1, + 0, 0, 1, + 0, 0, 1, + 0, 0, 1, + 0, 0, 1, + 0, 0, 1, + 0, 0, 1, + 0, 0, 1, + 0, 0, 1, + 0, 0, 1, + 0, 0, 1, + 0, 0, 1, + 0, 0, 1, + 0, 0, 1, + 0, 0, 1, + 0, 0, 1, + 0, 0, 1, + 0, 0, 1, + 0, 0, 1, + 0, 0, 1, + 0, 0, 1, + 0, 0, 1, + 0, 0, 1, + 0, 0, 1, + 0, 0, 1, + 0, 0, 1, + 0, 0, 1, + 0, 0, 1, + 0, 0, 1, + 0, 0, 1, + 0, 0, 1, + 0, 0, 1, + 0, 0, 1, + 0, 0, 1, + 0, 0, 1, + 0, 0, 1, + 0.098017, -0.995185, 0, + 0.290285, -0.95694, 0, + 0.471397, -0.881921, 0, + 0.634393, -0.77301, 0, + 0.773011, -0.634393, 0, + 0.881921, -0.471397, 0, + 0.95694, -0.290284, 0, + 0.995185, -0.098017, 0, + 0.995185, 0.098017, 0, + 0.95694, 0.290284, 0, + 0.881921, 0.471397, 0, + 0.773011, 0.634393, 0, + 0.634393, 0.773011, 0, + 0.471397, 0.881921, 0, + 0.290285, 0.95694, 0, + 0.098017, 0.995185, 0, + -0.098017, 0.995185, 0, + -0.290285, 0.95694, 0, + -0.471397, 0.881921, 0, + -0.634393, 0.773011, 0, + -0.773011, 0.634393, 0, + -0.881921, 0.471397, 0, + -0.95694, 0.290284, 0, + -0.995185, 0.098017, 0, + -0.995185, -0.098017, 0, + -0.95694, -0.290284, 0, + -0.881921, -0.471397, 0, + -0.773011, -0.634393, 0, + -0.634393, -0.77301, 0, + -0.471397, -0.881921, 0, + -0.290285, -0.95694, 0, + -0.098017, -0.995185, 0, + 0.098017, 0.995185, 0, + 0.290285, 0.95694, 0, + 0.471397, 0.881921, 0, + 0.634393, 0.773011, 0, + 0.773011, 0.634393, 0, + 0.881921, 0.471397, 0, + 0.95694, 0.290284, 0, + 0.995185, 0.098017, 0, + 0.995185, -0.098017, 0, + 0.95694, -0.290284, 0, + 0.881921, -0.471397, 0, + 0.773011, -0.634393, 0, + 0.634393, -0.77301, 0, + 0.471396, -0.881921, 0, + 0.290285, -0.95694, 0, + 0.098017, -0.995185, 0, + -0.098017, -0.995185, 0, + -0.290285, -0.95694, 0, + -0.471396, -0.881921, 0, + -0.634393, -0.77301, 0, + -0.773011, -0.634393, 0, + -0.881921, -0.471397, 0, + -0.95694, -0.290284, 0, + -0.995185, -0.098017, 0, + -0.995185, 0.098017, 0, + -0.95694, 0.290284, 0, + -0.881921, 0.471397, 0, + -0.773011, 0.634393, 0, + -0.634393, 0.773011, 0, + -0.471397, 0.881921, 0, + -0.290285, 0.95694, 0, + -0.098017, 0.995185, 0, + 0, 0, -1, +}; + +static const unsigned short int GuageHead_POLS[] = +{ + 3, 67, 3, 4, 1, 3, 68, 67, 4, 1, 3, 68, 4, 5, 1, 3, 69, 68, 5, 1, + 3, 70, 69, 5, 1, 3, 70, 5, 6, 1, 3, 70, 6, 7, 1, 3, 71, 70, 7, 1, + 3, 71, 7, 8, 1, 3, 72, 71, 8, 1, 3, 73, 72, 8, 1, 3, 73, 8, 9, 1, + 3, 74, 73, 9, 1, 3, 74, 9, 10, 1, 3, 74, 10, 11, 1, 3, 75, 74, 11, 1, + 3, 76, 75, 11, 1, 3, 76, 11, 12, 1, 3, 76, 12, 13, 1, 3, 77, 76, 13, 1, + 3, 78, 77, 13, 1, 3, 78, 13, 14, 1, 3, 78, 14, 15, 1, 3, 79, 78, 15, 1, + 3, 79, 15, 16, 1, 3, 80, 79, 16, 1, 3, 81, 80, 16, 1, 3, 81, 16, 17, 1, + 3, 82, 81, 17, 1, 3, 82, 17, 18, 1, 3, 82, 18, 19, 1, 3, 83, 82, 19, 1, + 3, 84, 83, 19, 1, 3, 84, 19, 20, 1, 3, 84, 20, 21, 1, 3, 85, 84, 21, 1, + 3, 86, 85, 21, 1, 3, 86, 21, 22, 1, 3, 86, 22, 23, 1, 3, 87, 86, 23, 1, + 3, 87, 23, 24, 1, 3, 88, 87, 24, 1, 3, 89, 88, 24, 1, 3, 89, 24, 25, 1, + 3, 90, 89, 25, 1, 3, 90, 25, 26, 1, 3, 90, 26, 27, 1, 3, 91, 90, 27, 1, + 3, 92, 91, 27, 1, 3, 92, 27, 28, 1, 3, 93, 92, 28, 1, 3, 93, 28, 29, 1, + 3, 2, 3, 67, 1, 3, 2, 67, 66, 1, 3, 1, 2, 66, 1, 3, 1, 66, 64, 1, + 3, 1, 64, 65, 1, 3, 0, 1, 65, 1, 3, 31, 0, 65, 1, 3, 31, 65, 95, 1, + 3, 31, 95, 94, 1, 3, 30, 31, 94, 1, 3, 30, 94, 93, 1, 3, 93, 29, 30, 1, + 4, 96, 97, 95, 65, 1, 4, 97, 98, 94, 95, 1, 4, 98, 99, 93, 94, 1, 4, 99, + 100, 92, 93, 1, 4, 100, 101, 91, 92, 1, 4, 101, 102, 90, 91, 1, 4, 102, 103, 89, +90, 1, 4, 103, 104, 88, 89, 1, 4, 104, 105, 87, 88, 1, 4, 105, 106, 86, 87, 1, + 4, 106, 107, 85, 86, 1, 4, 107, 108, 84, 85, 1, 4, 108, 109, 83, 84, 1, 4, 109, + 110, 82, 83, 1, 4, 110, 111, 81, 82, 1, 4, 111, 112, 80, 81, 1, 4, 112, 113, 79, +80, 1, 4, 113, 114, 78, 79, 1, 4, 114, 115, 77, 78, 1, 4, 115, 116, 76, 77, 1, + 4, 116, 117, 75, 76, 1, 4, 117, 118, 74, 75, 1, 4, 118, 119, 73, 74, 1, 4, 119, + 120, 72, 73, 1, 4, 120, 121, 71, 72, 1, 4, 121, 122, 70, 71, 1, 4, 122, 123, 69, +70, 1, 4, 123, 124, 68, 69, 1, 4, 124, 125, 67, 68, 1, 4, 125, 126, 66, 67, 1, + 4, 126, 127, 64, 66, 1, 4, 127, 96, 65, 64, 1, 4, 32, 33, 1, 0, 1, 4, 33, + 34, 2, 1, 1, 4, 34, 35, 3, 2, 1, 4, 35, 36, 4, 3, 1, 4, 36, 37, 5, + 4, 1, 4, 37, 38, 6, 5, 1, 4, 38, 39, 7, 6, 1, 4, 39, 40, 8, 7, 1, + 4, 40, 41, 9, 8, 1, 4, 41, 42, 10, 9, 1, 4, 42, 43, 11, 10, 1, 4, 43, + 44, 12, 11, 1, 4, 44, 45, 13, 12, 1, 4, 45, 46, 14, 13, 1, 4, 46, 47, 15, + 14, 1, 4, 47, 48, 16, 15, 1, 4, 48, 49, 17, 16, 1, 4, 49, 50, 18, 17, 1, + 4, 50, 51, 19, 18, 1, 4, 51, 52, 20, 19, 1, 4, 52, 53, 21, 20, 1, 4, 53, + 54, 22, 21, 1, 4, 54, 55, 23, 22, 1, 4, 55, 56, 24, 23, 1, 4, 56, 57, 25, + 24, 1, 4, 57, 58, 26, 25, 1, 4, 58, 59, 27, 26, 1, 4, 59, 60, 28, 27, 1, + 4, 60, 61, 29, 28, 1, 4, 61, 62, 30, 29, 1, 4, 62, 63, 31, 30, 1, 4, 63, +32, 0, 31, 1, 32, 32, 63, 62, 61, 60, 59, 58, 57, 56, 55, 54, 53, 52, 51, 50, + 49, 48, 47, 46, 45, 44, 43, 42, 41, 40, 39, 38, 37, 36, 35, 34, 33, 1, + 0 +}; + +struct lwo LWO_GuageHead = +{ + 128, /* number of points */ + GuageHead_PNTS, GuageHead_normals, GuageHead_POLS, 0L +}; + +static const GLfloat PipeBetweenBolts_PNTS[] = +{ + 0, 0.5, 0.5, + 0.12941, 0.482963, 0.5, + 0.25, 0.433013, 0.5, + 0.353553, 0.353553, 0.5, + 0.433013, 0.25, 0.5, + 0.482963, 0.12941, 0.5, + 0.5, 0, 0.5, + 0.482963, -0.12941, 0.5, + 0.433013, -0.25, 0.5, + 0.353553, -0.353553, 0.5, + 0.25, -0.433013, 0.5, + 0.12941, -0.482963, 0.5, + 0, -0.5, 0.5, + -0.12941, -0.482963, 0.5, + -0.25, -0.433013, 0.5, + -0.353553, -0.353553, 0.5, + -0.433013, -0.25, 0.5, + -0.482963, -0.12941, 0.5, + -0.5, 0, 0.5, + -0.482963, 0.12941, 0.5, + -0.433013, 0.25, 0.5, + -0.353553, 0.353553, 0.5, + -0.25, 0.433013, 0.5, + -0.12941, 0.482963, 0.5, + 0, 0.5, -0.5, + 0.12941, 0.482963, -0.5, + 0.25, 0.433013, -0.5, + 0.353553, 0.353553, -0.5, + 0.433013, 0.25, -0.5, + 0.482963, 0.12941, -0.5, + 0.5, 0, -0.5, + 0.482963, -0.12941, -0.5, + 0.433013, -0.25, -0.5, + 0.353553, -0.353553, -0.5, + 0.25, -0.433013, -0.5, + 0.12941, -0.482963, -0.5, + 0, -0.5, -0.5, + -0.12941, -0.482963, -0.5, + -0.25, -0.433013, -0.5, + -0.353553, -0.353553, -0.5, + -0.433013, -0.25, -0.5, + -0.482963, -0.12941, -0.5, + -0.5, 0, -0.5, + -0.482963, 0.12941, -0.5, + -0.433013, 0.25, -0.5, + -0.353553, 0.353553, -0.5, + -0.25, 0.433013, -0.5, + -0.12941, 0.482963, -0.5, +}; + +static const GLfloat PipeBetweenBolts_normals[] = +{ + 0, 0, 1, + 0.130526, 0.991445, 0, + 0.382683, 0.92388, 0, + 0.608761, 0.793353, 0, + 0.793353, 0.608761, 0, + 0.92388, 0.382683, 0, + 0.991445, 0.130526, 0, + 0.991445, -0.130526, 0, + 0.92388, -0.382683, 0, + 0.793353, -0.608761, 0, + 0.608761, -0.793353, 0, + 0.382683, -0.92388, 0, + 0.130526, -0.991445, 0, + -0.130526, -0.991445, 0, + -0.382683, -0.92388, 0, + -0.608761, -0.793353, 0, + -0.793353, -0.608761, 0, + -0.92388, -0.382683, 0, + -0.991445, -0.130526, 0, + -0.991445, 0.130526, 0, + -0.92388, 0.382683, 0, + -0.793353, 0.608761, 0, + -0.608761, 0.793353, 0, + -0.382683, 0.92388, 0, + -0.130526, 0.991445, 0, + 0, 0, -1, +}; + +static const unsigned short int PipeBetweenBolts_POLS[] = +{ + 24, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, + 19, 20, 21, 22, 23, 1, 4, 24, 25, 1, 0, 1, 4, 25, 26, 2, 1, 1, 4, 26, + 27, 3, 2, 1, 4, 27, 28, 4, 3, 1, 4, 28, 29, 5, 4, 1, 4, 29, 30, 6, + 5, 1, 4, 30, 31, 7, 6, 1, 4, 31, 32, 8, 7, 1, 4, 32, 33, 9, 8, 1, + 4, 33, 34, 10, 9, 1, 4, 34, 35, 11, 10, 1, 4, 35, 36, 12, 11, 1, 4, 36, + 37, 13, 12, 1, 4, 37, 38, 14, 13, 1, 4, 38, 39, 15, 14, 1, 4, 39, 40, 16, + 15, 1, 4, 40, 41, 17, 16, 1, 4, 41, 42, 18, 17, 1, 4, 42, 43, 19, 18, 1, + 4, 43, 44, 20, 19, 1, 4, 44, 45, 21, 20, 1, 4, 45, 46, 22, 21, 1, 4, 46, + 47, 23, 22, 1, 4, 47, 24, 0, 23, 1, 24, 24, 47, 46, 45, 44, 43, 42, 41, 40, + 39, 38, 37, 36, 35, 34, 33, 32, 31, 30, 29, 28, 27, 26, 25, 1, + 0 +}; + +struct lwo LWO_PipeBetweenBolts = +{ + 48, /* number of points */ + PipeBetweenBolts_PNTS, PipeBetweenBolts_normals, PipeBetweenBolts_POLS, 0L +}; + +static const GLfloat ElbowBolts_PNTS[] = +{ + 0.273122, -0.6, -0.403061, + 0.273122, 0.403061, -0.6, + 0.273122, 0.333061, -0.6, + 0.273122, -0.6, -0.333061, + 0.2125, 0.298061, -0.6, + 0.2125, -0.6, -0.298061, + 0.151878, 0.333061, -0.6, + 0.151878, -0.6, -0.333061, + 0.151878, 0.403061, -0.6, + 0.151878, -0.6, -0.403061, + 0.2125, -0.6, -0.438061, + 0.2125, 0.438061, -0.6, + 0.273122, -0.66, -0.403061, + 0.273122, 0.403061, -0.66, + 0.273122, -0.66, -0.333061, + 0.273122, 0.333061, -0.66, + 0.2125, 0.298061, -0.66, + 0.2125, -0.66, -0.298061, + 0.151878, -0.66, -0.333061, + 0.151878, 0.333061, -0.66, + 0.151878, 0.403061, -0.66, + 0.151878, -0.66, -0.403061, + 0.2125, -0.66, -0.438061, + 0.2125, 0.438061, -0.66, + 0.273122, 0.403061, -0.46, + 0.273122, -0.46, -0.403061, + 0.273122, 0.333061, -0.46, + 0.273122, -0.46, -0.333061, + 0.2125, 0.298061, -0.46, + 0.2125, -0.46, -0.298061, + 0.151878, 0.333061, -0.46, + 0.151878, -0.46, -0.333061, + 0.151878, 0.403061, -0.46, + 0.151878, -0.46, -0.403061, + 0.2125, -0.46, -0.438061, + 0.2125, 0.438061, -0.46, + 0.273122, 0.403061, -0.52, + 0.273122, -0.52, -0.403061, + 0.273122, -0.52, -0.333061, + 0.273122, 0.333061, -0.52, + 0.2125, 0.298061, -0.52, + 0.2125, -0.52, -0.298061, + 0.151878, 0.333061, -0.52, + 0.151878, -0.52, -0.333061, + 0.151878, 0.403061, -0.52, + 0.151878, -0.52, -0.403061, + 0.2125, -0.52, -0.438061, + 0.2125, 0.438061, -0.52, + 0.485622, -0.035, -0.46, + 0.485622, -0.46, 0.035, + 0.425, -0.07, -0.46, + 0.425, -0.46, 0.07, + 0.364378, -0.46, 0.035, + 0.364378, -0.035, -0.46, + 0.364378, 0.035, -0.46, + 0.364378, -0.46, -0.035, + 0.425, 0.07, -0.46, + 0.425, -0.46, -0.07, + 0.485622, 0.035, -0.46, + 0.485622, -0.46, -0.035, + 0.485622, -0.52, 0.035, + 0.485622, -0.035, -0.52, + 0.425, -0.07, -0.52, + 0.425, -0.52, 0.07, + 0.364378, -0.035, -0.52, + 0.364378, -0.52, 0.035, + 0.364378, -0.52, -0.035, + 0.364378, 0.035, -0.52, + 0.425, 0.07, -0.52, + 0.425, -0.52, -0.07, + 0.485622, 0.035, -0.52, + 0.485622, -0.52, -0.035, + 0.485622, -0.035, -0.6, + 0.485622, -0.6, 0.035, + 0.425, -0.6, 0.07, + 0.425, -0.07, -0.6, + 0.364378, -0.6, 0.035, + 0.364378, -0.035, -0.6, + 0.364378, 0.035, -0.6, + 0.364378, -0.6, -0.035, + 0.425, 0.07, -0.6, + 0.425, -0.6, -0.07, + 0.485622, -0.6, -0.035, + 0.485622, 0.035, -0.6, + 0.485622, -0.66, 0.035, + 0.485622, -0.035, -0.66, + 0.425, -0.66, 0.07, + 0.425, -0.07, -0.66, + 0.364378, -0.035, -0.66, + 0.364378, -0.66, 0.035, + 0.364378, -0.66, -0.035, + 0.364378, 0.035, -0.66, + 0.425, 0.07, -0.66, + 0.425, -0.66, -0.07, + 0.485622, -0.66, -0.035, + 0.485622, 0.035, -0.66, + 0.2125, -0.438061, -0.46, + 0.2125, -0.46, 0.438061, + 0.151878, -0.403061, -0.46, + 0.151878, -0.46, 0.403061, + 0.151878, -0.46, 0.333061, + 0.151878, -0.333061, -0.46, + 0.2125, -0.46, 0.298061, + 0.2125, -0.298061, -0.46, + 0.273122, -0.46, 0.333061, + 0.273122, -0.333061, -0.46, + 0.273122, -0.403061, -0.46, + 0.273122, -0.46, 0.403061, + 0.2125, -0.52, 0.438061, + 0.2125, -0.438061, -0.52, + 0.151878, -0.403061, -0.52, + 0.151878, -0.52, 0.403061, + 0.151878, -0.333061, -0.52, + 0.151878, -0.52, 0.333061, + 0.2125, -0.298061, -0.52, + 0.2125, -0.52, 0.298061, + 0.273122, -0.333061, -0.52, + 0.273122, -0.52, 0.333061, + 0.273122, -0.403061, -0.52, + 0.273122, -0.52, 0.403061, + 0.2125, -0.438061, -0.6, + 0.2125, -0.6, 0.438061, + 0.151878, -0.403061, -0.6, + 0.151878, -0.6, 0.403061, + 0.151878, -0.6, 0.333061, + 0.151878, -0.333061, -0.6, + 0.2125, -0.298061, -0.6, + 0.2125, -0.6, 0.298061, + 0.273122, -0.333061, -0.6, + 0.273122, -0.6, 0.333061, + 0.273122, -0.6, 0.403061, + 0.273122, -0.403061, -0.6, + 0.2125, -0.66, 0.438061, + 0.2125, -0.438061, -0.66, + 0.151878, -0.403061, -0.66, + 0.151878, -0.66, 0.403061, + 0.151878, -0.333061, -0.66, + 0.151878, -0.66, 0.333061, + 0.2125, -0.66, 0.298061, + 0.2125, -0.298061, -0.66, + 0.273122, -0.66, 0.333061, + 0.273122, -0.333061, -0.66, + 0.273122, -0.66, 0.403061, + 0.273122, -0.403061, -0.66, + -0.273122, -0.46, 0.403061, + -0.273122, -0.403061, -0.46, + -0.273122, -0.46, 0.333061, + -0.273122, -0.333061, -0.46, + -0.2125, -0.298061, -0.46, + -0.2125, -0.46, 0.298061, + -0.151878, -0.333061, -0.46, + -0.151878, -0.46, 0.333061, + -0.151878, -0.403061, -0.46, + -0.151878, -0.46, 0.403061, + -0.2125, -0.46, 0.438061, + -0.2125, -0.438061, -0.46, + -0.273122, -0.52, 0.403061, + -0.273122, -0.403061, -0.52, + -0.273122, -0.333061, -0.52, + -0.273122, -0.52, 0.333061, + -0.2125, -0.52, 0.298061, + -0.2125, -0.298061, -0.52, + -0.151878, -0.333061, -0.52, + -0.151878, -0.52, 0.333061, + -0.151878, -0.52, 0.403061, + -0.151878, -0.403061, -0.52, + -0.2125, -0.52, 0.438061, + -0.2125, -0.438061, -0.52, + -0.273122, -0.6, 0.403061, + -0.273122, -0.403061, -0.6, + -0.273122, -0.6, 0.333061, + -0.273122, -0.333061, -0.6, + -0.2125, -0.6, 0.298061, + -0.2125, -0.298061, -0.6, + -0.151878, -0.333061, -0.6, + -0.151878, -0.6, 0.333061, + -0.151878, -0.6, 0.403061, + -0.151878, -0.403061, -0.6, + -0.2125, -0.438061, -0.6, + -0.2125, -0.6, 0.438061, + -0.273122, -0.66, 0.403061, + -0.273122, -0.403061, -0.66, + -0.273122, -0.333061, -0.66, + -0.273122, -0.66, 0.333061, + -0.2125, -0.298061, -0.66, + -0.2125, -0.66, 0.298061, + -0.151878, -0.66, 0.333061, + -0.151878, -0.333061, -0.66, + -0.151878, -0.66, 0.403061, + -0.151878, -0.403061, -0.66, + -0.2125, -0.438061, -0.66, + -0.2125, -0.66, 0.438061, + -0.485622, -0.46, -0.035, + -0.485622, 0.035, -0.46, + -0.425, 0.07, -0.46, + -0.425, -0.46, -0.07, + -0.364378, 0.035, -0.46, + -0.364378, -0.46, -0.035, + -0.364378, -0.46, 0.035, + -0.364378, -0.035, -0.46, + -0.425, -0.46, 0.07, + -0.425, -0.07, -0.46, + -0.485622, -0.035, -0.46, + -0.485622, -0.46, 0.035, + -0.485622, -0.52, -0.035, + -0.485622, 0.035, -0.52, + -0.425, 0.07, -0.52, + -0.425, -0.52, -0.07, + -0.364378, 0.035, -0.52, + -0.364378, -0.52, -0.035, + -0.364378, -0.035, -0.52, + -0.364378, -0.52, 0.035, + -0.425, -0.52, 0.07, + -0.425, -0.07, -0.52, + -0.485622, -0.035, -0.52, + -0.485622, -0.52, 0.035, + -0.485622, 0.035, -0.6, + -0.485622, -0.6, -0.035, + -0.425, -0.6, -0.07, + -0.425, 0.07, -0.6, + -0.364378, -0.6, -0.035, + -0.364378, 0.035, -0.6, + -0.364378, -0.6, 0.035, + -0.364378, -0.035, -0.6, + -0.425, -0.6, 0.07, + -0.425, -0.07, -0.6, + -0.485622, -0.6, 0.035, + -0.485622, -0.035, -0.6, + -0.485622, -0.66, -0.035, + -0.485622, 0.035, -0.66, + -0.425, -0.66, -0.07, + -0.425, 0.07, -0.66, + -0.364378, 0.035, -0.66, + -0.364378, -0.66, -0.035, + -0.364378, -0.66, 0.035, + -0.364378, -0.035, -0.66, + -0.425, -0.07, -0.66, + -0.425, -0.66, 0.07, + -0.485622, -0.66, 0.035, + -0.485622, -0.035, -0.66, + -0.2125, -0.46, -0.438061, + -0.2125, 0.438061, -0.46, + -0.151878, 0.403061, -0.46, + -0.151878, -0.46, -0.403061, + -0.151878, -0.46, -0.333061, + -0.151878, 0.333061, -0.46, + -0.2125, 0.298061, -0.46, + -0.2125, -0.46, -0.298061, + -0.273122, 0.333061, -0.46, + -0.273122, -0.46, -0.333061, + -0.273122, -0.46, -0.403061, + -0.273122, 0.403061, -0.46, + -0.2125, -0.52, -0.438061, + -0.2125, 0.438061, -0.52, + -0.151878, 0.403061, -0.52, + -0.151878, -0.52, -0.403061, + -0.151878, -0.52, -0.333061, + -0.151878, 0.333061, -0.52, + -0.2125, 0.298061, -0.52, + -0.2125, -0.52, -0.298061, + -0.273122, 0.333061, -0.52, + -0.273122, -0.52, -0.333061, + -0.273122, 0.403061, -0.52, + -0.273122, -0.52, -0.403061, + -0.2125, 0.438061, -0.6, + -0.2125, -0.6, -0.438061, + -0.151878, -0.6, -0.403061, + -0.151878, 0.403061, -0.6, + -0.151878, 0.333061, -0.6, + -0.151878, -0.6, -0.333061, + -0.2125, -0.6, -0.298061, + -0.2125, 0.298061, -0.6, + -0.273122, -0.6, -0.333061, + -0.273122, 0.333061, -0.6, + -0.273122, -0.6, -0.403061, + -0.273122, 0.403061, -0.6, + -0.2125, -0.66, -0.438061, + -0.2125, 0.438061, -0.66, + -0.151878, -0.66, -0.403061, + -0.151878, 0.403061, -0.66, + -0.151878, -0.66, -0.333061, + -0.151878, 0.333061, -0.66, + -0.2125, -0.66, -0.298061, + -0.2125, 0.298061, -0.66, + -0.273122, -0.66, -0.333061, + -0.273122, 0.333061, -0.66, + -0.273122, 0.403061, -0.66, + -0.273122, -0.66, -0.403061, +}; + +static const GLfloat ElbowBolts_normals[] = +{ + 0, 0, 1, + 0.5, 0.866026, 0, + 1, 0, 0, + 0.5, -0.866025, 0, + -0.5, -0.866025, 0, + -1, 0, 0, + -0.5, 0.866025, 0, + 0, 0, -1, + 0, 0, 1, + 0.499999, 0.866026, 0, + 1, 0, 0, + 0.5, -0.866025, 0, + -0.5, -0.866025, 0, + -1, 0, 0, + -0.5, 0.866025, 0, + 0, 0, -1, + 0, 0, 1, + -0.5, 0.866025, 0, + 0.5, 0.866025, 0, + 1, 0, 0, + 0.5, -0.866025, 0, + -0.5, -0.866025, 0, + -1, 0, 0, + 0, 0, -1, + 0, 0, 1, + -0.5, 0.866025, 0, + 0.5, 0.866025, 0, + 1, 0, 0, + 0.5, -0.866025, 0, + -0.5, -0.866025, 0, + -1, 0, 0, + 0, 0, -1, + 0, 0, 1, + -1, 0, 0, + -0.5, 0.866026, 0, + 0.5, 0.866025, 0, + 1, 0, 0, + 0.5, -0.866026, 0, + -0.5, -0.866025, 0, + 0, 0, -1, + 0, 0, 1, + -1, 0, 0, + -0.5, 0.866026, 0, + 0.5, 0.866025, 0, + 1, 0, 0, + 0.5, -0.866025, 0, + -0.5, -0.866025, 0, + 0, 0, -1, + 0, 0, 1, + -0.5, -0.866026, 0, + -1, 0, 0, + -0.5, 0.866025, 0, + 0.5, 0.866025, 0, + 1, 0, 0, + 0.5, -0.866025, 0, + 0, 0, -1, + 0, 0, 1, + -0.499999, -0.866026, 0, + -1, 0, 0, + -0.5, 0.866025, 0, + 0.5, 0.866025, 0, + 1, 0, 0, + 0.5, -0.866025, 0, + 0, 0, -1, + 0, 0, 1, + 0.5, -0.866025, 0, + -0.5, -0.866025, 0, + -1, 0, 0, + -0.5, 0.866025, 0, + 0.5, 0.866025, 0, + 1, 0, 0, + 0, 0, -1, + 0, 0, 1, + 0.5, -0.866025, 0, + -0.5, -0.866025, 0, + -1, 0, 0, + -0.5, 0.866025, 0, + 0.5, 0.866025, 0, + 1, 0, 0, + 0, 0, -1, + 0, 0, 1, + 1, 0, 0, + 0.5, -0.866026, 0, + -0.5, -0.866025, 0, + -1, 0, 0, + -0.5, 0.866026, 0, + 0.5, 0.866025, 0, + 0, 0, -1, + 0, 0, 1, + 1, 0, 0, + 0.5, -0.866026, 0, + -0.5, -0.866025, 0, + -1, 0, 0, + -0.5, 0.866025, 0, + 0.5, 0.866025, 0, + 0, 0, -1, + 0, 1, 0, + 0.5, 0, -0.866026, + 1, 0, 0, + 0.5, 0, 0.866025, + -0.5, 0, 0.866025, + -1, 0, 0, + -0.5, 0, -0.866025, + 0, -1, 0, + 0, 1, 0, + 0.499999, 0, -0.866026, + 1, 0, 0, + 0.5, 0, 0.866025, + -0.5, 0, 0.866025, + -1, 0, 0, + -0.5, 0, -0.866025, + 0, -1, 0, + 0, 1, 0, + -0.5, 0, -0.866025, + 0.5, 0, -0.866025, + 1, 0, 0, + 0.5, 0, 0.866025, + -0.5, 0, 0.866025, + -1, 0, 0, + 0, -1, 0, + 0, 1, 0, + -0.5, 0, -0.866025, + 0.5, 0, -0.866025, + 1, 0, 0, + 0.5, 0, 0.866025, + -0.5, 0, 0.866025, + -1, 0, 0, + 0, -1, 0, + 0, 1, 0, + -1, 0, 0, + -0.5, 0, -0.866026, + 0.5, 0, -0.866025, + 1, 0, 0, + 0.5, 0, 0.866026, + -0.5, 0, 0.866025, + 0, -1, 0, + 0, 1, 0, + -1, 0, 0, + -0.5, 0, -0.866026, + 0.5, 0, -0.866025, + 1, 0, 0, + 0.5, 0, 0.866025, + -0.5, 0, 0.866025, + 0, -1, 0, + 0, 1, 0, + -0.5, 0, 0.866026, + -1, 0, 0, + -0.5, 0, -0.866025, + 0.5, 0, -0.866025, + 1, 0, 0, + 0.5, 0, 0.866025, + 0, -1, 0, + 0, 1, 0, + -0.499999, 0, 0.866026, + -1, 0, 0, + -0.5, 0, -0.866025, + 0.5, 0, -0.866025, + 1, 0, 0, + 0.5, 0, 0.866025, + 0, -1, 0, + 0, 1, 0, + 0.5, 0, 0.866025, + -0.5, 0, 0.866025, + -1, 0, 0, + -0.5, 0, -0.866025, + 0.5, 0, -0.866025, + 1, 0, 0, + 0, -1, 0, + 0, 1, 0, + 0.5, 0, 0.866025, + -0.5, 0, 0.866025, + -1, 0, 0, + -0.5, 0, -0.866025, + 0.5, 0, -0.866025, + 1, 0, 0, + 0, -1, 0, + 0, 1, 0, + 1, 0, 0, + 0.5, 0, 0.866026, + -0.5, 0, 0.866025, + -1, 0, 0, + -0.5, 0, -0.866026, + 0.5, 0, -0.866025, + 0, -1, 0, + 0, 1, 0, + 1, 0, 0, + 0.5, 0, 0.866026, + -0.5, 0, 0.866025, + -1, 0, 0, + -0.5, 0, -0.866025, + 0.5, 0, -0.866025, + 0, -1, 0, +}; + +static const unsigned short int ElbowBolts_POLS[] = +{ + 6, 241, 242, 245, 246, 248, 251, 1, 4, 253, 254, 242, 241, 1, 4, 254, 257, 245, 242, 1, + 4, 257, 258, 246, 245, 1, 4, 258, 260, 248, 246, 1, 4, 260, 262, 251, 248, 1, 4, 262, + 253, 241, 251, 1, 6, 253, 262, 260, 258, 257, 254, 1, 6, 264, 267, 268, 271, 273, 275, 1, + 4, 277, 279, 267, 264, 1, 4, 279, 281, 268, 267, 1, 4, 281, 283, 271, 268, 1, 4, 283, + 285, 273, 271, 1, 4, 285, 286, 275, 273, 1, 4, 286, 277, 264, 275, 1, 6, 277, 286, 285, + 283, 281, 279, 1, 6, 193, 194, 196, 199, 201, 202, 1, 4, 205, 206, 194, 193, 1, 4, 206, + 208, 196, 194, 1, 4, 208, 210, 199, 196, 1, 4, 210, 213, 201, 199, 1, 4, 213, 214, 202, + 201, 1, 4, 214, 205, 193, 202, 1, 6, 205, 214, 213, 210, 208, 206, 1, 6, 216, 219, 221, + 223, 225, 227, 1, 4, 229, 231, 219, 216, 1, 4, 231, 232, 221, 219, 1, 4, 232, 235, 223, + 221, 1, 4, 235, 236, 225, 223, 1, 4, 236, 239, 227, 225, 1, 4, 239, 229, 216, 227, 1, + 6, 229, 239, 236, 235, 232, 231, 1, 6, 145, 147, 148, 150, 152, 155, 1, 4, 157, 158, 147, + 145, 1, 4, 158, 161, 148, 147, 1, 4, 161, 162, 150, 148, 1, 4, 162, 165, 152, 150, 1, + 4, 165, 167, 155, 152, 1, 4, 167, 157, 145, 155, 1, 6, 157, 167, 165, 162, 161, 158, 1, + 6, 169, 171, 173, 174, 177, 178, 1, 4, 181, 182, 171, 169, 1, 4, 182, 184, 173, 171, 1, + 4, 184, 187, 174, 173, 1, 4, 187, 189, 177, 174, 1, 4, 189, 190, 178, 177, 1, 4, 190, + 181, 169, 178, 1, 6, 181, 190, 189, 187, 184, 182, 1, 6, 96, 98, 101, 103, 105, 106, 1, + 4, 109, 110, 98, 96, 1, 4, 110, 112, 101, 98, 1, 4, 112, 114, 103, 101, 1, 4, 114, + 116, 105, 103, 1, 4, 116, 118, 106, 105, 1, 4, 118, 109, 96, 106, 1, 6, 109, 118, 116, + 114, 112, 110, 1, 6, 120, 122, 125, 126, 128, 131, 1, 4, 133, 134, 122, 120, 1, 4, 134, + 136, 125, 122, 1, 4, 136, 139, 126, 125, 1, 4, 139, 141, 128, 126, 1, 4, 141, 143, 131, + 128, 1, 4, 143, 133, 120, 131, 1, 6, 133, 143, 141, 139, 136, 134, 1, 6, 48, 50, 53, + 54, 56, 58, 1, 4, 61, 62, 50, 48, 1, 4, 62, 64, 53, 50, 1, 4, 64, 67, 54, + 53, 1, 4, 67, 68, 56, 54, 1, 4, 68, 70, 58, 56, 1, 4, 70, 61, 48, 58, 1, + 6, 61, 70, 68, 67, 64, 62, 1, 6, 72, 75, 77, 78, 80, 83, 1, 4, 85, 87, 75, + 72, 1, 4, 87, 88, 77, 75, 1, 4, 88, 91, 78, 77, 1, 4, 91, 92, 80, 78, 1, + 4, 92, 95, 83, 80, 1, 4, 95, 85, 72, 83, 1, 6, 85, 95, 92, 91, 88, 87, 1, + 6, 24, 26, 28, 30, 32, 35, 1, 4, 36, 39, 26, 24, 1, 4, 39, 40, 28, 26, 1, + 4, 40, 42, 30, 28, 1, 4, 42, 44, 32, 30, 1, 4, 44, 47, 35, 32, 1, 4, 47, + 36, 24, 35, 1, 6, 36, 47, 44, 42, 40, 39, 1, 6, 1, 2, 4, 6, 8, 11, 1, + 4, 13, 15, 2, 1, 1, 4, 15, 16, 4, 2, 1, 4, 16, 19, 6, 4, 1, 4, 19, + 20, 8, 6, 1, 4, 20, 23, 11, 8, 1, 4, 23, 13, 1, 11, 1, 6, 13, 23, 20, + 19, 16, 15, 1, 6, 240, 243, 244, 247, 249, 250, 1, 4, 252, 255, 243, 240, 1, 4, 255, + 256, 244, 243, 1, 4, 256, 259, 247, 244, 1, 4, 259, 261, 249, 247, 1, 4, 261, 263, 250, + 249, 1, 4, 263, 252, 240, 250, 1, 6, 252, 263, 261, 259, 256, 255, 1, 6, 265, 266, 269, + 270, 272, 274, 1, 4, 276, 278, 266, 265, 1, 4, 278, 280, 269, 266, 1, 4, 280, 282, 270, + 269, 1, 4, 282, 284, 272, 270, 1, 4, 284, 287, 274, 272, 1, 4, 287, 276, 265, 274, 1, + 6, 276, 287, 284, 282, 280, 278, 1, 6, 192, 195, 197, 198, 200, 203, 1, 4, 204, 207, 195, + 192, 1, 4, 207, 209, 197, 195, 1, 4, 209, 211, 198, 197, 1, 4, 211, 212, 200, 198, 1, + 4, 212, 215, 203, 200, 1, 4, 215, 204, 192, 203, 1, 6, 204, 215, 212, 211, 209, 207, 1, + 6, 217, 218, 220, 222, 224, 226, 1, 4, 228, 230, 218, 217, 1, 4, 230, 233, 220, 218, 1, + 4, 233, 234, 222, 220, 1, 4, 234, 237, 224, 222, 1, 4, 237, 238, 226, 224, 1, 4, 238, + 228, 217, 226, 1, 6, 228, 238, 237, 234, 233, 230, 1, 6, 144, 146, 149, 151, 153, 154, 1, + 4, 156, 159, 146, 144, 1, 4, 159, 160, 149, 146, 1, 4, 160, 163, 151, 149, 1, 4, 163, + 164, 153, 151, 1, 4, 164, 166, 154, 153, 1, 4, 166, 156, 144, 154, 1, 6, 156, 166, 164, + 163, 160, 159, 1, 6, 168, 170, 172, 175, 176, 179, 1, 4, 180, 183, 170, 168, 1, 4, 183, + 185, 172, 170, 1, 4, 185, 186, 175, 172, 1, 4, 186, 188, 176, 175, 1, 4, 188, 191, 179, + 176, 1, 4, 191, 180, 168, 179, 1, 6, 180, 191, 188, 186, 185, 183, 1, 6, 97, 99, 100, + 102, 104, 107, 1, 4, 108, 111, 99, 97, 1, 4, 111, 113, 100, 99, 1, 4, 113, 115, 102, + 100, 1, 4, 115, 117, 104, 102, 1, 4, 117, 119, 107, 104, 1, 4, 119, 108, 97, 107, 1, + 6, 108, 119, 117, 115, 113, 111, 1, 6, 121, 123, 124, 127, 129, 130, 1, 4, 132, 135, 123, + 121, 1, 4, 135, 137, 124, 123, 1, 4, 137, 138, 127, 124, 1, 4, 138, 140, 129, 127, 1, + 4, 140, 142, 130, 129, 1, 4, 142, 132, 121, 130, 1, 6, 132, 142, 140, 138, 137, 135, 1, + 6, 49, 51, 52, 55, 57, 59, 1, 4, 60, 63, 51, 49, 1, 4, 63, 65, 52, 51, 1, + 4, 65, 66, 55, 52, 1, 4, 66, 69, 57, 55, 1, 4, 69, 71, 59, 57, 1, 4, 71, + 60, 49, 59, 1, 6, 60, 71, 69, 66, 65, 63, 1, 6, 73, 74, 76, 79, 81, 82, 1, + 4, 84, 86, 74, 73, 1, 4, 86, 89, 76, 74, 1, 4, 89, 90, 79, 76, 1, 4, 90, + 93, 81, 79, 1, 4, 93, 94, 82, 81, 1, 4, 94, 84, 73, 82, 1, 6, 84, 94, 93, + 90, 89, 86, 1, 6, 25, 27, 29, 31, 33, 34, 1, 4, 37, 38, 27, 25, 1, 4, 38, + 41, 29, 27, 1, 4, 41, 43, 31, 29, 1, 4, 43, 45, 33, 31, 1, 4, 45, 46, 34, + 33, 1, 4, 46, 37, 25, 34, 1, 6, 37, 46, 45, 43, 41, 38, 1, 6, 0, 3, 5, + 7, 9, 10, 1, 4, 12, 14, 3, 0, 1, 4, 14, 17, 5, 3, 1, 4, 17, 18, 7, + 5, 1, 4, 18, 21, 9, 7, 1, 4, 21, 22, 10, 9, 1, 4, 22, 12, 0, 10, 1, + 6, 12, 22, 21, 18, 17, 14, 1, + 0 +}; + +struct lwo LWO_ElbowBolts = +{ + 288, /* number of points */ + ElbowBolts_PNTS, ElbowBolts_normals, ElbowBolts_POLS, 0L +}; + +static const GLfloat ElbowCoins_PNTS[] = +{ + 0, -0.52, -0.5, + 0.097545, -0.52, -0.490393, + 0.191342, -0.52, -0.46194, + 0.277785, -0.52, -0.415735, + 0.353553, -0.52, -0.353553, + 0.415735, -0.52, -0.277785, + 0.46194, -0.52, -0.191342, + 0.490393, -0.52, -0.097545, + 0.5, -0.52, 0, + 0.490393, -0.52, 0.097545, + 0.46194, -0.52, 0.191342, + 0.415735, -0.52, 0.277785, + 0.353553, -0.52, 0.353553, + 0.277785, -0.52, 0.415735, + 0.191342, -0.52, 0.46194, + 0.097545, -0.52, 0.490393, + 0, -0.52, 0.5, + -0.097545, -0.52, 0.490393, + -0.191342, -0.52, 0.46194, + -0.277785, -0.52, 0.415735, + -0.353553, -0.52, 0.353553, + -0.415735, -0.52, 0.277785, + -0.46194, -0.52, 0.191342, + -0.490393, -0.52, 0.097545, + -0.5, -0.52, 0, + -0.490393, -0.52, -0.097545, + -0.46194, -0.52, -0.191342, + -0.415735, -0.52, -0.277785, + -0.353553, -0.52, -0.353553, + -0.277785, -0.52, -0.415735, + -0.191342, -0.52, -0.46194, + -0.097545, -0.52, -0.490393, + 0, -0.6, -0.5, + 0.097545, -0.6, -0.490393, + 0.191342, -0.6, -0.46194, + 0.277785, -0.6, -0.415735, + 0.353553, -0.6, -0.353553, + 0.415735, -0.6, -0.277785, + 0.46194, -0.6, -0.191342, + 0.490393, -0.6, -0.097545, + 0.5, -0.6, 0, + 0.490393, -0.6, 0.097545, + 0.46194, -0.6, 0.191342, + 0.415735, -0.6, 0.277785, + 0.353553, -0.6, 0.353553, + 0.277785, -0.6, 0.415735, + 0.191342, -0.6, 0.46194, + 0.097545, -0.6, 0.490393, + 0, -0.6, 0.5, + -0.097545, -0.6, 0.490393, + -0.191342, -0.6, 0.46194, + -0.277785, -0.6, 0.415735, + -0.353553, -0.6, 0.353553, + -0.415735, -0.6, 0.277785, + -0.46194, -0.6, 0.191342, + -0.490393, -0.6, 0.097545, + -0.5, -0.6, 0, + -0.490393, -0.6, -0.097545, + -0.46194, -0.6, -0.191342, + -0.415735, -0.6, -0.277785, + -0.353553, -0.6, -0.353553, + -0.277785, -0.6, -0.415735, + -0.191342, -0.6, -0.46194, + -0.097545, -0.6, -0.490393, + 0, 0.5, -0.52, + 0.097545, 0.490393, -0.52, + 0.191342, 0.46194, -0.52, + 0.277785, 0.415735, -0.52, + 0.353553, 0.353553, -0.52, + 0.415735, 0.277785, -0.52, + 0.46194, 0.191342, -0.52, + 0.490393, 0.097545, -0.52, + 0.5, 0, -0.52, + 0.490393, -0.097545, -0.52, + 0.46194, -0.191342, -0.52, + 0.415735, -0.277785, -0.52, + 0.353553, -0.353553, -0.52, + 0.277785, -0.415735, -0.52, + 0.191342, -0.46194, -0.52, + 0.097545, -0.490393, -0.52, + 0, -0.5, -0.52, + -0.097545, -0.490393, -0.52, + -0.191342, -0.46194, -0.52, + -0.277785, -0.415735, -0.52, + -0.353553, -0.353553, -0.52, + -0.415735, -0.277785, -0.52, + -0.46194, -0.191342, -0.52, + -0.490393, -0.097545, -0.52, + -0.5, 0, -0.52, + -0.490393, 0.097545, -0.52, + -0.46194, 0.191342, -0.52, + -0.415735, 0.277785, -0.52, + -0.353553, 0.353553, -0.52, + -0.277785, 0.415735, -0.52, + -0.191342, 0.46194, -0.52, + -0.097545, 0.490393, -0.52, + 0, 0.5, -0.6, + 0.097545, 0.490393, -0.6, + 0.191342, 0.46194, -0.6, + 0.277785, 0.415735, -0.6, + 0.353553, 0.353553, -0.6, + 0.415735, 0.277785, -0.6, + 0.46194, 0.191342, -0.6, + 0.490393, 0.097545, -0.6, + 0.5, 0, -0.6, + 0.490393, -0.097545, -0.6, + 0.46194, -0.191342, -0.6, + 0.415735, -0.277785, -0.6, + 0.353553, -0.353553, -0.6, + 0.277785, -0.415735, -0.6, + 0.191342, -0.46194, -0.6, + 0.097545, -0.490393, -0.6, + 0, -0.5, -0.6, + -0.097545, -0.490393, -0.6, + -0.191342, -0.46194, -0.6, + -0.277785, -0.415735, -0.6, + -0.353553, -0.353553, -0.6, + -0.415735, -0.277785, -0.6, + -0.46194, -0.191342, -0.6, + -0.490393, -0.097545, -0.6, + -0.5, 0, -0.6, + -0.490393, 0.097545, -0.6, + -0.46194, 0.191342, -0.6, + -0.415735, 0.277785, -0.6, + -0.353553, 0.353553, -0.6, + -0.277785, 0.415735, -0.6, + -0.191342, 0.46194, -0.6, + -0.097545, 0.490393, -0.6, +}; + +static const GLfloat ElbowCoins_normals[] = +{ + 0, 0, 1, + 0.098017, 0.995185, 0, + 0.290285, 0.95694, 0, + 0.471397, 0.881921, 0, + 0.634393, 0.77301, 0, + 0.77301, 0.634393, 0, + 0.881921, 0.471397, 0, + 0.95694, 0.290285, 0, + 0.995185, 0.098017, 0, + 0.995185, -0.098017, 0, + 0.95694, -0.290285, 0, + 0.881921, -0.471397, 0, + 0.77301, -0.634393, 0, + 0.634393, -0.77301, 0, + 0.471397, -0.881921, 0, + 0.290285, -0.95694, 0, + 0.098017, -0.995185, 0, + -0.098017, -0.995185, 0, + -0.290285, -0.95694, 0, + -0.471397, -0.881921, 0, + -0.634393, -0.77301, 0, + -0.77301, -0.634393, 0, + -0.881921, -0.471397, 0, + -0.95694, -0.290285, 0, + -0.995185, -0.098017, 0, + -0.995185, 0.098017, 0, + -0.95694, 0.290285, 0, + -0.881921, 0.471397, 0, + -0.77301, 0.634393, 0, + -0.634393, 0.77301, 0, + -0.471397, 0.881921, 0, + -0.290285, 0.95694, 0, + -0.098017, 0.995185, 0, + 0, 0, -1, + 0, 1, 0, + 0.098017, 0, -0.995185, + 0.290285, 0, -0.95694, + 0.471397, 0, -0.881921, + 0.634393, 0, -0.77301, + 0.77301, 0, -0.634393, + 0.881921, 0, -0.471397, + 0.95694, 0, -0.290285, + 0.995185, 0, -0.098017, + 0.995185, 0, 0.098017, + 0.95694, 0, 0.290285, + 0.881921, 0, 0.471397, + 0.77301, 0, 0.634393, + 0.634393, 0, 0.77301, + 0.471397, 0, 0.881921, + 0.290285, 0, 0.95694, + 0.098017, 0, 0.995185, + -0.098017, 0, 0.995185, + -0.290285, 0, 0.95694, + -0.471397, 0, 0.881921, + -0.634393, 0, 0.77301, + -0.77301, 0, 0.634393, + -0.881921, 0, 0.471397, + -0.95694, 0, 0.290285, + -0.995185, 0, 0.098017, + -0.995185, 0, -0.098017, + -0.95694, 0, -0.290285, + -0.881921, 0, -0.471397, + -0.77301, 0, -0.634393, + -0.634393, 0, -0.77301, + -0.471397, 0, -0.881921, + -0.290285, 0, -0.95694, + -0.098017, 0, -0.995185, + 0, -1, 0, +}; + +static const unsigned short int ElbowCoins_POLS[] = +{ + 32, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, + 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 1, 4, 96, 97, 65, 64, 1, + 4, 97, 98, 66, 65, 1, 4, 98, 99, 67, 66, 1, 4, 99, 100, 68, 67, 1, 4, 100, + 101, 69, 68, 1, 4, 101, 102, 70, 69, 1, 4, 102, 103, 71, 70, 1, 4, 103, 104, 72, +71, 1, 4, 104, 105, 73, 72, 1, 4, 105, 106, 74, 73, 1, 4, 106, 107, 75, 74, 1, + 4, 107, 108, 76, 75, 1, 4, 108, 109, 77, 76, 1, 4, 109, 110, 78, 77, 1, 4, 110, + 111, 79, 78, 1, 4, 111, 112, 80, 79, 1, 4, 112, 113, 81, 80, 1, 4, 113, 114, 82, +81, 1, 4, 114, 115, 83, 82, 1, 4, 115, 116, 84, 83, 1, 4, 116, 117, 85, 84, 1, + 4, 117, 118, 86, 85, 1, 4, 118, 119, 87, 86, 1, 4, 119, 120, 88, 87, 1, 4, 120, + 121, 89, 88, 1, 4, 121, 122, 90, 89, 1, 4, 122, 123, 91, 90, 1, 4, 123, 124, 92, +91, 1, 4, 124, 125, 93, 92, 1, 4, 125, 126, 94, 93, 1, 4, 126, 127, 95, 94, 1, + 4, 127, 96, 64, 95, 1, 32, 96, 127, 126, 125, 124, 123, 122, 121, 120, 119, 118, 117, 116, + 115, 114, 113, 112, 111, 110, 109, 108, 107, 106, 105, 104, 103, 102, 101, 100, 99, 98, 97, 1, + 32, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, + 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 1, 4, 32, 33, 1, 0, 1, + 4, 33, 34, 2, 1, 1, 4, 34, 35, 3, 2, 1, 4, 35, 36, 4, 3, 1, 4, 36, + 37, 5, 4, 1, 4, 37, 38, 6, 5, 1, 4, 38, 39, 7, 6, 1, 4, 39, 40, 8, + 7, 1, 4, 40, 41, 9, 8, 1, 4, 41, 42, 10, 9, 1, 4, 42, 43, 11, 10, 1, + 4, 43, 44, 12, 11, 1, 4, 44, 45, 13, 12, 1, 4, 45, 46, 14, 13, 1, 4, 46, + 47, 15, 14, 1, 4, 47, 48, 16, 15, 1, 4, 48, 49, 17, 16, 1, 4, 49, 50, 18, + 17, 1, 4, 50, 51, 19, 18, 1, 4, 51, 52, 20, 19, 1, 4, 52, 53, 21, 20, 1, + 4, 53, 54, 22, 21, 1, 4, 54, 55, 23, 22, 1, 4, 55, 56, 24, 23, 1, 4, 56, + 57, 25, 24, 1, 4, 57, 58, 26, 25, 1, 4, 58, 59, 27, 26, 1, 4, 59, 60, 28, + 27, 1, 4, 60, 61, 29, 28, 1, 4, 61, 62, 30, 29, 1, 4, 62, 63, 31, 30, 1, + 4, 63, 32, 0, 31, 1, 32, 32, 63, 62, 61, 60, 59, 58, 57, 56, 55, 54, 53, 52, +51, 50, 49, 48, 47, 46, 45, 44, 43, 42, 41, 40, 39, 38, 37, 36, 35, 34, 33, 1, + 0 +}; + +struct lwo LWO_ElbowCoins = +{ + 128, /* number of points */ + ElbowCoins_PNTS, ElbowCoins_normals, ElbowCoins_POLS, 0L +}; + +#endif /* USE_GL */ + +/* End of pipeobjs.c */ diff --git a/hacks/glx/pipes.c b/hacks/glx/pipes.c new file mode 100644 index 00000000..9ca14d24 --- /dev/null +++ b/hacks/glx/pipes.c @@ -0,0 +1,1252 @@ +/* -*- Mode: C; tab-width: 4 -*- */ +/* pipes --- 3D selfbuiding pipe system */ + +#if 0 +static const char sccsid[] = "@(#)pipes.c 4.07 97/11/24 xlockmore"; +#endif + +/*- + * Permission to use, copy, modify, and distribute this software and its + * documentation for any purpose and without fee is hereby granted, + * provided that the above copyright notice appear in all copies and that + * both that copyright notice and this permission notice appear in + * supporting documentation. + * + * This file is provided AS IS with no warranties of any kind. The author + * shall have no liability with respect to the infringement of copyrights, + * trade secrets or any patents by this file or any part thereof. In no + * event will the author be liable for any lost revenue or profits or + * other special, indirect and consequential damages. + * + * This program was inspired on a WindowsNT(R)'s screen saver. It was written + * from scratch and it was not based on any other source code. + * + * ========================================================================== + * The routine myElbow is derivated from the doughnut routine from the MesaGL + * library (more especifically the Mesaaux library) written by Brian Paul. + * ========================================================================== + * + * Thanks goes to Brian Paul for making it possible and inexpensive to use + * OpenGL at home. + * + * Since I'm not a native English speaker, my apologies for any grammatical + * mistake. + * + * My e-mail address is + * m-vianna@usa.net + * Marcelo F. Vianna (Apr-09-1997) + * + * Revision History: + * 24-Jun-12: Eliminate single-buffer dependency. + * 29-Apr-97: Factory equipment by Ed Mackey. Productive day today, eh? + * 29-Apr-97: Less tight turns Jeff Epler + * 29-Apr-97: Efficiency speed-ups by Marcelo F. Vianna + */ + +/* This program was originally written to be single-buffered: it kept + building up new objects in the front buffer by never clearing the + depth or color buffers at the end of each frame. In that way, it + was drawing a very small number of polygons per frame. However, + modern systems make it difficult to live in a single-buffered world + like that. So I changed it to re-generate the scene at every + frame, which makes it vastly less efficient, but also, makes it + work right on modern hardware. It generates the entire system up + front, putting each "frame" of the animation into its own display + list; then it draws successively more of those display lists each + time the redisplay method is called. When it reaches the end, + it regenerates a new system and re-populates the existing display + lists. -- jwz. + */ + +#ifdef STANDALONE +# define DEFAULTS "*delay: 10000 \n" \ + "*count: 2 \n" \ + "*cycles: 5 \n" \ + "*size: 500 \n" \ + "*showFPS: False \n" \ + "*fpsSolid: True \n" \ + "*wireframe: False \n" + +# define refresh_pipes 0 +# include "xlockmore.h" /* from the xscreensaver distribution */ +#else /* !STANDALONE */ +# include "xlock.h" /* from the xlockmore distribution */ +#endif /* !STANDALONE */ + +#ifdef USE_GL + +#ifdef HAVE_COCOA +# include "jwxyz.h" +#else +# include +# include +# include +#endif + +#ifdef HAVE_JWZGLES +# include "jwzgles.h" +#endif /* HAVE_JWZGLES */ + +#include "sphere.h" +#include "buildlwo.h" +#include "teapot.h" +#include "gltrackball.h" + +#define DEF_FACTORY "2" +#define DEF_FISHEYE "True" +#define DEF_TIGHTTURNS "False" +#define DEF_ROTATEPIPES "True" +#define NofSysTypes 3 + +static int factory; +static Bool fisheye, tightturns, rotatepipes; + +static XrmOptionDescRec opts[] = +{ + {"-factory", ".pipes.factory", XrmoptionSepArg, 0}, + {"-fisheye", ".pipes.fisheye", XrmoptionNoArg, "on"}, + {"+fisheye", ".pipes.fisheye", XrmoptionNoArg, "off"}, + {"-tightturns", ".pipes.tightturns", XrmoptionNoArg, "on"}, + {"+tightturns", ".pipes.tightturns", XrmoptionNoArg, "off"}, + {"-rotatepipes", ".pipes.rotatepipes", XrmoptionNoArg, "on"}, + {"+rotatepipes", ".pipes.rotatepipes", XrmoptionNoArg, "off"}, +}; +static argtype vars[] = +{ + {&factory, "factory", "Factory", DEF_FACTORY, t_Int}, + {&fisheye, "fisheye", "Fisheye", DEF_FISHEYE, t_Bool}, + {&tightturns, "tightturns", "Tightturns", DEF_TIGHTTURNS, t_Bool}, + {&rotatepipes, "rotatepipes", "Rotatepipes", DEF_ROTATEPIPES, t_Bool}, +}; +static OptionStruct desc[] = +{ + {"-factory num", "how much extra equipment in pipes (0 for none)"}, + {"-/+fisheye", "turn on/off zoomed-in view of pipes"}, + {"-/+tightturns", "turn on/off tight turns"}, + {"-/+rotatepipes", "turn on/off pipe system rotation per screenful"}, +}; + +ENTRYPOINT ModeSpecOpt pipes_opts = +{sizeof opts / sizeof opts[0], opts, sizeof vars / sizeof vars[0], vars, desc}; + +#ifdef USE_MODULES +ModStruct pipes_description = +{"pipes", "init_pipes", "draw_pipes", "release_pipes", + "draw_pipes", + "change_pipes", NULL, &pipes_opts, + 1000, 2, 5, 500, 4, 1.0, "", + "Shows a selfbuilding pipe system", 0, NULL}; + +#endif + +#define Scale4Window 0.1 + +#define one_third 0.3333333333333333333 + +#define dirNone -1 +#define dirUP 0 +#define dirDOWN 1 +#define dirLEFT 2 +#define dirRIGHT 3 +#define dirNEAR 4 +#define dirFAR 5 + +#define HCELLS 33 +#define VCELLS 25 +#define DEFINEDCOLORS 7 +#define elbowradius 0.5 + +/*************************************************************************/ + +typedef struct { + int flip; + + int Cells[HCELLS][VCELLS][HCELLS]; + int usedcolors[DEFINEDCOLORS]; + int directions[6]; + int ndirections; + int nowdir, olddir; + int system_number; + int counter; + int PX, PY, PZ; + int number_of_systems; + int system_type; + int system_length; + int turncounter; + Window window; + const float *system_color; + GLfloat initial_rotation; + GLuint valve, bolts, betweenbolts, elbowbolts, elbowcoins; + GLuint guagehead, guageface, guagedial, guageconnector, teapot; + int teapot_polys; + GLXContext *glx_context; + + Bool button_down_p; + trackball_state *trackball; + GLuint *dlists, *poly_counts; + int dlist_count, dlist_size; + int system_index, system_size; + + int fadeout; + +} pipesstruct; + +extern struct lwo LWO_BigValve, LWO_PipeBetweenBolts, LWO_Bolts3D; +extern struct lwo LWO_GuageHead, LWO_GuageFace, LWO_GuageDial, LWO_GuageConnector; +extern struct lwo LWO_ElbowBolts, LWO_ElbowCoins; + +static const float front_shininess[] = {60.0}; +static const float front_specular[] = {0.7, 0.7, 0.7, 1.0}; +static const float ambient0[] = {0.4, 0.4, 0.4, 1.0}; +static const float diffuse0[] = {1.0, 1.0, 1.0, 1.0}; +static const float ambient1[] = {0.2, 0.2, 0.2, 1.0}; +static const float diffuse1[] = {0.5, 0.5, 0.5, 1.0}; +static const float position0[] = {1.0, 1.0, 1.0, 0.0}; +static const float position1[] = {-1.0, -1.0, 1.0, 0.0}; +static const float lmodel_ambient[] = {0.5, 0.5, 0.5, 1.0}; +static const float lmodel_twoside[] = {GL_TRUE}; + +static const float MaterialRed[] = {0.7, 0.0, 0.0, 1.0}; +static const float MaterialGreen[] = {0.1, 0.5, 0.2, 1.0}; +static const float MaterialBlue[] = {0.0, 0.0, 0.7, 1.0}; +static const float MaterialCyan[] = {0.2, 0.5, 0.7, 1.0}; +static const float MaterialYellow[] = {0.7, 0.7, 0.0, 1.0}; +static const float MaterialMagenta[] = {0.6, 0.2, 0.5, 1.0}; +static const float MaterialWhite[] = {0.7, 0.7, 0.7, 1.0}; +static const float MaterialGray[] = {0.2, 0.2, 0.2, 1.0}; + +static pipesstruct *pipes = NULL; + + +static void +MakeTube(ModeInfo *mi, int direction) +{ + Bool wire = MI_IS_WIREFRAME(mi); + float an; + float SINan_3, COSan_3; + int facets = (wire ? 5 : 24); + + /*dirUP = 00000000 */ + /*dirDOWN = 00000001 */ + /*dirLEFT = 00000010 */ + /*dirRIGHT = 00000011 */ + /*dirNEAR = 00000100 */ + /*dirFAR = 00000101 */ + + if (!(direction & 4)) { + glRotatef(90.0, (direction & 2) ? 0.0 : 1.0, + (direction & 2) ? 1.0 : 0.0, 0.0); + } + glBegin(wire ? GL_LINE_STRIP : GL_QUAD_STRIP); + for (an = 0.0; an <= 2.0 * M_PI; an += M_PI * 2 / facets) { + glNormal3f((COSan_3 = cos(an) / 3.0), (SINan_3 = sin(an) / 3.0), 0.0); + glVertex3f(COSan_3, SINan_3, one_third); + glVertex3f(COSan_3, SINan_3, -one_third); + mi->polygon_count++; + } + glEnd(); +} + +static void +mySphere(float radius, Bool wire) +{ +#if 0 + GLUquadricObj *quadObj; + + quadObj = gluNewQuadric(); + gluQuadricDrawStyle(quadObj, (GLenum) GLU_FILL); + gluSphere(quadObj, radius, 16, 16); + gluDeleteQuadric(quadObj); +#else + glPushMatrix(); + glScalef (radius, radius, radius); + glRotatef (90, 1, 0, 0); + unit_sphere (16, 16, wire); + glPopMatrix(); +#endif +} + +static void +myElbow(ModeInfo * mi, int bolted) +{ + pipesstruct *pp = &pipes[MI_SCREEN(mi)]; + Bool wire = MI_IS_WIREFRAME(mi); + + int nsides = (wire ? 6 : 25); + int rings = nsides; +#define r one_third +#define R one_third + + int i, j; + GLfloat p0[3], p1[3], p2[3], p3[3]; + GLfloat n0[3], n1[3], n2[3], n3[3]; + GLfloat COSphi, COSphi1, COStheta, COStheta1; + GLfloat _SINtheta, _SINtheta1; + + for (i = 0; i <= rings / 4; i++) { + GLfloat theta, theta1; + + theta = (GLfloat) i *2.0 * M_PI / rings; + + theta1 = (GLfloat) (i + 1) * 2.0 * M_PI / rings; + for (j = 0; j < nsides; j++) { + GLfloat phi, phi1; + + phi = (GLfloat) j *2.0 * M_PI / nsides; + + phi1 = (GLfloat) (j + 1) * 2.0 * M_PI / nsides; + + p0[0] = (COStheta = cos(theta)) * (R + r * (COSphi = cos(phi))); + p0[1] = (_SINtheta = -sin(theta)) * (R + r * COSphi); + + p1[0] = (COStheta1 = cos(theta1)) * (R + r * COSphi); + p1[1] = (_SINtheta1 = -sin(theta1)) * (R + r * COSphi); + + p2[0] = COStheta1 * (R + r * (COSphi1 = cos(phi1))); + p2[1] = _SINtheta1 * (R + r * COSphi1); + + p3[0] = COStheta * (R + r * COSphi1); + p3[1] = _SINtheta * (R + r * COSphi1); + + n0[0] = COStheta * COSphi; + n0[1] = _SINtheta * COSphi; + + n1[0] = COStheta1 * COSphi; + n1[1] = _SINtheta1 * COSphi; + + n2[0] = COStheta1 * COSphi1; + n2[1] = _SINtheta1 * COSphi1; + + n3[0] = COStheta * COSphi1; + n3[1] = _SINtheta * COSphi1; + + p0[2] = p1[2] = r * (n0[2] = n1[2] = sin(phi)); + p2[2] = p3[2] = r * (n2[2] = n3[2] = sin(phi1)); + + glBegin(wire ? GL_LINE_LOOP : GL_QUADS); + glNormal3fv(n3); + glVertex3fv(p3); + glNormal3fv(n2); + glVertex3fv(p2); + glNormal3fv(n1); + glVertex3fv(p1); + glNormal3fv(n0); + glVertex3fv(p0); + mi->polygon_count++; + glEnd(); + } + } + + if (factory > 0 && bolted) { + /* Bolt the elbow onto the pipe system */ + glFrontFace(GL_CW); + glPushMatrix(); + glRotatef(90.0, 0.0, 0.0, -1.0); + glRotatef(90.0, 0.0, 1.0, 0.0); + glTranslatef(0.0, one_third, one_third); + glCallList(pp->elbowcoins); + mi->polygon_count += LWO_ElbowCoins.num_pnts/3; + glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, MaterialGray); + glCallList(pp->elbowbolts); + mi->polygon_count += LWO_ElbowBolts.num_pnts/3; + glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, pp->system_color); + glPopMatrix(); + glFrontFace(GL_CCW); + } +#undef r +#undef R +#undef nsides +#undef rings +} + +static void +FindNeighbors(ModeInfo * mi) +{ + pipesstruct *pp = &pipes[MI_SCREEN(mi)]; + + pp->ndirections = 0; + pp->directions[dirUP] = (!pp->Cells[pp->PX][pp->PY + 1][pp->PZ]) ? 1 : 0; + pp->ndirections += pp->directions[dirUP]; + pp->directions[dirDOWN] = (!pp->Cells[pp->PX][pp->PY - 1][pp->PZ]) ? 1 : 0; + pp->ndirections += pp->directions[dirDOWN]; + pp->directions[dirLEFT] = (!pp->Cells[pp->PX - 1][pp->PY][pp->PZ]) ? 1 : 0; + pp->ndirections += pp->directions[dirLEFT]; + pp->directions[dirRIGHT] = (!pp->Cells[pp->PX + 1][pp->PY][pp->PZ]) ? 1 : 0; + pp->ndirections += pp->directions[dirRIGHT]; + pp->directions[dirFAR] = (!pp->Cells[pp->PX][pp->PY][pp->PZ - 1]) ? 1 : 0; + pp->ndirections += pp->directions[dirFAR]; + pp->directions[dirNEAR] = (!pp->Cells[pp->PX][pp->PY][pp->PZ + 1]) ? 1 : 0; + pp->ndirections += pp->directions[dirNEAR]; +} + +static int +SelectNeighbor(ModeInfo * mi) +{ + pipesstruct *pp = &pipes[MI_SCREEN(mi)]; + int dirlist[6]; + int i, j; + + for (i = 0, j = 0; i < 6; i++) { + if (pp->directions[i]) { + dirlist[j] = i; + j++; + } + } + + return dirlist[NRAND(pp->ndirections)]; +} + +static void +MakeValve(ModeInfo * mi, int newdir) +{ + pipesstruct *pp = &pipes[MI_SCREEN(mi)]; + + /* There is a glPopMatrix() right after this subroutine returns. */ + switch (newdir) { + case dirUP: + case dirDOWN: + glRotatef(90.0, 1.0, 0.0, 0.0); + glRotatef(NRAND(3) * 90.0, 0.0, 0.0, 1.0); + break; + case dirLEFT: + case dirRIGHT: + glRotatef(90.0, 0.0, -1.0, 0.0); + glRotatef((NRAND(3) * 90.0) - 90.0, 0.0, 0.0, 1.0); + break; + case dirNEAR: + case dirFAR: + glRotatef(NRAND(4) * 90.0, 0.0, 0.0, 1.0); + break; + } + glFrontFace(GL_CW); + glCallList(pp->betweenbolts); + mi->polygon_count += LWO_PipeBetweenBolts.num_pnts/3; + glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, MaterialGray); + glCallList(pp->bolts); + mi->polygon_count += LWO_Bolts3D.num_pnts/3; + if (!MI_IS_MONO(mi)) { + if (pp->system_color == MaterialRed) { + glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, NRAND(2) ? MaterialYellow : MaterialBlue); + } else if (pp->system_color == MaterialBlue) { + glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, NRAND(2) ? MaterialRed : MaterialYellow); + } else if (pp->system_color == MaterialYellow) { + glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, NRAND(2) ? MaterialBlue : MaterialRed); + } else { + switch ((NRAND(3))) { + case 0: + glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, MaterialRed); + break; + case 1: + glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, MaterialBlue); + break; + case 2: + glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, MaterialYellow); + } + } + } + glRotatef((GLfloat) (NRAND(90)), 1.0, 0.0, 0.0); + glCallList(pp->valve); + mi->polygon_count += LWO_BigValve.num_pnts/3; + glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, pp->system_color); + glFrontFace(GL_CCW); +} + +static int +MakeGuage(ModeInfo * mi, int newdir) +{ + pipesstruct *pp = &pipes[MI_SCREEN(mi)]; + + /* Can't have a guage on a vertical pipe. */ + if ((newdir == dirUP) || (newdir == dirDOWN)) + return (0); + + /* Is there space above this pipe for a guage? */ + if (!pp->directions[dirUP]) + return (0); + + /* Yes! Mark the space as used. */ + pp->Cells[pp->PX][pp->PY + 1][pp->PZ] = 1; + + glFrontFace(GL_CW); + glPushMatrix(); + if ((newdir == dirLEFT) || (newdir == dirRIGHT)) + glRotatef(90.0, 0.0, 1.0, 0.0); + glCallList(pp->betweenbolts); + mi->polygon_count += LWO_PipeBetweenBolts.num_pnts/3; + glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, MaterialGray); + glCallList(pp->bolts); + mi->polygon_count += LWO_Bolts3D.num_pnts/3; + glPopMatrix(); + + glCallList(pp->guageconnector); + mi->polygon_count += LWO_GuageConnector.num_pnts/3; + glPushMatrix(); + glTranslatef(0.0, 1.33333, 0.0); + /* Do not change the above to 1 + ONE_THIRD, because */ + /* the object really is centered on 1.3333300000. */ + glRotatef(NRAND(270) + 45.0, 0.0, 0.0, -1.0); + /* Random rotation for the dial. I love it. */ + glCallList(pp->guagedial); + mi->polygon_count += LWO_GuageDial.num_pnts/3; + glPopMatrix(); + + glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, pp->system_color); + glCallList(pp->guagehead); + mi->polygon_count += LWO_GuageHead.num_pnts/3; + + /* GuageFace is drawn last, in case of low-res depth buffers. */ + glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, MaterialWhite); + glCallList(pp->guageface); + mi->polygon_count += LWO_GuageFace.num_pnts/3; + + glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, pp->system_color); + glFrontFace(GL_CCW); + + return (1); +} + + +static GLuint +build_teapot(ModeInfo *mi) +{ + pipesstruct *pp = &pipes[MI_SCREEN(mi)]; + GLuint list = glGenLists(1); + if (!list) return 0; + glNewList(list, GL_COMPILE); + pp->teapot_polys = unit_teapot (12, MI_IS_WIREFRAME(mi)); + glEndList(); + return list; +} + + +static void +MakeTeapot(ModeInfo * mi, int newdir) +{ + pipesstruct *pp = &pipes[MI_SCREEN(mi)]; + + switch (newdir) { + case dirUP: + case dirDOWN: + glRotatef(90.0, 1.0, 0.0, 0.0); + glRotatef(NRAND(3) * 90.0, 0.0, 0.0, 1.0); + break; + case dirLEFT: + case dirRIGHT: + glRotatef(90.0, 0.0, -1.0, 0.0); + glRotatef((NRAND(3) * 90.0) - 90.0, 0.0, 0.0, 1.0); + break; + case dirNEAR: + case dirFAR: + glRotatef(NRAND(4) * 90.0, 0.0, 0.0, 1.0); + break; + } + + glCallList(pp->teapot); + mi->polygon_count += pp->teapot_polys; + glFrontFace(GL_CCW); +} + + +static void +MakeShape(ModeInfo * mi, int newdir) +{ + int n = NRAND(100); + if (n < 50) { + if (!MakeGuage(mi, newdir)) + MakeTube(mi, newdir); + } else if (n < 98) { + MakeValve(mi, newdir); + } else { + MakeTeapot(mi,newdir); + } +} + +static void +pinit(ModeInfo * mi, int zera) +{ + pipesstruct *pp = &pipes[MI_SCREEN(mi)]; + int X, Y, Z; + + if (zera) { + pp->system_number = 1; + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + (void) memset(pp->Cells, 0, sizeof (pp->Cells)); + for (X = 0; X < HCELLS; X++) { + for (Y = 0; Y < VCELLS; Y++) { + pp->Cells[X][Y][0] = 1; + pp->Cells[X][Y][HCELLS - 1] = 1; + pp->Cells[0][Y][X] = 1; + pp->Cells[HCELLS - 1][Y][X] = 1; + } + } + for (X = 0; X < HCELLS; X++) { + for (Z = 0; Z < HCELLS; Z++) { + pp->Cells[X][0][Z] = 1; + pp->Cells[X][VCELLS - 1][Z] = 1; + } + } + (void) memset(pp->usedcolors, 0, sizeof (pp->usedcolors)); + } + pp->counter = 0; + pp->turncounter = 0; + + if (!MI_IS_MONO(mi)) { + int collist[DEFINEDCOLORS]; + int i, j, lower = 1000; + + /* Avoid repeating colors on the same screen unless necessary */ + for (i = 0; i < DEFINEDCOLORS; i++) { + if (lower > pp->usedcolors[i]) + lower = pp->usedcolors[i]; + } + for (i = 0, j = 0; i < DEFINEDCOLORS; i++) { + if (pp->usedcolors[i] == lower) { + collist[j] = i; + j++; + } + } + i = collist[NRAND(j)]; + pp->usedcolors[i]++; + switch (i) { + case 0: + pp->system_color = MaterialRed; + break; + case 1: + pp->system_color = MaterialGreen; + break; + case 2: + pp->system_color = MaterialBlue; + break; + case 3: + pp->system_color = MaterialCyan; + break; + case 4: + pp->system_color = MaterialYellow; + break; + case 5: + pp->system_color = MaterialMagenta; + break; + case 6: + pp->system_color = MaterialWhite; + break; + } + } else { + pp->system_color = MaterialGray; + } + + do { + pp->PX = NRAND((HCELLS - 1)) + 1; + pp->PY = NRAND((VCELLS - 1)) + 1; + pp->PZ = NRAND((HCELLS - 1)) + 1; + } while (pp->Cells[pp->PX][pp->PY][pp->PZ] || + (pp->Cells[pp->PX + 1][pp->PY][pp->PZ] && pp->Cells[pp->PX - 1][pp->PY][pp->PZ] && + pp->Cells[pp->PX][pp->PY + 1][pp->PZ] && pp->Cells[pp->PX][pp->PY - 1][pp->PZ] && + pp->Cells[pp->PX][pp->PY][pp->PZ + 1] && pp->Cells[pp->PX][pp->PY][pp->PZ - 1])); + pp->Cells[pp->PX][pp->PY][pp->PZ] = 1; + pp->olddir = dirNone; + + FindNeighbors(mi); + + pp->nowdir = SelectNeighbor(mi); +} + + +ENTRYPOINT void +reshape_pipes(ModeInfo * mi, int width, int height) +{ + glViewport(0, 0, width, (GLint) height); + glMatrixMode(GL_PROJECTION); + glLoadIdentity(); + /*glFrustum(-1.0, 1.0, -1.0, 1.0, 5.0, 15.0); */ + gluPerspective(65.0, (GLfloat) width / (GLfloat) height, 0.1, 20.0); + glMatrixMode(GL_MODELVIEW); + + glClear(GL_COLOR_BUFFER_BIT); +} + +ENTRYPOINT Bool +pipes_handle_event (ModeInfo *mi, XEvent *event) +{ + pipesstruct *pp = &pipes[MI_SCREEN(mi)]; + + if (event->xany.type == ButtonPress && + event->xbutton.button == Button1) + { + pp->button_down_p = True; + gltrackball_start (pp->trackball, + event->xbutton.x, event->xbutton.y, + MI_WIDTH (mi), MI_HEIGHT (mi)); + return True; + } + else if (event->xany.type == ButtonRelease && + event->xbutton.button == Button1) + { + pp->button_down_p = False; + return True; + } + else if (event->xany.type == ButtonPress && + (event->xbutton.button == Button4 || + event->xbutton.button == Button5 || + event->xbutton.button == Button6 || + event->xbutton.button == Button7)) + { + gltrackball_mousewheel (pp->trackball, event->xbutton.button, 10, + !!event->xbutton.state); + return True; + } + else if (event->xany.type == MotionNotify && + pp->button_down_p) + { + gltrackball_track (pp->trackball, + event->xmotion.x, event->xmotion.y, + MI_WIDTH (mi), MI_HEIGHT (mi)); + return True; + } + + return False; +} + + + +static void generate_system (ModeInfo *); + + +ENTRYPOINT void +init_pipes (ModeInfo * mi) +{ + int screen = MI_SCREEN(mi); + pipesstruct *pp; + + if (pipes == NULL) { + if ((pipes = (pipesstruct *) calloc(MI_NUM_SCREENS(mi), + sizeof (pipesstruct))) == NULL) + return; + } + pp = &pipes[screen]; + + pp->window = MI_WINDOW(mi); + if ((pp->glx_context = init_GL(mi)) != NULL) { + + reshape_pipes(mi, MI_WIDTH(mi), MI_HEIGHT(mi)); + if (rotatepipes) + pp->initial_rotation = NRAND(180); /* jwz */ + else + pp->initial_rotation = -10.0; + pinit(mi, 1); + + if (factory > 0) { + pp->valve = BuildLWO(MI_IS_WIREFRAME(mi), &LWO_BigValve); + pp->bolts = BuildLWO(MI_IS_WIREFRAME(mi), &LWO_Bolts3D); + pp->betweenbolts = BuildLWO(MI_IS_WIREFRAME(mi), &LWO_PipeBetweenBolts); + + pp->elbowbolts = BuildLWO(MI_IS_WIREFRAME(mi), &LWO_ElbowBolts); + pp->elbowcoins = BuildLWO(MI_IS_WIREFRAME(mi), &LWO_ElbowCoins); + + pp->guagehead = BuildLWO(MI_IS_WIREFRAME(mi), &LWO_GuageHead); + pp->guageface = BuildLWO(MI_IS_WIREFRAME(mi), &LWO_GuageFace); + pp->guagedial = BuildLWO(MI_IS_WIREFRAME(mi), &LWO_GuageDial); + pp->guageconnector = BuildLWO(MI_IS_WIREFRAME(mi), &LWO_GuageConnector); + pp->teapot = build_teapot(mi); + } + /* else they are all 0, thanks to calloc(). */ + + if (MI_COUNT(mi) < 1 || MI_COUNT(mi) > NofSysTypes + 1) { + pp->system_type = NRAND(NofSysTypes) + 1; + } else { + pp->system_type = MI_COUNT(mi); + } + + if (MI_CYCLES(mi) > 0 && MI_CYCLES(mi) < 11) { + pp->number_of_systems = MI_CYCLES(mi); + } else { + pp->number_of_systems = 5; + } + + if (MI_SIZE(mi) < 10) { + pp->system_length = 10; + } else if (MI_SIZE(mi) > 1000) { + pp->system_length = 1000; + } else { + pp->system_length = MI_SIZE(mi); + } + } else { + MI_CLEARWINDOW(mi); + } + + pp->trackball = gltrackball_init (); + generate_system (mi); +} + + +static GLuint +get_dlist (ModeInfo *mi, int i) +{ + pipesstruct *pp = &pipes[MI_SCREEN(mi)]; + if (i >= pp->dlist_count) + { + pp->dlist_count++; + if (pp->dlist_count >= pp->dlist_size) + { + int s2 = (pp->dlist_size + 100) * 1.2; + pp->dlists = (GLuint *) + realloc (pp->dlists, s2 * sizeof(*pp->dlists)); + if (! pp->dlists) abort(); + pp->poly_counts = (GLuint *) + realloc (pp->poly_counts, s2 * sizeof(*pp->poly_counts)); + if (! pp->poly_counts) abort(); + pp->dlist_size = s2; + } + pp->dlists [i] = glGenLists (1); + pp->poly_counts [i] = 0; + } + return pp->dlists[i]; +} + + + +static void +generate_system (ModeInfo * mi) +{ + pipesstruct *pp = &pipes[MI_SCREEN(mi)]; + Bool wire = MI_IS_WIREFRAME(mi); + + int newdir; + int OPX, OPY, OPZ; + + Bool reset_p = False; + + pp->system_index = 0; + pp->system_size = 0; + pinit (mi, 1); + + while (1) { + glNewList (get_dlist (mi, pp->system_size++), GL_COMPILE); + mi->polygon_count = 0; + + glPushMatrix(); + + FindNeighbors(mi); + + if (wire) + glColor4fv (pp->system_color); + else + glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, pp->system_color); + + /* If it's the begining of a system, draw a sphere */ + if (pp->olddir == dirNone) { + glPushMatrix(); + glTranslatef((pp->PX - 16) / 3.0 * 4.0, (pp->PY - 12) / 3.0 * 4.0, (pp->PZ - 16) / 3.0 * 4.0); + mySphere(0.6, wire); + glPopMatrix(); + } + /* Check for stop conditions */ + if (pp->ndirections == 0 || pp->counter > pp->system_length) { + glPushMatrix(); + glTranslatef((pp->PX - 16) / 3.0 * 4.0, (pp->PY - 12) / 3.0 * 4.0, (pp->PZ - 16) / 3.0 * 4.0); + /* Finish the system with another sphere */ + mySphere(0.6, wire); + + glPopMatrix(); + + /* If the maximum number of system was drawn, restart (clearing the screen), */ + /* else start a new system. */ + if (++pp->system_number > pp->number_of_systems) { + reset_p = True; + } else { + pinit(mi, 0); + } + + goto NEXT; + } + pp->counter++; + pp->turncounter++; + + /* Do will the direction change? if so, determine the new one */ + newdir = pp->nowdir; + if (!pp->directions[newdir]) { /* cannot proceed in the current direction */ + newdir = SelectNeighbor(mi); + } else { + if (tightturns) { + /* random change (20% chance) */ + if ((pp->counter > 1) && (NRAND(100) < 20)) { + newdir = SelectNeighbor(mi); + } + } else { + /* Chance to turn increases after each length of pipe drawn */ + if ((pp->counter > 1) && NRAND(50) < NRAND(pp->turncounter + 1)) { + newdir = SelectNeighbor(mi); + pp->turncounter = 0; + } + } + } + + /* Has the direction changed? */ + if (newdir == pp->nowdir) { + /* If not, draw the cell's center pipe */ + glPushMatrix(); + glTranslatef((pp->PX - 16) / 3.0 * 4.0, (pp->PY - 12) / 3.0 * 4.0, (pp->PZ - 16) / 3.0 * 4.0); + /* Chance of factory shape here, if enabled. */ + if ((pp->counter > 1) && (NRAND(100) < factory)) { + MakeShape(mi, newdir); + } else { + MakeTube(mi, newdir); + } + glPopMatrix(); + } else { + /* If so, draw the cell's center elbow/sphere */ + int sysT = pp->system_type; + + if (sysT == NofSysTypes + 1) { + sysT = ((pp->system_number - 1) % NofSysTypes) + 1; + } + glPushMatrix(); + + switch (sysT) { + case 1: + glTranslatef((pp->PX - 16) / 3.0 * 4.0, (pp->PY - 12) / 3.0 * 4.0, (pp->PZ - 16) / 3.0 * 4.0); + mySphere(elbowradius, wire); + break; + case 2: + case 3: + switch (pp->nowdir) { + case dirUP: + switch (newdir) { + case dirLEFT: + glTranslatef((pp->PX - 16) / 3.0 * 4.0 - (one_third), (pp->PY - 12) / 3.0 * 4.0 - (one_third), (pp->PZ - 16) / 3.0 * 4.0); + glRotatef(180.0, 1.0, 0.0, 0.0); + break; + case dirRIGHT: + glTranslatef((pp->PX - 16) / 3.0 * 4.0 + (one_third), (pp->PY - 12) / 3.0 * 4.0 - (one_third), (pp->PZ - 16) / 3.0 * 4.0); + glRotatef(180.0, 1.0, 0.0, 0.0); + glRotatef(180.0, 0.0, 1.0, 0.0); + break; + case dirFAR: + glTranslatef((pp->PX - 16) / 3.0 * 4.0, (pp->PY - 12) / 3.0 * 4.0 - (one_third), (pp->PZ - 16) / 3.0 * 4.0 - (one_third)); + glRotatef(90.0, 0.0, 1.0, 0.0); + glRotatef(180.0, 0.0, 0.0, 1.0); + break; + case dirNEAR: + glTranslatef((pp->PX - 16) / 3.0 * 4.0, (pp->PY - 12) / 3.0 * 4.0 - (one_third), (pp->PZ - 16) / 3.0 * 4.0 + (one_third)); + glRotatef(90.0, 0.0, 1.0, 0.0); + glRotatef(180.0, 1.0, 0.0, 0.0); + break; + } + break; + case dirDOWN: + switch (newdir) { + case dirLEFT: + glTranslatef((pp->PX - 16) / 3.0 * 4.0 - (one_third), (pp->PY - 12) / 3.0 * 4.0 + (one_third), (pp->PZ - 16) / 3.0 * 4.0); + break; + case dirRIGHT: + glTranslatef((pp->PX - 16) / 3.0 * 4.0 + (one_third), (pp->PY - 12) / 3.0 * 4.0 + (one_third), (pp->PZ - 16) / 3.0 * 4.0); + glRotatef(180.0, 0.0, 1.0, 0.0); + break; + case dirFAR: + glTranslatef((pp->PX - 16) / 3.0 * 4.0, (pp->PY - 12) / 3.0 * 4.0 + (one_third), (pp->PZ - 16) / 3.0 * 4.0 - (one_third)); + glRotatef(270.0, 0.0, 1.0, 0.0); + break; + case dirNEAR: + glTranslatef((pp->PX - 16) / 3.0 * 4.0, (pp->PY - 12) / 3.0 * 4.0 + (one_third), (pp->PZ - 16) / 3.0 * 4.0 + (one_third)); + glRotatef(90.0, 0.0, 1.0, 0.0); + break; + } + break; + case dirLEFT: + switch (newdir) { + case dirUP: + glTranslatef((pp->PX - 16) / 3.0 * 4.0 + (one_third), (pp->PY - 12) / 3.0 * 4.0 + (one_third), (pp->PZ - 16) / 3.0 * 4.0); + glRotatef(180.0, 0.0, 1.0, 0.0); + break; + case dirDOWN: + glTranslatef((pp->PX - 16) / 3.0 * 4.0 + (one_third), (pp->PY - 12) / 3.0 * 4.0 - (one_third), (pp->PZ - 16) / 3.0 * 4.0); + glRotatef(180.0, 1.0, 0.0, 0.0); + glRotatef(180.0, 0.0, 1.0, 0.0); + break; + case dirFAR: + glTranslatef((pp->PX - 16) / 3.0 * 4.0 + (one_third), (pp->PY - 12) / 3.0 * 4.0, (pp->PZ - 16) / 3.0 * 4.0 - (one_third)); + glRotatef(270.0, 1.0, 0.0, 0.0); + glRotatef(180.0, 0.0, 1.0, 0.0); + break; + case dirNEAR: + glTranslatef((pp->PX - 16) / 3.0 * 4.0 + (one_third), (pp->PY - 12) / 3.0 * 4.0, (pp->PZ - 16) / 3.0 * 4.0 + (one_third)); + glRotatef(270.0, 1.0, 0.0, 0.0); + glRotatef(180.0, 0.0, 0.0, 1.0); + break; + } + break; + case dirRIGHT: + switch (newdir) { + case dirUP: + glTranslatef((pp->PX - 16) / 3.0 * 4.0 - (one_third), (pp->PY - 12) / 3.0 * 4.0 + (one_third), (pp->PZ - 16) / 3.0 * 4.0); + break; + case dirDOWN: + glTranslatef((pp->PX - 16) / 3.0 * 4.0 - (one_third), (pp->PY - 12) / 3.0 * 4.0 - (one_third), (pp->PZ - 16) / 3.0 * 4.0); + glRotatef(180.0, 1.0, 0.0, 0.0); + break; + case dirFAR: + glTranslatef((pp->PX - 16) / 3.0 * 4.0 - (one_third), (pp->PY - 12) / 3.0 * 4.0, (pp->PZ - 16) / 3.0 * 4.0 - (one_third)); + glRotatef(270.0, 1.0, 0.0, 0.0); + break; + case dirNEAR: + glTranslatef((pp->PX - 16) / 3.0 * 4.0 - (one_third), (pp->PY - 12) / 3.0 * 4.0, (pp->PZ - 16) / 3.0 * 4.0 + (one_third)); + glRotatef(90.0, 1.0, 0.0, 0.0); + break; + } + break; + case dirNEAR: + switch (newdir) { + case dirLEFT: + glTranslatef((pp->PX - 16) / 3.0 * 4.0 - (one_third), (pp->PY - 12) / 3.0 * 4.0, (pp->PZ - 16) / 3.0 * 4.0 - (one_third)); + glRotatef(270.0, 1.0, 0.0, 0.0); + break; + case dirRIGHT: + glTranslatef((pp->PX - 16) / 3.0 * 4.0 + (one_third), (pp->PY - 12) / 3.0 * 4.0, (pp->PZ - 16) / 3.0 * 4.0 - (one_third)); + glRotatef(270.0, 1.0, 0.0, 0.0); + glRotatef(180.0, 0.0, 1.0, 0.0); + break; + case dirUP: + glTranslatef((pp->PX - 16) / 3.0 * 4.0, (pp->PY - 12) / 3.0 * 4.0 + (one_third), (pp->PZ - 16) / 3.0 * 4.0 - (one_third)); + glRotatef(270.0, 0.0, 1.0, 0.0); + break; + case dirDOWN: + glTranslatef((pp->PX - 16) / 3.0 * 4.0, (pp->PY - 12) / 3.0 * 4.0 - (one_third), (pp->PZ - 16) / 3.0 * 4.0 - (one_third)); + glRotatef(90.0, 0.0, 1.0, 0.0); + glRotatef(180.0, 0.0, 0.0, 1.0); + break; + } + break; + case dirFAR: + switch (newdir) { + case dirUP: + glTranslatef((pp->PX - 16) / 3.0 * 4.0, (pp->PY - 12) / 3.0 * 4.0 + (one_third), (pp->PZ - 16) / 3.0 * 4.0 + (one_third)); + glRotatef(90.0, 0.0, 1.0, 0.0); + break; + case dirDOWN: + glTranslatef((pp->PX - 16) / 3.0 * 4.0, (pp->PY - 12) / 3.0 * 4.0 - (one_third), (pp->PZ - 16) / 3.0 * 4.0 + (one_third)); + glRotatef(90.0, 0.0, 1.0, 0.0); + glRotatef(180.0, 1.0, 0.0, 0.0); + break; + case dirLEFT: + glTranslatef((pp->PX - 16) / 3.0 * 4.0 - (one_third), (pp->PY - 12) / 3.0 * 4.0, (pp->PZ - 16) / 3.0 * 4.0 + (one_third)); + glRotatef(90.0, 1.0, 0.0, 0.0); + break; + case dirRIGHT: + glTranslatef((pp->PX - 16) / 3.0 * 4.0 + (one_third), (pp->PY - 12) / 3.0 * 4.0, (pp->PZ - 16) / 3.0 * 4.0 + (one_third)); + glRotatef(270.0, 1.0, 0.0, 0.0); + glRotatef(180.0, 0.0, 0.0, 1.0); + break; + } + break; + } + myElbow(mi, (sysT == 2)); + break; + } + glPopMatrix(); + } + + OPX = pp->PX; + OPY = pp->PY; + OPZ = pp->PZ; + pp->olddir = pp->nowdir; + pp->nowdir = newdir; + switch (pp->nowdir) { + case dirUP: + pp->PY++; + break; + case dirDOWN: + pp->PY--; + break; + case dirLEFT: + pp->PX--; + break; + case dirRIGHT: + pp->PX++; + break; + case dirNEAR: + pp->PZ++; + break; + case dirFAR: + pp->PZ--; + break; + } + pp->Cells[pp->PX][pp->PY][pp->PZ] = 1; + + /* Cells'face pipe */ + glTranslatef(((pp->PX + OPX) / 2.0 - 16) / 3.0 * 4.0, ((pp->PY + OPY) / 2.0 - 12) / 3.0 * 4.0, ((pp->PZ + OPZ) / 2.0 - 16) / 3.0 * 4.0); + MakeTube(mi, newdir); + + NEXT: + glPopMatrix(); + glEndList(); + pp->poly_counts [pp->system_size-1] = mi->polygon_count; + + if (reset_p) + break; + } +} + + +ENTRYPOINT void +draw_pipes (ModeInfo * mi) +{ + pipesstruct *pp = &pipes[MI_SCREEN(mi)]; + Display *display = MI_DISPLAY(mi); + Window window = MI_WINDOW(mi); + Bool wire = MI_IS_WIREFRAME(mi); + int i = 0; + + if (!pp->glx_context) + return; + + glXMakeCurrent(MI_DISPLAY(mi), MI_WINDOW(mi), *(pp->glx_context)); + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + + glColor3f(1.0, 1.0, 1.0); + + glLightfv(GL_LIGHT0, GL_AMBIENT, ambient0); + glLightfv(GL_LIGHT0, GL_DIFFUSE, diffuse0); + glLightfv(GL_LIGHT0, GL_POSITION, position0); + glLightfv(GL_LIGHT1, GL_AMBIENT, ambient1); + glLightfv(GL_LIGHT1, GL_DIFFUSE, diffuse1); + glLightfv(GL_LIGHT1, GL_POSITION, position1); + glLightModelfv(GL_LIGHT_MODEL_AMBIENT, lmodel_ambient); + glLightModelfv(GL_LIGHT_MODEL_TWO_SIDE, lmodel_twoside); + + if (wire) + glDisable(GL_LIGHTING); + else + { + glEnable(GL_LIGHTING); + glEnable(GL_LIGHT0); + /* This looks crappy. */ + /* glEnable(GL_LIGHT1); */ + glEnable(GL_DEPTH_TEST); + glEnable(GL_NORMALIZE); + glEnable(GL_CULL_FACE); + } + + glShadeModel(GL_SMOOTH); + glMaterialfv(GL_FRONT_AND_BACK, GL_SHININESS, front_shininess); + glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, front_specular); + + glPushMatrix(); + + pp->initial_rotation += 0.02; + + glTranslatef(0.0, 0.0, fisheye ? -3.8 : -4.8); + + /* Do it twice because we don't track the device's orientation. */ + glRotatef( current_device_rotation(), 0, 0, 1); + gltrackball_rotate (pp->trackball); + glRotatef(-current_device_rotation(), 0, 0, 1); + + if (rotatepipes) + glRotatef(pp->initial_rotation, 0.0, 1.0, 0.0); + + glScalef(Scale4Window, Scale4Window, Scale4Window); + + mi->polygon_count = 0; + + if (pp->fadeout) + { + GLfloat s = (pp->fadeout * pp->fadeout) / 10000.0; + glScalef (s, s, s); + glRotatef (90 * (1 - (pp->fadeout/100.0)), 1, 0, 0.1); + pp->fadeout -= 4; + if (pp->fadeout <= 0) + { + pp->fadeout = 0; + generate_system (mi); + } + } + else if (pp->system_index < pp->system_size) + pp->system_index++; + else + pp->fadeout = 100; + + for (i = 0; i < pp->system_index; i++) + { + glCallList (pp->dlists[i]); + mi->polygon_count += pp->poly_counts[i]; + } + + glPopMatrix(); + + if (mi->fps_p) do_fps (mi); + glFinish(); + + glXSwapBuffers(display, window); +} + + +#ifndef STANDALONE +ENTRYPOINT void +change_pipes (ModeInfo * mi) +{ + pipesstruct *pp = &pipes[MI_SCREEN(mi)]; + + if (!pp->glx_context) + return; + + glXMakeCurrent(MI_DISPLAY(mi), MI_WINDOW(mi), *(pp->glx_context)); + pinit(mi, 1); +} +#endif /* !STANDALONE */ + + +ENTRYPOINT void +release_pipes (ModeInfo * mi) +{ + if (pipes != NULL) { + int screen; + + for (screen = 0; screen < MI_NUM_SCREENS(mi); screen++) { + pipesstruct *pp = &pipes[screen]; + + if (pp->glx_context) { + + /* Display lists MUST be freed while their glXContext is current. */ + glXMakeCurrent(MI_DISPLAY(mi), pp->window, *(pp->glx_context)); + + if (pp->valve) + glDeleteLists(pp->valve, 1); + if (pp->bolts) + glDeleteLists(pp->bolts, 1); + if (pp->betweenbolts) + glDeleteLists(pp->betweenbolts, 1); + + if (pp->elbowbolts) + glDeleteLists(pp->elbowbolts, 1); + if (pp->elbowcoins) + glDeleteLists(pp->elbowcoins, 1); + + if (pp->guagehead) + glDeleteLists(pp->guagehead, 1); + if (pp->guageface) + glDeleteLists(pp->guageface, 1); + if (pp->guagedial) + glDeleteLists(pp->guagedial, 1); + if (pp->guageconnector) + glDeleteLists(pp->guageconnector, 1); + if (pp->teapot) + glDeleteLists(pp->teapot, 1); + if (pp->dlists) + { + int i; + for (i = 0; i < pp->dlist_count; i++) + glDeleteLists (pp->dlists[i], 1); + free (pp->dlists); + free (pp->poly_counts); + } + } + } + + (void) free((void *) pipes); + pipes = NULL; + } + FreeAllGL(mi); +} + +XSCREENSAVER_MODULE ("Pipes", pipes) + +#endif diff --git a/hacks/glx/pipes.man b/hacks/glx/pipes.man new file mode 100644 index 00000000..b58a511b --- /dev/null +++ b/hacks/glx/pipes.man @@ -0,0 +1,85 @@ +.TH XScreenSaver 1 "" "X Version 11" +.SH NAME +pipes - fill the screen with a plumbing system. +.SH SYNOPSIS +.B pipes +[\-display \fIhost:display.screen\fP] +[\-visual \fIvisual\fP] +[\-window] +[\-root] +[-count 0] +[-count 1] +[-cycles \fInumber\fP] +[-size \fInumber\fP] +[-factory \fInumber\fP] +[-delay \fInumber\fP] +[-no-fisheye] +[-tightturns] +[-db] +[-fps] +.SH DESCRIPTION +If you've ever been in the same room as a Windows NT machine, you've +probably seen this GL hack. It fills the screen with a plumbing system. +.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 \-count 0 +Curved Pipes. +.TP 8 +.B \-count 1 +Ball Joints. +.TP 8 +.B \-cycles \fInumber\fP +Number of pipe systems to draw at once. Default: 5. +.TP 8 +.B \-size \fInumber\fP +Length of each pipe system. Default: 500. +.TP 8 +.B \-factory \fInumber\fP +How much gadgetry to create; Useful range is 0-10. Default: 2. +.TP 8 +.B \-delay \fInumber\fP +How long (in microseconds) to sleep between frames. Default: 10000. +.TP 8 +.B \-fisheye | \-no-fisheye +Whether to use a fisheye lens. +.TP 8 +.B \-tightturns | \-no-tightturns +Whether to allow tight turns. +.TP 8 +.B \-db | \-no-db +Whether to double-buffer. +.TP 8 +.B \-fps +Display the current frame rate, CPU load, and polygon count. +.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 2002 by Marcelo Vianna. 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 +Marcelo Vianna. diff --git a/hacks/glx/polyhedra-gl.c b/hacks/glx/polyhedra-gl.c new file mode 100644 index 00000000..f97d2bf7 --- /dev/null +++ b/hacks/glx/polyhedra-gl.c @@ -0,0 +1,758 @@ +/* polyhedra, Copyright (c) 2004-2012 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. + * + * Renders 160 different 3D solids, and displays some information about each. + * A new solid is chosen every few seconds. + * + * This file contains the OpenGL side; computation of the polyhedra themselves + * is in "polyhedra.c". + */ + +#define DEFAULTS "*delay: 30000 \n" \ + "*showFPS: False \n" \ + "*wireframe: False \n" \ + "*titleFont: -*-helvetica-medium-r-normal-*-140-*\n" \ + "*titleFont2: -*-helvetica-medium-r-normal-*-100-*\n" \ + "*titleFont3: -*-helvetica-medium-r-normal-*-80-*\n" \ + + +# define refresh_polyhedra 0 +# define release_polyhedra 0 +#undef countof +#define countof(x) (sizeof((x))/sizeof((*x))) + +#include "xlockmore.h" + +#ifdef HAVE_COCOA +# include "jwxyz.h" +#else +# include +# include +# include +#endif + +#ifdef HAVE_JWZGLES +# include "jwzgles.h" +#endif /* HAVE_JWZGLES */ + +#define DEF_SPIN "True" +#define DEF_WANDER "True" +#define DEF_SPEED "1.0" +#define DEF_TITLES "True" +#define DEF_DURATION "12" +#define DEF_WHICH "random" + +#include "glxfonts.h" +#include "normals.h" +#include "polyhedra.h" +#include "colors.h" +#include "rotator.h" +#include "gltrackball.h" +#include "teapot.h" + +#ifndef HAVE_COCOA +# define XK_MISCELLANY +# include +#endif + +#ifndef HAVE_JWZGLES +# define HAVE_TESS +#endif + + +#ifdef USE_GL /* whole file */ + +typedef struct { + GLXContext *glx_context; + rotator *rot; + trackball_state *trackball; + Bool button_down_p; + + int npolyhedra; + polyhedron **polyhedra; + + int which; + int change_to; + GLuint object_list; + GLuint title_list; + + int mode; /* 0 = normal, 1 = out, 2 = in */ + int mode_tick; + + int ncolors; + XColor *colors; + +# ifdef HAVE_GLBITMAP + XFontStruct *xfont1, *xfont2, *xfont3; + GLuint font1_dlist, font2_dlist, font3_dlist; +# else + texture_font_data *font1_data, *font2_data, *font3_data; +# endif + + time_t last_change_time; + int change_tick; + +} polyhedra_configuration; + +static polyhedra_configuration *bps = NULL; + +static Bool do_spin; +static GLfloat speed; +static Bool do_wander; +static Bool do_titles; +static int duration; +static int do_which; +static char *do_which_str; + +static XrmOptionDescRec opts[] = { + { "-spin", ".spin", XrmoptionNoArg, "True" }, + { "+spin", ".spin", XrmoptionNoArg, "False" }, + { "-speed", ".speed", XrmoptionSepArg, 0 }, + { "-wander", ".wander", XrmoptionNoArg, "True" }, + { "+wander", ".wander", XrmoptionNoArg, "False" }, + { "-titles", ".titles", XrmoptionNoArg, "True" }, + { "+titles", ".titles", XrmoptionNoArg, "False" }, + { "-duration",".duration",XrmoptionSepArg, 0 }, + { "-which", ".which", XrmoptionSepArg, 0 }, +}; + +static argtype vars[] = { + {&do_spin, "spin", "Spin", DEF_SPIN, t_Bool}, + {&do_wander, "wander", "Wander", DEF_WANDER, t_Bool}, + {&do_titles, "titles", "Titles", DEF_TITLES, t_Bool}, + {&speed, "speed", "Speed", DEF_SPEED, t_Float}, + {&duration,"duration","Duration",DEF_DURATION,t_Int}, + {&do_which_str,"which", "Which", DEF_WHICH, t_String}, +}; + +ENTRYPOINT ModeSpecOpt polyhedra_opts = {countof(opts), opts, countof(vars), vars, NULL}; + + + +/* Calculate the normals at each vertex of a face, and use the sum to + decide which normal to assign to the entire face. This also solves + problems caused by nonconvex faces, in most (but not all) cases. + */ +static void +kludge_normal (int n, const int *indices, const point *points) +{ + XYZ normal = { 0, 0, 0 }; + XYZ p = { 0, 0, 0 }; + int i; + + for (i = 0; i < n; ++i) { + int i1 = indices[i]; + int i2 = indices[(i + 1) % n]; + int i3 = indices[(i + 2) % n]; + XYZ p1, p2, p3; + + p1.x = points[i1].x; p1.y = points[i1].y; p1.z = points[i1].z; + p2.x = points[i2].x; p2.y = points[i2].y; p2.z = points[i2].z; + p3.x = points[i3].x; p3.y = points[i3].y; p3.z = points[i3].z; + + p = calc_normal (p1, p2, p3); + normal.x += p.x; + normal.y += p.y; + normal.z += p.z; + } + + /*normalize(&normal);*/ + if (normal.x == 0 && normal.y == 0 && normal.z == 0) { + glNormal3f (p.x, p.y, p.z); + } else { + glNormal3f (normal.x, normal.y, normal.z); + } +} + + +static void +load_fonts (ModeInfo *mi) +{ + polyhedra_configuration *bp = &bps[MI_SCREEN(mi)]; +# ifdef HAVE_GLBITMAP + load_font (mi->dpy, "titleFont", &bp->xfont1, &bp->font1_dlist); + load_font (mi->dpy, "titleFont2", &bp->xfont2, &bp->font2_dlist); + load_font (mi->dpy, "titleFont3", &bp->xfont3, &bp->font3_dlist); +# else /* !HAVE_GLBITMAP */ + bp->font1_data = load_texture_font (mi->dpy, "titleFont"); + bp->font2_data = load_texture_font (mi->dpy, "titleFont2"); + bp->font3_data = load_texture_font (mi->dpy, "titleFont3"); +# endif /* !HAVE_GLBITMAP */ +} + + + +static void +startup_blurb (ModeInfo *mi) +{ + polyhedra_configuration *bp = &bps[MI_SCREEN(mi)]; + const char *s = "Computing polyhedra..."; +# ifdef HAVE_GLBITMAP + XFontStruct *f = bp->xfont1; +# else /* !HAVE_GLBITMAP */ + texture_font_data *f = bp->font1_data; +# endif /* !HAVE_GLBITMAP */ + + glColor3f (0.8, 0.8, 0); + print_gl_string (mi->dpy, +# ifdef HAVE_GLBITMAP + bp->xfont1, bp->font1_dlist, +# else /* !HAVE_GLBITMAP */ + bp->font1_data, +# endif /* !HAVE_GLBITMAP */ + mi->xgwa.width, mi->xgwa.height, + mi->xgwa.width - ( +# ifdef HAVE_GLBITMAP + string_width (f, s, 0) +# else /* !HAVE_GLBITMAP */ + texture_string_width (f, s, 0) +# endif /* !HAVE_GLBITMAP */ + + 40), + mi->xgwa.height - 10, + s, False); + glFinish(); + glXSwapBuffers(MI_DISPLAY(mi), MI_WINDOW(mi)); +} + + + +/* Window management, etc + */ +static void new_label (ModeInfo *mi); + +ENTRYPOINT void +reshape_polyhedra (ModeInfo *mi, int width, int height) +{ + GLfloat h = (GLfloat) height / (GLfloat) width; + + glViewport (0, 0, (GLint) width, (GLint) height); + + glMatrixMode(GL_PROJECTION); + glLoadIdentity(); + gluPerspective (30.0, 1/h, 1.0, 100.0); + + glMatrixMode(GL_MODELVIEW); + glLoadIdentity(); + gluLookAt( 0.0, 0.0, 30.0, + 0.0, 0.0, 0.0, + 0.0, 1.0, 0.0); + + glClear(GL_COLOR_BUFFER_BIT); + + /* need to re-render the text when the window size changes */ + new_label (mi); +} + + +ENTRYPOINT Bool +polyhedra_handle_event (ModeInfo *mi, XEvent *event) +{ + polyhedra_configuration *bp = &bps[MI_SCREEN(mi)]; + + if (event->xany.type == ButtonPress && + event->xbutton.button == Button1) + { + bp->button_down_p = True; + gltrackball_start (bp->trackball, + event->xbutton.x, event->xbutton.y, + MI_WIDTH (mi), MI_HEIGHT (mi)); + return True; + } + else if (event->xany.type == ButtonRelease && + event->xbutton.button == Button1) + { + bp->button_down_p = False; + return True; + } + else if (event->xany.type == ButtonPress && + (event->xbutton.button == Button4 || + event->xbutton.button == Button5 || + event->xbutton.button == Button6 || + event->xbutton.button == Button7)) + { + gltrackball_mousewheel (bp->trackball, event->xbutton.button, 10, + !!event->xbutton.state); + return True; + } + else if (event->xany.type == KeyPress) + { + KeySym keysym; + char c = 0; + XLookupString (&event->xkey, &c, 1, &keysym, 0); + + bp->change_to = -1; + if (c == ' ' || c == '\t' || c == '\r' || c == '\n') + bp->change_to = random() % bp->npolyhedra; + else if (c == '>' || c == '.' || c == '+' || c == '=' || + keysym == XK_Right || keysym == XK_Up) + bp->change_to = (bp->which + 1) % bp->npolyhedra; + else if (c == '<' || c == ',' || c == '-' || c == '_' || + c == '\010' || c == '\177' || + keysym == XK_Left || keysym == XK_Down) + bp->change_to = (bp->which + bp->npolyhedra - 1) % bp->npolyhedra; + + if (bp->change_to != -1) + return True; + } + else if (event->xany.type == MotionNotify && + bp->button_down_p) + { + gltrackball_track (bp->trackball, + event->xmotion.x, event->xmotion.y, + MI_WIDTH (mi), MI_HEIGHT (mi)); + return True; + } + + return False; +} + + +static void +new_label (ModeInfo *mi) +{ + polyhedra_configuration *bp = &bps[MI_SCREEN(mi)]; + polyhedron *p = bp->which >= 0 ? bp->polyhedra[bp->which] : 0; + + glNewList (bp->title_list, GL_COMPILE); + if (p && do_titles) + { + char label[1024]; + char name2[255]; + strcpy (name2, p->name); + if (*p->class) + sprintf (name2 + strlen(name2), " (%s)", p->class); + + sprintf (label, + "Polyhedron %d: \t%s\n\n" + "Wythoff Symbol:\t%s\n" + "Vertex Configuration:\t%s\n" + "Symmetry Group:\t%s\n" + /* "Dual of: \t%s\n" */ + "\n" + "Faces:\t %d\n" + "Edges:\t %d\n" + "Vertices:\t %d\n" + "Density:\t %d\n" + "Euler:\t%s%d\n", + bp->which, name2, p->wythoff, p->config, p->group, + /* p->dual, */ + p->logical_faces, p->nedges, p->logical_vertices, + p->density, (p->chi < 0 ? "" : " "), p->chi); + + { +# ifdef HAVE_GLBITMAP + XFontStruct *f; + GLuint fl; +# else /* !HAVE_GLBITMAP */ + texture_font_data *f; +# endif /* !HAVE_GLBITMAP */ + if (MI_WIDTH(mi) >= 500 && MI_HEIGHT(mi) >= 375) +# ifdef HAVE_GLBITMAP + f = bp->xfont1, fl = bp->font1_dlist; /* big font */ +# else /* !HAVE_GLBITMAP */ + f = bp->font1_data; +# endif /* !HAVE_GLBITMAP */ + else if (MI_WIDTH(mi) >= 350 && MI_HEIGHT(mi) >= 260) +# ifdef HAVE_GLBITMAP + f = bp->xfont2, fl = bp->font2_dlist; /* small font */ +# else /* !HAVE_GLBITMAP */ + f = bp->font2_data; /* small font */ +# endif /* !HAVE_GLBITMAP */ + else +# ifdef HAVE_GLBITMAP + f = bp->xfont3, fl = bp->font3_dlist; /* tiny font */ +# else /* !HAVE_GLBITMAP */ + f = bp->font3_data; /* tiny font */ +# endif /* !HAVE_GLBITMAP */ + + glColor3f (0.8, 0.8, 0); + print_gl_string (mi->dpy, f, +# ifdef HAVE_GLBITMAP + fl, +# endif /* HAVE_GLBITMAP */ + mi->xgwa.width, mi->xgwa.height, + 10, mi->xgwa.height - 10, + label, False); + } + } + glEndList (); +} + + +#ifdef HAVE_TESS +static void +tess_error (GLenum errorCode) +{ + fprintf (stderr, "%s: tesselation error: %s\n", + progname, gluErrorString(errorCode)); + abort(); +} +#endif /* HAVE_TESS */ + + +static void +new_polyhedron (ModeInfo *mi) +{ + polyhedra_configuration *bp = &bps[MI_SCREEN(mi)]; + polyhedron *p; + int wire = MI_IS_WIREFRAME(mi); + int i; + + /* Use the GLU polygon tesselator so that nonconvex faces are displayed + correctly (e.g., for the "pentagrammic concave deltohedron"). + */ +# ifdef HAVE_TESS + GLUtesselator *tobj = gluNewTess(); + gluTessCallback (tobj, GLU_TESS_BEGIN, (void (*) (void)) &glBegin); + gluTessCallback (tobj, GLU_TESS_END, (void (*) (void)) &glEnd); + gluTessCallback (tobj, GLU_TESS_VERTEX, (void (*) (void)) &glVertex3dv); + gluTessCallback (tobj, GLU_TESS_ERROR, (void (*) (void)) &tess_error); +# endif /* HAVE_TESS */ + + mi->polygon_count = 0; + + bp->ncolors = 128; + bp->colors = (XColor *) calloc(bp->ncolors, sizeof(XColor)); + make_random_colormap (0, 0, 0, + bp->colors, &bp->ncolors, + True, False, 0, False); + + if (do_which >= bp->npolyhedra) + do_which = -1; + + bp->which = (bp->change_to != -1 ? bp->change_to : + do_which >= 0 ? do_which : + (random() % bp->npolyhedra)); + bp->change_to = -1; + p = bp->polyhedra[bp->which]; + + new_label (mi); + + if (wire) + glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); + + glNewList (bp->object_list, GL_COMPILE); + if (bp->which == bp->npolyhedra-1) + { + GLfloat bcolor[4]; + bcolor[0] = bp->colors[0].red / 65536.0; + bcolor[1] = bp->colors[0].green / 65536.0; + bcolor[2] = bp->colors[0].blue / 65536.0; + bcolor[3] = 1.0; + if (wire) + glColor3f (0, 1, 0); + else + glMaterialfv (GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, bcolor); + + glScalef (0.8, 0.8, 0.8); + p->nfaces = unit_teapot (6, wire); + p->nedges = p->nfaces * 3 / 2; + p->npoints = p->nfaces * 3; + p->logical_faces = p->nfaces; + p->logical_vertices = p->npoints; + } + else + { + glFrontFace (GL_CCW); + for (i = 0; i < p->nfaces; i++) + { + int j; + face *f = &p->faces[i]; + + if (f->color > 64 || f->color < 0) abort(); + if (wire) + glColor3f (0, 1, 0); + else + { + GLfloat bcolor[4]; + bcolor[0] = bp->colors[f->color].red / 65536.0; + bcolor[1] = bp->colors[f->color].green / 65536.0; + bcolor[2] = bp->colors[f->color].blue / 65536.0; + bcolor[3] = 1.0; + glMaterialfv (GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, bcolor); + } + + kludge_normal (f->npoints, f->points, p->points); + +# ifdef HAVE_TESS + gluTessBeginPolygon (tobj, 0); + gluTessBeginContour (tobj); + for (j = 0; j < f->npoints; j++) + { + point *pp = &p->points[f->points[j]]; + gluTessVertex (tobj, &pp->x, &pp->x); + } + gluTessEndContour (tobj); + gluTessEndPolygon (tobj); +# else /* !HAVE_TESS */ + glBegin (wire ? GL_LINE_LOOP : + f->npoints == 3 ? GL_TRIANGLES : + f->npoints == 4 ? GL_QUADS : + GL_POLYGON); + for (j = 0; j < f->npoints; j++) + { + point *pp = &p->points[f->points[j]]; + glVertex3f (pp->x, pp->y, pp->z); + } + glEnd(); +# endif /* !HAVE_TESS */ + } + } + glEndList (); + + mi->polygon_count += p->nfaces; +# ifdef HAVE_TESS + gluDeleteTess (tobj); +# endif +} + + +static void +construct_teapot (ModeInfo *mi) +{ + polyhedra_configuration *bp = &bps[MI_SCREEN(mi)]; + int n = bp->npolyhedra-1; + polyhedron *p = (polyhedron *) calloc (1, sizeof(*p)); + p->number = n; + p->wythoff = strdup("X00398|1984"); + p->name = strdup("Teapot"); + p->dual = strdup(""); + p->config = strdup("Melitta"); + p->group = strdup("Teapotahedral (Newell[1975])"); + p->class = strdup("Utah Teapotahedron"); + bp->polyhedra[n] = p; +} + + +ENTRYPOINT void +init_polyhedra (ModeInfo *mi) +{ + polyhedra_configuration *bp; + int wire = MI_IS_WIREFRAME(mi); + +# ifdef HAVE_JWZGLES /* #### glPolygonMode other than GL_FILL unimplemented */ + MI_IS_WIREFRAME(mi) = 0; + wire = 0; +# endif + + if (!bps) { + bps = (polyhedra_configuration *) + calloc (MI_NUM_SCREENS(mi), sizeof (polyhedra_configuration)); + if (!bps) { + fprintf(stderr, "%s: out of memory\n", progname); + exit(1); + } + } + + bp = &bps[MI_SCREEN(mi)]; + + bp->glx_context = init_GL(mi); + + bp->which = -1; + load_fonts (mi); + startup_blurb (mi); + + if (!wire) + { + GLfloat pos[4] = {1.0, 1.0, 1.0, 0.0}; + GLfloat amb[4] = {0.0, 0.0, 0.0, 1.0}; + GLfloat dif[4] = {1.0, 1.0, 1.0, 1.0}; + GLfloat spc[4] = {0.0, 1.0, 1.0, 1.0}; + + glEnable(GL_LIGHTING); + glEnable(GL_LIGHT0); + glEnable(GL_DEPTH_TEST); + /* glEnable(GL_CULL_FACE); */ + + /* We need two-sided lighting for polyhedra where both sides of + a face are simultaneously visible (e.g., the "X-hemi-Y-hedrons".) + */ + glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, GL_TRUE); + + glLightfv(GL_LIGHT0, GL_POSITION, pos); + glLightfv(GL_LIGHT0, GL_AMBIENT, amb); + glLightfv(GL_LIGHT0, GL_DIFFUSE, dif); + glLightfv(GL_LIGHT0, GL_SPECULAR, spc); + } + + { + double spin_speed = 2.0; + double wander_speed = 0.05; + double spin_accel = 0.2; + + bp->rot = make_rotator (do_spin ? spin_speed : 0, + do_spin ? spin_speed : 0, + do_spin ? spin_speed : 0, + spin_accel, + do_wander ? wander_speed : 0, + True); + bp->trackball = gltrackball_init (); + } + + bp->npolyhedra = construct_polyhedra (&bp->polyhedra); + construct_teapot (mi); + + bp->object_list = glGenLists (1); + bp->title_list = glGenLists (1); + bp->change_to = -1; + + { + int x; + char c; + do_which = -1; + if (!strcasecmp (do_which_str, "random")) + ; + else if (1 == sscanf (do_which_str, " %d %c", &x, &c)) + { + if (x >= 0 && x < bp->npolyhedra) + do_which = x; + else + fprintf (stderr, + "%s: polyhedron %d does not exist: there are only %d.\n", + progname, x, bp->npolyhedra-1); + } + else if (*do_which_str) + { + char *s; + for (s = do_which_str; *s; s++) + if (*s == '-' || *s == '_') *s = ' '; + + for (x = 0; x < bp->npolyhedra; x++) + if (!strcasecmp (do_which_str, bp->polyhedra[x]->name) || + !strcasecmp (do_which_str, bp->polyhedra[x]->class) || + !strcasecmp (do_which_str, bp->polyhedra[x]->wythoff) || + !strcasecmp (do_which_str, bp->polyhedra[x]->config)) + { + do_which = x; + break; + } + if (do_which < 0) + { + fprintf (stderr, "%s: no such polyhedron: \"%s\"\n", + progname, do_which_str); + exit (1); + } + } + } + + new_polyhedron (mi); + reshape_polyhedra (mi, MI_WIDTH(mi), MI_HEIGHT(mi)); + clear_gl_error(); /* WTF? sometimes "invalid op" from glViewport! */ + +} + + +ENTRYPOINT void +draw_polyhedra (ModeInfo *mi) +{ + polyhedra_configuration *bp = &bps[MI_SCREEN(mi)]; + Display *dpy = MI_DISPLAY(mi); + Window window = MI_WINDOW(mi); + + static const GLfloat bspec[4] = {1.0, 1.0, 1.0, 1.0}; + GLfloat bshiny = 128.0; + + if (!bp->glx_context) + return; + + glXMakeCurrent(MI_DISPLAY(mi), MI_WINDOW(mi), *(bp->glx_context)); + + if (bp->mode == 0 && do_which >= 0 && bp->change_to < 0) + ; + else if (bp->mode == 0) + { + if (bp->change_to >= 0) + bp->change_tick = 999, bp->last_change_time = 1; + if (bp->change_tick++ > 10) + { + time_t now = time((time_t *) 0); + if (bp->last_change_time == 0) bp->last_change_time = now; + bp->change_tick = 0; + if (!bp->button_down_p && now - bp->last_change_time >= duration) + { + bp->mode = 1; /* go out */ + bp->mode_tick = 20 * speed; + bp->last_change_time = now; + } + } + } + else if (bp->mode == 1) /* out */ + { + if (--bp->mode_tick <= 0) + { + new_polyhedron (mi); + bp->mode_tick = 20 * speed; + bp->mode = 2; /* go in */ + } + } + else if (bp->mode == 2) /* in */ + { + if (--bp->mode_tick <= 0) + bp->mode = 0; /* normal */ + } + else + abort(); + + glShadeModel(GL_FLAT); + glEnable(GL_NORMALIZE); + + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + + glPushMatrix (); + + glScalef(1.1, 1.1, 1.1); + + { + double x, y, z; + get_position (bp->rot, &x, &y, &z, !bp->button_down_p); + glTranslatef((x - 0.5) * 8, + (y - 0.5) * 8, + (z - 0.5) * 15); + + /* Do it twice because we don't track the device's orientation. */ + glRotatef( current_device_rotation(), 0, 0, 1); + gltrackball_rotate (bp->trackball); + glRotatef(-current_device_rotation(), 0, 0, 1); + + get_rotation (bp->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 (2.0, 2.0, 2.0); + + glMaterialfv (GL_FRONT_AND_BACK, GL_SPECULAR, bspec); + glMateriali (GL_FRONT_AND_BACK, GL_SHININESS, bshiny); + + if (bp->mode != 0) + { + GLfloat s = (bp->mode == 1 + ? bp->mode_tick / (20 * speed) + : ((20 * speed) - bp->mode_tick + 1) / (20 * speed)); + glScalef (s, s, s); + } + + glScalef (2, 2, 2); + glCallList (bp->object_list); + if (bp->mode == 0 && !bp->button_down_p) + glCallList (bp->title_list); + + glPopMatrix (); + + if (mi->fps_p) do_fps (mi); + glFinish(); + + glXSwapBuffers(dpy, window); +} + +XSCREENSAVER_MODULE ("Polyhedra", polyhedra) + +#endif /* USE_GL */ diff --git a/hacks/glx/polyhedra.c b/hacks/glx/polyhedra.c new file mode 100644 index 00000000..26f66d3a --- /dev/null +++ b/hacks/glx/polyhedra.c @@ -0,0 +1,2458 @@ +/***************************************************************************** + * #ident "Id: main.c,v 3.27 2002-01-06 16:23:01+02 rl Exp " + * kaleido + * + * Kaleidoscopic construction of uniform polyhedra + * Copyright (c) 1991-2002 Dr. Zvi Har'El + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The end-user documentation included with the redistribution, + * if any, must include the following acknowledgment: + * "This product includes software developed by + * Dr. Zvi Har'El (http://www.math.technion.ac.il/~rl/)." + * Alternately, this acknowledgment may appear in the software itself, + * if and wherever such third-party acknowledgments normally appear. + * + * This software is provided 'as-is', without any express or implied + * warranty. In no event will the author be held liable for any + * damages arising from the use of this software. + * + * Author: + * Dr. Zvi Har'El, + * Deptartment of Mathematics, + * Technion, Israel Institue of Technology, + * Haifa 32000, Israel. + * E-Mail: rl@math.technion.ac.il + * + * ftp://ftp.math.technion.ac.il/kaleido/ + * http://www.mathconsult.ch/showroom/unipoly/ + * + * Adapted for xscreensaver by Jamie Zawinski 25-Apr-2004 + * + ***************************************************************************** + */ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include +#include +#include +#include +#include +#include + +#include "polyhedra.h" + +extern const char *progname; + +#ifndef MAXLONG +#define MAXLONG 0x7FFFFFFF +#endif +#ifndef MAXDIGITS +#define MAXDIGITS 10 /* (int)log10((double)MAXLONG) + 1 */ +#endif + +#ifndef DBL_EPSILON +#define DBL_EPSILON 2.2204460492503131e-16 +#endif +#define BIG_EPSILON 3e-2 +#define AZ M_PI/7 /* axis azimuth */ +#define EL M_PI/17 /* axis elevation */ + +#define Err(x) do {\ + fprintf (stderr, "%s: %s\n", progname, (x)); \ + exit (1); \ + } while(0) + +#define Free(lvalue) do {\ + if (lvalue) {\ + free((char*) lvalue);\ + lvalue=0;\ + }\ + } while(0) + +#define Matfree(lvalue,n) do {\ + if (lvalue) \ + matfree((char*) lvalue, n);\ + lvalue=0;\ + } while(0) + +#define Malloc(lvalue,n,type) do {\ + if (!(lvalue = (type*) calloc((n), sizeof(type)))) \ + abort();\ + } while(0) + +#define Realloc(lvalue,n,type) do {\ + if (!(lvalue = (type*) realloc(lvalue, (n) * sizeof(type)))) \ + abort();\ + } while(0) + +#define Calloc(lvalue,n,type) do {\ + if (!(lvalue = (type*) calloc(n, sizeof(type))))\ + abort();\ + } while(0) + +#define Matalloc(lvalue,n,m,type) do {\ + if (!(lvalue = (type**) matalloc(n, (m) * sizeof(type))))\ + abort();\ + } while(0) + +#define Sprintfrac(lvalue,x) do {\ + if (!(lvalue=sprintfrac(x)))\ + return 0;\ + } while(0) + +#define numerator(x) (frac(x), frax.n) +#define denominator(x) (frac(x), frax.d) +#define compl(x) (frac(x), (double) frax.n / (frax.n-frax.d)) + +typedef struct { + double x, y, z; +} Vector; + +typedef struct { + /* NOTE: some of the int's can be replaced by short's, char's, + or even bit fields, at the expense of readability!!!*/ + int index; /* index to the standard list, the array uniform[] */ + int N; /* number of faces types (atmost 5)*/ + int M; /* vertex valency (may be big for dihedral polyhedra) */ + int V; /* vertex count */ + int E; /* edge count */ + int F; /* face count */ + int D; /* density */ + int chi; /* Euler characteristic */ + int g; /* order of symmetry group */ + int K; /* symmetry type: D=2, T=3, O=4, I=5 */ + int hemi;/* flag hemi polyhedron */ + int onesided;/* flag onesided polyhedron */ + int even; /* removed face in pqr| */ + int *Fi; /* face counts by type (array N)*/ + int *rot; /* vertex configuration (array M of 0..N-1) */ + int *snub; /* snub triangle configuration (array M of 0..1) */ + int *firstrot; /* temporary for vertex generation (array V) */ + int *anti; /* temporary for direction of ideal vertices (array E) */ + int *ftype; /* face types (array F) */ + int **e; /* edges (matrix 2 x E of 0..V-1)*/ + int **dual_e; /* dual edges (matrix 2 x E of 0..F-1)*/ + int **incid; /* vertex-face incidence (matrix M x V of 0..F-1)*/ + int **adj; /* vertex-vertex adjacency (matrix M x V of 0..V-1)*/ + double p[4]; /* p, q and r; |=0 */ + double minr; /* smallest nonzero inradius */ + double gon; /* basis type for dihedral polyhedra */ + double *n; /* number of side of a face of each type (array N) */ + double *m; /* number of faces at a vertex of each type (array N) */ + double *gamma; /* fundamental angles in radians (array N) */ + char *polyform; /* printable Wythoff symbol */ + char *config; /* printable vertex configuration */ + char *group; /* printable group name */ + char *name; /* name, standard or manifuctured */ + char *dual_name; /* dual name, standard or manifuctured */ + char *class; + char *dual_class; + Vector *v; /* vertex coordinates (array V) */ + Vector *f; /* face coordinates (array F)*/ +} Polyhedron; + +typedef struct { + long n,d; +} Fraction; + +static Polyhedron *polyalloc(void); +static Vector rotate(Vector vertex, Vector axis, double angle); + +static Vector sum3(Vector a, Vector b, Vector c); +static Vector scale(double k, Vector a); +static Vector sum(Vector a, Vector b); +static Vector diff(Vector a, Vector b); +static Vector pole (double r, Vector a, Vector b, Vector c); +static Vector cross(Vector a, Vector b); +static double dot(Vector a, Vector b); +static int same(Vector a, Vector b, double epsilon); + +static char *sprintfrac(double x); + +static void frac(double x); +static void matfree(void *mat, int rows); +static void *matalloc(int rows, int row_size); + +static Fraction frax; + + +static const struct { + char *Wythoff, *name, *dual, *group, *class, *dual_class; + short Coxeter, Wenninger; +} uniform[] = { + + /**************************************************************************** + * Dihedral Schwarz Triangles (D5 only) + ***************************************************************************/ + + /* {"3|2 5/2", "xyz", + "xyz", + "xyz", + "", + "", + 0, 0}, +*/ + + + + /* (2 2 5) (D1/5) */ + /* 1 */ {"2 5|2", "Pentagonal Prism", + "Pentagonal Dipyramid", + "Dihedral (D[1/5])", + "", + "", + 0, 0}, + + /* 2 */ {"|2 2 5", "Pentagonal Antiprism", + "Pentagonal Deltohedron", + "Dihedral (D[1/5])", + "", + "", + 0, 0}, + /* (2 2 5/2) (D2/5) */ + /* 3 */ {"2 5/2|2", "Pentagrammic Prism", + "Pentagrammic Dipyramid", + "Dihedral (D[2/5])", + "", + "", + 0, 0}, + + /* 4 */ {"|2 2 5/2", "Pentagrammic Antiprism", + "Pentagrammic Deltohedron", + "Dihedral (D[2/5])", + "", + "", + 0, 0}, + /* (5/3 2 2) (D3/5) */ + + /* 5 */ {"|2 2 5/3", "Pentagrammic Crossed Antiprism", + "Pentagrammic Concave Deltohedron", + "Dihedral (D[3/5])", + "", + "", + 0, 0}, + + /**************************************************************************** + * Tetrahedral + ***************************************************************************/ + + /* (2 3 3) (T1) */ + /* 6 */ {"3|2 3", "Tetrahedron", + "Tetrahedron", + "Tetrahedral (T[1])", + "Platonic Solid", + "Platonic Solid", + 15, 1}, + + /* 7 */ {"2 3|3", "Truncated Tetrahedron", + "Triakistetrahedron", + "Tetrahedral (T[1])", + "Archimedian Solid", + "Catalan Solid", + 16, 6}, + /* (3/2 3 3) (T2) */ + /* 8 */ {"3/2 3|3", "Octahemioctahedron", + "Octahemioctacron", + "Tetrahedral (T[2])", + "", + "", + 37, 68}, + + /* (3/2 2 3) (T3) */ + /* 9 */ {"3/2 3|2", "Tetrahemihexahedron", + "Tetrahemihexacron", + "Tetrahedral (T[3])", + "", + "", + 36, 67}, + + /**************************************************************************** + * Octahedral + ***************************************************************************/ + + /* (2 3 4) (O1) */ + /* 10 */ {"4|2 3", "Octahedron", + "Cube", + "Octahedral (O[1])", + "Platonic Solid", + "Platonic Solid", + 17, 2}, + + /* 11 */ {"3|2 4", "Cube", + "Octahedron", + "Octahedral (O[1])", + "Platonic Solid", + "Platonic Solid", + 18, 3}, + + /* 12 */ {"2|3 4", "Cuboctahedron", + "Rhombic Dodecahedron", + "Octahedral (O[1])", + "Archimedian Solid", + "Catalan Solid", + 19, 11}, + + /* 13 */ {"2 4|3", "Truncated Octahedron", + "Tetrakishexahedron", + "Octahedral (O[1])", + "Archimedian Solid", + "Catalan Solid", + 20, 7}, + + /* 14 */ {"2 3|4", "Truncated Cube", + "Triakisoctahedron", + "Octahedral (O[1])", + "Archimedian Solid", + "Catalan Solid", + 21, 8}, + + /* 15 */ {"3 4|2", "Rhombicuboctahedron", + "Deltoidal Icositetrahedron", + "Octahedral (O[1])", + "Archimedian Solid", + "Catalan Solid", + 22, 13}, + + /* 16 */ {"2 3 4|", "Truncated Cuboctahedron", + "Disdyakisdodecahedron", + "Octahedral (O[1])", + "Archimedian Solid", + "Catalan Solid", + 23, 15}, + + /* 17 */ {"|2 3 4", "Snub Cube", + "Pentagonal Icositetrahedron", + "Octahedral (O[1])", + "Archimedian Solid", + "Catalan Solid", + 24, 17}, + /* (3/2 4 4) (O2b) */ + + /* 18 */ {"3/2 4|4", "Small Cubicuboctahedron", + "Small Hexacronic Icositetrahedron", + "Octahedral (O[2b])", + "", + "", + 38, 69}, + /* (4/3 3 4) (O4) */ + + /* 19 */ {"3 4|4/3", "Great Cubicuboctahedron", + "Great Hexacronic Icositetrahedron", + "Octahedral (O[4])", + "", + "", + 50, 77}, + + /* 20 */ {"4/3 4|3", "Cubohemioctahedron", + "Hexahemioctacron", + "Octahedral (O[4])", + "", + "", + 51, 78}, + + /* 21 */ {"4/3 3 4|", "Cubitruncated Cuboctahedron", + "Tetradyakishexahedron", + "Octahedral (O[4])", + "", + "", + 52, 79}, + /* (3/2 2 4) (O5) */ + + /* 22 */ {"3/2 4|2", "Great Rhombicuboctahedron", + "Great Deltoidal Icositetrahedron", + "Octahedral (O[5])", + "", + "", + 59, 85}, + + /* 23 */ {"3/2 2 4|", "Small Rhombihexahedron", + "Small Rhombihexacron", + "Octahedral (O[5])", + "", + "", + 60, 86}, + /* (4/3 2 3) (O7) */ + + /* 24 */ {"2 3|4/3", "Stellated Truncated Hexahedron", + "Great Triakisoctahedron", + "Octahedral (O[7])", + "", + "", + 66, 92}, + + /* 25 */ {"4/3 2 3|", "Great Truncated Cuboctahedron", + "Great Disdyakisdodecahedron", + "Octahedral (O[7])", + "", + "", + 67, 93}, + /* (4/3 3/2 2) (O11) */ + + /* 26 */ {"4/3 3/2 2|", "Great Rhombihexahedron", + "Great Rhombihexacron", + "Octahedral (O[11])", + "", + "", + 82, 103}, + + /**************************************************************************** + * Icosahedral + ***************************************************************************/ + + /* (2 3 5) (I1) */ + /* 27 */ {"5|2 3", "Icosahedron", + "Dodecahedron", + "Icosahedral (I[1])", + "Platonic Solid", + "Platonic Solid", + 25, 4}, + + /* 28 */ {"3|2 5", "Dodecahedron", + "Icosahedron", + "Icosahedral (I[1])", + "Platonic Solid", + "Platonic Solid", + 26, 5}, + + /* 29 */ {"2|3 5", "Icosidodecahedron", + "Rhombic Triacontahedron", + "Icosahedral (I[1])", + "Archimedian Solid", + "Catalan Solid", + 28, 12}, + + /* 30 */ {"2 5|3", "Truncated Icosahedron", + "Pentakisdodecahedron", + "Icosahedral (I[1])", + "Archimedian Solid", + "Catalan Solid", + 27, 9}, + + /* 31 */ {"2 3|5", "Truncated Dodecahedron", + "Triakisicosahedron", + "Icosahedral (I[1])", + "Archimedian Solid", + "Catalan Solid", + 29, 10}, + + /* 32 */ {"3 5|2", "Rhombicosidodecahedron", + "Deltoidal Hexecontahedron", + "Icosahedral (I[1])", + "Archimedian Solid", + "Catalan Solid", + 30, 14}, + + /* 33 */ {"2 3 5|", "Truncated Icosidodecahedron", + "Disdyakistriacontahedron", + "Icosahedral (I[1])", + "Archimedian Solid", + "Catalan Solid", + 31, 16}, + + /* 34 */ {"|2 3 5", "Snub Dodecahedron", + "Pentagonal Hexecontahedron", + "Icosahedral (I[1])", + "Archimedian Solid", + "Catalan Solid", + 32, 18}, + /* (5/2 3 3) (I2a) */ + + /* 35 */ {"3|5/2 3", "Small Ditrigonal Icosidodecahedron", + "Small Triambic Icosahedron", + "Icosahedral (I[2a])", + "", + "", + 39, 70}, + + /* 36 */ {"5/2 3|3", "Small Icosicosidodecahedron", + "Small Icosacronic Hexecontahedron", + "Icosahedral (I[2a])", + "", + "", + 40, 71}, + + /* 37 */ {"|5/2 3 3", "Small Snub Icosicosidodecahedron", + "Small Hexagonal Hexecontahedron", + "Icosahedral (I[2a])", + "", + "", + 41, 110}, + /* (3/2 5 5) (I2b) */ + + /* 38 */ {"3/2 5|5", "Small Dodecicosidodecahedron", + "Small Dodecacronic Hexecontahedron", + "Icosahedral (I[2b])", + "", + "", + 42, 72}, + /* (2 5/2 5) (I3) */ + + /* 39 */ {"5|2 5/2", "Small Stellated Dodecahedron", + "Great Dodecahedron", + "Icosahedral (I[3])", + "Truncated Kepler-Poinsot Solid", + "", + 43, 20}, + + /* 40 */ {"5/2|2 5", "Great Dodecahedron", + "Small Stellated Dodecahedron", + "Icosahedral (I[3])", + "", + "", + 44, 21}, + + /* 41 */ {"2|5/2 5", "Great Dodecadodecahedron", + "Medial Rhombic Triacontahedron", + "Icosahedral (I[3])", + "", + "", + 45, 73}, + + /* 42 */ {"2 5/2|5", "Truncated Great Dodecahedron", + "Small Stellapentakisdodecahedron", + "Icosahedral (I[3])", + "Truncated Kepler-Poinsot Solid", + "", + 47, 75}, + + /* 43 */ {"5/2 5|2", "Rhombidodecadodecahedron", + "Medial Deltoidal Hexecontahedron", + "Icosahedral (I[3])", + "", + "", + 48, 76}, + + /* 44 */ {"2 5/2 5|", "Small Rhombidodecahedron", + "Small Rhombidodecacron", + "Icosahedral (I[3])", + "", + "", + 46, 74}, + + /* 45 */ {"|2 5/2 5", "Snub Dodecadodecahedron", + "Medial Pentagonal Hexecontahedron", + "Icosahedral (I[3])", + "", + "", + 49, 111}, + /* (5/3 3 5) (I4) */ + + /* 46 */ {"3|5/3 5", "Ditrigonal Dodecadodecahedron", + "Medial Triambic Icosahedron", + "Icosahedral (I[4])", + "", + "", + 53, 80}, + + /* 47 */ {"3 5|5/3", "Great Ditrigonal Dodecicosidodecahedron", + "Great Ditrigonal Dodecacronic Hexecontahedron", + "Icosahedral (I[4])", + "", + "", + 54, 81}, + + /* 48 */ {"5/3 3|5", "Small Ditrigonal Dodecicosidodecahedron", + "Small Ditrigonal Dodecacronic Hexecontahedron", + "Icosahedral (I[4])", + "", + "", + 55, 82}, + + /* 49 */ {"5/3 5|3", "Icosidodecadodecahedron", + "Medial Icosacronic Hexecontahedron", + "Icosahedral (I[4])", + "", + "", + 56, 83}, + + /* 50 */ {"5/3 3 5|", "Icositruncated Dodecadodecahedron", + "Tridyakisicosahedron", + "Icosahedral (I[4])", + "", + "", + 57, 84}, + + /* 51 */ {"|5/3 3 5", "Snub Icosidodecadodecahedron", + "Medial Hexagonal Hexecontahedron", + "Icosahedral (I[4])", + "", + "", + 58, 112}, + /* (3/2 3 5) (I6b) */ + + /* 52 */ {"3/2|3 5", "Great Ditrigonal Icosidodecahedron", + "Great Triambic Icosahedron", + "Icosahedral (I[6b])", + "", + "", + 61, 87}, + + /* 53 */ {"3/2 5|3", "Great Icosicosidodecahedron", + "Great Icosacronic Hexecontahedron", + "Icosahedral (I[6b])", + "", + "", + 62, 88}, + + /* 54 */ {"3/2 3|5", "Small Icosihemidodecahedron", + "Small Icosihemidodecacron", + "Icosahedral (I[6b])", + "", + "", + 63, 89}, + + /* 55 */ {"3/2 3 5|", "Small Dodecicosahedron", + "Small Dodecicosacron", + "Icosahedral (I[6b])", + "", + "", + 64, 90}, + /* (5/4 5 5) (I6c) */ + + /* 56 */ {"5/4 5|5", "Small Dodecahemidodecahedron", + "Small Dodecahemidodecacron", + "Icosahedral (I[6c])", + "", + "", + 65, 91}, + /* (2 5/2 3) (I7) */ + + /* 57 */ {"3|2 5/2", "Great Stellated Dodecahedron", + "Great Icosahedron", + "Icosahedral (I[7])", + "", + "", + 68, 22}, + + /* 58 */ {"5/2|2 3", "Great Icosahedron", + "Great Stellated Dodecahedron", + "Icosahedral (I[7])", + "", + "", + 69, 41}, + + /* 59 */ {"2|5/2 3", "Great Icosidodecahedron", + "Great Rhombic Triacontahedron", + "Icosahedral (I[7])", + "Truncated Kepler-Poinsot Solid", + "", + 70, 94}, + + /* 60 */ {"2 5/2|3", "Great Truncated Icosahedron", + "Great Stellapentakisdodecahedron", + "Icosahedral (I[7])", + "Truncated Kepler-Poinsot Solid", + "", + 71, 95}, + + /* 61 */ {"2 5/2 3|", "Rhombicosahedron", + "Rhombicosacron", + "Icosahedral (I[7])", + "", + "", + 72, 96}, + + /* 62 */ {"|2 5/2 3", "Great Snub Icosidodecahedron", + "Great Pentagonal Hexecontahedron", + "Icosahedral (I[7])", + "", + "", + 73, 113}, + /* (5/3 2 5) (I9) */ + + /* 63 */ {"2 5|5/3", "Small Stellated Truncated Dodecahedron", + "Great Pentakisdodekahedron", + "Icosahedral (I[9])", + "", + "", + 74, 97}, + + /* 64 */ {"5/3 2 5|", "Truncated Dodecadodecahedron", + "Medial Disdyakistriacontahedron", + "Icosahedral (I[9])", + "", + "", + 75, 98}, + + /* 65 */ {"|5/3 2 5", "Inverted Snub Dodecadodecahedron", + "Medial Inverted Pentagonal Hexecontahedron", + "Icosahedral (I[9])", + "", + "", + 76, 114}, + /* (5/3 5/2 3) (I10a) */ + + /* 66 */ {"5/2 3|5/3", "Great Dodecicosidodecahedron", + "Great Dodecacronic Hexecontahedron", + "Icosahedral (I[10a])", + "", + "", + 77, 99}, + + /* 67 */ {"5/3 5/2|3", "Small Dodecahemicosahedron", + "Small Dodecahemicosacron", + "Icosahedral (I[10a])", + "", + "", + 78, 100}, + + /* 68 */ {"5/3 5/2 3|", "Great Dodecicosahedron", + "Great Dodecicosacron", + "Icosahedral (I[10a])", + "", + "", + 79, 101}, + + /* 69 */ {"|5/3 5/2 3", "Great Snub Dodecicosidodecahedron", + "Great Hexagonal Hexecontahedron", + "Icosahedral (I[10a])", + "", + "", + 80, 115}, + /* (5/4 3 5) (I10b) */ + + /* 70 */ {"5/4 5|3", "Great Dodecahemicosahedron", + "Great Dodecahemicosacron", + "Icosahedral (I[10b])", + "", + "", + 81, 102}, + /* (5/3 2 3) (I13) */ + + /* 71 */ {"2 3|5/3", "Great Stellated Truncated Dodecahedron", + "Great Triakisicosahedron", + "Icosahedral (I[13])", + "", + "", + 83, 104}, + + /* 72 */ {"5/3 3|2", "Great Rhombicosidodecahedron", + "Great Deltoidal Hexecontahedron", + "Icosahedral (I[13])", + "", + "", + 84, 105}, + + /* 73 */ {"5/3 2 3|", "Great Truncated Icosidodecahedron", + "Great Disdyakistriacontahedron", + "Icosahedral (I[13])", + "", + "", + 87, 108}, + + /* 74 */ {"|5/3 2 3", "Great Inverted Snub Icosidodecahedron", + "Great Inverted Pentagonal Hexecontahedron", + "Icosahedral (I[13])", + "", + "", + 88, 116}, + /* (5/3 5/3 5/2) (I18a) */ + + /* 75 */ {"5/3 5/2|5/3", "Great Dodecahemidodecahedron", + "Great Dodecahemidodecacron", + "Icosahedral (I[18a])", + "", + "", + 86, 107}, + /* (3/2 5/3 3) (I18b) */ + + /* 76 */ {"3/2 3|5/3", "Great Icosihemidodecahedron", + "Great Icosihemidodecacron", + "Icosahedral (I[18b])", + "", + "", + 85, 106}, + /* (3/2 3/2 5/3) (I22) */ + + /* 77 */ {"|3/2 3/2 5/2","Small Retrosnub Icosicosidodecahedron", + "Small Hexagrammic Hexecontahedron", + "Icosahedral (I[22])", + "", + "", + 91, 118}, + /* (3/2 5/3 2) (I23) */ + + /* 78 */ {"3/2 5/3 2|", "Great Rhombidodecahedron", + "Great Rhombidodecacron", + "Icosahedral (I[23])", + "", + "", + 89, 109}, + + /* 79 */ {"|3/2 5/3 2", "Great Retrosnub Icosidodecahedron", + "Great Pentagrammic Hexecontahedron", + "Icosahedral (I[23])", + "", + "", + 90, 117}, + + /**************************************************************************** + * Last But Not Least + ***************************************************************************/ + + /* 80 */ {"3/2 5/3 3 5/2", "Great Dirhombicosidodecahedron", + "Great Dirhombicosidodecacron", + "Non-Wythoffian", + "", + "", + 92, 119} +}; + +static int last_uniform = sizeof (uniform) / sizeof (uniform[0]); + + + +static int unpacksym(char *sym, Polyhedron *P); +static int moebius(Polyhedron *P); +static int decompose(Polyhedron *P); +static int guessname(Polyhedron *P); +static int newton(Polyhedron *P, int need_approx); +static int exceptions(Polyhedron *P); +static int count(Polyhedron *P); +static int configuration(Polyhedron *P); +static int vertices(Polyhedron *P); +static int faces(Polyhedron *P); +static int edgelist(Polyhedron *P); + +static Polyhedron * +kaleido(char *sym, int need_coordinates, int need_edgelist, int need_approx, + int just_list) +{ + Polyhedron *P; + /* + * Allocate a Polyhedron structure P. + */ + if (!(P = polyalloc())) + return 0; + /* + * Unpack input symbol into P. + */ + if (!unpacksym(sym, P)) + return 0; + /* + * Find Mebius triangle, its density and Euler characteristic. + */ + if (!moebius(P)) + return 0; + /* + * Decompose Schwarz triangle. + */ + if (!decompose(P)) + return 0; + /* + * Find the names of the polyhedron and its dual. + */ + if (!guessname(P)) + return 0; + if (just_list) + return P; + /* + * Solve Fundamental triangles, optionally printing approximations. + */ + if (!newton(P,need_approx)) + return 0; + /* + * Deal with exceptional polyhedra. + */ + if (!exceptions(P)) + return 0; + /* + * Count edges and faces, update density and characteristic if needed. + */ + if (!count(P)) + return 0; + /* + * Generate printable vertex configuration. + */ + if (!configuration(P)) + return 0; + /* + * Compute coordinates. + */ + if (!need_coordinates && !need_edgelist) + return P; + if (!vertices(P)) + return 0; + if (!faces (P)) + return 0; + /* + * Compute edgelist. + */ + if (!need_edgelist) + return P; + if (!edgelist(P)) + return 0; + return P; +} + +/* + * Allocate a blank Polyhedron structure and initialize some of its nonblank + * fields. + * + * Array and matrix field are allocated when needed. + */ +static Polyhedron * +polyalloc() +{ + Polyhedron *P; + Calloc(P, 1, Polyhedron); + P->index = -1; + P->even = -1; + P->K = 2; + return P; +} + +/* + * Free the struture allocated by polyalloc(), as well as all the array and + * matrix fields. + */ +static void +polyfree(Polyhedron *P) +{ + Free(P->Fi); + Free(P->n); + Free(P->m); + Free(P->gamma); + Free(P->rot); + Free(P->snub); + Free(P->firstrot); + Free(P->anti); + Free(P->ftype); + Free(P->polyform); + Free(P->config); + if (P->index < 0) { + Free(P->name); + Free(P->dual_name); + } + Free(P->v); + Free(P->f); + Matfree(P->e, 2); + Matfree(P->dual_e, 2); + Matfree(P->incid, P->M); + Matfree(P->adj, P->M); + free(P); +} + +static void * +matalloc(int rows, int row_size) +{ + void **mat; + int i = 0; + if (!(mat = malloc(rows * sizeof (void *)))) + return 0; + while ((mat[i] = malloc(row_size)) && ++i < rows) + ; + if (i == rows) + return (void *)mat; + while (--i >= 0) + free(mat[i]); + free(mat); + return 0; +} + +static void +matfree(void *mat, int rows) +{ + while (--rows >= 0) + free(((void **)mat)[rows]); + free(mat); +} + +/* + * compute the mathematical modulus function. + */ +static int +mod (int i, int j) +{ + return (i%=j)>=0?i:j<0?i-j:i+j; +} + + +/* + * Find the numerator and the denominator using the Euclidean algorithm. + */ +static void +frac(double x) +{ + static const Fraction zero = {0,1}, inf = {1,0}; + Fraction r0, r; + long f; + double s = x; + r = zero; + frax = inf; + for (;;) { + if (fabs(s) > (double) MAXLONG) + return; + f = (long) floor (s); + r0 = r; + r = frax; + frax.n = frax.n * f + r0.n; + frax.d = frax.d * f + r0.d; + if (x == (double)frax.n/(double)frax.d) + return; + s = 1 / (s - f); + } +} + + +/* + * Unpack input symbol: Wythoff symbol or an index to uniform[]. The symbol is + * a # followed by a number, or a three fractions and a bar in some order. We + * allow no bars only if it result from the input symbol #80. + */ +static int +unpacksym(char *sym, Polyhedron *P) +{ + int i = 0, n, d, bars = 0; + char c; + while ((c = *sym++) && isspace(c)) + ; + if (!c) Err("no data"); + if (c == '#') { + while ((c = *sym++) && isspace(c)) + ; + if (!c) + Err("no digit after #"); + if (!isdigit(c)) + Err("not a digit"); + n = c - '0'; + while ((c = *sym++) && isdigit(c)) + n = n * 10 + c - '0'; + if (!n) + Err("zero index"); + if (n > last_uniform) + Err("index too big"); + sym--; + while ((c = *sym++) && isspace(c)) + ; + if (c) + Err("data exceeded"); + sym = uniform[P->index = n - 1].Wythoff; + } else + sym--; + + for (;;) { + while ((c = *sym++) && isspace(c)) + ; + if (!c) { + if (i == 4 && (bars || P->index == last_uniform - 1)) + return 1; + if (!bars) + Err("no bars"); + Err("not enough fractions"); + } + if (i == 4) + Err("data exceeded"); + if (c == '|'){ + if (++bars > 1) + Err("too many bars"); + P->p[i++] = 0; + continue; + } + if (!isdigit(c)) + Err("not a digit"); + n = c - '0'; + while ((c = *sym++) && isdigit(c)) + n = n * 10 + c - '0'; + if (c && isspace (c)) + while ((c = *sym++) && isspace(c)) + ; + if (c != '/') { + sym--; + if ((P->p[i++] = n) <= 1) + Err("fraction<=1"); + continue; + } + while ((c = *sym++) && isspace(c)) + ; + if (!c || !isdigit(c)) + return 0; + d = c - '0'; + while ((c = *sym++) && isdigit(c)) + d = d * 10 + c - '0'; + if (!d) + Err("zero denominator"); + sym--; + if ((P->p[i++] = (double) n / d) <= 1) + Err("fraction<=1"); + } +} + +/* + * Using Wythoff symbol (p|qr, pq|r, pqr| or |pqr), find the Moebius triangle + * (2 3 K) (or (2 2 n)) of the Schwarz triangle (pqr), the order g of its + * symmetry group, its Euler characteristic chi, and its covering density D. + * g is the number of copies of (2 3 K) covering the sphere, i.e., + * + * g * pi * (1/2 + 1/3 + 1/K - 1) = 4 * pi + * + * D is the number of times g copies of (pqr) cover the sphere, i.e. + * + * D * 4 * pi = g * pi * (1/p + 1/q + 1/r - 1) + * + * chi is V - E + F, where F = g is the number of triangles, E = 3*g/2 is the + * number of triangle edges, and V = Vp+ Vq+ Vr, with Vp = g/(2*np) being the + * number of vertices with angle pi/p (np is the numerator of p). + */ +static int +moebius(Polyhedron *P) +{ + int twos = 0, j, len = 1; + /* + * Arrange Wythoff symbol in a presentable form. In the same time check the + * restrictions on the three fractions: They all have to be greater then one, + * and the numerators 4 or 5 cannot occur together. We count the ocurrences + * of 2 in `two', and save the largest numerator in `P->K', since they + * reflect on the symmetry group. + */ + P->K = 2; + if (P->index == last_uniform - 1) { + Malloc(P->polyform, ++len, char); + strcpy(P->polyform, "|"); + } else + Calloc(P->polyform, len, char); + for (j = 0; j < 4; j++) { + if (P->p[j]) { + char *s; + Sprintfrac(s, P->p[j]); + if (j && P->p[j-1]) { + Realloc(P->polyform, len += strlen (s) + 1, char); + strcat(P->polyform, " "); + } else + Realloc (P->polyform, len += strlen (s), char); + strcat(P->polyform, s); + free(s); + if (P->p[j] != 2) { + int k; + if ((k = numerator (P->p[j])) > P->K) { + if (P->K == 4) + break; + P->K = k; + } else if (k < P->K && k == 4) + break; + } else + twos++; + } else { + Realloc(P->polyform, ++len, char); + strcat(P->polyform, "|"); + } + } + /* + * Find the symmetry group P->K (where 2, 3, 4, 5 represent the dihedral, + * tetrahedral, octahedral and icosahedral groups, respectively), and its + * order P->g. + */ + if (twos >= 2) {/* dihedral */ + P->g = 4 * P->K; + P->K = 2; + } else { + if (P->K > 5) + Err("numerator too large"); + P->g = 24 * P->K / (6 - P->K); + } + /* + * Compute the nominal density P->D and Euler characteristic P->chi. + * In few exceptional cases, these values will be modified later. + */ + if (P->index != last_uniform - 1) { + int i; + P->D = P->chi = - P->g; + for (j = 0; j < 4; j++) if (P->p[j]) { + P->chi += i = P->g / numerator(P->p[j]); + P->D += i * denominator(P->p[j]); + } + P->chi /= 2; + P->D /= 4; + if (P->D <= 0) + Err("nonpositive density"); + } + return 1; +} + +/* + * Decompose Schwarz triangle into N right triangles and compute the vertex + * count V and the vertex valency M. V is computed from the number g of + * Schwarz triangles in the cover, divided by the number of triangles which + * share a vertex. It is halved for one-sided polyhedra, because the + * kaleidoscopic construction really produces a double orientable covering of + * such polyhedra. All q' q|r are of the "hemi" type, i.e. have equatorial {2r} + * faces, and therefore are (except 3/2 3|3 and the dihedra 2 2|r) one-sided. A + * well known example is 3/2 3|4, the "one-sided heptahedron". Also, all p q r| + * with one even denominator have a crossed parallelogram as a vertex figure, + * and thus are one-sided as well. + */ +static int +decompose(Polyhedron *P) +{ + int j, J, *s, *t; + if (!P->p[1]) { /* p|q r */ + P->N = 2; + P->M = 2 * numerator(P->p[0]); + P->V = P->g / P->M; + Malloc(P->n, P->N, double); + Malloc(P->m, P->N, double); + Malloc(P->rot, P->M, int); + s = P->rot; + for (j = 0; j < 2; j++) { + P->n[j] = P->p[j+2]; + P->m[j] = P->p[0]; + } + for (j = P->M / 2; j--;) { + *s++ = 0; + *s++ = 1; + } + } else if (!P->p[2]) { /* p q|r */ + P->N = 3; + P->M = 4; + P->V = P->g / 2; + Malloc(P->n, P->N, double); + Malloc(P->m, P->N, double); + Malloc(P->rot, P->M, int); + s = P->rot; + P->n[0] = 2 * P->p[3]; + P->m[0] = 2; + for (j = 1; j < 3; j++) { + P->n[j] = P->p[j-1]; + P->m[j] = 1; + *s++ = 0; + *s++ = j; + } + if (fabs(P->p[0] - compl (P->p[1])) < DBL_EPSILON) {/* p = q' */ + /* P->p[0]==compl(P->p[1]) should work. However, MSDOS + * yeilds a 7e-17 difference! Reported by Jim Buddenhagen + * */ + P->hemi = 1; + P->D = 0; + if (P->p[0] != 2 && !(P->p[3] == 3 && (P->p[0] == 3 || + P->p[1] == 3))) { + P->onesided = 1; + P->V /= 2; + P->chi /= 2; + } + } + } else if (!P->p[3]) { /* p q r| */ + P->M = P->N = 3; + P->V = P->g; + Malloc(P->n, P->N, double); + Malloc(P->m, P->N, double); + Malloc(P->rot, P->M, int); + s = P->rot; + for (j = 0; j < 3; j++) { + if (!(denominator(P->p[j]) % 2)) { + /* what happens if there is more then one even denominator? */ + if (P->p[(j+1)%3] != P->p[(j+2)%3]) { /* needs postprocessing */ + P->even = j;/* memorize the removed face */ + P->chi -= P->g / numerator(P->p[j]) / 2; + P->onesided = 1; + P->D = 0; + } else {/* for p = q we get a double 2 2r|p */ + /* noted by Roman Maeder for 4 4 3/2| */ + /* Euler characteristic is still wrong */ + P->D /= 2; + } + P->V /= 2; + } + P->n[j] = 2 * P->p[j]; + P->m[j] = 1; + *s++ = j; + } + } else { /* |p q r - snub polyhedron */ + P->N = 4; + P->M = 6; + P->V = P->g / 2;/* Only "white" triangles carry a vertex */ + Malloc(P->n, P->N, double); + Malloc(P->m, P->N, double); + Malloc(P->rot, P->M, int); + Malloc(P->snub, P->M, int); + s = P->rot; + t = P->snub; + P->m[0] = P->n[0] = 3; + for (j = 1; j < 4; j++) { + P->n[j] = P->p[j]; + P->m[j] = 1; + *s++ = 0; + *s++ = j; + *t++ = 1; + *t++ = 0; + } + } + /* + * Sort the fundamental triangles (using bubble sort) according to decreasing + * n[i], while pushing the trivial triangles (n[i] = 2) to the end. + */ + J = P->N - 1; + while (J) { + int last; + last = J; + J = 0; + for (j = 0; j < last; j++) { + if ((P->n[j] < P->n[j+1] || P->n[j] == 2) && P->n[j+1] != 2) { + int i; + double temp; + temp = P->n[j]; + P->n[j] = P->n[j+1]; + P->n[j+1] = temp; + temp = P->m[j]; + P->m[j] = P->m[j+1]; + P->m[j+1] = temp; + for (i = 0; i < P->M; i++) { + if (P->rot[i] == j) + P->rot[i] = j+1; + else if (P->rot[i] == j+1) + P->rot[i] = j; + } + if (P->even != -1) { + if (P->even == j) + P->even = j+1; + else if (P->even == j+1) + P->even = j; + } + J = j; + } + } + } + /* + * Get rid of repeated triangles. + */ + for (J = 0; J < P->N && P->n[J] != 2;J++) { + int k, i; + for (j = J+1; j < P->N && P->n[j]==P->n[J]; j++) + P->m[J] += P->m[j]; + k = j - J - 1; + if (k) { + for (i = j; i < P->N; i++) { + P->n[i - k] = P->n[i]; + P->m[i - k] = P->m[i]; + } + P->N -= k; + for (i = 0; i < P->M; i++) { + if (P->rot[i] >= j) + P->rot[i] -= k; + else if (P->rot[i] > J) + P->rot[i] = J; + } + if (P->even >= j) + P->even -= k; + } + } + /* + * Get rid of trivial triangles. + */ + if (!J) + J = 1; /* hosohedron */ + if (J < P->N) { + int i; + P->N = J; + for (i = 0; i < P->M; i++) { + if (P->rot[i] >= P->N) { + for (j = i + 1; j < P->M; j++) { + P->rot[j-1] = P->rot[j]; + if (P->snub) + P->snub[j-1] = P->snub[j]; + } + P->M--; + } + } + } + /* + * Truncate arrays + */ + Realloc(P->n, P->N, double); + Realloc(P->m, P->N, double); + Realloc(P->rot, P->M, int); + if (P->snub) + Realloc(P->snub, P->M, int); + return 1; +} + + +static int dihedral(Polyhedron *P, char *name, char *dual_name); + + +/* + * Get the polyhedron name, using standard list or guesswork. Ideally, we + * should try to locate the Wythoff symbol in the standard list (unless, of + * course, it is dihedral), after doing few normalizations, such as sorting + * angles and splitting isoceles triangles. + */ +static int +guessname(Polyhedron *P) +{ + if (P->index != -1) {/* tabulated */ + P->name = uniform[P->index].name; + P->dual_name = uniform[P->index].dual; + P->group = uniform[P->index].group; + P->class = uniform[P->index].class; + P->dual_class = uniform[P->index].dual_class; + return 1; + } else if (P->K == 2) {/* dihedral nontabulated */ + if (!P->p[0]) { + if (P->N == 1) { + Malloc(P->name, sizeof ("Octahedron"), char); + Malloc(P->dual_name, sizeof ("Cube"), char); + strcpy(P->name, "Octahedron"); + strcpy(P->dual_name, "Cube"); + return 1; + } + P->gon = P->n[0] == 3 ? P->n[1] : P->n[0]; + if (P->gon >= 2) + return dihedral(P, "Antiprism", "Deltohedron"); + else + return dihedral(P, "Crossed Antiprism", "Concave Deltohedron"); + } else if (!P->p[3] || + (!P->p[2] && + P->p[3] == 2)) { + if (P->N == 1) { + Malloc(P->name, sizeof("Cube"), char); + Malloc(P->dual_name, sizeof("Octahedron"), char); + strcpy(P->name, "Cube"); + strcpy(P->dual_name, "Octahedron"); + return 1; + } + P->gon = P->n[0] == 4 ? P->n[1] : P->n[0]; + return dihedral(P, "Prism", "Dipyramid"); + } else if (!P->p[1] && P->p[0] != 2) { + P->gon = P->m[0]; + return dihedral(P, "Hosohedron", "Dihedron"); + } else { + P->gon = P->n[0]; + return dihedral(P, "Dihedron", "Hosohedron"); + } + } else {/* other nontabulated */ + static const char *pre[] = {"Tetr", "Oct", "Icos"}; + Malloc(P->name, 50, char); + Malloc(P->dual_name, 50, char); + sprintf(P->name, "%sahedral ", pre[P->K - 3]); + if (P->onesided) + strcat (P->name, "One-Sided "); + else if (P->D == 1) + strcat(P->name, "Convex "); + else + strcat(P->name, "Nonconvex "); + strcpy(P->dual_name, P->name); + strcat(P->name, "Isogonal Polyhedron"); + strcat(P->dual_name, "Isohedral Polyhedron"); + Realloc(P->name, strlen (P->name) + 1, char); + Realloc(P->dual_name, strlen (P->dual_name) + 1, char); + return 1; + } +} + +static int +dihedral(Polyhedron *P, char *name, char *dual_name) +{ + char *s; + int i; + Sprintfrac(s, P->gon < 2 ? compl (P->gon) : P->gon); + i = strlen(s) + sizeof ("-gonal "); + Malloc(P->name, i + strlen (name), char); + Malloc(P->dual_name, i + strlen (dual_name), char); + sprintf(P->name, "%s-gonal %s", s, name); + sprintf(P->dual_name, "%s-gonal %s", s, dual_name); + free(s); + return 1; +} + +/* + * Solve the fundamental right spherical triangles. + * If need_approx is set, print iterations on standard error. + */ +static int +newton(Polyhedron *P, int need_approx) +{ + /* + * First, we find initial approximations. + */ + int j; + double cosa; + Malloc(P->gamma, P->N, double); + if (P->N == 1) { + P->gamma[0] = M_PI / P->m[0]; + return 1; + } + for (j = 0; j < P->N; j++) + P->gamma[j] = M_PI / 2 - M_PI / P->n[j]; + errno = 0; /* may be non-zero from some reason */ + /* + * Next, iteratively find closer approximations for gamma[0] and compute + * other gamma[j]'s from Napier's equations. + */ + if (need_approx) + fprintf(stderr, "Solving %s\n", P->polyform); + for (;;) { + double delta = M_PI, sigma = 0; + for (j = 0; j < P->N; j++) { + if (need_approx) + fprintf(stderr, "%-20.15f", P->gamma[j]); + delta -= P->m[j] * P->gamma[j]; + } + if (need_approx) + printf("(%g)\n", delta); + if (fabs(delta) < 11 * DBL_EPSILON) + return 1; + /* On a RS/6000, fabs(delta)/DBL_EPSILON may occilate between 8 and + * 10. Reported by David W. Sanderson */ + for (j = 0; j < P->N; j++) + sigma += P->m[j] * tan(P->gamma[j]); + P->gamma[0] += delta * tan(P->gamma[0]) / sigma; + if (P->gamma[0] < 0 || P->gamma[0] > M_PI) + Err("gamma out of bounds"); + cosa = cos(M_PI / P->n[0]) / sin(P->gamma[0]); + for (j = 1; j < P->N; j++) + P->gamma[j] = asin(cos(M_PI / P->n[j]) / cosa); + if (errno) + Err(strerror(errno)); + } +} + +/* + * Postprocess pqr| where r has an even denominator (cf. Coxeter &al. Sec.9). + * Remove the {2r} and add a retrograde {2p} and retrograde {2q}. + */ +static int +exceptions(Polyhedron *P) +{ + int j; + if (P->even != -1) { + P->M = P->N = 4; + Realloc(P->n, P->N, double); + Realloc(P->m, P->N, double); + Realloc(P->gamma, P->N, double); + Realloc(P->rot, P->M, int); + for (j = P->even + 1; j < 3; j++) { + P->n[j-1] = P->n[j]; + P->gamma[j-1] = P->gamma[j]; + } + P->n[2] = compl(P->n[1]); + P->gamma[2] = - P->gamma[1]; + P->n[3] = compl(P->n[0]); + P->m[3] = 1; + P->gamma[3] = - P->gamma[0]; + P->rot[0] = 0; + P->rot[1] = 1; + P->rot[2] = 3; + P->rot[3] = 2; + } + + /* + * Postprocess the last polyhedron |3/2 5/3 3 5/2 by taking a |5/3 3 5/2, + * replacing the three snub triangles by four equatorial squares and adding + * the missing {3/2} (retrograde triangle, cf. Coxeter &al. Sec. 11). + */ + if (P->index == last_uniform - 1) { + P->N = 5; + P->M = 8; + Realloc(P->n, P->N, double); + Realloc(P->m, P->N, double); + Realloc(P->gamma, P->N, double); + Realloc(P->rot, P->M, int); + Realloc(P->snub, P->M, int); + P->hemi = 1; + P->D = 0; + for (j = 3; j; j--) { + P->m[j] = 1; + P->n[j] = P->n[j-1]; + P->gamma[j] = P->gamma[j-1]; + } + P->m[0] = P->n[0] = 4; + P->gamma[0] = M_PI / 2; + P->m[4] = 1; + P->n[4] = compl(P->n[1]); + P->gamma[4] = - P->gamma[1]; + for (j = 1; j < 6; j += 2) P->rot[j]++; + P->rot[6] = 0; + P->rot[7] = 4; + P->snub[6] = 1; + P->snub[7] = 0; + } + return 1; +} + +/* + * Compute edge and face counts, and update D and chi. Update D in the few + * cases the density of the polyhedron is meaningful but different than the + * density of the corresponding Schwarz triangle (cf. Coxeter &al., p. 418 and + * p. 425). + * In these cases, spherical faces of one type are concave (bigger than a + * hemisphere), and the actual density is the number of these faces less the + * computed density. Note that if j != 0, the assignment gamma[j] = asin(...) + * implies gamma[j] cannot be obtuse. Also, compute chi for the only + * non-Wythoffian polyhedron. + */ +static int +count(Polyhedron *P) +{ + int j, temp; + Malloc(P->Fi, P->N, int); + for (j = 0; j < P->N; j++) { + P->E += temp = P->V * numerator(P->m[j]); + P->F += P->Fi[j] = temp / numerator(P->n[j]); + } + P->E /= 2; + if (P->D && P->gamma[0] > M_PI / 2) + P->D = P->Fi[0] - P->D; + if (P->index == last_uniform - 1) + P->chi = P->V - P->E + P->F; + return 1; +} + +/* + * Generate a printable vertex configuration symbol. + */ +static int +configuration(Polyhedron *P) +{ + int j, len = 2; + for (j = 0; j < P->M; j++) { + char *s; + Sprintfrac(s, P->n[P->rot[j]]); + len += strlen (s) + 2; + if (!j) { + Malloc(P->config, len, char); +/* strcpy(P->config, "(");*/ + strcpy(P->config, ""); + } else { + Realloc(P->config, len, char); + strcat(P->config, ", "); + } + strcat(P->config, s); + free(s); + } +/* strcat (P->config, ")");*/ + if ((j = denominator (P->m[0])) != 1) { + char s[MAXDIGITS + 2]; + sprintf(s, "/%d", j); + Realloc(P->config, len + strlen (s), char); + strcat(P->config, s); + } + return 1; +} + +/* + * Compute polyhedron vertices and vertex adjecency lists. + * The vertices adjacent to v[i] are v[adj[0][i], v[adj[1][i], ... + * v[adj[M-1][i], ordered counterclockwise. The algorith is a BFS on the + * vertices, in such a way that the vetices adjacent to a givem vertex are + * obtained from its BFS parent by a cyclic sequence of rotations. firstrot[i] + * points to the first rotaion in the sequence when applied to v[i]. Note that + * for non-snub polyhedra, the rotations at a child are opposite in sense when + * compared to the rotations at the parent. Thus, we fill adj[*][i] from the + * end to signify clockwise rotations. The firstrot[] array is not needed for + * display thus it is freed after being used for face computations below. + */ +static int +vertices(Polyhedron *P) +{ + int i, newV = 2; + double cosa; + Malloc(P->v, P->V, Vector); + Matalloc(P->adj, P->M, P->V, int); + Malloc(P->firstrot, P->V, int); /* temporary , put in Polyhedron + structure so that may be freed on + error */ + cosa = cos(M_PI / P->n[0]) / sin(P->gamma[0]); + P->v[0].x = 0; + P->v[0].y = 0; + P->v[0].z = 1; + P->firstrot[0] = 0; + P->adj[0][0] = 1; + P->v[1].x = 2 * cosa * sqrt(1 - cosa * cosa); + P->v[1].y = 0; + P->v[1].z = 2 * cosa * cosa - 1; + if (!P->snub) { + P->firstrot[1] = 0; + P->adj[0][1] = -1;/* start the other side */ + P->adj[P->M-1][1] = 0; + } else { + P->firstrot[1] = P->snub[P->M-1] ? 0 : P->M-1 ; + P->adj[0][1] = 0; + } + for (i = 0; i < newV; i++) { + int j, k; + int last, one, start, limit; + if (P->adj[0][i] == -1) { + one = -1; start = P->M-2; limit = -1; + } else { + one = 1; start = 1; limit = P->M; + } + k = P->firstrot[i]; + for (j = start; j != limit; j += one) { + Vector temp; + int J; + temp = rotate (P->v[P->adj[j-one][i]], P->v[i], + one * 2 * P->gamma[P->rot[k]]); + for (J=0; Jv[J],temp,BIG_EPSILON); J++) + ;/* noop */ + P->adj[j][i] = J; + last = k; + if (++k == P->M) + k = 0; + if (J == newV) { /* new vertex */ + if (newV == P->V) Err ("too many vertices"); + P->v[newV++] = temp; + if (!P->snub) { + P->firstrot[J] = k; + if (one > 0) { + P->adj[0][J] = -1; + P->adj[P->M-1][J] = i; + } else { + P->adj[0][J] = i; + } + } else { + P->firstrot[J] = !P->snub[last] ? last : + !P->snub[k] ? (k+1)%P->M : k ; + P->adj[0][J] = i; + } + } + } + } + return 1; +} + +/* + * Compute polyhedron faces (dual vertices) and incidence matrices. + * For orientable polyhedra, we can distinguish between the two faces meeting + * at a given directed edge and identify the face on the left and the face on + * the right, as seen from the outside. For one-sided polyhedra, the vertex + * figure is a papillon (in Coxeter &al. terminology, a crossed parallelogram) + * and the two faces meeting at an edge can be identified as the side face + * (n[1] or n[2]) and the diagonal face (n[0] or n[3]). + */ +static int +faces(Polyhedron *P) +{ + int i, newF = 0; + Malloc (P->f, P->F, Vector); + Malloc (P->ftype, P->F, int); + Matalloc (P->incid, P->M, P->V, int); + P->minr = 1 / fabs (tan (M_PI / P->n[P->hemi]) * tan (P->gamma[P->hemi])); + for (i = P->M; --i>=0;) { + int j; + for (j = P->V; --j>=0;) + P->incid[i][j] = -1; + } + for (i = 0; i < P->V; i++) { + int j; + for (j = 0; j < P->M; j++) { + int i0, J; + int pap=0;/* papillon edge type */ + if (P->incid[j][i] != -1) + continue; + P->incid[j][i] = newF; + if (newF == P->F) + Err("too many faces"); + P->f[newF] = pole(P->minr, P->v[i], P->v[P->adj[j][i]], + P->v[P->adj[mod(j + 1, P->M)][i]]); + P->ftype[newF] = P->rot[mod(P->firstrot[i] + ((P->adj[0][i] < + P->adj[P->M - 1][i]) + ? j + : -j - 2), + P->M)]; + if (P->onesided) + pap = (P->firstrot[i] + j) % 2; + i0 = i; + J = j; + for (;;) { + int k; + k = i0; + if ((i0 = P->adj[J][k]) == i) break; + for (J = 0; J < P->M && P->adj[J][i0] != k; J++) + ;/* noop */ + if (J == P->M) + Err("too many faces"); + if (P->onesided && (J + P->firstrot[i0]) % 2 == pap) { + P->incid [J][i0] = newF; + if (++J >= P->M) + J = 0; + } else { + if (--J < 0) + J = P->M - 1; + P->incid [J][i0] = newF; + } + } + newF++; + } + } + Free(P->firstrot); + Free(P->rot); + Free(P->snub); + return 1; +} + +/* + * Compute edge list and graph polyhedron and dual. + * If the polyhedron is of the "hemi" type, each edge has one finite vertex and + * one ideal vertex. We make sure the latter is always the out-vertex, so that + * the edge becomes a ray (half-line). Each ideal vertex is represented by a + * unit Vector, and the direction of the ray is either parallel or + * anti-parallel this Vector. We flag this in the array P->anti[E]. + */ +static int +edgelist(Polyhedron *P) +{ + int i, j, *s, *t, *u; + Matalloc(P->e, 2, P->E, int); + Matalloc(P->dual_e, 2, P->E, int); + s = P->e[0]; + t = P->e[1]; + for (i = 0; i < P->V; i++) + for (j = 0; j < P->M; j++) + if (i < P->adj[j][i]) { + *s++ = i; + *t++ = P->adj[j][i]; + } + s = P->dual_e[0]; + t = P->dual_e[1]; + if (!P->hemi) + P->anti = 0; + else + Malloc(P->anti, P->E, int); + u = P->anti; + for (i = 0; i < P->V; i++) + for (j = 0; j < P->M; j++) + if (i < P->adj[j][i]) + { + if (!u) { + *s++ = P->incid[mod(j-1,P->M)][i]; + *t++ = P->incid[j][i]; + } else { + if (P->ftype[P->incid[j][i]]) { + *s = P->incid[j][i]; + *t = P->incid[mod(j-1,P->M)][i]; + } else { + *s = P->incid[mod(j-1,P->M)][i]; + *t = P->incid[j][i]; + } + *u++ = dot(P->f[*s++], P->f[*t++]) > 0; + } + } + return 1; +} + + +static char * +sprintfrac(double x) +{ + char *s; + frac (x); + if (!frax.d) { + Malloc(s, sizeof ("infinity"), char); + strcpy(s, "infinity"); + } else if (frax.d == 1) { + char n[MAXDIGITS + 1]; + sprintf(n, "%ld", frax.n); + Malloc(s, strlen (n) + 1, char); + strcpy(s, n); + } else { + char n[MAXDIGITS + 1], d[MAXDIGITS + 1]; + sprintf(n, "%ld", frax.n); + sprintf(d, "%ld", frax.d); + Malloc(s, strlen (n) + strlen (d) + 2, char); + sprintf(s, "%s/%s", n, d); + } + return s; +} + +static double +dot(Vector a, Vector b) +{ + return a.x * b.x + a.y * b.y + a.z * b.z; +} + +static Vector +scale(double k, Vector a) +{ + a.x *= k; + a.y *= k; + a.z *= k; + return a; +} + +static Vector +diff(Vector a, Vector b) +{ + a.x -= b.x; + a.y -= b.y; + a.z -= b.z; + return a; +} + +static Vector +cross(Vector a, Vector b) +{ + Vector p; + p.x = a.y * b.z - a.z * b.y; + p.y = a.z * b.x - a.x * b.z; + p.z = a.x * b.y - a.y * b.x; + return p; +} + +static Vector +sum(Vector a, Vector b) +{ + a.x += b.x; + a.y += b.y; + a.z += b.z; + return a; +} + +static Vector +sum3(Vector a, Vector b, Vector c) +{ + a.x += b.x + c.x; + a.y += b.y + c.y; + a.z += b.z + c.z; + return a; +} + +static Vector +rotate(Vector vertex, Vector axis, double angle) +{ + Vector p; + p = scale(dot (axis, vertex), axis); + return sum3(p, scale(cos(angle), diff(vertex, p)), + scale(sin(angle), cross(axis, vertex))); +} + +static Vector x, y, z; + +/* + * rotate the standard frame + */ +static void +rotframe(double azimuth, double elevation, double angle) +{ + static const Vector X = {1,0,0}, Y = {0,1,0}, Z = {0,0,1}; + Vector axis; + + axis = rotate(rotate (X, Y, elevation), Z, azimuth); + x = rotate(X, axis, angle); + y = rotate(Y, axis, angle); + z = rotate(Z, axis, angle); +} + +/* + * rotate an array of n Vectors + */ +static void +rotarray(Vector *new, Vector *old, int n) +{ + while (n--) { + *new++ = sum3(scale(old->x, x), scale(old->y, y), scale(old->z, z)); + old++; + } +} + +static int +same(Vector a, Vector b, double epsilon) +{ + return fabs(a.x - b.x) < epsilon && fabs(a.y - b.y) < epsilon + && fabs(a.z - b.z) < epsilon; +} + +/* + * Compute the polar reciprocal of the plane containing a, b and c: + * + * If this plane does not contain the origin, return p such that + * dot(p,a) = dot(p,b) = dot(p,b) = r. + * + * Otherwise, return p such that + * dot(p,a) = dot(p,b) = dot(p,c) = 0 + * and + * dot(p,p) = 1. + */ +static Vector +pole(double r, Vector a, Vector b, Vector c) +{ + Vector p; + double k; + p = cross(diff(b, a), diff(c, a)); + k = dot(p, a); + if (fabs(k) < 1e-6) + return scale(1 / sqrt(dot(p, p)), p); + else + return scale(r/ k , p); +} + + +/* output */ + + + + +static void rotframe(double azimuth, double elevation, double angle); +static void rotarray(Vector *new, Vector *old, int n); +static int mod (int i, int j); + + +static void +push_point (polyhedron *p, Vector v) +{ + p->points[p->npoints].x = v.x; + p->points[p->npoints].y = v.y; + p->points[p->npoints].z = v.z; + p->npoints++; +} + +static void +push_face3 (polyhedron *p, int x, int y, int z) +{ + p->faces[p->nfaces].npoints = 3; + Malloc (p->faces[p->nfaces].points, 3, int); + p->faces[p->nfaces].points[0] = x; + p->faces[p->nfaces].points[1] = y; + p->faces[p->nfaces].points[2] = z; + p->nfaces++; +} + +static void +push_face4 (polyhedron *p, int x, int y, int z, int w) +{ + p->faces[p->nfaces].npoints = 4; + Malloc (p->faces[p->nfaces].points, 4, int); + p->faces[p->nfaces].points[0] = x; + p->faces[p->nfaces].points[1] = y; + p->faces[p->nfaces].points[2] = z; + p->faces[p->nfaces].points[3] = w; + p->nfaces++; +} + + + + +static polyhedron * +construct_polyhedron (Polyhedron *P, Vector *v, int V, Vector *f, int F, + char *name, char *dual, char *class, char *star, + double azimuth, double elevation, double freeze) +{ + int i, j, k=0, l, ll, ii, *hit=0, facelets; + + polyhedron *result; + Vector *temp; + + Malloc (result, 1, polyhedron); + memset (result, 0, sizeof(*result)); + + /* + * Rotate polyhedron + */ + rotframe(azimuth, elevation, freeze); + Malloc(temp, V, Vector); + rotarray(temp, v, V); + v = temp; + Malloc(temp, F, Vector); + rotarray(temp, f, F); + f = temp; + + result->number = P->index + 1; + result->name = strdup (name); + result->dual = strdup (dual); + result->wythoff = strdup (P->polyform); + result->config = strdup (P->config); + result->group = strdup (P->group); + result->class = strdup (class); + + /* + * Vertex list + */ + Malloc (result->points, V + F * 13, point); + result->npoints = 0; + + result->nedges = P->E; + result->logical_faces = F; + result->logical_vertices = V; + result->density = P->D; + result->chi = P->chi; + + for (i = 0; i < V; i++) + push_point (result, v[i]); + + /* + * Auxiliary vertices (needed because current VRML browsers cannot handle + * non-simple polygons, i.e., ploygons with self intersections): Each + * non-simple face is assigned an auxiliary vertex. By connecting it to the + * rest of the vertices the face is triangulated. The circum-center is used + * for the regular star faces of uniform polyhedra. The in-center is used for + * the pentagram (#79) and hexagram (#77) of the high-density snub duals, and + * for the pentagrams (#40, #58) and hexagram (#52) of the stellated duals + * with configuration (....)/2. Finally, the self-intersection of the crossed + * parallelogram is used for duals with form p q r| with an even denominator. + * + * This method do not work for the hemi-duals, whose faces are not + * star-shaped and have two self-intersections each. + * + * Thus, for each face we need six auxiliary vertices: The self intersections + * and the terminal points of the truncations of the infinite edges. The + * ideal vertices are listed, but are not used by the face-list. + * + * Note that the face of the last dual (#80) is octagonal, and constists of + * two quadrilaterals of the infinite type. + */ + + if (*star && P->even != -1) + Malloc(hit, F, int); + for (i = 0; i < F; i++) + if ((!*star && + (frac(P->n[P->ftype[i]]), frax.d != 1 && frax.d != frax.n - 1)) || + (*star && + P->K == 5 && + (P->D > 30 || + denominator (P->m[0]) != 1))) { + /* find the center of the face */ + double h; + if (!*star && P->hemi && !P->ftype[i]) + h = 0; + else + h = P->minr / dot(f[i],f[i]); + push_point(result, scale (h, f[i])); + + } else if (*star && P->even != -1) { + /* find the self-intersection of a crossed parallelogram. + * hit is set if v0v1 intersects v2v3*/ + Vector v0, v1, v2, v3, c0, c1, p; + double d0, d1; + v0 = v[P->incid[0][i]]; + v1 = v[P->incid[1][i]]; + v2 = v[P->incid[2][i]]; + v3 = v[P->incid[3][i]]; + d0 = sqrt(dot(diff(v0, v2), diff(v0, v2))); + d1 = sqrt(dot (diff(v1, v3), diff(v1, v3))); + c0 = scale(d1, sum(v0, v2)); + c1 = scale(d0, sum(v1, v3)); + p = scale(0.5 / (d0 + d1), sum(c0, c1)); + push_point (result, p); + p = cross(diff(p, v2), diff(p, v3)); + hit[i] = (dot(p, p) < 1e-6); + } else if (*star && P->hemi && P->index != last_uniform - 1) { + /* find the terminal points of the truncation and the + * self-intersections. + * v23 v0 v21 + * | \ / \ / | + * | v0123 v0321 | + * | / \ / \ | + * v01 v2 v03 + */ + Vector v0, v1, v2, v3, v01, v03, v21, v23, v0123, v0321 ; + Vector u; + double t = 1.5;/* truncation adjustment factor */ + j = !P->ftype[P->incid[0][i]]; + v0 = v[P->incid[j][i]];/* real vertex */ + v1 = v[P->incid[j+1][i]];/* ideal vertex (unit vector) */ + v2 = v[P->incid[j+2][i]];/* real */ + v3 = v[P->incid[(j+3)%4][i]];/* ideal */ + /* compute intersections + * this uses the following linear algebra: + * v0123 = v0 + a v1 = v2 + b v3 + * v0 x v3 + a (v1 x v3) = v2 x v3 + * a (v1 x v3) = (v2 - v0) x v3 + * a (v1 x v3) . (v1 x v3) = (v2 - v0) x v3 . (v1 x v3) + */ + u = cross(v1, v3); + v0123 = sum(v0, scale(dot(cross(diff(v2, v0), v3), u) / dot(u,u), + v1)); + v0321 = sum(v0, scale(dot(cross(diff(v0, v2), v1), u) / dot(u,u), + v3)); + /* compute truncations */ + v01 = sum(v0 , scale(t, diff(v0123, v0))); + v23 = sum(v2 , scale(t, diff(v0123, v2))); + v03 = sum(v0 , scale(t, diff(v0321, v0))); + v21 = sum(v2 , scale(t, diff(v0321, v2))); + + push_point(result, v01); + push_point(result, v23); + push_point(result, v0123); + push_point(result, v03); + push_point(result, v21); + push_point(result, v0321); + + } else if (*star && P->index == last_uniform - 1) { + /* find the terminal points of the truncation and the + * self-intersections. + * v23 v0 v21 + * | \ / \ / | + * | v0123 v0721 | + * | / \ / \ | + * v01 v2 v07 + * + * v65 v4 v67 + * | \ / \ / | + * | v4365 v4567 | + * | / \ / \ | + * v43 v6 v45 + */ + Vector v0, v1, v2, v3, v4, v5, v6, v7, v01, v07, v21, v23; + Vector v43, v45, v65, v67, v0123, v0721, v4365, v4567; + double t = 1.5;/* truncation adjustment factor */ + Vector u; + for (j = 0; j < 8; j++) + if (P->ftype[P->incid[j][i]] == 3) + break; + v0 = v[P->incid[j][i]];/* real {5/3} */ + v1 = v[P->incid[(j+1)%8][i]];/* ideal */ + v2 = v[P->incid[(j+2)%8][i]];/* real {3} */ + v3 = v[P->incid[(j+3)%8][i]];/* ideal */ + v4 = v[P->incid[(j+4)%8][i]];/* real {5/2} */ + v5 = v[P->incid[(j+5)%8][i]];/* ideal */ + v6 = v[P->incid[(j+6)%8][i]];/* real {3/2} */ + v7 = v[P->incid[(j+7)%8][i]];/* ideal */ + /* compute intersections */ + u = cross(v1, v3); + v0123 = sum(v0, scale(dot(cross(diff(v2, v0), v3), u) / dot(u,u), + v1)); + u = cross(v7, v1); + v0721 = sum(v0, scale(dot(cross(diff(v2, v0), v1), u) / dot(u,u), + v7)); + u = cross(v5, v7); + v4567 = sum(v4, scale(dot(cross(diff(v6, v4), v7), u) / dot(u,u), + v5)); + u = cross(v3, v5); + v4365 = sum(v4, scale(dot(cross(diff(v6, v4), v5), u) / dot(u,u), + v3)); + /* compute truncations */ + v01 = sum(v0 , scale(t, diff(v0123, v0))); + v23 = sum(v2 , scale(t, diff(v0123, v2))); + v07 = sum(v0 , scale(t, diff(v0721, v0))); + v21 = sum(v2 , scale(t, diff(v0721, v2))); + v45 = sum(v4 , scale(t, diff(v4567, v4))); + v67 = sum(v6 , scale(t, diff(v4567, v6))); + v43 = sum(v4 , scale(t, diff(v4365, v4))); + v65 = sum(v6 , scale(t, diff(v4365, v6))); + + push_point(result, v01); + push_point(result, v23); + push_point(result, v0123); + push_point(result, v07); + push_point(result, v21); + push_point(result, v0721); + push_point(result, v45); + push_point(result, v67); + push_point(result, v4567); + push_point(result, v43); + push_point(result, v65); + push_point(result, v4365); + } + + /* + * Face list: + * Each face is printed in a separate line, by listing the indices of its + * vertices. In the non-simple case, the polygon is represented by the + * triangulation, each triangle consists of two polyhedron vertices and one + * auxiliary vertex. + */ + Malloc (result->faces, F * 10, face); + result->nfaces = 0; + + ii = V; + facelets = 0; + for (i = 0; i < F; i++) { + if (*star) { + if (P->K == 5 && + (P->D > 30 || + denominator (P->m[0]) != 1)) { + for (j = 0; j < P->M - 1; j++) { + push_face3 (result, P->incid[j][i], P->incid[j+1][i], ii); + facelets++; + } + + push_face3 (result, P->incid[j][i], P->incid[0][i], ii++); + facelets++; + + } else if (P->even != -1) { + if (hit && hit[i]) { + push_face3 (result, P->incid[3][i], P->incid[0][i], ii); + push_face3 (result, P->incid[1][i], P->incid[2][i], ii); + } else { + push_face3 (result, P->incid[0][i], P->incid[1][i], ii); + push_face3 (result, P->incid[2][i], P->incid[3][i], ii); + } + ii++; + facelets += 2; + + } else if (P->hemi && P->index != last_uniform - 1) { + j = !P->ftype[P->incid[0][i]]; + + push_face3 (result, ii, ii + 1, ii + 2); + push_face4 (result, P->incid[j][i], ii + 2, P->incid[j+2][i], ii + 5); + push_face3 (result, ii + 3, ii + 4, ii + 5); + ii += 6; + facelets += 3; + } else if (P->index == last_uniform - 1) { + for (j = 0; j < 8; j++) + if (P->ftype[P->incid[j][i]] == 3) + break; + push_face3 (result, ii, ii + 1, ii + 2); + push_face4 (result, + P->incid[j][i], ii + 2, P->incid[(j+2)%8][i], ii + 5); + push_face3 (result, ii + 3, ii + 4, ii + 5); + + push_face3 (result, ii + 6, ii + 7, ii + 8); + push_face4 (result, + P->incid[(j+4)%8][i], ii + 8, P->incid[(j+6)%8][i], + ii + 11); + push_face3 (result, ii + 9, ii + 10, ii + 11); + ii += 12; + facelets += 6; + } else { + + result->faces[result->nfaces].npoints = P->M; + Malloc (result->faces[result->nfaces].points, P->M, int); + for (j = 0; j < P->M; j++) + result->faces[result->nfaces].points[j] = P->incid[j][i]; + result->nfaces++; + facelets++; + } + } else { + int split = (frac(P->n[P->ftype[i]]), + frax.d != 1 && frax.d != frax.n - 1); + for (j = 0; j < V; j++) { + for (k = 0; k < P->M; k++) + if (P->incid[k][j] == i) + break; + if (k != P->M) + break; + } + if (split) { + ll = j; + for (l = P->adj[k][j]; l != j; l = P->adj[k][l]) { + for (k = 0; k < P->M; k++) + if (P->incid[k][l] == i) + break; + if (P->adj[k][l] == ll) + k = mod(k + 1 , P->M); + push_face3 (result, ll, l, ii); + facelets++; + ll = l; + } + push_face3 (result, ll, j, ii++); + facelets++; + + } else { + + int *pp; + int pi = 0; + Malloc (pp, 100, int); + + pp[pi++] = j; + ll = j; + for (l = P->adj[k][j]; l != j; l = P->adj[k][l]) { + for (k = 0; k < P->M; k++) + if (P->incid[k][l] == i) + break; + if (P->adj[k][l] == ll) + k = mod(k + 1 , P->M); + pp[pi++] = l; + ll = l; + } + result->faces[result->nfaces].npoints = pi; + result->faces[result->nfaces].points = pp; + result->nfaces++; + facelets++; + } + } + } + + /* + * Face color indices - for polyhedra with multiple face types + * For non-simple faces, the index is repeated as many times as needed by the + * triangulation. + */ + { + int ff = 0; + if (!*star && P->N != 1) { + for (i = 0; i < F; i++) + if (frac(P->n[P->ftype[i]]), frax.d == 1 || frax.d == frax.n - 1) + result->faces[ff++].color = P->ftype[i]; + else + for (j = 0; j < frax.n; j++) + result->faces[ff++].color = P->ftype[i]; + } else { + for (i = 0; i < facelets; i++) + result->faces[ff++].color = 0; + } + } + + if (*star && P->even != -1) + free(hit); + free(v); + free(f); + + return result; +} + + + +/* External interface (jwz) + */ + +void +free_polyhedron (polyhedron *p) +{ + if (!p) return; + Free (p->wythoff); + Free (p->name); + Free (p->group); + Free (p->class); + if (p->faces) + { + int i; + for (i = 0; i < p->nfaces; i++) + Free (p->faces[i].points); + Free (p->faces); + } + Free (p); +} + + +int +construct_polyhedra (polyhedron ***polyhedra_ret) +{ + double freeze = 0; + double azimuth = AZ; + double elevation = EL; + int index = 0; + + int count = 0; + polyhedron **result; + Malloc (result, last_uniform * 2 + 3, polyhedron*); + + while (index < last_uniform) { + char sym[4]; + Polyhedron *P; + + sprintf(sym, "#%d", index + 1); + if (!(P = kaleido(sym, 1, 0, 0, 0))) { + Err (strerror(errno)); + } + + result[count++] = construct_polyhedron (P, P->v, P->V, P->f, P->F, + P->name, P->dual_name, + P->class, "", + azimuth, elevation, freeze); + + result[count++] = construct_polyhedron (P, P->f, P->F, P->v, P->V, + P->dual_name, P->name, + P->dual_class, "*", + azimuth, elevation, freeze); + polyfree(P); + index++; + } + + *polyhedra_ret = result; + count++; /* leave room for teapot */ + return count; +} diff --git a/hacks/glx/polyhedra.h b/hacks/glx/polyhedra.h new file mode 100644 index 00000000..ace4ac7d --- /dev/null +++ b/hacks/glx/polyhedra.h @@ -0,0 +1,52 @@ +/* xscreensaver, Copyright (c) 2004 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. + */ + +#ifndef __POLYHEDRA_H__ +#define __POLYHEDRA_H__ + +typedef struct { + double x, y, z; +} point; + +typedef struct { + int color; + int npoints; + int *points; /* indexes into point list */ +} face; + +typedef struct { + + int number; + char *wythoff; + char *name; + char *dual; + char *config; + char *group; + char *class; + + int nfaces; + int logical_faces; + int logical_vertices; + int nedges; + int npoints; + int density; + int chi; + + point *points; + face *faces; + +} polyhedron; + + +extern int construct_polyhedra (polyhedron ***polyhedra_ret); +extern void free_polyhedron (polyhedron *p); + +#endif /* __POLYHEDRA_H__ */ diff --git a/hacks/glx/polyhedra.man b/hacks/glx/polyhedra.man new file mode 100644 index 00000000..b4e1cca3 --- /dev/null +++ b/hacks/glx/polyhedra.man @@ -0,0 +1,124 @@ +.TH XScreenSaver 1 "" "X Version 11" +.SH NAME +polyhedra - draws the 80 uniform polyhedra and their duals +.SH SYNOPSIS +.SH SYNOPSIS +.B polyhedra +[\-display \fIhost:display.screen\fP] +[\-visual \fIvisual\fP] +[\-window] +[\-root] +[\-delay \fInumber\fP] +[\-speed \fIfloat\fP] +[\-duration \fIseconds\fP] +[\-no-wander] +[\-spin \fIXYZ\fP] +[\-wireframe] +[\-no-titles] +[\-which \fIname\fP] +[\-wireframe] +[\-fps] +.SH DESCRIPTION +This program renders 160 different 3D solids, and displays some +information about each. A new solid is chosen every few seconds. + +There are 75 uniform polyhedra, plus an inifinite number of +prisms and antiprisms: + + * Convex Uniform Polyhedra: + * Platonic solids (5) + * Archimedean solids (13) + * Convex prisms and antiprisms (2 infinite families) + * Nonconvex Uniform Polyhedra: + * Kepler-Poinsot polyhedra (4) + * Nonconvex uniform polyhedra (53) + * Nonconvex prisms, antiprisms, and crossed antiprisms + (3 infinite families) + +Representative samples of the prism sets brings the total to 80 solids. +Including the \fIdual\fP of each brings the total up to 160. (To +create the "dual" of a polyhedron, faces are replaced with vertices, +and vertices with faces.) +.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 \-speed \fInumber\fP +Larger numbers mean run faster. Default: 1.0. +.TP 8 +.B \-duration \fIseconds\fP +How long before switching to a new polyhedron. Default 12 seconds. +.TP 8 +.B \-wander | \-no-wander +Whether the objects should wander around the screen. +.TP 8 +.B \-spin [XYZ] | \-no-spin +Which axes, if any, to spin around on. +.TP 8 +.B \-titles | \-no-titles +Whether to display text describing each object. +.TP 8 +.B \-which \fIobject-name\fP +Display only one particular object, identified by number, name, or +Whthoff symbol. +.TP 8 +.B \-wireframe | \-no-wireframe +Render in wireframe instead of solid. +.TP 8 +.B \-fps +Display the current frame rate, CPU load, and polygon count. +.SH KEY BINDINGS +When running in a window, you can rotate the object with the mouse. +Also, the following keystrokes are defined: +.TP 12 +.B SPC \fIor\fP TAB +Select a new polyhedron at random. +.TP 12 +.B + \fIor\fP > +Select the next-higher-numbered polyhedron. +.TP 12 +.B - \fIor\fP < +Select the next-lower-numbered polyhedron. +.TP 12 +.B ESC \fIor\fP ^C +Quit. +.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 1991-2002 Dr. Zvi Har'El. + +Copyright \(co 2004 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 +Based on the program \fIkaleido\fP ("Kaleidoscopic construction of +uniform polyhedra"), by Dr. Zvi Har'El + http://www.math.technion.ac.il/~rl/ + ftp://ftp.math.technion.ac.il/kaleido/ + +Adapted for OpenGL and XScreenSaver by Jamie Zawinski, 2004. diff --git a/hacks/glx/polytopes.c b/hacks/glx/polytopes.c new file mode 100644 index 00000000..703316aa --- /dev/null +++ b/hacks/glx/polytopes.c @@ -0,0 +1,3213 @@ +/* polytopes --- Shows one of the six regular polytopes rotating in 4d */ + +#if 0 +static const char sccsid[] = "@(#)polytopes.c 1.2 05/09/28 xlockmore"; +#endif + +/* Copyright (c) 2003-2009 Carsten Steger . */ + +/* + * Permission to use, copy, modify, and distribute this software and its + * documentation for any purpose and without fee is hereby granted, + * provided that the above copyright notice appear in all copies and that + * both that copyright notice and this permission notice appear in + * supporting documentation. + * + * This file is provided AS IS with no warranties of any kind. The author + * shall have no liability with respect to the infringement of copyrights, + * trade secrets or any patents by this file or any part thereof. In no + * event will the author be liable for any lost revenue or profits or + * other special, indirect and consequential damages. + * + * REVISION HISTORY: + * C. Steger - 03/08/10: Initial version + * C. Steger - 05/09/28: Added trackball support + * C. Steger - 07/01/23: Improved 4d trackball support + * C. Steger - 09/08/23: Removed check-config.pl warnings + */ + +/* + * This program shows one of the six regular 4D polytopes rotating in 4D. + * Written by Carsten Steger, inspired by H.S.M Coxeter's book "Regular + * Polytopes", 3rd Edition, Dover Publications, Inc., 1973, and Thomas + * Banchoff's book "Beyond the Third Dimension: Geometry, Computer + * Graphics, and Higher Dimensions", Scientific American Library, 1990. + */ + +#ifndef M_PI +#define M_PI 3.14159265358979323846 +#endif + +#define SQRT15OVER4 1.93649167310370844259 /* sqrt(15/4) */ +#define SQRT10OVER3 1.82574185835055371152 /* sqrt(10/3) */ +#define SQRT5OVER2 1.58113883008418966600 /* sqrt(5/2) */ +#define SQRT5OVER6 0.91287092917527685576 /* sqrt(5/6) */ +#define SQRT5OVER12 0.64549722436790281420 /* sqrt(5/12) */ +#define SQRT2 1.41421356237309504880 /* sqrt(2) */ +#define GOLDEN 1.61803398874989484820 /* (sqrt(5)+1)/2 */ +#define GOLDENINV 0.61803398874989484820 /* (sqrt(5)-1)/2 */ +#define SQRT2INV 0.70710678118654752440 /* sqrt(1/2) */ +#define GOLDEN2 1.14412280563536859520 /* ((sqrt(5)+1)/2)/sqrt(2) */ +#define GOLDENINV2 0.43701602444882107080 /* ((sqrt(5)-1)/2)/sqrt(2) */ +#define GOLDEN22 1.85122958682191611960 /* (((sqrt(5)+1)/2)^2)/sqrt(2) */ +#define GOLDENINV22 0.27009075673772645360 /* (((sqrt(5)-1)/2)^2)/sqrt(2) */ + +#define DISP_WIREFRAME 0 +#define DISP_SURFACE 1 +#define DISP_TRANSPARENT 2 + +#define POLYTOPE_RANDOM -1 +#define POLYTOPE_5_CELL 0 +#define POLYTOPE_8_CELL 1 +#define POLYTOPE_16_CELL 2 +#define POLYTOPE_24_CELL 3 +#define POLYTOPE_120_CELL 4 +#define POLYTOPE_600_CELL 5 +#define POLYTOPE_LAST_CELL POLYTOPE_600_CELL + +#define COLORS_SINGLE 0 +#define COLORS_DEPTH 1 + +#define DISP_3D_PERSPECTIVE 0 +#define DISP_3D_ORTHOGRAPHIC 1 + +#define DISP_4D_PERSPECTIVE 0 +#define DISP_4D_PERSPECTIVE_STR "0" +#define DISP_4D_ORTHOGRAPHIC 1 +#define DISP_4D_ORTHOGRAPHIC_STR "1" + +#define DEF_DISPLAY_MODE "transparent" +#define DEF_POLYTOPE "random" +#define DEF_COLORS "depth" +#define DEF_PROJECTION_3D "perspective" +#define DEF_PROJECTION_4D "perspective" +#define DEF_SPEEDWX "1.1" +#define DEF_SPEEDWY "1.3" +#define DEF_SPEEDWZ "1.5" +#define DEF_SPEEDXY "1.7" +#define DEF_SPEEDXZ "1.9" +#define DEF_SPEEDYZ "2.1" + +#ifdef STANDALONE +# define DEFAULTS "*delay: 25000 \n" \ + "*showFPS: False \n" + +# define refresh_polytopes 0 +# include "xlockmore.h" /* from the xscreensaver distribution */ +#else /* !STANDALONE */ +# include "xlock.h" /* from the xlockmore distribution */ +#endif /* !STANDALONE */ + +#ifdef USE_GL + +#ifndef HAVE_COCOA +# include +#endif +#include "gltrackball.h" + + +#ifdef USE_MODULES +ModStruct polytopes_description = +{"polytopes", "init_polytopes", "draw_polytopes", "release_polytopes", + "draw_polytopes", "change_polytopes", NULL, &polytopes_opts, + 25000, 1, 1, 1, 1.0, 4, "", + "Shows one of the six regular 4d polytopes rotating in 4d", 0, NULL}; + +#endif + + +static char *mode; +static int display_mode; +static char *poly_str; +static int polytope; +static char *color_str; +static int color_mode; +static char *proj_3d; +static int projection_3d; +static char *proj_4d; +static int projection_4d; +static float speed_wx; +static float speed_wy; +static float speed_wz; +static float speed_xy; +static float speed_xz; +static float speed_yz; + +static const float offset4d[4] = { 0.0, 0.0, 0.0, 3.0 }; +static const float offset3d[4] = { 0.0, 0.0, -2.0, 0.0 }; + + +static XrmOptionDescRec opts[] = +{ + {"-mode", ".displayMode", XrmoptionSepArg, 0 }, + {"-wireframe", ".displayMode", XrmoptionNoArg, "wireframe" }, + {"-surface", ".displayMode", XrmoptionNoArg, "surface" }, + {"-transparent", ".displayMode", XrmoptionNoArg, "transparent" }, + {"-polytope", ".polytope", XrmoptionSepArg, 0 }, + {"-random", ".polytope", XrmoptionNoArg, "random" }, + {"-5-cell", ".polytope", XrmoptionNoArg, "5-cell" }, + {"-8-cell", ".polytope", XrmoptionNoArg, "8-cell" }, + {"-16-cell", ".polytope", XrmoptionNoArg, "16-cell" }, + {"-24-cell", ".polytope", XrmoptionNoArg, "24-cell" }, + {"-120-cell", ".polytope", XrmoptionNoArg, "120-cell" }, + {"-600-cell", ".polytope", XrmoptionNoArg, "600-cell" }, + {"-single-color", ".colors", XrmoptionNoArg, "single" }, + {"-depth-colors", ".colors", XrmoptionNoArg, "depth" }, + {"-perspective-3d", ".projection3d", XrmoptionNoArg, "perspective" }, + {"-orthographic-3d", ".projection3d", XrmoptionNoArg, "orthographic" }, + {"-perspective-4d", ".projection4d", XrmoptionNoArg, "perspective" }, + {"-orthographic-4d", ".projection4d", XrmoptionNoArg, "orthographic" }, + {"-speed-wx", ".speedwx", XrmoptionSepArg, 0 }, + {"-speed-wy", ".speedwy", XrmoptionSepArg, 0 }, + {"-speed-wz", ".speedwz", XrmoptionSepArg, 0 }, + {"-speed-xy", ".speedxy", XrmoptionSepArg, 0 }, + {"-speed-xz", ".speedxz", XrmoptionSepArg, 0 }, + {"-speed-yz", ".speedyz", XrmoptionSepArg, 0 } +}; + +static argtype vars[] = +{ + { &mode, "displayMode", "DisplayMode", DEF_DISPLAY_MODE, t_String }, + { &poly_str, "polytope", "Polytope", DEF_POLYTOPE, t_String }, + { &color_str, "colors", "Colors", DEF_COLORS, t_String }, + { &proj_3d, "projection3d", "Projection3d",DEF_PROJECTION_3D, t_String }, + { &proj_4d, "projection4d", "Projection4d",DEF_PROJECTION_4D, t_String }, + { &speed_wx, "speedwx", "Speedwx", DEF_SPEEDWX, t_Float}, + { &speed_wy, "speedwy", "Speedwy", DEF_SPEEDWY, t_Float}, + { &speed_wz, "speedwz", "Speedwz", DEF_SPEEDWZ, t_Float}, + { &speed_xy, "speedxy", "Speedxy", DEF_SPEEDXY, t_Float}, + { &speed_xz, "speedxz", "Speedxz", DEF_SPEEDXZ, t_Float}, + { &speed_yz, "speedyz", "Speedyz", DEF_SPEEDYZ, t_Float} +}; + +static OptionStruct desc[] = +{ + { "-wireframe", "display the polytope as a wireframe mesh" }, + { "-surface", "display the polytope as a solid surface" }, + { "-transparent", "display the polytope as a transparent surface" }, + { "-solid", "display the polytope as a solid object" }, + { "-bands", "display the polytope as see-through bands" }, + { "-twosided", "display the polytope with two colors" }, + { "-colorwheel", "display the polytope with a smooth color wheel" }, + { "-perspective-3d", "project the polytope perspectively from 3d to 2d" }, + { "-orthographic-3d", "project the polytope orthographically from 3d to 2d"}, + { "-perspective-4d", "project the polytope perspectively from 4d to 3d" }, + { "-orthographic-4d", "project the polytope orthographically from 4d to 3d"}, + { "-speed-wx ", "rotation speed around the wx plane" }, + { "-speed-wy ", "rotation speed around the wy plane" }, + { "-speed-wz ", "rotation speed around the wz plane" }, + { "-speed-xy ", "rotation speed around the xy plane" }, + { "-speed-xz ", "rotation speed around the xz plane" }, + { "-speed-yz ", "rotation speed around the yz plane" } +}; + +ENTRYPOINT ModeSpecOpt polytopes_opts = +{sizeof opts / sizeof opts[0], opts, sizeof vars / sizeof vars[0], vars, desc}; + + +/* 5-cell {3,3,3} */ +#define NUM_VERT_5 5 +#define NUM_EDGE_5 10 +#define NUM_FACE_5 10 +#define VERT_PER_FACE_5 3 + +#define MIN_EDGE_DEPTH_5 (-0.5) +#define MAX_EDGE_DEPTH_5 0.75 +#define MIN_FACE_DEPTH_5 (-0.5) +#define MAX_FACE_DEPTH_5 (1.0/3.0) + + +/* 8-cell {4,3,3} */ +#define NUM_VERT_8 16 +#define NUM_EDGE_8 32 +#define NUM_FACE_8 24 +#define VERT_PER_FACE_8 4 + +#define MIN_EDGE_DEPTH_8 (-1.0) +#define MAX_EDGE_DEPTH_8 1.0 +#define MIN_FACE_DEPTH_8 (-1.0) +#define MAX_FACE_DEPTH_8 1.0 + +/* 16-cell {3,3,4} */ +#define NUM_VERT_16 8 +#define NUM_EDGE_16 24 +#define NUM_FACE_16 32 +#define VERT_PER_FACE_16 3 + +#define MIN_EDGE_DEPTH_16 (-1.0) +#define MAX_EDGE_DEPTH_16 1.0 +#define MIN_FACE_DEPTH_16 (-2.0/3.0) +#define MAX_FACE_DEPTH_16 (2.0/3.0) + + +/* 24-cell {3,4,3} */ +#define NUM_VERT_24 24 +#define NUM_EDGE_24 96 +#define NUM_FACE_24 96 +#define VERT_PER_FACE_24 3 + +#define MIN_EDGE_DEPTH_24 (-SQRT2) +#define MAX_EDGE_DEPTH_24 SQRT2 +#define MIN_FACE_DEPTH_24 (-SQRT2) +#define MAX_FACE_DEPTH_24 SQRT2 + + +/* 120-cell {5,3,3} */ +#define NUM_VERT_120 600 +#define NUM_EDGE_120 1200 +#define NUM_FACE_120 720 +#define VERT_PER_FACE_120 5 + +#define MIN_EDGE_DEPTH_120 (-GOLDEN22) +#define MAX_EDGE_DEPTH_120 GOLDEN22 +#define MIN_FACE_DEPTH_120 (-GOLDEN22) +#define MAX_FACE_DEPTH_120 GOLDEN22 + + +/* 600-cell {3,3,5} */ +#define NUM_VERT_600 120 +#define NUM_EDGE_600 720 +#define NUM_FACE_600 1200 +#define VERT_PER_FACE_600 3 + +#define MIN_EDGE_DEPTH_600 (-GOLDEN/2.0-1) +#define MAX_EDGE_DEPTH_600 (GOLDEN/2.0+1) +#define MIN_FACE_DEPTH_600 ((-2*GOLDEN-2)/3.0) +#define MAX_FACE_DEPTH_600 ((2*GOLDEN+2)/3.0) + + +typedef struct { + GLint WindH, WindW; + GLXContext *glx_context; + /* 4D rotation angles */ + float alpha, beta, delta, zeta, eta, theta; + /* Aspect ratio of the current window */ + float aspect; + /* Counter */ + int tick, poly; + /* Trackball states */ + trackball_state *trackballs[2]; + int current_trackball; + Bool button_pressed; + + float edge_color_5[NUM_EDGE_5][4]; + float face_color_5[NUM_FACE_5][4]; + float face_color_trans_5[NUM_FACE_5][4]; + + float edge_color_8[NUM_EDGE_8][4]; + float face_color_8[NUM_FACE_8][4]; + float face_color_trans_8[NUM_FACE_8][4]; + + float edge_color_16[NUM_EDGE_16][4]; + float face_color_16[NUM_FACE_16][4]; + float face_color_trans_16[NUM_FACE_16][4]; + + float edge_color_24[NUM_EDGE_24][4]; + float face_color_24[NUM_FACE_24][4]; + float face_color_trans_24[NUM_FACE_24][4]; + + float edge_color_120[NUM_EDGE_120][4]; + float face_color_120[NUM_FACE_120][4]; + float face_color_trans_120[NUM_FACE_120][4]; + + float edge_color_600[NUM_EDGE_600][4]; + float face_color_600[NUM_FACE_600][4]; + float face_color_trans_600[NUM_FACE_600][4]; + + float speed_scale; + +} polytopesstruct; + +static polytopesstruct *poly = (polytopesstruct *) NULL; + + +/* Vertex, edge, and face data for the six regular polytopes. All the + polytopes are constructed with coordinates chosen such that their 4d + circumsphere has a radius of 2. */ + +static const float vert_5[NUM_VERT_5][4] = { + { -SQRT5OVER2, -SQRT5OVER6, -SQRT5OVER12, -0.5 }, + { SQRT5OVER2, -SQRT5OVER6, -SQRT5OVER12, -0.5 }, + { 0.0, SQRT10OVER3, -SQRT5OVER12, -0.5 }, + { 0.0, 0.0, SQRT15OVER4, -0.5 }, + { 0.0, 0.0, 0.0, 2.0 } +}; + +static const int edge_5[NUM_EDGE_5][2] = { + { 0, 1 }, { 0, 2 }, { 0, 3 }, { 0, 4 }, { 1, 2 }, { 1, 3 }, { 1, 4 }, + { 2, 3 }, { 2, 4 }, { 3, 4 } +}; + +static const int face_5[NUM_FACE_5][VERT_PER_FACE_5] = { + { 0, 1, 2 }, { 0, 1, 3 }, { 0, 1, 4 }, { 0, 2, 3 }, { 0, 2, 4 }, { 0, 3, 4 }, + { 1, 2, 3 }, { 1, 2, 4 }, { 1, 3, 4 }, { 2, 3, 4 } +}; + + +static const float vert_8[NUM_VERT_8][4] = { + { -1.0, -1.0, -1.0, -1.0 }, { 1.0, -1.0, -1.0, -1.0 }, + { -1.0, 1.0, -1.0, -1.0 }, { 1.0, 1.0, -1.0, -1.0 }, + { -1.0, -1.0, 1.0, -1.0 }, { 1.0, -1.0, 1.0, -1.0 }, + { -1.0, 1.0, 1.0, -1.0 }, { 1.0, 1.0, 1.0, -1.0 }, + { -1.0, -1.0, -1.0, 1.0 }, { 1.0, -1.0, -1.0, 1.0 }, + { -1.0, 1.0, -1.0, 1.0 }, { 1.0, 1.0, -1.0, 1.0 }, + { -1.0, -1.0, 1.0, 1.0 }, { 1.0, -1.0, 1.0, 1.0 }, + { -1.0, 1.0, 1.0, 1.0 }, { 1.0, 1.0, 1.0, 1.0 } +}; + +static const int edge_8[NUM_EDGE_8][2] = { + { 0, 1 }, { 0, 2 }, { 0, 4 }, { 0, 8 }, { 1, 3 }, { 1, 5 }, + { 1, 9 }, { 2, 3 }, { 2, 6 }, { 2, 10 }, { 3, 7 }, { 3, 11 }, + { 4, 5 }, { 4, 6 }, { 4, 12 }, { 5, 7 }, { 5, 13 }, { 6, 7 }, + { 6, 14 }, { 7, 15 }, { 8, 9 }, { 8, 10 }, { 8, 12 }, { 9, 11 }, + { 9, 13 }, { 10, 11 }, { 10, 14 }, { 11, 15 }, { 12, 13 }, { 12, 14 }, + { 13, 15 }, { 14, 15 } +}; + +static const int face_8[NUM_FACE_8][VERT_PER_FACE_8] = { + { 0, 1, 3, 2 }, { 0, 1, 5, 4 }, { 0, 1, 9, 8 }, + { 0, 2, 6, 4 }, { 0, 2, 10, 8 }, { 0, 4, 12, 8 }, + { 1, 3, 7, 5 }, { 1, 3, 11, 9 }, { 1, 5, 13, 9 }, + { 2, 3, 7, 6 }, { 2, 3, 11, 10 }, { 2, 6, 14, 10 }, + { 3, 7, 15, 11 }, { 4, 5, 7, 6 }, { 4, 5, 13, 12 }, + { 4, 6, 14, 12 }, { 5, 7, 15, 13 }, { 6, 7, 15, 14 }, + { 8, 9, 11, 10 }, { 8, 9, 13, 12 }, { 8, 10, 14, 12 }, + { 9, 11, 15, 13 }, { 10, 11, 15, 14 }, { 12, 13, 15, 14 } +}; + + + +static const float vert_16[NUM_VERT_16][4] = { + { 0.0, 0.0, 0.0, -2.0 }, { 0.0, 0.0, -2.0, 0.0 }, + { 0.0, -2.0, 0.0, 0.0 }, { -2.0, 0.0, 0.0, 0.0 }, + { 2.0, 0.0, 0.0, 0.0 }, { 0.0, 2.0, 0.0, 0.0 }, + { 0.0, 0.0, 2.0, 0.0 }, { 0.0, 0.0, 0.0, 2.0 } +}; + +static const int edge_16[NUM_EDGE_16][2] = { + { 0, 1 }, { 0, 2 }, { 0, 3 }, { 0, 4 }, { 0, 5 }, { 0, 6 }, { 1, 2 }, + { 1, 3 }, { 1, 4 }, { 1, 5 }, { 1, 7 }, { 2, 3 }, { 2, 4 }, { 2, 6 }, + { 2, 7 }, { 3, 5 }, { 3, 6 }, { 3, 7 }, { 4, 5 }, { 4, 6 }, { 4, 7 }, + { 5, 6 }, { 5, 7 }, { 6, 7 } +}; + +static const int face_16[NUM_FACE_16][VERT_PER_FACE_16] = { + { 0, 1, 2 }, { 0, 1, 3 }, { 0, 1, 4 }, { 0, 1, 5 }, { 0, 2, 3 }, { 0, 2, 4 }, + { 0, 2, 6 }, { 0, 3, 5 }, { 0, 3, 6 }, { 0, 4, 5 }, { 0, 4, 6 }, { 0, 5, 6 }, + { 1, 2, 3 }, { 1, 2, 4 }, { 1, 2, 7 }, { 1, 3, 5 }, { 1, 3, 7 }, { 1, 4, 5 }, + { 1, 4, 7 }, { 1, 5, 7 }, { 2, 3, 6 }, { 2, 3, 7 }, { 2, 4, 6 }, { 2, 4, 7 }, + { 2, 6, 7 }, { 3, 5, 6 }, { 3, 5, 7 }, { 3, 6, 7 }, { 4, 5, 6 }, { 4, 5, 7 }, + { 4, 6, 7 }, { 5, 6, 7 } +}; + + + +static const float vert_24[NUM_VERT_24][4] = { + { 0.0, 0.0, -SQRT2, -SQRT2 }, { 0.0, -SQRT2, 0.0, -SQRT2 }, + { -SQRT2, 0.0, 0.0, -SQRT2 }, { SQRT2, 0.0, 0.0, -SQRT2 }, + { 0.0, SQRT2, 0.0, -SQRT2 }, { 0.0, 0.0, SQRT2, -SQRT2 }, + { 0.0, -SQRT2, -SQRT2, 0.0 }, { -SQRT2, 0.0, -SQRT2, 0.0 }, + { SQRT2, 0.0, -SQRT2, 0.0 }, { 0.0, SQRT2, -SQRT2, 0.0 }, + { -SQRT2, -SQRT2, 0.0, 0.0 }, { SQRT2, -SQRT2, 0.0, 0.0 }, + { -SQRT2, SQRT2, 0.0, 0.0 }, { SQRT2, SQRT2, 0.0, 0.0 }, + { 0.0, -SQRT2, SQRT2, 0.0 }, { -SQRT2, 0.0, SQRT2, 0.0 }, + { SQRT2, 0.0, SQRT2, 0.0 }, { 0.0, SQRT2, SQRT2, 0.0 }, + { 0.0, 0.0, -SQRT2, SQRT2 }, { 0.0, -SQRT2, 0.0, SQRT2 }, + { -SQRT2, 0.0, 0.0, SQRT2 }, { SQRT2, 0.0, 0.0, SQRT2 }, + { 0.0, SQRT2, 0.0, SQRT2 }, { 0.0, 0.0, SQRT2, SQRT2 } +}; + +static const int edge_24[NUM_EDGE_24][2] = { + { 0, 1 }, { 0, 2 }, { 0, 3 }, { 0, 4 }, { 0, 6 }, { 0, 7 }, + { 0, 8 }, { 0, 9 }, { 1, 2 }, { 1, 3 }, { 1, 5 }, { 1, 6 }, + { 1, 10 }, { 1, 11 }, { 1, 14 }, { 2, 4 }, { 2, 5 }, { 2, 7 }, + { 2, 10 }, { 2, 12 }, { 2, 15 }, { 3, 4 }, { 3, 5 }, { 3, 8 }, + { 3, 11 }, { 3, 13 }, { 3, 16 }, { 4, 5 }, { 4, 9 }, { 4, 12 }, + { 4, 13 }, { 4, 17 }, { 5, 14 }, { 5, 15 }, { 5, 16 }, { 5, 17 }, + { 6, 7 }, { 6, 8 }, { 6, 10 }, { 6, 11 }, { 6, 18 }, { 6, 19 }, + { 7, 9 }, { 7, 10 }, { 7, 12 }, { 7, 18 }, { 7, 20 }, { 8, 9 }, + { 8, 11 }, { 8, 13 }, { 8, 18 }, { 8, 21 }, { 9, 12 }, { 9, 13 }, + { 9, 18 }, { 9, 22 }, { 10, 14 }, { 10, 15 }, { 10, 19 }, { 10, 20 }, + { 11, 14 }, { 11, 16 }, { 11, 19 }, { 11, 21 }, { 12, 15 }, { 12, 17 }, + { 12, 20 }, { 12, 22 }, { 13, 16 }, { 13, 17 }, { 13, 21 }, { 13, 22 }, + { 14, 15 }, { 14, 16 }, { 14, 19 }, { 14, 23 }, { 15, 17 }, { 15, 20 }, + { 15, 23 }, { 16, 17 }, { 16, 21 }, { 16, 23 }, { 17, 22 }, { 17, 23 }, + { 18, 19 }, { 18, 20 }, { 18, 21 }, { 18, 22 }, { 19, 20 }, { 19, 21 }, + { 19, 23 }, { 20, 22 }, { 20, 23 }, { 21, 22 }, { 21, 23 }, { 22, 23 } +}; + +static const int face_24[NUM_FACE_24][VERT_PER_FACE_24] = { + { 0, 1, 2 }, { 0, 1, 3 }, { 0, 1, 6 }, { 0, 2, 4 }, + { 0, 2, 7 }, { 0, 3, 4 }, { 0, 3, 8 }, { 0, 4, 9 }, + { 0, 6, 7 }, { 0, 6, 8 }, { 0, 7, 9 }, { 0, 8, 9 }, + { 1, 2, 5 }, { 1, 2, 10 }, { 1, 3, 5 }, { 1, 3, 11 }, + { 1, 5, 14 }, { 1, 6, 10 }, { 1, 6, 11 }, { 1, 10, 14 }, + { 1, 11, 14 }, { 2, 4, 5 }, { 2, 4, 12 }, { 2, 5, 15 }, + { 2, 7, 10 }, { 2, 7, 12 }, { 2, 10, 15 }, { 2, 12, 15 }, + { 3, 4, 5 }, { 3, 4, 13 }, { 3, 5, 16 }, { 3, 8, 11 }, + { 3, 8, 13 }, { 3, 11, 16 }, { 3, 13, 16 }, { 4, 5, 17 }, + { 4, 9, 12 }, { 4, 9, 13 }, { 4, 12, 17 }, { 4, 13, 17 }, + { 5, 14, 15 }, { 5, 14, 16 }, { 5, 15, 17 }, { 5, 16, 17 }, + { 6, 7, 10 }, { 6, 7, 18 }, { 6, 8, 11 }, { 6, 8, 18 }, + { 6, 10, 19 }, { 6, 11, 19 }, { 6, 18, 19 }, { 7, 9, 12 }, + { 7, 9, 18 }, { 7, 10, 20 }, { 7, 12, 20 }, { 7, 18, 20 }, + { 8, 9, 13 }, { 8, 9, 18 }, { 8, 11, 21 }, { 8, 13, 21 }, + { 8, 18, 21 }, { 9, 12, 22 }, { 9, 13, 22 }, { 9, 18, 22 }, + { 10, 14, 15 }, { 10, 14, 19 }, { 10, 15, 20 }, { 10, 19, 20 }, + { 11, 14, 16 }, { 11, 14, 19 }, { 11, 16, 21 }, { 11, 19, 21 }, + { 12, 15, 17 }, { 12, 15, 20 }, { 12, 17, 22 }, { 12, 20, 22 }, + { 13, 16, 17 }, { 13, 16, 21 }, { 13, 17, 22 }, { 13, 21, 22 }, + { 14, 15, 23 }, { 14, 16, 23 }, { 14, 19, 23 }, { 15, 17, 23 }, + { 15, 20, 23 }, { 16, 17, 23 }, { 16, 21, 23 }, { 17, 22, 23 }, + { 18, 19, 20 }, { 18, 19, 21 }, { 18, 20, 22 }, { 18, 21, 22 }, + { 19, 20, 23 }, { 19, 21, 23 }, { 20, 22, 23 }, { 21, 22, 23 } +}; + + + + +static const float vert_120[NUM_VERT_120][4] = { + { -GOLDENINV22, 0.0, -SQRT2INV, -GOLDEN22 }, + { GOLDENINV22, 0.0, -SQRT2INV, -GOLDEN22 }, + { -GOLDENINV2, -GOLDENINV2, -GOLDENINV2, -GOLDEN22 }, + { GOLDENINV2, -GOLDENINV2, -GOLDENINV2, -GOLDEN22 }, + { -GOLDENINV2, GOLDENINV2, -GOLDENINV2, -GOLDEN22 }, + { GOLDENINV2, GOLDENINV2, -GOLDENINV2, -GOLDEN22 }, + { 0.0, -SQRT2INV, -GOLDENINV22, -GOLDEN22 }, + { 0.0, SQRT2INV, -GOLDENINV22, -GOLDEN22 }, + { -SQRT2INV, -GOLDENINV22, 0.0, -GOLDEN22 }, + { SQRT2INV, -GOLDENINV22, 0.0, -GOLDEN22 }, + { -SQRT2INV, GOLDENINV22, 0.0, -GOLDEN22 }, + { SQRT2INV, GOLDENINV22, 0.0, -GOLDEN22 }, + { 0.0, -SQRT2INV, GOLDENINV22, -GOLDEN22 }, + { 0.0, SQRT2INV, GOLDENINV22, -GOLDEN22 }, + { -GOLDENINV2, -GOLDENINV2, GOLDENINV2, -GOLDEN22 }, + { GOLDENINV2, -GOLDENINV2, GOLDENINV2, -GOLDEN22 }, + { -GOLDENINV2, GOLDENINV2, GOLDENINV2, -GOLDEN22 }, + { GOLDENINV2, GOLDENINV2, GOLDENINV2, -GOLDEN22 }, + { -GOLDENINV22, 0.0, SQRT2INV, -GOLDEN22 }, + { GOLDENINV22, 0.0, SQRT2INV, -GOLDEN22 }, + { -GOLDENINV2, 0.0, -GOLDEN2, -SQRT5OVER2 }, + { GOLDENINV2, 0.0, -GOLDEN2, -SQRT5OVER2 }, + { -SQRT2INV, -SQRT2INV, -SQRT2INV, -SQRT5OVER2 }, + { SQRT2INV, -SQRT2INV, -SQRT2INV, -SQRT5OVER2 }, + { -SQRT2INV, SQRT2INV, -SQRT2INV, -SQRT5OVER2 }, + { SQRT2INV, SQRT2INV, -SQRT2INV, -SQRT5OVER2 }, + { 0.0, -GOLDEN2, -GOLDENINV2, -SQRT5OVER2 }, + { 0.0, GOLDEN2, -GOLDENINV2, -SQRT5OVER2 }, + { -GOLDEN2, -GOLDENINV2, 0.0, -SQRT5OVER2 }, + { GOLDEN2, -GOLDENINV2, 0.0, -SQRT5OVER2 }, + { -GOLDEN2, GOLDENINV2, 0.0, -SQRT5OVER2 }, + { GOLDEN2, GOLDENINV2, 0.0, -SQRT5OVER2 }, + { 0.0, -GOLDEN2, GOLDENINV2, -SQRT5OVER2 }, + { 0.0, GOLDEN2, GOLDENINV2, -SQRT5OVER2 }, + { -SQRT2INV, -SQRT2INV, SQRT2INV, -SQRT5OVER2 }, + { SQRT2INV, -SQRT2INV, SQRT2INV, -SQRT5OVER2 }, + { -SQRT2INV, SQRT2INV, SQRT2INV, -SQRT5OVER2 }, + { SQRT2INV, SQRT2INV, SQRT2INV, -SQRT5OVER2 }, + { -GOLDENINV2, 0.0, GOLDEN2, -SQRT5OVER2 }, + { GOLDENINV2, 0.0, GOLDEN2, -SQRT5OVER2 }, + { 0.0, 0.0, -SQRT2, -SQRT2 }, + { -SQRT2INV, -GOLDENINV2, -GOLDEN2, -SQRT2 }, + { SQRT2INV, -GOLDENINV2, -GOLDEN2, -SQRT2 }, + { -SQRT2INV, GOLDENINV2, -GOLDEN2, -SQRT2 }, + { SQRT2INV, GOLDENINV2, -GOLDEN2, -SQRT2 }, + { -GOLDENINV2, -GOLDEN2, -SQRT2INV, -SQRT2 }, + { GOLDENINV2, -GOLDEN2, -SQRT2INV, -SQRT2 }, + { -GOLDENINV2, GOLDEN2, -SQRT2INV, -SQRT2 }, + { GOLDENINV2, GOLDEN2, -SQRT2INV, -SQRT2 }, + { -GOLDEN2, -SQRT2INV, -GOLDENINV2, -SQRT2 }, + { GOLDEN2, -SQRT2INV, -GOLDENINV2, -SQRT2 }, + { -GOLDEN2, SQRT2INV, -GOLDENINV2, -SQRT2 }, + { GOLDEN2, SQRT2INV, -GOLDENINV2, -SQRT2 }, + { 0.0, -SQRT2, 0.0, -SQRT2 }, + { -SQRT2, 0.0, 0.0, -SQRT2 }, + { SQRT2, 0.0, 0.0, -SQRT2 }, + { 0.0, SQRT2, 0.0, -SQRT2 }, + { -GOLDEN2, -SQRT2INV, GOLDENINV2, -SQRT2 }, + { GOLDEN2, -SQRT2INV, GOLDENINV2, -SQRT2 }, + { -GOLDEN2, SQRT2INV, GOLDENINV2, -SQRT2 }, + { GOLDEN2, SQRT2INV, GOLDENINV2, -SQRT2 }, + { -GOLDENINV2, -GOLDEN2, SQRT2INV, -SQRT2 }, + { GOLDENINV2, -GOLDEN2, SQRT2INV, -SQRT2 }, + { -GOLDENINV2, GOLDEN2, SQRT2INV, -SQRT2 }, + { GOLDENINV2, GOLDEN2, SQRT2INV, -SQRT2 }, + { -SQRT2INV, -GOLDENINV2, GOLDEN2, -SQRT2 }, + { SQRT2INV, -GOLDENINV2, GOLDEN2, -SQRT2 }, + { -SQRT2INV, GOLDENINV2, GOLDEN2, -SQRT2 }, + { SQRT2INV, GOLDENINV2, GOLDEN2, -SQRT2 }, + { 0.0, 0.0, SQRT2, -SQRT2 }, + { 0.0, -GOLDENINV2, -SQRT5OVER2, -GOLDEN2 }, + { 0.0, GOLDENINV2, -SQRT5OVER2, -GOLDEN2 }, + { -GOLDENINV2, -SQRT2INV, -SQRT2, -GOLDEN2 }, + { GOLDENINV2, -SQRT2INV, -SQRT2, -GOLDEN2 }, + { -GOLDENINV2, SQRT2INV, -SQRT2, -GOLDEN2 }, + { GOLDENINV2, SQRT2INV, -SQRT2, -GOLDEN2 }, + { -GOLDENINV22, -GOLDEN2, -GOLDEN2, -GOLDEN2 }, + { GOLDENINV22, -GOLDEN2, -GOLDEN2, -GOLDEN2 }, + { -GOLDEN2, -GOLDENINV22, -GOLDEN2, -GOLDEN2 }, + { GOLDEN2, -GOLDENINV22, -GOLDEN2, -GOLDEN2 }, + { -GOLDEN2, GOLDENINV22, -GOLDEN2, -GOLDEN2 }, + { GOLDEN2, GOLDENINV22, -GOLDEN2, -GOLDEN2 }, + { -GOLDENINV22, GOLDEN2, -GOLDEN2, -GOLDEN2 }, + { GOLDENINV22, GOLDEN2, -GOLDEN2, -GOLDEN2 }, + { -SQRT2, -GOLDENINV2, -SQRT2INV, -GOLDEN2 }, + { SQRT2, -GOLDENINV2, -SQRT2INV, -GOLDEN2 }, + { -SQRT2, GOLDENINV2, -SQRT2INV, -GOLDEN2 }, + { SQRT2, GOLDENINV2, -SQRT2INV, -GOLDEN2 }, + { -SQRT2INV, -SQRT2, -GOLDENINV2, -GOLDEN2 }, + { SQRT2INV, -SQRT2, -GOLDENINV2, -GOLDEN2 }, + { -SQRT5OVER2, 0.0, -GOLDENINV2, -GOLDEN2 }, + { SQRT5OVER2, 0.0, -GOLDENINV2, -GOLDEN2 }, + { -SQRT2INV, SQRT2, -GOLDENINV2, -GOLDEN2 }, + { SQRT2INV, SQRT2, -GOLDENINV2, -GOLDEN2 }, + { -GOLDEN2, -GOLDEN2, -GOLDENINV22, -GOLDEN2 }, + { GOLDEN2, -GOLDEN2, -GOLDENINV22, -GOLDEN2 }, + { -GOLDEN2, GOLDEN2, -GOLDENINV22, -GOLDEN2 }, + { GOLDEN2, GOLDEN2, -GOLDENINV22, -GOLDEN2 }, + { -GOLDENINV2, -SQRT5OVER2, 0.0, -GOLDEN2 }, + { GOLDENINV2, -SQRT5OVER2, 0.0, -GOLDEN2 }, + { -GOLDENINV2, SQRT5OVER2, 0.0, -GOLDEN2 }, + { GOLDENINV2, SQRT5OVER2, 0.0, -GOLDEN2 }, + { -GOLDEN2, -GOLDEN2, GOLDENINV22, -GOLDEN2 }, + { GOLDEN2, -GOLDEN2, GOLDENINV22, -GOLDEN2 }, + { -GOLDEN2, GOLDEN2, GOLDENINV22, -GOLDEN2 }, + { GOLDEN2, GOLDEN2, GOLDENINV22, -GOLDEN2 }, + { -SQRT2INV, -SQRT2, GOLDENINV2, -GOLDEN2 }, + { SQRT2INV, -SQRT2, GOLDENINV2, -GOLDEN2 }, + { -SQRT5OVER2, 0.0, GOLDENINV2, -GOLDEN2 }, + { SQRT5OVER2, 0.0, GOLDENINV2, -GOLDEN2 }, + { -SQRT2INV, SQRT2, GOLDENINV2, -GOLDEN2 }, + { SQRT2INV, SQRT2, GOLDENINV2, -GOLDEN2 }, + { -SQRT2, -GOLDENINV2, SQRT2INV, -GOLDEN2 }, + { SQRT2, -GOLDENINV2, SQRT2INV, -GOLDEN2 }, + { -SQRT2, GOLDENINV2, SQRT2INV, -GOLDEN2 }, + { SQRT2, GOLDENINV2, SQRT2INV, -GOLDEN2 }, + { -GOLDENINV22, -GOLDEN2, GOLDEN2, -GOLDEN2 }, + { GOLDENINV22, -GOLDEN2, GOLDEN2, -GOLDEN2 }, + { -GOLDEN2, -GOLDENINV22, GOLDEN2, -GOLDEN2 }, + { GOLDEN2, -GOLDENINV22, GOLDEN2, -GOLDEN2 }, + { -GOLDEN2, GOLDENINV22, GOLDEN2, -GOLDEN2 }, + { GOLDEN2, GOLDENINV22, GOLDEN2, -GOLDEN2 }, + { -GOLDENINV22, GOLDEN2, GOLDEN2, -GOLDEN2 }, + { GOLDENINV22, GOLDEN2, GOLDEN2, -GOLDEN2 }, + { -GOLDENINV2, -SQRT2INV, SQRT2, -GOLDEN2 }, + { GOLDENINV2, -SQRT2INV, SQRT2, -GOLDEN2 }, + { -GOLDENINV2, SQRT2INV, SQRT2, -GOLDEN2 }, + { GOLDENINV2, SQRT2INV, SQRT2, -GOLDEN2 }, + { 0.0, -GOLDENINV2, SQRT5OVER2, -GOLDEN2 }, + { 0.0, GOLDENINV2, SQRT5OVER2, -GOLDEN2 }, + { 0.0, -GOLDENINV22, -GOLDEN22, -SQRT2INV }, + { 0.0, GOLDENINV22, -GOLDEN22, -SQRT2INV }, + { -SQRT2INV, -SQRT2INV, -SQRT5OVER2, -SQRT2INV }, + { SQRT2INV, -SQRT2INV, -SQRT5OVER2, -SQRT2INV }, + { -SQRT2INV, SQRT2INV, -SQRT5OVER2, -SQRT2INV }, + { SQRT2INV, SQRT2INV, -SQRT5OVER2, -SQRT2INV }, + { -GOLDEN2, -GOLDENINV2, -SQRT2, -SQRT2INV }, + { GOLDEN2, -GOLDENINV2, -SQRT2, -SQRT2INV }, + { -GOLDEN2, GOLDENINV2, -SQRT2, -SQRT2INV }, + { GOLDEN2, GOLDENINV2, -SQRT2, -SQRT2INV }, + { -GOLDENINV2, -SQRT2, -GOLDEN2, -SQRT2INV }, + { GOLDENINV2, -SQRT2, -GOLDEN2, -SQRT2INV }, + { -GOLDENINV2, SQRT2, -GOLDEN2, -SQRT2INV }, + { GOLDENINV2, SQRT2, -GOLDEN2, -SQRT2INV }, + { -SQRT2INV, -SQRT5OVER2, -SQRT2INV, -SQRT2INV }, + { SQRT2INV, -SQRT5OVER2, -SQRT2INV, -SQRT2INV }, + { -SQRT5OVER2, -SQRT2INV, -SQRT2INV, -SQRT2INV }, + { SQRT5OVER2, -SQRT2INV, -SQRT2INV, -SQRT2INV }, + { -SQRT5OVER2, SQRT2INV, -SQRT2INV, -SQRT2INV }, + { SQRT5OVER2, SQRT2INV, -SQRT2INV, -SQRT2INV }, + { -SQRT2INV, SQRT5OVER2, -SQRT2INV, -SQRT2INV }, + { SQRT2INV, SQRT5OVER2, -SQRT2INV, -SQRT2INV }, + { -SQRT2, -GOLDEN2, -GOLDENINV2, -SQRT2INV }, + { SQRT2, -GOLDEN2, -GOLDENINV2, -SQRT2INV }, + { -SQRT2, GOLDEN2, -GOLDENINV2, -SQRT2INV }, + { SQRT2, GOLDEN2, -GOLDENINV2, -SQRT2INV }, + { -GOLDEN22, 0.0, -GOLDENINV22, -SQRT2INV }, + { GOLDEN22, 0.0, -GOLDENINV22, -SQRT2INV }, + { -GOLDENINV22, -GOLDEN22, 0.0, -SQRT2INV }, + { GOLDENINV22, -GOLDEN22, 0.0, -SQRT2INV }, + { -GOLDENINV22, GOLDEN22, 0.0, -SQRT2INV }, + { GOLDENINV22, GOLDEN22, 0.0, -SQRT2INV }, + { -GOLDEN22, 0.0, GOLDENINV22, -SQRT2INV }, + { GOLDEN22, 0.0, GOLDENINV22, -SQRT2INV }, + { -SQRT2, -GOLDEN2, GOLDENINV2, -SQRT2INV }, + { SQRT2, -GOLDEN2, GOLDENINV2, -SQRT2INV }, + { -SQRT2, GOLDEN2, GOLDENINV2, -SQRT2INV }, + { SQRT2, GOLDEN2, GOLDENINV2, -SQRT2INV }, + { -SQRT2INV, -SQRT5OVER2, SQRT2INV, -SQRT2INV }, + { SQRT2INV, -SQRT5OVER2, SQRT2INV, -SQRT2INV }, + { -SQRT5OVER2, -SQRT2INV, SQRT2INV, -SQRT2INV }, + { SQRT5OVER2, -SQRT2INV, SQRT2INV, -SQRT2INV }, + { -SQRT5OVER2, SQRT2INV, SQRT2INV, -SQRT2INV }, + { SQRT5OVER2, SQRT2INV, SQRT2INV, -SQRT2INV }, + { -SQRT2INV, SQRT5OVER2, SQRT2INV, -SQRT2INV }, + { SQRT2INV, SQRT5OVER2, SQRT2INV, -SQRT2INV }, + { -GOLDENINV2, -SQRT2, GOLDEN2, -SQRT2INV }, + { GOLDENINV2, -SQRT2, GOLDEN2, -SQRT2INV }, + { -GOLDENINV2, SQRT2, GOLDEN2, -SQRT2INV }, + { GOLDENINV2, SQRT2, GOLDEN2, -SQRT2INV }, + { -GOLDEN2, -GOLDENINV2, SQRT2, -SQRT2INV }, + { GOLDEN2, -GOLDENINV2, SQRT2, -SQRT2INV }, + { -GOLDEN2, GOLDENINV2, SQRT2, -SQRT2INV }, + { GOLDEN2, GOLDENINV2, SQRT2, -SQRT2INV }, + { -SQRT2INV, -SQRT2INV, SQRT5OVER2, -SQRT2INV }, + { SQRT2INV, -SQRT2INV, SQRT5OVER2, -SQRT2INV }, + { -SQRT2INV, SQRT2INV, SQRT5OVER2, -SQRT2INV }, + { SQRT2INV, SQRT2INV, SQRT5OVER2, -SQRT2INV }, + { 0.0, -GOLDENINV22, GOLDEN22, -SQRT2INV }, + { 0.0, GOLDENINV22, GOLDEN22, -SQRT2INV }, + { -GOLDENINV2, -GOLDENINV2, -GOLDEN22, -GOLDENINV2 }, + { GOLDENINV2, -GOLDENINV2, -GOLDEN22, -GOLDENINV2 }, + { -GOLDENINV2, GOLDENINV2, -GOLDEN22, -GOLDENINV2 }, + { GOLDENINV2, GOLDENINV2, -GOLDEN22, -GOLDENINV2 }, + { -GOLDEN2, 0.0, -SQRT5OVER2, -GOLDENINV2 }, + { GOLDEN2, 0.0, -SQRT5OVER2, -GOLDENINV2 }, + { -SQRT2INV, -GOLDEN2, -SQRT2, -GOLDENINV2 }, + { SQRT2INV, -GOLDEN2, -SQRT2, -GOLDENINV2 }, + { -SQRT2INV, GOLDEN2, -SQRT2, -GOLDENINV2 }, + { SQRT2INV, GOLDEN2, -SQRT2, -GOLDENINV2 }, + { 0.0, -SQRT5OVER2, -GOLDEN2, -GOLDENINV2 }, + { -SQRT2, -SQRT2INV, -GOLDEN2, -GOLDENINV2 }, + { SQRT2, -SQRT2INV, -GOLDEN2, -GOLDENINV2 }, + { -SQRT2, SQRT2INV, -GOLDEN2, -GOLDENINV2 }, + { SQRT2, SQRT2INV, -GOLDEN2, -GOLDENINV2 }, + { 0.0, SQRT5OVER2, -GOLDEN2, -GOLDENINV2 }, + { -GOLDEN2, -SQRT2, -SQRT2INV, -GOLDENINV2 }, + { GOLDEN2, -SQRT2, -SQRT2INV, -GOLDENINV2 }, + { -GOLDEN2, SQRT2, -SQRT2INV, -GOLDENINV2 }, + { GOLDEN2, SQRT2, -SQRT2INV, -GOLDENINV2 }, + { -GOLDENINV2, -GOLDEN22, -GOLDENINV2, -GOLDENINV2 }, + { GOLDENINV2, -GOLDEN22, -GOLDENINV2, -GOLDENINV2 }, + { -GOLDEN22, -GOLDENINV2, -GOLDENINV2, -GOLDENINV2 }, + { GOLDEN22, -GOLDENINV2, -GOLDENINV2, -GOLDENINV2 }, + { -GOLDEN22, GOLDENINV2, -GOLDENINV2, -GOLDENINV2 }, + { GOLDEN22, GOLDENINV2, -GOLDENINV2, -GOLDENINV2 }, + { -GOLDENINV2, GOLDEN22, -GOLDENINV2, -GOLDENINV2 }, + { GOLDENINV2, GOLDEN22, -GOLDENINV2, -GOLDENINV2 }, + { -SQRT5OVER2, -GOLDEN2, 0.0, -GOLDENINV2 }, + { SQRT5OVER2, -GOLDEN2, 0.0, -GOLDENINV2 }, + { -SQRT5OVER2, GOLDEN2, 0.0, -GOLDENINV2 }, + { SQRT5OVER2, GOLDEN2, 0.0, -GOLDENINV2 }, + { -GOLDENINV2, -GOLDEN22, GOLDENINV2, -GOLDENINV2 }, + { GOLDENINV2, -GOLDEN22, GOLDENINV2, -GOLDENINV2 }, + { -GOLDEN22, -GOLDENINV2, GOLDENINV2, -GOLDENINV2 }, + { GOLDEN22, -GOLDENINV2, GOLDENINV2, -GOLDENINV2 }, + { -GOLDEN22, GOLDENINV2, GOLDENINV2, -GOLDENINV2 }, + { GOLDEN22, GOLDENINV2, GOLDENINV2, -GOLDENINV2 }, + { -GOLDENINV2, GOLDEN22, GOLDENINV2, -GOLDENINV2 }, + { GOLDENINV2, GOLDEN22, GOLDENINV2, -GOLDENINV2 }, + { -GOLDEN2, -SQRT2, SQRT2INV, -GOLDENINV2 }, + { GOLDEN2, -SQRT2, SQRT2INV, -GOLDENINV2 }, + { -GOLDEN2, SQRT2, SQRT2INV, -GOLDENINV2 }, + { GOLDEN2, SQRT2, SQRT2INV, -GOLDENINV2 }, + { 0.0, -SQRT5OVER2, GOLDEN2, -GOLDENINV2 }, + { -SQRT2, -SQRT2INV, GOLDEN2, -GOLDENINV2 }, + { SQRT2, -SQRT2INV, GOLDEN2, -GOLDENINV2 }, + { -SQRT2, SQRT2INV, GOLDEN2, -GOLDENINV2 }, + { SQRT2, SQRT2INV, GOLDEN2, -GOLDENINV2 }, + { 0.0, SQRT5OVER2, GOLDEN2, -GOLDENINV2 }, + { -SQRT2INV, -GOLDEN2, SQRT2, -GOLDENINV2 }, + { SQRT2INV, -GOLDEN2, SQRT2, -GOLDENINV2 }, + { -SQRT2INV, GOLDEN2, SQRT2, -GOLDENINV2 }, + { SQRT2INV, GOLDEN2, SQRT2, -GOLDENINV2 }, + { -GOLDEN2, 0.0, SQRT5OVER2, -GOLDENINV2 }, + { GOLDEN2, 0.0, SQRT5OVER2, -GOLDENINV2 }, + { -GOLDENINV2, -GOLDENINV2, GOLDEN22, -GOLDENINV2 }, + { GOLDENINV2, -GOLDENINV2, GOLDEN22, -GOLDENINV2 }, + { -GOLDENINV2, GOLDENINV2, GOLDEN22, -GOLDENINV2 }, + { GOLDENINV2, GOLDENINV2, GOLDEN22, -GOLDENINV2 }, + { -SQRT2INV, 0.0, -GOLDEN22, -GOLDENINV22 }, + { SQRT2INV, 0.0, -GOLDEN22, -GOLDENINV22 }, + { -GOLDEN2, -GOLDEN2, -GOLDEN2, -GOLDENINV22 }, + { GOLDEN2, -GOLDEN2, -GOLDEN2, -GOLDENINV22 }, + { -GOLDEN2, GOLDEN2, -GOLDEN2, -GOLDENINV22 }, + { GOLDEN2, GOLDEN2, -GOLDEN2, -GOLDENINV22 }, + { 0.0, -GOLDEN22, -SQRT2INV, -GOLDENINV22 }, + { 0.0, GOLDEN22, -SQRT2INV, -GOLDENINV22 }, + { -GOLDEN22, -SQRT2INV, 0.0, -GOLDENINV22 }, + { GOLDEN22, -SQRT2INV, 0.0, -GOLDENINV22 }, + { -GOLDEN22, SQRT2INV, 0.0, -GOLDENINV22 }, + { GOLDEN22, SQRT2INV, 0.0, -GOLDENINV22 }, + { 0.0, -GOLDEN22, SQRT2INV, -GOLDENINV22 }, + { 0.0, GOLDEN22, SQRT2INV, -GOLDENINV22 }, + { -GOLDEN2, -GOLDEN2, GOLDEN2, -GOLDENINV22 }, + { GOLDEN2, -GOLDEN2, GOLDEN2, -GOLDENINV22 }, + { -GOLDEN2, GOLDEN2, GOLDEN2, -GOLDENINV22 }, + { GOLDEN2, GOLDEN2, GOLDEN2, -GOLDENINV22 }, + { -SQRT2INV, 0.0, GOLDEN22, -GOLDENINV22 }, + { SQRT2INV, 0.0, GOLDEN22, -GOLDENINV22 }, + { -GOLDENINV22, -SQRT2INV, -GOLDEN22, 0.0 }, + { GOLDENINV22, -SQRT2INV, -GOLDEN22, 0.0 }, + { -GOLDENINV22, SQRT2INV, -GOLDEN22, 0.0 }, + { GOLDENINV22, SQRT2INV, -GOLDEN22, 0.0 }, + { -GOLDENINV2, -GOLDEN2, -SQRT5OVER2, 0.0 }, + { GOLDENINV2, -GOLDEN2, -SQRT5OVER2, 0.0 }, + { -GOLDENINV2, GOLDEN2, -SQRT5OVER2, 0.0 }, + { GOLDENINV2, GOLDEN2, -SQRT5OVER2, 0.0 }, + { 0.0, -SQRT2, -SQRT2, 0.0 }, + { -SQRT2, 0.0, -SQRT2, 0.0 }, + { SQRT2, 0.0, -SQRT2, 0.0 }, + { 0.0, SQRT2, -SQRT2, 0.0 }, + { -SQRT5OVER2, -GOLDENINV2, -GOLDEN2, 0.0 }, + { SQRT5OVER2, -GOLDENINV2, -GOLDEN2, 0.0 }, + { -SQRT5OVER2, GOLDENINV2, -GOLDEN2, 0.0 }, + { SQRT5OVER2, GOLDENINV2, -GOLDEN2, 0.0 }, + { -GOLDEN22, -GOLDENINV22, -SQRT2INV, 0.0 }, + { GOLDEN22, -GOLDENINV22, -SQRT2INV, 0.0 }, + { -GOLDEN22, GOLDENINV22, -SQRT2INV, 0.0 }, + { GOLDEN22, GOLDENINV22, -SQRT2INV, 0.0 }, + { -GOLDEN2, -SQRT5OVER2, -GOLDENINV2, 0.0 }, + { GOLDEN2, -SQRT5OVER2, -GOLDENINV2, 0.0 }, + { -GOLDEN2, SQRT5OVER2, -GOLDENINV2, 0.0 }, + { GOLDEN2, SQRT5OVER2, -GOLDENINV2, 0.0 }, + { -SQRT2INV, -GOLDEN22, -GOLDENINV22, 0.0 }, + { SQRT2INV, -GOLDEN22, -GOLDENINV22, 0.0 }, + { -SQRT2INV, GOLDEN22, -GOLDENINV22, 0.0 }, + { SQRT2INV, GOLDEN22, -GOLDENINV22, 0.0 }, + { -SQRT2, -SQRT2, 0.0, 0.0 }, + { SQRT2, -SQRT2, 0.0, 0.0 }, + { -SQRT2, SQRT2, 0.0, 0.0 }, + { SQRT2, SQRT2, 0.0, 0.0 }, + { -SQRT2INV, -GOLDEN22, GOLDENINV22, 0.0 }, + { SQRT2INV, -GOLDEN22, GOLDENINV22, 0.0 }, + { -SQRT2INV, GOLDEN22, GOLDENINV22, 0.0 }, + { SQRT2INV, GOLDEN22, GOLDENINV22, 0.0 }, + { -GOLDEN2, -SQRT5OVER2, GOLDENINV2, 0.0 }, + { GOLDEN2, -SQRT5OVER2, GOLDENINV2, 0.0 }, + { -GOLDEN2, SQRT5OVER2, GOLDENINV2, 0.0 }, + { GOLDEN2, SQRT5OVER2, GOLDENINV2, 0.0 }, + { -GOLDEN22, -GOLDENINV22, SQRT2INV, 0.0 }, + { GOLDEN22, -GOLDENINV22, SQRT2INV, 0.0 }, + { -GOLDEN22, GOLDENINV22, SQRT2INV, 0.0 }, + { GOLDEN22, GOLDENINV22, SQRT2INV, 0.0 }, + { -SQRT5OVER2, -GOLDENINV2, GOLDEN2, 0.0 }, + { SQRT5OVER2, -GOLDENINV2, GOLDEN2, 0.0 }, + { -SQRT5OVER2, GOLDENINV2, GOLDEN2, 0.0 }, + { SQRT5OVER2, GOLDENINV2, GOLDEN2, 0.0 }, + { 0.0, -SQRT2, SQRT2, 0.0 }, + { -SQRT2, 0.0, SQRT2, 0.0 }, + { SQRT2, 0.0, SQRT2, 0.0 }, + { 0.0, SQRT2, SQRT2, 0.0 }, + { -GOLDENINV2, -GOLDEN2, SQRT5OVER2, 0.0 }, + { GOLDENINV2, -GOLDEN2, SQRT5OVER2, 0.0 }, + { -GOLDENINV2, GOLDEN2, SQRT5OVER2, 0.0 }, + { GOLDENINV2, GOLDEN2, SQRT5OVER2, 0.0 }, + { -GOLDENINV22, -SQRT2INV, GOLDEN22, 0.0 }, + { GOLDENINV22, -SQRT2INV, GOLDEN22, 0.0 }, + { -GOLDENINV22, SQRT2INV, GOLDEN22, 0.0 }, + { GOLDENINV22, SQRT2INV, GOLDEN22, 0.0 }, + { -SQRT2INV, 0.0, -GOLDEN22, GOLDENINV22 }, + { SQRT2INV, 0.0, -GOLDEN22, GOLDENINV22 }, + { -GOLDEN2, -GOLDEN2, -GOLDEN2, GOLDENINV22 }, + { GOLDEN2, -GOLDEN2, -GOLDEN2, GOLDENINV22 }, + { -GOLDEN2, GOLDEN2, -GOLDEN2, GOLDENINV22 }, + { GOLDEN2, GOLDEN2, -GOLDEN2, GOLDENINV22 }, + { 0.0, -GOLDEN22, -SQRT2INV, GOLDENINV22 }, + { 0.0, GOLDEN22, -SQRT2INV, GOLDENINV22 }, + { -GOLDEN22, -SQRT2INV, 0.0, GOLDENINV22 }, + { GOLDEN22, -SQRT2INV, 0.0, GOLDENINV22 }, + { -GOLDEN22, SQRT2INV, 0.0, GOLDENINV22 }, + { GOLDEN22, SQRT2INV, 0.0, GOLDENINV22 }, + { 0.0, -GOLDEN22, SQRT2INV, GOLDENINV22 }, + { 0.0, GOLDEN22, SQRT2INV, GOLDENINV22 }, + { -GOLDEN2, -GOLDEN2, GOLDEN2, GOLDENINV22 }, + { GOLDEN2, -GOLDEN2, GOLDEN2, GOLDENINV22 }, + { -GOLDEN2, GOLDEN2, GOLDEN2, GOLDENINV22 }, + { GOLDEN2, GOLDEN2, GOLDEN2, GOLDENINV22 }, + { -SQRT2INV, 0.0, GOLDEN22, GOLDENINV22 }, + { SQRT2INV, 0.0, GOLDEN22, GOLDENINV22 }, + { -GOLDENINV2, -GOLDENINV2, -GOLDEN22, GOLDENINV2 }, + { GOLDENINV2, -GOLDENINV2, -GOLDEN22, GOLDENINV2 }, + { -GOLDENINV2, GOLDENINV2, -GOLDEN22, GOLDENINV2 }, + { GOLDENINV2, GOLDENINV2, -GOLDEN22, GOLDENINV2 }, + { -GOLDEN2, 0.0, -SQRT5OVER2, GOLDENINV2 }, + { GOLDEN2, 0.0, -SQRT5OVER2, GOLDENINV2 }, + { -SQRT2INV, -GOLDEN2, -SQRT2, GOLDENINV2 }, + { SQRT2INV, -GOLDEN2, -SQRT2, GOLDENINV2 }, + { -SQRT2INV, GOLDEN2, -SQRT2, GOLDENINV2 }, + { SQRT2INV, GOLDEN2, -SQRT2, GOLDENINV2 }, + { 0.0, -SQRT5OVER2, -GOLDEN2, GOLDENINV2 }, + { -SQRT2, -SQRT2INV, -GOLDEN2, GOLDENINV2 }, + { SQRT2, -SQRT2INV, -GOLDEN2, GOLDENINV2 }, + { -SQRT2, SQRT2INV, -GOLDEN2, GOLDENINV2 }, + { SQRT2, SQRT2INV, -GOLDEN2, GOLDENINV2 }, + { 0.0, SQRT5OVER2, -GOLDEN2, GOLDENINV2 }, + { -GOLDEN2, -SQRT2, -SQRT2INV, GOLDENINV2 }, + { GOLDEN2, -SQRT2, -SQRT2INV, GOLDENINV2 }, + { -GOLDEN2, SQRT2, -SQRT2INV, GOLDENINV2 }, + { GOLDEN2, SQRT2, -SQRT2INV, GOLDENINV2 }, + { -GOLDENINV2, -GOLDEN22, -GOLDENINV2, GOLDENINV2 }, + { GOLDENINV2, -GOLDEN22, -GOLDENINV2, GOLDENINV2 }, + { -GOLDEN22, -GOLDENINV2, -GOLDENINV2, GOLDENINV2 }, + { GOLDEN22, -GOLDENINV2, -GOLDENINV2, GOLDENINV2 }, + { -GOLDEN22, GOLDENINV2, -GOLDENINV2, GOLDENINV2 }, + { GOLDEN22, GOLDENINV2, -GOLDENINV2, GOLDENINV2 }, + { -GOLDENINV2, GOLDEN22, -GOLDENINV2, GOLDENINV2 }, + { GOLDENINV2, GOLDEN22, -GOLDENINV2, GOLDENINV2 }, + { -SQRT5OVER2, -GOLDEN2, 0.0, GOLDENINV2 }, + { SQRT5OVER2, -GOLDEN2, 0.0, GOLDENINV2 }, + { -SQRT5OVER2, GOLDEN2, 0.0, GOLDENINV2 }, + { SQRT5OVER2, GOLDEN2, 0.0, GOLDENINV2 }, + { -GOLDENINV2, -GOLDEN22, GOLDENINV2, GOLDENINV2 }, + { GOLDENINV2, -GOLDEN22, GOLDENINV2, GOLDENINV2 }, + { -GOLDEN22, -GOLDENINV2, GOLDENINV2, GOLDENINV2 }, + { GOLDEN22, -GOLDENINV2, GOLDENINV2, GOLDENINV2 }, + { -GOLDEN22, GOLDENINV2, GOLDENINV2, GOLDENINV2 }, + { GOLDEN22, GOLDENINV2, GOLDENINV2, GOLDENINV2 }, + { -GOLDENINV2, GOLDEN22, GOLDENINV2, GOLDENINV2 }, + { GOLDENINV2, GOLDEN22, GOLDENINV2, GOLDENINV2 }, + { -GOLDEN2, -SQRT2, SQRT2INV, GOLDENINV2 }, + { GOLDEN2, -SQRT2, SQRT2INV, GOLDENINV2 }, + { -GOLDEN2, SQRT2, SQRT2INV, GOLDENINV2 }, + { GOLDEN2, SQRT2, SQRT2INV, GOLDENINV2 }, + { 0.0, -SQRT5OVER2, GOLDEN2, GOLDENINV2 }, + { -SQRT2, -SQRT2INV, GOLDEN2, GOLDENINV2 }, + { SQRT2, -SQRT2INV, GOLDEN2, GOLDENINV2 }, + { -SQRT2, SQRT2INV, GOLDEN2, GOLDENINV2 }, + { SQRT2, SQRT2INV, GOLDEN2, GOLDENINV2 }, + { 0.0, SQRT5OVER2, GOLDEN2, GOLDENINV2 }, + { -SQRT2INV, -GOLDEN2, SQRT2, GOLDENINV2 }, + { SQRT2INV, -GOLDEN2, SQRT2, GOLDENINV2 }, + { -SQRT2INV, GOLDEN2, SQRT2, GOLDENINV2 }, + { SQRT2INV, GOLDEN2, SQRT2, GOLDENINV2 }, + { -GOLDEN2, 0.0, SQRT5OVER2, GOLDENINV2 }, + { GOLDEN2, 0.0, SQRT5OVER2, GOLDENINV2 }, + { -GOLDENINV2, -GOLDENINV2, GOLDEN22, GOLDENINV2 }, + { GOLDENINV2, -GOLDENINV2, GOLDEN22, GOLDENINV2 }, + { -GOLDENINV2, GOLDENINV2, GOLDEN22, GOLDENINV2 }, + { GOLDENINV2, GOLDENINV2, GOLDEN22, GOLDENINV2 }, + { 0.0, -GOLDENINV22, -GOLDEN22, SQRT2INV }, + { 0.0, GOLDENINV22, -GOLDEN22, SQRT2INV }, + { -SQRT2INV, -SQRT2INV, -SQRT5OVER2, SQRT2INV }, + { SQRT2INV, -SQRT2INV, -SQRT5OVER2, SQRT2INV }, + { -SQRT2INV, SQRT2INV, -SQRT5OVER2, SQRT2INV }, + { SQRT2INV, SQRT2INV, -SQRT5OVER2, SQRT2INV }, + { -GOLDEN2, -GOLDENINV2, -SQRT2, SQRT2INV }, + { GOLDEN2, -GOLDENINV2, -SQRT2, SQRT2INV }, + { -GOLDEN2, GOLDENINV2, -SQRT2, SQRT2INV }, + { GOLDEN2, GOLDENINV2, -SQRT2, SQRT2INV }, + { -GOLDENINV2, -SQRT2, -GOLDEN2, SQRT2INV }, + { GOLDENINV2, -SQRT2, -GOLDEN2, SQRT2INV }, + { -GOLDENINV2, SQRT2, -GOLDEN2, SQRT2INV }, + { GOLDENINV2, SQRT2, -GOLDEN2, SQRT2INV }, + { -SQRT2INV, -SQRT5OVER2, -SQRT2INV, SQRT2INV }, + { SQRT2INV, -SQRT5OVER2, -SQRT2INV, SQRT2INV }, + { -SQRT5OVER2, -SQRT2INV, -SQRT2INV, SQRT2INV }, + { SQRT5OVER2, -SQRT2INV, -SQRT2INV, SQRT2INV }, + { -SQRT5OVER2, SQRT2INV, -SQRT2INV, SQRT2INV }, + { SQRT5OVER2, SQRT2INV, -SQRT2INV, SQRT2INV }, + { -SQRT2INV, SQRT5OVER2, -SQRT2INV, SQRT2INV }, + { SQRT2INV, SQRT5OVER2, -SQRT2INV, SQRT2INV }, + { -SQRT2, -GOLDEN2, -GOLDENINV2, SQRT2INV }, + { SQRT2, -GOLDEN2, -GOLDENINV2, SQRT2INV }, + { -SQRT2, GOLDEN2, -GOLDENINV2, SQRT2INV }, + { SQRT2, GOLDEN2, -GOLDENINV2, SQRT2INV }, + { -GOLDEN22, 0.0, -GOLDENINV22, SQRT2INV }, + { GOLDEN22, 0.0, -GOLDENINV22, SQRT2INV }, + { -GOLDENINV22, -GOLDEN22, 0.0, SQRT2INV }, + { GOLDENINV22, -GOLDEN22, 0.0, SQRT2INV }, + { -GOLDENINV22, GOLDEN22, 0.0, SQRT2INV }, + { GOLDENINV22, GOLDEN22, 0.0, SQRT2INV }, + { -GOLDEN22, 0.0, GOLDENINV22, SQRT2INV }, + { GOLDEN22, 0.0, GOLDENINV22, SQRT2INV }, + { -SQRT2, -GOLDEN2, GOLDENINV2, SQRT2INV }, + { SQRT2, -GOLDEN2, GOLDENINV2, SQRT2INV }, + { -SQRT2, GOLDEN2, GOLDENINV2, SQRT2INV }, + { SQRT2, GOLDEN2, GOLDENINV2, SQRT2INV }, + { -SQRT2INV, -SQRT5OVER2, SQRT2INV, SQRT2INV }, + { SQRT2INV, -SQRT5OVER2, SQRT2INV, SQRT2INV }, + { -SQRT5OVER2, -SQRT2INV, SQRT2INV, SQRT2INV }, + { SQRT5OVER2, -SQRT2INV, SQRT2INV, SQRT2INV }, + { -SQRT5OVER2, SQRT2INV, SQRT2INV, SQRT2INV }, + { SQRT5OVER2, SQRT2INV, SQRT2INV, SQRT2INV }, + { -SQRT2INV, SQRT5OVER2, SQRT2INV, SQRT2INV }, + { SQRT2INV, SQRT5OVER2, SQRT2INV, SQRT2INV }, + { -GOLDENINV2, -SQRT2, GOLDEN2, SQRT2INV }, + { GOLDENINV2, -SQRT2, GOLDEN2, SQRT2INV }, + { -GOLDENINV2, SQRT2, GOLDEN2, SQRT2INV }, + { GOLDENINV2, SQRT2, GOLDEN2, SQRT2INV }, + { -GOLDEN2, -GOLDENINV2, SQRT2, SQRT2INV }, + { GOLDEN2, -GOLDENINV2, SQRT2, SQRT2INV }, + { -GOLDEN2, GOLDENINV2, SQRT2, SQRT2INV }, + { GOLDEN2, GOLDENINV2, SQRT2, SQRT2INV }, + { -SQRT2INV, -SQRT2INV, SQRT5OVER2, SQRT2INV }, + { SQRT2INV, -SQRT2INV, SQRT5OVER2, SQRT2INV }, + { -SQRT2INV, SQRT2INV, SQRT5OVER2, SQRT2INV }, + { SQRT2INV, SQRT2INV, SQRT5OVER2, SQRT2INV }, + { 0.0, -GOLDENINV22, GOLDEN22, SQRT2INV }, + { 0.0, GOLDENINV22, GOLDEN22, SQRT2INV }, + { 0.0, -GOLDENINV2, -SQRT5OVER2, GOLDEN2 }, + { 0.0, GOLDENINV2, -SQRT5OVER2, GOLDEN2 }, + { -GOLDENINV2, -SQRT2INV, -SQRT2, GOLDEN2 }, + { GOLDENINV2, -SQRT2INV, -SQRT2, GOLDEN2 }, + { -GOLDENINV2, SQRT2INV, -SQRT2, GOLDEN2 }, + { GOLDENINV2, SQRT2INV, -SQRT2, GOLDEN2 }, + { -GOLDENINV22, -GOLDEN2, -GOLDEN2, GOLDEN2 }, + { GOLDENINV22, -GOLDEN2, -GOLDEN2, GOLDEN2 }, + { -GOLDEN2, -GOLDENINV22, -GOLDEN2, GOLDEN2 }, + { GOLDEN2, -GOLDENINV22, -GOLDEN2, GOLDEN2 }, + { -GOLDEN2, GOLDENINV22, -GOLDEN2, GOLDEN2 }, + { GOLDEN2, GOLDENINV22, -GOLDEN2, GOLDEN2 }, + { -GOLDENINV22, GOLDEN2, -GOLDEN2, GOLDEN2 }, + { GOLDENINV22, GOLDEN2, -GOLDEN2, GOLDEN2 }, + { -SQRT2, -GOLDENINV2, -SQRT2INV, GOLDEN2 }, + { SQRT2, -GOLDENINV2, -SQRT2INV, GOLDEN2 }, + { -SQRT2, GOLDENINV2, -SQRT2INV, GOLDEN2 }, + { SQRT2, GOLDENINV2, -SQRT2INV, GOLDEN2 }, + { -SQRT2INV, -SQRT2, -GOLDENINV2, GOLDEN2 }, + { SQRT2INV, -SQRT2, -GOLDENINV2, GOLDEN2 }, + { -SQRT5OVER2, 0.0, -GOLDENINV2, GOLDEN2 }, + { SQRT5OVER2, 0.0, -GOLDENINV2, GOLDEN2 }, + { -SQRT2INV, SQRT2, -GOLDENINV2, GOLDEN2 }, + { SQRT2INV, SQRT2, -GOLDENINV2, GOLDEN2 }, + { -GOLDEN2, -GOLDEN2, -GOLDENINV22, GOLDEN2 }, + { GOLDEN2, -GOLDEN2, -GOLDENINV22, GOLDEN2 }, + { -GOLDEN2, GOLDEN2, -GOLDENINV22, GOLDEN2 }, + { GOLDEN2, GOLDEN2, -GOLDENINV22, GOLDEN2 }, + { -GOLDENINV2, -SQRT5OVER2, 0.0, GOLDEN2 }, + { GOLDENINV2, -SQRT5OVER2, 0.0, GOLDEN2 }, + { -GOLDENINV2, SQRT5OVER2, 0.0, GOLDEN2 }, + { GOLDENINV2, SQRT5OVER2, 0.0, GOLDEN2 }, + { -GOLDEN2, -GOLDEN2, GOLDENINV22, GOLDEN2 }, + { GOLDEN2, -GOLDEN2, GOLDENINV22, GOLDEN2 }, + { -GOLDEN2, GOLDEN2, GOLDENINV22, GOLDEN2 }, + { GOLDEN2, GOLDEN2, GOLDENINV22, GOLDEN2 }, + { -SQRT2INV, -SQRT2, GOLDENINV2, GOLDEN2 }, + { SQRT2INV, -SQRT2, GOLDENINV2, GOLDEN2 }, + { -SQRT5OVER2, 0.0, GOLDENINV2, GOLDEN2 }, + { SQRT5OVER2, 0.0, GOLDENINV2, GOLDEN2 }, + { -SQRT2INV, SQRT2, GOLDENINV2, GOLDEN2 }, + { SQRT2INV, SQRT2, GOLDENINV2, GOLDEN2 }, + { -SQRT2, -GOLDENINV2, SQRT2INV, GOLDEN2 }, + { SQRT2, -GOLDENINV2, SQRT2INV, GOLDEN2 }, + { -SQRT2, GOLDENINV2, SQRT2INV, GOLDEN2 }, + { SQRT2, GOLDENINV2, SQRT2INV, GOLDEN2 }, + { -GOLDENINV22, -GOLDEN2, GOLDEN2, GOLDEN2 }, + { GOLDENINV22, -GOLDEN2, GOLDEN2, GOLDEN2 }, + { -GOLDEN2, -GOLDENINV22, GOLDEN2, GOLDEN2 }, + { GOLDEN2, -GOLDENINV22, GOLDEN2, GOLDEN2 }, + { -GOLDEN2, GOLDENINV22, GOLDEN2, GOLDEN2 }, + { GOLDEN2, GOLDENINV22, GOLDEN2, GOLDEN2 }, + { -GOLDENINV22, GOLDEN2, GOLDEN2, GOLDEN2 }, + { GOLDENINV22, GOLDEN2, GOLDEN2, GOLDEN2 }, + { -GOLDENINV2, -SQRT2INV, SQRT2, GOLDEN2 }, + { GOLDENINV2, -SQRT2INV, SQRT2, GOLDEN2 }, + { -GOLDENINV2, SQRT2INV, SQRT2, GOLDEN2 }, + { GOLDENINV2, SQRT2INV, SQRT2, GOLDEN2 }, + { 0.0, -GOLDENINV2, SQRT5OVER2, GOLDEN2 }, + { 0.0, GOLDENINV2, SQRT5OVER2, GOLDEN2 }, + { 0.0, 0.0, -SQRT2, SQRT2 }, + { -SQRT2INV, -GOLDENINV2, -GOLDEN2, SQRT2 }, + { SQRT2INV, -GOLDENINV2, -GOLDEN2, SQRT2 }, + { -SQRT2INV, GOLDENINV2, -GOLDEN2, SQRT2 }, + { SQRT2INV, GOLDENINV2, -GOLDEN2, SQRT2 }, + { -GOLDENINV2, -GOLDEN2, -SQRT2INV, SQRT2 }, + { GOLDENINV2, -GOLDEN2, -SQRT2INV, SQRT2 }, + { -GOLDENINV2, GOLDEN2, -SQRT2INV, SQRT2 }, + { GOLDENINV2, GOLDEN2, -SQRT2INV, SQRT2 }, + { -GOLDEN2, -SQRT2INV, -GOLDENINV2, SQRT2 }, + { GOLDEN2, -SQRT2INV, -GOLDENINV2, SQRT2 }, + { -GOLDEN2, SQRT2INV, -GOLDENINV2, SQRT2 }, + { GOLDEN2, SQRT2INV, -GOLDENINV2, SQRT2 }, + { 0.0, -SQRT2, 0.0, SQRT2 }, + { -SQRT2, 0.0, 0.0, SQRT2 }, + { SQRT2, 0.0, 0.0, SQRT2 }, + { 0.0, SQRT2, 0.0, SQRT2 }, + { -GOLDEN2, -SQRT2INV, GOLDENINV2, SQRT2 }, + { GOLDEN2, -SQRT2INV, GOLDENINV2, SQRT2 }, + { -GOLDEN2, SQRT2INV, GOLDENINV2, SQRT2 }, + { GOLDEN2, SQRT2INV, GOLDENINV2, SQRT2 }, + { -GOLDENINV2, -GOLDEN2, SQRT2INV, SQRT2 }, + { GOLDENINV2, -GOLDEN2, SQRT2INV, SQRT2 }, + { -GOLDENINV2, GOLDEN2, SQRT2INV, SQRT2 }, + { GOLDENINV2, GOLDEN2, SQRT2INV, SQRT2 }, + { -SQRT2INV, -GOLDENINV2, GOLDEN2, SQRT2 }, + { SQRT2INV, -GOLDENINV2, GOLDEN2, SQRT2 }, + { -SQRT2INV, GOLDENINV2, GOLDEN2, SQRT2 }, + { SQRT2INV, GOLDENINV2, GOLDEN2, SQRT2 }, + { 0.0, 0.0, SQRT2, SQRT2 }, + { -GOLDENINV2, 0.0, -GOLDEN2, SQRT5OVER2 }, + { GOLDENINV2, 0.0, -GOLDEN2, SQRT5OVER2 }, + { -SQRT2INV, -SQRT2INV, -SQRT2INV, SQRT5OVER2 }, + { SQRT2INV, -SQRT2INV, -SQRT2INV, SQRT5OVER2 }, + { -SQRT2INV, SQRT2INV, -SQRT2INV, SQRT5OVER2 }, + { SQRT2INV, SQRT2INV, -SQRT2INV, SQRT5OVER2 }, + { 0.0, -GOLDEN2, -GOLDENINV2, SQRT5OVER2 }, + { 0.0, GOLDEN2, -GOLDENINV2, SQRT5OVER2 }, + { -GOLDEN2, -GOLDENINV2, 0.0, SQRT5OVER2 }, + { GOLDEN2, -GOLDENINV2, 0.0, SQRT5OVER2 }, + { -GOLDEN2, GOLDENINV2, 0.0, SQRT5OVER2 }, + { GOLDEN2, GOLDENINV2, 0.0, SQRT5OVER2 }, + { 0.0, -GOLDEN2, GOLDENINV2, SQRT5OVER2 }, + { 0.0, GOLDEN2, GOLDENINV2, SQRT5OVER2 }, + { -SQRT2INV, -SQRT2INV, SQRT2INV, SQRT5OVER2 }, + { SQRT2INV, -SQRT2INV, SQRT2INV, SQRT5OVER2 }, + { -SQRT2INV, SQRT2INV, SQRT2INV, SQRT5OVER2 }, + { SQRT2INV, SQRT2INV, SQRT2INV, SQRT5OVER2 }, + { -GOLDENINV2, 0.0, GOLDEN2, SQRT5OVER2 }, + { GOLDENINV2, 0.0, GOLDEN2, SQRT5OVER2 }, + { -GOLDENINV22, 0.0, -SQRT2INV, GOLDEN22 }, + { GOLDENINV22, 0.0, -SQRT2INV, GOLDEN22 }, + { -GOLDENINV2, -GOLDENINV2, -GOLDENINV2, GOLDEN22 }, + { GOLDENINV2, -GOLDENINV2, -GOLDENINV2, GOLDEN22 }, + { -GOLDENINV2, GOLDENINV2, -GOLDENINV2, GOLDEN22 }, + { GOLDENINV2, GOLDENINV2, -GOLDENINV2, GOLDEN22 }, + { 0.0, -SQRT2INV, -GOLDENINV22, GOLDEN22 }, + { 0.0, SQRT2INV, -GOLDENINV22, GOLDEN22 }, + { -SQRT2INV, -GOLDENINV22, 0.0, GOLDEN22 }, + { SQRT2INV, -GOLDENINV22, 0.0, GOLDEN22 }, + { -SQRT2INV, GOLDENINV22, 0.0, GOLDEN22 }, + { SQRT2INV, GOLDENINV22, 0.0, GOLDEN22 }, + { 0.0, -SQRT2INV, GOLDENINV22, GOLDEN22 }, + { 0.0, SQRT2INV, GOLDENINV22, GOLDEN22 }, + { -GOLDENINV2, -GOLDENINV2, GOLDENINV2, GOLDEN22 }, + { GOLDENINV2, -GOLDENINV2, GOLDENINV2, GOLDEN22 }, + { -GOLDENINV2, GOLDENINV2, GOLDENINV2, GOLDEN22 }, + { GOLDENINV2, GOLDENINV2, GOLDENINV2, GOLDEN22 }, + { -GOLDENINV22, 0.0, SQRT2INV, GOLDEN22 }, + { GOLDENINV22, 0.0, SQRT2INV, GOLDEN22 } +}; + +static const int edge_120[NUM_EDGE_120][2] = { + { 0, 1 }, { 0, 2 }, { 0, 4 }, { 0, 20 }, { 1, 3 }, + { 1, 5 }, { 1, 21 }, { 2, 6 }, { 2, 8 }, { 2, 22 }, + { 3, 6 }, { 3, 9 }, { 3, 23 }, { 4, 7 }, { 4, 10 }, + { 4, 24 }, { 5, 7 }, { 5, 11 }, { 5, 25 }, { 6, 12 }, + { 6, 26 }, { 7, 13 }, { 7, 27 }, { 8, 10 }, { 8, 14 }, + { 8, 28 }, { 9, 11 }, { 9, 15 }, { 9, 29 }, { 10, 16 }, + { 10, 30 }, { 11, 17 }, { 11, 31 }, { 12, 14 }, { 12, 15 }, + { 12, 32 }, { 13, 16 }, { 13, 17 }, { 13, 33 }, { 14, 18 }, + { 14, 34 }, { 15, 19 }, { 15, 35 }, { 16, 18 }, { 16, 36 }, + { 17, 19 }, { 17, 37 }, { 18, 19 }, { 18, 38 }, { 19, 39 }, + { 20, 40 }, { 20, 41 }, { 20, 43 }, { 21, 40 }, { 21, 42 }, + { 21, 44 }, { 22, 41 }, { 22, 45 }, { 22, 49 }, { 23, 42 }, + { 23, 46 }, { 23, 50 }, { 24, 43 }, { 24, 47 }, { 24, 51 }, + { 25, 44 }, { 25, 48 }, { 25, 52 }, { 26, 45 }, { 26, 46 }, + { 26, 53 }, { 27, 47 }, { 27, 48 }, { 27, 56 }, { 28, 49 }, + { 28, 54 }, { 28, 57 }, { 29, 50 }, { 29, 55 }, { 29, 58 }, + { 30, 51 }, { 30, 54 }, { 30, 59 }, { 31, 52 }, { 31, 55 }, + { 31, 60 }, { 32, 53 }, { 32, 61 }, { 32, 62 }, { 33, 56 }, + { 33, 63 }, { 33, 64 }, { 34, 57 }, { 34, 61 }, { 34, 65 }, + { 35, 58 }, { 35, 62 }, { 35, 66 }, { 36, 59 }, { 36, 63 }, + { 36, 67 }, { 37, 60 }, { 37, 64 }, { 37, 68 }, { 38, 65 }, + { 38, 67 }, { 38, 69 }, { 39, 66 }, { 39, 68 }, { 39, 69 }, + { 40, 70 }, { 40, 71 }, { 41, 72 }, { 41, 78 }, { 42, 73 }, + { 42, 79 }, { 43, 74 }, { 43, 80 }, { 44, 75 }, { 44, 81 }, + { 45, 76 }, { 45, 88 }, { 46, 77 }, { 46, 89 }, { 47, 82 }, + { 47, 92 }, { 48, 83 }, { 48, 93 }, { 49, 84 }, { 49, 94 }, + { 50, 85 }, { 50, 95 }, { 51, 86 }, { 51, 96 }, { 52, 87 }, + { 52, 97 }, { 53, 98 }, { 53, 99 }, { 54, 90 }, { 54, 108 }, + { 55, 91 }, { 55, 109 }, { 56, 100 }, { 56, 101 }, { 57, 102 }, + { 57, 112 }, { 58, 103 }, { 58, 113 }, { 59, 104 }, { 59, 114 }, + { 60, 105 }, { 60, 115 }, { 61, 106 }, { 61, 116 }, { 62, 107 }, + { 62, 117 }, { 63, 110 }, { 63, 122 }, { 64, 111 }, { 64, 123 }, + { 65, 118 }, { 65, 124 }, { 66, 119 }, { 66, 125 }, { 67, 120 }, + { 67, 126 }, { 68, 121 }, { 68, 127 }, { 69, 128 }, { 69, 129 }, + { 70, 72 }, { 70, 73 }, { 70, 130 }, { 71, 74 }, { 71, 75 }, + { 71, 131 }, { 72, 76 }, { 72, 132 }, { 73, 77 }, { 73, 133 }, + { 74, 82 }, { 74, 134 }, { 75, 83 }, { 75, 135 }, { 76, 77 }, + { 76, 140 }, { 77, 141 }, { 78, 80 }, { 78, 84 }, { 78, 136 }, + { 79, 81 }, { 79, 85 }, { 79, 137 }, { 80, 86 }, { 80, 138 }, + { 81, 87 }, { 81, 139 }, { 82, 83 }, { 82, 142 }, { 83, 143 }, + { 84, 90 }, { 84, 146 }, { 85, 91 }, { 85, 147 }, { 86, 90 }, + { 86, 148 }, { 87, 91 }, { 87, 149 }, { 88, 94 }, { 88, 98 }, + { 88, 144 }, { 89, 95 }, { 89, 99 }, { 89, 145 }, { 90, 156 }, + { 91, 157 }, { 92, 96 }, { 92, 100 }, { 92, 150 }, { 93, 97 }, + { 93, 101 }, { 93, 151 }, { 94, 102 }, { 94, 152 }, { 95, 103 }, + { 95, 153 }, { 96, 104 }, { 96, 154 }, { 97, 105 }, { 97, 155 }, + { 98, 106 }, { 98, 158 }, { 99, 107 }, { 99, 159 }, { 100, 110 }, + { 100, 160 }, { 101, 111 }, { 101, 161 }, { 102, 106 }, { 102, 164 }, + { 103, 107 }, { 103, 165 }, { 104, 110 }, { 104, 166 }, { 105, 111 }, + { 105, 167 }, { 106, 168 }, { 107, 169 }, { 108, 112 }, { 108, 114 }, + { 108, 162 }, { 109, 113 }, { 109, 115 }, { 109, 163 }, { 110, 174 }, + { 111, 175 }, { 112, 118 }, { 112, 170 }, { 113, 119 }, { 113, 171 }, + { 114, 120 }, { 114, 172 }, { 115, 121 }, { 115, 173 }, { 116, 117 }, + { 116, 124 }, { 116, 176 }, { 117, 125 }, { 117, 177 }, { 118, 120 }, + { 118, 180 }, { 119, 121 }, { 119, 181 }, { 120, 182 }, { 121, 183 }, + { 122, 123 }, { 122, 126 }, { 122, 178 }, { 123, 127 }, { 123, 179 }, + { 124, 128 }, { 124, 184 }, { 125, 128 }, { 125, 185 }, { 126, 129 }, + { 126, 186 }, { 127, 129 }, { 127, 187 }, { 128, 188 }, { 129, 189 }, + { 130, 131 }, { 130, 190 }, { 130, 191 }, { 131, 192 }, { 131, 193 }, + { 132, 136 }, { 132, 190 }, { 132, 196 }, { 133, 137 }, { 133, 191 }, + { 133, 197 }, { 134, 138 }, { 134, 192 }, { 134, 198 }, { 135, 139 }, + { 135, 193 }, { 135, 199 }, { 136, 194 }, { 136, 201 }, { 137, 195 }, + { 137, 202 }, { 138, 194 }, { 138, 203 }, { 139, 195 }, { 139, 204 }, + { 140, 144 }, { 140, 196 }, { 140, 200 }, { 141, 145 }, { 141, 197 }, + { 141, 200 }, { 142, 150 }, { 142, 198 }, { 142, 205 }, { 143, 151 }, + { 143, 199 }, { 143, 205 }, { 144, 206 }, { 144, 210 }, { 145, 207 }, + { 145, 211 }, { 146, 152 }, { 146, 201 }, { 146, 212 }, { 147, 153 }, + { 147, 202 }, { 147, 213 }, { 148, 154 }, { 148, 203 }, { 148, 214 }, + { 149, 155 }, { 149, 204 }, { 149, 215 }, { 150, 208 }, { 150, 216 }, + { 151, 209 }, { 151, 217 }, { 152, 206 }, { 152, 218 }, { 153, 207 }, + { 153, 219 }, { 154, 208 }, { 154, 220 }, { 155, 209 }, { 155, 221 }, + { 156, 162 }, { 156, 212 }, { 156, 214 }, { 157, 163 }, { 157, 213 }, + { 157, 215 }, { 158, 159 }, { 158, 210 }, { 158, 222 }, { 159, 211 }, + { 159, 223 }, { 160, 161 }, { 160, 216 }, { 160, 228 }, { 161, 217 }, + { 161, 229 }, { 162, 224 }, { 162, 226 }, { 163, 225 }, { 163, 227 }, + { 164, 170 }, { 164, 218 }, { 164, 230 }, { 165, 171 }, { 165, 219 }, + { 165, 231 }, { 166, 172 }, { 166, 220 }, { 166, 232 }, { 167, 173 }, + { 167, 221 }, { 167, 233 }, { 168, 176 }, { 168, 222 }, { 168, 230 }, + { 169, 177 }, { 169, 223 }, { 169, 231 }, { 170, 224 }, { 170, 235 }, + { 171, 225 }, { 171, 236 }, { 172, 226 }, { 172, 237 }, { 173, 227 }, + { 173, 238 }, { 174, 178 }, { 174, 228 }, { 174, 232 }, { 175, 179 }, + { 175, 229 }, { 175, 233 }, { 176, 234 }, { 176, 240 }, { 177, 234 }, + { 177, 241 }, { 178, 239 }, { 178, 242 }, { 179, 239 }, { 179, 243 }, + { 180, 184 }, { 180, 235 }, { 180, 244 }, { 181, 185 }, { 181, 236 }, + { 181, 245 }, { 182, 186 }, { 182, 237 }, { 182, 244 }, { 183, 187 }, + { 183, 238 }, { 183, 245 }, { 184, 240 }, { 184, 246 }, { 185, 241 }, + { 185, 247 }, { 186, 242 }, { 186, 248 }, { 187, 243 }, { 187, 249 }, + { 188, 189 }, { 188, 246 }, { 188, 247 }, { 189, 248 }, { 189, 249 }, + { 190, 250 }, { 190, 270 }, { 191, 251 }, { 191, 271 }, { 192, 250 }, + { 192, 272 }, { 193, 251 }, { 193, 273 }, { 194, 250 }, { 194, 279 }, + { 195, 251 }, { 195, 280 }, { 196, 252 }, { 196, 274 }, { 197, 253 }, + { 197, 275 }, { 198, 254 }, { 198, 276 }, { 199, 255 }, { 199, 277 }, + { 200, 256 }, { 200, 278 }, { 201, 252 }, { 201, 282 }, { 202, 253 }, + { 202, 283 }, { 203, 254 }, { 203, 284 }, { 204, 255 }, { 204, 285 }, + { 205, 257 }, { 205, 281 }, { 206, 252 }, { 206, 290 }, { 207, 253 }, + { 207, 291 }, { 208, 254 }, { 208, 292 }, { 209, 255 }, { 209, 293 }, + { 210, 256 }, { 210, 294 }, { 211, 256 }, { 211, 295 }, { 212, 258 }, + { 212, 286 }, { 213, 259 }, { 213, 287 }, { 214, 260 }, { 214, 288 }, + { 215, 261 }, { 215, 289 }, { 216, 257 }, { 216, 296 }, { 217, 257 }, + { 217, 297 }, { 218, 258 }, { 218, 298 }, { 219, 259 }, { 219, 299 }, + { 220, 260 }, { 220, 300 }, { 221, 261 }, { 221, 301 }, { 222, 262 }, + { 222, 302 }, { 223, 262 }, { 223, 303 }, { 224, 258 }, { 224, 310 }, + { 225, 259 }, { 225, 311 }, { 226, 260 }, { 226, 312 }, { 227, 261 }, + { 227, 313 }, { 228, 263 }, { 228, 304 }, { 229, 263 }, { 229, 305 }, + { 230, 264 }, { 230, 306 }, { 231, 265 }, { 231, 307 }, { 232, 266 }, + { 232, 308 }, { 233, 267 }, { 233, 309 }, { 234, 262 }, { 234, 318 }, + { 235, 264 }, { 235, 314 }, { 236, 265 }, { 236, 315 }, { 237, 266 }, + { 237, 316 }, { 238, 267 }, { 238, 317 }, { 239, 263 }, { 239, 321 }, + { 240, 264 }, { 240, 322 }, { 241, 265 }, { 241, 323 }, { 242, 266 }, + { 242, 324 }, { 243, 267 }, { 243, 325 }, { 244, 268 }, { 244, 319 }, + { 245, 269 }, { 245, 320 }, { 246, 268 }, { 246, 326 }, { 247, 269 }, + { 247, 327 }, { 248, 268 }, { 248, 328 }, { 249, 269 }, { 249, 329 }, + { 250, 330 }, { 251, 331 }, { 252, 332 }, { 253, 333 }, { 254, 334 }, + { 255, 335 }, { 256, 336 }, { 257, 337 }, { 258, 338 }, { 259, 339 }, + { 260, 340 }, { 261, 341 }, { 262, 342 }, { 263, 343 }, { 264, 344 }, + { 265, 345 }, { 266, 346 }, { 267, 347 }, { 268, 348 }, { 269, 349 }, + { 270, 271 }, { 270, 274 }, { 270, 350 }, { 271, 275 }, { 271, 351 }, + { 272, 273 }, { 272, 276 }, { 272, 352 }, { 273, 277 }, { 273, 353 }, + { 274, 278 }, { 274, 356 }, { 275, 278 }, { 275, 357 }, { 276, 281 }, + { 276, 358 }, { 277, 281 }, { 277, 359 }, { 278, 360 }, { 279, 282 }, + { 279, 284 }, { 279, 354 }, { 280, 283 }, { 280, 285 }, { 280, 355 }, + { 281, 365 }, { 282, 286 }, { 282, 361 }, { 283, 287 }, { 283, 362 }, + { 284, 288 }, { 284, 363 }, { 285, 289 }, { 285, 364 }, { 286, 288 }, + { 286, 372 }, { 287, 289 }, { 287, 373 }, { 288, 374 }, { 289, 375 }, + { 290, 294 }, { 290, 298 }, { 290, 366 }, { 291, 295 }, { 291, 299 }, + { 291, 367 }, { 292, 296 }, { 292, 300 }, { 292, 368 }, { 293, 297 }, + { 293, 301 }, { 293, 369 }, { 294, 302 }, { 294, 370 }, { 295, 303 }, + { 295, 371 }, { 296, 304 }, { 296, 376 }, { 297, 305 }, { 297, 377 }, + { 298, 306 }, { 298, 378 }, { 299, 307 }, { 299, 379 }, { 300, 308 }, + { 300, 380 }, { 301, 309 }, { 301, 381 }, { 302, 306 }, { 302, 382 }, + { 303, 307 }, { 303, 383 }, { 304, 308 }, { 304, 388 }, { 305, 309 }, + { 305, 389 }, { 306, 390 }, { 307, 391 }, { 308, 392 }, { 309, 393 }, + { 310, 312 }, { 310, 314 }, { 310, 384 }, { 311, 313 }, { 311, 315 }, + { 311, 385 }, { 312, 316 }, { 312, 386 }, { 313, 317 }, { 313, 387 }, + { 314, 319 }, { 314, 395 }, { 315, 320 }, { 315, 396 }, { 316, 319 }, + { 316, 397 }, { 317, 320 }, { 317, 398 }, { 318, 322 }, { 318, 323 }, + { 318, 394 }, { 319, 404 }, { 320, 405 }, { 321, 324 }, { 321, 325 }, + { 321, 399 }, { 322, 326 }, { 322, 400 }, { 323, 327 }, { 323, 401 }, + { 324, 328 }, { 324, 402 }, { 325, 329 }, { 325, 403 }, { 326, 327 }, + { 326, 406 }, { 327, 407 }, { 328, 329 }, { 328, 408 }, { 329, 409 }, + { 330, 350 }, { 330, 352 }, { 330, 354 }, { 331, 351 }, { 331, 353 }, + { 331, 355 }, { 332, 356 }, { 332, 361 }, { 332, 366 }, { 333, 357 }, + { 333, 362 }, { 333, 367 }, { 334, 358 }, { 334, 363 }, { 334, 368 }, + { 335, 359 }, { 335, 364 }, { 335, 369 }, { 336, 360 }, { 336, 370 }, + { 336, 371 }, { 337, 365 }, { 337, 376 }, { 337, 377 }, { 338, 372 }, + { 338, 378 }, { 338, 384 }, { 339, 373 }, { 339, 379 }, { 339, 385 }, + { 340, 374 }, { 340, 380 }, { 340, 386 }, { 341, 375 }, { 341, 381 }, + { 341, 387 }, { 342, 382 }, { 342, 383 }, { 342, 394 }, { 343, 388 }, + { 343, 389 }, { 343, 399 }, { 344, 390 }, { 344, 395 }, { 344, 400 }, + { 345, 391 }, { 345, 396 }, { 345, 401 }, { 346, 392 }, { 346, 397 }, + { 346, 402 }, { 347, 393 }, { 347, 398 }, { 347, 403 }, { 348, 404 }, + { 348, 406 }, { 348, 408 }, { 349, 405 }, { 349, 407 }, { 349, 409 }, + { 350, 410 }, { 350, 412 }, { 351, 410 }, { 351, 413 }, { 352, 411 }, + { 352, 414 }, { 353, 411 }, { 353, 415 }, { 354, 416 }, { 354, 418 }, + { 355, 417 }, { 355, 419 }, { 356, 412 }, { 356, 420 }, { 357, 413 }, + { 357, 421 }, { 358, 414 }, { 358, 422 }, { 359, 415 }, { 359, 423 }, + { 360, 420 }, { 360, 421 }, { 361, 416 }, { 361, 426 }, { 362, 417 }, + { 362, 427 }, { 363, 418 }, { 363, 428 }, { 364, 419 }, { 364, 429 }, + { 365, 422 }, { 365, 423 }, { 366, 424 }, { 366, 432 }, { 367, 425 }, + { 367, 433 }, { 368, 430 }, { 368, 434 }, { 369, 431 }, { 369, 435 }, + { 370, 424 }, { 370, 438 }, { 371, 425 }, { 371, 439 }, { 372, 426 }, + { 372, 436 }, { 373, 427 }, { 373, 437 }, { 374, 428 }, { 374, 436 }, + { 375, 429 }, { 375, 437 }, { 376, 430 }, { 376, 440 }, { 377, 431 }, + { 377, 441 }, { 378, 432 }, { 378, 444 }, { 379, 433 }, { 379, 445 }, + { 380, 434 }, { 380, 446 }, { 381, 435 }, { 381, 447 }, { 382, 438 }, + { 382, 448 }, { 383, 439 }, { 383, 449 }, { 384, 442 }, { 384, 450 }, + { 385, 443 }, { 385, 451 }, { 386, 442 }, { 386, 452 }, { 387, 443 }, + { 387, 453 }, { 388, 440 }, { 388, 454 }, { 389, 441 }, { 389, 455 }, + { 390, 444 }, { 390, 448 }, { 391, 445 }, { 391, 449 }, { 392, 446 }, + { 392, 454 }, { 393, 447 }, { 393, 455 }, { 394, 456 }, { 394, 457 }, + { 395, 450 }, { 395, 460 }, { 396, 451 }, { 396, 461 }, { 397, 452 }, + { 397, 462 }, { 398, 453 }, { 398, 463 }, { 399, 458 }, { 399, 459 }, + { 400, 456 }, { 400, 464 }, { 401, 457 }, { 401, 465 }, { 402, 458 }, + { 402, 466 }, { 403, 459 }, { 403, 467 }, { 404, 460 }, { 404, 462 }, + { 405, 461 }, { 405, 463 }, { 406, 464 }, { 406, 468 }, { 407, 465 }, + { 407, 468 }, { 408, 466 }, { 408, 469 }, { 409, 467 }, { 409, 469 }, + { 410, 411 }, { 410, 470 }, { 411, 471 }, { 412, 416 }, { 412, 472 }, + { 413, 417 }, { 413, 473 }, { 414, 418 }, { 414, 474 }, { 415, 419 }, + { 415, 475 }, { 416, 478 }, { 417, 479 }, { 418, 480 }, { 419, 481 }, + { 420, 424 }, { 420, 476 }, { 421, 425 }, { 421, 477 }, { 422, 430 }, + { 422, 482 }, { 423, 431 }, { 423, 483 }, { 424, 488 }, { 425, 489 }, + { 426, 432 }, { 426, 484 }, { 427, 433 }, { 427, 485 }, { 428, 434 }, + { 428, 486 }, { 429, 435 }, { 429, 487 }, { 430, 492 }, { 431, 493 }, + { 432, 494 }, { 433, 495 }, { 434, 496 }, { 435, 497 }, { 436, 442 }, + { 436, 490 }, { 437, 443 }, { 437, 491 }, { 438, 439 }, { 438, 498 }, + { 439, 499 }, { 440, 441 }, { 440, 500 }, { 441, 501 }, { 442, 508 }, + { 443, 509 }, { 444, 450 }, { 444, 502 }, { 445, 451 }, { 445, 503 }, + { 446, 452 }, { 446, 504 }, { 447, 453 }, { 447, 505 }, { 448, 456 }, + { 448, 506 }, { 449, 457 }, { 449, 507 }, { 450, 512 }, { 451, 513 }, + { 452, 514 }, { 453, 515 }, { 454, 458 }, { 454, 510 }, { 455, 459 }, + { 455, 511 }, { 456, 516 }, { 457, 517 }, { 458, 522 }, { 459, 523 }, + { 460, 464 }, { 460, 518 }, { 461, 465 }, { 461, 519 }, { 462, 466 }, + { 462, 520 }, { 463, 467 }, { 463, 521 }, { 464, 524 }, { 465, 525 }, + { 466, 526 }, { 467, 527 }, { 468, 469 }, { 468, 528 }, { 469, 529 }, + { 470, 472 }, { 470, 473 }, { 470, 530 }, { 471, 474 }, { 471, 475 }, + { 471, 530 }, { 472, 476 }, { 472, 531 }, { 473, 477 }, { 473, 532 }, + { 474, 482 }, { 474, 533 }, { 475, 483 }, { 475, 534 }, { 476, 477 }, + { 476, 535 }, { 477, 536 }, { 478, 480 }, { 478, 484 }, { 478, 531 }, + { 479, 481 }, { 479, 485 }, { 479, 532 }, { 480, 486 }, { 480, 533 }, + { 481, 487 }, { 481, 534 }, { 482, 483 }, { 482, 537 }, { 483, 538 }, + { 484, 490 }, { 484, 539 }, { 485, 491 }, { 485, 540 }, { 486, 490 }, + { 486, 541 }, { 487, 491 }, { 487, 542 }, { 488, 494 }, { 488, 498 }, + { 488, 535 }, { 489, 495 }, { 489, 499 }, { 489, 536 }, { 490, 544 }, + { 491, 545 }, { 492, 496 }, { 492, 500 }, { 492, 537 }, { 493, 497 }, + { 493, 501 }, { 493, 538 }, { 494, 502 }, { 494, 539 }, { 495, 503 }, + { 495, 540 }, { 496, 504 }, { 496, 541 }, { 497, 505 }, { 497, 542 }, + { 498, 506 }, { 498, 543 }, { 499, 507 }, { 499, 543 }, { 500, 510 }, + { 500, 546 }, { 501, 511 }, { 501, 546 }, { 502, 506 }, { 502, 547 }, + { 503, 507 }, { 503, 548 }, { 504, 510 }, { 504, 549 }, { 505, 511 }, + { 505, 550 }, { 506, 551 }, { 507, 552 }, { 508, 512 }, { 508, 514 }, + { 508, 544 }, { 509, 513 }, { 509, 515 }, { 509, 545 }, { 510, 553 }, + { 511, 554 }, { 512, 518 }, { 512, 547 }, { 513, 519 }, { 513, 548 }, + { 514, 520 }, { 514, 549 }, { 515, 521 }, { 515, 550 }, { 516, 517 }, + { 516, 524 }, { 516, 551 }, { 517, 525 }, { 517, 552 }, { 518, 520 }, + { 518, 555 }, { 519, 521 }, { 519, 556 }, { 520, 557 }, { 521, 558 }, + { 522, 523 }, { 522, 526 }, { 522, 553 }, { 523, 527 }, { 523, 554 }, + { 524, 528 }, { 524, 555 }, { 525, 528 }, { 525, 556 }, { 526, 529 }, + { 526, 557 }, { 527, 529 }, { 527, 558 }, { 528, 559 }, { 529, 559 }, + { 530, 560 }, { 530, 561 }, { 531, 560 }, { 531, 562 }, { 532, 561 }, + { 532, 563 }, { 533, 560 }, { 533, 564 }, { 534, 561 }, { 534, 565 }, + { 535, 562 }, { 535, 566 }, { 536, 563 }, { 536, 566 }, { 537, 564 }, + { 537, 567 }, { 538, 565 }, { 538, 567 }, { 539, 562 }, { 539, 568 }, + { 540, 563 }, { 540, 569 }, { 541, 564 }, { 541, 570 }, { 542, 565 }, + { 542, 571 }, { 543, 566 }, { 543, 572 }, { 544, 568 }, { 544, 570 }, + { 545, 569 }, { 545, 571 }, { 546, 567 }, { 546, 573 }, { 547, 568 }, + { 547, 574 }, { 548, 569 }, { 548, 575 }, { 549, 570 }, { 549, 576 }, + { 550, 571 }, { 550, 577 }, { 551, 572 }, { 551, 574 }, { 552, 572 }, + { 552, 575 }, { 553, 573 }, { 553, 576 }, { 554, 573 }, { 554, 577 }, + { 555, 574 }, { 555, 578 }, { 556, 575 }, { 556, 579 }, { 557, 576 }, + { 557, 578 }, { 558, 577 }, { 558, 579 }, { 559, 578 }, { 559, 579 }, + { 560, 580 }, { 561, 581 }, { 562, 582 }, { 563, 583 }, { 564, 584 }, + { 565, 585 }, { 566, 586 }, { 567, 587 }, { 568, 588 }, { 569, 589 }, + { 570, 590 }, { 571, 591 }, { 572, 592 }, { 573, 593 }, { 574, 594 }, + { 575, 595 }, { 576, 596 }, { 577, 597 }, { 578, 598 }, { 579, 599 }, + { 580, 581 }, { 580, 582 }, { 580, 584 }, { 581, 583 }, { 581, 585 }, + { 582, 586 }, { 582, 588 }, { 583, 586 }, { 583, 589 }, { 584, 587 }, + { 584, 590 }, { 585, 587 }, { 585, 591 }, { 586, 592 }, { 587, 593 }, + { 588, 590 }, { 588, 594 }, { 589, 591 }, { 589, 595 }, { 590, 596 }, + { 591, 597 }, { 592, 594 }, { 592, 595 }, { 593, 596 }, { 593, 597 }, + { 594, 598 }, { 595, 599 }, { 596, 598 }, { 597, 599 }, { 598, 599 } +}; + +static const int face_120[NUM_FACE_120][VERT_PER_FACE_120] = { + { 0, 1, 3, 6, 2 }, { 0, 1, 5, 7, 4 }, + { 0, 1, 21, 40, 20 }, { 0, 2, 8, 10, 4 }, + { 0, 2, 22, 41, 20 }, { 0, 4, 24, 43, 20 }, + { 1, 3, 9, 11, 5 }, { 1, 3, 23, 42, 21 }, + { 1, 5, 25, 44, 21 }, { 2, 6, 12, 14, 8 }, + { 2, 6, 26, 45, 22 }, { 2, 8, 28, 49, 22 }, + { 3, 6, 12, 15, 9 }, { 3, 6, 26, 46, 23 }, + { 3, 9, 29, 50, 23 }, { 4, 7, 13, 16, 10 }, + { 4, 7, 27, 47, 24 }, { 4, 10, 30, 51, 24 }, + { 5, 7, 13, 17, 11 }, { 5, 7, 27, 48, 25 }, + { 5, 11, 31, 52, 25 }, { 6, 12, 32, 53, 26 }, + { 7, 13, 33, 56, 27 }, { 8, 10, 16, 18, 14 }, + { 8, 10, 30, 54, 28 }, { 8, 14, 34, 57, 28 }, + { 9, 11, 17, 19, 15 }, { 9, 11, 31, 55, 29 }, + { 9, 15, 35, 58, 29 }, { 10, 16, 36, 59, 30 }, + { 11, 17, 37, 60, 31 }, { 12, 14, 18, 19, 15 }, + { 12, 14, 34, 61, 32 }, { 12, 15, 35, 62, 32 }, + { 13, 16, 18, 19, 17 }, { 13, 16, 36, 63, 33 }, + { 13, 17, 37, 64, 33 }, { 14, 18, 38, 65, 34 }, + { 15, 19, 39, 66, 35 }, { 16, 18, 38, 67, 36 }, + { 17, 19, 39, 68, 37 }, { 18, 19, 39, 69, 38 }, + { 20, 40, 70, 72, 41 }, { 20, 40, 71, 74, 43 }, + { 20, 41, 78, 80, 43 }, { 21, 40, 70, 73, 42 }, + { 21, 40, 71, 75, 44 }, { 21, 42, 79, 81, 44 }, + { 22, 41, 72, 76, 45 }, { 22, 41, 78, 84, 49 }, + { 22, 45, 88, 94, 49 }, { 23, 42, 73, 77, 46 }, + { 23, 42, 79, 85, 50 }, { 23, 46, 89, 95, 50 }, + { 24, 43, 74, 82, 47 }, { 24, 43, 80, 86, 51 }, + { 24, 47, 92, 96, 51 }, { 25, 44, 75, 83, 48 }, + { 25, 44, 81, 87, 52 }, { 25, 48, 93, 97, 52 }, + { 26, 45, 76, 77, 46 }, { 26, 45, 88, 98, 53 }, + { 26, 46, 89, 99, 53 }, { 27, 47, 82, 83, 48 }, + { 27, 47, 92, 100, 56 }, { 27, 48, 93, 101, 56 }, + { 28, 49, 84, 90, 54 }, { 28, 49, 94, 102, 57 }, + { 28, 54, 108, 112, 57 }, { 29, 50, 85, 91, 55 }, + { 29, 50, 95, 103, 58 }, { 29, 55, 109, 113, 58 }, + { 30, 51, 86, 90, 54 }, { 30, 51, 96, 104, 59 }, + { 30, 54, 108, 114, 59 }, { 31, 52, 87, 91, 55 }, + { 31, 52, 97, 105, 60 }, { 31, 55, 109, 115, 60 }, + { 32, 53, 98, 106, 61 }, { 32, 53, 99, 107, 62 }, + { 32, 61, 116, 117, 62 }, { 33, 56, 100, 110, 63 }, + { 33, 56, 101, 111, 64 }, { 33, 63, 122, 123, 64 }, + { 34, 57, 102, 106, 61 }, { 34, 57, 112, 118, 65 }, + { 34, 61, 116, 124, 65 }, { 35, 58, 103, 107, 62 }, + { 35, 58, 113, 119, 66 }, { 35, 62, 117, 125, 66 }, + { 36, 59, 104, 110, 63 }, { 36, 59, 114, 120, 67 }, + { 36, 63, 122, 126, 67 }, { 37, 60, 105, 111, 64 }, + { 37, 60, 115, 121, 68 }, { 37, 64, 123, 127, 68 }, + { 38, 65, 118, 120, 67 }, { 38, 65, 124, 128, 69 }, + { 38, 67, 126, 129, 69 }, { 39, 66, 119, 121, 68 }, + { 39, 66, 125, 128, 69 }, { 39, 68, 127, 129, 69 }, + { 40, 70, 130, 131, 71 }, { 41, 72, 132, 136, 78 }, + { 42, 73, 133, 137, 79 }, { 43, 74, 134, 138, 80 }, + { 44, 75, 135, 139, 81 }, { 45, 76, 140, 144, 88 }, + { 46, 77, 141, 145, 89 }, { 47, 82, 142, 150, 92 }, + { 48, 83, 143, 151, 93 }, { 49, 84, 146, 152, 94 }, + { 50, 85, 147, 153, 95 }, { 51, 86, 148, 154, 96 }, + { 52, 87, 149, 155, 97 }, { 53, 98, 158, 159, 99 }, + { 54, 90, 156, 162, 108 }, { 55, 91, 157, 163, 109 }, + { 56, 100, 160, 161, 101 }, { 57, 102, 164, 170, 112 }, + { 58, 103, 165, 171, 113 }, { 59, 104, 166, 172, 114 }, + { 60, 105, 167, 173, 115 }, { 61, 106, 168, 176, 116 }, + { 62, 107, 169, 177, 117 }, { 63, 110, 174, 178, 122 }, + { 64, 111, 175, 179, 123 }, { 65, 118, 180, 184, 124 }, + { 66, 119, 181, 185, 125 }, { 67, 120, 182, 186, 126 }, + { 68, 121, 183, 187, 127 }, { 69, 128, 188, 189, 129 }, + { 70, 72, 76, 77, 73 }, { 70, 72, 132, 190, 130 }, + { 70, 73, 133, 191, 130 }, { 71, 74, 82, 83, 75 }, + { 71, 74, 134, 192, 131 }, { 71, 75, 135, 193, 131 }, + { 72, 76, 140, 196, 132 }, { 73, 77, 141, 197, 133 }, + { 74, 82, 142, 198, 134 }, { 75, 83, 143, 199, 135 }, + { 76, 77, 141, 200, 140 }, { 78, 80, 86, 90, 84 }, + { 78, 80, 138, 194, 136 }, { 78, 84, 146, 201, 136 }, + { 79, 81, 87, 91, 85 }, { 79, 81, 139, 195, 137 }, + { 79, 85, 147, 202, 137 }, { 80, 86, 148, 203, 138 }, + { 81, 87, 149, 204, 139 }, { 82, 83, 143, 205, 142 }, + { 84, 90, 156, 212, 146 }, { 85, 91, 157, 213, 147 }, + { 86, 90, 156, 214, 148 }, { 87, 91, 157, 215, 149 }, + { 88, 94, 102, 106, 98 }, { 88, 94, 152, 206, 144 }, + { 88, 98, 158, 210, 144 }, { 89, 95, 103, 107, 99 }, + { 89, 95, 153, 207, 145 }, { 89, 99, 159, 211, 145 }, + { 92, 96, 104, 110, 100 }, { 92, 96, 154, 208, 150 }, + { 92, 100, 160, 216, 150 }, { 93, 97, 105, 111, 101 }, + { 93, 97, 155, 209, 151 }, { 93, 101, 161, 217, 151 }, + { 94, 102, 164, 218, 152 }, { 95, 103, 165, 219, 153 }, + { 96, 104, 166, 220, 154 }, { 97, 105, 167, 221, 155 }, + { 98, 106, 168, 222, 158 }, { 99, 107, 169, 223, 159 }, + { 100, 110, 174, 228, 160 }, { 101, 111, 175, 229, 161 }, + { 102, 106, 168, 230, 164 }, { 103, 107, 169, 231, 165 }, + { 104, 110, 174, 232, 166 }, { 105, 111, 175, 233, 167 }, + { 108, 112, 118, 120, 114 }, { 108, 112, 170, 224, 162 }, + { 108, 114, 172, 226, 162 }, { 109, 113, 119, 121, 115 }, + { 109, 113, 171, 225, 163 }, { 109, 115, 173, 227, 163 }, + { 112, 118, 180, 235, 170 }, { 113, 119, 181, 236, 171 }, + { 114, 120, 182, 237, 172 }, { 115, 121, 183, 238, 173 }, + { 116, 117, 125, 128, 124 }, { 116, 117, 177, 234, 176 }, + { 116, 124, 184, 240, 176 }, { 117, 125, 185, 241, 177 }, + { 118, 120, 182, 244, 180 }, { 119, 121, 183, 245, 181 }, + { 122, 123, 127, 129, 126 }, { 122, 123, 179, 239, 178 }, + { 122, 126, 186, 242, 178 }, { 123, 127, 187, 243, 179 }, + { 124, 128, 188, 246, 184 }, { 125, 128, 188, 247, 185 }, + { 126, 129, 189, 248, 186 }, { 127, 129, 189, 249, 187 }, + { 130, 131, 192, 250, 190 }, { 130, 131, 193, 251, 191 }, + { 130, 190, 270, 271, 191 }, { 131, 192, 272, 273, 193 }, + { 132, 136, 194, 250, 190 }, { 132, 136, 201, 252, 196 }, + { 132, 190, 270, 274, 196 }, { 133, 137, 195, 251, 191 }, + { 133, 137, 202, 253, 197 }, { 133, 191, 271, 275, 197 }, + { 134, 138, 194, 250, 192 }, { 134, 138, 203, 254, 198 }, + { 134, 192, 272, 276, 198 }, { 135, 139, 195, 251, 193 }, + { 135, 139, 204, 255, 199 }, { 135, 193, 273, 277, 199 }, + { 136, 194, 279, 282, 201 }, { 137, 195, 280, 283, 202 }, + { 138, 194, 279, 284, 203 }, { 139, 195, 280, 285, 204 }, + { 140, 144, 206, 252, 196 }, { 140, 144, 210, 256, 200 }, + { 140, 196, 274, 278, 200 }, { 141, 145, 207, 253, 197 }, + { 141, 145, 211, 256, 200 }, { 141, 197, 275, 278, 200 }, + { 142, 150, 208, 254, 198 }, { 142, 150, 216, 257, 205 }, + { 142, 198, 276, 281, 205 }, { 143, 151, 209, 255, 199 }, + { 143, 151, 217, 257, 205 }, { 143, 199, 277, 281, 205 }, + { 144, 206, 290, 294, 210 }, { 145, 207, 291, 295, 211 }, + { 146, 152, 206, 252, 201 }, { 146, 152, 218, 258, 212 }, + { 146, 201, 282, 286, 212 }, { 147, 153, 207, 253, 202 }, + { 147, 153, 219, 259, 213 }, { 147, 202, 283, 287, 213 }, + { 148, 154, 208, 254, 203 }, { 148, 154, 220, 260, 214 }, + { 148, 203, 284, 288, 214 }, { 149, 155, 209, 255, 204 }, + { 149, 155, 221, 261, 215 }, { 149, 204, 285, 289, 215 }, + { 150, 208, 292, 296, 216 }, { 151, 209, 293, 297, 217 }, + { 152, 206, 290, 298, 218 }, { 153, 207, 291, 299, 219 }, + { 154, 208, 292, 300, 220 }, { 155, 209, 293, 301, 221 }, + { 156, 162, 224, 258, 212 }, { 156, 162, 226, 260, 214 }, + { 156, 212, 286, 288, 214 }, { 157, 163, 225, 259, 213 }, + { 157, 163, 227, 261, 215 }, { 157, 213, 287, 289, 215 }, + { 158, 159, 211, 256, 210 }, { 158, 159, 223, 262, 222 }, + { 158, 210, 294, 302, 222 }, { 159, 211, 295, 303, 223 }, + { 160, 161, 217, 257, 216 }, { 160, 161, 229, 263, 228 }, + { 160, 216, 296, 304, 228 }, { 161, 217, 297, 305, 229 }, + { 162, 224, 310, 312, 226 }, { 163, 225, 311, 313, 227 }, + { 164, 170, 224, 258, 218 }, { 164, 170, 235, 264, 230 }, + { 164, 218, 298, 306, 230 }, { 165, 171, 225, 259, 219 }, + { 165, 171, 236, 265, 231 }, { 165, 219, 299, 307, 231 }, + { 166, 172, 226, 260, 220 }, { 166, 172, 237, 266, 232 }, + { 166, 220, 300, 308, 232 }, { 167, 173, 227, 261, 221 }, + { 167, 173, 238, 267, 233 }, { 167, 221, 301, 309, 233 }, + { 168, 176, 234, 262, 222 }, { 168, 176, 240, 264, 230 }, + { 168, 222, 302, 306, 230 }, { 169, 177, 234, 262, 223 }, + { 169, 177, 241, 265, 231 }, { 169, 223, 303, 307, 231 }, + { 170, 224, 310, 314, 235 }, { 171, 225, 311, 315, 236 }, + { 172, 226, 312, 316, 237 }, { 173, 227, 313, 317, 238 }, + { 174, 178, 239, 263, 228 }, { 174, 178, 242, 266, 232 }, + { 174, 228, 304, 308, 232 }, { 175, 179, 239, 263, 229 }, + { 175, 179, 243, 267, 233 }, { 175, 229, 305, 309, 233 }, + { 176, 234, 318, 322, 240 }, { 177, 234, 318, 323, 241 }, + { 178, 239, 321, 324, 242 }, { 179, 239, 321, 325, 243 }, + { 180, 184, 240, 264, 235 }, { 180, 184, 246, 268, 244 }, + { 180, 235, 314, 319, 244 }, { 181, 185, 241, 265, 236 }, + { 181, 185, 247, 269, 245 }, { 181, 236, 315, 320, 245 }, + { 182, 186, 242, 266, 237 }, { 182, 186, 248, 268, 244 }, + { 182, 237, 316, 319, 244 }, { 183, 187, 243, 267, 238 }, + { 183, 187, 249, 269, 245 }, { 183, 238, 317, 320, 245 }, + { 184, 240, 322, 326, 246 }, { 185, 241, 323, 327, 247 }, + { 186, 242, 324, 328, 248 }, { 187, 243, 325, 329, 249 }, + { 188, 189, 248, 268, 246 }, { 188, 189, 249, 269, 247 }, + { 188, 246, 326, 327, 247 }, { 189, 248, 328, 329, 249 }, + { 190, 250, 330, 350, 270 }, { 191, 251, 331, 351, 271 }, + { 192, 250, 330, 352, 272 }, { 193, 251, 331, 353, 273 }, + { 194, 250, 330, 354, 279 }, { 195, 251, 331, 355, 280 }, + { 196, 252, 332, 356, 274 }, { 197, 253, 333, 357, 275 }, + { 198, 254, 334, 358, 276 }, { 199, 255, 335, 359, 277 }, + { 200, 256, 336, 360, 278 }, { 201, 252, 332, 361, 282 }, + { 202, 253, 333, 362, 283 }, { 203, 254, 334, 363, 284 }, + { 204, 255, 335, 364, 285 }, { 205, 257, 337, 365, 281 }, + { 206, 252, 332, 366, 290 }, { 207, 253, 333, 367, 291 }, + { 208, 254, 334, 368, 292 }, { 209, 255, 335, 369, 293 }, + { 210, 256, 336, 370, 294 }, { 211, 256, 336, 371, 295 }, + { 212, 258, 338, 372, 286 }, { 213, 259, 339, 373, 287 }, + { 214, 260, 340, 374, 288 }, { 215, 261, 341, 375, 289 }, + { 216, 257, 337, 376, 296 }, { 217, 257, 337, 377, 297 }, + { 218, 258, 338, 378, 298 }, { 219, 259, 339, 379, 299 }, + { 220, 260, 340, 380, 300 }, { 221, 261, 341, 381, 301 }, + { 222, 262, 342, 382, 302 }, { 223, 262, 342, 383, 303 }, + { 224, 258, 338, 384, 310 }, { 225, 259, 339, 385, 311 }, + { 226, 260, 340, 386, 312 }, { 227, 261, 341, 387, 313 }, + { 228, 263, 343, 388, 304 }, { 229, 263, 343, 389, 305 }, + { 230, 264, 344, 390, 306 }, { 231, 265, 345, 391, 307 }, + { 232, 266, 346, 392, 308 }, { 233, 267, 347, 393, 309 }, + { 234, 262, 342, 394, 318 }, { 235, 264, 344, 395, 314 }, + { 236, 265, 345, 396, 315 }, { 237, 266, 346, 397, 316 }, + { 238, 267, 347, 398, 317 }, { 239, 263, 343, 399, 321 }, + { 240, 264, 344, 400, 322 }, { 241, 265, 345, 401, 323 }, + { 242, 266, 346, 402, 324 }, { 243, 267, 347, 403, 325 }, + { 244, 268, 348, 404, 319 }, { 245, 269, 349, 405, 320 }, + { 246, 268, 348, 406, 326 }, { 247, 269, 349, 407, 327 }, + { 248, 268, 348, 408, 328 }, { 249, 269, 349, 409, 329 }, + { 270, 271, 275, 278, 274 }, { 270, 271, 351, 410, 350 }, + { 270, 274, 356, 412, 350 }, { 271, 275, 357, 413, 351 }, + { 272, 273, 277, 281, 276 }, { 272, 273, 353, 411, 352 }, + { 272, 276, 358, 414, 352 }, { 273, 277, 359, 415, 353 }, + { 274, 278, 360, 420, 356 }, { 275, 278, 360, 421, 357 }, + { 276, 281, 365, 422, 358 }, { 277, 281, 365, 423, 359 }, + { 279, 282, 286, 288, 284 }, { 279, 282, 361, 416, 354 }, + { 279, 284, 363, 418, 354 }, { 280, 283, 287, 289, 285 }, + { 280, 283, 362, 417, 355 }, { 280, 285, 364, 419, 355 }, + { 282, 286, 372, 426, 361 }, { 283, 287, 373, 427, 362 }, + { 284, 288, 374, 428, 363 }, { 285, 289, 375, 429, 364 }, + { 286, 288, 374, 436, 372 }, { 287, 289, 375, 437, 373 }, + { 290, 294, 302, 306, 298 }, { 290, 294, 370, 424, 366 }, + { 290, 298, 378, 432, 366 }, { 291, 295, 303, 307, 299 }, + { 291, 295, 371, 425, 367 }, { 291, 299, 379, 433, 367 }, + { 292, 296, 304, 308, 300 }, { 292, 296, 376, 430, 368 }, + { 292, 300, 380, 434, 368 }, { 293, 297, 305, 309, 301 }, + { 293, 297, 377, 431, 369 }, { 293, 301, 381, 435, 369 }, + { 294, 302, 382, 438, 370 }, { 295, 303, 383, 439, 371 }, + { 296, 304, 388, 440, 376 }, { 297, 305, 389, 441, 377 }, + { 298, 306, 390, 444, 378 }, { 299, 307, 391, 445, 379 }, + { 300, 308, 392, 446, 380 }, { 301, 309, 393, 447, 381 }, + { 302, 306, 390, 448, 382 }, { 303, 307, 391, 449, 383 }, + { 304, 308, 392, 454, 388 }, { 305, 309, 393, 455, 389 }, + { 310, 312, 316, 319, 314 }, { 310, 312, 386, 442, 384 }, + { 310, 314, 395, 450, 384 }, { 311, 313, 317, 320, 315 }, + { 311, 313, 387, 443, 385 }, { 311, 315, 396, 451, 385 }, + { 312, 316, 397, 452, 386 }, { 313, 317, 398, 453, 387 }, + { 314, 319, 404, 460, 395 }, { 315, 320, 405, 461, 396 }, + { 316, 319, 404, 462, 397 }, { 317, 320, 405, 463, 398 }, + { 318, 322, 326, 327, 323 }, { 318, 322, 400, 456, 394 }, + { 318, 323, 401, 457, 394 }, { 321, 324, 328, 329, 325 }, + { 321, 324, 402, 458, 399 }, { 321, 325, 403, 459, 399 }, + { 322, 326, 406, 464, 400 }, { 323, 327, 407, 465, 401 }, + { 324, 328, 408, 466, 402 }, { 325, 329, 409, 467, 403 }, + { 326, 327, 407, 468, 406 }, { 328, 329, 409, 469, 408 }, + { 330, 350, 410, 411, 352 }, { 330, 350, 412, 416, 354 }, + { 330, 352, 414, 418, 354 }, { 331, 351, 410, 411, 353 }, + { 331, 351, 413, 417, 355 }, { 331, 353, 415, 419, 355 }, + { 332, 356, 412, 416, 361 }, { 332, 356, 420, 424, 366 }, + { 332, 361, 426, 432, 366 }, { 333, 357, 413, 417, 362 }, + { 333, 357, 421, 425, 367 }, { 333, 362, 427, 433, 367 }, + { 334, 358, 414, 418, 363 }, { 334, 358, 422, 430, 368 }, + { 334, 363, 428, 434, 368 }, { 335, 359, 415, 419, 364 }, + { 335, 359, 423, 431, 369 }, { 335, 364, 429, 435, 369 }, + { 336, 360, 420, 424, 370 }, { 336, 360, 421, 425, 371 }, + { 336, 370, 438, 439, 371 }, { 337, 365, 422, 430, 376 }, + { 337, 365, 423, 431, 377 }, { 337, 376, 440, 441, 377 }, + { 338, 372, 426, 432, 378 }, { 338, 372, 436, 442, 384 }, + { 338, 378, 444, 450, 384 }, { 339, 373, 427, 433, 379 }, + { 339, 373, 437, 443, 385 }, { 339, 379, 445, 451, 385 }, + { 340, 374, 428, 434, 380 }, { 340, 374, 436, 442, 386 }, + { 340, 380, 446, 452, 386 }, { 341, 375, 429, 435, 381 }, + { 341, 375, 437, 443, 387 }, { 341, 381, 447, 453, 387 }, + { 342, 382, 438, 439, 383 }, { 342, 382, 448, 456, 394 }, + { 342, 383, 449, 457, 394 }, { 343, 388, 440, 441, 389 }, + { 343, 388, 454, 458, 399 }, { 343, 389, 455, 459, 399 }, + { 344, 390, 444, 450, 395 }, { 344, 390, 448, 456, 400 }, + { 344, 395, 460, 464, 400 }, { 345, 391, 445, 451, 396 }, + { 345, 391, 449, 457, 401 }, { 345, 396, 461, 465, 401 }, + { 346, 392, 446, 452, 397 }, { 346, 392, 454, 458, 402 }, + { 346, 397, 462, 466, 402 }, { 347, 393, 447, 453, 398 }, + { 347, 393, 455, 459, 403 }, { 347, 398, 463, 467, 403 }, + { 348, 404, 460, 464, 406 }, { 348, 404, 462, 466, 408 }, + { 348, 406, 468, 469, 408 }, { 349, 405, 461, 465, 407 }, + { 349, 405, 463, 467, 409 }, { 349, 407, 468, 469, 409 }, + { 350, 410, 470, 472, 412 }, { 351, 410, 470, 473, 413 }, + { 352, 411, 471, 474, 414 }, { 353, 411, 471, 475, 415 }, + { 354, 416, 478, 480, 418 }, { 355, 417, 479, 481, 419 }, + { 356, 412, 472, 476, 420 }, { 357, 413, 473, 477, 421 }, + { 358, 414, 474, 482, 422 }, { 359, 415, 475, 483, 423 }, + { 360, 420, 476, 477, 421 }, { 361, 416, 478, 484, 426 }, + { 362, 417, 479, 485, 427 }, { 363, 418, 480, 486, 428 }, + { 364, 419, 481, 487, 429 }, { 365, 422, 482, 483, 423 }, + { 366, 424, 488, 494, 432 }, { 367, 425, 489, 495, 433 }, + { 368, 430, 492, 496, 434 }, { 369, 431, 493, 497, 435 }, + { 370, 424, 488, 498, 438 }, { 371, 425, 489, 499, 439 }, + { 372, 426, 484, 490, 436 }, { 373, 427, 485, 491, 437 }, + { 374, 428, 486, 490, 436 }, { 375, 429, 487, 491, 437 }, + { 376, 430, 492, 500, 440 }, { 377, 431, 493, 501, 441 }, + { 378, 432, 494, 502, 444 }, { 379, 433, 495, 503, 445 }, + { 380, 434, 496, 504, 446 }, { 381, 435, 497, 505, 447 }, + { 382, 438, 498, 506, 448 }, { 383, 439, 499, 507, 449 }, + { 384, 442, 508, 512, 450 }, { 385, 443, 509, 513, 451 }, + { 386, 442, 508, 514, 452 }, { 387, 443, 509, 515, 453 }, + { 388, 440, 500, 510, 454 }, { 389, 441, 501, 511, 455 }, + { 390, 444, 502, 506, 448 }, { 391, 445, 503, 507, 449 }, + { 392, 446, 504, 510, 454 }, { 393, 447, 505, 511, 455 }, + { 394, 456, 516, 517, 457 }, { 395, 450, 512, 518, 460 }, + { 396, 451, 513, 519, 461 }, { 397, 452, 514, 520, 462 }, + { 398, 453, 515, 521, 463 }, { 399, 458, 522, 523, 459 }, + { 400, 456, 516, 524, 464 }, { 401, 457, 517, 525, 465 }, + { 402, 458, 522, 526, 466 }, { 403, 459, 523, 527, 467 }, + { 404, 460, 518, 520, 462 }, { 405, 461, 519, 521, 463 }, + { 406, 464, 524, 528, 468 }, { 407, 465, 525, 528, 468 }, + { 408, 466, 526, 529, 469 }, { 409, 467, 527, 529, 469 }, + { 410, 411, 471, 530, 470 }, { 412, 416, 478, 531, 472 }, + { 413, 417, 479, 532, 473 }, { 414, 418, 480, 533, 474 }, + { 415, 419, 481, 534, 475 }, { 420, 424, 488, 535, 476 }, + { 421, 425, 489, 536, 477 }, { 422, 430, 492, 537, 482 }, + { 423, 431, 493, 538, 483 }, { 426, 432, 494, 539, 484 }, + { 427, 433, 495, 540, 485 }, { 428, 434, 496, 541, 486 }, + { 429, 435, 497, 542, 487 }, { 436, 442, 508, 544, 490 }, + { 437, 443, 509, 545, 491 }, { 438, 439, 499, 543, 498 }, + { 440, 441, 501, 546, 500 }, { 444, 450, 512, 547, 502 }, + { 445, 451, 513, 548, 503 }, { 446, 452, 514, 549, 504 }, + { 447, 453, 515, 550, 505 }, { 448, 456, 516, 551, 506 }, + { 449, 457, 517, 552, 507 }, { 454, 458, 522, 553, 510 }, + { 455, 459, 523, 554, 511 }, { 460, 464, 524, 555, 518 }, + { 461, 465, 525, 556, 519 }, { 462, 466, 526, 557, 520 }, + { 463, 467, 527, 558, 521 }, { 468, 469, 529, 559, 528 }, + { 470, 472, 476, 477, 473 }, { 470, 472, 531, 560, 530 }, + { 470, 473, 532, 561, 530 }, { 471, 474, 482, 483, 475 }, + { 471, 474, 533, 560, 530 }, { 471, 475, 534, 561, 530 }, + { 472, 476, 535, 562, 531 }, { 473, 477, 536, 563, 532 }, + { 474, 482, 537, 564, 533 }, { 475, 483, 538, 565, 534 }, + { 476, 477, 536, 566, 535 }, { 478, 480, 486, 490, 484 }, + { 478, 480, 533, 560, 531 }, { 478, 484, 539, 562, 531 }, + { 479, 481, 487, 491, 485 }, { 479, 481, 534, 561, 532 }, + { 479, 485, 540, 563, 532 }, { 480, 486, 541, 564, 533 }, + { 481, 487, 542, 565, 534 }, { 482, 483, 538, 567, 537 }, + { 484, 490, 544, 568, 539 }, { 485, 491, 545, 569, 540 }, + { 486, 490, 544, 570, 541 }, { 487, 491, 545, 571, 542 }, + { 488, 494, 502, 506, 498 }, { 488, 494, 539, 562, 535 }, + { 488, 498, 543, 566, 535 }, { 489, 495, 503, 507, 499 }, + { 489, 495, 540, 563, 536 }, { 489, 499, 543, 566, 536 }, + { 492, 496, 504, 510, 500 }, { 492, 496, 541, 564, 537 }, + { 492, 500, 546, 567, 537 }, { 493, 497, 505, 511, 501 }, + { 493, 497, 542, 565, 538 }, { 493, 501, 546, 567, 538 }, + { 494, 502, 547, 568, 539 }, { 495, 503, 548, 569, 540 }, + { 496, 504, 549, 570, 541 }, { 497, 505, 550, 571, 542 }, + { 498, 506, 551, 572, 543 }, { 499, 507, 552, 572, 543 }, + { 500, 510, 553, 573, 546 }, { 501, 511, 554, 573, 546 }, + { 502, 506, 551, 574, 547 }, { 503, 507, 552, 575, 548 }, + { 504, 510, 553, 576, 549 }, { 505, 511, 554, 577, 550 }, + { 508, 512, 518, 520, 514 }, { 508, 512, 547, 568, 544 }, + { 508, 514, 549, 570, 544 }, { 509, 513, 519, 521, 515 }, + { 509, 513, 548, 569, 545 }, { 509, 515, 550, 571, 545 }, + { 512, 518, 555, 574, 547 }, { 513, 519, 556, 575, 548 }, + { 514, 520, 557, 576, 549 }, { 515, 521, 558, 577, 550 }, + { 516, 517, 525, 528, 524 }, { 516, 517, 552, 572, 551 }, + { 516, 524, 555, 574, 551 }, { 517, 525, 556, 575, 552 }, + { 518, 520, 557, 578, 555 }, { 519, 521, 558, 579, 556 }, + { 522, 523, 527, 529, 526 }, { 522, 523, 554, 573, 553 }, + { 522, 526, 557, 576, 553 }, { 523, 527, 558, 577, 554 }, + { 524, 528, 559, 578, 555 }, { 525, 528, 559, 579, 556 }, + { 526, 529, 559, 578, 557 }, { 527, 529, 559, 579, 558 }, + { 530, 560, 580, 581, 561 }, { 531, 560, 580, 582, 562 }, + { 532, 561, 581, 583, 563 }, { 533, 560, 580, 584, 564 }, + { 534, 561, 581, 585, 565 }, { 535, 562, 582, 586, 566 }, + { 536, 563, 583, 586, 566 }, { 537, 564, 584, 587, 567 }, + { 538, 565, 585, 587, 567 }, { 539, 562, 582, 588, 568 }, + { 540, 563, 583, 589, 569 }, { 541, 564, 584, 590, 570 }, + { 542, 565, 585, 591, 571 }, { 543, 566, 586, 592, 572 }, + { 544, 568, 588, 590, 570 }, { 545, 569, 589, 591, 571 }, + { 546, 567, 587, 593, 573 }, { 547, 568, 588, 594, 574 }, + { 548, 569, 589, 595, 575 }, { 549, 570, 590, 596, 576 }, + { 550, 571, 591, 597, 577 }, { 551, 572, 592, 594, 574 }, + { 552, 572, 592, 595, 575 }, { 553, 573, 593, 596, 576 }, + { 554, 573, 593, 597, 577 }, { 555, 574, 594, 598, 578 }, + { 556, 575, 595, 599, 579 }, { 557, 576, 596, 598, 578 }, + { 558, 577, 597, 599, 579 }, { 559, 578, 598, 599, 579 }, + { 580, 581, 583, 586, 582 }, { 580, 581, 585, 587, 584 }, + { 580, 582, 588, 590, 584 }, { 581, 583, 589, 591, 585 }, + { 582, 586, 592, 594, 588 }, { 583, 586, 592, 595, 589 }, + { 584, 587, 593, 596, 590 }, { 585, 587, 593, 597, 591 }, + { 588, 590, 596, 598, 594 }, { 589, 591, 597, 599, 595 }, + { 592, 594, 598, 599, 595 }, { 593, 596, 598, 599, 597 } +}; + + + +static const float vert_600[NUM_VERT_600][4] = { + { 0.0, 0.0, 0.0, -2.0 }, + { 0.0, -GOLDENINV, -1.0, -GOLDEN }, + { 0.0, GOLDENINV, -1.0, -GOLDEN }, + { -1.0, 0.0, -GOLDENINV, -GOLDEN }, + { 1.0, 0.0, -GOLDENINV, -GOLDEN }, + { -GOLDENINV, -1.0, 0.0, -GOLDEN }, + { GOLDENINV, -1.0, 0.0, -GOLDEN }, + { -GOLDENINV, 1.0, 0.0, -GOLDEN }, + { GOLDENINV, 1.0, 0.0, -GOLDEN }, + { -1.0, 0.0, GOLDENINV, -GOLDEN }, + { 1.0, 0.0, GOLDENINV, -GOLDEN }, + { 0.0, -GOLDENINV, 1.0, -GOLDEN }, + { 0.0, GOLDENINV, 1.0, -GOLDEN }, + { -GOLDENINV, 0.0, -GOLDEN, -1.0 }, + { GOLDENINV, 0.0, -GOLDEN, -1.0 }, + { -1.0, -1.0, -1.0, -1.0 }, + { 1.0, -1.0, -1.0, -1.0 }, + { -1.0, 1.0, -1.0, -1.0 }, + { 1.0, 1.0, -1.0, -1.0 }, + { 0.0, -GOLDEN, -GOLDENINV, -1.0 }, + { 0.0, GOLDEN, -GOLDENINV, -1.0 }, + { -GOLDEN, -GOLDENINV, 0.0, -1.0 }, + { GOLDEN, -GOLDENINV, 0.0, -1.0 }, + { -GOLDEN, GOLDENINV, 0.0, -1.0 }, + { GOLDEN, GOLDENINV, 0.0, -1.0 }, + { 0.0, -GOLDEN, GOLDENINV, -1.0 }, + { 0.0, GOLDEN, GOLDENINV, -1.0 }, + { -1.0, -1.0, 1.0, -1.0 }, + { 1.0, -1.0, 1.0, -1.0 }, + { -1.0, 1.0, 1.0, -1.0 }, + { 1.0, 1.0, 1.0, -1.0 }, + { -GOLDENINV, 0.0, GOLDEN, -1.0 }, + { GOLDENINV, 0.0, GOLDEN, -1.0 }, + { 0.0, -1.0, -GOLDEN, -GOLDENINV }, + { 0.0, 1.0, -GOLDEN, -GOLDENINV }, + { -GOLDEN, 0.0, -1.0, -GOLDENINV }, + { GOLDEN, 0.0, -1.0, -GOLDENINV }, + { -1.0, -GOLDEN, 0.0, -GOLDENINV }, + { 1.0, -GOLDEN, 0.0, -GOLDENINV }, + { -1.0, GOLDEN, 0.0, -GOLDENINV }, + { 1.0, GOLDEN, 0.0, -GOLDENINV }, + { -GOLDEN, 0.0, 1.0, -GOLDENINV }, + { GOLDEN, 0.0, 1.0, -GOLDENINV }, + { 0.0, -1.0, GOLDEN, -GOLDENINV }, + { 0.0, 1.0, GOLDEN, -GOLDENINV }, + { 0.0, 0.0, -2.0, 0.0 }, + { -1.0, -GOLDENINV, -GOLDEN, 0.0 }, + { 1.0, -GOLDENINV, -GOLDEN, 0.0 }, + { -1.0, GOLDENINV, -GOLDEN, 0.0 }, + { 1.0, GOLDENINV, -GOLDEN, 0.0 }, + { -GOLDENINV, -GOLDEN, -1.0, 0.0 }, + { GOLDENINV, -GOLDEN, -1.0, 0.0 }, + { -GOLDENINV, GOLDEN, -1.0, 0.0 }, + { GOLDENINV, GOLDEN, -1.0, 0.0 }, + { -GOLDEN, -1.0, -GOLDENINV, 0.0 }, + { GOLDEN, -1.0, -GOLDENINV, 0.0 }, + { -GOLDEN, 1.0, -GOLDENINV, 0.0 }, + { GOLDEN, 1.0, -GOLDENINV, 0.0 }, + { 0.0, -2.0, 0.0, 0.0 }, + { -2.0, 0.0, 0.0, 0.0 }, + { 2.0, 0.0, 0.0, 0.0 }, + { 0.0, 2.0, 0.0, 0.0 }, + { -GOLDEN, -1.0, GOLDENINV, 0.0 }, + { GOLDEN, -1.0, GOLDENINV, 0.0 }, + { -GOLDEN, 1.0, GOLDENINV, 0.0 }, + { GOLDEN, 1.0, GOLDENINV, 0.0 }, + { -GOLDENINV, -GOLDEN, 1.0, 0.0 }, + { GOLDENINV, -GOLDEN, 1.0, 0.0 }, + { -GOLDENINV, GOLDEN, 1.0, 0.0 }, + { GOLDENINV, GOLDEN, 1.0, 0.0 }, + { -1.0, -GOLDENINV, GOLDEN, 0.0 }, + { 1.0, -GOLDENINV, GOLDEN, 0.0 }, + { -1.0, GOLDENINV, GOLDEN, 0.0 }, + { 1.0, GOLDENINV, GOLDEN, 0.0 }, + { 0.0, 0.0, 2.0, 0.0 }, + { 0.0, -1.0, -GOLDEN, GOLDENINV }, + { 0.0, 1.0, -GOLDEN, GOLDENINV }, + { -GOLDEN, 0.0, -1.0, GOLDENINV }, + { GOLDEN, 0.0, -1.0, GOLDENINV }, + { -1.0, -GOLDEN, 0.0, GOLDENINV }, + { 1.0, -GOLDEN, 0.0, GOLDENINV }, + { -1.0, GOLDEN, 0.0, GOLDENINV }, + { 1.0, GOLDEN, 0.0, GOLDENINV }, + { -GOLDEN, 0.0, 1.0, GOLDENINV }, + { GOLDEN, 0.0, 1.0, GOLDENINV }, + { 0.0, -1.0, GOLDEN, GOLDENINV }, + { 0.0, 1.0, GOLDEN, GOLDENINV }, + { -GOLDENINV, 0.0, -GOLDEN, 1.0 }, + { GOLDENINV, 0.0, -GOLDEN, 1.0 }, + { -1.0, -1.0, -1.0, 1.0 }, + { 1.0, -1.0, -1.0, 1.0 }, + { -1.0, 1.0, -1.0, 1.0 }, + { 1.0, 1.0, -1.0, 1.0 }, + { 0.0, -GOLDEN, -GOLDENINV, 1.0 }, + { 0.0, GOLDEN, -GOLDENINV, 1.0 }, + { -GOLDEN, -GOLDENINV, 0.0, 1.0 }, + { GOLDEN, -GOLDENINV, 0.0, 1.0 }, + { -GOLDEN, GOLDENINV, 0.0, 1.0 }, + { GOLDEN, GOLDENINV, 0.0, 1.0 }, + { 0.0, -GOLDEN, GOLDENINV, 1.0 }, + { 0.0, GOLDEN, GOLDENINV, 1.0 }, + { -1.0, -1.0, 1.0, 1.0 }, + { 1.0, -1.0, 1.0, 1.0 }, + { -1.0, 1.0, 1.0, 1.0 }, + { 1.0, 1.0, 1.0, 1.0 }, + { -GOLDENINV, 0.0, GOLDEN, 1.0 }, + { GOLDENINV, 0.0, GOLDEN, 1.0 }, + { 0.0, -GOLDENINV, -1.0, GOLDEN }, + { 0.0, GOLDENINV, -1.0, GOLDEN }, + { -1.0, 0.0, -GOLDENINV, GOLDEN }, + { 1.0, 0.0, -GOLDENINV, GOLDEN }, + { -GOLDENINV, -1.0, 0.0, GOLDEN }, + { GOLDENINV, -1.0, 0.0, GOLDEN }, + { -GOLDENINV, 1.0, 0.0, GOLDEN }, + { GOLDENINV, 1.0, 0.0, GOLDEN }, + { -1.0, 0.0, GOLDENINV, GOLDEN }, + { 1.0, 0.0, GOLDENINV, GOLDEN }, + { 0.0, -GOLDENINV, 1.0, GOLDEN }, + { 0.0, GOLDENINV, 1.0, GOLDEN }, + { 0.0, 0.0, 0.0, 2.0 } +}; + +static const int edge_600[NUM_EDGE_600][2] = { + { 0, 1 }, { 0, 2 }, { 0, 3 }, { 0, 4 }, { 0, 5 }, + { 0, 6 }, { 0, 7 }, { 0, 8 }, { 0, 9 }, { 0, 10 }, + { 0, 11 }, { 0, 12 }, { 1, 2 }, { 1, 3 }, { 1, 4 }, + { 1, 5 }, { 1, 6 }, { 1, 13 }, { 1, 14 }, { 1, 15 }, + { 1, 16 }, { 1, 19 }, { 1, 33 }, { 2, 3 }, { 2, 4 }, + { 2, 7 }, { 2, 8 }, { 2, 13 }, { 2, 14 }, { 2, 17 }, + { 2, 18 }, { 2, 20 }, { 2, 34 }, { 3, 5 }, { 3, 7 }, + { 3, 9 }, { 3, 13 }, { 3, 15 }, { 3, 17 }, { 3, 21 }, + { 3, 23 }, { 3, 35 }, { 4, 6 }, { 4, 8 }, { 4, 10 }, + { 4, 14 }, { 4, 16 }, { 4, 18 }, { 4, 22 }, { 4, 24 }, + { 4, 36 }, { 5, 6 }, { 5, 9 }, { 5, 11 }, { 5, 15 }, + { 5, 19 }, { 5, 21 }, { 5, 25 }, { 5, 27 }, { 5, 37 }, + { 6, 10 }, { 6, 11 }, { 6, 16 }, { 6, 19 }, { 6, 22 }, + { 6, 25 }, { 6, 28 }, { 6, 38 }, { 7, 8 }, { 7, 9 }, + { 7, 12 }, { 7, 17 }, { 7, 20 }, { 7, 23 }, { 7, 26 }, + { 7, 29 }, { 7, 39 }, { 8, 10 }, { 8, 12 }, { 8, 18 }, + { 8, 20 }, { 8, 24 }, { 8, 26 }, { 8, 30 }, { 8, 40 }, + { 9, 11 }, { 9, 12 }, { 9, 21 }, { 9, 23 }, { 9, 27 }, + { 9, 29 }, { 9, 31 }, { 9, 41 }, { 10, 11 }, { 10, 12 }, + { 10, 22 }, { 10, 24 }, { 10, 28 }, { 10, 30 }, { 10, 32 }, + { 10, 42 }, { 11, 12 }, { 11, 25 }, { 11, 27 }, { 11, 28 }, + { 11, 31 }, { 11, 32 }, { 11, 43 }, { 12, 26 }, { 12, 29 }, + { 12, 30 }, { 12, 31 }, { 12, 32 }, { 12, 44 }, { 13, 14 }, + { 13, 15 }, { 13, 17 }, { 13, 33 }, { 13, 34 }, { 13, 35 }, + { 13, 45 }, { 13, 46 }, { 13, 48 }, { 14, 16 }, { 14, 18 }, + { 14, 33 }, { 14, 34 }, { 14, 36 }, { 14, 45 }, { 14, 47 }, + { 14, 49 }, { 15, 19 }, { 15, 21 }, { 15, 33 }, { 15, 35 }, + { 15, 37 }, { 15, 46 }, { 15, 50 }, { 15, 54 }, { 16, 19 }, + { 16, 22 }, { 16, 33 }, { 16, 36 }, { 16, 38 }, { 16, 47 }, + { 16, 51 }, { 16, 55 }, { 17, 20 }, { 17, 23 }, { 17, 34 }, + { 17, 35 }, { 17, 39 }, { 17, 48 }, { 17, 52 }, { 17, 56 }, + { 18, 20 }, { 18, 24 }, { 18, 34 }, { 18, 36 }, { 18, 40 }, + { 18, 49 }, { 18, 53 }, { 18, 57 }, { 19, 25 }, { 19, 33 }, + { 19, 37 }, { 19, 38 }, { 19, 50 }, { 19, 51 }, { 19, 58 }, + { 20, 26 }, { 20, 34 }, { 20, 39 }, { 20, 40 }, { 20, 52 }, + { 20, 53 }, { 20, 61 }, { 21, 23 }, { 21, 27 }, { 21, 35 }, + { 21, 37 }, { 21, 41 }, { 21, 54 }, { 21, 59 }, { 21, 62 }, + { 22, 24 }, { 22, 28 }, { 22, 36 }, { 22, 38 }, { 22, 42 }, + { 22, 55 }, { 22, 60 }, { 22, 63 }, { 23, 29 }, { 23, 35 }, + { 23, 39 }, { 23, 41 }, { 23, 56 }, { 23, 59 }, { 23, 64 }, + { 24, 30 }, { 24, 36 }, { 24, 40 }, { 24, 42 }, { 24, 57 }, + { 24, 60 }, { 24, 65 }, { 25, 27 }, { 25, 28 }, { 25, 37 }, + { 25, 38 }, { 25, 43 }, { 25, 58 }, { 25, 66 }, { 25, 67 }, + { 26, 29 }, { 26, 30 }, { 26, 39 }, { 26, 40 }, { 26, 44 }, + { 26, 61 }, { 26, 68 }, { 26, 69 }, { 27, 31 }, { 27, 37 }, + { 27, 41 }, { 27, 43 }, { 27, 62 }, { 27, 66 }, { 27, 70 }, + { 28, 32 }, { 28, 38 }, { 28, 42 }, { 28, 43 }, { 28, 63 }, + { 28, 67 }, { 28, 71 }, { 29, 31 }, { 29, 39 }, { 29, 41 }, + { 29, 44 }, { 29, 64 }, { 29, 68 }, { 29, 72 }, { 30, 32 }, + { 30, 40 }, { 30, 42 }, { 30, 44 }, { 30, 65 }, { 30, 69 }, + { 30, 73 }, { 31, 32 }, { 31, 41 }, { 31, 43 }, { 31, 44 }, + { 31, 70 }, { 31, 72 }, { 31, 74 }, { 32, 42 }, { 32, 43 }, + { 32, 44 }, { 32, 71 }, { 32, 73 }, { 32, 74 }, { 33, 45 }, + { 33, 46 }, { 33, 47 }, { 33, 50 }, { 33, 51 }, { 33, 75 }, + { 34, 45 }, { 34, 48 }, { 34, 49 }, { 34, 52 }, { 34, 53 }, + { 34, 76 }, { 35, 46 }, { 35, 48 }, { 35, 54 }, { 35, 56 }, + { 35, 59 }, { 35, 77 }, { 36, 47 }, { 36, 49 }, { 36, 55 }, + { 36, 57 }, { 36, 60 }, { 36, 78 }, { 37, 50 }, { 37, 54 }, + { 37, 58 }, { 37, 62 }, { 37, 66 }, { 37, 79 }, { 38, 51 }, + { 38, 55 }, { 38, 58 }, { 38, 63 }, { 38, 67 }, { 38, 80 }, + { 39, 52 }, { 39, 56 }, { 39, 61 }, { 39, 64 }, { 39, 68 }, + { 39, 81 }, { 40, 53 }, { 40, 57 }, { 40, 61 }, { 40, 65 }, + { 40, 69 }, { 40, 82 }, { 41, 59 }, { 41, 62 }, { 41, 64 }, + { 41, 70 }, { 41, 72 }, { 41, 83 }, { 42, 60 }, { 42, 63 }, + { 42, 65 }, { 42, 71 }, { 42, 73 }, { 42, 84 }, { 43, 66 }, + { 43, 67 }, { 43, 70 }, { 43, 71 }, { 43, 74 }, { 43, 85 }, + { 44, 68 }, { 44, 69 }, { 44, 72 }, { 44, 73 }, { 44, 74 }, + { 44, 86 }, { 45, 46 }, { 45, 47 }, { 45, 48 }, { 45, 49 }, + { 45, 75 }, { 45, 76 }, { 45, 87 }, { 45, 88 }, { 46, 48 }, + { 46, 50 }, { 46, 54 }, { 46, 75 }, { 46, 77 }, { 46, 87 }, + { 46, 89 }, { 47, 49 }, { 47, 51 }, { 47, 55 }, { 47, 75 }, + { 47, 78 }, { 47, 88 }, { 47, 90 }, { 48, 52 }, { 48, 56 }, + { 48, 76 }, { 48, 77 }, { 48, 87 }, { 48, 91 }, { 49, 53 }, + { 49, 57 }, { 49, 76 }, { 49, 78 }, { 49, 88 }, { 49, 92 }, + { 50, 51 }, { 50, 54 }, { 50, 58 }, { 50, 75 }, { 50, 79 }, + { 50, 89 }, { 50, 93 }, { 51, 55 }, { 51, 58 }, { 51, 75 }, + { 51, 80 }, { 51, 90 }, { 51, 93 }, { 52, 53 }, { 52, 56 }, + { 52, 61 }, { 52, 76 }, { 52, 81 }, { 52, 91 }, { 52, 94 }, + { 53, 57 }, { 53, 61 }, { 53, 76 }, { 53, 82 }, { 53, 92 }, + { 53, 94 }, { 54, 59 }, { 54, 62 }, { 54, 77 }, { 54, 79 }, + { 54, 89 }, { 54, 95 }, { 55, 60 }, { 55, 63 }, { 55, 78 }, + { 55, 80 }, { 55, 90 }, { 55, 96 }, { 56, 59 }, { 56, 64 }, + { 56, 77 }, { 56, 81 }, { 56, 91 }, { 56, 97 }, { 57, 60 }, + { 57, 65 }, { 57, 78 }, { 57, 82 }, { 57, 92 }, { 57, 98 }, + { 58, 66 }, { 58, 67 }, { 58, 79 }, { 58, 80 }, { 58, 93 }, + { 58, 99 }, { 59, 62 }, { 59, 64 }, { 59, 77 }, { 59, 83 }, + { 59, 95 }, { 59, 97 }, { 60, 63 }, { 60, 65 }, { 60, 78 }, + { 60, 84 }, { 60, 96 }, { 60, 98 }, { 61, 68 }, { 61, 69 }, + { 61, 81 }, { 61, 82 }, { 61, 94 }, { 61, 100 }, { 62, 66 }, + { 62, 70 }, { 62, 79 }, { 62, 83 }, { 62, 95 }, { 62, 101 }, + { 63, 67 }, { 63, 71 }, { 63, 80 }, { 63, 84 }, { 63, 96 }, + { 63, 102 }, { 64, 68 }, { 64, 72 }, { 64, 81 }, { 64, 83 }, + { 64, 97 }, { 64, 103 }, { 65, 69 }, { 65, 73 }, { 65, 82 }, + { 65, 84 }, { 65, 98 }, { 65, 104 }, { 66, 67 }, { 66, 70 }, + { 66, 79 }, { 66, 85 }, { 66, 99 }, { 66, 101 }, { 67, 71 }, + { 67, 80 }, { 67, 85 }, { 67, 99 }, { 67, 102 }, { 68, 69 }, + { 68, 72 }, { 68, 81 }, { 68, 86 }, { 68, 100 }, { 68, 103 }, + { 69, 73 }, { 69, 82 }, { 69, 86 }, { 69, 100 }, { 69, 104 }, + { 70, 72 }, { 70, 74 }, { 70, 83 }, { 70, 85 }, { 70, 101 }, + { 70, 105 }, { 71, 73 }, { 71, 74 }, { 71, 84 }, { 71, 85 }, + { 71, 102 }, { 71, 106 }, { 72, 74 }, { 72, 83 }, { 72, 86 }, + { 72, 103 }, { 72, 105 }, { 73, 74 }, { 73, 84 }, { 73, 86 }, + { 73, 104 }, { 73, 106 }, { 74, 85 }, { 74, 86 }, { 74, 105 }, + { 74, 106 }, { 75, 87 }, { 75, 88 }, { 75, 89 }, { 75, 90 }, + { 75, 93 }, { 75, 107 }, { 76, 87 }, { 76, 88 }, { 76, 91 }, + { 76, 92 }, { 76, 94 }, { 76, 108 }, { 77, 87 }, { 77, 89 }, + { 77, 91 }, { 77, 95 }, { 77, 97 }, { 77, 109 }, { 78, 88 }, + { 78, 90 }, { 78, 92 }, { 78, 96 }, { 78, 98 }, { 78, 110 }, + { 79, 89 }, { 79, 93 }, { 79, 95 }, { 79, 99 }, { 79, 101 }, + { 79, 111 }, { 80, 90 }, { 80, 93 }, { 80, 96 }, { 80, 99 }, + { 80, 102 }, { 80, 112 }, { 81, 91 }, { 81, 94 }, { 81, 97 }, + { 81, 100 }, { 81, 103 }, { 81, 113 }, { 82, 92 }, { 82, 94 }, + { 82, 98 }, { 82, 100 }, { 82, 104 }, { 82, 114 }, { 83, 95 }, + { 83, 97 }, { 83, 101 }, { 83, 103 }, { 83, 105 }, { 83, 115 }, + { 84, 96 }, { 84, 98 }, { 84, 102 }, { 84, 104 }, { 84, 106 }, + { 84, 116 }, { 85, 99 }, { 85, 101 }, { 85, 102 }, { 85, 105 }, + { 85, 106 }, { 85, 117 }, { 86, 100 }, { 86, 103 }, { 86, 104 }, + { 86, 105 }, { 86, 106 }, { 86, 118 }, { 87, 88 }, { 87, 89 }, + { 87, 91 }, { 87, 107 }, { 87, 108 }, { 87, 109 }, { 88, 90 }, + { 88, 92 }, { 88, 107 }, { 88, 108 }, { 88, 110 }, { 89, 93 }, + { 89, 95 }, { 89, 107 }, { 89, 109 }, { 89, 111 }, { 90, 93 }, + { 90, 96 }, { 90, 107 }, { 90, 110 }, { 90, 112 }, { 91, 94 }, + { 91, 97 }, { 91, 108 }, { 91, 109 }, { 91, 113 }, { 92, 94 }, + { 92, 98 }, { 92, 108 }, { 92, 110 }, { 92, 114 }, { 93, 99 }, + { 93, 107 }, { 93, 111 }, { 93, 112 }, { 94, 100 }, { 94, 108 }, + { 94, 113 }, { 94, 114 }, { 95, 97 }, { 95, 101 }, { 95, 109 }, + { 95, 111 }, { 95, 115 }, { 96, 98 }, { 96, 102 }, { 96, 110 }, + { 96, 112 }, { 96, 116 }, { 97, 103 }, { 97, 109 }, { 97, 113 }, + { 97, 115 }, { 98, 104 }, { 98, 110 }, { 98, 114 }, { 98, 116 }, + { 99, 101 }, { 99, 102 }, { 99, 111 }, { 99, 112 }, { 99, 117 }, + { 100, 103 }, { 100, 104 }, { 100, 113 }, { 100, 114 }, { 100, 118 }, + { 101, 105 }, { 101, 111 }, { 101, 115 }, { 101, 117 }, { 102, 106 }, + { 102, 112 }, { 102, 116 }, { 102, 117 }, { 103, 105 }, { 103, 113 }, + { 103, 115 }, { 103, 118 }, { 104, 106 }, { 104, 114 }, { 104, 116 }, + { 104, 118 }, { 105, 106 }, { 105, 115 }, { 105, 117 }, { 105, 118 }, + { 106, 116 }, { 106, 117 }, { 106, 118 }, { 107, 108 }, { 107, 109 }, + { 107, 110 }, { 107, 111 }, { 107, 112 }, { 107, 119 }, { 108, 109 }, + { 108, 110 }, { 108, 113 }, { 108, 114 }, { 108, 119 }, { 109, 111 }, + { 109, 113 }, { 109, 115 }, { 109, 119 }, { 110, 112 }, { 110, 114 }, + { 110, 116 }, { 110, 119 }, { 111, 112 }, { 111, 115 }, { 111, 117 }, + { 111, 119 }, { 112, 116 }, { 112, 117 }, { 112, 119 }, { 113, 114 }, + { 113, 115 }, { 113, 118 }, { 113, 119 }, { 114, 116 }, { 114, 118 }, + { 114, 119 }, { 115, 117 }, { 115, 118 }, { 115, 119 }, { 116, 117 }, + { 116, 118 }, { 116, 119 }, { 117, 118 }, { 117, 119 }, { 118, 119 } +}; + +static const int face_600[NUM_FACE_600][VERT_PER_FACE_600] = { + { 0, 1, 2 }, { 0, 1, 3 }, { 0, 1, 4 }, { 0, 1, 5 }, + { 0, 1, 6 }, { 0, 2, 3 }, { 0, 2, 4 }, { 0, 2, 7 }, + { 0, 2, 8 }, { 0, 3, 5 }, { 0, 3, 7 }, { 0, 3, 9 }, + { 0, 4, 6 }, { 0, 4, 8 }, { 0, 4, 10 }, { 0, 5, 6 }, + { 0, 5, 9 }, { 0, 5, 11 }, { 0, 6, 10 }, { 0, 6, 11 }, + { 0, 7, 8 }, { 0, 7, 9 }, { 0, 7, 12 }, { 0, 8, 10 }, + { 0, 8, 12 }, { 0, 9, 11 }, { 0, 9, 12 }, { 0, 10, 11 }, + { 0, 10, 12 }, { 0, 11, 12 }, { 1, 2, 3 }, { 1, 2, 4 }, + { 1, 2, 13 }, { 1, 2, 14 }, { 1, 3, 5 }, { 1, 3, 13 }, + { 1, 3, 15 }, { 1, 4, 6 }, { 1, 4, 14 }, { 1, 4, 16 }, + { 1, 5, 6 }, { 1, 5, 15 }, { 1, 5, 19 }, { 1, 6, 16 }, + { 1, 6, 19 }, { 1, 13, 14 }, { 1, 13, 15 }, { 1, 13, 33 }, + { 1, 14, 16 }, { 1, 14, 33 }, { 1, 15, 19 }, { 1, 15, 33 }, + { 1, 16, 19 }, { 1, 16, 33 }, { 1, 19, 33 }, { 2, 3, 7 }, + { 2, 3, 13 }, { 2, 3, 17 }, { 2, 4, 8 }, { 2, 4, 14 }, + { 2, 4, 18 }, { 2, 7, 8 }, { 2, 7, 17 }, { 2, 7, 20 }, + { 2, 8, 18 }, { 2, 8, 20 }, { 2, 13, 14 }, { 2, 13, 17 }, + { 2, 13, 34 }, { 2, 14, 18 }, { 2, 14, 34 }, { 2, 17, 20 }, + { 2, 17, 34 }, { 2, 18, 20 }, { 2, 18, 34 }, { 2, 20, 34 }, + { 3, 5, 9 }, { 3, 5, 15 }, { 3, 5, 21 }, { 3, 7, 9 }, + { 3, 7, 17 }, { 3, 7, 23 }, { 3, 9, 21 }, { 3, 9, 23 }, + { 3, 13, 15 }, { 3, 13, 17 }, { 3, 13, 35 }, { 3, 15, 21 }, + { 3, 15, 35 }, { 3, 17, 23 }, { 3, 17, 35 }, { 3, 21, 23 }, + { 3, 21, 35 }, { 3, 23, 35 }, { 4, 6, 10 }, { 4, 6, 16 }, + { 4, 6, 22 }, { 4, 8, 10 }, { 4, 8, 18 }, { 4, 8, 24 }, + { 4, 10, 22 }, { 4, 10, 24 }, { 4, 14, 16 }, { 4, 14, 18 }, + { 4, 14, 36 }, { 4, 16, 22 }, { 4, 16, 36 }, { 4, 18, 24 }, + { 4, 18, 36 }, { 4, 22, 24 }, { 4, 22, 36 }, { 4, 24, 36 }, + { 5, 6, 11 }, { 5, 6, 19 }, { 5, 6, 25 }, { 5, 9, 11 }, + { 5, 9, 21 }, { 5, 9, 27 }, { 5, 11, 25 }, { 5, 11, 27 }, + { 5, 15, 19 }, { 5, 15, 21 }, { 5, 15, 37 }, { 5, 19, 25 }, + { 5, 19, 37 }, { 5, 21, 27 }, { 5, 21, 37 }, { 5, 25, 27 }, + { 5, 25, 37 }, { 5, 27, 37 }, { 6, 10, 11 }, { 6, 10, 22 }, + { 6, 10, 28 }, { 6, 11, 25 }, { 6, 11, 28 }, { 6, 16, 19 }, + { 6, 16, 22 }, { 6, 16, 38 }, { 6, 19, 25 }, { 6, 19, 38 }, + { 6, 22, 28 }, { 6, 22, 38 }, { 6, 25, 28 }, { 6, 25, 38 }, + { 6, 28, 38 }, { 7, 8, 12 }, { 7, 8, 20 }, { 7, 8, 26 }, + { 7, 9, 12 }, { 7, 9, 23 }, { 7, 9, 29 }, { 7, 12, 26 }, + { 7, 12, 29 }, { 7, 17, 20 }, { 7, 17, 23 }, { 7, 17, 39 }, + { 7, 20, 26 }, { 7, 20, 39 }, { 7, 23, 29 }, { 7, 23, 39 }, + { 7, 26, 29 }, { 7, 26, 39 }, { 7, 29, 39 }, { 8, 10, 12 }, + { 8, 10, 24 }, { 8, 10, 30 }, { 8, 12, 26 }, { 8, 12, 30 }, + { 8, 18, 20 }, { 8, 18, 24 }, { 8, 18, 40 }, { 8, 20, 26 }, + { 8, 20, 40 }, { 8, 24, 30 }, { 8, 24, 40 }, { 8, 26, 30 }, + { 8, 26, 40 }, { 8, 30, 40 }, { 9, 11, 12 }, { 9, 11, 27 }, + { 9, 11, 31 }, { 9, 12, 29 }, { 9, 12, 31 }, { 9, 21, 23 }, + { 9, 21, 27 }, { 9, 21, 41 }, { 9, 23, 29 }, { 9, 23, 41 }, + { 9, 27, 31 }, { 9, 27, 41 }, { 9, 29, 31 }, { 9, 29, 41 }, + { 9, 31, 41 }, { 10, 11, 12 }, { 10, 11, 28 }, { 10, 11, 32 }, + { 10, 12, 30 }, { 10, 12, 32 }, { 10, 22, 24 }, { 10, 22, 28 }, + { 10, 22, 42 }, { 10, 24, 30 }, { 10, 24, 42 }, { 10, 28, 32 }, + { 10, 28, 42 }, { 10, 30, 32 }, { 10, 30, 42 }, { 10, 32, 42 }, + { 11, 12, 31 }, { 11, 12, 32 }, { 11, 25, 27 }, { 11, 25, 28 }, + { 11, 25, 43 }, { 11, 27, 31 }, { 11, 27, 43 }, { 11, 28, 32 }, + { 11, 28, 43 }, { 11, 31, 32 }, { 11, 31, 43 }, { 11, 32, 43 }, + { 12, 26, 29 }, { 12, 26, 30 }, { 12, 26, 44 }, { 12, 29, 31 }, + { 12, 29, 44 }, { 12, 30, 32 }, { 12, 30, 44 }, { 12, 31, 32 }, + { 12, 31, 44 }, { 12, 32, 44 }, { 13, 14, 33 }, { 13, 14, 34 }, + { 13, 14, 45 }, { 13, 15, 33 }, { 13, 15, 35 }, { 13, 15, 46 }, + { 13, 17, 34 }, { 13, 17, 35 }, { 13, 17, 48 }, { 13, 33, 45 }, + { 13, 33, 46 }, { 13, 34, 45 }, { 13, 34, 48 }, { 13, 35, 46 }, + { 13, 35, 48 }, { 13, 45, 46 }, { 13, 45, 48 }, { 13, 46, 48 }, + { 14, 16, 33 }, { 14, 16, 36 }, { 14, 16, 47 }, { 14, 18, 34 }, + { 14, 18, 36 }, { 14, 18, 49 }, { 14, 33, 45 }, { 14, 33, 47 }, + { 14, 34, 45 }, { 14, 34, 49 }, { 14, 36, 47 }, { 14, 36, 49 }, + { 14, 45, 47 }, { 14, 45, 49 }, { 14, 47, 49 }, { 15, 19, 33 }, + { 15, 19, 37 }, { 15, 19, 50 }, { 15, 21, 35 }, { 15, 21, 37 }, + { 15, 21, 54 }, { 15, 33, 46 }, { 15, 33, 50 }, { 15, 35, 46 }, + { 15, 35, 54 }, { 15, 37, 50 }, { 15, 37, 54 }, { 15, 46, 50 }, + { 15, 46, 54 }, { 15, 50, 54 }, { 16, 19, 33 }, { 16, 19, 38 }, + { 16, 19, 51 }, { 16, 22, 36 }, { 16, 22, 38 }, { 16, 22, 55 }, + { 16, 33, 47 }, { 16, 33, 51 }, { 16, 36, 47 }, { 16, 36, 55 }, + { 16, 38, 51 }, { 16, 38, 55 }, { 16, 47, 51 }, { 16, 47, 55 }, + { 16, 51, 55 }, { 17, 20, 34 }, { 17, 20, 39 }, { 17, 20, 52 }, + { 17, 23, 35 }, { 17, 23, 39 }, { 17, 23, 56 }, { 17, 34, 48 }, + { 17, 34, 52 }, { 17, 35, 48 }, { 17, 35, 56 }, { 17, 39, 52 }, + { 17, 39, 56 }, { 17, 48, 52 }, { 17, 48, 56 }, { 17, 52, 56 }, + { 18, 20, 34 }, { 18, 20, 40 }, { 18, 20, 53 }, { 18, 24, 36 }, + { 18, 24, 40 }, { 18, 24, 57 }, { 18, 34, 49 }, { 18, 34, 53 }, + { 18, 36, 49 }, { 18, 36, 57 }, { 18, 40, 53 }, { 18, 40, 57 }, + { 18, 49, 53 }, { 18, 49, 57 }, { 18, 53, 57 }, { 19, 25, 37 }, + { 19, 25, 38 }, { 19, 25, 58 }, { 19, 33, 50 }, { 19, 33, 51 }, + { 19, 37, 50 }, { 19, 37, 58 }, { 19, 38, 51 }, { 19, 38, 58 }, + { 19, 50, 51 }, { 19, 50, 58 }, { 19, 51, 58 }, { 20, 26, 39 }, + { 20, 26, 40 }, { 20, 26, 61 }, { 20, 34, 52 }, { 20, 34, 53 }, + { 20, 39, 52 }, { 20, 39, 61 }, { 20, 40, 53 }, { 20, 40, 61 }, + { 20, 52, 53 }, { 20, 52, 61 }, { 20, 53, 61 }, { 21, 23, 35 }, + { 21, 23, 41 }, { 21, 23, 59 }, { 21, 27, 37 }, { 21, 27, 41 }, + { 21, 27, 62 }, { 21, 35, 54 }, { 21, 35, 59 }, { 21, 37, 54 }, + { 21, 37, 62 }, { 21, 41, 59 }, { 21, 41, 62 }, { 21, 54, 59 }, + { 21, 54, 62 }, { 21, 59, 62 }, { 22, 24, 36 }, { 22, 24, 42 }, + { 22, 24, 60 }, { 22, 28, 38 }, { 22, 28, 42 }, { 22, 28, 63 }, + { 22, 36, 55 }, { 22, 36, 60 }, { 22, 38, 55 }, { 22, 38, 63 }, + { 22, 42, 60 }, { 22, 42, 63 }, { 22, 55, 60 }, { 22, 55, 63 }, + { 22, 60, 63 }, { 23, 29, 39 }, { 23, 29, 41 }, { 23, 29, 64 }, + { 23, 35, 56 }, { 23, 35, 59 }, { 23, 39, 56 }, { 23, 39, 64 }, + { 23, 41, 59 }, { 23, 41, 64 }, { 23, 56, 59 }, { 23, 56, 64 }, + { 23, 59, 64 }, { 24, 30, 40 }, { 24, 30, 42 }, { 24, 30, 65 }, + { 24, 36, 57 }, { 24, 36, 60 }, { 24, 40, 57 }, { 24, 40, 65 }, + { 24, 42, 60 }, { 24, 42, 65 }, { 24, 57, 60 }, { 24, 57, 65 }, + { 24, 60, 65 }, { 25, 27, 37 }, { 25, 27, 43 }, { 25, 27, 66 }, + { 25, 28, 38 }, { 25, 28, 43 }, { 25, 28, 67 }, { 25, 37, 58 }, + { 25, 37, 66 }, { 25, 38, 58 }, { 25, 38, 67 }, { 25, 43, 66 }, + { 25, 43, 67 }, { 25, 58, 66 }, { 25, 58, 67 }, { 25, 66, 67 }, + { 26, 29, 39 }, { 26, 29, 44 }, { 26, 29, 68 }, { 26, 30, 40 }, + { 26, 30, 44 }, { 26, 30, 69 }, { 26, 39, 61 }, { 26, 39, 68 }, + { 26, 40, 61 }, { 26, 40, 69 }, { 26, 44, 68 }, { 26, 44, 69 }, + { 26, 61, 68 }, { 26, 61, 69 }, { 26, 68, 69 }, { 27, 31, 41 }, + { 27, 31, 43 }, { 27, 31, 70 }, { 27, 37, 62 }, { 27, 37, 66 }, + { 27, 41, 62 }, { 27, 41, 70 }, { 27, 43, 66 }, { 27, 43, 70 }, + { 27, 62, 66 }, { 27, 62, 70 }, { 27, 66, 70 }, { 28, 32, 42 }, + { 28, 32, 43 }, { 28, 32, 71 }, { 28, 38, 63 }, { 28, 38, 67 }, + { 28, 42, 63 }, { 28, 42, 71 }, { 28, 43, 67 }, { 28, 43, 71 }, + { 28, 63, 67 }, { 28, 63, 71 }, { 28, 67, 71 }, { 29, 31, 41 }, + { 29, 31, 44 }, { 29, 31, 72 }, { 29, 39, 64 }, { 29, 39, 68 }, + { 29, 41, 64 }, { 29, 41, 72 }, { 29, 44, 68 }, { 29, 44, 72 }, + { 29, 64, 68 }, { 29, 64, 72 }, { 29, 68, 72 }, { 30, 32, 42 }, + { 30, 32, 44 }, { 30, 32, 73 }, { 30, 40, 65 }, { 30, 40, 69 }, + { 30, 42, 65 }, { 30, 42, 73 }, { 30, 44, 69 }, { 30, 44, 73 }, + { 30, 65, 69 }, { 30, 65, 73 }, { 30, 69, 73 }, { 31, 32, 43 }, + { 31, 32, 44 }, { 31, 32, 74 }, { 31, 41, 70 }, { 31, 41, 72 }, + { 31, 43, 70 }, { 31, 43, 74 }, { 31, 44, 72 }, { 31, 44, 74 }, + { 31, 70, 72 }, { 31, 70, 74 }, { 31, 72, 74 }, { 32, 42, 71 }, + { 32, 42, 73 }, { 32, 43, 71 }, { 32, 43, 74 }, { 32, 44, 73 }, + { 32, 44, 74 }, { 32, 71, 73 }, { 32, 71, 74 }, { 32, 73, 74 }, + { 33, 45, 46 }, { 33, 45, 47 }, { 33, 45, 75 }, { 33, 46, 50 }, + { 33, 46, 75 }, { 33, 47, 51 }, { 33, 47, 75 }, { 33, 50, 51 }, + { 33, 50, 75 }, { 33, 51, 75 }, { 34, 45, 48 }, { 34, 45, 49 }, + { 34, 45, 76 }, { 34, 48, 52 }, { 34, 48, 76 }, { 34, 49, 53 }, + { 34, 49, 76 }, { 34, 52, 53 }, { 34, 52, 76 }, { 34, 53, 76 }, + { 35, 46, 48 }, { 35, 46, 54 }, { 35, 46, 77 }, { 35, 48, 56 }, + { 35, 48, 77 }, { 35, 54, 59 }, { 35, 54, 77 }, { 35, 56, 59 }, + { 35, 56, 77 }, { 35, 59, 77 }, { 36, 47, 49 }, { 36, 47, 55 }, + { 36, 47, 78 }, { 36, 49, 57 }, { 36, 49, 78 }, { 36, 55, 60 }, + { 36, 55, 78 }, { 36, 57, 60 }, { 36, 57, 78 }, { 36, 60, 78 }, + { 37, 50, 54 }, { 37, 50, 58 }, { 37, 50, 79 }, { 37, 54, 62 }, + { 37, 54, 79 }, { 37, 58, 66 }, { 37, 58, 79 }, { 37, 62, 66 }, + { 37, 62, 79 }, { 37, 66, 79 }, { 38, 51, 55 }, { 38, 51, 58 }, + { 38, 51, 80 }, { 38, 55, 63 }, { 38, 55, 80 }, { 38, 58, 67 }, + { 38, 58, 80 }, { 38, 63, 67 }, { 38, 63, 80 }, { 38, 67, 80 }, + { 39, 52, 56 }, { 39, 52, 61 }, { 39, 52, 81 }, { 39, 56, 64 }, + { 39, 56, 81 }, { 39, 61, 68 }, { 39, 61, 81 }, { 39, 64, 68 }, + { 39, 64, 81 }, { 39, 68, 81 }, { 40, 53, 57 }, { 40, 53, 61 }, + { 40, 53, 82 }, { 40, 57, 65 }, { 40, 57, 82 }, { 40, 61, 69 }, + { 40, 61, 82 }, { 40, 65, 69 }, { 40, 65, 82 }, { 40, 69, 82 }, + { 41, 59, 62 }, { 41, 59, 64 }, { 41, 59, 83 }, { 41, 62, 70 }, + { 41, 62, 83 }, { 41, 64, 72 }, { 41, 64, 83 }, { 41, 70, 72 }, + { 41, 70, 83 }, { 41, 72, 83 }, { 42, 60, 63 }, { 42, 60, 65 }, + { 42, 60, 84 }, { 42, 63, 71 }, { 42, 63, 84 }, { 42, 65, 73 }, + { 42, 65, 84 }, { 42, 71, 73 }, { 42, 71, 84 }, { 42, 73, 84 }, + { 43, 66, 67 }, { 43, 66, 70 }, { 43, 66, 85 }, { 43, 67, 71 }, + { 43, 67, 85 }, { 43, 70, 74 }, { 43, 70, 85 }, { 43, 71, 74 }, + { 43, 71, 85 }, { 43, 74, 85 }, { 44, 68, 69 }, { 44, 68, 72 }, + { 44, 68, 86 }, { 44, 69, 73 }, { 44, 69, 86 }, { 44, 72, 74 }, + { 44, 72, 86 }, { 44, 73, 74 }, { 44, 73, 86 }, { 44, 74, 86 }, + { 45, 46, 48 }, { 45, 46, 75 }, { 45, 46, 87 }, { 45, 47, 49 }, + { 45, 47, 75 }, { 45, 47, 88 }, { 45, 48, 76 }, { 45, 48, 87 }, + { 45, 49, 76 }, { 45, 49, 88 }, { 45, 75, 87 }, { 45, 75, 88 }, + { 45, 76, 87 }, { 45, 76, 88 }, { 45, 87, 88 }, { 46, 48, 77 }, + { 46, 48, 87 }, { 46, 50, 54 }, { 46, 50, 75 }, { 46, 50, 89 }, + { 46, 54, 77 }, { 46, 54, 89 }, { 46, 75, 87 }, { 46, 75, 89 }, + { 46, 77, 87 }, { 46, 77, 89 }, { 46, 87, 89 }, { 47, 49, 78 }, + { 47, 49, 88 }, { 47, 51, 55 }, { 47, 51, 75 }, { 47, 51, 90 }, + { 47, 55, 78 }, { 47, 55, 90 }, { 47, 75, 88 }, { 47, 75, 90 }, + { 47, 78, 88 }, { 47, 78, 90 }, { 47, 88, 90 }, { 48, 52, 56 }, + { 48, 52, 76 }, { 48, 52, 91 }, { 48, 56, 77 }, { 48, 56, 91 }, + { 48, 76, 87 }, { 48, 76, 91 }, { 48, 77, 87 }, { 48, 77, 91 }, + { 48, 87, 91 }, { 49, 53, 57 }, { 49, 53, 76 }, { 49, 53, 92 }, + { 49, 57, 78 }, { 49, 57, 92 }, { 49, 76, 88 }, { 49, 76, 92 }, + { 49, 78, 88 }, { 49, 78, 92 }, { 49, 88, 92 }, { 50, 51, 58 }, + { 50, 51, 75 }, { 50, 51, 93 }, { 50, 54, 79 }, { 50, 54, 89 }, + { 50, 58, 79 }, { 50, 58, 93 }, { 50, 75, 89 }, { 50, 75, 93 }, + { 50, 79, 89 }, { 50, 79, 93 }, { 50, 89, 93 }, { 51, 55, 80 }, + { 51, 55, 90 }, { 51, 58, 80 }, { 51, 58, 93 }, { 51, 75, 90 }, + { 51, 75, 93 }, { 51, 80, 90 }, { 51, 80, 93 }, { 51, 90, 93 }, + { 52, 53, 61 }, { 52, 53, 76 }, { 52, 53, 94 }, { 52, 56, 81 }, + { 52, 56, 91 }, { 52, 61, 81 }, { 52, 61, 94 }, { 52, 76, 91 }, + { 52, 76, 94 }, { 52, 81, 91 }, { 52, 81, 94 }, { 52, 91, 94 }, + { 53, 57, 82 }, { 53, 57, 92 }, { 53, 61, 82 }, { 53, 61, 94 }, + { 53, 76, 92 }, { 53, 76, 94 }, { 53, 82, 92 }, { 53, 82, 94 }, + { 53, 92, 94 }, { 54, 59, 62 }, { 54, 59, 77 }, { 54, 59, 95 }, + { 54, 62, 79 }, { 54, 62, 95 }, { 54, 77, 89 }, { 54, 77, 95 }, + { 54, 79, 89 }, { 54, 79, 95 }, { 54, 89, 95 }, { 55, 60, 63 }, + { 55, 60, 78 }, { 55, 60, 96 }, { 55, 63, 80 }, { 55, 63, 96 }, + { 55, 78, 90 }, { 55, 78, 96 }, { 55, 80, 90 }, { 55, 80, 96 }, + { 55, 90, 96 }, { 56, 59, 64 }, { 56, 59, 77 }, { 56, 59, 97 }, + { 56, 64, 81 }, { 56, 64, 97 }, { 56, 77, 91 }, { 56, 77, 97 }, + { 56, 81, 91 }, { 56, 81, 97 }, { 56, 91, 97 }, { 57, 60, 65 }, + { 57, 60, 78 }, { 57, 60, 98 }, { 57, 65, 82 }, { 57, 65, 98 }, + { 57, 78, 92 }, { 57, 78, 98 }, { 57, 82, 92 }, { 57, 82, 98 }, + { 57, 92, 98 }, { 58, 66, 67 }, { 58, 66, 79 }, { 58, 66, 99 }, + { 58, 67, 80 }, { 58, 67, 99 }, { 58, 79, 93 }, { 58, 79, 99 }, + { 58, 80, 93 }, { 58, 80, 99 }, { 58, 93, 99 }, { 59, 62, 83 }, + { 59, 62, 95 }, { 59, 64, 83 }, { 59, 64, 97 }, { 59, 77, 95 }, + { 59, 77, 97 }, { 59, 83, 95 }, { 59, 83, 97 }, { 59, 95, 97 }, + { 60, 63, 84 }, { 60, 63, 96 }, { 60, 65, 84 }, { 60, 65, 98 }, + { 60, 78, 96 }, { 60, 78, 98 }, { 60, 84, 96 }, { 60, 84, 98 }, + { 60, 96, 98 }, { 61, 68, 69 }, { 61, 68, 81 }, { 61, 68, 100 }, + { 61, 69, 82 }, { 61, 69, 100 }, { 61, 81, 94 }, { 61, 81, 100 }, + { 61, 82, 94 }, { 61, 82, 100 }, { 61, 94, 100 }, { 62, 66, 70 }, + { 62, 66, 79 }, { 62, 66, 101 }, { 62, 70, 83 }, { 62, 70, 101 }, + { 62, 79, 95 }, { 62, 79, 101 }, { 62, 83, 95 }, { 62, 83, 101 }, + { 62, 95, 101 }, { 63, 67, 71 }, { 63, 67, 80 }, { 63, 67, 102 }, + { 63, 71, 84 }, { 63, 71, 102 }, { 63, 80, 96 }, { 63, 80, 102 }, + { 63, 84, 96 }, { 63, 84, 102 }, { 63, 96, 102 }, { 64, 68, 72 }, + { 64, 68, 81 }, { 64, 68, 103 }, { 64, 72, 83 }, { 64, 72, 103 }, + { 64, 81, 97 }, { 64, 81, 103 }, { 64, 83, 97 }, { 64, 83, 103 }, + { 64, 97, 103 }, { 65, 69, 73 }, { 65, 69, 82 }, { 65, 69, 104 }, + { 65, 73, 84 }, { 65, 73, 104 }, { 65, 82, 98 }, { 65, 82, 104 }, + { 65, 84, 98 }, { 65, 84, 104 }, { 65, 98, 104 }, { 66, 67, 85 }, + { 66, 67, 99 }, { 66, 70, 85 }, { 66, 70, 101 }, { 66, 79, 99 }, + { 66, 79, 101 }, { 66, 85, 99 }, { 66, 85, 101 }, { 66, 99, 101 }, + { 67, 71, 85 }, { 67, 71, 102 }, { 67, 80, 99 }, { 67, 80, 102 }, + { 67, 85, 99 }, { 67, 85, 102 }, { 67, 99, 102 }, { 68, 69, 86 }, + { 68, 69, 100 }, { 68, 72, 86 }, { 68, 72, 103 }, { 68, 81, 100 }, + { 68, 81, 103 }, { 68, 86, 100 }, { 68, 86, 103 }, { 68, 100, 103 }, + { 69, 73, 86 }, { 69, 73, 104 }, { 69, 82, 100 }, { 69, 82, 104 }, + { 69, 86, 100 }, { 69, 86, 104 }, { 69, 100, 104 }, { 70, 72, 74 }, + { 70, 72, 83 }, { 70, 72, 105 }, { 70, 74, 85 }, { 70, 74, 105 }, + { 70, 83, 101 }, { 70, 83, 105 }, { 70, 85, 101 }, { 70, 85, 105 }, + { 70, 101, 105 }, { 71, 73, 74 }, { 71, 73, 84 }, { 71, 73, 106 }, + { 71, 74, 85 }, { 71, 74, 106 }, { 71, 84, 102 }, { 71, 84, 106 }, + { 71, 85, 102 }, { 71, 85, 106 }, { 71, 102, 106 }, { 72, 74, 86 }, + { 72, 74, 105 }, { 72, 83, 103 }, { 72, 83, 105 }, { 72, 86, 103 }, + { 72, 86, 105 }, { 72, 103, 105 }, { 73, 74, 86 }, { 73, 74, 106 }, + { 73, 84, 104 }, { 73, 84, 106 }, { 73, 86, 104 }, { 73, 86, 106 }, + { 73, 104, 106 }, { 74, 85, 105 }, { 74, 85, 106 }, { 74, 86, 105 }, + { 74, 86, 106 }, { 74, 105, 106 }, { 75, 87, 88 }, { 75, 87, 89 }, + { 75, 87, 107 }, { 75, 88, 90 }, { 75, 88, 107 }, { 75, 89, 93 }, + { 75, 89, 107 }, { 75, 90, 93 }, { 75, 90, 107 }, { 75, 93, 107 }, + { 76, 87, 88 }, { 76, 87, 91 }, { 76, 87, 108 }, { 76, 88, 92 }, + { 76, 88, 108 }, { 76, 91, 94 }, { 76, 91, 108 }, { 76, 92, 94 }, + { 76, 92, 108 }, { 76, 94, 108 }, { 77, 87, 89 }, { 77, 87, 91 }, + { 77, 87, 109 }, { 77, 89, 95 }, { 77, 89, 109 }, { 77, 91, 97 }, + { 77, 91, 109 }, { 77, 95, 97 }, { 77, 95, 109 }, { 77, 97, 109 }, + { 78, 88, 90 }, { 78, 88, 92 }, { 78, 88, 110 }, { 78, 90, 96 }, + { 78, 90, 110 }, { 78, 92, 98 }, { 78, 92, 110 }, { 78, 96, 98 }, + { 78, 96, 110 }, { 78, 98, 110 }, { 79, 89, 93 }, { 79, 89, 95 }, + { 79, 89, 111 }, { 79, 93, 99 }, { 79, 93, 111 }, { 79, 95, 101 }, + { 79, 95, 111 }, { 79, 99, 101 }, { 79, 99, 111 }, { 79, 101, 111 }, + { 80, 90, 93 }, { 80, 90, 96 }, { 80, 90, 112 }, { 80, 93, 99 }, + { 80, 93, 112 }, { 80, 96, 102 }, { 80, 96, 112 }, { 80, 99, 102 }, + { 80, 99, 112 }, { 80, 102, 112 }, { 81, 91, 94 }, { 81, 91, 97 }, + { 81, 91, 113 }, { 81, 94, 100 }, { 81, 94, 113 }, { 81, 97, 103 }, + { 81, 97, 113 }, { 81, 100, 103 }, { 81, 100, 113 }, { 81, 103, 113 }, + { 82, 92, 94 }, { 82, 92, 98 }, { 82, 92, 114 }, { 82, 94, 100 }, + { 82, 94, 114 }, { 82, 98, 104 }, { 82, 98, 114 }, { 82, 100, 104 }, + { 82, 100, 114 }, { 82, 104, 114 }, { 83, 95, 97 }, { 83, 95, 101 }, + { 83, 95, 115 }, { 83, 97, 103 }, { 83, 97, 115 }, { 83, 101, 105 }, + { 83, 101, 115 }, { 83, 103, 105 }, { 83, 103, 115 }, { 83, 105, 115 }, + { 84, 96, 98 }, { 84, 96, 102 }, { 84, 96, 116 }, { 84, 98, 104 }, + { 84, 98, 116 }, { 84, 102, 106 }, { 84, 102, 116 }, { 84, 104, 106 }, + { 84, 104, 116 }, { 84, 106, 116 }, { 85, 99, 101 }, { 85, 99, 102 }, + { 85, 99, 117 }, { 85, 101, 105 }, { 85, 101, 117 }, { 85, 102, 106 }, + { 85, 102, 117 }, { 85, 105, 106 }, { 85, 105, 117 }, { 85, 106, 117 }, + { 86, 100, 103 }, { 86, 100, 104 }, { 86, 100, 118 }, { 86, 103, 105 }, + { 86, 103, 118 }, { 86, 104, 106 }, { 86, 104, 118 }, { 86, 105, 106 }, + { 86, 105, 118 }, { 86, 106, 118 }, { 87, 88, 107 }, { 87, 88, 108 }, + { 87, 89, 107 }, { 87, 89, 109 }, { 87, 91, 108 }, { 87, 91, 109 }, + { 87, 107, 108 }, { 87, 107, 109 }, { 87, 108, 109 }, { 88, 90, 107 }, + { 88, 90, 110 }, { 88, 92, 108 }, { 88, 92, 110 }, { 88, 107, 108 }, + { 88, 107, 110 }, { 88, 108, 110 }, { 89, 93, 107 }, { 89, 93, 111 }, + { 89, 95, 109 }, { 89, 95, 111 }, { 89, 107, 109 }, { 89, 107, 111 }, + { 89, 109, 111 }, { 90, 93, 107 }, { 90, 93, 112 }, { 90, 96, 110 }, + { 90, 96, 112 }, { 90, 107, 110 }, { 90, 107, 112 }, { 90, 110, 112 }, + { 91, 94, 108 }, { 91, 94, 113 }, { 91, 97, 109 }, { 91, 97, 113 }, + { 91, 108, 109 }, { 91, 108, 113 }, { 91, 109, 113 }, { 92, 94, 108 }, + { 92, 94, 114 }, { 92, 98, 110 }, { 92, 98, 114 }, { 92, 108, 110 }, + { 92, 108, 114 }, { 92, 110, 114 }, { 93, 99, 111 }, { 93, 99, 112 }, + { 93, 107, 111 }, { 93, 107, 112 }, { 93, 111, 112 }, { 94, 100, 113 }, + { 94, 100, 114 }, { 94, 108, 113 }, { 94, 108, 114 }, { 94, 113, 114 }, + { 95, 97, 109 }, { 95, 97, 115 }, { 95, 101, 111 }, { 95, 101, 115 }, + { 95, 109, 111 }, { 95, 109, 115 }, { 95, 111, 115 }, { 96, 98, 110 }, + { 96, 98, 116 }, { 96, 102, 112 }, { 96, 102, 116 }, { 96, 110, 112 }, + { 96, 110, 116 }, { 96, 112, 116 }, { 97, 103, 113 }, { 97, 103, 115 }, + { 97, 109, 113 }, { 97, 109, 115 }, { 97, 113, 115 }, { 98, 104, 114 }, + { 98, 104, 116 }, { 98, 110, 114 }, { 98, 110, 116 }, { 98, 114, 116 }, + { 99, 101, 111 }, { 99, 101, 117 }, { 99, 102, 112 }, { 99, 102, 117 }, + { 99, 111, 112 }, { 99, 111, 117 }, { 99, 112, 117 }, { 100, 103, 113 }, + { 100, 103, 118 }, { 100, 104, 114 }, { 100, 104, 118 }, { 100, 113, 114 }, + { 100, 113, 118 }, { 100, 114, 118 }, { 101, 105, 115 }, { 101, 105, 117 }, + { 101, 111, 115 }, { 101, 111, 117 }, { 101, 115, 117 }, { 102, 106, 116 }, + { 102, 106, 117 }, { 102, 112, 116 }, { 102, 112, 117 }, { 102, 116, 117 }, + { 103, 105, 115 }, { 103, 105, 118 }, { 103, 113, 115 }, { 103, 113, 118 }, + { 103, 115, 118 }, { 104, 106, 116 }, { 104, 106, 118 }, { 104, 114, 116 }, + { 104, 114, 118 }, { 104, 116, 118 }, { 105, 106, 117 }, { 105, 106, 118 }, + { 105, 115, 117 }, { 105, 115, 118 }, { 105, 117, 118 }, { 106, 116, 117 }, + { 106, 116, 118 }, { 106, 117, 118 }, { 107, 108, 109 }, { 107, 108, 110 }, + { 107, 108, 119 }, { 107, 109, 111 }, { 107, 109, 119 }, { 107, 110, 112 }, + { 107, 110, 119 }, { 107, 111, 112 }, { 107, 111, 119 }, { 107, 112, 119 }, + { 108, 109, 113 }, { 108, 109, 119 }, { 108, 110, 114 }, { 108, 110, 119 }, + { 108, 113, 114 }, { 108, 113, 119 }, { 108, 114, 119 }, { 109, 111, 115 }, + { 109, 111, 119 }, { 109, 113, 115 }, { 109, 113, 119 }, { 109, 115, 119 }, + { 110, 112, 116 }, { 110, 112, 119 }, { 110, 114, 116 }, { 110, 114, 119 }, + { 110, 116, 119 }, { 111, 112, 117 }, { 111, 112, 119 }, { 111, 115, 117 }, + { 111, 115, 119 }, { 111, 117, 119 }, { 112, 116, 117 }, { 112, 116, 119 }, + { 112, 117, 119 }, { 113, 114, 118 }, { 113, 114, 119 }, { 113, 115, 118 }, + { 113, 115, 119 }, { 113, 118, 119 }, { 114, 116, 118 }, { 114, 116, 119 }, + { 114, 118, 119 }, { 115, 117, 118 }, { 115, 117, 119 }, { 115, 118, 119 }, + { 116, 117, 118 }, { 116, 117, 119 }, { 116, 118, 119 }, { 117, 118, 119 } +}; + + + +/* Add a rotation around the wx-plane to the matrix m. */ +static void rotatewx(float m[4][4], float phi) +{ + float c, s, u, v; + int i; + + phi *= M_PI/180.0; + c = cos(phi); + s = sin(phi); + for (i=0; i<4; i++) + { + u = m[i][1]; + v = m[i][2]; + m[i][1] = c*u+s*v; + m[i][2] = -s*u+c*v; + } +} + + +/* Add a rotation around the wy-plane to the matrix m. */ +static void rotatewy(float m[4][4], float phi) +{ + float c, s, u, v; + int i; + + phi *= M_PI/180.0; + c = cos(phi); + s = sin(phi); + for (i=0; i<4; i++) + { + u = m[i][0]; + v = m[i][2]; + m[i][0] = c*u-s*v; + m[i][2] = s*u+c*v; + } +} + + +/* Add a rotation around the wz-plane to the matrix m. */ +static void rotatewz(float m[4][4], float phi) +{ + float c, s, u, v; + int i; + + phi *= M_PI/180.0; + c = cos(phi); + s = sin(phi); + for (i=0; i<4; i++) + { + u = m[i][0]; + v = m[i][1]; + m[i][0] = c*u+s*v; + m[i][1] = -s*u+c*v; + } +} + + +/* Add a rotation around the xy-plane to the matrix m. */ +static void rotatexy(float m[4][4], float phi) +{ + float c, s, u, v; + int i; + + phi *= M_PI/180.0; + c = cos(phi); + s = sin(phi); + for (i=0; i<4; i++) + { + u = m[i][2]; + v = m[i][3]; + m[i][2] = c*u+s*v; + m[i][3] = -s*u+c*v; + } +} + + +/* Add a rotation around the xz-plane to the matrix m. */ +static void rotatexz(float m[4][4], float phi) +{ + float c, s, u, v; + int i; + + phi *= M_PI/180.0; + c = cos(phi); + s = sin(phi); + for (i=0; i<4; i++) + { + u = m[i][1]; + v = m[i][3]; + m[i][1] = c*u-s*v; + m[i][3] = s*u+c*v; + } +} + + +/* Add a rotation around the yz-plane to the matrix m. */ +static void rotateyz(float m[4][4], float phi) +{ + float c, s, u, v; + int i; + + phi *= M_PI/180.0; + c = cos(phi); + s = sin(phi); + for (i=0; i<4; i++) + { + u = m[i][0]; + v = m[i][3]; + m[i][0] = c*u-s*v; + m[i][3] = s*u+c*v; + } +} + + +/* Compute the rotation matrix m from the rotation angles. */ +static void rotateall(float al, float be, float de, float ze, float et, + float th, float m[4][4]) +{ + int i, j; + + for (i=0; i<4; i++) + for (j=0; j<4; j++) + m[i][j] = (i==j); + rotatewx(m,al); + rotatewy(m,be); + rotatewz(m,de); + rotatexz(m,et); + rotatexy(m,ze); + rotateyz(m,th); +} + + +/* Multiply two rotation matrices: o=m*n. */ +static void mult_rotmat(float m[4][4], float n[4][4], float o[4][4]) +{ + int i, j, k; + + for (i=0; i<4; i++) + { + for (j=0; j<4; j++) + { + o[i][j] = 0.0; + for (k=0; k<4; k++) + o[i][j] += m[i][k]*n[k][j]; + } + } +} + + +/* Compute a 4D rotation matrix from two unit quaternions. */ +static void quats_to_rotmat(float p[4], float q[4], float m[4][4]) +{ + double al, be, de, ze, et, th; + double r00, r01, r02, r12, r22; + + r00 = 1.0-2.0*(p[1]*p[1]+p[2]*p[2]); + r01 = 2.0*(p[0]*p[1]+p[2]*p[3]); + r02 = 2.0*(p[2]*p[0]-p[1]*p[3]); + r12 = 2.0*(p[1]*p[2]+p[0]*p[3]); + r22 = 1.0-2.0*(p[1]*p[1]+p[0]*p[0]); + + al = atan2(-r12,r22)*180.0/M_PI; + be = atan2(r02,sqrt(r00*r00+r01*r01))*180.0/M_PI; + de = atan2(-r01,r00)*180.0/M_PI; + + r00 = 1.0-2.0*(q[1]*q[1]+q[2]*q[2]); + r01 = 2.0*(q[0]*q[1]+q[2]*q[3]); + r02 = 2.0*(q[2]*q[0]-q[1]*q[3]); + r12 = 2.0*(q[1]*q[2]+q[0]*q[3]); + r22 = 1.0-2.0*(q[1]*q[1]+q[0]*q[0]); + + et = atan2(-r12,r22)*180.0/M_PI; + th = atan2(r02,sqrt(r00*r00+r01*r01))*180.0/M_PI; + ze = atan2(-r01,r00)*180.0/M_PI; + + rotateall(al,be,de,ze,et,-th,m); +} + + +/* Compute the normal vector of a plane based on three points in the plane. */ +static void normal(const float *p, const float *q, const float *r, + float *n) +{ + float u[3], v[3], t; + + u[0] = q[0]-p[0]; + u[1] = q[1]-p[1]; + u[2] = q[2]-p[2]; + v[0] = r[0]-p[0]; + v[1] = r[1]-p[1]; + v[2] = r[2]-p[2]; + n[0] = u[1]*v[2]-u[2]*v[1]; + n[1] = u[2]*v[0]-u[0]*v[2]; + n[2] = u[0]*v[1]-u[1]*v[0]; + t = sqrt(n[0]*n[0]+n[1]*n[1]+n[2]*n[2]); + n[0] /= t; + n[1] /= t; + n[2] /= t; +} + + +/* Project an array of vertices from 4d to 3d. */ +static void project(ModeInfo *mi, const float vert[][4], float v[][4], int num) +{ + float s, q1[4], q2[4], r1[4][4], r2[4][4], m[4][4]; + int i, j, k; + polytopesstruct *pp = &poly[MI_SCREEN(mi)]; + + rotateall(pp->alpha,pp->beta,pp->delta,pp->zeta,pp->eta,pp->theta,r1); + + gltrackball_get_quaternion(pp->trackballs[0],q1); + gltrackball_get_quaternion(pp->trackballs[1],q2); + quats_to_rotmat(q1,q2,r2); + + mult_rotmat(r2,r1,m); + + /* Project the vertices from 4d to 3d. */ + for (i=0; ipolygon_count = 0; + if (display_mode == DISP_WIREFRAME) + { + if (color_mode == COLORS_SINGLE) + glColor4fv(red); + glBegin(GL_LINES); + for (i=0; ipolygon_count = num_edge; + } + else + { + if (color_mode == COLORS_SINGLE) + { + red_trans[3] = face_color_trans[0][3]/2.0; + if (display_mode == DISP_TRANSPARENT) + glMaterialfv(GL_FRONT_AND_BACK,GL_AMBIENT_AND_DIFFUSE,red_trans); + else + glMaterialfv(GL_FRONT_AND_BACK,GL_AMBIENT_AND_DIFFUSE,red); + } + for (i=0; ipolygon_count = num_face; + } +} + + +/* Draw a 5-cell {3,3,3} projected into 3d. */ +static void cell_5(ModeInfo *mi) +{ + polytopesstruct *hp = &poly[MI_SCREEN(mi)]; + float v[NUM_VERT_5][4]; + + project(mi,vert_5,v,NUM_VERT_5); + draw(mi,v,edge_5,NUM_EDGE_5,(int *)face_5,NUM_FACE_5, + VERT_PER_FACE_5,hp->edge_color_5,hp->face_color_5, + hp->face_color_trans_5); +} + + +/* Draw a 8-cell {4,3,3} projected into 3d. */ +static void cell_8(ModeInfo *mi) +{ + polytopesstruct *hp = &poly[MI_SCREEN(mi)]; + float v[NUM_VERT_8][4]; + + project(mi,vert_8,v,NUM_VERT_8); + draw(mi,v,edge_8,NUM_EDGE_8,(int *)face_8,NUM_FACE_8, + VERT_PER_FACE_8,hp->edge_color_8,hp->face_color_8, + hp->face_color_trans_8); +} + + +/* Draw a 16-cell {3,3,4} projected into 3d. */ +static void cell_16(ModeInfo *mi) +{ + polytopesstruct *hp = &poly[MI_SCREEN(mi)]; + float v[NUM_VERT_16][4]; + + project(mi,vert_16,v,NUM_VERT_16); + draw(mi,v,edge_16,NUM_EDGE_16,(int *)face_16,NUM_FACE_16, + VERT_PER_FACE_16,hp->edge_color_16,hp->face_color_16, + hp->face_color_trans_16); +} + + +/* Draw a 24-cell {3,4,3} projected into 3d. */ +static void cell_24(ModeInfo *mi) +{ + polytopesstruct *hp = &poly[MI_SCREEN(mi)]; + float v[NUM_VERT_24][4]; + + project(mi,vert_24,v,NUM_VERT_24); + draw(mi,v,edge_24,NUM_EDGE_24,(int *)face_24,NUM_FACE_24, + VERT_PER_FACE_24,hp->edge_color_24,hp->face_color_24, + hp->face_color_trans_24); +} + + +/* Draw a 120-cell {5,3,3} projected into 3d. */ +static void cell_120(ModeInfo *mi) +{ + polytopesstruct *hp = &poly[MI_SCREEN(mi)]; + float v[NUM_VERT_120][4]; + + project(mi,vert_120,v,NUM_VERT_120); + draw(mi,v,edge_120,NUM_EDGE_120,(int *)face_120,NUM_FACE_120, + VERT_PER_FACE_120,hp->edge_color_120,hp->face_color_120, + hp->face_color_trans_120); +} + + +/* Draw a 600-cell {3,3,5} projected into 3d. */ +static void cell_600(ModeInfo *mi) +{ + polytopesstruct *hp = &poly[MI_SCREEN(mi)]; + float v[NUM_VERT_600][4]; + + project(mi,vert_600,v,NUM_VERT_600); + draw(mi,v,edge_600,NUM_EDGE_600,(int *)face_600,NUM_FACE_600, + VERT_PER_FACE_600,hp->edge_color_600,hp->face_color_600, + hp->face_color_trans_600); +} + + +/* Compute a color based on the w-depth of a point. */ +static void color(float depth, float alpha, float min, float max, + float color[4]) +{ + double d, t; + int s; + + d = (depth-min)/(max-min); + s = floor(d*4.0); + t = d*4.0-s; + if (s < 0) + s += 6; + if (s >= 6) + s -= 6; + switch (s) + { + case 0: + color[0] = 1.0; + color[1] = t; + color[2] = 0.0; + break; + case 1: + color[0] = 1.0-t; + color[1] = 1.0; + color[2] = 0.0; + break; + case 2: + color[0] = 0.0; + color[1] = 1.0; + color[2] = t; + break; + case 3: + color[0] = 0.0; + color[1] = 1.0-t; + color[2] = 1.0; + break; + case 4: + color[0] = t; + color[1] = 0.0; + color[2] = 1.0; + break; + case 5: + color[0] = 1.0; + color[1] = 0.0; + color[2] = 1.0-t; + break; + } + color[3] = alpha; +} + + +/* Set the colors of a single polytope's edges and faces. */ +static void colors(const float vert[][4], + const int edge[][2], int num_edge, + const int face[], int num_face, + int vert_per_face, + float edge_color[][4], + float face_color[][4], + float face_color_trans[][4], + float alpha, + float min_edge_depth, float max_edge_depth, + float min_face_depth, float max_face_depth) +{ + int i, j; + float depth; + + for (i=0; iedge_color_5,hp->face_color_5, + hp->face_color_trans_5,0.5,MIN_EDGE_DEPTH_5, + MAX_EDGE_DEPTH_5,MIN_FACE_DEPTH_5,MAX_FACE_DEPTH_5); + + /* 8-cell. */ + colors(vert_8,edge_8,NUM_EDGE_8,(int *)face_8,NUM_FACE_8, + VERT_PER_FACE_8,hp->edge_color_8,hp->face_color_8, + hp->face_color_trans_8,0.4,MIN_EDGE_DEPTH_8, + MAX_EDGE_DEPTH_8,MIN_FACE_DEPTH_8,MAX_FACE_DEPTH_8); + + /* 16-cell. */ + colors(vert_16,edge_16,NUM_EDGE_16,(int *)face_16,NUM_FACE_16, + VERT_PER_FACE_16,hp->edge_color_16,hp->face_color_16, + hp->face_color_trans_16,0.25,MIN_EDGE_DEPTH_16, + MAX_EDGE_DEPTH_16,MIN_FACE_DEPTH_16,MAX_FACE_DEPTH_16); + + /* 24-cell. */ + colors(vert_24,edge_24,NUM_EDGE_24,(int *)face_24,NUM_FACE_24, + VERT_PER_FACE_24,hp->edge_color_24,hp->face_color_24, + hp->face_color_trans_24,0.25,MIN_EDGE_DEPTH_24, + MAX_EDGE_DEPTH_24,MIN_FACE_DEPTH_24,MAX_FACE_DEPTH_24); + + /* 120-cell. */ + colors(vert_120,edge_120,NUM_EDGE_120,(int *)face_120,NUM_FACE_120, + VERT_PER_FACE_120,hp->edge_color_120,hp->face_color_120, + hp->face_color_trans_120,0.15,MIN_EDGE_DEPTH_120, + MAX_EDGE_DEPTH_120,MIN_FACE_DEPTH_120,MAX_FACE_DEPTH_120); + + /* 600-cell. */ + colors(vert_600,edge_600,NUM_EDGE_600,(int *)face_600,NUM_FACE_600, + VERT_PER_FACE_600,hp->edge_color_600,hp->face_color_600, + hp->face_color_trans_600,0.06,MIN_EDGE_DEPTH_600, + MAX_EDGE_DEPTH_600,MIN_FACE_DEPTH_600,MAX_FACE_DEPTH_600); +} + + +static void init(ModeInfo *mi) +{ + polytopesstruct *pp = &poly[MI_SCREEN(mi)]; + + set_colors(mi); + + pp->alpha = 0.0; + pp->beta = 0.0; + pp->delta = 0.0; + pp->zeta = 0.0; + pp->eta = 0.0; + pp->theta = 0.0; + + pp->tick = 0; + pp->poly = 0; +} + + +/* Redisplay the polytopes. */ +static void display_polytopes(ModeInfo *mi) +{ + polytopesstruct *pp = &poly[MI_SCREEN(mi)]; + + if (!pp->button_pressed) + { + pp->alpha += speed_wx * pp->speed_scale; + if (pp->alpha >= 360.0) + pp->alpha -= 360.0; + pp->beta += speed_wy * pp->speed_scale; + if (pp->beta >= 360.0) + pp->beta -= 360.0; + pp->delta += speed_wz * pp->speed_scale; + if (pp->delta >= 360.0) + pp->delta -= 360.0; + pp->zeta += speed_xy * pp->speed_scale; + if (pp->zeta >= 360.0) + pp->zeta -= 360.0; + pp->eta += speed_xz * pp->speed_scale; + if (pp->eta >= 360.0) + pp->eta -= 360.0; + pp->theta += speed_yz * pp->speed_scale; + if (pp->theta >= 360.0) + pp->theta -= 360.0; + } + + glMatrixMode(GL_PROJECTION); + glLoadIdentity(); + if (projection_3d == DISP_3D_ORTHOGRAPHIC) + { + if (pp->aspect >= 1.0) + glOrtho(-pp->aspect,pp->aspect,-1.0,1.0,0.1,100.0); + else + glOrtho(-1.0,1.0,-1.0/pp->aspect,1.0/pp->aspect,0.1,100.0); + } + else + { + gluPerspective(60.0,pp->aspect,0.1,100.0); + } + glMatrixMode(GL_MODELVIEW); + glLoadIdentity(); + + if (pp->tick == 0) + { + if (polytope == POLYTOPE_RANDOM) + pp->poly = random() % (POLYTOPE_LAST_CELL+1); + else + pp->poly = polytope; + } + if (++pp->tick > 1000) + pp->tick = 0; + + if (pp->poly == POLYTOPE_5_CELL) + cell_5(mi); + else if (pp->poly == POLYTOPE_8_CELL) + cell_8(mi); + else if (pp->poly == POLYTOPE_16_CELL) + cell_16(mi); + else if (pp->poly == POLYTOPE_24_CELL) + cell_24(mi); + else if (pp->poly == POLYTOPE_120_CELL) + cell_120(mi); + else if (pp->poly == POLYTOPE_600_CELL) + cell_600(mi); + else + abort(); +} + + +ENTRYPOINT void reshape_polytopes(ModeInfo *mi, int width, int height) +{ + polytopesstruct *pp = &poly[MI_SCREEN(mi)]; + + pp->WindW = (GLint)width; + pp->WindH = (GLint)height; + glViewport(0,0,width,height); + pp->aspect = (GLfloat)width/(GLfloat)height; +} + + +ENTRYPOINT Bool polytopes_handle_event(ModeInfo *mi, XEvent *event) +{ + polytopesstruct *pp = &poly[MI_SCREEN(mi)]; + KeySym sym = 0; + char c = 0; + + if (event->xany.type == KeyPress || event->xany.type == KeyRelease) + XLookupString (&event->xkey, &c, 1, &sym, 0); + + if (event->xany.type == ButtonPress && + event->xbutton.button == Button1) + { + pp->button_pressed = True; + gltrackball_start(pp->trackballs[pp->current_trackball], + event->xbutton.x, event->xbutton.y, + MI_WIDTH(mi), MI_HEIGHT(mi)); + return True; + } + else if (event->xany.type == ButtonRelease && + event->xbutton.button == Button1) + { + pp->button_pressed = False; + return True; + } + else if (event->xany.type == KeyPress) + { + if (sym == XK_Shift_L || sym == XK_Shift_R) + { + pp->current_trackball = 1; + if (pp->button_pressed) + gltrackball_start(pp->trackballs[pp->current_trackball], + event->xbutton.x, event->xbutton.y, + MI_WIDTH(mi), MI_HEIGHT(mi)); + return True; + } + } + else if (event->xany.type == KeyRelease) + { + if (sym == XK_Shift_L || sym == XK_Shift_R) + { + pp->current_trackball = 0; + if (pp->button_pressed) + gltrackball_start(pp->trackballs[pp->current_trackball], + event->xbutton.x, event->xbutton.y, + MI_WIDTH(mi), MI_HEIGHT(mi)); + return True; + } + } + else if (event->xany.type == MotionNotify && pp->button_pressed) + { + gltrackball_track(pp->trackballs[pp->current_trackball], + event->xmotion.x, event->xmotion.y, + MI_WIDTH(mi), MI_HEIGHT(mi)); + return True; + } + + return False; +} + + +/* + *----------------------------------------------------------------------------- + *----------------------------------------------------------------------------- + * Xlock hooks. + *----------------------------------------------------------------------------- + *----------------------------------------------------------------------------- + */ + +/* + *----------------------------------------------------------------------------- + * Initialize polytopes. Called each time the window changes. + *----------------------------------------------------------------------------- + */ + +ENTRYPOINT void init_polytopes(ModeInfo *mi) +{ + polytopesstruct *pp; + + if (poly == NULL) + { + poly = (polytopesstruct *)calloc(MI_NUM_SCREENS(mi), + sizeof(polytopesstruct)); + if (poly == NULL) + return; + } + pp = &poly[MI_SCREEN(mi)]; + + pp->trackballs[0] = gltrackball_init(); + pp->trackballs[1] = gltrackball_init(); + pp->current_trackball = 0; + pp->button_pressed = False; + + /* Set the display mode. */ + if (!strcasecmp(mode,"wireframe") || !strcasecmp(mode,"0")) + { + display_mode = DISP_WIREFRAME; + } + else if (!strcasecmp(mode,"surface") || !strcasecmp(mode,"1")) + { + display_mode = DISP_SURFACE; + } + else if (!strcasecmp(mode,"transparent") || !strcasecmp(mode,"2")) + { + display_mode = DISP_TRANSPARENT; + } + else + { + display_mode = DISP_TRANSPARENT; + } + + /* Set the Klein bottle. */ + if (!strcasecmp(poly_str,"random") || !strcasecmp(poly_str,"-1")) + { + polytope = POLYTOPE_RANDOM; + } + else if (!strcasecmp(poly_str,"5-cell") || !strcasecmp(poly_str,"0")) + { + polytope = POLYTOPE_5_CELL; + } + else if (!strcasecmp(poly_str,"8-cell") || !strcasecmp(poly_str,"1")) + { + polytope = POLYTOPE_8_CELL; + } + else if (!strcasecmp(poly_str,"16-cell") || !strcasecmp(poly_str,"2")) + { + polytope = POLYTOPE_16_CELL; + } + else if (!strcasecmp(poly_str,"24-cell") || !strcasecmp(poly_str,"3")) + { + polytope = POLYTOPE_24_CELL; + } + else if (!strcasecmp(poly_str,"120-cell") || !strcasecmp(poly_str,"4")) + { + polytope = POLYTOPE_120_CELL; + } + else if (!strcasecmp(poly_str,"600-cell") || !strcasecmp(poly_str,"5")) + { + polytope = POLYTOPE_600_CELL; + } + else + { + polytope = POLYTOPE_RANDOM; + } + + /* Set the color mode. */ + if (!strcasecmp(color_str,"single") || !strcasecmp(color_str,"0")) + { + color_mode = COLORS_SINGLE; + } + else if (!strcasecmp(color_str,"depth") || !strcasecmp(color_str,"1")) + { + color_mode = COLORS_DEPTH; + } + else + { + color_mode = COLORS_DEPTH; + } + + /* Set the 3d projection mode. */ + if (!strcasecmp(proj_3d,"perspective") || !strcasecmp(proj_3d,"0")) + { + projection_3d = DISP_3D_PERSPECTIVE; + } + else if (!strcasecmp(proj_3d,"orthographic") || !strcasecmp(proj_3d,"1")) + { + projection_3d = DISP_3D_ORTHOGRAPHIC; + } + else + { + projection_3d = DISP_3D_PERSPECTIVE; + } + + /* Set the 4d projection mode. */ + if (!strcasecmp(proj_4d,"perspective") || !strcasecmp(proj_4d,"0")) + { + projection_4d = DISP_4D_PERSPECTIVE; + } + else if (!strcasecmp(proj_4d,"orthographic") || !strcasecmp(proj_4d,"1")) + { + projection_4d = DISP_4D_ORTHOGRAPHIC; + } + else + { + projection_4d = DISP_4D_PERSPECTIVE; + } + + /* make multiple screens rotate at slightly different rates. */ + pp->speed_scale = 0.9 + frand(0.3); + + if ((pp->glx_context = init_GL(mi)) != NULL) + { + reshape_polytopes(mi,MI_WIDTH(mi),MI_HEIGHT(mi)); + glDrawBuffer(GL_BACK); + init(mi); + } + else + { + MI_CLEARWINDOW(mi); + } +} + +/* + *----------------------------------------------------------------------------- + * Called by the mainline code periodically to update the display. + *----------------------------------------------------------------------------- + */ +ENTRYPOINT void draw_polytopes(ModeInfo *mi) +{ + static const GLfloat light_ambient[] = { 0.0, 0.0, 0.0, 1.0 }; + static const GLfloat light_diffuse[] = { 1.0, 1.0, 1.0, 1.0 }; + static const GLfloat light_specular[] = { 0.0, 0.0, 0.0, 1.0 }; + static const GLfloat light_position[] = { 0.0, 0.0, 1.0, 0.0 }; + static const GLfloat mat_specular[] = { 1.0, 1.0, 1.0, 1.0 }; + + Display *display = MI_DISPLAY(mi); + Window window = MI_WINDOW(mi); + polytopesstruct *hp; + + if (poly == NULL) + return; + hp = &poly[MI_SCREEN(mi)]; + + MI_IS_DRAWN(mi) = True; + if (!hp->glx_context) + return; + + glXMakeCurrent(display,window,*(hp->glx_context)); + + + glMatrixMode(GL_PROJECTION); + glLoadIdentity(); + if (projection_3d == DISP_3D_PERSPECTIVE) + gluPerspective(60.0,1.0,0.1,100.0); + else + glOrtho(-1.0,1.0,-1.0,1.0,0.1,100.0);; + glMatrixMode(GL_MODELVIEW); + glLoadIdentity(); + + if (display_mode == DISP_WIREFRAME) + { + glDisable(GL_DEPTH_TEST); + glDisable(GL_LIGHTING); + glDisable(GL_LIGHT0); + glDisable(GL_BLEND); + } + else if (display_mode == DISP_SURFACE) + { + glEnable(GL_DEPTH_TEST); + glDepthFunc(GL_LESS); + glLightModeli(GL_LIGHT_MODEL_TWO_SIDE,GL_TRUE); + glEnable(GL_LIGHTING); + glEnable(GL_LIGHT0); + glLightfv(GL_LIGHT0,GL_AMBIENT,light_ambient); + glLightfv(GL_LIGHT0,GL_DIFFUSE,light_diffuse); + glLightfv(GL_LIGHT0,GL_SPECULAR,light_specular); + glLightfv(GL_LIGHT0,GL_POSITION,light_position); + glMaterialfv(GL_FRONT_AND_BACK,GL_SPECULAR,mat_specular); + glMaterialf(GL_FRONT_AND_BACK,GL_SHININESS,0.0); + glDepthMask(GL_TRUE); + glDisable(GL_BLEND); + } + else if (display_mode == DISP_TRANSPARENT) + { + glDisable(GL_DEPTH_TEST); + glLightModeli(GL_LIGHT_MODEL_TWO_SIDE,GL_TRUE); + glEnable(GL_LIGHTING); + glEnable(GL_LIGHT0); + glLightfv(GL_LIGHT0,GL_AMBIENT,light_ambient); + glLightfv(GL_LIGHT0,GL_DIFFUSE,light_diffuse); + glLightfv(GL_LIGHT0,GL_SPECULAR,light_specular); + glLightfv(GL_LIGHT0,GL_POSITION,light_position); + glMaterialfv(GL_FRONT_AND_BACK,GL_SPECULAR,mat_specular); + glMaterialf(GL_FRONT_AND_BACK,GL_SHININESS,0.0); + glDepthMask(GL_FALSE); + glEnable(GL_BLEND); + glBlendFunc(GL_SRC_ALPHA,GL_ONE); + } + else + { + glDisable(GL_DEPTH_TEST); + glDisable(GL_LIGHTING); + glDisable(GL_LIGHT0); + glDisable(GL_BLEND); + } + + + glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT); + glLoadIdentity(); + + display_polytopes(mi); + + if (MI_IS_FPS(mi)) + do_fps (mi); + + glFlush(); + + glXSwapBuffers(display,window); +} + + +/* + *----------------------------------------------------------------------------- + * The display is being taken away from us. Free up malloc'ed + * memory and X resources that we've alloc'ed. Only called + * once, we must zap everything for every screen. + *----------------------------------------------------------------------------- + */ + +ENTRYPOINT void release_polytopes(ModeInfo *mi) +{ + if (poly != NULL) + { + int screen; + + for (screen = 0; screen < MI_NUM_SCREENS(mi); screen++) + { + polytopesstruct *hp = &poly[screen]; + + if (hp->glx_context) + hp->glx_context = (GLXContext *)NULL; + } + (void) free((void *)poly); + poly = (polytopesstruct *)NULL; + } + FreeAllGL(mi); +} + +#ifndef STANDALONE +ENTRYPOINT void change_polytopes(ModeInfo *mi) +{ + polytopesstruct *hp = &poly[MI_SCREEN(mi)]; + + if (!hp->glx_context) + return; + + glXMakeCurrent(MI_DISPLAY(mi),MI_WINDOW(mi),*(hp->glx_context)); + init(mi); +} +#endif /* !STANDALONE */ + +XSCREENSAVER_MODULE ("Polytopes", polytopes) + +#endif /* USE_GL */ diff --git a/hacks/glx/polytopes.man b/hacks/glx/polytopes.man new file mode 100644 index 00000000..45fcb4a8 --- /dev/null +++ b/hacks/glx/polytopes.man @@ -0,0 +1,207 @@ +.TH XScreenSaver 1 "" "X Version 11" +.SH NAME +polytopes - Draws one of the six regular 4d polytopes rotating in 4d. +.SH SYNOPSIS +.B polytopes +[\-display \fIhost:display.screen\fP] +[\-install] +[\-visual \fIvisual\fP] +[\-window] +[\-root] +[\-delay \fIusecs\fP] +[\-fps] +[\-5-cell] +[\-8-cell] +[\-16-cell] +[\-24-cell] +[\-120-cell] +[\-600-cell] +[\-wireframe] +[\-surface] +[\-transparent] +[\-single-color] +[\-depth-colors] +[\-perspective-3d] +[\-orthographic-3d] +[\-perspective-4d] +[\-orthographic-4d] +[\-speed-wx \fIfloat\fP] +[\-speed-wy \fIfloat\fP] +[\-speed-wz \fIfloat\fP] +[\-speed-xy \fIfloat\fP] +[\-speed-xz \fIfloat\fP] +[\-speed-yz \fIfloat\fP] +.SH DESCRIPTION +The \fIpolytopes\fP program shows one of the six regular 4d polytopes +(5-cell, 8-cell, 16-cell, 24-cell, 120-cell, or 600-cell) rotating in +4d. The program projects the 4d polytope to 3d using either a +perspective or an orthographic projection. The projected 3d polytope +can then be projected to the screen either perspectively or +orthographically. There are three display modes for the polytope: +mesh (wireframe), solid, or transparent. Furthermore, the colors with +which the polytope is drawn can be set to either single color or to a +coloring according to the 4d "depth" (the w coordinate) of the +polytope in its unrotated position. In the first case, the polytope +is drawn in red. This coloring combined with transparency gives a +nice visual effect of the structure of the polytope. The second mode +draws the polytope with a fully saturated color wheel in which the +edges or faces are colored accoring to their average 4d "depth". This +mode is best combined with the wireframe mode, where it allows you to +see how different parts of the polytope are moved to the "inside" of +the projected polytope in 3d. Of course, in 4d the cells, faces, and +edges of the polytope all have the same distance from the center of +the polytope. Only the projection creates the appearance that some of +the cells lie "inside" the figure in 3d. +.SH OPTIONS +.I polytopes +accepts the following options: +.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 \-install +Install a private colormap for the window. +.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 \-delay \fImicroseconds\fP +How much of a delay should be introduced between steps of the +animation. Default 25000, or 1/40th second. +.PP +The following six options are mutually exclusive. They determine +which polytope is displayed. +.TP 8 +.B \-5-cell +Display the 5-cell. The 5-cell is the 4d analogon of a regular +tetrahedron in 3d. It has 5 regular tetrahedra as its cells, 10 +equilateral triangles as faces, 10 edges, and 5 vertices. +.TP 8 +.B \-8-cell +Display the 8-cell (a.k.a. hypercube or tessaract). The 8-cell is the +4d analogon of a cube in 3d. It has 8 cubes as its cells, 24 squares +as faces, 32 edges, and 16 vertices. +.TP 8 +.B \-16-cell +Display the 16-cell. The 16-cell is the 4d analogon of an octahedron +in 3d. It has 16 regular tetrahedra as its cells, 32 equilateral +triangles as faces, 24 edges, and 8 vertices. +.TP 8 +.B \-24-cell +Display the 24-cell. The 24-cell has no 3d analogon. It has 24 +regular octahedra as its cells, 96 equilateral triangles as faces, 96 +edges, and 24 vertices. +.TP 8 +.B \-120-cell +Display the 120-cell. The 120-cell has no 3d analogon. It has 120 +regular dodecahedra as its cells, 720 regular pentagons as faces, 1200 +edges, and 600 vertices. +.TP 8 +.B \-600-cell +Display the 600-cell. The 600-cell has no 3d analogon. It has 600 +regular tetrahedra as its cells, 1200 equilateral triangles as faces, +720 edges, and 120 vertices. +.PP +The following three options are mutually exclusive. They determine +how the polytope is displayed. +.TP 8 +.B \-wireframe +Display the polytope as a wireframe mesh. +.TP 8 +.B \-surface +Display the polytope as a solid object. +.TP 8 +.B \-transparent +Display the polytope as a transparent object (default). +.PP +The following two options are mutually exclusive. They determine how +to color the polytope. +.TP 8 +.B \-single-color +Display the polytope in red. +.TP 8 +.B \-depth-colors +Display the polytope with a fully saturated color wheel in which the +edges or faces are colored accoring to their average 4d "depth", i.e., +the w coordinate of the polytope in its unrotated position (default). +.PP +The following two options are mutually exclusive. They determine how +the polytope is projected from 3d to 2d (i.e., to the screen). +.TP 8 +.B \-perspective-3d +Project the polytope from 3d to 2d using a perspective projection +(default). +.TP 8 +.B \-orthographic-3d +Project the polytope from 3d to 2d using an orthographic projection. +.PP +The following two options are mutually exclusive. They determine how +the polytope is projected from 4d to 3d. +.TP 8 +.B \-perspective-4d +Project the polytope from 4d to 3d using a perspective projection +(default). +.TP 8 +.B \-orthographic-4d +Project the polytope from 4d to 3d using an orthographic projection. +.PP +The following six options determine the rotation speed of the polytope +around the six possible hyperplanes. The rotation speed is measured +in degrees per frame. The speeds should be set to relatively small +values, e.g., less than 4 in magnitude. +.TP 8 +.B \-speed-wx \fIfloat\fP +Rotation speed around the wx plane (default: 1.1). +.TP 8 +.B \-speed-wy \fIfloat\fP +Rotation speed around the wy plane (default: 1.3). +.TP 8 +.B \-speed-wz \fIfloat\fP +Rotation speed around the wz plane (default: 1.5). +.TP 8 +.B \-speed-xy \fIfloat\fP +Rotation speed around the xy plane (default: 1.7). +.TP 8 +.B \-speed-xz \fIfloat\fP +Rotation speed around the xz plane (default: 1.9). +.TP 8 +.B \-speed-yz \fIfloat\fP +Rotation speed around the yz plane (default: 2.1). +.SH INTERACTION +If you run this program in standalone mode you can rotate the polytope +by dragging the mouse while pressing the left mouse button. This +rotates the polytope in 3D, i.e., around the wx, wy, and wz planes. +If you press the shift key while dragging the mouse with the left +button pressed the polytope is rotated in 4D, i.e., around the xy, xz, +and yz planes. To examine the polytope at your leisure, it is best to +set all speeds to 0. Otherwise, the polytope will rotate while the +left mouse button is not pressed. +.B \-fps +Display the current frame rate, CPU load, and polygon count. +.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 2003-2005 by Carsten Steger. 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 +Carsten Steger , 28-sep-2005. diff --git a/hacks/glx/providence.c b/hacks/glx/providence.c new file mode 100644 index 00000000..d9b64841 --- /dev/null +++ b/hacks/glx/providence.c @@ -0,0 +1,820 @@ +/* + * Permission to use, copy, modify, and distribute this software and its + * documentation for any purpose and without fee is hereby granted, + * provided that the above copyright notice appear in all copies and that + * both that copyright notice and this permission notice appear in + * supporting documentation. + * + * This file is provided AS IS with no warranties of any kind. The author + * shall have no liability with respect to the infringement of copyrights, + * trade secrets or any patents by this file or any part thereof. In no + * event will the author be liable for any lost revenue or profits or + * other special, indirect and consequential damages. + * + * Copyright 2004 Blair Tennessy + */ + +#ifdef STANDALONE +#define DEFAULTS "*delay: 20000 \n" \ + "*showFPS: False \n" \ + "*wireframe: False \n" + +# define refresh_providence 0 +#include "xlockmore.h" +#else +#include "xlock.h" +#endif + +#include "gltrackball.h" + +#define DEF_SOLIDPROVIDENCE "False" +#define DEF_EYE "True" + +static int eye; + +static XrmOptionDescRec opts[] = { + {"-eye", ".providence.eye", XrmoptionNoArg, "on"}, + {"+eye", ".providence.eye", XrmoptionNoArg, "off"} +}; + +static argtype vars[] = { + {&eye, "eye", "Eye", DEF_EYE, t_Bool} +}; + +static OptionStruct desc[] = { + {"-/+eye", "turn on/off eye of providence"} +}; + +ENTRYPOINT ModeSpecOpt providence_opts = { + sizeof opts / sizeof opts[0], opts, + sizeof vars / sizeof vars[0], vars, desc +}; + +#ifdef USE_MODULES +ModStruct providence_description = { + "providence", "init_providence", "draw_providence", + "release_providence", "draw_providence", "change_providence", + (char *) NULL, &providence_opts, 1000, 1, 1, 1, 4, 1.0, "", + "draws pyramid with glory", 0, NULL +}; +#endif + +#define Scale4Window 0.3 +#define Scale4Iconic 0.4 + +#define sqr(A) ((A)*(A)) + +#ifndef Pi +#define Pi M_PI +#endif + +/* brick texture */ +#define checkImageWidth 64 +#define checkImageHeight 64 + +#define EYE_PARTICLE_COUNT 2000 + +#define LOOKUPSIZE 3600 +#define EYELENGTH 300 + +#define EPSILON 0.0001 +#define PARTICLE_COUNT 2000 +#define FPS 50 + + +typedef struct { + GLint WindH, WindW; + GLXContext *glx_context; + trackball_state *trackball; + Bool button_down_p; + GLfloat position0[4]; + GLubyte checkImage[checkImageWidth][checkImageHeight][3]; + GLuint bricktexture; + + int mono, wire; + double camera_velocity; + double camera_z; + + int pyramidlist; + double currenttime; + double theta; + double theta_scale; + + double particles[PARTICLE_COUNT][5]; + int eyeparticles[EYE_PARTICLE_COUNT][2]; + double lookup[LOOKUPSIZE][EYELENGTH][2]; + double lookup2[LOOKUPSIZE][EYELENGTH][2]; + +} providencestruct; + +/* lighting variables */ +/*static const GLfloat front_shininess[] = {60.0};*/ +/*static const GLfloat front_specular[] = {0.2, 0.2, 0.2, 1.0};*/ +/*static const GLfloat ambient[] = {0.8, 0.8, 0.8, 1.0};*/ +static const GLfloat ambient2[] = {0.25, 0.25, 0.25, 1.0}; +static const GLfloat diffuse[] = {1.0, 1.0, 1.0, 1.0}; +static const GLfloat lmodel_ambient[] = {0.5, 0.5, 0.5, 1.0}; +static const GLfloat lmodel_twoside[] = {GL_TRUE}; + +/* gray-gray */ + +static const GLfloat MaterialGlory[] = {0.04, 0.30, 0.22, 0.7}; +static const GLfloat MaterialGloryB[] = {0.07, 0.50, 0.36, 0.6}; + +static const GLfloat MaterialGloryF[] = {0.07, 0.50, 0.36, 1.0}; +/* static const GLfloat MaterialGloryF[] = {0.06, 0.38, 0.27, 1.0}; */ +/*static const GLfloat MaterialGloryE[] = {0.06, 0.38, 0.27, 0.3};*/ +static const GLfloat MaterialGloryM[] = {0.5, 0.5, 0.5, 0.5}; +static const GLfloat MaterialGloryMB[] = {0.36, 0.36, 0.36, 0.4}; +/*static const GLfloat MaterialGreenback[4] = {0.04, 0.30, 0.22, 1.0};*/ +/*static const GLfloat MaterialBlack[4] = {0.0, 0.0, 0.0, 1.0};*/ + +static const GLfloat MaterialGray5[] = {0.5, 0.5, 0.5, 1.0}; +/*static const GLfloat MaterialGray6[] = {0.6, 0.6, 0.6, 1.0};*/ + +static providencestruct *providence = (providencestruct *) NULL; + +#define NUM_SCENES 2 + +/* build brick texture */ +static void make_brick(providencestruct *mp) +{ + int i, j, c; + + for (i = 0; i < checkImageWidth; i++) { + for (j = 0; j < checkImageHeight; j++) { + c = i % 16 == 15 ? 255 : (j + 48*(i / 16))%64 == 0 ? 255 : + 102 + random() % 102; + mp->checkImage[i][j][0] = (GLubyte) c; + mp->checkImage[i][j][1] = (GLubyte) c; + mp->checkImage[i][j][2] = (GLubyte) c; + } + } + + glGenTextures(1, &mp->bricktexture); + glBindTexture(GL_TEXTURE_2D, mp->bricktexture); + + glTexImage2D(GL_TEXTURE_2D, 0, 3, checkImageWidth, + checkImageHeight, 0, GL_RGB, GL_UNSIGNED_BYTE, + &mp->checkImage[0][0]); +} + + +/* build eye lookup table */ +static void build_eye(providencestruct *mp) +{ + int i, j; + double x; + double inc = 0.1 / EYELENGTH; + double inc2 = 2.4*Pi / EYELENGTH; + + /* describe all values tangentially out from pupil */ + for(i = 0; i < LOOKUPSIZE; ++i) { + double r = i * 2*Pi / LOOKUPSIZE;/*x + inc;*/ + double sr = sin(r); + double cr = cos(r); + x = 0.07; + + for(j = 0; j < EYELENGTH; ++j) { + mp->lookup[i][j][0] = x*sr; + mp->lookup[i][j][1] = x*cr; + x += inc; + } + } + + /* lookup2: dollar sign */ + for(i = 0; i < LOOKUPSIZE; ++i) { + double y = -1.2*Pi; + + for(j = 0; j < EYELENGTH; ++j) { + if(i % 2) { + mp->lookup2[i][j][0] = sin(y)/6.0 + i/36000.0 - 0.05; + mp->lookup2[i][j][1] = i%4 ? y/12.0 - 0.05 : 1.2*Pi-y/12.0 + 0.05; + } + else { + mp->lookup2[i][j][0] = i/36000.0 - 0.05; + mp->lookup2[i][j][1] = y/9.0 - 0.05; + } + y += inc2; + } + } +} + + +static double min(double a, double b) +{ + return a < b ? a : b; +} + +static double max(double a, double b) +{ + return a > b ? a : b; +} + +static void init_particle(providencestruct *mp, double particle[5]) +{ + /* position along glory */ + double p = (random() % 485410) / 100000.0; + + /* on a plane */ + particle[2] = 0.0; + + if(p < 1.5) { + particle[0] = p - 0.75; + particle[1] = -0.75001; + } + else if(p < 1.5 + sqrt(45)/4.0) { + double d = p - 1.5; + particle[0] = 0.75 - d*cos(atan(2.0)); + particle[1] = d*sin(atan(2.0)) - 0.75; + } + else { + double d = 4.8541 - p; + particle[0] = -0.75 + d*cos(atan(2.0)); + particle[1] = d*sin(atan(2.0)) - 0.75; + } + + particle[3] = mp->currenttime; + particle[4] = 1.25 + (random()%10)/10.0; +} + +/* init glory particles */ +static void init_particles(providencestruct *mp) +{ + int i; + for(i = 0; i < PARTICLE_COUNT; ++i) { + init_particle(mp, mp->particles[i]); + + /* set initial time */ + mp->particles[i][3] = mp->currenttime - (random()%1250)/1000.0; + } + + /* init eye particles */ + for(i = 0; i < EYE_PARTICLE_COUNT; ++i) { + mp->eyeparticles[i][0] = random()%LOOKUPSIZE; + mp->eyeparticles[i][1] = random()%EYELENGTH; + } +} + + +/* ugg, should be a priority queue if next event times known */ +static void update_particles(providencestruct *mp) +{ + int i; + + for(i = 0; i < PARTICLE_COUNT; ++i) { + /* check for time elapse */ + if(mp->currenttime > mp->particles[i][3] + mp->particles[i][4]) + init_particle(mp, mp->particles[i]); + } + + /* now update eye particles */ + for(i = 0; i < EYE_PARTICLE_COUNT; ++i) { +/* int x = eyeparticles[i][1] + random()%16; */ + int x = mp->eyeparticles[i][1] + random()%(cos(mp->theta) < 0.0 ? 8 : 16); + + /* reset if dead */ + if(x > EYELENGTH || random()%(cos(mp->theta) < 0.0 ? 40 : 10) == 0) { + +/* if(x > EYELENGTH || (x > EYELENGTH/(2/3.0) && random()%7 == 0)) { */ + mp->eyeparticles[i][0] = random()%LOOKUPSIZE; + mp->eyeparticles[i][1] = random()%40; + } + else { + mp->eyeparticles[i][1] = x; + } + } +} + +/* draw the pyramid */ +static void draw_seal(providencestruct *mp) +{ + int i; + double base = sqrt(2.0); + double top = 1.0 / sqrt(2.0); + double tmod = 7.0/6.0; + + glPushMatrix(); + + /* set options for mono, wireframe */ + if(mp->wire) { + glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); + glDisable(GL_LIGHTING); + glDisable(GL_TEXTURE_2D); + } + else { + glEnable(GL_TEXTURE_2D); + glBindTexture(GL_TEXTURE_2D, mp->bricktexture); + + glEnable(GL_LIGHTING); + + glColor4fv(mp->mono ? MaterialGray5 : MaterialGloryF); + glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, + mp->mono ? MaterialGray5 : MaterialGloryF); + } + + glRotatef(45.0, 0.0, 1.0, 0.0); + glTranslatef(0.0, -3.25, 0.0); + + for(i = 0; i < 4; ++i) { + glRotatef(i*90.0, 0.0, 1.0, 0.0); + + glBegin(GL_QUADS); + glNormal3f(1 / sqrt(6.0), 2 / sqrt(6.0), 1 / sqrt(6.0)); + glTexCoord2f(-base, 0.0); + glVertex3f(-base, 0.0, base); + glTexCoord2f(base, 0.0); + glVertex3f(base, 0.0, base); + glTexCoord2f(top, 13.0/4.0); + glVertex3f(top, 2.0, top); + glTexCoord2f(-top, 13.0/4.0); + glVertex3f(-top, 2.0, top); + glEnd(); + } + + glBegin(GL_QUADS); + + /* top */ + glNormal3f(0.0, 1.0, 0.0); + glTexCoord2f(0.02, 0.0); + glVertex3f(-top, 2.0, top); + glTexCoord2f(2.0*top, 0.0); + glVertex3f(top, 2.0, top); + glTexCoord2f(2.0*top, tmod*2.1*top); + glVertex3f(top, 2.0, -top); + glTexCoord2f(0.02, tmod*2.1*top); + glVertex3f(-top, 2.0, -top); + + /* base */ + glNormal3f(0.0, -1.0, 0.0); + glTexCoord2f(-base, 0.0); + glVertex3f(-base, 0.0, -base); + glTexCoord2f(top, 0.0); + glVertex3f(base, 0.0, -base); + glTexCoord2f(top, top*13.0/4.0); + glVertex3f(base, 0.0, base); + glTexCoord2f(-top, top*13.0/4.0); + glVertex3f(-base, 0.0, base); + + glEnd(); + + glPopMatrix(); + glDisable(GL_TEXTURE_2D); +} + +/* draw glory */ +static void draw_glory(providencestruct *mp) +{ + int i; + + if(mp->wire) { + glBegin(GL_TRIANGLES); + glVertex3f(-0.75, -0.75, 0.0); + glVertex3f(0.75, -0.75, 0.0); + glVertex3f(0.0, 0.75, 0.0); + + glVertex3f(0.0, 0.75, 0.0); + glVertex3f(0.75, -0.75, 0.0); + glVertex3f(-0.75, -0.75, 0.0); + glEnd(); + return; + } + + /* draw particles */ + glDisable(GL_LIGHTING); + glPushMatrix(); + glEnable(GL_BLEND); + + /* glory colour lines */ + glColor4fv(mp->mono ? MaterialGloryM : MaterialGlory); + glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, + mp->mono ? MaterialGloryM : MaterialGlory); + + glBegin(GL_LINES); + for(i = 0; i < PARTICLE_COUNT/2; ++i) { + double t = mp->currenttime - mp->particles[i][3]; + double th = atan(mp->particles[i][1] / mp->particles[i][0]); + if(mp->particles[i][0] < 0.0) + th += Pi; + + glVertex3f(mp->particles[i][0], mp->particles[i][1], mp->particles[i][2]); + glVertex3f(mp->particles[i][0] + 0.2*cos(th)*t, + mp->particles[i][1] + 0.2*sin(th)*t, + mp->particles[i][2]); + } + glEnd(); + + /* gloryb colour lines */ + glColor4fv(mp->mono ? MaterialGloryMB : MaterialGloryB); + glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, + mp->mono ? MaterialGloryMB : MaterialGloryB); + glBegin(GL_LINES); + for(; i < PARTICLE_COUNT; ++i) { + double t = mp->currenttime - mp->particles[i][3]; + double th = atan(mp->particles[i][1] / mp->particles[i][0]); + if(mp->particles[i][0] < 0.0) + th += Pi; + + glVertex3f(mp->particles[i][0], mp->particles[i][1], mp->particles[i][2]); + glVertex3f(mp->particles[i][0] + 0.2*cos(th)*t, + mp->particles[i][1] + 0.2*sin(th)*t, + mp->particles[i][2]); + } + glEnd(); + + glPopMatrix(); + glEnable(GL_LIGHTING); +} + +/* draw eye of providence */ +static void draw_eye(providencestruct *mp) +{ + int i; + + /* draw wireeye */ + if(mp->wire) { + glBegin(GL_TRIANGLES); + glVertex3f(-0.25, -0.25, 0.0); + glVertex3f(0.25, -0.25, 0.0); + glVertex3f(0.0, 0.25, 0.0); + glEnd(); + return; + } + + /* draw particles */ + glDisable(GL_LIGHTING); + glPushMatrix(); + glEnable(GL_BLEND); + + /* eye */ + glColor4fv(mp->mono ? MaterialGloryM : MaterialGlory); + glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, + mp->mono ? MaterialGloryM : MaterialGlory); + + /* draw eye particles on z = 0 plane */ + glBegin(GL_POINTS); + for(i = 0; i < EYE_PARTICLE_COUNT/2; ++i) { + glVertex3f(mp->lookup[mp->eyeparticles[i][0]][mp->eyeparticles[i][1]][0], + mp->lookup[mp->eyeparticles[i][0]][mp->eyeparticles[i][1]][1], + 0.0); + } + glEnd(); + + /* eye */ + glColor4fv(mp->mono ? MaterialGloryMB : MaterialGloryB); + glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, + mp->mono ? MaterialGloryMB : MaterialGloryB); + + /* draw eye particles on z = 0 plane */ + glBegin(GL_POINTS); + for(; i < EYE_PARTICLE_COUNT; ++i) { + glVertex3f(mp->lookup[mp->eyeparticles[i][0]][mp->eyeparticles[i][1]][0], + mp->lookup[mp->eyeparticles[i][0]][mp->eyeparticles[i][1]][1], + 0.0); + } + glEnd(); + + + /* draw scaled particles */ + glPushMatrix(); + glScalef(3.3, 2.2, 3.3); + + /* eye */ + glColor4fv(mp->mono ? MaterialGloryMB : MaterialGloryB); + glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, + mp->mono ? MaterialGloryMB : MaterialGloryB); + + /* draw eye particles on z = 0 plane */ + glBegin(GL_POINTS); + for(i = 0; i < EYE_PARTICLE_COUNT/2; ++i) { + glVertex3f(mp->lookup[mp->eyeparticles[i][0]][mp->eyeparticles[i][1]][0], + mp->lookup[mp->eyeparticles[i][0]][mp->eyeparticles[i][1]][1], + 0.0); + } + glEnd(); + + glColor4fv(mp->mono ? MaterialGloryM : MaterialGlory); + glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, + mp->mono ? MaterialGloryM : MaterialGlory); + + /* draw eye particles on z = 0 plane */ + glBegin(GL_POINTS); + for(; i < EYE_PARTICLE_COUNT; ++i) { + glVertex3f(mp->lookup[mp->eyeparticles[i][0]][mp->eyeparticles[i][1]][0], + mp->lookup[mp->eyeparticles[i][0]][mp->eyeparticles[i][1]][1], + 0.0); + } + glEnd(); + + glPopMatrix(); + + glPopMatrix(); + glEnable(GL_LIGHTING); +} + +/* draw eye of providence */ +static void draw_eye2(providencestruct *mp) +{ + int i; + + /* draw wireeye */ + if(mp->wire) { + glBegin(GL_TRIANGLES); + glVertex3f(0.0, 0.25, 0.0); + glVertex3f(0.25, -0.25, 0.0); + glVertex3f(-0.25, -0.25, 0.0); + glEnd(); + return; + } + + /* draw particles */ + glDisable(GL_LIGHTING); + glPushMatrix(); + glEnable(GL_BLEND); + + /* eye */ + glColor4fv(mp->mono ? MaterialGloryM : MaterialGlory); + glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, + mp->mono ? MaterialGloryM : MaterialGlory); + + /* draw eye particles on z = 0 plane */ + glBegin(GL_POINTS); + for(i = 0; i < EYE_PARTICLE_COUNT/2; ++i) { + glVertex3f(mp->lookup2[mp->eyeparticles[i][0]][mp->eyeparticles[i][1]][0], + mp->lookup2[mp->eyeparticles[i][0]][mp->eyeparticles[i][1]][1], + 0.0); + } + glEnd(); + + /* eye */ + glColor4fv(mp->mono ? MaterialGloryMB : MaterialGloryB); + glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, + mp->mono ? MaterialGloryMB : MaterialGloryB); + + /* draw eye particles on z = 0 plane */ + glBegin(GL_POINTS); + for(; i < EYE_PARTICLE_COUNT; ++i) { + glVertex3f(mp->lookup2[mp->eyeparticles[i][0]][mp->eyeparticles[i][1]][0], + mp->lookup2[mp->eyeparticles[i][0]][mp->eyeparticles[i][1]][1], + 0.0); + } + glEnd(); + + glPopMatrix(); + glEnable(GL_LIGHTING); +} + +/* draw the scene */ +static void draw_providence_strip(ModeInfo *mi) +{ + providencestruct *mp = &providence[MI_SCREEN(mi)]; + glTranslatef(0.0, 1.414, 0.0); + + mp->position0[0] = 1.6*sin(mp->theta); + mp->position0[1] = 1.2; + mp->position0[2] = 1.6*cos(mp->theta); + mp->position0[3] = 0.0; + glLightfv(GL_LIGHT0, GL_POSITION, mp->position0); + glLightfv(GL_LIGHT0, GL_AMBIENT, ambient2); + glEnable(GL_LIGHTING); + glEnable(GL_LIGHT0); + + /* draw pyramid, glory */ + glDisable(GL_BLEND); + glCallList(mp->pyramidlist); + draw_glory(mp); + if(eye) { + if(cos(mp->theta) < 0.0) + draw_eye2(mp); + else + draw_eye(mp); + } + + return; +} + +ENTRYPOINT void reshape_providence(ModeInfo * mi, int width, int height) +{ + double h = (GLfloat) height / (GLfloat) width; + providencestruct *mp = &providence[MI_SCREEN(mi)]; + + glViewport(0, 0, mp->WindW = (GLint) width, mp->WindH = (GLint) height); + glMatrixMode(GL_PROJECTION); + glLoadIdentity(); + + gluPerspective(45, 1/h, 0.001, 25.0); + + glMatrixMode(GL_MODELVIEW); + glLineWidth(2.0); + glPointSize(2.0); +} + +static void pinit(providencestruct *mp) +{ + glClearDepth(1.0); + + mp->currenttime = 0.0; + init_particles(mp); + make_brick(mp); + build_eye(mp); + + /* build pyramid list */ + mp->pyramidlist = glGenLists(1); + glNewList(mp->pyramidlist, GL_COMPILE); + draw_seal(mp); + glEndList(); +} + +/* cleanup routine */ +ENTRYPOINT void release_providence(ModeInfo * mi) +{ + + if(providence) { + free((void *) providence); + providence = (providencestruct *) NULL; + } + + FreeAllGL(mi); +} + +/* event handling */ +ENTRYPOINT Bool providence_handle_event(ModeInfo *mi, XEvent *event) +{ + providencestruct *mp = &providence[MI_SCREEN(mi)]; + + switch(event->xany.type) { + case ButtonPress: + + switch(event->xbutton.button) { + + case Button1: + mp->button_down_p = True; + gltrackball_start(mp->trackball, + event->xbutton.x, event->xbutton.y, + MI_WIDTH (mi), MI_HEIGHT (mi)); + break; + + case Button4: + mp->camera_velocity += 1.0; + break; + + case Button5: + mp->camera_velocity -= 1.0; + break; + } + + break; + + case ButtonRelease: + + switch(event->xbutton.button) { + case Button1: + mp->button_down_p = False; + break; + } + + break; + + case MotionNotify: + if(mp->button_down_p) + gltrackball_track(mp->trackball, + event->xmotion.x, event->xmotion.y, + MI_WIDTH (mi), MI_HEIGHT (mi)); + break; + + default: + return False; + } + + return True; +} + +ENTRYPOINT void init_providence(ModeInfo *mi) +{ + providencestruct *mp; + + if(!providence) { + if((providence = (providencestruct *) + calloc(MI_NUM_SCREENS(mi), sizeof (providencestruct))) == NULL) + return; + } + mp = &providence[MI_SCREEN(mi)]; + mp->trackball = gltrackball_init (); + + mp->position0[0] = 1; + mp->position0[1] = 5; + mp->position0[2] = 1; + mp->position0[3] = 1; + + mp->camera_velocity = -8.0; + + mp->mono = MI_IS_MONO(mi); + mp->wire = MI_IS_WIREFRAME(mi); + +# ifdef HAVE_JWZGLES /* #### glPolygonMode other than GL_FILL unimplemented */ + mp->wire = 0; +# endif + + /* make multiple screens rotate at slightly different rates. */ + mp->theta_scale = 0.7 + frand(0.6); + + if((mp->glx_context = init_GL(mi)) != NULL) { + reshape_providence(mi, MI_WIDTH(mi), MI_HEIGHT(mi)); + /* glDrawBuffer(GL_BACK); */ + pinit(mp); + } + else + MI_CLEARWINDOW(mi); +} + +ENTRYPOINT void draw_providence(ModeInfo * mi) +{ + providencestruct *mp; + + Display *display = MI_DISPLAY(mi); + Window window = MI_WINDOW(mi); + + if(!providence) + return; + mp = &providence[MI_SCREEN(mi)]; + + MI_IS_DRAWN(mi) = True; + + if(!mp->glx_context) + return; + + glXMakeCurrent(display, window, *(mp->glx_context)); + + /* setup twoside lighting */ + glLightfv(GL_LIGHT0, GL_AMBIENT, ambient2); + glLightfv(GL_LIGHT0, GL_DIFFUSE, diffuse); + glLightfv(GL_LIGHT0, GL_POSITION, mp->position0); + + glLightModelfv(GL_LIGHT_MODEL_AMBIENT, lmodel_ambient); + glLightModelfv(GL_LIGHT_MODEL_TWO_SIDE, lmodel_twoside); + glEnable(GL_LIGHTING); + glEnable(GL_LIGHT0); + + glEnable(GL_NORMALIZE); + glFrontFace(GL_CCW); +/* glDisable(GL_CULL_FACE); */ + glEnable(GL_CULL_FACE); + glCullFace(GL_BACK); + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + + glShadeModel(GL_SMOOTH); + glEnable(GL_DEPTH_TEST); + glDepthFunc(GL_LEQUAL); + + glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_S,GL_REPEAT); + glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_T,GL_REPEAT); + glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); + + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + + glPushMatrix(); + glRotatef(current_device_rotation(), 0, 0, 1); + + /* modify camera */ + if(fabs(mp->camera_velocity) > EPSILON) { + mp->camera_z = max(min(mp->camera_z + 0.1*mp->camera_velocity, -4.0), -12.0); + mp->camera_velocity = 0.95*mp->camera_velocity; + } + + /* rotate providence */ + glTranslatef(0.0, 0.0, mp->camera_z + sin(mp->theta/4.0)); + glRotatef(10.0+20.0*sin(mp->theta/2.0), 1.0, 0.0, 0.0); + gltrackball_rotate(mp->trackball); + glRotatef(mp->theta * 180.0 / Pi, 0.0, -1.0, 0.0); + + /* draw providence */ + draw_providence_strip(mi); + glPopMatrix(); + + if(MI_IS_FPS(mi)) do_fps (mi); + glFlush(); + + glXSwapBuffers(display, window); + + /* update */ + mp->currenttime += 1.0 / FPS; + mp->theta = mp->currenttime / 2.0 * mp->theta_scale; + update_particles(mp); +} + +#ifndef STANDALONE +ENTRYPOINT void change_providence(ModeInfo * mi) +{ + providencestruct *mp = &providence[MI_SCREEN(mi)]; + + if (!mp->glx_context) + return; + + glXMakeCurrent(MI_DISPLAY(mi), MI_WINDOW(mi), *(mp->glx_context)); + pinit(); +} +#endif /* !STANDALONE */ + +XSCREENSAVER_MODULE ("Providence", providence) diff --git a/hacks/glx/providence.man b/hacks/glx/providence.man new file mode 100644 index 00000000..ea7286d5 --- /dev/null +++ b/hacks/glx/providence.man @@ -0,0 +1,66 @@ +.TH XScreenSaver 1 "May 2004" +.SH NAME +providence - eye in glory screenhack +.SH SYNOPSIS +.B providence +[\-display \fIhost:display.screen\fP] +[\-window] +[\-root] + [\-install] +[\-visual \fIvisual\fP] +[\-delay \fImicroseconds\fP] +[\-wireframe] +[\-fps] +.SH DESCRIPTION +The \fIprovidence\fP code displays an eye, shrouded in glory, set upon the +base of a pyramid. +.SH OPTIONS +.I providence +accepts the following options: +.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 \-install +Install a private colormap for the window. +.TP 8 +.B \-eye +Draw an eye/$. +.TP 8 +.B \-visual \fIvisual\fP\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 \-wireframe +Render in wireframe (with hidden line removal) instead of as textured solids. +.TP 8 +.B \-fps +Display the current frame rate, CPU load, and polygon count. +.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) +.BR xscreensaver\-demo (1), +.BR xscreensaver\-getimage (1) +.SH COPYRIGHT +Copyright \(co 2004 by Blair Tennessy. 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 +Blair Tennessy , 11-May-2004. + diff --git a/hacks/glx/pulsar.c b/hacks/glx/pulsar.c new file mode 100644 index 00000000..0a821675 --- /dev/null +++ b/hacks/glx/pulsar.c @@ -0,0 +1,521 @@ +/* -*- Mode: C; tab-width: 4 -*- */ +/* pulsar --- pulsar module for xpulsar */ +/*- + * Permission to use, copy, modify, and distribute this software and its + * documentation for any purpose and without fee is hereby granted, + * provided that the above copyright notice appear in all copies and that + * both that copyright notice and this permission notice appear in + * supporting documentation. + * + * This file is provided AS IS with no warranties of any kind. The author + * shall have no liability with respect to the infringement of copyrights, + * trade secrets or any patents by this file or any part thereof. In no + * event will the author be liable for any lost revenue or profits or + * other special, indirect and consequential damages. + + * Revision History: + * 4-Apr-1999: dek@cgl.ucsf.edu Created module "pulsar" + * 27-Apr-1999: dek@cgl.ucsf.edu Submitted module "pulsar" + * 4-May-1999: jwz@jwz.org Added module "pulsar" + * 4-May-1999: dek@cgl.ucsf.edu Submitted module "pulsar" updates + * + * Notes: + * The pulsar pulsar draws a number of rotating, pulsing rectangles + * on your screen. Depending on the options you choose, you can set a number + * of interesting OpenGL parameters, including alpha blending, depth testing, fog, + * lighting, texturing, mipmapping, bilinear filtering, and line antialiasing. + * Additionally, there is a "frames per second" meter which gives an estimate of + * the speed of your graphics card. + * + * Example command-line switches: + * Only draw a single quad, and don't fill it (boring but fast) + * pulsar -wire -quads 1 -fps + * + * Only try this with hardware graphics acceleration (PPro 200 w/ a Voodoo 2 runs great) + * pulsar -quads 10 -texture -mipmap -texture_quality -light -fog -fps + * + */ + +#include +#include +#include + +#ifdef STANDALONE +#define DEFAULTS "*delay: 10000 \n" \ + "*showFPS: False \n" \ + +# define refresh_pulsar 0 +# define pulsar_handle_event 0 +# include "xlockmore.h" /* from the xpulsar distribution */ +#else /* !STANDALONE */ +# include "xlock.h" /* from the xlockmore distribution */ +#endif /* !STANDALONE */ + +#ifdef USE_GL /* whole file */ + +#ifdef HAVE_XMU +# ifndef VMS +# include +#else /* VMS */ +# include +# endif /* VMS */ +#endif + +#include "xpm-ximage.h" + +/* Functions for loading and storing textures */ + +#define checkImageWidth 64 +#define checkImageHeight 64 + +/* Functions for handling the frames per second timer */ + +#undef countof +#define countof(x) (sizeof((x))/sizeof((*x))) + +#define WIDTH 800 +#define HEIGHT 600 + +#define NUM_QUADS 5 +#define DEF_QUADS "5" +#define DEF_LIGHT "False" +#define DEF_WIRE "False" +#define DEF_BLEND "True" +#define DEF_FOG "False" +#define DEF_ANTIALIAS "False" +#define DEF_TEXTURE "False" +#define DEF_TEXTURE_QUALITY "False" +#define DEF_MIPMAP "False" +#define DEF_DO_DEPTH "False" +#define DEF_IMAGE "BUILTIN" + +static int num_quads; +static int do_light; +static int do_wire; +static int do_blend; +static int do_fog; +static int do_antialias; +static int do_texture; +static int do_texture_quality; +static int do_mipmap; +static int do_depth; +static char *which_image; + + +static XrmOptionDescRec opts[] = { + {"-quads", ".pulsar.quads", XrmoptionSepArg, 0 }, + {"-light", ".pulsar.light", XrmoptionNoArg, "true" }, + {"+light", ".pulsar.light", XrmoptionNoArg, "false" }, + {"-wire", ".pulsar.wire", XrmoptionNoArg, "true" }, + {"+wire", ".pulsar.wire", XrmoptionNoArg, "false" }, + {"-blend", ".pulsar.blend", XrmoptionNoArg, "true" }, + {"+blend", ".pulsar.blend", XrmoptionNoArg, "false" }, + {"-fog", ".pulsar.fog", XrmoptionNoArg, "true" }, + {"+fog", ".pulsar.fog", XrmoptionNoArg, "false" }, + {"-antialias", ".pulsar.antialias", XrmoptionNoArg, "true" }, + {"+antialias", ".pulsar.antialias", XrmoptionNoArg, "false" }, + {"-texture", ".pulsar.texture", XrmoptionNoArg, "true" }, + {"+texture", ".pulsar.texture", XrmoptionNoArg, "false" }, + {"-texture_quality", ".pulsar.textureQuality", XrmoptionNoArg, "true" }, + {"+texture_quality", ".pulsar.textureQuality", XrmoptionNoArg, "false" }, + {"-mipmap", ".pulsar.mipmap", XrmoptionNoArg, "true" }, + {"+mipmap", ".pulsar.mipmap", XrmoptionNoArg, "false" }, + {"-do_depth", ".pulsar.doDepth", XrmoptionNoArg, "true" }, + {"+do_depth", ".pulsar.doDepth", XrmoptionNoArg, "false" }, + {"-image", ".pulsar.image", XrmoptionSepArg, 0 }, +}; + + +static argtype vars[] = { + {&num_quads, "quads", "Quads", DEF_QUADS, t_Int}, + {&do_light, "light", "Light", DEF_LIGHT, t_Bool}, + {&do_wire, "wire", "Wire", DEF_WIRE, t_Bool}, + {&do_blend, "blend", "Blend", DEF_BLEND, t_Bool}, + {&do_fog, "fog", "Fog", DEF_FOG, t_Bool}, + {&do_antialias, "antialias", "Antialias", DEF_ANTIALIAS, t_Bool}, + {&do_texture, "texture", "Texture", DEF_TEXTURE, t_Bool}, + {&do_texture_quality, "textureQuality", "TextureQuality", DEF_TEXTURE_QUALITY, t_Bool}, + {&do_mipmap, "mipmap", "Mipmap", DEF_MIPMAP, t_Bool}, + {&do_depth, "doDepth", "DoDepth", DEF_DO_DEPTH, t_Bool}, + {&which_image, "image", "Image", DEF_IMAGE, t_String}, +}; + + +static OptionStruct desc[] = +{ + {"-quads num", "how many quads to draw"}, + {"-/+ light", "whether to do enable lighting (slower)"}, + {"-/+ wire", "whether to do use wireframe instead of filled (faster)"}, + {"-/+ blend", "whether to do enable blending (slower)"}, + {"-/+ fog", "whether to do enable fog (?)"}, + {"-/+ antialias", "whether to do enable antialiased lines (slower)"}, + {"-/+ texture", "whether to do enable texturing (much slower)"}, + {"-/+ texture_quality", "whether to do enable linear/mipmap filtering (much much slower)"}, + {"-/+ mipmap", "whether to do enable mipmaps (much slower)"}, + {"-/+ depth", "whether to do enable depth buffer checking (slower)"}, + {"-image ", "texture image to load"}, +}; + +ENTRYPOINT ModeSpecOpt pulsar_opts = {countof(opts), opts, countof(vars), vars, desc}; + +#ifdef USE_MODULES +ModStruct pulsar_description = +{"pulsar", "init_pulsar", "draw_pulsar", "release_pulsar", + "draw_pulsar", "init_pulsar", NULL, &pulsar_opts, + 1000, 1, 2, 1, 4, 1.0, "", + "OpenGL pulsar", 0, NULL}; +#endif + +struct quad +{ + GLfloat tx, ty, tz; + GLfloat rx, ry, rz; + + GLfloat dtx, dty, dtz; + GLfloat drx, dry, drz; + +}; + + +/* structure for holding the pulsar data */ +typedef struct { + int screen_width, screen_height; + GLXContext *glx_context; + Window window; + XColor fg, bg; + + GLint quad_list; + float scale_x, scale_y, scale_z; + int frame; + + struct quad *quads; + +} pulsarstruct; + +static pulsarstruct *Pulsar = NULL; + +static GLubyte * +Generate_Image(int *width, int *height, int *format) +{ + GLubyte *result; + int i, j, c; + int counter=0; + + *width = checkImageWidth; + *height = checkImageHeight; + result = (GLubyte *)malloc(4 * (*width) * (*height)); + + counter = 0; + for (i = 0; i < checkImageWidth; i++) { + for (j = 0; j < checkImageHeight; j++) { + c = (((((i&0x8)==0))^(((j&0x8))==0)))*255; + result[counter++] = (GLubyte) c; + result[counter++] = (GLubyte) c; + result[counter++] = (GLubyte) c; + result[counter++] = (GLubyte) 255; + } + } + + *format = GL_RGBA; + return result; +} + + +/* Create a texture in OpenGL. First an image is loaded + and stored in a raster buffer, then it's */ +static void Create_Texture(ModeInfo *mi, const char *filename) +{ + int height, width; + GLubyte *image; + int format; + + if ( !strncmp(filename, "BUILTIN", 7)) + image = Generate_Image(&width, &height, &format); + else + { + XImage *ximage = xpm_file_to_ximage (MI_DISPLAY (mi), MI_VISUAL (mi), + MI_COLORMAP (mi), filename); + image = (GLubyte *) ximage->data; + width = ximage->width; + height = ximage->height; + format = GL_RGBA; + } + + /* GL_MODULATE or GL_DECAL depending on what you want */ + 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); + glPixelStorei(GL_UNPACK_ALIGNMENT, 1); + /* perhaps we can edge a bit more speed at the expense of quality */ + glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_FASTEST); + + if (do_texture_quality) { + /* with texture_quality, the min and mag filters look *much* nice but are *much* slower */ + glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR); + } + else { + /* default is to do it quick and dirty */ + /* if you have mipmaps turned on, but not texture quality, nothing will happen! */ + glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + } + + /* mipmaps make the image look much nicer */ + if (do_mipmap) + { + int status; + clear_gl_error(); + status = gluBuild2DMipmaps(GL_TEXTURE_2D, 3, width, height, format, + GL_UNSIGNED_BYTE, image); + if (status) + { + const char *s = (char *) gluErrorString (status); + fprintf (stderr, "%s: error mipmapping %dx%d texture: %s\n", + progname, width, height, + (s ? s : "(unknown)")); + exit (1); + } + check_gl_error("mipmapping"); + } + else + { + clear_gl_error(); + glTexImage2D(GL_TEXTURE_2D, 0, format, width, height, 0, + format, GL_UNSIGNED_BYTE, image); + check_gl_error("texture"); + } +} + +static void resetProjection(void) +{ + glMatrixMode(GL_PROJECTION); + glLoadIdentity(); + glFrustum(-1, 1, -1, 1, 1, 100); + glMatrixMode(GL_MODELVIEW); + glLoadIdentity(); +} + + +static void GenerateQuad(pulsarstruct *gp) +{ + int i; + + gp->quad_list = glGenLists(1); + glNewList(gp->quad_list,GL_COMPILE); +#if 1 + glBegin(GL_QUADS); + glColor4f(1,0,0,.4); glNormal3f(0,0,1); glTexCoord2f(0,0); glVertex2f(-1, -1); + glColor4f(0,1,0,.4); glNormal3f(0,0,1); glTexCoord2f(0,1); glVertex2f(-1, 1); + glColor4f(0,0,1,.4); glNormal3f(0,0,1); glTexCoord2f(1,1); glVertex2f( 1, 1); + glColor4f(1,1,1,1); glNormal3f(0,0,1); glTexCoord2f(1,0); glVertex2f( 1, -1); +#else + glBegin(GL_TRIANGLE_STRIP); + glColor4f(0,1,0,.4); glNormal3f(0,0,1); glTexCoord2f(0,1); glVertex2f(-1, 1); + glColor4f(1,0,0,.4); glNormal3f(0,0,1); glTexCoord2f(0,0); glVertex2f(-1, -1); + glColor4f(0,0,1,.4); glNormal3f(0,0,1); glTexCoord2f(1,1); glVertex2f( 1, 1); + glColor4f(1,1,1,.4); glNormal3f(0,0,1); glTexCoord2f(1,0); glVertex2f( 1, -1); +#endif + glEnd(); + glEndList(); + + gp->quads = (struct quad *) malloc(sizeof(struct quad) * num_quads); + for (i=0; i < num_quads; i++) + { + gp->quads[i].rx = 0.; + gp->quads[i].ry = 0.; + gp->quads[i].rz = 0.; + gp->quads[i].tx = 0.; + gp->quads[i].ty = 0.; + gp->quads[i].tz = -10; + + gp->quads[i].drx = frand(5.0); + gp->quads[i].dry = frand(5.0); + gp->quads[i].drz = 0; + } +} + +static void initializeGL(ModeInfo *mi, GLsizei width, GLsizei height) +{ + pulsarstruct *gp = &Pulsar[MI_SCREEN(mi)]; + GLfloat fogColor[4] = { 0.1, 0.1, 0.1, 0.1 }; + + glViewport( 0, 0, width, height ); + resetProjection(); + + if (do_depth) + glEnable(GL_DEPTH_TEST); + + if (do_antialias) { + do_blend = 1; + glEnable(GL_LINE_SMOOTH); + } + + if (do_blend) { + glEnable(GL_BLEND); + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + } + + + if (do_light) { + glShadeModel(GL_SMOOTH); + glEnable(GL_COLOR_MATERIAL); + glColorMaterial(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE); + } + +# ifdef HAVE_JWZGLES /* #### glPolygonMode other than GL_FILL unimplemented */ + do_wire = 0; +# endif + + if (do_wire) + glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); + else + glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); + + if (do_fog) { + glEnable(GL_FOG); + glFogi(GL_FOG_MODE, GL_LINEAR); + glFogfv(GL_FOG_COLOR, fogColor); + glFogf(GL_FOG_DENSITY, 0.35); +/* glHint(GL_FOG_HINT, GL_FASTEST); */ + glFogf(GL_FOG_START, 50.0); + glFogf(GL_FOG_END, 100.0); + } + + + if (do_texture) + Create_Texture(mi, which_image); + + GenerateQuad(gp); +} + +static void drawQuads(pulsarstruct *gp) +{ + int i; + for (i=0; i < num_quads; i++) + { + glPushMatrix(); + glTranslatef(gp->quads[i].tx,0,0); + glTranslatef(0,gp->quads[i].ty,0); + glTranslatef(0,0,gp->quads[i].tz); + glRotatef(gp->quads[i].rx, 1,0,0); + glRotatef(gp->quads[i].ry, 0,1,0); + glRotatef(gp->quads[i].rz, 0,0,1); + glCallList(gp->quad_list); + glPopMatrix(); + + gp->quads[i].rx += gp->quads[i].drx; + gp->quads[i].ry += gp->quads[i].dry; + gp->quads[i].rz += gp->quads[i].drz; + + } +} + +static GLvoid drawScene(ModeInfo * mi) +{ + pulsarstruct *gp = &Pulsar[MI_SCREEN(mi)]; +/* check_gl_error ("drawScene"); */ + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + + /* we have to do this here because the FPS meter turns these 3 features off!! */ + { + if (do_light) { + glEnable(GL_LIGHTING); + glEnable(GL_LIGHT0); + } + + if (do_texture) { + glEnable(GL_TEXTURE_2D); + } + + if (do_blend) { + glEnable(GL_BLEND); + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + } + } + + resetProjection(); + + /* use XYZ scaling factors to change the size of the pulsar */ + glScalef(gp->scale_x, gp->scale_y, gp->scale_z); + drawQuads(gp); + mi->polygon_count = num_quads; + + /* update the scaling factors- cyclic */ + gp->scale_x = cos(gp->frame/360.)*10.; + gp->scale_y = sin(gp->frame/360.)*10.; + gp->scale_z = 1; + + /* increment frame-counter */ + gp->frame++; + +/* check_gl_error ("drawScene"); */ +} + + +ENTRYPOINT void draw_pulsar(ModeInfo * mi) +{ + pulsarstruct *gp = &Pulsar[MI_SCREEN(mi)]; + Display *display = MI_DISPLAY(mi); + Window window = MI_WINDOW(mi); + + if (!gp->glx_context) + return; + + glXMakeCurrent(display, window, *(gp->glx_context)); + drawScene(mi); + if (mi->fps_p) do_fps (mi); + glXSwapBuffers(display, window); +} + +/* Standard reshape function */ +ENTRYPOINT void +reshape_pulsar(ModeInfo *mi, int width, int height) +{ + glViewport( 0, 0, MI_WIDTH(mi), MI_HEIGHT(mi) ); + resetProjection(); +} + +ENTRYPOINT void +init_pulsar(ModeInfo * mi) +{ + int screen = MI_SCREEN(mi); + + pulsarstruct *gp; + + if (Pulsar == NULL) { + if ((Pulsar = (pulsarstruct *) calloc(MI_NUM_SCREENS(mi), sizeof (pulsarstruct))) == NULL) + return; + } + gp = &Pulsar[screen]; + + gp->window = MI_WINDOW(mi); + + gp->scale_x = gp->scale_y = gp->scale_z = 1; + + if ((gp->glx_context = init_GL(mi)) != NULL) { + reshape_pulsar(mi, MI_WIDTH(mi), MI_HEIGHT(mi)); + initializeGL(mi, MI_WIDTH(mi), MI_HEIGHT(mi)); + } else { + MI_CLEARWINDOW(mi); + } +} + + +/* all sorts of nice cleanup code should go here! */ +ENTRYPOINT void release_pulsar(ModeInfo * mi) +{ + int screen; + if (Pulsar != NULL) { + for (screen = 0; screen < MI_NUM_SCREENS(mi); screen++) { + pulsarstruct *gp = &Pulsar[screen]; + free(gp->quads); + } + (void) free((void *) Pulsar); + Pulsar = NULL; + } + FreeAllGL(mi); +} +#endif + +XSCREENSAVER_MODULE ("Pulsar", pulsar) diff --git a/hacks/glx/pulsar.man b/hacks/glx/pulsar.man new file mode 100644 index 00000000..f3b10090 --- /dev/null +++ b/hacks/glx/pulsar.man @@ -0,0 +1,102 @@ +.TH XScreenSaver 1 "" "X Version 11" +.SH NAME +pulsar - intersecting planes, alpha blending, fog, and textures. +.SH SYNOPSIS +.B pulsar +[\-display \fIhost:display.screen\fP] +[\-visual \fIvisual\fP] +[\-window] +[\-root] +[\-no-light] +[\-wire] +[\-delay \fInumber\fP] +[\-quads \fInumber\fP] +[\-image \fIfile\fP] +[\-light] +[\-fog] +[\-texture] +[\-mipmap] +[\-no-blend] +[\-antialias] +[\-texture_quality] +[\-do_depth] +[\-fps] +.SH DESCRIPTION +Draws some intersecting planes, making use of alpha blending, fog, +textures, and mipmaps, plus a ``frames per second'' meter so that you can +tell how fast your graphics card is... Requires OpenGL. +.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 \-light | \-no-light +Use Flat Coloring. +.TP 8 +.B \-wire +Render in wireframe instead of solid. +.TP 8 +.B \-delay \fInumber\fP +Per-frame delay, in microseconds. Default: 10000 (0.01 seconds.). +.TP 8 +.B \-image \fIfile\fP +The texture map to use. +.TP 8 +.B \-quads \fInumber\fP +Quad Count. 1 - 50. Default: 5. +.TP 8 +.B \-light | \-no-light +Whether to enable lighting. +.TP 8 +.B \-fog | \-no-fog +Whether to enable fog. +.TP 8 +.B \-texture | \-no-texture +Whether to enable texturing. +.TP 8 +.B \-mipmap | \-no-mipmap +Whether to enable texture mipmaps. +.TP 8 +.B \-blend | \-no-blend +Whether to enable blending. +.TP 8 +.B \-antialias | \-no-antialias +Whether to anti-alias lines. +.TP 8 +.B \-texture_quality | \-no-texture_quality +Whether to enable texture filtering. +.TP 8 +.B \-do_depth | \-no-do_depth +Whether to enable depth buffer. +.TP 8 +.B \-fps +Display the current frame rate, CPU load, and polygon count. +.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 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. +.SH AUTHOR +David Konerding. diff --git a/hacks/glx/queens.c b/hacks/glx/queens.c new file mode 100644 index 00000000..c1871f53 --- /dev/null +++ b/hacks/glx/queens.c @@ -0,0 +1,657 @@ +/* + * queens - solves n queens problem, displays + * i make no claims that this is an optimal solution to the problem, + * good enough for xss + * hacked from glchess + * + * version 1.0 - May 10, 2002 + * + * Copyright (C) 2002 Blair Tennessy (tennessy@cs.ubc.ca) + * + * 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. + */ + +#ifdef STANDALONE +#define DEFAULTS "*delay: 20000 \n" \ + "*showFPS: False \n" \ + "*wireframe: False \n" \ + +# define refresh_queens 0 +# include "xlockmore.h" + +#else +# include "xlock.h" +#endif + +#ifdef HAVE_COCOA +# include "jwxyz.h" +#else +# include +# include +# include +#endif + +#ifdef HAVE_JWZGLES +# include "jwzgles.h" +#endif /* HAVE_JWZGLES */ + +#ifdef USE_GL + +#include "gltrackball.h" +#include "chessmodels.h" + +#undef countof +#define countof(x) (sizeof((x))/sizeof((*x))) + +static XrmOptionDescRec opts[] = { + {"+rotate", ".queens.rotate", XrmoptionNoArg, "false" }, + {"-rotate", ".queens.rotate", XrmoptionNoArg, "true" }, + {"+flat", ".queens.flat", XrmoptionNoArg, "false" }, + {"-flat", ".queens.flat", XrmoptionNoArg, "true" }, +}; + +static int rotate, wire, clearbits, flat; + +static argtype vars[] = { + {&rotate, "rotate", "Rotate", "True", t_Bool}, + {&flat, "flat", "Flat", "False", t_Bool}, +}; + +ENTRYPOINT ModeSpecOpt queens_opts = {countof(opts), opts, countof(vars), vars, NULL}; + +#ifdef USE_MODULES +ModStruct queens_description = +{"queens", "init_queens", "draw_queens", "release_queens", + "draw_queens", "init_queens", NULL, &queens_opts, + 1000, 1, 2, 1, 4, 1.0, "", + "Queens", 0, NULL}; + +#endif + +#define NONE 0 +#define MINBOARD 5 +#define MAXBOARD 10 +#define COLORSETS 5 + +typedef struct { + GLXContext *glx_context; + Window window; + trackball_state *trackball; + Bool button_down_p; + GLfloat position[4]; + int queen_list; + + int board[MAXBOARD][MAXBOARD]; + int steps, colorset, BOARDSIZE; + double theta; + int queen_polys; + +} Queenscreen; + +static Queenscreen *qss = NULL; + +/* definition of white/black colors */ +static const GLfloat colors[COLORSETS][2][3] = + { + {{0.43, 0.54, 0.76}, {0.8, 0.8, 0.8}}, + {{0.5, 0.7, 0.9}, {0.2, 0.3, 0.6}}, + {{0.53725490196, 0.360784313725, 0.521568627451}, {0.6, 0.6, 0.6}}, + {{0.15, 0.77, 0.54}, {0.5, 0.5, 0.5}}, + {{0.9, 0.45, 0.0}, {0.5, 0.5, 0.5}}, + }; + +ENTRYPOINT Bool +queens_handle_event (ModeInfo *mi, XEvent *event) +{ + Queenscreen *qs = &qss[MI_SCREEN(mi)]; + + if (event->xany.type == ButtonPress && + event->xbutton.button == Button1) + { + qs->button_down_p = True; + gltrackball_start (qs->trackball, + event->xbutton.x, event->xbutton.y, + MI_WIDTH (mi), MI_HEIGHT (mi)); + return True; + } + else if (event->xany.type == ButtonRelease && + event->xbutton.button == Button1) + { + qs->button_down_p = False; + return True; + } + else if (event->xany.type == ButtonPress && + (event->xbutton.button == Button4 || + event->xbutton.button == Button5 || + event->xbutton.button == Button6 || + event->xbutton.button == Button7)) + { + gltrackball_mousewheel (qs->trackball, event->xbutton.button, 5, + !event->xbutton.state); + return True; + } + else if (event->xany.type == MotionNotify && + qs->button_down_p) + { + gltrackball_track (qs->trackball, + event->xmotion.x, event->xmotion.y, + MI_WIDTH (mi), MI_HEIGHT (mi)); + return True; + } + + return False; +} + + + +/* returns true if placing a queen on column c causes a conflict */ +static int conflictsCols(Queenscreen *qs, int c) +{ + int i; + + for(i = 0; i < qs->BOARDSIZE; ++i) + if(qs->board[i][c]) + return 1; + + return 0; +} + +/* returns true if placing a queen on (r,c) causes a diagonal conflict */ +static int conflictsDiag(Queenscreen *qs, int r, int c) +{ + int i; + + /* positive slope */ + int n = r < c ? r : c; + for(i = 0; i < qs->BOARDSIZE-abs(r-c); ++i) + if(qs->board[r-n+i][c-n+i]) + return 1; + + /* negative slope */ + n = r < qs->BOARDSIZE - (c+1) ? r : qs->BOARDSIZE - (c+1); + for(i = 0; i < qs->BOARDSIZE-abs(qs->BOARDSIZE - (1+r+c)); ++i) + if(qs->board[r-n+i][c+n-i]) + return 1; + + return 0; +} + +/* returns true if placing a queen at (r,c) causes a conflict */ +static int conflicts(Queenscreen *qs, int r, int c) +{ + return !conflictsCols(qs, c) ? conflictsDiag(qs, r, c) : 1; +} + +/* clear board */ +static void blank(Queenscreen *qs) +{ + int i, j; + + for(i = 0; i < MAXBOARD; ++i) + for(j = 0; j < MAXBOARD; ++j) + qs->board[i][j] = NONE; +} + +/* recursively determine solution */ +static int findSolution(Queenscreen *qs, int row, int col) +{ + if(row == qs->BOARDSIZE) + return 1; + + while(col < qs->BOARDSIZE) { + if(!conflicts(qs, row, col)) { + qs->board[row][col] = 1; + + if(findSolution(qs, row+1, 0)) + return 1; + + qs->board[row][col] = 0; + } + + ++col; + } + + return 0; +} + +/** driver for finding solution */ +static void go(Queenscreen *qs) { while(!findSolution(qs, 0, random()%qs->BOARDSIZE)); } + +/* lighting variables */ +static const GLfloat front_shininess[] = {60.0}; +static const GLfloat front_specular[] = {0.4, 0.4, 0.4, 1.0}; +static const GLfloat ambient[] = {0.3, 0.3, 0.3, 1.0}; +static const GLfloat diffuse[] = {0.8, 0.8, 0.8, 1.0}; + +/* configure lighting */ +static void setup_lights(Queenscreen *qs) +{ + + /* setup twoside lighting */ + glLightfv(GL_LIGHT0, GL_AMBIENT, ambient); + glLightfv(GL_LIGHT0, GL_DIFFUSE, diffuse); + glLightfv(GL_LIGHT0, GL_POSITION, qs->position); + glEnable(GL_LIGHTING); + glEnable(GL_LIGHT0); + + /* setup material properties */ + glMaterialfv(GL_FRONT_AND_BACK, GL_SHININESS, front_shininess); + glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, front_specular); + + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); +} + +#define checkImageWidth 8 +#define checkImageHeight 8 +/*static GLubyte checkImage[checkImageWidth][checkImageHeight][3];*/ + +/* return alpha value for fading */ +static GLfloat findAlpha(Queenscreen *qs) +{ + return qs->steps < 128 ? qs->steps/128.0 : qs->steps < 1024-128 ?1.0:(1024-qs->steps)/128.0; +} + +/* draw pieces */ +static int drawPieces(Queenscreen *qs) +{ + int i, j; + int polys = 0; + + for(i = 0; i < qs->BOARDSIZE; ++i) { + for(j = 0; j < qs->BOARDSIZE; ++j) { + if(qs->board[i][j]) { + glColor3fv(colors[qs->colorset][i%2]); + glCallList(qs->queen_list); + polys += qs->queen_polys; + } + + glTranslatef(1.0, 0.0, 0.0); + } + + glTranslatef(-1.0*qs->BOARDSIZE, 0.0, 1.0); + } + return polys; +} + +/** reflectionboard */ +static int draw_reflections(Queenscreen *qs) +{ + int i, j; + int polys = 0; + + glEnable(GL_STENCIL_TEST); + glStencilFunc(GL_ALWAYS, 1, 1); + glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE); + glColorMask(0,0,0,0); + glDisable(GL_CULL_FACE); + + glDisable(GL_DEPTH_TEST); + glBegin(GL_QUADS); + + /* only draw white squares */ + for(i = 0; i < qs->BOARDSIZE; ++i) { + for(j = (qs->BOARDSIZE+i) % 2; j < qs->BOARDSIZE; j += 2) { + glVertex3f(i, 0.0, j + 1.0); + glVertex3f(i + 1.0, 0.0, j + 1.0); + glVertex3f(i + 1.0, 0.0, j); + glVertex3f(i, 0.0, j); + polys++; + } + } + glEnd(); + glEnable(GL_DEPTH_TEST); + + glColorMask(1, 1, 1, 1); + glStencilFunc(GL_EQUAL, 1, 1); + glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP); + + glPushMatrix(); + glScalef(1.0, -1.0, 1.0); + glTranslatef(0.5, 0.001, 0.5); + glLightfv(GL_LIGHT0, GL_POSITION, qs->position); + polys += drawPieces(qs); + glPopMatrix(); + glDisable(GL_STENCIL_TEST); + + /* replace lights */ + glLightfv(GL_LIGHT0, GL_POSITION, qs->position); + + glEnable(GL_CULL_FACE); + glCullFace(GL_BACK); + glColorMask(1,1,1,1); + return polys; +} + +/* draw board */ +static int drawBoard(Queenscreen *qs) +{ + int i, j; + int polys = 0; + + glBegin(GL_QUADS); + + for(i = 0; i < qs->BOARDSIZE; ++i) + for(j = 0; j < qs->BOARDSIZE; ++j) { + int par = (i-j+qs->BOARDSIZE)%2; + glColor4f(colors[qs->colorset][par][0], + colors[qs->colorset][par][1], + colors[qs->colorset][par][2], + 0.70); + glNormal3f(0.0, 1.0, 0.0); + glVertex3f(i, 0.0, j + 1.0); + glVertex3f(i + 1.0, 0.0, j + 1.0); + glVertex3f(i + 1.0, 0.0, j); + glVertex3f(i, 0.0, j); + polys++; + } + + glEnd(); + + { + GLfloat off = 0.01; + GLfloat w = qs->BOARDSIZE; + GLfloat h = 0.1; + + /* Give the board a slight lip. */ + /* #### oops, normals are wrong here, but you can't tell */ + + glColor3f(0.3, 0.3, 0.3); + glBegin (GL_QUADS); + glVertex3f (0, 0, 0); + glVertex3f (0, -h, 0); + glVertex3f (0, -h, w); + glVertex3f (0, 0, w); + + glVertex3f (0, 0, w); + glVertex3f (0, -h, w); + glVertex3f (w, -h, w); + glVertex3f (w, 0, w); + + glVertex3f (w, 0, w); + glVertex3f (w, -h, w); + glVertex3f (w, -h, 0); + glVertex3f (w, 0, 0); + + glVertex3f (w, 0, 0); + glVertex3f (w, -h, 0); + glVertex3f (0, -h, 0); + glVertex3f (0, 0, 0); + + glVertex3f (0, -h, 0); + glVertex3f (w, -h, 0); + glVertex3f (w, -h, w); + glVertex3f (0, -h, w); + glEnd(); + polys += 4; + + /* Fill in the underside of the board with an invisible black box + to hide the reflections that are not on tiles. Probably there's + a way to do this with stencils instead. + */ + w -= off*2; + h = 5; + + glPushMatrix(); + glTranslatef (off, 0, off); + glDisable(GL_LIGHTING); + glColor3f(0,0,0); + glBegin (GL_QUADS); + glVertex3f (0, 0, 0); + glVertex3f (0, -h, 0); + glVertex3f (0, -h, w); + glVertex3f (0, 0, w); + + glVertex3f (0, 0, w); + glVertex3f (0, -h, w); + glVertex3f (w, -h, w); + glVertex3f (w, 0, w); + + glVertex3f (w, 0, w); + glVertex3f (w, -h, w); + glVertex3f (w, -h, 0); + glVertex3f (w, 0, 0); + + glVertex3f (w, 0, 0); + glVertex3f (w, -h, 0); + glVertex3f (0, -h, 0); + glVertex3f (0, 0, 0); + + glVertex3f (0, -h, 0); + glVertex3f (w, -h, 0); + glVertex3f (w, -h, w); + glVertex3f (0, -h, w); + glEnd(); + polys += 4; + glPopMatrix(); + if (!wire) + glEnable(GL_LIGHTING); + } + + return polys; +} + +static int display(Queenscreen *qs) +{ + int max = 1024; + int polys = 0; + glClear(clearbits); + + glMatrixMode(GL_MODELVIEW); + glLoadIdentity(); + + glRotatef(current_device_rotation(), 0, 0, 1); + + /* setup light attenuation */ + /* #### apparently this does nothing */ + glEnable(GL_COLOR_MATERIAL); + glLightf(GL_LIGHT0, GL_CONSTANT_ATTENUATION, 0.8/(0.01+findAlpha(qs))); + glLightf(GL_LIGHT0, GL_LINEAR_ATTENUATION, 0.06); + + /** setup perspective */ + glTranslatef(0.0, 0.0, -1.5*qs->BOARDSIZE); + glRotatef(30.0, 1.0, 0.0, 0.0); + gltrackball_rotate (qs->trackball); + glRotatef(qs->theta*100, 0.0, 1.0, 0.0); + glTranslatef(-0.5*qs->BOARDSIZE, 0.0, -0.5*qs->BOARDSIZE); + + /* find light positions */ + qs->position[0] = qs->BOARDSIZE/2.0 + qs->BOARDSIZE/1.4*-sin(qs->theta*100*M_PI/180.0); + qs->position[2] = qs->BOARDSIZE/2.0 + qs->BOARDSIZE/1.4*cos(qs->theta*100*M_PI/180.0); + qs->position[1] = 6.0; + + if(!wire) { + glEnable(GL_LIGHTING); + glLightfv(GL_LIGHT0, GL_POSITION, qs->position); + glEnable(GL_LIGHT0); + } + + /* Since the lighting attenuation trick up there doesn't seem to be working, + let's drop the old board down and drop the new board in. */ + if (qs->steps < (max/8.0)) { + GLfloat y = qs->steps / (max/8.0); + y = sin (M_PI/2 * y); + glTranslatef (0, 10 - (y * 10), 0); + } else if (qs->steps > max-(max/8.0)) { + GLfloat y = (qs->steps - (max-(max/8.0))) / (GLfloat) (max/8.0); + y = 1 - sin (M_PI/2 * (1-y)); + glTranslatef (0, -y * 15, 0); + } + + /* draw reflections */ + if(!wire) { + polys += draw_reflections(qs); + glEnable(GL_BLEND); + } + polys += drawBoard(qs); + if(!wire) + glDisable(GL_BLEND); + + glLightf(GL_LIGHT0, GL_LINEAR_ATTENUATION, 0.1); + + glTranslatef(0.5, 0.0, 0.5); + polys += drawPieces(qs); + + /* rotate camera */ + if(!qs->button_down_p) + qs->theta += .002; + + /* zero out board, find new solution of size MINBOARD <= i <= MAXBOARD */ + if(++qs->steps == max) { + qs->steps = 0; + blank(qs); + qs->BOARDSIZE = MINBOARD + (random() % (MAXBOARD - MINBOARD + 1)); + qs->colorset = (qs->colorset+1)%COLORSETS; + go(qs); + } + return polys; +} + +static const GLfloat spidermodel[][3] = + { + {0.48, 0.48, 0.22}, + {0.48, 0.34, 0.18}, + {0.34, 0.34, 0.10}, + {0.34, 0.18, 0.30}, + {0.18, 0.14, 0.38}, + {0.14, 0.29, 0.01}, + {0.29, 0.18, 0.18}, + {0.18, 0.18, 0.16}, + {0.18, 0.20, 0.26}, + {0.20, 0.27, 0.14}, + {0.27, 0.24, 0.08}, + {0.24, 0.17, 0.00}, + {0.17, 0.095, 0.08}, + {0.095, 0.07, 0.00}, + {0.07, 0.00, 0.12}, + }; + + +#define EPSILON 0.001 + +#if 0 +/** draws cylindermodel */ +static int draw_model(int chunks, const GLfloat model[][3], int r) +{ + int i = 0; + int polys = 0; + glPushMatrix(); + glRotatef(-90.0, 1.0, 0.0, 0.0); + + for(i = 0; i < chunks; ++i) { + if(model[i][0] > EPSILON || model[i][1] > EPSILON) { + polys += tube (0, 0, 0, + 0, 0, model[i][1], + model[i][0], 0, + r, False, False, False); +/* gluCylinder(quadric, model[i][0], model[i][1], model[i][2], r, 1); + polys += r;*/ + } + glTranslatef(0.0, 0.0, model[i][2]); + } + + glPopMatrix(); + return polys; +} +#endif + +ENTRYPOINT void reshape_queens(ModeInfo *mi, int width, int height) +{ + GLfloat h = (GLfloat) height / (GLfloat) width; + glViewport(0,0, width, height); + glMatrixMode(GL_PROJECTION); + glLoadIdentity(); + gluPerspective(45, 1/h, 2.0, 30.0); + glMatrixMode(GL_MODELVIEW); +} + +ENTRYPOINT void init_queens(ModeInfo *mi) +{ + int screen = MI_SCREEN(mi); + Queenscreen *qs; + int poly_counts[PIECES]; + wire = MI_IS_WIREFRAME(mi); + +# ifdef HAVE_JWZGLES /* #### glPolygonMode other than GL_FILL unimplemented */ + wire = 0; +# endif + + if(!qss && + !(qss = (Queenscreen *) calloc(MI_NUM_SCREENS(mi), sizeof(Queenscreen)))) + return; + + qs = &qss[screen]; + qs->window = MI_WINDOW(mi); + + if((qs->glx_context = init_GL(mi))) + reshape_queens(mi, MI_WIDTH(mi), MI_HEIGHT(mi)); + else + MI_CLEARWINDOW(mi); + + qs->trackball = gltrackball_init (); + + qs->BOARDSIZE = 8; /* 8 cuz its classic */ + + chessmodels_gen_lists(-1, poly_counts); + qs->queen_list = QUEEN; + qs->queen_polys = poly_counts[QUEEN]; + + /* find a solution */ + go(qs); +} + +ENTRYPOINT void draw_queens(ModeInfo *mi) +{ + Queenscreen *qs = &qss[MI_SCREEN(mi)]; + Window w = MI_WINDOW(mi); + Display *disp = MI_DISPLAY(mi); + + if(!qs->glx_context) + return; + + glXMakeCurrent(disp, w, *(qs->glx_context)); + + if(flat) + glShadeModel(GL_FLAT); + + clearbits = GL_COLOR_BUFFER_BIT; + + glColorMaterial(GL_FRONT, GL_DIFFUSE); + glEnable(GL_COLOR_MATERIAL); + + if(!wire) { + setup_lights(qs); + glEnable(GL_DEPTH_TEST); + clearbits |= GL_DEPTH_BUFFER_BIT; + clearbits |= GL_STENCIL_BUFFER_BIT; + glEnable(GL_CULL_FACE); + glCullFace(GL_BACK); + } + else + glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); + + mi->polygon_count = display(qs); + mi->recursion_depth = qs->BOARDSIZE; + + if(mi->fps_p) do_fps(mi); + glFinish(); + glXSwapBuffers(disp, w); +} + +ENTRYPOINT void release_queens(ModeInfo *mi) +{ + if(qss) + free((void *) qss); + qss = 0; + + FreeAllGL(mi); +} + +XSCREENSAVER_MODULE ("Queens", queens) + +#endif diff --git a/hacks/glx/queens.man b/hacks/glx/queens.man new file mode 100644 index 00000000..47fc3f4c --- /dev/null +++ b/hacks/glx/queens.man @@ -0,0 +1,66 @@ +.TH XScreenSaver 1 "May 2002" +.SH NAME +queens \- n queens screensaver +.SH SYNOPSIS +.B queens +[\-display \fIhost:display.screen\fP] +[\-window] +[\-root] +[\-install] +[\-visual \fIvisual\fP] +[\-delay \fImicroseconds\fP] +[\-wireframe] +[\-fps] +.SH DESCRIPTION +The \fIqueens\fP program solves the n-queens problem (where, in this +program, N is between 5 and 10 queens) using a straightforward +backtracking algorithm. The problem is: how may one place N queens +on an NxN chessboard such that no queen can attack a sister? +.SH OPTIONS +.I queens +accepts the following options: +.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 \-install +Install a private colormap for the window. +.TP 8 +.B \-visual \fIvisual\fP\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 \-wireframe +Render in wireframe instead of solid. +.B \-fps +Display the current frame rate, CPU load, and polygon count. +.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 BUGS +It's not unknown for this and other OpenGL hacks to fail under hardware accelaration (UtahGLX) and take the X server with them. Texture images must be 16x16 or 32x32 or 64x64 etc. +.SH SEE ALSO +.BR X (1), +.BR xscreensaver (1) +.BR xscreensaver\-demo (1), +.BR xscreensaver\-getimage (1) +.SH COPYRIGHT +Copyright \(co 2002 by Blair Tennessy. 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 +Blair Tennessy , 20-April-2002. + diff --git a/hacks/glx/rotator.c b/hacks/glx/rotator.c new file mode 100644 index 00000000..89fa6ffd --- /dev/null +++ b/hacks/glx/rotator.c @@ -0,0 +1,247 @@ +/* xscreensaver, Copyright (c) 1998-2002 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. + */ + +#include + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include +#include +#include "rotator.h" +#include "yarandom.h" + +struct rotator { + + double spin_x_speed, spin_y_speed, spin_z_speed; + double wander_speed; + + double rotx, roty, rotz; /* current object rotation */ + double dx, dy, dz; /* current rotational velocity */ + double ddx, ddy, ddz; /* current rotational acceleration */ + double d_max; /* max rotational velocity */ + + int wander_frame; /* position in the wander cycle */ + +}; + + +#undef ABS +#define ABS(x) ((x)<0?-(x):(x)) + +#define BELLRAND(n) ((frand((n)) + frand((n)) + frand((n))) / 3) +#define RANDSIGN() ((random() & 1) ? 1 : -1) + +static void +rotate_1 (double *pos, double *v, double *dv, double speed, double max_v) +{ + double ppos = *pos; + + if (speed == 0) return; + + /* tick position */ + if (ppos < 0) + ppos = -(ppos + *v); + else + ppos += *v; + + if (ppos > 1.0) + ppos -= 1.0; + else if (ppos < 0) + ppos += 1.0; + + if (ppos < 0) abort(); + if (ppos > 1.0) abort(); + *pos = (*pos > 0 ? ppos : -ppos); + + /* accelerate */ + *v += *dv; + + /* clamp velocity */ + if (*v > max_v || *v < -max_v) + { + *dv = -*dv; + } + /* If it stops, start it going in the other direction. */ + else if (*v < 0) + { + if (random() % 4) + { + *v = 0; + + /* keep going in the same direction */ + if (random() % 2) + *dv = 0; + else if (*dv < 0) + *dv = -*dv; + } + else + { + /* reverse gears */ + *v = -*v; + *dv = -*dv; + *pos = -*pos; + } + } + + /* Alter direction of rotational acceleration randomly. */ + if (! (random() % 120)) + *dv = -*dv; + + /* Change acceleration very occasionally. */ + if (! (random() % 200)) + { + if (*dv == 0) + *dv = 0.00001; + else if (random() & 1) + *dv *= 1.2; + else + *dv *= 0.8; + } +} + + +/* Returns a rotator object, which encapsulates rotation and motion state. + + spin_[xyz]_speed indicates the relative speed of rotation. + Specify 0 if you don't want any rotation around that axis. + + spin_accel specifies a scaling factor for the acceleration that is + randomly applied to spin: if you want the speed to change faster, + make this > 1. + + wander_speed indicates the relative speed through space. + + If randomize_initial_state_p is true, then the initial position and + rotation will be randomized (even if the spin speeds are 0.) If it + is false, then all values will be initially zeroed. + */ +rotator * +make_rotator (double spin_x_speed, + double spin_y_speed, + double spin_z_speed, + double spin_accel, + double wander_speed, + int randomize_initial_state_p) +{ + rotator *r = (rotator *) calloc (1, sizeof(*r)); + double d, dd; + + if (!r) return 0; + + if (spin_x_speed < 0 || spin_y_speed < 0 || spin_z_speed < 0 || + wander_speed < 0) + abort(); + + r->spin_x_speed = spin_x_speed; + r->spin_y_speed = spin_y_speed; + r->spin_z_speed = spin_z_speed; + r->wander_speed = wander_speed; + + if (randomize_initial_state_p) + { + r->rotx = frand(1.0) * RANDSIGN(); + r->roty = frand(1.0) * RANDSIGN(); + r->rotz = frand(1.0) * RANDSIGN(); + + r->wander_frame = random() % 0xFFFF; + } + else + { + r->rotx = r->roty = r->rotz = 0; + r->wander_frame = 0; + } + + d = 0.006; + dd = 0.00006; + + r->dx = BELLRAND(d * r->spin_x_speed); + r->dy = BELLRAND(d * r->spin_y_speed); + r->dz = BELLRAND(d * r->spin_z_speed); + + r->d_max = r->dx * 2; + + r->ddx = (dd + frand(dd+dd)) * r->spin_x_speed * spin_accel; + r->ddy = (dd + frand(dd+dd)) * r->spin_y_speed * spin_accel; + r->ddz = (dd + frand(dd+dd)) * r->spin_z_speed * spin_accel; + +# if 0 + fprintf (stderr, "rotator:\n"); + fprintf (stderr, " wander: %3d %6.2f\n", r->wander_frame, r->wander_speed); + fprintf (stderr, " speed: %6.2f %6.2f %6.2f\n", + r->spin_x_speed, r->spin_y_speed, r->spin_z_speed); + fprintf (stderr, " rot: %6.2f %6.2f %6.2f\n", + r->rotx, r->roty, r->rotz); + fprintf (stderr, " d: %6.2f %6.2f %6.2f, %6.2f\n", + r->dx, r->dy, r->dz, + r->d_max); + fprintf (stderr, " dd: %6.2f %6.2f %6.2f\n", + r->ddx, r->ddy, r->ddz); +# endif + + return r; +} + + +void +free_rotator (rotator *r) +{ + free (r); +} + +void +get_rotation (rotator *rot, double *x_ret, double *y_ret, double *z_ret, + int update_p) +{ + double x, y, z; + + if (update_p) { + rotate_1 (&rot->rotx, &rot->dx, &rot->ddx, rot->spin_x_speed, rot->d_max); + rotate_1 (&rot->roty, &rot->dy, &rot->ddy, rot->spin_y_speed, rot->d_max); + rotate_1 (&rot->rotz, &rot->dz, &rot->ddz, rot->spin_z_speed, rot->d_max); + } + + x = rot->rotx; + y = rot->roty; + z = rot->rotz; + if (x < 0) x = 1 - (x + 1); + if (y < 0) y = 1 - (y + 1); + if (z < 0) z = 1 - (z + 1); + + if (x_ret) *x_ret = x; + if (y_ret) *y_ret = y; + if (z_ret) *z_ret = z; +} + + +void +get_position (rotator *rot, double *x_ret, double *y_ret, double *z_ret, + int update_p) +{ + double x = 0.5, y = 0.5, z = 0.5; + + if (rot->wander_speed != 0) + { + if (update_p) + rot->wander_frame++; + +# define SINOID(F) ((1 + sin((rot->wander_frame * (F)) / 2 * M_PI)) / 2.0) + x = SINOID (0.71 * rot->wander_speed); + y = SINOID (0.53 * rot->wander_speed); + z = SINOID (0.37 * rot->wander_speed); +# undef SINOID + } + + if (x_ret) *x_ret = x; + if (y_ret) *y_ret = y; + if (z_ret) *z_ret = z; +} diff --git a/hacks/glx/rotator.h b/hacks/glx/rotator.h new file mode 100644 index 00000000..b3f36f68 --- /dev/null +++ b/hacks/glx/rotator.h @@ -0,0 +1,60 @@ +/* xscreensaver, Copyright (c) 1998-2002 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. + */ + +#ifndef __ROTATOR_H__ +#define __ROTATOR_H__ + +typedef struct rotator rotator; + +/* Returns a rotator object, which encapsulates rotation and motion state. + + spin_[xyz]_speed indicates the relative speed of rotation. + Specify 0 if you don't want any rotation around that axis. + + spin_accel specifies a scaling factor for the acceleration that is + randomly applied to spin: if you want the speed to change faster, + make this > 1. + + wander_speed indicates the relative speed through space. + + If randomize_initial_state_p is true, then the initial position and + rotation will be randomized (even if the spin speeds are 0.) If it + is false, then all values will be initially zeroed. + */ +extern rotator *make_rotator (double spin_x_speed, + double spin_y_speed, + double spin_z_speed, + double spin_accel, + double wander_speed, + int randomize_initial_state_p); + +/* Rotates one step, and returns the new rotation values. + x, y, and z range from 0.0-1.0, the fraction through the circle + (*not* radians or degrees!) + If `update_p' is non-zero, then (maybe) rotate first. + */ +extern void get_rotation (rotator *rot, + double *x_ret, double *y_ret, double *z_ret, + int update_p); + +/* Moves one step, and returns the new position values. + x, y, and z range from 0.0-1.0, the fraction through space: + scale those values as needed. + If `update_p' is non-zero, then (maybe) move first. + */ +extern void get_position (rotator *rot, + double *x_ret, double *y_ret, double *z_ret, + int update_p); + +/* Destroys and frees a `rotator' object. */ +extern void free_rotator (rotator *r); + +#endif /* __ROTATOR_H__ */ diff --git a/hacks/glx/rubik.c b/hacks/glx/rubik.c new file mode 100644 index 00000000..20ced973 --- /dev/null +++ b/hacks/glx/rubik.c @@ -0,0 +1,2167 @@ +/* -*- Mode: C; tab-width: 4 -*- */ +/* rubik --- Shows an auto-solving Rubik's cube */ + +#if 0 +static const char sccsid[] = "@(#)rubik.c 5.01 2001/03/01 xlockmore"; +#endif + +/*- + * Permission to use, copy, modify, and distribute this software and its + * documentation for any purpose and without fee is hereby granted, + * provided that the above copyright notice appear in all copies and that + * both that copyright notice and this permission notice appear in + * supporting documentation. + * + * This file is provided AS IS with no warranties of any kind. The author + * shall have no liability with respect to the infringement of copyrights, + * trade secrets or any patents by this file or any part thereof. In no + * event will the author be liable for any lost revenue or profits or + * other special, indirect and consequential damages. + * + * This mode shows an auto-solving rubik's cube "puzzle". If somebody + * intends to make a game or something based on this code, please let me + * know first, my e-mail address is provided in this comment. Marcelo. + * + * Thanks goes also to Brian Paul for making it possible and inexpensive + * to use OpenGL at home. + * + * Since I'm not a native English speaker, my apologies for any grammatical + * mistakes. + * + * My e-mail address is + * mfvianna@centroin.com.br + * + * Marcelo F. Vianna (Jul-31-1997) + * + * Revision History: + * 05-Apr-2002: Removed all gllist uses (fix some bug with nvidia driver) + * 01-Mar-2001: Added FPS stuff - Eric Lassauge + * 01-Nov-2000: Allocation checks + * 27-Apr-1999: LxMxN stuff added. + * 26-Sep-1998: Added some more movement (the cube does not stay in the screen + * center anymore. Also fixed the scale problem immediately after + * shuffling when the puzzle is solved. + * 08-Aug-1997: Now has some internals from xrubik by David Bagley + * This should make it easier to add features. + * 02-Aug-1997: Now behaves more like puzzle.c: first show the cube being + * shuffled and then being solved. A mode specific option was + * added: + * "+/-hideshuffling" to provide the original behavior (in which + * only the solution is shown). + * The color labels corners are now rounded. + * Optimized the cubit() routine using glLists. + * 01-Aug-1997: Shuffling now avoids movements that undoes the previous + * movement and three consecutive identical moves (which is + * pretty stupid). + * improved the "cycles" option in replacement of David's hack, + * now rp->anglestep is a GLfloat, so this option selects the + * "exact" number of frames that a rotation (movement) takes to + * complete. + * 30-Jul-1997: Initial release, there is no algorithm to solve the puzzle, + * instead, it randomly shuffle the cube and then make the + * movements in the reverse order. + * The mode was written in 1 day (I got sick and had the day off). + * There was not much to do since I could not leave home... :) + */ + +/*- + * Color labels mapping: + * ===================== + * + * +-----------+ + * |0--> | + * || | + * |v TOP(0) | + * | | + * | 8| + * +-----------+-----------+-----------+ + * |0--> |0--> |0--> | + * || || || | + * |v LEFT(1) |v FRONT(2) |v RIGHT(3) | + * | | | | + * | 8| 8| 8| + * +-----------+-----------+-----------+ + * |0--> | + * || | + * |v BOTTOM(4)| + * | | + * | 8| + * +-----------+ +---+---+---+ + * |0--> | | 0 | 1 | 2 | + * || | |--xxxxx(N)-+ + * |v BACK(5) | | 3 | 4 | 5 | + * | | +---+---+---+ + * | 8| | 6 | 7 | 8 | + * +-----------+ +---+---+---+ + * + * Map to 3d + * FRONT => X, Y + * BACK => X, Y + * LEFT => Z, Y + * RIGHT => Z, Y + * TOP => X, Z + * BOTTOM => X, Z + */ + +#ifdef STANDALONE +# define MODE_rubik +# define DEFAULTS "*delay: 20000 \n" \ + "*count: -30 \n" \ + "*showFPS: False \n" \ + "*cycles: 20 \n" \ + "*size: -6 \n" +# define refresh_rubik 0 +# include "xlockmore.h" /* from the xscreensaver distribution */ +#else /* !STANDALONE */ +# include "xlock.h" /* from the xlockmore distribution */ +# include "vis.h" +#endif /* !STANDALONE */ + +#include "gltrackball.h" + +#ifdef MODE_rubik + +#define DEF_SIZEX "0" +#define DEF_SIZEY "0" +#define DEF_SIZEZ "0" +#define DEF_HIDESHUFFLING "False" + +static int sizex; +static int sizey; +static int sizez; +static Bool hideshuffling; + +static XrmOptionDescRec opts[] = +{ + {"-sizex", ".rubik.sizex", XrmoptionSepArg, 0}, + {"-sizey", ".rubik.sizey", XrmoptionSepArg, 0}, + {"-sizez", ".rubik.sizez", XrmoptionSepArg, 0}, + {"-hideshuffling", ".rubik.hideshuffling", XrmoptionNoArg, "on"}, + {"+hideshuffling", ".rubik.hideshuffling", XrmoptionNoArg, "off"} +}; + +static argtype vars[] = +{ + {&sizex, "sizex", "SizeX", DEF_SIZEX, t_Int}, + {&sizey, "sizey", "SizeY", DEF_SIZEY, t_Int}, + {&sizez, "sizez", "SizeZ", DEF_SIZEZ, t_Int}, + {&hideshuffling, "hideshuffling", "Hideshuffling", DEF_HIDESHUFFLING, t_Bool} +}; + +static OptionStruct desc[] = +{ + {"-sizex num", "number of cubies along x axis (overrides size)"}, + {"-sizey num", "number of cubies along y axis (overrides size)"}, + {"-sizez num", "number of cubies along z axis (overrides size)"}, + {"-/+hideshuffling", "turn on/off hidden shuffle phase"} +}; + +ENTRYPOINT ModeSpecOpt rubik_opts = +{sizeof opts / sizeof opts[0], opts, sizeof vars / sizeof vars[0], vars, desc}; + +#ifdef USE_MODULES +ModStruct rubik_description = +{"rubik", "init_rubik", "draw_rubik", "release_rubik", + "draw_rubik", "change_rubik", (char *) NULL, &rubik_opts, + 10000, -30, 5, -6, 64, 1.0, "", + "Shows an auto-solving Rubik's Cube", 0, NULL}; + +#endif + +#define VectMul(X1,Y1,Z1,X2,Y2,Z2) (Y1)*(Z2)-(Z1)*(Y2),(Z1)*(X2)-(X1)*(Z2),(X1)*(Y2)-(Y1)*(X2) +#define sqr(A) ((A)*(A)) + +#ifndef Pi +#define Pi M_PI +#endif + + +#define ACTION_SOLVE 1 +#define ACTION_SHUFFLE 0 + +#define DELAY_AFTER_SHUFFLING 5 +#define DELAY_AFTER_SOLVING 20 + +/*************************************************************************/ + +#define MINSIZE 2 +#define MAXSIZEX (rp->sizex) +#define MAXSIZEY (rp->sizey) +#define MAXSIZEZ (rp->sizez) +#define AVSIZE ((rp->sizex+rp->sizey+rp->sizez)/3.0) /* Use of this should be minimized */ +#define MAXMAXSIZE (MAX(MAXSIZEX,MAX(MAXSIZEY,MAXSIZEZ))) +#define MAXSIZEXY (MAXSIZEX*MAXSIZEY) +#define MAXSIZEYZ (MAXSIZEY*MAXSIZEZ) +#define MAXSIZEZX (MAXSIZEZ*MAXSIZEX) +#define LASTX (MAXSIZEX-1) +#define LASTY (MAXSIZEY-1) +#define LASTZ (MAXSIZEZ-1) +/* These are not likely to change but... */ +#define FIRSTX 0 +#define FIRSTY 0 +#define FIRSTZ 0 + +#define Scale4Window (0.9/AVSIZE) +#define Scale4Iconic (2.1/AVSIZE) + +#define MAXORIENT 4 /* Number of orientations of a square */ +#define MAXFACES 6 /* Number of faces */ + +/* Directions relative to the face of a cubie */ +#define TOP 0 +#define RIGHT 1 +#define BOTTOM 2 +#define LEFT 3 +#define CW (MAXORIENT+1) +#define HALF (MAXORIENT+2) +#define CCW (2*MAXORIENT-1) + +#define TOP_FACE 0 +#define LEFT_FACE 1 +#define FRONT_FACE 2 +#define RIGHT_FACE 3 +#define BOTTOM_FACE 4 +#define BACK_FACE 5 +#define NO_FACE (MAXFACES) +#define NO_ROTATION (2*MAXORIENT) +#define NO_DEPTH MAXMAXSIZE + +#define REVX(a) (MAXSIZEX - a - 1) +#define REVY(a) (MAXSIZEY - a - 1) +#define REVZ(a) (MAXSIZEZ - a - 1) + +#define CUBELEN 0.50 +#define CUBEROUND (CUBELEN-0.05) +#define STICKERLONG (CUBEROUND-0.05) +#define STICKERSHORT (STICKERLONG-0.05) +#define STICKERDEPTH (CUBELEN+0.01) + +#define ObjCubit 0 +#define MaxObj 1 +typedef struct _RubikLoc { + int face; + int rotation; /* Not used yet */ +} RubikLoc; + +typedef struct _RubikRowNext { + int face, direction, sideFace; +} RubikRowNext; + +typedef struct _RubikMove { + int face, direction; + int position; +} RubikMove; + +typedef struct _RubikSlice { + int face, rotation; + int depth; +} RubikSlice; + +/*- + * Pick a face and a direction on face the next face and orientation + * is then known. + */ +static const RubikLoc slideNextRow[MAXFACES][MAXORIENT] = +{ + { + {5, TOP}, + {3, RIGHT}, + {2, TOP}, + {1, LEFT}}, + { + {0, RIGHT}, + {2, TOP}, + {4, LEFT}, + {5, BOTTOM}}, + { + {0, TOP}, + {3, TOP}, + {4, TOP}, + {1, TOP}}, + { + {0, LEFT}, + {5, BOTTOM}, + {4, RIGHT}, + {2, TOP}}, + { + {2, TOP}, + {3, LEFT}, + {5, TOP}, + {1, RIGHT}}, + { + {4, TOP}, + {3, BOTTOM}, + {0, TOP}, + {1, BOTTOM}} +}; + +/*- + * Examine cubie 0 on each face, its 4 movements (well only 2 since the + * other 2 will be opposites) and translate it into slice movements). + * CW = DEEP Depth CCW == SHALLOW Depth with reference to faces 0, 1, and 2 + */ +static const RubikLoc rotateSlice[MAXFACES][MAXORIENT / 2] = +{ + { + {1, CCW}, + {2, CW}, + }, + { + {2, CW}, + {0, CCW}, + }, + { + {1, CCW}, + {0, CCW}, + }, + { + {2, CCW}, + {0, CCW}, + }, + { + {1, CCW}, + {2, CCW}, + }, + { + {1, CCW}, + {0, CW}, + } +}; + +/*- + * Rotate face clockwise by a number of orients, then the top of the + * face then points to this face + */ +static const int rowToRotate[MAXFACES][MAXORIENT] = +{ + {3, 2, 1, 5}, + {2, 4, 5, 0}, + {3, 4, 1, 0}, + {5, 4, 2, 0}, + {3, 5, 1, 2}, + {3, 0, 1, 4} +}; + +/* + * This translates a clockwise move to something more manageable + */ +static const RubikRowNext rotateToRow[MAXFACES] = /*CW to min face */ +{ + {1, LEFT, TOP}, + {0, BOTTOM, RIGHT}, + {0, RIGHT, BOTTOM}, + {0, TOP, LEFT}, + {1, RIGHT, BOTTOM}, + {0, LEFT, TOP} +}; + +typedef struct { + GLint WindH, WindW; + GLfloat step; + RubikMove *moves; + int storedmoves; + int degreeTurn; + int shufflingmoves; + int sizex, sizey, sizez; + float avsize, avsizeSq; + int action; + int done; + GLfloat anglestep; + RubikLoc *cubeLoc[MAXFACES]; + RubikLoc *rowLoc[MAXORIENT]; + RubikMove movement; + GLfloat rotatestep; + GLfloat PX, PY, VX, VY; + GLXContext *glx_context; + Bool button_down_p; + trackball_state *trackball; +} rubikstruct; + +static const float front_shininess[] = {60.0}; +static const float front_specular[] = {0.7, 0.7, 0.7, 1.0}; +static const float ambient[] = {0.0, 0.0, 0.0, 1.0}; +static const float diffuse[] = {1.0, 1.0, 1.0, 1.0}; +static const float position0[] = {1.0, 1.0, 1.0, 0.0}; +static const float position1[] = {-1.0, -1.0, 1.0, 0.0}; +static const float lmodel_ambient[] = {0.5, 0.5, 0.5, 1.0}; +static const float lmodel_twoside[] = {GL_TRUE}; + +static const float MaterialRed[] = {0.5, 0.0, 0.0, 1.0}; +static const float MaterialGreen[] = {0.0, 0.5, 0.0, 1.0}; +static const float MaterialBlue[] = {0.0, 0.0, 0.5, 1.0}; +static const float MaterialYellow[] = {0.7, 0.7, 0.0, 1.0}; +static const float MaterialOrange[] = {0.9, 0.45, 0.36, 1.0}; + +#if 0 +static float MaterialMagenta[] = {0.7, 0.0, 0.7, 1.0}; +static float MaterialCyan[] = {0.0, 0.7, 0.7, 1.0}; + +#endif +static const float MaterialWhite[] = {0.8, 0.8, 0.8, 1.0}; +static const float MaterialGray[] = {0.2, 0.2, 0.2, 1.0}; +static const float MaterialGray3[] = {0.3, 0.3, 0.3, 1.0}; +static const float MaterialGray4[] = {0.4, 0.4, 0.4, 1.0}; +static const float MaterialGray5[] = {0.5, 0.5, 0.5, 1.0}; +static const float MaterialGray6[] = {0.6, 0.6, 0.6, 1.0}; +static const float MaterialGray7[] = {0.7, 0.7, 0.7, 1.0}; + +static rubikstruct *rubik = (rubikstruct *) NULL; + + +static void +pickcolor(int C, int mono) +{ + switch (C) { + case TOP_FACE: + if (mono) + glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, MaterialGray3); + else + glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, MaterialRed); + break; + case LEFT_FACE: + if (mono) + glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, MaterialGray6); + else + glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, MaterialYellow); + break; + case FRONT_FACE: + glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, MaterialWhite); + break; + case RIGHT_FACE: + if (mono) + glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, MaterialGray4); + else + glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, MaterialGreen); + break; + case BOTTOM_FACE: + if (mono) + glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, MaterialGray7); + else + glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, MaterialOrange); + break; + case BACK_FACE: + if (mono) + glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, MaterialGray5); + else + glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, MaterialBlue); + break; +#if 0 + glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, MaterialCyan); + glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, MaterialMagenta); +#endif + } +} + +static void +faceSizes(rubikstruct * rp, int face, int * sizeOfRow, int * sizeOfColumn) +{ + switch (face) { + case 0: /* TOP */ + case 4: /* BOTTOM */ + *sizeOfRow = MAXSIZEX; + *sizeOfColumn = MAXSIZEZ; + break; + case 1: /* LEFT */ + case 3: /* RIGHT */ + *sizeOfRow = MAXSIZEZ; + *sizeOfColumn = MAXSIZEY; + break; + case 2: /* FRONT */ + case 5: /* BACK */ + *sizeOfRow = MAXSIZEX; + *sizeOfColumn = MAXSIZEY; + break; + } +} + +static Bool +checkFaceSquare(rubikstruct * rp, int face) +{ + int sizeOfRow, sizeOfColumn; + + faceSizes(rp, face, &sizeOfRow, &sizeOfColumn); + return (sizeOfRow == sizeOfColumn); + /* Cubes can be made square with a 4x2 face where 90 degree turns + * should be permitted but that is kind of complicated for me. + * This can be done in 2 ways where the side of the cubies are + * the same size and one where one side (the side with half the + * number of cubies) is twice the size of the other. The first is + * complicated because faces of cubies can go under other faces. + * The second way is similar to "banded cubes" where scotch tape + * restricts the moves of some cubes. Here you have to keep track + * of the restrictions and show banded cubies graphically as one + * cube. + */ +} + +static int +sizeFace(rubikstruct * rp, int face) +{ + int sizeOfRow, sizeOfColumn; + + faceSizes(rp, face, &sizeOfRow, &sizeOfColumn); + return (sizeOfRow * sizeOfColumn); +} + +static int +sizeRow(rubikstruct * rp, int face) +{ + int sizeOfRow, sizeOfColumn; /* sizeOfColumn not used */ + + faceSizes(rp, face, &sizeOfRow, &sizeOfColumn); + return sizeOfRow; +} + +static Bool +draw_stickerless_cubit(rubikstruct *rp, unsigned long *polysP) +{ + glBegin(GL_QUADS); + glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, MaterialGray); + /* Put sticker here */ + glNormal3f(0.00, 0.00, 1.00); + glVertex3f(-CUBEROUND, -CUBEROUND, CUBELEN); + glVertex3f(CUBEROUND, -CUBEROUND, CUBELEN); + glVertex3f(CUBEROUND, CUBEROUND, CUBELEN); + glVertex3f(-CUBEROUND, CUBEROUND, CUBELEN); + (*polysP)++; + glNormal3f(0.00, 0.00, -1.00); + glVertex3f(-CUBEROUND, CUBEROUND, -CUBELEN); + glVertex3f(CUBEROUND, CUBEROUND, -CUBELEN); + glVertex3f(CUBEROUND, -CUBEROUND, -CUBELEN); + glVertex3f(-CUBEROUND, -CUBEROUND, -CUBELEN); + (*polysP)++; + glNormal3f(-1.00, 0.00, 0.00); + glVertex3f(-CUBELEN, -CUBEROUND, CUBEROUND); + glVertex3f(-CUBELEN, CUBEROUND, CUBEROUND); + glVertex3f(-CUBELEN, CUBEROUND, -CUBEROUND); + glVertex3f(-CUBELEN, -CUBEROUND, -CUBEROUND); + (*polysP)++; + glNormal3f(1.00, 0.00, 0.00); + glVertex3f(CUBELEN, -CUBEROUND, -CUBEROUND); + glVertex3f(CUBELEN, CUBEROUND, -CUBEROUND); + glVertex3f(CUBELEN, CUBEROUND, CUBEROUND); + glVertex3f(CUBELEN, -CUBEROUND, CUBEROUND); + (*polysP)++; + glNormal3f(0.00, -1.00, 0.00); + glVertex3f(CUBEROUND, -CUBELEN, -CUBEROUND); + glVertex3f(CUBEROUND, -CUBELEN, CUBEROUND); + glVertex3f(-CUBEROUND, -CUBELEN, CUBEROUND); + glVertex3f(-CUBEROUND, -CUBELEN, -CUBEROUND); + (*polysP)++; + glNormal3f(0.00, 1.00, 0.00); + glVertex3f(-CUBEROUND, CUBELEN, -CUBEROUND); + glVertex3f(-CUBEROUND, CUBELEN, CUBEROUND); + glVertex3f(CUBEROUND, CUBELEN, CUBEROUND); + glVertex3f(CUBEROUND, CUBELEN, -CUBEROUND); + (*polysP)++; + + /* Edges of cubit */ + glNormal3f(-1.00, -1.00, 0.00); + glVertex3f(-CUBEROUND, -CUBELEN, -CUBEROUND); + glVertex3f(-CUBEROUND, -CUBELEN, CUBEROUND); + glVertex3f(-CUBELEN, -CUBEROUND, CUBEROUND); + glVertex3f(-CUBELEN, -CUBEROUND, -CUBEROUND); + (*polysP)++; + glNormal3f(1.00, 1.00, 0.00); + glVertex3f(CUBEROUND, CUBELEN, -CUBEROUND); + glVertex3f(CUBEROUND, CUBELEN, CUBEROUND); + glVertex3f(CUBELEN, CUBEROUND, CUBEROUND); + glVertex3f(CUBELEN, CUBEROUND, -CUBEROUND); + (*polysP)++; + glNormal3f(-1.00, 1.00, 0.00); + glVertex3f(-CUBELEN, CUBEROUND, -CUBEROUND); + glVertex3f(-CUBELEN, CUBEROUND, CUBEROUND); + glVertex3f(-CUBEROUND, CUBELEN, CUBEROUND); + glVertex3f(-CUBEROUND, CUBELEN, -CUBEROUND); + (*polysP)++; + glNormal3f(1.00, -1.00, 0.00); + glVertex3f(CUBELEN, -CUBEROUND, -CUBEROUND); + glVertex3f(CUBELEN, -CUBEROUND, CUBEROUND); + glVertex3f(CUBEROUND, -CUBELEN, CUBEROUND); + glVertex3f(CUBEROUND, -CUBELEN, -CUBEROUND); + (*polysP)++; + glNormal3f(0.00, -1.00, -1.00); + glVertex3f(-CUBEROUND, -CUBEROUND, -CUBELEN); + glVertex3f(CUBEROUND, -CUBEROUND, -CUBELEN); + glVertex3f(CUBEROUND, -CUBELEN, -CUBEROUND); + glVertex3f(-CUBEROUND, -CUBELEN, -CUBEROUND); + (*polysP)++; + glNormal3f(0.00, 1.00, 1.00); + glVertex3f(-CUBEROUND, CUBEROUND, CUBELEN); + glVertex3f(CUBEROUND, CUBEROUND, CUBELEN); + glVertex3f(CUBEROUND, CUBELEN, CUBEROUND); + glVertex3f(-CUBEROUND, CUBELEN, CUBEROUND); + (*polysP)++; + glNormal3f(0.00, -1.00, 1.00); + glVertex3f(-CUBEROUND, -CUBELEN, CUBEROUND); + glVertex3f(CUBEROUND, -CUBELEN, CUBEROUND); + glVertex3f(CUBEROUND, -CUBEROUND, CUBELEN); + glVertex3f(-CUBEROUND, -CUBEROUND, CUBELEN); + (*polysP)++; + glNormal3f(0.00, 1.00, -1.00); + glVertex3f(-CUBEROUND, CUBELEN, -CUBEROUND); + glVertex3f(CUBEROUND, CUBELEN, -CUBEROUND); + glVertex3f(CUBEROUND, CUBEROUND, -CUBELEN); + glVertex3f(-CUBEROUND, CUBEROUND, -CUBELEN); + (*polysP)++; + glNormal3f(-1.00, 0.00, -1.00); + glVertex3f(-CUBELEN, -CUBEROUND, -CUBEROUND); + glVertex3f(-CUBELEN, CUBEROUND, -CUBEROUND); + glVertex3f(-CUBEROUND, CUBEROUND, -CUBELEN); + glVertex3f(-CUBEROUND, -CUBEROUND, -CUBELEN); + (*polysP)++; + glNormal3f(1.00, 0.00, 1.00); + glVertex3f(CUBELEN, -CUBEROUND, CUBEROUND); + glVertex3f(CUBELEN, CUBEROUND, CUBEROUND); + glVertex3f(CUBEROUND, CUBEROUND, CUBELEN); + glVertex3f(CUBEROUND, -CUBEROUND, CUBELEN); + (*polysP)++; + glNormal3f(1.00, 0.00, -1.00); + glVertex3f(CUBEROUND, -CUBEROUND, -CUBELEN); + glVertex3f(CUBEROUND, CUBEROUND, -CUBELEN); + glVertex3f(CUBELEN, CUBEROUND, -CUBEROUND); + glVertex3f(CUBELEN, -CUBEROUND, -CUBEROUND); + (*polysP)++; + glNormal3f(-1.00, 0.00, 1.00); + glVertex3f(-CUBEROUND, -CUBEROUND, CUBELEN); + glVertex3f(-CUBEROUND, CUBEROUND, CUBELEN); + glVertex3f(-CUBELEN, CUBEROUND, CUBEROUND); + glVertex3f(-CUBELEN, -CUBEROUND, CUBEROUND); + (*polysP)++; + glEnd(); + glBegin(GL_TRIANGLES); + glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, MaterialGray); + /* Corners of cubit */ + glNormal3f(1.00, 1.00, 1.00); + glVertex3f(CUBEROUND, CUBEROUND, CUBELEN); + glVertex3f(CUBELEN, CUBEROUND, CUBEROUND); + glVertex3f(CUBEROUND, CUBELEN, CUBEROUND); + (*polysP)++; + glNormal3f(-1.00, -1.00, -1.00); + glVertex3f(-CUBEROUND, -CUBELEN, -CUBEROUND); + glVertex3f(-CUBELEN, -CUBEROUND, -CUBEROUND); + glVertex3f(-CUBEROUND, -CUBEROUND, -CUBELEN); + (*polysP)++; + glNormal3f(-1.00, 1.00, 1.00); + glVertex3f(-CUBEROUND, CUBEROUND, CUBELEN); + glVertex3f(-CUBEROUND, CUBELEN, CUBEROUND); + (*polysP)++; + glVertex3f(-CUBELEN, CUBEROUND, CUBEROUND); + glNormal3f(1.00, -1.00, -1.00); + glVertex3f(CUBELEN, -CUBEROUND, -CUBEROUND); + glVertex3f(CUBEROUND, -CUBELEN, -CUBEROUND); + glVertex3f(CUBEROUND, -CUBEROUND, -CUBELEN); + (*polysP)++; + glNormal3f(1.00, -1.00, 1.00); + glVertex3f(CUBEROUND, -CUBEROUND, CUBELEN); + glVertex3f(CUBEROUND, -CUBELEN, CUBEROUND); + glVertex3f(CUBELEN, -CUBEROUND, CUBEROUND); + (*polysP)++; + glNormal3f(-1.00, 1.00, -1.00); + glVertex3f(-CUBELEN, CUBEROUND, -CUBEROUND); + glVertex3f(-CUBEROUND, CUBELEN, -CUBEROUND); + glVertex3f(-CUBEROUND, CUBEROUND, -CUBELEN); + (*polysP)++; + glNormal3f(-1.00, -1.00, 1.00); + glVertex3f(-CUBEROUND, -CUBEROUND, CUBELEN); + glVertex3f(-CUBELEN, -CUBEROUND, CUBEROUND); + glVertex3f(-CUBEROUND, -CUBELEN, CUBEROUND); + (*polysP)++; + glNormal3f(1.00, 1.00, -1.00); + glVertex3f(CUBELEN, CUBEROUND, -CUBEROUND); + glVertex3f(CUBEROUND, CUBEROUND, -CUBELEN); + glVertex3f(CUBEROUND, CUBELEN, -CUBEROUND); + (*polysP)++; + glEnd(); + return True; +} + +static Bool +draw_cubit(ModeInfo * mi, + int back, int front, int left, int right, int bottom, int top, + unsigned long *polysP) +{ + rubikstruct *rp = &rubik[MI_SCREEN(mi)]; + int mono = MI_IS_MONO(mi); + + if (!draw_stickerless_cubit(rp, polysP)) + return False; + if (back != NO_FACE) { + glBegin(GL_POLYGON); + pickcolor(back, mono); + glNormal3f(0.00, 0.00, -1.00); + glVertex3f(-STICKERSHORT, STICKERLONG, -STICKERDEPTH); + glVertex3f(STICKERSHORT, STICKERLONG, -STICKERDEPTH); + glVertex3f(STICKERLONG, STICKERSHORT, -STICKERDEPTH); + glVertex3f(STICKERLONG, -STICKERSHORT, -STICKERDEPTH); + glVertex3f(STICKERSHORT, -STICKERLONG, -STICKERDEPTH); + glVertex3f(-STICKERSHORT, -STICKERLONG, -STICKERDEPTH); + glVertex3f(-STICKERLONG, -STICKERSHORT, -STICKERDEPTH); + glVertex3f(-STICKERLONG, STICKERSHORT, -STICKERDEPTH); + (*polysP)++; + glEnd(); + } + if (front != NO_FACE) { + glBegin(GL_POLYGON); + pickcolor(front, mono); + glNormal3f(0.00, 0.00, 1.00); + glVertex3f(-STICKERSHORT, -STICKERLONG, STICKERDEPTH); + glVertex3f(STICKERSHORT, -STICKERLONG, STICKERDEPTH); + glVertex3f(STICKERLONG, -STICKERSHORT, STICKERDEPTH); + glVertex3f(STICKERLONG, STICKERSHORT, STICKERDEPTH); + glVertex3f(STICKERSHORT, STICKERLONG, STICKERDEPTH); + glVertex3f(-STICKERSHORT, STICKERLONG, STICKERDEPTH); + glVertex3f(-STICKERLONG, STICKERSHORT, STICKERDEPTH); + glVertex3f(-STICKERLONG, -STICKERSHORT, STICKERDEPTH); + (*polysP)++; + glEnd(); + } + if (left != NO_FACE) { + glBegin(GL_POLYGON); + pickcolor(left, mono); + glNormal3f(-1.00, 0.00, 0.00); + glVertex3f(-STICKERDEPTH, -STICKERSHORT, STICKERLONG); + glVertex3f(-STICKERDEPTH, STICKERSHORT, STICKERLONG); + glVertex3f(-STICKERDEPTH, STICKERLONG, STICKERSHORT); + glVertex3f(-STICKERDEPTH, STICKERLONG, -STICKERSHORT); + glVertex3f(-STICKERDEPTH, STICKERSHORT, -STICKERLONG); + glVertex3f(-STICKERDEPTH, -STICKERSHORT, -STICKERLONG); + glVertex3f(-STICKERDEPTH, -STICKERLONG, -STICKERSHORT); + glVertex3f(-STICKERDEPTH, -STICKERLONG, STICKERSHORT); + (*polysP)++; + glEnd(); + } + if (right != NO_FACE) { + glBegin(GL_POLYGON); + pickcolor(right, mono); + glNormal3f(1.00, 0.00, 0.00); + glVertex3f(STICKERDEPTH, -STICKERSHORT, -STICKERLONG); + glVertex3f(STICKERDEPTH, STICKERSHORT, -STICKERLONG); + glVertex3f(STICKERDEPTH, STICKERLONG, -STICKERSHORT); + glVertex3f(STICKERDEPTH, STICKERLONG, STICKERSHORT); + glVertex3f(STICKERDEPTH, STICKERSHORT, STICKERLONG); + glVertex3f(STICKERDEPTH, -STICKERSHORT, STICKERLONG); + glVertex3f(STICKERDEPTH, -STICKERLONG, STICKERSHORT); + glVertex3f(STICKERDEPTH, -STICKERLONG, -STICKERSHORT); + (*polysP)++; + glEnd(); + } + if (bottom != NO_FACE) { + glBegin(GL_POLYGON); + pickcolor(bottom, mono); + glNormal3f(0.00, -1.00, 0.00); + glVertex3f(STICKERLONG, -STICKERDEPTH, -STICKERSHORT); + glVertex3f(STICKERLONG, -STICKERDEPTH, STICKERSHORT); + glVertex3f(STICKERSHORT, -STICKERDEPTH, STICKERLONG); + glVertex3f(-STICKERSHORT, -STICKERDEPTH, STICKERLONG); + glVertex3f(-STICKERLONG, -STICKERDEPTH, STICKERSHORT); + glVertex3f(-STICKERLONG, -STICKERDEPTH, -STICKERSHORT); + glVertex3f(-STICKERSHORT, -STICKERDEPTH, -STICKERLONG); + glVertex3f(STICKERSHORT, -STICKERDEPTH, -STICKERLONG); + (*polysP)++; + glEnd(); + } + if (top != NO_FACE) { + glBegin(GL_POLYGON); + pickcolor(top, mono); + glNormal3f(0.00, 1.00, 0.00); + glVertex3f(-STICKERLONG, STICKERDEPTH, -STICKERSHORT); + glVertex3f(-STICKERLONG, STICKERDEPTH, STICKERSHORT); + glVertex3f(-STICKERSHORT, STICKERDEPTH, STICKERLONG); + glVertex3f(STICKERSHORT, STICKERDEPTH, STICKERLONG); + glVertex3f(STICKERLONG, STICKERDEPTH, STICKERSHORT); + glVertex3f(STICKERLONG, STICKERDEPTH, -STICKERSHORT); + glVertex3f(STICKERSHORT, STICKERDEPTH, -STICKERLONG); + glVertex3f(-STICKERSHORT, STICKERDEPTH, -STICKERLONG); + (*polysP)++; + glEnd(); + } + return True; +} + +/* Convert move to weird general notation */ +static void +convertMove(rubikstruct * rp, RubikMove move, RubikSlice * slice) +{ + RubikLoc plane; + int sizeOfRow, sizeOfColumn; + + plane = rotateSlice[(int) move.face][move.direction % 2]; + (*slice).face = plane.face; + (*slice).rotation = plane.rotation; + + faceSizes(rp, move.face, &sizeOfRow, &sizeOfColumn); + if (plane.face == 1 || /* VERTICAL */ + (plane.face == 2 && (move.face == 1 || move.face == 3))) { + if ((*slice).rotation == CW) + (*slice).depth = sizeOfRow - 1 - move.position % + sizeOfRow; + else + (*slice).depth = move.position % sizeOfRow; + } else { /* (plane.face == 0 || *//* HORIZONTAL *//* + (plane.face == 2 && (move.face == 0 || move.face == 4))) */ + if ((*slice).rotation == CW) + (*slice).depth = sizeOfColumn - 1 - move.position / + sizeOfRow; + else + (*slice).depth = move.position / sizeOfRow; + } + /* If (*slice).depth = 0 then face 0, face 1, or face 2 moves */ + if (move.direction / 2) + (*slice).rotation = ((*slice).rotation == CW) ? CCW : CW; +} + +/* Assume the size is at least 2, or its just not challenging... */ +static Bool +draw_cube(ModeInfo * mi) +{ +#define S1 1 +#define SX ((GLint)S1*(MAXSIZEX-1)) +#define SY ((GLint)S1*(MAXSIZEY-1)) +#define SZ ((GLint)S1*(MAXSIZEZ-1)) +#define HALFX (((GLfloat)MAXSIZEX-1.0)/2.0) +#define HALFY (((GLfloat)MAXSIZEY-1.0)/2.0) +#define HALFZ (((GLfloat)MAXSIZEZ-1.0)/2.0) +#define MIDX(a) (((GLfloat)(2*a-MAXSIZEX+1))/2.0) +#define MIDY(a) (((GLfloat)(2*a-MAXSIZEY+1))/2.0) +#define MIDZ(a) (((GLfloat)(2*a-MAXSIZEZ+1))/2.0) +#define DRAW_CUBIT(mi,b,f,l,r,bm,t) if (!draw_cubit(mi,b,f,l,r,bm,t,&mi->polygon_count)) return False + rubikstruct *rp = &rubik[MI_SCREEN(mi)]; + RubikSlice slice; + GLfloat rotatestep; + int i, j, k; + + if (rp->movement.face == NO_FACE) { + slice.face = NO_FACE; + slice.rotation = NO_ROTATION; + slice.depth = NO_DEPTH; + } else { + convertMove(rp, rp->movement, &slice); + } + rotatestep = (slice.rotation == CCW) ? rp->rotatestep : -rp->rotatestep; + + +/*- + * The glRotatef() routine transforms the coordinate system for every future + * vertex specification (this is not so simple, but by now comprehending this + * is sufficient). So if you want to rotate the inner slice, you can draw + * one slice, rotate the anglestep for the centerslice, draw the inner slice, + * rotate reversely and draw the other slice. + * There is a sequence for drawing cubies for each axis being moved... + */ + switch (slice.face) { + case NO_FACE: + case TOP_FACE: /* BOTTOM_FACE too */ + glPushMatrix(); + if (slice.depth == MAXSIZEY - 1) + glRotatef(rotatestep, 0, HALFY, 0); + + glTranslatef(-HALFX, -HALFY, -HALFZ); + DRAW_CUBIT(mi, + rp->cubeLoc[BACK_FACE][FIRSTX + MAXSIZEX * FIRSTY].face, NO_FACE, + rp->cubeLoc[LEFT_FACE][FIRSTZ + MAXSIZEZ * LASTY].face, NO_FACE, + rp->cubeLoc[BOTTOM_FACE][FIRSTX + MAXSIZEX * LASTZ].face, NO_FACE); + for (k = 1; k < MAXSIZEZ - 1; k++) { + glTranslatef(0, 0, S1); + DRAW_CUBIT(mi, + NO_FACE, NO_FACE, + rp->cubeLoc[LEFT_FACE][k + MAXSIZEZ * LASTY].face, NO_FACE, + rp->cubeLoc[BOTTOM_FACE][FIRSTX + MAXSIZEX * REVZ(k)].face, NO_FACE); + } + glTranslatef(0, 0, S1); + DRAW_CUBIT(mi, + NO_FACE, rp->cubeLoc[FRONT_FACE][FIRSTX + MAXSIZEX * LASTY].face, + rp->cubeLoc[LEFT_FACE][LASTZ + MAXSIZEZ * LASTY].face, NO_FACE, + rp->cubeLoc[BOTTOM_FACE][FIRSTX + MAXSIZEX * FIRSTZ].face, NO_FACE); + for (i = 1; i < MAXSIZEX - 1; i++) { + glTranslatef(S1, 0, -SZ); + DRAW_CUBIT(mi, + rp->cubeLoc[BACK_FACE][i + MAXSIZEX * FIRSTY].face, NO_FACE, + NO_FACE, NO_FACE, + rp->cubeLoc[BOTTOM_FACE][i + MAXSIZEX * LASTZ].face, NO_FACE); + for (k = 1; k < MAXSIZEZ - 1; k++) { + glTranslatef(0, 0, S1); + DRAW_CUBIT(mi, + NO_FACE, NO_FACE, + NO_FACE, NO_FACE, + rp->cubeLoc[BOTTOM_FACE][i + MAXSIZEX * REVZ(k)].face, NO_FACE); + } + glTranslatef(0, 0, S1); + DRAW_CUBIT(mi, + NO_FACE, rp->cubeLoc[FRONT_FACE][i + MAXSIZEX * LASTY].face, + NO_FACE, NO_FACE, + rp->cubeLoc[BOTTOM_FACE][i + MAXSIZEX * FIRSTZ].face, NO_FACE); + } + glTranslatef(S1, 0, -SZ); + DRAW_CUBIT(mi, + rp->cubeLoc[BACK_FACE][LASTX + MAXSIZEX * FIRSTY].face, NO_FACE, + NO_FACE, rp->cubeLoc[RIGHT_FACE][LASTZ + MAXSIZEZ * LASTY].face, + rp->cubeLoc[BOTTOM_FACE][LASTX + MAXSIZEX * LASTZ].face, NO_FACE); + for (k = 1; k < MAXSIZEZ - 1; k++) { + glTranslatef(0, 0, S1); + DRAW_CUBIT(mi, + NO_FACE, NO_FACE, + NO_FACE, rp->cubeLoc[RIGHT_FACE][REVZ(k) + MAXSIZEZ * LASTY].face, + rp->cubeLoc[BOTTOM_FACE][LASTX + MAXSIZEX * REVZ(k)].face, NO_FACE); + } + glTranslatef(0, 0, S1); + DRAW_CUBIT(mi, + NO_FACE, rp->cubeLoc[FRONT_FACE][LASTX + MAXSIZEX * LASTY].face, + NO_FACE, rp->cubeLoc[RIGHT_FACE][FIRSTZ + MAXSIZEZ * LASTY].face, + rp->cubeLoc[BOTTOM_FACE][LASTX + MAXSIZEX * FIRSTZ].face, NO_FACE); + glPopMatrix(); + for (j = 1; j < MAXSIZEY - 1; j++) { + glPushMatrix(); + if (slice.depth == REVY(j)) + glRotatef(rotatestep, 0, HALFY, 0); + glTranslatef(-HALFX, MIDY(j), -HALFZ); + DRAW_CUBIT(mi, + rp->cubeLoc[BACK_FACE][FIRSTX + MAXSIZEX * j].face, NO_FACE, + rp->cubeLoc[LEFT_FACE][FIRSTZ + MAXSIZEZ * REVY(j)].face, NO_FACE, + NO_FACE, NO_FACE); + for (k = 1; k < MAXSIZEZ - 1; k++) { + glTranslatef(0, 0, S1); + DRAW_CUBIT(mi, + NO_FACE, NO_FACE, + rp->cubeLoc[LEFT_FACE][k + MAXSIZEZ * REVY(j)].face, NO_FACE, + NO_FACE, NO_FACE); + } + glTranslatef(0, 0, S1); + DRAW_CUBIT(mi, + NO_FACE, rp->cubeLoc[FRONT_FACE][FIRSTX + MAXSIZEX * REVY(j)].face, + rp->cubeLoc[LEFT_FACE][LASTZ + MAXSIZEZ * REVY(j)].face, NO_FACE, + NO_FACE, NO_FACE); + for (i = 1; i < MAXSIZEX - 1; i++) { + glTranslatef(1, 0, -SZ); + DRAW_CUBIT(mi, + rp->cubeLoc[BACK_FACE][i + MAXSIZEX * j].face, NO_FACE, + NO_FACE, NO_FACE, + NO_FACE, NO_FACE); + /* Center */ + glTranslatef(0, 0, SZ); + DRAW_CUBIT(mi, + NO_FACE, rp->cubeLoc[FRONT_FACE][i + MAXSIZEX * REVY(j)].face, + NO_FACE, NO_FACE, + NO_FACE, NO_FACE); + } + glTranslatef(S1, 0, -SZ); + DRAW_CUBIT(mi, + rp->cubeLoc[BACK_FACE][LASTX + MAXSIZEX * j].face, NO_FACE, + NO_FACE, rp->cubeLoc[RIGHT_FACE][LASTZ + MAXSIZEZ * REVY(j)].face, + NO_FACE, NO_FACE); + for (k = 1; k < MAXSIZEZ - 1; k++) { + glTranslatef(0, 0, S1); + DRAW_CUBIT(mi, + NO_FACE, NO_FACE, + NO_FACE, rp->cubeLoc[RIGHT_FACE][REVZ(k) + MAXSIZEZ * REVY(j)].face, + NO_FACE, NO_FACE); + } + glTranslatef(0, 0, S1); + DRAW_CUBIT(mi, + NO_FACE, rp->cubeLoc[FRONT_FACE][LASTX + MAXSIZEX * REVY(j)].face, + NO_FACE, rp->cubeLoc[RIGHT_FACE][FIRSTZ + MAXSIZEZ * REVY(j)].face, + NO_FACE, NO_FACE); + glPopMatrix(); + } + if (slice.depth == 0) + glRotatef(rotatestep, 0, HALFY, 0); + + glTranslatef(-HALFX, HALFY, -HALFZ); + DRAW_CUBIT(mi, + rp->cubeLoc[BACK_FACE][FIRSTX + MAXSIZEX * LASTY].face, NO_FACE, + rp->cubeLoc[LEFT_FACE][FIRSTZ + MAXSIZEZ * FIRSTY].face, NO_FACE, + NO_FACE, rp->cubeLoc[TOP_FACE][FIRSTX + MAXSIZEX * FIRSTZ].face); + for (k = 1; k < MAXSIZEZ - 1; k++) { + glTranslatef(0, 0, S1); + DRAW_CUBIT(mi, + NO_FACE, NO_FACE, + rp->cubeLoc[LEFT_FACE][k + MAXSIZEZ * FIRSTY].face, NO_FACE, + NO_FACE, rp->cubeLoc[TOP_FACE][FIRSTX + MAXSIZEX * k].face); + } + glTranslatef(0, 0, S1); + DRAW_CUBIT(mi, + NO_FACE, rp->cubeLoc[FRONT_FACE][FIRSTX + MAXSIZEX * FIRSTY].face, + rp->cubeLoc[LEFT_FACE][LASTZ + MAXSIZEZ * FIRSTY].face, NO_FACE, + NO_FACE, rp->cubeLoc[TOP_FACE][FIRSTX + MAXSIZEX * LASTZ].face); + for (i = 1; i < MAXSIZEX - 1; i++) { + glTranslatef(S1, 0, -SZ); + DRAW_CUBIT(mi, + rp->cubeLoc[BACK_FACE][i + MAXSIZEX * LASTY].face, NO_FACE, + NO_FACE, NO_FACE, + NO_FACE, rp->cubeLoc[TOP_FACE][i + MAXSIZEX * FIRSTZ].face); + for (k = 1; k < MAXSIZEZ - 1; k++) { + glTranslatef(0, 0, S1); + DRAW_CUBIT(mi, + NO_FACE, NO_FACE, + NO_FACE, NO_FACE, + NO_FACE, rp->cubeLoc[TOP_FACE][i + MAXSIZEX * k].face); + } + glTranslatef(0, 0, S1); + DRAW_CUBIT(mi, + NO_FACE, rp->cubeLoc[FRONT_FACE][i + MAXSIZEX * FIRSTY].face, + NO_FACE, NO_FACE, + NO_FACE, rp->cubeLoc[TOP_FACE][i + MAXSIZEX * LASTZ].face); + } + glTranslatef(S1, 0, -SZ); + DRAW_CUBIT(mi, + rp->cubeLoc[BACK_FACE][LASTX + MAXSIZEX * LASTY].face, NO_FACE, + NO_FACE, rp->cubeLoc[RIGHT_FACE][LASTZ + MAXSIZEZ * FIRSTY].face, + NO_FACE, rp->cubeLoc[TOP_FACE][LASTX + MAXSIZEX * FIRSTZ].face); + for (k = 1; k < MAXSIZEZ - 1; k++) { + glTranslatef(0, 0, S1); + DRAW_CUBIT(mi, + NO_FACE, NO_FACE, + NO_FACE, rp->cubeLoc[RIGHT_FACE][REVZ(k) + MAXSIZEZ * FIRSTY].face, + NO_FACE, rp->cubeLoc[TOP_FACE][LASTX + MAXSIZEX * k].face); + } + glTranslatef(0, 0, S1); + DRAW_CUBIT(mi, + NO_FACE, rp->cubeLoc[FRONT_FACE][LASTX + MAXSIZEX * FIRSTY].face, + NO_FACE, rp->cubeLoc[RIGHT_FACE][FIRSTZ + MAXSIZEZ * FIRSTY].face, + NO_FACE, rp->cubeLoc[TOP_FACE][LASTX + MAXSIZEX * LASTZ].face); + break; + case LEFT_FACE: /* RIGHT_FACE too */ + /* rotatestep is negative because the RIGHT face is the default here */ + glPushMatrix(); + if (slice.depth == 0) + glRotatef(-rotatestep, HALFX, 0, 0); + + glTranslatef(-HALFX, -HALFY, -HALFZ); + DRAW_CUBIT(mi, + rp->cubeLoc[BACK_FACE][FIRSTX + MAXSIZEX * FIRSTY].face, NO_FACE, + rp->cubeLoc[LEFT_FACE][FIRSTZ + MAXSIZEZ * LASTY].face, NO_FACE, + rp->cubeLoc[BOTTOM_FACE][FIRSTX + MAXSIZEX * LASTZ].face, NO_FACE); + for (j = 1; j < MAXSIZEY - 1; j++) { + glTranslatef(0, S1, 0); + DRAW_CUBIT(mi, + rp->cubeLoc[BACK_FACE][FIRSTX + MAXSIZEX * j].face, NO_FACE, + rp->cubeLoc[LEFT_FACE][FIRSTZ + MAXSIZEZ * REVY(j)].face, NO_FACE, + NO_FACE, NO_FACE); + } + glTranslatef(0, S1, 0); + DRAW_CUBIT(mi, + rp->cubeLoc[BACK_FACE][FIRSTX + MAXSIZEX * LASTY].face, NO_FACE, + rp->cubeLoc[LEFT_FACE][FIRSTZ + MAXSIZEZ * FIRSTY].face, NO_FACE, + NO_FACE, rp->cubeLoc[TOP_FACE][FIRSTX + MAXSIZEX * FIRSTZ].face); + for (k = 1; k < MAXSIZEZ - 1; k++) { + glTranslatef(0, -SY, S1); + DRAW_CUBIT(mi, + NO_FACE, NO_FACE, + rp->cubeLoc[LEFT_FACE][k + MAXSIZEZ * LASTY].face, NO_FACE, + rp->cubeLoc[BOTTOM_FACE][FIRSTX + MAXSIZEX * REVZ(k)].face, NO_FACE); + for (j = 1; j < MAXSIZEY - 1; j++) { + glTranslatef(0, S1, 0); + DRAW_CUBIT(mi, + NO_FACE, NO_FACE, + rp->cubeLoc[LEFT_FACE][k + MAXSIZEZ * REVY(j)].face, NO_FACE, + NO_FACE, NO_FACE); + } + glTranslatef(0, S1, 0); + DRAW_CUBIT(mi, + NO_FACE, NO_FACE, + rp->cubeLoc[LEFT_FACE][k + MAXSIZEZ * FIRSTY].face, NO_FACE, + NO_FACE, rp->cubeLoc[TOP_FACE][FIRSTX + MAXSIZEX * k].face); + } + glTranslatef(0, -SY, S1); + DRAW_CUBIT(mi, + NO_FACE, rp->cubeLoc[FRONT_FACE][FIRSTX + MAXSIZEX * LASTY].face, + rp->cubeLoc[LEFT_FACE][LASTZ + MAXSIZEZ * LASTY].face, NO_FACE, + rp->cubeLoc[BOTTOM_FACE][FIRSTX + MAXSIZEX * FIRSTZ].face, NO_FACE); + for (j = 1; j < MAXSIZEY - 1; j++) { + glTranslatef(0, S1, 0); + DRAW_CUBIT(mi, + NO_FACE, rp->cubeLoc[FRONT_FACE][FIRSTX + MAXSIZEX * REVY(j)].face, + rp->cubeLoc[LEFT_FACE][LASTZ + MAXSIZEZ * REVY(j)].face, NO_FACE, + NO_FACE, NO_FACE); + } + glTranslatef(0, S1, 0); + DRAW_CUBIT(mi, + NO_FACE, rp->cubeLoc[FRONT_FACE][FIRSTX + MAXSIZEX * FIRSTY].face, + rp->cubeLoc[LEFT_FACE][LASTZ + MAXSIZEZ * FIRSTY].face, NO_FACE, + NO_FACE, rp->cubeLoc[TOP_FACE][FIRSTX + MAXSIZEX * LASTZ].face); + glPopMatrix(); + for (i = 1; i < MAXSIZEX - 1; i++) { + glPushMatrix(); + if (slice.depth == i) + glRotatef(-rotatestep, HALFX, 0, 0); + glTranslatef(MIDX(i), -HALFY, -HALFZ); + DRAW_CUBIT(mi, + rp->cubeLoc[BACK_FACE][i + MAXSIZEX * FIRSTY].face, NO_FACE, + NO_FACE, NO_FACE, + rp->cubeLoc[BOTTOM_FACE][i + MAXSIZEX * LASTZ].face, NO_FACE); + for (j = 1; j < MAXSIZEY - 1; j++) { + glTranslatef(0, S1, 0); + DRAW_CUBIT(mi, + rp->cubeLoc[BACK_FACE][i + MAXSIZEX * j].face, NO_FACE, + NO_FACE, NO_FACE, + NO_FACE, NO_FACE); + } + glTranslatef(0, S1, 0); + DRAW_CUBIT(mi, + rp->cubeLoc[BACK_FACE][i + MAXSIZEX * LASTY].face, NO_FACE, + NO_FACE, NO_FACE, + NO_FACE, rp->cubeLoc[TOP_FACE][i + MAXSIZEX * FIRSTZ].face); + for (k = 1; k < MAXSIZEZ - 1; k++) { + glTranslatef(0, -SY, S1); + DRAW_CUBIT(mi, + NO_FACE, NO_FACE, + NO_FACE, NO_FACE, + rp->cubeLoc[BOTTOM_FACE][i + MAXSIZEX * REVZ(k)].face, NO_FACE); + /* Center */ + glTranslatef(0, SY, 0); + DRAW_CUBIT(mi, + NO_FACE, NO_FACE, + NO_FACE, NO_FACE, + NO_FACE, rp->cubeLoc[TOP_FACE][i + MAXSIZEX * k].face); + } + glTranslatef(0, -SY, S1); + DRAW_CUBIT(mi, + NO_FACE, rp->cubeLoc[FRONT_FACE][i + MAXSIZEX * LASTY].face, + NO_FACE, NO_FACE, + rp->cubeLoc[BOTTOM_FACE][i + MAXSIZEX * FIRSTZ].face, NO_FACE); + for (j = 1; j < MAXSIZEY - 1; j++) { + glTranslatef(0, S1, 0); + DRAW_CUBIT(mi, + NO_FACE, rp->cubeLoc[FRONT_FACE][i + MAXSIZEX * REVY(j)].face, + NO_FACE, NO_FACE, + NO_FACE, NO_FACE); + } + glTranslatef(0, S1, 0); + DRAW_CUBIT(mi, + NO_FACE, rp->cubeLoc[FRONT_FACE][i + MAXSIZEX * FIRSTY].face, + NO_FACE, NO_FACE, + NO_FACE, rp->cubeLoc[TOP_FACE][i + MAXSIZEX * LASTZ].face); + glPopMatrix(); + } + if (slice.depth == MAXSIZEX - 1) + glRotatef(-rotatestep, HALFX, 0, 0); + glTranslatef(HALFX, -HALFY, -HALFZ); + DRAW_CUBIT(mi, + rp->cubeLoc[BACK_FACE][LASTX + MAXSIZEX * FIRSTY].face, NO_FACE, + NO_FACE, rp->cubeLoc[RIGHT_FACE][LASTZ + MAXSIZEZ * LASTY].face, + rp->cubeLoc[BOTTOM_FACE][LASTX + MAXSIZEX * LASTZ].face, NO_FACE); + for (j = 1; j < MAXSIZEY - 1; j++) { + glTranslatef(0, S1, 0); + DRAW_CUBIT(mi, + rp->cubeLoc[BACK_FACE][LASTX + MAXSIZEX * j].face, NO_FACE, + NO_FACE, rp->cubeLoc[RIGHT_FACE][LASTZ + MAXSIZEZ * REVY(j)].face, + NO_FACE, NO_FACE); + } + glTranslatef(0, S1, 0); + DRAW_CUBIT(mi, + rp->cubeLoc[BACK_FACE][LASTX + MAXSIZEX * LASTY].face, NO_FACE, + NO_FACE, rp->cubeLoc[RIGHT_FACE][LASTZ + MAXSIZEZ * FIRSTY].face, + NO_FACE, rp->cubeLoc[TOP_FACE][LASTX + MAXSIZEX * FIRSTZ].face); + for (k = 1; k < MAXSIZEZ - 1; k++) { + glTranslatef(0, -SY, S1); + DRAW_CUBIT(mi, + NO_FACE, NO_FACE, + NO_FACE, rp->cubeLoc[RIGHT_FACE][REVZ(k) + MAXSIZEZ * LASTY].face, + rp->cubeLoc[BOTTOM_FACE][LASTX + MAXSIZEX * REVZ(k)].face, NO_FACE); + for (j = 1; j < MAXSIZEY - 1; j++) { + glTranslatef(0, S1, 0); + DRAW_CUBIT(mi, + NO_FACE, NO_FACE, + NO_FACE, rp->cubeLoc[RIGHT_FACE][REVZ(k) + MAXSIZEZ * REVY(j)].face, + NO_FACE, NO_FACE); + } + glTranslatef(0, S1, 0); + DRAW_CUBIT(mi, + NO_FACE, NO_FACE, + NO_FACE, rp->cubeLoc[RIGHT_FACE][REVZ(k) + MAXSIZEZ * FIRSTY].face, + NO_FACE, rp->cubeLoc[TOP_FACE][LASTX + MAXSIZEX * k].face); + } + glTranslatef(0, -SY, S1); + DRAW_CUBIT(mi, + NO_FACE, rp->cubeLoc[FRONT_FACE][LASTX + MAXSIZEX * LASTY].face, + NO_FACE, rp->cubeLoc[RIGHT_FACE][FIRSTZ + MAXSIZEZ * LASTY].face, + rp->cubeLoc[BOTTOM_FACE][LASTX + MAXSIZEX * FIRSTZ].face, NO_FACE); + for (j = 1; j < MAXSIZEY - 1; j++) { + glTranslatef(0, S1, 0); + DRAW_CUBIT(mi, + NO_FACE, rp->cubeLoc[FRONT_FACE][LASTX + MAXSIZEX * REVY(j)].face, + NO_FACE, rp->cubeLoc[RIGHT_FACE][FIRSTZ + MAXSIZEZ * REVY(j)].face, + NO_FACE, NO_FACE); + } + glTranslatef(0, S1, 0); + DRAW_CUBIT(mi, + NO_FACE, rp->cubeLoc[FRONT_FACE][LASTX + MAXSIZEX * FIRSTY].face, + NO_FACE, rp->cubeLoc[RIGHT_FACE][FIRSTZ + MAXSIZEZ * FIRSTY].face, + NO_FACE, rp->cubeLoc[TOP_FACE][LASTX + MAXSIZEX * LASTZ].face); + break; + case FRONT_FACE: /* BACK_FACE too */ + glPushMatrix(); + if (slice.depth == MAXSIZEZ - 1) + glRotatef(rotatestep, 0, 0, HALFZ); + + glTranslatef(-HALFX, -HALFY, -HALFZ); + DRAW_CUBIT(mi, + rp->cubeLoc[BACK_FACE][FIRSTX + MAXSIZEX * FIRSTY].face, NO_FACE, + rp->cubeLoc[LEFT_FACE][FIRSTZ + MAXSIZEZ * LASTY].face, NO_FACE, + rp->cubeLoc[BOTTOM_FACE][FIRSTX + MAXSIZEX * LASTZ].face, NO_FACE); + for (i = 1; i < MAXSIZEX - 1; i++) { + glTranslatef(S1, 0, 0); + DRAW_CUBIT(mi, + rp->cubeLoc[BACK_FACE][i + MAXSIZEX * FIRSTY].face, NO_FACE, + NO_FACE, NO_FACE, + rp->cubeLoc[BOTTOM_FACE][i + MAXSIZEX * LASTZ].face, NO_FACE); + } + glTranslatef(S1, 0, 0); + DRAW_CUBIT(mi, + rp->cubeLoc[BACK_FACE][LASTX + MAXSIZEX * FIRSTY].face, NO_FACE, + NO_FACE, rp->cubeLoc[RIGHT_FACE][LASTZ + MAXSIZEZ * LASTY].face, + rp->cubeLoc[BOTTOM_FACE][LASTX + MAXSIZEX * LASTZ].face, NO_FACE); + for (j = 1; j < MAXSIZEY - 1; j++) { + glTranslatef(-SX, S1, 0); + DRAW_CUBIT(mi, + rp->cubeLoc[BACK_FACE][FIRSTX + MAXSIZEX * j].face, NO_FACE, + rp->cubeLoc[LEFT_FACE][FIRSTZ + MAXSIZEZ * REVY(j)].face, NO_FACE, + NO_FACE, NO_FACE); + for (i = 1; i < MAXSIZEX - 1; i++) { + glTranslatef(S1, 0, 0); + DRAW_CUBIT(mi, + rp->cubeLoc[BACK_FACE][i + MAXSIZEX * j].face, NO_FACE, + NO_FACE, NO_FACE, + NO_FACE, NO_FACE); + } + glTranslatef(S1, 0, 0); + DRAW_CUBIT(mi, + rp->cubeLoc[BACK_FACE][LASTX + MAXSIZEX * j].face, NO_FACE, + NO_FACE, rp->cubeLoc[RIGHT_FACE][LASTZ + MAXSIZEZ * REVY(j)].face, + NO_FACE, NO_FACE); + } + glTranslatef(-SX, S1, 0); + DRAW_CUBIT(mi, + rp->cubeLoc[BACK_FACE][FIRSTX + MAXSIZEX * LASTY].face, NO_FACE, + rp->cubeLoc[LEFT_FACE][FIRSTZ + MAXSIZEZ * FIRSTY].face, NO_FACE, + NO_FACE, rp->cubeLoc[TOP_FACE][FIRSTX + MAXSIZEX * FIRSTZ].face); + for (i = 1; i < MAXSIZEX - 1; i++) { + glTranslatef(S1, 0, 0); + DRAW_CUBIT(mi, + rp->cubeLoc[BACK_FACE][i + MAXSIZEX * LASTY].face, NO_FACE, + NO_FACE, NO_FACE, + NO_FACE, rp->cubeLoc[TOP_FACE][i + MAXSIZEX * FIRSTZ].face); + } + glTranslatef(S1, 0, 0); + DRAW_CUBIT(mi, + rp->cubeLoc[BACK_FACE][LASTX + MAXSIZEX * LASTY].face, NO_FACE, + NO_FACE, rp->cubeLoc[RIGHT_FACE][LASTZ + MAXSIZEZ * FIRSTY].face, + NO_FACE, rp->cubeLoc[TOP_FACE][LASTX + MAXSIZEX * FIRSTZ].face); + glPopMatrix(); + for (k = 1; k < MAXSIZEZ - 1; k++) { + glPushMatrix(); + if (slice.depth == REVZ(k)) + glRotatef(rotatestep, 0, 0, HALFZ); + glTranslatef(-HALFX, -HALFY, MIDZ(k)); + DRAW_CUBIT(mi, + NO_FACE, NO_FACE, + rp->cubeLoc[LEFT_FACE][k + MAXSIZEZ * LASTY].face, NO_FACE, + rp->cubeLoc[BOTTOM_FACE][FIRSTX + MAXSIZEX * REVZ(k)].face, NO_FACE); + for (i = 1; i < MAXSIZEX - 1; i++) { + glTranslatef(S1, 0, 0); + DRAW_CUBIT(mi, + NO_FACE, NO_FACE, + NO_FACE, NO_FACE, + rp->cubeLoc[BOTTOM_FACE][i + MAXSIZEX * REVZ(k)].face, NO_FACE); + } + glTranslatef(S1, 0, 0); + DRAW_CUBIT(mi, + NO_FACE, NO_FACE, + NO_FACE, rp->cubeLoc[RIGHT_FACE][REVZ(k) + MAXSIZEZ * LASTY].face, + rp->cubeLoc[BOTTOM_FACE][LASTX + MAXSIZEX * REVZ(k)].face, NO_FACE); + for (j = 1; j < MAXSIZEY - 1; j++) { + glTranslatef(-SX, S1, 0); + DRAW_CUBIT(mi, + NO_FACE, NO_FACE, + rp->cubeLoc[LEFT_FACE][k + MAXSIZEZ * REVY(j)].face, NO_FACE, + NO_FACE, NO_FACE); + /* Center */ + glTranslatef(SX, 0, 0); + DRAW_CUBIT(mi, + NO_FACE, NO_FACE, + NO_FACE, rp->cubeLoc[RIGHT_FACE][REVZ(k) + MAXSIZEZ * REVY(j)].face, + NO_FACE, NO_FACE); + } + glTranslatef(-SX, S1, 0); + DRAW_CUBIT(mi, + NO_FACE, NO_FACE, + rp->cubeLoc[LEFT_FACE][k + MAXSIZEZ * FIRSTY].face, NO_FACE, + NO_FACE, rp->cubeLoc[TOP_FACE][FIRSTX + MAXSIZEX * k].face); + for (i = 1; i < MAXSIZEX - 1; i++) { + glTranslatef(S1, 0, 0); + DRAW_CUBIT(mi, + NO_FACE, NO_FACE, + NO_FACE, NO_FACE, + NO_FACE, rp->cubeLoc[TOP_FACE][i + MAXSIZEX * k].face); + } + glTranslatef(S1, 0, 0); + DRAW_CUBIT(mi, + NO_FACE, NO_FACE, + NO_FACE, rp->cubeLoc[RIGHT_FACE][REVZ(k) + MAXSIZEZ * FIRSTY].face, + NO_FACE, rp->cubeLoc[TOP_FACE][LASTX + MAXSIZEX * k].face); + glPopMatrix(); + } + if (slice.depth == 0) + glRotatef(rotatestep, 0, 0, HALFZ); + glTranslatef(-HALFX, -HALFY, HALFZ); + DRAW_CUBIT(mi, + NO_FACE, rp->cubeLoc[FRONT_FACE][FIRSTX + MAXSIZEX * LASTY].face, + rp->cubeLoc[LEFT_FACE][LASTZ + MAXSIZEZ * LASTY].face, NO_FACE, + rp->cubeLoc[BOTTOM_FACE][FIRSTX + MAXSIZEX * FIRSTZ].face, NO_FACE); + for (i = 1; i < MAXSIZEX - 1; i++) { + glTranslatef(S1, 0, 0); + DRAW_CUBIT(mi, + NO_FACE, rp->cubeLoc[FRONT_FACE][i + MAXSIZEX * LASTY].face, + NO_FACE, NO_FACE, + rp->cubeLoc[BOTTOM_FACE][i + MAXSIZEX * FIRSTZ].face, NO_FACE); + } + glTranslatef(S1, 0, 0); + DRAW_CUBIT(mi, + NO_FACE, rp->cubeLoc[FRONT_FACE][LASTX + MAXSIZEX * LASTY].face, + NO_FACE, rp->cubeLoc[RIGHT_FACE][FIRSTZ + MAXSIZEZ * LASTY].face, + rp->cubeLoc[BOTTOM_FACE][LASTX + MAXSIZEX * FIRSTZ].face, NO_FACE); + for (j = 1; j < MAXSIZEY - 1; j++) { + glTranslatef(-SX, S1, 0); + DRAW_CUBIT(mi, + NO_FACE, rp->cubeLoc[FRONT_FACE][FIRSTX + MAXSIZEX * REVY(j)].face, + rp->cubeLoc[LEFT_FACE][LASTZ + MAXSIZEZ * REVY(j)].face, NO_FACE, + NO_FACE, NO_FACE); + for (i = 1; i < MAXSIZEX - 1; i++) { + glTranslatef(S1, 0, 0); + DRAW_CUBIT(mi, + NO_FACE, rp->cubeLoc[FRONT_FACE][i + MAXSIZEX * REVY(j)].face, + NO_FACE, NO_FACE, + NO_FACE, NO_FACE); + } + glTranslatef(S1, 0, 0); + DRAW_CUBIT(mi, + NO_FACE, rp->cubeLoc[FRONT_FACE][LASTX + MAXSIZEX * REVY(j)].face, + NO_FACE, rp->cubeLoc[RIGHT_FACE][FIRSTZ + MAXSIZEZ * REVY(j)].face, + NO_FACE, NO_FACE); + } + glTranslatef(-SX, S1, 0); + DRAW_CUBIT(mi, + NO_FACE, rp->cubeLoc[FRONT_FACE][FIRSTX + MAXSIZEX * FIRSTY].face, + rp->cubeLoc[LEFT_FACE][LASTZ + MAXSIZEZ * FIRSTY].face, NO_FACE, + NO_FACE, rp->cubeLoc[TOP_FACE][FIRSTX + MAXSIZEX * LASTZ].face); + for (i = 1; i < MAXSIZEX - 1; i++) { + glTranslatef(S1, 0, 0); + DRAW_CUBIT(mi, + NO_FACE, rp->cubeLoc[FRONT_FACE][i + MAXSIZEX * FIRSTY].face, + NO_FACE, NO_FACE, + NO_FACE, rp->cubeLoc[TOP_FACE][i + MAXSIZEX * LASTZ].face); + } + glTranslatef(S1, 0, 0); + DRAW_CUBIT(mi, + NO_FACE, rp->cubeLoc[FRONT_FACE][LASTX + MAXSIZEX * FIRSTY].face, + NO_FACE, rp->cubeLoc[RIGHT_FACE][FIRSTZ + MAXSIZEZ * FIRSTY].face, + NO_FACE, rp->cubeLoc[TOP_FACE][LASTX + MAXSIZEX * LASTZ].face); + break; + } + return True; +#undef S1 +} + +/* From David Bagley's xrubik. Used by permission. ;) */ +static void +readRC(rubikstruct * rp, int face, int dir, int h, int orient, int size) +{ + int g, sizeOfRow; + + sizeOfRow = sizeRow(rp, face); + if (dir == TOP || dir == BOTTOM) + for (g = 0; g < size; g++) + rp->rowLoc[orient][g] = + rp->cubeLoc[face][g * sizeOfRow + h]; + else /* dir == RIGHT || dir == LEFT */ + for (g = 0; g < size; g++) + rp->rowLoc[orient][g] = + rp->cubeLoc[face][h * sizeOfRow + g]; +} + +static void +rotateRC(rubikstruct * rp, int rotate, int orient, int size) +{ + int g; + + for (g = 0; g < size; g++) + rp->rowLoc[orient][g].rotation = + (rp->rowLoc[orient][g].rotation + rotate) % MAXORIENT; +} + +static void +reverseRC(rubikstruct * rp, int orient, int size) +{ + int g; + RubikLoc temp; + + for (g = 0; g < size / 2; g++) { + temp = rp->rowLoc[orient][size - 1 - g]; + rp->rowLoc[orient][size - 1 - g] = rp->rowLoc[orient][g]; + rp->rowLoc[orient][g] = temp; + } +} + +static void +writeRC(rubikstruct * rp, int face, int dir, int h, int orient, int size) +{ + int g, position, sizeOfRow; + + sizeOfRow = sizeRow(rp, face); + if (dir == TOP || dir == BOTTOM) { + for (g = 0; g < size; g++) { + position = g * sizeOfRow + h; + rp->cubeLoc[face][position] = rp->rowLoc[orient][g]; + /* DrawSquare(face, position); */ + } + } else { /* dir == RIGHT || dir == LEFT */ + for (g = 0; g < size; g++) { + position = h * sizeOfRow + g; + rp->cubeLoc[face][position] = rp->rowLoc[orient][g]; + /* DrawSquare(face, position); */ + } + } +} + +static Bool +rotateFace(rubikstruct * rp, int face, int direction) +{ + int position, i, j, sizeOfRow, sizeOfColumn, sizeOnPlane; + RubikLoc *faceLoc; + + faceSizes(rp, face, &sizeOfRow, &sizeOfColumn); + sizeOnPlane = sizeOfRow * sizeOfColumn; + if ((faceLoc = (RubikLoc *) malloc(sizeOnPlane * + sizeof (RubikLoc))) == NULL) { + return False; + } + /* Read Face */ + for (position = 0; position < sizeOnPlane; position++) + faceLoc[position] = rp->cubeLoc[face][position]; + /* Write Face */ + for (position = 0; position < sizeOnPlane; position++) { + i = position % sizeOfRow; + j = position / sizeOfRow; + if (direction == CW) + rp->cubeLoc[face][position] = + faceLoc[(sizeOfRow - i - 1) * sizeOfRow + j]; + else if (direction == CCW) + rp->cubeLoc[face][position] = + faceLoc[i * sizeOfRow + sizeOfColumn - j - 1]; + else /* (direction == HALF) */ + rp->cubeLoc[face][position] = + faceLoc[sizeOfRow - i - 1 + (sizeOfColumn - j - 1) * sizeOfRow]; + rp->cubeLoc[face][position].rotation = + (rp->cubeLoc[face][position].rotation + + direction - MAXORIENT) % MAXORIENT; + /* DrawSquare(face, position); */ + } + if (faceLoc != NULL) + (void) free((void *) faceLoc); + return True; +} + +/* Yeah this is big and ugly */ +static void +slideRC(int face, int direction, int h, int sizeOnOppAxis, + int *newFace, int *newDirection, int *newH, + int *rotate, Bool *reverse) +{ + *newFace = slideNextRow[face][direction].face; + *rotate = slideNextRow[face][direction].rotation; + *newDirection = (*rotate + direction) % MAXORIENT; + switch (*rotate) { + case TOP: + *newH = h; + *reverse = False; + break; + case RIGHT: + if (*newDirection == TOP || *newDirection == BOTTOM) { + *newH = sizeOnOppAxis - 1 - h; + *reverse = False; + } else { /* *newDirection == RIGHT || *newDirection == LEFT */ + *newH = h; + *reverse = True; + } + break; + case BOTTOM: + *newH = sizeOnOppAxis - 1 - h; + *reverse = True; + break; + case LEFT: + if (*newDirection == TOP || *newDirection == BOTTOM) { + *newH = h; + *reverse = True; + } else { /* *newDirection == RIGHT || *newDirection == LEFT */ + *newH = sizeOnOppAxis - 1 - h; + *reverse = False; + } + break; + default: + (void) printf("slideRC: rotate %d\n", *rotate); + *newH = 0; + *reverse = False; + } +} + +static Bool +moveRubik(rubikstruct * rp, int face, int direction, int position) +{ + int newFace, newDirection, rotate, reverse; + int h, k, newH; + int i, j, sizeOfRow, sizeOfColumn, sizeOnAxis, sizeOnOppAxis; + + faceSizes(rp, face, &sizeOfRow, &sizeOfColumn); + if (direction == CW || direction == CCW) { + direction = (direction == CCW) ? + (rotateToRow[face].direction + 2) % MAXORIENT : + rotateToRow[face].direction; + if (rotateToRow[face].sideFace == RIGHT) { + i = j = sizeOfColumn - 1; + } else if (rotateToRow[face].sideFace == BOTTOM) { + i = j = sizeOfRow - 1; + } else { + i = j = 0; + } + face = rotateToRow[face].face; + position = j * sizeOfRow + i; + } + i = position % sizeOfRow; + j = position / sizeOfRow; + h = (direction == TOP || direction == BOTTOM) ? i : j; + if (direction == TOP || direction == BOTTOM) { + sizeOnAxis = sizeOfColumn; + sizeOnOppAxis = sizeOfRow; + } else { + sizeOnAxis = sizeOfRow; + sizeOnOppAxis = sizeOfColumn; + } + /* rotate sides CW or CCW or HALF) */ + + if (h == sizeOnOppAxis - 1) { + newDirection = (direction == TOP || direction == BOTTOM) ? + TOP : RIGHT; + if (rp->degreeTurn == 180) { + if (!rotateFace(rp, rowToRotate[face][newDirection], HALF)) + return False; + } else if (direction == TOP || direction == RIGHT) { + if (!rotateFace(rp, rowToRotate[face][newDirection], CW)) + return False; + } else { /* direction == BOTTOM || direction == LEFT */ + if (!rotateFace(rp, rowToRotate[face][newDirection], CCW)) + return False; + } + } + if (h == 0) { + newDirection = (direction == TOP || direction == BOTTOM) ? + BOTTOM : LEFT; + if (rp->degreeTurn == 180) { + if (!rotateFace(rp, rowToRotate[face][newDirection], HALF)) + return False; + } else if (direction == TOP || direction == RIGHT) { + if (!rotateFace(rp, rowToRotate[face][newDirection], CCW)) + return False; + } else { /* direction == BOTTOM || direction == LEFT */ + if (!rotateFace(rp, rowToRotate[face][newDirection], CW)) + return False; + } + } + /* Slide rows or columns */ + readRC(rp, face, direction, h, 0, sizeOnAxis); + if (rp->degreeTurn == 180) { + int sizeOnDepthAxis; + + slideRC(face, direction, h, sizeOnOppAxis, + &newFace, &newDirection, &newH, &rotate, &reverse); + sizeOnDepthAxis = sizeFace(rp, newFace) / sizeOnOppAxis; + readRC(rp, newFace, newDirection, newH, 1, sizeOnDepthAxis); + rotateRC(rp, rotate, 0, sizeOnAxis); + if (reverse == True) + reverseRC(rp, 0, sizeOnAxis); + face = newFace; + direction = newDirection; + h = newH; + for (k = 2; k <= MAXORIENT + 1; k++) { + slideRC(face, direction, h, sizeOnOppAxis, + &newFace, &newDirection, &newH, &rotate, &reverse); + if (k != MAXORIENT && k != MAXORIENT + 1) + readRC(rp, newFace, newDirection, newH, k, + (k % 2) ? sizeOnDepthAxis : sizeOnAxis); + rotateRC(rp, rotate, k - 2, + (k % 2) ? sizeOnDepthAxis : sizeOnAxis); + if (k != MAXORIENT + 1) + rotateRC(rp, rotate, k - 1, + (k % 2) ? sizeOnAxis : sizeOnDepthAxis); + if (reverse == True) { + reverseRC(rp, k - 2, + (k % 2) ? sizeOnDepthAxis : sizeOnAxis); + if (k != MAXORIENT + 1) + reverseRC(rp, k - 1, + (k % 2) ? sizeOnAxis : sizeOnDepthAxis); + } + writeRC(rp, newFace, newDirection, newH, k - 2, + (k % 2) ? sizeOnDepthAxis : sizeOnAxis); + face = newFace; + direction = newDirection; + h = newH; + } + } else { + for (k = 1; k <= MAXORIENT; k++) { + slideRC(face, direction, h, sizeOnOppAxis, + &newFace, &newDirection, &newH, &rotate, &reverse); + if (k != MAXORIENT) + readRC(rp, newFace, newDirection, newH, k, sizeOnAxis); + rotateRC(rp, rotate, k - 1, sizeOnAxis); + if (reverse == True) + reverseRC(rp, k - 1, sizeOnAxis); + writeRC(rp, newFace, newDirection, newH, k - 1, sizeOnAxis); + face = newFace; + direction = newDirection; + h = newH; + } + } + return True; +} + +#ifdef DEBUG +void +printCube(rubikstruct * rp) +{ + int face, position, sizeOfRow, sizeOfColumn; + + for (face = 0; face < MAXFACES; face++) { + faceSizes(rp, face, &sizeOfRow, &sizeOfColumn); + for (position = 0; position < sizeOfRow * sizeOfColumn; position++) { + (void) printf("%d %d ", rp->cubeLoc[face][position].face, + rp->cubeLoc[face][position].rotation); + if (!((position + 1) % sizeOfRow)) + (void) printf("\n"); + } + (void) printf("\n"); + } + (void) printf("\n"); +} + +#endif + +static Bool +evalmovement(ModeInfo * mi, RubikMove movement) +{ + rubikstruct *rp = &rubik[MI_SCREEN(mi)]; + +#ifdef DEBUG + printCube(rp); +#endif + if (movement.face < 0 || movement.face >= MAXFACES) + return True; + if (!moveRubik(rp, movement.face, movement.direction, movement.position)) + return False; + return True; +} + +static Bool +compare_moves(rubikstruct * rp, RubikMove move1, RubikMove move2, Bool opp) +{ + RubikSlice slice1, slice2; + + convertMove(rp, move1, &slice1); + convertMove(rp, move2, &slice2); + if (slice1.face == slice2.face && + slice1.depth == slice2.depth) { + if (slice1.rotation == slice2.rotation) { /* CW or CCW */ + if (!opp) + return True; + } else { + if (opp) + return True; + } + } + return False; +} + +static Bool +shuffle(ModeInfo * mi) +{ + rubikstruct *rp = &rubik[MI_SCREEN(mi)]; + int i, face, position; + RubikMove move; + + if (sizex) + i = sizex; + else + i = MI_SIZE(mi); + if (i < -MINSIZE) + i = NRAND(-i - MINSIZE + 1) + MINSIZE; + else if (i < MINSIZE) + i = MINSIZE; + + if (LRAND() % 2 && !sizey && !sizez) { /* Make normal (NxNxN) cubes more likely */ + MAXSIZEX = MAXSIZEY = MAXSIZEZ = i; + } else { + MAXSIZEX = i; + if (sizey) + i = sizey; + else + i = MI_SIZE(mi); + if (i < -MINSIZE) + i = NRAND(-i - MINSIZE + 1) + MINSIZE; + else if (i < MINSIZE) + i = MINSIZE; + if (LRAND() % 2 && !sizez) { /* Make more MxNxN more likely than LxMxN */ + MAXSIZEY = MAXSIZEZ = i; + } else { + MAXSIZEY = i; + if (sizez) + i = sizez; + else + i = MI_SIZE(mi); + if (i < -MINSIZE) + i = NRAND(-i - MINSIZE + 1) + MINSIZE; + else if (i < MINSIZE) + i = MINSIZE; + MAXSIZEZ = i; + } + } + + for (face = 0; face < MAXFACES; face++) { + if (rp->cubeLoc[face] != NULL) + (void) free((void *) rp->cubeLoc[face]); + if ((rp->cubeLoc[face] = (RubikLoc *) malloc(sizeFace(rp, face) * + sizeof (RubikLoc))) == NULL) { + return False; + } + for (position = 0; position < sizeFace(rp, face); position++) { + rp->cubeLoc[face][position].face = face; + rp->cubeLoc[face][position].rotation = TOP; + } + } + for (i = 0; i < MAXORIENT; i++) { + if (rp->rowLoc[i] != NULL) + (void) free((void *) rp->rowLoc[i]); + /* The following is reused so make it the biggest size */ + if ((rp->rowLoc[i] = (RubikLoc *) malloc(MAXMAXSIZE * + sizeof (RubikLoc))) == NULL) { + return False; + } + } + rp->storedmoves = MI_COUNT(mi); + if (rp->storedmoves < 0) { + if (rp->moves != NULL) + (void) free((void *) rp->moves); + rp->moves = (RubikMove *) NULL; + rp->storedmoves = NRAND(-rp->storedmoves) + 1; + } + if ((rp->storedmoves) && (rp->moves == NULL)) + if ((rp->moves = (RubikMove *) calloc(rp->storedmoves + 1, + sizeof (RubikMove))) == NULL) { + return False; + } + if (MI_CYCLES(mi) <= 1) { + rp->anglestep = 90.0; + } else { + rp->anglestep = 90.0 / (GLfloat) (MI_CYCLES(mi)); + } + + for (i = 0; i < rp->storedmoves; i++) { + Bool condition; + + do { + move.face = NRAND(MAXFACES); + move.direction = NRAND(MAXORIENT); /* Exclude CW and CCW, its ok */ + move.position = NRAND(sizeFace(rp, move.face)); + rp->degreeTurn = (checkFaceSquare(rp, + rowToRotate[move.face][move.direction])) ? 90 : 180; + condition = True; + if (i > 0) { /* avoid immediate undoing moves */ + if (compare_moves(rp, move, rp->moves[i - 1], True)) + condition = False; + if (rp->degreeTurn == 180 && + compare_moves(rp, move, rp->moves[i - 1], False)) + condition = False; + } + if (i > 1) /* avoid 3 consecutive identical moves */ + if (compare_moves(rp, move, rp->moves[i - 1], False) && + compare_moves(rp, move, rp->moves[i - 2], False)) + condition = False; + /* + * Still some silly moves being made.... + */ + } while (!condition); + if (hideshuffling) + if (!evalmovement(mi, move)) + return False; + rp->moves[i] = move; + } + rp->VX = 0.005; + if (NRAND(100) < 50) + rp->VX *= -1; + rp->VY = 0.005; + if (NRAND(100) < 50) + rp->VY *= -1; + rp->movement.face = NO_FACE; + rp->rotatestep = 0; + rp->action = hideshuffling ? ACTION_SOLVE : ACTION_SHUFFLE; + rp->shufflingmoves = 0; + rp->done = 0; + return True; +} + +ENTRYPOINT void +reshape_rubik(ModeInfo * mi, int width, int height) +{ + rubikstruct *rp = &rubik[MI_SCREEN(mi)]; + + glViewport(0, 0, rp->WindW = (GLint) width, rp->WindH = (GLint) height); + glMatrixMode(GL_PROJECTION); + glLoadIdentity(); + glFrustum(-1.0, 1.0, -1.0, 1.0, 5.0, 15.0); + glMatrixMode(GL_MODELVIEW); + +} + +ENTRYPOINT Bool +rubik_handle_event (ModeInfo *mi, XEvent *event) +{ + rubikstruct *rp = &rubik[MI_SCREEN(mi)]; + + if (event->xany.type == ButtonPress && + event->xbutton.button == Button1) + { + rp->button_down_p = True; + gltrackball_start (rp->trackball, + event->xbutton.x, event->xbutton.y, + MI_WIDTH (mi), MI_HEIGHT (mi)); + return True; + } + else if (event->xany.type == ButtonRelease && + event->xbutton.button == Button1) + { + rp->button_down_p = False; + return True; + } + else if (event->xany.type == ButtonPress && + (event->xbutton.button == Button4 || + event->xbutton.button == Button5 || + event->xbutton.button == Button6 || + event->xbutton.button == Button7)) + { + gltrackball_mousewheel (rp->trackball, event->xbutton.button, 10, + !!event->xbutton.state); + return True; + } + else if (event->xany.type == MotionNotify && + rp->button_down_p) + { + gltrackball_track (rp->trackball, + event->xmotion.x, event->xmotion.y, + MI_WIDTH (mi), MI_HEIGHT (mi)); + return True; + } + + return False; +} + + +static Bool +pinit(ModeInfo * mi) +{ + glClearDepth(1.0); + glColor3f(1.0, 1.0, 1.0); + + glLightfv(GL_LIGHT0, GL_AMBIENT, ambient); + glLightfv(GL_LIGHT0, GL_DIFFUSE, diffuse); + glLightfv(GL_LIGHT0, GL_POSITION, position0); + glLightfv(GL_LIGHT1, GL_AMBIENT, ambient); + glLightfv(GL_LIGHT1, GL_DIFFUSE, diffuse); + glLightfv(GL_LIGHT1, GL_POSITION, position1); + glLightModelfv(GL_LIGHT_MODEL_AMBIENT, lmodel_ambient); + glLightModelfv(GL_LIGHT_MODEL_TWO_SIDE, lmodel_twoside); + glEnable(GL_LIGHTING); + glEnable(GL_LIGHT0); + glEnable(GL_LIGHT1); + glEnable(GL_DEPTH_TEST); + glEnable(GL_NORMALIZE); + glEnable(GL_CULL_FACE); + + glShadeModel(GL_FLAT); + glMaterialfv(GL_FRONT_AND_BACK, GL_SHININESS, front_shininess); + glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, front_specular); + + return (shuffle(mi)); +} + +static void +free_rubik(rubikstruct *rp) +{ + int i; + + for (i = 0; i < MAXFACES; i++) + if (rp->cubeLoc[i] != NULL) { + (void) free((void *) rp->cubeLoc[i]); + rp->cubeLoc[i] = (RubikLoc *) NULL; + } + for (i = 0; i < MAXORIENT; i++) + if (rp->rowLoc[i] != NULL) { + (void) free((void *) rp->rowLoc[i]); + rp->rowLoc[i] = (RubikLoc *) NULL; + } + if (rp->moves != NULL) { + (void) free((void *) rp->moves); + rp->moves = (RubikMove *) NULL; + } +} + +ENTRYPOINT void +release_rubik(ModeInfo * mi) +{ + if (rubik != NULL) { + int screen; + + for (screen = 0; screen < MI_NUM_SCREENS(mi); screen++) { + rubikstruct *rp = &rubik[screen]; + + free_rubik(rp); + } + (void) free((void *) rubik); + rubik = (rubikstruct *) NULL; + } + FreeAllGL(mi); +} + +ENTRYPOINT void +init_rubik(ModeInfo * mi) +{ + rubikstruct *rp; + + if (rubik == NULL) { + if ((rubik = (rubikstruct *) calloc(MI_NUM_SCREENS(mi), + sizeof (rubikstruct))) == NULL) + return; + } + rp = &rubik[MI_SCREEN(mi)]; + rp->step = NRAND(90); + rp->PX = ((float) LRAND() / (float) MAXRAND) * 2.0 - 1.0; + rp->PY = ((float) LRAND() / (float) MAXRAND) * 2.0 - 1.0; + + rp->trackball = gltrackball_init (); + + if ((rp->glx_context = init_GL(mi)) != NULL) { + + reshape_rubik(mi, MI_WIDTH(mi), MI_HEIGHT(mi)); + glDrawBuffer(GL_BACK); + if (!pinit(mi)) { + free_rubik(rp); + if (MI_IS_VERBOSE(mi)) { + (void) fprintf(stderr, + "Could not allocate memory for rubik\n"); + } + return; + } + } else { + MI_CLEARWINDOW(mi); + } +} + +ENTRYPOINT void +draw_rubik(ModeInfo * mi) +{ + Bool bounced = False; + Display *display = MI_DISPLAY(mi); + Window window = MI_WINDOW(mi); + rubikstruct *rp; + + if (rubik == NULL) + return; + rp = &rubik[MI_SCREEN(mi)]; + if (rp->cubeLoc[0] == NULL) + return; + + MI_IS_DRAWN(mi) = True; + if (!rp->glx_context) + return; + + mi->polygon_count = 0; + glXMakeCurrent(display, window, *(rp->glx_context)); + + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + + glPushMatrix(); + + glTranslatef(0.0, 0.0, -10.0); + + rp->PX += rp->VX; + rp->PY += rp->VY; + + if (rp->PY < -1) { + rp->PY += (-1) - (rp->PY); + rp->VY = -rp->VY; + bounced = True; + } + if (rp->PY > 1) { + rp->PY -= (rp->PY) - 1; + rp->VY = -rp->VY; + bounced = True; + } + if (rp->PX < -1) { + rp->PX += (-1) - (rp->PX); + rp->VX = -rp->VX; + bounced = True; + } + if (rp->PX > 1) { + rp->PX -= (rp->PX) - 1; + rp->VX = -rp->VX; + bounced = True; + } + if (bounced) { + rp->VX += ((float) LRAND() / (float) MAXRAND) * 0.002 - 0.001; + rp->VY += ((float) LRAND() / (float) MAXRAND) * 0.002 - 0.001; + if (rp->VX > 0.006) + rp->VX = 0.006; + if (rp->VY > 0.006) + rp->VY = 0.006; + if (rp->VX < -0.006) + rp->VX = -0.006; + if (rp->VY < -0.006) + rp->VY = -0.006; + } + if (!MI_IS_ICONIC(mi)) { + glTranslatef(rp->PX, rp->PY, 0); + glScalef(Scale4Window * rp->WindH / rp->WindW, Scale4Window, Scale4Window); + } else { + glScalef(Scale4Iconic * rp->WindH / rp->WindW, Scale4Iconic, Scale4Iconic); + } + + /* Do it twice because we don't track the device's orientation. */ + glRotatef( current_device_rotation(), 0, 0, 1); + gltrackball_rotate (rp->trackball); + glRotatef(-current_device_rotation(), 0, 0, 1); + + glRotatef(rp->step * 100, 1, 0, 0); + glRotatef(rp->step * 95, 0, 1, 0); + glRotatef(rp->step * 90, 0, 0, 1); + + if (!draw_cube(mi)) { + release_rubik(mi); + return; + } + if (MI_IS_FPS(mi)) do_fps (mi); + glXSwapBuffers(display, window); + + if (rp->action == ACTION_SHUFFLE) { + if (rp->done) { + if (++rp->rotatestep > DELAY_AFTER_SHUFFLING) { + rp->movement.face = NO_FACE; + rp->rotatestep = 0; + rp->action = ACTION_SOLVE; + rp->done = 0; + } + } else { + if (rp->movement.face == NO_FACE) { + if (rp->shufflingmoves < rp->storedmoves) { + rp->rotatestep = 0; + rp->movement = rp->moves[rp->shufflingmoves]; + } else { + rp->rotatestep = 0; + rp->done = 1; + } + } else { + if (rp->rotatestep == 0) { + if (rp->movement.direction == CW || rp->movement.direction == CCW) + rp->degreeTurn = (checkFaceSquare(rp, rp->movement.face)) ? 90 : 180; + else + rp->degreeTurn = (checkFaceSquare(rp, rowToRotate[rp->movement.face][rp->movement.direction])) ? 90 : 180; + } + rp->rotatestep += rp->anglestep; + if (rp->rotatestep > rp->degreeTurn) { + if (!evalmovement(mi, rp->movement)) { + free_rubik(rp); + if (MI_IS_VERBOSE(mi)) { + (void) fprintf(stderr, + "Could not allocate memory for rubik\n"); + } + return; + } + rp->shufflingmoves++; + rp->movement.face = NO_FACE; + } + } + } + } else { + if (rp->done) { + if (++rp->rotatestep > DELAY_AFTER_SOLVING) + if (!shuffle(mi)) { + free_rubik(rp); + if (MI_IS_VERBOSE(mi)) { + (void) fprintf(stderr, + "Could not allocate memory for rubik\n"); + } + return; + } + } else { + if (rp->movement.face == NO_FACE) { + if (rp->storedmoves > 0) { + rp->rotatestep = 0; + rp->movement = rp->moves[rp->storedmoves - 1]; + rp->movement.direction = (rp->movement.direction + + (MAXORIENT / 2)) % MAXORIENT; + } else { + rp->rotatestep = 0; + rp->done = 1; + } + } else { + if (rp->rotatestep == 0) { + if (rp->movement.direction == CW || rp->movement.direction == CCW) + rp->degreeTurn = (checkFaceSquare(rp, rp->movement.face)) ? 90 : 180; + else + rp->degreeTurn = (checkFaceSquare(rp, rowToRotate[rp->movement.face][rp->movement.direction])) ? 90 : 180; + } + rp->rotatestep += rp->anglestep; + if (rp->rotatestep > rp->degreeTurn) { + if (!evalmovement(mi, rp->movement)) { + free_rubik(rp); + if (MI_IS_VERBOSE(mi)) { + (void) fprintf(stderr, + "Could not allocate memory for rubik\n"); + } + return; + } + rp->storedmoves--; + rp->movement.face = NO_FACE; + } + } + } + } + + glPopMatrix(); + + glFlush(); + + rp->step += 0.002; +} + +#ifndef STANDALONE +ENTRYPOINT void +change_rubik(ModeInfo * mi) +{ + rubikstruct *rp; + + if (rubik == NULL) + return; + rp = &rubik[MI_SCREEN(mi)]; + + if (!rp->glx_context) + return; + if (!pinit(mi)) { + free_rubik(rp); + if (MI_IS_VERBOSE(mi)) { + (void) fprintf(stderr, + "Could not allocate memory for rubik\n"); + } + return; + } +} +#endif /* !STANDALONE */ + +#endif + +XSCREENSAVER_MODULE ("Rubik", rubik) diff --git a/hacks/glx/rubik.man b/hacks/glx/rubik.man new file mode 100644 index 00000000..08e5b94e --- /dev/null +++ b/hacks/glx/rubik.man @@ -0,0 +1,69 @@ +.TH XScreenSaver 1 "" "X Version 11" +.SH NAME +rubik - screen saver that solves Rubik's Cube. +.SH SYNOPSIS +.B rubik +[\-display \fIhost:display.screen\fP] +[\-visual \fIvisual\fP] +[\-window] +[\-root] +[\-count \fInumber\fP] +[\-cycles \fInumber\fP] +[\-delay \fInumber\fP] +[\-size \fInumber\fP] +[\-hideshuffling] +[\-fps] +.SH DESCRIPTION +Draws a Rubik's Cube that rotates in three dimensions and repeatedly +shuffles and solves itself. +.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 \-count \fInumber\fP +Count. -100 - 100. Default: -30. +.TP 8 +.B \-cycles \fInumber\fP +Timeout. 0 - 60. Default: 5. +.TP 8 +.B \-delay \fInumber\fP +Per-frame delay, in microseconds. Default: 40000 (0.04 seconds.). +.TP 8 +.B \-size \fInumber\fP +Size. -20 - 20. Default: -6. +.TP 8 +.B \-hideshuffling | \-no-hideshuffling +Show Shuffling. Boolean. +.TP 8 +.B \-fps +Display the current frame rate, CPU load, and polygon count. +.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 2002 by Marcelo Vianna. 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 +Marcelo Vianna. diff --git a/hacks/glx/rubikblocks.c b/hacks/glx/rubikblocks.c new file mode 100644 index 00000000..54c41341 --- /dev/null +++ b/hacks/glx/rubikblocks.c @@ -0,0 +1,662 @@ +/* rubikblocks, Copyright (c) 2009 Vasek Potocek + * + * 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. + */ + +/* RubikBlocks - a Rubik's Mirror Blocks puzzle introduced in 2008. + * No mirrors in this version, though, hence the altered name. + */ + +/* TODO: + * add reflection to the faces + */ + +#define DEFAULTS "*delay: 20000 \n" \ + "*showFPS: False \n" \ + "*wireframe: False \n" + +# define refresh_rubikblocks 0 +#include "xlockmore.h" +#include "rotator.h" +#include "gltrackball.h" + +#ifdef USE_GL + +#define DEF_SPIN "True" +#define DEF_WANDER "True" +#define DEF_TEXTURE "True" +#define DEF_RANDOMIZE "False" +#define DEF_SPINSPEED "0.1" +#define DEF_ROTSPEED "3.0" +#define DEF_WANDERSPEED "0.005" +#define DEF_WAIT "40.0" +#define DEF_CUBESIZE "1.0" + +#define SHUFFLE 100 + +#define TEX_WIDTH 64 +#define TEX_HEIGHT 64 +#define BORDER 5 +#define BORDER2 (BORDER*BORDER) + +#undef countof +#define countof(x) (sizeof((x))/sizeof((*x))) + +#define rnd01() ((int)(random()%2)) + +/*************************************************************************/ + +static Bool spin, wander, rndstart, tex; +static float spinspeed, tspeed, wspeed, twait, size; + +static argtype vars[] = { + { &spin, "spin", "Spin", DEF_SPIN, t_Bool}, + { &wander, "wander", "Wander", DEF_WANDER, t_Bool}, + { &rndstart, "randomize", "Randomize", DEF_RANDOMIZE, t_Bool}, + { &tex, "texture", "Texture", DEF_TEXTURE, t_Bool}, + { &spinspeed, "spinspeed", "SpinSpeed", DEF_SPINSPEED, t_Float}, + { &tspeed, "rotspeed", "RotSpeed", DEF_ROTSPEED, t_Float}, + { &wspeed, "wanderspeed", "WanderSpeed", DEF_WANDERSPEED, t_Float}, + { &twait, "wait", "Wait", DEF_WAIT, t_Float}, + { &size, "cubesize", "CubeSize", DEF_CUBESIZE, t_Float}, +}; + +static XrmOptionDescRec opts[] = { + { "-spin", ".spin", XrmoptionNoArg, "True" }, + { "+spin", ".spin", XrmoptionNoArg, "False" }, + { "-wander", ".wander", XrmoptionNoArg, "True" }, + { "+wander", ".wander", XrmoptionNoArg, "False" }, + { "-randomize", ".randomize", XrmoptionNoArg, "True" }, + { "+randomize", ".randomize", XrmoptionNoArg, "False" }, + { "-texture", ".texture", XrmoptionNoArg, "True" }, + { "+texture", ".texture", XrmoptionNoArg, "False" }, + { "-spinspeed", ".spinspeed", XrmoptionSepArg, 0 }, + { "-wanderspeed", ".wanderspeed", XrmoptionSepArg, 0 }, + { "-rotspeed", ".rotspeed", XrmoptionSepArg, 0 }, + { "-wait", ".wait", XrmoptionSepArg, 0 }, + { "-cubesize", ".cubesize", XrmoptionSepArg, 0 }, +}; + +ENTRYPOINT ModeSpecOpt rubikblocks_opts = {countof(opts), opts, countof(vars), vars, NULL}; + +#ifdef USE_MODULES +ModStruct rubikblocks_description = +{ "rubikblocks", "init_rubikblocks", "draw_rubikblocks", "release_rubikblocks", + "draw_rubikblocks", "change_rubikblocks", NULL, &rubikblocks_opts, + 25000, 1, 1, 1, 1.0, 4, "", + "Shows randomly shuffling Rubik's Mirror Blocks puzzle", 0, NULL +}; +#endif + +typedef struct { + float pos[3]; /* _original_ position */ + float qr[4]; /* quaternion of rotation */ + Bool act; /* flag if it is undergoing the current rotation */ +} piece_t; + +typedef struct { + GLXContext *glx_context; + rotator *rot; + trackball_state *trackball; + GLfloat ratio; + Bool button_down; + + Bool pause; /* pause between two rotations */ + float qfram[4]; /* quaternion describing the rotation in one anim. frame */ + GLfloat t, tmax; /* rotation clock */ + piece_t pieces[27]; /* type and tilt of all the pieces */ + + unsigned char texture[TEX_HEIGHT][TEX_WIDTH]; + GLuint list_base; + Bool wire; +} rubikblocks_conf; + +static rubikblocks_conf *rubikblocks = NULL; + +static const GLfloat shininess = 20.0; +static const GLfloat ambient[] = {0.0, 0.0, 0.0, 1.0}; +static const GLfloat diffuse[] = {1.0, 1.0, 1.0, 1.0}; +static const GLfloat position0[] = {1.0, 1.0, 1.0, 0.0}; +static const GLfloat position1[] = {-1.0, -1.0, 1.0, 0.0}; +static const GLfloat lmodel_ambient[] = {0.1, 0.1, 0.1, 1.0}; +static const GLfloat material_ambient[] = {0.7, 0.7, 0.7, 1.0}; +static const GLfloat material_diffuse[] = {0.7, 0.7, 0.7, 1.0}; +static const GLfloat material_specular[] = {0.2, 0.2, 0.2, 1.0}; +static const GLfloat zpos = -18.0; + +/*************************************************************************/ + +/* Multiplies two quaternions, src*dest, and stores the result in dest. */ +static void +mult_quat(float src[4], float dest[4]) +{ + float r, i, j, k; + r = src[0]*dest[0] - src[1]*dest[1] - src[2]*dest[2] - src[3]*dest[3]; + i = src[0]*dest[1] + src[1]*dest[0] + src[2]*dest[3] - src[3]*dest[2]; + j = src[0]*dest[2] + src[2]*dest[0] + src[3]*dest[1] - src[1]*dest[3]; + k = src[0]*dest[3] + src[3]*dest[0] + src[1]*dest[2] - src[2]*dest[1]; + dest[0] = r; + dest[1] = i; + dest[2] = j; + dest[3] = k; +} + +/* Sets the 'act' flag for pieces which will undergo the rotation. */ +static void +flag_pieces(piece_t pieces[27], int axis, int side) +{ + int i, j; + float q[4]; + for(i = 0; i < 27; i++) + { + q[0] = 0; + q[1] = pieces[i].pos[0]; + q[2] = pieces[i].pos[1]; + q[3] = pieces[i].pos[2]; + mult_quat(pieces[i].qr, q); + for(j = 1; j < 4; j++) + q[j] = -q[j]; + mult_quat(pieces[i].qr, q); + for(j = 1; j < 4; j++) + q[j] = -q[j]; + if(fabs(q[axis] - side) < 0.1) + pieces[i].act = True; + else + pieces[i].act = False; + } +} + +/* "Rounds" the value to the nearest from the set {0, +-1/2, +-1/sqrt(2), +-1}. + * It is guaranteed to be pretty close to one when this function is called. */ +static float +settle_value(float v) +{ + if(v > 0.9) return 1; + else if(v < -0.9) return -1; + else if(v > 0.6) return M_SQRT1_2; + else if(v < -0.6) return -M_SQRT1_2; + else if(v > 0.4) return 0.5; + else if(v < -0.4) return -0.5; + else return 0; +} + +static void +randomize(rubikblocks_conf *cp) +{ + int axis, side; + int i, j; + for(i = 0; i < SHUFFLE; i++) + { + axis = (random()%3)+1; + side = rnd01()*2-1; + flag_pieces(cp->pieces, axis, side); + for(j = 1; j < 4; j++) + cp->qfram[j] = 0; + cp->qfram[0] = M_SQRT1_2; + cp->qfram[axis] = M_SQRT1_2; + for(j = 0; j < 27; j++) + { + if(cp->pieces[j].act) + mult_quat(cp->qfram, cp->pieces[j].qr); + } + } +} + +static void +finish(rubikblocks_conf *cp) +{ + static int axis = 1; + int side, angle; + int i, j; + if(cp->pause) + { + switch(axis) + { + case 1: + axis = rnd01()+2; + break; + case 2: + axis = 2*rnd01()+1; + break; + default: + axis = rnd01()+1; + } + side = rnd01()*2-1; + angle = rnd01()+1; + flag_pieces(cp->pieces, axis, side); + cp->pause = False; + cp->tmax = 90.0*angle; + for(i = 1; i < 4; i++) + cp->qfram[i] = 0; + cp->qfram[0] = cos(tspeed*M_PI/360); + cp->qfram[axis] = sin((rnd01()*2-1)*tspeed*M_PI/360); + } + else + { + for(i = 0; i < 27; i++) + { + for(j = 0; j < 4; j++) + { + cp->pieces[i].qr[j] = settle_value(cp->pieces[i].qr[j]); + } + } + cp->pause = True; + cp->tmax = twait; + } + cp->t = 0; +} + +static Bool +draw_main(ModeInfo *mi, rubikblocks_conf *cp) +{ + int i; + double x, y, z; + + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + glLoadIdentity(); + get_position(cp->rot, &x, &y, &z, !cp->button_down); + glTranslatef((x-0.5)*6, (y-0.5)*6, -20); + + /* Do it twice because we don't track the device's orientation. */ + glRotatef( current_device_rotation(), 0, 0, 1); + gltrackball_rotate(cp->trackball); + glRotatef(-current_device_rotation(), 0, 0, 1); + + get_rotation(cp->rot, &x, &y, &z, !cp->button_down); + glRotatef(x*360, 1, 0, 0); + glRotatef(y*360, 0, 1, 0); + glRotatef(z*360, 0, 0, 1); + glScalef(size, size, size); + + if(cp->wire) glColor3f(0.7, 0.7, 0.7); + if(!cp->pause) + for(i = 0; i < 27; i++) + if(cp->pieces[i].act) + mult_quat(cp->qfram, cp->pieces[i].qr); + for(i = 0; i < 27; i++) + { + glPushMatrix(); + if(fabs(cp->pieces[i].qr[0]) < 1) + glRotatef(360/M_PI*acos(cp->pieces[i].qr[0]), + cp->pieces[i].qr[1], cp->pieces[i].qr[2], cp->pieces[i].qr[3]); + glCallList(cp->list_base + i); + glPopMatrix(); + } + if((cp->t += tspeed) > cp->tmax) finish(cp); + return True; +} + +static void +draw_horz_line(rubikblocks_conf *cp, int x1, int x2, int y) +{ + int x, y0 = y, w; + if(y < BORDER) y = -y; + else y = -BORDER; + for(; y < BORDER; y++) { + if(y0+y >= TEX_HEIGHT) break; + w = y*y*255/BORDER2; + for(x = x1; x <= x2; x++) + if(cp->texture[y0+y][x]>w) cp->texture[y0+y][x] = w; + } +} + +static void +draw_vert_line(rubikblocks_conf *cp, int x, int y1, int y2) +{ + int x0 = x, y, w; + if(x= TEX_WIDTH) break; + w = x*x*255/BORDER2; + for(y = y1; y <= y2; y++) + if(cp->texture[y][x0+x]>w) cp->texture[y][x0+x] = w; + } +} + +static void +make_texture(rubikblocks_conf *cp) +{ + int x, y; + for(y = 0; y < TEX_HEIGHT; y++) + for(x = 0; x < TEX_WIDTH; x++) + cp->texture[y][x] = 255; + draw_horz_line(cp, 0, TEX_WIDTH-1, 0); + draw_horz_line(cp, 0, TEX_WIDTH-1, TEX_HEIGHT-1); + draw_vert_line(cp, 0, 0, TEX_HEIGHT-1); + draw_vert_line(cp, TEX_WIDTH-1, 0, TEX_HEIGHT-1); +} + +/* These simple transforms make the actual shape of the pieces. The parameters + * A, B and C affect the excentricity of the pieces in each direction. */ +static float +fx(float x) +{ + const float A = 0.5; + if(x > 1.4) return 1.5 - A; + else if(x < -1.4) return -1.5 - A; + else return x; +} + +static float +fy(float y) +{ + const float B = 0.25; + if(y > 1.4) return 1.5 - B; + else if(y < -1.4) return -1.5 - B; + else return y; +} + +static float +fz(float z) +{ + const float C = 0.0; + if(z > 1.4) return 1.5 - C; + else if(z < -1.4) return -1.5 - C; + else return z; +} + +static void +init_lists(rubikblocks_conf *cp) +{ + GLuint base; + int i; + float x, y, z; + base = cp->list_base = glGenLists(27); + for(i = 0; i < 27; i++) + { + x = cp->pieces[i].pos[0]; + y = cp->pieces[i].pos[1]; + z = cp->pieces[i].pos[2]; + glNewList(base+i, GL_COMPILE); + glBegin(GL_QUAD_STRIP); + glNormal3f(1, 0, 0); + glTexCoord2f(0, 0); + glVertex3f(fx(x+0.5), fy(y-0.5), fz(z-0.5)); + glTexCoord2f(0, 1); + glVertex3f(fx(x+0.5), fy(y+0.5), fz(z-0.5)); + glTexCoord2f(1, 0); + glVertex3f(fx(x+0.5), fy(y-0.5), fz(z+0.5)); + glTexCoord2f(1, 1); + glVertex3f(fx(x+0.5), fy(y+0.5), fz(z+0.5)); + glNormal3f(0, 0, 1); + glTexCoord2f(0, 0); + glVertex3f(fx(x-0.5), fy(y-0.5), fz(z+0.5)); + glTexCoord2f(0, 1); + glVertex3f(fx(x-0.5), fy(y+0.5), fz(z+0.5)); + glNormal3f(-1, 0, 0); + glTexCoord2f(1, 0); + glVertex3f(fx(x-0.5), fy(y-0.5), fz(z-0.5)); + glTexCoord2f(1, 1); + glVertex3f(fx(x-0.5), fy(y+0.5), fz(z-0.5)); + glNormal3f(0, 0, -1); + glTexCoord2f(0, 0); + glVertex3f(fx(x+0.5), fy(y-0.5), fz(z-0.5)); + glTexCoord2f(0, 1); + glVertex3f(fx(x+0.5), fy(y+0.5), fz(z-0.5)); + glEnd(); + glBegin(GL_QUADS); + glNormal3f(0, 1, 0); + glTexCoord2f(0, 0); + glVertex3f(fx(x+0.5), fy(y+0.5), fz(z+0.5)); + glTexCoord2f(0, 1); + glVertex3f(fx(x+0.5), fy(y+0.5), fz(z-0.5)); + glTexCoord2f(1, 1); + glVertex3f(fx(x-0.5), fy(y+0.5), fz(z-0.5)); + glTexCoord2f(1, 0); + glVertex3f(fx(x-0.5), fy(y+0.5), fz(z+0.5)); + glNormal3f(0, -1, 0); + glTexCoord2f(0, 0); + glVertex3f(fx(x+0.5), fy(y-0.5), fz(z-0.5)); + glTexCoord2f(0, 1); + glVertex3f(fx(x+0.5), fy(y-0.5), fz(z+0.5)); + glTexCoord2f(1, 1); + glVertex3f(fx(x-0.5), fy(y-0.5), fz(z+0.5)); + glTexCoord2f(1, 0); + glVertex3f(fx(x-0.5), fy(y-0.5), fz(z-0.5)); + glEnd(); + glEndList(); + } +} + +/* It looks terrible... FIXME: any other ideas, maybe some anisotropic filtering? */ +/*#define MIPMAP*/ + +static void +init_gl(ModeInfo *mi) +{ + rubikblocks_conf *cp = &rubikblocks[MI_SCREEN(mi)]; +#ifdef MIPMAP + int status; +#endif + cp->wire = MI_IS_WIREFRAME(mi); + +# ifdef HAVE_JWZGLES /* #### glPolygonMode other than GL_FILL unimplemented */ + cp->wire = 0; +# endif + + if(MI_IS_MONO(mi)) + tex = False; + if(cp->wire) { + glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); + return; + } + + glClearDepth(1.0); + glDrawBuffer(GL_BACK); + glPixelStorei(GL_UNPACK_ALIGNMENT, 1); + glShadeModel(GL_FLAT); + glDepthFunc(GL_LESS); + glLightfv(GL_LIGHT0, GL_AMBIENT, ambient); + glLightfv(GL_LIGHT0, GL_DIFFUSE, diffuse); + glLightfv(GL_LIGHT0, GL_POSITION, position0); + glLightfv(GL_LIGHT1, GL_AMBIENT, ambient); + glLightfv(GL_LIGHT1, GL_DIFFUSE, diffuse); + glLightfv(GL_LIGHT1, GL_POSITION, position1); + glLightModelfv(GL_LIGHT_MODEL_AMBIENT, lmodel_ambient); + glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, GL_FALSE); + glEnable(GL_DEPTH_TEST); + glEnable(GL_LIGHT0); + glEnable(GL_LIGHT1); + glEnable(GL_LIGHTING); + glEnable(GL_NORMALIZE); + glEnable(GL_COLOR_MATERIAL); + glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, material_ambient); + glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, material_diffuse); + glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, material_specular); + glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, shininess); + if (!tex) return; + glEnable(GL_TEXTURE_2D); +#ifdef MIPMAP + clear_gl_error(); + status = gluBuild2DMipmaps(GL_TEXTURE_2D, 1, TEX_WIDTH, TEX_HEIGHT, + GL_LUMINANCE, GL_UNSIGNED_BYTE, cp->texture); + if (status) { + const char *s = (char *)gluErrorString(status); + fprintf (stderr, "%s: error mipmapping texture: %s\n", progname, (s?s:"(unknown)")); + exit (1); + } + check_gl_error("mipmapping"); +#else + glTexImage2D(GL_TEXTURE_2D, 0, 1, TEX_WIDTH, TEX_HEIGHT, + 0, GL_LUMINANCE, GL_UNSIGNED_BYTE, cp->texture); +#endif + glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); + glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP); + glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP); + glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); +#ifdef MIPMAP + glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR); +#else + glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); +#endif +} + +static void +init_cp(rubikblocks_conf *cp) +{ + int i, j, k, m; + + cp->pause = True; + cp->t = 0.0; + cp->tmax = twait; + + for(i = -1, m = 0; i <= 1; i++) + for(j = -1; j <= 1; j++) + for(k = -1; k <= 1; k++) + { + cp->pieces[m].pos[0] = k; + cp->pieces[m].pos[1] = j; + cp->pieces[m].pos[2] = i; + cp->pieces[m].qr[0] = 1; + cp->pieces[m].qr[1] = 0; + cp->pieces[m].qr[2] = 0; + cp->pieces[m].qr[3] = 0; + m++; + } + + cp->rot = make_rotator(spin?spinspeed:0, spin?spinspeed:0, spin?spinspeed:0, + 0.1, wander?wspeed:0, True); + cp->trackball = gltrackball_init(); + + if(rndstart) randomize(cp); +} + +/*************************************************************************/ + +ENTRYPOINT void +reshape_rubikblocks(ModeInfo *mi, int width, int height) +{ + rubikblocks_conf *cp = &rubikblocks[MI_SCREEN(mi)]; + if(!height) height = 1; + cp->ratio = (GLfloat)width/(GLfloat)height; + glViewport(0, 0, (GLint) width, (GLint) height); + glMatrixMode(GL_PROJECTION); + glLoadIdentity(); + gluPerspective(30.0, cp->ratio, 1.0, 100.0); + glMatrixMode(GL_MODELVIEW); + glClear(GL_COLOR_BUFFER_BIT); +} + +ENTRYPOINT void +release_rubikblocks(ModeInfo *mi) +{ + if (rubikblocks != NULL) + { + int screen; + for (screen = 0; screen < MI_NUM_SCREENS(mi); screen++) + { + rubikblocks_conf *cp = &rubikblocks[screen]; + if (cp->glx_context) { + cp->glx_context = NULL; + } + } + free((void *)rubikblocks); + rubikblocks = NULL; + } + FreeAllGL(mi); +} + +ENTRYPOINT void +init_rubikblocks(ModeInfo *mi) +{ + rubikblocks_conf *cp; + if(!rubikblocks) + { + rubikblocks = (rubikblocks_conf *)calloc(MI_NUM_SCREENS(mi), sizeof(rubikblocks_conf)); + if(!rubikblocks) return; + } + cp = &rubikblocks[MI_SCREEN(mi)]; + + if(tex) + make_texture(cp); + + if ((cp->glx_context = init_GL(mi)) != NULL) + { + init_gl(mi); + init_cp(cp); + init_lists(cp); + reshape_rubikblocks(mi, MI_WIDTH(mi), MI_HEIGHT(mi)); + } + else + { + MI_CLEARWINDOW(mi); + } +} + +ENTRYPOINT void +draw_rubikblocks(ModeInfo * mi) +{ + Display *display = MI_DISPLAY(mi); + Window window = MI_WINDOW(mi); + rubikblocks_conf *cp; + if (!rubikblocks) return; + cp = &rubikblocks[MI_SCREEN(mi)]; + MI_IS_DRAWN(mi) = True; + if (!cp->glx_context) return; + mi->polygon_count = 0; + glXMakeCurrent(display, window, *(cp->glx_context)); + if (!draw_main(mi, cp)) + { + release_rubikblocks(mi); + return; + } + if (MI_IS_FPS(mi)) do_fps (mi); + glFlush(); + glXSwapBuffers(display, window); +} + +#ifndef STANDALONE +ENTRYPOINT void +change_rubikblocks(ModeInfo * mi) +{ + rubikblocks_conf *cp = &rubikblocks[MI_SCREEN(mi)]; + if (!cp->glx_context) return; + glXMakeCurrent(MI_DISPLAY(mi), MI_WINDOW(mi), *(cp->glx_context)); + init_gl(mi); +} +#endif /* !STANDALONE */ + +ENTRYPOINT Bool +rubikblocks_handle_event (ModeInfo *mi, XEvent *event) +{ + rubikblocks_conf *cp = &rubikblocks[MI_SCREEN(mi)]; + if(event->xany.type == ButtonPress && event->xbutton.button == Button1) + { + cp->button_down = True; + gltrackball_start(cp->trackball, event->xbutton.x, event->xbutton.y, + MI_WIDTH(mi), MI_HEIGHT(mi)); + return True; + } + else if(event->xany.type == ButtonRelease && event->xbutton.button == Button1) + { + cp->button_down = False; + return True; + } + else if(event->xany.type == ButtonPress && + (event->xbutton.button == Button4 || event->xbutton.button == Button5 || + event->xbutton.button == Button6 || event->xbutton.button == Button7)) + { + gltrackball_mousewheel(cp->trackball, + event->xbutton.button, 5, !!event->xbutton.state); + return True; + } + else if(event->xany.type == MotionNotify && cp->button_down) + { + gltrackball_track(cp->trackball, event->xmotion.x, event->xmotion.y, + MI_WIDTH (mi), MI_HEIGHT (mi)); + return True; + } + return False; +} + + +XSCREENSAVER_MODULE ("RubikBlocks", rubikblocks) + +#endif diff --git a/hacks/glx/rubikblocks.man b/hacks/glx/rubikblocks.man new file mode 100644 index 00000000..c18d18f9 --- /dev/null +++ b/hacks/glx/rubikblocks.man @@ -0,0 +1,117 @@ +.TH XScreenSaver 1 "04-Feb-09" "X Version 11" +.SH NAME +rubikblocks - animates the Rubik's Mirror Blocks puzzle +.SH SYNOPSIS +.B rubikblocks +[\-display \fIhost:display.screen\fP] +[\-visual \fIvisual\fP] +[\-window] +[\-root] +[\-install] +[\-delay \fImicroseconds\fP] +[\-texture] [\-no\-texture] +[\-mono] +[\-wireframe] +[\-spin] [\-no\-spin] +[\-wander] [\-no\-wander] +[\-randomize] [\-no\-randomize] +[\-spinspeed \fInumber\fP] +[\-rotspeed \fInumber\fP] +[\-wanderspeed \fInumber\fP] +[\-wait \fInumber\fP] +[\-cubesize \fInumber\fP] +[\-fps] +.SH DESCRIPTION +This program animates a puzzle called Rubik's Mirror Blocks. +The moves are chosen randomly. +.SH OPTIONS +.I rubikblocks +accepts the following options: +.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 \-install +Install a private colormap for the window. +.TP 8 +.B \-visual \fIvisual\fP\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 \-delay \fImicroseconds\fP +How long to pause between frames. Default is 20000, or 0.02 second. +.TP 8 +.B \-texture +Use texture maps. This is the default. +.TP 8 +.B \-no\-texture +Use solid colors. Looks a bit weird. +.TP 8 +.B \-mono +Disable both texture maps and colors. Ditto. +.TP 8 +.B \-wireframe +Only draw outlines. Outlines of each piece, not only the whole object, are drawn. +.TP 8 +.B \-spin +Spin the whole object around X, Y and Z axes. This is the default. +.TP 8 +.B \-no\-spin +Do not spin, stay in the same tilt all the time. +.TP 8 +.B \-wander +Move the object around the screen. This is the default. +.TP 8 +.B \-no\-wander +Keep the object centered on the screen. +.TP 8 +.B \-randomize +Shuffle the puzzle randomly at startup. This is the default. +.TP 8 +.B \-no\-randomize +Do not shuffle at startup, begin at the shape of cube. +.TP 8 +.B \-spinspeed \fInumber\fP +The relative speed of spinning. Default is 1.0. +.TP 8 +.B \-rotspeed \fInumber\fP +The relative speed of the moves. Default is 3.0. Setting to \(<= 0.0 +makes the object stay at one configuration. +.TP 8 +.B \-wanderspeed \fInumber\fP +The relative speed of wandering around the screen. Default is 0.02. +.TP 8 +.B \-wait \fInumber\fP +How long to stay at final position after each move. The meaning of +the argument is again relative. Default is 40.0. +.TP 8 +.B \-cubesize \fInumber\fP +Size of the object. Value of 3.0 fills roughly all the screen. +.TP 8 +.B \-fps +Display the current frame rate, CPU load, and polygon count. +.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 2009 by Vasek Potocek. 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 +Vasek Potocek , 04-Feb-09. diff --git a/hacks/glx/s1_1.c b/hacks/glx/s1_1.c new file mode 100644 index 00000000..1f934296 --- /dev/null +++ b/hacks/glx/s1_1.c @@ -0,0 +1,1733 @@ +#include "gllist.h" +static const float data[]={ + 0.698103,-0.159073,-0.698103,0.667578,0.838781,-0.667578, + 0.92844,-0.14479,-0.342105,0.713281,0.838781,-0.591406, + 0.918718,-0.113815,-0.378157,0.721812,0.890313,-0.595062, + 0.698103,-0.159073,-0.698103,0.667578,0.838781,-0.667578, + 0.918718,-0.113815,-0.378157,0.721812,0.890313,-0.595062, + 0.705394,-0.069557,-0.705394,0.674281,0.890313,-0.674281, + 0.92844,-0.14479,-0.342105,0.713281,0.838781,-0.591406, + 0.991208,-0.132313,0,0.728516,0.838781,-0.5, + 0.995164,-0.09823,0,0.737656,0.890313,-0.5, + 0.995164,-0.09823,0,0.737656,0.890313,-0.5, + 0.918718,-0.113815,-0.378157,0.721812,0.890313,-0.595062, + 0.92844,-0.14479,-0.342105,0.713281,0.838781,-0.591406, + 0.995164,-0.09823,0,0.737656,0.890313,-0.5, + 0.911846,0.410531,0,0.738539,0.926712,-0.5, + 0.891913,0.278471,-0.356294,0.722453,0.926408,-0.595141, + 0.891913,0.278471,-0.356294,0.722453,0.926408,-0.595141, + 0.918718,-0.113815,-0.378157,0.721812,0.890313,-0.595062, + 0.995164,-0.09823,0,0.737656,0.890313,-0.5, + 0.891913,0.278471,-0.356294,0.722453,0.926408,-0.595141, + 0.66233,0.350197,-0.66233,0.674539,0.926104,-0.674539, + 0.705394,-0.069557,-0.705394,0.674281,0.890313,-0.674281, + 0.705394,-0.069557,-0.705394,0.674281,0.890313,-0.674281, + 0.918718,-0.113815,-0.378157,0.721812,0.890313,-0.595062, + 0.891913,0.278471,-0.356294,0.722453,0.926408,-0.595141, + 0.698103,-0.159073,0.698103,0.667578,0.838781,-0.332422, + 0.705394,-0.069557,0.705394,0.674281,0.890313,-0.325719, + 0.918719,-0.113815,0.378157,0.721812,0.890313,-0.404938, + 0.698103,-0.159073,0.698103,0.667578,0.838781,-0.332422, + 0.918719,-0.113815,0.378157,0.721812,0.890313,-0.404938, + 0.92844,-0.14479,0.342105,0.713281,0.838781,-0.408594, + 0.705394,-0.069557,0.705394,0.674281,0.890313,-0.325719, + 0.66233,0.350196,0.66233,0.674539,0.926104,-0.325461, + 0.891913,0.278471,0.356294,0.722453,0.926408,-0.404859, + 0.891913,0.278471,0.356294,0.722453,0.926408,-0.404859, + 0.918719,-0.113815,0.378157,0.721812,0.890313,-0.404938, + 0.705394,-0.069557,0.705394,0.674281,0.890313,-0.325719, + 0.891913,0.278471,0.356294,0.722453,0.926408,-0.404859, + 0.911846,0.410531,0,0.738539,0.926712,-0.5, + 0.995164,-0.09823,0,0.737656,0.890313,-0.5, + 0.995164,-0.09823,0,0.737656,0.890313,-0.5, + 0.918719,-0.113815,0.378157,0.721812,0.890313,-0.404938, + 0.891913,0.278471,0.356294,0.722453,0.926408,-0.404859, + 0.995164,-0.09823,0,0.737656,0.890313,-0.5, + 0.991208,-0.132313,0,0.728516,0.838781,-0.5, + 0.92844,-0.14479,0.342105,0.713281,0.838781,-0.408594, + 0.92844,-0.14479,0.342105,0.713281,0.838781,-0.408594, + 0.918719,-0.113815,0.378157,0.721812,0.890313,-0.404938, + 0.995164,-0.09823,0,0.737656,0.890313,-0.5, + 0.199329,0.959446,0.199329,0.638667,0.958463,-0.361333, + 0.18835,0.976969,0.100277,0.664625,0.962948,-0.4175, + 0.513442,0.838005,0.184732,0.706,0.949319,-0.4125, + 0.199329,0.959446,0.199329,0.638667,0.958463,-0.361333, + 0.513442,0.838005,0.184732,0.706,0.949319,-0.4125, + 0.448747,0.772821,0.448747,0.660875,0.948104,-0.339125, + 0.244558,0.969635,0,0.677562,0.965162,-0.5, + 0.592505,0.805566,0,0.7215,0.950535,-0.5, + 0.513442,0.838005,0.184732,0.706,0.949319,-0.4125, + 0.244558,0.969635,0,0.677562,0.965162,-0.5, + 0.513442,0.838005,0.184732,0.706,0.949319,-0.4125, + 0.18835,0.976969,0.100277,0.664625,0.962948,-0.4175, + 0.911846,0.410531,0,0.738539,0.926712,-0.5, + 0.891913,0.278471,0.356294,0.722453,0.926408,-0.404859, + 0.513442,0.838005,0.184732,0.706,0.949319,-0.4125, + 0.911846,0.410531,0,0.738539,0.926712,-0.5, + 0.513442,0.838005,0.184732,0.706,0.949319,-0.4125, + 0.592505,0.805566,0,0.7215,0.950535,-0.5, + 0.891913,0.278471,0.356294,0.722453,0.926408,-0.404859, + 0.66233,0.350196,0.66233,0.674539,0.926104,-0.325461, + 0.448747,0.772821,0.448747,0.660875,0.948104,-0.339125, + 0.448747,0.772821,0.448747,0.660875,0.948104,-0.339125, + 0.513442,0.838005,0.184732,0.706,0.949319,-0.4125, + 0.891913,0.278471,0.356294,0.722453,0.926408,-0.404859, + 0.199329,0.959446,-0.199329,0.638667,0.958463,-0.638667, + 0.448747,0.772821,-0.448747,0.660875,0.948104,-0.660875, + 0.513442,0.838005,-0.184732,0.706,0.949319,-0.5875, + 0.199329,0.959446,-0.199329,0.638667,0.958463,-0.638667, + 0.513442,0.838005,-0.184732,0.706,0.949319,-0.5875, + 0.18835,0.976969,-0.100277,0.664625,0.962948,-0.5825, + 0.448747,0.772821,-0.448747,0.660875,0.948104,-0.660875, + 0.66233,0.350197,-0.66233,0.674539,0.926104,-0.674539, + 0.891913,0.278471,-0.356294,0.722453,0.926408,-0.595141, + 0.891913,0.278471,-0.356294,0.722453,0.926408,-0.595141, + 0.513442,0.838005,-0.184732,0.706,0.949319,-0.5875, + 0.448747,0.772821,-0.448747,0.660875,0.948104,-0.660875, + 0.911846,0.410531,0,0.738539,0.926712,-0.5, + 0.592505,0.805566,0,0.7215,0.950535,-0.5, + 0.513442,0.838005,-0.184732,0.706,0.949319,-0.5875, + 0.911846,0.410531,0,0.738539,0.926712,-0.5, + 0.513442,0.838005,-0.184732,0.706,0.949319,-0.5875, + 0.891913,0.278471,-0.356294,0.722453,0.926408,-0.595141, + 0.244558,0.969635,0,0.677562,0.965162,-0.5, + 0.18835,0.976969,-0.100277,0.664625,0.962948,-0.5825, + 0.513442,0.838005,-0.184732,0.706,0.949319,-0.5875, + 0.244558,0.969635,0,0.677562,0.965162,-0.5, + 0.513442,0.838005,-0.184732,0.706,0.949319,-0.5875, + 0.592505,0.805566,0,0.7215,0.950535,-0.5, + 0.698103,-0.159073,0.698103,0.667578,0.838781,-0.332422, + 0.342105,-0.144791,0.92844,0.591406,0.838781,-0.286719, + 0.378157,-0.113815,0.918718,0.595062,0.890313,-0.278187, + 0.698103,-0.159073,0.698103,0.667578,0.838781,-0.332422, + 0.378157,-0.113815,0.918718,0.595062,0.890313,-0.278187, + 0.705394,-0.069557,0.705394,0.674281,0.890313,-0.325719, + 0.342105,-0.144791,0.92844,0.591406,0.838781,-0.286719, + 0,-0.132314,0.991208,0.5,0.838781,-0.271484, + 0,-0.09823,0.995164,0.5,0.890313,-0.262344, + 0,-0.09823,0.995164,0.5,0.890313,-0.262344, + 0.378157,-0.113815,0.918718,0.595062,0.890313,-0.278187, + 0.342105,-0.144791,0.92844,0.591406,0.838781,-0.286719, + 0,-0.09823,0.995164,0.5,0.890313,-0.262344, + 0,0.410531,0.911846,0.5,0.926712,-0.261461, + 0.356294,0.278471,0.891913,0.595141,0.926408,-0.277547, + 0.356294,0.278471,0.891913,0.595141,0.926408,-0.277547, + 0.378157,-0.113815,0.918718,0.595062,0.890313,-0.278187, + 0,-0.09823,0.995164,0.5,0.890313,-0.262344, + 0.356294,0.278471,0.891913,0.595141,0.926408,-0.277547, + 0.66233,0.350196,0.66233,0.674539,0.926104,-0.325461, + 0.705394,-0.069557,0.705394,0.674281,0.890313,-0.325719, + 0.705394,-0.069557,0.705394,0.674281,0.890313,-0.325719, + 0.378157,-0.113815,0.918718,0.595062,0.890313,-0.278187, + 0.356294,0.278471,0.891913,0.595141,0.926408,-0.277547, + -0.698103,-0.159073,0.698103,0.332422,0.838781,-0.332422, + -0.705394,-0.069557,0.705394,0.325719,0.890313,-0.325719, + -0.378157,-0.113815,0.918718,0.404938,0.890313,-0.278187, + -0.698103,-0.159073,0.698103,0.332422,0.838781,-0.332422, + -0.378157,-0.113815,0.918718,0.404938,0.890313,-0.278187, + -0.342105,-0.144791,0.92844,0.408594,0.838781,-0.286719, + -0.705394,-0.069557,0.705394,0.325719,0.890313,-0.325719, + -0.66233,0.350197,0.66233,0.325461,0.926104,-0.325461, + -0.356294,0.278471,0.891913,0.404859,0.926408,-0.277547, + -0.356294,0.278471,0.891913,0.404859,0.926408,-0.277547, + -0.378157,-0.113815,0.918718,0.404938,0.890313,-0.278187, + -0.705394,-0.069557,0.705394,0.325719,0.890313,-0.325719, + -0.356294,0.278471,0.891913,0.404859,0.926408,-0.277547, + 0,0.410531,0.911846,0.5,0.926712,-0.261461, + 0,-0.09823,0.995164,0.5,0.890313,-0.262344, + 0,-0.09823,0.995164,0.5,0.890313,-0.262344, + -0.378157,-0.113815,0.918718,0.404938,0.890313,-0.278187, + -0.356294,0.278471,0.891913,0.404859,0.926408,-0.277547, + 0,-0.09823,0.995164,0.5,0.890313,-0.262344, + 0,-0.132314,0.991208,0.5,0.838781,-0.271484, + -0.342105,-0.144791,0.92844,0.408594,0.838781,-0.286719, + -0.342105,-0.144791,0.92844,0.408594,0.838781,-0.286719, + -0.378157,-0.113815,0.918718,0.404938,0.890313,-0.278187, + 0,-0.09823,0.995164,0.5,0.890313,-0.262344, + -0.199329,0.959446,0.199329,0.361333,0.958463,-0.361333, + -0.100277,0.976969,0.18835,0.4175,0.962948,-0.335375, + -0.184731,0.838005,0.513442,0.4125,0.949319,-0.294, + -0.199329,0.959446,0.199329,0.361333,0.958463,-0.361333, + -0.184731,0.838005,0.513442,0.4125,0.949319,-0.294, + -0.448747,0.77282,0.448747,0.339125,0.948104,-0.339125, + 0,0.969635,0.244558,0.5,0.965162,-0.322437, + 0,0.805567,0.592505,0.5,0.950535,-0.2785, + -0.184731,0.838005,0.513442,0.4125,0.949319,-0.294, + 0,0.969635,0.244558,0.5,0.965162,-0.322437, + -0.184731,0.838005,0.513442,0.4125,0.949319,-0.294, + -0.100277,0.976969,0.18835,0.4175,0.962948,-0.335375, + 0,0.410531,0.911846,0.5,0.926712,-0.261461, + -0.356294,0.278471,0.891913,0.404859,0.926408,-0.277547, + -0.184731,0.838005,0.513442,0.4125,0.949319,-0.294, + 0,0.410531,0.911846,0.5,0.926712,-0.261461, + -0.184731,0.838005,0.513442,0.4125,0.949319,-0.294, + 0,0.805567,0.592505,0.5,0.950535,-0.2785, + -0.356294,0.278471,0.891913,0.404859,0.926408,-0.277547, + -0.66233,0.350197,0.66233,0.325461,0.926104,-0.325461, + -0.448747,0.77282,0.448747,0.339125,0.948104,-0.339125, + -0.448747,0.77282,0.448747,0.339125,0.948104,-0.339125, + -0.184731,0.838005,0.513442,0.4125,0.949319,-0.294, + -0.356294,0.278471,0.891913,0.404859,0.926408,-0.277547, + 0.199329,0.959446,0.199329,0.638667,0.958463,-0.361333, + 0.448747,0.772821,0.448747,0.660875,0.948104,-0.339125, + 0.184731,0.838005,0.513442,0.5875,0.949319,-0.294, + 0.199329,0.959446,0.199329,0.638667,0.958463,-0.361333, + 0.184731,0.838005,0.513442,0.5875,0.949319,-0.294, + 0.100277,0.976969,0.18835,0.5825,0.962948,-0.335375, + 0.448747,0.772821,0.448747,0.660875,0.948104,-0.339125, + 0.66233,0.350196,0.66233,0.674539,0.926104,-0.325461, + 0.356294,0.278471,0.891913,0.595141,0.926408,-0.277547, + 0.356294,0.278471,0.891913,0.595141,0.926408,-0.277547, + 0.184731,0.838005,0.513442,0.5875,0.949319,-0.294, + 0.448747,0.772821,0.448747,0.660875,0.948104,-0.339125, + 0,0.410531,0.911846,0.5,0.926712,-0.261461, + 0,0.805567,0.592505,0.5,0.950535,-0.2785, + 0.184731,0.838005,0.513442,0.5875,0.949319,-0.294, + 0,0.410531,0.911846,0.5,0.926712,-0.261461, + 0.184731,0.838005,0.513442,0.5875,0.949319,-0.294, + 0.356294,0.278471,0.891913,0.595141,0.926408,-0.277547, + 0,0.969635,0.244558,0.5,0.965162,-0.322437, + 0.100277,0.976969,0.18835,0.5825,0.962948,-0.335375, + 0.184731,0.838005,0.513442,0.5875,0.949319,-0.294, + 0,0.969635,0.244558,0.5,0.965162,-0.322437, + 0.184731,0.838005,0.513442,0.5875,0.949319,-0.294, + 0,0.805567,0.592505,0.5,0.950535,-0.2785, + -0.698103,-0.159073,0.698103,0.332422,0.838781,-0.332422, + -0.92844,-0.144791,0.342105,0.286719,0.838781,-0.408594, + -0.918718,-0.113815,0.378157,0.278187,0.890313,-0.404938, + -0.698103,-0.159073,0.698103,0.332422,0.838781,-0.332422, + -0.918718,-0.113815,0.378157,0.278187,0.890313,-0.404938, + -0.705394,-0.069557,0.705394,0.325719,0.890313,-0.325719, + -0.92844,-0.144791,0.342105,0.286719,0.838781,-0.408594, + -0.991208,-0.132314,0,0.271484,0.838781,-0.5, + -0.995164,-0.09823,0,0.262344,0.890313,-0.5, + -0.995164,-0.09823,0,0.262344,0.890313,-0.5, + -0.918718,-0.113815,0.378157,0.278187,0.890313,-0.404938, + -0.92844,-0.144791,0.342105,0.286719,0.838781,-0.408594, + -0.995164,-0.09823,0,0.262344,0.890313,-0.5, + -0.911846,0.410531,0,0.261461,0.926712,-0.5, + -0.891913,0.278471,0.356294,0.277547,0.926408,-0.404859, + -0.891913,0.278471,0.356294,0.277547,0.926408,-0.404859, + -0.918718,-0.113815,0.378157,0.278187,0.890313,-0.404938, + -0.995164,-0.09823,0,0.262344,0.890313,-0.5, + -0.891913,0.278471,0.356294,0.277547,0.926408,-0.404859, + -0.66233,0.350197,0.66233,0.325461,0.926104,-0.325461, + -0.705394,-0.069557,0.705394,0.325719,0.890313,-0.325719, + -0.705394,-0.069557,0.705394,0.325719,0.890313,-0.325719, + -0.918718,-0.113815,0.378157,0.278187,0.890313,-0.404938, + -0.891913,0.278471,0.356294,0.277547,0.926408,-0.404859, + -0.698103,-0.159073,-0.698103,0.332422,0.838781,-0.667578, + -0.705394,-0.069557,-0.705394,0.325719,0.890313,-0.674281, + -0.918718,-0.113815,-0.378157,0.278187,0.890313,-0.595062, + -0.698103,-0.159073,-0.698103,0.332422,0.838781,-0.667578, + -0.918718,-0.113815,-0.378157,0.278187,0.890313,-0.595062, + -0.92844,-0.144791,-0.342105,0.286719,0.838781,-0.591406, + -0.705394,-0.069557,-0.705394,0.325719,0.890313,-0.674281, + -0.66233,0.350196,-0.66233,0.325461,0.926104,-0.674539, + -0.891913,0.278471,-0.356294,0.277547,0.926408,-0.595141, + -0.891913,0.278471,-0.356294,0.277547,0.926408,-0.595141, + -0.918718,-0.113815,-0.378157,0.278187,0.890313,-0.595062, + -0.705394,-0.069557,-0.705394,0.325719,0.890313,-0.674281, + -0.891913,0.278471,-0.356294,0.277547,0.926408,-0.595141, + -0.911846,0.410531,0,0.261461,0.926712,-0.5, + -0.995164,-0.09823,0,0.262344,0.890313,-0.5, + -0.995164,-0.09823,0,0.262344,0.890313,-0.5, + -0.918718,-0.113815,-0.378157,0.278187,0.890313,-0.595062, + -0.891913,0.278471,-0.356294,0.277547,0.926408,-0.595141, + -0.995164,-0.09823,0,0.262344,0.890313,-0.5, + -0.991208,-0.132314,0,0.271484,0.838781,-0.5, + -0.92844,-0.144791,-0.342105,0.286719,0.838781,-0.591406, + -0.92844,-0.144791,-0.342105,0.286719,0.838781,-0.591406, + -0.918718,-0.113815,-0.378157,0.278187,0.890313,-0.595062, + -0.995164,-0.09823,0,0.262344,0.890313,-0.5, + -0.199329,0.959446,-0.199329,0.361333,0.958463,-0.638667, + -0.18835,0.976969,-0.100277,0.335375,0.962948,-0.5825, + -0.513442,0.838005,-0.184731,0.294,0.949319,-0.5875, + -0.199329,0.959446,-0.199329,0.361333,0.958463,-0.638667, + -0.513442,0.838005,-0.184731,0.294,0.949319,-0.5875, + -0.448747,0.772821,-0.448747,0.339125,0.948104,-0.660875, + -0.244558,0.969635,0,0.322437,0.965162,-0.5, + -0.592505,0.805566,0,0.2785,0.950535,-0.5, + -0.513442,0.838005,-0.184731,0.294,0.949319,-0.5875, + -0.244558,0.969635,0,0.322437,0.965162,-0.5, + -0.513442,0.838005,-0.184731,0.294,0.949319,-0.5875, + -0.18835,0.976969,-0.100277,0.335375,0.962948,-0.5825, + -0.911846,0.410531,0,0.261461,0.926712,-0.5, + -0.891913,0.278471,-0.356294,0.277547,0.926408,-0.595141, + -0.513442,0.838005,-0.184731,0.294,0.949319,-0.5875, + -0.911846,0.410531,0,0.261461,0.926712,-0.5, + -0.513442,0.838005,-0.184731,0.294,0.949319,-0.5875, + -0.592505,0.805566,0,0.2785,0.950535,-0.5, + -0.891913,0.278471,-0.356294,0.277547,0.926408,-0.595141, + -0.66233,0.350196,-0.66233,0.325461,0.926104,-0.674539, + -0.448747,0.772821,-0.448747,0.339125,0.948104,-0.660875, + -0.448747,0.772821,-0.448747,0.339125,0.948104,-0.660875, + -0.513442,0.838005,-0.184731,0.294,0.949319,-0.5875, + -0.891913,0.278471,-0.356294,0.277547,0.926408,-0.595141, + -0.199329,0.959446,0.199329,0.361333,0.958463,-0.361333, + -0.448747,0.77282,0.448747,0.339125,0.948104,-0.339125, + -0.513442,0.838005,0.184731,0.294,0.949319,-0.4125, + -0.199329,0.959446,0.199329,0.361333,0.958463,-0.361333, + -0.513442,0.838005,0.184731,0.294,0.949319,-0.4125, + -0.18835,0.976969,0.100277,0.335375,0.962948,-0.4175, + -0.448747,0.77282,0.448747,0.339125,0.948104,-0.339125, + -0.66233,0.350197,0.66233,0.325461,0.926104,-0.325461, + -0.891913,0.278471,0.356294,0.277547,0.926408,-0.404859, + -0.891913,0.278471,0.356294,0.277547,0.926408,-0.404859, + -0.513442,0.838005,0.184731,0.294,0.949319,-0.4125, + -0.448747,0.77282,0.448747,0.339125,0.948104,-0.339125, + -0.911846,0.410531,0,0.261461,0.926712,-0.5, + -0.592505,0.805566,0,0.2785,0.950535,-0.5, + -0.513442,0.838005,0.184731,0.294,0.949319,-0.4125, + -0.911846,0.410531,0,0.261461,0.926712,-0.5, + -0.513442,0.838005,0.184731,0.294,0.949319,-0.4125, + -0.891913,0.278471,0.356294,0.277547,0.926408,-0.404859, + -0.244558,0.969635,0,0.322437,0.965162,-0.5, + -0.18835,0.976969,0.100277,0.335375,0.962948,-0.4175, + -0.513442,0.838005,0.184731,0.294,0.949319,-0.4125, + -0.244558,0.969635,0,0.322437,0.965162,-0.5, + -0.513442,0.838005,0.184731,0.294,0.949319,-0.4125, + -0.592505,0.805566,0,0.2785,0.950535,-0.5, + -0.698103,-0.159073,-0.698103,0.332422,0.838781,-0.667578, + -0.342105,-0.14479,-0.92844,0.408594,0.838781,-0.713281, + -0.378157,-0.113815,-0.918719,0.404938,0.890313,-0.721812, + -0.698103,-0.159073,-0.698103,0.332422,0.838781,-0.667578, + -0.378157,-0.113815,-0.918719,0.404938,0.890313,-0.721812, + -0.705394,-0.069557,-0.705394,0.325719,0.890313,-0.674281, + -0.342105,-0.14479,-0.92844,0.408594,0.838781,-0.713281, + 0,-0.132313,-0.991208,0.5,0.838781,-0.728516, + 0,-0.09823,-0.995164,0.5,0.890313,-0.737656, + 0,-0.09823,-0.995164,0.5,0.890313,-0.737656, + -0.378157,-0.113815,-0.918719,0.404938,0.890313,-0.721812, + -0.342105,-0.14479,-0.92844,0.408594,0.838781,-0.713281, + 0,-0.09823,-0.995164,0.5,0.890313,-0.737656, + 0,0.410531,-0.911846,0.5,0.926712,-0.738539, + -0.356294,0.278471,-0.891913,0.404859,0.926408,-0.722453, + -0.356294,0.278471,-0.891913,0.404859,0.926408,-0.722453, + -0.378157,-0.113815,-0.918719,0.404938,0.890313,-0.721812, + 0,-0.09823,-0.995164,0.5,0.890313,-0.737656, + -0.356294,0.278471,-0.891913,0.404859,0.926408,-0.722453, + -0.66233,0.350196,-0.66233,0.325461,0.926104,-0.674539, + -0.705394,-0.069557,-0.705394,0.325719,0.890313,-0.674281, + -0.705394,-0.069557,-0.705394,0.325719,0.890313,-0.674281, + -0.378157,-0.113815,-0.918719,0.404938,0.890313,-0.721812, + -0.356294,0.278471,-0.891913,0.404859,0.926408,-0.722453, + 0.698103,-0.159073,-0.698103,0.667578,0.838781,-0.667578, + 0.705394,-0.069557,-0.705394,0.674281,0.890313,-0.674281, + 0.378157,-0.113815,-0.918718,0.595062,0.890313,-0.721812, + 0.698103,-0.159073,-0.698103,0.667578,0.838781,-0.667578, + 0.378157,-0.113815,-0.918718,0.595062,0.890313,-0.721812, + 0.342105,-0.14479,-0.92844,0.591406,0.838781,-0.713281, + 0.705394,-0.069557,-0.705394,0.674281,0.890313,-0.674281, + 0.66233,0.350197,-0.66233,0.674539,0.926104,-0.674539, + 0.356294,0.278471,-0.891913,0.595141,0.926408,-0.722453, + 0.356294,0.278471,-0.891913,0.595141,0.926408,-0.722453, + 0.378157,-0.113815,-0.918718,0.595062,0.890313,-0.721812, + 0.705394,-0.069557,-0.705394,0.674281,0.890313,-0.674281, + 0.356294,0.278471,-0.891913,0.595141,0.926408,-0.722453, + 0,0.410531,-0.911846,0.5,0.926712,-0.738539, + 0,-0.09823,-0.995164,0.5,0.890313,-0.737656, + 0,-0.09823,-0.995164,0.5,0.890313,-0.737656, + 0.378157,-0.113815,-0.918718,0.595062,0.890313,-0.721812, + 0.356294,0.278471,-0.891913,0.595141,0.926408,-0.722453, + 0,-0.09823,-0.995164,0.5,0.890313,-0.737656, + 0,-0.132313,-0.991208,0.5,0.838781,-0.728516, + 0.342105,-0.14479,-0.92844,0.591406,0.838781,-0.713281, + 0.342105,-0.14479,-0.92844,0.591406,0.838781,-0.713281, + 0.378157,-0.113815,-0.918718,0.595062,0.890313,-0.721812, + 0,-0.09823,-0.995164,0.5,0.890313,-0.737656, + 0.199329,0.959446,-0.199329,0.638667,0.958463,-0.638667, + 0.100277,0.976969,-0.18835,0.5825,0.962948,-0.664625, + 0.184732,0.838005,-0.513442,0.5875,0.949319,-0.706, + 0.199329,0.959446,-0.199329,0.638667,0.958463,-0.638667, + 0.184732,0.838005,-0.513442,0.5875,0.949319,-0.706, + 0.448747,0.772821,-0.448747,0.660875,0.948104,-0.660875, + 0,0.969635,-0.244558,0.5,0.965162,-0.677562, + 0,0.805567,-0.592505,0.5,0.950535,-0.7215, + 0.184732,0.838005,-0.513442,0.5875,0.949319,-0.706, + 0,0.969635,-0.244558,0.5,0.965162,-0.677562, + 0.184732,0.838005,-0.513442,0.5875,0.949319,-0.706, + 0.100277,0.976969,-0.18835,0.5825,0.962948,-0.664625, + 0,0.410531,-0.911846,0.5,0.926712,-0.738539, + 0.356294,0.278471,-0.891913,0.595141,0.926408,-0.722453, + 0.184732,0.838005,-0.513442,0.5875,0.949319,-0.706, + 0,0.410531,-0.911846,0.5,0.926712,-0.738539, + 0.184732,0.838005,-0.513442,0.5875,0.949319,-0.706, + 0,0.805567,-0.592505,0.5,0.950535,-0.7215, + 0.356294,0.278471,-0.891913,0.595141,0.926408,-0.722453, + 0.66233,0.350197,-0.66233,0.674539,0.926104,-0.674539, + 0.448747,0.772821,-0.448747,0.660875,0.948104,-0.660875, + 0.448747,0.772821,-0.448747,0.660875,0.948104,-0.660875, + 0.184732,0.838005,-0.513442,0.5875,0.949319,-0.706, + 0.356294,0.278471,-0.891913,0.595141,0.926408,-0.722453, + -0.199329,0.959446,-0.199329,0.361333,0.958463,-0.638667, + -0.448747,0.772821,-0.448747,0.339125,0.948104,-0.660875, + -0.184732,0.838005,-0.513442,0.4125,0.949319,-0.706, + -0.199329,0.959446,-0.199329,0.361333,0.958463,-0.638667, + -0.184732,0.838005,-0.513442,0.4125,0.949319,-0.706, + -0.100277,0.976969,-0.18835,0.4175,0.962948,-0.664625, + -0.448747,0.772821,-0.448747,0.339125,0.948104,-0.660875, + -0.66233,0.350196,-0.66233,0.325461,0.926104,-0.674539, + -0.356294,0.278471,-0.891913,0.404859,0.926408,-0.722453, + -0.356294,0.278471,-0.891913,0.404859,0.926408,-0.722453, + -0.184732,0.838005,-0.513442,0.4125,0.949319,-0.706, + -0.448747,0.772821,-0.448747,0.339125,0.948104,-0.660875, + 0,0.410531,-0.911846,0.5,0.926712,-0.738539, + 0,0.805567,-0.592505,0.5,0.950535,-0.7215, + -0.184732,0.838005,-0.513442,0.4125,0.949319,-0.706, + 0,0.410531,-0.911846,0.5,0.926712,-0.738539, + -0.184732,0.838005,-0.513442,0.4125,0.949319,-0.706, + -0.356294,0.278471,-0.891913,0.404859,0.926408,-0.722453, + 0,0.969635,-0.244558,0.5,0.965162,-0.677562, + -0.100277,0.976969,-0.18835,0.4175,0.962948,-0.664625, + -0.184732,0.838005,-0.513442,0.4125,0.949319,-0.706, + 0,0.969635,-0.244558,0.5,0.965162,-0.677562, + -0.184732,0.838005,-0.513442,0.4125,0.949319,-0.706, + 0,0.805567,-0.592505,0.5,0.950535,-0.7215, + 0.199329,0.959446,0.199329,0.638667,0.958463,-0.361333, + 0.100277,0.976969,0.18835,0.5825,0.962948,-0.335375, + 0.079739,0.993621,0.079739,0.5905,0.971195,-0.4095, + 0.199329,0.959446,0.199329,0.638667,0.958463,-0.361333, + 0.079739,0.993621,0.079739,0.5905,0.971195,-0.4095, + 0.18835,0.976969,0.100277,0.664625,0.962948,-0.4175, + 0.100277,0.976969,0.18835,0.5825,0.962948,-0.335375, + 0,0.969635,0.244558,0.5,0.965162,-0.322437, + 0,0.996384,0.08496,0.5,0.973972,-0.40225, + 0,0.996384,0.08496,0.5,0.973972,-0.40225, + 0.079739,0.993621,0.079739,0.5905,0.971195,-0.4095, + 0.100277,0.976969,0.18835,0.5825,0.962948,-0.335375, + 0,1,0,0.5,0.976924,-0.5, + 0.08496,0.996384,0,0.59775,0.973972,-0.5, + 0.079739,0.993621,0.079739,0.5905,0.971195,-0.4095, + 0,1,0,0.5,0.976924,-0.5, + 0.079739,0.993621,0.079739,0.5905,0.971195,-0.4095, + 0,0.996384,0.08496,0.5,0.973972,-0.40225, + 0.08496,0.996384,0,0.59775,0.973972,-0.5, + 0.244558,0.969635,0,0.677562,0.965162,-0.5, + 0.18835,0.976969,0.100277,0.664625,0.962948,-0.4175, + 0.18835,0.976969,0.100277,0.664625,0.962948,-0.4175, + 0.079739,0.993621,0.079739,0.5905,0.971195,-0.4095, + 0.08496,0.996384,0,0.59775,0.973972,-0.5, + -0.199329,0.959446,0.199329,0.361333,0.958463,-0.361333, + -0.18835,0.976969,0.100277,0.335375,0.962948,-0.4175, + -0.079739,0.993621,0.079739,0.4095,0.971195,-0.4095, + -0.199329,0.959446,0.199329,0.361333,0.958463,-0.361333, + -0.079739,0.993621,0.079739,0.4095,0.971195,-0.4095, + -0.100277,0.976969,0.18835,0.4175,0.962948,-0.335375, + -0.18835,0.976969,0.100277,0.335375,0.962948,-0.4175, + -0.244558,0.969635,0,0.322437,0.965162,-0.5, + -0.08496,0.996384,0,0.40225,0.973972,-0.5, + -0.08496,0.996384,0,0.40225,0.973972,-0.5, + -0.079739,0.993621,0.079739,0.4095,0.971195,-0.4095, + -0.18835,0.976969,0.100277,0.335375,0.962948,-0.4175, + 0,1,0,0.5,0.976924,-0.5, + 0,0.996384,0.08496,0.5,0.973972,-0.40225, + -0.079739,0.993621,0.079739,0.4095,0.971195,-0.4095, + 0,1,0,0.5,0.976924,-0.5, + -0.079739,0.993621,0.079739,0.4095,0.971195,-0.4095, + -0.08496,0.996384,0,0.40225,0.973972,-0.5, + 0,0.996384,0.08496,0.5,0.973972,-0.40225, + 0,0.969635,0.244558,0.5,0.965162,-0.322437, + -0.100277,0.976969,0.18835,0.4175,0.962948,-0.335375, + -0.100277,0.976969,0.18835,0.4175,0.962948,-0.335375, + -0.079739,0.993621,0.079739,0.4095,0.971195,-0.4095, + 0,0.996384,0.08496,0.5,0.973972,-0.40225, + -0.199329,0.959446,-0.199329,0.361333,0.958463,-0.638667, + -0.100277,0.976969,-0.18835,0.4175,0.962948,-0.664625, + -0.079739,0.993621,-0.079739,0.4095,0.971195,-0.5905, + -0.199329,0.959446,-0.199329,0.361333,0.958463,-0.638667, + -0.079739,0.993621,-0.079739,0.4095,0.971195,-0.5905, + -0.18835,0.976969,-0.100277,0.335375,0.962948,-0.5825, + -0.100277,0.976969,-0.18835,0.4175,0.962948,-0.664625, + 0,0.969635,-0.244558,0.5,0.965162,-0.677562, + 0,0.996384,-0.08496,0.5,0.973972,-0.59775, + 0,0.996384,-0.08496,0.5,0.973972,-0.59775, + -0.079739,0.993621,-0.079739,0.4095,0.971195,-0.5905, + -0.100277,0.976969,-0.18835,0.4175,0.962948,-0.664625, + 0,1,0,0.5,0.976924,-0.5, + -0.08496,0.996384,0,0.40225,0.973972,-0.5, + -0.079739,0.993621,-0.079739,0.4095,0.971195,-0.5905, + 0,1,0,0.5,0.976924,-0.5, + -0.079739,0.993621,-0.079739,0.4095,0.971195,-0.5905, + 0,0.996384,-0.08496,0.5,0.973972,-0.59775, + -0.08496,0.996384,0,0.40225,0.973972,-0.5, + -0.244558,0.969635,0,0.322437,0.965162,-0.5, + -0.18835,0.976969,-0.100277,0.335375,0.962948,-0.5825, + -0.18835,0.976969,-0.100277,0.335375,0.962948,-0.5825, + -0.079739,0.993621,-0.079739,0.4095,0.971195,-0.5905, + -0.08496,0.996384,0,0.40225,0.973972,-0.5, + 0.199329,0.959446,-0.199329,0.638667,0.958463,-0.638667, + 0.18835,0.976969,-0.100277,0.664625,0.962948,-0.5825, + 0.079739,0.993621,-0.079739,0.5905,0.971195,-0.5905, + 0.199329,0.959446,-0.199329,0.638667,0.958463,-0.638667, + 0.079739,0.993621,-0.079739,0.5905,0.971195,-0.5905, + 0.100277,0.976969,-0.18835,0.5825,0.962948,-0.664625, + 0.18835,0.976969,-0.100277,0.664625,0.962948,-0.5825, + 0.244558,0.969635,0,0.677562,0.965162,-0.5, + 0.08496,0.996384,0,0.59775,0.973972,-0.5, + 0.08496,0.996384,0,0.59775,0.973972,-0.5, + 0.079739,0.993621,-0.079739,0.5905,0.971195,-0.5905, + 0.18835,0.976969,-0.100277,0.664625,0.962948,-0.5825, + 0,1,0,0.5,0.976924,-0.5, + 0,0.996384,-0.08496,0.5,0.973972,-0.59775, + 0.079739,0.993621,-0.079739,0.5905,0.971195,-0.5905, + 0,1,0,0.5,0.976924,-0.5, + 0.079739,0.993621,-0.079739,0.5905,0.971195,-0.5905, + 0.08496,0.996384,0,0.59775,0.973972,-0.5, + 0,0.996384,-0.08496,0.5,0.973972,-0.59775, + 0,0.969635,-0.244558,0.5,0.965162,-0.677562, + 0.100277,0.976969,-0.18835,0.5825,0.962948,-0.664625, + 0.100277,0.976969,-0.18835,0.5825,0.962948,-0.664625, + 0.079739,0.993621,-0.079739,0.5905,0.971195,-0.5905, + 0,0.996384,-0.08496,0.5,0.973972,-0.59775, + 0.92844,-0.14479,-0.342105,0.713281,0.838781,-0.591406, + 0.698103,-0.159073,-0.698103,0.667578,0.838781,-0.667578, + 0.703449,-0.101581,-0.703449,0.661906,0.769563,-0.661906, + 0.703449,-0.101581,-0.703449,0.661906,0.769563,-0.661906, + 0.934344,-0.092655,-0.344117,0.706063,0.769563,-0.588313, + 0.92844,-0.14479,-0.342105,0.713281,0.838781,-0.591406, + 0.705656,-0.064019,-0.705656,0.657523,0.686547,-0.657523, + 0.936848,-0.057446,-0.344986,0.700484,0.686547,-0.585922, + 0.934344,-0.092655,-0.344117,0.706063,0.769563,-0.588313, + 0.705656,-0.064019,-0.705656,0.657523,0.686547,-0.657523, + 0.934344,-0.092655,-0.344117,0.706063,0.769563,-0.588313, + 0.703449,-0.101581,-0.703449,0.661906,0.769563,-0.661906, + 0.936848,-0.057446,-0.344986,0.700484,0.686547,-0.585922, + 0.998665,-0.051663,0,0.714805,0.686547,-0.5, + 0.996389,-0.084903,0,0.720781,0.769563,-0.5, + 0.996389,-0.084903,0,0.720781,0.769563,-0.5, + 0.934344,-0.092655,-0.344117,0.706063,0.769563,-0.588313, + 0.936848,-0.057446,-0.344986,0.700484,0.686547,-0.585922, + 0.991208,-0.132313,0,0.728516,0.838781,-0.5, + 0.92844,-0.14479,-0.342105,0.713281,0.838781,-0.591406, + 0.934344,-0.092655,-0.344117,0.706063,0.769563,-0.588313, + 0.991208,-0.132313,0,0.728516,0.838781,-0.5, + 0.934344,-0.092655,-0.344117,0.706063,0.769563,-0.588313, + 0.996389,-0.084903,0,0.720781,0.769563,-0.5, + 0.707107,-0.000155,-0.707107,0.653656,0.494688,-0.653656, + 0.958364,-0.000151,-0.285548,0.695563,0.494688,-0.583813, + 0.938032,-0.028246,-0.345395,0.696875,0.593625,-0.584375, + 0.707107,-0.000155,-0.707107,0.653656,0.494688,-0.653656, + 0.938032,-0.028246,-0.345395,0.696875,0.593625,-0.584375, + 0.706706,-0.033664,-0.706706,0.654688,0.593625,-0.654688, + 0.958364,-0.000151,-0.285548,0.695563,0.494688,-0.583813, + 1,-0.00015,0,0.709531,0.494688,-0.5, + 0.999728,-0.023338,0,0.710938,0.593625,-0.5, + 0.999728,-0.023338,0,0.710938,0.593625,-0.5, + 0.938032,-0.028246,-0.345395,0.696875,0.593625,-0.584375, + 0.958364,-0.000151,-0.285548,0.695563,0.494688,-0.583813, + 0.998665,-0.051663,0,0.714805,0.686547,-0.5, + 0.936848,-0.057446,-0.344986,0.700484,0.686547,-0.585922, + 0.938032,-0.028246,-0.345395,0.696875,0.593625,-0.584375, + 0.998665,-0.051663,0,0.714805,0.686547,-0.5, + 0.938032,-0.028246,-0.345395,0.696875,0.593625,-0.584375, + 0.999728,-0.023338,0,0.710938,0.593625,-0.5, + 0.936848,-0.057446,-0.344986,0.700484,0.686547,-0.585922, + 0.705656,-0.064019,-0.705656,0.657523,0.686547,-0.657523, + 0.706706,-0.033664,-0.706706,0.654688,0.593625,-0.654688, + 0.706706,-0.033664,-0.706706,0.654688,0.593625,-0.654688, + 0.938032,-0.028246,-0.345395,0.696875,0.593625,-0.584375, + 0.936848,-0.057446,-0.344986,0.700484,0.686547,-0.585922, + 0.707107,-0.000155,0.707107,0.653656,0.494688,-0.346344, + 0.706706,-0.033664,0.706706,0.654688,0.593625,-0.345313, + 0.938032,-0.028246,0.345395,0.696875,0.593625,-0.415625, + 0.707107,-0.000155,0.707107,0.653656,0.494688,-0.346344, + 0.938032,-0.028246,0.345395,0.696875,0.593625,-0.415625, + 0.958364,-0.000151,0.285548,0.695563,0.494688,-0.416187, + 0.706706,-0.033664,0.706706,0.654688,0.593625,-0.345313, + 0.705656,-0.064019,0.705656,0.657523,0.686547,-0.342477, + 0.936848,-0.057446,0.344986,0.700484,0.686547,-0.414078, + 0.936848,-0.057446,0.344986,0.700484,0.686547,-0.414078, + 0.938032,-0.028246,0.345395,0.696875,0.593625,-0.415625, + 0.706706,-0.033664,0.706706,0.654688,0.593625,-0.345313, + 0.998665,-0.051663,0,0.714805,0.686547,-0.5, + 0.999728,-0.023338,0,0.710938,0.593625,-0.5, + 0.938032,-0.028246,0.345395,0.696875,0.593625,-0.415625, + 0.998665,-0.051663,0,0.714805,0.686547,-0.5, + 0.938032,-0.028246,0.345395,0.696875,0.593625,-0.415625, + 0.936848,-0.057446,0.344986,0.700484,0.686547,-0.414078, + 0.999728,-0.023338,0,0.710938,0.593625,-0.5, + 1,-0.00015,0,0.709531,0.494688,-0.5, + 0.958364,-0.000151,0.285548,0.695563,0.494688,-0.416187, + 0.958364,-0.000151,0.285548,0.695563,0.494688,-0.416187, + 0.938032,-0.028246,0.345395,0.696875,0.593625,-0.415625, + 0.999728,-0.023338,0,0.710938,0.593625,-0.5, + 0.703449,-0.101581,0.703449,0.661906,0.769563,-0.338094, + 0.698103,-0.159073,0.698103,0.667578,0.838781,-0.332422, + 0.92844,-0.14479,0.342105,0.713281,0.838781,-0.408594, + 0.92844,-0.14479,0.342105,0.713281,0.838781,-0.408594, + 0.934344,-0.092655,0.344117,0.706063,0.769563,-0.411687, + 0.703449,-0.101581,0.703449,0.661906,0.769563,-0.338094, + 0.991208,-0.132313,0,0.728516,0.838781,-0.5, + 0.996389,-0.084903,0,0.720781,0.769563,-0.5, + 0.934344,-0.092655,0.344117,0.706063,0.769563,-0.411687, + 0.991208,-0.132313,0,0.728516,0.838781,-0.5, + 0.934344,-0.092655,0.344117,0.706063,0.769563,-0.411687, + 0.92844,-0.14479,0.342105,0.713281,0.838781,-0.408594, + 0.996389,-0.084903,0,0.720781,0.769563,-0.5, + 0.998665,-0.051663,0,0.714805,0.686547,-0.5, + 0.936848,-0.057446,0.344986,0.700484,0.686547,-0.414078, + 0.936848,-0.057446,0.344986,0.700484,0.686547,-0.414078, + 0.934344,-0.092655,0.344117,0.706063,0.769563,-0.411687, + 0.996389,-0.084903,0,0.720781,0.769563,-0.5, + 0.705656,-0.064019,0.705656,0.657523,0.686547,-0.342477, + 0.703449,-0.101581,0.703449,0.661906,0.769563,-0.338094, + 0.934344,-0.092655,0.344117,0.706063,0.769563,-0.411687, + 0.705656,-0.064019,0.705656,0.657523,0.686547,-0.342477, + 0.934344,-0.092655,0.344117,0.706063,0.769563,-0.411687, + 0.936848,-0.057446,0.344986,0.700484,0.686547,-0.414078, + -0.342105,-0.14479,-0.92844,0.408594,0.838781,-0.713281, + -0.698103,-0.159073,-0.698103,0.332422,0.838781,-0.667578, + -0.703449,-0.101581,-0.703449,0.338094,0.769563,-0.661906, + -0.703449,-0.101581,-0.703449,0.338094,0.769563,-0.661906, + -0.344117,-0.092655,-0.934344,0.411687,0.769563,-0.706063, + -0.342105,-0.14479,-0.92844,0.408594,0.838781,-0.713281, + -0.705656,-0.064019,-0.705656,0.342477,0.686547,-0.657523, + -0.344986,-0.057446,-0.936848,0.414078,0.686547,-0.700484, + -0.344117,-0.092655,-0.934344,0.411687,0.769563,-0.706063, + -0.705656,-0.064019,-0.705656,0.342477,0.686547,-0.657523, + -0.344117,-0.092655,-0.934344,0.411687,0.769563,-0.706063, + -0.703449,-0.101581,-0.703449,0.338094,0.769563,-0.661906, + -0.344986,-0.057446,-0.936848,0.414078,0.686547,-0.700484, + 0,-0.051663,-0.998665,0.5,0.686547,-0.714805, + 0,-0.084903,-0.996389,0.5,0.769563,-0.720781, + 0,-0.084903,-0.996389,0.5,0.769563,-0.720781, + -0.344117,-0.092655,-0.934344,0.411687,0.769563,-0.706063, + -0.344986,-0.057446,-0.936848,0.414078,0.686547,-0.700484, + 0,-0.132313,-0.991208,0.5,0.838781,-0.728516, + -0.342105,-0.14479,-0.92844,0.408594,0.838781,-0.713281, + -0.344117,-0.092655,-0.934344,0.411687,0.769563,-0.706063, + 0,-0.132313,-0.991208,0.5,0.838781,-0.728516, + -0.344117,-0.092655,-0.934344,0.411687,0.769563,-0.706063, + 0,-0.084903,-0.996389,0.5,0.769563,-0.720781, + -0.707107,-0.000155,-0.707107,0.346344,0.494688,-0.653656, + -0.285548,-0.000151,-0.958364,0.416187,0.494688,-0.695563, + -0.345395,-0.028246,-0.938032,0.415625,0.593625,-0.696875, + -0.707107,-0.000155,-0.707107,0.346344,0.494688,-0.653656, + -0.345395,-0.028246,-0.938032,0.415625,0.593625,-0.696875, + -0.706706,-0.033664,-0.706706,0.345313,0.593625,-0.654688, + -0.285548,-0.000151,-0.958364,0.416187,0.494688,-0.695563, + 0,-0.00015,-1,0.5,0.494688,-0.709531, + 0,-0.023338,-0.999728,0.5,0.593625,-0.710938, + 0,-0.023338,-0.999728,0.5,0.593625,-0.710938, + -0.345395,-0.028246,-0.938032,0.415625,0.593625,-0.696875, + -0.285548,-0.000151,-0.958364,0.416187,0.494688,-0.695563, + 0,-0.051663,-0.998665,0.5,0.686547,-0.714805, + -0.344986,-0.057446,-0.936848,0.414078,0.686547,-0.700484, + -0.345395,-0.028246,-0.938032,0.415625,0.593625,-0.696875, + 0,-0.051663,-0.998665,0.5,0.686547,-0.714805, + -0.345395,-0.028246,-0.938032,0.415625,0.593625,-0.696875, + 0,-0.023338,-0.999728,0.5,0.593625,-0.710938, + -0.344986,-0.057446,-0.936848,0.414078,0.686547,-0.700484, + -0.705656,-0.064019,-0.705656,0.342477,0.686547,-0.657523, + -0.706706,-0.033664,-0.706706,0.345313,0.593625,-0.654688, + -0.706706,-0.033664,-0.706706,0.345313,0.593625,-0.654688, + -0.345395,-0.028246,-0.938032,0.415625,0.593625,-0.696875, + -0.344986,-0.057446,-0.936848,0.414078,0.686547,-0.700484, + 0.707107,-0.000155,-0.707107,0.653656,0.494688,-0.653656, + 0.706706,-0.033664,-0.706706,0.654688,0.593625,-0.654688, + 0.345395,-0.028246,-0.938032,0.584375,0.593625,-0.696875, + 0.707107,-0.000155,-0.707107,0.653656,0.494688,-0.653656, + 0.345395,-0.028246,-0.938032,0.584375,0.593625,-0.696875, + 0.285548,-0.000151,-0.958364,0.583813,0.494688,-0.695563, + 0.706706,-0.033664,-0.706706,0.654688,0.593625,-0.654688, + 0.705656,-0.064019,-0.705656,0.657523,0.686547,-0.657523, + 0.344986,-0.057446,-0.936848,0.585922,0.686547,-0.700484, + 0.344986,-0.057446,-0.936848,0.585922,0.686547,-0.700484, + 0.345395,-0.028246,-0.938032,0.584375,0.593625,-0.696875, + 0.706706,-0.033664,-0.706706,0.654688,0.593625,-0.654688, + 0,-0.051663,-0.998665,0.5,0.686547,-0.714805, + 0,-0.023338,-0.999728,0.5,0.593625,-0.710938, + 0.345395,-0.028246,-0.938032,0.584375,0.593625,-0.696875, + 0,-0.051663,-0.998665,0.5,0.686547,-0.714805, + 0.345395,-0.028246,-0.938032,0.584375,0.593625,-0.696875, + 0.344986,-0.057446,-0.936848,0.585922,0.686547,-0.700484, + 0,-0.023338,-0.999728,0.5,0.593625,-0.710938, + 0,-0.00015,-1,0.5,0.494688,-0.709531, + 0.285548,-0.000151,-0.958364,0.583813,0.494688,-0.695563, + 0.285548,-0.000151,-0.958364,0.583813,0.494688,-0.695563, + 0.345395,-0.028246,-0.938032,0.584375,0.593625,-0.696875, + 0,-0.023338,-0.999728,0.5,0.593625,-0.710938, + 0.703449,-0.101581,-0.703449,0.661906,0.769563,-0.661906, + 0.698103,-0.159073,-0.698103,0.667578,0.838781,-0.667578, + 0.342105,-0.14479,-0.92844,0.591406,0.838781,-0.713281, + 0.342105,-0.14479,-0.92844,0.591406,0.838781,-0.713281, + 0.344117,-0.092655,-0.934344,0.588313,0.769563,-0.706063, + 0.703449,-0.101581,-0.703449,0.661906,0.769563,-0.661906, + 0,-0.132313,-0.991208,0.5,0.838781,-0.728516, + 0,-0.084903,-0.996389,0.5,0.769563,-0.720781, + 0.344117,-0.092655,-0.934344,0.588313,0.769563,-0.706063, + 0,-0.132313,-0.991208,0.5,0.838781,-0.728516, + 0.344117,-0.092655,-0.934344,0.588313,0.769563,-0.706063, + 0.342105,-0.14479,-0.92844,0.591406,0.838781,-0.713281, + 0,-0.084903,-0.996389,0.5,0.769563,-0.720781, + 0,-0.051663,-0.998665,0.5,0.686547,-0.714805, + 0.344986,-0.057446,-0.936848,0.585922,0.686547,-0.700484, + 0.344986,-0.057446,-0.936848,0.585922,0.686547,-0.700484, + 0.344117,-0.092655,-0.934344,0.588313,0.769563,-0.706063, + 0,-0.084903,-0.996389,0.5,0.769563,-0.720781, + 0.705656,-0.064019,-0.705656,0.657523,0.686547,-0.657523, + 0.703449,-0.101581,-0.703449,0.661906,0.769563,-0.661906, + 0.344117,-0.092655,-0.934344,0.588313,0.769563,-0.706063, + 0.705656,-0.064019,-0.705656,0.657523,0.686547,-0.657523, + 0.344117,-0.092655,-0.934344,0.588313,0.769563,-0.706063, + 0.344986,-0.057446,-0.936848,0.585922,0.686547,-0.700484, + -0.703449,-0.101581,0.703449,0.338094,0.769563,-0.338094, + -0.698103,-0.159073,0.698103,0.332422,0.838781,-0.332422, + -0.342105,-0.144791,0.92844,0.408594,0.838781,-0.286719, + -0.342105,-0.144791,0.92844,0.408594,0.838781,-0.286719, + -0.344116,-0.092655,0.934344,0.411687,0.769563,-0.293938, + -0.703449,-0.101581,0.703449,0.338094,0.769563,-0.338094, + 0,-0.132314,0.991208,0.5,0.838781,-0.271484, + 0,-0.084902,0.996389,0.5,0.769563,-0.279219, + -0.344116,-0.092655,0.934344,0.411687,0.769563,-0.293938, + 0,-0.132314,0.991208,0.5,0.838781,-0.271484, + -0.344116,-0.092655,0.934344,0.411687,0.769563,-0.293938, + -0.342105,-0.144791,0.92844,0.408594,0.838781,-0.286719, + 0,-0.084902,0.996389,0.5,0.769563,-0.279219, + 0,-0.051662,0.998665,0.5,0.686547,-0.285195, + -0.344986,-0.057445,0.936848,0.414078,0.686547,-0.299516, + -0.344986,-0.057445,0.936848,0.414078,0.686547,-0.299516, + -0.344116,-0.092655,0.934344,0.411687,0.769563,-0.293938, + 0,-0.084902,0.996389,0.5,0.769563,-0.279219, + -0.705656,-0.064019,0.705656,0.342477,0.686547,-0.342477, + -0.703449,-0.101581,0.703449,0.338094,0.769563,-0.338094, + -0.344116,-0.092655,0.934344,0.411687,0.769563,-0.293938, + -0.705656,-0.064019,0.705656,0.342477,0.686547,-0.342477, + -0.344116,-0.092655,0.934344,0.411687,0.769563,-0.293938, + -0.344986,-0.057445,0.936848,0.414078,0.686547,-0.299516, + 0.342105,-0.144791,0.92844,0.591406,0.838781,-0.286719, + 0.698103,-0.159073,0.698103,0.667578,0.838781,-0.332422, + 0.703449,-0.101581,0.703449,0.661906,0.769563,-0.338094, + 0.703449,-0.101581,0.703449,0.661906,0.769563,-0.338094, + 0.344116,-0.092655,0.934344,0.588313,0.769563,-0.293938, + 0.342105,-0.144791,0.92844,0.591406,0.838781,-0.286719, + 0.705656,-0.064019,0.705656,0.657523,0.686547,-0.342477, + 0.344986,-0.057445,0.936848,0.585922,0.686547,-0.299516, + 0.344116,-0.092655,0.934344,0.588313,0.769563,-0.293938, + 0.705656,-0.064019,0.705656,0.657523,0.686547,-0.342477, + 0.344116,-0.092655,0.934344,0.588313,0.769563,-0.293938, + 0.703449,-0.101581,0.703449,0.661906,0.769563,-0.338094, + 0.344986,-0.057445,0.936848,0.585922,0.686547,-0.299516, + 0,-0.051662,0.998665,0.5,0.686547,-0.285195, + 0,-0.084902,0.996389,0.5,0.769563,-0.279219, + 0,-0.084902,0.996389,0.5,0.769563,-0.279219, + 0.344116,-0.092655,0.934344,0.588313,0.769563,-0.293938, + 0.344986,-0.057445,0.936848,0.585922,0.686547,-0.299516, + 0,-0.132314,0.991208,0.5,0.838781,-0.271484, + 0.342105,-0.144791,0.92844,0.591406,0.838781,-0.286719, + 0.344116,-0.092655,0.934344,0.588313,0.769563,-0.293938, + 0,-0.132314,0.991208,0.5,0.838781,-0.271484, + 0.344116,-0.092655,0.934344,0.588313,0.769563,-0.293938, + 0,-0.084902,0.996389,0.5,0.769563,-0.279219, + 0.707107,-0.000155,0.707107,0.653656,0.494688,-0.346344, + 0.285548,-0.000151,0.958364,0.583813,0.494688,-0.304437, + 0.345395,-0.028246,0.938032,0.584375,0.593625,-0.303125, + 0.707107,-0.000155,0.707107,0.653656,0.494688,-0.346344, + 0.345395,-0.028246,0.938032,0.584375,0.593625,-0.303125, + 0.706706,-0.033664,0.706706,0.654688,0.593625,-0.345313, + 0.285548,-0.000151,0.958364,0.583813,0.494688,-0.304437, + 0,-0.00015,1,0.5,0.494688,-0.290469, + 0,-0.023338,0.999728,0.5,0.593625,-0.289063, + 0,-0.023338,0.999728,0.5,0.593625,-0.289063, + 0.345395,-0.028246,0.938032,0.584375,0.593625,-0.303125, + 0.285548,-0.000151,0.958364,0.583813,0.494688,-0.304437, + 0,-0.051662,0.998665,0.5,0.686547,-0.285195, + 0.344986,-0.057445,0.936848,0.585922,0.686547,-0.299516, + 0.345395,-0.028246,0.938032,0.584375,0.593625,-0.303125, + 0,-0.051662,0.998665,0.5,0.686547,-0.285195, + 0.345395,-0.028246,0.938032,0.584375,0.593625,-0.303125, + 0,-0.023338,0.999728,0.5,0.593625,-0.289063, + 0.344986,-0.057445,0.936848,0.585922,0.686547,-0.299516, + 0.705656,-0.064019,0.705656,0.657523,0.686547,-0.342477, + 0.706706,-0.033664,0.706706,0.654688,0.593625,-0.345313, + 0.706706,-0.033664,0.706706,0.654688,0.593625,-0.345313, + 0.345395,-0.028246,0.938032,0.584375,0.593625,-0.303125, + 0.344986,-0.057445,0.936848,0.585922,0.686547,-0.299516, + -0.707107,-0.000155,0.707107,0.346344,0.494688,-0.346344, + -0.706706,-0.033664,0.706706,0.345313,0.593625,-0.345313, + -0.345395,-0.028246,0.938032,0.415625,0.593625,-0.303125, + -0.707107,-0.000155,0.707107,0.346344,0.494688,-0.346344, + -0.345395,-0.028246,0.938032,0.415625,0.593625,-0.303125, + -0.285548,-0.000151,0.958364,0.416187,0.494688,-0.304437, + -0.706706,-0.033664,0.706706,0.345313,0.593625,-0.345313, + -0.705656,-0.064019,0.705656,0.342477,0.686547,-0.342477, + -0.344986,-0.057445,0.936848,0.414078,0.686547,-0.299516, + -0.344986,-0.057445,0.936848,0.414078,0.686547,-0.299516, + -0.345395,-0.028246,0.938032,0.415625,0.593625,-0.303125, + -0.706706,-0.033664,0.706706,0.345313,0.593625,-0.345313, + 0,-0.051662,0.998665,0.5,0.686547,-0.285195, + 0,-0.023338,0.999728,0.5,0.593625,-0.289063, + -0.345395,-0.028246,0.938032,0.415625,0.593625,-0.303125, + 0,-0.051662,0.998665,0.5,0.686547,-0.285195, + -0.345395,-0.028246,0.938032,0.415625,0.593625,-0.303125, + -0.344986,-0.057445,0.936848,0.414078,0.686547,-0.299516, + 0,-0.023338,0.999728,0.5,0.593625,-0.289063, + 0,-0.00015,1,0.5,0.494688,-0.290469, + -0.285548,-0.000151,0.958364,0.416187,0.494688,-0.304437, + -0.285548,-0.000151,0.958364,0.416187,0.494688,-0.304437, + -0.345395,-0.028246,0.938032,0.415625,0.593625,-0.303125, + 0,-0.023338,0.999728,0.5,0.593625,-0.289063, + -0.703449,-0.101581,-0.703449,0.338094,0.769563,-0.661906, + -0.698103,-0.159073,-0.698103,0.332422,0.838781,-0.667578, + -0.92844,-0.144791,-0.342105,0.286719,0.838781,-0.591406, + -0.92844,-0.144791,-0.342105,0.286719,0.838781,-0.591406, + -0.934344,-0.092655,-0.344116,0.293938,0.769563,-0.588313, + -0.703449,-0.101581,-0.703449,0.338094,0.769563,-0.661906, + -0.991208,-0.132314,0,0.271484,0.838781,-0.5, + -0.996389,-0.084902,0,0.279219,0.769563,-0.5, + -0.934344,-0.092655,-0.344116,0.293938,0.769563,-0.588313, + -0.991208,-0.132314,0,0.271484,0.838781,-0.5, + -0.934344,-0.092655,-0.344116,0.293938,0.769563,-0.588313, + -0.92844,-0.144791,-0.342105,0.286719,0.838781,-0.591406, + -0.996389,-0.084902,0,0.279219,0.769563,-0.5, + -0.998665,-0.051662,0,0.285195,0.686547,-0.5, + -0.936848,-0.057445,-0.344986,0.299516,0.686547,-0.585922, + -0.936848,-0.057445,-0.344986,0.299516,0.686547,-0.585922, + -0.934344,-0.092655,-0.344116,0.293938,0.769563,-0.588313, + -0.996389,-0.084902,0,0.279219,0.769563,-0.5, + -0.705656,-0.064019,-0.705656,0.342477,0.686547,-0.657523, + -0.703449,-0.101581,-0.703449,0.338094,0.769563,-0.661906, + -0.934344,-0.092655,-0.344116,0.293938,0.769563,-0.588313, + -0.705656,-0.064019,-0.705656,0.342477,0.686547,-0.657523, + -0.934344,-0.092655,-0.344116,0.293938,0.769563,-0.588313, + -0.936848,-0.057445,-0.344986,0.299516,0.686547,-0.585922, + -0.92844,-0.144791,0.342105,0.286719,0.838781,-0.408594, + -0.698103,-0.159073,0.698103,0.332422,0.838781,-0.332422, + -0.703449,-0.101581,0.703449,0.338094,0.769563,-0.338094, + -0.703449,-0.101581,0.703449,0.338094,0.769563,-0.338094, + -0.934344,-0.092655,0.344116,0.293938,0.769563,-0.411687, + -0.92844,-0.144791,0.342105,0.286719,0.838781,-0.408594, + -0.705656,-0.064019,0.705656,0.342477,0.686547,-0.342477, + -0.936848,-0.057445,0.344986,0.299516,0.686547,-0.414078, + -0.934344,-0.092655,0.344116,0.293938,0.769563,-0.411687, + -0.705656,-0.064019,0.705656,0.342477,0.686547,-0.342477, + -0.934344,-0.092655,0.344116,0.293938,0.769563,-0.411687, + -0.703449,-0.101581,0.703449,0.338094,0.769563,-0.338094, + -0.936848,-0.057445,0.344986,0.299516,0.686547,-0.414078, + -0.998665,-0.051662,0,0.285195,0.686547,-0.5, + -0.996389,-0.084902,0,0.279219,0.769563,-0.5, + -0.996389,-0.084902,0,0.279219,0.769563,-0.5, + -0.934344,-0.092655,0.344116,0.293938,0.769563,-0.411687, + -0.936848,-0.057445,0.344986,0.299516,0.686547,-0.414078, + -0.991208,-0.132314,0,0.271484,0.838781,-0.5, + -0.92844,-0.144791,0.342105,0.286719,0.838781,-0.408594, + -0.934344,-0.092655,0.344116,0.293938,0.769563,-0.411687, + -0.991208,-0.132314,0,0.271484,0.838781,-0.5, + -0.934344,-0.092655,0.344116,0.293938,0.769563,-0.411687, + -0.996389,-0.084902,0,0.279219,0.769563,-0.5, + -0.707107,-0.000155,0.707107,0.346344,0.494688,-0.346344, + -0.958364,-0.000151,0.285548,0.304437,0.494688,-0.416187, + -0.938032,-0.028246,0.345395,0.303125,0.593625,-0.415625, + -0.707107,-0.000155,0.707107,0.346344,0.494688,-0.346344, + -0.938032,-0.028246,0.345395,0.303125,0.593625,-0.415625, + -0.706706,-0.033664,0.706706,0.345313,0.593625,-0.345313, + -0.958364,-0.000151,0.285548,0.304437,0.494688,-0.416187, + -1,-0.00015,0,0.290469,0.494688,-0.5, + -0.999728,-0.023338,0,0.289063,0.593625,-0.5, + -0.999728,-0.023338,0,0.289063,0.593625,-0.5, + -0.938032,-0.028246,0.345395,0.303125,0.593625,-0.415625, + -0.958364,-0.000151,0.285548,0.304437,0.494688,-0.416187, + -0.998665,-0.051662,0,0.285195,0.686547,-0.5, + -0.936848,-0.057445,0.344986,0.299516,0.686547,-0.414078, + -0.938032,-0.028246,0.345395,0.303125,0.593625,-0.415625, + -0.998665,-0.051662,0,0.285195,0.686547,-0.5, + -0.938032,-0.028246,0.345395,0.303125,0.593625,-0.415625, + -0.999728,-0.023338,0,0.289063,0.593625,-0.5, + -0.936848,-0.057445,0.344986,0.299516,0.686547,-0.414078, + -0.705656,-0.064019,0.705656,0.342477,0.686547,-0.342477, + -0.706706,-0.033664,0.706706,0.345313,0.593625,-0.345313, + -0.706706,-0.033664,0.706706,0.345313,0.593625,-0.345313, + -0.938032,-0.028246,0.345395,0.303125,0.593625,-0.415625, + -0.936848,-0.057445,0.344986,0.299516,0.686547,-0.414078, + -0.707107,-0.000155,-0.707107,0.346344,0.494688,-0.653656, + -0.706706,-0.033664,-0.706706,0.345313,0.593625,-0.654688, + -0.938032,-0.028246,-0.345395,0.303125,0.593625,-0.584375, + -0.707107,-0.000155,-0.707107,0.346344,0.494688,-0.653656, + -0.938032,-0.028246,-0.345395,0.303125,0.593625,-0.584375, + -0.958364,-0.000151,-0.285548,0.304437,0.494688,-0.583813, + -0.706706,-0.033664,-0.706706,0.345313,0.593625,-0.654688, + -0.705656,-0.064019,-0.705656,0.342477,0.686547,-0.657523, + -0.936848,-0.057445,-0.344986,0.299516,0.686547,-0.585922, + -0.936848,-0.057445,-0.344986,0.299516,0.686547,-0.585922, + -0.938032,-0.028246,-0.345395,0.303125,0.593625,-0.584375, + -0.706706,-0.033664,-0.706706,0.345313,0.593625,-0.654688, + -0.998665,-0.051662,0,0.285195,0.686547,-0.5, + -0.999728,-0.023338,0,0.289063,0.593625,-0.5, + -0.938032,-0.028246,-0.345395,0.303125,0.593625,-0.584375, + -0.998665,-0.051662,0,0.285195,0.686547,-0.5, + -0.938032,-0.028246,-0.345395,0.303125,0.593625,-0.584375, + -0.936848,-0.057445,-0.344986,0.299516,0.686547,-0.585922, + -0.999728,-0.023338,0,0.289063,0.593625,-0.5, + -1,-0.00015,0,0.290469,0.494688,-0.5, + -0.958364,-0.000151,-0.285548,0.304437,0.494688,-0.583813, + -0.958364,-0.000151,-0.285548,0.304437,0.494688,-0.583813, + -0.938032,-0.028246,-0.345395,0.303125,0.593625,-0.584375, + -0.999728,-0.023338,0,0.289063,0.593625,-0.5, + -0.703939,0.094548,-0.703939,0.338094,0.207062,-0.661906, + -0.699155,0.149544,-0.699156,0.332422,0.132531,-0.667578, + -0.342523,0.135808,-0.929642,0.408594,0.132531,-0.713281, + -0.342523,0.135808,-0.929642,0.408594,0.132531,-0.713281, + -0.344301,0.086306,-0.934884,0.411687,0.207062,-0.706063, + -0.703939,0.094548,-0.703939,0.338094,0.207062,-0.661906, + 0,0.12379,-0.992308,0.5,0.132531,-0.728516, + 0,0.079157,-0.996862,0.5,0.207062,-0.720781, + -0.344301,0.086306,-0.934884,0.411687,0.207062,-0.706063, + 0,0.12379,-0.992308,0.5,0.132531,-0.728516, + -0.344301,0.086306,-0.934884,0.411687,0.207062,-0.706063, + -0.342523,0.135808,-0.929642,0.408594,0.132531,-0.713281, + 0,0.079157,-0.996862,0.5,0.207062,-0.720781, + 0,0.048741,-0.998811,0.5,0.295922,-0.714805, + -0.345045,0.054036,-0.937029,0.414078,0.295922,-0.700484, + -0.345045,0.054036,-0.937029,0.414078,0.295922,-0.700484, + -0.344301,0.086306,-0.934884,0.411687,0.207062,-0.706063, + 0,0.079157,-0.996862,0.5,0.207062,-0.720781, + -0.70583,0.060067,-0.70583,0.342477,0.295922,-0.657523, + -0.703939,0.094548,-0.703939,0.338094,0.207062,-0.661906, + -0.344301,0.086306,-0.934884,0.411687,0.207062,-0.706063, + -0.70583,0.060067,-0.70583,0.342477,0.295922,-0.657523, + -0.344301,0.086306,-0.934884,0.411687,0.207062,-0.706063, + -0.345045,0.054036,-0.937029,0.414078,0.295922,-0.700484, + 0.342523,0.135808,-0.929642,0.591406,0.132531,-0.713281, + 0.699155,0.149544,-0.699155,0.667578,0.132531,-0.667578, + 0.703939,0.094547,-0.703939,0.661906,0.207062,-0.661906, + 0.703939,0.094547,-0.703939,0.661906,0.207062,-0.661906, + 0.344301,0.086306,-0.934884,0.588313,0.207062,-0.706063, + 0.342523,0.135808,-0.929642,0.591406,0.132531,-0.713281, + 0.70583,0.060067,-0.70583,0.657523,0.295922,-0.657523, + 0.345045,0.054036,-0.937029,0.585922,0.295922,-0.700484, + 0.344301,0.086306,-0.934884,0.588313,0.207062,-0.706063, + 0.70583,0.060067,-0.70583,0.657523,0.295922,-0.657523, + 0.344301,0.086306,-0.934884,0.588313,0.207062,-0.706063, + 0.703939,0.094547,-0.703939,0.661906,0.207062,-0.661906, + 0.345045,0.054036,-0.937029,0.585922,0.295922,-0.700484, + 0,0.048741,-0.998811,0.5,0.295922,-0.714805, + 0,0.079157,-0.996862,0.5,0.207062,-0.720781, + 0,0.079157,-0.996862,0.5,0.207062,-0.720781, + 0.344301,0.086306,-0.934884,0.588313,0.207062,-0.706063, + 0.345045,0.054036,-0.937029,0.585922,0.295922,-0.700484, + 0,0.12379,-0.992308,0.5,0.132531,-0.728516, + 0.342523,0.135808,-0.929642,0.591406,0.132531,-0.713281, + 0.344301,0.086306,-0.934884,0.588313,0.207062,-0.706063, + 0,0.12379,-0.992308,0.5,0.132531,-0.728516, + 0.344301,0.086306,-0.934884,0.588313,0.207062,-0.706063, + 0,0.079157,-0.996862,0.5,0.207062,-0.720781, + 0.707107,-0.000155,-0.707107,0.653656,0.494688,-0.653656, + 0.285548,-0.000151,-0.958364,0.583813,0.494688,-0.695563, + 0.345404,0.027067,-0.938064,0.584375,0.393625,-0.696875, + 0.707107,-0.000155,-0.707107,0.653656,0.494688,-0.653656, + 0.345404,0.027067,-0.938064,0.584375,0.393625,-0.696875, + 0.706741,0.032156,-0.706741,0.654688,0.393625,-0.654688, + 0.285548,-0.000151,-0.958364,0.583813,0.494688,-0.695563, + 0,-0.00015,-1,0.5,0.494688,-0.709531, + 0,0.022461,-0.999748,0.5,0.393625,-0.710938, + 0,0.022461,-0.999748,0.5,0.393625,-0.710938, + 0.345404,0.027067,-0.938064,0.584375,0.393625,-0.696875, + 0.285548,-0.000151,-0.958364,0.583813,0.494688,-0.695563, + 0,0.048741,-0.998811,0.5,0.295922,-0.714805, + 0.345045,0.054036,-0.937029,0.585922,0.295922,-0.700484, + 0.345404,0.027067,-0.938064,0.584375,0.393625,-0.696875, + 0,0.048741,-0.998811,0.5,0.295922,-0.714805, + 0.345404,0.027067,-0.938064,0.584375,0.393625,-0.696875, + 0,0.022461,-0.999748,0.5,0.393625,-0.710938, + 0.345045,0.054036,-0.937029,0.585922,0.295922,-0.700484, + 0.70583,0.060067,-0.70583,0.657523,0.295922,-0.657523, + 0.706741,0.032156,-0.706741,0.654688,0.393625,-0.654688, + 0.706741,0.032156,-0.706741,0.654688,0.393625,-0.654688, + 0.345404,0.027067,-0.938064,0.584375,0.393625,-0.696875, + 0.345045,0.054036,-0.937029,0.585922,0.295922,-0.700484, + -0.707107,-0.000155,-0.707107,0.346344,0.494688,-0.653656, + -0.706741,0.032156,-0.706741,0.345313,0.393625,-0.654688, + -0.345404,0.027067,-0.938064,0.415625,0.393625,-0.696875, + -0.707107,-0.000155,-0.707107,0.346344,0.494688,-0.653656, + -0.345404,0.027067,-0.938064,0.415625,0.393625,-0.696875, + -0.285548,-0.000151,-0.958364,0.416187,0.494688,-0.695563, + -0.706741,0.032156,-0.706741,0.345313,0.393625,-0.654688, + -0.70583,0.060067,-0.70583,0.342477,0.295922,-0.657523, + -0.345045,0.054036,-0.937029,0.414078,0.295922,-0.700484, + -0.345045,0.054036,-0.937029,0.414078,0.295922,-0.700484, + -0.345404,0.027067,-0.938064,0.415625,0.393625,-0.696875, + -0.706741,0.032156,-0.706741,0.345313,0.393625,-0.654688, + 0,0.048741,-0.998811,0.5,0.295922,-0.714805, + 0,0.022461,-0.999748,0.5,0.393625,-0.710938, + -0.345404,0.027067,-0.938064,0.415625,0.393625,-0.696875, + 0,0.048741,-0.998811,0.5,0.295922,-0.714805, + -0.345404,0.027067,-0.938064,0.415625,0.393625,-0.696875, + -0.345045,0.054036,-0.937029,0.414078,0.295922,-0.700484, + 0,0.022461,-0.999748,0.5,0.393625,-0.710938, + 0,-0.00015,-1,0.5,0.494688,-0.709531, + -0.285548,-0.000151,-0.958364,0.416187,0.494688,-0.695563, + -0.285548,-0.000151,-0.958364,0.416187,0.494688,-0.695563, + -0.345404,0.027067,-0.938064,0.415625,0.393625,-0.696875, + 0,0.022461,-0.999748,0.5,0.393625,-0.710938, + -0.929642,0.135808,-0.342523,0.286719,0.132531,-0.591406, + -0.699155,0.149544,-0.699156,0.332422,0.132531,-0.667578, + -0.703939,0.094548,-0.703939,0.338094,0.207062,-0.661906, + -0.703939,0.094548,-0.703939,0.338094,0.207062,-0.661906, + -0.934884,0.086306,-0.344301,0.293938,0.207062,-0.588313, + -0.929642,0.135808,-0.342523,0.286719,0.132531,-0.591406, + -0.70583,0.060067,-0.70583,0.342477,0.295922,-0.657523, + -0.937029,0.054035,-0.345045,0.299516,0.295922,-0.585922, + -0.934884,0.086306,-0.344301,0.293938,0.207062,-0.588313, + -0.70583,0.060067,-0.70583,0.342477,0.295922,-0.657523, + -0.934884,0.086306,-0.344301,0.293938,0.207062,-0.588313, + -0.703939,0.094548,-0.703939,0.338094,0.207062,-0.661906, + -0.937029,0.054035,-0.345045,0.299516,0.295922,-0.585922, + -0.998811,0.04874,0,0.285195,0.295922,-0.5, + -0.996862,0.079157,0,0.279219,0.207062,-0.5, + -0.996862,0.079157,0,0.279219,0.207062,-0.5, + -0.934884,0.086306,-0.344301,0.293938,0.207062,-0.588313, + -0.937029,0.054035,-0.345045,0.299516,0.295922,-0.585922, + -0.992308,0.12379,0,0.271484,0.132531,-0.5, + -0.929642,0.135808,-0.342523,0.286719,0.132531,-0.591406, + -0.934884,0.086306,-0.344301,0.293938,0.207062,-0.588313, + -0.992308,0.12379,0,0.271484,0.132531,-0.5, + -0.934884,0.086306,-0.344301,0.293938,0.207062,-0.588313, + -0.996862,0.079157,0,0.279219,0.207062,-0.5, + -0.707107,-0.000155,-0.707107,0.346344,0.494688,-0.653656, + -0.958364,-0.000151,-0.285548,0.304437,0.494688,-0.583813, + -0.938064,0.027067,-0.345404,0.303125,0.393625,-0.584375, + -0.707107,-0.000155,-0.707107,0.346344,0.494688,-0.653656, + -0.938064,0.027067,-0.345404,0.303125,0.393625,-0.584375, + -0.706741,0.032156,-0.706741,0.345313,0.393625,-0.654688, + -0.958364,-0.000151,-0.285548,0.304437,0.494688,-0.583813, + -1,-0.00015,0,0.290469,0.494688,-0.5, + -0.999748,0.022461,0,0.289063,0.393625,-0.5, + -0.999748,0.022461,0,0.289063,0.393625,-0.5, + -0.938064,0.027067,-0.345404,0.303125,0.393625,-0.584375, + -0.958364,-0.000151,-0.285548,0.304437,0.494688,-0.583813, + -0.998811,0.04874,0,0.285195,0.295922,-0.5, + -0.937029,0.054035,-0.345045,0.299516,0.295922,-0.585922, + -0.938064,0.027067,-0.345404,0.303125,0.393625,-0.584375, + -0.998811,0.04874,0,0.285195,0.295922,-0.5, + -0.938064,0.027067,-0.345404,0.303125,0.393625,-0.584375, + -0.999748,0.022461,0,0.289063,0.393625,-0.5, + -0.937029,0.054035,-0.345045,0.299516,0.295922,-0.585922, + -0.70583,0.060067,-0.70583,0.342477,0.295922,-0.657523, + -0.706741,0.032156,-0.706741,0.345313,0.393625,-0.654688, + -0.706741,0.032156,-0.706741,0.345313,0.393625,-0.654688, + -0.938064,0.027067,-0.345404,0.303125,0.393625,-0.584375, + -0.937029,0.054035,-0.345045,0.299516,0.295922,-0.585922, + -0.707107,-0.000155,0.707107,0.346344,0.494688,-0.346344, + -0.706741,0.032156,0.706741,0.345313,0.393625,-0.345313, + -0.938064,0.027067,0.345404,0.303125,0.393625,-0.415625, + -0.707107,-0.000155,0.707107,0.346344,0.494688,-0.346344, + -0.938064,0.027067,0.345404,0.303125,0.393625,-0.415625, + -0.958364,-0.000151,0.285548,0.304437,0.494688,-0.416187, + -0.706741,0.032156,0.706741,0.345313,0.393625,-0.345313, + -0.70583,0.060067,0.70583,0.342477,0.295922,-0.342477, + -0.937029,0.054035,0.345045,0.299516,0.295922,-0.414078, + -0.937029,0.054035,0.345045,0.299516,0.295922,-0.414078, + -0.938064,0.027067,0.345404,0.303125,0.393625,-0.415625, + -0.706741,0.032156,0.706741,0.345313,0.393625,-0.345313, + -0.998811,0.04874,0,0.285195,0.295922,-0.5, + -0.999748,0.022461,0,0.289063,0.393625,-0.5, + -0.938064,0.027067,0.345404,0.303125,0.393625,-0.415625, + -0.998811,0.04874,0,0.285195,0.295922,-0.5, + -0.938064,0.027067,0.345404,0.303125,0.393625,-0.415625, + -0.937029,0.054035,0.345045,0.299516,0.295922,-0.414078, + -0.999748,0.022461,0,0.289063,0.393625,-0.5, + -1,-0.00015,0,0.290469,0.494688,-0.5, + -0.958364,-0.000151,0.285548,0.304437,0.494688,-0.416187, + -0.958364,-0.000151,0.285548,0.304437,0.494688,-0.416187, + -0.938064,0.027067,0.345404,0.303125,0.393625,-0.415625, + -0.999748,0.022461,0,0.289063,0.393625,-0.5, + -0.703939,0.094548,0.703939,0.338094,0.207062,-0.338094, + -0.699155,0.149545,0.699155,0.332422,0.132531,-0.332422, + -0.929642,0.135808,0.342523,0.286719,0.132531,-0.408594, + -0.929642,0.135808,0.342523,0.286719,0.132531,-0.408594, + -0.934884,0.086306,0.344301,0.293938,0.207062,-0.411687, + -0.703939,0.094548,0.703939,0.338094,0.207062,-0.338094, + -0.992308,0.12379,0,0.271484,0.132531,-0.5, + -0.996862,0.079157,0,0.279219,0.207062,-0.5, + -0.934884,0.086306,0.344301,0.293938,0.207062,-0.411687, + -0.992308,0.12379,0,0.271484,0.132531,-0.5, + -0.934884,0.086306,0.344301,0.293938,0.207062,-0.411687, + -0.929642,0.135808,0.342523,0.286719,0.132531,-0.408594, + -0.996862,0.079157,0,0.279219,0.207062,-0.5, + -0.998811,0.04874,0,0.285195,0.295922,-0.5, + -0.937029,0.054035,0.345045,0.299516,0.295922,-0.414078, + -0.937029,0.054035,0.345045,0.299516,0.295922,-0.414078, + -0.934884,0.086306,0.344301,0.293938,0.207062,-0.411687, + -0.996862,0.079157,0,0.279219,0.207062,-0.5, + -0.70583,0.060067,0.70583,0.342477,0.295922,-0.342477, + -0.703939,0.094548,0.703939,0.338094,0.207062,-0.338094, + -0.934884,0.086306,0.344301,0.293938,0.207062,-0.411687, + -0.70583,0.060067,0.70583,0.342477,0.295922,-0.342477, + -0.934884,0.086306,0.344301,0.293938,0.207062,-0.411687, + -0.937029,0.054035,0.345045,0.299516,0.295922,-0.414078, + -0.342523,0.135808,0.929642,0.408594,0.132531,-0.286719, + -0.699155,0.149545,0.699155,0.332422,0.132531,-0.332422, + -0.703939,0.094548,0.703939,0.338094,0.207062,-0.338094, + -0.703939,0.094548,0.703939,0.338094,0.207062,-0.338094, + -0.344301,0.086306,0.934884,0.411687,0.207062,-0.293938, + -0.342523,0.135808,0.929642,0.408594,0.132531,-0.286719, + -0.70583,0.060067,0.70583,0.342477,0.295922,-0.342477, + -0.345045,0.054035,0.937029,0.414078,0.295922,-0.299516, + -0.344301,0.086306,0.934884,0.411687,0.207062,-0.293938, + -0.70583,0.060067,0.70583,0.342477,0.295922,-0.342477, + -0.344301,0.086306,0.934884,0.411687,0.207062,-0.293938, + -0.703939,0.094548,0.703939,0.338094,0.207062,-0.338094, + -0.345045,0.054035,0.937029,0.414078,0.295922,-0.299516, + 0,0.04874,0.998811,0.5,0.295922,-0.285195, + 0,0.079157,0.996862,0.5,0.207062,-0.279219, + 0,0.079157,0.996862,0.5,0.207062,-0.279219, + -0.344301,0.086306,0.934884,0.411687,0.207062,-0.293938, + -0.345045,0.054035,0.937029,0.414078,0.295922,-0.299516, + 0,0.12379,0.992308,0.5,0.132531,-0.271484, + -0.342523,0.135808,0.929642,0.408594,0.132531,-0.286719, + -0.344301,0.086306,0.934884,0.411687,0.207062,-0.293938, + 0,0.12379,0.992308,0.5,0.132531,-0.271484, + -0.344301,0.086306,0.934884,0.411687,0.207062,-0.293938, + 0,0.079157,0.996862,0.5,0.207062,-0.279219, + -0.707107,-0.000155,0.707107,0.346344,0.494688,-0.346344, + -0.285548,-0.000151,0.958364,0.416187,0.494688,-0.304437, + -0.345404,0.027067,0.938064,0.415625,0.393625,-0.303125, + -0.707107,-0.000155,0.707107,0.346344,0.494688,-0.346344, + -0.345404,0.027067,0.938064,0.415625,0.393625,-0.303125, + -0.706741,0.032156,0.706741,0.345313,0.393625,-0.345313, + -0.285548,-0.000151,0.958364,0.416187,0.494688,-0.304437, + 0,-0.00015,1,0.5,0.494688,-0.290469, + 0,0.022461,0.999748,0.5,0.393625,-0.289063, + 0,0.022461,0.999748,0.5,0.393625,-0.289063, + -0.345404,0.027067,0.938064,0.415625,0.393625,-0.303125, + -0.285548,-0.000151,0.958364,0.416187,0.494688,-0.304437, + 0,0.04874,0.998811,0.5,0.295922,-0.285195, + -0.345045,0.054035,0.937029,0.414078,0.295922,-0.299516, + -0.345404,0.027067,0.938064,0.415625,0.393625,-0.303125, + 0,0.04874,0.998811,0.5,0.295922,-0.285195, + -0.345404,0.027067,0.938064,0.415625,0.393625,-0.303125, + 0,0.022461,0.999748,0.5,0.393625,-0.289063, + -0.345045,0.054035,0.937029,0.414078,0.295922,-0.299516, + -0.70583,0.060067,0.70583,0.342477,0.295922,-0.342477, + -0.706741,0.032156,0.706741,0.345313,0.393625,-0.345313, + -0.706741,0.032156,0.706741,0.345313,0.393625,-0.345313, + -0.345404,0.027067,0.938064,0.415625,0.393625,-0.303125, + -0.345045,0.054035,0.937029,0.414078,0.295922,-0.299516, + 0.707107,-0.000155,0.707107,0.653656,0.494688,-0.346344, + 0.706741,0.032156,0.706741,0.654688,0.393625,-0.345313, + 0.345404,0.027067,0.938064,0.584375,0.393625,-0.303125, + 0.707107,-0.000155,0.707107,0.653656,0.494688,-0.346344, + 0.345404,0.027067,0.938064,0.584375,0.393625,-0.303125, + 0.285548,-0.000151,0.958364,0.583813,0.494688,-0.304437, + 0.706741,0.032156,0.706741,0.654688,0.393625,-0.345313, + 0.70583,0.060067,0.70583,0.657523,0.295922,-0.342477, + 0.345045,0.054035,0.937029,0.585922,0.295922,-0.299516, + 0.345045,0.054035,0.937029,0.585922,0.295922,-0.299516, + 0.345404,0.027067,0.938064,0.584375,0.393625,-0.303125, + 0.706741,0.032156,0.706741,0.654688,0.393625,-0.345313, + 0,0.04874,0.998811,0.5,0.295922,-0.285195, + 0,0.022461,0.999748,0.5,0.393625,-0.289063, + 0.345404,0.027067,0.938064,0.584375,0.393625,-0.303125, + 0,0.04874,0.998811,0.5,0.295922,-0.285195, + 0.345404,0.027067,0.938064,0.584375,0.393625,-0.303125, + 0.345045,0.054035,0.937029,0.585922,0.295922,-0.299516, + 0,0.022461,0.999748,0.5,0.393625,-0.289063, + 0,-0.00015,1,0.5,0.494688,-0.290469, + 0.285548,-0.000151,0.958364,0.583813,0.494688,-0.304437, + 0.285548,-0.000151,0.958364,0.583813,0.494688,-0.304437, + 0.345404,0.027067,0.938064,0.584375,0.393625,-0.303125, + 0,0.022461,0.999748,0.5,0.393625,-0.289063, + 0.703939,0.094548,0.703939,0.661906,0.207062,-0.338094, + 0.699156,0.149544,0.699155,0.667578,0.132531,-0.332422, + 0.342523,0.135808,0.929642,0.591406,0.132531,-0.286719, + 0.342523,0.135808,0.929642,0.591406,0.132531,-0.286719, + 0.344301,0.086306,0.934884,0.588313,0.207062,-0.293938, + 0.703939,0.094548,0.703939,0.661906,0.207062,-0.338094, + 0,0.12379,0.992308,0.5,0.132531,-0.271484, + 0,0.079157,0.996862,0.5,0.207062,-0.279219, + 0.344301,0.086306,0.934884,0.588313,0.207062,-0.293938, + 0,0.12379,0.992308,0.5,0.132531,-0.271484, + 0.344301,0.086306,0.934884,0.588313,0.207062,-0.293938, + 0.342523,0.135808,0.929642,0.591406,0.132531,-0.286719, + 0,0.079157,0.996862,0.5,0.207062,-0.279219, + 0,0.04874,0.998811,0.5,0.295922,-0.285195, + 0.345045,0.054035,0.937029,0.585922,0.295922,-0.299516, + 0.345045,0.054035,0.937029,0.585922,0.295922,-0.299516, + 0.344301,0.086306,0.934884,0.588313,0.207062,-0.293938, + 0,0.079157,0.996862,0.5,0.207062,-0.279219, + 0.70583,0.060067,0.70583,0.657523,0.295922,-0.342477, + 0.703939,0.094548,0.703939,0.661906,0.207062,-0.338094, + 0.344301,0.086306,0.934884,0.588313,0.207062,-0.293938, + 0.70583,0.060067,0.70583,0.657523,0.295922,-0.342477, + 0.344301,0.086306,0.934884,0.588313,0.207062,-0.293938, + 0.345045,0.054035,0.937029,0.585922,0.295922,-0.299516, + 0.929642,0.135808,0.342523,0.713281,0.132531,-0.408594, + 0.699156,0.149544,0.699155,0.667578,0.132531,-0.332422, + 0.703939,0.094548,0.703939,0.661906,0.207062,-0.338094, + 0.703939,0.094548,0.703939,0.661906,0.207062,-0.338094, + 0.934884,0.086306,0.344301,0.706063,0.207062,-0.411687, + 0.929642,0.135808,0.342523,0.713281,0.132531,-0.408594, + 0.70583,0.060067,0.70583,0.657523,0.295922,-0.342477, + 0.937029,0.054036,0.345045,0.700484,0.295922,-0.414078, + 0.934884,0.086306,0.344301,0.706063,0.207062,-0.411687, + 0.70583,0.060067,0.70583,0.657523,0.295922,-0.342477, + 0.934884,0.086306,0.344301,0.706063,0.207062,-0.411687, + 0.703939,0.094548,0.703939,0.661906,0.207062,-0.338094, + 0.937029,0.054036,0.345045,0.700484,0.295922,-0.414078, + 0.998811,0.048741,0,0.714805,0.295922,-0.5, + 0.996862,0.079157,0,0.720781,0.207062,-0.5, + 0.996862,0.079157,0,0.720781,0.207062,-0.5, + 0.934884,0.086306,0.344301,0.706063,0.207062,-0.411687, + 0.937029,0.054036,0.345045,0.700484,0.295922,-0.414078, + 0.992308,0.12379,0,0.728516,0.132531,-0.5, + 0.929642,0.135808,0.342523,0.713281,0.132531,-0.408594, + 0.934884,0.086306,0.344301,0.706063,0.207062,-0.411687, + 0.992308,0.12379,0,0.728516,0.132531,-0.5, + 0.934884,0.086306,0.344301,0.706063,0.207062,-0.411687, + 0.996862,0.079157,0,0.720781,0.207062,-0.5, + 0.707107,-0.000155,0.707107,0.653656,0.494688,-0.346344, + 0.958364,-0.000151,0.285548,0.695563,0.494688,-0.416187, + 0.938064,0.027067,0.345404,0.696875,0.393625,-0.415625, + 0.707107,-0.000155,0.707107,0.653656,0.494688,-0.346344, + 0.938064,0.027067,0.345404,0.696875,0.393625,-0.415625, + 0.706741,0.032156,0.706741,0.654688,0.393625,-0.345313, + 0.958364,-0.000151,0.285548,0.695563,0.494688,-0.416187, + 1,-0.00015,0,0.709531,0.494688,-0.5, + 0.999748,0.022461,0,0.710938,0.393625,-0.5, + 0.999748,0.022461,0,0.710938,0.393625,-0.5, + 0.938064,0.027067,0.345404,0.696875,0.393625,-0.415625, + 0.958364,-0.000151,0.285548,0.695563,0.494688,-0.416187, + 0.998811,0.048741,0,0.714805,0.295922,-0.5, + 0.937029,0.054036,0.345045,0.700484,0.295922,-0.414078, + 0.938064,0.027067,0.345404,0.696875,0.393625,-0.415625, + 0.998811,0.048741,0,0.714805,0.295922,-0.5, + 0.938064,0.027067,0.345404,0.696875,0.393625,-0.415625, + 0.999748,0.022461,0,0.710938,0.393625,-0.5, + 0.937029,0.054036,0.345045,0.700484,0.295922,-0.414078, + 0.70583,0.060067,0.70583,0.657523,0.295922,-0.342477, + 0.706741,0.032156,0.706741,0.654688,0.393625,-0.345313, + 0.706741,0.032156,0.706741,0.654688,0.393625,-0.345313, + 0.938064,0.027067,0.345404,0.696875,0.393625,-0.415625, + 0.937029,0.054036,0.345045,0.700484,0.295922,-0.414078, + 0.707107,-0.000155,-0.707107,0.653656,0.494688,-0.653656, + 0.706741,0.032156,-0.706741,0.654688,0.393625,-0.654688, + 0.938064,0.027067,-0.345404,0.696875,0.393625,-0.584375, + 0.707107,-0.000155,-0.707107,0.653656,0.494688,-0.653656, + 0.938064,0.027067,-0.345404,0.696875,0.393625,-0.584375, + 0.958364,-0.000151,-0.285548,0.695563,0.494688,-0.583813, + 0.706741,0.032156,-0.706741,0.654688,0.393625,-0.654688, + 0.70583,0.060067,-0.70583,0.657523,0.295922,-0.657523, + 0.937029,0.054036,-0.345045,0.700484,0.295922,-0.585922, + 0.937029,0.054036,-0.345045,0.700484,0.295922,-0.585922, + 0.938064,0.027067,-0.345404,0.696875,0.393625,-0.584375, + 0.706741,0.032156,-0.706741,0.654688,0.393625,-0.654688, + 0.998811,0.048741,0,0.714805,0.295922,-0.5, + 0.999748,0.022461,0,0.710938,0.393625,-0.5, + 0.938064,0.027067,-0.345404,0.696875,0.393625,-0.584375, + 0.998811,0.048741,0,0.714805,0.295922,-0.5, + 0.938064,0.027067,-0.345404,0.696875,0.393625,-0.584375, + 0.937029,0.054036,-0.345045,0.700484,0.295922,-0.585922, + 0.999748,0.022461,0,0.710938,0.393625,-0.5, + 1,-0.00015,0,0.709531,0.494688,-0.5, + 0.958364,-0.000151,-0.285548,0.695563,0.494688,-0.583813, + 0.958364,-0.000151,-0.285548,0.695563,0.494688,-0.583813, + 0.938064,0.027067,-0.345404,0.696875,0.393625,-0.584375, + 0.999748,0.022461,0,0.710938,0.393625,-0.5, + 0.703939,0.094547,-0.703939,0.661906,0.207062,-0.661906, + 0.699155,0.149544,-0.699155,0.667578,0.132531,-0.667578, + 0.929642,0.135808,-0.342523,0.713281,0.132531,-0.591406, + 0.929642,0.135808,-0.342523,0.713281,0.132531,-0.591406, + 0.934884,0.086306,-0.344301,0.706063,0.207062,-0.588313, + 0.703939,0.094547,-0.703939,0.661906,0.207062,-0.661906, + 0.992308,0.12379,0,0.728516,0.132531,-0.5, + 0.996862,0.079157,0,0.720781,0.207062,-0.5, + 0.934884,0.086306,-0.344301,0.706063,0.207062,-0.588313, + 0.992308,0.12379,0,0.728516,0.132531,-0.5, + 0.934884,0.086306,-0.344301,0.706063,0.207062,-0.588313, + 0.929642,0.135808,-0.342523,0.713281,0.132531,-0.591406, + 0.996862,0.079157,0,0.720781,0.207062,-0.5, + 0.998811,0.048741,0,0.714805,0.295922,-0.5, + 0.937029,0.054036,-0.345045,0.700484,0.295922,-0.585922, + 0.937029,0.054036,-0.345045,0.700484,0.295922,-0.585922, + 0.934884,0.086306,-0.344301,0.706063,0.207062,-0.588313, + 0.996862,0.079157,0,0.720781,0.207062,-0.5, + 0.70583,0.060067,-0.70583,0.657523,0.295922,-0.657523, + 0.703939,0.094547,-0.703939,0.661906,0.207062,-0.661906, + 0.934884,0.086306,-0.344301,0.706063,0.207062,-0.588313, + 0.70583,0.060067,-0.70583,0.657523,0.295922,-0.657523, + 0.934884,0.086306,-0.344301,0.706063,0.207062,-0.588313, + 0.937029,0.054036,-0.345045,0.700484,0.295922,-0.585922, + 0.699156,0.149544,0.699155,0.667578,0.132531,-0.332422, + 0.929642,0.135808,0.342523,0.713281,0.132531,-0.408594, + 0.919364,0.107435,0.378454,0.721812,0.077813,-0.404938, + 0.699156,0.149544,0.699155,0.667578,0.132531,-0.332422, + 0.919364,0.107435,0.378454,0.721812,0.077813,-0.404938, + 0.705578,0.065727,0.705578,0.674281,0.077813,-0.325719, + 0.929642,0.135808,0.342523,0.713281,0.132531,-0.408594, + 0.992308,0.12379,0,0.728516,0.132531,-0.5, + 0.995686,0.092789,0,0.737656,0.077813,-0.5, + 0.995686,0.092789,0,0.737656,0.077813,-0.5, + 0.919364,0.107435,0.378454,0.721812,0.077813,-0.404938, + 0.929642,0.135808,0.342523,0.713281,0.132531,-0.408594, + 0.995686,0.092789,0,0.737656,0.077813,-0.5, + 0.914719,-0.404091,0,0.738539,0.039819,-0.5, + 0.892993,-0.274252,0.35686,0.722453,0.040123,-0.404859, + 0.892993,-0.274252,0.35686,0.722453,0.040123,-0.404859, + 0.919364,0.107435,0.378454,0.721812,0.077813,-0.404938, + 0.995686,0.092789,0,0.737656,0.077813,-0.5, + 0.892993,-0.274252,0.35686,0.722453,0.040123,-0.404859, + 0.663755,-0.344758,0.663755,0.674539,0.040427,-0.325461, + 0.705578,0.065727,0.705578,0.674281,0.077813,-0.325719, + 0.705578,0.065727,0.705578,0.674281,0.077813,-0.325719, + 0.919364,0.107435,0.378454,0.721812,0.077813,-0.404938, + 0.892993,-0.274252,0.35686,0.722453,0.040123,-0.404859, + 0.699155,0.149544,-0.699155,0.667578,0.132531,-0.667578, + 0.705578,0.065727,-0.705578,0.674281,0.077813,-0.674281, + 0.919364,0.107435,-0.378454,0.721812,0.077813,-0.595062, + 0.699155,0.149544,-0.699155,0.667578,0.132531,-0.667578, + 0.919364,0.107435,-0.378454,0.721812,0.077813,-0.595062, + 0.929642,0.135808,-0.342523,0.713281,0.132531,-0.591406, + 0.705578,0.065727,-0.705578,0.674281,0.077813,-0.674281, + 0.663755,-0.344758,-0.663755,0.674539,0.040427,-0.674539, + 0.892994,-0.274252,-0.356859,0.722453,0.040123,-0.595141, + 0.892994,-0.274252,-0.356859,0.722453,0.040123,-0.595141, + 0.919364,0.107435,-0.378454,0.721812,0.077813,-0.595062, + 0.705578,0.065727,-0.705578,0.674281,0.077813,-0.674281, + 0.892994,-0.274252,-0.356859,0.722453,0.040123,-0.595141, + 0.914719,-0.404091,0,0.738539,0.039819,-0.5, + 0.995686,0.092789,0,0.737656,0.077813,-0.5, + 0.995686,0.092789,0,0.737656,0.077813,-0.5, + 0.919364,0.107435,-0.378454,0.721812,0.077813,-0.595062, + 0.892994,-0.274252,-0.356859,0.722453,0.040123,-0.595141, + 0.995686,0.092789,0,0.737656,0.077813,-0.5, + 0.992308,0.12379,0,0.728516,0.132531,-0.5, + 0.929642,0.135808,-0.342523,0.713281,0.132531,-0.591406, + 0.929642,0.135808,-0.342523,0.713281,0.132531,-0.591406, + 0.919364,0.107435,-0.378454,0.721812,0.077813,-0.595062, + 0.995686,0.092789,0,0.737656,0.077813,-0.5, + 0.199329,-0.959446,-0.199329,0.638667,0.007537,-0.638667, + 0.18835,-0.976969,-0.100277,0.664625,0.003052,-0.5825, + 0.517064,-0.835523,-0.185868,0.706,0.016681,-0.5875, + 0.199329,-0.959446,-0.199329,0.638667,0.007537,-0.638667, + 0.517064,-0.835523,-0.185868,0.706,0.016681,-0.5875, + 0.452944,-0.767908,-0.452945,0.660875,0.017896,-0.660875, + 0.244558,-0.969635,0,0.677562,0.000839,-0.5, + 0.596646,-0.802505,0,0.7215,0.015465,-0.5, + 0.517064,-0.835523,-0.185868,0.706,0.016681,-0.5875, + 0.244558,-0.969635,0,0.677562,0.000839,-0.5, + 0.517064,-0.835523,-0.185868,0.706,0.016681,-0.5875, + 0.18835,-0.976969,-0.100277,0.664625,0.003052,-0.5825, + 0.914719,-0.404091,0,0.738539,0.039819,-0.5, + 0.892994,-0.274252,-0.356859,0.722453,0.040123,-0.595141, + 0.517064,-0.835523,-0.185868,0.706,0.016681,-0.5875, + 0.914719,-0.404091,0,0.738539,0.039819,-0.5, + 0.517064,-0.835523,-0.185868,0.706,0.016681,-0.5875, + 0.596646,-0.802505,0,0.7215,0.015465,-0.5, + 0.892994,-0.274252,-0.356859,0.722453,0.040123,-0.595141, + 0.663755,-0.344758,-0.663755,0.674539,0.040427,-0.674539, + 0.452944,-0.767908,-0.452945,0.660875,0.017896,-0.660875, + 0.452944,-0.767908,-0.452945,0.660875,0.017896,-0.660875, + 0.517064,-0.835523,-0.185868,0.706,0.016681,-0.5875, + 0.892994,-0.274252,-0.356859,0.722453,0.040123,-0.595141, + 0.199329,-0.959446,0.199329,0.638667,0.007537,-0.361333, + 0.452945,-0.767908,0.452945,0.660875,0.017896,-0.339125, + 0.517064,-0.835523,0.185868,0.706,0.016681,-0.4125, + 0.199329,-0.959446,0.199329,0.638667,0.007537,-0.361333, + 0.517064,-0.835523,0.185868,0.706,0.016681,-0.4125, + 0.18835,-0.976969,0.100277,0.664625,0.003052,-0.4175, + 0.452945,-0.767908,0.452945,0.660875,0.017896,-0.339125, + 0.663755,-0.344758,0.663755,0.674539,0.040427,-0.325461, + 0.892993,-0.274252,0.35686,0.722453,0.040123,-0.404859, + 0.892993,-0.274252,0.35686,0.722453,0.040123,-0.404859, + 0.517064,-0.835523,0.185868,0.706,0.016681,-0.4125, + 0.452945,-0.767908,0.452945,0.660875,0.017896,-0.339125, + 0.914719,-0.404091,0,0.738539,0.039819,-0.5, + 0.596646,-0.802505,0,0.7215,0.015465,-0.5, + 0.517064,-0.835523,0.185868,0.706,0.016681,-0.4125, + 0.914719,-0.404091,0,0.738539,0.039819,-0.5, + 0.517064,-0.835523,0.185868,0.706,0.016681,-0.4125, + 0.892993,-0.274252,0.35686,0.722453,0.040123,-0.404859, + 0.244558,-0.969635,0,0.677562,0.000839,-0.5, + 0.18835,-0.976969,0.100277,0.664625,0.003052,-0.4175, + 0.517064,-0.835523,0.185868,0.706,0.016681,-0.4125, + 0.244558,-0.969635,0,0.677562,0.000839,-0.5, + 0.517064,-0.835523,0.185868,0.706,0.016681,-0.4125, + 0.596646,-0.802505,0,0.7215,0.015465,-0.5, + 0.699155,0.149544,-0.699155,0.667578,0.132531,-0.667578, + 0.342523,0.135808,-0.929642,0.591406,0.132531,-0.713281, + 0.378454,0.107435,-0.919364,0.595062,0.077813,-0.721812, + 0.699155,0.149544,-0.699155,0.667578,0.132531,-0.667578, + 0.378454,0.107435,-0.919364,0.595062,0.077813,-0.721812, + 0.705578,0.065727,-0.705578,0.674281,0.077813,-0.674281, + 0.342523,0.135808,-0.929642,0.591406,0.132531,-0.713281, + 0,0.12379,-0.992308,0.5,0.132531,-0.728516, + 0,0.092789,-0.995686,0.5,0.077813,-0.737656, + 0,0.092789,-0.995686,0.5,0.077813,-0.737656, + 0.378454,0.107435,-0.919364,0.595062,0.077813,-0.721812, + 0.342523,0.135808,-0.929642,0.591406,0.132531,-0.713281, + 0,0.092789,-0.995686,0.5,0.077813,-0.737656, + 0,-0.404091,-0.914719,0.5,0.039819,-0.738539, + 0.356859,-0.274252,-0.892994,0.595141,0.040123,-0.722453, + 0.356859,-0.274252,-0.892994,0.595141,0.040123,-0.722453, + 0.378454,0.107435,-0.919364,0.595062,0.077813,-0.721812, + 0,0.092789,-0.995686,0.5,0.077813,-0.737656, + 0.356859,-0.274252,-0.892994,0.595141,0.040123,-0.722453, + 0.663755,-0.344758,-0.663755,0.674539,0.040427,-0.674539, + 0.705578,0.065727,-0.705578,0.674281,0.077813,-0.674281, + 0.705578,0.065727,-0.705578,0.674281,0.077813,-0.674281, + 0.378454,0.107435,-0.919364,0.595062,0.077813,-0.721812, + 0.356859,-0.274252,-0.892994,0.595141,0.040123,-0.722453, + -0.699155,0.149544,-0.699156,0.332422,0.132531,-0.667578, + -0.705578,0.065727,-0.705578,0.325719,0.077813,-0.674281, + -0.378454,0.107435,-0.919364,0.404938,0.077813,-0.721812, + -0.699155,0.149544,-0.699156,0.332422,0.132531,-0.667578, + -0.378454,0.107435,-0.919364,0.404938,0.077813,-0.721812, + -0.342523,0.135808,-0.929642,0.408594,0.132531,-0.713281, + -0.705578,0.065727,-0.705578,0.325719,0.077813,-0.674281, + -0.663755,-0.344758,-0.663755,0.325461,0.040427,-0.674539, + -0.35686,-0.274252,-0.892993,0.404859,0.040123,-0.722453, + -0.35686,-0.274252,-0.892993,0.404859,0.040123,-0.722453, + -0.378454,0.107435,-0.919364,0.404938,0.077813,-0.721812, + -0.705578,0.065727,-0.705578,0.325719,0.077813,-0.674281, + -0.35686,-0.274252,-0.892993,0.404859,0.040123,-0.722453, + 0,-0.404091,-0.914719,0.5,0.039819,-0.738539, + 0,0.092789,-0.995686,0.5,0.077813,-0.737656, + 0,0.092789,-0.995686,0.5,0.077813,-0.737656, + -0.378454,0.107435,-0.919364,0.404938,0.077813,-0.721812, + -0.35686,-0.274252,-0.892993,0.404859,0.040123,-0.722453, + 0,0.092789,-0.995686,0.5,0.077813,-0.737656, + 0,0.12379,-0.992308,0.5,0.132531,-0.728516, + -0.342523,0.135808,-0.929642,0.408594,0.132531,-0.713281, + -0.342523,0.135808,-0.929642,0.408594,0.132531,-0.713281, + -0.378454,0.107435,-0.919364,0.404938,0.077813,-0.721812, + 0,0.092789,-0.995686,0.5,0.077813,-0.737656, + -0.199329,-0.959446,-0.199329,0.361333,0.007537,-0.638667, + -0.100277,-0.976969,-0.18835,0.4175,0.003052,-0.664625, + -0.185868,-0.835523,-0.517064,0.4125,0.016681,-0.706, + -0.199329,-0.959446,-0.199329,0.361333,0.007537,-0.638667, + -0.185868,-0.835523,-0.517064,0.4125,0.016681,-0.706, + -0.452945,-0.767908,-0.452945,0.339125,0.017896,-0.660875, + 0,-0.969635,-0.244558,0.5,0.000839,-0.677562, + 0,-0.802505,-0.596646,0.5,0.015465,-0.7215, + -0.185868,-0.835523,-0.517064,0.4125,0.016681,-0.706, + 0,-0.969635,-0.244558,0.5,0.000839,-0.677562, + -0.185868,-0.835523,-0.517064,0.4125,0.016681,-0.706, + -0.100277,-0.976969,-0.18835,0.4175,0.003052,-0.664625, + 0,-0.404091,-0.914719,0.5,0.039819,-0.738539, + -0.35686,-0.274252,-0.892993,0.404859,0.040123,-0.722453, + -0.185868,-0.835523,-0.517064,0.4125,0.016681,-0.706, + 0,-0.404091,-0.914719,0.5,0.039819,-0.738539, + -0.185868,-0.835523,-0.517064,0.4125,0.016681,-0.706, + 0,-0.802505,-0.596646,0.5,0.015465,-0.7215, + -0.35686,-0.274252,-0.892993,0.404859,0.040123,-0.722453, + -0.663755,-0.344758,-0.663755,0.325461,0.040427,-0.674539, + -0.452945,-0.767908,-0.452945,0.339125,0.017896,-0.660875, + -0.452945,-0.767908,-0.452945,0.339125,0.017896,-0.660875, + -0.185868,-0.835523,-0.517064,0.4125,0.016681,-0.706, + -0.35686,-0.274252,-0.892993,0.404859,0.040123,-0.722453, + 0.199329,-0.959446,-0.199329,0.638667,0.007537,-0.638667, + 0.452944,-0.767908,-0.452945,0.660875,0.017896,-0.660875, + 0.185868,-0.835523,-0.517064,0.5875,0.016681,-0.706, + 0.199329,-0.959446,-0.199329,0.638667,0.007537,-0.638667, + 0.185868,-0.835523,-0.517064,0.5875,0.016681,-0.706, + 0.100277,-0.976969,-0.18835,0.5825,0.003052,-0.664625, + 0.452944,-0.767908,-0.452945,0.660875,0.017896,-0.660875, + 0.663755,-0.344758,-0.663755,0.674539,0.040427,-0.674539, + 0.356859,-0.274252,-0.892994,0.595141,0.040123,-0.722453, + 0.356859,-0.274252,-0.892994,0.595141,0.040123,-0.722453, + 0.185868,-0.835523,-0.517064,0.5875,0.016681,-0.706, + 0.452944,-0.767908,-0.452945,0.660875,0.017896,-0.660875, + 0,-0.404091,-0.914719,0.5,0.039819,-0.738539, + 0,-0.802505,-0.596646,0.5,0.015465,-0.7215, + 0.185868,-0.835523,-0.517064,0.5875,0.016681,-0.706, + 0,-0.404091,-0.914719,0.5,0.039819,-0.738539, + 0.185868,-0.835523,-0.517064,0.5875,0.016681,-0.706, + 0.356859,-0.274252,-0.892994,0.595141,0.040123,-0.722453, + 0,-0.969635,-0.244558,0.5,0.000839,-0.677562, + 0.100277,-0.976969,-0.18835,0.5825,0.003052,-0.664625, + 0.185868,-0.835523,-0.517064,0.5875,0.016681,-0.706, + 0,-0.969635,-0.244558,0.5,0.000839,-0.677562, + 0.185868,-0.835523,-0.517064,0.5875,0.016681,-0.706, + 0,-0.802505,-0.596646,0.5,0.015465,-0.7215, + -0.699155,0.149544,-0.699156,0.332422,0.132531,-0.667578, + -0.929642,0.135808,-0.342523,0.286719,0.132531,-0.591406, + -0.919364,0.107436,-0.378454,0.278187,0.077813,-0.595062, + -0.699155,0.149544,-0.699156,0.332422,0.132531,-0.667578, + -0.919364,0.107436,-0.378454,0.278187,0.077813,-0.595062, + -0.705578,0.065727,-0.705578,0.325719,0.077813,-0.674281, + -0.929642,0.135808,-0.342523,0.286719,0.132531,-0.591406, + -0.992308,0.12379,0,0.271484,0.132531,-0.5, + -0.995686,0.092789,0,0.262344,0.077813,-0.5, + -0.995686,0.092789,0,0.262344,0.077813,-0.5, + -0.919364,0.107436,-0.378454,0.278187,0.077813,-0.595062, + -0.929642,0.135808,-0.342523,0.286719,0.132531,-0.591406, + -0.995686,0.092789,0,0.262344,0.077813,-0.5, + -0.914719,-0.404091,0,0.261461,0.039819,-0.5, + -0.892993,-0.274251,-0.35686,0.277547,0.040123,-0.595141, + -0.892993,-0.274251,-0.35686,0.277547,0.040123,-0.595141, + -0.919364,0.107436,-0.378454,0.278187,0.077813,-0.595062, + -0.995686,0.092789,0,0.262344,0.077813,-0.5, + -0.892993,-0.274251,-0.35686,0.277547,0.040123,-0.595141, + -0.663755,-0.344758,-0.663755,0.325461,0.040427,-0.674539, + -0.705578,0.065727,-0.705578,0.325719,0.077813,-0.674281, + -0.705578,0.065727,-0.705578,0.325719,0.077813,-0.674281, + -0.919364,0.107436,-0.378454,0.278187,0.077813,-0.595062, + -0.892993,-0.274251,-0.35686,0.277547,0.040123,-0.595141, + -0.699155,0.149545,0.699155,0.332422,0.132531,-0.332422, + -0.705578,0.065726,0.705578,0.325719,0.077813,-0.325719, + -0.919364,0.107436,0.378454,0.278187,0.077813,-0.404938, + -0.699155,0.149545,0.699155,0.332422,0.132531,-0.332422, + -0.919364,0.107436,0.378454,0.278187,0.077813,-0.404938, + -0.929642,0.135808,0.342523,0.286719,0.132531,-0.408594, + -0.705578,0.065726,0.705578,0.325719,0.077813,-0.325719, + -0.663755,-0.344758,0.663755,0.325461,0.040427,-0.325461, + -0.892993,-0.274251,0.35686,0.277547,0.040123,-0.404859, + -0.892993,-0.274251,0.35686,0.277547,0.040123,-0.404859, + -0.919364,0.107436,0.378454,0.278187,0.077813,-0.404938, + -0.705578,0.065726,0.705578,0.325719,0.077813,-0.325719, + -0.892993,-0.274251,0.35686,0.277547,0.040123,-0.404859, + -0.914719,-0.404091,0,0.261461,0.039819,-0.5, + -0.995686,0.092789,0,0.262344,0.077813,-0.5, + -0.995686,0.092789,0,0.262344,0.077813,-0.5, + -0.919364,0.107436,0.378454,0.278187,0.077813,-0.404938, + -0.892993,-0.274251,0.35686,0.277547,0.040123,-0.404859, + -0.995686,0.092789,0,0.262344,0.077813,-0.5, + -0.992308,0.12379,0,0.271484,0.132531,-0.5, + -0.929642,0.135808,0.342523,0.286719,0.132531,-0.408594, + -0.929642,0.135808,0.342523,0.286719,0.132531,-0.408594, + -0.919364,0.107436,0.378454,0.278187,0.077813,-0.404938, + -0.995686,0.092789,0,0.262344,0.077813,-0.5, + -0.199328,-0.959446,0.199328,0.361333,0.007537,-0.361333, + -0.188349,-0.976969,0.100277,0.335375,0.003052,-0.4175, + -0.517064,-0.835523,0.185867,0.294,0.016681,-0.4125, + -0.199328,-0.959446,0.199328,0.361333,0.007537,-0.361333, + -0.517064,-0.835523,0.185867,0.294,0.016681,-0.4125, + -0.452945,-0.767908,0.452945,0.339125,0.017896,-0.339125, + -0.244558,-0.969635,0,0.322437,0.000839,-0.5, + -0.596646,-0.802505,0,0.2785,0.015465,-0.5, + -0.517064,-0.835523,0.185867,0.294,0.016681,-0.4125, + -0.244558,-0.969635,0,0.322437,0.000839,-0.5, + -0.517064,-0.835523,0.185867,0.294,0.016681,-0.4125, + -0.188349,-0.976969,0.100277,0.335375,0.003052,-0.4175, + -0.914719,-0.404091,0,0.261461,0.039819,-0.5, + -0.892993,-0.274251,0.35686,0.277547,0.040123,-0.404859, + -0.517064,-0.835523,0.185867,0.294,0.016681,-0.4125, + -0.914719,-0.404091,0,0.261461,0.039819,-0.5, + -0.517064,-0.835523,0.185867,0.294,0.016681,-0.4125, + -0.596646,-0.802505,0,0.2785,0.015465,-0.5, + -0.892993,-0.274251,0.35686,0.277547,0.040123,-0.404859, + -0.663755,-0.344758,0.663755,0.325461,0.040427,-0.325461, + -0.452945,-0.767908,0.452945,0.339125,0.017896,-0.339125, + -0.452945,-0.767908,0.452945,0.339125,0.017896,-0.339125, + -0.517064,-0.835523,0.185867,0.294,0.016681,-0.4125, + -0.892993,-0.274251,0.35686,0.277547,0.040123,-0.404859, + -0.199329,-0.959446,-0.199329,0.361333,0.007537,-0.638667, + -0.452945,-0.767908,-0.452945,0.339125,0.017896,-0.660875, + -0.517064,-0.835523,-0.185868,0.294,0.016681,-0.5875, + -0.199329,-0.959446,-0.199329,0.361333,0.007537,-0.638667, + -0.517064,-0.835523,-0.185868,0.294,0.016681,-0.5875, + -0.188349,-0.976969,-0.100277,0.335375,0.003052,-0.5825, + -0.452945,-0.767908,-0.452945,0.339125,0.017896,-0.660875, + -0.663755,-0.344758,-0.663755,0.325461,0.040427,-0.674539, + -0.892993,-0.274251,-0.35686,0.277547,0.040123,-0.595141, + -0.892993,-0.274251,-0.35686,0.277547,0.040123,-0.595141, + -0.517064,-0.835523,-0.185868,0.294,0.016681,-0.5875, + -0.452945,-0.767908,-0.452945,0.339125,0.017896,-0.660875, + -0.914719,-0.404091,0,0.261461,0.039819,-0.5, + -0.596646,-0.802505,0,0.2785,0.015465,-0.5, + -0.517064,-0.835523,-0.185868,0.294,0.016681,-0.5875, + -0.914719,-0.404091,0,0.261461,0.039819,-0.5, + -0.517064,-0.835523,-0.185868,0.294,0.016681,-0.5875, + -0.892993,-0.274251,-0.35686,0.277547,0.040123,-0.595141, + -0.244558,-0.969635,0,0.322437,0.000839,-0.5, + -0.188349,-0.976969,-0.100277,0.335375,0.003052,-0.5825, + -0.517064,-0.835523,-0.185868,0.294,0.016681,-0.5875, + -0.244558,-0.969635,0,0.322437,0.000839,-0.5, + -0.517064,-0.835523,-0.185868,0.294,0.016681,-0.5875, + -0.596646,-0.802505,0,0.2785,0.015465,-0.5, + -0.699155,0.149545,0.699155,0.332422,0.132531,-0.332422, + -0.342523,0.135808,0.929642,0.408594,0.132531,-0.286719, + -0.378454,0.107436,0.919364,0.404938,0.077813,-0.278187, + -0.699155,0.149545,0.699155,0.332422,0.132531,-0.332422, + -0.378454,0.107436,0.919364,0.404938,0.077813,-0.278187, + -0.705578,0.065726,0.705578,0.325719,0.077813,-0.325719, + -0.342523,0.135808,0.929642,0.408594,0.132531,-0.286719, + 0,0.12379,0.992308,0.5,0.132531,-0.271484, + 0,0.092789,0.995686,0.5,0.077813,-0.262344, + 0,0.092789,0.995686,0.5,0.077813,-0.262344, + -0.378454,0.107436,0.919364,0.404938,0.077813,-0.278187, + -0.342523,0.135808,0.929642,0.408594,0.132531,-0.286719, + 0,0.092789,0.995686,0.5,0.077813,-0.262344, + 0,-0.404091,0.914719,0.5,0.039819,-0.261461, + -0.35686,-0.274251,0.892993,0.404859,0.040123,-0.277547, + -0.35686,-0.274251,0.892993,0.404859,0.040123,-0.277547, + -0.378454,0.107436,0.919364,0.404938,0.077813,-0.278187, + 0,0.092789,0.995686,0.5,0.077813,-0.262344, + -0.35686,-0.274251,0.892993,0.404859,0.040123,-0.277547, + -0.663755,-0.344758,0.663755,0.325461,0.040427,-0.325461, + -0.705578,0.065726,0.705578,0.325719,0.077813,-0.325719, + -0.705578,0.065726,0.705578,0.325719,0.077813,-0.325719, + -0.378454,0.107436,0.919364,0.404938,0.077813,-0.278187, + -0.35686,-0.274251,0.892993,0.404859,0.040123,-0.277547, + 0.699156,0.149544,0.699155,0.667578,0.132531,-0.332422, + 0.705578,0.065727,0.705578,0.674281,0.077813,-0.325719, + 0.378454,0.107436,0.919364,0.595062,0.077813,-0.278187, + 0.699156,0.149544,0.699155,0.667578,0.132531,-0.332422, + 0.378454,0.107436,0.919364,0.595062,0.077813,-0.278187, + 0.342523,0.135808,0.929642,0.591406,0.132531,-0.286719, + 0.705578,0.065727,0.705578,0.674281,0.077813,-0.325719, + 0.663755,-0.344758,0.663755,0.674539,0.040427,-0.325461, + 0.35686,-0.274251,0.892993,0.595141,0.040123,-0.277547, + 0.35686,-0.274251,0.892993,0.595141,0.040123,-0.277547, + 0.378454,0.107436,0.919364,0.595062,0.077813,-0.278187, + 0.705578,0.065727,0.705578,0.674281,0.077813,-0.325719, + 0.35686,-0.274251,0.892993,0.595141,0.040123,-0.277547, + 0,-0.404091,0.914719,0.5,0.039819,-0.261461, + 0,0.092789,0.995686,0.5,0.077813,-0.262344, + 0,0.092789,0.995686,0.5,0.077813,-0.262344, + 0.378454,0.107436,0.919364,0.595062,0.077813,-0.278187, + 0.35686,-0.274251,0.892993,0.595141,0.040123,-0.277547, + 0,0.092789,0.995686,0.5,0.077813,-0.262344, + 0,0.12379,0.992308,0.5,0.132531,-0.271484, + 0.342523,0.135808,0.929642,0.591406,0.132531,-0.286719, + 0.342523,0.135808,0.929642,0.591406,0.132531,-0.286719, + 0.378454,0.107436,0.919364,0.595062,0.077813,-0.278187, + 0,0.092789,0.995686,0.5,0.077813,-0.262344, + 0.199329,-0.959446,0.199329,0.638667,0.007537,-0.361333, + 0.100277,-0.976969,0.188349,0.5825,0.003052,-0.335375, + 0.185868,-0.835523,0.517064,0.5875,0.016681,-0.294, + 0.199329,-0.959446,0.199329,0.638667,0.007537,-0.361333, + 0.185868,-0.835523,0.517064,0.5875,0.016681,-0.294, + 0.452945,-0.767908,0.452945,0.660875,0.017896,-0.339125, + 0,-0.969635,0.244558,0.5,0.000839,-0.322437, + 0,-0.802505,0.596646,0.5,0.015465,-0.2785, + 0.185868,-0.835523,0.517064,0.5875,0.016681,-0.294, + 0,-0.969635,0.244558,0.5,0.000839,-0.322437, + 0.185868,-0.835523,0.517064,0.5875,0.016681,-0.294, + 0.100277,-0.976969,0.188349,0.5825,0.003052,-0.335375, + 0,-0.404091,0.914719,0.5,0.039819,-0.261461, + 0.35686,-0.274251,0.892993,0.595141,0.040123,-0.277547, + 0.185868,-0.835523,0.517064,0.5875,0.016681,-0.294, + 0,-0.404091,0.914719,0.5,0.039819,-0.261461, + 0.185868,-0.835523,0.517064,0.5875,0.016681,-0.294, + 0,-0.802505,0.596646,0.5,0.015465,-0.2785, + 0.35686,-0.274251,0.892993,0.595141,0.040123,-0.277547, + 0.663755,-0.344758,0.663755,0.674539,0.040427,-0.325461, + 0.452945,-0.767908,0.452945,0.660875,0.017896,-0.339125, + 0.452945,-0.767908,0.452945,0.660875,0.017896,-0.339125, + 0.185868,-0.835523,0.517064,0.5875,0.016681,-0.294, + 0.35686,-0.274251,0.892993,0.595141,0.040123,-0.277547, + -0.199328,-0.959446,0.199328,0.361333,0.007537,-0.361333, + -0.452945,-0.767908,0.452945,0.339125,0.017896,-0.339125, + -0.185867,-0.835523,0.517064,0.4125,0.016681,-0.294, + -0.199328,-0.959446,0.199328,0.361333,0.007537,-0.361333, + -0.185867,-0.835523,0.517064,0.4125,0.016681,-0.294, + -0.100277,-0.976969,0.188349,0.4175,0.003052,-0.335375, + -0.452945,-0.767908,0.452945,0.339125,0.017896,-0.339125, + -0.663755,-0.344758,0.663755,0.325461,0.040427,-0.325461, + -0.35686,-0.274251,0.892993,0.404859,0.040123,-0.277547, + -0.35686,-0.274251,0.892993,0.404859,0.040123,-0.277547, + -0.185867,-0.835523,0.517064,0.4125,0.016681,-0.294, + -0.452945,-0.767908,0.452945,0.339125,0.017896,-0.339125, + 0,-0.404091,0.914719,0.5,0.039819,-0.261461, + 0,-0.802505,0.596646,0.5,0.015465,-0.2785, + -0.185867,-0.835523,0.517064,0.4125,0.016681,-0.294, + 0,-0.404091,0.914719,0.5,0.039819,-0.261461, + -0.185867,-0.835523,0.517064,0.4125,0.016681,-0.294, + -0.35686,-0.274251,0.892993,0.404859,0.040123,-0.277547, + 0,-0.969635,0.244558,0.5,0.000839,-0.322437, + -0.100277,-0.976969,0.188349,0.4175,0.003052,-0.335375, + -0.185867,-0.835523,0.517064,0.4125,0.016681,-0.294, + 0,-0.969635,0.244558,0.5,0.000839,-0.322437, + -0.185867,-0.835523,0.517064,0.4125,0.016681,-0.294, + 0,-0.802505,0.596646,0.5,0.015465,-0.2785, + 0.199329,-0.959446,-0.199329,0.638667,0.007537,-0.638667, + 0.100277,-0.976969,-0.18835,0.5825,0.003052,-0.664625, + 0.079739,-0.993621,-0.079739,0.5905,-0.005194,-0.5905, + 0.199329,-0.959446,-0.199329,0.638667,0.007537,-0.638667, + 0.079739,-0.993621,-0.079739,0.5905,-0.005194,-0.5905, + 0.18835,-0.976969,-0.100277,0.664625,0.003052,-0.5825, + 0.100277,-0.976969,-0.18835,0.5825,0.003052,-0.664625, + 0,-0.969635,-0.244558,0.5,0.000839,-0.677562, + 0,-0.996384,-0.08496,0.5,-0.007972,-0.59775, + 0,-0.996384,-0.08496,0.5,-0.007972,-0.59775, + 0.079739,-0.993621,-0.079739,0.5905,-0.005194,-0.5905, + 0.100277,-0.976969,-0.18835,0.5825,0.003052,-0.664625, + 0,-1,0,0.5,-0.010924,-0.5, + 0.08496,-0.996384,0,0.59775,-0.007972,-0.5, + 0.079739,-0.993621,-0.079739,0.5905,-0.005194,-0.5905, + 0,-1,0,0.5,-0.010924,-0.5, + 0.079739,-0.993621,-0.079739,0.5905,-0.005194,-0.5905, + 0,-0.996384,-0.08496,0.5,-0.007972,-0.59775, + 0.08496,-0.996384,0,0.59775,-0.007972,-0.5, + 0.244558,-0.969635,0,0.677562,0.000839,-0.5, + 0.18835,-0.976969,-0.100277,0.664625,0.003052,-0.5825, + 0.18835,-0.976969,-0.100277,0.664625,0.003052,-0.5825, + 0.079739,-0.993621,-0.079739,0.5905,-0.005194,-0.5905, + 0.08496,-0.996384,0,0.59775,-0.007972,-0.5, + -0.199329,-0.959446,-0.199329,0.361333,0.007537,-0.638667, + -0.188349,-0.976969,-0.100277,0.335375,0.003052,-0.5825, + -0.079739,-0.993621,-0.079739,0.4095,-0.005194,-0.5905, + -0.199329,-0.959446,-0.199329,0.361333,0.007537,-0.638667, + -0.079739,-0.993621,-0.079739,0.4095,-0.005194,-0.5905, + -0.100277,-0.976969,-0.18835,0.4175,0.003052,-0.664625, + -0.188349,-0.976969,-0.100277,0.335375,0.003052,-0.5825, + -0.244558,-0.969635,0,0.322437,0.000839,-0.5, + -0.08496,-0.996384,0,0.40225,-0.007972,-0.5, + -0.08496,-0.996384,0,0.40225,-0.007972,-0.5, + -0.079739,-0.993621,-0.079739,0.4095,-0.005194,-0.5905, + -0.188349,-0.976969,-0.100277,0.335375,0.003052,-0.5825, + 0,-1,0,0.5,-0.010924,-0.5, + 0,-0.996384,-0.08496,0.5,-0.007972,-0.59775, + -0.079739,-0.993621,-0.079739,0.4095,-0.005194,-0.5905, + 0,-1,0,0.5,-0.010924,-0.5, + -0.079739,-0.993621,-0.079739,0.4095,-0.005194,-0.5905, + -0.08496,-0.996384,0,0.40225,-0.007972,-0.5, + 0,-0.996384,-0.08496,0.5,-0.007972,-0.59775, + 0,-0.969635,-0.244558,0.5,0.000839,-0.677562, + -0.100277,-0.976969,-0.18835,0.4175,0.003052,-0.664625, + -0.100277,-0.976969,-0.18835,0.4175,0.003052,-0.664625, + -0.079739,-0.993621,-0.079739,0.4095,-0.005194,-0.5905, + 0,-0.996384,-0.08496,0.5,-0.007972,-0.59775, + -0.199328,-0.959446,0.199328,0.361333,0.007537,-0.361333, + -0.100277,-0.976969,0.188349,0.4175,0.003052,-0.335375, + -0.079739,-0.993621,0.079739,0.4095,-0.005194,-0.4095, + -0.199328,-0.959446,0.199328,0.361333,0.007537,-0.361333, + -0.079739,-0.993621,0.079739,0.4095,-0.005194,-0.4095, + -0.188349,-0.976969,0.100277,0.335375,0.003052,-0.4175, + -0.100277,-0.976969,0.188349,0.4175,0.003052,-0.335375, + 0,-0.969635,0.244558,0.5,0.000839,-0.322437, + 0,-0.996384,0.08496,0.5,-0.007972,-0.40225, + 0,-0.996384,0.08496,0.5,-0.007972,-0.40225, + -0.079739,-0.993621,0.079739,0.4095,-0.005194,-0.4095, + -0.100277,-0.976969,0.188349,0.4175,0.003052,-0.335375, + 0,-1,0,0.5,-0.010924,-0.5, + -0.08496,-0.996384,0,0.40225,-0.007972,-0.5, + -0.079739,-0.993621,0.079739,0.4095,-0.005194,-0.4095, + 0,-1,0,0.5,-0.010924,-0.5, + -0.079739,-0.993621,0.079739,0.4095,-0.005194,-0.4095, + 0,-0.996384,0.08496,0.5,-0.007972,-0.40225, + -0.08496,-0.996384,0,0.40225,-0.007972,-0.5, + -0.244558,-0.969635,0,0.322437,0.000839,-0.5, + -0.188349,-0.976969,0.100277,0.335375,0.003052,-0.4175, + -0.188349,-0.976969,0.100277,0.335375,0.003052,-0.4175, + -0.079739,-0.993621,0.079739,0.4095,-0.005194,-0.4095, + -0.08496,-0.996384,0,0.40225,-0.007972,-0.5, + 0.199329,-0.959446,0.199329,0.638667,0.007537,-0.361333, + 0.18835,-0.976969,0.100277,0.664625,0.003052,-0.4175, + 0.079739,-0.993621,0.079739,0.5905,-0.005194,-0.4095, + 0.199329,-0.959446,0.199329,0.638667,0.007537,-0.361333, + 0.079739,-0.993621,0.079739,0.5905,-0.005194,-0.4095, + 0.100277,-0.976969,0.188349,0.5825,0.003052,-0.335375, + 0.18835,-0.976969,0.100277,0.664625,0.003052,-0.4175, + 0.244558,-0.969635,0,0.677562,0.000839,-0.5, + 0.08496,-0.996384,0,0.59775,-0.007972,-0.5, + 0.08496,-0.996384,0,0.59775,-0.007972,-0.5, + 0.079739,-0.993621,0.079739,0.5905,-0.005194,-0.4095, + 0.18835,-0.976969,0.100277,0.664625,0.003052,-0.4175, + 0,-1,0,0.5,-0.010924,-0.5, + 0,-0.996384,0.08496,0.5,-0.007972,-0.40225, + 0.079739,-0.993621,0.079739,0.5905,-0.005194,-0.4095, + 0,-1,0,0.5,-0.010924,-0.5, + 0.079739,-0.993621,0.079739,0.5905,-0.005194,-0.4095, + 0.08496,-0.996384,0,0.59775,-0.007972,-0.5, + 0,-0.996384,0.08496,0.5,-0.007972,-0.40225, + 0,-0.969635,0.244558,0.5,0.000839,-0.322437, + 0.100277,-0.976969,0.188349,0.5825,0.003052,-0.335375, + 0.100277,-0.976969,0.188349,0.5825,0.003052,-0.335375, + 0.079739,-0.993621,0.079739,0.5905,-0.005194,-0.4095, + 0,-0.996384,0.08496,0.5,-0.007972,-0.40225, +}; +static const struct gllist frame={GL_N3F_V3F,GL_TRIANGLES,1728,data,NULL}; +const struct gllist *s1_1=&frame; diff --git a/hacks/glx/s1_2.c b/hacks/glx/s1_2.c new file mode 100644 index 00000000..5f494de6 --- /dev/null +++ b/hacks/glx/s1_2.c @@ -0,0 +1,1733 @@ +#include "gllist.h" +static const float data[]={ + 0.744225,-0.02143,-0.667585,0.865458,0.513412,-0.690781, + 0.945978,-0.110612,-0.304781,0.91525,0.49905,-0.604062, + 0.919806,-0.190639,-0.342948,0.925,0.532253,-0.600125, + 0.744225,-0.02143,-0.667585,0.865458,0.513412,-0.690781, + 0.919806,-0.190639,-0.342948,0.925,0.532253,-0.600125, + 0.749601,-0.05627,-0.659493,0.877427,0.54752,-0.683563, + 0.980435,-0.196846,0,0.931847,0.494263,-0.5, + 0.981457,-0.191681,0,0.940858,0.527164,-0.5, + 0.919806,-0.190639,-0.342948,0.925,0.532253,-0.600125, + 0.980435,-0.196846,0,0.931847,0.494263,-0.5, + 0.919806,-0.190639,-0.342948,0.925,0.532253,-0.600125, + 0.945978,-0.110612,-0.304781,0.91525,0.49905,-0.604062, + 0.981457,-0.191681,0,0.940858,0.527164,-0.5, + 0.973132,0.23025,0,0.945338,0.554869,-0.5, + 0.932108,0.142863,-0.332815,0.92981,0.559801,-0.596406, + 0.932108,0.142863,-0.332815,0.92981,0.559801,-0.596406, + 0.919806,-0.190639,-0.342948,0.925,0.532253,-0.600125, + 0.981457,-0.191681,0,0.940858,0.527164,-0.5, + 0.932108,0.142863,-0.332815,0.92981,0.559801,-0.596406, + 0.692376,0.299844,-0.656284,0.88375,0.575062,-0.676859, + 0.749601,-0.05627,-0.659493,0.877427,0.54752,-0.683563, + 0.749601,-0.05627,-0.659493,0.877427,0.54752,-0.683563, + 0.919806,-0.190639,-0.342948,0.925,0.532253,-0.600125, + 0.932108,0.142863,-0.332815,0.92981,0.559801,-0.596406, + 0.744225,-0.02143,0.667585,0.865458,0.513412,-0.309219, + 0.749602,-0.05627,0.659493,0.877427,0.54752,-0.316437, + 0.919806,-0.190639,0.342948,0.925,0.532253,-0.399875, + 0.744225,-0.02143,0.667585,0.865458,0.513412,-0.309219, + 0.919806,-0.190639,0.342948,0.925,0.532253,-0.399875, + 0.945978,-0.110612,0.304781,0.91525,0.49905,-0.395938, + 0.749602,-0.05627,0.659493,0.877427,0.54752,-0.316437, + 0.692376,0.299843,0.656284,0.88375,0.575062,-0.323141, + 0.932108,0.142863,0.332815,0.92981,0.559801,-0.403594, + 0.932108,0.142863,0.332815,0.92981,0.559801,-0.403594, + 0.919806,-0.190639,0.342948,0.925,0.532253,-0.399875, + 0.749602,-0.05627,0.659493,0.877427,0.54752,-0.316437, + 0.932108,0.142863,0.332815,0.92981,0.559801,-0.403594, + 0.973132,0.23025,0,0.945338,0.554869,-0.5, + 0.981457,-0.191681,0,0.940858,0.527164,-0.5, + 0.981457,-0.191681,0,0.940858,0.527164,-0.5, + 0.919806,-0.190639,0.342948,0.925,0.532253,-0.399875, + 0.932108,0.142863,0.332815,0.92981,0.559801,-0.403594, + 0.980435,-0.196846,0,0.931847,0.494263,-0.5, + 0.945978,-0.110612,0.304781,0.91525,0.49905,-0.395938, + 0.919806,-0.190639,0.342948,0.925,0.532253,-0.399875, + 0.980435,-0.196846,0,0.931847,0.494263,-0.5, + 0.919806,-0.190639,0.342948,0.925,0.532253,-0.399875, + 0.981457,-0.191681,0,0.940858,0.527164,-0.5, + 0.503147,0.845347,0.179535,0.858509,0.615264,-0.361333, + 0.496158,0.862422,0.100278,0.884513,0.611054,-0.4175, + 0.729041,0.662418,0.172342,0.919197,0.584697,-0.4125, + 0.503147,0.845347,0.179535,0.858509,0.615264,-0.361333, + 0.729041,0.662418,0.172342,0.919197,0.584697,-0.4125, + 0.634483,0.691277,0.345786,0.876135,0.59824,-0.339125, + 0.546916,0.837188,0,0.897467,0.608935,-0.5, + 0.788799,0.614652,0,0.934249,0.5808,-0.5, + 0.729041,0.662418,0.172342,0.919197,0.584697,-0.4125, + 0.546916,0.837188,0,0.897467,0.608935,-0.5, + 0.729041,0.662418,0.172342,0.919197,0.584697,-0.4125, + 0.496158,0.862422,0.100278,0.884513,0.611054,-0.4175, + 0.973132,0.23025,0,0.945338,0.554869,-0.5, + 0.932108,0.142863,0.332815,0.92981,0.559801,-0.403594, + 0.729041,0.662418,0.172342,0.919197,0.584697,-0.4125, + 0.973132,0.23025,0,0.945338,0.554869,-0.5, + 0.729041,0.662418,0.172342,0.919197,0.584697,-0.4125, + 0.788799,0.614652,0,0.934249,0.5808,-0.5, + 0.932108,0.142863,0.332815,0.92981,0.559801,-0.403594, + 0.692376,0.299843,0.656284,0.88375,0.575062,-0.323141, + 0.634483,0.691277,0.345786,0.876135,0.59824,-0.339125, + 0.634483,0.691277,0.345786,0.876135,0.59824,-0.339125, + 0.729041,0.662418,0.172342,0.919197,0.584697,-0.4125, + 0.932108,0.142863,0.332815,0.92981,0.559801,-0.403594, + 0.503147,0.845347,-0.179534,0.858509,0.615264,-0.638667, + 0.634482,0.691277,-0.345786,0.876135,0.59824,-0.660875, + 0.729041,0.662418,-0.172342,0.919197,0.584697,-0.5875, + 0.503147,0.845347,-0.179534,0.858509,0.615264,-0.638667, + 0.729041,0.662418,-0.172342,0.919197,0.584697,-0.5875, + 0.496158,0.862422,-0.100277,0.884513,0.611054,-0.5825, + 0.634482,0.691277,-0.345786,0.876135,0.59824,-0.660875, + 0.692376,0.299844,-0.656284,0.88375,0.575062,-0.676859, + 0.932108,0.142863,-0.332815,0.92981,0.559801,-0.596406, + 0.932108,0.142863,-0.332815,0.92981,0.559801,-0.596406, + 0.729041,0.662418,-0.172342,0.919197,0.584697,-0.5875, + 0.634482,0.691277,-0.345786,0.876135,0.59824,-0.660875, + 0.973132,0.23025,0,0.945338,0.554869,-0.5, + 0.788799,0.614652,0,0.934249,0.5808,-0.5, + 0.729041,0.662418,-0.172342,0.919197,0.584697,-0.5875, + 0.973132,0.23025,0,0.945338,0.554869,-0.5, + 0.729041,0.662418,-0.172342,0.919197,0.584697,-0.5875, + 0.932108,0.142863,-0.332815,0.92981,0.559801,-0.596406, + 0.546916,0.837188,0,0.897467,0.608935,-0.5, + 0.496158,0.862422,-0.100277,0.884513,0.611054,-0.5825, + 0.729041,0.662418,-0.172342,0.919197,0.584697,-0.5875, + 0.546916,0.837188,0,0.897467,0.608935,-0.5, + 0.729041,0.662418,-0.172342,0.919197,0.584697,-0.5875, + 0.788799,0.614652,0,0.934249,0.5808,-0.5, + 0.744225,-0.02143,0.667585,0.865458,0.513412,-0.309219, + 0.395884,0.173928,0.901679,0.782472,0.537348,-0.257187, + 0.413121,0.093331,0.905881,0.798138,0.572966,-0.266375, + 0.744225,-0.02143,0.667585,0.865458,0.513412,-0.309219, + 0.413121,0.093331,0.905881,0.798138,0.572966,-0.266375, + 0.749602,-0.05627,0.659493,0.877427,0.54752,-0.316437, + 0.395884,0.173928,0.901679,0.782472,0.537348,-0.257187, + 0.088734,0.313595,0.945402,0.682889,0.566071,-0.239844, + 0.075758,0.234707,0.96911,0.702992,0.603501,-0.249687, + 0.075758,0.234707,0.96911,0.702992,0.603501,-0.249687, + 0.413121,0.093331,0.905881,0.798138,0.572966,-0.266375, + 0.395884,0.173928,0.901679,0.782472,0.537348,-0.257187, + 0.190084,0.486023,0.853024,0.716506,0.632271,-0.258297, + 0.446948,0.373871,0.812686,0.80768,0.601112,-0.274594, + 0.413121,0.093331,0.905881,0.798138,0.572966,-0.266375, + 0.190084,0.486023,0.853024,0.716506,0.632271,-0.258297, + 0.413121,0.093331,0.905881,0.798138,0.572966,-0.266375, + 0.075758,0.234707,0.96911,0.702992,0.603501,-0.249687, + 0.692376,0.299843,0.656284,0.88375,0.575062,-0.323141, + 0.749602,-0.05627,0.659493,0.877427,0.54752,-0.316437, + 0.413121,0.093331,0.905881,0.798138,0.572966,-0.266375, + 0.692376,0.299843,0.656284,0.88375,0.575062,-0.323141, + 0.413121,0.093331,0.905881,0.798138,0.572966,-0.266375, + 0.446948,0.373871,0.812686,0.80768,0.601112,-0.274594, + -0.208655,0.445101,0.870832,0.583305,0.594795,-0.257187, + -0.468298,0.578298,0.668033,0.500319,0.618731,-0.309219, + -0.541739,0.509206,0.668752,0.528557,0.659482,-0.316437, + -0.541739,0.509206,0.668752,0.528557,0.659482,-0.316437, + -0.227561,0.374378,0.89892,0.607846,0.634036,-0.266375, + -0.208655,0.445101,0.870832,0.583305,0.594795,-0.257187, + -0.424048,0.688165,0.588737,0.548866,0.688331,-0.323141, + -0.109115,0.586342,0.802681,0.625134,0.662855,-0.274594, + -0.227561,0.374378,0.89892,0.607846,0.634036,-0.266375, + -0.424048,0.688165,0.588737,0.548866,0.688331,-0.323141, + -0.227561,0.374378,0.89892,0.607846,0.634036,-0.266375, + -0.541739,0.509206,0.668752,0.528557,0.659482,-0.316437, + -0.109115,0.586342,0.802681,0.625134,0.662855,-0.274594, + 0.190084,0.486023,0.853024,0.716506,0.632271,-0.258297, + 0.075758,0.234707,0.96911,0.702992,0.603501,-0.249687, + 0.075758,0.234707,0.96911,0.702992,0.603501,-0.249687, + -0.227561,0.374378,0.89892,0.607846,0.634036,-0.266375, + -0.109115,0.586342,0.802681,0.625134,0.662855,-0.274594, + 0.088734,0.313595,0.945402,0.682889,0.566071,-0.239844, + -0.208655,0.445101,0.870832,0.583305,0.594795,-0.257187, + -0.227561,0.374378,0.89892,0.607846,0.634036,-0.266375, + 0.088734,0.313595,0.945402,0.682889,0.566071,-0.239844, + -0.227561,0.374378,0.89892,0.607846,0.634036,-0.266375, + 0.075758,0.234707,0.96911,0.702992,0.603501,-0.249687, + 0.123897,0.972069,0.199329,0.596285,0.705555,-0.361333, + 0.226858,0.951027,0.209959,0.650852,0.69151,-0.335375, + 0.096538,0.86115,0.4991,0.641688,0.680252,-0.294, + 0.123897,0.972069,0.199329,0.596285,0.705555,-0.361333, + 0.096538,0.86115,0.4991,0.641688,0.680252,-0.294, + -0.070158,0.909054,0.410729,0.571915,0.702991,-0.339125, + 0.226858,0.951027,0.209959,0.650852,0.69151,-0.335375, + 0.329457,0.915147,0.232303,0.729578,0.666743,-0.322437, + 0.2681,0.82446,0.498385,0.724816,0.652913,-0.2785, + 0.2681,0.82446,0.498385,0.724816,0.652913,-0.2785, + 0.096538,0.86115,0.4991,0.641688,0.680252,-0.294, + 0.226858,0.951027,0.209959,0.650852,0.69151,-0.335375, + 0.190084,0.486023,0.853024,0.716506,0.632271,-0.258297, + -0.109115,0.586342,0.802681,0.625134,0.662855,-0.274594, + 0.096538,0.86115,0.4991,0.641688,0.680252,-0.294, + 0.190084,0.486023,0.853024,0.716506,0.632271,-0.258297, + 0.096538,0.86115,0.4991,0.641688,0.680252,-0.294, + 0.2681,0.82446,0.498385,0.724816,0.652913,-0.2785, + -0.109115,0.586342,0.802681,0.625134,0.662855,-0.274594, + -0.424048,0.688165,0.588737,0.548866,0.688331,-0.323141, + -0.070158,0.909054,0.410729,0.571915,0.702991,-0.339125, + -0.070158,0.909054,0.410729,0.571915,0.702991,-0.339125, + 0.096538,0.86115,0.4991,0.641688,0.680252,-0.294, + -0.109115,0.586342,0.802681,0.625134,0.662855,-0.274594, + 0.423992,0.883446,0.199385,0.806863,0.637791,-0.335375, + 0.503147,0.845347,0.179535,0.858509,0.615264,-0.361333, + 0.634483,0.691277,0.345786,0.876135,0.59824,-0.339125, + 0.634483,0.691277,0.345786,0.876135,0.59824,-0.339125, + 0.454725,0.723574,0.519294,0.807153,0.623277,-0.294, + 0.423992,0.883446,0.199385,0.806863,0.637791,-0.335375, + 0.692376,0.299843,0.656284,0.88375,0.575062,-0.323141, + 0.446948,0.373871,0.812686,0.80768,0.601112,-0.274594, + 0.454725,0.723574,0.519294,0.807153,0.623277,-0.294, + 0.692376,0.299843,0.656284,0.88375,0.575062,-0.323141, + 0.454725,0.723574,0.519294,0.807153,0.623277,-0.294, + 0.634483,0.691277,0.345786,0.876135,0.59824,-0.339125, + 0.190084,0.486023,0.853024,0.716506,0.632271,-0.258297, + 0.2681,0.82446,0.498385,0.724816,0.652913,-0.2785, + 0.454725,0.723574,0.519294,0.807153,0.623277,-0.294, + 0.190084,0.486023,0.853024,0.716506,0.632271,-0.258297, + 0.454725,0.723574,0.519294,0.807153,0.623277,-0.294, + 0.446948,0.373871,0.812686,0.80768,0.601112,-0.274594, + 0.329457,0.915147,0.232303,0.729578,0.666743,-0.322437, + 0.423992,0.883446,0.199385,0.806863,0.637791,-0.335375, + 0.454725,0.723574,0.519294,0.807153,0.623277,-0.294, + 0.329457,0.915147,0.232303,0.729578,0.666743,-0.322437, + 0.454725,0.723574,0.519294,0.807153,0.623277,-0.294, + 0.2681,0.82446,0.498385,0.724816,0.652913,-0.2785, + -0.541739,0.509206,0.668752,0.528557,0.659482,-0.316437, + -0.468298,0.578298,0.668033,0.500319,0.618731,-0.309219, + -0.677265,0.639604,0.363619,0.450527,0.633092,-0.395938, + -0.677265,0.639604,0.363619,0.450527,0.633092,-0.395938, + -0.740712,0.587497,0.325872,0.480984,0.67475,-0.399875, + -0.541739,0.509206,0.668752,0.528557,0.659482,-0.316437, + -0.749144,0.662408,0,0.43393,0.63788,-0.5, + -0.797112,0.603831,0,0.465127,0.679839,-0.5, + -0.740712,0.587497,0.325872,0.480984,0.67475,-0.399875, + -0.749144,0.662408,0,0.43393,0.63788,-0.5, + -0.740712,0.587497,0.325872,0.480984,0.67475,-0.399875, + -0.677265,0.639604,0.363619,0.450527,0.633092,-0.395938, + -0.797112,0.603831,0,0.465127,0.679839,-0.5, + -0.655082,0.755558,0,0.487673,0.709673,-0.5, + -0.606207,0.755737,0.247737,0.503003,0.704166,-0.403594, + -0.606207,0.755737,0.247737,0.503003,0.704166,-0.403594, + -0.740712,0.587497,0.325872,0.480984,0.67475,-0.399875, + -0.797112,0.603831,0,0.465127,0.679839,-0.5, + -0.424048,0.688165,0.588737,0.548866,0.688331,-0.323141, + -0.541739,0.509206,0.668752,0.528557,0.659482,-0.316437, + -0.740712,0.587497,0.325872,0.480984,0.67475,-0.399875, + -0.424048,0.688165,0.588737,0.548866,0.688331,-0.323141, + -0.740712,0.587497,0.325872,0.480984,0.67475,-0.399875, + -0.606207,0.755737,0.247737,0.503003,0.704166,-0.403594, + -0.677265,0.639604,-0.363619,0.450527,0.633092,-0.604062, + -0.468298,0.578298,-0.668033,0.500319,0.618731,-0.690781, + -0.541738,0.509206,-0.668752,0.528557,0.659482,-0.683563, + -0.541738,0.509206,-0.668752,0.528557,0.659482,-0.683563, + -0.740713,0.587497,-0.325872,0.480984,0.67475,-0.600125, + -0.677265,0.639604,-0.363619,0.450527,0.633092,-0.604062, + -0.424048,0.688166,-0.588737,0.548866,0.688331,-0.676859, + -0.606207,0.755737,-0.247737,0.503003,0.704166,-0.596406, + -0.740713,0.587497,-0.325872,0.480984,0.67475,-0.600125, + -0.424048,0.688166,-0.588737,0.548866,0.688331,-0.676859, + -0.740713,0.587497,-0.325872,0.480984,0.67475,-0.600125, + -0.541738,0.509206,-0.668752,0.528557,0.659482,-0.683563, + -0.606207,0.755737,-0.247737,0.503003,0.704166,-0.596406, + -0.655082,0.755558,0,0.487673,0.709673,-0.5, + -0.797112,0.603831,0,0.465127,0.679839,-0.5, + -0.797112,0.603831,0,0.465127,0.679839,-0.5, + -0.740713,0.587497,-0.325872,0.480984,0.67475,-0.600125, + -0.606207,0.755737,-0.247737,0.503003,0.704166,-0.596406, + -0.749144,0.662408,0,0.43393,0.63788,-0.5, + -0.677265,0.639604,-0.363619,0.450527,0.633092,-0.604062, + -0.740713,0.587497,-0.325872,0.480984,0.67475,-0.600125, + -0.749144,0.662408,0,0.43393,0.63788,-0.5, + -0.740713,0.587497,-0.325872,0.480984,0.67475,-0.600125, + -0.797112,0.603831,0,0.465127,0.679839,-0.5, + 0.123896,0.972069,-0.199329,0.596285,0.705555,-0.638667, + 0.139983,0.985063,-0.100277,0.573201,0.718247,-0.5825, + -0.142867,0.968199,-0.205377,0.529644,0.718831,-0.5875, + 0.123896,0.972069,-0.199329,0.596285,0.705555,-0.638667, + -0.142867,0.968199,-0.205377,0.529644,0.718831,-0.5875, + -0.070159,0.909054,-0.410729,0.571915,0.702991,-0.660875, + 0.084449,0.996428,0,0.561689,0.724552,-0.5, + -0.31505,0.949075,0,0.515384,0.725027,-0.5, + -0.142867,0.968199,-0.205377,0.529644,0.718831,-0.5875, + 0.084449,0.996428,0,0.561689,0.724552,-0.5, + -0.142867,0.968199,-0.205377,0.529644,0.718831,-0.5875, + 0.139983,0.985063,-0.100277,0.573201,0.718247,-0.5825, + -0.31505,0.949075,0,0.515384,0.725027,-0.5, + -0.655082,0.755558,0,0.487673,0.709673,-0.5, + -0.606207,0.755737,-0.247737,0.503003,0.704166,-0.596406, + -0.606207,0.755737,-0.247737,0.503003,0.704166,-0.596406, + -0.142867,0.968199,-0.205377,0.529644,0.718831,-0.5875, + -0.31505,0.949075,0,0.515384,0.725027,-0.5, + -0.424048,0.688166,-0.588737,0.548866,0.688331,-0.676859, + -0.070159,0.909054,-0.410729,0.571915,0.702991,-0.660875, + -0.142867,0.968199,-0.205377,0.529644,0.718831,-0.5875, + -0.424048,0.688166,-0.588737,0.548866,0.688331,-0.676859, + -0.142867,0.968199,-0.205377,0.529644,0.718831,-0.5875, + -0.606207,0.755737,-0.247737,0.503003,0.704166,-0.596406, + 0.123897,0.972069,0.199329,0.596285,0.705555,-0.361333, + -0.070158,0.909054,0.410729,0.571915,0.702991,-0.339125, + -0.142867,0.968199,0.205377,0.529644,0.718831,-0.4125, + 0.123897,0.972069,0.199329,0.596285,0.705555,-0.361333, + -0.142867,0.968199,0.205377,0.529644,0.718831,-0.4125, + 0.139983,0.985063,0.100277,0.573201,0.718247,-0.4175, + -0.424048,0.688165,0.588737,0.548866,0.688331,-0.323141, + -0.606207,0.755737,0.247737,0.503003,0.704166,-0.403594, + -0.142867,0.968199,0.205377,0.529644,0.718831,-0.4125, + -0.424048,0.688165,0.588737,0.548866,0.688331,-0.323141, + -0.142867,0.968199,0.205377,0.529644,0.718831,-0.4125, + -0.070158,0.909054,0.410729,0.571915,0.702991,-0.339125, + -0.606207,0.755737,0.247737,0.503003,0.704166,-0.403594, + -0.655082,0.755558,0,0.487673,0.709673,-0.5, + -0.31505,0.949075,0,0.515384,0.725027,-0.5, + -0.31505,0.949075,0,0.515384,0.725027,-0.5, + -0.142867,0.968199,0.205377,0.529644,0.718831,-0.4125, + -0.606207,0.755737,0.247737,0.503003,0.704166,-0.403594, + 0.084449,0.996428,0,0.561689,0.724552,-0.5, + 0.139983,0.985063,0.100277,0.573201,0.718247,-0.4175, + -0.142867,0.968199,0.205377,0.529644,0.718831,-0.4125, + 0.084449,0.996428,0,0.561689,0.724552,-0.5, + -0.142867,0.968199,0.205377,0.529644,0.718831,-0.4125, + -0.31505,0.949075,0,0.515384,0.725027,-0.5, + -0.541738,0.509206,-0.668752,0.528557,0.659482,-0.683563, + -0.468298,0.578298,-0.668033,0.500319,0.618731,-0.690781, + -0.208655,0.445101,-0.870832,0.583305,0.594795,-0.742813, + -0.208655,0.445101,-0.870832,0.583305,0.594795,-0.742813, + -0.227561,0.374378,-0.89892,0.607846,0.634036,-0.733625, + -0.541738,0.509206,-0.668752,0.528557,0.659482,-0.683563, + 0.088733,0.313595,-0.945402,0.682889,0.566071,-0.760156, + 0.075758,0.234708,-0.969109,0.702992,0.603501,-0.750313, + -0.227561,0.374378,-0.89892,0.607846,0.634036,-0.733625, + 0.088733,0.313595,-0.945402,0.682889,0.566071,-0.760156, + -0.227561,0.374378,-0.89892,0.607846,0.634036,-0.733625, + -0.208655,0.445101,-0.870832,0.583305,0.594795,-0.742813, + 0.075758,0.234708,-0.969109,0.702992,0.603501,-0.750313, + 0.190084,0.486023,-0.853024,0.716506,0.632271,-0.741703, + -0.109115,0.586342,-0.802681,0.625134,0.662855,-0.725406, + -0.109115,0.586342,-0.802681,0.625134,0.662855,-0.725406, + -0.227561,0.374378,-0.89892,0.607846,0.634036,-0.733625, + 0.075758,0.234708,-0.969109,0.702992,0.603501,-0.750313, + -0.424048,0.688166,-0.588737,0.548866,0.688331,-0.676859, + -0.541738,0.509206,-0.668752,0.528557,0.659482,-0.683563, + -0.227561,0.374378,-0.89892,0.607846,0.634036,-0.733625, + -0.424048,0.688166,-0.588737,0.548866,0.688331,-0.676859, + -0.227561,0.374378,-0.89892,0.607846,0.634036,-0.733625, + -0.109115,0.586342,-0.802681,0.625134,0.662855,-0.725406, + 0.744225,-0.02143,-0.667585,0.865458,0.513412,-0.690781, + 0.749601,-0.05627,-0.659493,0.877427,0.54752,-0.683563, + 0.41312,0.093332,-0.905881,0.798138,0.572966,-0.733625, + 0.744225,-0.02143,-0.667585,0.865458,0.513412,-0.690781, + 0.41312,0.093332,-0.905881,0.798138,0.572966,-0.733625, + 0.395884,0.173928,-0.901679,0.782472,0.537348,-0.742813, + 0.692376,0.299844,-0.656284,0.88375,0.575062,-0.676859, + 0.446948,0.373871,-0.812686,0.80768,0.601112,-0.725406, + 0.41312,0.093332,-0.905881,0.798138,0.572966,-0.733625, + 0.692376,0.299844,-0.656284,0.88375,0.575062,-0.676859, + 0.41312,0.093332,-0.905881,0.798138,0.572966,-0.733625, + 0.749601,-0.05627,-0.659493,0.877427,0.54752,-0.683563, + 0.190084,0.486023,-0.853024,0.716506,0.632271,-0.741703, + 0.075758,0.234708,-0.969109,0.702992,0.603501,-0.750313, + 0.41312,0.093332,-0.905881,0.798138,0.572966,-0.733625, + 0.190084,0.486023,-0.853024,0.716506,0.632271,-0.741703, + 0.41312,0.093332,-0.905881,0.798138,0.572966,-0.733625, + 0.446948,0.373871,-0.812686,0.80768,0.601112,-0.725406, + 0.075758,0.234708,-0.969109,0.702992,0.603501,-0.750313, + 0.088733,0.313595,-0.945402,0.682889,0.566071,-0.760156, + 0.395884,0.173928,-0.901679,0.782472,0.537348,-0.742813, + 0.395884,0.173928,-0.901679,0.782472,0.537348,-0.742813, + 0.41312,0.093332,-0.905881,0.798138,0.572966,-0.733625, + 0.075758,0.234708,-0.969109,0.702992,0.603501,-0.750313, + 0.634482,0.691277,-0.345786,0.876135,0.59824,-0.660875, + 0.503147,0.845347,-0.179534,0.858509,0.615264,-0.638667, + 0.423992,0.883446,-0.199386,0.806863,0.637791,-0.664625, + 0.423992,0.883446,-0.199386,0.806863,0.637791,-0.664625, + 0.454725,0.723574,-0.519294,0.807153,0.623277,-0.706, + 0.634482,0.691277,-0.345786,0.876135,0.59824,-0.660875, + 0.329457,0.915147,-0.232303,0.729578,0.666743,-0.677562, + 0.2681,0.82446,-0.498385,0.724816,0.652913,-0.7215, + 0.454725,0.723574,-0.519294,0.807153,0.623277,-0.706, + 0.329457,0.915147,-0.232303,0.729578,0.666743,-0.677562, + 0.454725,0.723574,-0.519294,0.807153,0.623277,-0.706, + 0.423992,0.883446,-0.199386,0.806863,0.637791,-0.664625, + 0.190084,0.486023,-0.853024,0.716506,0.632271,-0.741703, + 0.446948,0.373871,-0.812686,0.80768,0.601112,-0.725406, + 0.454725,0.723574,-0.519294,0.807153,0.623277,-0.706, + 0.190084,0.486023,-0.853024,0.716506,0.632271,-0.741703, + 0.454725,0.723574,-0.519294,0.807153,0.623277,-0.706, + 0.2681,0.82446,-0.498385,0.724816,0.652913,-0.7215, + 0.692376,0.299844,-0.656284,0.88375,0.575062,-0.676859, + 0.634482,0.691277,-0.345786,0.876135,0.59824,-0.660875, + 0.454725,0.723574,-0.519294,0.807153,0.623277,-0.706, + 0.692376,0.299844,-0.656284,0.88375,0.575062,-0.676859, + 0.454725,0.723574,-0.519294,0.807153,0.623277,-0.706, + 0.446948,0.373871,-0.812686,0.80768,0.601112,-0.725406, + 0.123896,0.972069,-0.199329,0.596285,0.705555,-0.638667, + -0.070159,0.909054,-0.410729,0.571915,0.702991,-0.660875, + 0.096538,0.86115,-0.4991,0.641688,0.680252,-0.706, + 0.123896,0.972069,-0.199329,0.596285,0.705555,-0.638667, + 0.096538,0.86115,-0.4991,0.641688,0.680252,-0.706, + 0.226858,0.951027,-0.209959,0.650852,0.69151,-0.664625, + -0.070159,0.909054,-0.410729,0.571915,0.702991,-0.660875, + -0.424048,0.688166,-0.588737,0.548866,0.688331,-0.676859, + -0.109115,0.586342,-0.802681,0.625134,0.662855,-0.725406, + -0.109115,0.586342,-0.802681,0.625134,0.662855,-0.725406, + 0.096538,0.86115,-0.4991,0.641688,0.680252,-0.706, + -0.070159,0.909054,-0.410729,0.571915,0.702991,-0.660875, + 0.190084,0.486023,-0.853024,0.716506,0.632271,-0.741703, + 0.2681,0.82446,-0.498385,0.724816,0.652913,-0.7215, + 0.096538,0.86115,-0.4991,0.641688,0.680252,-0.706, + 0.190084,0.486023,-0.853024,0.716506,0.632271,-0.741703, + 0.096538,0.86115,-0.4991,0.641688,0.680252,-0.706, + -0.109115,0.586342,-0.802681,0.625134,0.662855,-0.725406, + 0.2681,0.82446,-0.498385,0.724816,0.652913,-0.7215, + 0.329457,0.915147,-0.232303,0.729578,0.666743,-0.677562, + 0.226858,0.951027,-0.209959,0.650852,0.69151,-0.664625, + 0.226858,0.951027,-0.209959,0.650852,0.69151,-0.664625, + 0.096538,0.86115,-0.4991,0.641688,0.680252,-0.706, + 0.2681,0.82446,-0.498385,0.724816,0.652913,-0.7215, + 0.503147,0.845347,0.179535,0.858509,0.615264,-0.361333, + 0.423992,0.883446,0.199385,0.806863,0.637791,-0.335375, + 0.398886,0.913527,0.079739,0.817112,0.642984,-0.4095, + 0.503147,0.845347,0.179535,0.858509,0.615264,-0.361333, + 0.398886,0.913527,0.079739,0.817112,0.642984,-0.4095, + 0.496158,0.862422,0.100278,0.884513,0.611054,-0.4175, + 0.423992,0.883446,0.199385,0.806863,0.637791,-0.335375, + 0.329457,0.915147,0.232303,0.729578,0.666743,-0.322437, + 0.324391,0.9421,0.08496,0.732447,0.675074,-0.40225, + 0.324391,0.9421,0.08496,0.732447,0.675074,-0.40225, + 0.398886,0.913527,0.079739,0.817112,0.642984,-0.4095, + 0.423992,0.883446,0.199385,0.806863,0.637791,-0.335375, + 0.325568,0.945519,0,0.733407,0.677865,-0.5, + 0.404722,0.91444,0,0.824871,0.64325,-0.5, + 0.398886,0.913527,0.079739,0.817112,0.642984,-0.4095, + 0.325568,0.945519,0,0.733407,0.677865,-0.5, + 0.398886,0.913527,0.079739,0.817112,0.642984,-0.4095, + 0.324391,0.9421,0.08496,0.732447,0.675074,-0.40225, + 0.404722,0.91444,0,0.824871,0.64325,-0.5, + 0.546916,0.837188,0,0.897467,0.608935,-0.5, + 0.496158,0.862422,0.100278,0.884513,0.611054,-0.4175, + 0.496158,0.862422,0.100278,0.884513,0.611054,-0.4175, + 0.398886,0.913527,0.079739,0.817112,0.642984,-0.4095, + 0.404722,0.91444,0,0.824871,0.64325,-0.5, + 0.123897,0.972069,0.199329,0.596285,0.705555,-0.361333, + 0.139983,0.985063,0.100277,0.573201,0.718247,-0.4175, + 0.248097,0.965448,0.079739,0.645973,0.701912,-0.4095, + 0.123897,0.972069,0.199329,0.596285,0.705555,-0.361333, + 0.248097,0.965448,0.079739,0.645973,0.701912,-0.4095, + 0.226858,0.951027,0.209959,0.650852,0.69151,-0.335375, + 0.139983,0.985063,0.100277,0.573201,0.718247,-0.4175, + 0.084449,0.996428,0,0.561689,0.724552,-0.5, + 0.24406,0.96976,0,0.640022,0.706898,-0.5, + 0.24406,0.96976,0,0.640022,0.706898,-0.5, + 0.248097,0.965448,0.079739,0.645973,0.701912,-0.4095, + 0.139983,0.985063,0.100277,0.573201,0.718247,-0.4175, + 0.325568,0.945519,0,0.733407,0.677865,-0.5, + 0.324391,0.9421,0.08496,0.732447,0.675074,-0.40225, + 0.248097,0.965448,0.079739,0.645973,0.701912,-0.4095, + 0.325568,0.945519,0,0.733407,0.677865,-0.5, + 0.248097,0.965448,0.079739,0.645973,0.701912,-0.4095, + 0.24406,0.96976,0,0.640022,0.706898,-0.5, + 0.324391,0.9421,0.08496,0.732447,0.675074,-0.40225, + 0.329457,0.915147,0.232303,0.729578,0.666743,-0.322437, + 0.226858,0.951027,0.209959,0.650852,0.69151,-0.335375, + 0.226858,0.951027,0.209959,0.650852,0.69151,-0.335375, + 0.248097,0.965448,0.079739,0.645973,0.701912,-0.4095, + 0.324391,0.9421,0.08496,0.732447,0.675074,-0.40225, + 0.123896,0.972069,-0.199329,0.596285,0.705555,-0.638667, + 0.226858,0.951027,-0.209959,0.650852,0.69151,-0.664625, + 0.248097,0.965448,-0.079739,0.645973,0.701912,-0.5905, + 0.123896,0.972069,-0.199329,0.596285,0.705555,-0.638667, + 0.248097,0.965448,-0.079739,0.645973,0.701912,-0.5905, + 0.139983,0.985063,-0.100277,0.573201,0.718247,-0.5825, + 0.226858,0.951027,-0.209959,0.650852,0.69151,-0.664625, + 0.329457,0.915147,-0.232303,0.729578,0.666743,-0.677562, + 0.324391,0.9421,-0.08496,0.732447,0.675074,-0.59775, + 0.324391,0.9421,-0.08496,0.732447,0.675074,-0.59775, + 0.248097,0.965448,-0.079739,0.645973,0.701912,-0.5905, + 0.226858,0.951027,-0.209959,0.650852,0.69151,-0.664625, + 0.325568,0.945519,0,0.733407,0.677865,-0.5, + 0.24406,0.96976,0,0.640022,0.706898,-0.5, + 0.248097,0.965448,-0.079739,0.645973,0.701912,-0.5905, + 0.325568,0.945519,0,0.733407,0.677865,-0.5, + 0.248097,0.965448,-0.079739,0.645973,0.701912,-0.5905, + 0.324391,0.9421,-0.08496,0.732447,0.675074,-0.59775, + 0.24406,0.96976,0,0.640022,0.706898,-0.5, + 0.084449,0.996428,0,0.561689,0.724552,-0.5, + 0.139983,0.985063,-0.100277,0.573201,0.718247,-0.5825, + 0.139983,0.985063,-0.100277,0.573201,0.718247,-0.5825, + 0.248097,0.965448,-0.079739,0.645973,0.701912,-0.5905, + 0.24406,0.96976,0,0.640022,0.706898,-0.5, + 0.503147,0.845347,-0.179534,0.858509,0.615264,-0.638667, + 0.496158,0.862422,-0.100277,0.884513,0.611054,-0.5825, + 0.398886,0.913527,-0.079739,0.817112,0.642984,-0.5905, + 0.503147,0.845347,-0.179534,0.858509,0.615264,-0.638667, + 0.398886,0.913527,-0.079739,0.817112,0.642984,-0.5905, + 0.423992,0.883446,-0.199386,0.806863,0.637791,-0.664625, + 0.496158,0.862422,-0.100277,0.884513,0.611054,-0.5825, + 0.546916,0.837188,0,0.897467,0.608935,-0.5, + 0.404722,0.91444,0,0.824871,0.64325,-0.5, + 0.404722,0.91444,0,0.824871,0.64325,-0.5, + 0.398886,0.913527,-0.079739,0.817112,0.642984,-0.5905, + 0.496158,0.862422,-0.100277,0.884513,0.611054,-0.5825, + 0.325568,0.945519,0,0.733407,0.677865,-0.5, + 0.324391,0.9421,-0.08496,0.732447,0.675074,-0.59775, + 0.398886,0.913527,-0.079739,0.817112,0.642984,-0.5905, + 0.325568,0.945519,0,0.733407,0.677865,-0.5, + 0.398886,0.913527,-0.079739,0.817112,0.642984,-0.5905, + 0.404722,0.91444,0,0.824871,0.64325,-0.5, + 0.324391,0.9421,-0.08496,0.732447,0.675074,-0.59775, + 0.329457,0.915147,-0.232303,0.729578,0.666743,-0.677562, + 0.423992,0.883446,-0.199386,0.806863,0.637791,-0.664625, + 0.423992,0.883446,-0.199386,0.806863,0.637791,-0.664625, + 0.398886,0.913527,-0.079739,0.817112,0.642984,-0.5905, + 0.324391,0.9421,-0.08496,0.732447,0.675074,-0.59775, + 0.744225,-0.02143,-0.667585,0.865458,0.513412,-0.690781, + 0.730929,0.12699,-0.670535,0.856137,0.470533,-0.708313, + 0.942442,-0.005211,-0.334328,0.911045,0.457192,-0.613625, + 0.744225,-0.02143,-0.667585,0.865458,0.513412,-0.690781, + 0.942442,-0.005211,-0.334328,0.911045,0.457192,-0.613625, + 0.945978,-0.110612,-0.304781,0.91525,0.49905,-0.604062, + 0.730929,0.12699,-0.670535,0.856137,0.470533,-0.708313, + 0.725615,0.097758,-0.681122,0.846442,0.421012,-0.729453, + 0.940489,-0.03309,-0.338208,0.907494,0.408859,-0.625156, + 0.940489,-0.03309,-0.338208,0.907494,0.408859,-0.625156, + 0.942442,-0.005211,-0.334328,0.911045,0.457192,-0.613625, + 0.730929,0.12699,-0.670535,0.856137,0.470533,-0.708313, + 0.998189,-0.060158,0,0.927845,0.404808,-0.5, + 0.998674,-0.051473,0,0.929348,0.452746,-0.5, + 0.942442,-0.005211,-0.334328,0.911045,0.457192,-0.613625, + 0.998189,-0.060158,0,0.927845,0.404808,-0.5, + 0.942442,-0.005211,-0.334328,0.911045,0.457192,-0.613625, + 0.940489,-0.03309,-0.338208,0.907494,0.408859,-0.625156, + 0.998674,-0.051473,0,0.929348,0.452746,-0.5, + 0.980435,-0.196846,0,0.931847,0.494263,-0.5, + 0.945978,-0.110612,-0.304781,0.91525,0.49905,-0.604062, + 0.945978,-0.110612,-0.304781,0.91525,0.49905,-0.604062, + 0.942442,-0.005211,-0.334328,0.911045,0.457192,-0.613625, + 0.998674,-0.051473,0,0.929348,0.452746,-0.5, + 0.711272,-0.0413,-0.701703,0.83335,0.366979,-0.7475, + 0.63763,-0.234074,-0.733919,0.81384,0.310563,-0.75575, + 0.846641,-0.361408,-0.390619,0.882792,0.301487,-0.6395, + 0.846641,-0.361408,-0.390619,0.882792,0.301487,-0.6395, + 0.924673,-0.163459,-0.343891,0.899707,0.356231,-0.635, + 0.711272,-0.0413,-0.701703,0.83335,0.366979,-0.7475, + 0.918091,-0.39637,0,0.905776,0.298462,-0.5, + 0.985079,-0.172104,0,0.921826,0.352648,-0.5, + 0.924673,-0.163459,-0.343891,0.899707,0.356231,-0.635, + 0.918091,-0.39637,0,0.905776,0.298462,-0.5, + 0.924673,-0.163459,-0.343891,0.899707,0.356231,-0.635, + 0.846641,-0.361408,-0.390619,0.882792,0.301487,-0.6395, + 0.985079,-0.172104,0,0.921826,0.352648,-0.5, + 0.998189,-0.060158,0,0.927845,0.404808,-0.5, + 0.940489,-0.03309,-0.338208,0.907494,0.408859,-0.625156, + 0.940489,-0.03309,-0.338208,0.907494,0.408859,-0.625156, + 0.924673,-0.163459,-0.343891,0.899707,0.356231,-0.635, + 0.985079,-0.172104,0,0.921826,0.352648,-0.5, + 0.725615,0.097758,-0.681122,0.846442,0.421012,-0.729453, + 0.711272,-0.0413,-0.701703,0.83335,0.366979,-0.7475, + 0.924673,-0.163459,-0.343891,0.899707,0.356231,-0.635, + 0.725615,0.097758,-0.681122,0.846442,0.421012,-0.729453, + 0.924673,-0.163459,-0.343891,0.899707,0.356231,-0.635, + 0.940489,-0.03309,-0.338208,0.907494,0.408859,-0.625156, + 0.846641,-0.361408,0.39062,0.882792,0.301487,-0.3605, + 0.63763,-0.234074,0.733919,0.81384,0.310563,-0.24425, + 0.711272,-0.0413,0.701703,0.83335,0.366979,-0.2525, + 0.711272,-0.0413,0.701703,0.83335,0.366979,-0.2525, + 0.924673,-0.16346,0.343891,0.899707,0.356231,-0.365, + 0.846641,-0.361408,0.39062,0.882792,0.301487,-0.3605, + 0.725614,0.097758,0.681122,0.846442,0.421012,-0.270547, + 0.940489,-0.03309,0.338208,0.907494,0.408859,-0.374844, + 0.924673,-0.16346,0.343891,0.899707,0.356231,-0.365, + 0.725614,0.097758,0.681122,0.846442,0.421012,-0.270547, + 0.924673,-0.16346,0.343891,0.899707,0.356231,-0.365, + 0.711272,-0.0413,0.701703,0.83335,0.366979,-0.2525, + 0.940489,-0.03309,0.338208,0.907494,0.408859,-0.374844, + 0.998189,-0.060158,0,0.927845,0.404808,-0.5, + 0.985079,-0.172104,0,0.921826,0.352648,-0.5, + 0.985079,-0.172104,0,0.921826,0.352648,-0.5, + 0.924673,-0.16346,0.343891,0.899707,0.356231,-0.365, + 0.940489,-0.03309,0.338208,0.907494,0.408859,-0.374844, + 0.918091,-0.39637,0,0.905776,0.298462,-0.5, + 0.846641,-0.361408,0.39062,0.882792,0.301487,-0.3605, + 0.924673,-0.16346,0.343891,0.899707,0.356231,-0.365, + 0.918091,-0.39637,0,0.905776,0.298462,-0.5, + 0.924673,-0.16346,0.343891,0.899707,0.356231,-0.365, + 0.985079,-0.172104,0,0.921826,0.352648,-0.5, + 0.744225,-0.02143,0.667585,0.865458,0.513412,-0.309219, + 0.945978,-0.110612,0.304781,0.91525,0.49905,-0.395938, + 0.942442,-0.005211,0.334328,0.911045,0.457192,-0.386375, + 0.744225,-0.02143,0.667585,0.865458,0.513412,-0.309219, + 0.942442,-0.005211,0.334328,0.911045,0.457192,-0.386375, + 0.730929,0.126989,0.670535,0.856137,0.470533,-0.291687, + 0.945978,-0.110612,0.304781,0.91525,0.49905,-0.395938, + 0.980435,-0.196846,0,0.931847,0.494263,-0.5, + 0.998674,-0.051473,0,0.929348,0.452746,-0.5, + 0.998674,-0.051473,0,0.929348,0.452746,-0.5, + 0.942442,-0.005211,0.334328,0.911045,0.457192,-0.386375, + 0.945978,-0.110612,0.304781,0.91525,0.49905,-0.395938, + 0.998189,-0.060158,0,0.927845,0.404808,-0.5, + 0.940489,-0.03309,0.338208,0.907494,0.408859,-0.374844, + 0.942442,-0.005211,0.334328,0.911045,0.457192,-0.386375, + 0.998189,-0.060158,0,0.927845,0.404808,-0.5, + 0.942442,-0.005211,0.334328,0.911045,0.457192,-0.386375, + 0.998674,-0.051473,0,0.929348,0.452746,-0.5, + 0.940489,-0.03309,0.338208,0.907494,0.408859,-0.374844, + 0.725614,0.097758,0.681122,0.846442,0.421012,-0.270547, + 0.730929,0.126989,0.670535,0.856137,0.470533,-0.291687, + 0.730929,0.126989,0.670535,0.856137,0.470533,-0.291687, + 0.942442,-0.005211,0.334328,0.911045,0.457192,-0.386375, + 0.940489,-0.03309,0.338208,0.907494,0.408859,-0.374844, + -0.468298,0.578298,-0.668033,0.500319,0.618731,-0.690781, + -0.46274,0.649831,-0.602985,0.453481,0.568361,-0.708313, + -0.1826,0.53251,-0.826493,0.544994,0.546127,-0.765125, + -0.468298,0.578298,-0.668033,0.500319,0.618731,-0.690781, + -0.1826,0.53251,-0.826493,0.544994,0.546127,-0.765125, + -0.208655,0.445101,-0.870832,0.583305,0.594795,-0.742813, + -0.46274,0.649831,-0.602985,0.453481,0.568361,-0.708313, + -0.490654,0.624331,-0.60784,0.398726,0.51013,-0.729453, + -0.208343,0.508292,-0.835603,0.500479,0.489876,-0.792031, + -0.208343,0.508292,-0.835603,0.500479,0.489876,-0.792031, + -0.1826,0.53251,-0.826493,0.544994,0.546127,-0.765125, + -0.46274,0.649831,-0.602985,0.453481,0.568361,-0.708313, + 0.081884,0.387365,-0.918283,0.622584,0.465571,-0.812891, + 0.102672,0.412673,-0.905074,0.654809,0.519447,-0.784063, + -0.1826,0.53251,-0.826493,0.544994,0.546127,-0.765125, + 0.081884,0.387365,-0.918283,0.622584,0.465571,-0.812891, + -0.1826,0.53251,-0.826493,0.544994,0.546127,-0.765125, + -0.208343,0.508292,-0.835603,0.500479,0.489876,-0.792031, + 0.102672,0.412673,-0.905074,0.654809,0.519447,-0.784063, + 0.088733,0.313595,-0.945402,0.682889,0.566071,-0.760156, + -0.208655,0.445101,-0.870832,0.583305,0.594795,-0.742813, + -0.208655,0.445101,-0.870832,0.583305,0.594795,-0.742813, + -0.1826,0.53251,-0.826493,0.544994,0.546127,-0.765125, + 0.102672,0.412673,-0.905074,0.654809,0.519447,-0.784063, + -0.59415,0.505848,-0.625383,0.346736,0.445797,-0.7475, + -0.645198,0.198269,-0.737841,0.308193,0.377118,-0.75575, + -0.328501,0.124794,-0.936223,0.423113,0.361992,-0.8255, + -0.328501,0.124794,-0.936223,0.423113,0.361992,-0.8255, + -0.261623,0.387306,-0.884052,0.45733,0.427884,-0.815, + -0.59415,0.505848,-0.625383,0.346736,0.445797,-0.7475, + 0.001894,-0.000876,-0.999998,0.561017,0.343841,-0.84875, + 0.046906,0.258379,-0.964904,0.590043,0.406388,-0.8375, + -0.261623,0.387306,-0.884052,0.45733,0.427884,-0.815, + 0.001894,-0.000876,-0.999998,0.561017,0.343841,-0.84875, + -0.261623,0.387306,-0.884052,0.45733,0.427884,-0.815, + -0.328501,0.124794,-0.936223,0.423113,0.361992,-0.8255, + 0.046906,0.258379,-0.964904,0.590043,0.406388,-0.8375, + 0.081884,0.387365,-0.918283,0.622584,0.465571,-0.812891, + -0.208343,0.508292,-0.835603,0.500479,0.489876,-0.792031, + -0.208343,0.508292,-0.835603,0.500479,0.489876,-0.792031, + -0.261623,0.387306,-0.884052,0.45733,0.427884,-0.815, + 0.046906,0.258379,-0.964904,0.590043,0.406388,-0.8375, + -0.490654,0.624331,-0.60784,0.398726,0.51013,-0.729453, + -0.59415,0.505848,-0.625383,0.346736,0.445797,-0.7475, + -0.261623,0.387306,-0.884052,0.45733,0.427884,-0.815, + -0.490654,0.624331,-0.60784,0.398726,0.51013,-0.729453, + -0.261623,0.387306,-0.884052,0.45733,0.427884,-0.815, + -0.208343,0.508292,-0.835603,0.500479,0.489876,-0.792031, + 0.63763,-0.234074,-0.733919,0.81384,0.310563,-0.75575, + 0.711272,-0.0413,-0.701703,0.83335,0.366979,-0.7475, + 0.369337,0.119431,-0.921589,0.722756,0.384892,-0.815, + 0.63763,-0.234074,-0.733919,0.81384,0.310563,-0.75575, + 0.369337,0.119431,-0.921589,0.722756,0.384892,-0.815, + 0.330471,-0.133893,-0.93427,0.69892,0.325689,-0.8255, + 0.711272,-0.0413,-0.701703,0.83335,0.366979,-0.7475, + 0.725615,0.097758,-0.681122,0.846442,0.421012,-0.729453, + 0.390355,0.256716,-0.884149,0.744688,0.441266,-0.792031, + 0.390355,0.256716,-0.884149,0.744688,0.441266,-0.792031, + 0.369337,0.119431,-0.921589,0.722756,0.384892,-0.815, + 0.711272,-0.0413,-0.701703,0.83335,0.366979,-0.7475, + 0.081884,0.387365,-0.918283,0.622584,0.465571,-0.812891, + 0.046906,0.258379,-0.964904,0.590043,0.406388,-0.8375, + 0.369337,0.119431,-0.921589,0.722756,0.384892,-0.815, + 0.081884,0.387365,-0.918283,0.622584,0.465571,-0.812891, + 0.369337,0.119431,-0.921589,0.722756,0.384892,-0.815, + 0.390355,0.256716,-0.884149,0.744688,0.441266,-0.792031, + 0.046906,0.258379,-0.964904,0.590043,0.406388,-0.8375, + 0.001894,-0.000876,-0.999998,0.561017,0.343841,-0.84875, + 0.330471,-0.133893,-0.93427,0.69892,0.325689,-0.8255, + 0.330471,-0.133893,-0.93427,0.69892,0.325689,-0.8255, + 0.369337,0.119431,-0.921589,0.722756,0.384892,-0.815, + 0.046906,0.258379,-0.964904,0.590043,0.406388,-0.8375, + 0.730929,0.12699,-0.670535,0.856137,0.470533,-0.708313, + 0.744225,-0.02143,-0.667585,0.865458,0.513412,-0.690781, + 0.395884,0.173928,-0.901679,0.782472,0.537348,-0.742813, + 0.395884,0.173928,-0.901679,0.782472,0.537348,-0.742813, + 0.403724,0.284631,-0.869478,0.764624,0.492766,-0.765125, + 0.730929,0.12699,-0.670535,0.856137,0.470533,-0.708313, + 0.088733,0.313595,-0.945402,0.682889,0.566071,-0.760156, + 0.102672,0.412673,-0.905074,0.654809,0.519447,-0.784063, + 0.403724,0.284631,-0.869478,0.764624,0.492766,-0.765125, + 0.088733,0.313595,-0.945402,0.682889,0.566071,-0.760156, + 0.403724,0.284631,-0.869478,0.764624,0.492766,-0.765125, + 0.395884,0.173928,-0.901679,0.782472,0.537348,-0.742813, + 0.102672,0.412673,-0.905074,0.654809,0.519447,-0.784063, + 0.081884,0.387365,-0.918283,0.622584,0.465571,-0.812891, + 0.390355,0.256716,-0.884149,0.744688,0.441266,-0.792031, + 0.390355,0.256716,-0.884149,0.744688,0.441266,-0.792031, + 0.403724,0.284631,-0.869478,0.764624,0.492766,-0.765125, + 0.102672,0.412673,-0.905074,0.654809,0.519447,-0.784063, + 0.725615,0.097758,-0.681122,0.846442,0.421012,-0.729453, + 0.730929,0.12699,-0.670535,0.856137,0.470533,-0.708313, + 0.403724,0.284631,-0.869478,0.764624,0.492766,-0.765125, + 0.725615,0.097758,-0.681122,0.846442,0.421012,-0.729453, + 0.403724,0.284631,-0.869478,0.764624,0.492766,-0.765125, + 0.390355,0.256716,-0.884149,0.744688,0.441266,-0.792031, + -0.468298,0.578298,0.668033,0.500319,0.618731,-0.309219, + -0.208655,0.445101,0.870832,0.583305,0.594795,-0.257187, + -0.1826,0.532509,0.826493,0.544994,0.546127,-0.234875, + -0.468298,0.578298,0.668033,0.500319,0.618731,-0.309219, + -0.1826,0.532509,0.826493,0.544994,0.546127,-0.234875, + -0.46274,0.649831,0.602985,0.453481,0.568361,-0.291687, + -0.208655,0.445101,0.870832,0.583305,0.594795,-0.257187, + 0.088734,0.313595,0.945402,0.682889,0.566071,-0.239844, + 0.102672,0.412673,0.905074,0.654809,0.519447,-0.215937, + 0.102672,0.412673,0.905074,0.654809,0.519447,-0.215937, + -0.1826,0.532509,0.826493,0.544994,0.546127,-0.234875, + -0.208655,0.445101,0.870832,0.583305,0.594795,-0.257187, + 0.081884,0.387365,0.918283,0.622584,0.465571,-0.187109, + -0.208343,0.508292,0.835603,0.500479,0.489876,-0.207969, + -0.1826,0.532509,0.826493,0.544994,0.546127,-0.234875, + 0.081884,0.387365,0.918283,0.622584,0.465571,-0.187109, + -0.1826,0.532509,0.826493,0.544994,0.546127,-0.234875, + 0.102672,0.412673,0.905074,0.654809,0.519447,-0.215937, + -0.208343,0.508292,0.835603,0.500479,0.489876,-0.207969, + -0.490654,0.624331,0.60784,0.398726,0.51013,-0.270547, + -0.46274,0.649831,0.602985,0.453481,0.568361,-0.291687, + -0.46274,0.649831,0.602985,0.453481,0.568361,-0.291687, + -0.1826,0.532509,0.826493,0.544994,0.546127,-0.234875, + -0.208343,0.508292,0.835603,0.500479,0.489876,-0.207969, + 0.395884,0.173928,0.901679,0.782472,0.537348,-0.257187, + 0.744225,-0.02143,0.667585,0.865458,0.513412,-0.309219, + 0.730929,0.126989,0.670535,0.856137,0.470533,-0.291687, + 0.730929,0.126989,0.670535,0.856137,0.470533,-0.291687, + 0.403724,0.284631,0.869478,0.764624,0.492766,-0.234875, + 0.395884,0.173928,0.901679,0.782472,0.537348,-0.257187, + 0.725614,0.097758,0.681122,0.846442,0.421012,-0.270547, + 0.390355,0.256716,0.884149,0.744688,0.441266,-0.207969, + 0.403724,0.284631,0.869478,0.764624,0.492766,-0.234875, + 0.725614,0.097758,0.681122,0.846442,0.421012,-0.270547, + 0.403724,0.284631,0.869478,0.764624,0.492766,-0.234875, + 0.730929,0.126989,0.670535,0.856137,0.470533,-0.291687, + 0.390355,0.256716,0.884149,0.744688,0.441266,-0.207969, + 0.081884,0.387365,0.918283,0.622584,0.465571,-0.187109, + 0.102672,0.412673,0.905074,0.654809,0.519447,-0.215937, + 0.102672,0.412673,0.905074,0.654809,0.519447,-0.215937, + 0.403724,0.284631,0.869478,0.764624,0.492766,-0.234875, + 0.390355,0.256716,0.884149,0.744688,0.441266,-0.207969, + 0.088734,0.313595,0.945402,0.682889,0.566071,-0.239844, + 0.395884,0.173928,0.901679,0.782472,0.537348,-0.257187, + 0.403724,0.284631,0.869478,0.764624,0.492766,-0.234875, + 0.088734,0.313595,0.945402,0.682889,0.566071,-0.239844, + 0.403724,0.284631,0.869478,0.764624,0.492766,-0.234875, + 0.102672,0.412673,0.905074,0.654809,0.519447,-0.215937, + 0.63763,-0.234074,0.733919,0.81384,0.310563,-0.24425, + 0.330471,-0.133893,0.93427,0.69892,0.325689,-0.1745, + 0.369337,0.119431,0.921589,0.722756,0.384892,-0.185, + 0.63763,-0.234074,0.733919,0.81384,0.310563,-0.24425, + 0.369337,0.119431,0.921589,0.722756,0.384892,-0.185, + 0.711272,-0.0413,0.701703,0.83335,0.366979,-0.2525, + 0.330471,-0.133893,0.93427,0.69892,0.325689,-0.1745, + 0.001894,-0.000875,0.999998,0.561017,0.343841,-0.15125, + 0.046906,0.258379,0.964904,0.590043,0.406388,-0.1625, + 0.046906,0.258379,0.964904,0.590043,0.406388,-0.1625, + 0.369337,0.119431,0.921589,0.722756,0.384892,-0.185, + 0.330471,-0.133893,0.93427,0.69892,0.325689,-0.1745, + 0.081884,0.387365,0.918283,0.622584,0.465571,-0.187109, + 0.390355,0.256716,0.884149,0.744688,0.441266,-0.207969, + 0.369337,0.119431,0.921589,0.722756,0.384892,-0.185, + 0.081884,0.387365,0.918283,0.622584,0.465571,-0.187109, + 0.369337,0.119431,0.921589,0.722756,0.384892,-0.185, + 0.046906,0.258379,0.964904,0.590043,0.406388,-0.1625, + 0.390355,0.256716,0.884149,0.744688,0.441266,-0.207969, + 0.725614,0.097758,0.681122,0.846442,0.421012,-0.270547, + 0.711272,-0.0413,0.701703,0.83335,0.366979,-0.2525, + 0.711272,-0.0413,0.701703,0.83335,0.366979,-0.2525, + 0.369337,0.119431,0.921589,0.722756,0.384892,-0.185, + 0.390355,0.256716,0.884149,0.744688,0.441266,-0.207969, + -0.328501,0.124794,0.936223,0.423113,0.361992,-0.1745, + -0.645198,0.198269,0.737841,0.308193,0.377118,-0.24425, + -0.59415,0.505848,0.625383,0.346736,0.445797,-0.2525, + -0.59415,0.505848,0.625383,0.346736,0.445797,-0.2525, + -0.261623,0.387306,0.884052,0.45733,0.427884,-0.185, + -0.328501,0.124794,0.936223,0.423113,0.361992,-0.1745, + -0.490654,0.624331,0.60784,0.398726,0.51013,-0.270547, + -0.208343,0.508292,0.835603,0.500479,0.489876,-0.207969, + -0.261623,0.387306,0.884052,0.45733,0.427884,-0.185, + -0.490654,0.624331,0.60784,0.398726,0.51013,-0.270547, + -0.261623,0.387306,0.884052,0.45733,0.427884,-0.185, + -0.59415,0.505848,0.625383,0.346736,0.445797,-0.2525, + -0.208343,0.508292,0.835603,0.500479,0.489876,-0.207969, + 0.081884,0.387365,0.918283,0.622584,0.465571,-0.187109, + 0.046906,0.258379,0.964904,0.590043,0.406388,-0.1625, + 0.046906,0.258379,0.964904,0.590043,0.406388,-0.1625, + -0.261623,0.387306,0.884052,0.45733,0.427884,-0.185, + -0.208343,0.508292,0.835603,0.500479,0.489876,-0.207969, + 0.001894,-0.000875,0.999998,0.561017,0.343841,-0.15125, + -0.328501,0.124794,0.936223,0.423113,0.361992,-0.1745, + -0.261623,0.387306,0.884052,0.45733,0.427884,-0.185, + 0.001894,-0.000875,0.999998,0.561017,0.343841,-0.15125, + -0.261623,0.387306,0.884052,0.45733,0.427884,-0.185, + 0.046906,0.258379,0.964904,0.590043,0.406388,-0.1625, + -0.46274,0.649831,-0.602985,0.453481,0.568361,-0.708313, + -0.468298,0.578298,-0.668033,0.500319,0.618731,-0.690781, + -0.677265,0.639604,-0.363619,0.450527,0.633092,-0.604062, + -0.677265,0.639604,-0.363619,0.450527,0.633092,-0.604062, + -0.641469,0.710708,-0.288812,0.398573,0.581701,-0.613625, + -0.46274,0.649831,-0.602985,0.453481,0.568361,-0.708313, + -0.749144,0.662408,0,0.43393,0.63788,-0.5, + -0.689225,0.724547,0,0.380271,0.586148,-0.5, + -0.641469,0.710708,-0.288812,0.398573,0.581701,-0.613625, + -0.749144,0.662408,0,0.43393,0.63788,-0.5, + -0.641469,0.710708,-0.288812,0.398573,0.581701,-0.613625, + -0.677265,0.639604,-0.363619,0.450527,0.633092,-0.604062, + -0.689225,0.724547,0,0.380271,0.586148,-0.5, + -0.718122,0.695917,0,0.317323,0.526334,-0.5, + -0.680327,0.681689,-0.269175,0.337674,0.522283,-0.625156, + -0.680327,0.681689,-0.269175,0.337674,0.522283,-0.625156, + -0.641469,0.710708,-0.288812,0.398573,0.581701,-0.613625, + -0.689225,0.724547,0,0.380271,0.586148,-0.5, + -0.490654,0.624331,-0.60784,0.398726,0.51013,-0.729453, + -0.46274,0.649831,-0.602985,0.453481,0.568361,-0.708313, + -0.641469,0.710708,-0.288812,0.398573,0.581701,-0.613625, + -0.490654,0.624331,-0.60784,0.398726,0.51013,-0.729453, + -0.641469,0.710708,-0.288812,0.398573,0.581701,-0.613625, + -0.680327,0.681689,-0.269175,0.337674,0.522283,-0.625156, + -0.677265,0.639604,0.363619,0.450527,0.633092,-0.395938, + -0.468298,0.578298,0.668033,0.500319,0.618731,-0.309219, + -0.46274,0.649831,0.602985,0.453481,0.568361,-0.291687, + -0.46274,0.649831,0.602985,0.453481,0.568361,-0.291687, + -0.641469,0.710708,0.288812,0.398573,0.581701,-0.386375, + -0.677265,0.639604,0.363619,0.450527,0.633092,-0.395938, + -0.490654,0.624331,0.60784,0.398726,0.51013,-0.270547, + -0.680327,0.681689,0.269175,0.337674,0.522283,-0.374844, + -0.641469,0.710708,0.288812,0.398573,0.581701,-0.386375, + -0.490654,0.624331,0.60784,0.398726,0.51013,-0.270547, + -0.641469,0.710708,0.288812,0.398573,0.581701,-0.386375, + -0.46274,0.649831,0.602985,0.453481,0.568361,-0.291687, + -0.680327,0.681689,0.269175,0.337674,0.522283,-0.374844, + -0.718122,0.695917,0,0.317323,0.526334,-0.5, + -0.689225,0.724547,0,0.380271,0.586148,-0.5, + -0.689225,0.724547,0,0.380271,0.586148,-0.5, + -0.641469,0.710708,0.288812,0.398573,0.581701,-0.386375, + -0.680327,0.681689,0.269175,0.337674,0.522283,-0.374844, + -0.749144,0.662408,0,0.43393,0.63788,-0.5, + -0.677265,0.639604,0.363619,0.450527,0.633092,-0.395938, + -0.641469,0.710708,0.288812,0.398573,0.581701,-0.386375, + -0.749144,0.662408,0,0.43393,0.63788,-0.5, + -0.641469,0.710708,0.288812,0.398573,0.581701,-0.386375, + -0.689225,0.724547,0,0.380271,0.586148,-0.5, + -0.59415,0.505848,0.625383,0.346736,0.445797,-0.2525, + -0.645198,0.198269,0.737841,0.308193,0.377118,-0.24425, + -0.862657,0.31434,0.396249,0.239242,0.386194,-0.3605, + -0.862657,0.31434,0.396249,0.239242,0.386194,-0.3605, + -0.778413,0.562971,0.277735,0.280379,0.456545,-0.365, + -0.59415,0.505848,0.625383,0.346736,0.445797,-0.2525, + -0.940313,0.340311,0,0.216258,0.389219,-0.5, + -0.786635,0.617419,0,0.25826,0.460127,-0.5, + -0.778413,0.562971,0.277735,0.280379,0.456545,-0.365, + -0.940313,0.340311,0,0.216258,0.389219,-0.5, + -0.778413,0.562971,0.277735,0.280379,0.456545,-0.365, + -0.862657,0.31434,0.396249,0.239242,0.386194,-0.3605, + -0.786635,0.617419,0,0.25826,0.460127,-0.5, + -0.718122,0.695917,0,0.317323,0.526334,-0.5, + -0.680327,0.681689,0.269175,0.337674,0.522283,-0.374844, + -0.680327,0.681689,0.269175,0.337674,0.522283,-0.374844, + -0.778413,0.562971,0.277735,0.280379,0.456545,-0.365, + -0.786635,0.617419,0,0.25826,0.460127,-0.5, + -0.680327,0.681689,0.269175,0.337674,0.522283,-0.374844, + -0.490654,0.624331,0.60784,0.398726,0.51013,-0.270547, + -0.59415,0.505848,0.625383,0.346736,0.445797,-0.2525, + -0.59415,0.505848,0.625383,0.346736,0.445797,-0.2525, + -0.778413,0.562971,0.277735,0.280379,0.456545,-0.365, + -0.680327,0.681689,0.269175,0.337674,0.522283,-0.374844, + -0.862657,0.31434,-0.396249,0.239242,0.386194,-0.6395, + -0.645198,0.198269,-0.737841,0.308193,0.377118,-0.75575, + -0.59415,0.505848,-0.625383,0.346736,0.445797,-0.7475, + -0.59415,0.505848,-0.625383,0.346736,0.445797,-0.7475, + -0.778414,0.562971,-0.277735,0.280379,0.456545,-0.635, + -0.862657,0.31434,-0.396249,0.239242,0.386194,-0.6395, + -0.59415,0.505848,-0.625383,0.346736,0.445797,-0.7475, + -0.490654,0.624331,-0.60784,0.398726,0.51013,-0.729453, + -0.680327,0.681689,-0.269175,0.337674,0.522283,-0.625156, + -0.680327,0.681689,-0.269175,0.337674,0.522283,-0.625156, + -0.778414,0.562971,-0.277735,0.280379,0.456545,-0.635, + -0.59415,0.505848,-0.625383,0.346736,0.445797,-0.7475, + -0.680327,0.681689,-0.269175,0.337674,0.522283,-0.625156, + -0.718122,0.695917,0,0.317323,0.526334,-0.5, + -0.786635,0.617419,0,0.25826,0.460127,-0.5, + -0.786635,0.617419,0,0.25826,0.460127,-0.5, + -0.778414,0.562971,-0.277735,0.280379,0.456545,-0.635, + -0.680327,0.681689,-0.269175,0.337674,0.522283,-0.625156, + -0.940313,0.340311,0,0.216258,0.389219,-0.5, + -0.862657,0.31434,-0.396249,0.239242,0.386194,-0.6395, + -0.778414,0.562971,-0.277735,0.280379,0.456545,-0.635, + -0.940313,0.340311,0,0.216258,0.389219,-0.5, + -0.778414,0.562971,-0.277735,0.280379,0.456545,-0.635, + -0.786635,0.617419,0,0.25826,0.460127,-0.5, + -0.68646,-0.277096,-0.672303,0.316229,0.114342,-0.690781, + -0.340489,-0.258832,-0.903921,0.402791,0.111771,-0.742813, + -0.337162,-0.377107,-0.86262,0.400082,0.165542,-0.765125, + -0.68646,-0.277096,-0.672303,0.316229,0.114342,-0.690781, + -0.337162,-0.377107,-0.86262,0.400082,0.165542,-0.765125, + -0.681322,-0.324401,-0.656174,0.305709,0.170683,-0.708313, + -0.009985,-0.330184,-0.943864,0.506665,0.108686,-0.760156, + -0.024814,-0.431442,-0.901799,0.513329,0.159372,-0.784063, + -0.337162,-0.377107,-0.86262,0.400082,0.165542,-0.765125, + -0.009985,-0.330184,-0.943864,0.506665,0.108686,-0.760156, + -0.337162,-0.377107,-0.86262,0.400082,0.165542,-0.765125, + -0.340489,-0.258832,-0.903921,0.402791,0.111771,-0.742813, + -0.024814,-0.431442,-0.901799,0.513329,0.159372,-0.784063, + -0.034163,-0.398975,-0.916325,0.52383,0.217409,-0.812891, + -0.348349,-0.345034,-0.871553,0.399335,0.22743,-0.792031, + -0.348349,-0.345034,-0.871553,0.399335,0.22743,-0.792031, + -0.337162,-0.377107,-0.86262,0.400082,0.165542,-0.765125, + -0.024814,-0.431442,-0.901799,0.513329,0.159372,-0.784063, + -0.348349,-0.345034,-0.871553,0.399335,0.22743,-0.792031, + -0.700275,-0.236966,-0.673395,0.295589,0.235781,-0.729453, + -0.681322,-0.324401,-0.656174,0.305709,0.170683,-0.708313, + -0.681322,-0.324401,-0.656174,0.305709,0.170683,-0.708313, + -0.337162,-0.377107,-0.86262,0.400082,0.165542,-0.765125, + -0.348349,-0.345034,-0.871553,0.399335,0.22743,-0.792031, + 0.612462,-0.474039,-0.632596,0.6971,0.103031,-0.690781, + 0.562161,-0.569598,-0.59961,0.72095,0.148061,-0.708313, + 0.274839,-0.496479,-0.823391,0.626577,0.153203,-0.765125, + 0.612462,-0.474039,-0.632596,0.6971,0.103031,-0.690781, + 0.274839,-0.496479,-0.823391,0.626577,0.153203,-0.765125, + 0.309535,-0.382382,-0.870616,0.610539,0.105601,-0.742813, + 0.562161,-0.569598,-0.59961,0.72095,0.148061,-0.708313, + 0.562307,-0.55594,-0.612162,0.75207,0.199038,-0.729453, + 0.267074,-0.480259,-0.835478,0.648325,0.207388,-0.792031, + 0.267074,-0.480259,-0.835478,0.648325,0.207388,-0.792031, + 0.274839,-0.496479,-0.823391,0.626577,0.153203,-0.765125, + 0.562161,-0.569598,-0.59961,0.72095,0.148061,-0.708313, + -0.034163,-0.398975,-0.916325,0.52383,0.217409,-0.812891, + -0.024814,-0.431442,-0.901799,0.513329,0.159372,-0.784063, + 0.274839,-0.496479,-0.823391,0.626577,0.153203,-0.765125, + -0.034163,-0.398975,-0.916325,0.52383,0.217409,-0.812891, + 0.274839,-0.496479,-0.823391,0.626577,0.153203,-0.765125, + 0.267074,-0.480259,-0.835478,0.648325,0.207388,-0.792031, + -0.024814,-0.431442,-0.901799,0.513329,0.159372,-0.784063, + -0.009985,-0.330184,-0.943864,0.506665,0.108686,-0.760156, + 0.309535,-0.382382,-0.870616,0.610539,0.105601,-0.742813, + 0.309535,-0.382382,-0.870616,0.610539,0.105601,-0.742813, + 0.274839,-0.496479,-0.823391,0.626577,0.153203,-0.765125, + -0.024814,-0.431442,-0.901799,0.513329,0.159372,-0.784063, + 0.603048,-0.457417,-0.653531,0.78489,0.253894,-0.7475, + 0.63763,-0.234074,-0.733919,0.81384,0.310563,-0.75575, + 0.330471,-0.133893,-0.93427,0.69892,0.325689,-0.8255, + 0.330471,-0.133893,-0.93427,0.69892,0.325689,-0.8255, + 0.285459,-0.369325,-0.884371,0.673275,0.265703,-0.815, + 0.603048,-0.457417,-0.653531,0.78489,0.253894,-0.7475, + 0.001894,-0.000876,-0.999998,0.561017,0.343841,-0.84875, + -0.029604,-0.263,-0.964342,0.539336,0.279873,-0.8375, + 0.285459,-0.369325,-0.884371,0.673275,0.265703,-0.815, + 0.001894,-0.000876,-0.999998,0.561017,0.343841,-0.84875, + 0.285459,-0.369325,-0.884371,0.673275,0.265703,-0.815, + 0.330471,-0.133893,-0.93427,0.69892,0.325689,-0.8255, + -0.029604,-0.263,-0.964342,0.539336,0.279873,-0.8375, + -0.034163,-0.398975,-0.916325,0.52383,0.217409,-0.812891, + 0.267074,-0.480259,-0.835478,0.648325,0.207388,-0.792031, + 0.267074,-0.480259,-0.835478,0.648325,0.207388,-0.792031, + 0.285459,-0.369325,-0.884371,0.673275,0.265703,-0.815, + -0.029604,-0.263,-0.964342,0.539336,0.279873,-0.8375, + 0.562307,-0.55594,-0.612162,0.75207,0.199038,-0.729453, + 0.603048,-0.457417,-0.653531,0.78489,0.253894,-0.7475, + 0.285459,-0.369325,-0.884371,0.673275,0.265703,-0.815, + 0.562307,-0.55594,-0.612162,0.75207,0.199038,-0.729453, + 0.285459,-0.369325,-0.884371,0.673275,0.265703,-0.815, + 0.267074,-0.480259,-0.835478,0.648325,0.207388,-0.792031, + -0.645198,0.198269,-0.737841,0.308193,0.377118,-0.75575, + -0.746027,-0.030098,-0.665235,0.293781,0.305853,-0.7475, + -0.383319,-0.173246,-0.907222,0.405397,0.294044,-0.815, + -0.645198,0.198269,-0.737841,0.308193,0.377118,-0.75575, + -0.383319,-0.173246,-0.907222,0.405397,0.294044,-0.815, + -0.328501,0.124794,-0.936223,0.423113,0.361992,-0.8255, + -0.700275,-0.236966,-0.673395,0.295589,0.235781,-0.729453, + -0.348349,-0.345034,-0.871553,0.399335,0.22743,-0.792031, + -0.383319,-0.173246,-0.907222,0.405397,0.294044,-0.815, + -0.700275,-0.236966,-0.673395,0.295589,0.235781,-0.729453, + -0.383319,-0.173246,-0.907222,0.405397,0.294044,-0.815, + -0.746027,-0.030098,-0.665235,0.293781,0.305853,-0.7475, + -0.034163,-0.398975,-0.916325,0.52383,0.217409,-0.812891, + -0.029604,-0.263,-0.964342,0.539336,0.279873,-0.8375, + -0.383319,-0.173246,-0.907222,0.405397,0.294044,-0.815, + -0.034163,-0.398975,-0.916325,0.52383,0.217409,-0.812891, + -0.383319,-0.173246,-0.907222,0.405397,0.294044,-0.815, + -0.348349,-0.345034,-0.871553,0.399335,0.22743,-0.792031, + -0.029604,-0.263,-0.964342,0.539336,0.279873,-0.8375, + 0.001894,-0.000876,-0.999998,0.561017,0.343841,-0.84875, + -0.328501,0.124794,-0.936223,0.423113,0.361992,-0.8255, + -0.328501,0.124794,-0.936223,0.423113,0.361992,-0.8255, + -0.383319,-0.173246,-0.907222,0.405397,0.294044,-0.815, + -0.029604,-0.263,-0.964342,0.539336,0.279873,-0.8375, + -0.68646,-0.277096,-0.672303,0.316229,0.114342,-0.690781, + -0.681322,-0.324401,-0.656174,0.305709,0.170683,-0.708313, + -0.90316,-0.279949,-0.32547,0.249085,0.173768,-0.613625, + -0.68646,-0.277096,-0.672303,0.316229,0.114342,-0.690781, + -0.90316,-0.279949,-0.32547,0.249085,0.173768,-0.613625, + -0.917766,-0.211835,-0.335904,0.264292,0.115884,-0.604062, + -0.681322,-0.324401,-0.656174,0.305709,0.170683,-0.708313, + -0.700275,-0.236966,-0.673395,0.295589,0.235781,-0.729453, + -0.92222,-0.200491,-0.330626,0.233342,0.240791,-0.625156, + -0.92222,-0.200491,-0.330626,0.233342,0.240791,-0.625156, + -0.90316,-0.279949,-0.32547,0.249085,0.173768,-0.613625, + -0.681322,-0.324401,-0.656174,0.305709,0.170683,-0.708313, + -0.978535,-0.206083,0,0.212593,0.242461,-0.5, + -0.963203,-0.268774,0,0.23021,0.174796,-0.5, + -0.90316,-0.279949,-0.32547,0.249085,0.173768,-0.613625, + -0.978535,-0.206083,0,0.212593,0.242461,-0.5, + -0.90316,-0.279949,-0.32547,0.249085,0.173768,-0.613625, + -0.92222,-0.200491,-0.330626,0.233342,0.240791,-0.625156, + -0.963203,-0.268774,0,0.23021,0.174796,-0.5, + -0.984639,-0.174604,0,0.24698,0.116398,-0.5, + -0.917766,-0.211835,-0.335904,0.264292,0.115884,-0.604062, + -0.917766,-0.211835,-0.335904,0.264292,0.115884,-0.604062, + -0.90316,-0.279949,-0.32547,0.249085,0.173768,-0.613625, + -0.963203,-0.268774,0,0.23021,0.174796,-0.5, + -0.746027,-0.030098,-0.665235,0.293781,0.305853,-0.7475, + -0.645198,0.198269,-0.737841,0.308193,0.377118,-0.75575, + -0.862657,0.31434,-0.396249,0.239242,0.386194,-0.6395, + -0.862657,0.31434,-0.396249,0.239242,0.386194,-0.6395, + -0.939405,0.002804,-0.342799,0.226812,0.312938,-0.635, + -0.746027,-0.030098,-0.665235,0.293781,0.305853,-0.7475, + -0.940313,0.340311,0,0.216258,0.389219,-0.5, + -0.999757,-0.022023,0,0.204489,0.3153,-0.5, + -0.939405,0.002804,-0.342799,0.226812,0.312938,-0.635, + -0.940313,0.340311,0,0.216258,0.389219,-0.5, + -0.939405,0.002804,-0.342799,0.226812,0.312938,-0.635, + -0.862657,0.31434,-0.396249,0.239242,0.386194,-0.6395, + -0.999757,-0.022023,0,0.204489,0.3153,-0.5, + -0.978535,-0.206083,0,0.212593,0.242461,-0.5, + -0.92222,-0.200491,-0.330626,0.233342,0.240791,-0.625156, + -0.92222,-0.200491,-0.330626,0.233342,0.240791,-0.625156, + -0.939405,0.002804,-0.342799,0.226812,0.312938,-0.635, + -0.999757,-0.022023,0,0.204489,0.3153,-0.5, + -0.700275,-0.236966,-0.673395,0.295589,0.235781,-0.729453, + -0.746027,-0.030098,-0.665235,0.293781,0.305853,-0.7475, + -0.939405,0.002804,-0.342799,0.226812,0.312938,-0.635, + -0.700275,-0.236966,-0.673395,0.295589,0.235781,-0.729453, + -0.939405,0.002804,-0.342799,0.226812,0.312938,-0.635, + -0.92222,-0.200491,-0.330626,0.233342,0.240791,-0.625156, + -0.862657,0.31434,0.396249,0.239242,0.386194,-0.3605, + -0.645198,0.198269,0.737841,0.308193,0.377118,-0.24425, + -0.746027,-0.030098,0.665236,0.293781,0.305853,-0.2525, + -0.746027,-0.030098,0.665236,0.293781,0.305853,-0.2525, + -0.939405,0.002804,0.342799,0.226812,0.312938,-0.365, + -0.862657,0.31434,0.396249,0.239242,0.386194,-0.3605, + -0.700275,-0.236966,0.673395,0.295589,0.235781,-0.270547, + -0.92222,-0.200492,0.330626,0.233342,0.240791,-0.374844, + -0.939405,0.002804,0.342799,0.226812,0.312938,-0.365, + -0.700275,-0.236966,0.673395,0.295589,0.235781,-0.270547, + -0.939405,0.002804,0.342799,0.226812,0.312938,-0.365, + -0.746027,-0.030098,0.665236,0.293781,0.305853,-0.2525, + -0.92222,-0.200492,0.330626,0.233342,0.240791,-0.374844, + -0.978535,-0.206083,0,0.212593,0.242461,-0.5, + -0.999757,-0.022023,0,0.204489,0.3153,-0.5, + -0.999757,-0.022023,0,0.204489,0.3153,-0.5, + -0.939405,0.002804,0.342799,0.226812,0.312938,-0.365, + -0.92222,-0.200492,0.330626,0.233342,0.240791,-0.374844, + -0.940313,0.340311,0,0.216258,0.389219,-0.5, + -0.862657,0.31434,0.396249,0.239242,0.386194,-0.3605, + -0.939405,0.002804,0.342799,0.226812,0.312938,-0.365, + -0.940313,0.340311,0,0.216258,0.389219,-0.5, + -0.939405,0.002804,0.342799,0.226812,0.312938,-0.365, + -0.999757,-0.022023,0,0.204489,0.3153,-0.5, + -0.68646,-0.277096,0.672303,0.316229,0.114342,-0.309219, + -0.917766,-0.211835,0.335904,0.264292,0.115884,-0.395938, + -0.90316,-0.279949,0.32547,0.249085,0.173768,-0.386375, + -0.68646,-0.277096,0.672303,0.316229,0.114342,-0.309219, + -0.90316,-0.279949,0.32547,0.249085,0.173768,-0.386375, + -0.681322,-0.324401,0.656174,0.305709,0.170683,-0.291687, + -0.917766,-0.211835,0.335904,0.264292,0.115884,-0.395938, + -0.984639,-0.174604,0,0.24698,0.116398,-0.5, + -0.963203,-0.268774,0,0.23021,0.174796,-0.5, + -0.963203,-0.268774,0,0.23021,0.174796,-0.5, + -0.90316,-0.279949,0.32547,0.249085,0.173768,-0.386375, + -0.917766,-0.211835,0.335904,0.264292,0.115884,-0.395938, + -0.978535,-0.206083,0,0.212593,0.242461,-0.5, + -0.92222,-0.200492,0.330626,0.233342,0.240791,-0.374844, + -0.90316,-0.279949,0.32547,0.249085,0.173768,-0.386375, + -0.978535,-0.206083,0,0.212593,0.242461,-0.5, + -0.90316,-0.279949,0.32547,0.249085,0.173768,-0.386375, + -0.963203,-0.268774,0,0.23021,0.174796,-0.5, + -0.92222,-0.200492,0.330626,0.233342,0.240791,-0.374844, + -0.700275,-0.236966,0.673395,0.295589,0.235781,-0.270547, + -0.681322,-0.324401,0.656174,0.305709,0.170683,-0.291687, + -0.681322,-0.324401,0.656174,0.305709,0.170683,-0.291687, + -0.90316,-0.279949,0.32547,0.249085,0.173768,-0.386375, + -0.92222,-0.200492,0.330626,0.233342,0.240791,-0.374844, + -0.68646,-0.277096,0.672303,0.316229,0.114342,-0.309219, + -0.681322,-0.324401,0.656174,0.305709,0.170683,-0.291687, + -0.337162,-0.377107,0.862619,0.400082,0.165542,-0.234875, + -0.68646,-0.277096,0.672303,0.316229,0.114342,-0.309219, + -0.337162,-0.377107,0.862619,0.400082,0.165542,-0.234875, + -0.340489,-0.258832,0.903921,0.402791,0.111771,-0.257187, + -0.681322,-0.324401,0.656174,0.305709,0.170683,-0.291687, + -0.700275,-0.236966,0.673395,0.295589,0.235781,-0.270547, + -0.34835,-0.345034,0.871553,0.399335,0.22743,-0.207969, + -0.34835,-0.345034,0.871553,0.399335,0.22743,-0.207969, + -0.337162,-0.377107,0.862619,0.400082,0.165542,-0.234875, + -0.681322,-0.324401,0.656174,0.305709,0.170683,-0.291687, + -0.34835,-0.345034,0.871553,0.399335,0.22743,-0.207969, + -0.034164,-0.398975,0.916325,0.52383,0.217409,-0.187109, + -0.024814,-0.431443,0.901799,0.513329,0.159372,-0.215937, + -0.024814,-0.431443,0.901799,0.513329,0.159372,-0.215937, + -0.337162,-0.377107,0.862619,0.400082,0.165542,-0.234875, + -0.34835,-0.345034,0.871553,0.399335,0.22743,-0.207969, + -0.009985,-0.330184,0.943864,0.506665,0.108686,-0.239844, + -0.340489,-0.258832,0.903921,0.402791,0.111771,-0.257187, + -0.337162,-0.377107,0.862619,0.400082,0.165542,-0.234875, + -0.009985,-0.330184,0.943864,0.506665,0.108686,-0.239844, + -0.337162,-0.377107,0.862619,0.400082,0.165542,-0.234875, + -0.024814,-0.431443,0.901799,0.513329,0.159372,-0.215937, + -0.645198,0.198269,0.737841,0.308193,0.377118,-0.24425, + -0.328501,0.124794,0.936223,0.423113,0.361992,-0.1745, + -0.383319,-0.173246,0.907222,0.405397,0.294044,-0.185, + -0.645198,0.198269,0.737841,0.308193,0.377118,-0.24425, + -0.383319,-0.173246,0.907222,0.405397,0.294044,-0.185, + -0.746027,-0.030098,0.665236,0.293781,0.305853,-0.2525, + -0.328501,0.124794,0.936223,0.423113,0.361992,-0.1745, + 0.001894,-0.000875,0.999998,0.561017,0.343841,-0.15125, + -0.029604,-0.263,0.964342,0.539336,0.279873,-0.1625, + -0.029604,-0.263,0.964342,0.539336,0.279873,-0.1625, + -0.383319,-0.173246,0.907222,0.405397,0.294044,-0.185, + -0.328501,0.124794,0.936223,0.423113,0.361992,-0.1745, + -0.034164,-0.398975,0.916325,0.52383,0.217409,-0.187109, + -0.34835,-0.345034,0.871553,0.399335,0.22743,-0.207969, + -0.383319,-0.173246,0.907222,0.405397,0.294044,-0.185, + -0.034164,-0.398975,0.916325,0.52383,0.217409,-0.187109, + -0.383319,-0.173246,0.907222,0.405397,0.294044,-0.185, + -0.029604,-0.263,0.964342,0.539336,0.279873,-0.1625, + -0.700275,-0.236966,0.673395,0.295589,0.235781,-0.270547, + -0.746027,-0.030098,0.665236,0.293781,0.305853,-0.2525, + -0.383319,-0.173246,0.907222,0.405397,0.294044,-0.185, + -0.700275,-0.236966,0.673395,0.295589,0.235781,-0.270547, + -0.383319,-0.173246,0.907222,0.405397,0.294044,-0.185, + -0.34835,-0.345034,0.871553,0.399335,0.22743,-0.207969, + 0.330471,-0.133893,0.93427,0.69892,0.325689,-0.1745, + 0.63763,-0.234074,0.733919,0.81384,0.310563,-0.24425, + 0.603048,-0.457417,0.653531,0.78489,0.253894,-0.2525, + 0.603048,-0.457417,0.653531,0.78489,0.253894,-0.2525, + 0.285459,-0.369325,0.884371,0.673275,0.265703,-0.185, + 0.330471,-0.133893,0.93427,0.69892,0.325689,-0.1745, + 0.562306,-0.55594,0.612162,0.75207,0.199038,-0.270547, + 0.267074,-0.480259,0.835478,0.648325,0.207388,-0.207969, + 0.285459,-0.369325,0.884371,0.673275,0.265703,-0.185, + 0.562306,-0.55594,0.612162,0.75207,0.199038,-0.270547, + 0.285459,-0.369325,0.884371,0.673275,0.265703,-0.185, + 0.603048,-0.457417,0.653531,0.78489,0.253894,-0.2525, + 0.267074,-0.480259,0.835478,0.648325,0.207388,-0.207969, + -0.034164,-0.398975,0.916325,0.52383,0.217409,-0.187109, + -0.029604,-0.263,0.964342,0.539336,0.279873,-0.1625, + -0.029604,-0.263,0.964342,0.539336,0.279873,-0.1625, + 0.285459,-0.369325,0.884371,0.673275,0.265703,-0.185, + 0.267074,-0.480259,0.835478,0.648325,0.207388,-0.207969, + 0.001894,-0.000875,0.999998,0.561017,0.343841,-0.15125, + 0.330471,-0.133893,0.93427,0.69892,0.325689,-0.1745, + 0.285459,-0.369325,0.884371,0.673275,0.265703,-0.185, + 0.001894,-0.000875,0.999998,0.561017,0.343841,-0.15125, + 0.285459,-0.369325,0.884371,0.673275,0.265703,-0.185, + -0.029604,-0.263,0.964342,0.539336,0.279873,-0.1625, + 0.612462,-0.474038,0.632596,0.6971,0.103031,-0.309219, + 0.309535,-0.382382,0.870616,0.610539,0.105601,-0.257187, + 0.274839,-0.496479,0.823391,0.626577,0.153203,-0.234875, + 0.612462,-0.474038,0.632596,0.6971,0.103031,-0.309219, + 0.274839,-0.496479,0.823391,0.626577,0.153203,-0.234875, + 0.562162,-0.569598,0.59961,0.72095,0.148061,-0.291687, + 0.309535,-0.382382,0.870616,0.610539,0.105601,-0.257187, + -0.009985,-0.330184,0.943864,0.506665,0.108686,-0.239844, + -0.024814,-0.431443,0.901799,0.513329,0.159372,-0.215937, + -0.024814,-0.431443,0.901799,0.513329,0.159372,-0.215937, + 0.274839,-0.496479,0.823391,0.626577,0.153203,-0.234875, + 0.309535,-0.382382,0.870616,0.610539,0.105601,-0.257187, + -0.034164,-0.398975,0.916325,0.52383,0.217409,-0.187109, + 0.267074,-0.480259,0.835478,0.648325,0.207388,-0.207969, + 0.274839,-0.496479,0.823391,0.626577,0.153203,-0.234875, + -0.034164,-0.398975,0.916325,0.52383,0.217409,-0.187109, + 0.274839,-0.496479,0.823391,0.626577,0.153203,-0.234875, + -0.024814,-0.431443,0.901799,0.513329,0.159372,-0.215937, + 0.267074,-0.480259,0.835478,0.648325,0.207388,-0.207969, + 0.562306,-0.55594,0.612162,0.75207,0.199038,-0.270547, + 0.562162,-0.569598,0.59961,0.72095,0.148061,-0.291687, + 0.562162,-0.569598,0.59961,0.72095,0.148061,-0.291687, + 0.274839,-0.496479,0.823391,0.626577,0.153203,-0.234875, + 0.267074,-0.480259,0.835478,0.648325,0.207388,-0.207969, + 0.612462,-0.474038,0.632596,0.6971,0.103031,-0.309219, + 0.562162,-0.569598,0.59961,0.72095,0.148061,-0.291687, + 0.752224,-0.592299,0.288689,0.777574,0.144976,-0.386375, + 0.612462,-0.474038,0.632596,0.6971,0.103031,-0.309219, + 0.752224,-0.592299,0.288689,0.777574,0.144976,-0.386375, + 0.829185,-0.462729,0.313581,0.749037,0.101488,-0.395938, + 0.562162,-0.569598,0.59961,0.72095,0.148061,-0.291687, + 0.562306,-0.55594,0.612162,0.75207,0.199038,-0.270547, + 0.743616,-0.602792,0.28927,0.814318,0.194027,-0.374844, + 0.743616,-0.602792,0.28927,0.814318,0.194027,-0.374844, + 0.752224,-0.592299,0.288689,0.777574,0.144976,-0.386375, + 0.562162,-0.569598,0.59961,0.72095,0.148061,-0.291687, + 0.788677,-0.614808,0,0.835067,0.192357,-0.5, + 0.807803,-0.589452,0,0.796449,0.143948,-0.5, + 0.752224,-0.592299,0.288689,0.777574,0.144976,-0.386375, + 0.788677,-0.614808,0,0.835067,0.192357,-0.5, + 0.752224,-0.592299,0.288689,0.777574,0.144976,-0.386375, + 0.743616,-0.602792,0.28927,0.814318,0.194027,-0.374844, + 0.807803,-0.589452,0,0.796449,0.143948,-0.5, + 0.902893,-0.429866,0,0.766349,0.100974,-0.5, + 0.829185,-0.462729,0.313581,0.749037,0.101488,-0.395938, + 0.829185,-0.462729,0.313581,0.749037,0.101488,-0.395938, + 0.752224,-0.592299,0.288689,0.777574,0.144976,-0.386375, + 0.807803,-0.589452,0,0.796449,0.143948,-0.5, + 0.603048,-0.457417,0.653531,0.78489,0.253894,-0.2525, + 0.63763,-0.234074,0.733919,0.81384,0.310563,-0.24425, + 0.846641,-0.361408,0.39062,0.882792,0.301487,-0.3605, + 0.846641,-0.361408,0.39062,0.882792,0.301487,-0.3605, + 0.784719,-0.539182,0.305775,0.85186,0.246808,-0.365, + 0.603048,-0.457417,0.653531,0.78489,0.253894,-0.2525, + 0.918091,-0.39637,0,0.905776,0.298462,-0.5, + 0.822786,-0.568352,0,0.874183,0.244447,-0.5, + 0.784719,-0.539182,0.305775,0.85186,0.246808,-0.365, + 0.918091,-0.39637,0,0.905776,0.298462,-0.5, + 0.784719,-0.539182,0.305775,0.85186,0.246808,-0.365, + 0.846641,-0.361408,0.39062,0.882792,0.301487,-0.3605, + 0.822786,-0.568352,0,0.874183,0.244447,-0.5, + 0.788677,-0.614808,0,0.835067,0.192357,-0.5, + 0.743616,-0.602792,0.28927,0.814318,0.194027,-0.374844, + 0.743616,-0.602792,0.28927,0.814318,0.194027,-0.374844, + 0.784719,-0.539182,0.305775,0.85186,0.246808,-0.365, + 0.822786,-0.568352,0,0.874183,0.244447,-0.5, + 0.562306,-0.55594,0.612162,0.75207,0.199038,-0.270547, + 0.603048,-0.457417,0.653531,0.78489,0.253894,-0.2525, + 0.784719,-0.539182,0.305775,0.85186,0.246808,-0.365, + 0.562306,-0.55594,0.612162,0.75207,0.199038,-0.270547, + 0.784719,-0.539182,0.305775,0.85186,0.246808,-0.365, + 0.743616,-0.602792,0.28927,0.814318,0.194027,-0.374844, + 0.846641,-0.361408,-0.390619,0.882792,0.301487,-0.6395, + 0.63763,-0.234074,-0.733919,0.81384,0.310563,-0.75575, + 0.603048,-0.457417,-0.653531,0.78489,0.253894,-0.7475, + 0.603048,-0.457417,-0.653531,0.78489,0.253894,-0.7475, + 0.784719,-0.539182,-0.305775,0.85186,0.246808,-0.635, + 0.846641,-0.361408,-0.390619,0.882792,0.301487,-0.6395, + 0.562307,-0.55594,-0.612162,0.75207,0.199038,-0.729453, + 0.743616,-0.602791,-0.28927,0.814318,0.194027,-0.625156, + 0.784719,-0.539182,-0.305775,0.85186,0.246808,-0.635, + 0.562307,-0.55594,-0.612162,0.75207,0.199038,-0.729453, + 0.784719,-0.539182,-0.305775,0.85186,0.246808,-0.635, + 0.603048,-0.457417,-0.653531,0.78489,0.253894,-0.7475, + 0.743616,-0.602791,-0.28927,0.814318,0.194027,-0.625156, + 0.788677,-0.614808,0,0.835067,0.192357,-0.5, + 0.822786,-0.568352,0,0.874183,0.244447,-0.5, + 0.822786,-0.568352,0,0.874183,0.244447,-0.5, + 0.784719,-0.539182,-0.305775,0.85186,0.246808,-0.635, + 0.743616,-0.602791,-0.28927,0.814318,0.194027,-0.625156, + 0.918091,-0.39637,0,0.905776,0.298462,-0.5, + 0.846641,-0.361408,-0.390619,0.882792,0.301487,-0.6395, + 0.784719,-0.539182,-0.305775,0.85186,0.246808,-0.635, + 0.918091,-0.39637,0,0.905776,0.298462,-0.5, + 0.784719,-0.539182,-0.305775,0.85186,0.246808,-0.635, + 0.822786,-0.568352,0,0.874183,0.244447,-0.5, + 0.612462,-0.474039,-0.632596,0.6971,0.103031,-0.690781, + 0.829185,-0.462729,-0.313581,0.749037,0.101488,-0.604062, + 0.752224,-0.592299,-0.288689,0.777574,0.144976,-0.613625, + 0.612462,-0.474039,-0.632596,0.6971,0.103031,-0.690781, + 0.752224,-0.592299,-0.288689,0.777574,0.144976,-0.613625, + 0.562161,-0.569598,-0.59961,0.72095,0.148061,-0.708313, + 0.829185,-0.462729,-0.313581,0.749037,0.101488,-0.604062, + 0.902893,-0.429866,0,0.766349,0.100974,-0.5, + 0.807803,-0.589452,0,0.796449,0.143948,-0.5, + 0.807803,-0.589452,0,0.796449,0.143948,-0.5, + 0.752224,-0.592299,-0.288689,0.777574,0.144976,-0.613625, + 0.829185,-0.462729,-0.313581,0.749037,0.101488,-0.604062, + 0.788677,-0.614808,0,0.835067,0.192357,-0.5, + 0.743616,-0.602791,-0.28927,0.814318,0.194027,-0.625156, + 0.752224,-0.592299,-0.288689,0.777574,0.144976,-0.613625, + 0.788677,-0.614808,0,0.835067,0.192357,-0.5, + 0.752224,-0.592299,-0.288689,0.777574,0.144976,-0.613625, + 0.807803,-0.589452,0,0.796449,0.143948,-0.5, + 0.743616,-0.602791,-0.28927,0.814318,0.194027,-0.625156, + 0.562307,-0.55594,-0.612162,0.75207,0.199038,-0.729453, + 0.562161,-0.569598,-0.59961,0.72095,0.148061,-0.708313, + 0.562161,-0.569598,-0.59961,0.72095,0.148061,-0.708313, + 0.752224,-0.592299,-0.288689,0.777574,0.144976,-0.613625, + 0.743616,-0.602791,-0.28927,0.814318,0.194027,-0.625156, + 0.662382,-0.336592,0.669295,0.68609,0.066012,-0.316437, + 0.612462,-0.474038,0.632596,0.6971,0.103031,-0.309219, + 0.829185,-0.462729,0.313581,0.749037,0.101488,-0.395938, + 0.829185,-0.462729,0.313581,0.749037,0.101488,-0.395938, + 0.877019,-0.354062,0.324773,0.736115,0.065395,-0.399875, + 0.662382,-0.336592,0.669295,0.68609,0.066012,-0.316437, + 0.902893,-0.429866,0,0.766349,0.100974,-0.5, + 0.936513,-0.350633,0,0.75279,0.06519,-0.5, + 0.877019,-0.354062,0.324773,0.736115,0.065395,-0.399875, + 0.902893,-0.429866,0,0.766349,0.100974,-0.5, + 0.877019,-0.354062,0.324773,0.736115,0.065395,-0.399875, + 0.829185,-0.462729,0.313581,0.749037,0.101488,-0.395938, + 0.936513,-0.350633,0,0.75279,0.06519,-0.5, + 0.796583,-0.60453,0,0.742322,0.036664,-0.5, + 0.776532,-0.563325,0.282246,0.726029,0.037019,-0.403594, + 0.776532,-0.563325,0.282246,0.726029,0.037019,-0.403594, + 0.877019,-0.354062,0.324773,0.736115,0.065395,-0.399875, + 0.936513,-0.350633,0,0.75279,0.06519,-0.5, + 0.609651,-0.5022,0.613287,0.677491,0.037477,-0.323141, + 0.662382,-0.336592,0.669295,0.68609,0.066012,-0.316437, + 0.877019,-0.354062,0.324773,0.736115,0.065395,-0.399875, + 0.609651,-0.5022,0.613287,0.677491,0.037477,-0.323141, + 0.877019,-0.354062,0.324773,0.736115,0.065395,-0.399875, + 0.776532,-0.563325,0.282246,0.726029,0.037019,-0.403594, + 0.829185,-0.462729,-0.313581,0.749037,0.101488,-0.604062, + 0.612462,-0.474039,-0.632596,0.6971,0.103031,-0.690781, + 0.662382,-0.336592,-0.669295,0.68609,0.066012,-0.683563, + 0.662382,-0.336592,-0.669295,0.68609,0.066012,-0.683563, + 0.877019,-0.354062,-0.324773,0.736115,0.065395,-0.600125, + 0.829185,-0.462729,-0.313581,0.749037,0.101488,-0.604062, + 0.609651,-0.5022,-0.613287,0.677491,0.037477,-0.676859, + 0.776532,-0.563325,-0.282246,0.726029,0.037019,-0.596406, + 0.877019,-0.354062,-0.324773,0.736115,0.065395,-0.600125, + 0.609651,-0.5022,-0.613287,0.677491,0.037477,-0.676859, + 0.877019,-0.354062,-0.324773,0.736115,0.065395,-0.600125, + 0.662382,-0.336592,-0.669295,0.68609,0.066012,-0.683563, + 0.776532,-0.563325,-0.282246,0.726029,0.037019,-0.596406, + 0.796583,-0.60453,0,0.742322,0.036664,-0.5, + 0.936513,-0.350633,0,0.75279,0.06519,-0.5, + 0.936513,-0.350633,0,0.75279,0.06519,-0.5, + 0.877019,-0.354062,-0.324773,0.736115,0.065395,-0.600125, + 0.776532,-0.563325,-0.282246,0.726029,0.037019,-0.596406, + 0.902893,-0.429866,0,0.766349,0.100974,-0.5, + 0.829185,-0.462729,-0.313581,0.749037,0.101488,-0.604062, + 0.877019,-0.354062,-0.324773,0.736115,0.065395,-0.600125, + 0.902893,-0.429866,0,0.766349,0.100974,-0.5, + 0.877019,-0.354062,-0.324773,0.736115,0.065395,-0.600125, + 0.936513,-0.350633,0,0.75279,0.06519,-0.5, + 0.199329,-0.959446,-0.199329,0.638667,0.007537,-0.638667, + 0.18835,-0.976969,-0.100277,0.664625,0.003052,-0.5825, + 0.460562,-0.87149,-0.168487,0.706,0.016681,-0.5875, + 0.199329,-0.959446,-0.199329,0.638667,0.007537,-0.638667, + 0.460562,-0.87149,-0.168487,0.706,0.016681,-0.5875, + 0.392801,-0.830761,-0.394389,0.660875,0.017896,-0.660875, + 0.244558,-0.969635,0,0.677562,0.000839,-0.5, + 0.528671,-0.848827,0,0.7215,0.015465,-0.5, + 0.460562,-0.87149,-0.168487,0.706,0.016681,-0.5875, + 0.244558,-0.969635,0,0.677562,0.000839,-0.5, + 0.460562,-0.87149,-0.168487,0.706,0.016681,-0.5875, + 0.18835,-0.976969,-0.100277,0.664625,0.003052,-0.5825, + 0.796583,-0.60453,0,0.742322,0.036664,-0.5, + 0.776532,-0.563325,-0.282246,0.726029,0.037019,-0.596406, + 0.460562,-0.87149,-0.168487,0.706,0.016681,-0.5875, + 0.796583,-0.60453,0,0.742322,0.036664,-0.5, + 0.460562,-0.87149,-0.168487,0.706,0.016681,-0.5875, + 0.528671,-0.848827,0,0.7215,0.015465,-0.5, + 0.776532,-0.563325,-0.282246,0.726029,0.037019,-0.596406, + 0.609651,-0.5022,-0.613287,0.677491,0.037477,-0.676859, + 0.392801,-0.830761,-0.394389,0.660875,0.017896,-0.660875, + 0.392801,-0.830761,-0.394389,0.660875,0.017896,-0.660875, + 0.460562,-0.87149,-0.168487,0.706,0.016681,-0.5875, + 0.776532,-0.563325,-0.282246,0.726029,0.037019,-0.596406, + 0.199329,-0.959446,0.199329,0.638667,0.007537,-0.361333, + 0.392801,-0.830761,0.394389,0.660875,0.017896,-0.339125, + 0.460562,-0.87149,0.168487,0.706,0.016681,-0.4125, + 0.199329,-0.959446,0.199329,0.638667,0.007537,-0.361333, + 0.460562,-0.87149,0.168487,0.706,0.016681,-0.4125, + 0.18835,-0.976969,0.100277,0.664625,0.003052,-0.4175, + 0.392801,-0.830761,0.394389,0.660875,0.017896,-0.339125, + 0.609651,-0.5022,0.613287,0.677491,0.037477,-0.323141, + 0.776532,-0.563325,0.282246,0.726029,0.037019,-0.403594, + 0.776532,-0.563325,0.282246,0.726029,0.037019,-0.403594, + 0.460562,-0.87149,0.168487,0.706,0.016681,-0.4125, + 0.392801,-0.830761,0.394389,0.660875,0.017896,-0.339125, + 0.796583,-0.60453,0,0.742322,0.036664,-0.5, + 0.528671,-0.848827,0,0.7215,0.015465,-0.5, + 0.460562,-0.87149,0.168487,0.706,0.016681,-0.4125, + 0.796583,-0.60453,0,0.742322,0.036664,-0.5, + 0.460562,-0.87149,0.168487,0.706,0.016681,-0.4125, + 0.776532,-0.563325,0.282246,0.726029,0.037019,-0.403594, + 0.244558,-0.969635,0,0.677562,0.000839,-0.5, + 0.18835,-0.976969,0.100277,0.664625,0.003052,-0.4175, + 0.460562,-0.87149,0.168487,0.706,0.016681,-0.4125, + 0.244558,-0.969635,0,0.677562,0.000839,-0.5, + 0.460562,-0.87149,0.168487,0.706,0.016681,-0.4125, + 0.528671,-0.848827,0,0.7215,0.015465,-0.5, + 0.662382,-0.336592,-0.669295,0.68609,0.066012,-0.683563, + 0.612462,-0.474039,-0.632596,0.6971,0.103031,-0.690781, + 0.309535,-0.382382,-0.870616,0.610539,0.105601,-0.742813, + 0.309535,-0.382382,-0.870616,0.610539,0.105601,-0.742813, + 0.325986,-0.296158,-0.897788,0.602715,0.067041,-0.733625, + 0.662382,-0.336592,-0.669295,0.68609,0.066012,-0.683563, + -0.009985,-0.330184,-0.943864,0.506665,0.108686,-0.760156, + -0.003719,-0.252904,-0.967484,0.502666,0.068274,-0.750313, + 0.325986,-0.296158,-0.897788,0.602715,0.067041,-0.733625, + -0.009985,-0.330184,-0.943864,0.506665,0.108686,-0.760156, + 0.325986,-0.296158,-0.897788,0.602715,0.067041,-0.733625, + 0.309535,-0.382382,-0.870616,0.610539,0.105601,-0.742813, + -0.003719,-0.252904,-0.967484,0.502666,0.068274,-0.750313, + -0.025551,-0.524875,-0.850796,0.500666,0.037435,-0.741703, + 0.28571,-0.534951,-0.795108,0.597054,0.03743,-0.725406, + 0.28571,-0.534951,-0.795108,0.597054,0.03743,-0.725406, + 0.325986,-0.296158,-0.897788,0.602715,0.067041,-0.733625, + -0.003719,-0.252904,-0.967484,0.502666,0.068274,-0.750313, + 0.609651,-0.5022,-0.613287,0.677491,0.037477,-0.676859, + 0.662382,-0.336592,-0.669295,0.68609,0.066012,-0.683563, + 0.325986,-0.296158,-0.897788,0.602715,0.067041,-0.733625, + 0.609651,-0.5022,-0.613287,0.677491,0.037477,-0.676859, + 0.325986,-0.296158,-0.897788,0.602715,0.067041,-0.733625, + 0.28571,-0.534951,-0.795108,0.597054,0.03743,-0.725406, + -0.340489,-0.258832,-0.903921,0.402791,0.111771,-0.742813, + -0.68646,-0.277096,-0.672303,0.316229,0.114342,-0.690781, + -0.696634,-0.190085,-0.691787,0.319242,0.070537,-0.683563, + -0.696634,-0.190085,-0.691787,0.319242,0.070537,-0.683563, + -0.33904,-0.236102,-0.910663,0.402616,0.069508,-0.733625, + -0.340489,-0.258832,-0.903921,0.402791,0.111771,-0.742813, + -0.643521,-0.419436,-0.640277,0.323842,0.038608,-0.676859, + -0.321508,-0.547444,-0.772617,0.404279,0.038047,-0.725406, + -0.33904,-0.236102,-0.910663,0.402616,0.069508,-0.733625, + -0.643521,-0.419436,-0.640277,0.323842,0.038608,-0.676859, + -0.33904,-0.236102,-0.910663,0.402616,0.069508,-0.733625, + -0.696634,-0.190085,-0.691787,0.319242,0.070537,-0.683563, + -0.025551,-0.524875,-0.850796,0.500666,0.037435,-0.741703, + -0.003719,-0.252904,-0.967484,0.502666,0.068274,-0.750313, + -0.33904,-0.236102,-0.910663,0.402616,0.069508,-0.733625, + -0.025551,-0.524875,-0.850796,0.500666,0.037435,-0.741703, + -0.33904,-0.236102,-0.910663,0.402616,0.069508,-0.733625, + -0.321508,-0.547444,-0.772617,0.404279,0.038047,-0.725406, + -0.003719,-0.252904,-0.967484,0.502666,0.068274,-0.750313, + -0.009985,-0.330184,-0.943864,0.506665,0.108686,-0.760156, + -0.340489,-0.258832,-0.903921,0.402791,0.111771,-0.742813, + -0.340489,-0.258832,-0.903921,0.402791,0.111771,-0.742813, + -0.33904,-0.236102,-0.910663,0.402616,0.069508,-0.733625, + -0.003719,-0.252904,-0.967484,0.502666,0.068274,-0.750313, + -0.199329,-0.959446,-0.199329,0.361333,0.007537,-0.638667, + -0.100277,-0.976969,-0.18835,0.4175,0.003052,-0.664625, + -0.173348,-0.862844,-0.474818,0.4125,0.016681,-0.706, + -0.199329,-0.959446,-0.199329,0.361333,0.007537,-0.638667, + -0.173348,-0.862844,-0.474818,0.4125,0.016681,-0.706, + -0.412793,-0.812756,-0.411133,0.339125,0.017896,-0.660875, + 0,-0.969635,-0.244558,0.5,0.000839,-0.677562, + -0.000173,-0.840077,-0.542467,0.5,0.015465,-0.7215, + -0.173348,-0.862844,-0.474818,0.4125,0.016681,-0.706, + 0,-0.969635,-0.244558,0.5,0.000839,-0.677562, + -0.173348,-0.862844,-0.474818,0.4125,0.016681,-0.706, + -0.100277,-0.976969,-0.18835,0.4175,0.003052,-0.664625, + -0.025551,-0.524875,-0.850796,0.500666,0.037435,-0.741703, + -0.321508,-0.547444,-0.772617,0.404279,0.038047,-0.725406, + -0.173348,-0.862844,-0.474818,0.4125,0.016681,-0.706, + -0.025551,-0.524875,-0.850796,0.500666,0.037435,-0.741703, + -0.173348,-0.862844,-0.474818,0.4125,0.016681,-0.706, + -0.000173,-0.840077,-0.542467,0.5,0.015465,-0.7215, + -0.321508,-0.547444,-0.772617,0.404279,0.038047,-0.725406, + -0.643521,-0.419436,-0.640277,0.323842,0.038608,-0.676859, + -0.412793,-0.812756,-0.411133,0.339125,0.017896,-0.660875, + -0.412793,-0.812756,-0.411133,0.339125,0.017896,-0.660875, + -0.173348,-0.862844,-0.474818,0.4125,0.016681,-0.706, + -0.321508,-0.547444,-0.772617,0.404279,0.038047,-0.725406, + 0.199329,-0.959446,-0.199329,0.638667,0.007537,-0.638667, + 0.392801,-0.830761,-0.394389,0.660875,0.017896,-0.660875, + 0.170214,-0.866923,-0.468478,0.5875,0.016681,-0.706, + 0.199329,-0.959446,-0.199329,0.638667,0.007537,-0.638667, + 0.170214,-0.866923,-0.468478,0.5875,0.016681,-0.706, + 0.100277,-0.976969,-0.18835,0.5825,0.003052,-0.664625, + 0.392801,-0.830761,-0.394389,0.660875,0.017896,-0.660875, + 0.609651,-0.5022,-0.613287,0.677491,0.037477,-0.676859, + 0.28571,-0.534951,-0.795108,0.597054,0.03743,-0.725406, + 0.28571,-0.534951,-0.795108,0.597054,0.03743,-0.725406, + 0.170214,-0.866923,-0.468478,0.5875,0.016681,-0.706, + 0.392801,-0.830761,-0.394389,0.660875,0.017896,-0.660875, + -0.025551,-0.524875,-0.850796,0.500666,0.037435,-0.741703, + -0.000173,-0.840077,-0.542467,0.5,0.015465,-0.7215, + 0.170214,-0.866923,-0.468478,0.5875,0.016681,-0.706, + -0.025551,-0.524875,-0.850796,0.500666,0.037435,-0.741703, + 0.170214,-0.866923,-0.468478,0.5875,0.016681,-0.706, + 0.28571,-0.534951,-0.795108,0.597054,0.03743,-0.725406, + 0,-0.969635,-0.244558,0.5,0.000839,-0.677562, + 0.100277,-0.976969,-0.18835,0.5825,0.003052,-0.664625, + 0.170214,-0.866923,-0.468478,0.5875,0.016681,-0.706, + 0,-0.969635,-0.244558,0.5,0.000839,-0.677562, + 0.170214,-0.866923,-0.468478,0.5875,0.016681,-0.706, + -0.000173,-0.840077,-0.542467,0.5,0.015465,-0.7215, + -0.696634,-0.190085,-0.691787,0.319242,0.070537,-0.683563, + -0.68646,-0.277096,-0.672303,0.316229,0.114342,-0.690781, + -0.917766,-0.211835,-0.335904,0.264292,0.115884,-0.604062, + -0.917766,-0.211835,-0.335904,0.264292,0.115884,-0.604062, + -0.92467,-0.172819,-0.339293,0.269217,0.071154,-0.600125, + -0.696634,-0.190085,-0.691787,0.319242,0.070537,-0.683563, + -0.984639,-0.174604,0,0.24698,0.116398,-0.5, + -0.985139,-0.171761,0,0.252542,0.071359,-0.5, + -0.92467,-0.172819,-0.339293,0.269217,0.071154,-0.600125, + -0.984639,-0.174604,0,0.24698,0.116398,-0.5, + -0.92467,-0.172819,-0.339293,0.269217,0.071154,-0.600125, + -0.917766,-0.211835,-0.335904,0.264292,0.115884,-0.604062, + -0.985139,-0.171761,0,0.252542,0.071359,-0.5, + -0.851281,-0.524711,0,0.25901,0.038206,-0.5, + -0.829046,-0.471849,-0.300069,0.275304,0.038459,-0.596406, + -0.829046,-0.471849,-0.300069,0.275304,0.038459,-0.596406, + -0.92467,-0.172819,-0.339293,0.269217,0.071154,-0.600125, + -0.985139,-0.171761,0,0.252542,0.071359,-0.5, + -0.643521,-0.419436,-0.640277,0.323842,0.038608,-0.676859, + -0.696634,-0.190085,-0.691787,0.319242,0.070537,-0.683563, + -0.92467,-0.172819,-0.339293,0.269217,0.071154,-0.600125, + -0.643521,-0.419436,-0.640277,0.323842,0.038608,-0.676859, + -0.92467,-0.172819,-0.339293,0.269217,0.071154,-0.600125, + -0.829046,-0.471849,-0.300069,0.275304,0.038459,-0.596406, + -0.917766,-0.211835,0.335904,0.264292,0.115884,-0.395938, + -0.68646,-0.277096,0.672303,0.316229,0.114342,-0.309219, + -0.696634,-0.190085,0.691786,0.319242,0.070537,-0.316437, + -0.696634,-0.190085,0.691786,0.319242,0.070537,-0.316437, + -0.92467,-0.172819,0.339293,0.269217,0.071154,-0.399875, + -0.917766,-0.211835,0.335904,0.264292,0.115884,-0.395938, + -0.643521,-0.419436,0.640277,0.323842,0.038608,-0.323141, + -0.829046,-0.471848,0.300069,0.275304,0.038459,-0.403594, + -0.92467,-0.172819,0.339293,0.269217,0.071154,-0.399875, + -0.643521,-0.419436,0.640277,0.323842,0.038608,-0.323141, + -0.92467,-0.172819,0.339293,0.269217,0.071154,-0.399875, + -0.696634,-0.190085,0.691786,0.319242,0.070537,-0.316437, + -0.829046,-0.471848,0.300069,0.275304,0.038459,-0.403594, + -0.851281,-0.524711,0,0.25901,0.038206,-0.5, + -0.985139,-0.171761,0,0.252542,0.071359,-0.5, + -0.985139,-0.171761,0,0.252542,0.071359,-0.5, + -0.92467,-0.172819,0.339293,0.269217,0.071154,-0.399875, + -0.829046,-0.471848,0.300069,0.275304,0.038459,-0.403594, + -0.984639,-0.174604,0,0.24698,0.116398,-0.5, + -0.917766,-0.211835,0.335904,0.264292,0.115884,-0.395938, + -0.92467,-0.172819,0.339293,0.269217,0.071154,-0.399875, + -0.984639,-0.174604,0,0.24698,0.116398,-0.5, + -0.92467,-0.172819,0.339293,0.269217,0.071154,-0.399875, + -0.985139,-0.171761,0,0.252542,0.071359,-0.5, + -0.199328,-0.959446,0.199328,0.361333,0.007537,-0.361333, + -0.188349,-0.976969,0.100277,0.335375,0.003052,-0.4175, + -0.483213,-0.857792,0.175209,0.294,0.016681,-0.4125, + -0.199328,-0.959446,0.199328,0.361333,0.007537,-0.361333, + -0.483213,-0.857792,0.175209,0.294,0.016681,-0.4125, + -0.412793,-0.812756,0.411133,0.339125,0.017896,-0.339125, + -0.244558,-0.969635,0,0.322437,0.000839,-0.5, + -0.556955,-0.830542,0,0.2785,0.015465,-0.5, + -0.483213,-0.857792,0.175209,0.294,0.016681,-0.4125, + -0.244558,-0.969635,0,0.322437,0.000839,-0.5, + -0.483213,-0.857792,0.175209,0.294,0.016681,-0.4125, + -0.188349,-0.976969,0.100277,0.335375,0.003052,-0.4175, + -0.851281,-0.524711,0,0.25901,0.038206,-0.5, + -0.829046,-0.471848,0.300069,0.275304,0.038459,-0.403594, + -0.483213,-0.857792,0.175209,0.294,0.016681,-0.4125, + -0.851281,-0.524711,0,0.25901,0.038206,-0.5, + -0.483213,-0.857792,0.175209,0.294,0.016681,-0.4125, + -0.556955,-0.830542,0,0.2785,0.015465,-0.5, + -0.829046,-0.471848,0.300069,0.275304,0.038459,-0.403594, + -0.643521,-0.419436,0.640277,0.323842,0.038608,-0.323141, + -0.412793,-0.812756,0.411133,0.339125,0.017896,-0.339125, + -0.412793,-0.812756,0.411133,0.339125,0.017896,-0.339125, + -0.483213,-0.857792,0.175209,0.294,0.016681,-0.4125, + -0.829046,-0.471848,0.300069,0.275304,0.038459,-0.403594, + -0.199329,-0.959446,-0.199329,0.361333,0.007537,-0.638667, + -0.412793,-0.812756,-0.411133,0.339125,0.017896,-0.660875, + -0.483213,-0.857792,-0.17521,0.294,0.016681,-0.5875, + -0.199329,-0.959446,-0.199329,0.361333,0.007537,-0.638667, + -0.483213,-0.857792,-0.17521,0.294,0.016681,-0.5875, + -0.188349,-0.976969,-0.100277,0.335375,0.003052,-0.5825, + -0.412793,-0.812756,-0.411133,0.339125,0.017896,-0.660875, + -0.643521,-0.419436,-0.640277,0.323842,0.038608,-0.676859, + -0.829046,-0.471849,-0.300069,0.275304,0.038459,-0.596406, + -0.829046,-0.471849,-0.300069,0.275304,0.038459,-0.596406, + -0.483213,-0.857792,-0.17521,0.294,0.016681,-0.5875, + -0.412793,-0.812756,-0.411133,0.339125,0.017896,-0.660875, + -0.851281,-0.524711,0,0.25901,0.038206,-0.5, + -0.556955,-0.830542,0,0.2785,0.015465,-0.5, + -0.483213,-0.857792,-0.17521,0.294,0.016681,-0.5875, + -0.851281,-0.524711,0,0.25901,0.038206,-0.5, + -0.483213,-0.857792,-0.17521,0.294,0.016681,-0.5875, + -0.829046,-0.471849,-0.300069,0.275304,0.038459,-0.596406, + -0.244558,-0.969635,0,0.322437,0.000839,-0.5, + -0.188349,-0.976969,-0.100277,0.335375,0.003052,-0.5825, + -0.483213,-0.857792,-0.17521,0.294,0.016681,-0.5875, + -0.244558,-0.969635,0,0.322437,0.000839,-0.5, + -0.483213,-0.857792,-0.17521,0.294,0.016681,-0.5875, + -0.556955,-0.830542,0,0.2785,0.015465,-0.5, + -0.696634,-0.190085,0.691786,0.319242,0.070537,-0.316437, + -0.68646,-0.277096,0.672303,0.316229,0.114342,-0.309219, + -0.340489,-0.258832,0.903921,0.402791,0.111771,-0.257187, + -0.340489,-0.258832,0.903921,0.402791,0.111771,-0.257187, + -0.339041,-0.236102,0.910663,0.402616,0.069508,-0.266375, + -0.696634,-0.190085,0.691786,0.319242,0.070537,-0.316437, + -0.340489,-0.258832,0.903921,0.402791,0.111771,-0.257187, + -0.009985,-0.330184,0.943864,0.506665,0.108686,-0.239844, + -0.003719,-0.252904,0.967484,0.502666,0.068274,-0.249687, + -0.003719,-0.252904,0.967484,0.502666,0.068274,-0.249687, + -0.339041,-0.236102,0.910663,0.402616,0.069508,-0.266375, + -0.340489,-0.258832,0.903921,0.402791,0.111771,-0.257187, + -0.025551,-0.524875,0.850796,0.500666,0.037435,-0.258297, + -0.321508,-0.547444,0.772617,0.404279,0.038047,-0.274594, + -0.339041,-0.236102,0.910663,0.402616,0.069508,-0.266375, + -0.025551,-0.524875,0.850796,0.500666,0.037435,-0.258297, + -0.339041,-0.236102,0.910663,0.402616,0.069508,-0.266375, + -0.003719,-0.252904,0.967484,0.502666,0.068274,-0.249687, + -0.643521,-0.419436,0.640277,0.323842,0.038608,-0.323141, + -0.696634,-0.190085,0.691786,0.319242,0.070537,-0.316437, + -0.339041,-0.236102,0.910663,0.402616,0.069508,-0.266375, + -0.643521,-0.419436,0.640277,0.323842,0.038608,-0.323141, + -0.339041,-0.236102,0.910663,0.402616,0.069508,-0.266375, + -0.321508,-0.547444,0.772617,0.404279,0.038047,-0.274594, + 0.309535,-0.382382,0.870616,0.610539,0.105601,-0.257187, + 0.612462,-0.474038,0.632596,0.6971,0.103031,-0.309219, + 0.662382,-0.336592,0.669295,0.68609,0.066012,-0.316437, + 0.662382,-0.336592,0.669295,0.68609,0.066012,-0.316437, + 0.325986,-0.296157,0.897788,0.602715,0.067041,-0.266375, + 0.309535,-0.382382,0.870616,0.610539,0.105601,-0.257187, + 0.609651,-0.5022,0.613287,0.677491,0.037477,-0.323141, + 0.28571,-0.534951,0.795108,0.597054,0.03743,-0.274594, + 0.325986,-0.296157,0.897788,0.602715,0.067041,-0.266375, + 0.609651,-0.5022,0.613287,0.677491,0.037477,-0.323141, + 0.325986,-0.296157,0.897788,0.602715,0.067041,-0.266375, + 0.662382,-0.336592,0.669295,0.68609,0.066012,-0.316437, + 0.28571,-0.534951,0.795108,0.597054,0.03743,-0.274594, + -0.025551,-0.524875,0.850796,0.500666,0.037435,-0.258297, + -0.003719,-0.252904,0.967484,0.502666,0.068274,-0.249687, + -0.003719,-0.252904,0.967484,0.502666,0.068274,-0.249687, + 0.325986,-0.296157,0.897788,0.602715,0.067041,-0.266375, + 0.28571,-0.534951,0.795108,0.597054,0.03743,-0.274594, + -0.009985,-0.330184,0.943864,0.506665,0.108686,-0.239844, + 0.309535,-0.382382,0.870616,0.610539,0.105601,-0.257187, + 0.325986,-0.296157,0.897788,0.602715,0.067041,-0.266375, + -0.009985,-0.330184,0.943864,0.506665,0.108686,-0.239844, + 0.325986,-0.296157,0.897788,0.602715,0.067041,-0.266375, + -0.003719,-0.252904,0.967484,0.502666,0.068274,-0.249687, + 0.199329,-0.959446,0.199329,0.638667,0.007537,-0.361333, + 0.100277,-0.976969,0.188349,0.5825,0.003052,-0.335375, + 0.170214,-0.866923,0.468477,0.5875,0.016681,-0.294, + 0.199329,-0.959446,0.199329,0.638667,0.007537,-0.361333, + 0.170214,-0.866923,0.468477,0.5875,0.016681,-0.294, + 0.392801,-0.830761,0.394389,0.660875,0.017896,-0.339125, + 0,-0.969635,0.244558,0.5,0.000839,-0.322437, + -0.000173,-0.840077,0.542467,0.5,0.015465,-0.2785, + 0.170214,-0.866923,0.468477,0.5875,0.016681,-0.294, + 0,-0.969635,0.244558,0.5,0.000839,-0.322437, + 0.170214,-0.866923,0.468477,0.5875,0.016681,-0.294, + 0.100277,-0.976969,0.188349,0.5825,0.003052,-0.335375, + -0.025551,-0.524875,0.850796,0.500666,0.037435,-0.258297, + 0.28571,-0.534951,0.795108,0.597054,0.03743,-0.274594, + 0.170214,-0.866923,0.468477,0.5875,0.016681,-0.294, + -0.025551,-0.524875,0.850796,0.500666,0.037435,-0.258297, + 0.170214,-0.866923,0.468477,0.5875,0.016681,-0.294, + -0.000173,-0.840077,0.542467,0.5,0.015465,-0.2785, + 0.28571,-0.534951,0.795108,0.597054,0.03743,-0.274594, + 0.609651,-0.5022,0.613287,0.677491,0.037477,-0.323141, + 0.392801,-0.830761,0.394389,0.660875,0.017896,-0.339125, + 0.392801,-0.830761,0.394389,0.660875,0.017896,-0.339125, + 0.170214,-0.866923,0.468477,0.5875,0.016681,-0.294, + 0.28571,-0.534951,0.795108,0.597054,0.03743,-0.274594, + -0.199328,-0.959446,0.199328,0.361333,0.007537,-0.361333, + -0.412793,-0.812756,0.411133,0.339125,0.017896,-0.339125, + -0.173348,-0.862844,0.474817,0.4125,0.016681,-0.294, + -0.199328,-0.959446,0.199328,0.361333,0.007537,-0.361333, + -0.173348,-0.862844,0.474817,0.4125,0.016681,-0.294, + -0.100277,-0.976969,0.188349,0.4175,0.003052,-0.335375, + -0.412793,-0.812756,0.411133,0.339125,0.017896,-0.339125, + -0.643521,-0.419436,0.640277,0.323842,0.038608,-0.323141, + -0.321508,-0.547444,0.772617,0.404279,0.038047,-0.274594, + -0.321508,-0.547444,0.772617,0.404279,0.038047,-0.274594, + -0.173348,-0.862844,0.474817,0.4125,0.016681,-0.294, + -0.412793,-0.812756,0.411133,0.339125,0.017896,-0.339125, + -0.025551,-0.524875,0.850796,0.500666,0.037435,-0.258297, + -0.000173,-0.840077,0.542467,0.5,0.015465,-0.2785, + -0.173348,-0.862844,0.474817,0.4125,0.016681,-0.294, + -0.025551,-0.524875,0.850796,0.500666,0.037435,-0.258297, + -0.173348,-0.862844,0.474817,0.4125,0.016681,-0.294, + -0.321508,-0.547444,0.772617,0.404279,0.038047,-0.274594, + 0,-0.969635,0.244558,0.5,0.000839,-0.322437, + -0.100277,-0.976969,0.188349,0.4175,0.003052,-0.335375, + -0.173348,-0.862844,0.474817,0.4125,0.016681,-0.294, + 0,-0.969635,0.244558,0.5,0.000839,-0.322437, + -0.173348,-0.862844,0.474817,0.4125,0.016681,-0.294, + -0.000173,-0.840077,0.542467,0.5,0.015465,-0.2785, + 0.199329,-0.959446,-0.199329,0.638667,0.007537,-0.638667, + 0.100277,-0.976969,-0.18835,0.5825,0.003052,-0.664625, + 0.079739,-0.993621,-0.079739,0.5905,-0.005194,-0.5905, + 0.199329,-0.959446,-0.199329,0.638667,0.007537,-0.638667, + 0.079739,-0.993621,-0.079739,0.5905,-0.005194,-0.5905, + 0.18835,-0.976969,-0.100277,0.664625,0.003052,-0.5825, + 0.100277,-0.976969,-0.18835,0.5825,0.003052,-0.664625, + 0,-0.969635,-0.244558,0.5,0.000839,-0.677562, + 0,-0.996384,-0.08496,0.5,-0.007972,-0.59775, + 0,-0.996384,-0.08496,0.5,-0.007972,-0.59775, + 0.079739,-0.993621,-0.079739,0.5905,-0.005194,-0.5905, + 0.100277,-0.976969,-0.18835,0.5825,0.003052,-0.664625, + 0,-1,0,0.5,-0.010924,-0.5, + 0.08496,-0.996384,0,0.59775,-0.007972,-0.5, + 0.079739,-0.993621,-0.079739,0.5905,-0.005194,-0.5905, + 0,-1,0,0.5,-0.010924,-0.5, + 0.079739,-0.993621,-0.079739,0.5905,-0.005194,-0.5905, + 0,-0.996384,-0.08496,0.5,-0.007972,-0.59775, + 0.08496,-0.996384,0,0.59775,-0.007972,-0.5, + 0.244558,-0.969635,0,0.677562,0.000839,-0.5, + 0.18835,-0.976969,-0.100277,0.664625,0.003052,-0.5825, + 0.18835,-0.976969,-0.100277,0.664625,0.003052,-0.5825, + 0.079739,-0.993621,-0.079739,0.5905,-0.005194,-0.5905, + 0.08496,-0.996384,0,0.59775,-0.007972,-0.5, + -0.199329,-0.959446,-0.199329,0.361333,0.007537,-0.638667, + -0.188349,-0.976969,-0.100277,0.335375,0.003052,-0.5825, + -0.079739,-0.993621,-0.079739,0.4095,-0.005194,-0.5905, + -0.199329,-0.959446,-0.199329,0.361333,0.007537,-0.638667, + -0.079739,-0.993621,-0.079739,0.4095,-0.005194,-0.5905, + -0.100277,-0.976969,-0.18835,0.4175,0.003052,-0.664625, + -0.188349,-0.976969,-0.100277,0.335375,0.003052,-0.5825, + -0.244558,-0.969635,0,0.322437,0.000839,-0.5, + -0.08496,-0.996384,0,0.40225,-0.007972,-0.5, + -0.08496,-0.996384,0,0.40225,-0.007972,-0.5, + -0.079739,-0.993621,-0.079739,0.4095,-0.005194,-0.5905, + -0.188349,-0.976969,-0.100277,0.335375,0.003052,-0.5825, + 0,-1,0,0.5,-0.010924,-0.5, + 0,-0.996384,-0.08496,0.5,-0.007972,-0.59775, + -0.079739,-0.993621,-0.079739,0.4095,-0.005194,-0.5905, + 0,-1,0,0.5,-0.010924,-0.5, + -0.079739,-0.993621,-0.079739,0.4095,-0.005194,-0.5905, + -0.08496,-0.996384,0,0.40225,-0.007972,-0.5, + 0,-0.996384,-0.08496,0.5,-0.007972,-0.59775, + 0,-0.969635,-0.244558,0.5,0.000839,-0.677562, + -0.100277,-0.976969,-0.18835,0.4175,0.003052,-0.664625, + -0.100277,-0.976969,-0.18835,0.4175,0.003052,-0.664625, + -0.079739,-0.993621,-0.079739,0.4095,-0.005194,-0.5905, + 0,-0.996384,-0.08496,0.5,-0.007972,-0.59775, + -0.199328,-0.959446,0.199328,0.361333,0.007537,-0.361333, + -0.100277,-0.976969,0.188349,0.4175,0.003052,-0.335375, + -0.079739,-0.993621,0.079739,0.4095,-0.005194,-0.4095, + -0.199328,-0.959446,0.199328,0.361333,0.007537,-0.361333, + -0.079739,-0.993621,0.079739,0.4095,-0.005194,-0.4095, + -0.188349,-0.976969,0.100277,0.335375,0.003052,-0.4175, + -0.100277,-0.976969,0.188349,0.4175,0.003052,-0.335375, + 0,-0.969635,0.244558,0.5,0.000839,-0.322437, + 0,-0.996384,0.08496,0.5,-0.007972,-0.40225, + 0,-0.996384,0.08496,0.5,-0.007972,-0.40225, + -0.079739,-0.993621,0.079739,0.4095,-0.005194,-0.4095, + -0.100277,-0.976969,0.188349,0.4175,0.003052,-0.335375, + 0,-1,0,0.5,-0.010924,-0.5, + -0.08496,-0.996384,0,0.40225,-0.007972,-0.5, + -0.079739,-0.993621,0.079739,0.4095,-0.005194,-0.4095, + 0,-1,0,0.5,-0.010924,-0.5, + -0.079739,-0.993621,0.079739,0.4095,-0.005194,-0.4095, + 0,-0.996384,0.08496,0.5,-0.007972,-0.40225, + -0.08496,-0.996384,0,0.40225,-0.007972,-0.5, + -0.244558,-0.969635,0,0.322437,0.000839,-0.5, + -0.188349,-0.976969,0.100277,0.335375,0.003052,-0.4175, + -0.188349,-0.976969,0.100277,0.335375,0.003052,-0.4175, + -0.079739,-0.993621,0.079739,0.4095,-0.005194,-0.4095, + -0.08496,-0.996384,0,0.40225,-0.007972,-0.5, + 0.199329,-0.959446,0.199329,0.638667,0.007537,-0.361333, + 0.18835,-0.976969,0.100277,0.664625,0.003052,-0.4175, + 0.079739,-0.993621,0.079739,0.5905,-0.005194,-0.4095, + 0.199329,-0.959446,0.199329,0.638667,0.007537,-0.361333, + 0.079739,-0.993621,0.079739,0.5905,-0.005194,-0.4095, + 0.100277,-0.976969,0.188349,0.5825,0.003052,-0.335375, + 0.18835,-0.976969,0.100277,0.664625,0.003052,-0.4175, + 0.244558,-0.969635,0,0.677562,0.000839,-0.5, + 0.08496,-0.996384,0,0.59775,-0.007972,-0.5, + 0.08496,-0.996384,0,0.59775,-0.007972,-0.5, + 0.079739,-0.993621,0.079739,0.5905,-0.005194,-0.4095, + 0.18835,-0.976969,0.100277,0.664625,0.003052,-0.4175, + 0,-1,0,0.5,-0.010924,-0.5, + 0,-0.996384,0.08496,0.5,-0.007972,-0.40225, + 0.079739,-0.993621,0.079739,0.5905,-0.005194,-0.4095, + 0,-1,0,0.5,-0.010924,-0.5, + 0.079739,-0.993621,0.079739,0.5905,-0.005194,-0.4095, + 0.08496,-0.996384,0,0.59775,-0.007972,-0.5, + 0,-0.996384,0.08496,0.5,-0.007972,-0.40225, + 0,-0.969635,0.244558,0.5,0.000839,-0.322437, + 0.100277,-0.976969,0.188349,0.5825,0.003052,-0.335375, + 0.100277,-0.976969,0.188349,0.5825,0.003052,-0.335375, + 0.079739,-0.993621,0.079739,0.5905,-0.005194,-0.4095, + 0,-0.996384,0.08496,0.5,-0.007972,-0.40225, +}; +static const struct gllist frame={GL_N3F_V3F,GL_TRIANGLES,1728,data,NULL}; +const struct gllist *s1_2=&frame; diff --git a/hacks/glx/s1_3.c b/hacks/glx/s1_3.c new file mode 100644 index 00000000..eea1304c --- /dev/null +++ b/hacks/glx/s1_3.c @@ -0,0 +1,1733 @@ +#include "gllist.h" +static const float data[]={ + 0.202525,-0.691948,-0.692959,1.163707,0.362839,-0.676509, + 0.133481,-0.728232,-0.672207,1.115671,0.352342,-0.673147, + 0.164983,-0.93415,-0.316457,1.139957,0.313586,-0.594444, + 0.164983,-0.93415,-0.316457,1.139957,0.313586,-0.594444, + 0.257435,-0.906571,-0.334448,1.188046,0.322006,-0.596277, + 0.202525,-0.691948,-0.692959,1.163707,0.362839,-0.676509, + 0.166954,-0.985965,0,1.148052,0.300668,-0.5, + 0.301979,-0.953315,0,1.196159,0.308395,-0.5, + 0.257435,-0.906571,-0.334448,1.188046,0.322006,-0.596277, + 0.166954,-0.985965,0,1.148052,0.300668,-0.5, + 0.257435,-0.906571,-0.334448,1.188046,0.322006,-0.596277, + 0.164983,-0.93415,-0.316457,1.139957,0.313586,-0.594444, + 0.301979,-0.953315,0,1.196159,0.308395,-0.5, + 0.780431,-0.625241,0,1.227578,0.320768,-0.5, + 0.622801,-0.721415,-0.302786,1.219224,0.33452,-0.595444, + 0.622801,-0.721415,-0.302786,1.219224,0.33452,-0.595444, + 0.257435,-0.906571,-0.334448,1.188046,0.322006,-0.596277, + 0.301979,-0.953315,0,1.196159,0.308395,-0.5, + 0.631576,-0.472875,-0.614411,1.194861,0.37578,-0.675096, + 0.202525,-0.691948,-0.692959,1.163707,0.362839,-0.676509, + 0.257435,-0.906571,-0.334448,1.188046,0.322006,-0.596277, + 0.631576,-0.472875,-0.614411,1.194861,0.37578,-0.675096, + 0.257435,-0.906571,-0.334448,1.188046,0.322006,-0.596277, + 0.622801,-0.721415,-0.302786,1.219224,0.33452,-0.595444, + 0.164983,-0.93415,0.316457,1.139957,0.313586,-0.405556, + 0.133481,-0.728232,0.672206,1.115671,0.352342,-0.326853, + 0.202524,-0.691948,0.692959,1.163707,0.362839,-0.323491, + 0.202524,-0.691948,0.692959,1.163707,0.362839,-0.323491, + 0.257435,-0.906571,0.334448,1.188046,0.322006,-0.403722, + 0.164983,-0.93415,0.316457,1.139957,0.313586,-0.405556, + 0.631575,-0.472875,0.614412,1.194861,0.37578,-0.324904, + 0.622801,-0.721415,0.302786,1.219224,0.33452,-0.404556, + 0.257435,-0.906571,0.334448,1.188046,0.322006,-0.403722, + 0.631575,-0.472875,0.614412,1.194861,0.37578,-0.324904, + 0.257435,-0.906571,0.334448,1.188046,0.322006,-0.403722, + 0.202524,-0.691948,0.692959,1.163707,0.362839,-0.323491, + 0.622801,-0.721415,0.302786,1.219224,0.33452,-0.404556, + 0.780431,-0.625241,0,1.227578,0.320768,-0.5, + 0.301979,-0.953315,0,1.196159,0.308395,-0.5, + 0.301979,-0.953315,0,1.196159,0.308395,-0.5, + 0.257435,-0.906571,0.334448,1.188046,0.322006,-0.403722, + 0.622801,-0.721415,0.302786,1.219224,0.33452,-0.404556, + 0.166954,-0.985965,0,1.148052,0.300668,-0.5, + 0.164983,-0.93415,0.316457,1.139957,0.313586,-0.405556, + 0.257435,-0.906571,0.334448,1.188046,0.322006,-0.403722, + 0.166954,-0.985965,0,1.148052,0.300668,-0.5, + 0.257435,-0.906571,0.334448,1.188046,0.322006,-0.403722, + 0.301979,-0.953315,0,1.196159,0.308395,-0.5, + 0.930569,0.3071,0.199327,1.204957,0.421449,-0.361333, + 0.940255,0.325371,0.100277,1.221821,0.401211,-0.4175, + 0.974899,-0.059226,0.214627,1.230706,0.358565,-0.4125, + 0.930569,0.3071,0.199327,1.204957,0.421449,-0.361333, + 0.974899,-0.059226,0.214627,1.230706,0.358565,-0.4125, + 0.890812,0.056731,0.450816,1.207091,0.397037,-0.339125, + 0.962007,0.273026,0,1.230206,0.391113,-0.5, + 0.992798,-0.119797,0,1.239508,0.345749,-0.5, + 0.974899,-0.059226,0.214627,1.230706,0.358565,-0.4125, + 0.962007,0.273026,0,1.230206,0.391113,-0.5, + 0.974899,-0.059226,0.214627,1.230706,0.358565,-0.4125, + 0.940255,0.325371,0.100277,1.221821,0.401211,-0.4175, + 0.780431,-0.625241,0,1.227578,0.320768,-0.5, + 0.622801,-0.721415,0.302786,1.219224,0.33452,-0.404556, + 0.974899,-0.059226,0.214627,1.230706,0.358565,-0.4125, + 0.780431,-0.625241,0,1.227578,0.320768,-0.5, + 0.974899,-0.059226,0.214627,1.230706,0.358565,-0.4125, + 0.992798,-0.119797,0,1.239508,0.345749,-0.5, + 0.631575,-0.472875,0.614412,1.194861,0.37578,-0.324904, + 0.890812,0.056731,0.450816,1.207091,0.397037,-0.339125, + 0.974899,-0.059226,0.214627,1.230706,0.358565,-0.4125, + 0.631575,-0.472875,0.614412,1.194861,0.37578,-0.324904, + 0.974899,-0.059226,0.214627,1.230706,0.358565,-0.4125, + 0.622801,-0.721415,0.302786,1.219224,0.33452,-0.404556, + 0.930569,0.3071,-0.199328,1.204957,0.421449,-0.638667, + 0.890812,0.056731,-0.450816,1.207091,0.397037,-0.660875, + 0.974899,-0.059226,-0.214627,1.230706,0.358565,-0.5875, + 0.930569,0.3071,-0.199328,1.204957,0.421449,-0.638667, + 0.974899,-0.059226,-0.214627,1.230706,0.358565,-0.5875, + 0.940255,0.325371,-0.100277,1.221821,0.401211,-0.5825, + 0.631576,-0.472875,-0.614411,1.194861,0.37578,-0.675096, + 0.622801,-0.721415,-0.302786,1.219224,0.33452,-0.595444, + 0.974899,-0.059226,-0.214627,1.230706,0.358565,-0.5875, + 0.631576,-0.472875,-0.614411,1.194861,0.37578,-0.675096, + 0.974899,-0.059226,-0.214627,1.230706,0.358565,-0.5875, + 0.890812,0.056731,-0.450816,1.207091,0.397037,-0.660875, + 0.780431,-0.625241,0,1.227578,0.320768,-0.5, + 0.992798,-0.119797,0,1.239508,0.345749,-0.5, + 0.974899,-0.059226,-0.214627,1.230706,0.358565,-0.5875, + 0.780431,-0.625241,0,1.227578,0.320768,-0.5, + 0.974899,-0.059226,-0.214627,1.230706,0.358565,-0.5875, + 0.622801,-0.721415,-0.302786,1.219224,0.33452,-0.595444, + 0.962007,0.273026,0,1.230206,0.391113,-0.5, + 0.940255,0.325371,-0.100277,1.221821,0.401211,-0.5825, + 0.974899,-0.059226,-0.214627,1.230706,0.358565,-0.5875, + 0.962007,0.273026,0,1.230206,0.391113,-0.5, + 0.974899,-0.059226,-0.214627,1.230706,0.358565,-0.5875, + 0.992798,-0.119797,0,1.239508,0.345749,-0.5, + 0.133481,-0.728232,0.672206,1.115671,0.352342,-0.326853, + 0.060251,-0.377234,0.924156,1.075195,0.416935,-0.279631, + 0.095842,-0.348455,0.932413,1.123141,0.430895,-0.275352, + 0.133481,-0.728232,0.672206,1.115671,0.352342,-0.326853, + 0.095842,-0.348455,0.932413,1.123141,0.430895,-0.275352, + 0.202524,-0.691948,0.692959,1.163707,0.362839,-0.323491, + 0.060251,-0.377234,0.924156,1.075195,0.416935,-0.279631, + -0.042028,-0.027931,0.998726,1.026623,0.494446,-0.263891, + -0.024646,-0.015417,0.999577,1.074463,0.512562,-0.259306, + -0.024646,-0.015417,0.999577,1.074463,0.512562,-0.259306, + 0.095842,-0.348455,0.932413,1.123141,0.430895,-0.275352, + 0.060251,-0.377234,0.924156,1.075195,0.416935,-0.279631, + 0.346195,0.171304,0.92239,1.107591,0.526937,-0.260702, + 0.484632,-0.165545,0.858911,1.155185,0.444556,-0.276838, + 0.095842,-0.348455,0.932413,1.123141,0.430895,-0.275352, + 0.346195,0.171304,0.92239,1.107591,0.526937,-0.260702, + 0.095842,-0.348455,0.932413,1.123141,0.430895,-0.275352, + -0.024646,-0.015417,0.999577,1.074463,0.512562,-0.259306, + 0.484632,-0.165545,0.858911,1.155185,0.444556,-0.276838, + 0.631575,-0.472875,0.614412,1.194861,0.37578,-0.324904, + 0.202524,-0.691948,0.692959,1.163707,0.362839,-0.323491, + 0.202524,-0.691948,0.692959,1.163707,0.362839,-0.323491, + 0.095842,-0.348455,0.932413,1.123141,0.430895,-0.275352, + 0.484632,-0.165545,0.858911,1.155185,0.444556,-0.276838, + -0.176226,0.307645,0.935039,0.978052,0.571957,-0.279631, + -0.334947,0.636181,0.695043,0.937575,0.63655,-0.326853, + -0.323336,0.633934,0.702554,0.985218,0.662285,-0.323491, + -0.323336,0.633934,0.702554,0.985218,0.662285,-0.323491, + -0.162184,0.309455,0.936981,1.025784,0.594229,-0.275352, + -0.176226,0.307645,0.935039,0.978052,0.571957,-0.279631, + -0.011301,0.717458,0.69651,1.01927,0.677486,-0.324904, + 0.171113,0.465842,0.868165,1.059471,0.609015,-0.276838, + -0.162184,0.309455,0.936981,1.025784,0.594229,-0.275352, + -0.011301,0.717458,0.69651,1.01927,0.677486,-0.324904, + -0.162184,0.309455,0.936981,1.025784,0.594229,-0.275352, + -0.323336,0.633934,0.702554,0.985218,0.662285,-0.323491, + 0.171113,0.465842,0.868165,1.059471,0.609015,-0.276838, + 0.346195,0.171304,0.92239,1.107591,0.526937,-0.260702, + -0.024646,-0.015417,0.999577,1.074463,0.512562,-0.259306, + -0.024646,-0.015417,0.999577,1.074463,0.512562,-0.259306, + -0.162184,0.309455,0.936981,1.025784,0.594229,-0.275352, + 0.171113,0.465842,0.868165,1.059471,0.609015,-0.276838, + -0.042028,-0.027931,0.998726,1.026623,0.494446,-0.263891, + -0.176226,0.307645,0.935039,0.978052,0.571957,-0.279631, + -0.162184,0.309455,0.936981,1.025784,0.594229,-0.275352, + -0.042028,-0.027931,0.998726,1.026623,0.494446,-0.263891, + -0.162184,0.309455,0.936981,1.025784,0.594229,-0.275352, + -0.024646,-0.015417,0.999577,1.074463,0.512562,-0.259306, + 0.499427,0.759449,0.416905,1.046216,0.67568,-0.339125, + 0.73381,0.655202,0.179534,1.066291,0.661627,-0.361333, + 0.786313,0.584772,0.199385,1.098258,0.615227,-0.335375, + 0.786313,0.584772,0.199385,1.098258,0.615227,-0.335375, + 0.621316,0.565314,0.542574,1.083956,0.612743,-0.294, + 0.499427,0.759449,0.416905,1.046216,0.67568,-0.339125, + 0.83547,0.498022,0.232303,1.141425,0.544887,-0.322437, + 0.742505,0.410638,0.529209,1.128758,0.537574,-0.2785, + 0.621316,0.565314,0.542574,1.083956,0.612743,-0.294, + 0.83547,0.498022,0.232303,1.141425,0.544887,-0.322437, + 0.621316,0.565314,0.542574,1.083956,0.612743,-0.294, + 0.786313,0.584772,0.199385,1.098258,0.615227,-0.335375, + 0.346195,0.171304,0.92239,1.107591,0.526937,-0.260702, + 0.171113,0.465842,0.868165,1.059471,0.609015,-0.276838, + 0.621316,0.565314,0.542574,1.083956,0.612743,-0.294, + 0.346195,0.171304,0.92239,1.107591,0.526937,-0.260702, + 0.621316,0.565314,0.542574,1.083956,0.612743,-0.294, + 0.742505,0.410638,0.529209,1.128758,0.537574,-0.2785, + 0.171113,0.465842,0.868165,1.059471,0.609015,-0.276838, + -0.011301,0.717458,0.69651,1.01927,0.677486,-0.324904, + 0.499427,0.759449,0.416905,1.046216,0.67568,-0.339125, + 0.499427,0.759449,0.416905,1.046216,0.67568,-0.339125, + 0.621316,0.565314,0.542574,1.083956,0.612743,-0.294, + 0.171113,0.465842,0.868165,1.059471,0.609015,-0.276838, + 0.930569,0.3071,0.199327,1.204957,0.421449,-0.361333, + 0.890812,0.056731,0.450816,1.207091,0.397037,-0.339125, + 0.808962,0.235076,0.538813,1.171456,0.461189,-0.294, + 0.930569,0.3071,0.199327,1.204957,0.421449,-0.361333, + 0.808962,0.235076,0.538813,1.171456,0.461189,-0.294, + 0.890268,0.404155,0.209958,1.180758,0.472333,-0.335375, + 0.890812,0.056731,0.450816,1.207091,0.397037,-0.339125, + 0.631575,-0.472875,0.614412,1.194861,0.37578,-0.324904, + 0.484632,-0.165545,0.858911,1.155185,0.444556,-0.276838, + 0.484632,-0.165545,0.858911,1.155185,0.444556,-0.276838, + 0.808962,0.235076,0.538813,1.171456,0.461189,-0.294, + 0.890812,0.056731,0.450816,1.207091,0.397037,-0.339125, + 0.346195,0.171304,0.92239,1.107591,0.526937,-0.260702, + 0.742505,0.410638,0.529209,1.128758,0.537574,-0.2785, + 0.808962,0.235076,0.538813,1.171456,0.461189,-0.294, + 0.346195,0.171304,0.92239,1.107591,0.526937,-0.260702, + 0.808962,0.235076,0.538813,1.171456,0.461189,-0.294, + 0.484632,-0.165545,0.858911,1.155185,0.444556,-0.276838, + 0.742505,0.410638,0.529209,1.128758,0.537574,-0.2785, + 0.83547,0.498022,0.232303,1.141425,0.544887,-0.322437, + 0.890268,0.404155,0.209958,1.180758,0.472333,-0.335375, + 0.890268,0.404155,0.209958,1.180758,0.472333,-0.335375, + 0.808962,0.235076,0.538813,1.171456,0.461189,-0.294, + 0.742505,0.410638,0.529209,1.128758,0.537574,-0.2785, + -0.334947,0.636181,0.695043,0.937575,0.63655,-0.326853, + -0.440797,0.833329,0.333557,0.913289,0.675305,-0.405556, + -0.436203,0.832732,0.341005,0.960879,0.703118,-0.403722, + -0.334947,0.636181,0.695043,0.937575,0.63655,-0.326853, + -0.436203,0.832732,0.341005,0.960879,0.703118,-0.403722, + -0.323336,0.633934,0.702554,0.985218,0.662285,-0.323491, + -0.440797,0.833329,0.333557,0.913289,0.675305,-0.405556, + -0.456348,0.889801,0,0.905194,0.688224,-0.5, + -0.483417,0.87539,0,0.952766,0.71673,-0.5, + -0.483417,0.87539,0,0.952766,0.71673,-0.5, + -0.436203,0.832732,0.341005,0.960879,0.703118,-0.403722, + -0.440797,0.833329,0.333557,0.913289,0.675305,-0.405556, + -0.145364,0.989378,0,0.987605,0.733106,-0.5, + -0.079433,0.924124,0.373745,0.995432,0.719051,-0.404556, + -0.436203,0.832732,0.341005,0.960879,0.703118,-0.403722, + -0.145364,0.989378,0,0.987605,0.733106,-0.5, + -0.436203,0.832732,0.341005,0.960879,0.703118,-0.403722, + -0.483417,0.87539,0,0.952766,0.71673,-0.5, + -0.079433,0.924124,0.373745,0.995432,0.719051,-0.404556, + -0.011301,0.717458,0.69651,1.01927,0.677486,-0.324904, + -0.323336,0.633934,0.702554,0.985218,0.662285,-0.323491, + -0.323336,0.633934,0.702554,0.985218,0.662285,-0.323491, + -0.436203,0.832732,0.341005,0.960879,0.703118,-0.403722, + -0.079433,0.924124,0.373745,0.995432,0.719051,-0.404556, + -0.334948,0.636181,-0.695043,0.937575,0.63655,-0.673147, + -0.323336,0.633934,-0.702554,0.985218,0.662285,-0.676509, + -0.436203,0.832732,-0.341005,0.960879,0.703118,-0.596277, + -0.334948,0.636181,-0.695043,0.937575,0.63655,-0.673147, + -0.436203,0.832732,-0.341005,0.960879,0.703118,-0.596277, + -0.440797,0.833329,-0.333557,0.913289,0.675305,-0.594444, + -0.323336,0.633934,-0.702554,0.985218,0.662285,-0.676509, + -0.0113,0.717458,-0.69651,1.01927,0.677486,-0.675096, + -0.079433,0.924124,-0.373745,0.995432,0.719051,-0.595444, + -0.079433,0.924124,-0.373745,0.995432,0.719051,-0.595444, + -0.436203,0.832732,-0.341005,0.960879,0.703118,-0.596277, + -0.323336,0.633934,-0.702554,0.985218,0.662285,-0.676509, + -0.145364,0.989378,0,0.987605,0.733106,-0.5, + -0.483417,0.87539,0,0.952766,0.71673,-0.5, + -0.436203,0.832732,-0.341005,0.960879,0.703118,-0.596277, + -0.145364,0.989378,0,0.987605,0.733106,-0.5, + -0.436203,0.832732,-0.341005,0.960879,0.703118,-0.596277, + -0.079433,0.924124,-0.373745,0.995432,0.719051,-0.595444, + -0.483417,0.87539,0,0.952766,0.71673,-0.5, + -0.456348,0.889801,0,0.905194,0.688224,-0.5, + -0.440797,0.833329,-0.333557,0.913289,0.675305,-0.594444, + -0.440797,0.833329,-0.333557,0.913289,0.675305,-0.594444, + -0.436203,0.832732,-0.341005,0.960879,0.703118,-0.596277, + -0.483417,0.87539,0,0.952766,0.71673,-0.5, + 0.73381,0.655202,-0.179535,1.066291,0.661627,-0.638667, + 0.737725,0.668365,-0.095126,1.057196,0.68635,-0.5825, + 0.442446,0.874241,-0.199863,1.024706,0.715367,-0.5875, + 0.73381,0.655202,-0.179535,1.066291,0.661627,-0.638667, + 0.442446,0.874241,-0.199863,1.024706,0.715367,-0.5875, + 0.499427,0.759449,-0.416905,1.046216,0.67568,-0.660875, + 0.737725,0.668365,-0.095126,1.057196,0.68635,-0.5825, + 0.739038,0.673664,0,1.052644,0.698661,-0.5, + 0.507297,0.861771,0,1.018008,0.729398,-0.5, + 0.507297,0.861771,0,1.018008,0.729398,-0.5, + 0.442446,0.874241,-0.199863,1.024706,0.715367,-0.5875, + 0.737725,0.668365,-0.095126,1.057196,0.68635,-0.5825, + -0.145364,0.989378,0,0.987605,0.733106,-0.5, + -0.079433,0.924124,-0.373745,0.995432,0.719051,-0.595444, + 0.442446,0.874241,-0.199863,1.024706,0.715367,-0.5875, + -0.145364,0.989378,0,0.987605,0.733106,-0.5, + 0.442446,0.874241,-0.199863,1.024706,0.715367,-0.5875, + 0.507297,0.861771,0,1.018008,0.729398,-0.5, + -0.079433,0.924124,-0.373745,0.995432,0.719051,-0.595444, + -0.0113,0.717458,-0.69651,1.01927,0.677486,-0.675096, + 0.499427,0.759449,-0.416905,1.046216,0.67568,-0.660875, + 0.499427,0.759449,-0.416905,1.046216,0.67568,-0.660875, + 0.442446,0.874241,-0.199863,1.024706,0.715367,-0.5875, + -0.079433,0.924124,-0.373745,0.995432,0.719051,-0.595444, + 0.73381,0.655202,0.179534,1.066291,0.661627,-0.361333, + 0.499427,0.759449,0.416905,1.046216,0.67568,-0.339125, + 0.442446,0.874241,0.199863,1.024706,0.715367,-0.4125, + 0.73381,0.655202,0.179534,1.066291,0.661627,-0.361333, + 0.442446,0.874241,0.199863,1.024706,0.715367,-0.4125, + 0.737725,0.668365,0.095126,1.057196,0.68635,-0.4175, + 0.499427,0.759449,0.416905,1.046216,0.67568,-0.339125, + -0.011301,0.717458,0.69651,1.01927,0.677486,-0.324904, + -0.079433,0.924124,0.373745,0.995432,0.719051,-0.404556, + -0.079433,0.924124,0.373745,0.995432,0.719051,-0.404556, + 0.442446,0.874241,0.199863,1.024706,0.715367,-0.4125, + 0.499427,0.759449,0.416905,1.046216,0.67568,-0.339125, + -0.145364,0.989378,0,0.987605,0.733106,-0.5, + 0.507297,0.861771,0,1.018008,0.729398,-0.5, + 0.442446,0.874241,0.199863,1.024706,0.715367,-0.4125, + -0.145364,0.989378,0,0.987605,0.733106,-0.5, + 0.442446,0.874241,0.199863,1.024706,0.715367,-0.4125, + -0.079433,0.924124,0.373745,0.995432,0.719051,-0.404556, + 0.507297,0.861771,0,1.018008,0.729398,-0.5, + 0.739038,0.673664,0,1.052644,0.698661,-0.5, + 0.737725,0.668365,0.095126,1.057196,0.68635,-0.4175, + 0.737725,0.668365,0.095126,1.057196,0.68635,-0.4175, + 0.442446,0.874241,0.199863,1.024706,0.715367,-0.4125, + 0.507297,0.861771,0,1.018008,0.729398,-0.5, + -0.323336,0.633934,-0.702554,0.985218,0.662285,-0.676509, + -0.334948,0.636181,-0.695043,0.937575,0.63655,-0.673147, + -0.176226,0.307645,-0.935039,0.978052,0.571957,-0.720369, + -0.176226,0.307645,-0.935039,0.978052,0.571957,-0.720369, + -0.162184,0.309456,-0.936981,1.025784,0.594229,-0.724648, + -0.323336,0.633934,-0.702554,0.985218,0.662285,-0.676509, + -0.042028,-0.027931,-0.998726,1.026623,0.494446,-0.736109, + -0.024646,-0.015417,-0.999577,1.074463,0.512562,-0.740694, + -0.162184,0.309456,-0.936981,1.025784,0.594229,-0.724648, + -0.042028,-0.027931,-0.998726,1.026623,0.494446,-0.736109, + -0.162184,0.309456,-0.936981,1.025784,0.594229,-0.724648, + -0.176226,0.307645,-0.935039,0.978052,0.571957,-0.720369, + -0.024646,-0.015417,-0.999577,1.074463,0.512562,-0.740694, + 0.346195,0.171304,-0.92239,1.107591,0.526937,-0.739298, + 0.171114,0.465842,-0.868165,1.059471,0.609015,-0.723162, + 0.171114,0.465842,-0.868165,1.059471,0.609015,-0.723162, + -0.162184,0.309456,-0.936981,1.025784,0.594229,-0.724648, + -0.024646,-0.015417,-0.999577,1.074463,0.512562,-0.740694, + -0.0113,0.717458,-0.69651,1.01927,0.677486,-0.675096, + -0.323336,0.633934,-0.702554,0.985218,0.662285,-0.676509, + -0.162184,0.309456,-0.936981,1.025784,0.594229,-0.724648, + -0.0113,0.717458,-0.69651,1.01927,0.677486,-0.675096, + -0.162184,0.309456,-0.936981,1.025784,0.594229,-0.724648, + 0.171114,0.465842,-0.868165,1.059471,0.609015,-0.723162, + 0.133481,-0.728232,-0.672207,1.115671,0.352342,-0.673147, + 0.202525,-0.691948,-0.692959,1.163707,0.362839,-0.676509, + 0.095842,-0.348454,-0.932413,1.123141,0.430895,-0.724648, + 0.133481,-0.728232,-0.672207,1.115671,0.352342,-0.673147, + 0.095842,-0.348454,-0.932413,1.123141,0.430895,-0.724648, + 0.060251,-0.377234,-0.924156,1.075195,0.416935,-0.720369, + 0.202525,-0.691948,-0.692959,1.163707,0.362839,-0.676509, + 0.631576,-0.472875,-0.614411,1.194861,0.37578,-0.675096, + 0.484632,-0.165544,-0.85891,1.155185,0.444556,-0.723162, + 0.484632,-0.165544,-0.85891,1.155185,0.444556,-0.723162, + 0.095842,-0.348454,-0.932413,1.123141,0.430895,-0.724648, + 0.202525,-0.691948,-0.692959,1.163707,0.362839,-0.676509, + 0.346195,0.171304,-0.92239,1.107591,0.526937,-0.739298, + -0.024646,-0.015417,-0.999577,1.074463,0.512562,-0.740694, + 0.095842,-0.348454,-0.932413,1.123141,0.430895,-0.724648, + 0.346195,0.171304,-0.92239,1.107591,0.526937,-0.739298, + 0.095842,-0.348454,-0.932413,1.123141,0.430895,-0.724648, + 0.484632,-0.165544,-0.85891,1.155185,0.444556,-0.723162, + -0.024646,-0.015417,-0.999577,1.074463,0.512562,-0.740694, + -0.042028,-0.027931,-0.998726,1.026623,0.494446,-0.736109, + 0.060251,-0.377234,-0.924156,1.075195,0.416935,-0.720369, + 0.060251,-0.377234,-0.924156,1.075195,0.416935,-0.720369, + 0.095842,-0.348454,-0.932413,1.123141,0.430895,-0.724648, + -0.024646,-0.015417,-0.999577,1.074463,0.512562,-0.740694, + 0.930569,0.3071,-0.199328,1.204957,0.421449,-0.638667, + 0.890268,0.404155,-0.209958,1.180758,0.472333,-0.664625, + 0.808963,0.235076,-0.538812,1.171456,0.461189,-0.706, + 0.930569,0.3071,-0.199328,1.204957,0.421449,-0.638667, + 0.808963,0.235076,-0.538812,1.171456,0.461189,-0.706, + 0.890812,0.056731,-0.450816,1.207091,0.397037,-0.660875, + 0.890268,0.404155,-0.209958,1.180758,0.472333,-0.664625, + 0.83547,0.498022,-0.232303,1.141425,0.544887,-0.677562, + 0.742506,0.410638,-0.529208,1.128758,0.537574,-0.7215, + 0.742506,0.410638,-0.529208,1.128758,0.537574,-0.7215, + 0.808963,0.235076,-0.538812,1.171456,0.461189,-0.706, + 0.890268,0.404155,-0.209958,1.180758,0.472333,-0.664625, + 0.346195,0.171304,-0.92239,1.107591,0.526937,-0.739298, + 0.484632,-0.165544,-0.85891,1.155185,0.444556,-0.723162, + 0.808963,0.235076,-0.538812,1.171456,0.461189,-0.706, + 0.346195,0.171304,-0.92239,1.107591,0.526937,-0.739298, + 0.808963,0.235076,-0.538812,1.171456,0.461189,-0.706, + 0.742506,0.410638,-0.529208,1.128758,0.537574,-0.7215, + 0.484632,-0.165544,-0.85891,1.155185,0.444556,-0.723162, + 0.631576,-0.472875,-0.614411,1.194861,0.37578,-0.675096, + 0.890812,0.056731,-0.450816,1.207091,0.397037,-0.660875, + 0.890812,0.056731,-0.450816,1.207091,0.397037,-0.660875, + 0.808963,0.235076,-0.538812,1.171456,0.461189,-0.706, + 0.484632,-0.165544,-0.85891,1.155185,0.444556,-0.723162, + 0.786313,0.584772,-0.199385,1.098258,0.615227,-0.664625, + 0.73381,0.655202,-0.179535,1.066291,0.661627,-0.638667, + 0.499427,0.759449,-0.416905,1.046216,0.67568,-0.660875, + 0.499427,0.759449,-0.416905,1.046216,0.67568,-0.660875, + 0.621316,0.565314,-0.542574,1.083956,0.612743,-0.706, + 0.786313,0.584772,-0.199385,1.098258,0.615227,-0.664625, + 0.499427,0.759449,-0.416905,1.046216,0.67568,-0.660875, + -0.0113,0.717458,-0.69651,1.01927,0.677486,-0.675096, + 0.171114,0.465842,-0.868165,1.059471,0.609015,-0.723162, + 0.171114,0.465842,-0.868165,1.059471,0.609015,-0.723162, + 0.621316,0.565314,-0.542574,1.083956,0.612743,-0.706, + 0.499427,0.759449,-0.416905,1.046216,0.67568,-0.660875, + 0.346195,0.171304,-0.92239,1.107591,0.526937,-0.739298, + 0.742506,0.410638,-0.529208,1.128758,0.537574,-0.7215, + 0.621316,0.565314,-0.542574,1.083956,0.612743,-0.706, + 0.346195,0.171304,-0.92239,1.107591,0.526937,-0.739298, + 0.621316,0.565314,-0.542574,1.083956,0.612743,-0.706, + 0.171114,0.465842,-0.868165,1.059471,0.609015,-0.723162, + 0.83547,0.498022,-0.232303,1.141425,0.544887,-0.677562, + 0.786313,0.584772,-0.199385,1.098258,0.615227,-0.664625, + 0.621316,0.565314,-0.542574,1.083956,0.612743,-0.706, + 0.83547,0.498022,-0.232303,1.141425,0.544887,-0.677562, + 0.621316,0.565314,-0.542574,1.083956,0.612743,-0.706, + 0.742506,0.410638,-0.529208,1.128758,0.537574,-0.7215, + 0.930569,0.3071,0.199327,1.204957,0.421449,-0.361333, + 0.890268,0.404155,0.209958,1.180758,0.472333,-0.335375, + 0.900371,0.427755,0.079739,1.1919,0.469528,-0.4095, + 0.930569,0.3071,0.199327,1.204957,0.421449,-0.361333, + 0.900371,0.427755,0.079739,1.1919,0.469528,-0.4095, + 0.940255,0.325371,0.100277,1.221821,0.401211,-0.4175, + 0.890268,0.404155,0.209958,1.180758,0.472333,-0.335375, + 0.83547,0.498022,0.232303,1.141425,0.544887,-0.322437, + 0.862894,0.498192,0.08496,1.149055,0.549292,-0.40225, + 0.862894,0.498192,0.08496,1.149055,0.549292,-0.40225, + 0.900371,0.427755,0.079739,1.1919,0.469528,-0.4095, + 0.890268,0.404155,0.209958,1.180758,0.472333,-0.335375, + 0.866025,0.5,0,1.151611,0.550768,-0.5, + 0.905374,0.424615,0,1.19793,0.464638,-0.5, + 0.900371,0.427755,0.079739,1.1919,0.469528,-0.4095, + 0.866025,0.5,0,1.151611,0.550768,-0.5, + 0.900371,0.427755,0.079739,1.1919,0.469528,-0.4095, + 0.862894,0.498192,0.08496,1.149055,0.549292,-0.40225, + 0.905374,0.424615,0,1.19793,0.464638,-0.5, + 0.962007,0.273026,0,1.230206,0.391113,-0.5, + 0.940255,0.325371,0.100277,1.221821,0.401211,-0.4175, + 0.940255,0.325371,0.100277,1.221821,0.401211,-0.4175, + 0.900371,0.427755,0.079739,1.1919,0.469528,-0.4095, + 0.905374,0.424615,0,1.19793,0.464638,-0.5, + 0.73381,0.655202,0.179534,1.066291,0.661627,-0.361333, + 0.737725,0.668365,0.095126,1.057196,0.68635,-0.4175, + 0.820632,0.565867,0.079739,1.1014,0.626279,-0.4095, + 0.73381,0.655202,0.179534,1.066291,0.661627,-0.361333, + 0.820632,0.565867,0.079739,1.1014,0.626279,-0.4095, + 0.786313,0.584772,0.199385,1.098258,0.615227,-0.335375, + 0.737725,0.668365,0.095126,1.057196,0.68635,-0.4175, + 0.739038,0.673664,0,1.052644,0.698661,-0.5, + 0.820414,0.57177,0,1.10018,0.633946,-0.5, + 0.820414,0.57177,0,1.10018,0.633946,-0.5, + 0.820632,0.565867,0.079739,1.1014,0.626279,-0.4095, + 0.737725,0.668365,0.095126,1.057196,0.68635,-0.4175, + 0.866025,0.5,0,1.151611,0.550768,-0.5, + 0.862894,0.498192,0.08496,1.149055,0.549292,-0.40225, + 0.820632,0.565867,0.079739,1.1014,0.626279,-0.4095, + 0.866025,0.5,0,1.151611,0.550768,-0.5, + 0.820632,0.565867,0.079739,1.1014,0.626279,-0.4095, + 0.820414,0.57177,0,1.10018,0.633946,-0.5, + 0.862894,0.498192,0.08496,1.149055,0.549292,-0.40225, + 0.83547,0.498022,0.232303,1.141425,0.544887,-0.322437, + 0.786313,0.584772,0.199385,1.098258,0.615227,-0.335375, + 0.786313,0.584772,0.199385,1.098258,0.615227,-0.335375, + 0.820632,0.565867,0.079739,1.1014,0.626279,-0.4095, + 0.862894,0.498192,0.08496,1.149055,0.549292,-0.40225, + 0.73381,0.655202,-0.179535,1.066291,0.661627,-0.638667, + 0.786313,0.584772,-0.199385,1.098258,0.615227,-0.664625, + 0.820632,0.565867,-0.079739,1.1014,0.626279,-0.5905, + 0.73381,0.655202,-0.179535,1.066291,0.661627,-0.638667, + 0.820632,0.565867,-0.079739,1.1014,0.626279,-0.5905, + 0.737725,0.668365,-0.095126,1.057196,0.68635,-0.5825, + 0.786313,0.584772,-0.199385,1.098258,0.615227,-0.664625, + 0.83547,0.498022,-0.232303,1.141425,0.544887,-0.677562, + 0.862894,0.498192,-0.08496,1.149055,0.549292,-0.59775, + 0.862894,0.498192,-0.08496,1.149055,0.549292,-0.59775, + 0.820632,0.565867,-0.079739,1.1014,0.626279,-0.5905, + 0.786313,0.584772,-0.199385,1.098258,0.615227,-0.664625, + 0.866025,0.5,0,1.151611,0.550768,-0.5, + 0.820414,0.57177,0,1.10018,0.633946,-0.5, + 0.820632,0.565867,-0.079739,1.1014,0.626279,-0.5905, + 0.866025,0.5,0,1.151611,0.550768,-0.5, + 0.820632,0.565867,-0.079739,1.1014,0.626279,-0.5905, + 0.862894,0.498192,-0.08496,1.149055,0.549292,-0.59775, + 0.820414,0.57177,0,1.10018,0.633946,-0.5, + 0.739038,0.673664,0,1.052644,0.698661,-0.5, + 0.737725,0.668365,-0.095126,1.057196,0.68635,-0.5825, + 0.737725,0.668365,-0.095126,1.057196,0.68635,-0.5825, + 0.820632,0.565867,-0.079739,1.1014,0.626279,-0.5905, + 0.820414,0.57177,0,1.10018,0.633946,-0.5, + 0.930569,0.3071,-0.199328,1.204957,0.421449,-0.638667, + 0.940255,0.325371,-0.100277,1.221821,0.401211,-0.5825, + 0.900371,0.427755,-0.079739,1.1919,0.469528,-0.5905, + 0.930569,0.3071,-0.199328,1.204957,0.421449,-0.638667, + 0.900371,0.427755,-0.079739,1.1919,0.469528,-0.5905, + 0.890268,0.404155,-0.209958,1.180758,0.472333,-0.664625, + 0.940255,0.325371,-0.100277,1.221821,0.401211,-0.5825, + 0.962007,0.273026,0,1.230206,0.391113,-0.5, + 0.905374,0.424615,0,1.19793,0.464638,-0.5, + 0.905374,0.424615,0,1.19793,0.464638,-0.5, + 0.900371,0.427755,-0.079739,1.1919,0.469528,-0.5905, + 0.940255,0.325371,-0.100277,1.221821,0.401211,-0.5825, + 0.866025,0.5,0,1.151611,0.550768,-0.5, + 0.862894,0.498192,-0.08496,1.149055,0.549292,-0.59775, + 0.900371,0.427755,-0.079739,1.1919,0.469528,-0.5905, + 0.866025,0.5,0,1.151611,0.550768,-0.5, + 0.900371,0.427755,-0.079739,1.1919,0.469528,-0.5905, + 0.905374,0.424615,0,1.19793,0.464638,-0.5, + 0.862894,0.498192,-0.08496,1.149055,0.549292,-0.59775, + 0.83547,0.498022,-0.232303,1.141425,0.544887,-0.677562, + 0.890268,0.404155,-0.209958,1.180758,0.472333,-0.664625, + 0.890268,0.404155,-0.209958,1.180758,0.472333,-0.664625, + 0.900371,0.427755,-0.079739,1.1919,0.469528,-0.5905, + 0.862894,0.498192,-0.08496,1.149055,0.549292,-0.59775, + 0.133481,-0.728232,-0.672207,1.115671,0.352342,-0.673147, + 0.180025,-0.723743,-0.666173,1.052796,0.338416,-0.673044, + 0.197559,-0.930384,-0.308798,1.077742,0.301825,-0.594388, + 0.133481,-0.728232,-0.672207,1.115671,0.352342,-0.673147, + 0.197559,-0.930384,-0.308798,1.077742,0.301825,-0.594388, + 0.164983,-0.93415,-0.316457,1.139957,0.313586,-0.594444, + 0.180025,-0.723743,-0.666173,1.052796,0.338416,-0.673044, + 0.227251,-0.720523,-0.655136,0.982068,0.320307,-0.674787, + 0.245574,-0.922075,-0.299117,1.008335,0.286145,-0.595338, + 0.245574,-0.922075,-0.299117,1.008335,0.286145,-0.595338, + 0.197559,-0.930384,-0.308798,1.077742,0.301825,-0.594388, + 0.180025,-0.723743,-0.666173,1.052796,0.338416,-0.673044, + 0.233794,-0.972286,0,1.017091,0.274757,-0.5, + 0.1906,-0.981668,0,1.086058,0.289628,-0.5, + 0.197559,-0.930384,-0.308798,1.077742,0.301825,-0.594388, + 0.233794,-0.972286,0,1.017091,0.274757,-0.5, + 0.197559,-0.930384,-0.308798,1.077742,0.301825,-0.594388, + 0.245574,-0.922075,-0.299117,1.008335,0.286145,-0.595338, + 0.1906,-0.981668,0,1.086058,0.289628,-0.5, + 0.166954,-0.985965,0,1.148052,0.300668,-0.5, + 0.164983,-0.93415,-0.316457,1.139957,0.313586,-0.594444, + 0.164983,-0.93415,-0.316457,1.139957,0.313586,-0.594444, + 0.197559,-0.930384,-0.308798,1.077742,0.301825,-0.594388, + 0.1906,-0.981668,0,1.086058,0.289628,-0.5, + 0.287838,-0.708745,-0.644073,0.910476,0.29726,-0.676962, + 0.37574,-0.67126,-0.638928,0.845007,0.268518,-0.678159, + 0.438584,-0.8515,-0.287389,0.875679,0.240722,-0.597178, + 0.438584,-0.8515,-0.287389,0.875679,0.240722,-0.597178, + 0.319032,-0.902133,-0.290473,0.93867,0.26597,-0.596525, + 0.287838,-0.708745,-0.644073,0.910476,0.29726,-0.676962, + 0.419512,-0.90775,0,0.885904,0.231457,-0.5, + 0.303521,-0.952825,0,0.948068,0.255539,-0.5, + 0.319032,-0.902133,-0.290473,0.93867,0.26597,-0.596525, + 0.419512,-0.90775,0,0.885904,0.231457,-0.5, + 0.319032,-0.902133,-0.290473,0.93867,0.26597,-0.596525, + 0.438584,-0.8515,-0.287389,0.875679,0.240722,-0.597178, + 0.303521,-0.952825,0,0.948068,0.255539,-0.5, + 0.233794,-0.972286,0,1.017091,0.274757,-0.5, + 0.245574,-0.922075,-0.299117,1.008335,0.286145,-0.595338, + 0.245574,-0.922075,-0.299117,1.008335,0.286145,-0.595338, + 0.319032,-0.902133,-0.290473,0.93867,0.26597,-0.596525, + 0.303521,-0.952825,0,0.948068,0.255539,-0.5, + 0.227251,-0.720523,-0.655136,0.982068,0.320307,-0.674787, + 0.287838,-0.708745,-0.644073,0.910476,0.29726,-0.676962, + 0.319032,-0.902133,-0.290473,0.93867,0.26597,-0.596525, + 0.227251,-0.720523,-0.655136,0.982068,0.320307,-0.674787, + 0.319032,-0.902133,-0.290473,0.93867,0.26597,-0.596525, + 0.245574,-0.922075,-0.299117,1.008335,0.286145,-0.595338, + 0.438584,-0.8515,0.287389,0.875679,0.240722,-0.402822, + 0.37574,-0.67126,0.638928,0.845007,0.268518,-0.321841, + 0.287838,-0.708745,0.644073,0.910476,0.29726,-0.323037, + 0.287838,-0.708745,0.644073,0.910476,0.29726,-0.323037, + 0.319032,-0.902133,0.290473,0.93867,0.26597,-0.403475, + 0.438584,-0.8515,0.287389,0.875679,0.240722,-0.402822, + 0.227251,-0.720523,0.655136,0.982068,0.320307,-0.325213, + 0.245574,-0.922075,0.299116,1.008335,0.286145,-0.404662, + 0.319032,-0.902133,0.290473,0.93867,0.26597,-0.403475, + 0.227251,-0.720523,0.655136,0.982068,0.320307,-0.325213, + 0.319032,-0.902133,0.290473,0.93867,0.26597,-0.403475, + 0.287838,-0.708745,0.644073,0.910476,0.29726,-0.323037, + 0.245574,-0.922075,0.299116,1.008335,0.286145,-0.404662, + 0.233794,-0.972286,0,1.017091,0.274757,-0.5, + 0.303521,-0.952825,0,0.948068,0.255539,-0.5, + 0.303521,-0.952825,0,0.948068,0.255539,-0.5, + 0.319032,-0.902133,0.290473,0.93867,0.26597,-0.403475, + 0.245574,-0.922075,0.299116,1.008335,0.286145,-0.404662, + 0.419512,-0.90775,0,0.885904,0.231457,-0.5, + 0.438584,-0.8515,0.287389,0.875679,0.240722,-0.402822, + 0.319032,-0.902133,0.290473,0.93867,0.26597,-0.403475, + 0.419512,-0.90775,0,0.885904,0.231457,-0.5, + 0.319032,-0.902133,0.290473,0.93867,0.26597,-0.403475, + 0.303521,-0.952825,0,0.948068,0.255539,-0.5, + 0.133481,-0.728232,0.672206,1.115671,0.352342,-0.326853, + 0.164983,-0.93415,0.316457,1.139957,0.313586,-0.405556, + 0.19756,-0.930384,0.308798,1.077742,0.301825,-0.405612, + 0.133481,-0.728232,0.672206,1.115671,0.352342,-0.326853, + 0.19756,-0.930384,0.308798,1.077742,0.301825,-0.405612, + 0.180025,-0.723743,0.666173,1.052796,0.338416,-0.326956, + 0.164983,-0.93415,0.316457,1.139957,0.313586,-0.405556, + 0.166954,-0.985965,0,1.148052,0.300668,-0.5, + 0.1906,-0.981668,0,1.086058,0.289628,-0.5, + 0.1906,-0.981668,0,1.086058,0.289628,-0.5, + 0.19756,-0.930384,0.308798,1.077742,0.301825,-0.405612, + 0.164983,-0.93415,0.316457,1.139957,0.313586,-0.405556, + 0.233794,-0.972286,0,1.017091,0.274757,-0.5, + 0.245574,-0.922075,0.299116,1.008335,0.286145,-0.404662, + 0.19756,-0.930384,0.308798,1.077742,0.301825,-0.405612, + 0.233794,-0.972286,0,1.017091,0.274757,-0.5, + 0.19756,-0.930384,0.308798,1.077742,0.301825,-0.405612, + 0.1906,-0.981668,0,1.086058,0.289628,-0.5, + 0.245574,-0.922075,0.299116,1.008335,0.286145,-0.404662, + 0.227251,-0.720523,0.655136,0.982068,0.320307,-0.325213, + 0.180025,-0.723743,0.666173,1.052796,0.338416,-0.326956, + 0.180025,-0.723743,0.666173,1.052796,0.338416,-0.326956, + 0.19756,-0.930384,0.308798,1.077742,0.301825,-0.405612, + 0.245574,-0.922075,0.299116,1.008335,0.286145,-0.404662, + -0.334948,0.636181,-0.695043,0.937575,0.63655,-0.673147, + -0.290177,0.673481,-0.679868,0.869854,0.606754,-0.673044, + -0.128571,0.348912,-0.928294,0.911431,0.545768,-0.720237, + -0.334948,0.636181,-0.695043,0.937575,0.63655,-0.673147, + -0.128571,0.348912,-0.928294,0.911431,0.545768,-0.720237, + -0.176226,0.307645,-0.935039,0.978052,0.571957,-0.720369, + -0.290177,0.673481,-0.679868,0.869854,0.606754,-0.673044, + -0.308574,0.679683,-0.665442,0.789439,0.570833,-0.674787, + -0.132599,0.364183,-0.92184,0.833218,0.513896,-0.722456, + -0.132599,0.364183,-0.92184,0.833218,0.513896,-0.722456, + -0.128571,0.348912,-0.928294,0.911431,0.545768,-0.720237, + -0.290177,0.673481,-0.679868,0.869854,0.606754,-0.673044, + 0.026562,0.016059,-0.999518,0.885754,0.44557,-0.738345, + 0.010552,0.00411,-0.999936,0.961325,0.472585,-0.735969, + -0.128571,0.348912,-0.928294,0.911431,0.545768,-0.720237, + 0.026562,0.016059,-0.999518,0.885754,0.44557,-0.738345, + -0.128571,0.348912,-0.928294,0.911431,0.545768,-0.720237, + -0.132599,0.364183,-0.92184,0.833218,0.513896,-0.722456, + 0.010552,0.00411,-0.999936,0.961325,0.472585,-0.735969, + -0.042028,-0.027931,-0.998726,1.026623,0.494446,-0.736109, + -0.176226,0.307645,-0.935039,0.978052,0.571957,-0.720369, + -0.176226,0.307645,-0.935039,0.978052,0.571957,-0.720369, + -0.128571,0.348912,-0.928294,0.911431,0.545768,-0.720237, + 0.010552,0.00411,-0.999936,0.961325,0.472585,-0.735969, + -0.36742,0.660294,-0.654992,0.703717,0.526722,-0.676962, + -0.459897,0.603331,-0.651526,0.620074,0.472355,-0.678159, + -0.231331,0.321253,-0.918304,0.671195,0.426029,-0.726748, + -0.231331,0.321253,-0.918304,0.671195,0.426029,-0.726748, + -0.168868,0.358367,-0.918181,0.750708,0.474572,-0.725225, + -0.36742,0.660294,-0.654992,0.703717,0.526722,-0.676962, + 0.003382,-0.001295,-0.999993,0.73254,0.370437,-0.742944, + 0.02248,0.015117,-0.999633,0.807096,0.411991,-0.741313, + -0.168868,0.358367,-0.918181,0.750708,0.474572,-0.725225, + 0.003382,-0.001295,-0.999993,0.73254,0.370437,-0.742944, + -0.168868,0.358367,-0.918181,0.750708,0.474572,-0.725225, + -0.231331,0.321253,-0.918304,0.671195,0.426029,-0.726748, + 0.02248,0.015117,-0.999633,0.807096,0.411991,-0.741313, + 0.026562,0.016059,-0.999518,0.885754,0.44557,-0.738345, + -0.132599,0.364183,-0.92184,0.833218,0.513896,-0.722456, + -0.132599,0.364183,-0.92184,0.833218,0.513896,-0.722456, + -0.168868,0.358367,-0.918181,0.750708,0.474572,-0.725225, + 0.02248,0.015117,-0.999633,0.807096,0.411991,-0.741313, + -0.308574,0.679683,-0.665442,0.789439,0.570833,-0.674787, + -0.36742,0.660294,-0.654992,0.703717,0.526722,-0.676962, + -0.168868,0.358367,-0.918181,0.750708,0.474572,-0.725225, + -0.308574,0.679683,-0.665442,0.789439,0.570833,-0.674787, + -0.168868,0.358367,-0.918181,0.750708,0.474572,-0.725225, + -0.132599,0.364183,-0.92184,0.833218,0.513896,-0.722456, + 0.37574,-0.67126,-0.638928,0.845007,0.268518,-0.678159, + 0.287838,-0.708745,-0.644073,0.910476,0.29726,-0.676962, + 0.181001,-0.354486,-0.917376,0.863485,0.34941,-0.725225, + 0.37574,-0.67126,-0.638928,0.845007,0.268518,-0.678159, + 0.181001,-0.354486,-0.917376,0.863485,0.34941,-0.725225, + 0.214466,-0.344671,-0.913896,0.793886,0.314845,-0.726748, + 0.287838,-0.708745,-0.644073,0.910476,0.29726,-0.676962, + 0.227251,-0.720523,-0.655136,0.982068,0.320307,-0.674787, + 0.149984,-0.357133,-0.921933,0.938289,0.377245,-0.722456, + 0.149984,-0.357133,-0.921933,0.938289,0.377245,-0.722456, + 0.181001,-0.354486,-0.917376,0.863485,0.34941,-0.725225, + 0.287838,-0.708745,-0.644073,0.910476,0.29726,-0.676962, + 0.026562,0.016059,-0.999518,0.885754,0.44557,-0.738345, + 0.02248,0.015117,-0.999633,0.807096,0.411991,-0.741313, + 0.181001,-0.354486,-0.917376,0.863485,0.34941,-0.725225, + 0.026562,0.016059,-0.999518,0.885754,0.44557,-0.738345, + 0.181001,-0.354486,-0.917376,0.863485,0.34941,-0.725225, + 0.149984,-0.357133,-0.921933,0.938289,0.377245,-0.722456, + 0.02248,0.015117,-0.999633,0.807096,0.411991,-0.741313, + 0.003382,-0.001295,-0.999993,0.73254,0.370437,-0.742944, + 0.214466,-0.344671,-0.913896,0.793886,0.314845,-0.726748, + 0.214466,-0.344671,-0.913896,0.793886,0.314845,-0.726748, + 0.181001,-0.354486,-0.917376,0.863485,0.34941,-0.725225, + 0.02248,0.015117,-0.999633,0.807096,0.411991,-0.741313, + 0.180025,-0.723743,-0.666173,1.052796,0.338416,-0.673044, + 0.133481,-0.728232,-0.672207,1.115671,0.352342,-0.673147, + 0.060251,-0.377234,-0.924156,1.075195,0.416935,-0.720369, + 0.060251,-0.377234,-0.924156,1.075195,0.416935,-0.720369, + 0.114557,-0.361315,-0.92538,1.011218,0.399402,-0.720237, + 0.180025,-0.723743,-0.666173,1.052796,0.338416,-0.673044, + -0.042028,-0.027931,-0.998726,1.026623,0.494446,-0.736109, + 0.010552,0.00411,-0.999936,0.961325,0.472585,-0.735969, + 0.114557,-0.361315,-0.92538,1.011218,0.399402,-0.720237, + -0.042028,-0.027931,-0.998726,1.026623,0.494446,-0.736109, + 0.114557,-0.361315,-0.92538,1.011218,0.399402,-0.720237, + 0.060251,-0.377234,-0.924156,1.075195,0.416935,-0.720369, + 0.010552,0.00411,-0.999936,0.961325,0.472585,-0.735969, + 0.026562,0.016059,-0.999518,0.885754,0.44557,-0.738345, + 0.149984,-0.357133,-0.921933,0.938289,0.377245,-0.722456, + 0.149984,-0.357133,-0.921933,0.938289,0.377245,-0.722456, + 0.114557,-0.361315,-0.92538,1.011218,0.399402,-0.720237, + 0.010552,0.00411,-0.999936,0.961325,0.472585,-0.735969, + 0.227251,-0.720523,-0.655136,0.982068,0.320307,-0.674787, + 0.180025,-0.723743,-0.666173,1.052796,0.338416,-0.673044, + 0.114557,-0.361315,-0.92538,1.011218,0.399402,-0.720237, + 0.227251,-0.720523,-0.655136,0.982068,0.320307,-0.674787, + 0.114557,-0.361315,-0.92538,1.011218,0.399402,-0.720237, + 0.149984,-0.357133,-0.921933,0.938289,0.377245,-0.722456, + -0.334947,0.636181,0.695043,0.937575,0.63655,-0.326853, + -0.176226,0.307645,0.935039,0.978052,0.571957,-0.279631, + -0.128571,0.348912,0.928294,0.911431,0.545768,-0.279763, + -0.334947,0.636181,0.695043,0.937575,0.63655,-0.326853, + -0.128571,0.348912,0.928294,0.911431,0.545768,-0.279763, + -0.290177,0.673481,0.679868,0.869854,0.606754,-0.326956, + -0.176226,0.307645,0.935039,0.978052,0.571957,-0.279631, + -0.042028,-0.027931,0.998726,1.026623,0.494446,-0.263891, + 0.010552,0.00411,0.999936,0.961325,0.472585,-0.264031, + 0.010552,0.00411,0.999936,0.961325,0.472585,-0.264031, + -0.128571,0.348912,0.928294,0.911431,0.545768,-0.279763, + -0.176226,0.307645,0.935039,0.978052,0.571957,-0.279631, + 0.026562,0.01606,0.999518,0.885754,0.44557,-0.261655, + -0.132599,0.364183,0.921839,0.833218,0.513896,-0.277544, + -0.128571,0.348912,0.928294,0.911431,0.545768,-0.279763, + 0.026562,0.01606,0.999518,0.885754,0.44557,-0.261655, + -0.128571,0.348912,0.928294,0.911431,0.545768,-0.279763, + 0.010552,0.00411,0.999936,0.961325,0.472585,-0.264031, + -0.132599,0.364183,0.921839,0.833218,0.513896,-0.277544, + -0.308574,0.679683,0.665442,0.789439,0.570833,-0.325213, + -0.290177,0.673481,0.679868,0.869854,0.606754,-0.326956, + -0.290177,0.673481,0.679868,0.869854,0.606754,-0.326956, + -0.128571,0.348912,0.928294,0.911431,0.545768,-0.279763, + -0.132599,0.364183,0.921839,0.833218,0.513896,-0.277544, + 0.060251,-0.377234,0.924156,1.075195,0.416935,-0.279631, + 0.133481,-0.728232,0.672206,1.115671,0.352342,-0.326853, + 0.180025,-0.723743,0.666173,1.052796,0.338416,-0.326956, + 0.180025,-0.723743,0.666173,1.052796,0.338416,-0.326956, + 0.114557,-0.361314,0.92538,1.011218,0.399402,-0.279763, + 0.060251,-0.377234,0.924156,1.075195,0.416935,-0.279631, + 0.227251,-0.720523,0.655136,0.982068,0.320307,-0.325213, + 0.149984,-0.357133,0.921933,0.938289,0.377245,-0.277544, + 0.114557,-0.361314,0.92538,1.011218,0.399402,-0.279763, + 0.227251,-0.720523,0.655136,0.982068,0.320307,-0.325213, + 0.114557,-0.361314,0.92538,1.011218,0.399402,-0.279763, + 0.180025,-0.723743,0.666173,1.052796,0.338416,-0.326956, + 0.149984,-0.357133,0.921933,0.938289,0.377245,-0.277544, + 0.026562,0.01606,0.999518,0.885754,0.44557,-0.261655, + 0.010552,0.00411,0.999936,0.961325,0.472585,-0.264031, + 0.010552,0.00411,0.999936,0.961325,0.472585,-0.264031, + 0.114557,-0.361314,0.92538,1.011218,0.399402,-0.279763, + 0.149984,-0.357133,0.921933,0.938289,0.377245,-0.277544, + -0.042028,-0.027931,0.998726,1.026623,0.494446,-0.263891, + 0.060251,-0.377234,0.924156,1.075195,0.416935,-0.279631, + 0.114557,-0.361314,0.92538,1.011218,0.399402,-0.279763, + -0.042028,-0.027931,0.998726,1.026623,0.494446,-0.263891, + 0.114557,-0.361314,0.92538,1.011218,0.399402,-0.279763, + 0.010552,0.00411,0.999936,0.961325,0.472585,-0.264031, + 0.37574,-0.67126,0.638928,0.845007,0.268518,-0.321841, + 0.214466,-0.34467,0.913896,0.793886,0.314845,-0.273252, + 0.181001,-0.354486,0.917376,0.863485,0.34941,-0.274775, + 0.37574,-0.67126,0.638928,0.845007,0.268518,-0.321841, + 0.181001,-0.354486,0.917376,0.863485,0.34941,-0.274775, + 0.287838,-0.708745,0.644073,0.910476,0.29726,-0.323037, + 0.214466,-0.34467,0.913896,0.793886,0.314845,-0.273252, + 0.003382,-0.001295,0.999993,0.73254,0.370437,-0.257056, + 0.02248,0.015118,0.999633,0.807096,0.411991,-0.258687, + 0.02248,0.015118,0.999633,0.807096,0.411991,-0.258687, + 0.181001,-0.354486,0.917376,0.863485,0.34941,-0.274775, + 0.214466,-0.34467,0.913896,0.793886,0.314845,-0.273252, + 0.026562,0.01606,0.999518,0.885754,0.44557,-0.261655, + 0.149984,-0.357133,0.921933,0.938289,0.377245,-0.277544, + 0.181001,-0.354486,0.917376,0.863485,0.34941,-0.274775, + 0.026562,0.01606,0.999518,0.885754,0.44557,-0.261655, + 0.181001,-0.354486,0.917376,0.863485,0.34941,-0.274775, + 0.02248,0.015118,0.999633,0.807096,0.411991,-0.258687, + 0.149984,-0.357133,0.921933,0.938289,0.377245,-0.277544, + 0.227251,-0.720523,0.655136,0.982068,0.320307,-0.325213, + 0.287838,-0.708745,0.644073,0.910476,0.29726,-0.323037, + 0.287838,-0.708745,0.644073,0.910476,0.29726,-0.323037, + 0.181001,-0.354486,0.917376,0.863485,0.34941,-0.274775, + 0.149984,-0.357133,0.921933,0.938289,0.377245,-0.277544, + -0.231331,0.321253,0.918304,0.671195,0.426029,-0.273252, + -0.459898,0.603331,0.651526,0.620074,0.472355,-0.321841, + -0.36742,0.660294,0.654992,0.703717,0.526722,-0.323037, + -0.36742,0.660294,0.654992,0.703717,0.526722,-0.323037, + -0.168868,0.358366,0.918181,0.750708,0.474572,-0.274775, + -0.231331,0.321253,0.918304,0.671195,0.426029,-0.273252, + -0.308574,0.679683,0.665442,0.789439,0.570833,-0.325213, + -0.132599,0.364183,0.921839,0.833218,0.513896,-0.277544, + -0.168868,0.358366,0.918181,0.750708,0.474572,-0.274775, + -0.308574,0.679683,0.665442,0.789439,0.570833,-0.325213, + -0.168868,0.358366,0.918181,0.750708,0.474572,-0.274775, + -0.36742,0.660294,0.654992,0.703717,0.526722,-0.323037, + -0.132599,0.364183,0.921839,0.833218,0.513896,-0.277544, + 0.026562,0.01606,0.999518,0.885754,0.44557,-0.261655, + 0.02248,0.015118,0.999633,0.807096,0.411991,-0.258687, + 0.02248,0.015118,0.999633,0.807096,0.411991,-0.258687, + -0.168868,0.358366,0.918181,0.750708,0.474572,-0.274775, + -0.132599,0.364183,0.921839,0.833218,0.513896,-0.277544, + 0.003382,-0.001295,0.999993,0.73254,0.370437,-0.257056, + -0.231331,0.321253,0.918304,0.671195,0.426029,-0.273252, + -0.168868,0.358366,0.918181,0.750708,0.474572,-0.274775, + 0.003382,-0.001295,0.999993,0.73254,0.370437,-0.257056, + -0.168868,0.358366,0.918181,0.750708,0.474572,-0.274775, + 0.02248,0.015118,0.999633,0.807096,0.411991,-0.258687, + -0.290177,0.673481,-0.679868,0.869854,0.606754,-0.673044, + -0.334948,0.636181,-0.695043,0.937575,0.63655,-0.673147, + -0.440797,0.833329,-0.333557,0.913289,0.675305,-0.594444, + -0.440797,0.833329,-0.333557,0.913289,0.675305,-0.594444, + -0.397769,0.859277,-0.321594,0.844907,0.643346,-0.594388, + -0.290177,0.673481,-0.679868,0.869854,0.606754,-0.673044, + -0.456348,0.889801,0,0.905194,0.688224,-0.5, + -0.427853,0.903848,0,0.836591,0.655543,-0.5, + -0.397769,0.859277,-0.321594,0.844907,0.643346,-0.594388, + -0.456348,0.889801,0,0.905194,0.688224,-0.5, + -0.397769,0.859277,-0.321594,0.844907,0.643346,-0.594388, + -0.440797,0.833329,-0.333557,0.913289,0.675305,-0.594444, + -0.427853,0.903848,0,0.836591,0.655543,-0.5, + -0.459546,0.888154,0,0.754416,0.616383,-0.5, + -0.421194,0.852237,-0.310301,0.763171,0.604996,-0.595338, + -0.421194,0.852237,-0.310301,0.763171,0.604996,-0.595338, + -0.397769,0.859277,-0.321594,0.844907,0.643346,-0.594388, + -0.427853,0.903848,0,0.836591,0.655543,-0.5, + -0.308574,0.679683,-0.665442,0.789439,0.570833,-0.674787, + -0.290177,0.673481,-0.679868,0.869854,0.606754,-0.673044, + -0.397769,0.859277,-0.321594,0.844907,0.643346,-0.594388, + -0.308574,0.679683,-0.665442,0.789439,0.570833,-0.674787, + -0.397769,0.859277,-0.321594,0.844907,0.643346,-0.594388, + -0.421194,0.852237,-0.310301,0.763171,0.604996,-0.595338, + -0.440797,0.833329,0.333557,0.913289,0.675305,-0.405556, + -0.334947,0.636181,0.695043,0.937575,0.63655,-0.326853, + -0.290177,0.673481,0.679868,0.869854,0.606754,-0.326956, + -0.290177,0.673481,0.679868,0.869854,0.606754,-0.326956, + -0.397769,0.859277,0.321594,0.844907,0.643346,-0.405612, + -0.440797,0.833329,0.333557,0.913289,0.675305,-0.405556, + -0.308574,0.679683,0.665442,0.789439,0.570833,-0.325213, + -0.421194,0.852237,0.310301,0.763171,0.604996,-0.404662, + -0.397769,0.859277,0.321594,0.844907,0.643346,-0.405612, + -0.308574,0.679683,0.665442,0.789439,0.570833,-0.325213, + -0.397769,0.859277,0.321594,0.844907,0.643346,-0.405612, + -0.290177,0.673481,0.679868,0.869854,0.606754,-0.326956, + -0.421194,0.852237,0.310301,0.763171,0.604996,-0.404662, + -0.459546,0.888154,0,0.754416,0.616383,-0.5, + -0.427853,0.903848,0,0.836591,0.655543,-0.5, + -0.427853,0.903848,0,0.836591,0.655543,-0.5, + -0.397769,0.859277,0.321594,0.844907,0.643346,-0.405612, + -0.421194,0.852237,0.310301,0.763171,0.604996,-0.404662, + -0.456348,0.889801,0,0.905194,0.688224,-0.5, + -0.440797,0.833329,0.333557,0.913289,0.675305,-0.405556, + -0.397769,0.859277,0.321594,0.844907,0.643346,-0.405612, + -0.456348,0.889801,0,0.905194,0.688224,-0.5, + -0.397769,0.859277,0.321594,0.844907,0.643346,-0.405612, + -0.427853,0.903848,0,0.836591,0.655543,-0.5, + -0.459898,0.603331,0.651526,0.620074,0.472355,-0.321841, + -0.5899,0.750266,0.298526,0.589401,0.500151,-0.402822, + -0.487389,0.819353,0.301848,0.675523,0.558012,-0.403475, + -0.459898,0.603331,0.651526,0.620074,0.472355,-0.321841, + -0.487389,0.819353,0.301848,0.675523,0.558012,-0.403475, + -0.36742,0.660294,0.654992,0.703717,0.526722,-0.323037, + -0.5899,0.750266,0.298526,0.589401,0.500151,-0.402822, + -0.64127,0.767315,0,0.579177,0.509417,-0.5, + -0.532473,0.846447,0,0.666125,0.568442,-0.5, + -0.532473,0.846447,0,0.666125,0.568442,-0.5, + -0.487389,0.819353,0.301848,0.675523,0.558012,-0.403475, + -0.5899,0.750266,0.298526,0.589401,0.500151,-0.402822, + -0.459546,0.888154,0,0.754416,0.616383,-0.5, + -0.421194,0.852237,0.310301,0.763171,0.604996,-0.404662, + -0.487389,0.819353,0.301848,0.675523,0.558012,-0.403475, + -0.459546,0.888154,0,0.754416,0.616383,-0.5, + -0.487389,0.819353,0.301848,0.675523,0.558012,-0.403475, + -0.532473,0.846447,0,0.666125,0.568442,-0.5, + -0.421194,0.852237,0.310301,0.763171,0.604996,-0.404662, + -0.308574,0.679683,0.665442,0.789439,0.570833,-0.325213, + -0.36742,0.660294,0.654992,0.703717,0.526722,-0.323037, + -0.36742,0.660294,0.654992,0.703717,0.526722,-0.323037, + -0.487389,0.819353,0.301848,0.675523,0.558012,-0.403475, + -0.421194,0.852237,0.310301,0.763171,0.604996,-0.404662, + -0.459897,0.603331,-0.651526,0.620074,0.472355,-0.678159, + -0.36742,0.660294,-0.654992,0.703717,0.526722,-0.676962, + -0.487389,0.819353,-0.301848,0.675523,0.558012,-0.596525, + -0.459897,0.603331,-0.651526,0.620074,0.472355,-0.678159, + -0.487389,0.819353,-0.301848,0.675523,0.558012,-0.596525, + -0.5899,0.750266,-0.298526,0.589401,0.500151,-0.597178, + -0.36742,0.660294,-0.654992,0.703717,0.526722,-0.676962, + -0.308574,0.679683,-0.665442,0.789439,0.570833,-0.674787, + -0.421194,0.852237,-0.310301,0.763171,0.604996,-0.595338, + -0.421194,0.852237,-0.310301,0.763171,0.604996,-0.595338, + -0.487389,0.819353,-0.301848,0.675523,0.558012,-0.596525, + -0.36742,0.660294,-0.654992,0.703717,0.526722,-0.676962, + -0.459546,0.888154,0,0.754416,0.616383,-0.5, + -0.532473,0.846447,0,0.666125,0.568442,-0.5, + -0.487389,0.819353,-0.301848,0.675523,0.558012,-0.596525, + -0.459546,0.888154,0,0.754416,0.616383,-0.5, + -0.487389,0.819353,-0.301848,0.675523,0.558012,-0.596525, + -0.421194,0.852237,-0.310301,0.763171,0.604996,-0.595338, + -0.532473,0.846447,0,0.666125,0.568442,-0.5, + -0.64127,0.767315,0,0.579177,0.509417,-0.5, + -0.5899,0.750266,-0.298526,0.589401,0.500151,-0.597178, + -0.5899,0.750266,-0.298526,0.589401,0.500151,-0.597178, + -0.487389,0.819353,-0.301848,0.675523,0.558012,-0.596525, + -0.532473,0.846447,0,0.666125,0.568442,-0.5, + -0.610536,0.426181,-0.667544,0.428341,0.263148,-0.673044, + -0.603758,0.432599,-0.669577,0.386176,0.201223,-0.673147, + -0.304433,0.241938,-0.921296,0.458468,0.182068,-0.720369, + -0.304433,0.241938,-0.921296,0.458468,0.182068,-0.720369, + -0.317966,0.212815,-0.923909,0.495371,0.238512,-0.720237, + -0.610536,0.426181,-0.667544,0.428341,0.263148,-0.673044, + 0.013842,0.059444,-0.998136,0.545218,0.159081,-0.736109, + -0.005469,-0.009402,-0.999941,0.575807,0.208949,-0.735969, + -0.317966,0.212815,-0.923909,0.495371,0.238512,-0.720237, + 0.013842,0.059444,-0.998136,0.545218,0.159081,-0.736109, + -0.317966,0.212815,-0.923909,0.495371,0.238512,-0.720237, + -0.304433,0.241938,-0.921296,0.458468,0.182068,-0.720369, + -0.005469,-0.009402,-0.999941,0.575807,0.208949,-0.735969, + -0.015914,-0.029529,-0.999437,0.617093,0.264045,-0.738345, + -0.31459,0.228088,-0.921417,0.543287,0.301992,-0.722456, + -0.31459,0.228088,-0.921417,0.543287,0.301992,-0.722456, + -0.317966,0.212815,-0.923909,0.495371,0.238512,-0.720237, + -0.005469,-0.009402,-0.999941,0.575807,0.208949,-0.735969, + -0.595775,0.458968,-0.659091,0.481782,0.333615,-0.674787, + -0.610536,0.426181,-0.667544,0.428341,0.263148,-0.673044, + -0.317966,0.212815,-0.923909,0.495371,0.238512,-0.720237, + -0.595775,0.458968,-0.659091,0.481782,0.333615,-0.674787, + -0.317966,0.212815,-0.923909,0.495371,0.238512,-0.720237, + -0.31459,0.228088,-0.921417,0.543287,0.301992,-0.722456, + 0.677454,-0.2664,-0.685629,0.704261,0.116939,-0.673147, + 0.617578,-0.419692,-0.665174,0.723274,0.15475,-0.673044, + 0.314626,-0.214176,-0.924737,0.656244,0.179386,-0.720237, + 0.677454,-0.2664,-0.685629,0.704261,0.116939,-0.673147, + 0.314626,-0.214176,-0.924737,0.656244,0.179386,-0.720237, + 0.344586,-0.098997,-0.93352,0.631969,0.136095,-0.720369, + 0.617578,-0.419692,-0.665174,0.723274,0.15475,-0.673044, + 0.525124,-0.503608,-0.68602,0.752404,0.194475,-0.674787, + 0.282948,-0.282367,-0.916629,0.690899,0.226098,-0.722456, + 0.282948,-0.282367,-0.916629,0.690899,0.226098,-0.722456, + 0.314626,-0.214176,-0.924737,0.656244,0.179386,-0.720237, + 0.617578,-0.419692,-0.665174,0.723274,0.15475,-0.673044, + -0.015914,-0.029529,-0.999437,0.617093,0.264045,-0.738345, + -0.005469,-0.009402,-0.999941,0.575807,0.208949,-0.735969, + 0.314626,-0.214176,-0.924737,0.656244,0.179386,-0.720237, + -0.015914,-0.029529,-0.999437,0.617093,0.264045,-0.738345, + 0.314626,-0.214176,-0.924737,0.656244,0.179386,-0.720237, + 0.282948,-0.282367,-0.916629,0.690899,0.226098,-0.722456, + -0.005469,-0.009402,-0.999941,0.575807,0.208949,-0.735969, + 0.013842,0.059444,-0.998136,0.545218,0.159081,-0.736109, + 0.344586,-0.098997,-0.93352,0.631969,0.136095,-0.720369, + 0.344586,-0.098997,-0.93352,0.631969,0.136095,-0.720369, + 0.314626,-0.214176,-0.924737,0.656244,0.179386,-0.720237, + -0.005469,-0.009402,-0.999941,0.575807,0.208949,-0.735969, + 0.473586,-0.60369,-0.641307,0.792649,0.233327,-0.676962, + 0.37574,-0.67126,-0.638928,0.845007,0.268518,-0.678159, + 0.214466,-0.344671,-0.913896,0.793886,0.314845,-0.726748, + 0.214466,-0.344671,-0.913896,0.793886,0.314845,-0.726748, + 0.248581,-0.323271,-0.913074,0.736568,0.272496,-0.725225, + 0.473586,-0.60369,-0.641307,0.792649,0.233327,-0.676962, + 0.003382,-0.001295,-0.999993,0.73254,0.370437,-0.742944, + -0.014673,-0.023374,-0.999619,0.669271,0.319498,-0.741313, + 0.248581,-0.323271,-0.913074,0.736568,0.272496,-0.725225, + 0.003382,-0.001295,-0.999993,0.73254,0.370437,-0.742944, + 0.248581,-0.323271,-0.913074,0.736568,0.272496,-0.725225, + 0.214466,-0.344671,-0.913896,0.793886,0.314845,-0.726748, + -0.014673,-0.023374,-0.999619,0.669271,0.319498,-0.741313, + -0.015914,-0.029529,-0.999437,0.617093,0.264045,-0.738345, + 0.282948,-0.282367,-0.916629,0.690899,0.226098,-0.722456, + 0.282948,-0.282367,-0.916629,0.690899,0.226098,-0.722456, + 0.248581,-0.323271,-0.913074,0.736568,0.272496,-0.725225, + -0.014673,-0.023374,-0.999619,0.669271,0.319498,-0.741313, + 0.525124,-0.503608,-0.68602,0.752404,0.194475,-0.674787, + 0.473586,-0.60369,-0.641307,0.792649,0.233327,-0.676962, + 0.248581,-0.323271,-0.913074,0.736568,0.272496,-0.725225, + 0.525124,-0.503608,-0.68602,0.752404,0.194475,-0.674787, + 0.248581,-0.323271,-0.913074,0.736568,0.272496,-0.725225, + 0.282948,-0.282367,-0.916629,0.690899,0.226098,-0.722456, + -0.459897,0.603331,-0.651526,0.620074,0.472355,-0.678159, + -0.565284,0.537872,-0.625418,0.545894,0.405668,-0.676962, + -0.288623,0.26748,-0.919321,0.601974,0.3665,-0.725225, + -0.459897,0.603331,-0.651526,0.620074,0.472355,-0.678159, + -0.288623,0.26748,-0.919321,0.601974,0.3665,-0.725225, + -0.231331,0.321253,-0.918304,0.671195,0.426029,-0.726748, + -0.565284,0.537872,-0.625418,0.545894,0.405668,-0.676962, + -0.595775,0.458968,-0.659091,0.481782,0.333615,-0.674787, + -0.31459,0.228088,-0.921417,0.543287,0.301992,-0.722456, + -0.31459,0.228088,-0.921417,0.543287,0.301992,-0.722456, + -0.288623,0.26748,-0.919321,0.601974,0.3665,-0.725225, + -0.565284,0.537872,-0.625418,0.545894,0.405668,-0.676962, + -0.015914,-0.029529,-0.999437,0.617093,0.264045,-0.738345, + -0.014673,-0.023374,-0.999619,0.669271,0.319498,-0.741313, + -0.288623,0.26748,-0.919321,0.601974,0.3665,-0.725225, + -0.015914,-0.029529,-0.999437,0.617093,0.264045,-0.738345, + -0.288623,0.26748,-0.919321,0.601974,0.3665,-0.725225, + -0.31459,0.228088,-0.921417,0.543287,0.301992,-0.722456, + -0.014673,-0.023374,-0.999619,0.669271,0.319498,-0.741313, + 0.003382,-0.001295,-0.999993,0.73254,0.370437,-0.742944, + -0.231331,0.321253,-0.918304,0.671195,0.426029,-0.726748, + -0.231331,0.321253,-0.918304,0.671195,0.426029,-0.726748, + -0.288623,0.26748,-0.919321,0.601974,0.3665,-0.725225, + -0.014673,-0.023374,-0.999619,0.669271,0.319498,-0.741313, + -0.77971,0.541974,-0.313555,0.342801,0.212716,-0.594444, + -0.603758,0.432599,-0.669577,0.386176,0.201223,-0.673147, + -0.610536,0.426181,-0.667544,0.428341,0.263148,-0.673044, + -0.610536,0.426181,-0.667544,0.428341,0.263148,-0.673044, + -0.770954,0.557417,-0.308084,0.388123,0.27793,-0.594388, + -0.77971,0.541974,-0.313555,0.342801,0.212716,-0.594444, + -0.595775,0.458968,-0.659091,0.481782,0.333615,-0.674787, + -0.740072,0.600901,-0.302014,0.444878,0.352588,-0.595338, + -0.770954,0.557417,-0.308084,0.388123,0.27793,-0.594388, + -0.595775,0.458968,-0.659091,0.481782,0.333615,-0.674787, + -0.770954,0.557417,-0.308084,0.388123,0.27793,-0.594388, + -0.610536,0.426181,-0.667544,0.428341,0.263148,-0.673044, + -0.740072,0.600901,-0.302014,0.444878,0.352588,-0.595338, + -0.766999,0.641648,0,0.432577,0.358913,-0.5, + -0.804241,0.594303,0,0.374717,0.282857,-0.5, + -0.804241,0.594303,0,0.374717,0.282857,-0.5, + -0.770954,0.557417,-0.308084,0.388123,0.27793,-0.594388, + -0.740072,0.600901,-0.302014,0.444878,0.352588,-0.595338, + -0.820475,0.571682,0,0.328343,0.216547,-0.5, + -0.77971,0.541974,-0.313555,0.342801,0.212716,-0.594444, + -0.770954,0.557417,-0.308084,0.388123,0.27793,-0.594388, + -0.820475,0.571682,0,0.328343,0.216547,-0.5, + -0.770954,0.557417,-0.308084,0.388123,0.27793,-0.594388, + -0.804241,0.594303,0,0.374717,0.282857,-0.5, + -0.565284,0.537872,-0.625418,0.545894,0.405668,-0.676962, + -0.459897,0.603331,-0.651526,0.620074,0.472355,-0.678159, + -0.5899,0.750266,-0.298526,0.589401,0.500151,-0.597178, + -0.5899,0.750266,-0.298526,0.589401,0.500151,-0.597178, + -0.694867,0.675869,-0.245685,0.512245,0.429169,-0.596525, + -0.565284,0.537872,-0.625418,0.545894,0.405668,-0.676962, + -0.64127,0.767315,0,0.579177,0.509417,-0.5, + -0.716797,0.697282,0,0.501029,0.437003,-0.5, + -0.694867,0.675869,-0.245685,0.512245,0.429169,-0.596525, + -0.64127,0.767315,0,0.579177,0.509417,-0.5, + -0.694867,0.675869,-0.245685,0.512245,0.429169,-0.596525, + -0.5899,0.750266,-0.298526,0.589401,0.500151,-0.597178, + -0.766999,0.641648,0,0.432577,0.358913,-0.5, + -0.740072,0.600901,-0.302014,0.444878,0.352588,-0.595338, + -0.694867,0.675869,-0.245685,0.512245,0.429169,-0.596525, + -0.766999,0.641648,0,0.432577,0.358913,-0.5, + -0.694867,0.675869,-0.245685,0.512245,0.429169,-0.596525, + -0.716797,0.697282,0,0.501029,0.437003,-0.5, + -0.740072,0.600901,-0.302014,0.444878,0.352588,-0.595338, + -0.595775,0.458968,-0.659091,0.481782,0.333615,-0.674787, + -0.565284,0.537872,-0.625418,0.545894,0.405668,-0.676962, + -0.565284,0.537872,-0.625418,0.545894,0.405668,-0.676962, + -0.694867,0.675869,-0.245685,0.512245,0.429169,-0.596525, + -0.740072,0.600901,-0.302014,0.444878,0.352588,-0.595338, + -0.5899,0.750266,0.298526,0.589401,0.500151,-0.402822, + -0.459898,0.603331,0.651526,0.620074,0.472355,-0.321841, + -0.565284,0.537872,0.625418,0.545894,0.405668,-0.323037, + -0.565284,0.537872,0.625418,0.545894,0.405668,-0.323037, + -0.694867,0.675869,0.245685,0.512245,0.429169,-0.403475, + -0.5899,0.750266,0.298526,0.589401,0.500151,-0.402822, + -0.565284,0.537872,0.625418,0.545894,0.405668,-0.323037, + -0.595775,0.458968,0.659091,0.481782,0.333615,-0.325213, + -0.740072,0.600901,0.302014,0.444878,0.352588,-0.404662, + -0.740072,0.600901,0.302014,0.444878,0.352588,-0.404662, + -0.694867,0.675869,0.245685,0.512245,0.429169,-0.403475, + -0.565284,0.537872,0.625418,0.545894,0.405668,-0.323037, + -0.766999,0.641648,0,0.432577,0.358913,-0.5, + -0.716797,0.697282,0,0.501029,0.437003,-0.5, + -0.694867,0.675869,0.245685,0.512245,0.429169,-0.403475, + -0.766999,0.641648,0,0.432577,0.358913,-0.5, + -0.694867,0.675869,0.245685,0.512245,0.429169,-0.403475, + -0.740072,0.600901,0.302014,0.444878,0.352588,-0.404662, + -0.64127,0.767315,0,0.579177,0.509417,-0.5, + -0.5899,0.750266,0.298526,0.589401,0.500151,-0.402822, + -0.694867,0.675869,0.245685,0.512245,0.429169,-0.403475, + -0.64127,0.767315,0,0.579177,0.509417,-0.5, + -0.694867,0.675869,0.245685,0.512245,0.429169,-0.403475, + -0.716797,0.697282,0,0.501029,0.437003,-0.5, + -0.610536,0.426181,0.667544,0.428341,0.263148,-0.326956, + -0.603758,0.432599,0.669577,0.386176,0.201223,-0.326853, + -0.77971,0.541974,0.313555,0.342801,0.212716,-0.405556, + -0.77971,0.541974,0.313555,0.342801,0.212716,-0.405556, + -0.770954,0.557417,0.308084,0.388123,0.27793,-0.405612, + -0.610536,0.426181,0.667544,0.428341,0.263148,-0.326956, + -0.820475,0.571682,0,0.328343,0.216547,-0.5, + -0.804241,0.594303,0,0.374717,0.282857,-0.5, + -0.770954,0.557417,0.308084,0.388123,0.27793,-0.405612, + -0.820475,0.571682,0,0.328343,0.216547,-0.5, + -0.770954,0.557417,0.308084,0.388123,0.27793,-0.405612, + -0.77971,0.541974,0.313555,0.342801,0.212716,-0.405556, + -0.804241,0.594303,0,0.374717,0.282857,-0.5, + -0.766999,0.641648,0,0.432577,0.358913,-0.5, + -0.740072,0.600901,0.302014,0.444878,0.352588,-0.404662, + -0.740072,0.600901,0.302014,0.444878,0.352588,-0.404662, + -0.770954,0.557417,0.308084,0.388123,0.27793,-0.405612, + -0.804241,0.594303,0,0.374717,0.282857,-0.5, + -0.595775,0.458968,0.659091,0.481782,0.333615,-0.325213, + -0.610536,0.426181,0.667544,0.428341,0.263148,-0.326956, + -0.770954,0.557417,0.308084,0.388123,0.27793,-0.405612, + -0.595775,0.458968,0.659091,0.481782,0.333615,-0.325213, + -0.770954,0.557417,0.308084,0.388123,0.27793,-0.405612, + -0.740072,0.600901,0.302014,0.444878,0.352588,-0.404662, + -0.304433,0.241938,0.921296,0.458468,0.182068,-0.279631, + -0.603758,0.432599,0.669577,0.386176,0.201223,-0.326853, + -0.610536,0.426181,0.667544,0.428341,0.263148,-0.326956, + -0.610536,0.426181,0.667544,0.428341,0.263148,-0.326956, + -0.317966,0.212815,0.923909,0.495371,0.238512,-0.279763, + -0.304433,0.241938,0.921296,0.458468,0.182068,-0.279631, + -0.595775,0.458968,0.659091,0.481782,0.333615,-0.325213, + -0.31459,0.228088,0.921417,0.543287,0.301992,-0.277544, + -0.317966,0.212815,0.923909,0.495371,0.238512,-0.279763, + -0.595775,0.458968,0.659091,0.481782,0.333615,-0.325213, + -0.317966,0.212815,0.923909,0.495371,0.238512,-0.279763, + -0.610536,0.426181,0.667544,0.428341,0.263148,-0.326956, + -0.31459,0.228088,0.921417,0.543287,0.301992,-0.277544, + -0.015914,-0.029529,0.999437,0.617093,0.264045,-0.261655, + -0.005469,-0.009402,0.999941,0.575807,0.208949,-0.264031, + -0.005469,-0.009402,0.999941,0.575807,0.208949,-0.264031, + -0.317966,0.212815,0.923909,0.495371,0.238512,-0.279763, + -0.31459,0.228088,0.921417,0.543287,0.301992,-0.277544, + 0.013842,0.059444,0.998136,0.545218,0.159081,-0.263891, + -0.304433,0.241938,0.921296,0.458468,0.182068,-0.279631, + -0.317966,0.212815,0.923909,0.495371,0.238512,-0.279763, + 0.013842,0.059444,0.998136,0.545218,0.159081,-0.263891, + -0.317966,0.212815,0.923909,0.495371,0.238512,-0.279763, + -0.005469,-0.009402,0.999941,0.575807,0.208949,-0.264031, + -0.459898,0.603331,0.651526,0.620074,0.472355,-0.321841, + -0.231331,0.321253,0.918304,0.671195,0.426029,-0.273252, + -0.288623,0.267481,0.919321,0.601974,0.3665,-0.274775, + -0.459898,0.603331,0.651526,0.620074,0.472355,-0.321841, + -0.288623,0.267481,0.919321,0.601974,0.3665,-0.274775, + -0.565284,0.537872,0.625418,0.545894,0.405668,-0.323037, + -0.231331,0.321253,0.918304,0.671195,0.426029,-0.273252, + 0.003382,-0.001295,0.999993,0.73254,0.370437,-0.257056, + -0.014673,-0.023374,0.999619,0.669271,0.319498,-0.258687, + -0.014673,-0.023374,0.999619,0.669271,0.319498,-0.258687, + -0.288623,0.267481,0.919321,0.601974,0.3665,-0.274775, + -0.231331,0.321253,0.918304,0.671195,0.426029,-0.273252, + -0.015914,-0.029529,0.999437,0.617093,0.264045,-0.261655, + -0.31459,0.228088,0.921417,0.543287,0.301992,-0.277544, + -0.288623,0.267481,0.919321,0.601974,0.3665,-0.274775, + -0.015914,-0.029529,0.999437,0.617093,0.264045,-0.261655, + -0.288623,0.267481,0.919321,0.601974,0.3665,-0.274775, + -0.014673,-0.023374,0.999619,0.669271,0.319498,-0.258687, + -0.31459,0.228088,0.921417,0.543287,0.301992,-0.277544, + -0.595775,0.458968,0.659091,0.481782,0.333615,-0.325213, + -0.565284,0.537872,0.625418,0.545894,0.405668,-0.323037, + -0.565284,0.537872,0.625418,0.545894,0.405668,-0.323037, + -0.288623,0.267481,0.919321,0.601974,0.3665,-0.274775, + -0.31459,0.228088,0.921417,0.543287,0.301992,-0.277544, + 0.214466,-0.34467,0.913896,0.793886,0.314845,-0.273252, + 0.37574,-0.67126,0.638928,0.845007,0.268518,-0.321841, + 0.473587,-0.60369,0.641306,0.792649,0.233327,-0.323037, + 0.473587,-0.60369,0.641306,0.792649,0.233327,-0.323037, + 0.248581,-0.323271,0.913073,0.736568,0.272496,-0.274775, + 0.214466,-0.34467,0.913896,0.793886,0.314845,-0.273252, + 0.525124,-0.503609,0.68602,0.752404,0.194475,-0.325213, + 0.282948,-0.282367,0.916629,0.690899,0.226098,-0.277544, + 0.248581,-0.323271,0.913073,0.736568,0.272496,-0.274775, + 0.525124,-0.503609,0.68602,0.752404,0.194475,-0.325213, + 0.248581,-0.323271,0.913073,0.736568,0.272496,-0.274775, + 0.473587,-0.60369,0.641306,0.792649,0.233327,-0.323037, + 0.282948,-0.282367,0.916629,0.690899,0.226098,-0.277544, + -0.015914,-0.029529,0.999437,0.617093,0.264045,-0.261655, + -0.014673,-0.023374,0.999619,0.669271,0.319498,-0.258687, + -0.014673,-0.023374,0.999619,0.669271,0.319498,-0.258687, + 0.248581,-0.323271,0.913073,0.736568,0.272496,-0.274775, + 0.282948,-0.282367,0.916629,0.690899,0.226098,-0.277544, + 0.003382,-0.001295,0.999993,0.73254,0.370437,-0.257056, + 0.214466,-0.34467,0.913896,0.793886,0.314845,-0.273252, + 0.248581,-0.323271,0.913073,0.736568,0.272496,-0.274775, + 0.003382,-0.001295,0.999993,0.73254,0.370437,-0.257056, + 0.248581,-0.323271,0.913073,0.736568,0.272496,-0.274775, + -0.014673,-0.023374,0.999619,0.669271,0.319498,-0.258687, + 0.677454,-0.2664,0.685629,0.704261,0.116939,-0.326853, + 0.344586,-0.098997,0.93352,0.631969,0.136095,-0.279631, + 0.314626,-0.214176,0.924737,0.656244,0.179386,-0.279763, + 0.677454,-0.2664,0.685629,0.704261,0.116939,-0.326853, + 0.314626,-0.214176,0.924737,0.656244,0.179386,-0.279763, + 0.617578,-0.419693,0.665173,0.723274,0.15475,-0.326956, + 0.344586,-0.098997,0.93352,0.631969,0.136095,-0.279631, + 0.013842,0.059444,0.998136,0.545218,0.159081,-0.263891, + -0.005469,-0.009402,0.999941,0.575807,0.208949,-0.264031, + -0.005469,-0.009402,0.999941,0.575807,0.208949,-0.264031, + 0.314626,-0.214176,0.924737,0.656244,0.179386,-0.279763, + 0.344586,-0.098997,0.93352,0.631969,0.136095,-0.279631, + -0.015914,-0.029529,0.999437,0.617093,0.264045,-0.261655, + 0.282948,-0.282367,0.916629,0.690899,0.226098,-0.277544, + 0.314626,-0.214176,0.924737,0.656244,0.179386,-0.279763, + -0.015914,-0.029529,0.999437,0.617093,0.264045,-0.261655, + 0.314626,-0.214176,0.924737,0.656244,0.179386,-0.279763, + -0.005469,-0.009402,0.999941,0.575807,0.208949,-0.264031, + 0.282948,-0.282367,0.916629,0.690899,0.226098,-0.277544, + 0.525124,-0.503609,0.68602,0.752404,0.194475,-0.325213, + 0.617578,-0.419693,0.665173,0.723274,0.15475,-0.326956, + 0.617578,-0.419693,0.665173,0.723274,0.15475,-0.326956, + 0.314626,-0.214176,0.924737,0.656244,0.179386,-0.279763, + 0.282948,-0.282367,0.916629,0.690899,0.226098,-0.277544, + 0.677454,-0.2664,0.685629,0.704261,0.116939,-0.326853, + 0.617578,-0.419693,0.665173,0.723274,0.15475,-0.326956, + 0.814068,-0.486717,0.316859,0.763492,0.139968,-0.405612, + 0.677454,-0.2664,0.685629,0.704261,0.116939,-0.326853, + 0.814068,-0.486717,0.316859,0.763492,0.139968,-0.405612, + 0.894665,-0.298343,0.332514,0.747636,0.105446,-0.405556, + 0.617578,-0.419693,0.665173,0.723274,0.15475,-0.326956, + 0.525124,-0.503609,0.68602,0.752404,0.194475,-0.325213, + 0.694632,-0.626894,0.352832,0.789307,0.175501,-0.404662, + 0.694632,-0.626894,0.352832,0.789307,0.175501,-0.404662, + 0.814068,-0.486717,0.316859,0.763492,0.139968,-0.405612, + 0.617578,-0.419693,0.665173,0.723274,0.15475,-0.326956, + 0.746099,-0.665835,0,0.801608,0.169177,-0.5, + 0.881754,-0.47171,0,0.776898,0.135041,-0.5, + 0.814068,-0.486717,0.316859,0.763492,0.139968,-0.405612, + 0.746099,-0.665835,0,0.801608,0.169177,-0.5, + 0.814068,-0.486717,0.316859,0.763492,0.139968,-0.405612, + 0.694632,-0.626894,0.352832,0.789307,0.175501,-0.404662, + 0.881754,-0.47171,0,0.776898,0.135041,-0.5, + 0.961956,-0.273203,0,0.762094,0.101615,-0.5, + 0.894665,-0.298343,0.332514,0.747636,0.105446,-0.405556, + 0.894665,-0.298343,0.332514,0.747636,0.105446,-0.405556, + 0.814068,-0.486717,0.316859,0.763492,0.139968,-0.405612, + 0.881754,-0.47171,0,0.776898,0.135041,-0.5, + 0.37574,-0.67126,0.638928,0.845007,0.268518,-0.321841, + 0.438584,-0.8515,0.287389,0.875679,0.240722,-0.402822, + 0.582001,-0.759448,0.290711,0.826297,0.209826,-0.403475, + 0.37574,-0.67126,0.638928,0.845007,0.268518,-0.321841, + 0.582001,-0.759448,0.290711,0.826297,0.209826,-0.403475, + 0.473587,-0.60369,0.641306,0.792649,0.233327,-0.323037, + 0.438584,-0.8515,0.287389,0.875679,0.240722,-0.402822, + 0.419512,-0.90775,0,0.885904,0.231457,-0.5, + 0.576871,-0.816835,0,0.837513,0.201992,-0.5, + 0.576871,-0.816835,0,0.837513,0.201992,-0.5, + 0.582001,-0.759448,0.290711,0.826297,0.209826,-0.403475, + 0.438584,-0.8515,0.287389,0.875679,0.240722,-0.402822, + 0.746099,-0.665835,0,0.801608,0.169177,-0.5, + 0.694632,-0.626894,0.352832,0.789307,0.175501,-0.404662, + 0.582001,-0.759448,0.290711,0.826297,0.209826,-0.403475, + 0.746099,-0.665835,0,0.801608,0.169177,-0.5, + 0.582001,-0.759448,0.290711,0.826297,0.209826,-0.403475, + 0.576871,-0.816835,0,0.837513,0.201992,-0.5, + 0.694632,-0.626894,0.352832,0.789307,0.175501,-0.404662, + 0.525124,-0.503609,0.68602,0.752404,0.194475,-0.325213, + 0.473587,-0.60369,0.641306,0.792649,0.233327,-0.323037, + 0.473587,-0.60369,0.641306,0.792649,0.233327,-0.323037, + 0.582001,-0.759448,0.290711,0.826297,0.209826,-0.403475, + 0.694632,-0.626894,0.352832,0.789307,0.175501,-0.404662, + 0.37574,-0.67126,-0.638928,0.845007,0.268518,-0.678159, + 0.473586,-0.60369,-0.641307,0.792649,0.233327,-0.676962, + 0.582001,-0.759448,-0.290711,0.826297,0.209826,-0.596525, + 0.37574,-0.67126,-0.638928,0.845007,0.268518,-0.678159, + 0.582001,-0.759448,-0.290711,0.826297,0.209826,-0.596525, + 0.438584,-0.8515,-0.287389,0.875679,0.240722,-0.597178, + 0.473586,-0.60369,-0.641307,0.792649,0.233327,-0.676962, + 0.525124,-0.503608,-0.68602,0.752404,0.194475,-0.674787, + 0.694632,-0.626893,-0.352832,0.789307,0.175501,-0.595338, + 0.694632,-0.626893,-0.352832,0.789307,0.175501,-0.595338, + 0.582001,-0.759448,-0.290711,0.826297,0.209826,-0.596525, + 0.473586,-0.60369,-0.641307,0.792649,0.233327,-0.676962, + 0.746099,-0.665835,0,0.801608,0.169177,-0.5, + 0.576871,-0.816835,0,0.837513,0.201992,-0.5, + 0.582001,-0.759448,-0.290711,0.826297,0.209826,-0.596525, + 0.746099,-0.665835,0,0.801608,0.169177,-0.5, + 0.582001,-0.759448,-0.290711,0.826297,0.209826,-0.596525, + 0.694632,-0.626893,-0.352832,0.789307,0.175501,-0.595338, + 0.576871,-0.816835,0,0.837513,0.201992,-0.5, + 0.419512,-0.90775,0,0.885904,0.231457,-0.5, + 0.438584,-0.8515,-0.287389,0.875679,0.240722,-0.597178, + 0.438584,-0.8515,-0.287389,0.875679,0.240722,-0.597178, + 0.582001,-0.759448,-0.290711,0.826297,0.209826,-0.596525, + 0.576871,-0.816835,0,0.837513,0.201992,-0.5, + 0.677454,-0.2664,-0.685629,0.704261,0.116939,-0.673147, + 0.894665,-0.298343,-0.332514,0.747636,0.105446,-0.594444, + 0.814068,-0.486716,-0.31686,0.763492,0.139968,-0.594388, + 0.677454,-0.2664,-0.685629,0.704261,0.116939,-0.673147, + 0.814068,-0.486716,-0.31686,0.763492,0.139968,-0.594388, + 0.617578,-0.419692,-0.665174,0.723274,0.15475,-0.673044, + 0.894665,-0.298343,-0.332514,0.747636,0.105446,-0.594444, + 0.961956,-0.273203,0,0.762094,0.101615,-0.5, + 0.881754,-0.47171,0,0.776898,0.135041,-0.5, + 0.881754,-0.47171,0,0.776898,0.135041,-0.5, + 0.814068,-0.486716,-0.31686,0.763492,0.139968,-0.594388, + 0.894665,-0.298343,-0.332514,0.747636,0.105446,-0.594444, + 0.746099,-0.665835,0,0.801608,0.169177,-0.5, + 0.694632,-0.626893,-0.352832,0.789307,0.175501,-0.595338, + 0.814068,-0.486716,-0.31686,0.763492,0.139968,-0.594388, + 0.746099,-0.665835,0,0.801608,0.169177,-0.5, + 0.814068,-0.486716,-0.31686,0.763492,0.139968,-0.594388, + 0.881754,-0.47171,0,0.776898,0.135041,-0.5, + 0.694632,-0.626893,-0.352832,0.789307,0.175501,-0.595338, + 0.525124,-0.503608,-0.68602,0.752404,0.194475,-0.674787, + 0.617578,-0.419692,-0.665174,0.723274,0.15475,-0.673044, + 0.617578,-0.419692,-0.665174,0.723274,0.15475,-0.673044, + 0.814068,-0.486716,-0.31686,0.763492,0.139968,-0.594388, + 0.694632,-0.626893,-0.352832,0.789307,0.175501,-0.595338, + 0.691984,-0.189259,0.696663,0.694366,0.083832,-0.323491, + 0.677454,-0.2664,0.685629,0.704261,0.116939,-0.326853, + 0.894665,-0.298343,0.332514,0.747636,0.105446,-0.405556, + 0.894665,-0.298343,0.332514,0.747636,0.105446,-0.405556, + 0.903923,-0.26074,0.339026,0.740522,0.074155,-0.403722, + 0.691984,-0.189259,0.696663,0.694366,0.083832,-0.323491, + 0.961956,-0.273203,0,0.762094,0.101615,-0.5, + 0.957991,-0.286797,0,0.755907,0.07093,-0.5, + 0.903923,-0.26074,0.339026,0.740522,0.074155,-0.403722, + 0.961956,-0.273203,0,0.762094,0.101615,-0.5, + 0.903923,-0.26074,0.339026,0.740522,0.074155,-0.403722, + 0.894665,-0.298343,0.332514,0.747636,0.105446,-0.405556, + 0.957991,-0.286797,0,0.755907,0.07093,-0.5, + 0.740764,-0.671765,0,0.747335,0.045755,-0.5, + 0.78946,-0.545462,0.281469,0.731601,0.048967,-0.404556, + 0.78946,-0.545462,0.281469,0.731601,0.048967,-0.404556, + 0.903923,-0.26074,0.339026,0.740522,0.074155,-0.403722, + 0.957991,-0.286797,0,0.755907,0.07093,-0.5, + 0.570752,-0.537595,0.620673,0.684631,0.057942,-0.324904, + 0.691984,-0.189259,0.696663,0.694366,0.083832,-0.323491, + 0.903923,-0.26074,0.339026,0.740522,0.074155,-0.403722, + 0.570752,-0.537595,0.620673,0.684631,0.057942,-0.324904, + 0.903923,-0.26074,0.339026,0.740522,0.074155,-0.403722, + 0.78946,-0.545462,0.281469,0.731601,0.048967,-0.404556, + 0.894665,-0.298343,-0.332514,0.747636,0.105446,-0.594444, + 0.677454,-0.2664,-0.685629,0.704261,0.116939,-0.673147, + 0.691984,-0.189259,-0.696663,0.694366,0.083832,-0.676509, + 0.691984,-0.189259,-0.696663,0.694366,0.083832,-0.676509, + 0.903923,-0.26074,-0.339025,0.740522,0.074155,-0.596277, + 0.894665,-0.298343,-0.332514,0.747636,0.105446,-0.594444, + 0.570751,-0.537595,-0.620672,0.684631,0.057942,-0.675096, + 0.789459,-0.545462,-0.281469,0.731601,0.048967,-0.595444, + 0.903923,-0.26074,-0.339025,0.740522,0.074155,-0.596277, + 0.570751,-0.537595,-0.620672,0.684631,0.057942,-0.675096, + 0.903923,-0.26074,-0.339025,0.740522,0.074155,-0.596277, + 0.691984,-0.189259,-0.696663,0.694366,0.083832,-0.676509, + 0.789459,-0.545462,-0.281469,0.731601,0.048967,-0.595444, + 0.740764,-0.671765,0,0.747335,0.045755,-0.5, + 0.957991,-0.286797,0,0.755907,0.07093,-0.5, + 0.957991,-0.286797,0,0.755907,0.07093,-0.5, + 0.903923,-0.26074,-0.339025,0.740522,0.074155,-0.596277, + 0.789459,-0.545462,-0.281469,0.731601,0.048967,-0.595444, + 0.961956,-0.273203,0,0.762094,0.101615,-0.5, + 0.894665,-0.298343,-0.332514,0.747636,0.105446,-0.594444, + 0.903923,-0.26074,-0.339025,0.740522,0.074155,-0.596277, + 0.961956,-0.273203,0,0.762094,0.101615,-0.5, + 0.903923,-0.26074,-0.339025,0.740522,0.074155,-0.596277, + 0.957991,-0.286797,0,0.755907,0.07093,-0.5, + 0.029695,-0.979483,-0.199329,0.642426,0.035438,-0.638667, + 0.015839,-0.994833,-0.100277,0.667212,0.026513,-0.5825, + 0.33287,-0.922331,-0.196223,0.710325,0.03275,-0.5875, + 0.029695,-0.979483,-0.199329,0.642426,0.035438,-0.638667, + 0.33287,-0.922331,-0.196223,0.710325,0.03275,-0.5875, + 0.21248,-0.884802,-0.414701,0.666096,0.041783,-0.660875, + 0.072467,-0.997371,0,0.679568,0.022087,-0.5, + 0.389749,-0.920921,0,0.725378,0.028862,-0.5, + 0.33287,-0.922331,-0.196223,0.710325,0.03275,-0.5875, + 0.072467,-0.997371,0,0.679568,0.022087,-0.5, + 0.33287,-0.922331,-0.196223,0.710325,0.03275,-0.5875, + 0.015839,-0.994833,-0.100277,0.667212,0.026513,-0.5825, + 0.740764,-0.671765,0,0.747335,0.045755,-0.5, + 0.789459,-0.545462,-0.281469,0.731601,0.048967,-0.595444, + 0.33287,-0.922331,-0.196223,0.710325,0.03275,-0.5875, + 0.740764,-0.671765,0,0.747335,0.045755,-0.5, + 0.33287,-0.922331,-0.196223,0.710325,0.03275,-0.5875, + 0.389749,-0.920921,0,0.725378,0.028862,-0.5, + 0.570751,-0.537595,-0.620672,0.684631,0.057942,-0.675096, + 0.21248,-0.884802,-0.414701,0.666096,0.041783,-0.660875, + 0.33287,-0.922331,-0.196223,0.710325,0.03275,-0.5875, + 0.570751,-0.537595,-0.620672,0.684631,0.057942,-0.675096, + 0.33287,-0.922331,-0.196223,0.710325,0.03275,-0.5875, + 0.789459,-0.545462,-0.281469,0.731601,0.048967,-0.595444, + 0.029695,-0.979483,0.199329,0.642426,0.035438,-0.361333, + 0.21248,-0.884802,0.414702,0.666096,0.041783,-0.339125, + 0.33287,-0.922331,0.196223,0.710325,0.03275,-0.4125, + 0.029695,-0.979483,0.199329,0.642426,0.035438,-0.361333, + 0.33287,-0.922331,0.196223,0.710325,0.03275,-0.4125, + 0.015839,-0.994833,0.100277,0.667212,0.026513,-0.4175, + 0.570752,-0.537595,0.620673,0.684631,0.057942,-0.324904, + 0.78946,-0.545462,0.281469,0.731601,0.048967,-0.404556, + 0.33287,-0.922331,0.196223,0.710325,0.03275,-0.4125, + 0.570752,-0.537595,0.620673,0.684631,0.057942,-0.324904, + 0.33287,-0.922331,0.196223,0.710325,0.03275,-0.4125, + 0.21248,-0.884802,0.414702,0.666096,0.041783,-0.339125, + 0.740764,-0.671765,0,0.747335,0.045755,-0.5, + 0.389749,-0.920921,0,0.725378,0.028862,-0.5, + 0.33287,-0.922331,0.196223,0.710325,0.03275,-0.4125, + 0.740764,-0.671765,0,0.747335,0.045755,-0.5, + 0.33287,-0.922331,0.196223,0.710325,0.03275,-0.4125, + 0.78946,-0.545462,0.281469,0.731601,0.048967,-0.404556, + 0.072467,-0.997371,0,0.679568,0.022087,-0.5, + 0.015839,-0.994833,0.100277,0.667212,0.026513,-0.4175, + 0.33287,-0.922331,0.196223,0.710325,0.03275,-0.4125, + 0.072467,-0.997371,0,0.679568,0.022087,-0.5, + 0.33287,-0.922331,0.196223,0.710325,0.03275,-0.4125, + 0.389749,-0.920921,0,0.725378,0.028862,-0.5, + 0.691984,-0.189259,-0.696663,0.694366,0.083832,-0.676509, + 0.677454,-0.2664,-0.685629,0.704261,0.116939,-0.673147, + 0.344586,-0.098997,-0.93352,0.631969,0.136095,-0.720369, + 0.344586,-0.098997,-0.93352,0.631969,0.136095,-0.720369, + 0.338241,-0.103362,-0.935366,0.61744,0.099959,-0.724648, + 0.691984,-0.189259,-0.696663,0.694366,0.083832,-0.676509, + 0.013842,0.059444,-0.998136,0.545218,0.159081,-0.736109, + 0.007661,0.031192,-0.999484,0.525128,0.119312,-0.740694, + 0.338241,-0.103362,-0.935366,0.61744,0.099959,-0.724648, + 0.013842,0.059444,-0.998136,0.545218,0.159081,-0.736109, + 0.338241,-0.103362,-0.935366,0.61744,0.099959,-0.724648, + 0.344586,-0.098997,-0.93352,0.631969,0.136095,-0.720369, + 0.007661,0.031192,-0.999484,0.525128,0.119312,-0.740694, + -0.09747,-0.388654,-0.916214,0.513237,0.088956,-0.739298, + 0.227406,-0.473471,-0.850947,0.606658,0.072023,-0.723162, + 0.227406,-0.473471,-0.850947,0.606658,0.072023,-0.723162, + 0.338241,-0.103362,-0.935366,0.61744,0.099959,-0.724648, + 0.007661,0.031192,-0.999484,0.525128,0.119312,-0.740694, + 0.570751,-0.537595,-0.620672,0.684631,0.057942,-0.675096, + 0.691984,-0.189259,-0.696663,0.694366,0.083832,-0.676509, + 0.338241,-0.103362,-0.935366,0.61744,0.099959,-0.724648, + 0.570751,-0.537595,-0.620672,0.684631,0.057942,-0.675096, + 0.338241,-0.103362,-0.935366,0.61744,0.099959,-0.724648, + 0.227406,-0.473471,-0.850947,0.606658,0.072023,-0.723162, + -0.603758,0.432599,-0.669577,0.386176,0.201223,-0.673147, + -0.649491,0.313781,-0.692606,0.355891,0.154793,-0.676509, + -0.317034,0.182994,-0.930593,0.432817,0.138665,-0.724648, + -0.603758,0.432599,-0.669577,0.386176,0.201223,-0.673147, + -0.317034,0.182994,-0.930593,0.432817,0.138665,-0.724648, + -0.304433,0.241938,-0.921296,0.458468,0.182068,-0.720369, + -0.649491,0.313781,-0.692606,0.355891,0.154793,-0.676509, + -0.720224,-0.15594,-0.675988,0.342054,0.121167,-0.675096, + -0.440529,-0.24065,-0.864882,0.419921,0.106487,-0.723162, + -0.440529,-0.24065,-0.864882,0.419921,0.106487,-0.723162, + -0.317034,0.182994,-0.930593,0.432817,0.138665,-0.724648, + -0.649491,0.313781,-0.692606,0.355891,0.154793,-0.676509, + -0.09747,-0.388654,-0.916214,0.513237,0.088956,-0.739298, + 0.007661,0.031192,-0.999484,0.525128,0.119312,-0.740694, + -0.317034,0.182994,-0.930593,0.432817,0.138665,-0.724648, + -0.09747,-0.388654,-0.916214,0.513237,0.088956,-0.739298, + -0.317034,0.182994,-0.930593,0.432817,0.138665,-0.724648, + -0.440529,-0.24065,-0.864882,0.419921,0.106487,-0.723162, + 0.007661,0.031192,-0.999484,0.525128,0.119312,-0.740694, + 0.013842,0.059444,-0.998136,0.545218,0.159081,-0.736109, + -0.304433,0.241938,-0.921296,0.458468,0.182068,-0.720369, + -0.304433,0.241938,-0.921296,0.458468,0.182068,-0.720369, + -0.317034,0.182994,-0.930593,0.432817,0.138665,-0.724648, + 0.007661,0.031192,-0.999484,0.525128,0.119312,-0.740694, + -0.560128,-0.705465,-0.434253,0.349234,0.097654,-0.660875, + -0.364711,-0.913648,-0.179534,0.369306,0.083596,-0.638667, + -0.280571,-0.938896,-0.199385,0.423841,0.069426,-0.664625, + -0.280571,-0.938896,-0.199385,0.423841,0.069426,-0.664625, + -0.32072,-0.774629,-0.545059,0.421284,0.083716,-0.706, + -0.560128,-0.705465,-0.434253,0.349234,0.097654,-0.660875, + -0.168375,-0.954904,-0.244557,0.504703,0.05292,-0.677562, + -0.143026,-0.80792,-0.571672,0.507243,0.067325,-0.7215, + -0.32072,-0.774629,-0.545059,0.421284,0.083716,-0.706, + -0.168375,-0.954904,-0.244557,0.504703,0.05292,-0.677562, + -0.32072,-0.774629,-0.545059,0.421284,0.083716,-0.706, + -0.280571,-0.938896,-0.199385,0.423841,0.069426,-0.664625, + -0.09747,-0.388654,-0.916214,0.513237,0.088956,-0.739298, + -0.440529,-0.24065,-0.864882,0.419921,0.106487,-0.723162, + -0.32072,-0.774629,-0.545059,0.421284,0.083716,-0.706, + -0.09747,-0.388654,-0.916214,0.513237,0.088956,-0.739298, + -0.32072,-0.774629,-0.545059,0.421284,0.083716,-0.706, + -0.143026,-0.80792,-0.571672,0.507243,0.067325,-0.7215, + -0.440529,-0.24065,-0.864882,0.419921,0.106487,-0.723162, + -0.720224,-0.15594,-0.675988,0.342054,0.121167,-0.675096, + -0.560128,-0.705465,-0.434253,0.349234,0.097654,-0.660875, + -0.560128,-0.705465,-0.434253,0.349234,0.097654,-0.660875, + -0.32072,-0.774629,-0.545059,0.421284,0.083716,-0.706, + -0.440529,-0.24065,-0.864882,0.419921,0.106487,-0.723162, + 0.029695,-0.979483,-0.199329,0.642426,0.035438,-0.638667, + 0.21248,-0.884802,-0.414701,0.666096,0.041783,-0.660875, + 0.024087,-0.872904,-0.487296,0.593625,0.053327,-0.706, + 0.029695,-0.979483,-0.199329,0.642426,0.035438,-0.638667, + 0.024087,-0.872904,-0.487296,0.593625,0.053327,-0.706, + -0.070895,-0.97954,-0.18835,0.586334,0.040774,-0.664625, + 0.21248,-0.884802,-0.414701,0.666096,0.041783,-0.660875, + 0.570751,-0.537595,-0.620672,0.684631,0.057942,-0.675096, + 0.227406,-0.473471,-0.850947,0.606658,0.072023,-0.723162, + 0.227406,-0.473471,-0.850947,0.606658,0.072023,-0.723162, + 0.024087,-0.872904,-0.487296,0.593625,0.053327,-0.706, + 0.21248,-0.884802,-0.414701,0.666096,0.041783,-0.660875, + -0.09747,-0.388654,-0.916214,0.513237,0.088956,-0.739298, + -0.143026,-0.80792,-0.571672,0.507243,0.067325,-0.7215, + 0.024087,-0.872904,-0.487296,0.593625,0.053327,-0.706, + -0.09747,-0.388654,-0.916214,0.513237,0.088956,-0.739298, + 0.024087,-0.872904,-0.487296,0.593625,0.053327,-0.706, + 0.227406,-0.473471,-0.850947,0.606658,0.072023,-0.723162, + -0.168375,-0.954904,-0.244557,0.504703,0.05292,-0.677562, + -0.070895,-0.97954,-0.18835,0.586334,0.040774,-0.664625, + 0.024087,-0.872904,-0.487296,0.593625,0.053327,-0.706, + -0.168375,-0.954904,-0.244557,0.504703,0.05292,-0.677562, + 0.024087,-0.872904,-0.487296,0.593625,0.053327,-0.706, + -0.143026,-0.80792,-0.571672,0.507243,0.067325,-0.7215, + -0.603758,0.432599,-0.669577,0.386176,0.201223,-0.673147, + -0.77971,0.541974,-0.313555,0.342801,0.212716,-0.594444, + -0.828821,0.45488,-0.325791,0.309735,0.164469,-0.596277, + -0.603758,0.432599,-0.669577,0.386176,0.201223,-0.673147, + -0.828821,0.45488,-0.325791,0.309735,0.164469,-0.596277, + -0.649491,0.313781,-0.692606,0.355891,0.154793,-0.676509, + -0.77971,0.541974,-0.313555,0.342801,0.212716,-0.594444, + -0.820475,0.571682,0,0.328343,0.216547,-0.5, + -0.857982,0.51368,0,0.29435,0.167695,-0.5, + -0.857982,0.51368,0,0.29435,0.167695,-0.5, + -0.828821,0.45488,-0.325791,0.309735,0.164469,-0.596277, + -0.77971,0.541974,-0.313555,0.342801,0.212716,-0.594444, + -0.999967,0.008167,0,0.279139,0.132156,-0.5, + -0.916555,-0.053852,-0.396267,0.294978,0.129544,-0.595444, + -0.828821,0.45488,-0.325791,0.309735,0.164469,-0.596277, + -0.999967,0.008167,0,0.279139,0.132156,-0.5, + -0.828821,0.45488,-0.325791,0.309735,0.164469,-0.596277, + -0.857982,0.51368,0,0.29435,0.167695,-0.5, + -0.916555,-0.053852,-0.396267,0.294978,0.129544,-0.595444, + -0.720224,-0.15594,-0.675988,0.342054,0.121167,-0.675096, + -0.649491,0.313781,-0.692606,0.355891,0.154793,-0.676509, + -0.649491,0.313781,-0.692606,0.355891,0.154793,-0.676509, + -0.828821,0.45488,-0.325791,0.309735,0.164469,-0.596277, + -0.916555,-0.053852,-0.396267,0.294978,0.129544,-0.595444, + -0.603758,0.432599,0.669577,0.386176,0.201223,-0.326853, + -0.649491,0.313782,0.692606,0.355891,0.154793,-0.323491, + -0.828821,0.454881,0.325791,0.309735,0.164469,-0.403722, + -0.603758,0.432599,0.669577,0.386176,0.201223,-0.326853, + -0.828821,0.454881,0.325791,0.309735,0.164469,-0.403722, + -0.77971,0.541974,0.313555,0.342801,0.212716,-0.405556, + -0.649491,0.313782,0.692606,0.355891,0.154793,-0.323491, + -0.720224,-0.155939,0.675988,0.342054,0.121167,-0.324904, + -0.916555,-0.053852,0.396267,0.294978,0.129544,-0.404556, + -0.916555,-0.053852,0.396267,0.294978,0.129544,-0.404556, + -0.828821,0.454881,0.325791,0.309735,0.164469,-0.403722, + -0.649491,0.313782,0.692606,0.355891,0.154793,-0.323491, + -0.999967,0.008167,0,0.279139,0.132156,-0.5, + -0.857982,0.51368,0,0.29435,0.167695,-0.5, + -0.828821,0.454881,0.325791,0.309735,0.164469,-0.403722, + -0.999967,0.008167,0,0.279139,0.132156,-0.5, + -0.828821,0.454881,0.325791,0.309735,0.164469,-0.403722, + -0.916555,-0.053852,0.396267,0.294978,0.129544,-0.404556, + -0.857982,0.51368,0,0.29435,0.167695,-0.5, + -0.820475,0.571682,0,0.328343,0.216547,-0.5, + -0.77971,0.541974,0.313555,0.342801,0.212716,-0.405556, + -0.77971,0.541974,0.313555,0.342801,0.212716,-0.405556, + -0.828821,0.454881,0.325791,0.309735,0.164469,-0.403722, + -0.857982,0.51368,0,0.29435,0.167695,-0.5, + -0.364711,-0.913648,0.179534,0.369306,0.083596,-0.361333, + -0.355137,-0.92942,0.100277,0.342964,0.083687,-0.4175, + -0.672934,-0.714357,0.191973,0.304584,0.104293,-0.4125, + -0.364711,-0.913648,0.179534,0.369306,0.083596,-0.361333, + -0.672934,-0.714357,0.191973,0.304584,0.104293,-0.4125, + -0.560128,-0.705466,0.434252,0.349234,0.097654,-0.339125, + -0.409218,-0.912437,0,0.329838,0.083754,-0.5, + -0.75175,-0.659448,0,0.289108,0.105788,-0.5, + -0.672934,-0.714357,0.191973,0.304584,0.104293,-0.4125, + -0.409218,-0.912437,0,0.329838,0.083754,-0.5, + -0.672934,-0.714357,0.191973,0.304584,0.104293,-0.4125, + -0.355137,-0.92942,0.100277,0.342964,0.083687,-0.4175, + -0.999967,0.008167,0,0.279139,0.132156,-0.5, + -0.916555,-0.053852,0.396267,0.294978,0.129544,-0.404556, + -0.672934,-0.714357,0.191973,0.304584,0.104293,-0.4125, + -0.999967,0.008167,0,0.279139,0.132156,-0.5, + -0.672934,-0.714357,0.191973,0.304584,0.104293,-0.4125, + -0.75175,-0.659448,0,0.289108,0.105788,-0.5, + -0.916555,-0.053852,0.396267,0.294978,0.129544,-0.404556, + -0.720224,-0.155939,0.675988,0.342054,0.121167,-0.324904, + -0.560128,-0.705466,0.434252,0.349234,0.097654,-0.339125, + -0.560128,-0.705466,0.434252,0.349234,0.097654,-0.339125, + -0.672934,-0.714357,0.191973,0.304584,0.104293,-0.4125, + -0.916555,-0.053852,0.396267,0.294978,0.129544,-0.404556, + -0.364711,-0.913648,-0.179534,0.369306,0.083596,-0.638667, + -0.560128,-0.705465,-0.434253,0.349234,0.097654,-0.660875, + -0.672934,-0.714357,-0.191973,0.304584,0.104293,-0.5875, + -0.364711,-0.913648,-0.179534,0.369306,0.083596,-0.638667, + -0.672934,-0.714357,-0.191973,0.304584,0.104293,-0.5875, + -0.355137,-0.92942,-0.100277,0.342964,0.083687,-0.5825, + -0.560128,-0.705465,-0.434253,0.349234,0.097654,-0.660875, + -0.720224,-0.15594,-0.675988,0.342054,0.121167,-0.675096, + -0.916555,-0.053852,-0.396267,0.294978,0.129544,-0.595444, + -0.916555,-0.053852,-0.396267,0.294978,0.129544,-0.595444, + -0.672934,-0.714357,-0.191973,0.304584,0.104293,-0.5875, + -0.560128,-0.705465,-0.434253,0.349234,0.097654,-0.660875, + -0.999967,0.008167,0,0.279139,0.132156,-0.5, + -0.75175,-0.659448,0,0.289108,0.105788,-0.5, + -0.672934,-0.714357,-0.191973,0.304584,0.104293,-0.5875, + -0.999967,0.008167,0,0.279139,0.132156,-0.5, + -0.672934,-0.714357,-0.191973,0.304584,0.104293,-0.5875, + -0.916555,-0.053852,-0.396267,0.294978,0.129544,-0.595444, + -0.409218,-0.912437,0,0.329838,0.083754,-0.5, + -0.355137,-0.92942,-0.100277,0.342964,0.083687,-0.5825, + -0.672934,-0.714357,-0.191973,0.304584,0.104293,-0.5875, + -0.409218,-0.912437,0,0.329838,0.083754,-0.5, + -0.672934,-0.714357,-0.191973,0.304584,0.104293,-0.5875, + -0.75175,-0.659448,0,0.289108,0.105788,-0.5, + -0.603758,0.432599,0.669577,0.386176,0.201223,-0.326853, + -0.304433,0.241938,0.921296,0.458468,0.182068,-0.279631, + -0.317035,0.182994,0.930592,0.432817,0.138665,-0.275352, + -0.603758,0.432599,0.669577,0.386176,0.201223,-0.326853, + -0.317035,0.182994,0.930592,0.432817,0.138665,-0.275352, + -0.649491,0.313782,0.692606,0.355891,0.154793,-0.323491, + -0.304433,0.241938,0.921296,0.458468,0.182068,-0.279631, + 0.013842,0.059444,0.998136,0.545218,0.159081,-0.263891, + 0.007661,0.031192,0.999484,0.525128,0.119312,-0.259306, + 0.007661,0.031192,0.999484,0.525128,0.119312,-0.259306, + -0.317035,0.182994,0.930592,0.432817,0.138665,-0.275352, + -0.304433,0.241938,0.921296,0.458468,0.182068,-0.279631, + -0.09747,-0.388653,0.916214,0.513237,0.088956,-0.260702, + -0.44053,-0.240649,0.864882,0.419921,0.106487,-0.276838, + -0.317035,0.182994,0.930592,0.432817,0.138665,-0.275352, + -0.09747,-0.388653,0.916214,0.513237,0.088956,-0.260702, + -0.317035,0.182994,0.930592,0.432817,0.138665,-0.275352, + 0.007661,0.031192,0.999484,0.525128,0.119312,-0.259306, + -0.44053,-0.240649,0.864882,0.419921,0.106487,-0.276838, + -0.720224,-0.155939,0.675988,0.342054,0.121167,-0.324904, + -0.649491,0.313782,0.692606,0.355891,0.154793,-0.323491, + -0.649491,0.313782,0.692606,0.355891,0.154793,-0.323491, + -0.317035,0.182994,0.930592,0.432817,0.138665,-0.275352, + -0.44053,-0.240649,0.864882,0.419921,0.106487,-0.276838, + 0.344586,-0.098997,0.93352,0.631969,0.136095,-0.279631, + 0.677454,-0.2664,0.685629,0.704261,0.116939,-0.326853, + 0.691984,-0.189259,0.696663,0.694366,0.083832,-0.323491, + 0.691984,-0.189259,0.696663,0.694366,0.083832,-0.323491, + 0.338242,-0.103362,0.935366,0.61744,0.099959,-0.275352, + 0.344586,-0.098997,0.93352,0.631969,0.136095,-0.279631, + 0.570752,-0.537595,0.620673,0.684631,0.057942,-0.324904, + 0.227406,-0.473471,0.850948,0.606658,0.072023,-0.276838, + 0.338242,-0.103362,0.935366,0.61744,0.099959,-0.275352, + 0.570752,-0.537595,0.620673,0.684631,0.057942,-0.324904, + 0.338242,-0.103362,0.935366,0.61744,0.099959,-0.275352, + 0.691984,-0.189259,0.696663,0.694366,0.083832,-0.323491, + 0.227406,-0.473471,0.850948,0.606658,0.072023,-0.276838, + -0.09747,-0.388653,0.916214,0.513237,0.088956,-0.260702, + 0.007661,0.031192,0.999484,0.525128,0.119312,-0.259306, + 0.007661,0.031192,0.999484,0.525128,0.119312,-0.259306, + 0.338242,-0.103362,0.935366,0.61744,0.099959,-0.275352, + 0.227406,-0.473471,0.850948,0.606658,0.072023,-0.276838, + 0.013842,0.059444,0.998136,0.545218,0.159081,-0.263891, + 0.344586,-0.098997,0.93352,0.631969,0.136095,-0.279631, + 0.338242,-0.103362,0.935366,0.61744,0.099959,-0.275352, + 0.013842,0.059444,0.998136,0.545218,0.159081,-0.263891, + 0.338242,-0.103362,0.935366,0.61744,0.099959,-0.275352, + 0.007661,0.031192,0.999484,0.525128,0.119312,-0.259306, + 0.029695,-0.979483,0.199329,0.642426,0.035438,-0.361333, + -0.070895,-0.97954,0.188349,0.586334,0.040774,-0.335375, + 0.024087,-0.872904,0.487296,0.593625,0.053327,-0.294, + 0.029695,-0.979483,0.199329,0.642426,0.035438,-0.361333, + 0.024087,-0.872904,0.487296,0.593625,0.053327,-0.294, + 0.21248,-0.884802,0.414702,0.666096,0.041783,-0.339125, + -0.168376,-0.954904,0.244557,0.504703,0.05292,-0.322437, + -0.143026,-0.80792,0.571672,0.507243,0.067325,-0.2785, + 0.024087,-0.872904,0.487296,0.593625,0.053327,-0.294, + -0.168376,-0.954904,0.244557,0.504703,0.05292,-0.322437, + 0.024087,-0.872904,0.487296,0.593625,0.053327,-0.294, + -0.070895,-0.97954,0.188349,0.586334,0.040774,-0.335375, + -0.09747,-0.388653,0.916214,0.513237,0.088956,-0.260702, + 0.227406,-0.473471,0.850948,0.606658,0.072023,-0.276838, + 0.024087,-0.872904,0.487296,0.593625,0.053327,-0.294, + -0.09747,-0.388653,0.916214,0.513237,0.088956,-0.260702, + 0.024087,-0.872904,0.487296,0.593625,0.053327,-0.294, + -0.143026,-0.80792,0.571672,0.507243,0.067325,-0.2785, + 0.227406,-0.473471,0.850948,0.606658,0.072023,-0.276838, + 0.570752,-0.537595,0.620673,0.684631,0.057942,-0.324904, + 0.21248,-0.884802,0.414702,0.666096,0.041783,-0.339125, + 0.21248,-0.884802,0.414702,0.666096,0.041783,-0.339125, + 0.024087,-0.872904,0.487296,0.593625,0.053327,-0.294, + 0.227406,-0.473471,0.850948,0.606658,0.072023,-0.276838, + -0.280571,-0.938896,0.199385,0.423841,0.069426,-0.335375, + -0.364711,-0.913648,0.179534,0.369306,0.083596,-0.361333, + -0.560128,-0.705466,0.434252,0.349234,0.097654,-0.339125, + -0.560128,-0.705466,0.434252,0.349234,0.097654,-0.339125, + -0.32072,-0.774629,0.545059,0.421284,0.083716,-0.294, + -0.280571,-0.938896,0.199385,0.423841,0.069426,-0.335375, + -0.560128,-0.705466,0.434252,0.349234,0.097654,-0.339125, + -0.720224,-0.155939,0.675988,0.342054,0.121167,-0.324904, + -0.44053,-0.240649,0.864882,0.419921,0.106487,-0.276838, + -0.44053,-0.240649,0.864882,0.419921,0.106487,-0.276838, + -0.32072,-0.774629,0.545059,0.421284,0.083716,-0.294, + -0.560128,-0.705466,0.434252,0.349234,0.097654,-0.339125, + -0.09747,-0.388653,0.916214,0.513237,0.088956,-0.260702, + -0.143026,-0.80792,0.571672,0.507243,0.067325,-0.2785, + -0.32072,-0.774629,0.545059,0.421284,0.083716,-0.294, + -0.09747,-0.388653,0.916214,0.513237,0.088956,-0.260702, + -0.32072,-0.774629,0.545059,0.421284,0.083716,-0.294, + -0.44053,-0.240649,0.864882,0.419921,0.106487,-0.276838, + -0.168376,-0.954904,0.244557,0.504703,0.05292,-0.322437, + -0.280571,-0.938896,0.199385,0.423841,0.069426,-0.335375, + -0.32072,-0.774629,0.545059,0.421284,0.083716,-0.294, + -0.168376,-0.954904,0.244557,0.504703,0.05292,-0.322437, + -0.32072,-0.774629,0.545059,0.421284,0.083716,-0.294, + -0.143026,-0.80792,0.571672,0.507243,0.067325,-0.2785, + 0.029695,-0.979483,-0.199329,0.642426,0.035438,-0.638667, + -0.070895,-0.97954,-0.18835,0.586334,0.040774,-0.664625, + -0.094013,-0.992373,-0.079739,0.592781,0.031264,-0.5905, + 0.029695,-0.979483,-0.199329,0.642426,0.035438,-0.638667, + -0.094013,-0.992373,-0.079739,0.592781,0.031264,-0.5905, + 0.015839,-0.994833,-0.100277,0.667212,0.026513,-0.5825, + -0.070895,-0.97954,-0.18835,0.586334,0.040774,-0.664625, + -0.168375,-0.954904,-0.244557,0.504703,0.05292,-0.677562, + -0.17302,-0.981247,-0.08496,0.503173,0.044243,-0.59775, + -0.17302,-0.981247,-0.08496,0.503173,0.044243,-0.59775, + -0.094013,-0.992373,-0.079739,0.592781,0.031264,-0.5905, + -0.070895,-0.97954,-0.18835,0.586334,0.040774,-0.664625, + -0.173648,-0.984808,0,0.502661,0.041337,-0.5, + -0.089351,-0.996,0,0.599438,0.027269,-0.5, + -0.094013,-0.992373,-0.079739,0.592781,0.031264,-0.5905, + -0.173648,-0.984808,0,0.502661,0.041337,-0.5, + -0.094013,-0.992373,-0.079739,0.592781,0.031264,-0.5905, + -0.17302,-0.981247,-0.08496,0.503173,0.044243,-0.59775, + -0.089351,-0.996,0,0.599438,0.027269,-0.5, + 0.072467,-0.997371,0,0.679568,0.022087,-0.5, + 0.015839,-0.994833,-0.100277,0.667212,0.026513,-0.5825, + 0.015839,-0.994833,-0.100277,0.667212,0.026513,-0.5825, + -0.094013,-0.992373,-0.079739,0.592781,0.031264,-0.5905, + -0.089351,-0.996,0,0.599438,0.027269,-0.5, + -0.364711,-0.913648,-0.179534,0.369306,0.083596,-0.638667, + -0.355137,-0.92942,-0.100277,0.342964,0.083687,-0.5825, + -0.251068,-0.964679,-0.079739,0.414531,0.062694,-0.5905, + -0.364711,-0.913648,-0.179534,0.369306,0.083596,-0.638667, + -0.251068,-0.964679,-0.079739,0.414531,0.062694,-0.5905, + -0.280571,-0.938896,-0.199385,0.423841,0.069426,-0.664625, + -0.355137,-0.92942,-0.100277,0.342964,0.083687,-0.5825, + -0.409218,-0.912437,0,0.329838,0.083754,-0.5, + -0.25669,-0.966494,0,0.406908,0.061217,-0.5, + -0.25669,-0.966494,0,0.406908,0.061217,-0.5, + -0.251068,-0.964679,-0.079739,0.414531,0.062694,-0.5905, + -0.355137,-0.92942,-0.100277,0.342964,0.083687,-0.5825, + -0.173648,-0.984808,0,0.502661,0.041337,-0.5, + -0.17302,-0.981247,-0.08496,0.503173,0.044243,-0.59775, + -0.251068,-0.964679,-0.079739,0.414531,0.062694,-0.5905, + -0.173648,-0.984808,0,0.502661,0.041337,-0.5, + -0.251068,-0.964679,-0.079739,0.414531,0.062694,-0.5905, + -0.25669,-0.966494,0,0.406908,0.061217,-0.5, + -0.17302,-0.981247,-0.08496,0.503173,0.044243,-0.59775, + -0.168375,-0.954904,-0.244557,0.504703,0.05292,-0.677562, + -0.280571,-0.938896,-0.199385,0.423841,0.069426,-0.664625, + -0.280571,-0.938896,-0.199385,0.423841,0.069426,-0.664625, + -0.251068,-0.964679,-0.079739,0.414531,0.062694,-0.5905, + -0.17302,-0.981247,-0.08496,0.503173,0.044243,-0.59775, + -0.364711,-0.913648,0.179534,0.369306,0.083596,-0.361333, + -0.280571,-0.938896,0.199385,0.423841,0.069426,-0.335375, + -0.251068,-0.964679,0.079739,0.414531,0.062694,-0.4095, + -0.364711,-0.913648,0.179534,0.369306,0.083596,-0.361333, + -0.251068,-0.964679,0.079739,0.414531,0.062694,-0.4095, + -0.355137,-0.92942,0.100277,0.342964,0.083687,-0.4175, + -0.280571,-0.938896,0.199385,0.423841,0.069426,-0.335375, + -0.168376,-0.954904,0.244557,0.504703,0.05292,-0.322437, + -0.17302,-0.981247,0.08496,0.503173,0.044243,-0.40225, + -0.17302,-0.981247,0.08496,0.503173,0.044243,-0.40225, + -0.251068,-0.964679,0.079739,0.414531,0.062694,-0.4095, + -0.280571,-0.938896,0.199385,0.423841,0.069426,-0.335375, + -0.173648,-0.984808,0,0.502661,0.041337,-0.5, + -0.25669,-0.966494,0,0.406908,0.061217,-0.5, + -0.251068,-0.964679,0.079739,0.414531,0.062694,-0.4095, + -0.173648,-0.984808,0,0.502661,0.041337,-0.5, + -0.251068,-0.964679,0.079739,0.414531,0.062694,-0.4095, + -0.17302,-0.981247,0.08496,0.503173,0.044243,-0.40225, + -0.25669,-0.966494,0,0.406908,0.061217,-0.5, + -0.409218,-0.912437,0,0.329838,0.083754,-0.5, + -0.355137,-0.92942,0.100277,0.342964,0.083687,-0.4175, + -0.355137,-0.92942,0.100277,0.342964,0.083687,-0.4175, + -0.251068,-0.964679,0.079739,0.414531,0.062694,-0.4095, + -0.25669,-0.966494,0,0.406908,0.061217,-0.5, + 0.029695,-0.979483,0.199329,0.642426,0.035438,-0.361333, + 0.015839,-0.994833,0.100277,0.667212,0.026513,-0.4175, + -0.094013,-0.992373,0.079739,0.592781,0.031264,-0.4095, + 0.029695,-0.979483,0.199329,0.642426,0.035438,-0.361333, + -0.094013,-0.992373,0.079739,0.592781,0.031264,-0.4095, + -0.070895,-0.97954,0.188349,0.586334,0.040774,-0.335375, + 0.015839,-0.994833,0.100277,0.667212,0.026513,-0.4175, + 0.072467,-0.997371,0,0.679568,0.022087,-0.5, + -0.089351,-0.996,0,0.599438,0.027269,-0.5, + -0.089351,-0.996,0,0.599438,0.027269,-0.5, + -0.094013,-0.992373,0.079739,0.592781,0.031264,-0.4095, + 0.015839,-0.994833,0.100277,0.667212,0.026513,-0.4175, + -0.173648,-0.984808,0,0.502661,0.041337,-0.5, + -0.17302,-0.981247,0.08496,0.503173,0.044243,-0.40225, + -0.094013,-0.992373,0.079739,0.592781,0.031264,-0.4095, + -0.173648,-0.984808,0,0.502661,0.041337,-0.5, + -0.094013,-0.992373,0.079739,0.592781,0.031264,-0.4095, + -0.089351,-0.996,0,0.599438,0.027269,-0.5, + -0.17302,-0.981247,0.08496,0.503173,0.044243,-0.40225, + -0.168376,-0.954904,0.244557,0.504703,0.05292,-0.322437, + -0.070895,-0.97954,0.188349,0.586334,0.040774,-0.335375, + -0.070895,-0.97954,0.188349,0.586334,0.040774,-0.335375, + -0.094013,-0.992373,0.079739,0.592781,0.031264,-0.4095, + -0.17302,-0.981247,0.08496,0.503173,0.044243,-0.40225, +}; +static const struct gllist frame={GL_N3F_V3F,GL_TRIANGLES,1728,data,NULL}; +const struct gllist *s1_3=&frame; diff --git a/hacks/glx/s1_4.c b/hacks/glx/s1_4.c new file mode 100644 index 00000000..397412d6 --- /dev/null +++ b/hacks/glx/s1_4.c @@ -0,0 +1,1733 @@ +#include "gllist.h" +static const float data[]={ + -0.632405,-0.365743,-0.682858,1.262105,0.039911,-0.672877, + -0.695773,-0.304145,-0.650689,1.235562,0.083949,-0.664066, + -0.858311,-0.411605,-0.306404,1.208797,0.050229,-0.589491, + -0.858311,-0.411605,-0.306404,1.208797,0.050229,-0.589491, + -0.802735,-0.496752,-0.329932,1.231827,0.004686,-0.594296, + -0.632405,-0.365743,-0.682858,1.262105,0.039911,-0.672877, + -0.900624,-0.4346,0,1.199875,0.038989,-0.5, + -0.829744,-0.558144,0,1.221734,-0.007055,-0.5, + -0.802735,-0.496752,-0.329932,1.231827,0.004686,-0.594296, + -0.900624,-0.4346,0,1.199875,0.038989,-0.5, + -0.802735,-0.496752,-0.329932,1.231827,0.004686,-0.594296, + -0.858311,-0.411605,-0.306404,1.208797,0.050229,-0.589491, + -0.829744,-0.558144,0,1.221734,-0.007055,-0.5, + -0.372431,-0.92806,0,1.243033,-0.034453,-0.5, + -0.429143,-0.839931,-0.332192,1.253444,-0.022303,-0.594949, + -0.429143,-0.839931,-0.332192,1.253444,-0.022303,-0.594949, + -0.802735,-0.496752,-0.329932,1.231827,0.004686,-0.594296, + -0.829744,-0.558144,0,1.221734,-0.007055,-0.5, + -0.342337,-0.675989,-0.652567,1.284897,0.013483,-0.674188, + -0.632405,-0.365743,-0.682858,1.262105,0.039911,-0.672877, + -0.802735,-0.496752,-0.329932,1.231827,0.004686,-0.594296, + -0.342337,-0.675989,-0.652567,1.284897,0.013483,-0.674188, + -0.802735,-0.496752,-0.329932,1.231827,0.004686,-0.594296, + -0.429143,-0.839931,-0.332192,1.253444,-0.022303,-0.594949, + -0.858311,-0.411604,0.306404,1.208797,0.050229,-0.410509, + -0.695773,-0.304144,0.650689,1.235562,0.083949,-0.335934, + -0.632405,-0.365743,0.682858,1.262105,0.039911,-0.327123, + -0.632405,-0.365743,0.682858,1.262105,0.039911,-0.327123, + -0.802735,-0.496752,0.329932,1.231827,0.004686,-0.405704, + -0.858311,-0.411604,0.306404,1.208797,0.050229,-0.410509, + -0.342337,-0.675989,0.652567,1.284897,0.013483,-0.325812, + -0.429143,-0.839932,0.332191,1.253444,-0.022303,-0.405051, + -0.802735,-0.496752,0.329932,1.231827,0.004686,-0.405704, + -0.342337,-0.675989,0.652567,1.284897,0.013483,-0.325812, + -0.802735,-0.496752,0.329932,1.231827,0.004686,-0.405704, + -0.632405,-0.365743,0.682858,1.262105,0.039911,-0.327123, + -0.429143,-0.839932,0.332191,1.253444,-0.022303,-0.405051, + -0.372431,-0.92806,0,1.243033,-0.034453,-0.5, + -0.829744,-0.558144,0,1.221734,-0.007055,-0.5, + -0.829744,-0.558144,0,1.221734,-0.007055,-0.5, + -0.802735,-0.496752,0.329932,1.231827,0.004686,-0.405704, + -0.429143,-0.839932,0.332191,1.253444,-0.022303,-0.405051, + -0.900624,-0.4346,0,1.199875,0.038989,-0.5, + -0.858311,-0.411604,0.306404,1.208797,0.050229,-0.410509, + -0.802735,-0.496752,0.329932,1.231827,0.004686,-0.405704, + -0.900624,-0.4346,0,1.199875,0.038989,-0.5, + -0.802735,-0.496752,0.329932,1.231827,0.004686,-0.405704, + -0.829744,-0.558144,0,1.221734,-0.007055,-0.5, + 0.581551,-0.793452,0.179534,1.331736,0.017726,-0.361333, + 0.6,-0.793691,0.100277,1.3177,-0.004566,-0.4175, + 0.266434,-0.94535,0.187955,1.279887,-0.026194,-0.4125, + 0.581551,-0.793452,0.179534,1.331736,0.017726,-0.361333, + 0.266434,-0.94535,0.187955,1.279887,-0.026194,-0.4125, + 0.307416,-0.846879,0.433925,1.309178,0.008154,-0.339125, + 0.556938,-0.830554,0,1.310688,-0.015661,-0.5, + 0.184945,-0.982749,0,1.270418,-0.038526,-0.5, + 0.266434,-0.94535,0.187955,1.279887,-0.026194,-0.4125, + 0.556938,-0.830554,0,1.310688,-0.015661,-0.5, + 0.266434,-0.94535,0.187955,1.279887,-0.026194,-0.4125, + 0.6,-0.793691,0.100277,1.3177,-0.004566,-0.4175, + -0.372431,-0.92806,0,1.243033,-0.034453,-0.5, + -0.429143,-0.839932,0.332191,1.253444,-0.022303,-0.405051, + 0.266434,-0.94535,0.187955,1.279887,-0.026194,-0.4125, + -0.372431,-0.92806,0,1.243033,-0.034453,-0.5, + 0.266434,-0.94535,0.187955,1.279887,-0.026194,-0.4125, + 0.184945,-0.982749,0,1.270418,-0.038526,-0.5, + -0.429143,-0.839932,0.332191,1.253444,-0.022303,-0.405051, + -0.342337,-0.675989,0.652567,1.284897,0.013483,-0.325812, + 0.307416,-0.846879,0.433925,1.309178,0.008154,-0.339125, + 0.307416,-0.846879,0.433925,1.309178,0.008154,-0.339125, + 0.266434,-0.94535,0.187955,1.279887,-0.026194,-0.4125, + -0.429143,-0.839932,0.332191,1.253444,-0.022303,-0.405051, + 0.581551,-0.793452,-0.179534,1.331736,0.017726,-0.638667, + 0.307416,-0.846879,-0.433925,1.309178,0.008154,-0.660875, + 0.266434,-0.94535,-0.187955,1.279887,-0.026194,-0.5875, + 0.581551,-0.793452,-0.179534,1.331736,0.017726,-0.638667, + 0.266434,-0.94535,-0.187955,1.279887,-0.026194,-0.5875, + 0.6,-0.793691,-0.100277,1.3177,-0.004566,-0.5825, + 0.307416,-0.846879,-0.433925,1.309178,0.008154,-0.660875, + -0.342337,-0.675989,-0.652567,1.284897,0.013483,-0.674188, + -0.429143,-0.839931,-0.332192,1.253444,-0.022303,-0.594949, + -0.429143,-0.839931,-0.332192,1.253444,-0.022303,-0.594949, + 0.266434,-0.94535,-0.187955,1.279887,-0.026194,-0.5875, + 0.307416,-0.846879,-0.433925,1.309178,0.008154,-0.660875, + -0.372431,-0.92806,0,1.243033,-0.034453,-0.5, + 0.184945,-0.982749,0,1.270418,-0.038526,-0.5, + 0.266434,-0.94535,-0.187955,1.279887,-0.026194,-0.5875, + -0.372431,-0.92806,0,1.243033,-0.034453,-0.5, + 0.266434,-0.94535,-0.187955,1.279887,-0.026194,-0.5875, + -0.429143,-0.839931,-0.332192,1.253444,-0.022303,-0.594949, + 0.556938,-0.830554,0,1.310688,-0.015661,-0.5, + 0.6,-0.793691,-0.100277,1.3177,-0.004566,-0.5825, + 0.266434,-0.94535,-0.187955,1.279887,-0.026194,-0.5875, + 0.556938,-0.830554,0,1.310688,-0.015661,-0.5, + 0.266434,-0.94535,-0.187955,1.279887,-0.026194,-0.5875, + 0.184945,-0.982749,0,1.270418,-0.038526,-0.5, + -0.695773,-0.304144,0.650689,1.235562,0.083949,-0.335934, + -0.420703,-0.10775,0.900777,1.28017,0.14015,-0.291188, + -0.363086,-0.142915,0.92073,1.312568,0.09862,-0.279975, + -0.695773,-0.304144,0.650689,1.235562,0.083949,-0.335934, + -0.363086,-0.142915,0.92073,1.312568,0.09862,-0.279975, + -0.632405,-0.365743,0.682858,1.262105,0.039911,-0.327123, + -0.420703,-0.10775,0.900777,1.28017,0.14015,-0.291188, + -0.152737,0.118235,0.981169,1.3337,0.207591,-0.276273, + -0.10731,0.091019,0.990051,1.373124,0.16907,-0.264259, + -0.10731,0.091019,0.990051,1.373124,0.16907,-0.264259, + -0.363086,-0.142915,0.92073,1.312568,0.09862,-0.279975, + -0.420703,-0.10775,0.900777,1.28017,0.14015,-0.291188, + 0.221822,-0.232839,0.94688,1.400739,0.142695,-0.26194, + -0.050406,-0.482634,0.874371,1.337615,0.072243,-0.277994, + -0.363086,-0.142915,0.92073,1.312568,0.09862,-0.279975, + 0.221822,-0.232839,0.94688,1.400739,0.142695,-0.26194, + -0.363086,-0.142915,0.92073,1.312568,0.09862,-0.279975, + -0.10731,0.091019,0.990051,1.373124,0.16907,-0.264259, + -0.050406,-0.482634,0.874371,1.337615,0.072243,-0.277994, + -0.342337,-0.675989,0.652567,1.284897,0.013483,-0.325812, + -0.632405,-0.365743,0.682858,1.262105,0.039911,-0.327123, + -0.632405,-0.365743,0.682858,1.262105,0.039911,-0.327123, + -0.363086,-0.142915,0.92073,1.312568,0.09862,-0.279975, + -0.050406,-0.482634,0.874371,1.337615,0.072243,-0.277994, + 0.311074,0.63183,0.709947,1.431839,0.331232,-0.335934, + 0.365915,0.616651,0.697028,1.484144,0.298229,-0.327123, + 0.113526,0.358822,0.926476,1.433681,0.239521,-0.279975, + 0.311074,0.63183,0.709947,1.431839,0.331232,-0.335934, + 0.113526,0.358822,0.926476,1.433681,0.239521,-0.279975, + 0.074097,0.34389,0.936082,1.38723,0.275032,-0.291188, + 0.365915,0.616651,0.697028,1.484144,0.298229,-0.327123, + 0.704743,0.348932,0.617724,1.515677,0.27272,-0.325812, + 0.422175,0.108161,0.900039,1.463411,0.213552,-0.277994, + 0.422175,0.108161,0.900039,1.463411,0.213552,-0.277994, + 0.113526,0.358822,0.926476,1.433681,0.239521,-0.279975, + 0.365915,0.616651,0.697028,1.484144,0.298229,-0.327123, + 0.422175,0.108161,0.900039,1.463411,0.213552,-0.277994, + 0.221822,-0.232839,0.94688,1.400739,0.142695,-0.26194, + -0.10731,0.091019,0.990051,1.373124,0.16907,-0.264259, + -0.10731,0.091019,0.990051,1.373124,0.16907,-0.264259, + 0.113526,0.358822,0.926476,1.433681,0.239521,-0.279975, + 0.422175,0.108161,0.900039,1.463411,0.213552,-0.277994, + -0.152737,0.118235,0.981169,1.3337,0.207591,-0.276273, + 0.074097,0.34389,0.936082,1.38723,0.275032,-0.291188, + 0.113526,0.358822,0.926476,1.433681,0.239521,-0.279975, + -0.152737,0.118235,0.981169,1.3337,0.207591,-0.276273, + 0.113526,0.358822,0.926476,1.433681,0.239521,-0.279975, + -0.10731,0.091019,0.990051,1.373124,0.16907,-0.264259, + 0.846384,-0.493864,0.199328,1.517309,0.223825,-0.361333, + 0.786785,-0.580419,0.209959,1.483059,0.179084,-0.335375, + 0.736468,-0.384081,0.556864,1.476277,0.191919,-0.294, + 0.846384,-0.493864,0.199328,1.517309,0.223825,-0.361333, + 0.736468,-0.384081,0.556864,1.476277,0.191919,-0.294, + 0.85656,-0.215911,0.468709,1.524471,0.247261,-0.339125, + 0.786785,-0.580419,0.209959,1.483059,0.179084,-0.335375, + 0.725947,-0.653645,0.21389,1.4295,0.116294,-0.322437, + 0.64097,-0.57721,0.50595,1.418631,0.126081,-0.2785, + 0.64097,-0.57721,0.50595,1.418631,0.126081,-0.2785, + 0.736468,-0.384081,0.556864,1.476277,0.191919,-0.294, + 0.786785,-0.580419,0.209959,1.483059,0.179084,-0.335375, + 0.221822,-0.232839,0.94688,1.400739,0.142695,-0.26194, + 0.422175,0.108161,0.900039,1.463411,0.213552,-0.277994, + 0.736468,-0.384081,0.556864,1.476277,0.191919,-0.294, + 0.221822,-0.232839,0.94688,1.400739,0.142695,-0.26194, + 0.736468,-0.384081,0.556864,1.476277,0.191919,-0.294, + 0.64097,-0.57721,0.50595,1.418631,0.126081,-0.2785, + 0.422175,0.108161,0.900039,1.463411,0.213552,-0.277994, + 0.704743,0.348932,0.617724,1.515677,0.27272,-0.325812, + 0.85656,-0.215911,0.468709,1.524471,0.247261,-0.339125, + 0.85656,-0.215911,0.468709,1.524471,0.247261,-0.339125, + 0.736468,-0.384081,0.556864,1.476277,0.191919,-0.294, + 0.422175,0.108161,0.900039,1.463411,0.213552,-0.277994, + 0.649588,-0.728866,0.216309,1.372652,0.056465,-0.335375, + 0.581551,-0.793452,0.179534,1.331736,0.017726,-0.361333, + 0.307416,-0.846879,0.433925,1.309178,0.008154,-0.339125, + 0.307416,-0.846879,0.433925,1.309178,0.008154,-0.339125, + 0.432476,-0.665439,0.608404,1.359179,0.061869,-0.294, + 0.649588,-0.728866,0.216309,1.372652,0.056465,-0.335375, + 0.307416,-0.846879,0.433925,1.309178,0.008154,-0.339125, + -0.342337,-0.675989,0.652567,1.284897,0.013483,-0.325812, + -0.050406,-0.482634,0.874371,1.337615,0.072243,-0.277994, + -0.050406,-0.482634,0.874371,1.337615,0.072243,-0.277994, + 0.432476,-0.665439,0.608404,1.359179,0.061869,-0.294, + 0.307416,-0.846879,0.433925,1.309178,0.008154,-0.339125, + 0.221822,-0.232839,0.94688,1.400739,0.142695,-0.26194, + 0.64097,-0.57721,0.50595,1.418631,0.126081,-0.2785, + 0.432476,-0.665439,0.608404,1.359179,0.061869,-0.294, + 0.221822,-0.232839,0.94688,1.400739,0.142695,-0.26194, + 0.432476,-0.665439,0.608404,1.359179,0.061869,-0.294, + -0.050406,-0.482634,0.874371,1.337615,0.072243,-0.277994, + 0.64097,-0.57721,0.50595,1.418631,0.126081,-0.2785, + 0.725947,-0.653645,0.21389,1.4295,0.116294,-0.322437, + 0.649588,-0.728866,0.216309,1.372652,0.056465,-0.335375, + 0.649588,-0.728866,0.216309,1.372652,0.056465,-0.335375, + 0.432476,-0.665439,0.608404,1.359179,0.061869,-0.294, + 0.64097,-0.57721,0.50595,1.418631,0.126081,-0.2785, + 0.365915,0.616651,0.697028,1.484144,0.298229,-0.327123, + 0.311074,0.63183,0.709947,1.431839,0.331232,-0.335934, + 0.460195,0.823869,0.330849,1.458604,0.364953,-0.410509, + 0.460195,0.823869,0.330849,1.458604,0.364953,-0.410509, + 0.507038,0.792213,0.339576,1.514422,0.333454,-0.405704, + 0.365915,0.616651,0.697028,1.484144,0.298229,-0.327123, + 0.489941,0.871755,0,1.467526,0.376193,-0.5, + 0.561935,0.827181,0,1.524515,0.345196,-0.5, + 0.507038,0.792213,0.339576,1.514422,0.333454,-0.405704, + 0.489941,0.871755,0,1.467526,0.376193,-0.5, + 0.507038,0.792213,0.339576,1.514422,0.333454,-0.405704, + 0.460195,0.823869,0.330849,1.458604,0.364953,-0.410509, + 0.561935,0.827181,0,1.524515,0.345196,-0.5, + 0.887347,0.461103,0,1.558444,0.319842,-0.5, + 0.765648,0.567983,0.301958,1.547582,0.308099,-0.405051, + 0.765648,0.567983,0.301958,1.547582,0.308099,-0.405051, + 0.507038,0.792213,0.339576,1.514422,0.333454,-0.405704, + 0.561935,0.827181,0,1.524515,0.345196,-0.5, + 0.704743,0.348932,0.617724,1.515677,0.27272,-0.325812, + 0.365915,0.616651,0.697028,1.484144,0.298229,-0.327123, + 0.507038,0.792213,0.339576,1.514422,0.333454,-0.405704, + 0.704743,0.348932,0.617724,1.515677,0.27272,-0.325812, + 0.507038,0.792213,0.339576,1.514422,0.333454,-0.405704, + 0.765648,0.567983,0.301958,1.547582,0.308099,-0.405051, + 0.460195,0.823869,-0.330849,1.458604,0.364953,-0.589491, + 0.311074,0.63183,-0.709947,1.431839,0.331232,-0.664066, + 0.365915,0.616651,-0.697028,1.484144,0.298229,-0.672877, + 0.365915,0.616651,-0.697028,1.484144,0.298229,-0.672877, + 0.507038,0.792213,-0.339576,1.514422,0.333454,-0.594296, + 0.460195,0.823869,-0.330849,1.458604,0.364953,-0.589491, + 0.704744,0.348932,-0.617724,1.515677,0.27272,-0.674188, + 0.765648,0.567983,-0.301958,1.547582,0.308099,-0.594949, + 0.507038,0.792213,-0.339576,1.514422,0.333454,-0.594296, + 0.704744,0.348932,-0.617724,1.515677,0.27272,-0.674188, + 0.507038,0.792213,-0.339576,1.514422,0.333454,-0.594296, + 0.365915,0.616651,-0.697028,1.484144,0.298229,-0.672877, + 0.765648,0.567983,-0.301958,1.547582,0.308099,-0.594949, + 0.887347,0.461103,0,1.558444,0.319842,-0.5, + 0.561935,0.827181,0,1.524515,0.345196,-0.5, + 0.561935,0.827181,0,1.524515,0.345196,-0.5, + 0.507038,0.792213,-0.339576,1.514422,0.333454,-0.594296, + 0.765648,0.567983,-0.301958,1.547582,0.308099,-0.594949, + 0.489941,0.871755,0,1.467526,0.376193,-0.5, + 0.460195,0.823869,-0.330849,1.458604,0.364953,-0.589491, + 0.507038,0.792213,-0.339576,1.514422,0.333454,-0.594296, + 0.489941,0.871755,0,1.467526,0.376193,-0.5, + 0.507038,0.792213,-0.339576,1.514422,0.333454,-0.594296, + 0.561935,0.827181,0,1.524515,0.345196,-0.5, + 0.846384,-0.493864,-0.199329,1.517309,0.223825,-0.638667, + 0.85206,-0.513749,-0.100278,1.538011,0.240115,-0.5825, + 0.967592,-0.122072,-0.221053,1.555568,0.279982,-0.5875, + 0.846384,-0.493864,-0.199329,1.517309,0.223825,-0.638667, + 0.967592,-0.122072,-0.221053,1.555568,0.279982,-0.5875, + 0.85656,-0.215911,-0.468708,1.524471,0.247261,-0.660875, + 0.88422,-0.467071,0,1.548313,0.248248,-0.5, + 0.997731,-0.067332,0,1.566843,0.290687,-0.5, + 0.967592,-0.122072,-0.221053,1.555568,0.279982,-0.5875, + 0.88422,-0.467071,0,1.548313,0.248248,-0.5, + 0.967592,-0.122072,-0.221053,1.555568,0.279982,-0.5875, + 0.85206,-0.513749,-0.100278,1.538011,0.240115,-0.5825, + 0.887347,0.461103,0,1.558444,0.319842,-0.5, + 0.765648,0.567983,-0.301958,1.547582,0.308099,-0.594949, + 0.967592,-0.122072,-0.221053,1.555568,0.279982,-0.5875, + 0.887347,0.461103,0,1.558444,0.319842,-0.5, + 0.967592,-0.122072,-0.221053,1.555568,0.279982,-0.5875, + 0.997731,-0.067332,0,1.566843,0.290687,-0.5, + 0.704744,0.348932,-0.617724,1.515677,0.27272,-0.674188, + 0.85656,-0.215911,-0.468708,1.524471,0.247261,-0.660875, + 0.967592,-0.122072,-0.221053,1.555568,0.279982,-0.5875, + 0.704744,0.348932,-0.617724,1.515677,0.27272,-0.674188, + 0.967592,-0.122072,-0.221053,1.555568,0.279982,-0.5875, + 0.765648,0.567983,-0.301958,1.547582,0.308099,-0.594949, + 0.846384,-0.493864,0.199328,1.517309,0.223825,-0.361333, + 0.85656,-0.215911,0.468709,1.524471,0.247261,-0.339125, + 0.967592,-0.122072,0.221053,1.555568,0.279982,-0.4125, + 0.846384,-0.493864,0.199328,1.517309,0.223825,-0.361333, + 0.967592,-0.122072,0.221053,1.555568,0.279982,-0.4125, + 0.85206,-0.513749,0.100278,1.538011,0.240115,-0.4175, + 0.704743,0.348932,0.617724,1.515677,0.27272,-0.325812, + 0.765648,0.567983,0.301958,1.547582,0.308099,-0.405051, + 0.967592,-0.122072,0.221053,1.555568,0.279982,-0.4125, + 0.704743,0.348932,0.617724,1.515677,0.27272,-0.325812, + 0.967592,-0.122072,0.221053,1.555568,0.279982,-0.4125, + 0.85656,-0.215911,0.468709,1.524471,0.247261,-0.339125, + 0.887347,0.461103,0,1.558444,0.319842,-0.5, + 0.997731,-0.067332,0,1.566843,0.290687,-0.5, + 0.967592,-0.122072,0.221053,1.555568,0.279982,-0.4125, + 0.887347,0.461103,0,1.558444,0.319842,-0.5, + 0.967592,-0.122072,0.221053,1.555568,0.279982,-0.4125, + 0.765648,0.567983,0.301958,1.547582,0.308099,-0.405051, + 0.88422,-0.467071,0,1.548313,0.248248,-0.5, + 0.85206,-0.513749,0.100278,1.538011,0.240115,-0.4175, + 0.967592,-0.122072,0.221053,1.555568,0.279982,-0.4125, + 0.88422,-0.467071,0,1.548313,0.248248,-0.5, + 0.967592,-0.122072,0.221053,1.555568,0.279982,-0.4125, + 0.997731,-0.067332,0,1.566843,0.290687,-0.5, + 0.311074,0.63183,-0.709947,1.431839,0.331232,-0.664066, + 0.074097,0.34389,-0.936082,1.38723,0.275032,-0.708812, + 0.113526,0.358822,-0.926476,1.433681,0.239521,-0.720025, + 0.311074,0.63183,-0.709947,1.431839,0.331232,-0.664066, + 0.113526,0.358822,-0.926476,1.433681,0.239521,-0.720025, + 0.365915,0.616651,-0.697028,1.484144,0.298229,-0.672877, + -0.152737,0.118235,-0.981169,1.3337,0.207591,-0.723727, + -0.10731,0.091019,-0.990051,1.373124,0.16907,-0.735741, + 0.113526,0.358822,-0.926476,1.433681,0.239521,-0.720025, + -0.152737,0.118235,-0.981169,1.3337,0.207591,-0.723727, + 0.113526,0.358822,-0.926476,1.433681,0.239521,-0.720025, + 0.074097,0.34389,-0.936082,1.38723,0.275032,-0.708812, + -0.10731,0.091019,-0.990051,1.373124,0.16907,-0.735741, + 0.221822,-0.232839,-0.94688,1.400739,0.142695,-0.73806, + 0.422175,0.108161,-0.900039,1.463411,0.213552,-0.722006, + 0.422175,0.108161,-0.900039,1.463411,0.213552,-0.722006, + 0.113526,0.358822,-0.926476,1.433681,0.239521,-0.720025, + -0.10731,0.091019,-0.990051,1.373124,0.16907,-0.735741, + 0.422175,0.108161,-0.900039,1.463411,0.213552,-0.722006, + 0.704744,0.348932,-0.617724,1.515677,0.27272,-0.674188, + 0.365915,0.616651,-0.697028,1.484144,0.298229,-0.672877, + 0.365915,0.616651,-0.697028,1.484144,0.298229,-0.672877, + 0.113526,0.358822,-0.926476,1.433681,0.239521,-0.720025, + 0.422175,0.108161,-0.900039,1.463411,0.213552,-0.722006, + -0.695773,-0.304145,-0.650689,1.235562,0.083949,-0.664066, + -0.632405,-0.365743,-0.682858,1.262105,0.039911,-0.672877, + -0.363086,-0.142915,-0.92073,1.312568,0.09862,-0.720025, + -0.695773,-0.304145,-0.650689,1.235562,0.083949,-0.664066, + -0.363086,-0.142915,-0.92073,1.312568,0.09862,-0.720025, + -0.420703,-0.10775,-0.900777,1.28017,0.14015,-0.708812, + -0.632405,-0.365743,-0.682858,1.262105,0.039911,-0.672877, + -0.342337,-0.675989,-0.652567,1.284897,0.013483,-0.674188, + -0.050406,-0.482634,-0.87437,1.337615,0.072243,-0.722006, + -0.050406,-0.482634,-0.87437,1.337615,0.072243,-0.722006, + -0.363086,-0.142915,-0.92073,1.312568,0.09862,-0.720025, + -0.632405,-0.365743,-0.682858,1.262105,0.039911,-0.672877, + 0.221822,-0.232839,-0.94688,1.400739,0.142695,-0.73806, + -0.10731,0.091019,-0.990051,1.373124,0.16907,-0.735741, + -0.363086,-0.142915,-0.92073,1.312568,0.09862,-0.720025, + 0.221822,-0.232839,-0.94688,1.400739,0.142695,-0.73806, + -0.363086,-0.142915,-0.92073,1.312568,0.09862,-0.720025, + -0.050406,-0.482634,-0.87437,1.337615,0.072243,-0.722006, + -0.10731,0.091019,-0.990051,1.373124,0.16907,-0.735741, + -0.152737,0.118235,-0.981169,1.3337,0.207591,-0.723727, + -0.420703,-0.10775,-0.900777,1.28017,0.14015,-0.708812, + -0.420703,-0.10775,-0.900777,1.28017,0.14015,-0.708812, + -0.363086,-0.142915,-0.92073,1.312568,0.09862,-0.720025, + -0.10731,0.091019,-0.990051,1.373124,0.16907,-0.735741, + 0.307416,-0.846879,-0.433925,1.309178,0.008154,-0.660875, + 0.581551,-0.793452,-0.179534,1.331736,0.017726,-0.638667, + 0.649588,-0.728866,-0.216309,1.372652,0.056465,-0.664625, + 0.649588,-0.728866,-0.216309,1.372652,0.056465,-0.664625, + 0.432476,-0.665439,-0.608404,1.359179,0.061869,-0.706, + 0.307416,-0.846879,-0.433925,1.309178,0.008154,-0.660875, + 0.649588,-0.728866,-0.216309,1.372652,0.056465,-0.664625, + 0.725947,-0.653645,-0.21389,1.4295,0.116294,-0.677562, + 0.64097,-0.577211,-0.50595,1.418631,0.126081,-0.7215, + 0.64097,-0.577211,-0.50595,1.418631,0.126081,-0.7215, + 0.432476,-0.665439,-0.608404,1.359179,0.061869,-0.706, + 0.649588,-0.728866,-0.216309,1.372652,0.056465,-0.664625, + 0.221822,-0.232839,-0.94688,1.400739,0.142695,-0.73806, + -0.050406,-0.482634,-0.87437,1.337615,0.072243,-0.722006, + 0.432476,-0.665439,-0.608404,1.359179,0.061869,-0.706, + 0.221822,-0.232839,-0.94688,1.400739,0.142695,-0.73806, + 0.432476,-0.665439,-0.608404,1.359179,0.061869,-0.706, + 0.64097,-0.577211,-0.50595,1.418631,0.126081,-0.7215, + -0.050406,-0.482634,-0.87437,1.337615,0.072243,-0.722006, + -0.342337,-0.675989,-0.652567,1.284897,0.013483,-0.674188, + 0.307416,-0.846879,-0.433925,1.309178,0.008154,-0.660875, + 0.307416,-0.846879,-0.433925,1.309178,0.008154,-0.660875, + 0.432476,-0.665439,-0.608404,1.359179,0.061869,-0.706, + -0.050406,-0.482634,-0.87437,1.337615,0.072243,-0.722006, + 0.846384,-0.493864,-0.199329,1.517309,0.223825,-0.638667, + 0.85656,-0.215911,-0.468708,1.524471,0.247261,-0.660875, + 0.736467,-0.384081,-0.556864,1.476277,0.191919,-0.706, + 0.846384,-0.493864,-0.199329,1.517309,0.223825,-0.638667, + 0.736467,-0.384081,-0.556864,1.476277,0.191919,-0.706, + 0.786785,-0.580419,-0.209959,1.483059,0.179084,-0.664625, + 0.85656,-0.215911,-0.468708,1.524471,0.247261,-0.660875, + 0.704744,0.348932,-0.617724,1.515677,0.27272,-0.674188, + 0.422175,0.108161,-0.900039,1.463411,0.213552,-0.722006, + 0.422175,0.108161,-0.900039,1.463411,0.213552,-0.722006, + 0.736467,-0.384081,-0.556864,1.476277,0.191919,-0.706, + 0.85656,-0.215911,-0.468708,1.524471,0.247261,-0.660875, + 0.221822,-0.232839,-0.94688,1.400739,0.142695,-0.73806, + 0.64097,-0.577211,-0.50595,1.418631,0.126081,-0.7215, + 0.736467,-0.384081,-0.556864,1.476277,0.191919,-0.706, + 0.221822,-0.232839,-0.94688,1.400739,0.142695,-0.73806, + 0.736467,-0.384081,-0.556864,1.476277,0.191919,-0.706, + 0.422175,0.108161,-0.900039,1.463411,0.213552,-0.722006, + 0.64097,-0.577211,-0.50595,1.418631,0.126081,-0.7215, + 0.725947,-0.653645,-0.21389,1.4295,0.116294,-0.677562, + 0.786785,-0.580419,-0.209959,1.483059,0.179084,-0.664625, + 0.786785,-0.580419,-0.209959,1.483059,0.179084,-0.664625, + 0.736467,-0.384081,-0.556864,1.476277,0.191919,-0.706, + 0.64097,-0.577211,-0.50595,1.418631,0.126081,-0.7215, + 0.581551,-0.793452,0.179534,1.331736,0.017726,-0.361333, + 0.649588,-0.728866,0.216309,1.372652,0.056465,-0.335375, + 0.685049,-0.72412,0.079739,1.373428,0.045002,-0.4095, + 0.581551,-0.793452,0.179534,1.331736,0.017726,-0.361333, + 0.685049,-0.72412,0.079739,1.373428,0.045002,-0.4095, + 0.6,-0.793691,0.100277,1.3177,-0.004566,-0.4175, + 0.649588,-0.728866,0.216309,1.372652,0.056465,-0.335375, + 0.725947,-0.653645,0.21389,1.4295,0.116294,-0.322437, + 0.740458,-0.666711,0.08496,1.436048,0.110398,-0.40225, + 0.740458,-0.666711,0.08496,1.436048,0.110398,-0.40225, + 0.685049,-0.72412,0.079739,1.373428,0.045002,-0.4095, + 0.649588,-0.728866,0.216309,1.372652,0.056465,-0.335375, + 0.743145,-0.669131,0,1.438241,0.108423,-0.5, + 0.683609,-0.729849,0,1.370641,0.037756,-0.5, + 0.685049,-0.72412,0.079739,1.373428,0.045002,-0.4095, + 0.743145,-0.669131,0,1.438241,0.108423,-0.5, + 0.685049,-0.72412,0.079739,1.373428,0.045002,-0.4095, + 0.740458,-0.666711,0.08496,1.436048,0.110398,-0.40225, + 0.683609,-0.729849,0,1.370641,0.037756,-0.5, + 0.556938,-0.830554,0,1.310688,-0.015661,-0.5, + 0.6,-0.793691,0.100277,1.3177,-0.004566,-0.4175, + 0.6,-0.793691,0.100277,1.3177,-0.004566,-0.4175, + 0.685049,-0.72412,0.079739,1.373428,0.045002,-0.4095, + 0.683609,-0.729849,0,1.370641,0.037756,-0.5, + 0.846384,-0.493864,0.199328,1.517309,0.223825,-0.361333, + 0.85206,-0.513749,0.100278,1.538011,0.240115,-0.4175, + 0.791761,-0.605604,0.079739,1.49454,0.179511,-0.4095, + 0.846384,-0.493864,0.199328,1.517309,0.223825,-0.361333, + 0.791761,-0.605604,0.079739,1.49454,0.179511,-0.4095, + 0.786785,-0.580419,0.209959,1.483059,0.179084,-0.335375, + 0.85206,-0.513749,0.100278,1.538011,0.240115,-0.4175, + 0.88422,-0.467071,0,1.548313,0.248248,-0.5, + 0.797307,-0.603573,0,1.501456,0.18304,-0.5, + 0.797307,-0.603573,0,1.501456,0.18304,-0.5, + 0.791761,-0.605604,0.079739,1.49454,0.179511,-0.4095, + 0.85206,-0.513749,0.100278,1.538011,0.240115,-0.4175, + 0.743145,-0.669131,0,1.438241,0.108423,-0.5, + 0.740458,-0.666711,0.08496,1.436048,0.110398,-0.40225, + 0.791761,-0.605604,0.079739,1.49454,0.179511,-0.4095, + 0.743145,-0.669131,0,1.438241,0.108423,-0.5, + 0.791761,-0.605604,0.079739,1.49454,0.179511,-0.4095, + 0.797307,-0.603573,0,1.501456,0.18304,-0.5, + 0.740458,-0.666711,0.08496,1.436048,0.110398,-0.40225, + 0.725947,-0.653645,0.21389,1.4295,0.116294,-0.322437, + 0.786785,-0.580419,0.209959,1.483059,0.179084,-0.335375, + 0.786785,-0.580419,0.209959,1.483059,0.179084,-0.335375, + 0.791761,-0.605604,0.079739,1.49454,0.179511,-0.4095, + 0.740458,-0.666711,0.08496,1.436048,0.110398,-0.40225, + 0.846384,-0.493864,-0.199329,1.517309,0.223825,-0.638667, + 0.786785,-0.580419,-0.209959,1.483059,0.179084,-0.664625, + 0.791761,-0.605604,-0.079739,1.49454,0.179511,-0.5905, + 0.846384,-0.493864,-0.199329,1.517309,0.223825,-0.638667, + 0.791761,-0.605604,-0.079739,1.49454,0.179511,-0.5905, + 0.85206,-0.513749,-0.100278,1.538011,0.240115,-0.5825, + 0.786785,-0.580419,-0.209959,1.483059,0.179084,-0.664625, + 0.725947,-0.653645,-0.21389,1.4295,0.116294,-0.677562, + 0.740458,-0.666711,-0.08496,1.436048,0.110398,-0.59775, + 0.740458,-0.666711,-0.08496,1.436048,0.110398,-0.59775, + 0.791761,-0.605604,-0.079739,1.49454,0.179511,-0.5905, + 0.786785,-0.580419,-0.209959,1.483059,0.179084,-0.664625, + 0.743145,-0.669131,0,1.438241,0.108423,-0.5, + 0.797307,-0.603573,0,1.501456,0.18304,-0.5, + 0.791761,-0.605604,-0.079739,1.49454,0.179511,-0.5905, + 0.743145,-0.669131,0,1.438241,0.108423,-0.5, + 0.791761,-0.605604,-0.079739,1.49454,0.179511,-0.5905, + 0.740458,-0.666711,-0.08496,1.436048,0.110398,-0.59775, + 0.797307,-0.603573,0,1.501456,0.18304,-0.5, + 0.88422,-0.467071,0,1.548313,0.248248,-0.5, + 0.85206,-0.513749,-0.100278,1.538011,0.240115,-0.5825, + 0.85206,-0.513749,-0.100278,1.538011,0.240115,-0.5825, + 0.791761,-0.605604,-0.079739,1.49454,0.179511,-0.5905, + 0.797307,-0.603573,0,1.501456,0.18304,-0.5, + 0.581551,-0.793452,-0.179534,1.331736,0.017726,-0.638667, + 0.6,-0.793691,-0.100277,1.3177,-0.004566,-0.5825, + 0.685049,-0.72412,-0.079739,1.373428,0.045002,-0.5905, + 0.581551,-0.793452,-0.179534,1.331736,0.017726,-0.638667, + 0.685049,-0.72412,-0.079739,1.373428,0.045002,-0.5905, + 0.649588,-0.728866,-0.216309,1.372652,0.056465,-0.664625, + 0.6,-0.793691,-0.100277,1.3177,-0.004566,-0.5825, + 0.556938,-0.830554,0,1.310688,-0.015661,-0.5, + 0.683609,-0.729849,0,1.370641,0.037756,-0.5, + 0.683609,-0.729849,0,1.370641,0.037756,-0.5, + 0.685049,-0.72412,-0.079739,1.373428,0.045002,-0.5905, + 0.6,-0.793691,-0.100277,1.3177,-0.004566,-0.5825, + 0.743145,-0.669131,0,1.438241,0.108423,-0.5, + 0.740458,-0.666711,-0.08496,1.436048,0.110398,-0.59775, + 0.685049,-0.72412,-0.079739,1.373428,0.045002,-0.5905, + 0.743145,-0.669131,0,1.438241,0.108423,-0.5, + 0.685049,-0.72412,-0.079739,1.373428,0.045002,-0.5905, + 0.683609,-0.729849,0,1.370641,0.037756,-0.5, + 0.740458,-0.666711,-0.08496,1.436048,0.110398,-0.59775, + 0.725947,-0.653645,-0.21389,1.4295,0.116294,-0.677562, + 0.649588,-0.728866,-0.216309,1.372652,0.056465,-0.664625, + 0.649588,-0.728866,-0.216309,1.372652,0.056465,-0.664625, + 0.685049,-0.72412,-0.079739,1.373428,0.045002,-0.5905, + 0.740458,-0.666711,-0.08496,1.436048,0.110398,-0.59775, + -0.695773,-0.304145,-0.650689,1.235562,0.083949,-0.664066, + -0.687216,-0.351805,-0.635584,1.200029,0.142107,-0.654883, + -0.84747,-0.443196,-0.292185,1.178115,0.10978,-0.584482, + -0.695773,-0.304145,-0.650689,1.235562,0.083949,-0.664066, + -0.84747,-0.443196,-0.292185,1.178115,0.10978,-0.584482, + -0.858311,-0.411605,-0.306404,1.208797,0.050229,-0.589491, + -0.687216,-0.351805,-0.635584,1.200029,0.142107,-0.654883, + -0.659424,-0.432639,-0.614804,1.158118,0.203222,-0.646637, + -0.813982,-0.512235,-0.273951,1.142211,0.172121,-0.579984, + -0.813982,-0.512235,-0.273951,1.142211,0.172121,-0.579984, + -0.84747,-0.443196,-0.292185,1.178115,0.10978,-0.584482, + -0.687216,-0.351805,-0.635584,1.200029,0.142107,-0.654883, + -0.860968,-0.508659,0,1.136909,0.161755,-0.5, + -0.891261,-0.453491,0,1.170811,0.099004,-0.5, + -0.84747,-0.443196,-0.292185,1.178115,0.10978,-0.584482, + -0.860968,-0.508659,0,1.136909,0.161755,-0.5, + -0.84747,-0.443196,-0.292185,1.178115,0.10978,-0.584482, + -0.813982,-0.512235,-0.273951,1.142211,0.172121,-0.579984, + -0.891261,-0.453491,0,1.170811,0.099004,-0.5, + -0.900624,-0.4346,0,1.199875,0.038989,-0.5, + -0.858311,-0.411605,-0.306404,1.208797,0.050229,-0.589491, + -0.858311,-0.411605,-0.306404,1.208797,0.050229,-0.589491, + -0.84747,-0.443196,-0.292185,1.178115,0.10978,-0.584482, + -0.891261,-0.453491,0,1.170811,0.099004,-0.5, + -0.30458,-0.744204,-0.594467,1.065609,0.289676,-0.638205, + -0.39374,-0.892943,-0.218225,1.064451,0.260311,-0.575384, + -0.696441,-0.651142,-0.301635,1.103513,0.226037,-0.576713, + -0.30458,-0.744204,-0.594467,1.065609,0.289676,-0.638205, + -0.696441,-0.651142,-0.301635,1.103513,0.226037,-0.576713, + -0.547648,-0.532516,-0.645374,1.112441,0.256132,-0.640641, + -0.39374,-0.892943,-0.218225,1.064451,0.260311,-0.575384, + -0.417976,-0.908458,0,1.064065,0.250523,-0.5, + -0.753723,-0.657192,0,1.100538,0.216006,-0.5, + -0.753723,-0.657192,0,1.100538,0.216006,-0.5, + -0.696441,-0.651142,-0.301635,1.103513,0.226037,-0.576713, + -0.39374,-0.892943,-0.218225,1.064451,0.260311,-0.575384, + -0.753723,-0.657192,0,1.100538,0.216006,-0.5, + -0.860968,-0.508659,0,1.136909,0.161755,-0.5, + -0.813982,-0.512235,-0.273951,1.142211,0.172121,-0.579984, + -0.813982,-0.512235,-0.273951,1.142211,0.172121,-0.579984, + -0.696441,-0.651142,-0.301635,1.103513,0.226037,-0.576713, + -0.753723,-0.657192,0,1.100538,0.216006,-0.5, + -0.659424,-0.432639,-0.614804,1.158118,0.203222,-0.646637, + -0.547648,-0.532516,-0.645374,1.112441,0.256132,-0.640641, + -0.696441,-0.651142,-0.301635,1.103513,0.226037,-0.576713, + -0.659424,-0.432639,-0.614804,1.158118,0.203222,-0.646637, + -0.696441,-0.651142,-0.301635,1.103513,0.226037,-0.576713, + -0.813982,-0.512235,-0.273951,1.142211,0.172121,-0.579984, + -0.30458,-0.744204,0.594467,1.065609,0.289676,-0.361795, + -0.547648,-0.532516,0.645374,1.112441,0.256132,-0.359359, + -0.696441,-0.651142,0.301635,1.103513,0.226037,-0.423287, + -0.30458,-0.744204,0.594467,1.065609,0.289676,-0.361795, + -0.696441,-0.651142,0.301635,1.103513,0.226037,-0.423287, + -0.393741,-0.892942,0.218225,1.064451,0.260311,-0.424615, + -0.659424,-0.432639,0.614804,1.158118,0.203222,-0.353363, + -0.813982,-0.512235,0.273951,1.142211,0.172121,-0.420016, + -0.696441,-0.651142,0.301635,1.103513,0.226037,-0.423287, + -0.659424,-0.432639,0.614804,1.158118,0.203222,-0.353363, + -0.696441,-0.651142,0.301635,1.103513,0.226037,-0.423287, + -0.547648,-0.532516,0.645374,1.112441,0.256132,-0.359359, + -0.813982,-0.512235,0.273951,1.142211,0.172121,-0.420016, + -0.860968,-0.508659,0,1.136909,0.161755,-0.5, + -0.753723,-0.657192,0,1.100538,0.216006,-0.5, + -0.753723,-0.657192,0,1.100538,0.216006,-0.5, + -0.696441,-0.651142,0.301635,1.103513,0.226037,-0.423287, + -0.813982,-0.512235,0.273951,1.142211,0.172121,-0.420016, + -0.753723,-0.657192,0,1.100538,0.216006,-0.5, + -0.417976,-0.908458,0,1.064065,0.250523,-0.5, + -0.393741,-0.892942,0.218225,1.064451,0.260311,-0.424615, + -0.393741,-0.892942,0.218225,1.064451,0.260311,-0.424615, + -0.696441,-0.651142,0.301635,1.103513,0.226037,-0.423287, + -0.753723,-0.657192,0,1.100538,0.216006,-0.5, + -0.695773,-0.304144,0.650689,1.235562,0.083949,-0.335934, + -0.858311,-0.411604,0.306404,1.208797,0.050229,-0.410509, + -0.84747,-0.443196,0.292185,1.178115,0.10978,-0.415518, + -0.695773,-0.304144,0.650689,1.235562,0.083949,-0.335934, + -0.84747,-0.443196,0.292185,1.178115,0.10978,-0.415518, + -0.687216,-0.351805,0.635584,1.200029,0.142107,-0.345117, + -0.858311,-0.411604,0.306404,1.208797,0.050229,-0.410509, + -0.900624,-0.4346,0,1.199875,0.038989,-0.5, + -0.891261,-0.453491,0,1.170811,0.099004,-0.5, + -0.891261,-0.453491,0,1.170811,0.099004,-0.5, + -0.84747,-0.443196,0.292185,1.178115,0.10978,-0.415518, + -0.858311,-0.411604,0.306404,1.208797,0.050229,-0.410509, + -0.860968,-0.508659,0,1.136909,0.161755,-0.5, + -0.813982,-0.512235,0.273951,1.142211,0.172121,-0.420016, + -0.84747,-0.443196,0.292185,1.178115,0.10978,-0.415518, + -0.860968,-0.508659,0,1.136909,0.161755,-0.5, + -0.84747,-0.443196,0.292185,1.178115,0.10978,-0.415518, + -0.891261,-0.453491,0,1.170811,0.099004,-0.5, + -0.813982,-0.512235,0.273951,1.142211,0.172121,-0.420016, + -0.659424,-0.432639,0.614804,1.158118,0.203222,-0.353363, + -0.687216,-0.351805,0.635584,1.200029,0.142107,-0.345117, + -0.687216,-0.351805,0.635584,1.200029,0.142107,-0.345117, + -0.84747,-0.443196,0.292185,1.178115,0.10978,-0.415518, + -0.813982,-0.512235,0.273951,1.142211,0.172121,-0.420016, + 0.311074,0.63183,-0.709947,1.431839,0.331232,-0.664066, + 0.339667,0.655519,-0.674478,1.36073,0.379173,-0.654883, + 0.12092,0.358415,-0.925698,1.324207,0.325294,-0.697124, + 0.311074,0.63183,-0.709947,1.431839,0.331232,-0.664066, + 0.12092,0.358415,-0.925698,1.324207,0.325294,-0.697124, + 0.074097,0.34389,-0.936082,1.38723,0.275032,-0.708812, + 0.339667,0.655519,-0.674478,1.36073,0.379173,-0.654883, + 0.306584,0.689695,-0.655994,1.274769,0.43129,-0.646637, + 0.126992,0.363932,-0.922728,1.248257,0.379456,-0.686629, + 0.126992,0.363932,-0.922728,1.248257,0.379456,-0.686629, + 0.12092,0.358415,-0.925698,1.324207,0.325294,-0.697124, + 0.339667,0.655519,-0.674478,1.36073,0.379173,-0.654883, + -0.106175,0.048409,-0.993168,1.216443,0.317256,-0.69996, + -0.127933,0.082246,-0.988367,1.280379,0.26064,-0.711204, + 0.12092,0.358415,-0.925698,1.324207,0.325294,-0.697124, + -0.106175,0.048409,-0.993168,1.216443,0.317256,-0.69996, + 0.12092,0.358415,-0.925698,1.324207,0.325294,-0.697124, + 0.126992,0.363932,-0.922728,1.248257,0.379456,-0.686629, + -0.127933,0.082246,-0.988367,1.280379,0.26064,-0.711204, + -0.152737,0.118235,-0.981169,1.3337,0.207591,-0.723727, + 0.074097,0.34389,-0.936082,1.38723,0.275032,-0.708812, + 0.074097,0.34389,-0.936082,1.38723,0.275032,-0.708812, + 0.12092,0.358415,-0.925698,1.324207,0.325294,-0.697124, + -0.127933,0.082246,-0.988367,1.280379,0.26064,-0.711204, + 0.225321,0.739198,-0.634679,1.177908,0.476825,-0.640641, + 0.08947,0.74633,-0.659535,1.074101,0.505017,-0.638205, + 0.076521,0.412911,-0.907551,1.072171,0.456076,-0.675897, + 0.076521,0.412911,-0.907551,1.072171,0.456076,-0.675897, + 0.115814,0.384301,-0.915915,1.163029,0.426667,-0.678998, + 0.225321,0.739198,-0.634679,1.177908,0.476825,-0.640641, + 0.012548,-0.001301,-0.99992,1.069855,0.397346,-0.688461, + -0.066606,0.01431,-0.997677,1.145175,0.366478,-0.691783, + 0.115814,0.384301,-0.915915,1.163029,0.426667,-0.678998, + 0.012548,-0.001301,-0.99992,1.069855,0.397346,-0.688461, + 0.115814,0.384301,-0.915915,1.163029,0.426667,-0.678998, + 0.076521,0.412911,-0.907551,1.072171,0.456076,-0.675897, + -0.066606,0.01431,-0.997677,1.145175,0.366478,-0.691783, + -0.106175,0.048409,-0.993168,1.216443,0.317256,-0.69996, + 0.126992,0.363932,-0.922728,1.248257,0.379456,-0.686629, + 0.126992,0.363932,-0.922728,1.248257,0.379456,-0.686629, + 0.115814,0.384301,-0.915915,1.163029,0.426667,-0.678998, + -0.066606,0.01431,-0.997677,1.145175,0.366478,-0.691783, + 0.306584,0.689695,-0.655994,1.274769,0.43129,-0.646637, + 0.225321,0.739198,-0.634679,1.177908,0.476825,-0.640641, + 0.115814,0.384301,-0.915915,1.163029,0.426667,-0.678998, + 0.306584,0.689695,-0.655994,1.274769,0.43129,-0.646637, + 0.115814,0.384301,-0.915915,1.163029,0.426667,-0.678998, + 0.126992,0.363932,-0.922728,1.248257,0.379456,-0.686629, + -0.30458,-0.744204,-0.594467,1.065609,0.289676,-0.638205, + -0.547648,-0.532516,-0.645374,1.112441,0.256132,-0.640641, + -0.30711,-0.324628,-0.894595,1.12732,0.306289,-0.678998, + -0.30458,-0.744204,-0.594467,1.065609,0.289676,-0.638205, + -0.30711,-0.324628,-0.894595,1.12732,0.306289,-0.678998, + -0.094868,-0.409964,-0.907155,1.067539,0.338617,-0.675897, + -0.547648,-0.532516,-0.645374,1.112441,0.256132,-0.640641, + -0.659424,-0.432639,-0.614804,1.158118,0.203222,-0.646637, + -0.382336,-0.228691,-0.895276,1.18463,0.255055,-0.686629, + -0.382336,-0.228691,-0.895276,1.18463,0.255055,-0.686629, + -0.30711,-0.324628,-0.894595,1.12732,0.306289,-0.678998, + -0.547648,-0.532516,-0.645374,1.112441,0.256132,-0.640641, + -0.106175,0.048409,-0.993168,1.216443,0.317256,-0.69996, + -0.066606,0.01431,-0.997677,1.145175,0.366478,-0.691783, + -0.30711,-0.324628,-0.894595,1.12732,0.306289,-0.678998, + -0.106175,0.048409,-0.993168,1.216443,0.317256,-0.69996, + -0.30711,-0.324628,-0.894595,1.12732,0.306289,-0.678998, + -0.382336,-0.228691,-0.895276,1.18463,0.255055,-0.686629, + -0.066606,0.01431,-0.997677,1.145175,0.366478,-0.691783, + 0.012548,-0.001301,-0.99992,1.069855,0.397346,-0.688461, + -0.094868,-0.409964,-0.907155,1.067539,0.338617,-0.675897, + -0.094868,-0.409964,-0.907155,1.067539,0.338617,-0.675897, + -0.30711,-0.324628,-0.894595,1.12732,0.306289,-0.678998, + -0.066606,0.01431,-0.997677,1.145175,0.366478,-0.691783, + -0.687216,-0.351805,-0.635584,1.200029,0.142107,-0.654883, + -0.695773,-0.304145,-0.650689,1.235562,0.083949,-0.664066, + -0.420703,-0.10775,-0.900777,1.28017,0.14015,-0.708812, + -0.420703,-0.10775,-0.900777,1.28017,0.14015,-0.708812, + -0.406685,-0.158703,-0.899678,1.236552,0.195985,-0.697124, + -0.687216,-0.351805,-0.635584,1.200029,0.142107,-0.654883, + -0.152737,0.118235,-0.981169,1.3337,0.207591,-0.723727, + -0.127933,0.082246,-0.988367,1.280379,0.26064,-0.711204, + -0.406685,-0.158703,-0.899678,1.236552,0.195985,-0.697124, + -0.152737,0.118235,-0.981169,1.3337,0.207591,-0.723727, + -0.406685,-0.158703,-0.899678,1.236552,0.195985,-0.697124, + -0.420703,-0.10775,-0.900777,1.28017,0.14015,-0.708812, + -0.127933,0.082246,-0.988367,1.280379,0.26064,-0.711204, + -0.106175,0.048409,-0.993168,1.216443,0.317256,-0.69996, + -0.382336,-0.228691,-0.895276,1.18463,0.255055,-0.686629, + -0.382336,-0.228691,-0.895276,1.18463,0.255055,-0.686629, + -0.406685,-0.158703,-0.899678,1.236552,0.195985,-0.697124, + -0.127933,0.082246,-0.988367,1.280379,0.26064,-0.711204, + -0.659424,-0.432639,-0.614804,1.158118,0.203222,-0.646637, + -0.687216,-0.351805,-0.635584,1.200029,0.142107,-0.654883, + -0.406685,-0.158703,-0.899678,1.236552,0.195985,-0.697124, + -0.659424,-0.432639,-0.614804,1.158118,0.203222,-0.646637, + -0.406685,-0.158703,-0.899678,1.236552,0.195985,-0.697124, + -0.382336,-0.228691,-0.895276,1.18463,0.255055,-0.686629, + 0.311074,0.63183,0.709947,1.431839,0.331232,-0.335934, + 0.074097,0.34389,0.936082,1.38723,0.275032,-0.291188, + 0.12092,0.358415,0.925698,1.324207,0.325294,-0.302876, + 0.311074,0.63183,0.709947,1.431839,0.331232,-0.335934, + 0.12092,0.358415,0.925698,1.324207,0.325294,-0.302876, + 0.339667,0.655519,0.674478,1.36073,0.379173,-0.345117, + 0.074097,0.34389,0.936082,1.38723,0.275032,-0.291188, + -0.152737,0.118235,0.981169,1.3337,0.207591,-0.276273, + -0.127934,0.082246,0.988367,1.280379,0.26064,-0.288796, + -0.127934,0.082246,0.988367,1.280379,0.26064,-0.288796, + 0.12092,0.358415,0.925698,1.324207,0.325294,-0.302876, + 0.074097,0.34389,0.936082,1.38723,0.275032,-0.291188, + -0.106175,0.048409,0.993168,1.216443,0.317256,-0.30004, + 0.126992,0.363931,0.922728,1.248257,0.379456,-0.313371, + 0.12092,0.358415,0.925698,1.324207,0.325294,-0.302876, + -0.106175,0.048409,0.993168,1.216443,0.317256,-0.30004, + 0.12092,0.358415,0.925698,1.324207,0.325294,-0.302876, + -0.127934,0.082246,0.988367,1.280379,0.26064,-0.288796, + 0.126992,0.363931,0.922728,1.248257,0.379456,-0.313371, + 0.306584,0.689695,0.655994,1.274769,0.43129,-0.353363, + 0.339667,0.655519,0.674478,1.36073,0.379173,-0.345117, + 0.339667,0.655519,0.674478,1.36073,0.379173,-0.345117, + 0.12092,0.358415,0.925698,1.324207,0.325294,-0.302876, + 0.126992,0.363931,0.922728,1.248257,0.379456,-0.313371, + -0.420703,-0.10775,0.900777,1.28017,0.14015,-0.291188, + -0.695773,-0.304144,0.650689,1.235562,0.083949,-0.335934, + -0.687216,-0.351805,0.635584,1.200029,0.142107,-0.345117, + -0.687216,-0.351805,0.635584,1.200029,0.142107,-0.345117, + -0.406685,-0.158702,0.899678,1.236552,0.195985,-0.302876, + -0.420703,-0.10775,0.900777,1.28017,0.14015,-0.291188, + -0.659424,-0.432639,0.614804,1.158118,0.203222,-0.353363, + -0.382336,-0.228691,0.895276,1.18463,0.255055,-0.313371, + -0.406685,-0.158702,0.899678,1.236552,0.195985,-0.302876, + -0.659424,-0.432639,0.614804,1.158118,0.203222,-0.353363, + -0.406685,-0.158702,0.899678,1.236552,0.195985,-0.302876, + -0.687216,-0.351805,0.635584,1.200029,0.142107,-0.345117, + -0.382336,-0.228691,0.895276,1.18463,0.255055,-0.313371, + -0.106175,0.048409,0.993168,1.216443,0.317256,-0.30004, + -0.127934,0.082246,0.988367,1.280379,0.26064,-0.288796, + -0.127934,0.082246,0.988367,1.280379,0.26064,-0.288796, + -0.406685,-0.158702,0.899678,1.236552,0.195985,-0.302876, + -0.382336,-0.228691,0.895276,1.18463,0.255055,-0.313371, + -0.152737,0.118235,0.981169,1.3337,0.207591,-0.276273, + -0.420703,-0.10775,0.900777,1.28017,0.14015,-0.291188, + -0.406685,-0.158702,0.899678,1.236552,0.195985,-0.302876, + -0.152737,0.118235,0.981169,1.3337,0.207591,-0.276273, + -0.406685,-0.158702,0.899678,1.236552,0.195985,-0.302876, + -0.127934,0.082246,0.988367,1.280379,0.26064,-0.288796, + -0.30458,-0.744204,0.594467,1.065609,0.289676,-0.361795, + -0.094868,-0.409964,0.907155,1.067539,0.338617,-0.324103, + -0.30711,-0.324628,0.894595,1.12732,0.306289,-0.321002, + -0.30458,-0.744204,0.594467,1.065609,0.289676,-0.361795, + -0.30711,-0.324628,0.894595,1.12732,0.306289,-0.321002, + -0.547648,-0.532516,0.645374,1.112441,0.256132,-0.359359, + -0.094868,-0.409964,0.907155,1.067539,0.338617,-0.324103, + 0.012549,-0.001301,0.99992,1.069855,0.397346,-0.311539, + -0.066605,0.01431,0.997677,1.145175,0.366478,-0.308217, + -0.066605,0.01431,0.997677,1.145175,0.366478,-0.308217, + -0.30711,-0.324628,0.894595,1.12732,0.306289,-0.321002, + -0.094868,-0.409964,0.907155,1.067539,0.338617,-0.324103, + -0.106175,0.048409,0.993168,1.216443,0.317256,-0.30004, + -0.382336,-0.228691,0.895276,1.18463,0.255055,-0.313371, + -0.30711,-0.324628,0.894595,1.12732,0.306289,-0.321002, + -0.106175,0.048409,0.993168,1.216443,0.317256,-0.30004, + -0.30711,-0.324628,0.894595,1.12732,0.306289,-0.321002, + -0.066605,0.01431,0.997677,1.145175,0.366478,-0.308217, + -0.382336,-0.228691,0.895276,1.18463,0.255055,-0.313371, + -0.659424,-0.432639,0.614804,1.158118,0.203222,-0.353363, + -0.547648,-0.532516,0.645374,1.112441,0.256132,-0.359359, + -0.547648,-0.532516,0.645374,1.112441,0.256132,-0.359359, + -0.30711,-0.324628,0.894595,1.12732,0.306289,-0.321002, + -0.382336,-0.228691,0.895276,1.18463,0.255055,-0.313371, + 0.076521,0.412911,0.907551,1.072171,0.456076,-0.324103, + 0.08947,0.74633,0.659535,1.074101,0.505017,-0.361795, + 0.225321,0.739198,0.634679,1.177908,0.476825,-0.359359, + 0.225321,0.739198,0.634679,1.177908,0.476825,-0.359359, + 0.115814,0.384301,0.915915,1.163029,0.426667,-0.321002, + 0.076521,0.412911,0.907551,1.072171,0.456076,-0.324103, + 0.306584,0.689695,0.655994,1.274769,0.43129,-0.353363, + 0.126992,0.363931,0.922728,1.248257,0.379456,-0.313371, + 0.115814,0.384301,0.915915,1.163029,0.426667,-0.321002, + 0.306584,0.689695,0.655994,1.274769,0.43129,-0.353363, + 0.115814,0.384301,0.915915,1.163029,0.426667,-0.321002, + 0.225321,0.739198,0.634679,1.177908,0.476825,-0.359359, + 0.126992,0.363931,0.922728,1.248257,0.379456,-0.313371, + -0.106175,0.048409,0.993168,1.216443,0.317256,-0.30004, + -0.066605,0.01431,0.997677,1.145175,0.366478,-0.308217, + -0.066605,0.01431,0.997677,1.145175,0.366478,-0.308217, + 0.115814,0.384301,0.915915,1.163029,0.426667,-0.321002, + 0.126992,0.363931,0.922728,1.248257,0.379456,-0.313371, + 0.012549,-0.001301,0.99992,1.069855,0.397346,-0.311539, + 0.076521,0.412911,0.907551,1.072171,0.456076,-0.324103, + 0.115814,0.384301,0.915915,1.163029,0.426667,-0.321002, + 0.012549,-0.001301,0.99992,1.069855,0.397346,-0.311539, + 0.115814,0.384301,0.915915,1.163029,0.426667,-0.321002, + -0.066605,0.01431,0.997677,1.145175,0.366478,-0.308217, + 0.311074,0.63183,-0.709947,1.431839,0.331232,-0.664066, + 0.460195,0.823869,-0.330849,1.458604,0.364953,-0.589491, + 0.4628,0.825265,-0.323657,1.382643,0.4115,-0.584482, + 0.311074,0.63183,-0.709947,1.431839,0.331232,-0.664066, + 0.4628,0.825265,-0.323657,1.382643,0.4115,-0.584482, + 0.339667,0.655519,-0.674478,1.36073,0.379173,-0.654883, + 0.460195,0.823869,-0.330849,1.458604,0.364953,-0.589491, + 0.489941,0.871755,0,1.467526,0.376193,-0.5, + 0.499794,0.866144,0,1.389948,0.422275,-0.5, + 0.499794,0.866144,0,1.389948,0.422275,-0.5, + 0.4628,0.825265,-0.323657,1.382643,0.4115,-0.584482, + 0.460195,0.823869,-0.330849,1.458604,0.364953,-0.589491, + 0.445921,0.895072,0,1.295978,0.472757,-0.5, + 0.408321,0.858475,-0.310315,1.290676,0.46239,-0.579984, + 0.4628,0.825265,-0.323657,1.382643,0.4115,-0.584482, + 0.445921,0.895072,0,1.295978,0.472757,-0.5, + 0.4628,0.825265,-0.323657,1.382643,0.4115,-0.584482, + 0.499794,0.866144,0,1.389948,0.422275,-0.5, + 0.408321,0.858475,-0.310315,1.290676,0.46239,-0.579984, + 0.306584,0.689695,-0.655994,1.274769,0.43129,-0.646637, + 0.339667,0.655519,-0.674478,1.36073,0.379173,-0.654883, + 0.339667,0.655519,-0.674478,1.36073,0.379173,-0.654883, + 0.4628,0.825265,-0.323657,1.382643,0.4115,-0.584482, + 0.408321,0.858475,-0.310315,1.290676,0.46239,-0.579984, + 0.311074,0.63183,0.709947,1.431839,0.331232,-0.335934, + 0.339667,0.655519,0.674478,1.36073,0.379173,-0.345117, + 0.4628,0.825265,0.323657,1.382643,0.4115,-0.415518, + 0.311074,0.63183,0.709947,1.431839,0.331232,-0.335934, + 0.4628,0.825265,0.323657,1.382643,0.4115,-0.415518, + 0.460195,0.823869,0.330849,1.458604,0.364953,-0.410509, + 0.339667,0.655519,0.674478,1.36073,0.379173,-0.345117, + 0.306584,0.689695,0.655994,1.274769,0.43129,-0.353363, + 0.40832,0.858475,0.310315,1.290676,0.46239,-0.420016, + 0.40832,0.858475,0.310315,1.290676,0.46239,-0.420016, + 0.4628,0.825265,0.323657,1.382643,0.4115,-0.415518, + 0.339667,0.655519,0.674478,1.36073,0.379173,-0.345117, + 0.445921,0.895072,0,1.295978,0.472757,-0.5, + 0.499794,0.866144,0,1.389948,0.422275,-0.5, + 0.4628,0.825265,0.323657,1.382643,0.4115,-0.415518, + 0.445921,0.895072,0,1.295978,0.472757,-0.5, + 0.4628,0.825265,0.323657,1.382643,0.4115,-0.415518, + 0.40832,0.858475,0.310315,1.290676,0.46239,-0.420016, + 0.499794,0.866144,0,1.389948,0.422275,-0.5, + 0.489941,0.871755,0,1.467526,0.376193,-0.5, + 0.460195,0.823869,0.330849,1.458604,0.364953,-0.410509, + 0.460195,0.823869,0.330849,1.458604,0.364953,-0.410509, + 0.4628,0.825265,0.323657,1.382643,0.4115,-0.415518, + 0.499794,0.866144,0,1.389948,0.422275,-0.5, + 0.225321,0.739198,0.634679,1.177908,0.476825,-0.359359, + 0.08947,0.74633,0.659535,1.074101,0.505017,-0.361795, + 0.099282,0.948291,0.301476,1.075259,0.534381,-0.424615, + 0.099282,0.948291,0.301476,1.075259,0.534381,-0.424615, + 0.298199,0.907962,0.294419,1.186836,0.506919,-0.423287, + 0.225321,0.739198,0.634679,1.177908,0.476825,-0.359359, + 0.156232,0.98772,0,1.075645,0.544169,-0.5, + 0.336559,0.941662,0,1.189812,0.516951,-0.5, + 0.298199,0.907962,0.294419,1.186836,0.506919,-0.423287, + 0.156232,0.98772,0,1.075645,0.544169,-0.5, + 0.298199,0.907962,0.294419,1.186836,0.506919,-0.423287, + 0.099282,0.948291,0.301476,1.075259,0.534381,-0.424615, + 0.336559,0.941662,0,1.189812,0.516951,-0.5, + 0.445921,0.895072,0,1.295978,0.472757,-0.5, + 0.40832,0.858475,0.310315,1.290676,0.46239,-0.420016, + 0.40832,0.858475,0.310315,1.290676,0.46239,-0.420016, + 0.298199,0.907962,0.294419,1.186836,0.506919,-0.423287, + 0.336559,0.941662,0,1.189812,0.516951,-0.5, + 0.306584,0.689695,0.655994,1.274769,0.43129,-0.353363, + 0.225321,0.739198,0.634679,1.177908,0.476825,-0.359359, + 0.298199,0.907962,0.294419,1.186836,0.506919,-0.423287, + 0.306584,0.689695,0.655994,1.274769,0.43129,-0.353363, + 0.298199,0.907962,0.294419,1.186836,0.506919,-0.423287, + 0.40832,0.858475,0.310315,1.290676,0.46239,-0.420016, + 0.099282,0.948291,-0.301476,1.075259,0.534381,-0.575384, + 0.08947,0.74633,-0.659535,1.074101,0.505017,-0.638205, + 0.225321,0.739198,-0.634679,1.177908,0.476825,-0.640641, + 0.225321,0.739198,-0.634679,1.177908,0.476825,-0.640641, + 0.298199,0.907962,-0.294419,1.186836,0.506919,-0.576713, + 0.099282,0.948291,-0.301476,1.075259,0.534381,-0.575384, + 0.306584,0.689695,-0.655994,1.274769,0.43129,-0.646637, + 0.408321,0.858475,-0.310315,1.290676,0.46239,-0.579984, + 0.298199,0.907962,-0.294419,1.186836,0.506919,-0.576713, + 0.306584,0.689695,-0.655994,1.274769,0.43129,-0.646637, + 0.298199,0.907962,-0.294419,1.186836,0.506919,-0.576713, + 0.225321,0.739198,-0.634679,1.177908,0.476825,-0.640641, + 0.408321,0.858475,-0.310315,1.290676,0.46239,-0.579984, + 0.445921,0.895072,0,1.295978,0.472757,-0.5, + 0.336559,0.941662,0,1.189812,0.516951,-0.5, + 0.336559,0.941662,0,1.189812,0.516951,-0.5, + 0.298199,0.907962,-0.294419,1.186836,0.506919,-0.576713, + 0.408321,0.858475,-0.310315,1.290676,0.46239,-0.579984, + 0.156232,0.98772,0,1.075645,0.544169,-0.5, + 0.099282,0.948291,-0.301476,1.075259,0.534381,-0.575384, + 0.298199,0.907962,-0.294419,1.186836,0.506919,-0.576713, + 0.156232,0.98772,0,1.075645,0.544169,-0.5, + 0.298199,0.907962,-0.294419,1.186836,0.506919,-0.576713, + 0.336559,0.941662,0,1.189812,0.516951,-0.5, + -0.199176,0.745044,-0.636583,0.769932,0.456132,-0.654883, + -0.218035,0.735069,-0.641977,0.691977,0.424648,-0.664066, + -0.042916,0.448451,-0.892776,0.741552,0.375033,-0.708812, + -0.042916,0.448451,-0.892776,0.741552,0.375033,-0.708812, + -0.044996,0.438512,-0.897598,0.808756,0.407522,-0.697124, + -0.199176,0.745044,-0.636583,0.769932,0.456132,-0.654883, + 0.160738,0.160922,-0.97379,0.801042,0.315496,-0.723727, + 0.142808,0.115868,-0.982945,0.855345,0.34919,-0.711204, + -0.044996,0.438512,-0.897598,0.808756,0.407522,-0.697124, + 0.160738,0.160922,-0.97379,0.801042,0.315496,-0.723727, + -0.044996,0.438512,-0.897598,0.808756,0.407522,-0.697124, + -0.042916,0.448451,-0.892776,0.741552,0.375033,-0.708812, + 0.142808,0.115868,-0.982945,0.855345,0.34919,-0.711204, + 0.124797,0.069981,-0.989711,0.920924,0.379919,-0.69996, + -0.024081,0.437847,-0.898727,0.88977,0.437716,-0.686629, + -0.024081,0.437847,-0.898727,0.88977,0.437716,-0.686629, + -0.044996,0.438512,-0.897598,0.808756,0.407522,-0.697124, + 0.142808,0.115868,-0.982945,0.855345,0.34919,-0.711204, + -0.142137,0.766468,-0.626358,0.863808,0.485881,-0.646637, + -0.199176,0.745044,-0.636583,0.769932,0.456132,-0.654883, + -0.044996,0.438512,-0.897598,0.808756,0.407522,-0.697124, + -0.142137,0.766468,-0.626358,0.863808,0.485881,-0.646637, + -0.044996,0.438512,-0.897598,0.808756,0.407522,-0.697124, + -0.024081,0.437847,-0.898727,0.88977,0.437716,-0.686629, + 0.398283,-0.122544,-0.90904,0.860532,0.255958,-0.708812, + 0.66282,-0.338306,-0.667996,0.910107,0.206343,-0.664066, + 0.585878,-0.414463,-0.696396,0.940757,0.242249,-0.654883, + 0.585878,-0.414463,-0.696396,0.940757,0.242249,-0.654883, + 0.362669,-0.212082,-0.907465,0.901933,0.290859,-0.697124, + 0.398283,-0.122544,-0.90904,0.860532,0.255958,-0.708812, + 0.514373,-0.562786,-0.647064,0.978041,0.273957,-0.646637, + 0.281388,-0.318777,-0.905098,0.952079,0.322122,-0.686629, + 0.362669,-0.212082,-0.907465,0.901933,0.290859,-0.697124, + 0.514373,-0.562786,-0.647064,0.978041,0.273957,-0.646637, + 0.362669,-0.212082,-0.907465,0.901933,0.290859,-0.697124, + 0.585878,-0.414463,-0.696396,0.940757,0.242249,-0.654883, + 0.124797,0.069981,-0.989711,0.920924,0.379919,-0.69996, + 0.142808,0.115868,-0.982945,0.855345,0.34919,-0.711204, + 0.362669,-0.212082,-0.907465,0.901933,0.290859,-0.697124, + 0.124797,0.069981,-0.989711,0.920924,0.379919,-0.69996, + 0.362669,-0.212082,-0.907465,0.901933,0.290859,-0.697124, + 0.281388,-0.318777,-0.905098,0.952079,0.322122,-0.686629, + 0.142808,0.115868,-0.982945,0.855345,0.34919,-0.711204, + 0.160738,0.160922,-0.97379,0.801042,0.315496,-0.723727, + 0.398283,-0.122544,-0.90904,0.860532,0.255958,-0.708812, + 0.398283,-0.122544,-0.90904,0.860532,0.255958,-0.708812, + 0.362669,-0.212082,-0.907465,0.901933,0.290859,-0.697124, + 0.142808,0.115868,-0.982945,0.855345,0.34919,-0.711204, + 0.223486,-0.713834,-0.663698,1.020234,0.292692,-0.640641, + -0.30458,-0.744204,-0.594467,1.065609,0.289676,-0.638205, + -0.094868,-0.409964,-0.907155,1.067539,0.338617,-0.675897, + -0.094868,-0.409964,-0.907155,1.067539,0.338617,-0.675897, + 0.118719,-0.361063,-0.924954,1.008203,0.340968,-0.678998, + 0.223486,-0.713834,-0.663698,1.020234,0.292692,-0.640641, + 0.012548,-0.001301,-0.99992,1.069855,0.397346,-0.688461, + 0.086047,0.023651,-0.99601,0.993766,0.398899,-0.691783, + 0.118719,-0.361063,-0.924954,1.008203,0.340968,-0.678998, + 0.012548,-0.001301,-0.99992,1.069855,0.397346,-0.688461, + 0.118719,-0.361063,-0.924954,1.008203,0.340968,-0.678998, + -0.094868,-0.409964,-0.907155,1.067539,0.338617,-0.675897, + 0.086047,0.023651,-0.99601,0.993766,0.398899,-0.691783, + 0.124797,0.069981,-0.989711,0.920924,0.379919,-0.69996, + 0.281388,-0.318777,-0.905098,0.952079,0.322122,-0.686629, + 0.281388,-0.318777,-0.905098,0.952079,0.322122,-0.686629, + 0.118719,-0.361063,-0.924954,1.008203,0.340968,-0.678998, + 0.086047,0.023651,-0.99601,0.993766,0.398899,-0.691783, + 0.281388,-0.318777,-0.905098,0.952079,0.322122,-0.686629, + 0.514373,-0.562786,-0.647064,0.978041,0.273957,-0.646637, + 0.223486,-0.713834,-0.663698,1.020234,0.292692,-0.640641, + 0.223486,-0.713834,-0.663698,1.020234,0.292692,-0.640641, + 0.118719,-0.361063,-0.924954,1.008203,0.340968,-0.678998, + 0.281388,-0.318777,-0.905098,0.952079,0.322122,-0.686629, + 0.08947,0.74633,-0.659535,1.074101,0.505017,-0.638205, + -0.041682,0.78334,-0.620195,0.967299,0.505105,-0.640641, + 0.017449,0.433004,-0.901223,0.97933,0.45683,-0.678998, + 0.08947,0.74633,-0.659535,1.074101,0.505017,-0.638205, + 0.017449,0.433004,-0.901223,0.97933,0.45683,-0.678998, + 0.076521,0.412911,-0.907551,1.072171,0.456076,-0.675897, + -0.041682,0.78334,-0.620195,0.967299,0.505105,-0.640641, + -0.142137,0.766468,-0.626358,0.863808,0.485881,-0.646637, + -0.024081,0.437847,-0.898727,0.88977,0.437716,-0.686629, + -0.024081,0.437847,-0.898727,0.88977,0.437716,-0.686629, + 0.017449,0.433004,-0.901223,0.97933,0.45683,-0.678998, + -0.041682,0.78334,-0.620195,0.967299,0.505105,-0.640641, + 0.124797,0.069981,-0.989711,0.920924,0.379919,-0.69996, + 0.086047,0.023651,-0.99601,0.993766,0.398899,-0.691783, + 0.017449,0.433004,-0.901223,0.97933,0.45683,-0.678998, + 0.124797,0.069981,-0.989711,0.920924,0.379919,-0.69996, + 0.017449,0.433004,-0.901223,0.97933,0.45683,-0.678998, + -0.024081,0.437847,-0.898727,0.88977,0.437716,-0.686629, + 0.086047,0.023651,-0.99601,0.993766,0.398899,-0.691783, + 0.012548,-0.001301,-0.99992,1.069855,0.397346,-0.688461, + 0.076521,0.412911,-0.907551,1.072171,0.456076,-0.675897, + 0.076521,0.412911,-0.907551,1.072171,0.456076,-0.675897, + 0.017449,0.433004,-0.901223,0.97933,0.45683,-0.678998, + 0.086047,0.023651,-0.99601,0.993766,0.398899,-0.691783, + -0.218035,0.735069,-0.641977,0.691977,0.424648,-0.664066, + -0.199176,0.745044,-0.636583,0.769932,0.456132,-0.654883, + -0.283565,0.912815,-0.293871,0.746638,0.485298,-0.584482, + -0.218035,0.735069,-0.641977,0.691977,0.424648,-0.664066, + -0.283565,0.912815,-0.293871,0.746638,0.485298,-0.584482, + -0.31842,0.898971,-0.300764,0.662233,0.454417,-0.589491, + -0.199176,0.745044,-0.636583,0.769932,0.456132,-0.654883, + -0.142137,0.766468,-0.626358,0.863808,0.485881,-0.646637, + -0.20497,0.936687,-0.283911,0.848231,0.51478,-0.579984, + -0.20497,0.936687,-0.283911,0.848231,0.51478,-0.579984, + -0.283565,0.912815,-0.293871,0.746638,0.485298,-0.584482, + -0.199176,0.745044,-0.636583,0.769932,0.456132,-0.654883, + -0.237278,0.971442,0,0.843038,0.524412,-0.5, + -0.314129,0.94938,0,0.738873,0.49502,-0.5, + -0.283565,0.912815,-0.293871,0.746638,0.485298,-0.584482, + -0.237278,0.971442,0,0.843038,0.524412,-0.5, + -0.283565,0.912815,-0.293871,0.746638,0.485298,-0.584482, + -0.20497,0.936687,-0.283911,0.848231,0.51478,-0.579984, + -0.314129,0.94938,0,0.738873,0.49502,-0.5, + -0.346116,0.938192,0,0.652318,0.46434,-0.5, + -0.31842,0.898971,-0.300764,0.662233,0.454417,-0.589491, + -0.31842,0.898971,-0.300764,0.662233,0.454417,-0.589491, + -0.283565,0.912815,-0.293871,0.746638,0.485298,-0.584482, + -0.314129,0.94938,0,0.738873,0.49502,-0.5, + -0.041682,0.78334,-0.620195,0.967299,0.505105,-0.640641, + 0.08947,0.74633,-0.659535,1.074101,0.505017,-0.638205, + 0.099282,0.948291,-0.301476,1.075259,0.534381,-0.575384, + 0.099282,0.948291,-0.301476,1.075259,0.534381,-0.575384, + -0.090849,0.947666,-0.306066,0.960081,0.534071,-0.576713, + -0.041682,0.78334,-0.620195,0.967299,0.505105,-0.640641, + 0.099282,0.948291,-0.301476,1.075259,0.534381,-0.575384, + 0.156232,0.98772,0,1.075645,0.544169,-0.5, + -0.084634,0.996412,0,0.957675,0.543726,-0.5, + -0.084634,0.996412,0,0.957675,0.543726,-0.5, + -0.090849,0.947666,-0.306066,0.960081,0.534071,-0.576713, + 0.099282,0.948291,-0.301476,1.075259,0.534381,-0.575384, + -0.084634,0.996412,0,0.957675,0.543726,-0.5, + -0.237278,0.971442,0,0.843038,0.524412,-0.5, + -0.20497,0.936687,-0.283911,0.848231,0.51478,-0.579984, + -0.20497,0.936687,-0.283911,0.848231,0.51478,-0.579984, + -0.090849,0.947666,-0.306066,0.960081,0.534071,-0.576713, + -0.084634,0.996412,0,0.957675,0.543726,-0.5, + -0.142137,0.766468,-0.626358,0.863808,0.485881,-0.646637, + -0.041682,0.78334,-0.620195,0.967299,0.505105,-0.640641, + -0.090849,0.947666,-0.306066,0.960081,0.534071,-0.576713, + -0.142137,0.766468,-0.626358,0.863808,0.485881,-0.646637, + -0.090849,0.947666,-0.306066,0.960081,0.534071,-0.576713, + -0.20497,0.936687,-0.283911,0.848231,0.51478,-0.579984, + 0.099282,0.948291,0.301476,1.075259,0.534381,-0.424615, + 0.08947,0.74633,0.659535,1.074101,0.505017,-0.361795, + -0.041682,0.78334,0.620195,0.967299,0.505105,-0.359359, + -0.041682,0.78334,0.620195,0.967299,0.505105,-0.359359, + -0.090849,0.947666,0.306066,0.960081,0.534071,-0.423287, + 0.099282,0.948291,0.301476,1.075259,0.534381,-0.424615, + -0.142137,0.766468,0.626358,0.863808,0.485881,-0.353363, + -0.20497,0.936687,0.283911,0.848231,0.51478,-0.420016, + -0.090849,0.947666,0.306066,0.960081,0.534071,-0.423287, + -0.142137,0.766468,0.626358,0.863808,0.485881,-0.353363, + -0.090849,0.947666,0.306066,0.960081,0.534071,-0.423287, + -0.041682,0.78334,0.620195,0.967299,0.505105,-0.359359, + -0.20497,0.936687,0.283911,0.848231,0.51478,-0.420016, + -0.237278,0.971442,0,0.843038,0.524412,-0.5, + -0.084634,0.996412,0,0.957675,0.543726,-0.5, + -0.084634,0.996412,0,0.957675,0.543726,-0.5, + -0.090849,0.947666,0.306066,0.960081,0.534071,-0.423287, + -0.20497,0.936687,0.283911,0.848231,0.51478,-0.420016, + -0.084634,0.996412,0,0.957675,0.543726,-0.5, + 0.156232,0.98772,0,1.075645,0.544169,-0.5, + 0.099282,0.948291,0.301476,1.075259,0.534381,-0.424615, + 0.099282,0.948291,0.301476,1.075259,0.534381,-0.424615, + -0.090849,0.947666,0.306066,0.960081,0.534071,-0.423287, + -0.084634,0.996412,0,0.957675,0.543726,-0.5, + -0.218035,0.735069,0.641977,0.691977,0.424648,-0.335934, + -0.318419,0.898972,0.300764,0.662233,0.454417,-0.410509, + -0.283565,0.912815,0.293871,0.746638,0.485298,-0.415518, + -0.218035,0.735069,0.641977,0.691977,0.424648,-0.335934, + -0.283565,0.912815,0.293871,0.746638,0.485298,-0.415518, + -0.199176,0.745044,0.636583,0.769932,0.456132,-0.345117, + -0.318419,0.898972,0.300764,0.662233,0.454417,-0.410509, + -0.346116,0.938192,0,0.652318,0.46434,-0.5, + -0.314129,0.94938,0,0.738873,0.49502,-0.5, + -0.314129,0.94938,0,0.738873,0.49502,-0.5, + -0.283565,0.912815,0.293871,0.746638,0.485298,-0.415518, + -0.318419,0.898972,0.300764,0.662233,0.454417,-0.410509, + -0.237278,0.971442,0,0.843038,0.524412,-0.5, + -0.20497,0.936687,0.283911,0.848231,0.51478,-0.420016, + -0.283565,0.912815,0.293871,0.746638,0.485298,-0.415518, + -0.237278,0.971442,0,0.843038,0.524412,-0.5, + -0.283565,0.912815,0.293871,0.746638,0.485298,-0.415518, + -0.314129,0.94938,0,0.738873,0.49502,-0.5, + -0.20497,0.936687,0.283911,0.848231,0.51478,-0.420016, + -0.142137,0.766468,0.626358,0.863808,0.485881,-0.353363, + -0.199176,0.745044,0.636583,0.769932,0.456132,-0.345117, + -0.199176,0.745044,0.636583,0.769932,0.456132,-0.345117, + -0.283565,0.912815,0.293871,0.746638,0.485298,-0.415518, + -0.20497,0.936687,0.283911,0.848231,0.51478,-0.420016, + -0.042916,0.448451,0.892776,0.741552,0.375033,-0.291188, + -0.218035,0.735069,0.641977,0.691977,0.424648,-0.335934, + -0.199176,0.745044,0.636583,0.769932,0.456132,-0.345117, + -0.199176,0.745044,0.636583,0.769932,0.456132,-0.345117, + -0.044996,0.438512,0.897598,0.808756,0.407522,-0.302876, + -0.042916,0.448451,0.892776,0.741552,0.375033,-0.291188, + -0.142137,0.766468,0.626358,0.863808,0.485881,-0.353363, + -0.024081,0.437847,0.898727,0.88977,0.437716,-0.313371, + -0.044996,0.438512,0.897598,0.808756,0.407522,-0.302876, + -0.142137,0.766468,0.626358,0.863808,0.485881,-0.353363, + -0.044996,0.438512,0.897598,0.808756,0.407522,-0.302876, + -0.199176,0.745044,0.636583,0.769932,0.456132,-0.345117, + -0.024081,0.437847,0.898727,0.88977,0.437716,-0.313371, + 0.124797,0.069981,0.989711,0.920924,0.379919,-0.30004, + 0.142808,0.115868,0.982945,0.855345,0.34919,-0.288796, + 0.142808,0.115868,0.982945,0.855345,0.34919,-0.288796, + -0.044996,0.438512,0.897598,0.808756,0.407522,-0.302876, + -0.024081,0.437847,0.898727,0.88977,0.437716,-0.313371, + 0.160738,0.160922,0.97379,0.801042,0.315496,-0.276273, + -0.042916,0.448451,0.892776,0.741552,0.375033,-0.291188, + -0.044996,0.438512,0.897598,0.808756,0.407522,-0.302876, + 0.160738,0.160922,0.97379,0.801042,0.315496,-0.276273, + -0.044996,0.438512,0.897598,0.808756,0.407522,-0.302876, + 0.142808,0.115868,0.982945,0.855345,0.34919,-0.288796, + 0.08947,0.74633,0.659535,1.074101,0.505017,-0.361795, + 0.076521,0.412911,0.907551,1.072171,0.456076,-0.324103, + 0.017449,0.433004,0.901223,0.97933,0.45683,-0.321002, + 0.08947,0.74633,0.659535,1.074101,0.505017,-0.361795, + 0.017449,0.433004,0.901223,0.97933,0.45683,-0.321002, + -0.041682,0.78334,0.620195,0.967299,0.505105,-0.359359, + 0.076521,0.412911,0.907551,1.072171,0.456076,-0.324103, + 0.012549,-0.001301,0.99992,1.069855,0.397346,-0.311539, + 0.086047,0.023651,0.99601,0.993766,0.398899,-0.308217, + 0.086047,0.023651,0.99601,0.993766,0.398899,-0.308217, + 0.017449,0.433004,0.901223,0.97933,0.45683,-0.321002, + 0.076521,0.412911,0.907551,1.072171,0.456076,-0.324103, + 0.124797,0.069981,0.989711,0.920924,0.379919,-0.30004, + -0.024081,0.437847,0.898727,0.88977,0.437716,-0.313371, + 0.017449,0.433004,0.901223,0.97933,0.45683,-0.321002, + 0.124797,0.069981,0.989711,0.920924,0.379919,-0.30004, + 0.017449,0.433004,0.901223,0.97933,0.45683,-0.321002, + 0.086047,0.023651,0.99601,0.993766,0.398899,-0.308217, + -0.024081,0.437847,0.898727,0.88977,0.437716,-0.313371, + -0.142137,0.766468,0.626358,0.863808,0.485881,-0.353363, + -0.041682,0.78334,0.620195,0.967299,0.505105,-0.359359, + -0.041682,0.78334,0.620195,0.967299,0.505105,-0.359359, + 0.017449,0.433004,0.901223,0.97933,0.45683,-0.321002, + -0.024081,0.437847,0.898727,0.88977,0.437716,-0.313371, + -0.094868,-0.409964,0.907155,1.067539,0.338617,-0.324103, + -0.30458,-0.744204,0.594467,1.065609,0.289676,-0.361795, + 0.223486,-0.713834,0.663698,1.020234,0.292692,-0.359359, + 0.223486,-0.713834,0.663698,1.020234,0.292692,-0.359359, + 0.118719,-0.361063,0.924954,1.008203,0.340968,-0.321002, + -0.094868,-0.409964,0.907155,1.067539,0.338617,-0.324103, + 0.223486,-0.713834,0.663698,1.020234,0.292692,-0.359359, + 0.514373,-0.562786,0.647064,0.978041,0.273957,-0.353363, + 0.281389,-0.318776,0.905098,0.952079,0.322122,-0.313371, + 0.281389,-0.318776,0.905098,0.952079,0.322122,-0.313371, + 0.118719,-0.361063,0.924954,1.008203,0.340968,-0.321002, + 0.223486,-0.713834,0.663698,1.020234,0.292692,-0.359359, + 0.281389,-0.318776,0.905098,0.952079,0.322122,-0.313371, + 0.124797,0.069981,0.989711,0.920924,0.379919,-0.30004, + 0.086047,0.023651,0.99601,0.993766,0.398899,-0.308217, + 0.086047,0.023651,0.99601,0.993766,0.398899,-0.308217, + 0.118719,-0.361063,0.924954,1.008203,0.340968,-0.321002, + 0.281389,-0.318776,0.905098,0.952079,0.322122,-0.313371, + 0.012549,-0.001301,0.99992,1.069855,0.397346,-0.311539, + -0.094868,-0.409964,0.907155,1.067539,0.338617,-0.324103, + 0.118719,-0.361063,0.924954,1.008203,0.340968,-0.321002, + 0.012549,-0.001301,0.99992,1.069855,0.397346,-0.311539, + 0.118719,-0.361063,0.924954,1.008203,0.340968,-0.321002, + 0.086047,0.023651,0.99601,0.993766,0.398899,-0.308217, + 0.585878,-0.414463,0.696396,0.940757,0.242249,-0.345117, + 0.66282,-0.338306,0.667996,0.910107,0.206343,-0.335934, + 0.398283,-0.122544,0.90904,0.860532,0.255958,-0.291188, + 0.398283,-0.122544,0.90904,0.860532,0.255958,-0.291188, + 0.362669,-0.212082,0.907465,0.901933,0.290859,-0.302876, + 0.585878,-0.414463,0.696396,0.940757,0.242249,-0.345117, + 0.398283,-0.122544,0.90904,0.860532,0.255958,-0.291188, + 0.160738,0.160922,0.97379,0.801042,0.315496,-0.276273, + 0.142808,0.115868,0.982945,0.855345,0.34919,-0.288796, + 0.142808,0.115868,0.982945,0.855345,0.34919,-0.288796, + 0.362669,-0.212082,0.907465,0.901933,0.290859,-0.302876, + 0.398283,-0.122544,0.90904,0.860532,0.255958,-0.291188, + 0.124797,0.069981,0.989711,0.920924,0.379919,-0.30004, + 0.281389,-0.318776,0.905098,0.952079,0.322122,-0.313371, + 0.362669,-0.212082,0.907465,0.901933,0.290859,-0.302876, + 0.124797,0.069981,0.989711,0.920924,0.379919,-0.30004, + 0.362669,-0.212082,0.907465,0.901933,0.290859,-0.302876, + 0.142808,0.115868,0.982945,0.855345,0.34919,-0.288796, + 0.514373,-0.562786,0.647064,0.978041,0.273957,-0.353363, + 0.585878,-0.414463,0.696396,0.940757,0.242249,-0.345117, + 0.362669,-0.212082,0.907465,0.901933,0.290859,-0.302876, + 0.514373,-0.562786,0.647064,0.978041,0.273957,-0.353363, + 0.362669,-0.212082,0.907465,0.901933,0.290859,-0.302876, + 0.281389,-0.318776,0.905098,0.952079,0.322122,-0.313371, + 0.66282,-0.338306,0.667996,0.910107,0.206343,-0.335934, + 0.585878,-0.414463,0.696396,0.940757,0.242249,-0.345117, + 0.748153,-0.579603,0.322997,0.964051,0.213083,-0.415518, + 0.66282,-0.338306,0.667996,0.910107,0.206343,-0.335934, + 0.748153,-0.579603,0.322997,0.964051,0.213083,-0.415518, + 0.828154,-0.461264,0.318428,0.939852,0.176575,-0.410509, + 0.514373,-0.562786,0.647064,0.978041,0.273957,-0.353363, + 0.575394,-0.755507,0.31326,0.993618,0.245059,-0.420016, + 0.748153,-0.579603,0.322997,0.964051,0.213083,-0.415518, + 0.514373,-0.562786,0.647064,0.978041,0.273957,-0.353363, + 0.748153,-0.579603,0.322997,0.964051,0.213083,-0.415518, + 0.585878,-0.414463,0.696396,0.940757,0.242249,-0.345117, + 0.637531,-0.770425,0,0.998811,0.235426,-0.5, + 0.82345,-0.567389,0,0.971816,0.203361,-0.5, + 0.748153,-0.579603,0.322997,0.964051,0.213083,-0.415518, + 0.637531,-0.770425,0,0.998811,0.235426,-0.5, + 0.748153,-0.579603,0.322997,0.964051,0.213083,-0.415518, + 0.575394,-0.755507,0.31326,0.993618,0.245059,-0.420016, + 0.82345,-0.567389,0,0.971816,0.203361,-0.5, + 0.879883,-0.475191,0,0.949767,0.166652,-0.5, + 0.828154,-0.461264,0.318428,0.939852,0.176575,-0.410509, + 0.828154,-0.461264,0.318428,0.939852,0.176575,-0.410509, + 0.748153,-0.579603,0.322997,0.964051,0.213083,-0.415518, + 0.82345,-0.567389,0,0.971816,0.203361,-0.5, + -0.30458,-0.744204,0.594467,1.065609,0.289676,-0.361795, + -0.393741,-0.892942,0.218225,1.064451,0.260311,-0.424615, + 0.224558,-0.931869,0.284944,1.027452,0.263727,-0.423287, + -0.30458,-0.744204,0.594467,1.065609,0.289676,-0.361795, + 0.224558,-0.931869,0.284944,1.027452,0.263727,-0.423287, + 0.223486,-0.713834,0.663698,1.020234,0.292692,-0.359359, + -0.393741,-0.892942,0.218225,1.064451,0.260311,-0.424615, + -0.417976,-0.908458,0,1.064065,0.250523,-0.5, + 0.113113,-0.993582,0,1.029858,0.254072,-0.5, + 0.113113,-0.993582,0,1.029858,0.254072,-0.5, + 0.224558,-0.931869,0.284944,1.027452,0.263727,-0.423287, + -0.393741,-0.892942,0.218225,1.064451,0.260311,-0.424615, + 0.637531,-0.770425,0,0.998811,0.235426,-0.5, + 0.575394,-0.755507,0.31326,0.993618,0.245059,-0.420016, + 0.224558,-0.931869,0.284944,1.027452,0.263727,-0.423287, + 0.637531,-0.770425,0,0.998811,0.235426,-0.5, + 0.224558,-0.931869,0.284944,1.027452,0.263727,-0.423287, + 0.113113,-0.993582,0,1.029858,0.254072,-0.5, + 0.575394,-0.755507,0.31326,0.993618,0.245059,-0.420016, + 0.514373,-0.562786,0.647064,0.978041,0.273957,-0.353363, + 0.223486,-0.713834,0.663698,1.020234,0.292692,-0.359359, + 0.223486,-0.713834,0.663698,1.020234,0.292692,-0.359359, + 0.224558,-0.931869,0.284944,1.027452,0.263727,-0.423287, + 0.575394,-0.755507,0.31326,0.993618,0.245059,-0.420016, + -0.30458,-0.744204,-0.594467,1.065609,0.289676,-0.638205, + 0.223486,-0.713834,-0.663698,1.020234,0.292692,-0.640641, + 0.224558,-0.931869,-0.284944,1.027452,0.263727,-0.576713, + -0.30458,-0.744204,-0.594467,1.065609,0.289676,-0.638205, + 0.224558,-0.931869,-0.284944,1.027452,0.263727,-0.576713, + -0.39374,-0.892943,-0.218225,1.064451,0.260311,-0.575384, + 0.223486,-0.713834,-0.663698,1.020234,0.292692,-0.640641, + 0.514373,-0.562786,-0.647064,0.978041,0.273957,-0.646637, + 0.575393,-0.755507,-0.31326,0.993618,0.245059,-0.579984, + 0.575393,-0.755507,-0.31326,0.993618,0.245059,-0.579984, + 0.224558,-0.931869,-0.284944,1.027452,0.263727,-0.576713, + 0.223486,-0.713834,-0.663698,1.020234,0.292692,-0.640641, + 0.637531,-0.770425,0,0.998811,0.235426,-0.5, + 0.113113,-0.993582,0,1.029858,0.254072,-0.5, + 0.224558,-0.931869,-0.284944,1.027452,0.263727,-0.576713, + 0.637531,-0.770425,0,0.998811,0.235426,-0.5, + 0.224558,-0.931869,-0.284944,1.027452,0.263727,-0.576713, + 0.575393,-0.755507,-0.31326,0.993618,0.245059,-0.579984, + 0.113113,-0.993582,0,1.029858,0.254072,-0.5, + -0.417976,-0.908458,0,1.064065,0.250523,-0.5, + -0.39374,-0.892943,-0.218225,1.064451,0.260311,-0.575384, + -0.39374,-0.892943,-0.218225,1.064451,0.260311,-0.575384, + 0.224558,-0.931869,-0.284944,1.027452,0.263727,-0.576713, + 0.113113,-0.993582,0,1.029858,0.254072,-0.5, + 0.66282,-0.338306,-0.667996,0.910107,0.206343,-0.664066, + 0.828154,-0.461264,-0.318429,0.939852,0.176575,-0.589491, + 0.748153,-0.579603,-0.322997,0.964051,0.213083,-0.584482, + 0.66282,-0.338306,-0.667996,0.910107,0.206343,-0.664066, + 0.748153,-0.579603,-0.322997,0.964051,0.213083,-0.584482, + 0.585878,-0.414463,-0.696396,0.940757,0.242249,-0.654883, + 0.828154,-0.461264,-0.318429,0.939852,0.176575,-0.589491, + 0.879883,-0.475191,0,0.949767,0.166652,-0.5, + 0.82345,-0.567389,0,0.971816,0.203361,-0.5, + 0.82345,-0.567389,0,0.971816,0.203361,-0.5, + 0.748153,-0.579603,-0.322997,0.964051,0.213083,-0.584482, + 0.828154,-0.461264,-0.318429,0.939852,0.176575,-0.589491, + 0.637531,-0.770425,0,0.998811,0.235426,-0.5, + 0.575393,-0.755507,-0.31326,0.993618,0.245059,-0.579984, + 0.748153,-0.579603,-0.322997,0.964051,0.213083,-0.584482, + 0.637531,-0.770425,0,0.998811,0.235426,-0.5, + 0.748153,-0.579603,-0.322997,0.964051,0.213083,-0.584482, + 0.82345,-0.567389,0,0.971816,0.203361,-0.5, + 0.514373,-0.562786,-0.647064,0.978041,0.273957,-0.646637, + 0.585878,-0.414463,-0.696396,0.940757,0.242249,-0.654883, + 0.748153,-0.579603,-0.322997,0.964051,0.213083,-0.584482, + 0.514373,-0.562786,-0.647064,0.978041,0.273957,-0.646637, + 0.748153,-0.579603,-0.322997,0.964051,0.213083,-0.584482, + 0.575393,-0.755507,-0.31326,0.993618,0.245059,-0.579984, + 0.65574,-0.380493,0.652097,0.887817,0.175019,-0.327123, + 0.66282,-0.338306,0.667996,0.910107,0.206343,-0.335934, + 0.828154,-0.461264,0.318428,0.939852,0.176575,-0.410509, + 0.828154,-0.461264,0.318428,0.939852,0.176575,-0.410509, + 0.788892,-0.514111,0.336659,0.922122,0.14431,-0.405704, + 0.65574,-0.380493,0.652097,0.887817,0.175019,-0.327123, + 0.879883,-0.475191,0,0.949767,0.166652,-0.5, + 0.818537,-0.574454,0,0.933557,0.134073,-0.5, + 0.788892,-0.514111,0.336659,0.922122,0.14431,-0.405704, + 0.879883,-0.475191,0,0.949767,0.166652,-0.5, + 0.788892,-0.514111,0.336659,0.922122,0.14431,-0.405704, + 0.828154,-0.461264,0.318428,0.939852,0.176575,-0.410509, + 0.818537,-0.574454,0,0.933557,0.134073,-0.5, + 0.394485,-0.918903,0,0.915792,0.112008,-0.5, + 0.520237,-0.801686,0.294369,0.90384,0.122594,-0.405051, + 0.520237,-0.801686,0.294369,0.90384,0.122594,-0.405051, + 0.788892,-0.514111,0.336659,0.922122,0.14431,-0.405704, + 0.818537,-0.574454,0,0.933557,0.134073,-0.5, + 0.31991,-0.691022,0.648187,0.867858,0.153664,-0.325812, + 0.65574,-0.380493,0.652097,0.887817,0.175019,-0.327123, + 0.788892,-0.514111,0.336659,0.922122,0.14431,-0.405704, + 0.31991,-0.691022,0.648187,0.867858,0.153664,-0.325812, + 0.788892,-0.514111,0.336659,0.922122,0.14431,-0.405704, + 0.520237,-0.801686,0.294369,0.90384,0.122594,-0.405051, + 0.828154,-0.461264,-0.318429,0.939852,0.176575,-0.589491, + 0.66282,-0.338306,-0.667996,0.910107,0.206343,-0.664066, + 0.65574,-0.380493,-0.652097,0.887817,0.175019,-0.672877, + 0.65574,-0.380493,-0.652097,0.887817,0.175019,-0.672877, + 0.788892,-0.514111,-0.336659,0.922122,0.14431,-0.594296, + 0.828154,-0.461264,-0.318429,0.939852,0.176575,-0.589491, + 0.31991,-0.691022,-0.648187,0.867858,0.153664,-0.674188, + 0.520237,-0.801686,-0.29437,0.90384,0.122594,-0.594949, + 0.788892,-0.514111,-0.336659,0.922122,0.14431,-0.594296, + 0.31991,-0.691022,-0.648187,0.867858,0.153664,-0.674188, + 0.788892,-0.514111,-0.336659,0.922122,0.14431,-0.594296, + 0.65574,-0.380493,-0.652097,0.887817,0.175019,-0.672877, + 0.520237,-0.801686,-0.29437,0.90384,0.122594,-0.594949, + 0.394485,-0.918903,0,0.915792,0.112008,-0.5, + 0.818537,-0.574454,0,0.933557,0.134073,-0.5, + 0.818537,-0.574454,0,0.933557,0.134073,-0.5, + 0.788892,-0.514111,-0.336659,0.922122,0.14431,-0.594296, + 0.520237,-0.801686,-0.29437,0.90384,0.122594,-0.594949, + 0.879883,-0.475191,0,0.949767,0.166652,-0.5, + 0.828154,-0.461264,-0.318429,0.939852,0.176575,-0.589491, + 0.788892,-0.514111,-0.336659,0.922122,0.14431,-0.594296, + 0.879883,-0.475191,0,0.949767,0.166652,-0.5, + 0.788892,-0.514111,-0.336659,0.922122,0.14431,-0.594296, + 0.818537,-0.574454,0,0.933557,0.134073,-0.5, + -0.464025,-0.863104,-0.199329,0.820528,0.154011,-0.638667, + -0.4837,-0.869471,-0.100277,0.83753,0.13389,-0.5825, + -0.146037,-0.967926,-0.204432,0.877985,0.117734,-0.5875, + -0.464025,-0.863104,-0.199329,0.820528,0.154011,-0.638667, + -0.146037,-0.967926,-0.204432,0.877985,0.117734,-0.5875, + -0.23383,-0.86988,-0.434318,0.844199,0.147671,-0.660875, + -0.435927,-0.899982,0,0.846018,0.123878,-0.5, + -0.093893,-0.995582,0,0.889078,0.10684,-0.5, + -0.146037,-0.967926,-0.204432,0.877985,0.117734,-0.5875, + -0.435927,-0.899982,0,0.846018,0.123878,-0.5, + -0.146037,-0.967926,-0.204432,0.877985,0.117734,-0.5875, + -0.4837,-0.869471,-0.100277,0.83753,0.13389,-0.5825, + 0.394485,-0.918903,0,0.915792,0.112008,-0.5, + 0.520237,-0.801686,-0.29437,0.90384,0.122594,-0.594949, + -0.146037,-0.967926,-0.204432,0.877985,0.117734,-0.5875, + 0.394485,-0.918903,0,0.915792,0.112008,-0.5, + -0.146037,-0.967926,-0.204432,0.877985,0.117734,-0.5875, + -0.093893,-0.995582,0,0.889078,0.10684,-0.5, + 0.31991,-0.691022,-0.648187,0.867858,0.153664,-0.674188, + -0.23383,-0.86988,-0.434318,0.844199,0.147671,-0.660875, + -0.146037,-0.967926,-0.204432,0.877985,0.117734,-0.5875, + 0.31991,-0.691022,-0.648187,0.867858,0.153664,-0.674188, + -0.146037,-0.967926,-0.204432,0.877985,0.117734,-0.5875, + 0.520237,-0.801686,-0.29437,0.90384,0.122594,-0.594949, + -0.464025,-0.863104,0.199329,0.820528,0.154011,-0.361333, + -0.23383,-0.86988,0.434318,0.844199,0.147671,-0.339125, + -0.146037,-0.967926,0.204432,0.877985,0.117734,-0.4125, + -0.464025,-0.863104,0.199329,0.820528,0.154011,-0.361333, + -0.146037,-0.967926,0.204432,0.877985,0.117734,-0.4125, + -0.4837,-0.869471,0.100277,0.83753,0.13389,-0.4175, + 0.31991,-0.691022,0.648187,0.867858,0.153664,-0.325812, + 0.520237,-0.801686,0.294369,0.90384,0.122594,-0.405051, + -0.146037,-0.967926,0.204432,0.877985,0.117734,-0.4125, + 0.31991,-0.691022,0.648187,0.867858,0.153664,-0.325812, + -0.146037,-0.967926,0.204432,0.877985,0.117734,-0.4125, + -0.23383,-0.86988,0.434318,0.844199,0.147671,-0.339125, + 0.394485,-0.918903,0,0.915792,0.112008,-0.5, + -0.093893,-0.995582,0,0.889078,0.10684,-0.5, + -0.146037,-0.967926,0.204432,0.877985,0.117734,-0.4125, + 0.394485,-0.918903,0,0.915792,0.112008,-0.5, + -0.146037,-0.967926,0.204432,0.877985,0.117734,-0.4125, + 0.520237,-0.801686,0.294369,0.90384,0.122594,-0.405051, + -0.435927,-0.899982,0,0.846018,0.123878,-0.5, + -0.4837,-0.869471,0.100277,0.83753,0.13389,-0.4175, + -0.146037,-0.967926,0.204432,0.877985,0.117734,-0.4125, + -0.435927,-0.899982,0,0.846018,0.123878,-0.5, + -0.146037,-0.967926,0.204432,0.877985,0.117734,-0.4125, + -0.093893,-0.995582,0,0.889078,0.10684,-0.5, + 0.66282,-0.338306,-0.667996,0.910107,0.206343,-0.664066, + 0.398283,-0.122544,-0.90904,0.860532,0.255958,-0.708812, + 0.378094,-0.147323,-0.91397,0.830643,0.2262,-0.720025, + 0.66282,-0.338306,-0.667996,0.910107,0.206343,-0.664066, + 0.378094,-0.147323,-0.91397,0.830643,0.2262,-0.720025, + 0.65574,-0.380493,-0.652097,0.887817,0.175019,-0.672877, + 0.160738,0.160922,-0.97379,0.801042,0.315496,-0.723727, + 0.108083,0.116579,-0.987283,0.762033,0.287619,-0.735741, + 0.378094,-0.147323,-0.91397,0.830643,0.2262,-0.720025, + 0.160738,0.160922,-0.97379,0.801042,0.315496,-0.723727, + 0.378094,-0.147323,-0.91397,0.830643,0.2262,-0.720025, + 0.398283,-0.122544,-0.90904,0.860532,0.255958,-0.708812, + 0.108083,0.116579,-0.987283,0.762033,0.287619,-0.735741, + -0.233968,-0.2359,-0.943191,0.735693,0.265534,-0.73806, + 0.024413,-0.469703,-0.882487,0.807717,0.204533,-0.722006, + 0.024413,-0.469703,-0.882487,0.807717,0.204533,-0.722006, + 0.378094,-0.147323,-0.91397,0.830643,0.2262,-0.720025, + 0.108083,0.116579,-0.987283,0.762033,0.287619,-0.735741, + 0.31991,-0.691022,-0.648187,0.867858,0.153664,-0.674188, + 0.65574,-0.380493,-0.652097,0.887817,0.175019,-0.672877, + 0.378094,-0.147323,-0.91397,0.830643,0.2262,-0.720025, + 0.31991,-0.691022,-0.648187,0.867858,0.153664,-0.674188, + 0.378094,-0.147323,-0.91397,0.830643,0.2262,-0.720025, + 0.024413,-0.469703,-0.882487,0.807717,0.204533,-0.722006, + -0.218035,0.735069,-0.641977,0.691977,0.424648,-0.664066, + -0.304611,0.675798,-0.6712,0.636249,0.400218,-0.672877, + -0.106617,0.392034,-0.913752,0.693423,0.349037,-0.720025, + -0.218035,0.735069,-0.641977,0.691977,0.424648,-0.664066, + -0.106617,0.392034,-0.913752,0.693423,0.349037,-0.720025, + -0.042916,0.448451,-0.892776,0.741552,0.375033,-0.708812, + -0.304611,0.675798,-0.6712,0.636249,0.400218,-0.672877, + -0.638487,0.393678,-0.661326,0.60431,0.378335,-0.674188, + -0.462569,0.070189,-0.8838,0.66406,0.327,-0.722006, + -0.462569,0.070189,-0.8838,0.66406,0.327,-0.722006, + -0.106617,0.392034,-0.913752,0.693423,0.349037,-0.720025, + -0.304611,0.675798,-0.6712,0.636249,0.400218,-0.672877, + -0.233968,-0.2359,-0.943191,0.735693,0.265534,-0.73806, + 0.108083,0.116579,-0.987283,0.762033,0.287619,-0.735741, + -0.106617,0.392034,-0.913752,0.693423,0.349037,-0.720025, + -0.233968,-0.2359,-0.943191,0.735693,0.265534,-0.73806, + -0.106617,0.392034,-0.913752,0.693423,0.349037,-0.720025, + -0.462569,0.070189,-0.8838,0.66406,0.327,-0.722006, + 0.108083,0.116579,-0.987283,0.762033,0.287619,-0.735741, + 0.160738,0.160922,-0.97379,0.801042,0.315496,-0.723727, + -0.042916,0.448451,-0.892776,0.741552,0.375033,-0.708812, + -0.042916,0.448451,-0.892776,0.741552,0.375033,-0.708812, + -0.106617,0.392034,-0.913752,0.693423,0.349037,-0.720025, + 0.108083,0.116579,-0.987283,0.762033,0.287619,-0.735741, + -0.838454,-0.308168,-0.449475,0.597724,0.354488,-0.660875, + -0.772673,-0.608887,-0.179534,0.608078,0.332278,-0.638667, + -0.712429,-0.672822,-0.199386,0.648221,0.292739,-0.664625, + -0.712429,-0.672822,-0.199386,0.648221,0.292739,-0.664625, + -0.660431,-0.496512,-0.563299,0.653151,0.306393,-0.706, + -0.838454,-0.308168,-0.449475,0.597724,0.354488,-0.660875, + -0.635534,-0.736296,-0.232302,0.709997,0.238013,-0.677562, + -0.531095,-0.656282,-0.53594,0.719399,0.249218,-0.7215, + -0.660431,-0.496512,-0.563299,0.653151,0.306393,-0.706, + -0.635534,-0.736296,-0.232302,0.709997,0.238013,-0.677562, + -0.660431,-0.496512,-0.563299,0.653151,0.306393,-0.706, + -0.712429,-0.672822,-0.199386,0.648221,0.292739,-0.664625, + -0.233968,-0.2359,-0.943191,0.735693,0.265534,-0.73806, + -0.462569,0.070189,-0.8838,0.66406,0.327,-0.722006, + -0.660431,-0.496512,-0.563299,0.653151,0.306393,-0.706, + -0.233968,-0.2359,-0.943191,0.735693,0.265534,-0.73806, + -0.660431,-0.496512,-0.563299,0.653151,0.306393,-0.706, + -0.531095,-0.656282,-0.53594,0.719399,0.249218,-0.7215, + -0.462569,0.070189,-0.8838,0.66406,0.327,-0.722006, + -0.638487,0.393678,-0.661326,0.60431,0.378335,-0.674188, + -0.838454,-0.308168,-0.449475,0.597724,0.354488,-0.660875, + -0.838454,-0.308168,-0.449475,0.597724,0.354488,-0.660875, + -0.660431,-0.496512,-0.563299,0.653151,0.306393,-0.706, + -0.462569,0.070189,-0.8838,0.66406,0.327,-0.722006, + -0.464025,-0.863104,-0.199329,0.820528,0.154011,-0.638667, + -0.23383,-0.86988,-0.434318,0.844199,0.147671,-0.660875, + -0.376394,-0.756788,-0.534415,0.787209,0.193905,-0.706, + -0.464025,-0.863104,-0.199329,0.820528,0.154011,-0.638667, + -0.376394,-0.756788,-0.534415,0.787209,0.193905,-0.706, + -0.552608,-0.806562,-0.209959,0.774619,0.186679,-0.664625, + -0.23383,-0.86988,-0.434318,0.844199,0.147671,-0.660875, + 0.31991,-0.691022,-0.648187,0.867858,0.153664,-0.674188, + 0.024413,-0.469703,-0.882487,0.807717,0.204533,-0.722006, + 0.024413,-0.469703,-0.882487,0.807717,0.204533,-0.722006, + -0.376394,-0.756788,-0.534415,0.787209,0.193905,-0.706, + -0.23383,-0.86988,-0.434318,0.844199,0.147671,-0.660875, + -0.233968,-0.2359,-0.943191,0.735693,0.265534,-0.73806, + -0.531095,-0.656282,-0.53594,0.719399,0.249218,-0.7215, + -0.376394,-0.756788,-0.534415,0.787209,0.193905,-0.706, + -0.233968,-0.2359,-0.943191,0.735693,0.265534,-0.73806, + -0.376394,-0.756788,-0.534415,0.787209,0.193905,-0.706, + 0.024413,-0.469703,-0.882487,0.807717,0.204533,-0.722006, + -0.531095,-0.656282,-0.53594,0.719399,0.249218,-0.7215, + -0.635534,-0.736296,-0.232302,0.709997,0.238013,-0.677562, + -0.552608,-0.806562,-0.209959,0.774619,0.186679,-0.664625, + -0.552608,-0.806562,-0.209959,0.774619,0.186679,-0.664625, + -0.376394,-0.756788,-0.534415,0.787209,0.193905,-0.706, + -0.531095,-0.656282,-0.53594,0.719399,0.249218,-0.7215, + -0.304611,0.675798,-0.6712,0.636249,0.400218,-0.672877, + -0.218035,0.735069,-0.641977,0.691977,0.424648,-0.664066, + -0.31842,0.898971,-0.300764,0.662233,0.454417,-0.589491, + -0.31842,0.898971,-0.300764,0.662233,0.454417,-0.589491, + -0.419827,0.848984,-0.320893,0.601944,0.430927,-0.594296, + -0.304611,0.675798,-0.6712,0.636249,0.400218,-0.672877, + -0.346116,0.938192,0,0.652318,0.46434,-0.5, + -0.477849,0.878442,0,0.590509,0.441164,-0.5, + -0.419827,0.848984,-0.320893,0.601944,0.430927,-0.594296, + -0.346116,0.938192,0,0.652318,0.46434,-0.5, + -0.419827,0.848984,-0.320893,0.601944,0.430927,-0.594296, + -0.31842,0.898971,-0.300764,0.662233,0.454417,-0.589491, + -0.477849,0.878442,0,0.590509,0.441164,-0.5, + -0.89858,0.43881,0,0.555594,0.41906,-0.5, + -0.801359,0.491779,-0.340556,0.567937,0.40894,-0.594949, + -0.801359,0.491779,-0.340556,0.567937,0.40894,-0.594949, + -0.419827,0.848984,-0.320893,0.601944,0.430927,-0.594296, + -0.477849,0.878442,0,0.590509,0.441164,-0.5, + -0.638487,0.393678,-0.661326,0.60431,0.378335,-0.674188, + -0.304611,0.675798,-0.6712,0.636249,0.400218,-0.672877, + -0.419827,0.848984,-0.320893,0.601944,0.430927,-0.594296, + -0.638487,0.393678,-0.661326,0.60431,0.378335,-0.674188, + -0.419827,0.848984,-0.320893,0.601944,0.430927,-0.594296, + -0.801359,0.491779,-0.340556,0.567937,0.40894,-0.594949, + -0.318419,0.898972,0.300764,0.662233,0.454417,-0.410509, + -0.218035,0.735069,0.641977,0.691977,0.424648,-0.335934, + -0.304611,0.675798,0.6712,0.636249,0.400218,-0.327123, + -0.304611,0.675798,0.6712,0.636249,0.400218,-0.327123, + -0.419827,0.848984,0.320893,0.601944,0.430927,-0.405704, + -0.318419,0.898972,0.300764,0.662233,0.454417,-0.410509, + -0.638487,0.393678,0.661326,0.60431,0.378335,-0.325812, + -0.801358,0.491779,0.340556,0.567937,0.40894,-0.405051, + -0.419827,0.848984,0.320893,0.601944,0.430927,-0.405704, + -0.638487,0.393678,0.661326,0.60431,0.378335,-0.325812, + -0.419827,0.848984,0.320893,0.601944,0.430927,-0.405704, + -0.304611,0.675798,0.6712,0.636249,0.400218,-0.327123, + -0.801358,0.491779,0.340556,0.567937,0.40894,-0.405051, + -0.89858,0.43881,0,0.555594,0.41906,-0.5, + -0.477849,0.878442,0,0.590509,0.441164,-0.5, + -0.477849,0.878442,0,0.590509,0.441164,-0.5, + -0.419827,0.848984,0.320893,0.601944,0.430927,-0.405704, + -0.801358,0.491779,0.340556,0.567937,0.40894,-0.405051, + -0.346116,0.938192,0,0.652318,0.46434,-0.5, + -0.318419,0.898972,0.300764,0.662233,0.454417,-0.410509, + -0.419827,0.848984,0.320893,0.601944,0.430927,-0.405704, + -0.346116,0.938192,0,0.652318,0.46434,-0.5, + -0.419827,0.848984,0.320893,0.601944,0.430927,-0.405704, + -0.477849,0.878442,0,0.590509,0.441164,-0.5, + -0.772673,-0.608887,0.179534,0.608078,0.332278,-0.361333, + -0.772268,-0.627334,0.100277,0.58531,0.345528,-0.4175, + -0.944453,-0.263136,0.196897,0.562375,0.382563,-0.4125, + -0.772673,-0.608887,0.179534,0.608078,0.332278,-0.361333, + -0.944453,-0.263136,0.196897,0.562375,0.382563,-0.4125, + -0.838454,-0.308168,0.449475,0.597724,0.354488,-0.339125, + -0.810611,-0.585585,0,0.573976,0.352148,-0.5, + -0.985168,-0.171594,0,0.54972,0.391595,-0.5, + -0.944453,-0.263136,0.196897,0.562375,0.382563,-0.4125, + -0.810611,-0.585585,0,0.573976,0.352148,-0.5, + -0.944453,-0.263136,0.196897,0.562375,0.382563,-0.4125, + -0.772268,-0.627334,0.100277,0.58531,0.345528,-0.4175, + -0.89858,0.43881,0,0.555594,0.41906,-0.5, + -0.801358,0.491779,0.340556,0.567937,0.40894,-0.405051, + -0.944453,-0.263136,0.196897,0.562375,0.382563,-0.4125, + -0.89858,0.43881,0,0.555594,0.41906,-0.5, + -0.944453,-0.263136,0.196897,0.562375,0.382563,-0.4125, + -0.985168,-0.171594,0,0.54972,0.391595,-0.5, + -0.801358,0.491779,0.340556,0.567937,0.40894,-0.405051, + -0.638487,0.393678,0.661326,0.60431,0.378335,-0.325812, + -0.838454,-0.308168,0.449475,0.597724,0.354488,-0.339125, + -0.838454,-0.308168,0.449475,0.597724,0.354488,-0.339125, + -0.944453,-0.263136,0.196897,0.562375,0.382563,-0.4125, + -0.801358,0.491779,0.340556,0.567937,0.40894,-0.405051, + -0.772673,-0.608887,-0.179534,0.608078,0.332278,-0.638667, + -0.838454,-0.308168,-0.449475,0.597724,0.354488,-0.660875, + -0.944453,-0.263136,-0.196896,0.562375,0.382563,-0.5875, + -0.772673,-0.608887,-0.179534,0.608078,0.332278,-0.638667, + -0.944453,-0.263136,-0.196896,0.562375,0.382563,-0.5875, + -0.772268,-0.627334,-0.100277,0.58531,0.345528,-0.5825, + -0.838454,-0.308168,-0.449475,0.597724,0.354488,-0.660875, + -0.638487,0.393678,-0.661326,0.60431,0.378335,-0.674188, + -0.801359,0.491779,-0.340556,0.567937,0.40894,-0.594949, + -0.801359,0.491779,-0.340556,0.567937,0.40894,-0.594949, + -0.944453,-0.263136,-0.196896,0.562375,0.382563,-0.5875, + -0.838454,-0.308168,-0.449475,0.597724,0.354488,-0.660875, + -0.89858,0.43881,0,0.555594,0.41906,-0.5, + -0.985168,-0.171594,0,0.54972,0.391595,-0.5, + -0.944453,-0.263136,-0.196896,0.562375,0.382563,-0.5875, + -0.89858,0.43881,0,0.555594,0.41906,-0.5, + -0.944453,-0.263136,-0.196896,0.562375,0.382563,-0.5875, + -0.801359,0.491779,-0.340556,0.567937,0.40894,-0.594949, + -0.810611,-0.585585,0,0.573976,0.352148,-0.5, + -0.772268,-0.627334,-0.100277,0.58531,0.345528,-0.5825, + -0.944453,-0.263136,-0.196896,0.562375,0.382563,-0.5875, + -0.810611,-0.585585,0,0.573976,0.352148,-0.5, + -0.944453,-0.263136,-0.196896,0.562375,0.382563,-0.5875, + -0.985168,-0.171594,0,0.54972,0.391595,-0.5, + -0.218035,0.735069,0.641977,0.691977,0.424648,-0.335934, + -0.042916,0.448451,0.892776,0.741552,0.375033,-0.291188, + -0.106617,0.392034,0.913752,0.693423,0.349037,-0.279975, + -0.218035,0.735069,0.641977,0.691977,0.424648,-0.335934, + -0.106617,0.392034,0.913752,0.693423,0.349037,-0.279975, + -0.304611,0.675798,0.6712,0.636249,0.400218,-0.327123, + -0.042916,0.448451,0.892776,0.741552,0.375033,-0.291188, + 0.160738,0.160922,0.97379,0.801042,0.315496,-0.276273, + 0.108083,0.116579,0.987283,0.762033,0.287619,-0.264259, + 0.108083,0.116579,0.987283,0.762033,0.287619,-0.264259, + -0.106617,0.392034,0.913752,0.693423,0.349037,-0.279975, + -0.042916,0.448451,0.892776,0.741552,0.375033,-0.291188, + -0.233968,-0.2359,0.943191,0.735693,0.265534,-0.26194, + -0.462569,0.07019,0.883801,0.66406,0.327,-0.277994, + -0.106617,0.392034,0.913752,0.693423,0.349037,-0.279975, + -0.233968,-0.2359,0.943191,0.735693,0.265534,-0.26194, + -0.106617,0.392034,0.913752,0.693423,0.349037,-0.279975, + 0.108083,0.116579,0.987283,0.762033,0.287619,-0.264259, + -0.462569,0.07019,0.883801,0.66406,0.327,-0.277994, + -0.638487,0.393678,0.661326,0.60431,0.378335,-0.325812, + -0.304611,0.675798,0.6712,0.636249,0.400218,-0.327123, + -0.304611,0.675798,0.6712,0.636249,0.400218,-0.327123, + -0.106617,0.392034,0.913752,0.693423,0.349037,-0.279975, + -0.462569,0.07019,0.883801,0.66406,0.327,-0.277994, + 0.66282,-0.338306,0.667996,0.910107,0.206343,-0.335934, + 0.65574,-0.380493,0.652097,0.887817,0.175019,-0.327123, + 0.378094,-0.147323,0.91397,0.830643,0.2262,-0.279975, + 0.66282,-0.338306,0.667996,0.910107,0.206343,-0.335934, + 0.378094,-0.147323,0.91397,0.830643,0.2262,-0.279975, + 0.398283,-0.122544,0.90904,0.860532,0.255958,-0.291188, + 0.31991,-0.691022,0.648187,0.867858,0.153664,-0.325812, + 0.024414,-0.469703,0.882487,0.807717,0.204533,-0.277994, + 0.378094,-0.147323,0.91397,0.830643,0.2262,-0.279975, + 0.31991,-0.691022,0.648187,0.867858,0.153664,-0.325812, + 0.378094,-0.147323,0.91397,0.830643,0.2262,-0.279975, + 0.65574,-0.380493,0.652097,0.887817,0.175019,-0.327123, + 0.024414,-0.469703,0.882487,0.807717,0.204533,-0.277994, + -0.233968,-0.2359,0.943191,0.735693,0.265534,-0.26194, + 0.108083,0.116579,0.987283,0.762033,0.287619,-0.264259, + 0.108083,0.116579,0.987283,0.762033,0.287619,-0.264259, + 0.378094,-0.147323,0.91397,0.830643,0.2262,-0.279975, + 0.024414,-0.469703,0.882487,0.807717,0.204533,-0.277994, + 0.160738,0.160922,0.97379,0.801042,0.315496,-0.276273, + 0.398283,-0.122544,0.90904,0.860532,0.255958,-0.291188, + 0.378094,-0.147323,0.91397,0.830643,0.2262,-0.279975, + 0.160738,0.160922,0.97379,0.801042,0.315496,-0.276273, + 0.378094,-0.147323,0.91397,0.830643,0.2262,-0.279975, + 0.108083,0.116579,0.987283,0.762033,0.287619,-0.264259, + -0.464025,-0.863104,0.199329,0.820528,0.154011,-0.361333, + -0.552608,-0.806562,0.209959,0.774619,0.186679,-0.335375, + -0.376394,-0.756788,0.534415,0.787209,0.193905,-0.294, + -0.464025,-0.863104,0.199329,0.820528,0.154011,-0.361333, + -0.376394,-0.756788,0.534415,0.787209,0.193905,-0.294, + -0.23383,-0.86988,0.434318,0.844199,0.147671,-0.339125, + -0.552608,-0.806562,0.209959,0.774619,0.186679,-0.335375, + -0.635534,-0.736296,0.232302,0.709997,0.238013,-0.322437, + -0.531095,-0.656282,0.53594,0.719399,0.249218,-0.2785, + -0.531095,-0.656282,0.53594,0.719399,0.249218,-0.2785, + -0.376394,-0.756788,0.534415,0.787209,0.193905,-0.294, + -0.552608,-0.806562,0.209959,0.774619,0.186679,-0.335375, + -0.233968,-0.2359,0.943191,0.735693,0.265534,-0.26194, + 0.024414,-0.469703,0.882487,0.807717,0.204533,-0.277994, + -0.376394,-0.756788,0.534415,0.787209,0.193905,-0.294, + -0.233968,-0.2359,0.943191,0.735693,0.265534,-0.26194, + -0.376394,-0.756788,0.534415,0.787209,0.193905,-0.294, + -0.531095,-0.656282,0.53594,0.719399,0.249218,-0.2785, + 0.024414,-0.469703,0.882487,0.807717,0.204533,-0.277994, + 0.31991,-0.691022,0.648187,0.867858,0.153664,-0.325812, + -0.23383,-0.86988,0.434318,0.844199,0.147671,-0.339125, + -0.23383,-0.86988,0.434318,0.844199,0.147671,-0.339125, + -0.376394,-0.756788,0.534415,0.787209,0.193905,-0.294, + 0.024414,-0.469703,0.882487,0.807717,0.204533,-0.277994, + -0.712429,-0.672822,0.199385,0.648221,0.292739,-0.335375, + -0.772673,-0.608887,0.179534,0.608078,0.332278,-0.361333, + -0.838454,-0.308168,0.449475,0.597724,0.354488,-0.339125, + -0.838454,-0.308168,0.449475,0.597724,0.354488,-0.339125, + -0.660431,-0.496512,0.5633,0.653151,0.306393,-0.294, + -0.712429,-0.672822,0.199385,0.648221,0.292739,-0.335375, + -0.838454,-0.308168,0.449475,0.597724,0.354488,-0.339125, + -0.638487,0.393678,0.661326,0.60431,0.378335,-0.325812, + -0.462569,0.07019,0.883801,0.66406,0.327,-0.277994, + -0.462569,0.07019,0.883801,0.66406,0.327,-0.277994, + -0.660431,-0.496512,0.5633,0.653151,0.306393,-0.294, + -0.838454,-0.308168,0.449475,0.597724,0.354488,-0.339125, + -0.233968,-0.2359,0.943191,0.735693,0.265534,-0.26194, + -0.531095,-0.656282,0.53594,0.719399,0.249218,-0.2785, + -0.660431,-0.496512,0.5633,0.653151,0.306393,-0.294, + -0.233968,-0.2359,0.943191,0.735693,0.265534,-0.26194, + -0.660431,-0.496512,0.5633,0.653151,0.306393,-0.294, + -0.462569,0.07019,0.883801,0.66406,0.327,-0.277994, + -0.635534,-0.736296,0.232302,0.709997,0.238013,-0.322437, + -0.712429,-0.672822,0.199385,0.648221,0.292739,-0.335375, + -0.660431,-0.496512,0.5633,0.653151,0.306393,-0.294, + -0.635534,-0.736296,0.232302,0.709997,0.238013,-0.322437, + -0.660431,-0.496512,0.5633,0.653151,0.306393,-0.294, + -0.531095,-0.656282,0.53594,0.719399,0.249218,-0.2785, + -0.464025,-0.863104,-0.199329,0.820528,0.154011,-0.638667, + -0.552608,-0.806562,-0.209959,0.774619,0.186679,-0.664625, + -0.577604,-0.812413,-0.079739,0.775446,0.175219,-0.5905, + -0.464025,-0.863104,-0.199329,0.820528,0.154011,-0.638667, + -0.577604,-0.812413,-0.079739,0.775446,0.175219,-0.5905, + -0.4837,-0.869471,-0.100277,0.83753,0.13389,-0.5825, + -0.552608,-0.806562,-0.209959,0.774619,0.186679,-0.664625, + -0.635534,-0.736296,-0.232302,0.709997,0.238013,-0.677562, + -0.640463,-0.763275,-0.08496,0.704334,0.231264,-0.59775, + -0.640463,-0.763275,-0.08496,0.704334,0.231264,-0.59775, + -0.577604,-0.812413,-0.079739,0.775446,0.175219,-0.5905, + -0.552608,-0.806562,-0.209959,0.774619,0.186679,-0.664625, + -0.642787,-0.766045,0,0.702437,0.229003,-0.5, + -0.57538,-0.817886,0,0.779215,0.168431,-0.5, + -0.577604,-0.812413,-0.079739,0.775446,0.175219,-0.5905, + -0.642787,-0.766045,0,0.702437,0.229003,-0.5, + -0.577604,-0.812413,-0.079739,0.775446,0.175219,-0.5905, + -0.640463,-0.763275,-0.08496,0.704334,0.231264,-0.59775, + -0.57538,-0.817886,0,0.779215,0.168431,-0.5, + -0.435927,-0.899982,0,0.846018,0.123878,-0.5, + -0.4837,-0.869471,-0.100277,0.83753,0.13389,-0.5825, + -0.4837,-0.869471,-0.100277,0.83753,0.13389,-0.5825, + -0.577604,-0.812413,-0.079739,0.775446,0.175219,-0.5905, + -0.57538,-0.817886,0,0.779215,0.168431,-0.5, + -0.772673,-0.608887,-0.179534,0.608078,0.332278,-0.638667, + -0.772268,-0.627334,-0.100277,0.58531,0.345528,-0.5825, + -0.699771,-0.709903,-0.079739,0.636792,0.291564,-0.5905, + -0.772673,-0.608887,-0.179534,0.608078,0.332278,-0.638667, + -0.699771,-0.709903,-0.079739,0.636792,0.291564,-0.5905, + -0.712429,-0.672822,-0.199386,0.648221,0.292739,-0.664625, + -0.772268,-0.627334,-0.100277,0.58531,0.345528,-0.5825, + -0.810611,-0.585585,0,0.573976,0.352148,-0.5, + -0.705547,-0.708663,0,0.629453,0.294096,-0.5, + -0.705547,-0.708663,0,0.629453,0.294096,-0.5, + -0.699771,-0.709903,-0.079739,0.636792,0.291564,-0.5905, + -0.772268,-0.627334,-0.100277,0.58531,0.345528,-0.5825, + -0.642787,-0.766045,0,0.702437,0.229003,-0.5, + -0.640463,-0.763275,-0.08496,0.704334,0.231264,-0.59775, + -0.699771,-0.709903,-0.079739,0.636792,0.291564,-0.5905, + -0.642787,-0.766045,0,0.702437,0.229003,-0.5, + -0.699771,-0.709903,-0.079739,0.636792,0.291564,-0.5905, + -0.705547,-0.708663,0,0.629453,0.294096,-0.5, + -0.640463,-0.763275,-0.08496,0.704334,0.231264,-0.59775, + -0.635534,-0.736296,-0.232302,0.709997,0.238013,-0.677562, + -0.712429,-0.672822,-0.199386,0.648221,0.292739,-0.664625, + -0.712429,-0.672822,-0.199386,0.648221,0.292739,-0.664625, + -0.699771,-0.709903,-0.079739,0.636792,0.291564,-0.5905, + -0.640463,-0.763275,-0.08496,0.704334,0.231264,-0.59775, + -0.772673,-0.608887,0.179534,0.608078,0.332278,-0.361333, + -0.712429,-0.672822,0.199385,0.648221,0.292739,-0.335375, + -0.699771,-0.709903,0.079739,0.636792,0.291564,-0.4095, + -0.772673,-0.608887,0.179534,0.608078,0.332278,-0.361333, + -0.699771,-0.709903,0.079739,0.636792,0.291564,-0.4095, + -0.772268,-0.627334,0.100277,0.58531,0.345528,-0.4175, + -0.712429,-0.672822,0.199385,0.648221,0.292739,-0.335375, + -0.635534,-0.736296,0.232302,0.709997,0.238013,-0.322437, + -0.640463,-0.763275,0.08496,0.704334,0.231264,-0.40225, + -0.640463,-0.763275,0.08496,0.704334,0.231264,-0.40225, + -0.699771,-0.709903,0.079739,0.636792,0.291564,-0.4095, + -0.712429,-0.672822,0.199385,0.648221,0.292739,-0.335375, + -0.642787,-0.766045,0,0.702437,0.229003,-0.5, + -0.705547,-0.708663,0,0.629453,0.294096,-0.5, + -0.699771,-0.709903,0.079739,0.636792,0.291564,-0.4095, + -0.642787,-0.766045,0,0.702437,0.229003,-0.5, + -0.699771,-0.709903,0.079739,0.636792,0.291564,-0.4095, + -0.640463,-0.763275,0.08496,0.704334,0.231264,-0.40225, + -0.705547,-0.708663,0,0.629453,0.294096,-0.5, + -0.810611,-0.585585,0,0.573976,0.352148,-0.5, + -0.772268,-0.627334,0.100277,0.58531,0.345528,-0.4175, + -0.772268,-0.627334,0.100277,0.58531,0.345528,-0.4175, + -0.699771,-0.709903,0.079739,0.636792,0.291564,-0.4095, + -0.705547,-0.708663,0,0.629453,0.294096,-0.5, + -0.464025,-0.863104,0.199329,0.820528,0.154011,-0.361333, + -0.4837,-0.869471,0.100277,0.83753,0.13389,-0.4175, + -0.577604,-0.812413,0.079739,0.775446,0.175219,-0.4095, + -0.464025,-0.863104,0.199329,0.820528,0.154011,-0.361333, + -0.577604,-0.812413,0.079739,0.775446,0.175219,-0.4095, + -0.552608,-0.806562,0.209959,0.774619,0.186679,-0.335375, + -0.4837,-0.869471,0.100277,0.83753,0.13389,-0.4175, + -0.435927,-0.899982,0,0.846018,0.123878,-0.5, + -0.57538,-0.817886,0,0.779215,0.168431,-0.5, + -0.57538,-0.817886,0,0.779215,0.168431,-0.5, + -0.577604,-0.812413,0.079739,0.775446,0.175219,-0.4095, + -0.4837,-0.869471,0.100277,0.83753,0.13389,-0.4175, + -0.642787,-0.766045,0,0.702437,0.229003,-0.5, + -0.640463,-0.763275,0.08496,0.704334,0.231264,-0.40225, + -0.577604,-0.812413,0.079739,0.775446,0.175219,-0.4095, + -0.642787,-0.766045,0,0.702437,0.229003,-0.5, + -0.577604,-0.812413,0.079739,0.775446,0.175219,-0.4095, + -0.57538,-0.817886,0,0.779215,0.168431,-0.5, + -0.640463,-0.763275,0.08496,0.704334,0.231264,-0.40225, + -0.635534,-0.736296,0.232302,0.709997,0.238013,-0.322437, + -0.552608,-0.806562,0.209959,0.774619,0.186679,-0.335375, + -0.552608,-0.806562,0.209959,0.774619,0.186679,-0.335375, + -0.577604,-0.812413,0.079739,0.775446,0.175219,-0.4095, + -0.640463,-0.763275,0.08496,0.704334,0.231264,-0.40225, +}; +static const struct gllist frame={GL_N3F_V3F,GL_TRIANGLES,1728,data,NULL}; +const struct gllist *s1_4=&frame; diff --git a/hacks/glx/s1_5.c b/hacks/glx/s1_5.c new file mode 100644 index 00000000..dc4510a5 --- /dev/null +++ b/hacks/glx/s1_5.c @@ -0,0 +1,1733 @@ +#include "gllist.h" +static const float data[]={ + 0.575185,0.562873,-0.59358,0.995497,0.593044,-0.659921, + 0.642358,0.715039,-0.275852,0.998334,0.63557,-0.58723, + 0.5309,0.794781,-0.294055,0.944384,0.679375,-0.593392, + 0.575185,0.562873,-0.59358,0.995497,0.593044,-0.659921, + 0.5309,0.794781,-0.294055,0.944384,0.679375,-0.593392, + 0.429706,0.63213,-0.644798,0.943249,0.633115,-0.671218, + 0.642358,0.715039,-0.275852,0.998334,0.63557,-0.58723, + 0.662437,0.749118,0,0.99928,0.649745,-0.5, + 0.577305,0.816529,0,0.944762,0.694795,-0.5, + 0.577305,0.816529,0,0.944762,0.694795,-0.5, + 0.5309,0.794781,-0.294055,0.944384,0.679375,-0.593392, + 0.642358,0.715039,-0.275852,0.998334,0.63557,-0.58723, + 0.007037,0.999975,0,0.906869,0.713633,-0.5, + -0.039712,0.912418,-0.407328,0.907078,0.697653,-0.594723, + 0.5309,0.794781,-0.294055,0.944384,0.679375,-0.593392, + 0.007037,0.999975,0,0.906869,0.713633,-0.5, + 0.5309,0.794781,-0.294055,0.944384,0.679375,-0.593392, + 0.577305,0.816529,0,0.944762,0.694795,-0.5, + -0.039712,0.912418,-0.407328,0.907078,0.697653,-0.594723, + -0.115437,0.702917,-0.701842,0.907098,0.650057,-0.673773, + 0.429706,0.63213,-0.644798,0.943249,0.633115,-0.671218, + 0.429706,0.63213,-0.644798,0.943249,0.633115,-0.671218, + 0.5309,0.794781,-0.294055,0.944384,0.679375,-0.593392, + -0.039712,0.912418,-0.407328,0.907078,0.697653,-0.594723, + 0.575185,0.562873,0.59358,0.995497,0.593044,-0.340079, + 0.429706,0.63213,0.644797,0.943249,0.633115,-0.328782, + 0.530901,0.79478,0.294055,0.944384,0.679375,-0.406608, + 0.575185,0.562873,0.59358,0.995497,0.593044,-0.340079, + 0.530901,0.79478,0.294055,0.944384,0.679375,-0.406608, + 0.642358,0.715039,0.275852,0.998334,0.63557,-0.41277, + 0.429706,0.63213,0.644797,0.943249,0.633115,-0.328782, + -0.115435,0.702917,0.701842,0.907098,0.650057,-0.326227, + -0.039712,0.912418,0.407328,0.907078,0.697653,-0.405277, + -0.039712,0.912418,0.407328,0.907078,0.697653,-0.405277, + 0.530901,0.79478,0.294055,0.944384,0.679375,-0.406608, + 0.429706,0.63213,0.644797,0.943249,0.633115,-0.328782, + 0.007037,0.999975,0,0.906869,0.713633,-0.5, + 0.577305,0.816529,0,0.944762,0.694795,-0.5, + 0.530901,0.79478,0.294055,0.944384,0.679375,-0.406608, + 0.007037,0.999975,0,0.906869,0.713633,-0.5, + 0.530901,0.79478,0.294055,0.944384,0.679375,-0.406608, + -0.039712,0.912418,0.407328,0.907078,0.697653,-0.405277, + 0.577305,0.816529,0,0.944762,0.694795,-0.5, + 0.662437,0.749118,0,0.99928,0.649745,-0.5, + 0.642358,0.715039,0.275852,0.998334,0.63557,-0.41277, + 0.642358,0.715039,0.275852,0.998334,0.63557,-0.41277, + 0.530901,0.79478,0.294055,0.944384,0.679375,-0.406608, + 0.577305,0.816529,0,0.944762,0.694795,-0.5, + -0.959446,0.199329,0.199329,0.87462,0.619745,-0.361333, + -0.976969,0.188349,0.100277,0.870135,0.645704,-0.4175, + -0.794244,0.572801,0.20267,0.883764,0.687079,-0.4125, + -0.959446,0.199329,0.199329,0.87462,0.619745,-0.361333, + -0.794244,0.572801,0.20267,0.883764,0.687079,-0.4125, + -0.714284,0.497638,0.492092,0.884979,0.641954,-0.339125, + -0.969635,0.244558,0,0.867922,0.658641,-0.5, + -0.744977,0.66709,0,0.882548,0.702579,-0.5, + -0.794244,0.572801,0.20267,0.883764,0.687079,-0.4125, + -0.969635,0.244558,0,0.867922,0.658641,-0.5, + -0.794244,0.572801,0.20267,0.883764,0.687079,-0.4125, + -0.976969,0.188349,0.100277,0.870135,0.645704,-0.4175, + 0.007037,0.999975,0,0.906869,0.713633,-0.5, + -0.039712,0.912418,0.407328,0.907078,0.697653,-0.405277, + -0.794244,0.572801,0.20267,0.883764,0.687079,-0.4125, + 0.007037,0.999975,0,0.906869,0.713633,-0.5, + -0.794244,0.572801,0.20267,0.883764,0.687079,-0.4125, + -0.744977,0.66709,0,0.882548,0.702579,-0.5, + -0.039712,0.912418,0.407328,0.907078,0.697653,-0.405277, + -0.115435,0.702917,0.701842,0.907098,0.650057,-0.326227, + -0.714284,0.497638,0.492092,0.884979,0.641954,-0.339125, + -0.714284,0.497638,0.492092,0.884979,0.641954,-0.339125, + -0.794244,0.572801,0.20267,0.883764,0.687079,-0.4125, + -0.039712,0.912418,0.407328,0.907078,0.697653,-0.405277, + -0.959446,0.199329,-0.199329,0.87462,0.619745,-0.638667, + -0.714284,0.497638,-0.492092,0.884979,0.641954,-0.660875, + -0.794244,0.572801,-0.202671,0.883764,0.687079,-0.5875, + -0.959446,0.199329,-0.199329,0.87462,0.619745,-0.638667, + -0.794244,0.572801,-0.202671,0.883764,0.687079,-0.5875, + -0.976969,0.188349,-0.100277,0.870135,0.645704,-0.5825, + -0.714284,0.497638,-0.492092,0.884979,0.641954,-0.660875, + -0.115437,0.702917,-0.701842,0.907098,0.650057,-0.673773, + -0.039712,0.912418,-0.407328,0.907078,0.697653,-0.594723, + -0.039712,0.912418,-0.407328,0.907078,0.697653,-0.594723, + -0.794244,0.572801,-0.202671,0.883764,0.687079,-0.5875, + -0.714284,0.497638,-0.492092,0.884979,0.641954,-0.660875, + 0.007037,0.999975,0,0.906869,0.713633,-0.5, + -0.744977,0.66709,0,0.882548,0.702579,-0.5, + -0.794244,0.572801,-0.202671,0.883764,0.687079,-0.5875, + 0.007037,0.999975,0,0.906869,0.713633,-0.5, + -0.794244,0.572801,-0.202671,0.883764,0.687079,-0.5875, + -0.039712,0.912418,-0.407328,0.907078,0.697653,-0.594723, + -0.969635,0.244558,0,0.867922,0.658641,-0.5, + -0.976969,0.188349,-0.100277,0.870135,0.645704,-0.5825, + -0.794244,0.572801,-0.202671,0.883764,0.687079,-0.5875, + -0.969635,0.244558,0,0.867922,0.658641,-0.5, + -0.794244,0.572801,-0.202671,0.883764,0.687079,-0.5875, + -0.744977,0.66709,0,0.882548,0.702579,-0.5, + 0.575185,0.562873,0.59358,0.995497,0.593044,-0.340079, + 0.447221,0.281892,0.848841,0.990769,0.522168,-0.296464, + 0.345209,0.311815,0.885213,0.941357,0.556014,-0.282086, + 0.575185,0.562873,0.59358,0.995497,0.593044,-0.340079, + 0.345209,0.311815,0.885213,0.941357,0.556014,-0.282086, + 0.429706,0.63213,0.644797,0.943249,0.633115,-0.328782, + 0.447221,0.281892,0.848841,0.990769,0.522168,-0.296464, + 0.291601,-0.024985,0.956214,0.985095,0.437116,-0.281926, + 0.214014,-0.011143,0.976767,0.939088,0.463494,-0.26652, + 0.214014,-0.011143,0.976767,0.939088,0.463494,-0.26652, + 0.345209,0.311815,0.885213,0.941357,0.556014,-0.282086, + 0.447221,0.281892,0.848841,0.990769,0.522168,-0.296464, + -0.247399,0.003968,0.968906,0.905451,0.476683,-0.262505, + -0.23409,0.368714,0.899584,0.906322,0.571188,-0.278521, + 0.345209,0.311815,0.885213,0.941357,0.556014,-0.282086, + -0.247399,0.003968,0.968906,0.905451,0.476683,-0.262505, + 0.345209,0.311815,0.885213,0.941357,0.556014,-0.282086, + 0.214014,-0.011143,0.976767,0.939088,0.463494,-0.26652, + -0.23409,0.368714,0.899584,0.906322,0.571188,-0.278521, + -0.115435,0.702917,0.701842,0.907098,0.650057,-0.326227, + 0.429706,0.63213,0.644797,0.943249,0.633115,-0.328782, + 0.429706,0.63213,0.644797,0.943249,0.633115,-0.328782, + 0.345209,0.311815,0.885213,0.941357,0.556014,-0.282086, + -0.23409,0.368714,0.899584,0.906322,0.571188,-0.278521, + 0.110573,-0.360361,0.926236,0.979421,0.352064,-0.296464, + -0.103837,-0.707557,0.698986,0.974692,0.281188,-0.340079, + -0.088988,-0.705766,0.702834,0.934927,0.293873,-0.328782, + -0.088988,-0.705766,0.702834,0.934927,0.293873,-0.328782, + 0.06872,-0.352527,0.933275,0.936818,0.370973,-0.282086, + 0.110573,-0.360361,0.926236,0.979421,0.352064,-0.296464, + -0.455383,-0.61687,0.641949,0.905018,0.303308,-0.326227, + -0.359172,-0.316853,0.877838,0.905187,0.382177,-0.278521, + 0.06872,-0.352527,0.933275,0.936818,0.370973,-0.282086, + -0.455383,-0.61687,0.641949,0.905018,0.303308,-0.326227, + 0.06872,-0.352527,0.933275,0.936818,0.370973,-0.282086, + -0.088988,-0.705766,0.702834,0.934927,0.293873,-0.328782, + -0.359172,-0.316853,0.877838,0.905187,0.382177,-0.278521, + -0.247399,0.003968,0.968906,0.905451,0.476683,-0.262505, + 0.214014,-0.011143,0.976767,0.939088,0.463494,-0.26652, + 0.214014,-0.011143,0.976767,0.939088,0.463494,-0.26652, + 0.06872,-0.352527,0.933275,0.936818,0.370973,-0.282086, + -0.359172,-0.316853,0.877838,0.905187,0.382177,-0.278521, + 0.291601,-0.024985,0.956214,0.985095,0.437116,-0.281926, + 0.110573,-0.360361,0.926236,0.979421,0.352064,-0.296464, + 0.06872,-0.352527,0.933275,0.936818,0.370973,-0.282086, + 0.291601,-0.024985,0.956214,0.985095,0.437116,-0.281926, + 0.06872,-0.352527,0.933275,0.936818,0.370973,-0.282086, + 0.214014,-0.011143,0.976767,0.939088,0.463494,-0.26652, + -0.959446,-0.199329,0.199329,0.87462,0.342412,-0.361333, + -0.976969,-0.100277,0.18835,0.870135,0.398579,-0.335375, + -0.845588,-0.179708,0.502679,0.883764,0.393579,-0.294, + -0.959446,-0.199329,0.199329,0.87462,0.342412,-0.361333, + -0.845588,-0.179708,0.502679,0.883764,0.393579,-0.294, + -0.826326,-0.370128,0.424489,0.884979,0.320204,-0.339125, + -0.969635,0,0.244558,0.867922,0.481079,-0.322437, + -0.761522,0.030964,0.647398,0.882548,0.481079,-0.2785, + -0.845588,-0.179708,0.502679,0.883764,0.393579,-0.294, + -0.969635,0,0.244558,0.867922,0.481079,-0.322437, + -0.845588,-0.179708,0.502679,0.883764,0.393579,-0.294, + -0.976969,-0.100277,0.18835,0.870135,0.398579,-0.335375, + -0.247399,0.003968,0.968906,0.905451,0.476683,-0.262505, + -0.359172,-0.316853,0.877838,0.905187,0.382177,-0.278521, + -0.845588,-0.179708,0.502679,0.883764,0.393579,-0.294, + -0.247399,0.003968,0.968906,0.905451,0.476683,-0.262505, + -0.845588,-0.179708,0.502679,0.883764,0.393579,-0.294, + -0.761522,0.030964,0.647398,0.882548,0.481079,-0.2785, + -0.359172,-0.316853,0.877838,0.905187,0.382177,-0.278521, + -0.455383,-0.61687,0.641949,0.905018,0.303308,-0.326227, + -0.826326,-0.370128,0.424489,0.884979,0.320204,-0.339125, + -0.826326,-0.370128,0.424489,0.884979,0.320204,-0.339125, + -0.845588,-0.179708,0.502679,0.883764,0.393579,-0.294, + -0.359172,-0.316853,0.877838,0.905187,0.382177,-0.278521, + -0.959446,0.199329,0.199329,0.87462,0.619745,-0.361333, + -0.714284,0.497638,0.492092,0.884979,0.641954,-0.339125, + -0.859317,0.197434,0.471799,0.883764,0.568579,-0.294, + -0.959446,0.199329,0.199329,0.87462,0.619745,-0.361333, + -0.859317,0.197434,0.471799,0.883764,0.568579,-0.294, + -0.976969,0.100277,0.18835,0.870135,0.563579,-0.335375, + -0.714284,0.497638,0.492092,0.884979,0.641954,-0.339125, + -0.115435,0.702917,0.701842,0.907098,0.650057,-0.326227, + -0.23409,0.368714,0.899584,0.906322,0.571188,-0.278521, + -0.23409,0.368714,0.899584,0.906322,0.571188,-0.278521, + -0.859317,0.197434,0.471799,0.883764,0.568579,-0.294, + -0.714284,0.497638,0.492092,0.884979,0.641954,-0.339125, + -0.23409,0.368714,0.899584,0.906322,0.571188,-0.278521, + -0.247399,0.003968,0.968906,0.905451,0.476683,-0.262505, + -0.761522,0.030964,0.647398,0.882548,0.481079,-0.2785, + -0.761522,0.030964,0.647398,0.882548,0.481079,-0.2785, + -0.859317,0.197434,0.471799,0.883764,0.568579,-0.294, + -0.23409,0.368714,0.899584,0.906322,0.571188,-0.278521, + -0.969635,0,0.244558,0.867922,0.481079,-0.322437, + -0.976969,0.100277,0.18835,0.870135,0.563579,-0.335375, + -0.859317,0.197434,0.471799,0.883764,0.568579,-0.294, + -0.969635,0,0.244558,0.867922,0.481079,-0.322437, + -0.859317,0.197434,0.471799,0.883764,0.568579,-0.294, + -0.761522,0.030964,0.647398,0.882548,0.481079,-0.2785, + -0.103837,-0.707557,0.698986,0.974692,0.281188,-0.340079, + -0.260846,-0.906261,0.332641,0.971855,0.238662,-0.41277, + -0.196471,-0.920135,0.338748,0.933792,0.247612,-0.406608, + -0.103837,-0.707557,0.698986,0.974692,0.281188,-0.340079, + -0.196471,-0.920135,0.338748,0.933792,0.247612,-0.406608, + -0.088988,-0.705766,0.702834,0.934927,0.293873,-0.328782, + -0.260846,-0.906261,0.332641,0.971855,0.238662,-0.41277, + -0.339022,-0.940778,0,0.97091,0.224487,-0.5, + -0.217971,-0.975955,0,0.933414,0.232192,-0.5, + -0.217971,-0.975955,0,0.933414,0.232192,-0.5, + -0.196471,-0.920135,0.338748,0.933792,0.247612,-0.406608, + -0.260846,-0.906261,0.332641,0.971855,0.238662,-0.41277, + -0.489368,-0.872077,0,0.904032,0.239732,-0.5, + -0.438574,-0.828046,0.349274,0.90443,0.255712,-0.405277, + -0.196471,-0.920135,0.338748,0.933792,0.247612,-0.406608, + -0.489368,-0.872077,0,0.904032,0.239732,-0.5, + -0.196471,-0.920135,0.338748,0.933792,0.247612,-0.406608, + -0.217971,-0.975955,0,0.933414,0.232192,-0.5, + -0.438574,-0.828046,0.349274,0.90443,0.255712,-0.405277, + -0.455383,-0.61687,0.641949,0.905018,0.303308,-0.326227, + -0.088988,-0.705766,0.702834,0.934927,0.293873,-0.328782, + -0.088988,-0.705766,0.702834,0.934927,0.293873,-0.328782, + -0.196471,-0.920135,0.338748,0.933792,0.247612,-0.406608, + -0.438574,-0.828046,0.349274,0.90443,0.255712,-0.405277, + -0.103837,-0.707557,-0.698986,0.974692,0.281188,-0.659921, + -0.088988,-0.705766,-0.702834,0.934927,0.293873,-0.671218, + -0.196471,-0.920135,-0.338748,0.933792,0.247612,-0.593392, + -0.103837,-0.707557,-0.698986,0.974692,0.281188,-0.659921, + -0.196471,-0.920135,-0.338748,0.933792,0.247612,-0.593392, + -0.260846,-0.906261,-0.332641,0.971855,0.238662,-0.58723, + -0.088988,-0.705766,-0.702834,0.934927,0.293873,-0.671218, + -0.455383,-0.61687,-0.641949,0.905018,0.303308,-0.673773, + -0.438575,-0.828046,-0.349274,0.90443,0.255712,-0.594723, + -0.438575,-0.828046,-0.349274,0.90443,0.255712,-0.594723, + -0.196471,-0.920135,-0.338748,0.933792,0.247612,-0.593392, + -0.088988,-0.705766,-0.702834,0.934927,0.293873,-0.671218, + -0.489368,-0.872077,0,0.904032,0.239732,-0.5, + -0.217971,-0.975955,0,0.933414,0.232192,-0.5, + -0.196471,-0.920135,-0.338748,0.933792,0.247612,-0.593392, + -0.489368,-0.872077,0,0.904032,0.239732,-0.5, + -0.196471,-0.920135,-0.338748,0.933792,0.247612,-0.593392, + -0.438575,-0.828046,-0.349274,0.90443,0.255712,-0.594723, + -0.217971,-0.975955,0,0.933414,0.232192,-0.5, + -0.339022,-0.940778,0,0.97091,0.224487,-0.5, + -0.260846,-0.906261,-0.332641,0.971855,0.238662,-0.58723, + -0.260846,-0.906261,-0.332641,0.971855,0.238662,-0.58723, + -0.196471,-0.920135,-0.338748,0.933792,0.247612,-0.593392, + -0.217971,-0.975955,0,0.933414,0.232192,-0.5, + -0.959446,-0.199329,-0.199329,0.87462,0.342412,-0.638667, + -0.976969,-0.18835,-0.100277,0.870135,0.316454,-0.5825, + -0.849789,-0.488885,-0.197102,0.883764,0.275079,-0.5875, + -0.959446,-0.199329,-0.199329,0.87462,0.342412,-0.638667, + -0.849789,-0.488885,-0.197102,0.883764,0.275079,-0.5875, + -0.826325,-0.370128,-0.424489,0.884979,0.320204,-0.660875, + -0.969635,-0.244558,0,0.867922,0.303516,-0.5, + -0.84069,-0.541516,0,0.882548,0.259579,-0.5, + -0.849789,-0.488885,-0.197102,0.883764,0.275079,-0.5875, + -0.969635,-0.244558,0,0.867922,0.303516,-0.5, + -0.849789,-0.488885,-0.197102,0.883764,0.275079,-0.5875, + -0.976969,-0.18835,-0.100277,0.870135,0.316454,-0.5825, + -0.489368,-0.872077,0,0.904032,0.239732,-0.5, + -0.438575,-0.828046,-0.349274,0.90443,0.255712,-0.594723, + -0.849789,-0.488885,-0.197102,0.883764,0.275079,-0.5875, + -0.489368,-0.872077,0,0.904032,0.239732,-0.5, + -0.849789,-0.488885,-0.197102,0.883764,0.275079,-0.5875, + -0.84069,-0.541516,0,0.882548,0.259579,-0.5, + -0.455383,-0.61687,-0.641949,0.905018,0.303308,-0.673773, + -0.826325,-0.370128,-0.424489,0.884979,0.320204,-0.660875, + -0.849789,-0.488885,-0.197102,0.883764,0.275079,-0.5875, + -0.455383,-0.61687,-0.641949,0.905018,0.303308,-0.673773, + -0.849789,-0.488885,-0.197102,0.883764,0.275079,-0.5875, + -0.438575,-0.828046,-0.349274,0.90443,0.255712,-0.594723, + -0.959446,-0.199329,0.199329,0.87462,0.342412,-0.361333, + -0.826326,-0.370128,0.424489,0.884979,0.320204,-0.339125, + -0.849789,-0.488886,0.197102,0.883764,0.275079,-0.4125, + -0.959446,-0.199329,0.199329,0.87462,0.342412,-0.361333, + -0.849789,-0.488886,0.197102,0.883764,0.275079,-0.4125, + -0.976969,-0.18835,0.100277,0.870135,0.316454,-0.4175, + -0.455383,-0.61687,0.641949,0.905018,0.303308,-0.326227, + -0.438574,-0.828046,0.349274,0.90443,0.255712,-0.405277, + -0.849789,-0.488886,0.197102,0.883764,0.275079,-0.4125, + -0.455383,-0.61687,0.641949,0.905018,0.303308,-0.326227, + -0.849789,-0.488886,0.197102,0.883764,0.275079,-0.4125, + -0.826326,-0.370128,0.424489,0.884979,0.320204,-0.339125, + -0.489368,-0.872077,0,0.904032,0.239732,-0.5, + -0.84069,-0.541516,0,0.882548,0.259579,-0.5, + -0.849789,-0.488886,0.197102,0.883764,0.275079,-0.4125, + -0.489368,-0.872077,0,0.904032,0.239732,-0.5, + -0.849789,-0.488886,0.197102,0.883764,0.275079,-0.4125, + -0.438574,-0.828046,0.349274,0.90443,0.255712,-0.405277, + -0.969635,-0.244558,0,0.867922,0.303516,-0.5, + -0.976969,-0.18835,0.100277,0.870135,0.316454,-0.4175, + -0.849789,-0.488886,0.197102,0.883764,0.275079,-0.4125, + -0.969635,-0.244558,0,0.867922,0.303516,-0.5, + -0.849789,-0.488886,0.197102,0.883764,0.275079,-0.4125, + -0.84069,-0.541516,0,0.882548,0.259579,-0.5, + -0.088988,-0.705766,-0.702834,0.934927,0.293873,-0.671218, + -0.103837,-0.707557,-0.698986,0.974692,0.281188,-0.659921, + 0.110573,-0.360362,-0.926236,0.979421,0.352064,-0.703536, + 0.110573,-0.360362,-0.926236,0.979421,0.352064,-0.703536, + 0.06872,-0.352527,-0.933275,0.936818,0.370973,-0.717914, + -0.088988,-0.705766,-0.702834,0.934927,0.293873,-0.671218, + 0.291602,-0.024985,-0.956213,0.985095,0.437116,-0.718074, + 0.214013,-0.011144,-0.976767,0.939088,0.463494,-0.73348, + 0.06872,-0.352527,-0.933275,0.936818,0.370973,-0.717914, + 0.291602,-0.024985,-0.956213,0.985095,0.437116,-0.718074, + 0.06872,-0.352527,-0.933275,0.936818,0.370973,-0.717914, + 0.110573,-0.360362,-0.926236,0.979421,0.352064,-0.703536, + 0.214013,-0.011144,-0.976767,0.939088,0.463494,-0.73348, + -0.2474,0.003968,-0.968905,0.905451,0.476683,-0.737495, + -0.359172,-0.316853,-0.877838,0.905187,0.382177,-0.721479, + -0.359172,-0.316853,-0.877838,0.905187,0.382177,-0.721479, + 0.06872,-0.352527,-0.933275,0.936818,0.370973,-0.717914, + 0.214013,-0.011144,-0.976767,0.939088,0.463494,-0.73348, + -0.455383,-0.61687,-0.641949,0.905018,0.303308,-0.673773, + -0.088988,-0.705766,-0.702834,0.934927,0.293873,-0.671218, + 0.06872,-0.352527,-0.933275,0.936818,0.370973,-0.717914, + -0.455383,-0.61687,-0.641949,0.905018,0.303308,-0.673773, + 0.06872,-0.352527,-0.933275,0.936818,0.370973,-0.717914, + -0.359172,-0.316853,-0.877838,0.905187,0.382177,-0.721479, + 0.575185,0.562873,-0.59358,0.995497,0.593044,-0.659921, + 0.429706,0.63213,-0.644798,0.943249,0.633115,-0.671218, + 0.345208,0.311816,-0.885213,0.941357,0.556014,-0.717914, + 0.575185,0.562873,-0.59358,0.995497,0.593044,-0.659921, + 0.345208,0.311816,-0.885213,0.941357,0.556014,-0.717914, + 0.447221,0.281892,-0.84884,0.990769,0.522168,-0.703536, + 0.429706,0.63213,-0.644798,0.943249,0.633115,-0.671218, + -0.115437,0.702917,-0.701842,0.907098,0.650057,-0.673773, + -0.23409,0.368714,-0.899584,0.906322,0.571188,-0.721479, + -0.23409,0.368714,-0.899584,0.906322,0.571188,-0.721479, + 0.345208,0.311816,-0.885213,0.941357,0.556014,-0.717914, + 0.429706,0.63213,-0.644798,0.943249,0.633115,-0.671218, + -0.2474,0.003968,-0.968905,0.905451,0.476683,-0.737495, + 0.214013,-0.011144,-0.976767,0.939088,0.463494,-0.73348, + 0.345208,0.311816,-0.885213,0.941357,0.556014,-0.717914, + -0.2474,0.003968,-0.968905,0.905451,0.476683,-0.737495, + 0.345208,0.311816,-0.885213,0.941357,0.556014,-0.717914, + -0.23409,0.368714,-0.899584,0.906322,0.571188,-0.721479, + 0.214013,-0.011144,-0.976767,0.939088,0.463494,-0.73348, + 0.291602,-0.024985,-0.956213,0.985095,0.437116,-0.718074, + 0.447221,0.281892,-0.84884,0.990769,0.522168,-0.703536, + 0.447221,0.281892,-0.84884,0.990769,0.522168,-0.703536, + 0.345208,0.311816,-0.885213,0.941357,0.556014,-0.717914, + 0.214013,-0.011144,-0.976767,0.939088,0.463494,-0.73348, + -0.959446,0.199329,-0.199329,0.87462,0.619745,-0.638667, + -0.976969,0.100277,-0.18835,0.870135,0.563579,-0.664625, + -0.859317,0.197434,-0.471799,0.883764,0.568579,-0.706, + -0.959446,0.199329,-0.199329,0.87462,0.619745,-0.638667, + -0.859317,0.197434,-0.471799,0.883764,0.568579,-0.706, + -0.714284,0.497638,-0.492092,0.884979,0.641954,-0.660875, + -0.969635,0,-0.244558,0.867922,0.481079,-0.677562, + -0.761523,0.030964,-0.647398,0.882548,0.481079,-0.7215, + -0.859317,0.197434,-0.471799,0.883764,0.568579,-0.706, + -0.969635,0,-0.244558,0.867922,0.481079,-0.677562, + -0.859317,0.197434,-0.471799,0.883764,0.568579,-0.706, + -0.976969,0.100277,-0.18835,0.870135,0.563579,-0.664625, + -0.761523,0.030964,-0.647398,0.882548,0.481079,-0.7215, + -0.2474,0.003968,-0.968905,0.905451,0.476683,-0.737495, + -0.23409,0.368714,-0.899584,0.906322,0.571188,-0.721479, + -0.23409,0.368714,-0.899584,0.906322,0.571188,-0.721479, + -0.859317,0.197434,-0.471799,0.883764,0.568579,-0.706, + -0.761523,0.030964,-0.647398,0.882548,0.481079,-0.7215, + -0.23409,0.368714,-0.899584,0.906322,0.571188,-0.721479, + -0.115437,0.702917,-0.701842,0.907098,0.650057,-0.673773, + -0.714284,0.497638,-0.492092,0.884979,0.641954,-0.660875, + -0.714284,0.497638,-0.492092,0.884979,0.641954,-0.660875, + -0.859317,0.197434,-0.471799,0.883764,0.568579,-0.706, + -0.23409,0.368714,-0.899584,0.906322,0.571188,-0.721479, + -0.959446,-0.199329,-0.199329,0.87462,0.342412,-0.638667, + -0.826325,-0.370128,-0.424489,0.884979,0.320204,-0.660875, + -0.845588,-0.179708,-0.502678,0.883764,0.393579,-0.706, + -0.959446,-0.199329,-0.199329,0.87462,0.342412,-0.638667, + -0.845588,-0.179708,-0.502678,0.883764,0.393579,-0.706, + -0.976969,-0.100277,-0.18835,0.870135,0.398579,-0.664625, + -0.826325,-0.370128,-0.424489,0.884979,0.320204,-0.660875, + -0.455383,-0.61687,-0.641949,0.905018,0.303308,-0.673773, + -0.359172,-0.316853,-0.877838,0.905187,0.382177,-0.721479, + -0.359172,-0.316853,-0.877838,0.905187,0.382177,-0.721479, + -0.845588,-0.179708,-0.502678,0.883764,0.393579,-0.706, + -0.826325,-0.370128,-0.424489,0.884979,0.320204,-0.660875, + -0.2474,0.003968,-0.968905,0.905451,0.476683,-0.737495, + -0.761523,0.030964,-0.647398,0.882548,0.481079,-0.7215, + -0.845588,-0.179708,-0.502678,0.883764,0.393579,-0.706, + -0.2474,0.003968,-0.968905,0.905451,0.476683,-0.737495, + -0.845588,-0.179708,-0.502678,0.883764,0.393579,-0.706, + -0.359172,-0.316853,-0.877838,0.905187,0.382177,-0.721479, + -0.969635,0,-0.244558,0.867922,0.481079,-0.677562, + -0.976969,-0.100277,-0.18835,0.870135,0.398579,-0.664625, + -0.845588,-0.179708,-0.502678,0.883764,0.393579,-0.706, + -0.969635,0,-0.244558,0.867922,0.481079,-0.677562, + -0.845588,-0.179708,-0.502678,0.883764,0.393579,-0.706, + -0.761523,0.030964,-0.647398,0.882548,0.481079,-0.7215, + -0.959446,0.199329,0.199329,0.87462,0.619745,-0.361333, + -0.976969,0.100277,0.18835,0.870135,0.563579,-0.335375, + -0.993621,0.079739,0.079739,0.861889,0.571579,-0.4095, + -0.959446,0.199329,0.199329,0.87462,0.619745,-0.361333, + -0.993621,0.079739,0.079739,0.861889,0.571579,-0.4095, + -0.976969,0.188349,0.100277,0.870135,0.645704,-0.4175, + -0.976969,0.100277,0.18835,0.870135,0.563579,-0.335375, + -0.969635,0,0.244558,0.867922,0.481079,-0.322437, + -0.996384,0,0.08496,0.859111,0.481079,-0.40225, + -0.996384,0,0.08496,0.859111,0.481079,-0.40225, + -0.993621,0.079739,0.079739,0.861889,0.571579,-0.4095, + -0.976969,0.100277,0.18835,0.870135,0.563579,-0.335375, + -1,0,0,0.856159,0.481079,-0.5, + -0.996384,0.08496,0,0.859111,0.578829,-0.5, + -0.993621,0.079739,0.079739,0.861889,0.571579,-0.4095, + -1,0,0,0.856159,0.481079,-0.5, + -0.993621,0.079739,0.079739,0.861889,0.571579,-0.4095, + -0.996384,0,0.08496,0.859111,0.481079,-0.40225, + -0.996384,0.08496,0,0.859111,0.578829,-0.5, + -0.969635,0.244558,0,0.867922,0.658641,-0.5, + -0.976969,0.188349,0.100277,0.870135,0.645704,-0.4175, + -0.976969,0.188349,0.100277,0.870135,0.645704,-0.4175, + -0.993621,0.079739,0.079739,0.861889,0.571579,-0.4095, + -0.996384,0.08496,0,0.859111,0.578829,-0.5, + -0.959446,-0.199329,0.199329,0.87462,0.342412,-0.361333, + -0.976969,-0.18835,0.100277,0.870135,0.316454,-0.4175, + -0.993621,-0.079739,0.079739,0.861889,0.390579,-0.4095, + -0.959446,-0.199329,0.199329,0.87462,0.342412,-0.361333, + -0.993621,-0.079739,0.079739,0.861889,0.390579,-0.4095, + -0.976969,-0.100277,0.18835,0.870135,0.398579,-0.335375, + -0.976969,-0.18835,0.100277,0.870135,0.316454,-0.4175, + -0.969635,-0.244558,0,0.867922,0.303516,-0.5, + -0.996384,-0.08496,0,0.859111,0.383329,-0.5, + -0.996384,-0.08496,0,0.859111,0.383329,-0.5, + -0.993621,-0.079739,0.079739,0.861889,0.390579,-0.4095, + -0.976969,-0.18835,0.100277,0.870135,0.316454,-0.4175, + -1,0,0,0.856159,0.481079,-0.5, + -0.996384,0,0.08496,0.859111,0.481079,-0.40225, + -0.993621,-0.079739,0.079739,0.861889,0.390579,-0.4095, + -1,0,0,0.856159,0.481079,-0.5, + -0.993621,-0.079739,0.079739,0.861889,0.390579,-0.4095, + -0.996384,-0.08496,0,0.859111,0.383329,-0.5, + -0.996384,0,0.08496,0.859111,0.481079,-0.40225, + -0.969635,0,0.244558,0.867922,0.481079,-0.322437, + -0.976969,-0.100277,0.18835,0.870135,0.398579,-0.335375, + -0.976969,-0.100277,0.18835,0.870135,0.398579,-0.335375, + -0.993621,-0.079739,0.079739,0.861889,0.390579,-0.4095, + -0.996384,0,0.08496,0.859111,0.481079,-0.40225, + -0.959446,-0.199329,-0.199329,0.87462,0.342412,-0.638667, + -0.976969,-0.100277,-0.18835,0.870135,0.398579,-0.664625, + -0.993621,-0.079739,-0.079739,0.861889,0.390579,-0.5905, + -0.959446,-0.199329,-0.199329,0.87462,0.342412,-0.638667, + -0.993621,-0.079739,-0.079739,0.861889,0.390579,-0.5905, + -0.976969,-0.18835,-0.100277,0.870135,0.316454,-0.5825, + -0.976969,-0.100277,-0.18835,0.870135,0.398579,-0.664625, + -0.969635,0,-0.244558,0.867922,0.481079,-0.677562, + -0.996384,0,-0.08496,0.859111,0.481079,-0.59775, + -0.996384,0,-0.08496,0.859111,0.481079,-0.59775, + -0.993621,-0.079739,-0.079739,0.861889,0.390579,-0.5905, + -0.976969,-0.100277,-0.18835,0.870135,0.398579,-0.664625, + -1,0,0,0.856159,0.481079,-0.5, + -0.996384,-0.08496,0,0.859111,0.383329,-0.5, + -0.993621,-0.079739,-0.079739,0.861889,0.390579,-0.5905, + -1,0,0,0.856159,0.481079,-0.5, + -0.993621,-0.079739,-0.079739,0.861889,0.390579,-0.5905, + -0.996384,0,-0.08496,0.859111,0.481079,-0.59775, + -0.996384,-0.08496,0,0.859111,0.383329,-0.5, + -0.969635,-0.244558,0,0.867922,0.303516,-0.5, + -0.976969,-0.18835,-0.100277,0.870135,0.316454,-0.5825, + -0.976969,-0.18835,-0.100277,0.870135,0.316454,-0.5825, + -0.993621,-0.079739,-0.079739,0.861889,0.390579,-0.5905, + -0.996384,-0.08496,0,0.859111,0.383329,-0.5, + -0.959446,0.199329,-0.199329,0.87462,0.619745,-0.638667, + -0.976969,0.188349,-0.100277,0.870135,0.645704,-0.5825, + -0.993621,0.079739,-0.079739,0.861889,0.571579,-0.5905, + -0.959446,0.199329,-0.199329,0.87462,0.619745,-0.638667, + -0.993621,0.079739,-0.079739,0.861889,0.571579,-0.5905, + -0.976969,0.100277,-0.18835,0.870135,0.563579,-0.664625, + -0.976969,0.188349,-0.100277,0.870135,0.645704,-0.5825, + -0.969635,0.244558,0,0.867922,0.658641,-0.5, + -0.996384,0.08496,0,0.859111,0.578829,-0.5, + -0.996384,0.08496,0,0.859111,0.578829,-0.5, + -0.993621,0.079739,-0.079739,0.861889,0.571579,-0.5905, + -0.976969,0.188349,-0.100277,0.870135,0.645704,-0.5825, + -1,0,0,0.856159,0.481079,-0.5, + -0.996384,0,-0.08496,0.859111,0.481079,-0.59775, + -0.993621,0.079739,-0.079739,0.861889,0.571579,-0.5905, + -1,0,0,0.856159,0.481079,-0.5, + -0.993621,0.079739,-0.079739,0.861889,0.571579,-0.5905, + -0.996384,0.08496,0,0.859111,0.578829,-0.5, + -0.996384,0,-0.08496,0.859111,0.481079,-0.59775, + -0.969635,0,-0.244558,0.867922,0.481079,-0.677562, + -0.976969,0.100277,-0.18835,0.870135,0.563579,-0.664625, + -0.976969,0.100277,-0.18835,0.870135,0.563579,-0.664625, + -0.993621,0.079739,-0.079739,0.861889,0.571579,-0.5905, + -0.996384,0,-0.08496,0.859111,0.481079,-0.59775, + 0.642358,0.715039,-0.275852,0.998334,0.63557,-0.58723, + 0.575185,0.562873,-0.59358,0.995497,0.593044,-0.659921, + 0.599141,0.555368,-0.576712,1.065911,0.531759,-0.646592, + 0.599141,0.555368,-0.576712,1.065911,0.531759,-0.646592, + 0.668157,0.701389,-0.248233,1.071585,0.569561,-0.579959, + 0.642358,0.715039,-0.275852,0.998334,0.63557,-0.58723, + 0.599141,0.555368,-0.576712,1.065911,0.531759,-0.646592, + 0.585003,0.517563,-0.62442,1.149095,0.453892,-0.633787, + 0.682874,0.680924,-0.264625,1.158568,0.486483,-0.572975, + 0.682874,0.680924,-0.264625,1.158568,0.486483,-0.572975, + 0.668157,0.701389,-0.248233,1.071585,0.569561,-0.579959, + 0.599141,0.555368,-0.576712,1.065911,0.531759,-0.646592, + 0.682874,0.680924,-0.264625,1.158568,0.486483,-0.572975, + 0.700187,0.71396,0,1.161726,0.497346,-0.5, + 0.687547,0.72614,0,1.073477,0.582162,-0.5, + 0.687547,0.72614,0,1.073477,0.582162,-0.5, + 0.668157,0.701389,-0.248233,1.071585,0.569561,-0.579959, + 0.682874,0.680924,-0.264625,1.158568,0.486483,-0.572975, + 0.662437,0.749118,0,0.99928,0.649745,-0.5, + 0.642358,0.715039,-0.275852,0.998334,0.63557,-0.58723, + 0.668157,0.701389,-0.248233,1.071585,0.569561,-0.579959, + 0.662437,0.749118,0,0.99928,0.649745,-0.5, + 0.668157,0.701389,-0.248233,1.071585,0.569561,-0.579959, + 0.687547,0.72614,0,1.073477,0.582162,-0.5, + 0.568513,0.503436,-0.65065,1.23965,0.364075,-0.624059, + 0.547232,0.498931,-0.672015,1.332183,0.266938,-0.619965, + 0.694102,0.647395,-0.314805,1.351457,0.289652,-0.565436, + 0.694102,0.647395,-0.314805,1.351457,0.289652,-0.565436, + 0.688382,0.659806,-0.301308,1.253715,0.391468,-0.567669, + 0.568513,0.503436,-0.65065,1.23965,0.364075,-0.624059, + 0.726158,0.687528,0,1.357882,0.297224,-0.5, + 0.71287,0.701296,0,1.258403,0.4006,-0.5, + 0.688382,0.659806,-0.301308,1.253715,0.391468,-0.567669, + 0.726158,0.687528,0,1.357882,0.297224,-0.5, + 0.688382,0.659806,-0.301308,1.253715,0.391468,-0.567669, + 0.694102,0.647395,-0.314805,1.351457,0.289652,-0.565436, + 0.71287,0.701296,0,1.258403,0.4006,-0.5, + 0.700187,0.71396,0,1.161726,0.497346,-0.5, + 0.682874,0.680924,-0.264625,1.158568,0.486483,-0.572975, + 0.682874,0.680924,-0.264625,1.158568,0.486483,-0.572975, + 0.688382,0.659806,-0.301308,1.253715,0.391468,-0.567669, + 0.71287,0.701296,0,1.258403,0.4006,-0.5, + 0.585003,0.517563,-0.62442,1.149095,0.453892,-0.633787, + 0.568513,0.503436,-0.65065,1.23965,0.364075,-0.624059, + 0.688382,0.659806,-0.301308,1.253715,0.391468,-0.567669, + 0.585003,0.517563,-0.62442,1.149095,0.453892,-0.633787, + 0.688382,0.659806,-0.301308,1.253715,0.391468,-0.567669, + 0.682874,0.680924,-0.264625,1.158568,0.486483,-0.572975, + 0.694102,0.647395,0.314805,1.351457,0.289652,-0.434564, + 0.547232,0.498931,0.672016,1.332183,0.266938,-0.380035, + 0.568513,0.503436,0.65065,1.23965,0.364075,-0.375941, + 0.568513,0.503436,0.65065,1.23965,0.364075,-0.375941, + 0.688382,0.659806,0.301308,1.253715,0.391468,-0.432331, + 0.694102,0.647395,0.314805,1.351457,0.289652,-0.434564, + 0.585003,0.517563,0.62442,1.149095,0.453892,-0.366213, + 0.682874,0.680923,0.264625,1.158568,0.486483,-0.427025, + 0.688382,0.659806,0.301308,1.253715,0.391468,-0.432331, + 0.585003,0.517563,0.62442,1.149095,0.453892,-0.366213, + 0.688382,0.659806,0.301308,1.253715,0.391468,-0.432331, + 0.568513,0.503436,0.65065,1.23965,0.364075,-0.375941, + 0.682874,0.680923,0.264625,1.158568,0.486483,-0.427025, + 0.700187,0.71396,0,1.161726,0.497346,-0.5, + 0.71287,0.701296,0,1.258403,0.4006,-0.5, + 0.71287,0.701296,0,1.258403,0.4006,-0.5, + 0.688382,0.659806,0.301308,1.253715,0.391468,-0.432331, + 0.682874,0.680923,0.264625,1.158568,0.486483,-0.427025, + 0.726158,0.687528,0,1.357882,0.297224,-0.5, + 0.694102,0.647395,0.314805,1.351457,0.289652,-0.434564, + 0.688382,0.659806,0.301308,1.253715,0.391468,-0.432331, + 0.726158,0.687528,0,1.357882,0.297224,-0.5, + 0.688382,0.659806,0.301308,1.253715,0.391468,-0.432331, + 0.71287,0.701296,0,1.258403,0.4006,-0.5, + 0.599141,0.555368,0.576712,1.065911,0.531759,-0.353408, + 0.575185,0.562873,0.59358,0.995497,0.593044,-0.340079, + 0.642358,0.715039,0.275852,0.998334,0.63557,-0.41277, + 0.642358,0.715039,0.275852,0.998334,0.63557,-0.41277, + 0.668157,0.701389,0.248233,1.071585,0.569561,-0.420041, + 0.599141,0.555368,0.576712,1.065911,0.531759,-0.353408, + 0.662437,0.749118,0,0.99928,0.649745,-0.5, + 0.687547,0.72614,0,1.073477,0.582162,-0.5, + 0.668157,0.701389,0.248233,1.071585,0.569561,-0.420041, + 0.662437,0.749118,0,0.99928,0.649745,-0.5, + 0.668157,0.701389,0.248233,1.071585,0.569561,-0.420041, + 0.642358,0.715039,0.275852,0.998334,0.63557,-0.41277, + 0.687547,0.72614,0,1.073477,0.582162,-0.5, + 0.700187,0.71396,0,1.161726,0.497346,-0.5, + 0.682874,0.680923,0.264625,1.158568,0.486483,-0.427025, + 0.682874,0.680923,0.264625,1.158568,0.486483,-0.427025, + 0.668157,0.701389,0.248233,1.071585,0.569561,-0.420041, + 0.687547,0.72614,0,1.073477,0.582162,-0.5, + 0.682874,0.680923,0.264625,1.158568,0.486483,-0.427025, + 0.585003,0.517563,0.62442,1.149095,0.453892,-0.366213, + 0.599141,0.555368,0.576712,1.065911,0.531759,-0.353408, + 0.599141,0.555368,0.576712,1.065911,0.531759,-0.353408, + 0.668157,0.701389,0.248233,1.071585,0.569561,-0.420041, + 0.682874,0.680923,0.264625,1.158568,0.486483,-0.427025, + -0.103837,-0.707557,-0.698986,0.974692,0.281188,-0.659921, + -0.251782,-0.681632,-0.687011,1.024302,0.254547,-0.646592, + 0.010629,-0.366255,-0.930454,1.033759,0.31755,-0.686572, + -0.103837,-0.707557,-0.698986,0.974692,0.281188,-0.659921, + 0.010629,-0.366255,-0.930454,1.033759,0.31755,-0.686572, + 0.110573,-0.360362,-0.926236,0.979421,0.352064,-0.703536, + -0.251782,-0.681632,-0.687011,1.024302,0.254547,-0.646592, + -0.405056,-0.645141,-0.64786,1.079619,0.214898,-0.633787, + -0.092335,-0.356775,-0.929616,1.095409,0.269215,-0.670274, + -0.092335,-0.356775,-0.929616,1.095409,0.269215,-0.670274, + 0.010629,-0.366255,-0.930454,1.033759,0.31755,-0.686572, + -0.251782,-0.681632,-0.687011,1.024302,0.254547,-0.646592, + 0.167416,-0.052778,-0.984473,1.114357,0.334395,-0.682436, + 0.238763,-0.041303,-0.970199,1.045107,0.393153,-0.699898, + 0.010629,-0.366255,-0.930454,1.033759,0.31755,-0.686572, + 0.167416,-0.052778,-0.984473,1.114357,0.334395,-0.682436, + 0.010629,-0.366255,-0.930454,1.033759,0.31755,-0.686572, + -0.092335,-0.356775,-0.929616,1.095409,0.269215,-0.670274, + 0.238763,-0.041303,-0.970199,1.045107,0.393153,-0.699898, + 0.291602,-0.024985,-0.956213,0.985095,0.437116,-0.718074, + 0.110573,-0.360362,-0.926236,0.979421,0.352064,-0.703536, + 0.110573,-0.360362,-0.926236,0.979421,0.352064,-0.703536, + 0.010629,-0.366255,-0.930454,1.033759,0.31755,-0.686572, + 0.238763,-0.041303,-0.970199,1.045107,0.393153,-0.699898, + -0.469451,-0.529408,-0.706642,1.136509,0.163187,-0.624059, + -0.591819,-0.448047,-0.670078,1.190836,0.100363,-0.619965, + -0.293198,-0.238286,-0.925881,1.22296,0.138221,-0.652683, + -0.293198,-0.238286,-0.925881,1.22296,0.138221,-0.652683, + -0.19623,-0.318838,-0.927274,1.15995,0.208844,-0.657894, + -0.469451,-0.529408,-0.706642,1.136509,0.163187,-0.624059, + 0.003001,-0.001255,-0.999995,1.261509,0.18365,-0.663589, + 0.084953,-0.04518,-0.99536,1.18808,0.263631,-0.669172, + -0.19623,-0.318838,-0.927274,1.15995,0.208844,-0.657894, + 0.003001,-0.001255,-0.999995,1.261509,0.18365,-0.663589, + -0.19623,-0.318838,-0.927274,1.15995,0.208844,-0.657894, + -0.293198,-0.238286,-0.925881,1.22296,0.138221,-0.652683, + 0.084953,-0.04518,-0.99536,1.18808,0.263631,-0.669172, + 0.167416,-0.052778,-0.984473,1.114357,0.334395,-0.682436, + -0.092335,-0.356775,-0.929616,1.095409,0.269215,-0.670274, + -0.092335,-0.356775,-0.929616,1.095409,0.269215,-0.670274, + -0.19623,-0.318838,-0.927274,1.15995,0.208844,-0.657894, + 0.084953,-0.04518,-0.99536,1.18808,0.263631,-0.669172, + -0.405056,-0.645141,-0.64786,1.079619,0.214898,-0.633787, + -0.469451,-0.529408,-0.706642,1.136509,0.163187,-0.624059, + -0.19623,-0.318838,-0.927274,1.15995,0.208844,-0.657894, + -0.405056,-0.645141,-0.64786,1.079619,0.214898,-0.633787, + -0.19623,-0.318838,-0.927274,1.15995,0.208844,-0.657894, + -0.092335,-0.356775,-0.929616,1.095409,0.269215,-0.670274, + 0.547232,0.498931,-0.672015,1.332183,0.266938,-0.619965, + 0.568513,0.503436,-0.65065,1.23965,0.364075,-0.624059, + 0.340631,0.234777,-0.910412,1.216209,0.318418,-0.657894, + 0.547232,0.498931,-0.672015,1.332183,0.266938,-0.619965, + 0.340631,0.234777,-0.910412,1.216209,0.318418,-0.657894, + 0.284277,0.249094,-0.925818,1.300058,0.22908,-0.652683, + 0.568513,0.503436,-0.65065,1.23965,0.364075,-0.624059, + 0.585003,0.517563,-0.62442,1.149095,0.453892,-0.633787, + 0.392854,0.244042,-0.886628,1.133305,0.399575,-0.670274, + 0.392854,0.244042,-0.886628,1.133305,0.399575,-0.670274, + 0.340631,0.234777,-0.910412,1.216209,0.318418,-0.657894, + 0.568513,0.503436,-0.65065,1.23965,0.364075,-0.624059, + 0.167416,-0.052778,-0.984473,1.114357,0.334395,-0.682436, + 0.084953,-0.04518,-0.99536,1.18808,0.263631,-0.669172, + 0.340631,0.234777,-0.910412,1.216209,0.318418,-0.657894, + 0.167416,-0.052778,-0.984473,1.114357,0.334395,-0.682436, + 0.340631,0.234777,-0.910412,1.216209,0.318418,-0.657894, + 0.392854,0.244042,-0.886628,1.133305,0.399575,-0.670274, + 0.084953,-0.04518,-0.99536,1.18808,0.263631,-0.669172, + 0.003001,-0.001255,-0.999995,1.261509,0.18365,-0.663589, + 0.284277,0.249094,-0.925818,1.300058,0.22908,-0.652683, + 0.284277,0.249094,-0.925818,1.300058,0.22908,-0.652683, + 0.340631,0.234777,-0.910412,1.216209,0.318418,-0.657894, + 0.084953,-0.04518,-0.99536,1.18808,0.263631,-0.669172, + 0.599141,0.555368,-0.576712,1.065911,0.531759,-0.646592, + 0.575185,0.562873,-0.59358,0.995497,0.593044,-0.659921, + 0.447221,0.281892,-0.84884,0.990769,0.522168,-0.703536, + 0.447221,0.281892,-0.84884,0.990769,0.522168,-0.703536, + 0.431005,0.262774,-0.86324,1.056455,0.468757,-0.686572, + 0.599141,0.555368,-0.576712,1.065911,0.531759,-0.646592, + 0.291602,-0.024985,-0.956213,0.985095,0.437116,-0.718074, + 0.238763,-0.041303,-0.970199,1.045107,0.393153,-0.699898, + 0.431005,0.262774,-0.86324,1.056455,0.468757,-0.686572, + 0.291602,-0.024985,-0.956213,0.985095,0.437116,-0.718074, + 0.431005,0.262774,-0.86324,1.056455,0.468757,-0.686572, + 0.447221,0.281892,-0.84884,0.990769,0.522168,-0.703536, + 0.238763,-0.041303,-0.970199,1.045107,0.393153,-0.699898, + 0.167416,-0.052778,-0.984473,1.114357,0.334395,-0.682436, + 0.392854,0.244042,-0.886628,1.133305,0.399575,-0.670274, + 0.392854,0.244042,-0.886628,1.133305,0.399575,-0.670274, + 0.431005,0.262774,-0.86324,1.056455,0.468757,-0.686572, + 0.238763,-0.041303,-0.970199,1.045107,0.393153,-0.699898, + 0.585003,0.517563,-0.62442,1.149095,0.453892,-0.633787, + 0.599141,0.555368,-0.576712,1.065911,0.531759,-0.646592, + 0.431005,0.262774,-0.86324,1.056455,0.468757,-0.686572, + 0.585003,0.517563,-0.62442,1.149095,0.453892,-0.633787, + 0.431005,0.262774,-0.86324,1.056455,0.468757,-0.686572, + 0.392854,0.244042,-0.886628,1.133305,0.399575,-0.670274, + -0.103837,-0.707557,0.698986,0.974692,0.281188,-0.340079, + 0.110573,-0.360361,0.926236,0.979421,0.352064,-0.296464, + 0.010629,-0.366254,0.930454,1.033759,0.31755,-0.313428, + -0.103837,-0.707557,0.698986,0.974692,0.281188,-0.340079, + 0.010629,-0.366254,0.930454,1.033759,0.31755,-0.313428, + -0.251782,-0.681632,0.68701,1.024302,0.254547,-0.353408, + 0.110573,-0.360361,0.926236,0.979421,0.352064,-0.296464, + 0.291601,-0.024985,0.956214,0.985095,0.437116,-0.281926, + 0.238762,-0.041303,0.970199,1.045107,0.393153,-0.300102, + 0.238762,-0.041303,0.970199,1.045107,0.393153,-0.300102, + 0.010629,-0.366254,0.930454,1.033759,0.31755,-0.313428, + 0.110573,-0.360361,0.926236,0.979421,0.352064,-0.296464, + 0.167415,-0.052778,0.984473,1.114357,0.334395,-0.317564, + -0.092335,-0.356776,0.929616,1.095409,0.269215,-0.329726, + 0.010629,-0.366254,0.930454,1.033759,0.31755,-0.313428, + 0.167415,-0.052778,0.984473,1.114357,0.334395,-0.317564, + 0.010629,-0.366254,0.930454,1.033759,0.31755,-0.313428, + 0.238762,-0.041303,0.970199,1.045107,0.393153,-0.300102, + -0.092335,-0.356776,0.929616,1.095409,0.269215,-0.329726, + -0.405056,-0.645141,0.64786,1.079619,0.214898,-0.366213, + -0.251782,-0.681632,0.68701,1.024302,0.254547,-0.353408, + -0.251782,-0.681632,0.68701,1.024302,0.254547,-0.353408, + 0.010629,-0.366254,0.930454,1.033759,0.31755,-0.313428, + -0.092335,-0.356776,0.929616,1.095409,0.269215,-0.329726, + 0.447221,0.281892,0.848841,0.990769,0.522168,-0.296464, + 0.575185,0.562873,0.59358,0.995497,0.593044,-0.340079, + 0.599141,0.555368,0.576712,1.065911,0.531759,-0.353408, + 0.599141,0.555368,0.576712,1.065911,0.531759,-0.353408, + 0.431005,0.262774,0.863241,1.056455,0.468757,-0.313428, + 0.447221,0.281892,0.848841,0.990769,0.522168,-0.296464, + 0.585003,0.517563,0.62442,1.149095,0.453892,-0.366213, + 0.392854,0.244041,0.886628,1.133305,0.399575,-0.329726, + 0.431005,0.262774,0.863241,1.056455,0.468757,-0.313428, + 0.585003,0.517563,0.62442,1.149095,0.453892,-0.366213, + 0.431005,0.262774,0.863241,1.056455,0.468757,-0.313428, + 0.599141,0.555368,0.576712,1.065911,0.531759,-0.353408, + 0.392854,0.244041,0.886628,1.133305,0.399575,-0.329726, + 0.167415,-0.052778,0.984473,1.114357,0.334395,-0.317564, + 0.238762,-0.041303,0.970199,1.045107,0.393153,-0.300102, + 0.238762,-0.041303,0.970199,1.045107,0.393153,-0.300102, + 0.431005,0.262774,0.863241,1.056455,0.468757,-0.313428, + 0.392854,0.244041,0.886628,1.133305,0.399575,-0.329726, + 0.291601,-0.024985,0.956214,0.985095,0.437116,-0.281926, + 0.447221,0.281892,0.848841,0.990769,0.522168,-0.296464, + 0.431005,0.262774,0.863241,1.056455,0.468757,-0.313428, + 0.291601,-0.024985,0.956214,0.985095,0.437116,-0.281926, + 0.431005,0.262774,0.863241,1.056455,0.468757,-0.313428, + 0.238762,-0.041303,0.970199,1.045107,0.393153,-0.300102, + 0.547232,0.498931,0.672016,1.332183,0.266938,-0.380035, + 0.284277,0.249093,0.925818,1.300058,0.22908,-0.347317, + 0.34063,0.234777,0.910412,1.216209,0.318418,-0.342106, + 0.547232,0.498931,0.672016,1.332183,0.266938,-0.380035, + 0.34063,0.234777,0.910412,1.216209,0.318418,-0.342106, + 0.568513,0.503436,0.65065,1.23965,0.364075,-0.375941, + 0.284277,0.249093,0.925818,1.300058,0.22908,-0.347317, + 0.003001,-0.001255,0.999995,1.261509,0.18365,-0.336411, + 0.084953,-0.04518,0.99536,1.18808,0.263631,-0.330828, + 0.084953,-0.04518,0.99536,1.18808,0.263631,-0.330828, + 0.34063,0.234777,0.910412,1.216209,0.318418,-0.342106, + 0.284277,0.249093,0.925818,1.300058,0.22908,-0.347317, + 0.167415,-0.052778,0.984473,1.114357,0.334395,-0.317564, + 0.392854,0.244041,0.886628,1.133305,0.399575,-0.329726, + 0.34063,0.234777,0.910412,1.216209,0.318418,-0.342106, + 0.167415,-0.052778,0.984473,1.114357,0.334395,-0.317564, + 0.34063,0.234777,0.910412,1.216209,0.318418,-0.342106, + 0.084953,-0.04518,0.99536,1.18808,0.263631,-0.330828, + 0.392854,0.244041,0.886628,1.133305,0.399575,-0.329726, + 0.585003,0.517563,0.62442,1.149095,0.453892,-0.366213, + 0.568513,0.503436,0.65065,1.23965,0.364075,-0.375941, + 0.568513,0.503436,0.65065,1.23965,0.364075,-0.375941, + 0.34063,0.234777,0.910412,1.216209,0.318418,-0.342106, + 0.392854,0.244041,0.886628,1.133305,0.399575,-0.329726, + -0.293197,-0.238286,0.925881,1.22296,0.138221,-0.347317, + -0.591819,-0.448047,0.670078,1.190836,0.100363,-0.380035, + -0.469451,-0.529408,0.706642,1.136509,0.163187,-0.375941, + -0.469451,-0.529408,0.706642,1.136509,0.163187,-0.375941, + -0.19623,-0.318838,0.927274,1.15995,0.208844,-0.342106, + -0.293197,-0.238286,0.925881,1.22296,0.138221,-0.347317, + -0.405056,-0.645141,0.64786,1.079619,0.214898,-0.366213, + -0.092335,-0.356776,0.929616,1.095409,0.269215,-0.329726, + -0.19623,-0.318838,0.927274,1.15995,0.208844,-0.342106, + -0.405056,-0.645141,0.64786,1.079619,0.214898,-0.366213, + -0.19623,-0.318838,0.927274,1.15995,0.208844,-0.342106, + -0.469451,-0.529408,0.706642,1.136509,0.163187,-0.375941, + -0.092335,-0.356776,0.929616,1.095409,0.269215,-0.329726, + 0.167415,-0.052778,0.984473,1.114357,0.334395,-0.317564, + 0.084953,-0.04518,0.99536,1.18808,0.263631,-0.330828, + 0.084953,-0.04518,0.99536,1.18808,0.263631,-0.330828, + -0.19623,-0.318838,0.927274,1.15995,0.208844,-0.342106, + -0.092335,-0.356776,0.929616,1.095409,0.269215,-0.329726, + 0.003001,-0.001255,0.999995,1.261509,0.18365,-0.336411, + -0.293197,-0.238286,0.925881,1.22296,0.138221,-0.347317, + -0.19623,-0.318838,0.927274,1.15995,0.208844,-0.342106, + 0.003001,-0.001255,0.999995,1.261509,0.18365,-0.336411, + -0.19623,-0.318838,0.927274,1.15995,0.208844,-0.342106, + 0.084953,-0.04518,0.99536,1.18808,0.263631,-0.330828, + -0.251782,-0.681632,-0.687011,1.024302,0.254547,-0.646592, + -0.103837,-0.707557,-0.698986,0.974692,0.281188,-0.659921, + -0.260846,-0.906261,-0.332641,0.971855,0.238662,-0.58723, + -0.260846,-0.906261,-0.332641,0.971855,0.238662,-0.58723, + -0.42869,-0.845027,-0.319616,1.018628,0.216746,-0.579959, + -0.251782,-0.681632,-0.687011,1.024302,0.254547,-0.646592, + -0.339022,-0.940778,0,0.97091,0.224487,-0.5, + -0.49913,-0.866527,0,1.016736,0.204145,-0.5, + -0.42869,-0.845027,-0.319616,1.018628,0.216746,-0.579959, + -0.339022,-0.940778,0,0.97091,0.224487,-0.5, + -0.42869,-0.845027,-0.319616,1.018628,0.216746,-0.579959, + -0.260846,-0.906261,-0.332641,0.971855,0.238662,-0.58723, + -0.49913,-0.866527,0,1.016736,0.204145,-0.5, + -0.60511,-0.796142,0,1.066987,0.171444,-0.5, + -0.573691,-0.778283,-0.255254,1.070145,0.182308,-0.572975, + -0.573691,-0.778283,-0.255254,1.070145,0.182308,-0.572975, + -0.42869,-0.845027,-0.319616,1.018628,0.216746,-0.579959, + -0.49913,-0.866527,0,1.016736,0.204145,-0.5, + -0.405056,-0.645141,-0.64786,1.079619,0.214898,-0.633787, + -0.251782,-0.681632,-0.687011,1.024302,0.254547,-0.646592, + -0.42869,-0.845027,-0.319616,1.018628,0.216746,-0.579959, + -0.405056,-0.645141,-0.64786,1.079619,0.214898,-0.633787, + -0.42869,-0.845027,-0.319616,1.018628,0.216746,-0.579959, + -0.573691,-0.778283,-0.255254,1.070145,0.182308,-0.572975, + -0.260846,-0.906261,0.332641,0.971855,0.238662,-0.41277, + -0.103837,-0.707557,0.698986,0.974692,0.281188,-0.340079, + -0.251782,-0.681632,0.68701,1.024302,0.254547,-0.353408, + -0.251782,-0.681632,0.68701,1.024302,0.254547,-0.353408, + -0.42869,-0.845027,0.319616,1.018628,0.216746,-0.420041, + -0.260846,-0.906261,0.332641,0.971855,0.238662,-0.41277, + -0.405056,-0.645141,0.64786,1.079619,0.214898,-0.366213, + -0.573691,-0.778283,0.255254,1.070145,0.182308,-0.427025, + -0.42869,-0.845027,0.319616,1.018628,0.216746,-0.420041, + -0.405056,-0.645141,0.64786,1.079619,0.214898,-0.366213, + -0.42869,-0.845027,0.319616,1.018628,0.216746,-0.420041, + -0.251782,-0.681632,0.68701,1.024302,0.254547,-0.353408, + -0.573691,-0.778283,0.255254,1.070145,0.182308,-0.427025, + -0.60511,-0.796142,0,1.066987,0.171444,-0.5, + -0.49913,-0.866527,0,1.016736,0.204145,-0.5, + -0.49913,-0.866527,0,1.016736,0.204145,-0.5, + -0.42869,-0.845027,0.319616,1.018628,0.216746,-0.420041, + -0.573691,-0.778283,0.255254,1.070145,0.182308,-0.427025, + -0.339022,-0.940778,0,0.97091,0.224487,-0.5, + -0.260846,-0.906261,0.332641,0.971855,0.238662,-0.41277, + -0.42869,-0.845027,0.319616,1.018628,0.216746,-0.420041, + -0.339022,-0.940778,0,0.97091,0.224487,-0.5, + -0.42869,-0.845027,0.319616,1.018628,0.216746,-0.420041, + -0.49913,-0.866527,0,1.016736,0.204145,-0.5, + -0.591819,-0.448047,0.670078,1.190836,0.100363,-0.380035, + -0.769835,-0.555714,0.313903,1.171562,0.077649,-0.434564, + -0.649709,-0.667916,0.362996,1.122445,0.135794,-0.432331, + -0.591819,-0.448047,0.670078,1.190836,0.100363,-0.380035, + -0.649709,-0.667916,0.362996,1.122445,0.135794,-0.432331, + -0.469451,-0.529408,0.706642,1.136509,0.163187,-0.375941, + -0.769835,-0.555714,0.313903,1.171562,0.077649,-0.434564, + -0.831075,-0.55616,0,1.165137,0.070077,-0.5, + -0.713427,-0.700729,0,1.117756,0.126662,-0.5, + -0.713427,-0.700729,0,1.117756,0.126662,-0.5, + -0.649709,-0.667916,0.362996,1.122445,0.135794,-0.432331, + -0.769835,-0.555714,0.313903,1.171562,0.077649,-0.434564, + -0.713427,-0.700729,0,1.117756,0.126662,-0.5, + -0.60511,-0.796142,0,1.066987,0.171444,-0.5, + -0.573691,-0.778283,0.255254,1.070145,0.182308,-0.427025, + -0.573691,-0.778283,0.255254,1.070145,0.182308,-0.427025, + -0.649709,-0.667916,0.362996,1.122445,0.135794,-0.432331, + -0.713427,-0.700729,0,1.117756,0.126662,-0.5, + -0.405056,-0.645141,0.64786,1.079619,0.214898,-0.366213, + -0.469451,-0.529408,0.706642,1.136509,0.163187,-0.375941, + -0.649709,-0.667916,0.362996,1.122445,0.135794,-0.432331, + -0.405056,-0.645141,0.64786,1.079619,0.214898,-0.366213, + -0.649709,-0.667916,0.362996,1.122445,0.135794,-0.432331, + -0.573691,-0.778283,0.255254,1.070145,0.182308,-0.427025, + -0.591819,-0.448047,-0.670078,1.190836,0.100363,-0.619965, + -0.469451,-0.529408,-0.706642,1.136509,0.163187,-0.624059, + -0.649709,-0.667916,-0.362996,1.122445,0.135794,-0.567669, + -0.591819,-0.448047,-0.670078,1.190836,0.100363,-0.619965, + -0.649709,-0.667916,-0.362996,1.122445,0.135794,-0.567669, + -0.769835,-0.555714,-0.313903,1.171562,0.077649,-0.565436, + -0.405056,-0.645141,-0.64786,1.079619,0.214898,-0.633787, + -0.573691,-0.778283,-0.255254,1.070145,0.182308,-0.572975, + -0.649709,-0.667916,-0.362996,1.122445,0.135794,-0.567669, + -0.405056,-0.645141,-0.64786,1.079619,0.214898,-0.633787, + -0.649709,-0.667916,-0.362996,1.122445,0.135794,-0.567669, + -0.469451,-0.529408,-0.706642,1.136509,0.163187,-0.624059, + -0.573691,-0.778283,-0.255254,1.070145,0.182308,-0.572975, + -0.60511,-0.796142,0,1.066987,0.171444,-0.5, + -0.713427,-0.700729,0,1.117756,0.126662,-0.5, + -0.713427,-0.700729,0,1.117756,0.126662,-0.5, + -0.649709,-0.667916,-0.362996,1.122445,0.135794,-0.567669, + -0.573691,-0.778283,-0.255254,1.070145,0.182308,-0.572975, + -0.713427,-0.700729,0,1.117756,0.126662,-0.5, + -0.831075,-0.55616,0,1.165137,0.070077,-0.5, + -0.769835,-0.555714,-0.313903,1.171562,0.077649,-0.565436, + -0.769835,-0.555714,-0.313903,1.171562,0.077649,-0.565436, + -0.649709,-0.667916,-0.362996,1.122445,0.135794,-0.567669, + -0.713427,-0.700729,0,1.117756,0.126662,-0.5, + -0.693597,-0.068529,-0.717096,1.333479,-0.188456,-0.659921, + -0.356933,0.09138,-0.92965,1.401596,-0.166219,-0.703536, + -0.410606,0.007113,-0.911785,1.370721,-0.099359,-0.686572, + -0.693597,-0.068529,-0.717096,1.333479,-0.188456,-0.659921, + -0.410606,0.007113,-0.911785,1.370721,-0.099359,-0.686572, + -0.736772,-0.170063,-0.654405,1.310553,-0.12345,-0.646592, + -0.356933,0.09138,-0.92965,1.401596,-0.166219,-0.703536, + -0.07755,0.232519,-0.969495,1.483337,-0.139536,-0.718074, + -0.076935,0.189453,-0.978871,1.442923,-0.07045,-0.699898, + -0.076935,0.189453,-0.978871,1.442923,-0.07045,-0.699898, + -0.410606,0.007113,-0.911785,1.370721,-0.099359,-0.686572, + -0.356933,0.09138,-0.92965,1.401596,-0.166219,-0.703536, + -0.094492,0.118807,-0.988411,1.39106,0.010509,-0.682436, + -0.411811,-0.074302,-0.908235,1.329732,-0.022152,-0.670274, + -0.410606,0.007113,-0.911785,1.370721,-0.099359,-0.686572, + -0.094492,0.118807,-0.988411,1.39106,0.010509,-0.682436, + -0.410606,0.007113,-0.911785,1.370721,-0.099359,-0.686572, + -0.076935,0.189453,-0.978871,1.442923,-0.07045,-0.699898, + -0.691037,-0.22774,-0.686005,1.278626,-0.049369,-0.633787, + -0.736772,-0.170063,-0.654405,1.310553,-0.12345,-0.646592, + -0.410606,0.007113,-0.911785,1.370721,-0.099359,-0.686572, + -0.691037,-0.22774,-0.686005,1.278626,-0.049369,-0.633787, + -0.410606,0.007113,-0.911785,1.370721,-0.099359,-0.686572, + -0.411811,-0.074302,-0.908235,1.329732,-0.022152,-0.670274, + 0.223762,0.38464,-0.895535,1.565078,-0.112852,-0.703536, + 0.523401,0.54123,-0.65812,1.633195,-0.090616,-0.659921, + 0.523007,0.53259,-0.665441,1.575292,-0.017451,-0.646592, + 0.523007,0.53259,-0.665441,1.575292,-0.017451,-0.646592, + 0.22394,0.359068,-0.906047,1.515124,-0.041541,-0.686572, + 0.223762,0.38464,-0.895535,1.565078,-0.112852,-0.703536, + 0.522827,0.522069,-0.673866,1.503495,0.070388,-0.633787, + 0.227361,0.327503,-0.917087,1.452388,0.04317,-0.670274, + 0.22394,0.359068,-0.906047,1.515124,-0.041541,-0.686572, + 0.522827,0.522069,-0.673866,1.503495,0.070388,-0.633787, + 0.22394,0.359068,-0.906047,1.515124,-0.041541,-0.686572, + 0.523007,0.53259,-0.665441,1.575292,-0.017451,-0.646592, + 0.227361,0.327503,-0.917087,1.452388,0.04317,-0.670274, + -0.094492,0.118807,-0.988411,1.39106,0.010509,-0.682436, + -0.076935,0.189453,-0.978871,1.442923,-0.07045,-0.699898, + -0.076935,0.189453,-0.978871,1.442923,-0.07045,-0.699898, + 0.22394,0.359068,-0.906047,1.515124,-0.041541,-0.686572, + 0.227361,0.327503,-0.917087,1.452388,0.04317,-0.670274, + -0.07755,0.232519,-0.969495,1.483337,-0.139536,-0.718074, + 0.223762,0.38464,-0.895535,1.565078,-0.112852,-0.703536, + 0.22394,0.359068,-0.906047,1.515124,-0.041541,-0.686572, + -0.07755,0.232519,-0.969495,1.483337,-0.139536,-0.718074, + 0.22394,0.359068,-0.906047,1.515124,-0.041541,-0.686572, + -0.076935,0.189453,-0.978871,1.442923,-0.07045,-0.699898, + 0.509286,0.493808,-0.704828,1.421294,0.167113,-0.624059, + 0.547232,0.498931,-0.672015,1.332183,0.266938,-0.619965, + 0.284277,0.249094,-0.925818,1.300058,0.22908,-0.652683, + 0.284277,0.249094,-0.925818,1.300058,0.22908,-0.652683, + 0.192479,0.2506,-0.948763,1.379742,0.135354,-0.657894, + 0.509286,0.493808,-0.704828,1.421294,0.167113,-0.624059, + 0.003001,-0.001255,-0.999995,1.261509,0.18365,-0.663589, + -0.080719,0.04088,-0.995898,1.329879,0.097243,-0.669172, + 0.192479,0.2506,-0.948763,1.379742,0.135354,-0.657894, + 0.003001,-0.001255,-0.999995,1.261509,0.18365,-0.663589, + 0.192479,0.2506,-0.948763,1.379742,0.135354,-0.657894, + 0.284277,0.249094,-0.925818,1.300058,0.22908,-0.652683, + -0.094492,0.118807,-0.988411,1.39106,0.010509,-0.682436, + 0.227361,0.327503,-0.917087,1.452388,0.04317,-0.670274, + 0.192479,0.2506,-0.948763,1.379742,0.135354,-0.657894, + -0.094492,0.118807,-0.988411,1.39106,0.010509,-0.682436, + 0.192479,0.2506,-0.948763,1.379742,0.135354,-0.657894, + -0.080719,0.04088,-0.995898,1.329879,0.097243,-0.669172, + 0.227361,0.327503,-0.917087,1.452388,0.04317,-0.670274, + 0.522827,0.522069,-0.673866,1.503495,0.070388,-0.633787, + 0.509286,0.493808,-0.704828,1.421294,0.167113,-0.624059, + 0.509286,0.493808,-0.704828,1.421294,0.167113,-0.624059, + 0.192479,0.2506,-0.948763,1.379742,0.135354,-0.657894, + 0.227361,0.327503,-0.917087,1.452388,0.04317,-0.670274, + -0.591819,-0.448047,-0.670078,1.190836,0.100363,-0.619965, + -0.660133,-0.325846,-0.676793,1.238464,0.027373,-0.624059, + -0.356146,-0.13643,-0.924417,1.280017,0.059132,-0.657894, + -0.591819,-0.448047,-0.670078,1.190836,0.100363,-0.619965, + -0.356146,-0.13643,-0.924417,1.280017,0.059132,-0.657894, + -0.293198,-0.238286,-0.925881,1.22296,0.138221,-0.652683, + -0.660133,-0.325846,-0.676793,1.238464,0.027373,-0.624059, + -0.691037,-0.22774,-0.686005,1.278626,-0.049369,-0.633787, + -0.411811,-0.074302,-0.908235,1.329732,-0.022152,-0.670274, + -0.411811,-0.074302,-0.908235,1.329732,-0.022152,-0.670274, + -0.356146,-0.13643,-0.924417,1.280017,0.059132,-0.657894, + -0.660133,-0.325846,-0.676793,1.238464,0.027373,-0.624059, + -0.094492,0.118807,-0.988411,1.39106,0.010509,-0.682436, + -0.080719,0.04088,-0.995898,1.329879,0.097243,-0.669172, + -0.356146,-0.13643,-0.924417,1.280017,0.059132,-0.657894, + -0.094492,0.118807,-0.988411,1.39106,0.010509,-0.682436, + -0.356146,-0.13643,-0.924417,1.280017,0.059132,-0.657894, + -0.411811,-0.074302,-0.908235,1.329732,-0.022152,-0.670274, + -0.080719,0.04088,-0.995898,1.329879,0.097243,-0.669172, + 0.003001,-0.001255,-0.999995,1.261509,0.18365,-0.663589, + -0.293198,-0.238286,-0.925881,1.22296,0.138221,-0.652683, + -0.293198,-0.238286,-0.925881,1.22296,0.138221,-0.652683, + -0.356146,-0.13643,-0.924417,1.280017,0.059132,-0.657894, + -0.080719,0.04088,-0.995898,1.329879,0.097243,-0.669172, + -0.693597,-0.068529,-0.717096,1.333479,-0.188456,-0.659921, + -0.736772,-0.170063,-0.654405,1.310553,-0.12345,-0.646592, + -0.904992,-0.260217,-0.336566,1.274453,-0.137904,-0.579959, + -0.693597,-0.068529,-0.717096,1.333479,-0.188456,-0.659921, + -0.904992,-0.260217,-0.336566,1.274453,-0.137904,-0.579959, + -0.932432,-0.178414,-0.314228,1.292609,-0.201797,-0.58723, + -0.736772,-0.170063,-0.654405,1.310553,-0.12345,-0.646592, + -0.691037,-0.22774,-0.686005,1.278626,-0.049369,-0.633787, + -0.880661,-0.339398,-0.330522,1.247962,-0.0657,-0.572975, + -0.880661,-0.339398,-0.330522,1.247962,-0.0657,-0.572975, + -0.904992,-0.260217,-0.336566,1.274453,-0.137904,-0.579959, + -0.736772,-0.170063,-0.654405,1.310553,-0.12345,-0.646592, + -0.934966,-0.354738,0,1.237741,-0.071143,-0.5, + -0.960468,-0.278392,0,1.262419,-0.142723,-0.5, + -0.904992,-0.260217,-0.336566,1.274453,-0.137904,-0.579959, + -0.934966,-0.354738,0,1.237741,-0.071143,-0.5, + -0.904992,-0.260217,-0.336566,1.274453,-0.137904,-0.579959, + -0.880661,-0.339398,-0.330522,1.247962,-0.0657,-0.572975, + -0.960468,-0.278392,0,1.262419,-0.142723,-0.5, + -0.977953,-0.208824,0,1.278985,-0.206245,-0.5, + -0.932432,-0.178414,-0.314228,1.292609,-0.201797,-0.58723, + -0.932432,-0.178414,-0.314228,1.292609,-0.201797,-0.58723, + -0.904992,-0.260217,-0.336566,1.274453,-0.137904,-0.579959, + -0.960468,-0.278392,0,1.262419,-0.142723,-0.5, + -0.660133,-0.325846,-0.676793,1.238464,0.027373,-0.624059, + -0.591819,-0.448047,-0.670078,1.190836,0.100363,-0.619965, + -0.769835,-0.555714,-0.313903,1.171562,0.077649,-0.565436, + -0.769835,-0.555714,-0.313903,1.171562,0.077649,-0.565436, + -0.841533,-0.433873,-0.321832,1.213533,0.008318,-0.567669, + -0.660133,-0.325846,-0.676793,1.238464,0.027373,-0.624059, + -0.831075,-0.55616,0,1.165137,0.070077,-0.5, + -0.896641,-0.442758,0,1.205222,0.001966,-0.5, + -0.841533,-0.433873,-0.321832,1.213533,0.008318,-0.567669, + -0.831075,-0.55616,0,1.165137,0.070077,-0.5, + -0.841533,-0.433873,-0.321832,1.213533,0.008318,-0.567669, + -0.769835,-0.555714,-0.313903,1.171562,0.077649,-0.565436, + -0.896641,-0.442758,0,1.205222,0.001966,-0.5, + -0.934966,-0.354738,0,1.237741,-0.071143,-0.5, + -0.880661,-0.339398,-0.330522,1.247962,-0.0657,-0.572975, + -0.880661,-0.339398,-0.330522,1.247962,-0.0657,-0.572975, + -0.841533,-0.433873,-0.321832,1.213533,0.008318,-0.567669, + -0.896641,-0.442758,0,1.205222,0.001966,-0.5, + -0.841533,-0.433873,-0.321832,1.213533,0.008318,-0.567669, + -0.880661,-0.339398,-0.330522,1.247962,-0.0657,-0.572975, + -0.691037,-0.22774,-0.686005,1.278626,-0.049369,-0.633787, + -0.691037,-0.22774,-0.686005,1.278626,-0.049369,-0.633787, + -0.660133,-0.325846,-0.676793,1.238464,0.027373,-0.624059, + -0.841533,-0.433873,-0.321832,1.213533,0.008318,-0.567669, + -0.769835,-0.555714,0.313903,1.171562,0.077649,-0.434564, + -0.591819,-0.448047,0.670078,1.190836,0.100363,-0.380035, + -0.660133,-0.325846,0.676793,1.238464,0.027373,-0.375941, + -0.660133,-0.325846,0.676793,1.238464,0.027373,-0.375941, + -0.841533,-0.433873,0.321832,1.213533,0.008318,-0.432331, + -0.769835,-0.555714,0.313903,1.171562,0.077649,-0.434564, + -0.841533,-0.433873,0.321832,1.213533,0.008318,-0.432331, + -0.660133,-0.325846,0.676793,1.238464,0.027373,-0.375941, + -0.691037,-0.22774,0.686005,1.278626,-0.049369,-0.366213, + -0.691037,-0.22774,0.686005,1.278626,-0.049369,-0.366213, + -0.880661,-0.339398,0.330522,1.247962,-0.0657,-0.427025, + -0.841533,-0.433873,0.321832,1.213533,0.008318,-0.432331, + -0.880661,-0.339398,0.330522,1.247962,-0.0657,-0.427025, + -0.934966,-0.354738,0,1.237741,-0.071143,-0.5, + -0.896641,-0.442758,0,1.205222,0.001966,-0.5, + -0.896641,-0.442758,0,1.205222,0.001966,-0.5, + -0.841533,-0.433873,0.321832,1.213533,0.008318,-0.432331, + -0.880661,-0.339398,0.330522,1.247962,-0.0657,-0.427025, + -0.831075,-0.55616,0,1.165137,0.070077,-0.5, + -0.769835,-0.555714,0.313903,1.171562,0.077649,-0.434564, + -0.841533,-0.433873,0.321832,1.213533,0.008318,-0.432331, + -0.831075,-0.55616,0,1.165137,0.070077,-0.5, + -0.841533,-0.433873,0.321832,1.213533,0.008318,-0.432331, + -0.896641,-0.442758,0,1.205222,0.001966,-0.5, + -0.693597,-0.068529,0.717096,1.333479,-0.188456,-0.340079, + -0.932432,-0.178414,0.314228,1.292609,-0.201797,-0.41277, + -0.904992,-0.260217,0.336566,1.274453,-0.137904,-0.420041, + -0.693597,-0.068529,0.717096,1.333479,-0.188456,-0.340079, + -0.904992,-0.260217,0.336566,1.274453,-0.137904,-0.420041, + -0.736772,-0.170063,0.654405,1.310553,-0.12345,-0.353408, + -0.932432,-0.178414,0.314228,1.292609,-0.201797,-0.41277, + -0.977953,-0.208824,0,1.278985,-0.206245,-0.5, + -0.960468,-0.278392,0,1.262419,-0.142723,-0.5, + -0.960468,-0.278392,0,1.262419,-0.142723,-0.5, + -0.904992,-0.260217,0.336566,1.274453,-0.137904,-0.420041, + -0.932432,-0.178414,0.314228,1.292609,-0.201797,-0.41277, + -0.934966,-0.354738,0,1.237741,-0.071143,-0.5, + -0.880661,-0.339398,0.330522,1.247962,-0.0657,-0.427025, + -0.904992,-0.260217,0.336566,1.274453,-0.137904,-0.420041, + -0.934966,-0.354738,0,1.237741,-0.071143,-0.5, + -0.904992,-0.260217,0.336566,1.274453,-0.137904,-0.420041, + -0.960468,-0.278392,0,1.262419,-0.142723,-0.5, + -0.880661,-0.339398,0.330522,1.247962,-0.0657,-0.427025, + -0.691037,-0.22774,0.686005,1.278626,-0.049369,-0.366213, + -0.736772,-0.170063,0.654405,1.310553,-0.12345,-0.353408, + -0.736772,-0.170063,0.654405,1.310553,-0.12345,-0.353408, + -0.904992,-0.260217,0.336566,1.274453,-0.137904,-0.420041, + -0.880661,-0.339398,0.330522,1.247962,-0.0657,-0.427025, + -0.693597,-0.068529,0.717096,1.333479,-0.188456,-0.340079, + -0.736772,-0.170063,0.654405,1.310553,-0.12345,-0.353408, + -0.410607,0.007113,0.911785,1.370721,-0.099359,-0.313428, + -0.693597,-0.068529,0.717096,1.333479,-0.188456,-0.340079, + -0.410607,0.007113,0.911785,1.370721,-0.099359,-0.313428, + -0.356933,0.09138,0.92965,1.401596,-0.166219,-0.296464, + -0.691037,-0.22774,0.686005,1.278626,-0.049369,-0.366213, + -0.411811,-0.074302,0.908235,1.329732,-0.022152,-0.329726, + -0.410607,0.007113,0.911785,1.370721,-0.099359,-0.313428, + -0.691037,-0.22774,0.686005,1.278626,-0.049369,-0.366213, + -0.410607,0.007113,0.911785,1.370721,-0.099359,-0.313428, + -0.736772,-0.170063,0.654405,1.310553,-0.12345,-0.353408, + -0.094492,0.118807,0.988411,1.39106,0.010509,-0.317564, + -0.076935,0.189453,0.978871,1.442923,-0.07045,-0.300102, + -0.410607,0.007113,0.911785,1.370721,-0.099359,-0.313428, + -0.094492,0.118807,0.988411,1.39106,0.010509,-0.317564, + -0.410607,0.007113,0.911785,1.370721,-0.099359,-0.313428, + -0.411811,-0.074302,0.908235,1.329732,-0.022152,-0.329726, + -0.076935,0.189453,0.978871,1.442923,-0.07045,-0.300102, + -0.07755,0.232519,0.969495,1.483337,-0.139536,-0.281926, + -0.356933,0.09138,0.92965,1.401596,-0.166219,-0.296464, + -0.356933,0.09138,0.92965,1.401596,-0.166219,-0.296464, + -0.410607,0.007113,0.911785,1.370721,-0.099359,-0.313428, + -0.076935,0.189453,0.978871,1.442923,-0.07045,-0.300102, + -0.591819,-0.448047,0.670078,1.190836,0.100363,-0.380035, + -0.293197,-0.238286,0.925881,1.22296,0.138221,-0.347317, + -0.356146,-0.13643,0.924417,1.280017,0.059132,-0.342106, + -0.591819,-0.448047,0.670078,1.190836,0.100363,-0.380035, + -0.356146,-0.13643,0.924417,1.280017,0.059132,-0.342106, + -0.660133,-0.325846,0.676793,1.238464,0.027373,-0.375941, + -0.293197,-0.238286,0.925881,1.22296,0.138221,-0.347317, + 0.003001,-0.001255,0.999995,1.261509,0.18365,-0.336411, + -0.080719,0.04088,0.995898,1.329879,0.097243,-0.330828, + -0.080719,0.04088,0.995898,1.329879,0.097243,-0.330828, + -0.356146,-0.13643,0.924417,1.280017,0.059132,-0.342106, + -0.293197,-0.238286,0.925881,1.22296,0.138221,-0.347317, + -0.094492,0.118807,0.988411,1.39106,0.010509,-0.317564, + -0.411811,-0.074302,0.908235,1.329732,-0.022152,-0.329726, + -0.356146,-0.13643,0.924417,1.280017,0.059132,-0.342106, + -0.094492,0.118807,0.988411,1.39106,0.010509,-0.317564, + -0.356146,-0.13643,0.924417,1.280017,0.059132,-0.342106, + -0.080719,0.04088,0.995898,1.329879,0.097243,-0.330828, + -0.411811,-0.074302,0.908235,1.329732,-0.022152,-0.329726, + -0.691037,-0.22774,0.686005,1.278626,-0.049369,-0.366213, + -0.660133,-0.325846,0.676793,1.238464,0.027373,-0.375941, + -0.660133,-0.325846,0.676793,1.238464,0.027373,-0.375941, + -0.356146,-0.13643,0.924417,1.280017,0.059132,-0.342106, + -0.411811,-0.074302,0.908235,1.329732,-0.022152,-0.329726, + 0.284277,0.249093,0.925818,1.300058,0.22908,-0.347317, + 0.547232,0.498931,0.672016,1.332183,0.266938,-0.380035, + 0.509286,0.493808,0.704828,1.421294,0.167113,-0.375941, + 0.509286,0.493808,0.704828,1.421294,0.167113,-0.375941, + 0.192478,0.250599,0.948763,1.379742,0.135354,-0.342106, + 0.284277,0.249093,0.925818,1.300058,0.22908,-0.347317, + 0.509286,0.493808,0.704828,1.421294,0.167113,-0.375941, + 0.522827,0.522069,0.673866,1.503495,0.070388,-0.366213, + 0.227361,0.327503,0.917087,1.452388,0.04317,-0.329726, + 0.227361,0.327503,0.917087,1.452388,0.04317,-0.329726, + 0.192478,0.250599,0.948763,1.379742,0.135354,-0.342106, + 0.509286,0.493808,0.704828,1.421294,0.167113,-0.375941, + -0.094492,0.118807,0.988411,1.39106,0.010509,-0.317564, + -0.080719,0.04088,0.995898,1.329879,0.097243,-0.330828, + 0.192478,0.250599,0.948763,1.379742,0.135354,-0.342106, + -0.094492,0.118807,0.988411,1.39106,0.010509,-0.317564, + 0.192478,0.250599,0.948763,1.379742,0.135354,-0.342106, + 0.227361,0.327503,0.917087,1.452388,0.04317,-0.329726, + 0.003001,-0.001255,0.999995,1.261509,0.18365,-0.336411, + 0.284277,0.249093,0.925818,1.300058,0.22908,-0.347317, + 0.192478,0.250599,0.948763,1.379742,0.135354,-0.342106, + 0.003001,-0.001255,0.999995,1.261509,0.18365,-0.336411, + 0.192478,0.250599,0.948763,1.379742,0.135354,-0.342106, + -0.080719,0.04088,0.995898,1.329879,0.097243,-0.330828, + 0.523007,0.53259,0.665441,1.575292,-0.017451,-0.353408, + 0.523401,0.54123,0.65812,1.633195,-0.090616,-0.340079, + 0.223762,0.384639,0.895535,1.565078,-0.112852,-0.296464, + 0.223762,0.384639,0.895535,1.565078,-0.112852,-0.296464, + 0.22394,0.359067,0.906047,1.515124,-0.041541,-0.313428, + 0.523007,0.53259,0.665441,1.575292,-0.017451,-0.353408, + -0.07755,0.232519,0.969495,1.483337,-0.139536,-0.281926, + -0.076935,0.189453,0.978871,1.442923,-0.07045,-0.300102, + 0.22394,0.359067,0.906047,1.515124,-0.041541,-0.313428, + -0.07755,0.232519,0.969495,1.483337,-0.139536,-0.281926, + 0.22394,0.359067,0.906047,1.515124,-0.041541,-0.313428, + 0.223762,0.384639,0.895535,1.565078,-0.112852,-0.296464, + -0.076935,0.189453,0.978871,1.442923,-0.07045,-0.300102, + -0.094492,0.118807,0.988411,1.39106,0.010509,-0.317564, + 0.227361,0.327503,0.917087,1.452388,0.04317,-0.329726, + 0.227361,0.327503,0.917087,1.452388,0.04317,-0.329726, + 0.22394,0.359067,0.906047,1.515124,-0.041541,-0.313428, + -0.076935,0.189453,0.978871,1.442923,-0.07045,-0.300102, + 0.522827,0.522069,0.673866,1.503495,0.070388,-0.366213, + 0.523007,0.53259,0.665441,1.575292,-0.017451,-0.353408, + 0.22394,0.359067,0.906047,1.515124,-0.041541,-0.313428, + 0.522827,0.522069,0.673866,1.503495,0.070388,-0.366213, + 0.22394,0.359067,0.906047,1.515124,-0.041541,-0.313428, + 0.227361,0.327503,0.917087,1.452388,0.04317,-0.329726, + 0.709684,0.62897,0.317403,1.674065,-0.077274,-0.41277, + 0.523401,0.54123,0.65812,1.633195,-0.090616,-0.340079, + 0.523007,0.53259,0.665441,1.575292,-0.017451,-0.353408, + 0.523007,0.53259,0.665441,1.575292,-0.017451,-0.353408, + 0.706952,0.630412,0.320624,1.611392,-0.002996,-0.420041, + 0.709684,0.62897,0.317403,1.674065,-0.077274,-0.41277, + 0.522827,0.522069,0.673866,1.503495,0.070388,-0.366213, + 0.703,0.633573,0.323073,1.534158,0.086718,-0.427025, + 0.706952,0.630412,0.320624,1.611392,-0.002996,-0.420041, + 0.522827,0.522069,0.673866,1.503495,0.070388,-0.366213, + 0.706952,0.630412,0.320624,1.611392,-0.002996,-0.420041, + 0.523007,0.53259,0.665441,1.575292,-0.017451,-0.353408, + 0.703,0.633573,0.323073,1.534158,0.086718,-0.427025, + 0.747578,0.664174,0,1.54438,0.092162,-0.5, + 0.754132,0.656723,0,1.623426,0.001822,-0.5, + 0.754132,0.656723,0,1.623426,0.001822,-0.5, + 0.706952,0.630412,0.320624,1.611392,-0.002996,-0.420041, + 0.703,0.633573,0.323073,1.534158,0.086718,-0.427025, + 0.758437,0.651747,0,1.687689,-0.072827,-0.5, + 0.709684,0.62897,0.317403,1.674065,-0.077274,-0.41277, + 0.706952,0.630412,0.320624,1.611392,-0.002996,-0.420041, + 0.758437,0.651747,0,1.687689,-0.072827,-0.5, + 0.706952,0.630412,0.320624,1.611392,-0.002996,-0.420041, + 0.754132,0.656723,0,1.623426,0.001822,-0.5, + 0.547232,0.498931,0.672016,1.332183,0.266938,-0.380035, + 0.694102,0.647395,0.314805,1.351457,0.289652,-0.434564, + 0.698693,0.638817,0.32209,1.446226,0.186168,-0.432331, + 0.547232,0.498931,0.672016,1.332183,0.266938,-0.380035, + 0.698693,0.638817,0.32209,1.446226,0.186168,-0.432331, + 0.509286,0.493808,0.704828,1.421294,0.167113,-0.375941, + 0.694102,0.647395,0.314805,1.351457,0.289652,-0.434564, + 0.726158,0.687528,0,1.357882,0.297224,-0.5, + 0.738573,0.674173,0,1.454536,0.19252,-0.5, + 0.738573,0.674173,0,1.454536,0.19252,-0.5, + 0.698693,0.638817,0.32209,1.446226,0.186168,-0.432331, + 0.694102,0.647395,0.314805,1.351457,0.289652,-0.434564, + 0.747578,0.664174,0,1.54438,0.092162,-0.5, + 0.703,0.633573,0.323073,1.534158,0.086718,-0.427025, + 0.698693,0.638817,0.32209,1.446226,0.186168,-0.432331, + 0.747578,0.664174,0,1.54438,0.092162,-0.5, + 0.698693,0.638817,0.32209,1.446226,0.186168,-0.432331, + 0.738573,0.674173,0,1.454536,0.19252,-0.5, + 0.703,0.633573,0.323073,1.534158,0.086718,-0.427025, + 0.522827,0.522069,0.673866,1.503495,0.070388,-0.366213, + 0.509286,0.493808,0.704828,1.421294,0.167113,-0.375941, + 0.509286,0.493808,0.704828,1.421294,0.167113,-0.375941, + 0.698693,0.638817,0.32209,1.446226,0.186168,-0.432331, + 0.703,0.633573,0.323073,1.534158,0.086718,-0.427025, + 0.547232,0.498931,-0.672015,1.332183,0.266938,-0.619965, + 0.509286,0.493808,-0.704828,1.421294,0.167113,-0.624059, + 0.698693,0.638817,-0.32209,1.446226,0.186168,-0.567669, + 0.547232,0.498931,-0.672015,1.332183,0.266938,-0.619965, + 0.698693,0.638817,-0.32209,1.446226,0.186168,-0.567669, + 0.694102,0.647395,-0.314805,1.351457,0.289652,-0.565436, + 0.509286,0.493808,-0.704828,1.421294,0.167113,-0.624059, + 0.522827,0.522069,-0.673866,1.503495,0.070388,-0.633787, + 0.703,0.633573,-0.323073,1.534158,0.086718,-0.572975, + 0.703,0.633573,-0.323073,1.534158,0.086718,-0.572975, + 0.698693,0.638817,-0.32209,1.446226,0.186168,-0.567669, + 0.509286,0.493808,-0.704828,1.421294,0.167113,-0.624059, + 0.747578,0.664174,0,1.54438,0.092162,-0.5, + 0.738573,0.674173,0,1.454536,0.19252,-0.5, + 0.698693,0.638817,-0.32209,1.446226,0.186168,-0.567669, + 0.747578,0.664174,0,1.54438,0.092162,-0.5, + 0.698693,0.638817,-0.32209,1.446226,0.186168,-0.567669, + 0.703,0.633573,-0.323073,1.534158,0.086718,-0.572975, + 0.738573,0.674173,0,1.454536,0.19252,-0.5, + 0.726158,0.687528,0,1.357882,0.297224,-0.5, + 0.694102,0.647395,-0.314805,1.351457,0.289652,-0.565436, + 0.694102,0.647395,-0.314805,1.351457,0.289652,-0.565436, + 0.698693,0.638817,-0.32209,1.446226,0.186168,-0.567669, + 0.738573,0.674173,0,1.454536,0.19252,-0.5, + 0.523007,0.53259,-0.665441,1.575292,-0.017451,-0.646592, + 0.523401,0.54123,-0.65812,1.633195,-0.090616,-0.659921, + 0.709684,0.62897,-0.317403,1.674065,-0.077274,-0.58723, + 0.709684,0.62897,-0.317403,1.674065,-0.077274,-0.58723, + 0.706952,0.630412,-0.320624,1.611392,-0.002996,-0.579959, + 0.523007,0.53259,-0.665441,1.575292,-0.017451,-0.646592, + 0.758437,0.651747,0,1.687689,-0.072827,-0.5, + 0.754132,0.656723,0,1.623426,0.001822,-0.5, + 0.706952,0.630412,-0.320624,1.611392,-0.002996,-0.579959, + 0.758437,0.651747,0,1.687689,-0.072827,-0.5, + 0.706952,0.630412,-0.320624,1.611392,-0.002996,-0.579959, + 0.709684,0.62897,-0.317403,1.674065,-0.077274,-0.58723, + 0.754132,0.656723,0,1.623426,0.001822,-0.5, + 0.747578,0.664174,0,1.54438,0.092162,-0.5, + 0.703,0.633573,-0.323073,1.534158,0.086718,-0.572975, + 0.703,0.633573,-0.323073,1.534158,0.086718,-0.572975, + 0.706952,0.630412,-0.320624,1.611392,-0.002996,-0.579959, + 0.754132,0.656723,0,1.623426,0.001822,-0.5, + 0.522827,0.522069,-0.673866,1.503495,0.070388,-0.633787, + 0.523007,0.53259,-0.665441,1.575292,-0.017451,-0.646592, + 0.706952,0.630412,-0.320624,1.611392,-0.002996,-0.579959, + 0.522827,0.522069,-0.673866,1.503495,0.070388,-0.633787, + 0.706952,0.630412,-0.320624,1.611392,-0.002996,-0.579959, + 0.703,0.633573,-0.323073,1.534158,0.086718,-0.572975, + 0.523401,0.54123,0.65812,1.633195,-0.090616,-0.340079, + 0.709684,0.62897,0.317403,1.674065,-0.077274,-0.41277, + 0.765571,0.555064,0.325277,1.718314,-0.130413,-0.406608, + 0.523401,0.54123,0.65812,1.633195,-0.090616,-0.340079, + 0.765571,0.555064,0.325277,1.718314,-0.130413,-0.406608, + 0.58545,0.437052,0.682813,1.673712,-0.14332,-0.328782, + 0.709684,0.62897,0.317403,1.674065,-0.077274,-0.41277, + 0.758437,0.651747,0,1.687689,-0.072827,-0.5, + 0.798106,0.602517,0,1.733181,-0.12611,-0.5, + 0.798106,0.602517,0,1.733181,-0.12611,-0.5, + 0.765571,0.555064,0.325277,1.718314,-0.130413,-0.406608, + 0.709684,0.62897,0.317403,1.674065,-0.077274,-0.41277, + 0.990091,0.14043,0,1.755118,-0.163978,-0.5, + 0.911574,0.083749,0.402517,1.73961,-0.167898,-0.405277, + 0.765571,0.555064,0.325277,1.718314,-0.130413,-0.406608, + 0.990091,0.14043,0,1.755118,-0.163978,-0.5, + 0.765571,0.555064,0.325277,1.718314,-0.130413,-0.406608, + 0.798106,0.602517,0,1.733181,-0.12611,-0.5, + 0.911574,0.083749,0.402517,1.73961,-0.167898,-0.405277, + 0.722198,-0.015351,0.691516,1.693578,-0.180157,-0.326227, + 0.58545,0.437052,0.682813,1.673712,-0.14332,-0.328782, + 0.58545,0.437052,0.682813,1.673712,-0.14332,-0.328782, + 0.765571,0.555064,0.325277,1.718314,-0.130413,-0.406608, + 0.911574,0.083749,0.402517,1.73961,-0.167898,-0.405277, + 0.523401,0.54123,-0.65812,1.633195,-0.090616,-0.659921, + 0.58545,0.437052,-0.682813,1.673712,-0.14332,-0.671218, + 0.765571,0.555064,-0.325277,1.718314,-0.130413,-0.593392, + 0.523401,0.54123,-0.65812,1.633195,-0.090616,-0.659921, + 0.765571,0.555064,-0.325277,1.718314,-0.130413,-0.593392, + 0.709684,0.62897,-0.317403,1.674065,-0.077274,-0.58723, + 0.58545,0.437052,-0.682813,1.673712,-0.14332,-0.671218, + 0.722198,-0.015351,-0.691516,1.693578,-0.180157,-0.673773, + 0.911574,0.083749,-0.402516,1.73961,-0.167898,-0.594723, + 0.911574,0.083749,-0.402516,1.73961,-0.167898,-0.594723, + 0.765571,0.555064,-0.325277,1.718314,-0.130413,-0.593392, + 0.58545,0.437052,-0.682813,1.673712,-0.14332,-0.671218, + 0.990091,0.14043,0,1.755118,-0.163978,-0.5, + 0.798106,0.602517,0,1.733181,-0.12611,-0.5, + 0.765571,0.555064,-0.325277,1.718314,-0.130413,-0.593392, + 0.990091,0.14043,0,1.755118,-0.163978,-0.5, + 0.765571,0.555064,-0.325277,1.718314,-0.130413,-0.593392, + 0.911574,0.083749,-0.402516,1.73961,-0.167898,-0.594723, + 0.798106,0.602517,0,1.733181,-0.12611,-0.5, + 0.758437,0.651747,0,1.687689,-0.072827,-0.5, + 0.709684,0.62897,-0.317403,1.674065,-0.077274,-0.58723, + 0.709684,0.62897,-0.317403,1.674065,-0.077274,-0.58723, + 0.765571,0.555064,-0.325277,1.718314,-0.130413,-0.593392, + 0.798106,0.602517,0,1.733181,-0.12611,-0.5, + 0.442953,-0.878385,-0.179534,1.670754,-0.221475,-0.638667, + 0.43479,-0.894931,-0.100277,1.696988,-0.219088,-0.5825, + 0.746757,-0.63494,-0.198004,1.733426,-0.195216,-0.5875, + 0.442953,-0.878385,-0.179534,1.670754,-0.221475,-0.638667, + 0.746757,-0.63494,-0.198004,1.733426,-0.195216,-0.5875, + 0.633983,-0.622541,-0.458813,1.689524,-0.205721,-0.660875, + 0.487185,-0.873299,0,1.710058,-0.217878,-0.5, + 0.821423,-0.57032,0,1.748713,-0.192378,-0.5, + 0.746757,-0.63494,-0.198004,1.733426,-0.195216,-0.5875, + 0.487185,-0.873299,0,1.710058,-0.217878,-0.5, + 0.746757,-0.63494,-0.198004,1.733426,-0.195216,-0.5875, + 0.43479,-0.894931,-0.100277,1.696988,-0.219088,-0.5825, + 0.990091,0.14043,0,1.755118,-0.163978,-0.5, + 0.911574,0.083749,-0.402516,1.73961,-0.167898,-0.594723, + 0.746757,-0.63494,-0.198004,1.733426,-0.195216,-0.5875, + 0.990091,0.14043,0,1.755118,-0.163978,-0.5, + 0.746757,-0.63494,-0.198004,1.733426,-0.195216,-0.5875, + 0.821423,-0.57032,0,1.748713,-0.192378,-0.5, + 0.911574,0.083749,-0.402516,1.73961,-0.167898,-0.594723, + 0.722198,-0.015351,-0.691516,1.693578,-0.180157,-0.673773, + 0.633983,-0.622541,-0.458813,1.689524,-0.205721,-0.660875, + 0.633983,-0.622541,-0.458813,1.689524,-0.205721,-0.660875, + 0.746757,-0.63494,-0.198004,1.733426,-0.195216,-0.5875, + 0.911574,0.083749,-0.402516,1.73961,-0.167898,-0.594723, + 0.442953,-0.878385,0.179534,1.670754,-0.221475,-0.361333, + 0.633983,-0.62254,0.458813,1.689524,-0.205721,-0.339125, + 0.746757,-0.63494,0.198005,1.733426,-0.195216,-0.4125, + 0.442953,-0.878385,0.179534,1.670754,-0.221475,-0.361333, + 0.746757,-0.63494,0.198005,1.733426,-0.195216,-0.4125, + 0.43479,-0.894931,0.100278,1.696988,-0.219088,-0.4175, + 0.633983,-0.62254,0.458813,1.689524,-0.205721,-0.339125, + 0.722198,-0.015351,0.691516,1.693578,-0.180157,-0.326227, + 0.911574,0.083749,0.402517,1.73961,-0.167898,-0.405277, + 0.911574,0.083749,0.402517,1.73961,-0.167898,-0.405277, + 0.746757,-0.63494,0.198005,1.733426,-0.195216,-0.4125, + 0.633983,-0.62254,0.458813,1.689524,-0.205721,-0.339125, + 0.990091,0.14043,0,1.755118,-0.163978,-0.5, + 0.821423,-0.57032,0,1.748713,-0.192378,-0.5, + 0.746757,-0.63494,0.198005,1.733426,-0.195216,-0.4125, + 0.990091,0.14043,0,1.755118,-0.163978,-0.5, + 0.746757,-0.63494,0.198005,1.733426,-0.195216,-0.4125, + 0.911574,0.083749,0.402517,1.73961,-0.167898,-0.405277, + 0.487185,-0.873299,0,1.710058,-0.217878,-0.5, + 0.43479,-0.894931,0.100278,1.696988,-0.219088,-0.4175, + 0.746757,-0.63494,0.198005,1.733426,-0.195216,-0.4125, + 0.487185,-0.873299,0,1.710058,-0.217878,-0.5, + 0.746757,-0.63494,0.198005,1.733426,-0.195216,-0.4125, + 0.821423,-0.57032,0,1.748713,-0.192378,-0.5, + 0.523401,0.54123,-0.65812,1.633195,-0.090616,-0.659921, + 0.223762,0.38464,-0.895535,1.565078,-0.112852,-0.703536, + 0.256589,0.31723,-0.912977,1.599377,-0.164832,-0.717914, + 0.523401,0.54123,-0.65812,1.633195,-0.090616,-0.659921, + 0.256589,0.31723,-0.912977,1.599377,-0.164832,-0.717914, + 0.58545,0.437052,-0.682813,1.673712,-0.14332,-0.671218, + 0.223762,0.38464,-0.895535,1.565078,-0.112852,-0.703536, + -0.07755,0.232519,-0.969495,1.483337,-0.139536,-0.718074, + -0.053569,0.174234,-0.983246,1.510174,-0.190646,-0.73348, + -0.053569,0.174234,-0.983246,1.510174,-0.190646,-0.73348, + 0.256589,0.31723,-0.912977,1.599377,-0.164832,-0.717914, + 0.223762,0.38464,-0.895535,1.565078,-0.112852,-0.703536, + 0.100693,-0.274502,-0.9563,1.526344,-0.226473,-0.737495, + 0.442231,-0.107524,-0.890433,1.617509,-0.201252,-0.721479, + 0.256589,0.31723,-0.912977,1.599377,-0.164832,-0.717914, + 0.100693,-0.274502,-0.9563,1.526344,-0.226473,-0.737495, + 0.256589,0.31723,-0.912977,1.599377,-0.164832,-0.717914, + -0.053569,0.174234,-0.983246,1.510174,-0.190646,-0.73348, + 0.442231,-0.107524,-0.890433,1.617509,-0.201252,-0.721479, + 0.722198,-0.015351,-0.691516,1.693578,-0.180157,-0.673773, + 0.58545,0.437052,-0.682813,1.673712,-0.14332,-0.671218, + 0.58545,0.437052,-0.682813,1.673712,-0.14332,-0.671218, + 0.256589,0.31723,-0.912977,1.599377,-0.164832,-0.717914, + 0.442231,-0.107524,-0.890433,1.617509,-0.201252,-0.721479, + -0.693597,-0.068529,-0.717096,1.333479,-0.188456,-0.659921, + -0.738864,-0.111606,-0.664548,1.346635,-0.237972,-0.671218, + -0.39719,0.033721,-0.917117,1.420971,-0.21646,-0.717914, + -0.693597,-0.068529,-0.717096,1.333479,-0.188456,-0.659921, + -0.39719,0.033721,-0.917117,1.420971,-0.21646,-0.717914, + -0.356933,0.09138,-0.92965,1.401596,-0.166219,-0.703536, + -0.588534,-0.475384,-0.653941,1.358796,-0.271614,-0.673773, + -0.236076,-0.378114,-0.895152,1.435022,-0.251106,-0.721479, + -0.39719,0.033721,-0.917117,1.420971,-0.21646,-0.717914, + -0.588534,-0.475384,-0.653941,1.358796,-0.271614,-0.673773, + -0.39719,0.033721,-0.917117,1.420971,-0.21646,-0.717914, + -0.738864,-0.111606,-0.664548,1.346635,-0.237972,-0.671218, + -0.236076,-0.378114,-0.895152,1.435022,-0.251106,-0.721479, + 0.100693,-0.274502,-0.9563,1.526344,-0.226473,-0.737495, + -0.053569,0.174234,-0.983246,1.510174,-0.190646,-0.73348, + -0.053569,0.174234,-0.983246,1.510174,-0.190646,-0.73348, + -0.39719,0.033721,-0.917117,1.420971,-0.21646,-0.717914, + -0.236076,-0.378114,-0.895152,1.435022,-0.251106,-0.721479, + -0.07755,0.232519,-0.969495,1.483337,-0.139536,-0.718074, + -0.356933,0.09138,-0.92965,1.401596,-0.166219,-0.703536, + -0.39719,0.033721,-0.917117,1.420971,-0.21646,-0.717914, + -0.07755,0.232519,-0.969495,1.483337,-0.139536,-0.718074, + -0.39719,0.033721,-0.917117,1.420971,-0.21646,-0.717914, + -0.053569,0.174234,-0.983246,1.510174,-0.190646,-0.73348, + 0.055786,-0.978343,-0.199329,1.40287,-0.293254,-0.638667, + 0.155998,-0.969633,-0.18835,1.458284,-0.283049,-0.664625, + 0.03573,-0.852716,-0.521152,1.449927,-0.271179,-0.706, + 0.055786,-0.978343,-0.199329,1.40287,-0.293254,-0.638667, + 0.03573,-0.852716,-0.521152,1.449927,-0.271179,-0.706, + -0.175453,-0.874143,-0.452869,1.378738,-0.288996,-0.660875, + 0.25096,-0.936595,-0.244557,1.538546,-0.263835,-0.677562, + 0.205519,-0.76511,-0.61022,1.53476,-0.249706,-0.7215, + 0.03573,-0.852716,-0.521152,1.449927,-0.271179,-0.706, + 0.25096,-0.936595,-0.244557,1.538546,-0.263835,-0.677562, + 0.03573,-0.852716,-0.521152,1.449927,-0.271179,-0.706, + 0.155998,-0.969633,-0.18835,1.458284,-0.283049,-0.664625, + 0.100693,-0.274502,-0.9563,1.526344,-0.226473,-0.737495, + -0.236076,-0.378114,-0.895152,1.435022,-0.251106,-0.721479, + 0.03573,-0.852716,-0.521152,1.449927,-0.271179,-0.706, + 0.100693,-0.274502,-0.9563,1.526344,-0.226473,-0.737495, + 0.03573,-0.852716,-0.521152,1.449927,-0.271179,-0.706, + 0.205519,-0.76511,-0.61022,1.53476,-0.249706,-0.7215, + -0.236076,-0.378114,-0.895152,1.435022,-0.251106,-0.721479, + -0.588534,-0.475384,-0.653941,1.358796,-0.271614,-0.673773, + -0.175453,-0.874143,-0.452869,1.378738,-0.288996,-0.660875, + -0.175453,-0.874143,-0.452869,1.378738,-0.288996,-0.660875, + 0.03573,-0.852716,-0.521152,1.449927,-0.271179,-0.706, + -0.236076,-0.378114,-0.895152,1.435022,-0.251106,-0.721479, + 0.361333,-0.91087,-0.199385,1.617662,-0.240344,-0.664625, + 0.442953,-0.878385,-0.179534,1.670754,-0.221475,-0.638667, + 0.633983,-0.622541,-0.458813,1.689524,-0.205721,-0.660875, + 0.633983,-0.622541,-0.458813,1.689524,-0.205721,-0.660875, + 0.389599,-0.715498,-0.579893,1.618964,-0.225886,-0.706, + 0.361333,-0.91087,-0.199385,1.617662,-0.240344,-0.664625, + 0.633983,-0.622541,-0.458813,1.689524,-0.205721,-0.660875, + 0.722198,-0.015351,-0.691516,1.693578,-0.180157,-0.673773, + 0.442231,-0.107524,-0.890433,1.617509,-0.201252,-0.721479, + 0.442231,-0.107524,-0.890433,1.617509,-0.201252,-0.721479, + 0.389599,-0.715498,-0.579893,1.618964,-0.225886,-0.706, + 0.633983,-0.622541,-0.458813,1.689524,-0.205721,-0.660875, + 0.100693,-0.274502,-0.9563,1.526344,-0.226473,-0.737495, + 0.205519,-0.76511,-0.61022,1.53476,-0.249706,-0.7215, + 0.389599,-0.715498,-0.579893,1.618964,-0.225886,-0.706, + 0.100693,-0.274502,-0.9563,1.526344,-0.226473,-0.737495, + 0.389599,-0.715498,-0.579893,1.618964,-0.225886,-0.706, + 0.442231,-0.107524,-0.890433,1.617509,-0.201252,-0.721479, + 0.25096,-0.936595,-0.244557,1.538546,-0.263835,-0.677562, + 0.361333,-0.91087,-0.199385,1.617662,-0.240344,-0.664625, + 0.389599,-0.715498,-0.579893,1.618964,-0.225886,-0.706, + 0.25096,-0.936595,-0.244557,1.538546,-0.263835,-0.677562, + 0.389599,-0.715498,-0.579893,1.618964,-0.225886,-0.706, + 0.205519,-0.76511,-0.61022,1.53476,-0.249706,-0.7215, + -0.738864,-0.111606,-0.664548,1.346635,-0.237972,-0.671218, + -0.693597,-0.068529,-0.717096,1.333479,-0.188456,-0.659921, + -0.932432,-0.178414,-0.314228,1.292609,-0.201797,-0.58723, + -0.932432,-0.178414,-0.314228,1.292609,-0.201797,-0.58723, + -0.899118,-0.21787,-0.37963,1.302034,-0.25088,-0.593392, + -0.738864,-0.111606,-0.664548,1.346635,-0.237972,-0.671218, + -0.932432,-0.178414,-0.314228,1.292609,-0.201797,-0.58723, + -0.977953,-0.208824,0,1.278985,-0.206245,-0.5, + -0.972456,-0.233085,0,1.287166,-0.255182,-0.5, + -0.972456,-0.233085,0,1.287166,-0.255182,-0.5, + -0.899118,-0.21787,-0.37963,1.302034,-0.25088,-0.593392, + -0.932432,-0.178414,-0.314228,1.292609,-0.201797,-0.58723, + -0.972456,-0.233085,0,1.287166,-0.255182,-0.5, + -0.822459,-0.568824,0,1.297571,-0.288968,-0.5, + -0.77552,-0.569812,-0.271814,1.312921,-0.28446,-0.594723, + -0.77552,-0.569812,-0.271814,1.312921,-0.28446,-0.594723, + -0.899118,-0.21787,-0.37963,1.302034,-0.25088,-0.593392, + -0.972456,-0.233085,0,1.287166,-0.255182,-0.5, + -0.588534,-0.475384,-0.653941,1.358796,-0.271614,-0.673773, + -0.738864,-0.111606,-0.664548,1.346635,-0.237972,-0.671218, + -0.899118,-0.21787,-0.37963,1.302034,-0.25088,-0.593392, + -0.588534,-0.475384,-0.653941,1.358796,-0.271614,-0.673773, + -0.899118,-0.21787,-0.37963,1.302034,-0.25088,-0.593392, + -0.77552,-0.569812,-0.271814,1.312921,-0.28446,-0.594723, + -0.932432,-0.178414,0.314228,1.292609,-0.201797,-0.41277, + -0.693597,-0.068529,0.717096,1.333479,-0.188456,-0.340079, + -0.738864,-0.111606,0.664548,1.346635,-0.237972,-0.328782, + -0.738864,-0.111606,0.664548,1.346635,-0.237972,-0.328782, + -0.899119,-0.217869,0.37963,1.302034,-0.25088,-0.406608, + -0.932432,-0.178414,0.314228,1.292609,-0.201797,-0.41277, + -0.588534,-0.475383,0.653941,1.358796,-0.271614,-0.326227, + -0.775521,-0.569812,0.271814,1.312921,-0.28446,-0.405277, + -0.899119,-0.217869,0.37963,1.302034,-0.25088,-0.406608, + -0.588534,-0.475383,0.653941,1.358796,-0.271614,-0.326227, + -0.899119,-0.217869,0.37963,1.302034,-0.25088,-0.406608, + -0.738864,-0.111606,0.664548,1.346635,-0.237972,-0.328782, + -0.775521,-0.569812,0.271814,1.312921,-0.28446,-0.405277, + -0.822459,-0.568824,0,1.297571,-0.288968,-0.5, + -0.972456,-0.233085,0,1.287166,-0.255182,-0.5, + -0.972456,-0.233085,0,1.287166,-0.255182,-0.5, + -0.899119,-0.217869,0.37963,1.302034,-0.25088,-0.406608, + -0.775521,-0.569812,0.271814,1.312921,-0.28446,-0.405277, + -0.972456,-0.233085,0,1.287166,-0.255182,-0.5, + -0.977953,-0.208824,0,1.278985,-0.206245,-0.5, + -0.932432,-0.178414,0.314228,1.292609,-0.201797,-0.41277, + -0.932432,-0.178414,0.314228,1.292609,-0.201797,-0.41277, + -0.899119,-0.217869,0.37963,1.302034,-0.25088,-0.406608, + -0.972456,-0.233085,0,1.287166,-0.255182,-0.5, + 0.055786,-0.978344,0.199328,1.40287,-0.293254,-0.361333, + 0.070927,-0.992428,0.100277,1.378957,-0.304305,-0.4175, + -0.244016,-0.944635,0.219364,1.335465,-0.301849,-0.4125, + 0.055786,-0.978344,0.199328,1.40287,-0.293254,-0.361333, + -0.244016,-0.944635,0.219364,1.335465,-0.301849,-0.4125, + -0.175453,-0.874143,0.452869,1.378738,-0.288996,-0.339125, + 0.014735,-0.999891,0,1.367033,-0.309791,-0.5, + -0.433457,-0.901174,0,1.320807,-0.307035,-0.5, + -0.244016,-0.944635,0.219364,1.335465,-0.301849,-0.4125, + 0.014735,-0.999891,0,1.367033,-0.309791,-0.5, + -0.244016,-0.944635,0.219364,1.335465,-0.301849,-0.4125, + 0.070927,-0.992428,0.100277,1.378957,-0.304305,-0.4175, + -0.433457,-0.901174,0,1.320807,-0.307035,-0.5, + -0.822459,-0.568824,0,1.297571,-0.288968,-0.5, + -0.775521,-0.569812,0.271814,1.312921,-0.28446,-0.405277, + -0.775521,-0.569812,0.271814,1.312921,-0.28446,-0.405277, + -0.244016,-0.944635,0.219364,1.335465,-0.301849,-0.4125, + -0.433457,-0.901174,0,1.320807,-0.307035,-0.5, + -0.588534,-0.475383,0.653941,1.358796,-0.271614,-0.326227, + -0.175453,-0.874143,0.452869,1.378738,-0.288996,-0.339125, + -0.244016,-0.944635,0.219364,1.335465,-0.301849,-0.4125, + -0.588534,-0.475383,0.653941,1.358796,-0.271614,-0.326227, + -0.244016,-0.944635,0.219364,1.335465,-0.301849,-0.4125, + -0.775521,-0.569812,0.271814,1.312921,-0.28446,-0.405277, + 0.055786,-0.978343,-0.199329,1.40287,-0.293254,-0.638667, + -0.175453,-0.874143,-0.452869,1.378738,-0.288996,-0.660875, + -0.244016,-0.944635,-0.219364,1.335465,-0.301849,-0.5875, + 0.055786,-0.978343,-0.199329,1.40287,-0.293254,-0.638667, + -0.244016,-0.944635,-0.219364,1.335465,-0.301849,-0.5875, + 0.070927,-0.992428,-0.100277,1.378957,-0.304305,-0.5825, + -0.588534,-0.475384,-0.653941,1.358796,-0.271614,-0.673773, + -0.77552,-0.569812,-0.271814,1.312921,-0.28446,-0.594723, + -0.244016,-0.944635,-0.219364,1.335465,-0.301849,-0.5875, + -0.588534,-0.475384,-0.653941,1.358796,-0.271614,-0.673773, + -0.244016,-0.944635,-0.219364,1.335465,-0.301849,-0.5875, + -0.175453,-0.874143,-0.452869,1.378738,-0.288996,-0.660875, + -0.77552,-0.569812,-0.271814,1.312921,-0.28446,-0.594723, + -0.822459,-0.568824,0,1.297571,-0.288968,-0.5, + -0.433457,-0.901174,0,1.320807,-0.307035,-0.5, + -0.433457,-0.901174,0,1.320807,-0.307035,-0.5, + -0.244016,-0.944635,-0.219364,1.335465,-0.301849,-0.5875, + -0.77552,-0.569812,-0.271814,1.312921,-0.28446,-0.594723, + 0.014735,-0.999891,0,1.367033,-0.309791,-0.5, + 0.070927,-0.992428,-0.100277,1.378957,-0.304305,-0.5825, + -0.244016,-0.944635,-0.219364,1.335465,-0.301849,-0.5875, + 0.014735,-0.999891,0,1.367033,-0.309791,-0.5, + -0.244016,-0.944635,-0.219364,1.335465,-0.301849,-0.5875, + -0.433457,-0.901174,0,1.320807,-0.307035,-0.5, + -0.693597,-0.068529,0.717096,1.333479,-0.188456,-0.340079, + -0.356933,0.09138,0.92965,1.401596,-0.166219,-0.296464, + -0.39719,0.033722,0.917117,1.420971,-0.21646,-0.282086, + -0.693597,-0.068529,0.717096,1.333479,-0.188456,-0.340079, + -0.39719,0.033722,0.917117,1.420971,-0.21646,-0.282086, + -0.738864,-0.111606,0.664548,1.346635,-0.237972,-0.328782, + -0.07755,0.232519,0.969495,1.483337,-0.139536,-0.281926, + -0.053569,0.174235,0.983246,1.510174,-0.190646,-0.26652, + -0.39719,0.033722,0.917117,1.420971,-0.21646,-0.282086, + -0.07755,0.232519,0.969495,1.483337,-0.139536,-0.281926, + -0.39719,0.033722,0.917117,1.420971,-0.21646,-0.282086, + -0.356933,0.09138,0.92965,1.401596,-0.166219,-0.296464, + -0.053569,0.174235,0.983246,1.510174,-0.190646,-0.26652, + 0.100693,-0.274502,0.9563,1.526344,-0.226473,-0.262505, + -0.236076,-0.378113,0.895153,1.435022,-0.251106,-0.278521, + -0.236076,-0.378113,0.895153,1.435022,-0.251106,-0.278521, + -0.39719,0.033722,0.917117,1.420971,-0.21646,-0.282086, + -0.053569,0.174235,0.983246,1.510174,-0.190646,-0.26652, + -0.588534,-0.475383,0.653941,1.358796,-0.271614,-0.326227, + -0.738864,-0.111606,0.664548,1.346635,-0.237972,-0.328782, + -0.39719,0.033722,0.917117,1.420971,-0.21646,-0.282086, + -0.588534,-0.475383,0.653941,1.358796,-0.271614,-0.326227, + -0.39719,0.033722,0.917117,1.420971,-0.21646,-0.282086, + -0.236076,-0.378113,0.895153,1.435022,-0.251106,-0.278521, + 0.523401,0.54123,0.65812,1.633195,-0.090616,-0.340079, + 0.58545,0.437052,0.682813,1.673712,-0.14332,-0.328782, + 0.256589,0.31723,0.912977,1.599377,-0.164832,-0.282086, + 0.523401,0.54123,0.65812,1.633195,-0.090616,-0.340079, + 0.256589,0.31723,0.912977,1.599377,-0.164832,-0.282086, + 0.223762,0.384639,0.895535,1.565078,-0.112852,-0.296464, + 0.58545,0.437052,0.682813,1.673712,-0.14332,-0.328782, + 0.722198,-0.015351,0.691516,1.693578,-0.180157,-0.326227, + 0.442231,-0.107524,0.890433,1.617509,-0.201252,-0.278521, + 0.442231,-0.107524,0.890433,1.617509,-0.201252,-0.278521, + 0.256589,0.31723,0.912977,1.599377,-0.164832,-0.282086, + 0.58545,0.437052,0.682813,1.673712,-0.14332,-0.328782, + 0.100693,-0.274502,0.9563,1.526344,-0.226473,-0.262505, + -0.053569,0.174235,0.983246,1.510174,-0.190646,-0.26652, + 0.256589,0.31723,0.912977,1.599377,-0.164832,-0.282086, + 0.100693,-0.274502,0.9563,1.526344,-0.226473,-0.262505, + 0.256589,0.31723,0.912977,1.599377,-0.164832,-0.282086, + 0.442231,-0.107524,0.890433,1.617509,-0.201252,-0.278521, + -0.053569,0.174235,0.983246,1.510174,-0.190646,-0.26652, + -0.07755,0.232519,0.969495,1.483337,-0.139536,-0.281926, + 0.223762,0.384639,0.895535,1.565078,-0.112852,-0.296464, + 0.223762,0.384639,0.895535,1.565078,-0.112852,-0.296464, + 0.256589,0.31723,0.912977,1.599377,-0.164832,-0.282086, + -0.053569,0.174235,0.983246,1.510174,-0.190646,-0.26652, + 0.633983,-0.62254,0.458813,1.689524,-0.205721,-0.339125, + 0.442953,-0.878385,0.179534,1.670754,-0.221475,-0.361333, + 0.361333,-0.91087,0.199385,1.617662,-0.240344,-0.335375, + 0.361333,-0.91087,0.199385,1.617662,-0.240344,-0.335375, + 0.389599,-0.715497,0.579893,1.618964,-0.225886,-0.294, + 0.633983,-0.62254,0.458813,1.689524,-0.205721,-0.339125, + 0.25096,-0.936595,0.244557,1.538546,-0.263835,-0.322437, + 0.205519,-0.76511,0.610221,1.53476,-0.249706,-0.2785, + 0.389599,-0.715497,0.579893,1.618964,-0.225886,-0.294, + 0.25096,-0.936595,0.244557,1.538546,-0.263835,-0.322437, + 0.389599,-0.715497,0.579893,1.618964,-0.225886,-0.294, + 0.361333,-0.91087,0.199385,1.617662,-0.240344,-0.335375, + 0.100693,-0.274502,0.9563,1.526344,-0.226473,-0.262505, + 0.442231,-0.107524,0.890433,1.617509,-0.201252,-0.278521, + 0.389599,-0.715497,0.579893,1.618964,-0.225886,-0.294, + 0.100693,-0.274502,0.9563,1.526344,-0.226473,-0.262505, + 0.389599,-0.715497,0.579893,1.618964,-0.225886,-0.294, + 0.205519,-0.76511,0.610221,1.53476,-0.249706,-0.2785, + 0.442231,-0.107524,0.890433,1.617509,-0.201252,-0.278521, + 0.722198,-0.015351,0.691516,1.693578,-0.180157,-0.326227, + 0.633983,-0.62254,0.458813,1.689524,-0.205721,-0.339125, + 0.633983,-0.62254,0.458813,1.689524,-0.205721,-0.339125, + 0.389599,-0.715497,0.579893,1.618964,-0.225886,-0.294, + 0.442231,-0.107524,0.890433,1.617509,-0.201252,-0.278521, + 0.055786,-0.978344,0.199328,1.40287,-0.293254,-0.361333, + -0.175453,-0.874143,0.452869,1.378738,-0.288996,-0.339125, + 0.03573,-0.852716,0.521152,1.449927,-0.271179,-0.294, + 0.055786,-0.978344,0.199328,1.40287,-0.293254,-0.361333, + 0.03573,-0.852716,0.521152,1.449927,-0.271179,-0.294, + 0.155998,-0.969634,0.188349,1.458284,-0.283049,-0.335375, + -0.175453,-0.874143,0.452869,1.378738,-0.288996,-0.339125, + -0.588534,-0.475383,0.653941,1.358796,-0.271614,-0.326227, + -0.236076,-0.378113,0.895153,1.435022,-0.251106,-0.278521, + -0.236076,-0.378113,0.895153,1.435022,-0.251106,-0.278521, + 0.03573,-0.852716,0.521152,1.449927,-0.271179,-0.294, + -0.175453,-0.874143,0.452869,1.378738,-0.288996,-0.339125, + 0.100693,-0.274502,0.9563,1.526344,-0.226473,-0.262505, + 0.205519,-0.76511,0.610221,1.53476,-0.249706,-0.2785, + 0.03573,-0.852716,0.521152,1.449927,-0.271179,-0.294, + 0.100693,-0.274502,0.9563,1.526344,-0.226473,-0.262505, + 0.03573,-0.852716,0.521152,1.449927,-0.271179,-0.294, + -0.236076,-0.378113,0.895153,1.435022,-0.251106,-0.278521, + 0.25096,-0.936595,0.244557,1.538546,-0.263835,-0.322437, + 0.155998,-0.969634,0.188349,1.458284,-0.283049,-0.335375, + 0.03573,-0.852716,0.521152,1.449927,-0.271179,-0.294, + 0.25096,-0.936595,0.244557,1.538546,-0.263835,-0.322437, + 0.03573,-0.852716,0.521152,1.449927,-0.271179,-0.294, + 0.205519,-0.76511,0.610221,1.53476,-0.249706,-0.2785, + 0.442953,-0.878385,-0.179534,1.670754,-0.221475,-0.638667, + 0.361333,-0.91087,-0.199385,1.617662,-0.240344,-0.664625, + 0.33419,-0.939127,-0.079739,1.627523,-0.246239,-0.5905, + 0.442953,-0.878385,-0.179534,1.670754,-0.221475,-0.638667, + 0.33419,-0.939127,-0.079739,1.627523,-0.246239,-0.5905, + 0.43479,-0.894931,-0.100277,1.696988,-0.219088,-0.5825, + 0.361333,-0.91087,-0.199385,1.617662,-0.240344,-0.664625, + 0.25096,-0.936595,-0.244557,1.538546,-0.263835,-0.677562, + 0.257883,-0.962433,-0.08496,1.540826,-0.272345,-0.59775, + 0.257883,-0.962433,-0.08496,1.540826,-0.272345,-0.59775, + 0.33419,-0.939127,-0.079739,1.627523,-0.246239,-0.5905, + 0.361333,-0.91087,-0.199385,1.617662,-0.240344,-0.664625, + 0.258819,-0.965926,0,1.54159,-0.275196,-0.5, + 0.339948,-0.940444,0,1.635245,-0.247046,-0.5, + 0.33419,-0.939127,-0.079739,1.627523,-0.246239,-0.5905, + 0.258819,-0.965926,0,1.54159,-0.275196,-0.5, + 0.33419,-0.939127,-0.079739,1.627523,-0.246239,-0.5905, + 0.257883,-0.962433,-0.08496,1.540826,-0.272345,-0.59775, + 0.339948,-0.940444,0,1.635245,-0.247046,-0.5, + 0.487185,-0.873299,0,1.710058,-0.217878,-0.5, + 0.43479,-0.894931,-0.100277,1.696988,-0.219088,-0.5825, + 0.43479,-0.894931,-0.100277,1.696988,-0.219088,-0.5825, + 0.33419,-0.939127,-0.079739,1.627523,-0.246239,-0.5905, + 0.339948,-0.940444,0,1.635245,-0.247046,-0.5, + 0.055786,-0.978343,-0.199329,1.40287,-0.293254,-0.638667, + 0.070927,-0.992428,-0.100277,1.378957,-0.304305,-0.5825, + 0.180146,-0.980403,-0.079739,1.452691,-0.293085,-0.5905, + 0.055786,-0.978343,-0.199329,1.40287,-0.293254,-0.638667, + 0.180146,-0.980403,-0.079739,1.452691,-0.293085,-0.5905, + 0.155998,-0.969633,-0.18835,1.458284,-0.283049,-0.664625, + 0.070927,-0.992428,-0.100277,1.378957,-0.304305,-0.5825, + 0.014735,-0.999891,0,1.367033,-0.309791,-0.5, + 0.175818,-0.984423,0,1.446407,-0.297645,-0.5, + 0.175818,-0.984423,0,1.446407,-0.297645,-0.5, + 0.180146,-0.980403,-0.079739,1.452691,-0.293085,-0.5905, + 0.070927,-0.992428,-0.100277,1.378957,-0.304305,-0.5825, + 0.258819,-0.965926,0,1.54159,-0.275196,-0.5, + 0.257883,-0.962433,-0.08496,1.540826,-0.272345,-0.59775, + 0.180146,-0.980403,-0.079739,1.452691,-0.293085,-0.5905, + 0.258819,-0.965926,0,1.54159,-0.275196,-0.5, + 0.180146,-0.980403,-0.079739,1.452691,-0.293085,-0.5905, + 0.175818,-0.984423,0,1.446407,-0.297645,-0.5, + 0.257883,-0.962433,-0.08496,1.540826,-0.272345,-0.59775, + 0.25096,-0.936595,-0.244557,1.538546,-0.263835,-0.677562, + 0.155998,-0.969633,-0.18835,1.458284,-0.283049,-0.664625, + 0.155998,-0.969633,-0.18835,1.458284,-0.283049,-0.664625, + 0.180146,-0.980403,-0.079739,1.452691,-0.293085,-0.5905, + 0.257883,-0.962433,-0.08496,1.540826,-0.272345,-0.59775, + 0.055786,-0.978344,0.199328,1.40287,-0.293254,-0.361333, + 0.155998,-0.969634,0.188349,1.458284,-0.283049,-0.335375, + 0.180146,-0.980403,0.079739,1.452691,-0.293085,-0.4095, + 0.055786,-0.978344,0.199328,1.40287,-0.293254,-0.361333, + 0.180146,-0.980403,0.079739,1.452691,-0.293085,-0.4095, + 0.070927,-0.992428,0.100277,1.378957,-0.304305,-0.4175, + 0.155998,-0.969634,0.188349,1.458284,-0.283049,-0.335375, + 0.25096,-0.936595,0.244557,1.538546,-0.263835,-0.322437, + 0.257883,-0.962433,0.08496,1.540826,-0.272345,-0.40225, + 0.257883,-0.962433,0.08496,1.540826,-0.272345,-0.40225, + 0.180146,-0.980403,0.079739,1.452691,-0.293085,-0.4095, + 0.155998,-0.969634,0.188349,1.458284,-0.283049,-0.335375, + 0.258819,-0.965926,0,1.54159,-0.275196,-0.5, + 0.175818,-0.984423,0,1.446407,-0.297645,-0.5, + 0.180146,-0.980403,0.079739,1.452691,-0.293085,-0.4095, + 0.258819,-0.965926,0,1.54159,-0.275196,-0.5, + 0.180146,-0.980403,0.079739,1.452691,-0.293085,-0.4095, + 0.257883,-0.962433,0.08496,1.540826,-0.272345,-0.40225, + 0.175818,-0.984423,0,1.446407,-0.297645,-0.5, + 0.014735,-0.999891,0,1.367033,-0.309791,-0.5, + 0.070927,-0.992428,0.100277,1.378957,-0.304305,-0.4175, + 0.070927,-0.992428,0.100277,1.378957,-0.304305,-0.4175, + 0.180146,-0.980403,0.079739,1.452691,-0.293085,-0.4095, + 0.175818,-0.984423,0,1.446407,-0.297645,-0.5, + 0.442953,-0.878385,0.179534,1.670754,-0.221475,-0.361333, + 0.43479,-0.894931,0.100278,1.696988,-0.219088,-0.4175, + 0.33419,-0.939126,0.079739,1.627523,-0.246239,-0.4095, + 0.442953,-0.878385,0.179534,1.670754,-0.221475,-0.361333, + 0.33419,-0.939126,0.079739,1.627523,-0.246239,-0.4095, + 0.361333,-0.91087,0.199385,1.617662,-0.240344,-0.335375, + 0.43479,-0.894931,0.100278,1.696988,-0.219088,-0.4175, + 0.487185,-0.873299,0,1.710058,-0.217878,-0.5, + 0.339948,-0.940444,0,1.635245,-0.247046,-0.5, + 0.339948,-0.940444,0,1.635245,-0.247046,-0.5, + 0.33419,-0.939126,0.079739,1.627523,-0.246239,-0.4095, + 0.43479,-0.894931,0.100278,1.696988,-0.219088,-0.4175, + 0.258819,-0.965926,0,1.54159,-0.275196,-0.5, + 0.257883,-0.962433,0.08496,1.540826,-0.272345,-0.40225, + 0.33419,-0.939126,0.079739,1.627523,-0.246239,-0.4095, + 0.258819,-0.965926,0,1.54159,-0.275196,-0.5, + 0.33419,-0.939126,0.079739,1.627523,-0.246239,-0.4095, + 0.339948,-0.940444,0,1.635245,-0.247046,-0.5, + 0.257883,-0.962433,0.08496,1.540826,-0.272345,-0.40225, + 0.25096,-0.936595,0.244557,1.538546,-0.263835,-0.322437, + 0.361333,-0.91087,0.199385,1.617662,-0.240344,-0.335375, + 0.361333,-0.91087,0.199385,1.617662,-0.240344,-0.335375, + 0.33419,-0.939126,0.079739,1.627523,-0.246239,-0.4095, + 0.257883,-0.962433,0.08496,1.540826,-0.272345,-0.40225, +}; +static const struct gllist frame={GL_N3F_V3F,GL_TRIANGLES,1728,data,NULL}; +const struct gllist *s1_5=&frame; diff --git a/hacks/glx/s1_6.c b/hacks/glx/s1_6.c new file mode 100644 index 00000000..bf2490e1 --- /dev/null +++ b/hacks/glx/s1_6.c @@ -0,0 +1,1733 @@ +#include "gllist.h" +static const float data[]={ + 0.710152,0.225044,-0.667113,1.437472,0.482703,-0.67159, + 0.751095,0.142007,-0.644741,1.460394,0.412133,-0.660849, + 0.922813,0.236109,-0.304415,1.492239,0.440457,-0.587736, + 0.922813,0.236109,-0.304415,1.492239,0.440457,-0.587736, + 0.888327,0.330007,-0.319329,1.470529,0.515074,-0.593594, + 0.710152,0.225044,-0.667113,1.437472,0.482703,-0.67159, + 0.964484,0.264141,0,1.502855,0.449898,-0.5, + 0.923004,0.384789,0,1.481548,0.525864,-0.5, + 0.888327,0.330007,-0.319329,1.470529,0.515074,-0.593594, + 0.964484,0.264141,0,1.502855,0.449898,-0.5, + 0.888327,0.330007,-0.319329,1.470529,0.515074,-0.593594, + 0.922813,0.236109,-0.304415,1.492239,0.440457,-0.587736, + 0.923004,0.384789,0,1.481548,0.525864,-0.5, + 0.551211,0.834366,0,1.460683,0.568581,-0.5, + 0.590668,0.729279,-0.345345,1.449724,0.55695,-0.594774, + 0.590668,0.729279,-0.345345,1.449724,0.55695,-0.594774, + 0.888327,0.330007,-0.319329,1.470529,0.515074,-0.593594, + 0.923004,0.384789,0,1.481548,0.525864,-0.5, + 0.478093,0.57114,-0.667253,1.416649,0.522728,-0.673866, + 0.710152,0.225044,-0.667113,1.437472,0.482703,-0.67159, + 0.888327,0.330007,-0.319329,1.470529,0.515074,-0.593594, + 0.478093,0.57114,-0.667253,1.416649,0.522728,-0.673866, + 0.888327,0.330007,-0.319329,1.470529,0.515074,-0.593594, + 0.590668,0.729279,-0.345345,1.449724,0.55695,-0.594774, + 0.922813,0.236109,0.304415,1.492239,0.440457,-0.412264, + 0.751095,0.142007,0.644741,1.460394,0.412133,-0.339151, + 0.710152,0.225044,0.667112,1.437472,0.482703,-0.32841, + 0.710152,0.225044,0.667112,1.437472,0.482703,-0.32841, + 0.888327,0.330007,0.319329,1.470529,0.515074,-0.406406, + 0.922813,0.236109,0.304415,1.492239,0.440457,-0.412264, + 0.478094,0.57114,0.667253,1.416649,0.522728,-0.326134, + 0.590668,0.729279,0.345345,1.449724,0.55695,-0.405226, + 0.888327,0.330007,0.319329,1.470529,0.515074,-0.406406, + 0.478094,0.57114,0.667253,1.416649,0.522728,-0.326134, + 0.888327,0.330007,0.319329,1.470529,0.515074,-0.406406, + 0.710152,0.225044,0.667112,1.437472,0.482703,-0.32841, + 0.590668,0.729279,0.345345,1.449724,0.55695,-0.405226, + 0.551211,0.834366,0,1.460683,0.568581,-0.5, + 0.923004,0.384789,0,1.481548,0.525864,-0.5, + 0.923004,0.384789,0,1.481548,0.525864,-0.5, + 0.888327,0.330007,0.319329,1.470529,0.515074,-0.406406, + 0.590668,0.729279,0.345345,1.449724,0.55695,-0.405226, + 0.964484,0.264141,0,1.502855,0.449898,-0.5, + 0.922813,0.236109,0.304415,1.492239,0.440457,-0.412264, + 0.888327,0.330007,0.319329,1.470529,0.515074,-0.406406, + 0.964484,0.264141,0,1.502855,0.449898,-0.5, + 0.888327,0.330007,0.319329,1.470529,0.515074,-0.406406, + 0.923004,0.384789,0,1.481548,0.525864,-0.5, + -0.553505,0.813265,0.179534,1.370035,0.524394,-0.361333, + -0.571934,0.814147,0.100277,1.384841,0.546182,-0.4175, + -0.169784,0.964201,0.20369,1.423386,0.566478,-0.4125, + -0.553505,0.813265,0.179534,1.370035,0.524394,-0.361333, + -0.169784,0.964201,0.20369,1.423386,0.566478,-0.4125, + -0.216141,0.855174,0.471127,1.392914,0.533174,-0.339125, + -0.527613,0.849485,0,1.392236,0.557026,-0.5, + -0.070011,0.997546,0,1.433279,0.578472,-0.5, + -0.169784,0.964201,0.20369,1.423386,0.566478,-0.4125, + -0.527613,0.849485,0,1.392236,0.557026,-0.5, + -0.169784,0.964201,0.20369,1.423386,0.566478,-0.4125, + -0.571934,0.814147,0.100277,1.384841,0.546182,-0.4175, + 0.551211,0.834366,0,1.460683,0.568581,-0.5, + 0.590668,0.729279,0.345345,1.449724,0.55695,-0.405226, + -0.169784,0.964201,0.20369,1.423386,0.566478,-0.4125, + 0.551211,0.834366,0,1.460683,0.568581,-0.5, + -0.169784,0.964201,0.20369,1.423386,0.566478,-0.4125, + -0.070011,0.997546,0,1.433279,0.578472,-0.5, + 0.590668,0.729279,0.345345,1.449724,0.55695,-0.405226, + 0.478094,0.57114,0.667253,1.416649,0.522728,-0.326134, + -0.216141,0.855174,0.471127,1.392914,0.533174,-0.339125, + -0.216141,0.855174,0.471127,1.392914,0.533174,-0.339125, + -0.169784,0.964201,0.20369,1.423386,0.566478,-0.4125, + 0.590668,0.729279,0.345345,1.449724,0.55695,-0.405226, + -0.553505,0.813265,-0.179534,1.370035,0.524394,-0.638667, + -0.216141,0.855174,-0.471127,1.392914,0.533174,-0.660875, + -0.169784,0.964201,-0.203689,1.423386,0.566478,-0.5875, + -0.553505,0.813265,-0.179534,1.370035,0.524394,-0.638667, + -0.169784,0.964201,-0.203689,1.423386,0.566478,-0.5875, + -0.571934,0.814147,-0.100277,1.384841,0.546182,-0.5825, + -0.216141,0.855174,-0.471127,1.392914,0.533174,-0.660875, + 0.478093,0.57114,-0.667253,1.416649,0.522728,-0.673866, + 0.590668,0.729279,-0.345345,1.449724,0.55695,-0.594774, + 0.590668,0.729279,-0.345345,1.449724,0.55695,-0.594774, + -0.169784,0.964201,-0.203689,1.423386,0.566478,-0.5875, + -0.216141,0.855174,-0.471127,1.392914,0.533174,-0.660875, + 0.551211,0.834366,0,1.460683,0.568581,-0.5, + -0.070011,0.997546,0,1.433279,0.578472,-0.5, + -0.169784,0.964201,-0.203689,1.423386,0.566478,-0.5875, + 0.551211,0.834366,0,1.460683,0.568581,-0.5, + -0.169784,0.964201,-0.203689,1.423386,0.566478,-0.5875, + 0.590668,0.729279,-0.345345,1.449724,0.55695,-0.594774, + -0.527613,0.849485,0,1.392236,0.557026,-0.5, + -0.571934,0.814147,-0.100277,1.384841,0.546182,-0.5825, + -0.169784,0.964201,-0.203689,1.423386,0.566478,-0.5875, + -0.527613,0.849485,0,1.392236,0.557026,-0.5, + -0.169784,0.964201,-0.203689,1.423386,0.566478,-0.5875, + -0.070011,0.997546,0,1.433279,0.578472,-0.5, + 0.751095,0.142007,0.644741,1.460394,0.412133,-0.339151, + 0.45328,-0.00761,0.891335,1.407319,0.364926,-0.295283, + 0.413326,0.054801,0.908933,1.382377,0.428753,-0.281613, + 0.751095,0.142007,0.644741,1.460394,0.412133,-0.339151, + 0.413326,0.054801,0.908933,1.382377,0.428753,-0.281613, + 0.710152,0.225044,0.667112,1.437472,0.482703,-0.32841, + 0.45328,-0.00761,0.891335,1.407319,0.364926,-0.295283, + 0.144715,-0.16618,0.975419,1.343629,0.308278,-0.28066, + 0.112951,-0.120534,0.986262,1.316263,0.364012,-0.266014, + 0.112951,-0.120534,0.986262,1.316263,0.364012,-0.266014, + 0.413326,0.054801,0.908933,1.382377,0.428753,-0.281613, + 0.45328,-0.00761,0.891335,1.407319,0.364926,-0.295283, + -0.191431,0.222135,0.956039,1.294932,0.399266,-0.262379, + 0.141626,0.422273,0.895336,1.36126,0.466583,-0.278403, + 0.413326,0.054801,0.908933,1.382377,0.428753,-0.281613, + -0.191431,0.222135,0.956039,1.294932,0.399266,-0.262379, + 0.413326,0.054801,0.908933,1.382377,0.428753,-0.281613, + 0.112951,-0.120534,0.986262,1.316263,0.364012,-0.266014, + 0.141626,0.422273,0.895336,1.36126,0.466583,-0.278403, + 0.478094,0.57114,0.667253,1.416649,0.522728,-0.326134, + 0.710152,0.225044,0.667112,1.437472,0.482703,-0.32841, + 0.710152,0.225044,0.667112,1.437472,0.482703,-0.32841, + 0.413326,0.054801,0.908933,1.382377,0.428753,-0.281613, + 0.141626,0.422273,0.895336,1.36126,0.466583,-0.278403, + -0.17234,-0.336344,0.925836,1.279939,0.25163,-0.295283, + -0.503423,-0.512227,0.695837,1.226863,0.204423,-0.339151, + -0.508694,-0.497612,0.702576,1.195055,0.245321,-0.32841, + -0.508694,-0.497612,0.702576,1.195055,0.245321,-0.32841, + -0.19339,-0.303475,0.933008,1.25015,0.299272,-0.281613, + -0.17234,-0.336344,0.925836,1.279939,0.25163,-0.295283, + -0.73056,-0.181076,0.658402,1.174088,0.27496,-0.326134, + -0.461199,-0.002494,0.887293,1.22904,0.331527,-0.278403, + -0.19339,-0.303475,0.933008,1.25015,0.299272,-0.281613, + -0.73056,-0.181076,0.658402,1.174088,0.27496,-0.326134, + -0.19339,-0.303475,0.933008,1.25015,0.299272,-0.281613, + -0.508694,-0.497612,0.702576,1.195055,0.245321,-0.32841, + -0.461199,-0.002494,0.887293,1.22904,0.331527,-0.278403, + -0.191431,0.222135,0.956039,1.294932,0.399266,-0.262379, + 0.112951,-0.120534,0.986262,1.316263,0.364012,-0.266014, + 0.112951,-0.120534,0.986262,1.316263,0.364012,-0.266014, + -0.19339,-0.303475,0.933008,1.25015,0.299272,-0.281613, + -0.461199,-0.002494,0.887293,1.22904,0.331527,-0.278403, + 0.144715,-0.16618,0.975419,1.343629,0.308278,-0.28066, + -0.17234,-0.336344,0.925836,1.279939,0.25163,-0.295283, + -0.19339,-0.303475,0.933008,1.25015,0.299272,-0.281613, + 0.144715,-0.16618,0.975419,1.343629,0.308278,-0.28066, + -0.19339,-0.303475,0.933008,1.25015,0.299272,-0.281613, + 0.112951,-0.120534,0.986262,1.316263,0.364012,-0.266014, + -0.828633,0.523102,0.199328,1.177383,0.324897,-0.361333, + -0.766049,0.607525,0.209958,1.213173,0.368416,-0.335375, + -0.723455,0.416599,0.550508,1.219504,0.355352,-0.294, + -0.828633,0.523102,0.199328,1.177383,0.324897,-0.361333, + -0.723455,0.416599,0.550508,1.219504,0.355352,-0.294, + -0.850149,0.280677,0.445496,1.169407,0.301726,-0.339125, + -0.766049,0.607525,0.209958,1.213173,0.368416,-0.335375, + -0.702693,0.678582,0.21389,1.26889,0.429299,-0.322437, + -0.617508,0.597059,0.512059,1.279412,0.419138,-0.2785, + -0.617508,0.597059,0.512059,1.279412,0.419138,-0.2785, + -0.723455,0.416599,0.550508,1.219504,0.355352,-0.294, + -0.766049,0.607525,0.209958,1.213173,0.368416,-0.335375, + -0.191431,0.222135,0.956039,1.294932,0.399266,-0.262379, + -0.461199,-0.002494,0.887293,1.22904,0.331527,-0.278403, + -0.723455,0.416599,0.550508,1.219504,0.355352,-0.294, + -0.191431,0.222135,0.956039,1.294932,0.399266,-0.262379, + -0.723455,0.416599,0.550508,1.219504,0.355352,-0.294, + -0.617508,0.597059,0.512059,1.279412,0.419138,-0.2785, + -0.461199,-0.002494,0.887293,1.22904,0.331527,-0.278403, + -0.73056,-0.181076,0.658402,1.174088,0.27496,-0.326134, + -0.850149,0.280677,0.445496,1.169407,0.301726,-0.339125, + -0.850149,0.280677,0.445496,1.169407,0.301726,-0.339125, + -0.723455,0.416599,0.550508,1.219504,0.355352,-0.294, + -0.461199,-0.002494,0.887293,1.22904,0.331527,-0.278403, + -0.623755,0.751092,0.216309,1.327792,0.487107,-0.335375, + -0.553505,0.813265,0.179534,1.370035,0.524394,-0.361333, + -0.216141,0.855174,0.471127,1.392914,0.533174,-0.339125, + -0.216141,0.855174,0.471127,1.392914,0.533174,-0.339125, + -0.382645,0.670188,0.635949,1.341069,0.481236,-0.294, + -0.623755,0.751092,0.216309,1.327792,0.487107,-0.335375, + -0.216141,0.855174,0.471127,1.392914,0.533174,-0.339125, + 0.478094,0.57114,0.667253,1.416649,0.522728,-0.326134, + 0.141626,0.422273,0.895336,1.36126,0.466583,-0.278403, + 0.141626,0.422273,0.895336,1.36126,0.466583,-0.278403, + -0.382645,0.670188,0.635949,1.341069,0.481236,-0.294, + -0.216141,0.855174,0.471127,1.392914,0.533174,-0.339125, + -0.191431,0.222135,0.956039,1.294932,0.399266,-0.262379, + -0.617508,0.597059,0.512059,1.279412,0.419138,-0.2785, + -0.382645,0.670188,0.635949,1.341069,0.481236,-0.294, + -0.191431,0.222135,0.956039,1.294932,0.399266,-0.262379, + -0.382645,0.670188,0.635949,1.341069,0.481236,-0.294, + 0.141626,0.422273,0.895336,1.36126,0.466583,-0.278403, + -0.617508,0.597059,0.512059,1.279412,0.419138,-0.2785, + -0.702693,0.678582,0.21389,1.26889,0.429299,-0.322437, + -0.623755,0.751092,0.216309,1.327792,0.487107,-0.335375, + -0.623755,0.751092,0.216309,1.327792,0.487107,-0.335375, + -0.382645,0.670188,0.635949,1.341069,0.481236,-0.294, + -0.617508,0.597059,0.512059,1.279412,0.419138,-0.2785, + -0.503423,-0.512227,0.695837,1.226863,0.204423,-0.339151, + -0.715537,-0.612433,0.336055,1.195018,0.176099,-0.412264, + -0.707587,-0.61874,0.341293,1.161998,0.212951,-0.406406, + -0.503423,-0.512227,0.695837,1.226863,0.204423,-0.339151, + -0.707587,-0.61874,0.341293,1.161998,0.212951,-0.406406, + -0.508694,-0.497612,0.702576,1.195055,0.245321,-0.32841, + -0.715537,-0.612433,0.336055,1.195018,0.176099,-0.412264, + -0.784292,-0.620391,0,1.184403,0.166658,-0.5, + -0.749482,-0.662025,0,1.150979,0.202161,-0.5, + -0.749482,-0.662025,0,1.150979,0.202161,-0.5, + -0.707587,-0.61874,0.341293,1.161998,0.212951,-0.406406, + -0.715537,-0.612433,0.336055,1.195018,0.176099,-0.412264, + -0.92836,-0.371683,0,1.12918,0.229952,-0.5, + -0.856012,-0.369954,0.361078,1.140576,0.24116,-0.405226, + -0.707587,-0.61874,0.341293,1.161998,0.212951,-0.406406, + -0.92836,-0.371683,0,1.12918,0.229952,-0.5, + -0.707587,-0.61874,0.341293,1.161998,0.212951,-0.406406, + -0.749482,-0.662025,0,1.150979,0.202161,-0.5, + -0.856012,-0.369954,0.361078,1.140576,0.24116,-0.405226, + -0.73056,-0.181076,0.658402,1.174088,0.27496,-0.326134, + -0.508694,-0.497612,0.702576,1.195055,0.245321,-0.32841, + -0.508694,-0.497612,0.702576,1.195055,0.245321,-0.32841, + -0.707587,-0.61874,0.341293,1.161998,0.212951,-0.406406, + -0.856012,-0.369954,0.361078,1.140576,0.24116,-0.405226, + -0.503423,-0.512227,-0.695836,1.226863,0.204423,-0.660849, + -0.508694,-0.497611,-0.702576,1.195055,0.245321,-0.67159, + -0.707587,-0.61874,-0.341293,1.161998,0.212951,-0.593594, + -0.503423,-0.512227,-0.695836,1.226863,0.204423,-0.660849, + -0.707587,-0.61874,-0.341293,1.161998,0.212951,-0.593594, + -0.715537,-0.612433,-0.336055,1.195018,0.176099,-0.587736, + -0.508694,-0.497611,-0.702576,1.195055,0.245321,-0.67159, + -0.73056,-0.181076,-0.658402,1.174088,0.27496,-0.673866, + -0.856012,-0.369954,-0.361078,1.140576,0.24116,-0.594774, + -0.856012,-0.369954,-0.361078,1.140576,0.24116,-0.594774, + -0.707587,-0.61874,-0.341293,1.161998,0.212951,-0.593594, + -0.508694,-0.497611,-0.702576,1.195055,0.245321,-0.67159, + -0.92836,-0.371683,0,1.12918,0.229952,-0.5, + -0.749482,-0.662025,0,1.150979,0.202161,-0.5, + -0.707587,-0.61874,-0.341293,1.161998,0.212951,-0.593594, + -0.92836,-0.371683,0,1.12918,0.229952,-0.5, + -0.707587,-0.61874,-0.341293,1.161998,0.212951,-0.593594, + -0.856012,-0.369954,-0.361078,1.140576,0.24116,-0.594774, + -0.749482,-0.662025,0,1.150979,0.202161,-0.5, + -0.784292,-0.620391,0,1.184403,0.166658,-0.5, + -0.715537,-0.612433,-0.336055,1.195018,0.176099,-0.587736, + -0.715537,-0.612433,-0.336055,1.195018,0.176099,-0.587736, + -0.707587,-0.61874,-0.341293,1.161998,0.212951,-0.593594, + -0.749482,-0.662025,0,1.150979,0.202161,-0.5, + -0.828633,0.523102,-0.199328,1.177383,0.324897,-0.638667, + -0.833612,0.543172,-0.100277,1.156124,0.30934,-0.5825, + -0.955913,0.208955,-0.20632,1.137187,0.27011,-0.5875, + -0.828633,0.523102,-0.199328,1.177383,0.324897,-0.638667, + -0.955913,0.208955,-0.20632,1.137187,0.27011,-0.5875, + -0.850149,0.280677,-0.445496,1.169407,0.301726,-0.660875, + -0.867381,0.497645,0,1.145545,0.301571,-0.5, + -0.986597,0.163178,0,1.125545,0.259804,-0.5, + -0.955913,0.208955,-0.20632,1.137187,0.27011,-0.5875, + -0.867381,0.497645,0,1.145545,0.301571,-0.5, + -0.955913,0.208955,-0.20632,1.137187,0.27011,-0.5875, + -0.833612,0.543172,-0.100277,1.156124,0.30934,-0.5825, + -0.92836,-0.371683,0,1.12918,0.229952,-0.5, + -0.856012,-0.369954,-0.361078,1.140576,0.24116,-0.594774, + -0.955913,0.208955,-0.20632,1.137187,0.27011,-0.5875, + -0.92836,-0.371683,0,1.12918,0.229952,-0.5, + -0.955913,0.208955,-0.20632,1.137187,0.27011,-0.5875, + -0.986597,0.163178,0,1.125545,0.259804,-0.5, + -0.73056,-0.181076,-0.658402,1.174088,0.27496,-0.673866, + -0.850149,0.280677,-0.445496,1.169407,0.301726,-0.660875, + -0.955913,0.208955,-0.20632,1.137187,0.27011,-0.5875, + -0.73056,-0.181076,-0.658402,1.174088,0.27496,-0.673866, + -0.955913,0.208955,-0.20632,1.137187,0.27011,-0.5875, + -0.856012,-0.369954,-0.361078,1.140576,0.24116,-0.594774, + -0.828633,0.523102,0.199328,1.177383,0.324897,-0.361333, + -0.850149,0.280677,0.445496,1.169407,0.301726,-0.339125, + -0.955913,0.208955,0.20632,1.137187,0.27011,-0.4125, + -0.828633,0.523102,0.199328,1.177383,0.324897,-0.361333, + -0.955913,0.208955,0.20632,1.137187,0.27011,-0.4125, + -0.833612,0.543172,0.100277,1.156124,0.30934,-0.4175, + -0.73056,-0.181076,0.658402,1.174088,0.27496,-0.326134, + -0.856012,-0.369954,0.361078,1.140576,0.24116,-0.405226, + -0.955913,0.208955,0.20632,1.137187,0.27011,-0.4125, + -0.73056,-0.181076,0.658402,1.174088,0.27496,-0.326134, + -0.955913,0.208955,0.20632,1.137187,0.27011,-0.4125, + -0.850149,0.280677,0.445496,1.169407,0.301726,-0.339125, + -0.92836,-0.371683,0,1.12918,0.229952,-0.5, + -0.986597,0.163178,0,1.125545,0.259804,-0.5, + -0.955913,0.208955,0.20632,1.137187,0.27011,-0.4125, + -0.92836,-0.371683,0,1.12918,0.229952,-0.5, + -0.955913,0.208955,0.20632,1.137187,0.27011,-0.4125, + -0.856012,-0.369954,0.361078,1.140576,0.24116,-0.405226, + -0.867381,0.497645,0,1.145545,0.301571,-0.5, + -0.833612,0.543172,0.100277,1.156124,0.30934,-0.4175, + -0.955913,0.208955,0.20632,1.137187,0.27011,-0.4125, + -0.867381,0.497645,0,1.145545,0.301571,-0.5, + -0.955913,0.208955,0.20632,1.137187,0.27011,-0.4125, + -0.986597,0.163178,0,1.125545,0.259804,-0.5, + -0.508694,-0.497611,-0.702576,1.195055,0.245321,-0.67159, + -0.503423,-0.512227,-0.695836,1.226863,0.204423,-0.660849, + -0.17234,-0.336344,-0.925836,1.279939,0.25163,-0.704717, + -0.17234,-0.336344,-0.925836,1.279939,0.25163,-0.704717, + -0.193391,-0.303475,-0.933008,1.25015,0.299272,-0.718387, + -0.508694,-0.497611,-0.702576,1.195055,0.245321,-0.67159, + 0.144715,-0.16618,-0.975419,1.343629,0.308278,-0.71934, + 0.112951,-0.120534,-0.986262,1.316263,0.364012,-0.733986, + -0.193391,-0.303475,-0.933008,1.25015,0.299272,-0.718387, + 0.144715,-0.16618,-0.975419,1.343629,0.308278,-0.71934, + -0.193391,-0.303475,-0.933008,1.25015,0.299272,-0.718387, + -0.17234,-0.336344,-0.925836,1.279939,0.25163,-0.704717, + 0.112951,-0.120534,-0.986262,1.316263,0.364012,-0.733986, + -0.191432,0.222135,-0.956039,1.294932,0.399266,-0.737621, + -0.461199,-0.002494,-0.887293,1.22904,0.331527,-0.721597, + -0.461199,-0.002494,-0.887293,1.22904,0.331527,-0.721597, + -0.193391,-0.303475,-0.933008,1.25015,0.299272,-0.718387, + 0.112951,-0.120534,-0.986262,1.316263,0.364012,-0.733986, + -0.73056,-0.181076,-0.658402,1.174088,0.27496,-0.673866, + -0.508694,-0.497611,-0.702576,1.195055,0.245321,-0.67159, + -0.193391,-0.303475,-0.933008,1.25015,0.299272,-0.718387, + -0.73056,-0.181076,-0.658402,1.174088,0.27496,-0.673866, + -0.193391,-0.303475,-0.933008,1.25015,0.299272,-0.718387, + -0.461199,-0.002494,-0.887293,1.22904,0.331527,-0.721597, + 0.751095,0.142007,-0.644741,1.460394,0.412133,-0.660849, + 0.710152,0.225044,-0.667113,1.437472,0.482703,-0.67159, + 0.413326,0.054801,-0.908933,1.382377,0.428753,-0.718387, + 0.751095,0.142007,-0.644741,1.460394,0.412133,-0.660849, + 0.413326,0.054801,-0.908933,1.382377,0.428753,-0.718387, + 0.45328,-0.007609,-0.891335,1.407319,0.364926,-0.704717, + 0.710152,0.225044,-0.667113,1.437472,0.482703,-0.67159, + 0.478093,0.57114,-0.667253,1.416649,0.522728,-0.673866, + 0.141625,0.422274,-0.895336,1.36126,0.466583,-0.721597, + 0.141625,0.422274,-0.895336,1.36126,0.466583,-0.721597, + 0.413326,0.054801,-0.908933,1.382377,0.428753,-0.718387, + 0.710152,0.225044,-0.667113,1.437472,0.482703,-0.67159, + -0.191432,0.222135,-0.956039,1.294932,0.399266,-0.737621, + 0.112951,-0.120534,-0.986262,1.316263,0.364012,-0.733986, + 0.413326,0.054801,-0.908933,1.382377,0.428753,-0.718387, + -0.191432,0.222135,-0.956039,1.294932,0.399266,-0.737621, + 0.413326,0.054801,-0.908933,1.382377,0.428753,-0.718387, + 0.141625,0.422274,-0.895336,1.36126,0.466583,-0.721597, + 0.112951,-0.120534,-0.986262,1.316263,0.364012,-0.733986, + 0.144715,-0.16618,-0.975419,1.343629,0.308278,-0.71934, + 0.45328,-0.007609,-0.891335,1.407319,0.364926,-0.704717, + 0.45328,-0.007609,-0.891335,1.407319,0.364926,-0.704717, + 0.413326,0.054801,-0.908933,1.382377,0.428753,-0.718387, + 0.112951,-0.120534,-0.986262,1.316263,0.364012,-0.733986, + -0.216141,0.855174,-0.471127,1.392914,0.533174,-0.660875, + -0.553505,0.813265,-0.179534,1.370035,0.524394,-0.638667, + -0.623755,0.751092,-0.216309,1.327792,0.487107,-0.664625, + -0.623755,0.751092,-0.216309,1.327792,0.487107,-0.664625, + -0.382645,0.670188,-0.635948,1.341069,0.481236,-0.706, + -0.216141,0.855174,-0.471127,1.392914,0.533174,-0.660875, + -0.623755,0.751092,-0.216309,1.327792,0.487107,-0.664625, + -0.702693,0.678582,-0.21389,1.26889,0.429299,-0.677562, + -0.617508,0.597059,-0.512058,1.279412,0.419138,-0.7215, + -0.617508,0.597059,-0.512058,1.279412,0.419138,-0.7215, + -0.382645,0.670188,-0.635948,1.341069,0.481236,-0.706, + -0.623755,0.751092,-0.216309,1.327792,0.487107,-0.664625, + -0.191432,0.222135,-0.956039,1.294932,0.399266,-0.737621, + 0.141625,0.422274,-0.895336,1.36126,0.466583,-0.721597, + -0.382645,0.670188,-0.635948,1.341069,0.481236,-0.706, + -0.191432,0.222135,-0.956039,1.294932,0.399266,-0.737621, + -0.382645,0.670188,-0.635948,1.341069,0.481236,-0.706, + -0.617508,0.597059,-0.512058,1.279412,0.419138,-0.7215, + 0.141625,0.422274,-0.895336,1.36126,0.466583,-0.721597, + 0.478093,0.57114,-0.667253,1.416649,0.522728,-0.673866, + -0.216141,0.855174,-0.471127,1.392914,0.533174,-0.660875, + -0.216141,0.855174,-0.471127,1.392914,0.533174,-0.660875, + -0.382645,0.670188,-0.635948,1.341069,0.481236,-0.706, + 0.141625,0.422274,-0.895336,1.36126,0.466583,-0.721597, + -0.828633,0.523102,-0.199328,1.177383,0.324897,-0.638667, + -0.850149,0.280677,-0.445496,1.169407,0.301726,-0.660875, + -0.723455,0.416599,-0.550508,1.219504,0.355352,-0.706, + -0.828633,0.523102,-0.199328,1.177383,0.324897,-0.638667, + -0.723455,0.416599,-0.550508,1.219504,0.355352,-0.706, + -0.766049,0.607525,-0.209958,1.213173,0.368416,-0.664625, + -0.850149,0.280677,-0.445496,1.169407,0.301726,-0.660875, + -0.73056,-0.181076,-0.658402,1.174088,0.27496,-0.673866, + -0.461199,-0.002494,-0.887293,1.22904,0.331527,-0.721597, + -0.461199,-0.002494,-0.887293,1.22904,0.331527,-0.721597, + -0.723455,0.416599,-0.550508,1.219504,0.355352,-0.706, + -0.850149,0.280677,-0.445496,1.169407,0.301726,-0.660875, + -0.191432,0.222135,-0.956039,1.294932,0.399266,-0.737621, + -0.617508,0.597059,-0.512058,1.279412,0.419138,-0.7215, + -0.723455,0.416599,-0.550508,1.219504,0.355352,-0.706, + -0.191432,0.222135,-0.956039,1.294932,0.399266,-0.737621, + -0.723455,0.416599,-0.550508,1.219504,0.355352,-0.706, + -0.461199,-0.002494,-0.887293,1.22904,0.331527,-0.721597, + -0.617508,0.597059,-0.512058,1.279412,0.419138,-0.7215, + -0.702693,0.678582,-0.21389,1.26889,0.429299,-0.677562, + -0.766049,0.607525,-0.209958,1.213173,0.368416,-0.664625, + -0.766049,0.607525,-0.209958,1.213173,0.368416,-0.664625, + -0.723455,0.416599,-0.550508,1.219504,0.355352,-0.706, + -0.617508,0.597059,-0.512058,1.279412,0.419138,-0.7215, + -0.553505,0.813265,0.179534,1.370035,0.524394,-0.361333, + -0.623755,0.751092,0.216309,1.327792,0.487107,-0.335375, + -0.65936,0.747587,0.079739,1.327417,0.49859,-0.4095, + -0.553505,0.813265,0.179534,1.370035,0.524394,-0.361333, + -0.65936,0.747587,0.079739,1.327417,0.49859,-0.4095, + -0.571934,0.814147,0.100277,1.384841,0.546182,-0.4175, + -0.623755,0.751092,0.216309,1.327792,0.487107,-0.335375, + -0.702693,0.678582,0.21389,1.26889,0.429299,-0.322437, + -0.716739,0.692147,0.08496,1.262552,0.435419,-0.40225, + -0.716739,0.692147,0.08496,1.262552,0.435419,-0.40225, + -0.65936,0.747587,0.079739,1.327417,0.49859,-0.4095, + -0.623755,0.751092,0.216309,1.327792,0.487107,-0.335375, + -0.71934,0.694658,0,1.260429,0.437469,-0.5, + -0.65772,0.753262,0,1.330455,0.505735,-0.5, + -0.65936,0.747587,0.079739,1.327417,0.49859,-0.4095, + -0.71934,0.694658,0,1.260429,0.437469,-0.5, + -0.65936,0.747587,0.079739,1.327417,0.49859,-0.4095, + -0.716739,0.692147,0.08496,1.262552,0.435419,-0.40225, + -0.65772,0.753262,0,1.330455,0.505735,-0.5, + -0.527613,0.849485,0,1.392236,0.557026,-0.5, + -0.571934,0.814147,0.100277,1.384841,0.546182,-0.4175, + -0.571934,0.814147,0.100277,1.384841,0.546182,-0.4175, + -0.65936,0.747587,0.079739,1.327417,0.49859,-0.4095, + -0.65772,0.753262,0,1.330455,0.505735,-0.5, + -0.828633,0.523102,0.199328,1.177383,0.324897,-0.361333, + -0.833612,0.543172,0.100277,1.156124,0.30934,-0.4175, + -0.770142,0.632868,0.079739,1.201684,0.368389,-0.4095, + -0.828633,0.523102,0.199328,1.177383,0.324897,-0.361333, + -0.770142,0.632868,0.079739,1.201684,0.368389,-0.4095, + -0.766049,0.607525,0.209958,1.213173,0.368416,-0.335375, + -0.833612,0.543172,0.100277,1.156124,0.30934,-0.4175, + -0.867381,0.497645,0,1.145545,0.301571,-0.5, + -0.775757,0.631031,0,1.19465,0.365104,-0.5, + -0.775757,0.631031,0,1.19465,0.365104,-0.5, + -0.770142,0.632868,0.079739,1.201684,0.368389,-0.4095, + -0.833612,0.543172,0.100277,1.156124,0.30934,-0.4175, + -0.71934,0.694658,0,1.260429,0.437469,-0.5, + -0.716739,0.692147,0.08496,1.262552,0.435419,-0.40225, + -0.770142,0.632868,0.079739,1.201684,0.368389,-0.4095, + -0.71934,0.694658,0,1.260429,0.437469,-0.5, + -0.770142,0.632868,0.079739,1.201684,0.368389,-0.4095, + -0.775757,0.631031,0,1.19465,0.365104,-0.5, + -0.716739,0.692147,0.08496,1.262552,0.435419,-0.40225, + -0.702693,0.678582,0.21389,1.26889,0.429299,-0.322437, + -0.766049,0.607525,0.209958,1.213173,0.368416,-0.335375, + -0.766049,0.607525,0.209958,1.213173,0.368416,-0.335375, + -0.770142,0.632868,0.079739,1.201684,0.368389,-0.4095, + -0.716739,0.692147,0.08496,1.262552,0.435419,-0.40225, + -0.828633,0.523102,-0.199328,1.177383,0.324897,-0.638667, + -0.766049,0.607525,-0.209958,1.213173,0.368416,-0.664625, + -0.770142,0.632868,-0.079739,1.201684,0.368389,-0.5905, + -0.828633,0.523102,-0.199328,1.177383,0.324897,-0.638667, + -0.770142,0.632868,-0.079739,1.201684,0.368389,-0.5905, + -0.833612,0.543172,-0.100277,1.156124,0.30934,-0.5825, + -0.766049,0.607525,-0.209958,1.213173,0.368416,-0.664625, + -0.702693,0.678582,-0.21389,1.26889,0.429299,-0.677562, + -0.716739,0.692147,-0.08496,1.262552,0.435419,-0.59775, + -0.716739,0.692147,-0.08496,1.262552,0.435419,-0.59775, + -0.770142,0.632868,-0.079739,1.201684,0.368389,-0.5905, + -0.766049,0.607525,-0.209958,1.213173,0.368416,-0.664625, + -0.71934,0.694658,0,1.260429,0.437469,-0.5, + -0.775757,0.631031,0,1.19465,0.365104,-0.5, + -0.770142,0.632868,-0.079739,1.201684,0.368389,-0.5905, + -0.71934,0.694658,0,1.260429,0.437469,-0.5, + -0.770142,0.632868,-0.079739,1.201684,0.368389,-0.5905, + -0.716739,0.692147,-0.08496,1.262552,0.435419,-0.59775, + -0.775757,0.631031,0,1.19465,0.365104,-0.5, + -0.867381,0.497645,0,1.145545,0.301571,-0.5, + -0.833612,0.543172,-0.100277,1.156124,0.30934,-0.5825, + -0.833612,0.543172,-0.100277,1.156124,0.30934,-0.5825, + -0.770142,0.632868,-0.079739,1.201684,0.368389,-0.5905, + -0.775757,0.631031,0,1.19465,0.365104,-0.5, + -0.553505,0.813265,-0.179534,1.370035,0.524394,-0.638667, + -0.571934,0.814147,-0.100277,1.384841,0.546182,-0.5825, + -0.65936,0.747587,-0.079739,1.327417,0.49859,-0.5905, + -0.553505,0.813265,-0.179534,1.370035,0.524394,-0.638667, + -0.65936,0.747587,-0.079739,1.327417,0.49859,-0.5905, + -0.623755,0.751092,-0.216309,1.327792,0.487107,-0.664625, + -0.571934,0.814147,-0.100277,1.384841,0.546182,-0.5825, + -0.527613,0.849485,0,1.392236,0.557026,-0.5, + -0.65772,0.753262,0,1.330455,0.505735,-0.5, + -0.65772,0.753262,0,1.330455,0.505735,-0.5, + -0.65936,0.747587,-0.079739,1.327417,0.49859,-0.5905, + -0.571934,0.814147,-0.100277,1.384841,0.546182,-0.5825, + -0.71934,0.694658,0,1.260429,0.437469,-0.5, + -0.716739,0.692147,-0.08496,1.262552,0.435419,-0.59775, + -0.65936,0.747587,-0.079739,1.327417,0.49859,-0.5905, + -0.71934,0.694658,0,1.260429,0.437469,-0.5, + -0.65936,0.747587,-0.079739,1.327417,0.49859,-0.5905, + -0.65772,0.753262,0,1.330455,0.505735,-0.5, + -0.716739,0.692147,-0.08496,1.262552,0.435419,-0.59775, + -0.702693,0.678582,-0.21389,1.26889,0.429299,-0.677562, + -0.623755,0.751092,-0.216309,1.327792,0.487107,-0.664625, + -0.623755,0.751092,-0.216309,1.327792,0.487107,-0.664625, + -0.65936,0.747587,-0.079739,1.327417,0.49859,-0.5905, + -0.716739,0.692147,-0.08496,1.262552,0.435419,-0.59775, + 0.751095,0.142007,-0.644741,1.460394,0.412133,-0.660849, + 0.74475,0.138417,-0.652831,1.49043,0.310049,-0.648448, + 0.924767,0.224636,-0.307154,1.521298,0.332708,-0.580972, + 0.751095,0.142007,-0.644741,1.460394,0.412133,-0.660849, + 0.924767,0.224636,-0.307154,1.521298,0.332708,-0.580972, + 0.922813,0.236109,-0.304415,1.492239,0.440457,-0.587736, + 0.74475,0.138417,-0.652831,1.49043,0.310049,-0.648448, + 0.734405,0.137212,-0.664697,1.524188,0.186469,-0.636664, + 0.924854,0.216174,-0.312912,1.554547,0.202755,-0.574544, + 0.924854,0.216174,-0.312912,1.554547,0.202755,-0.574544, + 0.924767,0.224636,-0.307154,1.521298,0.332708,-0.580972, + 0.74475,0.138417,-0.652831,1.49043,0.310049,-0.648448, + 0.97102,0.238998,0,1.564666,0.208184,-0.5, + 0.968395,0.249424,0,1.531587,0.340261,-0.5, + 0.924767,0.224636,-0.307154,1.521298,0.332708,-0.580972, + 0.97102,0.238998,0,1.564666,0.208184,-0.5, + 0.924767,0.224636,-0.307154,1.521298,0.332708,-0.580972, + 0.924854,0.216174,-0.312912,1.554547,0.202755,-0.574544, + 0.968395,0.249424,0,1.531587,0.340261,-0.5, + 0.964484,0.264141,0,1.502855,0.449898,-0.5, + 0.922813,0.236109,-0.304415,1.492239,0.440457,-0.587736, + 0.922813,0.236109,-0.304415,1.492239,0.440457,-0.587736, + 0.924767,0.224636,-0.307154,1.521298,0.332708,-0.580972, + 0.968395,0.249424,0,1.531587,0.340261,-0.5, + 0.721766,0.139046,-0.678027,1.558275,0.051411,-0.627772, + 0.68395,0.1429,-0.715397,1.589301,-0.085107,-0.624049, + 0.923419,0.19798,-0.328787,1.620986,-0.080049,-0.567663, + 0.923419,0.19798,-0.328787,1.620986,-0.080049,-0.567663, + 0.924112,0.20782,-0.320669,1.588828,0.061527,-0.569694, + 0.721766,0.139046,-0.678027,1.558275,0.051411,-0.627772, + 0.976556,0.215262,0,1.631547,-0.078363,-0.5, + 0.973545,0.228495,0,1.599013,0.064899,-0.5, + 0.924112,0.20782,-0.320669,1.588828,0.061527,-0.569694, + 0.976556,0.215262,0,1.631547,-0.078363,-0.5, + 0.924112,0.20782,-0.320669,1.588828,0.061527,-0.569694, + 0.923419,0.19798,-0.328787,1.620986,-0.080049,-0.567663, + 0.973545,0.228495,0,1.599013,0.064899,-0.5, + 0.97102,0.238998,0,1.564666,0.208184,-0.5, + 0.924854,0.216174,-0.312912,1.554547,0.202755,-0.574544, + 0.924854,0.216174,-0.312912,1.554547,0.202755,-0.574544, + 0.924112,0.20782,-0.320669,1.588828,0.061527,-0.569694, + 0.973545,0.228495,0,1.599013,0.064899,-0.5, + 0.734405,0.137212,-0.664697,1.524188,0.186469,-0.636664, + 0.721766,0.139046,-0.678027,1.558275,0.051411,-0.627772, + 0.924112,0.20782,-0.320669,1.588828,0.061527,-0.569694, + 0.734405,0.137212,-0.664697,1.524188,0.186469,-0.636664, + 0.924112,0.20782,-0.320669,1.588828,0.061527,-0.569694, + 0.924854,0.216174,-0.312912,1.554547,0.202755,-0.574544, + 0.923419,0.19798,0.328787,1.620986,-0.080049,-0.432337, + 0.68395,0.1429,0.715397,1.589301,-0.085107,-0.375951, + 0.721766,0.139046,0.678027,1.558275,0.051411,-0.372228, + 0.721766,0.139046,0.678027,1.558275,0.051411,-0.372228, + 0.924112,0.20782,0.320669,1.588828,0.061527,-0.430306, + 0.923419,0.19798,0.328787,1.620986,-0.080049,-0.432337, + 0.734405,0.137212,0.664697,1.524188,0.186469,-0.363336, + 0.924854,0.216174,0.312912,1.554547,0.202755,-0.425456, + 0.924112,0.20782,0.320669,1.588828,0.061527,-0.430306, + 0.734405,0.137212,0.664697,1.524188,0.186469,-0.363336, + 0.924112,0.20782,0.320669,1.588828,0.061527,-0.430306, + 0.721766,0.139046,0.678027,1.558275,0.051411,-0.372228, + 0.924854,0.216174,0.312912,1.554547,0.202755,-0.425456, + 0.97102,0.238998,0,1.564666,0.208184,-0.5, + 0.973545,0.228495,0,1.599013,0.064899,-0.5, + 0.973545,0.228495,0,1.599013,0.064899,-0.5, + 0.924112,0.20782,0.320669,1.588828,0.061527,-0.430306, + 0.924854,0.216174,0.312912,1.554547,0.202755,-0.425456, + 0.976556,0.215262,0,1.631547,-0.078363,-0.5, + 0.923419,0.19798,0.328787,1.620986,-0.080049,-0.432337, + 0.924112,0.20782,0.320669,1.588828,0.061527,-0.430306, + 0.976556,0.215262,0,1.631547,-0.078363,-0.5, + 0.924112,0.20782,0.320669,1.588828,0.061527,-0.430306, + 0.973545,0.228495,0,1.599013,0.064899,-0.5, + 0.751095,0.142007,0.644741,1.460394,0.412133,-0.339151, + 0.922813,0.236109,0.304415,1.492239,0.440457,-0.412264, + 0.924767,0.224636,0.307154,1.521298,0.332708,-0.419028, + 0.751095,0.142007,0.644741,1.460394,0.412133,-0.339151, + 0.924767,0.224636,0.307154,1.521298,0.332708,-0.419028, + 0.74475,0.138417,0.652831,1.49043,0.310049,-0.351552, + 0.922813,0.236109,0.304415,1.492239,0.440457,-0.412264, + 0.964484,0.264141,0,1.502855,0.449898,-0.5, + 0.968395,0.249424,0,1.531587,0.340261,-0.5, + 0.968395,0.249424,0,1.531587,0.340261,-0.5, + 0.924767,0.224636,0.307154,1.521298,0.332708,-0.419028, + 0.922813,0.236109,0.304415,1.492239,0.440457,-0.412264, + 0.97102,0.238998,0,1.564666,0.208184,-0.5, + 0.924854,0.216174,0.312912,1.554547,0.202755,-0.425456, + 0.924767,0.224636,0.307154,1.521298,0.332708,-0.419028, + 0.97102,0.238998,0,1.564666,0.208184,-0.5, + 0.924767,0.224636,0.307154,1.521298,0.332708,-0.419028, + 0.968395,0.249424,0,1.531587,0.340261,-0.5, + 0.924854,0.216174,0.312912,1.554547,0.202755,-0.425456, + 0.734405,0.137212,0.664697,1.524188,0.186469,-0.363336, + 0.74475,0.138417,0.652831,1.49043,0.310049,-0.351552, + 0.74475,0.138417,0.652831,1.49043,0.310049,-0.351552, + 0.924767,0.224636,0.307154,1.521298,0.332708,-0.419028, + 0.924854,0.216174,0.312912,1.554547,0.202755,-0.425456, + -0.503423,-0.512227,-0.695836,1.226863,0.204423,-0.660849, + -0.575759,-0.440808,-0.688615,1.264067,0.143881,-0.648448, + -0.232261,-0.293469,-0.927325,1.315513,0.181646,-0.688934, + -0.503423,-0.512227,-0.695836,1.226863,0.204423,-0.660849, + -0.232261,-0.293469,-0.927325,1.315513,0.181646,-0.688934, + -0.17234,-0.336344,-0.925836,1.279939,0.25163,-0.704717, + -0.575759,-0.440808,-0.688615,1.264067,0.143881,-0.648448, + -0.637408,-0.358226,-0.682191,1.301556,0.067036,-0.636664, + -0.287334,-0.241218,-0.926959,1.352154,0.09418,-0.673936, + -0.287334,-0.241218,-0.926959,1.352154,0.09418,-0.673936, + -0.232261,-0.293469,-0.927325,1.315513,0.181646,-0.688934, + -0.575759,-0.440808,-0.688615,1.264067,0.143881,-0.648448, + 0.061121,-0.115002,-0.991483,1.412872,0.126752,-0.68636, + 0.103365,-0.143519,-0.984235,1.377249,0.226965,-0.70243, + -0.232261,-0.293469,-0.927325,1.315513,0.181646,-0.688934, + 0.061121,-0.115002,-0.991483,1.412872,0.126752,-0.68636, + -0.232261,-0.293469,-0.927325,1.315513,0.181646,-0.688934, + -0.287334,-0.241218,-0.926959,1.352154,0.09418,-0.673936, + 0.103365,-0.143519,-0.984235,1.377249,0.226965,-0.70243, + 0.144715,-0.16618,-0.975419,1.343629,0.308278,-0.71934, + -0.17234,-0.336344,-0.925836,1.279939,0.25163,-0.704717, + -0.17234,-0.336344,-0.925836,1.279939,0.25163,-0.704717, + -0.232261,-0.293469,-0.927325,1.315513,0.181646,-0.688934, + 0.103365,-0.143519,-0.984235,1.377249,0.226965,-0.70243, + -0.686016,-0.251158,-0.682863,1.33422,-0.022771,-0.627772, + -0.71415,-0.110296,-0.691249,1.356947,-0.122198,-0.624049, + -0.355153,-0.061801,-0.932763,1.409755,-0.113768,-0.657881, + -0.355153,-0.061801,-0.932763,1.409755,-0.113768,-0.657881, + -0.331282,-0.167258,-0.928589,1.385142,-0.005911,-0.662619, + -0.686016,-0.251158,-0.682863,1.33422,-0.022771,-0.627772, + -0.032665,-0.015822,-0.999341,1.473124,-0.103652,-0.669158, + 0.024003,-0.070986,-0.997189,1.446248,0.01432,-0.674234, + -0.331282,-0.167258,-0.928589,1.385142,-0.005911,-0.662619, + -0.032665,-0.015822,-0.999341,1.473124,-0.103652,-0.669158, + -0.331282,-0.167258,-0.928589,1.385142,-0.005911,-0.662619, + -0.355153,-0.061801,-0.932763,1.409755,-0.113768,-0.657881, + 0.024003,-0.070986,-0.997189,1.446248,0.01432,-0.674234, + 0.061121,-0.115002,-0.991483,1.412872,0.126752,-0.68636, + -0.287334,-0.241218,-0.926959,1.352154,0.09418,-0.673936, + -0.287334,-0.241218,-0.926959,1.352154,0.09418,-0.673936, + -0.331282,-0.167258,-0.928589,1.385142,-0.005911,-0.662619, + 0.024003,-0.070986,-0.997189,1.446248,0.01432,-0.674234, + -0.637408,-0.358226,-0.682191,1.301556,0.067036,-0.636664, + -0.686016,-0.251158,-0.682863,1.33422,-0.022771,-0.627772, + -0.331282,-0.167258,-0.928589,1.385142,-0.005911,-0.662619, + -0.637408,-0.358226,-0.682191,1.301556,0.067036,-0.636664, + -0.331282,-0.167258,-0.928589,1.385142,-0.005911,-0.662619, + -0.287334,-0.241218,-0.926959,1.352154,0.09418,-0.673936, + 0.68395,0.1429,-0.715397,1.589301,-0.085107,-0.624049, + 0.721766,0.139046,-0.678027,1.558275,0.051411,-0.627772, + 0.376201,0.032359,-0.925973,1.507354,0.034552,-0.662619, + 0.68395,0.1429,-0.715397,1.589301,-0.085107,-0.624049, + 0.376201,0.032359,-0.925973,1.507354,0.034552,-0.662619, + 0.294772,0.058288,-0.953788,1.536493,-0.093537,-0.657881, + 0.721766,0.139046,-0.678027,1.558275,0.051411,-0.627772, + 0.734405,0.137212,-0.664697,1.524188,0.186469,-0.636664, + 0.403594,0.012135,-0.914858,1.47359,0.159325,-0.673936, + 0.403594,0.012135,-0.914858,1.47359,0.159325,-0.673936, + 0.376201,0.032359,-0.925973,1.507354,0.034552,-0.662619, + 0.721766,0.139046,-0.678027,1.558275,0.051411,-0.627772, + 0.061121,-0.115002,-0.991483,1.412872,0.126752,-0.68636, + 0.024003,-0.070986,-0.997189,1.446248,0.01432,-0.674234, + 0.376201,0.032359,-0.925973,1.507354,0.034552,-0.662619, + 0.061121,-0.115002,-0.991483,1.412872,0.126752,-0.68636, + 0.376201,0.032359,-0.925973,1.507354,0.034552,-0.662619, + 0.403594,0.012135,-0.914858,1.47359,0.159325,-0.673936, + 0.024003,-0.070986,-0.997189,1.446248,0.01432,-0.674234, + -0.032665,-0.015822,-0.999341,1.473124,-0.103652,-0.669158, + 0.294772,0.058288,-0.953788,1.536493,-0.093537,-0.657881, + 0.294772,0.058288,-0.953788,1.536493,-0.093537,-0.657881, + 0.376201,0.032359,-0.925973,1.507354,0.034552,-0.662619, + 0.024003,-0.070986,-0.997189,1.446248,0.01432,-0.674234, + 0.74475,0.138417,-0.652831,1.49043,0.310049,-0.648448, + 0.751095,0.142007,-0.644741,1.460394,0.412133,-0.660849, + 0.45328,-0.007609,-0.891335,1.407319,0.364926,-0.704717, + 0.45328,-0.007609,-0.891335,1.407319,0.364926,-0.704717, + 0.430582,0.000669,-0.902551,1.438984,0.272283,-0.688934, + 0.74475,0.138417,-0.652831,1.49043,0.310049,-0.648448, + 0.144715,-0.16618,-0.975419,1.343629,0.308278,-0.71934, + 0.103365,-0.143519,-0.984235,1.377249,0.226965,-0.70243, + 0.430582,0.000669,-0.902551,1.438984,0.272283,-0.688934, + 0.144715,-0.16618,-0.975419,1.343629,0.308278,-0.71934, + 0.430582,0.000669,-0.902551,1.438984,0.272283,-0.688934, + 0.45328,-0.007609,-0.891335,1.407319,0.364926,-0.704717, + 0.103365,-0.143519,-0.984235,1.377249,0.226965,-0.70243, + 0.061121,-0.115002,-0.991483,1.412872,0.126752,-0.68636, + 0.403594,0.012135,-0.914858,1.47359,0.159325,-0.673936, + 0.403594,0.012135,-0.914858,1.47359,0.159325,-0.673936, + 0.430582,0.000669,-0.902551,1.438984,0.272283,-0.688934, + 0.103365,-0.143519,-0.984235,1.377249,0.226965,-0.70243, + 0.734405,0.137212,-0.664697,1.524188,0.186469,-0.636664, + 0.74475,0.138417,-0.652831,1.49043,0.310049,-0.648448, + 0.430582,0.000669,-0.902551,1.438984,0.272283,-0.688934, + 0.734405,0.137212,-0.664697,1.524188,0.186469,-0.636664, + 0.430582,0.000669,-0.902551,1.438984,0.272283,-0.688934, + 0.403594,0.012135,-0.914858,1.47359,0.159325,-0.673936, + -0.503423,-0.512227,0.695837,1.226863,0.204423,-0.339151, + -0.17234,-0.336344,0.925836,1.279939,0.25163,-0.295283, + -0.232261,-0.293468,0.927325,1.315513,0.181646,-0.311066, + -0.503423,-0.512227,0.695837,1.226863,0.204423,-0.339151, + -0.232261,-0.293468,0.927325,1.315513,0.181646,-0.311066, + -0.575759,-0.440808,0.688615,1.264067,0.143881,-0.351552, + -0.17234,-0.336344,0.925836,1.279939,0.25163,-0.295283, + 0.144715,-0.16618,0.975419,1.343629,0.308278,-0.28066, + 0.103365,-0.143519,0.984235,1.377249,0.226965,-0.29757, + 0.103365,-0.143519,0.984235,1.377249,0.226965,-0.29757, + -0.232261,-0.293468,0.927325,1.315513,0.181646,-0.311066, + -0.17234,-0.336344,0.925836,1.279939,0.25163,-0.295283, + 0.061121,-0.115002,0.991483,1.412872,0.126752,-0.31364, + -0.287334,-0.241218,0.926959,1.352154,0.09418,-0.326064, + -0.232261,-0.293468,0.927325,1.315513,0.181646,-0.311066, + 0.061121,-0.115002,0.991483,1.412872,0.126752,-0.31364, + -0.232261,-0.293468,0.927325,1.315513,0.181646,-0.311066, + 0.103365,-0.143519,0.984235,1.377249,0.226965,-0.29757, + -0.287334,-0.241218,0.926959,1.352154,0.09418,-0.326064, + -0.637408,-0.358226,0.682191,1.301556,0.067036,-0.363336, + -0.575759,-0.440808,0.688615,1.264067,0.143881,-0.351552, + -0.575759,-0.440808,0.688615,1.264067,0.143881,-0.351552, + -0.232261,-0.293468,0.927325,1.315513,0.181646,-0.311066, + -0.287334,-0.241218,0.926959,1.352154,0.09418,-0.326064, + 0.45328,-0.00761,0.891335,1.407319,0.364926,-0.295283, + 0.751095,0.142007,0.644741,1.460394,0.412133,-0.339151, + 0.74475,0.138417,0.652831,1.49043,0.310049,-0.351552, + 0.74475,0.138417,0.652831,1.49043,0.310049,-0.351552, + 0.430582,0.000669,0.902551,1.438984,0.272283,-0.311066, + 0.45328,-0.00761,0.891335,1.407319,0.364926,-0.295283, + 0.734405,0.137212,0.664697,1.524188,0.186469,-0.363336, + 0.403594,0.012135,0.914858,1.47359,0.159325,-0.326064, + 0.430582,0.000669,0.902551,1.438984,0.272283,-0.311066, + 0.734405,0.137212,0.664697,1.524188,0.186469,-0.363336, + 0.430582,0.000669,0.902551,1.438984,0.272283,-0.311066, + 0.74475,0.138417,0.652831,1.49043,0.310049,-0.351552, + 0.403594,0.012135,0.914858,1.47359,0.159325,-0.326064, + 0.061121,-0.115002,0.991483,1.412872,0.126752,-0.31364, + 0.103365,-0.143519,0.984235,1.377249,0.226965,-0.29757, + 0.103365,-0.143519,0.984235,1.377249,0.226965,-0.29757, + 0.430582,0.000669,0.902551,1.438984,0.272283,-0.311066, + 0.403594,0.012135,0.914858,1.47359,0.159325,-0.326064, + 0.144715,-0.16618,0.975419,1.343629,0.308278,-0.28066, + 0.45328,-0.00761,0.891335,1.407319,0.364926,-0.295283, + 0.430582,0.000669,0.902551,1.438984,0.272283,-0.311066, + 0.144715,-0.16618,0.975419,1.343629,0.308278,-0.28066, + 0.430582,0.000669,0.902551,1.438984,0.272283,-0.311066, + 0.103365,-0.143519,0.984235,1.377249,0.226965,-0.29757, + 0.68395,0.1429,0.715397,1.589301,-0.085107,-0.375951, + 0.294772,0.058287,0.953788,1.536493,-0.093537,-0.342119, + 0.376201,0.032359,0.925973,1.507354,0.034552,-0.337381, + 0.68395,0.1429,0.715397,1.589301,-0.085107,-0.375951, + 0.376201,0.032359,0.925973,1.507354,0.034552,-0.337381, + 0.721766,0.139046,0.678027,1.558275,0.051411,-0.372228, + 0.294772,0.058287,0.953788,1.536493,-0.093537,-0.342119, + -0.032665,-0.015822,0.999341,1.473124,-0.103652,-0.330842, + 0.024003,-0.070986,0.997189,1.446248,0.01432,-0.325766, + 0.024003,-0.070986,0.997189,1.446248,0.01432,-0.325766, + 0.376201,0.032359,0.925973,1.507354,0.034552,-0.337381, + 0.294772,0.058287,0.953788,1.536493,-0.093537,-0.342119, + 0.061121,-0.115002,0.991483,1.412872,0.126752,-0.31364, + 0.403594,0.012135,0.914858,1.47359,0.159325,-0.326064, + 0.376201,0.032359,0.925973,1.507354,0.034552,-0.337381, + 0.061121,-0.115002,0.991483,1.412872,0.126752,-0.31364, + 0.376201,0.032359,0.925973,1.507354,0.034552,-0.337381, + 0.024003,-0.070986,0.997189,1.446248,0.01432,-0.325766, + 0.403594,0.012135,0.914858,1.47359,0.159325,-0.326064, + 0.734405,0.137212,0.664697,1.524188,0.186469,-0.363336, + 0.721766,0.139046,0.678027,1.558275,0.051411,-0.372228, + 0.721766,0.139046,0.678027,1.558275,0.051411,-0.372228, + 0.376201,0.032359,0.925973,1.507354,0.034552,-0.337381, + 0.403594,0.012135,0.914858,1.47359,0.159325,-0.326064, + -0.355153,-0.061801,0.932763,1.409755,-0.113768,-0.342119, + -0.714149,-0.110296,0.691249,1.356947,-0.122198,-0.375951, + -0.686016,-0.251158,0.682863,1.33422,-0.022771,-0.372228, + -0.686016,-0.251158,0.682863,1.33422,-0.022771,-0.372228, + -0.331282,-0.167257,0.928589,1.385142,-0.005911,-0.337381, + -0.355153,-0.061801,0.932763,1.409755,-0.113768,-0.342119, + -0.637408,-0.358226,0.682191,1.301556,0.067036,-0.363336, + -0.287334,-0.241218,0.926959,1.352154,0.09418,-0.326064, + -0.331282,-0.167257,0.928589,1.385142,-0.005911,-0.337381, + -0.637408,-0.358226,0.682191,1.301556,0.067036,-0.363336, + -0.331282,-0.167257,0.928589,1.385142,-0.005911,-0.337381, + -0.686016,-0.251158,0.682863,1.33422,-0.022771,-0.372228, + -0.287334,-0.241218,0.926959,1.352154,0.09418,-0.326064, + 0.061121,-0.115002,0.991483,1.412872,0.126752,-0.31364, + 0.024003,-0.070986,0.997189,1.446248,0.01432,-0.325766, + 0.024003,-0.070986,0.997189,1.446248,0.01432,-0.325766, + -0.331282,-0.167257,0.928589,1.385142,-0.005911,-0.337381, + -0.287334,-0.241218,0.926959,1.352154,0.09418,-0.326064, + -0.032665,-0.015822,0.999341,1.473124,-0.103652,-0.330842, + -0.355153,-0.061801,0.932763,1.409755,-0.113768,-0.342119, + -0.331282,-0.167257,0.928589,1.385142,-0.005911,-0.337381, + -0.032665,-0.015822,0.999341,1.473124,-0.103652,-0.330842, + -0.331282,-0.167257,0.928589,1.385142,-0.005911,-0.337381, + 0.024003,-0.070986,0.997189,1.446248,0.01432,-0.325766, + -0.575759,-0.440808,-0.688615,1.264067,0.143881,-0.648448, + -0.503423,-0.512227,-0.695836,1.226863,0.204423,-0.660849, + -0.715537,-0.612433,-0.336055,1.195018,0.176099,-0.587736, + -0.715537,-0.612433,-0.336055,1.195018,0.176099,-0.587736, + -0.788495,-0.519776,-0.328798,1.2332,0.121222,-0.580972, + -0.575759,-0.440808,-0.688615,1.264067,0.143881,-0.648448, + -0.784292,-0.620391,0,1.184403,0.166658,-0.5, + -0.853449,-0.521176,0,1.222911,0.113669,-0.5, + -0.788495,-0.519776,-0.328798,1.2332,0.121222,-0.580972, + -0.784292,-0.620391,0,1.184403,0.166658,-0.5, + -0.788495,-0.519776,-0.328798,1.2332,0.121222,-0.580972, + -0.715537,-0.612433,-0.336055,1.195018,0.176099,-0.587736, + -0.853449,-0.521176,0,1.222911,0.113669,-0.5, + -0.912287,-0.409552,0,1.261078,0.045321,-0.5, + -0.849326,-0.416862,-0.323838,1.271198,0.05075,-0.574544, + -0.849326,-0.416862,-0.323838,1.271198,0.05075,-0.574544, + -0.788495,-0.519776,-0.328798,1.2332,0.121222,-0.580972, + -0.853449,-0.521176,0,1.222911,0.113669,-0.5, + -0.637408,-0.358226,-0.682191,1.301556,0.067036,-0.636664, + -0.575759,-0.440808,-0.688615,1.264067,0.143881,-0.648448, + -0.788495,-0.519776,-0.328798,1.2332,0.121222,-0.580972, + -0.637408,-0.358226,-0.682191,1.301556,0.067036,-0.636664, + -0.788495,-0.519776,-0.328798,1.2332,0.121222,-0.580972, + -0.849326,-0.416862,-0.323838,1.271198,0.05075,-0.574544, + -0.715537,-0.612433,0.336055,1.195018,0.176099,-0.412264, + -0.503423,-0.512227,0.695837,1.226863,0.204423,-0.339151, + -0.575759,-0.440808,0.688615,1.264067,0.143881,-0.351552, + -0.575759,-0.440808,0.688615,1.264067,0.143881,-0.351552, + -0.788495,-0.519776,0.328798,1.2332,0.121222,-0.419028, + -0.715537,-0.612433,0.336055,1.195018,0.176099,-0.412264, + -0.637408,-0.358226,0.682191,1.301556,0.067036,-0.363336, + -0.849326,-0.416862,0.323838,1.271198,0.05075,-0.425456, + -0.788495,-0.519776,0.328798,1.2332,0.121222,-0.419028, + -0.637408,-0.358226,0.682191,1.301556,0.067036,-0.363336, + -0.788495,-0.519776,0.328798,1.2332,0.121222,-0.419028, + -0.575759,-0.440808,0.688615,1.264067,0.143881,-0.351552, + -0.849326,-0.416862,0.323838,1.271198,0.05075,-0.425456, + -0.912287,-0.409552,0,1.261078,0.045321,-0.5, + -0.853449,-0.521176,0,1.222911,0.113669,-0.5, + -0.853449,-0.521176,0,1.222911,0.113669,-0.5, + -0.788495,-0.519776,0.328798,1.2332,0.121222,-0.419028, + -0.849326,-0.416862,0.323838,1.271198,0.05075,-0.425456, + -0.784292,-0.620391,0,1.184403,0.166658,-0.5, + -0.715537,-0.612433,0.336055,1.195018,0.176099,-0.412264, + -0.788495,-0.519776,0.328798,1.2332,0.121222,-0.419028, + -0.784292,-0.620391,0,1.184403,0.166658,-0.5, + -0.788495,-0.519776,0.328798,1.2332,0.121222,-0.419028, + -0.853449,-0.521176,0,1.222911,0.113669,-0.5, + -0.714149,-0.110296,0.691249,1.356947,-0.122198,-0.375951, + -0.933801,-0.132296,0.332437,1.325262,-0.127256,-0.432337, + -0.899929,-0.290508,0.325166,1.303667,-0.032887,-0.430306, + -0.714149,-0.110296,0.691249,1.356947,-0.122198,-0.375951, + -0.899929,-0.290508,0.325166,1.303667,-0.032887,-0.430306, + -0.686016,-0.251158,0.682863,1.33422,-0.022771,-0.372228, + -0.933801,-0.132296,0.332437,1.325262,-0.127256,-0.432337, + -0.994338,-0.106266,0,1.314701,-0.128942,-0.5, + -0.961859,-0.273547,0,1.293483,-0.036258,-0.5, + -0.961859,-0.273547,0,1.293483,-0.036258,-0.5, + -0.899929,-0.290508,0.325166,1.303667,-0.032887,-0.430306, + -0.933801,-0.132296,0.332437,1.325262,-0.127256,-0.432337, + -0.912287,-0.409552,0,1.261078,0.045321,-0.5, + -0.849326,-0.416862,0.323838,1.271198,0.05075,-0.425456, + -0.899929,-0.290508,0.325166,1.303667,-0.032887,-0.430306, + -0.912287,-0.409552,0,1.261078,0.045321,-0.5, + -0.899929,-0.290508,0.325166,1.303667,-0.032887,-0.430306, + -0.961859,-0.273547,0,1.293483,-0.036258,-0.5, + -0.849326,-0.416862,0.323838,1.271198,0.05075,-0.425456, + -0.637408,-0.358226,0.682191,1.301556,0.067036,-0.363336, + -0.686016,-0.251158,0.682863,1.33422,-0.022771,-0.372228, + -0.686016,-0.251158,0.682863,1.33422,-0.022771,-0.372228, + -0.899929,-0.290508,0.325166,1.303667,-0.032887,-0.430306, + -0.849326,-0.416862,0.323838,1.271198,0.05075,-0.425456, + -0.71415,-0.110296,-0.691249,1.356947,-0.122198,-0.624049, + -0.686016,-0.251158,-0.682863,1.33422,-0.022771,-0.627772, + -0.899929,-0.290508,-0.325166,1.303667,-0.032887,-0.569694, + -0.71415,-0.110296,-0.691249,1.356947,-0.122198,-0.624049, + -0.899929,-0.290508,-0.325166,1.303667,-0.032887,-0.569694, + -0.933801,-0.132296,-0.332437,1.325262,-0.127256,-0.567663, + -0.686016,-0.251158,-0.682863,1.33422,-0.022771,-0.627772, + -0.637408,-0.358226,-0.682191,1.301556,0.067036,-0.636664, + -0.849326,-0.416862,-0.323838,1.271198,0.05075,-0.574544, + -0.849326,-0.416862,-0.323838,1.271198,0.05075,-0.574544, + -0.899929,-0.290508,-0.325166,1.303667,-0.032887,-0.569694, + -0.686016,-0.251158,-0.682863,1.33422,-0.022771,-0.627772, + -0.912287,-0.409552,0,1.261078,0.045321,-0.5, + -0.961859,-0.273547,0,1.293483,-0.036258,-0.5, + -0.899929,-0.290508,-0.325166,1.303667,-0.032887,-0.569694, + -0.912287,-0.409552,0,1.261078,0.045321,-0.5, + -0.899929,-0.290508,-0.325166,1.303667,-0.032887,-0.569694, + -0.849326,-0.416862,-0.323838,1.271198,0.05075,-0.574544, + -0.961859,-0.273547,0,1.293483,-0.036258,-0.5, + -0.994338,-0.106266,0,1.314701,-0.128942,-0.5, + -0.933801,-0.132296,-0.332437,1.325262,-0.127256,-0.567663, + -0.933801,-0.132296,-0.332437,1.325262,-0.127256,-0.567663, + -0.899929,-0.290508,-0.325166,1.303667,-0.032887,-0.569694, + -0.961859,-0.273547,0,1.293483,-0.036258,-0.5, + -0.693871,0.192788,-0.693812,1.351552,-0.429344,-0.648448, + -0.686951,0.237061,-0.686951,1.339151,-0.510672,-0.660849, + -0.336776,0.225597,-0.91416,1.412264,-0.510672,-0.704717, + -0.336776,0.225597,-0.91416,1.412264,-0.510672,-0.704717, + -0.340683,0.181594,-0.922474,1.419028,-0.429344,-0.688934, + -0.693871,0.192788,-0.693812,1.351552,-0.429344,-0.648448, + 0,0.216323,-0.976322,1.5,-0.510672,-0.71934, + -0.000776,0.175432,-0.984491,1.5,-0.429344,-0.70243, + -0.340683,0.181594,-0.922474,1.419028,-0.429344,-0.688934, + 0,0.216323,-0.976322,1.5,-0.510672,-0.71934, + -0.340683,0.181594,-0.922474,1.419028,-0.429344,-0.688934, + -0.336776,0.225597,-0.91416,1.412264,-0.510672,-0.704717, + -0.000776,0.175432,-0.984491,1.5,-0.429344,-0.70243, + -0.003469,0.126882,-0.991912,1.497312,-0.330832,-0.68636, + -0.347569,0.124206,-0.929392,1.423198,-0.331844,-0.673936, + -0.347569,0.124206,-0.929392,1.423198,-0.331844,-0.673936, + -0.340683,0.181594,-0.922474,1.419028,-0.429344,-0.688934, + -0.000776,0.175432,-0.984491,1.5,-0.429344,-0.70243, + -0.702754,0.131399,-0.699193,1.361436,-0.332687,-0.636664, + -0.693871,0.192788,-0.693812,1.351552,-0.429344,-0.648448, + -0.340683,0.181594,-0.922474,1.419028,-0.429344,-0.688934, + -0.702754,0.131399,-0.699193,1.361436,-0.332687,-0.636664, + -0.340683,0.181594,-0.922474,1.419028,-0.429344,-0.688934, + -0.347569,0.124206,-0.929392,1.423198,-0.331844,-0.673936, + 0.336776,0.225597,-0.91416,1.587736,-0.510672,-0.704717, + 0.686951,0.237061,-0.686951,1.660849,-0.510672,-0.660849, + 0.692333,0.202928,-0.692456,1.648448,-0.429344,-0.648448, + 0.692333,0.202928,-0.692456,1.648448,-0.429344,-0.648448, + 0.339336,0.190036,-0.92127,1.580972,-0.429344,-0.688934, + 0.336776,0.225597,-0.91416,1.587736,-0.510672,-0.704717, + 0.695529,0.18142,-0.695217,1.633189,-0.328978,-0.636664, + 0.341595,0.155693,-0.926862,1.571427,-0.329821,-0.673936, + 0.339336,0.190036,-0.92127,1.580972,-0.429344,-0.688934, + 0.695529,0.18142,-0.695217,1.633189,-0.328978,-0.636664, + 0.339336,0.190036,-0.92127,1.580972,-0.429344,-0.688934, + 0.692333,0.202928,-0.692456,1.648448,-0.429344,-0.648448, + 0.341595,0.155693,-0.926862,1.571427,-0.329821,-0.673936, + -0.003469,0.126882,-0.991912,1.497312,-0.330832,-0.68636, + -0.000776,0.175432,-0.984491,1.5,-0.429344,-0.70243, + -0.000776,0.175432,-0.984491,1.5,-0.429344,-0.70243, + 0.339336,0.190036,-0.92127,1.580972,-0.429344,-0.688934, + 0.341595,0.155693,-0.926862,1.571427,-0.329821,-0.673936, + 0,0.216323,-0.976322,1.5,-0.510672,-0.71934, + 0.336776,0.225597,-0.91416,1.587736,-0.510672,-0.704717, + 0.339336,0.190036,-0.92127,1.580972,-0.429344,-0.688934, + 0,0.216323,-0.976322,1.5,-0.510672,-0.71934, + 0.339336,0.190036,-0.92127,1.580972,-0.429344,-0.688934, + -0.000776,0.175432,-0.984491,1.5,-0.429344,-0.70243, + 0.68395,0.1429,-0.715397,1.589301,-0.085107,-0.624049, + 0.294772,0.058288,-0.953788,1.536493,-0.093537,-0.657881, + 0.345572,0.118142,-0.930926,1.557226,-0.21644,-0.662619, + 0.68395,0.1429,-0.715397,1.589301,-0.085107,-0.624049, + 0.345572,0.118142,-0.930926,1.557226,-0.21644,-0.662619, + 0.699329,0.164944,-0.695509,1.613873,-0.213068,-0.627772, + 0.294772,0.058288,-0.953788,1.536493,-0.093537,-0.657881, + -0.032665,-0.015822,-0.999341,1.473124,-0.103652,-0.669158, + -0.00536,0.065692,-0.997826,1.489249,-0.220486,-0.674234, + -0.00536,0.065692,-0.997826,1.489249,-0.220486,-0.674234, + 0.345572,0.118142,-0.930926,1.557226,-0.21644,-0.662619, + 0.294772,0.058288,-0.953788,1.536493,-0.093537,-0.657881, + -0.003469,0.126882,-0.991912,1.497312,-0.330832,-0.68636, + 0.341595,0.155693,-0.926862,1.571427,-0.329821,-0.673936, + 0.345572,0.118142,-0.930926,1.557226,-0.21644,-0.662619, + -0.003469,0.126882,-0.991912,1.497312,-0.330832,-0.68636, + 0.345572,0.118142,-0.930926,1.557226,-0.21644,-0.662619, + -0.00536,0.065692,-0.997826,1.489249,-0.220486,-0.674234, + 0.341595,0.155693,-0.926862,1.571427,-0.329821,-0.673936, + 0.695529,0.18142,-0.695217,1.633189,-0.328978,-0.636664, + 0.699329,0.164944,-0.695509,1.613873,-0.213068,-0.627772, + 0.699329,0.164944,-0.695509,1.613873,-0.213068,-0.627772, + 0.345572,0.118142,-0.930926,1.557226,-0.21644,-0.662619, + 0.341595,0.155693,-0.926862,1.571427,-0.329821,-0.673936, + -0.71415,-0.110296,-0.691249,1.356947,-0.122198,-0.624049, + -0.739331,0.03305,-0.672531,1.364627,-0.227904,-0.627772, + -0.356256,0.046266,-0.933242,1.421273,-0.224532,-0.662619, + -0.71415,-0.110296,-0.691249,1.356947,-0.122198,-0.624049, + -0.356256,0.046266,-0.933242,1.421273,-0.224532,-0.662619, + -0.355153,-0.061801,-0.932763,1.409755,-0.113768,-0.657881, + -0.739331,0.03305,-0.672531,1.364627,-0.227904,-0.627772, + -0.702754,0.131399,-0.699193,1.361436,-0.332687,-0.636664, + -0.347569,0.124206,-0.929392,1.423198,-0.331844,-0.673936, + -0.347569,0.124206,-0.929392,1.423198,-0.331844,-0.673936, + -0.356256,0.046266,-0.933242,1.421273,-0.224532,-0.662619, + -0.739331,0.03305,-0.672531,1.364627,-0.227904,-0.627772, + -0.003469,0.126882,-0.991912,1.497312,-0.330832,-0.68636, + -0.00536,0.065692,-0.997826,1.489249,-0.220486,-0.674234, + -0.356256,0.046266,-0.933242,1.421273,-0.224532,-0.662619, + -0.003469,0.126882,-0.991912,1.497312,-0.330832,-0.68636, + -0.356256,0.046266,-0.933242,1.421273,-0.224532,-0.662619, + -0.347569,0.124206,-0.929392,1.423198,-0.331844,-0.673936, + -0.00536,0.065692,-0.997826,1.489249,-0.220486,-0.674234, + -0.032665,-0.015822,-0.999341,1.473124,-0.103652,-0.669158, + -0.355153,-0.061801,-0.932763,1.409755,-0.113768,-0.657881, + -0.355153,-0.061801,-0.932763,1.409755,-0.113768,-0.657881, + -0.356256,0.046266,-0.933242,1.421273,-0.224532,-0.662619, + -0.00536,0.065692,-0.997826,1.489249,-0.220486,-0.674234, + -0.914159,0.225597,-0.336777,1.295283,-0.510672,-0.587736, + -0.686951,0.237061,-0.686951,1.339151,-0.510672,-0.660849, + -0.693871,0.192788,-0.693812,1.351552,-0.429344,-0.648448, + -0.693871,0.192788,-0.693812,1.351552,-0.429344,-0.648448, + -0.923459,0.178536,-0.339629,1.311066,-0.429344,-0.580972, + -0.914159,0.225597,-0.336777,1.295283,-0.510672,-0.587736, + -0.702754,0.131399,-0.699193,1.361436,-0.332687,-0.636664, + -0.933761,0.111444,-0.340103,1.324378,-0.333193,-0.574544, + -0.923459,0.178536,-0.339629,1.311066,-0.429344,-0.580972, + -0.702754,0.131399,-0.699193,1.361436,-0.332687,-0.636664, + -0.923459,0.178536,-0.339629,1.311066,-0.429344,-0.580972, + -0.693871,0.192788,-0.693812,1.351552,-0.429344,-0.648448, + -0.933761,0.111444,-0.340103,1.324378,-0.333193,-0.574544, + -0.995379,0.096022,0,1.312026,-0.333361,-0.5, + -0.985978,0.166878,0,1.29757,-0.429344,-0.5, + -0.985978,0.166878,0,1.29757,-0.429344,-0.5, + -0.923459,0.178536,-0.339629,1.311066,-0.429344,-0.580972, + -0.933761,0.111444,-0.340103,1.324378,-0.333193,-0.574544, + -0.976322,0.216322,0,1.28066,-0.510672,-0.5, + -0.914159,0.225597,-0.336777,1.295283,-0.510672,-0.587736, + -0.923459,0.178536,-0.339629,1.311066,-0.429344,-0.580972, + -0.976322,0.216322,0,1.28066,-0.510672,-0.5, + -0.923459,0.178536,-0.339629,1.311066,-0.429344,-0.580972, + -0.985978,0.166878,0,1.29757,-0.429344,-0.5, + -0.739331,0.03305,-0.672531,1.364627,-0.227904,-0.627772, + -0.71415,-0.110296,-0.691249,1.356947,-0.122198,-0.624049, + -0.933801,-0.132296,-0.332437,1.325262,-0.127256,-0.567663, + -0.933801,-0.132296,-0.332437,1.325262,-0.127256,-0.567663, + -0.960211,0.01432,-0.27891,1.330638,-0.229927,-0.569694, + -0.739331,0.03305,-0.672531,1.364627,-0.227904,-0.627772, + -0.994338,-0.106266,0,1.314701,-0.128942,-0.5, + -0.999919,0.012734,0,1.319309,-0.230602,-0.5, + -0.960211,0.01432,-0.27891,1.330638,-0.229927,-0.569694, + -0.994338,-0.106266,0,1.314701,-0.128942,-0.5, + -0.960211,0.01432,-0.27891,1.330638,-0.229927,-0.569694, + -0.933801,-0.132296,-0.332437,1.325262,-0.127256,-0.567663, + -0.995379,0.096022,0,1.312026,-0.333361,-0.5, + -0.933761,0.111444,-0.340103,1.324378,-0.333193,-0.574544, + -0.960211,0.01432,-0.27891,1.330638,-0.229927,-0.569694, + -0.995379,0.096022,0,1.312026,-0.333361,-0.5, + -0.960211,0.01432,-0.27891,1.330638,-0.229927,-0.569694, + -0.999919,0.012734,0,1.319309,-0.230602,-0.5, + -0.933761,0.111444,-0.340103,1.324378,-0.333193,-0.574544, + -0.702754,0.131399,-0.699193,1.361436,-0.332687,-0.636664, + -0.739331,0.03305,-0.672531,1.364627,-0.227904,-0.627772, + -0.739331,0.03305,-0.672531,1.364627,-0.227904,-0.627772, + -0.960211,0.01432,-0.27891,1.330638,-0.229927,-0.569694, + -0.933761,0.111444,-0.340103,1.324378,-0.333193,-0.574544, + -0.933801,-0.132296,0.332437,1.325262,-0.127256,-0.432337, + -0.714149,-0.110296,0.691249,1.356947,-0.122198,-0.375951, + -0.739331,0.03305,0.672531,1.364627,-0.227904,-0.372228, + -0.739331,0.03305,0.672531,1.364627,-0.227904,-0.372228, + -0.960211,0.01432,0.27891,1.330638,-0.229927,-0.430306, + -0.933801,-0.132296,0.332437,1.325262,-0.127256,-0.432337, + -0.739331,0.03305,0.672531,1.364627,-0.227904,-0.372228, + -0.702754,0.131399,0.699193,1.361436,-0.332687,-0.363336, + -0.933761,0.111444,0.340103,1.324378,-0.333193,-0.425456, + -0.933761,0.111444,0.340103,1.324378,-0.333193,-0.425456, + -0.960211,0.01432,0.27891,1.330638,-0.229927,-0.430306, + -0.739331,0.03305,0.672531,1.364627,-0.227904,-0.372228, + -0.995379,0.096022,0,1.312026,-0.333361,-0.5, + -0.999919,0.012734,0,1.319309,-0.230602,-0.5, + -0.960211,0.01432,0.27891,1.330638,-0.229927,-0.430306, + -0.995379,0.096022,0,1.312026,-0.333361,-0.5, + -0.960211,0.01432,0.27891,1.330638,-0.229927,-0.430306, + -0.933761,0.111444,0.340103,1.324378,-0.333193,-0.425456, + -0.994338,-0.106266,0,1.314701,-0.128942,-0.5, + -0.933801,-0.132296,0.332437,1.325262,-0.127256,-0.432337, + -0.960211,0.01432,0.27891,1.330638,-0.229927,-0.430306, + -0.994338,-0.106266,0,1.314701,-0.128942,-0.5, + -0.960211,0.01432,0.27891,1.330638,-0.229927,-0.430306, + -0.999919,0.012734,0,1.319309,-0.230602,-0.5, + -0.693871,0.192788,0.693812,1.351552,-0.429344,-0.351552, + -0.68695,0.237061,0.686951,1.339151,-0.510672,-0.339151, + -0.914159,0.225597,0.336777,1.295283,-0.510672,-0.412264, + -0.914159,0.225597,0.336777,1.295283,-0.510672,-0.412264, + -0.923459,0.178536,0.339629,1.311066,-0.429344,-0.419028, + -0.693871,0.192788,0.693812,1.351552,-0.429344,-0.351552, + -0.976322,0.216322,0,1.28066,-0.510672,-0.5, + -0.985978,0.166878,0,1.29757,-0.429344,-0.5, + -0.923459,0.178536,0.339629,1.311066,-0.429344,-0.419028, + -0.976322,0.216322,0,1.28066,-0.510672,-0.5, + -0.923459,0.178536,0.339629,1.311066,-0.429344,-0.419028, + -0.914159,0.225597,0.336777,1.295283,-0.510672,-0.412264, + -0.985978,0.166878,0,1.29757,-0.429344,-0.5, + -0.995379,0.096022,0,1.312026,-0.333361,-0.5, + -0.933761,0.111444,0.340103,1.324378,-0.333193,-0.425456, + -0.933761,0.111444,0.340103,1.324378,-0.333193,-0.425456, + -0.923459,0.178536,0.339629,1.311066,-0.429344,-0.419028, + -0.985978,0.166878,0,1.29757,-0.429344,-0.5, + -0.702754,0.131399,0.699193,1.361436,-0.332687,-0.363336, + -0.693871,0.192788,0.693812,1.351552,-0.429344,-0.351552, + -0.923459,0.178536,0.339629,1.311066,-0.429344,-0.419028, + -0.702754,0.131399,0.699193,1.361436,-0.332687,-0.363336, + -0.923459,0.178536,0.339629,1.311066,-0.429344,-0.419028, + -0.933761,0.111444,0.340103,1.324378,-0.333193,-0.425456, + -0.336776,0.225598,0.914159,1.412264,-0.510672,-0.295283, + -0.68695,0.237061,0.686951,1.339151,-0.510672,-0.339151, + -0.693871,0.192788,0.693812,1.351552,-0.429344,-0.351552, + -0.693871,0.192788,0.693812,1.351552,-0.429344,-0.351552, + -0.340683,0.181594,0.922474,1.419028,-0.429344,-0.311066, + -0.336776,0.225598,0.914159,1.412264,-0.510672,-0.295283, + -0.702754,0.131399,0.699193,1.361436,-0.332687,-0.363336, + -0.347569,0.124206,0.929392,1.423198,-0.331844,-0.326064, + -0.340683,0.181594,0.922474,1.419028,-0.429344,-0.311066, + -0.702754,0.131399,0.699193,1.361436,-0.332687,-0.363336, + -0.340683,0.181594,0.922474,1.419028,-0.429344,-0.311066, + -0.693871,0.192788,0.693812,1.351552,-0.429344,-0.351552, + -0.347569,0.124206,0.929392,1.423198,-0.331844,-0.326064, + -0.003469,0.126882,0.991912,1.497312,-0.330832,-0.31364, + -0.000776,0.175432,0.984491,1.5,-0.429344,-0.29757, + -0.000776,0.175432,0.984491,1.5,-0.429344,-0.29757, + -0.340683,0.181594,0.922474,1.419028,-0.429344,-0.311066, + -0.347569,0.124206,0.929392,1.423198,-0.331844,-0.326064, + 0,0.216323,0.976322,1.5,-0.510672,-0.28066, + -0.336776,0.225598,0.914159,1.412264,-0.510672,-0.295283, + -0.340683,0.181594,0.922474,1.419028,-0.429344,-0.311066, + 0,0.216323,0.976322,1.5,-0.510672,-0.28066, + -0.340683,0.181594,0.922474,1.419028,-0.429344,-0.311066, + -0.000776,0.175432,0.984491,1.5,-0.429344,-0.29757, + -0.714149,-0.110296,0.691249,1.356947,-0.122198,-0.375951, + -0.355153,-0.061801,0.932763,1.409755,-0.113768,-0.342119, + -0.356256,0.046266,0.933242,1.421273,-0.224532,-0.337381, + -0.714149,-0.110296,0.691249,1.356947,-0.122198,-0.375951, + -0.356256,0.046266,0.933242,1.421273,-0.224532,-0.337381, + -0.739331,0.03305,0.672531,1.364627,-0.227904,-0.372228, + -0.355153,-0.061801,0.932763,1.409755,-0.113768,-0.342119, + -0.032665,-0.015822,0.999341,1.473124,-0.103652,-0.330842, + -0.005359,0.065692,0.997826,1.489249,-0.220486,-0.325766, + -0.005359,0.065692,0.997826,1.489249,-0.220486,-0.325766, + -0.356256,0.046266,0.933242,1.421273,-0.224532,-0.337381, + -0.355153,-0.061801,0.932763,1.409755,-0.113768,-0.342119, + -0.003469,0.126882,0.991912,1.497312,-0.330832,-0.31364, + -0.347569,0.124206,0.929392,1.423198,-0.331844,-0.326064, + -0.356256,0.046266,0.933242,1.421273,-0.224532,-0.337381, + -0.003469,0.126882,0.991912,1.497312,-0.330832,-0.31364, + -0.356256,0.046266,0.933242,1.421273,-0.224532,-0.337381, + -0.005359,0.065692,0.997826,1.489249,-0.220486,-0.325766, + -0.347569,0.124206,0.929392,1.423198,-0.331844,-0.326064, + -0.702754,0.131399,0.699193,1.361436,-0.332687,-0.363336, + -0.739331,0.03305,0.672531,1.364627,-0.227904,-0.372228, + -0.739331,0.03305,0.672531,1.364627,-0.227904,-0.372228, + -0.356256,0.046266,0.933242,1.421273,-0.224532,-0.337381, + -0.347569,0.124206,0.929392,1.423198,-0.331844,-0.326064, + 0.68395,0.1429,0.715397,1.589301,-0.085107,-0.375951, + 0.699329,0.164944,0.695509,1.613873,-0.213068,-0.372228, + 0.345572,0.118142,0.930926,1.557226,-0.21644,-0.337381, + 0.68395,0.1429,0.715397,1.589301,-0.085107,-0.375951, + 0.345572,0.118142,0.930926,1.557226,-0.21644,-0.337381, + 0.294772,0.058287,0.953788,1.536493,-0.093537,-0.342119, + 0.699329,0.164944,0.695509,1.613873,-0.213068,-0.372228, + 0.695529,0.18142,0.695217,1.633189,-0.328978,-0.363336, + 0.341595,0.155693,0.926862,1.571427,-0.329821,-0.326064, + 0.341595,0.155693,0.926862,1.571427,-0.329821,-0.326064, + 0.345572,0.118142,0.930926,1.557226,-0.21644,-0.337381, + 0.699329,0.164944,0.695509,1.613873,-0.213068,-0.372228, + -0.003469,0.126882,0.991912,1.497312,-0.330832,-0.31364, + -0.005359,0.065692,0.997826,1.489249,-0.220486,-0.325766, + 0.345572,0.118142,0.930926,1.557226,-0.21644,-0.337381, + -0.003469,0.126882,0.991912,1.497312,-0.330832,-0.31364, + 0.345572,0.118142,0.930926,1.557226,-0.21644,-0.337381, + 0.341595,0.155693,0.926862,1.571427,-0.329821,-0.326064, + -0.005359,0.065692,0.997826,1.489249,-0.220486,-0.325766, + -0.032665,-0.015822,0.999341,1.473124,-0.103652,-0.330842, + 0.294772,0.058287,0.953788,1.536493,-0.093537,-0.342119, + 0.294772,0.058287,0.953788,1.536493,-0.093537,-0.342119, + 0.345572,0.118142,0.930926,1.557226,-0.21644,-0.337381, + -0.005359,0.065692,0.997826,1.489249,-0.220486,-0.325766, + 0.692333,0.202929,0.692456,1.648448,-0.429344,-0.351552, + 0.68695,0.237061,0.686951,1.660849,-0.510672,-0.339151, + 0.336776,0.225598,0.914159,1.587736,-0.510672,-0.295283, + 0.336776,0.225598,0.914159,1.587736,-0.510672,-0.295283, + 0.339336,0.190036,0.921269,1.580972,-0.429344,-0.311066, + 0.692333,0.202929,0.692456,1.648448,-0.429344,-0.351552, + 0,0.216323,0.976322,1.5,-0.510672,-0.28066, + -0.000776,0.175432,0.984491,1.5,-0.429344,-0.29757, + 0.339336,0.190036,0.921269,1.580972,-0.429344,-0.311066, + 0,0.216323,0.976322,1.5,-0.510672,-0.28066, + 0.339336,0.190036,0.921269,1.580972,-0.429344,-0.311066, + 0.336776,0.225598,0.914159,1.587736,-0.510672,-0.295283, + -0.000776,0.175432,0.984491,1.5,-0.429344,-0.29757, + -0.003469,0.126882,0.991912,1.497312,-0.330832,-0.31364, + 0.341595,0.155693,0.926862,1.571427,-0.329821,-0.326064, + 0.341595,0.155693,0.926862,1.571427,-0.329821,-0.326064, + 0.339336,0.190036,0.921269,1.580972,-0.429344,-0.311066, + -0.000776,0.175432,0.984491,1.5,-0.429344,-0.29757, + 0.695529,0.18142,0.695217,1.633189,-0.328978,-0.363336, + 0.692333,0.202929,0.692456,1.648448,-0.429344,-0.351552, + 0.339336,0.190036,0.921269,1.580972,-0.429344,-0.311066, + 0.695529,0.18142,0.695217,1.633189,-0.328978,-0.363336, + 0.339336,0.190036,0.921269,1.580972,-0.429344,-0.311066, + 0.341595,0.155693,0.926862,1.571427,-0.329821,-0.326064, + 0.914159,0.225597,0.336777,1.704717,-0.510672,-0.412264, + 0.68695,0.237061,0.686951,1.660849,-0.510672,-0.339151, + 0.692333,0.202929,0.692456,1.648448,-0.429344,-0.351552, + 0.692333,0.202929,0.692456,1.648448,-0.429344,-0.351552, + 0.919751,0.19868,0.338503,1.688934,-0.429344,-0.419028, + 0.914159,0.225597,0.336777,1.704717,-0.510672,-0.412264, + 0.695529,0.18142,0.695217,1.633189,-0.328978,-0.363336, + 0.921783,0.189963,0.337979,1.670246,-0.328472,-0.425456, + 0.919751,0.19868,0.338503,1.688934,-0.429344,-0.419028, + 0.695529,0.18142,0.695217,1.633189,-0.328978,-0.363336, + 0.919751,0.19868,0.338503,1.688934,-0.429344,-0.419028, + 0.692333,0.202929,0.692456,1.648448,-0.429344,-0.351552, + 0.921783,0.189963,0.337979,1.670246,-0.328472,-0.425456, + 0.981065,0.19368,0,1.682599,-0.328303,-0.5, + 0.980577,0.196136,0,1.70243,-0.429344,-0.5, + 0.980577,0.196136,0,1.70243,-0.429344,-0.5, + 0.919751,0.19868,0.338503,1.688934,-0.429344,-0.419028, + 0.921783,0.189963,0.337979,1.670246,-0.328472,-0.425456, + 0.976322,0.216322,0,1.71934,-0.510672,-0.5, + 0.914159,0.225597,0.336777,1.704717,-0.510672,-0.412264, + 0.919751,0.19868,0.338503,1.688934,-0.429344,-0.419028, + 0.976322,0.216322,0,1.71934,-0.510672,-0.5, + 0.919751,0.19868,0.338503,1.688934,-0.429344,-0.419028, + 0.980577,0.196136,0,1.70243,-0.429344,-0.5, + 0.68395,0.1429,0.715397,1.589301,-0.085107,-0.375951, + 0.923419,0.19798,0.328787,1.620986,-0.080049,-0.432337, + 0.922767,0.190694,0.334869,1.647861,-0.211045,-0.430306, + 0.68395,0.1429,0.715397,1.589301,-0.085107,-0.375951, + 0.922767,0.190694,0.334869,1.647861,-0.211045,-0.430306, + 0.699329,0.164944,0.695509,1.613873,-0.213068,-0.372228, + 0.923419,0.19798,0.328787,1.620986,-0.080049,-0.432337, + 0.976556,0.215262,0,1.631547,-0.078363,-0.5, + 0.979589,0.201011,0,1.65919,-0.21037,-0.5, + 0.979589,0.201011,0,1.65919,-0.21037,-0.5, + 0.922767,0.190694,0.334869,1.647861,-0.211045,-0.430306, + 0.923419,0.19798,0.328787,1.620986,-0.080049,-0.432337, + 0.981065,0.19368,0,1.682599,-0.328303,-0.5, + 0.921783,0.189963,0.337979,1.670246,-0.328472,-0.425456, + 0.922767,0.190694,0.334869,1.647861,-0.211045,-0.430306, + 0.981065,0.19368,0,1.682599,-0.328303,-0.5, + 0.922767,0.190694,0.334869,1.647861,-0.211045,-0.430306, + 0.979589,0.201011,0,1.65919,-0.21037,-0.5, + 0.921783,0.189963,0.337979,1.670246,-0.328472,-0.425456, + 0.695529,0.18142,0.695217,1.633189,-0.328978,-0.363336, + 0.699329,0.164944,0.695509,1.613873,-0.213068,-0.372228, + 0.699329,0.164944,0.695509,1.613873,-0.213068,-0.372228, + 0.922767,0.190694,0.334869,1.647861,-0.211045,-0.430306, + 0.921783,0.189963,0.337979,1.670246,-0.328472,-0.425456, + 0.68395,0.1429,-0.715397,1.589301,-0.085107,-0.624049, + 0.699329,0.164944,-0.695509,1.613873,-0.213068,-0.627772, + 0.922767,0.190694,-0.334869,1.647861,-0.211045,-0.569694, + 0.68395,0.1429,-0.715397,1.589301,-0.085107,-0.624049, + 0.922767,0.190694,-0.334869,1.647861,-0.211045,-0.569694, + 0.923419,0.19798,-0.328787,1.620986,-0.080049,-0.567663, + 0.699329,0.164944,-0.695509,1.613873,-0.213068,-0.627772, + 0.695529,0.18142,-0.695217,1.633189,-0.328978,-0.636664, + 0.921783,0.189963,-0.337979,1.670246,-0.328472,-0.574544, + 0.921783,0.189963,-0.337979,1.670246,-0.328472,-0.574544, + 0.922767,0.190694,-0.334869,1.647861,-0.211045,-0.569694, + 0.699329,0.164944,-0.695509,1.613873,-0.213068,-0.627772, + 0.981065,0.19368,0,1.682599,-0.328303,-0.5, + 0.979589,0.201011,0,1.65919,-0.21037,-0.5, + 0.922767,0.190694,-0.334869,1.647861,-0.211045,-0.569694, + 0.981065,0.19368,0,1.682599,-0.328303,-0.5, + 0.922767,0.190694,-0.334869,1.647861,-0.211045,-0.569694, + 0.921783,0.189963,-0.337979,1.670246,-0.328472,-0.574544, + 0.979589,0.201011,0,1.65919,-0.21037,-0.5, + 0.976556,0.215262,0,1.631547,-0.078363,-0.5, + 0.923419,0.19798,-0.328787,1.620986,-0.080049,-0.567663, + 0.923419,0.19798,-0.328787,1.620986,-0.080049,-0.567663, + 0.922767,0.190694,-0.334869,1.647861,-0.211045,-0.569694, + 0.979589,0.201011,0,1.65919,-0.21037,-0.5, + 0.692333,0.202928,-0.692456,1.648448,-0.429344,-0.648448, + 0.686951,0.237061,-0.686951,1.660849,-0.510672,-0.660849, + 0.914159,0.225597,-0.336777,1.704717,-0.510672,-0.587736, + 0.914159,0.225597,-0.336777,1.704717,-0.510672,-0.587736, + 0.919751,0.19868,-0.338503,1.688934,-0.429344,-0.580972, + 0.692333,0.202928,-0.692456,1.648448,-0.429344,-0.648448, + 0.976322,0.216322,0,1.71934,-0.510672,-0.5, + 0.980577,0.196136,0,1.70243,-0.429344,-0.5, + 0.919751,0.19868,-0.338503,1.688934,-0.429344,-0.580972, + 0.976322,0.216322,0,1.71934,-0.510672,-0.5, + 0.919751,0.19868,-0.338503,1.688934,-0.429344,-0.580972, + 0.914159,0.225597,-0.336777,1.704717,-0.510672,-0.587736, + 0.980577,0.196136,0,1.70243,-0.429344,-0.5, + 0.981065,0.19368,0,1.682599,-0.328303,-0.5, + 0.921783,0.189963,-0.337979,1.670246,-0.328472,-0.574544, + 0.921783,0.189963,-0.337979,1.670246,-0.328472,-0.574544, + 0.919751,0.19868,-0.338503,1.688934,-0.429344,-0.580972, + 0.980577,0.196136,0,1.70243,-0.429344,-0.5, + 0.695529,0.18142,-0.695217,1.633189,-0.328978,-0.636664, + 0.692333,0.202928,-0.692456,1.648448,-0.429344,-0.648448, + 0.919751,0.19868,-0.338503,1.688934,-0.429344,-0.580972, + 0.695529,0.18142,-0.695217,1.633189,-0.328978,-0.636664, + 0.919751,0.19868,-0.338503,1.688934,-0.429344,-0.580972, + 0.921783,0.189963,-0.337979,1.670246,-0.328472,-0.574544, + 0.68695,0.237061,0.686951,1.660849,-0.510672,-0.339151, + 0.914159,0.225597,0.336777,1.704717,-0.510672,-0.412264, + 0.925394,0.167122,0.340171,1.718387,-0.569469,-0.406406, + 0.68695,0.237061,0.686951,1.660849,-0.510672,-0.339151, + 0.925394,0.167122,0.340171,1.718387,-0.569469,-0.406406, + 0.700149,0.139938,0.700149,1.67159,-0.569469,-0.32841, + 0.914159,0.225597,0.336777,1.704717,-0.510672,-0.412264, + 0.976322,0.216322,0,1.71934,-0.510672,-0.5, + 0.981432,0.191813,0,1.733986,-0.569469,-0.5, + 0.981432,0.191813,0,1.733986,-0.569469,-0.5, + 0.925394,0.167122,0.340171,1.718387,-0.569469,-0.406406, + 0.914159,0.225597,0.336777,1.704717,-0.510672,-0.412264, + 0.968451,-0.249205,0,1.737621,-0.609501,-0.5, + 0.878536,-0.271725,0.392861,1.721597,-0.609197,-0.405226, + 0.925394,0.167122,0.340171,1.718387,-0.569469,-0.406406, + 0.968451,-0.249205,0,1.737621,-0.609501,-0.5, + 0.925394,0.167122,0.340171,1.718387,-0.569469,-0.406406, + 0.981432,0.191813,0,1.733986,-0.569469,-0.5, + 0.878536,-0.271725,0.392861,1.721597,-0.609197,-0.405226, + 0.676292,-0.291987,0.676293,1.673866,-0.608893,-0.326134, + 0.700149,0.139938,0.700149,1.67159,-0.569469,-0.32841, + 0.700149,0.139938,0.700149,1.67159,-0.569469,-0.32841, + 0.925394,0.167122,0.340171,1.718387,-0.569469,-0.406406, + 0.878536,-0.271725,0.392861,1.721597,-0.609197,-0.405226, + 0.686951,0.237061,-0.686951,1.660849,-0.510672,-0.660849, + 0.700149,0.139938,-0.700149,1.67159,-0.569469,-0.67159, + 0.925394,0.167122,-0.340171,1.718387,-0.569469,-0.593594, + 0.686951,0.237061,-0.686951,1.660849,-0.510672,-0.660849, + 0.925394,0.167122,-0.340171,1.718387,-0.569469,-0.593594, + 0.914159,0.225597,-0.336777,1.704717,-0.510672,-0.587736, + 0.700149,0.139938,-0.700149,1.67159,-0.569469,-0.67159, + 0.676292,-0.291988,-0.676293,1.673866,-0.608893,-0.673866, + 0.878536,-0.271725,-0.392861,1.721597,-0.609197,-0.594774, + 0.878536,-0.271725,-0.392861,1.721597,-0.609197,-0.594774, + 0.925394,0.167122,-0.340171,1.718387,-0.569469,-0.593594, + 0.700149,0.139938,-0.700149,1.67159,-0.569469,-0.67159, + 0.968451,-0.249205,0,1.737621,-0.609501,-0.5, + 0.981432,0.191813,0,1.733986,-0.569469,-0.5, + 0.925394,0.167122,-0.340171,1.718387,-0.569469,-0.593594, + 0.968451,-0.249205,0,1.737621,-0.609501,-0.5, + 0.925394,0.167122,-0.340171,1.718387,-0.569469,-0.593594, + 0.878536,-0.271725,-0.392861,1.721597,-0.609197,-0.594774, + 0.981432,0.191813,0,1.733986,-0.569469,-0.5, + 0.976322,0.216322,0,1.71934,-0.510672,-0.5, + 0.914159,0.225597,-0.336777,1.704717,-0.510672,-0.587736, + 0.914159,0.225597,-0.336777,1.704717,-0.510672,-0.587736, + 0.925394,0.167122,-0.340171,1.718387,-0.569469,-0.593594, + 0.981432,0.191813,0,1.733986,-0.569469,-0.5, + 0.199329,-0.959446,-0.199329,1.638667,-0.642463,-0.638667, + 0.188349,-0.976969,-0.100277,1.664625,-0.646948,-0.5825, + 0.529853,-0.826565,-0.189859,1.706,-0.633319,-0.5875, + 0.199329,-0.959446,-0.199329,1.638667,-0.642463,-0.638667, + 0.529853,-0.826565,-0.189859,1.706,-0.633319,-0.5875, + 0.467068,-0.750796,-0.467068,1.660875,-0.632104,-0.660875, + 0.244558,-0.969635,0,1.677562,-0.649161,-0.5, + 0.611773,-0.791034,0,1.7215,-0.634535,-0.5, + 0.529853,-0.826565,-0.189859,1.706,-0.633319,-0.5875, + 0.244558,-0.969635,0,1.677562,-0.649161,-0.5, + 0.529853,-0.826565,-0.189859,1.706,-0.633319,-0.5875, + 0.188349,-0.976969,-0.100277,1.664625,-0.646948,-0.5825, + 0.968451,-0.249205,0,1.737621,-0.609501,-0.5, + 0.878536,-0.271725,-0.392861,1.721597,-0.609197,-0.594774, + 0.529853,-0.826565,-0.189859,1.706,-0.633319,-0.5875, + 0.968451,-0.249205,0,1.737621,-0.609501,-0.5, + 0.529853,-0.826565,-0.189859,1.706,-0.633319,-0.5875, + 0.611773,-0.791034,0,1.7215,-0.634535,-0.5, + 0.878536,-0.271725,-0.392861,1.721597,-0.609197,-0.594774, + 0.676292,-0.291988,-0.676293,1.673866,-0.608893,-0.673866, + 0.467068,-0.750796,-0.467068,1.660875,-0.632104,-0.660875, + 0.467068,-0.750796,-0.467068,1.660875,-0.632104,-0.660875, + 0.529853,-0.826565,-0.189859,1.706,-0.633319,-0.5875, + 0.878536,-0.271725,-0.392861,1.721597,-0.609197,-0.594774, + 0.199329,-0.959446,0.199329,1.638667,-0.642463,-0.361333, + 0.467068,-0.750796,0.467068,1.660875,-0.632104,-0.339125, + 0.529853,-0.826565,0.189859,1.706,-0.633319,-0.4125, + 0.199329,-0.959446,0.199329,1.638667,-0.642463,-0.361333, + 0.529853,-0.826565,0.189859,1.706,-0.633319,-0.4125, + 0.188349,-0.976969,0.100277,1.664625,-0.646948,-0.4175, + 0.467068,-0.750796,0.467068,1.660875,-0.632104,-0.339125, + 0.676292,-0.291987,0.676293,1.673866,-0.608893,-0.326134, + 0.878536,-0.271725,0.392861,1.721597,-0.609197,-0.405226, + 0.878536,-0.271725,0.392861,1.721597,-0.609197,-0.405226, + 0.529853,-0.826565,0.189859,1.706,-0.633319,-0.4125, + 0.467068,-0.750796,0.467068,1.660875,-0.632104,-0.339125, + 0.968451,-0.249205,0,1.737621,-0.609501,-0.5, + 0.611773,-0.791034,0,1.7215,-0.634535,-0.5, + 0.529853,-0.826565,0.189859,1.706,-0.633319,-0.4125, + 0.968451,-0.249205,0,1.737621,-0.609501,-0.5, + 0.529853,-0.826565,0.189859,1.706,-0.633319,-0.4125, + 0.878536,-0.271725,0.392861,1.721597,-0.609197,-0.405226, + 0.244558,-0.969635,0,1.677562,-0.649161,-0.5, + 0.188349,-0.976969,0.100277,1.664625,-0.646948,-0.4175, + 0.529853,-0.826565,0.189859,1.706,-0.633319,-0.4125, + 0.244558,-0.969635,0,1.677562,-0.649161,-0.5, + 0.529853,-0.826565,0.189859,1.706,-0.633319,-0.4125, + 0.611773,-0.791034,0,1.7215,-0.634535,-0.5, + 0.686951,0.237061,-0.686951,1.660849,-0.510672,-0.660849, + 0.336776,0.225597,-0.91416,1.587736,-0.510672,-0.704717, + 0.340171,0.167122,-0.925394,1.593594,-0.569469,-0.718387, + 0.686951,0.237061,-0.686951,1.660849,-0.510672,-0.660849, + 0.340171,0.167122,-0.925394,1.593594,-0.569469,-0.718387, + 0.700149,0.139938,-0.700149,1.67159,-0.569469,-0.67159, + 0.336776,0.225597,-0.91416,1.587736,-0.510672,-0.704717, + 0,0.216323,-0.976322,1.5,-0.510672,-0.71934, + 0,0.191813,-0.981432,1.5,-0.569469,-0.733986, + 0,0.191813,-0.981432,1.5,-0.569469,-0.733986, + 0.340171,0.167122,-0.925394,1.593594,-0.569469,-0.718387, + 0.336776,0.225597,-0.91416,1.587736,-0.510672,-0.704717, + 0,-0.249205,-0.968451,1.5,-0.609501,-0.737621, + 0.392861,-0.271725,-0.878536,1.594774,-0.609197,-0.721597, + 0.340171,0.167122,-0.925394,1.593594,-0.569469,-0.718387, + 0,-0.249205,-0.968451,1.5,-0.609501,-0.737621, + 0.340171,0.167122,-0.925394,1.593594,-0.569469,-0.718387, + 0,0.191813,-0.981432,1.5,-0.569469,-0.733986, + 0.392861,-0.271725,-0.878536,1.594774,-0.609197,-0.721597, + 0.676292,-0.291988,-0.676293,1.673866,-0.608893,-0.673866, + 0.700149,0.139938,-0.700149,1.67159,-0.569469,-0.67159, + 0.700149,0.139938,-0.700149,1.67159,-0.569469,-0.67159, + 0.340171,0.167122,-0.925394,1.593594,-0.569469,-0.718387, + 0.392861,-0.271725,-0.878536,1.594774,-0.609197,-0.721597, + -0.686951,0.237061,-0.686951,1.339151,-0.510672,-0.660849, + -0.700149,0.139938,-0.700149,1.32841,-0.569469,-0.67159, + -0.340171,0.167122,-0.925394,1.406406,-0.569469,-0.718387, + -0.686951,0.237061,-0.686951,1.339151,-0.510672,-0.660849, + -0.340171,0.167122,-0.925394,1.406406,-0.569469,-0.718387, + -0.336776,0.225597,-0.91416,1.412264,-0.510672,-0.704717, + -0.700149,0.139938,-0.700149,1.32841,-0.569469,-0.67159, + -0.676292,-0.291988,-0.676293,1.326134,-0.608893,-0.673866, + -0.392861,-0.271725,-0.878536,1.405226,-0.609197,-0.721597, + -0.392861,-0.271725,-0.878536,1.405226,-0.609197,-0.721597, + -0.340171,0.167122,-0.925394,1.406406,-0.569469,-0.718387, + -0.700149,0.139938,-0.700149,1.32841,-0.569469,-0.67159, + 0,-0.249205,-0.968451,1.5,-0.609501,-0.737621, + 0,0.191813,-0.981432,1.5,-0.569469,-0.733986, + -0.340171,0.167122,-0.925394,1.406406,-0.569469,-0.718387, + 0,-0.249205,-0.968451,1.5,-0.609501,-0.737621, + -0.340171,0.167122,-0.925394,1.406406,-0.569469,-0.718387, + -0.392861,-0.271725,-0.878536,1.405226,-0.609197,-0.721597, + 0,0.191813,-0.981432,1.5,-0.569469,-0.733986, + 0,0.216323,-0.976322,1.5,-0.510672,-0.71934, + -0.336776,0.225597,-0.91416,1.412264,-0.510672,-0.704717, + -0.336776,0.225597,-0.91416,1.412264,-0.510672,-0.704717, + -0.340171,0.167122,-0.925394,1.406406,-0.569469,-0.718387, + 0,0.191813,-0.981432,1.5,-0.569469,-0.733986, + -0.199329,-0.959446,-0.199329,1.361333,-0.642463,-0.638667, + -0.100277,-0.976969,-0.18835,1.4175,-0.646948,-0.664625, + -0.189859,-0.826565,-0.529853,1.4125,-0.633319,-0.706, + -0.199329,-0.959446,-0.199329,1.361333,-0.642463,-0.638667, + -0.189859,-0.826565,-0.529853,1.4125,-0.633319,-0.706, + -0.467068,-0.750796,-0.467068,1.339125,-0.632104,-0.660875, + 0,-0.969635,-0.244558,1.5,-0.649161,-0.677562, + 0,-0.791034,-0.611773,1.5,-0.634535,-0.7215, + -0.189859,-0.826565,-0.529853,1.4125,-0.633319,-0.706, + 0,-0.969635,-0.244558,1.5,-0.649161,-0.677562, + -0.189859,-0.826565,-0.529853,1.4125,-0.633319,-0.706, + -0.100277,-0.976969,-0.18835,1.4175,-0.646948,-0.664625, + 0,-0.249205,-0.968451,1.5,-0.609501,-0.737621, + -0.392861,-0.271725,-0.878536,1.405226,-0.609197,-0.721597, + -0.189859,-0.826565,-0.529853,1.4125,-0.633319,-0.706, + 0,-0.249205,-0.968451,1.5,-0.609501,-0.737621, + -0.189859,-0.826565,-0.529853,1.4125,-0.633319,-0.706, + 0,-0.791034,-0.611773,1.5,-0.634535,-0.7215, + -0.392861,-0.271725,-0.878536,1.405226,-0.609197,-0.721597, + -0.676292,-0.291988,-0.676293,1.326134,-0.608893,-0.673866, + -0.467068,-0.750796,-0.467068,1.339125,-0.632104,-0.660875, + -0.467068,-0.750796,-0.467068,1.339125,-0.632104,-0.660875, + -0.189859,-0.826565,-0.529853,1.4125,-0.633319,-0.706, + -0.392861,-0.271725,-0.878536,1.405226,-0.609197,-0.721597, + 0.199329,-0.959446,-0.199329,1.638667,-0.642463,-0.638667, + 0.467068,-0.750796,-0.467068,1.660875,-0.632104,-0.660875, + 0.189859,-0.826565,-0.529853,1.5875,-0.633319,-0.706, + 0.199329,-0.959446,-0.199329,1.638667,-0.642463,-0.638667, + 0.189859,-0.826565,-0.529853,1.5875,-0.633319,-0.706, + 0.100277,-0.976969,-0.18835,1.5825,-0.646948,-0.664625, + 0.467068,-0.750796,-0.467068,1.660875,-0.632104,-0.660875, + 0.676292,-0.291988,-0.676293,1.673866,-0.608893,-0.673866, + 0.392861,-0.271725,-0.878536,1.594774,-0.609197,-0.721597, + 0.392861,-0.271725,-0.878536,1.594774,-0.609197,-0.721597, + 0.189859,-0.826565,-0.529853,1.5875,-0.633319,-0.706, + 0.467068,-0.750796,-0.467068,1.660875,-0.632104,-0.660875, + 0,-0.249205,-0.968451,1.5,-0.609501,-0.737621, + 0,-0.791034,-0.611773,1.5,-0.634535,-0.7215, + 0.189859,-0.826565,-0.529853,1.5875,-0.633319,-0.706, + 0,-0.249205,-0.968451,1.5,-0.609501,-0.737621, + 0.189859,-0.826565,-0.529853,1.5875,-0.633319,-0.706, + 0.392861,-0.271725,-0.878536,1.594774,-0.609197,-0.721597, + 0,-0.969635,-0.244558,1.5,-0.649161,-0.677562, + 0.100277,-0.976969,-0.18835,1.5825,-0.646948,-0.664625, + 0.189859,-0.826565,-0.529853,1.5875,-0.633319,-0.706, + 0,-0.969635,-0.244558,1.5,-0.649161,-0.677562, + 0.189859,-0.826565,-0.529853,1.5875,-0.633319,-0.706, + 0,-0.791034,-0.611773,1.5,-0.634535,-0.7215, + -0.686951,0.237061,-0.686951,1.339151,-0.510672,-0.660849, + -0.914159,0.225597,-0.336777,1.295283,-0.510672,-0.587736, + -0.925394,0.167122,-0.340171,1.281613,-0.569469,-0.593594, + -0.686951,0.237061,-0.686951,1.339151,-0.510672,-0.660849, + -0.925394,0.167122,-0.340171,1.281613,-0.569469,-0.593594, + -0.700149,0.139938,-0.700149,1.32841,-0.569469,-0.67159, + -0.914159,0.225597,-0.336777,1.295283,-0.510672,-0.587736, + -0.976322,0.216322,0,1.28066,-0.510672,-0.5, + -0.981432,0.191813,0,1.266014,-0.569469,-0.5, + -0.981432,0.191813,0,1.266014,-0.569469,-0.5, + -0.925394,0.167122,-0.340171,1.281613,-0.569469,-0.593594, + -0.914159,0.225597,-0.336777,1.295283,-0.510672,-0.587736, + -0.968451,-0.249205,0,1.262379,-0.609501,-0.5, + -0.878536,-0.271725,-0.392861,1.278403,-0.609197,-0.594774, + -0.925394,0.167122,-0.340171,1.281613,-0.569469,-0.593594, + -0.968451,-0.249205,0,1.262379,-0.609501,-0.5, + -0.925394,0.167122,-0.340171,1.281613,-0.569469,-0.593594, + -0.981432,0.191813,0,1.266014,-0.569469,-0.5, + -0.878536,-0.271725,-0.392861,1.278403,-0.609197,-0.594774, + -0.676292,-0.291988,-0.676293,1.326134,-0.608893,-0.673866, + -0.700149,0.139938,-0.700149,1.32841,-0.569469,-0.67159, + -0.700149,0.139938,-0.700149,1.32841,-0.569469,-0.67159, + -0.925394,0.167122,-0.340171,1.281613,-0.569469,-0.593594, + -0.878536,-0.271725,-0.392861,1.278403,-0.609197,-0.594774, + -0.68695,0.237061,0.686951,1.339151,-0.510672,-0.339151, + -0.700149,0.139938,0.700149,1.32841,-0.569469,-0.32841, + -0.925394,0.167122,0.340171,1.281613,-0.569469,-0.406406, + -0.68695,0.237061,0.686951,1.339151,-0.510672,-0.339151, + -0.925394,0.167122,0.340171,1.281613,-0.569469,-0.406406, + -0.914159,0.225597,0.336777,1.295283,-0.510672,-0.412264, + -0.700149,0.139938,0.700149,1.32841,-0.569469,-0.32841, + -0.676292,-0.291987,0.676293,1.326134,-0.608893,-0.326134, + -0.878536,-0.271725,0.392861,1.278403,-0.609197,-0.405226, + -0.878536,-0.271725,0.392861,1.278403,-0.609197,-0.405226, + -0.925394,0.167122,0.340171,1.281613,-0.569469,-0.406406, + -0.700149,0.139938,0.700149,1.32841,-0.569469,-0.32841, + -0.968451,-0.249205,0,1.262379,-0.609501,-0.5, + -0.981432,0.191813,0,1.266014,-0.569469,-0.5, + -0.925394,0.167122,0.340171,1.281613,-0.569469,-0.406406, + -0.968451,-0.249205,0,1.262379,-0.609501,-0.5, + -0.925394,0.167122,0.340171,1.281613,-0.569469,-0.406406, + -0.878536,-0.271725,0.392861,1.278403,-0.609197,-0.405226, + -0.981432,0.191813,0,1.266014,-0.569469,-0.5, + -0.976322,0.216322,0,1.28066,-0.510672,-0.5, + -0.914159,0.225597,0.336777,1.295283,-0.510672,-0.412264, + -0.914159,0.225597,0.336777,1.295283,-0.510672,-0.412264, + -0.925394,0.167122,0.340171,1.281613,-0.569469,-0.406406, + -0.981432,0.191813,0,1.266014,-0.569469,-0.5, + -0.199329,-0.959446,0.199329,1.361333,-0.642463,-0.361333, + -0.188349,-0.976969,0.100277,1.335375,-0.646948,-0.4175, + -0.529853,-0.826565,0.189859,1.294,-0.633319,-0.4125, + -0.199329,-0.959446,0.199329,1.361333,-0.642463,-0.361333, + -0.529853,-0.826565,0.189859,1.294,-0.633319,-0.4125, + -0.467068,-0.750796,0.467068,1.339125,-0.632104,-0.339125, + -0.244558,-0.969635,0,1.322438,-0.649161,-0.5, + -0.611773,-0.791034,0,1.2785,-0.634535,-0.5, + -0.529853,-0.826565,0.189859,1.294,-0.633319,-0.4125, + -0.244558,-0.969635,0,1.322438,-0.649161,-0.5, + -0.529853,-0.826565,0.189859,1.294,-0.633319,-0.4125, + -0.188349,-0.976969,0.100277,1.335375,-0.646948,-0.4175, + -0.968451,-0.249205,0,1.262379,-0.609501,-0.5, + -0.878536,-0.271725,0.392861,1.278403,-0.609197,-0.405226, + -0.529853,-0.826565,0.189859,1.294,-0.633319,-0.4125, + -0.968451,-0.249205,0,1.262379,-0.609501,-0.5, + -0.529853,-0.826565,0.189859,1.294,-0.633319,-0.4125, + -0.611773,-0.791034,0,1.2785,-0.634535,-0.5, + -0.878536,-0.271725,0.392861,1.278403,-0.609197,-0.405226, + -0.676292,-0.291987,0.676293,1.326134,-0.608893,-0.326134, + -0.467068,-0.750796,0.467068,1.339125,-0.632104,-0.339125, + -0.467068,-0.750796,0.467068,1.339125,-0.632104,-0.339125, + -0.529853,-0.826565,0.189859,1.294,-0.633319,-0.4125, + -0.878536,-0.271725,0.392861,1.278403,-0.609197,-0.405226, + -0.199329,-0.959446,-0.199329,1.361333,-0.642463,-0.638667, + -0.467068,-0.750796,-0.467068,1.339125,-0.632104,-0.660875, + -0.529853,-0.826565,-0.189859,1.294,-0.633319,-0.5875, + -0.199329,-0.959446,-0.199329,1.361333,-0.642463,-0.638667, + -0.529853,-0.826565,-0.189859,1.294,-0.633319,-0.5875, + -0.188349,-0.976969,-0.100277,1.335375,-0.646948,-0.5825, + -0.467068,-0.750796,-0.467068,1.339125,-0.632104,-0.660875, + -0.676292,-0.291988,-0.676293,1.326134,-0.608893,-0.673866, + -0.878536,-0.271725,-0.392861,1.278403,-0.609197,-0.594774, + -0.878536,-0.271725,-0.392861,1.278403,-0.609197,-0.594774, + -0.529853,-0.826565,-0.189859,1.294,-0.633319,-0.5875, + -0.467068,-0.750796,-0.467068,1.339125,-0.632104,-0.660875, + -0.968451,-0.249205,0,1.262379,-0.609501,-0.5, + -0.611773,-0.791034,0,1.2785,-0.634535,-0.5, + -0.529853,-0.826565,-0.189859,1.294,-0.633319,-0.5875, + -0.968451,-0.249205,0,1.262379,-0.609501,-0.5, + -0.529853,-0.826565,-0.189859,1.294,-0.633319,-0.5875, + -0.878536,-0.271725,-0.392861,1.278403,-0.609197,-0.594774, + -0.244558,-0.969635,0,1.322438,-0.649161,-0.5, + -0.188349,-0.976969,-0.100277,1.335375,-0.646948,-0.5825, + -0.529853,-0.826565,-0.189859,1.294,-0.633319,-0.5875, + -0.244558,-0.969635,0,1.322438,-0.649161,-0.5, + -0.529853,-0.826565,-0.189859,1.294,-0.633319,-0.5875, + -0.611773,-0.791034,0,1.2785,-0.634535,-0.5, + -0.68695,0.237061,0.686951,1.339151,-0.510672,-0.339151, + -0.336776,0.225598,0.914159,1.412264,-0.510672,-0.295283, + -0.340171,0.167122,0.925394,1.406406,-0.569469,-0.281613, + -0.68695,0.237061,0.686951,1.339151,-0.510672,-0.339151, + -0.340171,0.167122,0.925394,1.406406,-0.569469,-0.281613, + -0.700149,0.139938,0.700149,1.32841,-0.569469,-0.32841, + -0.336776,0.225598,0.914159,1.412264,-0.510672,-0.295283, + 0,0.216323,0.976322,1.5,-0.510672,-0.28066, + 0,0.191813,0.981432,1.5,-0.569469,-0.266014, + 0,0.191813,0.981432,1.5,-0.569469,-0.266014, + -0.340171,0.167122,0.925394,1.406406,-0.569469,-0.281613, + -0.336776,0.225598,0.914159,1.412264,-0.510672,-0.295283, + 0,-0.249205,0.968451,1.5,-0.609501,-0.262379, + -0.392861,-0.271724,0.878536,1.405226,-0.609197,-0.278403, + -0.340171,0.167122,0.925394,1.406406,-0.569469,-0.281613, + 0,-0.249205,0.968451,1.5,-0.609501,-0.262379, + -0.340171,0.167122,0.925394,1.406406,-0.569469,-0.281613, + 0,0.191813,0.981432,1.5,-0.569469,-0.266014, + -0.392861,-0.271724,0.878536,1.405226,-0.609197,-0.278403, + -0.676292,-0.291987,0.676293,1.326134,-0.608893,-0.326134, + -0.700149,0.139938,0.700149,1.32841,-0.569469,-0.32841, + -0.700149,0.139938,0.700149,1.32841,-0.569469,-0.32841, + -0.340171,0.167122,0.925394,1.406406,-0.569469,-0.281613, + -0.392861,-0.271724,0.878536,1.405226,-0.609197,-0.278403, + 0.68695,0.237061,0.686951,1.660849,-0.510672,-0.339151, + 0.700149,0.139938,0.700149,1.67159,-0.569469,-0.32841, + 0.340171,0.167122,0.925394,1.593594,-0.569469,-0.281613, + 0.68695,0.237061,0.686951,1.660849,-0.510672,-0.339151, + 0.340171,0.167122,0.925394,1.593594,-0.569469,-0.281613, + 0.336776,0.225598,0.914159,1.587736,-0.510672,-0.295283, + 0.700149,0.139938,0.700149,1.67159,-0.569469,-0.32841, + 0.676292,-0.291987,0.676293,1.673866,-0.608893,-0.326134, + 0.392861,-0.271724,0.878536,1.594774,-0.609197,-0.278403, + 0.392861,-0.271724,0.878536,1.594774,-0.609197,-0.278403, + 0.340171,0.167122,0.925394,1.593594,-0.569469,-0.281613, + 0.700149,0.139938,0.700149,1.67159,-0.569469,-0.32841, + 0,-0.249205,0.968451,1.5,-0.609501,-0.262379, + 0,0.191813,0.981432,1.5,-0.569469,-0.266014, + 0.340171,0.167122,0.925394,1.593594,-0.569469,-0.281613, + 0,-0.249205,0.968451,1.5,-0.609501,-0.262379, + 0.340171,0.167122,0.925394,1.593594,-0.569469,-0.281613, + 0.392861,-0.271724,0.878536,1.594774,-0.609197,-0.278403, + 0,0.191813,0.981432,1.5,-0.569469,-0.266014, + 0,0.216323,0.976322,1.5,-0.510672,-0.28066, + 0.336776,0.225598,0.914159,1.587736,-0.510672,-0.295283, + 0.336776,0.225598,0.914159,1.587736,-0.510672,-0.295283, + 0.340171,0.167122,0.925394,1.593594,-0.569469,-0.281613, + 0,0.191813,0.981432,1.5,-0.569469,-0.266014, + 0.199329,-0.959446,0.199329,1.638667,-0.642463,-0.361333, + 0.100277,-0.976969,0.18835,1.5825,-0.646948,-0.335375, + 0.189859,-0.826565,0.529853,1.5875,-0.633319,-0.294, + 0.199329,-0.959446,0.199329,1.638667,-0.642463,-0.361333, + 0.189859,-0.826565,0.529853,1.5875,-0.633319,-0.294, + 0.467068,-0.750796,0.467068,1.660875,-0.632104,-0.339125, + 0,-0.969635,0.244558,1.5,-0.649161,-0.322437, + 0,-0.791034,0.611773,1.5,-0.634535,-0.2785, + 0.189859,-0.826565,0.529853,1.5875,-0.633319,-0.294, + 0,-0.969635,0.244558,1.5,-0.649161,-0.322437, + 0.189859,-0.826565,0.529853,1.5875,-0.633319,-0.294, + 0.100277,-0.976969,0.18835,1.5825,-0.646948,-0.335375, + 0,-0.249205,0.968451,1.5,-0.609501,-0.262379, + 0.392861,-0.271724,0.878536,1.594774,-0.609197,-0.278403, + 0.189859,-0.826565,0.529853,1.5875,-0.633319,-0.294, + 0,-0.249205,0.968451,1.5,-0.609501,-0.262379, + 0.189859,-0.826565,0.529853,1.5875,-0.633319,-0.294, + 0,-0.791034,0.611773,1.5,-0.634535,-0.2785, + 0.392861,-0.271724,0.878536,1.594774,-0.609197,-0.278403, + 0.676292,-0.291987,0.676293,1.673866,-0.608893,-0.326134, + 0.467068,-0.750796,0.467068,1.660875,-0.632104,-0.339125, + 0.467068,-0.750796,0.467068,1.660875,-0.632104,-0.339125, + 0.189859,-0.826565,0.529853,1.5875,-0.633319,-0.294, + 0.392861,-0.271724,0.878536,1.594774,-0.609197,-0.278403, + -0.199329,-0.959446,0.199329,1.361333,-0.642463,-0.361333, + -0.467068,-0.750796,0.467068,1.339125,-0.632104,-0.339125, + -0.189859,-0.826565,0.529853,1.4125,-0.633319,-0.294, + -0.199329,-0.959446,0.199329,1.361333,-0.642463,-0.361333, + -0.189859,-0.826565,0.529853,1.4125,-0.633319,-0.294, + -0.100277,-0.976969,0.18835,1.4175,-0.646948,-0.335375, + -0.467068,-0.750796,0.467068,1.339125,-0.632104,-0.339125, + -0.676292,-0.291987,0.676293,1.326134,-0.608893,-0.326134, + -0.392861,-0.271724,0.878536,1.405226,-0.609197,-0.278403, + -0.392861,-0.271724,0.878536,1.405226,-0.609197,-0.278403, + -0.189859,-0.826565,0.529853,1.4125,-0.633319,-0.294, + -0.467068,-0.750796,0.467068,1.339125,-0.632104,-0.339125, + 0,-0.249205,0.968451,1.5,-0.609501,-0.262379, + 0,-0.791034,0.611773,1.5,-0.634535,-0.2785, + -0.189859,-0.826565,0.529853,1.4125,-0.633319,-0.294, + 0,-0.249205,0.968451,1.5,-0.609501,-0.262379, + -0.189859,-0.826565,0.529853,1.4125,-0.633319,-0.294, + -0.392861,-0.271724,0.878536,1.405226,-0.609197,-0.278403, + 0,-0.969635,0.244558,1.5,-0.649161,-0.322437, + -0.100277,-0.976969,0.18835,1.4175,-0.646948,-0.335375, + -0.189859,-0.826565,0.529853,1.4125,-0.633319,-0.294, + 0,-0.969635,0.244558,1.5,-0.649161,-0.322437, + -0.189859,-0.826565,0.529853,1.4125,-0.633319,-0.294, + 0,-0.791034,0.611773,1.5,-0.634535,-0.2785, + 0.199329,-0.959446,-0.199329,1.638667,-0.642463,-0.638667, + 0.100277,-0.976969,-0.18835,1.5825,-0.646948,-0.664625, + 0.079739,-0.993621,-0.079739,1.5905,-0.655194,-0.5905, + 0.199329,-0.959446,-0.199329,1.638667,-0.642463,-0.638667, + 0.079739,-0.993621,-0.079739,1.5905,-0.655194,-0.5905, + 0.188349,-0.976969,-0.100277,1.664625,-0.646948,-0.5825, + 0.100277,-0.976969,-0.18835,1.5825,-0.646948,-0.664625, + 0,-0.969635,-0.244558,1.5,-0.649161,-0.677562, + 0,-0.996384,-0.08496,1.5,-0.657972,-0.59775, + 0,-0.996384,-0.08496,1.5,-0.657972,-0.59775, + 0.079739,-0.993621,-0.079739,1.5905,-0.655194,-0.5905, + 0.100277,-0.976969,-0.18835,1.5825,-0.646948,-0.664625, + 0,-1,0,1.5,-0.660924,-0.5, + 0.08496,-0.996384,0,1.59775,-0.657972,-0.5, + 0.079739,-0.993621,-0.079739,1.5905,-0.655194,-0.5905, + 0,-1,0,1.5,-0.660924,-0.5, + 0.079739,-0.993621,-0.079739,1.5905,-0.655194,-0.5905, + 0,-0.996384,-0.08496,1.5,-0.657972,-0.59775, + 0.08496,-0.996384,0,1.59775,-0.657972,-0.5, + 0.244558,-0.969635,0,1.677562,-0.649161,-0.5, + 0.188349,-0.976969,-0.100277,1.664625,-0.646948,-0.5825, + 0.188349,-0.976969,-0.100277,1.664625,-0.646948,-0.5825, + 0.079739,-0.993621,-0.079739,1.5905,-0.655194,-0.5905, + 0.08496,-0.996384,0,1.59775,-0.657972,-0.5, + -0.199329,-0.959446,-0.199329,1.361333,-0.642463,-0.638667, + -0.188349,-0.976969,-0.100277,1.335375,-0.646948,-0.5825, + -0.079739,-0.993621,-0.079739,1.4095,-0.655194,-0.5905, + -0.199329,-0.959446,-0.199329,1.361333,-0.642463,-0.638667, + -0.079739,-0.993621,-0.079739,1.4095,-0.655194,-0.5905, + -0.100277,-0.976969,-0.18835,1.4175,-0.646948,-0.664625, + -0.188349,-0.976969,-0.100277,1.335375,-0.646948,-0.5825, + -0.244558,-0.969635,0,1.322438,-0.649161,-0.5, + -0.08496,-0.996384,0,1.40225,-0.657972,-0.5, + -0.08496,-0.996384,0,1.40225,-0.657972,-0.5, + -0.079739,-0.993621,-0.079739,1.4095,-0.655194,-0.5905, + -0.188349,-0.976969,-0.100277,1.335375,-0.646948,-0.5825, + 0,-1,0,1.5,-0.660924,-0.5, + 0,-0.996384,-0.08496,1.5,-0.657972,-0.59775, + -0.079739,-0.993621,-0.079739,1.4095,-0.655194,-0.5905, + 0,-1,0,1.5,-0.660924,-0.5, + -0.079739,-0.993621,-0.079739,1.4095,-0.655194,-0.5905, + -0.08496,-0.996384,0,1.40225,-0.657972,-0.5, + 0,-0.996384,-0.08496,1.5,-0.657972,-0.59775, + 0,-0.969635,-0.244558,1.5,-0.649161,-0.677562, + -0.100277,-0.976969,-0.18835,1.4175,-0.646948,-0.664625, + -0.100277,-0.976969,-0.18835,1.4175,-0.646948,-0.664625, + -0.079739,-0.993621,-0.079739,1.4095,-0.655194,-0.5905, + 0,-0.996384,-0.08496,1.5,-0.657972,-0.59775, + -0.199329,-0.959446,0.199329,1.361333,-0.642463,-0.361333, + -0.100277,-0.976969,0.18835,1.4175,-0.646948,-0.335375, + -0.079739,-0.993621,0.079739,1.4095,-0.655194,-0.4095, + -0.199329,-0.959446,0.199329,1.361333,-0.642463,-0.361333, + -0.079739,-0.993621,0.079739,1.4095,-0.655194,-0.4095, + -0.188349,-0.976969,0.100277,1.335375,-0.646948,-0.4175, + -0.100277,-0.976969,0.18835,1.4175,-0.646948,-0.335375, + 0,-0.969635,0.244558,1.5,-0.649161,-0.322437, + 0,-0.996384,0.08496,1.5,-0.657972,-0.40225, + 0,-0.996384,0.08496,1.5,-0.657972,-0.40225, + -0.079739,-0.993621,0.079739,1.4095,-0.655194,-0.4095, + -0.100277,-0.976969,0.18835,1.4175,-0.646948,-0.335375, + 0,-1,0,1.5,-0.660924,-0.5, + -0.08496,-0.996384,0,1.40225,-0.657972,-0.5, + -0.079739,-0.993621,0.079739,1.4095,-0.655194,-0.4095, + 0,-1,0,1.5,-0.660924,-0.5, + -0.079739,-0.993621,0.079739,1.4095,-0.655194,-0.4095, + 0,-0.996384,0.08496,1.5,-0.657972,-0.40225, + -0.08496,-0.996384,0,1.40225,-0.657972,-0.5, + -0.244558,-0.969635,0,1.322438,-0.649161,-0.5, + -0.188349,-0.976969,0.100277,1.335375,-0.646948,-0.4175, + -0.188349,-0.976969,0.100277,1.335375,-0.646948,-0.4175, + -0.079739,-0.993621,0.079739,1.4095,-0.655194,-0.4095, + -0.08496,-0.996384,0,1.40225,-0.657972,-0.5, + 0.199329,-0.959446,0.199329,1.638667,-0.642463,-0.361333, + 0.188349,-0.976969,0.100277,1.664625,-0.646948,-0.4175, + 0.079739,-0.993621,0.079739,1.5905,-0.655194,-0.4095, + 0.199329,-0.959446,0.199329,1.638667,-0.642463,-0.361333, + 0.079739,-0.993621,0.079739,1.5905,-0.655194,-0.4095, + 0.100277,-0.976969,0.18835,1.5825,-0.646948,-0.335375, + 0.188349,-0.976969,0.100277,1.664625,-0.646948,-0.4175, + 0.244558,-0.969635,0,1.677562,-0.649161,-0.5, + 0.08496,-0.996384,0,1.59775,-0.657972,-0.5, + 0.08496,-0.996384,0,1.59775,-0.657972,-0.5, + 0.079739,-0.993621,0.079739,1.5905,-0.655194,-0.4095, + 0.188349,-0.976969,0.100277,1.664625,-0.646948,-0.4175, + 0,-1,0,1.5,-0.660924,-0.5, + 0,-0.996384,0.08496,1.5,-0.657972,-0.40225, + 0.079739,-0.993621,0.079739,1.5905,-0.655194,-0.4095, + 0,-1,0,1.5,-0.660924,-0.5, + 0.079739,-0.993621,0.079739,1.5905,-0.655194,-0.4095, + 0.08496,-0.996384,0,1.59775,-0.657972,-0.5, + 0,-0.996384,0.08496,1.5,-0.657972,-0.40225, + 0,-0.969635,0.244558,1.5,-0.649161,-0.322437, + 0.100277,-0.976969,0.18835,1.5825,-0.646948,-0.335375, + 0.100277,-0.976969,0.18835,1.5825,-0.646948,-0.335375, + 0.079739,-0.993621,0.079739,1.5905,-0.655194,-0.4095, + 0,-0.996384,0.08496,1.5,-0.657972,-0.40225, +}; +static const struct gllist frame={GL_N3F_V3F,GL_TRIANGLES,1728,data,NULL}; +const struct gllist *s1_6=&frame; diff --git a/hacks/glx/s1_b.c b/hacks/glx/s1_b.c new file mode 100644 index 00000000..efdecf33 --- /dev/null +++ b/hacks/glx/s1_b.c @@ -0,0 +1,505 @@ +#include "gllist.h" +static const float data[]={ + -0.137893,0.043508,-0.125711, + -0.095845,-0.165656,0.072892, + -0.093165,0.152051,0.327744, + -0.003795,0.001470,-0.102225, + 0.152845,-0.430757,-0.031907, + -0.118828,0.399389,0.091047, + -0.169137,-0.181241,-0.288763, + 0.048660,0.018262,-0.035049, + 0.008859,0.208004,-0.059048, + -0.009212,-0.042229,-0.000692, + -0.040025,0.115695,0.178962, + -0.198525,0.018630,0.257202, + 0.205081,-0.244569,0.136314, + -0.214336,-0.149946,-0.006872, + 0.245675,-0.227316,-0.184201, + -0.001494,0.259139,-0.260652, + 0.070243,0.038750,0.069425, + -0.033229,-0.259151,0.298856, + 0.088773,-0.065324,0.260294, + 0.009195,0.078651,0.055543, + -0.090795,0.025672,0.056988, + -0.163707,-0.011627,-0.096395, + 0.068886,0.257031,-0.264175, + -0.018086,-0.285526,0.152989, + -0.017489,0.031671,0.000107, + -0.075583,-0.097617,0.030074, + 0.129221,-0.087628,0.171748, + -0.007530,-0.084194,0.186045, + 0.474638,0.004818,0.200460, + 0.016796,0.096614,-0.221351, + 0.187032,0.031017,0.039986, + -0.142119,-0.105297,-0.100849, + 0.142768,-0.313960,-0.349716, + -0.146805,0.140482,0.035653, + 0.039939,-0.051822,-0.017672, + 0.057111,-0.075686,-0.103478, + 0.049696,-0.135070,0.055097, + 0.030271,0.075412,-0.103571, + 0.100158,-0.022917,0.073895, + 0.085544,-0.273613,0.092456, + 0.077489,-0.309836,-0.003664, + -0.017590,-0.127869,0.153118, + -0.157014,-0.242184,0.070478, + -0.018167,-0.133639,-0.174937, + -0.106973,-0.189783,0.038622, + -0.000096,0.104429,-0.032589, + -0.032036,-0.021493,0.279829, + -0.093181,-0.058024,0.182239, + 0.012941,-0.010409,0.088080, + 0.256718,-0.118137,-0.078847, + -0.113382,0.135060,0.269946, + 0.175810,-0.026321,0.013860, + -0.110606,-0.023553,-0.255525, + 0.007163,0.068674,0.010214, + 0.031631,-0.170381,-0.174604, + 0.117242,0.014353,-0.021215, + 0.090315,0.161755,0.074427, + 0.285616,0.335824,-0.083891, + -0.145763,0.109292,0.121340, + -0.147459,-0.041936,0.010427, + -0.082626,0.151300,-0.030875, + 0.217154,-0.288504,-0.202483, + 0.026532,-0.106796,0.121041, + 0.046695,-0.033673,-0.043721, + 0.135596,0.217426,-0.219631, + 0.137627,0.026335,-0.082390, + -0.031665,-0.115897,0.077834, + -0.214922,-0.162169,0.073035, + -0.076108,0.200481,0.036119, + 0.012715,-0.161921,0.179804, + 0.140409,-0.165899,-0.005149, + -0.054606,0.011149,0.045768, + 0.116640,-0.180314,0.045320, + 0.342166,0.295895,-0.049250, + -0.133242,0.129064,0.136969, + 0.137520,-0.387145,0.132137, + 0.023302,0.194298,-0.066187, + 0.089302,0.128683,-0.072530, + -0.141374,0.035924,-0.079354, + -0.209233,0.018987,-0.004193, + 0.156295,-0.034087,0.344315, + -0.005946,0.039791,0.071862, + 0.076043,-0.094430,0.090122, + 0.127394,0.031466,-0.028015, + -0.061000,0.169741,-0.127635, + -0.015117,-0.160883,-0.095443, + -0.185998,-0.182942,0.056857, + 0.016499,-0.308118,-0.075513, + 0.024971,-0.301226,-0.027251, + -0.035944,0.061566,0.013883, + 0.007215,0.046198,-0.227891, + 0.189165,0.079471,-0.067849, + 0.026963,0.027982,-0.050419, + -0.050896,0.069604,-0.196938, + 0.064274,-0.205263,0.297868, + -0.047543,0.147822,0.166593, + 0.010318,-0.002148,0.029434, + 0.036107,-0.523568,-0.118442, + -0.199410,0.233526,-0.161289, + -0.047441,-0.013973,0.112998, + -0.043494,-0.181796,0.065864, + -0.074984,0.177758,-0.156470, + 0.225216,0.081058,-0.169876, + -0.041510,0.025763,-0.231350, + 0.259015,0.274641,0.018290, + 0.039196,0.010028,0.072771, + 0.031646,0.075290,0.039258, + 0.052930,-0.034809,0.165429, + -0.072511,0.095786,-0.222144, + 0.038706,0.032296,-0.002495, + 0.011675,-0.061944,0.082555, + -0.168400,0.074113,0.049321, + 0.001263,-0.207436,0.013949, + -0.027045,0.015697,-0.047831, + 0.121989,-0.043014,-0.004426, + 0.238374,-0.320060,-0.111754, + 0.095077,0.014640,0.070665, + -0.084367,0.016444,0.000788, + -0.117804,0.113550,0.087029, + -0.109080,-0.155795,0.040085, + -0.020370,0.118787,0.101787, + 0.140877,-0.144829,0.107720, + -0.247002,-0.454632,0.070535, + -0.016278,-0.111440,0.270110, + -0.017624,-0.146232,0.154626, + 0.214030,0.041025,-0.170250, + 0.010009,-0.159290,-0.076895, + 0.116168,0.156775,-0.077935, + 0.199355,0.081120,0.003352, + 0.054178,-0.036863,-0.004573, + -0.015149,0.057005,-0.008878, + 0.374758,-0.007823,-0.078051, + -0.034977,0.026837,0.035441, + 0.101867,0.121954,0.040450, + -0.136911,0.010061,0.082698, + 0.121665,-0.589852,0.106401, + -0.064574,0.098679,0.059336, + 0.103037,-0.075263,0.172586, + -0.217492,-0.170584,-0.025846, + 0.260366,0.002117,0.041535, + -0.024112,-0.023437,-0.088146, + -0.007767,0.061738,0.116208, + 0.253471,0.113278,0.231012, + -0.011399,0.116962,-0.037465, + 0.233898,0.226108,0.077176, + -0.004640,0.209191,-0.091738, + 0.093995,0.328937,0.245098, + 0.155739,-0.327971,-0.115265, + 0.125306,0.174931,0.130030, + 0.005005,-0.022310,0.120651, + 0.046982,-0.058839,-0.097958, + -0.059618,-0.068114,0.070137, + 0.053184,-0.081163,0.000020, + 0.188066,-0.082942,-0.013689, + -0.161390,-0.335891,-0.060737, + 0.131189,0.036733,-0.093511, + -0.002496,-0.059035,-0.084055, + 0.109820,-0.235531,0.130865, + 0.018909,0.062351,0.111532, + 0.123548,0.094008,0.056761, + 0.106710,-0.049834,-0.147748, + 0.102940,-0.113169,0.191710, + -0.028647,0.128038,-0.104189, + 0.107226,-0.220633,-0.147310, + -0.205747,0.063433,-0.026135, + -0.064614,0.096963,-0.080108, + -0.083255,0.113008,-0.089852, + 0.180961,-0.269100,0.115523, + 0.044722,-0.023285,0.024813, + 0.078986,0.037242,0.005124, + 0.115141,0.124478,-0.034603, + 0.022454,0.155937,-0.096183, + 0.175318,0.007233,-0.138507, + 0.019182,-0.037869,0.074242, + 0.058218,0.212269,-0.003886, + -0.188525,-0.075703,0.075643, + -0.029085,-0.076746,-0.273473, + -0.105590,-0.238524,-0.087465, + 0.086122,-0.340807,-0.192851, + -0.247936,-0.003160,0.082106, + 0.137988,-0.041876,-0.012086, + -0.140714,-0.138827,-0.064179, + -0.059380,0.015642,0.113841, + -0.031501,0.007130,-0.125767, + 0.021294,-0.021957,-0.069365, + -0.012419,0.019780,-0.077459, + 0.085524,0.087513,-0.107484, + -0.303263,0.263672,-0.220649, + -0.090267,-0.376337,-0.127634, + 0.087681,0.015985,-0.029860, + 0.119257,0.140347,0.194003, + 0.066270,0.127178,-0.003765, + 0.037563,-0.110829,0.000382, + 0.034295,-0.045737,0.045204, + 0.017365,-0.072708,0.056698, + 0.045238,0.187956,-0.055878, + -0.132755,0.017969,-0.041205, + 0.189702,-0.020780,-0.077422, + 0.210419,0.178041,-0.005855, + 0.104527,-0.304323,0.002581, + 0.043359,-0.060695,-0.011878, + -0.000267,0.020510,-0.046383, + 0.252891,0.074246,-0.047689, + -0.069874,0.118962,-0.052781, + 0.086188,0.068354,-0.213621, + 0.086637,-0.171519,0.006447, + 0.196785,-0.086044,-0.068059, + 0.100401,0.243886,-0.142258, + 0.173010,0.303375,-0.060085, + -0.041181,-0.097467,0.073776, + -0.013471,-0.133299,-0.143570, + -0.302092,-0.158342,0.230719, + 0.074434,-0.143530,0.294895, + -0.165626,0.200869,-0.130737, + 0.102444,0.277067,0.078210, + -0.183696,-0.010502,-0.150481, + -0.070029,-0.019635,-0.059141, + -0.005930,0.069199,-0.013126, + -0.119333,-0.007972,0.119489, + 0.033072,0.081756,-0.034481, + -0.108282,-0.065310,0.146009, + 0.080950,0.111320,0.004291, + 0.071208,-0.112941,0.028135, + -0.024632,0.190525,-0.285626, + -0.105040,0.044008,0.020236, + -0.017815,-0.076684,-0.065840, + 0.083563,0.100873,-0.141154, + -0.062066,-0.010894,0.066110, + -0.056763,0.024777,-0.176209, + -0.014442,0.052861,0.013010, + -0.157546,-0.118279,-0.237648, + -0.234497,-0.158049,0.102635, + 0.061685,-0.052695,-0.042243, + 0.093961,-0.025060,0.046602, + 0.004395,0.150912,0.191784, + 0.067299,-0.059575,0.161018, + -0.233155,-0.109721,0.194653, + 0.217444,0.221231,-0.201241, + -0.033689,-0.341937,-0.099231, + 0.042771,-0.028862,0.067736, + 0.110240,0.274029,-0.157689, + -0.055994,0.144729,0.090901, + 0.211192,0.058165,-0.149872, + 0.102735,-0.044061,-0.044795, + -0.042153,-0.010955,0.014341, + -0.011649,0.099072,-0.086419, + -0.018920,0.000640,-0.031729, + -0.216886,-0.057512,0.071195, + -0.188150,0.049292,0.258489, + -0.023494,0.021489,0.199785, + -0.045818,0.066753,-0.035593, + 0.010986,0.166767,0.275085, + -0.177039,0.010372,0.167936, + -0.423239,0.027466,-0.126114, + -0.102035,0.282640,0.022622, + -0.023997,0.176943,0.093272, + -0.090009,0.015338,0.250857, + 0.011095,0.006703,0.057076, + 0.133423,0.234639,-0.070260, + -0.295994,0.185615,0.117148, + 0.235480,0.066195,0.078641, + -0.026545,0.093931,0.008019, + 0.181656,-0.088719,0.045959, + -0.076308,-0.164584,0.018271, + 0.092026,0.201866,-0.106051, + 0.019876,0.050967,0.176081, + -0.018546,0.138749,-0.008255, + -0.026049,-0.068465,-0.055467, + -0.260245,0.221833,-0.048541, + -0.169783,0.354992,-0.017943, + -0.306063,0.074787,0.101971, + 0.215973,0.107558,-0.008808, + 0.390235,-0.275652,-0.117085, + 0.033898,0.046047,-0.108977, + -0.263507,-0.091765,-0.250234, + -0.044613,0.149563,0.027937, + -0.015397,-0.040254,0.065692, + -0.017531,-0.013504,0.004021, + 0.054665,-0.018996,-0.006954, + 0.033068,0.219349,-0.194079, + -0.057780,0.011881,0.084904, + 0.139243,-0.109890,0.039145, + 0.223272,0.208110,0.165882, + -0.008046,0.103847,0.278718, + -0.035499,0.112662,-0.088418, + -0.053118,0.053871,-0.054706, + 0.118632,0.086431,-0.022494, + 0.014943,0.039622,0.047307, + 0.006570,0.093461,0.058982, + 0.031448,0.325716,-0.047305, + -0.193710,0.087226,0.051790, + 0.116154,-0.080023,-0.106643, + 0.156514,-0.222710,0.275425, + -0.084294,-0.101851,0.425222, + 0.030344,-0.141370,-0.282460, + 0.003022,0.108996,-0.229152, + -0.133040,0.061025,-0.128942, + -0.077348,0.013363,-0.072511, + -0.050317,0.452190,0.094114, + 0.053309,-0.143722,0.249884, + -0.257016,0.100544,0.012236, + -0.022056,-0.212133,0.023533, + 0.153299,0.031763,0.034577, + 0.161729,0.084914,0.050770, + 0.320438,0.112175,0.135015, + -0.040717,0.073400,0.080543, + -0.226004,0.143154,0.170139, + 0.009756,0.068337,0.132111, + 0.380191,0.233715,0.026664, + -0.018016,0.265426,-0.110691, + 0.041281,0.056674,-0.119834, + 0.170794,-0.112611,0.094839, + 0.216318,0.002081,0.154653, + -0.036815,0.024332,0.172587, + -0.064554,0.160699,0.101229, + 0.114451,0.016039,0.293489, + 0.023010,-0.028932,0.014800, + -0.290527,0.172553,0.129526, + -0.048159,-0.181222,0.305871, + 0.065351,-0.399962,-0.030479, + 0.334123,-0.120149,0.241310, + -0.203728,-0.155627,0.140805, + 0.061022,-0.016097,0.131688, + 0.045050,-0.313782,-0.279077, + 0.034252,-0.135512,-0.087765, + 0.276236,0.036449,0.418332, + -0.122146,0.050998,0.131453, + -0.087629,0.330142,0.061353, + 0.228676,0.093309,-0.009307, + 0.435264,0.186185,-0.127484, + 0.156565,0.013842,-0.103874, + -0.274053,-0.084119,0.096687, + -0.027947,-0.051152,-0.078997, + 0.013399,0.194440,0.072030, + 0.000082,0.130666,0.052218, + 0.064984,-0.136859,0.092204, + 0.109060,0.424779,-0.111867, + 0.061748,0.160827,-0.068538, + 0.062960,0.059638,-0.181514, + 0.018961,0.072298,0.003517, + -0.099508,-0.225455,-0.021791, + 0.001955,-0.320555,0.159506, + -0.057735,-0.054327,-0.095525, + 0.319748,-0.146158,-0.198384, + -0.158741,-0.265443,0.036635, + -0.093089,-0.358379,-0.110549, + -0.049805,0.022246,-0.036724, + 0.223000,0.247522,-0.232652, + -0.249441,-0.248325,-0.071169, + 0.000369,0.094598,-0.162153, + -0.133873,-0.188473,0.272734, + 0.046594,0.069766,0.015561, + 0.111582,-0.239786,0.034658, + 0.093232,0.183507,-0.011298, + -0.226805,0.514871,-0.064144, + 0.085949,0.031412,0.042790, + -0.043755,-0.290797,-0.159142, + 0.056671,0.167837,0.016536, + -0.034538,0.072185,0.066973, + -0.021211,0.064120,-0.174756, + 0.090627,-0.055253,0.109457, + 0.019686,0.004469,-0.096316, + -0.038864,-0.135083,0.244529, + 0.034613,-0.069587,0.144533, + -0.100009,-0.057516,-0.079338, + -0.178026,0.085994,0.061804, + -0.189256,0.342739,0.043372, + -0.046206,0.168946,-0.133904, + 0.015314,-0.090127,-0.058530, + 0.169657,-0.097086,0.013746, + 0.185131,-0.089445,0.347806, + -0.264432,-0.170170,-0.335858, + -0.086511,0.248252,-0.169698, + 0.002287,-0.028338,-0.266432, + -0.085060,0.001974,-0.032789, + 0.192750,-0.007081,0.098197, + 0.012577,0.034983,-0.003058, + -0.039249,0.038498,0.067306, + 0.021988,0.379705,-0.054619, + -0.151707,0.051034,-0.016003, + -0.057048,0.075729,-0.213397, + -0.137847,0.130600,0.046198, + 0.024786,0.049556,-0.045772, + -0.082533,0.155397,-0.096145, + 0.049152,0.270979,-0.147022, + 0.061153,-0.104531,-0.103623, + -0.142997,-0.232885,0.040538, + 0.048806,-0.013095,-0.003505, + -0.095063,0.241414,-0.202255, + 0.108558,-0.147584,0.162682, + 0.217105,0.252340,-0.114830, + -0.188028,0.417252,-0.077456, + -0.112855,0.105192,0.073968, + -0.186972,0.164022,-0.073415, + -0.074349,-0.324874,-0.056645, + 0.327855,-0.271424,-0.141142, + 0.151049,0.155239,-0.083116, + 0.035395,-0.133176,-0.095112, + 0.127283,-0.011837,0.199750, + -0.120775,0.103698,0.063302, + 0.014222,0.198468,0.137537, + -0.269656,0.120644,-0.153958, + -0.136743,-0.119817,-0.073747, + -0.068156,-0.138484,0.033507, + -0.106835,0.114964,0.023924, + -0.222525,0.330321,-0.007431, + -0.011739,0.095156,0.139086, + 0.146766,0.037685,0.136122, + -0.086532,-0.081295,0.009434, + 0.189439,0.290592,-0.048317, + 0.139152,0.224931,0.355509, + 0.017162,-0.016825,0.094198, + -0.237595,0.205475,-0.041412, + 0.050511,0.094900,0.252891, + -0.012538,-0.014082,0.064629, + -0.059810,0.020665,-0.260979, + 0.073490,-0.242270,0.085847, + 0.049499,-0.045617,-0.015894, + -0.121040,0.004350,0.381603, + -0.062798,0.055006,0.077472, + -0.156846,-0.033342,0.035284, + 0.105383,0.002776,-0.046394, + 0.247612,0.310528,0.046188, + -0.144567,-0.197996,0.083309, + -0.317845,-0.014793,-0.041608, + -0.169858,0.102631,0.283962, + -0.168757,0.093105,0.050325, + -0.013639,0.285100,0.047089, + 0.216644,0.102018,0.031983, + 0.046988,0.081482,0.021865, + 0.124995,-0.193086,0.127870, + 0.009153,0.178713,-0.077949, + -0.235371,-0.046817,-0.125764, + -0.089381,0.289172,-0.129356, + 0.312993,0.120426,0.296957, + -0.106431,0.117096,0.156971, + 0.030001,0.244577,0.085119, + 0.002958,-0.035469,-0.084615, + -0.052248,-0.004298,-0.129170, + -0.158458,0.059061,-0.041780, + -0.007117,-0.174211,0.098819, + -0.158387,0.060840,-0.064818, + 0.117241,-0.050754,-0.027945, + -0.014301,0.146402,-0.118414, + 0.186611,-0.162182,-0.150909, + -0.106992,0.286109,-0.055512, + 0.109689,-0.346409,0.072611, + -0.009694,-0.038102,0.098565, + -0.034598,0.323300,0.020962, + -0.149219,0.040596,-0.114206, + 0.164744,0.048081,0.105464, + 0.036214,0.099523,0.038595, + 0.056537,0.036271,0.003042, + -0.157110,0.001614,-0.133994, + -0.104357,-0.032004,0.262334, + 0.041215,-0.010418,-0.037968, + 0.223491,-0.387946,0.117291, + -0.344434,0.110318,-0.031448, + 0.123562,-0.315729,0.164533, + 0.008207,0.042004,0.050014, + -0.191339,-0.069291,-0.220065, + 0.023845,0.009474,0.035598, + -0.173295,-0.036604,-0.193323, + -0.040347,-0.106063,-0.055559, + -0.071543,0.136487,0.105697, + -0.179027,-0.071852,0.117512, + 0.064769,-0.345895,0.012833, + 0.044800,-0.032357,-0.042161, + 0.243586,0.392499,-0.180641, + -0.148924,-0.181446,0.146644, + -0.042773,0.045843,-0.176893, + 0.025938,0.058109,0.242063, + -0.028489,-0.024828,0.161289, + 0.073899,-0.081205,-0.023751, + 0.026149,0.051399,-0.072348, + 0.024308,-0.041819,-0.030578, + -0.077778,0.010272,0.066967, + -0.139184,-0.018983,0.035150, + -0.061359,-0.152358,-0.072849, + 0.043101,0.028278,0.077387, + 0.065599,-0.049676,0.043708, + -0.255767,0.023510,-0.076982, + 0.020468,-0.040630,0.208424, + 0.044922,0.025184,0.004764, + 0.107432,-0.009356,0.239863, + -0.005475,0.158400,0.089743, + 0.018352,0.134559,0.221650, + 0.094423,0.129390,-0.031274, + 0.048541,0.100595,-0.155938, + -0.016298,-0.036518,-0.149178, + -0.329953,-0.327602,-0.150086, + 0.148403,-0.363334,0.028237, + -0.305790,-0.009844,-0.075571, + -0.045131,0.152595,0.228720, + 0.039725,-0.127469,0.066522, + -0.078576,-0.349749,-0.146881, + 0.013160,-0.040312,0.129980, + 0.221142,-0.106068,0.254967, + 0.180912,-0.207357,-0.196999, + 0.098219,0.085231,0.121963, +}; +static const struct gllist frame={GL_V3F,GL_POINTS,500,data,NULL}; +const struct gllist *s1_b=&frame; diff --git a/hacks/glx/sballs.c b/hacks/glx/sballs.c new file mode 100644 index 00000000..833b0001 --- /dev/null +++ b/hacks/glx/sballs.c @@ -0,0 +1,873 @@ +/* sballs --- balls spinning like crazy in GL */ + +#if 0 +static const char sccsid[] = "@(#)sballs.c 5.02 2001/03/10 xlockmore"; +#endif + +/* Copyright (c) E. Lassauge, 2001. */ + +/* + * Permission to use, copy, modify, and distribute this software and its + * documentation for any purpose and without fee is hereby granted, + * provided that the above copyright notice appear in all copies and that + * both that copyright notice and this permission notice appear in + * supporting documentation. + * + * This file is provided AS IS with no warranties of any kind. The author + * shall have no liability with respect to the infringement of copyrights, + * trade secrets or any patents by this file or any part thereof. In no + * event will the author be liable for any lost revenue or profits or + * other special, indirect and consequential damages. + * + * The original code for this mode was written by + * Mustata Bogdan (LoneRunner) + * and can be found at http://www.cfxweb.net/lonerunner/ + * + * Eric Lassauge (November-07-2000) + * http://lassauge.free.fr/linux.html + * + * REVISION HISTORY: + * + * E.Lassauge - 03-Oct-2001: + * - minor bugfixes - get ready for xscreensaver + * E.Lassauge - 09-Mar-2001: + * - get rid of my framerate options to use showfps + * E.Lassauge - 28-Nov-2000: + * - add handling of polyhedrons (like in ico) + * - modified release part to add freeing of GL objects + * E.Lassauge - 14-Nov-2000: + * - use new common xpm_to_ximage function + * + */ + +#ifdef STANDALONE /* xscreensaver mode */ +#define DEFAULTS "*delay: 30000 \n" \ + "*size: 0 \n" \ + "*cycles: 4 \n" \ + "*showFPS: False \n" \ + "*wireframe: False \n" \ + +# define refresh_sballs 0 +#define MODE_sballs +#include "xlockmore.h" /* from the xscreensaver distribution */ +#include "gltrackball.h" +#else /* !STANDALONE */ +#include "xlock.h" /* from the xlockmore distribution */ +#include "visgl.h" +#endif /* !STANDALONE */ + +#ifdef MODE_sballs + +#define MINSIZE 32 /* minimal viewport size */ +#define FRAME 50 /* frame count interval */ +#define MAX_OBJ 8 /* number of 3D objects */ + +#if defined( USE_XPM ) || defined( USE_XPMINC ) || defined( STANDALONE ) +/* USE_XPM & USE_XPMINC in xlock mode ; HAVE_XPM in xscreensaver mode */ +# include "xpm-ximage.h" +# define I_HAVE_XPM + +# ifdef STANDALONE + +# ifdef __GNUC__ + __extension__ /* don't warn about "string length is greater than the length + ISO C89 compilers are required to support" when including + the following XPM file... */ +# endif +# include "../images/sball.xpm" +# ifdef __GNUC__ + __extension__ +# endif +# include "../images/sball-bg.xpm" +# else /* !STANDALONE */ +# include "pixmaps/sball.xpm" +# include "pixmaps/sball-bg.xpm" +# endif /* !STANDALONE */ +#endif /* HAVE_XPM */ + +/* Manage option vars */ +#define DEF_TEXTURE "True" +#define DEF_OBJECT "0" +static Bool do_texture; +static int object; +static int spheres; + +static XrmOptionDescRec opts[] = { + {"-texture", ".sballs.texture", XrmoptionNoArg, "on"}, + {"+texture", ".sballs.texture", XrmoptionNoArg, "off"}, + {"-object", ".sballs.object", XrmoptionSepArg, 0}, + +}; + +static argtype vars[] = { + {&do_texture, "texture", "Texture", DEF_TEXTURE, t_Bool}, + {&object, "object", "Object", DEF_OBJECT, t_Int}, + +}; + +static OptionStruct desc[] = { + /*{"-count spheres", "set number of spheres"},*/ + /*{"-cycles speed", "set ball speed value"},*/ + {"-/+texture", "turn on/off texturing"}, + {"-object num", "number of the 3D object (0 means random)"}, +}; + +ENTRYPOINT ModeSpecOpt sballs_opts = + { sizeof opts / sizeof opts[0], opts, sizeof vars / sizeof vars[0], vars, desc }; + +#ifdef USE_MODULES +ModStruct sballs_description = + { "sballs", "init_sballs", "draw_sballs", "release_sballs", + "draw_sballs", "change_sballs", (char *) NULL, &sballs_opts, + /* + delay,count,cycles,size,ncolors,sat + */ + 10000, 0, 10, 400, 64, 1.0, "", + "balls spinning like crazy in GL", 0, NULL +}; +#endif /* USE_MODULES */ + +/* misc types and defines */ +#define vinit(a,i,j,k) {\ + (a)[0]=i;\ + (a)[1]=j;\ + (a)[2]=k;\ +} +typedef float vec_t; +typedef vec_t vec3_t[3]; + +#define MAX_BALLS 20 + +/* the mode struct, contains all per screen variables */ +typedef struct { + GLint WIDTH, HEIGHT; /* display dimensions */ + GLXContext *glx_context; + + + XImage *btexture; /* back texture image bits */ + XImage *ftexture; /* face texture image bits */ + GLuint backid; /* back texture id: GL world */ + GLuint faceid; /* face texture id: GL world */ + + vec3_t eye; + vec3_t rotm; + int speed; + float radius[MAX_BALLS]; + + trackball_state *trackball; + Bool button_down_p; + +} sballsstruct; + +/* array of sballsstruct indexed by screen number */ +static sballsstruct *sballs = (sballsstruct *) NULL; + +/* lights */ +static const float LightAmbient[]= { 1.0f, 1.0f, 1.0f, 1.0f }; +static const float LightDiffuse[]= { 1.0f, 1.0f, 1.0f, 1.0f }; +static const float LightPosition[]= { 0.0f, 0.0f, 4.0f, 1.0f }; + +/* structure of the polyhedras */ +typedef struct { + const char *longname; /* long name of object */ + const char *shortname; /* short name of object */ + int numverts; /* number of vertices */ + float radius; /* radius */ + vec3_t v[MAX_BALLS];/* the vertices */ +} Polyinfo; + +static const Polyinfo polygons[] = +{ + +/* 0: objtetra - structure values for tetrahedron */ + { + "tetrahedron", "tetra", /* long and short names */ + 4, /* number of vertices */ + 0.8, + { /* vertices (x,y,z) */ + /* all points must be within radius 2 of the origin */ +#define T 1.0 + {T, T, T}, + {T, -T, -T}, + {-T, T, -T}, + {-T, -T, T}, +#undef T + } + }, + +/* 1: objcube - structure values for cube */ + + { + "hexahedron", "cube", /* long and short names */ + 8, /* number of vertices, edges, and faces */ + 0.6, + { /* vertices (x,y,z) */ + /* all points must be within radius 2 of the origin */ +#define T 1.0 + {T, T, T}, + {T, T, -T}, + {T, -T, -T}, + {T, -T, T}, + {-T, T, T}, + {-T, T, -T}, + {-T, -T, -T}, + {-T, -T, T}, +#undef T + } + }, + +/* 2: objocta - structure values for octahedron */ + + { + "octahedron", "octa", /* long and short names */ + 6, /* number of vertices */ + 0.6, + { /* vertices (x,y,z) */ + /* all points must be within radius 2 of the origin */ +#define T 1.5 + {T, 0, 0}, + {-T, 0, 0}, + {0, T, 0}, + {0, -T, 0}, + {0, 0, T}, + {0, 0, -T}, +#undef T + } + }, +/* 3: objdodec - structure values for dodecahedron */ + + { + "dodecahedron", "dodeca", /* long and short names */ + 20, /* number of vertices */ + 0.35, + { /* vertices (x,y,z) */ + /* all points must be within radius 2 of the origin */ + {0.000000, 0.500000, 1.000000}, + {0.000000, -0.500000, 1.000000}, + {0.000000, -0.500000, -1.000000}, + {0.000000, 0.500000, -1.000000}, + {1.000000, 0.000000, 0.500000}, + {-1.000000, 0.000000, 0.500000}, + {-1.000000, 0.000000, -0.500000}, + {1.000000, 0.000000, -0.500000}, + {0.500000, 1.000000, 0.000000}, + {-0.500000, 1.000000, 0.000000}, + {-0.500000, -1.000000, 0.000000}, + {0.500000, -1.000000, 0.000000}, + {0.750000, 0.750000, 0.750000}, + {-0.750000, 0.750000, 0.750000}, + {-0.750000, -0.750000, 0.750000}, + {0.750000, -0.750000, 0.750000}, + {0.750000, -0.750000, -0.750000}, + {0.750000, 0.750000, -0.750000}, + {-0.750000, 0.750000, -0.750000}, + {-0.750000, -0.750000, -0.750000}, + } + }, + +/* 4: objicosa - structure values for icosahedron */ + + { + "icosahedron", "icosa", /* long and short names */ + 12, /* number of vertices */ + 0.4, + { /* vertices (x,y,z) */ + /* all points must be within radius 2 of the origin */ + {0.00000000, 0.00000000, -0.95105650}, + {0.00000000, 0.85065080, -0.42532537}, + {0.80901698, 0.26286556, -0.42532537}, + {0.50000000, -0.68819095, -0.42532537}, + {-0.50000000, -0.68819095, -0.42532537}, + {-0.80901698, 0.26286556, -0.42532537}, + {0.50000000, 0.68819095, 0.42532537}, + {0.80901698, -0.26286556, 0.42532537}, + {0.00000000, -0.85065080, 0.42532537}, + {-0.80901698, -0.26286556, 0.42532537}, + {-0.50000000, 0.68819095, 0.42532537}, + {0.00000000, 0.00000000, 0.95105650} + } + }, + +/* 5: objplane - structure values for plane */ + + { + "plane", "plane", /* long and short names */ + 4, /* number of vertices */ + 0.7, + { /* vertices (x,y,z) */ + /* all points must be within radius 2 of the origin */ +#define T 1.1 + {T, 0, 0}, + {-T, 0, 0}, + {0, T, 0}, + {0, -T, 0}, +#undef T + } + }, + +/* 6: objpyr - structure values for pyramid */ + + { + "pyramid", "pyramid", /* long and short names */ + 5, /* number of vertices */ + 0.5, + { /* vertices (x,y,z) */ + /* all points must be within radius 1 of the origin */ +#define T 1.0 + {T, 0, 0}, + {-T, 0, 0}, + {0, T, 0}, + {0, -T, 0}, + {0, 0, T}, +#undef T + } + }, + +/* 7: objstar - structure values for octahedron star (stellated octahedron?) */ + { + "star", "star", /* long and short names */ + 8, /* number of vertices */ + 0.7, + { /* vertices (x,y,z) */ + /* all points must be within radius 1 of the origin */ +#define T 0.9 + {T, T, T}, + {T, -T, -T}, + {-T, T, -T}, + {-T, -T, T}, + {-T, -T, -T}, + {-T, T, T}, + {T, -T, T}, + {T, T, -T}, +#undef T + } + }, + +}; + + + + +/* + *----------------------------------------------------------------------------- + *----------------------------------------------------------------------------- + * Misc funcs. + *----------------------------------------------------------------------------- + *----------------------------------------------------------------------------- + */ + + +/* initialise textures */ +static void inittextures(ModeInfo * mi) +{ + sballsstruct *sb = &sballs[MI_SCREEN(mi)]; + +#if defined( I_HAVE_XPM ) + if (do_texture) { + + glGenTextures(1, &sb->backid); +#ifdef HAVE_GLBINDTEXTURE + glBindTexture(GL_TEXTURE_2D, sb->backid); +#endif /* HAVE_GLBINDTEXTURE */ + + sb->btexture = xpm_to_ximage(MI_DISPLAY(mi), + MI_VISUAL(mi), + MI_COLORMAP(mi), + sball_bg); + if (!(sb->btexture)) { + (void) fprintf(stderr, "Error reading the background texture.\n"); + glDeleteTextures(1, &sb->backid); + do_texture = False; + sb->faceid = 0; /* default textures */ + sb->backid = 0; + return; + } + + glPixelStorei(GL_UNPACK_ALIGNMENT, 1); + clear_gl_error(); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, + sb->btexture->width, sb->btexture->height, 0, + GL_RGBA, + /* GL_UNSIGNED_BYTE, */ + GL_UNSIGNED_INT_8_8_8_8_REV, + sb->btexture->data); + check_gl_error("texture"); + + glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); + glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); + + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + + glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); + + glGenTextures(1, &sb->faceid); +#ifdef HAVE_GLBINDTEXTURE + glBindTexture(GL_TEXTURE_2D, sb->faceid); +#endif /* HAVE_GLBINDTEXTURE */ + + sb->ftexture = xpm_to_ximage(MI_DISPLAY(mi), + MI_VISUAL(mi), + MI_COLORMAP(mi), + sball); + if (!(sb->ftexture)) { + (void) fprintf(stderr, "Error reading the face texture.\n"); + glDeleteTextures(1, &sb->faceid); + sb->faceid = 0; + return; + } + + glPixelStorei(GL_UNPACK_ALIGNMENT, 1); + clear_gl_error(); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, + sb->ftexture->width, sb->ftexture->height, 0, + GL_RGBA, + /* GL_UNSIGNED_BYTE, */ + GL_UNSIGNED_INT_8_8_8_8_REV, + sb->ftexture->data); + check_gl_error("texture"); + + glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); + glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); + + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + + glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); + } + else + { + sb->faceid = 0; /* default textures */ + sb->backid = 0; + } +#else /* !I_HAVE_XPM */ + do_texture = False; + sb->faceid = 0; /* default textures */ + sb->backid = 0; +#endif /* !I_HAVE_XPM */ +} + +static void drawSphere(ModeInfo * mi,int sphere_num) +{ + sballsstruct *sb = &sballs[MI_SCREEN(mi)]; + float x = polygons[object].v[sphere_num][0]; + float y = polygons[object].v[sphere_num][1]; + float z = polygons[object].v[sphere_num][2]; + int numMajor = 15; + int numMinor = 30; + float radius = sb->radius[sphere_num]; + double majorStep = (M_PI / numMajor); + double minorStep = (2.0 * M_PI / numMinor); + int i, j; + + glPushMatrix(); + glTranslatef(x, y, z); + + glColor4f(1, 1, 1, 1); + for (i = 0; i < numMajor; ++i) + { + double a = i * majorStep; + double b = a + majorStep; + double r0 = radius * sin(a); + double r1 = radius * sin(b); + GLfloat z0 = radius * cos(a); + GLfloat z1 = radius * cos(b); + + glBegin(MI_IS_WIREFRAME(mi) ? GL_LINE_STRIP: GL_TRIANGLE_STRIP); + for (j = 0; j <= numMinor; ++j) + { + double c = j * minorStep; + GLfloat x = cos(c); + GLfloat y = sin(c); + + glNormal3f((x * r0) / radius, (y * r0) / radius, z0 / radius); + glTexCoord2f(j / (GLfloat) numMinor, i / (GLfloat) numMajor); + glVertex3f(x * r0, y * r0, z0); + + glNormal3f((x * r1) / radius, (y * r1) / radius, z1 / radius); + glTexCoord2f(j / (GLfloat) numMinor, (i + 1) / (GLfloat) numMajor); + glVertex3f(x * r1, y * r1, z1); + + mi->polygon_count++; + } + glEnd(); + } + + glPopMatrix(); +} + +/* + *----------------------------------------------------------------------------- + *----------------------------------------------------------------------------- + * GL funcs. + *----------------------------------------------------------------------------- + *----------------------------------------------------------------------------- + */ + +#ifndef STANDALONE +static void Reshape(ModeInfo * mi) +#else +ENTRYPOINT void reshape_sballs(ModeInfo * mi, int width, int height) +#endif +{ + + sballsstruct *sb = &sballs[MI_SCREEN(mi)]; + int size = MI_SIZE(mi); + + /* Viewport is specified size if size >= MINSIZE && size < screensize */ + if (size <= 1) { + sb->WIDTH = MI_WIDTH(mi); + sb->HEIGHT = MI_HEIGHT(mi); + } else if (size < MINSIZE) { + sb->WIDTH = MINSIZE; + sb->HEIGHT = MINSIZE; + } else { + sb->WIDTH = (size > MI_WIDTH(mi)) ? MI_WIDTH(mi) : size; + sb->HEIGHT = (size > MI_HEIGHT(mi)) ? MI_HEIGHT(mi) : size; + } + glViewport((MI_WIDTH(mi) - sb->WIDTH) / 2, (MI_HEIGHT(mi) - sb->HEIGHT) / 2, sb->WIDTH, sb->HEIGHT); + glMatrixMode(GL_PROJECTION); + glLoadIdentity(); + gluPerspective(55.0, (float)sb->WIDTH / (float) sb->HEIGHT, 1.0, 300.0); + + glMatrixMode(GL_MODELVIEW); + +} + +static void Draw(ModeInfo * mi) +{ + sballsstruct *sb = &sballs[MI_SCREEN(mi)]; + int sphere; + + mi->polygon_count = 0; + + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + + glPushMatrix(); + glEnable(GL_DEPTH_TEST); + + /* move eyes */ + glTranslatef (-sb->eye[0], -sb->eye[1], -sb->eye[2]); + + /* draw background */ + if (do_texture) + { + glEnable(GL_LIGHTING); + glEnable(GL_TEXTURE_2D); + glColor3f(1, 1, 1); +#ifdef HAVE_GLBINDTEXTURE + glBindTexture(GL_TEXTURE_2D, sb->backid); +#endif /* HAVE_GLBINDTEXTURE */ + } + else + { + glColor3f(0, 0, 0); + } + glBegin(GL_QUAD_STRIP); +#ifndef USE_IPHONE + /* Letterbox the background image */ + glNormal3f(0, 0, 1); glTexCoord2f(0,0); glVertex3f(8, 4.1, -4); + glNormal3f(0, 0, 1); glTexCoord2f(0,1); glVertex3f(8, -4.1, -4); + glNormal3f(0, 0, 1); glTexCoord2f(1,0); glVertex3f(-8, 4.1, -4); + glNormal3f(0, 0, 1); glTexCoord2f(1,1); glVertex3f(-8, -4.1, -4); +#else + /* Fill the iPhone screen. Letterboxing looks dumb there. */ + glNormal3f(0, 0, 1); glTexCoord2f(0,0); glVertex3f(4, 5.2, -4); + glNormal3f(0, 0, 1); glTexCoord2f(0,1); glVertex3f(4, -5.2, -4); + glNormal3f(0, 0, 1); glTexCoord2f(1,0); glVertex3f(-4, 5.2, -4); + glNormal3f(0, 0, 1); glTexCoord2f(1,1); glVertex3f(-4, -5.2, -4); +#endif + glEnd(); + mi->polygon_count++; + + /* Do it twice because we don't track the device's orientation. */ + glRotatef( current_device_rotation(), 0, 0, 1); + gltrackball_rotate (sb->trackball); + glRotatef(-current_device_rotation(), 0, 0, 1); + + /* rotate the balls */ + glRotatef(sb->rotm[0], 1.0f, 0.0f, 0.0f); + glRotatef(sb->rotm[1], 0.0f, 1.0f, 0.0f); + glRotatef(sb->rotm[2], 0.0f, 0.0f, 1.0f); + + if (! sb->button_down_p) { + sb->rotm[0] += sb->speed; + sb->rotm[1] += -(sb->speed); + sb->rotm[2] += 0; + } + + /* draw the balls */ + if (do_texture) +#ifdef HAVE_GLBINDTEXTURE + glBindTexture(GL_TEXTURE_2D, sb->faceid); +#endif /* HAVE_GLBINDTEXTURE */ + else + glEnable(GL_LIGHTING); + for (sphere=0;spherebtexture = (XImage*) NULL; + sb->ftexture = (XImage*) NULL; + } + + vinit(sb->eye ,0.0f, 0.0f, 6.0f); + vinit(sb->rotm ,0.0f, 0.0f, 0.0f); + sb->speed = MI_CYCLES(mi); + + /* initialise object number */ + if ((object == 0) || (object > MAX_OBJ)) + object = NRAND(MAX_OBJ-1)+1; + object--; + + /* initialise sphere number */ + spheres = MI_COUNT(mi); + if (MI_COUNT(mi) > polygons[object].numverts) + spheres = polygons[object].numverts; + if (MI_COUNT(mi) < 1) + spheres = polygons[object].numverts; + /* initialise sphere radius */ + for(i=0; i < spheres;i++) + { +#if RANDOM_RADIUS + sb->radius[i] = ((float) LRAND() / (float) MAXRAND); + if (sb->radius[i] < 0.3) + sb->radius[i] = 0.3; + if (sb->radius[i] > 0.7) + sb->radius[i] = 0.7; +#else + sb->radius[i] = polygons[object].radius; +#endif + } + + if (MI_IS_DEBUG(mi)) { + (void) fprintf(stderr, + "%s:\n\tobject=%s\n\tspheres=%d\n\tspeed=%d\n\ttexture=%s\n", + MI_NAME(mi), + polygons[object].shortname, + spheres, + (int) MI_CYCLES(mi), + do_texture ? "on" : "off" + ); + } + + glLightfv(GL_LIGHT1, GL_AMBIENT, LightAmbient); + glLightfv(GL_LIGHT1, GL_DIFFUSE, LightDiffuse); + glLightfv(GL_LIGHT1, GL_POSITION,LightPosition); + glEnable(GL_LIGHT1); +} + +/* + *----------------------------------------------------------------------------- + *----------------------------------------------------------------------------- + * Xlock hooks. + *----------------------------------------------------------------------------- + *----------------------------------------------------------------------------- + */ + +/* + *----------------------------------------------------------------------------- + * Initialize sballs. Called each time the window changes. + *----------------------------------------------------------------------------- + */ + +ENTRYPOINT void init_sballs(ModeInfo * mi) +{ + sballsstruct *sb; + + if (sballs == NULL) { + if ((sballs = (sballsstruct *) calloc(MI_NUM_SCREENS(mi), + sizeof(sballsstruct))) == NULL) + return; + } + sb = &sballs[MI_SCREEN(mi)]; + + sb->trackball = gltrackball_init (); + + if ((sb->glx_context = init_GL(mi)) != NULL) { + +#ifndef STANDALONE + Reshape(mi); /* xlock mode */ +#else + reshape_sballs(mi,MI_WIDTH(mi),MI_HEIGHT(mi)); /* xscreensaver mode */ +#endif + glDrawBuffer(GL_BACK); + Init(mi); + + } else { + MI_CLEARWINDOW(mi); + } +} + +/* + *----------------------------------------------------------------------------- + * Called by the mainline code periodically to update the display. + *----------------------------------------------------------------------------- + */ +ENTRYPOINT void draw_sballs(ModeInfo * mi) +{ + Display *display = MI_DISPLAY(mi); + Window window = MI_WINDOW(mi); + sballsstruct *sb; + + if (sballs == NULL) + return; + sb = &sballs[MI_SCREEN(mi)]; + + MI_IS_DRAWN(mi) = True; + if (!sb->glx_context) + return; + + glXMakeCurrent(display, window, *(sb->glx_context)); + Draw(mi); +#ifndef STANDALONE + Reshape(mi); /* xlock mode */ +#else + reshape_sballs(mi,MI_WIDTH(mi),MI_HEIGHT(mi)); /* xscreensaver mode */ +#endif + + glFinish(); + glXSwapBuffers(display, window); +} + + +/* + *----------------------------------------------------------------------------- + * The display is being taken away from us. Free up malloc'ed + * memory and X resources that we've alloc'ed. Only called + * once, we must zap everything for every screen. + *----------------------------------------------------------------------------- + */ + +ENTRYPOINT void release_sballs(ModeInfo * mi) +{ + int screen; + + if (sballs != NULL) { + for (screen = 0; screen < MI_NUM_SCREENS(mi); screen++) { + sballsstruct *sb = &sballs[screen]; + if (sb->btexture) + { + glDeleteTextures(1,&sb->backid); + XDestroyImage(sb->btexture); + } + if (sb->ftexture) + { + glDeleteTextures(1,&sb->faceid); + XDestroyImage(sb->ftexture); + } + } + (void) free((void *) sballs); + sballs = (sballsstruct *) NULL; + } + FreeAllGL(mi); +} + +ENTRYPOINT Bool +sballs_handle_event (ModeInfo *mi, XEvent *event) +{ + sballsstruct *sb = &sballs[MI_SCREEN(mi)]; + + if (event->xany.type == ButtonPress && + event->xbutton.button == Button1) + { + sb->button_down_p = True; + gltrackball_start (sb->trackball, + event->xbutton.x, event->xbutton.y, + MI_WIDTH (mi), MI_HEIGHT (mi)); + return True; + } + else if (event->xany.type == ButtonRelease && + event->xbutton.button == Button1) + { + sb->button_down_p = False; + return True; + } + else if (event->xany.type == ButtonPress && + (event->xbutton.button == Button4 || + event->xbutton.button == Button5 || + event->xbutton.button == Button6 || + event->xbutton.button == Button7)) + { + gltrackball_mousewheel (sb->trackball, event->xbutton.button, 5, + !!event->xbutton.state); + return True; + } + else if (event->xany.type == MotionNotify && + sb->button_down_p) + { + gltrackball_track (sb->trackball, + event->xmotion.x, event->xmotion.y, + MI_WIDTH (mi), MI_HEIGHT (mi)); + return True; + } + + return False; +} + + +#ifndef STANDALONE +ENTRYPOINT void change_sballs(ModeInfo * mi) +{ + sballsstruct *sb; + + if (sballs == NULL) + return; + sb = &sballs[MI_SCREEN(mi)]; + + if (!sb->glx_context) + return; + + /* initialise object number */ + if ((object == 0) || (object > MAX_OBJ)) + object = NRAND(MAX_OBJ-1)+1; + object--; + + /* correct sphere number */ + spheres = MI_COUNT(mi); + if (MI_COUNT(mi) > polygons[object].numverts) + spheres = polygons[object].numverts; + if (MI_COUNT(mi) < 1) + spheres = polygons[object].numverts; + + if (MI_IS_DEBUG(mi)) { + (void) fprintf(stderr, + "%s:\n\tobject=%s\n\tspheres=%d\n\tspeed=%d\n\ttexture=%s\n", + MI_NAME(mi), + polygons[object].shortname, + spheres, + (int) MI_CYCLES(mi), + do_texture ? "on" : "off" + ); + } + glXMakeCurrent(MI_DISPLAY(mi), MI_WINDOW(mi), *(sb->glx_context)); + +} +#endif /* !STANDALONE */ + +XSCREENSAVER_MODULE ("SBalls", sballs) + +#endif /* MODE_sballs */ diff --git a/hacks/glx/sballs.man b/hacks/glx/sballs.man new file mode 100644 index 00000000..33cb9421 --- /dev/null +++ b/hacks/glx/sballs.man @@ -0,0 +1,125 @@ +.de EX \"Begin example +.ne 5 +.if n .sp 1 +.if t .sp .5 +.nf +.in +.5i +.. +.de EE +.fi +.in -.5i +.if n .sp 1 +.if t .sp .5 +.. +.TH XScreenSaver 1 "03-Oct-01" "X Version 11" +.SH NAME +sballs - draws balls spinning like crazy in GL +.SH SYNOPSIS +.B sballs +[\-display \fIhost:display.screen\fP] [\-window] [\-root] +[\-visual \fIvisual\fP] [\-delay \fImicroseconds\fP] +[\-object \fIobject_number\fP] +[\-cycles \fIsphere_speed\fP] +[\-size \fIviewport_size\fP] +[\-texture] [\-no-texture] +[\-wireframe] [\-no-wireframe] +[\-trackmouse] [\-no-trackmouse] +[\-fps] +.SH DESCRIPTION +The \fIsballs\fP program draws an animation of balls spinning like crazy in GL. +.SH OPTIONS +.I sballs +accepts the following options: +.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 \-install +Install a private colormap for the window. +.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 \-fps +Display the current frame rate, CPU load, and polygon count. +.TP 8 +.B \-object \fIobject_number\fP\fP +Specify how the spheres are grouped (forming an object). +Objects are: +.TP 10 +.B 1 +tetrahedron +.TP 10 +.B 2 +cube. This is the default. +.TP 10 +.B 3 +octahedron +.TP 10 +.B 4 +dodecahedron +.TP 10 +.B 5 +icosahedron +.TP 10 +.B 6 +plane +.TP 10 +.B 7 +pyramid +.TP 10 +.B 8 +star +.TP 8 +.B \-size \fIviewport_size\fP\fP +Viewport of GL scene is specified size if greater than 32 and less than screensize. Default value is 0, meaning full screensize. +.TP 8 +.B \-texture +Show a textured background and spheres. This is the default. +.TP 8 +.B \-no\-texture +Disables texturing the animation. +.TP 8 +.B \-trackmouse +Let the mouse be a joystick to change the view of the animation. +This implies +.I \-no\-wander. +.TP 8 +.B \-no\-trackmouse +Disables mouse tracking. This is the default. +.TP 8 +.B \-wire +Draw a wireframe rendition of the spheres. +.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 2001 by Eric Lassauge. +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. + +The original code for this mode was written by +Mustata Bogdan (LoneRunner) +and can be found at http://www.cfxweb.net/lonerunner/ + +.SH AUTHOR +Mustata Bogdan (LoneRunner) +Eric Lassauge diff --git a/hacks/glx/shark.c b/hacks/glx/shark.c new file mode 100644 index 00000000..682ed6e8 --- /dev/null +++ b/hacks/glx/shark.c @@ -0,0 +1,1395 @@ +/* atlantis --- Shows moving 3D sea animals */ + +#if 0 +static const char sccsid[] = "@(#)shark.c 1.2 98/06/16 xlockmore"; +#endif + +/* Copyright (c) E. Lassauge, 1998. */ + +/* + * Permission to use, copy, modify, and distribute this software and its + * documentation for any purpose and without fee is hereby granted, + * provided that the above copyright notice appear in all copies and that + * both that copyright notice and this permission notice appear in + * supporting documentation. + * + * This file is provided AS IS with no warranties of any kind. The author + * shall have no liability with respect to the infringement of copyrights, + * trade secrets or any patents by this file or any part thereof. In no + * event will the author be liable for any lost revenue or profits or + * other special, indirect and consequential damages. + * + * The original code for this mode was written by Mark J. Kilgard + * as a demo for openGL programming. + * + * Porting it to xlock was possible by comparing the original Mesa's morph3d + * demo with it's ported version to xlock, so thanks for Marcelo F. Vianna + * (look at morph3d.c) for his indirect help. + * + * Thanks goes also to Brian Paul for making it possible and inexpensive + * to use OpenGL at home. + * + * My e-mail address is lassauge@users.sourceforge.net + * + * Eric Lassauge (May-13-1998) + * + */ + +/** + * (c) Copyright 1993, 1994, Silicon Graphics, Inc. + * ALL RIGHTS RESERVED + * Permission to use, copy, modify, and distribute this software for + * any purpose and without fee is hereby granted, provided that the above + * copyright notice appear in all copies and that both the copyright notice + * and this permission notice appear in supporting documentation, and that + * the name of Silicon Graphics, Inc. not be used in advertising + * or publicity pertaining to distribution of the software without specific, + * written prior permission. + * + * THE MATERIAL EMBODIED ON THIS SOFTWARE IS PROVIDED TO YOU "AS-IS" + * AND WITHOUT WARRANTY OF ANY KIND, EXPRESS, IMPLIED OR OTHERWISE, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTY OF MERCHANTABILITY OR + * FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL SILICON + * GRAPHICS, INC. BE LIABLE TO YOU OR ANYONE ELSE FOR ANY DIRECT, + * SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY + * KIND, OR ANY DAMAGES WHATSOEVER, INCLUDING WITHOUT LIMITATION, + * LOSS OF PROFIT, LOSS OF USE, SAVINGS OR REVENUE, OR THE CLAIMS OF + * THIRD PARTIES, WHETHER OR NOT SILICON GRAPHICS, INC. HAS BEEN + * ADVISED OF THE POSSIBILITY OF SUCH LOSS, HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE + * POSSESSION, USE OR PERFORMANCE OF THIS SOFTWARE. + * + * US Government Users Restricted Rights + * Use, duplication, or disclosure by the Government is subject to + * restrictions set forth in FAR 52.227.19(c)(2) or subparagraph + * (c)(1)(ii) of the Rights in Technical Data and Computer Software + * clause at DFARS 252.227-7013 and/or in similar or successor + * clauses in the FAR or the DOD or NASA FAR Supplement. + * Unpublished-- rights reserved under the copyright laws of the + * United States. Contractor/manufacturer is Silicon Graphics, + * Inc., 2011 N. Shoreline Blvd., Mountain View, CA 94039-7311. + * + * OpenGL(TM) is a trademark of Silicon Graphics, Inc. + */ + +#ifdef USE_GL + +#include "atlantis.h" + +/* *INDENT-OFF* */ +#if 0 +static const float N001[3] = {0, 1, 0}; +#endif +static const float N002[3] = {0.000077, -0.020611, 0.999788}; +static const float N003[3] = {0.961425, 0.258729, -0.09339}; +static const float N004[3] = {0.510811, -0.769633, -0.383063}; +static const float N005[3] = {0.400123, 0.855734, -0.328055}; +static const float N006[3] = {-0.770715, 0.610204, -0.18344}; +static const float N007[3] = {-0.915597, -0.373345, -0.149316}; +static const float N008[3] = {-0.972788, 0.208921, -0.100179}; +static const float N009[3] = {-0.939713, -0.312268, -0.139383}; +static const float N010[3] = {-0.624138, -0.741047, -0.247589}; +static const float N011[3] = {0.591434, -0.768401, -0.244471}; +static const float N012[3] = {0.935152, -0.328495, -0.132598}; +static const float N013[3] = {0.997102, 0.074243, -0.016593}; +static const float N014[3] = {0.969995, 0.241712, -0.026186}; +static const float N015[3] = {0.844539, 0.502628, -0.184714}; +static const float N016[3] = {-0.906608, 0.386308, -0.169787}; +static const float N017[3] = {-0.970016, 0.241698, -0.025516}; +static const float N018[3] = {-0.998652, 0.050493, -0.012045}; +static const float N019[3] = {-0.942685, -0.333051, -0.020556}; +static const float N020[3] = {-0.660944, -0.750276, 0.01548}; +static const float N021[3] = {0.503549, -0.862908, -0.042749}; +static const float N022[3] = {0.953202, -0.302092, -0.012089}; +static const float N023[3] = {0.998738, 0.023574, 0.044344}; +static const float N024[3] = {0.979297, 0.193272, 0.060202}; +static const float N025[3] = {0.7983, 0.464885, 0.382883}; +static const float N026[3] = {-0.75659, 0.452403, 0.472126}; +static const float N027[3] = {-0.953855, 0.293003, 0.065651}; +static const float N028[3] = {-0.998033, 0.040292, 0.048028}; +static const float N029[3] = {-0.977079, -0.204288, 0.059858}; +static const float N030[3] = {-0.729117, -0.675304, 0.11114}; +static const float N031[3] = {0.598361, -0.792753, 0.116221}; +static const float N032[3] = {0.965192, -0.252991, 0.066332}; +static const float N033[3] = {0.998201, -0.00279, 0.059892}; +static const float N034[3] = {0.978657, 0.193135, 0.070207}; +static const float N035[3] = {0.718815, 0.680392, 0.142733}; +static const float N036[3] = {-0.383096, 0.906212, 0.178936}; +static const float N037[3] = {-0.952831, 0.29259, 0.080647}; +static const float N038[3] = {-0.99768, 0.032417, 0.059861}; +static const float N039[3] = {-0.982629, -0.169881, 0.0747}; +static const float N040[3] = {-0.695424, -0.703466, 0.1467}; +static const float N041[3] = {0.359323, -0.915531, 0.180805}; +static const float N042[3] = {0.943356, -0.319387, 0.089842}; +static const float N043[3] = {0.998272, -0.032435, 0.048993}; +static const float N044[3] = {0.978997, 0.193205, 0.065084}; +static const float N045[3] = {0.872144, 0.470094, -0.135565}; +static const float N046[3] = {-0.664282, 0.737945, -0.119027}; +static const float N047[3] = {-0.954508, 0.28857, 0.075107}; +static const float N048[3] = {-0.998273, 0.032406, 0.048993}; +static const float N049[3] = {-0.979908, -0.193579, 0.048038}; +static const float N050[3] = {-0.858736, -0.507202, -0.072938}; +static const float N051[3] = {0.643545, -0.763887, -0.048237}; +static const float N052[3] = {0.95558, -0.288954, 0.058068}; +#if 0 +static const float N053[3] = {0, 1, 0}; +static const float N054[3] = {0, 1, 0}; +static const float N055[3] = {0, 1, 0}; +static const float N056[3] = {0, 1, 0}; +static const float N057[3] = {0, 1, 0}; +#endif +static const float N058[3] = {0.00005, 0.793007, -0.609213}; +static const float N059[3] = {0.91351, 0.235418, -0.331779}; +static const float N060[3] = {-0.80797, 0.495, -0.319625}; +static const float N061[3] = {0, 0.784687, -0.619892}; +static const float N062[3] = {0, -1, 0}; +static const float N063[3] = {0, 1, 0}; +static const float N064[3] = {0, 1, 0}; +static const float N065[3] = {0, 1, 0}; +static const float N066[3] = {-0.055784, 0.257059, 0.964784}; +#if 0 +static const float N067[3] = {0, 1, 0}; +static const float N068[3] = {0, 1, 0}; +#endif +static const float N069[3] = {-0.000505, -0.929775, -0.368127}; +static const float N070[3] = {0, 1, 0}; +#if 0 +static const float N071[3] = {-0.987102, 0.131723, -0.090984}; +static const float N072[3] = {-0.987102, 0.131723, -0.090984}; +static const float N073[3] = {-0.987102, 0.131723, -0.090984}; +static const float N074[3] = {0, 1, 0}; +static const float N075[3] = {0, 1, 0}; +static const float N076[3] = {0, 1, 0}; +static const float N077[3] = {0.99521, 0.071962, -0.066168}; +static const float N078[3] = {0.99521, 0.071962, -0.066168}; +static const float N079[3] = {0.99521, 0.071962, -0.066168}; +static const float N080[3] = {0, 1, 0}; +static const float N081[3] = {0, 1, 0}; +static const float N082[3] = {0, 1, 0}; +static const float P001[3] = {0, 0, 0}; +#endif +static float P002[3] = {0, -36.59, 5687.72}; +static const float P003[3] = {90, 114.73, 724.38}; +static float P004[3] = {58.24, -146.84, 262.35}; +static const float P005[3] = {27.81, 231.52, 510.43}; +static const float P006[3] = {-27.81, 230.43, 509.76}; +static float P007[3] = {-46.09, -146.83, 265.84}; +static const float P008[3] = {-90, 103.84, 718.53}; +static const float P009[3] = {-131.1, -165.92, 834.85}; +static float P010[3] = {-27.81, -285.31, 500}; +static float P011[3] = {27.81, -285.32, 500}; +static const float P012[3] = {147.96, -170.89, 845.5}; +static const float P013[3] = {180, 0, 2000}; +static const float P014[3] = {145.62, 352.67, 2000}; +static const float P015[3] = {55.62, 570.63, 2000}; +static const float P016[3] = {-55.62, 570.64, 2000}; +static const float P017[3] = {-145.62, 352.68, 2000}; +static const float P018[3] = {-180, 0.01, 2000}; +static const float P019[3] = {-178.2, -352.66, 2001.61}; +static const float P020[3] = {-55.63, -570.63, 2000}; +static const float P021[3] = {55.62, -570.64, 2000}; +static const float P022[3] = {179.91, -352.69, 1998.39}; +static float P023[3] = {150, 0, 3000}; +static float P024[3] = {121.35, 293.89, 3000}; +static float P025[3] = {46.35, 502.93, 2883.09}; +static float P026[3] = {-46.35, 497.45, 2877.24}; +static float P027[3] = {-121.35, 293.9, 3000}; +static float P028[3] = {-150, 0, 3000}; +static float P029[3] = {-152.21, -304.84, 2858.68}; +static float P030[3] = {-46.36, -475.52, 3000}; +static float P031[3] = {46.35, -475.53, 3000}; +static float P032[3] = {155.64, -304.87, 2863.5}; +static float P033[3] = {90, 0, 4000}; +static float P034[3] = {72.81, 176.33, 4000}; +static float P035[3] = {27.81, 285.32, 4000}; +static float P036[3] = {-27.81, 285.32, 4000}; +static float P037[3] = {-72.81, 176.34, 4000}; +static float P038[3] = {-90, 0, 4000}; +static float P039[3] = {-72.81, -176.33, 4000}; +static float P040[3] = {-27.81, -285.31, 4000}; +static float P041[3] = {27.81, -285.32, 4000}; +static float P042[3] = {72.81, -176.34, 4000}; +static float P043[3] = {30, 0, 5000}; +static float P044[3] = {24.27, 58.78, 5000}; +static float P045[3] = {9.27, 95.11, 5000}; +static float P046[3] = {-9.27, 95.11, 5000}; +static float P047[3] = {-24.27, 58.78, 5000}; +static float P048[3] = {-30, 0, 5000}; +static float P049[3] = {-24.27, -58.78, 5000}; +static float P050[3] = {-9.27, -95.1, 5000}; +static float P051[3] = {9.27, -95.11, 5000}; +static float P052[3] = {24.27, -58.78, 5000}; +#if 0 +static const float P053[3] = {0, 0, 0}; +static const float P054[3] = {0, 0, 0}; +static const float P055[3] = {0, 0, 0}; +static const float P056[3] = {0, 0, 0}; +static const float P057[3] = {0, 0, 0}; +#endif +static const float P058[3] = {0, 1212.72, 2703.08}; +static const float P059[3] = {50.36, 0, 108.14}; +static const float P060[3] = {-22.18, 0, 108.14}; +static float P061[3] = {0, 1181.61, 6344.65}; +static const float P062[3] = {516.45, -887.08, 2535.45}; +static const float P063[3] = {-545.69, -879.31, 2555.63}; +static const float P064[3] = {618.89, -1005.64, 2988.32}; +static const float P065[3] = {-635.37, -1014.79, 2938.68}; +static const float P066[3] = {0, 1374.43, 3064.18}; +#if 0 +static const float P067[3] = {158.49, -11.89, 1401.56}; +static const float P068[3] = {-132.08, -17.9, 1394.31}; +#endif +static float P069[3] = {0, -418.25, 5765.04}; +static float P070[3] = {0, 1266.91, 6629.6}; +static const float P071[3] = {-139.12, -124.96, 997.98}; +static const float P072[3] = {-139.24, -110.18, 1020.68}; +static const float P073[3] = {-137.33, -94.52, 1022.63}; +static const float P074[3] = {-137.03, -79.91, 996.89}; +static const float P075[3] = {-135.21, -91.48, 969.14}; +static const float P076[3] = {-135.39, -110.87, 968.76}; +static const float P077[3] = {150.23, -78.44, 995.53}; +static const float P078[3] = {152.79, -92.76, 1018.46}; +static const float P079[3] = {154.19, -110.2, 1020.55}; +static const float P080[3] = {151.33, -124.15, 993.77}; +static const float P081[3] = {150.49, -111.19, 969.86}; +static const float P082[3] = {150.79, -92.41, 969.7}; +static const float iP002[3] = {0, -36.59, 5687.72}; +static const float iP004[3] = {58.24, -146.84, 262.35}; +static const float iP007[3] = {-46.09, -146.83, 265.84}; +static const float iP010[3] = {-27.81, -285.31, 500}; +static const float iP011[3] = {27.81, -285.32, 500}; +static const float iP023[3] = {150, 0, 3000}; +static const float iP024[3] = {121.35, 293.89, 3000}; +static const float iP025[3] = {46.35, 502.93, 2883.09}; +static const float iP026[3] = {-46.35, 497.45, 2877.24}; +static const float iP027[3] = {-121.35, 293.9, 3000}; +static const float iP028[3] = {-150, 0, 3000}; +static const float iP029[3] = {-121.35, -304.84, 2853.86}; +static const float iP030[3] = {-46.36, -475.52, 3000}; +static const float iP031[3] = {46.35, -475.53, 3000}; +static const float iP032[3] = {121.35, -304.87, 2853.86}; +static const float iP033[3] = {90, 0, 4000}; +static const float iP034[3] = {72.81, 176.33, 4000}; +static const float iP035[3] = {27.81, 285.32, 4000}; +static const float iP036[3] = {-27.81, 285.32, 4000}; +static const float iP037[3] = {-72.81, 176.34, 4000}; +static const float iP038[3] = {-90, 0, 4000}; +static const float iP039[3] = {-72.81, -176.33, 4000}; +static const float iP040[3] = {-27.81, -285.31, 4000}; +static const float iP041[3] = {27.81, -285.32, 4000}; +static const float iP042[3] = {72.81, -176.34, 4000}; +static const float iP043[3] = {30, 0, 5000}; +static const float iP044[3] = {24.27, 58.78, 5000}; +static const float iP045[3] = {9.27, 95.11, 5000}; +static const float iP046[3] = {-9.27, 95.11, 5000}; +static const float iP047[3] = {-24.27, 58.78, 5000}; +static const float iP048[3] = {-30, 0, 5000}; +static const float iP049[3] = {-24.27, -58.78, 5000}; +static const float iP050[3] = {-9.27, -95.1, 5000}; +static const float iP051[3] = {9.27, -95.11, 5000}; +static const float iP052[3] = {24.27, -58.78, 5000}; +#if 0 +static const float iP053[3] = {0, 0, 0}; +#endif +static const float iP061[3] = {0, 1181.61, 6344.65}; +static const float iP069[3] = {0, -418.25, 5765.04}; +static const float iP070[3] = {0, 1266.91, 6629.6}; +/* *INDENT-ON* */ + + + +static void +Fish001(GLenum cap) +{ + glBegin(cap); + glNormal3fv(N005); + glVertex3fv(P005); + glNormal3fv(N059); + glVertex3fv(P059); + glNormal3fv(N060); + glVertex3fv(P060); + glNormal3fv(N006); + glVertex3fv(P006); + glEnd(); + glBegin(cap); + glNormal3fv(N015); + glVertex3fv(P015); + glNormal3fv(N005); + glVertex3fv(P005); + glNormal3fv(N006); + glVertex3fv(P006); + glNormal3fv(N016); + glVertex3fv(P016); + glEnd(); + glBegin(cap); + glNormal3fv(N006); + glVertex3fv(P006); + glNormal3fv(N060); + glVertex3fv(P060); + glNormal3fv(N008); + glVertex3fv(P008); + glEnd(); + glBegin(cap); + glNormal3fv(N016); + glVertex3fv(P016); + glNormal3fv(N006); + glVertex3fv(P006); + glNormal3fv(N008); + glVertex3fv(P008); + glEnd(); + glBegin(cap); + glNormal3fv(N016); + glVertex3fv(P016); + glNormal3fv(N008); + glVertex3fv(P008); + glNormal3fv(N017); + glVertex3fv(P017); + glEnd(); + glBegin(cap); + glNormal3fv(N017); + glVertex3fv(P017); + glNormal3fv(N008); + glVertex3fv(P008); + glNormal3fv(N018); + glVertex3fv(P018); + glEnd(); + glBegin(cap); + glNormal3fv(N008); + glVertex3fv(P008); + glNormal3fv(N009); + glVertex3fv(P009); + glNormal3fv(N018); + glVertex3fv(P018); + glEnd(); + glBegin(cap); + glNormal3fv(N008); + glVertex3fv(P008); + glNormal3fv(N060); + glVertex3fv(P060); + glNormal3fv(N009); + glVertex3fv(P009); + glEnd(); + glBegin(cap); + glNormal3fv(N007); + glVertex3fv(P007); + glNormal3fv(N010); + glVertex3fv(P010); + glNormal3fv(N009); + glVertex3fv(P009); + glEnd(); + glBegin(cap); + glNormal3fv(N009); + glVertex3fv(P009); + glNormal3fv(N019); + glVertex3fv(P019); + glNormal3fv(N018); + glVertex3fv(P018); + glEnd(); + glBegin(cap); + glNormal3fv(N009); + glVertex3fv(P009); + glNormal3fv(N010); + glVertex3fv(P010); + glNormal3fv(N019); + glVertex3fv(P019); + glEnd(); + glBegin(cap); + glNormal3fv(N010); + glVertex3fv(P010); + glNormal3fv(N020); + glVertex3fv(P020); + glNormal3fv(N019); + glVertex3fv(P019); + glEnd(); + glBegin(cap); + glNormal3fv(N010); + glVertex3fv(P010); + glNormal3fv(N011); + glVertex3fv(P011); + glNormal3fv(N021); + glVertex3fv(P021); + glNormal3fv(N020); + glVertex3fv(P020); + glEnd(); + glBegin(cap); + glNormal3fv(N004); + glVertex3fv(P004); + glNormal3fv(N011); + glVertex3fv(P011); + glNormal3fv(N010); + glVertex3fv(P010); + glNormal3fv(N007); + glVertex3fv(P007); + glEnd(); + glBegin(cap); + glNormal3fv(N004); + glVertex3fv(P004); + glNormal3fv(N012); + glVertex3fv(P012); + glNormal3fv(N011); + glVertex3fv(P011); + glEnd(); + glBegin(cap); + glNormal3fv(N012); + glVertex3fv(P012); + glNormal3fv(N022); + glVertex3fv(P022); + glNormal3fv(N011); + glVertex3fv(P011); + glEnd(); + glBegin(cap); + glNormal3fv(N011); + glVertex3fv(P011); + glNormal3fv(N022); + glVertex3fv(P022); + glNormal3fv(N021); + glVertex3fv(P021); + glEnd(); + glBegin(cap); + glNormal3fv(N059); + glVertex3fv(P059); + glNormal3fv(N005); + glVertex3fv(P005); + glNormal3fv(N015); + glVertex3fv(P015); + glEnd(); + glBegin(cap); + glNormal3fv(N015); + glVertex3fv(P015); + glNormal3fv(N014); + glVertex3fv(P014); + glNormal3fv(N003); + glVertex3fv(P003); + glEnd(); + glBegin(cap); + glNormal3fv(N015); + glVertex3fv(P015); + glNormal3fv(N003); + glVertex3fv(P003); + glNormal3fv(N059); + glVertex3fv(P059); + glEnd(); + glBegin(cap); + glNormal3fv(N014); + glVertex3fv(P014); + glNormal3fv(N013); + glVertex3fv(P013); + glNormal3fv(N003); + glVertex3fv(P003); + glEnd(); + glBegin(cap); + glNormal3fv(N003); + glVertex3fv(P003); + glNormal3fv(N012); + glVertex3fv(P012); + glNormal3fv(N059); + glVertex3fv(P059); + glEnd(); + glBegin(cap); + glNormal3fv(N013); + glVertex3fv(P013); + glNormal3fv(N012); + glVertex3fv(P012); + glNormal3fv(N003); + glVertex3fv(P003); + glEnd(); + glBegin(cap); + glNormal3fv(N013); + glVertex3fv(P013); + glNormal3fv(N022); + glVertex3fv(P022); + glNormal3fv(N012); + glVertex3fv(P012); + glEnd(); + glBegin(cap); + glVertex3fv(P071); + glVertex3fv(P072); + glVertex3fv(P073); + glVertex3fv(P074); + glVertex3fv(P075); + glVertex3fv(P076); + glEnd(); + glBegin(cap); + glVertex3fv(P077); + glVertex3fv(P078); + glVertex3fv(P079); + glVertex3fv(P080); + glVertex3fv(P081); + glVertex3fv(P082); + glEnd(); +} + +static void +Fish002(GLenum cap) +{ + glBegin(cap); + glNormal3fv(N013); + glVertex3fv(P013); + glNormal3fv(N014); + glVertex3fv(P014); + glNormal3fv(N024); + glVertex3fv(P024); + glNormal3fv(N023); + glVertex3fv(P023); + glEnd(); + glBegin(cap); + glNormal3fv(N014); + glVertex3fv(P014); + glNormal3fv(N015); + glVertex3fv(P015); + glNormal3fv(N025); + glVertex3fv(P025); + glNormal3fv(N024); + glVertex3fv(P024); + glEnd(); + glBegin(cap); + glNormal3fv(N016); + glVertex3fv(P016); + glNormal3fv(N017); + glVertex3fv(P017); + glNormal3fv(N027); + glVertex3fv(P027); + glNormal3fv(N026); + glVertex3fv(P026); + glEnd(); + glBegin(cap); + glNormal3fv(N017); + glVertex3fv(P017); + glNormal3fv(N018); + glVertex3fv(P018); + glNormal3fv(N028); + glVertex3fv(P028); + glNormal3fv(N027); + glVertex3fv(P027); + glEnd(); + glBegin(cap); + glNormal3fv(N020); + glVertex3fv(P020); + glNormal3fv(N021); + glVertex3fv(P021); + glNormal3fv(N031); + glVertex3fv(P031); + glNormal3fv(N030); + glVertex3fv(P030); + glEnd(); + glBegin(cap); + glNormal3fv(N013); + glVertex3fv(P013); + glNormal3fv(N023); + glVertex3fv(P023); + glNormal3fv(N022); + glVertex3fv(P022); + glEnd(); + glBegin(cap); + glNormal3fv(N022); + glVertex3fv(P022); + glNormal3fv(N023); + glVertex3fv(P023); + glNormal3fv(N032); + glVertex3fv(P032); + glEnd(); + glBegin(cap); + glNormal3fv(N022); + glVertex3fv(P022); + glNormal3fv(N032); + glVertex3fv(P032); + glNormal3fv(N031); + glVertex3fv(P031); + glEnd(); + glBegin(cap); + glNormal3fv(N022); + glVertex3fv(P022); + glNormal3fv(N031); + glVertex3fv(P031); + glNormal3fv(N021); + glVertex3fv(P021); + glEnd(); + glBegin(cap); + glNormal3fv(N018); + glVertex3fv(P018); + glNormal3fv(N019); + glVertex3fv(P019); + glNormal3fv(N029); + glVertex3fv(P029); + glEnd(); + glBegin(cap); + glNormal3fv(N018); + glVertex3fv(P018); + glNormal3fv(N029); + glVertex3fv(P029); + glNormal3fv(N028); + glVertex3fv(P028); + glEnd(); + glBegin(cap); + glNormal3fv(N019); + glVertex3fv(P019); + glNormal3fv(N020); + glVertex3fv(P020); + glNormal3fv(N030); + glVertex3fv(P030); + glEnd(); + glBegin(cap); + glNormal3fv(N019); + glVertex3fv(P019); + glNormal3fv(N030); + glVertex3fv(P030); + glNormal3fv(N029); + glVertex3fv(P029); + glEnd(); +} + +static void +Fish003(GLenum cap) +{ + glBegin(cap); + glNormal3fv(N032); + glVertex3fv(P032); + glNormal3fv(N023); + glVertex3fv(P023); + glNormal3fv(N033); + glVertex3fv(P033); + glNormal3fv(N042); + glVertex3fv(P042); + glEnd(); + glBegin(cap); + glNormal3fv(N031); + glVertex3fv(P031); + glNormal3fv(N032); + glVertex3fv(P032); + glNormal3fv(N042); + glVertex3fv(P042); + glNormal3fv(N041); + glVertex3fv(P041); + glEnd(); + glBegin(cap); + glNormal3fv(N023); + glVertex3fv(P023); + glNormal3fv(N024); + glVertex3fv(P024); + glNormal3fv(N034); + glVertex3fv(P034); + glNormal3fv(N033); + glVertex3fv(P033); + glEnd(); + glBegin(cap); + glNormal3fv(N024); + glVertex3fv(P024); + glNormal3fv(N025); + glVertex3fv(P025); + glNormal3fv(N035); + glVertex3fv(P035); + glNormal3fv(N034); + glVertex3fv(P034); + glEnd(); + glBegin(cap); + glNormal3fv(N030); + glVertex3fv(P030); + glNormal3fv(N031); + glVertex3fv(P031); + glNormal3fv(N041); + glVertex3fv(P041); + glNormal3fv(N040); + glVertex3fv(P040); + glEnd(); + glBegin(cap); + glNormal3fv(N025); + glVertex3fv(P025); + glNormal3fv(N026); + glVertex3fv(P026); + glNormal3fv(N036); + glVertex3fv(P036); + glNormal3fv(N035); + glVertex3fv(P035); + glEnd(); + glBegin(cap); + glNormal3fv(N026); + glVertex3fv(P026); + glNormal3fv(N027); + glVertex3fv(P027); + glNormal3fv(N037); + glVertex3fv(P037); + glNormal3fv(N036); + glVertex3fv(P036); + glEnd(); + glBegin(cap); + glNormal3fv(N027); + glVertex3fv(P027); + glNormal3fv(N028); + glVertex3fv(P028); + glNormal3fv(N038); + glVertex3fv(P038); + glNormal3fv(N037); + glVertex3fv(P037); + glEnd(); + glBegin(cap); + glNormal3fv(N028); + glVertex3fv(P028); + glNormal3fv(N029); + glVertex3fv(P029); + glNormal3fv(N039); + glVertex3fv(P039); + glNormal3fv(N038); + glVertex3fv(P038); + glEnd(); + glBegin(cap); + glNormal3fv(N029); + glVertex3fv(P029); + glNormal3fv(N030); + glVertex3fv(P030); + glNormal3fv(N040); + glVertex3fv(P040); + glNormal3fv(N039); + glVertex3fv(P039); + glEnd(); +} + +static void +Fish004(GLenum cap) +{ + glBegin(cap); + glNormal3fv(N040); + glVertex3fv(P040); + glNormal3fv(N041); + glVertex3fv(P041); + glNormal3fv(N051); + glVertex3fv(P051); + glNormal3fv(N050); + glVertex3fv(P050); + glEnd(); + glBegin(cap); + glNormal3fv(N041); + glVertex3fv(P041); + glNormal3fv(N042); + glVertex3fv(P042); + glNormal3fv(N052); + glVertex3fv(P052); + glNormal3fv(N051); + glVertex3fv(P051); + glEnd(); + glBegin(cap); + glNormal3fv(N042); + glVertex3fv(P042); + glNormal3fv(N033); + glVertex3fv(P033); + glNormal3fv(N043); + glVertex3fv(P043); + glNormal3fv(N052); + glVertex3fv(P052); + glEnd(); + glBegin(cap); + glNormal3fv(N033); + glVertex3fv(P033); + glNormal3fv(N034); + glVertex3fv(P034); + glNormal3fv(N044); + glVertex3fv(P044); + glNormal3fv(N043); + glVertex3fv(P043); + glEnd(); + glBegin(cap); + glNormal3fv(N034); + glVertex3fv(P034); + glNormal3fv(N035); + glVertex3fv(P035); + glNormal3fv(N045); + glVertex3fv(P045); + glNormal3fv(N044); + glVertex3fv(P044); + glEnd(); + glBegin(cap); + glNormal3fv(N035); + glVertex3fv(P035); + glNormal3fv(N036); + glVertex3fv(P036); + glNormal3fv(N046); + glVertex3fv(P046); + glNormal3fv(N045); + glVertex3fv(P045); + glEnd(); + glBegin(cap); + glNormal3fv(N036); + glVertex3fv(P036); + glNormal3fv(N037); + glVertex3fv(P037); + glNormal3fv(N047); + glVertex3fv(P047); + glNormal3fv(N046); + glVertex3fv(P046); + glEnd(); + glBegin(cap); + glNormal3fv(N037); + glVertex3fv(P037); + glNormal3fv(N038); + glVertex3fv(P038); + glNormal3fv(N048); + glVertex3fv(P048); + glNormal3fv(N047); + glVertex3fv(P047); + glEnd(); + glBegin(cap); + glNormal3fv(N038); + glVertex3fv(P038); + glNormal3fv(N039); + glVertex3fv(P039); + glNormal3fv(N049); + glVertex3fv(P049); + glNormal3fv(N048); + glVertex3fv(P048); + glEnd(); + glBegin(cap); + glNormal3fv(N039); + glVertex3fv(P039); + glNormal3fv(N040); + glVertex3fv(P040); + glNormal3fv(N050); + glVertex3fv(P050); + glNormal3fv(N049); + glVertex3fv(P049); + glEnd(); + glBegin(cap); + glNormal3fv(N070); + glVertex3fv(P070); + glNormal3fv(N061); + glVertex3fv(P061); + glNormal3fv(N002); + glVertex3fv(P002); + glEnd(); + glBegin(cap); + glNormal3fv(N061); + glVertex3fv(P061); + glNormal3fv(N046); + glVertex3fv(P046); + glNormal3fv(N002); + glVertex3fv(P002); + glEnd(); + glBegin(cap); + glNormal3fv(N045); + glVertex3fv(P045); + glNormal3fv(N046); + glVertex3fv(P046); + glNormal3fv(N061); + glVertex3fv(P061); + glEnd(); + glBegin(cap); + glNormal3fv(N002); + glVertex3fv(P002); + glNormal3fv(N061); + glVertex3fv(P061); + glNormal3fv(N070); + glVertex3fv(P070); + glEnd(); + glBegin(cap); + glNormal3fv(N002); + glVertex3fv(P002); + glNormal3fv(N045); + glVertex3fv(P045); + glNormal3fv(N061); + glVertex3fv(P061); + glEnd(); +} + +static void +Fish005(GLenum cap) +{ + glBegin(cap); + glNormal3fv(N002); + glVertex3fv(P002); + glNormal3fv(N044); + glVertex3fv(P044); + glNormal3fv(N045); + glVertex3fv(P045); + glEnd(); + glBegin(cap); + glNormal3fv(N002); + glVertex3fv(P002); + glNormal3fv(N043); + glVertex3fv(P043); + glNormal3fv(N044); + glVertex3fv(P044); + glEnd(); + glBegin(cap); + glNormal3fv(N002); + glVertex3fv(P002); + glNormal3fv(N052); + glVertex3fv(P052); + glNormal3fv(N043); + glVertex3fv(P043); + glEnd(); + glBegin(cap); + glNormal3fv(N002); + glVertex3fv(P002); + glNormal3fv(N051); + glVertex3fv(P051); + glNormal3fv(N052); + glVertex3fv(P052); + glEnd(); + glBegin(cap); + glNormal3fv(N002); + glVertex3fv(P002); + glNormal3fv(N046); + glVertex3fv(P046); + glNormal3fv(N047); + glVertex3fv(P047); + glEnd(); + glBegin(cap); + glNormal3fv(N002); + glVertex3fv(P002); + glNormal3fv(N047); + glVertex3fv(P047); + glNormal3fv(N048); + glVertex3fv(P048); + glEnd(); + glBegin(cap); + glNormal3fv(N002); + glVertex3fv(P002); + glNormal3fv(N048); + glVertex3fv(P048); + glNormal3fv(N049); + glVertex3fv(P049); + glEnd(); + glBegin(cap); + glNormal3fv(N002); + glVertex3fv(P002); + glNormal3fv(N049); + glVertex3fv(P049); + glNormal3fv(N050); + glVertex3fv(P050); + glEnd(); + glBegin(cap); + glNormal3fv(N050); + glVertex3fv(P050); + glNormal3fv(N051); + glVertex3fv(P051); + glNormal3fv(N069); + glVertex3fv(P069); + glEnd(); + glBegin(cap); + glNormal3fv(N051); + glVertex3fv(P051); + glNormal3fv(N002); + glVertex3fv(P002); + glNormal3fv(N069); + glVertex3fv(P069); + glEnd(); + glBegin(cap); + glNormal3fv(N050); + glVertex3fv(P050); + glNormal3fv(N069); + glVertex3fv(P069); + glNormal3fv(N002); + glVertex3fv(P002); + glEnd(); +} + +static void +Fish006(GLenum cap) +{ + glBegin(cap); + glNormal3fv(N066); + glVertex3fv(P066); + glNormal3fv(N016); + glVertex3fv(P016); + glNormal3fv(N026); + glVertex3fv(P026); + glEnd(); + glBegin(cap); + glNormal3fv(N015); + glVertex3fv(P015); + glNormal3fv(N066); + glVertex3fv(P066); + glNormal3fv(N025); + glVertex3fv(P025); + glEnd(); + glBegin(cap); + glNormal3fv(N025); + glVertex3fv(P025); + glNormal3fv(N066); + glVertex3fv(P066); + glNormal3fv(N026); + glVertex3fv(P026); + glEnd(); + glBegin(cap); + glNormal3fv(N066); + glVertex3fv(P066); + glNormal3fv(N058); + glVertex3fv(P058); + glNormal3fv(N016); + glVertex3fv(P016); + glEnd(); + glBegin(cap); + glNormal3fv(N015); + glVertex3fv(P015); + glNormal3fv(N058); + glVertex3fv(P058); + glNormal3fv(N066); + glVertex3fv(P066); + glEnd(); + glBegin(cap); + glNormal3fv(N058); + glVertex3fv(P058); + glNormal3fv(N015); + glVertex3fv(P015); + glNormal3fv(N016); + glVertex3fv(P016); + glEnd(); +} + +static void +Fish007(GLenum cap) +{ + glBegin(cap); + glNormal3fv(N062); + glVertex3fv(P062); + glNormal3fv(N022); + glVertex3fv(P022); + glNormal3fv(N032); + glVertex3fv(P032); + glEnd(); + glBegin(cap); + glNormal3fv(N062); + glVertex3fv(P062); + glNormal3fv(N032); + glVertex3fv(P032); + glNormal3fv(N064); + glVertex3fv(P064); + glEnd(); + glBegin(cap); + glNormal3fv(N022); + glVertex3fv(P022); + glNormal3fv(N062); + glVertex3fv(P062); + glNormal3fv(N032); + glVertex3fv(P032); + glEnd(); + glBegin(cap); + glNormal3fv(N062); + glVertex3fv(P062); + glNormal3fv(N064); + glVertex3fv(P064); + glNormal3fv(N032); + glVertex3fv(P032); + glEnd(); +} + +static void +Fish008(GLenum cap) +{ + glBegin(cap); + glNormal3fv(N063); + glVertex3fv(P063); + glNormal3fv(N019); + glVertex3fv(P019); + glNormal3fv(N029); + glVertex3fv(P029); + glEnd(); + glBegin(cap); + glNormal3fv(N019); + glVertex3fv(P019); + glNormal3fv(N063); + glVertex3fv(P063); + glNormal3fv(N029); + glVertex3fv(P029); + glEnd(); + glBegin(cap); + glNormal3fv(N063); + glVertex3fv(P063); + glNormal3fv(N029); + glVertex3fv(P029); + glNormal3fv(N065); + glVertex3fv(P065); + glEnd(); + glBegin(cap); + glNormal3fv(N063); + glVertex3fv(P063); + glNormal3fv(N065); + glVertex3fv(P065); + glNormal3fv(N029); + glVertex3fv(P029); + glEnd(); +} + +static void +Fish009(GLenum cap) +{ + glBegin(cap); + glVertex3fv(P059); + glVertex3fv(P012); + glVertex3fv(P009); + glVertex3fv(P060); + glEnd(); + glBegin(cap); + glVertex3fv(P012); + glVertex3fv(P004); + glVertex3fv(P007); + glVertex3fv(P009); + glEnd(); +} + +static void +Fish_1(GLenum cap) +{ + Fish004(cap); + Fish005(cap); + Fish003(cap); + Fish007(cap); + Fish006(cap); + Fish002(cap); + Fish008(cap); + Fish009(cap); + Fish001(cap); +} + +static void +Fish_2(GLenum cap) +{ + Fish005(cap); + Fish004(cap); + Fish003(cap); + Fish008(cap); + Fish006(cap); + Fish002(cap); + Fish007(cap); + Fish009(cap); + Fish001(cap); +} + +static void +Fish_3(GLenum cap) +{ + Fish005(cap); + Fish004(cap); + Fish007(cap); + Fish003(cap); + Fish002(cap); + Fish008(cap); + Fish009(cap); + Fish001(cap); + Fish006(cap); +} + +static void +Fish_4(GLenum cap) +{ + Fish005(cap); + Fish004(cap); + Fish008(cap); + Fish003(cap); + Fish002(cap); + Fish007(cap); + Fish009(cap); + Fish001(cap); + Fish006(cap); +} + +static void +Fish_5(GLenum cap) +{ + Fish009(cap); + Fish006(cap); + Fish007(cap); + Fish001(cap); + Fish002(cap); + Fish003(cap); + Fish008(cap); + Fish004(cap); + Fish005(cap); +} + +static void +Fish_6(GLenum cap) +{ + Fish009(cap); + Fish006(cap); + Fish008(cap); + Fish001(cap); + Fish002(cap); + Fish007(cap); + Fish003(cap); + Fish004(cap); + Fish005(cap); +} + +static void +Fish_7(GLenum cap) +{ + Fish009(cap); + Fish001(cap); + Fish007(cap); + Fish005(cap); + Fish002(cap); + Fish008(cap); + Fish003(cap); + Fish004(cap); + Fish006(cap); +} + +static void +Fish_8(GLenum cap) +{ + Fish009(cap); + Fish008(cap); + Fish001(cap); + Fish002(cap); + Fish007(cap); + Fish003(cap); + Fish005(cap); + Fish004(cap); + Fish006(cap); +} + +void +DrawShark(fishRec * fish, int wire) +{ + float mat[4][4]; + int n; + float seg1, seg2, seg3, seg4, segup; + float thrash, chomp; + GLenum cap; + + fish->htail = (int) (fish->htail - (int) (5 * fish->v)) % 360; + + thrash = 50 * fish->v; + + seg1 = 0.6 * thrash * sin(fish->htail * RRAD); + seg2 = 1.8 * thrash * sin((fish->htail + 45) * RRAD); + seg3 = 3 * thrash * sin((fish->htail + 90) * RRAD); + seg4 = 4 * thrash * sin((fish->htail + 110) * RRAD); + + chomp = 0; + if (fish->v > 2) { + chomp = -(fish->v - 2) * 200; + } + P004[1] = iP004[1] + chomp; + P007[1] = iP007[1] + chomp; + P010[1] = iP010[1] + chomp; + P011[1] = iP011[1] + chomp; + + P023[0] = iP023[0] + seg1; + P024[0] = iP024[0] + seg1; + P025[0] = iP025[0] + seg1; + P026[0] = iP026[0] + seg1; + P027[0] = iP027[0] + seg1; + P028[0] = iP028[0] + seg1; + P029[0] = iP029[0] + seg1; + P030[0] = iP030[0] + seg1; + P031[0] = iP031[0] + seg1; + P032[0] = iP032[0] + seg1; + P033[0] = iP033[0] + seg2; + P034[0] = iP034[0] + seg2; + P035[0] = iP035[0] + seg2; + P036[0] = iP036[0] + seg2; + P037[0] = iP037[0] + seg2; + P038[0] = iP038[0] + seg2; + P039[0] = iP039[0] + seg2; + P040[0] = iP040[0] + seg2; + P041[0] = iP041[0] + seg2; + P042[0] = iP042[0] + seg2; + P043[0] = iP043[0] + seg3; + P044[0] = iP044[0] + seg3; + P045[0] = iP045[0] + seg3; + P046[0] = iP046[0] + seg3; + P047[0] = iP047[0] + seg3; + P048[0] = iP048[0] + seg3; + P049[0] = iP049[0] + seg3; + P050[0] = iP050[0] + seg3; + P051[0] = iP051[0] + seg3; + P052[0] = iP052[0] + seg3; + P002[0] = iP002[0] + seg4; + P061[0] = iP061[0] + seg4; + P069[0] = iP069[0] + seg4; + P070[0] = iP070[0] + seg4; + + fish->vtail += ((fish->dtheta - fish->vtail) * 0.1); + + if (fish->vtail > 0.5) { + fish->vtail = 0.5; + } else if (fish->vtail < -0.5) { + fish->vtail = -0.5; + } + segup = thrash * fish->vtail; + + P023[1] = iP023[1] + segup; + P024[1] = iP024[1] + segup; + P025[1] = iP025[1] + segup; + P026[1] = iP026[1] + segup; + P027[1] = iP027[1] + segup; + P028[1] = iP028[1] + segup; + P029[1] = iP029[1] + segup; + P030[1] = iP030[1] + segup; + P031[1] = iP031[1] + segup; + P032[1] = iP032[1] + segup; + P033[1] = iP033[1] + segup * 5; + P034[1] = iP034[1] + segup * 5; + P035[1] = iP035[1] + segup * 5; + P036[1] = iP036[1] + segup * 5; + P037[1] = iP037[1] + segup * 5; + P038[1] = iP038[1] + segup * 5; + P039[1] = iP039[1] + segup * 5; + P040[1] = iP040[1] + segup * 5; + P041[1] = iP041[1] + segup * 5; + P042[1] = iP042[1] + segup * 5; + P043[1] = iP043[1] + segup * 12; + P044[1] = iP044[1] + segup * 12; + P045[1] = iP045[1] + segup * 12; + P046[1] = iP046[1] + segup * 12; + P047[1] = iP047[1] + segup * 12; + P048[1] = iP048[1] + segup * 12; + P049[1] = iP049[1] + segup * 12; + P050[1] = iP050[1] + segup * 12; + P051[1] = iP051[1] + segup * 12; + P052[1] = iP052[1] + segup * 12; + P002[1] = iP002[1] + segup * 17; + P061[1] = iP061[1] + segup * 17; + P069[1] = iP069[1] + segup * 17; + P070[1] = iP070[1] + segup * 17; + + glPushMatrix(); + + glTranslatef(0, 0, -3000); + + glGetFloatv(GL_MODELVIEW_MATRIX, &mat[0][0]); + n = 0; + if (mat[0][2] >= 0) { + n += 1; + } + if (mat[1][2] >= 0) { + n += 2; + } + if (mat[2][2] >= 0) { + n += 4; + } + glScalef(2, 1, 1); + + glEnable(GL_CULL_FACE); + cap = wire ? GL_LINE_LOOP : GL_POLYGON; + switch (n) { + case 0: + Fish_1(cap); + break; + case 1: + Fish_2(cap); + break; + case 2: + Fish_3(cap); + break; + case 3: + Fish_4(cap); + break; + case 4: + Fish_5(cap); + break; + case 5: + Fish_6(cap); + break; + case 6: + Fish_7(cap); + break; + case 7: + Fish_8(cap); + break; + } + glDisable(GL_CULL_FACE); + + glPopMatrix(); +} +#endif diff --git a/hacks/glx/sierpinski3d.c b/hacks/glx/sierpinski3d.c new file mode 100644 index 00000000..7bcefcf2 --- /dev/null +++ b/hacks/glx/sierpinski3d.c @@ -0,0 +1,583 @@ +/* -*- Mode: C; tab-width: 4 -*- */ +/* Sierpinski3D --- 3D sierpinski gasket */ + +#if 0 +static const char sccsid[] = "@(#)sierpinski3D.c 00.01 99/11/04 xlockmore"; +#endif + +/*- + * Permission to use, copy, modify, and distribute this software and its + * documentation for any purpose and without fee is hereby granted, + * provided that the above copyright notice appear in all copies and that + * both that copyright notice and this permission notice appear in + * supporting documentation. + * + * This file is provided AS IS with no warranties of any kind. The author + * shall have no liability with respect to the infringement of copyrights, + * trade secrets or any patents by this file or any part thereof. In no + * event will the author be liable for any lost revenue or profits or + * other special, indirect and consequential damages. + * + * Revision History: + * 1999: written by Tim Robinson + * a 3-D representation of the Sierpinski gasket fractal. + * + * 10-Dec-99 jwz rewrote to draw a set of tetrahedrons instead of a + * random scattering of points. + */ + +#ifdef STANDALONE +# define DEFAULTS "*delay: 20000 \n" \ + "*showFPS: False \n" \ + "*wireframe: False \n" \ + +# define refresh_gasket 0 +# include "xlockmore.h" /* from the xscreensaver distribution */ +#else /* !STANDALONE */ +# include "xlock.h" /* from the xlockmore distribution */ +#endif /* !STANDALONE */ + +#ifdef USE_GL + +#define DEF_SPIN "True" +#define DEF_WANDER "True" +#define DEF_SPEED "150" +#define DEF_MAX_DEPTH "5" + +#include "rotator.h" +#include "gltrackball.h" + +#undef countof +#define countof(x) (sizeof((x))/sizeof((*x))) + +static int max_depth; +static int speed; +static Bool do_spin; +static Bool do_wander; + +static XrmOptionDescRec opts[] = { + {"-depth", ".sierpinski3d.maxDepth", XrmoptionSepArg, 0 }, + {"-speed", ".sierpinski3d.speed", XrmoptionSepArg, 0 }, + { "-spin", ".spin", XrmoptionNoArg, "True" }, + { "+spin", ".spin", XrmoptionNoArg, "False" }, + { "-wander", ".wander", XrmoptionNoArg, "True" }, + { "+wander", ".wander", XrmoptionNoArg, "False" }, +}; + +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_Int}, + {&max_depth, "maxDepth", "MaxDepth", DEF_MAX_DEPTH, t_Int}, +}; + + +ENTRYPOINT ModeSpecOpt gasket_opts = {countof(opts), opts, countof(vars), vars, NULL}; + +#ifdef USE_MODULES +ModStruct gasket_description = +{"gasket", "init_gasket", "draw_gasket", "release_gasket", + "draw_gasket", "init_gasket", NULL, &gasket_opts, + 1000, 1, 2, 1, 4, 1.0, "", + "Shows GL's Sierpinski gasket", 0, NULL}; + +#endif + +typedef struct { + double x,y,z; +} XYZ; + +typedef struct { + GLuint gasket0, gasket1, gasket2, gasket3; + GLXContext *glx_context; + Window window; + rotator *rot; + trackball_state *trackball; + Bool button_down_p; + + int current_depth; + + int ncolors; + XColor *colors; + int ccolor0; + int ccolor1; + int ccolor2; + int ccolor3; + + int tick; + +} gasketstruct; + +static gasketstruct *gasket = NULL; + + +static void +triangle (GLfloat x1, GLfloat y1, GLfloat z1, + GLfloat x2, GLfloat y2, GLfloat z2, + GLfloat x3, GLfloat y3, GLfloat z3, + Bool wireframe_p) +{ + if (wireframe_p) + glBegin (GL_LINE_LOOP); + else + glBegin (GL_TRIANGLES); + glVertex3f (x1, y1, z1); + glVertex3f (x2, y2, z2); + glVertex3f (x3, y3, z3); + glEnd(); +} + +static void +four_tetras (gasketstruct *gp, + XYZ *outer, XYZ *normals, + Bool wireframe_p, int countdown, int which, + int *countP) +{ + if (countdown <= 0) + { + (*countP)++; + if (which == 0) + { + glNormal3f (normals[0].x, normals[0].y, normals[0].z); + triangle (outer[0].x, outer[0].y, outer[0].z, + outer[1].x, outer[1].y, outer[1].z, + outer[2].x, outer[2].y, outer[2].z, + wireframe_p); + } + else if (which == 1) + { + glNormal3f (normals[1].x, normals[1].y, normals[1].z); + triangle (outer[0].x, outer[0].y, outer[0].z, + outer[3].x, outer[3].y, outer[3].z, + outer[1].x, outer[1].y, outer[1].z, + wireframe_p); + } + else if (which == 2) + { + glNormal3f (normals[2].x, normals[2].y, normals[2].z); + triangle (outer[0].x, outer[0].y, outer[0].z, + outer[2].x, outer[2].y, outer[2].z, + outer[3].x, outer[3].y, outer[3].z, + wireframe_p); + } + else + { + glNormal3f (normals[3].x, normals[3].y, normals[3].z); + triangle (outer[1].x, outer[1].y, outer[1].z, + outer[3].x, outer[3].y, outer[3].z, + outer[2].x, outer[2].y, outer[2].z, + wireframe_p); + } + } + else + { +# define M01 0 +# define M02 1 +# define M03 2 +# define M12 3 +# define M13 4 +# define M23 5 + XYZ inner[M23+1]; + XYZ corner[4]; + + inner[M01].x = (outer[0].x + outer[1].x) / 2.0; + inner[M01].y = (outer[0].y + outer[1].y) / 2.0; + inner[M01].z = (outer[0].z + outer[1].z) / 2.0; + + inner[M02].x = (outer[0].x + outer[2].x) / 2.0; + inner[M02].y = (outer[0].y + outer[2].y) / 2.0; + inner[M02].z = (outer[0].z + outer[2].z) / 2.0; + + inner[M03].x = (outer[0].x + outer[3].x) / 2.0; + inner[M03].y = (outer[0].y + outer[3].y) / 2.0; + inner[M03].z = (outer[0].z + outer[3].z) / 2.0; + + inner[M12].x = (outer[1].x + outer[2].x) / 2.0; + inner[M12].y = (outer[1].y + outer[2].y) / 2.0; + inner[M12].z = (outer[1].z + outer[2].z) / 2.0; + + inner[M13].x = (outer[1].x + outer[3].x) / 2.0; + inner[M13].y = (outer[1].y + outer[3].y) / 2.0; + inner[M13].z = (outer[1].z + outer[3].z) / 2.0; + + inner[M23].x = (outer[2].x + outer[3].x) / 2.0; + inner[M23].y = (outer[2].y + outer[3].y) / 2.0; + inner[M23].z = (outer[2].z + outer[3].z) / 2.0; + + countdown--; + + corner[0] = outer[0]; + corner[1] = inner[M01]; + corner[2] = inner[M02]; + corner[3] = inner[M03]; + four_tetras (gp, corner, normals, wireframe_p, countdown, which, countP); + + corner[0] = inner[M01]; + corner[1] = outer[1]; + corner[2] = inner[M12]; + corner[3] = inner[M13]; + four_tetras (gp, corner, normals, wireframe_p, countdown, which, countP); + + corner[0] = inner[M02]; + corner[1] = inner[M12]; + corner[2] = outer[2]; + corner[3] = inner[M23]; + four_tetras (gp, corner, normals, wireframe_p, countdown, which, countP); + + corner[0] = inner[M03]; + corner[1] = inner[M13]; + corner[2] = inner[M23]; + corner[3] = outer[3]; + four_tetras (gp, corner, normals, wireframe_p, countdown, which, countP); + } +} + + +static void +compile_gasket(ModeInfo *mi, int which) +{ + Bool wireframe_p = MI_IS_WIREFRAME(mi); + gasketstruct *gp = &gasket[MI_SCREEN(mi)]; + int count = 0; + XYZ vertex[5]; + XYZ normal[4]; + + vertex[0].x = -1; vertex[0].y = -1; vertex[0].z = -1; + vertex[1].x = 1; vertex[1].y = 1; vertex[1].z = -1; + vertex[2].x = 1; vertex[2].y = -1; vertex[2].z = 1; + vertex[3].x = -1; vertex[3].y = 1; vertex[3].z = 1; + vertex[4].x = 0; vertex[4].y = 0; vertex[4].z = 0; /* center */ + + normal[0].x = 1; normal[0].y = -1; normal[0].z = -1; + normal[1].x = -1; normal[1].y = 1; normal[1].z = -1; + normal[2].x = -1; normal[2].y = -1; normal[2].z = 1; + normal[3].x = 1; normal[3].y = 1; normal[3].z = 1; + + four_tetras (gp, vertex, normal, wireframe_p, + (gp->current_depth < 0 + ? -gp->current_depth : gp->current_depth), + which, + &count); + mi->polygon_count += count; +} + +static void +draw(ModeInfo *mi) +{ + Bool wireframe_p = MI_IS_WIREFRAME(mi); + gasketstruct *gp = &gasket[MI_SCREEN(mi)]; + + static const GLfloat pos[] = {-4.0, 3.0, 10.0, 1.0}; + static const GLfloat white[] = {1.0, 1.0, 1.0, 1.0}; + + GLfloat color0[] = {0.0, 0.0, 0.0, 1.0}; + GLfloat color1[] = {0.0, 0.0, 0.0, 1.0}; + GLfloat color2[] = {0.0, 0.0, 0.0, 1.0}; + GLfloat color3[] = {0.0, 0.0, 0.0, 1.0}; + + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + + if (!wireframe_p) + { + glColor4fv (white); + + glLightfv(GL_LIGHT0, GL_POSITION, pos); + + color0[0] = gp->colors[gp->ccolor0].red / 65536.0; + color0[1] = gp->colors[gp->ccolor0].green / 65536.0; + color0[2] = gp->colors[gp->ccolor0].blue / 65536.0; + + color1[0] = gp->colors[gp->ccolor1].red / 65536.0; + color1[1] = gp->colors[gp->ccolor1].green / 65536.0; + color1[2] = gp->colors[gp->ccolor1].blue / 65536.0; + + color2[0] = gp->colors[gp->ccolor2].red / 65536.0; + color2[1] = gp->colors[gp->ccolor2].green / 65536.0; + color2[2] = gp->colors[gp->ccolor2].blue / 65536.0; + + color3[0] = gp->colors[gp->ccolor3].red / 65536.0; + color3[1] = gp->colors[gp->ccolor3].green / 65536.0; + color3[2] = gp->colors[gp->ccolor3].blue / 65536.0; + + gp->ccolor0++; + gp->ccolor1++; + gp->ccolor2++; + gp->ccolor3++; + if (gp->ccolor0 >= gp->ncolors) gp->ccolor0 = 0; + if (gp->ccolor1 >= gp->ncolors) gp->ccolor1 = 0; + if (gp->ccolor2 >= gp->ncolors) gp->ccolor2 = 0; + if (gp->ccolor3 >= gp->ncolors) gp->ccolor3 = 0; + + glShadeModel(GL_SMOOTH); + + glEnable(GL_LIGHTING); + glEnable(GL_LIGHT0); + } + + glEnable(GL_DEPTH_TEST); + glEnable(GL_NORMALIZE); + glEnable(GL_CULL_FACE); + + glPushMatrix(); + + { + double x, y, z; + get_position (gp->rot, &x, &y, &z, !gp->button_down_p); + glTranslatef((x - 0.5) * 10, + (y - 0.5) * 10, + (z - 0.5) * 20); + + /* Do it twice because we don't track the device's orientation. */ + glRotatef( current_device_rotation(), 0, 0, 1); + gltrackball_rotate (gp->trackball); + glRotatef(-current_device_rotation(), 0, 0, 1); + + get_rotation (gp->rot, &x, &y, &z, !gp->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, 4, 4); + + glMaterialfv (GL_FRONT, GL_AMBIENT_AND_DIFFUSE, color0); + glCallList(gp->gasket0); + glMaterialfv (GL_FRONT, GL_AMBIENT_AND_DIFFUSE, color1); + glCallList(gp->gasket1); + glMaterialfv (GL_FRONT, GL_AMBIENT_AND_DIFFUSE, color2); + glCallList(gp->gasket2); + glMaterialfv (GL_FRONT, GL_AMBIENT_AND_DIFFUSE, color3); + glCallList(gp->gasket3); + + glPopMatrix(); + + + if (gp->tick++ >= speed) + { + gp->tick = 0; + if (gp->current_depth >= max_depth) + gp->current_depth = -max_depth; + gp->current_depth++; + + /* We make four different lists so that each face of the tetrahedrons + can have a different color (all triangles facing in the same + direction have the same color, which is different from all + triangles facing in other directions.) + */ + glDeleteLists (gp->gasket0, 1); + glDeleteLists (gp->gasket1, 1); + glDeleteLists (gp->gasket2, 1); + glDeleteLists (gp->gasket3, 1); + + mi->polygon_count = 0; + glNewList (gp->gasket0, GL_COMPILE); compile_gasket (mi, 0); glEndList(); + glNewList (gp->gasket1, GL_COMPILE); compile_gasket (mi, 1); glEndList(); + glNewList (gp->gasket2, GL_COMPILE); compile_gasket (mi, 2); glEndList(); + glNewList (gp->gasket3, GL_COMPILE); compile_gasket (mi, 3); glEndList(); + + mi->recursion_depth = (gp->current_depth > 0 + ? gp->current_depth + : -gp->current_depth); + } +} + + +/* new window size or exposure */ +ENTRYPOINT void +reshape_gasket(ModeInfo *mi, int width, int height) +{ + GLfloat h = (GLfloat) height / (GLfloat) width; + + glViewport(0, 0, (GLint) width, (GLint) height); + glMatrixMode(GL_PROJECTION); + glLoadIdentity(); + gluPerspective (30.0, 1/h, 1.0, 100.0); + + glMatrixMode(GL_MODELVIEW); + glLoadIdentity(); + gluLookAt( 0.0, 0.0, 30.0, + 0.0, 0.0, 0.0, + 0.0, 1.0, 0.0); + + glClear(GL_COLOR_BUFFER_BIT); +} + +static void +pinit(ModeInfo *mi) +{ + gasketstruct *gp = &gasket[MI_SCREEN(mi)]; + + /* draw the gasket */ + gp->gasket0 = glGenLists(1); + gp->gasket1 = glGenLists(1); + gp->gasket2 = glGenLists(1); + gp->gasket3 = glGenLists(1); + gp->current_depth = 1; /* start out at level 1, not 0 */ +} + + +ENTRYPOINT Bool +gasket_handle_event (ModeInfo *mi, XEvent *event) +{ + gasketstruct *gp = &gasket[MI_SCREEN(mi)]; + + if (event->xany.type == ButtonPress && + event->xbutton.button == Button1) + { + gp->button_down_p = True; + gltrackball_start (gp->trackball, + event->xbutton.x, event->xbutton.y, + MI_WIDTH (mi), MI_HEIGHT (mi)); + return True; + } + else if (event->xany.type == ButtonRelease && + event->xbutton.button == Button1) + { + gp->button_down_p = False; + return True; + } + else if (event->xany.type == ButtonPress && + (event->xbutton.button == Button4 || + event->xbutton.button == Button5 || + event->xbutton.button == Button6 || + event->xbutton.button == Button7)) + { + gltrackball_mousewheel (gp->trackball, event->xbutton.button, 10, + !!event->xbutton.state); + return True; + } + else if (event->xany.type == MotionNotify && + gp->button_down_p) + { + gltrackball_track (gp->trackball, + event->xmotion.x, event->xmotion.y, + MI_WIDTH (mi), MI_HEIGHT (mi)); + return True; + } + + return False; +} + + +ENTRYPOINT void +init_gasket(ModeInfo *mi) +{ + int screen = MI_SCREEN(mi); + gasketstruct *gp; + + if (gasket == NULL) + { + if ((gasket = (gasketstruct *) calloc(MI_NUM_SCREENS(mi), + sizeof (gasketstruct))) == NULL) + return; + } + gp = &gasket[screen]; + + gp->window = MI_WINDOW(mi); + + { + double spin_speed = 1.0; + double wander_speed = 0.03; + gp->rot = make_rotator (do_spin ? spin_speed : 0, + do_spin ? spin_speed : 0, + do_spin ? spin_speed : 0, + 1.0, + do_wander ? wander_speed : 0, + True); + gp->trackball = gltrackball_init (); + } + + gp->ncolors = 255; + gp->colors = (XColor *) calloc(gp->ncolors, sizeof(XColor)); + make_smooth_colormap (0, 0, 0, + gp->colors, &gp->ncolors, + False, 0, False); + gp->ccolor0 = 0; + gp->ccolor1 = gp->ncolors * 0.25; + gp->ccolor2 = gp->ncolors * 0.5; + gp->ccolor3 = gp->ncolors * 0.75; + gp->tick = 999999; + + if ((gp->glx_context = init_GL(mi)) != NULL) + { + reshape_gasket(mi, MI_WIDTH(mi), MI_HEIGHT(mi)); + pinit(mi); + } + else + { + MI_CLEARWINDOW(mi); + } +} + +ENTRYPOINT void +draw_gasket(ModeInfo * mi) +{ + gasketstruct *gp = &gasket[MI_SCREEN(mi)]; + Display *display = MI_DISPLAY(mi); + Window window = MI_WINDOW(mi); + + if (!gp->glx_context) return; + + glDrawBuffer(GL_BACK); + + /* 0 = 4 polygons + 1 = 16 polygons + 2 = 64 polygons + 3 = 256 polygons + 4 = 1,024 polygons + 5 = 4,096 polygons + 6 = 16,384 polygons + 7 = 65,536 polygons, 30 fps (3GHz Core 2 Duo, GeForce 8800 GS) + 8 = 262,144 polygons, 12 fps + 9 = 1,048,576 polygons, 4 fps + 10 = 4,194,304 polygons, 1 fps + 11 = 16,777,216 polygons, 0.3 fps + 12 = 67,108,864 polygons, OOM! + 13 = 268,435,456 polygons + 14 = 1,073,741,824 polygons, 31 bits + 15 = 4,294,967,296 polygons, 33 bits + 16 = 17,179,869,184 polygons, 35 bits + */ + if (max_depth > 10) + max_depth = 10; + + glXMakeCurrent(display, window, *(gp->glx_context)); + draw(mi); + if (mi->fps_p) do_fps (mi); + glFinish(); + glXSwapBuffers(display, window); +} + +ENTRYPOINT void +release_gasket(ModeInfo * mi) +{ + if (gasket != NULL) + { + int screen; + + for (screen = 0; screen < MI_NUM_SCREENS(mi); screen++) + { + gasketstruct *gp = &gasket[screen]; + + if (gp->glx_context) + { + /* Display lists MUST be freed while their glXContext is current. */ + glXMakeCurrent(MI_DISPLAY(mi), gp->window, *(gp->glx_context)); + + if (glIsList(gp->gasket0)) glDeleteLists(gp->gasket0, 1); + if (glIsList(gp->gasket1)) glDeleteLists(gp->gasket1, 1); + if (glIsList(gp->gasket2)) glDeleteLists(gp->gasket2, 1); + if (glIsList(gp->gasket3)) glDeleteLists(gp->gasket3, 1); + } + } + (void) free((void *) gasket); + gasket = NULL; + } + FreeAllGL(mi); +} + +XSCREENSAVER_MODULE_2 ("Sierpinski3D", sierpinski3d, gasket) + +/*********************************************************/ + +#endif diff --git a/hacks/glx/sierpinski3d.man b/hacks/glx/sierpinski3d.man new file mode 100644 index 00000000..ed3b69a9 --- /dev/null +++ b/hacks/glx/sierpinski3d.man @@ -0,0 +1,67 @@ +.TH XScreenSaver 1 "" "X Version 11" +.SH NAME +sierpinski3d - 3D Sierpinski triangle fractal. +.SH SYNOPSIS +.B sierpinski3d +[\-display \fIhost:display.screen\fP] +[\-visual \fIvisual\fP] +[\-window] +[\-root] +[\-delay \fInumber\fP] +[\-speed \fInumber\fP] +[\-depth \fInumber\fP] +[\-wireframe] +[\-fps] +.SH DESCRIPTION +This draws the three-dimensional variant of the recursive Sierpinski +triangle fractal, using GL. +.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: 20000 (0.02 seconds.). +.TP 8 +.B \-speed \fInumber\fP +Number of frames before changing shape. Default: 150. +.TP 8 +.B \-depth \fInumber\fP +Max depth to descend. Default: 5. You probably don't have enough +memory for 6. +.TP 8 +.B \-wireframe +Render in wireframe instead of solid. +.TP 8 +.B \-fps +Display the current frame rate, CPU load, and polygon count. +.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 2002 by Tim Robinson 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 +Tim Robinson and Jamie Zawinski. diff --git a/hacks/glx/skytentacles.c b/hacks/glx/skytentacles.c new file mode 100644 index 00000000..c140fc37 --- /dev/null +++ b/hacks/glx/skytentacles.c @@ -0,0 +1,1095 @@ +/* Sky Tentacles, Copyright (c) 2008-2012 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. + */ + +#define DEFAULTS "*delay: 30000 \n" \ + "*count: 9 \n" \ + "*showFPS: False \n" \ + "*wireframe: False \n" \ + +# define refresh_tentacles 0 +# define release_tentacles 0 +#undef countof +#define countof(x) (sizeof((x))/sizeof((*x))) + +#include "xlockmore.h" +#include "colors.h" +#include "normals.h" +#include "rotator.h" +#include "gltrackball.h" +#include + +#include "xpm-ximage.h" +#include "../images/scales.xpm" + +static char *grey_texture[] = { + "16 1 3 1", + "X c #808080", + "x c #C0C0C0", + ". c #FFFFFF", + "XXXxxxxx........" +}; + +#ifdef USE_GL /* whole file */ + +#define DEF_SPEED "1.0" +#define DEF_SMOOTH "True" +#define DEF_TEXTURE "True" +#define DEF_CEL "False" +#define DEF_INTERSECT "False" +#define DEF_SLICES "16" +#define DEF_SEGMENTS "24" +#define DEF_WIGGLINESS "0.35" +#define DEF_FLEXIBILITY "0.35" +#define DEF_THICKNESS "1.0" +#define DEF_LENGTH "9.0" +#define DEF_COLOR "#305A30" +#define DEF_STRIPE "#451A30" +#define DEF_SUCKER "#453E30" +#define DEF_DEBUG "False" + +#define BELLRAND(n) ((frand((n)) + frand((n)) + frand((n))) / 3) + +typedef struct { + GLfloat length; /* length of the segment coming out of this segment */ + GLfloat th; /* vector tilt (on yz plane) from previous segment */ + GLfloat phi; /* vector rotation (on xy plane) from previous segment */ + GLfloat thickness; /* radius of tentacle at the bottom of this segment */ + rotator *rot; /* motion modeller */ +} segment; + +typedef struct { + ModeInfo *mi; + GLfloat x, y, z; /* position of the base */ + int nsegments; + segment *segments; + GLfloat tentacle_color[4], stripe_color[4], sucker_color[4]; +} tentacle; + +typedef struct { + GLXContext *glx_context; + trackball_state *trackball; + Bool button_down_p; + + int ntentacles; + int tentacles_size; + tentacle **tentacles; + GLfloat tentacle_color[4], stripe_color[4], sucker_color[4]; + + int torus_polys; + int torus_step; + XYZ *torus_points; + XYZ *torus_normals; + + GLfloat line_thickness; + GLfloat outline_color[4]; + XImage *texture; + GLuint texid; + + Bool left_p; + + +} tentacles_configuration; + +static tentacles_configuration *tcs = NULL; + +static int debug_p; +static GLfloat arg_speed; +static int smooth_p; +static int texture_p; +static int cel_p; +static int intersect_p; +static int arg_slices; +static int arg_segments; +static GLfloat arg_thickness; +static GLfloat arg_length; +static GLfloat arg_wiggliness; +static GLfloat arg_flexibility; +static char *arg_color, *arg_stripe, *arg_sucker; + +/* we can only have one light when doing cel shading */ +static GLfloat light_pos[4] = {1.0, 1.0, 1.0, 0.0}; + + +static XrmOptionDescRec opts[] = { + { "-speed", ".speed", XrmoptionSepArg, 0 }, + { "-no-smooth", ".smooth", XrmoptionNoArg, "False" }, + { "-texture", ".texture", XrmoptionNoArg, "True" }, + { "-no-texture", ".texture", XrmoptionNoArg, "False" }, + { "-cel", ".cel", XrmoptionNoArg, "True" }, + { "-no-cel", ".cel", XrmoptionNoArg, "False" }, + { "-intersect", ".intersect", XrmoptionNoArg, "True" }, + { "-no-intersect", ".intersect", XrmoptionNoArg, "False" }, + { "-slices", ".slices", XrmoptionSepArg, 0 }, + { "-segments", ".segments", XrmoptionSepArg, 0 }, + { "-thickness", ".thickness", XrmoptionSepArg, 0 }, + { "-length", ".length", XrmoptionSepArg, 0 }, + { "-wiggliness", ".wiggliness", XrmoptionSepArg, 0 }, + { "-flexibility", ".flexibility", XrmoptionSepArg, 0 }, + { "-color", ".tentacleColor", XrmoptionSepArg, 0 }, + { "-stripe-color", ".stripeColor", XrmoptionSepArg, 0 }, + { "-sucker-color", ".suckerColor", XrmoptionSepArg, 0 }, + { "-debug", ".debug", XrmoptionNoArg, "True" }, +}; + +static argtype vars[] = { + {&arg_speed, "speed", "Speed", DEF_SPEED, t_Float}, + {&smooth_p, "smooth", "Smooth", DEF_SMOOTH, t_Bool}, + {&texture_p, "texture", "Texture", DEF_TEXTURE, t_Bool}, + {&cel_p, "cel", "Cel", DEF_CEL, t_Bool}, + {&intersect_p, "intersect", "Intersect", DEF_INTERSECT, t_Bool}, + {&arg_slices, "slices", "Slices", DEF_SLICES, t_Int}, + {&arg_segments, "segments", "Segments", DEF_SEGMENTS, t_Int}, + {&arg_thickness, "thickness", "Thickness", DEF_THICKNESS, t_Float}, + {&arg_length, "length", "Length", DEF_LENGTH, t_Float}, + {&arg_wiggliness, "wiggliness", "Wiggliness", DEF_WIGGLINESS, t_Float}, + {&arg_flexibility, "flexibility", "Flexibility", DEF_FLEXIBILITY, t_Float}, + {&arg_color, "tentacleColor", "Color", DEF_COLOR, t_String}, + {&arg_stripe, "stripeColor", "Color", DEF_STRIPE, t_String}, + {&arg_sucker, "suckerColor", "Color", DEF_SUCKER, t_String}, + {&debug_p, "debug", "Debug", DEF_DEBUG, t_Bool}, +}; + +ENTRYPOINT ModeSpecOpt tentacles_opts = {countof(opts), opts, countof(vars), vars, NULL}; + + +/* Window management, etc + */ +ENTRYPOINT void +reshape_tentacles (ModeInfo *mi, int width, int height) +{ + tentacles_configuration *tc = &tcs[MI_SCREEN(mi)]; + GLfloat h = (GLfloat) height / (GLfloat) width; + + glViewport (0, 0, (GLint) width, (GLint) height); + + glMatrixMode(GL_PROJECTION); + glLoadIdentity(); + gluPerspective (30.0, 1/h, 1.0, 100.0); + + glMatrixMode(GL_MODELVIEW); + glLoadIdentity(); + gluLookAt( 0.0, 0.0, 30.0, + 0.0, 0.0, 0.0, + 0.0, 1.0, 0.0); + + glClear(GL_COLOR_BUFFER_BIT); + + tc->line_thickness = (MI_IS_WIREFRAME (mi) ? 1 : MAX (3, width / 200)); +} + + +static void +normalize (GLfloat *x, GLfloat *y, GLfloat *z) +{ + GLfloat d = sqrt((*x)*(*x) + (*y)*(*y) + (*z)*(*z)); + *x /= d; + *y /= d; + *z /= d; +} + +static GLfloat +dot (GLfloat x0, GLfloat y0, GLfloat z0, + GLfloat x1, GLfloat y1, GLfloat z1) +{ + return x0*x1 + y0*y1 + z0*z1; +} + + +static void +compute_unit_torus (ModeInfo *mi, double ratio, int slices1, int slices2) +{ + tentacles_configuration *tc = &tcs[MI_SCREEN(mi)]; + Bool wire = MI_IS_WIREFRAME (mi); + int i, j, k, fp; + + if (wire) slices1 /= 2; + if (wire) slices2 /= 4; + if (slices1 < 3) slices1 = 3; + if (slices2 < 3) slices2 = 3; + + tc->torus_polys = slices1 * (slices2+1) * 2; + tc->torus_points = (XYZ *) calloc (tc->torus_polys + 1, + sizeof (*tc->torus_points)); + tc->torus_normals = (XYZ *) calloc (tc->torus_polys + 1, + sizeof (*tc->torus_normals)); + tc->torus_step = 2 * (slices2+1); + fp = 0; + for (i = 0; i < slices1; i++) + for (j = 0; j <= slices2; j++) + for (k = 0; k <= 1; k++) + { + double s = (i + k) % slices1 + 0.5; + double t = j % slices2; + XYZ p; + p.x = cos(t*M_PI*2/slices2) * cos(s*M_PI*2/slices1); + p.y = sin(t*M_PI*2/slices2) * cos(s*M_PI*2/slices1); + p.z = sin(s*M_PI*2/slices1); + tc->torus_normals[fp] = p; + + p.x = (1 + ratio * cos(s*M_PI*2/slices1)) * cos(t*M_PI*2/slices2) / 2; + p.y = (1 + ratio * cos(s*M_PI*2/slices1)) * sin(t*M_PI*2/slices2) / 2; + p.z = ratio * sin(s*M_PI*2/slices1) / 2; + tc->torus_points[fp] = p; + fp++; + } + if (fp != tc->torus_polys) abort(); + tc->torus_polys = fp; +} + + +/* Initializes a new tentacle and stores it in the list. + */ +static tentacle * +make_tentacle (ModeInfo *mi, int which, int total) +{ + tentacles_configuration *tc = &tcs[MI_SCREEN(mi)]; + tentacle *t = (tentacle *) calloc (1, sizeof (*t)); + double brightness; + int i; + + t->mi = mi; + + /* position tentacles on a grid */ + { + int cols = (int) (sqrt(total) + 0.5); + int rows = (total+cols-1) / cols; + int xx = which % cols; + int yy = which / cols; + double spc = arg_thickness * 0.8; + if (!intersect_p) cols = 1, xx = 0; + t->x = (cols * spc / 2) - (spc * (xx + 0.5)); + t->y = (rows * spc / 2) - (spc * (yy + 0.5)); + t->z = 0; + } + + /* Brighten or darken the colors of this tentacle from the default. + */ + brightness = 0.6 + frand(3.0); + memcpy (t->tentacle_color, tc->tentacle_color, 4 * sizeof(*t->tentacle_color)); + memcpy (t->stripe_color, tc->stripe_color, 4 * sizeof(*t->stripe_color)); + memcpy (t->sucker_color, tc->sucker_color, 4 * sizeof(*t->sucker_color)); +# define FROB(X) \ + t->X[0] *= brightness; if (t->X[0] > 1) t->X[0] = 1; \ + t->X[1] *= brightness; if (t->X[1] > 1) t->X[1] = 1; \ + t->X[2] *= brightness; if (t->X[2] > 1) t->X[2] = 1 + FROB (tentacle_color); + FROB (stripe_color); + FROB (sucker_color); +# undef FROB + + t->nsegments = (arg_segments) + BELLRAND(arg_segments); + + t->segments = (segment *) calloc (t->nsegments+1, sizeof(*t->segments)); + for (i = 0; i < t->nsegments; i++) + { + double spin_speed = 0; + double spin_accel = 0; + double wander_speed = arg_speed * (0.02 + BELLRAND(0.1)); + t->segments[i].rot = make_rotator (spin_speed, spin_speed, spin_speed, + spin_accel, wander_speed, True); + } + + t->segments[0].thickness = (((arg_thickness * 0.5) + + BELLRAND(arg_thickness * 0.6)) + / 1.0); + + if (tc->tentacles_size <= tc->ntentacles) + { + tc->tentacles_size = (tc->tentacles_size * 1.2) + tc->ntentacles + 2; + tc->tentacles = (tentacle **) + realloc (tc->tentacles, tc->tentacles_size * sizeof(*tc->tentacles)); + if (! tc->tentacles) + { + fprintf (stderr, "%s: out of memory (%d tentacles)\n", + progname, tc->tentacles_size); + exit (1); + } + } + + tc->tentacles[tc->ntentacles++] = t; + return t; +} + + +static void +draw_sucker (tentacle *t, Bool front_p) +{ + tentacles_configuration *tc = &tcs[MI_SCREEN(t->mi)]; + Bool wire = MI_IS_WIREFRAME (t->mi); + int i, j; + int strips = tc->torus_polys / tc->torus_step; + int points = 0; + + glFrontFace (front_p ? GL_CW : GL_CCW); + for (i = 0; i < strips; i++) + { + int ii = i * tc->torus_step; + + /* Leave off the polygons on the underside. This reduces polygon + count by about 10% with the default settings. */ + if (strips > 4 && i >= strips/2 && i < strips-1) + continue; + + glBegin (wire ? GL_LINE_STRIP : GL_QUAD_STRIP); + for (j = 0; j < tc->torus_step; j++) + { + XYZ sp = tc->torus_points[ii+j]; + XYZ sn = tc->torus_normals[ii+j]; + glNormal3f(sn.x, sn.y, sn.z); + glVertex3f(sp.x, sp.y, sp.z); + points++; + } + glEnd(); + } + t->mi->polygon_count += points/2; +} + + +static void +draw_tentacle (tentacle *t, Bool front_p) +{ + tentacles_configuration *tc = &tcs[MI_SCREEN(t->mi)]; + int i; + Bool wire = MI_IS_WIREFRAME (t->mi); + XYZ ctr = { 0,0,0 }; /* current position of base of segment */ + double cth = 0; /* overall orientation of current segment */ + double cphi = 0; + double cth_cos = 1, cth_sin = 0; + double cphi_cos = 1, cphi_sin = 0; + + GLfloat light[3]; /* vector to the light */ + + GLfloat t0 = 0.0; /* texture coordinate */ + + XYZ *ring, *oring; /* points around the edge (this, and previous) */ + XYZ *norm, *onorm; /* their normals */ + XYZ *ucirc; /* unit circle, to save some trig */ + + /* Which portion of the radius the indented/colored stripe takes up */ + int indented_points = arg_slices * 0.2; + + /* We do rotation this way to minimize the number of calls to sin/cos. + We have to hack the transformations manually instead of using + glRotate/glTranslate because those calls are not allowed *inside* + of a glBegin/glEnd block... + */ +# define ROT(P) do { \ + XYZ _p = P; \ + _p.y = ((P.y * cth_sin - P.x * cth_cos)); \ + _p.x = ((P.y * cth_cos + P.x * cth_sin) * cphi_sin - (P.z * cphi_cos)); \ + _p.z = ((P.y * cth_cos + P.x * cth_sin) * cphi_cos + (P.z * cphi_sin)); \ + P = _p; \ + } while(0) + + ring = (XYZ *) malloc (arg_slices * sizeof(*ring)); + norm = (XYZ *) malloc (arg_slices * sizeof(*norm)); + oring = (XYZ *) malloc (arg_slices * sizeof(*oring)); + onorm = (XYZ *) malloc (arg_slices * sizeof(*onorm)); + ucirc = (XYZ *) malloc (arg_slices * sizeof(*ucirc)); + + light[0] = light_pos[0]; + light[1] = light_pos[1]; + light[2] = light_pos[2]; + normalize (&light[0], &light[1], &light[2]); + + for (i = 0; i < arg_slices; i++) + { + double a = M_PI * 2 * i / arg_slices; + ucirc[i].x = cos(a); + ucirc[i].y = sin(a); + ucirc[i].z = 0; + } + + + if (cel_p) + glPolygonMode (GL_FRONT_AND_BACK, (front_p ? GL_FILL : GL_LINE)); + + glPushMatrix(); + glTranslatef (t->x, t->y, t->z); + + if (debug_p) + { + glPushAttrib (GL_ENABLE_BIT); + glDisable (GL_LIGHTING); + glDisable (GL_TEXTURE_1D); + glDisable (GL_TEXTURE_2D); + glColor3f (1, 1, 1); + glLineWidth (1); + glBegin(GL_LINE_LOOP); + for (i = 0; i < arg_slices; i++) + glVertex3f (arg_thickness / 2 * cos (M_PI * 2 * i / arg_slices), + arg_thickness / 2 * sin (M_PI * 2 * i / arg_slices), + 0); + glEnd(); + glPopAttrib(); + } + + if (!front_p) + glColor4fv (tc->outline_color); + else if (wire) + glColor4fv (t->tentacle_color); + else + { + static const GLfloat bspec[4] = {1.0, 1.0, 1.0, 1.0}; + static const GLfloat bshiny = 128.0; + glMaterialfv (GL_FRONT, GL_SPECULAR, bspec); + glMateriali (GL_FRONT, GL_SHININESS, bshiny); + } + + for (i = 0; i < t->nsegments; i++) + { + int j; + GLfloat t1 = t0 + i / (t->nsegments * M_PI * 2); + + for (j = 0; j < arg_slices; j++) + { + /* Construct a vertical disc at the origin, to use as the + base of this segment. + */ + double r = t->segments[i].thickness / 2; + + if (j <= indented_points/2 || j >= arg_slices-indented_points/2) + r *= 0.75; /* indent the stripe */ + + ring[j].x = r * ucirc[j].x; + ring[j].y = 0; + ring[j].z = r * ucirc[j].y; + + /* Then rotate the points by the angle of the current segment. */ + ROT(ring[j]); + + /* Then move the ring to the base of this segment. */ + ring[j].x += ctr.x; + ring[j].y += ctr.y; + ring[j].z += ctr.z; + } + + + /* Compute the normals of the faces on this segment. We do this + first so that the normals of the vertexes can be the average + of the normals of the faces. + #### Uh, except I didn't actually implement that... + but it would be a good idea. + */ + if (i > 0) + for (j = 0; j <= arg_slices; j++) + { + int j0 = j % arg_slices; + int j1 = (j+1) % arg_slices; + norm[j0] = calc_normal (oring[j0], ring[j0], ring[j1]); + } + + /* Draw! + */ + if (i > 0) + { + int j; + glLineWidth (tc->line_thickness); + glFrontFace (front_p ? GL_CCW : GL_CW); + glBegin (wire ? GL_LINES : smooth_p ? GL_QUAD_STRIP : GL_QUADS); + for (j = 0; j <= arg_slices; j++) + { + int j0 = j % arg_slices; + int j1 = (j+1) % arg_slices; + + GLfloat ts = j / (double) arg_slices; + + if (!front_p) + glColor4fv (tc->outline_color); + else if (j <= indented_points/2 || + j >= arg_slices-indented_points/2) + { + glColor4fv (t->stripe_color); + glMaterialfv (GL_FRONT, GL_AMBIENT_AND_DIFFUSE, + t->stripe_color); + } + else + { + glColor4fv (t->tentacle_color); + glMaterialfv (GL_FRONT, GL_AMBIENT_AND_DIFFUSE, + t->tentacle_color); + } + + /* For cel shading, the 1d texture coordinate (s) is the + dot product of the lighting vector and the vertex normal. + */ + if (cel_p) + { + t0 = dot (light[0], light[1], light[2], + onorm[j0].x, onorm[j0].y, onorm[j0].z); + t1 = dot (light[0], light[1], light[2], + norm[j0].x, norm[j0].y, norm[j0].z); + if (t0 < 0) t0 = 0; + if (t1 < 0) t1 = 0; + } + + glTexCoord2f (t0, ts); + glNormal3f (onorm[j0].x, onorm[j0].y, onorm[j0].z); + glVertex3f (oring[j0].x, oring[j0].y, oring[j0].z); + + glTexCoord2f (t1, ts); + glNormal3f ( norm[j0].x, norm[j0].y, norm[j0].z); + glVertex3f ( ring[j0].x, ring[j0].y, ring[j0].z); + + if (!smooth_p) + { + ts = j1 / (double) arg_slices; + glTexCoord2f (t1, ts); + glVertex3f ( ring[j1].x, ring[j1].y, ring[j1].z); + glTexCoord2f (t0, ts); + glVertex3f (oring[j1].x, oring[j1].y, oring[j1].z); + } + t->mi->polygon_count++; + } + glEnd (); + + if (wire) + { + glBegin (GL_LINE_LOOP); + for (j = 0; j < arg_slices; j++) + glVertex3f (ring[j].x, ring[j].y, ring[j].z); + glEnd(); + } + + /* Now draw the suckers! + */ + { + double seg_length = arg_length / t->nsegments; + double sucker_size = arg_thickness / 5; + double sucker_spacing = sucker_size * 1.3; + int nsuckers = seg_length / sucker_spacing; + double oth = cth - t->segments[i-1].th; + double ophi = cphi - t->segments[i-1].phi; + int k; + + if (!wire) + glLineWidth (MAX (2, tc->line_thickness / 2.0)); + glDisable (GL_TEXTURE_2D); + + /* Sometimes we have N suckers on one segment; + sometimes we have one sucker every N segments. */ + if (nsuckers == 0) + { + int segs_per_sucker = + (int) ((sucker_spacing / seg_length) + 0.5); + nsuckers = (i % segs_per_sucker) ? 0 : 1; + } + + if (front_p) + { + glColor4fv (t->sucker_color); + glMaterialfv (GL_FRONT, GL_AMBIENT_AND_DIFFUSE, + t->sucker_color); + } + + for (k = 0; k < nsuckers; k++) + { + double scale; + XYZ p0 = ring[0]; + XYZ p1 = oring[0]; + XYZ p; + p.x = p0.x + (p1.x - p0.x) * (k + 0.5) / nsuckers; + p.y = p0.y + (p1.y - p0.y) * (k + 0.5) / nsuckers; + p.z = p0.z + (p1.z - p0.z) * (k + 0.5) / nsuckers; + + glPushMatrix(); + glTranslatef (p.x, p.y, p.z); + glRotatef (ophi * 180 / M_PI, 0, 1, 0); + glRotatef (-oth * 180 / M_PI, 1, 0, 0); + glRotatef (90, 1, 0, 0); + + { /* Not quite right: this is the slope of the outer edge + if the next segment was not tilted at all... If there + is any tilt, then the angle of this wall and the + opposite wall are very different. + */ + double slope = ((t->segments[i-1].thickness - + t->segments[i].thickness) / + t->segments[i].length); + glRotatef (-45 * slope, 1, 0, 0); + } + + scale = t->segments[i].thickness / arg_thickness; + scale *= 0.7 * sucker_size; + glScalef (scale, scale, scale * 4); + + glTranslatef (0, 0, -0.1); /* embed */ + + glTranslatef (1, 0, 0); /* left */ + draw_sucker (t, front_p); + + glTranslatef (-2, 0, 0); /* right */ + draw_sucker (t, front_p); + + glPopMatrix(); + } + + if (texture_p) glEnable (GL_TEXTURE_2D); + } + } + + /* Now draw the end caps. + */ + glLineWidth (tc->line_thickness); + if (i == 0 || i == t->nsegments-1) + { + int j; + GLfloat ctrz = ctr.z + ((i == 0 ? -1 : 1) * + t->segments[i].thickness / 4); + if (front_p) + { + glColor4fv (t->tentacle_color); + glMaterialfv (GL_FRONT, GL_AMBIENT_AND_DIFFUSE, + t->tentacle_color); + } + glFrontFace ((front_p ? i == 0 : i != 0) ? GL_CCW : GL_CW); + glBegin (wire ? GL_LINES : GL_TRIANGLE_FAN); + glNormal3f (0, 0, (i == 0 ? -1 : 1)); + glTexCoord2f (t0 - 0.25, 0.5); + glVertex3f (ctr.x, ctr.y, ctrz); + for (j = 0; j <= arg_slices; j++) + { + int jj = j % arg_slices; + GLfloat ts = j / (double) arg_slices; + glTexCoord2f (t0, ts); + glNormal3f (norm[jj].x, norm[jj].y, norm[jj].z); + glVertex3f (ring[jj].x, ring[jj].y, ring[jj].z); + if (wire) glVertex3f (ctr.x, ctr.y, ctrz); + t->mi->polygon_count++; + } + glEnd(); + } + + /* Now move to the end of this segment in preparation for the next. + */ + if (i != t->nsegments-1) + { + XYZ p; + p.x = 0; + p.y = t->segments[i].length; + p.z = 0; + ROT (p); + ctr.x += p.x; + ctr.y += p.y; + ctr.z += p.z; + + /* Accumulate the current angle and rotation, to keep track of the + rotation of the upcoming segment. + */ + cth += t->segments[i].th; + cphi += t->segments[i].phi; + + cth_sin = sin (cth); + cth_cos = cos (cth); + cphi_sin = sin (cphi); + cphi_cos = cos (cphi); + + memcpy (oring, ring, arg_slices * sizeof(*ring)); + memcpy (onorm, norm, arg_slices * sizeof(*norm)); + } + + t0 = t1; + } + + glPopMatrix(); + + free (ring); + free (norm); + free (oring); + free (onorm); + free (ucirc); +} + + +static void +move_tentacle (tentacle *t) +{ + /* tentacles_configuration *tc = &tcs[MI_SCREEN(t->mi)]; */ + GLfloat len = 0; + double pos = 0; + int i, j; + int skip = t->nsegments * (1 - (arg_wiggliness + 0.5)); + int tick = 0; + int last = 0; + + for (i = 0; i < t->nsegments; i++) + { + if (++tick >= skip || i == t->nsegments-1) + { + /* randomize the motion of this segment... */ + double x, y, z; + double phi_range = M_PI * 0.8 * arg_flexibility; + double th_range = M_PI * 0.9 * arg_flexibility; + get_position (t->segments[i].rot, &x, &y, &z, True); + t->segments[i].phi = phi_range * (0.5 - y); + t->segments[i].th = th_range * (0.5 - z); + t->segments[i].length = ((0.8 + ((0.5 - x) * 0.4)) * + (arg_length / t->nsegments)); + + /* ...and make the previous N segments be interpolated + between this one and the previous randomized one. */ + for (j = last+1; j <= i; j++) + { + t->segments[j].phi = (t->segments[i].phi / (i - last)); + t->segments[j].th = (t->segments[i].th / (i - last)); + t->segments[j].length = (t->segments[i].length); + } + + tick = 0; + last = i; + } + len += t->segments[i].length; + } + + /* thickness of segment is relative to current position on tentacle + (not just the index of the segment). */ + for (i = 0; i < t->nsegments; i++) + { + if (i > 0) + { + double tt = (t->segments[0].thickness * (len - pos) / len); + if (tt < 0.001) tt = 0.001; + t->segments[i].thickness = tt; + } + pos += t->segments[i].length; + } +} + + + +ENTRYPOINT Bool +tentacles_handle_event (ModeInfo *mi, XEvent *event) +{ + tentacles_configuration *tc = &tcs[MI_SCREEN(mi)]; + + if (event->xany.type == ButtonPress && + event->xbutton.button == Button1) + { + tc->button_down_p = True; + gltrackball_start (tc->trackball, + event->xbutton.x, event->xbutton.y, + MI_WIDTH (mi), MI_HEIGHT (mi)); + return True; + } + else if (event->xany.type == ButtonRelease && + event->xbutton.button == Button1) + { + tc->button_down_p = False; + return True; + } + else if (event->xany.type == ButtonPress && + (event->xbutton.button == Button4 || + event->xbutton.button == Button5 || + event->xbutton.button == Button6 || + event->xbutton.button == Button7)) + { + gltrackball_mousewheel (tc->trackball, event->xbutton.button, 10, + !!event->xbutton.state); + return True; + } + else if (event->xany.type == MotionNotify && + tc->button_down_p) + { + gltrackball_track (tc->trackball, + event->xmotion.x, event->xmotion.y, + MI_WIDTH (mi), MI_HEIGHT (mi)); + return True; + } + else if (event->xany.type == KeyPress) + { + KeySym keysym; + char c = 0; + XLookupString (&event->xkey, &c, 1, &keysym, 0); + if (c == ' ') + { + gltrackball_reset (tc->trackball); + return True; + } + } + + return False; +} + + +static void +parse_color (ModeInfo *mi, const char *name, const char *s, GLfloat *a) +{ + XColor c; + a[3] = 1.0; /* alpha */ + + if (! XParseColor (MI_DISPLAY(mi), MI_COLORMAP(mi), s, &c)) + { + fprintf (stderr, "%s: can't parse %s color %s", progname, name, s); + exit (1); + } + a[0] = c.red / 65536.0; + a[1] = c.green / 65536.0; + a[2] = c.blue / 65536.0; +} + + +ENTRYPOINT void +init_tentacles (ModeInfo *mi) +{ + tentacles_configuration *tc; + int wire = MI_IS_WIREFRAME(mi); + int i; + + if (!tcs) { + tcs = (tentacles_configuration *) + calloc (MI_NUM_SCREENS(mi), sizeof (tentacles_configuration)); + if (!tcs) { + fprintf(stderr, "%s: out of memory\n", progname); + exit(1); + } + } + + tc = &tcs[MI_SCREEN(mi)]; + + tc->glx_context = init_GL(mi); + + reshape_tentacles (mi, MI_WIDTH(mi), MI_HEIGHT(mi)); + + if (!wire) + { + GLfloat amb[4] = {0.0, 0.0, 0.0, 1.0}; + GLfloat dif[4] = {1.0, 1.0, 1.0, 1.0}; + GLfloat spc[4] = {0.0, 1.0, 1.0, 1.0}; + glLightfv(GL_LIGHT0, GL_POSITION, light_pos); + glLightfv(GL_LIGHT0, GL_AMBIENT, amb); + glLightfv(GL_LIGHT0, GL_DIFFUSE, dif); + glLightfv(GL_LIGHT0, GL_SPECULAR, spc); + } + + if (!wire && !cel_p) + { + glEnable (GL_LIGHTING); + glEnable (GL_LIGHT0); + } + + tc->trackball = gltrackball_init (); + + tc->left_p = !(random() % 5); + + if (arg_segments < 2) arg_segments = 2; + if (arg_slices < 3) arg_slices = 3; + if (arg_thickness < 0.1) arg_thickness = 0.1; + if (arg_wiggliness < 0) arg_wiggliness = 0; + if (arg_wiggliness > 1) arg_wiggliness = 1; + if (arg_flexibility < 0) arg_flexibility = 0; + if (arg_flexibility > 1) arg_flexibility = 1; + + parse_color (mi, "tentacleColor", arg_color, tc->tentacle_color); + parse_color (mi, "stripeColor", arg_stripe, tc->stripe_color); + parse_color (mi, "suckerColor", arg_sucker, tc->sucker_color); + + /* Black outlines for light colors, white outlines for dark colors. */ + if (tc->tentacle_color[0] + tc->tentacle_color[1] + tc->tentacle_color[2] + < 0.4) + tc->outline_color[0] = 1; + tc->outline_color[1] = tc->outline_color[0]; + tc->outline_color[2] = tc->outline_color[0]; + tc->outline_color[3] = 1; + + for (i = 0; i < MI_COUNT(mi); i++) + move_tentacle (make_tentacle (mi, i, MI_COUNT(mi))); + +# ifdef HAVE_JWZGLES /* #### glPolygonMode other than GL_FILL unimplemented */ + cel_p = 0; +# endif + + if (wire) texture_p = cel_p = False; + if (cel_p) texture_p = False; + + if (texture_p || cel_p) { + glGenTextures(1, &tc->texid); +# ifdef HAVE_GLBINDTEXTURE + glBindTexture ((cel_p ? GL_TEXTURE_1D : GL_TEXTURE_2D), tc->texid); +# endif + + tc->texture = xpm_to_ximage (MI_DISPLAY(mi), MI_VISUAL(mi), + MI_COLORMAP(mi), + (cel_p ? grey_texture : scales)); + if (!tc->texture) texture_p = cel_p = False; + } + + if (texture_p) { + glPixelStorei (GL_UNPACK_ALIGNMENT, 1); + clear_gl_error(); + glTexImage2D (GL_TEXTURE_2D, 0, GL_RGBA, + tc->texture->width, tc->texture->height, 0, + GL_RGBA, + /* GL_UNSIGNED_BYTE, */ + GL_UNSIGNED_INT_8_8_8_8_REV, + tc->texture->data); + check_gl_error("texture"); + + glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); + glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); + + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + + glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); + + glEnable(GL_TEXTURE_2D); + } else if (cel_p) { + clear_gl_error(); + glTexImage1D (GL_TEXTURE_1D, 0, GL_RGBA, + tc->texture->width, 0, + GL_RGBA, + /* GL_UNSIGNED_BYTE, */ + GL_UNSIGNED_INT_8_8_8_8_REV, + tc->texture->data); + check_gl_error("texture"); + + glTexParameterf(GL_TEXTURE_1D, GL_TEXTURE_WRAP_S, GL_REPEAT); + glTexParameterf(GL_TEXTURE_1D, GL_TEXTURE_WRAP_T, GL_REPEAT); + + glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + + glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); + + glEnable(GL_TEXTURE_1D); + glHint (GL_LINE_SMOOTH_HINT, GL_NICEST); + glEnable (GL_LINE_SMOOTH); + glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + glEnable (GL_BLEND); + + /* Dark gray instead of black, so the outlines show up */ + glClearColor (0.13, 0.13, 0.13, 1.0); + } + + compute_unit_torus (mi, 0.5, + MAX(5, arg_slices/6), + MAX(9, arg_slices/3)); +} + + +ENTRYPOINT void +draw_tentacles (ModeInfo *mi) +{ + tentacles_configuration *tc = &tcs[MI_SCREEN(mi)]; + Display *dpy = MI_DISPLAY(mi); + Window window = MI_WINDOW(mi); + int i; + + if (!tc->glx_context) + return; + + glXMakeCurrent(MI_DISPLAY(mi), MI_WINDOW(mi), *(tc->glx_context)); + + glShadeModel(GL_SMOOTH); + + glEnable(GL_DEPTH_TEST); + glEnable(GL_NORMALIZE); + glEnable(GL_CULL_FACE); + + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + + glPushMatrix (); + glRotatef(current_device_rotation(), 0, 0, 1); + +# if 1 + glScalef (3, 3, 3); +# else + glPushAttrib (GL_ENABLE_BIT); + glPushMatrix(); + { GLfloat s = 8.7/1600; glScalef(s,s,s); } + glTranslatef(-800,-514,0); + glDisable(GL_LIGHTING); + glDisable(GL_TEXTURE_1D); + glDisable(GL_TEXTURE_2D); + glColor3f (1, 1, 1); + glBegin(GL_LINE_LOOP); + glVertex3f(0,0,0); + glVertex3f(0,1028,0); + glVertex3f(1600,1028,0); + glVertex3f(1600,0,0); + glEnd(); + glPopMatrix(); + glPopAttrib(); +# endif + + gltrackball_rotate (tc->trackball); + + mi->polygon_count = 0; + + if (debug_p) + { + glPushAttrib (GL_ENABLE_BIT); + glDisable (GL_LIGHTING); + glDisable (GL_TEXTURE_1D); + glDisable (GL_TEXTURE_2D); + glColor3f (1, 1, 1); + glLineWidth (1); + glBegin(GL_LINES); + glVertex3f(-0.5, 0, 0); glVertex3f(0.5, 0, 0); + glVertex3f(0, -0.5, 0); glVertex3f(0, 0.5, 0); + glEnd(); + glPopAttrib(); + } + else + { + GLfloat rx = 45; + GLfloat ry = -45; + GLfloat rz = 70; + if (tc->left_p) + ry = -ry, rz = -rz; + glRotatef (ry, 0, 1, 0); + glRotatef (rx, 1, 0, 0); + glRotatef (rz, 0, 0, 1); + if (intersect_p) + glTranslatef (0, -2.0, -4.5); + else + glTranslatef (0, -2.5, -5.0); + } + + if (!tc->button_down_p) + for (i = 0; i < tc->ntentacles; i++) + move_tentacle (tc->tentacles[i]); + +#if 1 + for (i = 0; i < tc->ntentacles; i++) + { + if (! intersect_p) + glClear(GL_DEPTH_BUFFER_BIT); + draw_tentacle (tc->tentacles[i], True); + if (cel_p) + draw_tentacle (tc->tentacles[i], False); + } +#else + glScalef (3, 3, 3); + glScalef (1, 1, 4); + glColor3f(1,1,1); + glPolygonMode (GL_FRONT_AND_BACK, GL_FILL); + draw_sucker (tc->tentacles[0], True); + if (cel_p) + { + glPolygonMode (GL_FRONT_AND_BACK, GL_LINE); + glLineWidth (tc->line_thickness); + glColor4fv (tc->outline_color); + draw_sucker (tc->tentacles[0], False); + } +#endif + + glPopMatrix (); + + if (mi->fps_p) do_fps (mi); + glFinish(); + + glXSwapBuffers(dpy, window); +} + +XSCREENSAVER_MODULE_2 ("SkyTentacles", skytentacles, tentacles) + +#endif /* USE_GL */ diff --git a/hacks/glx/skytentacles.man b/hacks/glx/skytentacles.man new file mode 100644 index 00000000..2e5cd16e --- /dev/null +++ b/hacks/glx/skytentacles.man @@ -0,0 +1,102 @@ +.TH XScreenSaver 1 "" "X Version 11" +.SH NAME +skytentacles - 3D tentacles from the sky! +.SH SYNOPSIS +.B skytentacles +[\-display \fIhost:display.screen\fP] +[\-visual \fIvisual\fP] +[\-window] +[\-root] +[\-delay \fIint\fP] +[\-speed \fIratio\fP] +[\-count \fIint\fP] +[\-slices \fIint\fP] +[\-length \fIfloat\fP] +[\-wiggliness \fIratio\fP] +[\-flexibility \fIratio\fP] +[\-color \fIcolor\fP] +[\-stripe\-color \fIcolor\fP] +[\-sucker\-color \fIcolor\fP] +[\-segments \fIint\fP] +[\-thickness \fIratio\fP] +[\-no\-smooth] +[\-fps] +.SH DESCRIPTION +There is a tentacled abomination in the sky. From above you it devours. +.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 \fIint\fP +Delay between frames, in microseconds. Default 30000. +.TP 8 +.B \-speed \fIratio\fP +Less than 1 for slower, greater than 1 for faster. Default 1. +.TP 8 +.B \-count \fIint\fP +How many tentacles. Default 8. +.TP 8 +.B \-thickness \fIratio\fP +Less than 1 for thinner tentacles, greater than 1 for thicker. Default 1. +.TP 8 +.B \-length \fIratio\fP +Length of the tentacles. Default 9. +.TP 8 +.B \-wiggliness \fIratio\fP +A measure of how bendy the tentacles are. Smaller numbers result in +smoother flexing; larger numbers make it "crinkly". Default 0.35. +.TP 8 +.B \-flexibility \fIratio\fP +Another measure of how bendy the tentacles are. Smaller numbers +result in straighter tentacles; larger numbers result in more extreme +curves. Default 0.35. +.TP 8 +.B \-color \fIcolor\fP +.TP 8 +.B \-stripe\-color \fIcolor\fP +.TP 8 +.B \-sucker\-color \fIcolor\fP +The colors of the various parts of the tentacle. Default green +with a redish stripe. +.TP 8 +.B \-slices \fIint\fP +.TP 8 +.B \-segments \fIint\fP +Larger numbers increase number of polygons in the object mesh. +Default 32. +.TP 8 +.B \-no\-smooth +Make the tentacles appear faceted instead of smooth. +.TP 8 +.B \-fps +Display the current frame rate, CPU load, and polygon count. +.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 2008 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/glx/sonar-icmp.c b/hacks/glx/sonar-icmp.c new file mode 100644 index 00000000..936fd8a1 --- /dev/null +++ b/hacks/glx/sonar-icmp.c @@ -0,0 +1,1417 @@ +/* sonar, Copyright (c) 1998-2012 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 + * 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. + * + * This implements the "ping" sensor for sonar. + */ + +#include "screenhackI.h" +#include "sonar.h" +#include "version.h" + +#undef usleep /* conflicts with unistd.h on OSX */ + +#ifdef USE_IPHONE + /* Note: to get this to compile for iPhone, you need to fix Xcode! + The icmp headers exist for the simulator build environment, but + not for the real-device build environment. This appears to + just be an Apple bug, not intentional. + + xc=/Applications/Xcode.app/Contents + for path in /Developer/Platforms/iPhone*?/Developer/SDKs/?* \ + $xc/Developer/Platforms/iPhone*?/Developer/SDKs/?* ; do + for file in \ + /usr/include/netinet/ip.h \ + /usr/include/netinet/in_systm.h \ + /usr/include/netinet/ip_icmp.h \ + /usr/include/netinet/ip_var.h \ + /usr/include/netinet/udp.h + do + ln -s "$file" "$path$file" + done + done + */ +#endif + +#ifndef USE_IPHONE +# define READ_FILES +#endif + +#if defined(HAVE_ICMP) || defined(HAVE_ICMPHDR) +# include +# include +# include +# include +# include +# include +# include +# include +# include +# include +# include +# include +# include +# include +# include +# include +# include +# ifdef HAVE_GETIFADDRS +# include +# endif +#endif /* HAVE_ICMP || HAVE_ICMPHDR */ + +#if defined(HAVE_ICMP) +# define HAVE_PING +# define ICMP icmp +# define ICMP_TYPE(p) (p)->icmp_type +# define ICMP_CODE(p) (p)->icmp_code +# define ICMP_CHECKSUM(p) (p)->icmp_cksum +# define ICMP_ID(p) (p)->icmp_id +# define ICMP_SEQ(p) (p)->icmp_seq +#elif defined(HAVE_ICMPHDR) +# define HAVE_PING +# define ICMP icmphdr +# define ICMP_TYPE(p) (p)->type +# define ICMP_CODE(p) (p)->code +# define ICMP_CHECKSUM(p) (p)->checksum +# define ICMP_ID(p) (p)->un.echo.id +# define ICMP_SEQ(p) (p)->un.echo.sequence +#else +# undef HAVE_PING +#endif + +#ifndef USE_IPHONE +# define LOAD_FILES +#endif + +#ifndef HAVE_PING + +sonar_sensor_data * +init_ping (Display *dpy, char **error_ret, char **desc_ret, + const char *subnet, int timeout, + Bool resolve_p, Bool times_p, Bool debug_p) +{ + if (! (!subnet || !*subnet || !strcmp(subnet, "default"))) + fprintf (stderr, "%s: not compiled with support for pinging hosts.\n", + progname); + return 0; +} + +#else /* HAVE_PING -- whole file */ + + +#if defined(__DECC) || defined(_IP_VHL) + /* This is how you do it on DEC C, and possibly some BSD systems. */ +# define IP_HDRLEN(ip) ((ip)->ip_vhl & 0x0F) +#else + /* This is how you do it on everything else. */ +# define IP_HDRLEN(ip) ((ip)->ip_hl) +#endif + +/* yes, there is only one, even when multiple savers are running in the + same address space - since we can only open this socket before dropping + privs. + */ +static int global_icmpsock = 0; + +/* Set by a signal handler. */ +static int timer_expired; + + + +static u_short checksum(u_short *, int); +static long delta(struct timeval *, struct timeval *); + + +typedef struct { + char *version; /* short version number of xscreensaver */ + int icmpsock; /* socket for sending pings */ + int pid; /* our process ID */ + int seq; /* packet sequence number */ + int timeout; /* packet timeout */ + + int target_count; + sonar_bogie *targets; /* the hosts we will ping; + those that pong end up on ssd->pending. */ + sonar_bogie *last_pinged; /* pointer into 'targets' list */ + double last_ping_time; + + Bool resolve_p; + Bool times_p; + Bool debug_p; + +} ping_data; + +typedef struct { + struct sockaddr address; /* ip address */ +} ping_bogie; + + + +/* Packs an IP address quad into bigendian network order. */ +static unsigned long +pack_addr (unsigned int a, unsigned int b, unsigned int c, unsigned int d) +{ + unsigned long i = (((a & 255) << 24) | + ((b & 255) << 16) | + ((c & 255) << 8) | + ((d & 255) )); + return htonl (i); +} + +/* Unpacks an IP address quad from bigendian network order. */ +static void +unpack_addr (unsigned long addr, + unsigned int *a, unsigned int *b, + unsigned int *c, unsigned int *d) +{ + addr = ntohl (addr); + *a = (addr >> 24) & 255; + *b = (addr >> 16) & 255; + *c = (addr >> 8) & 255; + *d = (addr ) & 255; +} + + + + +/* Resolves the bogie's name (either a hostname or ip address string) + to a hostent. Returns 1 if successful, 0 if it failed to resolve. + */ +static int +resolve_bogie_hostname (ping_data *pd, sonar_bogie *sb, Bool resolve_p) +{ + ping_bogie *pb = (ping_bogie *) sb->closure; + struct hostent *hent; + struct sockaddr_in *iaddr; + + unsigned int ip[4]; + char c; + + iaddr = (struct sockaddr_in *) &(pb->address); + iaddr->sin_family = AF_INET; + + if (4 == sscanf (sb->name, " %u.%u.%u.%u %c", + &ip[0], &ip[1], &ip[2], &ip[3], &c)) + { + /* It's an IP address. + */ + if (ip[3] == 0) + { + if (pd->debug_p > 1) + fprintf (stderr, "%s: ignoring bogus IP %s\n", + progname, sb->name); + return 0; + } + + iaddr->sin_addr.s_addr = pack_addr (ip[0], ip[1], ip[2], ip[3]); + if (resolve_p) + hent = gethostbyaddr ((const char *) &iaddr->sin_addr.s_addr, + sizeof(iaddr->sin_addr.s_addr), + AF_INET); + else + hent = 0; + + if (pd->debug_p > 1) + fprintf (stderr, "%s: %s => %s\n", + progname, sb->name, + ((hent && hent->h_name && *hent->h_name) + ? hent->h_name : "")); + + if (hent && hent->h_name && *hent->h_name) + sb->name = strdup (hent->h_name); + } + else + { + /* It's a host name. */ + + /* don't waste time being confused by non-hostname tokens + in .ssh/known_hosts */ + if (!strcmp (sb->name, "ssh-rsa") || + !strcmp (sb->name, "ssh-dsa") || + !strcmp (sb->name, "ssh-dss") || + strlen (sb->name) >= 80) + return 0; + + /* .ssh/known_hosts sometimes contains weirdness like "[host]:port". + Ignore it. */ + if (strchr (sb->name, '[')) + { + if (pd->debug_p) + fprintf (stderr, "%s: ignoring bogus address \"%s\"\n", + progname, sb->name); + return 0; + } + + /* If the name contains a colon, it's probably IPv6. */ + if (strchr (sb->name, ':')) + { + if (pd->debug_p) + fprintf (stderr, "%s: ignoring ipv6 address \"%s\"\n", + progname, sb->name); + return 0; + } + + hent = gethostbyname (sb->name); + if (!hent) + { + if (pd->debug_p) + fprintf (stderr, "%s: could not resolve host: %s\n", + progname, sb->name); + return 0; + } + + memcpy (&iaddr->sin_addr, hent->h_addr_list[0], + sizeof(iaddr->sin_addr)); + + if (pd->debug_p > 1) + { + unsigned int a, b, c, d; + unpack_addr (iaddr->sin_addr.s_addr, &a, &b, &c, &d); + fprintf (stderr, "%s: %s => %d.%d.%d.%d\n", + progname, sb->name, a, b, c, d); + } + } + return 1; +} + + +static void +print_host (FILE *out, unsigned long ip, const char *name) +{ + char ips[50]; + unsigned int a, b, c, d; + unpack_addr (ip, &a, &b, &c, &d); /* ip is in network order */ + sprintf (ips, "%u.%u.%u.%u", a, b, c, d); + if (!name || !*name) name = ""; + fprintf (out, "%-16s %s\n", ips, name); +} + + +/* Create a sonar_bogie from a host name or ip address string. + Returns NULL if the name could not be resolved. + */ +static sonar_bogie * +bogie_for_host (sonar_sensor_data *ssd, const char *name, Bool resolve_p) +{ + ping_data *pd = (ping_data *) ssd->closure; + sonar_bogie *b = (sonar_bogie *) calloc (1, sizeof(*b)); + ping_bogie *pb = (ping_bogie *) calloc (1, sizeof(*pb)); + struct sockaddr_in *iaddr; + unsigned long ip; + + b->name = strdup (name); + b->closure = pb; + + if (! resolve_bogie_hostname (pd, b, resolve_p)) + goto FAIL; + + iaddr = (struct sockaddr_in *) &(pb->address); + + /* Don't ever use loopback (127.0.0.x) hosts */ + ip = iaddr->sin_addr.s_addr; + if ((ntohl (ip) & 0xFFFFFF00L) == 0x7f000000L) /* 127.0.0.x */ + { + if (pd->debug_p) + fprintf (stderr, "%s: ignoring loopback host %s\n", + progname, b->name); + goto FAIL; + } + + /* Don't ever use broadcast (255.x.x.x) hosts */ + if ((ntohl (ip) & 0xFF000000L) == 0xFF000000L) /* 255.x.x.x */ + { + if (pd->debug_p) + fprintf (stderr, "%s: ignoring broadcast host %s\n", + progname, b->name); + goto FAIL; + } + + if (pd->debug_p > 1) + { + fprintf (stderr, "%s: added ", progname); + print_host (stderr, ip, b->name); + } + + return b; + + FAIL: + if (b) sonar_free_bogie (ssd, b); + return 0; +} + + +#ifdef READ_FILES + +/* Return a list of bogies read from a file. + The file can be like /etc/hosts or .ssh/known_hosts or probably + just about anything that has host names in it. + */ +static sonar_bogie * +read_hosts_file (sonar_sensor_data *ssd, const char *filename) +{ + ping_data *pd = (ping_data *) ssd->closure; + FILE *fp; + char buf[LINE_MAX]; + char *p; + sonar_bogie *list = 0; + char *addr, *name; + sonar_bogie *new; + + /* Kludge: on OSX, variables have not been expanded in the command + line arguments, so as a special case, allow the string to begin + with literal "$HOME/" or "~/". + + This is so that the "Known Hosts" menu item in sonar.xml works. + */ + if (!strncmp(filename, "~/", 2) || !strncmp(filename, "$HOME/", 6)) + { + char *s = strchr (filename, '/'); + strcpy (buf, getenv("HOME")); + strcat (buf, s); + filename = buf; + } + + fp = fopen(filename, "r"); + if (!fp) + { + char buf[1024]; + sprintf(buf, "%s: %s", progname, filename); +#ifdef HAVE_COCOA + if (pd->debug_p) /* on OSX don't syslog this */ +#endif + perror (buf); + return 0; + } + + if (pd->debug_p) + fprintf (stderr, "%s: reading \"%s\"\n", progname, filename); + + while ((p = fgets(buf, LINE_MAX, fp))) + { + while ((*p == ' ') || (*p == '\t')) /* skip whitespace */ + p++; + if (*p == '#') /* skip comments */ + continue; + + /* Get the name and address */ + + if ((addr = strtok(buf, " ,;\t\n"))) + name = strtok(0, " ,;\t\n"); + else + continue; + + /* Check to see if the addr looks like an addr. If not, assume + the addr is a name and there is no addr. This way, we can + handle files whose lines have "xx.xx.xx.xx hostname" as their + first two tokens, and also files that have a hostname as their + first token (like .ssh/known_hosts and .rhosts.) + */ + { + int i; char c; + if (4 != sscanf(addr, "%d.%d.%d.%d%c", &i, &i, &i, &i, &c)) + { + name = addr; + addr = 0; + } + } + + /* If the name is all digits, it's not a name. */ + if (name) + { + const char *s; + for (s = name; *s; s++) + if (*s < '0' || *s > '9') + break; + if (! *s) + { + if (pd->debug_p > 1) + fprintf (stderr, "%s: skipping bogus name \"%s\" (%s)\n", + progname, name, addr); + name = 0; + } + } + + /* Create a new target using first the name then the address */ + + new = 0; + if (name) + new = bogie_for_host (ssd, name, pd->resolve_p); + if (!new && addr) + new = bogie_for_host (ssd, addr, pd->resolve_p); + + if (new) + { + new->next = list; + list = new; + } + } + + fclose(fp); + return list; +} +#endif /* READ_FILES */ + + +static sonar_bogie * +delete_duplicate_hosts (sonar_sensor_data *ssd, sonar_bogie *list) +{ + ping_data *pd = (ping_data *) ssd->closure; + sonar_bogie *head = list; + sonar_bogie *sb; + + for (sb = head; sb; sb = sb->next) + { + ping_bogie *pb = (ping_bogie *) sb->closure; + struct sockaddr_in *i1 = (struct sockaddr_in *) &(pb->address); + unsigned long ip1 = i1->sin_addr.s_addr; + + sonar_bogie *sb2; + for (sb2 = sb; sb2; sb2 = sb2->next) + { + if (sb2 && sb2->next) + { + ping_bogie *pb2 = (ping_bogie *) sb2->next->closure; + struct sockaddr_in *i2 = (struct sockaddr_in *) &(pb2->address); + unsigned long ip2 = i2->sin_addr.s_addr; + + if (ip1 == ip2) + { + if (pd->debug_p) + { + fprintf (stderr, "%s: deleted duplicate: ", progname); + print_host (stderr, ip2, sb2->next->name); + } + sb2->next = sb2->next->next; + /* #### sb leaked */ + } + } + } + } + + return head; +} + + +static unsigned int +width_mask (int width) +{ + unsigned int m = 0; + int i; + for (i = 0; i < width; i++) + m |= (1L << (31-i)); + return m; +} + + +#ifdef HAVE_GETIFADDRS +static int +mask_width (unsigned int mask) +{ + int i; + for (i = 0; i < 32; i++) + if (mask & (1 << i)) + break; + return 32-i; +} +#endif + + +/* Generate a list of bogies consisting of all of the entries on + the same subnet. 'base' ip is in network order; 0 means localhost. + */ +static sonar_bogie * +subnet_hosts (sonar_sensor_data *ssd, char **error_ret, char **desc_ret, + unsigned long n_base, int subnet_width) +{ + ping_data *pd = (ping_data *) ssd->closure; + unsigned long h_mask; /* host order */ + unsigned long h_base; /* host order */ + char address[BUFSIZ]; + char *p; + int i; + sonar_bogie *new; + sonar_bogie *list = 0; + char buf[1024]; + + if (subnet_width < 24) + { + sprintf (buf, + "Pinging %lu hosts is a bad\n" + "idea. Please use a subnet\n" + "mask of 24 bits or more.", + (unsigned long) (1L << (32 - subnet_width)) - 1); + *error_ret = strdup(buf); + return 0; + } + else if (subnet_width > 30) + { + sprintf (buf, + "An %d-bit subnet\n" + "doesn't make sense.\n" + "Try \"subnet/24\"\n" + "or \"subnet/29\".\n", + subnet_width); + *error_ret = strdup(buf); + return 0; + } + + + if (pd->debug_p) + fprintf (stderr, "%s: adding %d-bit subnet\n", progname, subnet_width); + + + if (! n_base) + { +# ifdef HAVE_GETIFADDRS + + /* To determine the local subnet, we need to know the local IP address. + Do this by looking at the IPs of every network interface. + */ + struct in_addr in = { 0, }; + struct ifaddrs *all = 0, *ifa; + + if (pd->debug_p) + fprintf (stderr, "%s: listing network interfaces\n", progname); + + getifaddrs (&all); + for (ifa = all; ifa; ifa = ifa->ifa_next) + { + struct in_addr in2; + unsigned long mask; + if (ifa->ifa_addr->sa_family != AF_INET) + { + if (pd->debug_p) + fprintf (stderr, "%s: if: %4s: %s\n", progname, + ifa->ifa_name, + ( +# ifdef AF_UNIX + ifa->ifa_addr->sa_family == AF_UNIX ? "local" : +# endif +# ifdef AF_LINK + ifa->ifa_addr->sa_family == AF_LINK ? "link" : +# endif +# ifdef AF_INET6 + ifa->ifa_addr->sa_family == AF_INET6 ? "ipv6" : +# endif + "other")); + continue; + } + in2 = ((struct sockaddr_in *) ifa->ifa_addr)->sin_addr; + mask = ntohl (((struct sockaddr_in *) ifa->ifa_netmask) + ->sin_addr.s_addr); + if (pd->debug_p) + fprintf (stderr, "%s: if: %4s: inet = %s /%d 0x%08lx\n", + progname, + ifa->ifa_name, + inet_ntoa (in2), + mask_width (mask), + mask); + if (in2.s_addr == 0x0100007f || /* 127.0.0.1 in network order */ + mask == 0) + continue; + + /* At least on the AT&T 3G network, pinging either of the two + hosts on a /31 network doesn't work, so don't try. + */ + if (mask_width (mask) == 31) + { + sprintf (buf, + "Can't ping subnet:\n" + "local network is\n" + "%.100s/%d,\n" + "a p2p bridge\n" + "on if %.100s.", + inet_ntoa (in2), mask_width (mask), ifa->ifa_name); + if (*error_ret) free (*error_ret); + *error_ret = strdup (buf); + continue; + } + + in = in2; + subnet_width = mask_width (mask); + } + + if (in.s_addr) + { + if (*error_ret) free (*error_ret); + *error_ret = 0; + n_base = in.s_addr; /* already in network order, I think? */ + } + else if (!*error_ret) + *error_ret = strdup ("Unable to determine\nlocal IP address\n"); + + if (all) + freeifaddrs (all); + + if (*error_ret) + return 0; + +# else /* !HAVE_GETIFADDRS */ + + /* If we can't walk the list of network interfaces to figure out + our local IP address, try to do it by finding the local host + name, then resolving that. + */ + char hostname[BUFSIZ]; + struct hostent *hent = 0; + + if (gethostname(hostname, BUFSIZ)) + { + *error_ret = strdup ("Unable to determine\n" + "local host name!"); + return 0; + } + + /* Get our IP address and convert it to a string */ + + hent = gethostbyname(hostname); + if (! hent) + { + strcat (hostname, ".local"); /* Necessary on iphone */ + hent = gethostbyname(hostname); + } + + if (! hent) + { + sprintf(buf, + "Unable to resolve\n" + "local host \"%.100s\"", + hostname); + *error_ret = strdup(buf); + return 0; + } + + strcpy (address, inet_ntoa(*((struct in_addr *)hent->h_addr_list[0]))); + n_base = pack_addr (hent->h_addr_list[0][0], + hent->h_addr_list[0][1], + hent->h_addr_list[0][2], + hent->h_addr_list[0][3]); + + if (n_base == 0x0100007f) /* 127.0.0.1 in network order */ + { + unsigned int a, b, c, d; + unpack_addr (n_base, &a, &b, &c, &d); + sprintf (buf, + "Unable to determine\n" + "local subnet address:\n" + "\"%.100s\"\n" + "resolves to\n" + "loopback address\n" + "%u.%u.%u.%u.", + hostname, a, b, c, d); + *error_ret = strdup(buf); + return 0; + } + +# endif /* !HAVE_GETIFADDRS */ + } + + + /* Construct targets for all addresses in this subnet */ + + h_mask = width_mask (subnet_width); + h_base = ntohl (n_base); + + if (desc_ret && !*desc_ret) { + char buf[255]; + unsigned int a, b, c, d; + unsigned long bb = n_base & htonl(h_mask); + unpack_addr (bb, &a, &b, &c, &d); + if (subnet_width > 24) + sprintf (buf, "%u.%u.%u.%u/%d", a, b, c, d, subnet_width); + else + sprintf (buf, "%u.%u.%u/%d", a, b, c, subnet_width); + *desc_ret = strdup (buf); + } + + for (i = 255; i >= 0; i--) { + unsigned int a, b, c, d; + int ip = (h_base & 0xFFFFFF00L) | i; /* host order */ + + if ((ip & h_mask) != (h_base & h_mask)) /* skip out-of-subnet host */ + continue; + else if (subnet_width == 31) /* 1-bit bridge: 2 hosts */ + ; + else if ((ip & ~h_mask) == 0) /* skip network address */ + continue; + else if ((ip & ~h_mask) == ~h_mask) /* skip broadcast address */ + continue; + + unpack_addr (htonl (ip), &a, &b, &c, &d); + sprintf (address, "%u.%u.%u.%u", a, b, c, d); + + if (pd->debug_p > 1) + { + unsigned int aa, ab, ac, ad; + unsigned int ma, mb, mc, md; + unpack_addr (htonl (h_base & h_mask), &aa, &ab, &ac, &ad); + unpack_addr (htonl (h_mask), &ma, &mb, &mc, &md); + fprintf (stderr, + "%s: subnet: %s (%u.%u.%u.%u & %u.%u.%u.%u / %d)\n", + progname, address, + aa, ab, ac, ad, + ma, mb, mc, md, + subnet_width); + } + + p = address + strlen(address) + 1; + sprintf(p, "%d", i); + + new = bogie_for_host (ssd, address, pd->resolve_p); + if (new) + { + new->next = list; + list = new; + } + } + + return list; +} + + +/* Send a ping packet. + */ +static void +send_ping (ping_data *pd, const sonar_bogie *b) +{ + ping_bogie *pb = (ping_bogie *) b->closure; + u_char *packet; + struct ICMP *icmph; + const char *token = "org.jwz.xscreensaver.sonar"; + + int pcktsiz = (sizeof(struct ICMP) + sizeof(struct timeval) + + strlen(b->name) + 1 + + strlen(token) + 1 + + strlen(pd->version) + 1); + + /* Create the ICMP packet */ + + if (! (packet = (u_char *) calloc(1, pcktsiz))) + return; /* Out of memory */ + + icmph = (struct ICMP *) packet; + ICMP_TYPE(icmph) = ICMP_ECHO; + ICMP_CODE(icmph) = 0; + ICMP_CHECKSUM(icmph) = 0; + ICMP_ID(icmph) = pd->pid; + ICMP_SEQ(icmph) = pd->seq++; +# ifdef GETTIMEOFDAY_TWO_ARGS + gettimeofday((struct timeval *) &packet[sizeof(struct ICMP)], + (struct timezone *) 0); +# else + gettimeofday((struct timeval *) &packet[sizeof(struct ICMP)]); +# endif + + /* We store the name of the host we're pinging in the packet, and parse + that out of the return packet later (see get_ping() for why). + After that, we also include the name and version of this program, + just to give a clue to anyone sniffing and wondering what's up. + */ + sprintf ((char *) &packet[sizeof(struct ICMP) + sizeof(struct timeval)], + "%.100s%c%.20s %.20s", + b->name, 0, token, pd->version); + + ICMP_CHECKSUM(icmph) = checksum((u_short *)packet, pcktsiz); + + /* Send it */ + + if (sendto(pd->icmpsock, packet, pcktsiz, 0, + &pb->address, sizeof(pb->address)) + != pcktsiz) + { +#if 0 + char buf[BUFSIZ]; + sprintf(buf, "%s: pinging %.100s", progname, b->name); + perror(buf); +#endif + } +} + +/* signal handler */ +static void +sigcatcher (int sig) +{ + timer_expired = 1; +} + + +/* Compute the checksum on a ping packet. + */ +static u_short +checksum (u_short *packet, int size) +{ + register int nleft = size; + register u_short *w = packet; + register int sum = 0; + u_short answer = 0; + + /* Using a 32 bit accumulator (sum), we add sequential 16 bit words + to it, and at the end, fold back all the carry bits from the + top 16 bits into the lower 16 bits. + */ + while (nleft > 1) + { + sum += *w++; + nleft -= 2; + } + + /* mop up an odd byte, if necessary */ + + if (nleft == 1) + { + *(u_char *)(&answer) = *(u_char *)w ; + *(1 + (u_char *)(&answer)) = 0; + sum += answer; + } + + /* add back carry outs from top 16 bits to low 16 bits */ + + sum = (sum >> 16) + (sum & 0xffff); /* add hi 16 to low 16 */ + sum += (sum >> 16); /* add carry */ + answer = ~sum; /* truncate to 16 bits */ + + return(answer); +} + + +/* Copies the sonar_bogie and the underlying ping_bogie. + */ +static sonar_bogie * +copy_ping_bogie (sonar_sensor_data *ssd, const sonar_bogie *b) +{ + sonar_bogie *b2 = sonar_copy_bogie (ssd, b); + if (b->closure) + { + ping_bogie *pb = (ping_bogie *) b->closure; + ping_bogie *pb2 = (ping_bogie *) calloc (1, sizeof(*pb)); + pb2->address = pb->address; + b2->closure = pb2; + } + return b2; +} + + +/* Look for all outstanding ping replies. + */ +static sonar_bogie * +get_ping (sonar_sensor_data *ssd) +{ + ping_data *pd = (ping_data *) ssd->closure; + struct sockaddr from; + unsigned int fromlen; /* Posix says socklen_t, but that's not portable */ + int result; + u_char packet[1024]; + struct timeval now; + struct timeval *then; + struct ip *ip; + int iphdrlen; + struct ICMP *icmph; + sonar_bogie *bl = 0; + sonar_bogie *new = 0; + struct sigaction sa; + struct itimerval it; + fd_set rfds; + struct timeval tv; + + /* Set up a signal to interrupt our wait for a packet */ + + sigemptyset(&sa.sa_mask); + sa.sa_flags = 0; + sa.sa_handler = sigcatcher; + if (sigaction(SIGALRM, &sa, 0) == -1) + { + char msg[1024]; + sprintf(msg, "%s: unable to trap SIGALRM", progname); + perror(msg); + exit(1); + } + + /* Set up a timer to interupt us if we don't get a packet */ + + it.it_interval.tv_sec = 0; + it.it_interval.tv_usec = 0; + it.it_value.tv_sec = 0; + it.it_value.tv_usec = pd->timeout; + timer_expired = 0; + setitimer(ITIMER_REAL, &it, 0); + + /* Wait for a result packet */ + + fromlen = sizeof(from); + while (! timer_expired) + { + tv.tv_usec = pd->timeout; + tv.tv_sec = 0; +#if 0 + /* This breaks on BSD, which uses bzero() in the definition of FD_ZERO */ + FD_ZERO(&rfds); +#else + memset (&rfds, 0, sizeof(rfds)); +#endif + FD_SET(pd->icmpsock, &rfds); + /* only wait a little while, in case we raced with the timer expiration. + From Valentijn Sessink */ + if (select(pd->icmpsock + 1, &rfds, 0, 0, &tv) >0) + { + result = recvfrom (pd->icmpsock, packet, sizeof(packet), + 0, &from, &fromlen); + + /* Check the packet */ + +# ifdef GETTIMEOFDAY_TWO_ARGS + gettimeofday(&now, (struct timezone *) 0); +# else + gettimeofday(&now); +# endif + ip = (struct ip *) packet; + iphdrlen = IP_HDRLEN(ip) << 2; + icmph = (struct ICMP *) &packet[iphdrlen]; + then = (struct timeval *) &packet[iphdrlen + sizeof(struct ICMP)]; + + + /* Ignore anything but ICMP Replies */ + if (ICMP_TYPE(icmph) != ICMP_ECHOREPLY) + continue; + + /* Ignore packets not set from us */ + if (ICMP_ID(icmph) != pd->pid) + continue; + + /* Find the bogie in 'targets' that corresponds to this packet + and copy it, so that this bogie stays in the same spot (th) + on the screen, and so that we don't have to resolve it again. + + We could find the bogie by comparing ip->ip_src.s_addr to + pb->address, but it is possible that, in certain weird router + or NAT situations, that the reply will come back from a + different address than the one we sent it to. So instead, + we parse the name out of the reply packet payload. + */ + { + const char *name = (char *) &packet[iphdrlen + + sizeof(struct ICMP) + + sizeof(struct timeval)]; + sonar_bogie *b; + + /* Ensure that a maliciously-crafted return packet can't + make us overflow in strcmp. */ + packet[sizeof(packet)-1] = 0; + + for (b = pd->targets; b; b = b->next) + if (!strcmp (name, b->name)) + { + new = copy_ping_bogie (ssd, b); + break; + } + } + + if (! new) /* not in targets? */ + { + unsigned int a, b, c, d; + unpack_addr (ip->ip_src.s_addr, &a, &b, &c, &d); + fprintf (stderr, + "%s: UNEXPECTED PING REPLY! " + "%4d bytes, icmp_seq=%-4d from %d.%d.%d.%d\n", + progname, result, ICMP_SEQ(icmph), a, b, c, d); + continue; + } + + new->next = bl; + bl = new; + + { + double msec = delta(then, &now) / 1000.0; + + if (pd->times_p) + { + if (new->desc) free (new->desc); + new->desc = (char *) malloc (30); + if (msec > 99) sprintf (new->desc, "%.0f ms", msec); + else if (msec > 9) sprintf (new->desc, "%.1f ms", msec); + else if (msec > 1) sprintf (new->desc, "%.2f ms", msec); + else sprintf (new->desc, "%.3f ms", msec); + } + + if (pd->debug_p && pd->times_p) /* ping-like stdout log */ + { + char *s = strdup(new->name); + char *s2 = s; + if (strlen(s) > 28) + { + s2 = s + strlen(s) - 28; + strncpy (s2, "...", 3); + } + fprintf (stdout, + "%3d bytes from %28s: icmp_seq=%-4d time=%s\n", + result, s2, ICMP_SEQ(icmph), new->desc); + fflush (stdout); + free(s); + } + + /* The radius must be between 0.0 and 1.0. + We want to display ping times on a logarithmic scale, + with the three rings being 2.5, 70 and 2,000 milliseconds. + */ + if (msec <= 0) msec = 0.001; + new->r = log (msec * 10) / log (20000); + + /* Don't put anyone *too* close to the center of the screen. */ + if (new->r < 0) new->r = 0; + if (new->r < 0.1) new->r += 0.1; + } + } + } + + return bl; +} + + +/* difference between the two times in microseconds. + */ +static long +delta (struct timeval *then, struct timeval *now) +{ + return (((now->tv_sec - then->tv_sec) * 1000000) + + (now->tv_usec - then->tv_usec)); +} + + +static void +ping_free_data (sonar_sensor_data *ssd, void *closure) +{ + ping_data *pd = (ping_data *) closure; + sonar_bogie *b = pd->targets; + while (b) + { + sonar_bogie *b2 = b->next; + sonar_free_bogie (ssd, b); + b = b2; + } + free (pd); +} + +static void +ping_free_bogie_data (sonar_sensor_data *sd, void *closure) +{ + free (closure); +} + + +/* Returns the current time in seconds as a double. + */ +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)); +} + + +/* Pings the next bogie, if it's time. + Returns all outstanding ping replies. + */ +static sonar_bogie * +ping_scan (sonar_sensor_data *ssd) +{ + ping_data *pd = (ping_data *) ssd->closure; + double now = double_time(); + double ping_cycle = 10; /* re-ping a given host every 10 seconds */ + double ping_interval = ping_cycle / pd->target_count; + + if (now > pd->last_ping_time + ping_interval) /* time to ping someone */ + { + if (pd->last_pinged) + pd->last_pinged = pd->last_pinged->next; + if (! pd->last_pinged) + pd->last_pinged = pd->targets; + send_ping (pd, pd->last_pinged); + pd->last_ping_time = now; + } + + return get_ping (ssd); +} + + +/* Returns a list of hosts to ping based on the "-ping" argument. + */ +static sonar_bogie * +parse_mode (sonar_sensor_data *ssd, char **error_ret, char **desc_ret, + const char *ping_arg, Bool ping_works_p) +{ + ping_data *pd = (ping_data *) ssd->closure; + char *source, *token, *end, dummy; + sonar_bogie *hostlist = 0; + const char *fallback = "subnet"; + + AGAIN: + + if (fallback && (!ping_arg || !*ping_arg || !strcmp (ping_arg, "default"))) + source = strdup(fallback); + else if (ping_arg) + source = strdup(ping_arg); + else + return 0; + + token = source; + end = source + strlen(source); + while (token < end) + { + char *next; + sonar_bogie *new = 0; +# ifdef READ_FILES + struct stat st; +# endif + unsigned int n0=0, n1=0, n2=0, n3=0, m=0; + char d; + + for (next = token; + *next && + *next != ',' && *next != ' ' && *next != '\t' && *next != '\n'; + next++) + ; + *next = 0; + + + if (pd->debug_p) + fprintf (stderr, "%s: parsing %s\n", progname, token); + + if (!ping_works_p) + { + *error_ret = strdup ("Sonar must be setuid to ping!\n" + "Running simulation instead."); + return 0; + } + + if ((4 == sscanf (token, "%u.%u.%u/%u %c", &n0,&n1,&n2, &m,&d)) || + (5 == sscanf (token, "%u.%u.%u.%u/%u %c", &n0,&n1,&n2,&n3,&m,&d))) + { + /* subnet: A.B.C.D/M + subnet: A.B.C/M + */ + unsigned long ip = pack_addr (n0, n1, n2, n3); + new = subnet_hosts (ssd, error_ret, desc_ret, ip, m); + } + else if (4 == sscanf (token, "%u.%u.%u.%u %c", &n0, &n1, &n2, &n3, &d)) + { + /* IP: A.B.C.D + */ + new = bogie_for_host (ssd, token, pd->resolve_p); + } + else if (!strcmp (token, "subnet")) + { + new = subnet_hosts (ssd, error_ret, desc_ret, 0, 24); + } + else if (1 == sscanf (token, "subnet/%u %c", &m, &dummy)) + { + new = subnet_hosts (ssd, error_ret, desc_ret, 0, m); + } + else if (*token == '.' || *token == '/' || + *token == '$' || *token == '~') + { +# ifdef READ_FILES + new = read_hosts_file (ssd, token); +# else + if (pd->debug_p) fprintf (stderr, "%s: skipping file\n", progname); +# endif + } +# ifdef READ_FILES + else if (!stat (token, &st)) + { + new = read_hosts_file (ssd, token); + } +# endif /* READ_FILES */ + else + { + /* not an existant file - must be a host name + */ + new = bogie_for_host (ssd, token, pd->resolve_p); + } + + if (new) + { + sonar_bogie *nn = new; + while (nn->next) + nn = nn->next; + nn->next = hostlist; + hostlist = new; + } + + token = next + 1; + while (token < end && + (*token == ',' || *token == ' ' || + *token == '\t' || *token == '\n')) + token++; + } + + free (source); + + /* If the arg was completely unparsable, fall back to the local subnet. + This happens if the default is "/etc/hosts" but READ_FILES is off. + Or if we're on a /31 network, in which case we try twice then fail. + */ + if (!hostlist && fallback) + { + if (pd->debug_p) + fprintf (stderr, "%s: no hosts parsed! Trying %s\n", + progname, fallback); + ping_arg = fallback; + fallback = 0; + goto AGAIN; + } + + return hostlist; +} + + +sonar_sensor_data * +sonar_init_ping (Display *dpy, char **error_ret, char **desc_ret, + const char *subnet, int timeout, + Bool resolve_p, Bool times_p, Bool debug_p) +{ + sonar_sensor_data *ssd = (sonar_sensor_data *) calloc (1, sizeof(*ssd)); + ping_data *pd = (ping_data *) calloc (1, sizeof(*pd)); + sonar_bogie *b; + char *s; + + Bool socket_initted_p = False; + Bool socket_raw_p = False; + + pd->resolve_p = resolve_p; + pd->times_p = times_p; + pd->debug_p = debug_p; + + ssd->closure = pd; + ssd->scan_cb = ping_scan; + ssd->free_data_cb = ping_free_data; + ssd->free_bogie_cb = ping_free_bogie_data; + + /* Get short version number. */ + s = strchr (screensaver_id, ' '); + pd->version = strdup (s+1); + s = strchr (pd->version, ' '); + *s = 0; + + + /* Create the ICMP socket. Do this before dropping privs. + + Raw sockets can only be opened by root (or setuid root), so we + only try to do this when the effective uid is 0. + + We used to just always try, and notice the failure. But apparently + that causes "SELinux" to log spurious warnings when running with the + "strict" policy. So to avoid that, we just don't try unless we + know it will work. + + On MacOS X, we can avoid the whole problem by using a + non-privileged datagram instead of a raw socket. + */ + if (global_icmpsock) + { + pd->icmpsock = global_icmpsock; + socket_initted_p = True; + if (debug_p) + fprintf (stderr, "%s: re-using icmp socket\n", progname); + + } + else if ((pd->icmpsock = socket(AF_INET, SOCK_DGRAM, IPPROTO_ICMP)) >= 0) + { + socket_initted_p = True; + } + else if (geteuid() == 0 && + (pd->icmpsock = socket(AF_INET, SOCK_RAW, IPPROTO_ICMP)) >= 0) + { + socket_initted_p = True; + socket_raw_p = True; + } + + if (socket_initted_p) + { + global_icmpsock = pd->icmpsock; + socket_initted_p = True; + if (debug_p) + fprintf (stderr, "%s: opened %s icmp socket\n", progname, + (socket_raw_p ? "raw" : "dgram")); + } + else if (debug_p) + fprintf (stderr, "%s: unable to open icmp socket\n", progname); + + /* Disavow privs */ + setuid(getuid()); + + pd->pid = getpid() & 0xFFFF; + pd->seq = 0; + pd->timeout = timeout; + + /* Generate a list of targets */ + + pd->targets = parse_mode (ssd, error_ret, desc_ret, subnet, + socket_initted_p); + pd->targets = delete_duplicate_hosts (ssd, pd->targets); + + if (debug_p) + { + fprintf (stderr, "%s: Target list:\n", progname); + for (b = pd->targets; b; b = b->next) + { + ping_bogie *pb = (ping_bogie *) b->closure; + struct sockaddr_in *iaddr = (struct sockaddr_in *) &(pb->address); + unsigned long ip = iaddr->sin_addr.s_addr; + fprintf (stderr, "%s: ", progname); + print_host (stderr, ip, b->name); + } + } + + /* Make sure there is something to ping */ + + pd->target_count = 0; + for (b = pd->targets; b; b = b->next) + pd->target_count++; + + if (pd->target_count == 0) + { + if (! *error_ret) + *error_ret = strdup ("No hosts to ping!\n" + "Simulating instead."); + if (pd) ping_free_data (ssd, pd); + if (ssd) free (ssd); + return 0; + } + + /* Distribute them evenly around the display field, clockwise. + Even on a /24, allocated IPs tend to cluster together, so + don't put any two hosts closer together than N degrees to + avoid unnecessary overlap when we have plenty of space due + to addresses that probably won't respond. And don't spread + them out too far apart, because that looks too symmetrical + when there are a small number of hosts. + */ + { + double th = frand(M_PI); + double sep = 360.0 / pd->target_count; + if (sep < 23) sep = 23; + if (sep > 43) sep = 43; + sep /= 180/M_PI; + for (b = pd->targets; b; b = b->next) { + b->th = th; + th += sep; + } + } + + return ssd; +} + +#endif /* HAVE_PING -- whole file */ diff --git a/hacks/glx/sonar-sim.c b/hacks/glx/sonar-sim.c new file mode 100644 index 00000000..ea5452e7 --- /dev/null +++ b/hacks/glx/sonar-sim.c @@ -0,0 +1,112 @@ +/* sonar, Copyright (c) 1998-2012 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 + * 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. + * + * This implements the "simulation" sensor for sonar. + */ + +#include "screenhackI.h" +#include "sonar.h" + +typedef struct { + const char *team_a_name; + const char *team_b_name; + int team_a_count; + int team_b_count; + sonar_bogie *targets; + Bool debug_p; +} sim_data; + + +static void +sim_free_data (sonar_sensor_data *ssd, void *closure) +{ + sim_data *sd = (sim_data *) closure; + free (sd); +} + +static void +sim_free_bogie_data (sonar_sensor_data *ssd, void *closure) +{ + free (closure); +} + + +/* Return an updated (moved) copy of the bogies. + */ +static sonar_bogie * +sim_scan (sonar_sensor_data *ssd) +{ + sim_data *sd = (sim_data *) ssd->closure; + sonar_bogie *b, *b2, *list = 0; + double scale = 0.01; + for (b = sd->targets; b; b = b->next) + { + b->r += scale * (0.5 - frand(1.0)); + b->th += scale * (0.5 - frand(1.0)); + while (b->r < 0.2) b->r += scale * 0.1; + while (b->r > 0.9) b->r -= scale * 0.1; + + b2 = sonar_copy_bogie (ssd, b); + b2->next = list; + list = b2; + } + return list; +} + + +static void +make_bogies (sonar_sensor_data *ssd) +{ + sim_data *sd = (sim_data *) ssd->closure; + int i, j; + + for (j = 0; j <= 1; j++) + for (i = 0; i < (j ? sd->team_a_count : sd->team_b_count); i++) + { + sonar_bogie *b = (sonar_bogie *) calloc (1, sizeof(*b)); + const char *name = (j ? sd->team_a_name : sd->team_b_name); + b->name = (char *) malloc (strlen(name) + 10); + sprintf (b->name, "%s%03d", name, i+1); + b->r = 0.3 + frand(0.5); + b->th = frand (M_PI*2); + b->next = sd->targets; + sd->targets = b; + if (sd->debug_p) + fprintf (stderr, "%s: %s: %5.2f %5.2f\n", progname, + b->name, b->r, b->th); + } +} + + +sonar_sensor_data * +sonar_init_simulation (Display *dpy, char **error_ret, char **desc_ret, + const char *team_a_name, const char *team_b_name, + int team_a_count, int team_b_count, + Bool debug_p) +{ + sonar_sensor_data *ssd = (sonar_sensor_data *) calloc (1, sizeof(*ssd)); + sim_data *sd = (sim_data *) calloc (1, sizeof(*sd)); + + sd->team_a_name = team_a_name; + sd->team_b_name = team_b_name; + sd->team_a_count = team_a_count; + sd->team_b_count = team_b_count; + sd->debug_p = debug_p; + + ssd->closure = sd; + ssd->scan_cb = sim_scan; + ssd->free_data_cb = sim_free_data; + ssd->free_bogie_cb = sim_free_bogie_data; + + make_bogies (ssd); + + return ssd; +} + diff --git a/hacks/glx/sonar.c b/hacks/glx/sonar.c new file mode 100644 index 00000000..bafb43ed --- /dev/null +++ b/hacks/glx/sonar.c @@ -0,0 +1,1047 @@ +/* sonar, Copyright (c) 1998-2012 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 + * 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. + */ + +/* Created in Apr 1998 by Stephen Martin + * for the RedHat Screensaver Contest + * Heavily hacked by jwz ever since. + * Rewritten in OpenGL by jwz, Aug 2008. + * + * This is an implementation of a general purpose reporting tool in the + * format of a Sonar display. It is designed such that a sensor is read + * on every movement of a sweep arm and the results of that sensor are + * displayed on the screen. The location of the display points (targets) on the + * screen are determined by the current localtion of the sweep and a distance + * value associated with the target. + * + * Currently the only two sensors that are implemented are the simulator + * (the default) and the ping sensor. The simulator randomly creates a set + * of bogies that move around on the scope while the ping sensor can be + * used to display hosts on your network. + * + * The ping code is only compiled in if you define HAVE_ICMP or HAVE_ICMPHDR, + * because, unfortunately, different systems have different ways of creating + * these sorts of packets. + * + * In order to use the ping sensor on most systems, this program must be + * installed as setuid root, so that it can create an ICMP RAW socket. Root + * privileges are disavowed shortly after startup (just after connecting to + * the X server and reading the resource database) so this is *believed* to + * be a safe thing to do, but it is usually recommended that you have as few + * setuid programs around as possible, on general principles. + * + * It is not necessary to make it setuid on MacOS systems, because on those + * systems, unprivileged programs can ping by using ICMP DGRAM sockets + * instead of ICMP RAW. + * + * It should be easy to extend this code to support other sorts of sensors. + * Some ideas: + * + * - search the output of "netstat" for the list of hosts to ping; + * - plot the contents of /proc/interrupts; + * - plot the process table, by process size, cpu usage, or total time; + * - plot the logged on users by idle time or cpu usage. + * - plot IM contacts or Facebook friends and their last-activity times. + */ + +#define DEF_FONT "-*-lucidatypewriter-bold-r-normal-*-*-480-*-*-*-*-iso8859-1" +#define DEF_SPEED "1.0" +#define DEF_SWEEP_SIZE "0.3" +#define DEF_FONT_SIZE "12" +#define DEF_TEAM_A_NAME "F18" +#define DEF_TEAM_B_NAME "MIG" +#define DEF_TEAM_A_COUNT "4" +#define DEF_TEAM_B_COUNT "4" +#define DEF_PING "default" +#define DEF_PING_TIMEOUT "3000" +#define DEF_RESOLVE "True" +#define DEF_TIMES "True" +#define DEF_WOBBLE "True" +#define DEF_DEBUG "False" + +#define DEFAULTS "*delay: 30000 \n" \ + "*font: " DEF_FONT "\n" \ + "*showFPS: False \n" \ + "*wireframe: False \n" \ + + +# define refresh_sonar 0 +#undef countof +#define countof(x) (sizeof((x))/sizeof((*x))) + +#ifdef HAVE_UNISTD_H +# include /* for setuid() */ +#endif + +#include "xlockmore.h" +#include "sonar.h" +#include "gltrackball.h" +#include "rotator.h" +#include "texfont.h" +#include + +#ifdef USE_GL /* whole file */ + +typedef struct { + double x,y,z; +} XYZ; + +typedef struct { + GLXContext *glx_context; + trackball_state *trackball; + rotator *rot; + Bool button_down_p; + + double start_time; + GLfloat sweep_offset; + + GLuint screen_list, grid_list, sweep_list, table_list; + int screen_polys, grid_polys, sweep_polys, table_polys; + GLfloat sweep_th; + GLfloat line_thickness; + + texture_font_data *texfont; + + enum { MSG, RESOLVE, RUN } state; + sonar_sensor_data *ssd; + char *error; + char *desc; + + sonar_bogie *displayed; /* on screen and fading */ + sonar_bogie *pending; /* returned by sensor, not yet on screen */ + +} sonar_configuration; + +static sonar_configuration *sps = NULL; + +static GLfloat speed; +static GLfloat sweep_size; +static GLfloat font_size; +static Bool resolve_p; +static Bool times_p; +static Bool wobble_p; +static Bool debug_p; + +static char *team_a_name; +static char *team_b_name; +static int team_a_count; +static int team_b_count; +static int ping_timeout; +static char *ping_arg; + +static XrmOptionDescRec opts[] = { + { "-speed", ".speed", XrmoptionSepArg, 0 }, + { "-sweep-size", ".sweepSize", XrmoptionSepArg, 0 }, + { "-font-size", ".fontSize", XrmoptionSepArg, 0 }, + { "-team-a-name", ".teamAName", XrmoptionSepArg, 0 }, + { "-team-b-name", ".teamBName", XrmoptionSepArg, 0 }, + { "-team-a-count", ".teamACount", XrmoptionSepArg, 0 }, + { "-team-b-count", ".teamBCount", XrmoptionSepArg, 0 }, + { "-ping", ".ping", XrmoptionSepArg, 0 }, + { "-ping-timeout", ".pingTimeout", XrmoptionSepArg, 0 }, + { "-dns", ".resolve", XrmoptionNoArg, "True" }, + { "+dns", ".resolve", XrmoptionNoArg, "False" }, + { "-times", ".times", XrmoptionNoArg, "True" }, + { "+times", ".times", XrmoptionNoArg, "False" }, + { "-wobble", ".wobble", XrmoptionNoArg, "True" }, + { "+wobble", ".wobble", XrmoptionNoArg, "False" }, + { "-debug", ".debug", XrmoptionNoArg, "True" }, +}; + +static argtype vars[] = { + {&speed, "speed", "Speed", DEF_SPEED, t_Float}, + {&sweep_size, "sweepSize", "SweepSize", DEF_SWEEP_SIZE, t_Float}, + {&font_size, "fontSize", "FontSize", DEF_FONT_SIZE, t_Float}, + {&team_a_name, "teamAName", "TeamName", DEF_TEAM_A_NAME, t_String}, + {&team_b_name, "teamBName", "TeamName", DEF_TEAM_B_NAME, t_String}, + {&team_a_count, "teamACount", "TeamCount", DEF_TEAM_A_COUNT, t_Int}, + {&team_b_count, "teamBCount", "TeamCount", DEF_TEAM_A_COUNT, t_Int}, + {&ping_arg, "ping", "Ping", DEF_PING, t_String}, + {&ping_timeout, "pingTimeout", "PingTimeout", DEF_PING_TIMEOUT, t_Int}, + {&resolve_p, "resolve", "Resolve", DEF_RESOLVE, t_Bool}, + {×_p, "times", "Times", DEF_TIMES, t_Bool}, + {&wobble_p, "wobble", "Wobble", DEF_WOBBLE, t_Bool}, + {&debug_p, "debug", "Debug", DEF_DEBUG, t_Bool}, +}; + +ENTRYPOINT ModeSpecOpt sonar_opts = {countof(opts), opts, countof(vars), vars, NULL}; + + +static int +draw_screen (ModeInfo *mi, Bool mesh_p, Bool sweep_p) +{ + sonar_configuration *sp = &sps[MI_SCREEN(mi)]; + int wire = MI_IS_WIREFRAME(mi); + int polys = 0; + int i; + int th_steps, r_steps, r_skip, th_skip, th_skip2, outer_r; + GLfloat curvature = M_PI * 0.4; + GLfloat r0, r1, z0, z1, zoff; + XYZ *ring; + + static const GLfloat glass[4] = {0.0, 0.4, 0.0, 0.5}; + static const GLfloat lines[4] = {0.0, 0.7, 0.0, 0.5}; + static const GLfloat sweepc[4] = {0.2, 1.0, 0.2, 0.5}; + static const GLfloat spec[4] = {1.0, 1.0, 1.0, 1.0}; + static const GLfloat shiny = 20.0; + + if (wire && !(mesh_p || sweep_p)) return 0; + + glDisable (GL_TEXTURE_2D); + + glFrontFace (GL_CCW); + th_steps = 36 * 4; /* must be a multiple of th_skip2 divisor */ + r_steps = 40; + r_skip = 1; + th_skip = 1; + th_skip2 = 1; + outer_r = 0; + + glMaterialfv (GL_FRONT, GL_SPECULAR, spec); + glMateriali (GL_FRONT, GL_SHININESS, shiny); + glMaterialfv (GL_FRONT, GL_AMBIENT_AND_DIFFUSE, mesh_p ? lines : glass); + if (wire) glColor3fv (lines); + + if (mesh_p) + { + th_skip = th_steps / 12; + th_skip2 = th_steps / 36; + r_skip = r_steps / 3; + outer_r = r_steps * 0.93; + + if (! wire) + glLineWidth (sp->line_thickness); + } + + ring = (XYZ *) calloc (th_steps, sizeof(*ring)); + + for (i = 0; i < th_steps; i++) + { + double a = M_PI * 2 * i / th_steps; + ring[i].x = cos(a); + ring[i].y = sin(a); + } + + /* place the bottom of the disc on the xy plane. */ + zoff = cos (curvature/2 * (M_PI/2)) / 2; + + for (i = r_steps; i > 0; i--) + { + int j0, j1; + + r0 = i / (GLfloat) r_steps; + r1 = (i+1) / (GLfloat) r_steps; + + if (r1 > 1) r1 = 1; /* avoid asin lossage */ + + z0 = cos (curvature/2 * asin (r0)) / 2 - zoff; + z1 = cos (curvature/2 * asin (r1)) / 2 - zoff; + + glBegin(wire || mesh_p ? GL_LINES : GL_QUAD_STRIP); + for (j0 = 0; j0 <= th_steps; j0++) + { + if (mesh_p && + (i < outer_r + ? (j0 % th_skip != 0) + : (j0 % th_skip2 != 0))) + continue; + + if (sweep_p) + { + GLfloat color[4]; + GLfloat r = 1 - (j0 / (GLfloat) (th_steps * sweep_size)); +#if 0 + color[0] = glass[0] + (sweepc[0] - glass[0]) * r; + color[1] = glass[1] + (sweepc[1] - glass[1]) * r; + color[2] = glass[2] + (sweepc[2] - glass[2]) * r; + color[3] = glass[3]; +#else + color[0] = sweepc[0]; + color[1] = sweepc[1]; + color[2] = sweepc[2]; + color[3] = r; +#endif + glMaterialfv (GL_FRONT, GL_AMBIENT_AND_DIFFUSE, color); + } + + j1 = j0 % th_steps; + glNormal3f (r0 * ring[j1].x, r0 * ring[j1].y, z0); + glVertex3f (r0 * ring[j1].x, r0 * ring[j1].y, z0); + glNormal3f (r1 * ring[j1].x, r1 * ring[j1].y, z1); + glVertex3f (r1 * ring[j1].x, r1 * ring[j1].y, z1); + polys++; + + if (sweep_p && j0 >= th_steps * sweep_size) + break; + if (sweep_p && wire) + break; + } + glEnd(); + + if (mesh_p && + (i == outer_r || + i == r_steps || + (i % r_skip == 0 && + i < r_steps - r_skip))) + { + glBegin(GL_LINE_LOOP); + for (j0 = 0; j0 < th_steps; j0++) + { + glNormal3f (r0 * ring[j0].x, r0 * ring[j0].y, z0); + glVertex3f (r0 * ring[j0].x, r0 * ring[j0].y, z0); + polys++; + } + glEnd(); + } + } + + /* one more polygon for the middle */ + if (!wire && !sweep_p) + { + glBegin(wire || mesh_p ? GL_LINE_LOOP : GL_POLYGON); + glNormal3f (0, 0, 1); + for (i = 0; i < th_steps; i++) + { + glNormal3f (r0 * ring[i].x, r0 * ring[i].y, z0); + glVertex3f (r0 * ring[i].x, r0 * ring[i].y, z0); + } + polys++; + glEnd(); + } + + free (ring); + + return polys; +} + + +static int +draw_text (ModeInfo *mi, const char *string, GLfloat r, GLfloat th, + GLfloat ttl, GLfloat size) +{ + sonar_configuration *sp = &sps[MI_SCREEN(mi)]; + int wire = MI_IS_WIREFRAME(mi); + int polys = 0; + GLfloat font_scale = 0.001 * (size > 0 ? size : font_size) / 14.0; + int lines = 0, max_w = 0, lh = 0; + char *string2 = strdup (string); + char *token = string2; + char *line; + + if (size <= 0) /* if size not specified, draw in yellow with alpha */ + { + GLfloat color[4]; + color[0] = 1; + color[1] = 1; + color[2] = 0; + color[3] = (ttl / (M_PI * 2)) * 1.2; + if (color[3] > 1) color[3] = 1; + + glMaterialfv (GL_FRONT, GL_AMBIENT_AND_DIFFUSE, color); + if (wire) + glColor3f (color[0]*color[3], color[1]*color[3], color[2]*color[3]); + } + + while ((line = strtok (token, "\r\n"))) + { + int w = texture_string_width (sp->texfont, line, &lh); + if (w > max_w) max_w = w; + lines++; + token = 0; + } + + glPushMatrix(); + glTranslatef (r * cos (th), r * sin(th), 0); + glScalef (font_scale, font_scale, font_scale); + + if (size <= 0) /* Draw the dot */ + { + GLfloat s = font_size * 1.7; + glDisable (GL_TEXTURE_2D); + glFrontFace (GL_CW); + glBegin (wire ? GL_LINE_LOOP : GL_QUADS); + glVertex3f (0, s, 0); + glVertex3f (s, s, 0); + glVertex3f (s, 0, 0); + glVertex3f (0, 0, 0); + glEnd(); + glTranslatef (-max_w/2, -lh, 0); + } + else + glTranslatef (-max_w/2, -lh/2, 0); + + /* draw each line, centered */ + if (! wire) glEnable (GL_TEXTURE_2D); + free (string2); + string2 = strdup (string); + token = string2; + while ((line = strtok (token, "\r\n"))) + { + int w = texture_string_width (sp->texfont, line, 0); + glPushMatrix(); + glTranslatef ((max_w-w)/2, 0, 0); + + if (wire) + { + glBegin (GL_LINE_LOOP); + glVertex3f (0, 0, 0); + glVertex3f (w, 0, 0); + glVertex3f (w, lh, 0); + glVertex3f (0, lh, 0); + glEnd(); + } + else + { + glFrontFace (GL_CW); + print_texture_string (sp->texfont, line); + } + glPopMatrix(); + glTranslatef (0, -lh, 0); + polys++; + token = 0; + } + glPopMatrix(); + + free (string2); + + if (! wire) glEnable (GL_DEPTH_TEST); + + return polys; +} + + +/* There's a disc with a hole in it around the screen, to act as a mask + preventing slightly off-screen bogies from showing up. This clips 'em. + */ +static int +draw_table (ModeInfo *mi) +{ + /*sonar_configuration *sp = &sps[MI_SCREEN(mi)];*/ + int wire = MI_IS_WIREFRAME(mi); + int polys = 0; + int i; + int th_steps = 36 * 4; /* same as in draw_screen */ + + static const GLfloat color[4] = {0.0, 0.0, 0.0, 1.0}; + static const GLfloat text[4] = {0.15, 0.15, 0.15, 1.0}; + static const GLfloat spec[4] = {0.0, 0.0, 0.0, 1.0}; + static const GLfloat shiny = 0.0; + + if (wire) return 0; + + glDisable (GL_TEXTURE_2D); + + glMaterialfv (GL_FRONT, GL_SPECULAR, spec); + glMateriali (GL_FRONT, GL_SHININESS, shiny); + glMaterialfv (GL_FRONT, GL_AMBIENT_AND_DIFFUSE, color); + + glFrontFace (GL_CCW); + glBegin(wire ? GL_LINES : GL_QUAD_STRIP); + glNormal3f (0, 0, 1); + for (i = 0; i <= th_steps; i++) + { + double a = M_PI * 2 * i / th_steps; + double x = cos(a); + double y = sin(a); + glVertex3f (x, y, 0); + glVertex3f (x*10, y*10, 0); + polys++; + } + glEnd(); + + glMaterialfv (GL_FRONT, GL_AMBIENT_AND_DIFFUSE, text); + glTranslatef (0, 0, 0.01); + for (i = 0; i < 360; i += 10) + { + char buf[10]; + GLfloat a = M_PI/2 - (i / 180.0 * M_PI); + sprintf (buf, "%d", i); + polys += draw_text (mi, buf, 1.07, a, 0, 10.0); + } + + return polys; +} + + +static int +draw_bogies (ModeInfo *mi) +{ + sonar_configuration *sp = &sps[MI_SCREEN(mi)]; + int polys = 0; + sonar_bogie *b; + + for (b = sp->displayed; b; b = b->next) + { + char *s = (char *) + malloc (strlen (b->name) + (b->desc ? strlen(b->desc) : 0) + 3); + strcpy (s, b->name); + if (b->desc) + { + strcat (s, "\n"); + strcat (s, b->desc); + } + polys += draw_text (mi, s, b->r, b->th, b->ttl, -1); + free (s); + + /* Move *very slightly* forward so that the text is not all in the + same plane: this prevents flickering with overlapping text as + the textures fight for priority. */ + glTranslatef(0, 0, 0.00002); + } + + return polys; +} + + +/* called from sonar-sim.c and sonar-icmp.c */ +sonar_bogie * +sonar_copy_bogie (sonar_sensor_data *ssd, const sonar_bogie *b) +{ + sonar_bogie *b2 = (sonar_bogie *) calloc (1, sizeof(*b2)); + b2->name = strdup (b->name); + b2->desc = b->desc ? strdup (b->desc) : 0; + b2->r = b->r; + b2->th = b->th; + b2->ttl = b->ttl; + /* does not copy b->closure */ + + /* Take this opportunity to normalize 'th' to the range [0-2pi). */ + while (b2->th < 0) b2->th += M_PI*2; + while (b2->th >= M_PI*2) b2->th -= M_PI*2; + + return b2; +} + + +/* called from sonar-icmp.c */ +void +sonar_free_bogie (sonar_sensor_data *ssd, sonar_bogie *b) +{ + if (b->closure) + ssd->free_bogie_cb (ssd, b->closure); + free (b->name); + if (b->desc) free (b->desc); + free (b); +} + +/* removes it from the list and frees it + */ +static void +delete_bogie (sonar_sensor_data *ssd, sonar_bogie *b, + sonar_bogie **from_list) +{ + sonar_bogie *ob, *prev; + for (prev = 0, ob = *from_list; ob; prev = ob, ob = ob->next) + if (ob == b) + { + if (prev) + prev->next = b->next; + else + (*from_list) = b->next; + sonar_free_bogie (ssd, b); + break; + } +} + + +/* copies the bogie and adds it to the list. + if there's another bogie there with the same name, frees that one. + */ +static void +copy_and_insert_bogie (sonar_sensor_data *ssd, sonar_bogie *b, + sonar_bogie **to_list) +{ + sonar_bogie *ob, *next; + if (!b) abort(); + for (ob = *to_list, next = ob ? ob->next : 0; + ob; + ob = next, next = ob ? ob->next : 0) + { + if (ob == b) abort(); /* this will end badly */ + if (!strcmp (ob->name, b->name)) /* match! */ + { + delete_bogie (ssd, ob, to_list); + break; + } + } + + b = sonar_copy_bogie (ssd, b); + b->next = *to_list; + *to_list = b; +} + + +static void +update_sensor_data (sonar_configuration *sp) +{ + sonar_bogie *new_list = sp->ssd->scan_cb (sp->ssd); + sonar_bogie *b2; + + /* If a bogie exists in 'new_list' but not 'pending', add it. + If a bogie exists in both, update it in 'pending'. + */ + for (b2 = new_list; b2; b2 = b2->next) + { + if (debug_p > 2) + fprintf (stderr, "%s: updated: %s (%5.2f %5.2f %5.2f)\n", + progname, b2->name, b2->r, b2->th, b2->ttl); + copy_and_insert_bogie (sp->ssd, b2, &sp->pending); + } + if (debug_p > 2) fprintf (stderr, "\n"); +} + + +/* Returns whether the given angle lies between two other angles. + When those angles cross 0, it assumes the wedge is the smaller one. + That is: 5 lies between 10 and 350 degrees (a 20 degree wedge). + */ +static Bool +point_in_wedge (GLfloat th, GLfloat low, GLfloat high) +{ + if (low < high) + return (th > low && th <= high); + else + return (th <= high || th > low); +} + + +/* Returns the current time in seconds as a double. + */ +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 void +sweep (sonar_configuration *sp) +{ + sonar_bogie *b; + + /* Move the sweep forward (clockwise). + */ + GLfloat prev_sweep, this_sweep, tick; + GLfloat cycle_secs = 30 / speed; /* default to one cycle every N seconds */ + this_sweep = ((cycle_secs - fmod (double_time() - sp->start_time + + sp->sweep_offset, + cycle_secs)) + / cycle_secs + * M_PI * 2); + prev_sweep = sp->sweep_th; + tick = prev_sweep - this_sweep; + while (tick < 0) tick += M_PI*2; + + sp->sweep_th = this_sweep; + + if (this_sweep < 0 || this_sweep >= M_PI*2) abort(); + if (prev_sweep < 0) /* skip first time */ + return; + + if (tick < 0 || tick >= M_PI*2) abort(); + + + /* Go through the 'pending' sensor data, find those bogies who are + just now being swept, and move them from 'pending' to 'displayed'. + (Leave bogies that have not yet been swept alone: we'll get to + them when the sweep moves forward.) + */ + b = sp->pending; + while (b) + { + sonar_bogie *next = b->next; + if (point_in_wedge (b->th, this_sweep, prev_sweep)) + { + if (debug_p > 1) { + time_t t = time((time_t *) 0); + fprintf (stderr, + "%s: sweep hit: %02d:%02d: %s: (%5.2f %5.2f %5.2f;" + " th=[%.2f < %.2f <= %.2f])\n", + progname, + (int) (t / 60) % 60, (int) t % 60, + b->name, b->r, b->th, b->ttl, + this_sweep, b->th, prev_sweep); + } + b->ttl = M_PI * 2.1; + copy_and_insert_bogie (sp->ssd, b, &sp->displayed); + delete_bogie (sp->ssd, b, &sp->pending); + } + b = next; + } + + + /* Update TTL on all currently-displayed bogies; delete the dead. + + Request sensor updates on the ones just now being swept. + + Any updates go into 'pending' and might not show up until + the next time the sweep comes around. This is to prevent + already-drawn bogies from jumping to a new position without + having faded out first. + */ + b = sp->displayed; + while (b) + { + sonar_bogie *next = b->next; + b->ttl -= tick; + + if (b->ttl <= 0) + { + if (debug_p > 1) + fprintf (stderr, "%s: TTL expired: %s (%5.2f %5.2f %5.2f)\n", + progname, b->name, b->r, b->th, b->ttl); + delete_bogie (sp->ssd, b, &sp->displayed); + } + b = next; + } + + update_sensor_data (sp); +} + + +static void +draw_startup_blurb (ModeInfo *mi) +{ + sonar_configuration *sp = &sps[MI_SCREEN(mi)]; + const char *msg = (sp->error ? sp->error : "Resolving hosts..."); + static const GLfloat color[4] = {0, 1, 0, 1}; + + if (!sp->error && ping_arg && !strcmp (ping_arg, "simulation")) + return; /* don't bother */ + + glMaterialfv (GL_FRONT, GL_AMBIENT_AND_DIFFUSE, color); + glTranslatef (0, 0, 0.3); + draw_text (mi, msg, 0, 0, 0, 30.0); + + /* only leave error message up for N seconds */ + if (sp->error && + sp->start_time + 6 < double_time()) + { + free (sp->error); + sp->error = 0; + } +} + + +/* Window management, etc + */ +ENTRYPOINT void +reshape_sonar (ModeInfo *mi, int width, int height) +{ + sonar_configuration *sp = &sps[MI_SCREEN(mi)]; + GLfloat h = (GLfloat) height / (GLfloat) width; + + glViewport (0, 0, (GLint) width, (GLint) height); + + glMatrixMode(GL_PROJECTION); + glLoadIdentity(); + gluPerspective (30.0, 1/h, 1.0, 100.0); + + glMatrixMode(GL_MODELVIEW); + glLoadIdentity(); + gluLookAt( 0.0, 0.0, 30.0, + 0.0, 0.0, 0.0, + 0.0, 1.0, 0.0); + + glClear(GL_COLOR_BUFFER_BIT); + + sp->line_thickness = (MI_IS_WIREFRAME (mi) ? 1 : MAX (1, height / 300.0)); +} + + +ENTRYPOINT Bool +sonar_handle_event (ModeInfo *mi, XEvent *event) +{ + sonar_configuration *sp = &sps[MI_SCREEN(mi)]; + + if (event->xany.type == ButtonPress && + event->xbutton.button == Button1) + { + sp->button_down_p = True; + gltrackball_start (sp->trackball, + event->xbutton.x, event->xbutton.y, + MI_WIDTH (mi), MI_HEIGHT (mi)); + return True; + } + else if (event->xany.type == ButtonRelease && + event->xbutton.button == Button1) + { + sp->button_down_p = False; + return True; + } + else if (event->xany.type == ButtonPress && + (event->xbutton.button == Button4 || + event->xbutton.button == Button5 || + event->xbutton.button == Button6 || + event->xbutton.button == Button7)) + { + gltrackball_mousewheel (sp->trackball, event->xbutton.button, 10, + !!event->xbutton.state); + return True; + } + else if (event->xany.type == MotionNotify && + sp->button_down_p) + { + gltrackball_track (sp->trackball, + event->xmotion.x, event->xmotion.y, + MI_WIDTH (mi), MI_HEIGHT (mi)); + return True; + } + + return False; +} + + +ENTRYPOINT void +init_sonar (ModeInfo *mi) +{ + sonar_configuration *sp; + + if (!sps) { + sps = (sonar_configuration *) + calloc (MI_NUM_SCREENS(mi), sizeof (sonar_configuration)); + if (!sps) { + fprintf(stderr, "%s: out of memory\n", progname); + exit(1); + } + } + sp = &sps[MI_SCREEN(mi)]; + sp->glx_context = init_GL(mi); + + reshape_sonar (mi, MI_WIDTH(mi), MI_HEIGHT(mi)); + clear_gl_error(); /* WTF? sometimes "invalid op" from glViewport! */ + + sp->trackball = gltrackball_init (); + sp->rot = make_rotator (0, 0, 0, 0, speed * 0.003, True); + + sp->texfont = load_texture_font (MI_DISPLAY(mi), "font"); + check_gl_error ("loading font"); + + sp->table_list = glGenLists (1); + glNewList (sp->table_list, GL_COMPILE); + sp->table_polys = draw_table (mi); + glEndList (); + + sp->screen_list = glGenLists (1); + glNewList (sp->screen_list, GL_COMPILE); + sp->screen_polys = draw_screen (mi, False, False); + glEndList (); + + sp->grid_list = glGenLists (1); + glNewList (sp->grid_list, GL_COMPILE); + sp->grid_polys = draw_screen (mi, True, False); + glEndList (); + + sp->sweep_list = glGenLists (1); + glNewList (sp->sweep_list, GL_COMPILE); + sp->sweep_polys = draw_screen (mi, False, True); + glEndList (); + + sp->start_time = double_time (); + sp->sweep_offset = random() % 60; + sp->sweep_th = -1; + sp->state = MSG; +} + + +static void +init_sensor (ModeInfo *mi) +{ + sonar_configuration *sp = &sps[MI_SCREEN(mi)]; + + if (sp->ssd) abort(); + + if (!ping_arg || !*ping_arg || + !strcmp(ping_arg, "default") || + !!strcmp (ping_arg, "simulation")) + sp->ssd = sonar_init_ping (MI_DISPLAY (mi), &sp->error, &sp->desc, + ping_arg, ping_timeout, resolve_p, times_p, + debug_p); + + sp->start_time = double_time (); /* for error message timing */ + + /* Disavow privs. This was already done in init_ping(), but + we might not have called that at all, so do it again. */ + setuid(getuid()); + + if (!sp->ssd) + sp->ssd = sonar_init_simulation (MI_DISPLAY (mi), &sp->error, &sp->desc, + team_a_name, team_b_name, + team_a_count, team_b_count, + debug_p); + if (!sp->ssd) + abort(); +} + + +ENTRYPOINT void +draw_sonar (ModeInfo *mi) +{ + sonar_configuration *sp = &sps[MI_SCREEN(mi)]; + Display *dpy = MI_DISPLAY(mi); + Window window = MI_WINDOW(mi); + int wire = MI_IS_WIREFRAME(mi); + + if (!sp->glx_context) + return; + + glXMakeCurrent(MI_DISPLAY(mi), MI_WINDOW(mi), *(sp->glx_context)); + + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + + if (!wire) + { + GLfloat pos[4] = {0.05, 0.07, 1.00, 0.0}; + GLfloat amb[4] = {0.2, 0.2, 0.2, 1.0}; + GLfloat dif[4] = {1.0, 1.0, 1.0, 1.0}; + GLfloat spc[4] = {0.0, 1.0, 1.0, 1.0}; + + glEnable(GL_TEXTURE_2D); + glEnable(GL_LIGHTING); + glEnable(GL_LIGHT0); + glEnable(GL_CULL_FACE); + glEnable(GL_DEPTH_TEST); + glEnable(GL_NORMALIZE); + glEnable(GL_LINE_SMOOTH); + glEnable(GL_BLEND); + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + glHint(GL_LINE_SMOOTH_HINT, GL_NICEST); + glShadeModel(GL_SMOOTH); + + glLightfv(GL_LIGHT0, GL_POSITION, pos); + glLightfv(GL_LIGHT0, GL_AMBIENT, amb); + glLightfv(GL_LIGHT0, GL_DIFFUSE, dif); + glLightfv(GL_LIGHT0, GL_SPECULAR, spc); + } + + glPushMatrix (); + glRotatef(current_device_rotation(), 0, 0, 1); + + { + GLfloat s = 7; + if (MI_WIDTH(mi) < MI_HEIGHT(mi)) + s *= (MI_WIDTH(mi) / (float) MI_HEIGHT(mi)); + glScalef (s,s,s); + } + + gltrackball_rotate (sp->trackball); + + if (wobble_p) + { + double x, y, z; + double max = 40; + get_position (sp->rot, &x, &y, &z, !sp->button_down_p); + glRotatef (max/2 - x*max, 1, 0, 0); + glRotatef (max/2 - z*max, 0, 1, 0); + } + + mi->polygon_count = 0; + + glPushMatrix(); /* table */ + glCallList (sp->table_list); + mi->polygon_count += sp->table_polys; + glPopMatrix(); + + glPushMatrix(); /* text */ + glTranslatef (0, 0, -0.01); + mi->polygon_count += draw_bogies (mi); + glPopMatrix(); + + glCallList (sp->screen_list); /* glass */ + mi->polygon_count += sp->screen_polys; + + glTranslatef (0, 0, 0.004); /* sweep */ + glPushMatrix(); + glRotatef ((sp->sweep_th * 180 / M_PI), 0, 0, 1); + if (sp->sweep_th >= 0) + glCallList (sp->sweep_list); + mi->polygon_count += sp->sweep_polys; + glPopMatrix(); + + glTranslatef (0, 0, 0.004); /* grid */ + glCallList (sp->grid_list); + mi->polygon_count += sp->screen_polys; + + if (sp->desc) /* local subnet */ + { + glPushMatrix(); + glTranslatef (0, 0, 0.00002); + mi->polygon_count += draw_text (mi, sp->desc, 1.35, M_PI * 0.75, 0, 10); + /* glRotatef (45, 0, 0, 1); */ + /* mi->polygon_count += draw_text (mi, sp->desc, 1.2, M_PI/2, 0, 10); */ + glPopMatrix(); + } + + if (sp->error) + sp->state = MSG; + + switch (sp->state) { + case MSG: /* Frame 1: get "Resolving Hosts" on screen. */ + draw_startup_blurb(mi); + sp->state++; + break; + case RESOLVE: /* Frame 2: gethostbyaddr may take a while. */ + if (! sp->ssd) + init_sensor (mi); + sp->state++; + break; + case RUN: /* Frame N: ping away */ + sweep (sp); + break; + } + + glPopMatrix (); + + if (mi->fps_p) do_fps (mi); + glFinish(); + + glXSwapBuffers(dpy, window); +} + +ENTRYPOINT void +release_sonar (ModeInfo *mi) +{ +#if 0 + sonar_configuration *sp = &sps[MI_SCREEN(mi)]; + sonar_bogie *b = sp->displayed; + while (b) + { + sonar_bogie *next = b->next; + free_bogie (sp->ssd, b); + b = next; + } + sp->displayed = 0; + + b = sp->pending; + while (b) + { + sonar_bogie *next = b->next; + free_bogie (sp->ssd, b); + b = next; + } + sp->pending = 0; + + sp->ssd->free_data_cb (sp->ssd, sp->ssd->closure); + free (sp->ssd); + sp->ssd = 0; +#endif +} + +XSCREENSAVER_MODULE ("Sonar", sonar) + +#endif /* USE_GL */ diff --git a/hacks/glx/sonar.h b/hacks/glx/sonar.h new file mode 100644 index 00000000..d6473e00 --- /dev/null +++ b/hacks/glx/sonar.h @@ -0,0 +1,71 @@ +/* sonar, Copyright (c) 1998-2012 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 + * 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. + */ + +#ifndef __SONAR_XSCREENSAVER_H__ +#define __SONAR_XSCREENSAVER_H__ + +typedef struct sonar_sensor_data sonar_sensor_data; +typedef struct sonar_bogie sonar_bogie; + +struct sonar_bogie { + void *closure; + char *name; /* bogie name, e.g., host name */ + char *desc; /* second line of text, e.g., ping time */ + double r; /* distance, 0 - 1.0 */ + double th; /* heading, 0 - 2 pi */ + double ttl; /* time to live, 0 - 2 pi */ + sonar_bogie *next; /* next one in the list */ +}; + +struct sonar_sensor_data { + void *closure; + + /* Called frequently (every time the sweep moves). + Returns a list of new bogies to be added to the display list + once the sweep comes around to their position. + */ + sonar_bogie *(*scan_cb) (sonar_sensor_data *); + + /* Called when a bogie is freed, to free bogie->closure */ + void (*free_bogie_cb) (sonar_sensor_data *, void *closure); + + /* Called at exit, to free ssd->closure */ + void (*free_data_cb) (sonar_sensor_data *, void *closure); +}; + +/* frees bogie and its contents, including calling the free_bogie_cb. */ +extern void sonar_free_bogie (sonar_sensor_data *ssd, sonar_bogie *b); + +/* makes a copy of the bogie, not including the 'closure' data. */ +extern sonar_bogie *sonar_copy_bogie (sonar_sensor_data *, + const sonar_bogie *); + + +/* Set up and return sensor state for ICMP pings. */ +extern sonar_sensor_data *sonar_init_ping (Display *dpy, + char **error_ret, + char **desc_ret, + const char *subnets, + int ping_timeout, + Bool resolve_p, Bool times_p, + Bool debug_p); + +/* Set up and return sensor state for the simulation. */ +extern sonar_sensor_data *sonar_init_simulation (Display *dpy, + char **error_ret, + char **desc_ret, + const char *team_a_name, + const char *team_b_name, + int team_a_count, + int team_b_count, + Bool debug_p); + +#endif /* __SONAR_XSCREENSAVER_H__ */ diff --git a/hacks/glx/sonar.man b/hacks/glx/sonar.man new file mode 100644 index 00000000..9927b3bb --- /dev/null +++ b/hacks/glx/sonar.man @@ -0,0 +1,169 @@ +.de EX \"Begin example +.ne 5 +.if n .sp 1 +.if t .sp .5 +.nf +.in +.5i +.. +.de EE +.fi +.in -.5i +.if n .sp 1 +.if t .sp .5 +.. +.TH Sonar 1 "12-Aug-08" "X Version 11" +.SH NAME +sonar - display a sonar scope +.SH SYNOPSIS +.B sonar +[\-ping \fIhosts-or-subnets\fP] +[\-ping\-timeout \fIint\fP] +[\-delay \fIusecs\fP] +[\-speed \fIratio\fP] +[\-sweep-size \fIratio\fP] +[\-font-size \fIpoints\fP] +[\-team-a-name \fIstring\fP] +[\-team-b-name \fIstring\fP] +[\-team-a-count \fIint\fP] +[\-team-b-count \fIint\fP] +[\-no\-dns] +[\-no\-times] +[\-no\-wobble] +[\-debug] +[\-fps] +.SH DESCRIPTION +This draws a sonar screen that pings (get it?) the hosts on +your local network, and plots their distance (response time) from you. +The three rings represent ping times of approximately 2.5, 70 and 2,000 +milliseconds respectively. + +Alternately, it can run a simulation that doesn't involve hosts. +.SH OPTIONS +.I sonar +understands the following options: +.TP 8 +.B \-ping \fIhosts-or-subnets\fP +The list of things to ping, separated by commas or spaces. +Elements of this list may be: +.RS 8 +.TP 12 +.B simulation +Run in simulation mode instead of pinging real hosts. +.TP 12 +.I hostname +Ping the given host. +.TP 12 +.I A.B.C.D +Ping the given IPv4 address. +.TP 12 +.B subnet +Ping the local subnet. On systems where we can determine the local +network mask, we use that; otherwise, we assume Class C (254 hosts). +.TP 12 +.B subnet/\fINN\fP +Ping a different-sized local subnet: e.g., \fBsubnet/28\fP would ping +a 4-bit subnet (the nearest 14 addresses). On systems where we can +determine the local network mask, we always use that. +.TP 12 +.I A.B.C.D/NN +Ping an arbitrary other IPv4 subnet. The address specifies +the base address, and the part after the slash is how wide the +subnet is. Typical values are /24 (for 254 addresses) and /28 (for +14 addresses). +.TP 12 +.I filename +Ping the hosts listed in the given file. This file can be in the +format used by \fI/etc/hosts\fP, or it can be any file that has host +names as the first or second element on each line. If you use ssh, +try this: + + sonar -ping $HOME/.ssh/known_hosts +.RE +.TP 8 +.B \-ping\-timeout \fIint\fP +The amount of time in milliseconds the program will wait for an answer +to a ping. +.TP 8 +.B \-delay \fIint\fP +Delay between frames, in microseconds. Default 20000. +.TP 8 +.B \-speed \fIratio\fP +Less than 1 for slower, greater than 1 for faster. Default 1. +.TP 8 +.B \-sweep-size \fIratio\fP +How big the glowing sweep area should be. Default 0.3. +.TP 8 +.B \-font-size \fIpoints\fP +How large the text should be. Default 10 points. +.TP 8 +.B \-no\-wobble +Keep the display stationary instead of very slowly wobbling back and forth. +.TP 8 +.B \-no\-dns +Do not attempt to resolve IP addresses to hostnames. +.TP 8 +.B \-no\-times +Do not display ping times beneath the host names. +.TP 8 +.B \-team-a-name \fIstring\fP +In simulation mode, the name of team A. +.TP 8 +.B \-team-b-name \fIstring\fP +In simulation mode, the name of team B. +.TP 8 +.B \-team-a-count \fIint\fP +In simulation mode, the number of bogies on team A. +.TP 8 +.B \-team-b-count \fIint\fP +In simulation mode, the number of bogies on team B. +.TP 8 +.B \-fps +Display the current frame rate, polygon count, and CPU load. +.SH NOTES +On most Unix systems, this program must be installed as setuid root +in order to ping hosts. This is because root privileges are needed +to create an ICMP RAW socket. Privileges are disavowed shortly after +startup (just after connecting to the X server) so this is believed +to be safe: +.EX +chown root:root sonar +chmod u+s sonar +.EE +It is not necessary to make it setuid on MacOS systems, because on +MacOS, unprivileged programs can ping by using ICMP DGRAM sockets +instead of ICMP RAW. + +In ping-mode, the display is a logarithmic scale, calibrated so that the +three rings represent ping times of approximately 2.5, 70 and 2,000 +milliseconds respectively. + +This means that if any the hosts you are pinging take longer than 2 +seconds to respond, they won't show up; and if you are pinging several +hosts with very fast response times, they will all appear close to the +center of the screen (making their names hard to read.) +.SH BUGS +Does not support IPv6. +.SH SEE ALSO +.BR X (1), +.BR xscreensaver (1), +.BR ping (8), +.BR ping6 (8) +.SH COPYRIGHT +Copyright \(co 2000-2012 by Jamie Zawinski +.RE +Copyright \(co 1998 by 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 +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 AUTHORS +Stephen Martin , 3-nov-1998. + +Subnet support, etc. added by Jamie Zawinski, 17-Jul-2000. + +Rewritten using OpenGL instead of X11 by Jamie Zawinski, 12-Aug-2008. diff --git a/hacks/glx/sphere.c b/hacks/glx/sphere.c new file mode 100644 index 00000000..182d0084 --- /dev/null +++ b/hacks/glx/sphere.c @@ -0,0 +1,138 @@ +/* sphere, Copyright (c) 2002 Paul Bourke , + * Copyright (c) 2010 Jamie Zawinski + * Utility function to create a unit sphere in GL. + * + * 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. + * + * 8-Oct-98: dek Released initial version of "glplanet" + * 21-Mar-01: jwz@jwz.org Broke sphere routine out into its own file. + * 28-Feb-02: jwz@jwz.org New implementation from Paul Bourke: + * http://astronomy.swin.edu.au/~pbourke/opengl/sphere/ + * 21-Aug-10 jwz@jwz.org Converted to use glDrawArrays, for OpenGL ES. + */ + +#include +#include + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#ifndef HAVE_COCOA +# include +#endif + +#ifdef HAVE_JWZGLES +# include "jwzgles.h" +#endif /* HAVE_JWZGLES */ + +#include "sphere.h" + +typedef struct { GLfloat x, y, z; } XYZ; + +int +unit_sphere (int stacks, int slices, int wire_p) +{ + int polys = 0; + int i,j; + double theta1, theta2, theta3; + XYZ p, n; + XYZ la = { 0, -1, 0 }, lb = { 0, -1, 0 }; + XYZ c = {0, 0, 0}; /* center */ + double r = 1.0; /* radius */ + int stacks2 = stacks * 2; + + int mode = (wire_p ? GL_LINE_STRIP : GL_TRIANGLE_STRIP); + + int arraysize, out; + struct { XYZ p; XYZ n; GLfloat s, t; } *array; + + if (r < 0) + r = -r; + if (slices < 0) + slices = -slices; + + arraysize = (stacks+1) * (slices+1) * (wire_p ? 4 : 2); + array = (void *) calloc (arraysize, sizeof(*array)); + if (! array) abort(); + out = 0; + + if (slices < 4 || stacks < 2 || r <= 0) + { + mode = GL_POINTS; + array[out++].p = c; + goto END; + } + + for (j = 0; j < stacks; j++) + { + theta1 = j * (M_PI+M_PI) / stacks2 - M_PI_2; + theta2 = (j + 1) * (M_PI+M_PI) / stacks2 - M_PI_2; + + for (i = slices; i >= 0; i--) + { + theta3 = i * (M_PI+M_PI) / slices; + + if (wire_p) + { + array[out++].p = lb; /* vertex */ + array[out++].p = la; /* vertex */ + } + + n.x = cos (theta2) * cos(theta3); + n.y = sin (theta2); + n.z = cos (theta2) * sin(theta3); + p.x = c.x + r * n.x; + p.y = c.y + r * n.y; + p.z = c.z + r * n.z; + + array[out].p = p; /* vertex */ + array[out].n = n; /* normal */ + array[out].s = i / (GLfloat) slices; /* texture */ + array[out].t = 2*(j+1) / (GLfloat) stacks2; + out++; + + if (wire_p) la = p; + + n.x = cos(theta1) * cos(theta3); + n.y = sin(theta1); + n.z = cos(theta1) * sin(theta3); + p.x = c.x + r * n.x; + p.y = c.y + r * n.y; + p.z = c.z + r * n.z; + + array[out].p = p; /* vertex */ + array[out].n = n; /* normal */ + array[out].s = i / (GLfloat) slices; /* texture */ + array[out].t = 2*j / (GLfloat) stacks2; + out++; + + if (out >= arraysize) abort(); + + if (wire_p) lb = p; + polys++; + } + } + + END: + + glEnableClientState (GL_VERTEX_ARRAY); + glEnableClientState (GL_NORMAL_ARRAY); + glEnableClientState (GL_TEXTURE_COORD_ARRAY); + + glVertexPointer (3, GL_FLOAT, sizeof(*array), &array[0].p); + glNormalPointer ( GL_FLOAT, sizeof(*array), &array[0].n); + glTexCoordPointer (2, GL_FLOAT, sizeof(*array), &array[0].s); + + glDrawArrays (mode, 0, out); + + free (array); + + return polys; +} diff --git a/hacks/glx/sphere.h b/hacks/glx/sphere.h new file mode 100644 index 00000000..96d95146 --- /dev/null +++ b/hacks/glx/sphere.h @@ -0,0 +1,23 @@ +/* sphere, Copyright (c) 2001-2008 Jamie Zawinski + * Utility function to create a unit sphere in GL. + * + * 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. + */ + +#ifndef __SPHERE_H__ +#define __SPHERE_H__ + +/* Creates a diameter 1 sphere at 0, 0, 0. + stacks = number of north/south divisions (latitude) + slices = number of clockwise/counterclockwise divisions (longitude) + Returns number of polygons used. + */ +extern int unit_sphere (int stacks, int slices, int wire_p); + +#endif /* __SPHERE_H__ */ diff --git a/hacks/glx/spheremonics.c b/hacks/glx/spheremonics.c new file mode 100644 index 00000000..0da7b0c7 --- /dev/null +++ b/hacks/glx/spheremonics.c @@ -0,0 +1,927 @@ +/* xscreensaver, Copyright (c) 2002-2012 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. + * + * Algorithm by Paul Bourke + * http://astronomy.swin.edu.au/~pbourke/geometry/sphericalh/ + * Screensaver veneer and parameter selection by jwz. + * + * Paul says: + * + * These closed objects are commonly called spherical harmonics, + * although they are only remotely related to the mathematical + * definition found in the solution to certain wave functions, most + * notable the eigenfunctions of angular momentum operators. + * + * The formula is quite simple: the form used here is based upon + * spherical (polar) coordinates (radius, theta, phi). + * + * r = sin(m0 phi) ^ m1 + + * cos(m2 phi) ^ m3 + + * sin(m4 theta) ^ m5 + + * cos(m6 theta) ^ m7 + * + * Where phi ranges from 0 to pi (lines of latitude), and theta ranges + * from 0 to 2 pi (lines of longitude), and r is the radius. The + * parameters m0, m1, m2, m3, m4, m5, m6, and m7 are all integers + * greater than or equal to 0. + * + * As the degree increases, the objects become increasingly "pointed" + * and a large number of polygons are required to represent the surface + * faithfully. + * + * jwz adds: + * + * The eight parameters live in the `cc->m' array. + * Each time we permute the image, we alter *one* of those eight parameters. + * Each time we alter a parameter, we move it in the same direction (either + * toward larger or smaller values) in the range [0, 3]. + * + * By altering only one parameter at a time, and only by small amounts, + * we tend to produce successive objects that are pretty similar to each + * other, so you can see a progression. + * + * It'd be nice if they were even closer together, so that it looked more + * like a morph, but, well, that's not how it works. + * + * There tends to be a dark stripe in the colormaps. I don't know why. + * Perhaps utils/colors.c is at fault? + * + * Note that this equation sometimes generates faces that are inside out: + * -parameters 01210111 + * To make this work, we need to render back-faces with two-sided lighting: + * figuring out how to correct the winding and normals on those inside out + * surfaces would be too hard. + */ + +#define DEFAULTS "*delay: 30000 \n" \ + "*showFPS: False \n" \ + "*wireframe: False \n" \ + "*labelfont: -*-helvetica-medium-r-normal-*-180-*\n" + +# define refresh_spheremonics 0 +# define release_spheremonics 0 +#undef countof +#define countof(x) (sizeof((x))/sizeof((*x))) + +#include "xlockmore.h" +#include "glxfonts.h" +#include "normals.h" +#include "colors.h" +#include "rotator.h" +#include "gltrackball.h" +#include + +#ifdef USE_GL /* whole file */ + +#define DEF_DURATION "100" +#define DEF_SPIN "XYZ" +#define DEF_WANDER "False" +#define DEF_RESOLUTION "64" +#define DEF_BBOX "False" +#define DEF_GRID "True" +#define DEF_SMOOTH "True" +#define DEF_PARMS "(default)" + +typedef struct { + GLXContext *glx_context; + rotator *rot; + trackball_state *trackball; + Bool button_down_p; + + GLuint dlist, dlist2; + GLfloat scale; + XYZ bbox[2]; + + int resolution; + int ncolors; + XColor *colors; + + int m[8]; + int dm[8]; + int m_max; + + int tracer; + int mesher; + int polys1, polys2; /* polygon counts */ + +# ifdef HAVE_GLBITMAP + XFontStruct *font; + GLuint font_list; +# else + texture_font_data *font_data; +# endif + + int change_tick; + int done_once; + +} spheremonics_configuration; + +static spheremonics_configuration *ccs = NULL; + +static char *do_spin; +static Bool do_wander; +static Bool do_bbox; +static Bool do_grid; +static int smooth_p; +static char *static_parms; +static int res; +static int duration; + +static XrmOptionDescRec opts[] = { + { "-spin", ".spin", XrmoptionSepArg, 0 }, + { "+spin", ".spin", XrmoptionNoArg, "" }, + { "-wander", ".wander", XrmoptionNoArg, "True" }, + { "+wander", ".wander", XrmoptionNoArg, "False" }, + { "-resolution", ".resolution", XrmoptionSepArg, 0 }, + { "-duration", ".duration", XrmoptionSepArg, 0 }, + { "-bbox", ".bbox", XrmoptionNoArg, "True" }, + { "+bbox", ".bbox", XrmoptionNoArg, "False" }, + { "-grid", ".grid", XrmoptionNoArg, "True" }, + { "+grid", ".grid", XrmoptionNoArg, "False" }, + {"-smooth", ".smooth", XrmoptionNoArg, "True" }, + {"+smooth", ".smooth", XrmoptionNoArg, "False" }, + { "-parameters", ".parameters", XrmoptionSepArg, 0 }, +}; + +static argtype vars[] = { + {&do_spin, "spin", "Spin", DEF_SPIN, t_String}, + {&do_wander, "wander", "Wander", DEF_WANDER, t_Bool}, + {&res, "resolution", "Resolution", DEF_RESOLUTION, t_Int}, + {&duration, "duration", "Duration", DEF_DURATION, t_Int}, + {&do_bbox, "bbox", "BBox", DEF_BBOX, t_Bool}, + {&do_grid, "grid", "Grid", DEF_GRID, t_Bool}, + {&smooth_p, "smooth", "Smooth", DEF_SMOOTH, t_Bool}, + {&static_parms, "parameters", "Parameters", DEF_PARMS, t_String}, +}; + +ENTRYPOINT ModeSpecOpt spheremonics_opts = {countof(opts), opts, countof(vars), vars, NULL}; + + +/* Window management, etc + */ +ENTRYPOINT void +reshape_spheremonics (ModeInfo *mi, int width, int height) +{ + GLfloat h = (GLfloat) height / (GLfloat) width; + + glViewport (0, 0, (GLint) width, (GLint) height); + + glMatrixMode(GL_PROJECTION); + glLoadIdentity(); + gluPerspective (30.0, 1/h, 1.0, 100.0); + + glMatrixMode(GL_MODELVIEW); + glLoadIdentity(); + gluLookAt( 0.0, 0.0, 30.0, + 0.0, 0.0, 0.0, + 0.0, 1.0, 0.0); + + glClear(GL_COLOR_BUFFER_BIT); +} + + +static void +gl_init (ModeInfo *mi) +{ +/* spheremonics_configuration *cc = &ccs[MI_SCREEN(mi)]; */ + int wire = MI_IS_WIREFRAME(mi); + + static const GLfloat pos[4] = {5.0, 5.0, 10.0, 1.0}; + + glEnable(GL_NORMALIZE); + + if (!wire) + { + glLightfv(GL_LIGHT0, GL_POSITION, pos); + glEnable(GL_LIGHTING); + glEnable(GL_LIGHT0); + glEnable(GL_DEPTH_TEST); + + /* With objects that have proper winding and normals set up on all + their faces, one can cull back-faces; however, these equations + generate objects that are sometimes "inside out", and determining + whether a facet has been inverted like that is really hard. + So we render both front and back faces, at a probable performance + penalty on non-accelerated systems. + + When rendering back faces, we also need to do two-sided lighting, + or the fact that the normals are flipped gives us too-dark surfaces + on the inside-out surfaces. + + This isn't generally something you'd want, because you end up + with half the lighting dynamic range (kind of.) So if you had + a sphere with correctly pointing normals, and a single light + source, it would be illuminated from two sides. In this case, + though, it saves us from a difficult and time consuming + inside/outside test. And we don't really care about a precise + lighting effect. + */ + glDisable(GL_CULL_FACE); + glLightModeli (GL_LIGHT_MODEL_TWO_SIDE, True); + } + + if (smooth_p) + { + glEnable (GL_LINE_SMOOTH); + glHint (GL_LINE_SMOOTH_HINT, GL_NICEST); + glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + glEnable (GL_BLEND); + } +} + + + +/* generate the object */ + +static XYZ +sphere_eval (double theta, double phi, int *m) +{ + double r = 0; + XYZ p; + + r += pow (sin(m[0] * phi), (double)m[1]); + r += pow (cos(m[2] * phi), (double)m[3]); + r += pow (sin(m[4] * theta),(double)m[5]); + r += pow (cos(m[6] * theta),(double)m[7]); + + p.x = r * sin(phi) * cos(theta); + p.y = r * cos(phi); + p.z = r * sin(phi) * sin(theta); + + return (p); +} + + +static void +do_color (int i, XColor *colors) +{ + GLfloat c[4]; + c[0] = colors[i].red / 65535.0; + c[1] = colors[i].green / 65535.0; + c[2] = colors[i].blue / 65535.0; + c[3] = 1.0; + glMaterialfv (GL_FRONT, GL_AMBIENT_AND_DIFFUSE, c); + glColor3f (c[0], c[1], c[2]); +} + + +static void +draw_circle (ModeInfo *mi, Bool teeth_p) +{ + GLfloat th; + int tick = 0; + GLfloat x, y; + GLfloat step = (M_PI / 180); + + glBegin(GL_LINE_LOOP); + for (th = 0; th < M_PI*2; th += step*5) + { + GLfloat r1 = 0.5; + x = cos (th); + y = sin (th); + glVertex3f(x*r1, y*r1, 0); + } + glEnd(); + + if (!teeth_p) return; + + glBegin(GL_LINES); + for (th = 0; th < M_PI*2; th += step) + { + GLfloat r1 = 0.5; + GLfloat r2 = r1 - 0.01; + if (! (tick % 10)) + r2 -= 0.02; + else if (! (tick % 5)) + r2 -= 0.01; + tick++; + + x = cos (th); + y = sin (th); + glVertex3f(x*r1, y*r1, 0); + glVertex3f(x*r2, y*r2, 0); + } + glEnd(); +} + + +static void +draw_bounding_box (ModeInfo *mi) +{ + /* spheremonics_configuration *cc = &ccs[MI_SCREEN(mi)]; */ + + static const GLfloat c1[4] = { 0.2, 0.2, 0.6, 1.0 }; + static const GLfloat c2[4] = { 1.0, 0.0, 0.0, 1.0 }; + int wire = MI_IS_WIREFRAME(mi); + + GLfloat x1,y1,z1,x2,y2,z2; + +# if 0 + x1 = cc->bbox[0].x; + y1 = cc->bbox[0].y; + z1 = cc->bbox[0].z; + x2 = cc->bbox[1].x; + y2 = cc->bbox[1].y; + z2 = cc->bbox[1].z; +# else + x1 = y1 = z1 = -0.5; + x2 = y2 = z2 = 0.5; +# endif + + if (do_bbox && !wire) + { + glMaterialfv (GL_FRONT, GL_AMBIENT_AND_DIFFUSE, c1); + glFrontFace(GL_CCW); + glEnable(GL_CULL_FACE); + + glBegin(wire ? GL_LINE_LOOP : GL_QUADS); + glNormal3f(0, 1, 0); + glVertex3f(x1, y1, z1); glVertex3f(x1, y1, z2); + glVertex3f(x2, y1, z2); glVertex3f(x2, y1, z1); + glEnd(); + glBegin(wire ? GL_LINE_LOOP : GL_QUADS); + glNormal3f(0, -1, 0); + glVertex3f(x2, y2, z1); glVertex3f(x2, y2, z2); + glVertex3f(x1, y2, z2); glVertex3f(x1, y2, z1); + glEnd(); + glBegin(wire ? GL_LINE_LOOP : GL_QUADS); + glNormal3f(0, 0, 1); + glVertex3f(x1, y1, z1); glVertex3f(x2, y1, z1); + glVertex3f(x2, y2, z1); glVertex3f(x1, y2, z1); + glEnd(); + glBegin(wire ? GL_LINE_LOOP : GL_QUADS); + glNormal3f(0, 0, -1); + glVertex3f(x1, y2, z2); glVertex3f(x2, y2, z2); + glVertex3f(x2, y1, z2); glVertex3f(x1, y1, z2); + glEnd(); + glBegin(wire ? GL_LINE_LOOP : GL_QUADS); + glNormal3f(1, 0, 0); + glVertex3f(x1, y2, z1); glVertex3f(x1, y2, z2); + glVertex3f(x1, y1, z2); glVertex3f(x1, y1, z1); + glEnd(); + glBegin(wire ? GL_LINE_LOOP : GL_QUADS); + glNormal3f(-1, 0, 0); + glVertex3f(x2, y1, z1); glVertex3f(x2, y1, z2); + glVertex3f(x2, y2, z2); glVertex3f(x2, y2, z1); + glEnd(); + glDisable(GL_CULL_FACE); + } + + if (do_grid) + { + glDisable (GL_LIGHTING); + glColor3f (c2[0], c2[1], c2[2]); + glPushMatrix(); + glBegin(GL_LINES); + glVertex3f(0, -0.66, 0); + glVertex3f(0, 0.66, 0); + glEnd(); + draw_circle (mi, True); + glRotatef(90, 1, 0, 0); + draw_circle (mi, True); + glRotatef(90, 0, 1, 0); + draw_circle (mi, True); + glPopMatrix(); + } + else + { +#if 0 + glBegin(GL_LINES); + if (x1 > 0) x1 = 0; if (x2 < 0) x2 = 0; + if (y1 > 0) y1 = 0; if (y2 < 0) y2 = 0; + if (z1 > 0) z1 = 0; if (z2 < 0) z2 = 0; + glVertex3f(x1, 0, 0); glVertex3f(x2, 0, 0); + glVertex3f(0 , y1, 0); glVertex3f(0, y2, 0); + glVertex3f(0, 0, z1); glVertex3f(0, 0, z2); + glEnd(); +#endif + } +} + + +static void +do_tracer (ModeInfo *mi) +{ + spheremonics_configuration *cc = &ccs[MI_SCREEN(mi)]; + + if (cc->tracer == -1 && + cc->mesher == -1 && + !(random() % (duration * 4))) + { + if (random() & 1) + cc->tracer = ((random() & 1) ? 0 : 180); + else + cc->mesher = ((random() % ((duration / 3) + 1)) + + (random() % ((duration / 3) + 1))); + } + + if (cc->tracer >= 0) + { + int d = (90 - cc->tracer); + GLfloat th = d * (M_PI / 180); + GLfloat x = cos (th); + GLfloat y = sin (th); + GLfloat s = 1.5 / cc->scale; + + if (s > 0.001) + { + static const GLfloat c[4] = { 0.6, 0.5, 1.0, 1.0 }; + + glDisable (GL_LIGHTING); + + glPushMatrix(); + glRotatef (90, 1, 0, 0); + glTranslatef (0, 0, y*s/2); + s *= x; + glScalef(s, s, s); + glColor3f (c[0], c[1], c[2]); + draw_circle (mi, False); + glPopMatrix(); + + if (! MI_IS_WIREFRAME(mi)) glEnable (GL_LIGHTING); + } + + cc->tracer += 5; + if (cc->tracer == 180 || cc->tracer == 360) + cc->tracer = -1; + } +} + + +static int +unit_spheremonics (ModeInfo *mi, + int resolution, Bool wire, int *m, XColor *colors) +{ + spheremonics_configuration *cc = &ccs[MI_SCREEN(mi)]; + int polys = 0; + int i, j; + double du, dv; + XYZ q[4]; + XYZ n[4]; + int res = (wire == 2 + ? resolution / 2 + : resolution); + + cc->bbox[0].x = cc->bbox[0].y = cc->bbox[0].z = 0; + cc->bbox[1].x = cc->bbox[1].y = cc->bbox[1].z = 0; + + du = (M_PI+M_PI) / (double)res; /* Theta */ + dv = M_PI / (double)res; /* Phi */ + + if (wire) + glColor3f (1, 1, 1); + + glBegin (wire ? GL_LINE_LOOP : GL_QUADS); + + for (i = 0; i < res; i++) { + double u = i * du; + for (j = 0; j < res; j++) { + double v = j * dv; + q[0] = sphere_eval (u, v, m); + n[0] = calc_normal(q[0], + sphere_eval (u+du/10, v, m), + sphere_eval (u, v+dv/10, m)); + glNormal3f(n[0].x,n[0].y,n[0].z); + if (!wire) do_color (i, colors); + glVertex3f(q[0].x,q[0].y,q[0].z); + + q[1] = sphere_eval (u+du, v, m); + n[1] = calc_normal(q[1], + sphere_eval (u+du+du/10, v, m), + sphere_eval (u+du, v+dv/10, m)); + glNormal3f(n[1].x,n[1].y,n[1].z); + if (!wire) do_color ((i+1)%res, colors); + glVertex3f(q[1].x,q[1].y,q[1].z); + + q[2] = sphere_eval (u+du, v+dv, m); + n[2] = calc_normal(q[2], + sphere_eval (u+du+du/10, v+dv, m), + sphere_eval (u+du, v+dv+dv/10, m)); + glNormal3f(n[2].x,n[2].y,n[2].z); + if (!wire) do_color ((i+1)%res, colors); + glVertex3f(q[2].x,q[2].y,q[2].z); + + q[3] = sphere_eval (u,v+dv, m); + n[3] = calc_normal(q[3], + sphere_eval (u+du/10, v+dv, m), + sphere_eval (u, v+dv+dv/10, m)); + glNormal3f(n[3].x,n[3].y,n[3].z); + if (!wire) do_color (i, colors); + glVertex3f(q[3].x,q[3].y,q[3].z); + + polys++; + +# define CHECK_BBOX(N) \ + if (q[(N)].x < cc->bbox[0].x) cc->bbox[0].x = q[(N)].x; \ + if (q[(N)].y < cc->bbox[0].y) cc->bbox[0].y = q[(N)].y; \ + if (q[(N)].z < cc->bbox[0].z) cc->bbox[0].z = q[(N)].z; \ + if (q[(N)].x > cc->bbox[1].x) cc->bbox[1].x = q[(N)].x; \ + if (q[(N)].y > cc->bbox[1].y) cc->bbox[1].y = q[(N)].y; \ + if (q[(N)].z > cc->bbox[1].z) cc->bbox[1].z = q[(N)].z + + CHECK_BBOX(0); + CHECK_BBOX(1); + CHECK_BBOX(2); + CHECK_BBOX(3); +# undef CHECK_BBOX + } + } + glEnd(); + + { + GLfloat w = cc->bbox[1].x - cc->bbox[0].x; + GLfloat h = cc->bbox[1].y - cc->bbox[0].y; + GLfloat d = cc->bbox[1].z - cc->bbox[0].z; + GLfloat wh = (w > h ? w : h); + GLfloat hd = (h > d ? h : d); + GLfloat scale = (wh > hd ? wh : hd); + + cc->scale = 1/scale; + + if (wire < 2 && (do_bbox || do_grid)) + { + GLfloat s = scale * 1.5; + glPushMatrix(); + glScalef(s, s, s); + draw_bounding_box (mi); + glPopMatrix(); + } + } + return polys; +} + + +static void +init_colors (ModeInfo *mi) +{ + spheremonics_configuration *cc = &ccs[MI_SCREEN(mi)]; + int i; + cc->ncolors = cc->resolution; + cc->colors = (XColor *) calloc(cc->ncolors, sizeof(XColor)); + make_smooth_colormap (0, 0, 0, + cc->colors, &cc->ncolors, + False, 0, False); + + /* brighter colors, please... */ + for (i = 0; i < cc->ncolors; i++) + { + cc->colors[i].red = (cc->colors[i].red / 2) + 32767; + cc->colors[i].green = (cc->colors[i].green / 2) + 32767; + cc->colors[i].blue = (cc->colors[i].blue / 2) + 32767; + } +} + + +/* Pick one of the parameters to the function and tweak it up or down. + */ +static void +tweak_parameters (ModeInfo *mi) +{ + spheremonics_configuration *cc = &ccs[MI_SCREEN(mi)]; + + /* If the -parameters command line option was specified, just use that + all the time. + */ + if (static_parms && + *static_parms && + !!strcasecmp (static_parms, "(default)")) + { + unsigned long n; + char dummy; + if (8 == sscanf (static_parms, "%d %d %d %d %d %d %d %d %c", + &cc->m[0], &cc->m[1], &cc->m[2], &cc->m[3], + &cc->m[4], &cc->m[5], &cc->m[6], &cc->m[7], + &dummy)) + return; + else if (strlen (static_parms) == 8 && + 1 == sscanf (static_parms, "%lu %c", &n, &dummy)) + { + const char *s = static_parms; + int i = 0; + while (*s) + cc->m[i++] = (*s++)-'0'; + return; + } + fprintf (stderr, + "%s: -parameters must be a string of 8 ints (not \"%s\")\n", + progname, static_parms); + exit (1); + } + + static_parms = 0; + + +# define SHIFT(N) do { \ + int n = (N); \ + cc->m[n] += cc->dm[n]; \ + if (cc->m[n] <= 0) \ + cc->m[n] = 0, cc->dm[n] = -cc->dm[n]; \ + else if (cc->m[n] >= cc->m_max) \ + cc->m[n] = cc->m_max, cc->dm[n] = -cc->dm[n]; \ + } while(0) + +/* else if (cc->m[n] >= cc->m_max/2 && (! (random() % 3))) \ + cc->m[n] = cc->m_max/2, cc->dm[n] = -cc->dm[n]; \ +*/ + + switch(random() % 8) + { + case 0: SHIFT(0); break; + case 1: SHIFT(1); break; + case 2: SHIFT(2); break; + case 3: SHIFT(3); break; + case 4: SHIFT(4); break; + case 5: SHIFT(5); break; + case 6: SHIFT(6); break; + case 7: SHIFT(7); break; + default: abort(); break; + } +# undef SHIFT + +#if 0 + printf ("%s: state: %d %d %d %d %d %d %d %d\n", + progname, + cc->m[0], cc->m[1], cc->m[2], cc->m[3], + cc->m[4], cc->m[5], cc->m[6], cc->m[7]); +#endif + +} + + +static void +generate_spheremonics (ModeInfo *mi) +{ + spheremonics_configuration *cc = &ccs[MI_SCREEN(mi)]; + int wire = MI_IS_WIREFRAME(mi); + + tweak_parameters (mi); + + if (!cc->done_once || (0 == (random() % 20))) + { + init_colors (mi); + cc->done_once = True; + } + + { + glNewList(cc->dlist, GL_COMPILE); + cc->polys1 = unit_spheremonics (mi, cc->resolution, wire,cc->m,cc->colors); + glEndList(); + + glNewList(cc->dlist2, GL_COMPILE); + glPushMatrix(); + glScalef (1.05, 1.05, 1.05); + cc->polys2 = unit_spheremonics (mi, cc->resolution, 2, cc->m, cc->colors); + glPopMatrix(); + glEndList(); + } +} + + + + +ENTRYPOINT void +init_spheremonics (ModeInfo *mi) +{ + spheremonics_configuration *cc; + + if (!ccs) { + ccs = (spheremonics_configuration *) + calloc (MI_NUM_SCREENS(mi), sizeof (spheremonics_configuration)); + if (!ccs) { + fprintf(stderr, "%s: out of memory\n", progname); + exit(1); + } + } + + cc = &ccs[MI_SCREEN(mi)]; + + if ((cc->glx_context = init_GL(mi)) != NULL) { + gl_init(mi); + reshape_spheremonics (mi, MI_WIDTH(mi), MI_HEIGHT(mi)); + } + + { + Bool spinx=False, spiny=False, spinz=False; + double spin_speed = 1.0; + double wander_speed = 0.03; + + char *s = do_spin; + while (*s) + { + if (*s == 'x' || *s == 'X') spinx = True; + else if (*s == 'y' || *s == 'Y') spiny = True; + else if (*s == 'z' || *s == 'Z') spinz = True; + else if (*s == '0') ; + else + { + fprintf (stderr, + "%s: spin must contain only the characters X, Y, or Z (not \"%s\")\n", + progname, do_spin); + exit (1); + } + s++; + } + + cc->rot = make_rotator (spinx ? spin_speed : 0, + spinz ? spin_speed : 0, + spiny ? spin_speed : 0, + 1.0, + do_wander ? wander_speed : 0, + (spinx && spiny && spinz)); + cc->trackball = gltrackball_init (); + } + + cc->tracer = -1; + cc->mesher = -1; + + cc->resolution = res; + +# ifdef HAVE_GLBITMAP + load_font (mi->dpy, "labelfont", &cc->font, &cc->font_list); +# else /* !HAVE_GLBITMAP */ + cc->font_data = load_texture_font (mi->dpy, "labelFont"); +# endif /* !HAVE_GLBITMAP */ + + cc->dlist = glGenLists(1); + cc->dlist2 = glGenLists(1); + + cc->m_max = 4; /* 9? */ + { + unsigned int i; + for (i = 0; i < countof(cc->dm); i++) + cc->dm[i] = 1; /* going up! */ + + /* Generate a few more times so we don't always start off with a sphere */ + for (i = 0; i < 5; i++) + tweak_parameters (mi); + } + + generate_spheremonics(mi); +} + + +ENTRYPOINT Bool +spheremonics_handle_event (ModeInfo *mi, XEvent *event) +{ + spheremonics_configuration *cc = &ccs[MI_SCREEN(mi)]; + + if (event->xany.type == ButtonPress && + event->xbutton.button == Button1) + { + cc->button_down_p = True; + gltrackball_start (cc->trackball, + event->xbutton.x, event->xbutton.y, + MI_WIDTH (mi), MI_HEIGHT (mi)); + return True; + } + else if (event->xany.type == ButtonRelease && + event->xbutton.button == Button1) + { + cc->button_down_p = False; + return True; + } + else if (event->xany.type == ButtonPress && + (event->xbutton.button == Button4 || + event->xbutton.button == Button5 || + event->xbutton.button == Button6 || + event->xbutton.button == Button7)) + { + gltrackball_mousewheel (cc->trackball, event->xbutton.button, 10, + !!event->xbutton.state); + return True; + } + else if (event->xany.type == KeyPress) + { + KeySym keysym; + char c = 0; + XLookupString (&event->xkey, &c, 1, &keysym, 0); + + if (c == ' ' || c == '\t' || c == '\r' || c == '\n') + { + cc->change_tick = duration; + return True; + } + } + else if (event->xany.type == MotionNotify && + cc->button_down_p) + { + gltrackball_track (cc->trackball, + event->xmotion.x, event->xmotion.y, + MI_WIDTH (mi), MI_HEIGHT (mi)); + return True; + } + + return False; +} + + +ENTRYPOINT void +draw_spheremonics (ModeInfo *mi) +{ + spheremonics_configuration *cc = &ccs[MI_SCREEN(mi)]; + Display *dpy = MI_DISPLAY(mi); + Window window = MI_WINDOW(mi); + + if (!cc->glx_context) + return; + + glXMakeCurrent(MI_DISPLAY(mi), MI_WINDOW(mi), *(cc->glx_context)); + + gl_init(mi); + + glShadeModel(GL_SMOOTH); + + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + + glPushMatrix (); + + glScalef(1.1, 1.1, 1.1); + + { + double x, y, z; + get_position (cc->rot, &x, &y, &z, !cc->button_down_p); + glTranslatef((x - 0.5) * 8, + (y - 0.5) * 6, + (z - 0.5) * 8); + + /* Do it twice because we don't track the device's orientation. */ + glRotatef( current_device_rotation(), 0, 0, 1); + gltrackball_rotate (cc->trackball); + glRotatef(-current_device_rotation(), 0, 0, 1); + + get_rotation (cc->rot, &x, &y, &z, !cc->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(7,7,7); + + mi->polygon_count = 0; + + glScalef (cc->scale, cc->scale, cc->scale); + glCallList (cc->dlist); + mi->polygon_count += cc->polys1; + + if (cc->mesher >= 0 /* || cc->button_down_p */) + { + glDisable (GL_LIGHTING); + glCallList (cc->dlist2); + mi->polygon_count += cc->polys2; + if (cc->mesher >= 0) + cc->mesher--; + } + do_tracer(mi); + + + if (cc->button_down_p) + { + char buf[200]; + sprintf (buf, + ((cc->m[0]<10 && cc->m[1]<10 && cc->m[2]<10 && cc->m[3]<10 && + cc->m[4]<10 && cc->m[5]<10 && cc->m[6]<10 && cc->m[7]<10) + ? "%d%d%d%d%d%d%d%d" + : "%d %d %d %d %d %d %d %d"), + cc->m[0], cc->m[1], cc->m[2], cc->m[3], + cc->m[4], cc->m[5], cc->m[6], cc->m[7]); + + glColor3f(1.0, 1.0, 0.0); + print_gl_string (mi->dpy, +# ifdef HAVE_GLBITMAP + cc->font, cc->font_list, +# else /* !HAVE_GLBITMAP */ + cc->font_data, +# endif /* !HAVE_GLBITMAP */ + mi->xgwa.width, mi->xgwa.height, + 10, mi->xgwa.height - 10, + buf, False); + } + + if (!static_parms) + { + if (cc->change_tick++ >= duration && !cc->button_down_p) + { + generate_spheremonics(mi); + cc->change_tick = 0; + cc->mesher = -1; /* turn off the mesh when switching objects */ + } + } + + glPopMatrix(); + + if (mi->fps_p) do_fps (mi); + glFinish(); + + glXSwapBuffers(dpy, window); +} + +XSCREENSAVER_MODULE ("Spheremonics", spheremonics) + +#endif /* USE_GL */ diff --git a/hacks/glx/spheremonics.man b/hacks/glx/spheremonics.man new file mode 100644 index 00000000..5e6f437e --- /dev/null +++ b/hacks/glx/spheremonics.man @@ -0,0 +1,92 @@ +.TH XScreenSaver 1 "" "X Version 11" +.SH NAME +spheremonics - 3d spherical harmonic shapes. +.SH SYNOPSIS +.B spheremonics +[\-display \fIhost:display.screen\fP] +[\-visual \fIvisual\fP] +[\-window] +[\-root] +[\-delay \fInumber\fP] +[\-duration \fInumber\fP] +[\-resolution \fInumber\fP] +[\-wander] +[\-no-spin] +[\-spin \fI[XYZ]\fP] +[\-wireframe] +[\-no-smooth] +[\-no-grid] +[\-bbox] +[\-fps] +.SH DESCRIPTION +These closed objects are commonly called spherical harmonics, although they +are only remotely related to the mathematical definition found in the +solution to certain wave functions, most notable the eigenfunctions of +angular momentum operators. +.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 +Duration. 5 - 1000. Default: 100. +.TP 8 +.B \-resolution \fInumber\fP +Resolution. 5 - 100. Default: 64. +.TP 8 +.B \-wander | \-no-wander +Whether the object should wander around the screen. +.TP 8 +.B \-spin \fI[XYZ]\fP +Around which axes should the object spin? +.TP 8 +.B \-no-spin +Don't spin. +.TP 8 +.B \-wireframe +Render in wireframe instead of solid. +.TP 8 +.B \-smooth | \-no-smooth +Smoothed Lines. Boolean. +.TP 8 +.B \-grid | \-no-grid +Draw Grid. Boolean. +.TP 8 +.B \-bbox | \-no-bbox +Draw Bounding Box. Boolean. +.TP 8 +.B \-fps +Display the current frame rate, CPU load, and polygon count. +.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 2002 by Paul Bourke 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 +Paul Bourke and Jamie Zawinski. diff --git a/hacks/glx/sproingies.c b/hacks/glx/sproingies.c new file mode 100644 index 00000000..0892eff8 --- /dev/null +++ b/hacks/glx/sproingies.c @@ -0,0 +1,928 @@ +/* -*- Mode: C; tab-width: 4 -*- */ +/* sproingies.c - 3D sproingies */ + +#if 0 +static const char sccsid[] = "@(#)sproingies.c 4.04 97/07/28 xlockmore"; +#endif + +/*- + * sproingies.c - Copyright 1996 by Ed Mackey, freely distributable. + * + * Permission to use, copy, modify, and distribute this software and its + * documentation for any purpose and without fee is hereby granted, + * provided that the above copyright notice appear in all copies and that + * both that copyright notice and this permission notice appear in + * supporting documentation. + * + * This file is provided AS IS with no warranties of any kind. The author + * shall have no liability with respect to the infringement of copyrights, + * trade secrets or any patents by this file or any part thereof. In no + * event will the author be liable for any lost revenue or profits or + * other special, indirect and consequential damages. + * + * Revision History: + * See sproingiewrap.c + */ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif /* HAVE_CONFIG_H */ + +#ifdef STANDALONE +# include "xlockmoreI.h" /* from the xscreensaver distribution */ +#else /* !STANDALONE */ +# include "xlock.h" /* from the xlockmore distribution */ +#endif /* !STANDALONE */ + +#ifdef USE_GL + +#ifndef HAVE_COCOA +# include +#endif + +#include "gllist.h" +#include "sproingies.h" + +#define MAXSPROING 100 +#define TARGET_COUNT 40 +#define BOOM_FRAME 50 +#define NO_FRAME (-10) +#define RESET_SPROINGIE_LIFE (-30 + myrand(28)) +#define NEW_SPROINGIE_LIFE (40 + myrand(200)) +#define JUMP_LEFT 0 +#define JUMP_RIGHT 1 + +#define FIRST_FRAME 0 +#define LAST_FRAME 5 +/*- + * The sproingies have six "real" frames, (s1_1 to s1_6) that show a + * sproingie jumping off a block, headed down and to the right. + * The frames are numbered from 0 (FIRST_FRAME) to 5 (LAST_FRAME). + * + * There are other frame numbers for special cases (e.g. BOOM_FRAME). + */ +struct sPosColor { /* Position and color of the sproingie */ + int x, y, z; /* Position */ + int frame; /* Current frame (0-5) */ + int life; /* Life points */ + GLfloat r, g, b; /* Color RGB */ + int direction; /* Direction of next hop (left or right) */ +}; + +typedef struct { + int rotx, roty, dist, wireframe, flatshade, groundlevel, + maxsproingies, mono; + int sframe, target_rx, target_ry, target_dist, target_count; + const struct gllist *sproingies[6]; + const struct gllist *SproingieBoom; + GLuint TopsSides; + struct sPosColor *positions; +} sp_instance; + +static sp_instance *si_list = NULL; +static int active_screens = 0; + +extern const struct gllist *s1_1; +extern const struct gllist *s1_2; +extern const struct gllist *s1_3; +extern const struct gllist *s1_4; +extern const struct gllist *s1_5; +extern const struct gllist *s1_6; +extern const struct gllist *s1_b; + +static int +myrand(int range) +{ + return ((int) (((float) range) * LRAND() / (MAXRAND))); +} + +static int smart_sproingies = 0; + +static GLuint +build_TopsSides(int wireframe) +{ + GLuint dl_num; + GLfloat mat_color[4] = + {0.0, 0.0, 0.0, 1.0}; + + dl_num = glGenLists(2); + if (!dl_num) + return (0); /* 0 means out of display lists. */ + + /* Surface: Tops */ + glNewList(dl_num, GL_COMPILE); + mat_color[0] = 0.392157; + mat_color[1] = 0.784314; + mat_color[2] = 0.941176; + if (wireframe) + glColor3fv(mat_color); + else { + glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, mat_color); + } + glEndList(); + + /* Surface: Sides */ + glNewList(dl_num + 1, GL_COMPILE); + if (wireframe) + glColor3fv(mat_color); + else { + /* jwz: in wireframe mode, color tops and sides the same. */ + mat_color[0] = 0.156863; + mat_color[1] = 0.156863; + mat_color[2] = 0.392157; + glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, mat_color); + } + glEndList(); + return (dl_num); +} + +static void +LayGround(int sx, int sy, int sz, int width, int height, sp_instance * si) +{ + int x, y, z, w, h; + GLenum begin_polygon; + + if (si->wireframe) + begin_polygon = GL_LINE_LOOP; + else + begin_polygon = GL_POLYGON; + + if (!si->wireframe) { + if (!si->mono) + glCallList(si->TopsSides); /* Render the tops */ + glNormal3f(0.0, 1.0, 0.0); + + for (h = 0; h < height; ++h) { + x = sx + h; + y = sy - (h << 1); + z = sz + h; + for (w = 0; w < width; ++w) { + glBegin(begin_polygon); + glVertex3i(x, y, z); + glVertex3i(x, y, z - 1); + glVertex3i(x + 1, y, z - 1); + glVertex3i(x + 1, y, z); + glEnd(); + glBegin(begin_polygon); + glVertex3i(x + 1, y - 1, z); + glVertex3i(x + 1, y - 1, z - 1); + glVertex3i(x + 2, y - 1, z - 1); + glVertex3i(x + 2, y - 1, z); + glEnd(); + ++x; + --z; + } + } + } + if (!si->mono) + glCallList(si->TopsSides + 1); /* Render the sides */ + if (!si->wireframe) + glNormal3f(0.0, 0.0, 1.0); + + for (h = 0; h < height; ++h) { + x = sx + h; + y = sy - (h << 1); + z = sz + h; + for (w = 0; w < width; ++w) { + glBegin(begin_polygon); + glVertex3i(x, y, z); + glVertex3i(x + 1, y, z); + glVertex3i(x + 1, y - 1, z); + glVertex3i(x, y - 1, z); + glEnd(); + glBegin(begin_polygon); + glVertex3i(x + 1, y - 1, z); + glVertex3i(x + 2, y - 1, z); + glVertex3i(x + 2, y - 2, z); + glVertex3i(x + 1, y - 2, z); +/*- + * PURIFY 4.0.1 reports an unitialized memory read on the next line when using + * MesaGL 2.2 and -mono. This has been fixed in MesaGL 2.3 and later. */ + glEnd(); + ++x; + --z; + } + } + + /* Render the other sides */ + if (!si->wireframe) + glNormal3f(1.0, 0.0, 0.0); + + for (h = 0; h < height; ++h) { + x = sx + h; + y = sy - (h << 1); + z = sz + h; + for (w = 0; w < width; ++w) { + glBegin(begin_polygon); + glVertex3i(x + 1, y, z); + glVertex3i(x + 1, y, z - 1); + glVertex3i(x + 1, y - 1, z - 1); + glVertex3i(x + 1, y - 1, z); + glEnd(); + glBegin(begin_polygon); + glVertex3i(x + 2, y - 1, z); + glVertex3i(x + 2, y - 1, z - 1); + glVertex3i(x + 2, y - 2, z - 1); + glVertex3i(x + 2, y - 2, z); + glEnd(); + ++x; + --z; + } + } + + if (si->wireframe) { + if (!si->mono) + glCallList(si->TopsSides); /* Render the tops */ + + for (h = 0; h < height; ++h) { + x = sx + h; + y = sy - (h << 1); + z = sz + h; + for (w = 0; w < width; ++w) { + glBegin(begin_polygon); + glVertex3i(x, y, z); + glVertex3i(x, y, z - 1); + glVertex3i(x + 1, y, z - 1); + glVertex3i(x + 1, y, z); + glEnd(); + glBegin(begin_polygon); + glVertex3i(x + 1, y - 1, z); + glVertex3i(x + 1, y - 1, z - 1); + glVertex3i(x + 2, y - 1, z - 1); + glVertex3i(x + 2, y - 1, z); + glEnd(); + ++x; + --z; + } + } + } +} + +static void +AdvanceSproingie(int t, sp_instance * si) +{ + int g_higher, g_back, t2; + struct sPosColor *thisSproingie = &(si->positions[t]); + struct sPosColor *S2 = &(si->positions[0]); + + if (thisSproingie->life > 0) { + if ((++(thisSproingie->frame)) > LAST_FRAME) { + if (thisSproingie->frame >= BOOM_FRAME) { + if ((thisSproingie->r -= 0.08) < 0.0) + thisSproingie->r = 0.0; + if ((thisSproingie->g -= 0.08) < 0.0) + thisSproingie->g = 0.0; + if ((thisSproingie->b -= 0.08) < 0.0) + thisSproingie->b = 0.0; + if ((--(thisSproingie->life)) < 1) { + thisSproingie->life = RESET_SPROINGIE_LIFE; + } + return; + } + thisSproingie->frame = FIRST_FRAME; + + /* Check for collisions */ + for (t2 = 0; t2 < si->maxsproingies; ++t2) { + if ((t2 != t) && (thisSproingie->x == S2->x) && + (thisSproingie->y == S2->y) && (thisSproingie->z == S2->z) && + (S2->life > 10) && (S2->frame < LAST_FRAME + 1)) { +#if 0 + if (thisSproingie->life > S2->life) { + S2->life = 10; + } else { +#endif + if (thisSproingie->life > 10) { + thisSproingie->life = 10; + thisSproingie->frame = BOOM_FRAME; + if ((thisSproingie->r += 0.5) > 1.0) + thisSproingie->r = 1.0; + if ((thisSproingie->g += 0.5) > 1.0) + thisSproingie->g = 1.0; + if ((thisSproingie->b += 0.5) > 1.0) + thisSproingie->b = 1.0; + } +#if 0 + } +#endif + } + ++S2; + } + } + /* Time to disappear... */ + if (!((thisSproingie->life == 10) && + (thisSproingie->frame > FIRST_FRAME) && + (thisSproingie->frame < BOOM_FRAME))) { + if ((--(thisSproingie->life)) < 1) { + thisSproingie->life = RESET_SPROINGIE_LIFE; + } else if (thisSproingie->life < 9) { + thisSproingie->frame -= 2; + } + } /* ... else wait here for frame FIRST_FRAME to come about. */ + } else if (++(thisSproingie->life) >= 0) { + if (1 || t > 1) { + g_higher = -3 + myrand(5); + g_back = -2 + myrand(5); + } else if (t == 1) { + g_higher = -2 + myrand(3); + g_back = -1 + myrand(3); + } else { + g_higher = -1; + g_back = 0; + } + + thisSproingie->x = (-g_higher - g_back); + thisSproingie->y = (g_higher << 1); + thisSproingie->z = (g_back - g_higher); + thisSproingie->life = NEW_SPROINGIE_LIFE; + thisSproingie->frame = NO_FRAME; + thisSproingie->r = (GLfloat) (40 + myrand(200)) / 255.0; + thisSproingie->g = (GLfloat) (40 + myrand(200)) / 255.0; + thisSproingie->b = (GLfloat) (40 + myrand(200)) / 255.0; + + for (t2 = 0; t2 < si->maxsproingies; ++t2) { + if ((t2 != t) && (thisSproingie->x == S2->x) && + (thisSproingie->y == S2->y) && (thisSproingie->z == S2->z) && + (S2->life > 10) && (S2->frame < FIRST_FRAME)) { + /* If another is already on this place, wait. */ + thisSproingie->life = -1; + } + ++S2; + } + } +} + +static void +NextSproingie(int screen) +{ + sp_instance *si = &si_list[screen]; + int ddx, t; + struct sPosColor *thisSproingie = &(si->positions[0]); + + /* Although the sproingies cycle has six frames, the blocks cycle */ + /* has twelve. After a full cycle (12 frames), re-center positions */ + /* of sproingies */ + if (++si->sframe > 11) { + si->sframe = FIRST_FRAME; + for (t = 0; t < si->maxsproingies; ++t) { + thisSproingie->x -= 1; + thisSproingie->y += 2; + thisSproingie->z -= 1; + ++thisSproingie; + } + } + + for (t = 0; t < si->maxsproingies; ++t) { + AdvanceSproingie(t, si); + } + + if (si->target_count < 0) { /* track to current target */ + if (si->target_rx < si->rotx) + --si->rotx; + else if (si->target_rx > si->rotx) + ++si->rotx; + + if (si->target_ry < si->roty) + --si->roty; + else if (si->target_ry > si->roty) + ++si->roty; + + ddx = (si->target_dist - si->dist) / 8; + if (ddx) + si->dist += ddx; + else if (si->target_dist < si->dist) + --si->dist; + else if (si->target_dist > si->dist) + ++si->dist; + + if ((si->target_rx == si->rotx) && (si->target_ry == si->roty) && + (si->target_dist == si->dist)) { + si->target_count = TARGET_COUNT; + if (si->target_dist <= 32) + si->target_count >>= 2; + } + } else if (--si->target_count < 0) { /* make up new target */ + si->target_rx = myrand(100) - 35; + si->target_ry = -myrand(90); + si->target_dist = 32 << myrand(2); /* could be 32, 64, or 128, (previously or 256) */ + + if (si->target_dist >= si->dist) /* no duplicate distances */ + si->target_dist <<= 1; + } + /* Otherwise just hang loose for a while here */ +} + +#ifdef __AUXFUNCS__ +void +PrintEm(void) +{ + int t, count = 0; + + for (t = 0; t < maxsproingies; ++t) { + if (positions[t].life > 0) + ++count; + } + (void) printf("RotX: %d, RotY: %d, Dist: %d. Targets: X %d, Y %d, D %d. Visible: %d\n", + rotx, roty, dist, target_rx, target_ry, target_dist, count); +} + +void +ResetEm(void) +{ + int t; + + for (t = 0; t < maxsproingies; ++t) { + positions[t].x = 0; + positions[t].y = 0; + positions[t].z = 0; + positions[t].life = -2; + positions[t].frame = FIRST_FRAME; + } +} + +void +distAdd(void) +{ + if (dist < (1 << 16 << 4)) + dist <<= 1; +} + +void +distSubtract(void) +{ + if (dist > 1) + dist >>= 1; +} + +void +rotxAdd(void) +{ + rotx = (rotx + 5) % 360; +} + +void +rotxSubtract(void) +{ + rotx = (rotx - 5) % 360; +} + +void +rotyAdd(void) +{ + roty = (roty + 5) % 360; +} + +void +rotySubtract(void) +{ + roty = (roty - 5) % 360; +} + +void +rotxBAdd(void) +{ + rotx = (rotx + 45) % 360; +} + +void +rotxBSubtract(void) +{ + rotx = (rotx - 45) % 360; +} + +void +rotyBAdd(void) +{ + roty = (roty + 45) % 360; +} + +void +rotyBSubtract(void) +{ + roty = (roty - 45) % 360; +} + +#endif /* __AUXFUNCS__ */ + +static void +RenderSproingie(int t, sp_instance * si) +{ + GLfloat scale, pointsize, mat_color[4] = + {0.0, 0.0, 0.0, 1.0}; +#ifndef HAVE_JWZGLES + GLdouble clipplane[4] = + {0.0, 1.0, 0.0, 0.0}; +#endif + struct sPosColor *thisSproingie = &(si->positions[t]); + + if (thisSproingie->life < 1) + return; + + glPushMatrix(); + + if (!si->mono) { + mat_color[0] = thisSproingie->r; + mat_color[1] = thisSproingie->g; + mat_color[2] = thisSproingie->b; + if (si->wireframe) + glColor3fv(mat_color); + else { + glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, mat_color); + } + } + + if (thisSproingie->frame < FIRST_FRAME) { + glEnable(GL_CLIP_PLANE0); + glTranslatef((GLfloat) (thisSproingie->x), + (GLfloat) (thisSproingie->y) + + ((GLfloat) (thisSproingie->frame) / 9.0), + (GLfloat) (thisSproingie->z)); + +#ifndef HAVE_JWZGLES + /* OpenGLES doesn't have this but it doesn't seem to matter */ + clipplane[3] = ((GLdouble) (thisSproingie->frame) / 9.0) + + (si->wireframe ? 0.0 : 0.1); + glClipPlane(GL_CLIP_PLANE0, clipplane); +#endif + +/** glCallList(si->sproingies[0]);*/ +/**/ renderList(si->sproingies[0], si->wireframe); + glDisable(GL_CLIP_PLANE0); + } else if (thisSproingie->frame >= BOOM_FRAME) { + glTranslatef((GLfloat) (thisSproingie->x) + 0.5, + (GLfloat) (thisSproingie->y) + 0.5, + (GLfloat) (thisSproingie->z) - 0.5); + scale = (GLfloat) (1 << (thisSproingie->frame - BOOM_FRAME)); + glScalef(scale, scale, scale); + if (!si->wireframe) { + if (!si->mono) + glColor3fv(mat_color); + glDisable(GL_LIGHTING); + } + pointsize = (GLfloat) ((BOOM_FRAME + 8) - thisSproingie->frame) - + (si->dist / 64.0); + glPointSize((pointsize < 1.0) ? 1.0 : pointsize); +/*- + * PURIFY 4.0.1 reports an unitialized memory read on the next line when using + * MesaGL 2.2. This has been tracked to MesaGL 2.2 src/points.c line 313. */ +/** glCallList(si->SproingieBoom);*/ +/**/ renderList(si->SproingieBoom, si->wireframe); + glPointSize(1.0); + if (!si->wireframe) { + glEnable(GL_LIGHTING); + } + } else { + if (thisSproingie->direction == JUMP_LEFT) { + /* When the sproingie jumps to the left, the frames must be */ + /* rotated and translated */ + glTranslatef((GLfloat) (thisSproingie->x ), + (GLfloat) (thisSproingie->y ), + (GLfloat) (thisSproingie->z - 1)); + glRotatef((GLfloat) - 90.0, 0.0, 1.0, 0.0); + if (thisSproingie->frame == LAST_FRAME) { + thisSproingie->x -= 0; + thisSproingie->y -= 1; + thisSproingie->z += 1; + } + } else { + glTranslatef((GLfloat) (thisSproingie->x), + (GLfloat) (thisSproingie->y), + (GLfloat) (thisSproingie->z)); + glRotatef((GLfloat) - 0.0, 0.0, 1.0, 0.0); + if (thisSproingie->frame == LAST_FRAME) { + thisSproingie->x += 1; + thisSproingie->y -= 1; + thisSproingie->z -= 0; + } + } +/* } */ +/** glCallList(si->sproingies[thisSproingie->frame]);*/ +/**/ renderList(si->sproingies[thisSproingie->frame], si->wireframe); + + /* Every 6 frame cycle... */ + if (thisSproingie->frame == LAST_FRAME) { + /* ...check if the sproingies have gone out of the bricks */ + if (((thisSproingie->x - thisSproingie->z == 6) && + (2*thisSproingie->x + thisSproingie->y == 6)) || + ((thisSproingie->z - thisSproingie->x == 5) && + (2*thisSproingie->x + thisSproingie->y == -5))) { + /* If they have, then they die */ + if (thisSproingie->life > 0 && thisSproingie->frame < BOOM_FRAME && thisSproingie->frame > FIRST_FRAME) { + thisSproingie->frame = BOOM_FRAME; + } + } else { + /* If not, they choose a direction for the next hop */ + if (smart_sproingies) { + if ((thisSproingie->x - thisSproingie->z == 5) && + (2*thisSproingie->x + thisSproingie->y == 5)) { + thisSproingie->direction = JUMP_LEFT; + } else if ((thisSproingie->z - thisSproingie->x == 4) && + (2*thisSproingie->x + thisSproingie->y == -4)) { + thisSproingie->direction = JUMP_RIGHT; + } else { + thisSproingie->direction = myrand(2); + } + } else { + thisSproingie->direction = myrand(2); + } + } + } + } + + glPopMatrix(); + +} + +static void +ComputeGround(sp_instance * si) +{ + int g_higher, g_back, g_width, g_height; + + /* higher: x-1, y+2, z-1 */ + /* back: x-1, y, z+1 */ + + if (si->groundlevel == 0) { + g_back = 2; + g_width = 5; + } else if (si->groundlevel == 1) { + g_back = 4; + g_width = 8; + } else { + g_back = 8; + g_width = 16; + } + + if ((g_higher = si->dist >> 3) < 4) + g_higher = 4; + if (g_higher > 16) + g_higher = 16; + g_height = g_higher << 1; + + if (si->rotx < -10) + g_higher += (g_higher >> 2); + else if (si->rotx > 10) + g_higher -= (g_higher >> 2); + +#if 0 + if (si->dist > 128) { + ++g_higher; + ++g_back; + g_back <<= 1; + } else if (si->dist > 64) { + ++g_higher; + ++g_back; + } else if (si->dist > 32) { + /* nothing special */ + } else { + if (g_higher > 2) { + g_higher = g_back = 4; + } + } +#endif + + /* startx, starty, startz, width, height */ + LayGround((-g_higher - g_back), (g_higher << 1), (g_back - g_higher), + (g_width), (g_height), si); +} + +void +DisplaySproingies(int screen,int pause) +{ + sp_instance *si = &si_list[screen]; + int t; + GLfloat position[] = + {8.0, 5.0, -2.0, 0.1}; + + if (si->wireframe) + glClear(GL_COLOR_BUFFER_BIT); + else + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + + glPushMatrix(); + glTranslatef(0.0, 0.0, -(GLfloat) (si->dist) / 16.0); /* viewing transform */ + glRotatef((GLfloat) si->rotx, 1.0, 0.0, 0.0); + glRotatef((GLfloat) si->roty, 0.0, 1.0, 0.0); + + if (!si->wireframe) + glLightfv(GL_LIGHT0, GL_POSITION, position); + +#if 0 /* Show light pos */ + glPushMatrix(); + glTranslatef(position[0], position[1], position[2]); + glColor3f(1.0, 1.0, 1.0); + if (!si->wireframe) { + glDisable(GL_LIGHTING); + } + glCallList(si->SproingieBoom); + if (!si->wireframe) { + glEnable(GL_LIGHTING); + } + glPopMatrix(); +#endif + + glTranslatef((GLfloat) si->sframe * (-1.0 / 12.0) - 0.75, + (GLfloat) si->sframe * (2.0 / 12.0) - 0.5, + (GLfloat) si->sframe * (-1.0 / 12.0) + 0.75); + + if (si->wireframe) + ComputeGround(si); + + for (t = 0; t < si->maxsproingies; ++t) { + RenderSproingie(t, si); + } + + if (!si->wireframe) + ComputeGround(si); + + glPopMatrix(); + glFlush(); +} + +void +NextSproingieDisplay(int screen,int pause) +{ + NextSproingie(screen); +/* if (pause) usleep(pause); don't do this! -jwz */ + DisplaySproingies(screen,pause); +} + +void +ReshapeSproingies(int w, int h) +{ + glViewport(0, 0, w, h); + glMatrixMode(GL_PROJECTION); + glLoadIdentity(); + gluPerspective(65.0, (GLfloat) w / (GLfloat) h, 0.1, 2000.0); /* was 200000.0 */ + glMatrixMode(GL_MODELVIEW); + glLoadIdentity(); +} + +void +CleanupSproingies(int screen) +{ + sp_instance *si = &si_list[screen]; +/* + int t; + if (si->SproingieBoom) { + for (t = 0; t < 6; ++t) + glDeleteLists(si->sproingies[t], 1); + + glDeleteLists(si->TopsSides, 2); + glDeleteLists(si->SproingieBoom, 1); + + --active_screens; + si->SproingieBoom = 0; + } +*/ + if (si->TopsSides) { + glDeleteLists(si->TopsSides, 2); + } + if (si->positions) { + (void) free((void *) (si->positions)); + si->positions = NULL; + } + if ((active_screens == 0) && si_list) { + (void) free((void *) (si_list)); + si_list = NULL; + } +} + +void +InitSproingies(int wfmode, int grnd, int mspr, int smrtspr, + int screen, int numscreens, int mono) +{ + GLfloat ambient[] = + {0.2, 0.2, 0.2, 1.0}; + GLfloat position[] = + {10.0, 1.0, 1.0, 10.0}; + GLfloat mat_diffuse[] = + {0.6, 0.6, 0.6, 1.0}; + GLfloat mat_specular[] = + {0.8, 0.8, 0.8, 1.0}; + GLfloat mat_shininess[] = + {50.0}; + + sp_instance *si; + int t; + + if (si_list == NULL) { + if ((si_list = (sp_instance *) calloc(numscreens, + sizeof (sp_instance))) == NULL) + return; + } + si = &si_list[screen]; + + active_screens++; + CleanupSproingies(screen); + + if (mspr < 0) + mspr = 0; + if (mspr >= MAXSPROING) + mspr = MAXSPROING - 1; + + smart_sproingies = smrtspr; + + si->rotx = 0; + si->roty = -45; + si->dist = (16 << 2); + si->sframe = 0; + si->target_count = 0; + si->mono = mono; + + si->wireframe = si->flatshade = 0; + + if (wfmode == 2) + si->flatshade = 1; + else if (wfmode) + si->wireframe = 1; + + si->groundlevel = grnd; + si->maxsproingies = mspr; + + if (si->maxsproingies) { + si->positions = (struct sPosColor *) calloc(si->maxsproingies, + sizeof (struct sPosColor)); + + if (!(si->positions)) + si->maxsproingies = 0; + } + for (t = 0; t < si->maxsproingies; ++t) { + si->positions[t].x = 0; + si->positions[t].y = 0; + si->positions[t].z = 0; + si->positions[t].life = (-t * ((si->maxsproingies > 19) ? 1 : 4)) - 2; + si->positions[t].frame = FIRST_FRAME; + si->positions[t].direction = myrand(2); + } + +#if 0 /* Test boom */ + si->positions[0].x = 0; + si->positions[0].y = 0; + si->positions[0].z = 0; + si->positions[0].life = 10; + si->positions[0].frame = BOOM_FRAME; + si->positions[0].r = 0.656863; + si->positions[0].g = 1.0; + si->positions[0].b = 0.656863; +#endif + + if (!(si->TopsSides = build_TopsSides(si->wireframe))) + (void) fprintf(stderr, "build_TopsSides\n"); +/* + if (!(si->sproingies[0] = BuildLWO(si->wireframe, &LWO_s1_1))) + (void) fprintf(stderr, "BuildLWO - 1\n"); + if (!(si->sproingies[1] = BuildLWO(si->wireframe, &LWO_s1_2))) + (void) fprintf(stderr, "BuildLWO - 2\n"); + if (!(si->sproingies[2] = BuildLWO(si->wireframe, &LWO_s1_3))) + (void) fprintf(stderr, "BuildLWO - 3\n"); + if (!(si->sproingies[3] = BuildLWO(si->wireframe, &LWO_s1_4))) + (void) fprintf(stderr, "BuildLWO - 4\n"); + if (!(si->sproingies[4] = BuildLWO(si->wireframe, &LWO_s1_5))) + (void) fprintf(stderr, "BuildLWO - 5\n"); + if (!(si->sproingies[5] = BuildLWO(si->wireframe, &LWO_s1_6))) + (void) fprintf(stderr, "BuildLWO - 6\n"); + + if (!(si->SproingieBoom = BuildLWO(si->wireframe, &LWO_s1_b))) + (void) fprintf(stderr, "BuildLWO - b\n"); +*/ + si->sproingies[0]=s1_1; + si->sproingies[1]=s1_2; + si->sproingies[2]=s1_3; + si->sproingies[3]=s1_4; + si->sproingies[4]=s1_5; + si->sproingies[5]=s1_6; + si->SproingieBoom=s1_b; + + if (si->wireframe) { + glShadeModel(GL_FLAT); + glDisable(GL_LIGHTING); + } else { + if (si->flatshade) { + glShadeModel(GL_FLAT); + position[0] = 1.0; + position[3] = 0.0; + } + glEnable(GL_LIGHTING); + glEnable(GL_LIGHT0); + glDepthFunc(GL_LEQUAL); + glEnable(GL_DEPTH_TEST); + + glLightfv(GL_LIGHT0, GL_AMBIENT, ambient); + glLightfv(GL_LIGHT0, GL_POSITION, position); + + glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, mat_diffuse); + glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, mat_specular); + glMaterialfv(GL_FRONT_AND_BACK, GL_SHININESS, mat_shininess); + + /* glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, GL_FALSE); */ + glCullFace(GL_BACK); + glEnable(GL_CULL_FACE); + + glFrontFace(GL_CW); + /* glEnable(GL_NORMALIZE); */ + } +} + +#endif /* USE_GL */ + +/* End of sproingies.c */ + diff --git a/hacks/glx/sproingies.h b/hacks/glx/sproingies.h new file mode 100644 index 00000000..81c6cb7e --- /dev/null +++ b/hacks/glx/sproingies.h @@ -0,0 +1,25 @@ +/*- + * sproingies.c - Copyright 1996 by Ed Mackey, freely distributable. + * + * Permission to use, copy, modify, and distribute this software and its + * documentation for any purpose and without fee is hereby granted, + * provided that the above copyright notice appear in all copies and that + * both that copyright notice and this permission notice appear in + * supporting documentation. + * + * This file is provided AS IS with no warranties of any kind. The author + * shall have no liability with respect to the infringement of copyrights, + * trade secrets or any patents by this file or any part thereof. In no + * event will the author be liable for any lost revenue or profits or + * other special, indirect and consequential damages. + * + * Revision History: + * See sproingiewrap.c + */ + +extern void DisplaySproingies(int screen,int pause); +extern void NextSproingieDisplay(int screen,int pause); +extern void ReshapeSproingies(int w, int h); +extern void CleanupSproingies(int screen); +extern void InitSproingies(int wfmode, int grnd, int mspr, int smrtspr, + int screen, int numscreens, int mono); diff --git a/hacks/glx/sproingies.man b/hacks/glx/sproingies.man new file mode 100644 index 00000000..5150fca5 --- /dev/null +++ b/hacks/glx/sproingies.man @@ -0,0 +1,68 @@ +.TH XScreenSaver 1 "" "X Version 11" +.SH NAME +sproingies - Q-Bert meets Marble Madness! +.SH SYNOPSIS +.B sproingies +[\-display \fIhost:display.screen\fP] +[\-visual \fIvisual\fP] +[\-window] +[\-root] +[\-count \fInumber\fP] +[\-delay \fInumber\fP] +[\-size \fInumber\fP] +[\-no\-fall] +[\-wireframe] +[\-fps] +.SH DESCRIPTION +Q-Bert meets Marble Madness! +.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 \-count \fInumber\fP +How many sproingies to draw at once. Default: 5. +.TP 8 +.B \-delay \fInumber\fP +Per-frame delay, in microseconds. Default: 25000 (0.03 seconds.). +.TP 8 +.B \-size \fInumber\fP +How much to scale the image down. Default 0 (full screen.) +.TP 8 +.B \-no\-fall +Make sproingies "smart", so they do not fall down the edge. +.TP 8 +.B \-wireframe +Render in wireframe instead of solid. +.TP 8 +.B \-fps +Display the current frame rate, CPU load, and polygon count. +.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 2002 by Ed Mackey. 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 +Ed Mackey. Some additional code by Sergio Gutiérrez "Sergut". diff --git a/hacks/glx/sproingiewrap.c b/hacks/glx/sproingiewrap.c new file mode 100644 index 00000000..402b9103 --- /dev/null +++ b/hacks/glx/sproingiewrap.c @@ -0,0 +1,252 @@ +/* -*- Mode: C; tab-width: 4 -*- */ +/* sproingiewrap.c - sproingies wrapper */ + +#if 0 +static const char sccsid[] = "@(#)sproingiewrap.c 4.07 97/11/24 xlockmore"; +#endif + +/*- + * sproingiewrap.c - Copyright 1996 Sproingie Technologies Incorporated. + * + * Permission to use, copy, modify, and distribute this software and its + * documentation for any purpose and without fee is hereby granted, + * provided that the above copyright notice appear in all copies and that + * both that copyright notice and this permission notice appear in + * supporting documentation. + * + * This file is provided AS IS with no warranties of any kind. The author + * shall have no liability with respect to the infringement of copyrights, + * trade secrets or any patents by this file or any part thereof. In no + * event will the author be liable for any lost revenue or profits or + * other special, indirect and consequential damages. + * + * Programming: Ed Mackey, http://www.netaxs.com/~emackey/ + * Gordon Wrigley, gdw33@student.canterbury.ac.nz + * Sergio Gutiérrez "Sergut", sergut@gmail.com + * Sproingie 3D objects modeled by: Al Mackey, al@iam.com + * (using MetaNURBS in NewTek's Lightwave 3D v5). + * + * Revision History: + * 01-Sep-06: Make the sproingies select a new direction after each hop + * (6 frames); if they fall towards the edge, they explode. + * (TODO: let them fall for a time before they explode or + * disappear) [sergut] + * 13-Dec-02: Changed triangle normals into vertex normals to give a smooth + * apperance and moved the sproingies from Display Lists to + * Vertex Arrays, still need to do this for the TopsSides. + * [gordon] + * 26-Apr-97: Added glPointSize() calls around explosions, plus other fixes. + * 28-Mar-97: Added size support. + * 22-Mar-97: Updated to use glX interface instead of xmesa one. + * Also, support for multiscreens added. + * 20-Mar-97: Updated for xlockmore v4.02alpha7 and higher, using + * xlockmore's built-in Mesa/OpenGL support instead of + * my own. Submitted for inclusion in xlockmore. + * 09-Dec-96: Written. + */ + +#ifdef STANDALONE +# define DEFAULTS "*delay: 30000 \n" \ + "*count: 8 \n" \ + "*size: 0 \n" \ + "*showFPS: False \n" \ + "*fpsTop: True \n" \ + "*wireframe: False \n" + +# define refresh_sproingies 0 +# define sproingies_handle_event 0 +# include "xlockmore.h" /* from the xscreensaver distribution */ +#else /* !STANDALONE */ +# include "xlock.h" /* from the xlockmore distribution */ +#endif /* !STANDALONE */ + +#ifdef USE_GL + +#define DEF_SMART_SPROINGIES "True" /* Smart sproingies do not fall down the edge */ + +#include "sproingies.h" + +#undef countof +#define countof(x) (sizeof((x))/sizeof((*x))) + +static XrmOptionDescRec opts[] = { + {"-fall", ".smartSproingies", XrmoptionNoArg, "False"}, + {"-no-fall", ".smartSproingies", XrmoptionNoArg, "True"}, +}; + +static int smrt_spr; + +static argtype vars[] = { + {&smrt_spr, "smartSproingies", "Boolean", DEF_SMART_SPROINGIES, t_Bool}, +}; + +ENTRYPOINT ModeSpecOpt sproingies_opts = +{countof(opts), opts, countof(vars), vars, NULL}; + +#ifdef USE_MODULES +ModStruct sproingies_description = +{"sproingies", "init_sproingies", "draw_sproingies", "release_sproingies", + "refresh_sproingies", "init_sproingies", NULL, &sproingies_opts, + 1000, 5, 0, 400, 4, 1.0, "", + "Shows Sproingies! Nontoxic. Safe for pets and small children", 0, NULL}; + +#endif + +#define MINSIZE 32 + +#include + +void NextSproingie(int screen); +void NextSproingieDisplay(int screen,int pause); +void DisplaySproingies(int screen,int pause); +void ReshapeSproingies(int w, int h); +void CleanupSproingies(int screen); +void InitSproingies(int wfmode, int grnd, int mspr, int smrtspr, + int screen, int numscreens, int mono); + +typedef struct { + GLfloat view_rotx, view_roty, view_rotz; + GLint gear1, gear2, gear3; + GLfloat angle; + GLuint limit; + GLuint count; + GLXContext *glx_context; + int mono; + Window window; +} sproingiesstruct; + +static sproingiesstruct *sproingies = NULL; + + +ENTRYPOINT void +init_sproingies (ModeInfo * mi) +{ + Window window = MI_WINDOW(mi); + int screen = MI_SCREEN(mi); + + int count = MI_COUNT(mi); + int size = MI_SIZE(mi); + + sproingiesstruct *sp; + int wfmode = 0, grnd = 0, mspr, w, h; + + if (sproingies == NULL) { + if ((sproingies = (sproingiesstruct *) calloc(MI_NUM_SCREENS(mi), + sizeof (sproingiesstruct))) == NULL) + return; + } + sp = &sproingies[screen]; + + sp->mono = (MI_IS_MONO(mi) ? 1 : 0); + sp->window = window; + if ((sp->glx_context = init_GL(mi)) != NULL) { + + if (MI_IS_WIREFRAME(mi)) + wfmode = 1; + + if (grnd > 2) + grnd = 2; + + mspr = count; + if (mspr > 100) + mspr = 100; + + /* wireframe, ground, maxsproingies */ + InitSproingies(wfmode, grnd, mspr, smrt_spr, MI_SCREEN(mi), MI_NUM_SCREENS(mi), sp->mono); + + /* Viewport is specified size if size >= MINSIZE && size < screensize */ + if (size == 0) { + w = MI_WIDTH(mi); + h = MI_HEIGHT(mi); + } else if (size < MINSIZE) { + w = MINSIZE; + h = MINSIZE; + } else { + w = (size > MI_WIDTH(mi)) ? MI_WIDTH(mi) : size; + h = (size > MI_HEIGHT(mi)) ? MI_HEIGHT(mi) : size; + } + + glViewport((MI_WIDTH(mi) - w) / 2, (MI_HEIGHT(mi) - h) / 2, w, h); + glMatrixMode(GL_PROJECTION); + glLoadIdentity(); + gluPerspective(65.0, (GLfloat) w / (GLfloat) h, 0.1, 2000.0); /* was 200000.0 */ + glMatrixMode(GL_MODELVIEW); + glLoadIdentity(); + + DisplaySproingies(MI_SCREEN(mi),mi->pause); + + } else { + MI_CLEARWINDOW(mi); + } +} + +/* ARGSUSED */ +ENTRYPOINT void +draw_sproingies (ModeInfo * mi) +{ + sproingiesstruct *sp = &sproingies[MI_SCREEN(mi)]; + Display *display = MI_DISPLAY(mi); + Window window = MI_WINDOW(mi); + + if (!sp->glx_context) + return; + + glDrawBuffer(GL_BACK); + glXMakeCurrent(display, window, *(sp->glx_context)); + + glPushMatrix(); + glRotatef(current_device_rotation(), 0, 0, 1); + NextSproingieDisplay(MI_SCREEN(mi),mi->pause); /* It will swap. */ + glPopMatrix(); + + if (mi->fps_p) do_fps (mi); + glFinish(); + glXSwapBuffers(MI_DISPLAY(mi), MI_WINDOW(mi)); +} + +#ifndef STANDALONE +ENTRYPOINT void +refresh_sproingies(ModeInfo * mi) +{ + /* No need to do anything here... The whole screen is updated + * every frame anyway. Otherwise this would be just like + * draw_sproingies, above, but replace NextSproingieDisplay(...) + * with DisplaySproingies(...). + */ +} +#endif /* !STANDALONE */ + +ENTRYPOINT void +reshape_sproingies (ModeInfo *mi, int w, int h) +{ + ReshapeSproingies(w, h); +} + + +ENTRYPOINT void +release_sproingies (ModeInfo * mi) +{ + if (sproingies != NULL) { + int screen; + + for (screen = 0; screen < MI_NUM_SCREENS(mi); screen++) { + sproingiesstruct *sp = &sproingies[screen]; + + if (sp->glx_context) { + + glXMakeCurrent(MI_DISPLAY(mi), sp->window, *(sp->glx_context)); + CleanupSproingies(MI_SCREEN(mi)); + } + } + + (void) free((void *) sproingies); + sproingies = NULL; + } + FreeAllGL(mi); +} + +XSCREENSAVER_MODULE ("Sproingies", sproingies) + +#endif /* USE_GL */ + +/* End of sproingiewrap.c */ diff --git a/hacks/glx/stairs.c b/hacks/glx/stairs.c new file mode 100644 index 00000000..b300ee13 --- /dev/null +++ b/hacks/glx/stairs.c @@ -0,0 +1,627 @@ +/* -*- Mode: C; tab-width: 4 -*- */ +/* stairs --- Infinite Stairs, and Escher-like scene. */ + +#if 0 +static const char sccsid[] = "@(#)stairs.c 4.07 97/11/24 xlockmore"; +#endif + +/*- + * Permission to use, copy, modify, and distribute this software and its + * documentation for any purpose and without fee is hereby granted, + * provided that the above copyright notice appear in all copies and that + * both that copyright notice and this permission notice appear in + * supporting documentation. + * + * This file is provided AS IS with no warranties of any kind. The author + * shall have no liability with respect to the infringement of copyrights, + * trade secrets or any patents by this file or any part thereof. In no + * event will the author be liable for any lost revenue or profits or + * other special, indirect and consequential damages. + * + * This mode shows some interesting scenes that are impossible OR very + * weird to build in the real universe. Much of the scenes are inspirated + * on Mauritz Cornelis stairs's works which derivated the mode's name. + * M.C. Escher (1898-1972) was a dutch artist and many people prefer to + * say he was a mathematician. + * + * Thanks goes to Brian Paul for making it possible and inexpensive to use + * OpenGL at home. + * + * Since I'm not a native English speaker, my apologies for any grammatical + * mistake. + * + * My e-mail address is + * m-vianna@usa.net + * + * Marcelo F. Vianna (Jun-01-1997) + * + * Revision History: + * 07-Jan-98: This would be a scene for the escher mode, but now escher mode + * was splitted in different modes for each scene. This is the + * initial release and is not working yet. + * Marcelo F. Vianna. + * + */ + +/*- + * Texture mapping is only available on RGBA contexts, Mono and color index + * visuals DO NOT support texture mapping in OpenGL. + * + * BUT Mesa do implements RGBA contexts in pseudo color visuals, so texture + * mapping shuld work on PseudoColor, DirectColor, TrueColor using Mesa. Mono + * is not officially supported for both OpenGL and Mesa, but seems to not crash + * Mesa. + * + * In real OpenGL, PseudoColor DO NOT support texture map (as far as I know). + */ + +#ifdef STANDALONE +# define DEFAULTS "*delay: 20000 \n" \ + "*showFPS: False \n" + +# define refresh_stairs 0 +# include "xlockmore.h" /* from the xscreensaver distribution */ +#else /* !STANDALONE */ +# include "xlock.h" /* from the xlockmore distribution */ + +#endif /* !STANDALONE */ + +#ifdef USE_GL + +#if 0 +#include "e_textures.h" +#else +#include "xpm-ximage.h" +#include "../images/wood.xpm" +#endif + +#include "sphere.h" +#include "gltrackball.h" + +ENTRYPOINT ModeSpecOpt stairs_opts = +{0, NULL, 0, NULL, NULL}; + +#ifdef USE_MODULES +ModStruct stairs_description = +{"stairs", "init_stairs", "draw_stairs", "release_stairs", + "draw_stairs", "change_stairs", NULL, &stairs_opts, + 1000, 1, 1, 1, 4, 1.0, "", + "Shows Infinite Stairs, an Escher-like scene", 0, NULL}; + +#endif + +#define Scale4Window 0.3 +#define Scale4Iconic 0.4 + +#define sqr(A) ((A)*(A)) + +#ifndef Pi +#define Pi M_PI +#endif + +/*************************************************************************/ + +typedef struct { + GLint WindH, WindW; + GLfloat step; + int rotating; + int AreObjectsDefined[1]; + int sphere_position; + int sphere_tick; + GLXContext *glx_context; + trackball_state *trackball; + Bool button_down_p; + GLuint objects; +} stairsstruct; + +static const float front_shininess[] = {60.0}; +static const float front_specular[] = {0.7, 0.7, 0.7, 1.0}; +static const float ambient[] = {0.0, 0.0, 0.0, 1.0}; +static const float diffuse[] = {1.0, 1.0, 1.0, 1.0}; +static const float position0[] = {1.0, 1.0, 1.0, 0.0}; +static const float position1[] = {-1.0, -1.0, 1.0, 0.0}; +static const float lmodel_ambient[] = {0.5, 0.5, 0.5, 1.0}; +static const float lmodel_twoside[] = {GL_TRUE}; + +static const float MaterialYellow[] = {0.7, 0.7, 0.0, 1.0}; +static const float MaterialWhite[] = {0.7, 0.7, 0.7, 1.0}; + +static const float ball_positions[] = { + -3.0, 3.0, 1.0, + -3.0, 2.8, 2.0, + -3.0, 2.6, 3.0, + + -2.0, 2.4, 3.0, + -1.0, 2.2, 3.0, + 0.0, 2.0, 3.0, + 1.0, 1.8, 3.0, + 2.0, 1.6, 3.0, + + 2.0, 1.5, 2.0, + 2.0, 1.4, 1.0, + 2.0, 1.3, 0.0, + 2.0, 1.2, -1.0, + 2.0, 1.1, -2.0, + + 1.0, 0.9, -2.0, + 0.0, 0.7, -2.0, + -1.0, 0.5, -2.0, +}; + +#define NPOSITIONS ((sizeof ball_positions) / (sizeof ball_positions[0]) / 3) +#define SPHERE_TICKS 32 + +static stairsstruct *stairs = NULL; + +static int +draw_block(GLfloat width, GLfloat height, GLfloat thickness) +{ + int polys = 0; + glFrontFace(GL_CCW); + glBegin(GL_QUADS); + glNormal3f(0, 0, 1); + glTexCoord2f(0, 0); + glVertex3f(-width, -height, thickness); + glTexCoord2f(1, 0); + glVertex3f(width, -height, thickness); + glTexCoord2f(1, 1); + glVertex3f(width, height, thickness); + glTexCoord2f(0, 1); + glVertex3f(-width, height, thickness); + polys++; + glNormal3f(0, 0, -1); + glTexCoord2f(0, 0); + glVertex3f(-width, height, -thickness); + glTexCoord2f(1, 0); + glVertex3f(width, height, -thickness); + glTexCoord2f(1, 1); + glVertex3f(width, -height, -thickness); + glTexCoord2f(0, 1); + glVertex3f(-width, -height, -thickness); + polys++; + glNormal3f(0, 1, 0); + glTexCoord2f(0, 0); + glVertex3f(-width, height, thickness); + glTexCoord2f(1, 0); + glVertex3f(width, height, thickness); + glTexCoord2f(1, 1); + glVertex3f(width, height, -thickness); + glTexCoord2f(0, 1); + glVertex3f(-width, height, -thickness); + polys++; + glNormal3f(0, -1, 0); + glTexCoord2f(0, 0); + glVertex3f(-width, -height, -thickness); + glTexCoord2f(1, 0); + glVertex3f(width, -height, -thickness); + glTexCoord2f(1, 1); + glVertex3f(width, -height, thickness); + glTexCoord2f(0, 1); + glVertex3f(-width, -height, thickness); + polys++; + glNormal3f(1, 0, 0); + glTexCoord2f(0, 0); + glVertex3f(width, -height, thickness); + glTexCoord2f(1, 0); + glVertex3f(width, -height, -thickness); + glTexCoord2f(1, 1); + glVertex3f(width, height, -thickness); + glTexCoord2f(0, 1); + glVertex3f(width, height, thickness); + polys++; + glNormal3f(-1, 0, 0); + glTexCoord2f(0, 0); + glVertex3f(-width, height, thickness); + glTexCoord2f(1, 0); + glVertex3f(-width, height, -thickness); + glTexCoord2f(1, 1); + glVertex3f(-width, -height, -thickness); + glTexCoord2f(0, 1); + glVertex3f(-width, -height, thickness); + polys++; + glEnd(); + return polys; +} + +static void +draw_stairs_internal(ModeInfo * mi) +{ + GLfloat X; + + mi->polygon_count = 0; + + glPushMatrix(); + glPushMatrix(); + glTranslatef(-3.0, 0.1, 2.0); + for (X = 0; X < 2; X++) { + mi->polygon_count += draw_block(0.5, 2.7 + 0.1 * X, 0.5); + glTranslatef(0.0, 0.1, -1.0); + } + glPopMatrix(); + glTranslatef(-3.0, 0.0, 3.0); + glPushMatrix(); + + for (X = 0; X < 6; X++) { + mi->polygon_count += draw_block(0.5, 2.6 - 0.1 * X, 0.5); + glTranslatef(1.0, -0.1, 0.0); + } + glTranslatef(-1.0, -0.9, -1.0); + for (X = 0; X < 5; X++) { + mi->polygon_count += draw_block(0.5, 3.0 - 0.1 * X, 0.5); + glTranslatef(0.0, 0.0, -1.0); + } + glTranslatef(-1.0, -1.1, 1.0); + for (X = 0; X < 3; X++) { + mi->polygon_count += draw_block(0.5, 3.5 - 0.1 * X, 0.5); + glTranslatef(-1.0, -0.1, 0.0); + } + glPopMatrix(); + glPopMatrix(); +} + +/*#define DEBUG*/ +/*#define DEBUG_PATH*/ + +static int +draw_sphere(int pos, int tick) +{ + int pos2 = (pos+1) % NPOSITIONS; + GLfloat x1 = ball_positions[pos*3]; + GLfloat y1 = ball_positions[pos*3+1]; + GLfloat z1 = ball_positions[pos*3+2]; + GLfloat x2 = ball_positions[pos2*3]; + GLfloat y2 = ball_positions[pos2*3+1]; + GLfloat z2 = ball_positions[pos2*3+2]; + GLfloat frac = tick / (GLfloat) SPHERE_TICKS; + GLfloat x = x1 + (x2 - x1) * frac; + GLfloat y = y1 + (y2 - y1) * frac + (2 * sin (M_PI * frac)); + GLfloat z = z1 + (z2 - z1) * frac; + int polys = 0; + + glPushMatrix(); + +# ifdef DEBUG_PATH + glVertex3f(x, y, z); + if (tick == 0) { + glVertex3f(x, y-7.5, z); + glVertex3f(x, y, z); glVertex3f(x, y, z-0.6); + glVertex3f(x, y, z); glVertex3f(x, y, z+0.6); + glVertex3f(x, y, z); glVertex3f(x+0.6, y, z); + glVertex3f(x, y, z); glVertex3f(x-0.6, y, z); + glVertex3f(x, y, z); + } + +# else /* !DEBUG_PATH */ + y += 0.5; + glTranslatef(x, y, z); + + glScalef (0.5, 0.5, 0.5); + + /* make ball a little smaller on the gap to obscure distance */ + if (pos == NPOSITIONS-1) + glScalef (0.95, 0.95, 0.95); + + glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, MaterialYellow); + glDisable (GL_TEXTURE_2D); + glShadeModel(GL_SMOOTH); + glFrontFace(GL_CCW); + polys += unit_sphere (32, 32, False); + glShadeModel(GL_FLAT); + glEnable (GL_TEXTURE_2D); +#endif /* !DEBUG_PATH */ + + glPopMatrix(); + return polys; +} + + + +ENTRYPOINT void +reshape_stairs (ModeInfo * mi, int width, int height) +{ + stairsstruct *sp = &stairs[MI_SCREEN(mi)]; + + glViewport(0, 0, sp->WindW = (GLint) width, sp->WindH = (GLint) height); + glMatrixMode(GL_PROJECTION); + glLoadIdentity(); + glFrustum(-1.0, 1.0, -1.0, 1.0, 5.0, 15.0); + glMatrixMode(GL_MODELVIEW); + if (width >= 1024) { + glLineWidth(3); + glPointSize(3); + } else if (width >= 512) { + glLineWidth(2); + glPointSize(2); + } else { + glLineWidth(1); + glPointSize(1); + } +} + +ENTRYPOINT Bool +stairs_handle_event (ModeInfo *mi, XEvent *event) +{ + stairsstruct *sp = &stairs[MI_SCREEN(mi)]; + + if (event->xany.type == ButtonPress && + event->xbutton.button == Button1) + { + sp->button_down_p = True; + gltrackball_start (sp->trackball, + event->xbutton.x, event->xbutton.y, + MI_WIDTH (mi), MI_HEIGHT (mi)); + return True; + } + else if (event->xany.type == ButtonRelease && + event->xbutton.button == Button1) + { + sp->button_down_p = False; + return True; + } + else if (event->xany.type == ButtonPress && + (event->xbutton.button == Button4 || + event->xbutton.button == Button5 || + event->xbutton.button == Button6 || + event->xbutton.button == Button7)) + { + gltrackball_mousewheel (sp->trackball, event->xbutton.button, 10, + !!event->xbutton.state); + return True; + } + else if (event->xany.type == MotionNotify && + sp->button_down_p) + { + gltrackball_track (sp->trackball, + event->xmotion.x, event->xmotion.y, + MI_WIDTH (mi), MI_HEIGHT (mi)); + return True; + } + else if (event->xany.type == KeyPress) + { + KeySym keysym; + char c = 0; + XLookupString (&event->xkey, &c, 1, &keysym, 0); + if (c == ' ') + { + gltrackball_reset (sp->trackball); + return True; + } + } + + return False; +} + + +static void +pinit(ModeInfo *mi) +{ + /* int status; */ + glClearDepth(1.0); + glLightfv(GL_LIGHT0, GL_AMBIENT, ambient); + glLightfv(GL_LIGHT0, GL_DIFFUSE, diffuse); + glLightfv(GL_LIGHT0, GL_POSITION, position0); + glLightfv(GL_LIGHT1, GL_AMBIENT, ambient); + glLightfv(GL_LIGHT1, GL_DIFFUSE, diffuse); + glLightfv(GL_LIGHT1, GL_POSITION, position1); + glLightModelfv(GL_LIGHT_MODEL_AMBIENT, lmodel_ambient); + glLightModelfv(GL_LIGHT_MODEL_TWO_SIDE, lmodel_twoside); + glEnable(GL_LIGHTING); + glEnable(GL_LIGHT0); + glEnable(GL_LIGHT1); + glEnable(GL_NORMALIZE); + glCullFace(GL_BACK); + + glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, MaterialWhite); + glShadeModel(GL_FLAT); + glEnable(GL_DEPTH_TEST); + glEnable(GL_TEXTURE_2D); + glEnable(GL_CULL_FACE); + + glPixelStorei(GL_UNPACK_ALIGNMENT, 1); + +#if 0 + clear_gl_error(); + status = gluBuild2DMipmaps(GL_TEXTURE_2D, 3, + WoodTextureWidth, WoodTextureHeight, + GL_RGB, GL_UNSIGNED_BYTE, WoodTextureData); + if (status) + { + const char *s = (char *) gluErrorString (status); + fprintf (stderr, "%s: error mipmapping %dx%d texture: %s\n", + progname, WoodTextureWidth, WoodTextureHeight, + (s ? s : "(unknown)")); + exit (1); + } + check_gl_error("mipmapping"); +#else + { + XImage *img = xpm_to_ximage (mi->dpy, + mi->xgwa.visual, + mi->xgwa.colormap, + wood_texture); + glTexImage2D (GL_TEXTURE_2D, 0, GL_RGBA, + img->width, img->height, 0, + GL_RGBA, + /* GL_UNSIGNED_BYTE, */ + GL_UNSIGNED_INT_8_8_8_8_REV, + img->data); + check_gl_error("texture"); + XDestroyImage (img); + } +#endif + + 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_NEAREST); + glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + + glMaterialfv(GL_FRONT_AND_BACK, GL_SHININESS, front_shininess); + glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, front_specular); +} + +ENTRYPOINT void +init_stairs (ModeInfo * mi) +{ + int screen = MI_SCREEN(mi); + stairsstruct *sp; + + if (stairs == NULL) { + if ((stairs = (stairsstruct *) calloc(MI_NUM_SCREENS(mi), + sizeof (stairsstruct))) == NULL) + return; + } + sp = &stairs[screen]; + + sp->step = 0.0; + sp->rotating = 0; + sp->sphere_position = NRAND(NPOSITIONS); + sp->sphere_tick = 0; + + if ((sp->glx_context = init_GL(mi)) != NULL) { + + reshape_stairs(mi, MI_WIDTH(mi), MI_HEIGHT(mi)); + glDrawBuffer(GL_BACK); + if (!glIsList(sp->objects)) + sp->objects = glGenLists(1); + pinit(mi); + } else { + MI_CLEARWINDOW(mi); + } + + sp->trackball = gltrackball_init (); +} + +ENTRYPOINT void +draw_stairs (ModeInfo * mi) +{ + stairsstruct *sp = &stairs[MI_SCREEN(mi)]; + GLfloat rot = current_device_rotation(); + + Display *display = MI_DISPLAY(mi); + Window window = MI_WINDOW(mi); + + if (!sp->glx_context) + return; + + glXMakeCurrent(display, window, *(sp->glx_context)); + + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + + glPushMatrix(); + + glRotatef(rot, 0, 0, 1); + if ((rot > 45 && rot < 135) || + (rot < -45 && rot > -135)) + { + GLfloat s = MI_WIDTH(mi) / (GLfloat) MI_HEIGHT(mi); + glScalef (s, 1/s, 1); + } + + glTranslatef(0.0, 0.0, -10.0); + + if (!MI_IS_ICONIC(mi)) { + glScalef(Scale4Window * sp->WindH / sp->WindW, Scale4Window, Scale4Window); + } else { + glScalef(Scale4Iconic * sp->WindH / sp->WindW, Scale4Iconic, Scale4Iconic); + } + + gltrackball_rotate (sp->trackball); + + glTranslatef(0, 0.5, 0); + glRotatef(44.5, 1, 0, 0); + glRotatef(50, 0, 1, 0); + + if (!sp->rotating) { + if ((LRAND() % 500) == 0) + sp->rotating = (LRAND() & 1) ? 1 : -1; + } + + if (sp->rotating) { + glRotatef(sp->rotating * sp->step, 0, 1, 0); + if (sp->step >= 360) { + sp->rotating = 0; + sp->step = 0; + } + +# ifndef DEBUG + if (!sp->button_down_p) + sp->step += 2; +# endif /* DEBUG */ + } + + draw_stairs_internal(mi); + + +# ifdef DEBUG + { + int i, j; +# ifdef DEBUG_PATH + glDisable(GL_LIGHTING); + glDisable(GL_TEXTURE_2D); + glBegin (GL_LINE_LOOP); +# endif /* DEBUG_PATH */ + for (i = 0; i < NPOSITIONS; i ++) + for (j = 0; j < SPHERE_TICKS; j++) + mi->polygon_count += draw_sphere(i, j); +# ifdef DEBUG_PATH + glEnd(); + glEnable(GL_LIGHTING); + glEnable(GL_TEXTURE_2D); +# endif /* DEBUG_PATH */ + } +#else /* !DEBUG */ + mi->polygon_count += draw_sphere(sp->sphere_position, sp->sphere_tick); +#endif /* !DEBUG */ + + if (sp->button_down_p) + ; + else if (++sp->sphere_tick >= SPHERE_TICKS) + { + sp->sphere_tick = 0; + if (++sp->sphere_position >= NPOSITIONS) + sp->sphere_position = 0; + } + + glPopMatrix(); + + if (mi->fps_p) do_fps (mi); + glFlush(); + + glXSwapBuffers(display, window); +} + +#ifndef STANDALONE +ENTRYPOINT void +change_stairs (ModeInfo * mi) +{ + stairsstruct *sp = &stairs[MI_SCREEN(mi)]; + + if (!sp->glx_context) + return; + + glXMakeCurrent(MI_DISPLAY(mi), MI_WINDOW(mi), *(sp->glx_context)); + pinit(); +} +#endif /* !STANDALONE */ + +ENTRYPOINT void +release_stairs (ModeInfo * mi) +{ + if (stairs != NULL) { + int i; + for (i = 0; i < MI_NUM_SCREENS(mi); i++) { + stairsstruct *sp = &stairs[i]; + if (glIsList(sp->objects)) { + glDeleteLists(sp->objects, 1); + } + } + free(stairs); + stairs = NULL; + } + FreeAllGL(mi); +} + +XSCREENSAVER_MODULE ("Stairs", stairs) + +#endif diff --git a/hacks/glx/stairs.man b/hacks/glx/stairs.man new file mode 100644 index 00000000..898f7ffa --- /dev/null +++ b/hacks/glx/stairs.man @@ -0,0 +1,56 @@ +.TH XScreenSaver 1 "" "X Version 11" +.SH NAME +stairs - Escher's infinite staircase. +.SH SYNOPSIS +.B stairs +[\-display \fIhost:display.screen\fP] +[\-visual \fIvisual\fP] +[\-window] +[\-root] +[\-delay \fInumber\fP] +[\-wireframe] +[\-fps] +.SH DESCRIPTION +This draws an "infinite" staircase. +.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: 20000 (0.02 seconds.). +.TP 8 +.B \-wireframe +Render in wireframe instead of solid. +.TP 8 +.B \-fps +Display the current frame rate, CPU load, and polygon count. +.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 2002 by Marcelo Vianna. 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 +Marcelo Vianna. diff --git a/hacks/glx/starwars.c b/hacks/glx/starwars.c new file mode 100644 index 00000000..de3833c5 --- /dev/null +++ b/hacks/glx/starwars.c @@ -0,0 +1,1051 @@ +/* starwars, Copyright (c) 1998-2012 Jamie Zawinski and + * Claudio Matsuoka + * + * 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. + * + * Star Wars -- Phosphor meets a well-known scroller from a galaxy far, + * far away. + * + * Feb 2000 Claudio Matsuoka First version. + * Jan 2001 Jamie Zawinski Rewrote large sections to add the ability to + * run a subprocess, customization of the font + * size and other parameters, etc. + * Feb 2001 jepler@inetnebr.com Added anti-aliased lines, and fade-to-black. + * Feb 2005 Jamie Zawinski Added texture fonts. + * + * + * For the fanboys: + * + * starwars -program 'cat starwars.txt' -columns 25 -no-wrap + */ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif /* HAVE_CONFIG_H */ + +#include +#include + +#ifdef HAVE_UNISTD_H +# include +#endif + + +#include "starwars.h" +#define DEFAULTS "*delay: 40000 \n" \ + "*showFPS: False \n" \ + "*fpsTop: True \n" \ + "*usePty: False \n" \ + "*font: " DEF_FONT "\n" \ + "*textLiteral: " DEF_TEXT "\n" + + +# define refresh_sws 0 +# define sws_handle_event 0 +#undef countof +#define countof(x) (sizeof((x))/sizeof((*x))) + +#include "xlockmore.h" +#include "textclient.h" + +#ifdef USE_GL /* whole file */ + +/* Should be in */ +# ifndef GL_TEXTURE_MAX_ANISOTROPY_EXT +# define GL_TEXTURE_MAX_ANISOTROPY_EXT 0x84FE +# endif +# ifndef GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT +# define GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT 0x84FF +# endif + + +#define DEF_PROGRAM "xscreensaver-text --cols 0" /* don't wrap */ +#define DEF_LINES "125" +#define DEF_STEPS "35" +#define DEF_SPIN "0.03" +#define DEF_SIZE "-1" +#define DEF_COLUMNS "-1" +#define DEF_LINE_WRAP "True" +#define DEF_ALIGNMENT "Center" +#define DEF_SMOOTH "True" +#define DEF_THICK "True" +#define DEF_FADE "True" +#define DEF_TEXTURES "True" +#define DEF_DEBUG "False" + +/* Utopia 800 needs 64 512x512 textures (4096x4096 bitmap). + Utopia 720 needs 16 512x512 textures (2048x2048 bitmap). + Utopia 480 needs 16 512x512 textures (2048x2048 bitmap). + Utopia 400 needs 4 512x512 textures (1024x1024 bitmap). + Utopia 180 needs 1 512x512 texture. + Times 240 needs 1 512x512 texture. + */ +#define DEF_FONT "-*-utopia-bold-r-normal-*-*-720-*-*-*-*-iso8859-1" + +#define TAB_WIDTH 8 + +#define MAX_THICK_LINES 25 +#define FONT_WEIGHT 14 + +#ifndef USE_IPHONE +# define KEEP_ASPECT /* Letterboxing looks dumb on iPhone. */ +#endif + +#include "texfont.h" +#include "glutstroke.h" +#include "glut_roman.h" +#define GLUT_FONT (&glutStrokeRoman) + +typedef struct { + Display *dpy; + GLXContext *glx_context; + + GLuint text_list, star_list; + texture_font_data *texfont; + int polygon_count; + text_data *tc; + + char *buf; + int buf_size; + int buf_tail; + + char **lines; + int total_lines; + + double star_theta; + double char_width; + double line_height; + double font_scale; + double intra_line_scroll; + + int line_pixel_width; /* in font units (for wrapping text) */ + int line_pixel_height; /* in screen units (for computing line thickness) */ + GLfloat line_thickness; + +} sws_configuration; + + +static sws_configuration *scs = NULL; + +static char *program; +static int max_lines; +static int scroll_steps; +static float star_spin; +static float font_size; +static int target_columns; +static int wrap_p; +static int smooth_p; +static int thick_p; +static int fade_p; +static int textures_p; +static int debug_p; +static char *alignment_str; +static int alignment; + +static XrmOptionDescRec opts[] = { + {"-program", ".program", XrmoptionSepArg, 0 }, + {"-lines", ".lines", XrmoptionSepArg, 0 }, + {"-steps", ".steps", XrmoptionSepArg, 0 }, + {"-spin", ".spin", XrmoptionSepArg, 0 }, + {"-size", ".size", XrmoptionSepArg, 0 }, + {"-columns", ".columns", XrmoptionSepArg, 0 }, +/*{"-font", ".font", XrmoptionSepArg, 0 },*/ + {"-fade", ".fade", XrmoptionNoArg, "True" }, + {"-no-fade", ".fade", XrmoptionNoArg, "False" }, + {"-textures", ".textures", XrmoptionNoArg, "True" }, + {"-smooth", ".smooth", XrmoptionNoArg, "True" }, + {"-no-smooth", ".smooth", XrmoptionNoArg, "False" }, + {"-thick", ".thick", XrmoptionNoArg, "True" }, + {"-no-thick", ".thick", XrmoptionNoArg, "False" }, + {"-no-textures", ".textures", XrmoptionNoArg, "False" }, + {"-wrap", ".lineWrap", XrmoptionNoArg, "True" }, + {"-no-wrap", ".lineWrap", XrmoptionNoArg, "False" }, + {"-nowrap", ".lineWrap", XrmoptionNoArg, "False" }, + {"-alignment", ".alignment", XrmoptionSepArg, 0 }, + {"-left", ".alignment", XrmoptionNoArg, "Left" }, + {"-right", ".alignment", XrmoptionNoArg, "Right" }, + {"-center", ".alignment", XrmoptionNoArg, "Center" }, + {"-debug", ".debug", XrmoptionNoArg, "True" }, +}; + +static argtype vars[] = { + {&program, "program", "Program", DEF_PROGRAM, t_String}, + {&max_lines, "lines", "Integer", DEF_LINES, t_Int}, + {&scroll_steps, "steps", "Integer", DEF_STEPS, t_Int}, + {&star_spin, "spin", "Float", DEF_SPIN, t_Float}, + {&font_size, "size", "Float", DEF_SIZE, t_Float}, + {&target_columns, "columns", "Integer", DEF_COLUMNS, t_Int}, + {&wrap_p, "lineWrap", "Boolean", DEF_LINE_WRAP, t_Bool}, + {&alignment_str, "alignment", "Alignment", DEF_ALIGNMENT, t_String}, + {&smooth_p, "smooth", "Boolean", DEF_SMOOTH, t_Bool}, + {&thick_p, "thick", "Boolean", DEF_THICK, t_Bool}, + {&fade_p, "fade", "Boolean", DEF_FADE, t_Bool}, + {&textures_p, "textures", "Boolean", DEF_TEXTURES, t_Bool}, + {&debug_p, "debug", "Boolean", DEF_DEBUG, t_Bool}, +}; + +ENTRYPOINT ModeSpecOpt sws_opts = {countof(opts), opts, countof(vars), vars, NULL}; + + + +/* Tabs are bad, mmmkay? */ + +static char * +untabify (const char *string) +{ + const char *ostring = string; + char *result = (char *) malloc ((strlen(string) * 8) + 1); + char *out = result; + int col = 0; + while (*string) + { + if (*string == '\t') + { + do { + col++; + *out++ = ' '; + } while (col % TAB_WIDTH); + string++; + } + else if (*string == '\r' || *string == '\n') + { + *out++ = *string++; + col = 0; + } + else if (*string == '\010') /* backspace */ + { + if (string > ostring) + out--, string++; + } + else + { + *out++ = *string++; + col++; + } + } + *out = 0; + + return result; +} + +static void +strip (char *s, Bool leading, Bool trailing) +{ + int L = strlen(s); + if (trailing) + while (L > 0 && (s[L-1] == ' ' || s[L-1] == '\t')) + s[L--] = 0; + if (leading) + { + char *s2 = s; + while (*s2 == ' ' || *s2 == '\t') + s2++; + if (s == s2) + return; + while (*s2) + *s++ = *s2++; + *s = 0; + } +} + + +/* The GLUT font only has ASCII characters in them, so do what we can to + convert Latin1 characters to the nearest ASCII equivalent... + */ +static void +latin1_to_ascii (char *s) +{ + unsigned char *us = (unsigned char *) s; + const unsigned char ascii[95] = { + '!', 'C', '#', '#', 'Y', '|', 'S', '_', 'C', '?', '<', '=', '-', 'R', '_', + '?', '?', '2', '3', '\'','u', 'P', '.', ',', '1', 'o', '>', '?', '?', '?', + '?', 'A', 'A', 'A', 'A', 'A', 'A', 'E', 'C', 'E', 'E', 'E', 'E', 'I', 'I', + 'I', 'I', 'D', 'N', 'O', 'O', 'O', 'O', 'O', 'x', '0', 'U', 'U', 'U', 'U', + 'Y', 'p', 'S', 'a', 'a', 'a', 'a', 'a', 'a', 'e', 'c', 'e', 'e', 'e', 'e', + 'i', 'i', 'i', 'i', 'o', 'n', 'o', 'o', 'o', 'o', 'o', '/', 'o', 'u', 'u', + 'u', 'u', 'y', 'p', 'y' }; + while (*us) + { + if (*us >= 161) + *us = ascii[*us - 161]; + else if (*us > 127) + *us = '?'; + us++; + } +} + + +static int +string_width (sws_configuration *sc, const char *s) +{ + if (textures_p) + return texture_string_width (sc->texfont, s, 0); + else + return glutStrokeLength (GLUT_FONT, (unsigned char *) s); +} + +static int +char_width (sws_configuration *sc, char c) +{ + char s[2]; + s[0] = c; + s[1] = 0; + return string_width (sc, s); +} + + +/* Populates the sc->lines list with as many lines as possible. + */ +static void +get_more_lines (sws_configuration *sc) +{ + /* wrap anyway, if it's absurdly long. */ + int wrap_pix = (wrap_p ? sc->line_pixel_width : 10000); + + int col = 0; + int col_pix = 0; + + char *s = sc->buf; + + int target = sc->buf_size - sc->buf_tail - 2; + + /* Fill as much as we can into sc->buf. + */ + while (target > 0) + { + char c = textclient_getc (sc->tc); + if (c <= 0) + break; + sc->buf[sc->buf_tail++] = c; + sc->buf[sc->buf_tail] = 0; + target--; + } + + while (sc->total_lines < max_lines) + { + int cw; + + if (s >= sc->buf + sc->buf_tail) + /* Reached end of buffer before end of line. Bail. */ + return; + + cw = char_width (sc, *s); + + if (*s == '\r' || *s == '\n' || + col_pix + cw >= wrap_pix) + { + int L = s - sc->buf; + + if (*s == '\r' || *s == '\n') + { + if (*s == '\r' && s[1] == '\n') /* swallow CRLF too */ + *s++ = 0; + + *s++ = 0; + } + else + { + /* We wrapped -- try to back up to the previous word boundary. */ + char *s2 = s; + int n = 0; + while (s2 > sc->buf && *s2 != ' ' && *s2 != '\t') + s2--, n++; + if (s2 > sc->buf) + { + s = s2; + *s++ = 0; + L = s - sc->buf; + } + } + + sc->lines[sc->total_lines] = (char *) malloc (L+1); + memcpy (sc->lines[sc->total_lines], sc->buf, L); + sc->lines[sc->total_lines][L] = 0; + + if (!textures_p) + latin1_to_ascii (sc->lines[sc->total_lines]); + + { + char *t = sc->lines[sc->total_lines]; + char *ut = untabify (t); + strip (ut, (alignment == 0), 1); /* if centering, strip + leading whitespace too */ + sc->lines[sc->total_lines] = ut; + free (t); + } + + sc->total_lines++; + + if (sc->buf_tail > (s - sc->buf)) + { + int i = sc->buf_tail - (s - sc->buf); + memmove (sc->buf, s, i); + sc->buf_tail = i; + sc->buf[sc->buf_tail] = 0; + } + else + { + sc->buf_tail = 0; + } + + sc->buf[sc->buf_tail] = 0; + s = sc->buf; + col = 0; + col_pix = 0; + } + else + { + col++; + col_pix += cw; + if (*s == '\t') + { + int tab_pix = TAB_WIDTH * sc->char_width; + col = TAB_WIDTH * ((col / TAB_WIDTH) + 1); + col_pix = tab_pix * ((col / tab_pix) + 1); + } + s++; + } + } +} + + +static void +draw_string (sws_configuration *sc, GLfloat x, GLfloat y, const char *s) +{ + const char *os = s; + if (!s || !*s) return; + glPushMatrix (); + glTranslatef (x, y, 0); + + if (textures_p) + print_texture_string (sc->texfont, s); + else + while (*s) + glutStrokeCharacter (GLUT_FONT, *s++); + glPopMatrix (); + + if (debug_p) + { + GLfloat w; + GLfloat h = sc->line_height / sc->font_scale; + char c[2]; + c[1]=0; + s = os; + if (textures_p) glDisable (GL_TEXTURE_2D); + glLineWidth (1); + glColor3f (0.4, 0.4, 0.4); + glPushMatrix (); + glTranslatef (x, y, 0); + while (*s) + { + *c = *s++; + w = string_width (sc, c); + glBegin (GL_LINE_LOOP); + glVertex3f (0, 0, 0); + glVertex3f (w, 0, 0); + glVertex3f (w, h, 0); + glVertex3f (0, h, 0); + glEnd(); + glTranslatef (w, 0, 0); + } + glPopMatrix (); + if (textures_p) glEnable (GL_TEXTURE_2D); + } +} + + +static void +grid (double width, double height, double xspacing, double yspacing, double z) +{ + double x, y; + for (y = 0; y <= height/2; y += yspacing) + { + glBegin(GL_LINES); + glVertex3f(-width/2, y, z); + glVertex3f( width/2, y, z); + glVertex3f(-width/2, -y, z); + glVertex3f( width/2, -y, z); + glEnd(); + } + for (x = 0; x <= width/2; x += xspacing) + { + glBegin(GL_LINES); + glVertex3f( x, -height/2, z); + glVertex3f( x, height/2, z); + glVertex3f(-x, -height/2, z); + glVertex3f(-x, height/2, z); + glEnd(); + } + + glBegin(GL_LINES); + glVertex3f(-width, 0, z); + glVertex3f( width, 0, z); + glVertex3f(0, -height, z); + glVertex3f(0, height, z); + glEnd(); +} + +static void +box (double width, double height, double depth) +{ + glBegin(GL_LINE_LOOP); + glVertex3f(-width/2, -height/2, -depth/2); + glVertex3f(-width/2, height/2, -depth/2); + glVertex3f( width/2, height/2, -depth/2); + glVertex3f( width/2, -height/2, -depth/2); + glEnd(); + glBegin(GL_LINE_LOOP); + glVertex3f(-width/2, -height/2, depth/2); + glVertex3f(-width/2, height/2, depth/2); + glVertex3f( width/2, height/2, depth/2); + glVertex3f( width/2, -height/2, depth/2); + glEnd(); + glBegin(GL_LINE_LOOP); + glVertex3f(-width/2, -height/2, -depth/2); + glVertex3f(-width/2, -height/2, depth/2); + glVertex3f(-width/2, height/2, depth/2); + glVertex3f(-width/2, height/2, -depth/2); + glEnd(); + glBegin(GL_LINE_LOOP); + glVertex3f( width/2, -height/2, -depth/2); + glVertex3f( width/2, -height/2, depth/2); + glVertex3f( width/2, height/2, depth/2); + glVertex3f( width/2, height/2, -depth/2); + glEnd(); + + glBegin(GL_LINES); + glVertex3f(-width/2, height/2, depth/2); + glVertex3f(-width/2, -height/2, -depth/2); + + glVertex3f( width/2, height/2, depth/2); + glVertex3f( width/2, -height/2, -depth/2); + + glVertex3f(-width/2, -height/2, depth/2); + glVertex3f(-width/2, height/2, -depth/2); + + glVertex3f( width/2, -height/2, depth/2); + glVertex3f( width/2, height/2, -depth/2); + glEnd(); +} + + +/* Construct stars (number of stars is dependent on size of screen) */ +static void +init_stars (ModeInfo *mi, int width, int height) +{ + sws_configuration *sc = &scs[MI_SCREEN(mi)]; + int i, j; + int size = (width > height ? width : height); + int nstars = size * size / 320; + int max_size = 3; + GLfloat inc = 0.5; + int steps = max_size / inc; + + glDeleteLists (sc->star_list, 1); + sc->star_list = glGenLists (1); + glNewList (sc->star_list, GL_COMPILE); + + glEnable(GL_POINT_SMOOTH); + + for (j = 1; j <= steps; j++) + { + glPointSize(inc * j); + glBegin (GL_POINTS); + for (i = 0; i < nstars / steps; i++) + { + glColor3f (0.6 + frand(0.3), + 0.6 + frand(0.3), + 0.6 + frand(0.3)); + glVertex2f (2 * size * (0.5 - frand(1.0)), + 2 * size * (0.5 - frand(1.0))); + } + glEnd (); + } + glEndList (); +} + + +/* Window management, etc + */ +ENTRYPOINT void +reshape_sws (ModeInfo *mi, int width, int height) +{ + sws_configuration *sc = &scs[MI_SCREEN(mi)]; + + /* Set up matrices for perspective text display + */ + { + GLfloat desired_aspect = (GLfloat) 3/4; + int w = mi->xgwa.width; + int h = mi->xgwa.height; + int yoff = 0; + GLfloat rot = current_device_rotation(); + +#ifdef KEEP_ASPECT + { + int h2 = w * desired_aspect; + yoff = (h - h2) / 2; /* Wide window: letterbox at top and bottom. */ + if (yoff < 0) yoff = 0; /* Tall window: clip off the top. */ + h = h2; + } +#endif + + glMatrixMode (GL_PROJECTION); + glViewport (0, yoff, w, h); + + glMatrixMode (GL_MODELVIEW); + glLoadIdentity (); + gluPerspective (80.0, 1/desired_aspect, 1000, 55000); + gluLookAt (0.0, 0.0, 4600.0, + 0.0, 0.0, 0.0, + 0.0, 1.0, 0.0); + + glRotatef(rot, 0, 0, 1); + + /* Horrible kludge to prevent the text from materializing already + on screen on iPhone in landscape mode. + */ + if ((rot > 45 && rot < 135) || + (rot < -45 && rot > -135)) + { + GLfloat s = 1.1; + glScalef (s, s, s); + } + + glRotatef (-60.0, 1.0, 0.0, 0.0); + +#if 0 + glRotatef (60.0, 1.0, 0.0, 0.0); + glTranslatef (260, 3200, 0); + glScalef (1.85, 1.85, 1); +#endif + + /* The above gives us an arena where the bottom edge of the screen is + represented by the line (-2100,-3140,0) - ( 2100,-3140,0). */ + + /* Now let's move the origin to the front of the screen. */ + glTranslatef (0.0, -3140, 0.0); + + /* And then let's scale so that the bottom of the screen is 1.0 wide. */ + glScalef (4200, 4200, 4200); + } + + + /* Compute the height in pixels of the line at the bottom of the screen. */ + { + GLdouble mm[17], pm[17]; + GLint vp[5]; + GLdouble x = 0.5, y1 = 0, z = 0; + GLdouble y2 = sc->line_height; + GLdouble wx=-1, wy1=-1, wy2=-1, wz=-1; + + glGetDoublev (GL_MODELVIEW_MATRIX, mm); + glGetDoublev (GL_PROJECTION_MATRIX, pm); + glGetIntegerv (GL_VIEWPORT, vp); + gluProject (x, y1, z, mm, pm, vp, &wx, &wy1, &wz); + gluProject (x, y2, z, mm, pm, vp, &wx, &wy2, &wz); + sc->line_pixel_height = (wy2 - wy1); + glLineWidth (1); + } + + /* Compute the best looking line thickness for the bottom line. + */ + if (!thick_p) + sc->line_thickness = 1.0; + else + sc->line_thickness = (GLfloat) sc->line_pixel_height / FONT_WEIGHT; + + if (sc->line_thickness < 1.2) + sc->line_thickness = 1.0; +} + + +static void +gl_init (ModeInfo *mi) +{ + sws_configuration *sc = &scs[MI_SCREEN(mi)]; + + program = get_string_resource (mi->dpy, "program", "Program"); + + glDisable (GL_LIGHTING); + glDisable (GL_DEPTH_TEST); + + if (smooth_p) + { + glEnable (GL_LINE_SMOOTH); + glHint (GL_LINE_SMOOTH_HINT, GL_NICEST); + glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + glEnable (GL_BLEND); + } + + sc->text_list = glGenLists (1); + glNewList (sc->text_list, GL_COMPILE); + glEndList (); + + sc->star_list = glGenLists (1); + glNewList (sc->star_list, GL_COMPILE); + glEndList (); + + sc->line_thickness = 1.0; +} + + +ENTRYPOINT void +init_sws (ModeInfo *mi) +{ + double font_height; + + sws_configuration *sc = 0; + + if (!scs) { + scs = (sws_configuration *) + calloc (MI_NUM_SCREENS(mi), sizeof (sws_configuration)); + if (!scs) { + fprintf(stderr, "%s: out of memory\n", progname); + exit(1); + } + } + + sc = &scs[MI_SCREEN(mi)]; + + sc->dpy = MI_DISPLAY(mi); + sc = &scs[MI_SCREEN(mi)]; + sc->lines = (char **) calloc (max_lines+1, sizeof(char *)); + + if ((sc->glx_context = init_GL(mi)) != NULL) { + gl_init(mi); + reshape_sws (mi, MI_WIDTH(mi), MI_HEIGHT(mi)); + clear_gl_error(); /* WTF? sometimes "invalid op" from glViewport! */ + + init_stars (mi, MI_WIDTH(mi), MI_HEIGHT(mi)); + } + + if (textures_p) + { + int cw, lh; + sc->texfont = load_texture_font (MI_DISPLAY(mi), "font"); + cw = texture_string_width (sc->texfont, "n", &lh); + sc->char_width = cw; + font_height = lh; + glEnable(GL_ALPHA_TEST); + glEnable (GL_TEXTURE_2D); + + check_gl_error ("loading font"); + + /* "Anistropic filtering helps for quadrilateral-angled textures. + A sharper image is accomplished by interpolating and filtering + multiple samples from one or more mipmaps to better approximate + very distorted textures. This is the next level of filtering + after trilinear filtering." */ + if (smooth_p && + strstr ((char *) glGetString(GL_EXTENSIONS), + "GL_EXT_texture_filter_anisotropic")) + { + GLfloat anisotropic = 0.0; + glGetFloatv (GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, &anisotropic); + if (anisotropic >= 1.0) + glTexParameterf (GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, + anisotropic); + } + } + else + { + font_height = GLUT_FONT->top - GLUT_FONT->bottom; + sc->char_width = glutStrokeWidth (GLUT_FONT, 'z'); /* 'n' seems wide */ + } + + sc->font_scale = 1.0 / sc->char_width; + + + /* We consider a font that consumes 80 columns to be "18 points". + + If neither -size nor -columns was specified, default to 60 columns + (which is 24 points.) + + If both were specified, -columns has priority. + */ + { + int base_col = 80; + int base_size = 18; + + if (target_columns <= 0 && font_size <= 0) + target_columns = 60; + + if (target_columns > 0) + font_size = base_size * (base_col / (double) target_columns); + else if (font_size > 0) + target_columns = base_col * (base_size / (double) font_size); + } + + sc->line_pixel_width = target_columns * sc->char_width; + + sc->font_scale /= target_columns; + sc->line_height = font_height * sc->font_scale; + + + /* Buffer only two lines of text. + If the buffer is too big, there's a significant delay between + when the program launches and when the text appears, which can be + irritating for time-sensitive output (clock, current music, etc.) + */ + sc->buf_size = target_columns * 2; + if (sc->buf_size < 80) sc->buf_size = 80; + sc->buf = (char *) calloc (1, sc->buf_size); + + sc->total_lines = max_lines-1; + + if (random() & 1) + star_spin = -star_spin; + + if (!alignment_str || !*alignment_str || + !strcasecmp(alignment_str, "left")) + alignment = -1; + else if (!strcasecmp(alignment_str, "center") || + !strcasecmp(alignment_str, "middle")) + alignment = 0; + else if (!strcasecmp(alignment_str, "right")) + alignment = 1; + else + { + fprintf (stderr, + "%s: alignment must be left, center, or right, not \"%s\"\n", + progname, alignment_str); + exit (1); + } + + sc->tc = textclient_open (sc->dpy); + + /* one more reshape, after line_height has been computed */ + reshape_sws (mi, MI_WIDTH(mi), MI_HEIGHT(mi)); +} + + +static void +draw_stars (ModeInfo *mi) +{ + sws_configuration *sc = &scs[MI_SCREEN(mi)]; + + glMatrixMode (GL_PROJECTION); + glPushMatrix (); + { + glLoadIdentity (); + + glMatrixMode (GL_MODELVIEW); + glPushMatrix (); + { + glLoadIdentity (); + glOrtho (-0.5 * MI_WIDTH(mi), 0.5 * MI_WIDTH(mi), + -0.5 * MI_HEIGHT(mi), 0.5 * MI_HEIGHT(mi), + -100.0, 100.0); + glRotatef (sc->star_theta, 0.0, 0.0, 1.0); + if (textures_p) glDisable (GL_TEXTURE_2D); + + /* Keep the stars pointing in the same direction after rotation */ + glRotatef(current_device_rotation(), 0, 0, 1); + + glCallList (sc->star_list); + if (textures_p) glEnable (GL_TEXTURE_2D); + } + glPopMatrix (); + } + glMatrixMode (GL_PROJECTION); + glPopMatrix (); +} + +ENTRYPOINT void +draw_sws (ModeInfo *mi) +{ + sws_configuration *sc = &scs[MI_SCREEN(mi)]; +/* XtAppContext app = XtDisplayToApplicationContext (sc->dpy);*/ + Display *dpy = MI_DISPLAY(mi); + Window window = MI_WINDOW(mi); + int i; + + if (!sc->glx_context) + return; + + glDrawBuffer (GL_BACK); + glXMakeCurrent (dpy, window, *(sc->glx_context)); + + glClear (GL_COLOR_BUFFER_BIT); + + draw_stars (mi); + + glMatrixMode (GL_MODELVIEW); + glPushMatrix (); + +# ifdef USE_IPHONE + /* Need to do this every time to get device rotation right */ + reshape_sws (mi, MI_WIDTH(mi), MI_HEIGHT(mi)); +# endif + + if (debug_p) + { + int i; + glPushMatrix (); + if (textures_p) glDisable (GL_TEXTURE_2D); + glLineWidth (1); + glTranslatef (0,-1, 0); + + glColor3f(1, 0, 0); /* Red line is where text appears */ + glPushMatrix(); + glTranslatef(0, -0.028, 0); + glLineWidth (4); + glBegin(GL_LINES); + glVertex3f(-0.5, 1, 0); + glVertex3f( 0.5, 1, 0); + glVertex3f(-0.5, -1, 0); + glVertex3f( 0.5, -1, 0); + glEnd(); + glLineWidth (1); + glPopMatrix(); + + glColor3f (0.4, 0.4, 0.4); + for (i = 0; i < 16; i++) + { + box (1, 1, 1); + grid (1, 1, sc->char_width * sc->font_scale, sc->line_height, 0); + glTranslatef(0, 1, 0); + } + if (textures_p) glEnable (GL_TEXTURE_2D); + glPopMatrix (); + } + + /* Scroll to current position */ + glTranslatef (0.0, sc->intra_line_scroll, 0.0); + + glColor3f (1.0, 1.0, 0.4); + glCallList (sc->text_list); + mi->polygon_count = sc->polygon_count; + + sc->intra_line_scroll += sc->line_height / scroll_steps; + + if (sc->intra_line_scroll >= sc->line_height) + { + sc->intra_line_scroll = 0; + + /* Drop the oldest line off the end. */ + if (sc->lines[0]) + free (sc->lines[0]); + + /* Scroll the contents of the lines array toward 0. */ + if (sc->total_lines > 0) + { + for (i = 1; i < sc->total_lines; i++) + sc->lines[i-1] = sc->lines[i]; + sc->lines[--sc->total_lines] = 0; + } + + /* Bring in new lines at the end. */ + get_more_lines (sc); + + if (sc->total_lines < max_lines) + /* Oops, we ran out of text... well, insert some blank lines + here so that new text still pulls in from the bottom of + the screen, isntead of just appearing. */ + sc->total_lines = max_lines; + + glDeleteLists (sc->text_list, 1); + sc->text_list = glGenLists (1); + glNewList (sc->text_list, GL_COMPILE); + sc->polygon_count = 0; + glPushMatrix (); + glScalef (sc->font_scale, sc->font_scale, sc->font_scale); + for (i = 0; i < sc->total_lines; i++) + { + double fade = (fade_p ? 1.0 * i / sc->total_lines : 1.0); + int offscreen_lines = 2; + + double x = -0.5; + double y = ((sc->total_lines - (i + offscreen_lines) - 1) + * sc->line_height); + double xoff = 0; + char *line = sc->lines[i]; + + if (debug_p) + { + double xx = x * 1.4; /* a little more to the left */ + char n[20]; + sprintf(n, "%d:", i); + draw_string (sc, xx / sc->font_scale, y / sc->font_scale, n); + } + + if (!line || !*line) + continue; + + if (sc->line_thickness != 1 && !textures_p) + { + int max_thick_lines = MAX_THICK_LINES; + GLfloat thinnest_line = 1.0; + GLfloat thickest_line = sc->line_thickness; + GLfloat range = thickest_line - thinnest_line; + GLfloat thickness; + + int j = sc->total_lines - i - 1; + + if (j > max_thick_lines) + thickness = thinnest_line; + else + thickness = (thinnest_line + + (range * ((max_thick_lines - j) / + (GLfloat) max_thick_lines))); + + glLineWidth (thickness); + } + + if (alignment >= 0) + { + int n = string_width (sc, line); + xoff = 1.0 - (n * sc->font_scale); + } + + if (alignment == 0) + xoff /= 2; + + glColor3f (fade, fade, 0.5 * fade); + draw_string (sc, (x + xoff) / sc->font_scale, y / sc->font_scale, + line); + if (textures_p) + sc->polygon_count += strlen (line); + } + glPopMatrix (); + glEndList (); + } + + glPopMatrix (); + + if (mi->fps_p) do_fps (mi); + glFinish(); + glXSwapBuffers(dpy, window); + + sc->star_theta += star_spin; +} + +ENTRYPOINT void +release_sws (ModeInfo *mi) +{ + if (scs) { + int screen; + for (screen = 0; screen < MI_NUM_SCREENS(mi); screen++) { + sws_configuration *sc = &scs[screen]; + if (sc->tc) + textclient_close (sc->tc); + + /* #### there's more to free here */ + } + free (scs); + scs = 0; + } + FreeAllGL(mi); +} + + +XSCREENSAVER_MODULE_2 ("StarWars", starwars, sws) + +#endif /* USE_GL */ diff --git a/hacks/glx/starwars.h b/hacks/glx/starwars.h new file mode 100644 index 00000000..0db66d9b --- /dev/null +++ b/hacks/glx/starwars.h @@ -0,0 +1,312 @@ +#define DEF_TEXT \ +"Episode IV\\n" \ +"\\n" \ +"STAR WARS: A NEW HOPE\\n" \ +"\\n" \ +"It is a period of Civil War.\\n" \ +"Rebel Spaceships, striking\\n" \ +"from a hidden base, have won\\n" \ +"their first victory against\\n" \ +"the evil Galactic Empire.\\n" \ +"\\n" \ +"During the battle, Rebel\\n" \ +"spies managed to steal secret\\n" \ +"plans to the Empire's\\n" \ +"ultimate weapon, the DEATH\\n" \ +"STAR, an armored space\\n" \ +"station with enough power to\\n" \ +"destroy an entire planet.\\n" \ +"\\n" \ +"Pursued by the Empire's\\n" \ +"sinister agents, Princess\\n" \ +"Leia races home aboard her\\n" \ +"starship, custodian of the\\n" \ +"stolen plans that can save\\n" \ +"her people and restore\\n" \ +"freedom to the galaxy...\\n" \ +"\\n" \ +"\\n" \ +"\\n" \ +"\\n" \ +"\\n" \ +"\\n" \ +"\\n" \ +"\\n" \ +"\\n" \ +"\\n" \ +"\\n" \ +"\\n" \ +"\\n" \ +"\\n" \ +"\\n" \ +"\\n" \ +"\\n" \ +"\\n" \ +"\\n" \ +"\\n" \ +"\\n" \ +"\\n" \ +"\\n" \ +"\\n" \ +"\\n" \ +"\\n" \ +"\\n" \ +"\\n" \ +"Episode V\\n" \ +"\\n" \ +"THE EMPIRE STRIKES BACK\\n" \ +"\\n" \ +"It is a dark time for the\\n" \ +"Rebellion. Although the Death\\n" \ +"Star has been destroyed,\\n" \ +"Imperial troops have driven the\\n" \ +"Rebel forces from their hidden\\n" \ +"base and pursued them across\\n" \ +"the galaxy.\\n" \ +"\\n" \ +"Evading the dreaded Imperial\\n" \ +"Starfleet, a group of freedom\\n" \ +"fighters led by Luke Skywalker\\n" \ +"has established a new secret\\n" \ +"base on the remote ice world\\n" \ +"of Hoth.\\n" \ +"\\n" \ +"The evil lord Darth Vader,\\n" \ +"obsessed with finding young\\n" \ +"Skywalker, has dispatched\\n" \ +"thousands of remote probes into\\n" \ +"the far reaches of space....\\n" \ +"\\n" \ +"\\n" \ +"\\n" \ +"\\n" \ +"\\n" \ +"\\n" \ +"\\n" \ +"\\n" \ +"\\n" \ +"\\n" \ +"\\n" \ +"\\n" \ +"\\n" \ +"\\n" \ +"\\n" \ +"\\n" \ +"\\n" \ +"\\n" \ +"\\n" \ +"\\n" \ +"\\n" \ +"\\n" \ +"\\n" \ +"\\n" \ +"\\n" \ +"\\n" \ +"\\n" \ +"\\n" \ +"Episode VI\\n" \ +"\\n" \ +"RETURN OF THE JEDI\\n" \ +"\\n" \ +"Luke Skywalker has returned to\\n" \ +"his home planet of Tatooine in\\n" \ +"an attempt to rescue his\\n" \ +"friend Han Solo from the\\n" \ +"clutches of the vile gangster\\n" \ +"Jabba the Hutt.\\n" \ +"\\n" \ +"Little does Luke know that the\\n" \ +"GALACTIC EMPIRE has secretly\\n" \ +"begun construction on a new\\n" \ +"armored space station even\\n" \ +"more powerful than the first\\n" \ +"dreaded Death Star.\\n" \ +"\\n" \ +"When completed, this ultimate\\n" \ +"weapon will spell certain doom\\n" \ +"for the small band of rebels\\n" \ +"struggling to restore freedom\\n" \ +"to the galaxy...\\n" \ +"\\n" \ +"\\n" \ +"\\n" \ +"\\n" \ +"\\n" \ +"\\n" \ +"\\n" \ +"\\n" \ +"\\n" \ +"\\n" \ +"\\n" \ +"\\n" \ +"\\n" \ +"\\n" \ +"\\n" \ +"\\n" \ +"\\n" \ +"\\n" \ +"\\n" \ +"\\n" \ +"\\n" \ +"\\n" \ +"\\n" \ +"\\n" \ +"\\n" \ +"\\n" \ +"\\n" \ +"\\n" \ +"Episode I\\n" \ +"\\n" \ +"THE PHANTOM MENACE\\n" \ +"\\n" \ +"Turmoil has engulfed the\\n" \ +"Galactic Republic. The taxation\\n" \ +"of trade routes to outlying star\\n" \ +"systems is in dispute.\\n" \ +"\\n" \ +"Hoping to resolve the matter\\n" \ +"with a blockade of deadly\\n" \ +"battleships, the greedy Trade\\n" \ +"Federation has stopped all\\n" \ +"shipping to the small planet\\n" \ +"of Naboo.\\n" \ +"\\n" \ +"While the Congress of the\\n" \ +"Republic endlessly debates\\n" \ +"this alarming chain of events,\\n" \ +"the Supreme Chancellor has\\n" \ +"secretly dispatched two Jedi\\n" \ +"Knights, the guardians of\\n" \ +"peace and justice in the\\n" \ +"galaxy to settle the conflict...\\n" \ +"\\n" \ +"\\n" \ +"\\n" \ +"\\n" \ +"\\n" \ +"\\n" \ +"\\n" \ +"\\n" \ +"\\n" \ +"\\n" \ +"\\n" \ +"\\n" \ +"\\n" \ +"\\n" \ +"\\n" \ +"\\n" \ +"\\n" \ +"\\n" \ +"\\n" \ +"\\n" \ +"\\n" \ +"\\n" \ +"\\n" \ +"\\n" \ +"\\n" \ +"\\n" \ +"\\n" \ +"\\n" \ +"Episode II\\n" \ +"\\n" \ +"ATTACK OF THE CLONES\\n" \ +"\\n" \ +"There is unrest in the Galactic\\n" \ +"Senate. Several thousand solar\\n" \ +"systems have declared their\\n" \ +"intentions to leave the Republic.\\n" \ +"\\n" \ +"This separatist movement,\\n" \ +"under the leadership of the\\n" \ +"mysterious Count Dooku, has\\n" \ +"made it difficult for the limited\\n" \ +"number of Jedi Knights to\\n" \ +"maintain peace and order in the\\n" \ +"galaxy.\\n" \ +"\\n" \ +"Senator Amidala, the former\\n" \ +"Queen of Naboo, is returning\\n" \ +"to the Galactic Senate to vote\\n" \ +"on the critical issue of creating\\n" \ +"an ARMY OF THE REPUBLIC\\n" \ +"to assist the overwhelmed\\n" \ +"Jedi....\\n" \ +"\\n" \ +"\\n" \ +"\\n" \ +"\\n" \ +"\\n" \ +"\\n" \ +"\\n" \ +"\\n" \ +"\\n" \ +"\\n" \ +"\\n" \ +"\\n" \ +"\\n" \ +"\\n" \ +"\\n" \ +"\\n" \ +"\\n" \ +"\\n" \ +"\\n" \ +"\\n" \ +"\\n" \ +"\\n" \ +"\\n" \ +"\\n" \ +"\\n" \ +"\\n" \ +"\\n" \ +"\\n" \ +"Episode III\\n" \ +"\\n" \ +"REVENGE OF THE SITH\\n" \ +"\\n" \ +"War! The Republic is crumbling\\n" \ +"under attacks by the ruthless\\n" \ +"Sith Lord, Count Dooku.\\n" \ +"There are heroes on both sides.\\n" \ +"Evil is everywhere.\\n" \ +"\\n" \ +"In a stunning move, the\\n" \ +"fiendish droid leader, General\\n" \ +"Grievous, has swept into the\\n" \ +"Republic capital and kidnapped\\n" \ +"Chancellor Palpatine, leader of\\n" \ +"the Galactic Senate.\\n" \ +"\\n" \ +"As the Separatist Droid Army\\n" \ +"attempts to flee th besieged\\n" \ +"capital with their valuable\\n" \ +"hostage, two Jedi Knights lead a\\n" \ +"desperate mission to rescue the\\n" \ +"captive Chancellor....\\n" \ +"\\n" \ +"\\n" \ +"\\n" \ +"\\n" \ +"\\n" \ +"\\n" \ +"\\n" \ +"\\n" \ +"\\n" \ +"\\n" \ +"\\n" \ +"\\n" \ +"\\n" \ +"\\n" \ +"\\n" \ +"\\n" \ +"\\n" \ +"\\n" \ +"\\n" \ +"\\n" \ +"\\n" \ +"\\n" \ +"\\n" \ +"\\n" \ +"\\n" \ +"\\n" \ +"\\n" \ +"\\n" diff --git a/hacks/glx/starwars.man b/hacks/glx/starwars.man new file mode 100644 index 00000000..d7dc7f22 --- /dev/null +++ b/hacks/glx/starwars.man @@ -0,0 +1,181 @@ +.de EX \"Begin example +.ne 5 +.if n .sp 1 +.if t .sp .5 +.nf +.in +.5i +.. +.de EE +.fi +.in -.5i +.if n .sp 1 +.if t .sp .5 +.. +.TH XScreenSaver 1 "25-Jul-98" "X Version 11" +.SH NAME +starwars - draws a perspective text crawl, like at the beginning of the movie +.SH SYNOPSIS +.B starwars +[\-display \fIhost:display.screen\fP] [\-window] [\-root] +[\-visual \fIvisual\fP] +[\-delay \fImicroseconds\fP] +[\-program \fIcommand\fP] +[\-size \fIinteger\fP ] +[\-columns \fIinteger\fP] +[\-wrap | \-no\-wrap] +[\-left | \-center | \-right] +[\-lines \fIinteger\fP] +[\-spin \fIfloat\fP] +[\-steps \fIinteger\fP] +[\-delay \fIusecs\fP] +[\-font \fIxlfd\fP] +[\-no\-textures] +[\-no\-smooth] +[\-no\-thick] +[\-fps] +.SH DESCRIPTION +The \fIstarwars\fP program runs another program to generate a stream of +text, then animates that text receeding into the background at an angle, +in front of a star field. +.SH OPTIONS +.I starwars +accepts the following options: +.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 \-install +Install a private colormap for the window. +.TP 8 +.B \-visual \fIvisual\fP\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 \-program \fIsh-command\fP +The command to run to generate the text to display. This option may be +any string acceptable to /bin/sh. The program will be run at the end of +a pipe, and any characters that it prints to \fIstdout\fP will be printed +on the starwars window. If the program exits, it will be launched again +after we have processed all the text it produced. + +Note that starwars is \fInot\fP a terminal emulator: programs that try to +directly address the screen will not do what you might expect. This +program merely draws the characters on the screen left to right, top +to bottom, in perspective. Lines (may) wrap when they reach the right +edge. + +In other words, programs like +.BR fortune (1) +will work, but programs like +.BR top (1) +won't. + +Some examples: +.EX +starwars -program 'cat /usr/src/linux*/README' +starwars -columns 30 -program 'ping www.starwars.com' +starwars -left -no-wrap -program 'ps -auxwwf' +starwars -left -no-wrap -columns 45 -program 'top -bn1' +starwars -left -columns 40 -program 'od -txC /dev/urandom' +starwars -font fixed -program 'od -txC /dev/urandom' +.EE +.TP 8 +.B \-size \fIinteger\fP +How large a font to use, in points. (Well, in some arbitrary unit +we're calling "points" for the sake of argument.) Default: 24. +.TP 8 +.B \-columns \fIinteger\fP +How many columns of text should be visible on the bottom line of the +screen. Default: 60. + +Only one of \fI\-columns\fP and \fI\-size\fP may be specified; +if both are specified, \fI\-columns\fP takes priority. +.TP 8 +.B \-wrap +Word-wrap lines when they reach the rightmost column. This is the default. +.TP 8 +.B \-no\-wrap +Do not word-wrap: just let the lines go off the right side of the screen. +.TP 8 +.B \-left | \-center | \-right +Whether to align the text flush left, centered, or flush right. +The default is centered. +.TP 8 +.B \-lines \fIinteger\fP +How many lines should be allowed to be on the screen before they fall off +the end. The default is 125. +.TP 8 +.B \-spin \fIfloat\fP +The star field on the background slowly rotates. This is how fast. +The default is 0.03. +.TP 8 +.B \-steps \fIinteger\fP +How many steps should be used to scroll a single line. The default is 35. +If the animation looks jerky to you, increase this number. +.TP 8 +.B \-delay \fIusecs\fP +The delay between steps of the animation; default is 40000 (1/25th second.) +.TP 8 +.B \-font \fIfont-name\fP +The name of the font to use. For best effect, this should be a large +font (at least 36 points.) The bigger the font, the better looking the +characters will be. Note that the size of this font affects only the +clarity of the characters, not their size on the screen: for that, use +the \fI\-size\fP or \fI\-columns\fP options. + +Default: -*-utopia-bold-r-normal-*-*-720-*-*-*-*-iso8859-1 +.TP 8 +.B \-no\-textures +Instead of texture-mapping a real font to render the text, use a +built-in font composed of line segments. On graphics cards without +texture support, the line-segment font will have much better +performance. +.TP 8 +.B \-no\-smooth +When using the line-segment font, turn off anti-aliasing of the lines +used to draw the font. This will make the text blockier, but may +improve performance. +.TP 8 +.B \-no\-thick +When using the line-segment font, turn off use of thick lines for the +characters that are close to the foreground. This will make the text +appear unnaturally skinny, but may improve performance. +.TP 8 +.B \-fps +Display the current frame rate, CPU load, and polygon count. +.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 xscreensaver (1), +.BR xscreensaver-text (1), +.BR fortune (1), +.BR phosphor (MANSUFFIX), +.BR apple2 (MANSUFFIX), +.BR fontglide (MANSUFFIX), +.BR ljlatest (MANSUFFIX), +.BR dadadodo (1), +.BR webcollage (MANSUFFIX), +.BR driftnet (1) +.BR EtherPEG , +.BR EtherPeek +.SH COPYRIGHT +Copyright \(co 1998-2005 by Jamie Zawinski and Claudio Matsuoka. +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 and Claudio Matauoka diff --git a/hacks/glx/starwars.txt b/hacks/glx/starwars.txt new file mode 100644 index 00000000..e056f922 --- /dev/null +++ b/hacks/glx/starwars.txt @@ -0,0 +1,311 @@ +Episode IV + +STAR WARS: A NEW HOPE + +It is a period of Civil War. +Rebel Spaceships, striking +from a hidden base, have won +their first victory against +the evil Galactic Empire. + +During the battle, Rebel +spies managed to steal secret +plans to the Empire's +ultimate weapon, the DEATH +STAR, an armored space +station with enough power to +destroy an entire planet. + +Pursued by the Empire's +sinister agents, Princess +Leia races home aboard her +starship, custodian of the +stolen plans that can save +her people and restore +freedom to the galaxy... + + + + + + + + + + + + + + + + + + + + + + + + + + + + +Episode V + +THE EMPIRE STRIKES BACK + +It is a dark time for the +Rebellion. Although the Death +Star has been destroyed, +Imperial troops have driven the +Rebel forces from their hidden +base and pursued them across +the galaxy. + +Evading the dreaded Imperial +Starfleet, a group of freedom +fighters led by Luke Skywalker +has established a new secret +base on the remote ice world +of Hoth. + +The evil lord Darth Vader, +obsessed with finding young +Skywalker, has dispatched +thousands of remote probes into +the far reaches of space.... + + + + + + + + + + + + + + + + + + + + + + + + + + + + +Episode VI + +RETURN OF THE JEDI + +Luke Skywalker has returned to +his home planet of Tatooine in +an attempt to rescue his +friend Han Solo from the +clutches of the vile gangster +Jabba the Hutt. + +Little does Luke know that the +GALACTIC EMPIRE has secretly +begun construction on a new +armored space station even +more powerful than the first +dreaded Death Star. + +When completed, this ultimate +weapon will spell certain doom +for the small band of rebels +struggling to restore freedom +to the galaxy... + + + + + + + + + + + + + + + + + + + + + + + + + + + + +Episode I + +THE PHANTOM MENACE + +Turmoil has engulfed the +Galactic Republic. The taxation +of trade routes to outlying star +systems is in dispute. + +Hoping to resolve the matter +with a blockade of deadly +battleships, the greedy Trade +Federation has stopped all +shipping to the small planet +of Naboo. + +While the Congress of the +Republic endlessly debates +this alarming chain of events, +the Supreme Chancellor has +secretly dispatched two Jedi +Knights, the guardians of +peace and justice in the +galaxy to settle the conflict... + + + + + + + + + + + + + + + + + + + + + + + + + + + + +Episode II + +ATTACK OF THE CLONES + +There is unrest in the Galactic +Senate. Several thousand solar +systems have declared their +intentions to leave the Republic. + +This separatist movement, +under the leadership of the +mysterious Count Dooku, has +made it difficult for the limited +number of Jedi Knights to +maintain peace and order in the +galaxy. + +Senator Amidala, the former +Queen of Naboo, is returning +to the Galactic Senate to vote +on the critical issue of creating +an ARMY OF THE REPUBLIC +to assist the overwhelmed +Jedi.... + + + + + + + + + + + + + + + + + + + + + + + + + + + + +Episode III + +REVENGE OF THE SITH + +War! The Republic is crumbling +under attacks by the ruthless +Sith Lord, Count Dooku. +There are heroes on both sides. +Evil is everywhere. + +In a stunning move, the +fiendish droid leader, General +Grievous, has swept into the +Republic capital and kidnapped +Chancellor Palpatine, leader of +the Galactic Senate. + +As the Separatist Droid Army +attempts to flee th besieged +capital with their valuable +hostage, two Jedi Knights lead a +desperate mission to rescue the +captive Chancellor.... + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/hacks/glx/stonerview-move.c b/hacks/glx/stonerview-move.c new file mode 100644 index 00000000..fc2931d4 --- /dev/null +++ b/hacks/glx/stonerview-move.c @@ -0,0 +1,155 @@ +/* StonerView: An eccentric visual toy. + Copyright 1998-2001 by Andrew Plotkin (erkyrath@eblong.com) + + 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. +*/ + +#include + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include +#include + +#ifndef HAVE_COCOA +# include +#endif + +#ifdef HAVE_JWZGLES +# include "jwzgles.h" +#endif /* HAVE_JWZGLES */ + +#include "yarandom.h" +#include "stonerview.h" + + +void +stonerview_init_move(stonerview_state *st) +{ + /*st->theta = new_osc_linear( + new_osc_wrap(0, 36000, 25), + new_osc_constant(2000));*/ + + st->theta = new_osc_linear(st, + new_osc_velowrap(st, 0, 36000, new_osc_multiplex(st, + new_osc_randphaser(st, 300, 600), + new_osc_constant(st, 25), + new_osc_constant(st, 75), + new_osc_constant(st, 50), + new_osc_constant(st, 100)) + ), + + new_osc_multiplex(st, + new_osc_buffer(st, new_osc_randphaser(st, 300, 600)), + new_osc_buffer(st, new_osc_wrap(st, 0, 36000, 10)), + new_osc_buffer(st, new_osc_wrap(st, 0, 36000, -8)), + new_osc_wrap(st, 0, 36000, 4), + new_osc_buffer(st, new_osc_bounce(st, -2000, 2000, 20)) + ) + ); + + st->rad = new_osc_buffer(st, new_osc_multiplex(st, + new_osc_randphaser(st, 250, 500), + new_osc_bounce(st, -1000, 1000, 10), + new_osc_bounce(st, 200, 1000, -15), + new_osc_bounce(st, 400, 1000, 10), + new_osc_bounce(st, -1000, 1000, -20))); + /*st->rad = new_osc_constant(st, 1000);*/ + + st->alti = new_osc_linear(st, + new_osc_constant(st, -1000), + new_osc_constant(st, 2000 / st->num_els)); + + /*st->alti = new_osc_multiplex( + new_osc_buffer(st, new_osc_randphaser(60, 270)), + new_osc_buffer(st, new_osc_bounce(-1000, 1000, 48)), + new_osc_linear( + new_osc_constant(-1000), + new_osc_constant(2000 / st->num_els)), + new_osc_buffer(st, new_osc_bounce(-1000, 1000, 27)), + new_osc_linear( + new_osc_constant(-1000), + new_osc_constant(2000 / st->num_els)) + );*/ + + /*st->color = new_osc_buffer(st, new_osc_randphaser(5, 35));*/ + + /*st->color = new_osc_buffer(st, new_osc_multiplex( + new_osc_randphaser(25, 70), + new_osc_wrap(0, 3600, 20), + new_osc_wrap(0, 3600, 30), + new_osc_wrap(0, 3600, -20), + new_osc_wrap(0, 3600, 10)));*/ + st->color = new_osc_multiplex(st, + new_osc_buffer(st, new_osc_randphaser(st, 150, 300)), + new_osc_buffer(st, new_osc_wrap(st, 0, 3600, 13)), + new_osc_buffer(st, new_osc_wrap(st, 0, 3600, 32)), + new_osc_buffer(st, new_osc_wrap(st, 0, 3600, 17)), + new_osc_buffer(st, new_osc_wrap(st, 0, 3600, 7))); + + stonerview_move_increment(st); +} + +/* Set up the list of polygon data for rendering. */ +void +stonerview_move_increment(stonerview_state *st) +{ + int ix, val; +/* GLfloat fval; */ +/* GLfloat recipels = (1.0 / (GLfloat)st->num_els); */ + GLfloat pt[2]; + GLfloat ptrad, pttheta; + + for (ix=0; ixnum_els; ix++) { + stonerview_elem_t *el = &st->elist[ix]; + + /* Grab r and theta... */ + val = osc_get(st, st->theta, ix); + pttheta = val * (0.01 * M_PI / 180.0); + ptrad = (GLfloat)osc_get(st, st->rad, ix) * 0.001; + /* And convert them to x,y coordinates. */ + pt[0] = ptrad * cos(pttheta); + pt[1] = ptrad * sin(pttheta); + + /* Set x,y,z. */ + el->pos[0] = pt[0]; + el->pos[1] = pt[1]; + el->pos[2] = (GLfloat)osc_get(st, st->alti, ix) * 0.001; + + /* Set which way the square is rotated. This is fixed for now, although + it would be trivial to make the squares spin as they revolve. */ + el->vervec[0] = 0.11; + el->vervec[1] = 0.0; + + /* Grab the color, and convert it to RGB values. Technically, we're + converting an HSV value to RGB, where S and V are always 1. */ + val = osc_get(st, st->color, ix); + if (val < 1200) { + el->col[0] = ((GLfloat)val / 1200.0); + el->col[1] = 0; + el->col[2] = (GLfloat)(1200 - val) / 1200.0; + } + else if (val < 2400) { + el->col[0] = (GLfloat)(2400 - val) / 1200.0; + el->col[1] = ((GLfloat)(val - 1200) / 1200.0); + el->col[2] = 0; + } + else { + el->col[0] = 0; + el->col[1] = (GLfloat)(3600 - val) / 1200.0; + el->col[2] = ((GLfloat)(val - 2400) / 1200.0); + } + el->col[3] = 1.0; + } + + osc_increment(st); +} + diff --git a/hacks/glx/stonerview-move.h b/hacks/glx/stonerview-move.h new file mode 100644 index 00000000..a3e0acd2 --- /dev/null +++ b/hacks/glx/stonerview-move.h @@ -0,0 +1,32 @@ +/* StonerView: An eccentric visual toy. + Copyright 1998-2001 by Andrew Plotkin (erkyrath@eblong.com) + + 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. +*/ + +#ifndef __STONERVIEW_MOVE_H__ +#define __STONERVIEW_MOVE_H__ + +typedef struct { + GLfloat pos[3]; + GLfloat vervec[2]; + GLfloat col[4]; +} stonerview_elem_t; + +extern void stonerview_init_move(stonerview_state *); +extern void stonerview_final_move(stonerview_state *); +extern void stonerview_move_increment(stonerview_state *); + + +extern stonerview_state * stonerview_init_view(int wireframe_p, + int transparent_p); +extern void stonerview_win_draw(stonerview_state *); +extern void stonerview_win_release(stonerview_state *); + +#endif /* __STONERVIEW_MOVE_H__ */ diff --git a/hacks/glx/stonerview-osc.c b/hacks/glx/stonerview-osc.c new file mode 100644 index 00000000..1b79a236 --- /dev/null +++ b/hacks/glx/stonerview-osc.c @@ -0,0 +1,341 @@ +/* StonerView: An eccentric visual toy. + Copyright 1998-2001 by Andrew Plotkin (erkyrath@eblong.com) + + 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. +*/ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include +#include + +#include "yarandom.h" +#include "stonerview.h" + + +/* Return a random number between min and max, inclusive. */ +static int rand_range(int min, int max) +{ + int res; + unsigned int diff = (max+1) - min; + if (diff <= 1) + return min; + res = random() % diff; + return min+res; +} + + +/* Create a new, blank osc_t. The caller must fill in the type data. */ +static osc_t *create_osc(stonerview_state *st, int type) +{ + osc_t *osc = (osc_t *)malloc(sizeof(osc_t)); + if (!osc) + return NULL; + + osc->type = type; + osc->next = NULL; + + *st->osctail = osc; + st->osctail = &(osc->next); + + return osc; +} + +/* Creation functions for all the osc_t types. These are all pretty obvious + in their construction. */ + +osc_t *new_osc_constant(stonerview_state *st, int val) +{ + osc_t *osc = create_osc(st, otyp_Constant); + if (!osc) + return NULL; + + osc->u.oconstant.val = val; + return osc; +} + +osc_t *new_osc_bounce(stonerview_state *st, int min, int max, int step) +{ + int diff; + osc_t *osc = create_osc(st, otyp_Bounce); + if (!osc) + return NULL; + + osc->u.obounce.min = min; + osc->u.obounce.max = max; + osc->u.obounce.step = step; + + /* Pick a random initial value between min and max. */ + if (step < 0) + step = (-step); + diff = (max-min) / step; + osc->u.obounce.val = min + step * rand_range(0, diff-1); + + return osc; +} + +osc_t *new_osc_wrap(stonerview_state *st, int min, int max, int step) +{ + int diff; + osc_t *osc = create_osc(st, otyp_Wrap); + if (!osc) + return NULL; + + osc->u.owrap.min = min; + osc->u.owrap.max = max; + osc->u.owrap.step = step; + + /* Pick a random initial value between min and max. */ + if (step < 0) + step = (-step); + diff = (max-min) / step; + osc->u.owrap.val = min + step * rand_range(0, diff-1); + + return osc; +} + +osc_t *new_osc_velowrap(stonerview_state *st, int min, int max, osc_t *step) +{ + osc_t *osc = create_osc(st, otyp_VeloWrap); + if (!osc) + return NULL; + + osc->u.ovelowrap.min = min; + osc->u.ovelowrap.max = max; + osc->u.ovelowrap.step = step; + + /* Pick a random initial value between min and max. */ + osc->u.ovelowrap.val = rand_range(min, max); + + return osc; +} + +osc_t *new_osc_multiplex(stonerview_state *st, + osc_t *sel, osc_t *ox0, + osc_t *ox1, osc_t *ox2, + osc_t *ox3) +{ + osc_t *osc = create_osc(st, otyp_Multiplex); + if (!osc) + return NULL; + + osc->u.omultiplex.sel = sel; + osc->u.omultiplex.val[0] = ox0; + osc->u.omultiplex.val[1] = ox1; + osc->u.omultiplex.val[2] = ox2; + osc->u.omultiplex.val[3] = ox3; + + return osc; +} + +osc_t *new_osc_phaser(stonerview_state *st, int phaselen) +{ + osc_t *osc = create_osc(st, otyp_Phaser); + if (!osc) + return NULL; + + osc->u.ophaser.phaselen = phaselen; + + osc->u.ophaser.count = 0; + /* Pick a random phase to start in. */ + osc->u.ophaser.curphase = rand_range(0, NUM_PHASES-1); + + return osc; +} + +osc_t *new_osc_randphaser(stonerview_state *st, + int minphaselen, int maxphaselen) +{ + osc_t *osc = create_osc(st, otyp_RandPhaser); + if (!osc) + return NULL; + + osc->u.orandphaser.minphaselen = minphaselen; + osc->u.orandphaser.maxphaselen = maxphaselen; + + osc->u.orandphaser.count = 0; + /* Pick a random phaselen to start with. */ + osc->u.orandphaser.curphaselen = rand_range(minphaselen, maxphaselen); + /* Pick a random phase to start in. */ + osc->u.orandphaser.curphase = rand_range(0, NUM_PHASES-1); + + return osc; +} + +osc_t *new_osc_linear(stonerview_state *st, osc_t *base, osc_t *diff) +{ + osc_t *osc = create_osc(st, otyp_Linear); + if (!osc) + return NULL; + + osc->u.olinear.base = base; + osc->u.olinear.diff = diff; + + return osc; +} + +osc_t *new_osc_buffer(stonerview_state *st, osc_t *val) +{ + int ix; + osc_t *osc = create_osc(st, otyp_Buffer); + if (!osc) + return NULL; + + osc->u.obuffer.val = val; + osc->u.obuffer.firstel = st->num_els-1; + + /* The last N values are stored in a ring buffer, which we must initialize + here. */ + for (ix=0; ixnum_els; ix++) { + osc->u.obuffer.el[ix] = osc_get(st, val, 0); + } + + return osc; +} + +/* Compute f(i,el) for the current i. */ +int osc_get(stonerview_state *st, osc_t *osc, int el) +{ + if (!osc) + return 0; + + switch (osc->type) { + + case otyp_Constant: + return osc->u.oconstant.val; + + case otyp_Bounce: + return osc->u.obounce.val; + + case otyp_Wrap: + return osc->u.owrap.val; + + case otyp_VeloWrap: + return osc->u.ovelowrap.val; + + case otyp_Linear: + return osc_get(st, osc->u.olinear.base, el) + + el * osc_get(st, osc->u.olinear.diff, el); + + case otyp_Multiplex: { + struct omultiplex_struct *ox = &(osc->u.omultiplex); + int sel = osc_get(st, ox->sel, el); + return osc_get(st, ox->val[sel % NUM_PHASES], el); + } + + case otyp_Phaser: { + struct ophaser_struct *ox = &(osc->u.ophaser); + return ox->curphase; + } + + case otyp_RandPhaser: { + struct orandphaser_struct *ox = &(osc->u.orandphaser); + return ox->curphase; + } + + case otyp_Buffer: { + struct obuffer_struct *ox = &(osc->u.obuffer); + return ox->el[(ox->firstel + el) % st->num_els]; + } + + default: + return 0; + } +} + +/* Increment i. This affects all osc_t objects; we go down the linked list to + get them all. */ +void osc_increment(stonerview_state *st) +{ + osc_t *osc; + + for (osc = st->oscroot; osc; osc = osc->next) { + switch (osc->type) { + + case otyp_Bounce: { + struct obounce_struct *ox = &(osc->u.obounce); + ox->val += ox->step; + if (ox->val < ox->min && ox->step < 0) { + ox->step = -(ox->step); + ox->val = ox->min + (ox->min - ox->val); + } + if (ox->val > ox->max && ox->step > 0) { + ox->step = -(ox->step); + ox->val = ox->max + (ox->max - ox->val); + } + break; + } + + case otyp_Wrap: { + struct owrap_struct *ox = &(osc->u.owrap); + ox->val += ox->step; + if (ox->val < ox->min && ox->step < 0) { + ox->val += (ox->max - ox->min); + } + if (ox->val > ox->max && ox->step > 0) { + ox->val -= (ox->max - ox->min); + } + break; + } + + case otyp_VeloWrap: { + struct ovelowrap_struct *ox = &(osc->u.ovelowrap); + int diff = (ox->max - ox->min); + ox->val += osc_get(st, ox->step, 0); + while (ox->val < ox->min) + ox->val += diff; + while (ox->val > ox->max) + ox->val -= diff; + break; + } + + case otyp_Phaser: { + struct ophaser_struct *ox = &(osc->u.ophaser); + ox->count++; + if (ox->count >= ox->phaselen) { + ox->count = 0; + ox->curphase++; + if (ox->curphase >= NUM_PHASES) + ox->curphase = 0; + } + break; + } + + case otyp_RandPhaser: { + struct orandphaser_struct *ox = &(osc->u.orandphaser); + ox->count++; + if (ox->count >= ox->curphaselen) { + ox->count = 0; + ox->curphaselen = rand_range(ox->minphaselen, ox->maxphaselen); + ox->curphase++; + if (ox->curphase >= NUM_PHASES) + ox->curphase = 0; + } + break; + } + + case otyp_Buffer: { + struct obuffer_struct *ox = &(osc->u.obuffer); + ox->firstel--; + if (ox->firstel < 0) + ox->firstel += st->num_els; + ox->el[ox->firstel] = osc_get(st, ox->val, 0); + /* We can assume that ox->val has already been incremented, since it + was created first. This is why new objects are put on the end + of the linked list... yeah, it's gross. */ + break; + } + + default: + break; + } + } +} diff --git a/hacks/glx/stonerview-osc.h b/hacks/glx/stonerview-osc.h new file mode 100644 index 00000000..b8c07780 --- /dev/null +++ b/hacks/glx/stonerview-osc.h @@ -0,0 +1,175 @@ +/* StonerView: An eccentric visual toy. + Copyright 1998-2001 by Andrew Plotkin (erkyrath@eblong.com) + + 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. +*/ + +#ifndef __STONERVIEW_OSC_H__ +#define __STONERVIEW_OSC_H__ + +/* This defines the osc_t object, which generates a stream of + numbers. It is the heart of the StonerSound/StonerView engine. + + The idea is simple; an osc_t represents some function f(), which + can be evaluated to generate an infinite stream of integers (f(0), + f(1), f(2), f(3)...). Some of these functions are defined in + terms of other osc_t functions: f(i) = g(h(i)) or some such thing. + + To simplify the code, we don't try to calculate f(i) for any + arbitrary i. Instead, we start with i=0. Calling osc_get(f) + returns f(0) for all osc_t's in the system. When we're ready, we + call osc_increment(), which advances every osc_t to i=1; + thereafter, calling osc_get(f) returns f(1). When you call + osc_increment() again, you get f(2). And so on. You can't go + backwards, or move forwards more than 1 at a time, or move some + osc_t's without moving others. This is a very restricted model, but + it's exactly what's needed for this system. + + Now, there's an additional complication. To get the rippling + effect, we don't pull out single values, but *sets* of N elements + at a time. (N is defined by NUM_ELS below.) So f(i) is really an + ordered N-tuple (f(i,0), f(i,1), f(i,2), f(i,3), f(i,4)). And f() + generates an infinite stream of these N-tuples. The osc_get() call + really has two parameters; you call osc_get(f, n) to find the n'th + element of the current N-tuple. Remember, n must be between 0 and + n-1. + + (Do *not* try to get an infinite stream f(i) by calling + osc_get(f, i) for i ranging to infinity! Use osc_increment() to + advance to the next N-tuple in the stream.) +*/ + +#define NUM_ELS (40) /* Forty polygons at a time. */ + +#define NUM_PHASES (4) /* Some of the osc functions switch between P + alternatives. We arbitrarily choose P=4. */ + +/* Here are the functions which are available. + Constant: f(i,n) = k. Always the same value. Very simple. + Wrap: f(i,n) slides up or down as i increases. There's a minimum and maximum + value, and a step. When the current value reaches the min or max, it jumps + to the other end and keeps moving the same direction. + Bounce: f(i,n) slides up and down as i increases. There's a minimum and + maximum value, and a step. When the current value reaches the min or max, + the step is flipped to move the other way. + Phaser: f(i,n) = floor(i / phaselen) modulo 4. That is, it generates + phaselen 0 values, and then phaselen 1 values, then phaselen 2 values, + then phaselen 3 values, then back to 0. (Phaselen is a parameter you + supply when you create the phaser.) As you see, this is much the same as + the Wrap function, with a minimum of 0, a maximum of 3, and a step of + 1/phaselen. But since this code uses integer math, fractional steps + aren't possible; it's easier to write a separate function. + RandPhaser: The same as Phaser, but the phaselen isn't fixed. It varies + randomly between a minimum and maximum value you supply. + Multiplex: There are five subsidiary functions within a multiplex function: + g0, g1, g2, g3, and a selector function s. Then: + f(i,n) = gX(i,n), where X = s(i,n). (Obviously s must generate only values + in the range 0 to 3. This is what the phaser functions are designed for, + but you can use anything.) + Linear: There are two subsidiary functions within this, a and b. Then: + f(i,n) = a(i,n) + n*b(i,n). This is an easy way to make an N-tuple that + forms a linear sequence, such as (41, 43, 45, 47, 49). + Buffer: This takes a subsidiary function g, and computes: + f(i,n) = g(i-n,0). That is, the 0th element of the N-tuple is the + *current* value of g; the 1st element is the *previous* value of g; the + 2nd element is the second-to-last value, and so on back in time. This + is a weird idea, but it causes exactly the rippling-change effect that + we want. + + Note that Buffer only looks up g(i,0) -- it only uses the 0th elements of + the N-tuples that g generates. This saves time and memory, but it means + that certain things don't work. For example, if you try to build + Buffer(Linear(A,B)), B will have no effect, because Linear computes + a(i,n) + n*b(i,n), and inside the Buffer, n is always zero. On the other + hand, Linear(Buffer(A),Buffer(B)) works fine, and is probably what you + wanted anyway. + Similarly, Buffer(Buffer(A)) is the same as Buffer(A). Proof left as an + exercise. +*/ + +#define otyp_Constant (1) +#define otyp_Bounce (2) +#define otyp_Wrap (3) +#define otyp_Phaser (4) +#define otyp_RandPhaser (5) +#define otyp_VeloWrap (7) +#define otyp_Linear (6) +#define otyp_Buffer (8) +#define otyp_Multiplex (9) + +/* The osc_t structure itself. */ +typedef struct osc_struct { + int type; /* An otyp_* constant. */ + + struct osc_struct *next; /* osc.c uses this to maintain a private linked list + of all osc_t objects created. */ + + /* Union of the data used by all the possible osc_t functions. */ + union { + struct { + int val; + } oconstant; + struct owrap_struct { + int min, max, step; + int val; + } owrap; + struct obounce_struct { + int min, max, step; + int val; + } obounce; + struct omultiplex_struct { + struct osc_struct *sel; + struct osc_struct *val[NUM_PHASES]; + } omultiplex; + struct ophaser_struct { + int phaselen; + int count; + int curphase; + } ophaser; + struct orandphaser_struct { + int minphaselen, maxphaselen; + int count; + int curphaselen; + int curphase; + } orandphaser; + struct ovelowrap_struct { + int min, max; + struct osc_struct *step; + int val; + } ovelowrap; + struct olinear_struct { + struct osc_struct *base; + struct osc_struct *diff; + } olinear; + struct obuffer_struct { + struct osc_struct *val; + int firstel; + int el[NUM_ELS]; + } obuffer; + } u; +} osc_t; + +extern osc_t *new_osc_constant(stonerview_state *, int val); +extern osc_t *new_osc_bounce(stonerview_state *, int min, int max, int step); +extern osc_t *new_osc_wrap(stonerview_state *, int min, int max, int step); +extern osc_t *new_osc_phaser(stonerview_state *, int phaselen); +extern osc_t *new_osc_randphaser(stonerview_state *, + int minphaselen, int maxphaselen); +extern osc_t *new_osc_velowrap(stonerview_state *, + int min, int max, osc_t *step); +extern osc_t *new_osc_linear(stonerview_state *, osc_t *base, osc_t *diff); +extern osc_t *new_osc_buffer(stonerview_state *st, osc_t *val); +extern osc_t *new_osc_multiplex(stonerview_state *, + osc_t *sel, osc_t *ox0, osc_t *ox1, + osc_t *ox2, osc_t *ox3); + +extern int osc_get(stonerview_state *, osc_t *osc, int el); +extern void osc_increment(stonerview_state *); + +#endif /* __STONERVIEW_OSC_H__ */ diff --git a/hacks/glx/stonerview-view.c b/hacks/glx/stonerview-view.c new file mode 100644 index 00000000..d66eab28 --- /dev/null +++ b/hacks/glx/stonerview-view.c @@ -0,0 +1,116 @@ +/* StonerView: An eccentric visual toy. + Copyright 1998-2001 by Andrew Plotkin (erkyrath@eblong.com) + http://www.eblong.com/zarf/stonerview.html + + 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. +*/ + +/* Ported away from GLUT (so that it can do `-root' and work with xscreensaver) + by Jamie Zawinski , 22-Jan-2001. + */ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include +#include "stonerview.h" + +static GLfloat view_rotx = -45.0, view_roty = 0.0, view_rotz = 15.0; +static GLfloat view_scale = 4.0; + + +stonerview_state * +stonerview_init_view(int wireframe_p, int transparent_p) +{ + stonerview_state *st = (stonerview_state *) calloc (1, sizeof(*st)); + + st->wireframe = wireframe_p; + st->transparent = transparent_p; + st->num_els = NUM_ELS; + st->elist = (stonerview_elem_t *) calloc (st->num_els, sizeof(*st->elist)); + + st->osctail = &st->oscroot; + + /* for trackball, two-sided lighting and no face culling */ + glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, GL_TRUE); + + glEnable(GL_CULL_FACE); + glEnable(GL_LIGHTING); + glEnable(GL_LIGHT0); + glEnable(GL_DEPTH_TEST); + + glEnable(GL_NORMALIZE); + + glHint(GL_LINE_SMOOTH_HINT, GL_NICEST); + glEnable(GL_LINE_SMOOTH); + glEnable(GL_BLEND); + + if (st->transparent) + glBlendFunc(GL_SRC_ALPHA,GL_ONE); + + return st; +} + +/* callback: draw everything */ +void +stonerview_win_draw(stonerview_state *st) +{ + int ix; + static const GLfloat white[] = { 1.0, 1.0, 1.0, 1.0 }; + static const GLfloat gray[] = { 0.6, 0.6, 0.6, 1.0 }; + + glDrawBuffer(GL_BACK); + + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + + glPushMatrix(); + glScalef(view_scale, view_scale, view_scale); + glRotatef(view_rotx, 1.0, 0.0, 0.0); + glRotatef(view_roty, 0.0, 1.0, 0.0); + glRotatef(view_rotz, 0.0, 0.0, 1.0); + + glShadeModel(GL_FLAT); + + for (ix=0; ix < st->num_els; ix++) { + stonerview_elem_t *el = &st->elist[ix]; + + glNormal3f(0.0, 0.0, 1.0); + + /* outline the square */ + glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, (st->wireframe ? white : gray)); + glBegin(GL_LINE_LOOP); + glVertex3f(el->pos[0]-el->vervec[0], el->pos[1]-el->vervec[1], el->pos[2]); + glVertex3f(el->pos[0]+el->vervec[1], el->pos[1]-el->vervec[0], el->pos[2]); + glVertex3f(el->pos[0]+el->vervec[0], el->pos[1]+el->vervec[1], el->pos[2]); + glVertex3f(el->pos[0]-el->vervec[1], el->pos[1]+el->vervec[0], el->pos[2]); + glEnd(); + + if (st->wireframe) continue; + + /* fill the square */ + glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, el->col); + glBegin(GL_QUADS); + glVertex3f(el->pos[0]-el->vervec[0], el->pos[1]-el->vervec[1], el->pos[2]); + glVertex3f(el->pos[0]+el->vervec[1], el->pos[1]-el->vervec[0], el->pos[2]); + glVertex3f(el->pos[0]+el->vervec[0], el->pos[1]+el->vervec[1], el->pos[2]); + glVertex3f(el->pos[0]-el->vervec[1], el->pos[1]+el->vervec[0], el->pos[2]); + glEnd(); + } + + glPopMatrix(); +} + +void +stonerview_win_release(stonerview_state *st) +{ + free (st->elist); + /*free (st->oscroot); -- #### how do we free this? */ + free (st); +} diff --git a/hacks/glx/stonerview.c b/hacks/glx/stonerview.c new file mode 100644 index 00000000..0e11395e --- /dev/null +++ b/hacks/glx/stonerview.c @@ -0,0 +1,189 @@ +/* StonerView: An eccentric visual toy. + Copyright 1998-2001 by Andrew Plotkin (erkyrath@eblong.com) + + For the latest version, source code, and links to more of my stuff, see: + http://www.eblong.com/zarf/stonerview.html + + 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. +*/ + +/* Ported away from GLUT (so that it can do `-root' and work with xscreensaver) + by Jamie Zawinski , 22-Jan-2001. + + Revamped to work in the xlockmore framework so that it will also work + with the MacOS X port of xscreensaver by jwz, 21-Feb-2006. + */ + +#define DEFAULTS "*delay: 20000 \n" \ + "*showFPS: False \n" \ + "*wireframe: False \n" + +# define refresh_stonerview 0 +#undef countof +#define countof(x) (sizeof((x))/sizeof((*x))) + +#include "xlockmore.h" + +#ifdef USE_GL /* whole file */ + +#include "stonerview.h" +#include "gltrackball.h" + +#define DEF_TRANSPARENT "True" + +typedef struct { + GLXContext *glx_context; + stonerview_state *st; + trackball_state *trackball; + Bool button_down_p; +} stonerview_configuration; + +static stonerview_configuration *bps = NULL; + +static Bool transparent_p; + + +static XrmOptionDescRec opts[] = { + { "-transparent", ".transparent", XrmoptionNoArg, "True" }, + { "+transparent", ".transparent", XrmoptionNoArg, "False" }, +}; + +static argtype vars[] = { + {&transparent_p, "transparent", "Transparent", DEF_TRANSPARENT, t_Bool}, +}; + +ENTRYPOINT ModeSpecOpt stonerview_opts = {countof(opts), opts, countof(vars), vars, NULL}; + + +ENTRYPOINT void +reshape_stonerview (ModeInfo *mi, int width, int height) +{ + GLfloat h = (GLfloat) height / (GLfloat) width; + + glViewport(0, 0, (GLint) width, (GLint) height); + glMatrixMode(GL_PROJECTION); + glLoadIdentity(); + glFrustum(-1.0, 1.0, -h, h, 5.0, 60.0); + glMatrixMode(GL_MODELVIEW); + glLoadIdentity(); + glTranslatef(0.0, 0.0, -40.0); +} + + +ENTRYPOINT void +init_stonerview (ModeInfo *mi) +{ + stonerview_configuration *bp; + + if (!bps) { + bps = (stonerview_configuration *) + calloc (MI_NUM_SCREENS(mi), sizeof (stonerview_configuration)); + if (!bps) { + fprintf(stderr, "%s: out of memory\n", progname); + exit(1); + } + } + + bp = &bps[MI_SCREEN(mi)]; + + bp->glx_context = init_GL(mi); + + bp->trackball = gltrackball_init (); + bp->st = stonerview_init_view(MI_IS_WIREFRAME(mi), transparent_p); + stonerview_init_move(bp->st); + + reshape_stonerview (mi, MI_WIDTH(mi), MI_HEIGHT(mi)); + clear_gl_error(); /* WTF? sometimes "invalid op" from glViewport! */ +} + + +ENTRYPOINT void +draw_stonerview (ModeInfo *mi) +{ + stonerview_configuration *bp = &bps[MI_SCREEN(mi)]; + + glXMakeCurrent(MI_DISPLAY(mi), MI_WINDOW(mi), *(bp->glx_context)); + + glPushMatrix (); + glRotatef( current_device_rotation(), 0, 0, 1); + gltrackball_rotate (bp->trackball); + + stonerview_win_draw(bp->st); + if (! bp->button_down_p) + stonerview_move_increment(bp->st); + glPopMatrix (); + + mi->polygon_count = NUM_ELS; + if (mi->fps_p) do_fps (mi); + glFinish(); + + glXSwapBuffers(MI_DISPLAY (mi), MI_WINDOW(mi)); +} + +ENTRYPOINT void +release_stonerview (ModeInfo *mi) +{ + if (bps) { + int screen; + for (screen = 0; screen < MI_NUM_SCREENS(mi); screen++) { + stonerview_configuration *bp = &bps[screen]; + if (bp->st) + stonerview_win_release (bp->st); + } + free (bps); + bps = 0; + } + FreeAllGL(mi); +} + +ENTRYPOINT Bool +stonerview_handle_event (ModeInfo *mi, XEvent *event) +{ + stonerview_configuration *bp = &bps[MI_SCREEN(mi)]; + + if (event->xany.type == ButtonPress && + event->xbutton.button == Button1) + { + bp->button_down_p = True; + gltrackball_start (bp->trackball, + event->xbutton.x, event->xbutton.y, + MI_WIDTH (mi), MI_HEIGHT (mi)); + return True; + } + else if (event->xany.type == ButtonRelease && + event->xbutton.button == Button1) + { + bp->button_down_p = False; + return True; + } + else if (event->xany.type == ButtonPress && + (event->xbutton.button == Button4 || + event->xbutton.button == Button5 || + event->xbutton.button == Button6 || + event->xbutton.button == Button7)) + { + gltrackball_mousewheel (bp->trackball, event->xbutton.button, 10, + !!event->xbutton.state); + return True; + } + else if (event->xany.type == MotionNotify && + bp->button_down_p) + { + gltrackball_track (bp->trackball, + event->xmotion.x, event->xmotion.y, + MI_WIDTH (mi), MI_HEIGHT (mi)); + return True; + } + + return False; +} + +XSCREENSAVER_MODULE ("StonerView", stonerview) + +#endif /* USE_GL */ diff --git a/hacks/glx/stonerview.h b/hacks/glx/stonerview.h new file mode 100644 index 00000000..afbd53c5 --- /dev/null +++ b/hacks/glx/stonerview.h @@ -0,0 +1,67 @@ +/* StonerView: An eccentric visual toy. + Copyright 1998-2001 by Andrew Plotkin (erkyrath@eblong.com) + + 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. +*/ + +#ifndef __STONERVIEW_H__ +# define __STONERVIEW_H__ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif /* HAVE_CONFIG_H */ + +#ifndef HAVE_COCOA +# include +#endif + +#ifdef HAVE_JWZGLES +# include "jwzgles.h" +#endif /* HAVE_JWZGLES */ + +typedef struct stonerview_state stonerview_state; + +#include "stonerview-osc.h" +#include "stonerview-move.h" + +struct stonerview_state { + + int wireframe; + int transparent; + + /* The list of polygons. This is filled in by move_increment(), and rendered + by perform_render(). */ + int num_els; + stonerview_elem_t *elist; + + /* A linked list of all osc_t objects created. New objects are added + to the end of the list, not the beginning. */ + osc_t *oscroot; + osc_t **osctail; + + /* The polygons are controlled by four parameters. Each is represented by + an osc_t object, which is just something that returns a stream of numbers. + (Originally the name stood for "oscillator", but it does ever so much more + now... see osc.c.) + Imagine a cylinder with a vertical axis (along the Z axis), stretching + from Z=1 to Z=-1, and a radius of 1. + */ + osc_t *theta; /* Angle around the axis. This is expressed in + hundredths of a degree, so it's actually 0 to 36000. */ + osc_t *rad; /* Distance from the axis. This goes up to 1000, + but we actually allow negative distances -- that just + goes to the opposite side of the circle -- so the range + is really -1000 to 1000. */ + osc_t *alti; /* Height (Z position). This goes from -1000 to 1000. */ + osc_t *color; /* Consider this to be an angle of a circle going + around the color wheel. It's in tenths of a degree + (consistency is all I ask) so it ranges from 0 to 3600. */ +}; + +#endif /* __STONERVIEW_H__ */ diff --git a/hacks/glx/stonerview.man b/hacks/glx/stonerview.man new file mode 100644 index 00000000..820e9af1 --- /dev/null +++ b/hacks/glx/stonerview.man @@ -0,0 +1,53 @@ +.TH XScreenSaver 1 "" "X Version 11" +.SH NAME +stonerview - 3D undulating ribbons of squares. +.SH SYNOPSIS +.B stonerview +[\-display \fIhost:display.screen\fP] +[\-visual \fIvisual\fP] +[\-window] +[\-root] +[\-wireframe] +[\-fps] +.SH DESCRIPTION +Chains of colorful squares dance around each other in complex spiral +patterns. This is a clone of the SGI "electropaint" screen saver. +.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 \-wireframe +Render in wireframe instead of solid. +.TP 8 +.B \-fps +Display the current frame rate, CPU load, and polygon count. +.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 2002 by Andrew Plotkin. 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 +Andrew Plotkin. diff --git a/hacks/glx/superquadrics.c b/hacks/glx/superquadrics.c new file mode 100644 index 00000000..f52cc6b2 --- /dev/null +++ b/hacks/glx/superquadrics.c @@ -0,0 +1,797 @@ +/* -*- Mode: C; tab-width: 4 -*- */ +/* superquadrics --- 3D mathematical shapes */ + +#if 0 +static const char sccsid[] = "@(#)superquadrics.c 4.07 97/11/24 xlockmore"; +#endif + +/*- + * Permission to use, copy, modify, and distribute this software and its + * documentation for any purpose and without fee is hereby granted, + * provided that the above copyright notice appear in all copies and that + * both that copyright notice and this permission notice appear in + * supporting documentation. + * + * This file is provided AS IS with no warranties of any kind. The author + * shall have no liability with respect to the infringement of copyrights, + * trade secrets or any patents by this file or any part thereof. In no + * event will the author be liable for any lost revenue or profits or + * other special, indirect and consequential damages. + * + * Superquadrics were invented by Dr. Alan Barr of Caltech University. + * They were first published in "Computer Graphics and Applications", + * volume 1, number 1, 1981, in the article "Superquadrics and Angle- + * Preserving Transformations." Dr. Barr based the Superquadrics on + * Piet Hein's "super ellipses." Super ellipses are like 2D ellipses, + * except that the formula includes an exponent, raising its X and Y + * values to a (fractional) power, and allowing them to gradually + * change from round to square edges. Superquadrics extend this + * idea into 3 dimensions, using two exponents to modify a + * quadric surface in a similar fashion. + * + * Revision History: + * 30-Mar-97: Turned into a module for xlockmore 4.02 alpha. The code + * is almost unrecognizable now from the first revision, except for + * a few remaining two-letter variable names. I still don't have + * the normal vectors working right (I wrote the buggy normal vector + * code myself, can you tell?) + * 07-Jan-97: A legend reborn; Superquadrics make an appearance as a + * real OpenGL program written in C. I can even render them with + * proper lighting and specular highlights. Gee, they look almost + * as good now as the original color plates of them that my uncle + * showed me as a child in 1981. I don't know what computer hardware + * he was using at the time, but it's taken a couple decades for the + * PC clone hardware to catch up to it. + * 05-Jan-97: After almost a decade, Superquadrics had almost faded away + * into the myths and folklore of all the things my brother and I played + * with on computers when we were kids with too much time on our hands. + * I had since gotten involved in Unix, OpenGL, and other things. + * A sudden flash of inspiration caused me to dig out the old Pascal + * source code, run it through p2c, and start ripping away the old + * wireframe rendering code, to be replaced by OpenGL. + * Late 1989 or early 1990: Around this time I did the Turbo Pascal + * port of the Superquadrics. Unfortunately, many of the original variable + * names remained the same from the C= 64 original. This was unfortunate + * because BASIC on the c64 only allowed 2-letter, global variable names. + * But the speed improvement over BASIC was very impressive at the time. + * Thanksgiving, 1987: Written. My uncle Al, who invented Superquadrics some + * years earlier, came to visit us. I was a high school kid at the time, + * with nothing more than a Commodore 64. Somehow we wrote this program, + * (he did the math obviously, I just coded it into BASIC for the c64). + * Yeah, 320x200 resolution, colorless white wireframe, and half an hour + * rendering time per superquadric. PLOT x,y. THOSE were the days. + * In the following years I would port Superquadrics to AppleBASIC, + * AmigaBASIC, and then Turbo Pascal for IBM clones. 5 minutes on a 286! + * Talk about fast rendering! But these days, when my Pentium 166 runs + * the same program, the superquadric will already be waiting on the + * screen before my monitor can change frequency from text to graphics + * mode. Can't time the number of minutes that way! Darn ;) + * + * Ed Mackey + */ + +#ifdef STANDALONE +# define DEFAULTS "*delay: 40000 \n" \ + "*count: 25 \n" \ + "*cycles: 40 \n" \ + "*showFPS: False \n" \ + "*wireframe: False \n" + +# define superquadrics_handle_event 0 +# include "xlockmore.h" /* from the xscreensaver distribution */ +#else /* !STANDALONE */ +# include "xlock.h" /* from the xlockmore distribution */ +#endif /* !STANDALONE */ + +#ifdef USE_GL + +/*- + * Note for low-CPU-speed machines: If your frame rate is so low that + * attempts at animation appear futile, try using "-cycles 1", which puts + * Superquadrics into kind of a slide-show mode. It will still use up + * all of your CPU power, but it may look nicer. + */ + +#define DEF_SPINSPEED "5.0" + +static float spinspeed; + +static XrmOptionDescRec opts[] = +{ + {"-spinspeed", ".superquadrics.spinspeed", XrmoptionSepArg, 0} +}; +static argtype vars[] = +{ + {&spinspeed, "spinspeed", "Spinspeed", DEF_SPINSPEED, t_Float} +}; +static OptionStruct desc[] = +{ + {"-spinspeed num", "speed of rotation, in degrees per frame"} +}; + +ENTRYPOINT ModeSpecOpt superquadrics_opts = +{sizeof opts / sizeof opts[0], opts, sizeof vars / sizeof vars[0], vars, desc}; + +#ifdef USE_MODULES +ModStruct superquadrics_description = +{"superquadrics", "init_superquadrics", "draw_superquadrics", "release_superquadrics", + "refresh_superquadrics", "init_superquadrics", NULL, &superquadrics_opts, + 1000, 25, 40, 1, 4, 1.0, "", + "Shows 3D mathematical shapes", 0, NULL}; + +#endif + +#define MaxRes 50 +#define MinRes 5 + +typedef double dimi[MaxRes + 1]; + +typedef struct { + double xExponent, yExponent; + GLfloat r[4], g[4], b[4]; + long Mode; + int rotx, rotz; +} state; + +typedef struct { + GLXContext *glx_context; + int dist, wireframe, flatshade, shownorms, maxcount, maxwait; + int counter, viewcount, viewwait, mono; + GLfloat curmat[4][4], rotx, roty, rotz, spinspeed; + /* In dimi: the first letter stands for cosine/sine, the second + * stands for North, South, East, or West. I think. + */ + dimi cs, se, sw, sn, ss, ce, cw, cn, Prevxx, Prevyy, Prevzz, + Prevxn, Prevyn, Prevzn; + double xExponent, yExponent, Mode; + int resolution; + state now, later; + + int pats[4][4]; + int cullmode; + +} superquadricsstruct; + +static superquadricsstruct *superquadrics = NULL; + +#define CLIP_NORMALS 10000.0 + +static void ReshapeSuperquadrics(int w, int h); + +static int +myrand(int range) +{ + return ((int) (((float) range) * LRAND() / (MAXRAND))); +} + +static float +myrandreal(void) +{ + return (LRAND() / (MAXRAND)); +} + +/* Some old, old, OLD code follows. Ahh this takes me back..... */ + +/* Output from p2c, the Pascal-to-C translator */ +/* From input file "squad.pas" */ + +static double +XtoY(double x, double y) +{ + double z, a; + + /* This is NOT your typical raise-X-to-the-Y-power function. Do not attempt + * to replace this with a standard exponent function. If you must, just + * replace the "a = exp(y * log(z));" line with something faster. + */ + + z = fabs(x); + if (z < 1e-20) { + a = 0.0; + return a; + } + a = exp(y * log(z)); + if (a > CLIP_NORMALS) + a = CLIP_NORMALS; + if (x < 0) + a = -a; + return a; +} + + +static double +Sine(double x, double e) +{ + /* This is just the sine wave raised to the exponent. BUT, you can't + * raise negative numbers to fractional exponents. So we have a special + * XtoY routune which handles it in a way useful to superquadrics. + */ + + return (XtoY(sin(x), e)); +} + + +static double +Cosine(double x, double e) +{ + return (XtoY(cos(x), e)); +} + + +static void +MakeUpStuff(int allstuff, superquadricsstruct * sp) +{ + int dostuff; + int t, pat; + GLfloat r, g, b, r2, g2, b2; + + /* randomize it. */ + + if (sp->maxcount < 2) + allstuff = 1; + dostuff = allstuff * 15; + if (!dostuff) { + dostuff = myrand(3) + 1; + if (myrand(2) || (dostuff & 1)) + dostuff |= 4; + if (myrand(2)) + dostuff |= 8; + } + if (dostuff & 1) { + sp->later.xExponent = (((long) floor(myrandreal() * 250 + 0.5)) / 100.0) + 0.1; + sp->later.yExponent = (((long) floor(myrandreal() * 250 + 0.5)) / 100.0) + 0.1; + + /* Increase the 2.0 .. 2.5 range to 2.0 .. 3.0 */ + if (sp->later.xExponent > 2.0) + sp->later.xExponent = (sp->later.xExponent * 2.0) - 2.0; + if (sp->later.yExponent > 2.0) + sp->later.yExponent = (sp->later.yExponent * 2.0) - 2.0; + } + if (dostuff & 2) { + do { + sp->later.Mode = myrand(3L) + 1; + } while (!allstuff && (sp->later.Mode == sp->now.Mode)); + /* On init: make sure it can stay in mode 1 if it feels like it. */ + } + if (dostuff & 4) { + if (sp->mono) { + if (sp->wireframe) { + b = g = r = 1.0; + b2 = g2 = r2 = 1.0; + } else { + b = g = r = (GLfloat) (140 + myrand(100)) / 255.0; + b2 = g2 = r2 = ((r > 0.69) ? (1.0 - r) : r); + } + } else { + r = (GLfloat) (40 + myrand(200)) / 255.0; + g = (GLfloat) (40 + myrand(200)) / 255.0; + b = (GLfloat) (40 + myrand(200)) / 255.0; + + r2 = ((myrand(4) && ((r < 0.31) || (r > 0.69))) ? (1.0 - r) : r); + g2 = ((myrand(4) && ((g < 0.31) || (g > 0.69))) ? (1.0 - g) : g); + b2 = ((myrand(4) && ((b < 0.31) || (b > 0.69))) ? (1.0 - b) : b); + } + + pat = myrand(4); + for (t = 0; t < 4; ++t) { + sp->later.r[t] = sp->pats[pat][t] ? r : r2; + sp->later.g[t] = sp->pats[pat][t] ? g : g2; + sp->later.b[t] = sp->pats[pat][t] ? b : b2; + } + } + if (dostuff & 8) { + sp->later.rotx = myrand(360) - 180; + sp->later.rotz = myrand(160) - 80; + } +} + +static void +inputs(superquadricsstruct * sp) +{ + int iv; + double u, v, mode3, cn3, inverter2, flatu, flatv; + + if (sp->Mode < 1.000001) { + mode3 = 1.0; + cn3 = 0.0; + inverter2 = 1.0; + } else if (sp->Mode < 2.000001) { + mode3 = 1.0; + cn3 = (sp->Mode - 1.0) * 1.5; + inverter2 = (sp->Mode - 1.0) * -2.0 + 1.0; + } else { + mode3 = (sp->Mode - 1.0); + cn3 = (sp->Mode - 2.0) / 2.0 + 1.5; + inverter2 = -1.0; + } + + if (sp->flatshade) { + flatu = M_PI / (sp->resolution - 1); + flatv = mode3 * M_PI / ((sp->resolution - 1) * 2); + } else { + flatu = flatv = 0.0; + } + + /* (void) printf("Calculating....\n"); */ + for (iv = 1; iv <= sp->resolution; iv++) { + + /* u ranges from PI down to -PI */ + u = (1 - iv) * 2 * M_PI / (sp->resolution - 1) + M_PI; + + /* v ranges from PI/2 down to -PI/2 */ + v = (1 - iv) * mode3 * M_PI / (sp->resolution - 1) + M_PI * (mode3 / 2.0); + + /* Use of xExponent */ + sp->se[iv] = Sine(u, sp->xExponent); + sp->ce[iv] = Cosine(u, sp->xExponent); + sp->sn[iv] = Sine(v, sp->yExponent); + sp->cn[iv] = Cosine(v, sp->yExponent) * inverter2 + cn3; + + /* Normal vector computations only */ + sp->sw[iv] = Sine(u + flatu, 2 - sp->xExponent); + sp->cw[iv] = Cosine(u + flatu, 2 - sp->xExponent); + sp->ss[iv] = Sine(v + flatv, 2 - sp->yExponent) * inverter2; + sp->cs[iv] = Cosine(v + flatv, 2 - sp->yExponent); + } /* next */ + + /* Now fix up the endpoints */ + sp->se[sp->resolution] = sp->se[1]; + sp->ce[sp->resolution] = sp->ce[1]; + + if (sp->Mode > 2.999999) { + sp->sn[sp->resolution] = sp->sn[1]; + sp->cn[sp->resolution] = sp->cn[1]; + } +} + + +static int +DoneScale(superquadricsstruct * sp) +{ + double xx, yy, zz, xp = 0, yp = 0, zp = 0, xn, yn, zn, xnp = 0, + ynp = 0, znp = 0; + int ih, iv; + int polys = 0; + + /* Hey don't knock my 2-letter variable names. Simon's BASIC rules, man! ;-> */ + /* Just kidding..... */ + int toggle = 0; + + for (ih = 1; ih <= sp->resolution; ih++) { + toggle ^= 2; + for (iv = 1; iv <= sp->resolution; iv++) { + toggle ^= 1; + if (sp->wireframe) + glColor3f(sp->curmat[toggle][0], sp->curmat[toggle][1], sp->curmat[toggle][2]); + else + glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, sp->curmat[toggle]); + + xx = sp->cn[iv] * sp->ce[ih]; + zz = sp->cn[iv] * sp->se[ih]; + yy = sp->sn[iv]; + + if (sp->wireframe) { + if ((ih > 1) || (iv > 1)) { + glBegin(GL_LINES); + if (ih > 1) { + glVertex3f(xx, yy, zz); + glVertex3f(sp->Prevxx[iv], sp->Prevyy[iv], sp->Prevzz[iv]); + polys++; + } + if (iv > 1) { + glVertex3f(xx, yy, zz); + glVertex3f(sp->Prevxx[iv - 1], sp->Prevyy[iv - 1], sp->Prevzz[iv - 1]); + polys++; + } +/* PURIFY 4.0.1 reports an unitialized memory read on the next line when using + * MesaGL 2.2 and -mono. This has been fixed in MesaGL 2.3 and later. */ + glEnd(); + } + } else { + if ((sp->cs[iv] > 1e+10) || (sp->cs[iv] < -1e+10)) { + xn = sp->cs[iv]; + zn = sp->cs[iv]; + yn = sp->ss[iv]; + } else { + xn = sp->cs[iv] * sp->cw[ih]; + zn = sp->cs[iv] * sp->sw[ih]; + yn = sp->ss[iv]; + } + if ((ih > 1) && (iv > 1)) { + glNormal3f(xn, yn, zn); + glBegin(GL_POLYGON); + glVertex3f(xx, yy, zz); + if (!sp->flatshade) + glNormal3f(sp->Prevxn[iv], sp->Prevyn[iv], sp->Prevzn[iv]); + glVertex3f(sp->Prevxx[iv], sp->Prevyy[iv], sp->Prevzz[iv]); + if (!sp->flatshade) + glNormal3f(xnp, ynp, znp); + glVertex3f(xp, yp, zp); + if (!sp->flatshade) + glNormal3f(sp->Prevxn[iv - 1], sp->Prevyn[iv - 1], sp->Prevzn[iv - 1]); + glVertex3f(sp->Prevxx[iv - 1], sp->Prevyy[iv - 1], sp->Prevzz[iv - 1]); + polys++; + glEnd(); + } + if (sp->shownorms) { + if (!sp->flatshade) + glShadeModel(GL_FLAT); + glDisable(GL_LIGHTING); + glBegin(GL_LINES); + glVertex3f(xx, yy, zz); + glVertex3f(xx + xn, yy + yn, zz + zn); + polys++; + glEnd(); + if (!sp->flatshade) + glShadeModel(GL_SMOOTH); + glEnable(GL_LIGHTING); + } + xnp = sp->Prevxn[iv]; + ynp = sp->Prevyn[iv]; + znp = sp->Prevzn[iv]; + sp->Prevxn[iv] = xn; + sp->Prevyn[iv] = yn; + sp->Prevzn[iv] = zn; + } + + xp = sp->Prevxx[iv]; + yp = sp->Prevyy[iv]; + zp = sp->Prevzz[iv]; + sp->Prevxx[iv] = xx; + sp->Prevyy[iv] = yy; + sp->Prevzz[iv] = zz; + + } /* next */ + } /* next */ + return polys; +} + +/**** End of really old code ****/ + +static void +SetCull(int init, superquadricsstruct * sp) +{ + if (init) { + glDisable(GL_CULL_FACE); + sp->cullmode = 0; + return; + } + if (sp->Mode < 1.0001) { + if (sp->cullmode != 1) { + glEnable(GL_CULL_FACE); + glCullFace(GL_BACK); + sp->cullmode = 1; + } + } else if (sp->Mode > 2.9999) { + if (sp->cullmode != 2) { + glEnable(GL_CULL_FACE); + glCullFace(GL_FRONT); + sp->cullmode = 2; + } + } else { + if (sp->cullmode) { + glDisable(GL_CULL_FACE); + sp->cullmode = 0; + } + } +} + +static void +SetCurrentShape(superquadricsstruct * sp) +{ + int t; + + sp->xExponent = sp->now.xExponent = sp->later.xExponent; + sp->yExponent = sp->now.yExponent = sp->later.yExponent; + + for (t = 0; t < 4; ++t) { + sp->curmat[t][0] = sp->now.r[t] = sp->later.r[t]; + sp->curmat[t][1] = sp->now.g[t] = sp->later.g[t]; + sp->curmat[t][2] = sp->now.b[t] = sp->later.b[t]; + } + + sp->Mode = (double) (sp->now.Mode = sp->later.Mode); + sp->rotx = sp->now.rotx = sp->later.rotx; + sp->rotz = sp->now.rotz = sp->later.rotz; + + sp->counter = -sp->maxwait; + + inputs(sp); +} + +static void +NextSuperquadric(superquadricsstruct * sp) +{ + double fnow, flater; + int t; + + sp->roty -= sp->spinspeed; + while (sp->roty >= 360.0) + sp->roty -= 360.0; + while (sp->roty < 0.0) + sp->roty += 360.0; + + --sp->viewcount; + + if (sp->counter > 0) { + if (--sp->counter == 0) { + SetCurrentShape(sp); + if (sp->counter == 0) { /* Happens if sp->maxwait == 0 */ + MakeUpStuff(0, sp); + sp->counter = sp->maxcount; + } + } else { + fnow = (double) sp->counter / (double) sp->maxcount; + flater = (double) (sp->maxcount - sp->counter) / (double) sp->maxcount; + sp->xExponent = sp->now.xExponent * fnow + sp->later.xExponent * flater; + sp->yExponent = sp->now.yExponent * fnow + sp->later.yExponent * flater; + + for (t = 0; t < 4; ++t) { + sp->curmat[t][0] = sp->now.r[t] * fnow + sp->later.r[t] * flater; + sp->curmat[t][1] = sp->now.g[t] * fnow + sp->later.g[t] * flater; + sp->curmat[t][2] = sp->now.b[t] * fnow + sp->later.b[t] * flater; + } + + sp->Mode = (double) sp->now.Mode * fnow + (double) sp->later.Mode * flater; + sp->rotx = (double) sp->now.rotx * fnow + (double) sp->later.rotx * flater; + sp->rotz = (double) sp->now.rotz * fnow + (double) sp->later.rotz * flater; + + inputs(sp); + } + } else { + if (++sp->counter >= 0) { + MakeUpStuff(0, sp); + sp->counter = sp->maxcount; + } + } +} + +static int +DisplaySuperquadrics(superquadricsstruct * sp) +{ + int polys = 0; + glDrawBuffer(GL_BACK); + if (sp->wireframe) + glClear(GL_COLOR_BUFFER_BIT); + else + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + + if (sp->viewcount < 1) { + sp->viewcount = sp->viewwait; +/* ReshapeSuperquadrics(-1, -1);*/ + } + glPushMatrix(); + glTranslatef(0.0, 0.0, -((GLfloat) (sp->dist) / 16.0) - (sp->Mode * 3.0 - 1.0)); /* viewing transform */ + glRotatef(sp->rotx, 1.0, 0.0, 0.0); /* pitch */ + glRotatef(sp->rotz, 0.0, 0.0, 1.0); /* bank */ + glRotatef(sp->roty, 0.0, 1.0, 0.0); /* "spin", like heading but comes after P & B */ + + SetCull(0, sp); + + glScalef(0.7, 0.7, 0.7); /* jwz: scale it down a bit */ + polys = DoneScale(sp); + + glPopMatrix(); + + /* Remember to flush & swap the buffers after calling this function! */ + return polys; +} + +static int +NextSuperquadricDisplay(superquadricsstruct * sp) +{ + NextSuperquadric(sp); + return DisplaySuperquadrics(sp); +} + +#define MINSIZE 200 +static void +ReshapeSuperquadrics(int w, int h) +{ +#if 0 + int maxsize, cursize; + + maxsize = (w < h) ? w : h; + if (maxsize <= MINSIZE) { + cursize = maxsize; + } else { + cursize = myrand(maxsize - MINSIZE) + MINSIZE; + } + if ((w > cursize) && (h > cursize)) { + glViewport(myrand(w - cursize), myrand(h - cursize), cursize, cursize); + w = h = cursize; + } else { + glViewport(0, 0, w, h); + } +#else + glViewport(0, 0, w, h); +#endif + + glMatrixMode(GL_PROJECTION); + glLoadIdentity(); + gluPerspective(15.0, (GLfloat) w / (GLfloat) h, 0.1, 200.0); + glMatrixMode(GL_MODELVIEW); + glLoadIdentity(); +} + +static void +InitSuperquadrics(int wfmode, int snorm, int res, int count, float speed, superquadricsstruct * sp) +{ + GLfloat ambient[] = + {0.4, 0.4, 0.4, 1.0}; + GLfloat position[] = + {10.0, 1.0, 1.0, 10.0}; + GLfloat mat_diffuse[] = + {1.0, 0.5, 0.5, 1.0}; + GLfloat mat_specular[] = + {0.8, 0.8, 0.8, 1.0}; + GLfloat mat_shininess[] = + {50.0}; + + int t; + + for (t = 0; t < 4; ++t) { + sp->curmat[t][0] = 0.0; + sp->curmat[t][1] = 0.0; + sp->curmat[t][2] = 0.0; + sp->curmat[t][3] = 1.0; + } + + sp->rotx = 35.0; + sp->roty = 0.0; + sp->rotz = 0.0; + sp->dist = (16 << 3); + sp->wireframe = sp->flatshade = sp->shownorms = 0; + sp->maxcount = count; + if (sp->maxcount < 1) + sp->maxcount = 1; + sp->maxwait = sp->maxcount >> 1; + SetCull(1, sp); + + sp->mono = 0; + sp->spinspeed = speed; + sp->viewcount = sp->viewwait = (sp->maxcount < 2) ? 1 : (sp->maxcount << 3); + + if (res < MinRes) + res = MinRes; + if (res > MaxRes) + res = MaxRes; + sp->resolution = res; + + if (wfmode == 2) + sp->flatshade = 1; + else if (wfmode) + sp->wireframe = 1; + + if (snorm) + sp->shownorms = 1; + + glClearDepth(1.0); + + if (sp->wireframe) { + glShadeModel(GL_FLAT); + glDisable(GL_LIGHTING); + glColor3f(mat_diffuse[0], mat_diffuse[1], mat_diffuse[2]); + } else { + if (sp->flatshade) { + glShadeModel(GL_FLAT); + position[0] = 1.0; + position[3] = 0.0; + } + glEnable(GL_LIGHTING); + glEnable(GL_LIGHT0); + glDepthFunc(GL_LEQUAL); + glEnable(GL_DEPTH_TEST); + + glLightfv(GL_LIGHT0, GL_AMBIENT, ambient); + glLightfv(GL_LIGHT0, GL_POSITION, position); + + /*glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, mat_diffuse); */ + glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, mat_specular); + glMaterialfv(GL_FRONT_AND_BACK, GL_SHININESS, mat_shininess); + + glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, GL_TRUE); + + glFrontFace(GL_CW); + glEnable(GL_NORMALIZE); + } + + MakeUpStuff(1, sp); + SetCurrentShape(sp); + MakeUpStuff(1, sp); /* Initialize it */ + sp->counter = sp->maxcount; +} + +/* End of superquadrics main functions */ + +ENTRYPOINT void +init_superquadrics(ModeInfo * mi) +{ + Display *display = MI_DISPLAY(mi); + Window window = MI_WINDOW(mi); + int screen = MI_SCREEN(mi); + + superquadricsstruct *sp; + + if (superquadrics == NULL) { + if ((superquadrics = (superquadricsstruct *) calloc(MI_NUM_SCREENS(mi), + sizeof (superquadricsstruct))) == NULL) + return; + } + sp = &superquadrics[screen]; + sp->mono = (MI_IS_MONO(mi) ? 1 : 0); + + sp->pats[1][1] = 1; + sp->pats[1][3] = 1; + sp->pats[2][2] = 1; + sp->pats[2][3] = 1; + sp->pats[3][1] = 1; + sp->pats[3][2] = 1; + +/* {0, 0, 0, 0}, + {0, 1, 0, 1}, + {0, 0, 1, 1}, + {0, 1, 1, 0} + */ + + if ((sp->glx_context = init_GL(mi)) != NULL) { + + InitSuperquadrics(MI_IS_WIREFRAME(mi), 0, + MI_COUNT(mi), MI_CYCLES(mi), spinspeed, sp); + ReshapeSuperquadrics(MI_WIDTH(mi), MI_HEIGHT(mi)); + + DisplaySuperquadrics(sp); + glFinish(); + glXSwapBuffers(display, window); + } else { + MI_CLEARWINDOW(mi); + } +} + +ENTRYPOINT void +draw_superquadrics(ModeInfo * mi) +{ + superquadricsstruct *sp = &superquadrics[MI_SCREEN(mi)]; + Display *display = MI_DISPLAY(mi); + Window window = MI_WINDOW(mi); + + if (!sp->glx_context) + return; + + glXMakeCurrent(display, window, *(sp->glx_context)); + + mi->polygon_count = NextSuperquadricDisplay(sp); + + if (mi->fps_p) do_fps (mi); + glFinish(); + glXSwapBuffers(display, window); +} + +ENTRYPOINT void +refresh_superquadrics(ModeInfo * mi) +{ + /* Nothing happens here */ +} + +ENTRYPOINT void +reshape_superquadrics(ModeInfo * mi, int width, int height) +{ + ReshapeSuperquadrics(MI_WIDTH(mi), MI_HEIGHT(mi)); +} + +ENTRYPOINT void +release_superquadrics(ModeInfo * mi) +{ + if (superquadrics != NULL) { + (void) free((void *) superquadrics); + superquadrics = NULL; + } + FreeAllGL(mi); +} + + +#endif + +/* End of superquadrics.c */ + +XSCREENSAVER_MODULE ("Superquadrics", superquadrics) diff --git a/hacks/glx/superquadrics.man b/hacks/glx/superquadrics.man new file mode 100644 index 00000000..8a127f0b --- /dev/null +++ b/hacks/glx/superquadrics.man @@ -0,0 +1,70 @@ +.TH XScreenSaver 1 "" "X Version 11" +.SH NAME +superquadrics - morphing 3d shapes. +.SH SYNOPSIS +.B superquadrics +[\-display \fIhost:display.screen\fP] +[\-visual \fIvisual\fP] +[\-window] +[\-root] +[\-delay \fInumber\fP] +[\-spinspeed \fInumber\fP] +[\-count \fInumber\fP] +[\-cycles \fInumber\fP] +[\-wireframe] +[\-fps] +.SH DESCRIPTION +Ed Mackey reports that he wrote the first version of this program in BASIC +on a Commodore 64 in 1987, as a 320x200 black and white wireframe. Now it +is GL and has specular reflections. +.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: 40000 (0.04 seconds.). +.TP 8 +.B \-spinspeed \fInumber\fP +0.1 - 15.0. Default: 5.0. +.TP 8 +.B \-count \fInumber\fP +0 - 100. Default: 25. +.TP 8 +.B \-cycles \fInumber\fP +0 - 100. Default: 40. +.TP 8 +.B \-wireframe +Render in wireframe instead of solid. +.TP 8 +.B \-fps +Display the current frame rate, CPU load, and polygon count. +.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 2002 by Ed Mackey. 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 +Ed Mackey. diff --git a/hacks/glx/surfaces.c b/hacks/glx/surfaces.c new file mode 100644 index 00000000..9dac523b --- /dev/null +++ b/hacks/glx/surfaces.c @@ -0,0 +1,683 @@ +/* Surface --- Parametric 3d surfaces visualization */ + +/* + * Revision History: + * 2000: written by Andrey Mirtchovski + * + * 01-Mar-2003 mirtchov Modified as a xscreensaver hack. + * 01-jan-2009 steger Renamed from klein.c to surfaces.c. + * Removed the Klein bottle. + * Added many new surfaces. + * Added many command line options. + * + */ + +/* surfaces to draw */ +#define SURFACE_RANDOM -1 +#define SURFACE_DINI 0 +#define SURFACE_ENNEPER 1 +#define SURFACE_KUEN 2 +#define SURFACE_MOEBIUS 3 +#define SURFACE_SEASHELL 4 +#define SURFACE_SWALLOWTAIL 5 +#define SURFACE_BOHEMIAN 6 +#define SURFACE_WHITNEY 7 +#define SURFACE_PLUECKER 8 +#define SURFACE_HENNEBERG 9 +#define SURFACE_CATALAN 10 +#define SURFACE_CORKSCREW 11 +#define NUM_SURFACES 12 + +/* primitives to draw with + * note that we skip the polygons and + * triangle fans -- too slow + * + * also removed triangle_strip and quads -- + * just doesn't look good enough + */ +#define RENDER_RANDOM -1 +#define RENDER_POINTS 0 +#define RENDER_LINES 1 +#define RENDER_LINE_LOOP 2 +#define NUM_RENDER 3 + +#ifdef STANDALONE +# define DEFAULTS "*delay: 20000 \n" \ + "*showFPS: False \n" + +# define refresh_surface 0 +# include "xlockmore.h" /* from the xscreensaver distribution */ +#else /* !STANDALONE */ +# include "xlock.h" /* from the xlockmore distribution */ +#endif /* !STANDALONE */ + +#ifdef USE_GL + +#define DEF_SURFACE "random" +#define DEF_MODE "random" +#define DEF_SPIN "True" +#define DEF_WANDER "False" +#define DEF_SPEED "300" + +#include "rotator.h" +#include "gltrackball.h" + +#undef countof +#define countof(x) (sizeof((x))/sizeof((*x))) + + +static char *surface_type; +static char *render_mode; +static int render; +static int speed; +static Bool do_spin; +static Bool do_wander; + +static XrmOptionDescRec opts[] = { + { "-surface", ".surface", XrmoptionSepArg, 0 }, + { "-random-surface", ".surface", XrmoptionNoArg, "random" }, + { "-dini", ".surface", XrmoptionNoArg, "dini" }, + { "-enneper", ".surface", XrmoptionNoArg, "enneper" }, + { "-kuen", ".surface", XrmoptionNoArg, "kuen" }, + { "-moebius", ".surface", XrmoptionNoArg, "moebius" }, + { "-seashell", ".surface", XrmoptionNoArg, "seashell" }, + { "-swallowtail", ".surface", XrmoptionNoArg, "swallowtail" }, + { "-bohemian", ".surface", XrmoptionNoArg, "bohemian" }, + { "-whitney", ".surface", XrmoptionNoArg, "whitney" }, + { "-pluecker", ".surface", XrmoptionNoArg, "pluecker" }, + { "-henneberg", ".surface", XrmoptionNoArg, "henneberg" }, + { "-catalan", ".surface", XrmoptionNoArg, "catalan" }, + { "-corkscrew", ".surface", XrmoptionNoArg, "corkscrew" }, + { "-mode", ".mode", XrmoptionSepArg, 0 }, + { "-random-mode", ".mode", XrmoptionNoArg, "random" }, + { "-points", ".mode", XrmoptionNoArg, "points" }, + { "-lines", ".mode", XrmoptionNoArg, "lines" }, + { "-line-loops", ".mode", XrmoptionNoArg, "line-loops" }, + { "-speed", ".speed", XrmoptionSepArg, 0 }, + { "-spin", ".spin", XrmoptionNoArg, "True" }, + { "+spin", ".spin", XrmoptionNoArg, "False" }, + { "-wander", ".wander", XrmoptionNoArg, "True" }, + { "+wander", ".wander", XrmoptionNoArg, "False" }, +}; + +static argtype vars[] = { + {&surface_type, "surface", "Surface", DEF_SURFACE, t_String }, + {&render_mode, "mode", "Mode", DEF_MODE, t_String }, + {&do_spin, "spin", "Spin", DEF_SPIN, t_Bool }, + {&do_wander, "wander", "Wander", DEF_WANDER, t_Bool }, + {&speed, "speed", "Speed", DEF_SPEED, t_Int }, +}; + + +ENTRYPOINT ModeSpecOpt surface_opts = +{countof(opts), opts, countof(vars), vars, NULL}; + + + +typedef struct { + GLfloat x; + GLfloat y; + GLfloat z; +} GL_VECTOR; + +typedef struct { + GLXContext *glx_context; + Window window; + rotator *rot; + trackball_state *trackball; + Bool button_down_p; + + int render; + Bool random_render; + int surface; + Bool random_surface; + int frame; + + float du, dv; + float a, b, c; + + float draw_step; +} surfacestruct; + +static surfacestruct *surface = NULL; + + +static void draw(ModeInfo *mi) +{ + surfacestruct *sp = &surface[MI_SCREEN(mi)]; + double u, v; + float coord[3]; + int render; + + mi->polygon_count = 0; + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + + glEnable(GL_DEPTH_TEST); + glEnable(GL_NORMALIZE); + glEnable(GL_CULL_FACE); + + glPushMatrix(); + + { + double x, y, z; + get_position(sp->rot, &x, &y, &z, !sp->button_down_p); + glTranslatef((x-0.5)*10, (y-0.5)*10, (z-0.5)*20); + + /* Do it twice because we don't track the device's orientation. */ + glRotatef( current_device_rotation(), 0, 0, 1); + gltrackball_rotate(sp->trackball); + glRotatef(-current_device_rotation(), 0, 0, 1); + + get_rotation(sp->rot, &x, &y, &z, !sp->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); + + switch(sp->surface) + { + case SURFACE_DINI: + for (v=0.11; v<=2.0; v+=sp->dv) + { + glBegin(sp->render); + for (u=0; u<=6.0*M_PI; u+=sp->du) + { + coord[0] = sp->a*cos(u)*sin(v); + coord[1] = sp->a*sin(u)*sin(v); + coord[2] = sp->a*(cos(v)+log(tan(0.5*v)))+0.2*sp->b*u; + glColor3f(coord[0]+0.7, coord[1]+0.7, coord[2]+0.7); + glVertex3fv(coord); + mi->polygon_count++; + } + glEnd(); + } + break; + case SURFACE_ENNEPER: + for (u=-M_PI; u<=M_PI; u+=sp->du) + { + glBegin(sp->render); + for (v=-M_PI; vdv) + { + coord[0] = sp->a*(u-(1.0/3.0*u*u*u)+u*v*v); + coord[1] = sp->b*(v-(1.0/3.0*v*v*v)+u*u*v); + coord[2] = u*u-v*v; + glColor3f(coord[0]+0.7, coord[1]+0.7, coord[2]+0.7); + glVertex3fv(coord); + mi->polygon_count++; + } + glEnd(); + } + break; + case SURFACE_KUEN: + for (u=-4.48; u<=4.48; u+=sp->du) + { + glBegin(sp->render); + for (v=M_PI/51; vdv) + { + coord[0] = 2*(cos(u)+u*sin(u))*sin(v)/(1+u*u*sin(v)*sin(v)); + coord[1] = 2*(sin(u)-u*cos(u))*sin(v)/(1+u*u*sin(v)*sin(v)); + coord[2] = log(tan(0.5*v))+2*cos(v)/(1+u*u*sin(v)*sin(v)); + glColor3f(coord[0]+0.7, coord[1]+0.7, coord[2]+0.7); + glVertex3fv(coord); + mi->polygon_count++; + } + glEnd(); + } + break; + case SURFACE_MOEBIUS: + for (u=-M_PI; udu) + { + glBegin(sp->render); + for (v=-0.735; v<0.74; v+=sp->dv) + { + coord[0] = cos(u)+v*cos(u/2)*cos(u); + coord[1] = sin(u)+v*cos(u/2)*sin(u); + coord[2] = v*sin(u/2); + glColor3f(coord[0]+0.7, coord[1]+0.7, coord[2]+0.7); + glVertex3fv(coord); + mi->polygon_count++; + } + glEnd(); + } + break; + case SURFACE_SEASHELL: + for (u=0; u<2*M_PI; u+=sp->du) + { + glBegin(sp->render); + for (v=0; v<2*M_PI; v+=sp->dv) + { + coord[0] = sp->a*(1-v/(2*M_PI))*cos(2*v)*(1+cos(u))+sp->c*cos(2*v); + coord[1] = sp->a*(1-v/(2*M_PI))*sin(2*v)*(1+cos(u))+sp->c*sin(2*v); + coord[2] = 2*sp->b*v/(2*M_PI)+sp->a*(1-v/(2*M_PI))*sin(u); + glColor3f(coord[0]+0.7, coord[1]+0.7, coord[2]+0.7); + glVertex3fv(coord); + mi->polygon_count++; + } + glEnd(); + } + break; + case SURFACE_SWALLOWTAIL: + for (u=-2.5; u<2.0; u+=sp->du) + { + glBegin(sp->render); + for (v=-1.085; v<1.09; v+=sp->dv) + { + coord[0] = u*v*v+3*v*v*v*v; + coord[1] = -2*u*v-4*v*v*v; + coord[2] = u; + glColor3f(coord[0]+0.7, coord[1]+0.7, coord[2]+0.7); + glVertex3fv(coord); + mi->polygon_count++; + } + glEnd(); + } + break; + case SURFACE_BOHEMIAN: + for (u=-M_PI; udu) + { + glBegin(sp->render); + for (v=-M_PI; vdv) + { + coord[0] = sp->a*cos(u); + coord[1] = sp->b*cos(v)+sp->a*sin(u); + coord[2] = sin(v); + glColor3f(coord[0]+0.7, coord[1]+0.7, coord[2]+0.7); + glVertex3fv(coord); + mi->polygon_count++; + } + glEnd(); + } + break; + case SURFACE_WHITNEY: + for (v=-1.995; v<2.0; v+=sp->dv) + { + glBegin(sp->render); + for (u=-1.995; u<2.0; u+=sp->du) + { + coord[0] = u*v; + coord[1] = u; + coord[2] = v*v-2; + glColor3f(coord[0]+0.7, coord[1]+0.7, coord[2]+0.7); + glVertex3fv(coord); + mi->polygon_count++; + } + glEnd(); + } + break; + case SURFACE_PLUECKER: + for (u=0; u<2.5; u+=sp->dv) + { + glBegin(sp->render); + for (v=-M_PI; vdu) + { + coord[0] = u*cos(v); + coord[1] = u*sin(v); + coord[2] = 2*cos(v)*sin(v); + glColor3f(coord[0]+0.7, coord[1]+0.7, coord[2]+0.7); + glVertex3fv(coord); + mi->polygon_count++; + } + glEnd(); + } + break; + case SURFACE_HENNEBERG: + for (u=0.9; u<2.55; u+=sp->dv) + { + glBegin(sp->render); + for (v=-M_PI; vdu) + { + coord[0] = sinh(1.0/3.0*u)*cos(v)-1.0/3.0*sinh(u)*cos(3.0*v); + coord[1] = sinh(1.0/3.0*u)*sin(v)+1.0/3.0*sinh(u)*sin(3.0*v); + coord[2] = cosh(2.0/3.0*u)*cos(2.0*v); + glColor3f(coord[0]+0.7, coord[1]+0.7, coord[2]+0.7); + glVertex3fv(coord); + mi->polygon_count++; + } + glEnd(); + } + break; + case SURFACE_CATALAN: + for (v=-2; v<2; v+=sp->du) + { + glBegin(sp->render); + for (u=-2*M_PI; u<2*M_PI+0.05; u+=sp->dv) + { + coord[0] = 0.33*(u-sin(u)*cosh(v)); + coord[1] = 0.33*(1.0-cos(u)*cosh(v)); + coord[2] = 0.33*4.0*sin(0.5*u)*sinh(0.5*v); + glColor3f(coord[0]+0.7, coord[1]+0.7, coord[2]+0.7); + glVertex3fv(coord); + mi->polygon_count++; + } + glEnd(); + } + break; + case SURFACE_CORKSCREW: + for (v=-M_PI; vdu) + { + glBegin(sp->render); + for (u=-M_PI; udv) + { + coord[0] = 0.5*(sp->a+2.0)*cos(u)*cos(v); + coord[1] = 0.5*(sp->a+2.0)*sin(u)*cos(v); + coord[2] = 0.5*(sp->a+2.0)*sin(v)+u; + glColor3f(coord[0]+0.7, coord[1]+0.7, coord[2]+0.7); + glVertex3fv(coord); + mi->polygon_count++; + } + glEnd(); + } + break; + } + glPopMatrix(); + + if (sp->render == GL_LINES) + mi->polygon_count /= 2; + + sp->a = sin(sp->draw_step+=0.01); + sp->b = cos(sp->draw_step+=0.01); + sp->c = sin(sp->draw_step+0.25*M_PI); + + if (sp->random_surface || sp->random_render) + { + sp->frame++; + if (sp->frame >= speed) + { + sp->frame = 0; + if (sp->random_surface) + sp->surface = random() % NUM_SURFACES; + if (sp->random_render) + { + render = random() % NUM_RENDER; + switch (render) + { + case RENDER_POINTS: + sp->render = GL_POINTS; + break; + case RENDER_LINES: + sp->render = GL_LINES; + break; + case RENDER_LINE_LOOP: + if (sp->surface == SURFACE_BOHEMIAN || + sp->surface == SURFACE_PLUECKER || + sp->surface == SURFACE_HENNEBERG) + sp->render = GL_LINE_LOOP; + else + sp->render = GL_LINE_STRIP; + break; + default: + sp->render = GL_LINE_LOOP; + break; + } + } + } + } +} + + +/* new window size or exposure */ +ENTRYPOINT void reshape_surface(ModeInfo *mi, int width, int height) +{ + GLfloat h = (GLfloat) height / (GLfloat) width; + + glViewport(0, 0, (GLint) width, (GLint) height); + glMatrixMode(GL_PROJECTION); + glLoadIdentity(); + gluPerspective (30.0, 1/h, 1.0, 100.0); + + glMatrixMode(GL_MODELVIEW); + glLoadIdentity(); + gluLookAt(0.0, 0.0, 30.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0); + + glClear(GL_COLOR_BUFFER_BIT); +} + + +ENTRYPOINT Bool surface_handle_event(ModeInfo *mi, XEvent *event) +{ + surfacestruct *sp = &surface[MI_SCREEN(mi)]; + + if (event->xany.type == ButtonPress && event->xbutton.button == Button1) + { + sp->button_down_p = True; + gltrackball_start(sp->trackball, event->xbutton.x, event->xbutton.y, + MI_WIDTH (mi), MI_HEIGHT (mi)); + return True; + } + else if (event->xany.type == ButtonRelease && + event->xbutton.button == Button1) + { + sp->button_down_p = False; + return True; + } + else if (event->xany.type == ButtonPress && + (event->xbutton.button == Button4 || + event->xbutton.button == Button5 || + event->xbutton.button == Button6 || + event->xbutton.button == Button7)) { + gltrackball_mousewheel(sp->trackball, event->xbutton.button, 10, + !!event->xbutton.state); + return True; + } + else if (event->xany.type == MotionNotify && sp->button_down_p) + { + gltrackball_track (sp->trackball, event->xmotion.x, event->xmotion.y, + MI_WIDTH (mi), MI_HEIGHT (mi)); + return True; + } + + return False; +} + + +ENTRYPOINT void init_surface(ModeInfo *mi) +{ + int screen = MI_SCREEN(mi); + surfacestruct *sp; + + if (surface == NULL) + { + if ((surface = (surfacestruct *) calloc(MI_NUM_SCREENS(mi), + sizeof(surfacestruct))) == NULL) + return; + } + sp = &surface[screen]; + + sp->window = MI_WINDOW(mi); + + { + double spin_speed = 1.0; + double wander_speed = 0.03; + sp->rot = make_rotator(do_spin ? spin_speed : 0, + do_spin ? spin_speed : 0, + do_spin ? spin_speed : 0, + 1.0, + do_wander ? wander_speed : 0, + True); + sp->trackball = gltrackball_init (); + } + + if (!strcasecmp(surface_type,"random")) + { + sp->random_surface = True; + sp->surface = random() % NUM_SURFACES; + } + else if (!strcasecmp(surface_type,"dini")) + { + sp->random_surface = False; + sp->surface = SURFACE_DINI; + } + else if (!strcasecmp(surface_type,"enneper")) + { + sp->random_surface = False; + sp->surface = SURFACE_ENNEPER; + } + else if (!strcasecmp(surface_type,"kuen")) + { + sp->random_surface = False; + sp->surface = SURFACE_KUEN; + } + else if (!strcasecmp(surface_type,"moebius")) + { + sp->random_surface = False; + sp->surface = SURFACE_MOEBIUS; + } + else if (!strcasecmp(surface_type,"seashell")) + { + sp->random_surface = False; + sp->surface = SURFACE_SEASHELL; + } + else if (!strcasecmp(surface_type,"swallowtail")) + { + sp->random_surface = False; + sp->surface = SURFACE_SWALLOWTAIL; + } + else if (!strcasecmp(surface_type,"bohemian")) + { + sp->random_surface = False; + sp->surface = SURFACE_BOHEMIAN; + } + else if (!strcasecmp(surface_type,"whitney")) + { + sp->random_surface = False; + sp->surface = SURFACE_WHITNEY; + } + else if (!strcasecmp(surface_type,"pluecker")) + { + sp->random_surface = False; + sp->surface = SURFACE_PLUECKER; + } + else if (!strcasecmp(surface_type,"henneberg")) + { + sp->random_surface = False; + sp->surface = SURFACE_HENNEBERG; + } + else if (!strcasecmp(surface_type,"catalan")) + { + sp->random_surface = False; + sp->surface = SURFACE_CATALAN; + } + else if (!strcasecmp(surface_type,"corkscrew")) + { + sp->random_surface = False; + sp->surface = SURFACE_CORKSCREW; + } + else + { + sp->random_surface = True; + sp->surface = random() % NUM_SURFACES; + } + + if (!strcasecmp(render_mode,"random")) + { + sp->random_render = True; + render = random() % NUM_RENDER; + } + else if (!strcasecmp(render_mode,"points")) + { + sp->random_render = False; + render = RENDER_POINTS; + } + else if (!strcasecmp(render_mode,"lines")) + { + sp->random_render = False; + render = RENDER_LINES; + } + else if (!strcasecmp(render_mode,"line-loops")) + { + sp->random_render = False; + render = RENDER_LINE_LOOP; + } + else + { + sp->random_render = True; + render = random() % NUM_RENDER; + } + + switch (render) + { + case RENDER_POINTS: + sp->render = GL_POINTS; + break; + case RENDER_LINES: + sp->render = GL_LINES; + break; + case RENDER_LINE_LOOP: + if (sp->surface == SURFACE_BOHEMIAN || + sp->surface == SURFACE_PLUECKER || + sp->surface == SURFACE_HENNEBERG) + sp->render = GL_LINE_LOOP; + else + sp->render = GL_LINE_STRIP; + break; + default: + sp->render = GL_LINE_LOOP; + break; + } + + sp->frame = 0; + + sp->du = 0.07; + sp->dv = 0.07; + sp->a = sp->b = 1; + sp->c = 0.1; + + if ((sp->glx_context = init_GL(mi)) != NULL) + { + reshape_surface(mi, MI_WIDTH(mi), MI_HEIGHT(mi)); + } + else + { + MI_CLEARWINDOW(mi); + } +} + + +ENTRYPOINT void draw_surface(ModeInfo * mi) +{ + surfacestruct *sp = &surface[MI_SCREEN(mi)]; + Display *display = MI_DISPLAY(mi); + Window window = MI_WINDOW(mi); + + if (!sp->glx_context) + return; + + glDrawBuffer(GL_BACK); + + glXMakeCurrent(display, window, *(sp->glx_context)); + draw(mi); + if (mi->fps_p) + do_fps(mi); + glFinish(); + glXSwapBuffers(display, window); +} + + +ENTRYPOINT void release_surface(ModeInfo * mi) +{ + if (surface != NULL) + { + int screen; + + for (screen = 0; screen < MI_NUM_SCREENS(mi); screen++) + { + surfacestruct *sp = &surface[screen]; + + if (sp->glx_context) + { + /* Display lists MUST be freed while their glXContext is current. */ + glXMakeCurrent(MI_DISPLAY(mi), sp->window, *(sp->glx_context)); + } + } + (void) free((void *)surface); + surface = NULL; + } + FreeAllGL(mi); +} + + +XSCREENSAVER_MODULE_2("Surfaces", surfaces, surface) + +#endif diff --git a/hacks/glx/surfaces.man b/hacks/glx/surfaces.man new file mode 100644 index 00000000..4c62a0e7 --- /dev/null +++ b/hacks/glx/surfaces.man @@ -0,0 +1,127 @@ +.TH XScreenSaver 1 "" "X Version 11" +.SH NAME +surfaces - Draws some interesting 3d parametric surfaces. +.SH SYNOPSIS +.B surfaces +[\-display \fIhost:display.screen\fP] +[\-visual \fIvisual\fP] +[\-window] +[\-root] +[\-speed \fInumber\fP] +[\-rand] +[\-spin] +[\-wander] +[\-fps] +[\-surface \fIsurface-name\fP] +[\-random-surface] +[\-dini] +[\-enneper] +[\-kuen] +[\-moebius] +[\-seashell] +[\-swallowtail] +[\-bohemian] +[\-whitney] +[\-pluecker] +[\-henneberg] +[\-catalan] +[\-corkscrew] +[\-mode \fIdisplay-mode\fP] +[\-random-mode] +[\-points] +[\-lines] +[\-line-loops] +.SH DESCRIPTION +This draws one of several three dimensional parametric surfaces. +.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: 20000 (0.02 seconds.). +.TP 8 +.B \-speed \fInumber\fP +Number of frames before changing shape. Default: 1000. +.TP 8 +.B \-surface random \fP(Shortcut: \fB\-random-surface\fP) +Display a random surface. This is the default. +.TP 8 +.B \-surface dini \fP(Shortcut: \fB\-dini\fP) +Display Dini's surface. +.TP 8 +.B \-surface enneper \fP(Shortcut: \fB\-enneper\fP) +Display Enneper's minimal surface. +.TP 8 +.B \-surface kuen \fP(Shortcut: \fB\-kuen\fP) +Display the Kuen surface. +.TP 8 +.B \-surface moebius \fP(Shortcut: \fB\-moebius\fP) +Display the Moebius strip. +.TP 8 +.B \-surface seashell \fP(Shortcut: \fB\-seashell\fP) +Display the seashell surface. +.TP 8 +.B \-surface swallowtail \fP(Shortcut: \fB\-swallowtail\fP) +Display the swallowtail catastrophe. +.TP 8 +.B \-surface bohemian \fP(Shortcut: \fB\-bohemian\fP) +Display the Bohemian dome. +.TP 8 +.B \-surface whitney \fP(Shortcut: \fB\-whitney\fP) +Display the Whitney umbrella. +.TP 8 +.B \-surface pluecker \fP(Shortcut: \fB\-pluecker\fP) +Display Pluecker's conoid. +.TP 8 +.B \-surface henneberg \fP(Shortcut: \fB\-henneberg\fP) +Display Henneberg's minimal surface. +.TP 8 +.B \-surface catalan \fP(Shortcut: \fB\-catalan\fP) +Display Catalan's minimal surface. +.TP 8 +.B \-surface corkscrew \fP(Shortcut: \fB\-corkscrew\fP) +Display the corkscrew surface. +.TP 8 +.B \-mode random \fP(Shortcut: \fB\-random-mode\fP) +Use random OpenGL primitives to display the surface. This is the +default. +.TP 8 +.B \-mode points \fP(Shortcut: \fB\-points\fP) +Use OpenGL points to display the surface. +.TP 8 +.B \-mode lines \fP(Shortcut: \fB\-lines\fP) +Use OpenGL lines to display the surface. +.TP 8 +.B \-mode line-loops \fP(Shortcut: \fB\-line-loops\fP) +Use OpenGL line loops to display the surface. +.TP 8 +.B \-wander | \-no-wander +Whether to wander around the screen. +.TP 8 +.B \-spin | \-no-spin +Whether to rotate around the center of the figure. +.TP 8 +.B \-fps +Display the current frame rate, CPU load, and polygon count. +.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 AUTHORS +Andrey Mirtchovski, Carsten Steger diff --git a/hacks/glx/swim.c b/hacks/glx/swim.c new file mode 100644 index 00000000..e20655a2 --- /dev/null +++ b/hacks/glx/swim.c @@ -0,0 +1,232 @@ +/* atlantis --- Shows moving 3D sea animals */ + +#if 0 +static const char sccsid[] = "@(#)swim.c 1.3 98/06/18 xlockmore"; +#endif + +/* Copyright (c) E. Lassauge, 1998. */ + +/* + * Permission to use, copy, modify, and distribute this software and its + * documentation for any purpose and without fee is hereby granted, + * provided that the above copyright notice appear in all copies and that + * both that copyright notice and this permission notice appear in + * supporting documentation. + * + * This file is provided AS IS with no warranties of any kind. The author + * shall have no liability with respect to the infringement of copyrights, + * trade secrets or any patents by this file or any part thereof. In no + * event will the author be liable for any lost revenue or profits or + * other special, indirect and consequential damages. + * + * The original code for this mode was written by Mark J. Kilgard + * as a demo for openGL programming. + * + * Porting it to xlock was possible by comparing the original Mesa's morph3d + * demo with it's ported version to xlock, so thanks for Marcelo F. Vianna + * (look at morph3d.c) for his indirect help. + * + * Thanks goes also to Brian Paul for making it possible and inexpensive + * to use OpenGL at home. + * + * My e-mail address is lassauge@users.sourceforge.net + * + * Eric Lassauge (May-13-1998) + * + */ + +/** + * (c) Copyright 1993, 1994, Silicon Graphics, Inc. + * ALL RIGHTS RESERVED + * Permission to use, copy, modify, and distribute this software for + * any purpose and without fee is hereby granted, provided that the above + * copyright notice appear in all copies and that both the copyright notice + * and this permission notice appear in supporting documentation, and that + * the name of Silicon Graphics, Inc. not be used in advertising + * or publicity pertaining to distribution of the software without specific, + * written prior permission. + * + * THE MATERIAL EMBODIED ON THIS SOFTWARE IS PROVIDED TO YOU "AS-IS" + * AND WITHOUT WARRANTY OF ANY KIND, EXPRESS, IMPLIED OR OTHERWISE, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTY OF MERCHANTABILITY OR + * FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL SILICON + * GRAPHICS, INC. BE LIABLE TO YOU OR ANYONE ELSE FOR ANY DIRECT, + * SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY + * KIND, OR ANY DAMAGES WHATSOEVER, INCLUDING WITHOUT LIMITATION, + * LOSS OF PROFIT, LOSS OF USE, SAVINGS OR REVENUE, OR THE CLAIMS OF + * THIRD PARTIES, WHETHER OR NOT SILICON GRAPHICS, INC. HAS BEEN + * ADVISED OF THE POSSIBILITY OF SUCH LOSS, HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE + * POSSESSION, USE OR PERFORMANCE OF THIS SOFTWARE. + * + * US Government Users Restricted Rights + * Use, duplication, or disclosure by the Government is subject to + * restrictions set forth in FAR 52.227.19(c)(2) or subparagraph + * (c)(1)(ii) of the Rights in Technical Data and Computer Software + * clause at DFARS 252.227-7013 and/or in similar or successor + * clauses in the FAR or the DOD or NASA FAR Supplement. + * Unpublished-- rights reserved under the copyright laws of the + * United States. Contractor/manufacturer is Silicon Graphics, + * Inc., 2011 N. Shoreline Blvd., Mountain View, CA 94039-7311. + * + * OpenGL(TM) is a trademark of Silicon Graphics, Inc. + */ + +#ifdef STANDALONE +# include +# include "xlockmoreI.h" /* from the xscreensaver distribution */ +#else /* !STANDALONE */ +# include "xlock.h" /* from the xlockmore distribution */ +#endif /* !STANDALONE */ + +#ifdef USE_GL + +#include "atlantis.h" + +void +FishTransform(fishRec * fish) +{ + + glTranslatef(fish->y, fish->z, -fish->x); + glRotatef(-fish->psi, 0.0, 1.0, 0.0); + glRotatef(fish->theta, 1.0, 0.0, 0.0); + glRotatef(-fish->phi, 0.0, 0.0, 1.0); +} + +void +WhalePilot(fishRec * fish, float whalespeed, Bool whaledir) +{ + + fish->phi = -20.0; + fish->theta = 0.0; + fish->psi += ((whaledir) ? -0.5 : 0.5); + + fish->x += whalespeed * fish->v * cos(fish->psi / RAD) * cos(fish->theta / RAD); + fish->y += whalespeed * fish->v * sin(fish->psi / RAD) * cos(fish->theta / RAD); + fish->z += whalespeed * fish->v * sin(fish->theta / RAD); +} + +void +SharkPilot(fishRec * fish, float sharkspeed) +{ + float X, Y, Z, tpsi, ttheta, thetal; + + fish->xt = 60000.0; + fish->yt = 0.0; + fish->zt = 0.0; + + X = fish->xt - fish->x; + Y = fish->yt - fish->y; + Z = fish->zt - fish->z; + + thetal = fish->theta; + + ttheta = RAD * atan(Z / (sqrt(X * X + Y * Y))); + + if (ttheta > fish->theta + 0.25) { + fish->theta += 0.5; + } else if (ttheta < fish->theta - 0.25) { + fish->theta -= 0.5; + } + if (fish->theta > 90.0) { + fish->theta = 90.0; + } + if (fish->theta < -90.0) { + fish->theta = -90.0; + } + fish->dtheta = fish->theta - thetal; + + tpsi = RAD * atan2(Y, X); + + fish->attack = 0; + + if (fabs(tpsi - fish->psi) < 10.0) { + fish->attack = 1; + } else if (fabs(tpsi - fish->psi) < 45.0) { + if (fish->psi > tpsi) { + fish->psi -= 0.5; + if (fish->psi < -180.0) { + fish->psi += 360.0; + } + } else if (fish->psi < tpsi) { + fish->psi += 0.5; + if (fish->psi > 180.0) { + fish->psi -= 360.0; + } + } + } else { + if (NRAND(100) > 98) { + fish->sign = (fish->sign < 0 ? 1 : -1); + } + fish->psi += (fish->sign ? 1 : -1); + if (fish->psi > 180.0) { + fish->psi -= 360.0; + } + if (fish->psi < -180.0) { + fish->psi += 360.0; + } + } + + if (fish->attack) { + if (fish->v < 1.1) { + fish->spurt = 1; + } + if (fish->spurt) { + fish->v += 0.2; + } + if (fish->v > 5.0) { + fish->spurt = 0; + } + if ((fish->v > 1.0) && (!fish->spurt)) { + fish->v -= 0.2; + } + } else { + if (!(NRAND(400)) && (!fish->spurt)) { + fish->spurt = 1; + } + if (fish->spurt) { + fish->v += 0.05; + } + if (fish->v > 3.0) { + fish->spurt = 0; + } + if ((fish->v > 1.0) && (!fish->spurt)) { + fish->v -= 0.05; + } + } + + fish->x += sharkspeed * fish->v * cos(fish->psi / RAD) * cos(fish->theta / RAD); + fish->y += sharkspeed * fish->v * sin(fish->psi / RAD) * cos(fish->theta / RAD); + fish->z += sharkspeed * fish->v * sin(fish->theta / RAD); +} + +void +SharkMiss(atlantisstruct * ap, int i) +{ + int j; + float avoid, thetal; + float X, Y, Z, R; + + for (j = 0; j < ap->num_sharks; j++) { + if (j != i) { + X = ap->sharks[j].x - ap->sharks[i].x; + Y = ap->sharks[j].y - ap->sharks[i].y; + Z = ap->sharks[j].z - ap->sharks[i].z; + + R = sqrt(X * X + Y * Y + Z * Z); + + avoid = 1.0; + thetal = ap->sharks[i].theta; + + if (R < ap->sharksize) { + if (Z > 0.0) { + ap->sharks[i].theta -= avoid; + } else { + ap->sharks[i].theta += avoid; + } + } + ap->sharks[i].dtheta += (ap->sharks[i].theta - thetal); + } + } +} +#endif diff --git a/hacks/glx/tangram.c b/hacks/glx/tangram.c new file mode 100644 index 00000000..02247759 --- /dev/null +++ b/hacks/glx/tangram.c @@ -0,0 +1,1095 @@ +/* tangram, Copyright (c) 2005 Jeremy English + * + * 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. + * + * Sun 10 July 2005 Changed the code that solves the puzzles. + * Also, limited the palette and added names. + * + * Wed 13 July 2005 Added option to turn off rotation. + * Changed color and materials + */ + + +#define DEFAULTS "*delay: 10000 \n" \ + "*wireframe: False \n" \ + "*titleFont: -*-helvetica-medium-r-normal-*-180-*\n" \ + "*titleFont2: -*-helvetica-medium-r-normal-*-120-*\n" \ + "*titleFont3: -*-helvetica-medium-r-normal-*-80-*\n" \ + +# define refresh_tangram 0 +# define release_tangram 0 +# define tangram_handle_event 0 +#undef countof +#define countof(x) (sizeof((x))/sizeof((*x))) + +#include "xlockmore.h" + +#include + + +#ifdef USE_GL /* whole file */ + +#include +#include +#include "tangram_shapes.h" +#include "glxfonts.h" + +typedef struct { + GLubyte r; + GLubyte g; + GLubyte b; +} color; + +typedef struct { + GLfloat x; + GLfloat y; + GLfloat z; +} coord; + +typedef struct { + coord crd; /* coordinates */ + GLint r; /* rotation */ + GLint fr; /* flip Rotate. Used to keep track during animation */ + GLint dl; /* display List */ + GLfloat dz; /* velocity */ + GLfloat ddz; /* Acceleration */ + GLfloat solved; /* shapes state */ + Bool up; /* Move up the z axis? */ +} tangram_shape; + +typedef struct { + char *name; + tangram_shape ts[7]; +} puzzle; + +typedef enum { + no_shape = -1, + small_triangle1 = 0, + small_triangle2 = 1, + medium_triangle = 2, + large_triangle1 = 3, + large_triangle2 = 4, + square = 5, + rhomboid = 6 +} shape_type; + +#define SPEED 0.03 +enum { + BOTTOM = 0, + DEF_WAIT = 500, + INIT_DZ = 2, + NUM_SHAPES = 7 +}; + +typedef struct { + GLXContext *glx_context; + tangram_shape tsm1, tsm2, tm, tlg1, tlg2, sq, rh; + tangram_shape n_tsm1, n_tsm2, n_tm, n_tlg1, n_tlg2, n_sq, n_rh; + char *puzzle_name; + int csi; + + int ncolors; + XColor *colors; + int ccolor; + +# ifdef HAVE_GLBITMAP + XFontStruct *xfont1; + XFontStruct *xfont2; + XFontStruct *xfont3; + GLuint font1_dlist, font2_dlist, font3_dlist; +# else + texture_font_data *font1_data, *font2_data, *font3_data; +# endif + + GLuint name_list; + + GLfloat theta[3]; + Bool going_down[3]; + + const char *pn; + int display_counter; + +} tangram_configuration; + +static tangram_configuration *tps = NULL; + +#define DEF_VIEWING_TIME "5" +#define DEF_ROTATE "True" +#define DEF_X_CAMERA_ROTATE "0.2" +#define DEF_Y_CAMERA_ROTATE "0.5" +#define DEF_Z_CAMERA_ROTATE "0" +#define DEF_LABELS "True" + +static GLuint viewing_time; +static Bool do_rotate; +static Bool do_labels; +static GLfloat x_camera_rotate; +static GLfloat y_camera_rotate; +static GLfloat z_camera_rotate; +static int wire; + +static XrmOptionDescRec opts[] = { + {"-viewing_time", ".viewingTime", XrmoptionSepArg, 0}, + {"-rotate", ".rotate", XrmoptionNoArg, "True"}, + {"+rotate", ".rotate", XrmoptionNoArg, "False"}, + {"-labels", ".labels", XrmoptionNoArg, "True"}, + {"+labels", ".labels", XrmoptionNoArg, "False"}, + {"-x_camera_rotate", ".xCameraRotate", XrmoptionSepArg, 0}, + {"-y_camera_rotate", ".yCameraRotate", XrmoptionSepArg, 0}, + {"-z_camera_rotate", ".zCameraRotate", XrmoptionSepArg, 0} +}; + +static argtype vars[] = { + {&viewing_time, "viewingTime", "ViewingTime", DEF_VIEWING_TIME, t_Int}, + {&do_rotate, "rotate", "Rotate", DEF_ROTATE, t_Bool}, + {&do_labels, "labels", "Labels", DEF_LABELS, t_Bool}, + {&x_camera_rotate, "xCameraRotate", "XCameraRotate", DEF_X_CAMERA_ROTATE, t_Float}, + {&y_camera_rotate, "yCameraRotate", "YCameraRotate", DEF_Y_CAMERA_ROTATE, t_Float}, + {&z_camera_rotate, "zCameraRotate", "ZCameraRotate", DEF_Z_CAMERA_ROTATE, t_Float} +}; + +ENTRYPOINT ModeSpecOpt tangram_opts = { countof(opts), opts, countof(vars), vars, NULL }; + +static const puzzle solved[] = { + {"Teapot", { + {{-1.664000, -1.552000, 0}, 135, 0, 0, INIT_DZ, -SPEED, 0, True}, + {{-1.696000, 0.944000, 0}, 315, 0, 0, INIT_DZ, -SPEED, 0, False}, + {{0.064000, -2.128000, 0}, 135, 0, 0, INIT_DZ, -SPEED, 0, True}, + {{-0.960000, -1.056000, 0}, 90, 0, 0, INIT_DZ, -SPEED, 0, False}, + {{1.104000, 0.960000, 0}, 270, 0, 0, INIT_DZ, -SPEED, 0, True}, + {{-1.376000, -0.800000, 0}, 180, 0, 0, INIT_DZ, -SPEED, 0, False}, + {{1.152000, 0.736000, 0}, 360, 0, 0, INIT_DZ, -SPEED, 0, True}, + }, + }, + {"Candle", { + {{-0.016000, 2.176001, 0}, 135, 180, 0, INIT_DZ, -SPEED, 0, False}, + {{0.016000, 2.960001, 0}, 315, 0, 0, INIT_DZ, -SPEED, 0, True}, + {{0.000000, 0.400000, 0}, 135, 180, 0, INIT_DZ, -SPEED, 0, False}, + {{-2.015998, 2.208001, 0}, 90, 180, 0, INIT_DZ, -SPEED, 0, True}, + {{2.000001, 2.208001, 0}, 270, 0, 0, INIT_DZ, -SPEED, 0, False}, + {{0.496000, 0.432000, 0}, 180, 0, 0, INIT_DZ, -SPEED, 0, True}, + {{-0.016000, -0.672000, 0}, 335, 0, 0, INIT_DZ, -SPEED, 0, False}, + }, + }, + {"Square", { + {{-0.048000, -0.016000, 0}, 225, 0, 0, INIT_DZ, -SPEED, 0, True}, + {{0.704000, 0.736000, 0}, 135, 0, 0, INIT_DZ, -SPEED, 0, False}, + {{-1.488000, 1.424001, 0}, 0, 0, 0, INIT_DZ, -SPEED, 0, True}, + {{-0.016000, -0.016000, 0}, 315, 0, 0, INIT_DZ, -SPEED, 0, False}, + {{0.000000, 0.000000, 0}, 45, 0, 0, INIT_DZ, -SPEED, 0, True}, + {{0.688000, 0.720000, 0}, 225, 0, 0, INIT_DZ, -SPEED, 0, False}, + {{-0.784000, 0.672000, 0}, 315, 0, 0, INIT_DZ, -SPEED, 0, True}, + }, + }, + {"Crane", { + {{1.248001, 1.759999, 0}, 225, 0, 0, INIT_DZ, -SPEED, 0, False}, + {{1.024000, 3.071999, 0}, 270, 0, 0, INIT_DZ, -SPEED, 0, True}, + {{-0.975999, -2.096001, 0}, 270, 0, 0, INIT_DZ, -SPEED, 0, False}, + {{0.480000, -1.968001, 0}, 135, 0, 0, INIT_DZ, -SPEED, 0, True}, + {{1.056000, -0.496000, 0}, 180, 0, 0, INIT_DZ, -SPEED, 0, False}, + {{-0.239999, -1.312001, 0}, 225, 0, 0, INIT_DZ, -SPEED, 0, True}, + {{-0.223999, -1.360001, 0}, 315, 0, 0, INIT_DZ, -SPEED, 0, False}, + }, + }, + {"Crane", { + {{0.320000, 1.360000, 0}, 90, 0, 0, INIT_DZ, -SPEED, 0, True}, + {{0.704000, 3.072000, 0}, 270, 0, 0, INIT_DZ, -SPEED, 0, False}, + {{-1.200000, -3.392000, 0}, 135, 0, 0, INIT_DZ, -SPEED, 0, True}, + {{0.688000, -1.184000, 0}, 135, 0, 0, INIT_DZ, -SPEED, 0, False}, + {{-0.768000, 0.192000, 0}, 315, 0, 0, INIT_DZ, -SPEED, 0, True}, + {{-1.168000, -2.304000, 0}, 180, 0, 0, INIT_DZ, -SPEED, 0, False}, + {{1.312000, 1.296000, 0}, 270, 0, 0, INIT_DZ, -SPEED, 0, True}, + }, + }, + {"Duck", { + {{-1.391999, 1.424000, 0}, 65, 0, 0, INIT_DZ, -SPEED, 0, False}, + {{0.768000, 2.000000, 0}, 99, 180, 0, INIT_DZ, -SPEED, 0, True}, + {{2.688001, -1.872000, 0}, 270, 180, 0, INIT_DZ, -SPEED, 0, False}, + {{-1.343999, 0.944000, 0}, 315, 0, 0, INIT_DZ, -SPEED, 0, True}, + {{0.112000, -0.464000, 0}, 135, 0, 0, INIT_DZ, -SPEED, 0, False}, + {{1.984001, -1.120000, 0}, 225, 0, 0, INIT_DZ, -SPEED, 0, True}, + {{1.536001, 0.912000, 0}, 180, 180, 0, INIT_DZ, -SPEED, 0, False}, + }, + }, + {"Pelican", { + {{1.088000, 0.064001, 0}, 135, 0, 0, INIT_DZ, -SPEED, 0, True}, + {{0.864000, -1.279999, 0}, 90, 180, 0, INIT_DZ, -SPEED, 0, False}, + {{-1.807999, 1.520000, 0}, 90, 180, 0, INIT_DZ, -SPEED, 0, True}, + {{1.824001, -1.231998, 0}, 180, 0, 0, INIT_DZ, -SPEED, 0, False}, + {{-0.368000, 1.472000, 0}, 135, 180, 0, INIT_DZ, -SPEED, 0, True}, + {{0.832000, -2.271998, 0}, 180, 0, 0, INIT_DZ, -SPEED, 0, False}, + {{1.776001, 0.816000, 0}, 225, 0, 0, INIT_DZ, -SPEED, 0, True}, + }, + }, + {"Cat", { + {{0.416000, -2.432000, 0}, 45, 0, 0, INIT_DZ, -SPEED, 0, False}, + {{0.352000, -2.432000, 0}, 225, 180, 0, INIT_DZ, -SPEED, 0, True}, + {{0.832000, -0.480000, 0}, 225, 180, 0, INIT_DZ, -SPEED, 0, False}, + {{-1.632000, 3.056000, 0}, 0, 0, 0, INIT_DZ, -SPEED, 0, True}, + {{-1.616000, 1.040000, 0}, 45, 180, 0, INIT_DZ, -SPEED, 0, False}, + {{1.088000, -1.696000, 0}, 225, 0, 0, INIT_DZ, -SPEED, 0, True}, + {{0.832000, -0.432000, 0}, 180, 0, 0, INIT_DZ, -SPEED, 0, False}, + }, + }, + {"Coi", { + {{1.264000, -1.232000, 0}, 45, 0, 0, INIT_DZ, -SPEED, 0, True}, + {{1.216000, 0.816000, 0}, 180, 180, 0, INIT_DZ, -SPEED, 0, False}, + {{-1.631999, 1.872000, 0}, 135, 180, 0, INIT_DZ, -SPEED, 0, True}, + {{0.832000, 2.287999, 0}, 315, 0, 0, INIT_DZ, -SPEED, 0, False}, + {{-0.608000, 0.912000, 0}, 315, 180, 0, INIT_DZ, -SPEED, 0, True}, + {{2.240001, -0.176000, 0}, 180, 0, 0, INIT_DZ, -SPEED, 0, False}, + {{0.256000, -1.200000, 0}, 90, 0, 0, INIT_DZ, -SPEED, 0, True}, + }, + }, + {"Man Skipping", { + {{1.727998, 2.303998, 0}, 180, 0, 0, INIT_DZ, -SPEED, 0, False}, + {{-1.120000, 3.376001, 0}, 180, 180, 0, INIT_DZ, -SPEED, 0, True}, + {{0.879998, -3.008001, 0}, 180, 0, 0, INIT_DZ, -SPEED, 0, False}, + {{-1.072000, 2.559999, 0}, 360, 0, 0, INIT_DZ, -SPEED, 0, True}, + {{-1.440000, 0.144000, 0}, 45, 180, 0, INIT_DZ, -SPEED, 0, False}, + {{-0.192001, -2.592001, 0}, 135, 0, 0, INIT_DZ, -SPEED, 0, True}, + {{0.015999, 0.176000, 0}, 135, 0, 0, INIT_DZ, -SPEED, 0, False}, + }, + }, + {"Old Man", { + {{-0.400000, 1.744000, 0}, 58, 180, 0, INIT_DZ, -SPEED, 0, True}, + {{0.704000, 0.128000, 0}, 90, 180, 0, INIT_DZ, -SPEED, 0, False}, + {{0.656000, 0.320000, 0}, 180, 180, 0, INIT_DZ, -SPEED, 0, True}, + {{-0.112000, -0.384000, 0}, 225, 0, 0, INIT_DZ, -SPEED, 0, False}, + {{-0.096000, -0.399999, 0}, 135, 180, 0, INIT_DZ, -SPEED, 0, True}, + {{-0.736000, 0.352000, 0}, 123, 0, 0, INIT_DZ, -SPEED, 0, False}, + {{-0.336000, 0.352000, 0}, 90, 0, 0, INIT_DZ, -SPEED, 0, True}, + }, + }, + {"Spear Head", { + {{0.688000, -0.144000, 0}, 45, 180, 0, INIT_DZ, -SPEED, 0, False}, + {{-0.080000, 0.592000, 0}, 225, 0, 0, INIT_DZ, -SPEED, 0, True}, + {{-0.048000, 0.592000, 0}, 315, 180, 0, INIT_DZ, -SPEED, 0, False}, + {{-1.488000, -0.848000, 0}, 45, 0, 0, INIT_DZ, -SPEED, 0, True}, + {{1.376000, -0.864000, 0}, 225, 180, 0, INIT_DZ, -SPEED, 0, False}, + {{0.688000, -0.128000, 0}, 135, 0, 0, INIT_DZ, -SPEED, 0, True}, + {{-1.504000, -0.832000, 0}, 135, 0, 0, INIT_DZ, -SPEED, 0, False}, + }, + }, + {"Diamond", { + {{0.624000, -1.776000, 0}, 225, 180, 0, INIT_DZ, -SPEED, 0, True}, + {{-0.144000, 0.432000, 0}, 225, 0, 0, INIT_DZ, -SPEED, 0, False}, + {{-0.800000, -0.272000, 0}, 45, 180, 0, INIT_DZ, -SPEED, 0, True}, + {{-2.320000, -0.304000, 0}, 45, 0, 0, INIT_DZ, -SPEED, 0, False}, + {{2.048000, -0.320000, 0}, 225, 180, 0, INIT_DZ, -SPEED, 0, True}, + {{-0.112000, 0.480000, 0}, 135, 0, 0, INIT_DZ, -SPEED, 0, False}, + {{-0.832000, -0.320000, 0}, 135, 180, 0, INIT_DZ, -SPEED, 0, True}, + }, + }, + {"Arrow", { + {{-2.048001, -1.232000, 0}, 45, 180, 0, INIT_DZ, -SPEED, 0, False}, + {{0.112000, 0.943999, 0}, 315, 0, 0, INIT_DZ, -SPEED, 0, True}, + {{-1.312001, -0.560000, 0}, 90, 180, 0, INIT_DZ, -SPEED, 0, False}, + {{0.496000, 0.656000, 0}, 135, 0, 0, INIT_DZ, -SPEED, 0, True}, + {{0.528000, 0.608000, 0}, 45, 180, 0, INIT_DZ, -SPEED, 0, False}, + {{-2.048001, -2.704000, 0}, 135, 0, 0, INIT_DZ, -SPEED, 0, True}, + {{-1.312001, -0.512000, 0}, 45, 180, 0, INIT_DZ, -SPEED, 0, False}, + }, + }, + {"Lady", { + {{-0.720000, 3.440000, 0}, 180, 180, 0, INIT_DZ, -SPEED, 0, True}, + {{0.912000, -1.072000, 0}, 225, 0, 0, INIT_DZ, -SPEED, 0, False}, + {{0.736000, 3.440000, 0}, 180, 180, 0, INIT_DZ, -SPEED, 0, True}, + {{0.720000, 1.984000, 0}, 225, 0, 0, INIT_DZ, -SPEED, 0, False}, + {{-0.672000, 0.544000, 0}, 45, 180, 0, INIT_DZ, -SPEED, 0, True}, + {{-0.192000, -3.840000, 0}, 135, 0, 0, INIT_DZ, -SPEED, 0, False}, + {{-0.528000, -2.480000, 0}, 135, 0, 0, INIT_DZ, -SPEED, 0, True}, + }, + }, + {"Running Man", { + {{1.136000, 2.720000, 0}, 90, 180, 0, INIT_DZ, -SPEED, 0, False}, + {{-2.304001, 1.776000, 0}, 90, 0, 0, INIT_DZ, -SPEED, 0, True}, + {{-0.256000, 0.288000, 0}, 45, 180, 0, INIT_DZ, -SPEED, 0, False}, + {{-0.304000, 0.304000, 0}, 135, 0, 0, INIT_DZ, -SPEED, 0, True}, + {{0.096000, -0.128000, 0}, 135, 180, 0, INIT_DZ, -SPEED, 0, False}, + {{-0.656000, -2.832000, 0}, 105, 0, 0, INIT_DZ, -SPEED, 0, True}, + {{0.784000, -0.096000, 0}, 135, 0, 0, INIT_DZ, -SPEED, 0, False}, + }, + }, + {"Parallelogram", { + {{-1.104000, -1.455999, 0}, 90, 0, 0, INIT_DZ, -SPEED, 0, True}, + {{0.912000, -0.447999, 0}, 180, 0, 0, INIT_DZ, -SPEED, 0, False}, + {{-0.048000, -1.471999, 0}, 135, 0, 0, INIT_DZ, -SPEED, 0, True}, + {{-1.136000, -1.439999, 0}, 180, 0, 0, INIT_DZ, -SPEED, 0, False}, + {{0.944000, 1.552000, 0}, 0, 0, 0, INIT_DZ, -SPEED, 0, True}, + {{0.912000, 0.560000, 0}, 180, 0, 0, INIT_DZ, -SPEED, 0, False}, + {{-0.112000, 1.568000, 0}, 180, 180, 0, INIT_DZ, -SPEED, 0, True}, + }, + }, + {"N", { + {{-1.615999, 0.064000, 0}, 0, 0, 0, INIT_DZ, -SPEED, 0, False}, + {{-0.592000, 0.112000, 0}, 90, 0, 0, INIT_DZ, -SPEED, 0, True}, + {{0.432000, 0.096000, 0}, 45, 0, 0, INIT_DZ, -SPEED, 0, False}, + {{-1.679999, -0.880000, 0}, 180, 0, 0, INIT_DZ, -SPEED, 0, True}, + {{1.488001, 1.103999, 0}, 0, 0, 0, INIT_DZ, -SPEED, 0, False}, + {{-0.640000, 0.112000, 0}, 180, 0, 0, INIT_DZ, -SPEED, 0, True}, + {{1.392001, -0.928000, 0}, 270, 180, 0, INIT_DZ, -SPEED, 0, False}, + }, + }, + {"Farm House", { + {{2.112000, 1.504000, 0}, 0, 0, 0, INIT_DZ, -SPEED, 0, True}, + {{-1.040000, 1.472000, 0}, 180, 180, 0, INIT_DZ, -SPEED, 0, False}, + {{0.032000, -1.600000, 0}, 135, 0, 0, INIT_DZ, -SPEED, 0, True}, + {{1.056000, 1.504000, 0}, 270, 0, 0, INIT_DZ, -SPEED, 0, False}, + {{-0.992000, -0.528000, 0}, 0, 180, 0, INIT_DZ, -SPEED, 0, True}, + {{2.080000, 0.512000, 0}, 180, 0, 0, INIT_DZ, -SPEED, 0, False}, + {{-1.104000, 0.480000, 0}, 270, 180, 0, INIT_DZ, -SPEED, 0, True}, + }, + }, + {"Vulture", { + {{0.912000, 1.728000, 0}, 135, 0, 0, INIT_DZ, -SPEED, 0, False}, + {{-2.623998, -1.040000, 0}, 135, 0, 0, INIT_DZ, -SPEED, 0, True}, + {{0.992000, 1.104000, 0}, 90, 180, 0, INIT_DZ, -SPEED, 0, False}, + {{0.944000, -0.288000, 0}, 180, 0, 0, INIT_DZ, -SPEED, 0, True}, + {{-0.448000, -1.760000, 0}, 315, 180, 0, INIT_DZ, -SPEED, 0, False}, + {{-1.887998, -0.368000, 0}, 315, 0, 0, INIT_DZ, -SPEED, 0, True}, + {{3.008002, 2.160000, 0}, 270, 0, 0, INIT_DZ, -SPEED, 0, False}, + }, + }, + {"Swan", { + {{0.720000, 0.352000, 0}, 45, 0, 0, INIT_DZ, -SPEED, 0, True}, + {{0.672000, -1.568000, 0}, 0, 0, 0, INIT_DZ, -SPEED, 0, False}, + {{1.376000, 1.104000, 0}, 225, 180, 0, INIT_DZ, -SPEED, 0, True}, + {{-1.151999, 1.488000, 0}, 315, 0, 0, INIT_DZ, -SPEED, 0, False}, + {{0.320000, 2.096000, 0}, 180, 180, 0, INIT_DZ, -SPEED, 0, True}, + {{0.656000, 0.304000, 0}, 315, 0, 0, INIT_DZ, -SPEED, 0, False}, + {{0.624000, -2.559999, 0}, 315, 180, 0, INIT_DZ, -SPEED, 0, True}, + }, + }, + {"High Karate", { + {{-0.144000, 2.576000, 0}, 270, 0, 0, INIT_DZ, -SPEED, 0, False}, + {{1.696001, -2.432000, 0}, 90, 0, 0, INIT_DZ, -SPEED, 0, True}, + {{2.176001, -0.400000, 0}, 180, 180, 0, INIT_DZ, -SPEED, 0, False}, + {{-0.624000, -0.512000, 0}, 270, 0, 0, INIT_DZ, -SPEED, 0, True}, + {{-0.576000, -1.152000, 0}, 0, 180, 0, INIT_DZ, -SPEED, 0, False}, + {{-1.919999, -1.376000, 0}, 303, 0, 0, INIT_DZ, -SPEED, 0, True}, + {{0.448000, -0.096001, 0}, 180, 0, 0, INIT_DZ, -SPEED, 0, False}, + }, + }, + {"Lazy", { + {{-2.416000, 1.120000, 0}, 315, 0, 0, INIT_DZ, -SPEED, 0, True}, + {{-1.952000, -2.016000, 0}, 45, 0, 0, INIT_DZ, -SPEED, 0, False}, + {{-1.552000, -0.640000, 0}, 315, 180, 0, INIT_DZ, -SPEED, 0, True}, + {{-0.016000, 1.840000, 0}, 315, 0, 0, INIT_DZ, -SPEED, 0, False}, + {{1.456000, -1.072000, 0}, 315, 180, 0, INIT_DZ, -SPEED, 0, True}, + {{0.848000, -0.816000, 0}, 332, 0, 0, INIT_DZ, -SPEED, 0, False}, + {{-1.200000, -1.792000, 0}, 135, 0, 0, INIT_DZ, -SPEED, 0, True}, + }, + }, + {"Bat", { + {{-0.304000, -0.352000, 0}, 259, 0, 0, INIT_DZ, -SPEED, 0, False}, + {{0.304000, -1.344000, 0}, 105, 0, 0, INIT_DZ, -SPEED, 0, True}, + {{1.312000, -1.024000, 0}, 300, 180, 0, INIT_DZ, -SPEED, 0, False}, + {{1.952000, 0.240000, 0}, 195, 0, 0, INIT_DZ, -SPEED, 0, True}, + {{-2.272000, 0.096000, 0}, 11, 180, 0, INIT_DZ, -SPEED, 0, False}, + {{-0.112000, -1.056000, 0}, 315, 0, 0, INIT_DZ, -SPEED, 0, True}, + {{-0.560000, -1.344000, 0}, 281, 180, 0, INIT_DZ, -SPEED, 0, False}, + }, + }, + {"Sail Boat", { + {{0.544000, 2.000000, 0}, 315, 0, 0, INIT_DZ, -SPEED, 0, True}, + {{0.880000, 0.160000, 0}, 360, 0, 0, INIT_DZ, -SPEED, 0, False}, + {{0.656000, -1.503999, 0}, 220, 180, 0, INIT_DZ, -SPEED, 0, True}, + {{-0.656000, -0.336000, 0}, 50, 0, 0, INIT_DZ, -SPEED, 0, False}, + {{-0.688000, -0.288000, 0}, 310, 180, 0, INIT_DZ, -SPEED, 0, True}, + {{0.864000, 1.232000, 0}, 360, 0, 0, INIT_DZ, -SPEED, 0, False}, + {{0.496000, 2.016001, 0}, 225, 180, 0, INIT_DZ, -SPEED, 0, True}, + }, + }, + {"Glenda", { + {{-2.016000, 2.080000, 0}, 45, 0, 0, INIT_DZ, -SPEED, 0, False}, + {{0.240001, 1.824000, 0}, 360, 0, 0, INIT_DZ, -SPEED, 0, True}, + {{2.239999, -0.752000, 0}, 180, 180, 0, INIT_DZ, -SPEED, 0, False}, + {{-1.264000, 2.784000, 0}, 360, 0, 0, INIT_DZ, -SPEED, 0, True}, + {{-1.248000, 0.736000, 0}, 45, 180, 0, INIT_DZ, -SPEED, 0, False}, + {{0.240001, 0.304000, 0}, 360, 0, 0, INIT_DZ, -SPEED, 0, True}, + {{0.544000, -2.976001, 0}, 149, 0, 0, INIT_DZ, -SPEED, 0, False}, + }, + }, + {"Cat", { + {{1.376000, -1.536001, 0}, 225, 0, 0, INIT_DZ, -SPEED, 0, True}, + {{1.488000, -1.552001, 0}, 45, 0, 0, INIT_DZ, -SPEED, 0, False}, + {{0.352000, -0.048000, 0}, 225, 0, 0, INIT_DZ, -SPEED, 0, True}, + {{-2.144000, 2.415999, 0}, 0, 0, 0, INIT_DZ, -SPEED, 0, False}, + {{-2.096000, 0.368000, 0}, 45, 0, 0, INIT_DZ, -SPEED, 0, True}, + {{2.144000, -0.800000, 0}, 225, 0, 0, INIT_DZ, -SPEED, 0, False}, + {{1.392000, -0.064000, 0}, 270, 0, 0, INIT_DZ, -SPEED, 0, True}, + }, + }, + {"Lying Cat", { + {{2.480000, -0.912000, 0}, 225, 0, 0, INIT_DZ, -SPEED, 0, False}, + {{2.592000, -0.928000, 0}, 45, 0, 0, INIT_DZ, -SPEED, 0, True}, + {{0.352000, 1.280000, 0}, 315, 0, 0, INIT_DZ, -SPEED, 0, False}, + {{-0.688000, 0.336000, 0}, 135, 0, 0, INIT_DZ, -SPEED, 0, True}, + {{1.808000, -0.112000, 0}, 135, 0, 0, INIT_DZ, -SPEED, 0, False}, + {{3.248000, -0.176000, 0}, 225, 0, 0, INIT_DZ, -SPEED, 0, True}, + {{-1.472000, 1.024000, 0}, 225, 0, 0, INIT_DZ, -SPEED, 0, False}, + }, + }, + {"Witch", { + {{-0.943999, -0.304000, 0}, 270, 0, 0, INIT_DZ, -SPEED, 0, True}, + {{-0.144000, 0.288000, 0}, 270, 0, 0, INIT_DZ, -SPEED, 0, False}, + {{1.360000, -2.304000, 0}, 180, 0, 0, INIT_DZ, -SPEED, 0, True}, + {{1.328000, -0.848000, 0}, 225, 0, 0, INIT_DZ, -SPEED, 0, False}, + {{1.008000, 1.584000, 0}, 270, 0, 0, INIT_DZ, -SPEED, 0, True}, + {{0.512000, 2.688000, 0}, 270, 0, 0, INIT_DZ, -SPEED, 0, False}, + {{-0.863999, -0.096000, 0}, 135, 180, 0, INIT_DZ, -SPEED, 0, True}, + }, + }, + {"Laugh", { + {{0.703999, -0.160000, 0}, 0, 0, 0, INIT_DZ, -SPEED, 0, False}, + {{-0.064000, -0.400000, 0}, 45, 0, 0, INIT_DZ, -SPEED, 0, True}, + {{0.767999, -1.408000, 0}, 270, 0, 0, INIT_DZ, -SPEED, 0, False}, + {{-1.232000, -1.328000, 0}, 90, 0, 0, INIT_DZ, -SPEED, 0, True}, + {{-1.040000, 2.624000, 0}, 0, 0, 0, INIT_DZ, -SPEED, 0, False}, + {{-0.288000, 1.264000, 0}, 315, 0, 0, INIT_DZ, -SPEED, 0, True}, + {{-1.760001, -1.408000, 0}, 90, 180, 0, INIT_DZ, -SPEED, 0, False}, + }, + }, + {"Standing Man", { + {{0.272000, 3.392000, 0}, 270, 0, 0, INIT_DZ, -SPEED, 0, True}, + {{-0.144000, -1.328000, 0}, 331, 0, 0, INIT_DZ, -SPEED, 0, False}, + {{1.216001, 0.272000, 0}, 180, 0, 0, INIT_DZ, -SPEED, 0, True}, + {{0.736000, 0.208000, 0}, 270, 0, 0, INIT_DZ, -SPEED, 0, False}, + {{0.432000, -3.440000, 0}, 151, 0, 0, INIT_DZ, -SPEED, 0, True}, + {{0.720000, 2.320000, 0}, 270, 0, 0, INIT_DZ, -SPEED, 0, False}, + {{-1.263998, 0.272000, 0}, 90, 0, 0, INIT_DZ, -SPEED, 0, True}, + }, + }, + {"Walking Man", { + {{-1.056000, -3.456000, 0}, 90, 0, 0, INIT_DZ, -SPEED, 0, False}, + {{0.736000, 2.000000, 0}, 135, 0, 0, INIT_DZ, -SPEED, 0, True}, + {{-1.488000, 1.760000, 0}, 45, 0, 0, INIT_DZ, -SPEED, 0, False}, + {{-0.432000, 0.016000, 0}, 0, 180, 0, INIT_DZ, -SPEED, 0, True}, + {{-0.432000, -0.064000, 0}, 0, 0, 0, INIT_DZ, -SPEED, 0, False}, + {{0.560000, -2.576000, 0}, 225, 0, 0, INIT_DZ, -SPEED, 0, True}, + {{0.032000, 2.656000, 0}, 0, 0, 0, INIT_DZ, -SPEED, 0, False}, + }, + }, + {"Repose", { + {{-2.800000, -2.304000, 0}, 101, 0, 0, INIT_DZ, -SPEED, 0, True}, + {{1.888000, 2.032000, 0}, 135, 180, 0, INIT_DZ, -SPEED, 0, False}, + {{-1.856000, 2.016000, 0}, 315, 0, 0, INIT_DZ, -SPEED, 0, True}, + {{0.352000, -0.144000, 0}, 315, 180, 0, INIT_DZ, -SPEED, 0, False}, + {{-2.848000, 0.976000, 0}, 0, 0, 0, INIT_DZ, -SPEED, 0, True}, + {{-1.424000, -1.104000, 0}, 236, 0, 0, INIT_DZ, -SPEED, 0, False}, + {{-1.792000, 2.016000, 0}, 45, 0, 0, INIT_DZ, -SPEED, 0, True}, + }, + }, + {"Shape", { + {{1.263999, 1.600001, 0}, 180, 0, 0, INIT_DZ, -SPEED, 0, False}, + {{1.311999, -1.568000, 0}, 180, 180, 0, INIT_DZ, -SPEED, 0, True}, + {{-0.736000, 0.576000, 0}, 45, 0, 0, INIT_DZ, -SPEED, 0, False}, + {{-0.736000, -2.591999, 0}, 360, 180, 0, INIT_DZ, -SPEED, 0, True}, + {{-0.768000, 2.640001, 0}, 0, 0, 0, INIT_DZ, -SPEED, 0, False}, + {{-0.784000, -0.528000, 0}, 180, 0, 0, INIT_DZ, -SPEED, 0, True}, + {{-0.736000, 0.496000, 0}, 0, 0, 0, INIT_DZ, -SPEED, 0, False}, + }, + }, + {"Shape", { + {{-0.816000, 1.392000, 0}, 90, 0, 0, INIT_DZ, -SPEED, 0, True}, + {{-0.832000, -1.807999, 0}, 90, 180, 0, INIT_DZ, -SPEED, 0, False}, + {{1.216000, -0.752000, 0}, 225, 0, 0, INIT_DZ, -SPEED, 0, True}, + {{1.232000, -2.815999, 0}, 270, 180, 0, INIT_DZ, -SPEED, 0, False}, + {{1.248000, 2.400000, 0}, 270, 0, 0, INIT_DZ, -SPEED, 0, True}, + {{-0.864000, 1.392000, 0}, 180, 0, 0, INIT_DZ, -SPEED, 0, False}, + {{0.240000, 1.328000, 0}, 0, 0, 0, INIT_DZ, -SPEED, 0, True}, + }, + }, + {"Lightning", { + {{0.176000, -2.448000, 0}, 90, 0, 0, INIT_DZ, -SPEED, 0, False}, + {{-1.888000, 2.880000, 0}, 90, 180, 0, INIT_DZ, -SPEED, 0, True}, + {{-1.856000, 1.824000, 0}, 45, 0, 0, INIT_DZ, -SPEED, 0, False}, + {{-1.872000, -1.392000, 0}, 0, 180, 0, INIT_DZ, -SPEED, 0, True}, + {{1.264000, -0.432000, 0}, 270, 0, 0, INIT_DZ, -SPEED, 0, False}, + {{2.320001, -2.432000, 0}, 180, 0, 0, INIT_DZ, -SPEED, 0, True}, + {{-1.872000, 1.728000, 0}, 0, 0, 0, INIT_DZ, -SPEED, 0, False}, + }, + }, + {"E", { + {{0.928000, 1.664000, 0}, 180, 0, 0, INIT_DZ, -SPEED, 0, True}, + {{0.896000, -1.519998, 0}, 180, 180, 0, INIT_DZ, -SPEED, 0, False}, + {{-1.136000, 0.608000, 0}, 45, 0, 0, INIT_DZ, -SPEED, 0, True}, + {{-1.152000, -2.559998, 0}, 0, 180, 0, INIT_DZ, -SPEED, 0, False}, + {{-1.152000, 2.672002, 0}, 0, 0, 0, INIT_DZ, -SPEED, 0, True}, + {{0.960000, -0.384000, 0}, 180, 0, 0, INIT_DZ, -SPEED, 0, False}, + {{-1.136000, 0.528000, 0}, 0, 0, 0, INIT_DZ, -SPEED, 0, True}, + }, + }, + {"Dagger", { + {{-0.096000, 0.448000, 0}, 225, 0, 0, INIT_DZ, -SPEED, 0, False}, + {{0.640000, 2.656000, 0}, 225, 180, 0, INIT_DZ, -SPEED, 0, True}, + {{-0.064000, -3.104000, 0}, 135, 0, 0, INIT_DZ, -SPEED, 0, False}, + {{-0.767999, 1.184000, 0}, 45, 180, 0, INIT_DZ, -SPEED, 0, True}, + {{-0.080000, 0.416000, 0}, 315, 0, 0, INIT_DZ, -SPEED, 0, False}, + {{0.416000, -2.064000, 0}, 180, 0, 0, INIT_DZ, -SPEED, 0, True}, + {{-0.112000, 3.328001, 0}, 315, 0, 0, INIT_DZ, -SPEED, 0, False}, + }, + }, + {"Knight", { + {{-0.368000, 0.400000, 0}, 315, 0, 0, INIT_DZ, -SPEED, 0, True}, + {{1.871998, -1.808000, 0}, 225, 180, 0, INIT_DZ, -SPEED, 0, False}, + {{-1.056000, -0.368000, 0}, 0, 0, 0, INIT_DZ, -SPEED, 0, True}, + {{-1.056000, -1.840000, 0}, 45, 180, 0, INIT_DZ, -SPEED, 0, False}, + {{-0.352000, 1.440000, 0}, 315, 180, 0, INIT_DZ, -SPEED, 0, True}, + {{0.128000, 0.432000, 0}, 180, 0, 0, INIT_DZ, -SPEED, 0, False}, + {{1.119999, -1.120000, 0}, 315, 0, 0, INIT_DZ, -SPEED, 0, True}, + }, + }, + {"Candy", { + {{-1.039999, 1.136000, 0}, 360, 0, 0, INIT_DZ, -SPEED, 0, False}, + {{1.024000, 0.096000, 0}, 180, 180, 0, INIT_DZ, -SPEED, 0, True}, + {{-0.016000, 0.048000, 0}, 315, 0, 0, INIT_DZ, -SPEED, 0, False}, + {{-0.016000, -1.008000, 0}, 135, 180, 0, INIT_DZ, -SPEED, 0, True}, + {{-0.016000, 1.216000, 0}, 315, 180, 0, INIT_DZ, -SPEED, 0, False}, + {{1.024000, 0.144000, 0}, 180, 0, 0, INIT_DZ, -SPEED, 0, True}, + {{-0.032000, 1.088000, 0}, 180, 180, 0, INIT_DZ, -SPEED, 0, False}, + }, + }, + {"King", { + {{-0.688000, 1.904000, 0}, 135, 0, 0, INIT_DZ, -SPEED, 0, True}, + {{0.800000, 1.904000, 0}, 135, 0, 0, INIT_DZ, -SPEED, 0, False}, + {{0.512000, -1.392000, 0}, 315, 0, 0, INIT_DZ, -SPEED, 0, True}, + {{1.488000, 1.120000, 0}, 225, 0, 0, INIT_DZ, -SPEED, 0, False}, + {{-1.392000, 1.120000, 0}, 45, 0, 0, INIT_DZ, -SPEED, 0, True}, + {{0.496000, -1.312000, 0}, 180, 0, 0, INIT_DZ, -SPEED, 0, False}, + {{0.480000, -1.376000, 0}, 270, 0, 0, INIT_DZ, -SPEED, 0, True}, + }, + }, + {"Top", { + {{-1.055999, -0.800000, 0}, 90, 0, 0, INIT_DZ, -SPEED, 0, False}, + {{-1.103999, 0.208000, 0}, 270, 0, 0, INIT_DZ, -SPEED, 0, True}, + {{0.000000, -0.784000, 0}, 135, 0, 0, INIT_DZ, -SPEED, 0, False}, + {{0.016000, 0.272000, 0}, 90, 0, 0, INIT_DZ, -SPEED, 0, True}, + {{-0.032000, 0.288000, 0}, 180, 0, 0, INIT_DZ, -SPEED, 0, False}, + {{0.480000, -1.855999, 0}, 180, 0, 0, INIT_DZ, -SPEED, 0, True}, + {{2.096001, 0.224000, 0}, 270, 0, 0, INIT_DZ, -SPEED, 0, False}, + }, + }, + {"Dog", { + {{-2.896000, -0.128000, 0}, 45, 0, 0, INIT_DZ, -SPEED, 0, True}, + {{-0.800000, 0.992000, 0}, 135, 0, 0, INIT_DZ, -SPEED, 0, False}, + {{-1.152000, -0.416000, 0}, 225, 0, 0, INIT_DZ, -SPEED, 0, True}, + {{-0.016000, 0.656000, 0}, 315, 0, 0, INIT_DZ, -SPEED, 0, False}, + {{1.456000, -0.736000, 0}, 135, 0, 0, INIT_DZ, -SPEED, 0, True}, + {{2.864000, 0.736000, 0}, 180, 0, 0, INIT_DZ, -SPEED, 0, False}, + {{-0.048000, 1.664000, 0}, 180, 180, 0, INIT_DZ, -SPEED, 0, True}, + }, + }, + {"Moose Head", { + {{2.944000, -0.288000, 0}, 270, 0, 0, INIT_DZ, -SPEED, 0, False}, + {{1.936000, -0.224000, 0}, 90, 0, 0, INIT_DZ, -SPEED, 0, True}, + {{-0.112000, 1.808000, 0}, 315, 0, 0, INIT_DZ, -SPEED, 0, False}, + {{-2.128000, 0.768000, 0}, 90, 180, 0, INIT_DZ, -SPEED, 0, True}, + {{1.888000, 0.768000, 0}, 180, 180, 0, INIT_DZ, -SPEED, 0, False}, + {{-0.112000, -0.688000, 0}, 135, 0, 0, INIT_DZ, -SPEED, 0, True}, + {{-3.184000, -1.216000, 0}, 360, 180, 0, INIT_DZ, -SPEED, 0, False}, + }, + }, + {"Negative Square", { + {{-1.520000, -0.624000, 0}, 270, 0, 0, INIT_DZ, -SPEED, 0, True}, + {{-1.520000, 0.480000, 0}, 180, 0, 0, INIT_DZ, -SPEED, 0, False}, + {{2.352000, 0.480000, 0}, 225, 0, 0, INIT_DZ, -SPEED, 0, True}, + {{-0.080000, -3.040000, 0}, 315, 180, 0, INIT_DZ, -SPEED, 0, False}, + {{-0.096000, 2.944000, 0}, 135, 180, 0, INIT_DZ, -SPEED, 0, True}, + {{-2.528000, -0.576000, 0}, 90, 0, 0, INIT_DZ, -SPEED, 0, False}, + {{1.360000, -1.600000, 0}, 360, 180, INIT_DZ, -SPEED, 0, True}, + }} +}; + + +static void get_solved_puzzle(ModeInfo * mi, + tangram_shape * tsm1, tangram_shape * tsm2, + tangram_shape * tm, tangram_shape * tlg1, + tangram_shape * tlg2, tangram_shape * sq, + tangram_shape * rh) +{ + tangram_configuration *tp = &tps[MI_SCREEN(mi)]; + int sz = sizeof(solved) / sizeof(solved[0]); + int r; + + /* we don't want to see the same puzzle twice */ + do { + r = random() % sz; + } while (r == tp->csi); + tp->csi = r; + + *tsm1 = solved[r].ts[small_triangle1]; + *tsm2 = solved[r].ts[small_triangle2]; + *tm = solved[r].ts[medium_triangle]; + *tlg1 = solved[r].ts[large_triangle1]; + *tlg2 = solved[r].ts[large_triangle2]; + *sq = solved[r].ts[square]; + *rh = solved[r].ts[rhomboid]; + + tp->puzzle_name = solved[r].name; +} + +static int approach_number(int goal, int current, int step) +{ + + int i = 0; + + if (goal > current) { + while (i < step) { + current++; + if (goal <= current) + break; + i++; + } + } else if (goal < current) { + while (i < step) { + current--; + if (goal >= current) + break; + i++; + } + } + + return current; +} + +/* gt - floating point greater than comparison */ +static Bool gt(GLfloat x1, GLfloat x2, GLfloat per) +{ + if ((x1 > x2) && (fabs(x1 - x2) > per)) + return True; + else + return False; +} + +/* lt - floating point less than comparison */ +static Bool lt(GLfloat x1, GLfloat x2, GLfloat per) +{ + if ((x1 < x2) && (fabs(x1 - x2) > per)) + return True; + else + return False; +} + +static GLfloat approach_float(GLfloat goal, GLfloat current, + Bool * changed, GLfloat per) +{ + *changed = False; + if (gt(goal, current, per)) { + current += per; + *changed = True; + } else if (lt(goal, current, per)) { + current -= per; + *changed = True; + } + return current; +} + +#if 0 +static void print_shape(char *s, tangram_shape sh) +{ + fprintf(stderr, "%s\n", s); + fprintf(stderr, "(%f, %f, %f)\n", sh.crd.x, sh.crd.y, sh.crd.z); + fprintf(stderr, "%d\n", sh.r); + fprintf(stderr, "%d\n", sh.fr); + fprintf(stderr, "\n"); +} +#endif + + +static void reset_shape(tangram_shape * ts) +{ + GLfloat r = random() % 10; + GLfloat f = r / 10; + ts->crd.z = BOTTOM; + ts->dz = INIT_DZ + f; + ts->ddz = -SPEED; +} + +static void bounce(tangram_shape * ts) +{ + ts->crd.z *= -1; /* ignore this */ + ts->dz += ts->ddz; + ts->crd.z += ts->dz * SPEED; + if (ts->crd.z < BOTTOM) { + reset_shape(ts); + } + + ts->crd.z *= -1; /* ignore this */ +} + +static void draw_tangram_shape(tangram_shape ts) +{ + glPushMatrix(); + + if (!do_rotate) { + ts.up = True; + } + + glTranslatef(ts.crd.x, ts.crd.y, ts.up ? ts.crd.z : -ts.crd.z); + glRotated(90, 1, 0, 0); + glRotated(ts.fr, 1, 0, 0); + glRotated(ts.r, 0, 1, 0); + glCallList(ts.dl); + glPopMatrix(); +} + +static void load_fonts(ModeInfo * mi) +{ + tangram_configuration *tp = &tps[MI_SCREEN(mi)]; +# ifdef HAVE_GLBITMAP + load_font(mi->dpy, "titleFont", &tp->xfont1, &tp->font1_dlist); + load_font(mi->dpy, "titleFont2", &tp->xfont2, &tp->font2_dlist); + load_font(mi->dpy, "titleFont3", &tp->xfont3, &tp->font3_dlist); +# else /* !HAVE_GLBITMAP */ + tp->font1_data = load_texture_font (mi->dpy, "titleFont"); + tp->font2_data = load_texture_font (mi->dpy, "titleFont2"); + tp->font3_data = load_texture_font (mi->dpy, "titleFont3"); +# endif /* !HAVE_GLBITMAP */ +} + +static void draw_shapes(ModeInfo * mi) +{ + tangram_configuration *tp = &tps[MI_SCREEN(mi)]; + + draw_tangram_shape(tp->tsm1); + + draw_tangram_shape(tp->tsm2); + draw_tangram_shape(tp->tm); + draw_tangram_shape(tp->tlg1); + draw_tangram_shape(tp->tlg2); + draw_tangram_shape(tp->sq); + draw_tangram_shape(tp->rh); + if (do_labels) glCallList(tp->name_list); +} + +static void set_perspective(void) +{ + glPushMatrix(); + glMatrixMode(GL_PROJECTION); + glLoadIdentity(); + gluPerspective(60, -1, 0.1, 50); + gluLookAt(0, 5, -5, 0, 0, 0, 0, -1, 0); + glMatrixMode(GL_MODELVIEW); + glPopMatrix(); + +} + +ENTRYPOINT void reshape_tangram(ModeInfo * mi, int w, int h) +{ + glViewport(0, 0, w, h); + set_perspective(); + glLoadIdentity(); +} + +static void set_camera(tangram_configuration *tp) +{ + glPushMatrix(); + glMatrixMode(GL_PROJECTION); + glLoadIdentity(); + gluPerspective(60, -1, 0.1, 50); + + + gluLookAt(0, 5, -5, 0, 0, 0, 0, -1, 0); + + if (do_rotate) { + glRotatef(tp->theta[0], 1, 0, 0); + glRotatef(tp->theta[1], 0, 1, 0); + glRotatef(tp->theta[2], 0, 0, 1); + } + + glMatrixMode(GL_MODELVIEW); + glPopMatrix(); + + + if (tp->going_down[0] && tp->theta[0] < 0) { + + tp->going_down[0] = False; + } else if ((!tp->going_down[0]) && tp->theta[0] > 90) { + + tp->going_down[0] = True; + } + + if (tp->theta[1] > 360.0) + tp->theta[1] -= 360.0; + + if (tp->theta[2] > 360.0) + tp->theta[2] -= 360.0; + + if (tp->going_down[0]) + tp->theta[0] -= x_camera_rotate; + else + tp->theta[0] += x_camera_rotate; + + tp->theta[1] += y_camera_rotate; + tp->theta[2] += z_camera_rotate; +} + +static void init_shapes(ModeInfo * mi) +{ + int wire = MI_IS_WIREFRAME(mi); + tangram_configuration *tp = &tps[MI_SCREEN(mi)]; + get_solved_puzzle(mi, &tp->tsm1, &tp->tsm2, &tp->tm, &tp->tlg1, + &tp->tlg2, &tp->sq, &tp->rh); + get_solved_puzzle(mi, &tp->n_tsm1, &tp->n_tsm2, &tp->n_tm, &tp->n_tlg1, + &tp->n_tlg2, &tp->n_sq, &tp->n_rh); + tp->tsm1.dl = tangram_get_sm_tri_dl(wire); + tp->tsm2.dl = tangram_get_sm_tri_dl(wire); + tp->tm.dl = tangram_get_md_tri_dl(wire); + tp->tlg1.dl = tangram_get_lg_tri_dl(wire); + tp->tlg2.dl = tangram_get_lg_tri_dl(wire); + tp->sq.dl = tangram_get_square_dl(wire); + tp->rh.dl = tangram_get_rhomboid_dl(wire); +} + +static void gl_init(ModeInfo * mi) +{ + + int wire = MI_IS_WIREFRAME(mi); + + GLfloat y = do_rotate ? -10 : 3; + GLfloat x = do_rotate ? 5 : 10; + GLfloat pos[4] = { 0, 0, -5, 1.00 }; + GLfloat pos2[4] = { 0, 0, 5, 1.00 }; + GLfloat dif2[4] = { 1, 1, 1, 1 }; + + pos[0] = -x; + pos[1] = y; + + pos2[1] = x; + pos2[1] = y; + + if (!wire) { + glEnable(GL_LIGHTING); + glLightfv(GL_LIGHT0, GL_POSITION, pos); + glEnable(GL_LIGHT0); + if (do_rotate) { + glLightfv(GL_LIGHT1, GL_POSITION, pos2); + glLightfv(GL_LIGHT1, GL_DIFFUSE, dif2); + glEnable(GL_LIGHT1); + } + glEnable(GL_DEPTH_TEST); + } + +} + +ENTRYPOINT void init_tangram(ModeInfo * mi) +{ + tangram_configuration *tp; + + if (!tps) { + tps = (tangram_configuration *) + calloc(MI_NUM_SCREENS(mi), sizeof(tangram_configuration)); + if (!tps) { + fprintf(stderr, "%s: out of memory\n", progname); + exit(1); + } + } + + tp = &tps[MI_SCREEN(mi)]; + + if ((tp->glx_context = init_GL(mi)) != NULL) { + gl_init(mi); + } + + wire = MI_IS_WIREFRAME(mi); + + tp->name_list = glGenLists(1); + + load_fonts(mi); + init_shapes(mi); + + tp->theta[0] = tp->theta[1] = tp->theta[2] = 1; + +} + +static Bool all_solved(tangram_shape * ls[]) +{ + int i; + Bool b = True; + for (i = 0; i < NUM_SHAPES; i++) { + b = (b && ls[i]->solved); + } + return b; +} + +static void solve(tangram_shape * new_s, tangram_shape * old_s) +{ + Bool moved_x, moved_y, moved_r, moved_fr, z_ok; + + old_s->fr = approach_number(new_s->fr, old_s->fr, 2); + moved_fr = (old_s->fr != new_s->fr); + + old_s->r = approach_number(new_s->r, old_s->r, 2); + moved_r = (old_s->r != new_s->r); + + old_s->crd.x = + approach_float(new_s->crd.x, old_s->crd.x, &moved_x, 0.1); + if (!moved_x) + old_s->crd.x = new_s->crd.x; + + old_s->crd.y = + approach_float(new_s->crd.y, old_s->crd.y, &moved_y, 0.1); + if (!moved_y) + old_s->crd.y = new_s->crd.y; + + z_ok = (-old_s->crd.z <= BOTTOM); + + old_s->solved = (moved_x == False && moved_y == False && + moved_r == False && moved_fr == False && + z_ok == True); +} + +static void set_not_solved(tangram_shape * ls[]) +{ + int i; + for (i = 0; i < NUM_SHAPES; i++) + ls[i]->solved = False; +} + + +ENTRYPOINT void draw_tangram(ModeInfo * mi) +{ + Display *dpy = MI_DISPLAY(mi); + Window window = MI_WINDOW(mi); + tangram_configuration *tp = &tps[MI_SCREEN(mi)]; + + tangram_shape *ls[NUM_SHAPES]; + tangram_shape *nls[NUM_SHAPES]; + + + int i; + int MAX_DISPLAY; + + GLfloat color[4] = { 0.0, 0.0, 0.0, 1.0 }; + GLfloat white[4] = { 1.0, 1.0, 1.0, 1.0 }; + MAX_DISPLAY = viewing_time * 100; + + if (! tp->glx_context) + return; + glXMakeCurrent(MI_DISPLAY(mi), MI_WINDOW(mi), *(tp->glx_context)); + + ls[small_triangle1] = &tp->tsm1; + ls[small_triangle2] = &tp->tsm2; + ls[medium_triangle] = &tp->tm; + ls[large_triangle1] = &tp->tlg1; + ls[large_triangle2] = &tp->tlg2; + ls[square] = &tp->sq; + ls[rhomboid] = &tp->rh; + + nls[small_triangle1] = &tp->n_tsm1; + nls[small_triangle2] = &tp->n_tsm2; + nls[medium_triangle] = &tp->n_tm; + nls[large_triangle1] = &tp->n_tlg1; + nls[large_triangle2] = &tp->n_tlg2; + nls[square] = &tp->n_sq; + nls[rhomboid] = &tp->n_rh; + + set_camera(tp); + + if (tp->display_counter <= 0) { + for (i = 0; i < NUM_SHAPES; i++) { + if (ls[i]->solved) { + if (all_solved(ls)) { + tp->display_counter = MAX_DISPLAY; + tp->pn = tp->puzzle_name; + get_solved_puzzle(mi, nls[small_triangle1], + nls[small_triangle2], + nls[medium_triangle], + nls[large_triangle1], + nls[large_triangle2], nls[square], + nls[rhomboid]); + tp->ncolors = 128; + tp->colors = + (XColor *) calloc(tp->ncolors, sizeof(XColor)); + + make_random_colormap(0, 0, 0, + tp->colors, &tp->ncolors, + True, False, 0, False); + + + color[0] = tp->colors[0].red / 65536.0; + color[1] = tp->colors[1].green / 65536.0; + color[2] = tp->colors[2].blue / 65536.0; + + + glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, + color); + + set_not_solved(ls); + break; + } + } else { + tp->pn = ""; + bounce(ls[i]); + solve(nls[i], ls[i]); + } + } + } else { + tp->display_counter--; + } + + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + glPushMatrix(); + + glLoadIdentity(); + if (do_labels) + { +# ifdef HAVE_GLBITMAP + XFontStruct *f; + GLuint fl; +# else /* !HAVE_GLBITMAP */ + texture_font_data *f; +# endif /* !HAVE_GLBITMAP */ + if (MI_WIDTH(mi) >= 500 && MI_HEIGHT(mi) >= 375) +# ifdef HAVE_GLBITMAP + f = tp->xfont1, fl = tp->font1_dlist; +# else /* !HAVE_GLBITMAP */ + f = tp->font1_data; +# endif /* !HAVE_GLBITMAP */ + else if (MI_WIDTH(mi) >= 350 && MI_HEIGHT(mi) >= 260) +# ifdef HAVE_GLBITMAP + f = tp->xfont2, fl = tp->font2_dlist; +# else /* !HAVE_GLBITMAP */ + f = tp->font2_data; +# endif /* !HAVE_GLBITMAP */ + else +# ifdef HAVE_GLBITMAP + f = tp->xfont3, fl = tp->font3_dlist; +# else /* !HAVE_GLBITMAP */ + f = tp->font3_data; +# endif /* !HAVE_GLBITMAP */ + + glNewList(tp->name_list, GL_COMPILE); + glColor3f(0.8, 0.8, 0); + print_gl_string(mi->dpy, f, +# ifdef HAVE_GLBITMAP + fl, +# endif /* !HAVE_GLBITMAP */ + mi->xgwa.width, mi->xgwa.height, + 10, mi->xgwa.height - 10, tp->pn, False); + glEndList(); + } + + glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, white); + glMateriali(GL_FRONT_AND_BACK, GL_SHININESS, 128); + + draw_shapes(mi); + + if (mi->fps_p) do_fps (mi); + + glFlush(); + glPopMatrix(); + glXSwapBuffers(dpy, window); +} + +XSCREENSAVER_MODULE ("Tangram", tangram) + +#endif /* USE_GL */ diff --git a/hacks/glx/tangram.man b/hacks/glx/tangram.man new file mode 100644 index 00000000..c5d39809 --- /dev/null +++ b/hacks/glx/tangram.man @@ -0,0 +1,67 @@ +.TH XScreenSaver 1 "" "X Version 11" +.SH NAME +tangram - watch the computer solve tangram puzzles. +.SH SYNOPSIS +.B tangram +[\-display \fIhost:display.screen\fP] +[\-visual \fIvisual\fP] +[\-window] +[\-root] +[\-delay \fInumber\fP] +[\-wireframe] +[\-viewing_time \fInumber\fP] +[\-rotate] +[\-fps] +.SH DESCRIPTION +The \fItangram\fP program uses a few basic shapes to build silhouettes of recognizable objects. +.SH OPTIONS +.I tangram +accepts the following 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: 10000 (0.01 seconds.). +.TP 8 +.B \-wireframe | \-no-wireframe +Render in wireframe instead of solid. +.TP 8 +.B \-viewing_time \fInumber\fP +Specify the length of time, in seconds, that the finished puzzle +should be displayed. Default: 5 +.TP 8 +.B \-rotate | \-no-rotate +Rotate the camera around the puzzle. +.TP 8 +.B \-fps +Display the current frame rate, CPU load, and polygon count. +.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 2005 by Jeremy English. 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 +Jeremy English diff --git a/hacks/glx/tangram_shapes.c b/hacks/glx/tangram_shapes.c new file mode 100644 index 00000000..19f065b0 --- /dev/null +++ b/hacks/glx/tangram_shapes.c @@ -0,0 +1,236 @@ +/* tangram, Copyright (c) 2005 Jeremy English + * + * 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. + */ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif /* HAVE_CONFIG_H */ + +#ifndef HAVE_COCOA +# include +#endif + +#ifdef HAVE_JWZGLES +# include "jwzgles.h" +#endif /* HAVE_JWZGLES */ + +#include "tangram_shapes.h" + +#define small_scale ( 1 ) +#define large_scale ( 2 ) +#define medium_scale ( 1.414213562 ) + +#define alpha (0.05) + +static void +tri_45_90(int wire) +{ + GLfloat vertices[][3] = { + {0, alpha, 0}, + {0, alpha, 1}, + {1, alpha, 0}, + {0, -alpha, 0}, + {0, -alpha, 1}, + {1, -alpha, 0} + }; + + glBegin((wire) ? GL_LINE_LOOP : GL_TRIANGLES); + + glNormal3f(0, 1, 0); + glVertex3fv(vertices[0]); + glNormal3f(0, 1, 0); + glVertex3fv(vertices[2]); + glNormal3f(0, 1, 0); + glVertex3fv(vertices[1]); + + glNormal3f(0, -1, 0); + glVertex3fv(vertices[3]); + glNormal3f(0, -1, 0); + glVertex3fv(vertices[4]); + glNormal3f(0, -1, 0); + glVertex3fv(vertices[5]); + glEnd(); + + glBegin((wire) ? GL_LINE_LOOP : GL_QUADS); + glNormal3f(1, 0, 1); + glVertex3fv(vertices[2]); + glNormal3f(1, 0, 1); + glVertex3fv(vertices[5]); + glNormal3f(1, 0, 1); + glVertex3fv(vertices[4]); + glNormal3f(1, 0, 1); + glVertex3fv(vertices[1]); + + glNormal3f(-1, 0, 0); + glVertex3fv(vertices[0]); + glNormal3f(-1, 0, 0); + glVertex3fv(vertices[1]); + glNormal3f(-1, 0, 0); + glVertex3fv(vertices[4]); + glNormal3f(-1, 0, 0); + glVertex3fv(vertices[3]); + + glNormal3f(0, 0, -1); + glVertex3fv(vertices[0]); + glNormal3f(0, 0, -1); + glVertex3fv(vertices[3]); + glNormal3f(0, 0, -1); + glVertex3fv(vertices[5]); + glNormal3f(0, 0, -1); + glVertex3fv(vertices[2]); + glEnd(); +} + +static void +unit_cube(int wire) +{ + glBegin((wire) ? GL_LINE_LOOP : GL_QUADS); + + + glNormal3f(0.0f, 1.0f, 0.0f); + glVertex3f(0.0f, alpha, 0.0f); + glVertex3f(0.0f, alpha, 1.0f); + glVertex3f(1.0f, alpha, 1.0f); + glVertex3f(1.0f, alpha, 0.0f); + + glNormal3f(0.0f, 0.0f, 1.0f); + glVertex3f(0.0f, -alpha, 1.0f); + glVertex3f(1.0f, -alpha, 1.0f); + glVertex3f(1.0f, alpha, 1.0f); + glVertex3f(0.0f, alpha, 1.0f); + + glNormal3f(0.0f, 0.0f, -1.0f); + glVertex3f(0.0f, -alpha, 0.0f); + glVertex3f(0.0f, alpha, 0.0f); + glVertex3f(1.0f, alpha, 0.0f); + glVertex3f(1.0f, -alpha, 0.0f); + + glNormal3f(1.0f, 0.0f, 0.0f); + glVertex3f(1.0f, -alpha, 0.0f); + glVertex3f(1.0f, alpha, 0.0f); + glVertex3f(1.0f, alpha, 1.0f); + glVertex3f(1.0f, -alpha, 1.0f); + + glNormal3f(-1.0f, 0.0f, 0.0f); + glVertex3f(0.0f, -alpha, 0.0f); + glVertex3f(0.0f, -alpha, 1.0f); + glVertex3f(0.0f, alpha, 1.0f); + glVertex3f(0.0f, alpha, 0.0f); + + glNormal3f(0.0f, -1.0f, 0.0f); + glVertex3f(0.0f, -alpha, 0.0f); + glVertex3f(1.0f, -alpha, 0.0f); + glVertex3f(1.0f, -alpha, 1.0f); + glVertex3f(0.0f, -alpha, 1.0f); + + glEnd(); +} + +static void +unit_rhomboid(int wire) +{ + glBegin((wire) ? GL_LINE_LOOP : GL_QUADS); + + glNormal3f(0.0f, 1.0f, 0.0f); + glVertex3f(0, alpha, 0); + glVertex3f(1, alpha, 1); + glVertex3f(1, alpha, 2); + glVertex3f(0, alpha, 1); + + glNormal3f(0.0f, -1.0f, 0.0f); + glVertex3f(0, -alpha, 0); + glVertex3f(0, -alpha, 1); + glVertex3f(1, -alpha, 2); + glVertex3f(1, -alpha, 1); + + glNormal3f(-1.0f, 0.0f, 0.0f); + glVertex3f(0, alpha, 0); + glVertex3f(0, alpha, 1); + glVertex3f(0, -alpha, 1); + glVertex3f(0, -alpha, 0); + + + glNormal3f(0.0f, 0.0f, 1.0f); + glVertex3f(0, alpha, 1); + glVertex3f(1, alpha, 2); + glVertex3f(1, -alpha, 2); + glVertex3f(0, -alpha, 1); + + glNormal3f(1.0f, 0.0f, 0.0f); + glVertex3f(1, alpha, 1); + glVertex3f(1, -alpha, 1); + glVertex3f(1, -alpha, 2); + glVertex3f(1, alpha, 2); + + glNormal3f(0.0f, 0.0f, 1.0f); + glVertex3f(0, alpha, 0); + glVertex3f(0, -alpha, 0); + glVertex3f(1, -alpha, 1); + glVertex3f(1, alpha, 1); + + glEnd(); +} + +/* All of the pieces have the same thickness so all of the Y values are the same */ + +GLuint +tangram_get_sm_tri_dl(int wire) +{ + GLuint triangle = glGenLists(1); + glNewList(triangle, GL_COMPILE); + glScalef(small_scale, small_scale, small_scale); + tri_45_90(wire); + glEndList(); + return triangle; +} + +GLuint +tangram_get_lg_tri_dl(int wire) +{ + GLuint triangle = glGenLists(1); + glNewList(triangle, GL_COMPILE); + glScalef(large_scale, small_scale, large_scale); + tri_45_90(wire); + glEndList(); + return triangle; +} + +GLuint +tangram_get_md_tri_dl(int wire) +{ + GLuint triangle = glGenLists(1); + glNewList(triangle, GL_COMPILE); + glScalef(medium_scale, small_scale, medium_scale); + tri_45_90(wire); + glEndList(); + return triangle; +} + +GLuint +tangram_get_square_dl(int wire) +{ + GLuint square = glGenLists(1); + glNewList(square, GL_COMPILE); + glScalef(small_scale, small_scale, small_scale); + unit_cube(wire); + glEndList(); + return square; +} + +GLuint +tangram_get_rhomboid_dl(int wire) +{ + GLuint rhomboid = glGenLists(1); + glNewList(rhomboid, GL_COMPILE); + glScalef(small_scale, small_scale, small_scale); + unit_rhomboid(wire); + glEndList(); + return rhomboid; +} diff --git a/hacks/glx/tangram_shapes.h b/hacks/glx/tangram_shapes.h new file mode 100644 index 00000000..254f8f34 --- /dev/null +++ b/hacks/glx/tangram_shapes.h @@ -0,0 +1,15 @@ +#ifndef TANGRAM_SHAPES_H +#define TANGRAM_SHAPES_H + +/* get_sm_tri_dl - Get small triangle Display List */ +GLuint tangram_get_sm_tri_dl(int wire); +/* get_lg_tri_dl - Get large triangle Display List */ +GLuint tangram_get_lg_tri_dl(int wire); +/* get_md_tri_dl - Get medium triangle Display List */ +GLuint tangram_get_md_tri_dl(int wire); +/* get_square_dl - Get square Display List */ +GLuint tangram_get_square_dl(int wire); +/* get_rhomboid_dl - Get rhomboid Display List */ +GLuint tangram_get_rhomboid_dl(int wire); + +#endif diff --git a/hacks/glx/teapot.c b/hacks/glx/teapot.c new file mode 100644 index 00000000..05d652ed --- /dev/null +++ b/hacks/glx/teapot.c @@ -0,0 +1,282 @@ + +/* Copyright (c) Mark J. Kilgard, 1994. */ + +/** +(c) Copyright 1993, Silicon Graphics, Inc. + +ALL RIGHTS RESERVED + +Permission to use, copy, modify, and distribute this software +for any purpose and without fee is hereby granted, provided +that the above copyright notice appear in all copies and that +both the copyright notice and this permission notice appear in +supporting documentation, and that the name of Silicon +Graphics, Inc. not be used in advertising or publicity +pertaining to distribution of the software without specific, +written prior permission. + +THE MATERIAL EMBODIED ON THIS SOFTWARE IS PROVIDED TO YOU +"AS-IS" AND WITHOUT WARRANTY OF ANY KIND, EXPRESS, IMPLIED OR +OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY WARRANTY OF +MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. IN NO +EVENT SHALL SILICON GRAPHICS, INC. BE LIABLE TO YOU OR ANYONE +ELSE FOR ANY DIRECT, SPECIAL, INCIDENTAL, INDIRECT OR +CONSEQUENTIAL DAMAGES OF ANY KIND, OR ANY DAMAGES WHATSOEVER, +INCLUDING WITHOUT LIMITATION, LOSS OF PROFIT, LOSS OF USE, +SAVINGS OR REVENUE, OR THE CLAIMS OF THIRD PARTIES, WHETHER OR +NOT SILICON GRAPHICS, INC. HAS BEEN ADVISED OF THE POSSIBILITY +OF SUCH LOSS, HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +ARISING OUT OF OR IN CONNECTION WITH THE POSSESSION, USE OR +PERFORMANCE OF THIS SOFTWARE. + +US Government Users Restricted Rights + +Use, duplication, or disclosure by the Government is subject to +restrictions set forth in FAR 52.227.19(c)(2) or subparagraph +(c)(1)(ii) of the Rights in Technical Data and Computer +Software clause at DFARS 252.227-7013 and/or in similar or +successor clauses in the FAR or the DOD or NASA FAR +Supplement. Unpublished-- rights reserved under the copyright +laws of the United States. Contractor/manufacturer is Silicon +Graphics, Inc., 2011 N. Shoreline Blvd., Mountain View, CA +94039-7311. + +OpenGL(TM) is a trademark of Silicon Graphics, Inc. +*/ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include "teapot.h" + +#ifndef HAVE_COCOA +# include +#endif + +#ifdef HAVE_JWZGLES +# include "jwzgles.h" +#else +# define HAVE_GLMAP +#endif + + +#ifdef HAVE_GLMAP + +/* Rim, body, lid, and bottom data must be reflected in x + and y; handle and spout data across the y axis only. */ + +static long patchdata[][16] = +{ + /* rim */ + {102, 103, 104, 105, 4, 5, 6, 7, 8, 9, 10, 11, + 12, 13, 14, 15}, + /* body */ + {12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, + 24, 25, 26, 27}, + {24, 25, 26, 27, 29, 30, 31, 32, 33, 34, 35, 36, + 37, 38, 39, 40}, + /* lid */ + {96, 96, 96, 96, 97, 98, 99, 100, 101, 101, 101, + 101, 0, 1, 2, 3,}, + {0, 1, 2, 3, 106, 107, 108, 109, 110, 111, 112, + 113, 114, 115, 116, 117}, + /* bottom */ + {118, 118, 118, 118, 124, 122, 119, 121, 123, 126, + 125, 120, 40, 39, 38, 37}, + /* handle */ + {41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, + 53, 54, 55, 56}, + {53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, + 28, 65, 66, 67}, + /* spout */ + {68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, + 80, 81, 82, 83}, + {80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, + 92, 93, 94, 95} +}; +/* *INDENT-OFF* */ + +static float cpdata[][3] = +{ + {0.2, 0, 2.7}, {0.2, -0.112, 2.7}, {0.112, -0.2, 2.7}, {0, + -0.2, 2.7}, {1.3375, 0, 2.53125}, {1.3375, -0.749, 2.53125}, + {0.749, -1.3375, 2.53125}, {0, -1.3375, 2.53125}, {1.4375, + 0, 2.53125}, {1.4375, -0.805, 2.53125}, {0.805, -1.4375, + 2.53125}, {0, -1.4375, 2.53125}, {1.5, 0, 2.4}, {1.5, -0.84, + 2.4}, {0.84, -1.5, 2.4}, {0, -1.5, 2.4}, {1.75, 0, 1.875}, + {1.75, -0.98, 1.875}, {0.98, -1.75, 1.875}, {0, -1.75, + 1.875}, {2, 0, 1.35}, {2, -1.12, 1.35}, {1.12, -2, 1.35}, + {0, -2, 1.35}, {2, 0, 0.9}, {2, -1.12, 0.9}, {1.12, -2, + 0.9}, {0, -2, 0.9}, {-2, 0, 0.9}, {2, 0, 0.45}, {2, -1.12, + 0.45}, {1.12, -2, 0.45}, {0, -2, 0.45}, {1.5, 0, 0.225}, + {1.5, -0.84, 0.225}, {0.84, -1.5, 0.225}, {0, -1.5, 0.225}, + {1.5, 0, 0.15}, {1.5, -0.84, 0.15}, {0.84, -1.5, 0.15}, {0, + -1.5, 0.15}, {-1.6, 0, 2.025}, {-1.6, -0.3, 2.025}, {-1.5, + -0.3, 2.25}, {-1.5, 0, 2.25}, {-2.3, 0, 2.025}, {-2.3, -0.3, + 2.025}, {-2.5, -0.3, 2.25}, {-2.5, 0, 2.25}, {-2.7, 0, + 2.025}, {-2.7, -0.3, 2.025}, {-3, -0.3, 2.25}, {-3, 0, + 2.25}, {-2.7, 0, 1.8}, {-2.7, -0.3, 1.8}, {-3, -0.3, 1.8}, + {-3, 0, 1.8}, {-2.7, 0, 1.575}, {-2.7, -0.3, 1.575}, {-3, + -0.3, 1.35}, {-3, 0, 1.35}, {-2.5, 0, 1.125}, {-2.5, -0.3, + 1.125}, {-2.65, -0.3, 0.9375}, {-2.65, 0, 0.9375}, {-2, + -0.3, 0.9}, {-1.9, -0.3, 0.6}, {-1.9, 0, 0.6}, {1.7, 0, + 1.425}, {1.7, -0.66, 1.425}, {1.7, -0.66, 0.6}, {1.7, 0, + 0.6}, {2.6, 0, 1.425}, {2.6, -0.66, 1.425}, {3.1, -0.66, + 0.825}, {3.1, 0, 0.825}, {2.3, 0, 2.1}, {2.3, -0.25, 2.1}, + {2.4, -0.25, 2.025}, {2.4, 0, 2.025}, {2.7, 0, 2.4}, {2.7, + -0.25, 2.4}, {3.3, -0.25, 2.4}, {3.3, 0, 2.4}, {2.8, 0, + 2.475}, {2.8, -0.25, 2.475}, {3.525, -0.25, 2.49375}, + {3.525, 0, 2.49375}, {2.9, 0, 2.475}, {2.9, -0.15, 2.475}, + {3.45, -0.15, 2.5125}, {3.45, 0, 2.5125}, {2.8, 0, 2.4}, + {2.8, -0.15, 2.4}, {3.2, -0.15, 2.4}, {3.2, 0, 2.4}, {0, 0, + 3.15}, {0.8, 0, 3.15}, {0.8, -0.45, 3.15}, {0.45, -0.8, + 3.15}, {0, -0.8, 3.15}, {0, 0, 2.85}, {1.4, 0, 2.4}, {1.4, + -0.784, 2.4}, {0.784, -1.4, 2.4}, {0, -1.4, 2.4}, {0.4, 0, + 2.55}, {0.4, -0.224, 2.55}, {0.224, -0.4, 2.55}, {0, -0.4, + 2.55}, {1.3, 0, 2.55}, {1.3, -0.728, 2.55}, {0.728, -1.3, + 2.55}, {0, -1.3, 2.55}, {1.3, 0, 2.4}, {1.3, -0.728, 2.4}, + {0.728, -1.3, 2.4}, {0, -1.3, 2.4}, {0, 0, 0}, {1.425, + -0.798, 0}, {1.5, 0, 0.075}, {1.425, 0, 0}, {0.798, -1.425, + 0}, {0, -1.5, 0.075}, {0, -1.425, 0}, {1.5, -0.84, 0.075}, + {0.84, -1.5, 0.075} +}; + +static float tex[2][2][2] = +{ + { {0, 0}, + {1, 0}}, + { {0, 1}, + {1, 1}} +}; + + +int +unit_teapot (int grid, int wire_p) +{ + GLenum type = wire_p ? GL_LINE : GL_FILL; + float p[4][4][3], q[4][4][3], r[4][4][3], s[4][4][3]; + long i, j, k, l; + int polys = 0; + + glPushAttrib(GL_ENABLE_BIT | GL_EVAL_BIT); + glEnable(GL_AUTO_NORMAL); + glEnable(GL_NORMALIZE); + glEnable(GL_MAP2_VERTEX_3); + glEnable(GL_MAP2_TEXTURE_COORD_2); + glFrontFace (GL_CW); + glPushMatrix(); + glRotatef(270.0, 1.0, 0.0, 0.0); + glScalef(0.5, 0.5, 0.5); + glTranslatef(0.0, 0.0, -1.5); + for (i = 0; i < 10; i++) { + for (j = 0; j < 4; j++) { + for (k = 0; k < 4; k++) { + for (l = 0; l < 3; l++) { + p[j][k][l] = cpdata[patchdata[i][j * 4 + k]][l]; + q[j][k][l] = cpdata[patchdata[i][j * 4 + (3 - k)]][l]; + if (l == 1) + q[j][k][l] *= -1.0; + if (i < 6) { + r[j][k][l] = + cpdata[patchdata[i][j * 4 + (3 - k)]][l]; + if (l == 0) + r[j][k][l] *= -1.0; + s[j][k][l] = cpdata[patchdata[i][j * 4 + k]][l]; + if (l == 0) + s[j][k][l] *= -1.0; + if (l == 1) + s[j][k][l] *= -1.0; + } + } + } + } + glMap2f(GL_MAP2_TEXTURE_COORD_2, 0, 1, 2, 2, 0, 1, 4, 2, + &tex[0][0][0]); + glMap2f(GL_MAP2_VERTEX_3, 0, 1, 3, 4, 0, 1, 12, 4, + &p[0][0][0]); + glMapGrid2f(grid, 0.0, 1.0, grid, 0.0, 1.0); + glEvalMesh2(type, 0, grid, 0, grid); + polys += grid*grid*2; + glMap2f(GL_MAP2_VERTEX_3, 0, 1, 3, 4, 0, 1, 12, 4, + &q[0][0][0]); + glEvalMesh2(type, 0, grid, 0, grid); + polys += grid*grid*2; + if (i < 6) { + glMap2f(GL_MAP2_VERTEX_3, 0, 1, 3, 4, 0, 1, 12, 4, + &r[0][0][0]); + glEvalMesh2(type, 0, grid, 0, grid); + polys += grid*grid*2; + glMap2f(GL_MAP2_VERTEX_3, 0, 1, 3, 4, 0, 1, 12, 4, + &s[0][0][0]); + glEvalMesh2(type, 0, grid, 0, grid); + polys += grid*grid*2; + } + } + glPopMatrix(); + glPopAttrib(); + + return polys; +} + +#else /* !HAVE_GLMAP */ + +# include "normals.h" +# include "teapot2.h" + +int +unit_teapot (int grid, int wire_p) +{ + int polys = sizeof (teapot_triangles) / sizeof (*teapot_triangles) / 9; + int i; + const GLfloat *p = teapot_triangles; + GLfloat scale = 1 / 2.3; + + glPushMatrix(); + glScalef (scale, scale, scale); + glTranslatef (0, -1.25, 0); + + if (wire_p) + { + glBegin (GL_LINES); + for (i = 0; i < polys; i++) + { + XYZ p1, p2, p3; + p1.x = *p++; p1.y = *p++; p1.z = *p++; + p2.x = *p++; p2.y = *p++; p2.z = *p++; + p3.x = *p++; p3.y = *p++; p3.z = *p++; + glVertex3f (p1.x, p1.y, p1.z); /* Draw 2 edges of each triangle */ + glVertex3f (p2.x, p2.y, p2.z); + glVertex3f (p1.x, p1.y, p1.z); + glVertex3f (p3.x, p3.y, p3.z); + i++; /* Skip every other triangle */ + p += 9; + } + glEnd(); + polys /= 2; + } + else + { + glFrontFace (GL_CCW); + glBegin (GL_TRIANGLES); + for (i = 0; i < polys; i++) + { + XYZ p1, p2, p3; + p1.x = *p++; p1.y = *p++; p1.z = *p++; + p2.x = *p++; p2.y = *p++; p2.z = *p++; + p3.x = *p++; p3.y = *p++; p3.z = *p++; + do_normal (p1.x, p1.y, p1.z, + p2.x, p2.y, p2.z, + p3.x, p3.y, p3.z); + glVertex3f (p1.x, p1.y, p1.z); + glVertex3f (p2.x, p2.y, p2.z); + glVertex3f (p3.x, p3.y, p3.z); + } + glEnd(); + } + glPopMatrix(); + + return polys; +} + +#endif /* !HAVE_GLMAP */ diff --git a/hacks/glx/teapot.h b/hacks/glx/teapot.h new file mode 100644 index 00000000..60b5fe52 --- /dev/null +++ b/hacks/glx/teapot.h @@ -0,0 +1,7 @@ + +#ifndef __TEAPOT_H__ +#define __TEAPOT_H__ + +extern int unit_teapot (int density, int wire_p); + +#endif /* __TEAPOT_H__ */ diff --git a/hacks/glx/teapot2.h b/hacks/glx/teapot2.h new file mode 100644 index 00000000..c9d4def0 --- /dev/null +++ b/hacks/glx/teapot2.h @@ -0,0 +1,6330 @@ +/* The Utah Teapot. Martin Newell, 1975. + + Since GLUtesselator doesn't exist in the iOS build, we use these + triangles there instead of generating the teapot from Newell's + original Bezier patches, because I didn't feel like re-implementing + that code. + */ + +static const GLfloat teapot_triangles[] = { + 1.368074,2.435437,-0.227403, 1.381968,2.4,-0.229712, 1.4,2.4,0, + 1.4,2.4,0, 1.385925,2.435437,0, 1.368074,2.435437,-0.227403, + 1.316296,2.435437,-0.442166, 1.329664,2.4,-0.446656, 1.381968,2.4,-0.229712, + 1.381968,2.4,-0.229712, 1.368074,2.435437,-0.227403, 1.316296,2.435437,-0.442166, + 1.233252,2.435437,-0.641628, 1.245776,2.4,-0.648144, 1.329664,2.4,-0.446656, + 1.329664,2.4,-0.446656, 1.316296,2.435437,-0.442166, 1.233252,2.435437,-0.641628, + 1.121601,2.435437,-0.823129, 1.132992,2.4,-0.831488, 1.245776,2.4,-0.648144, + 1.245776,2.4,-0.648144, 1.233252,2.435437,-0.641628, 1.121601,2.435437,-0.823129, + 0.984007,2.435437,-0.984007, 0.994,2.4,-0.994, 1.132992,2.4,-0.831488, + 1.132992,2.4,-0.831488, 1.121601,2.435437,-0.823129, 0.984007,2.435437,-0.984007, + 0.823129,2.435437,-1.121601, 0.831488,2.4,-1.132992, 0.994,2.4,-0.994, + 0.994,2.4,-0.994, 0.984007,2.435437,-0.984007, 0.823129,2.435437,-1.121601, + 0.641628,2.435437,-1.233252, 0.648144,2.4,-1.245776, 0.831488,2.4,-1.132992, + 0.831488,2.4,-1.132992, 0.823129,2.435437,-1.121601, 0.641628,2.435437,-1.233252, + 0.442166,2.435437,-1.316296, 0.446656,2.4,-1.329664, 0.648144,2.4,-1.245776, + 0.648144,2.4,-1.245776, 0.641628,2.435437,-1.233252, 0.442166,2.435437,-1.316296, + 0.227403,2.435437,-1.368074, 0.229712,2.4,-1.381968, 0.446656,2.4,-1.329664, + 0.446656,2.4,-1.329664, 0.442166,2.435437,-1.316296, 0.227403,2.435437,-1.368074, + 0,2.435437,-1.385925, 0,2.4,-1.4, 0.229712,2.4,-1.381968, + 0.229712,2.4,-1.381968, 0.227403,2.435437,-1.368074, 0,2.435437,-1.385925, + 1.36262,2.463,-0.226496, 1.368074,2.435437,-0.227403, 1.385925,2.435437,0, + 1.385925,2.435437,0, 1.3804,2.463,0, 1.36262,2.463,-0.226496, + 1.311049,2.463,-0.440403, 1.316296,2.435437,-0.442166, 1.368074,2.435437,-0.227403, + 1.368074,2.435437,-0.227403, 1.36262,2.463,-0.226496, 1.311049,2.463,-0.440403, + 1.228335,2.463,-0.63907, 1.233252,2.435437,-0.641628, 1.316296,2.435437,-0.442166, + 1.316296,2.435437,-0.442166, 1.311049,2.463,-0.440403, 1.228335,2.463,-0.63907, + 1.11713,2.463,-0.819847, 1.121601,2.435437,-0.823129, 1.233252,2.435437,-0.641628, + 1.233252,2.435437,-0.641628, 1.228335,2.463,-0.63907, 1.11713,2.463,-0.819847, + 0.980084,2.463,-0.980084, 0.984007,2.435437,-0.984007, 1.121601,2.435437,-0.823129, + 1.121601,2.435437,-0.823129, 1.11713,2.463,-0.819847, 0.980084,2.463,-0.980084, + 0.819847,2.463,-1.11713, 0.823129,2.435437,-1.121601, 0.984007,2.435437,-0.984007, + 0.984007,2.435437,-0.984007, 0.980084,2.463,-0.980084, 0.819847,2.463,-1.11713, + 0.63907,2.463,-1.228335, 0.641628,2.435437,-1.233252, 0.823129,2.435437,-1.121601, + 0.823129,2.435437,-1.121601, 0.819847,2.463,-1.11713, 0.63907,2.463,-1.228335, + 0.440403,2.463,-1.311049, 0.442166,2.435437,-1.316296, 0.641628,2.435437,-1.233252, + 0.641628,2.435437,-1.233252, 0.63907,2.463,-1.228335, 0.440403,2.463,-1.311049, + 0.226496,2.463,-1.36262, 0.227403,2.435437,-1.368074, 0.442166,2.435437,-1.316296, + 0.442166,2.435437,-1.316296, 0.440403,2.463,-1.311049, 0.226496,2.463,-1.36262, + 0,2.463,-1.3804, 0,2.435437,-1.385925, 0.227403,2.435437,-1.368074, + 0.227403,2.435437,-1.368074, 0.226496,2.463,-1.36262, 0,2.463,-1.3804, + 1.364422,2.482687,-0.226795, 1.36262,2.463,-0.226496, 1.3804,2.463,0, + 1.3804,2.463,0, 1.382225,2.482687,0, 1.364422,2.482687,-0.226795, + 1.312782,2.482687,-0.440985, 1.311049,2.463,-0.440403, 1.36262,2.463,-0.226496, + 1.36262,2.463,-0.226496, 1.364422,2.482687,-0.226795, 1.312782,2.482687,-0.440985, + 1.229959,2.482687,-0.639915, 1.228335,2.463,-0.63907, 1.311049,2.463,-0.440403, + 1.311049,2.463,-0.440403, 1.312782,2.482687,-0.440985, 1.229959,2.482687,-0.639915, + 1.118607,2.482687,-0.820931, 1.11713,2.463,-0.819847, 1.228335,2.463,-0.63907, + 1.228335,2.463,-0.63907, 1.229959,2.482687,-0.639915, 1.118607,2.482687,-0.820931, + 0.98138,2.482687,-0.98138, 0.980084,2.463,-0.980084, 1.11713,2.463,-0.819847, + 1.11713,2.463,-0.819847, 1.118607,2.482687,-0.820931, 0.98138,2.482687,-0.98138, + 0.820931,2.482687,-1.118607, 0.819847,2.463,-1.11713, 0.980084,2.463,-0.980084, + 0.980084,2.463,-0.980084, 0.98138,2.482687,-0.98138, 0.820931,2.482687,-1.118607, + 0.639915,2.482687,-1.229959, 0.63907,2.463,-1.228335, 0.819847,2.463,-1.11713, + 0.819847,2.463,-1.11713, 0.820931,2.482687,-1.118607, 0.639915,2.482687,-1.229959, + 0.440985,2.482687,-1.312782, 0.440403,2.463,-1.311049, 0.63907,2.463,-1.228335, + 0.63907,2.463,-1.228335, 0.639915,2.482687,-1.229959, 0.440985,2.482687,-1.312782, + 0.226795,2.482687,-1.364422, 0.226496,2.463,-1.36262, 0.440403,2.463,-1.311049, + 0.440403,2.463,-1.311049, 0.440985,2.482687,-1.312782, 0.226795,2.482687,-1.364422, + 0,2.482687,-1.382225, 0,2.463,-1.3804, 0.226496,2.463,-1.36262, + 0.226496,2.463,-1.36262, 0.226795,2.482687,-1.364422, 0,2.482687,-1.382225, + 1.372294,2.4945,-0.228104, 1.364422,2.482687,-0.226795, 1.382225,2.482687,0, + 1.382225,2.482687,0, 1.3902,2.4945,0, 1.372294,2.4945,-0.228104, + 1.320356,2.4945,-0.443529, 1.312782,2.482687,-0.440985, 1.364422,2.482687,-0.226795, + 1.364422,2.482687,-0.226795, 1.372294,2.4945,-0.228104, 1.320356,2.4945,-0.443529, + 1.237056,2.4945,-0.643607, 1.229959,2.482687,-0.639915, 1.312782,2.482687,-0.440985, + 1.312782,2.482687,-0.440985, 1.320356,2.4945,-0.443529, 1.237056,2.4945,-0.643607, + 1.125061,2.4945,-0.825668, 1.118607,2.482687,-0.820931, 1.229959,2.482687,-0.639915, + 1.229959,2.482687,-0.639915, 1.237056,2.4945,-0.643607, 1.125061,2.4945,-0.825668, + 0.987042,2.4945,-0.987042, 0.98138,2.482687,-0.98138, 1.118607,2.482687,-0.820931, + 1.118607,2.482687,-0.820931, 1.125061,2.4945,-0.825668, 0.987042,2.4945,-0.987042, + 0.825668,2.4945,-1.125061, 0.820931,2.482687,-1.118607, 0.98138,2.482687,-0.98138, + 0.98138,2.482687,-0.98138, 0.987042,2.4945,-0.987042, 0.825668,2.4945,-1.125061, + 0.643607,2.4945,-1.237056, 0.639915,2.482687,-1.229959, 0.820931,2.482687,-1.118607, + 0.820931,2.482687,-1.118607, 0.825668,2.4945,-1.125061, 0.643607,2.4945,-1.237056, + 0.443529,2.4945,-1.320356, 0.440985,2.482687,-1.312782, 0.639915,2.482687,-1.229959, + 0.639915,2.482687,-1.229959, 0.643607,2.4945,-1.237056, 0.443529,2.4945,-1.320356, + 0.228104,2.4945,-1.372294, 0.226795,2.482687,-1.364422, 0.440985,2.482687,-1.312782, + 0.440985,2.482687,-1.312782, 0.443529,2.4945,-1.320356, 0.228104,2.4945,-1.372294, + 0,2.4945,-1.3902, 0,2.482687,-1.382225, 0.226795,2.482687,-1.364422, + 0.226795,2.482687,-1.364422, 0.228104,2.4945,-1.372294, 0,2.4945,-1.3902, + 1.385053,2.498438,-0.230225, 1.372294,2.4945,-0.228104, 1.3902,2.4945,0, + 1.3902,2.4945,0, 1.403125,2.498438,0, 1.385053,2.498438,-0.230225, + 1.332632,2.498438,-0.447653, 1.320356,2.4945,-0.443529, 1.372294,2.4945,-0.228104, + 1.372294,2.4945,-0.228104, 1.385053,2.498438,-0.230225, 1.332632,2.498438,-0.447653, + 1.248557,2.498438,-0.649591, 1.237056,2.4945,-0.643607, 1.320356,2.4945,-0.443529, + 1.320356,2.4945,-0.443529, 1.332632,2.498438,-0.447653, 1.248557,2.498438,-0.649591, + 1.135521,2.498438,-0.833344, 1.125061,2.4945,-0.825668, 1.237056,2.4945,-0.643607, + 1.237056,2.4945,-0.643607, 1.248557,2.498438,-0.649591, 1.135521,2.498438,-0.833344, + 0.996219,2.498438,-0.996219, 0.987042,2.4945,-0.987042, 1.125061,2.4945,-0.825668, + 1.125061,2.4945,-0.825668, 1.135521,2.498438,-0.833344, 0.996219,2.498438,-0.996219, + 0.833344,2.498438,-1.135521, 0.825668,2.4945,-1.125061, 0.987042,2.4945,-0.987042, + 0.987042,2.4945,-0.987042, 0.996219,2.498438,-0.996219, 0.833344,2.498438,-1.135521, + 0.649591,2.498438,-1.248557, 0.643607,2.4945,-1.237056, 0.825668,2.4945,-1.125061, + 0.825668,2.4945,-1.125061, 0.833344,2.498438,-1.135521, 0.649591,2.498438,-1.248557, + 0.447653,2.498438,-1.332632, 0.443529,2.4945,-1.320356, 0.643607,2.4945,-1.237056, + 0.643607,2.4945,-1.237056, 0.649591,2.498438,-1.248557, 0.447653,2.498438,-1.332632, + 0.230225,2.498438,-1.385053, 0.228104,2.4945,-1.372294, 0.443529,2.4945,-1.320356, + 0.443529,2.4945,-1.320356, 0.447653,2.498438,-1.332632, 0.230225,2.498438,-1.385053, + 0,2.498438,-1.403125, 0,2.4945,-1.3902, 0.228104,2.4945,-1.372294, + 0.228104,2.4945,-1.372294, 0.230225,2.498438,-1.385053, 0,2.498438,-1.403125, + 1.401513,2.4945,-0.232961, 1.385053,2.498438,-0.230225, 1.403125,2.498438,0, + 1.403125,2.498438,0, 1.4198,2.4945,0, 1.401513,2.4945,-0.232961, + 1.348469,2.4945,-0.452973, 1.332632,2.498438,-0.447653, 1.385053,2.498438,-0.230225, + 1.385053,2.498438,-0.230225, 1.401513,2.4945,-0.232961, 1.348469,2.4945,-0.452973, + 1.263395,2.4945,-0.657311, 1.248557,2.498438,-0.649591, 1.332632,2.498438,-0.447653, + 1.332632,2.498438,-0.447653, 1.348469,2.4945,-0.452973, 1.263395,2.4945,-0.657311, + 1.149016,2.4945,-0.843248, 1.135521,2.498438,-0.833344, 1.248557,2.498438,-0.649591, + 1.248557,2.498438,-0.649591, 1.263395,2.4945,-0.657311, 1.149016,2.4945,-0.843248, + 1.008058,2.4945,-1.008058, 0.996219,2.498438,-0.996219, 1.135521,2.498438,-0.833344, + 1.135521,2.498438,-0.833344, 1.149016,2.4945,-0.843248, 1.008058,2.4945,-1.008058, + 0.843248,2.4945,-1.149016, 0.833344,2.498438,-1.135521, 0.996219,2.498438,-0.996219, + 0.996219,2.498438,-0.996219, 1.008058,2.4945,-1.008058, 0.843248,2.4945,-1.149016, + 0.657311,2.4945,-1.263395, 0.649591,2.498438,-1.248557, 0.833344,2.498438,-1.135521, + 0.833344,2.498438,-1.135521, 0.843248,2.4945,-1.149016, 0.657311,2.4945,-1.263395, + 0.452973,2.4945,-1.348469, 0.447653,2.498438,-1.332632, 0.649591,2.498438,-1.248557, + 0.649591,2.498438,-1.248557, 0.657311,2.4945,-1.263395, 0.452973,2.4945,-1.348469, + 0.232961,2.4945,-1.401513, 0.230225,2.498438,-1.385053, 0.447653,2.498438,-1.332632, + 0.447653,2.498438,-1.332632, 0.452973,2.4945,-1.348469, 0.232961,2.4945,-1.401513, + 0,2.4945,-1.4198, 0,2.498438,-1.403125, 0.230225,2.498438,-1.385053, + 0.230225,2.498438,-1.385053, 0.232961,2.4945,-1.401513, 0,2.4945,-1.4198, + 1.42049,2.482687,-0.236115, 1.401513,2.4945,-0.232961, 1.4198,2.4945,0, + 1.4198,2.4945,0, 1.439025,2.482687,0, 1.42049,2.482687,-0.236115, + 1.366728,2.482687,-0.459107, 1.348469,2.4945,-0.452973, 1.401513,2.4945,-0.232961, + 1.401513,2.4945,-0.232961, 1.42049,2.482687,-0.236115, 1.366728,2.482687,-0.459107, + 1.280502,2.482687,-0.666211, 1.263395,2.4945,-0.657311, 1.348469,2.4945,-0.452973, + 1.348469,2.4945,-0.452973, 1.366728,2.482687,-0.459107, 1.280502,2.482687,-0.666211, + 1.164574,2.482687,-0.854666, 1.149016,2.4945,-0.843248, 1.263395,2.4945,-0.657311, + 1.263395,2.4945,-0.657311, 1.280502,2.482687,-0.666211, 1.164574,2.482687,-0.854666, + 1.021708,2.482687,-1.021708, 1.008058,2.4945,-1.008058, 1.149016,2.4945,-0.843248, + 1.149016,2.4945,-0.843248, 1.164574,2.482687,-0.854666, 1.021708,2.482687,-1.021708, + 0.854666,2.482687,-1.164574, 0.843248,2.4945,-1.149016, 1.008058,2.4945,-1.008058, + 1.008058,2.4945,-1.008058, 1.021708,2.482687,-1.021708, 0.854666,2.482687,-1.164574, + 0.666211,2.482687,-1.280502, 0.657311,2.4945,-1.263395, 0.843248,2.4945,-1.149016, + 0.843248,2.4945,-1.149016, 0.854666,2.482687,-1.164574, 0.666211,2.482687,-1.280502, + 0.459107,2.482687,-1.366728, 0.452973,2.4945,-1.348469, 0.657311,2.4945,-1.263395, + 0.657311,2.4945,-1.263395, 0.666211,2.482687,-1.280502, 0.459107,2.482687,-1.366728, + 0.236115,2.482687,-1.42049, 0.232961,2.4945,-1.401513, 0.452973,2.4945,-1.348469, + 0.452973,2.4945,-1.348469, 0.459107,2.482687,-1.366728, 0.236115,2.482687,-1.42049, + 0,2.482687,-1.439025, 0,2.4945,-1.4198, 0.232961,2.4945,-1.401513, + 0.232961,2.4945,-1.401513, 0.236115,2.482687,-1.42049, 0,2.482687,-1.439025, + 1.4408,2.463,-0.239491, 1.42049,2.482687,-0.236115, 1.439025,2.482687,0, + 1.439025,2.482687,0, 1.4596,2.463,0, 1.4408,2.463,-0.239491, + 1.38627,2.463,-0.465671, 1.366728,2.482687,-0.459107, 1.42049,2.482687,-0.236115, + 1.42049,2.482687,-0.236115, 1.4408,2.463,-0.239491, 1.38627,2.463,-0.465671, + 1.29881,2.463,-0.675736, 1.280502,2.482687,-0.666211, 1.366728,2.482687,-0.459107, + 1.366728,2.482687,-0.459107, 1.38627,2.463,-0.465671, 1.29881,2.463,-0.675736, + 1.181225,2.463,-0.866886, 1.164574,2.482687,-0.854666, 1.280502,2.482687,-0.666211, + 1.280502,2.482687,-0.666211, 1.29881,2.463,-0.675736, 1.181225,2.463,-0.866886, + 1.036316,2.463,-1.036316, 1.021708,2.482687,-1.021708, 1.164574,2.482687,-0.854666, + 1.164574,2.482687,-0.854666, 1.181225,2.463,-0.866886, 1.036316,2.463,-1.036316, + 0.866886,2.463,-1.181225, 0.854666,2.482687,-1.164574, 1.021708,2.482687,-1.021708, + 1.021708,2.482687,-1.021708, 1.036316,2.463,-1.036316, 0.866886,2.463,-1.181225, + 0.675736,2.463,-1.29881, 0.666211,2.482687,-1.280502, 0.854666,2.482687,-1.164574, + 0.854666,2.482687,-1.164574, 0.866886,2.463,-1.181225, 0.675736,2.463,-1.29881, + 0.465671,2.463,-1.38627, 0.459107,2.482687,-1.366728, 0.666211,2.482687,-1.280502, + 0.666211,2.482687,-1.280502, 0.675736,2.463,-1.29881, 0.465671,2.463,-1.38627, + 0.239491,2.463,-1.4408, 0.236115,2.482687,-1.42049, 0.459107,2.482687,-1.366728, + 0.459107,2.482687,-1.366728, 0.465671,2.463,-1.38627, 0.239491,2.463,-1.4408, + 0,2.463,-1.4596, 0,2.482687,-1.439025, 0.236115,2.482687,-1.42049, + 0.236115,2.482687,-1.42049, 0.239491,2.463,-1.4408, 0,2.463,-1.4596, + 1.461258,2.435437,-0.242892, 1.4408,2.463,-0.239491, 1.4596,2.463,0, + 1.4596,2.463,0, 1.480325,2.435437,0, 1.461258,2.435437,-0.242892, + 1.405953,2.435437,-0.472283, 1.38627,2.463,-0.465671, 1.4408,2.463,-0.239491, + 1.4408,2.463,-0.239491, 1.461258,2.435437,-0.242892, 1.405953,2.435437,-0.472283, + 1.317252,2.435437,-0.685331, 1.29881,2.463,-0.675736, 1.38627,2.463,-0.465671, + 1.38627,2.463,-0.465671, 1.405953,2.435437,-0.472283, 1.317252,2.435437,-0.685331, + 1.197997,2.435437,-0.879195, 1.181225,2.463,-0.866886, 1.29881,2.463,-0.675736, + 1.29881,2.463,-0.675736, 1.317252,2.435437,-0.685331, 1.197997,2.435437,-0.879195, + 1.051031,2.435437,-1.051031, 1.036316,2.463,-1.036316, 1.181225,2.463,-0.866886, + 1.181225,2.463,-0.866886, 1.197997,2.435437,-0.879195, 1.051031,2.435437,-1.051031, + 0.879195,2.435437,-1.197997, 0.866886,2.463,-1.181225, 1.036316,2.463,-1.036316, + 1.036316,2.463,-1.036316, 1.051031,2.435437,-1.051031, 0.879195,2.435437,-1.197997, + 0.685331,2.435437,-1.317252, 0.675736,2.463,-1.29881, 0.866886,2.463,-1.181225, + 0.866886,2.463,-1.181225, 0.879195,2.435437,-1.197997, 0.685331,2.435437,-1.317252, + 0.472283,2.435437,-1.405953, 0.465671,2.463,-1.38627, 0.675736,2.463,-1.29881, + 0.675736,2.463,-1.29881, 0.685331,2.435437,-1.317252, 0.472283,2.435437,-1.405953, + 0.242892,2.435437,-1.461258, 0.239491,2.463,-1.4408, 0.465671,2.463,-1.38627, + 0.465671,2.463,-1.38627, 0.472283,2.435437,-1.405953, 0.242892,2.435437,-1.461258, + 0,2.435437,-1.480325, 0,2.463,-1.4596, 0.239491,2.463,-1.4408, + 0.239491,2.463,-1.4408, 0.242892,2.435437,-1.461258, 0,2.435437,-1.480325, + 1.48068,2.4,-0.24612, 1.461258,2.435437,-0.242892, 1.480325,2.435437,0, + 1.480325,2.435437,0, 1.5,2.4,0, 1.48068,2.4,-0.24612, + 1.42464,2.4,-0.47856, 1.405953,2.435437,-0.472283, 1.461258,2.435437,-0.242892, + 1.461258,2.435437,-0.242892, 1.48068,2.4,-0.24612, 1.42464,2.4,-0.47856, + 1.33476,2.4,-0.69444, 1.317252,2.435437,-0.685331, 1.405953,2.435437,-0.472283, + 1.405953,2.435437,-0.472283, 1.42464,2.4,-0.47856, 1.33476,2.4,-0.69444, + 1.21392,2.4,-0.89088, 1.197997,2.435437,-0.879195, 1.317252,2.435437,-0.685331, + 1.317252,2.435437,-0.685331, 1.33476,2.4,-0.69444, 1.21392,2.4,-0.89088, + 1.065,2.4,-1.065, 1.051031,2.435437,-1.051031, 1.197997,2.435437,-0.879195, + 1.197997,2.435437,-0.879195, 1.21392,2.4,-0.89088, 1.065,2.4,-1.065, + 0.89088,2.4,-1.21392, 0.879195,2.435437,-1.197997, 1.051031,2.435437,-1.051031, + 1.051031,2.435437,-1.051031, 1.065,2.4,-1.065, 0.89088,2.4,-1.21392, + 0.69444,2.4,-1.33476, 0.685331,2.435437,-1.317252, 0.879195,2.435437,-1.197997, + 0.879195,2.435437,-1.197997, 0.89088,2.4,-1.21392, 0.69444,2.4,-1.33476, + 0.47856,2.4,-1.42464, 0.472283,2.435437,-1.405953, 0.685331,2.435437,-1.317252, + 0.685331,2.435437,-1.317252, 0.69444,2.4,-1.33476, 0.47856,2.4,-1.42464, + 0.24612,2.4,-1.48068, 0.242892,2.435437,-1.461258, 0.472283,2.435437,-1.405953, + 0.472283,2.435437,-1.405953, 0.47856,2.4,-1.42464, 0.24612,2.4,-1.48068, + 0,2.4,-1.5, 0,2.435437,-1.480325, 0.242892,2.435437,-1.461258, + 0.242892,2.435437,-1.461258, 0.24612,2.4,-1.48068, 0,2.4,-1.5, + -0.227403,2.435437,-1.368074, -0.229712,2.4,-1.381968, 0,2.4,-1.4, + 0,2.4,-1.4, 0,2.435437,-1.385925, -0.227403,2.435437,-1.368074, + -0.442166,2.435437,-1.316296, -0.446656,2.4,-1.329664, -0.229712,2.4,-1.381968, + -0.229712,2.4,-1.381968, -0.227403,2.435437,-1.368074, -0.442166,2.435437,-1.316296, + -0.641628,2.435437,-1.233252, -0.648144,2.4,-1.245776, -0.446656,2.4,-1.329664, + -0.446656,2.4,-1.329664, -0.442166,2.435437,-1.316296, -0.641628,2.435437,-1.233252, + -0.823129,2.435437,-1.121601, -0.831488,2.4,-1.132992, -0.648144,2.4,-1.245776, + -0.648144,2.4,-1.245776, -0.641628,2.435437,-1.233252, -0.823129,2.435437,-1.121601, + -0.984007,2.435437,-0.984007, -0.994,2.4,-0.994, -0.831488,2.4,-1.132992, + -0.831488,2.4,-1.132992, -0.823129,2.435437,-1.121601, -0.984007,2.435437,-0.984007, + -1.121601,2.435437,-0.823129, -1.132992,2.4,-0.831488, -0.994,2.4,-0.994, + -0.994,2.4,-0.994, -0.984007,2.435437,-0.984007, -1.121601,2.435437,-0.823129, + -1.233252,2.435437,-0.641628, -1.245776,2.4,-0.648144, -1.132992,2.4,-0.831488, + -1.132992,2.4,-0.831488, -1.121601,2.435437,-0.823129, -1.233252,2.435437,-0.641628, + -1.316296,2.435437,-0.442166, -1.329664,2.4,-0.446656, -1.245776,2.4,-0.648144, + -1.245776,2.4,-0.648144, -1.233252,2.435437,-0.641628, -1.316296,2.435437,-0.442166, + -1.368074,2.435437,-0.227403, -1.381968,2.4,-0.229712, -1.329664,2.4,-0.446656, + -1.329664,2.4,-0.446656, -1.316296,2.435437,-0.442166, -1.368074,2.435437,-0.227403, + -1.385925,2.435437,0, -1.4,2.4,0, -1.381968,2.4,-0.229712, + -1.381968,2.4,-0.229712, -1.368074,2.435437,-0.227403, -1.385925,2.435437,0, + -0.226496,2.463,-1.36262, -0.227403,2.435437,-1.368074, 0,2.435437,-1.385925, + 0,2.435437,-1.385925, 0,2.463,-1.3804, -0.226496,2.463,-1.36262, + -0.440403,2.463,-1.311049, -0.442166,2.435437,-1.316296, -0.227403,2.435437,-1.368074, + -0.227403,2.435437,-1.368074, -0.226496,2.463,-1.36262, -0.440403,2.463,-1.311049, + -0.63907,2.463,-1.228335, -0.641628,2.435437,-1.233252, -0.442166,2.435437,-1.316296, + -0.442166,2.435437,-1.316296, -0.440403,2.463,-1.311049, -0.63907,2.463,-1.228335, + -0.819847,2.463,-1.11713, -0.823129,2.435437,-1.121601, -0.641628,2.435437,-1.233252, + -0.641628,2.435437,-1.233252, -0.63907,2.463,-1.228335, -0.819847,2.463,-1.11713, + -0.980084,2.463,-0.980084, -0.984007,2.435437,-0.984007, -0.823129,2.435437,-1.121601, + -0.823129,2.435437,-1.121601, -0.819847,2.463,-1.11713, -0.980084,2.463,-0.980084, + -1.11713,2.463,-0.819847, -1.121601,2.435437,-0.823129, -0.984007,2.435437,-0.984007, + -0.984007,2.435437,-0.984007, -0.980084,2.463,-0.980084, -1.11713,2.463,-0.819847, + -1.228335,2.463,-0.63907, -1.233252,2.435437,-0.641628, -1.121601,2.435437,-0.823129, + -1.121601,2.435437,-0.823129, -1.11713,2.463,-0.819847, -1.228335,2.463,-0.63907, + -1.311049,2.463,-0.440403, -1.316296,2.435437,-0.442166, -1.233252,2.435437,-0.641628, + -1.233252,2.435437,-0.641628, -1.228335,2.463,-0.63907, -1.311049,2.463,-0.440403, + -1.36262,2.463,-0.226496, -1.368074,2.435437,-0.227403, -1.316296,2.435437,-0.442166, + -1.316296,2.435437,-0.442166, -1.311049,2.463,-0.440403, -1.36262,2.463,-0.226496, + -1.3804,2.463,0, -1.385925,2.435437,0, -1.368074,2.435437,-0.227403, + -1.368074,2.435437,-0.227403, -1.36262,2.463,-0.226496, -1.3804,2.463,0, + -0.226795,2.482687,-1.364422, -0.226496,2.463,-1.36262, 0,2.463,-1.3804, + 0,2.463,-1.3804, 0,2.482687,-1.382225, -0.226795,2.482687,-1.364422, + -0.440985,2.482687,-1.312782, -0.440403,2.463,-1.311049, -0.226496,2.463,-1.36262, + -0.226496,2.463,-1.36262, -0.226795,2.482687,-1.364422, -0.440985,2.482687,-1.312782, + -0.639915,2.482687,-1.229959, -0.63907,2.463,-1.228335, -0.440403,2.463,-1.311049, + -0.440403,2.463,-1.311049, -0.440985,2.482687,-1.312782, -0.639915,2.482687,-1.229959, + -0.820931,2.482687,-1.118607, -0.819847,2.463,-1.11713, -0.63907,2.463,-1.228335, + -0.63907,2.463,-1.228335, -0.639915,2.482687,-1.229959, -0.820931,2.482687,-1.118607, + -0.98138,2.482687,-0.98138, -0.980084,2.463,-0.980084, -0.819847,2.463,-1.11713, + -0.819847,2.463,-1.11713, -0.820931,2.482687,-1.118607, -0.98138,2.482687,-0.98138, + -1.118607,2.482687,-0.820931, -1.11713,2.463,-0.819847, -0.980084,2.463,-0.980084, + -0.980084,2.463,-0.980084, -0.98138,2.482687,-0.98138, -1.118607,2.482687,-0.820931, + -1.229959,2.482687,-0.639915, -1.228335,2.463,-0.63907, -1.11713,2.463,-0.819847, + -1.11713,2.463,-0.819847, -1.118607,2.482687,-0.820931, -1.229959,2.482687,-0.639915, + -1.312782,2.482687,-0.440985, -1.311049,2.463,-0.440403, -1.228335,2.463,-0.63907, + -1.228335,2.463,-0.63907, -1.229959,2.482687,-0.639915, -1.312782,2.482687,-0.440985, + -1.364422,2.482687,-0.226795, -1.36262,2.463,-0.226496, -1.311049,2.463,-0.440403, + -1.311049,2.463,-0.440403, -1.312782,2.482687,-0.440985, -1.364422,2.482687,-0.226795, + -1.382225,2.482687,0, -1.3804,2.463,0, -1.36262,2.463,-0.226496, + -1.36262,2.463,-0.226496, -1.364422,2.482687,-0.226795, -1.382225,2.482687,0, + -0.228104,2.4945,-1.372294, -0.226795,2.482687,-1.364422, 0,2.482687,-1.382225, + 0,2.482687,-1.382225, 0,2.4945,-1.3902, -0.228104,2.4945,-1.372294, + -0.443529,2.4945,-1.320356, -0.440985,2.482687,-1.312782, -0.226795,2.482687,-1.364422, + -0.226795,2.482687,-1.364422, -0.228104,2.4945,-1.372294, -0.443529,2.4945,-1.320356, + -0.643607,2.4945,-1.237056, -0.639915,2.482687,-1.229959, -0.440985,2.482687,-1.312782, + -0.440985,2.482687,-1.312782, -0.443529,2.4945,-1.320356, -0.643607,2.4945,-1.237056, + -0.825668,2.4945,-1.125061, -0.820931,2.482687,-1.118607, -0.639915,2.482687,-1.229959, + -0.639915,2.482687,-1.229959, -0.643607,2.4945,-1.237056, -0.825668,2.4945,-1.125061, + -0.987042,2.4945,-0.987042, -0.98138,2.482687,-0.98138, -0.820931,2.482687,-1.118607, + -0.820931,2.482687,-1.118607, -0.825668,2.4945,-1.125061, -0.987042,2.4945,-0.987042, + -1.125061,2.4945,-0.825668, -1.118607,2.482687,-0.820931, -0.98138,2.482687,-0.98138, + -0.98138,2.482687,-0.98138, -0.987042,2.4945,-0.987042, -1.125061,2.4945,-0.825668, + -1.237056,2.4945,-0.643607, -1.229959,2.482687,-0.639915, -1.118607,2.482687,-0.820931, + -1.118607,2.482687,-0.820931, -1.125061,2.4945,-0.825668, -1.237056,2.4945,-0.643607, + -1.320356,2.4945,-0.443529, -1.312782,2.482687,-0.440985, -1.229959,2.482687,-0.639915, + -1.229959,2.482687,-0.639915, -1.237056,2.4945,-0.643607, -1.320356,2.4945,-0.443529, + -1.372294,2.4945,-0.228104, -1.364422,2.482687,-0.226795, -1.312782,2.482687,-0.440985, + -1.312782,2.482687,-0.440985, -1.320356,2.4945,-0.443529, -1.372294,2.4945,-0.228104, + -1.3902,2.4945,0, -1.382225,2.482687,0, -1.364422,2.482687,-0.226795, + -1.364422,2.482687,-0.226795, -1.372294,2.4945,-0.228104, -1.3902,2.4945,0, + -0.230225,2.498438,-1.385053, -0.228104,2.4945,-1.372294, 0,2.4945,-1.3902, + 0,2.4945,-1.3902, 0,2.498438,-1.403125, -0.230225,2.498438,-1.385053, + -0.447653,2.498438,-1.332632, -0.443529,2.4945,-1.320356, -0.228104,2.4945,-1.372294, + -0.228104,2.4945,-1.372294, -0.230225,2.498438,-1.385053, -0.447653,2.498438,-1.332632, + -0.649591,2.498438,-1.248557, -0.643607,2.4945,-1.237056, -0.443529,2.4945,-1.320356, + -0.443529,2.4945,-1.320356, -0.447653,2.498438,-1.332632, -0.649591,2.498438,-1.248557, + -0.833344,2.498438,-1.135521, -0.825668,2.4945,-1.125061, -0.643607,2.4945,-1.237056, + -0.643607,2.4945,-1.237056, -0.649591,2.498438,-1.248557, -0.833344,2.498438,-1.135521, + -0.996219,2.498438,-0.996219, -0.987042,2.4945,-0.987042, -0.825668,2.4945,-1.125061, + -0.825668,2.4945,-1.125061, -0.833344,2.498438,-1.135521, -0.996219,2.498438,-0.996219, + -1.135521,2.498438,-0.833344, -1.125061,2.4945,-0.825668, -0.987042,2.4945,-0.987042, + -0.987042,2.4945,-0.987042, -0.996219,2.498438,-0.996219, -1.135521,2.498438,-0.833344, + -1.248557,2.498438,-0.649591, -1.237056,2.4945,-0.643607, -1.125061,2.4945,-0.825668, + -1.125061,2.4945,-0.825668, -1.135521,2.498438,-0.833344, -1.248557,2.498438,-0.649591, + -1.332632,2.498438,-0.447653, -1.320356,2.4945,-0.443529, -1.237056,2.4945,-0.643607, + -1.237056,2.4945,-0.643607, -1.248557,2.498438,-0.649591, -1.332632,2.498438,-0.447653, + -1.385053,2.498438,-0.230225, -1.372294,2.4945,-0.228104, -1.320356,2.4945,-0.443529, + -1.320356,2.4945,-0.443529, -1.332632,2.498438,-0.447653, -1.385053,2.498438,-0.230225, + -1.403125,2.498438,0, -1.3902,2.4945,0, -1.372294,2.4945,-0.228104, + -1.372294,2.4945,-0.228104, -1.385053,2.498438,-0.230225, -1.403125,2.498438,0, + -0.232961,2.4945,-1.401513, -0.230225,2.498438,-1.385053, 0,2.498438,-1.403125, + 0,2.498438,-1.403125, 0,2.4945,-1.4198, -0.232961,2.4945,-1.401513, + -0.452973,2.4945,-1.348469, -0.447653,2.498438,-1.332632, -0.230225,2.498438,-1.385053, + -0.230225,2.498438,-1.385053, -0.232961,2.4945,-1.401513, -0.452973,2.4945,-1.348469, + -0.657311,2.4945,-1.263395, -0.649591,2.498438,-1.248557, -0.447653,2.498438,-1.332632, + -0.447653,2.498438,-1.332632, -0.452973,2.4945,-1.348469, -0.657311,2.4945,-1.263395, + -0.843248,2.4945,-1.149016, -0.833344,2.498438,-1.135521, -0.649591,2.498438,-1.248557, + -0.649591,2.498438,-1.248557, -0.657311,2.4945,-1.263395, -0.843248,2.4945,-1.149016, + -1.008058,2.4945,-1.008058, -0.996219,2.498438,-0.996219, -0.833344,2.498438,-1.135521, + -0.833344,2.498438,-1.135521, -0.843248,2.4945,-1.149016, -1.008058,2.4945,-1.008058, + -1.149016,2.4945,-0.843248, -1.135521,2.498438,-0.833344, -0.996219,2.498438,-0.996219, + -0.996219,2.498438,-0.996219, -1.008058,2.4945,-1.008058, -1.149016,2.4945,-0.843248, + -1.263395,2.4945,-0.657311, -1.248557,2.498438,-0.649591, -1.135521,2.498438,-0.833344, + -1.135521,2.498438,-0.833344, -1.149016,2.4945,-0.843248, -1.263395,2.4945,-0.657311, + -1.348469,2.4945,-0.452973, -1.332632,2.498438,-0.447653, -1.248557,2.498438,-0.649591, + -1.248557,2.498438,-0.649591, -1.263395,2.4945,-0.657311, -1.348469,2.4945,-0.452973, + -1.401513,2.4945,-0.232961, -1.385053,2.498438,-0.230225, -1.332632,2.498438,-0.447653, + -1.332632,2.498438,-0.447653, -1.348469,2.4945,-0.452973, -1.401513,2.4945,-0.232961, + -1.4198,2.4945,0, -1.403125,2.498438,0, -1.385053,2.498438,-0.230225, + -1.385053,2.498438,-0.230225, -1.401513,2.4945,-0.232961, -1.4198,2.4945,0, + -0.236115,2.482687,-1.42049, -0.232961,2.4945,-1.401513, 0,2.4945,-1.4198, + 0,2.4945,-1.4198, 0,2.482687,-1.439025, -0.236115,2.482687,-1.42049, + -0.459107,2.482687,-1.366728, -0.452973,2.4945,-1.348469, -0.232961,2.4945,-1.401513, + -0.232961,2.4945,-1.401513, -0.236115,2.482687,-1.42049, -0.459107,2.482687,-1.366728, + -0.666211,2.482687,-1.280502, -0.657311,2.4945,-1.263395, -0.452973,2.4945,-1.348469, + -0.452973,2.4945,-1.348469, -0.459107,2.482687,-1.366728, -0.666211,2.482687,-1.280502, + -0.854666,2.482687,-1.164574, -0.843248,2.4945,-1.149016, -0.657311,2.4945,-1.263395, + -0.657311,2.4945,-1.263395, -0.666211,2.482687,-1.280502, -0.854666,2.482687,-1.164574, + -1.021708,2.482687,-1.021708, -1.008058,2.4945,-1.008058, -0.843248,2.4945,-1.149016, + -0.843248,2.4945,-1.149016, -0.854666,2.482687,-1.164574, -1.021708,2.482687,-1.021708, + -1.164574,2.482687,-0.854666, -1.149016,2.4945,-0.843248, -1.008058,2.4945,-1.008058, + -1.008058,2.4945,-1.008058, -1.021708,2.482687,-1.021708, -1.164574,2.482687,-0.854666, + -1.280502,2.482687,-0.666211, -1.263395,2.4945,-0.657311, -1.149016,2.4945,-0.843248, + -1.149016,2.4945,-0.843248, -1.164574,2.482687,-0.854666, -1.280502,2.482687,-0.666211, + -1.366728,2.482687,-0.459107, -1.348469,2.4945,-0.452973, -1.263395,2.4945,-0.657311, + -1.263395,2.4945,-0.657311, -1.280502,2.482687,-0.666211, -1.366728,2.482687,-0.459107, + -1.42049,2.482687,-0.236115, -1.401513,2.4945,-0.232961, -1.348469,2.4945,-0.452973, + -1.348469,2.4945,-0.452973, -1.366728,2.482687,-0.459107, -1.42049,2.482687,-0.236115, + -1.439025,2.482687,0, -1.4198,2.4945,0, -1.401513,2.4945,-0.232961, + -1.401513,2.4945,-0.232961, -1.42049,2.482687,-0.236115, -1.439025,2.482687,0, + -0.239491,2.463,-1.4408, -0.236115,2.482687,-1.42049, 0,2.482687,-1.439025, + 0,2.482687,-1.439025, 0,2.463,-1.4596, -0.239491,2.463,-1.4408, + -0.465671,2.463,-1.38627, -0.459107,2.482687,-1.366728, -0.236115,2.482687,-1.42049, + -0.236115,2.482687,-1.42049, -0.239491,2.463,-1.4408, -0.465671,2.463,-1.38627, + -0.675736,2.463,-1.29881, -0.666211,2.482687,-1.280502, -0.459107,2.482687,-1.366728, + -0.459107,2.482687,-1.366728, -0.465671,2.463,-1.38627, -0.675736,2.463,-1.29881, + -0.866886,2.463,-1.181225, -0.854666,2.482687,-1.164574, -0.666211,2.482687,-1.280502, + -0.666211,2.482687,-1.280502, -0.675736,2.463,-1.29881, -0.866886,2.463,-1.181225, + -1.036316,2.463,-1.036316, -1.021708,2.482687,-1.021708, -0.854666,2.482687,-1.164574, + -0.854666,2.482687,-1.164574, -0.866886,2.463,-1.181225, -1.036316,2.463,-1.036316, + -1.181225,2.463,-0.866886, -1.164574,2.482687,-0.854666, -1.021708,2.482687,-1.021708, + -1.021708,2.482687,-1.021708, -1.036316,2.463,-1.036316, -1.181225,2.463,-0.866886, + -1.29881,2.463,-0.675736, -1.280502,2.482687,-0.666211, -1.164574,2.482687,-0.854666, + -1.164574,2.482687,-0.854666, -1.181225,2.463,-0.866886, -1.29881,2.463,-0.675736, + -1.38627,2.463,-0.465671, -1.366728,2.482687,-0.459107, -1.280502,2.482687,-0.666211, + -1.280502,2.482687,-0.666211, -1.29881,2.463,-0.675736, -1.38627,2.463,-0.465671, + -1.4408,2.463,-0.239491, -1.42049,2.482687,-0.236115, -1.366728,2.482687,-0.459107, + -1.366728,2.482687,-0.459107, -1.38627,2.463,-0.465671, -1.4408,2.463,-0.239491, + -1.4596,2.463,0, -1.439025,2.482687,0, -1.42049,2.482687,-0.236115, + -1.42049,2.482687,-0.236115, -1.4408,2.463,-0.239491, -1.4596,2.463,0, + -0.242892,2.435437,-1.461258, -0.239491,2.463,-1.4408, 0,2.463,-1.4596, + 0,2.463,-1.4596, 0,2.435437,-1.480325, -0.242892,2.435437,-1.461258, + -0.472283,2.435437,-1.405953, -0.465671,2.463,-1.38627, -0.239491,2.463,-1.4408, + -0.239491,2.463,-1.4408, -0.242892,2.435437,-1.461258, -0.472283,2.435437,-1.405953, + -0.685331,2.435437,-1.317252, -0.675736,2.463,-1.29881, -0.465671,2.463,-1.38627, + -0.465671,2.463,-1.38627, -0.472283,2.435437,-1.405953, -0.685331,2.435437,-1.317252, + -0.879195,2.435437,-1.197997, -0.866886,2.463,-1.181225, -0.675736,2.463,-1.29881, + -0.675736,2.463,-1.29881, -0.685331,2.435437,-1.317252, -0.879195,2.435437,-1.197997, + -1.051031,2.435437,-1.051031, -1.036316,2.463,-1.036316, -0.866886,2.463,-1.181225, + -0.866886,2.463,-1.181225, -0.879195,2.435437,-1.197997, -1.051031,2.435437,-1.051031, + -1.197997,2.435437,-0.879195, -1.181225,2.463,-0.866886, -1.036316,2.463,-1.036316, + -1.036316,2.463,-1.036316, -1.051031,2.435437,-1.051031, -1.197997,2.435437,-0.879195, + -1.317252,2.435437,-0.685331, -1.29881,2.463,-0.675736, -1.181225,2.463,-0.866886, + -1.181225,2.463,-0.866886, -1.197997,2.435437,-0.879195, -1.317252,2.435437,-0.685331, + -1.405953,2.435437,-0.472283, -1.38627,2.463,-0.465671, -1.29881,2.463,-0.675736, + -1.29881,2.463,-0.675736, -1.317252,2.435437,-0.685331, -1.405953,2.435437,-0.472283, + -1.461258,2.435437,-0.242892, -1.4408,2.463,-0.239491, -1.38627,2.463,-0.465671, + -1.38627,2.463,-0.465671, -1.405953,2.435437,-0.472283, -1.461258,2.435437,-0.242892, + -1.480325,2.435437,0, -1.4596,2.463,0, -1.4408,2.463,-0.239491, + -1.4408,2.463,-0.239491, -1.461258,2.435437,-0.242892, -1.480325,2.435437,0, + -0.24612,2.4,-1.48068, -0.242892,2.435437,-1.461258, 0,2.435437,-1.480325, + 0,2.435437,-1.480325, 0,2.4,-1.5, -0.24612,2.4,-1.48068, + -0.47856,2.4,-1.42464, -0.472283,2.435437,-1.405953, -0.242892,2.435437,-1.461258, + -0.242892,2.435437,-1.461258, -0.24612,2.4,-1.48068, -0.47856,2.4,-1.42464, + -0.69444,2.4,-1.33476, -0.685331,2.435437,-1.317252, -0.472283,2.435437,-1.405953, + -0.472283,2.435437,-1.405953, -0.47856,2.4,-1.42464, -0.69444,2.4,-1.33476, + -0.89088,2.4,-1.21392, -0.879195,2.435437,-1.197997, -0.685331,2.435437,-1.317252, + -0.685331,2.435437,-1.317252, -0.69444,2.4,-1.33476, -0.89088,2.4,-1.21392, + -1.065,2.4,-1.065, -1.051031,2.435437,-1.051031, -0.879195,2.435437,-1.197997, + -0.879195,2.435437,-1.197997, -0.89088,2.4,-1.21392, -1.065,2.4,-1.065, + -1.21392,2.4,-0.89088, -1.197997,2.435437,-0.879195, -1.051031,2.435437,-1.051031, + -1.051031,2.435437,-1.051031, -1.065,2.4,-1.065, -1.21392,2.4,-0.89088, + -1.33476,2.4,-0.69444, -1.317252,2.435437,-0.685331, -1.197997,2.435437,-0.879195, + -1.197997,2.435437,-0.879195, -1.21392,2.4,-0.89088, -1.33476,2.4,-0.69444, + -1.42464,2.4,-0.47856, -1.405953,2.435437,-0.472283, -1.317252,2.435437,-0.685331, + -1.317252,2.435437,-0.685331, -1.33476,2.4,-0.69444, -1.42464,2.4,-0.47856, + -1.48068,2.4,-0.24612, -1.461258,2.435437,-0.242892, -1.405953,2.435437,-0.472283, + -1.405953,2.435437,-0.472283, -1.42464,2.4,-0.47856, -1.48068,2.4,-0.24612, + -1.5,2.4,0, -1.480325,2.435437,0, -1.461258,2.435437,-0.242892, + -1.461258,2.435437,-0.242892, -1.48068,2.4,-0.24612, -1.5,2.4,0, + -1.368074,2.435437,0.227403, -1.381968,2.4,0.229712, -1.4,2.4,0, + -1.4,2.4,0, -1.385925,2.435437,0, -1.368074,2.435437,0.227403, + -1.316296,2.435437,0.442166, -1.329664,2.4,0.446656, -1.381968,2.4,0.229712, + -1.381968,2.4,0.229712, -1.368074,2.435437,0.227403, -1.316296,2.435437,0.442166, + -1.233252,2.435437,0.641628, -1.245776,2.4,0.648144, -1.329664,2.4,0.446656, + -1.329664,2.4,0.446656, -1.316296,2.435437,0.442166, -1.233252,2.435437,0.641628, + -1.121601,2.435437,0.823129, -1.132992,2.4,0.831488, -1.245776,2.4,0.648144, + -1.245776,2.4,0.648144, -1.233252,2.435437,0.641628, -1.121601,2.435437,0.823129, + -0.984007,2.435437,0.984007, -0.994,2.4,0.994, -1.132992,2.4,0.831488, + -1.132992,2.4,0.831488, -1.121601,2.435437,0.823129, -0.984007,2.435437,0.984007, + -0.823129,2.435437,1.121601, -0.831488,2.4,1.132992, -0.994,2.4,0.994, + -0.994,2.4,0.994, -0.984007,2.435437,0.984007, -0.823129,2.435437,1.121601, + -0.641628,2.435437,1.233252, -0.648144,2.4,1.245776, -0.831488,2.4,1.132992, + -0.831488,2.4,1.132992, -0.823129,2.435437,1.121601, -0.641628,2.435437,1.233252, + -0.442166,2.435437,1.316296, -0.446656,2.4,1.329664, -0.648144,2.4,1.245776, + -0.648144,2.4,1.245776, -0.641628,2.435437,1.233252, -0.442166,2.435437,1.316296, + -0.227403,2.435437,1.368074, -0.229712,2.4,1.381968, -0.446656,2.4,1.329664, + -0.446656,2.4,1.329664, -0.442166,2.435437,1.316296, -0.227403,2.435437,1.368074, + 0,2.435437,1.385925, 0,2.4,1.4, -0.229712,2.4,1.381968, + -0.229712,2.4,1.381968, -0.227403,2.435437,1.368074, 0,2.435437,1.385925, + -1.36262,2.463,0.226496, -1.368074,2.435437,0.227403, -1.385925,2.435437,0, + -1.385925,2.435437,0, -1.3804,2.463,0, -1.36262,2.463,0.226496, + -1.311049,2.463,0.440403, -1.316296,2.435437,0.442166, -1.368074,2.435437,0.227403, + -1.368074,2.435437,0.227403, -1.36262,2.463,0.226496, -1.311049,2.463,0.440403, + -1.228335,2.463,0.63907, -1.233252,2.435437,0.641628, -1.316296,2.435437,0.442166, + -1.316296,2.435437,0.442166, -1.311049,2.463,0.440403, -1.228335,2.463,0.63907, + -1.11713,2.463,0.819847, -1.121601,2.435437,0.823129, -1.233252,2.435437,0.641628, + -1.233252,2.435437,0.641628, -1.228335,2.463,0.63907, -1.11713,2.463,0.819847, + -0.980084,2.463,0.980084, -0.984007,2.435437,0.984007, -1.121601,2.435437,0.823129, + -1.121601,2.435437,0.823129, -1.11713,2.463,0.819847, -0.980084,2.463,0.980084, + -0.819847,2.463,1.11713, -0.823129,2.435437,1.121601, -0.984007,2.435437,0.984007, + -0.984007,2.435437,0.984007, -0.980084,2.463,0.980084, -0.819847,2.463,1.11713, + -0.63907,2.463,1.228335, -0.641628,2.435437,1.233252, -0.823129,2.435437,1.121601, + -0.823129,2.435437,1.121601, -0.819847,2.463,1.11713, -0.63907,2.463,1.228335, + -0.440403,2.463,1.311049, -0.442166,2.435437,1.316296, -0.641628,2.435437,1.233252, + -0.641628,2.435437,1.233252, -0.63907,2.463,1.228335, -0.440403,2.463,1.311049, + -0.226496,2.463,1.36262, -0.227403,2.435437,1.368074, -0.442166,2.435437,1.316296, + -0.442166,2.435437,1.316296, -0.440403,2.463,1.311049, -0.226496,2.463,1.36262, + 0,2.463,1.3804, 0,2.435437,1.385925, -0.227403,2.435437,1.368074, + -0.227403,2.435437,1.368074, -0.226496,2.463,1.36262, 0,2.463,1.3804, + -1.364422,2.482687,0.226795, -1.36262,2.463,0.226496, -1.3804,2.463,0, + -1.3804,2.463,0, -1.382225,2.482687,0, -1.364422,2.482687,0.226795, + -1.312782,2.482687,0.440985, -1.311049,2.463,0.440403, -1.36262,2.463,0.226496, + -1.36262,2.463,0.226496, -1.364422,2.482687,0.226795, -1.312782,2.482687,0.440985, + -1.229959,2.482687,0.639915, -1.228335,2.463,0.63907, -1.311049,2.463,0.440403, + -1.311049,2.463,0.440403, -1.312782,2.482687,0.440985, -1.229959,2.482687,0.639915, + -1.118607,2.482687,0.820931, -1.11713,2.463,0.819847, -1.228335,2.463,0.63907, + -1.228335,2.463,0.63907, -1.229959,2.482687,0.639915, -1.118607,2.482687,0.820931, + -0.98138,2.482687,0.98138, -0.980084,2.463,0.980084, -1.11713,2.463,0.819847, + -1.11713,2.463,0.819847, -1.118607,2.482687,0.820931, -0.98138,2.482687,0.98138, + -0.820931,2.482687,1.118607, -0.819847,2.463,1.11713, -0.980084,2.463,0.980084, + -0.980084,2.463,0.980084, -0.98138,2.482687,0.98138, -0.820931,2.482687,1.118607, + -0.639915,2.482687,1.229959, -0.63907,2.463,1.228335, -0.819847,2.463,1.11713, + -0.819847,2.463,1.11713, -0.820931,2.482687,1.118607, -0.639915,2.482687,1.229959, + -0.440985,2.482687,1.312782, -0.440403,2.463,1.311049, -0.63907,2.463,1.228335, + -0.63907,2.463,1.228335, -0.639915,2.482687,1.229959, -0.440985,2.482687,1.312782, + -0.226795,2.482687,1.364422, -0.226496,2.463,1.36262, -0.440403,2.463,1.311049, + -0.440403,2.463,1.311049, -0.440985,2.482687,1.312782, -0.226795,2.482687,1.364422, + 0,2.482687,1.382225, 0,2.463,1.3804, -0.226496,2.463,1.36262, + -0.226496,2.463,1.36262, -0.226795,2.482687,1.364422, 0,2.482687,1.382225, + -1.372294,2.4945,0.228104, -1.364422,2.482687,0.226795, -1.382225,2.482687,0, + -1.382225,2.482687,0, -1.3902,2.4945,0, -1.372294,2.4945,0.228104, + -1.320356,2.4945,0.443529, -1.312782,2.482687,0.440985, -1.364422,2.482687,0.226795, + -1.364422,2.482687,0.226795, -1.372294,2.4945,0.228104, -1.320356,2.4945,0.443529, + -1.237056,2.4945,0.643607, -1.229959,2.482687,0.639915, -1.312782,2.482687,0.440985, + -1.312782,2.482687,0.440985, -1.320356,2.4945,0.443529, -1.237056,2.4945,0.643607, + -1.125061,2.4945,0.825668, -1.118607,2.482687,0.820931, -1.229959,2.482687,0.639915, + -1.229959,2.482687,0.639915, -1.237056,2.4945,0.643607, -1.125061,2.4945,0.825668, + -0.987042,2.4945,0.987042, -0.98138,2.482687,0.98138, -1.118607,2.482687,0.820931, + -1.118607,2.482687,0.820931, -1.125061,2.4945,0.825668, -0.987042,2.4945,0.987042, + -0.825668,2.4945,1.125061, -0.820931,2.482687,1.118607, -0.98138,2.482687,0.98138, + -0.98138,2.482687,0.98138, -0.987042,2.4945,0.987042, -0.825668,2.4945,1.125061, + -0.643607,2.4945,1.237056, -0.639915,2.482687,1.229959, -0.820931,2.482687,1.118607, + -0.820931,2.482687,1.118607, -0.825668,2.4945,1.125061, -0.643607,2.4945,1.237056, + -0.443529,2.4945,1.320356, -0.440985,2.482687,1.312782, -0.639915,2.482687,1.229959, + -0.639915,2.482687,1.229959, -0.643607,2.4945,1.237056, -0.443529,2.4945,1.320356, + -0.228104,2.4945,1.372294, -0.226795,2.482687,1.364422, -0.440985,2.482687,1.312782, + -0.440985,2.482687,1.312782, -0.443529,2.4945,1.320356, -0.228104,2.4945,1.372294, + 0,2.4945,1.3902, 0,2.482687,1.382225, -0.226795,2.482687,1.364422, + -0.226795,2.482687,1.364422, -0.228104,2.4945,1.372294, 0,2.4945,1.3902, + -1.385053,2.498438,0.230225, -1.372294,2.4945,0.228104, -1.3902,2.4945,0, + -1.3902,2.4945,0, -1.403125,2.498438,0, -1.385053,2.498438,0.230225, + -1.332632,2.498438,0.447653, -1.320356,2.4945,0.443529, -1.372294,2.4945,0.228104, + -1.372294,2.4945,0.228104, -1.385053,2.498438,0.230225, -1.332632,2.498438,0.447653, + -1.248557,2.498438,0.649591, -1.237056,2.4945,0.643607, -1.320356,2.4945,0.443529, + -1.320356,2.4945,0.443529, -1.332632,2.498438,0.447653, -1.248557,2.498438,0.649591, + -1.135521,2.498438,0.833344, -1.125061,2.4945,0.825668, -1.237056,2.4945,0.643607, + -1.237056,2.4945,0.643607, -1.248557,2.498438,0.649591, -1.135521,2.498438,0.833344, + -0.996219,2.498438,0.996219, -0.987042,2.4945,0.987042, -1.125061,2.4945,0.825668, + -1.125061,2.4945,0.825668, -1.135521,2.498438,0.833344, -0.996219,2.498438,0.996219, + -0.833344,2.498438,1.135521, -0.825668,2.4945,1.125061, -0.987042,2.4945,0.987042, + -0.987042,2.4945,0.987042, -0.996219,2.498438,0.996219, -0.833344,2.498438,1.135521, + -0.649591,2.498438,1.248557, -0.643607,2.4945,1.237056, -0.825668,2.4945,1.125061, + -0.825668,2.4945,1.125061, -0.833344,2.498438,1.135521, -0.649591,2.498438,1.248557, + -0.447653,2.498438,1.332632, -0.443529,2.4945,1.320356, -0.643607,2.4945,1.237056, + -0.643607,2.4945,1.237056, -0.649591,2.498438,1.248557, -0.447653,2.498438,1.332632, + -0.230225,2.498438,1.385053, -0.228104,2.4945,1.372294, -0.443529,2.4945,1.320356, + -0.443529,2.4945,1.320356, -0.447653,2.498438,1.332632, -0.230225,2.498438,1.385053, + 0,2.498438,1.403125, 0,2.4945,1.3902, -0.228104,2.4945,1.372294, + -0.228104,2.4945,1.372294, -0.230225,2.498438,1.385053, 0,2.498438,1.403125, + -1.401513,2.4945,0.232961, -1.385053,2.498438,0.230225, -1.403125,2.498438,0, + -1.403125,2.498438,0, -1.4198,2.4945,0, -1.401513,2.4945,0.232961, + -1.348469,2.4945,0.452973, -1.332632,2.498438,0.447653, -1.385053,2.498438,0.230225, + -1.385053,2.498438,0.230225, -1.401513,2.4945,0.232961, -1.348469,2.4945,0.452973, + -1.263395,2.4945,0.657311, -1.248557,2.498438,0.649591, -1.332632,2.498438,0.447653, + -1.332632,2.498438,0.447653, -1.348469,2.4945,0.452973, -1.263395,2.4945,0.657311, + -1.149016,2.4945,0.843248, -1.135521,2.498438,0.833344, -1.248557,2.498438,0.649591, + -1.248557,2.498438,0.649591, -1.263395,2.4945,0.657311, -1.149016,2.4945,0.843248, + -1.008058,2.4945,1.008058, -0.996219,2.498438,0.996219, -1.135521,2.498438,0.833344, + -1.135521,2.498438,0.833344, -1.149016,2.4945,0.843248, -1.008058,2.4945,1.008058, + -0.843248,2.4945,1.149016, -0.833344,2.498438,1.135521, -0.996219,2.498438,0.996219, + -0.996219,2.498438,0.996219, -1.008058,2.4945,1.008058, -0.843248,2.4945,1.149016, + -0.657311,2.4945,1.263395, -0.649591,2.498438,1.248557, -0.833344,2.498438,1.135521, + -0.833344,2.498438,1.135521, -0.843248,2.4945,1.149016, -0.657311,2.4945,1.263395, + -0.452973,2.4945,1.348469, -0.447653,2.498438,1.332632, -0.649591,2.498438,1.248557, + -0.649591,2.498438,1.248557, -0.657311,2.4945,1.263395, -0.452973,2.4945,1.348469, + -0.232961,2.4945,1.401513, -0.230225,2.498438,1.385053, -0.447653,2.498438,1.332632, + -0.447653,2.498438,1.332632, -0.452973,2.4945,1.348469, -0.232961,2.4945,1.401513, + 0,2.4945,1.4198, 0,2.498438,1.403125, -0.230225,2.498438,1.385053, + -0.230225,2.498438,1.385053, -0.232961,2.4945,1.401513, 0,2.4945,1.4198, + -1.42049,2.482687,0.236115, -1.401513,2.4945,0.232961, -1.4198,2.4945,0, + -1.4198,2.4945,0, -1.439025,2.482687,0, -1.42049,2.482687,0.236115, + -1.366728,2.482687,0.459107, -1.348469,2.4945,0.452973, -1.401513,2.4945,0.232961, + -1.401513,2.4945,0.232961, -1.42049,2.482687,0.236115, -1.366728,2.482687,0.459107, + -1.280502,2.482687,0.666211, -1.263395,2.4945,0.657311, -1.348469,2.4945,0.452973, + -1.348469,2.4945,0.452973, -1.366728,2.482687,0.459107, -1.280502,2.482687,0.666211, + -1.164574,2.482687,0.854666, -1.149016,2.4945,0.843248, -1.263395,2.4945,0.657311, + -1.263395,2.4945,0.657311, -1.280502,2.482687,0.666211, -1.164574,2.482687,0.854666, + -1.021708,2.482687,1.021708, -1.008058,2.4945,1.008058, -1.149016,2.4945,0.843248, + -1.149016,2.4945,0.843248, -1.164574,2.482687,0.854666, -1.021708,2.482687,1.021708, + -0.854666,2.482687,1.164574, -0.843248,2.4945,1.149016, -1.008058,2.4945,1.008058, + -1.008058,2.4945,1.008058, -1.021708,2.482687,1.021708, -0.854666,2.482687,1.164574, + -0.666211,2.482687,1.280502, -0.657311,2.4945,1.263395, -0.843248,2.4945,1.149016, + -0.843248,2.4945,1.149016, -0.854666,2.482687,1.164574, -0.666211,2.482687,1.280502, + -0.459107,2.482687,1.366728, -0.452973,2.4945,1.348469, -0.657311,2.4945,1.263395, + -0.657311,2.4945,1.263395, -0.666211,2.482687,1.280502, -0.459107,2.482687,1.366728, + -0.236115,2.482687,1.42049, -0.232961,2.4945,1.401513, -0.452973,2.4945,1.348469, + -0.452973,2.4945,1.348469, -0.459107,2.482687,1.366728, -0.236115,2.482687,1.42049, + 0,2.482687,1.439025, 0,2.4945,1.4198, -0.232961,2.4945,1.401513, + -0.232961,2.4945,1.401513, -0.236115,2.482687,1.42049, 0,2.482687,1.439025, + -1.4408,2.463,0.239491, -1.42049,2.482687,0.236115, -1.439025,2.482687,0, + -1.439025,2.482687,0, -1.4596,2.463,0, -1.4408,2.463,0.239491, + -1.38627,2.463,0.465671, -1.366728,2.482687,0.459107, -1.42049,2.482687,0.236115, + -1.42049,2.482687,0.236115, -1.4408,2.463,0.239491, -1.38627,2.463,0.465671, + -1.29881,2.463,0.675736, -1.280502,2.482687,0.666211, -1.366728,2.482687,0.459107, + -1.366728,2.482687,0.459107, -1.38627,2.463,0.465671, -1.29881,2.463,0.675736, + -1.181225,2.463,0.866886, -1.164574,2.482687,0.854666, -1.280502,2.482687,0.666211, + -1.280502,2.482687,0.666211, -1.29881,2.463,0.675736, -1.181225,2.463,0.866886, + -1.036316,2.463,1.036316, -1.021708,2.482687,1.021708, -1.164574,2.482687,0.854666, + -1.164574,2.482687,0.854666, -1.181225,2.463,0.866886, -1.036316,2.463,1.036316, + -0.866886,2.463,1.181225, -0.854666,2.482687,1.164574, -1.021708,2.482687,1.021708, + -1.021708,2.482687,1.021708, -1.036316,2.463,1.036316, -0.866886,2.463,1.181225, + -0.675736,2.463,1.29881, -0.666211,2.482687,1.280502, -0.854666,2.482687,1.164574, + -0.854666,2.482687,1.164574, -0.866886,2.463,1.181225, -0.675736,2.463,1.29881, + -0.465671,2.463,1.38627, -0.459107,2.482687,1.366728, -0.666211,2.482687,1.280502, + -0.666211,2.482687,1.280502, -0.675736,2.463,1.29881, -0.465671,2.463,1.38627, + -0.239491,2.463,1.4408, -0.236115,2.482687,1.42049, -0.459107,2.482687,1.366728, + -0.459107,2.482687,1.366728, -0.465671,2.463,1.38627, -0.239491,2.463,1.4408, + 0,2.463,1.4596, 0,2.482687,1.439025, -0.236115,2.482687,1.42049, + -0.236115,2.482687,1.42049, -0.239491,2.463,1.4408, 0,2.463,1.4596, + -1.461258,2.435437,0.242892, -1.4408,2.463,0.239491, -1.4596,2.463,0, + -1.4596,2.463,0, -1.480325,2.435437,0, -1.461258,2.435437,0.242892, + -1.405953,2.435437,0.472283, -1.38627,2.463,0.465671, -1.4408,2.463,0.239491, + -1.4408,2.463,0.239491, -1.461258,2.435437,0.242892, -1.405953,2.435437,0.472283, + -1.317252,2.435437,0.685331, -1.29881,2.463,0.675736, -1.38627,2.463,0.465671, + -1.38627,2.463,0.465671, -1.405953,2.435437,0.472283, -1.317252,2.435437,0.685331, + -1.197997,2.435437,0.879195, -1.181225,2.463,0.866886, -1.29881,2.463,0.675736, + -1.29881,2.463,0.675736, -1.317252,2.435437,0.685331, -1.197997,2.435437,0.879195, + -1.051031,2.435437,1.051031, -1.036316,2.463,1.036316, -1.181225,2.463,0.866886, + -1.181225,2.463,0.866886, -1.197997,2.435437,0.879195, -1.051031,2.435437,1.051031, + -0.879195,2.435437,1.197997, -0.866886,2.463,1.181225, -1.036316,2.463,1.036316, + -1.036316,2.463,1.036316, -1.051031,2.435437,1.051031, -0.879195,2.435437,1.197997, + -0.685331,2.435437,1.317252, -0.675736,2.463,1.29881, -0.866886,2.463,1.181225, + -0.866886,2.463,1.181225, -0.879195,2.435437,1.197997, -0.685331,2.435437,1.317252, + -0.472283,2.435437,1.405953, -0.465671,2.463,1.38627, -0.675736,2.463,1.29881, + -0.675736,2.463,1.29881, -0.685331,2.435437,1.317252, -0.472283,2.435437,1.405953, + -0.242892,2.435437,1.461258, -0.239491,2.463,1.4408, -0.465671,2.463,1.38627, + -0.465671,2.463,1.38627, -0.472283,2.435437,1.405953, -0.242892,2.435437,1.461258, + 0,2.435437,1.480325, 0,2.463,1.4596, -0.239491,2.463,1.4408, + -0.239491,2.463,1.4408, -0.242892,2.435437,1.461258, 0,2.435437,1.480325, + -1.48068,2.4,0.24612, -1.461258,2.435437,0.242892, -1.480325,2.435437,0, + -1.480325,2.435437,0, -1.5,2.4,0, -1.48068,2.4,0.24612, + -1.42464,2.4,0.47856, -1.405953,2.435437,0.472283, -1.461258,2.435437,0.242892, + -1.461258,2.435437,0.242892, -1.48068,2.4,0.24612, -1.42464,2.4,0.47856, + -1.33476,2.4,0.69444, -1.317252,2.435437,0.685331, -1.405953,2.435437,0.472283, + -1.405953,2.435437,0.472283, -1.42464,2.4,0.47856, -1.33476,2.4,0.69444, + -1.21392,2.4,0.89088, -1.197997,2.435437,0.879195, -1.317252,2.435437,0.685331, + -1.317252,2.435437,0.685331, -1.33476,2.4,0.69444, -1.21392,2.4,0.89088, + -1.065,2.4,1.065, -1.051031,2.435437,1.051031, -1.197997,2.435437,0.879195, + -1.197997,2.435437,0.879195, -1.21392,2.4,0.89088, -1.065,2.4,1.065, + -0.89088,2.4,1.21392, -0.879195,2.435437,1.197997, -1.051031,2.435437,1.051031, + -1.051031,2.435437,1.051031, -1.065,2.4,1.065, -0.89088,2.4,1.21392, + -0.69444,2.4,1.33476, -0.685331,2.435437,1.317252, -0.879195,2.435437,1.197997, + -0.879195,2.435437,1.197997, -0.89088,2.4,1.21392, -0.69444,2.4,1.33476, + -0.47856,2.4,1.42464, -0.472283,2.435437,1.405953, -0.685331,2.435437,1.317252, + -0.685331,2.435437,1.317252, -0.69444,2.4,1.33476, -0.47856,2.4,1.42464, + -0.24612,2.4,1.48068, -0.242892,2.435437,1.461258, -0.472283,2.435437,1.405953, + -0.472283,2.435437,1.405953, -0.47856,2.4,1.42464, -0.24612,2.4,1.48068, + 0,2.4,1.5, 0,2.435437,1.480325, -0.242892,2.435437,1.461258, + -0.242892,2.435437,1.461258, -0.24612,2.4,1.48068, 0,2.4,1.5, + 0.227403,2.435437,1.368074, 0.229712,2.4,1.381968, 0,2.4,1.4, + 0,2.4,1.4, 0,2.435437,1.385925, 0.227403,2.435437,1.368074, + 0.442166,2.435437,1.316296, 0.446656,2.4,1.329664, 0.229712,2.4,1.381968, + 0.229712,2.4,1.381968, 0.227403,2.435437,1.368074, 0.442166,2.435437,1.316296, + 0.641628,2.435437,1.233252, 0.648144,2.4,1.245776, 0.446656,2.4,1.329664, + 0.446656,2.4,1.329664, 0.442166,2.435437,1.316296, 0.641628,2.435437,1.233252, + 0.823129,2.435437,1.121601, 0.831488,2.4,1.132992, 0.648144,2.4,1.245776, + 0.648144,2.4,1.245776, 0.641628,2.435437,1.233252, 0.823129,2.435437,1.121601, + 0.984007,2.435437,0.984007, 0.994,2.4,0.994, 0.831488,2.4,1.132992, + 0.831488,2.4,1.132992, 0.823129,2.435437,1.121601, 0.984007,2.435437,0.984007, + 1.121601,2.435437,0.823129, 1.132992,2.4,0.831488, 0.994,2.4,0.994, + 0.994,2.4,0.994, 0.984007,2.435437,0.984007, 1.121601,2.435437,0.823129, + 1.233252,2.435437,0.641628, 1.245776,2.4,0.648144, 1.132992,2.4,0.831488, + 1.132992,2.4,0.831488, 1.121601,2.435437,0.823129, 1.233252,2.435437,0.641628, + 1.316296,2.435437,0.442166, 1.329664,2.4,0.446656, 1.245776,2.4,0.648144, + 1.245776,2.4,0.648144, 1.233252,2.435437,0.641628, 1.316296,2.435437,0.442166, + 1.368074,2.435437,0.227403, 1.381968,2.4,0.229712, 1.329664,2.4,0.446656, + 1.329664,2.4,0.446656, 1.316296,2.435437,0.442166, 1.368074,2.435437,0.227403, + 1.385925,2.435437,0, 1.4,2.4,0, 1.381968,2.4,0.229712, + 1.381968,2.4,0.229712, 1.368074,2.435437,0.227403, 1.385925,2.435437,0, + 0.226496,2.463,1.36262, 0.227403,2.435437,1.368074, 0,2.435437,1.385925, + 0,2.435437,1.385925, 0,2.463,1.3804, 0.226496,2.463,1.36262, + 0.440403,2.463,1.311049, 0.442166,2.435437,1.316296, 0.227403,2.435437,1.368074, + 0.227403,2.435437,1.368074, 0.226496,2.463,1.36262, 0.440403,2.463,1.311049, + 0.63907,2.463,1.228335, 0.641628,2.435437,1.233252, 0.442166,2.435437,1.316296, + 0.442166,2.435437,1.316296, 0.440403,2.463,1.311049, 0.63907,2.463,1.228335, + 0.819847,2.463,1.11713, 0.823129,2.435437,1.121601, 0.641628,2.435437,1.233252, + 0.641628,2.435437,1.233252, 0.63907,2.463,1.228335, 0.819847,2.463,1.11713, + 0.980084,2.463,0.980084, 0.984007,2.435437,0.984007, 0.823129,2.435437,1.121601, + 0.823129,2.435437,1.121601, 0.819847,2.463,1.11713, 0.980084,2.463,0.980084, + 1.11713,2.463,0.819847, 1.121601,2.435437,0.823129, 0.984007,2.435437,0.984007, + 0.984007,2.435437,0.984007, 0.980084,2.463,0.980084, 1.11713,2.463,0.819847, + 1.228335,2.463,0.63907, 1.233252,2.435437,0.641628, 1.121601,2.435437,0.823129, + 1.121601,2.435437,0.823129, 1.11713,2.463,0.819847, 1.228335,2.463,0.63907, + 1.311049,2.463,0.440403, 1.316296,2.435437,0.442166, 1.233252,2.435437,0.641628, + 1.233252,2.435437,0.641628, 1.228335,2.463,0.63907, 1.311049,2.463,0.440403, + 1.36262,2.463,0.226496, 1.368074,2.435437,0.227403, 1.316296,2.435437,0.442166, + 1.316296,2.435437,0.442166, 1.311049,2.463,0.440403, 1.36262,2.463,0.226496, + 1.3804,2.463,0, 1.385925,2.435437,0, 1.368074,2.435437,0.227403, + 1.368074,2.435437,0.227403, 1.36262,2.463,0.226496, 1.3804,2.463,0, + 0.226795,2.482687,1.364422, 0.226496,2.463,1.36262, 0,2.463,1.3804, + 0,2.463,1.3804, 0,2.482687,1.382225, 0.226795,2.482687,1.364422, + 0.440985,2.482687,1.312782, 0.440403,2.463,1.311049, 0.226496,2.463,1.36262, + 0.226496,2.463,1.36262, 0.226795,2.482687,1.364422, 0.440985,2.482687,1.312782, + 0.639915,2.482687,1.229959, 0.63907,2.463,1.228335, 0.440403,2.463,1.311049, + 0.440403,2.463,1.311049, 0.440985,2.482687,1.312782, 0.639915,2.482687,1.229959, + 0.820931,2.482687,1.118607, 0.819847,2.463,1.11713, 0.63907,2.463,1.228335, + 0.63907,2.463,1.228335, 0.639915,2.482687,1.229959, 0.820931,2.482687,1.118607, + 0.98138,2.482687,0.98138, 0.980084,2.463,0.980084, 0.819847,2.463,1.11713, + 0.819847,2.463,1.11713, 0.820931,2.482687,1.118607, 0.98138,2.482687,0.98138, + 1.118607,2.482687,0.820931, 1.11713,2.463,0.819847, 0.980084,2.463,0.980084, + 0.980084,2.463,0.980084, 0.98138,2.482687,0.98138, 1.118607,2.482687,0.820931, + 1.229959,2.482687,0.639915, 1.228335,2.463,0.63907, 1.11713,2.463,0.819847, + 1.11713,2.463,0.819847, 1.118607,2.482687,0.820931, 1.229959,2.482687,0.639915, + 1.312782,2.482687,0.440985, 1.311049,2.463,0.440403, 1.228335,2.463,0.63907, + 1.228335,2.463,0.63907, 1.229959,2.482687,0.639915, 1.312782,2.482687,0.440985, + 1.364422,2.482687,0.226795, 1.36262,2.463,0.226496, 1.311049,2.463,0.440403, + 1.311049,2.463,0.440403, 1.312782,2.482687,0.440985, 1.364422,2.482687,0.226795, + 1.382225,2.482687,0, 1.3804,2.463,0, 1.36262,2.463,0.226496, + 1.36262,2.463,0.226496, 1.364422,2.482687,0.226795, 1.382225,2.482687,0, + 0.228104,2.4945,1.372294, 0.226795,2.482687,1.364422, 0,2.482687,1.382225, + 0,2.482687,1.382225, 0,2.4945,1.3902, 0.228104,2.4945,1.372294, + 0.443529,2.4945,1.320356, 0.440985,2.482687,1.312782, 0.226795,2.482687,1.364422, + 0.226795,2.482687,1.364422, 0.228104,2.4945,1.372294, 0.443529,2.4945,1.320356, + 0.643607,2.4945,1.237056, 0.639915,2.482687,1.229959, 0.440985,2.482687,1.312782, + 0.440985,2.482687,1.312782, 0.443529,2.4945,1.320356, 0.643607,2.4945,1.237056, + 0.825668,2.4945,1.125061, 0.820931,2.482687,1.118607, 0.639915,2.482687,1.229959, + 0.639915,2.482687,1.229959, 0.643607,2.4945,1.237056, 0.825668,2.4945,1.125061, + 0.987042,2.4945,0.987042, 0.98138,2.482687,0.98138, 0.820931,2.482687,1.118607, + 0.820931,2.482687,1.118607, 0.825668,2.4945,1.125061, 0.987042,2.4945,0.987042, + 1.125061,2.4945,0.825668, 1.118607,2.482687,0.820931, 0.98138,2.482687,0.98138, + 0.98138,2.482687,0.98138, 0.987042,2.4945,0.987042, 1.125061,2.4945,0.825668, + 1.237056,2.4945,0.643607, 1.229959,2.482687,0.639915, 1.118607,2.482687,0.820931, + 1.118607,2.482687,0.820931, 1.125061,2.4945,0.825668, 1.237056,2.4945,0.643607, + 1.320356,2.4945,0.443529, 1.312782,2.482687,0.440985, 1.229959,2.482687,0.639915, + 1.229959,2.482687,0.639915, 1.237056,2.4945,0.643607, 1.320356,2.4945,0.443529, + 1.372294,2.4945,0.228104, 1.364422,2.482687,0.226795, 1.312782,2.482687,0.440985, + 1.312782,2.482687,0.440985, 1.320356,2.4945,0.443529, 1.372294,2.4945,0.228104, + 1.3902,2.4945,0, 1.382225,2.482687,0, 1.364422,2.482687,0.226795, + 1.364422,2.482687,0.226795, 1.372294,2.4945,0.228104, 1.3902,2.4945,0, + 0.230225,2.498438,1.385053, 0.228104,2.4945,1.372294, 0,2.4945,1.3902, + 0,2.4945,1.3902, 0,2.498438,1.403125, 0.230225,2.498438,1.385053, + 0.447653,2.498438,1.332632, 0.443529,2.4945,1.320356, 0.228104,2.4945,1.372294, + 0.228104,2.4945,1.372294, 0.230225,2.498438,1.385053, 0.447653,2.498438,1.332632, + 0.649591,2.498438,1.248557, 0.643607,2.4945,1.237056, 0.443529,2.4945,1.320356, + 0.443529,2.4945,1.320356, 0.447653,2.498438,1.332632, 0.649591,2.498438,1.248557, + 0.833344,2.498438,1.135521, 0.825668,2.4945,1.125061, 0.643607,2.4945,1.237056, + 0.643607,2.4945,1.237056, 0.649591,2.498438,1.248557, 0.833344,2.498438,1.135521, + 0.996219,2.498438,0.996219, 0.987042,2.4945,0.987042, 0.825668,2.4945,1.125061, + 0.825668,2.4945,1.125061, 0.833344,2.498438,1.135521, 0.996219,2.498438,0.996219, + 1.135521,2.498438,0.833344, 1.125061,2.4945,0.825668, 0.987042,2.4945,0.987042, + 0.987042,2.4945,0.987042, 0.996219,2.498438,0.996219, 1.135521,2.498438,0.833344, + 1.248557,2.498438,0.649591, 1.237056,2.4945,0.643607, 1.125061,2.4945,0.825668, + 1.125061,2.4945,0.825668, 1.135521,2.498438,0.833344, 1.248557,2.498438,0.649591, + 1.332632,2.498438,0.447653, 1.320356,2.4945,0.443529, 1.237056,2.4945,0.643607, + 1.237056,2.4945,0.643607, 1.248557,2.498438,0.649591, 1.332632,2.498438,0.447653, + 1.385053,2.498438,0.230225, 1.372294,2.4945,0.228104, 1.320356,2.4945,0.443529, + 1.320356,2.4945,0.443529, 1.332632,2.498438,0.447653, 1.385053,2.498438,0.230225, + 1.403125,2.498438,0, 1.3902,2.4945,0, 1.372294,2.4945,0.228104, + 1.372294,2.4945,0.228104, 1.385053,2.498438,0.230225, 1.403125,2.498438,0, + 0.232961,2.4945,1.401513, 0.230225,2.498438,1.385053, 0,2.498438,1.403125, + 0,2.498438,1.403125, 0,2.4945,1.4198, 0.232961,2.4945,1.401513, + 0.452973,2.4945,1.348469, 0.447653,2.498438,1.332632, 0.230225,2.498438,1.385053, + 0.230225,2.498438,1.385053, 0.232961,2.4945,1.401513, 0.452973,2.4945,1.348469, + 0.657311,2.4945,1.263395, 0.649591,2.498438,1.248557, 0.447653,2.498438,1.332632, + 0.447653,2.498438,1.332632, 0.452973,2.4945,1.348469, 0.657311,2.4945,1.263395, + 0.843248,2.4945,1.149016, 0.833344,2.498438,1.135521, 0.649591,2.498438,1.248557, + 0.649591,2.498438,1.248557, 0.657311,2.4945,1.263395, 0.843248,2.4945,1.149016, + 1.008058,2.4945,1.008058, 0.996219,2.498438,0.996219, 0.833344,2.498438,1.135521, + 0.833344,2.498438,1.135521, 0.843248,2.4945,1.149016, 1.008058,2.4945,1.008058, + 1.149016,2.4945,0.843248, 1.135521,2.498438,0.833344, 0.996219,2.498438,0.996219, + 0.996219,2.498438,0.996219, 1.008058,2.4945,1.008058, 1.149016,2.4945,0.843248, + 1.263395,2.4945,0.657311, 1.248557,2.498438,0.649591, 1.135521,2.498438,0.833344, + 1.135521,2.498438,0.833344, 1.149016,2.4945,0.843248, 1.263395,2.4945,0.657311, + 1.348469,2.4945,0.452973, 1.332632,2.498438,0.447653, 1.248557,2.498438,0.649591, + 1.248557,2.498438,0.649591, 1.263395,2.4945,0.657311, 1.348469,2.4945,0.452973, + 1.401513,2.4945,0.232961, 1.385053,2.498438,0.230225, 1.332632,2.498438,0.447653, + 1.332632,2.498438,0.447653, 1.348469,2.4945,0.452973, 1.401513,2.4945,0.232961, + 1.4198,2.4945,0, 1.403125,2.498438,0, 1.385053,2.498438,0.230225, + 1.385053,2.498438,0.230225, 1.401513,2.4945,0.232961, 1.4198,2.4945,0, + 0.236115,2.482687,1.42049, 0.232961,2.4945,1.401513, 0,2.4945,1.4198, + 0,2.4945,1.4198, 0,2.482687,1.439025, 0.236115,2.482687,1.42049, + 0.459107,2.482687,1.366728, 0.452973,2.4945,1.348469, 0.232961,2.4945,1.401513, + 0.232961,2.4945,1.401513, 0.236115,2.482687,1.42049, 0.459107,2.482687,1.366728, + 0.666211,2.482687,1.280502, 0.657311,2.4945,1.263395, 0.452973,2.4945,1.348469, + 0.452973,2.4945,1.348469, 0.459107,2.482687,1.366728, 0.666211,2.482687,1.280502, + 0.854666,2.482687,1.164574, 0.843248,2.4945,1.149016, 0.657311,2.4945,1.263395, + 0.657311,2.4945,1.263395, 0.666211,2.482687,1.280502, 0.854666,2.482687,1.164574, + 1.021708,2.482687,1.021708, 1.008058,2.4945,1.008058, 0.843248,2.4945,1.149016, + 0.843248,2.4945,1.149016, 0.854666,2.482687,1.164574, 1.021708,2.482687,1.021708, + 1.164574,2.482687,0.854666, 1.149016,2.4945,0.843248, 1.008058,2.4945,1.008058, + 1.008058,2.4945,1.008058, 1.021708,2.482687,1.021708, 1.164574,2.482687,0.854666, + 1.280502,2.482687,0.666211, 1.263395,2.4945,0.657311, 1.149016,2.4945,0.843248, + 1.149016,2.4945,0.843248, 1.164574,2.482687,0.854666, 1.280502,2.482687,0.666211, + 1.366728,2.482687,0.459107, 1.348469,2.4945,0.452973, 1.263395,2.4945,0.657311, + 1.263395,2.4945,0.657311, 1.280502,2.482687,0.666211, 1.366728,2.482687,0.459107, + 1.42049,2.482687,0.236115, 1.401513,2.4945,0.232961, 1.348469,2.4945,0.452973, + 1.348469,2.4945,0.452973, 1.366728,2.482687,0.459107, 1.42049,2.482687,0.236115, + 1.439025,2.482687,0, 1.4198,2.4945,0, 1.401513,2.4945,0.232961, + 1.401513,2.4945,0.232961, 1.42049,2.482687,0.236115, 1.439025,2.482687,0, + 0.239491,2.463,1.4408, 0.236115,2.482687,1.42049, 0,2.482687,1.439025, + 0,2.482687,1.439025, 0,2.463,1.4596, 0.239491,2.463,1.4408, + 0.465671,2.463,1.38627, 0.459107,2.482687,1.366728, 0.236115,2.482687,1.42049, + 0.236115,2.482687,1.42049, 0.239491,2.463,1.4408, 0.465671,2.463,1.38627, + 0.675736,2.463,1.29881, 0.666211,2.482687,1.280502, 0.459107,2.482687,1.366728, + 0.459107,2.482687,1.366728, 0.465671,2.463,1.38627, 0.675736,2.463,1.29881, + 0.866886,2.463,1.181225, 0.854666,2.482687,1.164574, 0.666211,2.482687,1.280502, + 0.666211,2.482687,1.280502, 0.675736,2.463,1.29881, 0.866886,2.463,1.181225, + 1.036316,2.463,1.036316, 1.021708,2.482687,1.021708, 0.854666,2.482687,1.164574, + 0.854666,2.482687,1.164574, 0.866886,2.463,1.181225, 1.036316,2.463,1.036316, + 1.181225,2.463,0.866886, 1.164574,2.482687,0.854666, 1.021708,2.482687,1.021708, + 1.021708,2.482687,1.021708, 1.036316,2.463,1.036316, 1.181225,2.463,0.866886, + 1.29881,2.463,0.675736, 1.280502,2.482687,0.666211, 1.164574,2.482687,0.854666, + 1.164574,2.482687,0.854666, 1.181225,2.463,0.866886, 1.29881,2.463,0.675736, + 1.38627,2.463,0.465671, 1.366728,2.482687,0.459107, 1.280502,2.482687,0.666211, + 1.280502,2.482687,0.666211, 1.29881,2.463,0.675736, 1.38627,2.463,0.465671, + 1.4408,2.463,0.239491, 1.42049,2.482687,0.236115, 1.366728,2.482687,0.459107, + 1.366728,2.482687,0.459107, 1.38627,2.463,0.465671, 1.4408,2.463,0.239491, + 1.4596,2.463,0, 1.439025,2.482687,0, 1.42049,2.482687,0.236115, + 1.42049,2.482687,0.236115, 1.4408,2.463,0.239491, 1.4596,2.463,0, + 0.242892,2.435437,1.461258, 0.239491,2.463,1.4408, 0,2.463,1.4596, + 0,2.463,1.4596, 0,2.435437,1.480325, 0.242892,2.435437,1.461258, + 0.472283,2.435437,1.405953, 0.465671,2.463,1.38627, 0.239491,2.463,1.4408, + 0.239491,2.463,1.4408, 0.242892,2.435437,1.461258, 0.472283,2.435437,1.405953, + 0.685331,2.435437,1.317252, 0.675736,2.463,1.29881, 0.465671,2.463,1.38627, + 0.465671,2.463,1.38627, 0.472283,2.435437,1.405953, 0.685331,2.435437,1.317252, + 0.879195,2.435437,1.197997, 0.866886,2.463,1.181225, 0.675736,2.463,1.29881, + 0.675736,2.463,1.29881, 0.685331,2.435437,1.317252, 0.879195,2.435437,1.197997, + 1.051031,2.435437,1.051031, 1.036316,2.463,1.036316, 0.866886,2.463,1.181225, + 0.866886,2.463,1.181225, 0.879195,2.435437,1.197997, 1.051031,2.435437,1.051031, + 1.197997,2.435437,0.879195, 1.181225,2.463,0.866886, 1.036316,2.463,1.036316, + 1.036316,2.463,1.036316, 1.051031,2.435437,1.051031, 1.197997,2.435437,0.879195, + 1.317252,2.435437,0.685331, 1.29881,2.463,0.675736, 1.181225,2.463,0.866886, + 1.181225,2.463,0.866886, 1.197997,2.435437,0.879195, 1.317252,2.435437,0.685331, + 1.405953,2.435437,0.472283, 1.38627,2.463,0.465671, 1.29881,2.463,0.675736, + 1.29881,2.463,0.675736, 1.317252,2.435437,0.685331, 1.405953,2.435437,0.472283, + 1.461258,2.435437,0.242892, 1.4408,2.463,0.239491, 1.38627,2.463,0.465671, + 1.38627,2.463,0.465671, 1.405953,2.435437,0.472283, 1.461258,2.435437,0.242892, + 1.480325,2.435437,0, 1.4596,2.463,0, 1.4408,2.463,0.239491, + 1.4408,2.463,0.239491, 1.461258,2.435437,0.242892, 1.480325,2.435437,0, + 0.24612,2.4,1.48068, 0.242892,2.435437,1.461258, 0,2.435437,1.480325, + 0,2.435437,1.480325, 0,2.4,1.5, 0.24612,2.4,1.48068, + 0.47856,2.4,1.42464, 0.472283,2.435437,1.405953, 0.242892,2.435437,1.461258, + 0.242892,2.435437,1.461258, 0.24612,2.4,1.48068, 0.47856,2.4,1.42464, + 0.69444,2.4,1.33476, 0.685331,2.435437,1.317252, 0.472283,2.435437,1.405953, + 0.472283,2.435437,1.405953, 0.47856,2.4,1.42464, 0.69444,2.4,1.33476, + 0.89088,2.4,1.21392, 0.879195,2.435437,1.197997, 0.685331,2.435437,1.317252, + 0.685331,2.435437,1.317252, 0.69444,2.4,1.33476, 0.89088,2.4,1.21392, + 1.065,2.4,1.065, 1.051031,2.435437,1.051031, 0.879195,2.435437,1.197997, + 0.879195,2.435437,1.197997, 0.89088,2.4,1.21392, 1.065,2.4,1.065, + 1.21392,2.4,0.89088, 1.197997,2.435437,0.879195, 1.051031,2.435437,1.051031, + 1.051031,2.435437,1.051031, 1.065,2.4,1.065, 1.21392,2.4,0.89088, + 1.33476,2.4,0.69444, 1.317252,2.435437,0.685331, 1.197997,2.435437,0.879195, + 1.197997,2.435437,0.879195, 1.21392,2.4,0.89088, 1.33476,2.4,0.69444, + 1.42464,2.4,0.47856, 1.405953,2.435437,0.472283, 1.317252,2.435437,0.685331, + 1.317252,2.435437,0.685331, 1.33476,2.4,0.69444, 1.42464,2.4,0.47856, + 1.48068,2.4,0.24612, 1.461258,2.435437,0.242892, 1.405953,2.435437,0.472283, + 1.405953,2.435437,0.472283, 1.42464,2.4,0.47856, 1.48068,2.4,0.24612, + 1.5,2.4,0, 1.480325,2.435437,0, 1.461258,2.435437,0.242892, + 1.461258,2.435437,0.242892, 1.48068,2.4,0.24612, 1.5,2.4,0, + 1.554467,2.242575,-0.258385, 1.48068,2.4,-0.24612, 1.5,2.4,0, + 1.5,2.4,0, 1.57475,2.242575,0, 1.554467,2.242575,-0.258385, + 1.495635,2.242575,-0.502408, 1.42464,2.4,-0.47856, 1.48068,2.4,-0.24612, + 1.48068,2.4,-0.24612, 1.554467,2.242575,-0.258385, 1.495635,2.242575,-0.502408, + 1.401276,2.242575,-0.729046, 1.33476,2.4,-0.69444, 1.42464,2.4,-0.47856, + 1.42464,2.4,-0.47856, 1.495635,2.242575,-0.502408, 1.401276,2.242575,-0.729046, + 1.274414,2.242575,-0.935276, 1.21392,2.4,-0.89088, 1.33476,2.4,-0.69444, + 1.33476,2.4,-0.69444, 1.401276,2.242575,-0.729046, 1.274414,2.242575,-0.935276, + 1.118073,2.242575,-1.118073, 1.065,2.4,-1.065, 1.21392,2.4,-0.89088, + 1.21392,2.4,-0.89088, 1.274414,2.242575,-0.935276, 1.118073,2.242575,-1.118073, + 0.935276,2.242575,-1.274414, 0.89088,2.4,-1.21392, 1.065,2.4,-1.065, + 1.065,2.4,-1.065, 1.118073,2.242575,-1.118073, 0.935276,2.242575,-1.274414, + 0.729046,2.242575,-1.401276, 0.69444,2.4,-1.33476, 0.89088,2.4,-1.21392, + 0.89088,2.4,-1.21392, 0.935276,2.242575,-1.274414, 0.729046,2.242575,-1.401276, + 0.502408,2.242575,-1.495635, 0.47856,2.4,-1.42464, 0.69444,2.4,-1.33476, + 0.69444,2.4,-1.33476, 0.729046,2.242575,-1.401276, 0.502408,2.242575,-1.495635, + 0.258385,2.242575,-1.554467, 0.24612,2.4,-1.48068, 0.47856,2.4,-1.42464, + 0.47856,2.4,-1.42464, 0.502408,2.242575,-1.495635, 0.258385,2.242575,-1.554467, + 0,2.242575,-1.57475, 0,2.4,-1.5, 0.24612,2.4,-1.48068, + 0.24612,2.4,-1.48068, 0.258385,2.242575,-1.554467, 0,2.242575,-1.57475, + 1.626774,2.0856,-0.270404, 1.554467,2.242575,-0.258385, 1.57475,2.242575,0, + 1.57475,2.242575,0, 1.648,2.0856,0, 1.626774,2.0856,-0.270404, + 1.565204,2.0856,-0.525778, 1.495635,2.242575,-0.502408, 1.554467,2.242575,-0.258385, + 1.554467,2.242575,-0.258385, 1.626774,2.0856,-0.270404, 1.565204,2.0856,-0.525778, + 1.466456,2.0856,-0.762958, 1.401276,2.242575,-0.729046, 1.495635,2.242575,-0.502408, + 1.495635,2.242575,-0.502408, 1.565204,2.0856,-0.525778, 1.466456,2.0856,-0.762958, + 1.333693,2.0856,-0.97878, 1.274414,2.242575,-0.935276, 1.401276,2.242575,-0.729046, + 1.401276,2.242575,-0.729046, 1.466456,2.0856,-0.762958, 1.333693,2.0856,-0.97878, + 1.17008,2.0856,-1.17008, 1.118073,2.242575,-1.118073, 1.274414,2.242575,-0.935276, + 1.274414,2.242575,-0.935276, 1.333693,2.0856,-0.97878, 1.17008,2.0856,-1.17008, + 0.97878,2.0856,-1.333693, 0.935276,2.242575,-1.274414, 1.118073,2.242575,-1.118073, + 1.118073,2.242575,-1.118073, 1.17008,2.0856,-1.17008, 0.97878,2.0856,-1.333693, + 0.762958,2.0856,-1.466456, 0.729046,2.242575,-1.401276, 0.935276,2.242575,-1.274414, + 0.935276,2.242575,-1.274414, 0.97878,2.0856,-1.333693, 0.762958,2.0856,-1.466456, + 0.525778,2.0856,-1.565204, 0.502408,2.242575,-1.495635, 0.729046,2.242575,-1.401276, + 0.729046,2.242575,-1.401276, 0.762958,2.0856,-1.466456, 0.525778,2.0856,-1.565204, + 0.270404,2.0856,-1.626774, 0.258385,2.242575,-1.554467, 0.502408,2.242575,-1.495635, + 0.502408,2.242575,-1.495635, 0.525778,2.0856,-1.565204, 0.270404,2.0856,-1.626774, + 0,2.0856,-1.648, 0,2.242575,-1.57475, 0.258385,2.242575,-1.554467, + 0.258385,2.242575,-1.554467, 0.270404,2.0856,-1.626774, 0,2.0856,-1.648, + 1.696119,1.929525,-0.28193, 1.626774,2.0856,-0.270404, 1.648,2.0856,0, + 1.648,2.0856,0, 1.71825,1.929525,0, 1.696119,1.929525,-0.28193, + 1.631925,1.929525,-0.54819, 1.565204,2.0856,-0.525778, 1.626774,2.0856,-0.270404, + 1.626774,2.0856,-0.270404, 1.696119,1.929525,-0.28193, 1.631925,1.929525,-0.54819, + 1.528968,1.929525,-0.795481, 1.466456,2.0856,-0.762958, 1.565204,2.0856,-0.525778, + 1.565204,2.0856,-0.525778, 1.631925,1.929525,-0.54819, 1.528968,1.929525,-0.795481, + 1.390545,1.929525,-1.020503, 1.333693,2.0856,-0.97878, 1.466456,2.0856,-0.762958, + 1.466456,2.0856,-0.762958, 1.528968,1.929525,-0.795481, 1.390545,1.929525,-1.020503, + 1.219958,1.929525,-1.219958, 1.17008,2.0856,-1.17008, 1.333693,2.0856,-0.97878, + 1.333693,2.0856,-0.97878, 1.390545,1.929525,-1.020503, 1.219958,1.929525,-1.219958, + 1.020503,1.929525,-1.390545, 0.97878,2.0856,-1.333693, 1.17008,2.0856,-1.17008, + 1.17008,2.0856,-1.17008, 1.219958,1.929525,-1.219958, 1.020503,1.929525,-1.390545, + 0.795481,1.929525,-1.528968, 0.762958,2.0856,-1.466456, 0.97878,2.0856,-1.333693, + 0.97878,2.0856,-1.333693, 1.020503,1.929525,-1.390545, 0.795481,1.929525,-1.528968, + 0.54819,1.929525,-1.631925, 0.525778,2.0856,-1.565204, 0.762958,2.0856,-1.466456, + 0.762958,2.0856,-1.466456, 0.795481,1.929525,-1.528968, 0.54819,1.929525,-1.631925, + 0.28193,1.929525,-1.696119, 0.270404,2.0856,-1.626774, 0.525778,2.0856,-1.565204, + 0.525778,2.0856,-1.565204, 0.54819,1.929525,-1.631925, 0.28193,1.929525,-1.696119, + 0,1.929525,-1.71825, 0,2.0856,-1.648, 0.270404,2.0856,-1.626774, + 0.270404,2.0856,-1.626774, 0.28193,1.929525,-1.696119, 0,1.929525,-1.71825, + 1.761022,1.7748,-0.292719, 1.696119,1.929525,-0.28193, 1.71825,1.929525,0, + 1.71825,1.929525,0, 1.784,1.7748,0, 1.761022,1.7748,-0.292719, + 1.694372,1.7748,-0.569167, 1.631925,1.929525,-0.54819, 1.696119,1.929525,-0.28193, + 1.696119,1.929525,-0.28193, 1.761022,1.7748,-0.292719, 1.694372,1.7748,-0.569167, + 1.587475,1.7748,-0.825921, 1.528968,1.929525,-0.795481, 1.631925,1.929525,-0.54819, + 1.631925,1.929525,-0.54819, 1.694372,1.7748,-0.569167, 1.587475,1.7748,-0.825921, + 1.443756,1.7748,-1.059553, 1.390545,1.929525,-1.020503, 1.528968,1.929525,-0.795481, + 1.528968,1.929525,-0.795481, 1.587475,1.7748,-0.825921, 1.443756,1.7748,-1.059553, + 1.26664,1.7748,-1.26664, 1.219958,1.929525,-1.219958, 1.390545,1.929525,-1.020503, + 1.390545,1.929525,-1.020503, 1.443756,1.7748,-1.059553, 1.26664,1.7748,-1.26664, + 1.059553,1.7748,-1.443756, 1.020503,1.929525,-1.390545, 1.219958,1.929525,-1.219958, + 1.219958,1.929525,-1.219958, 1.26664,1.7748,-1.26664, 1.059553,1.7748,-1.443756, + 0.825921,1.7748,-1.587475, 0.795481,1.929525,-1.528968, 1.020503,1.929525,-1.390545, + 1.020503,1.929525,-1.390545, 1.059553,1.7748,-1.443756, 0.825921,1.7748,-1.587475, + 0.569167,1.7748,-1.694372, 0.54819,1.929525,-1.631925, 0.795481,1.929525,-1.528968, + 0.795481,1.929525,-1.528968, 0.825921,1.7748,-1.587475, 0.569167,1.7748,-1.694372, + 0.292719,1.7748,-1.761022, 0.28193,1.929525,-1.696119, 0.54819,1.929525,-1.631925, + 0.54819,1.929525,-1.631925, 0.569167,1.7748,-1.694372, 0.292719,1.7748,-1.761022, + 0,1.7748,-1.784, 0,1.929525,-1.71825, 0.28193,1.929525,-1.696119, + 0.28193,1.929525,-1.696119, 0.292719,1.7748,-1.761022, 0,1.7748,-1.784, + 1.820003,1.621875,-0.302523, 1.761022,1.7748,-0.292719, 1.784,1.7748,0, + 1.784,1.7748,0, 1.84375,1.621875,0, 1.820003,1.621875,-0.302523, + 1.75112,1.621875,-0.58823, 1.694372,1.7748,-0.569167, 1.761022,1.7748,-0.292719, + 1.761022,1.7748,-0.292719, 1.820003,1.621875,-0.302523, 1.75112,1.621875,-0.58823, + 1.640643,1.621875,-0.853583, 1.587475,1.7748,-0.825921, 1.694372,1.7748,-0.569167, + 1.694372,1.7748,-0.569167, 1.75112,1.621875,-0.58823, 1.640643,1.621875,-0.853583, + 1.49211,1.621875,-1.09504, 1.443756,1.7748,-1.059553, 1.587475,1.7748,-0.825921, + 1.587475,1.7748,-0.825921, 1.640643,1.621875,-0.853583, 1.49211,1.621875,-1.09504, + 1.309063,1.621875,-1.309063, 1.26664,1.7748,-1.26664, 1.443756,1.7748,-1.059553, + 1.443756,1.7748,-1.059553, 1.49211,1.621875,-1.09504, 1.309063,1.621875,-1.309063, + 1.09504,1.621875,-1.49211, 1.059553,1.7748,-1.443756, 1.26664,1.7748,-1.26664, + 1.26664,1.7748,-1.26664, 1.309063,1.621875,-1.309063, 1.09504,1.621875,-1.49211, + 0.853583,1.621875,-1.640643, 0.825921,1.7748,-1.587475, 1.059553,1.7748,-1.443756, + 1.059553,1.7748,-1.443756, 1.09504,1.621875,-1.49211, 0.853583,1.621875,-1.640643, + 0.58823,1.621875,-1.75112, 0.569167,1.7748,-1.694372, 0.825921,1.7748,-1.587475, + 0.825921,1.7748,-1.587475, 0.853583,1.621875,-1.640643, 0.58823,1.621875,-1.75112, + 0.302522,1.621875,-1.820003, 0.292719,1.7748,-1.761022, 0.569167,1.7748,-1.694372, + 0.569167,1.7748,-1.694372, 0.58823,1.621875,-1.75112, 0.302522,1.621875,-1.820003, + 0,1.621875,-1.84375, 0,1.7748,-1.784, 0.292719,1.7748,-1.761022, + 0.292719,1.7748,-1.761022, 0.302522,1.621875,-1.820003, 0,1.621875,-1.84375, + 1.87158,1.4712,-0.311096, 1.820003,1.621875,-0.302523, 1.84375,1.621875,0, + 1.84375,1.621875,0, 1.896,1.4712,0, 1.87158,1.4712,-0.311096, + 1.800745,1.4712,-0.6049, 1.75112,1.621875,-0.58823, 1.820003,1.621875,-0.302523, + 1.820003,1.621875,-0.302523, 1.87158,1.4712,-0.311096, 1.800745,1.4712,-0.6049, + 1.687137,1.4712,-0.877772, 1.640643,1.621875,-0.853583, 1.75112,1.621875,-0.58823, + 1.75112,1.621875,-0.58823, 1.800745,1.4712,-0.6049, 1.687137,1.4712,-0.877772, + 1.534395,1.4712,-1.126072, 1.49211,1.621875,-1.09504, 1.640643,1.621875,-0.853583, + 1.640643,1.621875,-0.853583, 1.687137,1.4712,-0.877772, 1.534395,1.4712,-1.126072, + 1.34616,1.4712,-1.34616, 1.309063,1.621875,-1.309063, 1.49211,1.621875,-1.09504, + 1.49211,1.621875,-1.09504, 1.534395,1.4712,-1.126072, 1.34616,1.4712,-1.34616, + 1.126072,1.4712,-1.534395, 1.09504,1.621875,-1.49211, 1.309063,1.621875,-1.309063, + 1.309063,1.621875,-1.309063, 1.34616,1.4712,-1.34616, 1.126072,1.4712,-1.534395, + 0.877772,1.4712,-1.687137, 0.853583,1.621875,-1.640643, 1.09504,1.621875,-1.49211, + 1.09504,1.621875,-1.49211, 1.126072,1.4712,-1.534395, 0.877772,1.4712,-1.687137, + 0.6049,1.4712,-1.800745, 0.58823,1.621875,-1.75112, 0.853583,1.621875,-1.640643, + 0.853583,1.621875,-1.640643, 0.877772,1.4712,-1.687137, 0.6049,1.4712,-1.800745, + 0.311096,1.4712,-1.87158, 0.302522,1.621875,-1.820003, 0.58823,1.621875,-1.75112, + 0.58823,1.621875,-1.75112, 0.6049,1.4712,-1.800745, 0.311096,1.4712,-1.87158, + 0,1.4712,-1.896, 0,1.621875,-1.84375, 0.302522,1.621875,-1.820003, + 0.302522,1.621875,-1.820003, 0.311096,1.4712,-1.87158, 0,1.4712,-1.896, + 1.914272,1.323225,-0.318192, 1.87158,1.4712,-0.311096, 1.896,1.4712,0, + 1.896,1.4712,0, 1.93925,1.323225,0, 1.914272,1.323225,-0.318192, + 1.841822,1.323225,-0.618698, 1.800745,1.4712,-0.6049, 1.87158,1.4712,-0.311096, + 1.87158,1.4712,-0.311096, 1.914272,1.323225,-0.318192, 1.841822,1.323225,-0.618698, + 1.725622,1.323225,-0.897795, 1.687137,1.4712,-0.877772, 1.800745,1.4712,-0.6049, + 1.800745,1.4712,-0.6049, 1.841822,1.323225,-0.618698, 1.725622,1.323225,-0.897795, + 1.569396,1.323225,-1.151759, 1.534395,1.4712,-1.126072, 1.687137,1.4712,-0.877772, + 1.687137,1.4712,-0.877772, 1.725622,1.323225,-0.897795, 1.569396,1.323225,-1.151759, + 1.376867,1.323225,-1.376868, 1.34616,1.4712,-1.34616, 1.534395,1.4712,-1.126072, + 1.534395,1.4712,-1.126072, 1.569396,1.323225,-1.151759, 1.376867,1.323225,-1.376868, + 1.151759,1.323225,-1.569396, 1.126072,1.4712,-1.534395, 1.34616,1.4712,-1.34616, + 1.34616,1.4712,-1.34616, 1.376867,1.323225,-1.376868, 1.151759,1.323225,-1.569396, + 0.897795,1.323225,-1.725622, 0.877772,1.4712,-1.687137, 1.126072,1.4712,-1.534395, + 1.126072,1.4712,-1.534395, 1.151759,1.323225,-1.569396, 0.897795,1.323225,-1.725622, + 0.618698,1.323225,-1.841822, 0.6049,1.4712,-1.800745, 0.877772,1.4712,-1.687137, + 0.877772,1.4712,-1.687137, 0.897795,1.323225,-1.725622, 0.618698,1.323225,-1.841822, + 0.318192,1.323225,-1.914272, 0.311096,1.4712,-1.87158, 0.6049,1.4712,-1.800745, + 0.6049,1.4712,-1.800745, 0.618698,1.323225,-1.841822, 0.318192,1.323225,-1.914272, + 0,1.323225,-1.93925, 0,1.4712,-1.896, 0.311096,1.4712,-1.87158, + 0.311096,1.4712,-1.87158, 0.318192,1.323225,-1.914272, 0,1.323225,-1.93925, + 1.946601,1.1784,-0.323566, 1.914272,1.323225,-0.318192, 1.93925,1.323225,0, + 1.93925,1.323225,0, 1.972,1.1784,0, 1.946601,1.1784,-0.323566, + 1.872927,1.1784,-0.629147, 1.841822,1.323225,-0.618698, 1.914272,1.323225,-0.318192, + 1.914272,1.323225,-0.318192, 1.946601,1.1784,-0.323566, 1.872927,1.1784,-0.629147, + 1.754764,1.1784,-0.912957, 1.725622,1.323225,-0.897795, 1.841822,1.323225,-0.618698, + 1.841822,1.323225,-0.618698, 1.872927,1.1784,-0.629147, 1.754764,1.1784,-0.912957, + 1.5959,1.1784,-1.17121, 1.569396,1.323225,-1.151759, 1.725622,1.323225,-0.897795, + 1.725622,1.323225,-0.897795, 1.754764,1.1784,-0.912957, 1.5959,1.1784,-1.17121, + 1.40012,1.1784,-1.40012, 1.376867,1.323225,-1.376868, 1.569396,1.323225,-1.151759, + 1.569396,1.323225,-1.151759, 1.5959,1.1784,-1.17121, 1.40012,1.1784,-1.40012, + 1.17121,1.1784,-1.5959, 1.151759,1.323225,-1.569396, 1.376867,1.323225,-1.376868, + 1.376867,1.323225,-1.376868, 1.40012,1.1784,-1.40012, 1.17121,1.1784,-1.5959, + 0.912957,1.1784,-1.754764, 0.897795,1.323225,-1.725622, 1.151759,1.323225,-1.569396, + 1.151759,1.323225,-1.569396, 1.17121,1.1784,-1.5959, 0.912957,1.1784,-1.754764, + 0.629147,1.1784,-1.872927, 0.618698,1.323225,-1.841822, 0.897795,1.323225,-1.725622, + 0.897795,1.323225,-1.725622, 0.912957,1.1784,-1.754764, 0.629147,1.1784,-1.872927, + 0.323566,1.1784,-1.946601, 0.318192,1.323225,-1.914272, 0.618698,1.323225,-1.841822, + 0.618698,1.323225,-1.841822, 0.629147,1.1784,-1.872927, 0.323566,1.1784,-1.946601, + 0,1.1784,-1.972, 0,1.323225,-1.93925, 0.318192,1.323225,-1.914272, + 0.318192,1.323225,-1.914272, 0.323566,1.1784,-1.946601, 0,1.1784,-1.972, + 1.967083,1.037175,-0.32697, 1.946601,1.1784,-0.323566, 1.972,1.1784,0, + 1.972,1.1784,0, 1.99275,1.037175,0, 1.967083,1.037175,-0.32697, + 1.892634,1.037175,-0.635767, 1.872927,1.1784,-0.629147, 1.946601,1.1784,-0.323566, + 1.946601,1.1784,-0.323566, 1.967083,1.037175,-0.32697, 1.892634,1.037175,-0.635767, + 1.773229,1.037175,-0.922564, 1.754764,1.1784,-0.912957, 1.872927,1.1784,-0.629147, + 1.872927,1.1784,-0.629147, 1.892634,1.037175,-0.635767, 1.773229,1.037175,-0.922564, + 1.612693,1.037175,-1.183534, 1.5959,1.1784,-1.17121, 1.754764,1.1784,-0.912957, + 1.754764,1.1784,-0.912957, 1.773229,1.037175,-0.922564, 1.612693,1.037175,-1.183534, + 1.414853,1.037175,-1.414853, 1.40012,1.1784,-1.40012, 1.5959,1.1784,-1.17121, + 1.5959,1.1784,-1.17121, 1.612693,1.037175,-1.183534, 1.414853,1.037175,-1.414853, + 1.183534,1.037175,-1.612693, 1.17121,1.1784,-1.5959, 1.40012,1.1784,-1.40012, + 1.40012,1.1784,-1.40012, 1.414853,1.037175,-1.414853, 1.183534,1.037175,-1.612693, + 0.922564,1.037175,-1.773229, 0.912957,1.1784,-1.754764, 1.17121,1.1784,-1.5959, + 1.17121,1.1784,-1.5959, 1.183534,1.037175,-1.612693, 0.922564,1.037175,-1.773229, + 0.635767,1.037175,-1.892634, 0.629147,1.1784,-1.872927, 0.912957,1.1784,-1.754764, + 0.912957,1.1784,-1.754764, 0.922564,1.037175,-1.773229, 0.635767,1.037175,-1.892634, + 0.32697,1.037175,-1.967083, 0.323566,1.1784,-1.946601, 0.629147,1.1784,-1.872927, + 0.629147,1.1784,-1.872927, 0.635767,1.037175,-1.892634, 0.32697,1.037175,-1.967083, + 0,1.037175,-1.99275, 0,1.1784,-1.972, 0.323566,1.1784,-1.946601, + 0.323566,1.1784,-1.946601, 0.32697,1.037175,-1.967083, 0,1.037175,-1.99275, + 1.97424,0.9,-0.32816, 1.967083,1.037175,-0.32697, 1.99275,1.037175,0, + 1.99275,1.037175,0, 2,0.9,0, 1.97424,0.9,-0.32816, + 1.89952,0.9,-0.63808, 1.892634,1.037175,-0.635767, 1.967083,1.037175,-0.32697, + 1.967083,1.037175,-0.32697, 1.97424,0.9,-0.32816, 1.89952,0.9,-0.63808, + 1.77968,0.9,-0.92592, 1.773229,1.037175,-0.922564, 1.892634,1.037175,-0.635767, + 1.892634,1.037175,-0.635767, 1.89952,0.9,-0.63808, 1.77968,0.9,-0.92592, + 1.61856,0.9,-1.18784, 1.612693,1.037175,-1.183534, 1.773229,1.037175,-0.922564, + 1.773229,1.037175,-0.922564, 1.77968,0.9,-0.92592, 1.61856,0.9,-1.18784, + 1.42,0.9,-1.42, 1.414853,1.037175,-1.414853, 1.612693,1.037175,-1.183534, + 1.612693,1.037175,-1.183534, 1.61856,0.9,-1.18784, 1.42,0.9,-1.42, + 1.18784,0.9,-1.61856, 1.183534,1.037175,-1.612693, 1.414853,1.037175,-1.414853, + 1.414853,1.037175,-1.414853, 1.42,0.9,-1.42, 1.18784,0.9,-1.61856, + 0.92592,0.9,-1.77968, 0.922564,1.037175,-1.773229, 1.183534,1.037175,-1.612693, + 1.183534,1.037175,-1.612693, 1.18784,0.9,-1.61856, 0.92592,0.9,-1.77968, + 0.63808,0.9,-1.89952, 0.635767,1.037175,-1.892634, 0.922564,1.037175,-1.773229, + 0.922564,1.037175,-1.773229, 0.92592,0.9,-1.77968, 0.63808,0.9,-1.89952, + 0.32816,0.9,-1.97424, 0.32697,1.037175,-1.967083, 0.635767,1.037175,-1.892634, + 0.635767,1.037175,-1.892634, 0.63808,0.9,-1.89952, 0.32816,0.9,-1.97424, + 0,0.9,-2, 0,1.037175,-1.99275, 0.32697,1.037175,-1.967083, + 0.32697,1.037175,-1.967083, 0.32816,0.9,-1.97424, 0,0.9,-2, + -0.258385,2.242575,-1.554467, -0.24612,2.4,-1.48068, 0,2.4,-1.5, + 0,2.4,-1.5, 0,2.242575,-1.57475, -0.258385,2.242575,-1.554467, + -0.502408,2.242575,-1.495635, -0.47856,2.4,-1.42464, -0.24612,2.4,-1.48068, + -0.24612,2.4,-1.48068, -0.258385,2.242575,-1.554467, -0.502408,2.242575,-1.495635, + -0.729046,2.242575,-1.401276, -0.69444,2.4,-1.33476, -0.47856,2.4,-1.42464, + -0.47856,2.4,-1.42464, -0.502408,2.242575,-1.495635, -0.729046,2.242575,-1.401276, + -0.935276,2.242575,-1.274414, -0.89088,2.4,-1.21392, -0.69444,2.4,-1.33476, + -0.69444,2.4,-1.33476, -0.729046,2.242575,-1.401276, -0.935276,2.242575,-1.274414, + -1.118073,2.242575,-1.118073, -1.065,2.4,-1.065, -0.89088,2.4,-1.21392, + -0.89088,2.4,-1.21392, -0.935276,2.242575,-1.274414, -1.118073,2.242575,-1.118073, + -1.274414,2.242575,-0.935276, -1.21392,2.4,-0.89088, -1.065,2.4,-1.065, + -1.065,2.4,-1.065, -1.118073,2.242575,-1.118073, -1.274414,2.242575,-0.935276, + -1.401276,2.242575,-0.729046, -1.33476,2.4,-0.69444, -1.21392,2.4,-0.89088, + -1.21392,2.4,-0.89088, -1.274414,2.242575,-0.935276, -1.401276,2.242575,-0.729046, + -1.495635,2.242575,-0.502408, -1.42464,2.4,-0.47856, -1.33476,2.4,-0.69444, + -1.33476,2.4,-0.69444, -1.401276,2.242575,-0.729046, -1.495635,2.242575,-0.502408, + -1.554467,2.242575,-0.258385, -1.48068,2.4,-0.24612, -1.42464,2.4,-0.47856, + -1.42464,2.4,-0.47856, -1.495635,2.242575,-0.502408, -1.554467,2.242575,-0.258385, + -1.57475,2.242575,0, -1.5,2.4,0, -1.48068,2.4,-0.24612, + -1.48068,2.4,-0.24612, -1.554467,2.242575,-0.258385, -1.57475,2.242575,0, + -0.270404,2.0856,-1.626774, -0.258385,2.242575,-1.554467, 0,2.242575,-1.57475, + 0,2.242575,-1.57475, 0,2.0856,-1.648, -0.270404,2.0856,-1.626774, + -0.525778,2.0856,-1.565204, -0.502408,2.242575,-1.495635, -0.258385,2.242575,-1.554467, + -0.258385,2.242575,-1.554467, -0.270404,2.0856,-1.626774, -0.525778,2.0856,-1.565204, + -0.762958,2.0856,-1.466456, -0.729046,2.242575,-1.401276, -0.502408,2.242575,-1.495635, + -0.502408,2.242575,-1.495635, -0.525778,2.0856,-1.565204, -0.762958,2.0856,-1.466456, + -0.97878,2.0856,-1.333693, -0.935276,2.242575,-1.274414, -0.729046,2.242575,-1.401276, + -0.729046,2.242575,-1.401276, -0.762958,2.0856,-1.466456, -0.97878,2.0856,-1.333693, + -1.17008,2.0856,-1.17008, -1.118073,2.242575,-1.118073, -0.935276,2.242575,-1.274414, + -0.935276,2.242575,-1.274414, -0.97878,2.0856,-1.333693, -1.17008,2.0856,-1.17008, + -1.333693,2.0856,-0.97878, -1.274414,2.242575,-0.935276, -1.118073,2.242575,-1.118073, + -1.118073,2.242575,-1.118073, -1.17008,2.0856,-1.17008, -1.333693,2.0856,-0.97878, + -1.466456,2.0856,-0.762958, -1.401276,2.242575,-0.729046, -1.274414,2.242575,-0.935276, + -1.274414,2.242575,-0.935276, -1.333693,2.0856,-0.97878, -1.466456,2.0856,-0.762958, + -1.565204,2.0856,-0.525778, -1.495635,2.242575,-0.502408, -1.401276,2.242575,-0.729046, + -1.401276,2.242575,-0.729046, -1.466456,2.0856,-0.762958, -1.565204,2.0856,-0.525778, + -1.626774,2.0856,-0.270404, -1.554467,2.242575,-0.258385, -1.495635,2.242575,-0.502408, + -1.495635,2.242575,-0.502408, -1.565204,2.0856,-0.525778, -1.626774,2.0856,-0.270404, + -1.648,2.0856,0, -1.57475,2.242575,0, -1.554467,2.242575,-0.258385, + -1.554467,2.242575,-0.258385, -1.626774,2.0856,-0.270404, -1.648,2.0856,0, + -0.28193,1.929525,-1.696119, -0.270404,2.0856,-1.626774, 0,2.0856,-1.648, + 0,2.0856,-1.648, 0,1.929525,-1.71825, -0.28193,1.929525,-1.696119, + -0.54819,1.929525,-1.631925, -0.525778,2.0856,-1.565204, -0.270404,2.0856,-1.626774, + -0.270404,2.0856,-1.626774, -0.28193,1.929525,-1.696119, -0.54819,1.929525,-1.631925, + -0.795481,1.929525,-1.528968, -0.762958,2.0856,-1.466456, -0.525778,2.0856,-1.565204, + -0.525778,2.0856,-1.565204, -0.54819,1.929525,-1.631925, -0.795481,1.929525,-1.528968, + -1.020503,1.929525,-1.390545, -0.97878,2.0856,-1.333693, -0.762958,2.0856,-1.466456, + -0.762958,2.0856,-1.466456, -0.795481,1.929525,-1.528968, -1.020503,1.929525,-1.390545, + -1.219958,1.929525,-1.219958, -1.17008,2.0856,-1.17008, -0.97878,2.0856,-1.333693, + -0.97878,2.0856,-1.333693, -1.020503,1.929525,-1.390545, -1.219958,1.929525,-1.219958, + -1.390545,1.929525,-1.020503, -1.333693,2.0856,-0.97878, -1.17008,2.0856,-1.17008, + -1.17008,2.0856,-1.17008, -1.219958,1.929525,-1.219958, -1.390545,1.929525,-1.020503, + -1.528968,1.929525,-0.795481, -1.466456,2.0856,-0.762958, -1.333693,2.0856,-0.97878, + -1.333693,2.0856,-0.97878, -1.390545,1.929525,-1.020503, -1.528968,1.929525,-0.795481, + -1.631925,1.929525,-0.54819, -1.565204,2.0856,-0.525778, -1.466456,2.0856,-0.762958, + -1.466456,2.0856,-0.762958, -1.528968,1.929525,-0.795481, -1.631925,1.929525,-0.54819, + -1.696119,1.929525,-0.28193, -1.626774,2.0856,-0.270404, -1.565204,2.0856,-0.525778, + -1.565204,2.0856,-0.525778, -1.631925,1.929525,-0.54819, -1.696119,1.929525,-0.28193, + -1.71825,1.929525,0, -1.648,2.0856,0, -1.626774,2.0856,-0.270404, + -1.626774,2.0856,-0.270404, -1.696119,1.929525,-0.28193, -1.71825,1.929525,0, + -0.292719,1.7748,-1.761022, -0.28193,1.929525,-1.696119, 0,1.929525,-1.71825, + 0,1.929525,-1.71825, 0,1.7748,-1.784, -0.292719,1.7748,-1.761022, + -0.569167,1.7748,-1.694372, -0.54819,1.929525,-1.631925, -0.28193,1.929525,-1.696119, + -0.28193,1.929525,-1.696119, -0.292719,1.7748,-1.761022, -0.569167,1.7748,-1.694372, + -0.825921,1.7748,-1.587475, -0.795481,1.929525,-1.528968, -0.54819,1.929525,-1.631925, + -0.54819,1.929525,-1.631925, -0.569167,1.7748,-1.694372, -0.825921,1.7748,-1.587475, + -1.059553,1.7748,-1.443756, -1.020503,1.929525,-1.390545, -0.795481,1.929525,-1.528968, + -0.795481,1.929525,-1.528968, -0.825921,1.7748,-1.587475, -1.059553,1.7748,-1.443756, + -1.26664,1.7748,-1.26664, -1.219958,1.929525,-1.219958, -1.020503,1.929525,-1.390545, + -1.020503,1.929525,-1.390545, -1.059553,1.7748,-1.443756, -1.26664,1.7748,-1.26664, + -1.443756,1.7748,-1.059553, -1.390545,1.929525,-1.020503, -1.219958,1.929525,-1.219958, + -1.219958,1.929525,-1.219958, -1.26664,1.7748,-1.26664, -1.443756,1.7748,-1.059553, + -1.587475,1.7748,-0.825921, -1.528968,1.929525,-0.795481, -1.390545,1.929525,-1.020503, + -1.390545,1.929525,-1.020503, -1.443756,1.7748,-1.059553, -1.587475,1.7748,-0.825921, + -1.694372,1.7748,-0.569167, -1.631925,1.929525,-0.54819, -1.528968,1.929525,-0.795481, + -1.528968,1.929525,-0.795481, -1.587475,1.7748,-0.825921, -1.694372,1.7748,-0.569167, + -1.761022,1.7748,-0.292719, -1.696119,1.929525,-0.28193, -1.631925,1.929525,-0.54819, + -1.631925,1.929525,-0.54819, -1.694372,1.7748,-0.569167, -1.761022,1.7748,-0.292719, + -1.784,1.7748,0, -1.71825,1.929525,0, -1.696119,1.929525,-0.28193, + -1.696119,1.929525,-0.28193, -1.761022,1.7748,-0.292719, -1.784,1.7748,0, + -0.302523,1.621875,-1.820003, -0.292719,1.7748,-1.761022, 0,1.7748,-1.784, + 0,1.7748,-1.784, 0,1.621875,-1.84375, -0.302523,1.621875,-1.820003, + -0.58823,1.621875,-1.75112, -0.569167,1.7748,-1.694372, -0.292719,1.7748,-1.761022, + -0.292719,1.7748,-1.761022, -0.302523,1.621875,-1.820003, -0.58823,1.621875,-1.75112, + -0.853583,1.621875,-1.640643, -0.825921,1.7748,-1.587475, -0.569167,1.7748,-1.694372, + -0.569167,1.7748,-1.694372, -0.58823,1.621875,-1.75112, -0.853583,1.621875,-1.640643, + -1.09504,1.621875,-1.49211, -1.059553,1.7748,-1.443756, -0.825921,1.7748,-1.587475, + -0.825921,1.7748,-1.587475, -0.853583,1.621875,-1.640643, -1.09504,1.621875,-1.49211, + -1.309063,1.621875,-1.309063, -1.26664,1.7748,-1.26664, -1.059553,1.7748,-1.443756, + -1.059553,1.7748,-1.443756, -1.09504,1.621875,-1.49211, -1.309063,1.621875,-1.309063, + -1.49211,1.621875,-1.09504, -1.443756,1.7748,-1.059553, -1.26664,1.7748,-1.26664, + -1.26664,1.7748,-1.26664, -1.309063,1.621875,-1.309063, -1.49211,1.621875,-1.09504, + -1.640643,1.621875,-0.853583, -1.587475,1.7748,-0.825921, -1.443756,1.7748,-1.059553, + -1.443756,1.7748,-1.059553, -1.49211,1.621875,-1.09504, -1.640643,1.621875,-0.853583, + -1.75112,1.621875,-0.58823, -1.694372,1.7748,-0.569167, -1.587475,1.7748,-0.825921, + -1.587475,1.7748,-0.825921, -1.640643,1.621875,-0.853583, -1.75112,1.621875,-0.58823, + -1.820003,1.621875,-0.302522, -1.761022,1.7748,-0.292719, -1.694372,1.7748,-0.569167, + -1.694372,1.7748,-0.569167, -1.75112,1.621875,-0.58823, -1.820003,1.621875,-0.302522, + -1.84375,1.621875,0, -1.784,1.7748,0, -1.761022,1.7748,-0.292719, + -1.761022,1.7748,-0.292719, -1.820003,1.621875,-0.302522, -1.84375,1.621875,0, + -0.311096,1.4712,-1.87158, -0.302523,1.621875,-1.820003, 0,1.621875,-1.84375, + 0,1.621875,-1.84375, 0,1.4712,-1.896, -0.311096,1.4712,-1.87158, + -0.6049,1.4712,-1.800745, -0.58823,1.621875,-1.75112, -0.302523,1.621875,-1.820003, + -0.302523,1.621875,-1.820003, -0.311096,1.4712,-1.87158, -0.6049,1.4712,-1.800745, + -0.877772,1.4712,-1.687137, -0.853583,1.621875,-1.640643, -0.58823,1.621875,-1.75112, + -0.58823,1.621875,-1.75112, -0.6049,1.4712,-1.800745, -0.877772,1.4712,-1.687137, + -1.126072,1.4712,-1.534395, -1.09504,1.621875,-1.49211, -0.853583,1.621875,-1.640643, + -0.853583,1.621875,-1.640643, -0.877772,1.4712,-1.687137, -1.126072,1.4712,-1.534395, + -1.34616,1.4712,-1.34616, -1.309063,1.621875,-1.309063, -1.09504,1.621875,-1.49211, + -1.09504,1.621875,-1.49211, -1.126072,1.4712,-1.534395, -1.34616,1.4712,-1.34616, + -1.534395,1.4712,-1.126072, -1.49211,1.621875,-1.09504, -1.309063,1.621875,-1.309063, + -1.309063,1.621875,-1.309063, -1.34616,1.4712,-1.34616, -1.534395,1.4712,-1.126072, + -1.687137,1.4712,-0.877772, -1.640643,1.621875,-0.853583, -1.49211,1.621875,-1.09504, + -1.49211,1.621875,-1.09504, -1.534395,1.4712,-1.126072, -1.687137,1.4712,-0.877772, + -1.800745,1.4712,-0.6049, -1.75112,1.621875,-0.58823, -1.640643,1.621875,-0.853583, + -1.640643,1.621875,-0.853583, -1.687137,1.4712,-0.877772, -1.800745,1.4712,-0.6049, + -1.87158,1.4712,-0.311096, -1.820003,1.621875,-0.302522, -1.75112,1.621875,-0.58823, + -1.75112,1.621875,-0.58823, -1.800745,1.4712,-0.6049, -1.87158,1.4712,-0.311096, + -1.896,1.4712,0, -1.84375,1.621875,0, -1.820003,1.621875,-0.302522, + -1.820003,1.621875,-0.302522, -1.87158,1.4712,-0.311096, -1.896,1.4712,0, + -0.318192,1.323225,-1.914272, -0.311096,1.4712,-1.87158, 0,1.4712,-1.896, + 0,1.4712,-1.896, 0,1.323225,-1.93925, -0.318192,1.323225,-1.914272, + -0.618698,1.323225,-1.841822, -0.6049,1.4712,-1.800745, -0.311096,1.4712,-1.87158, + -0.311096,1.4712,-1.87158, -0.318192,1.323225,-1.914272, -0.618698,1.323225,-1.841822, + -0.897795,1.323225,-1.725622, -0.877772,1.4712,-1.687137, -0.6049,1.4712,-1.800745, + -0.6049,1.4712,-1.800745, -0.618698,1.323225,-1.841822, -0.897795,1.323225,-1.725622, + -1.151759,1.323225,-1.569396, -1.126072,1.4712,-1.534395, -0.877772,1.4712,-1.687137, + -0.877772,1.4712,-1.687137, -0.897795,1.323225,-1.725622, -1.151759,1.323225,-1.569396, + -1.376868,1.323225,-1.376867, -1.34616,1.4712,-1.34616, -1.126072,1.4712,-1.534395, + -1.126072,1.4712,-1.534395, -1.151759,1.323225,-1.569396, -1.376868,1.323225,-1.376867, + -1.569396,1.323225,-1.151759, -1.534395,1.4712,-1.126072, -1.34616,1.4712,-1.34616, + -1.34616,1.4712,-1.34616, -1.376868,1.323225,-1.376867, -1.569396,1.323225,-1.151759, + -1.725622,1.323225,-0.897795, -1.687137,1.4712,-0.877772, -1.534395,1.4712,-1.126072, + -1.534395,1.4712,-1.126072, -1.569396,1.323225,-1.151759, -1.725622,1.323225,-0.897795, + -1.841822,1.323225,-0.618698, -1.800745,1.4712,-0.6049, -1.687137,1.4712,-0.877772, + -1.687137,1.4712,-0.877772, -1.725622,1.323225,-0.897795, -1.841822,1.323225,-0.618698, + -1.914272,1.323225,-0.318192, -1.87158,1.4712,-0.311096, -1.800745,1.4712,-0.6049, + -1.800745,1.4712,-0.6049, -1.841822,1.323225,-0.618698, -1.914272,1.323225,-0.318192, + -1.93925,1.323225,0, -1.896,1.4712,0, -1.87158,1.4712,-0.311096, + -1.87158,1.4712,-0.311096, -1.914272,1.323225,-0.318192, -1.93925,1.323225,0, + -0.323566,1.1784,-1.946601, -0.318192,1.323225,-1.914272, 0,1.323225,-1.93925, + 0,1.323225,-1.93925, 0,1.1784,-1.972, -0.323566,1.1784,-1.946601, + -0.629147,1.1784,-1.872927, -0.618698,1.323225,-1.841822, -0.318192,1.323225,-1.914272, + -0.318192,1.323225,-1.914272, -0.323566,1.1784,-1.946601, -0.629147,1.1784,-1.872927, + -0.912957,1.1784,-1.754764, -0.897795,1.323225,-1.725622, -0.618698,1.323225,-1.841822, + -0.618698,1.323225,-1.841822, -0.629147,1.1784,-1.872927, -0.912957,1.1784,-1.754764, + -1.17121,1.1784,-1.5959, -1.151759,1.323225,-1.569396, -0.897795,1.323225,-1.725622, + -0.897795,1.323225,-1.725622, -0.912957,1.1784,-1.754764, -1.17121,1.1784,-1.5959, + -1.40012,1.1784,-1.40012, -1.376868,1.323225,-1.376867, -1.151759,1.323225,-1.569396, + -1.151759,1.323225,-1.569396, -1.17121,1.1784,-1.5959, -1.40012,1.1784,-1.40012, + -1.5959,1.1784,-1.17121, -1.569396,1.323225,-1.151759, -1.376868,1.323225,-1.376867, + -1.376868,1.323225,-1.376867, -1.40012,1.1784,-1.40012, -1.5959,1.1784,-1.17121, + -1.754764,1.1784,-0.912957, -1.725622,1.323225,-0.897795, -1.569396,1.323225,-1.151759, + -1.569396,1.323225,-1.151759, -1.5959,1.1784,-1.17121, -1.754764,1.1784,-0.912957, + -1.872927,1.1784,-0.629147, -1.841822,1.323225,-0.618698, -1.725622,1.323225,-0.897795, + -1.725622,1.323225,-0.897795, -1.754764,1.1784,-0.912957, -1.872927,1.1784,-0.629147, + -1.946601,1.1784,-0.323566, -1.914272,1.323225,-0.318192, -1.841822,1.323225,-0.618698, + -1.841822,1.323225,-0.618698, -1.872927,1.1784,-0.629147, -1.946601,1.1784,-0.323566, + -1.972,1.1784,0, -1.93925,1.323225,0, -1.914272,1.323225,-0.318192, + -1.914272,1.323225,-0.318192, -1.946601,1.1784,-0.323566, -1.972,1.1784,0, + -0.32697,1.037175,-1.967083, -0.323566,1.1784,-1.946601, 0,1.1784,-1.972, + 0,1.1784,-1.972, 0,1.037175,-1.99275, -0.32697,1.037175,-1.967083, + -0.635767,1.037175,-1.892634, -0.629147,1.1784,-1.872927, -0.323566,1.1784,-1.946601, + -0.323566,1.1784,-1.946601, -0.32697,1.037175,-1.967083, -0.635767,1.037175,-1.892634, + -0.922564,1.037175,-1.773229, -0.912957,1.1784,-1.754764, -0.629147,1.1784,-1.872927, + -0.629147,1.1784,-1.872927, -0.635767,1.037175,-1.892634, -0.922564,1.037175,-1.773229, + -1.183534,1.037175,-1.612693, -1.17121,1.1784,-1.5959, -0.912957,1.1784,-1.754764, + -0.912957,1.1784,-1.754764, -0.922564,1.037175,-1.773229, -1.183534,1.037175,-1.612693, + -1.414853,1.037175,-1.414853, -1.40012,1.1784,-1.40012, -1.17121,1.1784,-1.5959, + -1.17121,1.1784,-1.5959, -1.183534,1.037175,-1.612693, -1.414853,1.037175,-1.414853, + -1.612693,1.037175,-1.183534, -1.5959,1.1784,-1.17121, -1.40012,1.1784,-1.40012, + -1.40012,1.1784,-1.40012, -1.414853,1.037175,-1.414853, -1.612693,1.037175,-1.183534, + -1.773229,1.037175,-0.922564, -1.754764,1.1784,-0.912957, -1.5959,1.1784,-1.17121, + -1.5959,1.1784,-1.17121, -1.612693,1.037175,-1.183534, -1.773229,1.037175,-0.922564, + -1.892634,1.037175,-0.635767, -1.872927,1.1784,-0.629147, -1.754764,1.1784,-0.912957, + -1.754764,1.1784,-0.912957, -1.773229,1.037175,-0.922564, -1.892634,1.037175,-0.635767, + -1.967083,1.037175,-0.32697, -1.946601,1.1784,-0.323566, -1.872927,1.1784,-0.629147, + -1.872927,1.1784,-0.629147, -1.892634,1.037175,-0.635767, -1.967083,1.037175,-0.32697, + -1.99275,1.037175,0, -1.972,1.1784,0, -1.946601,1.1784,-0.323566, + -1.946601,1.1784,-0.323566, -1.967083,1.037175,-0.32697, -1.99275,1.037175,0, + -0.32816,0.9,-1.97424, -0.32697,1.037175,-1.967083, 0,1.037175,-1.99275, + 0,1.037175,-1.99275, 0,0.9,-2, -0.32816,0.9,-1.97424, + -0.63808,0.9,-1.89952, -0.635767,1.037175,-1.892634, -0.32697,1.037175,-1.967083, + -0.32697,1.037175,-1.967083, -0.32816,0.9,-1.97424, -0.63808,0.9,-1.89952, + -0.92592,0.9,-1.77968, -0.922564,1.037175,-1.773229, -0.635767,1.037175,-1.892634, + -0.635767,1.037175,-1.892634, -0.63808,0.9,-1.89952, -0.92592,0.9,-1.77968, + -1.18784,0.9,-1.61856, -1.183534,1.037175,-1.612693, -0.922564,1.037175,-1.773229, + -0.922564,1.037175,-1.773229, -0.92592,0.9,-1.77968, -1.18784,0.9,-1.61856, + -1.42,0.9,-1.42, -1.414853,1.037175,-1.414853, -1.183534,1.037175,-1.612693, + -1.183534,1.037175,-1.612693, -1.18784,0.9,-1.61856, -1.42,0.9,-1.42, + -1.61856,0.9,-1.18784, -1.612693,1.037175,-1.183534, -1.414853,1.037175,-1.414853, + -1.414853,1.037175,-1.414853, -1.42,0.9,-1.42, -1.61856,0.9,-1.18784, + -1.77968,0.9,-0.92592, -1.773229,1.037175,-0.922564, -1.612693,1.037175,-1.183534, + -1.612693,1.037175,-1.183534, -1.61856,0.9,-1.18784, -1.77968,0.9,-0.92592, + -1.89952,0.9,-0.63808, -1.892634,1.037175,-0.635767, -1.773229,1.037175,-0.922564, + -1.773229,1.037175,-0.922564, -1.77968,0.9,-0.92592, -1.89952,0.9,-0.63808, + -1.97424,0.9,-0.32816, -1.967083,1.037175,-0.32697, -1.892634,1.037175,-0.635767, + -1.892634,1.037175,-0.635767, -1.89952,0.9,-0.63808, -1.97424,0.9,-0.32816, + -2,0.9,0, -1.99275,1.037175,0, -1.967083,1.037175,-0.32697, + -1.967083,1.037175,-0.32697, -1.97424,0.9,-0.32816, -2,0.9,0, + -1.554467,2.242575,0.258385, -1.48068,2.4,0.24612, -1.5,2.4,0, + -1.5,2.4,0, -1.57475,2.242575,0, -1.554467,2.242575,0.258385, + -1.495635,2.242575,0.502408, -1.42464,2.4,0.47856, -1.48068,2.4,0.24612, + -1.48068,2.4,0.24612, -1.554467,2.242575,0.258385, -1.495635,2.242575,0.502408, + -1.401276,2.242575,0.729046, -1.33476,2.4,0.69444, -1.42464,2.4,0.47856, + -1.42464,2.4,0.47856, -1.495635,2.242575,0.502408, -1.401276,2.242575,0.729046, + -1.274414,2.242575,0.935276, -1.21392,2.4,0.89088, -1.33476,2.4,0.69444, + -1.33476,2.4,0.69444, -1.401276,2.242575,0.729046, -1.274414,2.242575,0.935276, + -1.118073,2.242575,1.118073, -1.065,2.4,1.065, -1.21392,2.4,0.89088, + -1.21392,2.4,0.89088, -1.274414,2.242575,0.935276, -1.118073,2.242575,1.118073, + -0.935276,2.242575,1.274414, -0.89088,2.4,1.21392, -1.065,2.4,1.065, + -1.065,2.4,1.065, -1.118073,2.242575,1.118073, -0.935276,2.242575,1.274414, + -0.729046,2.242575,1.401276, -0.69444,2.4,1.33476, -0.89088,2.4,1.21392, + -0.89088,2.4,1.21392, -0.935276,2.242575,1.274414, -0.729046,2.242575,1.401276, + -0.502408,2.242575,1.495635, -0.47856,2.4,1.42464, -0.69444,2.4,1.33476, + -0.69444,2.4,1.33476, -0.729046,2.242575,1.401276, -0.502408,2.242575,1.495635, + -0.258385,2.242575,1.554467, -0.24612,2.4,1.48068, -0.47856,2.4,1.42464, + -0.47856,2.4,1.42464, -0.502408,2.242575,1.495635, -0.258385,2.242575,1.554467, + 0,2.242575,1.57475, 0,2.4,1.5, -0.24612,2.4,1.48068, + -0.24612,2.4,1.48068, -0.258385,2.242575,1.554467, 0,2.242575,1.57475, + -1.626774,2.0856,0.270404, -1.554467,2.242575,0.258385, -1.57475,2.242575,0, + -1.57475,2.242575,0, -1.648,2.0856,0, -1.626774,2.0856,0.270404, + -1.565204,2.0856,0.525778, -1.495635,2.242575,0.502408, -1.554467,2.242575,0.258385, + -1.554467,2.242575,0.258385, -1.626774,2.0856,0.270404, -1.565204,2.0856,0.525778, + -1.466456,2.0856,0.762958, -1.401276,2.242575,0.729046, -1.495635,2.242575,0.502408, + -1.495635,2.242575,0.502408, -1.565204,2.0856,0.525778, -1.466456,2.0856,0.762958, + -1.333693,2.0856,0.97878, -1.274414,2.242575,0.935276, -1.401276,2.242575,0.729046, + -1.401276,2.242575,0.729046, -1.466456,2.0856,0.762958, -1.333693,2.0856,0.97878, + -1.17008,2.0856,1.17008, -1.118073,2.242575,1.118073, -1.274414,2.242575,0.935276, + -1.274414,2.242575,0.935276, -1.333693,2.0856,0.97878, -1.17008,2.0856,1.17008, + -0.97878,2.0856,1.333693, -0.935276,2.242575,1.274414, -1.118073,2.242575,1.118073, + -1.118073,2.242575,1.118073, -1.17008,2.0856,1.17008, -0.97878,2.0856,1.333693, + -0.762958,2.0856,1.466456, -0.729046,2.242575,1.401276, -0.935276,2.242575,1.274414, + -0.935276,2.242575,1.274414, -0.97878,2.0856,1.333693, -0.762958,2.0856,1.466456, + -0.525778,2.0856,1.565204, -0.502408,2.242575,1.495635, -0.729046,2.242575,1.401276, + -0.729046,2.242575,1.401276, -0.762958,2.0856,1.466456, -0.525778,2.0856,1.565204, + -0.270404,2.0856,1.626774, -0.258385,2.242575,1.554467, -0.502408,2.242575,1.495635, + -0.502408,2.242575,1.495635, -0.525778,2.0856,1.565204, -0.270404,2.0856,1.626774, + 0,2.0856,1.648, 0,2.242575,1.57475, -0.258385,2.242575,1.554467, + -0.258385,2.242575,1.554467, -0.270404,2.0856,1.626774, 0,2.0856,1.648, + -1.696119,1.929525,0.28193, -1.626774,2.0856,0.270404, -1.648,2.0856,0, + -1.648,2.0856,0, -1.71825,1.929525,0, -1.696119,1.929525,0.28193, + -1.631925,1.929525,0.54819, -1.565204,2.0856,0.525778, -1.626774,2.0856,0.270404, + -1.626774,2.0856,0.270404, -1.696119,1.929525,0.28193, -1.631925,1.929525,0.54819, + -1.528968,1.929525,0.795481, -1.466456,2.0856,0.762958, -1.565204,2.0856,0.525778, + -1.565204,2.0856,0.525778, -1.631925,1.929525,0.54819, -1.528968,1.929525,0.795481, + -1.390545,1.929525,1.020503, -1.333693,2.0856,0.97878, -1.466456,2.0856,0.762958, + -1.466456,2.0856,0.762958, -1.528968,1.929525,0.795481, -1.390545,1.929525,1.020503, + -1.219958,1.929525,1.219958, -1.17008,2.0856,1.17008, -1.333693,2.0856,0.97878, + -1.333693,2.0856,0.97878, -1.390545,1.929525,1.020503, -1.219958,1.929525,1.219958, + -1.020503,1.929525,1.390545, -0.97878,2.0856,1.333693, -1.17008,2.0856,1.17008, + -1.17008,2.0856,1.17008, -1.219958,1.929525,1.219958, -1.020503,1.929525,1.390545, + -0.795481,1.929525,1.528968, -0.762958,2.0856,1.466456, -0.97878,2.0856,1.333693, + -0.97878,2.0856,1.333693, -1.020503,1.929525,1.390545, -0.795481,1.929525,1.528968, + -0.54819,1.929525,1.631925, -0.525778,2.0856,1.565204, -0.762958,2.0856,1.466456, + -0.762958,2.0856,1.466456, -0.795481,1.929525,1.528968, -0.54819,1.929525,1.631925, + -0.28193,1.929525,1.696119, -0.270404,2.0856,1.626774, -0.525778,2.0856,1.565204, + -0.525778,2.0856,1.565204, -0.54819,1.929525,1.631925, -0.28193,1.929525,1.696119, + 0,1.929525,1.71825, 0,2.0856,1.648, -0.270404,2.0856,1.626774, + -0.270404,2.0856,1.626774, -0.28193,1.929525,1.696119, 0,1.929525,1.71825, + -1.761022,1.7748,0.292719, -1.696119,1.929525,0.28193, -1.71825,1.929525,0, + -1.71825,1.929525,0, -1.784,1.7748,0, -1.761022,1.7748,0.292719, + -1.694372,1.7748,0.569167, -1.631925,1.929525,0.54819, -1.696119,1.929525,0.28193, + -1.696119,1.929525,0.28193, -1.761022,1.7748,0.292719, -1.694372,1.7748,0.569167, + -1.587475,1.7748,0.825921, -1.528968,1.929525,0.795481, -1.631925,1.929525,0.54819, + -1.631925,1.929525,0.54819, -1.694372,1.7748,0.569167, -1.587475,1.7748,0.825921, + -1.443756,1.7748,1.059553, -1.390545,1.929525,1.020503, -1.528968,1.929525,0.795481, + -1.528968,1.929525,0.795481, -1.587475,1.7748,0.825921, -1.443756,1.7748,1.059553, + -1.26664,1.7748,1.26664, -1.219958,1.929525,1.219958, -1.390545,1.929525,1.020503, + -1.390545,1.929525,1.020503, -1.443756,1.7748,1.059553, -1.26664,1.7748,1.26664, + -1.059553,1.7748,1.443756, -1.020503,1.929525,1.390545, -1.219958,1.929525,1.219958, + -1.219958,1.929525,1.219958, -1.26664,1.7748,1.26664, -1.059553,1.7748,1.443756, + -0.825921,1.7748,1.587475, -0.795481,1.929525,1.528968, -1.020503,1.929525,1.390545, + -1.020503,1.929525,1.390545, -1.059553,1.7748,1.443756, -0.825921,1.7748,1.587475, + -0.569167,1.7748,1.694372, -0.54819,1.929525,1.631925, -0.795481,1.929525,1.528968, + -0.795481,1.929525,1.528968, -0.825921,1.7748,1.587475, -0.569167,1.7748,1.694372, + -0.292719,1.7748,1.761022, -0.28193,1.929525,1.696119, -0.54819,1.929525,1.631925, + -0.54819,1.929525,1.631925, -0.569167,1.7748,1.694372, -0.292719,1.7748,1.761022, + 0,1.7748,1.784, 0,1.929525,1.71825, -0.28193,1.929525,1.696119, + -0.28193,1.929525,1.696119, -0.292719,1.7748,1.761022, 0,1.7748,1.784, + -1.820003,1.621875,0.302523, -1.761022,1.7748,0.292719, -1.784,1.7748,0, + -1.784,1.7748,0, -1.84375,1.621875,0, -1.820003,1.621875,0.302523, + -1.75112,1.621875,0.58823, -1.694372,1.7748,0.569167, -1.761022,1.7748,0.292719, + -1.761022,1.7748,0.292719, -1.820003,1.621875,0.302523, -1.75112,1.621875,0.58823, + -1.640643,1.621875,0.853583, -1.587475,1.7748,0.825921, -1.694372,1.7748,0.569167, + -1.694372,1.7748,0.569167, -1.75112,1.621875,0.58823, -1.640643,1.621875,0.853583, + -1.49211,1.621875,1.09504, -1.443756,1.7748,1.059553, -1.587475,1.7748,0.825921, + -1.587475,1.7748,0.825921, -1.640643,1.621875,0.853583, -1.49211,1.621875,1.09504, + -1.309063,1.621875,1.309063, -1.26664,1.7748,1.26664, -1.443756,1.7748,1.059553, + -1.443756,1.7748,1.059553, -1.49211,1.621875,1.09504, -1.309063,1.621875,1.309063, + -1.09504,1.621875,1.49211, -1.059553,1.7748,1.443756, -1.26664,1.7748,1.26664, + -1.26664,1.7748,1.26664, -1.309063,1.621875,1.309063, -1.09504,1.621875,1.49211, + -0.853583,1.621875,1.640643, -0.825921,1.7748,1.587475, -1.059553,1.7748,1.443756, + -1.059553,1.7748,1.443756, -1.09504,1.621875,1.49211, -0.853583,1.621875,1.640643, + -0.58823,1.621875,1.75112, -0.569167,1.7748,1.694372, -0.825921,1.7748,1.587475, + -0.825921,1.7748,1.587475, -0.853583,1.621875,1.640643, -0.58823,1.621875,1.75112, + -0.302522,1.621875,1.820003, -0.292719,1.7748,1.761022, -0.569167,1.7748,1.694372, + -0.569167,1.7748,1.694372, -0.58823,1.621875,1.75112, -0.302522,1.621875,1.820003, + 0,1.621875,1.84375, 0,1.7748,1.784, -0.292719,1.7748,1.761022, + -0.292719,1.7748,1.761022, -0.302522,1.621875,1.820003, 0,1.621875,1.84375, + -1.87158,1.4712,0.311096, -1.820003,1.621875,0.302523, -1.84375,1.621875,0, + -1.84375,1.621875,0, -1.896,1.4712,0, -1.87158,1.4712,0.311096, + -1.800745,1.4712,0.6049, -1.75112,1.621875,0.58823, -1.820003,1.621875,0.302523, + -1.820003,1.621875,0.302523, -1.87158,1.4712,0.311096, -1.800745,1.4712,0.6049, + -1.687137,1.4712,0.877772, -1.640643,1.621875,0.853583, -1.75112,1.621875,0.58823, + -1.75112,1.621875,0.58823, -1.800745,1.4712,0.6049, -1.687137,1.4712,0.877772, + -1.534395,1.4712,1.126072, -1.49211,1.621875,1.09504, -1.640643,1.621875,0.853583, + -1.640643,1.621875,0.853583, -1.687137,1.4712,0.877772, -1.534395,1.4712,1.126072, + -1.34616,1.4712,1.34616, -1.309063,1.621875,1.309063, -1.49211,1.621875,1.09504, + -1.49211,1.621875,1.09504, -1.534395,1.4712,1.126072, -1.34616,1.4712,1.34616, + -1.126072,1.4712,1.534395, -1.09504,1.621875,1.49211, -1.309063,1.621875,1.309063, + -1.309063,1.621875,1.309063, -1.34616,1.4712,1.34616, -1.126072,1.4712,1.534395, + -0.877772,1.4712,1.687137, -0.853583,1.621875,1.640643, -1.09504,1.621875,1.49211, + -1.09504,1.621875,1.49211, -1.126072,1.4712,1.534395, -0.877772,1.4712,1.687137, + -0.6049,1.4712,1.800745, -0.58823,1.621875,1.75112, -0.853583,1.621875,1.640643, + -0.853583,1.621875,1.640643, -0.877772,1.4712,1.687137, -0.6049,1.4712,1.800745, + -0.311096,1.4712,1.87158, -0.302522,1.621875,1.820003, -0.58823,1.621875,1.75112, + -0.58823,1.621875,1.75112, -0.6049,1.4712,1.800745, -0.311096,1.4712,1.87158, + 0,1.4712,1.896, 0,1.621875,1.84375, -0.302522,1.621875,1.820003, + -0.302522,1.621875,1.820003, -0.311096,1.4712,1.87158, 0,1.4712,1.896, + -1.914272,1.323225,0.318192, -1.87158,1.4712,0.311096, -1.896,1.4712,0, + -1.896,1.4712,0, -1.93925,1.323225,0, -1.914272,1.323225,0.318192, + -1.841822,1.323225,0.618698, -1.800745,1.4712,0.6049, -1.87158,1.4712,0.311096, + -1.87158,1.4712,0.311096, -1.914272,1.323225,0.318192, -1.841822,1.323225,0.618698, + -1.725622,1.323225,0.897795, -1.687137,1.4712,0.877772, -1.800745,1.4712,0.6049, + -1.800745,1.4712,0.6049, -1.841822,1.323225,0.618698, -1.725622,1.323225,0.897795, + -1.569396,1.323225,1.151759, -1.534395,1.4712,1.126072, -1.687137,1.4712,0.877772, + -1.687137,1.4712,0.877772, -1.725622,1.323225,0.897795, -1.569396,1.323225,1.151759, + -1.376867,1.323225,1.376868, -1.34616,1.4712,1.34616, -1.534395,1.4712,1.126072, + -1.534395,1.4712,1.126072, -1.569396,1.323225,1.151759, -1.376867,1.323225,1.376868, + -1.151759,1.323225,1.569396, -1.126072,1.4712,1.534395, -1.34616,1.4712,1.34616, + -1.34616,1.4712,1.34616, -1.376867,1.323225,1.376868, -1.151759,1.323225,1.569396, + -0.897795,1.323225,1.725622, -0.877772,1.4712,1.687137, -1.126072,1.4712,1.534395, + -1.126072,1.4712,1.534395, -1.151759,1.323225,1.569396, -0.897795,1.323225,1.725622, + -0.618698,1.323225,1.841822, -0.6049,1.4712,1.800745, -0.877772,1.4712,1.687137, + -0.877772,1.4712,1.687137, -0.897795,1.323225,1.725622, -0.618698,1.323225,1.841822, + -0.318192,1.323225,1.914272, -0.311096,1.4712,1.87158, -0.6049,1.4712,1.800745, + -0.6049,1.4712,1.800745, -0.618698,1.323225,1.841822, -0.318192,1.323225,1.914272, + 0,1.323225,1.93925, 0,1.4712,1.896, -0.311096,1.4712,1.87158, + -0.311096,1.4712,1.87158, -0.318192,1.323225,1.914272, 0,1.323225,1.93925, + -1.946601,1.1784,0.323566, -1.914272,1.323225,0.318192, -1.93925,1.323225,0, + -1.93925,1.323225,0, -1.972,1.1784,0, -1.946601,1.1784,0.323566, + -1.872927,1.1784,0.629147, -1.841822,1.323225,0.618698, -1.914272,1.323225,0.318192, + -1.914272,1.323225,0.318192, -1.946601,1.1784,0.323566, -1.872927,1.1784,0.629147, + -1.754764,1.1784,0.912957, -1.725622,1.323225,0.897795, -1.841822,1.323225,0.618698, + -1.841822,1.323225,0.618698, -1.872927,1.1784,0.629147, -1.754764,1.1784,0.912957, + -1.5959,1.1784,1.17121, -1.569396,1.323225,1.151759, -1.725622,1.323225,0.897795, + -1.725622,1.323225,0.897795, -1.754764,1.1784,0.912957, -1.5959,1.1784,1.17121, + -1.40012,1.1784,1.40012, -1.376867,1.323225,1.376868, -1.569396,1.323225,1.151759, + -1.569396,1.323225,1.151759, -1.5959,1.1784,1.17121, -1.40012,1.1784,1.40012, + -1.17121,1.1784,1.5959, -1.151759,1.323225,1.569396, -1.376867,1.323225,1.376868, + -1.376867,1.323225,1.376868, -1.40012,1.1784,1.40012, -1.17121,1.1784,1.5959, + -0.912957,1.1784,1.754764, -0.897795,1.323225,1.725622, -1.151759,1.323225,1.569396, + -1.151759,1.323225,1.569396, -1.17121,1.1784,1.5959, -0.912957,1.1784,1.754764, + -0.629147,1.1784,1.872927, -0.618698,1.323225,1.841822, -0.897795,1.323225,1.725622, + -0.897795,1.323225,1.725622, -0.912957,1.1784,1.754764, -0.629147,1.1784,1.872927, + -0.323566,1.1784,1.946601, -0.318192,1.323225,1.914272, -0.618698,1.323225,1.841822, + -0.618698,1.323225,1.841822, -0.629147,1.1784,1.872927, -0.323566,1.1784,1.946601, + 0,1.1784,1.972, 0,1.323225,1.93925, -0.318192,1.323225,1.914272, + -0.318192,1.323225,1.914272, -0.323566,1.1784,1.946601, 0,1.1784,1.972, + -1.967083,1.037175,0.32697, -1.946601,1.1784,0.323566, -1.972,1.1784,0, + -1.972,1.1784,0, -1.99275,1.037175,0, -1.967083,1.037175,0.32697, + -1.892634,1.037175,0.635767, -1.872927,1.1784,0.629147, -1.946601,1.1784,0.323566, + -1.946601,1.1784,0.323566, -1.967083,1.037175,0.32697, -1.892634,1.037175,0.635767, + -1.773229,1.037175,0.922564, -1.754764,1.1784,0.912957, -1.872927,1.1784,0.629147, + -1.872927,1.1784,0.629147, -1.892634,1.037175,0.635767, -1.773229,1.037175,0.922564, + -1.612693,1.037175,1.183534, -1.5959,1.1784,1.17121, -1.754764,1.1784,0.912957, + -1.754764,1.1784,0.912957, -1.773229,1.037175,0.922564, -1.612693,1.037175,1.183534, + -1.414853,1.037175,1.414853, -1.40012,1.1784,1.40012, -1.5959,1.1784,1.17121, + -1.5959,1.1784,1.17121, -1.612693,1.037175,1.183534, -1.414853,1.037175,1.414853, + -1.183534,1.037175,1.612693, -1.17121,1.1784,1.5959, -1.40012,1.1784,1.40012, + -1.40012,1.1784,1.40012, -1.414853,1.037175,1.414853, -1.183534,1.037175,1.612693, + -0.922564,1.037175,1.773229, -0.912957,1.1784,1.754764, -1.17121,1.1784,1.5959, + -1.17121,1.1784,1.5959, -1.183534,1.037175,1.612693, -0.922564,1.037175,1.773229, + -0.635767,1.037175,1.892634, -0.629147,1.1784,1.872927, -0.912957,1.1784,1.754764, + -0.912957,1.1784,1.754764, -0.922564,1.037175,1.773229, -0.635767,1.037175,1.892634, + -0.32697,1.037175,1.967083, -0.323566,1.1784,1.946601, -0.629147,1.1784,1.872927, + -0.629147,1.1784,1.872927, -0.635767,1.037175,1.892634, -0.32697,1.037175,1.967083, + 0,1.037175,1.99275, 0,1.1784,1.972, -0.323566,1.1784,1.946601, + -0.323566,1.1784,1.946601, -0.32697,1.037175,1.967083, 0,1.037175,1.99275, + -1.97424,0.9,0.32816, -1.967083,1.037175,0.32697, -1.99275,1.037175,0, + -1.99275,1.037175,0, -2,0.9,0, -1.97424,0.9,0.32816, + -1.89952,0.9,0.63808, -1.892634,1.037175,0.635767, -1.967083,1.037175,0.32697, + -1.967083,1.037175,0.32697, -1.97424,0.9,0.32816, -1.89952,0.9,0.63808, + -1.77968,0.9,0.92592, -1.773229,1.037175,0.922564, -1.892634,1.037175,0.635767, + -1.892634,1.037175,0.635767, -1.89952,0.9,0.63808, -1.77968,0.9,0.92592, + -1.61856,0.9,1.18784, -1.612693,1.037175,1.183534, -1.773229,1.037175,0.922564, + -1.773229,1.037175,0.922564, -1.77968,0.9,0.92592, -1.61856,0.9,1.18784, + -1.42,0.9,1.42, -1.414853,1.037175,1.414853, -1.612693,1.037175,1.183534, + -1.612693,1.037175,1.183534, -1.61856,0.9,1.18784, -1.42,0.9,1.42, + -1.18784,0.9,1.61856, -1.183534,1.037175,1.612693, -1.414853,1.037175,1.414853, + -1.414853,1.037175,1.414853, -1.42,0.9,1.42, -1.18784,0.9,1.61856, + -0.92592,0.9,1.77968, -0.922564,1.037175,1.773229, -1.183534,1.037175,1.612693, + -1.183534,1.037175,1.612693, -1.18784,0.9,1.61856, -0.92592,0.9,1.77968, + -0.63808,0.9,1.89952, -0.635767,1.037175,1.892634, -0.922564,1.037175,1.773229, + -0.922564,1.037175,1.773229, -0.92592,0.9,1.77968, -0.63808,0.9,1.89952, + -0.32816,0.9,1.97424, -0.32697,1.037175,1.967083, -0.635767,1.037175,1.892634, + -0.635767,1.037175,1.892634, -0.63808,0.9,1.89952, -0.32816,0.9,1.97424, + 0,0.9,2, 0,1.037175,1.99275, -0.32697,1.037175,1.967083, + -0.32697,1.037175,1.967083, -0.32816,0.9,1.97424, 0,0.9,2, + 0.258385,2.242575,1.554467, 0.24612,2.4,1.48068, 0,2.4,1.5, + 0,2.4,1.5, 0,2.242575,1.57475, 0.258385,2.242575,1.554467, + 0.502408,2.242575,1.495635, 0.47856,2.4,1.42464, 0.24612,2.4,1.48068, + 0.24612,2.4,1.48068, 0.258385,2.242575,1.554467, 0.502408,2.242575,1.495635, + 0.729046,2.242575,1.401276, 0.69444,2.4,1.33476, 0.47856,2.4,1.42464, + 0.47856,2.4,1.42464, 0.502408,2.242575,1.495635, 0.729046,2.242575,1.401276, + 0.935276,2.242575,1.274414, 0.89088,2.4,1.21392, 0.69444,2.4,1.33476, + 0.69444,2.4,1.33476, 0.729046,2.242575,1.401276, 0.935276,2.242575,1.274414, + 1.118073,2.242575,1.118073, 1.065,2.4,1.065, 0.89088,2.4,1.21392, + 0.89088,2.4,1.21392, 0.935276,2.242575,1.274414, 1.118073,2.242575,1.118073, + 1.274414,2.242575,0.935276, 1.21392,2.4,0.89088, 1.065,2.4,1.065, + 1.065,2.4,1.065, 1.118073,2.242575,1.118073, 1.274414,2.242575,0.935276, + 1.401276,2.242575,0.729046, 1.33476,2.4,0.69444, 1.21392,2.4,0.89088, + 1.21392,2.4,0.89088, 1.274414,2.242575,0.935276, 1.401276,2.242575,0.729046, + 1.495635,2.242575,0.502408, 1.42464,2.4,0.47856, 1.33476,2.4,0.69444, + 1.33476,2.4,0.69444, 1.401276,2.242575,0.729046, 1.495635,2.242575,0.502408, + 1.554467,2.242575,0.258385, 1.48068,2.4,0.24612, 1.42464,2.4,0.47856, + 1.42464,2.4,0.47856, 1.495635,2.242575,0.502408, 1.554467,2.242575,0.258385, + 1.57475,2.242575,0, 1.5,2.4,0, 1.48068,2.4,0.24612, + 1.48068,2.4,0.24612, 1.554467,2.242575,0.258385, 1.57475,2.242575,0, + 0.270404,2.0856,1.626774, 0.258385,2.242575,1.554467, 0,2.242575,1.57475, + 0,2.242575,1.57475, 0,2.0856,1.648, 0.270404,2.0856,1.626774, + 0.525778,2.0856,1.565204, 0.502408,2.242575,1.495635, 0.258385,2.242575,1.554467, + 0.258385,2.242575,1.554467, 0.270404,2.0856,1.626774, 0.525778,2.0856,1.565204, + 0.762958,2.0856,1.466456, 0.729046,2.242575,1.401276, 0.502408,2.242575,1.495635, + 0.502408,2.242575,1.495635, 0.525778,2.0856,1.565204, 0.762958,2.0856,1.466456, + 0.97878,2.0856,1.333693, 0.935276,2.242575,1.274414, 0.729046,2.242575,1.401276, + 0.729046,2.242575,1.401276, 0.762958,2.0856,1.466456, 0.97878,2.0856,1.333693, + 1.17008,2.0856,1.17008, 1.118073,2.242575,1.118073, 0.935276,2.242575,1.274414, + 0.935276,2.242575,1.274414, 0.97878,2.0856,1.333693, 1.17008,2.0856,1.17008, + 1.333693,2.0856,0.97878, 1.274414,2.242575,0.935276, 1.118073,2.242575,1.118073, + 1.118073,2.242575,1.118073, 1.17008,2.0856,1.17008, 1.333693,2.0856,0.97878, + 1.466456,2.0856,0.762958, 1.401276,2.242575,0.729046, 1.274414,2.242575,0.935276, + 1.274414,2.242575,0.935276, 1.333693,2.0856,0.97878, 1.466456,2.0856,0.762958, + 1.565204,2.0856,0.525778, 1.495635,2.242575,0.502408, 1.401276,2.242575,0.729046, + 1.401276,2.242575,0.729046, 1.466456,2.0856,0.762958, 1.565204,2.0856,0.525778, + 1.626774,2.0856,0.270404, 1.554467,2.242575,0.258385, 1.495635,2.242575,0.502408, + 1.495635,2.242575,0.502408, 1.565204,2.0856,0.525778, 1.626774,2.0856,0.270404, + 1.648,2.0856,0, 1.57475,2.242575,0, 1.554467,2.242575,0.258385, + 1.554467,2.242575,0.258385, 1.626774,2.0856,0.270404, 1.648,2.0856,0, + 0.28193,1.929525,1.696119, 0.270404,2.0856,1.626774, 0,2.0856,1.648, + 0,2.0856,1.648, 0,1.929525,1.71825, 0.28193,1.929525,1.696119, + 0.54819,1.929525,1.631925, 0.525778,2.0856,1.565204, 0.270404,2.0856,1.626774, + 0.270404,2.0856,1.626774, 0.28193,1.929525,1.696119, 0.54819,1.929525,1.631925, + 0.795481,1.929525,1.528968, 0.762958,2.0856,1.466456, 0.525778,2.0856,1.565204, + 0.525778,2.0856,1.565204, 0.54819,1.929525,1.631925, 0.795481,1.929525,1.528968, + 1.020503,1.929525,1.390545, 0.97878,2.0856,1.333693, 0.762958,2.0856,1.466456, + 0.762958,2.0856,1.466456, 0.795481,1.929525,1.528968, 1.020503,1.929525,1.390545, + 1.219958,1.929525,1.219958, 1.17008,2.0856,1.17008, 0.97878,2.0856,1.333693, + 0.97878,2.0856,1.333693, 1.020503,1.929525,1.390545, 1.219958,1.929525,1.219958, + 1.390545,1.929525,1.020503, 1.333693,2.0856,0.97878, 1.17008,2.0856,1.17008, + 1.17008,2.0856,1.17008, 1.219958,1.929525,1.219958, 1.390545,1.929525,1.020503, + 1.528968,1.929525,0.795481, 1.466456,2.0856,0.762958, 1.333693,2.0856,0.97878, + 1.333693,2.0856,0.97878, 1.390545,1.929525,1.020503, 1.528968,1.929525,0.795481, + 1.631925,1.929525,0.54819, 1.565204,2.0856,0.525778, 1.466456,2.0856,0.762958, + 1.466456,2.0856,0.762958, 1.528968,1.929525,0.795481, 1.631925,1.929525,0.54819, + 1.696119,1.929525,0.28193, 1.626774,2.0856,0.270404, 1.565204,2.0856,0.525778, + 1.565204,2.0856,0.525778, 1.631925,1.929525,0.54819, 1.696119,1.929525,0.28193, + 1.71825,1.929525,0, 1.648,2.0856,0, 1.626774,2.0856,0.270404, + 1.626774,2.0856,0.270404, 1.696119,1.929525,0.28193, 1.71825,1.929525,0, + 0.292719,1.7748,1.761022, 0.28193,1.929525,1.696119, 0,1.929525,1.71825, + 0,1.929525,1.71825, 0,1.7748,1.784, 0.292719,1.7748,1.761022, + 0.569167,1.7748,1.694372, 0.54819,1.929525,1.631925, 0.28193,1.929525,1.696119, + 0.28193,1.929525,1.696119, 0.292719,1.7748,1.761022, 0.569167,1.7748,1.694372, + 0.825921,1.7748,1.587475, 0.795481,1.929525,1.528968, 0.54819,1.929525,1.631925, + 0.54819,1.929525,1.631925, 0.569167,1.7748,1.694372, 0.825921,1.7748,1.587475, + 1.059553,1.7748,1.443756, 1.020503,1.929525,1.390545, 0.795481,1.929525,1.528968, + 0.795481,1.929525,1.528968, 0.825921,1.7748,1.587475, 1.059553,1.7748,1.443756, + 1.26664,1.7748,1.26664, 1.219958,1.929525,1.219958, 1.020503,1.929525,1.390545, + 1.020503,1.929525,1.390545, 1.059553,1.7748,1.443756, 1.26664,1.7748,1.26664, + 1.443756,1.7748,1.059553, 1.390545,1.929525,1.020503, 1.219958,1.929525,1.219958, + 1.219958,1.929525,1.219958, 1.26664,1.7748,1.26664, 1.443756,1.7748,1.059553, + 1.587475,1.7748,0.825921, 1.528968,1.929525,0.795481, 1.390545,1.929525,1.020503, + 1.390545,1.929525,1.020503, 1.443756,1.7748,1.059553, 1.587475,1.7748,0.825921, + 1.694372,1.7748,0.569167, 1.631925,1.929525,0.54819, 1.528968,1.929525,0.795481, + 1.528968,1.929525,0.795481, 1.587475,1.7748,0.825921, 1.694372,1.7748,0.569167, + 1.761022,1.7748,0.292719, 1.696119,1.929525,0.28193, 1.631925,1.929525,0.54819, + 1.631925,1.929525,0.54819, 1.694372,1.7748,0.569167, 1.761022,1.7748,0.292719, + 1.784,1.7748,0, 1.71825,1.929525,0, 1.696119,1.929525,0.28193, + 1.696119,1.929525,0.28193, 1.761022,1.7748,0.292719, 1.784,1.7748,0, + 0.302523,1.621875,1.820003, 0.292719,1.7748,1.761022, 0,1.7748,1.784, + 0,1.7748,1.784, 0,1.621875,1.84375, 0.302523,1.621875,1.820003, + 0.58823,1.621875,1.75112, 0.569167,1.7748,1.694372, 0.292719,1.7748,1.761022, + 0.292719,1.7748,1.761022, 0.302523,1.621875,1.820003, 0.58823,1.621875,1.75112, + 0.853583,1.621875,1.640643, 0.825921,1.7748,1.587475, 0.569167,1.7748,1.694372, + 0.569167,1.7748,1.694372, 0.58823,1.621875,1.75112, 0.853583,1.621875,1.640643, + 1.09504,1.621875,1.49211, 1.059553,1.7748,1.443756, 0.825921,1.7748,1.587475, + 0.825921,1.7748,1.587475, 0.853583,1.621875,1.640643, 1.09504,1.621875,1.49211, + 1.309063,1.621875,1.309063, 1.26664,1.7748,1.26664, 1.059553,1.7748,1.443756, + 1.059553,1.7748,1.443756, 1.09504,1.621875,1.49211, 1.309063,1.621875,1.309063, + 1.49211,1.621875,1.09504, 1.443756,1.7748,1.059553, 1.26664,1.7748,1.26664, + 1.26664,1.7748,1.26664, 1.309063,1.621875,1.309063, 1.49211,1.621875,1.09504, + 1.640643,1.621875,0.853583, 1.587475,1.7748,0.825921, 1.443756,1.7748,1.059553, + 1.443756,1.7748,1.059553, 1.49211,1.621875,1.09504, 1.640643,1.621875,0.853583, + 1.75112,1.621875,0.58823, 1.694372,1.7748,0.569167, 1.587475,1.7748,0.825921, + 1.587475,1.7748,0.825921, 1.640643,1.621875,0.853583, 1.75112,1.621875,0.58823, + 1.820003,1.621875,0.302522, 1.761022,1.7748,0.292719, 1.694372,1.7748,0.569167, + 1.694372,1.7748,0.569167, 1.75112,1.621875,0.58823, 1.820003,1.621875,0.302522, + 1.84375,1.621875,0, 1.784,1.7748,0, 1.761022,1.7748,0.292719, + 1.761022,1.7748,0.292719, 1.820003,1.621875,0.302522, 1.84375,1.621875,0, + 0.311096,1.4712,1.87158, 0.302523,1.621875,1.820003, 0,1.621875,1.84375, + 0,1.621875,1.84375, 0,1.4712,1.896, 0.311096,1.4712,1.87158, + 0.6049,1.4712,1.800745, 0.58823,1.621875,1.75112, 0.302523,1.621875,1.820003, + 0.302523,1.621875,1.820003, 0.311096,1.4712,1.87158, 0.6049,1.4712,1.800745, + 0.877772,1.4712,1.687137, 0.853583,1.621875,1.640643, 0.58823,1.621875,1.75112, + 0.58823,1.621875,1.75112, 0.6049,1.4712,1.800745, 0.877772,1.4712,1.687137, + 1.126072,1.4712,1.534395, 1.09504,1.621875,1.49211, 0.853583,1.621875,1.640643, + 0.853583,1.621875,1.640643, 0.877772,1.4712,1.687137, 1.126072,1.4712,1.534395, + 1.34616,1.4712,1.34616, 1.309063,1.621875,1.309063, 1.09504,1.621875,1.49211, + 1.09504,1.621875,1.49211, 1.126072,1.4712,1.534395, 1.34616,1.4712,1.34616, + 1.534395,1.4712,1.126072, 1.49211,1.621875,1.09504, 1.309063,1.621875,1.309063, + 1.309063,1.621875,1.309063, 1.34616,1.4712,1.34616, 1.534395,1.4712,1.126072, + 1.687137,1.4712,0.877772, 1.640643,1.621875,0.853583, 1.49211,1.621875,1.09504, + 1.49211,1.621875,1.09504, 1.534395,1.4712,1.126072, 1.687137,1.4712,0.877772, + 1.800745,1.4712,0.6049, 1.75112,1.621875,0.58823, 1.640643,1.621875,0.853583, + 1.640643,1.621875,0.853583, 1.687137,1.4712,0.877772, 1.800745,1.4712,0.6049, + 1.87158,1.4712,0.311096, 1.820003,1.621875,0.302522, 1.75112,1.621875,0.58823, + 1.75112,1.621875,0.58823, 1.800745,1.4712,0.6049, 1.87158,1.4712,0.311096, + 1.896,1.4712,0, 1.84375,1.621875,0, 1.820003,1.621875,0.302522, + 1.820003,1.621875,0.302522, 1.87158,1.4712,0.311096, 1.896,1.4712,0, + 0.318192,1.323225,1.914272, 0.311096,1.4712,1.87158, 0,1.4712,1.896, + 0,1.4712,1.896, 0,1.323225,1.93925, 0.318192,1.323225,1.914272, + 0.618698,1.323225,1.841822, 0.6049,1.4712,1.800745, 0.311096,1.4712,1.87158, + 0.311096,1.4712,1.87158, 0.318192,1.323225,1.914272, 0.618698,1.323225,1.841822, + 0.897795,1.323225,1.725622, 0.877772,1.4712,1.687137, 0.6049,1.4712,1.800745, + 0.6049,1.4712,1.800745, 0.618698,1.323225,1.841822, 0.897795,1.323225,1.725622, + 1.151759,1.323225,1.569396, 1.126072,1.4712,1.534395, 0.877772,1.4712,1.687137, + 0.877772,1.4712,1.687137, 0.897795,1.323225,1.725622, 1.151759,1.323225,1.569396, + 1.376868,1.323225,1.376867, 1.34616,1.4712,1.34616, 1.126072,1.4712,1.534395, + 1.126072,1.4712,1.534395, 1.151759,1.323225,1.569396, 1.376868,1.323225,1.376867, + 1.569396,1.323225,1.151759, 1.534395,1.4712,1.126072, 1.34616,1.4712,1.34616, + 1.34616,1.4712,1.34616, 1.376868,1.323225,1.376867, 1.569396,1.323225,1.151759, + 1.725622,1.323225,0.897795, 1.687137,1.4712,0.877772, 1.534395,1.4712,1.126072, + 1.534395,1.4712,1.126072, 1.569396,1.323225,1.151759, 1.725622,1.323225,0.897795, + 1.841822,1.323225,0.618698, 1.800745,1.4712,0.6049, 1.687137,1.4712,0.877772, + 1.687137,1.4712,0.877772, 1.725622,1.323225,0.897795, 1.841822,1.323225,0.618698, + 1.914272,1.323225,0.318192, 1.87158,1.4712,0.311096, 1.800745,1.4712,0.6049, + 1.800745,1.4712,0.6049, 1.841822,1.323225,0.618698, 1.914272,1.323225,0.318192, + 1.93925,1.323225,0, 1.896,1.4712,0, 1.87158,1.4712,0.311096, + 1.87158,1.4712,0.311096, 1.914272,1.323225,0.318192, 1.93925,1.323225,0, + 0.323566,1.1784,1.946601, 0.318192,1.323225,1.914272, 0,1.323225,1.93925, + 0,1.323225,1.93925, 0,1.1784,1.972, 0.323566,1.1784,1.946601, + 0.629147,1.1784,1.872927, 0.618698,1.323225,1.841822, 0.318192,1.323225,1.914272, + 0.318192,1.323225,1.914272, 0.323566,1.1784,1.946601, 0.629147,1.1784,1.872927, + 0.912957,1.1784,1.754764, 0.897795,1.323225,1.725622, 0.618698,1.323225,1.841822, + 0.618698,1.323225,1.841822, 0.629147,1.1784,1.872927, 0.912957,1.1784,1.754764, + 1.17121,1.1784,1.5959, 1.151759,1.323225,1.569396, 0.897795,1.323225,1.725622, + 0.897795,1.323225,1.725622, 0.912957,1.1784,1.754764, 1.17121,1.1784,1.5959, + 1.40012,1.1784,1.40012, 1.376868,1.323225,1.376867, 1.151759,1.323225,1.569396, + 1.151759,1.323225,1.569396, 1.17121,1.1784,1.5959, 1.40012,1.1784,1.40012, + 1.5959,1.1784,1.17121, 1.569396,1.323225,1.151759, 1.376868,1.323225,1.376867, + 1.376868,1.323225,1.376867, 1.40012,1.1784,1.40012, 1.5959,1.1784,1.17121, + 1.754764,1.1784,0.912957, 1.725622,1.323225,0.897795, 1.569396,1.323225,1.151759, + 1.569396,1.323225,1.151759, 1.5959,1.1784,1.17121, 1.754764,1.1784,0.912957, + 1.872927,1.1784,0.629147, 1.841822,1.323225,0.618698, 1.725622,1.323225,0.897795, + 1.725622,1.323225,0.897795, 1.754764,1.1784,0.912957, 1.872927,1.1784,0.629147, + 1.946601,1.1784,0.323566, 1.914272,1.323225,0.318192, 1.841822,1.323225,0.618698, + 1.841822,1.323225,0.618698, 1.872927,1.1784,0.629147, 1.946601,1.1784,0.323566, + 1.972,1.1784,0, 1.93925,1.323225,0, 1.914272,1.323225,0.318192, + 1.914272,1.323225,0.318192, 1.946601,1.1784,0.323566, 1.972,1.1784,0, + 0.32697,1.037175,1.967083, 0.323566,1.1784,1.946601, 0,1.1784,1.972, + 0,1.1784,1.972, 0,1.037175,1.99275, 0.32697,1.037175,1.967083, + 0.635767,1.037175,1.892634, 0.629147,1.1784,1.872927, 0.323566,1.1784,1.946601, + 0.323566,1.1784,1.946601, 0.32697,1.037175,1.967083, 0.635767,1.037175,1.892634, + 0.922564,1.037175,1.773229, 0.912957,1.1784,1.754764, 0.629147,1.1784,1.872927, + 0.629147,1.1784,1.872927, 0.635767,1.037175,1.892634, 0.922564,1.037175,1.773229, + 1.183534,1.037175,1.612693, 1.17121,1.1784,1.5959, 0.912957,1.1784,1.754764, + 0.912957,1.1784,1.754764, 0.922564,1.037175,1.773229, 1.183534,1.037175,1.612693, + 1.414853,1.037175,1.414853, 1.40012,1.1784,1.40012, 1.17121,1.1784,1.5959, + 1.17121,1.1784,1.5959, 1.183534,1.037175,1.612693, 1.414853,1.037175,1.414853, + 1.612693,1.037175,1.183534, 1.5959,1.1784,1.17121, 1.40012,1.1784,1.40012, + 1.40012,1.1784,1.40012, 1.414853,1.037175,1.414853, 1.612693,1.037175,1.183534, + 1.773229,1.037175,0.922564, 1.754764,1.1784,0.912957, 1.5959,1.1784,1.17121, + 1.5959,1.1784,1.17121, 1.612693,1.037175,1.183534, 1.773229,1.037175,0.922564, + 1.892634,1.037175,0.635767, 1.872927,1.1784,0.629147, 1.754764,1.1784,0.912957, + 1.754764,1.1784,0.912957, 1.773229,1.037175,0.922564, 1.892634,1.037175,0.635767, + 1.967083,1.037175,0.32697, 1.946601,1.1784,0.323566, 1.872927,1.1784,0.629147, + 1.872927,1.1784,0.629147, 1.892634,1.037175,0.635767, 1.967083,1.037175,0.32697, + 1.99275,1.037175,0, 1.972,1.1784,0, 1.946601,1.1784,0.323566, + 1.946601,1.1784,0.323566, 1.967083,1.037175,0.32697, 1.99275,1.037175,0, + 0.32816,0.9,1.97424, 0.32697,1.037175,1.967083, 0,1.037175,1.99275, + 0,1.037175,1.99275, 0,0.9,2, 0.32816,0.9,1.97424, + 0.63808,0.9,1.89952, 0.635767,1.037175,1.892634, 0.32697,1.037175,1.967083, + 0.32697,1.037175,1.967083, 0.32816,0.9,1.97424, 0.63808,0.9,1.89952, + 0.92592,0.9,1.77968, 0.922564,1.037175,1.773229, 0.635767,1.037175,1.892634, + 0.635767,1.037175,1.892634, 0.63808,0.9,1.89952, 0.92592,0.9,1.77968, + 1.18784,0.9,1.61856, 1.183534,1.037175,1.612693, 0.922564,1.037175,1.773229, + 0.922564,1.037175,1.773229, 0.92592,0.9,1.77968, 1.18784,0.9,1.61856, + 1.42,0.9,1.42, 1.414853,1.037175,1.414853, 1.183534,1.037175,1.612693, + 1.183534,1.037175,1.612693, 1.18784,0.9,1.61856, 1.42,0.9,1.42, + 1.61856,0.9,1.18784, 1.612693,1.037175,1.183534, 1.414853,1.037175,1.414853, + 1.414853,1.037175,1.414853, 1.42,0.9,1.42, 1.61856,0.9,1.18784, + 1.77968,0.9,0.92592, 1.773229,1.037175,0.922564, 1.612693,1.037175,1.183534, + 1.612693,1.037175,1.183534, 1.61856,0.9,1.18784, 1.77968,0.9,0.92592, + 1.89952,0.9,0.63808, 1.892634,1.037175,0.635767, 1.773229,1.037175,0.922564, + 1.773229,1.037175,0.922564, 1.77968,0.9,0.92592, 1.89952,0.9,0.63808, + 1.97424,0.9,0.32816, 1.967083,1.037175,0.32697, 1.892634,1.037175,0.635767, + 1.892634,1.037175,0.635767, 1.89952,0.9,0.63808, 1.97424,0.9,0.32816, + 2,0.9,0, 1.99275,1.037175,0, 1.967083,1.037175,0.32697, + 1.967083,1.037175,0.32697, 1.97424,0.9,0.32816, 2,0.9,0, + 1.96042,0.771675,-0.325863, 1.97424,0.9,-0.32816, 2,0.9,0, + 2,0.9,0, 1.986,0.771675,0, 1.96042,0.771675,-0.325863, + 1.886223,0.771675,-0.633613, 1.89952,0.9,-0.63808, 1.97424,0.9,-0.32816, + 1.97424,0.9,-0.32816, 1.96042,0.771675,-0.325863, 1.886223,0.771675,-0.633613, + 1.767222,0.771675,-0.919439, 1.77968,0.9,-0.92592, 1.89952,0.9,-0.63808, + 1.89952,0.9,-0.63808, 1.886223,0.771675,-0.633613, 1.767222,0.771675,-0.919439, + 1.60723,0.771675,-1.179525, 1.61856,0.9,-1.18784, 1.77968,0.9,-0.92592, + 1.77968,0.9,-0.92592, 1.767222,0.771675,-0.919439, 1.60723,0.771675,-1.179525, + 1.41006,0.771675,-1.41006, 1.42,0.9,-1.42, 1.61856,0.9,-1.18784, + 1.61856,0.9,-1.18784, 1.60723,0.771675,-1.179525, 1.41006,0.771675,-1.41006, + 1.179525,0.771675,-1.60723, 1.18784,0.9,-1.61856, 1.42,0.9,-1.42, + 1.42,0.9,-1.42, 1.41006,0.771675,-1.41006, 1.179525,0.771675,-1.60723, + 0.919439,0.771675,-1.767222, 0.92592,0.9,-1.77968, 1.18784,0.9,-1.61856, + 1.18784,0.9,-1.61856, 1.179525,0.771675,-1.60723, 0.919439,0.771675,-1.767222, + 0.633613,0.771675,-1.886223, 0.63808,0.9,-1.89952, 0.92592,0.9,-1.77968, + 0.92592,0.9,-1.77968, 0.919439,0.771675,-1.767222, 0.633613,0.771675,-1.886223, + 0.325863,0.771675,-1.96042, 0.32816,0.9,-1.97424, 0.63808,0.9,-1.89952, + 0.63808,0.9,-1.89952, 0.633613,0.771675,-1.886223, 0.325863,0.771675,-1.96042, + 0,0.771675,-1.986, 0,0.9,-2, 0.32816,0.9,-1.97424, + 0.32816,0.9,-1.97424, 0.325863,0.771675,-1.96042, 0,0.771675,-1.986, + 1.92291,0.6564,-0.319628, 1.96042,0.771675,-0.325863, 1.986,0.771675,0, + 1.986,0.771675,0, 1.948,0.6564,0, 1.92291,0.6564,-0.319628, + 1.850132,0.6564,-0.62149, 1.886223,0.771675,-0.633613, 1.96042,0.771675,-0.325863, + 1.96042,0.771675,-0.325863, 1.92291,0.6564,-0.319628, 1.850132,0.6564,-0.62149, + 1.733408,0.6564,-0.901846, 1.767222,0.771675,-0.919439, 1.886223,0.771675,-0.633613, + 1.886223,0.771675,-0.633613, 1.850132,0.6564,-0.62149, 1.733408,0.6564,-0.901846, + 1.576477,0.6564,-1.156956, 1.60723,0.771675,-1.179525, 1.767222,0.771675,-0.919439, + 1.767222,0.771675,-0.919439, 1.733408,0.6564,-0.901846, 1.576477,0.6564,-1.156956, + 1.38308,0.6564,-1.38308, 1.41006,0.771675,-1.41006, 1.60723,0.771675,-1.179525, + 1.60723,0.771675,-1.179525, 1.576477,0.6564,-1.156956, 1.38308,0.6564,-1.38308, + 1.156956,0.6564,-1.576477, 1.179525,0.771675,-1.60723, 1.41006,0.771675,-1.41006, + 1.41006,0.771675,-1.41006, 1.38308,0.6564,-1.38308, 1.156956,0.6564,-1.576477, + 0.901846,0.6564,-1.733408, 0.919439,0.771675,-1.767222, 1.179525,0.771675,-1.60723, + 1.179525,0.771675,-1.60723, 1.156956,0.6564,-1.576477, 0.901846,0.6564,-1.733408, + 0.62149,0.6564,-1.850132, 0.633613,0.771675,-1.886223, 0.919439,0.771675,-1.767222, + 0.919439,0.771675,-1.767222, 0.901846,0.6564,-1.733408, 0.62149,0.6564,-1.850132, + 0.319628,0.6564,-1.92291, 0.325863,0.771675,-1.96042, 0.633613,0.771675,-1.886223, + 0.633613,0.771675,-1.886223, 0.62149,0.6564,-1.850132, 0.319628,0.6564,-1.92291, + 0,0.6564,-1.948, 0,0.771675,-1.986, 0.325863,0.771675,-1.96042, + 0.325863,0.771675,-1.96042, 0.319628,0.6564,-1.92291, 0,0.6564,-1.948, + 1.867631,0.553725,-0.310439, 1.92291,0.6564,-0.319628, 1.948,0.6564,0, + 1.948,0.6564,0, 1.892,0.553725,0, 1.867631,0.553725,-0.310439, + 1.796946,0.553725,-0.603624, 1.850132,0.6564,-0.62149, 1.92291,0.6564,-0.319628, + 1.92291,0.6564,-0.319628, 1.867631,0.553725,-0.310439, 1.796946,0.553725,-0.603624, + 1.683577,0.553725,-0.87592, 1.733408,0.6564,-0.901846, 1.850132,0.6564,-0.62149, + 1.850132,0.6564,-0.62149, 1.796946,0.553725,-0.603624, 1.683577,0.553725,-0.87592, + 1.531158,0.553725,-1.123697, 1.576477,0.6564,-1.156956, 1.733408,0.6564,-0.901846, + 1.733408,0.6564,-0.901846, 1.683577,0.553725,-0.87592, 1.531158,0.553725,-1.123697, + 1.34332,0.553725,-1.34332, 1.38308,0.6564,-1.38308, 1.576477,0.6564,-1.156956, + 1.576477,0.6564,-1.156956, 1.531158,0.553725,-1.123697, 1.34332,0.553725,-1.34332, + 1.123697,0.553725,-1.531158, 1.156956,0.6564,-1.576477, 1.38308,0.6564,-1.38308, + 1.38308,0.6564,-1.38308, 1.34332,0.553725,-1.34332, 1.123697,0.553725,-1.531158, + 0.87592,0.553725,-1.683577, 0.901846,0.6564,-1.733408, 1.156956,0.6564,-1.576477, + 1.156956,0.6564,-1.576477, 1.123697,0.553725,-1.531158, 0.87592,0.553725,-1.683577, + 0.603624,0.553725,-1.796946, 0.62149,0.6564,-1.850132, 0.901846,0.6564,-1.733408, + 0.901846,0.6564,-1.733408, 0.87592,0.553725,-1.683577, 0.603624,0.553725,-1.796946, + 0.310439,0.553725,-1.867631, 0.319628,0.6564,-1.92291, 0.62149,0.6564,-1.850132, + 0.62149,0.6564,-1.850132, 0.603624,0.553725,-1.796946, 0.310439,0.553725,-1.867631, + 0,0.553725,-1.892, 0,0.6564,-1.948, 0.319628,0.6564,-1.92291, + 0.319628,0.6564,-1.92291, 0.310439,0.553725,-1.867631, 0,0.553725,-1.892, + 1.800507,0.4632,-0.299282, 1.867631,0.553725,-0.310439, 1.892,0.553725,0, + 1.892,0.553725,0, 1.824,0.4632,0, 1.800507,0.4632,-0.299282, + 1.732362,0.4632,-0.581929, 1.796946,0.553725,-0.603624, 1.867631,0.553725,-0.310439, + 1.867631,0.553725,-0.310439, 1.800507,0.4632,-0.299282, 1.732362,0.4632,-0.581929, + 1.623068,0.4632,-0.844439, 1.683577,0.553725,-0.87592, 1.796946,0.553725,-0.603624, + 1.796946,0.553725,-0.603624, 1.732362,0.4632,-0.581929, 1.623068,0.4632,-0.844439, + 1.476127,0.4632,-1.08331, 1.531158,0.553725,-1.123697, 1.683577,0.553725,-0.87592, + 1.683577,0.553725,-0.87592, 1.623068,0.4632,-0.844439, 1.476127,0.4632,-1.08331, + 1.29504,0.4632,-1.29504, 1.34332,0.553725,-1.34332, 1.531158,0.553725,-1.123697, + 1.531158,0.553725,-1.123697, 1.476127,0.4632,-1.08331, 1.29504,0.4632,-1.29504, + 1.08331,0.4632,-1.476127, 1.123697,0.553725,-1.531158, 1.34332,0.553725,-1.34332, + 1.34332,0.553725,-1.34332, 1.29504,0.4632,-1.29504, 1.08331,0.4632,-1.476127, + 0.844439,0.4632,-1.623068, 0.87592,0.553725,-1.683577, 1.123697,0.553725,-1.531158, + 1.123697,0.553725,-1.531158, 1.08331,0.4632,-1.476127, 0.844439,0.4632,-1.623068, + 0.581929,0.4632,-1.732362, 0.603624,0.553725,-1.796946, 0.87592,0.553725,-1.683577, + 0.87592,0.553725,-1.683577, 0.844439,0.4632,-1.623068, 0.581929,0.4632,-1.732362, + 0.299282,0.4632,-1.800507, 0.310439,0.553725,-1.867631, 0.603624,0.553725,-1.796946, + 0.603624,0.553725,-1.796946, 0.581929,0.4632,-1.732362, 0.299282,0.4632,-1.800507, + 0,0.4632,-1.824, 0,0.553725,-1.892, 0.310439,0.553725,-1.867631, + 0.310439,0.553725,-1.867631, 0.299282,0.4632,-1.800507, 0,0.4632,-1.824, + 1.72746,0.384375,-0.28714, 1.800507,0.4632,-0.299282, 1.824,0.4632,0, + 1.824,0.4632,0, 1.75,0.384375,0, 1.72746,0.384375,-0.28714, + 1.66208,0.384375,-0.55832, 1.732362,0.4632,-0.581929, 1.800507,0.4632,-0.299282, + 1.800507,0.4632,-0.299282, 1.72746,0.384375,-0.28714, 1.66208,0.384375,-0.55832, + 1.55722,0.384375,-0.81018, 1.623068,0.4632,-0.844439, 1.732362,0.4632,-0.581929, + 1.732362,0.4632,-0.581929, 1.66208,0.384375,-0.55832, 1.55722,0.384375,-0.81018, + 1.41624,0.384375,-1.03936, 1.476127,0.4632,-1.08331, 1.623068,0.4632,-0.844439, + 1.623068,0.4632,-0.844439, 1.55722,0.384375,-0.81018, 1.41624,0.384375,-1.03936, + 1.2425,0.384375,-1.2425, 1.29504,0.4632,-1.29504, 1.476127,0.4632,-1.08331, + 1.476127,0.4632,-1.08331, 1.41624,0.384375,-1.03936, 1.2425,0.384375,-1.2425, + 1.03936,0.384375,-1.41624, 1.08331,0.4632,-1.476127, 1.29504,0.4632,-1.29504, + 1.29504,0.4632,-1.29504, 1.2425,0.384375,-1.2425, 1.03936,0.384375,-1.41624, + 0.81018,0.384375,-1.55722, 0.844439,0.4632,-1.623068, 1.08331,0.4632,-1.476127, + 1.08331,0.4632,-1.476127, 1.03936,0.384375,-1.41624, 0.81018,0.384375,-1.55722, + 0.55832,0.384375,-1.66208, 0.581929,0.4632,-1.732362, 0.844439,0.4632,-1.623068, + 0.844439,0.4632,-1.623068, 0.81018,0.384375,-1.55722, 0.55832,0.384375,-1.66208, + 0.28714,0.384375,-1.72746, 0.299282,0.4632,-1.800507, 0.581929,0.4632,-1.732362, + 0.581929,0.4632,-1.732362, 0.55832,0.384375,-1.66208, 0.28714,0.384375,-1.72746, + 0,0.384375,-1.75, 0,0.4632,-1.824, 0.299282,0.4632,-1.800507, + 0.299282,0.4632,-1.800507, 0.28714,0.384375,-1.72746, 0,0.384375,-1.75, + 1.654413,0.3168,-0.274998, 1.72746,0.384375,-0.28714, 1.75,0.384375,0, + 1.75,0.384375,0, 1.676,0.3168,0, 1.654413,0.3168,-0.274998, + 1.591798,0.3168,-0.534711, 1.66208,0.384375,-0.55832, 1.72746,0.384375,-0.28714, + 1.72746,0.384375,-0.28714, 1.654413,0.3168,-0.274998, 1.591798,0.3168,-0.534711, + 1.491372,0.3168,-0.775921, 1.55722,0.384375,-0.81018, 1.66208,0.384375,-0.55832, + 1.66208,0.384375,-0.55832, 1.591798,0.3168,-0.534711, 1.491372,0.3168,-0.775921, + 1.356353,0.3168,-0.99541, 1.41624,0.384375,-1.03936, 1.55722,0.384375,-0.81018, + 1.55722,0.384375,-0.81018, 1.491372,0.3168,-0.775921, 1.356353,0.3168,-0.99541, + 1.18996,0.3168,-1.18996, 1.2425,0.384375,-1.2425, 1.41624,0.384375,-1.03936, + 1.41624,0.384375,-1.03936, 1.356353,0.3168,-0.99541, 1.18996,0.3168,-1.18996, + 0.99541,0.3168,-1.356353, 1.03936,0.384375,-1.41624, 1.2425,0.384375,-1.2425, + 1.2425,0.384375,-1.2425, 1.18996,0.3168,-1.18996, 0.99541,0.3168,-1.356353, + 0.775921,0.3168,-1.491372, 0.81018,0.384375,-1.55722, 1.03936,0.384375,-1.41624, + 1.03936,0.384375,-1.41624, 0.99541,0.3168,-1.356353, 0.775921,0.3168,-1.491372, + 0.534711,0.3168,-1.591798, 0.55832,0.384375,-1.66208, 0.81018,0.384375,-1.55722, + 0.81018,0.384375,-1.55722, 0.775921,0.3168,-1.491372, 0.534711,0.3168,-1.591798, + 0.274998,0.3168,-1.654413, 0.28714,0.384375,-1.72746, 0.55832,0.384375,-1.66208, + 0.55832,0.384375,-1.66208, 0.534711,0.3168,-1.591798, 0.274998,0.3168,-1.654413, + 0,0.3168,-1.676, 0,0.384375,-1.75, 0.28714,0.384375,-1.72746, + 0.28714,0.384375,-1.72746, 0.274998,0.3168,-1.654413, 0,0.3168,-1.676, + 1.587289,0.260025,-0.263841, 1.654413,0.3168,-0.274998, 1.676,0.3168,0, + 1.676,0.3168,0, 1.608,0.260025,0, 1.587289,0.260025,-0.263841, + 1.527214,0.260025,-0.513016, 1.591798,0.3168,-0.534711, 1.654413,0.3168,-0.274998, + 1.654413,0.3168,-0.274998, 1.587289,0.260025,-0.263841, 1.527214,0.260025,-0.513016, + 1.430863,0.260025,-0.74444, 1.491372,0.3168,-0.775921, 1.591798,0.3168,-0.534711, + 1.591798,0.3168,-0.534711, 1.527214,0.260025,-0.513016, 1.430863,0.260025,-0.74444, + 1.301322,0.260025,-0.955023, 1.356353,0.3168,-0.99541, 1.491372,0.3168,-0.775921, + 1.491372,0.3168,-0.775921, 1.430863,0.260025,-0.74444, 1.301322,0.260025,-0.955023, + 1.14168,0.260025,-1.14168, 1.18996,0.3168,-1.18996, 1.356353,0.3168,-0.99541, + 1.356353,0.3168,-0.99541, 1.301322,0.260025,-0.955023, 1.14168,0.260025,-1.14168, + 0.955023,0.260025,-1.301322, 0.99541,0.3168,-1.356353, 1.18996,0.3168,-1.18996, + 1.18996,0.3168,-1.18996, 1.14168,0.260025,-1.14168, 0.955023,0.260025,-1.301322, + 0.74444,0.260025,-1.430863, 0.775921,0.3168,-1.491372, 0.99541,0.3168,-1.356353, + 0.99541,0.3168,-1.356353, 0.955023,0.260025,-1.301322, 0.74444,0.260025,-1.430863, + 0.513016,0.260025,-1.527214, 0.534711,0.3168,-1.591798, 0.775921,0.3168,-1.491372, + 0.775921,0.3168,-1.491372, 0.74444,0.260025,-1.430863, 0.513016,0.260025,-1.527214, + 0.263841,0.260025,-1.587289, 0.274998,0.3168,-1.654413, 0.534711,0.3168,-1.591798, + 0.534711,0.3168,-1.591798, 0.513016,0.260025,-1.527214, 0.263841,0.260025,-1.587289, + 0,0.260025,-1.608, 0,0.3168,-1.676, 0.274998,0.3168,-1.654413, + 0.274998,0.3168,-1.654413, 0.263841,0.260025,-1.587289, 0,0.260025,-1.608, + 1.53201,0.2136,-0.254652, 1.587289,0.260025,-0.263841, 1.608,0.260025,0, + 1.608,0.260025,0, 1.552,0.2136,0, 1.53201,0.2136,-0.254652, + 1.474028,0.2136,-0.49515, 1.527214,0.260025,-0.513016, 1.587289,0.260025,-0.263841, + 1.587289,0.260025,-0.263841, 1.53201,0.2136,-0.254652, 1.474028,0.2136,-0.49515, + 1.381032,0.2136,-0.718514, 1.430863,0.260025,-0.74444, 1.527214,0.260025,-0.513016, + 1.527214,0.260025,-0.513016, 1.474028,0.2136,-0.49515, 1.381032,0.2136,-0.718514, + 1.256003,0.2136,-0.921764, 1.301322,0.260025,-0.955023, 1.430863,0.260025,-0.74444, + 1.430863,0.260025,-0.74444, 1.381032,0.2136,-0.718514, 1.256003,0.2136,-0.921764, + 1.10192,0.2136,-1.10192, 1.14168,0.260025,-1.14168, 1.301322,0.260025,-0.955023, + 1.301322,0.260025,-0.955023, 1.256003,0.2136,-0.921764, 1.10192,0.2136,-1.10192, + 0.921764,0.2136,-1.256003, 0.955023,0.260025,-1.301322, 1.14168,0.260025,-1.14168, + 1.14168,0.260025,-1.14168, 1.10192,0.2136,-1.10192, 0.921764,0.2136,-1.256003, + 0.718514,0.2136,-1.381032, 0.74444,0.260025,-1.430863, 0.955023,0.260025,-1.301322, + 0.955023,0.260025,-1.301322, 0.921764,0.2136,-1.256003, 0.718514,0.2136,-1.381032, + 0.49515,0.2136,-1.474028, 0.513016,0.260025,-1.527214, 0.74444,0.260025,-1.430863, + 0.74444,0.260025,-1.430863, 0.718514,0.2136,-1.381032, 0.49515,0.2136,-1.474028, + 0.254652,0.2136,-1.53201, 0.263841,0.260025,-1.587289, 0.513016,0.260025,-1.527214, + 0.513016,0.260025,-1.527214, 0.49515,0.2136,-1.474028, 0.254652,0.2136,-1.53201, + 0,0.2136,-1.552, 0,0.260025,-1.608, 0.263841,0.260025,-1.587289, + 0.263841,0.260025,-1.587289, 0.254652,0.2136,-1.53201, 0,0.2136,-1.552, + 1.4945,0.177075,-0.248417, 1.53201,0.2136,-0.254652, 1.552,0.2136,0, + 1.552,0.2136,0, 1.514,0.177075,0, 1.4945,0.177075,-0.248417, + 1.437937,0.177075,-0.483027, 1.474028,0.2136,-0.49515, 1.53201,0.2136,-0.254652, + 1.53201,0.2136,-0.254652, 1.4945,0.177075,-0.248417, 1.437937,0.177075,-0.483027, + 1.347218,0.177075,-0.700921, 1.381032,0.2136,-0.718514, 1.474028,0.2136,-0.49515, + 1.474028,0.2136,-0.49515, 1.437937,0.177075,-0.483027, 1.347218,0.177075,-0.700921, + 1.22525,0.177075,-0.899195, 1.256003,0.2136,-0.921764, 1.381032,0.2136,-0.718514, + 1.381032,0.2136,-0.718514, 1.347218,0.177075,-0.700921, 1.22525,0.177075,-0.899195, + 1.07494,0.177075,-1.07494, 1.10192,0.2136,-1.10192, 1.256003,0.2136,-0.921764, + 1.256003,0.2136,-0.921764, 1.22525,0.177075,-0.899195, 1.07494,0.177075,-1.07494, + 0.899195,0.177075,-1.22525, 0.921764,0.2136,-1.256003, 1.10192,0.2136,-1.10192, + 1.10192,0.2136,-1.10192, 1.07494,0.177075,-1.07494, 0.899195,0.177075,-1.22525, + 0.700921,0.177075,-1.347218, 0.718514,0.2136,-1.381032, 0.921764,0.2136,-1.256003, + 0.921764,0.2136,-1.256003, 0.899195,0.177075,-1.22525, 0.700921,0.177075,-1.347218, + 0.483027,0.177075,-1.437937, 0.49515,0.2136,-1.474028, 0.718514,0.2136,-1.381032, + 0.718514,0.2136,-1.381032, 0.700921,0.177075,-1.347218, 0.483027,0.177075,-1.437937, + 0.248417,0.177075,-1.4945, 0.254652,0.2136,-1.53201, 0.49515,0.2136,-1.474028, + 0.49515,0.2136,-1.474028, 0.483027,0.177075,-1.437937, 0.248417,0.177075,-1.4945, + 0,0.177075,-1.514, 0,0.2136,-1.552, 0.254652,0.2136,-1.53201, + 0.254652,0.2136,-1.53201, 0.248417,0.177075,-1.4945, 0,0.177075,-1.514, + 1.48068,0.15,-0.24612, 1.4945,0.177075,-0.248417, 1.514,0.177075,0, + 1.514,0.177075,0, 1.5,0.15,0, 1.48068,0.15,-0.24612, + 1.42464,0.15,-0.47856, 1.437937,0.177075,-0.483027, 1.4945,0.177075,-0.248417, + 1.4945,0.177075,-0.248417, 1.48068,0.15,-0.24612, 1.42464,0.15,-0.47856, + 1.33476,0.15,-0.69444, 1.347218,0.177075,-0.700921, 1.437937,0.177075,-0.483027, + 1.437937,0.177075,-0.483027, 1.42464,0.15,-0.47856, 1.33476,0.15,-0.69444, + 1.21392,0.15,-0.89088, 1.22525,0.177075,-0.899195, 1.347218,0.177075,-0.700921, + 1.347218,0.177075,-0.700921, 1.33476,0.15,-0.69444, 1.21392,0.15,-0.89088, + 1.065,0.15,-1.065, 1.07494,0.177075,-1.07494, 1.22525,0.177075,-0.899195, + 1.22525,0.177075,-0.899195, 1.21392,0.15,-0.89088, 1.065,0.15,-1.065, + 0.89088,0.15,-1.21392, 0.899195,0.177075,-1.22525, 1.07494,0.177075,-1.07494, + 1.07494,0.177075,-1.07494, 1.065,0.15,-1.065, 0.89088,0.15,-1.21392, + 0.69444,0.15,-1.33476, 0.700921,0.177075,-1.347218, 0.899195,0.177075,-1.22525, + 0.899195,0.177075,-1.22525, 0.89088,0.15,-1.21392, 0.69444,0.15,-1.33476, + 0.47856,0.15,-1.42464, 0.483027,0.177075,-1.437937, 0.700921,0.177075,-1.347218, + 0.700921,0.177075,-1.347218, 0.69444,0.15,-1.33476, 0.47856,0.15,-1.42464, + 0.24612,0.15,-1.48068, 0.248417,0.177075,-1.4945, 0.483027,0.177075,-1.437937, + 0.483027,0.177075,-1.437937, 0.47856,0.15,-1.42464, 0.24612,0.15,-1.48068, + 0,0.15,-1.5, 0,0.177075,-1.514, 0.248417,0.177075,-1.4945, + 0.248417,0.177075,-1.4945, 0.24612,0.15,-1.48068, 0,0.15,-1.5, + -0.325863,0.771675,-1.96042, -0.32816,0.9,-1.97424, 0,0.9,-2, + 0,0.9,-2, 0,0.771675,-1.986, -0.325863,0.771675,-1.96042, + -0.633613,0.771675,-1.886223, -0.63808,0.9,-1.89952, -0.32816,0.9,-1.97424, + -0.32816,0.9,-1.97424, -0.325863,0.771675,-1.96042, -0.633613,0.771675,-1.886223, + -0.919439,0.771675,-1.767222, -0.92592,0.9,-1.77968, -0.63808,0.9,-1.89952, + -0.63808,0.9,-1.89952, -0.633613,0.771675,-1.886223, -0.919439,0.771675,-1.767222, + -1.179525,0.771675,-1.60723, -1.18784,0.9,-1.61856, -0.92592,0.9,-1.77968, + -0.92592,0.9,-1.77968, -0.919439,0.771675,-1.767222, -1.179525,0.771675,-1.60723, + -1.41006,0.771675,-1.41006, -1.42,0.9,-1.42, -1.18784,0.9,-1.61856, + -1.18784,0.9,-1.61856, -1.179525,0.771675,-1.60723, -1.41006,0.771675,-1.41006, + -1.60723,0.771675,-1.179525, -1.61856,0.9,-1.18784, -1.42,0.9,-1.42, + -1.42,0.9,-1.42, -1.41006,0.771675,-1.41006, -1.60723,0.771675,-1.179525, + -1.767222,0.771675,-0.919439, -1.77968,0.9,-0.92592, -1.61856,0.9,-1.18784, + -1.61856,0.9,-1.18784, -1.60723,0.771675,-1.179525, -1.767222,0.771675,-0.919439, + -1.886223,0.771675,-0.633613, -1.89952,0.9,-0.63808, -1.77968,0.9,-0.92592, + -1.77968,0.9,-0.92592, -1.767222,0.771675,-0.919439, -1.886223,0.771675,-0.633613, + -1.96042,0.771675,-0.325863, -1.97424,0.9,-0.32816, -1.89952,0.9,-0.63808, + -1.89952,0.9,-0.63808, -1.886223,0.771675,-0.633613, -1.96042,0.771675,-0.325863, + -1.986,0.771675,0, -2,0.9,0, -1.97424,0.9,-0.32816, + -1.97424,0.9,-0.32816, -1.96042,0.771675,-0.325863, -1.986,0.771675,0, + -0.319628,0.6564,-1.92291, -0.325863,0.771675,-1.96042, 0,0.771675,-1.986, + 0,0.771675,-1.986, 0,0.6564,-1.948, -0.319628,0.6564,-1.92291, + -0.62149,0.6564,-1.850132, -0.633613,0.771675,-1.886223, -0.325863,0.771675,-1.96042, + -0.325863,0.771675,-1.96042, -0.319628,0.6564,-1.92291, -0.62149,0.6564,-1.850132, + -0.901846,0.6564,-1.733408, -0.919439,0.771675,-1.767222, -0.633613,0.771675,-1.886223, + -0.633613,0.771675,-1.886223, -0.62149,0.6564,-1.850132, -0.901846,0.6564,-1.733408, + -1.156956,0.6564,-1.576477, -1.179525,0.771675,-1.60723, -0.919439,0.771675,-1.767222, + -0.919439,0.771675,-1.767222, -0.901846,0.6564,-1.733408, -1.156956,0.6564,-1.576477, + -1.38308,0.6564,-1.38308, -1.41006,0.771675,-1.41006, -1.179525,0.771675,-1.60723, + -1.179525,0.771675,-1.60723, -1.156956,0.6564,-1.576477, -1.38308,0.6564,-1.38308, + -1.576477,0.6564,-1.156956, -1.60723,0.771675,-1.179525, -1.41006,0.771675,-1.41006, + -1.41006,0.771675,-1.41006, -1.38308,0.6564,-1.38308, -1.576477,0.6564,-1.156956, + -1.733408,0.6564,-0.901846, -1.767222,0.771675,-0.919439, -1.60723,0.771675,-1.179525, + -1.60723,0.771675,-1.179525, -1.576477,0.6564,-1.156956, -1.733408,0.6564,-0.901846, + -1.850132,0.6564,-0.62149, -1.886223,0.771675,-0.633613, -1.767222,0.771675,-0.919439, + -1.767222,0.771675,-0.919439, -1.733408,0.6564,-0.901846, -1.850132,0.6564,-0.62149, + -1.92291,0.6564,-0.319628, -1.96042,0.771675,-0.325863, -1.886223,0.771675,-0.633613, + -1.886223,0.771675,-0.633613, -1.850132,0.6564,-0.62149, -1.92291,0.6564,-0.319628, + -1.948,0.6564,0, -1.986,0.771675,0, -1.96042,0.771675,-0.325863, + -1.96042,0.771675,-0.325863, -1.92291,0.6564,-0.319628, -1.948,0.6564,0, + -0.310439,0.553725,-1.867631, -0.319628,0.6564,-1.92291, 0,0.6564,-1.948, + 0,0.6564,-1.948, 0,0.553725,-1.892, -0.310439,0.553725,-1.867631, + -0.603624,0.553725,-1.796946, -0.62149,0.6564,-1.850132, -0.319628,0.6564,-1.92291, + -0.319628,0.6564,-1.92291, -0.310439,0.553725,-1.867631, -0.603624,0.553725,-1.796946, + -0.87592,0.553725,-1.683577, -0.901846,0.6564,-1.733408, -0.62149,0.6564,-1.850132, + -0.62149,0.6564,-1.850132, -0.603624,0.553725,-1.796946, -0.87592,0.553725,-1.683577, + -1.123697,0.553725,-1.531158, -1.156956,0.6564,-1.576477, -0.901846,0.6564,-1.733408, + -0.901846,0.6564,-1.733408, -0.87592,0.553725,-1.683577, -1.123697,0.553725,-1.531158, + -1.34332,0.553725,-1.34332, -1.38308,0.6564,-1.38308, -1.156956,0.6564,-1.576477, + -1.156956,0.6564,-1.576477, -1.123697,0.553725,-1.531158, -1.34332,0.553725,-1.34332, + -1.531158,0.553725,-1.123697, -1.576477,0.6564,-1.156956, -1.38308,0.6564,-1.38308, + -1.38308,0.6564,-1.38308, -1.34332,0.553725,-1.34332, -1.531158,0.553725,-1.123697, + -1.683577,0.553725,-0.87592, -1.733408,0.6564,-0.901846, -1.576477,0.6564,-1.156956, + -1.576477,0.6564,-1.156956, -1.531158,0.553725,-1.123697, -1.683577,0.553725,-0.87592, + -1.796946,0.553725,-0.603624, -1.850132,0.6564,-0.62149, -1.733408,0.6564,-0.901846, + -1.733408,0.6564,-0.901846, -1.683577,0.553725,-0.87592, -1.796946,0.553725,-0.603624, + -1.867631,0.553725,-0.310439, -1.92291,0.6564,-0.319628, -1.850132,0.6564,-0.62149, + -1.850132,0.6564,-0.62149, -1.796946,0.553725,-0.603624, -1.867631,0.553725,-0.310439, + -1.892,0.553725,0, -1.948,0.6564,0, -1.92291,0.6564,-0.319628, + -1.92291,0.6564,-0.319628, -1.867631,0.553725,-0.310439, -1.892,0.553725,0, + -0.299282,0.4632,-1.800507, -0.310439,0.553725,-1.867631, 0,0.553725,-1.892, + 0,0.553725,-1.892, 0,0.4632,-1.824, -0.299282,0.4632,-1.800507, + -0.581929,0.4632,-1.732362, -0.603624,0.553725,-1.796946, -0.310439,0.553725,-1.867631, + -0.310439,0.553725,-1.867631, -0.299282,0.4632,-1.800507, -0.581929,0.4632,-1.732362, + -0.844439,0.4632,-1.623068, -0.87592,0.553725,-1.683577, -0.603624,0.553725,-1.796946, + -0.603624,0.553725,-1.796946, -0.581929,0.4632,-1.732362, -0.844439,0.4632,-1.623068, + -1.08331,0.4632,-1.476127, -1.123697,0.553725,-1.531158, -0.87592,0.553725,-1.683577, + -0.87592,0.553725,-1.683577, -0.844439,0.4632,-1.623068, -1.08331,0.4632,-1.476127, + -1.29504,0.4632,-1.29504, -1.34332,0.553725,-1.34332, -1.123697,0.553725,-1.531158, + -1.123697,0.553725,-1.531158, -1.08331,0.4632,-1.476127, -1.29504,0.4632,-1.29504, + -1.476127,0.4632,-1.08331, -1.531158,0.553725,-1.123697, -1.34332,0.553725,-1.34332, + -1.34332,0.553725,-1.34332, -1.29504,0.4632,-1.29504, -1.476127,0.4632,-1.08331, + -1.623068,0.4632,-0.844439, -1.683577,0.553725,-0.87592, -1.531158,0.553725,-1.123697, + -1.531158,0.553725,-1.123697, -1.476127,0.4632,-1.08331, -1.623068,0.4632,-0.844439, + -1.732362,0.4632,-0.581929, -1.796946,0.553725,-0.603624, -1.683577,0.553725,-0.87592, + -1.683577,0.553725,-0.87592, -1.623068,0.4632,-0.844439, -1.732362,0.4632,-0.581929, + -1.800507,0.4632,-0.299282, -1.867631,0.553725,-0.310439, -1.796946,0.553725,-0.603624, + -1.796946,0.553725,-0.603624, -1.732362,0.4632,-0.581929, -1.800507,0.4632,-0.299282, + -1.824,0.4632,0, -1.892,0.553725,0, -1.867631,0.553725,-0.310439, + -1.867631,0.553725,-0.310439, -1.800507,0.4632,-0.299282, -1.824,0.4632,0, + -0.28714,0.384375,-1.72746, -0.299282,0.4632,-1.800507, 0,0.4632,-1.824, + 0,0.4632,-1.824, 0,0.384375,-1.75, -0.28714,0.384375,-1.72746, + -0.55832,0.384375,-1.66208, -0.581929,0.4632,-1.732362, -0.299282,0.4632,-1.800507, + -0.299282,0.4632,-1.800507, -0.28714,0.384375,-1.72746, -0.55832,0.384375,-1.66208, + -0.81018,0.384375,-1.55722, -0.844439,0.4632,-1.623068, -0.581929,0.4632,-1.732362, + -0.581929,0.4632,-1.732362, -0.55832,0.384375,-1.66208, -0.81018,0.384375,-1.55722, + -1.03936,0.384375,-1.41624, -1.08331,0.4632,-1.476127, -0.844439,0.4632,-1.623068, + -0.844439,0.4632,-1.623068, -0.81018,0.384375,-1.55722, -1.03936,0.384375,-1.41624, + -1.2425,0.384375,-1.2425, -1.29504,0.4632,-1.29504, -1.08331,0.4632,-1.476127, + -1.08331,0.4632,-1.476127, -1.03936,0.384375,-1.41624, -1.2425,0.384375,-1.2425, + -1.41624,0.384375,-1.03936, -1.476127,0.4632,-1.08331, -1.29504,0.4632,-1.29504, + -1.29504,0.4632,-1.29504, -1.2425,0.384375,-1.2425, -1.41624,0.384375,-1.03936, + -1.55722,0.384375,-0.81018, -1.623068,0.4632,-0.844439, -1.476127,0.4632,-1.08331, + -1.476127,0.4632,-1.08331, -1.41624,0.384375,-1.03936, -1.55722,0.384375,-0.81018, + -1.66208,0.384375,-0.55832, -1.732362,0.4632,-0.581929, -1.623068,0.4632,-0.844439, + -1.623068,0.4632,-0.844439, -1.55722,0.384375,-0.81018, -1.66208,0.384375,-0.55832, + -1.72746,0.384375,-0.28714, -1.800507,0.4632,-0.299282, -1.732362,0.4632,-0.581929, + -1.732362,0.4632,-0.581929, -1.66208,0.384375,-0.55832, -1.72746,0.384375,-0.28714, + -1.75,0.384375,0, -1.824,0.4632,0, -1.800507,0.4632,-0.299282, + -1.800507,0.4632,-0.299282, -1.72746,0.384375,-0.28714, -1.75,0.384375,0, + -0.274998,0.3168,-1.654413, -0.28714,0.384375,-1.72746, 0,0.384375,-1.75, + 0,0.384375,-1.75, 0,0.3168,-1.676, -0.274998,0.3168,-1.654413, + -0.534711,0.3168,-1.591798, -0.55832,0.384375,-1.66208, -0.28714,0.384375,-1.72746, + -0.28714,0.384375,-1.72746, -0.274998,0.3168,-1.654413, -0.534711,0.3168,-1.591798, + -0.775921,0.3168,-1.491372, -0.81018,0.384375,-1.55722, -0.55832,0.384375,-1.66208, + -0.55832,0.384375,-1.66208, -0.534711,0.3168,-1.591798, -0.775921,0.3168,-1.491372, + -0.99541,0.3168,-1.356353, -1.03936,0.384375,-1.41624, -0.81018,0.384375,-1.55722, + -0.81018,0.384375,-1.55722, -0.775921,0.3168,-1.491372, -0.99541,0.3168,-1.356353, + -1.18996,0.3168,-1.18996, -1.2425,0.384375,-1.2425, -1.03936,0.384375,-1.41624, + -1.03936,0.384375,-1.41624, -0.99541,0.3168,-1.356353, -1.18996,0.3168,-1.18996, + -1.356353,0.3168,-0.99541, -1.41624,0.384375,-1.03936, -1.2425,0.384375,-1.2425, + -1.2425,0.384375,-1.2425, -1.18996,0.3168,-1.18996, -1.356353,0.3168,-0.99541, + -1.491372,0.3168,-0.775921, -1.55722,0.384375,-0.81018, -1.41624,0.384375,-1.03936, + -1.41624,0.384375,-1.03936, -1.356353,0.3168,-0.99541, -1.491372,0.3168,-0.775921, + -1.591798,0.3168,-0.534711, -1.66208,0.384375,-0.55832, -1.55722,0.384375,-0.81018, + -1.55722,0.384375,-0.81018, -1.491372,0.3168,-0.775921, -1.591798,0.3168,-0.534711, + -1.654413,0.3168,-0.274998, -1.72746,0.384375,-0.28714, -1.66208,0.384375,-0.55832, + -1.66208,0.384375,-0.55832, -1.591798,0.3168,-0.534711, -1.654413,0.3168,-0.274998, + -1.676,0.3168,0, -1.75,0.384375,0, -1.72746,0.384375,-0.28714, + -1.72746,0.384375,-0.28714, -1.654413,0.3168,-0.274998, -1.676,0.3168,0, + -0.263841,0.260025,-1.587289, -0.274998,0.3168,-1.654413, 0,0.3168,-1.676, + 0,0.3168,-1.676, 0,0.260025,-1.608, -0.263841,0.260025,-1.587289, + -0.513016,0.260025,-1.527214, -0.534711,0.3168,-1.591798, -0.274998,0.3168,-1.654413, + -0.274998,0.3168,-1.654413, -0.263841,0.260025,-1.587289, -0.513016,0.260025,-1.527214, + -0.74444,0.260025,-1.430863, -0.775921,0.3168,-1.491372, -0.534711,0.3168,-1.591798, + -0.534711,0.3168,-1.591798, -0.513016,0.260025,-1.527214, -0.74444,0.260025,-1.430863, + -0.955023,0.260025,-1.301322, -0.99541,0.3168,-1.356353, -0.775921,0.3168,-1.491372, + -0.775921,0.3168,-1.491372, -0.74444,0.260025,-1.430863, -0.955023,0.260025,-1.301322, + -1.14168,0.260025,-1.14168, -1.18996,0.3168,-1.18996, -0.99541,0.3168,-1.356353, + -0.99541,0.3168,-1.356353, -0.955023,0.260025,-1.301322, -1.14168,0.260025,-1.14168, + -1.301322,0.260025,-0.955023, -1.356353,0.3168,-0.99541, -1.18996,0.3168,-1.18996, + -1.18996,0.3168,-1.18996, -1.14168,0.260025,-1.14168, -1.301322,0.260025,-0.955023, + -1.430863,0.260025,-0.74444, -1.491372,0.3168,-0.775921, -1.356353,0.3168,-0.99541, + -1.356353,0.3168,-0.99541, -1.301322,0.260025,-0.955023, -1.430863,0.260025,-0.74444, + -1.527214,0.260025,-0.513016, -1.591798,0.3168,-0.534711, -1.491372,0.3168,-0.775921, + -1.491372,0.3168,-0.775921, -1.430863,0.260025,-0.74444, -1.527214,0.260025,-0.513016, + -1.587289,0.260025,-0.263841, -1.654413,0.3168,-0.274998, -1.591798,0.3168,-0.534711, + -1.591798,0.3168,-0.534711, -1.527214,0.260025,-0.513016, -1.587289,0.260025,-0.263841, + -1.608,0.260025,0, -1.676,0.3168,0, -1.654413,0.3168,-0.274998, + -1.654413,0.3168,-0.274998, -1.587289,0.260025,-0.263841, -1.608,0.260025,0, + -0.254652,0.2136,-1.53201, -0.263841,0.260025,-1.587289, 0,0.260025,-1.608, + 0,0.260025,-1.608, 0,0.2136,-1.552, -0.254652,0.2136,-1.53201, + -0.49515,0.2136,-1.474028, -0.513016,0.260025,-1.527214, -0.263841,0.260025,-1.587289, + -0.263841,0.260025,-1.587289, -0.254652,0.2136,-1.53201, -0.49515,0.2136,-1.474028, + -0.718514,0.2136,-1.381032, -0.74444,0.260025,-1.430863, -0.513016,0.260025,-1.527214, + -0.513016,0.260025,-1.527214, -0.49515,0.2136,-1.474028, -0.718514,0.2136,-1.381032, + -0.921764,0.2136,-1.256003, -0.955023,0.260025,-1.301322, -0.74444,0.260025,-1.430863, + -0.74444,0.260025,-1.430863, -0.718514,0.2136,-1.381032, -0.921764,0.2136,-1.256003, + -1.10192,0.2136,-1.10192, -1.14168,0.260025,-1.14168, -0.955023,0.260025,-1.301322, + -0.955023,0.260025,-1.301322, -0.921764,0.2136,-1.256003, -1.10192,0.2136,-1.10192, + -1.256003,0.2136,-0.921764, -1.301322,0.260025,-0.955023, -1.14168,0.260025,-1.14168, + -1.14168,0.260025,-1.14168, -1.10192,0.2136,-1.10192, -1.256003,0.2136,-0.921764, + -1.381032,0.2136,-0.718514, -1.430863,0.260025,-0.74444, -1.301322,0.260025,-0.955023, + -1.301322,0.260025,-0.955023, -1.256003,0.2136,-0.921764, -1.381032,0.2136,-0.718514, + -1.474028,0.2136,-0.49515, -1.527214,0.260025,-0.513016, -1.430863,0.260025,-0.74444, + -1.430863,0.260025,-0.74444, -1.381032,0.2136,-0.718514, -1.474028,0.2136,-0.49515, + -1.53201,0.2136,-0.254652, -1.587289,0.260025,-0.263841, -1.527214,0.260025,-0.513016, + -1.527214,0.260025,-0.513016, -1.474028,0.2136,-0.49515, -1.53201,0.2136,-0.254652, + -1.552,0.2136,0, -1.608,0.260025,0, -1.587289,0.260025,-0.263841, + -1.587289,0.260025,-0.263841, -1.53201,0.2136,-0.254652, -1.552,0.2136,0, + -0.248417,0.177075,-1.4945, -0.254652,0.2136,-1.53201, 0,0.2136,-1.552, + 0,0.2136,-1.552, 0,0.177075,-1.514, -0.248417,0.177075,-1.4945, + -0.483027,0.177075,-1.437937, -0.49515,0.2136,-1.474028, -0.254652,0.2136,-1.53201, + -0.254652,0.2136,-1.53201, -0.248417,0.177075,-1.4945, -0.483027,0.177075,-1.437937, + -0.700921,0.177075,-1.347218, -0.718514,0.2136,-1.381032, -0.49515,0.2136,-1.474028, + -0.49515,0.2136,-1.474028, -0.483027,0.177075,-1.437937, -0.700921,0.177075,-1.347218, + -0.899195,0.177075,-1.22525, -0.921764,0.2136,-1.256003, -0.718514,0.2136,-1.381032, + -0.718514,0.2136,-1.381032, -0.700921,0.177075,-1.347218, -0.899195,0.177075,-1.22525, + -1.07494,0.177075,-1.07494, -1.10192,0.2136,-1.10192, -0.921764,0.2136,-1.256003, + -0.921764,0.2136,-1.256003, -0.899195,0.177075,-1.22525, -1.07494,0.177075,-1.07494, + -1.22525,0.177075,-0.899195, -1.256003,0.2136,-0.921764, -1.10192,0.2136,-1.10192, + -1.10192,0.2136,-1.10192, -1.07494,0.177075,-1.07494, -1.22525,0.177075,-0.899195, + -1.347218,0.177075,-0.700921, -1.381032,0.2136,-0.718514, -1.256003,0.2136,-0.921764, + -1.256003,0.2136,-0.921764, -1.22525,0.177075,-0.899195, -1.347218,0.177075,-0.700921, + -1.437937,0.177075,-0.483027, -1.474028,0.2136,-0.49515, -1.381032,0.2136,-0.718514, + -1.381032,0.2136,-0.718514, -1.347218,0.177075,-0.700921, -1.437937,0.177075,-0.483027, + -1.4945,0.177075,-0.248417, -1.53201,0.2136,-0.254652, -1.474028,0.2136,-0.49515, + -1.474028,0.2136,-0.49515, -1.437937,0.177075,-0.483027, -1.4945,0.177075,-0.248417, + -1.514,0.177075,0, -1.552,0.2136,0, -1.53201,0.2136,-0.254652, + -1.53201,0.2136,-0.254652, -1.4945,0.177075,-0.248417, -1.514,0.177075,0, + -0.24612,0.15,-1.48068, -0.248417,0.177075,-1.4945, 0,0.177075,-1.514, + 0,0.177075,-1.514, 0,0.15,-1.5, -0.24612,0.15,-1.48068, + -0.47856,0.15,-1.42464, -0.483027,0.177075,-1.437937, -0.248417,0.177075,-1.4945, + -0.248417,0.177075,-1.4945, -0.24612,0.15,-1.48068, -0.47856,0.15,-1.42464, + -0.69444,0.15,-1.33476, -0.700921,0.177075,-1.347218, -0.483027,0.177075,-1.437937, + -0.483027,0.177075,-1.437937, -0.47856,0.15,-1.42464, -0.69444,0.15,-1.33476, + -0.89088,0.15,-1.21392, -0.899195,0.177075,-1.22525, -0.700921,0.177075,-1.347218, + -0.700921,0.177075,-1.347218, -0.69444,0.15,-1.33476, -0.89088,0.15,-1.21392, + -1.065,0.15,-1.065, -1.07494,0.177075,-1.07494, -0.899195,0.177075,-1.22525, + -0.899195,0.177075,-1.22525, -0.89088,0.15,-1.21392, -1.065,0.15,-1.065, + -1.21392,0.15,-0.89088, -1.22525,0.177075,-0.899195, -1.07494,0.177075,-1.07494, + -1.07494,0.177075,-1.07494, -1.065,0.15,-1.065, -1.21392,0.15,-0.89088, + -1.33476,0.15,-0.69444, -1.347218,0.177075,-0.700921, -1.22525,0.177075,-0.899195, + -1.22525,0.177075,-0.899195, -1.21392,0.15,-0.89088, -1.33476,0.15,-0.69444, + -1.42464,0.15,-0.47856, -1.437937,0.177075,-0.483027, -1.347218,0.177075,-0.700921, + -1.347218,0.177075,-0.700921, -1.33476,0.15,-0.69444, -1.42464,0.15,-0.47856, + -1.48068,0.15,-0.24612, -1.4945,0.177075,-0.248417, -1.437937,0.177075,-0.483027, + -1.437937,0.177075,-0.483027, -1.42464,0.15,-0.47856, -1.48068,0.15,-0.24612, + -1.5,0.15,0, -1.514,0.177075,0, -1.4945,0.177075,-0.248417, + -1.4945,0.177075,-0.248417, -1.48068,0.15,-0.24612, -1.5,0.15,0, + -1.96042,0.771675,0.325863, -1.97424,0.9,0.32816, -2,0.9,0, + -2,0.9,0, -1.986,0.771675,0, -1.96042,0.771675,0.325863, + -1.886223,0.771675,0.633613, -1.89952,0.9,0.63808, -1.97424,0.9,0.32816, + -1.97424,0.9,0.32816, -1.96042,0.771675,0.325863, -1.886223,0.771675,0.633613, + -1.767222,0.771675,0.919439, -1.77968,0.9,0.92592, -1.89952,0.9,0.63808, + -1.89952,0.9,0.63808, -1.886223,0.771675,0.633613, -1.767222,0.771675,0.919439, + -1.60723,0.771675,1.179525, -1.61856,0.9,1.18784, -1.77968,0.9,0.92592, + -1.77968,0.9,0.92592, -1.767222,0.771675,0.919439, -1.60723,0.771675,1.179525, + -1.41006,0.771675,1.41006, -1.42,0.9,1.42, -1.61856,0.9,1.18784, + -1.61856,0.9,1.18784, -1.60723,0.771675,1.179525, -1.41006,0.771675,1.41006, + -1.179525,0.771675,1.60723, -1.18784,0.9,1.61856, -1.42,0.9,1.42, + -1.42,0.9,1.42, -1.41006,0.771675,1.41006, -1.179525,0.771675,1.60723, + -0.919439,0.771675,1.767222, -0.92592,0.9,1.77968, -1.18784,0.9,1.61856, + -1.18784,0.9,1.61856, -1.179525,0.771675,1.60723, -0.919439,0.771675,1.767222, + -0.633613,0.771675,1.886223, -0.63808,0.9,1.89952, -0.92592,0.9,1.77968, + -0.92592,0.9,1.77968, -0.919439,0.771675,1.767222, -0.633613,0.771675,1.886223, + -0.325863,0.771675,1.96042, -0.32816,0.9,1.97424, -0.63808,0.9,1.89952, + -0.63808,0.9,1.89952, -0.633613,0.771675,1.886223, -0.325863,0.771675,1.96042, + 0,0.771675,1.986, 0,0.9,2, -0.32816,0.9,1.97424, + -0.32816,0.9,1.97424, -0.325863,0.771675,1.96042, 0,0.771675,1.986, + -1.92291,0.6564,0.319628, -1.96042,0.771675,0.325863, -1.986,0.771675,0, + -1.986,0.771675,0, -1.948,0.6564,0, -1.92291,0.6564,0.319628, + -1.850132,0.6564,0.62149, -1.886223,0.771675,0.633613, -1.96042,0.771675,0.325863, + -1.96042,0.771675,0.325863, -1.92291,0.6564,0.319628, -1.850132,0.6564,0.62149, + -1.733408,0.6564,0.901846, -1.767222,0.771675,0.919439, -1.886223,0.771675,0.633613, + -1.886223,0.771675,0.633613, -1.850132,0.6564,0.62149, -1.733408,0.6564,0.901846, + -1.576477,0.6564,1.156956, -1.60723,0.771675,1.179525, -1.767222,0.771675,0.919439, + -1.767222,0.771675,0.919439, -1.733408,0.6564,0.901846, -1.576477,0.6564,1.156956, + -1.38308,0.6564,1.38308, -1.41006,0.771675,1.41006, -1.60723,0.771675,1.179525, + -1.60723,0.771675,1.179525, -1.576477,0.6564,1.156956, -1.38308,0.6564,1.38308, + -1.156956,0.6564,1.576477, -1.179525,0.771675,1.60723, -1.41006,0.771675,1.41006, + -1.41006,0.771675,1.41006, -1.38308,0.6564,1.38308, -1.156956,0.6564,1.576477, + -0.901846,0.6564,1.733408, -0.919439,0.771675,1.767222, -1.179525,0.771675,1.60723, + -1.179525,0.771675,1.60723, -1.156956,0.6564,1.576477, -0.901846,0.6564,1.733408, + -0.62149,0.6564,1.850132, -0.633613,0.771675,1.886223, -0.919439,0.771675,1.767222, + -0.919439,0.771675,1.767222, -0.901846,0.6564,1.733408, -0.62149,0.6564,1.850132, + -0.319628,0.6564,1.92291, -0.325863,0.771675,1.96042, -0.633613,0.771675,1.886223, + -0.633613,0.771675,1.886223, -0.62149,0.6564,1.850132, -0.319628,0.6564,1.92291, + 0,0.6564,1.948, 0,0.771675,1.986, -0.325863,0.771675,1.96042, + -0.325863,0.771675,1.96042, -0.319628,0.6564,1.92291, 0,0.6564,1.948, + -1.867631,0.553725,0.310439, -1.92291,0.6564,0.319628, -1.948,0.6564,0, + -1.948,0.6564,0, -1.892,0.553725,0, -1.867631,0.553725,0.310439, + -1.796946,0.553725,0.603624, -1.850132,0.6564,0.62149, -1.92291,0.6564,0.319628, + -1.92291,0.6564,0.319628, -1.867631,0.553725,0.310439, -1.796946,0.553725,0.603624, + -1.683577,0.553725,0.87592, -1.733408,0.6564,0.901846, -1.850132,0.6564,0.62149, + -1.850132,0.6564,0.62149, -1.796946,0.553725,0.603624, -1.683577,0.553725,0.87592, + -1.531158,0.553725,1.123697, -1.576477,0.6564,1.156956, -1.733408,0.6564,0.901846, + -1.733408,0.6564,0.901846, -1.683577,0.553725,0.87592, -1.531158,0.553725,1.123697, + -1.34332,0.553725,1.34332, -1.38308,0.6564,1.38308, -1.576477,0.6564,1.156956, + -1.576477,0.6564,1.156956, -1.531158,0.553725,1.123697, -1.34332,0.553725,1.34332, + -1.123697,0.553725,1.531158, -1.156956,0.6564,1.576477, -1.38308,0.6564,1.38308, + -1.38308,0.6564,1.38308, -1.34332,0.553725,1.34332, -1.123697,0.553725,1.531158, + -0.87592,0.553725,1.683577, -0.901846,0.6564,1.733408, -1.156956,0.6564,1.576477, + -1.156956,0.6564,1.576477, -1.123697,0.553725,1.531158, -0.87592,0.553725,1.683577, + -0.603624,0.553725,1.796946, -0.62149,0.6564,1.850132, -0.901846,0.6564,1.733408, + -0.901846,0.6564,1.733408, -0.87592,0.553725,1.683577, -0.603624,0.553725,1.796946, + -0.310439,0.553725,1.867631, -0.319628,0.6564,1.92291, -0.62149,0.6564,1.850132, + -0.62149,0.6564,1.850132, -0.603624,0.553725,1.796946, -0.310439,0.553725,1.867631, + 0,0.553725,1.892, 0,0.6564,1.948, -0.319628,0.6564,1.92291, + -0.319628,0.6564,1.92291, -0.310439,0.553725,1.867631, 0,0.553725,1.892, + -1.800507,0.4632,0.299282, -1.867631,0.553725,0.310439, -1.892,0.553725,0, + -1.892,0.553725,0, -1.824,0.4632,0, -1.800507,0.4632,0.299282, + -1.732362,0.4632,0.581929, -1.796946,0.553725,0.603624, -1.867631,0.553725,0.310439, + -1.867631,0.553725,0.310439, -1.800507,0.4632,0.299282, -1.732362,0.4632,0.581929, + -1.623068,0.4632,0.844439, -1.683577,0.553725,0.87592, -1.796946,0.553725,0.603624, + -1.796946,0.553725,0.603624, -1.732362,0.4632,0.581929, -1.623068,0.4632,0.844439, + -1.476127,0.4632,1.08331, -1.531158,0.553725,1.123697, -1.683577,0.553725,0.87592, + -1.683577,0.553725,0.87592, -1.623068,0.4632,0.844439, -1.476127,0.4632,1.08331, + -1.29504,0.4632,1.29504, -1.34332,0.553725,1.34332, -1.531158,0.553725,1.123697, + -1.531158,0.553725,1.123697, -1.476127,0.4632,1.08331, -1.29504,0.4632,1.29504, + -1.08331,0.4632,1.476127, -1.123697,0.553725,1.531158, -1.34332,0.553725,1.34332, + -1.34332,0.553725,1.34332, -1.29504,0.4632,1.29504, -1.08331,0.4632,1.476127, + -0.844439,0.4632,1.623068, -0.87592,0.553725,1.683577, -1.123697,0.553725,1.531158, + -1.123697,0.553725,1.531158, -1.08331,0.4632,1.476127, -0.844439,0.4632,1.623068, + -0.581929,0.4632,1.732362, -0.603624,0.553725,1.796946, -0.87592,0.553725,1.683577, + -0.87592,0.553725,1.683577, -0.844439,0.4632,1.623068, -0.581929,0.4632,1.732362, + -0.299282,0.4632,1.800507, -0.310439,0.553725,1.867631, -0.603624,0.553725,1.796946, + -0.603624,0.553725,1.796946, -0.581929,0.4632,1.732362, -0.299282,0.4632,1.800507, + 0,0.4632,1.824, 0,0.553725,1.892, -0.310439,0.553725,1.867631, + -0.310439,0.553725,1.867631, -0.299282,0.4632,1.800507, 0,0.4632,1.824, + -1.72746,0.384375,0.28714, -1.800507,0.4632,0.299282, -1.824,0.4632,0, + -1.824,0.4632,0, -1.75,0.384375,0, -1.72746,0.384375,0.28714, + -1.66208,0.384375,0.55832, -1.732362,0.4632,0.581929, -1.800507,0.4632,0.299282, + -1.800507,0.4632,0.299282, -1.72746,0.384375,0.28714, -1.66208,0.384375,0.55832, + -1.55722,0.384375,0.81018, -1.623068,0.4632,0.844439, -1.732362,0.4632,0.581929, + -1.732362,0.4632,0.581929, -1.66208,0.384375,0.55832, -1.55722,0.384375,0.81018, + -1.41624,0.384375,1.03936, -1.476127,0.4632,1.08331, -1.623068,0.4632,0.844439, + -1.623068,0.4632,0.844439, -1.55722,0.384375,0.81018, -1.41624,0.384375,1.03936, + -1.2425,0.384375,1.2425, -1.29504,0.4632,1.29504, -1.476127,0.4632,1.08331, + -1.476127,0.4632,1.08331, -1.41624,0.384375,1.03936, -1.2425,0.384375,1.2425, + -1.03936,0.384375,1.41624, -1.08331,0.4632,1.476127, -1.29504,0.4632,1.29504, + -1.29504,0.4632,1.29504, -1.2425,0.384375,1.2425, -1.03936,0.384375,1.41624, + -0.81018,0.384375,1.55722, -0.844439,0.4632,1.623068, -1.08331,0.4632,1.476127, + -1.08331,0.4632,1.476127, -1.03936,0.384375,1.41624, -0.81018,0.384375,1.55722, + -0.55832,0.384375,1.66208, -0.581929,0.4632,1.732362, -0.844439,0.4632,1.623068, + -0.844439,0.4632,1.623068, -0.81018,0.384375,1.55722, -0.55832,0.384375,1.66208, + -0.28714,0.384375,1.72746, -0.299282,0.4632,1.800507, -0.581929,0.4632,1.732362, + -0.581929,0.4632,1.732362, -0.55832,0.384375,1.66208, -0.28714,0.384375,1.72746, + 0,0.384375,1.75, 0,0.4632,1.824, -0.299282,0.4632,1.800507, + -0.299282,0.4632,1.800507, -0.28714,0.384375,1.72746, 0,0.384375,1.75, + -1.654413,0.3168,0.274998, -1.72746,0.384375,0.28714, -1.75,0.384375,0, + -1.75,0.384375,0, -1.676,0.3168,0, -1.654413,0.3168,0.274998, + -1.591798,0.3168,0.534711, -1.66208,0.384375,0.55832, -1.72746,0.384375,0.28714, + -1.72746,0.384375,0.28714, -1.654413,0.3168,0.274998, -1.591798,0.3168,0.534711, + -1.491372,0.3168,0.775921, -1.55722,0.384375,0.81018, -1.66208,0.384375,0.55832, + -1.66208,0.384375,0.55832, -1.591798,0.3168,0.534711, -1.491372,0.3168,0.775921, + -1.356353,0.3168,0.99541, -1.41624,0.384375,1.03936, -1.55722,0.384375,0.81018, + -1.55722,0.384375,0.81018, -1.491372,0.3168,0.775921, -1.356353,0.3168,0.99541, + -1.18996,0.3168,1.18996, -1.2425,0.384375,1.2425, -1.41624,0.384375,1.03936, + -1.41624,0.384375,1.03936, -1.356353,0.3168,0.99541, -1.18996,0.3168,1.18996, + -0.99541,0.3168,1.356353, -1.03936,0.384375,1.41624, -1.2425,0.384375,1.2425, + -1.2425,0.384375,1.2425, -1.18996,0.3168,1.18996, -0.99541,0.3168,1.356353, + -0.775921,0.3168,1.491372, -0.81018,0.384375,1.55722, -1.03936,0.384375,1.41624, + -1.03936,0.384375,1.41624, -0.99541,0.3168,1.356353, -0.775921,0.3168,1.491372, + -0.534711,0.3168,1.591798, -0.55832,0.384375,1.66208, -0.81018,0.384375,1.55722, + -0.81018,0.384375,1.55722, -0.775921,0.3168,1.491372, -0.534711,0.3168,1.591798, + -0.274998,0.3168,1.654413, -0.28714,0.384375,1.72746, -0.55832,0.384375,1.66208, + -0.55832,0.384375,1.66208, -0.534711,0.3168,1.591798, -0.274998,0.3168,1.654413, + 0,0.3168,1.676, 0,0.384375,1.75, -0.28714,0.384375,1.72746, + -0.28714,0.384375,1.72746, -0.274998,0.3168,1.654413, 0,0.3168,1.676, + -1.587289,0.260025,0.263841, -1.654413,0.3168,0.274998, -1.676,0.3168,0, + -1.676,0.3168,0, -1.608,0.260025,0, -1.587289,0.260025,0.263841, + -1.527214,0.260025,0.513016, -1.591798,0.3168,0.534711, -1.654413,0.3168,0.274998, + -1.654413,0.3168,0.274998, -1.587289,0.260025,0.263841, -1.527214,0.260025,0.513016, + -1.430863,0.260025,0.74444, -1.491372,0.3168,0.775921, -1.591798,0.3168,0.534711, + -1.591798,0.3168,0.534711, -1.527214,0.260025,0.513016, -1.430863,0.260025,0.74444, + -1.301322,0.260025,0.955023, -1.356353,0.3168,0.99541, -1.491372,0.3168,0.775921, + -1.491372,0.3168,0.775921, -1.430863,0.260025,0.74444, -1.301322,0.260025,0.955023, + -1.14168,0.260025,1.14168, -1.18996,0.3168,1.18996, -1.356353,0.3168,0.99541, + -1.356353,0.3168,0.99541, -1.301322,0.260025,0.955023, -1.14168,0.260025,1.14168, + -0.955023,0.260025,1.301322, -0.99541,0.3168,1.356353, -1.18996,0.3168,1.18996, + -1.18996,0.3168,1.18996, -1.14168,0.260025,1.14168, -0.955023,0.260025,1.301322, + -0.74444,0.260025,1.430863, -0.775921,0.3168,1.491372, -0.99541,0.3168,1.356353, + -0.99541,0.3168,1.356353, -0.955023,0.260025,1.301322, -0.74444,0.260025,1.430863, + -0.513016,0.260025,1.527214, -0.534711,0.3168,1.591798, -0.775921,0.3168,1.491372, + -0.775921,0.3168,1.491372, -0.74444,0.260025,1.430863, -0.513016,0.260025,1.527214, + -0.263841,0.260025,1.587289, -0.274998,0.3168,1.654413, -0.534711,0.3168,1.591798, + -0.534711,0.3168,1.591798, -0.513016,0.260025,1.527214, -0.263841,0.260025,1.587289, + 0,0.260025,1.608, 0,0.3168,1.676, -0.274998,0.3168,1.654413, + -0.274998,0.3168,1.654413, -0.263841,0.260025,1.587289, 0,0.260025,1.608, + -1.53201,0.2136,0.254652, -1.587289,0.260025,0.263841, -1.608,0.260025,0, + -1.608,0.260025,0, -1.552,0.2136,0, -1.53201,0.2136,0.254652, + -1.474028,0.2136,0.49515, -1.527214,0.260025,0.513016, -1.587289,0.260025,0.263841, + -1.587289,0.260025,0.263841, -1.53201,0.2136,0.254652, -1.474028,0.2136,0.49515, + -1.381032,0.2136,0.718514, -1.430863,0.260025,0.74444, -1.527214,0.260025,0.513016, + -1.527214,0.260025,0.513016, -1.474028,0.2136,0.49515, -1.381032,0.2136,0.718514, + -1.256003,0.2136,0.921764, -1.301322,0.260025,0.955023, -1.430863,0.260025,0.74444, + -1.430863,0.260025,0.74444, -1.381032,0.2136,0.718514, -1.256003,0.2136,0.921764, + -1.10192,0.2136,1.10192, -1.14168,0.260025,1.14168, -1.301322,0.260025,0.955023, + -1.301322,0.260025,0.955023, -1.256003,0.2136,0.921764, -1.10192,0.2136,1.10192, + -0.921764,0.2136,1.256003, -0.955023,0.260025,1.301322, -1.14168,0.260025,1.14168, + -1.14168,0.260025,1.14168, -1.10192,0.2136,1.10192, -0.921764,0.2136,1.256003, + -0.718514,0.2136,1.381032, -0.74444,0.260025,1.430863, -0.955023,0.260025,1.301322, + -0.955023,0.260025,1.301322, -0.921764,0.2136,1.256003, -0.718514,0.2136,1.381032, + -0.49515,0.2136,1.474028, -0.513016,0.260025,1.527214, -0.74444,0.260025,1.430863, + -0.74444,0.260025,1.430863, -0.718514,0.2136,1.381032, -0.49515,0.2136,1.474028, + -0.254652,0.2136,1.53201, -0.263841,0.260025,1.587289, -0.513016,0.260025,1.527214, + -0.513016,0.260025,1.527214, -0.49515,0.2136,1.474028, -0.254652,0.2136,1.53201, + 0,0.2136,1.552, 0,0.260025,1.608, -0.263841,0.260025,1.587289, + -0.263841,0.260025,1.587289, -0.254652,0.2136,1.53201, 0,0.2136,1.552, + -1.4945,0.177075,0.248417, -1.53201,0.2136,0.254652, -1.552,0.2136,0, + -1.552,0.2136,0, -1.514,0.177075,0, -1.4945,0.177075,0.248417, + -1.437937,0.177075,0.483027, -1.474028,0.2136,0.49515, -1.53201,0.2136,0.254652, + -1.53201,0.2136,0.254652, -1.4945,0.177075,0.248417, -1.437937,0.177075,0.483027, + -1.347218,0.177075,0.700921, -1.381032,0.2136,0.718514, -1.474028,0.2136,0.49515, + -1.474028,0.2136,0.49515, -1.437937,0.177075,0.483027, -1.347218,0.177075,0.700921, + -1.22525,0.177075,0.899195, -1.256003,0.2136,0.921764, -1.381032,0.2136,0.718514, + -1.381032,0.2136,0.718514, -1.347218,0.177075,0.700921, -1.22525,0.177075,0.899195, + -1.07494,0.177075,1.07494, -1.10192,0.2136,1.10192, -1.256003,0.2136,0.921764, + -1.256003,0.2136,0.921764, -1.22525,0.177075,0.899195, -1.07494,0.177075,1.07494, + -0.899195,0.177075,1.22525, -0.921764,0.2136,1.256003, -1.10192,0.2136,1.10192, + -1.10192,0.2136,1.10192, -1.07494,0.177075,1.07494, -0.899195,0.177075,1.22525, + -0.700921,0.177075,1.347218, -0.718514,0.2136,1.381032, -0.921764,0.2136,1.256003, + -0.921764,0.2136,1.256003, -0.899195,0.177075,1.22525, -0.700921,0.177075,1.347218, + -0.483027,0.177075,1.437937, -0.49515,0.2136,1.474028, -0.718514,0.2136,1.381032, + -0.718514,0.2136,1.381032, -0.700921,0.177075,1.347218, -0.483027,0.177075,1.437937, + -0.248417,0.177075,1.4945, -0.254652,0.2136,1.53201, -0.49515,0.2136,1.474028, + -0.49515,0.2136,1.474028, -0.483027,0.177075,1.437937, -0.248417,0.177075,1.4945, + 0,0.177075,1.514, 0,0.2136,1.552, -0.254652,0.2136,1.53201, + -0.254652,0.2136,1.53201, -0.248417,0.177075,1.4945, 0,0.177075,1.514, + -1.48068,0.15,0.24612, -1.4945,0.177075,0.248417, -1.514,0.177075,0, + -1.514,0.177075,0, -1.5,0.15,0, -1.48068,0.15,0.24612, + -1.42464,0.15,0.47856, -1.437937,0.177075,0.483027, -1.4945,0.177075,0.248417, + -1.4945,0.177075,0.248417, -1.48068,0.15,0.24612, -1.42464,0.15,0.47856, + -1.33476,0.15,0.69444, -1.347218,0.177075,0.700921, -1.437937,0.177075,0.483027, + -1.437937,0.177075,0.483027, -1.42464,0.15,0.47856, -1.33476,0.15,0.69444, + -1.21392,0.15,0.89088, -1.22525,0.177075,0.899195, -1.347218,0.177075,0.700921, + -1.347218,0.177075,0.700921, -1.33476,0.15,0.69444, -1.21392,0.15,0.89088, + -1.065,0.15,1.065, -1.07494,0.177075,1.07494, -1.22525,0.177075,0.899195, + -1.22525,0.177075,0.899195, -1.21392,0.15,0.89088, -1.065,0.15,1.065, + -0.89088,0.15,1.21392, -0.899195,0.177075,1.22525, -1.07494,0.177075,1.07494, + -1.07494,0.177075,1.07494, -1.065,0.15,1.065, -0.89088,0.15,1.21392, + -0.69444,0.15,1.33476, -0.700921,0.177075,1.347218, -0.899195,0.177075,1.22525, + -0.899195,0.177075,1.22525, -0.89088,0.15,1.21392, -0.69444,0.15,1.33476, + -0.47856,0.15,1.42464, -0.483027,0.177075,1.437937, -0.700921,0.177075,1.347218, + -0.700921,0.177075,1.347218, -0.69444,0.15,1.33476, -0.47856,0.15,1.42464, + -0.24612,0.15,1.48068, -0.248417,0.177075,1.4945, -0.483027,0.177075,1.437937, + -0.483027,0.177075,1.437937, -0.47856,0.15,1.42464, -0.24612,0.15,1.48068, + 0,0.15,1.5, 0,0.177075,1.514, -0.248417,0.177075,1.4945, + -0.248417,0.177075,1.4945, -0.24612,0.15,1.48068, 0,0.15,1.5, + 0.325863,0.771675,1.96042, 0.32816,0.9,1.97424, 0,0.9,2, + 0,0.9,2, 0,0.771675,1.986, 0.325863,0.771675,1.96042, + 0.633613,0.771675,1.886223, 0.63808,0.9,1.89952, 0.32816,0.9,1.97424, + 0.32816,0.9,1.97424, 0.325863,0.771675,1.96042, 0.633613,0.771675,1.886223, + 0.919439,0.771675,1.767222, 0.92592,0.9,1.77968, 0.63808,0.9,1.89952, + 0.63808,0.9,1.89952, 0.633613,0.771675,1.886223, 0.919439,0.771675,1.767222, + 1.179525,0.771675,1.60723, 1.18784,0.9,1.61856, 0.92592,0.9,1.77968, + 0.92592,0.9,1.77968, 0.919439,0.771675,1.767222, 1.179525,0.771675,1.60723, + 1.41006,0.771675,1.41006, 1.42,0.9,1.42, 1.18784,0.9,1.61856, + 1.18784,0.9,1.61856, 1.179525,0.771675,1.60723, 1.41006,0.771675,1.41006, + 1.60723,0.771675,1.179525, 1.61856,0.9,1.18784, 1.42,0.9,1.42, + 1.42,0.9,1.42, 1.41006,0.771675,1.41006, 1.60723,0.771675,1.179525, + 1.767222,0.771675,0.919439, 1.77968,0.9,0.92592, 1.61856,0.9,1.18784, + 1.61856,0.9,1.18784, 1.60723,0.771675,1.179525, 1.767222,0.771675,0.919439, + 1.886223,0.771675,0.633613, 1.89952,0.9,0.63808, 1.77968,0.9,0.92592, + 1.77968,0.9,0.92592, 1.767222,0.771675,0.919439, 1.886223,0.771675,0.633613, + 1.96042,0.771675,0.325863, 1.97424,0.9,0.32816, 1.89952,0.9,0.63808, + 1.89952,0.9,0.63808, 1.886223,0.771675,0.633613, 1.96042,0.771675,0.325863, + 1.986,0.771675,0, 2,0.9,0, 1.97424,0.9,0.32816, + 1.97424,0.9,0.32816, 1.96042,0.771675,0.325863, 1.986,0.771675,0, + 0.319628,0.6564,1.92291, 0.325863,0.771675,1.96042, 0,0.771675,1.986, + 0,0.771675,1.986, 0,0.6564,1.948, 0.319628,0.6564,1.92291, + 0.62149,0.6564,1.850132, 0.633613,0.771675,1.886223, 0.325863,0.771675,1.96042, + 0.325863,0.771675,1.96042, 0.319628,0.6564,1.92291, 0.62149,0.6564,1.850132, + 0.901846,0.6564,1.733408, 0.919439,0.771675,1.767222, 0.633613,0.771675,1.886223, + 0.633613,0.771675,1.886223, 0.62149,0.6564,1.850132, 0.901846,0.6564,1.733408, + 1.156956,0.6564,1.576477, 1.179525,0.771675,1.60723, 0.919439,0.771675,1.767222, + 0.919439,0.771675,1.767222, 0.901846,0.6564,1.733408, 1.156956,0.6564,1.576477, + 1.38308,0.6564,1.38308, 1.41006,0.771675,1.41006, 1.179525,0.771675,1.60723, + 1.179525,0.771675,1.60723, 1.156956,0.6564,1.576477, 1.38308,0.6564,1.38308, + 1.576477,0.6564,1.156956, 1.60723,0.771675,1.179525, 1.41006,0.771675,1.41006, + 1.41006,0.771675,1.41006, 1.38308,0.6564,1.38308, 1.576477,0.6564,1.156956, + 1.733408,0.6564,0.901846, 1.767222,0.771675,0.919439, 1.60723,0.771675,1.179525, + 1.60723,0.771675,1.179525, 1.576477,0.6564,1.156956, 1.733408,0.6564,0.901846, + 1.850132,0.6564,0.62149, 1.886223,0.771675,0.633613, 1.767222,0.771675,0.919439, + 1.767222,0.771675,0.919439, 1.733408,0.6564,0.901846, 1.850132,0.6564,0.62149, + 1.92291,0.6564,0.319628, 1.96042,0.771675,0.325863, 1.886223,0.771675,0.633613, + 1.886223,0.771675,0.633613, 1.850132,0.6564,0.62149, 1.92291,0.6564,0.319628, + 1.948,0.6564,0, 1.986,0.771675,0, 1.96042,0.771675,0.325863, + 1.96042,0.771675,0.325863, 1.92291,0.6564,0.319628, 1.948,0.6564,0, + 0.310439,0.553725,1.867631, 0.319628,0.6564,1.92291, 0,0.6564,1.948, + 0,0.6564,1.948, 0,0.553725,1.892, 0.310439,0.553725,1.867631, + 0.603624,0.553725,1.796946, 0.62149,0.6564,1.850132, 0.319628,0.6564,1.92291, + 0.319628,0.6564,1.92291, 0.310439,0.553725,1.867631, 0.603624,0.553725,1.796946, + 0.87592,0.553725,1.683577, 0.901846,0.6564,1.733408, 0.62149,0.6564,1.850132, + 0.62149,0.6564,1.850132, 0.603624,0.553725,1.796946, 0.87592,0.553725,1.683577, + 1.123697,0.553725,1.531158, 1.156956,0.6564,1.576477, 0.901846,0.6564,1.733408, + 0.901846,0.6564,1.733408, 0.87592,0.553725,1.683577, 1.123697,0.553725,1.531158, + 1.34332,0.553725,1.34332, 1.38308,0.6564,1.38308, 1.156956,0.6564,1.576477, + 1.156956,0.6564,1.576477, 1.123697,0.553725,1.531158, 1.34332,0.553725,1.34332, + 1.531158,0.553725,1.123697, 1.576477,0.6564,1.156956, 1.38308,0.6564,1.38308, + 1.38308,0.6564,1.38308, 1.34332,0.553725,1.34332, 1.531158,0.553725,1.123697, + 1.683577,0.553725,0.87592, 1.733408,0.6564,0.901846, 1.576477,0.6564,1.156956, + 1.576477,0.6564,1.156956, 1.531158,0.553725,1.123697, 1.683577,0.553725,0.87592, + 1.796946,0.553725,0.603624, 1.850132,0.6564,0.62149, 1.733408,0.6564,0.901846, + 1.733408,0.6564,0.901846, 1.683577,0.553725,0.87592, 1.796946,0.553725,0.603624, + 1.867631,0.553725,0.310439, 1.92291,0.6564,0.319628, 1.850132,0.6564,0.62149, + 1.850132,0.6564,0.62149, 1.796946,0.553725,0.603624, 1.867631,0.553725,0.310439, + 1.892,0.553725,0, 1.948,0.6564,0, 1.92291,0.6564,0.319628, + 1.92291,0.6564,0.319628, 1.867631,0.553725,0.310439, 1.892,0.553725,0, + 0.299282,0.4632,1.800507, 0.310439,0.553725,1.867631, 0,0.553725,1.892, + 0,0.553725,1.892, 0,0.4632,1.824, 0.299282,0.4632,1.800507, + 0.581929,0.4632,1.732362, 0.603624,0.553725,1.796946, 0.310439,0.553725,1.867631, + 0.310439,0.553725,1.867631, 0.299282,0.4632,1.800507, 0.581929,0.4632,1.732362, + 0.844439,0.4632,1.623068, 0.87592,0.553725,1.683577, 0.603624,0.553725,1.796946, + 0.603624,0.553725,1.796946, 0.581929,0.4632,1.732362, 0.844439,0.4632,1.623068, + 1.08331,0.4632,1.476127, 1.123697,0.553725,1.531158, 0.87592,0.553725,1.683577, + 0.87592,0.553725,1.683577, 0.844439,0.4632,1.623068, 1.08331,0.4632,1.476127, + 1.29504,0.4632,1.29504, 1.34332,0.553725,1.34332, 1.123697,0.553725,1.531158, + 1.123697,0.553725,1.531158, 1.08331,0.4632,1.476127, 1.29504,0.4632,1.29504, + 1.476127,0.4632,1.08331, 1.531158,0.553725,1.123697, 1.34332,0.553725,1.34332, + 1.34332,0.553725,1.34332, 1.29504,0.4632,1.29504, 1.476127,0.4632,1.08331, + 1.623068,0.4632,0.844439, 1.683577,0.553725,0.87592, 1.531158,0.553725,1.123697, + 1.531158,0.553725,1.123697, 1.476127,0.4632,1.08331, 1.623068,0.4632,0.844439, + 1.732362,0.4632,0.581929, 1.796946,0.553725,0.603624, 1.683577,0.553725,0.87592, + 1.683577,0.553725,0.87592, 1.623068,0.4632,0.844439, 1.732362,0.4632,0.581929, + 1.800507,0.4632,0.299282, 1.867631,0.553725,0.310439, 1.796946,0.553725,0.603624, + 1.796946,0.553725,0.603624, 1.732362,0.4632,0.581929, 1.800507,0.4632,0.299282, + 1.824,0.4632,0, 1.892,0.553725,0, 1.867631,0.553725,0.310439, + 1.867631,0.553725,0.310439, 1.800507,0.4632,0.299282, 1.824,0.4632,0, + 0.28714,0.384375,1.72746, 0.299282,0.4632,1.800507, 0,0.4632,1.824, + 0,0.4632,1.824, 0,0.384375,1.75, 0.28714,0.384375,1.72746, + 0.55832,0.384375,1.66208, 0.581929,0.4632,1.732362, 0.299282,0.4632,1.800507, + 0.299282,0.4632,1.800507, 0.28714,0.384375,1.72746, 0.55832,0.384375,1.66208, + 0.81018,0.384375,1.55722, 0.844439,0.4632,1.623068, 0.581929,0.4632,1.732362, + 0.581929,0.4632,1.732362, 0.55832,0.384375,1.66208, 0.81018,0.384375,1.55722, + 1.03936,0.384375,1.41624, 1.08331,0.4632,1.476127, 0.844439,0.4632,1.623068, + 0.844439,0.4632,1.623068, 0.81018,0.384375,1.55722, 1.03936,0.384375,1.41624, + 1.2425,0.384375,1.2425, 1.29504,0.4632,1.29504, 1.08331,0.4632,1.476127, + 1.08331,0.4632,1.476127, 1.03936,0.384375,1.41624, 1.2425,0.384375,1.2425, + 1.41624,0.384375,1.03936, 1.476127,0.4632,1.08331, 1.29504,0.4632,1.29504, + 1.29504,0.4632,1.29504, 1.2425,0.384375,1.2425, 1.41624,0.384375,1.03936, + 1.55722,0.384375,0.81018, 1.623068,0.4632,0.844439, 1.476127,0.4632,1.08331, + 1.476127,0.4632,1.08331, 1.41624,0.384375,1.03936, 1.55722,0.384375,0.81018, + 1.66208,0.384375,0.55832, 1.732362,0.4632,0.581929, 1.623068,0.4632,0.844439, + 1.623068,0.4632,0.844439, 1.55722,0.384375,0.81018, 1.66208,0.384375,0.55832, + 1.72746,0.384375,0.28714, 1.800507,0.4632,0.299282, 1.732362,0.4632,0.581929, + 1.732362,0.4632,0.581929, 1.66208,0.384375,0.55832, 1.72746,0.384375,0.28714, + 1.75,0.384375,0, 1.824,0.4632,0, 1.800507,0.4632,0.299282, + 1.800507,0.4632,0.299282, 1.72746,0.384375,0.28714, 1.75,0.384375,0, + 0.274998,0.3168,1.654413, 0.28714,0.384375,1.72746, 0,0.384375,1.75, + 0,0.384375,1.75, 0,0.3168,1.676, 0.274998,0.3168,1.654413, + 0.534711,0.3168,1.591798, 0.55832,0.384375,1.66208, 0.28714,0.384375,1.72746, + 0.28714,0.384375,1.72746, 0.274998,0.3168,1.654413, 0.534711,0.3168,1.591798, + 0.775921,0.3168,1.491372, 0.81018,0.384375,1.55722, 0.55832,0.384375,1.66208, + 0.55832,0.384375,1.66208, 0.534711,0.3168,1.591798, 0.775921,0.3168,1.491372, + 0.99541,0.3168,1.356353, 1.03936,0.384375,1.41624, 0.81018,0.384375,1.55722, + 0.81018,0.384375,1.55722, 0.775921,0.3168,1.491372, 0.99541,0.3168,1.356353, + 1.18996,0.3168,1.18996, 1.2425,0.384375,1.2425, 1.03936,0.384375,1.41624, + 1.03936,0.384375,1.41624, 0.99541,0.3168,1.356353, 1.18996,0.3168,1.18996, + 1.356353,0.3168,0.99541, 1.41624,0.384375,1.03936, 1.2425,0.384375,1.2425, + 1.2425,0.384375,1.2425, 1.18996,0.3168,1.18996, 1.356353,0.3168,0.99541, + 1.491372,0.3168,0.775921, 1.55722,0.384375,0.81018, 1.41624,0.384375,1.03936, + 1.41624,0.384375,1.03936, 1.356353,0.3168,0.99541, 1.491372,0.3168,0.775921, + 1.591798,0.3168,0.534711, 1.66208,0.384375,0.55832, 1.55722,0.384375,0.81018, + 1.55722,0.384375,0.81018, 1.491372,0.3168,0.775921, 1.591798,0.3168,0.534711, + 1.654413,0.3168,0.274998, 1.72746,0.384375,0.28714, 1.66208,0.384375,0.55832, + 1.66208,0.384375,0.55832, 1.591798,0.3168,0.534711, 1.654413,0.3168,0.274998, + 1.676,0.3168,0, 1.75,0.384375,0, 1.72746,0.384375,0.28714, + 1.72746,0.384375,0.28714, 1.654413,0.3168,0.274998, 1.676,0.3168,0, + 0.263841,0.260025,1.587289, 0.274998,0.3168,1.654413, 0,0.3168,1.676, + 0,0.3168,1.676, 0,0.260025,1.608, 0.263841,0.260025,1.587289, + 0.513016,0.260025,1.527214, 0.534711,0.3168,1.591798, 0.274998,0.3168,1.654413, + 0.274998,0.3168,1.654413, 0.263841,0.260025,1.587289, 0.513016,0.260025,1.527214, + 0.74444,0.260025,1.430863, 0.775921,0.3168,1.491372, 0.534711,0.3168,1.591798, + 0.534711,0.3168,1.591798, 0.513016,0.260025,1.527214, 0.74444,0.260025,1.430863, + 0.955023,0.260025,1.301322, 0.99541,0.3168,1.356353, 0.775921,0.3168,1.491372, + 0.775921,0.3168,1.491372, 0.74444,0.260025,1.430863, 0.955023,0.260025,1.301322, + 1.14168,0.260025,1.14168, 1.18996,0.3168,1.18996, 0.99541,0.3168,1.356353, + 0.99541,0.3168,1.356353, 0.955023,0.260025,1.301322, 1.14168,0.260025,1.14168, + 1.301322,0.260025,0.955023, 1.356353,0.3168,0.99541, 1.18996,0.3168,1.18996, + 1.18996,0.3168,1.18996, 1.14168,0.260025,1.14168, 1.301322,0.260025,0.955023, + 1.430863,0.260025,0.74444, 1.491372,0.3168,0.775921, 1.356353,0.3168,0.99541, + 1.356353,0.3168,0.99541, 1.301322,0.260025,0.955023, 1.430863,0.260025,0.74444, + 1.527214,0.260025,0.513016, 1.591798,0.3168,0.534711, 1.491372,0.3168,0.775921, + 1.491372,0.3168,0.775921, 1.430863,0.260025,0.74444, 1.527214,0.260025,0.513016, + 1.587289,0.260025,0.263841, 1.654413,0.3168,0.274998, 1.591798,0.3168,0.534711, + 1.591798,0.3168,0.534711, 1.527214,0.260025,0.513016, 1.587289,0.260025,0.263841, + 1.608,0.260025,0, 1.676,0.3168,0, 1.654413,0.3168,0.274998, + 1.654413,0.3168,0.274998, 1.587289,0.260025,0.263841, 1.608,0.260025,0, + 0.254652,0.2136,1.53201, 0.263841,0.260025,1.587289, 0,0.260025,1.608, + 0,0.260025,1.608, 0,0.2136,1.552, 0.254652,0.2136,1.53201, + 0.49515,0.2136,1.474028, 0.513016,0.260025,1.527214, 0.263841,0.260025,1.587289, + 0.263841,0.260025,1.587289, 0.254652,0.2136,1.53201, 0.49515,0.2136,1.474028, + 0.718514,0.2136,1.381032, 0.74444,0.260025,1.430863, 0.513016,0.260025,1.527214, + 0.513016,0.260025,1.527214, 0.49515,0.2136,1.474028, 0.718514,0.2136,1.381032, + 0.921764,0.2136,1.256003, 0.955023,0.260025,1.301322, 0.74444,0.260025,1.430863, + 0.74444,0.260025,1.430863, 0.718514,0.2136,1.381032, 0.921764,0.2136,1.256003, + 1.10192,0.2136,1.10192, 1.14168,0.260025,1.14168, 0.955023,0.260025,1.301322, + 0.955023,0.260025,1.301322, 0.921764,0.2136,1.256003, 1.10192,0.2136,1.10192, + 1.256003,0.2136,0.921764, 1.301322,0.260025,0.955023, 1.14168,0.260025,1.14168, + 1.14168,0.260025,1.14168, 1.10192,0.2136,1.10192, 1.256003,0.2136,0.921764, + 1.381032,0.2136,0.718514, 1.430863,0.260025,0.74444, 1.301322,0.260025,0.955023, + 1.301322,0.260025,0.955023, 1.256003,0.2136,0.921764, 1.381032,0.2136,0.718514, + 1.474028,0.2136,0.49515, 1.527214,0.260025,0.513016, 1.430863,0.260025,0.74444, + 1.430863,0.260025,0.74444, 1.381032,0.2136,0.718514, 1.474028,0.2136,0.49515, + 1.53201,0.2136,0.254652, 1.587289,0.260025,0.263841, 1.527214,0.260025,0.513016, + 1.527214,0.260025,0.513016, 1.474028,0.2136,0.49515, 1.53201,0.2136,0.254652, + 1.552,0.2136,0, 1.608,0.260025,0, 1.587289,0.260025,0.263841, + 1.587289,0.260025,0.263841, 1.53201,0.2136,0.254652, 1.552,0.2136,0, + 0.248417,0.177075,1.4945, 0.254652,0.2136,1.53201, 0,0.2136,1.552, + 0,0.2136,1.552, 0,0.177075,1.514, 0.248417,0.177075,1.4945, + 0.483027,0.177075,1.437937, 0.49515,0.2136,1.474028, 0.254652,0.2136,1.53201, + 0.254652,0.2136,1.53201, 0.248417,0.177075,1.4945, 0.483027,0.177075,1.437937, + 0.700921,0.177075,1.347218, 0.718514,0.2136,1.381032, 0.49515,0.2136,1.474028, + 0.49515,0.2136,1.474028, 0.483027,0.177075,1.437937, 0.700921,0.177075,1.347218, + 0.899195,0.177075,1.22525, 0.921764,0.2136,1.256003, 0.718514,0.2136,1.381032, + 0.718514,0.2136,1.381032, 0.700921,0.177075,1.347218, 0.899195,0.177075,1.22525, + 1.07494,0.177075,1.07494, 1.10192,0.2136,1.10192, 0.921764,0.2136,1.256003, + 0.921764,0.2136,1.256003, 0.899195,0.177075,1.22525, 1.07494,0.177075,1.07494, + 1.22525,0.177075,0.899195, 1.256003,0.2136,0.921764, 1.10192,0.2136,1.10192, + 1.10192,0.2136,1.10192, 1.07494,0.177075,1.07494, 1.22525,0.177075,0.899195, + 1.347218,0.177075,0.700921, 1.381032,0.2136,0.718514, 1.256003,0.2136,0.921764, + 1.256003,0.2136,0.921764, 1.22525,0.177075,0.899195, 1.347218,0.177075,0.700921, + 1.437937,0.177075,0.483027, 1.474028,0.2136,0.49515, 1.381032,0.2136,0.718514, + 1.381032,0.2136,0.718514, 1.347218,0.177075,0.700921, 1.437937,0.177075,0.483027, + 1.4945,0.177075,0.248417, 1.53201,0.2136,0.254652, 1.474028,0.2136,0.49515, + 1.474028,0.2136,0.49515, 1.437937,0.177075,0.483027, 1.4945,0.177075,0.248417, + 1.514,0.177075,0, 1.552,0.2136,0, 1.53201,0.2136,0.254652, + 1.53201,0.2136,0.254652, 1.4945,0.177075,0.248417, 1.514,0.177075,0, + 0.24612,0.15,1.48068, 0.248417,0.177075,1.4945, 0,0.177075,1.514, + 0,0.177075,1.514, 0,0.15,1.5, 0.24612,0.15,1.48068, + 0.47856,0.15,1.42464, 0.483027,0.177075,1.437937, 0.248417,0.177075,1.4945, + 0.248417,0.177075,1.4945, 0.24612,0.15,1.48068, 0.47856,0.15,1.42464, + 0.69444,0.15,1.33476, 0.700921,0.177075,1.347218, 0.483027,0.177075,1.437937, + 0.483027,0.177075,1.437937, 0.47856,0.15,1.42464, 0.69444,0.15,1.33476, + 0.89088,0.15,1.21392, 0.899195,0.177075,1.22525, 0.700921,0.177075,1.347218, + 0.700921,0.177075,1.347218, 0.69444,0.15,1.33476, 0.89088,0.15,1.21392, + 1.065,0.15,1.065, 1.07494,0.177075,1.07494, 0.899195,0.177075,1.22525, + 0.899195,0.177075,1.22525, 0.89088,0.15,1.21392, 1.065,0.15,1.065, + 1.21392,0.15,0.89088, 1.22525,0.177075,0.899195, 1.07494,0.177075,1.07494, + 1.07494,0.177075,1.07494, 1.065,0.15,1.065, 1.21392,0.15,0.89088, + 1.33476,0.15,0.69444, 1.347218,0.177075,0.700921, 1.22525,0.177075,0.899195, + 1.22525,0.177075,0.899195, 1.21392,0.15,0.89088, 1.33476,0.15,0.69444, + 1.42464,0.15,0.47856, 1.437937,0.177075,0.483027, 1.347218,0.177075,0.700921, + 1.347218,0.177075,0.700921, 1.33476,0.15,0.69444, 1.42464,0.15,0.47856, + 1.48068,0.15,0.24612, 1.4945,0.177075,0.248417, 1.437937,0.177075,0.483027, + 1.437937,0.177075,0.483027, 1.42464,0.15,0.47856, 1.48068,0.15,0.24612, + 1.5,0.15,0, 1.514,0.177075,0, 1.4945,0.177075,0.248417, + 1.4945,0.177075,0.248417, 1.48068,0.15,0.24612, 1.5,0.15,0, + -1.800455,2.031069,-0.081, -1.5972,2.0313,-0.081, -1.6,2.025,0, + -1.6,2.025,0, -1.8009,2.024775,0, -1.800455,2.031069,-0.081, + -1.799246,2.048152,-0.144, -1.5896,2.0484,-0.144, -1.5972,2.0313,-0.081, + -1.5972,2.0313,-0.081, -1.800455,2.031069,-0.081, -1.799246,2.048152,-0.144, + -1.797466,2.073326,-0.189, -1.5784,2.0736,-0.189, -1.5896,2.0484,-0.144, + -1.5896,2.0484,-0.144, -1.799246,2.048152,-0.144, -1.797466,2.073326,-0.189, + -1.795303,2.103896,-0.216, -1.5648,2.1042,-0.216, -1.5784,2.0736,-0.189, + -1.5784,2.0736,-0.189, -1.797466,2.073326,-0.189, -1.795303,2.103896,-0.216, + -1.79295,2.137163,-0.225, -1.55,2.1375,-0.225, -1.5648,2.1042,-0.216, + -1.5648,2.1042,-0.216, -1.795303,2.103896,-0.216, -1.79295,2.137163,-0.225, + -1.790597,2.170429,-0.216, -1.5352,2.1708,-0.216, -1.55,2.1375,-0.225, + -1.55,2.1375,-0.225, -1.79295,2.137163,-0.225, -1.790597,2.170429,-0.216, + -1.788434,2.200999,-0.189, -1.5216,2.2014,-0.189, -1.5352,2.1708,-0.216, + -1.5352,2.1708,-0.216, -1.790597,2.170429,-0.216, -1.788434,2.200999,-0.189, + -1.786654,2.226173,-0.144, -1.5104,2.2266,-0.144, -1.5216,2.2014,-0.189, + -1.5216,2.2014,-0.189, -1.788434,2.200999,-0.189, -1.786654,2.226173,-0.144, + -1.785445,2.243256,-0.081, -1.5028,2.2437,-0.081, -1.5104,2.2266,-0.144, + -1.5104,2.2266,-0.144, -1.786654,2.226173,-0.144, -1.785445,2.243256,-0.081, + -1.785,2.24955,0, -1.5,2.25,0, -1.5028,2.2437,-0.081, + -1.5028,2.2437,-0.081, -1.785445,2.243256,-0.081, -1.785,2.24955,0, + -1.98479,2.02945,-0.081, -1.800455,2.031069,-0.081, -1.8009,2.024775,0, + -1.8009,2.024775,0, -1.9832,2.0232,0, -1.98479,2.02945,-0.081, + -1.989107,2.046413,-0.144, -1.799246,2.048152,-0.144, -1.800455,2.031069,-0.081, + -1.800455,2.031069,-0.081, -1.98479,2.02945,-0.081, -1.989107,2.046413,-0.144, + -1.995469,2.071411,-0.189, -1.797466,2.073326,-0.189, -1.799246,2.048152,-0.144, + -1.799246,2.048152,-0.144, -1.989107,2.046413,-0.144, -1.995469,2.071411,-0.189, + -2.003194,2.101766,-0.216, -1.795303,2.103896,-0.216, -1.797466,2.073326,-0.189, + -1.797466,2.073326,-0.189, -1.995469,2.071411,-0.189, -2.003194,2.101766,-0.216, + -2.0116,2.1348,-0.225, -1.79295,2.137163,-0.225, -1.795303,2.103896,-0.216, + -1.795303,2.103896,-0.216, -2.003194,2.101766,-0.216, -2.0116,2.1348,-0.225, + -2.020006,2.167834,-0.216, -1.790597,2.170429,-0.216, -1.79295,2.137163,-0.225, + -1.79295,2.137163,-0.225, -2.0116,2.1348,-0.225, -2.020006,2.167834,-0.216, + -2.027731,2.198189,-0.189, -1.788434,2.200999,-0.189, -1.790597,2.170429,-0.216, + -1.790597,2.170429,-0.216, -2.020006,2.167834,-0.216, -2.027731,2.198189,-0.189, + -2.034093,2.223187,-0.144, -1.786654,2.226173,-0.144, -1.788434,2.200999,-0.189, + -1.788434,2.200999,-0.189, -2.027731,2.198189,-0.189, -2.034093,2.223187,-0.144, + -2.03841,2.24015,-0.081, -1.785445,2.243256,-0.081, -1.786654,2.226173,-0.144, + -1.786654,2.226173,-0.144, -2.034093,2.223187,-0.144, -2.03841,2.24015,-0.081, + -2.04,2.2464,0, -1.785,2.24955,0, -1.785445,2.243256,-0.081, + -1.785445,2.243256,-0.081, -2.03841,2.24015,-0.081, -2.04,2.2464,0, + -2.149624,2.025055,-0.081, -1.98479,2.02945,-0.081, -1.9832,2.0232,0, + -1.9832,2.0232,0, -2.1463,2.018925,0, -2.149624,2.025055,-0.081, + -2.158645,2.041693,-0.144, -1.989107,2.046413,-0.144, -1.98479,2.02945,-0.081, + -1.98479,2.02945,-0.081, -2.149624,2.025055,-0.081, -2.158645,2.041693,-0.144, + -2.171939,2.066213,-0.189, -1.995469,2.071411,-0.189, -1.989107,2.046413,-0.144, + -1.989107,2.046413,-0.144, -2.158645,2.041693,-0.144, -2.171939,2.066213,-0.189, + -2.188082,2.095987,-0.216, -2.003194,2.101766,-0.216, -1.995469,2.071411,-0.189, + -1.995469,2.071411,-0.189, -2.171939,2.066213,-0.189, -2.188082,2.095987,-0.216, + -2.20565,2.128388,-0.225, -2.0116,2.1348,-0.225, -2.003194,2.101766,-0.216, + -2.003194,2.101766,-0.216, -2.188082,2.095987,-0.216, -2.20565,2.128388,-0.225, + -2.223218,2.160788,-0.216, -2.020006,2.167834,-0.216, -2.0116,2.1348,-0.225, + -2.0116,2.1348,-0.225, -2.20565,2.128388,-0.225, -2.223218,2.160788,-0.216, + -2.239361,2.190562,-0.189, -2.027731,2.198189,-0.189, -2.020006,2.167834,-0.216, + -2.020006,2.167834,-0.216, -2.223218,2.160788,-0.216, -2.239361,2.190562,-0.189, + -2.252655,2.215082,-0.144, -2.034093,2.223187,-0.144, -2.027731,2.198189,-0.189, + -2.027731,2.198189,-0.189, -2.239361,2.190562,-0.189, -2.252655,2.215082,-0.144, + -2.261676,2.23172,-0.081, -2.03841,2.24015,-0.081, -2.034093,2.223187,-0.144, + -2.034093,2.223187,-0.144, -2.252655,2.215082,-0.144, -2.261676,2.23172,-0.081, + -2.265,2.23785,0, -2.04,2.2464,0, -2.03841,2.24015,-0.081, + -2.03841,2.24015,-0.081, -2.261676,2.23172,-0.081, -2.265,2.23785,0, + -2.294371,2.016497,-0.081, -2.149624,2.025055,-0.081, -2.1463,2.018925,0, + -2.1463,2.018925,0, -2.2896,2.0106,0, -2.294371,2.016497,-0.081, + -2.307322,2.032502,-0.144, -2.158645,2.041693,-0.144, -2.149624,2.025055,-0.081, + -2.149624,2.025055,-0.081, -2.294371,2.016497,-0.081, -2.307322,2.032502,-0.144, + -2.326406,2.05609,-0.189, -2.171939,2.066213,-0.189, -2.158645,2.041693,-0.144, + -2.158645,2.041693,-0.144, -2.307322,2.032502,-0.144, -2.326406,2.05609,-0.189, + -2.349581,2.084731,-0.216, -2.188082,2.095987,-0.216, -2.171939,2.066213,-0.189, + -2.171939,2.066213,-0.189, -2.326406,2.05609,-0.189, -2.349581,2.084731,-0.216, + -2.3748,2.1159,-0.225, -2.20565,2.128388,-0.225, -2.188082,2.095987,-0.216, + -2.188082,2.095987,-0.216, -2.349581,2.084731,-0.216, -2.3748,2.1159,-0.225, + -2.400019,2.147069,-0.216, -2.223218,2.160788,-0.216, -2.20565,2.128388,-0.225, + -2.20565,2.128388,-0.225, -2.3748,2.1159,-0.225, -2.400019,2.147069,-0.216, + -2.423194,2.17571,-0.189, -2.239361,2.190562,-0.189, -2.223218,2.160788,-0.216, + -2.223218,2.160788,-0.216, -2.400019,2.147069,-0.216, -2.423194,2.17571,-0.189, + -2.442278,2.199298,-0.144, -2.252655,2.215082,-0.144, -2.239361,2.190562,-0.189, + -2.239361,2.190562,-0.189, -2.423194,2.17571,-0.189, -2.442278,2.199298,-0.144, + -2.455229,2.215303,-0.081, -2.261676,2.23172,-0.081, -2.252655,2.215082,-0.144, + -2.252655,2.215082,-0.144, -2.442278,2.199298,-0.144, -2.455229,2.215303,-0.081, + -2.46,2.2212,0, -2.265,2.23785,0, -2.261676,2.23172,-0.081, + -2.261676,2.23172,-0.081, -2.455229,2.215303,-0.081, -2.46,2.2212,0, + -2.41845,2.002387,-0.081, -2.294371,2.016497,-0.081, -2.2896,2.0106,0, + -2.2896,2.0106,0, -2.4125,1.996875,0, -2.41845,2.002387,-0.081, + -2.4346,2.01735,-0.144, -2.307322,2.032502,-0.144, -2.294371,2.016497,-0.081, + -2.294371,2.016497,-0.081, -2.41845,2.002387,-0.081, -2.4346,2.01735,-0.144, + -2.4584,2.0394,-0.189, -2.326406,2.05609,-0.189, -2.307322,2.032502,-0.144, + -2.307322,2.032502,-0.144, -2.4346,2.01735,-0.144, -2.4584,2.0394,-0.189, + -2.4873,2.066175,-0.216, -2.349581,2.084731,-0.216, -2.326406,2.05609,-0.189, + -2.326406,2.05609,-0.189, -2.4584,2.0394,-0.189, -2.4873,2.066175,-0.216, + -2.51875,2.095312,-0.225, -2.3748,2.1159,-0.225, -2.349581,2.084731,-0.216, + -2.349581,2.084731,-0.216, -2.4873,2.066175,-0.216, -2.51875,2.095312,-0.225, + -2.5502,2.12445,-0.216, -2.400019,2.147069,-0.216, -2.3748,2.1159,-0.225, + -2.3748,2.1159,-0.225, -2.51875,2.095312,-0.225, -2.5502,2.12445,-0.216, + -2.5791,2.151225,-0.189, -2.423194,2.17571,-0.189, -2.400019,2.147069,-0.216, + -2.400019,2.147069,-0.216, -2.5502,2.12445,-0.216, -2.5791,2.151225,-0.189, + -2.6029,2.173275,-0.144, -2.442278,2.199298,-0.144, -2.423194,2.17571,-0.189, + -2.423194,2.17571,-0.189, -2.5791,2.151225,-0.189, -2.6029,2.173275,-0.144, + -2.61905,2.188238,-0.081, -2.455229,2.215303,-0.081, -2.442278,2.199298,-0.144, + -2.442278,2.199298,-0.144, -2.6029,2.173275,-0.144, -2.61905,2.188238,-0.081, + -2.625,2.19375,0, -2.46,2.2212,0, -2.455229,2.215303,-0.081, + -2.455229,2.215303,-0.081, -2.61905,2.188238,-0.081, -2.625,2.19375,0, + -2.521277,1.981339,-0.081, -2.41845,2.002387,-0.081, -2.4125,1.996875,0, + -2.4125,1.996875,0, -2.5144,1.9764,0, -2.521277,1.981339,-0.081, + -2.539942,1.994746,-0.144, -2.4346,2.01735,-0.144, -2.41845,2.002387,-0.081, + -2.41845,2.002387,-0.081, -2.521277,1.981339,-0.081, -2.539942,1.994746,-0.144, + -2.56745,2.014502,-0.189, -2.4584,2.0394,-0.189, -2.4346,2.01735,-0.144, + -2.4346,2.01735,-0.144, -2.539942,1.994746,-0.144, -2.56745,2.014502,-0.189, + -2.600851,2.038493,-0.216, -2.4873,2.066175,-0.216, -2.4584,2.0394,-0.189, + -2.4584,2.0394,-0.189, -2.56745,2.014502,-0.189, -2.600851,2.038493,-0.216, + -2.6372,2.0646,-0.225, -2.51875,2.095312,-0.225, -2.4873,2.066175,-0.216, + -2.4873,2.066175,-0.216, -2.600851,2.038493,-0.216, -2.6372,2.0646,-0.225, + -2.673549,2.090707,-0.216, -2.5502,2.12445,-0.216, -2.51875,2.095312,-0.225, + -2.51875,2.095312,-0.225, -2.6372,2.0646,-0.225, -2.673549,2.090707,-0.216, + -2.70695,2.114698,-0.189, -2.5791,2.151225,-0.189, -2.5502,2.12445,-0.216, + -2.5502,2.12445,-0.216, -2.673549,2.090707,-0.216, -2.70695,2.114698,-0.189, + -2.734458,2.134454,-0.144, -2.6029,2.173275,-0.144, -2.5791,2.151225,-0.189, + -2.5791,2.151225,-0.189, -2.70695,2.114698,-0.189, -2.734458,2.134454,-0.144, + -2.753123,2.147861,-0.081, -2.61905,2.188238,-0.081, -2.6029,2.173275,-0.144, + -2.6029,2.173275,-0.144, -2.734458,2.134454,-0.144, -2.753123,2.147861,-0.081, + -2.76,2.1528,0, -2.625,2.19375,0, -2.61905,2.188238,-0.081, + -2.61905,2.188238,-0.081, -2.753123,2.147861,-0.081, -2.76,2.1528,0, + -2.602268,1.951964,-0.081, -2.521277,1.981339,-0.081, -2.5144,1.9764,0, + -2.5144,1.9764,0, -2.5947,1.947825,0, -2.602268,1.951964,-0.081, + -2.622811,1.963199,-0.144, -2.539942,1.994746,-0.144, -2.521277,1.981339,-0.081, + -2.521277,1.981339,-0.081, -2.602268,1.951964,-0.081, -2.622811,1.963199,-0.144, + -2.653085,1.979755,-0.189, -2.56745,2.014502,-0.189, -2.539942,1.994746,-0.144, + -2.539942,1.994746,-0.144, -2.622811,1.963199,-0.144, -2.653085,1.979755,-0.189, + -2.689846,1.999859,-0.216, -2.600851,2.038493,-0.216, -2.56745,2.014502,-0.189, + -2.56745,2.014502,-0.189, -2.653085,1.979755,-0.189, -2.689846,1.999859,-0.216, + -2.72985,2.021737,-0.225, -2.6372,2.0646,-0.225, -2.600851,2.038493,-0.216, + -2.600851,2.038493,-0.216, -2.689846,1.999859,-0.216, -2.72985,2.021737,-0.225, + -2.769854,2.043616,-0.216, -2.673549,2.090707,-0.216, -2.6372,2.0646,-0.225, + -2.6372,2.0646,-0.225, -2.72985,2.021737,-0.225, -2.769854,2.043616,-0.216, + -2.806615,2.06372,-0.189, -2.70695,2.114698,-0.189, -2.673549,2.090707,-0.216, + -2.673549,2.090707,-0.216, -2.769854,2.043616,-0.216, -2.806615,2.06372,-0.189, + -2.836889,2.080276,-0.144, -2.734458,2.134454,-0.144, -2.70695,2.114698,-0.189, + -2.70695,2.114698,-0.189, -2.806615,2.06372,-0.189, -2.836889,2.080276,-0.144, + -2.857432,2.091511,-0.081, -2.753123,2.147861,-0.081, -2.734458,2.134454,-0.144, + -2.734458,2.134454,-0.144, -2.836889,2.080276,-0.144, -2.857432,2.091511,-0.081, + -2.865,2.09565,0, -2.76,2.1528,0, -2.753123,2.147861,-0.081, + -2.753123,2.147861,-0.081, -2.857432,2.091511,-0.081, -2.865,2.09565,0, + -2.660842,1.912874,-0.081, -2.602268,1.951964,-0.081, -2.5947,1.947825,0, + -2.5947,1.947825,0, -2.6528,1.9098,0, -2.660842,1.912874,-0.081, + -2.682669,1.921219,-0.144, -2.622811,1.963199,-0.144, -2.602268,1.951964,-0.081, + -2.602268,1.951964,-0.081, -2.660842,1.912874,-0.081, -2.682669,1.921219,-0.144, + -2.714835,1.933517,-0.189, -2.653085,1.979755,-0.189, -2.622811,1.963199,-0.144, + -2.622811,1.963199,-0.144, -2.682669,1.921219,-0.144, -2.714835,1.933517,-0.189, + -2.753894,1.94845,-0.216, -2.689846,1.999859,-0.216, -2.653085,1.979755,-0.189, + -2.653085,1.979755,-0.189, -2.714835,1.933517,-0.189, -2.753894,1.94845,-0.216, + -2.7964,1.9647,-0.225, -2.72985,2.021737,-0.225, -2.689846,1.999859,-0.216, + -2.689846,1.999859,-0.216, -2.753894,1.94845,-0.216, -2.7964,1.9647,-0.225, + -2.838906,1.98095,-0.216, -2.769854,2.043616,-0.216, -2.72985,2.021737,-0.225, + -2.72985,2.021737,-0.225, -2.7964,1.9647,-0.225, -2.838906,1.98095,-0.216, + -2.877965,1.995883,-0.189, -2.806615,2.06372,-0.189, -2.769854,2.043616,-0.216, + -2.769854,2.043616,-0.216, -2.838906,1.98095,-0.216, -2.877965,1.995883,-0.189, + -2.910131,2.008181,-0.144, -2.836889,2.080276,-0.144, -2.806615,2.06372,-0.189, + -2.806615,2.06372,-0.189, -2.877965,1.995883,-0.189, -2.910131,2.008181,-0.144, + -2.931958,2.016526,-0.081, -2.857432,2.091511,-0.081, -2.836889,2.080276,-0.144, + -2.836889,2.080276,-0.144, -2.910131,2.008181,-0.144, -2.931958,2.016526,-0.081, + -2.94,2.0196,0, -2.865,2.09565,0, -2.857432,2.091511,-0.081, + -2.857432,2.091511,-0.081, -2.931958,2.016526,-0.081, -2.94,2.0196,0, + -2.696413,1.862682,-0.081, -2.660842,1.912874,-0.081, -2.6528,1.9098,0, + -2.6528,1.9098,0, -2.6881,1.860975,0, -2.696413,1.862682,-0.081, + -2.718978,1.867316,-0.144, -2.682669,1.921219,-0.144, -2.660842,1.912874,-0.081, + -2.660842,1.912874,-0.081, -2.696413,1.862682,-0.081, -2.718978,1.867316,-0.144, + -2.75223,1.874146,-0.189, -2.714835,1.933517,-0.189, -2.682669,1.921219,-0.144, + -2.682669,1.921219,-0.144, -2.718978,1.867316,-0.144, -2.75223,1.874146,-0.189, + -2.792609,1.882438,-0.216, -2.753894,1.94845,-0.216, -2.714835,1.933517,-0.189, + -2.714835,1.933517,-0.189, -2.75223,1.874146,-0.189, -2.792609,1.882438,-0.216, + -2.83655,1.891463,-0.225, -2.7964,1.9647,-0.225, -2.753894,1.94845,-0.216, + -2.753894,1.94845,-0.216, -2.792609,1.882438,-0.216, -2.83655,1.891463,-0.225, + -2.880491,1.900487,-0.216, -2.838906,1.98095,-0.216, -2.7964,1.9647,-0.225, + -2.7964,1.9647,-0.225, -2.83655,1.891463,-0.225, -2.880491,1.900487,-0.216, + -2.92087,1.908779,-0.189, -2.877965,1.995883,-0.189, -2.838906,1.98095,-0.216, + -2.838906,1.98095,-0.216, -2.880491,1.900487,-0.216, -2.92087,1.908779,-0.189, + -2.954122,1.915609,-0.144, -2.910131,2.008181,-0.144, -2.877965,1.995883,-0.189, + -2.877965,1.995883,-0.189, -2.92087,1.908779,-0.189, -2.954122,1.915609,-0.144, + -2.976687,1.920243,-0.081, -2.931958,2.016526,-0.081, -2.910131,2.008181,-0.144, + -2.910131,2.008181,-0.144, -2.954122,1.915609,-0.144, -2.976687,1.920243,-0.081, + -2.985,1.92195,0, -2.94,2.0196,0, -2.931958,2.016526,-0.081, + -2.931958,2.016526,-0.081, -2.976687,1.920243,-0.081, -2.985,1.92195,0, + -2.7084,1.8,-0.081, -2.696413,1.862682,-0.081, -2.6881,1.860975,0, + -2.6881,1.860975,0, -2.7,1.8,0, -2.7084,1.8,-0.081, + -2.7312,1.8,-0.144, -2.718978,1.867316,-0.144, -2.696413,1.862682,-0.081, + -2.696413,1.862682,-0.081, -2.7084,1.8,-0.081, -2.7312,1.8,-0.144, + -2.7648,1.8,-0.189, -2.75223,1.874146,-0.189, -2.718978,1.867316,-0.144, + -2.718978,1.867316,-0.144, -2.7312,1.8,-0.144, -2.7648,1.8,-0.189, + -2.8056,1.8,-0.216, -2.792609,1.882438,-0.216, -2.75223,1.874146,-0.189, + -2.75223,1.874146,-0.189, -2.7648,1.8,-0.189, -2.8056,1.8,-0.216, + -2.85,1.8,-0.225, -2.83655,1.891463,-0.225, -2.792609,1.882438,-0.216, + -2.792609,1.882438,-0.216, -2.8056,1.8,-0.216, -2.85,1.8,-0.225, + -2.8944,1.8,-0.216, -2.880491,1.900487,-0.216, -2.83655,1.891463,-0.225, + -2.83655,1.891463,-0.225, -2.85,1.8,-0.225, -2.8944,1.8,-0.216, + -2.9352,1.8,-0.189, -2.92087,1.908779,-0.189, -2.880491,1.900487,-0.216, + -2.880491,1.900487,-0.216, -2.8944,1.8,-0.216, -2.9352,1.8,-0.189, + -2.9688,1.8,-0.144, -2.954122,1.915609,-0.144, -2.92087,1.908779,-0.189, + -2.92087,1.908779,-0.189, -2.9352,1.8,-0.189, -2.9688,1.8,-0.144, + -2.9916,1.8,-0.081, -2.976687,1.920243,-0.081, -2.954122,1.915609,-0.144, + -2.954122,1.915609,-0.144, -2.9688,1.8,-0.144, -2.9916,1.8,-0.081, + -3,1.8,0, -2.985,1.92195,0, -2.976687,1.920243,-0.081, + -2.976687,1.920243,-0.081, -2.9916,1.8,-0.081, -3,1.8,0, + -1.785445,2.243256,0.081, -1.5028,2.2437,0.081, -1.5,2.25,0, + -1.5,2.25,0, -1.785,2.24955,0, -1.785445,2.243256,0.081, + -1.786654,2.226173,0.144, -1.5104,2.2266,0.144, -1.5028,2.2437,0.081, + -1.5028,2.2437,0.081, -1.785445,2.243256,0.081, -1.786654,2.226173,0.144, + -1.788434,2.200999,0.189, -1.5216,2.2014,0.189, -1.5104,2.2266,0.144, + -1.5104,2.2266,0.144, -1.786654,2.226173,0.144, -1.788434,2.200999,0.189, + -1.790597,2.170429,0.216, -1.5352,2.1708,0.216, -1.5216,2.2014,0.189, + -1.5216,2.2014,0.189, -1.788434,2.200999,0.189, -1.790597,2.170429,0.216, + -1.79295,2.137163,0.225, -1.55,2.1375,0.225, -1.5352,2.1708,0.216, + -1.5352,2.1708,0.216, -1.790597,2.170429,0.216, -1.79295,2.137163,0.225, + -1.795303,2.103896,0.216, -1.5648,2.1042,0.216, -1.55,2.1375,0.225, + -1.55,2.1375,0.225, -1.79295,2.137163,0.225, -1.795303,2.103896,0.216, + -1.797466,2.073326,0.189, -1.5784,2.0736,0.189, -1.5648,2.1042,0.216, + -1.5648,2.1042,0.216, -1.795303,2.103896,0.216, -1.797466,2.073326,0.189, + -1.799246,2.048152,0.144, -1.5896,2.0484,0.144, -1.5784,2.0736,0.189, + -1.5784,2.0736,0.189, -1.797466,2.073326,0.189, -1.799246,2.048152,0.144, + -1.800455,2.031069,0.081, -1.5972,2.0313,0.081, -1.5896,2.0484,0.144, + -1.5896,2.0484,0.144, -1.799246,2.048152,0.144, -1.800455,2.031069,0.081, + -1.8009,2.024775,0, -1.6,2.025,0, -1.5972,2.0313,0.081, + -1.5972,2.0313,0.081, -1.800455,2.031069,0.081, -1.8009,2.024775,0, + -2.03841,2.24015,0.081, -1.785445,2.243256,0.081, -1.785,2.24955,0, + -1.785,2.24955,0, -2.04,2.2464,0, -2.03841,2.24015,0.081, + -2.034093,2.223187,0.144, -1.786654,2.226173,0.144, -1.785445,2.243256,0.081, + -1.785445,2.243256,0.081, -2.03841,2.24015,0.081, -2.034093,2.223187,0.144, + -2.027731,2.198189,0.189, -1.788434,2.200999,0.189, -1.786654,2.226173,0.144, + -1.786654,2.226173,0.144, -2.034093,2.223187,0.144, -2.027731,2.198189,0.189, + -2.020006,2.167834,0.216, -1.790597,2.170429,0.216, -1.788434,2.200999,0.189, + -1.788434,2.200999,0.189, -2.027731,2.198189,0.189, -2.020006,2.167834,0.216, + -2.0116,2.1348,0.225, -1.79295,2.137163,0.225, -1.790597,2.170429,0.216, + -1.790597,2.170429,0.216, -2.020006,2.167834,0.216, -2.0116,2.1348,0.225, + -2.003194,2.101766,0.216, -1.795303,2.103896,0.216, -1.79295,2.137163,0.225, + -1.79295,2.137163,0.225, -2.0116,2.1348,0.225, -2.003194,2.101766,0.216, + -1.995469,2.071411,0.189, -1.797466,2.073326,0.189, -1.795303,2.103896,0.216, + -1.795303,2.103896,0.216, -2.003194,2.101766,0.216, -1.995469,2.071411,0.189, + -1.989107,2.046413,0.144, -1.799246,2.048152,0.144, -1.797466,2.073326,0.189, + -1.797466,2.073326,0.189, -1.995469,2.071411,0.189, -1.989107,2.046413,0.144, + -1.98479,2.02945,0.081, -1.800455,2.031069,0.081, -1.799246,2.048152,0.144, + -1.799246,2.048152,0.144, -1.989107,2.046413,0.144, -1.98479,2.02945,0.081, + -1.9832,2.0232,0, -1.8009,2.024775,0, -1.800455,2.031069,0.081, + -1.800455,2.031069,0.081, -1.98479,2.02945,0.081, -1.9832,2.0232,0, + -2.261676,2.23172,0.081, -2.03841,2.24015,0.081, -2.04,2.2464,0, + -2.04,2.2464,0, -2.265,2.23785,0, -2.261676,2.23172,0.081, + -2.252655,2.215082,0.144, -2.034093,2.223187,0.144, -2.03841,2.24015,0.081, + -2.03841,2.24015,0.081, -2.261676,2.23172,0.081, -2.252655,2.215082,0.144, + -2.239361,2.190562,0.189, -2.027731,2.198189,0.189, -2.034093,2.223187,0.144, + -2.034093,2.223187,0.144, -2.252655,2.215082,0.144, -2.239361,2.190562,0.189, + -2.223218,2.160788,0.216, -2.020006,2.167834,0.216, -2.027731,2.198189,0.189, + -2.027731,2.198189,0.189, -2.239361,2.190562,0.189, -2.223218,2.160788,0.216, + -2.20565,2.128387,0.225, -2.0116,2.1348,0.225, -2.020006,2.167834,0.216, + -2.020006,2.167834,0.216, -2.223218,2.160788,0.216, -2.20565,2.128387,0.225, + -2.188082,2.095987,0.216, -2.003194,2.101766,0.216, -2.0116,2.1348,0.225, + -2.0116,2.1348,0.225, -2.20565,2.128387,0.225, -2.188082,2.095987,0.216, + -2.171939,2.066213,0.189, -1.995469,2.071411,0.189, -2.003194,2.101766,0.216, + -2.003194,2.101766,0.216, -2.188082,2.095987,0.216, -2.171939,2.066213,0.189, + -2.158645,2.041693,0.144, -1.989107,2.046413,0.144, -1.995469,2.071411,0.189, + -1.995469,2.071411,0.189, -2.171939,2.066213,0.189, -2.158645,2.041693,0.144, + -2.149624,2.025055,0.081, -1.98479,2.02945,0.081, -1.989107,2.046413,0.144, + -1.989107,2.046413,0.144, -2.158645,2.041693,0.144, -2.149624,2.025055,0.081, + -2.1463,2.018925,0, -1.9832,2.0232,0, -1.98479,2.02945,0.081, + -1.98479,2.02945,0.081, -2.149624,2.025055,0.081, -2.1463,2.018925,0, + -2.455229,2.215303,0.081, -2.261676,2.23172,0.081, -2.265,2.23785,0, + -2.265,2.23785,0, -2.46,2.2212,0, -2.455229,2.215303,0.081, + -2.442278,2.199298,0.144, -2.252655,2.215082,0.144, -2.261676,2.23172,0.081, + -2.261676,2.23172,0.081, -2.455229,2.215303,0.081, -2.442278,2.199298,0.144, + -2.423194,2.17571,0.189, -2.239361,2.190562,0.189, -2.252655,2.215082,0.144, + -2.252655,2.215082,0.144, -2.442278,2.199298,0.144, -2.423194,2.17571,0.189, + -2.400019,2.147069,0.216, -2.223218,2.160788,0.216, -2.239361,2.190562,0.189, + -2.239361,2.190562,0.189, -2.423194,2.17571,0.189, -2.400019,2.147069,0.216, + -2.3748,2.1159,0.225, -2.20565,2.128387,0.225, -2.223218,2.160788,0.216, + -2.223218,2.160788,0.216, -2.400019,2.147069,0.216, -2.3748,2.1159,0.225, + -2.349581,2.084731,0.216, -2.188082,2.095987,0.216, -2.20565,2.128387,0.225, + -2.20565,2.128387,0.225, -2.3748,2.1159,0.225, -2.349581,2.084731,0.216, + -2.326406,2.05609,0.189, -2.171939,2.066213,0.189, -2.188082,2.095987,0.216, + -2.188082,2.095987,0.216, -2.349581,2.084731,0.216, -2.326406,2.05609,0.189, + -2.307322,2.032502,0.144, -2.158645,2.041693,0.144, -2.171939,2.066213,0.189, + -2.171939,2.066213,0.189, -2.326406,2.05609,0.189, -2.307322,2.032502,0.144, + -2.294371,2.016497,0.081, -2.149624,2.025055,0.081, -2.158645,2.041693,0.144, + -2.158645,2.041693,0.144, -2.307322,2.032502,0.144, -2.294371,2.016497,0.081, + -2.2896,2.0106,0, -2.1463,2.018925,0, -2.149624,2.025055,0.081, + -2.149624,2.025055,0.081, -2.294371,2.016497,0.081, -2.2896,2.0106,0, + -2.61905,2.188238,0.081, -2.455229,2.215303,0.081, -2.46,2.2212,0, + -2.46,2.2212,0, -2.625,2.19375,0, -2.61905,2.188238,0.081, + -2.6029,2.173275,0.144, -2.442278,2.199298,0.144, -2.455229,2.215303,0.081, + -2.455229,2.215303,0.081, -2.61905,2.188238,0.081, -2.6029,2.173275,0.144, + -2.5791,2.151225,0.189, -2.423194,2.17571,0.189, -2.442278,2.199298,0.144, + -2.442278,2.199298,0.144, -2.6029,2.173275,0.144, -2.5791,2.151225,0.189, + -2.5502,2.12445,0.216, -2.400019,2.147069,0.216, -2.423194,2.17571,0.189, + -2.423194,2.17571,0.189, -2.5791,2.151225,0.189, -2.5502,2.12445,0.216, + -2.51875,2.095312,0.225, -2.3748,2.1159,0.225, -2.400019,2.147069,0.216, + -2.400019,2.147069,0.216, -2.5502,2.12445,0.216, -2.51875,2.095312,0.225, + -2.4873,2.066175,0.216, -2.349581,2.084731,0.216, -2.3748,2.1159,0.225, + -2.3748,2.1159,0.225, -2.51875,2.095312,0.225, -2.4873,2.066175,0.216, + -2.4584,2.0394,0.189, -2.326406,2.05609,0.189, -2.349581,2.084731,0.216, + -2.349581,2.084731,0.216, -2.4873,2.066175,0.216, -2.4584,2.0394,0.189, + -2.4346,2.01735,0.144, -2.307322,2.032502,0.144, -2.326406,2.05609,0.189, + -2.326406,2.05609,0.189, -2.4584,2.0394,0.189, -2.4346,2.01735,0.144, + -2.41845,2.002388,0.081, -2.294371,2.016497,0.081, -2.307322,2.032502,0.144, + -2.307322,2.032502,0.144, -2.4346,2.01735,0.144, -2.41845,2.002388,0.081, + -2.4125,1.996875,0, -2.2896,2.0106,0, -2.294371,2.016497,0.081, + -2.294371,2.016497,0.081, -2.41845,2.002388,0.081, -2.4125,1.996875,0, + -2.753123,2.147861,0.081, -2.61905,2.188238,0.081, -2.625,2.19375,0, + -2.625,2.19375,0, -2.76,2.1528,0, -2.753123,2.147861,0.081, + -2.734458,2.134454,0.144, -2.6029,2.173275,0.144, -2.61905,2.188238,0.081, + -2.61905,2.188238,0.081, -2.753123,2.147861,0.081, -2.734458,2.134454,0.144, + -2.70695,2.114698,0.189, -2.5791,2.151225,0.189, -2.6029,2.173275,0.144, + -2.6029,2.173275,0.144, -2.734458,2.134454,0.144, -2.70695,2.114698,0.189, + -2.673549,2.090707,0.216, -2.5502,2.12445,0.216, -2.5791,2.151225,0.189, + -2.5791,2.151225,0.189, -2.70695,2.114698,0.189, -2.673549,2.090707,0.216, + -2.6372,2.0646,0.225, -2.51875,2.095312,0.225, -2.5502,2.12445,0.216, + -2.5502,2.12445,0.216, -2.673549,2.090707,0.216, -2.6372,2.0646,0.225, + -2.600851,2.038493,0.216, -2.4873,2.066175,0.216, -2.51875,2.095312,0.225, + -2.51875,2.095312,0.225, -2.6372,2.0646,0.225, -2.600851,2.038493,0.216, + -2.56745,2.014502,0.189, -2.4584,2.0394,0.189, -2.4873,2.066175,0.216, + -2.4873,2.066175,0.216, -2.600851,2.038493,0.216, -2.56745,2.014502,0.189, + -2.539942,1.994746,0.144, -2.4346,2.01735,0.144, -2.4584,2.0394,0.189, + -2.4584,2.0394,0.189, -2.56745,2.014502,0.189, -2.539942,1.994746,0.144, + -2.521277,1.981339,0.081, -2.41845,2.002388,0.081, -2.4346,2.01735,0.144, + -2.4346,2.01735,0.144, -2.539942,1.994746,0.144, -2.521277,1.981339,0.081, + -2.5144,1.9764,0, -2.4125,1.996875,0, -2.41845,2.002388,0.081, + -2.41845,2.002388,0.081, -2.521277,1.981339,0.081, -2.5144,1.9764,0, + -2.857432,2.091511,0.081, -2.753123,2.147861,0.081, -2.76,2.1528,0, + -2.76,2.1528,0, -2.865,2.09565,0, -2.857432,2.091511,0.081, + -2.836889,2.080276,0.144, -2.734458,2.134454,0.144, -2.753123,2.147861,0.081, + -2.753123,2.147861,0.081, -2.857432,2.091511,0.081, -2.836889,2.080276,0.144, + -2.806615,2.06372,0.189, -2.70695,2.114698,0.189, -2.734458,2.134454,0.144, + -2.734458,2.134454,0.144, -2.836889,2.080276,0.144, -2.806615,2.06372,0.189, + -2.769854,2.043616,0.216, -2.673549,2.090707,0.216, -2.70695,2.114698,0.189, + -2.70695,2.114698,0.189, -2.806615,2.06372,0.189, -2.769854,2.043616,0.216, + -2.72985,2.021737,0.225, -2.6372,2.0646,0.225, -2.673549,2.090707,0.216, + -2.673549,2.090707,0.216, -2.769854,2.043616,0.216, -2.72985,2.021737,0.225, + -2.689846,1.999859,0.216, -2.600851,2.038493,0.216, -2.6372,2.0646,0.225, + -2.6372,2.0646,0.225, -2.72985,2.021737,0.225, -2.689846,1.999859,0.216, + -2.653085,1.979755,0.189, -2.56745,2.014502,0.189, -2.600851,2.038493,0.216, + -2.600851,2.038493,0.216, -2.689846,1.999859,0.216, -2.653085,1.979755,0.189, + -2.622811,1.963199,0.144, -2.539942,1.994746,0.144, -2.56745,2.014502,0.189, + -2.56745,2.014502,0.189, -2.653085,1.979755,0.189, -2.622811,1.963199,0.144, + -2.602268,1.951964,0.081, -2.521277,1.981339,0.081, -2.539942,1.994746,0.144, + -2.539942,1.994746,0.144, -2.622811,1.963199,0.144, -2.602268,1.951964,0.081, + -2.5947,1.947825,0, -2.5144,1.9764,0, -2.521277,1.981339,0.081, + -2.521277,1.981339,0.081, -2.602268,1.951964,0.081, -2.5947,1.947825,0, + -2.931958,2.016526,0.081, -2.857432,2.091511,0.081, -2.865,2.09565,0, + -2.865,2.09565,0, -2.94,2.0196,0, -2.931958,2.016526,0.081, + -2.910131,2.008181,0.144, -2.836889,2.080276,0.144, -2.857432,2.091511,0.081, + -2.857432,2.091511,0.081, -2.931958,2.016526,0.081, -2.910131,2.008181,0.144, + -2.877965,1.995883,0.189, -2.806615,2.06372,0.189, -2.836889,2.080276,0.144, + -2.836889,2.080276,0.144, -2.910131,2.008181,0.144, -2.877965,1.995883,0.189, + -2.838906,1.98095,0.216, -2.769854,2.043616,0.216, -2.806615,2.06372,0.189, + -2.806615,2.06372,0.189, -2.877965,1.995883,0.189, -2.838906,1.98095,0.216, + -2.7964,1.9647,0.225, -2.72985,2.021737,0.225, -2.769854,2.043616,0.216, + -2.769854,2.043616,0.216, -2.838906,1.98095,0.216, -2.7964,1.9647,0.225, + -2.753894,1.94845,0.216, -2.689846,1.999859,0.216, -2.72985,2.021737,0.225, + -2.72985,2.021737,0.225, -2.7964,1.9647,0.225, -2.753894,1.94845,0.216, + -2.714835,1.933517,0.189, -2.653085,1.979755,0.189, -2.689846,1.999859,0.216, + -2.689846,1.999859,0.216, -2.753894,1.94845,0.216, -2.714835,1.933517,0.189, + -2.682669,1.921219,0.144, -2.622811,1.963199,0.144, -2.653085,1.979755,0.189, + -2.653085,1.979755,0.189, -2.714835,1.933517,0.189, -2.682669,1.921219,0.144, + -2.660842,1.912874,0.081, -2.602268,1.951964,0.081, -2.622811,1.963199,0.144, + -2.622811,1.963199,0.144, -2.682669,1.921219,0.144, -2.660842,1.912874,0.081, + -2.6528,1.9098,0, -2.5947,1.947825,0, -2.602268,1.951964,0.081, + -2.602268,1.951964,0.081, -2.660842,1.912874,0.081, -2.6528,1.9098,0, + -2.976687,1.920243,0.081, -2.931958,2.016526,0.081, -2.94,2.0196,0, + -2.94,2.0196,0, -2.985,1.92195,0, -2.976687,1.920243,0.081, + -2.954122,1.915609,0.144, -2.910131,2.008181,0.144, -2.931958,2.016526,0.081, + -2.931958,2.016526,0.081, -2.976687,1.920243,0.081, -2.954122,1.915609,0.144, + -2.92087,1.908779,0.189, -2.877965,1.995883,0.189, -2.910131,2.008181,0.144, + -2.910131,2.008181,0.144, -2.954122,1.915609,0.144, -2.92087,1.908779,0.189, + -2.880491,1.900487,0.216, -2.838906,1.98095,0.216, -2.877965,1.995883,0.189, + -2.877965,1.995883,0.189, -2.92087,1.908779,0.189, -2.880491,1.900487,0.216, + -2.83655,1.891463,0.225, -2.7964,1.9647,0.225, -2.838906,1.98095,0.216, + -2.838906,1.98095,0.216, -2.880491,1.900487,0.216, -2.83655,1.891463,0.225, + -2.792609,1.882438,0.216, -2.753894,1.94845,0.216, -2.7964,1.9647,0.225, + -2.7964,1.9647,0.225, -2.83655,1.891463,0.225, -2.792609,1.882438,0.216, + -2.75223,1.874146,0.189, -2.714835,1.933517,0.189, -2.753894,1.94845,0.216, + -2.753894,1.94845,0.216, -2.792609,1.882438,0.216, -2.75223,1.874146,0.189, + -2.718978,1.867316,0.144, -2.682669,1.921219,0.144, -2.714835,1.933517,0.189, + -2.714835,1.933517,0.189, -2.75223,1.874146,0.189, -2.718978,1.867316,0.144, + -2.696413,1.862682,0.081, -2.660842,1.912874,0.081, -2.682669,1.921219,0.144, + -2.682669,1.921219,0.144, -2.718978,1.867316,0.144, -2.696413,1.862682,0.081, + -2.6881,1.860975,0, -2.6528,1.9098,0, -2.660842,1.912874,0.081, + -2.660842,1.912874,0.081, -2.696413,1.862682,0.081, -2.6881,1.860975,0, + -2.9916,1.8,0.081, -2.976687,1.920243,0.081, -2.985,1.92195,0, + -2.985,1.92195,0, -3,1.8,0, -2.9916,1.8,0.081, + -2.9688,1.8,0.144, -2.954122,1.915609,0.144, -2.976687,1.920243,0.081, + -2.976687,1.920243,0.081, -2.9916,1.8,0.081, -2.9688,1.8,0.144, + -2.9352,1.8,0.189, -2.92087,1.908779,0.189, -2.954122,1.915609,0.144, + -2.954122,1.915609,0.144, -2.9688,1.8,0.144, -2.9352,1.8,0.189, + -2.8944,1.8,0.216, -2.880491,1.900487,0.216, -2.92087,1.908779,0.189, + -2.92087,1.908779,0.189, -2.9352,1.8,0.189, -2.8944,1.8,0.216, + -2.85,1.8,0.225, -2.83655,1.891463,0.225, -2.880491,1.900487,0.216, + -2.880491,1.900487,0.216, -2.8944,1.8,0.216, -2.85,1.8,0.225, + -2.8056,1.8,0.216, -2.792609,1.882438,0.216, -2.83655,1.891463,0.225, + -2.83655,1.891463,0.225, -2.85,1.8,0.225, -2.8056,1.8,0.216, + -2.7648,1.8,0.189, -2.75223,1.874146,0.189, -2.792609,1.882438,0.216, + -2.792609,1.882438,0.216, -2.8056,1.8,0.216, -2.7648,1.8,0.189, + -2.7312,1.8,0.144, -2.718978,1.867316,0.144, -2.75223,1.874146,0.189, + -2.75223,1.874146,0.189, -2.7648,1.8,0.189, -2.7312,1.8,0.144, + -2.7084,1.8,0.081, -2.696413,1.862682,0.081, -2.718978,1.867316,0.144, + -2.718978,1.867316,0.144, -2.7312,1.8,0.144, -2.7084,1.8,0.081, + -2.7,1.8,0, -2.6881,1.860975,0, -2.696413,1.862682,0.081, + -2.696413,1.862682,0.081, -2.7084,1.8,0.081, -2.7,1.8,0, + -2.702175,1.724519,-0.081, -2.7084,1.8,-0.081, -2.7,1.8,0, + -2.7,1.8,0, -2.6939,1.7262,0, -2.702175,1.724519,-0.081, + -2.724637,1.719956,-0.144, -2.7312,1.8,-0.144, -2.7084,1.8,-0.081, + -2.7084,1.8,-0.081, -2.702175,1.724519,-0.081, -2.724637,1.719956,-0.144, + -2.757739,1.713232,-0.189, -2.7648,1.8,-0.189, -2.7312,1.8,-0.144, + -2.7312,1.8,-0.144, -2.724637,1.719956,-0.144, -2.757739,1.713232,-0.189, + -2.797934,1.705067,-0.216, -2.8056,1.8,-0.216, -2.7648,1.8,-0.189, + -2.7648,1.8,-0.189, -2.757739,1.713232,-0.189, -2.797934,1.705067,-0.216, + -2.841675,1.696181,-0.225, -2.85,1.8,-0.225, -2.8056,1.8,-0.216, + -2.8056,1.8,-0.216, -2.797934,1.705067,-0.216, -2.841675,1.696181,-0.225, + -2.885416,1.687296,-0.216, -2.8944,1.8,-0.216, -2.85,1.8,-0.225, + -2.85,1.8,-0.225, -2.841675,1.696181,-0.225, -2.885416,1.687296,-0.216, + -2.925611,1.679131,-0.189, -2.9352,1.8,-0.189, -2.8944,1.8,-0.216, + -2.8944,1.8,-0.216, -2.885416,1.687296,-0.216, -2.925611,1.679131,-0.189, + -2.958713,1.672406,-0.144, -2.9688,1.8,-0.144, -2.9352,1.8,-0.189, + -2.9352,1.8,-0.189, -2.925611,1.679131,-0.189, -2.958713,1.672406,-0.144, + -2.981175,1.667844,-0.081, -2.9916,1.8,-0.081, -2.9688,1.8,-0.144, + -2.9688,1.8,-0.144, -2.958713,1.672406,-0.144, -2.981175,1.667844,-0.081, + -2.98945,1.666162,0, -3,1.8,0, -2.9916,1.8,-0.081, + -2.9916,1.8,-0.081, -2.981175,1.667844,-0.081, -2.98945,1.666162,0, + -2.683107,1.63861,-0.081, -2.702175,1.724519,-0.081, -2.6939,1.7262,0, + -2.6939,1.7262,0, -2.6752,1.6416,0, -2.683107,1.63861,-0.081, + -2.70457,1.630493,-0.144, -2.724637,1.719956,-0.144, -2.702175,1.724519,-0.081, + -2.702175,1.724519,-0.081, -2.683107,1.63861,-0.081, -2.70457,1.630493,-0.144, + -2.736198,1.618531,-0.189, -2.757739,1.713232,-0.189, -2.724637,1.719956,-0.144, + -2.724637,1.719956,-0.144, -2.70457,1.630493,-0.144, -2.736198,1.618531,-0.189, + -2.774605,1.604006,-0.216, -2.797934,1.705067,-0.216, -2.757739,1.713232,-0.189, + -2.757739,1.713232,-0.189, -2.736198,1.618531,-0.189, -2.774605,1.604006,-0.216, + -2.8164,1.5882,-0.225, -2.841675,1.696181,-0.225, -2.797934,1.705067,-0.216, + -2.797934,1.705067,-0.216, -2.774605,1.604006,-0.216, -2.8164,1.5882,-0.225, + -2.858195,1.572394,-0.216, -2.885416,1.687296,-0.216, -2.841675,1.696181,-0.225, + -2.841675,1.696181,-0.225, -2.8164,1.5882,-0.225, -2.858195,1.572394,-0.216, + -2.896602,1.557869,-0.189, -2.925611,1.679131,-0.189, -2.885416,1.687296,-0.216, + -2.885416,1.687296,-0.216, -2.858195,1.572394,-0.216, -2.896602,1.557869,-0.189, + -2.92823,1.545907,-0.144, -2.958713,1.672406,-0.144, -2.925611,1.679131,-0.189, + -2.925611,1.679131,-0.189, -2.896602,1.557869,-0.189, -2.92823,1.545907,-0.144, + -2.949693,1.53779,-0.081, -2.981175,1.667844,-0.081, -2.958713,1.672406,-0.144, + -2.958713,1.672406,-0.144, -2.92823,1.545907,-0.144, -2.949693,1.53779,-0.081, + -2.9576,1.5348,0, -2.98945,1.666162,0, -2.981175,1.667844,-0.081, + -2.981175,1.667844,-0.081, -2.949693,1.53779,-0.081, -2.9576,1.5348,0, + -2.650604,1.544903,-0.081, -2.683107,1.63861,-0.081, -2.6752,1.6416,0, + -2.6752,1.6416,0, -2.6433,1.5489,0, -2.650604,1.544903,-0.081, + -2.670428,1.534053,-0.144, -2.70457,1.630493,-0.144, -2.683107,1.63861,-0.081, + -2.683107,1.63861,-0.081, -2.650604,1.544903,-0.081, -2.670428,1.534053,-0.144, + -2.699644,1.518063,-0.189, -2.736198,1.618531,-0.189, -2.70457,1.630493,-0.144, + -2.70457,1.630493,-0.144, -2.670428,1.534053,-0.144, -2.699644,1.518063,-0.189, + -2.735119,1.498648,-0.216, -2.774605,1.604006,-0.216, -2.736198,1.618531,-0.189, + -2.736198,1.618531,-0.189, -2.699644,1.518063,-0.189, -2.735119,1.498648,-0.216, + -2.773725,1.477519,-0.225, -2.8164,1.5882,-0.225, -2.774605,1.604006,-0.216, + -2.774605,1.604006,-0.216, -2.735119,1.498648,-0.216, -2.773725,1.477519,-0.225, + -2.812331,1.45639,-0.216, -2.858195,1.572394,-0.216, -2.8164,1.5882,-0.225, + -2.8164,1.5882,-0.225, -2.773725,1.477519,-0.225, -2.812331,1.45639,-0.216, + -2.847806,1.436974,-0.189, -2.896602,1.557869,-0.189, -2.858195,1.572394,-0.216, + -2.858195,1.572394,-0.216, -2.812331,1.45639,-0.216, -2.847806,1.436974,-0.189, + -2.877022,1.420985,-0.144, -2.92823,1.545907,-0.144, -2.896602,1.557869,-0.189, + -2.896602,1.557869,-0.189, -2.847806,1.436974,-0.189, -2.877022,1.420985,-0.144, + -2.896846,1.410135,-0.081, -2.949693,1.53779,-0.081, -2.92823,1.545907,-0.144, + -2.92823,1.545907,-0.144, -2.877022,1.420985,-0.144, -2.896846,1.410135,-0.081, + -2.90415,1.406137,0, -2.9576,1.5348,0, -2.949693,1.53779,-0.081, + -2.949693,1.53779,-0.081, -2.896846,1.410135,-0.081, -2.90415,1.406137,0, + -2.604074,1.446029,-0.081, -2.650604,1.544903,-0.081, -2.6433,1.5489,0, + -2.6433,1.5489,0, -2.5976,1.4508,0, -2.604074,1.446029,-0.081, + -2.621645,1.433078,-0.144, -2.670428,1.534053,-0.144, -2.650604,1.544903,-0.081, + -2.650604,1.544903,-0.081, -2.604074,1.446029,-0.081, -2.621645,1.433078,-0.144, + -2.647539,1.413994,-0.189, -2.699644,1.518063,-0.189, -2.670428,1.534053,-0.144, + -2.670428,1.534053,-0.144, -2.621645,1.433078,-0.144, -2.647539,1.413994,-0.189, + -2.678982,1.390819,-0.216, -2.735119,1.498648,-0.216, -2.699644,1.518063,-0.189, + -2.699644,1.518063,-0.189, -2.647539,1.413994,-0.189, -2.678982,1.390819,-0.216, + -2.7132,1.3656,-0.225, -2.773725,1.477519,-0.225, -2.735119,1.498648,-0.216, + -2.735119,1.498648,-0.216, -2.678982,1.390819,-0.216, -2.7132,1.3656,-0.225, + -2.747418,1.340381,-0.216, -2.812331,1.45639,-0.216, -2.773725,1.477519,-0.225, + -2.773725,1.477519,-0.225, -2.7132,1.3656,-0.225, -2.747418,1.340381,-0.216, + -2.778861,1.317206,-0.189, -2.847806,1.436974,-0.189, -2.812331,1.45639,-0.216, + -2.812331,1.45639,-0.216, -2.747418,1.340381,-0.216, -2.778861,1.317206,-0.189, + -2.804755,1.298122,-0.144, -2.877022,1.420985,-0.144, -2.847806,1.436974,-0.189, + -2.847806,1.436974,-0.189, -2.778861,1.317206,-0.189, -2.804755,1.298122,-0.144, + -2.822326,1.285171,-0.081, -2.896846,1.410135,-0.081, -2.877022,1.420985,-0.144, + -2.877022,1.420985,-0.144, -2.804755,1.298122,-0.144, -2.822326,1.285171,-0.081, + -2.8288,1.2804,0, -2.90415,1.406137,0, -2.896846,1.410135,-0.081, + -2.896846,1.410135,-0.081, -2.822326,1.285171,-0.081, -2.8288,1.2804,0, + -2.542925,1.344619,-0.081, -2.604074,1.446029,-0.081, -2.5976,1.4508,0, + -2.5976,1.4508,0, -2.5375,1.35,0, -2.542925,1.344619,-0.081, + -2.55765,1.330013,-0.144, -2.621645,1.433078,-0.144, -2.604074,1.446029,-0.081, + -2.604074,1.446029,-0.081, -2.542925,1.344619,-0.081, -2.55765,1.330013,-0.144, + -2.57935,1.308488,-0.189, -2.647539,1.413994,-0.189, -2.621645,1.433078,-0.144, + -2.621645,1.433078,-0.144, -2.55765,1.330013,-0.144, -2.57935,1.308488,-0.189, + -2.6057,1.28235,-0.216, -2.678982,1.390819,-0.216, -2.647539,1.413994,-0.189, + -2.647539,1.413994,-0.189, -2.57935,1.308488,-0.189, -2.6057,1.28235,-0.216, + -2.634375,1.253906,-0.225, -2.7132,1.3656,-0.225, -2.678982,1.390819,-0.216, + -2.678982,1.390819,-0.216, -2.6057,1.28235,-0.216, -2.634375,1.253906,-0.225, + -2.66305,1.225463,-0.216, -2.747418,1.340381,-0.216, -2.7132,1.3656,-0.225, + -2.7132,1.3656,-0.225, -2.634375,1.253906,-0.225, -2.66305,1.225463,-0.216, + -2.6894,1.199325,-0.189, -2.778861,1.317206,-0.189, -2.747418,1.340381,-0.216, + -2.747418,1.340381,-0.216, -2.66305,1.225463,-0.216, -2.6894,1.199325,-0.189, + -2.7111,1.1778,-0.144, -2.804755,1.298122,-0.144, -2.778861,1.317206,-0.189, + -2.778861,1.317206,-0.189, -2.6894,1.199325,-0.189, -2.7111,1.1778,-0.144, + -2.725825,1.163194,-0.081, -2.822326,1.285171,-0.081, -2.804755,1.298122,-0.144, + -2.804755,1.298122,-0.144, -2.7111,1.1778,-0.144, -2.725825,1.163194,-0.081, + -2.73125,1.157813,0, -2.8288,1.2804,0, -2.822326,1.285171,-0.081, + -2.822326,1.285171,-0.081, -2.725825,1.163194,-0.081, -2.73125,1.157813,0, + -2.466566,1.243303,-0.081, -2.542925,1.344619,-0.081, -2.5375,1.35,0, + -2.5375,1.35,0, -2.4624,1.2492,0, -2.466566,1.243303,-0.081, + -2.477875,1.227298,-0.144, -2.55765,1.330013,-0.144, -2.542925,1.344619,-0.081, + -2.542925,1.344619,-0.081, -2.466566,1.243303,-0.081, -2.477875,1.227298,-0.144, + -2.494541,1.20371,-0.189, -2.57935,1.308488,-0.189, -2.55765,1.330013,-0.144, + -2.55765,1.330013,-0.144, -2.477875,1.227298,-0.144, -2.494541,1.20371,-0.189, + -2.514778,1.175069,-0.216, -2.6057,1.28235,-0.216, -2.57935,1.308488,-0.189, + -2.57935,1.308488,-0.189, -2.494541,1.20371,-0.189, -2.514778,1.175069,-0.216, + -2.5368,1.1439,-0.225, -2.634375,1.253906,-0.225, -2.6057,1.28235,-0.216, + -2.6057,1.28235,-0.216, -2.514778,1.175069,-0.216, -2.5368,1.1439,-0.225, + -2.558822,1.112731,-0.216, -2.66305,1.225463,-0.216, -2.634375,1.253906,-0.225, + -2.634375,1.253906,-0.225, -2.5368,1.1439,-0.225, -2.558822,1.112731,-0.216, + -2.579059,1.08409,-0.189, -2.6894,1.199325,-0.189, -2.66305,1.225463,-0.216, + -2.66305,1.225463,-0.216, -2.558822,1.112731,-0.216, -2.579059,1.08409,-0.189, + -2.595725,1.060502,-0.144, -2.7111,1.1778,-0.144, -2.6894,1.199325,-0.189, + -2.6894,1.199325,-0.189, -2.579059,1.08409,-0.189, -2.595725,1.060502,-0.144, + -2.607034,1.044497,-0.081, -2.725825,1.163194,-0.081, -2.7111,1.1778,-0.144, + -2.7111,1.1778,-0.144, -2.595725,1.060502,-0.144, -2.607034,1.044497,-0.081, + -2.6112,1.0386,0, -2.73125,1.157813,0, -2.725825,1.163194,-0.081, + -2.725825,1.163194,-0.081, -2.607034,1.044497,-0.081, -2.6112,1.0386,0, + -2.374406,1.144713,-0.081, -2.466566,1.243303,-0.081, -2.4624,1.2492,0, + -2.4624,1.2492,0, -2.3717,1.1511,0, -2.374406,1.144713,-0.081, + -2.381752,1.127376,-0.144, -2.477875,1.227298,-0.144, -2.466566,1.243303,-0.081, + -2.466566,1.243303,-0.081, -2.374406,1.144713,-0.081, -2.381752,1.127376,-0.144, + -2.392576,1.101828,-0.189, -2.494541,1.20371,-0.189, -2.477875,1.227298,-0.144, + -2.477875,1.227298,-0.144, -2.381752,1.127376,-0.144, -2.392576,1.101828,-0.189, + -2.405721,1.070804,-0.216, -2.514778,1.175069,-0.216, -2.494541,1.20371,-0.189, + -2.494541,1.20371,-0.189, -2.392576,1.101828,-0.189, -2.405721,1.070804,-0.216, + -2.420025,1.037044,-0.225, -2.5368,1.1439,-0.225, -2.514778,1.175069,-0.216, + -2.514778,1.175069,-0.216, -2.405721,1.070804,-0.216, -2.420025,1.037044,-0.225, + -2.434329,1.003283,-0.216, -2.558822,1.112731,-0.216, -2.5368,1.1439,-0.225, + -2.5368,1.1439,-0.225, -2.420025,1.037044,-0.225, -2.434329,1.003283,-0.216, + -2.447474,0.97226,-0.189, -2.579059,1.08409,-0.189, -2.558822,1.112731,-0.216, + -2.558822,1.112731,-0.216, -2.434329,1.003283,-0.216, -2.447474,0.97226,-0.189, + -2.458298,0.946711,-0.144, -2.595725,1.060502,-0.144, -2.579059,1.08409,-0.189, + -2.579059,1.08409,-0.189, -2.447474,0.97226,-0.189, -2.458298,0.946711,-0.144, + -2.465644,0.929375,-0.081, -2.607034,1.044497,-0.081, -2.595725,1.060502,-0.144, + -2.595725,1.060502,-0.144, -2.458298,0.946711,-0.144, -2.465644,0.929375,-0.081, + -2.46835,0.922987,0, -2.6112,1.0386,0, -2.607034,1.044497,-0.081, + -2.607034,1.044497,-0.081, -2.465644,0.929375,-0.081, -2.46835,0.922987,0, + -2.265853,1.051478,-0.081, -2.374406,1.144713,-0.081, -2.3717,1.1511,0, + -2.3717,1.1511,0, -2.2648,1.0584,0, -2.265853,1.051478,-0.081, + -2.26871,1.032691,-0.144, -2.381752,1.127376,-0.144, -2.374406,1.144713,-0.081, + -2.374406,1.144713,-0.081, -2.265853,1.051478,-0.081, -2.26871,1.032691,-0.144, + -2.272922,1.005005,-0.189, -2.392576,1.101828,-0.189, -2.381752,1.127376,-0.144, + -2.381752,1.127376,-0.144, -2.26871,1.032691,-0.144, -2.272922,1.005005,-0.189, + -2.278035,0.971386,-0.216, -2.405721,1.070804,-0.216, -2.392576,1.101828,-0.189, + -2.392576,1.101828,-0.189, -2.272922,1.005005,-0.189, -2.278035,0.971386,-0.216, + -2.2836,0.9348,-0.225, -2.420025,1.037044,-0.225, -2.405721,1.070804,-0.216, + -2.405721,1.070804,-0.216, -2.278035,0.971386,-0.216, -2.2836,0.9348,-0.225, + -2.289165,0.898214,-0.216, -2.434329,1.003283,-0.216, -2.420025,1.037044,-0.225, + -2.420025,1.037044,-0.225, -2.2836,0.9348,-0.225, -2.289165,0.898214,-0.216, + -2.294278,0.864595,-0.189, -2.447474,0.97226,-0.189, -2.434329,1.003283,-0.216, + -2.434329,1.003283,-0.216, -2.289165,0.898214,-0.216, -2.294278,0.864595,-0.189, + -2.29849,0.836909,-0.144, -2.458298,0.946711,-0.144, -2.447474,0.97226,-0.189, + -2.447474,0.97226,-0.189, -2.294278,0.864595,-0.189, -2.29849,0.836909,-0.144, + -2.301347,0.818122,-0.081, -2.465644,0.929375,-0.081, -2.458298,0.946711,-0.144, + -2.458298,0.946711,-0.144, -2.29849,0.836909,-0.144, -2.301347,0.818122,-0.081, + -2.3024,0.8112,0, -2.46835,0.922987,0, -2.465644,0.929375,-0.081, + -2.465644,0.929375,-0.081, -2.301347,0.818122,-0.081, -2.3024,0.8112,0, + -2.140315,0.966231,-0.081, -2.265853,1.051478,-0.081, -2.2648,1.0584,0, + -2.2648,1.0584,0, -2.1411,0.9738,0, -2.140315,0.966231,-0.081, + -2.138183,0.945685,-0.144, -2.26871,1.032691,-0.144, -2.265853,1.051478,-0.081, + -2.265853,1.051478,-0.081, -2.140315,0.966231,-0.081, -2.138183,0.945685,-0.144, + -2.135041,0.915407,-0.189, -2.272922,1.005005,-0.189, -2.26871,1.032691,-0.144, + -2.26871,1.032691,-0.144, -2.138183,0.945685,-0.144, -2.135041,0.915407,-0.189, + -2.131226,0.878641,-0.216, -2.278035,0.971386,-0.216, -2.272922,1.005005,-0.189, + -2.272922,1.005005,-0.189, -2.135041,0.915407,-0.189, -2.131226,0.878641,-0.216, + -2.127075,0.838631,-0.225, -2.2836,0.9348,-0.225, -2.278035,0.971386,-0.216, + -2.278035,0.971386,-0.216, -2.131226,0.878641,-0.216, -2.127075,0.838631,-0.225, + -2.122924,0.798621,-0.216, -2.289165,0.898214,-0.216, -2.2836,0.9348,-0.225, + -2.2836,0.9348,-0.225, -2.127075,0.838631,-0.225, -2.122924,0.798621,-0.216, + -2.119109,0.761855,-0.189, -2.294278,0.864595,-0.189, -2.289165,0.898214,-0.216, + -2.289165,0.898214,-0.216, -2.122924,0.798621,-0.216, -2.119109,0.761855,-0.189, + -2.115967,0.731578,-0.144, -2.29849,0.836909,-0.144, -2.294278,0.864595,-0.189, + -2.294278,0.864595,-0.189, -2.119109,0.761855,-0.189, -2.115967,0.731578,-0.144, + -2.113835,0.711032,-0.081, -2.301347,0.818122,-0.081, -2.29849,0.836909,-0.144, + -2.29849,0.836909,-0.144, -2.115967,0.731578,-0.144, -2.113835,0.711032,-0.081, + -2.11305,0.703463,0, -2.3024,0.8112,0, -2.301347,0.818122,-0.081, + -2.301347,0.818122,-0.081, -2.113835,0.711032,-0.081, -2.11305,0.703463,0, + -1.9972,0.8916,-0.081, -2.140315,0.966231,-0.081, -2.1411,0.9738,0, + -2.1411,0.9738,0, -2,0.9,0, -1.9972,0.8916,-0.081, + -1.9896,0.8688,-0.144, -2.138183,0.945685,-0.144, -2.140315,0.966231,-0.081, + -2.140315,0.966231,-0.081, -1.9972,0.8916,-0.081, -1.9896,0.8688,-0.144, + -1.9784,0.8352,-0.189, -2.135041,0.915407,-0.189, -2.138183,0.945685,-0.144, + -2.138183,0.945685,-0.144, -1.9896,0.8688,-0.144, -1.9784,0.8352,-0.189, + -1.9648,0.7944,-0.216, -2.131226,0.878641,-0.216, -2.135041,0.915407,-0.189, + -2.135041,0.915407,-0.189, -1.9784,0.8352,-0.189, -1.9648,0.7944,-0.216, + -1.95,0.75,-0.225, -2.127075,0.838631,-0.225, -2.131226,0.878641,-0.216, + -2.131226,0.878641,-0.216, -1.9648,0.7944,-0.216, -1.95,0.75,-0.225, + -1.9352,0.7056,-0.216, -2.122924,0.798621,-0.216, -2.127075,0.838631,-0.225, + -2.127075,0.838631,-0.225, -1.95,0.75,-0.225, -1.9352,0.7056,-0.216, + -1.9216,0.6648,-0.189, -2.119109,0.761855,-0.189, -2.122924,0.798621,-0.216, + -2.122924,0.798621,-0.216, -1.9352,0.7056,-0.216, -1.9216,0.6648,-0.189, + -1.9104,0.6312,-0.144, -2.115967,0.731578,-0.144, -2.119109,0.761855,-0.189, + -2.119109,0.761855,-0.189, -1.9216,0.6648,-0.189, -1.9104,0.6312,-0.144, + -1.9028,0.6084,-0.081, -2.113835,0.711032,-0.081, -2.115967,0.731578,-0.144, + -2.115967,0.731578,-0.144, -1.9104,0.6312,-0.144, -1.9028,0.6084,-0.081, + -1.9,0.6,0, -2.11305,0.703463,0, -2.113835,0.711032,-0.081, + -2.113835,0.711032,-0.081, -1.9028,0.6084,-0.081, -1.9,0.6,0, + -2.981175,1.667844,0.081, -2.9916,1.8,0.081, -3,1.8,0, + -3,1.8,0, -2.98945,1.666162,0, -2.981175,1.667844,0.081, + -2.958713,1.672406,0.144, -2.9688,1.8,0.144, -2.9916,1.8,0.081, + -2.9916,1.8,0.081, -2.981175,1.667844,0.081, -2.958713,1.672406,0.144, + -2.925611,1.679131,0.189, -2.9352,1.8,0.189, -2.9688,1.8,0.144, + -2.9688,1.8,0.144, -2.958713,1.672406,0.144, -2.925611,1.679131,0.189, + -2.885416,1.687296,0.216, -2.8944,1.8,0.216, -2.9352,1.8,0.189, + -2.9352,1.8,0.189, -2.925611,1.679131,0.189, -2.885416,1.687296,0.216, + -2.841675,1.696181,0.225, -2.85,1.8,0.225, -2.8944,1.8,0.216, + -2.8944,1.8,0.216, -2.885416,1.687296,0.216, -2.841675,1.696181,0.225, + -2.797934,1.705067,0.216, -2.8056,1.8,0.216, -2.85,1.8,0.225, + -2.85,1.8,0.225, -2.841675,1.696181,0.225, -2.797934,1.705067,0.216, + -2.757739,1.713232,0.189, -2.7648,1.8,0.189, -2.8056,1.8,0.216, + -2.8056,1.8,0.216, -2.797934,1.705067,0.216, -2.757739,1.713232,0.189, + -2.724637,1.719956,0.144, -2.7312,1.8,0.144, -2.7648,1.8,0.189, + -2.7648,1.8,0.189, -2.757739,1.713232,0.189, -2.724637,1.719956,0.144, + -2.702175,1.724519,0.081, -2.7084,1.8,0.081, -2.7312,1.8,0.144, + -2.7312,1.8,0.144, -2.724637,1.719956,0.144, -2.702175,1.724519,0.081, + -2.6939,1.7262,0, -2.7,1.8,0, -2.7084,1.8,0.081, + -2.7084,1.8,0.081, -2.702175,1.724519,0.081, -2.6939,1.7262,0, + -2.949693,1.53779,0.081, -2.981175,1.667844,0.081, -2.98945,1.666162,0, + -2.98945,1.666162,0, -2.9576,1.5348,0, -2.949693,1.53779,0.081, + -2.92823,1.545907,0.144, -2.958713,1.672406,0.144, -2.981175,1.667844,0.081, + -2.981175,1.667844,0.081, -2.949693,1.53779,0.081, -2.92823,1.545907,0.144, + -2.896602,1.557869,0.189, -2.925611,1.679131,0.189, -2.958713,1.672406,0.144, + -2.958713,1.672406,0.144, -2.92823,1.545907,0.144, -2.896602,1.557869,0.189, + -2.858195,1.572394,0.216, -2.885416,1.687296,0.216, -2.925611,1.679131,0.189, + -2.925611,1.679131,0.189, -2.896602,1.557869,0.189, -2.858195,1.572394,0.216, + -2.8164,1.5882,0.225, -2.841675,1.696181,0.225, -2.885416,1.687296,0.216, + -2.885416,1.687296,0.216, -2.858195,1.572394,0.216, -2.8164,1.5882,0.225, + -2.774605,1.604006,0.216, -2.797934,1.705067,0.216, -2.841675,1.696181,0.225, + -2.841675,1.696181,0.225, -2.8164,1.5882,0.225, -2.774605,1.604006,0.216, + -2.736198,1.618531,0.189, -2.757739,1.713232,0.189, -2.797934,1.705067,0.216, + -2.797934,1.705067,0.216, -2.774605,1.604006,0.216, -2.736198,1.618531,0.189, + -2.70457,1.630493,0.144, -2.724637,1.719956,0.144, -2.757739,1.713232,0.189, + -2.757739,1.713232,0.189, -2.736198,1.618531,0.189, -2.70457,1.630493,0.144, + -2.683107,1.63861,0.081, -2.702175,1.724519,0.081, -2.724637,1.719956,0.144, + -2.724637,1.719956,0.144, -2.70457,1.630493,0.144, -2.683107,1.63861,0.081, + -2.6752,1.6416,0, -2.6939,1.7262,0, -2.702175,1.724519,0.081, + -2.702175,1.724519,0.081, -2.683107,1.63861,0.081, -2.6752,1.6416,0, + -2.896846,1.410135,0.081, -2.949693,1.53779,0.081, -2.9576,1.5348,0, + -2.9576,1.5348,0, -2.90415,1.406137,0, -2.896846,1.410135,0.081, + -2.877022,1.420985,0.144, -2.92823,1.545907,0.144, -2.949693,1.53779,0.081, + -2.949693,1.53779,0.081, -2.896846,1.410135,0.081, -2.877022,1.420985,0.144, + -2.847806,1.436974,0.189, -2.896602,1.557869,0.189, -2.92823,1.545907,0.144, + -2.92823,1.545907,0.144, -2.877022,1.420985,0.144, -2.847806,1.436974,0.189, + -2.812331,1.45639,0.216, -2.858195,1.572394,0.216, -2.896602,1.557869,0.189, + -2.896602,1.557869,0.189, -2.847806,1.436974,0.189, -2.812331,1.45639,0.216, + -2.773725,1.477519,0.225, -2.8164,1.5882,0.225, -2.858195,1.572394,0.216, + -2.858195,1.572394,0.216, -2.812331,1.45639,0.216, -2.773725,1.477519,0.225, + -2.735119,1.498648,0.216, -2.774605,1.604006,0.216, -2.8164,1.5882,0.225, + -2.8164,1.5882,0.225, -2.773725,1.477519,0.225, -2.735119,1.498648,0.216, + -2.699644,1.518063,0.189, -2.736198,1.618531,0.189, -2.774605,1.604006,0.216, + -2.774605,1.604006,0.216, -2.735119,1.498648,0.216, -2.699644,1.518063,0.189, + -2.670428,1.534053,0.144, -2.70457,1.630493,0.144, -2.736198,1.618531,0.189, + -2.736198,1.618531,0.189, -2.699644,1.518063,0.189, -2.670428,1.534053,0.144, + -2.650604,1.544903,0.081, -2.683107,1.63861,0.081, -2.70457,1.630493,0.144, + -2.70457,1.630493,0.144, -2.670428,1.534053,0.144, -2.650604,1.544903,0.081, + -2.6433,1.5489,0, -2.6752,1.6416,0, -2.683107,1.63861,0.081, + -2.683107,1.63861,0.081, -2.650604,1.544903,0.081, -2.6433,1.5489,0, + -2.822326,1.285171,0.081, -2.896846,1.410135,0.081, -2.90415,1.406137,0, + -2.90415,1.406137,0, -2.8288,1.2804,0, -2.822326,1.285171,0.081, + -2.804755,1.298122,0.144, -2.877022,1.420985,0.144, -2.896846,1.410135,0.081, + -2.896846,1.410135,0.081, -2.822326,1.285171,0.081, -2.804755,1.298122,0.144, + -2.778861,1.317206,0.189, -2.847806,1.436974,0.189, -2.877022,1.420985,0.144, + -2.877022,1.420985,0.144, -2.804755,1.298122,0.144, -2.778861,1.317206,0.189, + -2.747418,1.340381,0.216, -2.812331,1.45639,0.216, -2.847806,1.436974,0.189, + -2.847806,1.436974,0.189, -2.778861,1.317206,0.189, -2.747418,1.340381,0.216, + -2.7132,1.3656,0.225, -2.773725,1.477519,0.225, -2.812331,1.45639,0.216, + -2.812331,1.45639,0.216, -2.747418,1.340381,0.216, -2.7132,1.3656,0.225, + -2.678982,1.390819,0.216, -2.735119,1.498648,0.216, -2.773725,1.477519,0.225, + -2.773725,1.477519,0.225, -2.7132,1.3656,0.225, -2.678982,1.390819,0.216, + -2.647539,1.413994,0.189, -2.699644,1.518063,0.189, -2.735119,1.498648,0.216, + -2.735119,1.498648,0.216, -2.678982,1.390819,0.216, -2.647539,1.413994,0.189, + -2.621645,1.433078,0.144, -2.670428,1.534053,0.144, -2.699644,1.518063,0.189, + -2.699644,1.518063,0.189, -2.647539,1.413994,0.189, -2.621645,1.433078,0.144, + -2.604074,1.446029,0.081, -2.650604,1.544903,0.081, -2.670428,1.534053,0.144, + -2.670428,1.534053,0.144, -2.621645,1.433078,0.144, -2.604074,1.446029,0.081, + -2.5976,1.4508,0, -2.6433,1.5489,0, -2.650604,1.544903,0.081, + -2.650604,1.544903,0.081, -2.604074,1.446029,0.081, -2.5976,1.4508,0, + -2.725825,1.163194,0.081, -2.822326,1.285171,0.081, -2.8288,1.2804,0, + -2.8288,1.2804,0, -2.73125,1.157813,0, -2.725825,1.163194,0.081, + -2.7111,1.1778,0.144, -2.804755,1.298122,0.144, -2.822326,1.285171,0.081, + -2.822326,1.285171,0.081, -2.725825,1.163194,0.081, -2.7111,1.1778,0.144, + -2.6894,1.199325,0.189, -2.778861,1.317206,0.189, -2.804755,1.298122,0.144, + -2.804755,1.298122,0.144, -2.7111,1.1778,0.144, -2.6894,1.199325,0.189, + -2.66305,1.225463,0.216, -2.747418,1.340381,0.216, -2.778861,1.317206,0.189, + -2.778861,1.317206,0.189, -2.6894,1.199325,0.189, -2.66305,1.225463,0.216, + -2.634375,1.253906,0.225, -2.7132,1.3656,0.225, -2.747418,1.340381,0.216, + -2.747418,1.340381,0.216, -2.66305,1.225463,0.216, -2.634375,1.253906,0.225, + -2.6057,1.28235,0.216, -2.678982,1.390819,0.216, -2.7132,1.3656,0.225, + -2.7132,1.3656,0.225, -2.634375,1.253906,0.225, -2.6057,1.28235,0.216, + -2.57935,1.308488,0.189, -2.647539,1.413994,0.189, -2.678982,1.390819,0.216, + -2.678982,1.390819,0.216, -2.6057,1.28235,0.216, -2.57935,1.308488,0.189, + -2.55765,1.330013,0.144, -2.621645,1.433078,0.144, -2.647539,1.413994,0.189, + -2.647539,1.413994,0.189, -2.57935,1.308488,0.189, -2.55765,1.330013,0.144, + -2.542925,1.344619,0.081, -2.604074,1.446029,0.081, -2.621645,1.433078,0.144, + -2.621645,1.433078,0.144, -2.55765,1.330013,0.144, -2.542925,1.344619,0.081, + -2.5375,1.35,0, -2.5976,1.4508,0, -2.604074,1.446029,0.081, + -2.604074,1.446029,0.081, -2.542925,1.344619,0.081, -2.5375,1.35,0, + -2.607034,1.044497,0.081, -2.725825,1.163194,0.081, -2.73125,1.157813,0, + -2.73125,1.157813,0, -2.6112,1.0386,0, -2.607034,1.044497,0.081, + -2.595725,1.060502,0.144, -2.7111,1.1778,0.144, -2.725825,1.163194,0.081, + -2.725825,1.163194,0.081, -2.607034,1.044497,0.081, -2.595725,1.060502,0.144, + -2.579059,1.08409,0.189, -2.6894,1.199325,0.189, -2.7111,1.1778,0.144, + -2.7111,1.1778,0.144, -2.595725,1.060502,0.144, -2.579059,1.08409,0.189, + -2.558822,1.112731,0.216, -2.66305,1.225463,0.216, -2.6894,1.199325,0.189, + -2.6894,1.199325,0.189, -2.579059,1.08409,0.189, -2.558822,1.112731,0.216, + -2.5368,1.1439,0.225, -2.634375,1.253906,0.225, -2.66305,1.225463,0.216, + -2.66305,1.225463,0.216, -2.558822,1.112731,0.216, -2.5368,1.1439,0.225, + -2.514778,1.175069,0.216, -2.6057,1.28235,0.216, -2.634375,1.253906,0.225, + -2.634375,1.253906,0.225, -2.5368,1.1439,0.225, -2.514778,1.175069,0.216, + -2.494541,1.20371,0.189, -2.57935,1.308488,0.189, -2.6057,1.28235,0.216, + -2.6057,1.28235,0.216, -2.514778,1.175069,0.216, -2.494541,1.20371,0.189, + -2.477875,1.227298,0.144, -2.55765,1.330013,0.144, -2.57935,1.308488,0.189, + -2.57935,1.308488,0.189, -2.494541,1.20371,0.189, -2.477875,1.227298,0.144, + -2.466566,1.243303,0.081, -2.542925,1.344619,0.081, -2.55765,1.330013,0.144, + -2.55765,1.330013,0.144, -2.477875,1.227298,0.144, -2.466566,1.243303,0.081, + -2.4624,1.2492,0, -2.5375,1.35,0, -2.542925,1.344619,0.081, + -2.542925,1.344619,0.081, -2.466566,1.243303,0.081, -2.4624,1.2492,0, + -2.465644,0.929375,0.081, -2.607034,1.044497,0.081, -2.6112,1.0386,0, + -2.6112,1.0386,0, -2.46835,0.922987,0, -2.465644,0.929375,0.081, + -2.458298,0.946711,0.144, -2.595725,1.060502,0.144, -2.607034,1.044497,0.081, + -2.607034,1.044497,0.081, -2.465644,0.929375,0.081, -2.458298,0.946711,0.144, + -2.447474,0.97226,0.189, -2.579059,1.08409,0.189, -2.595725,1.060502,0.144, + -2.595725,1.060502,0.144, -2.458298,0.946711,0.144, -2.447474,0.97226,0.189, + -2.434329,1.003283,0.216, -2.558822,1.112731,0.216, -2.579059,1.08409,0.189, + -2.579059,1.08409,0.189, -2.447474,0.97226,0.189, -2.434329,1.003283,0.216, + -2.420025,1.037044,0.225, -2.5368,1.1439,0.225, -2.558822,1.112731,0.216, + -2.558822,1.112731,0.216, -2.434329,1.003283,0.216, -2.420025,1.037044,0.225, + -2.405721,1.070804,0.216, -2.514778,1.175069,0.216, -2.5368,1.1439,0.225, + -2.5368,1.1439,0.225, -2.420025,1.037044,0.225, -2.405721,1.070804,0.216, + -2.392576,1.101828,0.189, -2.494541,1.20371,0.189, -2.514778,1.175069,0.216, + -2.514778,1.175069,0.216, -2.405721,1.070804,0.216, -2.392576,1.101828,0.189, + -2.381752,1.127376,0.144, -2.477875,1.227298,0.144, -2.494541,1.20371,0.189, + -2.494541,1.20371,0.189, -2.392576,1.101828,0.189, -2.381752,1.127376,0.144, + -2.374406,1.144713,0.081, -2.466566,1.243303,0.081, -2.477875,1.227298,0.144, + -2.477875,1.227298,0.144, -2.381752,1.127376,0.144, -2.374406,1.144713,0.081, + -2.3717,1.1511,0, -2.4624,1.2492,0, -2.466566,1.243303,0.081, + -2.466566,1.243303,0.081, -2.374406,1.144713,0.081, -2.3717,1.1511,0, + -2.301347,0.818122,0.081, -2.465644,0.929375,0.081, -2.46835,0.922987,0, + -2.46835,0.922987,0, -2.3024,0.8112,0, -2.301347,0.818122,0.081, + -2.29849,0.836909,0.144, -2.458298,0.946711,0.144, -2.465644,0.929375,0.081, + -2.465644,0.929375,0.081, -2.301347,0.818122,0.081, -2.29849,0.836909,0.144, + -2.294278,0.864595,0.189, -2.447474,0.97226,0.189, -2.458298,0.946711,0.144, + -2.458298,0.946711,0.144, -2.29849,0.836909,0.144, -2.294278,0.864595,0.189, + -2.289165,0.898214,0.216, -2.434329,1.003283,0.216, -2.447474,0.97226,0.189, + -2.447474,0.97226,0.189, -2.294278,0.864595,0.189, -2.289165,0.898214,0.216, + -2.2836,0.9348,0.225, -2.420025,1.037044,0.225, -2.434329,1.003283,0.216, + -2.434329,1.003283,0.216, -2.289165,0.898214,0.216, -2.2836,0.9348,0.225, + -2.278035,0.971386,0.216, -2.405721,1.070804,0.216, -2.420025,1.037044,0.225, + -2.420025,1.037044,0.225, -2.2836,0.9348,0.225, -2.278035,0.971386,0.216, + -2.272922,1.005005,0.189, -2.392576,1.101828,0.189, -2.405721,1.070804,0.216, + -2.405721,1.070804,0.216, -2.278035,0.971386,0.216, -2.272922,1.005005,0.189, + -2.26871,1.032691,0.144, -2.381752,1.127376,0.144, -2.392576,1.101828,0.189, + -2.392576,1.101828,0.189, -2.272922,1.005005,0.189, -2.26871,1.032691,0.144, + -2.265853,1.051478,0.081, -2.374406,1.144713,0.081, -2.381752,1.127376,0.144, + -2.381752,1.127376,0.144, -2.26871,1.032691,0.144, -2.265853,1.051478,0.081, + -2.2648,1.0584,0, -2.3717,1.1511,0, -2.374406,1.144713,0.081, + -2.374406,1.144713,0.081, -2.265853,1.051478,0.081, -2.2648,1.0584,0, + -2.113835,0.711032,0.081, -2.301347,0.818122,0.081, -2.3024,0.8112,0, + -2.3024,0.8112,0, -2.11305,0.703463,0, -2.113835,0.711032,0.081, + -2.115967,0.731578,0.144, -2.29849,0.836909,0.144, -2.301347,0.818122,0.081, + -2.301347,0.818122,0.081, -2.113835,0.711032,0.081, -2.115967,0.731578,0.144, + -2.119109,0.761855,0.189, -2.294278,0.864595,0.189, -2.29849,0.836909,0.144, + -2.29849,0.836909,0.144, -2.115967,0.731578,0.144, -2.119109,0.761855,0.189, + -2.122924,0.798621,0.216, -2.289165,0.898214,0.216, -2.294278,0.864595,0.189, + -2.294278,0.864595,0.189, -2.119109,0.761855,0.189, -2.122924,0.798621,0.216, + -2.127075,0.838631,0.225, -2.2836,0.9348,0.225, -2.289165,0.898214,0.216, + -2.289165,0.898214,0.216, -2.122924,0.798621,0.216, -2.127075,0.838631,0.225, + -2.131226,0.878641,0.216, -2.278035,0.971386,0.216, -2.2836,0.9348,0.225, + -2.2836,0.9348,0.225, -2.127075,0.838631,0.225, -2.131226,0.878641,0.216, + -2.135041,0.915407,0.189, -2.272922,1.005005,0.189, -2.278035,0.971386,0.216, + -2.278035,0.971386,0.216, -2.131226,0.878641,0.216, -2.135041,0.915407,0.189, + -2.138183,0.945685,0.144, -2.26871,1.032691,0.144, -2.272922,1.005005,0.189, + -2.272922,1.005005,0.189, -2.135041,0.915407,0.189, -2.138183,0.945685,0.144, + -2.140315,0.966231,0.081, -2.265853,1.051478,0.081, -2.26871,1.032691,0.144, + -2.26871,1.032691,0.144, -2.138183,0.945685,0.144, -2.140315,0.966231,0.081, + -2.1411,0.9738,0, -2.2648,1.0584,0, -2.265853,1.051478,0.081, + -2.265853,1.051478,0.081, -2.140315,0.966231,0.081, -2.1411,0.9738,0, + -1.9028,0.6084,0.081, -2.113835,0.711032,0.081, -2.11305,0.703463,0, + -2.11305,0.703463,0, -1.9,0.6,0, -1.9028,0.6084,0.081, + -1.9104,0.6312,0.144, -2.115967,0.731578,0.144, -2.113835,0.711032,0.081, + -2.113835,0.711032,0.081, -1.9028,0.6084,0.081, -1.9104,0.6312,0.144, + -1.9216,0.6648,0.189, -2.119109,0.761855,0.189, -2.115967,0.731578,0.144, + -2.115967,0.731578,0.144, -1.9104,0.6312,0.144, -1.9216,0.6648,0.189, + -1.9352,0.7056,0.216, -2.122924,0.798621,0.216, -2.119109,0.761855,0.189, + -2.119109,0.761855,0.189, -1.9216,0.6648,0.189, -1.9352,0.7056,0.216, + -1.95,0.75,0.225, -2.127075,0.838631,0.225, -2.122924,0.798621,0.216, + -2.122924,0.798621,0.216, -1.9352,0.7056,0.216, -1.95,0.75,0.225, + -1.9648,0.7944,0.216, -2.131226,0.878641,0.216, -2.127075,0.838631,0.225, + -2.127075,0.838631,0.225, -1.95,0.75,0.225, -1.9648,0.7944,0.216, + -1.9784,0.8352,0.189, -2.135041,0.915407,0.189, -2.131226,0.878641,0.216, + -2.131226,0.878641,0.216, -1.9648,0.7944,0.216, -1.9784,0.8352,0.189, + -1.9896,0.8688,0.144, -2.138183,0.945685,0.144, -2.135041,0.915407,0.189, + -2.135041,0.915407,0.189, -1.9784,0.8352,0.189, -1.9896,0.8688,0.144, + -1.9972,0.8916,0.081, -2.140315,0.966231,0.081, -2.138183,0.945685,0.144, + -2.138183,0.945685,0.144, -1.9896,0.8688,0.144, -1.9972,0.8916,0.081, + -2,0.9,0, -2.1411,0.9738,0, -2.140315,0.966231,0.081, + -2.140315,0.966231,0.081, -1.9972,0.8916,0.081, -2,0.9,0, + 1.939394,1.423221,-0.1751, 1.7,1.4019,-0.1782, 1.7,1.425,0, + 1.7,1.425,0, 1.9359,1.4442,0, 1.939394,1.423221,-0.1751, + 1.948879,1.366278,-0.31129, 1.7,1.3392,-0.3168, 1.7,1.4019,-0.1782, + 1.7,1.4019,-0.1782, 1.939394,1.423221,-0.1751, 1.948879,1.366278,-0.31129, + 1.962857,1.282362,-0.408568, 1.7,1.2468,-0.4158, 1.7,1.3392,-0.3168, + 1.7,1.3392,-0.3168, 1.948879,1.366278,-0.31129, 1.962857,1.282362,-0.408568, + 1.97983,1.180464,-0.466934, 1.7,1.1346,-0.4752, 1.7,1.2468,-0.4158, + 1.7,1.2468,-0.4158, 1.962857,1.282362,-0.408568, 1.97983,1.180464,-0.466934, + 1.9983,1.069575,-0.48639, 1.7,1.0125,-0.495, 1.7,1.1346,-0.4752, + 1.7,1.1346,-0.4752, 1.97983,1.180464,-0.466934, 1.9983,1.069575,-0.48639, + 2.01677,0.958686,-0.466934, 1.7,0.8904,-0.4752, 1.7,1.0125,-0.495, + 1.7,1.0125,-0.495, 1.9983,1.069575,-0.48639, 2.01677,0.958686,-0.466934, + 2.033743,0.856788,-0.408568, 1.7,0.7782,-0.4158, 1.7,0.8904,-0.4752, + 1.7,0.8904,-0.4752, 2.01677,0.958686,-0.466934, 2.033743,0.856788,-0.408568, + 2.047721,0.772872,-0.31129, 1.7,0.6858,-0.3168, 1.7,0.7782,-0.4158, + 1.7,0.7782,-0.4158, 2.033743,0.856788,-0.408568, 2.047721,0.772872,-0.31129, + 2.057206,0.715929,-0.1751, 1.7,0.6231,-0.1782, 1.7,0.6858,-0.3168, + 1.7,0.6858,-0.3168, 2.047721,0.772872,-0.31129, 2.057206,0.715929,-0.1751, + 2.0607,0.69495,0, 1.7,0.6,0, 1.7,0.6231,-0.1782, + 1.7,0.6231,-0.1782, 2.057206,0.715929,-0.1751, 2.0607,0.69495,0, + 2.116979,1.47912,-0.166687, 1.939394,1.423221,-0.1751, 1.9359,1.4442,0, + 1.9359,1.4442,0, 2.1112,1.4976,0, 2.116979,1.47912,-0.166687, + 2.132666,1.42896,-0.296333, 1.948879,1.366278,-0.31129, 1.939394,1.423221,-0.1751, + 1.939394,1.423221,-0.1751, 2.116979,1.47912,-0.166687, 2.132666,1.42896,-0.296333, + 2.155782,1.35504,-0.388937, 1.962857,1.282362,-0.408568, 1.948879,1.366278,-0.31129, + 1.948879,1.366278,-0.31129, 2.132666,1.42896,-0.296333, 2.155782,1.35504,-0.388937, + 2.183853,1.26528,-0.444499, 1.97983,1.180464,-0.466934, 1.962857,1.282362,-0.408568, + 1.962857,1.282362,-0.408568, 2.155782,1.35504,-0.388937, 2.183853,1.26528,-0.444499, + 2.2144,1.1676,-0.46302, 1.9983,1.069575,-0.48639, 1.97983,1.180464,-0.466934, + 1.97983,1.180464,-0.466934, 2.183853,1.26528,-0.444499, 2.2144,1.1676,-0.46302, + 2.244947,1.06992,-0.444499, 2.01677,0.958686,-0.466934, 1.9983,1.069575,-0.48639, + 1.9983,1.069575,-0.48639, 2.2144,1.1676,-0.46302, 2.244947,1.06992,-0.444499, + 2.273018,0.98016,-0.388937, 2.033743,0.856788,-0.408568, 2.01677,0.958686,-0.466934, + 2.01677,0.958686,-0.466934, 2.244947,1.06992,-0.444499, 2.273018,0.98016,-0.388937, + 2.296134,0.90624,-0.296333, 2.047721,0.772872,-0.31129, 2.033743,0.856788,-0.408568, + 2.033743,0.856788,-0.408568, 2.273018,0.98016,-0.388937, 2.296134,0.90624,-0.296333, + 2.311821,0.85608,-0.166687, 2.057206,0.715929,-0.1751, 2.047721,0.772872,-0.31129, + 2.047721,0.772872,-0.31129, 2.296134,0.90624,-0.296333, 2.311821,0.85608,-0.166687, + 2.3176,0.8376,0, 2.0607,0.69495,0, 2.057206,0.715929,-0.1751, + 2.057206,0.715929,-0.1751, 2.311821,0.85608,-0.166687, 2.3176,0.8376,0, + 2.244457,1.563171,-0.154289, 2.116979,1.47912,-0.166687, 2.1112,1.4976,0, + 2.1112,1.4976,0, 2.2373,1.5789,0, 2.244457,1.563171,-0.154289, + 2.263882,1.520478,-0.274291, 2.132666,1.42896,-0.296333, 2.116979,1.47912,-0.166687, + 2.116979,1.47912,-0.166687, 2.244457,1.563171,-0.154289, 2.263882,1.520478,-0.274291, + 2.29251,1.457562,-0.360007, 2.155782,1.35504,-0.388937, 2.132666,1.42896,-0.296333, + 2.132666,1.42896,-0.296333, 2.263882,1.520478,-0.274291, 2.29251,1.457562,-0.360007, + 2.327271,1.381164,-0.411437, 2.183853,1.26528,-0.444499, 2.155782,1.35504,-0.388937, + 2.155782,1.35504,-0.388937, 2.29251,1.457562,-0.360007, 2.327271,1.381164,-0.411437, + 2.3651,1.298025,-0.42858, 2.2144,1.1676,-0.46302, 2.183853,1.26528,-0.444499, + 2.183853,1.26528,-0.444499, 2.327271,1.381164,-0.411437, 2.3651,1.298025,-0.42858, + 2.402929,1.214886,-0.411437, 2.244947,1.06992,-0.444499, 2.2144,1.1676,-0.46302, + 2.2144,1.1676,-0.46302, 2.3651,1.298025,-0.42858, 2.402929,1.214886,-0.411437, + 2.43769,1.138488,-0.360007, 2.273018,0.98016,-0.388937, 2.244947,1.06992,-0.444499, + 2.244947,1.06992,-0.444499, 2.402929,1.214886,-0.411437, 2.43769,1.138488,-0.360007, + 2.466318,1.075572,-0.274291, 2.296134,0.90624,-0.296333, 2.273018,0.98016,-0.388937, + 2.273018,0.98016,-0.388937, 2.43769,1.138488,-0.360007, 2.466318,1.075572,-0.274291, + 2.485743,1.032879,-0.154289, 2.311821,0.85608,-0.166687, 2.296134,0.90624,-0.296333, + 2.296134,0.90624,-0.296333, 2.466318,1.075572,-0.274291, 2.485743,1.032879,-0.154289, + 2.4929,1.01715,0, 2.3176,0.8376,0, 2.311821,0.85608,-0.166687, + 2.311821,0.85608,-0.166687, 2.485743,1.032879,-0.154289, 2.4929,1.01715,0, + 2.33353,1.668948,-0.139234, 2.244457,1.563171,-0.154289, 2.2373,1.5789,0, + 2.2373,1.5789,0, 2.3256,1.6818,0, 2.33353,1.668948,-0.139234, + 2.355053,1.634064,-0.247526, 2.263882,1.520478,-0.274291, 2.244457,1.563171,-0.154289, + 2.244457,1.563171,-0.154289, 2.33353,1.668948,-0.139234, 2.355053,1.634064,-0.247526, + 2.386771,1.582656,-0.324878, 2.29251,1.457562,-0.360007, 2.263882,1.520478,-0.274291, + 2.263882,1.520478,-0.274291, 2.355053,1.634064,-0.247526, 2.386771,1.582656,-0.324878, + 2.425286,1.520232,-0.37129, 2.327271,1.381164,-0.411437, 2.29251,1.457562,-0.360007, + 2.29251,1.457562,-0.360007, 2.386771,1.582656,-0.324878, 2.425286,1.520232,-0.37129, + 2.4672,1.4523,-0.38676, 2.3651,1.298025,-0.42858, 2.327271,1.381164,-0.411437, + 2.327271,1.381164,-0.411437, 2.425286,1.520232,-0.37129, 2.4672,1.4523,-0.38676, + 2.509114,1.384368,-0.37129, 2.402929,1.214886,-0.411437, 2.3651,1.298025,-0.42858, + 2.3651,1.298025,-0.42858, 2.4672,1.4523,-0.38676, 2.509114,1.384368,-0.37129, + 2.547629,1.321944,-0.324878, 2.43769,1.138488,-0.360007, 2.402929,1.214886,-0.411437, + 2.402929,1.214886,-0.411437, 2.509114,1.384368,-0.37129, 2.547629,1.321944,-0.324878, + 2.579347,1.270536,-0.247526, 2.466318,1.075572,-0.274291, 2.43769,1.138488,-0.360007, + 2.43769,1.138488,-0.360007, 2.547629,1.321944,-0.324878, 2.579347,1.270536,-0.247526, + 2.60087,1.235652,-0.139234, 2.485743,1.032879,-0.154289, 2.466318,1.075572,-0.274291, + 2.466318,1.075572,-0.274291, 2.579347,1.270536,-0.247526, 2.60087,1.235652,-0.139234, + 2.6088,1.2228,0, 2.4929,1.01715,0, 2.485743,1.032879,-0.154289, + 2.485743,1.032879,-0.154289, 2.60087,1.235652,-0.139234, 2.6088,1.2228,0, + 2.3959,1.790025,-0.12285, 2.33353,1.668948,-0.139234, 2.3256,1.6818,0, + 2.3256,1.6818,0, 2.3875,1.8,0, 2.3959,1.790025,-0.12285, + 2.4187,1.76295,-0.2184, 2.355053,1.634064,-0.247526, 2.33353,1.668948,-0.139234, + 2.33353,1.668948,-0.139234, 2.3959,1.790025,-0.12285, 2.4187,1.76295,-0.2184, + 2.4523,1.72305,-0.28665, 2.386771,1.582656,-0.324878, 2.355053,1.634064,-0.247526, + 2.355053,1.634064,-0.247526, 2.4187,1.76295,-0.2184, 2.4523,1.72305,-0.28665, + 2.4931,1.6746,-0.3276, 2.425286,1.520232,-0.37129, 2.386771,1.582656,-0.324878, + 2.386771,1.582656,-0.324878, 2.4523,1.72305,-0.28665, 2.4931,1.6746,-0.3276, + 2.5375,1.621875,-0.34125, 2.4672,1.4523,-0.38676, 2.425286,1.520232,-0.37129, + 2.425286,1.520232,-0.37129, 2.4931,1.6746,-0.3276, 2.5375,1.621875,-0.34125, + 2.5819,1.56915,-0.3276, 2.509114,1.384368,-0.37129, 2.4672,1.4523,-0.38676, + 2.4672,1.4523,-0.38676, 2.5375,1.621875,-0.34125, 2.5819,1.56915,-0.3276, + 2.6227,1.5207,-0.28665, 2.547629,1.321944,-0.324878, 2.509114,1.384368,-0.37129, + 2.509114,1.384368,-0.37129, 2.5819,1.56915,-0.3276, 2.6227,1.5207,-0.28665, + 2.6563,1.4808,-0.2184, 2.579347,1.270536,-0.247526, 2.547629,1.321944,-0.324878, + 2.547629,1.321944,-0.324878, 2.6227,1.5207,-0.28665, 2.6563,1.4808,-0.2184, + 2.6791,1.453725,-0.12285, 2.60087,1.235652,-0.139234, 2.579347,1.270536,-0.247526, + 2.579347,1.270536,-0.247526, 2.6563,1.4808,-0.2184, 2.6791,1.453725,-0.12285, + 2.6875,1.44375,0, 2.6088,1.2228,0, 2.60087,1.235652,-0.139234, + 2.60087,1.235652,-0.139234, 2.6791,1.453725,-0.12285, 2.6875,1.44375,0, + 2.44327,1.919976,-0.106466, 2.3959,1.790025,-0.12285, 2.3875,1.8,0, + 2.3875,1.8,0, 2.4344,1.9272,0, 2.44327,1.919976,-0.106466, + 2.467347,1.900368,-0.189274, 2.4187,1.76295,-0.2184, 2.3959,1.790025,-0.12285, + 2.3959,1.790025,-0.12285, 2.44327,1.919976,-0.106466, 2.467347,1.900368,-0.189274, + 2.502829,1.871472,-0.248422, 2.4523,1.72305,-0.28665, 2.4187,1.76295,-0.2184, + 2.4187,1.76295,-0.2184, 2.467347,1.900368,-0.189274, 2.502829,1.871472,-0.248422, + 2.545914,1.836384,-0.28391, 2.4931,1.6746,-0.3276, 2.4523,1.72305,-0.28665, + 2.4523,1.72305,-0.28665, 2.502829,1.871472,-0.248422, 2.545914,1.836384,-0.28391, + 2.5928,1.7982,-0.29574, 2.5375,1.621875,-0.34125, 2.4931,1.6746,-0.3276, + 2.4931,1.6746,-0.3276, 2.545914,1.836384,-0.28391, 2.5928,1.7982,-0.29574, + 2.639686,1.760016,-0.28391, 2.5819,1.56915,-0.3276, 2.5375,1.621875,-0.34125, + 2.5375,1.621875,-0.34125, 2.5928,1.7982,-0.29574, 2.639686,1.760016,-0.28391, + 2.682771,1.724928,-0.248422, 2.6227,1.5207,-0.28665, 2.5819,1.56915,-0.3276, + 2.5819,1.56915,-0.3276, 2.639686,1.760016,-0.28391, 2.682771,1.724928,-0.248422, + 2.718253,1.696032,-0.189274, 2.6563,1.4808,-0.2184, 2.6227,1.5207,-0.28665, + 2.6227,1.5207,-0.28665, 2.682771,1.724928,-0.248422, 2.718253,1.696032,-0.189274, + 2.74233,1.676424,-0.106466, 2.6791,1.453725,-0.12285, 2.6563,1.4808,-0.2184, + 2.6563,1.4808,-0.2184, 2.718253,1.696032,-0.189274, 2.74233,1.676424,-0.106466, + 2.7512,1.6692,0, 2.6875,1.44375,0, 2.6791,1.453725,-0.12285, + 2.6791,1.453725,-0.12285, 2.74233,1.676424,-0.106466, 2.7512,1.6692,0, + 2.487343,2.052375,-0.091411, 2.44327,1.919976,-0.106466, 2.4344,1.9272,0, + 2.4344,1.9272,0, 2.4777,2.0571,0, 2.487343,2.052375,-0.091411, + 2.513518,2.03955,-0.162509, 2.467347,1.900368,-0.189274, 2.44327,1.919976,-0.106466, + 2.44327,1.919976,-0.106466, 2.487343,2.052375,-0.091411, 2.513518,2.03955,-0.162509, + 2.55209,2.02065,-0.213293, 2.502829,1.871472,-0.248422, 2.467347,1.900368,-0.189274, + 2.467347,1.900368,-0.189274, 2.513518,2.03955,-0.162509, 2.55209,2.02065,-0.213293, + 2.598929,1.9977,-0.243763, 2.545914,1.836384,-0.28391, 2.502829,1.871472,-0.248422, + 2.502829,1.871472,-0.248422, 2.55209,2.02065,-0.213293, 2.598929,1.9977,-0.243763, + 2.6499,1.972725,-0.25392, 2.5928,1.7982,-0.29574, 2.545914,1.836384,-0.28391, + 2.545914,1.836384,-0.28391, 2.598929,1.9977,-0.243763, 2.6499,1.972725,-0.25392, + 2.700871,1.94775,-0.243763, 2.639686,1.760016,-0.28391, 2.5928,1.7982,-0.29574, + 2.5928,1.7982,-0.29574, 2.6499,1.972725,-0.25392, 2.700871,1.94775,-0.243763, + 2.74771,1.9248,-0.213293, 2.682771,1.724928,-0.248422, 2.639686,1.760016,-0.28391, + 2.639686,1.760016,-0.28391, 2.700871,1.94775,-0.243763, 2.74771,1.9248,-0.213293, + 2.786282,1.9059,-0.162509, 2.718253,1.696032,-0.189274, 2.682771,1.724928,-0.248422, + 2.682771,1.724928,-0.248422, 2.74771,1.9248,-0.213293, 2.786282,1.9059,-0.162509, + 2.812457,1.893075,-0.091411, 2.74233,1.676424,-0.106466, 2.718253,1.696032,-0.189274, + 2.718253,1.696032,-0.189274, 2.786282,1.9059,-0.162509, 2.812457,1.893075,-0.091411, + 2.8221,1.88835,0, 2.7512,1.6692,0, 2.74233,1.676424,-0.106466, + 2.74233,1.676424,-0.106466, 2.812457,1.893075,-0.091411, 2.8221,1.88835,0, + 2.539821,2.180796,-0.079013, 2.487343,2.052375,-0.091411, 2.4777,2.0571,0, + 2.4777,2.0571,0, 2.5288,2.1834,0, 2.539821,2.180796,-0.079013, + 2.569734,2.173728,-0.140467, 2.513518,2.03955,-0.162509, 2.487343,2.052375,-0.091411, + 2.487343,2.052375,-0.091411, 2.539821,2.180796,-0.079013, 2.569734,2.173728,-0.140467, + 2.613818,2.163312,-0.184363, 2.55209,2.02065,-0.213293, 2.513518,2.03955,-0.162509, + 2.513518,2.03955,-0.162509, 2.569734,2.173728,-0.140467, 2.613818,2.163312,-0.184363, + 2.667347,2.150664,-0.210701, 2.598929,1.9977,-0.243763, 2.55209,2.02065,-0.213293, + 2.55209,2.02065,-0.213293, 2.613818,2.163312,-0.184363, 2.667347,2.150664,-0.210701, + 2.7256,2.1369,-0.21948, 2.6499,1.972725,-0.25392, 2.598929,1.9977,-0.243763, + 2.598929,1.9977,-0.243763, 2.667347,2.150664,-0.210701, 2.7256,2.1369,-0.21948, + 2.783853,2.123136,-0.210701, 2.700871,1.94775,-0.243763, 2.6499,1.972725,-0.25392, + 2.6499,1.972725,-0.25392, 2.7256,2.1369,-0.21948, 2.783853,2.123136,-0.210701, + 2.837382,2.110488,-0.184363, 2.74771,1.9248,-0.213293, 2.700871,1.94775,-0.243763, + 2.700871,1.94775,-0.243763, 2.783853,2.123136,-0.210701, 2.837382,2.110488,-0.184363, + 2.881466,2.100072,-0.140467, 2.786282,1.9059,-0.162509, 2.74771,1.9248,-0.213293, + 2.74771,1.9248,-0.213293, 2.837382,2.110488,-0.184363, 2.881466,2.100072,-0.140467, + 2.911379,2.093004,-0.079013, 2.812457,1.893075,-0.091411, 2.786282,1.9059,-0.162509, + 2.786282,1.9059,-0.162509, 2.881466,2.100072,-0.140467, 2.911379,2.093004,-0.079013, + 2.9224,2.0904,0, 2.8221,1.88835,0, 2.812457,1.893075,-0.091411, + 2.812457,1.893075,-0.091411, 2.911379,2.093004,-0.079013, 2.9224,2.0904,0, + 2.612406,2.298813,-0.0706, 2.539821,2.180796,-0.079013, 2.5288,2.1834,0, + 2.5288,2.1834,0, 2.5991,2.2998,0, 2.612406,2.298813,-0.0706, + 2.648521,2.296134,-0.12551, 2.569734,2.173728,-0.140467, 2.539821,2.180796,-0.079013, + 2.539821,2.180796,-0.079013, 2.612406,2.298813,-0.0706, 2.648521,2.296134,-0.12551, + 2.701743,2.292186,-0.164732, 2.613818,2.163312,-0.184363, 2.569734,2.173728,-0.140467, + 2.569734,2.173728,-0.140467, 2.648521,2.296134,-0.12551, 2.701743,2.292186,-0.164732, + 2.76637,2.287392,-0.188266, 2.667347,2.150664,-0.210701, 2.613818,2.163312,-0.184363, + 2.613818,2.163312,-0.184363, 2.701743,2.292186,-0.164732, 2.76637,2.287392,-0.188266, + 2.8367,2.282175,-0.19611, 2.7256,2.1369,-0.21948, 2.667347,2.150664,-0.210701, + 2.667347,2.150664,-0.210701, 2.76637,2.287392,-0.188266, 2.8367,2.282175,-0.19611, + 2.90703,2.276958,-0.188266, 2.783853,2.123136,-0.210701, 2.7256,2.1369,-0.21948, + 2.7256,2.1369,-0.21948, 2.8367,2.282175,-0.19611, 2.90703,2.276958,-0.188266, + 2.971657,2.272164,-0.164732, 2.837382,2.110488,-0.184363, 2.783853,2.123136,-0.210701, + 2.783853,2.123136,-0.210701, 2.90703,2.276958,-0.188266, 2.971657,2.272164,-0.164732, + 3.024879,2.268216,-0.12551, 2.881466,2.100072,-0.140467, 2.837382,2.110488,-0.184363, + 2.837382,2.110488,-0.184363, 2.971657,2.272164,-0.164732, 3.024879,2.268216,-0.12551, + 3.060994,2.265537,-0.0706, 2.911379,2.093004,-0.079013, 2.881466,2.100072,-0.140467, + 2.881466,2.100072,-0.140467, 3.024879,2.268216,-0.12551, 3.060994,2.265537,-0.0706, + 3.0743,2.26455,0, 2.9224,2.0904,0, 2.911379,2.093004,-0.079013, + 2.911379,2.093004,-0.079013, 3.060994,2.265537,-0.0706, 3.0743,2.26455,0, + 2.7168,2.4,-0.0675, 2.612406,2.298813,-0.0706, 2.5991,2.2998,0, + 2.5991,2.2998,0, 2.7,2.4,0, 2.7168,2.4,-0.0675, + 2.7624,2.4,-0.12, 2.648521,2.296134,-0.12551, 2.612406,2.298813,-0.0706, + 2.612406,2.298813,-0.0706, 2.7168,2.4,-0.0675, 2.7624,2.4,-0.12, + 2.8296,2.4,-0.1575, 2.701743,2.292186,-0.164732, 2.648521,2.296134,-0.12551, + 2.648521,2.296134,-0.12551, 2.7624,2.4,-0.12, 2.8296,2.4,-0.1575, + 2.9112,2.4,-0.18, 2.76637,2.287392,-0.188266, 2.701743,2.292186,-0.164732, + 2.701743,2.292186,-0.164732, 2.8296,2.4,-0.1575, 2.9112,2.4,-0.18, + 3,2.4,-0.1875, 2.8367,2.282175,-0.19611, 2.76637,2.287392,-0.188266, + 2.76637,2.287392,-0.188266, 2.9112,2.4,-0.18, 3,2.4,-0.1875, + 3.0888,2.4,-0.18, 2.90703,2.276958,-0.188266, 2.8367,2.282175,-0.19611, + 2.8367,2.282175,-0.19611, 3,2.4,-0.1875, 3.0888,2.4,-0.18, + 3.1704,2.4,-0.1575, 2.971657,2.272164,-0.164732, 2.90703,2.276958,-0.188266, + 2.90703,2.276958,-0.188266, 3.0888,2.4,-0.18, 3.1704,2.4,-0.1575, + 3.2376,2.4,-0.12, 3.024879,2.268216,-0.12551, 2.971657,2.272164,-0.164732, + 2.971657,2.272164,-0.164732, 3.1704,2.4,-0.1575, 3.2376,2.4,-0.12, + 3.2832,2.4,-0.0675, 3.060994,2.265537,-0.0706, 3.024879,2.268216,-0.12551, + 3.024879,2.268216,-0.12551, 3.2376,2.4,-0.12, 3.2832,2.4,-0.0675, + 3.3,2.4,0, 3.0743,2.26455,0, 3.060994,2.265537,-0.0706, + 3.060994,2.265537,-0.0706, 3.2832,2.4,-0.0675, 3.3,2.4,0, + 2.057206,0.715929,0.1751, 1.7,0.6231,0.1782, 1.7,0.6,0, + 1.7,0.6,0, 2.0607,0.69495,0, 2.057206,0.715929,0.1751, + 2.047721,0.772872,0.31129, 1.7,0.6858,0.3168, 1.7,0.6231,0.1782, + 1.7,0.6231,0.1782, 2.057206,0.715929,0.1751, 2.047721,0.772872,0.31129, + 2.033743,0.856788,0.408568, 1.7,0.7782,0.4158, 1.7,0.6858,0.3168, + 1.7,0.6858,0.3168, 2.047721,0.772872,0.31129, 2.033743,0.856788,0.408568, + 2.01677,0.958686,0.466934, 1.7,0.8904,0.4752, 1.7,0.7782,0.4158, + 1.7,0.7782,0.4158, 2.033743,0.856788,0.408568, 2.01677,0.958686,0.466934, + 1.9983,1.069575,0.48639, 1.7,1.0125,0.495, 1.7,0.8904,0.4752, + 1.7,0.8904,0.4752, 2.01677,0.958686,0.466934, 1.9983,1.069575,0.48639, + 1.97983,1.180464,0.466934, 1.7,1.1346,0.4752, 1.7,1.0125,0.495, + 1.7,1.0125,0.495, 1.9983,1.069575,0.48639, 1.97983,1.180464,0.466934, + 1.962857,1.282362,0.408568, 1.7,1.2468,0.4158, 1.7,1.1346,0.4752, + 1.7,1.1346,0.4752, 1.97983,1.180464,0.466934, 1.962857,1.282362,0.408568, + 1.948879,1.366278,0.31129, 1.7,1.3392,0.3168, 1.7,1.2468,0.4158, + 1.7,1.2468,0.4158, 1.962857,1.282362,0.408568, 1.948879,1.366278,0.31129, + 1.939394,1.423221,0.1751, 1.7,1.4019,0.1782, 1.7,1.3392,0.3168, + 1.7,1.3392,0.3168, 1.948879,1.366278,0.31129, 1.939394,1.423221,0.1751, + 1.9359,1.4442,0, 1.7,1.425,0, 1.7,1.4019,0.1782, + 1.7,1.4019,0.1782, 1.939394,1.423221,0.1751, 1.9359,1.4442,0, + 2.311821,0.85608,0.166687, 2.057206,0.715929,0.1751, 2.0607,0.69495,0, + 2.0607,0.69495,0, 2.3176,0.8376,0, 2.311821,0.85608,0.166687, + 2.296134,0.90624,0.296333, 2.047721,0.772872,0.31129, 2.057206,0.715929,0.1751, + 2.057206,0.715929,0.1751, 2.311821,0.85608,0.166687, 2.296134,0.90624,0.296333, + 2.273018,0.98016,0.388937, 2.033743,0.856788,0.408568, 2.047721,0.772872,0.31129, + 2.047721,0.772872,0.31129, 2.296134,0.90624,0.296333, 2.273018,0.98016,0.388937, + 2.244947,1.06992,0.444499, 2.01677,0.958686,0.466934, 2.033743,0.856788,0.408568, + 2.033743,0.856788,0.408568, 2.273018,0.98016,0.388937, 2.244947,1.06992,0.444499, + 2.2144,1.1676,0.46302, 1.9983,1.069575,0.48639, 2.01677,0.958686,0.466934, + 2.01677,0.958686,0.466934, 2.244947,1.06992,0.444499, 2.2144,1.1676,0.46302, + 2.183853,1.26528,0.444499, 1.97983,1.180464,0.466934, 1.9983,1.069575,0.48639, + 1.9983,1.069575,0.48639, 2.2144,1.1676,0.46302, 2.183853,1.26528,0.444499, + 2.155782,1.35504,0.388937, 1.962857,1.282362,0.408568, 1.97983,1.180464,0.466934, + 1.97983,1.180464,0.466934, 2.183853,1.26528,0.444499, 2.155782,1.35504,0.388937, + 2.132666,1.42896,0.296333, 1.948879,1.366278,0.31129, 1.962857,1.282362,0.408568, + 1.962857,1.282362,0.408568, 2.155782,1.35504,0.388937, 2.132666,1.42896,0.296333, + 2.116979,1.47912,0.166687, 1.939394,1.423221,0.1751, 1.948879,1.366278,0.31129, + 1.948879,1.366278,0.31129, 2.132666,1.42896,0.296333, 2.116979,1.47912,0.166687, + 2.1112,1.4976,0, 1.9359,1.4442,0, 1.939394,1.423221,0.1751, + 1.939394,1.423221,0.1751, 2.116979,1.47912,0.166687, 2.1112,1.4976,0, + 2.485743,1.032879,0.154289, 2.311821,0.85608,0.166687, 2.3176,0.8376,0, + 2.3176,0.8376,0, 2.4929,1.01715,0, 2.485743,1.032879,0.154289, + 2.466318,1.075572,0.274291, 2.296134,0.90624,0.296333, 2.311821,0.85608,0.166687, + 2.311821,0.85608,0.166687, 2.485743,1.032879,0.154289, 2.466318,1.075572,0.274291, + 2.43769,1.138488,0.360007, 2.273018,0.98016,0.388937, 2.296134,0.90624,0.296333, + 2.296134,0.90624,0.296333, 2.466318,1.075572,0.274291, 2.43769,1.138488,0.360007, + 2.402929,1.214886,0.411437, 2.244947,1.06992,0.444499, 2.273018,0.98016,0.388937, + 2.273018,0.98016,0.388937, 2.43769,1.138488,0.360007, 2.402929,1.214886,0.411437, + 2.3651,1.298025,0.42858, 2.2144,1.1676,0.46302, 2.244947,1.06992,0.444499, + 2.244947,1.06992,0.444499, 2.402929,1.214886,0.411437, 2.3651,1.298025,0.42858, + 2.327271,1.381164,0.411437, 2.183853,1.26528,0.444499, 2.2144,1.1676,0.46302, + 2.2144,1.1676,0.46302, 2.3651,1.298025,0.42858, 2.327271,1.381164,0.411437, + 2.29251,1.457562,0.360007, 2.155782,1.35504,0.388937, 2.183853,1.26528,0.444499, + 2.183853,1.26528,0.444499, 2.327271,1.381164,0.411437, 2.29251,1.457562,0.360007, + 2.263882,1.520478,0.274291, 2.132666,1.42896,0.296333, 2.155782,1.35504,0.388937, + 2.155782,1.35504,0.388937, 2.29251,1.457562,0.360007, 2.263882,1.520478,0.274291, + 2.244457,1.563171,0.154289, 2.116979,1.47912,0.166687, 2.132666,1.42896,0.296333, + 2.132666,1.42896,0.296333, 2.263882,1.520478,0.274291, 2.244457,1.563171,0.154289, + 2.2373,1.5789,0, 2.1112,1.4976,0, 2.116979,1.47912,0.166687, + 2.116979,1.47912,0.166687, 2.244457,1.563171,0.154289, 2.2373,1.5789,0, + 2.60087,1.235652,0.139234, 2.485743,1.032879,0.154289, 2.4929,1.01715,0, + 2.4929,1.01715,0, 2.6088,1.2228,0, 2.60087,1.235652,0.139234, + 2.579347,1.270536,0.247526, 2.466318,1.075572,0.274291, 2.485743,1.032879,0.154289, + 2.485743,1.032879,0.154289, 2.60087,1.235652,0.139234, 2.579347,1.270536,0.247526, + 2.547629,1.321944,0.324878, 2.43769,1.138488,0.360007, 2.466318,1.075572,0.274291, + 2.466318,1.075572,0.274291, 2.579347,1.270536,0.247526, 2.547629,1.321944,0.324878, + 2.509114,1.384368,0.37129, 2.402929,1.214886,0.411437, 2.43769,1.138488,0.360007, + 2.43769,1.138488,0.360007, 2.547629,1.321944,0.324878, 2.509114,1.384368,0.37129, + 2.4672,1.4523,0.38676, 2.3651,1.298025,0.42858, 2.402929,1.214886,0.411437, + 2.402929,1.214886,0.411437, 2.509114,1.384368,0.37129, 2.4672,1.4523,0.38676, + 2.425286,1.520232,0.37129, 2.327271,1.381164,0.411437, 2.3651,1.298025,0.42858, + 2.3651,1.298025,0.42858, 2.4672,1.4523,0.38676, 2.425286,1.520232,0.37129, + 2.386771,1.582656,0.324878, 2.29251,1.457562,0.360007, 2.327271,1.381164,0.411437, + 2.327271,1.381164,0.411437, 2.425286,1.520232,0.37129, 2.386771,1.582656,0.324878, + 2.355053,1.634064,0.247526, 2.263882,1.520478,0.274291, 2.29251,1.457562,0.360007, + 2.29251,1.457562,0.360007, 2.386771,1.582656,0.324878, 2.355053,1.634064,0.247526, + 2.33353,1.668948,0.139234, 2.244457,1.563171,0.154289, 2.263882,1.520478,0.274291, + 2.263882,1.520478,0.274291, 2.355053,1.634064,0.247526, 2.33353,1.668948,0.139234, + 2.3256,1.6818,0, 2.2373,1.5789,0, 2.244457,1.563171,0.154289, + 2.244457,1.563171,0.154289, 2.33353,1.668948,0.139234, 2.3256,1.6818,0, + 2.6791,1.453725,0.12285, 2.60087,1.235652,0.139234, 2.6088,1.2228,0, + 2.6088,1.2228,0, 2.6875,1.44375,0, 2.6791,1.453725,0.12285, + 2.6563,1.4808,0.2184, 2.579347,1.270536,0.247526, 2.60087,1.235652,0.139234, + 2.60087,1.235652,0.139234, 2.6791,1.453725,0.12285, 2.6563,1.4808,0.2184, + 2.6227,1.5207,0.28665, 2.547629,1.321944,0.324878, 2.579347,1.270536,0.247526, + 2.579347,1.270536,0.247526, 2.6563,1.4808,0.2184, 2.6227,1.5207,0.28665, + 2.5819,1.56915,0.3276, 2.509114,1.384368,0.37129, 2.547629,1.321944,0.324878, + 2.547629,1.321944,0.324878, 2.6227,1.5207,0.28665, 2.5819,1.56915,0.3276, + 2.5375,1.621875,0.34125, 2.4672,1.4523,0.38676, 2.509114,1.384368,0.37129, + 2.509114,1.384368,0.37129, 2.5819,1.56915,0.3276, 2.5375,1.621875,0.34125, + 2.4931,1.6746,0.3276, 2.425286,1.520232,0.37129, 2.4672,1.4523,0.38676, + 2.4672,1.4523,0.38676, 2.5375,1.621875,0.34125, 2.4931,1.6746,0.3276, + 2.4523,1.72305,0.28665, 2.386771,1.582656,0.324878, 2.425286,1.520232,0.37129, + 2.425286,1.520232,0.37129, 2.4931,1.6746,0.3276, 2.4523,1.72305,0.28665, + 2.4187,1.76295,0.2184, 2.355053,1.634064,0.247526, 2.386771,1.582656,0.324878, + 2.386771,1.582656,0.324878, 2.4523,1.72305,0.28665, 2.4187,1.76295,0.2184, + 2.3959,1.790025,0.12285, 2.33353,1.668948,0.139234, 2.355053,1.634064,0.247526, + 2.355053,1.634064,0.247526, 2.4187,1.76295,0.2184, 2.3959,1.790025,0.12285, + 2.3875,1.8,0, 2.3256,1.6818,0, 2.33353,1.668948,0.139234, + 2.33353,1.668948,0.139234, 2.3959,1.790025,0.12285, 2.3875,1.8,0, + 2.74233,1.676424,0.106466, 2.6791,1.453725,0.12285, 2.6875,1.44375,0, + 2.6875,1.44375,0, 2.7512,1.6692,0, 2.74233,1.676424,0.106466, + 2.718253,1.696032,0.189274, 2.6563,1.4808,0.2184, 2.6791,1.453725,0.12285, + 2.6791,1.453725,0.12285, 2.74233,1.676424,0.106466, 2.718253,1.696032,0.189274, + 2.682771,1.724928,0.248422, 2.6227,1.5207,0.28665, 2.6563,1.4808,0.2184, + 2.6563,1.4808,0.2184, 2.718253,1.696032,0.189274, 2.682771,1.724928,0.248422, + 2.639686,1.760016,0.28391, 2.5819,1.56915,0.3276, 2.6227,1.5207,0.28665, + 2.6227,1.5207,0.28665, 2.682771,1.724928,0.248422, 2.639686,1.760016,0.28391, + 2.5928,1.7982,0.29574, 2.5375,1.621875,0.34125, 2.5819,1.56915,0.3276, + 2.5819,1.56915,0.3276, 2.639686,1.760016,0.28391, 2.5928,1.7982,0.29574, + 2.545914,1.836384,0.28391, 2.4931,1.6746,0.3276, 2.5375,1.621875,0.34125, + 2.5375,1.621875,0.34125, 2.5928,1.7982,0.29574, 2.545914,1.836384,0.28391, + 2.502829,1.871472,0.248422, 2.4523,1.72305,0.28665, 2.4931,1.6746,0.3276, + 2.4931,1.6746,0.3276, 2.545914,1.836384,0.28391, 2.502829,1.871472,0.248422, + 2.467347,1.900368,0.189274, 2.4187,1.76295,0.2184, 2.4523,1.72305,0.28665, + 2.4523,1.72305,0.28665, 2.502829,1.871472,0.248422, 2.467347,1.900368,0.189274, + 2.44327,1.919976,0.106466, 2.3959,1.790025,0.12285, 2.4187,1.76295,0.2184, + 2.4187,1.76295,0.2184, 2.467347,1.900368,0.189274, 2.44327,1.919976,0.106466, + 2.4344,1.9272,0, 2.3875,1.8,0, 2.3959,1.790025,0.12285, + 2.3959,1.790025,0.12285, 2.44327,1.919976,0.106466, 2.4344,1.9272,0, + 2.812457,1.893075,0.091411, 2.74233,1.676424,0.106466, 2.7512,1.6692,0, + 2.7512,1.6692,0, 2.8221,1.88835,0, 2.812457,1.893075,0.091411, + 2.786282,1.9059,0.162509, 2.718253,1.696032,0.189274, 2.74233,1.676424,0.106466, + 2.74233,1.676424,0.106466, 2.812457,1.893075,0.091411, 2.786282,1.9059,0.162509, + 2.74771,1.9248,0.213293, 2.682771,1.724928,0.248422, 2.718253,1.696032,0.189274, + 2.718253,1.696032,0.189274, 2.786282,1.9059,0.162509, 2.74771,1.9248,0.213293, + 2.700871,1.94775,0.243763, 2.639686,1.760016,0.28391, 2.682771,1.724928,0.248422, + 2.682771,1.724928,0.248422, 2.74771,1.9248,0.213293, 2.700871,1.94775,0.243763, + 2.6499,1.972725,0.25392, 2.5928,1.7982,0.29574, 2.639686,1.760016,0.28391, + 2.639686,1.760016,0.28391, 2.700871,1.94775,0.243763, 2.6499,1.972725,0.25392, + 2.598929,1.9977,0.243763, 2.545914,1.836384,0.28391, 2.5928,1.7982,0.29574, + 2.5928,1.7982,0.29574, 2.6499,1.972725,0.25392, 2.598929,1.9977,0.243763, + 2.55209,2.02065,0.213293, 2.502829,1.871472,0.248422, 2.545914,1.836384,0.28391, + 2.545914,1.836384,0.28391, 2.598929,1.9977,0.243763, 2.55209,2.02065,0.213293, + 2.513518,2.03955,0.162509, 2.467347,1.900368,0.189274, 2.502829,1.871472,0.248422, + 2.502829,1.871472,0.248422, 2.55209,2.02065,0.213293, 2.513518,2.03955,0.162509, + 2.487343,2.052375,0.091411, 2.44327,1.919976,0.106466, 2.467347,1.900368,0.189274, + 2.467347,1.900368,0.189274, 2.513518,2.03955,0.162509, 2.487343,2.052375,0.091411, + 2.4777,2.0571,0, 2.4344,1.9272,0, 2.44327,1.919976,0.106466, + 2.44327,1.919976,0.106466, 2.487343,2.052375,0.091411, 2.4777,2.0571,0, + 2.911379,2.093004,0.079013, 2.812457,1.893075,0.091411, 2.8221,1.88835,0, + 2.8221,1.88835,0, 2.9224,2.0904,0, 2.911379,2.093004,0.079013, + 2.881466,2.100072,0.140467, 2.786282,1.9059,0.162509, 2.812457,1.893075,0.091411, + 2.812457,1.893075,0.091411, 2.911379,2.093004,0.079013, 2.881466,2.100072,0.140467, + 2.837382,2.110488,0.184363, 2.74771,1.9248,0.213293, 2.786282,1.9059,0.162509, + 2.786282,1.9059,0.162509, 2.881466,2.100072,0.140467, 2.837382,2.110488,0.184363, + 2.783853,2.123136,0.210701, 2.700871,1.94775,0.243763, 2.74771,1.9248,0.213293, + 2.74771,1.9248,0.213293, 2.837382,2.110488,0.184363, 2.783853,2.123136,0.210701, + 2.7256,2.1369,0.21948, 2.6499,1.972725,0.25392, 2.700871,1.94775,0.243763, + 2.700871,1.94775,0.243763, 2.783853,2.123136,0.210701, 2.7256,2.1369,0.21948, + 2.667347,2.150664,0.210701, 2.598929,1.9977,0.243763, 2.6499,1.972725,0.25392, + 2.6499,1.972725,0.25392, 2.7256,2.1369,0.21948, 2.667347,2.150664,0.210701, + 2.613818,2.163312,0.184363, 2.55209,2.02065,0.213293, 2.598929,1.9977,0.243763, + 2.598929,1.9977,0.243763, 2.667347,2.150664,0.210701, 2.613818,2.163312,0.184363, + 2.569734,2.173728,0.140467, 2.513518,2.03955,0.162509, 2.55209,2.02065,0.213293, + 2.55209,2.02065,0.213293, 2.613818,2.163312,0.184363, 2.569734,2.173728,0.140467, + 2.539821,2.180796,0.079013, 2.487343,2.052375,0.091411, 2.513518,2.03955,0.162509, + 2.513518,2.03955,0.162509, 2.569734,2.173728,0.140467, 2.539821,2.180796,0.079013, + 2.5288,2.1834,0, 2.4777,2.0571,0, 2.487343,2.052375,0.091411, + 2.487343,2.052375,0.091411, 2.539821,2.180796,0.079013, 2.5288,2.1834,0, + 3.060994,2.265537,0.0706, 2.911379,2.093004,0.079013, 2.9224,2.0904,0, + 2.9224,2.0904,0, 3.0743,2.26455,0, 3.060994,2.265537,0.0706, + 3.024879,2.268216,0.12551, 2.881466,2.100072,0.140467, 2.911379,2.093004,0.079013, + 2.911379,2.093004,0.079013, 3.060994,2.265537,0.0706, 3.024879,2.268216,0.12551, + 2.971657,2.272164,0.164732, 2.837382,2.110488,0.184363, 2.881466,2.100072,0.140467, + 2.881466,2.100072,0.140467, 3.024879,2.268216,0.12551, 2.971657,2.272164,0.164732, + 2.90703,2.276958,0.188266, 2.783853,2.123136,0.210701, 2.837382,2.110488,0.184363, + 2.837382,2.110488,0.184363, 2.971657,2.272164,0.164732, 2.90703,2.276958,0.188266, + 2.8367,2.282175,0.19611, 2.7256,2.1369,0.21948, 2.783853,2.123136,0.210701, + 2.783853,2.123136,0.210701, 2.90703,2.276958,0.188266, 2.8367,2.282175,0.19611, + 2.76637,2.287392,0.188266, 2.667347,2.150664,0.210701, 2.7256,2.1369,0.21948, + 2.7256,2.1369,0.21948, 2.8367,2.282175,0.19611, 2.76637,2.287392,0.188266, + 2.701743,2.292186,0.164732, 2.613818,2.163312,0.184363, 2.667347,2.150664,0.210701, + 2.667347,2.150664,0.210701, 2.76637,2.287392,0.188266, 2.701743,2.292186,0.164732, + 2.648521,2.296134,0.12551, 2.569734,2.173728,0.140467, 2.613818,2.163312,0.184363, + 2.613818,2.163312,0.184363, 2.701743,2.292186,0.164732, 2.648521,2.296134,0.12551, + 2.612406,2.298813,0.0706, 2.539821,2.180796,0.079013, 2.569734,2.173728,0.140467, + 2.569734,2.173728,0.140467, 2.648521,2.296134,0.12551, 2.612406,2.298813,0.0706, + 2.5991,2.2998,0, 2.5288,2.1834,0, 2.539821,2.180796,0.079013, + 2.539821,2.180796,0.079013, 2.612406,2.298813,0.0706, 2.5991,2.2998,0, + 3.2832,2.4,0.0675, 3.060994,2.265537,0.0706, 3.0743,2.26455,0, + 3.0743,2.26455,0, 3.3,2.4,0, 3.2832,2.4,0.0675, + 3.2376,2.4,0.12, 3.024879,2.268216,0.12551, 3.060994,2.265537,0.0706, + 3.060994,2.265537,0.0706, 3.2832,2.4,0.0675, 3.2376,2.4,0.12, + 3.1704,2.4,0.1575, 2.971657,2.272164,0.164732, 3.024879,2.268216,0.12551, + 3.024879,2.268216,0.12551, 3.2376,2.4,0.12, 3.1704,2.4,0.1575, + 3.0888,2.4,0.18, 2.90703,2.276958,0.188266, 2.971657,2.272164,0.164732, + 2.971657,2.272164,0.164732, 3.1704,2.4,0.1575, 3.0888,2.4,0.18, + 3,2.4,0.1875, 2.8367,2.282175,0.19611, 2.90703,2.276958,0.188266, + 2.90703,2.276958,0.188266, 3.0888,2.4,0.18, 3,2.4,0.1875, + 2.9112,2.4,0.18, 2.76637,2.287392,0.188266, 2.8367,2.282175,0.19611, + 2.8367,2.282175,0.19611, 3,2.4,0.1875, 2.9112,2.4,0.18, + 2.8296,2.4,0.1575, 2.701743,2.292186,0.164732, 2.76637,2.287392,0.188266, + 2.76637,2.287392,0.188266, 2.9112,2.4,0.18, 2.8296,2.4,0.1575, + 2.7624,2.4,0.12, 2.648521,2.296134,0.12551, 2.701743,2.292186,0.164732, + 2.701743,2.292186,0.164732, 2.8296,2.4,0.1575, 2.7624,2.4,0.12, + 2.7168,2.4,0.0675, 2.612406,2.298813,0.0706, 2.648521,2.296134,0.12551, + 2.648521,2.296134,0.12551, 2.7624,2.4,0.12, 2.7168,2.4,0.0675, + 2.7,2.4,0, 2.5991,2.2998,0, 2.612406,2.298813,0.0706, + 2.612406,2.298813,0.0706, 2.7168,2.4,0.0675, 2.7,2.4,0, + 2.747407,2.420406,-0.066744, 2.7168,2.4,-0.0675, 2.7,2.4,0, + 2.7,2.4,0, 2.7298,2.42025,0, 2.747407,2.420406,-0.066744, + 2.795198,2.420829,-0.118656, 2.7624,2.4,-0.12, 2.7168,2.4,-0.0675, + 2.7168,2.4,-0.0675, 2.747407,2.420406,-0.066744, 2.795198,2.420829,-0.118656, + 2.865626,2.421453,-0.155736, 2.8296,2.4,-0.1575, 2.7624,2.4,-0.12, + 2.7624,2.4,-0.12, 2.795198,2.420829,-0.118656, 2.865626,2.421453,-0.155736, + 2.951146,2.42221,-0.177984, 2.9112,2.4,-0.18, 2.8296,2.4,-0.1575, + 2.8296,2.4,-0.1575, 2.865626,2.421453,-0.155736, 2.951146,2.42221,-0.177984, + 3.044212,2.423034,-0.1854, 3,2.4,-0.1875, 2.9112,2.4,-0.18, + 2.9112,2.4,-0.18, 2.951146,2.42221,-0.177984, 3.044212,2.423034,-0.1854, + 3.137279,2.423859,-0.177984, 3.0888,2.4,-0.18, 3,2.4,-0.1875, + 3,2.4,-0.1875, 3.044212,2.423034,-0.1854, 3.137279,2.423859,-0.177984, + 3.222799,2.424616,-0.155736, 3.1704,2.4,-0.1575, 3.0888,2.4,-0.18, + 3.0888,2.4,-0.18, 3.137279,2.423859,-0.177984, 3.222799,2.424616,-0.155736, + 3.293227,2.42524,-0.118656, 3.2376,2.4,-0.12, 3.1704,2.4,-0.1575, + 3.1704,2.4,-0.1575, 3.222799,2.424616,-0.155736, 3.293227,2.42524,-0.118656, + 3.341018,2.425663,-0.066744, 3.2832,2.4,-0.0675, 3.2376,2.4,-0.12, + 3.2376,2.4,-0.12, 3.293227,2.42524,-0.118656, 3.341018,2.425663,-0.066744, + 3.358625,2.425819,0, 3.3,2.4,0, 3.2832,2.4,-0.0675, + 3.2832,2.4,-0.0675, 3.341018,2.425663,-0.066744, 3.358625,2.425819,0, + 2.776365,2.436302,-0.064692, 2.747407,2.420406,-0.066744, 2.7298,2.42025,0, + 2.7298,2.42025,0, 2.7584,2.436,0, 2.776365,2.436302,-0.064692, + 2.825126,2.437123,-0.115008, 2.795198,2.420829,-0.118656, 2.747407,2.420406,-0.066744, + 2.747407,2.420406,-0.066744, 2.776365,2.436302,-0.064692, 2.825126,2.437123,-0.115008, + 2.896986,2.438333,-0.150948, 2.865626,2.421453,-0.155736, 2.795198,2.420829,-0.118656, + 2.795198,2.420829,-0.118656, 2.825126,2.437123,-0.115008, 2.896986,2.438333,-0.150948, + 2.984243,2.439802,-0.172512, 2.951146,2.42221,-0.177984, 2.865626,2.421453,-0.155736, + 2.865626,2.421453,-0.155736, 2.896986,2.438333,-0.150948, 2.984243,2.439802,-0.172512, + 3.0792,2.4414,-0.1797, 3.044212,2.423034,-0.1854, 2.951146,2.42221,-0.177984, + 2.951146,2.42221,-0.177984, 2.984243,2.439802,-0.172512, 3.0792,2.4414,-0.1797, + 3.174157,2.442998,-0.172512, 3.137279,2.423859,-0.177984, 3.044212,2.423034,-0.1854, + 3.044212,2.423034,-0.1854, 3.0792,2.4414,-0.1797, 3.174157,2.442998,-0.172512, + 3.261414,2.444467,-0.150948, 3.222799,2.424616,-0.155736, 3.137279,2.423859,-0.177984, + 3.137279,2.423859,-0.177984, 3.174157,2.442998,-0.172512, 3.261414,2.444467,-0.150948, + 3.333274,2.445677,-0.115008, 3.293227,2.42524,-0.118656, 3.222799,2.424616,-0.155736, + 3.222799,2.424616,-0.155736, 3.261414,2.444467,-0.150948, 3.333274,2.445677,-0.115008, + 3.382035,2.446498,-0.064692, 3.341018,2.425663,-0.066744, 3.293227,2.42524,-0.118656, + 3.293227,2.42524,-0.118656, 3.333274,2.445677,-0.115008, 3.382035,2.446498,-0.064692, + 3.4,2.4468,0, 3.358625,2.425819,0, 3.341018,2.425663,-0.066744, + 3.341018,2.425663,-0.066744, 3.382035,2.446498,-0.064692, 3.4,2.4468,0, + 2.802528,2.44768,-0.061668, 2.776365,2.436302,-0.064692, 2.7584,2.436,0, + 2.7584,2.436,0, 2.7846,2.44725,0, 2.802528,2.44768,-0.061668, + 2.851189,2.448847,-0.109632, 2.825126,2.437123,-0.115008, 2.776365,2.436302,-0.064692, + 2.776365,2.436302,-0.064692, 2.802528,2.44768,-0.061668, 2.851189,2.448847,-0.109632, + 2.922899,2.450567,-0.143892, 2.896986,2.438333,-0.150948, 2.825126,2.437123,-0.115008, + 2.825126,2.437123,-0.115008, 2.851189,2.448847,-0.109632, 2.922899,2.450567,-0.143892, + 3.009977,2.452655,-0.164448, 2.984243,2.439802,-0.172512, 2.896986,2.438333,-0.150948, + 2.896986,2.438333,-0.150948, 2.922899,2.450567,-0.143892, 3.009977,2.452655,-0.164448, + 3.104737,2.454928,-0.1713, 3.0792,2.4414,-0.1797, 2.984243,2.439802,-0.172512, + 2.984243,2.439802,-0.172512, 3.009977,2.452655,-0.164448, 3.104737,2.454928,-0.1713, + 3.199498,2.457201,-0.164448, 3.174157,2.442998,-0.172512, 3.0792,2.4414,-0.1797, + 3.0792,2.4414,-0.1797, 3.104737,2.454928,-0.1713, 3.199498,2.457201,-0.164448, + 3.286576,2.459289,-0.143892, 3.261414,2.444467,-0.150948, 3.174157,2.442998,-0.172512, + 3.174157,2.442998,-0.172512, 3.199498,2.457201,-0.164448, 3.286576,2.459289,-0.143892, + 3.358286,2.461009,-0.109632, 3.333274,2.445677,-0.115008, 3.261414,2.444467,-0.150948, + 3.261414,2.444467,-0.150948, 3.286576,2.459289,-0.143892, 3.358286,2.461009,-0.109632, + 3.406947,2.462176,-0.061668, 3.382035,2.446498,-0.064692, 3.333274,2.445677,-0.115008, + 3.333274,2.445677,-0.115008, 3.358286,2.461009,-0.109632, 3.406947,2.462176,-0.061668, + 3.424875,2.462606,0, 3.4,2.4468,0, 3.382035,2.446498,-0.064692, + 3.382035,2.446498,-0.064692, 3.406947,2.462176,-0.061668, 3.424875,2.462606,0, + 2.82475,2.454529,-0.057996, 2.802528,2.44768,-0.061668, 2.7846,2.44725,0, + 2.7846,2.44725,0, 2.8072,2.454,0, 2.82475,2.454529,-0.057996, + 2.872387,2.455966,-0.103104, 2.851189,2.448847,-0.109632, 2.802528,2.44768,-0.061668, + 2.802528,2.44768,-0.061668, 2.82475,2.454529,-0.057996, 2.872387,2.455966,-0.103104, + 2.942589,2.458082,-0.135324, 2.922899,2.450567,-0.143892, 2.851189,2.448847,-0.109632, + 2.851189,2.448847,-0.109632, 2.872387,2.455966,-0.103104, 2.942589,2.458082,-0.135324, + 3.027834,2.460653,-0.154656, 3.009977,2.452655,-0.164448, 2.922899,2.450567,-0.143892, + 2.922899,2.450567,-0.143892, 2.942589,2.458082,-0.135324, 3.027834,2.460653,-0.154656, + 3.1206,2.46345,-0.1611, 3.104737,2.454928,-0.1713, 3.009977,2.452655,-0.164448, + 3.009977,2.452655,-0.164448, 3.027834,2.460653,-0.154656, 3.1206,2.46345,-0.1611, + 3.213366,2.466247,-0.154656, 3.199498,2.457201,-0.164448, 3.104737,2.454928,-0.1713, + 3.104737,2.454928,-0.1713, 3.1206,2.46345,-0.1611, 3.213366,2.466247,-0.154656, + 3.298611,2.468818,-0.135324, 3.286576,2.459289,-0.143892, 3.199498,2.457201,-0.164448, + 3.199498,2.457201,-0.164448, 3.213366,2.466247,-0.154656, 3.298611,2.468818,-0.135324, + 3.368813,2.470934,-0.103104, 3.358286,2.461009,-0.109632, 3.286576,2.459289,-0.143892, + 3.286576,2.459289,-0.143892, 3.298611,2.468818,-0.135324, 3.368813,2.470934,-0.103104, + 3.41645,2.472371,-0.057996, 3.406947,2.462176,-0.061668, 3.358286,2.461009,-0.109632, + 3.358286,2.461009,-0.109632, 3.368813,2.470934,-0.103104, 3.41645,2.472371,-0.057996, + 3.434,2.4729,0, 3.424875,2.462606,0, 3.406947,2.462176,-0.061668, + 3.406947,2.462176,-0.061668, 3.41645,2.472371,-0.057996, 3.434,2.4729,0, + 2.841887,2.456841,-0.054, 2.82475,2.454529,-0.057996, 2.8072,2.454,0, + 2.8072,2.454,0, 2.825,2.45625,0, 2.841887,2.456841,-0.054, + 2.887725,2.458444,-0.096, 2.872387,2.455966,-0.103104, 2.82475,2.454529,-0.057996, + 2.82475,2.454529,-0.057996, 2.841887,2.456841,-0.054, 2.887725,2.458444,-0.096, + 2.955275,2.460806,-0.126, 2.942589,2.458082,-0.135324, 2.872387,2.455966,-0.103104, + 2.872387,2.455966,-0.103104, 2.887725,2.458444,-0.096, 2.955275,2.460806,-0.126, + 3.0373,2.463675,-0.144, 3.027834,2.460653,-0.154656, 2.942589,2.458082,-0.135324, + 2.942589,2.458082,-0.135324, 2.955275,2.460806,-0.126, 3.0373,2.463675,-0.144, + 3.126562,2.466797,-0.15, 3.1206,2.46345,-0.1611, 3.027834,2.460653,-0.154656, + 3.027834,2.460653,-0.154656, 3.0373,2.463675,-0.144, 3.126562,2.466797,-0.15, + 3.215825,2.469919,-0.144, 3.213366,2.466247,-0.154656, 3.1206,2.46345,-0.1611, + 3.1206,2.46345,-0.1611, 3.126562,2.466797,-0.15, 3.215825,2.469919,-0.144, + 3.29785,2.472787,-0.126, 3.298611,2.468818,-0.135324, 3.213366,2.466247,-0.154656, + 3.213366,2.466247,-0.154656, 3.215825,2.469919,-0.144, 3.29785,2.472787,-0.126, + 3.3654,2.47515,-0.096, 3.368813,2.470934,-0.103104, 3.298611,2.468818,-0.135324, + 3.298611,2.468818,-0.135324, 3.29785,2.472787,-0.126, 3.3654,2.47515,-0.096, + 3.411237,2.476753,-0.054, 3.41645,2.472371,-0.057996, 3.368813,2.470934,-0.103104, + 3.368813,2.470934,-0.103104, 3.3654,2.47515,-0.096, 3.411237,2.476753,-0.054, + 3.428125,2.477344,0, 3.434,2.4729,0, 3.41645,2.472371,-0.057996, + 3.41645,2.472371,-0.057996, 3.411237,2.476753,-0.054, 3.428125,2.477344,0, + 2.852794,2.454605,-0.050004, 2.841887,2.456841,-0.054, 2.825,2.45625,0, + 2.825,2.45625,0, 2.8368,2.454,0, 2.852794,2.454605,-0.050004, + 2.896205,2.456246,-0.088896, 2.887725,2.458444,-0.096, 2.841887,2.456841,-0.054, + 2.841887,2.456841,-0.054, 2.852794,2.454605,-0.050004, 2.896205,2.456246,-0.088896, + 2.960179,2.458666,-0.116676, 2.955275,2.460806,-0.126, 2.887725,2.458444,-0.096, + 2.887725,2.458444,-0.096, 2.896205,2.456246,-0.088896, 2.960179,2.458666,-0.116676, + 3.037862,2.461603,-0.133344, 3.0373,2.463675,-0.144, 2.955275,2.460806,-0.126, + 2.955275,2.460806,-0.126, 2.960179,2.458666,-0.116676, 3.037862,2.461603,-0.133344, + 3.1224,2.4648,-0.1389, 3.126562,2.466797,-0.15, 3.0373,2.463675,-0.144, + 3.0373,2.463675,-0.144, 3.037862,2.461603,-0.133344, 3.1224,2.4648,-0.1389, + 3.206938,2.467997,-0.133344, 3.215825,2.469919,-0.144, 3.126562,2.466797,-0.15, + 3.126562,2.466797,-0.15, 3.1224,2.4648,-0.1389, 3.206938,2.467997,-0.133344, + 3.284621,2.470934,-0.116676, 3.29785,2.472787,-0.126, 3.215825,2.469919,-0.144, + 3.215825,2.469919,-0.144, 3.206938,2.467997,-0.133344, 3.284621,2.470934,-0.116676, + 3.348595,2.473354,-0.088896, 3.3654,2.47515,-0.096, 3.29785,2.472787,-0.126, + 3.29785,2.472787,-0.126, 3.284621,2.470934,-0.116676, 3.348595,2.473354,-0.088896, + 3.392006,2.474995,-0.050004, 3.411237,2.476753,-0.054, 3.3654,2.47515,-0.096, + 3.3654,2.47515,-0.096, 3.348595,2.473354,-0.088896, 3.392006,2.474995,-0.050004, + 3.408,2.4756,0, 3.428125,2.477344,0, 3.411237,2.476753,-0.054, + 3.411237,2.476753,-0.054, 3.392006,2.474995,-0.050004, 3.408,2.4756,0, + 2.856323,2.447812,-0.046332, 2.852794,2.454605,-0.050004, 2.8368,2.454,0, + 2.8368,2.454,0, 2.8414,2.44725,0, 2.856323,2.447812,-0.046332, + 2.896829,2.449338,-0.082368, 2.896205,2.456246,-0.088896, 2.852794,2.454605,-0.050004, + 2.852794,2.454605,-0.050004, 2.856323,2.447812,-0.046332, 2.896829,2.449338,-0.082368, + 2.956523,2.451588,-0.108108, 2.960179,2.458666,-0.116676, 2.896205,2.456246,-0.088896, + 2.896205,2.456246,-0.088896, 2.896829,2.449338,-0.082368, 2.956523,2.451588,-0.108108, + 3.029007,2.454319,-0.123552, 3.037862,2.461603,-0.133344, 2.960179,2.458666,-0.116676, + 2.960179,2.458666,-0.116676, 2.956523,2.451588,-0.108108, 3.029007,2.454319,-0.123552, + 3.107887,2.457291,-0.1287, 3.1224,2.4648,-0.1389, 3.037862,2.461603,-0.133344, + 3.037862,2.461603,-0.133344, 3.029007,2.454319,-0.123552, 3.107887,2.457291,-0.1287, + 3.186768,2.460263,-0.123552, 3.206938,2.467997,-0.133344, 3.1224,2.4648,-0.1389, + 3.1224,2.4648,-0.1389, 3.107887,2.457291,-0.1287, 3.186768,2.460263,-0.123552, + 3.259252,2.462994,-0.108108, 3.284621,2.470934,-0.116676, 3.206938,2.467997,-0.133344, + 3.206938,2.467997,-0.133344, 3.186768,2.460263,-0.123552, 3.259252,2.462994,-0.108108, + 3.318946,2.465243,-0.082368, 3.348595,2.473354,-0.088896, 3.284621,2.470934,-0.116676, + 3.284621,2.470934,-0.116676, 3.259252,2.462994,-0.108108, 3.318946,2.465243,-0.082368, + 3.359452,2.466769,-0.046332, 3.392006,2.474995,-0.050004, 3.348595,2.473354,-0.088896, + 3.348595,2.473354,-0.088896, 3.318946,2.465243,-0.082368, 3.359452,2.466769,-0.046332, + 3.374375,2.467331,0, 3.408,2.4756,0, 3.392006,2.474995,-0.050004, + 3.392006,2.474995,-0.050004, 3.359452,2.466769,-0.046332, 3.374375,2.467331,0, + 2.851331,2.436454,-0.043308, 2.856323,2.447812,-0.046332, 2.8414,2.44725,0, + 2.8414,2.44725,0, 2.8376,2.436,0, 2.851331,2.436454,-0.043308, + 2.888602,2.437685,-0.076992, 2.896829,2.449338,-0.082368, 2.856323,2.447812,-0.046332, + 2.856323,2.447812,-0.046332, 2.851331,2.436454,-0.043308, 2.888602,2.437685,-0.076992, + 2.943526,2.439499,-0.101052, 2.956523,2.451588,-0.108108, 2.896829,2.449338,-0.082368, + 2.896829,2.449338,-0.082368, 2.888602,2.437685,-0.076992, 2.943526,2.439499,-0.101052, + 3.010221,2.441702,-0.115488, 3.029007,2.454319,-0.123552, 2.956523,2.451588,-0.108108, + 2.956523,2.451588,-0.108108, 2.943526,2.439499,-0.101052, 3.010221,2.441702,-0.115488, + 3.0828,2.4441,-0.1203, 3.107887,2.457291,-0.1287, 3.029007,2.454319,-0.123552, + 3.029007,2.454319,-0.123552, 3.010221,2.441702,-0.115488, 3.0828,2.4441,-0.1203, + 3.155379,2.446498,-0.115488, 3.186768,2.460263,-0.123552, 3.107887,2.457291,-0.1287, + 3.107887,2.457291,-0.1287, 3.0828,2.4441,-0.1203, 3.155379,2.446498,-0.115488, + 3.222074,2.448701,-0.101052, 3.259252,2.462994,-0.108108, 3.186768,2.460263,-0.123552, + 3.186768,2.460263,-0.123552, 3.155379,2.446498,-0.115488, 3.222074,2.448701,-0.101052, + 3.276998,2.450515,-0.076992, 3.318946,2.465243,-0.082368, 3.259252,2.462994,-0.108108, + 3.259252,2.462994,-0.108108, 3.222074,2.448701,-0.101052, 3.276998,2.450515,-0.076992, + 3.314269,2.451746,-0.043308, 3.359452,2.466769,-0.046332, 3.318946,2.465243,-0.082368, + 3.318946,2.465243,-0.082368, 3.276998,2.450515,-0.076992, 3.314269,2.451746,-0.043308, + 3.328,2.4522,0, 3.374375,2.467331,0, 3.359452,2.466769,-0.046332, + 3.359452,2.466769,-0.046332, 3.314269,2.451746,-0.043308, 3.328,2.4522,0, + 2.836672,2.420519,-0.041256, 2.851331,2.436454,-0.043308, 2.8376,2.436,0, + 2.8376,2.436,0, 2.8242,2.42025,0, 2.836672,2.420519,-0.041256, + 2.870524,2.42125,-0.073344, 2.888602,2.437685,-0.076992, 2.851331,2.436454,-0.043308, + 2.851331,2.436454,-0.043308, 2.836672,2.420519,-0.041256, 2.870524,2.42125,-0.073344, + 2.920412,2.422328,-0.096264, 2.943526,2.439499,-0.101052, 2.888602,2.437685,-0.076992, + 2.888602,2.437685,-0.076992, 2.870524,2.42125,-0.073344, 2.920412,2.422328,-0.096264, + 2.98099,2.423636,-0.110016, 3.010221,2.441702,-0.115488, 2.943526,2.439499,-0.101052, + 2.943526,2.439499,-0.101052, 2.920412,2.422328,-0.096264, 2.98099,2.423636,-0.110016, + 3.046912,2.425059,-0.1146, 3.0828,2.4441,-0.1203, 3.010221,2.441702,-0.115488, + 3.010221,2.441702,-0.115488, 2.98099,2.423636,-0.110016, 3.046912,2.425059,-0.1146, + 3.112835,2.426483,-0.110016, 3.155379,2.446498,-0.115488, 3.0828,2.4441,-0.1203, + 3.0828,2.4441,-0.1203, 3.046912,2.425059,-0.1146, 3.112835,2.426483,-0.110016, + 3.173413,2.427791,-0.096264, 3.222074,2.448701,-0.101052, 3.155379,2.446498,-0.115488, + 3.155379,2.446498,-0.115488, 3.112835,2.426483,-0.110016, 3.173413,2.427791,-0.096264, + 3.223301,2.428868,-0.073344, 3.276998,2.450515,-0.076992, 3.222074,2.448701,-0.101052, + 3.222074,2.448701,-0.101052, 3.173413,2.427791,-0.096264, 3.223301,2.428868,-0.073344, + 3.257153,2.429599,-0.041256, 3.314269,2.451746,-0.043308, 3.276998,2.450515,-0.076992, + 3.276998,2.450515,-0.076992, 3.223301,2.428868,-0.073344, 3.257153,2.429599,-0.041256, + 3.269625,2.429869,0, 3.328,2.4522,0, 3.314269,2.451746,-0.043308, + 3.314269,2.451746,-0.043308, 3.257153,2.429599,-0.041256, 3.269625,2.429869,0, + 2.8112,2.4,-0.0405, 2.836672,2.420519,-0.041256, 2.8242,2.42025,0, + 2.8242,2.42025,0, 2.8,2.4,0, 2.8112,2.4,-0.0405, + 2.8416,2.4,-0.072, 2.870524,2.42125,-0.073344, 2.836672,2.420519,-0.041256, + 2.836672,2.420519,-0.041256, 2.8112,2.4,-0.0405, 2.8416,2.4,-0.072, + 2.8864,2.4,-0.0945, 2.920412,2.422328,-0.096264, 2.870524,2.42125,-0.073344, + 2.870524,2.42125,-0.073344, 2.8416,2.4,-0.072, 2.8864,2.4,-0.0945, + 2.9408,2.4,-0.108, 2.98099,2.423636,-0.110016, 2.920412,2.422328,-0.096264, + 2.920412,2.422328,-0.096264, 2.8864,2.4,-0.0945, 2.9408,2.4,-0.108, + 3,2.4,-0.1125, 3.046912,2.425059,-0.1146, 2.98099,2.423636,-0.110016, + 2.98099,2.423636,-0.110016, 2.9408,2.4,-0.108, 3,2.4,-0.1125, + 3.0592,2.4,-0.108, 3.112835,2.426483,-0.110016, 3.046912,2.425059,-0.1146, + 3.046912,2.425059,-0.1146, 3,2.4,-0.1125, 3.0592,2.4,-0.108, + 3.1136,2.4,-0.0945, 3.173413,2.427791,-0.096264, 3.112835,2.426483,-0.110016, + 3.112835,2.426483,-0.110016, 3.0592,2.4,-0.108, 3.1136,2.4,-0.0945, + 3.1584,2.4,-0.072, 3.223301,2.428868,-0.073344, 3.173413,2.427791,-0.096264, + 3.173413,2.427791,-0.096264, 3.1136,2.4,-0.0945, 3.1584,2.4,-0.072, + 3.1888,2.4,-0.0405, 3.257153,2.429599,-0.041256, 3.223301,2.428868,-0.073344, + 3.223301,2.428868,-0.073344, 3.1584,2.4,-0.072, 3.1888,2.4,-0.0405, + 3.2,2.4,0, 3.269625,2.429869,0, 3.257153,2.429599,-0.041256, + 3.257153,2.429599,-0.041256, 3.1888,2.4,-0.0405, 3.2,2.4,0, + 3.341018,2.425663,0.066744, 3.2832,2.4,0.0675, 3.3,2.4,0, + 3.3,2.4,0, 3.358625,2.425819,0, 3.341018,2.425663,0.066744, + 3.293227,2.42524,0.118656, 3.2376,2.4,0.12, 3.2832,2.4,0.0675, + 3.2832,2.4,0.0675, 3.341018,2.425663,0.066744, 3.293227,2.42524,0.118656, + 3.222799,2.424616,0.155736, 3.1704,2.4,0.1575, 3.2376,2.4,0.12, + 3.2376,2.4,0.12, 3.293227,2.42524,0.118656, 3.222799,2.424616,0.155736, + 3.137279,2.423859,0.177984, 3.0888,2.4,0.18, 3.1704,2.4,0.1575, + 3.1704,2.4,0.1575, 3.222799,2.424616,0.155736, 3.137279,2.423859,0.177984, + 3.044212,2.423034,0.1854, 3,2.4,0.1875, 3.0888,2.4,0.18, + 3.0888,2.4,0.18, 3.137279,2.423859,0.177984, 3.044212,2.423034,0.1854, + 2.951146,2.42221,0.177984, 2.9112,2.4,0.18, 3,2.4,0.1875, + 3,2.4,0.1875, 3.044212,2.423034,0.1854, 2.951146,2.42221,0.177984, + 2.865626,2.421453,0.155736, 2.8296,2.4,0.1575, 2.9112,2.4,0.18, + 2.9112,2.4,0.18, 2.951146,2.42221,0.177984, 2.865626,2.421453,0.155736, + 2.795198,2.420829,0.118656, 2.7624,2.4,0.12, 2.8296,2.4,0.1575, + 2.8296,2.4,0.1575, 2.865626,2.421453,0.155736, 2.795198,2.420829,0.118656, + 2.747407,2.420406,0.066744, 2.7168,2.4,0.0675, 2.7624,2.4,0.12, + 2.7624,2.4,0.12, 2.795198,2.420829,0.118656, 2.747407,2.420406,0.066744, + 2.7298,2.42025,0, 2.7,2.4,0, 2.7168,2.4,0.0675, + 2.7168,2.4,0.0675, 2.747407,2.420406,0.066744, 2.7298,2.42025,0, + 3.382035,2.446498,0.064692, 3.341018,2.425663,0.066744, 3.358625,2.425819,0, + 3.358625,2.425819,0, 3.4,2.4468,0, 3.382035,2.446498,0.064692, + 3.333274,2.445677,0.115008, 3.293227,2.42524,0.118656, 3.341018,2.425663,0.066744, + 3.341018,2.425663,0.066744, 3.382035,2.446498,0.064692, 3.333274,2.445677,0.115008, + 3.261414,2.444467,0.150948, 3.222799,2.424616,0.155736, 3.293227,2.42524,0.118656, + 3.293227,2.42524,0.118656, 3.333274,2.445677,0.115008, 3.261414,2.444467,0.150948, + 3.174157,2.442998,0.172512, 3.137279,2.423859,0.177984, 3.222799,2.424616,0.155736, + 3.222799,2.424616,0.155736, 3.261414,2.444467,0.150948, 3.174157,2.442998,0.172512, + 3.0792,2.4414,0.1797, 3.044212,2.423034,0.1854, 3.137279,2.423859,0.177984, + 3.137279,2.423859,0.177984, 3.174157,2.442998,0.172512, 3.0792,2.4414,0.1797, + 2.984243,2.439802,0.172512, 2.951146,2.42221,0.177984, 3.044212,2.423034,0.1854, + 3.044212,2.423034,0.1854, 3.0792,2.4414,0.1797, 2.984243,2.439802,0.172512, + 2.896986,2.438333,0.150948, 2.865626,2.421453,0.155736, 2.951146,2.42221,0.177984, + 2.951146,2.42221,0.177984, 2.984243,2.439802,0.172512, 2.896986,2.438333,0.150948, + 2.825126,2.437123,0.115008, 2.795198,2.420829,0.118656, 2.865626,2.421453,0.155736, + 2.865626,2.421453,0.155736, 2.896986,2.438333,0.150948, 2.825126,2.437123,0.115008, + 2.776365,2.436302,0.064692, 2.747407,2.420406,0.066744, 2.795198,2.420829,0.118656, + 2.795198,2.420829,0.118656, 2.825126,2.437123,0.115008, 2.776365,2.436302,0.064692, + 2.7584,2.436,0, 2.7298,2.42025,0, 2.747407,2.420406,0.066744, + 2.747407,2.420406,0.066744, 2.776365,2.436302,0.064692, 2.7584,2.436,0, + 3.406947,2.462176,0.061668, 3.382035,2.446498,0.064692, 3.4,2.4468,0, + 3.4,2.4468,0, 3.424875,2.462606,0, 3.406947,2.462176,0.061668, + 3.358286,2.461009,0.109632, 3.333274,2.445677,0.115008, 3.382035,2.446498,0.064692, + 3.382035,2.446498,0.064692, 3.406947,2.462176,0.061668, 3.358286,2.461009,0.109632, + 3.286576,2.459289,0.143892, 3.261414,2.444467,0.150948, 3.333274,2.445677,0.115008, + 3.333274,2.445677,0.115008, 3.358286,2.461009,0.109632, 3.286576,2.459289,0.143892, + 3.199498,2.457201,0.164448, 3.174157,2.442998,0.172512, 3.261414,2.444467,0.150948, + 3.261414,2.444467,0.150948, 3.286576,2.459289,0.143892, 3.199498,2.457201,0.164448, + 3.104738,2.454928,0.1713, 3.0792,2.4414,0.1797, 3.174157,2.442998,0.172512, + 3.174157,2.442998,0.172512, 3.199498,2.457201,0.164448, 3.104738,2.454928,0.1713, + 3.009977,2.452655,0.164448, 2.984243,2.439802,0.172512, 3.0792,2.4414,0.1797, + 3.0792,2.4414,0.1797, 3.104738,2.454928,0.1713, 3.009977,2.452655,0.164448, + 2.922899,2.450567,0.143892, 2.896986,2.438333,0.150948, 2.984243,2.439802,0.172512, + 2.984243,2.439802,0.172512, 3.009977,2.452655,0.164448, 2.922899,2.450567,0.143892, + 2.851189,2.448847,0.109632, 2.825126,2.437123,0.115008, 2.896986,2.438333,0.150948, + 2.896986,2.438333,0.150948, 2.922899,2.450567,0.143892, 2.851189,2.448847,0.109632, + 2.802528,2.44768,0.061668, 2.776365,2.436302,0.064692, 2.825126,2.437123,0.115008, + 2.825126,2.437123,0.115008, 2.851189,2.448847,0.109632, 2.802528,2.44768,0.061668, + 2.7846,2.44725,0, 2.7584,2.436,0, 2.776365,2.436302,0.064692, + 2.776365,2.436302,0.064692, 2.802528,2.44768,0.061668, 2.7846,2.44725,0, + 3.41645,2.472371,0.057996, 3.406947,2.462176,0.061668, 3.424875,2.462606,0, + 3.424875,2.462606,0, 3.434,2.4729,0, 3.41645,2.472371,0.057996, + 3.368813,2.470934,0.103104, 3.358286,2.461009,0.109632, 3.406947,2.462176,0.061668, + 3.406947,2.462176,0.061668, 3.41645,2.472371,0.057996, 3.368813,2.470934,0.103104, + 3.298611,2.468818,0.135324, 3.286576,2.459289,0.143892, 3.358286,2.461009,0.109632, + 3.358286,2.461009,0.109632, 3.368813,2.470934,0.103104, 3.298611,2.468818,0.135324, + 3.213366,2.466247,0.154656, 3.199498,2.457201,0.164448, 3.286576,2.459289,0.143892, + 3.286576,2.459289,0.143892, 3.298611,2.468818,0.135324, 3.213366,2.466247,0.154656, + 3.1206,2.46345,0.1611, 3.104738,2.454928,0.1713, 3.199498,2.457201,0.164448, + 3.199498,2.457201,0.164448, 3.213366,2.466247,0.154656, 3.1206,2.46345,0.1611, + 3.027834,2.460653,0.154656, 3.009977,2.452655,0.164448, 3.104738,2.454928,0.1713, + 3.104738,2.454928,0.1713, 3.1206,2.46345,0.1611, 3.027834,2.460653,0.154656, + 2.942589,2.458082,0.135324, 2.922899,2.450567,0.143892, 3.009977,2.452655,0.164448, + 3.009977,2.452655,0.164448, 3.027834,2.460653,0.154656, 2.942589,2.458082,0.135324, + 2.872387,2.455966,0.103104, 2.851189,2.448847,0.109632, 2.922899,2.450567,0.143892, + 2.922899,2.450567,0.143892, 2.942589,2.458082,0.135324, 2.872387,2.455966,0.103104, + 2.82475,2.454529,0.057996, 2.802528,2.44768,0.061668, 2.851189,2.448847,0.109632, + 2.851189,2.448847,0.109632, 2.872387,2.455966,0.103104, 2.82475,2.454529,0.057996, + 2.8072,2.454,0, 2.7846,2.44725,0, 2.802528,2.44768,0.061668, + 2.802528,2.44768,0.061668, 2.82475,2.454529,0.057996, 2.8072,2.454,0, + 3.411237,2.476753,0.054, 3.41645,2.472371,0.057996, 3.434,2.4729,0, + 3.434,2.4729,0, 3.428125,2.477344,0, 3.411237,2.476753,0.054, + 3.3654,2.47515,0.096, 3.368813,2.470934,0.103104, 3.41645,2.472371,0.057996, + 3.41645,2.472371,0.057996, 3.411237,2.476753,0.054, 3.3654,2.47515,0.096, + 3.29785,2.472788,0.126, 3.298611,2.468818,0.135324, 3.368813,2.470934,0.103104, + 3.368813,2.470934,0.103104, 3.3654,2.47515,0.096, 3.29785,2.472788,0.126, + 3.215825,2.469919,0.144, 3.213366,2.466247,0.154656, 3.298611,2.468818,0.135324, + 3.298611,2.468818,0.135324, 3.29785,2.472788,0.126, 3.215825,2.469919,0.144, + 3.126562,2.466797,0.15, 3.1206,2.46345,0.1611, 3.213366,2.466247,0.154656, + 3.213366,2.466247,0.154656, 3.215825,2.469919,0.144, 3.126562,2.466797,0.15, + 3.0373,2.463675,0.144, 3.027834,2.460653,0.154656, 3.1206,2.46345,0.1611, + 3.1206,2.46345,0.1611, 3.126562,2.466797,0.15, 3.0373,2.463675,0.144, + 2.955275,2.460806,0.126, 2.942589,2.458082,0.135324, 3.027834,2.460653,0.154656, + 3.027834,2.460653,0.154656, 3.0373,2.463675,0.144, 2.955275,2.460806,0.126, + 2.887725,2.458444,0.096, 2.872387,2.455966,0.103104, 2.942589,2.458082,0.135324, + 2.942589,2.458082,0.135324, 2.955275,2.460806,0.126, 2.887725,2.458444,0.096, + 2.841887,2.456841,0.054, 2.82475,2.454529,0.057996, 2.872387,2.455966,0.103104, + 2.872387,2.455966,0.103104, 2.887725,2.458444,0.096, 2.841887,2.456841,0.054, + 2.825,2.45625,0, 2.8072,2.454,0, 2.82475,2.454529,0.057996, + 2.82475,2.454529,0.057996, 2.841887,2.456841,0.054, 2.825,2.45625,0, + 3.392006,2.474995,0.050004, 3.411237,2.476753,0.054, 3.428125,2.477344,0, + 3.428125,2.477344,0, 3.408,2.4756,0, 3.392006,2.474995,0.050004, + 3.348595,2.473354,0.088896, 3.3654,2.47515,0.096, 3.411237,2.476753,0.054, + 3.411237,2.476753,0.054, 3.392006,2.474995,0.050004, 3.348595,2.473354,0.088896, + 3.284621,2.470934,0.116676, 3.29785,2.472788,0.126, 3.3654,2.47515,0.096, + 3.3654,2.47515,0.096, 3.348595,2.473354,0.088896, 3.284621,2.470934,0.116676, + 3.206938,2.467997,0.133344, 3.215825,2.469919,0.144, 3.29785,2.472788,0.126, + 3.29785,2.472788,0.126, 3.284621,2.470934,0.116676, 3.206938,2.467997,0.133344, + 3.1224,2.4648,0.1389, 3.126562,2.466797,0.15, 3.215825,2.469919,0.144, + 3.215825,2.469919,0.144, 3.206938,2.467997,0.133344, 3.1224,2.4648,0.1389, + 3.037862,2.461603,0.133344, 3.0373,2.463675,0.144, 3.126562,2.466797,0.15, + 3.126562,2.466797,0.15, 3.1224,2.4648,0.1389, 3.037862,2.461603,0.133344, + 2.960179,2.458666,0.116676, 2.955275,2.460806,0.126, 3.0373,2.463675,0.144, + 3.0373,2.463675,0.144, 3.037862,2.461603,0.133344, 2.960179,2.458666,0.116676, + 2.896205,2.456246,0.088896, 2.887725,2.458444,0.096, 2.955275,2.460806,0.126, + 2.955275,2.460806,0.126, 2.960179,2.458666,0.116676, 2.896205,2.456246,0.088896, + 2.852794,2.454605,0.050004, 2.841887,2.456841,0.054, 2.887725,2.458444,0.096, + 2.887725,2.458444,0.096, 2.896205,2.456246,0.088896, 2.852794,2.454605,0.050004, + 2.8368,2.454,0, 2.825,2.45625,0, 2.841887,2.456841,0.054, + 2.841887,2.456841,0.054, 2.852794,2.454605,0.050004, 2.8368,2.454,0, + 3.359452,2.466769,0.046332, 3.392006,2.474995,0.050004, 3.408,2.4756,0, + 3.408,2.4756,0, 3.374375,2.467331,0, 3.359452,2.466769,0.046332, + 3.318946,2.465243,0.082368, 3.348595,2.473354,0.088896, 3.392006,2.474995,0.050004, + 3.392006,2.474995,0.050004, 3.359452,2.466769,0.046332, 3.318946,2.465243,0.082368, + 3.259252,2.462994,0.108108, 3.284621,2.470934,0.116676, 3.348595,2.473354,0.088896, + 3.348595,2.473354,0.088896, 3.318946,2.465243,0.082368, 3.259252,2.462994,0.108108, + 3.186768,2.460263,0.123552, 3.206938,2.467997,0.133344, 3.284621,2.470934,0.116676, + 3.284621,2.470934,0.116676, 3.259252,2.462994,0.108108, 3.186768,2.460263,0.123552, + 3.107887,2.457291,0.1287, 3.1224,2.4648,0.1389, 3.206938,2.467997,0.133344, + 3.206938,2.467997,0.133344, 3.186768,2.460263,0.123552, 3.107887,2.457291,0.1287, + 3.029007,2.454319,0.123552, 3.037862,2.461603,0.133344, 3.1224,2.4648,0.1389, + 3.1224,2.4648,0.1389, 3.107887,2.457291,0.1287, 3.029007,2.454319,0.123552, + 2.956523,2.451588,0.108108, 2.960179,2.458666,0.116676, 3.037862,2.461603,0.133344, + 3.037862,2.461603,0.133344, 3.029007,2.454319,0.123552, 2.956523,2.451588,0.108108, + 2.896829,2.449338,0.082368, 2.896205,2.456246,0.088896, 2.960179,2.458666,0.116676, + 2.960179,2.458666,0.116676, 2.956523,2.451588,0.108108, 2.896829,2.449338,0.082368, + 2.856323,2.447812,0.046332, 2.852794,2.454605,0.050004, 2.896205,2.456246,0.088896, + 2.896205,2.456246,0.088896, 2.896829,2.449338,0.082368, 2.856323,2.447812,0.046332, + 2.8414,2.44725,0, 2.8368,2.454,0, 2.852794,2.454605,0.050004, + 2.852794,2.454605,0.050004, 2.856323,2.447812,0.046332, 2.8414,2.44725,0, + 3.314269,2.451746,0.043308, 3.359452,2.466769,0.046332, 3.374375,2.467331,0, + 3.374375,2.467331,0, 3.328,2.4522,0, 3.314269,2.451746,0.043308, + 3.276998,2.450515,0.076992, 3.318946,2.465243,0.082368, 3.359452,2.466769,0.046332, + 3.359452,2.466769,0.046332, 3.314269,2.451746,0.043308, 3.276998,2.450515,0.076992, + 3.222074,2.448701,0.101052, 3.259252,2.462994,0.108108, 3.318946,2.465243,0.082368, + 3.318946,2.465243,0.082368, 3.276998,2.450515,0.076992, 3.222074,2.448701,0.101052, + 3.155379,2.446498,0.115488, 3.186768,2.460263,0.123552, 3.259252,2.462994,0.108108, + 3.259252,2.462994,0.108108, 3.222074,2.448701,0.101052, 3.155379,2.446498,0.115488, + 3.0828,2.4441,0.1203, 3.107887,2.457291,0.1287, 3.186768,2.460263,0.123552, + 3.186768,2.460263,0.123552, 3.155379,2.446498,0.115488, 3.0828,2.4441,0.1203, + 3.010221,2.441702,0.115488, 3.029007,2.454319,0.123552, 3.107887,2.457291,0.1287, + 3.107887,2.457291,0.1287, 3.0828,2.4441,0.1203, 3.010221,2.441702,0.115488, + 2.943526,2.439499,0.101052, 2.956523,2.451588,0.108108, 3.029007,2.454319,0.123552, + 3.029007,2.454319,0.123552, 3.010221,2.441702,0.115488, 2.943526,2.439499,0.101052, + 2.888602,2.437685,0.076992, 2.896829,2.449338,0.082368, 2.956523,2.451588,0.108108, + 2.956523,2.451588,0.108108, 2.943526,2.439499,0.101052, 2.888602,2.437685,0.076992, + 2.851331,2.436454,0.043308, 2.856323,2.447812,0.046332, 2.896829,2.449338,0.082368, + 2.896829,2.449338,0.082368, 2.888602,2.437685,0.076992, 2.851331,2.436454,0.043308, + 2.8376,2.436,0, 2.8414,2.44725,0, 2.856323,2.447812,0.046332, + 2.856323,2.447812,0.046332, 2.851331,2.436454,0.043308, 2.8376,2.436,0, + 3.257153,2.429599,0.041256, 3.314269,2.451746,0.043308, 3.328,2.4522,0, + 3.328,2.4522,0, 3.269625,2.429869,0, 3.257153,2.429599,0.041256, + 3.223301,2.428868,0.073344, 3.276998,2.450515,0.076992, 3.314269,2.451746,0.043308, + 3.314269,2.451746,0.043308, 3.257153,2.429599,0.041256, 3.223301,2.428868,0.073344, + 3.173413,2.427791,0.096264, 3.222074,2.448701,0.101052, 3.276998,2.450515,0.076992, + 3.276998,2.450515,0.076992, 3.223301,2.428868,0.073344, 3.173413,2.427791,0.096264, + 3.112835,2.426483,0.110016, 3.155379,2.446498,0.115488, 3.222074,2.448701,0.101052, + 3.222074,2.448701,0.101052, 3.173413,2.427791,0.096264, 3.112835,2.426483,0.110016, + 3.046912,2.425059,0.1146, 3.0828,2.4441,0.1203, 3.155379,2.446498,0.115488, + 3.155379,2.446498,0.115488, 3.112835,2.426483,0.110016, 3.046912,2.425059,0.1146, + 2.98099,2.423636,0.110016, 3.010221,2.441702,0.115488, 3.0828,2.4441,0.1203, + 3.0828,2.4441,0.1203, 3.046912,2.425059,0.1146, 2.98099,2.423636,0.110016, + 2.920412,2.422328,0.096264, 2.943526,2.439499,0.101052, 3.010221,2.441702,0.115488, + 3.010221,2.441702,0.115488, 2.98099,2.423636,0.110016, 2.920412,2.422328,0.096264, + 2.870524,2.42125,0.073344, 2.888602,2.437685,0.076992, 2.943526,2.439499,0.101052, + 2.943526,2.439499,0.101052, 2.920412,2.422328,0.096264, 2.870524,2.42125,0.073344, + 2.836672,2.420519,0.041256, 2.851331,2.436454,0.043308, 2.888602,2.437685,0.076992, + 2.888602,2.437685,0.076992, 2.870524,2.42125,0.073344, 2.836672,2.420519,0.041256, + 2.8242,2.42025,0, 2.8376,2.436,0, 2.851331,2.436454,0.043308, + 2.851331,2.436454,0.043308, 2.836672,2.420519,0.041256, 2.8242,2.42025,0, + 3.1888,2.4,0.0405, 3.257153,2.429599,0.041256, 3.269625,2.429869,0, + 3.269625,2.429869,0, 3.2,2.4,0, 3.1888,2.4,0.0405, + 3.1584,2.4,0.072, 3.223301,2.428868,0.073344, 3.257153,2.429599,0.041256, + 3.257153,2.429599,0.041256, 3.1888,2.4,0.0405, 3.1584,2.4,0.072, + 3.1136,2.4,0.0945, 3.173413,2.427791,0.096264, 3.223301,2.428868,0.073344, + 3.223301,2.428868,0.073344, 3.1584,2.4,0.072, 3.1136,2.4,0.0945, + 3.0592,2.4,0.108, 3.112835,2.426483,0.110016, 3.173413,2.427791,0.096264, + 3.173413,2.427791,0.096264, 3.1136,2.4,0.0945, 3.0592,2.4,0.108, + 3,2.4,0.1125, 3.046912,2.425059,0.1146, 3.112835,2.426483,0.110016, + 3.112835,2.426483,0.110016, 3.0592,2.4,0.108, 3,2.4,0.1125, + 2.9408,2.4,0.108, 2.98099,2.423636,0.110016, 3.046912,2.425059,0.1146, + 3.046912,2.425059,0.1146, 3,2.4,0.1125, 2.9408,2.4,0.108, + 2.8864,2.4,0.0945, 2.920412,2.422328,0.096264, 2.98099,2.423636,0.110016, + 2.98099,2.423636,0.110016, 2.9408,2.4,0.108, 2.8864,2.4,0.0945, + 2.8416,2.4,0.072, 2.870524,2.42125,0.073344, 2.920412,2.422328,0.096264, + 2.920412,2.422328,0.096264, 2.8864,2.4,0.0945, 2.8416,2.4,0.072, + 2.8112,2.4,0.0405, 2.836672,2.420519,0.041256, 2.870524,2.42125,0.073344, + 2.870524,2.42125,0.073344, 2.8416,2.4,0.072, 2.8112,2.4,0.0405, + 2.8,2.4,0, 2.8242,2.42025,0, 2.836672,2.420519,0.041256, + 2.836672,2.420519,0.041256, 2.8112,2.4,0.0405, 2.8,2.4,0, + 0,3.15,0, 0.1946,3.14145,0, 0.192107,3.14145,-0.032048, + 0,3.15,0, 0.192107,3.14145,-0.032048, 0.18487,3.14145,-0.062272, + 0,3.15,0, 0.18487,3.14145,-0.062272, 0.173255,3.14145,-0.090306, + 0,3.15,0, 0.173255,3.14145,-0.090306, 0.157626,3.14145,-0.115787, + 0,3.15,0, 0.157626,3.14145,-0.115787, 0.138348,3.14145,-0.138348, + 0,3.15,0, 0.138348,3.14145,-0.138348, 0.115787,3.14145,-0.157626, + 0,3.15,0, 0.115787,3.14145,-0.157626, 0.090306,3.14145,-0.173255, + 0,3.15,0, 0.090306,3.14145,-0.173255, 0.062272,3.14145,-0.18487, + 0,3.15,0, 0.062272,3.14145,-0.18487, 0.032048,3.14145,-0.192107, + 0,3.15,0, 0.032048,3.14145,-0.192107, 0,3.14145,-0.1946, + 0.304843,3.1176,-0.050855, 0.192107,3.14145,-0.032048, 0.1946,3.14145,0, + 0.1946,3.14145,0, 0.3088,3.1176,0, 0.304843,3.1176,-0.050855, + 0.29336,3.1176,-0.098814, 0.18487,3.14145,-0.062272, 0.192107,3.14145,-0.032048, + 0.192107,3.14145,-0.032048, 0.304843,3.1176,-0.050855, 0.29336,3.1176,-0.098814, + 0.274928,3.1176,-0.143301, 0.173255,3.14145,-0.090306, 0.18487,3.14145,-0.062272, + 0.18487,3.14145,-0.062272, 0.29336,3.1176,-0.098814, 0.274928,3.1176,-0.143301, + 0.250127,3.1176,-0.183734, 0.157626,3.14145,-0.115787, 0.173255,3.14145,-0.090306, + 0.173255,3.14145,-0.090306, 0.274928,3.1176,-0.143301, 0.250127,3.1176,-0.183734, + 0.219536,3.1176,-0.219536, 0.138348,3.14145,-0.138348, 0.157626,3.14145,-0.115787, + 0.157626,3.14145,-0.115787, 0.250127,3.1176,-0.183734, 0.219536,3.1176,-0.219536, + 0.183734,3.1176,-0.250127, 0.115787,3.14145,-0.157626, 0.138348,3.14145,-0.138348, + 0.138348,3.14145,-0.138348, 0.219536,3.1176,-0.219536, 0.183734,3.1176,-0.250127, + 0.143301,3.1176,-0.274928, 0.090306,3.14145,-0.173255, 0.115787,3.14145,-0.157626, + 0.115787,3.14145,-0.157626, 0.183734,3.1176,-0.250127, 0.143301,3.1176,-0.274928, + 0.098814,3.1176,-0.29336, 0.062272,3.14145,-0.18487, 0.090306,3.14145,-0.173255, + 0.090306,3.14145,-0.173255, 0.143301,3.1176,-0.274928, 0.098814,3.1176,-0.29336, + 0.050855,3.1176,-0.304843, 0.032048,3.14145,-0.192107, 0.062272,3.14145,-0.18487, + 0.062272,3.14145,-0.18487, 0.098814,3.1176,-0.29336, 0.050855,3.1176,-0.304843, + 0,3.1176,-0.3088, 0,3.14145,-0.1946, 0.032048,3.14145,-0.192107, + 0.032048,3.14145,-0.192107, 0.050855,3.1176,-0.304843, 0,3.1176,-0.3088, + 0.35361,3.08115,-0.058988, 0.304843,3.1176,-0.050855, 0.3088,3.1176,0, + 0.3088,3.1176,0, 0.3582,3.08115,0, 0.35361,3.08115,-0.058988, + 0.340289,3.08115,-0.114619, 0.29336,3.1176,-0.098814, 0.304843,3.1176,-0.050855, + 0.304843,3.1176,-0.050855, 0.35361,3.08115,-0.058988, 0.340289,3.08115,-0.114619, + 0.318907,3.08115,-0.166221, 0.274928,3.1176,-0.143301, 0.29336,3.1176,-0.098814, + 0.29336,3.1176,-0.098814, 0.340289,3.08115,-0.114619, 0.318907,3.08115,-0.166221, + 0.290138,3.08115,-0.213123, 0.250127,3.1176,-0.183734, 0.274928,3.1176,-0.143301, + 0.274928,3.1176,-0.143301, 0.318907,3.08115,-0.166221, 0.290138,3.08115,-0.213123, + 0.254653,3.08115,-0.254653, 0.219536,3.1176,-0.219536, 0.250127,3.1176,-0.183734, + 0.250127,3.1176,-0.183734, 0.290138,3.08115,-0.213123, 0.254653,3.08115,-0.254653, + 0.213123,3.08115,-0.290138, 0.183734,3.1176,-0.250127, 0.219536,3.1176,-0.219536, + 0.219536,3.1176,-0.219536, 0.254653,3.08115,-0.254653, 0.213123,3.08115,-0.290138, + 0.166221,3.08115,-0.318907, 0.143301,3.1176,-0.274928, 0.183734,3.1176,-0.250127, + 0.183734,3.1176,-0.250127, 0.213123,3.08115,-0.290138, 0.166221,3.08115,-0.318907, + 0.114619,3.08115,-0.340289, 0.098814,3.1176,-0.29336, 0.143301,3.1176,-0.274928, + 0.143301,3.1176,-0.274928, 0.166221,3.08115,-0.318907, 0.114619,3.08115,-0.340289, + 0.058988,3.08115,-0.35361, 0.050855,3.1176,-0.304843, 0.098814,3.1176,-0.29336, + 0.098814,3.1176,-0.29336, 0.114619,3.08115,-0.340289, 0.058988,3.08115,-0.35361, + 0,3.08115,-0.3582, 0,3.1176,-0.3088, 0.050855,3.1176,-0.304843, + 0.050855,3.1176,-0.304843, 0.058988,3.08115,-0.35361, 0,3.08115,-0.3582, + 0.353807,3.0348,-0.059016, 0.35361,3.08115,-0.058988, 0.3582,3.08115,0, + 0.3582,3.08115,0, 0.3584,3.0348,0, 0.353807,3.0348,-0.059016, + 0.340477,3.0348,-0.114676, 0.340289,3.08115,-0.114619, 0.35361,3.08115,-0.058988, + 0.35361,3.08115,-0.058988, 0.353807,3.0348,-0.059016, 0.340477,3.0348,-0.114676, + 0.319082,3.0348,-0.166306, 0.318907,3.08115,-0.166221, 0.340289,3.08115,-0.114619, + 0.340289,3.08115,-0.114619, 0.340477,3.0348,-0.114676, 0.319082,3.0348,-0.166306, + 0.290295,3.0348,-0.213234, 0.290138,3.08115,-0.213123, 0.318907,3.08115,-0.166221, + 0.318907,3.08115,-0.166221, 0.319082,3.0348,-0.166306, 0.290295,3.0348,-0.213234, + 0.254788,3.0348,-0.254788, 0.254653,3.08115,-0.254653, 0.290138,3.08115,-0.213123, + 0.290138,3.08115,-0.213123, 0.290295,3.0348,-0.213234, 0.254788,3.0348,-0.254788, + 0.213234,3.0348,-0.290295, 0.213123,3.08115,-0.290138, 0.254653,3.08115,-0.254653, + 0.254653,3.08115,-0.254653, 0.254788,3.0348,-0.254788, 0.213234,3.0348,-0.290295, + 0.166306,3.0348,-0.319082, 0.166221,3.08115,-0.318907, 0.213123,3.08115,-0.290138, + 0.213123,3.08115,-0.290138, 0.213234,3.0348,-0.290295, 0.166306,3.0348,-0.319082, + 0.114676,3.0348,-0.340477, 0.114619,3.08115,-0.340289, 0.166221,3.08115,-0.318907, + 0.166221,3.08115,-0.318907, 0.166306,3.0348,-0.319082, 0.114676,3.0348,-0.340477, + 0.059016,3.0348,-0.353807, 0.058988,3.08115,-0.35361, 0.114619,3.08115,-0.340289, + 0.114619,3.08115,-0.340289, 0.114676,3.0348,-0.340477, 0.059016,3.0348,-0.353807, + 0,3.0348,-0.3584, 0,3.08115,-0.3582, 0.058988,3.08115,-0.35361, + 0.058988,3.08115,-0.35361, 0.059016,3.0348,-0.353807, 0,3.0348,-0.3584, + 0.320834,2.98125,-0.053508, 0.353807,3.0348,-0.059016, 0.3584,3.0348,0, + 0.3584,3.0348,0, 0.325,2.98125,0, 0.320834,2.98125,-0.053508, + 0.308744,2.98125,-0.103976, 0.340477,3.0348,-0.114676, 0.353807,3.0348,-0.059016, + 0.353807,3.0348,-0.059016, 0.320834,2.98125,-0.053508, 0.308744,2.98125,-0.103976, + 0.28934,2.98125,-0.150793, 0.319082,3.0348,-0.166306, 0.340477,3.0348,-0.114676, + 0.340477,3.0348,-0.114676, 0.308744,2.98125,-0.103976, 0.28934,2.98125,-0.150793, + 0.263232,2.98125,-0.193348, 0.290295,3.0348,-0.213234, 0.319082,3.0348,-0.166306, + 0.319082,3.0348,-0.166306, 0.28934,2.98125,-0.150793, 0.263232,2.98125,-0.193348, + 0.231031,2.98125,-0.231031, 0.254788,3.0348,-0.254788, 0.290295,3.0348,-0.213234, + 0.290295,3.0348,-0.213234, 0.263232,2.98125,-0.193348, 0.231031,2.98125,-0.231031, + 0.193348,2.98125,-0.263232, 0.213234,3.0348,-0.290295, 0.254788,3.0348,-0.254788, + 0.254788,3.0348,-0.254788, 0.231031,2.98125,-0.231031, 0.193348,2.98125,-0.263232, + 0.150793,2.98125,-0.28934, 0.166306,3.0348,-0.319082, 0.213234,3.0348,-0.290295, + 0.213234,3.0348,-0.290295, 0.193348,2.98125,-0.263232, 0.150793,2.98125,-0.28934, + 0.103976,2.98125,-0.308744, 0.114676,3.0348,-0.340477, 0.166306,3.0348,-0.319082, + 0.166306,3.0348,-0.319082, 0.150793,2.98125,-0.28934, 0.103976,2.98125,-0.308744, + 0.053508,2.98125,-0.320834, 0.059016,3.0348,-0.353807, 0.114676,3.0348,-0.340477, + 0.114676,3.0348,-0.340477, 0.103976,2.98125,-0.308744, 0.053508,2.98125,-0.320834, + 0,2.98125,-0.325, 0,3.0348,-0.3584, 0.059016,3.0348,-0.353807, + 0.059016,3.0348,-0.353807, 0.053508,2.98125,-0.320834, 0,2.98125,-0.325, + 0.270092,2.9232,-0.045032, 0.320834,2.98125,-0.053508, 0.325,2.98125,0, + 0.325,2.98125,0, 0.2736,2.9232,0, 0.270092,2.9232,-0.045032, + 0.25991,2.9232,-0.087511, 0.308744,2.98125,-0.103976, 0.320834,2.98125,-0.053508, + 0.320834,2.98125,-0.053508, 0.270092,2.9232,-0.045032, 0.25991,2.9232,-0.087511, + 0.243569,2.9232,-0.12692, 0.28934,2.98125,-0.150793, 0.308744,2.98125,-0.103976, + 0.308744,2.98125,-0.103976, 0.25991,2.9232,-0.087511, 0.243569,2.9232,-0.12692, + 0.221585,2.9232,-0.162745, 0.263232,2.98125,-0.193348, 0.28934,2.98125,-0.150793, + 0.28934,2.98125,-0.150793, 0.243569,2.9232,-0.12692, 0.221585,2.9232,-0.162745, + 0.194472,2.9232,-0.194472, 0.231031,2.98125,-0.231031, 0.263232,2.98125,-0.193348, + 0.263232,2.98125,-0.193348, 0.221585,2.9232,-0.162745, 0.194472,2.9232,-0.194472, + 0.162745,2.9232,-0.221585, 0.193348,2.98125,-0.263232, 0.231031,2.98125,-0.231031, + 0.231031,2.98125,-0.231031, 0.194472,2.9232,-0.194472, 0.162745,2.9232,-0.221585, + 0.12692,2.9232,-0.243569, 0.150793,2.98125,-0.28934, 0.193348,2.98125,-0.263232, + 0.193348,2.98125,-0.263232, 0.162745,2.9232,-0.221585, 0.12692,2.9232,-0.243569, + 0.087511,2.9232,-0.25991, 0.103976,2.98125,-0.308744, 0.150793,2.98125,-0.28934, + 0.150793,2.98125,-0.28934, 0.12692,2.9232,-0.243569, 0.087511,2.9232,-0.25991, + 0.045032,2.9232,-0.270092, 0.053508,2.98125,-0.320834, 0.103976,2.98125,-0.308744, + 0.103976,2.98125,-0.308744, 0.087511,2.9232,-0.25991, 0.045032,2.9232,-0.270092, + 0,2.9232,-0.2736, 0,2.98125,-0.325, 0.053508,2.98125,-0.320834, + 0.053508,2.98125,-0.320834, 0.045032,2.9232,-0.270092, 0,2.9232,-0.2736, + 0.216979,2.86335,-0.036157, 0.270092,2.9232,-0.045032, 0.2736,2.9232,0, + 0.2736,2.9232,0, 0.2198,2.86335,0, 0.216979,2.86335,-0.036157, + 0.208794,2.86335,-0.07027, 0.25991,2.9232,-0.087511, 0.270092,2.9232,-0.045032, + 0.270092,2.9232,-0.045032, 0.216979,2.86335,-0.036157, 0.208794,2.86335,-0.07027, + 0.195658,2.86335,-0.101925, 0.243569,2.9232,-0.12692, 0.25991,2.9232,-0.087511, + 0.25991,2.9232,-0.087511, 0.208794,2.86335,-0.07027, 0.195658,2.86335,-0.101925, + 0.177989,2.86335,-0.130707, 0.221585,2.9232,-0.162745, 0.243569,2.9232,-0.12692, + 0.243569,2.9232,-0.12692, 0.195658,2.86335,-0.101925, 0.177989,2.86335,-0.130707, + 0.1562,2.86335,-0.1562, 0.194472,2.9232,-0.194472, 0.221585,2.9232,-0.162745, + 0.221585,2.9232,-0.162745, 0.177989,2.86335,-0.130707, 0.1562,2.86335,-0.1562, + 0.130707,2.86335,-0.177989, 0.162745,2.9232,-0.221585, 0.194472,2.9232,-0.194472, + 0.194472,2.9232,-0.194472, 0.1562,2.86335,-0.1562, 0.130707,2.86335,-0.177989, + 0.101925,2.86335,-0.195658, 0.12692,2.9232,-0.243569, 0.162745,2.9232,-0.221585, + 0.162745,2.9232,-0.221585, 0.130707,2.86335,-0.177989, 0.101925,2.86335,-0.195658, + 0.07027,2.86335,-0.208794, 0.087511,2.9232,-0.25991, 0.12692,2.9232,-0.243569, + 0.12692,2.9232,-0.243569, 0.101925,2.86335,-0.195658, 0.07027,2.86335,-0.208794, + 0.036157,2.86335,-0.216979, 0.045032,2.9232,-0.270092, 0.087511,2.9232,-0.25991, + 0.087511,2.9232,-0.25991, 0.07027,2.86335,-0.208794, 0.036157,2.86335,-0.216979, + 0,2.86335,-0.2198, 0,2.9232,-0.2736, 0.045032,2.9232,-0.270092, + 0.045032,2.9232,-0.270092, 0.036157,2.86335,-0.216979, 0,2.86335,-0.2198, + 0.176897,2.8044,-0.02945, 0.216979,2.86335,-0.036157, 0.2198,2.86335,0, + 0.2198,2.86335,0, 0.1792,2.8044,0, 0.176897,2.8044,-0.02945, + 0.170215,2.8044,-0.057246, 0.208794,2.86335,-0.07027, 0.216979,2.86335,-0.036157, + 0.216979,2.86335,-0.036157, 0.176897,2.8044,-0.02945, 0.170215,2.8044,-0.057246, + 0.159496,2.8044,-0.083047, 0.195658,2.86335,-0.101925, 0.208794,2.86335,-0.07027, + 0.208794,2.86335,-0.07027, 0.170215,2.8044,-0.057246, 0.159496,2.8044,-0.083047, + 0.145078,2.8044,-0.106513, 0.177989,2.86335,-0.130707, 0.195658,2.86335,-0.101925, + 0.195658,2.86335,-0.101925, 0.159496,2.8044,-0.083047, 0.145078,2.8044,-0.106513, + 0.127304,2.8044,-0.127304, 0.1562,2.86335,-0.1562, 0.177989,2.86335,-0.130707, + 0.177989,2.86335,-0.130707, 0.145078,2.8044,-0.106513, 0.127304,2.8044,-0.127304, + 0.106513,2.8044,-0.145078, 0.130707,2.86335,-0.177989, 0.1562,2.86335,-0.1562, + 0.1562,2.86335,-0.1562, 0.127304,2.8044,-0.127304, 0.106513,2.8044,-0.145078, + 0.083047,2.8044,-0.159496, 0.101925,2.86335,-0.195658, 0.130707,2.86335,-0.177989, + 0.130707,2.86335,-0.177989, 0.106513,2.8044,-0.145078, 0.083047,2.8044,-0.159496, + 0.057246,2.8044,-0.170215, 0.07027,2.86335,-0.208794, 0.101925,2.86335,-0.195658, + 0.101925,2.86335,-0.195658, 0.083047,2.8044,-0.159496, 0.057246,2.8044,-0.170215, + 0.02945,2.8044,-0.176897, 0.036157,2.86335,-0.216979, 0.07027,2.86335,-0.208794, + 0.07027,2.86335,-0.208794, 0.057246,2.8044,-0.170215, 0.02945,2.8044,-0.176897, + 0,2.8044,-0.1792, 0,2.86335,-0.2198, 0.036157,2.86335,-0.216979, + 0.036157,2.86335,-0.216979, 0.02945,2.8044,-0.176897, 0,2.8044,-0.1792, + 0.165245,2.74905,-0.02748, 0.176897,2.8044,-0.02945, 0.1792,2.8044,0, + 0.1792,2.8044,0, 0.1674,2.74905,0, 0.165245,2.74905,-0.02748, + 0.158995,2.74905,-0.053428, 0.170215,2.8044,-0.057246, 0.176897,2.8044,-0.02945, + 0.176897,2.8044,-0.02945, 0.165245,2.74905,-0.02748, 0.158995,2.74905,-0.053428, + 0.148969,2.74905,-0.077523, 0.159496,2.8044,-0.083047, 0.170215,2.8044,-0.057246, + 0.170215,2.8044,-0.057246, 0.158995,2.74905,-0.053428, 0.148969,2.74905,-0.077523, + 0.135489,2.74905,-0.099446, 0.145078,2.8044,-0.106513, 0.159496,2.8044,-0.083047, + 0.159496,2.8044,-0.083047, 0.148969,2.74905,-0.077523, 0.135489,2.74905,-0.099446, + 0.118874,2.74905,-0.118874, 0.127304,2.8044,-0.127304, 0.145078,2.8044,-0.106513, + 0.145078,2.8044,-0.106513, 0.135489,2.74905,-0.099446, 0.118874,2.74905,-0.118874, + 0.099446,2.74905,-0.135489, 0.106513,2.8044,-0.145078, 0.127304,2.8044,-0.127304, + 0.127304,2.8044,-0.127304, 0.118874,2.74905,-0.118874, 0.099446,2.74905,-0.135489, + 0.077523,2.74905,-0.148969, 0.083047,2.8044,-0.159496, 0.106513,2.8044,-0.145078, + 0.106513,2.8044,-0.145078, 0.099446,2.74905,-0.135489, 0.077523,2.74905,-0.148969, + 0.053428,2.74905,-0.158995, 0.057246,2.8044,-0.170215, 0.083047,2.8044,-0.159496, + 0.083047,2.8044,-0.159496, 0.077523,2.74905,-0.148969, 0.053428,2.74905,-0.158995, + 0.02748,2.74905,-0.165245, 0.02945,2.8044,-0.176897, 0.057246,2.8044,-0.170215, + 0.057246,2.8044,-0.170215, 0.053428,2.74905,-0.158995, 0.02748,2.74905,-0.165245, + 0,2.74905,-0.1674, 0,2.8044,-0.1792, 0.02945,2.8044,-0.176897, + 0.02945,2.8044,-0.176897, 0.02748,2.74905,-0.165245, 0,2.74905,-0.1674, + 0.197424,2.7,-0.032816, 0.165245,2.74905,-0.02748, 0.1674,2.74905,0, + 0.1674,2.74905,0, 0.2,2.7,0, 0.197424,2.7,-0.032816, + 0.189952,2.7,-0.063808, 0.158995,2.74905,-0.053428, 0.165245,2.74905,-0.02748, + 0.165245,2.74905,-0.02748, 0.197424,2.7,-0.032816, 0.189952,2.7,-0.063808, + 0.177968,2.7,-0.092592, 0.148969,2.74905,-0.077523, 0.158995,2.74905,-0.053428, + 0.158995,2.74905,-0.053428, 0.189952,2.7,-0.063808, 0.177968,2.7,-0.092592, + 0.161856,2.7,-0.118784, 0.135489,2.74905,-0.099446, 0.148969,2.74905,-0.077523, + 0.148969,2.74905,-0.077523, 0.177968,2.7,-0.092592, 0.161856,2.7,-0.118784, + 0.142,2.7,-0.142, 0.118874,2.74905,-0.118874, 0.135489,2.74905,-0.099446, + 0.135489,2.74905,-0.099446, 0.161856,2.7,-0.118784, 0.142,2.7,-0.142, + 0.118784,2.7,-0.161856, 0.099446,2.74905,-0.135489, 0.118874,2.74905,-0.118874, + 0.118874,2.74905,-0.118874, 0.142,2.7,-0.142, 0.118784,2.7,-0.161856, + 0.092592,2.7,-0.177968, 0.077523,2.74905,-0.148969, 0.099446,2.74905,-0.135489, + 0.099446,2.74905,-0.135489, 0.118784,2.7,-0.161856, 0.092592,2.7,-0.177968, + 0.063808,2.7,-0.189952, 0.053428,2.74905,-0.158995, 0.077523,2.74905,-0.148969, + 0.077523,2.74905,-0.148969, 0.092592,2.7,-0.177968, 0.063808,2.7,-0.189952, + 0.032816,2.7,-0.197424, 0.02748,2.74905,-0.165245, 0.053428,2.74905,-0.158995, + 0.053428,2.74905,-0.158995, 0.063808,2.7,-0.189952, 0.032816,2.7,-0.197424, + 0,2.7,-0.2, 0,2.74905,-0.1674, 0.02748,2.74905,-0.165245, + 0.02748,2.74905,-0.165245, 0.032816,2.7,-0.197424, 0,2.7,-0.2, + 0,3.15,0, 0,3.14145,-0.1946, -0.032048,3.14145,-0.192107, + 0,3.15,0, -0.032048,3.14145,-0.192107, -0.062272,3.14145,-0.18487, + 0,3.15,0, -0.062272,3.14145,-0.18487, -0.090306,3.14145,-0.173255, + 0,3.15,0, -0.090306,3.14145,-0.173255, -0.115787,3.14145,-0.157626, + 0,3.15,0, -0.115787,3.14145,-0.157626, -0.138348,3.14145,-0.138348, + 0,3.15,0, -0.138348,3.14145,-0.138348, -0.157626,3.14145,-0.115787, + 0,3.15,0, -0.157626,3.14145,-0.115787, -0.173255,3.14145,-0.090306, + 0,3.15,0, -0.173255,3.14145,-0.090306, -0.18487,3.14145,-0.062272, + 0,3.15,0, -0.18487,3.14145,-0.062272, -0.192107,3.14145,-0.032048, + 0,3.15,0, -0.192107,3.14145,-0.032048, -0.1946,3.14145,0, + -0.050855,3.1176,-0.304843, -0.032048,3.14145,-0.192107, 0,3.14145,-0.1946, + 0,3.14145,-0.1946, 0,3.1176,-0.3088, -0.050855,3.1176,-0.304843, + -0.098814,3.1176,-0.29336, -0.062272,3.14145,-0.18487, -0.032048,3.14145,-0.192107, + -0.032048,3.14145,-0.192107, -0.050855,3.1176,-0.304843, -0.098814,3.1176,-0.29336, + -0.143301,3.1176,-0.274928, -0.090306,3.14145,-0.173255, -0.062272,3.14145,-0.18487, + -0.062272,3.14145,-0.18487, -0.098814,3.1176,-0.29336, -0.143301,3.1176,-0.274928, + -0.183734,3.1176,-0.250127, -0.115787,3.14145,-0.157626, -0.090306,3.14145,-0.173255, + -0.090306,3.14145,-0.173255, -0.143301,3.1176,-0.274928, -0.183734,3.1176,-0.250127, + -0.219536,3.1176,-0.219536, -0.138348,3.14145,-0.138348, -0.115787,3.14145,-0.157626, + -0.115787,3.14145,-0.157626, -0.183734,3.1176,-0.250127, -0.219536,3.1176,-0.219536, + -0.250127,3.1176,-0.183734, -0.157626,3.14145,-0.115787, -0.138348,3.14145,-0.138348, + -0.138348,3.14145,-0.138348, -0.219536,3.1176,-0.219536, -0.250127,3.1176,-0.183734, + -0.274928,3.1176,-0.143301, -0.173255,3.14145,-0.090306, -0.157626,3.14145,-0.115787, + -0.157626,3.14145,-0.115787, -0.250127,3.1176,-0.183734, -0.274928,3.1176,-0.143301, + -0.29336,3.1176,-0.098814, -0.18487,3.14145,-0.062272, -0.173255,3.14145,-0.090306, + -0.173255,3.14145,-0.090306, -0.274928,3.1176,-0.143301, -0.29336,3.1176,-0.098814, + -0.304843,3.1176,-0.050855, -0.192107,3.14145,-0.032048, -0.18487,3.14145,-0.062272, + -0.18487,3.14145,-0.062272, -0.29336,3.1176,-0.098814, -0.304843,3.1176,-0.050855, + -0.3088,3.1176,0, -0.1946,3.14145,0, -0.192107,3.14145,-0.032048, + -0.192107,3.14145,-0.032048, -0.304843,3.1176,-0.050855, -0.3088,3.1176,0, + -0.058988,3.08115,-0.35361, -0.050855,3.1176,-0.304843, 0,3.1176,-0.3088, + 0,3.1176,-0.3088, 0,3.08115,-0.3582, -0.058988,3.08115,-0.35361, + -0.114619,3.08115,-0.340289, -0.098814,3.1176,-0.29336, -0.050855,3.1176,-0.304843, + -0.050855,3.1176,-0.304843, -0.058988,3.08115,-0.35361, -0.114619,3.08115,-0.340289, + -0.166221,3.08115,-0.318907, -0.143301,3.1176,-0.274928, -0.098814,3.1176,-0.29336, + -0.098814,3.1176,-0.29336, -0.114619,3.08115,-0.340289, -0.166221,3.08115,-0.318907, + -0.213123,3.08115,-0.290138, -0.183734,3.1176,-0.250127, -0.143301,3.1176,-0.274928, + -0.143301,3.1176,-0.274928, -0.166221,3.08115,-0.318907, -0.213123,3.08115,-0.290138, + -0.254653,3.08115,-0.254653, -0.219536,3.1176,-0.219536, -0.183734,3.1176,-0.250127, + -0.183734,3.1176,-0.250127, -0.213123,3.08115,-0.290138, -0.254653,3.08115,-0.254653, + -0.290138,3.08115,-0.213123, -0.250127,3.1176,-0.183734, -0.219536,3.1176,-0.219536, + -0.219536,3.1176,-0.219536, -0.254653,3.08115,-0.254653, -0.290138,3.08115,-0.213123, + -0.318907,3.08115,-0.166221, -0.274928,3.1176,-0.143301, -0.250127,3.1176,-0.183734, + -0.250127,3.1176,-0.183734, -0.290138,3.08115,-0.213123, -0.318907,3.08115,-0.166221, + -0.340289,3.08115,-0.114619, -0.29336,3.1176,-0.098814, -0.274928,3.1176,-0.143301, + -0.274928,3.1176,-0.143301, -0.318907,3.08115,-0.166221, -0.340289,3.08115,-0.114619, + -0.35361,3.08115,-0.058988, -0.304843,3.1176,-0.050855, -0.29336,3.1176,-0.098814, + -0.29336,3.1176,-0.098814, -0.340289,3.08115,-0.114619, -0.35361,3.08115,-0.058988, + -0.3582,3.08115,0, -0.3088,3.1176,0, -0.304843,3.1176,-0.050855, + -0.304843,3.1176,-0.050855, -0.35361,3.08115,-0.058988, -0.3582,3.08115,0, + -0.059016,3.0348,-0.353807, -0.058988,3.08115,-0.35361, 0,3.08115,-0.3582, + 0,3.08115,-0.3582, 0,3.0348,-0.3584, -0.059016,3.0348,-0.353807, + -0.114676,3.0348,-0.340477, -0.114619,3.08115,-0.340289, -0.058988,3.08115,-0.35361, + -0.058988,3.08115,-0.35361, -0.059016,3.0348,-0.353807, -0.114676,3.0348,-0.340477, + -0.166306,3.0348,-0.319082, -0.166221,3.08115,-0.318907, -0.114619,3.08115,-0.340289, + -0.114619,3.08115,-0.340289, -0.114676,3.0348,-0.340477, -0.166306,3.0348,-0.319082, + -0.213234,3.0348,-0.290295, -0.213123,3.08115,-0.290138, -0.166221,3.08115,-0.318907, + -0.166221,3.08115,-0.318907, -0.166306,3.0348,-0.319082, -0.213234,3.0348,-0.290295, + -0.254788,3.0348,-0.254788, -0.254653,3.08115,-0.254653, -0.213123,3.08115,-0.290138, + -0.213123,3.08115,-0.290138, -0.213234,3.0348,-0.290295, -0.254788,3.0348,-0.254788, + -0.290295,3.0348,-0.213234, -0.290138,3.08115,-0.213123, -0.254653,3.08115,-0.254653, + -0.254653,3.08115,-0.254653, -0.254788,3.0348,-0.254788, -0.290295,3.0348,-0.213234, + -0.319082,3.0348,-0.166306, -0.318907,3.08115,-0.166221, -0.290138,3.08115,-0.213123, + -0.290138,3.08115,-0.213123, -0.290295,3.0348,-0.213234, -0.319082,3.0348,-0.166306, + -0.340477,3.0348,-0.114676, -0.340289,3.08115,-0.114619, -0.318907,3.08115,-0.166221, + -0.318907,3.08115,-0.166221, -0.319082,3.0348,-0.166306, -0.340477,3.0348,-0.114676, + -0.353807,3.0348,-0.059016, -0.35361,3.08115,-0.058988, -0.340289,3.08115,-0.114619, + -0.340289,3.08115,-0.114619, -0.340477,3.0348,-0.114676, -0.353807,3.0348,-0.059016, + -0.3584,3.0348,0, -0.3582,3.08115,0, -0.35361,3.08115,-0.058988, + -0.35361,3.08115,-0.058988, -0.353807,3.0348,-0.059016, -0.3584,3.0348,0, + -0.053508,2.98125,-0.320834, -0.059016,3.0348,-0.353807, 0,3.0348,-0.3584, + 0,3.0348,-0.3584, 0,2.98125,-0.325, -0.053508,2.98125,-0.320834, + -0.103976,2.98125,-0.308744, -0.114676,3.0348,-0.340477, -0.059016,3.0348,-0.353807, + -0.059016,3.0348,-0.353807, -0.053508,2.98125,-0.320834, -0.103976,2.98125,-0.308744, + -0.150793,2.98125,-0.28934, -0.166306,3.0348,-0.319082, -0.114676,3.0348,-0.340477, + -0.114676,3.0348,-0.340477, -0.103976,2.98125,-0.308744, -0.150793,2.98125,-0.28934, + -0.193348,2.98125,-0.263232, -0.213234,3.0348,-0.290295, -0.166306,3.0348,-0.319082, + -0.166306,3.0348,-0.319082, -0.150793,2.98125,-0.28934, -0.193348,2.98125,-0.263232, + -0.231031,2.98125,-0.231031, -0.254788,3.0348,-0.254788, -0.213234,3.0348,-0.290295, + -0.213234,3.0348,-0.290295, -0.193348,2.98125,-0.263232, -0.231031,2.98125,-0.231031, + -0.263232,2.98125,-0.193348, -0.290295,3.0348,-0.213234, -0.254788,3.0348,-0.254788, + -0.254788,3.0348,-0.254788, -0.231031,2.98125,-0.231031, -0.263232,2.98125,-0.193348, + -0.28934,2.98125,-0.150793, -0.319082,3.0348,-0.166306, -0.290295,3.0348,-0.213234, + -0.290295,3.0348,-0.213234, -0.263232,2.98125,-0.193348, -0.28934,2.98125,-0.150793, + -0.308744,2.98125,-0.103976, -0.340477,3.0348,-0.114676, -0.319082,3.0348,-0.166306, + -0.319082,3.0348,-0.166306, -0.28934,2.98125,-0.150793, -0.308744,2.98125,-0.103976, + -0.320834,2.98125,-0.053508, -0.353807,3.0348,-0.059016, -0.340477,3.0348,-0.114676, + -0.340477,3.0348,-0.114676, -0.308744,2.98125,-0.103976, -0.320834,2.98125,-0.053508, + -0.325,2.98125,0, -0.3584,3.0348,0, -0.353807,3.0348,-0.059016, + -0.353807,3.0348,-0.059016, -0.320834,2.98125,-0.053508, -0.325,2.98125,0, + -0.045032,2.9232,-0.270092, -0.053508,2.98125,-0.320834, 0,2.98125,-0.325, + 0,2.98125,-0.325, 0,2.9232,-0.2736, -0.045032,2.9232,-0.270092, + -0.087511,2.9232,-0.25991, -0.103976,2.98125,-0.308744, -0.053508,2.98125,-0.320834, + -0.053508,2.98125,-0.320834, -0.045032,2.9232,-0.270092, -0.087511,2.9232,-0.25991, + -0.12692,2.9232,-0.243569, -0.150793,2.98125,-0.28934, -0.103976,2.98125,-0.308744, + -0.103976,2.98125,-0.308744, -0.087511,2.9232,-0.25991, -0.12692,2.9232,-0.243569, + -0.162745,2.9232,-0.221585, -0.193348,2.98125,-0.263232, -0.150793,2.98125,-0.28934, + -0.150793,2.98125,-0.28934, -0.12692,2.9232,-0.243569, -0.162745,2.9232,-0.221585, + -0.194472,2.9232,-0.194472, -0.231031,2.98125,-0.231031, -0.193348,2.98125,-0.263232, + -0.193348,2.98125,-0.263232, -0.162745,2.9232,-0.221585, -0.194472,2.9232,-0.194472, + -0.221585,2.9232,-0.162745, -0.263232,2.98125,-0.193348, -0.231031,2.98125,-0.231031, + -0.231031,2.98125,-0.231031, -0.194472,2.9232,-0.194472, -0.221585,2.9232,-0.162745, + -0.243569,2.9232,-0.12692, -0.28934,2.98125,-0.150793, -0.263232,2.98125,-0.193348, + -0.263232,2.98125,-0.193348, -0.221585,2.9232,-0.162745, -0.243569,2.9232,-0.12692, + -0.25991,2.9232,-0.087511, -0.308744,2.98125,-0.103976, -0.28934,2.98125,-0.150793, + -0.28934,2.98125,-0.150793, -0.243569,2.9232,-0.12692, -0.25991,2.9232,-0.087511, + -0.270092,2.9232,-0.045032, -0.320834,2.98125,-0.053508, -0.308744,2.98125,-0.103976, + -0.308744,2.98125,-0.103976, -0.25991,2.9232,-0.087511, -0.270092,2.9232,-0.045032, + -0.2736,2.9232,0, -0.325,2.98125,0, -0.320834,2.98125,-0.053508, + -0.320834,2.98125,-0.053508, -0.270092,2.9232,-0.045032, -0.2736,2.9232,0, + -0.036157,2.86335,-0.216979, -0.045032,2.9232,-0.270092, 0,2.9232,-0.2736, + 0,2.9232,-0.2736, 0,2.86335,-0.2198, -0.036157,2.86335,-0.216979, + -0.07027,2.86335,-0.208794, -0.087511,2.9232,-0.25991, -0.045032,2.9232,-0.270092, + -0.045032,2.9232,-0.270092, -0.036157,2.86335,-0.216979, -0.07027,2.86335,-0.208794, + -0.101925,2.86335,-0.195658, -0.12692,2.9232,-0.243569, -0.087511,2.9232,-0.25991, + -0.087511,2.9232,-0.25991, -0.07027,2.86335,-0.208794, -0.101925,2.86335,-0.195658, + -0.130707,2.86335,-0.177989, -0.162745,2.9232,-0.221585, -0.12692,2.9232,-0.243569, + -0.12692,2.9232,-0.243569, -0.101925,2.86335,-0.195658, -0.130707,2.86335,-0.177989, + -0.1562,2.86335,-0.1562, -0.194472,2.9232,-0.194472, -0.162745,2.9232,-0.221585, + -0.162745,2.9232,-0.221585, -0.130707,2.86335,-0.177989, -0.1562,2.86335,-0.1562, + -0.177989,2.86335,-0.130707, -0.221585,2.9232,-0.162745, -0.194472,2.9232,-0.194472, + -0.194472,2.9232,-0.194472, -0.1562,2.86335,-0.1562, -0.177989,2.86335,-0.130707, + -0.195658,2.86335,-0.101925, -0.243569,2.9232,-0.12692, -0.221585,2.9232,-0.162745, + -0.221585,2.9232,-0.162745, -0.177989,2.86335,-0.130707, -0.195658,2.86335,-0.101925, + -0.208794,2.86335,-0.07027, -0.25991,2.9232,-0.087511, -0.243569,2.9232,-0.12692, + -0.243569,2.9232,-0.12692, -0.195658,2.86335,-0.101925, -0.208794,2.86335,-0.07027, + -0.216979,2.86335,-0.036157, -0.270092,2.9232,-0.045032, -0.25991,2.9232,-0.087511, + -0.25991,2.9232,-0.087511, -0.208794,2.86335,-0.07027, -0.216979,2.86335,-0.036157, + -0.2198,2.86335,0, -0.2736,2.9232,0, -0.270092,2.9232,-0.045032, + -0.270092,2.9232,-0.045032, -0.216979,2.86335,-0.036157, -0.2198,2.86335,0, + -0.02945,2.8044,-0.176897, -0.036157,2.86335,-0.216979, 0,2.86335,-0.2198, + 0,2.86335,-0.2198, 0,2.8044,-0.1792, -0.02945,2.8044,-0.176897, + -0.057246,2.8044,-0.170215, -0.07027,2.86335,-0.208794, -0.036157,2.86335,-0.216979, + -0.036157,2.86335,-0.216979, -0.02945,2.8044,-0.176897, -0.057246,2.8044,-0.170215, + -0.083047,2.8044,-0.159496, -0.101925,2.86335,-0.195658, -0.07027,2.86335,-0.208794, + -0.07027,2.86335,-0.208794, -0.057246,2.8044,-0.170215, -0.083047,2.8044,-0.159496, + -0.106513,2.8044,-0.145078, -0.130707,2.86335,-0.177989, -0.101925,2.86335,-0.195658, + -0.101925,2.86335,-0.195658, -0.083047,2.8044,-0.159496, -0.106513,2.8044,-0.145078, + -0.127304,2.8044,-0.127304, -0.1562,2.86335,-0.1562, -0.130707,2.86335,-0.177989, + -0.130707,2.86335,-0.177989, -0.106513,2.8044,-0.145078, -0.127304,2.8044,-0.127304, + -0.145078,2.8044,-0.106513, -0.177989,2.86335,-0.130707, -0.1562,2.86335,-0.1562, + -0.1562,2.86335,-0.1562, -0.127304,2.8044,-0.127304, -0.145078,2.8044,-0.106513, + -0.159496,2.8044,-0.083047, -0.195658,2.86335,-0.101925, -0.177989,2.86335,-0.130707, + -0.177989,2.86335,-0.130707, -0.145078,2.8044,-0.106513, -0.159496,2.8044,-0.083047, + -0.170215,2.8044,-0.057246, -0.208794,2.86335,-0.07027, -0.195658,2.86335,-0.101925, + -0.195658,2.86335,-0.101925, -0.159496,2.8044,-0.083047, -0.170215,2.8044,-0.057246, + -0.176897,2.8044,-0.02945, -0.216979,2.86335,-0.036157, -0.208794,2.86335,-0.07027, + -0.208794,2.86335,-0.07027, -0.170215,2.8044,-0.057246, -0.176897,2.8044,-0.02945, + -0.1792,2.8044,0, -0.2198,2.86335,0, -0.216979,2.86335,-0.036157, + -0.216979,2.86335,-0.036157, -0.176897,2.8044,-0.02945, -0.1792,2.8044,0, + -0.02748,2.74905,-0.165245, -0.02945,2.8044,-0.176897, 0,2.8044,-0.1792, + 0,2.8044,-0.1792, 0,2.74905,-0.1674, -0.02748,2.74905,-0.165245, + -0.053428,2.74905,-0.158995, -0.057246,2.8044,-0.170215, -0.02945,2.8044,-0.176897, + -0.02945,2.8044,-0.176897, -0.02748,2.74905,-0.165245, -0.053428,2.74905,-0.158995, + -0.077523,2.74905,-0.148969, -0.083047,2.8044,-0.159496, -0.057246,2.8044,-0.170215, + -0.057246,2.8044,-0.170215, -0.053428,2.74905,-0.158995, -0.077523,2.74905,-0.148969, + -0.099446,2.74905,-0.135489, -0.106513,2.8044,-0.145078, -0.083047,2.8044,-0.159496, + -0.083047,2.8044,-0.159496, -0.077523,2.74905,-0.148969, -0.099446,2.74905,-0.135489, + -0.118874,2.74905,-0.118874, -0.127304,2.8044,-0.127304, -0.106513,2.8044,-0.145078, + -0.106513,2.8044,-0.145078, -0.099446,2.74905,-0.135489, -0.118874,2.74905,-0.118874, + -0.135489,2.74905,-0.099446, -0.145078,2.8044,-0.106513, -0.127304,2.8044,-0.127304, + -0.127304,2.8044,-0.127304, -0.118874,2.74905,-0.118874, -0.135489,2.74905,-0.099446, + -0.148969,2.74905,-0.077523, -0.159496,2.8044,-0.083047, -0.145078,2.8044,-0.106513, + -0.145078,2.8044,-0.106513, -0.135489,2.74905,-0.099446, -0.148969,2.74905,-0.077523, + -0.158995,2.74905,-0.053428, -0.170215,2.8044,-0.057246, -0.159496,2.8044,-0.083047, + -0.159496,2.8044,-0.083047, -0.148969,2.74905,-0.077523, -0.158995,2.74905,-0.053428, + -0.165245,2.74905,-0.02748, -0.176897,2.8044,-0.02945, -0.170215,2.8044,-0.057246, + -0.170215,2.8044,-0.057246, -0.158995,2.74905,-0.053428, -0.165245,2.74905,-0.02748, + -0.1674,2.74905,0, -0.1792,2.8044,0, -0.176897,2.8044,-0.02945, + -0.176897,2.8044,-0.02945, -0.165245,2.74905,-0.02748, -0.1674,2.74905,0, + -0.032816,2.7,-0.197424, -0.02748,2.74905,-0.165245, 0,2.74905,-0.1674, + 0,2.74905,-0.1674, 0,2.7,-0.2, -0.032816,2.7,-0.197424, + -0.063808,2.7,-0.189952, -0.053428,2.74905,-0.158995, -0.02748,2.74905,-0.165245, + -0.02748,2.74905,-0.165245, -0.032816,2.7,-0.197424, -0.063808,2.7,-0.189952, + -0.092592,2.7,-0.177968, -0.077523,2.74905,-0.148969, -0.053428,2.74905,-0.158995, + -0.053428,2.74905,-0.158995, -0.063808,2.7,-0.189952, -0.092592,2.7,-0.177968, + -0.118784,2.7,-0.161856, -0.099446,2.74905,-0.135489, -0.077523,2.74905,-0.148969, + -0.077523,2.74905,-0.148969, -0.092592,2.7,-0.177968, -0.118784,2.7,-0.161856, + -0.142,2.7,-0.142, -0.118874,2.74905,-0.118874, -0.099446,2.74905,-0.135489, + -0.099446,2.74905,-0.135489, -0.118784,2.7,-0.161856, -0.142,2.7,-0.142, + -0.161856,2.7,-0.118784, -0.135489,2.74905,-0.099446, -0.118874,2.74905,-0.118874, + -0.118874,2.74905,-0.118874, -0.142,2.7,-0.142, -0.161856,2.7,-0.118784, + -0.177968,2.7,-0.092592, -0.148969,2.74905,-0.077523, -0.135489,2.74905,-0.099446, + -0.135489,2.74905,-0.099446, -0.161856,2.7,-0.118784, -0.177968,2.7,-0.092592, + -0.189952,2.7,-0.063808, -0.158995,2.74905,-0.053428, -0.148969,2.74905,-0.077523, + -0.148969,2.74905,-0.077523, -0.177968,2.7,-0.092592, -0.189952,2.7,-0.063808, + -0.197424,2.7,-0.032816, -0.165245,2.74905,-0.02748, -0.158995,2.74905,-0.053428, + -0.158995,2.74905,-0.053428, -0.189952,2.7,-0.063808, -0.197424,2.7,-0.032816, + -0.2,2.7,0, -0.1674,2.74905,0, -0.165245,2.74905,-0.02748, + -0.165245,2.74905,-0.02748, -0.197424,2.7,-0.032816, -0.2,2.7,0, + 0,3.15,0, -0.1946,3.14145,0, -0.192107,3.14145,0.032048, + 0,3.15,0, -0.192107,3.14145,0.032048, -0.18487,3.14145,0.062272, + 0,3.15,0, -0.18487,3.14145,0.062272, -0.173255,3.14145,0.090306, + 0,3.15,0, -0.173255,3.14145,0.090306, -0.157626,3.14145,0.115787, + 0,3.15,0, -0.157626,3.14145,0.115787, -0.138348,3.14145,0.138348, + 0,3.15,0, -0.138348,3.14145,0.138348, -0.115787,3.14145,0.157626, + 0,3.15,0, -0.115787,3.14145,0.157626, -0.090306,3.14145,0.173255, + 0,3.15,0, -0.090306,3.14145,0.173255, -0.062272,3.14145,0.18487, + 0,3.15,0, -0.062272,3.14145,0.18487, -0.032048,3.14145,0.192107, + 0,3.15,0, -0.032048,3.14145,0.192107, 0,3.14145,0.1946, + -0.304843,3.1176,0.050855, -0.192107,3.14145,0.032048, -0.1946,3.14145,0, + -0.1946,3.14145,0, -0.3088,3.1176,0, -0.304843,3.1176,0.050855, + -0.29336,3.1176,0.098814, -0.18487,3.14145,0.062272, -0.192107,3.14145,0.032048, + -0.192107,3.14145,0.032048, -0.304843,3.1176,0.050855, -0.29336,3.1176,0.098814, + -0.274928,3.1176,0.143301, -0.173255,3.14145,0.090306, -0.18487,3.14145,0.062272, + -0.18487,3.14145,0.062272, -0.29336,3.1176,0.098814, -0.274928,3.1176,0.143301, + -0.250127,3.1176,0.183734, -0.157626,3.14145,0.115787, -0.173255,3.14145,0.090306, + -0.173255,3.14145,0.090306, -0.274928,3.1176,0.143301, -0.250127,3.1176,0.183734, + -0.219536,3.1176,0.219536, -0.138348,3.14145,0.138348, -0.157626,3.14145,0.115787, + -0.157626,3.14145,0.115787, -0.250127,3.1176,0.183734, -0.219536,3.1176,0.219536, + -0.183734,3.1176,0.250127, -0.115787,3.14145,0.157626, -0.138348,3.14145,0.138348, + -0.138348,3.14145,0.138348, -0.219536,3.1176,0.219536, -0.183734,3.1176,0.250127, + -0.143301,3.1176,0.274928, -0.090306,3.14145,0.173255, -0.115787,3.14145,0.157626, + -0.115787,3.14145,0.157626, -0.183734,3.1176,0.250127, -0.143301,3.1176,0.274928, + -0.098814,3.1176,0.29336, -0.062272,3.14145,0.18487, -0.090306,3.14145,0.173255, + -0.090306,3.14145,0.173255, -0.143301,3.1176,0.274928, -0.098814,3.1176,0.29336, + -0.050855,3.1176,0.304843, -0.032048,3.14145,0.192107, -0.062272,3.14145,0.18487, + -0.062272,3.14145,0.18487, -0.098814,3.1176,0.29336, -0.050855,3.1176,0.304843, + 0,3.1176,0.3088, 0,3.14145,0.1946, -0.032048,3.14145,0.192107, + -0.032048,3.14145,0.192107, -0.050855,3.1176,0.304843, 0,3.1176,0.3088, + -0.35361,3.08115,0.058988, -0.304843,3.1176,0.050855, -0.3088,3.1176,0, + -0.3088,3.1176,0, -0.3582,3.08115,0, -0.35361,3.08115,0.058988, + -0.340289,3.08115,0.114619, -0.29336,3.1176,0.098814, -0.304843,3.1176,0.050855, + -0.304843,3.1176,0.050855, -0.35361,3.08115,0.058988, -0.340289,3.08115,0.114619, + -0.318907,3.08115,0.166221, -0.274928,3.1176,0.143301, -0.29336,3.1176,0.098814, + -0.29336,3.1176,0.098814, -0.340289,3.08115,0.114619, -0.318907,3.08115,0.166221, + -0.290138,3.08115,0.213123, -0.250127,3.1176,0.183734, -0.274928,3.1176,0.143301, + -0.274928,3.1176,0.143301, -0.318907,3.08115,0.166221, -0.290138,3.08115,0.213123, + -0.254653,3.08115,0.254653, -0.219536,3.1176,0.219536, -0.250127,3.1176,0.183734, + -0.250127,3.1176,0.183734, -0.290138,3.08115,0.213123, -0.254653,3.08115,0.254653, + -0.213123,3.08115,0.290138, -0.183734,3.1176,0.250127, -0.219536,3.1176,0.219536, + -0.219536,3.1176,0.219536, -0.254653,3.08115,0.254653, -0.213123,3.08115,0.290138, + -0.166221,3.08115,0.318907, -0.143301,3.1176,0.274928, -0.183734,3.1176,0.250127, + -0.183734,3.1176,0.250127, -0.213123,3.08115,0.290138, -0.166221,3.08115,0.318907, + -0.114619,3.08115,0.340289, -0.098814,3.1176,0.29336, -0.143301,3.1176,0.274928, + -0.143301,3.1176,0.274928, -0.166221,3.08115,0.318907, -0.114619,3.08115,0.340289, + -0.058988,3.08115,0.35361, -0.050855,3.1176,0.304843, -0.098814,3.1176,0.29336, + -0.098814,3.1176,0.29336, -0.114619,3.08115,0.340289, -0.058988,3.08115,0.35361, + 0,3.08115,0.3582, 0,3.1176,0.3088, -0.050855,3.1176,0.304843, + -0.050855,3.1176,0.304843, -0.058988,3.08115,0.35361, 0,3.08115,0.3582, + -0.353807,3.0348,0.059016, -0.35361,3.08115,0.058988, -0.3582,3.08115,0, + -0.3582,3.08115,0, -0.3584,3.0348,0, -0.353807,3.0348,0.059016, + -0.340477,3.0348,0.114676, -0.340289,3.08115,0.114619, -0.35361,3.08115,0.058988, + -0.35361,3.08115,0.058988, -0.353807,3.0348,0.059016, -0.340477,3.0348,0.114676, + -0.319082,3.0348,0.166306, -0.318907,3.08115,0.166221, -0.340289,3.08115,0.114619, + -0.340289,3.08115,0.114619, -0.340477,3.0348,0.114676, -0.319082,3.0348,0.166306, + -0.290295,3.0348,0.213234, -0.290138,3.08115,0.213123, -0.318907,3.08115,0.166221, + -0.318907,3.08115,0.166221, -0.319082,3.0348,0.166306, -0.290295,3.0348,0.213234, + -0.254788,3.0348,0.254788, -0.254653,3.08115,0.254653, -0.290138,3.08115,0.213123, + -0.290138,3.08115,0.213123, -0.290295,3.0348,0.213234, -0.254788,3.0348,0.254788, + -0.213234,3.0348,0.290295, -0.213123,3.08115,0.290138, -0.254653,3.08115,0.254653, + -0.254653,3.08115,0.254653, -0.254788,3.0348,0.254788, -0.213234,3.0348,0.290295, + -0.166306,3.0348,0.319082, -0.166221,3.08115,0.318907, -0.213123,3.08115,0.290138, + -0.213123,3.08115,0.290138, -0.213234,3.0348,0.290295, -0.166306,3.0348,0.319082, + -0.114676,3.0348,0.340477, -0.114619,3.08115,0.340289, -0.166221,3.08115,0.318907, + -0.166221,3.08115,0.318907, -0.166306,3.0348,0.319082, -0.114676,3.0348,0.340477, + -0.059016,3.0348,0.353807, -0.058988,3.08115,0.35361, -0.114619,3.08115,0.340289, + -0.114619,3.08115,0.340289, -0.114676,3.0348,0.340477, -0.059016,3.0348,0.353807, + 0,3.0348,0.3584, 0,3.08115,0.3582, -0.058988,3.08115,0.35361, + -0.058988,3.08115,0.35361, -0.059016,3.0348,0.353807, 0,3.0348,0.3584, + -0.320834,2.98125,0.053508, -0.353807,3.0348,0.059016, -0.3584,3.0348,0, + -0.3584,3.0348,0, -0.325,2.98125,0, -0.320834,2.98125,0.053508, + -0.308744,2.98125,0.103976, -0.340477,3.0348,0.114676, -0.353807,3.0348,0.059016, + -0.353807,3.0348,0.059016, -0.320834,2.98125,0.053508, -0.308744,2.98125,0.103976, + -0.28934,2.98125,0.150793, -0.319082,3.0348,0.166306, -0.340477,3.0348,0.114676, + -0.340477,3.0348,0.114676, -0.308744,2.98125,0.103976, -0.28934,2.98125,0.150793, + -0.263232,2.98125,0.193348, -0.290295,3.0348,0.213234, -0.319082,3.0348,0.166306, + -0.319082,3.0348,0.166306, -0.28934,2.98125,0.150793, -0.263232,2.98125,0.193348, + -0.231031,2.98125,0.231031, -0.254788,3.0348,0.254788, -0.290295,3.0348,0.213234, + -0.290295,3.0348,0.213234, -0.263232,2.98125,0.193348, -0.231031,2.98125,0.231031, + -0.193348,2.98125,0.263232, -0.213234,3.0348,0.290295, -0.254788,3.0348,0.254788, + -0.254788,3.0348,0.254788, -0.231031,2.98125,0.231031, -0.193348,2.98125,0.263232, + -0.150793,2.98125,0.28934, -0.166306,3.0348,0.319082, -0.213234,3.0348,0.290295, + -0.213234,3.0348,0.290295, -0.193348,2.98125,0.263232, -0.150793,2.98125,0.28934, + -0.103976,2.98125,0.308744, -0.114676,3.0348,0.340477, -0.166306,3.0348,0.319082, + -0.166306,3.0348,0.319082, -0.150793,2.98125,0.28934, -0.103976,2.98125,0.308744, + -0.053508,2.98125,0.320834, -0.059016,3.0348,0.353807, -0.114676,3.0348,0.340477, + -0.114676,3.0348,0.340477, -0.103976,2.98125,0.308744, -0.053508,2.98125,0.320834, + 0,2.98125,0.325, 0,3.0348,0.3584, -0.059016,3.0348,0.353807, + -0.059016,3.0348,0.353807, -0.053508,2.98125,0.320834, 0,2.98125,0.325, + -0.270092,2.9232,0.045032, -0.320834,2.98125,0.053508, -0.325,2.98125,0, + -0.325,2.98125,0, -0.2736,2.9232,0, -0.270092,2.9232,0.045032, + -0.25991,2.9232,0.087511, -0.308744,2.98125,0.103976, -0.320834,2.98125,0.053508, + -0.320834,2.98125,0.053508, -0.270092,2.9232,0.045032, -0.25991,2.9232,0.087511, + -0.243569,2.9232,0.12692, -0.28934,2.98125,0.150793, -0.308744,2.98125,0.103976, + -0.308744,2.98125,0.103976, -0.25991,2.9232,0.087511, -0.243569,2.9232,0.12692, + -0.221585,2.9232,0.162745, -0.263232,2.98125,0.193348, -0.28934,2.98125,0.150793, + -0.28934,2.98125,0.150793, -0.243569,2.9232,0.12692, -0.221585,2.9232,0.162745, + -0.194472,2.9232,0.194472, -0.231031,2.98125,0.231031, -0.263232,2.98125,0.193348, + -0.263232,2.98125,0.193348, -0.221585,2.9232,0.162745, -0.194472,2.9232,0.194472, + -0.162745,2.9232,0.221585, -0.193348,2.98125,0.263232, -0.231031,2.98125,0.231031, + -0.231031,2.98125,0.231031, -0.194472,2.9232,0.194472, -0.162745,2.9232,0.221585, + -0.12692,2.9232,0.243569, -0.150793,2.98125,0.28934, -0.193348,2.98125,0.263232, + -0.193348,2.98125,0.263232, -0.162745,2.9232,0.221585, -0.12692,2.9232,0.243569, + -0.087511,2.9232,0.25991, -0.103976,2.98125,0.308744, -0.150793,2.98125,0.28934, + -0.150793,2.98125,0.28934, -0.12692,2.9232,0.243569, -0.087511,2.9232,0.25991, + -0.045032,2.9232,0.270092, -0.053508,2.98125,0.320834, -0.103976,2.98125,0.308744, + -0.103976,2.98125,0.308744, -0.087511,2.9232,0.25991, -0.045032,2.9232,0.270092, + 0,2.9232,0.2736, 0,2.98125,0.325, -0.053508,2.98125,0.320834, + -0.053508,2.98125,0.320834, -0.045032,2.9232,0.270092, 0,2.9232,0.2736, + -0.216979,2.86335,0.036157, -0.270092,2.9232,0.045032, -0.2736,2.9232,0, + -0.2736,2.9232,0, -0.2198,2.86335,0, -0.216979,2.86335,0.036157, + -0.208794,2.86335,0.07027, -0.25991,2.9232,0.087511, -0.270092,2.9232,0.045032, + -0.270092,2.9232,0.045032, -0.216979,2.86335,0.036157, -0.208794,2.86335,0.07027, + -0.195658,2.86335,0.101925, -0.243569,2.9232,0.12692, -0.25991,2.9232,0.087511, + -0.25991,2.9232,0.087511, -0.208794,2.86335,0.07027, -0.195658,2.86335,0.101925, + -0.177989,2.86335,0.130707, -0.221585,2.9232,0.162745, -0.243569,2.9232,0.12692, + -0.243569,2.9232,0.12692, -0.195658,2.86335,0.101925, -0.177989,2.86335,0.130707, + -0.1562,2.86335,0.1562, -0.194472,2.9232,0.194472, -0.221585,2.9232,0.162745, + -0.221585,2.9232,0.162745, -0.177989,2.86335,0.130707, -0.1562,2.86335,0.1562, + -0.130707,2.86335,0.177989, -0.162745,2.9232,0.221585, -0.194472,2.9232,0.194472, + -0.194472,2.9232,0.194472, -0.1562,2.86335,0.1562, -0.130707,2.86335,0.177989, + -0.101925,2.86335,0.195658, -0.12692,2.9232,0.243569, -0.162745,2.9232,0.221585, + -0.162745,2.9232,0.221585, -0.130707,2.86335,0.177989, -0.101925,2.86335,0.195658, + -0.07027,2.86335,0.208794, -0.087511,2.9232,0.25991, -0.12692,2.9232,0.243569, + -0.12692,2.9232,0.243569, -0.101925,2.86335,0.195658, -0.07027,2.86335,0.208794, + -0.036157,2.86335,0.216979, -0.045032,2.9232,0.270092, -0.087511,2.9232,0.25991, + -0.087511,2.9232,0.25991, -0.07027,2.86335,0.208794, -0.036157,2.86335,0.216979, + 0,2.86335,0.2198, 0,2.9232,0.2736, -0.045032,2.9232,0.270092, + -0.045032,2.9232,0.270092, -0.036157,2.86335,0.216979, 0,2.86335,0.2198, + -0.176897,2.8044,0.02945, -0.216979,2.86335,0.036157, -0.2198,2.86335,0, + -0.2198,2.86335,0, -0.1792,2.8044,0, -0.176897,2.8044,0.02945, + -0.170215,2.8044,0.057246, -0.208794,2.86335,0.07027, -0.216979,2.86335,0.036157, + -0.216979,2.86335,0.036157, -0.176897,2.8044,0.02945, -0.170215,2.8044,0.057246, + -0.159496,2.8044,0.083047, -0.195658,2.86335,0.101925, -0.208794,2.86335,0.07027, + -0.208794,2.86335,0.07027, -0.170215,2.8044,0.057246, -0.159496,2.8044,0.083047, + -0.145078,2.8044,0.106513, -0.177989,2.86335,0.130707, -0.195658,2.86335,0.101925, + -0.195658,2.86335,0.101925, -0.159496,2.8044,0.083047, -0.145078,2.8044,0.106513, + -0.127304,2.8044,0.127304, -0.1562,2.86335,0.1562, -0.177989,2.86335,0.130707, + -0.177989,2.86335,0.130707, -0.145078,2.8044,0.106513, -0.127304,2.8044,0.127304, + -0.106513,2.8044,0.145078, -0.130707,2.86335,0.177989, -0.1562,2.86335,0.1562, + -0.1562,2.86335,0.1562, -0.127304,2.8044,0.127304, -0.106513,2.8044,0.145078, + -0.083047,2.8044,0.159496, -0.101925,2.86335,0.195658, -0.130707,2.86335,0.177989, + -0.130707,2.86335,0.177989, -0.106513,2.8044,0.145078, -0.083047,2.8044,0.159496, + -0.057246,2.8044,0.170215, -0.07027,2.86335,0.208794, -0.101925,2.86335,0.195658, + -0.101925,2.86335,0.195658, -0.083047,2.8044,0.159496, -0.057246,2.8044,0.170215, + -0.02945,2.8044,0.176897, -0.036157,2.86335,0.216979, -0.07027,2.86335,0.208794, + -0.07027,2.86335,0.208794, -0.057246,2.8044,0.170215, -0.02945,2.8044,0.176897, + 0,2.8044,0.1792, 0,2.86335,0.2198, -0.036157,2.86335,0.216979, + -0.036157,2.86335,0.216979, -0.02945,2.8044,0.176897, 0,2.8044,0.1792, + -0.165245,2.74905,0.02748, -0.176897,2.8044,0.02945, -0.1792,2.8044,0, + -0.1792,2.8044,0, -0.1674,2.74905,0, -0.165245,2.74905,0.02748, + -0.158995,2.74905,0.053428, -0.170215,2.8044,0.057246, -0.176897,2.8044,0.02945, + -0.176897,2.8044,0.02945, -0.165245,2.74905,0.02748, -0.158995,2.74905,0.053428, + -0.148969,2.74905,0.077523, -0.159496,2.8044,0.083047, -0.170215,2.8044,0.057246, + -0.170215,2.8044,0.057246, -0.158995,2.74905,0.053428, -0.148969,2.74905,0.077523, + -0.135489,2.74905,0.099446, -0.145078,2.8044,0.106513, -0.159496,2.8044,0.083047, + -0.159496,2.8044,0.083047, -0.148969,2.74905,0.077523, -0.135489,2.74905,0.099446, + -0.118874,2.74905,0.118874, -0.127304,2.8044,0.127304, -0.145078,2.8044,0.106513, + -0.145078,2.8044,0.106513, -0.135489,2.74905,0.099446, -0.118874,2.74905,0.118874, + -0.099446,2.74905,0.135489, -0.106513,2.8044,0.145078, -0.127304,2.8044,0.127304, + -0.127304,2.8044,0.127304, -0.118874,2.74905,0.118874, -0.099446,2.74905,0.135489, + -0.077523,2.74905,0.148969, -0.083047,2.8044,0.159496, -0.106513,2.8044,0.145078, + -0.106513,2.8044,0.145078, -0.099446,2.74905,0.135489, -0.077523,2.74905,0.148969, + -0.053428,2.74905,0.158995, -0.057246,2.8044,0.170215, -0.083047,2.8044,0.159496, + -0.083047,2.8044,0.159496, -0.077523,2.74905,0.148969, -0.053428,2.74905,0.158995, + -0.02748,2.74905,0.165245, -0.02945,2.8044,0.176897, -0.057246,2.8044,0.170215, + -0.057246,2.8044,0.170215, -0.053428,2.74905,0.158995, -0.02748,2.74905,0.165245, + 0,2.74905,0.1674, 0,2.8044,0.1792, -0.02945,2.8044,0.176897, + -0.02945,2.8044,0.176897, -0.02748,2.74905,0.165245, 0,2.74905,0.1674, + -0.197424,2.7,0.032816, -0.165245,2.74905,0.02748, -0.1674,2.74905,0, + -0.1674,2.74905,0, -0.2,2.7,0, -0.197424,2.7,0.032816, + -0.189952,2.7,0.063808, -0.158995,2.74905,0.053428, -0.165245,2.74905,0.02748, + -0.165245,2.74905,0.02748, -0.197424,2.7,0.032816, -0.189952,2.7,0.063808, + -0.177968,2.7,0.092592, -0.148969,2.74905,0.077523, -0.158995,2.74905,0.053428, + -0.158995,2.74905,0.053428, -0.189952,2.7,0.063808, -0.177968,2.7,0.092592, + -0.161856,2.7,0.118784, -0.135489,2.74905,0.099446, -0.148969,2.74905,0.077523, + -0.148969,2.74905,0.077523, -0.177968,2.7,0.092592, -0.161856,2.7,0.118784, + -0.142,2.7,0.142, -0.118874,2.74905,0.118874, -0.135489,2.74905,0.099446, + -0.135489,2.74905,0.099446, -0.161856,2.7,0.118784, -0.142,2.7,0.142, + -0.118784,2.7,0.161856, -0.099446,2.74905,0.135489, -0.118874,2.74905,0.118874, + -0.118874,2.74905,0.118874, -0.142,2.7,0.142, -0.118784,2.7,0.161856, + -0.092592,2.7,0.177968, -0.077523,2.74905,0.148969, -0.099446,2.74905,0.135489, + -0.099446,2.74905,0.135489, -0.118784,2.7,0.161856, -0.092592,2.7,0.177968, + -0.063808,2.7,0.189952, -0.053428,2.74905,0.158995, -0.077523,2.74905,0.148969, + -0.077523,2.74905,0.148969, -0.092592,2.7,0.177968, -0.063808,2.7,0.189952, + -0.032816,2.7,0.197424, -0.02748,2.74905,0.165245, -0.053428,2.74905,0.158995, + -0.053428,2.74905,0.158995, -0.063808,2.7,0.189952, -0.032816,2.7,0.197424, + 0,2.7,0.2, 0,2.74905,0.1674, -0.02748,2.74905,0.165245, + -0.02748,2.74905,0.165245, -0.032816,2.7,0.197424, 0,2.7,0.2, + 0,3.15,0, 0,3.14145,0.1946, 0.032048,3.14145,0.192107, + 0,3.15,0, 0.032048,3.14145,0.192107, 0.062272,3.14145,0.18487, + 0,3.15,0, 0.062272,3.14145,0.18487, 0.090306,3.14145,0.173255, + 0,3.15,0, 0.090306,3.14145,0.173255, 0.115787,3.14145,0.157626, + 0,3.15,0, 0.115787,3.14145,0.157626, 0.138348,3.14145,0.138348, + 0,3.15,0, 0.138348,3.14145,0.138348, 0.157626,3.14145,0.115787, + 0,3.15,0, 0.157626,3.14145,0.115787, 0.173255,3.14145,0.090306, + 0,3.15,0, 0.173255,3.14145,0.090306, 0.18487,3.14145,0.062272, + 0,3.15,0, 0.18487,3.14145,0.062272, 0.192107,3.14145,0.032048, + 0,3.15,0, 0.192107,3.14145,0.032048, 0.1946,3.14145,0, + 0.050855,3.1176,0.304843, 0.032048,3.14145,0.192107, 0,3.14145,0.1946, + 0,3.14145,0.1946, 0,3.1176,0.3088, 0.050855,3.1176,0.304843, + 0.098814,3.1176,0.29336, 0.062272,3.14145,0.18487, 0.032048,3.14145,0.192107, + 0.032048,3.14145,0.192107, 0.050855,3.1176,0.304843, 0.098814,3.1176,0.29336, + 0.143301,3.1176,0.274928, 0.090306,3.14145,0.173255, 0.062272,3.14145,0.18487, + 0.062272,3.14145,0.18487, 0.098814,3.1176,0.29336, 0.143301,3.1176,0.274928, + 0.183734,3.1176,0.250127, 0.115787,3.14145,0.157626, 0.090306,3.14145,0.173255, + 0.090306,3.14145,0.173255, 0.143301,3.1176,0.274928, 0.183734,3.1176,0.250127, + 0.219536,3.1176,0.219536, 0.138348,3.14145,0.138348, 0.115787,3.14145,0.157626, + 0.115787,3.14145,0.157626, 0.183734,3.1176,0.250127, 0.219536,3.1176,0.219536, + 0.250127,3.1176,0.183734, 0.157626,3.14145,0.115787, 0.138348,3.14145,0.138348, + 0.138348,3.14145,0.138348, 0.219536,3.1176,0.219536, 0.250127,3.1176,0.183734, + 0.274928,3.1176,0.143301, 0.173255,3.14145,0.090306, 0.157626,3.14145,0.115787, + 0.157626,3.14145,0.115787, 0.250127,3.1176,0.183734, 0.274928,3.1176,0.143301, + 0.29336,3.1176,0.098814, 0.18487,3.14145,0.062272, 0.173255,3.14145,0.090306, + 0.173255,3.14145,0.090306, 0.274928,3.1176,0.143301, 0.29336,3.1176,0.098814, + 0.304843,3.1176,0.050855, 0.192107,3.14145,0.032048, 0.18487,3.14145,0.062272, + 0.18487,3.14145,0.062272, 0.29336,3.1176,0.098814, 0.304843,3.1176,0.050855, + 0.3088,3.1176,0, 0.1946,3.14145,0, 0.192107,3.14145,0.032048, + 0.192107,3.14145,0.032048, 0.304843,3.1176,0.050855, 0.3088,3.1176,0, + 0.058988,3.08115,0.35361, 0.050855,3.1176,0.304843, 0,3.1176,0.3088, + 0,3.1176,0.3088, 0,3.08115,0.3582, 0.058988,3.08115,0.35361, + 0.114619,3.08115,0.340289, 0.098814,3.1176,0.29336, 0.050855,3.1176,0.304843, + 0.050855,3.1176,0.304843, 0.058988,3.08115,0.35361, 0.114619,3.08115,0.340289, + 0.166221,3.08115,0.318907, 0.143301,3.1176,0.274928, 0.098814,3.1176,0.29336, + 0.098814,3.1176,0.29336, 0.114619,3.08115,0.340289, 0.166221,3.08115,0.318907, + 0.213123,3.08115,0.290138, 0.183734,3.1176,0.250127, 0.143301,3.1176,0.274928, + 0.143301,3.1176,0.274928, 0.166221,3.08115,0.318907, 0.213123,3.08115,0.290138, + 0.254653,3.08115,0.254653, 0.219536,3.1176,0.219536, 0.183734,3.1176,0.250127, + 0.183734,3.1176,0.250127, 0.213123,3.08115,0.290138, 0.254653,3.08115,0.254653, + 0.290138,3.08115,0.213123, 0.250127,3.1176,0.183734, 0.219536,3.1176,0.219536, + 0.219536,3.1176,0.219536, 0.254653,3.08115,0.254653, 0.290138,3.08115,0.213123, + 0.318907,3.08115,0.166221, 0.274928,3.1176,0.143301, 0.250127,3.1176,0.183734, + 0.250127,3.1176,0.183734, 0.290138,3.08115,0.213123, 0.318907,3.08115,0.166221, + 0.340289,3.08115,0.114619, 0.29336,3.1176,0.098814, 0.274928,3.1176,0.143301, + 0.274928,3.1176,0.143301, 0.318907,3.08115,0.166221, 0.340289,3.08115,0.114619, + 0.35361,3.08115,0.058988, 0.304843,3.1176,0.050855, 0.29336,3.1176,0.098814, + 0.29336,3.1176,0.098814, 0.340289,3.08115,0.114619, 0.35361,3.08115,0.058988, + 0.3582,3.08115,0, 0.3088,3.1176,0, 0.304843,3.1176,0.050855, + 0.304843,3.1176,0.050855, 0.35361,3.08115,0.058988, 0.3582,3.08115,0, + 0.059016,3.0348,0.353807, 0.058988,3.08115,0.35361, 0,3.08115,0.3582, + 0,3.08115,0.3582, 0,3.0348,0.3584, 0.059016,3.0348,0.353807, + 0.114676,3.0348,0.340477, 0.114619,3.08115,0.340289, 0.058988,3.08115,0.35361, + 0.058988,3.08115,0.35361, 0.059016,3.0348,0.353807, 0.114676,3.0348,0.340477, + 0.166306,3.0348,0.319082, 0.166221,3.08115,0.318907, 0.114619,3.08115,0.340289, + 0.114619,3.08115,0.340289, 0.114676,3.0348,0.340477, 0.166306,3.0348,0.319082, + 0.213234,3.0348,0.290295, 0.213123,3.08115,0.290138, 0.166221,3.08115,0.318907, + 0.166221,3.08115,0.318907, 0.166306,3.0348,0.319082, 0.213234,3.0348,0.290295, + 0.254788,3.0348,0.254788, 0.254653,3.08115,0.254653, 0.213123,3.08115,0.290138, + 0.213123,3.08115,0.290138, 0.213234,3.0348,0.290295, 0.254788,3.0348,0.254788, + 0.290295,3.0348,0.213234, 0.290138,3.08115,0.213123, 0.254653,3.08115,0.254653, + 0.254653,3.08115,0.254653, 0.254788,3.0348,0.254788, 0.290295,3.0348,0.213234, + 0.319082,3.0348,0.166306, 0.318907,3.08115,0.166221, 0.290138,3.08115,0.213123, + 0.290138,3.08115,0.213123, 0.290295,3.0348,0.213234, 0.319082,3.0348,0.166306, + 0.340477,3.0348,0.114676, 0.340289,3.08115,0.114619, 0.318907,3.08115,0.166221, + 0.318907,3.08115,0.166221, 0.319082,3.0348,0.166306, 0.340477,3.0348,0.114676, + 0.353807,3.0348,0.059016, 0.35361,3.08115,0.058988, 0.340289,3.08115,0.114619, + 0.340289,3.08115,0.114619, 0.340477,3.0348,0.114676, 0.353807,3.0348,0.059016, + 0.3584,3.0348,0, 0.3582,3.08115,0, 0.35361,3.08115,0.058988, + 0.35361,3.08115,0.058988, 0.353807,3.0348,0.059016, 0.3584,3.0348,0, + 0.053508,2.98125,0.320834, 0.059016,3.0348,0.353807, 0,3.0348,0.3584, + 0,3.0348,0.3584, 0,2.98125,0.325, 0.053508,2.98125,0.320834, + 0.103976,2.98125,0.308744, 0.114676,3.0348,0.340477, 0.059016,3.0348,0.353807, + 0.059016,3.0348,0.353807, 0.053508,2.98125,0.320834, 0.103976,2.98125,0.308744, + 0.150793,2.98125,0.28934, 0.166306,3.0348,0.319082, 0.114676,3.0348,0.340477, + 0.114676,3.0348,0.340477, 0.103976,2.98125,0.308744, 0.150793,2.98125,0.28934, + 0.193348,2.98125,0.263232, 0.213234,3.0348,0.290295, 0.166306,3.0348,0.319082, + 0.166306,3.0348,0.319082, 0.150793,2.98125,0.28934, 0.193348,2.98125,0.263232, + 0.231031,2.98125,0.231031, 0.254788,3.0348,0.254788, 0.213234,3.0348,0.290295, + 0.213234,3.0348,0.290295, 0.193348,2.98125,0.263232, 0.231031,2.98125,0.231031, + 0.263232,2.98125,0.193348, 0.290295,3.0348,0.213234, 0.254788,3.0348,0.254788, + 0.254788,3.0348,0.254788, 0.231031,2.98125,0.231031, 0.263232,2.98125,0.193348, + 0.28934,2.98125,0.150793, 0.319082,3.0348,0.166306, 0.290295,3.0348,0.213234, + 0.290295,3.0348,0.213234, 0.263232,2.98125,0.193348, 0.28934,2.98125,0.150793, + 0.308744,2.98125,0.103976, 0.340477,3.0348,0.114676, 0.319082,3.0348,0.166306, + 0.319082,3.0348,0.166306, 0.28934,2.98125,0.150793, 0.308744,2.98125,0.103976, + 0.320834,2.98125,0.053508, 0.353807,3.0348,0.059016, 0.340477,3.0348,0.114676, + 0.340477,3.0348,0.114676, 0.308744,2.98125,0.103976, 0.320834,2.98125,0.053508, + 0.325,2.98125,0, 0.3584,3.0348,0, 0.353807,3.0348,0.059016, + 0.353807,3.0348,0.059016, 0.320834,2.98125,0.053508, 0.325,2.98125,0, + 0.045032,2.9232,0.270092, 0.053508,2.98125,0.320834, 0,2.98125,0.325, + 0,2.98125,0.325, 0,2.9232,0.2736, 0.045032,2.9232,0.270092, + 0.087511,2.9232,0.25991, 0.103976,2.98125,0.308744, 0.053508,2.98125,0.320834, + 0.053508,2.98125,0.320834, 0.045032,2.9232,0.270092, 0.087511,2.9232,0.25991, + 0.12692,2.9232,0.243569, 0.150793,2.98125,0.28934, 0.103976,2.98125,0.308744, + 0.103976,2.98125,0.308744, 0.087511,2.9232,0.25991, 0.12692,2.9232,0.243569, + 0.162745,2.9232,0.221585, 0.193348,2.98125,0.263232, 0.150793,2.98125,0.28934, + 0.150793,2.98125,0.28934, 0.12692,2.9232,0.243569, 0.162745,2.9232,0.221585, + 0.194472,2.9232,0.194472, 0.231031,2.98125,0.231031, 0.193348,2.98125,0.263232, + 0.193348,2.98125,0.263232, 0.162745,2.9232,0.221585, 0.194472,2.9232,0.194472, + 0.221585,2.9232,0.162745, 0.263232,2.98125,0.193348, 0.231031,2.98125,0.231031, + 0.231031,2.98125,0.231031, 0.194472,2.9232,0.194472, 0.221585,2.9232,0.162745, + 0.243569,2.9232,0.12692, 0.28934,2.98125,0.150793, 0.263232,2.98125,0.193348, + 0.263232,2.98125,0.193348, 0.221585,2.9232,0.162745, 0.243569,2.9232,0.12692, + 0.25991,2.9232,0.087511, 0.308744,2.98125,0.103976, 0.28934,2.98125,0.150793, + 0.28934,2.98125,0.150793, 0.243569,2.9232,0.12692, 0.25991,2.9232,0.087511, + 0.270092,2.9232,0.045032, 0.320834,2.98125,0.053508, 0.308744,2.98125,0.103976, + 0.308744,2.98125,0.103976, 0.25991,2.9232,0.087511, 0.270092,2.9232,0.045032, + 0.2736,2.9232,0, 0.325,2.98125,0, 0.320834,2.98125,0.053508, + 0.320834,2.98125,0.053508, 0.270092,2.9232,0.045032, 0.2736,2.9232,0, + 0.036157,2.86335,0.216979, 0.045032,2.9232,0.270092, 0,2.9232,0.2736, + 0,2.9232,0.2736, 0,2.86335,0.2198, 0.036157,2.86335,0.216979, + 0.07027,2.86335,0.208794, 0.087511,2.9232,0.25991, 0.045032,2.9232,0.270092, + 0.045032,2.9232,0.270092, 0.036157,2.86335,0.216979, 0.07027,2.86335,0.208794, + 0.101925,2.86335,0.195658, 0.12692,2.9232,0.243569, 0.087511,2.9232,0.25991, + 0.087511,2.9232,0.25991, 0.07027,2.86335,0.208794, 0.101925,2.86335,0.195658, + 0.130707,2.86335,0.177989, 0.162745,2.9232,0.221585, 0.12692,2.9232,0.243569, + 0.12692,2.9232,0.243569, 0.101925,2.86335,0.195658, 0.130707,2.86335,0.177989, + 0.1562,2.86335,0.1562, 0.194472,2.9232,0.194472, 0.162745,2.9232,0.221585, + 0.162745,2.9232,0.221585, 0.130707,2.86335,0.177989, 0.1562,2.86335,0.1562, + 0.177989,2.86335,0.130707, 0.221585,2.9232,0.162745, 0.194472,2.9232,0.194472, + 0.194472,2.9232,0.194472, 0.1562,2.86335,0.1562, 0.177989,2.86335,0.130707, + 0.195658,2.86335,0.101925, 0.243569,2.9232,0.12692, 0.221585,2.9232,0.162745, + 0.221585,2.9232,0.162745, 0.177989,2.86335,0.130707, 0.195658,2.86335,0.101925, + 0.208794,2.86335,0.07027, 0.25991,2.9232,0.087511, 0.243569,2.9232,0.12692, + 0.243569,2.9232,0.12692, 0.195658,2.86335,0.101925, 0.208794,2.86335,0.07027, + 0.216979,2.86335,0.036157, 0.270092,2.9232,0.045032, 0.25991,2.9232,0.087511, + 0.25991,2.9232,0.087511, 0.208794,2.86335,0.07027, 0.216979,2.86335,0.036157, + 0.2198,2.86335,0, 0.2736,2.9232,0, 0.270092,2.9232,0.045032, + 0.270092,2.9232,0.045032, 0.216979,2.86335,0.036157, 0.2198,2.86335,0, + 0.02945,2.8044,0.176897, 0.036157,2.86335,0.216979, 0,2.86335,0.2198, + 0,2.86335,0.2198, 0,2.8044,0.1792, 0.02945,2.8044,0.176897, + 0.057246,2.8044,0.170215, 0.07027,2.86335,0.208794, 0.036157,2.86335,0.216979, + 0.036157,2.86335,0.216979, 0.02945,2.8044,0.176897, 0.057246,2.8044,0.170215, + 0.083047,2.8044,0.159496, 0.101925,2.86335,0.195658, 0.07027,2.86335,0.208794, + 0.07027,2.86335,0.208794, 0.057246,2.8044,0.170215, 0.083047,2.8044,0.159496, + 0.106513,2.8044,0.145078, 0.130707,2.86335,0.177989, 0.101925,2.86335,0.195658, + 0.101925,2.86335,0.195658, 0.083047,2.8044,0.159496, 0.106513,2.8044,0.145078, + 0.127304,2.8044,0.127304, 0.1562,2.86335,0.1562, 0.130707,2.86335,0.177989, + 0.130707,2.86335,0.177989, 0.106513,2.8044,0.145078, 0.127304,2.8044,0.127304, + 0.145078,2.8044,0.106513, 0.177989,2.86335,0.130707, 0.1562,2.86335,0.1562, + 0.1562,2.86335,0.1562, 0.127304,2.8044,0.127304, 0.145078,2.8044,0.106513, + 0.159496,2.8044,0.083047, 0.195658,2.86335,0.101925, 0.177989,2.86335,0.130707, + 0.177989,2.86335,0.130707, 0.145078,2.8044,0.106513, 0.159496,2.8044,0.083047, + 0.170215,2.8044,0.057246, 0.208794,2.86335,0.07027, 0.195658,2.86335,0.101925, + 0.195658,2.86335,0.101925, 0.159496,2.8044,0.083047, 0.170215,2.8044,0.057246, + 0.176897,2.8044,0.02945, 0.216979,2.86335,0.036157, 0.208794,2.86335,0.07027, + 0.208794,2.86335,0.07027, 0.170215,2.8044,0.057246, 0.176897,2.8044,0.02945, + 0.1792,2.8044,0, 0.2198,2.86335,0, 0.216979,2.86335,0.036157, + 0.216979,2.86335,0.036157, 0.176897,2.8044,0.02945, 0.1792,2.8044,0, + 0.02748,2.74905,0.165245, 0.02945,2.8044,0.176897, 0,2.8044,0.1792, + 0,2.8044,0.1792, 0,2.74905,0.1674, 0.02748,2.74905,0.165245, + 0.053428,2.74905,0.158995, 0.057246,2.8044,0.170215, 0.02945,2.8044,0.176897, + 0.02945,2.8044,0.176897, 0.02748,2.74905,0.165245, 0.053428,2.74905,0.158995, + 0.077523,2.74905,0.148969, 0.083047,2.8044,0.159496, 0.057246,2.8044,0.170215, + 0.057246,2.8044,0.170215, 0.053428,2.74905,0.158995, 0.077523,2.74905,0.148969, + 0.099446,2.74905,0.135489, 0.106513,2.8044,0.145078, 0.083047,2.8044,0.159496, + 0.083047,2.8044,0.159496, 0.077523,2.74905,0.148969, 0.099446,2.74905,0.135489, + 0.118874,2.74905,0.118874, 0.127304,2.8044,0.127304, 0.106513,2.8044,0.145078, + 0.106513,2.8044,0.145078, 0.099446,2.74905,0.135489, 0.118874,2.74905,0.118874, + 0.135489,2.74905,0.099446, 0.145078,2.8044,0.106513, 0.127304,2.8044,0.127304, + 0.127304,2.8044,0.127304, 0.118874,2.74905,0.118874, 0.135489,2.74905,0.099446, + 0.148969,2.74905,0.077523, 0.159496,2.8044,0.083047, 0.145078,2.8044,0.106513, + 0.145078,2.8044,0.106513, 0.135489,2.74905,0.099446, 0.148969,2.74905,0.077523, + 0.158995,2.74905,0.053428, 0.170215,2.8044,0.057246, 0.159496,2.8044,0.083047, + 0.159496,2.8044,0.083047, 0.148969,2.74905,0.077523, 0.158995,2.74905,0.053428, + 0.165245,2.74905,0.02748, 0.176897,2.8044,0.02945, 0.170215,2.8044,0.057246, + 0.170215,2.8044,0.057246, 0.158995,2.74905,0.053428, 0.165245,2.74905,0.02748, + 0.1674,2.74905,0, 0.1792,2.8044,0, 0.176897,2.8044,0.02945, + 0.176897,2.8044,0.02945, 0.165245,2.74905,0.02748, 0.1674,2.74905,0, + 0.032816,2.7,0.197424, 0.02748,2.74905,0.165245, 0,2.74905,0.1674, + 0,2.74905,0.1674, 0,2.7,0.2, 0.032816,2.7,0.197424, + 0.063808,2.7,0.189952, 0.053428,2.74905,0.158995, 0.02748,2.74905,0.165245, + 0.02748,2.74905,0.165245, 0.032816,2.7,0.197424, 0.063808,2.7,0.189952, + 0.092592,2.7,0.177968, 0.077523,2.74905,0.148969, 0.053428,2.74905,0.158995, + 0.053428,2.74905,0.158995, 0.063808,2.7,0.189952, 0.092592,2.7,0.177968, + 0.118784,2.7,0.161856, 0.099446,2.74905,0.135489, 0.077523,2.74905,0.148969, + 0.077523,2.74905,0.148969, 0.092592,2.7,0.177968, 0.118784,2.7,0.161856, + 0.142,2.7,0.142, 0.118874,2.74905,0.118874, 0.099446,2.74905,0.135489, + 0.099446,2.74905,0.135489, 0.118784,2.7,0.161856, 0.142,2.7,0.142, + 0.161856,2.7,0.118784, 0.135489,2.74905,0.099446, 0.118874,2.74905,0.118874, + 0.118874,2.74905,0.118874, 0.142,2.7,0.142, 0.161856,2.7,0.118784, + 0.177968,2.7,0.092592, 0.148969,2.74905,0.077523, 0.135489,2.74905,0.099446, + 0.135489,2.74905,0.099446, 0.161856,2.7,0.118784, 0.177968,2.7,0.092592, + 0.189952,2.7,0.063808, 0.158995,2.74905,0.053428, 0.148969,2.74905,0.077523, + 0.148969,2.74905,0.077523, 0.177968,2.7,0.092592, 0.189952,2.7,0.063808, + 0.197424,2.7,0.032816, 0.165245,2.74905,0.02748, 0.158995,2.74905,0.053428, + 0.158995,2.74905,0.053428, 0.189952,2.7,0.063808, 0.197424,2.7,0.032816, + 0.2,2.7,0, 0.1674,2.74905,0, 0.165245,2.74905,0.02748, + 0.165245,2.74905,0.02748, 0.197424,2.7,0.032816, 0.2,2.7,0, + 0.275801,2.6592,-0.045844, 0.197424,2.7,-0.032816, 0.2,2.7,0, + 0.2,2.7,0, 0.2794,2.6592,0, 0.275801,2.6592,-0.045844, + 0.265363,2.6592,-0.08914, 0.189952,2.7,-0.063808, 0.197424,2.7,-0.032816, + 0.197424,2.7,-0.032816, 0.275801,2.6592,-0.045844, 0.265363,2.6592,-0.08914, + 0.248621,2.6592,-0.129351, 0.177968,2.7,-0.092592, 0.189952,2.7,-0.063808, + 0.189952,2.7,-0.063808, 0.265363,2.6592,-0.08914, 0.248621,2.6592,-0.129351, + 0.226113,2.6592,-0.165941, 0.161856,2.7,-0.118784, 0.177968,2.7,-0.092592, + 0.177968,2.7,-0.092592, 0.248621,2.6592,-0.129351, 0.226113,2.6592,-0.165941, + 0.198374,2.6592,-0.198374, 0.142,2.7,-0.142, 0.161856,2.7,-0.118784, + 0.161856,2.7,-0.118784, 0.226113,2.6592,-0.165941, 0.198374,2.6592,-0.198374, + 0.165941,2.6592,-0.226113, 0.118784,2.7,-0.161856, 0.142,2.7,-0.142, + 0.142,2.7,-0.142, 0.198374,2.6592,-0.198374, 0.165941,2.6592,-0.226113, + 0.129351,2.6592,-0.248621, 0.092592,2.7,-0.177968, 0.118784,2.7,-0.161856, + 0.118784,2.7,-0.161856, 0.165941,2.6592,-0.226113, 0.129351,2.6592,-0.248621, + 0.08914,2.6592,-0.265363, 0.063808,2.7,-0.189952, 0.092592,2.7,-0.177968, + 0.092592,2.7,-0.177968, 0.129351,2.6592,-0.248621, 0.08914,2.6592,-0.265363, + 0.045844,2.6592,-0.275801, 0.032816,2.7,-0.197424, 0.063808,2.7,-0.189952, + 0.063808,2.7,-0.189952, 0.08914,2.6592,-0.265363, 0.045844,2.6592,-0.275801, + 0,2.6592,-0.2794, 0,2.7,-0.2, 0.032816,2.7,-0.197424, + 0.032816,2.7,-0.197424, 0.045844,2.6592,-0.275801, 0,2.6592,-0.2794, + 0.386161,2.6256,-0.064188, 0.275801,2.6592,-0.045844, 0.2794,2.6592,0, + 0.2794,2.6592,0, 0.3912,2.6256,0, 0.386161,2.6256,-0.064188, + 0.371546,2.6256,-0.124808, 0.265363,2.6592,-0.08914, 0.275801,2.6592,-0.045844, + 0.275801,2.6592,-0.045844, 0.386161,2.6256,-0.064188, 0.371546,2.6256,-0.124808, + 0.348105,2.6256,-0.18111, 0.248621,2.6592,-0.129351, 0.265363,2.6592,-0.08914, + 0.265363,2.6592,-0.08914, 0.371546,2.6256,-0.124808, 0.348105,2.6256,-0.18111, + 0.31659,2.6256,-0.232342, 0.226113,2.6592,-0.165941, 0.248621,2.6592,-0.129351, + 0.248621,2.6592,-0.129351, 0.348105,2.6256,-0.18111, 0.31659,2.6256,-0.232342, + 0.277752,2.6256,-0.277752, 0.198374,2.6592,-0.198374, 0.226113,2.6592,-0.165941, + 0.226113,2.6592,-0.165941, 0.31659,2.6256,-0.232342, 0.277752,2.6256,-0.277752, + 0.232342,2.6256,-0.31659, 0.165941,2.6592,-0.226113, 0.198374,2.6592,-0.198374, + 0.198374,2.6592,-0.198374, 0.277752,2.6256,-0.277752, 0.232342,2.6256,-0.31659, + 0.18111,2.6256,-0.348105, 0.129351,2.6592,-0.248621, 0.165941,2.6592,-0.226113, + 0.165941,2.6592,-0.226113, 0.232342,2.6256,-0.31659, 0.18111,2.6256,-0.348105, + 0.124808,2.6256,-0.371546, 0.08914,2.6592,-0.265363, 0.129351,2.6592,-0.248621, + 0.129351,2.6592,-0.248621, 0.18111,2.6256,-0.348105, 0.124808,2.6256,-0.371546, + 0.064188,2.6256,-0.386161, 0.045844,2.6592,-0.275801, 0.08914,2.6592,-0.265363, + 0.08914,2.6592,-0.265363, 0.124808,2.6256,-0.371546, 0.064188,2.6256,-0.386161, + 0,2.6256,-0.3912, 0,2.6592,-0.2794, 0.045844,2.6592,-0.275801, + 0.045844,2.6592,-0.275801, 0.064188,2.6256,-0.386161, 0,2.6256,-0.3912, + 0.519028,2.5974,-0.086273, 0.386161,2.6256,-0.064188, 0.3912,2.6256,0, + 0.3912,2.6256,0, 0.5258,2.5974,0, 0.519028,2.5974,-0.086273, + 0.499384,2.5974,-0.167751, 0.371546,2.6256,-0.124808, 0.386161,2.6256,-0.064188, + 0.386161,2.6256,-0.064188, 0.519028,2.5974,-0.086273, 0.499384,2.5974,-0.167751, + 0.467878,2.5974,-0.243424, 0.348105,2.6256,-0.18111, 0.371546,2.6256,-0.124808, + 0.371546,2.6256,-0.124808, 0.499384,2.5974,-0.167751, 0.467878,2.5974,-0.243424, + 0.425519,2.5974,-0.312283, 0.31659,2.6256,-0.232342, 0.348105,2.6256,-0.18111, + 0.348105,2.6256,-0.18111, 0.467878,2.5974,-0.243424, 0.425519,2.5974,-0.312283, + 0.373318,2.5974,-0.373318, 0.277752,2.6256,-0.277752, 0.31659,2.6256,-0.232342, + 0.31659,2.6256,-0.232342, 0.425519,2.5974,-0.312283, 0.373318,2.5974,-0.373318, + 0.312283,2.5974,-0.425519, 0.232342,2.6256,-0.31659, 0.277752,2.6256,-0.277752, + 0.277752,2.6256,-0.277752, 0.373318,2.5974,-0.373318, 0.312283,2.5974,-0.425519, + 0.243424,2.5974,-0.467878, 0.18111,2.6256,-0.348105, 0.232342,2.6256,-0.31659, + 0.232342,2.6256,-0.31659, 0.312283,2.5974,-0.425519, 0.243424,2.5974,-0.467878, + 0.167751,2.5974,-0.499384, 0.124808,2.6256,-0.371546, 0.18111,2.6256,-0.348105, + 0.18111,2.6256,-0.348105, 0.243424,2.5974,-0.467878, 0.167751,2.5974,-0.499384, + 0.086273,2.5974,-0.519028, 0.064188,2.6256,-0.386161, 0.124808,2.6256,-0.371546, + 0.124808,2.6256,-0.371546, 0.167751,2.5974,-0.499384, 0.086273,2.5974,-0.519028, + 0,2.5974,-0.5258, 0,2.6256,-0.3912, 0.064188,2.6256,-0.386161, + 0.064188,2.6256,-0.386161, 0.086273,2.5974,-0.519028, 0,2.5974,-0.5258, + 0.664924,2.5728,-0.110524, 0.519028,2.5974,-0.086273, 0.5258,2.5974,0, + 0.5258,2.5974,0, 0.6736,2.5728,0, 0.664924,2.5728,-0.110524, + 0.639758,2.5728,-0.214905, 0.499384,2.5974,-0.167751, 0.519028,2.5974,-0.086273, + 0.519028,2.5974,-0.086273, 0.664924,2.5728,-0.110524, 0.639758,2.5728,-0.214905, + 0.599396,2.5728,-0.31185, 0.467878,2.5974,-0.243424, 0.499384,2.5974,-0.167751, + 0.499384,2.5974,-0.167751, 0.639758,2.5728,-0.214905, 0.599396,2.5728,-0.31185, + 0.545131,2.5728,-0.400065, 0.425519,2.5974,-0.312283, 0.467878,2.5974,-0.243424, + 0.467878,2.5974,-0.243424, 0.599396,2.5728,-0.31185, 0.545131,2.5728,-0.400065, + 0.478256,2.5728,-0.478256, 0.373318,2.5974,-0.373318, 0.425519,2.5974,-0.312283, + 0.425519,2.5974,-0.312283, 0.545131,2.5728,-0.400065, 0.478256,2.5728,-0.478256, + 0.400065,2.5728,-0.545131, 0.312283,2.5974,-0.425519, 0.373318,2.5974,-0.373318, + 0.373318,2.5974,-0.373318, 0.478256,2.5728,-0.478256, 0.400065,2.5728,-0.545131, + 0.31185,2.5728,-0.599396, 0.243424,2.5974,-0.467878, 0.312283,2.5974,-0.425519, + 0.312283,2.5974,-0.425519, 0.400065,2.5728,-0.545131, 0.31185,2.5728,-0.599396, + 0.214905,2.5728,-0.639758, 0.167751,2.5974,-0.499384, 0.243424,2.5974,-0.467878, + 0.243424,2.5974,-0.467878, 0.31185,2.5728,-0.599396, 0.214905,2.5728,-0.639758, + 0.110524,2.5728,-0.664924, 0.086273,2.5974,-0.519028, 0.167751,2.5974,-0.499384, + 0.167751,2.5974,-0.499384, 0.214905,2.5728,-0.639758, 0.110524,2.5728,-0.664924, + 0,2.5728,-0.6736, 0,2.5974,-0.5258, 0.086273,2.5974,-0.519028, + 0.086273,2.5974,-0.519028, 0.110524,2.5728,-0.664924, 0,2.5728,-0.6736, + 0.814374,2.55,-0.135366, 0.664924,2.5728,-0.110524, 0.6736,2.5728,0, + 0.6736,2.5728,0, 0.825,2.55,0, 0.814374,2.55,-0.135366, + 0.783552,2.55,-0.263208, 0.639758,2.5728,-0.214905, 0.664924,2.5728,-0.110524, + 0.664924,2.5728,-0.110524, 0.814374,2.55,-0.135366, 0.783552,2.55,-0.263208, + 0.734118,2.55,-0.381942, 0.599396,2.5728,-0.31185, 0.639758,2.5728,-0.214905, + 0.639758,2.5728,-0.214905, 0.783552,2.55,-0.263208, 0.734118,2.55,-0.381942, + 0.667656,2.55,-0.489984, 0.545131,2.5728,-0.400065, 0.599396,2.5728,-0.31185, + 0.599396,2.5728,-0.31185, 0.734118,2.55,-0.381942, 0.667656,2.55,-0.489984, + 0.58575,2.55,-0.58575, 0.478256,2.5728,-0.478256, 0.545131,2.5728,-0.400065, + 0.545131,2.5728,-0.400065, 0.667656,2.55,-0.489984, 0.58575,2.55,-0.58575, + 0.489984,2.55,-0.667656, 0.400065,2.5728,-0.545131, 0.478256,2.5728,-0.478256, + 0.478256,2.5728,-0.478256, 0.58575,2.55,-0.58575, 0.489984,2.55,-0.667656, + 0.381942,2.55,-0.734118, 0.31185,2.5728,-0.599396, 0.400065,2.5728,-0.545131, + 0.400065,2.5728,-0.545131, 0.489984,2.55,-0.667656, 0.381942,2.55,-0.734118, + 0.263208,2.55,-0.783552, 0.214905,2.5728,-0.639758, 0.31185,2.5728,-0.599396, + 0.31185,2.5728,-0.599396, 0.381942,2.55,-0.734118, 0.263208,2.55,-0.783552, + 0.135366,2.55,-0.814374, 0.110524,2.5728,-0.664924, 0.214905,2.5728,-0.639758, + 0.214905,2.5728,-0.639758, 0.263208,2.55,-0.783552, 0.135366,2.55,-0.814374, + 0,2.55,-0.825, 0,2.5728,-0.6736, 0.110524,2.5728,-0.664924, + 0.110524,2.5728,-0.664924, 0.135366,2.55,-0.814374, 0,2.55,-0.825, + 0.957901,2.5272,-0.159223, 0.814374,2.55,-0.135366, 0.825,2.55,0, + 0.825,2.55,0, 0.9704,2.5272,0, 0.957901,2.5272,-0.159223, + 0.921647,2.5272,-0.309596, 0.783552,2.55,-0.263208, 0.814374,2.55,-0.135366, + 0.814374,2.55,-0.135366, 0.957901,2.5272,-0.159223, 0.921647,2.5272,-0.309596, + 0.863501,2.5272,-0.449256, 0.734118,2.55,-0.381942, 0.783552,2.55,-0.263208, + 0.783552,2.55,-0.263208, 0.921647,2.5272,-0.309596, 0.863501,2.5272,-0.449256, + 0.785325,2.5272,-0.57634, 0.667656,2.55,-0.489984, 0.734118,2.55,-0.381942, + 0.734118,2.55,-0.381942, 0.863501,2.5272,-0.449256, 0.785325,2.5272,-0.57634, + 0.688984,2.5272,-0.688984, 0.58575,2.55,-0.58575, 0.667656,2.55,-0.489984, + 0.667656,2.55,-0.489984, 0.785325,2.5272,-0.57634, 0.688984,2.5272,-0.688984, + 0.57634,2.5272,-0.785325, 0.489984,2.55,-0.667656, 0.58575,2.55,-0.58575, + 0.58575,2.55,-0.58575, 0.688984,2.5272,-0.688984, 0.57634,2.5272,-0.785325, + 0.449256,2.5272,-0.863501, 0.381942,2.55,-0.734118, 0.489984,2.55,-0.667656, + 0.489984,2.55,-0.667656, 0.57634,2.5272,-0.785325, 0.449256,2.5272,-0.863501, + 0.309596,2.5272,-0.921647, 0.263208,2.55,-0.783552, 0.381942,2.55,-0.734118, + 0.381942,2.55,-0.734118, 0.449256,2.5272,-0.863501, 0.309596,2.5272,-0.921647, + 0.159223,2.5272,-0.957901, 0.135366,2.55,-0.814374, 0.263208,2.55,-0.783552, + 0.263208,2.55,-0.783552, 0.309596,2.5272,-0.921647, 0.159223,2.5272,-0.957901, + 0,2.5272,-0.9704, 0,2.55,-0.825, 0.135366,2.55,-0.814374, + 0.135366,2.55,-0.814374, 0.159223,2.5272,-0.957901, 0,2.5272,-0.9704, + 1.086029,2.5026,-0.180521, 0.957901,2.5272,-0.159223, 0.9704,2.5272,0, + 0.9704,2.5272,0, 1.1002,2.5026,0, 1.086029,2.5026,-0.180521, + 1.044926,2.5026,-0.351008, 0.921647,2.5272,-0.309596, 0.957901,2.5272,-0.159223, + 0.957901,2.5272,-0.159223, 1.086029,2.5026,-0.180521, 1.044926,2.5026,-0.351008, + 0.979002,2.5026,-0.509349, 0.863501,2.5272,-0.449256, 0.921647,2.5272,-0.309596, + 0.921647,2.5272,-0.309596, 1.044926,2.5026,-0.351008, 0.979002,2.5026,-0.509349, + 0.89037,2.5026,-0.653431, 0.785325,2.5272,-0.57634, 0.863501,2.5272,-0.449256, + 0.863501,2.5272,-0.449256, 0.979002,2.5026,-0.509349, 0.89037,2.5026,-0.653431, + 0.781142,2.5026,-0.781142, 0.688984,2.5272,-0.688984, 0.785325,2.5272,-0.57634, + 0.785325,2.5272,-0.57634, 0.89037,2.5026,-0.653431, 0.781142,2.5026,-0.781142, + 0.653431,2.5026,-0.89037, 0.57634,2.5272,-0.785325, 0.688984,2.5272,-0.688984, + 0.688984,2.5272,-0.688984, 0.781142,2.5026,-0.781142, 0.653431,2.5026,-0.89037, + 0.509349,2.5026,-0.979002, 0.449256,2.5272,-0.863501, 0.57634,2.5272,-0.785325, + 0.57634,2.5272,-0.785325, 0.653431,2.5026,-0.89037, 0.509349,2.5026,-0.979002, + 0.351008,2.5026,-1.044926, 0.309596,2.5272,-0.921647, 0.449256,2.5272,-0.863501, + 0.449256,2.5272,-0.863501, 0.509349,2.5026,-0.979002, 0.351008,2.5026,-1.044926, + 0.180521,2.5026,-1.086029, 0.159223,2.5272,-0.957901, 0.309596,2.5272,-0.921647, + 0.309596,2.5272,-0.921647, 0.351008,2.5026,-1.044926, 0.180521,2.5026,-1.086029, + 0,2.5026,-1.1002, 0,2.5272,-0.9704, 0.159223,2.5272,-0.957901, + 0.159223,2.5272,-0.957901, 0.180521,2.5026,-1.086029, 0,2.5026,-1.1002, + 1.189282,2.4744,-0.197684, 1.086029,2.5026,-0.180521, 1.1002,2.5026,0, + 1.1002,2.5026,0, 1.2048,2.4744,0, 1.189282,2.4744,-0.197684, + 1.144271,2.4744,-0.384379, 1.044926,2.5026,-0.351008, 1.086029,2.5026,-0.180521, + 1.086029,2.5026,-0.180521, 1.189282,2.4744,-0.197684, 1.144271,2.4744,-0.384379, + 1.072079,2.4744,-0.557774, 0.979002,2.5026,-0.509349, 1.044926,2.5026,-0.351008, + 1.044926,2.5026,-0.351008, 1.144271,2.4744,-0.384379, 1.072079,2.4744,-0.557774, + 0.975021,2.4744,-0.715555, 0.89037,2.5026,-0.653431, 0.979002,2.5026,-0.509349, + 0.979002,2.5026,-0.509349, 1.072079,2.4744,-0.557774, 0.975021,2.4744,-0.715555, + 0.855408,2.4744,-0.855408, 0.781142,2.5026,-0.781142, 0.89037,2.5026,-0.653431, + 0.89037,2.5026,-0.653431, 0.975021,2.4744,-0.715555, 0.855408,2.4744,-0.855408, + 0.715555,2.4744,-0.975021, 0.653431,2.5026,-0.89037, 0.781142,2.5026,-0.781142, + 0.781142,2.5026,-0.781142, 0.855408,2.4744,-0.855408, 0.715555,2.4744,-0.975021, + 0.557774,2.4744,-1.072079, 0.509349,2.5026,-0.979002, 0.653431,2.5026,-0.89037, + 0.653431,2.5026,-0.89037, 0.715555,2.4744,-0.975021, 0.557774,2.4744,-1.072079, + 0.384379,2.4744,-1.144271, 0.351008,2.5026,-1.044926, 0.509349,2.5026,-0.979002, + 0.509349,2.5026,-0.979002, 0.557774,2.4744,-1.072079, 0.384379,2.4744,-1.144271, + 0.197684,2.4744,-1.189282, 0.180521,2.5026,-1.086029, 0.351008,2.5026,-1.044926, + 0.351008,2.5026,-1.044926, 0.384379,2.4744,-1.144271, 0.197684,2.4744,-1.189282, + 0,2.4744,-1.2048, 0,2.5026,-1.1002, 0.180521,2.5026,-1.086029, + 0.180521,2.5026,-1.086029, 0.197684,2.4744,-1.189282, 0,2.4744,-1.2048, + 1.258183,2.4408,-0.209136, 1.189282,2.4744,-0.197684, 1.2048,2.4744,0, + 1.2048,2.4744,0, 1.2746,2.4408,0, 1.258183,2.4408,-0.209136, + 1.210564,2.4408,-0.406648, 1.144271,2.4744,-0.384379, 1.189282,2.4744,-0.197684, + 1.189282,2.4744,-0.197684, 1.258183,2.4408,-0.209136, 1.210564,2.4408,-0.406648, + 1.13419,2.4408,-0.590089, 1.072079,2.4744,-0.557774, 1.144271,2.4744,-0.384379, + 1.144271,2.4744,-0.384379, 1.210564,2.4408,-0.406648, 1.13419,2.4408,-0.590089, + 1.031508,2.4408,-0.75701, 0.975021,2.4744,-0.715555, 1.072079,2.4744,-0.557774, + 1.072079,2.4744,-0.557774, 1.13419,2.4408,-0.590089, 1.031508,2.4408,-0.75701, + 0.904966,2.4408,-0.904966, 0.855408,2.4744,-0.855408, 0.975021,2.4744,-0.715555, + 0.975021,2.4744,-0.715555, 1.031508,2.4408,-0.75701, 0.904966,2.4408,-0.904966, + 0.75701,2.4408,-1.031508, 0.715555,2.4744,-0.975021, 0.855408,2.4744,-0.855408, + 0.855408,2.4744,-0.855408, 0.904966,2.4408,-0.904966, 0.75701,2.4408,-1.031508, + 0.590089,2.4408,-1.13419, 0.557774,2.4744,-1.072079, 0.715555,2.4744,-0.975021, + 0.715555,2.4744,-0.975021, 0.75701,2.4408,-1.031508, 0.590089,2.4408,-1.13419, + 0.406648,2.4408,-1.210564, 0.384379,2.4744,-1.144271, 0.557774,2.4744,-1.072079, + 0.557774,2.4744,-1.072079, 0.590089,2.4408,-1.13419, 0.406648,2.4408,-1.210564, + 0.209136,2.4408,-1.258183, 0.197684,2.4744,-1.189282, 0.384379,2.4744,-1.144271, + 0.384379,2.4744,-1.144271, 0.406648,2.4408,-1.210564, 0.209136,2.4408,-1.258183, + 0,2.4408,-1.2746, 0,2.4744,-1.2048, 0.197684,2.4744,-1.189282, + 0.197684,2.4744,-1.189282, 0.209136,2.4408,-1.258183, 0,2.4408,-1.2746, + 1.283256,2.4,-0.213304, 1.258183,2.4408,-0.209136, 1.2746,2.4408,0, + 1.2746,2.4408,0, 1.3,2.4,0, 1.283256,2.4,-0.213304, + 1.234688,2.4,-0.414752, 1.210564,2.4408,-0.406648, 1.258183,2.4408,-0.209136, + 1.258183,2.4408,-0.209136, 1.283256,2.4,-0.213304, 1.234688,2.4,-0.414752, + 1.156792,2.4,-0.601848, 1.13419,2.4408,-0.590089, 1.210564,2.4408,-0.406648, + 1.210564,2.4408,-0.406648, 1.234688,2.4,-0.414752, 1.156792,2.4,-0.601848, + 1.052064,2.4,-0.772096, 1.031508,2.4408,-0.75701, 1.13419,2.4408,-0.590089, + 1.13419,2.4408,-0.590089, 1.156792,2.4,-0.601848, 1.052064,2.4,-0.772096, + 0.923,2.4,-0.923, 0.904966,2.4408,-0.904966, 1.031508,2.4408,-0.75701, + 1.031508,2.4408,-0.75701, 1.052064,2.4,-0.772096, 0.923,2.4,-0.923, + 0.772096,2.4,-1.052064, 0.75701,2.4408,-1.031508, 0.904966,2.4408,-0.904966, + 0.904966,2.4408,-0.904966, 0.923,2.4,-0.923, 0.772096,2.4,-1.052064, + 0.601848,2.4,-1.156792, 0.590089,2.4408,-1.13419, 0.75701,2.4408,-1.031508, + 0.75701,2.4408,-1.031508, 0.772096,2.4,-1.052064, 0.601848,2.4,-1.156792, + 0.414752,2.4,-1.234688, 0.406648,2.4408,-1.210564, 0.590089,2.4408,-1.13419, + 0.590089,2.4408,-1.13419, 0.601848,2.4,-1.156792, 0.414752,2.4,-1.234688, + 0.213304,2.4,-1.283256, 0.209136,2.4408,-1.258183, 0.406648,2.4408,-1.210564, + 0.406648,2.4408,-1.210564, 0.414752,2.4,-1.234688, 0.213304,2.4,-1.283256, + 0,2.4,-1.3, 0,2.4408,-1.2746, 0.209136,2.4408,-1.258183, + 0.209136,2.4408,-1.258183, 0.213304,2.4,-1.283256, 0,2.4,-1.3, + -0.045844,2.6592,-0.275801, -0.032816,2.7,-0.197424, 0,2.7,-0.2, + 0,2.7,-0.2, 0,2.6592,-0.2794, -0.045844,2.6592,-0.275801, + -0.08914,2.6592,-0.265363, -0.063808,2.7,-0.189952, -0.032816,2.7,-0.197424, + -0.032816,2.7,-0.197424, -0.045844,2.6592,-0.275801, -0.08914,2.6592,-0.265363, + -0.129351,2.6592,-0.248621, -0.092592,2.7,-0.177968, -0.063808,2.7,-0.189952, + -0.063808,2.7,-0.189952, -0.08914,2.6592,-0.265363, -0.129351,2.6592,-0.248621, + -0.165941,2.6592,-0.226113, -0.118784,2.7,-0.161856, -0.092592,2.7,-0.177968, + -0.092592,2.7,-0.177968, -0.129351,2.6592,-0.248621, -0.165941,2.6592,-0.226113, + -0.198374,2.6592,-0.198374, -0.142,2.7,-0.142, -0.118784,2.7,-0.161856, + -0.118784,2.7,-0.161856, -0.165941,2.6592,-0.226113, -0.198374,2.6592,-0.198374, + -0.226113,2.6592,-0.165941, -0.161856,2.7,-0.118784, -0.142,2.7,-0.142, + -0.142,2.7,-0.142, -0.198374,2.6592,-0.198374, -0.226113,2.6592,-0.165941, + -0.248621,2.6592,-0.129351, -0.177968,2.7,-0.092592, -0.161856,2.7,-0.118784, + -0.161856,2.7,-0.118784, -0.226113,2.6592,-0.165941, -0.248621,2.6592,-0.129351, + -0.265363,2.6592,-0.08914, -0.189952,2.7,-0.063808, -0.177968,2.7,-0.092592, + -0.177968,2.7,-0.092592, -0.248621,2.6592,-0.129351, -0.265363,2.6592,-0.08914, + -0.275801,2.6592,-0.045844, -0.197424,2.7,-0.032816, -0.189952,2.7,-0.063808, + -0.189952,2.7,-0.063808, -0.265363,2.6592,-0.08914, -0.275801,2.6592,-0.045844, + -0.2794,2.6592,0, -0.2,2.7,0, -0.197424,2.7,-0.032816, + -0.197424,2.7,-0.032816, -0.275801,2.6592,-0.045844, -0.2794,2.6592,0, + -0.064188,2.6256,-0.386161, -0.045844,2.6592,-0.275801, 0,2.6592,-0.2794, + 0,2.6592,-0.2794, 0,2.6256,-0.3912, -0.064188,2.6256,-0.386161, + -0.124808,2.6256,-0.371546, -0.08914,2.6592,-0.265363, -0.045844,2.6592,-0.275801, + -0.045844,2.6592,-0.275801, -0.064188,2.6256,-0.386161, -0.124808,2.6256,-0.371546, + -0.18111,2.6256,-0.348105, -0.129351,2.6592,-0.248621, -0.08914,2.6592,-0.265363, + -0.08914,2.6592,-0.265363, -0.124808,2.6256,-0.371546, -0.18111,2.6256,-0.348105, + -0.232342,2.6256,-0.31659, -0.165941,2.6592,-0.226113, -0.129351,2.6592,-0.248621, + -0.129351,2.6592,-0.248621, -0.18111,2.6256,-0.348105, -0.232342,2.6256,-0.31659, + -0.277752,2.6256,-0.277752, -0.198374,2.6592,-0.198374, -0.165941,2.6592,-0.226113, + -0.165941,2.6592,-0.226113, -0.232342,2.6256,-0.31659, -0.277752,2.6256,-0.277752, + -0.31659,2.6256,-0.232342, -0.226113,2.6592,-0.165941, -0.198374,2.6592,-0.198374, + -0.198374,2.6592,-0.198374, -0.277752,2.6256,-0.277752, -0.31659,2.6256,-0.232342, + -0.348105,2.6256,-0.18111, -0.248621,2.6592,-0.129351, -0.226113,2.6592,-0.165941, + -0.226113,2.6592,-0.165941, -0.31659,2.6256,-0.232342, -0.348105,2.6256,-0.18111, + -0.371546,2.6256,-0.124808, -0.265363,2.6592,-0.08914, -0.248621,2.6592,-0.129351, + -0.248621,2.6592,-0.129351, -0.348105,2.6256,-0.18111, -0.371546,2.6256,-0.124808, + -0.386161,2.6256,-0.064188, -0.275801,2.6592,-0.045844, -0.265363,2.6592,-0.08914, + -0.265363,2.6592,-0.08914, -0.371546,2.6256,-0.124808, -0.386161,2.6256,-0.064188, + -0.3912,2.6256,0, -0.2794,2.6592,0, -0.275801,2.6592,-0.045844, + -0.275801,2.6592,-0.045844, -0.386161,2.6256,-0.064188, -0.3912,2.6256,0, + -0.086273,2.5974,-0.519028, -0.064188,2.6256,-0.386161, 0,2.6256,-0.3912, + 0,2.6256,-0.3912, 0,2.5974,-0.5258, -0.086273,2.5974,-0.519028, + -0.167751,2.5974,-0.499384, -0.124808,2.6256,-0.371546, -0.064188,2.6256,-0.386161, + -0.064188,2.6256,-0.386161, -0.086273,2.5974,-0.519028, -0.167751,2.5974,-0.499384, + -0.243424,2.5974,-0.467878, -0.18111,2.6256,-0.348105, -0.124808,2.6256,-0.371546, + -0.124808,2.6256,-0.371546, -0.167751,2.5974,-0.499384, -0.243424,2.5974,-0.467878, + -0.312283,2.5974,-0.425519, -0.232342,2.6256,-0.31659, -0.18111,2.6256,-0.348105, + -0.18111,2.6256,-0.348105, -0.243424,2.5974,-0.467878, -0.312283,2.5974,-0.425519, + -0.373318,2.5974,-0.373318, -0.277752,2.6256,-0.277752, -0.232342,2.6256,-0.31659, + -0.232342,2.6256,-0.31659, -0.312283,2.5974,-0.425519, -0.373318,2.5974,-0.373318, + -0.425519,2.5974,-0.312283, -0.31659,2.6256,-0.232342, -0.277752,2.6256,-0.277752, + -0.277752,2.6256,-0.277752, -0.373318,2.5974,-0.373318, -0.425519,2.5974,-0.312283, + -0.467878,2.5974,-0.243424, -0.348105,2.6256,-0.18111, -0.31659,2.6256,-0.232342, + -0.31659,2.6256,-0.232342, -0.425519,2.5974,-0.312283, -0.467878,2.5974,-0.243424, + -0.499384,2.5974,-0.167751, -0.371546,2.6256,-0.124808, -0.348105,2.6256,-0.18111, + -0.348105,2.6256,-0.18111, -0.467878,2.5974,-0.243424, -0.499384,2.5974,-0.167751, + -0.519028,2.5974,-0.086273, -0.386161,2.6256,-0.064188, -0.371546,2.6256,-0.124808, + -0.371546,2.6256,-0.124808, -0.499384,2.5974,-0.167751, -0.519028,2.5974,-0.086273, + -0.5258,2.5974,0, -0.3912,2.6256,0, -0.386161,2.6256,-0.064188, + -0.386161,2.6256,-0.064188, -0.519028,2.5974,-0.086273, -0.5258,2.5974,0, + -0.110524,2.5728,-0.664924, -0.086273,2.5974,-0.519028, 0,2.5974,-0.5258, + 0,2.5974,-0.5258, 0,2.5728,-0.6736, -0.110524,2.5728,-0.664924, + -0.214905,2.5728,-0.639758, -0.167751,2.5974,-0.499384, -0.086273,2.5974,-0.519028, + -0.086273,2.5974,-0.519028, -0.110524,2.5728,-0.664924, -0.214905,2.5728,-0.639758, + -0.31185,2.5728,-0.599396, -0.243424,2.5974,-0.467878, -0.167751,2.5974,-0.499384, + -0.167751,2.5974,-0.499384, -0.214905,2.5728,-0.639758, -0.31185,2.5728,-0.599396, + -0.400065,2.5728,-0.545131, -0.312283,2.5974,-0.425519, -0.243424,2.5974,-0.467878, + -0.243424,2.5974,-0.467878, -0.31185,2.5728,-0.599396, -0.400065,2.5728,-0.545131, + -0.478256,2.5728,-0.478256, -0.373318,2.5974,-0.373318, -0.312283,2.5974,-0.425519, + -0.312283,2.5974,-0.425519, -0.400065,2.5728,-0.545131, -0.478256,2.5728,-0.478256, + -0.545131,2.5728,-0.400065, -0.425519,2.5974,-0.312283, -0.373318,2.5974,-0.373318, + -0.373318,2.5974,-0.373318, -0.478256,2.5728,-0.478256, -0.545131,2.5728,-0.400065, + -0.599396,2.5728,-0.31185, -0.467878,2.5974,-0.243424, -0.425519,2.5974,-0.312283, + -0.425519,2.5974,-0.312283, -0.545131,2.5728,-0.400065, -0.599396,2.5728,-0.31185, + -0.639758,2.5728,-0.214905, -0.499384,2.5974,-0.167751, -0.467878,2.5974,-0.243424, + -0.467878,2.5974,-0.243424, -0.599396,2.5728,-0.31185, -0.639758,2.5728,-0.214905, + -0.664924,2.5728,-0.110524, -0.519028,2.5974,-0.086273, -0.499384,2.5974,-0.167751, + -0.499384,2.5974,-0.167751, -0.639758,2.5728,-0.214905, -0.664924,2.5728,-0.110524, + -0.6736,2.5728,0, -0.5258,2.5974,0, -0.519028,2.5974,-0.086273, + -0.519028,2.5974,-0.086273, -0.664924,2.5728,-0.110524, -0.6736,2.5728,0, + -0.135366,2.55,-0.814374, -0.110524,2.5728,-0.664924, 0,2.5728,-0.6736, + 0,2.5728,-0.6736, 0,2.55,-0.825, -0.135366,2.55,-0.814374, + -0.263208,2.55,-0.783552, -0.214905,2.5728,-0.639758, -0.110524,2.5728,-0.664924, + -0.110524,2.5728,-0.664924, -0.135366,2.55,-0.814374, -0.263208,2.55,-0.783552, + -0.381942,2.55,-0.734118, -0.31185,2.5728,-0.599396, -0.214905,2.5728,-0.639758, + -0.214905,2.5728,-0.639758, -0.263208,2.55,-0.783552, -0.381942,2.55,-0.734118, + -0.489984,2.55,-0.667656, -0.400065,2.5728,-0.545131, -0.31185,2.5728,-0.599396, + -0.31185,2.5728,-0.599396, -0.381942,2.55,-0.734118, -0.489984,2.55,-0.667656, + -0.58575,2.55,-0.58575, -0.478256,2.5728,-0.478256, -0.400065,2.5728,-0.545131, + -0.400065,2.5728,-0.545131, -0.489984,2.55,-0.667656, -0.58575,2.55,-0.58575, + -0.667656,2.55,-0.489984, -0.545131,2.5728,-0.400065, -0.478256,2.5728,-0.478256, + -0.478256,2.5728,-0.478256, -0.58575,2.55,-0.58575, -0.667656,2.55,-0.489984, + -0.734118,2.55,-0.381942, -0.599396,2.5728,-0.31185, -0.545131,2.5728,-0.400065, + -0.545131,2.5728,-0.400065, -0.667656,2.55,-0.489984, -0.734118,2.55,-0.381942, + -0.783552,2.55,-0.263208, -0.639758,2.5728,-0.214905, -0.599396,2.5728,-0.31185, + -0.599396,2.5728,-0.31185, -0.734118,2.55,-0.381942, -0.783552,2.55,-0.263208, + -0.814374,2.55,-0.135366, -0.664924,2.5728,-0.110524, -0.639758,2.5728,-0.214905, + -0.639758,2.5728,-0.214905, -0.783552,2.55,-0.263208, -0.814374,2.55,-0.135366, + -0.825,2.55,0, -0.6736,2.5728,0, -0.664924,2.5728,-0.110524, + -0.664924,2.5728,-0.110524, -0.814374,2.55,-0.135366, -0.825,2.55,0, + -0.159223,2.5272,-0.957901, -0.135366,2.55,-0.814374, 0,2.55,-0.825, + 0,2.55,-0.825, 0,2.5272,-0.9704, -0.159223,2.5272,-0.957901, + -0.309596,2.5272,-0.921647, -0.263208,2.55,-0.783552, -0.135366,2.55,-0.814374, + -0.135366,2.55,-0.814374, -0.159223,2.5272,-0.957901, -0.309596,2.5272,-0.921647, + -0.449256,2.5272,-0.863501, -0.381942,2.55,-0.734118, -0.263208,2.55,-0.783552, + -0.263208,2.55,-0.783552, -0.309596,2.5272,-0.921647, -0.449256,2.5272,-0.863501, + -0.57634,2.5272,-0.785325, -0.489984,2.55,-0.667656, -0.381942,2.55,-0.734118, + -0.381942,2.55,-0.734118, -0.449256,2.5272,-0.863501, -0.57634,2.5272,-0.785325, + -0.688984,2.5272,-0.688984, -0.58575,2.55,-0.58575, -0.489984,2.55,-0.667656, + -0.489984,2.55,-0.667656, -0.57634,2.5272,-0.785325, -0.688984,2.5272,-0.688984, + -0.785325,2.5272,-0.57634, -0.667656,2.55,-0.489984, -0.58575,2.55,-0.58575, + -0.58575,2.55,-0.58575, -0.688984,2.5272,-0.688984, -0.785325,2.5272,-0.57634, + -0.863501,2.5272,-0.449256, -0.734118,2.55,-0.381942, -0.667656,2.55,-0.489984, + -0.667656,2.55,-0.489984, -0.785325,2.5272,-0.57634, -0.863501,2.5272,-0.449256, + -0.921647,2.5272,-0.309596, -0.783552,2.55,-0.263208, -0.734118,2.55,-0.381942, + -0.734118,2.55,-0.381942, -0.863501,2.5272,-0.449256, -0.921647,2.5272,-0.309596, + -0.957901,2.5272,-0.159223, -0.814374,2.55,-0.135366, -0.783552,2.55,-0.263208, + -0.783552,2.55,-0.263208, -0.921647,2.5272,-0.309596, -0.957901,2.5272,-0.159223, + -0.9704,2.5272,0, -0.825,2.55,0, -0.814374,2.55,-0.135366, + -0.814374,2.55,-0.135366, -0.957901,2.5272,-0.159223, -0.9704,2.5272,0, + -0.180521,2.5026,-1.086029, -0.159223,2.5272,-0.957901, 0,2.5272,-0.9704, + 0,2.5272,-0.9704, 0,2.5026,-1.1002, -0.180521,2.5026,-1.086029, + -0.351008,2.5026,-1.044926, -0.309596,2.5272,-0.921647, -0.159223,2.5272,-0.957901, + -0.159223,2.5272,-0.957901, -0.180521,2.5026,-1.086029, -0.351008,2.5026,-1.044926, + -0.509349,2.5026,-0.979002, -0.449256,2.5272,-0.863501, -0.309596,2.5272,-0.921647, + -0.309596,2.5272,-0.921647, -0.351008,2.5026,-1.044926, -0.509349,2.5026,-0.979002, + -0.653431,2.5026,-0.89037, -0.57634,2.5272,-0.785325, -0.449256,2.5272,-0.863501, + -0.449256,2.5272,-0.863501, -0.509349,2.5026,-0.979002, -0.653431,2.5026,-0.89037, + -0.781142,2.5026,-0.781142, -0.688984,2.5272,-0.688984, -0.57634,2.5272,-0.785325, + -0.57634,2.5272,-0.785325, -0.653431,2.5026,-0.89037, -0.781142,2.5026,-0.781142, + -0.89037,2.5026,-0.653431, -0.785325,2.5272,-0.57634, -0.688984,2.5272,-0.688984, + -0.688984,2.5272,-0.688984, -0.781142,2.5026,-0.781142, -0.89037,2.5026,-0.653431, + -0.979002,2.5026,-0.509349, -0.863501,2.5272,-0.449256, -0.785325,2.5272,-0.57634, + -0.785325,2.5272,-0.57634, -0.89037,2.5026,-0.653431, -0.979002,2.5026,-0.509349, + -1.044926,2.5026,-0.351008, -0.921647,2.5272,-0.309596, -0.863501,2.5272,-0.449256, + -0.863501,2.5272,-0.449256, -0.979002,2.5026,-0.509349, -1.044926,2.5026,-0.351008, + -1.086029,2.5026,-0.180521, -0.957901,2.5272,-0.159223, -0.921647,2.5272,-0.309596, + -0.921647,2.5272,-0.309596, -1.044926,2.5026,-0.351008, -1.086029,2.5026,-0.180521, + -1.1002,2.5026,0, -0.9704,2.5272,0, -0.957901,2.5272,-0.159223, + -0.957901,2.5272,-0.159223, -1.086029,2.5026,-0.180521, -1.1002,2.5026,0, + -0.197684,2.4744,-1.189282, -0.180521,2.5026,-1.086029, 0,2.5026,-1.1002, + 0,2.5026,-1.1002, 0,2.4744,-1.2048, -0.197684,2.4744,-1.189282, + -0.384379,2.4744,-1.144271, -0.351008,2.5026,-1.044926, -0.180521,2.5026,-1.086029, + -0.180521,2.5026,-1.086029, -0.197684,2.4744,-1.189282, -0.384379,2.4744,-1.144271, + -0.557774,2.4744,-1.072079, -0.509349,2.5026,-0.979002, -0.351008,2.5026,-1.044926, + -0.351008,2.5026,-1.044926, -0.384379,2.4744,-1.144271, -0.557774,2.4744,-1.072079, + -0.715555,2.4744,-0.975021, -0.653431,2.5026,-0.89037, -0.509349,2.5026,-0.979002, + -0.509349,2.5026,-0.979002, -0.557774,2.4744,-1.072079, -0.715555,2.4744,-0.975021, + -0.855408,2.4744,-0.855408, -0.781142,2.5026,-0.781142, -0.653431,2.5026,-0.89037, + -0.653431,2.5026,-0.89037, -0.715555,2.4744,-0.975021, -0.855408,2.4744,-0.855408, + -0.975021,2.4744,-0.715555, -0.89037,2.5026,-0.653431, -0.781142,2.5026,-0.781142, + -0.781142,2.5026,-0.781142, -0.855408,2.4744,-0.855408, -0.975021,2.4744,-0.715555, + -1.072079,2.4744,-0.557774, -0.979002,2.5026,-0.509349, -0.89037,2.5026,-0.653431, + -0.89037,2.5026,-0.653431, -0.975021,2.4744,-0.715555, -1.072079,2.4744,-0.557774, + -1.144271,2.4744,-0.384379, -1.044926,2.5026,-0.351008, -0.979002,2.5026,-0.509349, + -0.979002,2.5026,-0.509349, -1.072079,2.4744,-0.557774, -1.144271,2.4744,-0.384379, + -1.189282,2.4744,-0.197684, -1.086029,2.5026,-0.180521, -1.044926,2.5026,-0.351008, + -1.044926,2.5026,-0.351008, -1.144271,2.4744,-0.384379, -1.189282,2.4744,-0.197684, + -1.2048,2.4744,0, -1.1002,2.5026,0, -1.086029,2.5026,-0.180521, + -1.086029,2.5026,-0.180521, -1.189282,2.4744,-0.197684, -1.2048,2.4744,0, + -0.209136,2.4408,-1.258183, -0.197684,2.4744,-1.189282, 0,2.4744,-1.2048, + 0,2.4744,-1.2048, 0,2.4408,-1.2746, -0.209136,2.4408,-1.258183, + -0.406648,2.4408,-1.210564, -0.384379,2.4744,-1.144271, -0.197684,2.4744,-1.189282, + -0.197684,2.4744,-1.189282, -0.209136,2.4408,-1.258183, -0.406648,2.4408,-1.210564, + -0.590089,2.4408,-1.13419, -0.557774,2.4744,-1.072079, -0.384379,2.4744,-1.144271, + -0.384379,2.4744,-1.144271, -0.406648,2.4408,-1.210564, -0.590089,2.4408,-1.13419, + -0.75701,2.4408,-1.031508, -0.715555,2.4744,-0.975021, -0.557774,2.4744,-1.072079, + -0.557774,2.4744,-1.072079, -0.590089,2.4408,-1.13419, -0.75701,2.4408,-1.031508, + -0.904966,2.4408,-0.904966, -0.855408,2.4744,-0.855408, -0.715555,2.4744,-0.975021, + -0.715555,2.4744,-0.975021, -0.75701,2.4408,-1.031508, -0.904966,2.4408,-0.904966, + -1.031508,2.4408,-0.75701, -0.975021,2.4744,-0.715555, -0.855408,2.4744,-0.855408, + -0.855408,2.4744,-0.855408, -0.904966,2.4408,-0.904966, -1.031508,2.4408,-0.75701, + -1.13419,2.4408,-0.590089, -1.072079,2.4744,-0.557774, -0.975021,2.4744,-0.715555, + -0.975021,2.4744,-0.715555, -1.031508,2.4408,-0.75701, -1.13419,2.4408,-0.590089, + -1.210564,2.4408,-0.406648, -1.144271,2.4744,-0.384379, -1.072079,2.4744,-0.557774, + -1.072079,2.4744,-0.557774, -1.13419,2.4408,-0.590089, -1.210564,2.4408,-0.406648, + -1.258183,2.4408,-0.209136, -1.189282,2.4744,-0.197684, -1.144271,2.4744,-0.384379, + -1.144271,2.4744,-0.384379, -1.210564,2.4408,-0.406648, -1.258183,2.4408,-0.209136, + -1.2746,2.4408,0, -1.2048,2.4744,0, -1.189282,2.4744,-0.197684, + -1.189282,2.4744,-0.197684, -1.258183,2.4408,-0.209136, -1.2746,2.4408,0, + -0.213304,2.4,-1.283256, -0.209136,2.4408,-1.258183, 0,2.4408,-1.2746, + 0,2.4408,-1.2746, 0,2.4,-1.3, -0.213304,2.4,-1.283256, + -0.414752,2.4,-1.234688, -0.406648,2.4408,-1.210564, -0.209136,2.4408,-1.258183, + -0.209136,2.4408,-1.258183, -0.213304,2.4,-1.283256, -0.414752,2.4,-1.234688, + -0.601848,2.4,-1.156792, -0.590089,2.4408,-1.13419, -0.406648,2.4408,-1.210564, + -0.406648,2.4408,-1.210564, -0.414752,2.4,-1.234688, -0.601848,2.4,-1.156792, + -0.772096,2.4,-1.052064, -0.75701,2.4408,-1.031508, -0.590089,2.4408,-1.13419, + -0.590089,2.4408,-1.13419, -0.601848,2.4,-1.156792, -0.772096,2.4,-1.052064, + -0.923,2.4,-0.923, -0.904966,2.4408,-0.904966, -0.75701,2.4408,-1.031508, + -0.75701,2.4408,-1.031508, -0.772096,2.4,-1.052064, -0.923,2.4,-0.923, + -1.052064,2.4,-0.772096, -1.031508,2.4408,-0.75701, -0.904966,2.4408,-0.904966, + -0.904966,2.4408,-0.904966, -0.923,2.4,-0.923, -1.052064,2.4,-0.772096, + -1.156792,2.4,-0.601848, -1.13419,2.4408,-0.590089, -1.031508,2.4408,-0.75701, + -1.031508,2.4408,-0.75701, -1.052064,2.4,-0.772096, -1.156792,2.4,-0.601848, + -1.234688,2.4,-0.414752, -1.210564,2.4408,-0.406648, -1.13419,2.4408,-0.590089, + -1.13419,2.4408,-0.590089, -1.156792,2.4,-0.601848, -1.234688,2.4,-0.414752, + -1.283256,2.4,-0.213304, -1.258183,2.4408,-0.209136, -1.210564,2.4408,-0.406648, + -1.210564,2.4408,-0.406648, -1.234688,2.4,-0.414752, -1.283256,2.4,-0.213304, + -1.3,2.4,0, -1.2746,2.4408,0, -1.258183,2.4408,-0.209136, + -1.258183,2.4408,-0.209136, -1.283256,2.4,-0.213304, -1.3,2.4,0, + -0.275801,2.6592,0.045844, -0.197424,2.7,0.032816, -0.2,2.7,0, + -0.2,2.7,0, -0.2794,2.6592,0, -0.275801,2.6592,0.045844, + -0.265363,2.6592,0.08914, -0.189952,2.7,0.063808, -0.197424,2.7,0.032816, + -0.197424,2.7,0.032816, -0.275801,2.6592,0.045844, -0.265363,2.6592,0.08914, + -0.248621,2.6592,0.129351, -0.177968,2.7,0.092592, -0.189952,2.7,0.063808, + -0.189952,2.7,0.063808, -0.265363,2.6592,0.08914, -0.248621,2.6592,0.129351, + -0.226113,2.6592,0.165941, -0.161856,2.7,0.118784, -0.177968,2.7,0.092592, + -0.177968,2.7,0.092592, -0.248621,2.6592,0.129351, -0.226113,2.6592,0.165941, + -0.198374,2.6592,0.198374, -0.142,2.7,0.142, -0.161856,2.7,0.118784, + -0.161856,2.7,0.118784, -0.226113,2.6592,0.165941, -0.198374,2.6592,0.198374, + -0.165941,2.6592,0.226113, -0.118784,2.7,0.161856, -0.142,2.7,0.142, + -0.142,2.7,0.142, -0.198374,2.6592,0.198374, -0.165941,2.6592,0.226113, + -0.129351,2.6592,0.248621, -0.092592,2.7,0.177968, -0.118784,2.7,0.161856, + -0.118784,2.7,0.161856, -0.165941,2.6592,0.226113, -0.129351,2.6592,0.248621, + -0.08914,2.6592,0.265363, -0.063808,2.7,0.189952, -0.092592,2.7,0.177968, + -0.092592,2.7,0.177968, -0.129351,2.6592,0.248621, -0.08914,2.6592,0.265363, + -0.045844,2.6592,0.275801, -0.032816,2.7,0.197424, -0.063808,2.7,0.189952, + -0.063808,2.7,0.189952, -0.08914,2.6592,0.265363, -0.045844,2.6592,0.275801, + 0,2.6592,0.2794, 0,2.7,0.2, -0.032816,2.7,0.197424, + -0.032816,2.7,0.197424, -0.045844,2.6592,0.275801, 0,2.6592,0.2794, + -0.386161,2.6256,0.064188, -0.275801,2.6592,0.045844, -0.2794,2.6592,0, + -0.2794,2.6592,0, -0.3912,2.6256,0, -0.386161,2.6256,0.064188, + -0.371546,2.6256,0.124808, -0.265363,2.6592,0.08914, -0.275801,2.6592,0.045844, + -0.275801,2.6592,0.045844, -0.386161,2.6256,0.064188, -0.371546,2.6256,0.124808, + -0.348105,2.6256,0.18111, -0.248621,2.6592,0.129351, -0.265363,2.6592,0.08914, + -0.265363,2.6592,0.08914, -0.371546,2.6256,0.124808, -0.348105,2.6256,0.18111, + -0.31659,2.6256,0.232342, -0.226113,2.6592,0.165941, -0.248621,2.6592,0.129351, + -0.248621,2.6592,0.129351, -0.348105,2.6256,0.18111, -0.31659,2.6256,0.232342, + -0.277752,2.6256,0.277752, -0.198374,2.6592,0.198374, -0.226113,2.6592,0.165941, + -0.226113,2.6592,0.165941, -0.31659,2.6256,0.232342, -0.277752,2.6256,0.277752, + -0.232342,2.6256,0.31659, -0.165941,2.6592,0.226113, -0.198374,2.6592,0.198374, + -0.198374,2.6592,0.198374, -0.277752,2.6256,0.277752, -0.232342,2.6256,0.31659, + -0.18111,2.6256,0.348105, -0.129351,2.6592,0.248621, -0.165941,2.6592,0.226113, + -0.165941,2.6592,0.226113, -0.232342,2.6256,0.31659, -0.18111,2.6256,0.348105, + -0.124808,2.6256,0.371546, -0.08914,2.6592,0.265363, -0.129351,2.6592,0.248621, + -0.129351,2.6592,0.248621, -0.18111,2.6256,0.348105, -0.124808,2.6256,0.371546, + -0.064188,2.6256,0.386161, -0.045844,2.6592,0.275801, -0.08914,2.6592,0.265363, + -0.08914,2.6592,0.265363, -0.124808,2.6256,0.371546, -0.064188,2.6256,0.386161, + 0,2.6256,0.3912, 0,2.6592,0.2794, -0.045844,2.6592,0.275801, + -0.045844,2.6592,0.275801, -0.064188,2.6256,0.386161, 0,2.6256,0.3912, + -0.519028,2.5974,0.086273, -0.386161,2.6256,0.064188, -0.3912,2.6256,0, + -0.3912,2.6256,0, -0.5258,2.5974,0, -0.519028,2.5974,0.086273, + -0.499384,2.5974,0.167751, -0.371546,2.6256,0.124808, -0.386161,2.6256,0.064188, + -0.386161,2.6256,0.064188, -0.519028,2.5974,0.086273, -0.499384,2.5974,0.167751, + -0.467878,2.5974,0.243424, -0.348105,2.6256,0.18111, -0.371546,2.6256,0.124808, + -0.371546,2.6256,0.124808, -0.499384,2.5974,0.167751, -0.467878,2.5974,0.243424, + -0.425519,2.5974,0.312283, -0.31659,2.6256,0.232342, -0.348105,2.6256,0.18111, + -0.348105,2.6256,0.18111, -0.467878,2.5974,0.243424, -0.425519,2.5974,0.312283, + -0.373318,2.5974,0.373318, -0.277752,2.6256,0.277752, -0.31659,2.6256,0.232342, + -0.31659,2.6256,0.232342, -0.425519,2.5974,0.312283, -0.373318,2.5974,0.373318, + -0.312283,2.5974,0.425519, -0.232342,2.6256,0.31659, -0.277752,2.6256,0.277752, + -0.277752,2.6256,0.277752, -0.373318,2.5974,0.373318, -0.312283,2.5974,0.425519, + -0.243424,2.5974,0.467878, -0.18111,2.6256,0.348105, -0.232342,2.6256,0.31659, + -0.232342,2.6256,0.31659, -0.312283,2.5974,0.425519, -0.243424,2.5974,0.467878, + -0.167751,2.5974,0.499384, -0.124808,2.6256,0.371546, -0.18111,2.6256,0.348105, + -0.18111,2.6256,0.348105, -0.243424,2.5974,0.467878, -0.167751,2.5974,0.499384, + -0.086273,2.5974,0.519028, -0.064188,2.6256,0.386161, -0.124808,2.6256,0.371546, + -0.124808,2.6256,0.371546, -0.167751,2.5974,0.499384, -0.086273,2.5974,0.519028, + 0,2.5974,0.5258, 0,2.6256,0.3912, -0.064188,2.6256,0.386161, + -0.064188,2.6256,0.386161, -0.086273,2.5974,0.519028, 0,2.5974,0.5258, + -0.664924,2.5728,0.110524, -0.519028,2.5974,0.086273, -0.5258,2.5974,0, + -0.5258,2.5974,0, -0.6736,2.5728,0, -0.664924,2.5728,0.110524, + -0.639758,2.5728,0.214905, -0.499384,2.5974,0.167751, -0.519028,2.5974,0.086273, + -0.519028,2.5974,0.086273, -0.664924,2.5728,0.110524, -0.639758,2.5728,0.214905, + -0.599396,2.5728,0.31185, -0.467878,2.5974,0.243424, -0.499384,2.5974,0.167751, + -0.499384,2.5974,0.167751, -0.639758,2.5728,0.214905, -0.599396,2.5728,0.31185, + -0.545131,2.5728,0.400065, -0.425519,2.5974,0.312283, -0.467878,2.5974,0.243424, + -0.467878,2.5974,0.243424, -0.599396,2.5728,0.31185, -0.545131,2.5728,0.400065, + -0.478256,2.5728,0.478256, -0.373318,2.5974,0.373318, -0.425519,2.5974,0.312283, + -0.425519,2.5974,0.312283, -0.545131,2.5728,0.400065, -0.478256,2.5728,0.478256, + -0.400065,2.5728,0.545131, -0.312283,2.5974,0.425519, -0.373318,2.5974,0.373318, + -0.373318,2.5974,0.373318, -0.478256,2.5728,0.478256, -0.400065,2.5728,0.545131, + -0.31185,2.5728,0.599396, -0.243424,2.5974,0.467878, -0.312283,2.5974,0.425519, + -0.312283,2.5974,0.425519, -0.400065,2.5728,0.545131, -0.31185,2.5728,0.599396, + -0.214905,2.5728,0.639758, -0.167751,2.5974,0.499384, -0.243424,2.5974,0.467878, + -0.243424,2.5974,0.467878, -0.31185,2.5728,0.599396, -0.214905,2.5728,0.639758, + -0.110524,2.5728,0.664924, -0.086273,2.5974,0.519028, -0.167751,2.5974,0.499384, + -0.167751,2.5974,0.499384, -0.214905,2.5728,0.639758, -0.110524,2.5728,0.664924, + 0,2.5728,0.6736, 0,2.5974,0.5258, -0.086273,2.5974,0.519028, + -0.086273,2.5974,0.519028, -0.110524,2.5728,0.664924, 0,2.5728,0.6736, + -0.814374,2.55,0.135366, -0.664924,2.5728,0.110524, -0.6736,2.5728,0, + -0.6736,2.5728,0, -0.825,2.55,0, -0.814374,2.55,0.135366, + -0.783552,2.55,0.263208, -0.639758,2.5728,0.214905, -0.664924,2.5728,0.110524, + -0.664924,2.5728,0.110524, -0.814374,2.55,0.135366, -0.783552,2.55,0.263208, + -0.734118,2.55,0.381942, -0.599396,2.5728,0.31185, -0.639758,2.5728,0.214905, + -0.639758,2.5728,0.214905, -0.783552,2.55,0.263208, -0.734118,2.55,0.381942, + -0.667656,2.55,0.489984, -0.545131,2.5728,0.400065, -0.599396,2.5728,0.31185, + -0.599396,2.5728,0.31185, -0.734118,2.55,0.381942, -0.667656,2.55,0.489984, + -0.58575,2.55,0.58575, -0.478256,2.5728,0.478256, -0.545131,2.5728,0.400065, + -0.545131,2.5728,0.400065, -0.667656,2.55,0.489984, -0.58575,2.55,0.58575, + -0.489984,2.55,0.667656, -0.400065,2.5728,0.545131, -0.478256,2.5728,0.478256, + -0.478256,2.5728,0.478256, -0.58575,2.55,0.58575, -0.489984,2.55,0.667656, + -0.381942,2.55,0.734118, -0.31185,2.5728,0.599396, -0.400065,2.5728,0.545131, + -0.400065,2.5728,0.545131, -0.489984,2.55,0.667656, -0.381942,2.55,0.734118, + -0.263208,2.55,0.783552, -0.214905,2.5728,0.639758, -0.31185,2.5728,0.599396, + -0.31185,2.5728,0.599396, -0.381942,2.55,0.734118, -0.263208,2.55,0.783552, + -0.135366,2.55,0.814374, -0.110524,2.5728,0.664924, -0.214905,2.5728,0.639758, + -0.214905,2.5728,0.639758, -0.263208,2.55,0.783552, -0.135366,2.55,0.814374, + 0,2.55,0.825, 0,2.5728,0.6736, -0.110524,2.5728,0.664924, + -0.110524,2.5728,0.664924, -0.135366,2.55,0.814374, 0,2.55,0.825, + -0.957901,2.5272,0.159223, -0.814374,2.55,0.135366, -0.825,2.55,0, + -0.825,2.55,0, -0.9704,2.5272,0, -0.957901,2.5272,0.159223, + -0.921647,2.5272,0.309596, -0.783552,2.55,0.263208, -0.814374,2.55,0.135366, + -0.814374,2.55,0.135366, -0.957901,2.5272,0.159223, -0.921647,2.5272,0.309596, + -0.863501,2.5272,0.449256, -0.734118,2.55,0.381942, -0.783552,2.55,0.263208, + -0.783552,2.55,0.263208, -0.921647,2.5272,0.309596, -0.863501,2.5272,0.449256, + -0.785325,2.5272,0.57634, -0.667656,2.55,0.489984, -0.734118,2.55,0.381942, + -0.734118,2.55,0.381942, -0.863501,2.5272,0.449256, -0.785325,2.5272,0.57634, + -0.688984,2.5272,0.688984, -0.58575,2.55,0.58575, -0.667656,2.55,0.489984, + -0.667656,2.55,0.489984, -0.785325,2.5272,0.57634, -0.688984,2.5272,0.688984, + -0.57634,2.5272,0.785325, -0.489984,2.55,0.667656, -0.58575,2.55,0.58575, + -0.58575,2.55,0.58575, -0.688984,2.5272,0.688984, -0.57634,2.5272,0.785325, + -0.449256,2.5272,0.863501, -0.381942,2.55,0.734118, -0.489984,2.55,0.667656, + -0.489984,2.55,0.667656, -0.57634,2.5272,0.785325, -0.449256,2.5272,0.863501, + -0.309596,2.5272,0.921647, -0.263208,2.55,0.783552, -0.381942,2.55,0.734118, + -0.381942,2.55,0.734118, -0.449256,2.5272,0.863501, -0.309596,2.5272,0.921647, + -0.159223,2.5272,0.957901, -0.135366,2.55,0.814374, -0.263208,2.55,0.783552, + -0.263208,2.55,0.783552, -0.309596,2.5272,0.921647, -0.159223,2.5272,0.957901, + 0,2.5272,0.9704, 0,2.55,0.825, -0.135366,2.55,0.814374, + -0.135366,2.55,0.814374, -0.159223,2.5272,0.957901, 0,2.5272,0.9704, + -1.086029,2.5026,0.180521, -0.957901,2.5272,0.159223, -0.9704,2.5272,0, + -0.9704,2.5272,0, -1.1002,2.5026,0, -1.086029,2.5026,0.180521, + -1.044926,2.5026,0.351008, -0.921647,2.5272,0.309596, -0.957901,2.5272,0.159223, + -0.957901,2.5272,0.159223, -1.086029,2.5026,0.180521, -1.044926,2.5026,0.351008, + -0.979002,2.5026,0.509349, -0.863501,2.5272,0.449256, -0.921647,2.5272,0.309596, + -0.921647,2.5272,0.309596, -1.044926,2.5026,0.351008, -0.979002,2.5026,0.509349, + -0.89037,2.5026,0.653431, -0.785325,2.5272,0.57634, -0.863501,2.5272,0.449256, + -0.863501,2.5272,0.449256, -0.979002,2.5026,0.509349, -0.89037,2.5026,0.653431, + -0.781142,2.5026,0.781142, -0.688984,2.5272,0.688984, -0.785325,2.5272,0.57634, + -0.785325,2.5272,0.57634, -0.89037,2.5026,0.653431, -0.781142,2.5026,0.781142, + -0.653431,2.5026,0.89037, -0.57634,2.5272,0.785325, -0.688984,2.5272,0.688984, + -0.688984,2.5272,0.688984, -0.781142,2.5026,0.781142, -0.653431,2.5026,0.89037, + -0.509349,2.5026,0.979002, -0.449256,2.5272,0.863501, -0.57634,2.5272,0.785325, + -0.57634,2.5272,0.785325, -0.653431,2.5026,0.89037, -0.509349,2.5026,0.979002, + -0.351008,2.5026,1.044926, -0.309596,2.5272,0.921647, -0.449256,2.5272,0.863501, + -0.449256,2.5272,0.863501, -0.509349,2.5026,0.979002, -0.351008,2.5026,1.044926, + -0.180521,2.5026,1.086029, -0.159223,2.5272,0.957901, -0.309596,2.5272,0.921647, + -0.309596,2.5272,0.921647, -0.351008,2.5026,1.044926, -0.180521,2.5026,1.086029, + 0,2.5026,1.1002, 0,2.5272,0.9704, -0.159223,2.5272,0.957901, + -0.159223,2.5272,0.957901, -0.180521,2.5026,1.086029, 0,2.5026,1.1002, + -1.189282,2.4744,0.197684, -1.086029,2.5026,0.180521, -1.1002,2.5026,0, + -1.1002,2.5026,0, -1.2048,2.4744,0, -1.189282,2.4744,0.197684, + -1.144271,2.4744,0.384379, -1.044926,2.5026,0.351008, -1.086029,2.5026,0.180521, + -1.086029,2.5026,0.180521, -1.189282,2.4744,0.197684, -1.144271,2.4744,0.384379, + -1.072079,2.4744,0.557774, -0.979002,2.5026,0.509349, -1.044926,2.5026,0.351008, + -1.044926,2.5026,0.351008, -1.144271,2.4744,0.384379, -1.072079,2.4744,0.557774, + -0.975021,2.4744,0.715555, -0.89037,2.5026,0.653431, -0.979002,2.5026,0.509349, + -0.979002,2.5026,0.509349, -1.072079,2.4744,0.557774, -0.975021,2.4744,0.715555, + -0.855408,2.4744,0.855408, -0.781142,2.5026,0.781142, -0.89037,2.5026,0.653431, + -0.89037,2.5026,0.653431, -0.975021,2.4744,0.715555, -0.855408,2.4744,0.855408, + -0.715555,2.4744,0.975021, -0.653431,2.5026,0.89037, -0.781142,2.5026,0.781142, + -0.781142,2.5026,0.781142, -0.855408,2.4744,0.855408, -0.715555,2.4744,0.975021, + -0.557774,2.4744,1.072079, -0.509349,2.5026,0.979002, -0.653431,2.5026,0.89037, + -0.653431,2.5026,0.89037, -0.715555,2.4744,0.975021, -0.557774,2.4744,1.072079, + -0.384379,2.4744,1.144271, -0.351008,2.5026,1.044926, -0.509349,2.5026,0.979002, + -0.509349,2.5026,0.979002, -0.557774,2.4744,1.072079, -0.384379,2.4744,1.144271, + -0.197684,2.4744,1.189282, -0.180521,2.5026,1.086029, -0.351008,2.5026,1.044926, + -0.351008,2.5026,1.044926, -0.384379,2.4744,1.144271, -0.197684,2.4744,1.189282, + 0,2.4744,1.2048, 0,2.5026,1.1002, -0.180521,2.5026,1.086029, + -0.180521,2.5026,1.086029, -0.197684,2.4744,1.189282, 0,2.4744,1.2048, + -1.258183,2.4408,0.209136, -1.189282,2.4744,0.197684, -1.2048,2.4744,0, + -1.2048,2.4744,0, -1.2746,2.4408,0, -1.258183,2.4408,0.209136, + -1.210564,2.4408,0.406648, -1.144271,2.4744,0.384379, -1.189282,2.4744,0.197684, + -1.189282,2.4744,0.197684, -1.258183,2.4408,0.209136, -1.210564,2.4408,0.406648, + -1.13419,2.4408,0.590089, -1.072079,2.4744,0.557774, -1.144271,2.4744,0.384379, + -1.144271,2.4744,0.384379, -1.210564,2.4408,0.406648, -1.13419,2.4408,0.590089, + -1.031508,2.4408,0.75701, -0.975021,2.4744,0.715555, -1.072079,2.4744,0.557774, + -1.072079,2.4744,0.557774, -1.13419,2.4408,0.590089, -1.031508,2.4408,0.75701, + -0.904966,2.4408,0.904966, -0.855408,2.4744,0.855408, -0.975021,2.4744,0.715555, + -0.975021,2.4744,0.715555, -1.031508,2.4408,0.75701, -0.904966,2.4408,0.904966, + -0.75701,2.4408,1.031508, -0.715555,2.4744,0.975021, -0.855408,2.4744,0.855408, + -0.855408,2.4744,0.855408, -0.904966,2.4408,0.904966, -0.75701,2.4408,1.031508, + -0.590089,2.4408,1.13419, -0.557774,2.4744,1.072079, -0.715555,2.4744,0.975021, + -0.715555,2.4744,0.975021, -0.75701,2.4408,1.031508, -0.590089,2.4408,1.13419, + -0.406648,2.4408,1.210564, -0.384379,2.4744,1.144271, -0.557774,2.4744,1.072079, + -0.557774,2.4744,1.072079, -0.590089,2.4408,1.13419, -0.406648,2.4408,1.210564, + -0.209136,2.4408,1.258183, -0.197684,2.4744,1.189282, -0.384379,2.4744,1.144271, + -0.384379,2.4744,1.144271, -0.406648,2.4408,1.210564, -0.209136,2.4408,1.258183, + 0,2.4408,1.2746, 0,2.4744,1.2048, -0.197684,2.4744,1.189282, + -0.197684,2.4744,1.189282, -0.209136,2.4408,1.258183, 0,2.4408,1.2746, + -1.283256,2.4,0.213304, -1.258183,2.4408,0.209136, -1.2746,2.4408,0, + -1.2746,2.4408,0, -1.3,2.4,0, -1.283256,2.4,0.213304, + -1.234688,2.4,0.414752, -1.210564,2.4408,0.406648, -1.258183,2.4408,0.209136, + -1.258183,2.4408,0.209136, -1.283256,2.4,0.213304, -1.234688,2.4,0.414752, + -1.156792,2.4,0.601848, -1.13419,2.4408,0.590089, -1.210564,2.4408,0.406648, + -1.210564,2.4408,0.406648, -1.234688,2.4,0.414752, -1.156792,2.4,0.601848, + -1.052064,2.4,0.772096, -1.031508,2.4408,0.75701, -1.13419,2.4408,0.590089, + -1.13419,2.4408,0.590089, -1.156792,2.4,0.601848, -1.052064,2.4,0.772096, + -0.923,2.4,0.923, -0.904966,2.4408,0.904966, -1.031508,2.4408,0.75701, + -1.031508,2.4408,0.75701, -1.052064,2.4,0.772096, -0.923,2.4,0.923, + -0.772096,2.4,1.052064, -0.75701,2.4408,1.031508, -0.904966,2.4408,0.904966, + -0.904966,2.4408,0.904966, -0.923,2.4,0.923, -0.772096,2.4,1.052064, + -0.601848,2.4,1.156792, -0.590089,2.4408,1.13419, -0.75701,2.4408,1.031508, + -0.75701,2.4408,1.031508, -0.772096,2.4,1.052064, -0.601848,2.4,1.156792, + -0.414752,2.4,1.234688, -0.406648,2.4408,1.210564, -0.590089,2.4408,1.13419, + -0.590089,2.4408,1.13419, -0.601848,2.4,1.156792, -0.414752,2.4,1.234688, + -0.213304,2.4,1.283256, -0.209136,2.4408,1.258183, -0.406648,2.4408,1.210564, + -0.406648,2.4408,1.210564, -0.414752,2.4,1.234688, -0.213304,2.4,1.283256, + 0,2.4,1.3, 0,2.4408,1.2746, -0.209136,2.4408,1.258183, + -0.209136,2.4408,1.258183, -0.213304,2.4,1.283256, 0,2.4,1.3, + 0.045844,2.6592,0.275801, 0.032816,2.7,0.197424, 0,2.7,0.2, + 0,2.7,0.2, 0,2.6592,0.2794, 0.045844,2.6592,0.275801, + 0.08914,2.6592,0.265363, 0.063808,2.7,0.189952, 0.032816,2.7,0.197424, + 0.032816,2.7,0.197424, 0.045844,2.6592,0.275801, 0.08914,2.6592,0.265363, + 0.129351,2.6592,0.248621, 0.092592,2.7,0.177968, 0.063808,2.7,0.189952, + 0.063808,2.7,0.189952, 0.08914,2.6592,0.265363, 0.129351,2.6592,0.248621, + 0.165941,2.6592,0.226113, 0.118784,2.7,0.161856, 0.092592,2.7,0.177968, + 0.092592,2.7,0.177968, 0.129351,2.6592,0.248621, 0.165941,2.6592,0.226113, + 0.198374,2.6592,0.198374, 0.142,2.7,0.142, 0.118784,2.7,0.161856, + 0.118784,2.7,0.161856, 0.165941,2.6592,0.226113, 0.198374,2.6592,0.198374, + 0.226113,2.6592,0.165941, 0.161856,2.7,0.118784, 0.142,2.7,0.142, + 0.142,2.7,0.142, 0.198374,2.6592,0.198374, 0.226113,2.6592,0.165941, + 0.248621,2.6592,0.129351, 0.177968,2.7,0.092592, 0.161856,2.7,0.118784, + 0.161856,2.7,0.118784, 0.226113,2.6592,0.165941, 0.248621,2.6592,0.129351, + 0.265363,2.6592,0.08914, 0.189952,2.7,0.063808, 0.177968,2.7,0.092592, + 0.177968,2.7,0.092592, 0.248621,2.6592,0.129351, 0.265363,2.6592,0.08914, + 0.275801,2.6592,0.045844, 0.197424,2.7,0.032816, 0.189952,2.7,0.063808, + 0.189952,2.7,0.063808, 0.265363,2.6592,0.08914, 0.275801,2.6592,0.045844, + 0.2794,2.6592,0, 0.2,2.7,0, 0.197424,2.7,0.032816, + 0.197424,2.7,0.032816, 0.275801,2.6592,0.045844, 0.2794,2.6592,0, + 0.064188,2.6256,0.386161, 0.045844,2.6592,0.275801, 0,2.6592,0.2794, + 0,2.6592,0.2794, 0,2.6256,0.3912, 0.064188,2.6256,0.386161, + 0.124808,2.6256,0.371546, 0.08914,2.6592,0.265363, 0.045844,2.6592,0.275801, + 0.045844,2.6592,0.275801, 0.064188,2.6256,0.386161, 0.124808,2.6256,0.371546, + 0.18111,2.6256,0.348105, 0.129351,2.6592,0.248621, 0.08914,2.6592,0.265363, + 0.08914,2.6592,0.265363, 0.124808,2.6256,0.371546, 0.18111,2.6256,0.348105, + 0.232342,2.6256,0.31659, 0.165941,2.6592,0.226113, 0.129351,2.6592,0.248621, + 0.129351,2.6592,0.248621, 0.18111,2.6256,0.348105, 0.232342,2.6256,0.31659, + 0.277752,2.6256,0.277752, 0.198374,2.6592,0.198374, 0.165941,2.6592,0.226113, + 0.165941,2.6592,0.226113, 0.232342,2.6256,0.31659, 0.277752,2.6256,0.277752, + 0.31659,2.6256,0.232342, 0.226113,2.6592,0.165941, 0.198374,2.6592,0.198374, + 0.198374,2.6592,0.198374, 0.277752,2.6256,0.277752, 0.31659,2.6256,0.232342, + 0.348105,2.6256,0.18111, 0.248621,2.6592,0.129351, 0.226113,2.6592,0.165941, + 0.226113,2.6592,0.165941, 0.31659,2.6256,0.232342, 0.348105,2.6256,0.18111, + 0.371546,2.6256,0.124808, 0.265363,2.6592,0.08914, 0.248621,2.6592,0.129351, + 0.248621,2.6592,0.129351, 0.348105,2.6256,0.18111, 0.371546,2.6256,0.124808, + 0.386161,2.6256,0.064188, 0.275801,2.6592,0.045844, 0.265363,2.6592,0.08914, + 0.265363,2.6592,0.08914, 0.371546,2.6256,0.124808, 0.386161,2.6256,0.064188, + 0.3912,2.6256,0, 0.2794,2.6592,0, 0.275801,2.6592,0.045844, + 0.275801,2.6592,0.045844, 0.386161,2.6256,0.064188, 0.3912,2.6256,0, + 0.086273,2.5974,0.519028, 0.064188,2.6256,0.386161, 0,2.6256,0.3912, + 0,2.6256,0.3912, 0,2.5974,0.5258, 0.086273,2.5974,0.519028, + 0.167751,2.5974,0.499384, 0.124808,2.6256,0.371546, 0.064188,2.6256,0.386161, + 0.064188,2.6256,0.386161, 0.086273,2.5974,0.519028, 0.167751,2.5974,0.499384, + 0.243424,2.5974,0.467878, 0.18111,2.6256,0.348105, 0.124808,2.6256,0.371546, + 0.124808,2.6256,0.371546, 0.167751,2.5974,0.499384, 0.243424,2.5974,0.467878, + 0.312283,2.5974,0.425519, 0.232342,2.6256,0.31659, 0.18111,2.6256,0.348105, + 0.18111,2.6256,0.348105, 0.243424,2.5974,0.467878, 0.312283,2.5974,0.425519, + 0.373318,2.5974,0.373318, 0.277752,2.6256,0.277752, 0.232342,2.6256,0.31659, + 0.232342,2.6256,0.31659, 0.312283,2.5974,0.425519, 0.373318,2.5974,0.373318, + 0.425519,2.5974,0.312283, 0.31659,2.6256,0.232342, 0.277752,2.6256,0.277752, + 0.277752,2.6256,0.277752, 0.373318,2.5974,0.373318, 0.425519,2.5974,0.312283, + 0.467878,2.5974,0.243424, 0.348105,2.6256,0.18111, 0.31659,2.6256,0.232342, + 0.31659,2.6256,0.232342, 0.425519,2.5974,0.312283, 0.467878,2.5974,0.243424, + 0.499384,2.5974,0.167751, 0.371546,2.6256,0.124808, 0.348105,2.6256,0.18111, + 0.348105,2.6256,0.18111, 0.467878,2.5974,0.243424, 0.499384,2.5974,0.167751, + 0.519028,2.5974,0.086273, 0.386161,2.6256,0.064188, 0.371546,2.6256,0.124808, + 0.371546,2.6256,0.124808, 0.499384,2.5974,0.167751, 0.519028,2.5974,0.086273, + 0.5258,2.5974,0, 0.3912,2.6256,0, 0.386161,2.6256,0.064188, + 0.386161,2.6256,0.064188, 0.519028,2.5974,0.086273, 0.5258,2.5974,0, + 0.110524,2.5728,0.664924, 0.086273,2.5974,0.519028, 0,2.5974,0.5258, + 0,2.5974,0.5258, 0,2.5728,0.6736, 0.110524,2.5728,0.664924, + 0.214905,2.5728,0.639758, 0.167751,2.5974,0.499384, 0.086273,2.5974,0.519028, + 0.086273,2.5974,0.519028, 0.110524,2.5728,0.664924, 0.214905,2.5728,0.639758, + 0.31185,2.5728,0.599396, 0.243424,2.5974,0.467878, 0.167751,2.5974,0.499384, + 0.167751,2.5974,0.499384, 0.214905,2.5728,0.639758, 0.31185,2.5728,0.599396, + 0.400065,2.5728,0.545131, 0.312283,2.5974,0.425519, 0.243424,2.5974,0.467878, + 0.243424,2.5974,0.467878, 0.31185,2.5728,0.599396, 0.400065,2.5728,0.545131, + 0.478256,2.5728,0.478256, 0.373318,2.5974,0.373318, 0.312283,2.5974,0.425519, + 0.312283,2.5974,0.425519, 0.400065,2.5728,0.545131, 0.478256,2.5728,0.478256, + 0.545131,2.5728,0.400065, 0.425519,2.5974,0.312283, 0.373318,2.5974,0.373318, + 0.373318,2.5974,0.373318, 0.478256,2.5728,0.478256, 0.545131,2.5728,0.400065, + 0.599396,2.5728,0.31185, 0.467878,2.5974,0.243424, 0.425519,2.5974,0.312283, + 0.425519,2.5974,0.312283, 0.545131,2.5728,0.400065, 0.599396,2.5728,0.31185, + 0.639758,2.5728,0.214905, 0.499384,2.5974,0.167751, 0.467878,2.5974,0.243424, + 0.467878,2.5974,0.243424, 0.599396,2.5728,0.31185, 0.639758,2.5728,0.214905, + 0.664924,2.5728,0.110524, 0.519028,2.5974,0.086273, 0.499384,2.5974,0.167751, + 0.499384,2.5974,0.167751, 0.639758,2.5728,0.214905, 0.664924,2.5728,0.110524, + 0.6736,2.5728,0, 0.5258,2.5974,0, 0.519028,2.5974,0.086273, + 0.519028,2.5974,0.086273, 0.664924,2.5728,0.110524, 0.6736,2.5728,0, + 0.135366,2.55,0.814374, 0.110524,2.5728,0.664924, 0,2.5728,0.6736, + 0,2.5728,0.6736, 0,2.55,0.825, 0.135366,2.55,0.814374, + 0.263208,2.55,0.783552, 0.214905,2.5728,0.639758, 0.110524,2.5728,0.664924, + 0.110524,2.5728,0.664924, 0.135366,2.55,0.814374, 0.263208,2.55,0.783552, + 0.381942,2.55,0.734118, 0.31185,2.5728,0.599396, 0.214905,2.5728,0.639758, + 0.214905,2.5728,0.639758, 0.263208,2.55,0.783552, 0.381942,2.55,0.734118, + 0.489984,2.55,0.667656, 0.400065,2.5728,0.545131, 0.31185,2.5728,0.599396, + 0.31185,2.5728,0.599396, 0.381942,2.55,0.734118, 0.489984,2.55,0.667656, + 0.58575,2.55,0.58575, 0.478256,2.5728,0.478256, 0.400065,2.5728,0.545131, + 0.400065,2.5728,0.545131, 0.489984,2.55,0.667656, 0.58575,2.55,0.58575, + 0.667656,2.55,0.489984, 0.545131,2.5728,0.400065, 0.478256,2.5728,0.478256, + 0.478256,2.5728,0.478256, 0.58575,2.55,0.58575, 0.667656,2.55,0.489984, + 0.734118,2.55,0.381942, 0.599396,2.5728,0.31185, 0.545131,2.5728,0.400065, + 0.545131,2.5728,0.400065, 0.667656,2.55,0.489984, 0.734118,2.55,0.381942, + 0.783552,2.55,0.263208, 0.639758,2.5728,0.214905, 0.599396,2.5728,0.31185, + 0.599396,2.5728,0.31185, 0.734118,2.55,0.381942, 0.783552,2.55,0.263208, + 0.814374,2.55,0.135366, 0.664924,2.5728,0.110524, 0.639758,2.5728,0.214905, + 0.639758,2.5728,0.214905, 0.783552,2.55,0.263208, 0.814374,2.55,0.135366, + 0.825,2.55,0, 0.6736,2.5728,0, 0.664924,2.5728,0.110524, + 0.664924,2.5728,0.110524, 0.814374,2.55,0.135366, 0.825,2.55,0, + 0.159223,2.5272,0.957901, 0.135366,2.55,0.814374, 0,2.55,0.825, + 0,2.55,0.825, 0,2.5272,0.9704, 0.159223,2.5272,0.957901, + 0.309596,2.5272,0.921647, 0.263208,2.55,0.783552, 0.135366,2.55,0.814374, + 0.135366,2.55,0.814374, 0.159223,2.5272,0.957901, 0.309596,2.5272,0.921647, + 0.449256,2.5272,0.863501, 0.381942,2.55,0.734118, 0.263208,2.55,0.783552, + 0.263208,2.55,0.783552, 0.309596,2.5272,0.921647, 0.449256,2.5272,0.863501, + 0.57634,2.5272,0.785325, 0.489984,2.55,0.667656, 0.381942,2.55,0.734118, + 0.381942,2.55,0.734118, 0.449256,2.5272,0.863501, 0.57634,2.5272,0.785325, + 0.688984,2.5272,0.688984, 0.58575,2.55,0.58575, 0.489984,2.55,0.667656, + 0.489984,2.55,0.667656, 0.57634,2.5272,0.785325, 0.688984,2.5272,0.688984, + 0.785325,2.5272,0.57634, 0.667656,2.55,0.489984, 0.58575,2.55,0.58575, + 0.58575,2.55,0.58575, 0.688984,2.5272,0.688984, 0.785325,2.5272,0.57634, + 0.863501,2.5272,0.449256, 0.734118,2.55,0.381942, 0.667656,2.55,0.489984, + 0.667656,2.55,0.489984, 0.785325,2.5272,0.57634, 0.863501,2.5272,0.449256, + 0.921647,2.5272,0.309596, 0.783552,2.55,0.263208, 0.734118,2.55,0.381942, + 0.734118,2.55,0.381942, 0.863501,2.5272,0.449256, 0.921647,2.5272,0.309596, + 0.957901,2.5272,0.159223, 0.814374,2.55,0.135366, 0.783552,2.55,0.263208, + 0.783552,2.55,0.263208, 0.921647,2.5272,0.309596, 0.957901,2.5272,0.159223, + 0.9704,2.5272,0, 0.825,2.55,0, 0.814374,2.55,0.135366, + 0.814374,2.55,0.135366, 0.957901,2.5272,0.159223, 0.9704,2.5272,0, + 0.180521,2.5026,1.086029, 0.159223,2.5272,0.957901, 0,2.5272,0.9704, + 0,2.5272,0.9704, 0,2.5026,1.1002, 0.180521,2.5026,1.086029, + 0.351008,2.5026,1.044926, 0.309596,2.5272,0.921647, 0.159223,2.5272,0.957901, + 0.159223,2.5272,0.957901, 0.180521,2.5026,1.086029, 0.351008,2.5026,1.044926, + 0.509349,2.5026,0.979002, 0.449256,2.5272,0.863501, 0.309596,2.5272,0.921647, + 0.309596,2.5272,0.921647, 0.351008,2.5026,1.044926, 0.509349,2.5026,0.979002, + 0.653431,2.5026,0.89037, 0.57634,2.5272,0.785325, 0.449256,2.5272,0.863501, + 0.449256,2.5272,0.863501, 0.509349,2.5026,0.979002, 0.653431,2.5026,0.89037, + 0.781142,2.5026,0.781142, 0.688984,2.5272,0.688984, 0.57634,2.5272,0.785325, + 0.57634,2.5272,0.785325, 0.653431,2.5026,0.89037, 0.781142,2.5026,0.781142, + 0.89037,2.5026,0.653431, 0.785325,2.5272,0.57634, 0.688984,2.5272,0.688984, + 0.688984,2.5272,0.688984, 0.781142,2.5026,0.781142, 0.89037,2.5026,0.653431, + 0.979002,2.5026,0.509349, 0.863501,2.5272,0.449256, 0.785325,2.5272,0.57634, + 0.785325,2.5272,0.57634, 0.89037,2.5026,0.653431, 0.979002,2.5026,0.509349, + 1.044926,2.5026,0.351008, 0.921647,2.5272,0.309596, 0.863501,2.5272,0.449256, + 0.863501,2.5272,0.449256, 0.979002,2.5026,0.509349, 1.044926,2.5026,0.351008, + 1.086029,2.5026,0.180521, 0.957901,2.5272,0.159223, 0.921647,2.5272,0.309596, + 0.921647,2.5272,0.309596, 1.044926,2.5026,0.351008, 1.086029,2.5026,0.180521, + 1.1002,2.5026,0, 0.9704,2.5272,0, 0.957901,2.5272,0.159223, + 0.957901,2.5272,0.159223, 1.086029,2.5026,0.180521, 1.1002,2.5026,0, + 0.197684,2.4744,1.189282, 0.180521,2.5026,1.086029, 0,2.5026,1.1002, + 0,2.5026,1.1002, 0,2.4744,1.2048, 0.197684,2.4744,1.189282, + 0.384379,2.4744,1.144271, 0.351008,2.5026,1.044926, 0.180521,2.5026,1.086029, + 0.180521,2.5026,1.086029, 0.197684,2.4744,1.189282, 0.384379,2.4744,1.144271, + 0.557774,2.4744,1.072079, 0.509349,2.5026,0.979002, 0.351008,2.5026,1.044926, + 0.351008,2.5026,1.044926, 0.384379,2.4744,1.144271, 0.557774,2.4744,1.072079, + 0.715555,2.4744,0.975021, 0.653431,2.5026,0.89037, 0.509349,2.5026,0.979002, + 0.509349,2.5026,0.979002, 0.557774,2.4744,1.072079, 0.715555,2.4744,0.975021, + 0.855408,2.4744,0.855408, 0.781142,2.5026,0.781142, 0.653431,2.5026,0.89037, + 0.653431,2.5026,0.89037, 0.715555,2.4744,0.975021, 0.855408,2.4744,0.855408, + 0.975021,2.4744,0.715555, 0.89037,2.5026,0.653431, 0.781142,2.5026,0.781142, + 0.781142,2.5026,0.781142, 0.855408,2.4744,0.855408, 0.975021,2.4744,0.715555, + 1.072079,2.4744,0.557774, 0.979002,2.5026,0.509349, 0.89037,2.5026,0.653431, + 0.89037,2.5026,0.653431, 0.975021,2.4744,0.715555, 1.072079,2.4744,0.557774, + 1.144271,2.4744,0.384379, 1.044926,2.5026,0.351008, 0.979002,2.5026,0.509349, + 0.979002,2.5026,0.509349, 1.072079,2.4744,0.557774, 1.144271,2.4744,0.384379, + 1.189282,2.4744,0.197684, 1.086029,2.5026,0.180521, 1.044926,2.5026,0.351008, + 1.044926,2.5026,0.351008, 1.144271,2.4744,0.384379, 1.189282,2.4744,0.197684, + 1.2048,2.4744,0, 1.1002,2.5026,0, 1.086029,2.5026,0.180521, + 1.086029,2.5026,0.180521, 1.189282,2.4744,0.197684, 1.2048,2.4744,0, + 0.209136,2.4408,1.258183, 0.197684,2.4744,1.189282, 0,2.4744,1.2048, + 0,2.4744,1.2048, 0,2.4408,1.2746, 0.209136,2.4408,1.258183, + 0.406648,2.4408,1.210564, 0.384379,2.4744,1.144271, 0.197684,2.4744,1.189282, + 0.197684,2.4744,1.189282, 0.209136,2.4408,1.258183, 0.406648,2.4408,1.210564, + 0.590089,2.4408,1.13419, 0.557774,2.4744,1.072079, 0.384379,2.4744,1.144271, + 0.384379,2.4744,1.144271, 0.406648,2.4408,1.210564, 0.590089,2.4408,1.13419, + 0.75701,2.4408,1.031508, 0.715555,2.4744,0.975021, 0.557774,2.4744,1.072079, + 0.557774,2.4744,1.072079, 0.590089,2.4408,1.13419, 0.75701,2.4408,1.031508, + 0.904966,2.4408,0.904966, 0.855408,2.4744,0.855408, 0.715555,2.4744,0.975021, + 0.715555,2.4744,0.975021, 0.75701,2.4408,1.031508, 0.904966,2.4408,0.904966, + 1.031508,2.4408,0.75701, 0.975021,2.4744,0.715555, 0.855408,2.4744,0.855408, + 0.855408,2.4744,0.855408, 0.904966,2.4408,0.904966, 1.031508,2.4408,0.75701, + 1.13419,2.4408,0.590089, 1.072079,2.4744,0.557774, 0.975021,2.4744,0.715555, + 0.975021,2.4744,0.715555, 1.031508,2.4408,0.75701, 1.13419,2.4408,0.590089, + 1.210564,2.4408,0.406648, 1.144271,2.4744,0.384379, 1.072079,2.4744,0.557774, + 1.072079,2.4744,0.557774, 1.13419,2.4408,0.590089, 1.210564,2.4408,0.406648, + 1.258183,2.4408,0.209136, 1.189282,2.4744,0.197684, 1.144271,2.4744,0.384379, + 1.144271,2.4744,0.384379, 1.210564,2.4408,0.406648, 1.258183,2.4408,0.209136, + 1.2746,2.4408,0, 1.2048,2.4744,0, 1.189282,2.4744,0.197684, + 1.189282,2.4744,0.197684, 1.258183,2.4408,0.209136, 1.2746,2.4408,0, + 0.213304,2.4,1.283256, 0.209136,2.4408,1.258183, 0,2.4408,1.2746, + 0,2.4408,1.2746, 0,2.4,1.3, 0.213304,2.4,1.283256, + 0.414752,2.4,1.234688, 0.406648,2.4408,1.210564, 0.209136,2.4408,1.258183, + 0.209136,2.4408,1.258183, 0.213304,2.4,1.283256, 0.414752,2.4,1.234688, + 0.601848,2.4,1.156792, 0.590089,2.4408,1.13419, 0.406648,2.4408,1.210564, + 0.406648,2.4408,1.210564, 0.414752,2.4,1.234688, 0.601848,2.4,1.156792, + 0.772096,2.4,1.052064, 0.75701,2.4408,1.031508, 0.590089,2.4408,1.13419, + 0.590089,2.4408,1.13419, 0.601848,2.4,1.156792, 0.772096,2.4,1.052064, + 0.923,2.4,0.923, 0.904966,2.4408,0.904966, 0.75701,2.4408,1.031508, + 0.75701,2.4408,1.031508, 0.772096,2.4,1.052064, 0.923,2.4,0.923, + 1.052064,2.4,0.772096, 1.031508,2.4408,0.75701, 0.904966,2.4408,0.904966, + 0.904966,2.4408,0.904966, 0.923,2.4,0.923, 1.052064,2.4,0.772096, + 1.156792,2.4,0.601848, 1.13419,2.4408,0.590089, 1.031508,2.4408,0.75701, + 1.031508,2.4408,0.75701, 1.052064,2.4,0.772096, 1.156792,2.4,0.601848, + 1.234688,2.4,0.414752, 1.210564,2.4408,0.406648, 1.13419,2.4408,0.590089, + 1.13419,2.4408,0.590089, 1.156792,2.4,0.601848, 1.234688,2.4,0.414752, + 1.283256,2.4,0.213304, 1.258183,2.4408,0.209136, 1.210564,2.4408,0.406648, + 1.210564,2.4408,0.406648, 1.234688,2.4,0.414752, 1.283256,2.4,0.213304, + 1.3,2.4,0, 1.2746,2.4408,0, 1.258183,2.4408,0.209136, + 1.258183,2.4408,0.209136, 1.283256,2.4,0.213304, 1.3,2.4,0, + 0,0,0, 0.388275,0.002175,0, 0.383274,0.002175,0.063708, + 0,0,0, 0.383274,0.002175,0.063708, 0.368768,0.002175,0.123875, + 0,0,0, 0.368768,0.002175,0.123875, 0.345503,0.002175,0.179756, + 0,0,0, 0.345503,0.002175,0.179756, 0.314223,0.002175,0.230604, + 0,0,0, 0.314223,0.002175,0.230604, 0.275675,0.002175,0.275675, + 0,0,0, 0.275675,0.002175,0.275675, 0.230604,0.002175,0.314223, + 0,0,0, 0.230604,0.002175,0.314223, 0.179756,0.002175,0.345503, + 0,0,0, 0.179756,0.002175,0.345503, 0.123875,0.002175,0.368768, + 0,0,0, 0.123875,0.002175,0.368768, 0.063708,0.002175,0.383274, + 0,0,0, 0.063708,0.002175,0.383274, 0,0.002175,0.388275, + 0.694143,0.0084,0.115381, 0.383274,0.002175,0.063708, 0.388275,0.002175,0, + 0.388275,0.002175,0, 0.7032,0.0084,0, 0.694143,0.0084,0.115381, + 0.667871,0.0084,0.224349, 0.368768,0.002175,0.123875, 0.383274,0.002175,0.063708, + 0.383274,0.002175,0.063708, 0.694143,0.0084,0.115381, 0.667871,0.0084,0.224349, + 0.625735,0.0084,0.325553, 0.345503,0.002175,0.179756, 0.368768,0.002175,0.123875, + 0.368768,0.002175,0.123875, 0.667871,0.0084,0.224349, 0.625735,0.0084,0.325553, + 0.569086,0.0084,0.417645, 0.314223,0.002175,0.230604, 0.345503,0.002175,0.179756, + 0.345503,0.002175,0.179756, 0.625735,0.0084,0.325553, 0.569086,0.0084,0.417645, + 0.499272,0.0084,0.499272, 0.275675,0.002175,0.275675, 0.314223,0.002175,0.230604, + 0.314223,0.002175,0.230604, 0.569086,0.0084,0.417645, 0.499272,0.0084,0.499272, + 0.417645,0.0084,0.569086, 0.230604,0.002175,0.314223, 0.275675,0.002175,0.275675, + 0.275675,0.002175,0.275675, 0.499272,0.0084,0.499272, 0.417645,0.0084,0.569086, + 0.325553,0.0084,0.625735, 0.179756,0.002175,0.345503, 0.230604,0.002175,0.314223, + 0.230604,0.002175,0.314223, 0.417645,0.0084,0.569086, 0.325553,0.0084,0.625735, + 0.224349,0.0084,0.667871, 0.123875,0.002175,0.368768, 0.179756,0.002175,0.345503, + 0.179756,0.002175,0.345503, 0.325553,0.0084,0.625735, 0.224349,0.0084,0.667871, + 0.115381,0.0084,0.694143, 0.063708,0.002175,0.383274, 0.123875,0.002175,0.368768, + 0.123875,0.002175,0.368768, 0.224349,0.0084,0.667871, 0.115381,0.0084,0.694143, + 0,0.0084,0.7032, 0,0.002175,0.388275, 0.063708,0.002175,0.383274, + 0.063708,0.002175,0.383274, 0.115381,0.0084,0.694143, 0,0.0084,0.7032, + 0.940158,0.018225,0.156274, 0.694143,0.0084,0.115381, 0.7032,0.0084,0, + 0.7032,0.0084,0, 0.952425,0.018225,0, 0.940158,0.018225,0.156274, + 0.904575,0.018225,0.303862, 0.667871,0.0084,0.224349, 0.694143,0.0084,0.115381, + 0.694143,0.0084,0.115381, 0.940158,0.018225,0.156274, 0.904575,0.018225,0.303862, + 0.847506,0.018225,0.440935, 0.625735,0.0084,0.325553, 0.667871,0.0084,0.224349, + 0.667871,0.0084,0.224349, 0.904575,0.018225,0.303862, 0.847506,0.018225,0.440935, + 0.770779,0.018225,0.565664, 0.569086,0.0084,0.417645, 0.625735,0.0084,0.325553, + 0.625735,0.0084,0.325553, 0.847506,0.018225,0.440935, 0.770779,0.018225,0.565664, + 0.676222,0.018225,0.676222, 0.499272,0.0084,0.499272, 0.569086,0.0084,0.417645, + 0.569086,0.0084,0.417645, 0.770779,0.018225,0.565664, 0.676222,0.018225,0.676222, + 0.565664,0.018225,0.770779, 0.417645,0.0084,0.569086, 0.499272,0.0084,0.499272, + 0.499272,0.0084,0.499272, 0.676222,0.018225,0.676222, 0.565664,0.018225,0.770779, + 0.440935,0.018225,0.847506, 0.325553,0.0084,0.625735, 0.417645,0.0084,0.569086, + 0.417645,0.0084,0.569086, 0.565664,0.018225,0.770779, 0.440935,0.018225,0.847506, + 0.303862,0.018225,0.904575, 0.224349,0.0084,0.667871, 0.325553,0.0084,0.625735, + 0.325553,0.0084,0.625735, 0.440935,0.018225,0.847506, 0.303862,0.018225,0.904575, + 0.156274,0.018225,0.940158, 0.115381,0.0084,0.694143, 0.224349,0.0084,0.667871, + 0.224349,0.0084,0.667871, 0.303862,0.018225,0.904575, 0.156274,0.018225,0.940158, + 0,0.018225,0.952425, 0,0.0084,0.7032, 0.115381,0.0084,0.694143, + 0.115381,0.0084,0.694143, 0.156274,0.018225,0.940158, 0,0.018225,0.952425, + 1.12887,0.0312,0.187642, 0.940158,0.018225,0.156274, 0.952425,0.018225,0, + 0.952425,0.018225,0, 1.1436,0.0312,0, 1.12887,0.0312,0.187642, + 1.086146,0.0312,0.364854, 0.904575,0.018225,0.303862, 0.940158,0.018225,0.156274, + 0.940158,0.018225,0.156274, 1.12887,0.0312,0.187642, 1.086146,0.0312,0.364854, + 1.017621,0.0312,0.529441, 0.847506,0.018225,0.440935, 0.904575,0.018225,0.303862, + 0.904575,0.018225,0.303862, 1.086146,0.0312,0.364854, 1.017621,0.0312,0.529441, + 0.925493,0.0312,0.679207, 0.770779,0.018225,0.565664, 0.847506,0.018225,0.440935, + 0.847506,0.018225,0.440935, 1.017621,0.0312,0.529441, 0.925493,0.0312,0.679207, + 0.811956,0.0312,0.811956, 0.676222,0.018225,0.676222, 0.770779,0.018225,0.565664, + 0.770779,0.018225,0.565664, 0.925493,0.0312,0.679207, 0.811956,0.0312,0.811956, + 0.679207,0.0312,0.925493, 0.565664,0.018225,0.770779, 0.676222,0.018225,0.676222, + 0.676222,0.018225,0.676222, 0.811956,0.0312,0.811956, 0.679207,0.0312,0.925493, + 0.529441,0.0312,1.017621, 0.440935,0.018225,0.847506, 0.565664,0.018225,0.770779, + 0.565664,0.018225,0.770779, 0.679207,0.0312,0.925493, 0.529441,0.0312,1.017621, + 0.364854,0.0312,1.086146, 0.303862,0.018225,0.904575, 0.440935,0.018225,0.847506, + 0.440935,0.018225,0.847506, 0.529441,0.0312,1.017621, 0.364854,0.0312,1.086146, + 0.187642,0.0312,1.12887, 0.156274,0.018225,0.940158, 0.303862,0.018225,0.904575, + 0.303862,0.018225,0.904575, 0.364854,0.0312,1.086146, 0.187642,0.0312,1.12887, + 0,0.0312,1.1436, 0,0.018225,0.952425, 0.156274,0.018225,0.940158, + 0.156274,0.018225,0.940158, 0.187642,0.0312,1.12887, 0,0.0312,1.1436, + 1.267832,0.046875,0.21074, 1.12887,0.0312,0.187642, 1.1436,0.0312,0, + 1.1436,0.0312,0, 1.284375,0.046875,0, 1.267832,0.046875,0.21074, + 1.219848,0.046875,0.409767, 1.086146,0.0312,0.364854, 1.12887,0.0312,0.187642, + 1.12887,0.0312,0.187642, 1.267832,0.046875,0.21074, 1.219848,0.046875,0.409767, + 1.142888,0.046875,0.594614, 1.017621,0.0312,0.529441, 1.086146,0.0312,0.364854, + 1.086146,0.0312,0.364854, 1.219848,0.046875,0.409767, 1.142888,0.046875,0.594614, + 1.039419,0.046875,0.762816, 0.925493,0.0312,0.679207, 1.017621,0.0312,0.529441, + 1.017621,0.0312,0.529441, 1.142888,0.046875,0.594614, 1.039419,0.046875,0.762816, + 0.911906,0.046875,0.911906, 0.811956,0.0312,0.811956, 0.925493,0.0312,0.679207, + 0.925493,0.0312,0.679207, 1.039419,0.046875,0.762816, 0.911906,0.046875,0.911906, + 0.762816,0.046875,1.039419, 0.679207,0.0312,0.925493, 0.811956,0.0312,0.811956, + 0.811956,0.0312,0.811956, 0.911906,0.046875,0.911906, 0.762816,0.046875,1.039419, + 0.594614,0.046875,1.142888, 0.529441,0.0312,1.017621, 0.679207,0.0312,0.925493, + 0.679207,0.0312,0.925493, 0.762816,0.046875,1.039419, 0.594614,0.046875,1.142888, + 0.409767,0.046875,1.219848, 0.364854,0.0312,1.086146, 0.529441,0.0312,1.017621, + 0.529441,0.0312,1.017621, 0.594614,0.046875,1.142888, 0.409767,0.046875,1.219848, + 0.21074,0.046875,1.267832, 0.187642,0.0312,1.12887, 0.364854,0.0312,1.086146, + 0.364854,0.0312,1.086146, 0.409767,0.046875,1.219848, 0.21074,0.046875,1.267832, + 0,0.046875,1.284375, 0,0.0312,1.1436, 0.187642,0.0312,1.12887, + 0.187642,0.0312,1.12887, 0.21074,0.046875,1.267832, 0,0.046875,1.284375, + 1.364595,0.0648,0.226824, 1.267832,0.046875,0.21074, 1.284375,0.046875,0, + 1.284375,0.046875,0, 1.3824,0.0648,0, 1.364595,0.0648,0.226824, + 1.312948,0.0648,0.441041, 1.219848,0.046875,0.409767, 1.267832,0.046875,0.21074, + 1.267832,0.046875,0.21074, 1.364595,0.0648,0.226824, 1.312948,0.0648,0.441041, + 1.230115,0.0648,0.639996, 1.142888,0.046875,0.594614, 1.219848,0.046875,0.409767, + 1.219848,0.046875,0.409767, 1.312948,0.0648,0.441041, 1.230115,0.0648,0.639996, + 1.118749,0.0648,0.821035, 1.039419,0.046875,0.762816, 1.142888,0.046875,0.594614, + 1.142888,0.046875,0.594614, 1.230115,0.0648,0.639996, 1.118749,0.0648,0.821035, + 0.981504,0.0648,0.981504, 0.911906,0.046875,0.911906, 1.039419,0.046875,0.762816, + 1.039419,0.046875,0.762816, 1.118749,0.0648,0.821035, 0.981504,0.0648,0.981504, + 0.821035,0.0648,1.118749, 0.762816,0.046875,1.039419, 0.911906,0.046875,0.911906, + 0.911906,0.046875,0.911906, 0.981504,0.0648,0.981504, 0.821035,0.0648,1.118749, + 0.639996,0.0648,1.230115, 0.594614,0.046875,1.142888, 0.762816,0.046875,1.039419, + 0.762816,0.046875,1.039419, 0.821035,0.0648,1.118749, 0.639996,0.0648,1.230115, + 0.441041,0.0648,1.312948, 0.409767,0.046875,1.219848, 0.594614,0.046875,1.142888, + 0.594614,0.046875,1.142888, 0.639996,0.0648,1.230115, 0.441041,0.0648,1.312948, + 0.226824,0.0648,1.364595, 0.21074,0.046875,1.267832, 0.409767,0.046875,1.219848, + 0.409767,0.046875,1.219848, 0.441041,0.0648,1.312948, 0.226824,0.0648,1.364595, + 0,0.0648,1.3824, 0,0.046875,1.284375, 0.21074,0.046875,1.267832, + 0.21074,0.046875,1.267832, 0.226824,0.0648,1.364595, 0,0.0648,1.3824, + 1.426709,0.084525,0.237149, 1.364595,0.0648,0.226824, 1.3824,0.0648,0, + 1.3824,0.0648,0, 1.445325,0.084525,0, 1.426709,0.084525,0.237149, + 1.372712,0.084525,0.461116, 1.312948,0.0648,0.441041, 1.364595,0.0648,0.226824, + 1.364595,0.0648,0.226824, 1.426709,0.084525,0.237149, 1.372712,0.084525,0.461116, + 1.286108,0.084525,0.669128, 1.230115,0.0648,0.639996, 1.312948,0.0648,0.441041, + 1.312948,0.0648,0.441041, 1.372712,0.084525,0.461116, 1.286108,0.084525,0.669128, + 1.169673,0.084525,0.858407, 1.118749,0.0648,0.821035, 1.230115,0.0648,0.639996, + 1.230115,0.0648,0.639996, 1.286108,0.084525,0.669128, 1.169673,0.084525,0.858407, + 1.026181,0.084525,1.026181, 0.981504,0.0648,0.981504, 1.118749,0.0648,0.821035, + 1.118749,0.0648,0.821035, 1.169673,0.084525,0.858407, 1.026181,0.084525,1.026181, + 0.858407,0.084525,1.169673, 0.821035,0.0648,1.118749, 0.981504,0.0648,0.981504, + 0.981504,0.0648,0.981504, 1.026181,0.084525,1.026181, 0.858407,0.084525,1.169673, + 0.669128,0.084525,1.286108, 0.639996,0.0648,1.230115, 0.821035,0.0648,1.118749, + 0.821035,0.0648,1.118749, 0.858407,0.084525,1.169673, 0.669128,0.084525,1.286108, + 0.461116,0.084525,1.372712, 0.441041,0.0648,1.312948, 0.639996,0.0648,1.230115, + 0.639996,0.0648,1.230115, 0.669128,0.084525,1.286108, 0.461116,0.084525,1.372712, + 0.237149,0.084525,1.426709, 0.226824,0.0648,1.364595, 0.441041,0.0648,1.312948, + 0.441041,0.0648,1.312948, 0.461116,0.084525,1.372712, 0.237149,0.084525,1.426709, + 0,0.084525,1.445325, 0,0.0648,1.3824, 0.226824,0.0648,1.364595, + 0.226824,0.0648,1.364595, 0.237149,0.084525,1.426709, 0,0.084525,1.445325, + 1.461727,0.1056,0.24297, 1.426709,0.084525,0.237149, 1.445325,0.084525,0, + 1.445325,0.084525,0, 1.4808,0.1056,0, 1.461727,0.1056,0.24297, + 1.406405,0.1056,0.472434, 1.372712,0.084525,0.461116, 1.426709,0.084525,0.237149, + 1.426709,0.084525,0.237149, 1.461727,0.1056,0.24297, 1.406405,0.1056,0.472434, + 1.317675,0.1056,0.685551, 1.286108,0.084525,0.669128, 1.372712,0.084525,0.461116, + 1.372712,0.084525,0.461116, 1.406405,0.1056,0.472434, 1.317675,0.1056,0.685551, + 1.198382,0.1056,0.879477, 1.169673,0.084525,0.858407, 1.286108,0.084525,0.669128, + 1.286108,0.084525,0.669128, 1.317675,0.1056,0.685551, 1.198382,0.1056,0.879477, + 1.051368,0.1056,1.051368, 1.026181,0.084525,1.026181, 1.169673,0.084525,0.858407, + 1.169673,0.084525,0.858407, 1.198382,0.1056,0.879477, 1.051368,0.1056,1.051368, + 0.879477,0.1056,1.198382, 0.858407,0.084525,1.169673, 1.026181,0.084525,1.026181, + 1.026181,0.084525,1.026181, 1.051368,0.1056,1.051368, 0.879477,0.1056,1.198382, + 0.685551,0.1056,1.317675, 0.669128,0.084525,1.286108, 0.858407,0.084525,1.169673, + 0.858407,0.084525,1.169673, 0.879477,0.1056,1.198382, 0.685551,0.1056,1.317675, + 0.472434,0.1056,1.406405, 0.461116,0.084525,1.372712, 0.669128,0.084525,1.286108, + 0.669128,0.084525,1.286108, 0.685551,0.1056,1.317675, 0.472434,0.1056,1.406405, + 0.24297,0.1056,1.461727, 0.237149,0.084525,1.426709, 0.461116,0.084525,1.372712, + 0.461116,0.084525,1.372712, 0.472434,0.1056,1.406405, 0.24297,0.1056,1.461727, + 0,0.1056,1.4808, 0,0.084525,1.445325, 0.237149,0.084525,1.426709, + 0.237149,0.084525,1.426709, 0.24297,0.1056,1.461727, 0,0.1056,1.4808, + 1.4772,0.127575,0.245542, 1.461727,0.1056,0.24297, 1.4808,0.1056,0, + 1.4808,0.1056,0, 1.496475,0.127575,0, 1.4772,0.127575,0.245542, + 1.421292,0.127575,0.477435, 1.406405,0.1056,0.472434, 1.461727,0.1056,0.24297, + 1.461727,0.1056,0.24297, 1.4772,0.127575,0.245542, 1.421292,0.127575,0.477435, + 1.331623,0.127575,0.692808, 1.317675,0.1056,0.685551, 1.406405,0.1056,0.472434, + 1.406405,0.1056,0.472434, 1.421292,0.127575,0.477435, 1.331623,0.127575,0.692808, + 1.211067,0.127575,0.888786, 1.198382,0.1056,0.879477, 1.317675,0.1056,0.685551, + 1.317675,0.1056,0.685551, 1.331623,0.127575,0.692808, 1.211067,0.127575,0.888786, + 1.062497,0.127575,1.062497, 1.051368,0.1056,1.051368, 1.198382,0.1056,0.879477, + 1.198382,0.1056,0.879477, 1.211067,0.127575,0.888786, 1.062497,0.127575,1.062497, + 0.888786,0.127575,1.211067, 0.879477,0.1056,1.198382, 1.051368,0.1056,1.051368, + 1.051368,0.1056,1.051368, 1.062497,0.127575,1.062497, 0.888786,0.127575,1.211067, + 0.692808,0.127575,1.331623, 0.685551,0.1056,1.317675, 0.879477,0.1056,1.198382, + 0.879477,0.1056,1.198382, 0.888786,0.127575,1.211067, 0.692808,0.127575,1.331623, + 0.477435,0.127575,1.421292, 0.472434,0.1056,1.406405, 0.685551,0.1056,1.317675, + 0.685551,0.1056,1.317675, 0.692808,0.127575,1.331623, 0.477435,0.127575,1.421292, + 0.245542,0.127575,1.4772, 0.24297,0.1056,1.461727, 0.472434,0.1056,1.406405, + 0.472434,0.1056,1.406405, 0.477435,0.127575,1.421292, 0.245542,0.127575,1.4772, + 0,0.127575,1.496475, 0,0.1056,1.4808, 0.24297,0.1056,1.461727, + 0.24297,0.1056,1.461727, 0.245542,0.127575,1.4772, 0,0.127575,1.496475, + 1.48068,0.15,0.24612, 1.4772,0.127575,0.245542, 1.496475,0.127575,0, + 1.496475,0.127575,0, 1.5,0.15,0, 1.48068,0.15,0.24612, + 1.42464,0.15,0.47856, 1.421292,0.127575,0.477435, 1.4772,0.127575,0.245542, + 1.4772,0.127575,0.245542, 1.48068,0.15,0.24612, 1.42464,0.15,0.47856, + 1.33476,0.15,0.69444, 1.331623,0.127575,0.692808, 1.421292,0.127575,0.477435, + 1.421292,0.127575,0.477435, 1.42464,0.15,0.47856, 1.33476,0.15,0.69444, + 1.21392,0.15,0.89088, 1.211067,0.127575,0.888786, 1.331623,0.127575,0.692808, + 1.331623,0.127575,0.692808, 1.33476,0.15,0.69444, 1.21392,0.15,0.89088, + 1.065,0.15,1.065, 1.062497,0.127575,1.062497, 1.211067,0.127575,0.888786, + 1.211067,0.127575,0.888786, 1.21392,0.15,0.89088, 1.065,0.15,1.065, + 0.89088,0.15,1.21392, 0.888786,0.127575,1.211067, 1.062497,0.127575,1.062497, + 1.062497,0.127575,1.062497, 1.065,0.15,1.065, 0.89088,0.15,1.21392, + 0.69444,0.15,1.33476, 0.692808,0.127575,1.331623, 0.888786,0.127575,1.211067, + 0.888786,0.127575,1.211067, 0.89088,0.15,1.21392, 0.69444,0.15,1.33476, + 0.47856,0.15,1.42464, 0.477435,0.127575,1.421292, 0.692808,0.127575,1.331623, + 0.692808,0.127575,1.331623, 0.69444,0.15,1.33476, 0.47856,0.15,1.42464, + 0.24612,0.15,1.48068, 0.245542,0.127575,1.4772, 0.477435,0.127575,1.421292, + 0.477435,0.127575,1.421292, 0.47856,0.15,1.42464, 0.24612,0.15,1.48068, + 0,0.15,1.5, 0,0.127575,1.496475, 0.245542,0.127575,1.4772, + 0.245542,0.127575,1.4772, 0.24612,0.15,1.48068, 0,0.15,1.5, + 0,0,0, 0,0.002175,0.388275, -0.063708,0.002175,0.383274, + 0,0,0, -0.063708,0.002175,0.383274, -0.123875,0.002175,0.368768, + 0,0,0, -0.123875,0.002175,0.368768, -0.179756,0.002175,0.345503, + 0,0,0, -0.179756,0.002175,0.345503, -0.230604,0.002175,0.314223, + 0,0,0, -0.230604,0.002175,0.314223, -0.275675,0.002175,0.275675, + 0,0,0, -0.275675,0.002175,0.275675, -0.314223,0.002175,0.230604, + 0,0,0, -0.314223,0.002175,0.230604, -0.345503,0.002175,0.179756, + 0,0,0, -0.345503,0.002175,0.179756, -0.368768,0.002175,0.123875, + 0,0,0, -0.368768,0.002175,0.123875, -0.383274,0.002175,0.063708, + 0,0,0, -0.383274,0.002175,0.063708, -0.388275,0.002175,0, + -0.115381,0.0084,0.694143, -0.063708,0.002175,0.383274, 0,0.002175,0.388275, + 0,0.002175,0.388275, 0,0.0084,0.7032, -0.115381,0.0084,0.694143, + -0.224349,0.0084,0.667871, -0.123875,0.002175,0.368768, -0.063708,0.002175,0.383274, + -0.063708,0.002175,0.383274, -0.115381,0.0084,0.694143, -0.224349,0.0084,0.667871, + -0.325553,0.0084,0.625735, -0.179756,0.002175,0.345503, -0.123875,0.002175,0.368768, + -0.123875,0.002175,0.368768, -0.224349,0.0084,0.667871, -0.325553,0.0084,0.625735, + -0.417645,0.0084,0.569086, -0.230604,0.002175,0.314223, -0.179756,0.002175,0.345503, + -0.179756,0.002175,0.345503, -0.325553,0.0084,0.625735, -0.417645,0.0084,0.569086, + -0.499272,0.0084,0.499272, -0.275675,0.002175,0.275675, -0.230604,0.002175,0.314223, + -0.230604,0.002175,0.314223, -0.417645,0.0084,0.569086, -0.499272,0.0084,0.499272, + -0.569086,0.0084,0.417645, -0.314223,0.002175,0.230604, -0.275675,0.002175,0.275675, + -0.275675,0.002175,0.275675, -0.499272,0.0084,0.499272, -0.569086,0.0084,0.417645, + -0.625735,0.0084,0.325553, -0.345503,0.002175,0.179756, -0.314223,0.002175,0.230604, + -0.314223,0.002175,0.230604, -0.569086,0.0084,0.417645, -0.625735,0.0084,0.325553, + -0.667871,0.0084,0.224349, -0.368768,0.002175,0.123875, -0.345503,0.002175,0.179756, + -0.345503,0.002175,0.179756, -0.625735,0.0084,0.325553, -0.667871,0.0084,0.224349, + -0.694143,0.0084,0.115381, -0.383274,0.002175,0.063708, -0.368768,0.002175,0.123875, + -0.368768,0.002175,0.123875, -0.667871,0.0084,0.224349, -0.694143,0.0084,0.115381, + -0.7032,0.0084,0, -0.388275,0.002175,0, -0.383274,0.002175,0.063708, + -0.383274,0.002175,0.063708, -0.694143,0.0084,0.115381, -0.7032,0.0084,0, + -0.156274,0.018225,0.940158, -0.115381,0.0084,0.694143, 0,0.0084,0.7032, + 0,0.0084,0.7032, 0,0.018225,0.952425, -0.156274,0.018225,0.940158, + -0.303862,0.018225,0.904575, -0.224349,0.0084,0.667871, -0.115381,0.0084,0.694143, + -0.115381,0.0084,0.694143, -0.156274,0.018225,0.940158, -0.303862,0.018225,0.904575, + -0.440935,0.018225,0.847506, -0.325553,0.0084,0.625735, -0.224349,0.0084,0.667871, + -0.224349,0.0084,0.667871, -0.303862,0.018225,0.904575, -0.440935,0.018225,0.847506, + -0.565664,0.018225,0.770779, -0.417645,0.0084,0.569086, -0.325553,0.0084,0.625735, + -0.325553,0.0084,0.625735, -0.440935,0.018225,0.847506, -0.565664,0.018225,0.770779, + -0.676222,0.018225,0.676222, -0.499272,0.0084,0.499272, -0.417645,0.0084,0.569086, + -0.417645,0.0084,0.569086, -0.565664,0.018225,0.770779, -0.676222,0.018225,0.676222, + -0.770779,0.018225,0.565664, -0.569086,0.0084,0.417645, -0.499272,0.0084,0.499272, + -0.499272,0.0084,0.499272, -0.676222,0.018225,0.676222, -0.770779,0.018225,0.565664, + -0.847506,0.018225,0.440935, -0.625735,0.0084,0.325553, -0.569086,0.0084,0.417645, + -0.569086,0.0084,0.417645, -0.770779,0.018225,0.565664, -0.847506,0.018225,0.440935, + -0.904575,0.018225,0.303862, -0.667871,0.0084,0.224349, -0.625735,0.0084,0.325553, + -0.625735,0.0084,0.325553, -0.847506,0.018225,0.440935, -0.904575,0.018225,0.303862, + -0.940158,0.018225,0.156274, -0.694143,0.0084,0.115381, -0.667871,0.0084,0.224349, + -0.667871,0.0084,0.224349, -0.904575,0.018225,0.303862, -0.940158,0.018225,0.156274, + -0.952425,0.018225,0, -0.7032,0.0084,0, -0.694143,0.0084,0.115381, + -0.694143,0.0084,0.115381, -0.940158,0.018225,0.156274, -0.952425,0.018225,0, + -0.187642,0.0312,1.12887, -0.156274,0.018225,0.940158, 0,0.018225,0.952425, + 0,0.018225,0.952425, 0,0.0312,1.1436, -0.187642,0.0312,1.12887, + -0.364854,0.0312,1.086146, -0.303862,0.018225,0.904575, -0.156274,0.018225,0.940158, + -0.156274,0.018225,0.940158, -0.187642,0.0312,1.12887, -0.364854,0.0312,1.086146, + -0.529441,0.0312,1.017621, -0.440935,0.018225,0.847506, -0.303862,0.018225,0.904575, + -0.303862,0.018225,0.904575, -0.364854,0.0312,1.086146, -0.529441,0.0312,1.017621, + -0.679207,0.0312,0.925493, -0.565664,0.018225,0.770779, -0.440935,0.018225,0.847506, + -0.440935,0.018225,0.847506, -0.529441,0.0312,1.017621, -0.679207,0.0312,0.925493, + -0.811956,0.0312,0.811956, -0.676222,0.018225,0.676222, -0.565664,0.018225,0.770779, + -0.565664,0.018225,0.770779, -0.679207,0.0312,0.925493, -0.811956,0.0312,0.811956, + -0.925493,0.0312,0.679207, -0.770779,0.018225,0.565664, -0.676222,0.018225,0.676222, + -0.676222,0.018225,0.676222, -0.811956,0.0312,0.811956, -0.925493,0.0312,0.679207, + -1.017621,0.0312,0.529441, -0.847506,0.018225,0.440935, -0.770779,0.018225,0.565664, + -0.770779,0.018225,0.565664, -0.925493,0.0312,0.679207, -1.017621,0.0312,0.529441, + -1.086146,0.0312,0.364854, -0.904575,0.018225,0.303862, -0.847506,0.018225,0.440935, + -0.847506,0.018225,0.440935, -1.017621,0.0312,0.529441, -1.086146,0.0312,0.364854, + -1.12887,0.0312,0.187642, -0.940158,0.018225,0.156274, -0.904575,0.018225,0.303862, + -0.904575,0.018225,0.303862, -1.086146,0.0312,0.364854, -1.12887,0.0312,0.187642, + -1.1436,0.0312,0, -0.952425,0.018225,0, -0.940158,0.018225,0.156274, + -0.940158,0.018225,0.156274, -1.12887,0.0312,0.187642, -1.1436,0.0312,0, + -0.21074,0.046875,1.267832, -0.187642,0.0312,1.12887, 0,0.0312,1.1436, + 0,0.0312,1.1436, 0,0.046875,1.284375, -0.21074,0.046875,1.267832, + -0.409767,0.046875,1.219848, -0.364854,0.0312,1.086146, -0.187642,0.0312,1.12887, + -0.187642,0.0312,1.12887, -0.21074,0.046875,1.267832, -0.409767,0.046875,1.219848, + -0.594614,0.046875,1.142888, -0.529441,0.0312,1.017621, -0.364854,0.0312,1.086146, + -0.364854,0.0312,1.086146, -0.409767,0.046875,1.219848, -0.594614,0.046875,1.142888, + -0.762816,0.046875,1.039419, -0.679207,0.0312,0.925493, -0.529441,0.0312,1.017621, + -0.529441,0.0312,1.017621, -0.594614,0.046875,1.142888, -0.762816,0.046875,1.039419, + -0.911906,0.046875,0.911906, -0.811956,0.0312,0.811956, -0.679207,0.0312,0.925493, + -0.679207,0.0312,0.925493, -0.762816,0.046875,1.039419, -0.911906,0.046875,0.911906, + -1.039419,0.046875,0.762816, -0.925493,0.0312,0.679207, -0.811956,0.0312,0.811956, + -0.811956,0.0312,0.811956, -0.911906,0.046875,0.911906, -1.039419,0.046875,0.762816, + -1.142888,0.046875,0.594614, -1.017621,0.0312,0.529441, -0.925493,0.0312,0.679207, + -0.925493,0.0312,0.679207, -1.039419,0.046875,0.762816, -1.142888,0.046875,0.594614, + -1.219848,0.046875,0.409767, -1.086146,0.0312,0.364854, -1.017621,0.0312,0.529441, + -1.017621,0.0312,0.529441, -1.142888,0.046875,0.594614, -1.219848,0.046875,0.409767, + -1.267832,0.046875,0.21074, -1.12887,0.0312,0.187642, -1.086146,0.0312,0.364854, + -1.086146,0.0312,0.364854, -1.219848,0.046875,0.409767, -1.267832,0.046875,0.21074, + -1.284375,0.046875,0, -1.1436,0.0312,0, -1.12887,0.0312,0.187642, + -1.12887,0.0312,0.187642, -1.267832,0.046875,0.21074, -1.284375,0.046875,0, + -0.226824,0.0648,1.364595, -0.21074,0.046875,1.267832, 0,0.046875,1.284375, + 0,0.046875,1.284375, 0,0.0648,1.3824, -0.226824,0.0648,1.364595, + -0.441041,0.0648,1.312948, -0.409767,0.046875,1.219848, -0.21074,0.046875,1.267832, + -0.21074,0.046875,1.267832, -0.226824,0.0648,1.364595, -0.441041,0.0648,1.312948, + -0.639996,0.0648,1.230115, -0.594614,0.046875,1.142888, -0.409767,0.046875,1.219848, + -0.409767,0.046875,1.219848, -0.441041,0.0648,1.312948, -0.639996,0.0648,1.230115, + -0.821035,0.0648,1.118749, -0.762816,0.046875,1.039419, -0.594614,0.046875,1.142888, + -0.594614,0.046875,1.142888, -0.639996,0.0648,1.230115, -0.821035,0.0648,1.118749, + -0.981504,0.0648,0.981504, -0.911906,0.046875,0.911906, -0.762816,0.046875,1.039419, + -0.762816,0.046875,1.039419, -0.821035,0.0648,1.118749, -0.981504,0.0648,0.981504, + -1.118749,0.0648,0.821035, -1.039419,0.046875,0.762816, -0.911906,0.046875,0.911906, + -0.911906,0.046875,0.911906, -0.981504,0.0648,0.981504, -1.118749,0.0648,0.821035, + -1.230115,0.0648,0.639996, -1.142888,0.046875,0.594614, -1.039419,0.046875,0.762816, + -1.039419,0.046875,0.762816, -1.118749,0.0648,0.821035, -1.230115,0.0648,0.639996, + -1.312948,0.0648,0.441041, -1.219848,0.046875,0.409767, -1.142888,0.046875,0.594614, + -1.142888,0.046875,0.594614, -1.230115,0.0648,0.639996, -1.312948,0.0648,0.441041, + -1.364595,0.0648,0.226824, -1.267832,0.046875,0.21074, -1.219848,0.046875,0.409767, + -1.219848,0.046875,0.409767, -1.312948,0.0648,0.441041, -1.364595,0.0648,0.226824, + -1.3824,0.0648,0, -1.284375,0.046875,0, -1.267832,0.046875,0.21074, + -1.267832,0.046875,0.21074, -1.364595,0.0648,0.226824, -1.3824,0.0648,0, + -0.237149,0.084525,1.426709, -0.226824,0.0648,1.364595, 0,0.0648,1.3824, + 0,0.0648,1.3824, 0,0.084525,1.445325, -0.237149,0.084525,1.426709, + -0.461116,0.084525,1.372712, -0.441041,0.0648,1.312948, -0.226824,0.0648,1.364595, + -0.226824,0.0648,1.364595, -0.237149,0.084525,1.426709, -0.461116,0.084525,1.372712, + -0.669128,0.084525,1.286108, -0.639996,0.0648,1.230115, -0.441041,0.0648,1.312948, + -0.441041,0.0648,1.312948, -0.461116,0.084525,1.372712, -0.669128,0.084525,1.286108, + -0.858407,0.084525,1.169673, -0.821035,0.0648,1.118749, -0.639996,0.0648,1.230115, + -0.639996,0.0648,1.230115, -0.669128,0.084525,1.286108, -0.858407,0.084525,1.169673, + -1.026181,0.084525,1.026181, -0.981504,0.0648,0.981504, -0.821035,0.0648,1.118749, + -0.821035,0.0648,1.118749, -0.858407,0.084525,1.169673, -1.026181,0.084525,1.026181, + -1.169673,0.084525,0.858407, -1.118749,0.0648,0.821035, -0.981504,0.0648,0.981504, + -0.981504,0.0648,0.981504, -1.026181,0.084525,1.026181, -1.169673,0.084525,0.858407, + -1.286108,0.084525,0.669128, -1.230115,0.0648,0.639996, -1.118749,0.0648,0.821035, + -1.118749,0.0648,0.821035, -1.169673,0.084525,0.858407, -1.286108,0.084525,0.669128, + -1.372712,0.084525,0.461116, -1.312948,0.0648,0.441041, -1.230115,0.0648,0.639996, + -1.230115,0.0648,0.639996, -1.286108,0.084525,0.669128, -1.372712,0.084525,0.461116, + -1.426709,0.084525,0.237149, -1.364595,0.0648,0.226824, -1.312948,0.0648,0.441041, + -1.312948,0.0648,0.441041, -1.372712,0.084525,0.461116, -1.426709,0.084525,0.237149, + -1.445325,0.084525,0, -1.3824,0.0648,0, -1.364595,0.0648,0.226824, + -1.364595,0.0648,0.226824, -1.426709,0.084525,0.237149, -1.445325,0.084525,0, + -0.24297,0.1056,1.461727, -0.237149,0.084525,1.426709, 0,0.084525,1.445325, + 0,0.084525,1.445325, 0,0.1056,1.4808, -0.24297,0.1056,1.461727, + -0.472434,0.1056,1.406405, -0.461116,0.084525,1.372712, -0.237149,0.084525,1.426709, + -0.237149,0.084525,1.426709, -0.24297,0.1056,1.461727, -0.472434,0.1056,1.406405, + -0.685551,0.1056,1.317675, -0.669128,0.084525,1.286108, -0.461116,0.084525,1.372712, + -0.461116,0.084525,1.372712, -0.472434,0.1056,1.406405, -0.685551,0.1056,1.317675, + -0.879477,0.1056,1.198382, -0.858407,0.084525,1.169673, -0.669128,0.084525,1.286108, + -0.669128,0.084525,1.286108, -0.685551,0.1056,1.317675, -0.879477,0.1056,1.198382, + -1.051368,0.1056,1.051368, -1.026181,0.084525,1.026181, -0.858407,0.084525,1.169673, + -0.858407,0.084525,1.169673, -0.879477,0.1056,1.198382, -1.051368,0.1056,1.051368, + -1.198382,0.1056,0.879477, -1.169673,0.084525,0.858407, -1.026181,0.084525,1.026181, + -1.026181,0.084525,1.026181, -1.051368,0.1056,1.051368, -1.198382,0.1056,0.879477, + -1.317675,0.1056,0.685551, -1.286108,0.084525,0.669128, -1.169673,0.084525,0.858407, + -1.169673,0.084525,0.858407, -1.198382,0.1056,0.879477, -1.317675,0.1056,0.685551, + -1.406405,0.1056,0.472434, -1.372712,0.084525,0.461116, -1.286108,0.084525,0.669128, + -1.286108,0.084525,0.669128, -1.317675,0.1056,0.685551, -1.406405,0.1056,0.472434, + -1.461727,0.1056,0.24297, -1.426709,0.084525,0.237149, -1.372712,0.084525,0.461116, + -1.372712,0.084525,0.461116, -1.406405,0.1056,0.472434, -1.461727,0.1056,0.24297, + -1.4808,0.1056,0, -1.445325,0.084525,0, -1.426709,0.084525,0.237149, + -1.426709,0.084525,0.237149, -1.461727,0.1056,0.24297, -1.4808,0.1056,0, + -0.245542,0.127575,1.4772, -0.24297,0.1056,1.461727, 0,0.1056,1.4808, + 0,0.1056,1.4808, 0,0.127575,1.496475, -0.245542,0.127575,1.4772, + -0.477435,0.127575,1.421292, -0.472434,0.1056,1.406405, -0.24297,0.1056,1.461727, + -0.24297,0.1056,1.461727, -0.245542,0.127575,1.4772, -0.477435,0.127575,1.421292, + -0.692808,0.127575,1.331623, -0.685551,0.1056,1.317675, -0.472434,0.1056,1.406405, + -0.472434,0.1056,1.406405, -0.477435,0.127575,1.421292, -0.692808,0.127575,1.331623, + -0.888786,0.127575,1.211067, -0.879477,0.1056,1.198382, -0.685551,0.1056,1.317675, + -0.685551,0.1056,1.317675, -0.692808,0.127575,1.331623, -0.888786,0.127575,1.211067, + -1.062497,0.127575,1.062497, -1.051368,0.1056,1.051368, -0.879477,0.1056,1.198382, + -0.879477,0.1056,1.198382, -0.888786,0.127575,1.211067, -1.062497,0.127575,1.062497, + -1.211067,0.127575,0.888786, -1.198382,0.1056,0.879477, -1.051368,0.1056,1.051368, + -1.051368,0.1056,1.051368, -1.062497,0.127575,1.062497, -1.211067,0.127575,0.888786, + -1.331623,0.127575,0.692808, -1.317675,0.1056,0.685551, -1.198382,0.1056,0.879477, + -1.198382,0.1056,0.879477, -1.211067,0.127575,0.888786, -1.331623,0.127575,0.692808, + -1.421292,0.127575,0.477435, -1.406405,0.1056,0.472434, -1.317675,0.1056,0.685551, + -1.317675,0.1056,0.685551, -1.331623,0.127575,0.692808, -1.421292,0.127575,0.477435, + -1.4772,0.127575,0.245542, -1.461727,0.1056,0.24297, -1.406405,0.1056,0.472434, + -1.406405,0.1056,0.472434, -1.421292,0.127575,0.477435, -1.4772,0.127575,0.245542, + -1.496475,0.127575,0, -1.4808,0.1056,0, -1.461727,0.1056,0.24297, + -1.461727,0.1056,0.24297, -1.4772,0.127575,0.245542, -1.496475,0.127575,0, + -0.24612,0.15,1.48068, -0.245542,0.127575,1.4772, 0,0.127575,1.496475, + 0,0.127575,1.496475, 0,0.15,1.5, -0.24612,0.15,1.48068, + -0.47856,0.15,1.42464, -0.477435,0.127575,1.421292, -0.245542,0.127575,1.4772, + -0.245542,0.127575,1.4772, -0.24612,0.15,1.48068, -0.47856,0.15,1.42464, + -0.69444,0.15,1.33476, -0.692808,0.127575,1.331623, -0.477435,0.127575,1.421292, + -0.477435,0.127575,1.421292, -0.47856,0.15,1.42464, -0.69444,0.15,1.33476, + -0.89088,0.15,1.21392, -0.888786,0.127575,1.211067, -0.692808,0.127575,1.331623, + -0.692808,0.127575,1.331623, -0.69444,0.15,1.33476, -0.89088,0.15,1.21392, + -1.065,0.15,1.065, -1.062497,0.127575,1.062497, -0.888786,0.127575,1.211067, + -0.888786,0.127575,1.211067, -0.89088,0.15,1.21392, -1.065,0.15,1.065, + -1.21392,0.15,0.89088, -1.211067,0.127575,0.888786, -1.062497,0.127575,1.062497, + -1.062497,0.127575,1.062497, -1.065,0.15,1.065, -1.21392,0.15,0.89088, + -1.33476,0.15,0.69444, -1.331623,0.127575,0.692808, -1.211067,0.127575,0.888786, + -1.211067,0.127575,0.888786, -1.21392,0.15,0.89088, -1.33476,0.15,0.69444, + -1.42464,0.15,0.47856, -1.421292,0.127575,0.477435, -1.331623,0.127575,0.692808, + -1.331623,0.127575,0.692808, -1.33476,0.15,0.69444, -1.42464,0.15,0.47856, + -1.48068,0.15,0.24612, -1.4772,0.127575,0.245542, -1.421292,0.127575,0.477435, + -1.421292,0.127575,0.477435, -1.42464,0.15,0.47856, -1.48068,0.15,0.24612, + -1.5,0.15,0, -1.496475,0.127575,0, -1.4772,0.127575,0.245542, + -1.4772,0.127575,0.245542, -1.48068,0.15,0.24612, -1.5,0.15,0, + 0,0,0, -0.388275,0.002175,0, -0.383274,0.002175,-0.063708, + 0,0,0, -0.383274,0.002175,-0.063708, -0.368768,0.002175,-0.123875, + 0,0,0, -0.368768,0.002175,-0.123875, -0.345503,0.002175,-0.179756, + 0,0,0, -0.345503,0.002175,-0.179756, -0.314223,0.002175,-0.230604, + 0,0,0, -0.314223,0.002175,-0.230604, -0.275675,0.002175,-0.275675, + 0,0,0, -0.275675,0.002175,-0.275675, -0.230604,0.002175,-0.314223, + 0,0,0, -0.230604,0.002175,-0.314223, -0.179756,0.002175,-0.345503, + 0,0,0, -0.179756,0.002175,-0.345503, -0.123875,0.002175,-0.368768, + 0,0,0, -0.123875,0.002175,-0.368768, -0.063708,0.002175,-0.383274, + 0,0,0, -0.063708,0.002175,-0.383274, 0,0.002175,-0.388275, + -0.694143,0.0084,-0.115381, -0.383274,0.002175,-0.063708, -0.388275,0.002175,0, + -0.388275,0.002175,0, -0.7032,0.0084,0, -0.694143,0.0084,-0.115381, + -0.667871,0.0084,-0.224349, -0.368768,0.002175,-0.123875, -0.383274,0.002175,-0.063708, + -0.383274,0.002175,-0.063708, -0.694143,0.0084,-0.115381, -0.667871,0.0084,-0.224349, + -0.625735,0.0084,-0.325553, -0.345503,0.002175,-0.179756, -0.368768,0.002175,-0.123875, + -0.368768,0.002175,-0.123875, -0.667871,0.0084,-0.224349, -0.625735,0.0084,-0.325553, + -0.569086,0.0084,-0.417645, -0.314223,0.002175,-0.230604, -0.345503,0.002175,-0.179756, + -0.345503,0.002175,-0.179756, -0.625735,0.0084,-0.325553, -0.569086,0.0084,-0.417645, + -0.499272,0.0084,-0.499272, -0.275675,0.002175,-0.275675, -0.314223,0.002175,-0.230604, + -0.314223,0.002175,-0.230604, -0.569086,0.0084,-0.417645, -0.499272,0.0084,-0.499272, + -0.417645,0.0084,-0.569086, -0.230604,0.002175,-0.314223, -0.275675,0.002175,-0.275675, + -0.275675,0.002175,-0.275675, -0.499272,0.0084,-0.499272, -0.417645,0.0084,-0.569086, + -0.325553,0.0084,-0.625735, -0.179756,0.002175,-0.345503, -0.230604,0.002175,-0.314223, + -0.230604,0.002175,-0.314223, -0.417645,0.0084,-0.569086, -0.325553,0.0084,-0.625735, + -0.224349,0.0084,-0.667871, -0.123875,0.002175,-0.368768, -0.179756,0.002175,-0.345503, + -0.179756,0.002175,-0.345503, -0.325553,0.0084,-0.625735, -0.224349,0.0084,-0.667871, + -0.115381,0.0084,-0.694143, -0.063708,0.002175,-0.383274, -0.123875,0.002175,-0.368768, + -0.123875,0.002175,-0.368768, -0.224349,0.0084,-0.667871, -0.115381,0.0084,-0.694143, + 0,0.0084,-0.7032, 0,0.002175,-0.388275, -0.063708,0.002175,-0.383274, + -0.063708,0.002175,-0.383274, -0.115381,0.0084,-0.694143, 0,0.0084,-0.7032, + -0.940158,0.018225,-0.156274, -0.694143,0.0084,-0.115381, -0.7032,0.0084,0, + -0.7032,0.0084,0, -0.952425,0.018225,0, -0.940158,0.018225,-0.156274, + -0.904575,0.018225,-0.303862, -0.667871,0.0084,-0.224349, -0.694143,0.0084,-0.115381, + -0.694143,0.0084,-0.115381, -0.940158,0.018225,-0.156274, -0.904575,0.018225,-0.303862, + -0.847506,0.018225,-0.440935, -0.625735,0.0084,-0.325553, -0.667871,0.0084,-0.224349, + -0.667871,0.0084,-0.224349, -0.904575,0.018225,-0.303862, -0.847506,0.018225,-0.440935, + -0.770779,0.018225,-0.565664, -0.569086,0.0084,-0.417645, -0.625735,0.0084,-0.325553, + -0.625735,0.0084,-0.325553, -0.847506,0.018225,-0.440935, -0.770779,0.018225,-0.565664, + -0.676222,0.018225,-0.676222, -0.499272,0.0084,-0.499272, -0.569086,0.0084,-0.417645, + -0.569086,0.0084,-0.417645, -0.770779,0.018225,-0.565664, -0.676222,0.018225,-0.676222, + -0.565664,0.018225,-0.770779, -0.417645,0.0084,-0.569086, -0.499272,0.0084,-0.499272, + -0.499272,0.0084,-0.499272, -0.676222,0.018225,-0.676222, -0.565664,0.018225,-0.770779, + -0.440935,0.018225,-0.847506, -0.325553,0.0084,-0.625735, -0.417645,0.0084,-0.569086, + -0.417645,0.0084,-0.569086, -0.565664,0.018225,-0.770779, -0.440935,0.018225,-0.847506, + -0.303862,0.018225,-0.904575, -0.224349,0.0084,-0.667871, -0.325553,0.0084,-0.625735, + -0.325553,0.0084,-0.625735, -0.440935,0.018225,-0.847506, -0.303862,0.018225,-0.904575, + -0.156274,0.018225,-0.940158, -0.115381,0.0084,-0.694143, -0.224349,0.0084,-0.667871, + -0.224349,0.0084,-0.667871, -0.303862,0.018225,-0.904575, -0.156274,0.018225,-0.940158, + 0,0.018225,-0.952425, 0,0.0084,-0.7032, -0.115381,0.0084,-0.694143, + -0.115381,0.0084,-0.694143, -0.156274,0.018225,-0.940158, 0,0.018225,-0.952425, + -1.12887,0.0312,-0.187642, -0.940158,0.018225,-0.156274, -0.952425,0.018225,0, + -0.952425,0.018225,0, -1.1436,0.0312,0, -1.12887,0.0312,-0.187642, + -1.086146,0.0312,-0.364854, -0.904575,0.018225,-0.303862, -0.940158,0.018225,-0.156274, + -0.940158,0.018225,-0.156274, -1.12887,0.0312,-0.187642, -1.086146,0.0312,-0.364854, + -1.017621,0.0312,-0.529441, -0.847506,0.018225,-0.440935, -0.904575,0.018225,-0.303862, + -0.904575,0.018225,-0.303862, -1.086146,0.0312,-0.364854, -1.017621,0.0312,-0.529441, + -0.925493,0.0312,-0.679207, -0.770779,0.018225,-0.565664, -0.847506,0.018225,-0.440935, + -0.847506,0.018225,-0.440935, -1.017621,0.0312,-0.529441, -0.925493,0.0312,-0.679207, + -0.811956,0.0312,-0.811956, -0.676222,0.018225,-0.676222, -0.770779,0.018225,-0.565664, + -0.770779,0.018225,-0.565664, -0.925493,0.0312,-0.679207, -0.811956,0.0312,-0.811956, + -0.679207,0.0312,-0.925493, -0.565664,0.018225,-0.770779, -0.676222,0.018225,-0.676222, + -0.676222,0.018225,-0.676222, -0.811956,0.0312,-0.811956, -0.679207,0.0312,-0.925493, + -0.529441,0.0312,-1.017621, -0.440935,0.018225,-0.847506, -0.565664,0.018225,-0.770779, + -0.565664,0.018225,-0.770779, -0.679207,0.0312,-0.925493, -0.529441,0.0312,-1.017621, + -0.364854,0.0312,-1.086146, -0.303862,0.018225,-0.904575, -0.440935,0.018225,-0.847506, + -0.440935,0.018225,-0.847506, -0.529441,0.0312,-1.017621, -0.364854,0.0312,-1.086146, + -0.187642,0.0312,-1.12887, -0.156274,0.018225,-0.940158, -0.303862,0.018225,-0.904575, + -0.303862,0.018225,-0.904575, -0.364854,0.0312,-1.086146, -0.187642,0.0312,-1.12887, + 0,0.0312,-1.1436, 0,0.018225,-0.952425, -0.156274,0.018225,-0.940158, + -0.156274,0.018225,-0.940158, -0.187642,0.0312,-1.12887, 0,0.0312,-1.1436, + -1.267832,0.046875,-0.21074, -1.12887,0.0312,-0.187642, -1.1436,0.0312,0, + -1.1436,0.0312,0, -1.284375,0.046875,0, -1.267832,0.046875,-0.21074, + -1.219848,0.046875,-0.409767, -1.086146,0.0312,-0.364854, -1.12887,0.0312,-0.187642, + -1.12887,0.0312,-0.187642, -1.267832,0.046875,-0.21074, -1.219848,0.046875,-0.409767, + -1.142888,0.046875,-0.594614, -1.017621,0.0312,-0.529441, -1.086146,0.0312,-0.364854, + -1.086146,0.0312,-0.364854, -1.219848,0.046875,-0.409767, -1.142888,0.046875,-0.594614, + -1.039419,0.046875,-0.762816, -0.925493,0.0312,-0.679207, -1.017621,0.0312,-0.529441, + -1.017621,0.0312,-0.529441, -1.142888,0.046875,-0.594614, -1.039419,0.046875,-0.762816, + -0.911906,0.046875,-0.911906, -0.811956,0.0312,-0.811956, -0.925493,0.0312,-0.679207, + -0.925493,0.0312,-0.679207, -1.039419,0.046875,-0.762816, -0.911906,0.046875,-0.911906, + -0.762816,0.046875,-1.039419, -0.679207,0.0312,-0.925493, -0.811956,0.0312,-0.811956, + -0.811956,0.0312,-0.811956, -0.911906,0.046875,-0.911906, -0.762816,0.046875,-1.039419, + -0.594614,0.046875,-1.142888, -0.529441,0.0312,-1.017621, -0.679207,0.0312,-0.925493, + -0.679207,0.0312,-0.925493, -0.762816,0.046875,-1.039419, -0.594614,0.046875,-1.142888, + -0.409767,0.046875,-1.219848, -0.364854,0.0312,-1.086146, -0.529441,0.0312,-1.017621, + -0.529441,0.0312,-1.017621, -0.594614,0.046875,-1.142888, -0.409767,0.046875,-1.219848, + -0.21074,0.046875,-1.267832, -0.187642,0.0312,-1.12887, -0.364854,0.0312,-1.086146, + -0.364854,0.0312,-1.086146, -0.409767,0.046875,-1.219848, -0.21074,0.046875,-1.267832, + 0,0.046875,-1.284375, 0,0.0312,-1.1436, -0.187642,0.0312,-1.12887, + -0.187642,0.0312,-1.12887, -0.21074,0.046875,-1.267832, 0,0.046875,-1.284375, + -1.364595,0.0648,-0.226824, -1.267832,0.046875,-0.21074, -1.284375,0.046875,0, + -1.284375,0.046875,0, -1.3824,0.0648,0, -1.364595,0.0648,-0.226824, + -1.312948,0.0648,-0.441041, -1.219848,0.046875,-0.409767, -1.267832,0.046875,-0.21074, + -1.267832,0.046875,-0.21074, -1.364595,0.0648,-0.226824, -1.312948,0.0648,-0.441041, + -1.230115,0.0648,-0.639996, -1.142888,0.046875,-0.594614, -1.219848,0.046875,-0.409767, + -1.219848,0.046875,-0.409767, -1.312948,0.0648,-0.441041, -1.230115,0.0648,-0.639996, + -1.118749,0.0648,-0.821035, -1.039419,0.046875,-0.762816, -1.142888,0.046875,-0.594614, + -1.142888,0.046875,-0.594614, -1.230115,0.0648,-0.639996, -1.118749,0.0648,-0.821035, + -0.981504,0.0648,-0.981504, -0.911906,0.046875,-0.911906, -1.039419,0.046875,-0.762816, + -1.039419,0.046875,-0.762816, -1.118749,0.0648,-0.821035, -0.981504,0.0648,-0.981504, + -0.821035,0.0648,-1.118749, -0.762816,0.046875,-1.039419, -0.911906,0.046875,-0.911906, + -0.911906,0.046875,-0.911906, -0.981504,0.0648,-0.981504, -0.821035,0.0648,-1.118749, + -0.639996,0.0648,-1.230115, -0.594614,0.046875,-1.142888, -0.762816,0.046875,-1.039419, + -0.762816,0.046875,-1.039419, -0.821035,0.0648,-1.118749, -0.639996,0.0648,-1.230115, + -0.441041,0.0648,-1.312948, -0.409767,0.046875,-1.219848, -0.594614,0.046875,-1.142888, + -0.594614,0.046875,-1.142888, -0.639996,0.0648,-1.230115, -0.441041,0.0648,-1.312948, + -0.226824,0.0648,-1.364595, -0.21074,0.046875,-1.267832, -0.409767,0.046875,-1.219848, + -0.409767,0.046875,-1.219848, -0.441041,0.0648,-1.312948, -0.226824,0.0648,-1.364595, + 0,0.0648,-1.3824, 0,0.046875,-1.284375, -0.21074,0.046875,-1.267832, + -0.21074,0.046875,-1.267832, -0.226824,0.0648,-1.364595, 0,0.0648,-1.3824, + -1.426709,0.084525,-0.237149, -1.364595,0.0648,-0.226824, -1.3824,0.0648,0, + -1.3824,0.0648,0, -1.445325,0.084525,0, -1.426709,0.084525,-0.237149, + -1.372712,0.084525,-0.461116, -1.312948,0.0648,-0.441041, -1.364595,0.0648,-0.226824, + -1.364595,0.0648,-0.226824, -1.426709,0.084525,-0.237149, -1.372712,0.084525,-0.461116, + -1.286108,0.084525,-0.669128, -1.230115,0.0648,-0.639996, -1.312948,0.0648,-0.441041, + -1.312948,0.0648,-0.441041, -1.372712,0.084525,-0.461116, -1.286108,0.084525,-0.669128, + -1.169673,0.084525,-0.858407, -1.118749,0.0648,-0.821035, -1.230115,0.0648,-0.639996, + -1.230115,0.0648,-0.639996, -1.286108,0.084525,-0.669128, -1.169673,0.084525,-0.858407, + -1.026181,0.084525,-1.026181, -0.981504,0.0648,-0.981504, -1.118749,0.0648,-0.821035, + -1.118749,0.0648,-0.821035, -1.169673,0.084525,-0.858407, -1.026181,0.084525,-1.026181, + -0.858407,0.084525,-1.169673, -0.821035,0.0648,-1.118749, -0.981504,0.0648,-0.981504, + -0.981504,0.0648,-0.981504, -1.026181,0.084525,-1.026181, -0.858407,0.084525,-1.169673, + -0.669128,0.084525,-1.286108, -0.639996,0.0648,-1.230115, -0.821035,0.0648,-1.118749, + -0.821035,0.0648,-1.118749, -0.858407,0.084525,-1.169673, -0.669128,0.084525,-1.286108, + -0.461116,0.084525,-1.372712, -0.441041,0.0648,-1.312948, -0.639996,0.0648,-1.230115, + -0.639996,0.0648,-1.230115, -0.669128,0.084525,-1.286108, -0.461116,0.084525,-1.372712, + -0.237149,0.084525,-1.426709, -0.226824,0.0648,-1.364595, -0.441041,0.0648,-1.312948, + -0.441041,0.0648,-1.312948, -0.461116,0.084525,-1.372712, -0.237149,0.084525,-1.426709, + 0,0.084525,-1.445325, 0,0.0648,-1.3824, -0.226824,0.0648,-1.364595, + -0.226824,0.0648,-1.364595, -0.237149,0.084525,-1.426709, 0,0.084525,-1.445325, + -1.461727,0.1056,-0.24297, -1.426709,0.084525,-0.237149, -1.445325,0.084525,0, + -1.445325,0.084525,0, -1.4808,0.1056,0, -1.461727,0.1056,-0.24297, + -1.406405,0.1056,-0.472434, -1.372712,0.084525,-0.461116, -1.426709,0.084525,-0.237149, + -1.426709,0.084525,-0.237149, -1.461727,0.1056,-0.24297, -1.406405,0.1056,-0.472434, + -1.317675,0.1056,-0.685551, -1.286108,0.084525,-0.669128, -1.372712,0.084525,-0.461116, + -1.372712,0.084525,-0.461116, -1.406405,0.1056,-0.472434, -1.317675,0.1056,-0.685551, + -1.198382,0.1056,-0.879477, -1.169673,0.084525,-0.858407, -1.286108,0.084525,-0.669128, + -1.286108,0.084525,-0.669128, -1.317675,0.1056,-0.685551, -1.198382,0.1056,-0.879477, + -1.051368,0.1056,-1.051368, -1.026181,0.084525,-1.026181, -1.169673,0.084525,-0.858407, + -1.169673,0.084525,-0.858407, -1.198382,0.1056,-0.879477, -1.051368,0.1056,-1.051368, + -0.879477,0.1056,-1.198382, -0.858407,0.084525,-1.169673, -1.026181,0.084525,-1.026181, + -1.026181,0.084525,-1.026181, -1.051368,0.1056,-1.051368, -0.879477,0.1056,-1.198382, + -0.685551,0.1056,-1.317675, -0.669128,0.084525,-1.286108, -0.858407,0.084525,-1.169673, + -0.858407,0.084525,-1.169673, -0.879477,0.1056,-1.198382, -0.685551,0.1056,-1.317675, + -0.472434,0.1056,-1.406405, -0.461116,0.084525,-1.372712, -0.669128,0.084525,-1.286108, + -0.669128,0.084525,-1.286108, -0.685551,0.1056,-1.317675, -0.472434,0.1056,-1.406405, + -0.24297,0.1056,-1.461727, -0.237149,0.084525,-1.426709, -0.461116,0.084525,-1.372712, + -0.461116,0.084525,-1.372712, -0.472434,0.1056,-1.406405, -0.24297,0.1056,-1.461727, + 0,0.1056,-1.4808, 0,0.084525,-1.445325, -0.237149,0.084525,-1.426709, + -0.237149,0.084525,-1.426709, -0.24297,0.1056,-1.461727, 0,0.1056,-1.4808, + -1.4772,0.127575,-0.245542, -1.461727,0.1056,-0.24297, -1.4808,0.1056,0, + -1.4808,0.1056,0, -1.496475,0.127575,0, -1.4772,0.127575,-0.245542, + -1.421292,0.127575,-0.477435, -1.406405,0.1056,-0.472434, -1.461727,0.1056,-0.24297, + -1.461727,0.1056,-0.24297, -1.4772,0.127575,-0.245542, -1.421292,0.127575,-0.477435, + -1.331623,0.127575,-0.692808, -1.317675,0.1056,-0.685551, -1.406405,0.1056,-0.472434, + -1.406405,0.1056,-0.472434, -1.421292,0.127575,-0.477435, -1.331623,0.127575,-0.692808, + -1.211067,0.127575,-0.888786, -1.198382,0.1056,-0.879477, -1.317675,0.1056,-0.685551, + -1.317675,0.1056,-0.685551, -1.331623,0.127575,-0.692808, -1.211067,0.127575,-0.888786, + -1.062497,0.127575,-1.062497, -1.051368,0.1056,-1.051368, -1.198382,0.1056,-0.879477, + -1.198382,0.1056,-0.879477, -1.211067,0.127575,-0.888786, -1.062497,0.127575,-1.062497, + -0.888786,0.127575,-1.211067, -0.879477,0.1056,-1.198382, -1.051368,0.1056,-1.051368, + -1.051368,0.1056,-1.051368, -1.062497,0.127575,-1.062497, -0.888786,0.127575,-1.211067, + -0.692808,0.127575,-1.331623, -0.685551,0.1056,-1.317675, -0.879477,0.1056,-1.198382, + -0.879477,0.1056,-1.198382, -0.888786,0.127575,-1.211067, -0.692808,0.127575,-1.331623, + -0.477435,0.127575,-1.421292, -0.472434,0.1056,-1.406405, -0.685551,0.1056,-1.317675, + -0.685551,0.1056,-1.317675, -0.692808,0.127575,-1.331623, -0.477435,0.127575,-1.421292, + -0.245542,0.127575,-1.4772, -0.24297,0.1056,-1.461727, -0.472434,0.1056,-1.406405, + -0.472434,0.1056,-1.406405, -0.477435,0.127575,-1.421292, -0.245542,0.127575,-1.4772, + 0,0.127575,-1.496475, 0,0.1056,-1.4808, -0.24297,0.1056,-1.461727, + -0.24297,0.1056,-1.461727, -0.245542,0.127575,-1.4772, 0,0.127575,-1.496475, + -1.48068,0.15,-0.24612, -1.4772,0.127575,-0.245542, -1.496475,0.127575,0, + -1.496475,0.127575,0, -1.5,0.15,0, -1.48068,0.15,-0.24612, + -1.42464,0.15,-0.47856, -1.421292,0.127575,-0.477435, -1.4772,0.127575,-0.245542, + -1.4772,0.127575,-0.245542, -1.48068,0.15,-0.24612, -1.42464,0.15,-0.47856, + -1.33476,0.15,-0.69444, -1.331623,0.127575,-0.692808, -1.421292,0.127575,-0.477435, + -1.421292,0.127575,-0.477435, -1.42464,0.15,-0.47856, -1.33476,0.15,-0.69444, + -1.21392,0.15,-0.89088, -1.211067,0.127575,-0.888786, -1.331623,0.127575,-0.692808, + -1.331623,0.127575,-0.692808, -1.33476,0.15,-0.69444, -1.21392,0.15,-0.89088, + -1.065,0.15,-1.065, -1.062497,0.127575,-1.062497, -1.211067,0.127575,-0.888786, + -1.211067,0.127575,-0.888786, -1.21392,0.15,-0.89088, -1.065,0.15,-1.065, + -0.89088,0.15,-1.21392, -0.888786,0.127575,-1.211067, -1.062497,0.127575,-1.062497, + -1.062497,0.127575,-1.062497, -1.065,0.15,-1.065, -0.89088,0.15,-1.21392, + -0.69444,0.15,-1.33476, -0.692808,0.127575,-1.331623, -0.888786,0.127575,-1.211067, + -0.888786,0.127575,-1.211067, -0.89088,0.15,-1.21392, -0.69444,0.15,-1.33476, + -0.47856,0.15,-1.42464, -0.477435,0.127575,-1.421292, -0.692808,0.127575,-1.331623, + -0.692808,0.127575,-1.331623, -0.69444,0.15,-1.33476, -0.47856,0.15,-1.42464, + -0.24612,0.15,-1.48068, -0.245542,0.127575,-1.4772, -0.477435,0.127575,-1.421292, + -0.477435,0.127575,-1.421292, -0.47856,0.15,-1.42464, -0.24612,0.15,-1.48068, + 0,0.15,-1.5, 0,0.127575,-1.496475, -0.245542,0.127575,-1.4772, + -0.245542,0.127575,-1.4772, -0.24612,0.15,-1.48068, 0,0.15,-1.5, + 0,0,0, 0,0.002175,-0.388275, 0.063708,0.002175,-0.383274, + 0,0,0, 0.063708,0.002175,-0.383274, 0.123875,0.002175,-0.368768, + 0,0,0, 0.123875,0.002175,-0.368768, 0.179756,0.002175,-0.345503, + 0,0,0, 0.179756,0.002175,-0.345503, 0.230604,0.002175,-0.314223, + 0,0,0, 0.230604,0.002175,-0.314223, 0.275675,0.002175,-0.275675, + 0,0,0, 0.275675,0.002175,-0.275675, 0.314223,0.002175,-0.230604, + 0,0,0, 0.314223,0.002175,-0.230604, 0.345503,0.002175,-0.179756, + 0,0,0, 0.345503,0.002175,-0.179756, 0.368768,0.002175,-0.123875, + 0,0,0, 0.368768,0.002175,-0.123875, 0.383274,0.002175,-0.063708, + 0,0,0, 0.383274,0.002175,-0.063708, 0.388275,0.002175,0, + 0.115381,0.0084,-0.694143, 0.063708,0.002175,-0.383274, 0,0.002175,-0.388275, + 0,0.002175,-0.388275, 0,0.0084,-0.7032, 0.115381,0.0084,-0.694143, + 0.224349,0.0084,-0.667871, 0.123875,0.002175,-0.368768, 0.063708,0.002175,-0.383274, + 0.063708,0.002175,-0.383274, 0.115381,0.0084,-0.694143, 0.224349,0.0084,-0.667871, + 0.325553,0.0084,-0.625735, 0.179756,0.002175,-0.345503, 0.123875,0.002175,-0.368768, + 0.123875,0.002175,-0.368768, 0.224349,0.0084,-0.667871, 0.325553,0.0084,-0.625735, + 0.417645,0.0084,-0.569086, 0.230604,0.002175,-0.314223, 0.179756,0.002175,-0.345503, + 0.179756,0.002175,-0.345503, 0.325553,0.0084,-0.625735, 0.417645,0.0084,-0.569086, + 0.499272,0.0084,-0.499272, 0.275675,0.002175,-0.275675, 0.230604,0.002175,-0.314223, + 0.230604,0.002175,-0.314223, 0.417645,0.0084,-0.569086, 0.499272,0.0084,-0.499272, + 0.569086,0.0084,-0.417645, 0.314223,0.002175,-0.230604, 0.275675,0.002175,-0.275675, + 0.275675,0.002175,-0.275675, 0.499272,0.0084,-0.499272, 0.569086,0.0084,-0.417645, + 0.625735,0.0084,-0.325553, 0.345503,0.002175,-0.179756, 0.314223,0.002175,-0.230604, + 0.314223,0.002175,-0.230604, 0.569086,0.0084,-0.417645, 0.625735,0.0084,-0.325553, + 0.667871,0.0084,-0.224349, 0.368768,0.002175,-0.123875, 0.345503,0.002175,-0.179756, + 0.345503,0.002175,-0.179756, 0.625735,0.0084,-0.325553, 0.667871,0.0084,-0.224349, + 0.694143,0.0084,-0.115381, 0.383274,0.002175,-0.063708, 0.368768,0.002175,-0.123875, + 0.368768,0.002175,-0.123875, 0.667871,0.0084,-0.224349, 0.694143,0.0084,-0.115381, + 0.7032,0.0084,0, 0.388275,0.002175,0, 0.383274,0.002175,-0.063708, + 0.383274,0.002175,-0.063708, 0.694143,0.0084,-0.115381, 0.7032,0.0084,0, + 0.156274,0.018225,-0.940158, 0.115381,0.0084,-0.694143, 0,0.0084,-0.7032, + 0,0.0084,-0.7032, 0,0.018225,-0.952425, 0.156274,0.018225,-0.940158, + 0.303862,0.018225,-0.904575, 0.224349,0.0084,-0.667871, 0.115381,0.0084,-0.694143, + 0.115381,0.0084,-0.694143, 0.156274,0.018225,-0.940158, 0.303862,0.018225,-0.904575, + 0.440935,0.018225,-0.847506, 0.325553,0.0084,-0.625735, 0.224349,0.0084,-0.667871, + 0.224349,0.0084,-0.667871, 0.303862,0.018225,-0.904575, 0.440935,0.018225,-0.847506, + 0.565664,0.018225,-0.770779, 0.417645,0.0084,-0.569086, 0.325553,0.0084,-0.625735, + 0.325553,0.0084,-0.625735, 0.440935,0.018225,-0.847506, 0.565664,0.018225,-0.770779, + 0.676222,0.018225,-0.676222, 0.499272,0.0084,-0.499272, 0.417645,0.0084,-0.569086, + 0.417645,0.0084,-0.569086, 0.565664,0.018225,-0.770779, 0.676222,0.018225,-0.676222, + 0.770779,0.018225,-0.565664, 0.569086,0.0084,-0.417645, 0.499272,0.0084,-0.499272, + 0.499272,0.0084,-0.499272, 0.676222,0.018225,-0.676222, 0.770779,0.018225,-0.565664, + 0.847506,0.018225,-0.440935, 0.625735,0.0084,-0.325553, 0.569086,0.0084,-0.417645, + 0.569086,0.0084,-0.417645, 0.770779,0.018225,-0.565664, 0.847506,0.018225,-0.440935, + 0.904575,0.018225,-0.303862, 0.667871,0.0084,-0.224349, 0.625735,0.0084,-0.325553, + 0.625735,0.0084,-0.325553, 0.847506,0.018225,-0.440935, 0.904575,0.018225,-0.303862, + 0.940158,0.018225,-0.156274, 0.694143,0.0084,-0.115381, 0.667871,0.0084,-0.224349, + 0.667871,0.0084,-0.224349, 0.904575,0.018225,-0.303862, 0.940158,0.018225,-0.156274, + 0.952425,0.018225,0, 0.7032,0.0084,0, 0.694143,0.0084,-0.115381, + 0.694143,0.0084,-0.115381, 0.940158,0.018225,-0.156274, 0.952425,0.018225,0, + 0.187642,0.0312,-1.12887, 0.156274,0.018225,-0.940158, 0,0.018225,-0.952425, + 0,0.018225,-0.952425, 0,0.0312,-1.1436, 0.187642,0.0312,-1.12887, + 0.364854,0.0312,-1.086146, 0.303862,0.018225,-0.904575, 0.156274,0.018225,-0.940158, + 0.156274,0.018225,-0.940158, 0.187642,0.0312,-1.12887, 0.364854,0.0312,-1.086146, + 0.529441,0.0312,-1.017621, 0.440935,0.018225,-0.847506, 0.303862,0.018225,-0.904575, + 0.303862,0.018225,-0.904575, 0.364854,0.0312,-1.086146, 0.529441,0.0312,-1.017621, + 0.679207,0.0312,-0.925493, 0.565664,0.018225,-0.770779, 0.440935,0.018225,-0.847506, + 0.440935,0.018225,-0.847506, 0.529441,0.0312,-1.017621, 0.679207,0.0312,-0.925493, + 0.811956,0.0312,-0.811956, 0.676222,0.018225,-0.676222, 0.565664,0.018225,-0.770779, + 0.565664,0.018225,-0.770779, 0.679207,0.0312,-0.925493, 0.811956,0.0312,-0.811956, + 0.925493,0.0312,-0.679207, 0.770779,0.018225,-0.565664, 0.676222,0.018225,-0.676222, + 0.676222,0.018225,-0.676222, 0.811956,0.0312,-0.811956, 0.925493,0.0312,-0.679207, + 1.017621,0.0312,-0.529441, 0.847506,0.018225,-0.440935, 0.770779,0.018225,-0.565664, + 0.770779,0.018225,-0.565664, 0.925493,0.0312,-0.679207, 1.017621,0.0312,-0.529441, + 1.086146,0.0312,-0.364854, 0.904575,0.018225,-0.303862, 0.847506,0.018225,-0.440935, + 0.847506,0.018225,-0.440935, 1.017621,0.0312,-0.529441, 1.086146,0.0312,-0.364854, + 1.12887,0.0312,-0.187642, 0.940158,0.018225,-0.156274, 0.904575,0.018225,-0.303862, + 0.904575,0.018225,-0.303862, 1.086146,0.0312,-0.364854, 1.12887,0.0312,-0.187642, + 1.1436,0.0312,0, 0.952425,0.018225,0, 0.940158,0.018225,-0.156274, + 0.940158,0.018225,-0.156274, 1.12887,0.0312,-0.187642, 1.1436,0.0312,0, + 0.21074,0.046875,-1.267832, 0.187642,0.0312,-1.12887, 0,0.0312,-1.1436, + 0,0.0312,-1.1436, 0,0.046875,-1.284375, 0.21074,0.046875,-1.267832, + 0.409767,0.046875,-1.219848, 0.364854,0.0312,-1.086146, 0.187642,0.0312,-1.12887, + 0.187642,0.0312,-1.12887, 0.21074,0.046875,-1.267832, 0.409767,0.046875,-1.219848, + 0.594614,0.046875,-1.142888, 0.529441,0.0312,-1.017621, 0.364854,0.0312,-1.086146, + 0.364854,0.0312,-1.086146, 0.409767,0.046875,-1.219848, 0.594614,0.046875,-1.142888, + 0.762816,0.046875,-1.039419, 0.679207,0.0312,-0.925493, 0.529441,0.0312,-1.017621, + 0.529441,0.0312,-1.017621, 0.594614,0.046875,-1.142888, 0.762816,0.046875,-1.039419, + 0.911906,0.046875,-0.911906, 0.811956,0.0312,-0.811956, 0.679207,0.0312,-0.925493, + 0.679207,0.0312,-0.925493, 0.762816,0.046875,-1.039419, 0.911906,0.046875,-0.911906, + 1.039419,0.046875,-0.762816, 0.925493,0.0312,-0.679207, 0.811956,0.0312,-0.811956, + 0.811956,0.0312,-0.811956, 0.911906,0.046875,-0.911906, 1.039419,0.046875,-0.762816, + 1.142888,0.046875,-0.594614, 1.017621,0.0312,-0.529441, 0.925493,0.0312,-0.679207, + 0.925493,0.0312,-0.679207, 1.039419,0.046875,-0.762816, 1.142888,0.046875,-0.594614, + 1.219848,0.046875,-0.409767, 1.086146,0.0312,-0.364854, 1.017621,0.0312,-0.529441, + 1.017621,0.0312,-0.529441, 1.142888,0.046875,-0.594614, 1.219848,0.046875,-0.409767, + 1.267832,0.046875,-0.21074, 1.12887,0.0312,-0.187642, 1.086146,0.0312,-0.364854, + 1.086146,0.0312,-0.364854, 1.219848,0.046875,-0.409767, 1.267832,0.046875,-0.21074, + 1.284375,0.046875,0, 1.1436,0.0312,0, 1.12887,0.0312,-0.187642, + 1.12887,0.0312,-0.187642, 1.267832,0.046875,-0.21074, 1.284375,0.046875,0, + 0.226824,0.0648,-1.364595, 0.21074,0.046875,-1.267832, 0,0.046875,-1.284375, + 0,0.046875,-1.284375, 0,0.0648,-1.3824, 0.226824,0.0648,-1.364595, + 0.441041,0.0648,-1.312948, 0.409767,0.046875,-1.219848, 0.21074,0.046875,-1.267832, + 0.21074,0.046875,-1.267832, 0.226824,0.0648,-1.364595, 0.441041,0.0648,-1.312948, + 0.639996,0.0648,-1.230115, 0.594614,0.046875,-1.142888, 0.409767,0.046875,-1.219848, + 0.409767,0.046875,-1.219848, 0.441041,0.0648,-1.312948, 0.639996,0.0648,-1.230115, + 0.821035,0.0648,-1.118749, 0.762816,0.046875,-1.039419, 0.594614,0.046875,-1.142888, + 0.594614,0.046875,-1.142888, 0.639996,0.0648,-1.230115, 0.821035,0.0648,-1.118749, + 0.981504,0.0648,-0.981504, 0.911906,0.046875,-0.911906, 0.762816,0.046875,-1.039419, + 0.762816,0.046875,-1.039419, 0.821035,0.0648,-1.118749, 0.981504,0.0648,-0.981504, + 1.118749,0.0648,-0.821035, 1.039419,0.046875,-0.762816, 0.911906,0.046875,-0.911906, + 0.911906,0.046875,-0.911906, 0.981504,0.0648,-0.981504, 1.118749,0.0648,-0.821035, + 1.230115,0.0648,-0.639996, 1.142888,0.046875,-0.594614, 1.039419,0.046875,-0.762816, + 1.039419,0.046875,-0.762816, 1.118749,0.0648,-0.821035, 1.230115,0.0648,-0.639996, + 1.312948,0.0648,-0.441041, 1.219848,0.046875,-0.409767, 1.142888,0.046875,-0.594614, + 1.142888,0.046875,-0.594614, 1.230115,0.0648,-0.639996, 1.312948,0.0648,-0.441041, + 1.364595,0.0648,-0.226824, 1.267832,0.046875,-0.21074, 1.219848,0.046875,-0.409767, + 1.219848,0.046875,-0.409767, 1.312948,0.0648,-0.441041, 1.364595,0.0648,-0.226824, + 1.3824,0.0648,0, 1.284375,0.046875,0, 1.267832,0.046875,-0.21074, + 1.267832,0.046875,-0.21074, 1.364595,0.0648,-0.226824, 1.3824,0.0648,0, + 0.237149,0.084525,-1.426709, 0.226824,0.0648,-1.364595, 0,0.0648,-1.3824, + 0,0.0648,-1.3824, 0,0.084525,-1.445325, 0.237149,0.084525,-1.426709, + 0.461116,0.084525,-1.372712, 0.441041,0.0648,-1.312948, 0.226824,0.0648,-1.364595, + 0.226824,0.0648,-1.364595, 0.237149,0.084525,-1.426709, 0.461116,0.084525,-1.372712, + 0.669128,0.084525,-1.286108, 0.639996,0.0648,-1.230115, 0.441041,0.0648,-1.312948, + 0.441041,0.0648,-1.312948, 0.461116,0.084525,-1.372712, 0.669128,0.084525,-1.286108, + 0.858407,0.084525,-1.169673, 0.821035,0.0648,-1.118749, 0.639996,0.0648,-1.230115, + 0.639996,0.0648,-1.230115, 0.669128,0.084525,-1.286108, 0.858407,0.084525,-1.169673, + 1.026181,0.084525,-1.026181, 0.981504,0.0648,-0.981504, 0.821035,0.0648,-1.118749, + 0.821035,0.0648,-1.118749, 0.858407,0.084525,-1.169673, 1.026181,0.084525,-1.026181, + 1.169673,0.084525,-0.858407, 1.118749,0.0648,-0.821035, 0.981504,0.0648,-0.981504, + 0.981504,0.0648,-0.981504, 1.026181,0.084525,-1.026181, 1.169673,0.084525,-0.858407, + 1.286108,0.084525,-0.669128, 1.230115,0.0648,-0.639996, 1.118749,0.0648,-0.821035, + 1.118749,0.0648,-0.821035, 1.169673,0.084525,-0.858407, 1.286108,0.084525,-0.669128, + 1.372712,0.084525,-0.461116, 1.312948,0.0648,-0.441041, 1.230115,0.0648,-0.639996, + 1.230115,0.0648,-0.639996, 1.286108,0.084525,-0.669128, 1.372712,0.084525,-0.461116, + 1.426709,0.084525,-0.237149, 1.364595,0.0648,-0.226824, 1.312948,0.0648,-0.441041, + 1.312948,0.0648,-0.441041, 1.372712,0.084525,-0.461116, 1.426709,0.084525,-0.237149, + 1.445325,0.084525,0, 1.3824,0.0648,0, 1.364595,0.0648,-0.226824, + 1.364595,0.0648,-0.226824, 1.426709,0.084525,-0.237149, 1.445325,0.084525,0, + 0.24297,0.1056,-1.461727, 0.237149,0.084525,-1.426709, 0,0.084525,-1.445325, + 0,0.084525,-1.445325, 0,0.1056,-1.4808, 0.24297,0.1056,-1.461727, + 0.472434,0.1056,-1.406405, 0.461116,0.084525,-1.372712, 0.237149,0.084525,-1.426709, + 0.237149,0.084525,-1.426709, 0.24297,0.1056,-1.461727, 0.472434,0.1056,-1.406405, + 0.685551,0.1056,-1.317675, 0.669128,0.084525,-1.286108, 0.461116,0.084525,-1.372712, + 0.461116,0.084525,-1.372712, 0.472434,0.1056,-1.406405, 0.685551,0.1056,-1.317675, + 0.879477,0.1056,-1.198382, 0.858407,0.084525,-1.169673, 0.669128,0.084525,-1.286108, + 0.669128,0.084525,-1.286108, 0.685551,0.1056,-1.317675, 0.879477,0.1056,-1.198382, + 1.051368,0.1056,-1.051368, 1.026181,0.084525,-1.026181, 0.858407,0.084525,-1.169673, + 0.858407,0.084525,-1.169673, 0.879477,0.1056,-1.198382, 1.051368,0.1056,-1.051368, + 1.198382,0.1056,-0.879477, 1.169673,0.084525,-0.858407, 1.026181,0.084525,-1.026181, + 1.026181,0.084525,-1.026181, 1.051368,0.1056,-1.051368, 1.198382,0.1056,-0.879477, + 1.317675,0.1056,-0.685551, 1.286108,0.084525,-0.669128, 1.169673,0.084525,-0.858407, + 1.169673,0.084525,-0.858407, 1.198382,0.1056,-0.879477, 1.317675,0.1056,-0.685551, + 1.406405,0.1056,-0.472434, 1.372712,0.084525,-0.461116, 1.286108,0.084525,-0.669128, + 1.286108,0.084525,-0.669128, 1.317675,0.1056,-0.685551, 1.406405,0.1056,-0.472434, + 1.461727,0.1056,-0.24297, 1.426709,0.084525,-0.237149, 1.372712,0.084525,-0.461116, + 1.372712,0.084525,-0.461116, 1.406405,0.1056,-0.472434, 1.461727,0.1056,-0.24297, + 1.4808,0.1056,0, 1.445325,0.084525,0, 1.426709,0.084525,-0.237149, + 1.426709,0.084525,-0.237149, 1.461727,0.1056,-0.24297, 1.4808,0.1056,0, + 0.245542,0.127575,-1.4772, 0.24297,0.1056,-1.461727, 0,0.1056,-1.4808, + 0,0.1056,-1.4808, 0,0.127575,-1.496475, 0.245542,0.127575,-1.4772, + 0.477435,0.127575,-1.421292, 0.472434,0.1056,-1.406405, 0.24297,0.1056,-1.461727, + 0.24297,0.1056,-1.461727, 0.245542,0.127575,-1.4772, 0.477435,0.127575,-1.421292, + 0.692808,0.127575,-1.331623, 0.685551,0.1056,-1.317675, 0.472434,0.1056,-1.406405, + 0.472434,0.1056,-1.406405, 0.477435,0.127575,-1.421292, 0.692808,0.127575,-1.331623, + 0.888786,0.127575,-1.211067, 0.879477,0.1056,-1.198382, 0.685551,0.1056,-1.317675, + 0.685551,0.1056,-1.317675, 0.692808,0.127575,-1.331623, 0.888786,0.127575,-1.211067, + 1.062497,0.127575,-1.062497, 1.051368,0.1056,-1.051368, 0.879477,0.1056,-1.198382, + 0.879477,0.1056,-1.198382, 0.888786,0.127575,-1.211067, 1.062497,0.127575,-1.062497, + 1.211067,0.127575,-0.888786, 1.198382,0.1056,-0.879477, 1.051368,0.1056,-1.051368, + 1.051368,0.1056,-1.051368, 1.062497,0.127575,-1.062497, 1.211067,0.127575,-0.888786, + 1.331623,0.127575,-0.692808, 1.317675,0.1056,-0.685551, 1.198382,0.1056,-0.879477, + 1.198382,0.1056,-0.879477, 1.211067,0.127575,-0.888786, 1.331623,0.127575,-0.692808, + 1.421292,0.127575,-0.477435, 1.406405,0.1056,-0.472434, 1.317675,0.1056,-0.685551, + 1.317675,0.1056,-0.685551, 1.331623,0.127575,-0.692808, 1.421292,0.127575,-0.477435, + 1.4772,0.127575,-0.245542, 1.461727,0.1056,-0.24297, 1.406405,0.1056,-0.472434, + 1.406405,0.1056,-0.472434, 1.421292,0.127575,-0.477435, 1.4772,0.127575,-0.245542, + 1.496475,0.127575,0, 1.4808,0.1056,0, 1.461727,0.1056,-0.24297, + 1.461727,0.1056,-0.24297, 1.4772,0.127575,-0.245542, 1.496475,0.127575,0, + 0.24612,0.15,-1.48068, 0.245542,0.127575,-1.4772, 0,0.127575,-1.496475, + 0,0.127575,-1.496475, 0,0.15,-1.5, 0.24612,0.15,-1.48068, + 0.47856,0.15,-1.42464, 0.477435,0.127575,-1.421292, 0.245542,0.127575,-1.4772, + 0.245542,0.127575,-1.4772, 0.24612,0.15,-1.48068, 0.47856,0.15,-1.42464, + 0.69444,0.15,-1.33476, 0.692808,0.127575,-1.331623, 0.477435,0.127575,-1.421292, + 0.477435,0.127575,-1.421292, 0.47856,0.15,-1.42464, 0.69444,0.15,-1.33476, + 0.89088,0.15,-1.21392, 0.888786,0.127575,-1.211067, 0.692808,0.127575,-1.331623, + 0.692808,0.127575,-1.331623, 0.69444,0.15,-1.33476, 0.89088,0.15,-1.21392, + 1.065,0.15,-1.065, 1.062497,0.127575,-1.062497, 0.888786,0.127575,-1.211067, + 0.888786,0.127575,-1.211067, 0.89088,0.15,-1.21392, 1.065,0.15,-1.065, + 1.21392,0.15,-0.89088, 1.211067,0.127575,-0.888786, 1.062497,0.127575,-1.062497, + 1.062497,0.127575,-1.062497, 1.065,0.15,-1.065, 1.21392,0.15,-0.89088, + 1.33476,0.15,-0.69444, 1.331623,0.127575,-0.692808, 1.211067,0.127575,-0.888786, + 1.211067,0.127575,-0.888786, 1.21392,0.15,-0.89088, 1.33476,0.15,-0.69444, + 1.42464,0.15,-0.47856, 1.421292,0.127575,-0.477435, 1.331623,0.127575,-0.692808, + 1.331623,0.127575,-0.692808, 1.33476,0.15,-0.69444, 1.42464,0.15,-0.47856, + 1.48068,0.15,-0.24612, 1.4772,0.127575,-0.245542, 1.421292,0.127575,-0.477435, + 1.421292,0.127575,-0.477435, 1.42464,0.15,-0.47856, 1.48068,0.15,-0.24612, + 1.5,0.15,0, 1.496475,0.127575,0, 1.4772,0.127575,-0.245542, + 1.4772,0.127575,-0.245542, 1.48068,0.15,-0.24612, 1.5,0.15,0 +}; diff --git a/hacks/glx/texfont.c b/hacks/glx/texfont.c new file mode 100644 index 00000000..f58755d1 --- /dev/null +++ b/hacks/glx/texfont.c @@ -0,0 +1,585 @@ +/* texfonts, Copyright (c) 2005-2012 Jamie Zawinski + * Loads X11 fonts into textures for use with OpenGL. + * + * 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. + */ + + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include +#include +#include +#include + +#ifdef HAVE_COCOA +# ifdef USE_IPHONE +# include "jwzgles.h" +# else +# include +# endif +#else +# include +# include +#endif + +#ifdef HAVE_JWZGLES +# include "jwzgles.h" +#endif /* HAVE_JWZGLES */ + +#include "resources.h" +#include "texfont.h" + +/* These are in xlock-gl.c */ +extern void clear_gl_error (void); +extern void check_gl_error (const char *type); + +/* screenhack.h */ +extern char *progname; + +struct texture_font_data { + Display *dpy; + XFontStruct *font; + int cell_width, cell_height; /* maximal charcell */ + int tex_width, tex_height; /* size of each texture */ + + int grid_mag; /* 1, 2, 4, or 8 */ + int ntextures; /* 1, 4, 16, or 64 (grid_mag ^ 2) */ + + GLuint texid[64]; /* must hold ntextures */ +}; + + +/* return the next larger power of 2. */ +static int +to_pow2 (int i) +{ + static const unsigned int pow2[] = { + 1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024, + 2048, 4096, 8192, 16384, 32768, 65536 }; + int j; + for (j = 0; j < sizeof(pow2)/sizeof(*pow2); j++) + if (pow2[j] >= i) return pow2[j]; + abort(); /* too big! */ +} + + +/* Given a Pixmap (of screen depth), converts it to an OpenGL luminance mipmap. + RGB are averaged to grayscale, and the resulting value is treated as alpha. + Pass in the size of the pixmap; the size of the texture is returned + (it may be larger, since GL like powers of 2.) + + We use a screen-depth pixmap instead of a 1bpp bitmap so that if the fonts + were drawn with antialiasing, that is preserved. + */ +static void +bitmap_to_texture (Display *dpy, Pixmap p, Visual *visual, int *wP, int *hP) +{ + Bool mipmap_p = True; + int ow = *wP; + int oh = *hP; + int w2 = to_pow2 (ow); + int h2 = to_pow2 (oh); + int x, y; + XImage *image = XGetImage (dpy, p, 0, 0, ow, oh, ~0L, ZPixmap); + unsigned char *data = (unsigned char *) calloc (w2 * 2, (h2 + 1)); + unsigned char *out = data; + + /* OpenGLES doesn't support GL_INTENSITY, so instead of using a + texture with 1 byte per pixel, the intensity value, we have + to use 2 bytes per pixel: solid white, and an alpha value. + */ +# ifdef HAVE_JWZGLES +# undef GL_INTENSITY +# endif + +# ifdef GL_INTENSITY + GLuint iformat = GL_INTENSITY; + GLuint format = GL_LUMINANCE; +# else + GLuint iformat = GL_LUMINANCE_ALPHA; + GLuint format = GL_LUMINANCE_ALPHA; +# endif + GLuint type = GL_UNSIGNED_BYTE; + +# ifdef HAVE_JWZGLES + /* This would work, but it's wasteful for no benefit. */ + mipmap_p = False; +# endif + + for (y = 0; y < h2; y++) + for (x = 0; x < w2; x++) { + unsigned long pixel = (x >= ow || y >= oh ? 0 : XGetPixel (image, x, y)); + /* instead of averaging all three channels, let's just use red, + and assume it was already grayscale. */ + unsigned long r = pixel & visual->red_mask; + /* This goofy trick is to make any of RGBA/ABGR/ARGB work. */ + pixel = ((r >> 24) | (r >> 16) | (r >> 8) | r) & 0xFF; +# ifndef GL_INTENSITY + *out++ = 0xFF; /* 2 bytes per pixel */ +# endif + *out++ = pixel; + } + XDestroyImage (image); + image = 0; + + if (mipmap_p) + gluBuild2DMipmaps (GL_TEXTURE_2D, iformat, w2, h2, format, type, data); + else + glTexImage2D (GL_TEXTURE_2D, 0, iformat, w2, h2, 0, format, type, data); + + { + char msg[100]; + sprintf (msg, "texture font %s (%d x %d)", + mipmap_p ? "gluBuild2DMipmaps" : "glTexImage2D", + w2, h2); + check_gl_error (msg); + } + + + glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, + mipmap_p ? GL_LINEAR_MIPMAP_LINEAR : GL_LINEAR); + + glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); + glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); + + free (data); + + *wP = w2; + *hP = h2; +} + + +/* Loads the font named by the X resource "res" and returns + a texture-font object. +*/ +texture_font_data * +load_texture_font (Display *dpy, char *res) +{ + Screen *screen = DefaultScreenOfDisplay (dpy); + Window root = RootWindowOfScreen (screen); + XWindowAttributes xgwa; + + texture_font_data *data = 0; + char *font = get_string_resource (dpy, res, "Font"); + const char *def1 = "-*-helvetica-medium-r-normal-*-240-*"; + const char *def2 = "-*-helvetica-medium-r-normal-*-180-*"; + const char *def3 = "fixed"; + XFontStruct *f; + int which; + GLint old_texture = 0; + + glGetIntegerv (GL_TEXTURE_BINDING_2D, &old_texture); + + if (!strcmp (res, "fpsFont")) + def1 = "-*-courier-bold-r-normal-*-180-*"; /* Kludge. Sue me. */ + + XGetWindowAttributes (dpy, root, &xgwa); + + if (!res || !*res) abort(); + if (!font) font = strdup(def1); + + f = XLoadQueryFont(dpy, font); + if (!f && !!strcmp (font, def1)) + { + fprintf (stderr, "%s: unable to load font \"%s\", using \"%s\"\n", + progname, font, def1); + free (font); + font = strdup (def1); + f = XLoadQueryFont(dpy, font); + } + + if (!f && !!strcmp (font, def2)) + { + fprintf (stderr, "%s: unable to load font \"%s\", using \"%s\"\n", + progname, font, def2); + free (font); + font = strdup (def2); + f = XLoadQueryFont(dpy, font); + } + + if (!f && !!strcmp (font, def3)) + { + fprintf (stderr, "%s: unable to load font \"%s\", using \"%s\"\n", + progname, font, def3); + free (font); + font = strdup (def3); + f = XLoadQueryFont(dpy, font); + } + + if (!f) + { + fprintf (stderr, "%s: unable to load fallback font \"%s\" either!\n", + progname, font); + exit (1); + } + + free (font); + font = 0; + + data = (texture_font_data *) calloc (1, sizeof(*data)); + data->dpy = dpy; + data->font = f; + + /* Figure out how many textures to use. + E.g., if we need 1024x1024 bits, use four 512x512 textures, + to be gentle to machines with low texture size limits. + */ + { + int w = to_pow2 (16 * (f->max_bounds.rbearing - f->min_bounds.lbearing)); + int h = to_pow2 (16 * (f->max_bounds.ascent + f->max_bounds.descent)); + int i = (w > h ? w : h); + + if (i <= 512) data->grid_mag = 1; /* 1 tex of 16x16 chars */ + else if (i <= 1024) data->grid_mag = 2; /* 4 tex of 8x8 chars */ + else if (i <= 2048) data->grid_mag = 4; /* 16 tex of 4x4 chars */ + else data->grid_mag = 8; /* 32 tex of 2x2 chars */ + + data->ntextures = data->grid_mag * data->grid_mag; + +# if 0 + fprintf (stderr, + "%s: %dx%d grid of %d textures of %dx%d chars (%dx%d bits)\n", + progname, + data->grid_mag, data->grid_mag, + data->ntextures, + 16 / data->grid_mag, 16 / data->grid_mag, + i, i); +# endif + } + + for (which = 0; which < data->ntextures; which++) + { + /* Create a pixmap big enough to fit every character in the font. + (modulo the "ntextures" scaling.) + Make it square-ish, since GL likes dimensions to be powers of 2. + */ + XGCValues gcv; + GC gc; + Pixmap p; + int cw = f->max_bounds.rbearing - f->min_bounds.lbearing; + int ch = f->max_bounds.ascent + f->max_bounds.descent; + int grid_size = (16 / data->grid_mag); + int w = cw * grid_size; + int h = ch * grid_size; + int i; + + data->cell_width = cw; + data->cell_height = ch; + + p = XCreatePixmap (dpy, root, w, h, xgwa.depth); + gcv.font = f->fid; + gcv.foreground = BlackPixelOfScreen (xgwa.screen); + gcv.background = BlackPixelOfScreen (xgwa.screen); + gc = XCreateGC (dpy, p, (GCFont|GCForeground|GCBackground), &gcv); + XFillRectangle (dpy, p, gc, 0, 0, w, h); + XSetForeground (dpy, gc, WhitePixelOfScreen (xgwa.screen)); + for (i = 0; i < 256 / data->ntextures; i++) + { + int ii = (i + (which * 256 / data->ntextures)); + char c = (char) ii; + int x = (i % grid_size) * cw; + int y = (i / grid_size) * ch; + + /* See comment in print_texture_string for bit layout explanation. + */ + int lbearing = (f->per_char && ii >= f->min_char_or_byte2 + ? f->per_char[ii - f->min_char_or_byte2].lbearing + : f->min_bounds.lbearing); + int ascent = (f->per_char && ii >= f->min_char_or_byte2 + ? f->per_char[ii - f->min_char_or_byte2].ascent + : f->max_bounds.ascent); + int width = (f->per_char && ii >= f->min_char_or_byte2 + ? f->per_char[ii - f->min_char_or_byte2].width + : f->max_bounds.width); + + if (width == 0) continue; + XDrawString (dpy, p, gc, x - lbearing, y + ascent, &c, 1); + } + XFreeGC (dpy, gc); + + glGenTextures (1, &data->texid[which]); + glBindTexture (GL_TEXTURE_2D, data->texid[which]); + check_gl_error ("texture font load"); + data->tex_width = w; + data->tex_height = h; + +#if 0 /* debugging: splat the bitmap onto the desktop root window */ + { + Window win = RootWindow (dpy, 0); + GC gc2 = XCreateGC (dpy, win, 0, &gcv); + XSetForeground (dpy, gc2, BlackPixel (dpy, 0)); + XSetBackground (dpy, gc2, WhitePixel (dpy, 0)); + XCopyArea (dpy, p, win, gc2, 0, 0, w, h, 0, 0); + XFreeGC (dpy, gc2); + XSync(dpy, False); + usleep (100000); + } +#endif + +#if 0 /* debugging: write the bitmap to a pgm file */ + { + char file[255]; + XImage *image; + int x, y; + FILE *f; + sprintf (file, "/tmp/%02d.pgm", which); + image = XGetImage (dpy, p, 0, 0, w, h, ~0L, ZPixmap); + f = fopen (file, "w"); + fprintf (f, "P5\n%d %d\n255\n", w, h); + for (y = 0; y < h; y++) + for (x = 0; x < w; x++) { + unsigned long pix = XGetPixel (image, x, y); + unsigned long r = (pix & xgwa.visual->red_mask); + r = ((r >> 24) | (r >> 16) | (r >> 8) | r); + fprintf (f, "%c", (char) r); + } + fclose (f); + XDestroyImage (image); + fprintf (stderr, "%s: wrote %s\n", progname, file); + } +#endif + + bitmap_to_texture (dpy, p, xgwa.visual, + &data->tex_width, &data->tex_height); + XFreePixmap (dpy, p); + } + + /* Reset to the caller's default */ + glBindTexture (GL_TEXTURE_2D, old_texture); + + return data; +} + + +/* Width of the string in pixels. + */ +int +texture_string_width (texture_font_data *data, const char *c, + int *height_ret) +{ + int x = 0; + int max_w = 0; + XFontStruct *f = data->font; + int h = f->ascent + f->descent; + while (*c) + { + int cc = *((unsigned char *) c); + if (*c == '\n') + { + if (x > max_w) max_w = x; + x = 0; + h += f->ascent + f->descent; + } + else + x += (f->per_char && cc >= f->min_char_or_byte2 + ? f->per_char[cc-f->min_char_or_byte2].width + : f->min_bounds.rbearing); + c++; + } + if (x > max_w) max_w = x; + if (height_ret) *height_ret = h; + + return max_w; +} + + +/* Draws the string in the scene at the current point. + Newlines, tab stops and subscripts are honored. + */ +void +print_texture_string (texture_font_data *data, const char *string) +{ + XFontStruct *f = data->font; + GLfloat line_height = f->ascent + f->descent; +# ifdef DO_SUBSCRIPTS + GLfloat sub_shift = (line_height * 0.3); + Bool sub_p = False; +# endif /* DO_SUBSCRIPTS */ + int cw = texture_string_width (data, "m", 0); + int tabs = cw * 7; + int x, y; + unsigned int i; + GLint old_texture = 0; + GLfloat omatrix[16]; + int ofront; + + glGetIntegerv (GL_TEXTURE_BINDING_2D, &old_texture); + glGetIntegerv (GL_FRONT_FACE, &ofront); + glGetFloatv (GL_TEXTURE_MATRIX, omatrix); + + clear_gl_error (); + + glPushMatrix(); + + glNormal3f (0, 0, 1); + glFrontFace (GL_CW); + + glMatrixMode (GL_TEXTURE); + glLoadIdentity (); + glMatrixMode (GL_MODELVIEW); + + x = 0; + y = 0; + for (i = 0; i < strlen(string); i++) + { + unsigned char c = string[i]; + if (c == '\n') + { + y -= line_height; + x = 0; + } + else if (c == '\t') + { + x = ((x + tabs) / tabs) * tabs; /* tab to tab stop */ + } +# ifdef DO_SUBSCRIPTS + else if (c == '[' && (isdigit (string[i+1]))) + { + sub_p = True; + y -= sub_shift; + } + else if (c == ']' && sub_p) + { + sub_p = False; + y += sub_shift; + } +# endif /* DO_SUBSCRIPTS */ + else + { + /* For a small font, the texture is divided into 16x16 rectangles + whose size are the max_bounds charcell of the font. Within each + rectangle, the individual characters' charcells sit in the upper + left. + + For a larger font, the texture will itself be subdivided, to + keep the texture sizes small (in that case we deal with, e.g., + 4 grids of 8x8 characters instead of 1 grid of 16x16.) + + Within each texture: + + [A]---------------------------- + | | | | | + | l | w | | r | + | b | i | | b | + | e | d | | e | + | a | t | | a | + | r | h | | r | + | i | | | i | + | n | | | n | + | g | | | g | + | | | | | + |----[B]----------|---| | + | | ascent | | | + | | | | | + | | | | | + |--------------------[C] | + | descent | + | | cell_width, + ------------------------------ cell_height + + We want to make a quad from point A to point C. + We want to position that quad so that point B lies at x,y. + */ + int lbearing = (f->per_char && c >= f->min_char_or_byte2 + ? f->per_char[c - f->min_char_or_byte2].lbearing + : f->min_bounds.lbearing); + int rbearing = (f->per_char && c >= f->min_char_or_byte2 + ? f->per_char[c - f->min_char_or_byte2].rbearing + : f->max_bounds.rbearing); + int ascent = (f->per_char && c >= f->min_char_or_byte2 + ? f->per_char[c - f->min_char_or_byte2].ascent + : f->max_bounds.ascent); + int descent = (f->per_char && c >= f->min_char_or_byte2 + ? f->per_char[c - f->min_char_or_byte2].descent + : f->max_bounds.descent); + int cwidth = (f->per_char && c >= f->min_char_or_byte2 + ? f->per_char[c - f->min_char_or_byte2].width + : f->max_bounds.width); + + unsigned char cc = c % (256 / data->ntextures); + + int gs = (16 / data->grid_mag); /* grid size */ + + int ax = ((int) cc % gs) * data->cell_width; /* point A */ + int ay = ((int) cc / gs) * data->cell_height; + + int bx = ax - lbearing; /* point B */ + int by = ay + ascent; + + int cx = bx + rbearing; /* point C */ + int cy = by + descent; + + GLfloat tax = (GLfloat) ax / data->tex_width; /* tex coords of A */ + GLfloat tay = (GLfloat) ay / data->tex_height; + + GLfloat tcx = (GLfloat) cx / data->tex_width; /* tex coords of C */ + GLfloat tcy = (GLfloat) cy / data->tex_height; + + GLfloat qx0 = x + lbearing; /* quad top left */ + GLfloat qy0 = y + ascent; + GLfloat qx1 = qx0 + rbearing - lbearing; /* quad bot right */ + GLfloat qy1 = qy0 - (ascent + descent); + + if (cwidth > 0 && c != ' ') + { + int which = c / (256 / data->ntextures); + if (which >= data->ntextures) abort(); + glBindTexture (GL_TEXTURE_2D, data->texid[which]); + + glBegin (GL_QUADS); + glTexCoord2f (tax, tay); glVertex3f (qx0, qy0, 0); + glTexCoord2f (tcx, tay); glVertex3f (qx1, qy0, 0); + glTexCoord2f (tcx, tcy); glVertex3f (qx1, qy1, 0); + glTexCoord2f (tax, tcy); glVertex3f (qx0, qy1, 0); + glEnd(); +#if 0 + glDisable(GL_TEXTURE_2D); + glBegin (GL_LINE_LOOP); + glTexCoord2f (tax, tay); glVertex3f (qx0, qy0, 0); + glTexCoord2f (tcx, tay); glVertex3f (qx1, qy0, 0); + glTexCoord2f (tcx, tcy); glVertex3f (qx1, qy1, 0); + glTexCoord2f (tax, tcy); glVertex3f (qx0, qy1, 0); + glEnd(); + glEnable(GL_TEXTURE_2D); +#endif + } + + x += cwidth; + } + } + glPopMatrix(); + + /* Reset to the caller's default */ + glBindTexture (GL_TEXTURE_2D, old_texture); + glFrontFace (ofront); + + glMatrixMode (GL_TEXTURE); + glMultMatrixf (omatrix); + glMatrixMode (GL_MODELVIEW); + + check_gl_error ("texture font print"); +} + +/* Releases the font and texture. + */ +void +free_texture_font (texture_font_data *data) +{ + int i; + if (data->font) + XFreeFont (data->dpy, data->font); + for (i = 0; i < data->ntextures; i++) + if (data->texid[i]) + glDeleteTextures (1, &data->texid[i]); + free (data); +} diff --git a/hacks/glx/texfont.h b/hacks/glx/texfont.h new file mode 100644 index 00000000..05c9219a --- /dev/null +++ b/hacks/glx/texfont.h @@ -0,0 +1,37 @@ +/* texfonts, Copyright (c) 2005 Jamie Zawinski + * Loads X11 fonts into textures for use with OpenGL. + * + * 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. + */ + +#ifndef __TEXTURE_FONT_H__ +#define __TEXTURE_FONT_H__ + +typedef struct texture_font_data texture_font_data; + +/* Loads the font named by the X resource "res" and returns + a texture-font object. +*/ +extern texture_font_data *load_texture_font (Display *, char *res); + +/* Width of the string in pixels. + */ +extern int texture_string_width (texture_font_data *, const char *, + int *line_height_ret); + +/* Draws the string in the scene at the origin. + Newlines and tab stops are honored. + */ +extern void print_texture_string (texture_font_data *, const char *); + +/* Releases the texture font. + */ +extern void free_texture_font (texture_font_data *); + +#endif /* __TEXTURE_FONT_H__ */ diff --git a/hacks/glx/timetunnel.c b/hacks/glx/timetunnel.c new file mode 100644 index 00000000..89d89461 --- /dev/null +++ b/hacks/glx/timetunnel.c @@ -0,0 +1,1267 @@ +/* timetunnel. Based on dangerball.c, hack by Sean Brennan */ +/* dangerball, Copyright (c) 2001-2004 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. + */ + +#define GL_GLEXT_PROTOTYPES 1 + +#include /* for log2 */ + +#define DEFAULTS "*delay: 30000 \n" \ + "*count: 30 \n" \ + "*showFPS: False \n" \ + "*timeStart: 0.0 \n" \ + "*timeEnd: 27.79 \n" \ + "*wireframe: False \n" \ + + + +# define refresh_tunnel 0 +# define release_tunnel 0 +#undef countof +#define countof(x) (sizeof((x))/sizeof((*x))) + +#include "xlockmore.h" +#include "colors.h" +#include "rotator.h" +#include "gltrackball.h" + +#define DEF_START "0.00" +#define DEF_DILATE "1.00" +#define DEF_END "27.79" +#define DEF_LOCKLOGO "False" +#define DEF_DRAWLOGO "True" +#define DEF_REVERSE "False" +#define DEF_FOG "True" +#define DEF_TEXTURE "True" +#define MAX_TEXTURE 10 +#define CYL_LEN 14.0 +#define DIAMOND_LEN 10.0 + +static float start, end, dilate; +static Bool do_texture, drawlogo, wire, reverse, do_fog; +static const char *do_tx1, *do_tx2, *do_tx3, *do_tun1, *do_tun2, *do_tun3; + +static XrmOptionDescRec opts[] = { + {"-texture" , ".texture", XrmoptionNoArg, "true" }, + {"+texture" , ".texture", XrmoptionNoArg, "false" }, + {"-start" , ".start", XrmoptionSepArg, 0 }, + {"-end" , ".end", XrmoptionSepArg, 0 }, + {"-dilate" , ".dilate", XrmoptionSepArg, 0 }, + {"+logo" , ".drawlogo", XrmoptionNoArg, "false" }, + {"-reverse" , ".reverse", XrmoptionNoArg, "true" }, + {"+fog" , ".fog", XrmoptionNoArg, "false" }, + {"-marquee" , ".marquee", XrmoptionSepArg, 0}, + /* {"+marquee" , ".marquee", XrmoptionNoArg, "(none)"}, */ + {"-tardis" , ".tardis", XrmoptionSepArg, 0}, + /* {"+tardis" , ".tardis", XrmoptionNoArg, "(none)"}, */ + {"-head" , ".head", XrmoptionSepArg, 0}, + /* {"+head" , ".head", XrmoptionNoArg, "(none)"}, */ + {"-tun1" , ".tun1", XrmoptionSepArg, 0}, + /* {"+tun1" , ".tun1", XrmoptionNoArg, "(none)"}, */ + {"-tun2" , ".tun2", XrmoptionSepArg, 0}, + /* {"+tun2" , ".tun2", XrmoptionNoArg, "(none)"}, */ + {"-tun3" , ".tun3", XrmoptionSepArg, 0}, + /* {"+tun3" , ".tun3", XrmoptionNoArg, "(none)"}, */ +}; + +static argtype vars[] = { + {&do_texture, "texture", "Texture", DEF_TEXTURE, t_Bool}, + {&start, "start", "Start", DEF_START, t_Float}, + {&end, "end", "End", DEF_END , t_Float}, + {&dilate, "dilate", "Dilate", DEF_DILATE , t_Float}, + {&drawlogo, "drawlogo", "DrawLogo", DEF_DRAWLOGO , t_Bool}, + {&reverse, "reverse", "Reverse", DEF_REVERSE , t_Bool}, + {&do_fog, "fog", "Fog", DEF_FOG , t_Bool}, + {&do_tx1, "marquee", "Marquee", "(none)", t_String}, + {&do_tx2, "tardis", "Tardis", "(none)", t_String}, + {&do_tx3, "head", "Head", "(none)", t_String}, + {&do_tun1, "tun1", "Tunnel 1", "(none)", t_String}, + {&do_tun2, "tun2", "Tunnel 2", "(none)", t_String}, + {&do_tun3, "tun3", "Tunnel 3", "(none)", t_String}, +}; + +ENTRYPOINT ModeSpecOpt tunnel_opts = {countof(opts), opts, countof(vars), vars, NULL}; +#include "xpm-ximage.h" +#include "images/logo-180.xpm" +#include "images/tunnelstar.xpm" +#include "images/timetunnel0.xpm" +#include "images/timetunnel1.xpm" +#include "images/timetunnel2.xpm" + + +#ifdef USE_GL /* whole file */ + +/* ANIMATION CONTROLS */ +/* an effect is a collection of floating point variables that vary with time. +A knot is a timestamp with an array of floats. State is the current values of the floats. +State is set by linearly interpolating between knots */ +typedef struct { + float *knots, *state; + int numknots, knotwidth; + float direction; +} effect_t; + +typedef struct { + GLXContext *glx_context; + rotator *rot; + trackball_state *trackball; + Bool button_down_p; + + int time_oldusec, time_oldsec; + + int num_texshifts; /* animates tunnels. Not an effect. */ + GLfloat pos, *texshift; + + GLuint texture_binds[MAX_TEXTURE], cyllist, diamondlist; + + float effect_time, effect_maxsecs; /* global time controls */ + float start_time, end_time; + + int num_effects; + effect_t *effects; /* array of all effects */ + +} tunnel_configuration; + +static tunnel_configuration *tconf = NULL; + +/* allocate memory and populate effect with knot data */ +static void init_effect(effect_t *e, int numk, int kwidth, + float dir, float *data ) +{ + int i, j; + + e->numknots = numk; + e->knotwidth = kwidth; + e->direction = dir; + e->knots = calloc(numk * kwidth, sizeof(float)); + e->state = calloc(numk, sizeof(float)); + for ( i = 0 ; i < e->numknots ; i++) + for ( j = 0 ; j < e->knotwidth; j++) + e->knots[i * kwidth + j] = data[i * kwidth + j]; +} + +/* static knot data. each effect is listed and knot data is hard coded. + Knots are linerally interpolated to yield float values, depending on + knot width. knot format is [time, data, data, data...]. + Data can be alpha, zvalue, etc. */ +static void init_effects(effect_t *e, int effectnum) +{ + /* effect 1: wall tunnel. percent closed */ + float e1d[6][2] = + {{0.0, 0.055}, + {2.77, 0.055}, + {3.07,1.0}, + {8.08, 1.0}, + {8.08, 0.0}, + {10.0, 0.0}}; + /* effect 2: tardis. distance and alpha */ + float e2d[8][3] = + { {0.0, 0.0 , 0.0}, + {3.44, 0.0 , 0.0}, + {3.36, 5.4 , 0.0}, + {4.24, 3.66, 1.0}, + {6.51, 2.4, 0.94}, + {8.08, 0.75 , 0.0}, + {8.08, 0.0 , 0.0}, + {10.0, 0.0, 0.0}}; + /* effect 3: cylinder. alpha */ + float e3d[5][2] = + {{0.0, 0.0}, + {6.41, 0.00}, + {8.08, 1.0}, + {14.81, 1.0}, + {15.65, 0.0}}; + + /* effect 4: fog. color, density, start, end */ + float e4d[9][5] = + {{0.0 , 1.0, 0.45, 3.0, 15.0}, + {6.40, 1.0, 0.45, 3.0, 14.0}, + {8.08, 1.0, 0.95, 1.0, 14.0}, + {15.17, 1.0, 0.95, 1.0, 6.0}, + {15.51, 1.0, 0.95, 3.0, 8.0}, + {23.35, 1.0, 0.95, 3.0, 8.0}, + {24.02, 0.0, 0.95, 2.3, 5.0}, + {26.02, 0.0, 0.95, 2.3, 5.0}, + {27.72, 0.0, 1.00, 0.3, 0.9} + }; + + /* effect 5: logo. dist, alpha */ + float e5d[7][3] = + {{0.0, 0.0, 0.0}, + {16.52, 0.00, 0.0}, + {16.52, 0.80, 0.01}, + {17.18, 1.15, 1.0}, + {22.36, 5.3, 1.0}, + {22.69, 5.7, 0.0}, + {22.69, 0.0, 0.0} + }; + /* effect 6: diamond tunnel. alpha */ + float e6d[3][2] = + {{0.0, 0.00}, + {15.17, 0.00}, + {15.51,1.0}}; + + /* effect 7: tardis cap draw . positive draws cap*/ + float e7d[3][2] = + {{0.0, -1.00}, + {4.24, -1.00}, + {4.24, 1.00}}; + + /* effect 8: star/asterisk: alpha */ + float e8d[5][2] = + {{0.0, .00}, + {10.77, .00}, + {11.48, 1.00}, + {15.35, 1.00}, + {16.12, 0.00}}; + + /* effect 9: whohead 1 alpha */ + float e9d[5][2] = + {{0.0, .00}, + {13.35, .00}, + {14.48, 1.00}, + {15.17, 1.00}, + {15.97, 0.00}}; + /* {14.87, 1.00}, + {15.17, 0.00}}; */ + + /* effect 10: whohead-brite alpha */ + float e10d[5][2] = + {{0.0, .00}, + {11.34, .00}, + {12.34, .20}, + {13.35, 0.60}, + {14.48, 0.00}}; + /* {13.95, 0.00}}; */ + + /* effect 11: whohead-psy alpha */ + float e11d[5][2] = + {{0.0, .00}, + {14.87, .00}, + {15.17, 1.00}, + {15.91, 0.00}, + {16.12, 0.00}}; + + /* effect 12: whohead-silhouette pos-z, alpha */ + float e12d[6][3] = + {{0.0, 1.0, .00}, + {15.07, 1.0, 0.00}, + {15.07, 1.0, 1.00}, + {16.01, 1.0, 1.00}, + {16.78, 0.5, 1.00}, + {16.78, 0.1, 0.00} }; + + /* effect 1: wall tunnel */ + if (effectnum == 1) + init_effect(e, 6, 2, -0.2, (float *) e1d); + + /* effect 2: tardisl */ + if (effectnum == 2) + init_effect(e, 8, 3, 1.0, (float *) e2d); + + /* effect 3: cylinder tunnel */ + if (effectnum == 3) + init_effect(e, 5, 2, 0.889 , (float *) e3d); + + /* effect 4: fog color */ + if (effectnum == 4) + init_effect(e, 9, 5, 1.0, (float *) e4d); + /* effect 5: logo distance, alpha*/ + if (effectnum == 5) + init_effect(e, 7, 3, 1.0, (float *) e5d); + /* effect 6: diamond tunnel, alpha*/ + if (effectnum == 6) + init_effect(e, 3, 2, 0.24 , (float *) e6d); + + /* effect 7: cap wall tunnel*/ + if (effectnum == 7) + init_effect(e, 3, 2, 1.0, (float *) e7d); + + /* effect 8: asterisk */ + if (effectnum == 8) + init_effect(e, 5, 2, 1.0, (float *) e8d); + + /* effect 9, 10, 11, 12: whoheads */ + if (effectnum == 9 ) + init_effect(e, 5, 2, 1.0, (float *) e9d); + if (effectnum == 10 ) + init_effect(e, 5, 2, 1.0, (float *) e10d); + if (effectnum == 11 ) + init_effect(e, 5, 2, 1.0, (float *) e11d); + if (effectnum == 12 ) + init_effect(e, 6, 3, 1.0, (float *) e12d); +} + + +/* set fog parameters, controlled by effect */ +static void update_fog(float color, float density, float start, float end) +{ + GLfloat col[4]; + + col[0] = col[1] = col[2] = color; + col[3] = 1.0; + + glFogi(GL_FOG_MODE, GL_LINEAR); + glFogfv(GL_FOG_COLOR, col); + glFogf(GL_FOG_DENSITY, density); + glFogf(GL_FOG_START, start); + glFogf(GL_FOG_END, end); +} + +/* set effect's floating point data values by linearally interpolating +between two knots whose times bound the current time: eff_time */ + +static void update_knots(effect_t *e, float eff_time) +{ + int i, j; + float timedelta, lowknot, highknot, *curknot, *nextknot; + + for ( i = 0 ; i < e->numknots ; i++) + if (e->knots[i * e->knotwidth] <= eff_time) { + if ( i < e->numknots - 1) + nextknot = e->knots + (i + 1) * e->knotwidth; + else + /*repeat last knot to carry knot data forward*/ + nextknot = e->knots + (i) * e->knotwidth; + curknot = e->knots + i * e->knotwidth; + if (*nextknot - *curknot <= 0.0) timedelta = 1.0; + else + timedelta = (eff_time-*curknot)/(*nextknot-*curknot); + if (timedelta > 1.0) timedelta = 1.0; + for (j = 1 ; j < e->knotwidth ; j++) { + highknot = (float) *(nextknot + j); + lowknot = (float) *(curknot + j); + e->state[j - 1 ] = lowknot+(highknot-lowknot)*timedelta; + } + } + +} + + +/* Window management, etc + */ +ENTRYPOINT void +reshape_tunnel (ModeInfo *mi, int width, int height) +{ + GLfloat h = (GLfloat) height / (GLfloat) width; + + glViewport (0, 0, (GLint) width, (GLint) height); + + glMatrixMode(GL_PROJECTION); + glLoadIdentity(); + gluPerspective (90.0, 1/h, 0.2, 50.0); + + glMatrixMode(GL_MODELVIEW); + glLoadIdentity(); + gluLookAt( 0.0, 0.0, 0.3, + 0.0, 0.0, 1.0, + 0.0, 1.0, 0.0); + + glClear(GL_COLOR_BUFFER_BIT); +} + + + + +ENTRYPOINT Bool +tunnel_handle_event (ModeInfo *mi, XEvent *event) +{ + tunnel_configuration *tc = &tconf[MI_SCREEN(mi)]; + + if (event->xany.type == ButtonPress && + event->xbutton.button == Button1) + { + tc->button_down_p = True; + gltrackball_start (tc->trackball, + event->xbutton.x, event->xbutton.y, + MI_WIDTH (mi), MI_HEIGHT (mi)); + return True; + } + else if (event->xany.type == ButtonRelease && + event->xbutton.button == Button1) + { + tc->button_down_p = False; + return True; + } + else if (event->xany.type == ButtonPress && + (event->xbutton.button == Button4 || + event->xbutton.button == Button5)) + { + gltrackball_mousewheel (tc->trackball, event->xbutton.button, 10, + !!event->xbutton.state); + return True; + } + else if (event->xany.type == MotionNotify && + tc->button_down_p) + { + gltrackball_track (tc->trackball, + event->xmotion.x, event->xmotion.y, + MI_WIDTH (mi), MI_HEIGHT (mi)); + return True; + } + + return False; +} + +static void setTexParams(void) +{ + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); + glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); +} + +static void update_animation(tunnel_configuration *tc) { + + /* time based, of course*/ + /* shift texture based on elapsed time since previous call*/ + struct timeval tv; + struct timezone tz; + int elapsed_usecs, elapsed_secs, i; + float computed_timeshift; + + /* get new animation time */ + gettimeofday(&tv, &tz); + elapsed_secs = tv.tv_sec - tc->time_oldsec; + elapsed_usecs = tv.tv_usec - tc->time_oldusec; + /* store current time */ + tc->time_oldsec = tv.tv_sec ; + tc->time_oldusec = tv.tv_usec; + /* elaped time. computed timeshift is tenths of a second */ + computed_timeshift = (float) (elapsed_secs * 1000000. + elapsed_usecs)/ + 100000.0; + + /* calibrate effect time to lie between start and end times */ + /* loop if time exceeds end time */ + if (reverse) + tc->effect_time -= computed_timeshift / 10.0 * dilate; + else + tc->effect_time += computed_timeshift / 10.0 * dilate; + if ( tc->effect_time >= tc->end_time) + tc->effect_time = tc->start_time; + if ( tc->effect_time < tc->start_time) + tc->effect_time = tc->end_time;; + + /* move texture shifters in effect's direction, e.g. tardis + tunnel moves backward, effect 1's direction */ + if (reverse) { + tc->texshift[0] -= tc->effects[1].direction * computed_timeshift/ 10.0; + tc->texshift[1] -= tc->effects[3].direction * computed_timeshift/ 10.0; + tc->texshift[2] -= tc->effects[6].direction * computed_timeshift/ 10.0; + + } else { + tc->texshift[0] += tc->effects[1].direction * computed_timeshift/ 10.0; + tc->texshift[1] += tc->effects[3].direction * computed_timeshift/ 10.0; + tc->texshift[2] += tc->effects[6].direction * computed_timeshift/ 10.0; + } + + /* loop texture shifters if necessary */ + for ( i = 0 ; i < tc->num_texshifts; i++) { + if (tc->texshift[i] > 1.0) + tc->texshift[i] -= (int) tc->texshift[i]; + if (tc->texshift[i]< -1.0) + tc->texshift[i] -= (int) tc->texshift[i]; + } + + /* update effect data with current time. Uses linear interpolation */ + for ( i = 1 ; i <= tc->num_effects ; i++) + update_knots(&tc->effects[i], tc->effect_time); + +} /*update_animation*/ + +/* draw a textured(tex) quad at a certain depth (z), and certain alpha (alpha), +with aspect ratio (aspect), and blending mode (blend_mode) of either adding +or subtracting. if alpha is zero or less, nothing happens */ +static void draw_sign(ModeInfo *mi, tunnel_configuration *tc, float z, float alpha, float aspect, + GLuint tex, int blend_mode) +{ + +#ifndef HAVE_JWZGLES + if (alpha > 0.0) { + mi->polygon_count ++; + /* glEnable(GL_BLEND); */ + glBlendColor(0.0, 0.0, 0.0, alpha); + /*glBlendColor(0.0, 0.0, 0.0, 0.0); */ + if (blend_mode == 1) { + glBlendFunc(GL_CONSTANT_ALPHA, + GL_ONE); + glBlendEquation(GL_FUNC_REVERSE_SUBTRACT); + } else if (blend_mode == 2) { + glBlendFunc(GL_CONSTANT_ALPHA, + GL_ONE); + glBlendEquation(GL_FUNC_ADD); + } else { + glBlendFunc(GL_CONSTANT_ALPHA, + GL_ONE_MINUS_CONSTANT_ALPHA); + glBlendEquation(GL_FUNC_ADD); + } /* blend mode switch */ + +#ifdef HAVE_GLBINDTEXTURE + if (do_texture) + glBindTexture(GL_TEXTURE_2D, tc->texture_binds[tex]); +#endif + glBegin(GL_QUADS); + glTexCoord2f(1.0, 0.0); + glVertex3f(-1.0 , -1.0 * aspect , z); + glTexCoord2f(1.0, 1.0); + glVertex3f(-1.0 , 1.0 * aspect , z); + glTexCoord2f(0.0, 1.0); + glVertex3f(1.0 , 1.0 * aspect , z); + glTexCoord2f(0.0, 0.0); + glVertex3f(1.0 , -1.0 * aspect , z); + glEnd(); + if (blend_mode != 0) { + glBlendFunc(GL_CONSTANT_ALPHA, + GL_ONE_MINUS_CONSTANT_ALPHA); + glBlendEquation(GL_FUNC_ADD); + } + /* glDisable(GL_BLEND); */ + + } +#endif /* !HAVE_JWZGLES */ +} /* draw sign */ + + +/* draw a time tunnel. used for both cylinder and diamond tunnels. + uses texture shifter (indexed by shiftnum) to simulate motion. + tunnel does not move, and is acutally a display list. if alpha = 0, skip */ +static void draw_cyl(ModeInfo *mi, tunnel_configuration *tc, float alpha, int texnum, int listnum, int shiftnum) +{ +#ifndef HAVE_JWZGLES + if (alpha > 0.0) { + if (listnum == tc->diamondlist) + mi->polygon_count += 4; + if (listnum == tc->cyllist) + mi->polygon_count += 30; + glMatrixMode(GL_TEXTURE); + glLoadIdentity(); + glTranslatef(tc->texshift[shiftnum], 0.0, 0.0); + glMatrixMode(GL_MODELVIEW); + /* glEnable(GL_BLEND); */ + glBlendColor(0.0, 0.0, 0.0, alpha); + glBlendFunc(GL_CONSTANT_ALPHA, GL_ONE_MINUS_CONSTANT_ALPHA); + +#ifdef HAVE_GLBINDTEXTURE + if (do_texture) + glBindTexture(GL_TEXTURE_2D, tc->texture_binds[texnum]); +#endif + glCallList(listnum); + + glMatrixMode(GL_TEXTURE); + glLoadIdentity(); + glMatrixMode(GL_MODELVIEW); + /* glDisable(GL_BLEND); */ + } +#endif /* HAVE_JWZGLES */ +} + + +/* make tardis type tunnel. Starts as walls and then +grows to outline of tardis. percent is how complete +tardis outline is. cap is to draw cap for nice fog effects */ + +static void make_wall_tunnel(ModeInfo *mi, tunnel_configuration *tc, float percent, float cap) +{ + /* tardis is about 2x1, so wrap tex around, starting at the base*/ + /* tex coords are: + + _tl__tr_ + | | +l| |r + | | + -bl__br_ + that's br=bottom right, etc. ttr is top-top-right */ + + float half_floor= 0.08333333333333333, + full_wall = 0.33333333333333333; + float br1, + r0 , r1 , + tr0, tr1, + tl0, tl1, + l0 , l1 , + depth=0.3, zdepth=15.0; + /* zdepth is how far back tunnel goes */ + /* depth is tex coord scale. low number = fast texture shifting */ + + float textop, texbot; + float height; + + br1 = half_floor; + r0 = br1 ; + r1 = r0 + full_wall; + tr0 = r1; + tr1 = r1 + half_floor; + tl0 = tr1; + tl1 = tl0 + half_floor; + l0 = tr1; + l1 = l0 + full_wall; + + glMatrixMode(GL_TEXTURE); + glLoadIdentity(); + glRotatef(90.0, 0.0, 0.0, 1.0); + glTranslatef(tc->texshift[0], 0.0, 0.0); + glMatrixMode(GL_MODELVIEW); + +#ifdef HAVE_GLBINDTEXTURE + if (do_texture) + glBindTexture(GL_TEXTURE_2D, tc->texture_binds[0]); +#endif + glColor3f(1.0, 1.0, 0.0); + if (cap > 0.0 && percent > 0.0 && drawlogo && do_fog) { + mi->polygon_count += 6; + glBegin(GL_TRIANGLE_FAN); + glVertex3f(0.0, 0.0, zdepth); + glVertex3f(-1.0, -2.0, zdepth); + glVertex3f(1.0, -2.0, zdepth); + glVertex3f(1.0, 2.0, zdepth); + glVertex3f(0.2, 2.0, zdepth); + glVertex3f(0.2, 2.2, zdepth); + glVertex3f(-0.2, 2.2, zdepth); + glVertex3f(-0.2, 2.0, zdepth); + glVertex3f(-1.0, 2.0, zdepth); + glVertex3f(-1.0, -2.0, zdepth); + glEnd(); + } + if (percent > ( full_wall * 2.0)) { + glBegin(GL_QUADS); + + height = (percent - full_wall * 2.0) /( 1.0 - full_wall * 2.0); + if (height > 1.0) height = 1.0; + + + if ( height > 0.8) { + mi->polygon_count += 2; + if ( height > 0.90) { + mi->polygon_count += 2; + /* TTTR */ + texbot = tr0; + textop = tr0 + half_floor * height; + glTexCoord2f(0.0, texbot); + glVertex3f(0.2, 2.2, 0.0); + + glTexCoord2f(0.0, textop); + glVertex3f(2.0 - height * 2.0, 2.2, 0.0); + + glTexCoord2f(depth, textop); + glVertex3f(2.0 - height * 2.0, 2.2, zdepth); + + glTexCoord2f(depth, texbot); + glVertex3f(0.2, 2.2, zdepth); + + /* TTTL */ + texbot = tl1 - half_floor * height; + textop = tl1; + glTexCoord2f(0.0, texbot); + glVertex3f(-2.0 + height * 2.0, 2.2, 0.0); + + glTexCoord2f(0.0, textop); + glVertex3f(-0.2, 2.2, 0.0); + + glTexCoord2f(depth, textop); + glVertex3f(-0.2, 2.2, zdepth); + + glTexCoord2f(depth, texbot); + glVertex3f(-2.0 + height * 2.0, 2.2, zdepth); + } + if (height > 0.90) height = 0.90; + + /* TTR */ + texbot = tr0; + textop = tr0 + half_floor * height; + glTexCoord2f(0.0, texbot); + glVertex3f(0.2, 2.0, 0.0); + + glTexCoord2f(0.0, textop); + glVertex3f(0.2, 0.4 + height * 2.0, 0.0); + + glTexCoord2f(depth, textop); + glVertex3f(0.2, 0.4 + height * 2.0, zdepth); + + glTexCoord2f(depth, texbot); + glVertex3f(0.2, 2.0, zdepth); + + /* TTL */ + texbot = tl1 - half_floor * height; + textop = tl1; + glTexCoord2f(0.0, texbot); + /*glVertex3f(-.2, 2.0 + (0.9 - height) * 2.0, 0.0); */ + glVertex3f(-.2, 0.4 + height * 2.0, 0.0); + + glTexCoord2f(0.0, textop); + glVertex3f(-.2, 2.0, 0.0); + + glTexCoord2f(depth, textop); + glVertex3f(-.2, 2.0, zdepth); + + glTexCoord2f(depth, texbot); + glVertex3f(-.2, 0.4 + height * 2.0, zdepth); + } + + height = (percent - full_wall * 2.0) /( 1.0 - full_wall * 2.0); + if (height > 0.8) height = 0.8; + + + mi->polygon_count += 2; + /* TR */ + texbot = tr0; + textop = tr0 + half_floor * height; + glTexCoord2f(0.0, texbot); + glVertex3f(1.0, 2.0, 0.0); + + glTexCoord2f(0.0, textop); + glVertex3f(1.0 - height, 2.0, 0.0); + + glTexCoord2f(depth, textop); + glVertex3f(1.0 - height, 2.0, zdepth); + + glTexCoord2f(depth, texbot); + glVertex3f(1.0, 2.0, zdepth); + + /* TL */ + texbot = tl1 - half_floor * height; + textop = tl1; + glTexCoord2f(0.0, texbot); + glVertex3f(-1.0 + height, 2.0, 0.0); + + glTexCoord2f(0.0, textop); + glVertex3f(-1.0, 2.0, 0.0); + + glTexCoord2f(depth, textop); + glVertex3f(-1.0, 2.0, zdepth); + + glTexCoord2f(depth, texbot); + glVertex3f(-1.0 + height, 2.0, zdepth); + + height = (percent - full_wall * 2.0) /( 1.0 - full_wall * 2.0); + + if (height > 1.0) height = 1.0; + + + mi->polygon_count += 2; + /* BR */ + texbot = tr0; + textop = tr0 + half_floor * height; + glTexCoord2f(0.0, texbot); + glVertex3f(1.0, -2.0, 0.0); + + glTexCoord2f(0.0, textop); + glVertex3f(1.0 - height, -2.0, 0.0); + + glTexCoord2f(depth, textop); + glVertex3f(1.0 - height, -2.0, zdepth); + + glTexCoord2f(depth, texbot); + glVertex3f(1.0, -2.0, zdepth); + + /* BL */ + texbot = tl1 - half_floor * height; + textop = tl1; + glTexCoord2f(0.0, texbot); + glVertex3f(-1.0 + height, -2.0, 0.0); + + glTexCoord2f(0.0, textop); + glVertex3f(-1.0, -2.0, 0.0); + + glTexCoord2f(depth, textop); + glVertex3f(-1.0, -2.0, zdepth); + + glTexCoord2f(depth, texbot); + glVertex3f(-1.0 + height, -2.0, zdepth); + + + glEnd(); + } + + if (percent > 0.0) { + mi->polygon_count += 2; + glBegin(GL_QUADS); + height = percent / ( full_wall * 2.0); + if (height > 1.0) height = 1.0; + textop = (l0 + l1) / 2.0 - full_wall * 0.5 * height; + texbot = (l0 + l1) / 2.0 + full_wall * 0.5 * height; + + glTexCoord2f(0.0, textop); + glVertex3f(-1.0, height * 2, 0.0); + + glTexCoord2f(0.0, texbot); + glVertex3f(-1.0, -height * 2, 0.0); + + glTexCoord2f(depth, texbot); + glVertex3f(-1.0, -height * 2, zdepth); + + glTexCoord2f(depth, textop); + glVertex3f(-1.0, height * 2, zdepth); + + textop = (r0 + r1) / 2.0 - full_wall * 0.5 * height; + texbot = (r0 + r1) / 2.0 + full_wall * 0.5 * height; + + glTexCoord2f(0.0, texbot); + glVertex3f(1.0, height * 2, 0.0); + + glTexCoord2f(0.0, textop); + glVertex3f(1.0, -height * 2, 0.0); + + glTexCoord2f(depth, textop); + glVertex3f(1.0, -height * 2, zdepth); + + glTexCoord2f(depth, texbot); + glVertex3f(1.0, height * 2, zdepth); + glEnd(); + } + + + glMatrixMode(GL_TEXTURE); + glLoadIdentity(); + glMatrixMode(GL_MODELVIEW); +} /* make_wall_tunnel */ + +/* wraps an int to between min and max. + Kind of like the remainder when devided by (max - min). + Used to create torus mapping on square array */ +static int wrapVal(int val, int min, int max) +{ + int ret; + + ret = val; + if (val >= max) + ret = min + (val - max ) % (max - min); + if (val < min) + ret = max - (min - val) % (max - min); + return(ret); +} + +/*=================== Load Texture =========================================*/ +/* ripped from atunnel.c, Copyright (c) E. Lassauge, 2003-2004. */ +/* modified like so by Sean Brennan: + take texture object for glbind + removed xlock stuff + Added filters: + blur color / alpha channel [3x3 box filter, done [blur] times + anegative : create b/w image from zero alpha. zero alpha gets bw_color, + nonzero alpha gets 1.0 - bwcolor, then alpha flipped to 1-alpha. + + Inputs: xpm structure, or filename of xmp image. if filename == NULL, use structure. + Outputs: texture bound to texutre Id texbind. + +*/ + +static float mylog2(float x) { return ( log(x) / log(2));} + +static void LoadTexture(ModeInfo * mi, char **fn, const char *filename, GLuint texbind, int blur, float bw_color, Bool anegative, Bool onealpha) +{ + /* looping and temporary array index variables */ + int ix, iy, bx, by, indx, indy, boxsize, cchan, tmpidx, dtaidx; + + float boxdiv, tmpfa, blursum ; + unsigned char *tmpbuf, tmpa; + Bool rescale; + + + XImage *teximage; /* Texture data */ + + rescale = False; + + boxsize = 2; + boxdiv = 1.0 / ( boxsize * 2.0 + 1.0) / ( boxsize * 2.0 + 1.0); + + + if (filename) + teximage = xpm_file_to_ximage(MI_DISPLAY(mi), MI_VISUAL(mi), + MI_COLORMAP(mi), filename); + else + teximage = xpm_to_ximage(MI_DISPLAY(mi), MI_VISUAL(mi), + MI_COLORMAP(mi), fn); + if (teximage == NULL) { + fprintf(stderr, "%s: error reading the texture.\n", progname); + glDeleteTextures(1, &texbind); + do_texture = False; + exit(0); + } + + /* check if image is 2^kumquat, where kumquat is an integer between 1 and 10. Recale to + nearest power of 2. */ + tmpfa = mylog2((float) teximage->width); + bx = 2 << (int) (tmpfa -1); + if (bx != teximage->width) { + rescale = True; + if ((tmpfa - (int) tmpfa) > 0.5849) + bx = bx * 2; + } + tmpfa = mylog2((float) teximage->height); + by = 2 << (int) (tmpfa - 1); + if (by != teximage->height) { + rescale = True; + if ((tmpfa - (int) tmpfa) > 0.5849) + by = by * 2; + } + +#ifndef HAVE_JWZGLES + if (rescale) { + tmpbuf = calloc(bx * by * 4, sizeof(unsigned char)); + if (gluScaleImage(GL_RGBA, teximage->width, teximage->height, GL_UNSIGNED_BYTE, teximage->data, + bx, by, GL_UNSIGNED_BYTE, tmpbuf)) + check_gl_error("scale image"); + + free(teximage->data); + teximage->data = (char *) tmpbuf; + teximage->width = bx; + teximage->height= by; + } + /* end rescale code */ +#endif /* !HAVE_JWZGLES */ + + if (anegative ) { + for (ix = 0 ; ix < teximage->height * teximage->width; ix++) + { + if (!teximage->data[ ix * 4 + 3]) { + teximage->data[ ix * 4 + 3] = (unsigned char) 0xff; + tmpa = (unsigned char) (bw_color * 0xff); + } else { + if (onealpha) + teximage->data[ ix * 4 + 3] = (unsigned char) 0xff; + else + teximage->data[ ix * 4 + 3] = (unsigned char) 0xff - + teximage->data[ ix * 4 + 3]; + tmpa = (unsigned char) ((1.0 - bw_color) * 0xff); + } + /* make texture uniform b/w color */ + teximage->data[ ix * 4 + 0] = + (unsigned char) ( tmpa); + teximage->data[ ix * 4 + 1] = + (unsigned char) ( tmpa); + teximage->data[ ix * 4 + 2] = + (unsigned char) ( tmpa); + /* negate alpha */ + } + } + + if (blur > 0) { + if (! anegative ) /* anegative alread b/w's the whole image */ + for (ix = 0 ; ix < teximage->height * teximage->width; ix++) + if (!teximage->data[ ix * 4 + 3]) + { + teximage->data[ ix * 4 + 0] = + (unsigned char) ( 255.0 * bw_color); + teximage->data[ ix * 4 + 1] = + (unsigned char) ( 255.0 * bw_color); + teximage->data[ ix * 4 + 2] = + (unsigned char) ( 255.0 * bw_color); + } + ; + tmpbuf = calloc(teximage->height * teximage->width * 4, sizeof(unsigned char) ) ; + while (blur--) { + /* zero out tmp alpha buffer */ + for (iy = 0 ; iy height * teximage->width * 4 ; iy++) + tmpbuf[iy] = 0; + for (cchan = 0; cchan < 4 ; cchan++) { + for (iy = 0 ; iy < teximage->height ; iy++) { + for (ix = 0 ; ix < teximage->width ; ix++) { + dtaidx = (teximage->width * iy + ix) * 4; + tmpa = teximage->data[dtaidx + cchan]; + tmpfa = (float) tmpa * boxdiv; + /* box filter */ + for (by = -boxsize ; by <= boxsize; by++) { + for (bx = -boxsize ; bx <= boxsize; bx++) { + indx = wrapVal(ix + bx, 0, teximage->width); + indy = wrapVal(iy + by, 0, teximage->height); + tmpidx = (teximage->width * indy + indx) * 4; + blursum = tmpfa; + tmpbuf[tmpidx + cchan] += (unsigned char) blursum; + } /* for bx */ + } /* for by */ + } /* for ix */ + } /* for iy */ + } /* for cchan */ + /* copy back buffer */ + for (ix = 0 ; ix < teximage->height * teximage->width * 4; ix++) + teximage->data[ix] = tmpbuf[ix]; + } /*while blur */ + free(tmpbuf); /*tidy*/ + } /* if blur */ + + + + + clear_gl_error(); +#ifdef HAVE_GLBINDTEXTURE + glBindTexture(GL_TEXTURE_2D, texbind); + clear_gl_error(); /* WTF? sometimes "invalid op" from glBindTexture! */ +#endif + glPixelStorei(GL_UNPACK_ALIGNMENT, 4); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, teximage->width, teximage->height, + 0, GL_RGBA, GL_UNSIGNED_BYTE, teximage->data); + check_gl_error("texture"); + setTexParams(); + XDestroyImage(teximage); +} + +/* creates cylinder for time tunnel. sides, zmin, zmax, rad(ius) obvious. + stretch scales texture coords; makes tunnel go slower the larger it is. + not drawn, but put into display list. */ +static void makecyl(int sides, float zmin, float zmax, float rad, float stretch) +{ + int i; + float theta; + + /* cap */ + if (do_fog) { + glBegin(GL_TRIANGLE_FAN); + glTexCoord2f(1.0, 0.0); + glVertex3f(0.0 , 0.0 , zmax); + for (i = 0 ; i <= sides; i++) { + theta = 2.0 * M_PI * ((float) i / (float) sides); + glVertex3f(cos(theta) * rad, sin(theta) * rad, zmax); + } + glVertex3f(cos(0.0) * rad, sin(0.0) * rad, zmax); + glEnd(); + } + + glBegin(GL_QUAD_STRIP); + for (i = 0 ; i <= sides; i++) + { + if ( i != sides) { + theta = 2.0 * M_PI * ((float) i / (float) sides); + glTexCoord2f(0.0, 1.0 * (float) i / (float) sides); + glVertex3f(cos(theta) * rad, sin(theta) * rad, zmin); + glTexCoord2f(stretch, 1.0 * (float) i / (float) sides); + glVertex3f(cos(theta) * rad, sin(theta) * rad, zmax); + } else { + theta = 0.0; + glTexCoord2f(0.0, 1.0); + glVertex3f(cos(theta) * rad, sin(theta) * rad, zmin); + glTexCoord2f(stretch, 1.0); + glVertex3f(cos(theta) * rad, sin(theta) * rad, zmax); + } + } + glEnd(); +} + +ENTRYPOINT void +init_tunnel (ModeInfo *mi) +{ + int i; + + tunnel_configuration *tc; + + wire = MI_IS_WIREFRAME(mi); + +# ifdef HAVE_JWZGLES /* #### glPolygonMode other than GL_FILL unimplemented */ + wire = 0; +# endif + + if (!tconf) { + tconf = (tunnel_configuration *) + calloc (MI_NUM_SCREENS(mi), sizeof (tunnel_configuration)); + if (!tconf) { + fprintf(stderr, "%s: out of memory\n", progname); + exit(1); + } + } + + tc = &tconf[MI_SCREEN(mi)]; + + tc->glx_context = init_GL(mi); + + tc->cyllist = glGenLists(1); + tc->diamondlist = glGenLists(1); + tc->num_effects = 12; + tc->num_texshifts = 3; + tc->effect_time = 0.0; + tc->effect_maxsecs = 30.00; + /* check bounds on cmd line opts */ + if (start > tc->effect_maxsecs) start = tc->effect_maxsecs; + if (end > tc->effect_maxsecs) end = tc->effect_maxsecs; + if (start < tc->effect_time) start = tc->effect_time; + if (end < tc->effect_time) end = tc->effect_time; + + /* set loop times, in seconds */ + tc->start_time = start; + tc->end_time = end; + + /* reset animation knots, effect 0 not defined. */ + tc->effects = malloc(sizeof(effect_t) * ( tc->num_effects + 1)); + for ( i = 1; i <= tc->num_effects ; i++) + init_effects(&tc->effects[i], i); + + if (wire) { + glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); + do_texture = False; + } + + if (do_texture) + { + /* the following textures are loaded, and possible overridden: + tunnel 1, tunnel 2, tunnel 3, marquee, tardis, head */ + glGenTextures(MAX_TEXTURE, tc->texture_binds); + + /*LoadTexture(*mi, **fn, *filename, texbind, bluralpha, bw_color, anegative, onealpha)*/ + if (strcasecmp (do_tun1, "(none)")) /* tunnel 1 */ + LoadTexture(mi, NULL, do_tun1, tc->texture_binds[0], 0,0.0, False, False); + else + LoadTexture(mi, timetunnel0_xpm, NULL, tc->texture_binds[0], 0, 0.0, False, False); + if (strcasecmp (do_tun2, "(none)")) /* tunnel 2 */ + LoadTexture(mi, NULL, do_tun2, tc->texture_binds[2], 0,0.0, False, False); + else + LoadTexture(mi, timetunnel1_xpm, NULL, tc->texture_binds[2], 0, 0.0, False, False); + if (strcasecmp (do_tun3, "(none)")) /* tunnel 3 */ + LoadTexture(mi, NULL, do_tun3, tc->texture_binds[5], 0,0.0, False, False); + else + LoadTexture(mi, timetunnel2_xpm, NULL, tc->texture_binds[5], 0, 0.0, False, False); + LoadTexture(mi, tunnelstar_xpm, NULL, tc->texture_binds[4], 0, 0.0, False, False); + if (strcasecmp (do_tx1, "(none)")) /* marquee */ + LoadTexture(mi, NULL, do_tx1, tc->texture_binds[3], 0,0.0, False, False); +#ifndef HAVE_JWZGLES /* logo_180_xpm is 180px which is not a power of 2! */ + else + LoadTexture(mi, (char **) logo_180_xpm, NULL, tc->texture_binds[3], 0,0.0, False, False); +#endif + if (strcasecmp (do_tx2, "(none)")) /* tardis */ + LoadTexture(mi, NULL, do_tx2, tc->texture_binds[1], 0, 0.0 ,False, False); +#ifndef HAVE_JWZGLES /* logo_180_xpm is 180px which is not a power of 2! */ + else + LoadTexture(mi, (char **) logo_180_xpm, NULL, tc->texture_binds[1], 0,0.0, False, False); +#endif + if (strcasecmp (do_tx3, "(none)")) { /* head */ + LoadTexture(mi, NULL, do_tx3, tc->texture_binds[6], 0, 0.0 ,False, False); + /* negative */ + LoadTexture(mi, NULL, do_tx3, tc->texture_binds[9], 2,1.0, True, True); +#ifndef HAVE_JWZGLES /* logo_180_xpm is 180px which is not a power of 2! */ + } else { + LoadTexture(mi, (char **) logo_180_xpm, NULL, tc->texture_binds[6], 0,0.0, False, False); + /* negative */ + LoadTexture(mi, (char **) logo_180_xpm, NULL, tc->texture_binds[9], 2,1.0, True, True); +#endif + } + glEnable(GL_TEXTURE_2D); + check_gl_error("tex"); + } + + reshape_tunnel (mi, MI_WIDTH(mi), MI_HEIGHT(mi)); + + glDisable(GL_DEPTH_TEST); /* who needs it? ;-) */ + + if (do_fog) + glEnable(GL_FOG); + + if (!wire) + { + glEnable(GL_ALPHA_TEST); + glAlphaFunc(GL_GREATER, 0.5); + } + + tc->trackball = gltrackball_init (); + + + tc->texshift = calloc(tc->num_texshifts, sizeof(GLfloat)); + for ( i = 0 ; i < tc->num_texshifts; i++) + tc->texshift[i] = 0.0; + + glNewList(tc->cyllist, GL_COMPILE); + makecyl(30, -0.1, CYL_LEN, 1., 10. / 40.0 * CYL_LEN); + /*makecyl(30, -0.5, DIAMOND_LEN, 1., 4. / 40 * DIAMOND_LEN); */ + glEndList(); + + glNewList(tc->diamondlist, GL_COMPILE); + makecyl(4, -0.5, DIAMOND_LEN, 1., 4. / 40 * DIAMOND_LEN); + glEndList(); +} + + +ENTRYPOINT void +draw_tunnel (ModeInfo *mi) +{ + tunnel_configuration *tc = &tconf[MI_SCREEN(mi)]; + Display *dpy = MI_DISPLAY(mi); + Window window = MI_WINDOW(mi); + + + if (!tc->glx_context) + return; + + glXMakeCurrent(MI_DISPLAY(mi), MI_WINDOW(mi), *(tc->glx_context)); + + glShadeModel(GL_SMOOTH); + + glEnable(GL_NORMALIZE); + /* glEnable(GL_CULL_FACE); */ + + glClear(GL_COLOR_BUFFER_BIT ); + + update_animation(tc); + + + glPushMatrix (); + + glRotatef(180., 0., 1., 0.); + gltrackball_rotate (tc->trackball); + glRotatef(180., 0., 1., 0.); + + + + mi->polygon_count = 0; + + update_fog(tc->effects[4].state[0], /*color*/ + tc->effects[4].state[1], /*density*/ + tc->effects[4].state[2], /*start*/ + tc->effects[4].state[3]); /*end*/ + + /* --- begin composite image assembly --- */ + + /* head mask and draw diamond tunnel */ + + glEnable(GL_BLEND); + draw_cyl(mi, tc, tc->effects[6].state[0], 5, tc->diamondlist, 2); + if (drawlogo) + draw_sign(mi, tc,tc->effects[12].state[0], tc->effects[12].state[1], 1.0 / 1.33, 9, 1); + glDisable(GL_BLEND); + /* then tardis tunnel */ + make_wall_tunnel(mi, tc, tc->effects[1].state[0], tc->effects[7].state[0]); + + /* then cylinder tunnel */ + glEnable(GL_BLEND); + draw_cyl(mi, tc, tc->effects[3].state[0], 2, tc->cyllist, 1); + + /*void draw_sign(mi, tc,z,alpha,aspect,tex,blendmode)*/ + /* tardis */ + if (drawlogo) + draw_sign(mi, tc, tc->effects[2].state[0], tc->effects[2].state[1], 2.0, 1, 0); + /* marquee */ + if (drawlogo) + draw_sign(mi, tc, tc->effects[5].state[0], tc->effects[5].state[1], 1.0, 3, 0); + /*who head brite*/ + if (drawlogo) + draw_sign(mi, tc,1.0, tc->effects[10].state[0], 1.0 / 1.33, 6, 2); + /*who head psychadelic REMOVED*/ + /* draw_sign(mi, tc,1.0, tc->effects[11].state[0], 1.0 / 1.33, 8, 0); */ + + /* star */ + /* draw_sign(mi, tc, tc->effects[8].state[0]tc->effects[8].state[0], 1.0 , 1.0, 4, 1); */ + draw_sign(mi, tc, tc->effects[8].state[0], tc->effects[8].state[0], 1.0, 4, 1); + + /* normal head */ + if (drawlogo) + draw_sign(mi, tc,1.0, tc->effects[9].state[0], 1.0 / 1.33, 6, 0); + + /* --- end composite image assembly --- */ + + + glPopMatrix (); + + if (mi->fps_p) do_fps (mi); + glFinish(); + + check_gl_error("drawing done, calling swap buffers"); + glXSwapBuffers(dpy, window); +} + +XSCREENSAVER_MODULE_2 ("TimeTunnel", timetunnel, tunnel) + +#endif /* USE_GL */ diff --git a/hacks/glx/timetunnel.man b/hacks/glx/timetunnel.man new file mode 100644 index 00000000..cdd6af5b --- /dev/null +++ b/hacks/glx/timetunnel.man @@ -0,0 +1,105 @@ +.TH XScreenSaver 1 "" "X Version 11" +.SH NAME +timetunnel - Plasma tunnels fade in and out +.SH SYNOPSIS +.B timetunnel +[\-display \fIhost:display.screen\fP] +[\-visual \fIvisual\fP] +[\-window] +[\-root] +[\-start \fInumber\fP] +[\-end \fInumber\fP] +[\-dilate \fInumber\fP] +[\-no-logo] +[\-reverse] +[\-no-fog] +[\-no-texture] +[\-wireframe] +[\-fps] +[\-tardis \fItexture\fP] +[\-head \fItexture\fP] +[\-marquee \fItexture\fP] +[\-tun1 \fItexture\fP] +[\-tun2 \fItexture\fP] +[\-tun3 \fItexture\fP] +.SH DESCRIPTION +Draws an animation similar to the opening and closing effects on the +Dr. Who television show. +.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 \-start \fInumber\fP +Start time of loop, 0.0 - 30.00. Default 0.0. May be identical to end time. +.TP 8 +.B \-end \fInumber\fP +End time of loop, 0.0 - 30.00. Default 27.79. May be identical to start time. +.TP 8 +.B \-dilate \fInumber\fP +Scale time to speed or slow simulation. Numbers less than one slow it down. +.TP 8 +.B \-no-logo +Show only tunnels, no logos, etc. +.TP 8 +.B \-reverse +Play in reverse, including tunnels. +.TP 8 +.B \-no-fog +Turn off fog. +.TP 8 +.B \-no-texture +Turn off textures. +.TP 8 +.B \-wireframe +Show as wire frame. +.TP 8 +.B \-fps | \-no-fps +Whether to show a frames-per-second display at the bottom of the screen. +.TP 8 +.B \-tardis \fItexture\fP +Specify an xpm file to override default tardis texture. +.TP 8 +.B \-head \fItexture\fP +Specify an xpm file to override default Dr. Who head texture. +.TP 8 +.B \-marquee \fItexture\fP +Specify an xpm file to override default show marquee texture. +.TP 8 +.B \-tun1 \fItexture\fP +Specify an xpm file to override default tardis tunnel texture. +.TP 8 +.B \-tun2 \fItexture\fP +Specify an xpm file to override default middle tunnel texture. +.TP 8 +.B \-tun3 \fItexture\fP +Specify an xpm file to override default final tunnel texture. +.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 2005 by Sean Brennan. 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 +Sean Brennan diff --git a/hacks/glx/toast.c b/hacks/glx/toast.c new file mode 100644 index 00000000..e2ea6024 --- /dev/null +++ b/hacks/glx/toast.c @@ -0,0 +1,185 @@ +#include "gllist.h" +static const float data[]={ + 0,0,0,0.391859,-0.5,0.047937, + -0.767086,-0.641544,0,-0.3866,-0.5,-0.047937, + 0.794299,-0.607527,0,0.391859,-0.5,-0.047937, + -0.767086,-0.641544,0,-0.3866,-0.5,-0.047937, + 0,0,0,0.391859,-0.5,0.047937, + 0.794299,-0.607527,0,-0.3866,-0.5,0.047937, + 0.94718,-0.320703,0,0.448134,-0.426425,-0.047937, + 1,0,0,0.391859,-0.5,0.047937, + 0.94718,-0.320703,0,0.391859,-0.5,-0.047937, + 1,0,0,0.391859,-0.5,0.047937, + 0.94718,-0.320703,0,0.448134,-0.426425,-0.047937, + 1,0,0,0.448134,-0.426425,0.047937, + 0.919578,0.392907,0,0.448134,0.061584,-0.047937, + 1,0,0,0.448134,-0.426425,0.047937, + 0.94718,-0.320703,0,0.448134,-0.426425,-0.047937, + 1,0,0,0.448134,-0.426425,0.047937, + 0.919578,0.392907,0,0.448134,0.061584,-0.047937, + 1,0,0,0.448134,0.061584,0.047937, + 0.15469,0.987963,0,-0.3866,0.438467,0.047937, + -0.987898,0.155108,0,-0.448134,0.247342,-0.047937, + -0.306512,0.951867,0,-0.448134,0.247342,0.047937, + -0.987898,0.155108,0,-0.448134,0.247342,-0.047937, + 0.15469,0.987963,0,-0.3866,0.438467,0.047937, + -0.306512,0.951867,0,-0.3866,0.438467,-0.047937, + -0.306512,0.951867,0,-0.448134,0.247342,0.047937, + -0.757441,-0.652904,0,-0.448134,0.184705,-0.047937, + -0.757441,-0.652904,0,-0.448134,0.184705,0.047937, + -0.757441,-0.652904,0,-0.448134,0.184705,-0.047937, + -0.306512,0.951867,0,-0.448134,0.247342,0.047937, + -0.987898,0.155108,0,-0.448134,0.247342,-0.047937, + 0.484474,0.874806,0,-0.3866,0.438467,0.047937, + 0,1,0,-0.195512,0.5,-0.047937, + -0.306512,0.951867,0,-0.3866,0.438467,-0.047937, + 0,1,0,-0.195512,0.5,-0.047937, + 0.484474,0.874806,0,-0.3866,0.438467,0.047937, + 0.484474,0.874806,0,-0.195512,0.5,0.047937, + 1,0,0,0.448134,0.247342,-0.047937, + 0.999987,0.005091,0,0.448134,0.184705,0.047937, + 0.922977,-0.384855,0,0.448134,0.184705,-0.047937, + 0.999987,0.005091,0,0.448134,0.184705,0.047937, + 1,0,0,0.448134,0.247342,-0.047937, + 0.999987,0.005091,0,0.448134,0.247342,0.047937, + 0.703967,0.710233,0,0.384905,0.438467,-0.047937, + 0.999987,0.005091,0,0.448134,0.247342,0.047937, + 1,0,0,0.448134,0.247342,-0.047937, + 0.999987,0.005091,0,0.448134,0.247342,0.047937, + 0.703967,0.710233,0,0.384905,0.438467,-0.047937, + 0.703967,0.710233,0,0.384905,0.438467,0.047937, + 0,0,-1,-0.3866,0.438467,-0.047937, + 0,0,-1,-0.448134,0.184705,-0.047937, + 0,0,-1,-0.448134,0.247342,-0.047937, + 0,0,-1,-0.448134,0.184705,-0.047937, + 0,0,-1,-0.3866,0.438467,-0.047937, + 0,0,-1,-0.394142,0.122068,-0.047937, + 0,0,-1,0.448134,0.247342,-0.047937, + 0,0,0,0.384905,0.122068,-0.047937, + 0,0,0,0.384905,0.438467,-0.047937, + 0,0,0,0.384905,0.122068,-0.047937, + 0,0,-1,0.448134,0.247342,-0.047937, + 0,0,-1,0.448134,0.184705,-0.047937, + 0,0,-1,-0.394142,0.122068,-0.047937, + 0,0,-1,-0.448134,-0.426425,-0.047937, + 0,0,-1,-0.448134,0.061584,-0.047937, + 0,0,-1,-0.448134,-0.426425,-0.047937, + 0,0,-1,-0.394142,0.122068,-0.047937, + 0,0,-1,-0.3866,-0.5,-0.047937, + 0,0,-1,-0.3866,-0.5,-0.047937, + 0,0,-1,-0.394142,0.122068,-0.047937, + 0,0,-1,-0.3866,0.438467,-0.047937, + 0,0,-1,-0.3866,-0.5,-0.047937, + 0,0,-1,-0.3866,0.438467,-0.047937, + 0,0,-1,-0.195512,0.5,-0.047937, + 0,0,-1,-0.3866,-0.5,-0.047937, + 0,0,-1,-0.195512,0.5,-0.047937, + 0,0,-1,0.391859,-0.5,-0.047937, + 0,0,-1,0.391859,-0.5,-0.047937, + 0,0,-1,-0.195512,0.5,-0.047937, + 0,0,0,0.193226,0.5,-0.047937, + 0,0,-1,0.391859,-0.5,-0.047937, + 0,0,0,0.193226,0.5,-0.047937, + 0,0,0,0.384905,0.122068,-0.047937, + 0,0,0,0.384905,0.122068,-0.047937, + 0,0,0,0.193226,0.5,-0.047937, + 0,0,0,0.384905,0.438467,-0.047937, + 0,0,-1,0.391859,-0.5,-0.047937, + 0,0,0,0.384905,0.122068,-0.047937, + 0,0,0,0.448134,0.061584,-0.047937, + 0,0,-1,0.391859,-0.5,-0.047937, + 0,0,0,0.448134,0.061584,-0.047937, + 0,0,-1,0.448134,-0.426425,-0.047937, + 0.703967,0.710233,0,0.193226,0.5,0.047937, + 0.703967,0.710233,0,0.384905,0.438467,-0.047937, + 0.484474,0.874806,0,0.193226,0.5,-0.047937, + 0.703967,0.710233,0,0.384905,0.438467,-0.047937, + 0.703967,0.710233,0,0.193226,0.5,0.047937, + 0.703967,0.710233,0,0.384905,0.438467,0.047937, + 0.484474,0.874806,0,-0.195512,0.5,0.047937, + 0.484474,0.874806,0,0.193226,0.5,-0.047937, + 0,1,0,-0.195512,0.5,-0.047937, + 0.484474,0.874806,0,0.193226,0.5,-0.047937, + 0.484474,0.874806,0,-0.195512,0.5,0.047937, + 0.703967,0.710233,0,0.193226,0.5,0.047937, + 0.919578,0.392907,0,0.384905,0.122068,0.047937, + 0.919578,0.392907,0,0.448134,0.061584,-0.047937, + 0.919578,0.392907,0,0.384905,0.122068,-0.047937, + 0.919578,0.392907,0,0.448134,0.061584,-0.047937, + 0.919578,0.392907,0,0.384905,0.122068,0.047937, + 1,0,0,0.448134,0.061584,0.047937, + -0.999962,0.008668,0,-0.448134,0.061584,0.047937, + -0.93997,-0.341258,0,-0.448134,-0.426425,-0.047937, + -0.93997,-0.341258,0,-0.448134,-0.426425,0.047937, + -0.93997,-0.341258,0,-0.448134,-0.426425,-0.047937, + -0.999962,0.008668,0,-0.448134,0.061584,0.047937, + -0.746008,0.665937,0,-0.448134,0.061584,-0.047937, + -0.93997,-0.341258,0,-0.448134,-0.426425,0.047937, + -0.93997,-0.341258,0,-0.3866,-0.5,-0.047937, + 0,0,0,-0.3866,-0.5,0.047937, + -0.93997,-0.341258,0,-0.3866,-0.5,-0.047937, + -0.93997,-0.341258,0,-0.448134,-0.426425,0.047937, + -0.93997,-0.341258,0,-0.448134,-0.426425,-0.047937, + 0.922977,-0.384855,0,0.448134,0.184705,0.047937, + 0.922977,-0.384855,0,0.384905,0.122068,-0.047937, + 0.922977,-0.384855,0,0.448134,0.184705,-0.047937, + 0.922977,-0.384855,0,0.384905,0.122068,-0.047937, + 0.922977,-0.384855,0,0.448134,0.184705,0.047937, + 0.922977,-0.384855,0,0.384905,0.122068,0.047937, + -0.999962,0.008668,0,-0.394142,0.122068,0.047937, + -0.746008,0.665937,0,-0.448134,0.061584,-0.047937, + -0.999962,0.008668,0,-0.448134,0.061584,0.047937, + -0.746008,0.665937,0,-0.448134,0.061584,-0.047937, + -0.999962,0.008668,0,-0.394142,0.122068,0.047937, + -0.757441,-0.652904,0,-0.394142,0.122068,-0.047937, + -0.757441,-0.652904,0,-0.448134,0.184705,0.047937, + -0.757441,-0.652904,0,-0.394142,0.122068,-0.047937, + -0.999962,0.008668,0,-0.394142,0.122068,0.047937, + -0.757441,-0.652904,0,-0.394142,0.122068,-0.047937, + -0.757441,-0.652904,0,-0.448134,0.184705,0.047937, + -0.757441,-0.652904,0,-0.448134,0.184705,-0.047937, + 0,0,1,-0.3866,-0.5,0.047937, + 0,0,1,-0.448134,0.061584,0.047937, + 0,0,1,-0.448134,-0.426425,0.047937, + 0,0,1,-0.448134,0.061584,0.047937, + 0,0,1,-0.3866,-0.5,0.047937, + 0,0,1,-0.394142,0.122068,0.047937, + 0,0,1,-0.394142,0.122068,0.047937, + 0,0,1,-0.448134,0.247342,0.047937, + 0,0,1,-0.448134,0.184705,0.047937, + 0,0,1,-0.448134,0.247342,0.047937, + 0,0,1,-0.394142,0.122068,0.047937, + 0,0,1,-0.3866,0.438467,0.047937, + 0,0,1,-0.3866,0.438467,0.047937, + 0,0,1,-0.394142,0.122068,0.047937, + 0,0,1,-0.3866,-0.5,0.047937, + 0,0,1,-0.3866,0.438467,0.047937, + 0,0,1,-0.3866,-0.5,0.047937, + 0,0,1,0.391859,-0.5,0.047937, + 0,0,1,-0.3866,0.438467,0.047937, + 0,0,1,0.391859,-0.5,0.047937, + 0,0,1,-0.195512,0.5,0.047937, + 0,0,1,-0.195512,0.5,0.047937, + 0,0,1,0.391859,-0.5,0.047937, + 0,0,1,0.193226,0.5,0.047937, + 0,0,1,0.193226,0.5,0.047937, + 0,0,1,0.391859,-0.5,0.047937, + 0,0,1,0.384905,0.122068,0.047937, + 0,0,1,0.193226,0.5,0.047937, + 0,0,1,0.384905,0.122068,0.047937, + 0,0,1,0.384905,0.438467,0.047937, + 0,0,1,0.384905,0.122068,0.047937, + 0,0,1,0.391859,-0.5,0.047937, + 0,0,1,0.448134,0.061584,0.047937, + 0,0,1,0.448134,0.061584,0.047937, + 0,0,1,0.391859,-0.5,0.047937, + 0,0,1,0.448134,-0.426425,0.047937, + 0,0,1,0.384905,0.122068,0.047937, + 0,0,1,0.448134,0.247342,0.047937, + 0,0,1,0.384905,0.438467,0.047937, + 0,0,1,0.448134,0.247342,0.047937, + 0,0,1,0.384905,0.122068,0.047937, + 0,0,1,0.448134,0.184705,0.047937 +}; +static const struct gllist frame={GL_N3F_V3F,GL_TRIANGLES,180,data,NULL}; +const struct gllist *toast=&frame; diff --git a/hacks/glx/toast2.c b/hacks/glx/toast2.c new file mode 100644 index 00000000..1f38415b --- /dev/null +++ b/hacks/glx/toast2.c @@ -0,0 +1,209 @@ +#include "gllist.h" +static const float data[]={ + -0.999962,0.008668,0,-0.394142,0.122068,0.047937, + -0.934347,0.356365,0,-0.448134,0.061584,-0.047937, + -0.934347,0.356365,0,-0.448134,0.061584,0.047937, + -0.934347,0.356365,0,-0.448134,0.061584,-0.047937, + -0.999962,0.008668,0,-0.394142,0.122068,0.047937, + 0,0,0,-0.394142,0.122068,-0.047937, + -0.937401,-0.348252,0,-0.448134,0.184705,0.047937, + 0,0,0,-0.394142,0.122068,-0.047937, + -0.999962,0.008668,0,-0.394142,0.122068,0.047937, + 0,0,0,-0.394142,0.122068,-0.047937, + -0.937401,-0.348252,0,-0.448134,0.184705,0.047937, + -1,0,0,-0.448134,0.184705,-0.047937, + 0,0,0,0.448134,0.247342,-0.047937, + 0,0,0,0.384905,0.122068,-0.047937, + 0,0,0,0.384905,0.438467,-0.047937, + 0,0,0,0.384905,0.122068,-0.047937, + 0,0,0,0.448134,0.247342,-0.047937, + 0,0,-1,0.448134,0.184705,-0.047937, + 0,0,0,-0.233894,0.20122,-0.047937, + 0,0,-1,-0.448134,0.184705,-0.047937, + 0,0,-1,-0.448134,0.247342,-0.047937, + 0,0,-1,-0.448134,0.184705,-0.047937, + 0,0,0,-0.233894,0.20122,-0.047937, + 0,0,-1,-0.394142,0.122068,-0.047937, + 0,0,-1,-0.394142,0.122068,-0.047937, + 0,0,0,-0.233894,0.20122,-0.047937, + 0,0,-1,-0.3866,-0.5,-0.047937, + 0,0,-1,-0.3866,-0.5,-0.047937, + 0,0,0,-0.233894,0.20122,-0.047937, + 0,0,-1,0.391859,-0.5,-0.047937, + 0,0,-1,0.391859,-0.5,-0.047937, + 0,0,0,-0.233894,0.20122,-0.047937, + 0,0,0,-0.092355,0.236111,-0.047937, + 0,0,-1,0.391859,-0.5,-0.047937, + 0,0,0,-0.092355,0.236111,-0.047937, + 0,0,0,-0.001143,0.324361,-0.047937, + 0,0,-1,0.391859,-0.5,-0.047937, + 0,0,0,-0.001143,0.324361,-0.047937, + 0,0,-1,0.039021,0.5,-0.047937, + 0,0,-1,0.391859,-0.5,-0.047937, + 0,0,-1,0.039021,0.5,-0.047937, + 0,0,0,0.193226,0.5,-0.047937, + 0,0,-1,0.391859,-0.5,-0.047937, + 0,0,0,0.193226,0.5,-0.047937, + 0,0,0,0.384905,0.122068,-0.047937, + 0,0,0,0.384905,0.122068,-0.047937, + 0,0,0,0.193226,0.5,-0.047937, + 0,0,0,0.384905,0.438467,-0.047937, + 0,0,-1,0.391859,-0.5,-0.047937, + 0,0,0,0.384905,0.122068,-0.047937, + 0,0,0,0.448134,0.061584,-0.047937, + 0,0,-1,0.391859,-0.5,-0.047937, + 0,0,0,0.448134,0.061584,-0.047937, + 0,0,0,0.448134,-0.426425,-0.047937, + 0,0,-1,-0.394142,0.122068,-0.047937, + 0,0,-1,-0.448134,-0.426425,-0.047937, + 0,0,-1,-0.448134,0.061584,-0.047937, + 0,0,-1,-0.448134,-0.426425,-0.047937, + 0,0,-1,-0.394142,0.122068,-0.047937, + 0,0,-1,-0.3866,-0.5,-0.047937, + 0,0,1,-0.3866,-0.5,0.047937, + 0,0,0,-0.448134,0.061584,0.047937, + 0,0,0,-0.448134,-0.426425,0.047937, + 0,0,0,-0.448134,0.061584,0.047937, + 0,0,1,-0.3866,-0.5,0.047937, + 0,0,1,-0.394142,0.122068,0.047937, + 0,0,1,-0.394142,0.122068,0.047937, + 0,0,0,-0.448134,0.247342,0.047937, + 0,0,1,-0.448134,0.184705,0.047937, + 0,0,0,-0.448134,0.247342,0.047937, + 0,0,1,-0.394142,0.122068,0.047937, + 0,0,1,-0.233894,0.20122,0.047937, + 0,0,1,-0.233894,0.20122,0.047937, + 0,0,1,-0.394142,0.122068,0.047937, + 0,0,1,-0.3866,-0.5,0.047937, + 0,0,1,-0.233894,0.20122,0.047937, + 0,0,1,-0.3866,-0.5,0.047937, + 0,0,1,0.391859,-0.5,0.047937, + 0,0,1,-0.233894,0.20122,0.047937, + 0,0,1,0.391859,-0.5,0.047937, + 0,0,1,-0.092355,0.236111,0.047937, + 0,0,1,-0.092355,0.236111,0.047937, + 0,0,1,0.391859,-0.5,0.047937, + 0,0,1,-0.001143,0.324361,0.047937, + 0,0,1,-0.001143,0.324361,0.047937, + 0,0,1,0.391859,-0.5,0.047937, + 0,0,1,0.039021,0.5,0.047937, + 0,0,1,0.039021,0.5,0.047937, + 0,0,1,0.391859,-0.5,0.047937, + 0,0,1,0.193226,0.5,0.047937, + 0,0,1,0.193226,0.5,0.047937, + 0,0,1,0.391859,-0.5,0.047937, + 0,0,1,0.384905,0.122068,0.047937, + 0,0,1,0.193226,0.5,0.047937, + 0,0,1,0.384905,0.122068,0.047937, + 0,0,1,0.384905,0.438467,0.047937, + 0,0,1,0.384905,0.122068,0.047937, + 0,0,1,0.391859,-0.5,0.047937, + 0,0,1,0.448134,0.061584,0.047937, + 0,0,1,0.448134,0.061584,0.047937, + 0,0,1,0.391859,-0.5,0.047937, + 0,0,1,0.448134,-0.426425,0.047937, + 0,0,1,0.384905,0.122068,0.047937, + 0,0,1,0.448134,0.247342,0.047937, + 0,0,1,0.384905,0.438467,0.047937, + 0,0,1,0.448134,0.247342,0.047937, + 0,0,1,0.384905,0.122068,0.047937, + 0,0,1,0.448134,0.184705,0.047937, + 0.210457,0.977603,0,-0.448134,0.247342,0.047937, + -0.014824,0.99989,0,-0.233894,0.20122,-0.047937, + 0.210457,0.977603,0,-0.448134,0.247342,-0.047937, + -0.014824,0.99989,0,-0.233894,0.20122,-0.047937, + 0.210457,0.977603,0,-0.448134,0.247342,0.047937, + -0.239346,0.970934,0,-0.233894,0.20122,0.047937, + 0,1,0,0.039021,0.5,0.047937, + -0.871101,0.491104,0,-0.001143,0.324361,-0.047937, + -0.871101,0.491104,0,-0.001143,0.324361,0.047937, + -0.871101,0.491104,0,-0.001143,0.324361,-0.047937, + 0,1,0,0.039021,0.5,0.047937, + -0.623331,0.781958,0,0.039021,0.5,-0.047937, + -0.239346,0.970934,0,-0.233894,0.20122,0.047937, + -0.484063,0.875033,0,-0.092355,0.236111,-0.047937, + -0.014824,0.99989,0,-0.233894,0.20122,-0.047937, + -0.484063,0.875033,0,-0.092355,0.236111,-0.047937, + -0.239346,0.970934,0,-0.233894,0.20122,0.047937, + -0.871101,0.491104,0,-0.092355,0.236111,0.047937, + -0.871101,0.491104,0,-0.092355,0.236111,0.047937, + -0.871101,0.491104,0,-0.001143,0.324361,-0.047937, + -0.484063,0.875033,0,-0.092355,0.236111,-0.047937, + -0.871101,0.491104,0,-0.001143,0.324361,-0.047937, + -0.871101,0.491104,0,-0.092355,0.236111,0.047937, + -0.871101,0.491104,0,-0.001143,0.324361,0.047937, + -1,0,0,-0.448134,0.247342,0.047937, + -1,0,0,-0.448134,0.184705,-0.047937, + -0.937401,-0.348252,0,-0.448134,0.184705,0.047937, + -1,0,0,-0.448134,0.184705,-0.047937, + -1,0,0,-0.448134,0.247342,0.047937, + -1,0,0,-0.448134,0.247342,-0.047937, + 0,1,0,0.039021,0.5,0.047937, + 0.15469,0.987963,0,0.193226,0.5,-0.047937, + -0.623331,0.781958,0,0.039021,0.5,-0.047937, + 0.15469,0.987963,0,0.193226,0.5,-0.047937, + 0,1,0,0.039021,0.5,0.047937, + 0.305656,0.952142,0,0.193226,0.5,0.047937, + 0.305656,0.952142,0,0.193226,0.5,0.047937, + 0.703967,0.710233,0,0.384905,0.438467,-0.047937, + 0.15469,0.987963,0,0.193226,0.5,-0.047937, + 0.703967,0.710233,0,0.384905,0.438467,-0.047937, + 0.305656,0.952142,0,0.193226,0.5,0.047937, + 0.703967,0.710233,0,0.384905,0.438467,0.047937, + 0.703967,0.710233,0,0.384905,0.438467,-0.047937, + 0.871946,0.489602,0,0.448134,0.247342,0.047937, + 0.871946,0.489602,0,0.448134,0.247342,-0.047937, + 0.871946,0.489602,0,0.448134,0.247342,0.047937, + 0.703967,0.710233,0,0.384905,0.438467,-0.047937, + 0.703967,0.710233,0,0.384905,0.438467,0.047937, + 0.871946,0.489602,0,0.448134,0.247342,-0.047937, + 0.703773,-0.710425,0,0.448134,0.184705,0.047937, + 0.922977,-0.384855,0,0.448134,0.184705,-0.047937, + 0.703773,-0.710425,0,0.448134,0.184705,0.047937, + 0.871946,0.489602,0,0.448134,0.247342,-0.047937, + 0.871946,0.489602,0,0.448134,0.247342,0.047937, + 0.703773,-0.710425,0,0.448134,0.184705,0.047937, + 0.703773,-0.710425,0,0.384905,0.122068,-0.047937, + 0.922977,-0.384855,0,0.448134,0.184705,-0.047937, + 0.703773,-0.710425,0,0.384905,0.122068,-0.047937, + 0.703773,-0.710425,0,0.448134,0.184705,0.047937, + 0,0,0,0.384905,0.122068,0.047937, + 0.691249,0.722617,0,0.384905,0.122068,0.047937, + 0.919578,0.392907,0,0.448134,0.061584,-0.047937, + 0.691249,0.722617,0,0.384905,0.122068,-0.047937, + 0.919578,0.392907,0,0.448134,0.061584,-0.047937, + 0.691249,0.722617,0,0.384905,0.122068,0.047937, + 0.919578,0.392907,0,0.448134,0.061584,0.047937, + 0.919578,0.392907,0,0.448134,0.061584,-0.047937, + 0.99893,0.046254,0,0.448134,-0.426425,0.047937, + 0.99893,0.046254,0,0.448134,-0.426425,-0.047937, + 0.99893,0.046254,0,0.448134,-0.426425,0.047937, + 0.919578,0.392907,0,0.448134,0.061584,-0.047937, + 0.919578,0.392907,0,0.448134,0.061584,0.047937, + 0.99893,0.046254,0,0.448134,-0.426425,-0.047937, + 0,-1,0,0.391859,-0.5,0.047937, + 0.442986,-0.896528,0,0.391859,-0.5,-0.047937, + 0,-1,0,0.391859,-0.5,0.047937, + 0.99893,0.046254,0,0.448134,-0.426425,-0.047937, + 0.99893,0.046254,0,0.448134,-0.426425,0.047937, + 0,-1,0,0.391859,-0.5,0.047937, + -0.767086,-0.641544,0,-0.3866,-0.5,-0.047937, + 0.442986,-0.896528,0,0.391859,-0.5,-0.047937, + -0.767086,-0.641544,0,-0.3866,-0.5,-0.047937, + 0,-1,0,0.391859,-0.5,0.047937, + -0.423353,-0.905965,0,-0.3866,-0.5,0.047937, + -0.93997,-0.341258,0,-0.448134,-0.426425,0.047937, + -0.767086,-0.641544,0,-0.3866,-0.5,-0.047937, + -0.423353,-0.905965,0,-0.3866,-0.5,0.047937, + -0.767086,-0.641544,0,-0.3866,-0.5,-0.047937, + -0.93997,-0.341258,0,-0.448134,-0.426425,0.047937, + -0.934347,0.356365,0,-0.448134,-0.426425,-0.047937, + -0.934347,0.356365,0,-0.448134,0.061584,0.047937, + -0.934347,0.356365,0,-0.448134,-0.426425,-0.047937, + -0.93997,-0.341258,0,-0.448134,-0.426425,0.047937, + -0.934347,0.356365,0,-0.448134,-0.426425,-0.047937, + -0.934347,0.356365,0,-0.448134,0.061584,0.047937, + -0.934347,0.356365,0,-0.448134,0.061584,-0.047937 +}; +static const struct gllist frame={GL_N3F_V3F,GL_TRIANGLES,204,data,NULL}; +const struct gllist *toast2=&frame; diff --git a/hacks/glx/toaster.c b/hacks/glx/toaster.c new file mode 100644 index 00000000..3258730e --- /dev/null +++ b/hacks/glx/toaster.c @@ -0,0 +1,371 @@ +#include "gllist.h" +static const float data[]={ + -0.083557,-0.996461,-0.009165,-0.283103,-0.467335,0.222248, + -0.083557,-0.996461,-0.009165,-0.234168,-0.483652,-0.380912, + -0.132836,-0.912766,0.386282,-0.234168,-0.483652,0.222248, + 0.016318,0.569809,0.821615,-0.001224,0.5,0.222248, + -0.630337,0.598312,0.494671,-0.234168,0.483652,-0.380912, + -0.630337,0.598312,0.494671,-0.234168,0.483652,0.222248, + 0,-0.593633,0.804736,-0.17891,-0.455225,0.279296, + -0.132836,-0.912766,0.386282,-0.234168,-0.483652,0.222248, + 0.256797,-0.68367,0.683119,-0.001224,-0.5,0.222248, + -0.690527,-0.541416,0.479627,-0.345926,0,-0.380912, + -0.593343,-0.615334,0.518949,-0.299415,-0.418387,-0.380912, + -0.716279,-0.483147,0.503502,-0.331315,-0.208938,0.222248, + 0.976636,0.081646,0.198785,0.331315,0.208938,0.222248, + 0.974495,-0.224383,-0.003566,0.331315,-0.208938,0.222248, + 0.976696,-0.21451,-0.007138,0.345926,0,-0.380912, + 0.016318,0.569809,0.821615,-0.001224,0.5,0.222248, + 0.136339,0.966309,0.218307,0.234168,0.483652,-0.380912, + -0.630337,0.598312,0.494671,-0.234168,0.483652,-0.380912, + -0.132836,-0.912766,0.386282,-0.234168,-0.483652,0.222248, + -0.083557,-0.996461,-0.009165,-0.234168,-0.483652,-0.380912, + 0.256797,-0.68367,0.683119,-0.001224,-0.5,0.222248, + 0.987814,0.154993,0.014136,0.292931,0.437844,-0.141156, + 0.972186,0.234211,0,0.299415,0.418387,0.222248, + 0.998455,0.055333,0.005018,0.299415,0.418387,-0.380912, + 0.972186,0.234211,0,0.299415,0.418387,0.222248, + 0.987814,0.154993,0.014136,0.292931,0.437844,-0.141156, + 0.332175,0.255552,0.907939,0.283103,0.467335,0.222248, + 0.332175,0.255552,0.907939,0.283103,0.467335,0.222248, + 0.987814,0.154993,0.014136,0.292931,0.437844,-0.141156, + 0.707166,0.707048,0,0.288017,0.45259,0.040546, + 0.332175,0.255552,0.907939,0.283103,0.467335,0.222248, + 0.136339,0.966309,0.218307,0.283103,0.467335,-0.380912, + 0.016318,0.569809,0.821615,0.234168,0.483652,0.222248, + 0.136339,0.966309,0.218307,0.283103,0.467335,-0.380912, + 0.987814,0.154993,0.014136,0.292931,0.437844,-0.141156, + 0.894538,0.049574,-0.444235,0.299415,0.418387,-0.380912, + 0.987814,0.154993,0.014136,0.292931,0.437844,-0.141156, + 0.136339,0.966309,0.218307,0.283103,0.467335,-0.380912, + 0.707166,0.707048,0,0.288017,0.45259,0.040546, + 0.707166,0.707048,0,0.288017,0.45259,0.040546, + 0.136339,0.966309,0.218307,0.283103,0.467335,-0.380912, + 0.332175,0.255552,0.907939,0.283103,0.467335,0.222248, + 0,0.227898,0.973685,0.054097,0.251982,0.357142, + 0,0.227898,0.973685,-0.054097,0.251982,0.357142, + 0,-0.183338,0.98305,0.05339,0,0.380912, + -0.753212,-0.381237,0.536031,-0.257344,0.251982,0.320299, + -0.699045,0.10647,0.707107,-0.31207,0.335293,0.222248, + -0.753212,-0.381237,0.536031,-0.331315,0.208938,0.222248, + -0.699045,0.10647,0.707107,-0.31207,0.335293,0.222248, + -0.753212,-0.381237,0.536031,-0.257344,0.251982,0.320299, + -0.680969,0.208836,0.701903,-0.299415,0.418387,0.222248, + 0,0,1,-0.31207,0.335293,0.222248, + -0.680969,0.208836,0.701903,-0.299415,0.418387,0.222248, + 0,0,1,-0.305628,0.377591,0.222248, + 0.963807,-0.225386,0.142397,0.257344,-0.251982,0.320299, + 0.630607,-0.116308,0.767338,0.166895,0,0.380912, + 0.390635,-0.324541,0.861439,0.166895,-0.251982,0.357142, + 0.808614,0.13115,0.573536,0.257344,0.251982,0.320299, + 0.355577,0.157361,0.921305,0.166895,0.251982,0.357142, + 0.630607,-0.116308,0.767338,0.166895,0,0.380912, + 0.974495,-0.224383,-0.003566,0.331315,-0.208938,0.222248, + 0.808614,0.13115,0.573536,0.257344,0.251982,0.320299, + 0.963807,-0.225386,0.142397,0.257344,-0.251982,0.320299, + 0.808614,0.13115,0.573536,0.257344,0.251982,0.320299, + 0.974495,-0.224383,-0.003566,0.331315,-0.208938,0.222248, + 0.976636,0.081646,0.198785,0.331315,0.208938,0.222248, + 0,-0.183338,0.98305,0.05339,0,0.380912, + 0,0.227898,0.973685,-0.054097,0.251982,0.357142, + 0,-0.183338,0.98305,-0.05339,0,0.380912, + -0.988599,0.150572,-0,-0.31207,0.335293,0.222248, + -0.972543,0.133925,0.190327,-0.299415,0.418387,-0.380912, + -0.80967,-0.28833,0.511175,-0.331315,0.208938,0.222248, + -0.972543,0.133925,0.190327,-0.299415,0.418387,-0.380912, + -0.988599,0.150572,-0,-0.31207,0.335293,0.222248, + -0.988599,0.150572,0,-0.305628,0.377591,0.222248, + -0.972543,0.133925,0.190327,-0.299415,0.418387,-0.380912, + -0.988599,0.150572,0,-0.305628,0.377591,0.222248, + -0.680969,0.208836,0.701903,-0.299415,0.418387,0.222248, + -0.4243,-0.491509,0.760519,-0.257344,-0.251982,0.320299, + -0.606546,-0.596974,0.525094,-0.299415,-0.418387,0.222248, + -0.083557,-0.996461,-0.009165,-0.283103,-0.467335,0.222248, + 0,-0.593633,0.804736,-0.17891,-0.455225,0.279296, + -0.083557,-0.996461,-0.009165,-0.283103,-0.467335,0.222248, + -0.132836,-0.912766,0.386282,-0.234168,-0.483652,0.222248, + 0,-0.593633,0.804736,-0.17891,-0.455225,0.279296, + -0.4243,-0.491509,0.760519,-0.257344,-0.251982,0.320299, + -0.083557,-0.996461,-0.009165,-0.283103,-0.467335,0.222248, + -0.680969,0.208836,0.701903,-0.299415,0.418387,0.222248, + -0.94871,0.316149,-0,-0.286127,0.45826,0.110422, + -0.972543,0.133925,0.190327,-0.299415,0.418387,-0.380912, + -0.94871,0.316149,-0,-0.286127,0.45826,0.110422, + -0.680969,0.208836,0.701903,-0.299415,0.418387,0.222248, + -0.667422,0.448147,0.594737,-0.283103,0.467335,0.222248, + 0.812952,-0.581784,0.025229,-0.286127,0.45826,0.110422, + 0,0,0,-0.283103,0.467335,0.222248, + 0.812952,-0.581784,0.025229,-0.285423,0.460375,0.136473, + -0.94871,0.316149,-0,-0.286127,0.45826,0.110422, + -0.630337,0.598312,0.494671,-0.283103,0.467335,-0.380912, + -0.972543,0.133925,0.190327,-0.299415,0.418387,-0.380912, + -0.630337,0.598312,0.494671,-0.283103,0.467335,-0.380912, + -0.94871,0.316149,-0,-0.286127,0.45826,0.110422, + -0.948709,0.31615,0,-0.285423,0.460375,0.136473, + -0.630337,0.598312,0.494671,-0.283103,0.467335,-0.380912, + -0.948709,0.31615,0,-0.285423,0.460375,0.136473, + -0.667422,0.448147,0.594737,-0.283103,0.467335,0.222248, + -0.680969,0.208836,0.701903,-0.231791,0.418387,0.27573, + -0.630337,0.598312,0.494671,-0.234168,0.483652,0.222248, + -0.667422,0.448147,0.594737,-0.283103,0.467335,0.222248, + 0,0.437247,0.899341,0.054097,0.455225,0.279296, + 0.016318,0.569809,0.821615,-0.001224,0.5,0.222248, + 0,0.227898,0.973685,-0.054097,0.455225,0.279296, + 0.234091,-0.650537,0.722498,0.054097,-0.455225,0.279296, + 0,-0.593633,0.804736,-0.054097,-0.455225,0.279296, + 0.256797,-0.68367,0.683119,-0.001224,-0.5,0.222248, + 0,-0.593633,0.804736,-0.054097,-0.455225,0.279296, + 0.234091,-0.650537,0.722498,0.054097,-0.455225,0.279296, + 0,-0.357681,0.933844,0,-0.455225,0.279296, + 0,-0.357681,0.933844,0,-0.455225,0.279296, + 0,-0.357681,0.933844,-0.054097,-0.251982,0.357142, + 0,-0.593633,0.804736,-0.054097,-0.455225,0.279296, + 0,-0.357681,0.933844,-0.054097,-0.251982,0.357142, + 0,-0.357681,0.933844,0,-0.455225,0.279296, + 0.234091,-0.650537,0.722498,0.054097,-0.455225,0.279296, + -0.292283,-0.637068,0.713243,-0.166895,-0.251982,0.357142, + -0.4243,-0.491509,0.760519,-0.257344,-0.251982,0.320299, + 0,-0.593633,0.804736,-0.17891,-0.455225,0.279296, + 0,0.227898,0.973685,-0.054097,0.455225,0.279296, + 0.016318,0.569809,0.821615,-0.001224,0.5,0.222248, + -0.560153,0.569636,0.601451,-0.17891,0.455225,0.279296, + -0.680969,0.208836,0.701903,-0.231791,0.418387,0.27573, + -0.680969,0.208836,0.701903,-0.299415,0.418387,0.222248, + -0.753212,-0.381237,0.536031,-0.257344,0.251982,0.320299, + 0.707166,-0.707048,0,0.283103,-0.467335,0.222248, + 0.963807,-0.225386,0.142397,0.257344,-0.251982,0.320299, + 0.256797,-0.68367,0.683119,0.17891,-0.455225,0.279296, + 0.998455,0.055333,0.005018,0.299415,0.418387,-0.380912, + 0.972186,0.234211,0,0.318731,0.29156,0.222248, + 0.976636,0.081646,0.198785,0.331315,0.208938,0.222248, + 0.972186,0.234211,0,0.318731,0.29156,0.222248, + 0.998455,0.055333,0.005018,0.299415,0.418387,-0.380912, + 0.972186,0.234211,0,0.310276,0.347076,0.222248, + 0.972186,0.234211,0,0.310276,0.347076,0.222248, + 0.998455,0.055333,0.005018,0.299415,0.418387,-0.380912, + 0.972186,0.234211,0,0.299415,0.418387,0.222248, + -0.560153,0.569636,0.601451,-0.17891,0.455225,0.279296, + -0.630337,0.598312,0.494671,-0.234168,0.483652,0.222248, + -0.680969,0.208836,0.701903,-0.231791,0.418387,0.27573, + 0,-0.357681,0.933844,0.054097,-0.251982,0.357142, + 0,-0.183338,0.98305,0.05339,0,0.380912, + 0,-0.357681,0.933844,-0.054097,-0.251982,0.357142, + 0.894538,0.049574,-0.444235,0.299415,0.418387,-0.380912, + 0.976636,0.081646,0.198785,0.331315,0.208938,0.222248, + 0.870112,-0.191101,-0.454297,0.345926,0,-0.380912, + 0.617265,-0.617162,-0.48795,0.234168,-0.483652,-0.380912, + 0,-0.999633,-0.027095,0.008103,-0.487773,-0.228855, + -0.078932,-0.941308,-0.328191,-0.234168,-0.483652,-0.380912, + 0,-0.999633,-0.027095,0.008103,-0.487773,-0.228855, + 0.617265,-0.617162,-0.48795,0.234168,-0.483652,-0.380912, + 0.026189,-0.809627,0.586361,0.054066,-0.49616,0.080576, + 0,-0.999633,-0.027095,0.008103,-0.487773,-0.228855, + 0.026189,-0.809627,0.586361,0.054066,-0.49616,0.080576, + 0,-0.999633,-0.027095,0.008103,-0.49662,0.097563, + 0,-0.999633,-0.027095,0.008103,-0.49662,0.097563, + 0.026189,-0.809627,0.586361,0.054066,-0.49616,0.080576, + 0.256797,-0.68367,0.683119,-0.001224,-0.5,0.222248, + 0,-0.999633,-0.027095,0.008103,-0.49662,0.097563, + 0.256797,-0.68367,0.683119,-0.001224,-0.5,0.222248, + 0,-0.999633,-0.027095,-0.017747,-0.49662,0.097563, + -0.078932,-0.941308,-0.328191,-0.234168,-0.483652,-0.380912, + 0,-0.999633,-0.027095,-0.017747,-0.49662,0.097563, + 0.256797,-0.68367,0.683119,-0.001224,-0.5,0.222248, + 0,-0.999633,-0.027095,-0.017747,-0.49662,0.097563, + -0.078932,-0.941308,-0.328191,-0.234168,-0.483652,-0.380912, + 0,-0.999633,-0.027095,-0.017747,-0.487773,-0.228855, + 0,-0.999633,-0.027095,-0.017747,-0.487773,-0.228855, + -0.078932,-0.941308,-0.328191,-0.234168,-0.483652,-0.380912, + 0,-0.999633,-0.027095,0.008103,-0.487773,-0.228855, + -0.716279,-0.483147,0.503502,-0.331315,-0.208938,0.222248, + -0.606546,-0.596974,0.525094,-0.299415,-0.418387,0.222248, + -0.4243,-0.491509,0.760519,-0.257344,-0.251982,0.320299, + 0,-0.593633,0.804736,-0.17891,-0.455225,0.279296, + 0.256797,-0.68367,0.683119,-0.001224,-0.5,0.222248, + 0,-0.593633,0.804736,-0.054097,-0.455225,0.279296, + 0,0.437247,0.899341,0.054097,0.455225,0.279296, + 0,0.227898,0.973685,-0.054097,0.455225,0.279296, + 0,0.227898,0.973685,-0.054097,0.251982,0.357142, + -0.554782,0.205685,0.80617,-0.166895,0.251982,0.357142, + -0.680969,0.208836,0.701903,-0.231791,0.418387,0.27573, + -0.753212,-0.381237,0.536031,-0.257344,0.251982,0.320299, + -0.554782,0.205685,0.80617,-0.166895,0.251982,0.357142, + -0.560153,0.569636,0.601451,-0.17891,0.455225,0.279296, + -0.680969,0.208836,0.701903,-0.231791,0.418387,0.27573, + 0.88454,-0.466449,-0.003915,0.234168,-0.483652,0.222248, + 0.026189,-0.809627,0.586361,0.054066,-0.49616,0.080576, + 0.707166,-0.707048,0,0.234168,-0.483652,-0.380912, + 0.026189,-0.809627,0.586361,0.054066,-0.49616,0.080576, + 0.851855,-0.449213,-0.269352,0.234168,-0.483652,0.222248, + 0.256797,-0.68367,0.683119,-0.001224,-0.5,0.222248, + -0.991416,0.130553,-0.0071,-0.299415,0.418387,-0.380912, + 0,0,0,-0.299415,-0.418387,-0.380912, + 0,0,0,-0.345926,0,-0.380912, + 0,0,0,-0.299415,-0.418387,-0.380912, + -0.991416,0.130553,-0.0071,-0.299415,0.418387,-0.380912, + 0,0,0,-0.283103,0.467335,-0.380912, + 0,0,0,-0.299415,-0.418387,-0.380912, + 0,0,0,-0.283103,0.467335,-0.380912, + 0,-0.697462,-0.716622,-0.283103,-0.467335,-0.380912, + 0,-0.697462,-0.716622,-0.283103,-0.467335,-0.380912, + 0,0,0,-0.283103,0.467335,-0.380912, + 0,0,0,-0.234168,0.483652,-0.380912, + 0,-0.697462,-0.716622,-0.283103,-0.467335,-0.380912, + 0,0,0,-0.234168,0.483652,-0.380912, + 0,-0.697462,-0.716622,-0.234168,-0.483652,-0.380912, + 0,-0.697462,-0.716622,-0.234168,-0.483652,-0.380912, + 0,0,0,-0.234168,0.483652,-0.380912, + 0,0,0,0.234168,0.483652,-0.380912, + 0,-0.697462,-0.716622,-0.234168,-0.483652,-0.380912, + 0,0,0,0.234168,0.483652,-0.380912, + 0,0,-1,0.234168,-0.483652,-0.380912, + 0,0,-1,0.234168,-0.483652,-0.380912, + 0,0,0,0.234168,0.483652,-0.380912, + 0,0,-1,0.283103,-0.467335,-0.380912, + 0,0,-1,0.283103,-0.467335,-0.380912, + 0,0,0,0.234168,0.483652,-0.380912, + 0,0,0,0.283103,0.467335,-0.380912, + 0,0,-1,0.283103,-0.467335,-0.380912, + 0,0,0,0.283103,0.467335,-0.380912, + 0.697771,-0.07757,-0.712109,0.299415,-0.418387,-0.380912, + 0.697771,-0.07757,-0.712109,0.299415,-0.418387,-0.380912, + 0,0,0,0.283103,0.467335,-0.380912, + 0.697771,0.07757,-0.712109,0.299415,0.418387,-0.380912, + 0.697771,-0.07757,-0.712109,0.299415,-0.418387,-0.380912, + 0.697771,0.07757,-0.712109,0.299415,0.418387,-0.380912, + 0.697771,-0.07757,-0.712109,0.345926,0,-0.380912, + -0.680969,0.208836,0.701903,-0.231791,0.418387,0.27573, + -0.667422,0.448147,0.594737,-0.283103,0.467335,0.222248, + -0.680969,0.208836,0.701903,-0.299415,0.418387,0.222248, + 0.963807,-0.225386,0.142397,0.257344,-0.251982,0.320299, + 0.390635,-0.324541,0.861439,0.166895,-0.251982,0.357142, + 0.256797,-0.68367,0.683119,0.17891,-0.455225,0.279296, + 0.256797,-0.68367,0.683119,0.17891,-0.455225,0.279296, + 0.88454,-0.466449,-0.003915,0.234168,-0.483652,0.222248, + 0.707166,-0.707048,0,0.283103,-0.467335,0.222248, + 0.963807,-0.225386,0.142397,0.257344,-0.251982,0.320299, + 0.707166,-0.707048,0,0.283103,-0.467335,0.222248, + 0.974495,-0.224383,-0.003566,0.299415,-0.418387,0.222248, + 0,0.437247,0.899341,0.054097,0.455225,0.279296, + 0,0.227898,0.973685,-0.054097,0.251982,0.357142, + 0,0.227898,0.973685,0.054097,0.251982,0.357142, + -0.593343,-0.615334,0.518949,-0.299415,-0.418387,-0.380912, + -0.083557,-0.996461,-0.009165,-0.283103,-0.467335,0.222248, + -0.606546,-0.596974,0.525094,-0.299415,-0.418387,0.222248, + -0.716279,-0.483147,0.503502,-0.331315,-0.208938,0.222248, + -0.593343,-0.615334,0.518949,-0.299415,-0.418387,-0.380912, + -0.606546,-0.596974,0.525094,-0.299415,-0.418387,0.222248, + 0,-0.183338,0.98305,0.05339,0,0.380912, + 0,-0.183338,0.98305,-0.05339,0,0.380912, + 0,-0.357681,0.933844,-0.054097,-0.251982,0.357142, + 0,-0.357681,0.933844,0.054097,-0.251982,0.357142, + 0,-0.357681,0.933844,-0.054097,-0.251982,0.357142, + 0.234091,-0.650537,0.722498,0.054097,-0.455225,0.279296, + -0.630337,0.598312,0.494671,-0.234168,0.483652,0.222248, + -0.630337,0.598312,0.494671,-0.283103,0.467335,-0.380912, + -0.667422,0.448147,0.594737,-0.283103,0.467335,0.222248, + 0.974495,-0.224383,-0.003566,0.299415,-0.418387,-0.380912, + 0.707166,-0.707048,0,0.283103,-0.467335,0.222248, + 0.707166,-0.707048,0,0.283103,-0.467335,-0.380912, + 0.016318,0.569809,0.821615,0.234168,0.483652,0.222248, + 0.136339,0.966309,0.218307,0.234168,0.483652,-0.380912, + 0.016318,0.569809,0.821615,-0.001224,0.5,0.222248, + -0.560153,0.569636,0.601451,-0.17891,0.455225,0.279296, + 0.016318,0.569809,0.821615,-0.001224,0.5,0.222248, + -0.630337,0.598312,0.494671,-0.234168,0.483652,0.222248, + -0.630337,0.598312,0.494671,-0.234168,0.483652,0.222248, + -0.630337,0.598312,0.494671,-0.234168,0.483652,-0.380912, + -0.630337,0.598312,0.494671,-0.283103,0.467335,-0.380912, + 0.016318,0.569809,0.821615,0.234168,0.483652,0.222248, + 0.016318,0.569809,0.821615,0.17891,0.455225,0.279296, + 0.332175,0.255552,0.907939,0.231791,0.418387,0.27573, + -0.593343,-0.615334,0.518949,-0.299415,-0.418387,-0.380912, + -0.083557,-0.996461,-0.009165,-0.283103,-0.467335,-0.380912, + -0.083557,-0.996461,-0.009165,-0.283103,-0.467335,0.222248, + -0.083557,-0.996461,-0.009165,-0.283103,-0.467335,0.222248, + -0.083557,-0.996461,-0.009165,-0.283103,-0.467335,-0.380912, + -0.083557,-0.996461,-0.009165,-0.234168,-0.483652,-0.380912, + 0.234091,-0.650537,0.722498,0.054097,-0.455225,0.279296, + 0.256797,-0.68367,0.683119,-0.001224,-0.5,0.222248, + 0.256797,-0.68367,0.683119,0.17891,-0.455225,0.279296, + 0.972186,0.234211,0,0.299415,0.418387,0.222248, + 0.332175,0.255552,0.907939,0.231791,0.418387,0.27573, + 0.808614,0.13115,0.573536,0.257344,0.251982,0.320299, + 0.972186,0.234211,0,0.299415,0.418387,0.222248, + 0.332175,0.255552,0.907939,0.283103,0.467335,0.222248, + 0.332175,0.255552,0.907939,0.231791,0.418387,0.27573, + 0.808614,0.13115,0.573536,0.257344,0.251982,0.320299, + 0.332175,0.255552,0.907939,0.231791,0.418387,0.27573, + 0.355577,0.157361,0.921305,0.166895,0.251982,0.357142, + 0.808614,0.13115,0.573536,0.257344,0.251982,0.320299, + 0.630607,-0.116308,0.767338,0.166895,0,0.380912, + 0.963807,-0.225386,0.142397,0.257344,-0.251982,0.320299, + 0.870112,-0.191101,-0.454297,0.345926,0,-0.380912, + 0.944342,-0.21744,-0.246856,0.331315,-0.208938,0.222248, + 0.944342,-0.21744,-0.246856,0.299415,-0.418387,-0.380912, + 0.332175,0.255552,0.907939,0.231791,0.418387,0.27573, + 0.016318,0.569809,0.821615,0.17891,0.455225,0.279296, + 0.355577,0.157361,0.921305,0.166895,0.251982,0.357142, + 0.974495,-0.224383,-0.003566,0.299415,-0.418387,0.222248, + 0.707166,-0.707048,0,0.283103,-0.467335,0.222248, + 0.974495,-0.224383,-0.003566,0.299415,-0.418387,-0.380912, + 0.256797,-0.68367,0.683119,0.17891,-0.455225,0.279296, + 0.256797,-0.68367,0.683119,-0.001224,-0.5,0.222248, + 0.88454,-0.466449,-0.003915,0.234168,-0.483652,0.222248, + 0.974495,-0.224383,-0.003566,0.331315,-0.208938,0.222248, + 0.963807,-0.225386,0.142397,0.257344,-0.251982,0.320299, + 0.974495,-0.224383,-0.003566,0.299415,-0.418387,0.222248, + 0.016318,0.569809,0.821615,0.17891,0.455225,0.279296, + 0.016318,0.569809,0.821615,-0.001224,0.5,0.222248, + 0,0.437247,0.899341,0.054097,0.455225,0.279296, + 0.016318,0.569809,0.821615,0.234168,0.483652,0.222248, + 0.136339,0.966309,0.218307,0.283103,0.467335,-0.380912, + 0.136339,0.966309,0.218307,0.234168,0.483652,-0.380912, + 0.972186,0.234211,0,0.318731,0.29156,0.222248, + 0.808614,0.13115,0.573536,0.257344,0.251982,0.320299, + 0.976636,0.081646,0.198785,0.331315,0.208938,0.222248, + 0.808614,0.13115,0.573536,0.257344,0.251982,0.320299, + 0.972186,0.234211,0,0.318731,0.29156,0.222248, + 0.972186,0.234211,0,0.299415,0.418387,0.222248, + 0,0,-1,0.299415,0.418387,0.222248, + 0,0,-1,0.318731,0.29156,0.222248, + 0,0,-1,0.310276,0.347076,0.222248, + 0.88454,-0.466449,-0.003915,0.234168,-0.483652,0.222248, + 0.707166,-0.707048,0,0.234168,-0.483652,-0.380912, + 0.707166,-0.707048,0,0.283103,-0.467335,0.222248, + 0.707166,-0.707048,0,0.283103,-0.467335,0.222248, + 0.707166,-0.707048,0,0.234168,-0.483652,-0.380912, + 0.707166,-0.707048,0,0.283103,-0.467335,-0.380912, + 0.974495,-0.224383,-0.003566,0.331315,-0.208938,0.222248, + 0.974495,-0.224383,-0.003566,0.299415,-0.418387,0.222248, + 0.974495,-0.224383,-0.003566,0.299415,-0.418387,-0.380912, + 0.332175,0.255552,0.907939,0.283103,0.467335,0.222248, + 0.016318,0.569809,0.821615,0.234168,0.483652,0.222248, + 0.332175,0.255552,0.907939,0.231791,0.418387,0.27573, + -0.346098,-0.553785,0.757324,-0.166895,0,0.380912, + -0.4243,-0.491509,0.760519,-0.257344,-0.251982,0.320299, + -0.292283,-0.637068,0.713243,-0.166895,-0.251982,0.357142, + -0.36572,-0.42515,0.827947,-0.166895,0,0.380912, + -0.554782,0.205685,0.80617,-0.166895,0.251982,0.357142, + -0.753212,-0.381237,0.536031,-0.257344,0.251982,0.320299, + 0.016318,0.569809,0.821615,0.17891,0.455225,0.279296, + 0.016318,0.569809,0.821615,0.234168,0.483652,0.222248, + 0.016318,0.569809,0.821615,-0.001224,0.5,0.222248, + -0.972543,0.133925,0.190327,-0.299415,0.418387,-0.380912, + -0.804326,-0.334215,0.491284,-0.345926,0,-0.380912, + -0.80967,-0.28833,0.511175,-0.331315,0.208938,0.222248, + -0.346098,-0.553785,0.757324,-0.166895,0,0.380912, + -0.716279,-0.483147,0.503502,-0.257344,0.251982,0.320299, + -0.4243,-0.491509,0.760519,-0.257344,-0.251982,0.320299, + -0.716279,-0.483147,0.503502,-0.331315,0.208938,0.222248, + -0.690527,-0.541416,0.479627,-0.345926,0,-0.380912, + -0.716279,-0.483147,0.503502,-0.331315,-0.208938,0.222248, + -0.716279,-0.483147,0.503502,-0.257344,0.251982,0.320299, + -0.716279,-0.483147,0.503502,-0.331315,-0.208938,0.222248, + -0.4243,-0.491509,0.760519,-0.257344,-0.251982,0.320299, + -0.716279,-0.483147,0.503502,-0.331315,-0.208938,0.222248, + -0.716279,-0.483147,0.503502,-0.257344,0.251982,0.320299, + -0.716279,-0.483147,0.503502,-0.331315,0.208938,0.222248 +}; +static const struct gllist frame={GL_N3F_V3F,GL_TRIANGLES,366,data,NULL}; +const struct gllist *toaster=&frame; diff --git a/hacks/glx/toaster_base.c b/hacks/glx/toaster_base.c new file mode 100644 index 00000000..74771c8c --- /dev/null +++ b/hacks/glx/toaster_base.c @@ -0,0 +1,125 @@ +#include "gllist.h" +static const float data[]={ + -0.160224,0.987081,0,-0.242083,0.5,0.052679, + 0.316307,0.948657,0,0.242083,0.5,-0.052679, + -0.160224,0.987081,0,-0.242083,0.5,-0.052679, + 0.316307,0.948657,0,0.242083,0.5,-0.052679, + -0.160224,0.987081,0,-0.242083,0.5,0.052679, + 0.316307,0.948657,0,0.242083,0.5,0.052679, + 0.976722,0.21451,0,0.309535,0.432529,-0.052679, + 1,0,0,0.357619,0,0.052679, + 1,0,0,0.357619,0,-0.052679, + 1,0,0,0.357619,0,0.052679, + 0.976722,0.21451,0,0.309535,0.432529,-0.052679, + 0.707166,0.707048,0,0.309535,0.432529,0.052679, + 0.160224,-0.987081,0,0.242083,-0.5,0.052679, + -0.160224,-0.987081,0,-0.242083,-0.5,-0.052679, + 0.160224,-0.987081,0,0.242083,-0.5,-0.052679, + -0.160224,-0.987081,0,-0.242083,-0.5,-0.052679, + 0.160224,-0.987081,0,0.242083,-0.5,0.052679, + -0.707166,-0.707048,0,-0.242083,-0.5,0.052679, + -0.976722,0.21451,0,-0.309535,0.432529,0.052679, + -1,0,0,-0.357619,0,-0.052679, + -1,0,0,-0.357619,0,0.052679, + -1,0,0,-0.357619,0,-0.052679, + -0.976722,0.21451,0,-0.309535,0.432529,0.052679, + -0.584744,0.811218,0,-0.309535,0.432529,-0.052679, + 0,0,-1,-0.309535,0.432529,-0.052679, + 0,0,-1,-0.309535,-0.432529,-0.052679, + 0,0,-1,-0.357619,0,-0.052679, + 0,0,-1,-0.309535,-0.432529,-0.052679, + 0,0,-1,-0.309535,0.432529,-0.052679, + 0,0,-1,-0.292672,0.483132,-0.052679, + 0,0,-1,-0.309535,-0.432529,-0.052679, + 0,0,-1,-0.292672,0.483132,-0.052679, + 0,0,0,-0.292672,-0.483132,-0.052679, + 0,0,0,-0.292672,-0.483132,-0.052679, + 0,0,-1,-0.292672,0.483132,-0.052679, + 0,0,0,-0.242083,0.5,-0.052679, + 0,0,0,-0.292672,-0.483132,-0.052679, + 0,0,0,-0.242083,0.5,-0.052679, + 0,0,-1,-0.242083,-0.5,-0.052679, + 0,0,-1,-0.242083,-0.5,-0.052679, + 0,0,0,-0.242083,0.5,-0.052679, + 0,0,-1,0.242083,0.5,-0.052679, + 0,0,-1,-0.242083,-0.5,-0.052679, + 0,0,-1,0.242083,0.5,-0.052679, + 0,0,0,0.242083,-0.5,-0.052679, + 0,0,0,0.242083,-0.5,-0.052679, + 0,0,-1,0.242083,0.5,-0.052679, + 0,0,-1,0.292672,-0.483132,-0.052679, + 0,0,-1,0.292672,-0.483132,-0.052679, + 0,0,-1,0.242083,0.5,-0.052679, + 0,0,0,0.292672,0.483132,-0.052679, + 0,0,-1,0.292672,-0.483132,-0.052679, + 0,0,0,0.292672,0.483132,-0.052679, + 0,0,0,0.309535,-0.432529,-0.052679, + 0,0,0,0.309535,-0.432529,-0.052679, + 0,0,0,0.292672,0.483132,-0.052679, + 0,0,-1,0.309535,0.432529,-0.052679, + 0,0,0,0.309535,-0.432529,-0.052679, + 0,0,-1,0.309535,0.432529,-0.052679, + 0,0,0,0.357619,0,-0.052679, + 1,0,0,0.357619,0,-0.052679, + 0.994254,-0.107045,0,0.309535,-0.432529,0.052679, + 0.994254,-0.107045,0,0.309535,-0.432529,-0.052679, + 0.994254,-0.107045,0,0.309535,-0.432529,0.052679, + 1,0,0,0.357619,0,-0.052679, + 1,0,0,0.357619,0,0.052679, + -1,0,0,-0.357619,0,0.052679, + -0.994254,-0.107045,0,-0.309535,-0.432529,-0.052679, + -0.994254,-0.107045,0,-0.309535,-0.432529,0.052679, + -0.994254,-0.107045,0,-0.309535,-0.432529,-0.052679, + -1,0,0,-0.357619,0,0.052679, + -1,0,0,-0.357619,0,-0.052679, + -0.994254,-0.107045,0,-0.309535,-0.432529,0.052679, + -0.707166,-0.707048,0,-0.292672,-0.483132,-0.052679, + -0.707166,-0.707048,0,-0.292672,-0.483132,0.052679, + -0.707166,-0.707048,0,-0.292672,-0.483132,-0.052679, + -0.994254,-0.107045,0,-0.309535,-0.432529,0.052679, + -0.994254,-0.107045,0,-0.309535,-0.432529,-0.052679, + -0.707166,-0.707048,0,-0.242083,-0.5,0.052679, + -0.707166,-0.707048,0,-0.292672,-0.483132,-0.052679, + -0.160224,-0.987081,0,-0.242083,-0.5,-0.052679, + -0.707166,-0.707048,0,-0.292672,-0.483132,-0.052679, + -0.707166,-0.707048,0,-0.242083,-0.5,0.052679, + -0.707166,-0.707048,0,-0.292672,-0.483132,0.052679, + 0.994254,-0.107045,0,0.292672,-0.483132,0.052679, + 0.160224,-0.987081,0,0.242083,-0.5,-0.052679, + 0.707166,-0.707048,0,0.292672,-0.483132,-0.052679, + 0.160224,-0.987081,0,0.242083,-0.5,-0.052679, + 0.994254,-0.107045,0,0.292672,-0.483132,0.052679, + 0.160224,-0.987081,0,0.242083,-0.5,0.052679, + 0.994254,-0.107045,0,0.309535,-0.432529,-0.052679, + 0.994254,-0.107045,0,0.292672,-0.483132,0.052679, + 0.707166,-0.707048,0,0.292672,-0.483132,-0.052679, + 0.994254,-0.107045,0,0.292672,-0.483132,0.052679, + 0.994254,-0.107045,0,0.309535,-0.432529,-0.052679, + 0.994254,-0.107045,0,0.309535,-0.432529,0.052679, + 0.316307,0.948657,0,0.242083,0.5,0.052679, + 0.707166,0.707048,0,0.292672,0.483132,-0.052679, + 0.316307,0.948657,0,0.242083,0.5,-0.052679, + 0.707166,0.707048,0,0.292672,0.483132,-0.052679, + 0.316307,0.948657,0,0.242083,0.5,0.052679, + 0.707166,0.707048,0,0.292672,0.483132,0.052679, + 0.707166,0.707048,0,0.292672,0.483132,-0.052679, + 0.707166,0.707048,0,0.309535,0.432529,0.052679, + 0.976722,0.21451,0,0.309535,0.432529,-0.052679, + 0.707166,0.707048,0,0.309535,0.432529,0.052679, + 0.707166,0.707048,0,0.292672,0.483132,-0.052679, + 0.707166,0.707048,0,0.292672,0.483132,0.052679, + -0.160224,0.987081,0,-0.292672,0.483132,0.052679, + -0.584744,0.811218,0,-0.309535,0.432529,-0.052679, + -0.976722,0.21451,0,-0.309535,0.432529,0.052679, + -0.584744,0.811218,0,-0.309535,0.432529,-0.052679, + -0.160224,0.987081,0,-0.292672,0.483132,0.052679, + -0.487642,0.873044,0,-0.292672,0.483132,-0.052679, + -0.160224,0.987081,0,-0.292672,0.483132,0.052679, + -0.160224,0.987081,0,-0.242083,0.5,-0.052679, + -0.487642,0.873044,0,-0.292672,0.483132,-0.052679, + -0.160224,0.987081,0,-0.242083,0.5,-0.052679, + -0.160224,0.987081,0,-0.292672,0.483132,0.052679, + -0.160224,0.987081,0,-0.242083,0.5,0.052679 +}; +static const struct gllist frame={GL_N3F_V3F,GL_TRIANGLES,120,data,NULL}; +const struct gllist *toaster_base=&frame; diff --git a/hacks/glx/toaster_handle.c b/hacks/glx/toaster_handle.c new file mode 100644 index 00000000..89d30122 --- /dev/null +++ b/hacks/glx/toaster_handle.c @@ -0,0 +1,59 @@ +#include "gllist.h" +static const float data[]={ + 0,0,1,0.5,-0.094169,0.035224, + 0,0,1,-0.356403,0.038624,0.035224, + 0,0,1,-0.5,-0.094169,0.035224, + 0,0,1,-0.356403,0.038624,0.035224, + 0,0,1,0.5,-0.094169,0.035224, + 0,0,1,-0.210084,0.094169,0.035224, + 0,0,1,-0.210084,0.094169,0.035224, + 0,0,1,0.5,-0.094169,0.035224, + 0,0,1,0.210084,0.094169,0.035224, + 0,0,1,0.210084,0.094169,0.035224, + 0,0,1,0.5,-0.094169,0.035224, + 0,0,1,0.356403,0.038624,0.035224, + -0.678947,0.734187,0,-0.5,-0.094169,0.035224, + -0.354908,0.934901,0,-0.356403,0.038624,-0.035224, + -0.678947,0.734187,0,-0.5,-0.094169,-0.035224, + -0.354908,0.934901,0,-0.356403,0.038624,-0.035224, + -0.678947,0.734187,0,-0.5,-0.094169,0.035224, + -0.180414,0.983591,0,-0.356403,0.038624,0.035224, + 0,0,-1,-0.356403,0.038624,-0.035224, + 0,0,0,0.5,-0.094169,-0.035224, + 0,0,-1,-0.5,-0.094169,-0.035224, + 0,0,0,0.5,-0.094169,-0.035224, + 0,0,-1,-0.356403,0.038624,-0.035224, + 0,0,0,-0.210084,0.094169,-0.035224, + 0,0,0,0.5,-0.094169,-0.035224, + 0,0,0,-0.210084,0.094169,-0.035224, + 0,0,0,0.210084,0.094169,-0.035224, + 0,0,0,0.5,-0.094169,-0.035224, + 0,0,0,0.210084,0.094169,-0.035224, + 0,0,0,0.356403,0.038624,-0.035224, + 0.526579,0.850126,0,0.356403,0.038624,0.035224, + 0.678947,0.734187,0,0.5,-0.094169,-0.035224, + 0.526579,0.850126,0,0.356403,0.038624,-0.035224, + 0.678947,0.734187,0,0.5,-0.094169,-0.035224, + 0.526579,0.850126,0,0.356403,0.038624,0.035224, + 0.678947,0.734187,0,0.5,-0.094169,0.035224, + -0.180414,0.983591,0,-0.210084,0.094169,0.035224, + 0.180414,0.983591,0,0.210084,0.094169,-0.035224, + -0.180414,0.983591,0,-0.210084,0.094169,-0.035224, + 0.180414,0.983591,0,0.210084,0.094169,-0.035224, + -0.180414,0.983591,0,-0.210084,0.094169,0.035224, + 0.526579,0.850126,0,0.210084,0.094169,0.035224, + 0.526579,0.850126,0,0.210084,0.094169,0.035224, + 0.526579,0.850126,0,0.356403,0.038624,-0.035224, + 0.180414,0.983591,0,0.210084,0.094169,-0.035224, + 0.526579,0.850126,0,0.356403,0.038624,-0.035224, + 0.526579,0.850126,0,0.210084,0.094169,0.035224, + 0.526579,0.850126,0,0.356403,0.038624,0.035224, + -0.180414,0.983591,0,-0.356403,0.038624,0.035224, + -0.180414,0.983591,0,-0.210084,0.094169,-0.035224, + -0.354908,0.934901,0,-0.356403,0.038624,-0.035224, + -0.180414,0.983591,0,-0.210084,0.094169,-0.035224, + -0.180414,0.983591,0,-0.356403,0.038624,0.035224, + -0.180414,0.983591,0,-0.210084,0.094169,0.035224 +}; +static const struct gllist frame={GL_N3F_V3F,GL_TRIANGLES,54,data,NULL}; +const struct gllist *toaster_handle=&frame; diff --git a/hacks/glx/toaster_handle2.c b/hacks/glx/toaster_handle2.c new file mode 100644 index 00000000..ce9ab9fb --- /dev/null +++ b/hacks/glx/toaster_handle2.c @@ -0,0 +1,35 @@ +#include "gllist.h" +static const float data[]={ + 0,-0.027094,0.999633,0.038934,-0.294903,-0.5, + 0,-0.027094,0.999633,-0.038934,0.321555,-0.483291, + 0,-0.027094,0.999633,-0.038934,-0.294903,-0.5, + 0,-0.027094,0.999633,-0.038934,0.321555,-0.483291, + 0,-0.027094,0.999633,0.038934,-0.294903,-0.5, + 0,-0.027094,0.999633,0.038934,0.321555,-0.483291, + -1,0,0,0.038934,0.294903,0.5, + -1,0,0,0.038934,-0.294903,-0.5, + -1,0,0,0.038934,-0.321555,0.483291, + -1,0,0,0.038934,-0.294903,-0.5, + -1,0,0,0.038934,0.294903,0.5, + -1,0,0,0.038934,0.321555,-0.483291, + 0,0.027094,-0.999633,0.038934,0.294903,0.5, + 0,0.027094,-0.999633,-0.038934,-0.321555,0.483291, + 0,0.027094,-0.999633,-0.038934,0.294903,0.5, + 0,0.027094,-0.999633,-0.038934,-0.321555,0.483291, + 0,0.027094,-0.999633,0.038934,0.294903,0.5, + 0,0.027094,-0.999633,0.038934,-0.321555,0.483291, + 1,0,-0,-0.038934,-0.294903,-0.5, + 1,0,-0,-0.038934,0.294903,0.5, + 1,0,-0,-0.038934,-0.321555,0.483291, + 1,0,0,-0.038934,0.294903,0.5, + 1,0,0,-0.038934,-0.294903,-0.5, + 1,0,0,-0.038934,0.321555,-0.483291, + 0,-0.999633,-0.027095,0.038934,0.294903,0.5, + 0,-0.999633,-0.027095,-0.038934,0.321555,-0.483291, + 0,-0.999633,-0.027095,0.038934,0.321555,-0.483291, + 0,-0.999633,-0.027095,-0.038934,0.321555,-0.483291, + 0,-0.999633,-0.027095,0.038934,0.294903,0.5, + 0,-0.999633,-0.027095,-0.038934,0.294903,0.5 +}; +static const struct gllist frame={GL_N3F_V3F,GL_TRIANGLES,30,data,NULL}; +const struct gllist *toaster_handle2=&frame; diff --git a/hacks/glx/toaster_jet.c b/hacks/glx/toaster_jet.c new file mode 100644 index 00000000..d78351e0 --- /dev/null +++ b/hacks/glx/toaster_jet.c @@ -0,0 +1,173 @@ +#include "gllist.h" +static const float data[]={ + 0.083052,-0.217721,0.972471,-0.002117,-0.240071,0.000396, + 0.964758,-0.225993,0.13479,-0.061503,-0.5,-0.010357, + -0.355644,0,0.934621,-0.031551,-0.5,-0.055285, + -0.080443,-0.050111,0.995499,0.012946,0.394969,0.120155, + -0.551252,-0.284714,0.784257,-0.087986,-0.240071,0.081748, + -0.259565,-0.228446,0.938317,0.012946,-0.240071,0.120155, + -0.683511,-0.336869,0.647559,-0.002117,-0.240071,0.000396, + 0.083052,-0.217721,0.972471,0.022249,-0.5,-0.059879, + 0.083052,-0.217721,0.972471,0.059386,-0.5,-0.020681, + -0.860848,0.070085,0.504013,-0.120888,0.394969,-0.02111, + -0.989378,-0.13796,0.045806,-0.120888,-0.240071,-0.02111, + -0.779868,0.161126,0.604851,-0.087986,0.394969,0.081748, + 0.344811,-0.242597,-0.906781,0.022249,-0.5,-0.059879, + -0.827472,-0.10476,-0.551648,-0.031551,-0.5,-0.055285, + -0.827472,-0.10476,-0.551648,-0.060985,-0.240071,-0.110965, + 0.344811,-0.242597,-0.906781,0.046616,-0.240071,-0.120155, + -0.438499,0.513796,-0.737382,-0.060985,0.394969,-0.110965, + 0.354384,-0.081711,-0.931523,0.046616,0.394969,-0.120155, + 0.354384,-0.081711,-0.931523,0.046616,0.394969,-0.120155, + -0.438499,0.513796,-0.737382,-0.031551,0.5,-0.055285, + 0.301519,0.526234,-0.795087,0.022249,0.5,-0.059879, + 0.85386,-0.060139,-0.517016,0.105904,-0.240071,0.065189, + 0.601848,-0.2504,0.758339,0.051893,-0.5,0.032792, + 0.85386,-0.060139,-0.517016,0.120888,-0.240071,-0.041759, + 0.344811,-0.242597,-0.906781,0.046616,-0.240071,-0.120155, + -0.827472,-0.10476,-0.551648,-0.060985,-0.240071,-0.110965, + -0.438499,0.513796,-0.737382,-0.060985,0.394969,-0.110965, + 0.341978,0.779287,-0.525131,0.059386,0.5,-0.020681, + 0.509494,-0.077315,-0.856994,0.120888,0.394969,-0.041759, + 0.301519,0.526234,-0.795087,0.022249,0.5,-0.059879, + 0.135936,-0.214419,-0.967236,-0.002117,-0.240071,0.000396, + 0.135936,-0.214419,-0.967236,-0.045051,-0.5,0.041072, + 0.964758,-0.225993,0.13479,-0.061503,-0.5,-0.010357, + 0.344811,-0.242597,-0.906781,0.046616,-0.240071,-0.120155, + 0.344811,-0.242597,-0.906781,0.022249,-0.5,-0.059879, + -0.827472,-0.10476,-0.551648,-0.060985,-0.240071,-0.110965, + 0.866986,0.483301,0.121473,0.105904,0.394969,0.065189, + 0.193897,0.013369,0.980931,0.051893,0.5,0.032792, + 0.193897,0.013369,0.980931,0.012946,0.394969,0.120155, + 0.866986,0.483301,0.121473,0.105904,0.394969,0.065189, + 0.85386,-0.060139,-0.517016,0.105904,-0.240071,0.065189, + 0.85386,-0.060139,-0.517016,0.120888,0.394969,-0.041759, + 0.083052,-0.217721,0.972471,0.022249,-0.5,-0.059879, + 0.083052,-0.217721,0.972471,-0.002117,-0.240071,0.000396, + -0.717987,-0.111888,0.687005,-0.031551,-0.5,-0.055285, + -0.989378,-0.13796,0.045806,-0.120888,-0.240071,-0.02111, + -0.964758,-0.225993,-0.13479,-0.061503,-0.5,-0.010357, + -0.812264,-0.396635,0.427676,-0.087986,-0.240071,0.081748, + -0.438499,0.513796,-0.737382,-0.060985,0.394969,-0.110965, + -0.944444,-0.149855,-0.292522,-0.060985,-0.240071,-0.110965, + -0.948821,0.087293,0.303511,-0.120888,0.394969,-0.02111, + 0.990327,0,0.138754,0.105904,-0.240071,0.065189, + 0.087286,-0.149954,0.984832,0.012946,-0.240071,0.120155, + 0.601848,-0.2504,0.758339,0.005415,-0.5,0.060275, + -0.63255,0.49066,0.599278,0.022249,0.5,-0.059879, + 0.438499,0.513796,0.737382,-0.031551,0.5,-0.055285, + -0.695462,0.01321,0.718442,-0.002117,0.394969,0.000396, + -0.601848,-0.2504,-0.758339,0.051893,-0.5,0.032792, + -0.601848,-0.2504,-0.758339,0.005415,-0.5,0.060275, + -0.372495,-0.262398,-0.890166,-0.002117,-0.240071,0.000396, + -0.812264,-0.396635,0.427676,-0.087986,-0.240071,0.081748, + -0.964758,-0.225993,-0.13479,-0.061503,-0.5,-0.010357, + -0.812264,-0.396635,0.427676,-0.045051,-0.5,0.041072, + -0.601848,-0.2504,-0.758339,-0.002117,-0.240071,0.000396, + -0.083052,-0.217721,-0.972471,0.059386,-0.5,-0.020681, + -0.601848,-0.2504,-0.758339,0.051893,-0.5,0.032792, + 0.438499,0.513796,0.737382,-0.031551,0.5,-0.055285, + 0.849395,0.452441,-0.271707,-0.061503,0.5,-0.010357, + 0.979889,0.024806,0.197996,-0.002117,0.394969,0.000396, + 0.85386,-0.060139,-0.517016,0.120888,-0.240071,-0.041759, + 0.601848,-0.2504,0.758339,0.051893,-0.5,0.032792, + 0.829146,-0.460842,0.316452,0.059386,-0.5,-0.020681, + 0.301519,0.526234,-0.795087,0.022249,0.5,-0.059879, + 0.509494,-0.077315,-0.856994,0.120888,0.394969,-0.041759, + 0.354384,-0.081711,-0.931523,0.046616,0.394969,-0.120155, + -0.956201,0.260713,-0.133076,-0.061503,0.5,-0.010357, + -0.438499,0.513796,-0.737382,-0.060985,0.394969,-0.110965, + -0.948821,0.087293,0.303511,-0.120888,0.394969,-0.02111, + -0.438499,0.513796,-0.737382,-0.060985,0.394969,-0.110965, + -0.956201,0.260713,-0.133076,-0.061503,0.5,-0.010357, + -0.438499,0.513796,-0.737382,-0.031551,0.5,-0.055285, + -0.860848,0.070085,0.504013,-0.045051,0.5,0.041072, + -0.956201,0.260713,-0.133076,-0.061503,0.5,-0.010357, + -0.860848,0.070085,0.504013,-0.120888,0.394969,-0.02111, + -0.372495,-0.262398,-0.890166,0.051893,0.5,0.032792, + -0.95999,0.279553,0.016421,-0.002117,0.394969,0.000396, + -0.372495,-0.262398,-0.890166,0.005415,0.5,0.060275, + 0.509494,-0.077315,-0.856994,0.120888,-0.240071,-0.041759, + 0.344811,-0.242597,-0.906781,0.059386,-0.5,-0.020681, + 0.344811,-0.242597,-0.906781,0.046616,-0.240071,-0.120155, + -0.63255,0.49066,0.599278,0.022249,0.5,-0.059879, + -0.860848,0.070085,0.504013,-0.002117,0.394969,0.000396, + -0.712635,0.513796,-0.477665,0.059386,0.5,-0.020681, + -0.080443,-0.050111,0.995499,0.012946,0.394969,0.120155, + -0.626884,0.119795,0.769848,-0.087986,0.394969,0.081748, + -0.551252,-0.284714,0.784257,-0.087986,-0.240071,0.081748, + 0.961364,0.020143,-0.274544,-0.045051,0.5,0.041072, + 0.961364,0.020143,-0.274544,-0.002117,0.394969,0.000396, + 0.849395,0.452441,-0.271707,-0.061503,0.5,-0.010357, + 0.866986,0.483301,0.121473,0.105904,0.394969,0.065189, + 0.087286,-0.149954,0.984832,0.012946,-0.240071,0.120155, + 0.990327,0,0.138754,0.105904,-0.240071,0.065189, + -0.080443,-0.050111,0.995499,0.005415,0.5,0.060275, + -0.695462,0.01321,0.718442,-0.045051,0.5,0.041072, + -0.626884,0.119795,0.769848,-0.087986,0.394969,0.081748, + 0.354384,-0.081711,-0.931523,0.046616,0.394969,-0.120155, + -0.438499,0.513796,-0.737382,-0.060985,0.394969,-0.110965, + -0.438499,0.513796,-0.737382,-0.031551,0.5,-0.055285, + 0.354384,-0.081711,-0.931523,0.046616,0.394969,-0.120155, + 0.509494,-0.077315,-0.856994,0.120888,-0.240071,-0.041759, + 0.344811,-0.242597,-0.906781,0.046616,-0.240071,-0.120155, + 0.866986,0.483301,0.121473,0.059386,0.5,-0.020681, + 0.866986,0.483301,0.121473,0.105904,0.394969,0.065189, + 0.85386,-0.060139,-0.517016,0.120888,0.394969,-0.041759, + -0.712635,0.513796,-0.477665,0.059386,0.5,-0.020681, + -0.91736,0.232882,0.322826,-0.002117,0.394969,0.000396, + -0.817565,-0.364245,-0.445995,0.051893,0.5,0.032792, + -0.259565,-0.228446,0.938317,0.012946,-0.240071,0.120155, + -0.551252,-0.284714,0.784257,-0.045051,-0.5,0.041072, + -0.209736,-0.350079,0.912938,0.005415,-0.5,0.060275, + -0.948821,0.087293,0.303511,-0.120888,0.394969,-0.02111, + -0.944444,-0.149855,-0.292522,-0.060985,-0.240071,-0.110965, + -0.944444,-0.149855,-0.292522,-0.120888,-0.240071,-0.02111, + -0.779868,0.161126,0.604851,-0.087986,0.394969,0.081748, + -0.989378,-0.13796,0.045806,-0.120888,-0.240071,-0.02111, + -0.812264,-0.396635,0.427676,-0.087986,-0.240071,0.081748, + -0.860848,0.070085,0.504013,-0.045051,0.5,0.041072, + -0.860848,0.070085,0.504013,-0.120888,0.394969,-0.02111, + -0.779868,0.161126,0.604851,-0.087986,0.394969,0.081748, + -0.082706,-0.223052,-0.971292,0.005415,0.5,0.060275, + 0.733181,0.147558,-0.663831,-0.002117,0.394969,0.000396, + 0.733181,0.147558,-0.663831,-0.045051,0.5,0.041072, + -0.944444,-0.149855,-0.292522,-0.120888,-0.240071,-0.02111, + -0.944444,-0.149855,-0.292522,-0.031551,-0.5,-0.055285, + -0.964758,-0.225993,-0.13479,-0.061503,-0.5,-0.010357, + -0.944444,-0.149855,-0.292522,-0.031551,-0.5,-0.055285, + -0.944444,-0.149855,-0.292522,-0.120888,-0.240071,-0.02111, + -0.944444,-0.149855,-0.292522,-0.060985,-0.240071,-0.110965, + 0.209736,-0.350079,-0.912938,0.005415,-0.5,0.060275, + -0.082706,-0.223052,-0.971292,-0.045051,-0.5,0.041072, + -0.082706,-0.223052,-0.971292,-0.002117,-0.240071,0.000396, + -0.259565,-0.228446,0.938317,0.012946,-0.240071,0.120155, + -0.551252,-0.284714,0.784257,-0.087986,-0.240071,0.081748, + -0.551252,-0.284714,0.784257,-0.045051,-0.5,0.041072, + -0.080443,-0.050111,0.995499,0.012946,0.394969,0.120155, + -0.080443,-0.050111,0.995499,0.005415,0.5,0.060275, + -0.626884,0.119795,0.769848,-0.087986,0.394969,0.081748, + 0.990327,0,0.138754,0.105904,-0.240071,0.065189, + 0.601848,-0.2504,0.758339,0.005415,-0.5,0.060275, + 0.601848,-0.2504,0.758339,0.051893,-0.5,0.032792, + 0.509494,-0.077315,-0.856994,0.120888,0.394969,-0.041759, + 0.509494,-0.077315,-0.856994,0.120888,-0.240071,-0.041759, + 0.354384,-0.081711,-0.931523,0.046616,0.394969,-0.120155, + 0.85386,-0.060139,-0.517016,0.120888,0.394969,-0.041759, + 0.85386,-0.060139,-0.517016,0.105904,-0.240071,0.065189, + 0.85386,-0.060139,-0.517016,0.120888,-0.240071,-0.041759, + 0.866986,0.483301,0.121473,0.105904,0.394969,0.065189, + 0.193897,0.013369,0.980931,0.012946,0.394969,0.120155, + 0.087286,-0.149954,0.984832,0.012946,-0.240071,0.120155, + 0.637701,0.021937,0.769971,0.051893,0.5,0.032792, + 0.866986,0.483301,0.121473,0.105904,0.394969,0.065189, + 0.866986,0.483301,0.121473,0.059386,0.5,-0.020681, + 0.193897,0.013369,0.980931,0.051893,0.5,0.032792, + 0.193897,0.013369,0.980931,0.005415,0.5,0.060275, + 0.193897,0.013369,0.980931,0.012946,0.394969,0.120155, + 0.344811,-0.242597,-0.906781,0.046616,-0.240071,-0.120155, + 0.344811,-0.242597,-0.906781,0.059386,-0.5,-0.020681, + 0.344811,-0.242597,-0.906781,0.022249,-0.5,-0.059879 +}; +static const struct gllist frame={GL_N3F_V3F,GL_TRIANGLES,168,data,NULL}; +const struct gllist *toaster_jet=&frame; diff --git a/hacks/glx/toaster_knob.c b/hacks/glx/toaster_knob.c new file mode 100644 index 00000000..3c673084 --- /dev/null +++ b/hacks/glx/toaster_knob.c @@ -0,0 +1,71 @@ +#include "gllist.h" +static const float data[]={ + 0.894098,0.012135,-0.447706,0.220972,-0.2059,-0.429683, + 0.894098,0.012135,-0.447706,0.372946,0.214524,-0.114788, + 0.894098,0.012135,-0.447706,0.372946,-0.21412,-0.126406, + 0.894098,0.012135,-0.447706,0.372946,0.214524,-0.114788, + 0.894098,0.012135,-0.447706,0.220972,-0.2059,-0.429683, + 0.894098,0.012135,-0.447706,0.220972,0.222744,-0.418065, + -0.999879,-0.000422,0.015577,-0.367658,0.209613,0.06637, + -0.999879,-0.000422,0.015577,-0.372946,-0.209838,-0.284406, + -0.999879,-0.000422,0.015577,-0.367658,-0.21903,0.054752, + -0.999879,-0.000422,0.015577,-0.372946,-0.209838,-0.284406, + -0.999879,-0.000422,0.015577,-0.367658,0.209613,0.06637, + -0.999879,-0.000422,0.015577,-0.372946,0.218806,-0.272788, + 0.907621,-0.011374,0.419637,0.372946,-0.21412,-0.126406, + 0.907621,-0.011374,0.419637,0.2305,0.206179,0.193077, + 0.907621,-0.011374,0.419637,0.2305,-0.222464,0.181458, + 0.907621,-0.011374,0.419637,0.2305,0.206179,0.193077, + 0.907621,-0.011374,0.419637,0.372946,-0.21412,-0.126406, + 0.907621,-0.011374,0.419637,0.372946,0.214524,-0.114788, + -0.611231,-0.021444,0.791162,-0.099099,-0.22465,0.262081, + -0.611231,-0.021444,0.791162,-0.367658,0.209613,0.06637, + -0.611231,-0.021444,0.791162,-0.367658,-0.21903,0.054752, + -0.611231,-0.021444,0.791162,-0.367658,0.209613,0.06637, + -0.611231,-0.021444,0.791162,-0.099099,-0.22465,0.262081, + -0.611231,-0.021444,0.791162,-0.099099,0.203994,0.2737, + -0,-0.999633,-0.027096,0.220972,-0.2059,-0.429683, + -0,-0.999633,-0.027096,-0.372946,-0.209838,-0.284406, + -0,-0.999633,-0.027096,-0.11098,-0.203994,-0.5, + 0,-0.999633,-0.027094,-0.372946,-0.209838,-0.284406, + 0,-0.999633,-0.027094,0.220972,-0.2059,-0.429683, + 0,-0.999633,-0.027094,0.372946,-0.21412,-0.126406, + 0,-0.999633,-0.027095,-0.372946,-0.209838,-0.284406, + 0,-0.999633,-0.027095,0.372946,-0.21412,-0.126406, + 0,-0.999633,-0.027095,-0.367658,-0.21903,0.054752, + 0,-0.999633,-0.027094,-0.367658,-0.21903,0.054752, + 0,-0.999633,-0.027094,0.372946,-0.21412,-0.126406, + 0,-0.999633,-0.027094,0.2305,-0.222464,0.181458, + 0,-0.999633,-0.027095,-0.367658,-0.21903,0.054752, + 0,-0.999633,-0.027095,0.2305,-0.222464,0.181458, + 0,-0.999633,-0.027095,0.065701,-0.223557,0.22177, + 0,-0.999633,-0.027095,-0.367658,-0.21903,0.054752, + 0,-0.999633,-0.027095,0.065701,-0.223557,0.22177, + 0,-0.999633,-0.027095,-0.099099,-0.22465,0.262081, + -0.635597,0.020918,-0.771737,-0.11098,0.22465,-0.488382, + -0.635597,0.020918,-0.771737,-0.372946,-0.209838,-0.284406, + -0.635597,0.020918,-0.771737,-0.372946,0.218806,-0.272788, + -0.635597,0.020918,-0.771737,-0.372946,-0.209838,-0.284406, + -0.635597,0.020918,-0.771737,-0.11098,0.22465,-0.488382, + -0.635597,0.020918,-0.771737,-0.11098,-0.203994,-0.5, + 0.207302,0.026506,-0.977918,0.220972,0.222744,-0.418065, + 0.207302,0.026506,-0.977918,-0.11098,-0.203994,-0.5, + 0.207302,0.026506,-0.977918,-0.11098,0.22465,-0.488382, + 0.207302,0.026506,-0.977918,-0.11098,-0.203994,-0.5, + 0.207302,0.026506,-0.977918,0.220972,0.222744,-0.418065, + 0.207302,0.026506,-0.977918,0.220972,-0.2059,-0.429683, + 0.237686,-0.026318,0.970985,0.065701,-0.223557,0.22177, + 0.237686,-0.026318,0.970985,-0.099099,0.203994,0.2737, + 0.237686,-0.026318,0.970985,-0.099099,-0.22465,0.262081, + -0.6794,-0.340802,0.649823,0.116801,0.205086,0.5, + -0.6794,-0.340802,0.649823,-0.099099,0.203994,0.2737, + -0.6794,-0.340802,0.649823,0.065701,-0.223557,0.22177, + 0.237686,-0.026318,0.970985,0.2305,0.206179,0.193077, + 0.237686,-0.026318,0.970985,0.065701,-0.223557,0.22177, + 0.237686,-0.026318,0.970985,0.2305,-0.222464,0.181458, + 0.88909,-0.319042,0.328226,0.2305,0.206179,0.193077, + 0.88909,-0.319042,0.328226,0.116801,0.205086,0.5, + 0.88909,-0.319042,0.328226,0.065701,-0.223557,0.22177 +}; +static const struct gllist frame={GL_N3F_V3F,GL_TRIANGLES,66,data,NULL}; +const struct gllist *toaster_knob=&frame; diff --git a/hacks/glx/toaster_slots.c b/hacks/glx/toaster_slots.c new file mode 100644 index 00000000..3def0ffb --- /dev/null +++ b/hacks/glx/toaster_slots.c @@ -0,0 +1,101 @@ +#include "gllist.h" +static const float data[]={ + 0.998257,-0.059011,0,-0.18331,-0.276766,0.209005, + 0.998257,-0.059011,0,-0.196507,-0.5,0.123502, + 0.998257,-0.059011,0,-0.196507,-0.5,-0.235113, + 0.99951,0.002941,-0.031177,-0.18331,0,0.235113, + 0.99951,0.002941,-0.031177,-0.18331,-0.276766,0.209005, + 0.99951,0.002941,-0.031177,-0.196507,-0.5,-0.235113, + 0,1,0,-0.059418,-0.5,0.123502, + 0,1,0,-0.058641,-0.5,-0.235113, + 0,1,0,-0.196507,-0.5,-0.235113, + 0,1,0,-0.059418,-0.5,0.123502, + 0,1,0,-0.196507,-0.5,-0.235113, + 0,1,0,-0.196507,-0.5,0.123502, + 0.998257,0.059011,0,-0.196507,0.5,0.123502, + 0.998257,0.059011,0,-0.18331,0.276766,0.209005, + 0.998257,0.059011,0,-0.196507,0.5,-0.235113, + 0.99951,-0.002941,-0.031177,-0.196507,0.5,-0.235113, + 0.99951,-0.002941,-0.031177,-0.18331,0.276766,0.209005, + 0.99951,-0.002941,-0.031177,-0.18331,0,0.235113, + 0,-1,0,-0.196507,0.5,0.123502, + 0,-1,0,-0.196507,0.5,-0.235113, + 0,-1,0,-0.059418,0.5,0.123502, + 0.999606,0,-0.028053,-0.196507,0.5,-0.235113, + 0.999606,0,-0.028053,-0.18331,0,0.235113, + 0.999606,0,-0.028053,-0.196507,-0.5,-0.235113, + -0.99999,-0.003119,-0.003317,-0.058641,0.5,-0.235113, + -0.99999,-0.003119,-0.003317,-0.058641,0,0.235113, + -0.99999,-0.003119,-0.003317,-0.059418,0.276766,0.209005, + -0.999997,0.00083,-0.002166,-0.059418,-0.276766,0.209005, + -0.999997,0.00083,-0.002166,-0.058641,-0.5,-0.235113, + -0.999997,0.00083,-0.002166,-0.059418,-0.5,0.123502, + -0.99999,0.003119,-0.003317,-0.058641,0,0.235113, + -0.99999,0.003119,-0.003317,-0.058641,-0.5,-0.235113, + -0.99999,0.003119,-0.003317,-0.059418,-0.276766,0.209005, + -1,0,0,-0.058641,0.5,-0.235113, + -1,0,0,-0.058641,-0.5,-0.235113, + -1,0,0,-0.058641,0,0.235113, + 0,-0,1,-0.058641,-0.5,-0.235113, + 0,-0,1,-0.058641,0.5,-0.235113, + 0,-0,1,-0.196507,0.5,-0.235113, + 0,0,1,-0.058641,-0.5,-0.235113, + 0,0,1,-0.196507,0.5,-0.235113, + 0,0,1,-0.196507,-0.5,-0.235113, + 0,-1,-0,-0.059418,0.5,0.123502, + 0,-1,-0,-0.196507,0.5,-0.235113, + 0,-1,-0,-0.058641,0.5,-0.235113, + -0.999997,-0.00083,-0.002166,-0.058641,0.5,-0.235113, + -0.999997,-0.00083,-0.002166,-0.059418,0.276766,0.209005, + -0.999997,-0.00083,-0.002166,-0.059418,0.5,0.123502, + 1,0,0,0.058641,0.5,-0.235113, + 1,0,0,0.058641,0,0.235113, + 1,0,0,0.058641,-0.5,-0.235113, + 0.999997,0.00083,-0.002166,0.059418,-0.276766,0.209005, + 0.999997,0.00083,-0.002166,0.059418,-0.5,0.123502, + 0.999997,0.00083,-0.002166,0.058641,-0.5,-0.235113, + 0.99999,-0.003119,-0.003317,0.058641,0.5,-0.235113, + 0.99999,-0.003119,-0.003317,0.059418,0.276766,0.209005, + 0.99999,-0.003119,-0.003317,0.058641,0,0.235113, + 0.99999,0.003119,-0.003317,0.058641,0,0.235113, + 0.99999,0.003119,-0.003317,0.059418,-0.276766,0.209005, + 0.99999,0.003119,-0.003317,0.058641,-0.5,-0.235113, + -0.998257,0.059011,0,0.196507,0.5,-0.235113, + -0.998257,0.059011,0,0.18331,0.276766,0.209005, + -0.998257,0.059011,0,0.196507,0.5,0.123502, + -0.99951,0.002941,-0.031177,0.18331,0,0.235113, + -0.99951,0.002941,-0.031177,0.196507,-0.5,-0.235113, + -0.99951,0.002941,-0.031177,0.18331,-0.276766,0.209005, + 0,1,0,0.059418,-0.5,0.123502, + 0,1,0,0.196507,-0.5,-0.235113, + 0,1,0,0.058641,-0.5,-0.235113, + -0.998257,-0.059011,0,0.18331,-0.276766,0.209005, + -0.998257,-0.059011,0,0.196507,-0.5,-0.235113, + -0.998257,-0.059011,0,0.196507,-0.5,0.123502, + 0,-1,0,0.059418,0.5,0.123502, + 0,-1,0,0.196507,0.5,-0.235113, + 0,-1,0,0.196507,0.5,0.123502, + 0,1,0,0.196507,-0.5,0.123502, + 0,1,0,0.196507,-0.5,-0.235113, + 0,1,0,0.059418,-0.5,0.123502, + -0.99951,-0.002941,-0.031177,0.196507,0.5,-0.235113, + -0.99951,-0.002941,-0.031177,0.18331,0,0.235113, + -0.99951,-0.002941,-0.031177,0.18331,0.276766,0.209005, + -0.999606,-0,-0.028053,0.196507,0.5,-0.235113, + -0.999606,-0,-0.028053,0.196507,-0.5,-0.235113, + -0.999606,-0,-0.028053,0.18331,0,0.235113, + 0,0,1,0.196507,0.5,-0.235113, + 0,0,1,0.058641,-0.5,-0.235113, + 0,0,1,0.196507,-0.5,-0.235113, + 0,0,1,0.196507,0.5,-0.235113, + 0,0,1,0.058641,0.5,-0.235113, + 0,0,1,0.058641,-0.5,-0.235113, + 0.999997,-0.00083,-0.002166,0.059418,0.5,0.123502, + 0.999997,-0.00083,-0.002166,0.059418,0.276766,0.209005, + 0.999997,-0.00083,-0.002166,0.058641,0.5,-0.235113, + 0,-1,-0,0.059418,0.5,0.123502, + 0,-1,-0,0.058641,0.5,-0.235113, + 0,-1,-0,0.196507,0.5,-0.235113 +}; +static const struct gllist frame={GL_N3F_V3F,GL_TRIANGLES,96,data,NULL}; +const struct gllist *toaster_slots=&frame; diff --git a/hacks/glx/toaster_wing.c b/hacks/glx/toaster_wing.c new file mode 100644 index 00000000..b1f8167c --- /dev/null +++ b/hacks/glx/toaster_wing.c @@ -0,0 +1,38 @@ +#include "gllist.h" +static const float data[]={ + -0.002931,-0.001173,-0.999995,0.5,-0.248054,-0.034832, + -0.002931,-0.001173,-0.999995,-0.5,0.248054,-0.032483, + -0.002931,-0.001173,-0.999995,0.399306,0.003521,-0.034832, + 0.189903,0.691703,0.696767,0.399306,0.003521,-0.034832, + 0.189903,0.691703,0.696767,-0.5,0.248054,-0.032483, + 0.189903,0.691703,0.696767,0.3827,-0.039065,0.01197, + -0.035459,-0.237307,0.970787,0.5,-0.248054,-0.034832, + -0.035459,-0.237307,0.970787,0.3827,-0.039065,0.01197, + -0.035459,-0.237307,0.970787,-0.466673,-0.094003,-0.032483, + -0.002468,-0.00024,-0.999997,0.5,-0.248054,-0.034832, + -0.002468,-0.00024,-0.999997,-0.466673,-0.094003,-0.032483, + -0.002468,-0.00024,-0.999997,-0.5,0.248054,-0.032483, + -0.051938,-0.00506,0.998637,0.3827,-0.039065,0.01197, + -0.051938,-0.00506,0.998637,-0.5,0.248054,-0.032483, + -0.051938,-0.00506,0.998637,-0.466673,-0.094003,-0.032483, + -0.031687,-0.285224,0.957937,0.3827,-0.039065,0.01197, + -0.031687,-0.285224,0.957937,-0.482606,0.13385,0.034832, + -0.031687,-0.285224,0.957937,-0.466673,-0.094003,-0.032483, + 0.370589,0,0.928797,0.5,-0.065307,-0.034832, + 0.370589,0,0.928797,0.3827,-0.039065,0.01197, + 0.370589,0,0.928797,0.5,-0.248054,-0.034832, + 0.125848,0.517903,0.846131,0.3827,-0.039065,0.01197, + 0.125848,0.517903,0.846131,-0.5,0.248054,-0.032483, + 0.125848,0.517903,0.846131,-0.482606,0.13385,0.034832, + -0.772167,-0.309062,-0.555193,0.399306,0.003521,-0.034832, + -0.772167,-0.309062,-0.555193,0.5,-0.248054,-0.034832, + -0.772167,-0.309062,-0.555193,0.3827,-0.039065,0.01197, + 0.408832,0.598113,0.689287,0.5,-0.065307,-0.034832, + 0.408832,0.598113,0.689287,0.399306,0.003521,-0.034832, + 0.408832,0.598113,0.689287,0.3827,-0.039065,0.01197, + 0,0,-1,0.5,-0.248054,-0.034832, + 0,0,-1,0.399306,0.003521,-0.034832, + 0,0,-1,0.5,-0.065307,-0.034832 +}; +static const struct gllist frame={GL_N3F_V3F,GL_TRIANGLES,33,data,NULL}; +const struct gllist *toaster_wing=&frame; diff --git a/hacks/glx/topblock.c b/hacks/glx/topblock.c new file mode 100644 index 00000000..6523102a --- /dev/null +++ b/hacks/glx/topblock.c @@ -0,0 +1,890 @@ +/* topblock, Copyright (c) 2006-2012 rednuht + * + * 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. + * + * + * + +topBlock - a simple openGL 3D hack of falling blocks +based on jwz's dangerball hack + +The proporations of the blocks and their features is not even close to the commercial building block products offered by a variety companies. + +information on this hack might be found at +http://www.jumpstation.co.uk/xscreensaver/topblock/ + +History +25/02/2006 v1.0 release +29/04/2006 v1.11 updated to better fit with xscreensaver v5 + colors defaults to 7 (no black) +19/06/2006 v1.2 fixed dropSpeed = 7 bug, added gltrackball support and some code neatening, thanks to Valdis Kletnieks and JWZ for their input. +*/ + +#include + +# define refresh_topBlock 0 + +#define DEFAULTS "*delay: 10000 \n" \ + "*count: 30 \n" \ + "*showFPS: False \n" \ + "*wireframe: False \n" \ + +#undef countof +#define countof(x) (sizeof((x))/sizeof((*x))) + +#include "xlockmore.h" +#include "topblock.h" +#include "sphere.h" +#include "tube.h" +#include "gltrackball.h" +#include + +#ifdef USE_GL /* whole file */ + +#ifndef HAVE_COCOA +# include +#endif + +typedef struct +{ + GLXContext *glx_context; + trackball_state *trackball; + Bool button_down_p; + int numFallingBlocks; + GLfloat highest,highestFalling; + GLfloat eyeLine,eyeX,eyeY,eyeZ; + int carpetWidth, carpetLength; + int followMode; + GLfloat followRadius,followAngle; + int plusheight; + GLuint carpet; + GLuint block; + int carpet_polys, block_polys; + NODE *blockNodeRoot; + NODE *blockNodeFollow; + GLfloat rotation; +} topBlockSTATE; + +/* parameter vars */ +static Bool override; +static Bool rotate; +static Bool follow; +static Bool drawCarpet; +static Bool drawBlob; +static Bool drawNipples; +static GLfloat rotateSpeed; +static GLfloat camX; +static GLfloat camY; +static GLfloat camZ; +static GLfloat dropSpeed; +static int maxFalling; +static int maxColors; +static int size; +static int spawn; +static int resolution; + +static XrmOptionDescRec opts[] = { + { "-size", ".size", XrmoptionSepArg, 0 }, + { "-spawn", ".spawn", XrmoptionSepArg, 0 }, + { "-camX", ".camX", XrmoptionSepArg, 0 }, + { "-camY", ".camY", XrmoptionSepArg, 0 }, + { "-camZ", ".camZ", XrmoptionSepArg, 0 }, + { "+rotate", ".rotate", XrmoptionNoArg, "False" }, + { "-rotate", ".rotate", XrmoptionNoArg, "True" }, + { "+carpet", ".carpet", XrmoptionNoArg, "False" }, + { "+nipples", ".nipples", XrmoptionNoArg, "False" }, + { "-blob", ".blob", XrmoptionNoArg, "True" }, + { "-rotateSpeed", ".rotateSpeed", XrmoptionSepArg, 0 }, + { "-follow", ".follow", XrmoptionNoArg, "True" }, + { "-maxFalling", ".maxFalling", XrmoptionSepArg, 0 }, + { "-resolution", ".resolution", XrmoptionSepArg, 0 }, + { "-maxColors", ".maxColors", XrmoptionSepArg, 0 }, + { "-dropSpeed", ".dropSpeed", XrmoptionSepArg, 0 }, + { "-override", ".override", XrmoptionNoArg, "True" }, +}; + +#define DEF_OVERRIDE "False" +#define DEF_ROTATE "True" +#define DEF_FOLLOW "False" +#define DEF_CARPET "True" +#define DEF_BLOB "False" +#define DEF_NIPPLES "True" +#define DEF_ROTATE_SPEED "10" +#define DEF_MAX_FALLING "500" +#define DEF_MAX_COLORS "7" +#define DEF_SIZE "2" +#define DEF_SPAWN "50" +#define DEF_RESOLUTION "4" +#define DEF_CAM_X "1" +#define DEF_CAM_Y "20" +#define DEF_CAM_Z "25" +#define DEF_DROP_SPEED "4" + +static argtype vars[] = { + {&override, "override", "Override", DEF_OVERRIDE, t_Bool}, + {&rotate, "rotate", "Rotate", DEF_ROTATE, t_Bool}, + {&drawCarpet, "carpet", "Carpet", DEF_CARPET, t_Bool}, + {&drawNipples, "nipples", "Nipples", DEF_NIPPLES, t_Bool}, + {&drawBlob, "blob", "Blob", DEF_BLOB, t_Bool}, + {&rotateSpeed, "rotateSpeed", "RotateSpeed", DEF_ROTATE_SPEED, t_Float}, + {&follow, "follow", "Follow", DEF_FOLLOW, t_Bool}, + {&camX, "camX", "camX", DEF_CAM_X, t_Float}, + {&camY, "camY", "camY", DEF_CAM_Y, t_Float}, + {&camZ, "camZ", "camZ", DEF_CAM_Z, t_Float}, + {&size, "size", "size", DEF_SIZE, t_Int}, + {&spawn, "spawn", "spawn", DEF_SPAWN, t_Int}, + {&maxFalling, "maxFalling", "maxFalling", DEF_MAX_FALLING, t_Int}, + {&resolution, "resolution", "resolution", DEF_RESOLUTION, t_Int}, + {&maxColors, "maxColors", "maxColors", DEF_MAX_COLORS, t_Int}, + {&dropSpeed, "dropSpeed", "DropSpeed", DEF_DROP_SPEED, t_Float}, +}; + +static topBlockSTATE *tbs = NULL; + +static ModeSpecOpt topBlock_opts = {countof(opts), opts, countof(vars), vars, NULL}; + +/* Window management, etc */ +ENTRYPOINT void +reshape_topBlock (ModeInfo *mi, int width, int height) +{ + GLfloat h = (GLfloat) height / (GLfloat) width; + glViewport (0, 0, (GLint) width, (GLint) height); + glMatrixMode(GL_PROJECTION); + glLoadIdentity(); + gluPerspective (60.0, 1/h, 1.0, 1000.0); + glMatrixMode(GL_MODELVIEW); + glLoadIdentity(); + glClear(GL_COLOR_BUFFER_BIT); +} + +/* clean up on exit, not required ... */ +ENTRYPOINT void +release_topBlock(ModeInfo *mi) +{ + topBlockSTATE *tb = &tbs[MI_SCREEN(mi)]; + NODE *llCurrent, *llOld; + llCurrent = tb->blockNodeRoot; + while (llCurrent != NULL) { + llOld = llCurrent; + llCurrent = llCurrent->next; + free(llOld); + } +} + +/* setup */ +ENTRYPOINT void +init_topBlock (ModeInfo *mi) +{ + topBlockSTATE *tb; + int wire = MI_IS_WIREFRAME(mi); + + if (!tbs) { + tbs = (topBlockSTATE *) + calloc (MI_NUM_SCREENS(mi), sizeof (topBlockSTATE)); + if (!tbs) abort(); + } + + tb = &tbs[MI_SCREEN(mi)]; + + tb->glx_context = init_GL(mi); + + reshape_topBlock (mi, MI_WIDTH(mi), MI_HEIGHT(mi)); + +/* if (wire) { drawNipples=False; }*/ + tb->numFallingBlocks=0; + + if (size>10) { size = 10; } + if (size<1) { size = 2; } + tb->carpetWidth = 8 * size; + tb->carpetLength = tb->carpetWidth; + + maxFalling*=size; + + if (spawn<4) { spawn=4; } + if (spawn>1000) { spawn=1000; } + + if (rotateSpeed<1) {rotateSpeed=1; } + if (rotateSpeed>1000) {rotateSpeed=1000;} + rotateSpeed /= 100; + + if (resolution<4) {resolution=4;} + if (resolution>20) {resolution=20;} + resolution*=2; + + if (maxColors<1) {maxColors=1;} + if (maxColors>8) {maxColors=8;} + + if (dropSpeed<1) {dropSpeed=1;} + if (dropSpeed>9) {dropSpeed=9;} /* 10+ produces blocks that can pass through each other */ + + dropSpeed = 80/dropSpeed; + dropSpeed = (blockHeight/dropSpeed); + + reshape_topBlock (mi, MI_WIDTH(mi), MI_HEIGHT(mi)); + glClearDepth(1.0f); + if (!wire) { + GLfloat pos[4] = {10.0, 10.0, 1.0, 0.0}; + GLfloat amb[4] = {0.1, 0.1, 0.1, 1.0}; + GLfloat dif[4] = {1.0, 1.0, 1.0, 1.0}; + GLfloat spc[4] = {0.0, 1.0, 1.0, 1.0}; + + 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); + } + glDepthFunc(GL_LEQUAL); + glEnable(GL_DEPTH_TEST); + glDisable(GL_CULL_FACE); /* all objects exhibit a reverse side */ + glCullFace(GL_BACK); + + if (drawBlob) { + buildBlobBlock(mi); + } else { + buildBlock(mi); /* build the display list holding the simple block */ + } + buildCarpet(mi); /* build the base */ + tb->highest=0; + tb->highestFalling=0; + tb->eyeLine=tb->highest; + tb->eyeX=0; + tb->eyeY=0; + tb->eyeZ=0; + tb->followMode=0; + if (follow) { + tb->plusheight=100; + camZ=camZ-60; + } else { + tb->rotation=random() % 360; + tb->eyeY=10; + tb->plusheight=30; + } + tb->followRadius=0; + /* override camera settings */ + if (override) { + tb->plusheight=100; + drawCarpet=False; + camX=0; + camY=1; + camZ=0; + tb->eyeX=-1; + tb->eyeY=20; + tb->eyeZ=0; + } + tb->trackball = gltrackball_init (); +} + +/* provides the per frame entertainment */ +ENTRYPOINT void +draw_topBlock (ModeInfo *mi) +{ + Display *dpy = MI_DISPLAY(mi); + Window window = MI_WINDOW(mi); + NODE *llCurrent; + NODE *llNode; + topBlockSTATE *tb = &tbs[MI_SCREEN(mi)]; + GLfloat spcN1x,spcN1y,spcN2x,spcN2y; + GLfloat spcC1x,spcC1y,spcC2x,spcC2y; + int wire = MI_IS_WIREFRAME(mi); + GLfloat color[4]; + + if (!tb->glx_context) + return; + glXMakeCurrent(MI_DISPLAY(mi), MI_WINDOW(mi), *(tb->glx_context)); + mi->polygon_count = 0; + + generateNewBlock(mi); + + if (rotate && (!tb->button_down_p)) { tb->rotation += rotateSpeed; } + if (tb->rotation>=360) { tb->rotation=tb->rotation-360; } + + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); /* clear current */ + glLoadIdentity(); /* resets directions, do it every time ! */ + glRotatef(current_device_rotation(), 0, 0, 1); + + if (!follow) { + if (tb->highest>tb->eyeLine) { tb->eyeLine+=((tb->highest-tb->eyeLine)/100); } /* creates a smooth camera transition */ + gluLookAt(camX, camY+tb->eyeLine, camZ, tb->eyeX, tb->eyeY+tb->eyeLine, tb->eyeZ, 0.0, 1.0, 0.0); /* setup viewer, xyz cam, xyz looking at and where is up normaly 0,1,0 */ + glRotatef(90, 1.0, 0.0, 0.0); /* x axis */ + } else { + glRotatef(90, 0.0, 0.0, 1.0); /* z axis */ + followBlock(mi); + } + + /* Rotate the scene around a point that's a little higher up. */ + glTranslatef (0, 0, -5); + gltrackball_rotate (tb->trackball); + glTranslatef (0, 0, 5); + + /* rotate the world */ + glRotatef(tb->rotation, 0.0, 0.0, 1.0); + + llCurrent = tb->blockNodeRoot; + if (drawCarpet) { + /* center carpet */ + glTranslatef(0.0-(tb->carpetWidth/2),0.0-(tb->carpetLength/2),0.0); + glCallList(tb->carpet); + mi->polygon_count += tb->carpet_polys; + glTranslatef(0.0+(tb->carpetWidth/2),0.0+(tb->carpetLength/2),0.0); + glTranslatef(0.0,0.0,-0.55); + } + tb->highestFalling=0; + while (llCurrent != NULL) { /* for each block */ + glPushMatrix(); /* save state */ + /* set color */ + switch (llCurrent->color) { + case 0: + color[0] = 1.0f; + color[1] = 0.0f; + color[2] = 0.0f; + color[3] = 1.0f; + break; + case 1: + color[0] = 0.0f; + color[1] = 1.0f; + color[2] = 0.0f; + color[3] = 1.0f; + break; + case 2: + color[0] = 0.0f; + color[1] = 0.0f; + color[2] = 1.0f; + color[3] = 1.0f; + break; + case 3: + color[0] = 0.95f; + color[1] = 0.95f; + color[2] = 0.95f; + color[3] = 1.0f; + break; + case 4: + color[0] = 1.0f; + color[1] = 0.5f; + color[2] = 0.0f; + color[3] = 1.0f; + break; + case 5: + color[0] = 1.0f; + color[1] = 1.0f; + color[2] = 0.0f; + color[3] = 1.0f; + break; + case 6: + color[0] = 0.5f; + color[1] = 0.5f; + color[2] = 0.5f; + color[3] = 1.0f; + break; + case 7: + color[0] = 0.05f; + color[1] = 0.05f; + color[2] = 0.05f; + color[3] = 1.0f; + break; + } + if (wire) { glColor3fv(color); } + else { glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, color); } + + if (llCurrent->falling==1) { + spcC2x = 0; + spcC2y = 0; + spcN2x = 0; + spcN2y = 0; + if (llCurrent->height>tb->highestFalling) {tb->highestFalling=llCurrent->height;} + /* all blocks fall at the same rate to avoid mid air collisions */ + llCurrent->height-=dropSpeed; + if (llCurrent->height<=0) { + llCurrent->falling=0; + if (tb->highest==0) { + tb->highest+=blockHeight; + } + } + if ( (llCurrent->height<=tb->highest+1) && (llCurrent->falling==1) ) { + /* check for collision */ + llNode = tb->blockNodeRoot; + spcC1x = llCurrent->x; + spcC1y = llCurrent->y; + switch(llCurrent->rotation) { + case getOrientation(0): + spcC2x = spcC1x; + spcC2y = spcC1y-2; + break; + case getOrientation(1): + spcC2x = spcC1x+2; + spcC2y = spcC1y; + break; + case getOrientation(2): + spcC2x = spcC1x; + spcC2y = spcC1y+2; + break; + case getOrientation(3): + spcC2x = spcC1x-2; + spcC2y = spcC1y; + break; + } + while (llNode != NULL) { + if ( (llNode->falling==0) && (llCurrent->falling==1) ) { + spcN1x = llNode->x; + spcN1y = llNode->y; + switch(llNode->rotation) { + case getOrientation(0): + spcN2x = spcN1x; + spcN2y = spcN1y-2; + break; + case getOrientation(1): + spcN2x = spcN1x+2; + spcN2y = spcN1y; + break; + case getOrientation(2): + spcN2x = spcN1x; + spcN2y = spcN1y+2; + break; + case getOrientation(3): + spcN2x = spcN1x-2; + spcN2y = spcN1y; + break; + } + if ( + ( (spcC1x==spcN1x) && (spcC1y==spcN1y) ) || + ( (spcC1x==spcN2x) && (spcC1y==spcN2y) ) || + ( (spcC2x==spcN2x) && (spcC2y==spcN2y) ) || + ( (spcC2x==spcN1x) && (spcC2y==spcN1y) ) + ){ + if ( fabs(llCurrent->height-(llNode->height+blockHeight)) <= TOLERANCE) { + + llCurrent->falling=0; + llCurrent->height=llNode->height+blockHeight; /* if this is missing then small errors build up until the model fails */ + if ( fabs(llCurrent->height-tb->highest) <= TOLERANCE+blockHeight ) { + tb->highest+=blockHeight; + } + } + } + } + llNode=llNode->next; + } + } + } + /* set location in space */ + glTranslatef(llCurrent->x,llCurrent->y,-llCurrent->height); + /* rotate */ + glRotatef(llCurrent->rotation, 0.0f, 0.0f, 1.0f); + if ((tb->followMode==0) && (llCurrent->next==NULL)) { + tb->blockNodeFollow = llCurrent; + tb->followMode=1; + } + llCurrent = llCurrent->next; + /* draw */ + glCallList(tb->block); + mi->polygon_count += tb->block_polys; + glPopMatrix(); /* restore state */ + } + if (mi->fps_p) do_fps (mi); + glFinish(); + + if (tb->highest>(5*maxFalling)) { drawCarpet=False; } + glXSwapBuffers(dpy, window); +} + + + +/* camera is in follow mode, work out where we should be looking */ +static void followBlock(ModeInfo *mi) +{ + GLfloat xLen,yLen,cx,cy,rangle,xTarget,yTarget; + topBlockSTATE *tb = &tbs[MI_SCREEN(mi)]; + cx=0;cy=0; + if ((tb->blockNodeFollow!=NULL) && (tb->followMode==1)){ + + if (tb->highest>tb->eyeLine) { tb->eyeLine+= ((tb->highest-tb->eyeLine)/100); } + /*tb->blockNodeFollow->color=1; only noticable if you set the colors to 1 */ + + if (tb->blockNodeFollow->height > tb->eyeZ) { tb->eyeZ+= ((tb->blockNodeFollow->height - tb->eyeZ)/100); } + if (tb->blockNodeFollow->height < tb->eyeZ) { tb->eyeZ-= ((tb->eyeZ - tb->blockNodeFollow->height)/100); } + + + /* when the scene is rotated we need to know where the block is in the 2 dimensional coordinates of the carpet area + (see http://www.jumpstation.co.uk/rotation/) + */ + + if (tb->followRadius==0) { + xLen = tb->blockNodeFollow->x-cx; + yLen = tb->blockNodeFollow->y-cy; + tb->followRadius=sqrt( (xLen*xLen) + (yLen*yLen) ); + tb->followAngle = (180/M_PI) * asin(xLen/tb->followRadius); + tb->followAngle = quadrantCorrection(tb->followAngle,(int)cx,(int)cy,(int)tb->blockNodeFollow->x,(int)tb->blockNodeFollow->y); + } + rangle = (tb->followAngle+tb->rotation) * M_PI /180; + xTarget = cos(rangle) * tb->followRadius + cx; + yTarget = sin(rangle) * tb->followRadius + cy; + if (tb->followAngle>360) { tb->followAngle=tb->followAngle-360; } + + if (xTarget < tb->eyeX) { tb->eyeX-= ((tb->eyeX - xTarget)/100); } + if (xTarget > tb->eyeX) { tb->eyeX+= ((xTarget - tb->eyeX)/100); } + + if (yTarget < tb->eyeY) { tb->eyeY-= ((tb->eyeY - yTarget)/100); } + if (yTarget > tb->eyeY) { tb->eyeY+= ((yTarget - tb->eyeY)/100); } + if (!tb->blockNodeFollow->falling) { + tb->followMode=0; + /*tb->blockNodeFollow->color=2; only noticable if you set the colors to 1 */ + tb->followRadius=0; + } + } + gluLookAt(camX, camY, camZ-tb->eyeLine, tb->eyeX, tb->eyeY, -tb->eyeZ,-1.0,0.0,0.0); +} + +/* each quater of the circle has to be adjusted for */ +static double quadrantCorrection(double angle,int cx,int cy,int x,int y) +{ + if ((x>=cx) && (y>=cy)) { + angle += (90-(angle-90) * 2); + } else if ((x>=cx) && (y<=cy)) { + angle += 90; + } else if ((x<=cx) && (y<=cy)) { + angle += 90; + } else if ((x<=cx) && (y>=cy)) { + angle += (90-(angle-90) * 2); + } + return(angle-180); +} + +/* if random chance then create a new falling block */ +static void generateNewBlock(ModeInfo *mi) +{ + NODE *llCurrent, *llTail; + GLfloat startOffx, startOffy; + int endOffx, endOffy; + topBlockSTATE *tb = &tbs[MI_SCREEN(mi)]; + if ( ((random() % spawn) == 1) && (tb->highestFallingplusheight-blockHeight)+tb->highest)) ) { + startOffx=0; + endOffx=0; + startOffy=0; + endOffy=0; + tb->numFallingBlocks++; + llTail = tb->blockNodeRoot; + if (llTail == NULL) { + llCurrent = ((NODE*) malloc(sizeof(NODE))); + if (!llCurrent) abort(); + llTail = llCurrent; + tb->blockNodeRoot = llCurrent; + } else { + if (tb->numFallingBlocks>=maxFalling) { + /* recycle */ + llCurrent=llTail->next; + tb->blockNodeRoot=llCurrent->next; + } else { + llCurrent = ((NODE*) malloc(sizeof(NODE))); + if (!llCurrent) abort(); + } + while (llTail->next != NULL) { llTail = llTail->next; } /* find last item in list */ + } + llCurrent->falling=1; + llCurrent->rotation=getOrientation(random() % 4); + if (llCurrent->rotation==getOrientation(0)) { + startOffx=1.0; + endOffx=0; + startOffy=3.0; + endOffy=-1; + } else if (llCurrent->rotation==getOrientation(1)) { + startOffx=1.0; + endOffx=-1; + startOffy=1.0; + endOffy=0; + } else if (llCurrent->rotation==getOrientation(2)) { + startOffx=1.0; + endOffx=0; + startOffy=3.0; + endOffy=-1; + } else if (llCurrent->rotation==getOrientation(3)) { + startOffx=5.0; + endOffx=-1; + startOffy=1.0; + endOffy=0; + } + + llCurrent->x=(startOffx-(tb->carpetLength/2)) + getLocation(random() % ((tb->carpetLength/2)+endOffx) ); + llCurrent->y=(startOffy-(tb->carpetLength/2)) + getLocation(random() % ((tb->carpetLength/2)+endOffy) ); + llCurrent->color=(random() % maxColors); + llCurrent->height=getHeight(tb->plusheight+tb->highest); + if (tb->numFallingBlocks>=maxFalling) { + tb->numFallingBlocks--; + tb->numFallingBlocks--; + } + llTail->next = llCurrent; + llTail = llCurrent; + llTail->next = NULL; + + } +} + +/* called at init this creates the 'carpet' display list item */ +static void buildCarpet(ModeInfo *mi) +{ + int i,c,x,y; + GLfloat color[4]; + int wire = MI_IS_WIREFRAME(mi); + topBlockSTATE *tb = &tbs[MI_SCREEN(mi)]; + color[0] = 0.0f; + color[1] = 1.0f; + color[2] = 0.0f; + color[3] = 1.0f; + tb->carpet=glGenLists(1); /* only one */ + glNewList(tb->carpet,GL_COMPILE); + tb->carpet_polys=0; + glPushMatrix(); /* save state */ + x=tb->carpetWidth; + y=tb->carpetLength; + if (wire) { glColor3fv(color); } + else { glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, color); } + /* draw carpet plane */ + glBegin( wire ? GL_LINE_LOOP : GL_QUADS ); + /* draw top */ + glNormal3f( 0, 0, -1 ); + glVertex3f(0.0,0.0,0.0); + glVertex3f(x,0.0,0.0); + glVertex3f(x,y,0.0); + glVertex3f(0.0,y,0.0); + tb->carpet_polys++; + if (!wire) { + /* add edge pieces */ + /* side 1 */ + glNormal3f( 0, -1, 0 ); + glVertex3f(0.0,0.0,0.0); + glVertex3f(x,0.0,0.0); + glVertex3f(x,0,singleThick); + glVertex3f(0.0,0,singleThick); + tb->carpet_polys++; + /* side 2 */ + glNormal3f( -1, 0, 0 ); + glVertex3f(0.0,0.0,0.0); + glVertex3f(0,y,0.0); + glVertex3f(0,y,singleThick); + glVertex3f(0.0,0,singleThick); + tb->carpet_polys++; + /* side 3 */ + glNormal3f( 1, 0, 0 ); + glVertex3f(x,0.0,0.0); + glVertex3f(x,y,0.0); + glVertex3f(x,y,singleThick); + glVertex3f(x,0,singleThick); + tb->carpet_polys++; + /* side 4 */ + glNormal3f( 0, 1, 0 ); + glVertex3f(0,y,0.0); + glVertex3f(x,y,0.0); + glVertex3f(x,y,singleThick); + glVertex3f(0,y,singleThick); + tb->carpet_polys++; + } + glEnd(); + /* nipples */ + if (drawNipples) { + glTranslatef(0.5f,0.5f,-.25); /* move to the cylinder center */ + for (c=0;ccarpet_polys += tube(0, 0, -0.1, + 0, 0, 0.26, + cylSize, 0, + resolution, True, True, + wire); + glRotatef(180, 0.0f, 1.0f, 0.0f); /* they are upside down */ + glRotatef(180, 0.0f, 1.0f, 0.0f); /* recover */ + glTranslatef(0.0f,1.0f,0.0f); /* move to the next cylinder center (backward) */ + } + glPopMatrix(); /* save state */ + glTranslatef(1.0f,0.0f,0.0f); /* reset */ + } + } + glPopMatrix(); /* restore state */ + glEndList(); +} + +/* using the verticies arrays builds the plane, now with normals */ +static void polygonPlane(int wire, int a, int b, int c , int d, int i) +{ + GLfloat topBlockNormals[5][3] = { {0,0,-1}, {0,1,0}, {1,0,0}, {0,0,1}, {0,-1,0} }; + GLfloat topBlockVertices[8][3] = { {-0.49,-2.97,-0.99}, {0.99,-2.97,-0.99}, {0.99,0.99,-0.99} , {-0.49,0.99,-0.99}, {-0.49,-2.97,0.99} , {0.99,-2.97,0.99}, {0.99,0.99,0.99} , {-0.49,0.99,0.99} }; + glBegin( wire ? GL_LINE_LOOP : GL_POLYGON); + glNormal3fv(topBlockNormals[i] ); + glVertex3fv(topBlockVertices[a]); + glVertex3fv(topBlockVertices[b]); + glVertex3fv(topBlockVertices[c]); + glVertex3fv(topBlockVertices[d]); + glEnd(); +} + +/* called at init this creates the 'block' display list item */ +/* the spheres came about originaly as quick way to test the directional lighting/normals */ +static void buildBlock(ModeInfo *mi) +{ + int i,c; + int wire = MI_IS_WIREFRAME(mi); + topBlockSTATE *tb = &tbs[MI_SCREEN(mi)]; + tb->block=glGenLists(1); /* only one */ + glNewList(tb->block,GL_COMPILE); + tb->block_polys=0; + glPushMatrix(); /* save state */ + glRotatef(90, 0.0f, 1.0f, 0.0f); + /* base */ + polygonPlane(wire, 0,3,2,1,0); tb->block_polys++; + polygonPlane(wire, 2,3,7,6,1); tb->block_polys++; + polygonPlane(wire, 1,2,6,5,2); tb->block_polys++; + polygonPlane(wire, 4,5,6,7,3); tb->block_polys++; + polygonPlane(wire, 0,1,5,4,4); tb->block_polys++; + if (drawNipples) { + /* nipples */ + /* draw 8 cylinders each with a disk cap */ + glRotatef(90, 0.0f, 1.0f, 0.0f); /* 'aim' the pointer ready for the cylinder */ + glTranslatef(0.5f,0.5f,0.99f); /* move to the cylinder center */ + for (c=0;c<2;c++) { + for (i=0;i<4;i++) { + tb->block_polys += tube(0, 0, 0, + 0, 0, 0.25, + cylSize, 0, + resolution, True, True, + wire); + glTranslatef(0.0f,0.0f,0.25f); /* move to the cylinder cap */ + glTranslatef(0.0f,0.0f,-0.25f); /* move back from the cylinder cap */ + if (c==0) { + glTranslatef(0.0f,-1.0f,0.0f); /* move to the next cylinder center (forward) */ + } else { + glTranslatef(0.0f,1.0f,0.0f); /* move to the next cylinder center (backward) */ + } + } + glTranslatef(-1.0f,1.0f,0.0f); /* move to the cylinder center */ + } + /* udders */ + /* 3 cylinders on the underside */ + glTranslatef(1.5f,-2.5f,-1.5f); /* move to the center, under the top of the brick */ + if (! wire) + for (c=0;c<3;c++) { + tb->block_polys += tube(0, 0, 0.1, + 0, 0, 1.4, + uddSize, 0, + resolution, True, True, wire); + glTranslatef(0.0f,-1.0f,0.0f); /* move to the center */ + } + } + glPopMatrix(); /* restore state */ + glEndList(); +} + +/* + rip off of the builBlock() function creating the GL compilied pointer "block" but only creates two spheres. + spheres are created with unit_sphere from spheres.h to allow wire frame +*/ +static void buildBlobBlock(ModeInfo *mi) +{ + int wire = MI_IS_WIREFRAME(mi); + topBlockSTATE *tb = &tbs[MI_SCREEN(mi)]; + tb->block=glGenLists(1); /* only one */ + glNewList(tb->block,GL_COMPILE); + glPushMatrix(); + glScalef(1.4,1.4,1.4); + unit_sphere (resolution/2,resolution, wire); + glPopMatrix(); + glTranslatef(0.0f,-2.0f,0.0f); + glScalef(1.4,1.4,1.4); + unit_sphere (resolution/2,resolution, wire); + glEndList(); +} + + +/* handle input events or not if daemon running the show */ +ENTRYPOINT Bool +topBlock_handle_event (ModeInfo *mi, XEvent *event) +{ + topBlockSTATE *tb = &tbs[MI_SCREEN(mi)]; + if (event->xany.type == KeyPress) { + KeySym keysym; + char c = 0; + XLookupString (&event->xkey, &c, 1, &keysym, 0); + if (c == 'a') { + tb->eyeX++; + return True; + } else if (c == 'z') { + tb->eyeX--; + return True; + } else if (c == 's') { + tb->eyeY--; + return True; + } else if (c == 'x') { + tb->eyeY++; + return True; + } else if (c == 'd') { + tb->eyeZ++; + return True; + } else if (c == 'c') { + tb->eyeZ--; + return True; + } else if (c == 'f') { + camX++; + return True; + } else if (c == 'v') { + camX--; + return True; + } else if (c == 'g') { + camY++; + return True; + } else if (c == 'b') { + camY--; + return True; + } else if (c == 'h') { + camZ++; + return True; + } else if (c == 'n') { + camZ--; + return True; + } else if (c == 'r') { + tb->rotation++; + return True; + } + } + if (event->xany.type == ButtonPress && + event->xbutton.button == Button1) + { + tb->button_down_p = True; + gltrackball_start (tb->trackball, + event->xbutton.x, event->xbutton.y, + MI_WIDTH (mi), MI_HEIGHT (mi)); + return True; + } + else if (event->xany.type == ButtonRelease && + event->xbutton.button == Button1) + { + tb->button_down_p = False; + return True; + } + else if (event->xany.type == ButtonPress && + (event->xbutton.button == Button4 || + event->xbutton.button == Button5 || + event->xbutton.button == Button6 || + event->xbutton.button == Button7)) + { + gltrackball_mousewheel (tb->trackball, event->xbutton.button, 10, + !!event->xbutton.state); + return True; + } + else if (event->xany.type == MotionNotify && + tb->button_down_p) + { + gltrackball_track (tb->trackball, + event->xmotion.x, event->xmotion.y, + MI_WIDTH (mi), MI_HEIGHT (mi)); + return True; + } + return False; +} + +/* this is tha main change for v5 compatability and acompanying ENTRYPOINTS */ +XSCREENSAVER_MODULE_2 ("TopBlock", topblock, topBlock) + +#endif /* USE_GL */ diff --git a/hacks/glx/topblock.h b/hacks/glx/topblock.h new file mode 100644 index 00000000..1a66c5d2 --- /dev/null +++ b/hacks/glx/topblock.h @@ -0,0 +1,45 @@ +/* topblock - openGL based hack */ + +static void buildCarpet(ModeInfo *); +static void polygonPlane(int, int, int, int, int ,int); +static void buildBlock(ModeInfo *); +static void generateNewBlock(ModeInfo *); +static void followBlock(ModeInfo *); +static void buildBlobBlock(ModeInfo *); +static double quadrantCorrection(double,int,int,int,int); + +/* this structure holds all the attributes about a block */ +typedef struct blockNode { + int color; /* indexed */ + int rotation; /* indexed: 0=S-N, 1=W-E, 2=N-S, 3=E-W */ + GLfloat height; + GLfloat x; + GLfloat y; + int falling; + struct blockNode *next; +} NODE; + + +/* some handy macros and definitions */ +#define blockHeight 1.49f +#define getHeight(a) (a * blockHeight) + +#define getOrientation(a) (a * 90) + +#define blockWidth 2.0f +#define getLocation(a) (a * blockWidth) + +#define TOLERANCE 0.1f + +#define cylSize 0.333334f +#define uddSize 0.4f +#define singleThick 0.29 /* defines the thickness of the carpet */ + + + + + + + + + diff --git a/hacks/glx/topblock.man b/hacks/glx/topblock.man new file mode 100644 index 00000000..bbe4965e --- /dev/null +++ b/hacks/glx/topblock.man @@ -0,0 +1,170 @@ +.TH XScreenSaver 1 "" "X Version 11" +.SH NAME +topblock - a 3D world of falling blocks that build up and up. +.SH SYNOPSIS +.B topblock +[\-display \fIhost:display.screen\fP] +[\-visual \fIvisual\fP] +[\-window] +[\-root] +[\-delay \fInumber\fP] +[\-wireframe] +[\-fps] +[\-size \fInumber\fP] +[\-spawn \fInumber\fP] +[\-camX \fInumber\fP] +[\-camY \fInumber\fP] +[\-camZ \fInumber\fP] +[\-rotate] +[\-no-carpet] +[\-no-nipples] +[\-blob] +[\-rotateSpeed \fInumber\fP] +[\-follow] +[\-maxFalling \fInumber\fP] +[\-resolution \fInumber\fP] +[\-maxColors \fInumber\fP] +[\-dropSpeed \fInumber\fP] +[\-override] +.SH DESCRIPTION +Creates a world of falling blocks that build up and up. +.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: 10000 (0.01 seconds.). +.TP 8 +.B \-wireframe | \-no-wireframe +Render in wireframe instead of solid. +.TP 8 +.B \-fps +Display the current frame rate, CPU load, and polygon count. +.TP 8 +.B \-size \fInumber\fP +Size of the base/carpet. +.TP 8 +.B \-spawn \fInumber\fP +Likeyhood of a new block being created per frame : 1 high, 1000 very low. +.TP 8 +.B \-camX \fInumber\fP +Initial camera X location in the world. +.TP 8 +.B \-camY \fInumber\fP +Initial camera Y location in the world. +.TP 8 +.B \-camZ \fInumber\fP +Initial camera Z location in the world. +.TP 8 +.B \-rotate | -no-rotate +Add/Remove rotation to/from the animation. +.TP 8 +.B \-no-carpet +Remove the base/carpet. +.TP 8 +.B \-no-nipples +Remove nipples on the blocks (also applies to udders) (has no effect in blob mode). +.TP 8 +.B \-blob +Run in blob mode, blocks become over sized spheres. +.TP 8 +.B \-rotateSpeed \fInumber\fP +Varries speed of world rotation. +.TP 8 +.B \-follow +Camera follows blocks as they fall instead of camera being semi static (stays with top block). +.TP 8 +.B \-maxFalling \fInumber\fP +Maximum number of objects created before recycling occurs. +.TP 8 +.B \-resolution \fInumber\fP +Resolution of tubes, disks and spheres. +.TP 8 +.B \-maxColors \fInumber\fP +Number of different colors available to falling objects. +.TP 8 +.B \-dropSpeed \fInumber\fP +Varries speed of falling objects. +.TP 8 +.B \-override +Overrides camera settings and provides a tunnel view. + +.SH KEYS +.PP +.TP 8 +.B a +Increases viewing X coordinate. +.TP 8 +.B z +Decreases viewing X coordinate. +.TP 8 +.B s +Increases viewing Y coordinate. +.TP 8 +.B x +Decreases viewing Y coordinate. +.TP 8 +.B d +Increases viewing Z coordinate. +.TP 8 +.B c +Decreases viewing Z coordinate. +.TP 8 +.B f +Increases camera location X coordinate. +.TP 8 +.B v +Decreases camera location X coordinate. +.TP 8 +.B g +Increases camera location Y coordinate. +.TP 8 +.B b +Decreases camera location Y coordinate. +.TP 8 +.B h +Increases camera location Z coordinate. +.TP 8 +.B n +Decreases camera location Z coordinate. +.TP 8 +.B r +Increases world rotation. +.TP 8 +.B q +quit. +.SH EXAMPLES +To see which block follow-mode is tracking, set the number of block colors to 1. +.TP 8 +.B topblock -follow -maxColors 1 +.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 2006 by rednuht. 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 +rednuht + diff --git a/hacks/glx/trackball.c b/hacks/glx/trackball.c new file mode 100644 index 00000000..429ade91 --- /dev/null +++ b/hacks/glx/trackball.c @@ -0,0 +1,331 @@ +/* + * (c) Copyright 1993, 1994, Silicon Graphics, Inc. + * ALL RIGHTS RESERVED + * Permission to use, copy, modify, and distribute this software for + * any purpose and without fee is hereby granted, provided that the above + * copyright notice appear in all copies and that both the copyright notice + * and this permission notice appear in supporting documentation, and that + * the name of Silicon Graphics, Inc. not be used in advertising + * or publicity pertaining to distribution of the software without specific, + * written prior permission. + * + * THE MATERIAL EMBODIED ON THIS SOFTWARE IS PROVIDED TO YOU "AS-IS" + * AND WITHOUT WARRANTY OF ANY KIND, EXPRESS, IMPLIED OR OTHERWISE, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTY OF MERCHANTABILITY OR + * FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL SILICON + * GRAPHICS, INC. BE LIABLE TO YOU OR ANYONE ELSE FOR ANY DIRECT, + * SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY + * KIND, OR ANY DAMAGES WHATSOEVER, INCLUDING WITHOUT LIMITATION, + * LOSS OF PROFIT, LOSS OF USE, SAVINGS OR REVENUE, OR THE CLAIMS OF + * THIRD PARTIES, WHETHER OR NOT SILICON GRAPHICS, INC. HAS BEEN + * ADVISED OF THE POSSIBILITY OF SUCH LOSS, HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE + * POSSESSION, USE OR PERFORMANCE OF THIS SOFTWARE. + * + * US Government Users Restricted Rights + * Use, duplication, or disclosure by the Government is subject to + * restrictions set forth in FAR 52.227.19(c)(2) or subparagraph + * (c)(1)(ii) of the Rights in Technical Data and Computer Software + * clause at DFARS 252.227-7013 and/or in similar or successor + * clauses in the FAR or the DOD or NASA FAR Supplement. + * Unpublished-- rights reserved under the copyright laws of the + * United States. Contractor/manufacturer is Silicon Graphics, + * Inc., 2011 N. Shoreline Blvd., Mountain View, CA 94039-7311. + * + * OpenGL(TM) is a trademark of Silicon Graphics, Inc. + */ +/* + * Trackball code: + * + * Implementation of a virtual trackball. + * Implemented by Gavin Bell, lots of ideas from Thant Tessman and + * the August '88 issue of Siggraph's "Computer Graphics," pp. 121-129. + * + * Vector manip code: + * + * Original code from: + * David M. Ciemiewicz, Mark Grossman, Henry Moreton, and Paul Haeberli + * + * Much mucking with by: + * Gavin Bell + */ + +#include + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include "trackball.h" + +/* + * This size should really be based on the distance from the center of + * rotation to the point on the object underneath the mouse. That + * point would then track the mouse as closely as possible. This is a + * simple example, though, so that is left as an Exercise for the + * Programmer. + */ +#define TRACKBALLSIZE (0.8) + +/* + * Local function prototypes (not defined in trackball.h) + */ +static float tb_project_to_sphere(float, float, float); +static void normalize_quat(float [4]); +static void axis_to_quat(float a[3], float phi, float q[4]); + +static void +vzero(float *v) +{ + v[0] = 0.0; + v[1] = 0.0; + v[2] = 0.0; +} + +static void +vset(float *v, float x, float y, float z) +{ + v[0] = x; + v[1] = y; + v[2] = z; +} + +static void +vsub(const float *src1, const float *src2, float *dst) +{ + dst[0] = src1[0] - src2[0]; + dst[1] = src1[1] - src2[1]; + dst[2] = src1[2] - src2[2]; +} + +static void +vcopy(const float *v1, float *v2) +{ + register int i; + for (i = 0 ; i < 3 ; i++) + v2[i] = v1[i]; +} + +static void +vcross(const float *v1, const float *v2, float *cross) +{ + float temp[3]; + + temp[0] = (v1[1] * v2[2]) - (v1[2] * v2[1]); + temp[1] = (v1[2] * v2[0]) - (v1[0] * v2[2]); + temp[2] = (v1[0] * v2[1]) - (v1[1] * v2[0]); + vcopy(temp, cross); +} + +static float +vlength(const float *v) +{ + return sqrt(v[0] * v[0] + v[1] * v[1] + v[2] * v[2]); +} + +static void +vscale(float *v, float div) +{ + v[0] *= div; + v[1] *= div; + v[2] *= div; +} + +static void +vnormal(float *v) +{ + vscale(v,1.0/vlength(v)); +} + +static float +vdot(const float *v1, const float *v2) +{ + return v1[0]*v2[0] + v1[1]*v2[1] + v1[2]*v2[2]; +} + +static void +vadd(const float *src1, const float *src2, float *dst) +{ + dst[0] = src1[0] + src2[0]; + dst[1] = src1[1] + src2[1]; + dst[2] = src1[2] + src2[2]; +} + +/* + * Ok, simulate a track-ball. Project the points onto the virtual + * trackball, then figure out the axis of rotation, which is the cross + * product of P1 P2 and O P1 (O is the center of the ball, 0,0,0) + * Note: This is a deformed trackball-- is a trackball in the center, + * but is deformed into a hyperbolic sheet of rotation away from the + * center. This particular function was chosen after trying out + * several variations. + * + * It is assumed that the arguments to this routine are in the range + * (-1.0 ... 1.0) + */ +void +trackball(float q[4], float p1x, float p1y, float p2x, float p2y) +{ + float a[3]; /* Axis of rotation */ + float phi; /* how much to rotate about axis */ + float p1[3], p2[3], d[3]; + float t; + + if (p1x == p2x && p1y == p2y) { + /* Zero rotation */ + vzero(q); + q[3] = 1.0; + return; + } + + /* + * First, figure out z-coordinates for projection of P1 and P2 to + * deformed sphere + */ + vset(p1,p1x,p1y,tb_project_to_sphere(TRACKBALLSIZE,p1x,p1y)); + vset(p2,p2x,p2y,tb_project_to_sphere(TRACKBALLSIZE,p2x,p2y)); + + /* + * Now, we want the cross product of P1 and P2 + */ + vcross(p2,p1,a); + + /* + * Figure out how much to rotate around that axis. + */ + vsub(p1,p2,d); + t = vlength(d) / (2.0*TRACKBALLSIZE); + + /* + * Avoid problems with out-of-control values... + */ + if (t > 1.0) t = 1.0; + if (t < -1.0) t = -1.0; + phi = 2.0 * asin(t); + + axis_to_quat(a,phi,q); +} + +/* + * Given an axis and angle, compute quaternion. + */ +void +axis_to_quat(float a[3], float phi, float q[4]) +{ + vnormal(a); + vcopy(a,q); + vscale(q,sin(phi/2.0)); + q[3] = cos(phi/2.0); +} + +/* + * Project an x,y pair onto a sphere of radius r OR a hyperbolic sheet + * if we are away from the center of the sphere. + */ +static float +tb_project_to_sphere(float r, float x, float y) +{ + float d, t, z; + + d = sqrt(x*x + y*y); + if (d < r * 0.70710678118654752440) { /* Inside sphere */ + z = sqrt(r*r - d*d); + } else { /* On hyperbola */ + t = r / 1.41421356237309504880; + z = t*t / d; + } + return z; +} + +/* + * Given two rotations, e1 and e2, expressed as quaternion rotations, + * figure out the equivalent single rotation and stuff it into dest. + * + * This routine also normalizes the result every RENORMCOUNT times it is + * called, to keep error from creeping in. + * + * NOTE: This routine is written so that q1 or q2 may be the same + * as dest (or each other). + */ + +#define RENORMCOUNT 97 + +void +add_quats(float q1[4], float q2[4], float dest[4]) +{ + static int count=0; + float t1[4], t2[4], t3[4]; + float tf[4]; + + vcopy(q1,t1); + vscale(t1,q2[3]); + + vcopy(q2,t2); + vscale(t2,q1[3]); + + vcross(q2,q1,t3); + vadd(t1,t2,tf); + vadd(t3,tf,tf); + tf[3] = q1[3] * q2[3] - vdot(q1,q2); + + dest[0] = tf[0]; + dest[1] = tf[1]; + dest[2] = tf[2]; + dest[3] = tf[3]; + + if (++count > RENORMCOUNT) { + count = 0; + normalize_quat(dest); + } +} + +/* + * Quaternions always obey: a^2 + b^2 + c^2 + d^2 = 1.0 + * If they don't add up to 1.0, dividing by their magnitued will + * renormalize them. + * + * Note: See the following for more information on quaternions: + * + * - Shoemake, K., Animating rotation with quaternion curves, Computer + * Graphics 19, No 3 (Proc. SIGGRAPH'85), 245-254, 1985. + * - Pletinckx, D., Quaternion calculus as a basic tool in computer + * graphics, The Visual Computer 5, 2-13, 1989. + */ +static void +normalize_quat(float q[4]) +{ + int i; + float mag; + + mag = (q[0]*q[0] + q[1]*q[1] + q[2]*q[2] + q[3]*q[3]); + for (i = 0; i < 4; i++) q[i] /= mag; +} + +/* + * Build a rotation matrix, given a quaternion rotation. + * + */ +void +build_rotmatrix(float m[4][4], float q[4]) +{ + m[0][0] = 1.0 - 2.0 * (q[1] * q[1] + q[2] * q[2]); + m[0][1] = 2.0 * (q[0] * q[1] - q[2] * q[3]); + m[0][2] = 2.0 * (q[2] * q[0] + q[1] * q[3]); + m[0][3] = 0.0; + + m[1][0] = 2.0 * (q[0] * q[1] + q[2] * q[3]); + m[1][1]= 1.0 - 2.0 * (q[2] * q[2] + q[0] * q[0]); + m[1][2] = 2.0 * (q[1] * q[2] - q[0] * q[3]); + m[1][3] = 0.0; + + m[2][0] = 2.0 * (q[2] * q[0] - q[1] * q[3]); + m[2][1] = 2.0 * (q[1] * q[2] + q[0] * q[3]); + m[2][2] = 1.0 - 2.0 * (q[1] * q[1] + q[0] * q[0]); + m[2][3] = 0.0; + + m[3][0] = 0.0; + m[3][1] = 0.0; + m[3][2] = 0.0; + m[3][3] = 1.0; +} + diff --git a/hacks/glx/trackball.h b/hacks/glx/trackball.h new file mode 100644 index 00000000..4b84ab71 --- /dev/null +++ b/hacks/glx/trackball.h @@ -0,0 +1,82 @@ +/* + * (c) Copyright 1993, 1994, Silicon Graphics, Inc. + * ALL RIGHTS RESERVED + * Permission to use, copy, modify, and distribute this software for + * any purpose and without fee is hereby granted, provided that the above + * copyright notice appear in all copies and that both the copyright notice + * and this permission notice appear in supporting documentation, and that + * the name of Silicon Graphics, Inc. not be used in advertising + * or publicity pertaining to distribution of the software without specific, + * written prior permission. + * + * THE MATERIAL EMBODIED ON THIS SOFTWARE IS PROVIDED TO YOU "AS-IS" + * AND WITHOUT WARRANTY OF ANY KIND, EXPRESS, IMPLIED OR OTHERWISE, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTY OF MERCHANTABILITY OR + * FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL SILICON + * GRAPHICS, INC. BE LIABLE TO YOU OR ANYONE ELSE FOR ANY DIRECT, + * SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY + * KIND, OR ANY DAMAGES WHATSOEVER, INCLUDING WITHOUT LIMITATION, + * LOSS OF PROFIT, LOSS OF USE, SAVINGS OR REVENUE, OR THE CLAIMS OF + * THIRD PARTIES, WHETHER OR NOT SILICON GRAPHICS, INC. HAS BEEN + * ADVISED OF THE POSSIBILITY OF SUCH LOSS, HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE + * POSSESSION, USE OR PERFORMANCE OF THIS SOFTWARE. + * + * US Government Users Restricted Rights + * Use, duplication, or disclosure by the Government is subject to + * restrictions set forth in FAR 52.227.19(c)(2) or subparagraph + * (c)(1)(ii) of the Rights in Technical Data and Computer Software + * clause at DFARS 252.227-7013 and/or in similar or successor + * clauses in the FAR or the DOD or NASA FAR Supplement. + * Unpublished-- rights reserved under the copyright laws of the + * United States. Contractor/manufacturer is Silicon Graphics, + * Inc., 2011 N. Shoreline Blvd., Mountain View, CA 94039-7311. + * + * OpenGL(TM) is a trademark of Silicon Graphics, Inc. + */ +/* + * trackball.h + * A virtual trackball implementation + * Written by Gavin Bell for Silicon Graphics, November 1988. + */ + +#ifndef __TRACKBALL_H__ +#define __TRACKBALL_H__ + +/* + * Pass the x and y coordinates of the last and current positions of + * the mouse, scaled so they are from (-1.0 ... 1.0). + * + * The resulting rotation is returned as a quaternion rotation in the + * first paramater. + */ +void +trackball(float q[4], float p1x, float p1y, float p2x, float p2y); + +/* + * Given two quaternions, add them together to get a third quaternion. + * Adding quaternions to get a compound rotation is analagous to adding + * translations to get a compound translation. When incrementally + * adding rotations, the first argument here should be the new + * rotation, the second and third the total rotation (which will be + * over-written with the resulting new total rotation). + */ +void +add_quats(float *q1, float *q2, float *dest); + +/* + * A useful function, builds a rotation matrix in Matrix based on + * given quaternion. + */ +void +build_rotmatrix(float m[4][4], float q[4]); + +/* + * This function computes a quaternion based on an axis (defined by + * the given vector) and an angle about which to rotate. The angle is + * expressed in radians. The result is put into the third argument. + */ +/* void +axis_to_quat(float a[3], float phi, float q[4]); */ + +#endif /* __TRACKBALL_H__ */ diff --git a/hacks/glx/tronbit.c b/hacks/glx/tronbit.c new file mode 100644 index 00000000..3ab69f1d --- /dev/null +++ b/hacks/glx/tronbit.c @@ -0,0 +1,550 @@ +/* tronbit, Copyright (c) 2011-2012 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. + */ + +#define DEFAULTS "*delay: 30000 \n" \ + "*count: 30 \n" \ + "*showFPS: False \n" \ + "*wireframe: False \n" + +# define refresh_bit 0 +# define release_bit 0 +#undef countof +#define countof(x) (sizeof((x))/sizeof((*x))) + +#include "xlockmore.h" +#include "colors.h" +#include "sphere.h" +#include "rotator.h" +#include "gltrackball.h" +#include + +#ifdef USE_GL /* whole file */ + +#include "gllist.h" + +extern const struct gllist *tronbit_idle1, *tronbit_idle2, + *tronbit_no, *tronbit_yes; +static const struct gllist * const *all_objs[] = { + &tronbit_idle1, &tronbit_idle2, &tronbit_no, &tronbit_yes }; + + +#define DEF_SPIN "True" +#define DEF_WANDER "True" +#define DEF_SPEED "1.0" + +#define HISTORY_LENGTH 512 +typedef enum { BIT_IDLE1, BIT_IDLE2, BIT_NO, BIT_YES } bit_state; +#define MODELS 4 + + +typedef struct { + GLXContext *glx_context; + rotator *rot; + trackball_state *trackball; + Bool button_down_p; + + double frequency; + double confidence; + + double last_time; + unsigned char history [HISTORY_LENGTH]; + unsigned char histogram [HISTORY_LENGTH]; + int history_fp, histogram_fp; + + GLuint dlists[MODELS], polys[MODELS]; + char kbd; + +} bit_configuration; + +static bit_configuration *bps = NULL; + +static const GLfloat colors[][4] = { + { 0.66, 0.85, 1.00, 1.00 }, + { 0.66, 0.85, 1.00, 1.00 }, + { 1.00, 0.12, 0.12, 1.00 }, + { 0.98, 0.85, 0.30, 1.00 } +}; + + +static Bool do_spin; +static GLfloat speed; +static Bool do_wander; + +static XrmOptionDescRec opts[] = { + { "-spin", ".spin", XrmoptionNoArg, "True" }, + { "+spin", ".spin", XrmoptionNoArg, "False" }, + { "-speed", ".speed", XrmoptionSepArg, 0 }, + { "-wander", ".wander", XrmoptionNoArg, "True" }, + { "+wander", ".wander", XrmoptionNoArg, "False" } +}; + +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}, +}; + +ENTRYPOINT ModeSpecOpt bit_opts = {countof(opts), opts, countof(vars), vars, NULL}; + + +/* Returns the current time in seconds as a double. + */ +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 int +make_bit (ModeInfo *mi, bit_state which) +{ + static const GLfloat spec[4] = {1.0, 1.0, 1.0, 1.0}; + static const GLfloat shiny = 128.0; + const GLfloat *color = colors[which]; + int wire = MI_IS_WIREFRAME(mi); + int polys = 0; + GLfloat s; + const struct gllist *gll; + + glMaterialfv (GL_FRONT, GL_SPECULAR, spec); + glMateriali (GL_FRONT, GL_SHININESS, shiny); + glMaterialfv (GL_FRONT, GL_AMBIENT_AND_DIFFUSE, color); + glColor4f (color[0], color[1], color[2], color[3]); + + glPushMatrix(); + switch (which) + { + case BIT_IDLE1: + glRotatef (-44, 0, 1, 0); /* line up the models with each other */ + glRotatef (-11, 1, 0, 0); + glRotatef ( 8, 0, 0, 1); + s = 1.0; + break; + case BIT_IDLE2: + glRotatef ( 16.0, 0, 0, 1); + glRotatef (-28.0, 1, 0, 0); + s = 1.0; + break; + case BIT_NO: + glRotatef ( 16.0, 0, 0, 1); + glRotatef (-28.0, 1, 0, 0); + s = 1.6; + break; + case BIT_YES: + glRotatef (-44.0, 0, 1, 0); + glRotatef (-32.0, 1, 0, 0); + s = 1.53; + break; + default: + abort(); + break; + } + glScalef (s, s, s); + gll = *all_objs[which]; + renderList (gll, wire); + polys += gll->points / 3; + glPopMatrix(); + + return polys; +} + + +static void +tick_bit (ModeInfo *mi, double now) +{ + bit_configuration *bp = &bps[MI_SCREEN(mi)]; + double freq = bp->frequency; + int n = bp->history[bp->history_fp]; + int histogram_speed = 3 * speed; + int i; + + if (histogram_speed < 1) histogram_speed = 1; + + if (n == BIT_YES || n == BIT_NO) + freq *= 2; + + if (bp->button_down_p) return; + + for (i = 0; i < histogram_speed; i++) + { + int nn = (n == BIT_YES ? 240 : n == BIT_NO ? 17 : 128); + int on = bp->histogram[(bp->histogram_fp-1) % countof(bp->histogram)]; + + /* smooth out the square wave a little bit */ + + if (!(nn > 100 && nn < 200) != + !(on > 100 && on < 200)) + nn += (((random() % 48) - 32) * + ((on > 100 && on < 200) ? 1 : -1)); + + nn += (random() % 16) - 8; + + bp->histogram_fp++; + if (bp->histogram_fp >= countof(bp->history)) + bp->histogram_fp = 0; + bp->histogram [bp->histogram_fp] = nn; + } + + + if (bp->last_time + freq > now && !bp->kbd) return; + + bp->last_time = now; + + bp->history_fp++; + if (bp->history_fp >= countof(bp->history)) + bp->history_fp = 0; + + if (bp->kbd) + { + n = (bp->kbd == '1' ? BIT_YES : + bp->kbd == '0' ? BIT_NO : + (random() & 1) ? BIT_YES : BIT_NO); + bp->kbd = 0; + } + else if (n == BIT_YES || + n == BIT_NO || + frand(1.0) >= bp->confidence) + n = (n == BIT_IDLE1 ? BIT_IDLE2 : BIT_IDLE1); + else + n = (random() & 1) ? BIT_YES : BIT_NO; + + bp->history [bp->history_fp] = n; +} + + +static int +animate_bits (ModeInfo *mi, bit_state omodel, bit_state nmodel, GLfloat ratio) +{ + bit_configuration *bp = &bps[MI_SCREEN(mi)]; + int polys = 0; + GLfloat scale = sin (ratio * M_PI / 2); + GLfloat osize, nsize, small; + int wire = MI_IS_WIREFRAME(mi); + + glShadeModel(GL_SMOOTH); + + glEnable(GL_DEPTH_TEST); + glEnable(GL_NORMALIZE); + glEnable(GL_CULL_FACE); + + if (!wire) + { + glEnable(GL_LIGHTING); + glEnable(GL_DEPTH_TEST); + glEnable(GL_CULL_FACE); + } + + if ((omodel == BIT_IDLE1 || omodel == BIT_IDLE2) && + (nmodel == BIT_IDLE1 || nmodel == BIT_IDLE2)) + small = 0.9; + else + small = 0.5; + + nsize = small + (1 - small) * scale; + osize = small + (1 - small) * (1 - scale); + + glPushMatrix(); + glScalef (osize, osize, osize); + glCallList (bp->dlists [omodel]); + polys += bp->polys [omodel]; + glPopMatrix(); + + glPushMatrix(); + glScalef (nsize, nsize, nsize); + glCallList (bp->dlists [nmodel]); + polys += bp->polys [nmodel]; + glPopMatrix(); + + return polys; +} + + +static int +draw_histogram (ModeInfo *mi, GLfloat ratio) +{ + bit_configuration *bp = &bps[MI_SCREEN(mi)]; + int samples = countof (bp->histogram); + GLfloat scalex = (GLfloat) mi->xgwa.width / samples; + GLfloat scaley = mi->xgwa.height / 255.0 / 4; /* about 1/4th of screen */ + int polys = 0; + int overlays = 5; + int k; + + glDisable (GL_TEXTURE_2D); + glDisable (GL_LIGHTING); + glDisable (GL_BLEND); + glDisable (GL_DEPTH_TEST); + glDisable (GL_CULL_FACE); + + glMatrixMode(GL_PROJECTION); + glPushMatrix(); + { + glLoadIdentity(); + glMatrixMode(GL_MODELVIEW); + glPushMatrix(); + + glLoadIdentity(); + glRotatef(current_device_rotation(), 0, 0, 1); + glOrtho (0, mi->xgwa.width, 0, mi->xgwa.height, -1, 1); + + for (k = 0; k < overlays; k++) + { + int i, j; + GLfloat a = (GLfloat) k / overlays; + + glColor3f (0.3 * a, 0.7 * a, 1.0 * a); + + glBegin (GL_LINE_STRIP); + + j = bp->histogram_fp + 1; + for (i = 0; i < samples; i++) + { + GLfloat x = i; + GLfloat y = bp->histogram[j]; + GLfloat z = 0; + + y += (int) ((random() % 16) - 8); + y += 16; /* margin at bottom of screen */ + + x *= scalex; + y *= scaley; + + glVertex3f (x, y, z); + if (++j >= samples) j = 0; + polys++; + } + glEnd(); + } + + glPopMatrix(); + } + glMatrixMode(GL_PROJECTION); + glPopMatrix(); + + glMatrixMode(GL_MODELVIEW); + + return polys; +} + + +/* Window management, etc + */ +ENTRYPOINT void +reshape_bit (ModeInfo *mi, int width, int height) +{ + GLfloat h = (GLfloat) height / (GLfloat) width; + + glViewport (0, 0, (GLint) width, (GLint) height); + + glMatrixMode(GL_PROJECTION); + glLoadIdentity(); + gluPerspective (30.0, 1/h, 1.0, 100.0); + + glMatrixMode(GL_MODELVIEW); + glLoadIdentity(); + gluLookAt( 0.0, 0.0, 30.0, + 0.0, 0.0, 0.0, + 0.0, 1.0, 0.0); + + glClear(GL_COLOR_BUFFER_BIT); +} + + + +ENTRYPOINT Bool +bit_handle_event (ModeInfo *mi, XEvent *event) +{ + bit_configuration *bp = &bps[MI_SCREEN(mi)]; + + if (event->xany.type == ButtonPress && + event->xbutton.button == Button1) + { + bp->button_down_p = True; + gltrackball_start (bp->trackball, + event->xbutton.x, event->xbutton.y, + MI_WIDTH (mi), MI_HEIGHT (mi)); + return True; + } + else if (event->xany.type == ButtonRelease && + event->xbutton.button == Button1) + { + bp->button_down_p = False; + return True; + } + else if (event->xany.type == ButtonPress && + (event->xbutton.button == Button4 || + event->xbutton.button == Button5 || + event->xbutton.button == Button6 || + event->xbutton.button == Button7)) + { + gltrackball_mousewheel (bp->trackball, event->xbutton.button, 3, + !!event->xbutton.state); + return True; + } + else if (event->xany.type == MotionNotify && + bp->button_down_p) + { + gltrackball_track (bp->trackball, + event->xmotion.x, event->xmotion.y, + MI_WIDTH (mi), MI_HEIGHT (mi)); + return True; + } + else if (event->xany.type == KeyPress) + { + KeySym keysym; + char c = 0; + XLookupString (&event->xkey, &c, 1, &keysym, 0); + if (c == ' ' || c == '1' || c == '0') + { + bp->kbd = c; + return True; + } + } + + return False; +} + + +ENTRYPOINT void +init_bit (ModeInfo *mi) +{ + bit_configuration *bp; + int i; + + if (!bps) { + bps = (bit_configuration *) + calloc (MI_NUM_SCREENS(mi), sizeof (bit_configuration)); + if (!bps) { + fprintf(stderr, "%s: out of memory\n", progname); + exit(1); + } + } + + bp = &bps[MI_SCREEN(mi)]; + + bp->glx_context = init_GL(mi); + + reshape_bit (mi, MI_WIDTH(mi), MI_HEIGHT(mi)); + + { + double spin_speed = 3.0; + double wander_speed = 0.03 * speed; + double spin_accel = 4.0; + + bp->rot = make_rotator (do_spin ? spin_speed : 0, + do_spin ? spin_speed : 0, + do_spin ? spin_speed : 0, + spin_accel, + do_wander ? wander_speed : 0, + False); + bp->trackball = gltrackball_init (); + } + + for (i = 0; i < countof(bp->dlists); i++) + { + bp->dlists[i] = glGenLists (1); + glNewList (bp->dlists[i], GL_COMPILE); + bp->polys [i] = make_bit (mi, i); + glEndList (); + } + + bp->frequency = 0.30 / speed; /* parity around 3x/second */ + bp->confidence = 0.06; /* provide answer 1/15 or so */ + + for (i = 0; i < countof(bp->histogram); i++) + bp->histogram[i] = 128 + (random() % 16) - 8; +} + + +ENTRYPOINT void +draw_bit (ModeInfo *mi) +{ + bit_configuration *bp = &bps[MI_SCREEN(mi)]; + Display *dpy = MI_DISPLAY(mi); + Window window = MI_WINDOW(mi); + int wire = MI_IS_WIREFRAME(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); + + if (!wire) + { + GLfloat pos[4] = {1.0, 1.0, 1.0, 0.0}; + GLfloat amb[4] = {0.0, 0.0, 0.0, 1.0}; + GLfloat dif[4] = {1.0, 1.0, 1.0, 1.0}; + GLfloat spc[4] = {0.0, 1.0, 1.0, 1.0}; + + 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); + } + + glPushMatrix (); + glRotatef(current_device_rotation(), 0, 0, 1); + glScalef(1.1, 1.1, 1.1); + + { + double x, y, z; + get_position (bp->rot, &x, &y, &z, !bp->button_down_p); + glTranslatef((x - 0.5) * 11, + (y - 0.5) * 5, + (z - 0.5) * 3); + gltrackball_rotate (bp->trackball); + + get_rotation (bp->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); + } + + mi->polygon_count = 0; + + glScalef (6, 6, 6); + + { + int nmodel = bp->history [bp->history_fp]; + int omodel = bp->history [bp->history_fp > 0 + ? bp->history_fp-1 + : countof(bp->history)-1]; + double now = double_time(); + double ratio = 1 - ((bp->last_time + bp->frequency) - now) / bp->frequency; + if (ratio > 1) ratio = 1; + mi->polygon_count += draw_histogram (mi, ratio); + mi->polygon_count += animate_bits (mi, omodel, nmodel, ratio); + tick_bit (mi, now); + } + glPopMatrix (); + + if (mi->fps_p) do_fps (mi); + glFinish(); + + glXSwapBuffers(dpy, window); +} + +XSCREENSAVER_MODULE_2 ("TronBit", tronbit, bit) + +#endif /* USE_GL */ diff --git a/hacks/glx/tronbit.man b/hacks/glx/tronbit.man new file mode 100644 index 00000000..9001f0e3 --- /dev/null +++ b/hacks/glx/tronbit.man @@ -0,0 +1,79 @@ +.TH XScreenSaver 1 "" "X Version 11" +.SH NAME +tronbit - Yes. Yes. No. Yes. Yes. No. Yes. Yes yes yes yes yes. +.SH SYNOPSIS +.B tronbit +[\-display \fIhost:display.screen\fP] +[\-visual \fIvisual\fP] +[\-window] +[\-root] +[\-delay \fInumber\fP] +[\-speed \fIratio\fP] +[\-spin] +[\-wander] +[\-wireframe] +[\-fps] +.SH DESCRIPTION +Draws an animation of the character "Bit" from the film, \fITron\fP. + +The "yes" state is a tetrahedron; the "no" state is the second +stellation of an icosahedron; and the idle state oscillates between +a small triambic icosahedron and the compound of an icosahedron and +a dodecahedron. +.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 \-speed \fInumber\fP +How fast the animation should run. +Less than 1 for slower, greater than 1 for faster. +.TP 8 +.B \-no\-spin +Don't rotate. +.TP 8 +.B \-no\-wander +Don't wander around. +.TP 8 +.B \-wireframe +Render in wireframe instead of solid. +.TP 8 +.B \-fps +Display the current frame rate, CPU load, and polygon count. +.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 polyhedra (1), +.BR dangerball (1), +.BR companioncube (1), +.BR xscreensaver (1), +.BR TRON. +.SH COPYRIGHT +Copyright \(co 2011 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, who fights for the users. diff --git a/hacks/glx/tronbit_idle1.c b/hacks/glx/tronbit_idle1.c new file mode 100644 index 00000000..f053259c --- /dev/null +++ b/hacks/glx/tronbit_idle1.c @@ -0,0 +1,247 @@ +/* odd parity = small triambic icosahedron */ + +#include "gllist.h" +static const float data[]={ + 0,0,1,0.263523,-0.204124,0.372678, + 0,0,1,0.263523,0.10775,0.372678, + 0,0,1,0.045015,0.33028,0.372678, + 0,0,1,0.263523,-0.204124,0.372678, + 0,0,1,0.045015,0.33028,0.372678, + 0,0,1,-0.225076,0.174343,0.372678, + 0,0,1,0.263523,-0.204124,0.372678, + 0,0,1,-0.225076,0.174343,0.372678, + 0,0,1,-0.308538,-0.126156,0.372678, + 0,0,1,0.263523,-0.204124,0.372678, + 0,0,1,-0.308538,-0.126156,0.372678, + 0,0,1,-0.038448,-0.282093,0.372678, + 0.942809,0,0.333333,0.263523,-0.204124,0.372678, + 0.942809,0,0.333333,0.36418,-0.282093,0.087977, + 0.942809,0,0.333333,0.45421,-0.126156,-0.166667, + 0.942809,0,0.333333,0.263523,-0.204124,0.372678, + 0.942809,0,0.333333,0.45421,-0.126156,-0.166667, + 0.942809,0,0.333333,0.426389,0.174343,-0.087977, + 0.942809,0,0.333333,0.263523,-0.204124,0.372678, + 0.942809,0,0.333333,0.426389,0.174343,-0.087977, + 0.942809,0,0.333333,0.336359,0.33028,0.166667, + 0.942809,0,0.333333,0.263523,-0.204124,0.372678, + 0.942809,0,0.333333,0.336359,0.33028,0.166667, + 0.942809,0,0.333333,0.263523,0.10775,0.372678, + 0.672718,0.66056,0.333333,0.263523,0.10775,0.372678, + 0.672718,0.66056,0.333333,0.471405,0,0.166667, + 0.672718,0.66056,0.333333,0.426389,0.174343,-0.087977, + 0.672718,0.66056,0.333333,0.263523,0.10775,0.372678, + 0.672718,0.66056,0.333333,0.426389,0.174343,-0.087977, + 0.672718,0.66056,0.333333,0.235702,0.408248,-0.166667, + 0.672718,0.66056,0.333333,0.263523,0.10775,0.372678, + 0.672718,0.66056,0.333333,0.235702,0.408248,-0.166667, + 0.672718,0.66056,0.333333,0.062209,0.456436,0.087977, + 0.672718,0.66056,0.333333,0.263523,0.10775,0.372678, + 0.672718,0.66056,0.333333,0.062209,0.456436,0.087977, + 0.672718,0.66056,0.333333,0.045015,0.33028,0.372678, + -0.471405,0.816497,0.333333,0.045015,0.33028,0.372678, + -0.471405,0.816497,0.333333,0.062209,0.456436,0.087977, + -0.471405,0.816497,0.333333,-0.117851,0.456436,-0.166667, + -0.471405,0.816497,0.333333,0.045015,0.33028,0.372678, + -0.471405,0.816497,0.333333,-0.117851,0.456436,-0.166667, + -0.471405,0.816497,0.333333,-0.36418,0.282093,-0.087977, + -0.471405,0.816497,0.333333,0.045015,0.33028,0.372678, + -0.471405,0.816497,0.333333,-0.36418,0.282093,-0.087977, + -0.471405,0.816497,0.333333,-0.45421,0.126156,0.166667, + -0.471405,0.816497,0.333333,0.045015,0.33028,0.372678, + -0.471405,0.816497,0.333333,-0.45421,0.126156,0.166667, + -0.471405,0.816497,0.333333,-0.225076,0.174343,0.372678, + -0.908421,0.252311,0.333333,-0.225076,0.174343,0.372678, + -0.908421,0.252311,0.333333,-0.235702,0.408248,0.166667, + -0.908421,0.252311,0.333333,-0.36418,0.282093,-0.087977, + -0.90842,0.252312,0.333333,-0.225076,0.174343,0.372678, + -0.90842,0.252312,0.333333,-0.36418,0.282093,-0.087977, + -0.90842,0.252312,0.333333,-0.471405,0,-0.166667, + -0.90842,0.252311,0.333334,-0.225076,0.174343,0.372678, + -0.90842,0.252311,0.333334,-0.471405,0,-0.166667, + -0.90842,0.252311,0.333334,-0.426389,-0.174343,0.087977, + -0.908421,0.252311,0.333333,-0.225076,0.174343,0.372678, + -0.908421,0.252311,0.333333,-0.426389,-0.174343,0.087977, + -0.908421,0.252311,0.333333,-0.308538,-0.126156,0.372678, + -0.471405,-0.816497,0.333333,-0.308538,-0.126156,0.372678, + -0.471405,-0.816497,0.333333,-0.426389,-0.174343,0.087977, + -0.471405,-0.816497,0.333333,-0.336359,-0.33028,-0.166667, + -0.471404,-0.816497,0.333333,-0.308538,-0.126156,0.372678, + -0.471404,-0.816497,0.333333,-0.336359,-0.33028,-0.166667, + -0.471404,-0.816497,0.333333,-0.062209,-0.456436,-0.087977, + -0.471405,-0.816497,0.333333,-0.308538,-0.126156,0.372678, + -0.471405,-0.816497,0.333333,-0.062209,-0.456436,-0.087977, + -0.471405,-0.816497,0.333333,0.117851,-0.456436,0.166667, + -0.471405,-0.816497,0.333333,-0.308538,-0.126156,0.372678, + -0.471405,-0.816497,0.333333,0.117851,-0.456436,0.166667, + -0.471405,-0.816497,0.333333,-0.038448,-0.282093,0.372678, + 0.235702,-0.912871,0.333333,-0.038448,-0.282093,0.372678, + 0.235702,-0.912871,0.333333,-0.235702,-0.408248,0.166667, + 0.235702,-0.912871,0.333333,-0.062209,-0.456436,-0.087977, + 0.235702,-0.912871,0.333333,-0.038448,-0.282093,0.372678, + 0.235702,-0.912871,0.333333,-0.062209,-0.456436,-0.087977, + 0.235702,-0.912871,0.333333,0.235702,-0.408248,-0.166667, + 0.235702,-0.912871,0.333333,-0.038448,-0.282093,0.372678, + 0.235702,-0.912871,0.333333,0.235702,-0.408248,-0.166667, + 0.235702,-0.912871,0.333333,0.36418,-0.282093,0.087977, + 0.235702,-0.912871,0.333333,-0.038448,-0.282093,0.372678, + 0.235702,-0.912871,0.333333,0.36418,-0.282093,0.087977, + 0.235702,-0.912871,0.333333,0.263523,-0.204124,0.372678, + 0.09003,0.66056,0.745356,0.263523,0.10775,0.372678, + 0.09003,0.66056,0.745356,0.336359,0.33028,0.166667, + 0.09003,0.66056,0.745356,0.062209,0.456436,0.087977, + 0.09003,0.66056,0.745356,0.263523,0.10775,0.372678, + 0.09003,0.66056,0.745356,0.062209,0.456436,0.087977, + 0.09003,0.66056,0.745356,-0.235702,0.408248,0.166667, + 0.09003,0.66056,0.745356,0.263523,0.10775,0.372678, + 0.09003,0.66056,0.745356,-0.235702,0.408248,0.166667, + 0.09003,0.66056,0.745356,-0.225076,0.174343,0.372678, + 0.09003,0.660559,0.745356,0.263523,0.10775,0.372678, + 0.09003,0.660559,0.745356,-0.225076,0.174343,0.372678, + 0.09003,0.660559,0.745356,0,0,0.5, + 0.471405,0.816497,-0.333333,0.336359,0.33028,0.166667, + 0.471405,0.816497,-0.333333,0.426389,0.174343,-0.087977, + 0.471405,0.816497,-0.333333,0.308538,0.126156,-0.372678, + 0.471405,0.816497,-0.333333,0.336359,0.33028,0.166667, + 0.471405,0.816497,-0.333333,0.308538,0.126156,-0.372678, + 0.471405,0.816497,-0.333333,0.038448,0.282093,-0.372678, + 0.471405,0.816497,-0.333333,0.336359,0.33028,0.166667, + 0.471405,0.816497,-0.333333,0.038448,0.282093,-0.372678, + 0.471405,0.816497,-0.333333,-0.117851,0.456436,-0.166667, + 0.471404,0.816497,-0.333333,0.336359,0.33028,0.166667, + 0.471404,0.816497,-0.333333,-0.117851,0.456436,-0.166667, + 0.471404,0.816497,-0.333333,0.062209,0.456436,0.087977, + 0.617077,0.252311,-0.745356,0.426389,0.174343,-0.087977, + 0.617077,0.252311,-0.745356,0.45421,-0.126156,-0.166667, + 0.617077,0.252311,-0.745356,0.225076,-0.174343,-0.372678, + 0.617076,0.252311,-0.745356,0.426389,0.174343,-0.087977, + 0.617076,0.252311,-0.745356,0.225076,-0.174343,-0.372678, + 0.617076,0.252311,-0.745356,0,0,-0.5, + 0.617077,0.252311,-0.745356,0.426389,0.174343,-0.087977, + 0.617077,0.252311,-0.745356,0,0,-0.5, + 0.617077,0.252311,-0.745356,0.038448,0.282093,-0.372678, + 0.617077,0.252311,-0.745356,0.426389,0.174343,-0.087977, + 0.617077,0.252311,-0.745356,0.038448,0.282093,-0.372678, + 0.617077,0.252311,-0.745356,0.235702,0.408248,-0.166667, + 0.471405,-0.816497,-0.333333,0.45421,-0.126156,-0.166667, + 0.471405,-0.816497,-0.333333,0.36418,-0.282093,0.087977, + 0.471405,-0.816497,-0.333333,0.117851,-0.456436,0.166667, + 0.471405,-0.816497,-0.333333,0.45421,-0.126156,-0.166667, + 0.471405,-0.816497,-0.333333,0.117851,-0.456436,0.166667, + 0.471405,-0.816497,-0.333333,-0.062209,-0.456436,-0.087977, + 0.471405,-0.816497,-0.333333,0.45421,-0.126156,-0.166667, + 0.471405,-0.816497,-0.333333,-0.062209,-0.456436,-0.087977, + 0.471405,-0.816497,-0.333333,-0.045015,-0.33028,-0.372678, + 0.471405,-0.816497,-0.333333,0.45421,-0.126156,-0.166667, + 0.471405,-0.816497,-0.333333,-0.045015,-0.33028,-0.372678, + 0.471405,-0.816497,-0.333333,0.225076,-0.174343,-0.372678, + -0.235702,0.912871,-0.333333,0.062209,0.456436,0.087977, + -0.235702,0.912871,-0.333333,0.235702,0.408248,-0.166667, + -0.235702,0.912871,-0.333333,0.038448,0.282093,-0.372678, + -0.235702,0.912871,-0.333333,0.062209,0.456436,0.087977, + -0.235702,0.912871,-0.333333,0.038448,0.282093,-0.372678, + -0.235702,0.912871,-0.333333,-0.263523,0.204124,-0.372678, + -0.235702,0.912871,-0.333333,0.062209,0.456436,0.087977, + -0.235702,0.912871,-0.333333,-0.263523,0.204124,-0.372678, + -0.235702,0.912871,-0.333333,-0.36418,0.282093,-0.087977, + -0.235702,0.912871,-0.333333,0.062209,0.456436,0.087977, + -0.235702,0.912871,-0.333333,-0.36418,0.282093,-0.087977, + -0.235702,0.912871,-0.333333,-0.235702,0.408248,0.166667, + 0.90842,-0.252312,-0.333334,0.426389,0.174343,-0.087977, + 0.90842,-0.252312,-0.333334,0.471405,0,0.166667, + 0.90842,-0.252312,-0.333334,0.36418,-0.282093,0.087977, + 0.908421,-0.252311,-0.333333,0.426389,0.174343,-0.087977, + 0.908421,-0.252311,-0.333333,0.36418,-0.282093,0.087977, + 0.908421,-0.252311,-0.333333,0.235702,-0.408248,-0.166667, + 0.908421,-0.252311,-0.333333,0.426389,0.174343,-0.087977, + 0.908421,-0.252311,-0.333333,0.235702,-0.408248,-0.166667, + 0.908421,-0.252311,-0.333333,0.225076,-0.174343,-0.372678, + 0.908421,-0.252311,-0.333333,0.426389,0.174343,-0.087977, + 0.908421,-0.252311,-0.333333,0.225076,-0.174343,-0.372678, + 0.908421,-0.252311,-0.333333,0.308538,0.126156,-0.372678, + 0.527046,-0.408248,0.745356,0.471405,0,0.166667, + 0.527046,-0.408248,0.745356,0.263523,0.10775,0.372678, + 0.527046,-0.408248,0.745356,0,0,0.5, + 0.527046,-0.408248,0.745356,0.471405,0,0.166667, + 0.527046,-0.408248,0.745356,0,0,0.5, + 0.527046,-0.408248,0.745356,-0.038448,-0.282093,0.372678, + 0.527046,-0.408248,0.745356,0.471405,0,0.166667, + 0.527046,-0.408248,0.745356,-0.038448,-0.282093,0.372678, + 0.527046,-0.408248,0.745356,0.117851,-0.456436,0.166667, + 0.527047,-0.408249,0.745356,0.471405,0,0.166667, + 0.527047,-0.408249,0.745356,0.117851,-0.456436,0.166667, + 0.527047,-0.408249,0.745356,0.36418,-0.282093,0.087977, + -0.617077,-0.252311,0.745356,-0.225076,0.174343,0.372678, + -0.617077,-0.252311,0.745356,-0.45421,0.126156,0.166667, + -0.617077,-0.252311,0.745356,-0.426389,-0.174343,0.087977, + -0.617077,-0.252311,0.745356,-0.225076,0.174343,0.372678, + -0.617077,-0.252311,0.745356,-0.426389,-0.174343,0.087977, + -0.617077,-0.252311,0.745356,-0.235702,-0.408248,0.166667, + -0.617077,-0.252311,0.745356,-0.225076,0.174343,0.372678, + -0.617077,-0.252311,0.745356,-0.235702,-0.408248,0.166667, + -0.617077,-0.252311,0.745356,-0.038448,-0.282093,0.372678, + -0.617076,-0.252311,0.745356,-0.225076,0.174343,0.372678, + -0.617076,-0.252311,0.745356,-0.038448,-0.282093,0.372678, + -0.617076,-0.252311,0.745356,0,0,0.5, + -0.942809,0,-0.333333,-0.45421,0.126156,0.166667, + -0.942809,0,-0.333333,-0.36418,0.282093,-0.087977, + -0.942809,0,-0.333333,-0.263523,0.204124,-0.372678, + -0.942809,0,-0.333333,-0.45421,0.126156,0.166667, + -0.942809,0,-0.333333,-0.263523,0.204124,-0.372678, + -0.942809,0,-0.333333,-0.263523,-0.10775,-0.372678, + -0.942809,0,-0.333333,-0.45421,0.126156,0.166667, + -0.942809,0,-0.333333,-0.263523,-0.10775,-0.372678, + -0.942809,0,-0.333333,-0.336359,-0.33028,-0.166667, + -0.942809,0,-0.333333,-0.45421,0.126156,0.166667, + -0.942809,0,-0.333333,-0.336359,-0.33028,-0.166667, + -0.942809,0,-0.333333,-0.426389,-0.174343,0.087977, + -0.527046,0.408248,-0.745356,-0.36418,0.282093,-0.087977, + -0.527046,0.408248,-0.745356,-0.117851,0.456436,-0.166667, + -0.527046,0.408248,-0.745356,0.038448,0.282093,-0.372678, + -0.527046,0.408248,-0.745356,-0.36418,0.282093,-0.087977, + -0.527046,0.408248,-0.745356,0.038448,0.282093,-0.372678, + -0.527046,0.408248,-0.745356,0,0,-0.5, + -0.527046,0.408248,-0.745356,-0.36418,0.282093,-0.087977, + -0.527046,0.408248,-0.745356,0,0,-0.5, + -0.527046,0.408248,-0.745356,-0.263523,-0.10775,-0.372678, + -0.527046,0.408249,-0.745356,-0.36418,0.282093,-0.087977, + -0.527046,0.408249,-0.745356,-0.263523,-0.10775,-0.372678, + -0.527046,0.408249,-0.745356,-0.471405,0,-0.166667, + -0.672718,-0.66056,-0.333333,-0.426389,-0.174343,0.087977, + -0.672718,-0.66056,-0.333333,-0.471405,0,-0.166667, + -0.672718,-0.66056,-0.333333,-0.263523,-0.10775,-0.372678, + -0.672718,-0.66056,-0.333333,-0.426389,-0.174343,0.087977, + -0.672718,-0.66056,-0.333333,-0.263523,-0.10775,-0.372678, + -0.672718,-0.66056,-0.333333,-0.045015,-0.33028,-0.372678, + -0.672718,-0.66056,-0.333333,-0.426389,-0.174343,0.087977, + -0.672718,-0.66056,-0.333333,-0.045015,-0.33028,-0.372678, + -0.672718,-0.66056,-0.333333,-0.062209,-0.456436,-0.087977, + -0.672718,-0.66056,-0.333333,-0.426389,-0.174343,0.087977, + -0.672718,-0.66056,-0.333333,-0.062209,-0.456436,-0.087977, + -0.672718,-0.66056,-0.333333,-0.235702,-0.408248,0.166667, + -0.09003,-0.66056,-0.745356,-0.062209,-0.456436,-0.087977, + -0.09003,-0.66056,-0.745356,-0.336359,-0.33028,-0.166667, + -0.09003,-0.66056,-0.745356,-0.263523,-0.10775,-0.372678, + -0.09003,-0.66056,-0.745356,-0.062209,-0.456436,-0.087977, + -0.09003,-0.66056,-0.745356,-0.263523,-0.10775,-0.372678, + -0.09003,-0.66056,-0.745356,0,0,-0.5, + -0.09003,-0.66056,-0.745356,-0.062209,-0.456436,-0.087977, + -0.09003,-0.66056,-0.745356,0,0,-0.5, + -0.09003,-0.66056,-0.745356,0.225076,-0.174343,-0.372678, + -0.09003,-0.66056,-0.745356,-0.062209,-0.456436,-0.087977, + -0.09003,-0.66056,-0.745356,0.225076,-0.174343,-0.372678, + -0.09003,-0.66056,-0.745356,0.235702,-0.408248,-0.166667, + 0,0,-1,0.308538,0.126156,-0.372678, + 0,0,-1,0.225076,-0.174343,-0.372678, + 0,0,-1,-0.045015,-0.33028,-0.372678, + 0,0,-1,0.308538,0.126156,-0.372678, + 0,0,-1,-0.045015,-0.33028,-0.372678, + 0,0,-1,-0.263523,-0.10775,-0.372678, + 0,0,-1,0.308538,0.126156,-0.372678, + 0,0,-1,-0.263523,-0.10775,-0.372678, + 0,0,-1,-0.263523,0.204124,-0.372678, + 0,0,-1,0.308538,0.126156,-0.372678, + 0,0,-1,-0.263523,0.204124,-0.372678, + 0,0,-1,0.038448,0.282093,-0.372678 +}; +static const struct gllist frame={GL_N3F_V3F,GL_TRIANGLES,240,data,NULL}; +const struct gllist *tronbit_idle1=&frame; diff --git a/hacks/glx/tronbit_idle2.c b/hacks/glx/tronbit_idle2.c new file mode 100644 index 00000000..8ee0380f --- /dev/null +++ b/hacks/glx/tronbit_idle2.c @@ -0,0 +1,175 @@ +/* even parity = compound of icosahedron and dodecahedron */ + +#include "gllist.h" +static const float data[]={ + 0.491123,0.356822,0.794655,0.138196,0.425326,0.223607, + 0.491123,0.356822,0.794655,0,0,0.5, + 0.491123,0.356822,0.794655,0.447213,0,0.223607, + -0.187593,0.57735,0.794655,-0.361804,0.262865,0.223607, + -0.187593,0.57735,0.794655,0,0,0.5, + -0.187593,0.57735,0.794655,0.138196,0.425326,0.223607, + -0.607062,0,0.794655,-0.361804,-0.262865,0.223607, + -0.607062,0,0.794655,0,0,0.5, + -0.607062,0,0.794655,-0.361804,0.262865,0.223607, + -0.187593,-0.57735,0.794655,0.138196,-0.425326,0.223607, + -0.187593,-0.57735,0.794655,0,0,0.5, + -0.187593,-0.57735,0.794655,-0.361804,-0.262865,0.223607, + 0.491123,-0.356822,0.794655,0,0,0.5, + 0.491123,-0.356822,0.794655,0.138196,-0.425326,0.223607, + 0.491123,-0.356822,0.794655,0.447213,0,0.223607, + 0.794655,-0.57735,0.187593,0.361804,-0.262865,-0.223607, + 0.794655,-0.57735,0.187593,0.447213,0,0.223607, + 0.794655,-0.57735,0.187593,0.138196,-0.425326,0.223607, + 0.982247,0,-0.187592,0.447213,0,0.223607, + 0.982247,0,-0.187592,0.361804,-0.262865,-0.223607, + 0.982247,0,-0.187592,0.361804,0.262865,-0.223607, + 0.794655,0.57735,0.187593,0.447213,0,0.223607, + 0.794655,0.57735,0.187593,0.361804,0.262865,-0.223607, + 0.794655,0.57735,0.187593,0.138196,0.425326,0.223607, + 0.303531,0.934172,-0.187592,-0.138196,0.425326,-0.223607, + 0.303531,0.934172,-0.187592,0.138196,0.425326,0.223607, + 0.303531,0.934172,-0.187592,0.361804,0.262865,-0.223607, + -0.303531,0.934172,0.187592,0.138196,0.425326,0.223607, + -0.303531,0.934172,0.187592,-0.138196,0.425326,-0.223607, + -0.303531,0.934172,0.187592,-0.361804,0.262865,0.223607, + -0.794655,0.57735,-0.187593,-0.447213,0,-0.223607, + -0.794655,0.57735,-0.187593,-0.361804,0.262865,0.223607, + -0.794655,0.57735,-0.187593,-0.138196,0.425326,-0.223607, + -0.982247,0,0.187592,-0.361804,0.262865,0.223607, + -0.982247,0,0.187592,-0.447213,0,-0.223607, + -0.982247,0,0.187592,-0.361804,-0.262865,0.223607, + -0.794655,-0.57735,-0.187593,-0.138196,-0.425326,-0.223607, + -0.794655,-0.57735,-0.187593,-0.361804,-0.262865,0.223607, + -0.794655,-0.57735,-0.187593,-0.447213,0,-0.223607, + -0.303531,-0.934172,0.187592,-0.361804,-0.262865,0.223607, + -0.303531,-0.934172,0.187592,-0.138196,-0.425326,-0.223607, + -0.303531,-0.934172,0.187592,0.138196,-0.425326,0.223607, + 0.303531,-0.934172,-0.187592,0.138196,-0.425326,0.223607, + 0.303531,-0.934172,-0.187592,-0.138196,-0.425326,-0.223607, + 0.303531,-0.934172,-0.187592,0.361804,-0.262865,-0.223607, + 0.607062,0,-0.794655,0,0,-0.5, + 0.607062,0,-0.794655,0.361804,0.262865,-0.223607, + 0.607062,0,-0.794655,0.361804,-0.262865,-0.223607, + 0.187593,0.57735,-0.794655,0.361804,0.262865,-0.223607, + 0.187593,0.57735,-0.794655,0,0,-0.5, + 0.187593,0.57735,-0.794655,-0.138196,0.425326,-0.223607, + 0.187593,-0.57735,-0.794655,0,0,-0.5, + 0.187593,-0.57735,-0.794655,0.361804,-0.262865,-0.223607, + 0.187593,-0.57735,-0.794655,-0.138196,-0.425326,-0.223607, + -0.491123,0.356822,-0.794655,-0.138196,0.425326,-0.223607, + -0.491123,0.356822,-0.794655,0,0,-0.5, + -0.491123,0.356822,-0.794655,-0.447213,0,-0.223607, + -0.491123,-0.356822,-0.794655,-0.447213,0,-0.223607, + -0.491123,-0.356822,-0.794655,0,0,-0.5, + -0.491123,-0.356822,-0.794655,-0.138196,-0.425326,-0.223607, + 0,0,1,0.223607,0.16246,0.361804, + 0,0,1,-0.08541,0.262865,0.361804, + 0,0,1,-0.276393,0,0.361804, + 0,0,1,0.223607,0.16246,0.361804, + 0,0,1,-0.276393,0,0.361804, + 0,0,1,-0.08541,-0.262865,0.361804, + 0,0,1,0.223607,0.16246,0.361804, + 0,0,1,-0.08541,-0.262865,0.361804, + 0,0,1,0.223607,-0.16246,0.361804, + 0.894427,0,0.447214,0.361804,-0.262865,0.08541, + 0.894427,0,0.447214,0.447213,0,-0.08541, + 0.894427,0,0.447214,0.361804,0.262865,0.08541, + 0.894428,0,0.447213,0.361804,-0.262865,0.08541, + 0.894428,0,0.447213,0.361804,0.262865,0.08541, + 0.894428,0,0.447213,0.223607,0.16246,0.361804, + 0.894428,0,0.447213,0.361804,-0.262865,0.08541, + 0.894428,0,0.447213,0.223607,0.16246,0.361804, + 0.894428,0,0.447213,0.223607,-0.16246,0.361804, + 0.276393,0.85065,0.447214,0.361804,0.262865,0.08541, + 0.276393,0.85065,0.447214,0.138196,0.425326,-0.08541, + 0.276393,0.85065,0.447214,-0.138196,0.425326,0.08541, + 0.276393,0.850651,0.447213,0.361804,0.262865,0.08541, + 0.276393,0.850651,0.447213,-0.138196,0.425326,0.08541, + 0.276393,0.850651,0.447213,-0.08541,0.262865,0.361804, + 0.276393,0.850652,0.447212,0.361804,0.262865,0.08541, + 0.276393,0.850652,0.447212,-0.08541,0.262865,0.361804, + 0.276393,0.850652,0.447212,0.223607,0.16246,0.361804, + -0.723606,0.525731,0.447215,-0.138196,0.425326,0.08541, + -0.723606,0.525731,0.447215,-0.361804,0.262865,-0.08541, + -0.723606,0.525731,0.447215,-0.447213,0,0.08541, + -0.723607,0.525731,0.447213,-0.138196,0.425326,0.08541, + -0.723607,0.525731,0.447213,-0.447213,0,0.08541, + -0.723607,0.525731,0.447213,-0.276393,0,0.361804, + -0.723607,0.525731,0.447214,-0.138196,0.425326,0.08541, + -0.723607,0.525731,0.447214,-0.276393,0,0.361804, + -0.723607,0.525731,0.447214,-0.08541,0.262865,0.361804, + -0.723606,-0.525731,0.447215,-0.447213,0,0.08541, + -0.723606,-0.525731,0.447215,-0.361804,-0.262865,-0.08541, + -0.723606,-0.525731,0.447215,-0.138196,-0.425326,0.08541, + -0.723607,-0.525731,0.447214,-0.447213,0,0.08541, + -0.723607,-0.525731,0.447214,-0.138196,-0.425326,0.08541, + -0.723607,-0.525731,0.447214,-0.08541,-0.262865,0.361804, + -0.723607,-0.525731,0.447213,-0.447213,0,0.08541, + -0.723607,-0.525731,0.447213,-0.08541,-0.262865,0.361804, + -0.723607,-0.525731,0.447213,-0.276393,0,0.361804, + 0.276393,-0.85065,0.447214,-0.138196,-0.425326,0.08541, + 0.276393,-0.85065,0.447214,0.138196,-0.425326,-0.08541, + 0.276393,-0.85065,0.447214,0.361804,-0.262865,0.08541, + 0.276394,-0.850651,0.447213,-0.138196,-0.425326,0.08541, + 0.276394,-0.850651,0.447213,0.361804,-0.262865,0.08541, + 0.276394,-0.850651,0.447213,0.223607,-0.16246,0.361804, + 0.276393,-0.850651,0.447214,-0.138196,-0.425326,0.08541, + 0.276393,-0.850651,0.447214,0.223607,-0.16246,0.361804, + 0.276393,-0.850651,0.447214,-0.08541,-0.262865,0.361804, + 0.723607,0.525731,-0.447213,0.447213,0,-0.08541, + 0.723607,0.525731,-0.447213,0.276393,0,-0.361804, + 0.723607,0.525731,-0.447213,0.08541,0.262865,-0.361804, + 0.723607,0.525731,-0.447214,0.447213,0,-0.08541, + 0.723607,0.525731,-0.447214,0.08541,0.262865,-0.361804, + 0.723607,0.525731,-0.447214,0.138196,0.425326,-0.08541, + 0.723606,0.525731,-0.447215,0.447213,0,-0.08541, + 0.723606,0.525731,-0.447215,0.138196,0.425326,-0.08541, + 0.723606,0.525731,-0.447215,0.361804,0.262865,0.08541, + 0.723606,-0.525732,-0.447214,0.361804,-0.262865,0.08541, + 0.723606,-0.525732,-0.447214,0.138196,-0.425326,-0.08541, + 0.723606,-0.525732,-0.447214,0.08541,-0.262865,-0.361804, + 0.723607,-0.525731,-0.447214,0.361804,-0.262865,0.08541, + 0.723607,-0.525731,-0.447214,0.08541,-0.262865,-0.361804, + 0.723607,-0.525731,-0.447214,0.276393,0,-0.361804, + 0.723607,-0.52573,-0.447214,0.361804,-0.262865,0.08541, + 0.723607,-0.52573,-0.447214,0.276393,0,-0.361804, + 0.723607,-0.52573,-0.447214,0.447213,0,-0.08541, + -0.276393,0.850651,-0.447214,0.138196,0.425326,-0.08541, + -0.276393,0.850651,-0.447214,0.08541,0.262865,-0.361804, + -0.276393,0.850651,-0.447214,-0.223607,0.16246,-0.361804, + -0.276394,0.850651,-0.447213,0.138196,0.425326,-0.08541, + -0.276394,0.850651,-0.447213,-0.223607,0.16246,-0.361804, + -0.276394,0.850651,-0.447213,-0.361804,0.262865,-0.08541, + -0.276393,0.85065,-0.447214,0.138196,0.425326,-0.08541, + -0.276393,0.85065,-0.447214,-0.361804,0.262865,-0.08541, + -0.276393,0.85065,-0.447214,-0.138196,0.425326,0.08541, + -0.894428,0,-0.447213,-0.361804,0.262865,-0.08541, + -0.894428,0,-0.447213,-0.223607,0.16246,-0.361804, + -0.894428,0,-0.447213,-0.223607,-0.16246,-0.361804, + -0.894428,0,-0.447213,-0.361804,0.262865,-0.08541, + -0.894428,0,-0.447213,-0.223607,-0.16246,-0.361804, + -0.894428,0,-0.447213,-0.361804,-0.262865,-0.08541, + -0.894427,0,-0.447214,-0.361804,0.262865,-0.08541, + -0.894427,0,-0.447214,-0.361804,-0.262865,-0.08541, + -0.894427,0,-0.447214,-0.447213,0,0.08541, + -0.276393,-0.850652,-0.447212,-0.361804,-0.262865,-0.08541, + -0.276393,-0.850652,-0.447212,-0.223607,-0.16246,-0.361804, + -0.276393,-0.850652,-0.447212,0.08541,-0.262865,-0.361804, + -0.276393,-0.850651,-0.447213,-0.361804,-0.262865,-0.08541, + -0.276393,-0.850651,-0.447213,0.08541,-0.262865,-0.361804, + -0.276393,-0.850651,-0.447213,0.138196,-0.425326,-0.08541, + -0.276393,-0.85065,-0.447214,-0.361804,-0.262865,-0.08541, + -0.276393,-0.85065,-0.447214,0.138196,-0.425326,-0.08541, + -0.276393,-0.85065,-0.447214,-0.138196,-0.425326,0.08541, + 0,0,-1,0.08541,-0.262865,-0.361804, + 0,0,-1,-0.223607,-0.16246,-0.361804, + 0,0,-1,-0.223607,0.16246,-0.361804, + 0,0,-1,0.08541,-0.262865,-0.361804, + 0,0,-1,-0.223607,0.16246,-0.361804, + 0,0,-1,0.08541,0.262865,-0.361804, + 0,0,-1,0.08541,-0.262865,-0.361804, + 0,0,-1,0.08541,0.262865,-0.361804, + 0,0,-1,0.276393,0,-0.361804 +}; +static const struct gllist frame={GL_N3F_V3F,GL_TRIANGLES,168,data,NULL}; +const struct gllist *tronbit_idle2=&frame; diff --git a/hacks/glx/tronbit_no.c b/hacks/glx/tronbit_no.c new file mode 100644 index 00000000..305790dc --- /dev/null +++ b/hacks/glx/tronbit_no.c @@ -0,0 +1,1087 @@ +/* no = second stellation of icosahedron */ + +#include "gllist.h" +static const float data[]={ + -0.491121,-0.356821,-0.794656,-0.072949,0.100406,-0.118034, + -0.491121,-0.356821,-0.794656,-0.11459,0.117557,-0.1, + -0.491121,-0.356821,-0.794656,-0.138196,0.425325,-0.223606, + -0.491129,-0.356821,-0.794652,-0.038197,0.117557,-0.147214, + -0.491129,-0.356821,-0.794652,-0.072949,0.100406,-0.118034, + -0.491129,-0.356821,-0.794652,-0.138196,0.425325,-0.223606, + -0.491121,-0.356826,-0.794654,-0.138196,-0.100406,0.012461, + -0.491121,-0.356826,-0.794654,-0.123606,-0.145308,0.023607, + -0.491121,-0.356826,-0.794654,-0.361803,-0.262865,0.223606, + -0.491119,-0.356829,-0.794654,-0.176394,-0.072654,0.023607, + -0.491119,-0.356829,-0.794654,-0.138196,-0.100406,0.012461, + -0.491119,-0.356829,-0.794654,-0.361803,-0.262865,0.223606, + -0.491125,-0.356827,-0.794651,0.072949,-0.100406,-0.118034, + -0.491125,-0.356827,-0.794651,0.1,-0.072654,-0.147214, + -0.491125,-0.356827,-0.794651,0.361803,-0.262865,-0.223606, + -0.491124,-0.356824,-0.794654,0.076393,-0.145308,-0.1, + -0.491124,-0.356824,-0.794654,0.072949,-0.100406,-0.118034, + -0.491124,-0.356824,-0.794654,0.361803,-0.262865,-0.223606, + -0.491124,-0.356822,-0.794654,-0.150658,0.062054,-0.052786, + -0.491124,-0.356822,-0.794654,-0.18541,0.044903,-0.023607, + -0.491124,-0.356822,-0.794654,-0.223606,0.162459,-0.052786, + -0.491128,-0.356819,-0.794653,-0.052786,-0.162459,-0.012461, + -0.491128,-0.356819,-0.794653,-0.01459,-0.190211,-0.023607, + -0.491128,-0.356819,-0.794653,-0.08541,-0.262865,0.052786, + -0.491122,-0.356835,-0.79465,0.065247,0,-0.158359, + -0.491122,-0.356835,-0.79465,0.061803,0.044903,-0.176394, + -0.491122,-0.356835,-0.79465,0.17082,0,-0.223606, + -0.491135,-0.356817,-0.79465,0.061803,0.044903,-0.176394, + -0.491135,-0.356817,-0.79465,0.020163,0.062054,-0.158359, + -0.491135,-0.356817,-0.79465,0.052786,0.162459,-0.223606, + -0.491124,-0.356824,-0.794654,-0.18541,0.044903,-0.023607, + -0.491124,-0.356824,-0.794654,-0.17082,0,-0.012461, + -0.491124,-0.356824,-0.794654,-0.276393,0,0.052786, + -0.49112,-0.35682,-0.794658,-0.01459,-0.190211,-0.023607, + -0.49112,-0.35682,-0.794658,0.012461,-0.162459,-0.052786, + -0.49112,-0.35682,-0.794658,0.08541,-0.262865,-0.052786, + -0.491124,-0.35682,-0.794655,-0.11459,0.117557,-0.1, + -0.491124,-0.35682,-0.794655,-0.111804,0.08123,-0.08541, + -0.491124,-0.35682,-0.794655,-0.223606,0.162459,-0.052786, + -0.491133,-0.356822,-0.794648,-0.123606,-0.145308,0.023607, + -0.491133,-0.356822,-0.794648,-0.095491,-0.131433,0, + -0.491133,-0.356822,-0.794648,-0.08541,-0.262865,0.052786, + -0.491129,-0.356813,-0.794655,0.1,-0.072654,-0.147214, + -0.491129,-0.356813,-0.794655,0.069098,-0.050203,-0.138196, + -0.491129,-0.356813,-0.794655,0.17082,0,-0.223606, + -0.491117,-0.35683,-0.794655,-0.026393,0.08123,-0.138196, + -0.491117,-0.35683,-0.794655,-0.038197,0.117557,-0.147214, + -0.491117,-0.35683,-0.794655,0.052786,0.162459,-0.223606, + -0.491122,-0.356812,-0.79466,-0.154508,-0.050203,0, + -0.491122,-0.356812,-0.79466,-0.176394,-0.072654,0.023607, + -0.491122,-0.356812,-0.79466,-0.276393,0,0.052786, + -0.491117,-0.356823,-0.794658,0.042705,-0.131433,-0.08541, + -0.491117,-0.356823,-0.794658,0.076393,-0.145308,-0.1, + -0.491117,-0.356823,-0.794658,0.08541,-0.262865,-0.052786, + -0.607065,0.000003,0.794652,0,0.124108,0.118034, + -0.607065,0.000003,0.794652,0.038197,0.117557,0.147214, + -0.607065,0.000003,0.794652,0.138196,0.425325,0.223606, + -0.607062,0,0.794655,-0.023607,0.162459,0.1, + -0.607062,0,0.794655,0,0.124108,0.118034, + -0.607062,0,0.794655,0.138196,0.425325,0.223606, + -0.607062,0,0.794655,0,-0.124108,0.118034, + -0.607062,0,0.794655,-0.023607,-0.162459,0.1, + -0.607062,0,0.794655,0.138196,-0.425325,0.223606, + -0.607065,-0.000003,0.794652,0.038197,-0.117557,0.147214, + -0.607065,-0.000003,0.794652,0,-0.124108,0.118034, + -0.607065,-0.000003,0.794652,0.138196,-0.425325,0.223606, + -0.607062,-0.000002,0.794654,-0.17082,0,-0.012461, + -0.607062,-0.000002,0.794654,-0.18541,0.044903,-0.023607, + -0.607062,-0.000002,0.794654,-0.447213,0,-0.223606, + -0.607062,0.000002,0.794654,-0.18541,-0.044903,-0.023607, + -0.607062,0.000002,0.794654,-0.17082,0,-0.012461, + -0.607062,0.000002,0.794654,-0.447213,0,-0.223606, + -0.607069,0.000012,0.794649,0.052786,0.038352,0.158359, + -0.607069,0.000012,0.794649,0.076393,0,0.176394, + -0.607069,0.000012,0.794649,0.138196,0.100406,0.223606, + -0.607066,0,0.794652,-0.08541,-0.138758,0.052786, + -0.607066,0,0.794652,-0.123606,-0.145308,0.023607, + -0.607066,0,0.794652,-0.08541,-0.262865,0.052786, + -0.607061,0.000001,0.794655,-0.138196,0.100406,0.012461, + -0.607061,0.000001,0.794655,-0.123606,0.145308,0.023607, + -0.607061,0.000001,0.794655,-0.223606,0.162459,-0.052786, + -0.607066,0,0.794652,-0.123606,0.145308,0.023607, + -0.607066,0,0.794652,-0.08541,0.138758,0.052786, + -0.607066,0,0.794652,-0.08541,0.262865,0.052786, + -0.607069,-0.000012,0.794649,0.076393,0,0.176394, + -0.607069,-0.000012,0.794649,0.052786,-0.038352,0.158359, + -0.607069,-0.000012,0.794649,0.138196,-0.100406,0.223606, + -0.607061,-0.000001,0.794655,-0.123606,-0.145308,0.023607, + -0.607061,-0.000001,0.794655,-0.138196,-0.100406,0.012461, + -0.607061,-0.000001,0.794655,-0.223606,-0.162459,-0.052786, + -0.607061,-0.00001,0.794655,0.038197,0.117557,0.147214, + -0.607061,-0.00001,0.794655,0.026393,0.08123,0.138196, + -0.607061,-0.00001,0.794655,0.138196,0.100406,0.223606, + -0.607061,0,0.794655,-0.023607,-0.162459,0.1, + -0.607061,0,0.794655,-0.042705,-0.131433,0.08541, + -0.607061,0,0.794655,-0.08541,-0.262865,0.052786, + -0.60706,0.000002,0.794656,-0.18541,0.044903,-0.023607, + -0.60706,0.000002,0.794656,-0.154508,0.050203,0, + -0.60706,0.000002,0.794656,-0.223606,0.162459,-0.052786, + -0.607061,0,0.794655,-0.042705,0.131433,0.08541, + -0.607061,0,0.794655,-0.023607,0.162459,0.1, + -0.607061,0,0.794655,-0.08541,0.262865,0.052786, + -0.607061,0.00001,0.794655,0.026393,-0.08123,0.138196, + -0.607061,0.00001,0.794655,0.038197,-0.117557,0.147214, + -0.607061,0.00001,0.794655,0.138196,-0.100406,0.223606, + -0.60706,-0.000002,0.794656,-0.154508,-0.050203,0, + -0.60706,-0.000002,0.794656,-0.18541,-0.044903,-0.023607, + -0.60706,-0.000002,0.794656,-0.223606,-0.162459,-0.052786, + 0.303526,0.934174,-0.187592,0.020163,0.062054,-0.158359, + 0.303526,0.934174,-0.187592,0.061803,0.044903,-0.176394, + 0.303526,0.934174,-0.187592,0,0,-0.5, + 0.303535,0.934171,-0.187592,-0.023607,0.072654,-0.176394, + 0.303535,0.934171,-0.187592,0.020163,0.062054,-0.158359, + 0.303535,0.934171,-0.187592,0,0,-0.5, + 0.303532,0.934172,-0.187594,0.150658,0.062054,0.052786, + 0.303532,0.934172,-0.187594,0.147214,0.072654,0.1, + 0.303532,0.934172,-0.187594,0.447213,0,0.223606, + 0.303531,0.934173,-0.187591,0.18541,0.044903,0.023607, + 0.303531,0.934173,-0.187591,0.150658,0.062054,0.052786, + 0.303531,0.934173,-0.187591,0.447213,0,0.223606, + 0.303523,0.934173,-0.187603,-0.08541,0.138758,0.052786, + 0.303523,0.934173,-0.187603,-0.123606,0.145308,0.023607, + 0.303523,0.934173,-0.187603,-0.361803,0.262865,0.223606, + 0.303538,0.934173,-0.187579,-0.076393,0.145308,0.1, + 0.303538,0.934173,-0.187579,-0.08541,0.138758,0.052786, + 0.303538,0.934173,-0.187579,-0.361803,0.262865,0.223606, + 0.303529,0.934173,-0.187594,0.118034,0.038352,-0.118034, + 0.303529,0.934173,-0.187594,0.161804,0.027751,-0.1, + 0.303529,0.934173,-0.187594,0.17082,0,-0.223606, + 0.30353,0.934173,-0.187591,0.072949,0.100406,0.118034, + 0.30353,0.934173,-0.187591,0.038197,0.117557,0.147214, + 0.30353,0.934173,-0.187591,0.138196,0.100406,0.223606, + 0.303526,0.934172,-0.187599,-0.105573,0.124108,-0.052786, + 0.303526,0.934172,-0.187599,-0.11459,0.117557,-0.1, + 0.303526,0.934172,-0.187599,-0.223606,0.162459,-0.052786, + 0.30353,0.934173,-0.187591,-0.11459,0.117557,-0.1, + 0.30353,0.934173,-0.187591,-0.072949,0.100406,-0.118034, + 0.30353,0.934173,-0.187591,-0.138196,0.100406,-0.223606, + 0.303531,0.934173,-0.187588,0.161804,0.027751,-0.1, + 0.303531,0.934173,-0.187588,0.158359,0.038352,-0.052786, + 0.303531,0.934173,-0.187588,0.276393,0,-0.052786, + 0.303534,0.934173,-0.187586,0.038197,0.117557,0.147214, + 0.303534,0.934173,-0.187586,0,0.124108,0.118034, + 0.303534,0.934173,-0.187586,-0.052786,0.162459,0.223606, + 0.303535,0.934172,-0.187588,0.061803,0.044903,-0.176394, + 0.303535,0.934172,-0.187588,0.069098,0.050203,-0.138196, + 0.303535,0.934172,-0.187588,0.17082,0,-0.223606, + 0.303531,0.934173,-0.187592,0.147214,0.072654,0.1, + 0.303531,0.934173,-0.187592,0.111804,0.08123,0.08541, + 0.303531,0.934173,-0.187592,0.138196,0.100406,0.223606, + 0.303524,0.934177,-0.187583,-0.123606,0.145308,0.023607, + 0.303524,0.934177,-0.187583,-0.095491,0.131433,0, + 0.303524,0.934177,-0.187583,-0.223606,0.162459,-0.052786, + 0.303529,0.934174,-0.187588,-0.026393,0.08123,-0.138196, + 0.303529,0.934174,-0.187588,-0.023607,0.072654,-0.176394, + 0.303529,0.934174,-0.187588,-0.138196,0.100406,-0.223606, + 0.30353,0.934172,-0.187595,0.154508,0.050203,0, + 0.30353,0.934172,-0.187595,0.18541,0.044903,0.023607, + 0.30353,0.934172,-0.187595,0.276393,0,-0.052786, + 0.303516,0.934178,-0.18759,-0.042705,0.131433,0.08541, + 0.303516,0.934178,-0.18759,-0.076393,0.145308,0.1, + 0.303516,0.934178,-0.18759,-0.052786,0.162459,0.223606, + 0.794658,-0.577347,0.187587,0.012461,-0.162459,-0.052786, + 0.794658,-0.577347,0.187587,-0.01459,-0.190211,-0.023607, + 0.794658,-0.577347,0.187587,-0.138196,-0.425325,-0.223606, + 0.794655,-0.577349,0.187593,0.023607,-0.162459,-0.1, + 0.794655,-0.577349,0.187593,0.012461,-0.162459,-0.052786, + 0.794655,-0.577349,0.187593,-0.138196,-0.425325,-0.223606, + 0.794653,-0.577353,0.187592,0.052786,-0.038352,0.158359, + 0.794653,-0.577353,0.187592,0.076393,0,0.176394, + 0.794653,-0.577353,0.187592,0,0,0.5, + 0.794657,-0.577347,0.187592,0.023607,-0.072654,0.176394, + 0.794657,-0.577347,0.187592,0.052786,-0.038352,0.158359, + 0.794657,-0.577347,0.187592,0,0,0.5, + 0.794656,-0.577344,0.187604,0.158359,0.038352,-0.052786, + 0.794656,-0.577344,0.187604,0.161804,0.027751,-0.1, + 0.794656,-0.577344,0.187604,0.361803,0.262865,-0.223606, + 0.794652,-0.577358,0.18758,0.176394,0.072654,-0.023607, + 0.794652,-0.577358,0.18758,0.158359,0.038352,-0.052786, + 0.794652,-0.577358,0.18758,0.361803,0.262865,-0.223606, + 0.794654,-0.57735,0.187593,-0.012461,-0.162459,0.052786, + 0.794654,-0.57735,0.187593,-0.023607,-0.162459,0.1, + 0.794654,-0.57735,0.187593,-0.08541,-0.262865,0.052786, + 0.794652,-0.577353,0.187596,0.118034,0.038352,0.118034, + 0.794652,-0.577353,0.187596,0.147214,0.072654,0.1, + 0.794652,-0.577353,0.187596,0.138196,0.100406,0.223606, + 0.794654,-0.577351,0.187592,0.118034,-0.038352,-0.118034, + 0.794654,-0.577351,0.187592,0.1,-0.072654,-0.147214, + 0.794654,-0.577351,0.187592,0.17082,0,-0.223606, + 0.794655,-0.57735,0.18759,0.1,-0.072654,-0.147214, + 0.794655,-0.57735,0.18759,0.072949,-0.100406,-0.118034, + 0.794655,-0.57735,0.18759,0.052786,-0.162459,-0.223606, + 0.79465,-0.577356,0.187592,-0.023607,-0.162459,0.1, + 0.79465,-0.577356,0.187592,0,-0.124108,0.118034, + 0.79465,-0.577356,0.187592,-0.052786,-0.162459,0.223606, + 0.794655,-0.577351,0.187588,0.147214,0.072654,0.1, + 0.794655,-0.577351,0.187588,0.150658,0.062054,0.052786, + 0.794655,-0.577351,0.187588,0.223606,0.162459,0.052786, + 0.794655,-0.577346,0.187602,-0.01459,-0.190211,-0.023607, + 0.794655,-0.577346,0.187602,0,-0.162459,0, + 0.794655,-0.577346,0.187602,-0.08541,-0.262865,0.052786, + 0.794657,-0.577348,0.18759,0.076393,0,0.176394, + 0.794657,-0.577348,0.18759,0.08541,0,0.138196, + 0.794657,-0.577348,0.18759,0.138196,0.100406,0.223606, + 0.794646,-0.577362,0.187591,0.161804,0.027751,-0.1, + 0.794646,-0.577362,0.187591,0.138196,0,-0.08541, + 0.794646,-0.577362,0.187591,0.17082,0,-0.223606, + 0.794649,-0.577358,0.187592,0.042705,-0.131433,-0.08541, + 0.794649,-0.577358,0.187592,0.023607,-0.162459,-0.1, + 0.794649,-0.577358,0.187592,0.052786,-0.162459,-0.223606, + 0.794652,-0.577354,0.18759,0.026393,-0.08123,0.138196, + 0.794652,-0.577354,0.18759,0.023607,-0.072654,0.176394, + 0.794652,-0.577354,0.18759,-0.052786,-0.162459,0.223606, + 0.794648,-0.577354,0.187607,0.154508,0.050203,0, + 0.794648,-0.577354,0.187607,0.176394,0.072654,-0.023607, + 0.794648,-0.577354,0.187607,0.223606,0.162459,0.052786, + -0.187591,0.577356,0.794651,0.118034,0.038352,0.118034, + -0.187591,0.577356,0.794651,0.123606,0,0.147214, + -0.187591,0.577356,0.794651,0.447213,0,0.223606, + -0.187592,0.577351,0.794654,0.147214,0.072654,0.1, + -0.187592,0.577351,0.794654,0.118034,0.038352,0.118034, + -0.187592,0.577351,0.794654,0.447213,0,0.223606, + -0.187591,0.577349,0.794656,-0.118034,-0.038352,0.118034, + -0.187591,0.577349,0.794656,-0.161804,-0.027751,0.1, + -0.187591,0.577349,0.794656,-0.361803,-0.262865,0.223606, + -0.187596,0.577353,0.794652,-0.1,-0.072654,0.147214, + -0.187596,0.577353,0.794652,-0.118034,-0.038352,0.118034, + -0.187596,0.577353,0.794652,-0.361803,-0.262865,0.223606, + -0.1876,0.577347,0.794655,-0.052786,0.162459,-0.012461, + -0.1876,0.577347,0.794655,-0.01459,0.190211,-0.023607, + -0.1876,0.577347,0.794655,-0.138196,0.425325,-0.223606, + -0.187593,0.577349,0.794655,-0.1,0.162459,-0.023607, + -0.187593,0.577349,0.794655,-0.052786,0.162459,-0.012461, + -0.187593,0.577349,0.794655,-0.138196,0.425325,-0.223606, + -0.187583,0.57736,0.79465,0.052786,-0.038352,0.158359, + -0.187583,0.57736,0.79465,0.023607,-0.072654,0.176394, + -0.187583,0.57736,0.79465,0.138196,-0.100406,0.223606, + -0.187592,0.577347,0.794657,-0.158359,0.038352,0.052786, + -0.187592,0.577347,0.794657,-0.176394,0.072654,0.023607, + -0.187592,0.577347,0.794657,-0.276393,0,0.052786, + -0.187593,0.57735,0.794654,0.052786,0.162459,0.012461, + -0.187593,0.57735,0.794654,0.1,0.162459,0.023607, + -0.187593,0.57735,0.794654,0.08541,0.262865,-0.052786, + -0.187592,0.577357,0.79465,0.1,0.162459,0.023607, + -0.187592,0.577357,0.79465,0.105573,0.124108,0.052786, + -0.187592,0.577357,0.79465,0.223606,0.162459,0.052786, + -0.187605,0.577354,0.794649,0.023607,-0.072654,0.176394, + -0.187605,0.577354,0.794649,-0.020163,-0.062054,0.158359, + -0.187605,0.577354,0.794649,-0.052786,-0.162459,0.223606, + -0.187591,0.577354,0.794652,-0.176394,0.072654,0.023607, + -0.187591,0.577354,0.794652,-0.138196,0.100406,0.012461, + -0.187591,0.577354,0.794652,-0.223606,0.162459,-0.052786, + -0.187604,0.577345,0.794656,0.123606,0,0.147214, + -0.187604,0.577345,0.794656,0.08541,0,0.138196, + -0.187604,0.577345,0.794656,0.138196,-0.100406,0.223606, + -0.187593,0.577352,0.794653,-0.161804,-0.027751,0.1, + -0.187593,0.577352,0.794653,-0.138196,0,0.08541, + -0.187593,0.577352,0.794653,-0.276393,0,0.052786, + -0.187583,0.577345,0.79466,-0.01459,0.190211,-0.023607, + -0.187583,0.577345,0.79466,0,0.162459,0, + -0.187583,0.577345,0.79466,0.08541,0.262865,-0.052786, + -0.187592,0.577351,0.794654,0.111804,0.08123,0.08541, + -0.187592,0.577351,0.794654,0.147214,0.072654,0.1, + -0.187592,0.577351,0.794654,0.223606,0.162459,0.052786, + -0.187584,0.577353,0.794655,-0.069098,-0.050203,0.138196, + -0.187584,0.577353,0.794655,-0.1,-0.072654,0.147214, + -0.187584,0.577353,0.794655,-0.052786,-0.162459,0.223606, + -0.187591,0.577359,0.794648,-0.095491,0.131433,0, + -0.187591,0.577359,0.794648,-0.1,0.162459,-0.023607, + -0.187591,0.577359,0.794648,-0.223606,0.162459,-0.052786, + -0.491124,0.356824,-0.794654,0.072949,0.100406,-0.118034, + -0.491124,0.356824,-0.794654,0.076393,0.145308,-0.1, + -0.491124,0.356824,-0.794654,0.361803,0.262865,-0.223606, + -0.491125,0.356827,-0.794651,0.1,0.072654,-0.147214, + -0.491125,0.356827,-0.794651,0.072949,0.100406,-0.118034, + -0.491125,0.356827,-0.794651,0.361803,0.262865,-0.223606, + -0.491119,0.356829,-0.794654,-0.138196,0.100406,0.012461, + -0.491119,0.356829,-0.794654,-0.176394,0.072654,0.023607, + -0.491119,0.356829,-0.794654,-0.361803,0.262865,0.223606, + -0.491121,0.356826,-0.794654,-0.123606,0.145308,0.023607, + -0.491121,0.356826,-0.794654,-0.138196,0.100406,0.012461, + -0.491121,0.356826,-0.794654,-0.361803,0.262865,0.223606, + -0.491129,0.356821,-0.794652,-0.072949,-0.100406,-0.118034, + -0.491129,0.356821,-0.794652,-0.038197,-0.117557,-0.147214, + -0.491129,0.356821,-0.794652,-0.138196,-0.425325,-0.223606, + -0.491121,0.356821,-0.794656,-0.11459,-0.117557,-0.1, + -0.491121,0.356821,-0.794656,-0.072949,-0.100406,-0.118034, + -0.491121,0.356821,-0.794656,-0.138196,-0.425325,-0.223606, + -0.49112,0.35682,-0.794658,0.012461,0.162459,-0.052786, + -0.49112,0.35682,-0.794658,-0.01459,0.190211,-0.023607, + -0.49112,0.35682,-0.794658,0.08541,0.262865,-0.052786, + -0.491124,0.356824,-0.794654,-0.17082,0,-0.012461, + -0.491124,0.356824,-0.794654,-0.18541,-0.044903,-0.023607, + -0.491124,0.356824,-0.794654,-0.276393,0,0.052786, + -0.491135,0.356817,-0.79465,0.020163,-0.062054,-0.158359, + -0.491135,0.356817,-0.79465,0.061803,-0.044903,-0.176394, + -0.491135,0.356817,-0.79465,0.052786,-0.162459,-0.223606, + -0.491122,0.356835,-0.79465,0.061803,-0.044903,-0.176394, + -0.491122,0.356835,-0.79465,0.065247,0,-0.158359, + -0.491122,0.356835,-0.79465,0.17082,0,-0.223606, + -0.491128,0.356819,-0.794653,-0.01459,0.190211,-0.023607, + -0.491128,0.356819,-0.794653,-0.052786,0.162459,-0.012461, + -0.491128,0.356819,-0.794653,-0.08541,0.262865,0.052786, + -0.491124,0.356822,-0.794654,-0.18541,-0.044903,-0.023607, + -0.491124,0.356822,-0.794654,-0.150658,-0.062054,-0.052786, + -0.491124,0.356822,-0.794654,-0.223606,-0.162459,-0.052786, + -0.491117,0.356823,-0.794658,0.076393,0.145308,-0.1, + -0.491117,0.356823,-0.794658,0.042705,0.131433,-0.08541, + -0.491117,0.356823,-0.794658,0.08541,0.262865,-0.052786, + -0.491122,0.356812,-0.79466,-0.176394,0.072654,0.023607, + -0.491122,0.356812,-0.79466,-0.154508,0.050203,0, + -0.491122,0.356812,-0.79466,-0.276393,0,0.052786, + -0.491117,0.35683,-0.794655,-0.038197,-0.117557,-0.147214, + -0.491117,0.35683,-0.794655,-0.026393,-0.08123,-0.138196, + -0.491117,0.35683,-0.794655,0.052786,-0.162459,-0.223606, + -0.491129,0.356813,-0.794655,0.069098,0.050203,-0.138196, + -0.491129,0.356813,-0.794655,0.1,0.072654,-0.147214, + -0.491129,0.356813,-0.794655,0.17082,0,-0.223606, + -0.491133,0.356822,-0.794648,-0.095491,0.131433,0, + -0.491133,0.356822,-0.794648,-0.123606,0.145308,0.023607, + -0.491133,0.356822,-0.794648,-0.08541,0.262865,0.052786, + -0.491124,0.35682,-0.794655,-0.111804,-0.08123,-0.08541, + -0.491124,0.35682,-0.794655,-0.11459,-0.117557,-0.1, + -0.491124,0.35682,-0.794655,-0.223606,-0.162459,-0.052786, + 0.982247,0.000005,-0.187592,0.065247,0,-0.158359, + 0.982247,0.000005,-0.187592,0.061803,-0.044903,-0.176394, + 0.982247,0.000005,-0.187592,0,0,-0.5, + 0.982247,-0.000005,-0.187592,0.061803,0.044903,-0.176394, + 0.982247,-0.000005,-0.187592,0.065247,0,-0.158359, + 0.982247,-0.000005,-0.187592,0,0,-0.5, + 0.982245,-0.000005,-0.187601,0.105573,-0.124108,0.052786, + 0.982245,-0.000005,-0.187601,0.11459,-0.117557,0.1, + 0.982245,-0.000005,-0.187601,0.138196,-0.425325,0.223606, + 0.982248,0.000002,-0.187589,0.1,-0.162459,0.023607, + 0.982248,0.000002,-0.187589,0.105573,-0.124108,0.052786, + 0.982248,0.000002,-0.187589,0.138196,-0.425325,0.223606, + 0.982248,-0.000002,-0.187589,0.105573,0.124108,0.052786, + 0.982248,-0.000002,-0.187589,0.1,0.162459,0.023607, + 0.982248,-0.000002,-0.187589,0.138196,0.425325,0.223606, + 0.982245,0.000005,-0.187601,0.11459,0.117557,0.1, + 0.982245,0.000005,-0.187601,0.105573,0.124108,0.052786, + 0.982245,0.000005,-0.187601,0.138196,0.425325,0.223606, + 0.982247,-0.000001,-0.187593,0.072949,-0.100406,-0.118034, + 0.982247,-0.000001,-0.187593,0.076393,-0.145308,-0.1, + 0.982247,-0.000001,-0.187593,0.052786,-0.162459,-0.223606, + 0.982248,0.000006,-0.187588,0.118034,-0.038352,0.118034, + 0.982248,0.000006,-0.187588,0.123606,0,0.147214, + 0.982248,0.000006,-0.187588,0.138196,-0.100406,0.223606, + 0.982247,0,-0.187593,0.08541,0.138758,-0.052786, + 0.982247,0,-0.187593,0.076393,0.145308,-0.1, + 0.982247,0,-0.187593,0.08541,0.262865,-0.052786, + 0.982247,0.000001,-0.187593,0.076393,0.145308,-0.1, + 0.982247,0.000001,-0.187593,0.072949,0.100406,-0.118034, + 0.982247,0.000001,-0.187593,0.052786,0.162459,-0.223606, + 0.982247,0,-0.187593,0.076393,-0.145308,-0.1, + 0.982247,0,-0.187593,0.08541,-0.138758,-0.052786, + 0.982247,0,-0.187593,0.08541,-0.262865,-0.052786, + 0.982248,-0.000006,-0.187588,0.123606,0,0.147214, + 0.982248,-0.000006,-0.187588,0.118034,0.038352,0.118034, + 0.982248,-0.000006,-0.187588,0.138196,0.100406,0.223606, + 0.982248,-0.000003,-0.187589,0.061803,-0.044903,-0.176394, + 0.982248,-0.000003,-0.187589,0.069098,-0.050203,-0.138196, + 0.982248,-0.000003,-0.187589,0.052786,-0.162459,-0.223606, + 0.982248,-0.000002,-0.187589,0.11459,-0.117557,0.1, + 0.982248,-0.000002,-0.187589,0.111804,-0.08123,0.08541, + 0.982248,-0.000002,-0.187589,0.138196,-0.100406,0.223606, + 0.982247,0.000001,-0.187591,0.1,0.162459,0.023607, + 0.982247,0.000001,-0.187591,0.095491,0.131433,0, + 0.982247,0.000001,-0.187591,0.08541,0.262865,-0.052786, + 0.982248,0.000003,-0.187589,0.069098,0.050203,-0.138196, + 0.982248,0.000003,-0.187589,0.061803,0.044903,-0.176394, + 0.982248,0.000003,-0.187589,0.052786,0.162459,-0.223606, + 0.982247,-0.000001,-0.187591,0.095491,-0.131433,0, + 0.982247,-0.000001,-0.187591,0.1,-0.162459,0.023607, + 0.982247,-0.000001,-0.187591,0.08541,-0.262865,-0.052786, + 0.982248,0.000002,-0.187589,0.111804,0.08123,0.08541, + 0.982248,0.000002,-0.187589,0.11459,0.117557,0.1, + 0.982248,0.000002,-0.187589,0.138196,0.100406,0.223606, + -0.303531,-0.934173,0.187591,-0.150658,-0.062054,-0.052786, + -0.303531,-0.934173,0.187591,-0.18541,-0.044903,-0.023607, + -0.303531,-0.934173,0.187591,-0.447213,0,-0.223606, + -0.303532,-0.934172,0.187594,-0.147214,-0.072654,-0.1, + -0.303532,-0.934172,0.187594,-0.150658,-0.062054,-0.052786, + -0.303532,-0.934172,0.187594,-0.447213,0,-0.223606, + -0.303535,-0.934171,0.187592,-0.020163,-0.062054,0.158359, + -0.303535,-0.934171,0.187592,0.023607,-0.072654,0.176394, + -0.303535,-0.934171,0.187592,0,0,0.5, + -0.303526,-0.934174,0.187592,-0.061803,-0.044903,0.176394, + -0.303526,-0.934174,0.187592,-0.020163,-0.062054,0.158359, + -0.303526,-0.934174,0.187592,0,0,0.5, + -0.303538,-0.934173,0.187579,0.08541,-0.138758,-0.052786, + -0.303538,-0.934173,0.187579,0.076393,-0.145308,-0.1, + -0.303538,-0.934173,0.187579,0.361803,-0.262865,-0.223606, + -0.303523,-0.934173,0.187603,0.123606,-0.145308,-0.023607, + -0.303523,-0.934173,0.187603,0.08541,-0.138758,-0.052786, + -0.303523,-0.934173,0.187603,0.361803,-0.262865,-0.223606, + -0.303531,-0.934173,0.187588,-0.158359,-0.038352,0.052786, + -0.303531,-0.934173,0.187588,-0.161804,-0.027751,0.1, + -0.303531,-0.934173,0.187588,-0.276393,0,0.052786, + -0.30353,-0.934173,0.187591,0.072949,-0.100406,0.118034, + -0.30353,-0.934173,0.187591,0.11459,-0.117557,0.1, + -0.30353,-0.934173,0.187591,0.138196,-0.100406,0.223606, + -0.303534,-0.934173,0.187586,0,-0.124108,-0.118034, + -0.303534,-0.934173,0.187586,-0.038197,-0.117557,-0.147214, + -0.303534,-0.934173,0.187586,0.052786,-0.162459,-0.223606, + -0.30353,-0.934173,0.187591,-0.038197,-0.117557,-0.147214, + -0.30353,-0.934173,0.187591,-0.072949,-0.100406,-0.118034, + -0.30353,-0.934173,0.187591,-0.138196,-0.100406,-0.223606, + -0.303529,-0.934173,0.187594,-0.161804,-0.027751,0.1, + -0.303529,-0.934173,0.187594,-0.118034,-0.038352,0.118034, + -0.303529,-0.934173,0.187594,-0.17082,0,0.223606, + -0.303526,-0.934172,0.187599,0.11459,-0.117557,0.1, + -0.303526,-0.934172,0.187599,0.105573,-0.124108,0.052786, + -0.303526,-0.934172,0.187599,0.223606,-0.162459,0.052786, + -0.30353,-0.934172,0.187595,-0.18541,-0.044903,-0.023607, + -0.30353,-0.934172,0.187595,-0.154508,-0.050203,0, + -0.30353,-0.934172,0.187595,-0.276393,0,0.052786, + -0.303529,-0.934174,0.187588,0.023607,-0.072654,0.176394, + -0.303529,-0.934174,0.187588,0.026393,-0.08123,0.138196, + -0.303529,-0.934174,0.187588,0.138196,-0.100406,0.223606, + -0.303516,-0.934178,0.18759,0.076393,-0.145308,-0.1, + -0.303516,-0.934178,0.18759,0.042705,-0.131433,-0.08541, + -0.303516,-0.934178,0.18759,0.052786,-0.162459,-0.223606, + -0.303531,-0.934173,0.187592,-0.111804,-0.08123,-0.08541, + -0.303531,-0.934173,0.187592,-0.147214,-0.072654,-0.1, + -0.303531,-0.934173,0.187592,-0.138196,-0.100406,-0.223606, + -0.303535,-0.934172,0.187588,-0.069098,-0.050203,0.138196, + -0.303535,-0.934172,0.187588,-0.061803,-0.044903,0.176394, + -0.303535,-0.934172,0.187588,-0.17082,0,0.223606, + -0.303524,-0.934177,0.187583,0.095491,-0.131433,0, + -0.303524,-0.934177,0.187583,0.123606,-0.145308,-0.023607, + -0.303524,-0.934177,0.187583,0.223606,-0.162459,0.052786, + 0.187592,-0.577351,-0.794654,-0.118034,-0.038352,-0.118034, + 0.187592,-0.577351,-0.794654,-0.147214,-0.072654,-0.1, + 0.187592,-0.577351,-0.794654,-0.447213,0,-0.223606, + 0.187591,-0.577356,-0.794651,-0.123606,0,-0.147214, + 0.187591,-0.577356,-0.794651,-0.118034,-0.038352,-0.118034, + 0.187591,-0.577356,-0.794651,-0.447213,0,-0.223606, + 0.187593,-0.577349,-0.794655,0.052786,-0.162459,0.012461, + 0.187593,-0.577349,-0.794655,0.1,-0.162459,0.023607, + 0.187593,-0.577349,-0.794655,0.138196,-0.425325,0.223606, + 0.1876,-0.577347,-0.794655,0.01459,-0.190211,0.023607, + 0.1876,-0.577347,-0.794655,0.052786,-0.162459,0.012461, + 0.1876,-0.577347,-0.794655,0.138196,-0.425325,0.223606, + 0.187596,-0.577353,-0.794652,0.118034,0.038352,-0.118034, + 0.187596,-0.577353,-0.794652,0.1,0.072654,-0.147214, + 0.187596,-0.577353,-0.794652,0.361803,0.262865,-0.223606, + 0.187591,-0.577349,-0.794656,0.161804,0.027751,-0.1, + 0.187591,-0.577349,-0.794656,0.118034,0.038352,-0.118034, + 0.187591,-0.577349,-0.794656,0.361803,0.262865,-0.223606, + 0.187592,-0.577357,-0.79465,-0.105573,-0.124108,-0.052786, + 0.187592,-0.577357,-0.79465,-0.1,-0.162459,-0.023607, + 0.187592,-0.577357,-0.79465,-0.223606,-0.162459,-0.052786, + 0.187591,-0.577354,-0.794652,0.138196,-0.100406,-0.012461, + 0.187591,-0.577354,-0.794652,0.176394,-0.072654,-0.023607, + 0.187591,-0.577354,-0.794652,0.223606,-0.162459,0.052786, + 0.187605,-0.577354,-0.794649,0.020163,0.062054,-0.158359, + 0.187605,-0.577354,-0.794649,-0.023607,0.072654,-0.176394, + 0.187605,-0.577354,-0.794649,0.052786,0.162459,-0.223606, + 0.187583,-0.57736,-0.79465,-0.023607,0.072654,-0.176394, + 0.187583,-0.57736,-0.79465,-0.052786,0.038352,-0.158359, + 0.187583,-0.57736,-0.79465,-0.138196,0.100406,-0.223606, + 0.187593,-0.57735,-0.794654,-0.1,-0.162459,-0.023607, + 0.187593,-0.57735,-0.794654,-0.052786,-0.162459,-0.012461, + 0.187593,-0.57735,-0.794654,-0.08541,-0.262865,0.052786, + 0.187592,-0.577347,-0.794657,0.176394,-0.072654,-0.023607, + 0.187592,-0.577347,-0.794657,0.158359,-0.038352,-0.052786, + 0.187592,-0.577347,-0.794657,0.276393,0,-0.052786, + 0.187592,-0.577351,-0.794654,-0.147214,-0.072654,-0.1, + 0.187592,-0.577351,-0.794654,-0.111804,-0.08123,-0.08541, + 0.187592,-0.577351,-0.794654,-0.223606,-0.162459,-0.052786, + 0.187591,-0.577359,-0.794648,0.1,-0.162459,0.023607, + 0.187591,-0.577359,-0.794648,0.095491,-0.131433,0, + 0.187591,-0.577359,-0.794648,0.223606,-0.162459,0.052786, + 0.187584,-0.577353,-0.794655,0.1,0.072654,-0.147214, + 0.187584,-0.577353,-0.794655,0.069098,0.050203,-0.138196, + 0.187584,-0.577353,-0.794655,0.052786,0.162459,-0.223606, + 0.187604,-0.577345,-0.794656,-0.08541,0,-0.138196, + 0.187604,-0.577345,-0.794656,-0.123606,0,-0.147214, + 0.187604,-0.577345,-0.794656,-0.138196,0.100406,-0.223606, + 0.187583,-0.577345,-0.79466,0,-0.162459,0, + 0.187583,-0.577345,-0.79466,0.01459,-0.190211,0.023607, + 0.187583,-0.577345,-0.79466,-0.08541,-0.262865,0.052786, + 0.187593,-0.577352,-0.794653,0.138196,0,-0.08541, + 0.187593,-0.577352,-0.794653,0.161804,0.027751,-0.1, + 0.187593,-0.577352,-0.794653,0.276393,0,-0.052786, + -0.187596,-0.577353,0.794652,-0.118034,0.038352,0.118034, + -0.187596,-0.577353,0.794652,-0.1,0.072654,0.147214, + -0.187596,-0.577353,0.794652,-0.361803,0.262865,0.223606, + -0.187591,-0.577349,0.794656,-0.161804,0.027751,0.1, + -0.187591,-0.577349,0.794656,-0.118034,0.038352,0.118034, + -0.187591,-0.577349,0.794656,-0.361803,0.262865,0.223606, + -0.187592,-0.577351,0.794654,0.118034,-0.038352,0.118034, + -0.187592,-0.577351,0.794654,0.147214,-0.072654,0.1, + -0.187592,-0.577351,0.794654,0.447213,0,0.223606, + -0.187591,-0.577356,0.794651,0.123606,0,0.147214, + -0.187591,-0.577356,0.794651,0.118034,-0.038352,0.118034, + -0.187591,-0.577356,0.794651,0.447213,0,0.223606, + -0.187593,-0.577349,0.794655,-0.052786,-0.162459,-0.012461, + -0.187593,-0.577349,0.794655,-0.1,-0.162459,-0.023607, + -0.187593,-0.577349,0.794655,-0.138196,-0.425325,-0.223606, + -0.1876,-0.577347,0.794655,-0.01459,-0.190211,-0.023607, + -0.1876,-0.577347,0.794655,-0.052786,-0.162459,-0.012461, + -0.1876,-0.577347,0.794655,-0.138196,-0.425325,-0.223606, + -0.187605,-0.577354,0.794649,-0.020163,0.062054,0.158359, + -0.187605,-0.577354,0.794649,0.023607,0.072654,0.176394, + -0.187605,-0.577354,0.794649,-0.052786,0.162459,0.223606, + -0.187592,-0.577357,0.79465,0.105573,-0.124108,0.052786, + -0.187592,-0.577357,0.79465,0.1,-0.162459,0.023607, + -0.187592,-0.577357,0.79465,0.223606,-0.162459,0.052786, + -0.187591,-0.577354,0.794652,-0.138196,-0.100406,0.012461, + -0.187591,-0.577354,0.794652,-0.176394,-0.072654,0.023607, + -0.187591,-0.577354,0.794652,-0.223606,-0.162459,-0.052786, + -0.187592,-0.577347,0.794657,-0.176394,-0.072654,0.023607, + -0.187592,-0.577347,0.794657,-0.158359,-0.038352,0.052786, + -0.187592,-0.577347,0.794657,-0.276393,0,0.052786, + -0.187583,-0.57736,0.79465,0.023607,0.072654,0.176394, + -0.187583,-0.57736,0.79465,0.052786,0.038352,0.158359, + -0.187583,-0.57736,0.79465,0.138196,0.100406,0.223606, + -0.187593,-0.57735,0.794654,0.1,-0.162459,0.023607, + -0.187593,-0.57735,0.794654,0.052786,-0.162459,0.012461, + -0.187593,-0.57735,0.794654,0.08541,-0.262865,-0.052786, + -0.187584,-0.577353,0.794655,-0.1,0.072654,0.147214, + -0.187584,-0.577353,0.794655,-0.069098,0.050203,0.138196, + -0.187584,-0.577353,0.794655,-0.052786,0.162459,0.223606, + -0.187592,-0.577351,0.794654,0.147214,-0.072654,0.1, + -0.187592,-0.577351,0.794654,0.111804,-0.08123,0.08541, + -0.187592,-0.577351,0.794654,0.223606,-0.162459,0.052786, + -0.187591,-0.577359,0.794648,-0.1,-0.162459,-0.023607, + -0.187591,-0.577359,0.794648,-0.095491,-0.131433,0, + -0.187591,-0.577359,0.794648,-0.223606,-0.162459,-0.052786, + -0.187593,-0.577352,0.794653,-0.138196,0,0.08541, + -0.187593,-0.577352,0.794653,-0.161804,0.027751,0.1, + -0.187593,-0.577352,0.794653,-0.276393,0,0.052786, + -0.187604,-0.577345,0.794656,0.08541,0,0.138196, + -0.187604,-0.577345,0.794656,0.123606,0,0.147214, + -0.187604,-0.577345,0.794656,0.138196,0.100406,0.223606, + -0.187583,-0.577345,0.79466,0,-0.162459,0, + -0.187583,-0.577345,0.79466,-0.01459,-0.190211,-0.023607, + -0.187583,-0.577345,0.79466,0.08541,-0.262865,-0.052786, + 0.794652,0.577358,0.18758,0.158359,-0.038352,-0.052786, + 0.794652,0.577358,0.18758,0.176394,-0.072654,-0.023607, + 0.794652,0.577358,0.18758,0.361803,-0.262865,-0.223606, + 0.794656,0.577344,0.187604,0.161804,-0.027751,-0.1, + 0.794656,0.577344,0.187604,0.158359,-0.038352,-0.052786, + 0.794656,0.577344,0.187604,0.361803,-0.262865,-0.223606, + 0.794657,0.577347,0.187592,0.052786,0.038352,0.158359, + 0.794657,0.577347,0.187592,0.023607,0.072654,0.176394, + 0.794657,0.577347,0.187592,0,0,0.5, + 0.794653,0.577353,0.187592,0.076393,0,0.176394, + 0.794653,0.577353,0.187592,0.052786,0.038352,0.158359, + 0.794653,0.577353,0.187592,0,0,0.5, + 0.794655,0.577349,0.187593,0.012461,0.162459,-0.052786, + 0.794655,0.577349,0.187593,0.023607,0.162459,-0.1, + 0.794655,0.577349,0.187593,-0.138196,0.425325,-0.223606, + 0.794658,0.577347,0.187587,-0.01459,0.190211,-0.023607, + 0.794658,0.577347,0.187587,0.012461,0.162459,-0.052786, + 0.794658,0.577347,0.187587,-0.138196,0.425325,-0.223606, + 0.794655,0.577351,0.187588,0.150658,-0.062054,0.052786, + 0.794655,0.577351,0.187588,0.147214,-0.072654,0.1, + 0.794655,0.577351,0.187588,0.223606,-0.162459,0.052786, + 0.79465,0.577356,0.187592,0,0.124108,0.118034, + 0.79465,0.577356,0.187592,-0.023607,0.162459,0.1, + 0.79465,0.577356,0.187592,-0.052786,0.162459,0.223606, + 0.794655,0.57735,0.18759,0.072949,0.100406,-0.118034, + 0.794655,0.57735,0.18759,0.1,0.072654,-0.147214, + 0.794655,0.57735,0.18759,0.052786,0.162459,-0.223606, + 0.794654,0.577351,0.187592,0.1,0.072654,-0.147214, + 0.794654,0.577351,0.187592,0.118034,0.038352,-0.118034, + 0.794654,0.577351,0.187592,0.17082,0,-0.223606, + 0.794652,0.577353,0.187596,0.147214,-0.072654,0.1, + 0.794652,0.577353,0.187596,0.118034,-0.038352,0.118034, + 0.794652,0.577353,0.187596,0.138196,-0.100406,0.223606, + 0.794654,0.57735,0.187593,-0.023607,0.162459,0.1, + 0.794654,0.57735,0.187593,-0.012461,0.162459,0.052786, + 0.794654,0.57735,0.187593,-0.08541,0.262865,0.052786, + 0.794648,0.577354,0.187607,0.176394,-0.072654,-0.023607, + 0.794648,0.577354,0.187607,0.154508,-0.050203,0, + 0.794648,0.577354,0.187607,0.223606,-0.162459,0.052786, + 0.794652,0.577354,0.18759,0.023607,0.072654,0.176394, + 0.794652,0.577354,0.18759,0.026393,0.08123,0.138196, + 0.794652,0.577354,0.18759,-0.052786,0.162459,0.223606, + 0.794649,0.577358,0.187592,0.023607,0.162459,-0.1, + 0.794649,0.577358,0.187592,0.042705,0.131433,-0.08541, + 0.794649,0.577358,0.187592,0.052786,0.162459,-0.223606, + 0.794646,0.577362,0.187591,0.138196,0,-0.08541, + 0.794646,0.577362,0.187591,0.161804,-0.027751,-0.1, + 0.794646,0.577362,0.187591,0.17082,0,-0.223606, + 0.794657,0.577348,0.18759,0.08541,0,0.138196, + 0.794657,0.577348,0.18759,0.076393,0,0.176394, + 0.794657,0.577348,0.18759,0.138196,-0.100406,0.223606, + 0.794655,0.577346,0.187602,0,0.162459,0, + 0.794655,0.577346,0.187602,-0.01459,0.190211,-0.023607, + 0.794655,0.577346,0.187602,-0.08541,0.262865,0.052786, + -0.794657,0.577347,-0.187592,-0.052786,0.038352,-0.158359, + -0.794657,0.577347,-0.187592,-0.023607,0.072654,-0.176394, + -0.794657,0.577347,-0.187592,0,0,-0.5, + -0.794653,0.577353,-0.187592,-0.076393,0,-0.176394, + -0.794653,0.577353,-0.187592,-0.052786,0.038352,-0.158359, + -0.794653,0.577353,-0.187592,0,0,-0.5, + -0.794655,0.577349,-0.187593,-0.012461,0.162459,0.052786, + -0.794655,0.577349,-0.187593,-0.023607,0.162459,0.1, + -0.794655,0.577349,-0.187593,0.138196,0.425325,0.223606, + -0.794658,0.577347,-0.187587,0.01459,0.190211,0.023607, + -0.794658,0.577347,-0.187587,-0.012461,0.162459,0.052786, + -0.794658,0.577347,-0.187587,0.138196,0.425325,0.223606, + -0.794652,0.577358,-0.18758,-0.158359,-0.038352,0.052786, + -0.794652,0.577358,-0.18758,-0.176394,-0.072654,0.023607, + -0.794652,0.577358,-0.18758,-0.361803,-0.262865,0.223606, + -0.794656,0.577344,-0.187604,-0.161804,-0.027751,0.1, + -0.794656,0.577344,-0.187604,-0.158359,-0.038352,0.052786, + -0.794656,0.577344,-0.187604,-0.361803,-0.262865,0.223606, + -0.79465,0.577356,-0.187592,0,0.124108,-0.118034, + -0.79465,0.577356,-0.187592,0.023607,0.162459,-0.1, + -0.79465,0.577356,-0.187592,0.052786,0.162459,-0.223606, + -0.794655,0.57735,-0.18759,-0.072949,0.100406,0.118034, + -0.794655,0.57735,-0.18759,-0.1,0.072654,0.147214, + -0.794655,0.57735,-0.18759,-0.052786,0.162459,0.223606, + -0.794655,0.577351,-0.187588,-0.150658,-0.062054,-0.052786, + -0.794655,0.577351,-0.187588,-0.147214,-0.072654,-0.1, + -0.794655,0.577351,-0.187588,-0.223606,-0.162459,-0.052786, + -0.794652,0.577353,-0.187596,-0.147214,-0.072654,-0.1, + -0.794652,0.577353,-0.187596,-0.118034,-0.038352,-0.118034, + -0.794652,0.577353,-0.187596,-0.138196,-0.100406,-0.223606, + -0.794654,0.57735,-0.187593,0.023607,0.162459,-0.1, + -0.794654,0.57735,-0.187593,0.012461,0.162459,-0.052786, + -0.794654,0.57735,-0.187593,0.08541,0.262865,-0.052786, + -0.794654,0.577351,-0.187592,-0.1,0.072654,0.147214, + -0.794654,0.577351,-0.187592,-0.118034,0.038352,0.118034, + -0.794654,0.577351,-0.187592,-0.17082,0,0.223606, + -0.794652,0.577354,-0.18759,-0.023607,0.072654,-0.176394, + -0.794652,0.577354,-0.18759,-0.026393,0.08123,-0.138196, + -0.794652,0.577354,-0.18759,0.052786,0.162459,-0.223606, + -0.794649,0.577358,-0.187592,-0.023607,0.162459,0.1, + -0.794649,0.577358,-0.187592,-0.042705,0.131433,0.08541, + -0.794649,0.577358,-0.187592,-0.052786,0.162459,0.223606, + -0.794648,0.577354,-0.187607,-0.176394,-0.072654,0.023607, + -0.794648,0.577354,-0.187607,-0.154508,-0.050203,0, + -0.794648,0.577354,-0.187607,-0.223606,-0.162459,-0.052786, + -0.794657,0.577348,-0.18759,-0.08541,0,-0.138196, + -0.794657,0.577348,-0.18759,-0.076393,0,-0.176394, + -0.794657,0.577348,-0.18759,-0.138196,-0.100406,-0.223606, + -0.794655,0.577346,-0.187602,0,0.162459,0, + -0.794655,0.577346,-0.187602,0.01459,0.190211,0.023607, + -0.794655,0.577346,-0.187602,0.08541,0.262865,-0.052786, + -0.794646,0.577362,-0.187591,-0.138196,0,0.08541, + -0.794646,0.577362,-0.187591,-0.161804,-0.027751,0.1, + -0.794646,0.577362,-0.187591,-0.17082,0,0.223606, + 0.491129,0.356821,0.794652,0.072949,-0.100406,0.118034, + 0.491129,0.356821,0.794652,0.038197,-0.117557,0.147214, + 0.491129,0.356821,0.794652,0.138196,-0.425325,0.223606, + 0.491121,0.356821,0.794656,0.11459,-0.117557,0.1, + 0.491121,0.356821,0.794656,0.072949,-0.100406,0.118034, + 0.491121,0.356821,0.794656,0.138196,-0.425325,0.223606, + 0.491124,0.356824,0.794654,-0.072949,0.100406,0.118034, + 0.491124,0.356824,0.794654,-0.076393,0.145308,0.1, + 0.491124,0.356824,0.794654,-0.361803,0.262865,0.223606, + 0.491125,0.356827,0.794651,-0.1,0.072654,0.147214, + 0.491125,0.356827,0.794651,-0.072949,0.100406,0.118034, + 0.491125,0.356827,0.794651,-0.361803,0.262865,0.223606, + 0.491119,0.356829,0.794654,0.138196,0.100406,-0.012461, + 0.491119,0.356829,0.794654,0.176394,0.072654,-0.023607, + 0.491119,0.356829,0.794654,0.361803,0.262865,-0.223606, + 0.491121,0.356826,0.794654,0.123606,0.145308,-0.023607, + 0.491121,0.356826,0.794654,0.138196,0.100406,-0.012461, + 0.491121,0.356826,0.794654,0.361803,0.262865,-0.223606, + 0.491135,0.356817,0.79465,-0.020163,-0.062054,0.158359, + 0.491135,0.356817,0.79465,-0.061803,-0.044903,0.176394, + 0.491135,0.356817,0.79465,-0.052786,-0.162459,0.223606, + 0.49112,0.35682,0.794658,-0.012461,0.162459,0.052786, + 0.49112,0.35682,0.794658,0.01459,0.190211,0.023607, + 0.49112,0.35682,0.794658,-0.08541,0.262865,0.052786, + 0.491124,0.356824,0.794654,0.17082,0,0.012461, + 0.491124,0.356824,0.794654,0.18541,-0.044903,0.023607, + 0.491124,0.356824,0.794654,0.276393,0,-0.052786, + 0.491124,0.356822,0.794654,0.18541,-0.044903,0.023607, + 0.491124,0.356822,0.794654,0.150658,-0.062054,0.052786, + 0.491124,0.356822,0.794654,0.223606,-0.162459,0.052786, + 0.491122,0.356835,0.79465,-0.061803,-0.044903,0.176394, + 0.491122,0.356835,0.79465,-0.065247,0,0.158359, + 0.491122,0.356835,0.79465,-0.17082,0,0.223606, + 0.491128,0.356819,0.794653,0.01459,0.190211,0.023607, + 0.491128,0.356819,0.794653,0.052786,0.162459,0.012461, + 0.491128,0.356819,0.794653,0.08541,0.262865,-0.052786, + 0.491117,0.35683,0.794655,0.038197,-0.117557,0.147214, + 0.491117,0.35683,0.794655,0.026393,-0.08123,0.138196, + 0.491117,0.35683,0.794655,-0.052786,-0.162459,0.223606, + 0.491117,0.356823,0.794658,-0.076393,0.145308,0.1, + 0.491117,0.356823,0.794658,-0.042705,0.131433,0.08541, + 0.491117,0.356823,0.794658,-0.08541,0.262865,0.052786, + 0.491122,0.356812,0.79466,0.176394,0.072654,-0.023607, + 0.491122,0.356812,0.79466,0.154508,0.050203,0, + 0.491122,0.356812,0.79466,0.276393,0,-0.052786, + 0.491124,0.35682,0.794655,0.111804,-0.08123,0.08541, + 0.491124,0.35682,0.794655,0.11459,-0.117557,0.1, + 0.491124,0.35682,0.794655,0.223606,-0.162459,0.052786, + 0.491129,0.356813,0.794655,-0.069098,0.050203,0.138196, + 0.491129,0.356813,0.794655,-0.1,0.072654,0.147214, + 0.491129,0.356813,0.794655,-0.17082,0,0.223606, + 0.491133,0.356822,0.794648,0.095491,0.131433,0, + 0.491133,0.356822,0.794648,0.123606,0.145308,-0.023607, + 0.491133,0.356822,0.794648,0.08541,0.262865,-0.052786, + 0.187591,0.577349,-0.794656,0.118034,-0.038352,-0.118034, + 0.187591,0.577349,-0.794656,0.161804,-0.027751,-0.1, + 0.187591,0.577349,-0.794656,0.361803,-0.262865,-0.223606, + 0.187596,0.577353,-0.794652,0.1,-0.072654,-0.147214, + 0.187596,0.577353,-0.794652,0.118034,-0.038352,-0.118034, + 0.187596,0.577353,-0.794652,0.361803,-0.262865,-0.223606, + 0.1876,0.577347,-0.794655,0.052786,0.162459,0.012461, + 0.1876,0.577347,-0.794655,0.01459,0.190211,0.023607, + 0.1876,0.577347,-0.794655,0.138196,0.425325,0.223606, + 0.187593,0.577349,-0.794655,0.1,0.162459,0.023607, + 0.187593,0.577349,-0.794655,0.052786,0.162459,0.012461, + 0.187593,0.577349,-0.794655,0.138196,0.425325,0.223606, + 0.187591,0.577356,-0.794651,-0.118034,0.038352,-0.118034, + 0.187591,0.577356,-0.794651,-0.123606,0,-0.147214, + 0.187591,0.577356,-0.794651,-0.447213,0,-0.223606, + 0.187592,0.577351,-0.794654,-0.147214,0.072654,-0.1, + 0.187592,0.577351,-0.794654,-0.118034,0.038352,-0.118034, + 0.187592,0.577351,-0.794654,-0.447213,0,-0.223606, + 0.187592,0.577347,-0.794657,0.158359,0.038352,-0.052786, + 0.187592,0.577347,-0.794657,0.176394,0.072654,-0.023607, + 0.187592,0.577347,-0.794657,0.276393,0,-0.052786, + 0.187593,0.57735,-0.794654,-0.052786,0.162459,-0.012461, + 0.187593,0.57735,-0.794654,-0.1,0.162459,-0.023607, + 0.187593,0.57735,-0.794654,-0.08541,0.262865,0.052786, + 0.187583,0.57736,-0.79465,-0.052786,-0.038352,-0.158359, + 0.187583,0.57736,-0.79465,-0.023607,-0.072654,-0.176394, + 0.187583,0.57736,-0.79465,-0.138196,-0.100406,-0.223606, + 0.187605,0.577354,-0.794649,-0.023607,-0.072654,-0.176394, + 0.187605,0.577354,-0.794649,0.020163,-0.062054,-0.158359, + 0.187605,0.577354,-0.794649,0.052786,-0.162459,-0.223606, + 0.187591,0.577354,-0.794652,0.176394,0.072654,-0.023607, + 0.187591,0.577354,-0.794652,0.138196,0.100406,-0.012461, + 0.187591,0.577354,-0.794652,0.223606,0.162459,0.052786, + 0.187592,0.577357,-0.79465,-0.1,0.162459,-0.023607, + 0.187592,0.577357,-0.79465,-0.105573,0.124108,-0.052786, + 0.187592,0.577357,-0.79465,-0.223606,0.162459,-0.052786, + 0.187593,0.577352,-0.794653,0.161804,-0.027751,-0.1, + 0.187593,0.577352,-0.794653,0.138196,0,-0.08541, + 0.187593,0.577352,-0.794653,0.276393,0,-0.052786, + 0.187583,0.577345,-0.79466,0.01459,0.190211,0.023607, + 0.187583,0.577345,-0.79466,0,0.162459,0, + 0.187583,0.577345,-0.79466,-0.08541,0.262865,0.052786, + 0.187604,0.577345,-0.794656,-0.123606,0,-0.147214, + 0.187604,0.577345,-0.794656,-0.08541,0,-0.138196, + 0.187604,0.577345,-0.794656,-0.138196,-0.100406,-0.223606, + 0.187584,0.577353,-0.794655,0.069098,-0.050203,-0.138196, + 0.187584,0.577353,-0.794655,0.1,-0.072654,-0.147214, + 0.187584,0.577353,-0.794655,0.052786,-0.162459,-0.223606, + 0.187591,0.577359,-0.794648,0.095491,0.131433,0, + 0.187591,0.577359,-0.794648,0.1,0.162459,0.023607, + 0.187591,0.577359,-0.794648,0.223606,0.162459,0.052786, + 0.187592,0.577351,-0.794654,-0.111804,0.08123,-0.08541, + 0.187592,0.577351,-0.794654,-0.147214,0.072654,-0.1, + 0.187592,0.577351,-0.794654,-0.223606,0.162459,-0.052786, + 0.303535,-0.934171,-0.187592,0.020163,-0.062054,-0.158359, + 0.303535,-0.934171,-0.187592,-0.023607,-0.072654,-0.176394, + 0.303535,-0.934171,-0.187592,0,0,-0.5, + 0.303526,-0.934174,-0.187592,0.061803,-0.044903,-0.176394, + 0.303526,-0.934174,-0.187592,0.020163,-0.062054,-0.158359, + 0.303526,-0.934174,-0.187592,0,0,-0.5, + 0.303538,-0.934173,-0.187579,-0.08541,-0.138758,0.052786, + 0.303538,-0.934173,-0.187579,-0.076393,-0.145308,0.1, + 0.303538,-0.934173,-0.187579,-0.361803,-0.262865,0.223606, + 0.303523,-0.934173,-0.187603,-0.123606,-0.145308,0.023607, + 0.303523,-0.934173,-0.187603,-0.08541,-0.138758,0.052786, + 0.303523,-0.934173,-0.187603,-0.361803,-0.262865,0.223606, + 0.303531,-0.934173,-0.187591,0.150658,-0.062054,0.052786, + 0.303531,-0.934173,-0.187591,0.18541,-0.044903,0.023607, + 0.303531,-0.934173,-0.187591,0.447213,0,0.223606, + 0.303532,-0.934172,-0.187594,0.147214,-0.072654,0.1, + 0.303532,-0.934172,-0.187594,0.150658,-0.062054,0.052786, + 0.303532,-0.934172,-0.187594,0.447213,0,0.223606, + 0.30353,-0.934173,-0.187591,-0.072949,-0.100406,-0.118034, + 0.30353,-0.934173,-0.187591,-0.11459,-0.117557,-0.1, + 0.30353,-0.934173,-0.187591,-0.138196,-0.100406,-0.223606, + 0.303534,-0.934173,-0.187586,0,-0.124108,0.118034, + 0.303534,-0.934173,-0.187586,0.038197,-0.117557,0.147214, + 0.303534,-0.934173,-0.187586,-0.052786,-0.162459,0.223606, + 0.303531,-0.934173,-0.187588,0.158359,-0.038352,-0.052786, + 0.303531,-0.934173,-0.187588,0.161804,-0.027751,-0.1, + 0.303531,-0.934173,-0.187588,0.276393,0,-0.052786, + 0.303529,-0.934173,-0.187594,0.161804,-0.027751,-0.1, + 0.303529,-0.934173,-0.187594,0.118034,-0.038352,-0.118034, + 0.303529,-0.934173,-0.187594,0.17082,0,-0.223606, + 0.303526,-0.934172,-0.187599,-0.11459,-0.117557,-0.1, + 0.303526,-0.934172,-0.187599,-0.105573,-0.124108,-0.052786, + 0.303526,-0.934172,-0.187599,-0.223606,-0.162459,-0.052786, + 0.30353,-0.934173,-0.187591,0.038197,-0.117557,0.147214, + 0.30353,-0.934173,-0.187591,0.072949,-0.100406,0.118034, + 0.30353,-0.934173,-0.187591,0.138196,-0.100406,0.223606, + 0.303529,-0.934174,-0.187588,-0.023607,-0.072654,-0.176394, + 0.303529,-0.934174,-0.187588,-0.026393,-0.08123,-0.138196, + 0.303529,-0.934174,-0.187588,-0.138196,-0.100406,-0.223606, + 0.303516,-0.934178,-0.18759,-0.076393,-0.145308,0.1, + 0.303516,-0.934178,-0.18759,-0.042705,-0.131433,0.08541, + 0.303516,-0.934178,-0.18759,-0.052786,-0.162459,0.223606, + 0.30353,-0.934172,-0.187595,0.18541,-0.044903,0.023607, + 0.30353,-0.934172,-0.187595,0.154508,-0.050203,0, + 0.30353,-0.934172,-0.187595,0.276393,0,-0.052786, + 0.303535,-0.934172,-0.187588,0.069098,-0.050203,-0.138196, + 0.303535,-0.934172,-0.187588,0.061803,-0.044903,-0.176394, + 0.303535,-0.934172,-0.187588,0.17082,0,-0.223606, + 0.303524,-0.934177,-0.187583,-0.095491,-0.131433,0, + 0.303524,-0.934177,-0.187583,-0.123606,-0.145308,0.023607, + 0.303524,-0.934177,-0.187583,-0.223606,-0.162459,-0.052786, + 0.303531,-0.934173,-0.187592,0.111804,-0.08123,0.08541, + 0.303531,-0.934173,-0.187592,0.147214,-0.072654,0.1, + 0.303531,-0.934173,-0.187592,0.138196,-0.100406,0.223606, + -0.982248,-0.000002,0.187589,-0.105573,0.124108,-0.052786, + -0.982248,-0.000002,0.187589,-0.1,0.162459,-0.023607, + -0.982248,-0.000002,0.187589,-0.138196,0.425325,-0.223606, + -0.982245,0.000005,0.187601,-0.11459,0.117557,-0.1, + -0.982245,0.000005,0.187601,-0.105573,0.124108,-0.052786, + -0.982245,0.000005,0.187601,-0.138196,0.425325,-0.223606, + -0.982247,0.000005,0.187592,-0.065247,0,0.158359, + -0.982247,0.000005,0.187592,-0.061803,-0.044903,0.176394, + -0.982247,0.000005,0.187592,0,0,0.5, + -0.982247,-0.000005,0.187592,-0.061803,0.044903,0.176394, + -0.982247,-0.000005,0.187592,-0.065247,0,0.158359, + -0.982247,-0.000005,0.187592,0,0,0.5, + -0.982245,-0.000005,0.187601,-0.105573,-0.124108,-0.052786, + -0.982245,-0.000005,0.187601,-0.11459,-0.117557,-0.1, + -0.982245,-0.000005,0.187601,-0.138196,-0.425325,-0.223606, + -0.982248,0.000002,0.187589,-0.1,-0.162459,-0.023607, + -0.982248,0.000002,0.187589,-0.105573,-0.124108,-0.052786, + -0.982248,0.000002,0.187589,-0.138196,-0.425325,-0.223606, + -0.982247,0,0.187593,-0.08541,0.138758,0.052786, + -0.982247,0,0.187593,-0.076393,0.145308,0.1, + -0.982247,0,0.187593,-0.08541,0.262865,0.052786, + -0.982247,-0.000001,0.187593,-0.072949,-0.100406,0.118034, + -0.982247,-0.000001,0.187593,-0.076393,-0.145308,0.1, + -0.982247,-0.000001,0.187593,-0.052786,-0.162459,0.223606, + -0.982248,0.000006,0.187588,-0.118034,-0.038352,-0.118034, + -0.982248,0.000006,0.187588,-0.123606,0,-0.147214, + -0.982248,0.000006,0.187588,-0.138196,-0.100406,-0.223606, + -0.982248,-0.000006,0.187588,-0.123606,0,-0.147214, + -0.982248,-0.000006,0.187588,-0.118034,0.038352,-0.118034, + -0.982248,-0.000006,0.187588,-0.138196,0.100406,-0.223606, + -0.982247,0.000001,0.187593,-0.076393,0.145308,0.1, + -0.982247,0.000001,0.187593,-0.072949,0.100406,0.118034, + -0.982247,0.000001,0.187593,-0.052786,0.162459,0.223606, + -0.982247,0,0.187593,-0.076393,-0.145308,0.1, + -0.982247,0,0.187593,-0.08541,-0.138758,0.052786, + -0.982247,0,0.187593,-0.08541,-0.262865,0.052786, + -0.982247,0.000001,0.187591,-0.1,0.162459,-0.023607, + -0.982247,0.000001,0.187591,-0.095491,0.131433,0, + -0.982247,0.000001,0.187591,-0.08541,0.262865,0.052786, + -0.982248,-0.000003,0.187589,-0.061803,-0.044903,0.176394, + -0.982248,-0.000003,0.187589,-0.069098,-0.050203,0.138196, + -0.982248,-0.000003,0.187589,-0.052786,-0.162459,0.223606, + -0.982248,-0.000002,0.187589,-0.11459,-0.117557,-0.1, + -0.982248,-0.000002,0.187589,-0.111804,-0.08123,-0.08541, + -0.982248,-0.000002,0.187589,-0.138196,-0.100406,-0.223606, + -0.982248,0.000002,0.187589,-0.111804,0.08123,-0.08541, + -0.982248,0.000002,0.187589,-0.11459,0.117557,-0.1, + -0.982248,0.000002,0.187589,-0.138196,0.100406,-0.223606, + -0.982248,0.000003,0.187589,-0.069098,0.050203,0.138196, + -0.982248,0.000003,0.187589,-0.061803,0.044903,0.176394, + -0.982248,0.000003,0.187589,-0.052786,0.162459,0.223606, + -0.982247,-0.000001,0.187591,-0.095491,-0.131433,0, + -0.982247,-0.000001,0.187591,-0.1,-0.162459,-0.023607, + -0.982247,-0.000001,0.187591,-0.08541,-0.262865,0.052786, + 0.607062,0,-0.794655,0,-0.124108,-0.118034, + 0.607062,0,-0.794655,0.023607,-0.162459,-0.1, + 0.607062,0,-0.794655,-0.138196,-0.425325,-0.223606, + 0.607065,-0.000003,-0.794652,-0.038197,-0.117557,-0.147214, + 0.607065,-0.000003,-0.794652,0,-0.124108,-0.118034, + 0.607065,-0.000003,-0.794652,-0.138196,-0.425325,-0.223606, + 0.607062,-0.000002,-0.794654,0.17082,0,0.012461, + 0.607062,-0.000002,-0.794654,0.18541,0.044903,0.023607, + 0.607062,-0.000002,-0.794654,0.447213,0,0.223606, + 0.607062,0.000002,-0.794654,0.18541,-0.044903,0.023607, + 0.607062,0.000002,-0.794654,0.17082,0,0.012461, + 0.607062,0.000002,-0.794654,0.447213,0,0.223606, + 0.607065,0.000003,-0.794652,0,0.124108,-0.118034, + 0.607065,0.000003,-0.794652,-0.038197,0.117557,-0.147214, + 0.607065,0.000003,-0.794652,-0.138196,0.425325,-0.223606, + 0.607062,0,-0.794655,0.023607,0.162459,-0.1, + 0.607062,0,-0.794655,0,0.124108,-0.118034, + 0.607062,0,-0.794655,-0.138196,0.425325,-0.223606, + 0.607066,0,-0.794652,0.08541,-0.138758,-0.052786, + 0.607066,0,-0.794652,0.123606,-0.145308,-0.023607, + 0.607066,0,-0.794652,0.08541,-0.262865,-0.052786, + 0.607061,0.000001,-0.794655,0.138196,0.100406,-0.012461, + 0.607061,0.000001,-0.794655,0.123606,0.145308,-0.023607, + 0.607061,0.000001,-0.794655,0.223606,0.162459,0.052786, + 0.607069,0.000012,-0.794649,-0.052786,0.038352,-0.158359, + 0.607069,0.000012,-0.794649,-0.076393,0,-0.176394, + 0.607069,0.000012,-0.794649,-0.138196,0.100406,-0.223606, + 0.607069,-0.000012,-0.794649,-0.076393,0,-0.176394, + 0.607069,-0.000012,-0.794649,-0.052786,-0.038352,-0.158359, + 0.607069,-0.000012,-0.794649,-0.138196,-0.100406,-0.223606, + 0.607061,-0.000001,-0.794655,0.123606,-0.145308,-0.023607, + 0.607061,-0.000001,-0.794655,0.138196,-0.100406,-0.012461, + 0.607061,-0.000001,-0.794655,0.223606,-0.162459,0.052786, + 0.607066,0,-0.794652,0.123606,0.145308,-0.023607, + 0.607066,0,-0.794652,0.08541,0.138758,-0.052786, + 0.607066,0,-0.794652,0.08541,0.262865,-0.052786, + 0.607061,0,-0.794655,0.023607,-0.162459,-0.1, + 0.607061,0,-0.794655,0.042705,-0.131433,-0.08541, + 0.607061,0,-0.794655,0.08541,-0.262865,-0.052786, + 0.60706,0.000002,-0.794656,0.18541,0.044903,0.023607, + 0.60706,0.000002,-0.794656,0.154508,0.050203,0, + 0.60706,0.000002,-0.794656,0.223606,0.162459,0.052786, + 0.607061,-0.00001,-0.794655,-0.038197,0.117557,-0.147214, + 0.607061,-0.00001,-0.794655,-0.026393,0.08123,-0.138196, + 0.607061,-0.00001,-0.794655,-0.138196,0.100406,-0.223606, + 0.607061,0.00001,-0.794655,-0.026393,-0.08123,-0.138196, + 0.607061,0.00001,-0.794655,-0.038197,-0.117557,-0.147214, + 0.607061,0.00001,-0.794655,-0.138196,-0.100406,-0.223606, + 0.60706,-0.000002,-0.794656,0.154508,-0.050203,0, + 0.60706,-0.000002,-0.794656,0.18541,-0.044903,0.023607, + 0.60706,-0.000002,-0.794656,0.223606,-0.162459,0.052786, + 0.607061,0,-0.794655,0.042705,0.131433,-0.08541, + 0.607061,0,-0.794655,0.023607,0.162459,-0.1, + 0.607061,0,-0.794655,0.08541,0.262865,-0.052786, + 0.491125,-0.356827,0.794651,-0.072949,-0.100406,0.118034, + 0.491125,-0.356827,0.794651,-0.1,-0.072654,0.147214, + 0.491125,-0.356827,0.794651,-0.361803,-0.262865,0.223606, + 0.491124,-0.356824,0.794654,-0.076393,-0.145308,0.1, + 0.491124,-0.356824,0.794654,-0.072949,-0.100406,0.118034, + 0.491124,-0.356824,0.794654,-0.361803,-0.262865,0.223606, + 0.491121,-0.356821,0.794656,0.072949,0.100406,0.118034, + 0.491121,-0.356821,0.794656,0.11459,0.117557,0.1, + 0.491121,-0.356821,0.794656,0.138196,0.425325,0.223606, + 0.491129,-0.356821,0.794652,0.038197,0.117557,0.147214, + 0.491129,-0.356821,0.794652,0.072949,0.100406,0.118034, + 0.491129,-0.356821,0.794652,0.138196,0.425325,0.223606, + 0.491121,-0.356826,0.794654,0.138196,-0.100406,-0.012461, + 0.491121,-0.356826,0.794654,0.123606,-0.145308,-0.023607, + 0.491121,-0.356826,0.794654,0.361803,-0.262865,-0.223606, + 0.491119,-0.356829,0.794654,0.176394,-0.072654,-0.023607, + 0.491119,-0.356829,0.794654,0.138196,-0.100406,-0.012461, + 0.491119,-0.356829,0.794654,0.361803,-0.262865,-0.223606, + 0.491122,-0.356835,0.79465,-0.065247,0,0.158359, + 0.491122,-0.356835,0.79465,-0.061803,0.044903,0.176394, + 0.491122,-0.356835,0.79465,-0.17082,0,0.223606, + 0.491124,-0.356822,0.794654,0.150658,0.062054,0.052786, + 0.491124,-0.356822,0.794654,0.18541,0.044903,0.023607, + 0.491124,-0.356822,0.794654,0.223606,0.162459,0.052786, + 0.491128,-0.356819,0.794653,0.052786,-0.162459,0.012461, + 0.491128,-0.356819,0.794653,0.01459,-0.190211,0.023607, + 0.491128,-0.356819,0.794653,0.08541,-0.262865,-0.052786, + 0.49112,-0.35682,0.794658,0.01459,-0.190211,0.023607, + 0.49112,-0.35682,0.794658,-0.012461,-0.162459,0.052786, + 0.49112,-0.35682,0.794658,-0.08541,-0.262865,0.052786, + 0.491135,-0.356817,0.79465,-0.061803,0.044903,0.176394, + 0.491135,-0.356817,0.79465,-0.020163,0.062054,0.158359, + 0.491135,-0.356817,0.79465,-0.052786,0.162459,0.223606, + 0.491124,-0.356824,0.794654,0.18541,0.044903,0.023607, + 0.491124,-0.356824,0.794654,0.17082,0,0.012461, + 0.491124,-0.356824,0.794654,0.276393,0,-0.052786, + 0.491129,-0.356813,0.794655,-0.1,-0.072654,0.147214, + 0.491129,-0.356813,0.794655,-0.069098,-0.050203,0.138196, + 0.491129,-0.356813,0.794655,-0.17082,0,0.223606, + 0.491124,-0.35682,0.794655,0.11459,0.117557,0.1, + 0.491124,-0.35682,0.794655,0.111804,0.08123,0.08541, + 0.491124,-0.35682,0.794655,0.223606,0.162459,0.052786, + 0.491133,-0.356822,0.794648,0.123606,-0.145308,-0.023607, + 0.491133,-0.356822,0.794648,0.095491,-0.131433,0, + 0.491133,-0.356822,0.794648,0.08541,-0.262865,-0.052786, + 0.491117,-0.356823,0.794658,-0.042705,-0.131433,0.08541, + 0.491117,-0.356823,0.794658,-0.076393,-0.145308,0.1, + 0.491117,-0.356823,0.794658,-0.08541,-0.262865,0.052786, + 0.491117,-0.35683,0.794655,0.026393,0.08123,0.138196, + 0.491117,-0.35683,0.794655,0.038197,0.117557,0.147214, + 0.491117,-0.35683,0.794655,-0.052786,0.162459,0.223606, + 0.491122,-0.356812,0.79466,0.154508,-0.050203,0, + 0.491122,-0.356812,0.79466,0.176394,-0.072654,-0.023607, + 0.491122,-0.356812,0.79466,0.276393,0,-0.052786, + -0.794653,-0.577353,-0.187592,-0.052786,-0.038352,-0.158359, + -0.794653,-0.577353,-0.187592,-0.076393,0,-0.176394, + -0.794653,-0.577353,-0.187592,0,0,-0.5, + -0.794657,-0.577347,-0.187592,-0.023607,-0.072654,-0.176394, + -0.794657,-0.577347,-0.187592,-0.052786,-0.038352,-0.158359, + -0.794657,-0.577347,-0.187592,0,0,-0.5, + -0.794656,-0.577344,-0.187604,-0.158359,0.038352,0.052786, + -0.794656,-0.577344,-0.187604,-0.161804,0.027751,0.1, + -0.794656,-0.577344,-0.187604,-0.361803,0.262865,0.223606, + -0.794652,-0.577358,-0.18758,-0.176394,0.072654,0.023607, + -0.794652,-0.577358,-0.18758,-0.158359,0.038352,0.052786, + -0.794652,-0.577358,-0.18758,-0.361803,0.262865,0.223606, + -0.794658,-0.577347,-0.187587,-0.012461,-0.162459,0.052786, + -0.794658,-0.577347,-0.187587,0.01459,-0.190211,0.023607, + -0.794658,-0.577347,-0.187587,0.138196,-0.425325,0.223606, + -0.794655,-0.577349,-0.187593,-0.023607,-0.162459,0.1, + -0.794655,-0.577349,-0.187593,-0.012461,-0.162459,0.052786, + -0.794655,-0.577349,-0.187593,0.138196,-0.425325,0.223606, + -0.794652,-0.577353,-0.187596,-0.118034,0.038352,-0.118034, + -0.794652,-0.577353,-0.187596,-0.147214,0.072654,-0.1, + -0.794652,-0.577353,-0.187596,-0.138196,0.100406,-0.223606, + -0.794654,-0.577351,-0.187592,-0.118034,-0.038352,0.118034, + -0.794654,-0.577351,-0.187592,-0.1,-0.072654,0.147214, + -0.794654,-0.577351,-0.187592,-0.17082,0,0.223606, + -0.794654,-0.57735,-0.187593,0.012461,-0.162459,-0.052786, + -0.794654,-0.57735,-0.187593,0.023607,-0.162459,-0.1, + -0.794654,-0.57735,-0.187593,0.08541,-0.262865,-0.052786, + -0.79465,-0.577356,-0.187592,0.023607,-0.162459,-0.1, + -0.79465,-0.577356,-0.187592,0,-0.124108,-0.118034, + -0.79465,-0.577356,-0.187592,0.052786,-0.162459,-0.223606, + -0.794655,-0.577351,-0.187588,-0.147214,0.072654,-0.1, + -0.794655,-0.577351,-0.187588,-0.150658,0.062054,-0.052786, + -0.794655,-0.577351,-0.187588,-0.223606,0.162459,-0.052786, + -0.794655,-0.57735,-0.18759,-0.1,-0.072654,0.147214, + -0.794655,-0.57735,-0.18759,-0.072949,-0.100406,0.118034, + -0.794655,-0.57735,-0.18759,-0.052786,-0.162459,0.223606, + -0.794657,-0.577348,-0.18759,-0.076393,0,-0.176394, + -0.794657,-0.577348,-0.18759,-0.08541,0,-0.138196, + -0.794657,-0.577348,-0.18759,-0.138196,0.100406,-0.223606, + -0.794646,-0.577362,-0.187591,-0.161804,0.027751,0.1, + -0.794646,-0.577362,-0.187591,-0.138196,0,0.08541, + -0.794646,-0.577362,-0.187591,-0.17082,0,0.223606, + -0.794655,-0.577346,-0.187602,0.01459,-0.190211,0.023607, + -0.794655,-0.577346,-0.187602,0,-0.162459,0, + -0.794655,-0.577346,-0.187602,0.08541,-0.262865,-0.052786, + -0.794652,-0.577354,-0.18759,-0.026393,-0.08123,-0.138196, + -0.794652,-0.577354,-0.18759,-0.023607,-0.072654,-0.176394, + -0.794652,-0.577354,-0.18759,0.052786,-0.162459,-0.223606, + -0.794648,-0.577354,-0.187607,-0.154508,0.050203,0, + -0.794648,-0.577354,-0.187607,-0.176394,0.072654,0.023607, + -0.794648,-0.577354,-0.187607,-0.223606,0.162459,-0.052786, + -0.794649,-0.577358,-0.187592,-0.042705,-0.131433,0.08541, + -0.794649,-0.577358,-0.187592,-0.023607,-0.162459,0.1, + -0.794649,-0.577358,-0.187592,-0.052786,-0.162459,0.223606, + -0.303523,0.934173,0.187603,0.08541,0.138758,-0.052786, + -0.303523,0.934173,0.187603,0.123606,0.145308,-0.023607, + -0.303523,0.934173,0.187603,0.361803,0.262865,-0.223606, + -0.303538,0.934173,0.187579,0.076393,0.145308,-0.1, + -0.303538,0.934173,0.187579,0.08541,0.138758,-0.052786, + -0.303538,0.934173,0.187579,0.361803,0.262865,-0.223606, + -0.303526,0.934174,0.187592,-0.020163,0.062054,0.158359, + -0.303526,0.934174,0.187592,-0.061803,0.044903,0.176394, + -0.303526,0.934174,0.187592,0,0,0.5, + -0.303535,0.934171,0.187592,0.023607,0.072654,0.176394, + -0.303535,0.934171,0.187592,-0.020163,0.062054,0.158359, + -0.303535,0.934171,0.187592,0,0,0.5, + -0.303532,0.934172,0.187594,-0.150658,0.062054,-0.052786, + -0.303532,0.934172,0.187594,-0.147214,0.072654,-0.1, + -0.303532,0.934172,0.187594,-0.447213,0,-0.223606, + -0.303531,0.934173,0.187591,-0.18541,0.044903,-0.023607, + -0.303531,0.934173,0.187591,-0.150658,0.062054,-0.052786, + -0.303531,0.934173,0.187591,-0.447213,0,-0.223606, + -0.303526,0.934172,0.187599,0.105573,0.124108,0.052786, + -0.303526,0.934172,0.187599,0.11459,0.117557,0.1, + -0.303526,0.934172,0.187599,0.223606,0.162459,0.052786, + -0.303529,0.934173,0.187594,-0.118034,0.038352,0.118034, + -0.303529,0.934173,0.187594,-0.161804,0.027751,0.1, + -0.303529,0.934173,0.187594,-0.17082,0,0.223606, + -0.30353,0.934173,0.187591,-0.072949,0.100406,-0.118034, + -0.30353,0.934173,0.187591,-0.038197,0.117557,-0.147214, + -0.30353,0.934173,0.187591,-0.138196,0.100406,-0.223606, + -0.303534,0.934173,0.187586,-0.038197,0.117557,-0.147214, + -0.303534,0.934173,0.187586,0,0.124108,-0.118034, + -0.303534,0.934173,0.187586,0.052786,0.162459,-0.223606, + -0.30353,0.934173,0.187591,0.11459,0.117557,0.1, + -0.30353,0.934173,0.187591,0.072949,0.100406,0.118034, + -0.30353,0.934173,0.187591,0.138196,0.100406,0.223606, + -0.303531,0.934173,0.187588,-0.161804,0.027751,0.1, + -0.303531,0.934173,0.187588,-0.158359,0.038352,0.052786, + -0.303531,0.934173,0.187588,-0.276393,0,0.052786, + -0.303524,0.934177,0.187583,0.123606,0.145308,-0.023607, + -0.303524,0.934177,0.187583,0.095491,0.131433,0, + -0.303524,0.934177,0.187583,0.223606,0.162459,0.052786, + -0.303535,0.934172,0.187588,-0.061803,0.044903,0.176394, + -0.303535,0.934172,0.187588,-0.069098,0.050203,0.138196, + -0.303535,0.934172,0.187588,-0.17082,0,0.223606, + -0.303531,0.934173,0.187592,-0.147214,0.072654,-0.1, + -0.303531,0.934173,0.187592,-0.111804,0.08123,-0.08541, + -0.303531,0.934173,0.187592,-0.138196,0.100406,-0.223606, + -0.303516,0.934178,0.18759,0.042705,0.131433,-0.08541, + -0.303516,0.934178,0.18759,0.076393,0.145308,-0.1, + -0.303516,0.934178,0.18759,0.052786,0.162459,-0.223606, + -0.303529,0.934174,0.187588,0.026393,0.08123,0.138196, + -0.303529,0.934174,0.187588,0.023607,0.072654,0.176394, + -0.303529,0.934174,0.187588,0.138196,0.100406,0.223606, + -0.30353,0.934172,0.187595,-0.154508,0.050203,0, + -0.30353,0.934172,0.187595,-0.18541,0.044903,-0.023607, + -0.30353,0.934172,0.187595,-0.276393,0,0.052786 +}; +static const struct gllist frame={GL_N3F_V3F,GL_TRIANGLES,1080,data,NULL}; +const struct gllist *tronbit_no=&frame; diff --git a/hacks/glx/tronbit_yes.c b/hacks/glx/tronbit_yes.c new file mode 100644 index 00000000..376e96c2 --- /dev/null +++ b/hacks/glx/tronbit_yes.c @@ -0,0 +1,31 @@ +/* yes = tetrahedron */ + +#include "gllist.h" +static const float data[]={ + 0.57735,0.57735,0.57735,0,0,0.5, + 0.57735,0.57735,0.57735,0.5,0,0, + 0.57735,0.57735,0.57735,0,0.5,0, + -0.57735,0.57735,0.57735,0,0,0.5, + -0.57735,0.57735,0.57735,0,0.5,0, + -0.57735,0.57735,0.57735,-0.5,0,0, + -0.57735,-0.57735,0.57735,0,0,0.5, + -0.57735,-0.57735,0.57735,-0.5,0,0, + -0.57735,-0.57735,0.57735,0,-0.5,0, + 0.57735,-0.57735,0.57735,0,0,0.5, + 0.57735,-0.57735,0.57735,0,-0.5,0, + 0.57735,-0.57735,0.57735,0.5,0,0, + 0.57735,-0.57735,-0.57735,0.5,0,0, + 0.57735,-0.57735,-0.57735,0,-0.5,0, + 0.57735,-0.57735,-0.57735,0,0,-0.5, + 0.57735,0.57735,-0.57735,0.5,0,0, + 0.57735,0.57735,-0.57735,0,0,-0.5, + 0.57735,0.57735,-0.57735,0,0.5,0, + -0.57735,0.57735,-0.57735,0,0.5,0, + -0.57735,0.57735,-0.57735,0,0,-0.5, + -0.57735,0.57735,-0.57735,-0.5,0,0, + -0.57735,-0.57735,-0.57735,-0.5,0,0, + -0.57735,-0.57735,-0.57735,0,0,-0.5, + -0.57735,-0.57735,-0.57735,0,-0.5,0 +}; +static const struct gllist frame={GL_N3F_V3F,GL_TRIANGLES,24,data,NULL}; +const struct gllist *tronbit_yes=&frame; diff --git a/hacks/glx/tube.c b/hacks/glx/tube.c new file mode 100644 index 00000000..b0e29e68 --- /dev/null +++ b/hacks/glx/tube.c @@ -0,0 +1,400 @@ +/* tube, Copyright (c) 2001-2012 Jamie Zawinski + * Utility functions to create tubes and cones in GL. + * + * 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. + */ + +#include + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include + +#ifndef HAVE_COCOA +# include +#endif + +#ifdef HAVE_JWZGLES +# include "jwzgles.h" +#endif /* HAVE_JWZGLES */ + +#include "tube.h" + +typedef struct { GLfloat x, y, z; } XYZ; + + +static int +unit_tube (int faces, int smooth, int caps_p, int wire_p) +{ + int i; + int polys = 0; + GLfloat step = M_PI * 2 / faces; + GLfloat s2 = step/2; + GLfloat th; + GLfloat x, y, x0=0, y0=0; + int z = 0; + + int arraysize, out; + struct { XYZ p; XYZ n; GLfloat s, t; } *array; + + arraysize = (faces+1) * 6; + array = (void *) calloc (arraysize, sizeof(*array)); + if (! array) abort(); + out = 0; + + + /* #### texture coords are currently not being computed */ + + + /* side walls + */ + th = 0; + x = 1; + y = 0; + + if (!smooth) + { + x0 = cos (s2); + y0 = sin (s2); + } + + if (smooth) faces++; + + for (i = 0; i < faces; i++) + { + array[out].p.x = x; /* bottom point A */ + array[out].p.y = 0; + array[out].p.z = y; + + if (smooth) + array[out].n = array[out].p; /* its own normal */ + else + { + array[out].n.x = x0; /* mid-plane normal */ + array[out].n.y = 0; + array[out].n.z = y0; + } + out++; + + + array[out].p.x = x; /* top point A */ + array[out].p.y = 1; + array[out].p.z = y; + array[out].n = array[out-1].n; /* same normal */ + out++; + + + th += step; + x = cos (th); + y = sin (th); + + if (!smooth) + { + x0 = cos (th + s2); + y0 = sin (th + s2); + + array[out].p.x = x; /* top point B */ + array[out].p.y = 1; + array[out].p.z = y; + array[out].n = array[out-1].n; /* same normal */ + out++; + + + array[out] = array[out-3]; /* bottom point A */ + out++; + + array[out] = array[out-2]; /* top point B */ + out++; + + array[out].p.x = x; /* bottom point B */ + array[out].p.y = 0; + array[out].p.z = y; + array[out].n = array[out-1].n; /* same normal */ + out++; + + polys++; + } + + polys++; + if (out >= arraysize) abort(); + } + + glEnableClientState (GL_VERTEX_ARRAY); + glEnableClientState (GL_NORMAL_ARRAY); + glEnableClientState (GL_TEXTURE_COORD_ARRAY); + + glVertexPointer (3, GL_FLOAT, sizeof(*array), &array[0].p); + glNormalPointer ( GL_FLOAT, sizeof(*array), &array[0].n); + glTexCoordPointer (2, GL_FLOAT, sizeof(*array), &array[0].s); + + glFrontFace(GL_CCW); + glDrawArrays ((wire_p ? GL_LINES : + (smooth ? GL_TRIANGLE_STRIP : GL_TRIANGLES)), + 0, out); + + + /* End caps + */ + if (caps_p) + for (z = 0; z <= 1; z++) + { + out = 0; + if (! wire_p) + { + array[out].p.x = 0; + array[out].p.y = z; + array[out].p.z = 0; + + array[out].n.x = 0; + array[out].n.y = (z == 0 ? -1 : 1); + array[out].n.z = 0; + out++; + } + + th = 0; + for (i = (z == 0 ? 0 : faces); + (z == 0 ? i <= faces : i >= 0); + i += (z == 0 ? 1 : -1)) { + GLfloat x = cos (th); + GLfloat y = sin (th); + + array[out] = array[0]; /* same normal and texture */ + array[out].p.x = x; + array[out].p.y = z; + array[out].p.z = y; + out++; + + th += (z == 0 ? step : -step); + + polys++; + if (out >= arraysize) abort(); + } + + glVertexPointer (3, GL_FLOAT, sizeof(*array), &array[0].p); + glNormalPointer ( GL_FLOAT, sizeof(*array), &array[0].n); + glTexCoordPointer (2, GL_FLOAT, sizeof(*array), &array[0].s); + + glFrontFace(GL_CCW); + glDrawArrays ((wire_p ? GL_LINE_LOOP : GL_TRIANGLE_FAN), 0, out); + } + + free(array); + + return polys; +} + + +static int +unit_cone (int faces, int smooth, int cap_p, int wire_p) +{ + int i; + int polys = 0; + GLfloat step = M_PI * 2 / faces; + GLfloat s2 = step/2; + GLfloat th; + GLfloat x, y, x0, y0; + + int arraysize, out; + struct { XYZ p; XYZ n; GLfloat s, t; } *array; + + arraysize = (faces+1) * 3; + array = (void *) calloc (arraysize, sizeof(*array)); + if (! array) abort(); + out = 0; + + + /* #### texture coords are currently not being computed */ + + + /* side walls + */ + + th = 0; + x = 1; + y = 0; + x0 = cos (s2); + y0 = sin (s2); + + for (i = 0; i < faces; i++) + { + array[out].p.x = x; /* bottom point A */ + array[out].p.y = 0; + array[out].p.z = y; + + if (smooth) + array[out].n = array[out].p; /* its own normal */ + else + { + array[out].n.x = x0; /* mid-plane normal */ + array[out].n.y = 0; + array[out].n.z = y0; + } + out++; + + + array[out].p.x = 0; /* tip point */ + array[out].p.y = 1; + array[out].p.z = 0; + + array[out].n.x = x0; /* mid-plane normal */ + array[out].n.y = 0; + array[out].n.z = y0; + out++; + + + th += step; + x0 = cos (th + s2); + y0 = sin (th + s2); + x = cos (th); + y = sin (th); + + array[out].p.x = x; /* bottom point B */ + array[out].p.y = 0; + array[out].p.z = y; + + if (smooth) + array[out].n = array[out].p; /* its own normal */ + else + array[out].n = array[out-1].n; /* same normal as other two */ + out++; + + + if (out >= arraysize) abort(); + polys++; + } + + glEnableClientState (GL_VERTEX_ARRAY); + glEnableClientState (GL_NORMAL_ARRAY); + glEnableClientState (GL_TEXTURE_COORD_ARRAY); + + glVertexPointer (3, GL_FLOAT, sizeof(*array), &array[0].p); + glNormalPointer ( GL_FLOAT, sizeof(*array), &array[0].n); + glTexCoordPointer (2, GL_FLOAT, sizeof(*array), &array[0].s); + + glFrontFace(GL_CCW); + glDrawArrays ((wire_p ? GL_LINES : GL_TRIANGLES), 0, out); + + + /* End cap + */ + if (cap_p) + { + out = 0; + + if (! wire_p) + { + array[out].p.x = 0; + array[out].p.y = 0; + array[out].p.z = 0; + + array[out].n.x = 0; + array[out].n.y = -1; + array[out].n.z = 0; + out++; + } + + for (i = 0, th = 0; i <= faces; i++) + { + GLfloat x = cos (th); + GLfloat y = sin (th); + + array[out] = array[0]; /* same normal and texture */ + array[out].p.x = x; + array[out].p.y = 0; + array[out].p.z = y; + out++; + th += step; + polys++; + if (out >= arraysize) abort(); + } + + glVertexPointer (3, GL_FLOAT, sizeof(*array), &array[0].p); + glNormalPointer ( GL_FLOAT, sizeof(*array), &array[0].n); + glTexCoordPointer (2, GL_FLOAT, sizeof(*array), &array[0].s); + + glFrontFace(GL_CCW); + glDrawArrays ((wire_p ? GL_LINE_LOOP : GL_TRIANGLE_FAN), 0, out); + } + + free (array); + + return polys; +} + + +static int +tube_1 (GLfloat x1, GLfloat y1, GLfloat z1, + GLfloat x2, GLfloat y2, GLfloat z2, + GLfloat diameter, GLfloat cap_size, + int faces, int smooth, int caps_p, int wire_p, + int cone_p) +{ + GLfloat length, X, Y, Z; + int polys = 0; + + if (diameter <= 0) abort(); + + X = (x2 - x1); + Y = (y2 - y1); + Z = (z2 - z1); + + if (X == 0 && Y == 0 && Z == 0) + return 0; + + length = sqrt (X*X + Y*Y + Z*Z); + + glPushMatrix(); + + glTranslatef(x1, y1, z1); + glRotatef (-atan2 (X, Y) * (180 / M_PI), 0, 0, 1); + glRotatef ( atan2 (Z, sqrt(X*X + Y*Y)) * (180 / M_PI), 1, 0, 0); + glScalef (diameter, length, diameter); + + /* extend the endpoints of the tube by the cap size in both directions */ + if (cap_size != 0) + { + GLfloat c = cap_size/length; + glTranslatef (0, -c, 0); + glScalef (1, 1+c+c, 1); + } + + if (cone_p) + polys = unit_cone (faces, smooth, caps_p, wire_p); + else + polys = unit_tube (faces, smooth, caps_p, wire_p); + + glPopMatrix(); + return polys; +} + + +int +tube (GLfloat x1, GLfloat y1, GLfloat z1, + GLfloat x2, GLfloat y2, GLfloat z2, + GLfloat diameter, GLfloat cap_size, + int faces, int smooth, int caps_p, int wire_p) +{ + return tube_1 (x1, y1, z1, x2, y2, z2, diameter, cap_size, + faces, smooth, caps_p, wire_p, + 0); +} + + +int +cone (GLfloat x1, GLfloat y1, GLfloat z1, + GLfloat x2, GLfloat y2, GLfloat z2, + GLfloat diameter, GLfloat cap_size, + int faces, int smooth, int cap_p, int wire_p) +{ + return tube_1 (x1, y1, z1, x2, y2, z2, diameter, cap_size, + faces, smooth, cap_p, wire_p, + 1); +} diff --git a/hacks/glx/tube.h b/hacks/glx/tube.h new file mode 100644 index 00000000..e3fff592 --- /dev/null +++ b/hacks/glx/tube.h @@ -0,0 +1,32 @@ +/* tube, Copyright (c) 2001, 2003, 2007 Jamie Zawinski + * Utility functions to create tubes and cones in GL. + * + * 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. + */ + +#ifndef __TUBE_H__ +#define __TUBE_H__ + +/* Renders a tube along the line described by the two points. + Returns the number of polygons used. + */ +extern int tube (GLfloat x1, GLfloat y1, GLfloat z1, + GLfloat x2, GLfloat y2, GLfloat z2, + GLfloat diameter, GLfloat cap_size, + int faces, int smooth, int caps_p, int wire_p); + +/* Renders a cone along the line described by the two points. + Returns the number of polygons used. + */ +extern int cone (GLfloat x1, GLfloat y1, GLfloat z1, + GLfloat x2, GLfloat y2, GLfloat z2, + GLfloat diameter, GLfloat cap_size, + int faces, int smooth, int cap_p, int wire_p); + +#endif /* __TUBE_H__ */ diff --git a/hacks/glx/tunnel_draw.c b/hacks/glx/tunnel_draw.c new file mode 100644 index 00000000..333161bb --- /dev/null +++ b/hacks/glx/tunnel_draw.c @@ -0,0 +1,512 @@ +/* -*- Mode: C; tab-width: 4 -*- */ +/* atunnels --- OpenGL Advanced Tunnel Demo */ + +#if 0 +static const char sccsid[] = "@(#)tunnel_draw.c 5.13 2004/05/25 xlockmore"; +#endif + +/* Copyright (c) E. Lassauge, 2002-2004. */ + +/* + * Permission to use, copy, modify, and distribute this software and its + * documentation for any purpose and without fee is hereby granted, + * provided that the above copyright notice appear in all copies and that + * both that copyright notice and this permission notice appear in + * supporting documentation. + * + * This file is provided AS IS with no warranties of any kind. The author + * shall have no liability with respect to the infringement of copyrights, + * trade secrets or any patents by this file or any part thereof. In no + * event will the author be liable for any lost revenue or profits or + * other special, indirect and consequential damages. + * + * The original code for this mode was written by Roman Podobedov + * Email: romka@ut.ee + * WEB: http://romka.demonews.com + * + * Eric Lassauge (May-25-2004) + * http://lassauge.free.fr/linux.html + * + * REVISION HISTORY: + * E.Lassauge - 25-May-2004: + * - added more texture + * - random texture init + * + */ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#ifdef USE_GL /* whole file */ + +#include +#include +#include + +#ifdef STANDALONE +# ifndef HAVE_COCOA +# include +# include +# endif +#endif + +#include "tunnel_draw.h" + +#ifdef STANDALONE /* For NRAND() */ +#include "xlockmoreI.h" /* in xscreensaver distribution */ +#else /* STANDALONE */ +#include "xlock.h" /* in xlockmore distribution */ +#endif /* STANDALONE */ + +typedef struct +{ + float x, y, z; /* Point coordinates */ +} cvPoint; + +typedef struct _tnPath +{ + cvPoint p; + struct _tnPath *next; +} tnPath; + + +static const cvPoint initpath[]={ +{0.000000, 0.000000, 0.000000}, +{2.000000, 1.000000, 0.000000}, +{4.000000, 0.000000, 0.000000}, +{6.000000, 1.000000, 0.000000}, +{8.000000, 0.000000, 1.000000}, +{10.000000, 1.000000, 1.000000}, +{12.000000, 1.500000, 0.000000}, +{14.000000, 0.000000, 0.000000}, +{16.000000, 1.000000, 0.000000}, +{18.000000, 0.000000, 0.000000}, +{20.000000, 0.000000, 1.000000}, +{22.000000, 1.000000, 0.000000}, +{24.000000, 0.000000, 1.000000}, +{26.000000, 0.000000, 1.000000}, +{28.000000, 1.000000, 0.000000}, +{30.000000, 0.000000, 2.000000}, +{32.000000, 1.000000, 0.000000}, +{34.000000, 0.000000, 2.000000}, +{-1.000000, -1.000000, -1.000000} +}; + + +struct tunnel_state { + + tnPath *path; + + float cam_t; /* Camera variables */ + tnPath *cam_pos; + float alpha; + + int tFlag; /* Tunnel Drawing Variables */ + cvPoint prev_points[10]; + int current_texture; + + float ModeX; /* Modes */ + int ModeXFlag; +}; + +/*=================== Vector normalization ==================================*/ +static void +normalize(cvPoint *V) +{ + float d; + + /* Vector length */ + d = (float)sqrt(V->x*V->x + V->y*V->y + V->z*V->z); + + /* Normalization */ + V->x /= d; + V->y /= d; + V->z /= d; +} +/*=================== C = A x B (Vector multiply) ==========================*/ +#if 0 +static void +vect_mult(cvPoint *A, cvPoint *B, cvPoint *C) +{ + /* Vector multiply */ + C->x = A->y*B->z - A->z*B->y; + C->y = A->z*B->x - A->x*B->z; + C->z = A->x*B->y - A->y*B->x; +} +#endif + +/* Catmull-Rom Curve calculations */ +static void +cvCatmullRom(cvPoint *p, float t, cvPoint *outp) +{ + float t2, t3, t1; + + t2 = t*t; + t3 = t*t*t; + t1 = (1-t)*(1-t); + + outp->x = (-t*t1*p[0].x + (2-5*t2+3*t3)*p[1].x + t*(1+4*t-3*t2)*p[2].x - t2*(1-t)*p[3].x)/2; + outp->y = (-t*t1*p[0].y + (2-5*t2+3*t3)*p[1].y + t*(1+4*t-3*t2)*p[2].y - t2*(1-t)*p[3].y)/2; + outp->z = (-t*t1*p[0].z + (2-5*t2+3*t3)*p[1].z + t*(1+4*t-3*t2)*p[2].z - t2*(1-t)*p[3].z)/2; +} + +/*=================== Point Rotating Around Line =========================== +// p - original point +// pp - pivot point +// pl - pivot line (vector) +// a - angle to rotate in radians +// outp - output point +//========================================================================== +*/ +static void +RotateAroundLine(cvPoint *p, cvPoint *pp, cvPoint *pl, float a, cvPoint *outp) +{ + cvPoint p1, p2; + float l, m, n, ca, sa; + + p1.x = p->x - pp->x; + p1.y = p->y - pp->y; + p1.z = p->z - pp->z; + + l = pl->x; + m = pl->y; + n = pl->z; + + ca = cos(a); + sa = sin(a); + + p2.x = p1.x*((l*l)+ca*(1-l*l)) + p1.y*(l*(1-ca)*m+n*sa) + p1.z*(l*(1-ca)*n-m*sa); + p2.y = p1.x*(l*(1-ca)*m-n*sa) + p1.y*(m*m+ca*(1-m*m)) + p1.z*(m*(1-ca)*n+l*sa); + p2.z = p1.x*(l*(1-ca)*n+m*sa) + p1.y*(m*(1-ca)*n-l*sa) + p1.z*(n*n+ca*(1-n*n)); + + outp->x = p2.x + pp->x; + outp->y = p2.y + pp->y; + outp->z = p2.z + pp->z; +} + + +/*=================== Load camera and tunnel path ==========================*/ +static void +LoadPath(struct tunnel_state *st) +{ + float x, y, z; + tnPath *path1=NULL, *path2=NULL; + + cvPoint *f = (cvPoint *)initpath; + + while (f->x != -1.0) + { + x = f->x; + y = f->y; + z = f->z; + f++; + + if (st->path == NULL) + { + st->path = (tnPath *)malloc(sizeof(tnPath)); + path1 = st->path; + } + else + { + if (!path1) path1 = st->path; + path2 = (tnPath *)malloc(sizeof(tnPath)); + path1->next = path2; + path1 = path2; + } + + path1->next = NULL; + path1->p.x = x; + path1->p.y = y; + path1->p.z = z; + } + + st->cam_pos = st->path; + st->cam_t = 0; +} + +/*=================== Tunnel Initialization ================================*/ +struct tunnel_state * +atunnel_InitTunnel(void) +{ + struct tunnel_state *st = (struct tunnel_state *) calloc (1, sizeof(*st)); + LoadPath(st); + st->current_texture = NRAND(MAX_TEXTURE); + return st; +} + +void +atunnel_DrawTunnel(struct tunnel_state *st, + int do_texture, int do_light, GLuint *textures) +{ + tnPath *p, *p1, *cmpos; + cvPoint op, p4[4], T, ppp, ppp1, op1, op2; + float t; + int i, j, k, flag; + cvPoint points[10]; + GLfloat light_position[4]; + + + /* Select current tunnel texture */ + if (do_texture) + glBindTexture(GL_TEXTURE_2D, textures[st->current_texture]); + + cmpos = st->cam_pos; + /* Get current curve */ + if (st->cam_pos->next && + st->cam_pos->next->next && + st->cam_pos->next->next->next) + { + p1 = st->cam_pos; + for (i=0; i<4; i++) + { + p4[i].x = p1->p.x; + p4[i].y = p1->p.y; + p4[i].z = p1->p.z; + p1 = p1->next; + } + } + else + { + /* End of tunnel */ + st->ModeX = 1.0; + st->ModeXFlag = 0; + return; + }; + + /* Get current camera position */ + cvCatmullRom(p4, st->cam_t, &op); + + /* Next camera position */ + st->cam_t += 0.02f; + if (st->cam_t >= 1) + { + st->cam_t = st->cam_t - 1; + cmpos = st->cam_pos->next; + } + + /* Get curve for next camera position */ + if (cmpos->next->next->next) + { + p1 = cmpos; + for (i=0; i<4; i++) + { + p4[i].x = p1->p.x; + p4[i].y = p1->p.y; + p4[i].z = p1->p.z; + p1 = p1->next; + } + } + else + { + /* End of tunnel */ + st->ModeX = 1.0; + st->ModeXFlag = 0; + return; + } + + /* Get next camera position */ + cvCatmullRom(p4, st->cam_t, &op1); + + /* Rotate camera */ + glRotatef(st->alpha, 0, 0, -1); + st->alpha += 1; + /* Set camera position */ + gluLookAt(op.x, op.y, op.z, op1.x, op1.y, op1.z, 0, 1, 0); + + /* Set light position */ + if (do_light) + { + light_position[0] = op.x; + light_position[1] = op.y; + light_position[2] = op.z; + light_position[3] = 1; + glLightfv(GL_LIGHT0, GL_POSITION, light_position); + } + + p = st->cam_pos; + flag = 0; + t = 0; + k = 0; + /* Draw tunnel from current curve and next 2 curves */ + glBegin(GL_QUADS); + while (k < 3) + { + if (p->next->next->next) + { + p1 = p; + for (i=0; i<4; i++) + { + p4[i].x = p1->p.x; + p4[i].y = p1->p.y; + p4[i].z = p1->p.z; + p1 = p1->next; + } + } + else + { + /* End of tunnel */ + st->ModeX = 1.0; + st->ModeXFlag = 0; + glEnd(); + return; + } + cvCatmullRom(p4, t, &op); + + ppp.x = op.x; + ppp.y = op.y; + ppp.z = op.z + 0.25; + + t += 0.1; + if (t >= 1.0) + { + t = t - 1; + k++; + p = p->next; + } + + if (p->next->next->next) + { + p1 = p; + for (i=0; i<4; i++) + { + p4[i].x = p1->p.x; + p4[i].y = p1->p.y; + p4[i].z = p1->p.z; + p1 = p1->next; + } + } + else + { + /* End of tunnel */ + st->ModeX = 1.0; + st->ModeXFlag = 0; + glEnd(); + return; + } + + cvCatmullRom(p4, t, &op1); + + ppp1.x = op1.x; + ppp1.y = op1.y; + ppp1.z = op1.z + 0.25; + + T.x = op1.x - op.x; + T.y = op1.y - op.y; + T.z = op1.z - op.z; + + normalize(&T); + + for (i=0; i<10; i++) + { + RotateAroundLine(&ppp, &op, &T, ((float)i*36.0*M_PI/180.0), &op2); + points[i].x = op2.x; + points[i].y = op2.y; + points[i].z = op2.z; + if (!flag) + { + st->prev_points[i].x = op2.x; + st->prev_points[i].y = op2.y; + st->prev_points[i].z = op2.z; + } + } + + if (!flag) + { + flag = 1; + continue; + } + + /* Draw 10 polygons for current point */ + for (i=0; i<10; i++) + { + j = i+1; + if (j > 9) j = 0; + glNormal3f(0, 0, 1); /* Normal for lighting */ + glTexCoord2f(0, 0); glVertex3f(st->prev_points[i].x, st->prev_points[i].y, st->prev_points[i].z); + glNormal3f(0, 0, 1); + glTexCoord2f(1, 0); glVertex3f(points[i].x, points[i].y, points[i].z); + glNormal3f(0, 0, 1); + glTexCoord2f(1, 1); glVertex3f(points[j].x, points[j].y, points[j].z); + glNormal3f(0, 0, 1); + glTexCoord2f(0, 1); glVertex3f(st->prev_points[j].x, st->prev_points[j].y, st->prev_points[j].z); + } + /* Save current polygon coordinates for next position */ + for (i=0; i<10; i++) + { + st->prev_points[i].x = points[i].x; + st->prev_points[i].y = points[i].y; + st->prev_points[i].z = points[i].z; + } + } + glEnd(); + st->cam_pos = cmpos; +} + +/* =================== Show splash screen =================================== */ +void +atunnel_SplashScreen(struct tunnel_state *st, + int do_wire, int do_texture, int do_light) +{ + if (st->ModeX > 0) + { + /* Reset tunnel and camera position */ + if (!st->ModeXFlag) + { + st->cam_pos = st->path; + st->cam_t = 0; + st->tFlag = 0; + st->ModeXFlag = 1; + st->current_texture++; + if (st->current_texture >= MAX_TEXTURE) st->current_texture = 0; + } + /* Now we want to draw splash screen */ + glLoadIdentity(); + /* Disable all unused features */ + glDisable(GL_DEPTH_TEST); + glDisable(GL_LIGHTING); + glDisable(GL_FOG); + glDisable(GL_CULL_FACE); + + glBlendFunc(GL_SRC_ALPHA, GL_DST_ALPHA); + glEnable(GL_BLEND); + glDisable(GL_TEXTURE_2D); + glColor4f(1, 1, 1, st->ModeX); + + /* Draw splash screen (simply quad) */ + glBegin(GL_QUADS); + glVertex3f(-10, -10, -1); + glVertex3f(10, -10, -1); + glVertex3f(10, 10, -1); + glVertex3f(-10, 10, -1); + glEnd(); + + st->ModeX -= 0.05; + if (st->ModeX <= 0) st->ModeX = 0; + + if (!do_wire) + { + glEnable(GL_CULL_FACE); + glEnable(GL_DEPTH_TEST); + } + if (do_light) + { + glEnable(GL_LIGHTING); + glEnable(GL_FOG); + } + if (do_texture) + { + glEnable(GL_TEXTURE_2D); + } + glDisable(GL_BLEND); + glColor4f(1, 1, 1, 1); + } +} + +void +atunnel_FreeTunnel(struct tunnel_state *st) +{ + free (st); +} + +#endif diff --git a/hacks/glx/tunnel_draw.h b/hacks/glx/tunnel_draw.h new file mode 100644 index 00000000..643b9584 --- /dev/null +++ b/hacks/glx/tunnel_draw.h @@ -0,0 +1,11 @@ +#define MAX_TEXTURE 10 + +struct tunnel_state; + +extern struct tunnel_state * atunnel_InitTunnel(void); +extern void atunnel_DrawTunnel(struct tunnel_state *, + int do_texture, int do_light, GLuint *textures); +extern void atunnel_SplashScreen(struct tunnel_state *, + int do_wire, int do_texture, int do_light); +extern void atunnel_FreeTunnel(struct tunnel_state *); + diff --git a/hacks/glx/voronoi.c b/hacks/glx/voronoi.c new file mode 100644 index 00000000..b207bbc0 --- /dev/null +++ b/hacks/glx/voronoi.c @@ -0,0 +1,506 @@ +/* voronoi, Copyright (c) 2007, 2008 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. + */ + +#define DEFAULTS "*delay: 20000 \n" \ + "*showFPS: False \n" \ + + +# define refresh_voronoi 0 +# define release_voronoi 0 +#undef countof +#define countof(x) (sizeof((x))/sizeof((*x))) + +#define BELLRAND(n) ((frand((n)) + frand((n)) + frand((n))) / 3) + + +#include "xlockmore.h" +#include + +#ifdef USE_GL /* whole file */ + +#define DEF_POINTS "25" +#define DEF_POINT_SIZE "9" +#define DEF_POINT_SPEED "1.0" +#define DEF_POINT_DELAY "0.05" +#define DEF_ZOOM_SPEED "1.0" +#define DEF_ZOOM_DELAY "15" + +typedef struct node { + GLfloat x, y; + GLfloat dx, dy; + GLfloat ddx, ddy; + struct node *next; + GLfloat color[4], color2[4]; + int rot; +} node; + +typedef struct { + GLXContext *glx_context; + node *nodes; + int nnodes; + node *dragging; + int ncolors; + XColor *colors; + + enum { MODE_WAITING, MODE_ADDING, MODE_ZOOMING } mode; + int adding; + double last_time; + + GLfloat zooming; /* 1.0 starting zoom, 0.0 no longer zooming. */ + GLfloat zoom_toward[2]; + +} voronoi_configuration; + +static voronoi_configuration *vps = NULL; + +/* command line arguments */ +static int npoints; +static GLfloat point_size, point_speed, point_delay; +static GLfloat zoom_speed, zoom_delay; + +static XrmOptionDescRec opts[] = { + { "-points", ".points", XrmoptionSepArg, 0 }, + { "-point-size", ".pointSize", XrmoptionSepArg, 0 }, + { "-point-speed", ".pointSpeed", XrmoptionSepArg, 0 }, + { "-point-delay", ".pointDelay", XrmoptionSepArg, 0 }, + { "-zoom-speed", ".zoomSpeed", XrmoptionSepArg, 0 }, + { "-zoom-delay", ".zoomDelay", XrmoptionSepArg, 0 }, +}; + +static argtype vars[] = { + {&npoints, "points", "Points", DEF_POINTS, t_Int}, + {&point_size, "pointSize", "PointSize", DEF_POINT_SIZE, t_Float}, + {&point_speed, "pointSpeed", "PointSpeed", DEF_POINT_SPEED, t_Float}, + {&point_delay, "pointDelay", "PointDelay", DEF_POINT_DELAY, t_Float}, + {&zoom_speed, "zoomSpeed", "ZoomSpeed", DEF_ZOOM_SPEED, t_Float}, + {&zoom_delay, "zoomDelay", "ZoomDelay", DEF_ZOOM_DELAY, t_Float}, +}; + +ENTRYPOINT ModeSpecOpt voronoi_opts = + {countof(opts), opts, countof(vars), vars, NULL}; + + +/* Returns the current time in seconds as a double. + */ +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 node * +add_node (voronoi_configuration *vp, GLfloat x, GLfloat y) +{ + node *nn = (node *) calloc (1, sizeof (*nn)); + int i; + nn->x = x; + nn->y = y; + + i = random() % vp->ncolors; + nn->color[0] = vp->colors[i].red / 65536.0; + nn->color[1] = vp->colors[i].green / 65536.0; + nn->color[2] = vp->colors[i].blue / 65536.0; + nn->color[3] = 1.0; + + nn->color2[0] = nn->color[0] * 0.7; + nn->color2[1] = nn->color[1] * 0.7; + nn->color2[2] = nn->color[2] * 0.7; + nn->color2[3] = 1.0; + + nn->ddx = frand (0.000001 * point_speed) * (random() & 1 ? 1 : -1); + nn->ddy = frand (0.000001 * point_speed) * (random() & 1 ? 1 : -1); + + nn->rot = (random() % 360) * (random() & 1 ? 1 : -1); + + nn->next = vp->nodes; + vp->nodes = nn; + vp->nnodes++; + return nn; +} + + +static int +cone (void) +{ + int i; + int faces = 64; + GLfloat step = M_PI * 2 / faces; + GLfloat th = 0; + GLfloat x = 1; + GLfloat y = 0; + + glBegin(GL_TRIANGLE_FAN); + glVertex3f (0, 0, 1); + for (i = 0; i < faces; i++) + { + glVertex3f (x, y, 0); + th += step; + x = cos (th); + y = sin (th); + } + glVertex3f (1, 0, 0); + glEnd(); + return faces; +} + + +static void +move_points (voronoi_configuration *vp) +{ + node *nn; + for (nn = vp->nodes; nn; nn = nn->next) + { + if (nn == vp->dragging) continue; + nn->x += nn->dx; + nn->y += nn->dy; + + if (vp->mode == MODE_WAITING) + { + nn->dx += nn->ddx; + nn->dy += nn->ddy; + } + } +} + + +static void +prune_points (voronoi_configuration *vp) +{ + node *nn; + node *prev = 0; + int lim = 5; + + for (nn = vp->nodes; nn; prev = nn, nn = (nn ? nn->next : 0)) + if (nn->x < -lim || nn->x > lim || + nn->y < -lim || nn->y > lim) + { + if (prev) + prev->next = nn->next; + else + vp->nodes = nn->next; + free (nn); + vp->nnodes--; + nn = prev; + } +} + + +static void +zoom_points (voronoi_configuration *vp) +{ + node *nn; + + GLfloat tick = sin (vp->zooming * M_PI); + GLfloat scale = 1 + (tick * 0.02 * zoom_speed); + + vp->zooming -= (0.01 * zoom_speed); + if (vp->zooming < 0) vp->zooming = 0; + + if (vp->zooming <= 0) return; + + if (scale < 1) scale = 1; + + for (nn = vp->nodes; nn; nn = nn->next) + { + GLfloat x = nn->x - vp->zoom_toward[0]; + GLfloat y = nn->y - vp->zoom_toward[1]; + x *= scale; + y *= scale; + nn->x = x + vp->zoom_toward[0]; + nn->y = y + vp->zoom_toward[1]; + } +} + + + +static void +draw_cells (ModeInfo *mi) +{ + voronoi_configuration *vp = &vps[MI_SCREEN(mi)]; + node *nn; + int lim = 5; + + for (nn = vp->nodes; nn; nn = nn->next) + { + if (nn->x < -lim || nn->x > lim || + nn->y < -lim || nn->y > lim) + continue; + + glPushMatrix(); + glTranslatef (nn->x, nn->y, 0); + glScalef (lim*2, lim*2, 1); + glColor4fv (nn->color); + mi->polygon_count += cone (); + glPopMatrix(); + } + + glClear (GL_DEPTH_BUFFER_BIT); + + if (point_size <= 0) + ; + else if (point_size < 3) + { + glPointSize (point_size); + for (nn = vp->nodes; nn; nn = nn->next) + { + glBegin (GL_POINTS); + glColor4fv (nn->color2); + glVertex2f (nn->x, nn->y); + glEnd(); + mi->polygon_count++; + } + } + else + { + for (nn = vp->nodes; nn; nn = nn->next) + { + int w = MI_WIDTH (mi); + int h = MI_HEIGHT (mi); + int s = point_size; + int i; + + glColor4fv (nn->color2); + glPushMatrix(); + glTranslatef (nn->x, nn->y, 0); + glScalef (1.0 / w * s, 1.0 / h * s, 1); + + glLineWidth (point_size / 10); + nn->rot += (nn->rot < 0 ? -1 : 1); + glRotatef (nn->rot, 0, 0, 1); + + glRotatef (180, 0, 0, 1); + for (i = 0; i < 5; i++) + { + glBegin (GL_TRIANGLES); + glVertex2f (0, 1); + glVertex2f (-0.2, 0); + glVertex2f ( 0.2, 0); + glEnd (); + glRotatef (360.0/5, 0, 0, 1); + mi->polygon_count++; + } + glPopMatrix(); + } + } +} + + +/* Window management, etc + */ +ENTRYPOINT void +reshape_voronoi (ModeInfo *mi, int width, int height) +{ +/* voronoi_configuration *vp = &vps[MI_SCREEN(mi)];*/ + + glViewport (0, 0, (GLint) width, (GLint) height); + + glMatrixMode(GL_PROJECTION); + glLoadIdentity(); + glOrtho (0, 1, 1, 0, -1, 1); + + glMatrixMode(GL_MODELVIEW); + glLoadIdentity(); + + glClear(GL_COLOR_BUFFER_BIT); +} + + +static node * +find_node (ModeInfo *mi, GLfloat x, GLfloat y) +{ + voronoi_configuration *vp = &vps[MI_SCREEN(mi)]; + int ps = (point_size < 5 ? 5 : point_size); + GLfloat hysteresis = (1.0 / MI_WIDTH (mi)) * ps; + node *nn; + for (nn = vp->nodes; nn; nn = nn->next) + if (nn->x > x - hysteresis && nn->x < x + hysteresis && + nn->y > y - hysteresis && nn->y < y + hysteresis) + return nn; + return 0; +} + + +ENTRYPOINT Bool +voronoi_handle_event (ModeInfo *mi, XEvent *event) +{ + voronoi_configuration *vp = &vps[MI_SCREEN(mi)]; + + if (event->xany.type == ButtonPress) + { + GLfloat x = (GLfloat) event->xbutton.x / MI_WIDTH (mi); + GLfloat y = (GLfloat) event->xbutton.y / MI_HEIGHT (mi); + node *nn = find_node (mi, x, y); + if (!nn) + nn = add_node (vp, x, y); + vp->dragging = nn; + + return True; + } + else if (event->xany.type == ButtonRelease && vp->dragging) + { + vp->dragging = 0; + return True; + } + else if (event->xany.type == MotionNotify && vp->dragging) + { + vp->dragging->x = (GLfloat) event->xmotion.x / MI_WIDTH (mi); + vp->dragging->y = (GLfloat) event->xmotion.y / MI_HEIGHT (mi); + return True; + } + + return False; +} + +static void +state_change (ModeInfo *mi) +{ + voronoi_configuration *vp = &vps[MI_SCREEN(mi)]; + double now = double_time(); + + if (vp->dragging) + { + vp->last_time = now; + vp->adding = 0; + vp->zooming = 0; + return; + } + + switch (vp->mode) + { + case MODE_WAITING: + if (vp->last_time + zoom_delay <= now) + { + node *tn = vp->nodes; + vp->zoom_toward[0] = (tn ? tn->x : 0.5); + vp->zoom_toward[1] = (tn ? tn->y : 0.5); + + vp->mode = MODE_ZOOMING; + vp->zooming = 1; + + vp->last_time = now; + } + break; + + case MODE_ADDING: + if (vp->last_time + point_delay <= now) + { + add_node (vp, + BELLRAND(0.5) + 0.25, + BELLRAND(0.5) + 0.25); + vp->last_time = now; + vp->adding--; + if (vp->adding <= 0) + { + vp->adding = 0; + vp->mode = MODE_WAITING; + vp->last_time = now; + } + } + break; + + case MODE_ZOOMING: + { + zoom_points (vp); + if (vp->zooming <= 0) + { + vp->mode = MODE_ADDING; + vp->adding = npoints; + vp->last_time = now; + } + } + break; + + default: + abort(); + } +} + + +ENTRYPOINT void +init_voronoi (ModeInfo *mi) +{ + voronoi_configuration *vp; + + if (!vps) { + vps = (voronoi_configuration *) + calloc (MI_NUM_SCREENS(mi), sizeof (voronoi_configuration)); + if (!vps) { + fprintf(stderr, "%s: out of memory\n", progname); + exit(1); + } + } + + vp = &vps[MI_SCREEN(mi)]; + + vp->glx_context = init_GL(mi); + + if (point_size < 0) point_size = 10; + + vp->ncolors = 128; + vp->colors = (XColor *) calloc (vp->ncolors, sizeof(XColor)); + make_smooth_colormap (0, 0, 0, + vp->colors, &vp->ncolors, + False, False, False); + + reshape_voronoi (mi, MI_WIDTH(mi), MI_HEIGHT(mi)); + + vp->mode = MODE_ADDING; + vp->adding = npoints * 2; + vp->last_time = 0; +} + + +ENTRYPOINT void +draw_voronoi (ModeInfo *mi) +{ + voronoi_configuration *vp = &vps[MI_SCREEN(mi)]; + Display *dpy = MI_DISPLAY(mi); + Window window = MI_WINDOW(mi); + + if (!vp->glx_context) + return; + + glXMakeCurrent(MI_DISPLAY(mi), MI_WINDOW(mi), *(vp->glx_context)); + + glShadeModel(GL_FLAT); + glEnable(GL_POINT_SMOOTH); +/* glEnable(GL_LINE_SMOOTH);*/ +/* glEnable(GL_POLYGON_SMOOTH);*/ + + glEnable (GL_DEPTH_TEST); + glDepthFunc (GL_LEQUAL); + + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + + mi->polygon_count = 0; + draw_cells (mi); + move_points (vp); + prune_points (vp); + state_change (mi); + + if (mi->fps_p) do_fps (mi); + glFinish(); + + glXSwapBuffers(dpy, window); +} + +XSCREENSAVER_MODULE ("Voronoi", voronoi) + +#endif /* USE_GL */ diff --git a/hacks/glx/voronoi.man b/hacks/glx/voronoi.man new file mode 100644 index 00000000..713f08cf --- /dev/null +++ b/hacks/glx/voronoi.man @@ -0,0 +1,88 @@ +.TH XScreenSaver 1 "" "X Version 11" +.SH NAME +voronoi - draws a randomly-colored Voronoi tessellation +.SH SYNOPSIS +.B voronoi +[\-display \fIhost:display.screen\fP] +[\-visual \fIvisual\fP] +[\-window] +[\-root] +[\-points \fIint\fP] +[\-point\-size \fIint\fP] +[\-point\-speed \fIratio\fP] +[\-point\-delay \fIseconds\fP] +[\-zoom\-speed \fIratio\fP] +[\-zoom\-delay \fIseconds\fP] +[\-fps] +.SH DESCRIPTION +Draws a randomly-colored Voronoi tessellation, and periodically zooms +in and adds new points. The existing points also wander around. + +There are a set of control points on the plane, each at the center of +a colored cell. Every pixel within that cell is closer to that cell's +control point than to any other control point. That is what +determines the cell's shapes. + +When running in a window, you can click to insert a new point at +the mouse position. Clicking on an existing point lets you drag +it around. + +This implementation takes advantage of the OpenGL depth buffer to +compute the cells for us, by rendering the intersection of overlapping +cones in an orthographic plane. +.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 \-points \fIint\fP +How many points to add each time we zoom in. +.TP 8 +.B \-point\-size \fIint\fP +How big to draw the stars, in pixels. 0 for no stars. +.TP 8 +.B \-point\-speed \fIratio\fP +How fast the points should wander. +Less than 1 for slower, greater than 1 for faster. +.TP 8 +.B \-point\-delay \fIseconds\fP +How quickly to insert new points, when adding. +.TP 8 +.B \-zoom\-speed \fIratio\fP +How fast to zoom in. +Less than 1 for slower, greater than 1 for faster. +.TP 8 +.B \-zoom\-delay \fIseconds\fP +Zoom in every this-many seconds. +.TP 8 +.B \-fps +Display the current frame rate, CPU load, and polygon count. +.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 2007 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/glx/vrml2gl.pl b/hacks/glx/vrml2gl.pl new file mode 100755 index 00000000..84dc4ccf --- /dev/null +++ b/hacks/glx/vrml2gl.pl @@ -0,0 +1,361 @@ +#!/usr/bin/perl -w +# Copyright © 2003-2011 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. +# +# Reads a VRML WRL file, and emits C data suitable for use with OpenGL's +# glInterleavedArrays() and glDrawArrays() routines. +# +# Face normals are computed. +# +# Options: +# +# --normalize Compute the bounding box of the object, and scale all +# coordinates so that the object fits inside a unit cube. +# +# Created: 8-Mar-2003 for Wavefront OBJ, converted to VRML 27-Sep-2011. + +require 5; +use diagnostics; +use strict; + +my $progname = $0; $progname =~ s@.*/@@g; +my $version = q{ $Revision: 1.1 $ }; $version =~ s/^[^0-9]+([0-9.]+).*$/$1/; + +my $verbose = 0; + + +# convert a vector to a unit vector +sub normalize($$$) { + my ($x, $y, $z) = @_; + my $L = sqrt (($x * $x) + ($y * $y) + ($z * $z)); + if ($L != 0) { + $x /= $L; + $y /= $L; + $z /= $L; + } else { + $x = $y = $z = 0; + } + return ($x, $y, $z); +} + + +# Calculate the unit normal at p0 given two other points p1,p2 on the +# surface. The normal points in the direction of p1 crossproduct p2. +# +sub face_normal($$$$$$$$$) { + my ($p0x, $p0y, $p0z, + $p1x, $p1y, $p1z, + $p2x, $p2y, $p2z) = @_; + + my ($nx, $ny, $nz); + my ($pax, $pay, $paz); + my ($pbx, $pby, $pbz); + + $pax = $p1x - $p0x; + $pay = $p1y - $p0y; + $paz = $p1z - $p0z; + $pbx = $p2x - $p0x; + $pby = $p2y - $p0y; + $pbz = $p2z - $p0z; + $nx = $pay * $pbz - $paz * $pby; + $ny = $paz * $pbx - $pax * $pbz; + $nz = $pax * $pby - $pay * $pbx; + + return (normalize ($nx, $ny, $nz)); +} + + +sub parse_vrml_1($$$) { + my ($filename, $body, $normalize_p) = @_; + + my @verts = (); # list of refs of coords, [x, y, z] + my @faces = (); # list of refs of [ point, point, point, ... ] + # where 'point' is a list of indexes into 'verts'. + + $body =~ s% \b point \s* \[ (.*?) \] %{ + foreach my $point (split (/,/, $1)) { + $point =~ s/^\s+|\s+$//gsi; + next unless $point; + my @p = split(/\s+/, $point); + push @verts, \@p; + } + }%gsexi; + + $body =~ s% \b coordIndex \s* \[ (.*?) \] %{ + foreach my $face (split (/\s*,-1,?\s*/, $1)) { + $face =~ s/^\s+|\s+$//gsi; + next unless $face; + my @p = split(/\s*,\s*/, $face); + push @faces, \@p; + } + }%gsexi; + + return () if ($#verts < 0); + + # generate interleaved list of triangle coordinates and normals + # + my @triangles = (); + my $nfaces = $#faces+1; + + foreach my $f (@faces) { + # $f is [ p1, p2, p3, ... ] + + my @f = @$f; + + error ("too few points in face") if ($#f < 2); + my $p1 = shift @f; + + # If there are more than 3 points, do a triangle fan from the first one: + # [1 2 3] [1 3 4] [1 4 5] etc. Doesn't always work with convex shapes. + + while ($#f) { + my $p2 = shift @f; + my $p3 = $f[0]; + + my ($pp1, $pp2, $pp3) = ($p1, $p2, $p3); + # Reverse the winding order. +# ($pp1, $pp2, $pp3) = ($pp3, $pp2, $pp1); + + my $x1 = $verts[$pp1]->[0]; + my $y1 = $verts[$pp1]->[1]; + my $z1 = $verts[$pp1]->[2]; + + my $x2 = $verts[$pp2]->[0]; + my $y2 = $verts[$pp2]->[1]; + my $z2 = $verts[$pp2]->[2]; + + my $x3 = $verts[$pp3]->[0]; + my $y3 = $verts[$pp3]->[1]; + my $z3 = $verts[$pp3]->[2]; + + error ("missing points in face") unless defined($z3); + + my ($nx, $ny, $nz) = face_normal ($x1, $y1, $z1, + $x2, $y2, $z2, + $x3, $y3, $z3); + + push @triangles, [$nx, $ny, $nz, $x1, $y1, $z1, + $nx, $ny, $nz, $x2, $y2, $z2, + $nx, $ny, $nz, $x3, $y3, $z3]; + } + } + + return (@triangles); +} + + +sub parse_vrml($$$) { + my ($filename, $body, $normalize_p) = @_; + + my @triangles = (); + + $body =~ s/\s*\#.*$//gmi; # comments + + # Lose 2D imagery + $body =~ s/\bIndexedLineSet \s* { \s* coordIndex \s* \[ .*? \] \s* }//gsix; + + $body =~ s/(\bSeparator\b)/\001$1/g; + + foreach my $sec (split (m/\001/, $body)) { + push @triangles, parse_vrml_1 ($filename, $sec, $normalize_p); + } + + + # find bounding box, and normalize + # + if ($normalize_p || $verbose) { + my $minx = 999999999; + my $miny = 999999999; + my $minz = 999999999; + my $maxx = -999999999; + my $maxy = -999999999; + my $maxz = -999999999; + my $i = 0; + + foreach my $t (@triangles) { + my ($nx1, $ny1, $nz1, $x1, $y1, $z1, + $nx2, $ny2, $nz2, $x2, $y2, $z2, + $nx3, $ny3, $nz3, $x3, $y3, $z3) = @$t; + + foreach my $x ($x1, $x2, $x3) { + $minx = $x if ($x < $minx); + $maxx = $x if ($x > $maxx); + } + foreach my $y ($y1, $y2, $y3) { + $miny = $y if ($y < $miny); + $maxy = $y if ($y > $maxy); + } + foreach my $z ($z1, $z2, $z3) { + $minz = $z if ($z < $minz); + $maxz = $z if ($z > $maxz); + } + } + + my $w = ($maxx - $minx); + my $h = ($maxy - $miny); + my $d = ($maxz - $minz); + my $sizea = ($w > $h ? $w : $h); + my $sizeb = ($w > $d ? $w : $d); + my $size = ($sizea > $sizeb ? $sizea : $sizeb); + + print STDERR "$progname: bbox is " . + sprintf("%.2f x %.2f x %.2f\n", $w, $h, $d) + if ($verbose); + + if ($normalize_p) { + $w /= $size; + $h /= $size; + $d /= $size; + print STDERR "$progname: dividing by $size for bbox of " . + sprintf("%.2f x %.2f x %.2f\n", $w, $h, $d) + if ($verbose); + + foreach my $t (@triangles) { + my @t = @$t; + $t[3] /= $size; $t[4] /= $size; $t[5] /= $size; + $t[9] /= $size; $t[10] /= $size; $t[11] /= $size; + $t[15] /= $size; $t[16] /= $size; $t[17] /= $size; + $t = \@t; + } + } + } + + return @triangles; +} + + +sub generate_c($@) { + my ($filename, @triangles) = @_; + + my $code = ''; + + $code .= "#include \"gllist.h\"\n"; + $code .= "static const float data[]={\n"; + + my $nfaces = $#triangles + 1; + my $npoints = $nfaces * 3; + + foreach my $t (@triangles) { + my ($nx1, $ny1, $nz1, $x1, $y1, $z1, + $nx2, $ny2, $nz2, $x2, $y2, $z2, + $nx3, $ny3, $nz3, $x3, $y3, $z3) = @$t; + my $lines = sprintf("\t" . "%.6f,%.6f,%.6f," . "%.6f,%.6f,%.6f,\n" . + "\t" . "%.6f,%.6f,%.6f," . "%.6f,%.6f,%.6f,\n" . + "\t" . "%.6f,%.6f,%.6f," . "%.6f,%.6f,%.6f,\n", + $nx1, $ny1, $nz1, $x1, $y1, $z1, + $nx2, $ny2, $nz2, $x2, $y2, $z2, + $nx3, $ny3, $nz3, $x3, $y3, $z3); + $lines =~ s/([.\d])0+,/$1,/g; # lose trailing insignificant zeroes + $lines =~ s/\.,/,/g; + $lines =~ s/-0,/0,/g; + + $code .= $lines; + } + + my $token = $filename; # guess at a C token from the filename + $token =~ s/\<[^<>]*\>//; + $token =~ s@^.*/@@; + $token =~ s/\.[^.]*$//; + $token =~ s/[^a-z\d]/_/gi; + $token =~ s/__+/_/g; + $token =~ s/^_//g; + $token =~ s/_$//g; + $token =~ tr [A-Z] [a-z]; + $token = 'foo' if ($token eq ''); + + my $format = 'GL_N3F_V3F'; + my $primitive = 'GL_TRIANGLES'; + + $code =~ s/,\n$//s; + $code .= "\n};\n"; + $code .= "static const struct gllist frame={"; + $code .= "$format,$primitive,$npoints,data,NULL};\n"; + $code .= "const struct gllist *$token=&frame;\n"; + + print STDERR "$filename: " . + (($#triangles+1)*3) . " points, " . + (($#triangles+1)) . " faces.\n" + if ($verbose); + + return $code; +} + + +sub vrml_to_gl($$$) { + my ($infile, $outfile, $normalize_p) = @_; + my $body = ''; + + my $in; + if ($infile eq '-') { + $in = *STDIN; + } else { + open ($in, '<', $infile) || error ("$infile: $!"); + } + my $filename = ($infile eq '-' ? "" : $infile); + print STDERR "$progname: reading $filename...\n" + if ($verbose); + while (<$in>) { $body .= $_; } + close $in; + + $body =~ s/\r\n/\n/g; # CRLF -> LF + $body =~ s/\r/\n/g; # CR -> LF + + my @triangles = parse_vrml ($filename, $body, $normalize_p); + + $filename = ($outfile eq '-' ? "" : $outfile); + my $code = generate_c ($filename, @triangles); + + my $out; + if ($outfile eq '-') { + $out = *STDOUT; + } else { + open ($out, '>', $outfile) || error ("$outfile: $!"); + } + (print $out $code) || error ("$filename: $!"); + (close $out) || error ("$filename: $!"); + + print STDERR "$progname: wrote $filename\n" + if ($verbose || $outfile ne '-'); +} + + +sub error { + ($_) = @_; + print STDERR "$progname: $_\n"; + exit 1; +} + +sub usage { + print STDERR "usage: $progname [--verbose] [infile [outfile]]\n"; + exit 1; +} + +sub main { + my ($infile, $outfile); + my $normalize_p = 0; + while ($_ = $ARGV[0]) { + shift @ARGV; + if ($_ eq "--verbose") { $verbose++; } + elsif (m/^-v+$/) { $verbose += length($_)-1; } + elsif ($_ eq "--normalize") { $normalize_p = 1; } + elsif (m/^-./) { usage; } + elsif (!defined($infile)) { $infile = $_; } + elsif (!defined($outfile)) { $outfile = $_; } + else { usage; } + } + + $infile = "-" unless defined ($infile); + $outfile = "-" unless defined ($outfile); + + vrml_to_gl ($infile, $outfile, $normalize_p); +} + +main; +exit 0; diff --git a/hacks/glx/wfront2gl.pl b/hacks/glx/wfront2gl.pl new file mode 100755 index 00000000..69c28a64 --- /dev/null +++ b/hacks/glx/wfront2gl.pl @@ -0,0 +1,361 @@ +#!/usr/bin/perl -w +# Copyright © 2003-2012 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. +# +# Reads a Wavefront OBJ file, and emits C data suitable for use with OpenGL's +# glInterleavedArrays() and glDrawArrays() routines. +# +# If the OBJ file does not contain face normals, they are computed. +# Texture coordinates are ignored. +# +# Options: +# +# --normalize Compute the bounding box of the object, and scale all +# coordinates so that the object fits inside a unit cube. +# +# Created: 8-Mar-2003. + +require 5; +use diagnostics; +use strict; + +my $progname = $0; $progname =~ s@.*/@@g; +my $version = q{ $Revision: 1.5 $ }; $version =~ s/^[^0-9]+([0-9.]+).*$/$1/; + +my $verbose = 0; + + +# convert a vector to a unit vector +sub normalize($$$) { + my ($x, $y, $z) = @_; + my $L = sqrt (($x * $x) + ($y * $y) + ($z * $z)); + if ($L != 0) { + $x /= $L; + $y /= $L; + $z /= $L; + } else { + $x = $y = $z = 0; + } + return ($x, $y, $z); +} + + +# Calculate the unit normal at p0 given two other points p1,p2 on the +# surface. The normal points in the direction of p1 crossproduct p2. +# +sub face_normal($$$$$$$$$) { + my ($p0x, $p0y, $p0z, + $p1x, $p1y, $p1z, + $p2x, $p2y, $p2z) = @_; + + my ($nx, $ny, $nz); + my ($pax, $pay, $paz); + my ($pbx, $pby, $pbz); + + $pax = $p1x - $p0x; + $pay = $p1y - $p0y; + $paz = $p1z - $p0z; + $pbx = $p2x - $p0x; + $pby = $p2y - $p0y; + $pbz = $p2z - $p0z; + $nx = $pay * $pbz - $paz * $pby; + $ny = $paz * $pbx - $pax * $pbz; + $nz = $pax * $pby - $pay * $pbx; + + return (normalize ($nx, $ny, $nz)); +} + + +sub parse_obj($$$) { + my ($filename, $obj, $normalize_p) = @_; + + $_ = $obj; + my @verts = (); # list of refs of coords, [x, y, z] + my @norms = (); # list of refs of coords, [x, y, z] + my @texts = (); # list of refs of coords, [u, v] + my @faces = (); # list of refs of [ point, point, point, ... ] + # where 'point' is a ref of indexes into the + # above lists, [ vert, text, norm ] + + my $lineno = 0; + foreach (split (/\n/, $obj)) { + $lineno++; + next if (m/^\s*$|^\s*\#/); + + if (m/^v\s/) { + my ($x, $y, $z) = m/^v\s+([^\s]+)\s+([^\s]+)\s+([^\s]+)\s*$/; + error ("line $lineno: unparsable V line: $_") unless defined($z); + push @verts, [$x+0, $y+0, $z+0]; + + } elsif (m/^vn\s/) { + my ($x, $y, $z) = m/^vn\s+([^\s]+)\s+([^\s]+)\s+([^\s]+)\s*$/; + error ("line $lineno: unparsable VN line: $_") unless defined($z); + push @norms, [$x+0, $y+0, $z+0]; + + } elsif (m/^vt\s/) { + my ($u, $v) = m/^vt\s+([^\s]+)\s+([^\s]+)\s*$/; + error ("line $lineno: unparsable VT line: $_") unless defined($v); + push @texts, [$u+0, $v+0]; + + } elsif (m/^g\b/) { + # group name + + } elsif (m/f\s/) { + my @f = split(/\s+/, $_); + shift @f; + my @vs = (); + foreach my $f (@f) { + my ($v, $t, $n); + if ($f =~ m@^(\d+)$@s) { $v = $1; } + elsif ($f =~ m@^(\d+)/(\d+)$@s) { $v = $1, $t = $2; } + elsif ($f =~ m@^(\d+)/(\d+)/(\d+)$@s) { $v = $1, $t = $2; $n = $3; } + elsif ($f =~ m@^(\d+)///?(\d+)$@s) { $v = $1; $n = $3; } + else { + error ("line $lineno: unparsable F line: $_") unless defined($v); + } + $t = -1 unless defined($t); + $n = -1 unless defined($n); + push @vs, [$v+0, $t+0, $n+0]; + } + push @faces, \@vs; + + } elsif (m/^s\b/) { + # turn on smooth shading + } elsif (m/^(mtllib|usemtl)\b/) { + # reference to external materials file (textures, etc.) + } else { + error ("line $lineno: unknown line: $_"); + } + } + + + # find bounding box, and normalize + # + if ($normalize_p || $verbose) { + my $minx = 999999999; + my $miny = 999999999; + my $minz = 999999999; + my $maxx = -999999999; + my $maxy = -999999999; + my $maxz = -999999999; + my $i = 0; + foreach my $v (@verts) { + my ($x, $y, $z) = @$v; + $minx = $x if ($x < $minx); + $maxx = $x if ($x > $maxx); + $miny = $y if ($y < $miny); + $maxy = $y if ($y > $maxy); + $minz = $z if ($z < $minz); + $maxz = $z if ($z > $maxz); + } + + my $w = ($maxx - $minx); + my $h = ($maxy - $miny); + my $d = ($maxz - $minz); + my $sizea = ($w > $h ? $w : $h); + my $sizeb = ($w > $d ? $w : $d); + my $size = ($sizea > $sizeb ? $sizea : $sizeb); + + print STDERR "$progname: bbox is " . + sprintf("%.2f x %.2f x %.2f\n", $w, $h, $d) + if ($verbose); + + if ($normalize_p) { + $w /= $size; + $h /= $size; + $d /= $size; + print STDERR "$progname: dividing by $size for bbox of " . + sprintf("%.2f x %.2f x %.2f\n", $w, $h, $d) + if ($verbose); + foreach my $n (@verts) { + my @n = @$n; + foreach (@n) { $_ /= $size; } + $n = \@n; + } + } + } + + # generate interleaved list of triangle coordinates and normals + # + my @triangles = (); + my $nfaces = $#faces+1; + + foreach my $f (@faces) { + # $f is [ [v, t, n], [v, t, n], ... ] + + my @f = @$f; + +# # (Kludge for the companion cube model) +# if ($#f > 15) { +# my $i = 12; +# @f = (@f[$i-1 .. $#f], @f[0 .. $i]); +# } + + error ("too few points in face") if ($#f < 2); + my $p1 = shift @f; + + # If there are more than 3 points, do a triangle fan from the first one: + # [1 2 3] [1 3 4] [1 4 5] etc. Doesn't always work with convex shapes. + + while ($#f) { + my $p2 = shift @f; + my $p3 = $f[0]; + + my $x1 = $verts[$p1->[0]-1]->[0]; my $nx1 = $norms[$p1->[2]-1]->[0]; + my $y1 = $verts[$p1->[0]-1]->[1]; my $ny1 = $norms[$p1->[2]-1]->[1]; + my $z1 = $verts[$p1->[0]-1]->[2]; my $nz1 = $norms[$p1->[2]-1]->[2]; + + my $x2 = $verts[$p2->[0]-1]->[0]; my $nx2 = $norms[$p2->[2]-1]->[0]; + my $y2 = $verts[$p2->[0]-1]->[1]; my $ny2 = $norms[$p2->[2]-1]->[1]; + my $z2 = $verts[$p2->[0]-1]->[2]; my $nz2 = $norms[$p2->[2]-1]->[2]; + + my $x3 = $verts[$p3->[0]-1]->[0]; my $nx3 = $norms[$p3->[2]-1]->[0]; + my $y3 = $verts[$p3->[0]-1]->[1]; my $ny3 = $norms[$p3->[2]-1]->[1]; + my $z3 = $verts[$p3->[0]-1]->[2]; my $nz3 = $norms[$p3->[2]-1]->[2]; + + error ("missing points in face") unless defined($z3); + + if (!defined($nz3)) { + my ($nx, $ny, $nz) = face_normal ($x1, $y1, $z1, + $x2, $y2, $z2, + $x3, $y3, $z3); + $nx1 = $nx2 = $nx3 = $nx; + $ny1 = $ny2 = $ny3 = $ny; + $nz1 = $nz2 = $nz3 = $nz; + } + + + push @triangles, [$nx1, $ny1, $nz1, $x1, $y1, $z1, + $nx2, $ny2, $nz2, $x2, $y2, $z2, + $nx3, $ny3, $nz3, $x3, $y3, $z3]; + } + } + + return (@triangles); +} + + +sub generate_c($@) { + my ($filename, @triangles) = @_; + + my $code = ''; + + $code .= "#include \"gllist.h\"\n"; + $code .= "static const float data[]={\n"; + + my $nfaces = $#triangles + 1; + my $npoints = $nfaces * 3; + + foreach my $t (@triangles) { + my ($nx1, $ny1, $nz1, $x1, $y1, $z1, + $nx2, $ny2, $nz2, $x2, $y2, $z2, + $nx3, $ny3, $nz3, $x3, $y3, $z3) = @$t; + my $lines = sprintf("\t" . "%.6f,%.6f,%.6f," . "%.6f,%.6f,%.6f,\n" . + "\t" . "%.6f,%.6f,%.6f," . "%.6f,%.6f,%.6f,\n" . + "\t" . "%.6f,%.6f,%.6f," . "%.6f,%.6f,%.6f,\n", + $nx1, $ny1, $nz1, $x1, $y1, $z1, + $nx2, $ny2, $nz2, $x2, $y2, $z2, + $nx3, $ny3, $nz3, $x3, $y3, $z3); + $lines =~ s/([.\d])0+,/$1,/g; # lose trailing insignificant zeroes + $lines =~ s/\.,/,/g; + $lines =~ s/-0,/0,/g; + + $code .= $lines; + } + + my $token = $filename; # guess at a C token from the filename + $token =~ s/\<[^<>]*\>//; + $token =~ s@^.*/@@; + $token =~ s/\.[^.]*$//; + $token =~ s/[^a-z\d]/_/gi; + $token =~ s/__+/_/g; + $token =~ s/^_//g; + $token =~ s/_$//g; + $token =~ tr [A-Z] [a-z]; + $token = 'foo' if ($token eq ''); + + my $format = 'GL_N3F_V3F'; + my $primitive = 'GL_TRIANGLES'; + + $code =~ s/,\n$//s; + $code .= "\n};\n"; + $code .= "static const struct gllist frame={"; + $code .= "$format,$primitive,$npoints,data,NULL};\n"; + $code .= "const struct gllist *$token=&frame;\n"; + + print STDERR "$filename: " . + (($#triangles+1)*3) . " points, " . + (($#triangles+1)) . " faces.\n" + if ($verbose); + + return $code; +} + + +sub obj_to_gl($$$) { + my ($infile, $outfile, $normalize_p) = @_; + my $obj = ''; + open (my $in, '<', $infile) || error ("$infile: $!"); + my $filename = ($infile eq '-' ? "" : $infile); + print STDERR "$progname: reading $filename...\n" + if ($verbose); + while (<$in>) { $obj .= $_; } + close $in; + + $obj =~ s/\r\n/\n/g; # CRLF -> LF + $obj =~ s/\r/\n/g; # CR -> LF + + my @triangles = parse_obj ($filename, $obj, $normalize_p); + + $filename = ($outfile eq '-' ? "" : $outfile); + my $code = generate_c ($filename, @triangles); + + open (my $out, '>', $outfile) || error ("$outfile: $!"); + (print $out $code) || error ("$filename: $!"); + (close $out) || error ("$filename: $!"); + + print STDERR "$progname: wrote $filename\n" + if ($verbose || $outfile ne '-'); +} + + +sub error { + ($_) = @_; + print STDERR "$progname: $_\n"; + exit 1; +} + +sub usage { + print STDERR "usage: $progname [--verbose] [infile [outfile]]\n"; + exit 1; +} + +sub main { + my ($infile, $outfile); + my $normalize_p = 0; + while ($_ = $ARGV[0]) { + shift @ARGV; + if ($_ eq "--verbose") { $verbose++; } + elsif (m/^-v+$/) { $verbose += length($_)-1; } + elsif ($_ eq "--normalize") { $normalize_p = 1; } + elsif (m/^-./) { usage; } + elsif (!defined($infile)) { $infile = $_; } + elsif (!defined($outfile)) { $outfile = $_; } + else { usage; } + } + + $infile = "-" unless defined ($infile); + $outfile = "-" unless defined ($outfile); + + obj_to_gl ($infile, $outfile, $normalize_p); +} + +main; +exit 0; diff --git a/hacks/glx/whale.c b/hacks/glx/whale.c new file mode 100644 index 00000000..638f6421 --- /dev/null +++ b/hacks/glx/whale.c @@ -0,0 +1,1887 @@ +/* atlantis --- Shows moving 3D sea animals */ + +#if 0 +static const char sccsid[] = "@(#)whale.c 1.3 98/06/18 xlockmore"; +#endif + +/* Copyright (c) E. Lassauge, 1998. */ + +/*- + * Permission to use, copy, modify, and distribute this software and its + * documentation for any purpose and without fee is hereby granted, + * provided that the above copyright notice appear in all copies and that + * both that copyright notice and this permission notice appear in + * supporting documentation. + * + * This file is provided AS IS with no warranties of any kind. The author + * shall have no liability with respect to the infringement of copyrights, + * trade secrets or any patents by this file or any part thereof. In no + * event will the author be liable for any lost revenue or profits or + * other special, indirect and consequential damages. + * + * The original code for this mode was written by Mark J. Kilgard + * as a demo for openGL programming. + * + * Porting it to xlock was possible by comparing the original Mesa's morph3d + * demo with it's ported version to xlock, so thanks for Marcelo F. Vianna + * (look at morph3d.c) for his indirect help. + * + * Thanks goes also to Brian Paul for making it possible and inexpensive + * to use OpenGL at home. + * + * My e-mail address is lassauge@users.sourceforge.net + * + * Eric Lassauge (May-13-1998) + * + */ + +/*- + * (c) Copyright 1993, 1994, Silicon Graphics, Inc. + * ALL RIGHTS RESERVED + * Permission to use, copy, modify, and distribute this software for + * any purpose and without fee is hereby granted, provided that the above + * copyright notice appear in all copies and that both the copyright notice + * and this permission notice appear in supporting documentation, and that + * the name of Silicon Graphics, Inc. not be used in advertising + * or publicity pertaining to distribution of the software without specific, + * written prior permission. + * + * THE MATERIAL EMBODIED ON THIS SOFTWARE IS PROVIDED TO YOU "AS-IS" + * AND WITHOUT WARRANTY OF ANY KIND, EXPRESS, IMPLIED OR OTHERWISE, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTY OF MERCHANTABILITY OR + * FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL SILICON + * GRAPHICS, INC. BE LIABLE TO YOU OR ANYONE ELSE FOR ANY DIRECT, + * SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY + * KIND, OR ANY DAMAGES WHATSOEVER, INCLUDING WITHOUT LIMITATION, + * LOSS OF PROFIT, LOSS OF USE, SAVINGS OR REVENUE, OR THE CLAIMS OF + * THIRD PARTIES, WHETHER OR NOT SILICON GRAPHICS, INC. HAS BEEN + * ADVISED OF THE POSSIBILITY OF SUCH LOSS, HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE + * POSSESSION, USE OR PERFORMANCE OF THIS SOFTWARE. + * + * US Government Users Restricted Rights + * Use, duplication, or disclosure by the Government is subject to + * restrictions set forth in FAR 52.227.19(c)(2) or subparagraph + * (c)(1)(ii) of the Rights in Technical Data and Computer Software + * clause at DFARS 252.227-7013 and/or in similar or successor + * clauses in the FAR or the DOD or NASA FAR Supplement. + * Unpublished-- rights reserved under the copyright laws of the + * United States. Contractor/manufacturer is Silicon Graphics, + * Inc., 2011 N. Shoreline Blvd., Mountain View, CA 94039-7311. + * + * OpenGL(TM) is a trademark of Silicon Graphics, Inc. + */ + +#ifdef USE_GL + +#include "atlantis.h" + +/* *INDENT-OFF* */ +static const float N001[3] = {0.019249, 0.01134, -0.99975}; +static const float N002[3] = {-0.132579, 0.954547, 0.266952}; +static const float N003[3] = {-0.196061, 0.980392, -0.019778}; +static const float N004[3] = {0.695461, 0.604704, 0.388158}; +static const float N005[3] = {0.8706, 0.425754, 0.246557}; +static const float N006[3] = {-0.881191, 0.392012, 0.264251}; +#if 0 +static const float N007[3] = {0, 1, 0}; +#endif +static const float N008[3] = {-0.341437, 0.887477, 0.309523}; +static const float N009[3] = {0.124035, -0.992278, 0}; +static const float N010[3] = {0.242536, 0, -0.970143}; +static const float N011[3] = {0.588172, 0, 0.808736}; +static const float N012[3] = {0.929824, -0.340623, -0.139298}; +static const float N013[3] = {0.954183, 0.267108, -0.134865}; +static const float N014[3] = {0.495127, 0.855436, -0.151914}; +static const float N015[3] = {-0.390199, 0.906569, -0.160867}; +static const float N016[3] = {-0.923605, 0.354581, -0.145692}; +static const float N017[3] = {-0.955796, -0.260667, -0.136036}; +static const float N018[3] = {-0.501283, -0.853462, -0.14254}; +static const float N019[3] = {0.4053, -0.901974, -0.148913}; +static const float N020[3] = {0.909913, -0.392746, -0.133451}; +static const float N021[3] = {0.936494, 0.331147, -0.115414}; +static const float N022[3] = {0.600131, 0.793724, -0.099222}; +static const float N023[3] = {-0.231556, 0.968361, -0.093053}; +static const float N024[3] = {-0.844369, 0.52533, -0.105211}; +static const float N025[3] = {-0.982725, -0.136329, -0.125164}; +static const float N026[3] = {-0.560844, -0.822654, -0.093241}; +static const float N027[3] = {0.263884, -0.959981, -0.093817}; +static const float N028[3] = {0.842057, -0.525192, -0.122938}; +static const float N029[3] = {0.92162, 0.367565, -0.124546}; +static const float N030[3] = {0.613927, 0.784109, -0.090918}; +static const float N031[3] = {-0.448754, 0.888261, -0.098037}; +static const float N032[3] = {-0.891865, 0.434376, -0.126077}; +static const float N033[3] = {-0.881447, -0.448017, -0.149437}; +static const float N034[3] = {-0.345647, -0.922057, -0.174183}; +static const float N035[3] = {0.307998, -0.941371, -0.137688}; +static const float N036[3] = {0.806316, -0.574647, -0.140124}; +static const float N037[3] = {0.961346, 0.233646, -0.145681}; +static const float N038[3] = {0.488451, 0.865586, -0.110351}; +static const float N039[3] = {-0.37429, 0.921953, -0.099553}; +static const float N040[3] = {-0.928504, 0.344533, -0.138485}; +static const float N041[3] = {-0.918419, -0.371792, -0.135189}; +static const float N042[3] = {-0.520666, -0.833704, -0.183968}; +static const float N043[3] = {0.339204, -0.920273, -0.195036}; +static const float N044[3] = {0.921475, -0.387382, -0.028636}; +static const float N045[3] = {0.842465, 0.533335, -0.076204}; +static const float N046[3] = {0.38011, 0.924939, 0.002073}; +static const float N047[3] = {-0.276128, 0.961073, -0.009579}; +static const float N048[3] = {-0.879684, 0.473001, -0.04925}; +static const float N049[3] = {-0.947184, -0.317614, -0.044321}; +static const float N050[3] = {-0.642059, -0.764933, -0.051363}; +static const float N051[3] = {0.466794, -0.880921, -0.07799}; +static const float N052[3] = {0.898509, -0.432277, 0.076279}; +static const float N053[3] = {0.938985, 0.328141, 0.103109}; +static const float N054[3] = {0.44242, 0.895745, 0.043647}; +static const float N055[3] = {-0.255163, 0.966723, 0.018407}; +static const float N056[3] = {-0.833769, 0.54065, 0.111924}; +static const float N057[3] = {-0.953653, -0.289939, 0.080507}; +static const float N058[3] = {-0.672357, -0.730524, 0.119461}; +static const float N059[3] = {0.522249, -0.846652, 0.102157}; +static const float N060[3] = {0.885868, -0.427631, 0.179914}; +#if 0 +static const float N061[3] = {0, 1, 0}; +#endif +static const float N062[3] = {0.648942, 0.743116, 0.163255}; +static const float N063[3] = {-0.578967, 0.80773, 0.111219}; +#if 0 +static const float N064[3] = {0, 1, 0}; +#endif +static const float N065[3] = {-0.909864, -0.352202, 0.219321}; +static const float N066[3] = {-0.502541, -0.81809, 0.27961}; +static const float N067[3] = {0.322919, -0.915358, 0.240504}; +static const float N068[3] = {0.242536, 0, -0.970143}; +static const float N069[3] = {0, 1, 0}; +static const float N070[3] = {0, 1, 0}; +static const float N071[3] = {0, 1, 0}; +static const float N072[3] = {0, 1, 0}; +static const float N073[3] = {0, 1, 0}; +static const float N074[3] = {0, 1, 0}; +static const float N075[3] = {0.03122, 0.999025, -0.03122}; +static const float N076[3] = {0, 1, 0}; +static const float N077[3] = {0.446821, 0.893642, 0.041889}; +static const float N078[3] = {0.863035, -0.10098, 0.494949}; +static const float N079[3] = {0.585597, -0.808215, 0.062174}; +static const float N080[3] = {0, 1, 0}; +static const float N081[3] = {1, 0, 0}; +static const float N082[3] = {0, 1, 0}; +static const float N083[3] = {-1, 0, 0}; +static const float N084[3] = {-0.478893, 0.837129, -0.264343}; +static const float N085[3] = {0, 1, 0}; +static const float N086[3] = {0.763909, 0.539455, -0.354163}; +static const float N087[3] = {0.446821, 0.893642, 0.041889}; +static const float N088[3] = {0.385134, -0.908288, 0.163352}; +static const float N089[3] = {-0.605952, 0.779253, -0.159961}; +static const float N090[3] = {0, 1, 0}; +static const float N091[3] = {0, 1, 0}; +static const float N092[3] = {0, 1, 0}; +static const float N093[3] = {0, 1, 0}; +static const float N094[3] = {1, 0, 0}; +static const float N095[3] = {-1, 0, 0}; +static const float N096[3] = {0.644444, -0.621516, 0.445433}; +static const float N097[3] = {-0.760896, -0.474416, 0.442681}; +static const float N098[3] = {0.636888, -0.464314, 0.615456}; +static const float N099[3] = {-0.710295, 0.647038, 0.277168}; +static const float N100[3] = {0.009604, 0.993655, 0.112063}; +#if 0 +static const float N101[3] = {0, 1, 0}; +static const float N102[3] = {0, 1, 0}; +static const float N103[3] = {0, 1, 0}; +static const float N104[3] = {0.031837, 0.999285, 0.020415}; +static const float N105[3] = {0.031837, 0.999285, 0.020415}; +static const float N106[3] = {0.031837, 0.999285, 0.020415}; +static const float N107[3] = {0.014647, 0.999648, 0.022115}; +static const float N108[3] = {0.014647, 0.999648, 0.022115}; +static const float N109[3] = {0.014647, 0.999648, 0.022115}; +static const float N110[3] = {-0.985141, 0.039475, 0.167149}; +static const float N111[3] = {-0.985141, 0.039475, 0.167149}; +static const float N112[3] = {-0.985141, 0.039475, 0.167149}; +static const float N113[3] = {0, 1, 0}; +static const float N114[3] = {0, 1, 0}; +static const float N115[3] = {0, 1, 0}; +static const float N116[3] = {0, 1, 0}; +static const float N117[3] = {0, 1, 0}; +static const float N118[3] = {0, 1, 0}; +static const float N119[3] = {0, 1, 0}; +static const float N120[3] = {0, 1, 0}; +static const float N121[3] = {0, 1, 0}; +#endif +static const float iP001[3] = {18.74, 13.19, 3.76}; +static float P001[3] = {18.74, 13.19, 3.76}; +static const float P002[3] = {0, 390.42, 10292.57}; +static const float P003[3] = {55.8, 622.31, 8254.35}; +static const float P004[3] = {20.8, 247.66, 10652.13}; +static const float P005[3] = {487.51, 198.05, 9350.78}; +static const float P006[3] = {-457.61, 199.04, 9353.01}; +#if 0 +static const float P007[3] = {0, 259, 10276.27}; +#endif +static const float P008[3] = {-34.67, 247.64, 10663.71}; +static const float iP009[3] = {97.46, 67.63, 593.82}; +static const float iP010[3] = {-84.33, 67.63, 588.18}; +static const float iP011[3] = {118.69, 8.98, -66.91}; +static float P009[3] = {97.46, 67.63, 593.82}; +static float P010[3] = {-84.33, 67.63, 588.18}; +static float P011[3] = {118.69, 8.98, -66.91}; +static const float iP012[3] = {156.48, -31.95, 924.54}; +static const float iP013[3] = {162, 110.22, 924.54}; +static const float iP014[3] = {88.16, 221.65, 924.54}; +static const float iP015[3] = {-65.21, 231.16, 924.54}; +static const float iP016[3] = {-156.48, 121.97, 924.54}; +static const float iP017[3] = {-162, -23.93, 924.54}; +static const float iP018[3] = {-88.16, -139.1, 924.54}; +static const float iP019[3] = {65.21, -148.61, 924.54}; +static const float iP020[3] = {246.87, -98.73, 1783.04}; +static const float iP021[3] = {253.17, 127.76, 1783.04}; +static const float iP022[3] = {132.34, 270.77, 1783.04}; +static const float iP023[3] = {-97.88, 285.04, 1783.04}; +static const float iP024[3] = {-222.97, 139.8, 1783.04}; +static const float iP025[3] = {-225.29, -86.68, 1783.04}; +static const float iP026[3] = {-108.44, -224.15, 1783.04}; +static const float iP027[3] = {97.88, -221.56, 1783.04}; +static const float iP028[3] = {410.55, -200.66, 3213.87}; +static const float iP029[3] = {432.19, 148.42, 3213.87}; +static const float iP030[3] = {200.66, 410.55, 3213.87}; +static const float iP031[3] = {-148.42, 432.19, 3213.87}; +static const float iP032[3] = {-407.48, 171.88, 3213.87}; +static const float iP033[3] = {-432.19, -148.42, 3213.87}; +static const float iP034[3] = {-148.88, -309.74, 3213.87}; +static const float iP035[3] = {156.38, -320.17, 3213.87}; +static const float iP036[3] = {523.39, -303.81, 4424.57}; +static const float iP037[3] = {574.66, 276.84, 4424.57}; +static const float iP038[3] = {243.05, 492.5, 4424.57}; +static const float iP039[3] = {-191.23, 520.13, 4424.57}; +static const float iP040[3] = {-523.39, 304.01, 4424.57}; +static const float iP041[3] = {-574.66, -231.83, 4424.57}; +static const float iP042[3] = {-266.95, -578.17, 4424.57}; +static const float iP043[3] = {211.14, -579.67, 4424.57}; +static const float iP044[3] = {680.57, -370.27, 5943.46}; +static const float iP045[3] = {834.01, 363.09, 5943.46}; +static const float iP046[3] = {371.29, 614.13, 5943.46}; +static const float iP047[3] = {-291.43, 621.86, 5943.46}; +static const float iP048[3] = {-784.13, 362.6, 5943.46}; +static const float iP049[3] = {-743.29, -325.82, 5943.46}; +static const float iP050[3] = {-383.24, -804.77, 5943.46}; +static const float iP051[3] = {283.47, -846.09, 5943.46}; +static float P012[3] = {156.48, -31.95, 924.54}; +static float P013[3] = {162, 110.22, 924.54}; +static float P014[3] = {88.16, 221.65, 924.54}; +static float P015[3] = {-65.21, 231.16, 924.54}; +static float P016[3] = {-156.48, 121.97, 924.54}; +static float P017[3] = {-162, -23.93, 924.54}; +static float P018[3] = {-88.16, -139.1, 924.54}; +static float P019[3] = {65.21, -148.61, 924.54}; +static float P020[3] = {246.87, -98.73, 1783.04}; +static float P021[3] = {253.17, 127.76, 1783.04}; +static float P022[3] = {132.34, 270.77, 1783.04}; +static float P023[3] = {-97.88, 285.04, 1783.04}; +static float P024[3] = {-222.97, 139.8, 1783.04}; +static float P025[3] = {-225.29, -86.68, 1783.04}; +static float P026[3] = {-108.44, -224.15, 1783.04}; +static float P027[3] = {97.88, -221.56, 1783.04}; +static float P028[3] = {410.55, -200.66, 3213.87}; +static float P029[3] = {432.19, 148.42, 3213.87}; +static float P030[3] = {200.66, 410.55, 3213.87}; +static float P031[3] = {-148.42, 432.19, 3213.87}; +static float P032[3] = {-407.48, 171.88, 3213.87}; +static float P033[3] = {-432.19, -148.42, 3213.87}; +static float P034[3] = {-148.88, -309.74, 3213.87}; +static float P035[3] = {156.38, -320.17, 3213.87}; +static float P036[3] = {523.39, -303.81, 4424.57}; +static float P037[3] = {574.66, 276.84, 4424.57}; +static float P038[3] = {243.05, 492.5, 4424.57}; +static float P039[3] = {-191.23, 520.13, 4424.57}; +static float P040[3] = {-523.39, 304.01, 4424.57}; +static float P041[3] = {-574.66, -231.83, 4424.57}; +static float P042[3] = {-266.95, -578.17, 4424.57}; +static float P043[3] = {211.14, -579.67, 4424.57}; +static float P044[3] = {680.57, -370.27, 5943.46}; +static float P045[3] = {834.01, 363.09, 5943.46}; +static float P046[3] = {371.29, 614.13, 5943.46}; +static float P047[3] = {-291.43, 621.86, 5943.46}; +static float P048[3] = {-784.13, 362.6, 5943.46}; +static float P049[3] = {-743.29, -325.82, 5943.46}; +static float P050[3] = {-383.24, -804.77, 5943.46}; +static float P051[3] = {283.47, -846.09, 5943.46}; +static const float P052[3] = {599.09, -332.24, 7902.59}; +static const float P053[3] = {735.48, 306.26, 7911.92}; +static const float P054[3] = {321.55, 558.53, 7902.59}; +static const float P055[3] = {-260.54, 559.84, 7902.59}; +static const float P056[3] = {-698.66, 320.83, 7902.59}; +static const float P057[3] = {-643.29, -299.16, 7902.59}; +static const float P058[3] = {-341.47, -719.3, 7902.59}; +static const float P059[3] = {252.57, -756.12, 7902.59}; +static const float P060[3] = {458.39, -265.31, 9355.44}; +static const float iP061[3] = {353.63, 138.7, 10214.2}; +static float P061[3] = {353.63, 138.7, 10214.2}; +static const float P062[3] = {224.04, 438.98, 9364.77}; +static const float P063[3] = {-165.71, 441.27, 9355.44}; +static const float iP064[3] = {-326.4, 162.04, 10209.54}; +static float P064[3] = {-326.4, 162.04, 10209.54}; +static const float P065[3] = {-473.99, -219.71, 9355.44}; +static const float P066[3] = {-211.97, -479.87, 9355.44}; +static const float P067[3] = {192.86, -504.03, 9355.44}; +static const float iP068[3] = {-112.44, 9.25, -64.42}; +static const float iP069[3] = {1155.63, 0, -182.46}; +static const float iP070[3] = {-1143.13, 0, -181.54}; +static const float iP071[3] = {1424.23, 0, -322.09}; +static const float iP072[3] = {-1368.01, 0, -310.38}; +static const float iP073[3] = {1255.57, 2.31, 114.05}; +static const float iP074[3] = {-1149.38, 0, 117.12}; +static const float iP075[3] = {718.36, 0, 433.36}; +static const float iP076[3] = {-655.9, 0, 433.36}; +static float P068[3] = {-112.44, 9.25, -64.42}; +static float P069[3] = {1155.63, 0, -182.46}; +static float P070[3] = {-1143.13, 0, -181.54}; +static float P071[3] = {1424.23, 0, -322.09}; +static float P072[3] = {-1368.01, 0, -310.38}; +static float P073[3] = {1255.57, 2.31, 114.05}; +static float P074[3] = {-1149.38, 0, 117.12}; +static float P075[3] = {718.36, 0, 433.36}; +static float P076[3] = {-655.9, 0, 433.36}; +static const float P077[3] = {1058, -2.66, 7923.51}; +static const float P078[3] = {-1016.51, -15.47, 7902.87}; +static const float P079[3] = {-1363.99, -484.5, 7593.38}; +static const float P080[3] = {1478.09, -861.47, 7098.12}; +static const float P081[3] = {1338.06, -284.68, 7024.15}; +static const float P082[3] = {-1545.51, -860.64, 7106.6}; +static const float P083[3] = {1063.19, -70.46, 7466.6}; +static const float P084[3] = {-1369.18, -288.11, 7015.34}; +static const float P085[3] = {1348.44, -482.5, 7591.41}; +static const float P086[3] = {-1015.45, -96.8, 7474.86}; +static const float P087[3] = {731.04, 148.38, 7682.58}; +static const float P088[3] = {-697.03, 151.82, 7668.81}; +static const float P089[3] = {-686.82, 157.09, 7922.29}; +static const float P090[3] = {724.73, 147.75, 7931.39}; +static const float iP091[3] = {0, 327.1, 2346.55}; +static const float iP092[3] = {0, 552.28, 2311.31}; +static const float iP093[3] = {0, 721.16, 2166.41}; +static const float iP094[3] = {0, 693.42, 2388.8}; +static const float iP095[3] = {0, 389.44, 2859.97}; +static float P091[3] = {0, 327.1, 2346.55}; +static float P092[3] = {0, 552.28, 2311.31}; +static float P093[3] = {0, 721.16, 2166.41}; +static float P094[3] = {0, 693.42, 2388.8}; +static float P095[3] = {0, 389.44, 2859.97}; +static const float iP096[3] = {222.02, -183.67, 10266.89}; +static const float iP097[3] = {-128.9, -182.7, 10266.89}; +static const float iP098[3] = {41.04, 88.31, 10659.36}; +static const float iP099[3] = {-48.73, 88.3, 10659.36}; +static float P096[3] = {222.02, -183.67, 10266.89}; +static float P097[3] = {-128.9, -182.7, 10266.89}; +static float P098[3] = {41.04, 88.31, 10659.36}; +static float P099[3] = {-48.73, 88.3, 10659.36}; +static const float P100[3] = {0, 603.42, 9340.68}; +#if 0 +static const float P101[3] = {5.7, 567, 7862.98}; +static const float P102[3] = {521.61, 156.61, 9162.34}; +static const float P103[3] = {83.68, 566.67, 7861.26}; +#endif +static const float P104[3] = {-9.86, 567.62, 7858.65}; +static const float P105[3] = {31.96, 565.27, 7908.46}; +static const float P106[3] = {22.75, 568.13, 7782.83}; +static const float P107[3] = {58.93, 568.42, 7775.94}; +static const float P108[3] = {55.91, 565.59, 7905.86}; +static const float P109[3] = {99.21, 566, 7858.65}; +static const float P110[3] = {-498.83, 148.14, 9135.1}; +static const float P111[3] = {-495.46, 133.24, 9158.48}; +static const float P112[3] = {-490.82, 146.23, 9182.76}; +static const float P113[3] = {-489.55, 174.11, 9183.66}; +static const float P114[3] = {-492.92, 189, 9160.28}; +static const float P115[3] = {-497.56, 176.02, 9136}; +static const float P116[3] = {526.54, 169.68, 9137.7}; +static const float P117[3] = {523.49, 184.85, 9161.42}; +static const float P118[3] = {518.56, 171.78, 9186.06}; +static const float P119[3] = {516.68, 143.53, 9186.98}; +static const float P120[3] = {519.73, 128.36, 9163.26}; +static const float P121[3] = {524.66, 141.43, 9138.62}; +/* *INDENT-ON* */ + + + +static void +Whale001(GLenum cap) +{ + glBegin(cap); + glNormal3fv(N001); + glVertex3fv(P001); + glNormal3fv(N068); + glVertex3fv(P068); + glNormal3fv(N010); + glVertex3fv(P010); + glEnd(); + glBegin(cap); + glNormal3fv(N068); + glVertex3fv(P068); + glNormal3fv(N076); + glVertex3fv(P076); + glNormal3fv(N010); + glVertex3fv(P010); + glEnd(); + glBegin(cap); + glNormal3fv(N068); + glVertex3fv(P068); + glNormal3fv(N070); + glVertex3fv(P070); + glNormal3fv(N076); + glVertex3fv(P076); + glEnd(); + glBegin(cap); + glNormal3fv(N076); + glVertex3fv(P076); + glNormal3fv(N070); + glVertex3fv(P070); + glNormal3fv(N074); + glVertex3fv(P074); + glEnd(); + glBegin(cap); + glNormal3fv(N070); + glVertex3fv(P070); + glNormal3fv(N072); + glVertex3fv(P072); + glNormal3fv(N074); + glVertex3fv(P074); + glEnd(); + glBegin(cap); + glNormal3fv(N072); + glVertex3fv(P072); + glNormal3fv(N070); + glVertex3fv(P070); + glNormal3fv(N074); + glVertex3fv(P074); + glEnd(); + glBegin(cap); + glNormal3fv(N074); + glVertex3fv(P074); + glNormal3fv(N070); + glVertex3fv(P070); + glNormal3fv(N076); + glVertex3fv(P076); + glEnd(); + glBegin(cap); + glNormal3fv(N070); + glVertex3fv(P070); + glNormal3fv(N068); + glVertex3fv(P068); + glNormal3fv(N076); + glVertex3fv(P076); + glEnd(); + glBegin(cap); + glNormal3fv(N076); + glVertex3fv(P076); + glNormal3fv(N068); + glVertex3fv(P068); + glNormal3fv(N010); + glVertex3fv(P010); + glEnd(); + glBegin(cap); + glNormal3fv(N068); + glVertex3fv(P068); + glNormal3fv(N001); + glVertex3fv(P001); + glNormal3fv(N010); + glVertex3fv(P010); + glEnd(); +} + +static void +Whale002(GLenum cap) +{ + glBegin(cap); + glNormal3fv(N011); + glVertex3fv(P011); + glNormal3fv(N001); + glVertex3fv(P001); + glNormal3fv(N009); + glVertex3fv(P009); + glEnd(); + glBegin(cap); + glNormal3fv(N075); + glVertex3fv(P075); + glNormal3fv(N011); + glVertex3fv(P011); + glNormal3fv(N009); + glVertex3fv(P009); + glEnd(); + glBegin(cap); + glNormal3fv(N069); + glVertex3fv(P069); + glNormal3fv(N011); + glVertex3fv(P011); + glNormal3fv(N075); + glVertex3fv(P075); + glEnd(); + glBegin(cap); + glNormal3fv(N069); + glVertex3fv(P069); + glNormal3fv(N075); + glVertex3fv(P075); + glNormal3fv(N073); + glVertex3fv(P073); + glEnd(); + glBegin(cap); + glNormal3fv(N071); + glVertex3fv(P071); + glNormal3fv(N069); + glVertex3fv(P069); + glNormal3fv(N073); + glVertex3fv(P073); + glEnd(); + glBegin(cap); + glNormal3fv(N001); + glVertex3fv(P001); + glNormal3fv(N011); + glVertex3fv(P011); + glNormal3fv(N009); + glVertex3fv(P009); + glEnd(); + glBegin(cap); + glNormal3fv(N009); + glVertex3fv(P009); + glNormal3fv(N011); + glVertex3fv(P011); + glNormal3fv(N075); + glVertex3fv(P075); + glEnd(); + glBegin(cap); + glNormal3fv(N011); + glVertex3fv(P011); + glNormal3fv(N069); + glVertex3fv(P069); + glNormal3fv(N075); + glVertex3fv(P075); + glEnd(); + glBegin(cap); + glNormal3fv(N069); + glVertex3fv(P069); + glNormal3fv(N073); + glVertex3fv(P073); + glNormal3fv(N075); + glVertex3fv(P075); + glEnd(); + glBegin(cap); + glNormal3fv(N069); + glVertex3fv(P069); + glNormal3fv(N071); + glVertex3fv(P071); + glNormal3fv(N073); + glVertex3fv(P073); + glEnd(); +} + +static void +Whale003(GLenum cap) +{ + glBegin(cap); + glNormal3fv(N018); + glVertex3fv(P018); + glNormal3fv(N001); + glVertex3fv(P001); + glNormal3fv(N019); + glVertex3fv(P019); + glEnd(); + glBegin(cap); + glNormal3fv(N019); + glVertex3fv(P019); + glNormal3fv(N001); + glVertex3fv(P001); + glNormal3fv(N012); + glVertex3fv(P012); + glEnd(); + glBegin(cap); + glNormal3fv(N017); + glVertex3fv(P017); + glNormal3fv(N001); + glVertex3fv(P001); + glNormal3fv(N018); + glVertex3fv(P018); + glEnd(); + glBegin(cap); + glNormal3fv(N001); + glVertex3fv(P001); + glNormal3fv(N017); + glVertex3fv(P017); + glNormal3fv(N016); + glVertex3fv(P016); + glEnd(); + glBegin(cap); + glNormal3fv(N001); + glVertex3fv(P001); + glNormal3fv(N013); + glVertex3fv(P013); + glNormal3fv(N012); + glVertex3fv(P012); + glEnd(); + glBegin(cap); + glNormal3fv(N001); + glVertex3fv(P001); + glNormal3fv(N016); + glVertex3fv(P016); + glNormal3fv(N015); + glVertex3fv(P015); + glEnd(); + glBegin(cap); + glNormal3fv(N001); + glVertex3fv(P001); + glNormal3fv(N014); + glVertex3fv(P014); + glNormal3fv(N013); + glVertex3fv(P013); + glEnd(); + glBegin(cap); + glNormal3fv(N001); + glVertex3fv(P001); + glNormal3fv(N015); + glVertex3fv(P015); + glNormal3fv(N014); + glVertex3fv(P014); + glEnd(); +} + +static void +Whale004(GLenum cap) +{ + glBegin(cap); + glNormal3fv(N014); + glVertex3fv(P014); + glNormal3fv(N015); + glVertex3fv(P015); + glNormal3fv(N023); + glVertex3fv(P023); + glNormal3fv(N022); + glVertex3fv(P022); + glEnd(); + glBegin(cap); + glNormal3fv(N015); + glVertex3fv(P015); + glNormal3fv(N016); + glVertex3fv(P016); + glNormal3fv(N024); + glVertex3fv(P024); + glNormal3fv(N023); + glVertex3fv(P023); + glEnd(); + glBegin(cap); + glNormal3fv(N016); + glVertex3fv(P016); + glNormal3fv(N017); + glVertex3fv(P017); + glNormal3fv(N025); + glVertex3fv(P025); + glNormal3fv(N024); + glVertex3fv(P024); + glEnd(); + glBegin(cap); + glNormal3fv(N017); + glVertex3fv(P017); + glNormal3fv(N018); + glVertex3fv(P018); + glNormal3fv(N026); + glVertex3fv(P026); + glNormal3fv(N025); + glVertex3fv(P025); + glEnd(); + glBegin(cap); + glNormal3fv(N013); + glVertex3fv(P013); + glNormal3fv(N014); + glVertex3fv(P014); + glNormal3fv(N022); + glVertex3fv(P022); + glNormal3fv(N021); + glVertex3fv(P021); + glEnd(); + glBegin(cap); + glNormal3fv(N012); + glVertex3fv(P012); + glNormal3fv(N013); + glVertex3fv(P013); + glNormal3fv(N021); + glVertex3fv(P021); + glNormal3fv(N020); + glVertex3fv(P020); + glEnd(); + glBegin(cap); + glNormal3fv(N018); + glVertex3fv(P018); + glNormal3fv(N019); + glVertex3fv(P019); + glNormal3fv(N027); + glVertex3fv(P027); + glNormal3fv(N026); + glVertex3fv(P026); + glEnd(); + glBegin(cap); + glNormal3fv(N019); + glVertex3fv(P019); + glNormal3fv(N012); + glVertex3fv(P012); + glNormal3fv(N020); + glVertex3fv(P020); + glNormal3fv(N027); + glVertex3fv(P027); + glEnd(); +} + +static void +Whale005(GLenum cap) +{ + glBegin(cap); + glNormal3fv(N022); + glVertex3fv(P022); + glNormal3fv(N023); + glVertex3fv(P023); + glNormal3fv(N031); + glVertex3fv(P031); + glNormal3fv(N030); + glVertex3fv(P030); + glEnd(); + glBegin(cap); + glNormal3fv(N021); + glVertex3fv(P021); + glNormal3fv(N022); + glVertex3fv(P022); + glNormal3fv(N030); + glVertex3fv(P030); + glEnd(); + glBegin(cap); + glNormal3fv(N021); + glVertex3fv(P021); + glNormal3fv(N030); + glVertex3fv(P030); + glNormal3fv(N029); + glVertex3fv(P029); + glEnd(); + glBegin(cap); + glNormal3fv(N023); + glVertex3fv(P023); + glNormal3fv(N024); + glVertex3fv(P024); + glNormal3fv(N031); + glVertex3fv(P031); + glEnd(); + glBegin(cap); + glNormal3fv(N024); + glVertex3fv(P024); + glNormal3fv(N032); + glVertex3fv(P032); + glNormal3fv(N031); + glVertex3fv(P031); + glEnd(); + glBegin(cap); + glNormal3fv(N024); + glVertex3fv(P024); + glNormal3fv(N025); + glVertex3fv(P025); + glNormal3fv(N032); + glVertex3fv(P032); + glEnd(); + glBegin(cap); + glNormal3fv(N025); + glVertex3fv(P025); + glNormal3fv(N033); + glVertex3fv(P033); + glNormal3fv(N032); + glVertex3fv(P032); + glEnd(); + glBegin(cap); + glNormal3fv(N020); + glVertex3fv(P020); + glNormal3fv(N021); + glVertex3fv(P021); + glNormal3fv(N029); + glVertex3fv(P029); + glEnd(); + glBegin(cap); + glNormal3fv(N020); + glVertex3fv(P020); + glNormal3fv(N029); + glVertex3fv(P029); + glNormal3fv(N028); + glVertex3fv(P028); + glEnd(); + glBegin(cap); + glNormal3fv(N027); + glVertex3fv(P027); + glNormal3fv(N020); + glVertex3fv(P020); + glNormal3fv(N028); + glVertex3fv(P028); + glEnd(); + glBegin(cap); + glNormal3fv(N027); + glVertex3fv(P027); + glNormal3fv(N028); + glVertex3fv(P028); + glNormal3fv(N035); + glVertex3fv(P035); + glEnd(); + glBegin(cap); + glNormal3fv(N025); + glVertex3fv(P025); + glNormal3fv(N026); + glVertex3fv(P026); + glNormal3fv(N033); + glVertex3fv(P033); + glEnd(); + glBegin(cap); + glNormal3fv(N033); + glVertex3fv(P033); + glNormal3fv(N026); + glVertex3fv(P026); + glNormal3fv(N034); + glVertex3fv(P034); + glEnd(); + glBegin(cap); + glNormal3fv(N026); + glVertex3fv(P026); + glNormal3fv(N027); + glVertex3fv(P027); + glNormal3fv(N035); + glVertex3fv(P035); + glNormal3fv(N034); + glVertex3fv(P034); + glEnd(); +} + +static void +Whale006(GLenum cap) +{ + glBegin(cap); + glNormal3fv(N092); + glVertex3fv(P092); + glNormal3fv(N093); + glVertex3fv(P093); + glNormal3fv(N094); + glVertex3fv(P094); + glEnd(); + glBegin(cap); + glNormal3fv(N093); + glVertex3fv(P093); + glNormal3fv(N092); + glVertex3fv(P092); + glNormal3fv(N094); + glVertex3fv(P094); + glEnd(); + glBegin(cap); + glNormal3fv(N092); + glVertex3fv(P092); + glNormal3fv(N091); + glVertex3fv(P091); + glNormal3fv(N095); + glVertex3fv(P095); + glNormal3fv(N094); + glVertex3fv(P094); + glEnd(); + glBegin(cap); + glNormal3fv(N091); + glVertex3fv(P091); + glNormal3fv(N092); + glVertex3fv(P092); + glNormal3fv(N094); + glVertex3fv(P094); + glNormal3fv(N095); + glVertex3fv(P095); + glEnd(); +} + +static void +Whale007(GLenum cap) +{ + glBegin(cap); + glNormal3fv(N030); + glVertex3fv(P030); + glNormal3fv(N031); + glVertex3fv(P031); + glNormal3fv(N039); + glVertex3fv(P039); + glNormal3fv(N038); + glVertex3fv(P038); + glEnd(); + glBegin(cap); + glNormal3fv(N029); + glVertex3fv(P029); + glNormal3fv(N030); + glVertex3fv(P030); + glNormal3fv(N038); + glVertex3fv(P038); + glEnd(); + glBegin(cap); + glNormal3fv(N029); + glVertex3fv(P029); + glNormal3fv(N038); + glVertex3fv(P038); + glNormal3fv(N037); + glVertex3fv(P037); + glEnd(); + glBegin(cap); + glNormal3fv(N028); + glVertex3fv(P028); + glNormal3fv(N029); + glVertex3fv(P029); + glNormal3fv(N037); + glVertex3fv(P037); + glEnd(); + glBegin(cap); + glNormal3fv(N028); + glVertex3fv(P028); + glNormal3fv(N037); + glVertex3fv(P037); + glNormal3fv(N036); + glVertex3fv(P036); + glEnd(); + glBegin(cap); + glNormal3fv(N035); + glVertex3fv(P035); + glNormal3fv(N028); + glVertex3fv(P028); + glNormal3fv(N036); + glVertex3fv(P036); + glEnd(); + glBegin(cap); + glNormal3fv(N035); + glVertex3fv(P035); + glNormal3fv(N036); + glVertex3fv(P036); + glNormal3fv(N043); + glVertex3fv(P043); + glEnd(); + glBegin(cap); + glNormal3fv(N034); + glVertex3fv(P034); + glNormal3fv(N035); + glVertex3fv(P035); + glNormal3fv(N043); + glVertex3fv(P043); + glNormal3fv(N042); + glVertex3fv(P042); + glEnd(); + glBegin(cap); + glNormal3fv(N033); + glVertex3fv(P033); + glNormal3fv(N034); + glVertex3fv(P034); + glNormal3fv(N042); + glVertex3fv(P042); + glEnd(); + glBegin(cap); + glNormal3fv(N033); + glVertex3fv(P033); + glNormal3fv(N042); + glVertex3fv(P042); + glNormal3fv(N041); + glVertex3fv(P041); + glEnd(); + glBegin(cap); + glNormal3fv(N031); + glVertex3fv(P031); + glNormal3fv(N032); + glVertex3fv(P032); + glNormal3fv(N039); + glVertex3fv(P039); + glEnd(); + glBegin(cap); + glNormal3fv(N039); + glVertex3fv(P039); + glNormal3fv(N032); + glVertex3fv(P032); + glNormal3fv(N040); + glVertex3fv(P040); + glEnd(); + glBegin(cap); + glNormal3fv(N032); + glVertex3fv(P032); + glNormal3fv(N033); + glVertex3fv(P033); + glNormal3fv(N040); + glVertex3fv(P040); + glEnd(); + glBegin(cap); + glNormal3fv(N040); + glVertex3fv(P040); + glNormal3fv(N033); + glVertex3fv(P033); + glNormal3fv(N041); + glVertex3fv(P041); + glEnd(); +} + +static void +Whale008(GLenum cap) +{ + glBegin(cap); + glNormal3fv(N042); + glVertex3fv(P042); + glNormal3fv(N043); + glVertex3fv(P043); + glNormal3fv(N051); + glVertex3fv(P051); + glNormal3fv(N050); + glVertex3fv(P050); + glEnd(); + glBegin(cap); + glNormal3fv(N043); + glVertex3fv(P043); + glNormal3fv(N036); + glVertex3fv(P036); + glNormal3fv(N051); + glVertex3fv(P051); + glEnd(); + glBegin(cap); + glNormal3fv(N051); + glVertex3fv(P051); + glNormal3fv(N036); + glVertex3fv(P036); + glNormal3fv(N044); + glVertex3fv(P044); + glEnd(); + glBegin(cap); + glNormal3fv(N041); + glVertex3fv(P041); + glNormal3fv(N042); + glVertex3fv(P042); + glNormal3fv(N050); + glVertex3fv(P050); + glEnd(); + glBegin(cap); + glNormal3fv(N041); + glVertex3fv(P041); + glNormal3fv(N050); + glVertex3fv(P050); + glNormal3fv(N049); + glVertex3fv(P049); + glEnd(); + glBegin(cap); + glNormal3fv(N036); + glVertex3fv(P036); + glNormal3fv(N037); + glVertex3fv(P037); + glNormal3fv(N044); + glVertex3fv(P044); + glEnd(); + glBegin(cap); + glNormal3fv(N044); + glVertex3fv(P044); + glNormal3fv(N037); + glVertex3fv(P037); + glNormal3fv(N045); + glVertex3fv(P045); + glEnd(); + glBegin(cap); + glNormal3fv(N040); + glVertex3fv(P040); + glNormal3fv(N041); + glVertex3fv(P041); + glNormal3fv(N049); + glVertex3fv(P049); + glEnd(); + glBegin(cap); + glNormal3fv(N040); + glVertex3fv(P040); + glNormal3fv(N049); + glVertex3fv(P049); + glNormal3fv(N048); + glVertex3fv(P048); + glEnd(); + glBegin(cap); + glNormal3fv(N039); + glVertex3fv(P039); + glNormal3fv(N040); + glVertex3fv(P040); + glNormal3fv(N048); + glVertex3fv(P048); + glEnd(); + glBegin(cap); + glNormal3fv(N039); + glVertex3fv(P039); + glNormal3fv(N048); + glVertex3fv(P048); + glNormal3fv(N047); + glVertex3fv(P047); + glEnd(); + glBegin(cap); + glNormal3fv(N037); + glVertex3fv(P037); + glNormal3fv(N038); + glVertex3fv(P038); + glNormal3fv(N045); + glVertex3fv(P045); + glEnd(); + glBegin(cap); + glNormal3fv(N038); + glVertex3fv(P038); + glNormal3fv(N046); + glVertex3fv(P046); + glNormal3fv(N045); + glVertex3fv(P045); + glEnd(); + glBegin(cap); + glNormal3fv(N038); + glVertex3fv(P038); + glNormal3fv(N039); + glVertex3fv(P039); + glNormal3fv(N047); + glVertex3fv(P047); + glNormal3fv(N046); + glVertex3fv(P046); + glEnd(); +} + +static void +Whale009(GLenum cap) +{ + glBegin(cap); + glNormal3fv(N050); + glVertex3fv(P050); + glNormal3fv(N051); + glVertex3fv(P051); + glNormal3fv(N059); + glVertex3fv(P059); + glNormal3fv(N058); + glVertex3fv(P058); + glEnd(); + glBegin(cap); + glNormal3fv(N051); + glVertex3fv(P051); + glNormal3fv(N044); + glVertex3fv(P044); + glNormal3fv(N059); + glVertex3fv(P059); + glEnd(); + glBegin(cap); + glNormal3fv(N059); + glVertex3fv(P059); + glNormal3fv(N044); + glVertex3fv(P044); + glNormal3fv(N052); + glVertex3fv(P052); + glEnd(); + glBegin(cap); + glNormal3fv(N044); + glVertex3fv(P044); + glNormal3fv(N045); + glVertex3fv(P045); + glNormal3fv(N053); + glVertex3fv(P053); + glEnd(); + glBegin(cap); + glNormal3fv(N044); + glVertex3fv(P044); + glNormal3fv(N053); + glVertex3fv(P053); + glNormal3fv(N052); + glVertex3fv(P052); + glEnd(); + glBegin(cap); + glNormal3fv(N049); + glVertex3fv(P049); + glNormal3fv(N050); + glVertex3fv(P050); + glNormal3fv(N058); + glVertex3fv(P058); + glEnd(); + glBegin(cap); + glNormal3fv(N049); + glVertex3fv(P049); + glNormal3fv(N058); + glVertex3fv(P058); + glNormal3fv(N057); + glVertex3fv(P057); + glEnd(); + glBegin(cap); + glNormal3fv(N048); + glVertex3fv(P048); + glNormal3fv(N049); + glVertex3fv(P049); + glNormal3fv(N057); + glVertex3fv(P057); + glEnd(); + glBegin(cap); + glNormal3fv(N048); + glVertex3fv(P048); + glNormal3fv(N057); + glVertex3fv(P057); + glNormal3fv(N056); + glVertex3fv(P056); + glEnd(); + glBegin(cap); + glNormal3fv(N047); + glVertex3fv(P047); + glNormal3fv(N048); + glVertex3fv(P048); + glNormal3fv(N056); + glVertex3fv(P056); + glEnd(); + glBegin(cap); + glNormal3fv(N047); + glVertex3fv(P047); + glNormal3fv(N056); + glVertex3fv(P056); + glNormal3fv(N055); + glVertex3fv(P055); + glEnd(); + glBegin(cap); + glNormal3fv(N045); + glVertex3fv(P045); + glNormal3fv(N046); + glVertex3fv(P046); + glNormal3fv(N053); + glVertex3fv(P053); + glEnd(); + glBegin(cap); + glNormal3fv(N046); + glVertex3fv(P046); + glNormal3fv(N054); + glVertex3fv(P054); + glNormal3fv(N053); + glVertex3fv(P053); + glEnd(); + glBegin(cap); + glNormal3fv(N046); + glVertex3fv(P046); + glNormal3fv(N047); + glVertex3fv(P047); + glNormal3fv(N055); + glVertex3fv(P055); + glNormal3fv(N054); + glVertex3fv(P054); + glEnd(); +} + +static void +Whale010(GLenum cap) +{ + glBegin(cap); + glNormal3fv(N080); + glVertex3fv(P080); + glNormal3fv(N081); + glVertex3fv(P081); + glNormal3fv(N085); + glVertex3fv(P085); + glEnd(); + glBegin(cap); + glNormal3fv(N081); + glVertex3fv(P081); + glNormal3fv(N083); + glVertex3fv(P083); + glNormal3fv(N085); + glVertex3fv(P085); + glEnd(); + glBegin(cap); + glNormal3fv(N085); + glVertex3fv(P085); + glNormal3fv(N083); + glVertex3fv(P083); + glNormal3fv(N077); + glVertex3fv(P077); + glEnd(); + glBegin(cap); + glNormal3fv(N083); + glVertex3fv(P083); + glNormal3fv(N087); + glVertex3fv(P087); + glNormal3fv(N077); + glVertex3fv(P077); + glEnd(); + glBegin(cap); + glNormal3fv(N077); + glVertex3fv(P077); + glNormal3fv(N087); + glVertex3fv(P087); + glNormal3fv(N090); + glVertex3fv(P090); + glEnd(); + glBegin(cap); + glNormal3fv(N081); + glVertex3fv(P081); + glNormal3fv(N080); + glVertex3fv(P080); + glNormal3fv(N085); + glVertex3fv(P085); + glEnd(); + glBegin(cap); + glNormal3fv(N083); + glVertex3fv(P083); + glNormal3fv(N081); + glVertex3fv(P081); + glNormal3fv(N085); + glVertex3fv(P085); + glEnd(); + glBegin(cap); + glNormal3fv(N083); + glVertex3fv(P083); + glNormal3fv(N085); + glVertex3fv(P085); + glNormal3fv(N077); + glVertex3fv(P077); + glEnd(); + glBegin(cap); + glNormal3fv(N087); + glVertex3fv(P087); + glNormal3fv(N083); + glVertex3fv(P083); + glNormal3fv(N077); + glVertex3fv(P077); + glEnd(); + glBegin(cap); + glNormal3fv(N087); + glVertex3fv(P087); + glNormal3fv(N077); + glVertex3fv(P077); + glNormal3fv(N090); + glVertex3fv(P090); + glEnd(); +} + +static void +Whale011(GLenum cap) +{ + glBegin(cap); + glNormal3fv(N082); + glVertex3fv(P082); + glNormal3fv(N084); + glVertex3fv(P084); + glNormal3fv(N079); + glVertex3fv(P079); + glEnd(); + glBegin(cap); + glNormal3fv(N084); + glVertex3fv(P084); + glNormal3fv(N086); + glVertex3fv(P086); + glNormal3fv(N079); + glVertex3fv(P079); + glEnd(); + glBegin(cap); + glNormal3fv(N079); + glVertex3fv(P079); + glNormal3fv(N086); + glVertex3fv(P086); + glNormal3fv(N078); + glVertex3fv(P078); + glEnd(); + glBegin(cap); + glNormal3fv(N086); + glVertex3fv(P086); + glNormal3fv(N088); + glVertex3fv(P088); + glNormal3fv(N078); + glVertex3fv(P078); + glEnd(); + glBegin(cap); + glNormal3fv(N078); + glVertex3fv(P078); + glNormal3fv(N088); + glVertex3fv(P088); + glNormal3fv(N089); + glVertex3fv(P089); + glEnd(); + glBegin(cap); + glNormal3fv(N088); + glVertex3fv(P088); + glNormal3fv(N086); + glVertex3fv(P086); + glNormal3fv(N089); + glVertex3fv(P089); + glEnd(); + glBegin(cap); + glNormal3fv(N089); + glVertex3fv(P089); + glNormal3fv(N086); + glVertex3fv(P086); + glNormal3fv(N078); + glVertex3fv(P078); + glEnd(); + glBegin(cap); + glNormal3fv(N086); + glVertex3fv(P086); + glNormal3fv(N084); + glVertex3fv(P084); + glNormal3fv(N078); + glVertex3fv(P078); + glEnd(); + glBegin(cap); + glNormal3fv(N078); + glVertex3fv(P078); + glNormal3fv(N084); + glVertex3fv(P084); + glNormal3fv(N079); + glVertex3fv(P079); + glEnd(); + glBegin(cap); + glNormal3fv(N084); + glVertex3fv(P084); + glNormal3fv(N082); + glVertex3fv(P082); + glNormal3fv(N079); + glVertex3fv(P079); + glEnd(); +} + +static void +Whale012(GLenum cap) +{ + glBegin(cap); + glNormal3fv(N058); + glVertex3fv(P058); + glNormal3fv(N059); + glVertex3fv(P059); + glNormal3fv(N067); + glVertex3fv(P067); + glNormal3fv(N066); + glVertex3fv(P066); + glEnd(); + glBegin(cap); + glNormal3fv(N059); + glVertex3fv(P059); + glNormal3fv(N052); + glVertex3fv(P052); + glNormal3fv(N060); + glVertex3fv(P060); + glEnd(); + glBegin(cap); + glNormal3fv(N059); + glVertex3fv(P059); + glNormal3fv(N060); + glVertex3fv(P060); + glNormal3fv(N067); + glVertex3fv(P067); + glEnd(); + glBegin(cap); + glNormal3fv(N058); + glVertex3fv(P058); + glNormal3fv(N066); + glVertex3fv(P066); + glNormal3fv(N065); + glVertex3fv(P065); + glEnd(); + glBegin(cap); + glNormal3fv(N058); + glVertex3fv(P058); + glNormal3fv(N065); + glVertex3fv(P065); + glNormal3fv(N057); + glVertex3fv(P057); + glEnd(); + glBegin(cap); + glNormal3fv(N056); + glVertex3fv(P056); + glNormal3fv(N057); + glVertex3fv(P057); + glNormal3fv(N065); + glVertex3fv(P065); + glEnd(); + glBegin(cap); + glNormal3fv(N056); + glVertex3fv(P056); + glNormal3fv(N065); + glVertex3fv(P065); + glNormal3fv(N006); + glVertex3fv(P006); + glEnd(); + glBegin(cap); + glNormal3fv(N056); + glVertex3fv(P056); + glNormal3fv(N006); + glVertex3fv(P006); + glNormal3fv(N063); + glVertex3fv(P063); + glEnd(); + glBegin(cap); + glNormal3fv(N056); + glVertex3fv(P056); + glNormal3fv(N063); + glVertex3fv(P063); + glNormal3fv(N055); + glVertex3fv(P055); + glEnd(); + glBegin(cap); + glNormal3fv(N054); + glVertex3fv(P054); + glNormal3fv(N062); + glVertex3fv(P062); + glNormal3fv(N005); + glVertex3fv(P005); + glEnd(); + glBegin(cap); + glNormal3fv(N054); + glVertex3fv(P054); + glNormal3fv(N005); + glVertex3fv(P005); + glNormal3fv(N053); + glVertex3fv(P053); + glEnd(); + glBegin(cap); + glNormal3fv(N053); + glVertex3fv(P053); + glNormal3fv(N005); + glVertex3fv(P005); + glNormal3fv(N060); + glVertex3fv(P060); + glEnd(); + glBegin(cap); + glNormal3fv(N053); + glVertex3fv(P053); + glNormal3fv(N060); + glVertex3fv(P060); + glNormal3fv(N052); + glVertex3fv(P052); + glEnd(); +} + +static void +Whale013(GLenum cap) +{ + glBegin(cap); + glNormal3fv(N066); + glVertex3fv(P066); + glNormal3fv(N067); + glVertex3fv(P067); + glNormal3fv(N096); + glVertex3fv(P096); + glNormal3fv(N097); + glVertex3fv(P097); + glEnd(); + glBegin(cap); + glNormal3fv(N097); + glVertex3fv(P097); + glNormal3fv(N096); + glVertex3fv(P096); + glNormal3fv(N098); + glVertex3fv(P098); + glNormal3fv(N099); + glVertex3fv(P099); + glEnd(); + glBegin(cap); + glNormal3fv(N065); + glVertex3fv(P065); + glNormal3fv(N066); + glVertex3fv(P066); + glNormal3fv(N097); + glVertex3fv(P097); + glEnd(); + glBegin(cap); + glNormal3fv(N067); + glVertex3fv(P067); + glNormal3fv(N060); + glVertex3fv(P060); + glNormal3fv(N096); + glVertex3fv(P096); + glEnd(); + glBegin(cap); + glNormal3fv(N060); + glVertex3fv(P060); + glNormal3fv(N005); + glVertex3fv(P005); + glNormal3fv(N096); + glVertex3fv(P096); + glEnd(); + glBegin(cap); + glNormal3fv(N096); + glVertex3fv(P096); + glNormal3fv(N005); + glVertex3fv(P005); + glNormal3fv(N098); + glVertex3fv(P098); + glEnd(); + glBegin(cap); + glNormal3fv(N006); + glVertex3fv(P006); + glNormal3fv(N065); + glVertex3fv(P065); + glNormal3fv(N097); + glVertex3fv(P097); + glEnd(); + glBegin(cap); + glNormal3fv(N006); + glVertex3fv(P006); + glNormal3fv(N097); + glVertex3fv(P097); + glNormal3fv(N099); + glVertex3fv(P099); + glEnd(); + glBegin(cap); + glVertex3fv(P005); + glVertex3fv(P006); + glVertex3fv(P099); + glVertex3fv(P098); + glEnd(); +} + +static void +Whale014(GLenum cap) +{ + glBegin(cap); + glNormal3fv(N062); + glVertex3fv(P062); + glNormal3fv(N004); + glVertex3fv(P004); + glNormal3fv(N005); + glVertex3fv(P005); + glEnd(); + glBegin(cap); + glVertex3fv(P006); + glVertex3fv(P005); + glVertex3fv(P004); + glVertex3fv(P008); + glEnd(); + glBegin(cap); + glNormal3fv(N063); + glVertex3fv(P063); + glNormal3fv(N006); + glVertex3fv(P006); + glNormal3fv(N002); + glVertex3fv(P002); + glEnd(); + glBegin(cap); + glNormal3fv(N002); + glVertex3fv(P002); + glNormal3fv(N006); + glVertex3fv(P006); + glNormal3fv(N008); + glVertex3fv(P008); + glEnd(); + glBegin(cap); + glNormal3fv(N002); + glVertex3fv(P002); + glNormal3fv(N008); + glVertex3fv(P008); + glNormal3fv(N004); + glVertex3fv(P004); + glEnd(); + glBegin(cap); + glNormal3fv(N062); + glVertex3fv(P062); + glNormal3fv(N002); + glVertex3fv(P002); + glNormal3fv(N004); + glVertex3fv(P004); + glEnd(); +} + +static void +Whale015(GLenum cap) +{ + glBegin(cap); + glNormal3fv(N055); + glVertex3fv(P055); + glNormal3fv(N003); + glVertex3fv(P003); + glNormal3fv(N054); + glVertex3fv(P054); + glEnd(); + glBegin(cap); + glNormal3fv(N003); + glVertex3fv(P003); + glNormal3fv(N055); + glVertex3fv(P055); + glNormal3fv(N063); + glVertex3fv(P063); + glEnd(); + glBegin(cap); + glNormal3fv(N003); + glVertex3fv(P003); + glNormal3fv(N063); + glVertex3fv(P063); + glNormal3fv(N100); + glVertex3fv(P100); + glEnd(); + glBegin(cap); + glNormal3fv(N003); + glVertex3fv(P003); + glNormal3fv(N100); + glVertex3fv(P100); + glNormal3fv(N054); + glVertex3fv(P054); + glEnd(); + glBegin(cap); + glNormal3fv(N054); + glVertex3fv(P054); + glNormal3fv(N100); + glVertex3fv(P100); + glNormal3fv(N062); + glVertex3fv(P062); + glEnd(); + glBegin(cap); + glNormal3fv(N100); + glVertex3fv(P100); + glNormal3fv(N063); + glVertex3fv(P063); + glNormal3fv(N002); + glVertex3fv(P002); + glEnd(); + glBegin(cap); + glNormal3fv(N100); + glVertex3fv(P100); + glNormal3fv(N002); + glVertex3fv(P002); + glNormal3fv(N062); + glVertex3fv(P062); + glEnd(); +} + +static void +Whale016(GLenum cap) +{ + glBegin(cap); + glVertex3fv(P104); + glVertex3fv(P105); + glVertex3fv(P106); + glEnd(); + glBegin(cap); + glVertex3fv(P107); + glVertex3fv(P108); + glVertex3fv(P109); + glEnd(); + glBegin(cap); + glVertex3fv(P110); + glVertex3fv(P111); + glVertex3fv(P112); + glVertex3fv(P113); + glVertex3fv(P114); + glVertex3fv(P115); + glEnd(); + glBegin(cap); + glVertex3fv(P116); + glVertex3fv(P117); + glVertex3fv(P118); + glVertex3fv(P119); + glVertex3fv(P120); + glVertex3fv(P121); + glEnd(); +} + +void +DrawWhale(fishRec * fish, int wire) +{ + float seg0, seg1, seg2, seg3, seg4, seg5, seg6, seg7; + float pitch, thrash, chomp; + GLenum cap; + + fish->htail = (int) (fish->htail - (int) (5 * fish->v)) % 360; + + thrash = 70 * fish->v; + + seg0 = 1.5 * thrash * sin((fish->htail) * RRAD); + seg1 = 2.5 * thrash * sin((fish->htail + 10) * RRAD); + seg2 = 3.7 * thrash * sin((fish->htail + 15) * RRAD); + seg3 = 4.8 * thrash * sin((fish->htail + 23) * RRAD); + seg4 = 6 * thrash * sin((fish->htail + 28) * RRAD); + seg5 = 6.5 * thrash * sin((fish->htail + 35) * RRAD); + seg6 = 6.5 * thrash * sin((fish->htail + 40) * RRAD); + seg7 = 6.5 * thrash * sin((fish->htail + 55) * RRAD); + + pitch = fish->v * sin((fish->htail - 160) * RRAD); + + chomp = 0; + if (fish->v > 2) { + chomp = -(fish->v - 2) * 200; + } + P012[1] = iP012[1] + seg5; + P013[1] = iP013[1] + seg5; + P014[1] = iP014[1] + seg5; + P015[1] = iP015[1] + seg5; + P016[1] = iP016[1] + seg5; + P017[1] = iP017[1] + seg5; + P018[1] = iP018[1] + seg5; + P019[1] = iP019[1] + seg5; + + P020[1] = iP020[1] + seg4; + P021[1] = iP021[1] + seg4; + P022[1] = iP022[1] + seg4; + P023[1] = iP023[1] + seg4; + P024[1] = iP024[1] + seg4; + P025[1] = iP025[1] + seg4; + P026[1] = iP026[1] + seg4; + P027[1] = iP027[1] + seg4; + + P028[1] = iP028[1] + seg2; + P029[1] = iP029[1] + seg2; + P030[1] = iP030[1] + seg2; + P031[1] = iP031[1] + seg2; + P032[1] = iP032[1] + seg2; + P033[1] = iP033[1] + seg2; + P034[1] = iP034[1] + seg2; + P035[1] = iP035[1] + seg2; + + P036[1] = iP036[1] + seg1; + P037[1] = iP037[1] + seg1; + P038[1] = iP038[1] + seg1; + P039[1] = iP039[1] + seg1; + P040[1] = iP040[1] + seg1; + P041[1] = iP041[1] + seg1; + P042[1] = iP042[1] + seg1; + P043[1] = iP043[1] + seg1; + + P044[1] = iP044[1] + seg0; + P045[1] = iP045[1] + seg0; + P046[1] = iP046[1] + seg0; + P047[1] = iP047[1] + seg0; + P048[1] = iP048[1] + seg0; + P049[1] = iP049[1] + seg0; + P050[1] = iP050[1] + seg0; + P051[1] = iP051[1] + seg0; + + P009[1] = iP009[1] + seg6; + P010[1] = iP010[1] + seg6; + P075[1] = iP075[1] + seg6; + P076[1] = iP076[1] + seg6; + + P001[1] = iP001[1] + seg7; + P011[1] = iP011[1] + seg7; + P068[1] = iP068[1] + seg7; + P069[1] = iP069[1] + seg7; + P070[1] = iP070[1] + seg7; + P071[1] = iP071[1] + seg7; + P072[1] = iP072[1] + seg7; + P073[1] = iP073[1] + seg7; + P074[1] = iP074[1] + seg7; + + P091[1] = iP091[1] + seg3 * 1.1; + P092[1] = iP092[1] + seg3; + P093[1] = iP093[1] + seg3; + P094[1] = iP094[1] + seg3; + P095[1] = iP095[1] + seg3 * 0.9; + + P099[1] = iP099[1] + chomp; + P098[1] = iP098[1] + chomp; + P064[1] = iP064[1] + chomp; + P061[1] = iP061[1] + chomp; + P097[1] = iP097[1] + chomp; + P096[1] = iP096[1] + chomp; + + glPushMatrix(); + + glRotatef(pitch, 1, 0, 0); + + glTranslatef(0, 0, 8000); + + glRotatef(180, 0, 1, 0); + + glScalef(3, 3, 3); + + glEnable(GL_CULL_FACE); + + cap = wire ? GL_LINE_LOOP : GL_POLYGON; + Whale001(cap); + Whale002(cap); + Whale003(cap); + Whale004(cap); + Whale005(cap); + Whale006(cap); + Whale007(cap); + Whale008(cap); + Whale009(cap); + Whale010(cap); + Whale011(cap); + Whale012(cap); + Whale013(cap); + Whale014(cap); + Whale015(cap); + Whale016(cap); + + glDisable(GL_CULL_FACE); + + glPopMatrix(); +} +#endif diff --git a/hacks/glx/xlock-gl-utils.c b/hacks/glx/xlock-gl-utils.c new file mode 100644 index 00000000..0921731f --- /dev/null +++ b/hacks/glx/xlock-gl-utils.c @@ -0,0 +1,219 @@ +/* xlock-gl.c --- xscreensaver compatibility layer for xlockmore GL modules. + * xscreensaver, Copyright (c) 1997-2008 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. + * + * This file, along with xlockmore.h, make it possible to compile an xlockmore + * GL module into a standalone program, and thus use it with xscreensaver. + * By Jamie Zawinski on 31-May-97. + */ + +#include +#include "xlockmoreI.h" +#include "glxfonts.h" + +#ifndef isupper +# define isupper(c) ((c) >= 'A' && (c) <= 'Z') +#endif +#ifndef _tolower +# define _tolower(c) ((c) - 'A' + 'a') +#endif + + +/* Gag -- we use this to turn X errors from glXCreateContext() into + something that will actually make sense to the user. + */ +static XErrorHandler orig_ehandler = 0; +static Bool got_error = 0; + +static int +BadValue_ehandler (Display *dpy, XErrorEvent *error) +{ + if (error->error_code == BadValue) + { + got_error = True; + return 0; + } + else + return orig_ehandler (dpy, error); +} + + +GLXContext * +init_GL(ModeInfo * mi) +{ + Display *dpy = mi->dpy; + Window window = mi->window; + Screen *screen = mi->xgwa.screen; + Visual *visual = mi->xgwa.visual; + GLXContext glx_context = 0; + XVisualInfo vi_in, *vi_out; + int out_count; + + vi_in.screen = screen_number (screen); + vi_in.visualid = XVisualIDFromVisual (visual); + vi_out = XGetVisualInfo (dpy, VisualScreenMask|VisualIDMask, + &vi_in, &out_count); + if (! vi_out) abort (); + + { + XSync (dpy, False); + orig_ehandler = XSetErrorHandler (BadValue_ehandler); + glx_context = glXCreateContext (dpy, vi_out, 0, GL_TRUE); + XSync (dpy, False); + XSetErrorHandler (orig_ehandler); + if (got_error) + glx_context = 0; + } + + XFree((char *) vi_out); + + if (!glx_context) + { + fprintf(stderr, "%s: couldn't create GL context for visual 0x%x.\n", + progname, (unsigned int) XVisualIDFromVisual (visual)); + exit(1); + } + + glXMakeCurrent (dpy, window, glx_context); + + { + GLboolean rgba_mode = 0; + glGetBooleanv(GL_RGBA_MODE, &rgba_mode); + if (!rgba_mode) + { + glIndexi (WhitePixelOfScreen (screen)); + glClearIndex (BlackPixelOfScreen (screen)); + } + } + + + /* jwz: the doc for glDrawBuffer says "The initial value is GL_FRONT + for single-buffered contexts, and GL_BACK for double-buffered + contexts." However, I find that this is not always the case, + at least with Mesa 3.4.2 -- sometimes the default seems to be + GL_FRONT even when glGet(GL_DOUBLEBUFFER) is true. So, let's + make sure. + + Oh, hmm -- maybe this only happens when we are re-using the + xscreensaver window, and the previous GL hack happened to die with + the other buffer selected? I'm not sure. Anyway, this fixes it. + */ + { + GLboolean d = False; + glGetBooleanv (GL_DOUBLEBUFFER, &d); + if (d) + glDrawBuffer (GL_BACK); + else + glDrawBuffer (GL_FRONT); + } + + /* Sometimes glDrawBuffer() throws "invalid op". Dunno why. Ignore. */ + clear_gl_error (); + + /* Process the -background argument. */ + { + char *s = get_string_resource(mi->dpy, "background", "Background"); + XColor c = { 0, }; + if (! XParseColor (dpy, mi->xgwa.colormap, s, &c)) + fprintf (stderr, "%s: can't parse color %s; using black.\n", + progname, s); + glClearColor (c.red / 65535.0, + c.green / 65535.0, + c.blue / 65535.0, + 1.0); + } + + /* GLXContext is already a pointer type. + Why this function returns a pointer to a pointer, I have no idea... + */ + { + GLXContext *ptr = (GLXContext *) malloc(sizeof(GLXContext)); + *ptr = glx_context; + return ptr; + } +} + + + +/* clear away any lingering error codes */ +void +clear_gl_error (void) +{ + while (glGetError() != GL_NO_ERROR) + ; +} + +/* report a GL error. */ +void +check_gl_error (const char *type) +{ + char buf[100]; + GLenum i; + const char *e; + switch ((i = glGetError())) { + case GL_NO_ERROR: return; + case GL_INVALID_ENUM: e = "invalid enum"; break; + case GL_INVALID_VALUE: e = "invalid value"; break; + case GL_INVALID_OPERATION: e = "invalid operation"; break; + case GL_STACK_OVERFLOW: e = "stack overflow"; break; + case GL_STACK_UNDERFLOW: e = "stack underflow"; break; + case GL_OUT_OF_MEMORY: e = "out of memory"; break; +#ifdef GL_TABLE_TOO_LARGE_EXT + case GL_TABLE_TOO_LARGE_EXT: e = "table too large"; break; +#endif +#ifdef GL_TEXTURE_TOO_LARGE_EXT + case GL_TEXTURE_TOO_LARGE_EXT: e = "texture too large"; break; +#endif + default: + e = buf; sprintf (buf, "unknown error %d", (int) i); break; + } + fprintf (stderr, "%s: %s error: %s\n", progname, type, e); + exit (1); +} + + +/* Callback in xscreensaver_function_table, via xlockmore.c. + */ +Visual * +xlockmore_pick_gl_visual (Screen *screen) +{ + /* pick the "best" visual by interrogating the GL library instead of + by asking Xlib. GL knows better. + */ + Visual *v = 0; + Display *dpy = DisplayOfScreen (screen); + char *string = get_string_resource (dpy, "visualID", "VisualID"); + char *s; + + if (string) + for (s = string; *s; s++) + if (isupper (*s)) *s = _tolower (*s); + + if (!string || !*string || + !strcmp (string, "gl") || + !strcmp (string, "best") || + !strcmp (string, "color") || + !strcmp (string, "default")) + v = get_gl_visual (screen); /* from ../utils/visual-gl.c */ + + if (string) + free (string); + + return v; +} + + +/* Callback in xscreensaver_function_table, via xlockmore.c. + */ +Bool +xlockmore_validate_gl_visual (Screen *screen, const char *name, Visual *visual) +{ + return validate_gl_visual (stderr, screen, name, visual); +} diff --git a/hacks/glx/xpm-ximage.c b/hacks/glx/xpm-ximage.c new file mode 100644 index 00000000..94578c23 --- /dev/null +++ b/hacks/glx/xpm-ximage.c @@ -0,0 +1,462 @@ +/* xpm-ximage.c --- converts XPM data to an XImage for use with OpenGL. + * xscreensaver, Copyright (c) 1998-2008 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. + * + * Alpha channel support by Eric Lassauge + */ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include +#include + +#ifdef HAVE_COCOA +# include "jwxyz.h" +#else +# include +#endif + +#include "xpm-ximage.h" + +extern char *progname; + + +#if defined(HAVE_GDK_PIXBUF) || defined(HAVE_XPM) +static Bool +bigendian (void) +{ + union { int i; char c[sizeof(int)]; } u; + u.i = 1; + return !u.c[0]; +} +#endif /* HAVE_GDK_PIXBUF || HAVE_XPM */ + + +#if defined(HAVE_GDK_PIXBUF) + +# include + +# ifdef HAVE_GTK2 +# include +# else /* !HAVE_GTK2 */ +# include +# endif /* !HAVE_GTK2 */ + + +/* Returns an XImage structure containing the bits of the given XPM image. + This XImage will be 32 bits per pixel, 8 each per R, G, and B, with the + extra byte set to either 0xFF or 0x00 (based on the XPM file's mask.) + + The Display and Visual arguments are used only for creating the XImage; + no bits are pushed to the server. + + The Colormap argument is used just for parsing color names; no colors + are allocated. + + This is the gdk_pixbuf version of this function. + */ +static XImage * +xpm_to_ximage_1 (Display *dpy, Visual *visual, Colormap cmap, + const char *filename, + char **xpm_data) +{ + GdkPixbuf *pb; + static int initted = 0; +#ifdef HAVE_GTK2 + GError *gerr = NULL; +#endif + + if (!initted) + { +#ifdef HAVE_GTK2 + g_type_init (); +#endif + gdk_pixbuf_xlib_init (dpy, DefaultScreen (dpy)); + xlib_rgb_init (dpy, DefaultScreenOfDisplay (dpy)); + initted = 1; + } + + pb = (filename +#ifdef HAVE_GTK2 + ? gdk_pixbuf_new_from_file (filename, &gerr) +#else + ? gdk_pixbuf_new_from_file (filename) +#endif /* HAVE_GTK2 */ + : gdk_pixbuf_new_from_xpm_data ((const char **) xpm_data)); + if (pb) + { + XImage *image; + int w = gdk_pixbuf_get_width (pb); + int h = gdk_pixbuf_get_height (pb); + guchar *row = gdk_pixbuf_get_pixels (pb); + int stride = gdk_pixbuf_get_rowstride (pb); + int chan = gdk_pixbuf_get_n_channels (pb); + int x, y; + + image = XCreateImage (dpy, visual, 32, ZPixmap, 0, 0, w, h, 32, 0); + image->data = (char *) malloc(h * image->bytes_per_line); + + /* Set the bit order in the XImage structure to whatever the + local host's native bit order is. + */ + image->bitmap_bit_order = + image->byte_order = + (bigendian() ? MSBFirst : LSBFirst); + + + if (!image->data) + { + fprintf (stderr, "%s: out of memory (%d x %d)\n", progname, w, h); + exit (1); + } + + for (y = 0; y < h; y++) + { + int y2 = (h-1-y); /* Texture maps are upside down. */ + + guchar *i = row; + for (x = 0; x < w; x++) + { + unsigned long rgba = 0; + switch (chan) { + case 1: + rgba = ((0xFF << 24) | + (*i << 16) | + (*i << 8) | + *i); + i++; + break; + case 3: + rgba = ((0xFF << 24) | + (i[2] << 16) | + (i[1] << 8) | + i[0]); + i += 3; + break; + case 4: + rgba = ((i[3] << 24) | + (i[2] << 16) | + (i[1] << 8) | + i[0]); + i += 4; + break; + default: + abort(); + break; + } + XPutPixel (image, x, y2, rgba); + } + row += stride; + } + gdk_pixbuf_unref (pb); /* #### does doing this free colors? */ + + return image; + } + else if (filename) + { +#ifdef HAVE_GTK2 + fprintf (stderr, "%s: %s\n", progname, gerr->message); + g_error_free (gerr); +#else + fprintf (stderr, "%s: unable to load %s\n", progname, filename); +#endif /* HAVE_GTK2 */ + exit (1); + } + else + { + fprintf (stderr, "%s: unable to initialize builtin texture\n", progname); + exit (1); + } +} + + +#elif defined(HAVE_XPM) + + +#include +#include +#include + +#include +#include + +#undef countof +#define countof(x) (sizeof((x))/sizeof((*x))) + + + +/* The libxpm version of this function... + */ +static XImage * +xpm_to_ximage_1 (Display *dpy, Visual *visual, Colormap cmap, + const char *filename, char **xpm_data) +{ + /* All we want to do is get RGB data out of the XPM file built in to this + program. This is a pain, because there is no way (as of XPM version + 4.6, at least) to get libXpm to make an XImage without also allocating + colors with XAllocColor. So, instead, we create an XpmImage and parse + out the RGB values of the pixels ourselves; and construct an XImage + by hand. Regardless of the depth of the visual we're using, this + XImage will have 32 bits per pixel, 8 each per R, G, and B. We put + 0xFF or 0x00 in the fourth (alpha) slot, depending on the file's mask. + */ + XImage *ximage = 0; + XpmImage xpm_image; + XpmInfo xpm_info; + int result; + int transparent_color_index = -1; + int x, y, i; + int bpl, wpl; + XColor colors[256]; + + memset (&xpm_image, 0, sizeof(xpm_image)); + memset (&xpm_info, 0, sizeof(xpm_info)); + + if (filename) + { + xpm_data = 0; + if (XpmSuccess != XpmReadFileToData ((char *) filename, &xpm_data)) + { + fprintf (stderr, "%s: unable to read XPM file %s\n", + progname, filename); + exit (1); + } + } + + result = XpmCreateXpmImageFromData (xpm_data, &xpm_image, &xpm_info); + if (result != XpmSuccess) + { + fprintf(stderr, "%s: unable to parse xpm data (%d).\n", progname, + result); + exit (1); + } + + if (xpm_image.ncolors > countof(colors)) + { + fprintf (stderr, "%s: too many colors (%d) in XPM.\n", + progname, xpm_image.ncolors); + exit (1); + } + + ximage = XCreateImage (dpy, visual, 32, ZPixmap, 0, 0, + xpm_image.width, xpm_image.height, 32, 0); + + bpl = ximage->bytes_per_line; + wpl = bpl/4; + + ximage->data = (char *) malloc(xpm_image.height * bpl); + + /* Parse the colors in the XPM into RGB values. */ + for (i = 0; i < xpm_image.ncolors; i++) + { + const char *c = xpm_image.colorTable[i].c_color; + if (!c) + { + fprintf(stderr, "%s: bogus color table? (%d)\n", progname, i); + exit (1); + } + else if (!strncasecmp (c, "None", 4)) + { + transparent_color_index = i; + colors[transparent_color_index].red = 0xFF; + colors[transparent_color_index].green = 0xFF; + colors[transparent_color_index].blue = 0xFF; + } + else if (!XParseColor (dpy, cmap, c, &colors[i])) + { + fprintf(stderr, "%s: unparsable color: %s\n", progname, c); + exit (1); + } + } + + /* Translate the XpmImage to an RGB XImage. */ + { + int rpos, gpos, bpos, apos; /* bitfield positions */ + + /* Note that unlike X, which is endianness-agnostic (since any XImage + can have its own specific bit ordering, with the server reversing + things as necessary) OpenGL pretends everything is client-side, so + we need to pack things in the right order for the client machine. + */ + + ximage->bitmap_bit_order = + ximage->byte_order = + (bigendian() ? MSBFirst : LSBFirst); + +#if 0 + /* #### Cherub says that the little-endian case must be taken on MacOSX, + or else the colors/alpha are the wrong way around. How can + that be the case? + */ + if (bigendian()) + rpos = 24, gpos = 16, bpos = 8, apos = 0; + else +#endif + rpos = 0, gpos = 8, bpos = 16, apos = 24; + + } + + /* I sure hope these only free the contents, and not the args. */ +#if 0 /* Apparently not? Gotta love those well-documented APIs! */ + XpmFreeXpmImage (&xpm_image); + XpmFreeXpmInfo (&xpm_info); +#endif + + return ximage; +} + + +#else /* !HAVE_XPM && !HAVE_GDK_PIXBUF */ + +/* If we don't have libXPM or Pixbuf, then use "minixpm". + This can read XPM data from memory, but can't read files. + */ + +#include +#include +#include "minixpm.h" + +#undef countof +#define countof(x) (sizeof((x))/sizeof((*x))) + + +/* Given a bitmask, returns the position and width of the field. + */ +static void +decode_mask (unsigned int mask, unsigned int *pos_ret, unsigned int *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; + } +} + + +/* The minixpm version of this function... + */ +static XImage * +xpm_to_ximage_1 (Display *dpy, Visual *visual, Colormap cmap, + const char *filename, char **xpm_data) +{ + int iw, ih, w8, x, y; + XImage *ximage; + char *data; + unsigned char *mask = 0; + int depth = 32; + unsigned long background_color = + BlackPixelOfScreen (DefaultScreenOfDisplay (dpy)); + unsigned long *pixels = 0; + int npixels = 0; + int bpl; + + unsigned int rpos=0, gpos=0, bpos=0, apos=0; + unsigned int rmsk=0, gmsk=0, bmsk=0, amsk=0; + unsigned int rsiz=0, gsiz=0, bsiz=0, asiz=0; + + if (filename) + { + fprintf(stderr, + "%s: no files: not compiled with XPM or Pixbuf support.\n", + progname); + exit (1); + } + + if (! xpm_data) abort(); + ximage = minixpm_to_ximage (dpy, visual, cmap, depth, background_color, + (const char * const *) xpm_data, + &iw, &ih, &pixels, &npixels, &mask); + if (pixels) free (pixels); + + bpl = ximage->bytes_per_line; + data = ximage->data; + ximage->data = malloc (ximage->height * bpl); + + /* Flip image upside down, for texture maps; + process the mask; and re-arrange the color components for GL. + */ + w8 = (ximage->width + 7) / 8; + + rmsk = ximage->red_mask; + gmsk = ximage->green_mask; + bmsk = ximage->blue_mask; + amsk = ~(rmsk|gmsk|bmsk); + + decode_mask (rmsk, &rpos, &rsiz); + decode_mask (gmsk, &gpos, &gsiz); + decode_mask (bmsk, &bpos, &bsiz); + decode_mask (amsk, &apos, &asiz); + + for (y = 0; y < ximage->height; y++) + { + int y2 = (ximage->height-1-y); + + unsigned int *oline = (unsigned int *) (ximage->data + (y * bpl)); + unsigned int *iline = (unsigned int *) (data + (y2 * bpl)); + + for (x = 0; x < ximage->width; x++) + { + unsigned long pixel = iline[x]; + unsigned char r = (pixel & rmsk) >> rpos; + unsigned char g = (pixel & gmsk) >> gpos; + unsigned char b = (pixel & bmsk) >> bpos; + unsigned char a = (mask + ? ((mask [(y2 * w8) + (x >> 3)] & (1 << (x % 8))) + ? 0xFF : 0) + : 0xFF); +# if 0 + pixel = ((r << rpos) | (g << gpos) | (b << bpos) | (a << apos)); +# else + pixel = ((a << 24) | (b << 16) | (g << 8) | r); +# endif + oline[x] = pixel; + } + } + free (data); + + return ximage; +} + +#endif /* !HAVE_XPM */ + + +/* Returns an XImage structure containing the bits of the given XPM image. + This XImage will be 32 bits per pixel, 8 each per R, G, and B, with the + extra byte set to either 0xFF or 0x00 (based on the XPM file's mask.) + + The Display and Visual arguments are used only for creating the XImage; + no bits are pushed to the server. + + The Colormap argument is used just for parsing color names; no colors + are allocated. + */ +XImage * +xpm_to_ximage (Display *dpy, Visual *visual, Colormap cmap, + char **xpm_data) +{ + return xpm_to_ximage_1 (dpy, visual, cmap, 0, xpm_data); +} + + +XImage * +xpm_file_to_ximage (Display *dpy, Visual *visual, Colormap cmap, + const char *filename) +{ + return xpm_to_ximage_1 (dpy, visual, cmap, filename, 0); +} diff --git a/hacks/glx/xpm-ximage.h b/hacks/glx/xpm-ximage.h new file mode 100644 index 00000000..234f76bf --- /dev/null +++ b/hacks/glx/xpm-ximage.h @@ -0,0 +1,31 @@ +/* xpm-ximage.h --- converts XPM data to an XImage for use with OpenGL. + * xscreensaver, Copyright (c) 1998, 2002 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. + */ + +#ifndef _XPM_TEXTURE_H_ +#define _XPM_TEXTURE_H_ + +/* Returns an XImage structure containing the bits of the given XPM image. + This XImage will be 32 bits per pixel, 8 each per R, G, and B, with the + extra byte set to 0xFF. + + The Display and Visual arguments are used only for creating the XImage; + no bits are pushed to the server. + + The Colormap argument is used just for parsing color names; no colors + are allocated. + */ +extern XImage *xpm_to_ximage (Display *, Visual *, Colormap, + char **xpm_data); +extern XImage *xpm_file_to_ximage (Display *, Visual *, Colormap, + const char *filename); + +#endif /* _XPM_TEXTURE_H_ */ diff --git a/hacks/glx/xscreensaver-gl-helper.c b/hacks/glx/xscreensaver-gl-helper.c new file mode 100644 index 00000000..6da8a7f4 --- /dev/null +++ b/hacks/glx/xscreensaver-gl-helper.c @@ -0,0 +1,74 @@ +/* xscreensaver, Copyright (c) 2000, 2002 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. + */ + +/* xscreensaver-gl-helper -- prints the ID of the best visual to use + for GL programs on stdout. + */ + +#include "utils.h" +#include "visual.h" + +#include +#include + +char *progname = 0; +char *progclass = "XScreenSaver"; + +int +main (int argc, char **argv) +{ + Display *dpy; + Screen *screen; + Visual *visual; + char *d = getenv ("DISPLAY"); + int i; + + progname = argv[0]; + for (i = 1; i < argc; i++) + { + if (argv[i][0] == '-' && argv[i][1] == '-') argv[i]++; + if (strlen(argv[i]) >= 2 && + !strncmp ("-display", argv[i], strlen(argv[i]))) + { + if (i == argc-1) goto LOSE; + d = argv[i+1]; + i++; + } + else + { + LOSE: + fprintf (stderr, "usage: %s [ -display host:dpy.screen ]\n", + progname); + fprintf (stderr, + "This program prints out the ID of the best " + "X visual for GL programs to use.\n"); + exit (1); + } + } + + dpy = XOpenDisplay (d); + if (!dpy) + { + fprintf (stderr, "%s: couldn't open display %s\n", progname, + (d ? d : "(null)")); + exit (1); + } + + screen = DefaultScreenOfDisplay (dpy); + visual = get_gl_visual (screen); + + if (visual) + printf ("0x%x\n", (unsigned int) XVisualIDFromVisual (visual)); + else + printf ("none\n"); + + exit (0); +} diff --git a/hacks/glx/xscreensaver-gl-helper.man b/hacks/glx/xscreensaver-gl-helper.man new file mode 100644 index 00000000..7c40eb37 --- /dev/null +++ b/hacks/glx/xscreensaver-gl-helper.man @@ -0,0 +1,33 @@ +.TH XScreenSaver 1 "5-Nov-00" "X Version 11" +.SH NAME +xscreensaver-gl-helper - figure out which X visual to use for GL programs +.SH SYNOPSIS +.B xscreensaver-gl-helper +[\-display \fIhost:display.screen\fP] +.SH DESCRIPTION +This program prints the ID of the visual that should be used for proper +operation of OpenGL programs. This program only exists so that the +.BR xscreensaver (1) +daemon does not need to link against the OpenGL library. +.SH ENVIRONMENT +.PP +.TP 8 +.B DISPLAY +to get the default host, display, and screen number. +.SH SEE ALSO +.BR X (1), +.BR xdpyinfo (1), +.BR xglinfo (1), +.BR glxinfo (1), +.BR glxdpyinfo (1), +.BR xscreensaver (1), +.BR xscreensaver\-demo (1), +.BR xscreensaver\-command (1) +.SH COPYRIGHT +Copyright \(co 2000 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. diff --git a/hacks/goop.c b/hacks/goop.c new file mode 100644 index 00000000..02a5b113 --- /dev/null +++ b/hacks/goop.c @@ -0,0 +1,600 @@ +/* xscreensaver, Copyright (c) 1997-2008 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. + */ + +#include +#include "screenhack.h" +#include "spline.h" +#include "alpha.h" + + +/* This is pretty compute-intensive, probably due to the large number of + polygon fills. I tried introducing a scaling factor to make the spline + code emit fewer line segments, but that made the edges very rough. + However, tuning *maxVelocity, *elasticity and *delay can result in much + smoother looking animation. I tuned these for a 1280x1024 Indy display, + but I don't know whether these values will be reasonable for a slower + machine... + + The more planes the better -- SGIs have a 12-bit pseudocolor display + (4096 colormap cells) which is mostly useless, except for this program, + where it means you can have 11 or 12 mutually-transparent objects instead + of only 7 or 8. But, if you are using the 12-bit visual, you should crank + down the velocity and elasticity, or server slowness will cause the + animation to look jerky (yes, it's sad but true, SGI's X server is + perceptibly slower when using plane masks on a 12-bit visual than on an + 8-bit visual.) Using -max-velocity 0.5 -elasticity 0.9 seems to work ok + on my Indy R5k with visual 0x27 and the bottom-of-the-line 24-bit graphics + board. + + It might look better if each blob had an outline, which was a *slightly* + darker color than the center, to give them a bit more definition -- but + that would mean using two planes per blob. (Or maybe allocating the + outline colors outside of the plane-space? Then the outlines wouldn't be + transparent, but maybe that wouldn't be so noticeable?) + + Oh, for an alpha channel... maybe I should rewrite this in GL. Then the + blobs could have thickness, and curved edges with specular reflections... + */ + +#define SCALE 10000 /* fixed-point math, for sub-pixel motion */ +#define DEF_COUNT 12 /* When planes and count are 0, how many blobs. */ + +#define RAND(n) ((long) ((random() & 0x7fffffff) % ((long) (n)))) +#define RANDSIGN() ((random() & 1) ? 1 : -1) + +struct blob { + long x, y; /* position of midpoint */ + long dx, dy; /* velocity and direction */ + double torque; /* rotational speed */ + double th; /* angle of rotation */ + long elasticity; /* how fast they deform */ + long max_velocity; /* speed limit */ + long min_r, max_r; /* radius range */ + int npoints; /* control points */ + long *r; /* radii */ + spline *spline; +}; + +struct layer { + int nblobs; + struct blob **blobs; + Pixmap pixmap; + unsigned long pixel; + GC gc; +}; + +enum goop_mode { + transparent, + opaque, + xor, + outline +}; + +struct goop { + enum goop_mode mode; + int width, height; + int nlayers; + struct layer **layers; + unsigned long background; + Pixmap pixmap; + GC pixmap_gc; + GC window_gc; + Bool additive_p; + Bool cmap_p; + int delay; +}; + + +static struct blob * +make_blob (Display *dpy, int maxx, int maxy, int size) +{ + struct blob *b = (struct blob *) calloc(1, sizeof(*b)); + int i; + int mid; + + maxx *= SCALE; + maxy *= SCALE; + size *= SCALE; + + b->max_r = size/2; + b->min_r = size/10; + + if (b->min_r < (5*SCALE)) b->min_r = (5*SCALE); + mid = ((b->min_r + b->max_r) / 2); + + b->torque = get_float_resource (dpy, "torque", "Torque"); + b->elasticity = SCALE * get_float_resource (dpy, "elasticity", "Elasticity"); + b->max_velocity = SCALE * get_float_resource (dpy, "maxVelocity", "MaxVelocity"); + + b->x = RAND(maxx); + b->y = RAND(maxy); + + b->dx = RAND(b->max_velocity) * RANDSIGN(); + b->dy = RAND(b->max_velocity) * RANDSIGN(); + b->th = frand(M_PI+M_PI) * RANDSIGN(); + b->npoints = (random() % 5) + 5; + + b->spline = make_spline (b->npoints); + b->r = (long *) malloc (sizeof(*b->r) * b->npoints); + for (i = 0; i < b->npoints; i++) + b->r[i] = (long) ((random() % mid) + (mid/2)) * RANDSIGN(); + return b; +} + +static void +throb_blob (struct blob *b) +{ + int i; + double frac = ((M_PI+M_PI) / b->npoints); + + for (i = 0; i < b->npoints; i++) + { + long r = b->r[i]; + long ra = (r > 0 ? r : -r); + double th = (b->th > 0 ? b->th : -b->th); + long x, y; + + /* place control points evenly around perimiter, shifted by theta */ + x = b->x + ra * cos (i * frac + th); + y = b->y + ra * sin (i * frac + th); + + b->spline->control_x[i] = x / SCALE; + b->spline->control_y[i] = y / SCALE; + + /* alter the radius by a random amount, in the direction in which + it had been going (the sign of the radius indicates direction.) */ + ra += (RAND(b->elasticity) * (r > 0 ? 1 : -1)); + r = ra * (r >= 0 ? 1 : -1); + + /* If we've reached the end (too long or too short) reverse direction. */ + if ((ra > b->max_r && r >= 0) || + (ra < b->min_r && r < 0)) + r = -r; + /* And reverse direction in mid-course once every 50 times. */ + else if (! (random() % 50)) + r = -r; + + b->r[i] = r; + } +} + +static void +move_blob (struct blob *b, int maxx, int maxy) +{ + maxx *= SCALE; + maxy *= SCALE; + + b->x += b->dx; + b->y += b->dy; + + /* If we've reached the edge of the box, reverse direction. */ + if ((b->x > maxx && b->dx >= 0) || + (b->x < 0 && b->dx < 0)) + { + b->dx = -b->dx; + } + if ((b->y > maxy && b->dy >= 0) || + (b->y < 0 && b->dy < 0)) + { + b->dy = -b->dy; + } + + /* Alter velocity randomly. */ + if (! (random() % 10)) + { + b->dx += (RAND(b->max_velocity/2) * RANDSIGN()); + b->dy += (RAND(b->max_velocity/2) * RANDSIGN()); + + /* Throttle velocity */ + if (b->dx > b->max_velocity || b->dx < -b->max_velocity) + b->dx /= 2; + if (b->dy > b->max_velocity || b->dy < -b->max_velocity) + b->dy /= 2; + } + + { + double th = b->th; + double d = (b->torque == 0 ? 0 : frand(b->torque)); + if (th < 0) + th = -(th + d); + else + th += d; + + if (th > (M_PI+M_PI)) + th -= (M_PI+M_PI); + else if (th < 0) + th += (M_PI+M_PI); + + b->th = (b->th > 0 ? th : -th); + } + + /* Alter direction of rotation randomly. */ + if (! (random() % 100)) + b->th *= -1; +} + +static void +draw_blob (Display *dpy, Drawable drawable, GC gc, struct blob *b, + Bool fill_p) +{ + compute_closed_spline (b->spline); +#ifdef DEBUG + { + int i; + for (i = 0; i < b->npoints; i++) + XDrawLine (dpy, drawable, gc, b->x/SCALE, b->y/SCALE, + b->spline->control_x[i], b->spline->control_y[i]); + } +#else + if (fill_p) + XFillPolygon (dpy, drawable, gc, b->spline->points, b->spline->n_points, + Nonconvex, CoordModeOrigin); + else +#endif + XDrawLines (dpy, drawable, gc, b->spline->points, b->spline->n_points, + CoordModeOrigin); +} + + +static struct layer * +make_layer (Display *dpy, Window window, int width, int height, int nblobs) +{ + int i; + struct layer *layer = (struct layer *) calloc(1, sizeof(*layer)); + int blob_min, blob_max; + XGCValues gcv; + layer->nblobs = nblobs; + + layer->blobs = (struct blob **) malloc(sizeof(*layer->blobs)*layer->nblobs); + + blob_max = (width < height ? width : height) / 2; + blob_min = (blob_max * 2) / 3; + for (i = 0; i < layer->nblobs; i++){ + int j = blob_max - blob_min; + layer->blobs[i] = make_blob (dpy, width, height, + (j ? random() % j : 0) + blob_min); + } + + layer->pixmap = XCreatePixmap (dpy, window, width, height, 1); + layer->gc = XCreateGC (dpy, layer->pixmap, 0, &gcv); + +# ifdef HAVE_COCOA + jwxyz_XSetAlphaAllowed (dpy, layer->gc, True); +# endif /* HAVE_COCOA */ + + return layer; +} + + +#ifndef HAVE_COCOA +static void +draw_layer_plane (Display *dpy, struct layer *layer, int width, int height) +{ + int i; + for (i = 0; i < layer->nblobs; i++) + { + throb_blob (layer->blobs[i]); + move_blob (layer->blobs[i], width, height); + draw_blob (dpy, layer->pixmap, layer->gc, layer->blobs[i], True); + } +} +#endif /* !HAVE_COCOA */ + + +static void +draw_layer_blobs (Display *dpy, Drawable drawable, GC gc, + struct layer *layer, int width, int height, + Bool fill_p) +{ + int i; + for (i = 0; i < layer->nblobs; i++) + { + draw_blob (dpy, drawable, gc, layer->blobs[i], fill_p); + throb_blob (layer->blobs[i]); + move_blob (layer->blobs[i], width, height); + } +} + + +static struct goop * +make_goop (Screen *screen, Visual *visual, Window window, Colormap cmap, + int width, int height, long depth) +{ + Display *dpy = DisplayOfScreen (screen); + int i; + struct goop *goop = (struct goop *) calloc(1, sizeof(*goop)); + XGCValues gcv; + int nblobs = get_integer_resource (dpy, "count", "Count"); + + unsigned long *plane_masks = 0; +# ifndef HAVE_COCOA + unsigned long base_pixel = 0; +# endif + char *s; + + s = get_string_resource (dpy, "mode", "Mode"); + goop->mode = transparent; + if (!s || !*s || !strcasecmp (s, "transparent")) + ; + else if (!strcasecmp (s, "opaque")) + goop->mode = opaque; + else if (!strcasecmp (s, "xor")) + goop->mode = xor; + else + fprintf (stderr, "%s: bogus mode: \"%s\"\n", progname, s); + + goop->delay = get_integer_resource (dpy, "delay", "Integer"); + + goop->width = width; + goop->height = height; + + goop->nlayers = get_integer_resource (dpy, "planes", "Planes"); + if (goop->nlayers <= 0) + goop->nlayers = (random() % (depth-2)) + 2; + if (! goop->layers) + goop->layers = (struct layer **) + malloc(sizeof(*goop->layers)*goop->nlayers); + + goop->additive_p = get_boolean_resource (dpy, "additive", "Additive"); + goop->cmap_p = has_writable_cells (screen, visual); + + if (mono_p && goop->mode == transparent) + goop->mode = opaque; + +# ifndef HAVE_COCOA + /* Try to allocate some color planes before committing to nlayers. + */ + if (goop->mode == transparent) + { + int nplanes = goop->nlayers; + allocate_alpha_colors (screen, visual, cmap, + &nplanes, goop->additive_p, &plane_masks, + &base_pixel); + if (nplanes > 1) + goop->nlayers = nplanes; + else + { + fprintf (stderr, + "%s: couldn't allocate any color planes; turning transparency off.\n", + progname); + goop->mode = opaque; + } + } +# endif /* !HAVE_COCOA */ + + { + int lblobs[32]; + int total = DEF_COUNT; + memset (lblobs, 0, sizeof(lblobs)); + if (nblobs <= 0) + while (total) + for (i = 0; total && i < goop->nlayers; i++) + lblobs[i]++, total--; + for (i = 0; i < goop->nlayers; i++) + goop->layers[i] = make_layer (dpy, window, width, height, + (nblobs > 0 ? nblobs : lblobs[i])); + } + +# ifndef HAVE_COCOA + if (goop->mode == transparent && plane_masks) + { + for (i = 0; i < goop->nlayers; i++) + goop->layers[i]->pixel = base_pixel | plane_masks[i]; + goop->background = base_pixel; + } +# endif /* !HAVE_COCOA */ + + if (plane_masks) + free (plane_masks); + +# ifndef HAVE_COCOA + if (goop->mode != transparent) +# endif /* !HAVE_COCOA */ + { + XColor color; + color.flags = DoRed|DoGreen|DoBlue; + + goop->background = + get_pixel_resource (dpy,cmap, "background", "Background"); + + for (i = 0; i < goop->nlayers; i++) + { + int H = random() % 360; /* range 0-360 */ + double S = ((double) (random()%70) + 30)/100.0; /* range 30%-100% */ + double V = ((double) (random()%34) + 66)/100.0; /* range 66%-100% */ + hsv_to_rgb (H, S, V, &color.red, &color.green, &color.blue); + if (XAllocColor (dpy, cmap, &color)) + goop->layers[i]->pixel = color.pixel; + else + goop->layers[i]->pixel = + WhitePixelOfScreen(DefaultScreenOfDisplay(dpy)); +# ifdef HAVE_COCOA + if (goop->mode == transparent) + { + /* give a non-opaque alpha to the color */ + unsigned long pixel = goop->layers[i]->pixel; + unsigned long amask = BlackPixelOfScreen (0); + unsigned long a = (0xBBBBBBBB & amask); + pixel = (pixel & (~amask)) | a; + goop->layers[i]->pixel = pixel; + } +# endif /* HAVE_COCOA */ + } + } + + goop->pixmap = XCreatePixmap (dpy, window, width, height, + (goop->mode == xor ? 1L : depth)); + + gcv.background = goop->background; + gcv.foreground = get_pixel_resource (dpy, cmap, "foreground", "Foreground"); + gcv.line_width = get_integer_resource (dpy, "thickness","Thickness"); + goop->pixmap_gc = XCreateGC (dpy, goop->pixmap, GCLineWidth, &gcv); + goop->window_gc = XCreateGC (dpy, window, GCForeground|GCBackground, &gcv); + +# ifdef HAVE_COCOA + jwxyz_XSetAlphaAllowed (dpy, goop->pixmap_gc, True); +# endif /* HAVE_COCOA */ + + return goop; +} + +static void * +goop_init (Display *dpy, Window window) +{ + XWindowAttributes xgwa; + XGetWindowAttributes (dpy, window, &xgwa); + return make_goop (xgwa.screen, xgwa.visual, window, xgwa.colormap, + xgwa.width, xgwa.height, xgwa.depth); +} + +static unsigned long +goop_draw (Display *dpy, Window window, void *closure) +{ + struct goop *goop = (struct goop *) closure; + int i; + + switch (goop->mode) + { +# ifndef HAVE_COCOA + case transparent: + + for (i = 0; i < goop->nlayers; i++) + draw_layer_plane (dpy, goop->layers[i], goop->width, goop->height); + + XSetForeground (dpy, goop->pixmap_gc, goop->background); + XSetFunction (dpy, goop->pixmap_gc, GXcopy); + XSetPlaneMask (dpy, goop->pixmap_gc, AllPlanes); + XFillRectangle (dpy, goop->pixmap, goop->pixmap_gc, 0, 0, + goop->width, goop->height); + + XSetForeground (dpy, goop->pixmap_gc, ~0L); + + if (!goop->cmap_p && !goop->additive_p) + { + int j; + for (i = 0; i < goop->nlayers; i++) + for (j = 0; j < goop->layers[i]->nblobs; j++) + draw_blob (dpy, goop->pixmap, goop->pixmap_gc, + goop->layers[i]->blobs[j], True); + XSetFunction (dpy, goop->pixmap_gc, GXclear); + } + + for (i = 0; i < goop->nlayers; i++) + { + XSetPlaneMask (dpy, goop->pixmap_gc, goop->layers[i]->pixel); + draw_layer_blobs (dpy, goop->pixmap, goop->pixmap_gc, + goop->layers[i], goop->width, goop->height, + True); + } + XCopyArea (dpy, goop->pixmap, window, goop->window_gc, 0, 0, + goop->width, goop->height, 0, 0); + break; +#endif /* !HAVE_COCOA */ + + case xor: + XSetFunction (dpy, goop->pixmap_gc, GXcopy); + XSetForeground (dpy, goop->pixmap_gc, 0); + XFillRectangle (dpy, goop->pixmap, goop->pixmap_gc, 0, 0, + goop->width, goop->height); + XSetFunction (dpy, goop->pixmap_gc, GXxor); + XSetForeground (dpy, goop->pixmap_gc, 1); + for (i = 0; i < goop->nlayers; i++) + draw_layer_blobs (dpy, goop->pixmap, goop->pixmap_gc, + goop->layers[i], goop->width, goop->height, + (goop->mode != outline)); + XCopyPlane (dpy, goop->pixmap, window, goop->window_gc, 0, 0, + goop->width, goop->height, 0, 0, 1L); + break; + +# ifdef HAVE_COCOA + case transparent: +# endif + case opaque: + case outline: + XSetForeground (dpy, goop->pixmap_gc, goop->background); + XFillRectangle (dpy, goop->pixmap, goop->pixmap_gc, 0, 0, + goop->width, goop->height); + for (i = 0; i < goop->nlayers; i++) + { + XSetForeground (dpy, goop->pixmap_gc, goop->layers[i]->pixel); + draw_layer_blobs (dpy, goop->pixmap, goop->pixmap_gc, + goop->layers[i], goop->width, goop->height, + (goop->mode != outline)); + } + XCopyArea (dpy, goop->pixmap, window, goop->window_gc, 0, 0, + goop->width, goop->height, 0, 0); + break; + + default: + abort (); + break; + } + return goop->delay; +} + +static void +goop_reshape (Display *dpy, Window window, void *closure, + unsigned int w, unsigned int h) +{ + struct goop *goop = (struct goop *) closure; + + /* #### leaks like crazy */ + struct goop *goop2 = goop_init (dpy, window); + memcpy (goop, goop2, sizeof(*goop)); +} + +static Bool +goop_event (Display *dpy, Window window, void *closure, XEvent *event) +{ + return False; +} + +static void +goop_free (Display *dpy, Window window, void *closure) +{ +} + + + + +static const char *goop_defaults [] = { + ".background: black", + ".foreground: yellow", + "*delay: 12000", + "*additive: true", + "*mode: transparent", + "*count: 1", + "*planes: 12", + "*thickness: 5", + "*torque: 0.0075", + "*elasticity: 0.9", + "*maxVelocity: 0.5", + 0 +}; + +static XrmOptionDescRec goop_options [] = { + { "-delay", ".delay", XrmoptionSepArg, 0 }, + { "-count", ".count", XrmoptionSepArg, 0 }, + { "-planes", ".planes", XrmoptionSepArg, 0 }, + { "-mode", ".mode", XrmoptionSepArg, 0 }, + { "-xor", ".mode", XrmoptionNoArg, "xor" }, + { "-transparent", ".mode", XrmoptionNoArg, "transparent" }, + { "-opaque", ".mode", XrmoptionNoArg, "opaque" }, + { "-additive", ".additive", XrmoptionNoArg, "True" }, + { "-subtractive", ".additive", XrmoptionNoArg, "false" }, + { "-thickness", ".thickness", XrmoptionSepArg, 0 }, + { "-torque", ".torque", XrmoptionSepArg, 0 }, + { "-elasticity", ".elasticity", XrmoptionSepArg, 0 }, + { "-max-velocity", ".maxVelocity", XrmoptionSepArg, 0 }, + { 0, 0, 0, 0 } +}; + +XSCREENSAVER_MODULE ("Goop", goop) diff --git a/hacks/goop.man b/hacks/goop.man new file mode 100644 index 00000000..573bd1ec --- /dev/null +++ b/hacks/goop.man @@ -0,0 +1,84 @@ +.TH XScreenSaver 1 "11-Jun-97" "X Version 11" +.SH NAME +goop - squishy transparent oil and bubble screenhack +.SH SYNOPSIS +.B goop +[\-display \fIhost:display.screen\fP] [\-foreground \fIcolor\fP] [\-background \fIcolor\fP] [\-window] [\-root] [\-mono] [\-install] [\-visual \fIvisual\fP] [\-transparent] [\-non\-transparent] [\-additive] [\-subtractive] [\-xor] [\-no\-xor] +[\-fps] +.SH DESCRIPTION +The \fIgoop\fP program draws a simulation of bubbles in layers of +overlapping multicolored translucent fluid. +.SH OPTIONS +.I goop +accepts the following options: +.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 \-mono +If on a color display, pretend we're on a monochrome display. +.TP 8 +.B \-install +Install a private colormap for the window. +.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 \-count \fIinteger\fP +How many bubbles to draw per layer. Default: random. +.TP 8 +.B \-planes \fIinteger\fP +How many planes to draw. Default: random, based on screen depth. +.TP 8 +.B \-delay \fImicroseconds\fP +How much of a delay should be introduced between steps of the animation. +Default 12000, or about 0.012 seconds. +.TP 8 +.B \-transparent +If \fI\-layers\fP is greater than 1, then each layer will be drawn in one +color, and when they overlap, the colors will be mixed. This is the default. +.TP 8 +.B \-non\-transparent +Turns off \fI\-transparent\fP. +.TP 8 +.B \-additive +If \fI\-transparent\fP is specified, then this option means that the colors +will be mixed using an additive color model, as if the blobs were projected +light. This is the default. +.TP 8 +.B \-subtractive +If \fI\-transparent\fP is specified, then this option means that the +colors will be mixed using a subtractive color model, as if the blobs were +translucent filters. +.TP 8 +.B \-xor +Draw with xor instead of the other color tricks. +.TP 8 +.B \-fps +Display the current frame rate and CPU load. +.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 1997 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 , 11-Jun-97. diff --git a/hacks/grav.c b/hacks/grav.c new file mode 100644 index 00000000..a6ea6312 --- /dev/null +++ b/hacks/grav.c @@ -0,0 +1,363 @@ +/* -*- Mode: C; tab-width: 4 -*- */ +/* grav --- planets spinning around a pulsar */ + +#if 0 +static const char sccsid[] = "@(#)grav.c 5.00 2000/11/01 xlockmore"; +#endif + +/*- + * Copyright (c) 1993 by Greg Boewring + * + * Permission to use, copy, modify, and distribute this software and its + * documentation for any purpose and without fee is hereby granted, + * provided that the above copyright notice appear in all copies and that + * both that copyright notice and this permission notice appear in + * supporting documentation. + * + * This file is provided AS IS with no warranties of any kind. The author + * shall have no liability with respect to the infringement of copyrights, + * trade secrets or any patents by this file or any part thereof. In no + * event will the author be liable for any lost revenue or profits or + * other special, indirect and consequential damages. + * + * Revision History: + * 01-Nov-2000: Allocation checks + * 10-May-1997: Compatible with xscreensaver + * 11-Jul-1994: color version + * 06-Oct-1993: Written by Greg Bowering + */ + +#ifdef STANDALONE +#define MODE_grav +#define DEFAULTS "*delay: 10000 \n" \ + "*count: 12 \n" \ + "*ncolors: 64 \n" \ + "*fpsSolid: true \n" \ + +#define BRIGHT_COLORS +# define grav_handle_event 0 +# include "xlockmore.h" /* in xscreensaver distribution */ +#else /* STANDALONE */ +# include "xlock.h" /* in xlockmore distribution */ +#endif /* STANDALONE */ + +#ifdef MODE_grav + +#define DEF_DECAY "True" /* Damping for decaying orbits */ +#define DEF_TRAIL "True" /* For trails (works good in mono only) */ + +static Bool decay; +static Bool trail; + +static XrmOptionDescRec opts[] = +{ + {"-decay", ".grav.decay", XrmoptionNoArg, "on"}, + {"+decay", ".grav.decay", XrmoptionNoArg, "off"}, + {"-trail", ".grav.trail", XrmoptionNoArg, "on"}, + {"+trail", ".grav.trail", XrmoptionNoArg, "off"} +}; +static argtype vars[] = +{ + {&decay, "decay", "Decay", DEF_DECAY, t_Bool}, + {&trail, "trail", "Trail", DEF_TRAIL, t_Bool} +}; +static OptionStruct desc[] = +{ + {"-/+decay", "turn on/off decaying orbits"}, + {"-/+trail", "turn on/off trail dots"} +}; + +ENTRYPOINT ModeSpecOpt grav_opts = +{sizeof opts / sizeof opts[0], opts, sizeof vars / sizeof vars[0], vars, desc}; + +#ifdef USE_MODULES +ModStruct grav_description = +{"grav", "init_grav", "draw_grav", "release_grav", + "refresh_grav", "init_grav", (char *) NULL, &grav_opts, + 10000, -12, 1, 1, 64, 1.0, "", + "Shows orbiting planets", 0, NULL}; + +#endif + +#define GRAV -0.02 /* Gravitational constant */ +#define DIST 16.0 +#define COLLIDE 0.0001 +#define ALMOST 15.99 +#define HALF 0.5 +/* #define INTRINSIC_RADIUS 200.0 */ +#define INTRINSIC_RADIUS ((float) (gp->height/5)) +#define STARRADIUS (unsigned int)(gp->height/(2*DIST)) +#define AVG_RADIUS (INTRINSIC_RADIUS/DIST) +#define RADIUS (unsigned int)(INTRINSIC_RADIUS/(POS(Z)+DIST)) + +#define XR HALF*ALMOST +#define YR HALF*ALMOST +#define ZR HALF*ALMOST + +#define VR 0.04 + +#define DIMENSIONS 3 +#define X 0 +#define Y 1 +#define Z 2 + +#define DAMP 0.999999 +#define MaxA 0.1 /* Maximum acceleration (w/ damping) */ + +#define POS(c) planet->P[c] +#define VEL(c) planet->V[c] +#define ACC(c) planet->A[c] + +#define Planet(x,y)\ + if ((x) >= 0 && (y) >= 0 && (x) <= gp->width && (y) <= gp->height) {\ + if (planet->ri < 2)\ + XDrawPoint(display, window, gc, (x), (y));\ + else\ + XFillArc(display, window, gc,\ + (x) - planet->ri / 2, (y) - planet->ri / 2, planet->ri, planet->ri,\ + 0, 23040);\ + } + +#define FLOATRAND(min,max) ((min)+(LRAND()/MAXRAND)*((max)-(min))) + +typedef struct { + double P[DIMENSIONS], V[DIMENSIONS], A[DIMENSIONS]; + int xi, yi, ri; + unsigned long colors; +} planetstruct; + +typedef struct { + int width, height; + int x, y, sr, nplanets; + unsigned long starcolor; + planetstruct *planets; +} gravstruct; + +static gravstruct *gravs = (gravstruct *) NULL; + +static void +init_planet(ModeInfo * mi, planetstruct * planet) +{ + Display *display = MI_DISPLAY(mi); + Window window = MI_WINDOW(mi); + GC gc = MI_GC(mi); + gravstruct *gp = &gravs[MI_SCREEN(mi)]; + +# ifdef HAVE_COCOA + jwxyz_XSetAntiAliasing (MI_DISPLAY(mi), MI_GC(mi), False); +# endif + + if (MI_NPIXELS(mi) > 2) + planet->colors = MI_PIXEL(mi, NRAND(MI_NPIXELS(mi))); + else + planet->colors = MI_WHITE_PIXEL(mi); + /* Initialize positions */ + POS(X) = FLOATRAND(-XR, XR); + POS(Y) = FLOATRAND(-YR, YR); + POS(Z) = FLOATRAND(-ZR, ZR); + + if (POS(Z) > -ALMOST) { + planet->xi = (int) + ((double) gp->width * (HALF + POS(X) / (POS(Z) + DIST))); + planet->yi = (int) + ((double) gp->height * (HALF + POS(Y) / (POS(Z) + DIST))); + } else + planet->xi = planet->yi = -1; + planet->ri = RADIUS; + + /* Initialize velocities */ + VEL(X) = FLOATRAND(-VR, VR); + VEL(Y) = FLOATRAND(-VR, VR); + VEL(Z) = FLOATRAND(-VR, VR); + + /* Draw planets */ + Planet(planet->xi, planet->yi); +} + +static void +draw_planet(ModeInfo * mi, planetstruct * planet) +{ + Display *display = MI_DISPLAY(mi); + Window window = MI_WINDOW(mi); + GC gc = MI_GC(mi); + gravstruct *gp = &gravs[MI_SCREEN(mi)]; + double D; /* A distance variable to work with */ + register unsigned char cmpt; + + D = POS(X) * POS(X) + POS(Y) * POS(Y) + POS(Z) * POS(Z); + if (D < COLLIDE) + D = COLLIDE; + D = sqrt(D); + D = D * D * D; + for (cmpt = X; cmpt < DIMENSIONS; cmpt++) { + ACC(cmpt) = POS(cmpt) * GRAV / D; + if (decay) { + if (ACC(cmpt) > MaxA) + ACC(cmpt) = MaxA; + else if (ACC(cmpt) < -MaxA) + ACC(cmpt) = -MaxA; + VEL(cmpt) = VEL(cmpt) + ACC(cmpt); + VEL(cmpt) *= DAMP; + } else { + /* update velocity */ + VEL(cmpt) = VEL(cmpt) + ACC(cmpt); + } + /* update position */ + POS(cmpt) = POS(cmpt) + VEL(cmpt); + } + + gp->x = planet->xi; + gp->y = planet->yi; + + if (POS(Z) > -ALMOST) { + planet->xi = (int) + ((double) gp->width * (HALF + POS(X) / (POS(Z) + DIST))); + planet->yi = (int) + ((double) gp->height * (HALF + POS(Y) / (POS(Z) + DIST))); + } else + planet->xi = planet->yi = -1; + + /* Mask */ + XSetForeground(display, gc, MI_BLACK_PIXEL(mi)); + Planet(gp->x, gp->y); + if (trail) { + XSetForeground(display, gc, planet->colors); + XDrawPoint(display, MI_WINDOW(mi), gc, gp->x, gp->y); + } + /* Move */ + gp->x = planet->xi; + gp->y = planet->yi; + planet->ri = RADIUS; + + /* Redraw */ + XSetForeground(display, gc, planet->colors); + Planet(gp->x, gp->y); +} + +ENTRYPOINT void +init_grav(ModeInfo * mi) +{ + Display *display = MI_DISPLAY(mi); + GC gc = MI_GC(mi); + unsigned char ball; + gravstruct *gp; + + if (gravs == NULL) { + if ((gravs = (gravstruct *) calloc(MI_NUM_SCREENS(mi), + sizeof (gravstruct))) == NULL) + return; + } + gp = &gravs[MI_SCREEN(mi)]; + + gp->width = MI_WIDTH(mi); + gp->height = MI_HEIGHT(mi); + + gp->sr = STARRADIUS; + + gp->nplanets = MI_COUNT(mi); + if (gp->nplanets < 0) { + if (gp->planets) { + (void) free((void *) gp->planets); + gp->planets = (planetstruct *) NULL; + } + gp->nplanets = NRAND(-gp->nplanets) + 1; /* Add 1 so its not too boring */ + } + if (gp->planets == NULL) { + if ((gp->planets = (planetstruct *) calloc(gp->nplanets, + sizeof (planetstruct))) == NULL) + return; + } + + MI_CLEARWINDOW(mi); + + if (MI_NPIXELS(mi) > 2) + gp->starcolor = MI_PIXEL(mi, NRAND(MI_NPIXELS(mi))); + else + gp->starcolor = MI_WHITE_PIXEL(mi); + for (ball = 0; ball < (unsigned char) gp->nplanets; ball++) + init_planet(mi, &gp->planets[ball]); + + /* Draw centrepoint */ + XDrawArc(display, MI_WINDOW(mi), gc, + gp->width / 2 - gp->sr / 2, gp->height / 2 - gp->sr / 2, gp->sr, gp->sr, + 0, 23040); +} + +ENTRYPOINT void +draw_grav(ModeInfo * mi) +{ + Display *display = MI_DISPLAY(mi); + Window window = MI_WINDOW(mi); + GC gc = MI_GC(mi); + register unsigned char ball; + gravstruct *gp; + + if (gravs == NULL) + return; + gp = &gravs[MI_SCREEN(mi)]; + if (gp->planets == NULL) + return; + + MI_IS_DRAWN(mi) = True; + /* Mask centrepoint */ + XSetForeground(display, gc, MI_BLACK_PIXEL(mi)); + XDrawArc(display, window, gc, + gp->width / 2 - gp->sr / 2, gp->height / 2 - gp->sr / 2, gp->sr, gp->sr, + 0, 23040); + + /* Resize centrepoint */ + switch (NRAND(4)) { + case 0: + if (gp->sr < (int) STARRADIUS) + gp->sr++; + break; + case 1: + if (gp->sr > 2) + gp->sr--; + } + + /* Draw centrepoint */ + XSetForeground(display, gc, gp->starcolor); + XDrawArc(display, window, gc, + gp->width / 2 - gp->sr / 2, gp->height / 2 - gp->sr / 2, gp->sr, gp->sr, + 0, 23040); + + for (ball = 0; ball < (unsigned char) gp->nplanets; ball++) + draw_planet(mi, &gp->planets[ball]); +} + +ENTRYPOINT void +reshape_grav(ModeInfo * mi, int width, int height) +{ + gravstruct *gp = &gravs[MI_SCREEN(mi)]; + gp->width = width; + gp->height = height; + XClearWindow (MI_DISPLAY (mi), MI_WINDOW(mi)); +} + +ENTRYPOINT void +release_grav(ModeInfo * mi) +{ + if (gravs != NULL) { + int screen; + + for (screen = 0; screen < MI_NUM_SCREENS(mi); screen++) { + gravstruct *gp = &gravs[screen]; + + if (gp->planets) + (void) free((void *) gp->planets); + } + (void) free((void *) gravs); + gravs = (gravstruct *) NULL; + } +} + +ENTRYPOINT void +refresh_grav(ModeInfo * mi) +{ + MI_CLEARWINDOW(mi); +} + +XSCREENSAVER_MODULE ("Grav", grav) + +#endif /* MODE_grav */ diff --git a/hacks/grav.man b/hacks/grav.man new file mode 100644 index 00000000..f7017a76 --- /dev/null +++ b/hacks/grav.man @@ -0,0 +1,78 @@ +.TH XScreenSaver 1 "10-May-97" "X Version 11" +.SH NAME +grav - draws a simple orbital simulation +.SH SYNOPSIS +.B grav +[\-display \fIhost:display.screen\fP] [\-foreground \fIcolor\fP] [\-background \fIcolor\fP] [\-window] [\-root] [\-mono] [\-install] [\-visual \fIvisual\fP] [\-ncolors \fIinteger\fP] [\-delay \fImicroseconds\fP] [\-count \fIinteger\fP] [\-decay] [\-no\-decay] [\-trail] [\-no\-trail] + +[\-fps] +.SH DESCRIPTION +The \fIgrav\fP program draws a simple orbital simulation +.SH OPTIONS +.I grav +accepts the following options: +.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 \-mono +If on a color display, pretend we're on a monochrome display. +.TP 8 +.B \-install +Install a private colormap for the window. +.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 \-ncolors \fIinteger\fP +How many colors should be used (if possible). Default 64. +The colors are chosen randomly. +.TP 8 +.B \-count \fIinteger\fP +Default 12. +.TP 8 +.B \-decay +.TP 8 +.B \-no\-decay +Whether orbits should decay. + +.TP 8 +.B \-trail +.TP 8 +.B \-no\-trail +Whether the objects should leave trails behind them (makes it look vaguely +like a cloud-chamber. + +.TP 8 +.B \-fps +Display the current frame rate and CPU load. +.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), +.BR xlock (1) +.SH COPYRIGHT +Copyright \(co 1993 by Greg Bowering. + +Permission to use, copy, modify, and distribute this software and its +documentation for any purpose and without fee is hereby granted, +provided that the above copyright notice appear in all copies and that +both that copyright notice and this permission notice appear in +supporting documentation. +.SH AUTHOR +Greg Bowering , 1993. + +Ability to run standalone or with \fIxscreensaver\fP added by +Jamie Zawinski , 10-May-97. diff --git a/hacks/greynetic.c b/hacks/greynetic.c new file mode 100644 index 00000000..2496cdf5 --- /dev/null +++ b/hacks/greynetic.c @@ -0,0 +1,290 @@ +/* xscreensaver, Copyright (c) 1992-2008 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. + */ + +#include "screenhack.h" + +#ifndef HAVE_COCOA +# define DO_STIPPLE +#endif + +#define NBITS 12 + +/* On some systems (notably MacOS X) these files are messed up. + * They're tiny, so we might as well just inline them here. + * + * # include + * # include + * # include + * # include + * # include + * # include + * # include + * # include + * # include + * # include + * # include + * # include +*/ + +#ifdef DO_STIPPLE +#define stipple_width 16 +#define stipple_height 4 +static unsigned char stipple_bits[] = { + 0x55, 0x55, 0xee, 0xee, 0x55, 0x55, 0xba, 0xbb}; + +#define cross_weave_width 16 +#define cross_weave_height 16 +static unsigned char cross_weave_bits[] = { + 0x55, 0x55, 0x88, 0x88, 0x55, 0x55, 0x22, 0x22, 0x55, 0x55, 0x88, 0x88, + 0x55, 0x55, 0x22, 0x22, 0x55, 0x55, 0x88, 0x88, 0x55, 0x55, 0x22, 0x22, + 0x55, 0x55, 0x88, 0x88, 0x55, 0x55, 0x22, 0x22}; + +#define dimple1_width 16 +#define dimple1_height 16 +static unsigned char dimple1_bits[] = { + 0x55, 0x55, 0x00, 0x00, 0x55, 0x55, 0x00, 0x00, 0x55, 0x55, 0x00, 0x00, + 0x55, 0x55, 0x00, 0x00, 0x55, 0x55, 0x00, 0x00, 0x55, 0x55, 0x00, 0x00, + 0x55, 0x55, 0x00, 0x00, 0x55, 0x55, 0x00, 0x00}; + +#define dimple3_width 16 +#define dimple3_height 16 +static unsigned char dimple3_bits[] = { + 0x11, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0x11, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x11, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x11, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; + +#define flipped_gray_width 4 +#define flipped_gray_height 2 +static char flipped_gray_bits[] = { 0x07, 0x0d}; +#define gray1_width 2 +#define gray1_height 2 +static char gray1_bits[] = { 0x01, 0x02}; +#define gray3_width 4 +#define gray3_height 4 +static char gray3_bits[] = { 0x01, 0x00, 0x04, 0x00}; +#define hlines2_width 1 +#define hlines2_height 2 +static char hlines2_bits[] = { 0x01, 0x00}; +#define light_gray_width 4 +#define light_gray_height 2 +static char light_gray_bits[] = { 0x08, 0x02}; +#define root_weave_width 4 +#define root_weave_height 4 +static char root_weave_bits[] = { 0x07, 0x0d, 0x0b, 0x0e}; +#define vlines2_width 2 +#define vlines2_height 1 +static char vlines2_bits[] = { 0x01}; +#define vlines3_width 3 +#define vlines3_height 1 +static char vlines3_bits[] = { 0x02}; + +#endif /* DO_STIPPLE */ + +struct state { + Display *dpy; + Window window; + + Pixmap pixmaps [NBITS]; + + GC gc; + int delay; + unsigned long fg, bg, pixels [512]; + int npixels; + int xlim, ylim; + Bool grey_p; + Colormap cmap; +}; + + +static void * +greynetic_init (Display *dpy, Window window) +{ + struct state *st = (struct state *) calloc (1, sizeof(*st)); +# ifdef DO_STIPPLE + int i; +# endif /* DO_STIPPLE */ + XGCValues gcv; + XWindowAttributes xgwa; + st->dpy = dpy; + st->window = window; + + XGetWindowAttributes (st->dpy, st->window, &xgwa); + st->xlim = xgwa.width; + st->ylim = xgwa.height; + st->cmap = xgwa.colormap; + st->npixels = 0; + st->grey_p = get_boolean_resource(st->dpy, "grey", "Boolean"); + gcv.foreground= st->fg= get_pixel_resource(st->dpy, st->cmap, "foreground","Foreground"); + gcv.background= st->bg= get_pixel_resource(st->dpy, st->cmap, "background","Background"); + + st->delay = get_integer_resource (st->dpy, "delay", "Integer"); + if (st->delay < 0) st->delay = 0; + +# ifndef DO_STIPPLE + st->gc = XCreateGC (st->dpy, st->window, GCForeground, &gcv); +# ifdef HAVE_COCOA /* allow non-opaque alpha components in pixel values */ + jwxyz_XSetAlphaAllowed (st->dpy, st->gc, True); +# endif /* HAVE_COCOA */ +# else /* DO_STIPPLE */ + gcv.fill_style= FillOpaqueStippled; + st->gc = XCreateGC (st->dpy, st->window, GCForeground|GCBackground|GCFillStyle, &gcv); + + i = 0; +# define BITS(n,w,h) \ + st->pixmaps [i++] = \ + XCreatePixmapFromBitmapData (st->dpy, st->window, (char *) n, w, h, 1, 0, 1) + + BITS (stipple_bits, stipple_width, stipple_height); + BITS (cross_weave_bits, cross_weave_width, cross_weave_height); + BITS (dimple1_bits, dimple1_width, dimple1_height); + BITS (dimple3_bits, dimple3_width, dimple3_height); + BITS (flipped_gray_bits, flipped_gray_width, flipped_gray_height); + BITS (gray1_bits, gray1_width, gray1_height); + BITS (gray3_bits, gray3_width, gray3_height); + BITS (hlines2_bits, hlines2_width, hlines2_height); + BITS (light_gray_bits, light_gray_width, light_gray_height); + BITS (root_weave_bits, root_weave_width, root_weave_height); + BITS (vlines2_bits, vlines2_width, vlines2_height); + BITS (vlines3_bits, vlines3_width, vlines3_height); +# endif /* DO_STIPPLE */ + return st; +} + +static unsigned long +greynetic_draw (Display *dpy, Window window, void *closure) +{ + struct state *st = (struct state *) closure; + int x, y, w=0, h=0, i; + XGCValues gcv; + + for (i = 0; i < 10; i++) /* minimize area, but don't try too hard */ + { + w = 50 + random () % (st->xlim - 50); + h = 50 + random () % (st->ylim - 50); + if (w + h < st->xlim && w + h < st->ylim) + break; + } + x = random () % (st->xlim - w); + y = random () % (st->ylim - h); +# ifdef DO_STIPPLE + gcv.stipple = st->pixmaps [random () % NBITS]; +# endif /* !DO_STIPPLE */ + if (mono_p) + { + MONO: + if (random () & 1) + gcv.foreground = st->fg, gcv.background = st->bg; + else + gcv.foreground = st->bg, gcv.background = st->fg; + } + else + { + XColor fgc, bgc; + if (st->npixels == sizeof (st->pixels) / sizeof (unsigned long)) + goto REUSE; + fgc.flags = bgc.flags = DoRed|DoGreen|DoBlue; + fgc.red = random (); + fgc.green = random (); + fgc.blue = random (); +# ifdef DO_STIPPLE + bgc.red = random (); + bgc.green = random (); + bgc.blue = random (); +# endif /* DO_STIPPLE */ + + if (st->grey_p) + { + fgc.green = fgc.blue = fgc.red; + bgc.green = bgc.blue = bgc.red; + } + + if (! XAllocColor (st->dpy, st->cmap, &fgc)) + goto REUSE; + st->pixels [st->npixels++] = fgc.pixel; + gcv.foreground = fgc.pixel; +# ifdef DO_STIPPLE + if (! XAllocColor (st->dpy, st->cmap, &bgc)) + goto REUSE; + st->pixels [st->npixels++] = bgc.pixel; + gcv.background = bgc.pixel; +# endif /* DO_STIPPLE */ + goto DONE; + REUSE: + if (st->npixels <= 0) + { + mono_p = 1; + goto MONO; + } + gcv.foreground = st->pixels [random () % st->npixels]; +# ifdef DO_STIPPLE + gcv.background = st->pixels [random () % st->npixels]; +# endif /* DO_STIPPLE */ + DONE: + ; + +# ifdef HAVE_COCOA + { + /* give a non-opaque alpha to the color */ + unsigned long pixel = gcv.foreground; + unsigned long amask = BlackPixelOfScreen (0); + unsigned long a = (random() & amask); + pixel = (pixel & (~amask)) | a; + gcv.foreground = pixel; + } +# endif /* !HAVE_COCOA */ + } +# ifndef DO_STIPPLE + XChangeGC (st->dpy, st->gc, GCForeground, &gcv); +# else /* DO_STIPPLE */ + XChangeGC (st->dpy, st->gc, GCStipple|GCForeground|GCBackground, &gcv); +# endif /* DO_STIPPLE */ + XFillRectangle (st->dpy, st->window, st->gc, x, y, w, h); + return st->delay; +} + + +static const char *greynetic_defaults [] = { + ".background: black", + ".foreground: white", + "*fpsSolid: true", + "*delay: 10000", + "*grey: false", + 0 +}; + +static XrmOptionDescRec greynetic_options [] = { + { "-delay", ".delay", XrmoptionSepArg, 0 }, + { "-grey", ".grey", XrmoptionNoArg, "True" }, + { 0, 0, 0, 0 } +}; + +static void +greynetic_reshape (Display *dpy, Window window, void *closure, + unsigned int w, unsigned int h) +{ + struct state *st = (struct state *) closure; + st->xlim = w; + st->ylim = h; +} + +static Bool +greynetic_event (Display *dpy, Window window, void *closure, XEvent *event) +{ + return False; +} + +static void +greynetic_free (Display *dpy, Window window, void *closure) +{ +} + +XSCREENSAVER_MODULE ("Greynetic", greynetic) + diff --git a/hacks/greynetic.man b/hacks/greynetic.man new file mode 100644 index 00000000..1144a820 --- /dev/null +++ b/hacks/greynetic.man @@ -0,0 +1,56 @@ +.TH XScreenSaver 1 "13-aug-92" "X Version 11" +.SH NAME +greynetic - draw random stippled/color rectangles +.SH SYNOPSIS +.B greynetic +[\-display \fIhost:display.screen\fP] [\-foreground \fIcolor\fP] [\-background \fIcolor\fP] [\-window] [\-root] [\-mono] [\-install] [\-visual \fIvisual\fP] [\-delay \fIusecs\fP] +[\-fps] +.SH DESCRIPTION +The \fIgreynetic\fP program draws random rectangles. +.SH OPTIONS +.I greynetic +accepts the following options: +.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 \-mono +If on a color display, pretend we're on a monochrome display. +.TP 8 +.B \-install +Install a private colormap for the window. +.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 \-delay \fImicroseconds\fP +Slow it down. +.TP 8 +.B \-fps +Display the current frame rate and CPU load. +.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 1992 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 , 13-aug-92. diff --git a/hacks/halftone.c b/hacks/halftone.c new file mode 100644 index 00000000..5cd78b50 --- /dev/null +++ b/hacks/halftone.c @@ -0,0 +1,394 @@ +/* halftone, Copyright (c) 2002 by Peter Jaric + * + * 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. + * + * Description: + * Draws the gravitational force in each point on the screen seen + * through a halftone dot pattern. The force is calculated from a set + * of moving mass points. View it from a distance for best effect. + */ + +#include +#include +#include +#include "screenhack.h" + +#define DEFAULT_DELAY 10000 +#define DEFAULT_SPACING 14 +#define DEFAULT_SIZE_FACTOR 1.5 +#define DEFAULT_COUNT 10 +#define DEFAULT_MIN_MASS 0.001 +#define DEFAULT_MAX_MASS 0.02 +#define DEFAULT_MIN_SPEED 0.001 +#define DEFAULT_MAX_SPEED 0.02 + + +typedef struct +{ + /* halftone dots */ + double * dots; + int dots_width; + int dots_height; + int spacing; + int max_dot_size; + + /* Moving gravity points */ + int gravity_point_count; + + double* gravity_point_x; + double* gravity_point_y; + double* gravity_point_mass; + double* gravity_point_x_inc; + double* gravity_point_y_inc; + + /* X stuff */ + Display *dpy; + Window window; + GC gc; + + int ncolors; + XColor *colors; + int color0, color1; + int color_tick, cycle_speed; + + /* Off screen buffer */ + Pixmap buffer; + GC buffer_gc; + int buffer_width; + int buffer_height; + + int delay; + +} halftone_screen; + + +static void update_buffer(halftone_screen *halftone, XWindowAttributes * attrs) +{ + if (halftone->buffer_width != attrs->width || + halftone->buffer_height != attrs->height) + { + XGCValues gc_values; + + if (halftone->buffer_width != -1 && + halftone->buffer_height != -1) + { + if (halftone->buffer != halftone->window) + XFreePixmap(halftone->dpy, halftone->buffer); + XFreeGC(halftone->dpy, halftone->buffer_gc); + } + + halftone->buffer_width = attrs->width; + halftone->buffer_height = attrs->height; +#ifdef HAVE_COCOA /* Don't second-guess Quartz's double-buffering */ + halftone->buffer = halftone->window; +#else + halftone->buffer = XCreatePixmap(halftone->dpy, halftone->window, halftone->buffer_width, halftone->buffer_height, attrs->depth); +#endif + + halftone->buffer_gc = XCreateGC(halftone->dpy, halftone->buffer, 0, &gc_values); + } +} + +static void update_dot_attributes(halftone_screen *halftone, XWindowAttributes * attrs) +{ + double dots_width = attrs->width / halftone->spacing + 1; + double dots_height = attrs->height / halftone->spacing + 1; + + if (halftone->dots == NULL || + (dots_width != halftone->dots_width || + dots_height != halftone->dots_height)) + { + if (halftone->dots != NULL) + free(halftone->dots); + + halftone->dots_width = dots_width; + halftone->dots_height = dots_height; + halftone->dots = (double *) malloc(halftone->dots_width * halftone->dots_height * sizeof(double)); + } +} + +static void * +halftone_init (Display *dpy, Window window) +{ + int x, y, i; + int count; + int spacing; + double factor; + double min_mass; + double max_mass; + double min_speed; + double max_speed; + XGCValues gc_values; + XWindowAttributes attrs; + halftone_screen *halftone; + + halftone = (halftone_screen *) calloc (1, sizeof(halftone_screen)); + + halftone->dpy = dpy; + halftone->window = window; + + halftone->delay = get_integer_resource (dpy, "delay", "Integer"); + halftone->delay = (halftone->delay < 0 ? DEFAULT_DELAY : halftone->delay); + + halftone->gc = XCreateGC (halftone->dpy, halftone->window, 0, &gc_values); + + halftone->buffer_width = -1; + halftone->buffer_height = -1; + halftone->dots = NULL; + + /* Read command line arguments and set all settings. */ + count = get_integer_resource (dpy, "count", "Count"); + halftone->gravity_point_count = count < 1 ? DEFAULT_COUNT : count; + + spacing = get_integer_resource (dpy, "spacing", "Integer"); + halftone->spacing = spacing < 1 ? DEFAULT_SPACING : spacing; + + factor = get_float_resource (dpy, "sizeFactor", "Double"); + halftone->max_dot_size = + (factor < 0 ? DEFAULT_SIZE_FACTOR : factor) * halftone->spacing; + + min_mass = get_float_resource (dpy, "minMass", "Double"); + min_mass = min_mass < 0 ? DEFAULT_MIN_MASS : min_mass; + + max_mass = get_float_resource (dpy, "maxMass", "Double"); + max_mass = max_mass < 0 ? DEFAULT_MAX_MASS : max_mass; + max_mass = max_mass < min_mass ? min_mass : max_mass; + + min_speed = get_float_resource (dpy, "minSpeed", "Double"); + min_speed = min_speed < 0 ? DEFAULT_MIN_SPEED : min_speed; + + max_speed = get_float_resource (dpy, "maxSpeed", "Double"); + max_speed = max_speed < 0 ? DEFAULT_MAX_SPEED : max_speed; + max_speed = max_speed < min_speed ? min_speed : max_speed; + + + /* Set up the moving gravity points. */ + halftone->gravity_point_x = (double *) malloc(halftone->gravity_point_count * sizeof(double)); + halftone->gravity_point_y = (double *) malloc(halftone->gravity_point_count * sizeof(double)); + halftone->gravity_point_mass = (double *) malloc(halftone->gravity_point_count * sizeof(double)); + halftone->gravity_point_x_inc = (double *) malloc(halftone->gravity_point_count * sizeof(double)); + halftone->gravity_point_y_inc = (double *) malloc(halftone->gravity_point_count * sizeof(double)); + + for (i = 0; i < halftone->gravity_point_count; i++) + { + halftone->gravity_point_x[i] = frand(1); + halftone->gravity_point_y[i] = frand(1); + halftone->gravity_point_mass[i] = min_mass + (max_mass - min_mass) * frand(1); + halftone->gravity_point_x_inc[i] = min_speed + (max_speed - min_speed) * frand(1); + halftone->gravity_point_y_inc[i] = min_speed + (max_speed - min_speed) * frand(1); + } + + + /* Set up the dots. */ + XGetWindowAttributes(halftone->dpy, halftone->window, &attrs); + + halftone->ncolors = get_integer_resource (dpy, "colors", "Colors"); + if (halftone->ncolors < 4) halftone->ncolors = 4; + halftone->colors = (XColor *) calloc(halftone->ncolors, sizeof(XColor)); + make_smooth_colormap (dpy, attrs.visual, attrs.colormap, + halftone->colors, &halftone->ncolors, + True, 0, False); + halftone->color0 = 0; + halftone->color1 = halftone->ncolors / 2; + halftone->cycle_speed = get_integer_resource (dpy, "cycleSpeed", "CycleSpeed"); + halftone->color_tick = 0; + + update_buffer(halftone, &attrs); + update_dot_attributes(halftone, &attrs); + + for (x = 0; x < halftone->dots_width; x++) + for (y = 0; y < halftone->dots_height; y++) + { + halftone->dots[x + y * halftone->dots_width] = 0; + } + + return halftone; +} + + + +static void fill_circle(Display *dpy, Window window, GC gc, int x, int y, int size) +{ + int start_x = x - (size / 2); + int start_y = y - (size / 2); + unsigned int width = size; + unsigned int height = size; + int angle1 = 0; + int angle2 = 360 * 64; /* A full circle */ + + XFillArc (dpy, window, gc, + start_x, start_y, width, height, + angle1, angle2); +} + +static void repaint_halftone(halftone_screen *halftone) +{ + int x, y; + /* + int x_offset = halftone->spacing / 2; + int y_offset = halftone->spacing / 2; + */ + int x_offset = 0; + int y_offset = 0; + + + /* Fill buffer with background color */ + XSetForeground (halftone->dpy, halftone->buffer_gc, + halftone->colors[halftone->color0].pixel); + XFillRectangle(halftone->dpy, halftone->buffer, halftone->buffer_gc, 0, 0, halftone->buffer_width, halftone->buffer_height); + + /* Draw dots on buffer */ + XSetForeground (halftone->dpy, halftone->buffer_gc, + halftone->colors[halftone->color1].pixel); + + if (halftone->color_tick++ >= halftone->cycle_speed) + { + halftone->color_tick = 0; + halftone->color0 = (halftone->color0 + 1) % halftone->ncolors; + halftone->color1 = (halftone->color1 + 1) % halftone->ncolors; + } + + for (x = 0; x < halftone->dots_width; x++) + for (y = 0; y < halftone->dots_height; y++) + fill_circle(halftone->dpy, halftone->buffer, halftone->buffer_gc, + x_offset + x * halftone->spacing, y_offset + y * halftone->spacing, + halftone->max_dot_size * halftone->dots[x + y * halftone->dots_width]); + + /* Copy buffer to window */ + if (halftone->buffer != halftone->window) + XCopyArea(halftone->dpy, halftone->buffer, halftone->window, halftone->gc, 0, 0, halftone->buffer_width, halftone->buffer_height, 0, 0); +} + +static double calculate_gravity(halftone_screen *halftone, int x, int y) +{ + int i; + double gx = 0; + double gy = 0; + + for (i = 0; i < halftone->gravity_point_count; i++) + { + double dx = ((double) x) - halftone->gravity_point_x[i] * halftone->dots_width; + double dy = ((double) y) - halftone->gravity_point_y[i] * halftone->dots_height; + double distance = sqrt(dx * dx + dy * dy); + + if (distance != 0) + { + double gravity = halftone->gravity_point_mass[i] / (distance * distance / (halftone->dots_width * halftone->dots_height)); + + gx += (dx / distance) * gravity; + gy += (dy / distance) * gravity; + } + } + + return sqrt(gx * gx + gy * gy); +} + +static void update_halftone(halftone_screen *halftone) +{ + int x, y, i; + XWindowAttributes attrs; + + XGetWindowAttributes(halftone->dpy, halftone->window, &attrs); + + /* Make sure we have a valid buffer */ + update_buffer(halftone, &attrs); + + /* Make sure all dot attributes (spacing, width, height, etc) are correct */ + update_dot_attributes(halftone, &attrs); + + /* Move gravity points */ + for (i = 0; i < halftone->gravity_point_count; i++) + { + halftone->gravity_point_x_inc[i] = + (halftone->gravity_point_x[i] >= 1 || halftone->gravity_point_x[i] <= 0 ? + -halftone->gravity_point_x_inc[i] : + halftone->gravity_point_x_inc[i]); + halftone->gravity_point_y_inc[i] = + (halftone->gravity_point_y[i] >= 1 || halftone->gravity_point_y[i] <= 0 ? + -halftone->gravity_point_y_inc[i] : + halftone->gravity_point_y_inc[i]); + + halftone->gravity_point_x[i] += halftone->gravity_point_x_inc[i]; + halftone->gravity_point_y[i] += halftone->gravity_point_y_inc[i]; + } + + /* Update gravity in each dot .*/ + for (x = 0; x < halftone->dots_width; x++) + for (y = 0; y < halftone->dots_height; y++) + { + double gravity = calculate_gravity(halftone, x, y); + + halftone->dots[x + y * halftone->dots_width] = (gravity > 1 ? 1 : (gravity < 0 ? 0 : gravity)); + } +} + + +static unsigned long +halftone_draw (Display *dpy, Window window, void *closure) +{ + halftone_screen *halftone = (halftone_screen *) closure; + + repaint_halftone(halftone); + update_halftone(halftone); + + return halftone->delay; +} + + +static void +halftone_reshape (Display *dpy, Window window, void *closure, + unsigned int w, unsigned int h) +{ +} + +static Bool +halftone_event (Display *dpy, Window window, void *closure, XEvent *event) +{ + return False; +} + +static void +halftone_free (Display *dpy, Window window, void *closure) +{ + halftone_screen *halftone = (halftone_screen *) closure; + free (halftone); +} + + +static const char *halftone_defaults [] = { + ".background: Black", + "*delay: 10000", + "*count: 10", + "*minMass: 0.001", + "*maxMass: 0.02", + "*minSpeed: 0.001", + "*maxSpeed: 0.02", + "*spacing: 14", + "*sizeFactor: 1.5", + "*colors: 200", + "*cycleSpeed: 10", + 0 +}; + +static XrmOptionDescRec halftone_options [] = { + { "-delay", ".delay", XrmoptionSepArg, 0 }, + { "-count", ".count", XrmoptionSepArg, 0 }, + { "-minmass", ".minMass", XrmoptionSepArg, 0 }, + { "-maxmass", ".maxMass", XrmoptionSepArg, 0 }, + { "-minspeed", ".minSpeed", XrmoptionSepArg, 0 }, + { "-maxspeed", ".maxSpeed", XrmoptionSepArg, 0 }, + { "-spacing", ".spacing", XrmoptionSepArg, 0 }, + { "-sizefactor", ".sizeFactor", XrmoptionSepArg, 0 }, + { "-colors", ".colors", XrmoptionSepArg, 0 }, + { "-cycle-speed", ".cycleSpeed", XrmoptionSepArg, 0 }, + { 0, 0, 0, 0 } +}; + + +XSCREENSAVER_MODULE ("Halftone", halftone) diff --git a/hacks/halftone.man b/hacks/halftone.man new file mode 100644 index 00000000..21ffb134 --- /dev/null +++ b/hacks/halftone.man @@ -0,0 +1,83 @@ +.TH XScreenSaver 1 "9-oct-2002" "X Version 11" +.SH NAME +halftone - simple halftone pattern of moving mass points +.SH SYNOPSIS +.B halftone +[\-display \fIhost:display.screen\fP] +[\-visual \fIvisual\fP] +[\-window] +[\-root] +[\-count \fInumber\fP] +[\-spacing \fInumber\fP] +[\-sizefactor \fInumber\fP] +[\-delay \fInumber\fP] +[\-minmass \fInumber\fP] +[\-maxmass \fInumber\fP] +[\-minspeed \fInumber\fP] +[\-maxspeed \fInumber\fP] +[\-fps] +.SH DESCRIPTION +Draws the gravity force in each point on the screen seen through a +halftone dot pattern. The gravity force is calculated from a set of +moving mass points. View it from a distance for best effect. +.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 \-count \fInumber\fP +How many mass points to move around. Default: 10 +.TP 8 +.B \-spacing \fInumber\fP +Distance between each halftone dot. Default: 14 +.TP 8 +.B \-sizefactor \fInumber\fP +How big each halftone dot should be drawn compared to the spacing value. Default: 1.5 +.TP 8 +.B \-minmass \fInumber\fP +The minimum mass of each mass point. Default: 0.001 +.TP 8 +.B \-maxmass \fInumber\fP +The maximum mass of each mass point. Default: 0.02 +.TP 8 +.B \-minspeed \fInumber\fP +The minimum speed of each mass point. Default: 0.001 +.TP 8 +.B \-maxspeed \fInumber\fP +The maximum speed of each mass point. Default: 0.02 +.B \-delay \fInumber\fP +Per-frame delay, in microseconds. Default: 10000 +.TP 8 +.B \-fps +Display the current frame rate and CPU load. +.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 2002 by Peter Jaric. 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 +Peter Jaric + diff --git a/hacks/halo.c b/hacks/halo.c new file mode 100644 index 00000000..2b7e30fb --- /dev/null +++ b/hacks/halo.c @@ -0,0 +1,436 @@ +/* xscreensaver, Copyright (c) 1993, 1995, 1996, 1997, 1998, 1999, 2003, 2006 + * 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. + */ + +/* I wanted to lay down new circles with TV:ALU-ADD instead of TV:ALU-XOR, + but X doesn't support arithmetic combinations of pixmaps!! What losers. + I suppose I could crank out the 2's compliment math by hand, but that's + a real drag... + + This would probably look good with shapes other than circles as well. + + */ + +#include "screenhack.h" +#include + +struct circle { + int x, y, radius; + int increment; + int dx, dy; +}; + +static enum color_mode { + seuss_mode, ramp_mode, random_mode +} cmode; + + +struct state { + Display *dpy; + Window window; + + struct circle *circles; + int count, global_count; + Pixmap pixmap, buffer; + int width, height, global_inc; + int delay, delay2; + unsigned long fg_pixel, bg_pixel; + GC draw_gc, erase_gc, copy_gc, merge_gc; + Bool anim_p; + Colormap cmap; + + int ncolors; + XColor *colors; + int fg_index; + int bg_index; + + int iterations; + Bool done_once; + Bool done_once_no_really; + int clear_tick; + struct timeval then; +}; + +#define min(x,y) ((x)<(y)?(x):(y)) +#define max(x,y) ((x)>(y)?(x):(y)) + +static void +init_circles_1 (struct state *st) +{ + int i; + st->count = (st->global_count ? st->global_count + : (3 + (random () % max (1, (min (st->width, st->height) / 50))) + + (random () % max (1, (min (st->width, st->height) / 50))))); + st->circles = (struct circle *) malloc (st->count * sizeof (struct circle)); + for (i = 0; i < st->count; i++) + { + st->circles [i].x = 10 + random () % (st->width - 20); + st->circles [i].y = 10 + random () % (st->height - 20); + if (st->global_inc) + st->circles [i].increment = st->global_inc; + else + { /* prefer smaller increments to larger ones */ + int j = 8; + int inc = ((random()%j) + (random()%j) + (random()%j)) - ((j*3)/2); + if (inc < 0) inc = -inc + 3; + st->circles [i].increment = inc + 3; + } + st->circles [i].radius = random () % st->circles [i].increment; + st->circles [i].dx = ((random () % 3) - 1) * (1 + random () % 5); + st->circles [i].dy = ((random () % 3) - 1) * (1 + random () % 5); + } +} + +static void * +halo_init (Display *dpy, Window window) +{ + struct state *st = (struct state *) calloc (1, sizeof(*st)); + XGCValues gcv; + XWindowAttributes xgwa; + char *mode_str = 0; + st->dpy = dpy; + st->window = window; + XGetWindowAttributes (st->dpy, st->window, &xgwa); + st->cmap = xgwa.colormap; + st->global_count = get_integer_resource (st->dpy, "count", "Integer"); + if (st->global_count < 0) st->global_count = 0; + st->global_inc = get_integer_resource (st->dpy, "increment", "Integer"); + if (st->global_inc < 0) st->global_inc = 0; + st->anim_p = get_boolean_resource (st->dpy, "animate", "Boolean"); + st->delay = get_integer_resource (st->dpy, "delay", "Integer"); + st->delay2 = get_integer_resource (st->dpy, "delay2", "Integer") * 1000000; + mode_str = get_string_resource (st->dpy, "colorMode", "ColorMode"); + if (! mode_str) cmode = random_mode; + else if (!strcmp (mode_str, "seuss")) cmode = seuss_mode; + else if (!strcmp (mode_str, "ramp")) cmode = ramp_mode; + else if (!strcmp (mode_str, "random")) cmode = random_mode; + else { + fprintf (stderr, + "%s: colorMode must be seuss, ramp, or random, not \"%s\"\n", + progname, mode_str); + exit (1); + } + + if (mono_p) cmode = seuss_mode; + if (cmode == random_mode) + cmode = ((random()&3) == 1) ? ramp_mode : seuss_mode; + + if (cmode == ramp_mode) + st->anim_p = False; /* This combo doesn't work right... */ + + st->ncolors = get_integer_resource (st->dpy, "colors", "Colors"); + if (st->ncolors < 2) st->ncolors = 2; + if (st->ncolors <= 2) mono_p = True; + + if (mono_p) + st->colors = 0; + else + st->colors = (XColor *) malloc(sizeof(*st->colors) * (st->ncolors+1)); + + + if (mono_p) + ; + else if (random() % (cmode == seuss_mode ? 2 : 10)) + make_uniform_colormap (st->dpy, xgwa.visual, st->cmap, st->colors, &st->ncolors, + True, 0, True); + else + make_smooth_colormap (st->dpy, xgwa.visual, st->cmap, st->colors, &st->ncolors, + True, 0, True); + + if (st->ncolors <= 2) mono_p = True; + if (mono_p) cmode = seuss_mode; + + if (mono_p) + { + st->fg_pixel = get_pixel_resource (st->dpy, st->cmap, "foreground", "Foreground"); + st->bg_pixel = get_pixel_resource (st->dpy, st->cmap, "background", "Background"); + } + else + { + st->fg_index = 0; + st->bg_index = st->ncolors / 4; + if (st->fg_index == st->bg_index) st->bg_index++; + st->fg_pixel = st->colors[st->fg_index].pixel; + st->bg_pixel = st->colors[st->bg_index].pixel; + } + + st->width = max (50, xgwa.width); + st->height = max (50, xgwa.height); + +#ifdef DEBUG + st->width/=2; st->height/=2; +#endif + + st->pixmap = XCreatePixmap (st->dpy, st->window, st->width, st->height, 1); + if (cmode == seuss_mode) + st->buffer = XCreatePixmap (st->dpy, st->window, st->width, st->height, 1); + else + st->buffer = 0; + + gcv.foreground = 1; + gcv.background = 0; + st->draw_gc = XCreateGC (st->dpy, st->pixmap, GCForeground | GCBackground, &gcv); + gcv.foreground = 0; + st->erase_gc = XCreateGC (st->dpy, st->pixmap, GCForeground, &gcv); + gcv.foreground = st->fg_pixel; + gcv.background = st->bg_pixel; + st->copy_gc = XCreateGC (st->dpy, st->window, GCForeground | GCBackground, &gcv); + +#ifdef HAVE_COCOA + jwxyz_XSetAntiAliasing (dpy, st->draw_gc, False); + jwxyz_XSetAntiAliasing (dpy, st->erase_gc, False); + jwxyz_XSetAntiAliasing (dpy, st->copy_gc, False); +#endif + + if (cmode == seuss_mode) + { + gcv.foreground = 1; + gcv.background = 0; + gcv.function = GXxor; + st->merge_gc = XCreateGC (st->dpy, st->pixmap, + GCForeground | GCBackground | GCFunction, &gcv); + } + else + { + gcv.foreground = st->fg_pixel; + gcv.background = st->bg_pixel; + gcv.function = GXcopy; + st->merge_gc = XCreateGC (st->dpy, st->window, + GCForeground | GCBackground | GCFunction, &gcv); + } + + init_circles_1 (st); + XClearWindow (st->dpy, st->window); + if (st->buffer) XFillRectangle (st->dpy, st->buffer, st->erase_gc, 0, 0, st->width, st->height); + return st; +} + +static unsigned long +halo_draw (Display *dpy, Window window, void *closure) +{ + struct state *st = (struct state *) closure; + int i; + Bool done = False; + Bool inhibit_sleep = False; + int this_delay = st->delay; + + XFillRectangle (st->dpy, st->pixmap, st->erase_gc, 0, 0, st->width, st->height); + for (i = 0; i < st->count; i++) + { + int radius = st->circles [i].radius; + int inc = st->circles [i].increment; + + if (! (st->iterations & 1)) /* never stop on an odd number of iterations */ + ; + else if (radius == 0) /* eschew inf */ + ; + else if (radius < 0) /* stop when the circles are points */ + done = True; + else /* stop when the circles fill the st->window */ + { + /* Probably there's a simpler way to ask the musical question, + "is this square completely enclosed by this circle," but I've + forgotten too much trig to know it... (That's not really the + right question anyway, but the right question is too hard.) */ + double x1 = ((double) (-st->circles [i].x)) / ((double) radius); + double y1 = ((double) (-st->circles [i].y)) / ((double) radius); + double x2 = ((double) (st->width - st->circles [i].x)) / ((double) radius); + double y2 = ((double) (st->height - st->circles [i].y)) / ((double) radius); + x1 *= x1; x2 *= x2; y1 *= y1; y2 *= y2; + if ((x1 + y1) < 1 && (x2 + y2) < 1 && (x1 + y2) < 1 && (x2 + y1) < 1) + done = True; + } + + if (radius > 0 && + (cmode == seuss_mode || /* drawing all circles, or */ + st->circles [0].increment < 0)) /* on the way back in */ + { + XFillArc (st->dpy, + (cmode == seuss_mode ? st->pixmap : st->window), + (cmode == seuss_mode ? st->draw_gc : st->merge_gc), + st->circles [i].x - radius, st->circles [i].y - radius, + radius * 2, radius * 2, 0, 360*64); + } + st->circles [i].radius += inc; + } + + if (st->anim_p && !st->done_once) + inhibit_sleep = !done; + + if (done) + { + if (st->anim_p) + { + st->done_once = True; + for (i = 0; i < st->count; i++) + { + st->circles [i].x += st->circles [i].dx; + st->circles [i].y += st->circles [i].dy; + st->circles [i].radius %= st->circles [i].increment; + if (st->circles [i].x < 0 || st->circles [i].x >= st->width) + { + st->circles [i].dx = -st->circles [i].dx; + st->circles [i].x += (2 * st->circles [i].dx); + } + if (st->circles [i].y < 0 || st->circles [i].y >= st->height) + { + st->circles [i].dy = -st->circles [i].dy; + st->circles [i].y += (2 * st->circles [i].dy); + } + } + } + else if (st->circles [0].increment < 0) + { + /* We've zoomed out and the screen is blank -- re-pick the + center points, and shift the st->colors. + */ + free (st->circles); + init_circles_1 (st); + if (! mono_p) + { + st->fg_index = (st->fg_index + 1) % st->ncolors; + st->bg_index = (st->fg_index + (st->ncolors/2)) % st->ncolors; + XSetForeground (st->dpy, st->copy_gc, st->colors [st->fg_index].pixel); + XSetBackground (st->dpy, st->copy_gc, st->colors [st->bg_index].pixel); + } + } + /* Sometimes go out from the inside instead of the outside */ + else if (st->clear_tick == 0 && ((random () % 3) == 0)) + { + st->iterations = 0; /* ick */ + for (i = 0; i < st->count; i++) + st->circles [i].radius %= st->circles [i].increment; + + st->clear_tick = ((random() % 8) + 4) | 1; /* must be odd */ + } + else + { + for (i = 0; i < st->count; i++) + { + st->circles [i].increment = -st->circles [i].increment; + st->circles [i].radius += (2 * st->circles [i].increment); + } + } + } + + if (st->buffer) + XCopyPlane (st->dpy, st->pixmap, st->buffer, st->merge_gc, 0, 0, st->width, st->height, 0, 0, 1); + else if (cmode != seuss_mode) + { + + if (!mono_p) + { + st->fg_index++; + st->bg_index++; + if (st->fg_index >= st->ncolors) st->fg_index = 0; + if (st->bg_index >= st->ncolors) st->bg_index = 0; + XSetForeground (st->dpy, st->merge_gc, st->colors [st->fg_index].pixel); + } + + if (st->circles [0].increment >= 0) + inhibit_sleep = True; + else if (done && cmode == seuss_mode) + XFillRectangle (st->dpy, st->window, st->merge_gc, 0, 0, st->width, st->height); + } + else + XCopyPlane (st->dpy, st->pixmap, st->window, st->merge_gc, 0, 0, st->width, st->height, 0, 0, 1); + + /* st->buffer is only used in seuss-mode or anim-mode */ + if (st->buffer && (st->anim_p + ? (done || (!st->done_once && (st->iterations & 1))) + : (st->iterations & 1))) + { + XCopyPlane (st->dpy, st->buffer, st->window, st->copy_gc, 0, 0, st->width, st->height, 0, 0, 1); + if (st->anim_p && done) + XFillRectangle (st->dpy, st->buffer, st->erase_gc, 0, 0, st->width, st->height); + } + +#ifdef DEBUG + XCopyPlane (st->dpy, st->pixmap, st->window, st->copy_gc, 0,0,st->width,st->height,st->width,st->height, 1); + if (st->buffer) + XCopyPlane (st->dpy, st->buffer, st->window, st->copy_gc, 0,0,st->width,st->height,0,st->height, 1); +#endif + + if (done) + st->iterations = 0; + else + st->iterations++; + + if (st->delay && !inhibit_sleep) + { + int d = st->delay; + + if (cmode == seuss_mode && st->anim_p) + this_delay = d/100; + else + this_delay = d; + + if (done) + st->done_once_no_really = True; + } + + if (done && st->clear_tick > 0) + { + st->clear_tick--; + if (!st->clear_tick) + { + XClearWindow (st->dpy, st->window); + if (st->buffer) XFillRectangle (st->dpy, st->buffer, st->erase_gc, 0,0,st->width,st->height); + } + } + + if (inhibit_sleep) this_delay = 0; + + return this_delay; +} + + + +static const char *halo_defaults [] = { + ".background: black", + ".foreground: white", + "*colorMode: random", + "*colors: 100", + "*count: 0", + "*delay: 100000", + "*delay2: 20", + "*increment: 0", + "*animate: False", + 0 +}; + +static XrmOptionDescRec halo_options [] = { + { "-count", ".count", XrmoptionSepArg, 0 }, + { "-delay", ".delay", XrmoptionSepArg, 0 }, + { "-animate", ".animate", XrmoptionNoArg, "True" }, + { "-mode", ".colorMode", XrmoptionSepArg, 0 }, + { "-colors", ".colors", XrmoptionSepArg, 0 }, + { 0, 0, 0, 0 } +}; + +static void +halo_reshape (Display *dpy, Window window, void *closure, + unsigned int w, unsigned int h) +{ +} + +static Bool +halo_event (Display *dpy, Window window, void *closure, XEvent *event) +{ + return False; +} + +static void +halo_free (Display *dpy, Window window, void *closure) +{ +} + +XSCREENSAVER_MODULE ("Halo", halo) diff --git a/hacks/halo.man b/hacks/halo.man new file mode 100644 index 00000000..98960c4f --- /dev/null +++ b/hacks/halo.man @@ -0,0 +1,75 @@ +.TH XScreenSaver 1 "12-Jun-97" "X Version 11" +.SH NAME +halo - draw circular patterns +.SH SYNOPSIS +.B halo +[\-display \fIhost:display.screen\fP] [\-foreground \fIcolor\fP] [\-background \fIcolor\fP] [\-window] [\-root] [\-mono] [\-install] [\-visual \fIvisual\fP] [\-count \fIint\fP] [\-delay \fIusecs\fP] [\-mode seuss | ramp | random ] [\-animate] [\-colors \fIinteger\fP] +[\-fps] +.SH DESCRIPTION +The \fIhalo\fP program draws cool patterns based on circles. +.SH OPTIONS +.I halo +accepts the following options: +.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 \-mono +If on a color display, pretend we're on a monochrome display. +.TP 8 +.B \-install +Install a private colormap for the window. +.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 \-count \fIinteger\fP +How many circles to draw. Default 0, meaning random. +.TP 8 +.B \-mode "seuss | ramp | random" +In \fIseuss\fP mode, alternating striped curves will be drawn. + +In \fIramp\fP mode, a color ramp will be drawn. + +\fIrandom\fP means pick the mode randomly. +.TP 8 +.B \-delay \fImicroseconds\fP +How much of a delay should be introduced between steps of the animation. +Default 100000, or about 0.1 second. +.TP 8 +.B \-colors \fIinteger\fP +How many colors to use. Default 100. +.TP 8 +.B \-animate +If specified, then the centerpoints of the circles will bounce around. +Otherwise, the circles will be drawn once, erased, and a new set of +circles will be drawn. +.TP 8 +.B \-fps +Display the current frame rate and CPU load. +.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 1993 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 , 6-jul-93. diff --git a/hacks/helix.c b/hacks/helix.c new file mode 100644 index 00000000..ea28f690 --- /dev/null +++ b/hacks/helix.c @@ -0,0 +1,353 @@ +/* xscreensaver, Copyright (c) 1992-2008 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. + */ + +/* Algorithm from a Mac program by Chris Tate, written in 1988 or so. */ + +/* 18-Sep-97: Johannes Keukelaar (johannes@nada.kth.se): Improved screen + * eraser. + * 10-May-97: merged ellipse code by Dan Stromberg + * as found in xlockmore 4.03a10. + * 1992: jwz created. + */ + +/* 25 April 2002: Matthew Strait added +-subdelay option so the drawing process can be watched */ + +#include +#include "screenhack.h" +#include "erase.h" + +enum draw_state { HELIX, DRAW_HELIX, TRIG, DRAW_TRIG, LINGER, ERASE }; + +struct state { + enum draw_state dstate; + double sins [360]; + double coss [360]; + + GC draw_gc; + unsigned int default_fg_pixel; + int sleep_time; + int subdelay; + eraser_state *eraser; + + int width, height; + Colormap cmap; + + int x1, y1, x2, y2, angle, i; + + int radius1, radius2, d_angle, factor1, factor2, factor3, factor4; + int d_angle_offset; + int offset, dir, density; +}; + +static void * +helix_init (Display *dpy, Window window) +{ + struct state *st = (struct state *) calloc (1, sizeof(*st)); + int i; + XGCValues gcv; + XWindowAttributes xgwa; + + st->sleep_time = get_integer_resource(dpy, "delay", "Integer"); + st->subdelay = get_integer_resource(dpy, "subdelay", "Integer"); + + XGetWindowAttributes (dpy, window, &xgwa); + st->width = xgwa.width; + st->height = xgwa.height; + st->cmap = xgwa.colormap; + gcv.foreground = st->default_fg_pixel = + get_pixel_resource (dpy, st->cmap, "foreground", "Foreground"); + st->draw_gc = XCreateGC (dpy, window, GCForeground, &gcv); + gcv.foreground = get_pixel_resource (dpy, st->cmap, "background", "Background"); + + for (i = 0; i < 360; i++) + { + st->sins [i] = sin ((((double) i) / 180.0) * M_PI); + st->coss [i] = cos ((((double) i) / 180.0) * M_PI); + } + + st->dstate = (random() & 1) ? HELIX : TRIG; + + return st; +} + +static int +gcd (int a, int b) +{ + while (b > 0) + { + int tmp; + tmp = a % b; + a = b; + b = tmp; + } + return (a < 0 ? -a : a); +} + +static void +helix (Display *dpy, Window window, struct state *st) +{ + int xmid = st->width / 2; + int ymid = st->height / 2; + int limit = 1 + (360 / gcd (360, st->d_angle)); + + if (st->i == 0) + { + st->x1 = xmid; + st->y1 = ymid + st->radius2; + st->x2 = xmid; + st->y2 = ymid + st->radius1; + st->angle = 0; + } + +/* for (st->i = 0; st->i < limit; st->i++)*/ + { + int tmp; +#define pmod(x,y) (tmp=((x) % (y)), (tmp >= 0 ? tmp : (tmp + (y)))) + + st->x1 = xmid + (((double) st->radius1) * st->sins [pmod ((st->angle * st->factor1), 360)]); + st->y1 = ymid + (((double) st->radius2) * st->coss [pmod ((st->angle * st->factor2), 360)]); + XDrawLine (dpy, window, st->draw_gc, st->x1, st->y1, st->x2, st->y2); + st->x2 = xmid + (((double) st->radius2) * st->sins [pmod ((st->angle * st->factor3), 360)]); + st->y2 = ymid + (((double) st->radius1) * st->coss [pmod ((st->angle * st->factor4), 360)]); + XDrawLine (dpy, window, st->draw_gc, st->x1, st->y1, st->x2, st->y2); + st->angle += st->d_angle; + } + st->i++; + + if (st->i >= limit) + st->dstate = LINGER; +} + +static void +trig (Display *dpy, Window window, struct state *st) +{ + int xmid = st->width / 2; + int ymid = st->height / 2; + +/* while (st->d_angle >= -360 && st->d_angle <= 360)*/ + { + int tmp; + int angle = st->d_angle + st->d_angle_offset; + st->x1 = (st->sins [pmod(angle * st->factor1, 360)] * xmid) + xmid; + st->y1 = (st->coss [pmod(angle * st->factor1, 360)] * ymid) + ymid; + st->x2 = (st->sins [pmod(angle * st->factor2 + st->offset, 360)] * xmid) + xmid; + st->y2 = (st->coss [pmod(angle * st->factor2 + st->offset, 360)] * ymid) + ymid; + XDrawLine(dpy, window, st->draw_gc, st->x1, st->y1, st->x2, st->y2); + tmp = (int) 360 / (2 * st->density * st->factor1 * st->factor2); + if (tmp == 0) /* Do not want it getting stuck... */ + tmp = 1; /* Would not need if floating point */ + st->d_angle += st->dir * tmp; + } + + if (st->d_angle < -360 || st->d_angle > 360) + st->dstate = LINGER; +} + + +#define min(a,b) ((a)<(b)?(a):(b)) + +static void +random_helix (Display *dpy, Window window, struct state *st, + XColor *color, Bool *got_color) +{ + int radius; + double divisor; + + radius = min (st->width, st->height) / 2; + + st->i = 0; + st->d_angle = 0; + st->factor1 = 2; + st->factor2 = 2; + st->factor3 = 2; + st->factor4 = 2; + + divisor = ((frand (3.0) + 1) * (((random() & 1) * 2) - 1)); + + if ((random () & 1) == 0) + { + st->radius1 = radius; + st->radius2 = radius / divisor; + } + else + { + st->radius2 = radius; + st->radius1 = radius / divisor; + } + + while (gcd (360, st->d_angle) >= 2) + st->d_angle = random () % 360; + +#define random_factor() \ + (((random() % 7) ? ((random() & 1) + 1) : 3) \ + * (((random() & 1) * 2) - 1)) + + while (gcd (gcd (gcd (st->factor1, st->factor2), st->factor3), st->factor4) != 1) + { + st->factor1 = random_factor (); + st->factor2 = random_factor (); + st->factor3 = random_factor (); + st->factor4 = random_factor (); + } + + if (mono_p) + XSetForeground (dpy, st->draw_gc, st->default_fg_pixel); + else + { + hsv_to_rgb (random () % 360, frand (1.0), frand (0.5) + 0.5, + &color->red, &color->green, &color->blue); + if ((*got_color = XAllocColor (dpy, st->cmap, color))) + XSetForeground (dpy, st->draw_gc, color->pixel); + else + XSetForeground (dpy, st->draw_gc, st->default_fg_pixel); + } + + XClearWindow (dpy, window); +} + +static void +random_trig (Display *dpy, Window window, struct state *st, + XColor *color, Bool *got_color) +{ + st->d_angle = 0; + st->factor1 = (random() % 8) + 1; + do { + st->factor2 = (random() % 8) + 1; + } while (st->factor1 == st->factor2); + + st->dir = (random() & 1) ? 1 : -1; + st->d_angle_offset = random() % 360; + st->offset = ((random() % ((360 / 4) - 1)) + 1) / 4; + st->density = 1 << ((random() % 4) + 4); /* Higher density, higher angles */ + + if (mono_p) + XSetForeground (dpy, st->draw_gc, st->default_fg_pixel); + else + { + hsv_to_rgb (random () % 360, frand (1.0), frand (0.5) + 0.5, + &color->red, &color->green, &color->blue); + if ((*got_color = XAllocColor (dpy, st->cmap, color))) + XSetForeground (dpy, st->draw_gc, color->pixel); + else + XSetForeground (dpy, st->draw_gc, st->default_fg_pixel); + } + + XClearWindow (dpy, window); +} + + +/* random_helix_or_trig */ +static unsigned long +helix_draw (Display *dpy, Window window, void *closure) +{ + struct state *st = (struct state *) closure; + Bool free_color = False; + XColor color; + int delay = st->subdelay; + int erase_delay = 10000; + int ii; + + if (st->eraser) { + st->eraser = erase_window (dpy, window, st->eraser); + if (st->eraser) + delay = erase_delay; + goto END; + } + + switch (st->dstate) + { + case LINGER: + delay = st->sleep_time * 1000000; + st->dstate = ERASE; + break; + + case ERASE: + st->eraser = erase_window (dpy, window, st->eraser); + delay = erase_delay; + if (free_color) XFreeColors (dpy, st->cmap, &color.pixel, 1, 0); + st->dstate = (random() & 1) ? HELIX : TRIG; + break; + + case DRAW_HELIX: + for (ii = 0; ii < 10; ii++) { + helix (dpy, window, st); + if (st->dstate != DRAW_HELIX) + break; + } + break; + + case DRAW_TRIG: + for (ii = 0; ii < 5; ii++) { + trig (dpy, window, st); + if (st->dstate != DRAW_TRIG) + break; + } + break; + + case HELIX: + random_helix (dpy, window, st, &color, &free_color); + st->dstate = DRAW_HELIX; + break; + + case TRIG: + random_trig(dpy, window, st, &color, &free_color); + st->dstate = DRAW_TRIG; + break; + + default: + abort(); + } + + END: + return delay; +} + +static void +helix_reshape (Display *dpy, Window window, void *closure, + unsigned int w, unsigned int h) +{ + struct state *st = (struct state *) closure; + st->width = w; + st->height = h; +} + +static Bool +helix_event (Display *dpy, Window window, void *closure, XEvent *event) +{ + return False; +} + +static void +helix_free (Display *dpy, Window window, void *closure) +{ + struct state *st = (struct state *) closure; + free (st); +} + + + +static const char *helix_defaults [] = { + ".background: black", + ".foreground: white", + "*fpsSolid: true", + "*delay: 5", + "*subdelay: 20000", + 0 +}; + +static XrmOptionDescRec helix_options [] = { + { "-delay", ".delay", XrmoptionSepArg, 0 }, + { "-subdelay", ".subdelay", XrmoptionSepArg, 0 }, + { 0, 0, 0, 0 }, +}; + +XSCREENSAVER_MODULE ("Helix", helix) diff --git a/hacks/helix.man b/hacks/helix.man new file mode 100644 index 00000000..e0222945 --- /dev/null +++ b/hacks/helix.man @@ -0,0 +1,62 @@ +.TH XScreenSaver 1 "18-sep-97" "X Version 11" +.SH NAME +helix - draw helical string-art patterns +.SH SYNOPSIS +.B helix +[\-display \fIhost:display.screen\fP] [\-foreground \fIcolor\fP] [\-background \fIcolor\fP] [\-window] [\-root] [\-mono] [\-erase\-speed \fIusecs\fP] [\-erase\-mode \fIinteger\fP] [\-delay \fIseconds\fP] [\-install] [\-visual \fIvisual\fP] +[\-fps] +.SH DESCRIPTION +The \fIhelix\fP program draws interesting patterns composed of line segments +in random colors. +.SH OPTIONS +.I helix +accepts the following options: +.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 \-mono +If on a color display, pretend we're on a monochrome display. +.TP 8 +.B \-delay \fIseconds\fP +This sets the number of seconds that the helix will be on the screen. +.TP 8 +.B \-subdelay \fImicroseconds\fP +This sets the amount of time to pause periodically while drawing. +.TP 8 +.B \-install +Install a private colormap for the window. +.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 \-fps +Display the current frame rate and CPU load. +.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 1992 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 , 13-aug-92. +Screen eraser improved by Johannes Keukelaar , + 18-sep-97. diff --git a/hacks/hopalong.c b/hacks/hopalong.c new file mode 100644 index 00000000..09614458 --- /dev/null +++ b/hacks/hopalong.c @@ -0,0 +1,579 @@ +/* -*- Mode: C; tab-width: 4 -*- */ +/* hop --- real plane fractals */ + +#if 0 +static const char sccsid[] = "@(#)hop.c 5.00 2000/11/01 xlockmore"; +#endif + +/*- + * Copyright (c) 1991 by Patrick J. Naughton. + * + * Permission to use, copy, modify, and distribute this software and its + * documentation for any purpose and without fee is hereby granted, + * provided that the above copyright notice appear in all copies and that + * both that copyright notice and this permission notice appear in + * supporting documentation. + * + * This file is provided AS IS with no warranties of any kind. The author + * shall have no liability with respect to the infringement of copyrights, + * trade secrets or any patents by this file or any part thereof. In no + * event will the author be liable for any lost revenue or profits or + * other special, indirect and consequential damages. + * + * Revision History: + * Changes in xlockmore distribution + * 01-Nov-2000: Allocation checks + * 24-Jun-1997: EJK and RR functions stolen from xmartin2.2 + * Ed Kubaitis ejk functions and xmartin + * Renaldo Recuerdo rr function, generalized exponent version + * of the Barry Martin's square root function + * 10-May-1997: Compatible with xscreensaver + * 27-Jul-1995: added Peter de Jong's hop from Scientific American + * July 87 p. 111. Sometimes they are amazing but there are a + * few duds (I did not see a pattern in the parameters). + * 29-Mar-1995: changed name from hopalong to hop + * 09-Dec-1994: added Barry Martin's sine hop + * Changes in original xlock + * 29-Oct-1990: fix bad (int) cast. + * 29-Jul-1990: support for multiple screens. + * 08-Jul-1990: new timing and colors and new algorithm for fractals. + * 15-Dec-1989: Fix for proper skipping of {White,Black}Pixel() in colors. + * 08-Oct-1989: Fixed long standing typo bug in RandomInitHop(); + * Fixed bug in memory allocation in init_hop(); + * Moved seconds() to an extern. + * Got rid of the % mod since .mod is slow on a sparc. + * 20-Sep-1989: Lint. + * 31-Aug-1988: Forked from xlock.c for modularity. + * 23-Mar-1988: Coded HOPALONG routines from Scientific American Sept. 86 p. 14. + * Hopalong was attributed to Barry Martin of Aston University + * (Birmingham, England) + */ + + +#ifdef STANDALONE +#define MODE_hop +#define DEFAULTS "*delay: 10000 \n" \ + "*count: 1000 \n" \ + "*cycles: 2500 \n" \ + "*ncolors: 200 \n" \ + "*fpsSolid: true \n" \ + +# define SMOOTH_COLORS +# define reshape_hop 0 +# define hop_handle_event 0 +# include "xlockmore.h" /* in xscreensaver distribution */ +# include "erase.h" +#else /* STANDALONE */ +# include "xlock.h" /* in xlockmore distribution */ +#endif /* STANDALONE */ + +#ifdef MODE_hop + +#define DEF_MARTIN "False" +#define DEF_POPCORN "False" +#define DEF_EJK1 "False" +#define DEF_EJK2 "False" +#define DEF_EJK3 "False" +#define DEF_EJK4 "False" +#define DEF_EJK5 "False" +#define DEF_EJK6 "False" +#define DEF_RR "False" +#define DEF_JONG "False" +#define DEF_SINE "False" + +static Bool martin; +static Bool popcorn; +static Bool ejk1; +static Bool ejk2; +static Bool ejk3; +static Bool ejk4; +static Bool ejk5; +static Bool ejk6; +static Bool rr; +static Bool jong; +static Bool sine; + +static XrmOptionDescRec opts[] = +{ + {"-martin", ".hop.martin", XrmoptionNoArg, "on"}, + {"+martin", ".hop.martin", XrmoptionNoArg, "off"}, + {"-popcorn", ".hop.popcorn", XrmoptionNoArg, "on"}, + {"+popcorn", ".hop.popcorn", XrmoptionNoArg, "off"}, + {"-ejk1", ".hop.ejk1", XrmoptionNoArg, "on"}, + {"+ejk1", ".hop.ejk1", XrmoptionNoArg, "off"}, + {"-ejk2", ".hop.ejk2", XrmoptionNoArg, "on"}, + {"+ejk2", ".hop.ejk2", XrmoptionNoArg, "off"}, + {"-ejk3", ".hop.ejk3", XrmoptionNoArg, "on"}, + {"+ejk3", ".hop.ejk3", XrmoptionNoArg, "off"}, + {"-ejk4", ".hop.ejk4", XrmoptionNoArg, "on"}, + {"+ejk4", ".hop.ejk4", XrmoptionNoArg, "off"}, + {"-ejk5", ".hop.ejk5", XrmoptionNoArg, "on"}, + {"+ejk5", ".hop.ejk5", XrmoptionNoArg, "off"}, + {"-ejk6", ".hop.ejk6", XrmoptionNoArg, "on"}, + {"+ejk6", ".hop.ejk6", XrmoptionNoArg, "off"}, + {"-rr", ".hop.rr", XrmoptionNoArg, "on"}, + {"+rr", ".hop.rr", XrmoptionNoArg, "off"}, + {"-jong", ".hop.jong", XrmoptionNoArg, "on"}, + {"+jong", ".hop.jong", XrmoptionNoArg, "off"}, + {"-sine", ".hop.sine", XrmoptionNoArg, "on"}, + {"+sine", ".hop.sine", XrmoptionNoArg, "off"} +}; +static argtype vars[] = +{ + {&martin, "martin", "Martin", DEF_MARTIN, t_Bool}, + {&popcorn, "popcorn", "Popcorn", DEF_POPCORN, t_Bool}, + {&ejk1, "ejk1", "EJK1", DEF_EJK1, t_Bool}, + {&ejk2, "ejk2", "EJK2", DEF_EJK2, t_Bool}, + {&ejk3, "ejk3", "EJK3", DEF_EJK3, t_Bool}, + {&ejk4, "ejk4", "EJK4", DEF_EJK4, t_Bool}, + {&ejk5, "ejk5", "EJK5", DEF_EJK5, t_Bool}, + {&ejk6, "ejk6", "EJK6", DEF_EJK6, t_Bool}, + {&rr, "rr", "RR", DEF_RR, t_Bool}, + {&jong, "jong", "Jong", DEF_JONG, t_Bool}, + {&sine, "sine", "Sine", DEF_SINE, t_Bool} +}; +static OptionStruct desc[] = +{ + {"-/+martin", "turn on/off sqrt format"}, + {"-/+popcorn", "turn on/off Clifford A. Pickover's popcorn format"}, + {"-/+ejk1", "turn on/off ejk1 format"}, + {"-/+ejk2", "turn on/off ejk2 format"}, + {"-/+ejk3", "turn on/off ejk3 format"}, + {"-/+ejk4", "turn on/off ejk4 format"}, + {"-/+ejk5", "turn on/off ejk5 format"}, + {"-/+ejk6", "turn on/off ejk6 format"}, + {"-/+rr", "turn on/off rr format"}, + {"-/+jong", "turn on/off jong format"}, + {"-/+sine", "turn on/off sine format"} +}; + +ENTRYPOINT ModeSpecOpt hop_opts = +{sizeof opts / sizeof opts[0], opts, sizeof vars / sizeof vars[0], vars, desc}; + +#ifdef USE_MODULES +ModStruct hop_description = +{"hop", "init_hop", "draw_hop", "release_hop", + "refresh_hop", "init_hop", (char *) NULL, &hop_opts, + 10000, 1000, 2500, 1, 64, 1.0, "", + "Shows real plane iterated fractals", 0, NULL}; + +#endif + +#define MARTIN 0 +#define POPCORN 7 +#define SINE 8 +#define EJK1 1 +#define EJK2 2 +#define EJK3 9 +#define EJK4 3 +#define EJK5 4 +#define EJK6 10 +#define RR 5 +#define JONG 6 +#ifdef OFFENDING +#define OPS 8 /* 8, 9, 10 might be too close to a swastika for some... */ +#else +#define OPS 11 +#endif + +typedef struct { + int centerx, centery; /* center of the screen */ + double a, b, c, d; + double i, j; /* hopalong parameters */ + int inc; + int pix; + int op; + int count; + int bufsize; + XPoint *pointBuffer; /* pointer for XDrawPoints */ +#ifdef STANDALONE + eraser_state *eraser; +#endif +} hopstruct; + +static hopstruct *hops = (hopstruct *) NULL; + +ENTRYPOINT void +init_hop(ModeInfo * mi) +{ + Display *display = MI_DISPLAY(mi); + GC gc = MI_GC(mi); + double range; + hopstruct *hp; + + if (hops == NULL) { + if ((hops = (hopstruct *) calloc(MI_NUM_SCREENS(mi), + sizeof (hopstruct))) == NULL) + return; + } + hp = &hops[MI_SCREEN(mi)]; + + hp->centerx = MI_WIDTH(mi) / 2; + hp->centery = MI_HEIGHT(mi) / 2; + /* Make the other operations less common since they are less interesting */ + if (MI_IS_FULLRANDOM(mi)) { + hp->op = NRAND(OPS); + } else { + if (martin) + hp->op = MARTIN; + else if (popcorn) + hp->op = POPCORN; + else if (ejk1) + hp->op = EJK1; + else if (ejk2) + hp->op = EJK2; + else if (ejk3) + hp->op = EJK3; + else if (ejk4) + hp->op = EJK4; + else if (ejk5) + hp->op = EJK5; + else if (ejk6) + hp->op = EJK6; + else if (rr) + hp->op = RR; + else if (jong) + hp->op = JONG; + else if (sine) + hp->op = SINE; + else + hp->op = NRAND(OPS); + } + + range = sqrt((double) hp->centerx * hp->centerx + + (double) hp->centery * hp->centery) / (1.0 + LRAND() / MAXRAND); + hp->i = hp->j = 0.0; + hp->inc = (int) ((LRAND() / MAXRAND) * 200) - 100; +#undef XMARTIN + switch (hp->op) { + case MARTIN: +#ifdef XMARTIN + hp->a = (LRAND() / MAXRAND) * 1500.0 + 40.0; + hp->b = (LRAND() / MAXRAND) * 17.0 + 3.0; + hp->c = (LRAND() / MAXRAND) * 3000.0 + 100.0; +#else + hp->a = ((LRAND() / MAXRAND) * 2.0 - 1.0) * range / 20.0; + hp->b = ((LRAND() / MAXRAND) * 2.0 - 1.0) * range / 20.0; + if (LRAND() & 1) + hp->c = ((LRAND() / MAXRAND) * 2.0 - 1.0) * range / 20.0; + else + hp->c = 0.0; +#endif + if (MI_IS_VERBOSE(mi)) + (void) fprintf(stdout, "sqrt a=%g, b=%g, c=%g\n", hp->a, hp->b, hp->c); + break; + case EJK1: +#ifdef XMARTIN + hp->a = (LRAND() / MAXRAND) * 500.0; + hp->c = (LRAND() / MAXRAND) * 100.0 + 10.0; +#else + hp->a = ((LRAND() / MAXRAND) * 2.0 - 1.0) * range / 30.0; + hp->c = ((LRAND() / MAXRAND) * 2.0 - 1.0) * range / 40.0; +#endif + hp->b = (LRAND() / MAXRAND) * 0.4; + if (MI_IS_VERBOSE(mi)) + (void) fprintf(stdout, "ejk1 a=%g, b=%g, c=%g\n", hp->a, hp->b, hp->c); + break; + case EJK2: +#ifdef XMARTIN + hp->a = (LRAND() / MAXRAND) * 500.0; +#else + hp->a = ((LRAND() / MAXRAND) * 2.0 - 1.0) * range / 30.0; +#endif + hp->b = pow(10.0, 6.0 + (LRAND() / MAXRAND) * 24.0); + if (LRAND() & 1) + hp->b = -hp->b; + hp->c = pow(10.0, (LRAND() / MAXRAND) * 9.0); + if (LRAND() & 1) + hp->c = -hp->c; + if (MI_IS_VERBOSE(mi)) + (void) fprintf(stdout, "ejk2 a=%g, b=%g, c=%g\n", hp->a, hp->b, hp->c); + break; + case EJK3: +#ifdef XMARTIN + hp->a = (LRAND() / MAXRAND) * 500.0; + hp->c = (LRAND() / MAXRAND) * 80.0 + 30.0; +#else + hp->a = ((LRAND() / MAXRAND) * 2.0 - 1.0) * range / 30.0; + hp->c = ((LRAND() / MAXRAND) * 2.0 - 1.0) * range / 70.0; +#endif + hp->b = (LRAND() / MAXRAND) * 0.35 + 0.5; + if (MI_IS_VERBOSE(mi)) + (void) fprintf(stdout, "ejk3 a=%g, b=%g, c=%g\n", hp->a, hp->b, hp->c); + break; + case EJK4: +#ifdef XMARTIN + hp->a = (LRAND() / MAXRAND) * 1000.0; + hp->c = (LRAND() / MAXRAND) * 40.0 + 30.0; +#else + hp->a = ((LRAND() / MAXRAND) * 2.0 - 1.0) * range / 2.0; + hp->c = ((LRAND() / MAXRAND) * 2.0 - 1.0) * range / 200.0; +#endif + hp->b = (LRAND() / MAXRAND) * 9.0 + 1.0; + if (MI_IS_VERBOSE(mi)) + (void) fprintf(stdout, "ejk4 a=%g, b=%g, c=%g\n", hp->a, hp->b, hp->c); + break; + case EJK5: +#ifdef XMARTIN + hp->a = (LRAND() / MAXRAND) * 600.0; + hp->c = (LRAND() / MAXRAND) * 90.0 + 20.0; +#else + hp->a = ((LRAND() / MAXRAND) * 2.0 - 1.0) * range / 2.0; + hp->c = ((LRAND() / MAXRAND) * 2.0 - 1.0) * range / 200.0; +#endif + hp->b = (LRAND() / MAXRAND) * 0.3 + 0.1; + if (MI_IS_VERBOSE(mi)) + (void) fprintf(stdout, "ejk5 a=%g, b=%g, c=%g\n", hp->a, hp->b, hp->c); + break; + case EJK6: +#ifdef XMARTIN + hp->a = (LRAND() / MAXRAND) * 100.0 + 550.0; +#else + hp->a = ((LRAND() / MAXRAND) * 2.0 - 1.0) * range / 30.0; +#endif + hp->b = (LRAND() / MAXRAND) + 0.5; + if (MI_IS_VERBOSE(mi)) + (void) fprintf(stdout, "ejk6 a=%g, b=%g\n", hp->a, hp->b); + break; + case RR: +#ifdef XMARTIN + hp->a = (LRAND() / MAXRAND) * 100.0; + hp->b = (LRAND() / MAXRAND) * 20.0; + hp->c = (LRAND() / MAXRAND) * 200.0; +#else + hp->a = ((LRAND() / MAXRAND) * 2.0 - 1.0) * range / 40.0; + hp->b = ((LRAND() / MAXRAND) * 2.0 - 1.0) * range / 200.0; + hp->c = ((LRAND() / MAXRAND) * 2.0 - 1.0) * range / 20.0; +#endif + hp->d = (LRAND() / MAXRAND) * 0.9; + if (MI_IS_VERBOSE(mi)) + (void) fprintf(stdout, "rr a=%g, b=%g, c=%g, d=%g\n", + hp->a, hp->b, hp->c, hp->d); + break; + case POPCORN: + hp->a = 0.0; + hp->b = 0.0; + hp->c = ((LRAND() / MAXRAND) * 2.0 - 1.0) * 0.24 + 0.25; + hp->inc = 100; + if (MI_IS_VERBOSE(mi)) + (void) fprintf(stdout, "popcorn a=%g, b=%g, c=%g, d=%g\n", + hp->a, hp->b, hp->c, hp->d); + break; + case JONG: + hp->a = ((LRAND() / MAXRAND) * 2.0 - 1.0) * M_PI; + hp->b = ((LRAND() / MAXRAND) * 2.0 - 1.0) * M_PI; + hp->c = ((LRAND() / MAXRAND) * 2.0 - 1.0) * M_PI; + hp->d = ((LRAND() / MAXRAND) * 2.0 - 1.0) * M_PI; + if (MI_IS_VERBOSE(mi)) + (void) fprintf(stdout, "jong a=%g, b=%g, c=%g, d=%g\n", + hp->a, hp->b, hp->c, hp->d); + break; + case SINE: /* MARTIN2 */ +#ifdef XMARTIN + hp->a = M_PI + ((LRAND() / MAXRAND) * 2.0 - 1.0) * 0.07; +#else + hp->a = M_PI + ((LRAND() / MAXRAND) * 2.0 - 1.0) * 0.7; +#endif + if (MI_IS_VERBOSE(mi)) + (void) fprintf(stdout, "sine a=%g\n", hp->a); + break; + } + if (MI_NPIXELS(mi) > 2) + hp->pix = NRAND(MI_NPIXELS(mi)); + hp->bufsize = MI_COUNT(mi); + + if (hp->pointBuffer == NULL) { + if ((hp->pointBuffer = (XPoint *) malloc(hp->bufsize * + sizeof (XPoint))) == NULL) + return; + } + +#ifndef STANDALONE + MI_CLEARWINDOW(mi); +#endif + + XSetForeground(display, gc, MI_WHITE_PIXEL(mi)); + hp->count = 0; +} + + +ENTRYPOINT void +draw_hop(ModeInfo * mi) +{ + double oldj, oldi; + XPoint *xp; + int k; + hopstruct *hp; + + if (hops == NULL) + return; + hp = &hops[MI_SCREEN(mi)]; + +#ifdef STANDALONE + if (hp->eraser) { + hp->eraser = erase_window (MI_DISPLAY(mi), MI_WINDOW(mi), hp->eraser); + return; + } +#endif + + + if (hp->pointBuffer == NULL) + return; + xp = hp->pointBuffer; + k = hp->bufsize; + + MI_IS_DRAWN(mi) = True; + hp->inc++; + if (MI_NPIXELS(mi) > 2) { + XSetForeground(MI_DISPLAY(mi), MI_GC(mi), MI_PIXEL(mi, hp->pix)); + if (++hp->pix >= MI_NPIXELS(mi)) + hp->pix = 0; + } + while (k--) { + oldj = hp->j; + switch (hp->op) { + case MARTIN: /* SQRT, MARTIN1 */ + oldi = hp->i + hp->inc; + hp->j = hp->a - hp->i; + hp->i = oldj + ((hp->i < 0) + ? sqrt(fabs(hp->b * oldi - hp->c)) + : -sqrt(fabs(hp->b * oldi - hp->c))); + xp->x = hp->centerx + (int) (hp->i + hp->j); + xp->y = hp->centery - (int) (hp->i - hp->j); + break; + case EJK1: + oldi = hp->i + hp->inc; + hp->j = hp->a - hp->i; + hp->i = oldj - ((hp->i > 0) ? (hp->b * oldi - hp->c) : + -(hp->b * oldi - hp->c)); + xp->x = hp->centerx + (int) (hp->i + hp->j); + xp->y = hp->centery - (int) (hp->i - hp->j); + break; + case EJK2: + oldi = hp->i + hp->inc; + hp->j = hp->a - hp->i; + hp->i = oldj - ((hp->i < 0) ? log(fabs(hp->b * oldi - hp->c)) : + -log(fabs(hp->b * oldi - hp->c))); + xp->x = hp->centerx + (int) (hp->i + hp->j); + xp->y = hp->centery - (int) (hp->i - hp->j); + break; + case EJK3: + oldi = hp->i + hp->inc; + hp->j = hp->a - hp->i; + hp->i = oldj - ((hp->i > 0) ? sin(hp->b * oldi) - hp->c : + -sin(hp->b * oldi) - hp->c); + xp->x = hp->centerx + (int) (hp->i + hp->j); + xp->y = hp->centery - (int) (hp->i - hp->j); + break; + case EJK4: + oldi = hp->i + hp->inc; + hp->j = hp->a - hp->i; + hp->i = oldj - ((hp->i > 0) ? sin(hp->b * oldi) - hp->c : + -sqrt(fabs(hp->b * oldi - hp->c))); + xp->x = hp->centerx + (int) (hp->i + hp->j); + xp->y = hp->centery - (int) (hp->i - hp->j); + break; + case EJK5: + oldi = hp->i + hp->inc; + hp->j = hp->a - hp->i; + hp->i = oldj - ((hp->i > 0) ? sin(hp->b * oldi) - hp->c : + -(hp->b * oldi - hp->c)); + xp->x = hp->centerx + (int) (hp->i + hp->j); + xp->y = hp->centery - (int) (hp->i - hp->j); + break; + case EJK6: + oldi = hp->i + hp->inc; + hp->j = hp->a - hp->i; + hp->i = oldj - asin((hp->b * oldi) - (long) (hp->b * oldi)); + xp->x = hp->centerx + (int) (hp->i + hp->j); + xp->y = hp->centery - (int) (hp->i - hp->j); + break; + case RR: /* RR1 */ + oldi = hp->i + hp->inc; + hp->j = hp->a - hp->i; + hp->i = oldj - ((hp->i < 0) ? -pow(fabs(hp->b * oldi - hp->c), hp->d) : + pow(fabs(hp->b * oldi - hp->c), hp->d)); + xp->x = hp->centerx + (int) (hp->i + hp->j); + xp->y = hp->centery - (int) (hp->i - hp->j); + break; + case POPCORN: +#define HVAL 0.05 +#define INCVAL 50 + { + double tempi, tempj; + + if (hp->inc >= 100) + hp->inc = 0; + if (hp->inc == 0) { + if (hp->a++ >= INCVAL) { + hp->a = 0; + if (hp->b++ >= INCVAL) + hp->b = 0; + } + hp->i = (-hp->c * INCVAL / 2 + hp->c * hp->a) * M_PI / 180.0; + hp->j = (-hp->c * INCVAL / 2 + hp->c * hp->b) * M_PI / 180.0; + } + tempi = hp->i - HVAL * sin(hp->j + tan(3.0 * hp->j)); + tempj = hp->j - HVAL * sin(hp->i + tan(3.0 * hp->i)); + xp->x = hp->centerx + (int) (MI_WIDTH(mi) / 40 * tempi); + xp->y = hp->centery + (int) (MI_HEIGHT(mi) / 40 * tempj); + hp->i = tempi; + hp->j = tempj; + } + break; + case JONG: + if (hp->centerx > 0) + oldi = hp->i + 4 * hp->inc / hp->centerx; + else + oldi = hp->i; + hp->j = sin(hp->c * hp->i) - cos(hp->d * hp->j); + hp->i = sin(hp->a * oldj) - cos(hp->b * oldi); + xp->x = hp->centerx + (int) (hp->centerx * (hp->i + hp->j) / 4.0); + xp->y = hp->centery - (int) (hp->centery * (hp->i - hp->j) / 4.0); + break; + case SINE: /* MARTIN2 */ + oldi = hp->i + hp->inc; + hp->j = hp->a - hp->i; + hp->i = oldj - sin(oldi); + xp->x = hp->centerx + (int) (hp->i + hp->j); + xp->y = hp->centery - (int) (hp->i - hp->j); + break; + } + xp++; + } + XDrawPoints(MI_DISPLAY(mi), MI_WINDOW(mi), MI_GC(mi), + hp->pointBuffer, hp->bufsize, CoordModeOrigin); + if (++hp->count > MI_CYCLES(mi)) { +#ifdef STANDALONE + hp->eraser = erase_window (MI_DISPLAY(mi), MI_WINDOW(mi), hp->eraser); +#endif /* STANDALONE */ + init_hop(mi); + } +} + +ENTRYPOINT void +release_hop(ModeInfo * mi) +{ + if (hops != NULL) { + int screen; + + for (screen = 0; screen < MI_NUM_SCREENS(mi); screen++) { + hopstruct *hp = &hops[screen]; + + if (hp->pointBuffer != NULL) + (void) free((void *) hp->pointBuffer); + } + (void) free((void *) hops); + hops = (hopstruct *) NULL; + } +} + +ENTRYPOINT void +refresh_hop(ModeInfo * mi) +{ + MI_CLEARWINDOW(mi); +} + +XSCREENSAVER_MODULE_2 ("Hopalong", hopalong, hop) + +#endif /* MODE_hop */ diff --git a/hacks/hopalong.man b/hacks/hopalong.man new file mode 100644 index 00000000..f38b4812 --- /dev/null +++ b/hacks/hopalong.man @@ -0,0 +1,82 @@ +.TH XScreenSaver 1 "10-May-97" "X Version 11" +.SH NAME +hopalong - draw real plane fractals +.SH SYNOPSIS +.B hopalong +[\-display \fIhost:display.screen\fP] [\-foreground \fIcolor\fP] [\-background \fIcolor\fP] [\-window] [\-root] [\-mono] [\-install] [\-visual \fIvisual\fP] [\-ncolors \fIinteger\fP] [\-delay \fImicroseconds\fP] [\-cycles \fIinteger\fP] [\-count \fIinteger\fP] [\-jong] [\-no\-jong] [\-jong] [\-no\-sine] + +[\-fps] +.SH DESCRIPTION +The \fIhop\fP program generates real plane fractals as described in +the September 1986 issue of Scientific American. +.SH OPTIONS +.I hopalong +accepts the following options: +.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 \-mono +If on a color display, pretend we're on a monochrome display. +.TP 8 +.B \-install +Install a private colormap for the window. +.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 \-ncolors \fIinteger\fP +How many colors should be used (if possible). Default 200. +The colors used cycle through the hue, making N stops around +the color wheel. +.TP 8 +.B \-cycles \fIinteger\fP +How long to run each batch. Default 2500 pixels. +.TP 8 +.B \-count \fIinteger\fP +How many pixels should be drawn before a color change. Default 1000. +.TP 8 +.B \-jong \fIinteger\fP +.TP 8 +.B \-no\-jong \fIinteger\fP +Whether to use the Jong format (default is to choose randomly.) + +.TP 8 +.B \-sine \fIinteger\fP +.TP 8 +.B \-no\-sine \fIinteger\fP +Whether to use the Sine format (default is to choose randomly.) + +.TP 8 +.B \-fps +Display the current frame rate and CPU load. +.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), +.BR xlock (1) +.SH COPYRIGHT +Copyright \(co 1988-91 by Patrick J. Naughton. + +Permission to use, copy, modify, and distribute this software and its +documentation for any purpose and without fee is hereby granted, +provided that the above copyright notice appear in all copies and that +both that copyright notice and this permission notice appear in +supporting documentation. +.SH AUTHOR +Patrick J. Naughton , 23-mar-88. + +Ability to run standalone or with \fIxscreensaver\fP added by +Jamie Zawinski , 13-aug-92, and again on 10-May-97. diff --git a/hacks/hyperball.c b/hacks/hyperball.c new file mode 100644 index 00000000..8a26cef7 --- /dev/null +++ b/hacks/hyperball.c @@ -0,0 +1,2463 @@ +/* xscreensaver, Copyright (c) 1992, 1995, 1996, 1998, 2000 + * 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. + * + * This code derived from TI Explorer Lisp code by Joe Keane, Fritz Mueller, + * and Jamie Zawinski. + */ + +#include +#include "screenhack.h" + +#define POINT_COUNT 600 +#define LINE_COUNT 1200 + +#define ANGLE_SCALE 0.001 + +struct point_info +{ + float pg_a; + float pg_b; + float pg_c; + float pg_d; +}; + +struct line_info +{ + short li_ip; + short li_iq; + char li_color; + char li_pad[3]; +}; + +struct point_state +{ + short old_x, old_y; + short new_x, new_y; + unsigned char old_dep, new_dep; +}; + +struct hyper_state +{ + char hs_stop; + char hs_resize; + char hs_redraw; + char hs_icon; + Display *hs_display; + Window hs_window; + float hs_observer_z; + float hs_unit_scale; + float hs_offset_x; + float hs_offset_y; + int hs_delay; + double hs_angle_xy; + double hs_angle_xz; + double hs_angle_yz; + double hs_angle_xw; + double hs_angle_yw; + double hs_angle_zw; + double hs_cos_xy, hs_sin_xy; + double hs_cos_xz, hs_sin_xz; + double hs_cos_yz, hs_sin_yz; + double hs_cos_xw, hs_sin_xw; + double hs_cos_yw, hs_sin_yw; + double hs_cos_zw, hs_sin_zw; + double hs_ref_ax, hs_ref_ay, hs_ref_az, hs_ref_aw; + double hs_ref_bx, hs_ref_by, hs_ref_bz, hs_ref_bw; + double hs_ref_cx, hs_ref_cy, hs_ref_cz, hs_ref_cw; + double hs_ref_dx, hs_ref_dy, hs_ref_dz, hs_ref_dw; + GC hs_color_gcs[8][8]; + GC black_gc; + char hs_moved[POINT_COUNT]; + struct point_state hs_points[POINT_COUNT]; + int roted; +}; + +static const struct point_info point_table[POINT_COUNT]; +static const struct line_info line_table[LINE_COUNT]; + +static void set_sizes (struct hyper_state *hs, int width, int height); + +static void * +hyperball_init (Display *dpy, Window win) +{ + struct hyper_state *hs = (struct hyper_state *) calloc (1, sizeof(*hs)); + + XGCValues gcv; + Colormap cmap; + /* double xy, xz, yz, xw, yw, zw; */ + unsigned long bg_pixel; + float observer_z; + int delay; + + hs->hs_display = dpy; + hs->hs_window = win; + + observer_z = get_float_resource (dpy, "observer-z", "Float"); + if (observer_z < 1.125) + observer_z = 1.125; + hs->hs_observer_z = observer_z; + + { + XWindowAttributes wa; + XGetWindowAttributes (dpy, win, &wa); + cmap = wa.colormap; + set_sizes (hs, wa.width, wa.height); + } + + hs->hs_angle_xy = get_float_resource (dpy, "xy", "Float") * ANGLE_SCALE; + hs->hs_angle_xz = get_float_resource (dpy, "xz", "Float") * ANGLE_SCALE; + hs->hs_angle_yz = get_float_resource (dpy, "yz", "Float") * ANGLE_SCALE; + hs->hs_angle_xw = get_float_resource (dpy, "xw", "Float") * ANGLE_SCALE; + hs->hs_angle_yw = get_float_resource (dpy, "yw", "Float") * ANGLE_SCALE; + hs->hs_angle_zw = get_float_resource (dpy, "zw", "Float") * ANGLE_SCALE; + + delay = get_integer_resource (dpy, "delay", "Integer"); + hs->hs_delay = delay; + + bg_pixel = get_pixel_resource (dpy, cmap, "background", "Background"); + + if (mono_p) + { + GC black_gc; + unsigned long fg_pixel; + GC white_gc; + + gcv.function = GXcopy; + gcv.foreground = bg_pixel; + black_gc = XCreateGC (dpy, win, GCForeground|GCFunction, &gcv); + fg_pixel = get_pixel_resource (dpy, cmap, "foreground", "Foreground"); + gcv.foreground = fg_pixel; + white_gc = XCreateGC (dpy, win, GCForeground|GCFunction, &gcv); + hs->hs_color_gcs[0][0] = black_gc; + hs->hs_color_gcs[0][1] = white_gc; + } + else + { + int col; + int dep; + + gcv.function = GXcopy; + + gcv.foreground = get_pixel_resource (dpy, cmap, + "background", "Background"); + hs->black_gc = XCreateGC (dpy, win, GCForeground|GCFunction, &gcv); + + for (col = 0; col < 8; col++) + for (dep = 0; dep < 8; dep++) + { + char buffer[16]; + unsigned long fg_pixel; + GC color_gc; + + sprintf (buffer, "color%d%d", col, dep); + fg_pixel = get_pixel_resource (dpy, cmap, buffer, "Foreground"); + gcv.foreground = fg_pixel /*^ bg_pixel*/; + color_gc = XCreateGC (dpy, win, GCForeground|GCFunction, &gcv); + hs->hs_color_gcs[col][dep] = color_gc; + } + } + + { + double xy; + double xz; + double yz; + double xw; + double yw; + double zw; +#if 1 + double cos_xy, sin_xy; + double cos_xz, sin_xz; + double cos_yz, sin_yz; + double cos_xw, sin_xw; + double cos_yw, sin_yw; + double cos_zw, sin_zw; +#endif + + hs->hs_ref_ax = 1.0, hs->hs_ref_ay = 0.0, hs->hs_ref_az = 0.0, hs->hs_ref_aw = 0.0; + hs->hs_ref_bx = 0.0, hs->hs_ref_by = 1.0, hs->hs_ref_bz = 0.0, hs->hs_ref_bw = 0.0; + hs->hs_ref_cx = 0.0, hs->hs_ref_cy = 0.0, hs->hs_ref_cz = 1.0, hs->hs_ref_cw = 0.0; + hs->hs_ref_dx = 0.0, hs->hs_ref_dy = 0.0, hs->hs_ref_dz = 0.0, hs->hs_ref_dw = 1.0; + + xy = hs->hs_angle_xy; + xz = hs->hs_angle_xz; + yz = hs->hs_angle_yz; + xw = hs->hs_angle_xw; + yw = hs->hs_angle_yw; + zw = hs->hs_angle_zw; + + cos_xy = cos (xy), sin_xy = sin (xy); + hs->hs_cos_xy = cos_xy, hs->hs_sin_xy = sin_xy; + cos_xz = cos (xz), sin_xz = sin (xz); + hs->hs_cos_xz = cos_xz, hs->hs_sin_xz = sin_xz; + cos_yz = cos (yz), sin_yz = sin (yz); + hs->hs_cos_yz = cos_yz, hs->hs_sin_yz = sin_yz; + cos_xw = cos (xw), sin_xw = sin (xw); + hs->hs_cos_xw = cos_xw, hs->hs_sin_xw = sin_xw; + cos_yw = cos (yw), sin_yw = sin (yw); + hs->hs_cos_yw = cos_yw, hs->hs_sin_yw = sin_yw; + cos_zw = cos (zw), sin_zw = sin (zw); + hs->hs_cos_zw = cos_zw, hs->hs_sin_zw = sin_zw; + } + + return hs; +} + + +static unsigned long +hyperball_draw (Display *dpy, Window window, void *closure) +{ + struct hyper_state *hs = (struct hyper_state *) closure; + + int icon; + int resize; + int redraw; + int stop; + int delay; + + icon = hs->hs_icon; + resize = hs->hs_resize; + if (icon || !(hs->roted | resize)) + goto skip1; + +#ifdef HAVE_COCOA /* Don't second-guess Quartz's double-buffering */ + XClearWindow (dpy, window); +#endif + + { + int pc; + const struct point_info *point_ptr; + struct point_state *point_state; + float observer_z; + float unit_scale; + float offset_x; + float offset_y; + char *mark_ptr; + + pc = POINT_COUNT; + point_ptr = &point_table[0]; + point_state = &hs->hs_points[0]; + mark_ptr = &hs->hs_moved[0]; + + while (--pc >= 0) + { + double pos_a; + double pos_b; + double pos_c; + double pos_d; + double az, bz, cz, dz; + double sum_z; + double ax, bx, cx, dx; + double sum_x; + double ay, by, cy, dy; + double sum_y; + double mul; + int old_x; + int old_y; + int old_dep; + double xf; + double yf; + int new_x; + int new_y; + int new_dep; + int mov; + + pos_a = point_ptr->pg_a; + pos_b = point_ptr->pg_b; + pos_c = point_ptr->pg_c; + pos_d = point_ptr->pg_d; + point_ptr++; + az = hs->hs_ref_az; bz = hs->hs_ref_bz; cz = hs->hs_ref_cz; dz = hs->hs_ref_dz; + ax = hs->hs_ref_ax; bx = hs->hs_ref_bx; cx = hs->hs_ref_cx; dx = hs->hs_ref_dx; + ay = hs->hs_ref_ay; by = hs->hs_ref_by; cy = hs->hs_ref_cy; dy = hs->hs_ref_dy; + sum_z = pos_a * az + pos_b * bz + pos_c * cz + pos_d * dz; + observer_z = hs->hs_observer_z; + unit_scale = hs->hs_unit_scale; + sum_x = pos_a * ax + pos_b * bx + pos_c * cx + pos_d * dx; + sum_y = pos_a * ay + pos_b * by + pos_c * cy + pos_d * dy; + mul = unit_scale / (observer_z - sum_z); + offset_x = hs->hs_offset_x; + offset_y = hs->hs_offset_y; + old_x = point_state->new_x; + old_y = point_state->new_y; + old_dep = point_state->new_dep; + xf = sum_x * mul + offset_x; + yf = sum_y * mul + offset_y; + new_x = (int)rint(xf); + new_y = (int)rint(yf); + new_dep = (int)floor(sum_z * -128.0) + 128; + point_state->old_x = old_x; + point_state->old_y = old_y; + point_state->old_dep = old_dep; + point_state->new_x = new_x; + point_state->new_y = new_y; + point_state->new_dep = new_dep; + point_state++; + mov = new_x != old_x || new_y != old_y || new_dep != old_dep; + *mark_ptr = mov; + mark_ptr++; + } + } + + skip1: + icon = hs->hs_icon; + redraw = hs->hs_redraw; + if (icon || !(hs->roted | redraw)) + goto skip2; + + { + int lc; + const struct line_info *li_ptr; + int mono; + Window win = hs->hs_window; + + lc = LINE_COUNT; + li_ptr = &line_table[0]; + mono = mono_p; + + while (--lc >= 0) + { + int ip; + int iq; + int col; + int mov_p; + int mov_q; + struct point_state *sp; + struct point_state *sq; + int p_x; + int p_y; + int q_x; + int q_y; + GC erase_gc; + GC draw_gc; + int old_sum; + int new_sum; + int old_dep; + int new_dep; + + ip = li_ptr->li_ip; + iq = li_ptr->li_iq; + col = li_ptr->li_color; + li_ptr++; + mov_p = hs->hs_moved[ip]; + mov_q = hs->hs_moved[iq]; + if (!(redraw | mov_p | mov_q)) + continue; + + sp = &hs->hs_points[ip]; + sq = &hs->hs_points[iq]; + + if (mono) + { + erase_gc = hs->hs_color_gcs[0][0]; + draw_gc = hs->hs_color_gcs[0][1]; + } + else + { + GC *row; + + old_sum = sp->old_dep + sq->old_dep; + new_sum = sp->new_dep + sq->new_dep; + row = &hs->hs_color_gcs[col][0]; + old_dep = old_sum >> 6; + new_dep = new_sum >> 6; + erase_gc = hs->black_gc; + draw_gc = row[new_dep]; + } + + if (!redraw && erase_gc) + { + p_x = sp->old_x; + p_y = sp->old_y; + q_x = sq->old_x; + q_y = sq->old_y; + XDrawLine (dpy, win, erase_gc, p_x, p_y, q_x, q_y); + } + + p_x = sp->new_x; + p_y = sp->new_y; + q_x = sq->new_x; + q_y = sq->new_y; + XDrawLine (dpy, win, draw_gc, p_x, p_y, q_x, q_y); + } + } + + skip2: + stop = hs->hs_stop; + hs->roted = 0; + if (stop) + goto skip3; + + hs->roted = 1; + + { + double cos_a; + double sin_a; + double old_u; + double old_v; + double new_u; + double new_v; + + /* If you get error messages about the following forms, and you think you're + using an ANSI C conforming compiler, then you're mistaken. Possibly you're + mixing an ANSI compiler with a non-ANSI preprocessor, or vice versa. + Regardless, your system is broken; it's not a bug in this program. + */ +#if defined(__STDC__) || defined(__ANSI_CPP__) + +#define rotate(name,dim0,dim1) \ + old_u = hs->hs_ref_##name##dim0; \ + old_v = hs->hs_ref_##name##dim1; \ + new_u = old_u * cos_a + old_v * sin_a; \ + new_v = old_v * cos_a - old_u * sin_a; \ + hs->hs_ref_##name##dim0 = new_u; \ + hs->hs_ref_##name##dim1 = new_v; + +#define rotates(dim0,dim1) \ + if (hs->hs_sin_##dim0##dim1 != 0) { \ + cos_a = hs->hs_cos_##dim0##dim1; \ + sin_a = hs->hs_sin_##dim0##dim1; \ + rotate(a, dim0, dim1); \ + rotate(b, dim0, dim1); \ + rotate(c, dim0, dim1); \ + rotate(d, dim0, dim1); \ + } + +#else /* !__STDC__, courtesy of Andreas Luik */ + +#define rotate(name,dim0,dim1,cos,sin) \ + old_u = hs->hs_ref_/**/name/**/dim0; \ + old_v = hs->hs_ref_/**/name/**/dim1; \ + new_u = old_u * cos_a + old_v * sin_a; \ + new_v = old_v * cos_a - old_u * sin_a; \ + hs->hs_ref_/**/name/**/dim0 = new_u; \ + hs->hs_ref_/**/name/**/dim1 = new_v; + +#define rotates(dim0,dim1) \ + if (hs->hs_sin_/**/dim0/**/dim1 != 0) { \ + cos_a = hs->hs_cos_/**/dim0/**/dim1; \ + sin_a = hs->hs_sin_/**/dim0/**/dim1; \ + rotate(a, dim0, dim1); \ + rotate(b, dim0, dim1); \ + rotate(c, dim0, dim1); \ + rotate(d, dim0, dim1); \ + } + +#endif + + rotates (x, y); + rotates (x, z); + rotates (y, z); + rotates (x, w); + rotates (y, w); + rotates (z, w); + } + + skip3: + /* stop = hs->hs_stop; */ + delay = hs->hs_delay; + if (stop && delay < 10000) + delay = 10000; + + hs->hs_redraw = 0; + hs->hs_resize = 0; + + return delay; +} + + +static Bool +hyperball_event (Display *dpy, Window win, void *closure, XEvent *event) +{ + struct hyper_state *hs = (struct hyper_state *) closure; + + hs->hs_redraw = 0; + + switch (event->type) + { + case Expose: + hs->hs_icon = 0; + hs->hs_redraw = 1; + break; + + case ButtonPress: + switch (event->xbutton.button) + { + case 2: + hs->hs_stop = !hs->hs_stop; + break; + default: + break; + } + break; + +#ifndef HAVE_COCOA + case UnmapNotify: + hs->hs_icon = 1; + hs->hs_redraw = 0; + break; +#endif + + default: + break; + } + + if (hs->hs_redraw) + XClearWindow (dpy, win); + + return False; +} + +static void +hyperball_reshape (Display *dpy, Window window, void *closure, + unsigned int w, unsigned int h) +{ + struct hyper_state *hs = (struct hyper_state *) closure; + hs->hs_icon = 0; + hs->hs_resize = 1; + hs->hs_redraw = 1; + set_sizes (hs, w, h); + XClearWindow (dpy, window); +} + + +static void +set_sizes (struct hyper_state *hs, int width, int height) +{ + double observer_z; + int min_dim; + double var; + double offset_x; + double offset_y; + double unit_scale; + + observer_z = hs->hs_observer_z; + min_dim = width < height ? width : height; + var = sqrt(observer_z * observer_z - 1.0); + offset_x = 0.5 * (width - 1); + offset_y = 0.5 * (height - 1); + unit_scale = 0.4 * min_dim * var; + hs->hs_offset_x = (float)offset_x; + hs->hs_offset_y = (float)offset_y; + hs->hs_unit_scale = (float)unit_scale; +} + +static void +hyperball_free (Display *dpy, Window window, void *closure) +{ + struct hyper_state *hs = (struct hyper_state *) closure; + free (hs); +} + +/* data */ + +static const struct point_info point_table[POINT_COUNT] = +{ + { 0.93, 0.30, 0.09, 0.03, }, + { 0.84, 0.49, -0.08, 0.05, }, + { 0.72, 0.65, 0.02, -0.09, }, + { 0.57, 0.79, 0.05, 0.07, }, + { 0.40, 0.89, -0.09, -0.01, }, + { 0.20, 0.95, 0.07, -0.06, }, + { 0.00, 0.97, 0.00, 0.09, }, + { -0.20, 0.95, -0.07, -0.06, }, + { -0.40, 0.89, 0.09, -0.01, }, + { -0.57, 0.79, -0.05, 0.07, }, + { -0.72, 0.65, -0.02, -0.09, }, + { -0.84, 0.49, 0.08, 0.05, }, + { -0.93, 0.30, -0.09, 0.03, }, + { -0.97, 0.10, 0.04, -0.08, }, + { -0.97, -0.10, 0.04, 0.08, }, + { -0.93, -0.30, -0.09, -0.03, }, + { -0.84, -0.49, 0.08, -0.05, }, + { -0.72, -0.65, -0.02, 0.09, }, + { -0.57, -0.79, -0.05, -0.07, }, + { -0.40, -0.89, 0.09, 0.01, }, + { -0.20, -0.95, -0.07, 0.06, }, + { 0.00, -0.97, 0.00, -0.09, }, + { 0.20, -0.95, 0.07, 0.06, }, + { 0.40, -0.89, -0.09, 0.01, }, + { 0.57, -0.79, 0.05, -0.07, }, + { 0.72, -0.65, 0.02, 0.09, }, + { 0.84, -0.49, -0.08, -0.05, }, + { 0.93, -0.30, 0.09, -0.03, }, + { 0.97, -0.10, -0.04, 0.08, }, + { 0.97, 0.10, -0.04, -0.08, }, + { 0.27, 0.83, -0.13, -0.41, }, + { 0.09, 0.87, 0.40, 0.18, }, + { -0.09, 0.87, -0.40, 0.18, }, + { -0.27, 0.83, 0.13, -0.41, }, + { -0.44, 0.76, 0.22, 0.38, }, + { -0.59, 0.65, -0.42, -0.09, }, + { -0.71, 0.51, 0.35, -0.25, }, + { -0.80, 0.36, -0.05, 0.43, }, + { -0.86, 0.18, -0.29, -0.32, }, + { -0.88, 0.00, 0.43, 0.00, }, + { -0.86, -0.18, -0.29, 0.32, }, + { -0.80, -0.36, -0.05, -0.43, }, + { -0.71, -0.51, 0.35, 0.25, }, + { -0.59, -0.65, -0.42, 0.09, }, + { -0.44, -0.76, 0.22, -0.38, }, + { -0.27, -0.83, 0.13, 0.41, }, + { -0.09, -0.87, -0.40, -0.18, }, + { 0.09, -0.87, 0.40, -0.18, }, + { 0.27, -0.83, -0.13, 0.41, }, + { 0.44, -0.76, -0.22, -0.38, }, + { 0.59, -0.65, 0.42, 0.09, }, + { 0.71, -0.51, -0.35, 0.25, }, + { 0.80, -0.36, 0.05, -0.43, }, + { 0.86, -0.18, 0.29, 0.32, }, + { 0.88, 0.00, -0.43, 0.00, }, + { 0.86, 0.18, 0.29, -0.32, }, + { 0.80, 0.36, 0.05, 0.43, }, + { 0.71, 0.51, -0.35, -0.25, }, + { 0.59, 0.65, 0.42, -0.09, }, + { 0.44, 0.76, -0.22, 0.38, }, + { -0.13, 0.41, -0.27, 0.83, }, + { -0.22, 0.38, -0.44, -0.76, }, + { -0.29, 0.32, 0.86, 0.18, }, + { -0.35, 0.25, -0.71, 0.51, }, + { -0.40, 0.18, 0.09, -0.87, }, + { -0.42, 0.09, 0.59, 0.65, }, + { -0.43, 0.00, -0.88, 0.00, }, + { -0.42, -0.09, 0.59, -0.65, }, + { -0.40, -0.18, 0.09, 0.87, }, + { -0.35, -0.25, -0.71, -0.51, }, + { -0.29, -0.32, 0.86, -0.18, }, + { -0.22, -0.38, -0.44, 0.76, }, + { -0.13, -0.41, -0.27, -0.83, }, + { -0.05, -0.43, 0.80, 0.36, }, + { 0.05, -0.43, -0.80, 0.36, }, + { 0.13, -0.41, 0.27, -0.83, }, + { 0.22, -0.38, 0.44, 0.76, }, + { 0.29, -0.32, -0.86, -0.18, }, + { 0.35, -0.25, 0.71, -0.51, }, + { 0.40, -0.18, -0.09, 0.87, }, + { 0.42, -0.09, -0.59, -0.65, }, + { 0.43, 0.00, 0.88, 0.00, }, + { 0.42, 0.09, -0.59, 0.65, }, + { 0.40, 0.18, -0.09, -0.87, }, + { 0.35, 0.25, 0.71, 0.51, }, + { 0.29, 0.32, -0.86, 0.18, }, + { 0.22, 0.38, 0.44, -0.76, }, + { 0.13, 0.41, 0.27, 0.83, }, + { 0.05, 0.43, -0.80, -0.36, }, + { -0.05, 0.43, 0.80, -0.36, }, + { 0.09, -0.03, -0.93, 0.30, }, + { 0.09, -0.01, 0.40, -0.89, }, + { 0.09, 0.01, 0.40, 0.89, }, + { 0.09, 0.03, -0.93, -0.30, }, + { 0.08, 0.05, 0.84, -0.49, }, + { 0.07, 0.06, -0.20, 0.95, }, + { 0.05, 0.07, -0.57, -0.79, }, + { 0.04, 0.08, 0.97, 0.10, }, + { 0.02, 0.09, -0.72, 0.65, }, + { 0.00, 0.09, 0.00, -0.97, }, + { -0.02, 0.09, 0.72, 0.65, }, + { -0.04, 0.08, -0.97, 0.10, }, + { -0.05, 0.07, 0.57, -0.79, }, + { -0.07, 0.06, 0.20, 0.95, }, + { -0.08, 0.05, -0.84, -0.49, }, + { -0.09, 0.03, 0.93, -0.30, }, + { -0.09, 0.01, -0.40, 0.89, }, + { -0.09, -0.01, -0.40, -0.89, }, + { -0.09, -0.03, 0.93, 0.30, }, + { -0.08, -0.05, -0.84, 0.49, }, + { -0.07, -0.06, 0.20, -0.95, }, + { -0.05, -0.07, 0.57, 0.79, }, + { -0.04, -0.08, -0.97, -0.10, }, + { -0.02, -0.09, 0.72, -0.65, }, + { 0.00, -0.09, 0.00, 0.97, }, + { 0.02, -0.09, -0.72, -0.65, }, + { 0.04, -0.08, 0.97, -0.10, }, + { 0.05, -0.07, -0.57, 0.79, }, + { 0.07, -0.06, -0.20, -0.95, }, + { 0.08, -0.05, 0.84, 0.49, }, + { 0.64, 0.67, -0.15, -0.28, }, + { 0.49, 0.79, 0.30, 0.07, }, + { 0.31, 0.87, -0.26, 0.18, }, + { 0.13, 0.92, 0.04, -0.31, }, + { -0.07, 0.92, 0.20, 0.24, }, + { -0.26, 0.89, -0.31, -0.01, }, + { -0.44, 0.82, 0.22, -0.23, }, + { -0.60, 0.71, 0.02, 0.31, }, + { -0.73, 0.57, -0.25, -0.19, }, + { -0.83, 0.40, 0.31, -0.06, }, + { -0.90, 0.22, -0.16, 0.27, }, + { -0.93, 0.03, -0.09, -0.30, }, + { -0.91, -0.16, 0.28, 0.14, }, + { -0.86, -0.35, -0.29, 0.12, }, + { -0.77, -0.52, 0.11, -0.29, }, + { -0.64, -0.67, 0.15, 0.28, }, + { -0.49, -0.79, -0.30, -0.07, }, + { -0.31, -0.87, 0.26, -0.18, }, + { -0.13, -0.92, -0.04, 0.31, }, + { 0.07, -0.92, -0.20, -0.24, }, + { 0.26, -0.89, 0.31, 0.01, }, + { 0.44, -0.82, -0.22, 0.23, }, + { 0.60, -0.71, -0.02, -0.31, }, + { 0.73, -0.57, 0.25, 0.19, }, + { 0.83, -0.40, -0.31, 0.06, }, + { 0.90, -0.22, 0.16, -0.27, }, + { 0.93, -0.03, 0.09, 0.30, }, + { 0.91, 0.16, -0.28, -0.14, }, + { 0.86, 0.35, 0.29, -0.12, }, + { 0.77, 0.52, -0.11, 0.29, }, + { 0.44, 0.82, -0.22, -0.23, }, + { 0.26, 0.89, 0.31, -0.01, }, + { 0.07, 0.92, -0.20, 0.24, }, + { -0.12, 0.92, -0.04, -0.31, }, + { -0.31, 0.87, 0.26, 0.18, }, + { -0.49, 0.79, -0.30, 0.07, }, + { -0.64, 0.67, 0.15, -0.28, }, + { -0.77, 0.52, 0.11, 0.29, }, + { -0.86, 0.35, -0.29, -0.12, }, + { -0.91, 0.16, 0.28, -0.14, }, + { -0.93, -0.03, -0.09, 0.30, }, + { -0.90, -0.22, -0.16, -0.27, }, + { -0.83, -0.40, 0.31, 0.06, }, + { -0.73, -0.57, -0.25, 0.19, }, + { -0.60, -0.71, 0.02, -0.31, }, + { -0.44, -0.82, 0.22, 0.23, }, + { -0.26, -0.89, -0.31, 0.01, }, + { -0.07, -0.92, 0.20, -0.24, }, + { 0.12, -0.92, 0.04, 0.31, }, + { 0.31, -0.87, -0.26, -0.18, }, + { 0.49, -0.79, 0.30, -0.07, }, + { 0.64, -0.67, -0.15, 0.28, }, + { 0.77, -0.52, -0.11, -0.29, }, + { 0.86, -0.35, 0.29, 0.12, }, + { 0.91, -0.16, -0.28, 0.14, }, + { 0.93, 0.03, 0.09, -0.30, }, + { 0.90, 0.22, 0.16, 0.27, }, + { 0.83, 0.40, -0.31, -0.06, }, + { 0.73, 0.57, 0.25, -0.19, }, + { 0.60, 0.71, -0.02, 0.31, }, + { -0.13, 0.83, -0.27, -0.41, }, + { -0.30, 0.79, 0.49, 0.07, }, + { -0.46, 0.71, -0.38, 0.31, }, + { -0.60, 0.60, 0.02, -0.49, }, + { -0.71, 0.46, 0.35, 0.35, }, + { -0.79, 0.30, -0.49, 0.03, }, + { -0.83, 0.13, 0.31, -0.38, }, + { -0.84, -0.05, 0.08, 0.49, }, + { -0.81, -0.22, -0.41, -0.27, }, + { -0.75, -0.38, 0.48, -0.13, }, + { -0.65, -0.53, -0.22, 0.44, }, + { -0.53, -0.66, -0.18, -0.46, }, + { -0.38, -0.75, 0.46, 0.17, }, + { -0.22, -0.82, -0.44, 0.23, }, + { -0.04, -0.84, 0.12, -0.48, }, + { 0.13, -0.83, 0.27, 0.41, }, + { 0.30, -0.79, -0.49, -0.07, }, + { 0.46, -0.71, 0.38, -0.31, }, + { 0.60, -0.60, -0.02, 0.49, }, + { 0.71, -0.46, -0.35, -0.35, }, + { 0.79, -0.30, 0.49, -0.03, }, + { 0.83, -0.13, -0.31, 0.38, }, + { 0.84, 0.05, -0.08, -0.49, }, + { 0.81, 0.22, 0.41, 0.27, }, + { 0.75, 0.38, -0.48, 0.13, }, + { 0.65, 0.53, 0.22, -0.44, }, + { 0.53, 0.66, 0.18, 0.46, }, + { 0.38, 0.75, -0.46, -0.17, }, + { 0.22, 0.82, 0.44, -0.23, }, + { 0.04, 0.84, -0.12, 0.48, }, + { -0.65, 0.53, -0.22, -0.44, }, + { -0.75, 0.38, 0.48, 0.13, }, + { -0.81, 0.22, -0.41, 0.27, }, + { -0.84, 0.05, 0.08, -0.49, }, + { -0.83, -0.13, 0.31, 0.38, }, + { -0.79, -0.30, -0.49, -0.03, }, + { -0.71, -0.46, 0.35, -0.35, }, + { -0.60, -0.60, 0.02, 0.49, }, + { -0.46, -0.71, -0.38, -0.31, }, + { -0.30, -0.79, 0.49, -0.07, }, + { -0.13, -0.83, -0.27, 0.41, }, + { 0.04, -0.84, -0.13, -0.48, }, + { 0.22, -0.82, 0.44, 0.23, }, + { 0.38, -0.75, -0.46, 0.17, }, + { 0.53, -0.66, 0.18, -0.46, }, + { 0.65, -0.53, 0.22, 0.44, }, + { 0.75, -0.38, -0.48, -0.13, }, + { 0.81, -0.22, 0.41, -0.27, }, + { 0.84, -0.05, -0.08, 0.49, }, + { 0.83, 0.13, -0.31, -0.38, }, + { 0.79, 0.30, 0.49, 0.03, }, + { 0.71, 0.46, -0.35, 0.35, }, + { 0.60, 0.60, -0.02, -0.49, }, + { 0.46, 0.71, 0.38, 0.31, }, + { 0.30, 0.79, -0.49, 0.07, }, + { 0.13, 0.83, 0.27, -0.41, }, + { -0.04, 0.84, 0.13, 0.48, }, + { -0.22, 0.82, -0.44, -0.23, }, + { -0.38, 0.75, 0.46, -0.17, }, + { -0.53, 0.66, -0.18, 0.46, }, + { 0.11, 0.78, -0.33, -0.47, }, + { -0.05, 0.79, 0.57, 0.07, }, + { -0.22, 0.76, -0.44, 0.38, }, + { -0.37, 0.70, 0.01, -0.58, }, + { -0.51, 0.60, 0.42, 0.40, }, + { -0.62, 0.49, -0.57, 0.05, }, + { -0.71, 0.35, 0.35, -0.46, }, + { -0.77, 0.19, 0.11, 0.57, }, + { -0.79, 0.03, -0.49, -0.30, }, + { -0.78, -0.14, 0.55, -0.16, }, + { -0.73, -0.29, -0.25, 0.52, }, + { -0.65, -0.44, -0.22, -0.53, }, + { -0.55, -0.57, 0.54, 0.19, }, + { -0.42, -0.67, -0.51, 0.28, }, + { -0.27, -0.74, 0.13, -0.56, }, + { -0.11, -0.78, 0.33, 0.47, }, + { 0.05, -0.79, -0.57, -0.07, }, + { 0.22, -0.76, 0.44, -0.38, }, + { 0.37, -0.70, -0.01, 0.58, }, + { 0.51, -0.60, -0.42, -0.40, }, + { 0.62, -0.49, 0.57, -0.05, }, + { 0.71, -0.35, -0.35, 0.46, }, + { 0.77, -0.19, -0.11, -0.57, }, + { 0.79, -0.03, 0.49, 0.30, }, + { 0.78, 0.14, -0.55, 0.16, }, + { 0.73, 0.29, 0.25, -0.52, }, + { 0.65, 0.44, 0.22, 0.53, }, + { 0.55, 0.57, -0.54, -0.19, }, + { 0.42, 0.67, 0.51, -0.28, }, + { 0.27, 0.74, -0.13, 0.56, }, + { -0.73, 0.29, -0.25, -0.52, }, + { -0.78, 0.14, 0.55, 0.16, }, + { -0.79, -0.03, -0.49, 0.30, }, + { -0.77, -0.19, 0.11, -0.57, }, + { -0.71, -0.35, 0.35, 0.46, }, + { -0.62, -0.49, -0.57, -0.05, }, + { -0.51, -0.60, 0.42, -0.40, }, + { -0.37, -0.70, 0.01, 0.58, }, + { -0.22, -0.76, -0.44, -0.38, }, + { -0.05, -0.79, 0.57, -0.07, }, + { 0.11, -0.78, -0.33, 0.47, }, + { 0.27, -0.74, -0.13, -0.56, }, + { 0.42, -0.67, 0.51, 0.28, }, + { 0.55, -0.57, -0.54, 0.19, }, + { 0.65, -0.44, 0.22, -0.53, }, + { 0.73, -0.29, 0.25, 0.52, }, + { 0.78, -0.14, -0.55, -0.16, }, + { 0.79, 0.03, 0.49, -0.30, }, + { 0.77, 0.19, -0.11, 0.57, }, + { 0.71, 0.35, -0.35, -0.46, }, + { 0.62, 0.49, 0.57, 0.05, }, + { 0.51, 0.60, -0.42, 0.40, }, + { 0.37, 0.70, -0.01, -0.58, }, + { 0.22, 0.76, 0.44, 0.38, }, + { 0.05, 0.79, -0.57, 0.07, }, + { -0.11, 0.78, 0.33, -0.47, }, + { -0.27, 0.74, 0.13, 0.56, }, + { -0.42, 0.67, -0.51, -0.28, }, + { -0.55, 0.57, 0.54, -0.19, }, + { -0.65, 0.44, -0.22, 0.53, }, + { -0.28, 0.70, -0.24, -0.58, }, + { -0.42, 0.62, 0.59, 0.21, }, + { -0.54, 0.52, -0.55, 0.29, }, + { -0.64, 0.40, 0.15, -0.60, }, + { -0.71, 0.25, 0.35, 0.51, }, + { -0.75, 0.10, -0.62, -0.08, }, + { -0.75, -0.06, 0.48, -0.40, }, + { -0.72, -0.21, -0.02, 0.62, }, + { -0.66, -0.36, -0.45, -0.43, }, + { -0.57, -0.49, 0.62, -0.05, }, + { -0.46, -0.60, -0.38, 0.49, }, + { -0.33, -0.68, -0.11, -0.61, }, + { -0.18, -0.73, 0.53, 0.33, }, + { -0.02, -0.75, -0.60, 0.17, }, + { 0.13, -0.74, 0.27, -0.56, }, + { 0.28, -0.70, 0.24, 0.58, }, + { 0.42, -0.62, -0.59, -0.21, }, + { 0.54, -0.52, 0.55, -0.29, }, + { 0.64, -0.40, -0.15, 0.60, }, + { 0.71, -0.25, -0.35, -0.51, }, + { 0.75, -0.10, 0.62, 0.08, }, + { 0.75, 0.06, -0.48, 0.40, }, + { 0.72, 0.21, 0.02, -0.62, }, + { 0.66, 0.36, 0.45, 0.43, }, + { 0.57, 0.49, -0.62, 0.05, }, + { 0.46, 0.60, 0.38, -0.49, }, + { 0.33, 0.68, 0.11, 0.61, }, + { 0.18, 0.73, -0.53, -0.33, }, + { 0.02, 0.75, 0.60, -0.17, }, + { -0.13, 0.74, -0.27, 0.56, }, + { -0.46, 0.60, -0.38, -0.49, }, + { -0.57, 0.49, 0.62, 0.05, }, + { -0.66, 0.36, -0.45, 0.43, }, + { -0.72, 0.21, -0.02, -0.62, }, + { -0.75, 0.06, 0.48, 0.40, }, + { -0.75, -0.10, -0.62, 0.08, }, + { -0.71, -0.25, 0.35, -0.51, }, + { -0.64, -0.40, 0.15, 0.60, }, + { -0.54, -0.52, -0.55, -0.29, }, + { -0.42, -0.62, 0.59, -0.21, }, + { -0.28, -0.70, -0.24, 0.58, }, + { -0.13, -0.74, -0.27, -0.56, }, + { 0.02, -0.75, 0.60, 0.17, }, + { 0.18, -0.73, -0.53, 0.33, }, + { 0.33, -0.68, 0.11, -0.61, }, + { 0.46, -0.60, 0.38, 0.49, }, + { 0.57, -0.49, -0.62, -0.05, }, + { 0.66, -0.36, 0.45, -0.43, }, + { 0.72, -0.21, 0.02, 0.62, }, + { 0.75, -0.06, -0.48, -0.40, }, + { 0.75, 0.10, 0.62, -0.08, }, + { 0.71, 0.25, -0.35, 0.51, }, + { 0.64, 0.40, -0.15, -0.60, }, + { 0.54, 0.52, 0.55, 0.29, }, + { 0.42, 0.62, -0.59, 0.21, }, + { 0.28, 0.70, 0.24, -0.58, }, + { 0.13, 0.74, 0.27, 0.56, }, + { -0.02, 0.75, -0.60, -0.17, }, + { -0.18, 0.73, 0.53, -0.33, }, + { -0.33, 0.68, -0.11, 0.61, }, + { -0.24, 0.58, 0.28, 0.70, }, + { -0.35, 0.51, -0.71, -0.25, }, + { -0.45, 0.43, 0.66, -0.36, }, + { -0.53, 0.33, -0.18, 0.73, }, + { -0.59, 0.21, -0.42, -0.62, }, + { -0.62, 0.08, 0.75, 0.10, }, + { -0.62, -0.05, -0.57, 0.49, }, + { -0.60, -0.17, 0.02, -0.75, }, + { -0.55, -0.29, 0.54, 0.52, }, + { -0.48, -0.40, -0.75, 0.06, }, + { -0.38, -0.49, 0.46, -0.60, }, + { -0.27, -0.56, 0.13, 0.74, }, + { -0.15, -0.60, -0.64, -0.40, }, + { -0.02, -0.62, 0.72, -0.21, }, + { 0.11, -0.61, -0.33, 0.68, }, + { 0.24, -0.58, -0.29, -0.70, }, + { 0.35, -0.51, 0.71, 0.25, }, + { 0.45, -0.43, -0.66, 0.36, }, + { 0.53, -0.33, 0.18, -0.73, }, + { 0.59, -0.21, 0.42, 0.62, }, + { 0.62, -0.08, -0.75, -0.10, }, + { 0.62, 0.05, 0.57, -0.49, }, + { 0.60, 0.17, -0.02, 0.75, }, + { 0.55, 0.29, -0.54, -0.52, }, + { 0.48, 0.40, 0.75, -0.06, }, + { 0.38, 0.49, -0.46, 0.60, }, + { 0.27, 0.56, -0.13, -0.74, }, + { 0.15, 0.60, 0.64, 0.40, }, + { 0.02, 0.62, -0.72, 0.21, }, + { -0.11, 0.61, 0.33, -0.68, }, + { -0.38, 0.49, 0.46, 0.60, }, + { -0.48, 0.40, -0.75, -0.06, }, + { -0.55, 0.29, 0.54, -0.52, }, + { -0.60, 0.17, 0.02, 0.75, }, + { -0.62, 0.05, -0.57, -0.49, }, + { -0.62, -0.08, 0.75, -0.10, }, + { -0.59, -0.21, -0.42, 0.62, }, + { -0.53, -0.33, -0.18, -0.73, }, + { -0.45, -0.43, 0.66, 0.36, }, + { -0.35, -0.51, -0.71, 0.25, }, + { -0.24, -0.58, 0.28, -0.70, }, + { -0.11, -0.61, 0.33, 0.68, }, + { 0.02, -0.62, -0.72, -0.21, }, + { 0.15, -0.60, 0.64, -0.40, }, + { 0.27, -0.56, -0.13, 0.74, }, + { 0.38, -0.49, -0.46, -0.60, }, + { 0.48, -0.40, 0.75, 0.06, }, + { 0.55, -0.29, -0.54, 0.52, }, + { 0.60, -0.17, -0.02, -0.75, }, + { 0.62, -0.05, 0.57, 0.49, }, + { 0.62, 0.08, -0.75, 0.10, }, + { 0.59, 0.21, 0.42, -0.62, }, + { 0.53, 0.33, 0.18, 0.73, }, + { 0.45, 0.43, -0.66, -0.36, }, + { 0.35, 0.51, 0.71, -0.25, }, + { 0.24, 0.58, -0.28, 0.70, }, + { 0.11, 0.61, -0.33, -0.68, }, + { -0.02, 0.62, 0.72, 0.21, }, + { -0.15, 0.60, -0.64, 0.40, }, + { -0.27, 0.56, 0.13, -0.74, }, + { -0.33, 0.47, -0.11, 0.78, }, + { -0.42, 0.40, -0.51, -0.60, }, + { -0.49, 0.30, 0.79, 0.03, }, + { -0.54, 0.19, -0.55, 0.57, }, + { -0.57, 0.07, -0.05, -0.79, }, + { -0.57, -0.05, 0.62, 0.49, }, + { -0.55, -0.16, -0.78, 0.14, }, + { -0.51, -0.28, 0.42, -0.67, }, + { -0.44, -0.38, 0.22, 0.76, }, + { -0.35, -0.46, -0.71, -0.35, }, + { -0.25, -0.52, 0.73, -0.29, }, + { -0.13, -0.56, -0.27, 0.74, }, + { -0.01, -0.58, -0.37, -0.70, }, + { 0.11, -0.57, 0.77, 0.19, }, + { 0.22, -0.53, -0.65, 0.44, }, + { 0.33, -0.47, 0.11, -0.78, }, + { 0.42, -0.40, 0.51, 0.60, }, + { 0.49, -0.30, -0.79, -0.03, }, + { 0.54, -0.19, 0.55, -0.57, }, + { 0.57, -0.07, 0.05, 0.79, }, + { 0.57, 0.05, -0.62, -0.49, }, + { 0.55, 0.16, 0.78, -0.14, }, + { 0.51, 0.28, -0.42, 0.67, }, + { 0.44, 0.38, -0.22, -0.76, }, + { 0.35, 0.46, 0.71, 0.35, }, + { 0.25, 0.52, -0.73, 0.29, }, + { 0.13, 0.56, 0.27, -0.74, }, + { 0.01, 0.58, 0.37, 0.70, }, + { -0.11, 0.57, -0.77, -0.19, }, + { -0.22, 0.53, 0.65, -0.44, }, + { -0.25, 0.52, 0.73, 0.29, }, + { -0.35, 0.46, -0.71, 0.35, }, + { -0.44, 0.38, 0.22, -0.76, }, + { -0.51, 0.28, 0.42, 0.67, }, + { -0.55, 0.16, -0.78, -0.14, }, + { -0.57, 0.05, 0.62, -0.49, }, + { -0.57, -0.07, -0.05, 0.79, }, + { -0.54, -0.19, -0.55, -0.57, }, + { -0.49, -0.30, 0.79, -0.03, }, + { -0.42, -0.40, -0.51, 0.60, }, + { -0.33, -0.47, -0.11, -0.78, }, + { -0.22, -0.53, 0.65, 0.44, }, + { -0.11, -0.57, -0.77, 0.19, }, + { 0.01, -0.58, 0.37, -0.70, }, + { 0.13, -0.56, 0.27, 0.74, }, + { 0.25, -0.52, -0.73, -0.29, }, + { 0.35, -0.46, 0.71, -0.35, }, + { 0.44, -0.38, -0.22, 0.76, }, + { 0.51, -0.28, -0.42, -0.67, }, + { 0.55, -0.16, 0.78, 0.14, }, + { 0.57, -0.05, -0.62, 0.49, }, + { 0.57, 0.07, 0.05, -0.79, }, + { 0.54, 0.19, 0.55, 0.57, }, + { 0.49, 0.30, -0.79, 0.03, }, + { 0.42, 0.40, 0.51, -0.60, }, + { 0.33, 0.47, 0.11, 0.78, }, + { 0.22, 0.53, -0.65, -0.44, }, + { 0.11, 0.57, 0.77, -0.19, }, + { -0.01, 0.58, -0.37, 0.70, }, + { -0.13, 0.56, -0.27, -0.74, }, + { -0.27, 0.41, 0.13, 0.83, }, + { -0.35, 0.35, -0.71, -0.46, }, + { -0.41, 0.27, 0.81, -0.22, }, + { -0.46, 0.17, -0.38, 0.75, }, + { -0.49, 0.07, -0.30, -0.79, }, + { -0.49, -0.03, 0.79, 0.30, }, + { -0.48, -0.13, -0.75, 0.38, }, + { -0.44, -0.23, 0.22, -0.82, }, + { -0.38, -0.31, 0.46, 0.71, }, + { -0.31, -0.38, -0.83, -0.13, }, + { -0.22, -0.44, 0.65, -0.53, }, + { -0.13, -0.48, -0.04, 0.84, }, + { -0.02, -0.49, -0.60, -0.60, }, + { 0.08, -0.49, 0.84, -0.05, }, + { 0.18, -0.46, -0.53, 0.66, }, + { 0.27, -0.41, -0.13, -0.83, }, + { 0.35, -0.35, 0.71, 0.46, }, + { 0.41, -0.27, -0.81, 0.22, }, + { 0.46, -0.17, 0.38, -0.75, }, + { 0.49, -0.07, 0.30, 0.79, }, + { 0.49, 0.03, -0.79, -0.30, }, + { 0.48, 0.13, 0.75, -0.38, }, + { 0.44, 0.23, -0.22, 0.82, }, + { 0.38, 0.31, -0.46, -0.71, }, + { 0.31, 0.38, 0.83, 0.13, }, + { 0.22, 0.44, -0.65, 0.53, }, + { 0.12, 0.48, 0.04, -0.84, }, + { 0.02, 0.49, 0.60, 0.60, }, + { -0.08, 0.49, -0.84, 0.05, }, + { -0.18, 0.46, 0.53, -0.66, }, + { -0.22, 0.44, 0.65, 0.53, }, + { -0.31, 0.38, -0.83, 0.13, }, + { -0.38, 0.31, 0.46, -0.71, }, + { -0.44, 0.23, 0.22, 0.82, }, + { -0.48, 0.13, -0.75, -0.38, }, + { -0.49, 0.03, 0.79, -0.30, }, + { -0.49, -0.07, -0.30, 0.79, }, + { -0.46, -0.17, -0.38, -0.75, }, + { -0.41, -0.27, 0.81, 0.22, }, + { -0.35, -0.35, -0.71, 0.46, }, + { -0.27, -0.41, 0.13, -0.83, }, + { -0.18, -0.46, 0.53, 0.66, }, + { -0.08, -0.49, -0.84, -0.05, }, + { 0.02, -0.49, 0.60, -0.60, }, + { 0.12, -0.48, 0.04, 0.84, }, + { 0.22, -0.44, -0.65, -0.53, }, + { 0.31, -0.38, 0.83, -0.13, }, + { 0.38, -0.31, -0.46, 0.71, }, + { 0.44, -0.23, -0.22, -0.82, }, + { 0.48, -0.13, 0.75, 0.38, }, + { 0.49, -0.03, -0.79, 0.30, }, + { 0.49, 0.07, 0.30, -0.79, }, + { 0.46, 0.17, 0.38, 0.75, }, + { 0.41, 0.27, -0.81, -0.22, }, + { 0.35, 0.35, 0.71, -0.46, }, + { 0.27, 0.41, -0.13, 0.83, }, + { 0.18, 0.46, -0.53, -0.66, }, + { 0.08, 0.49, 0.84, 0.05, }, + { -0.02, 0.49, -0.60, 0.60, }, + { -0.12, 0.48, -0.04, -0.84, }, + { -0.15, 0.28, -0.64, 0.67, }, + { -0.20, 0.24, -0.07, -0.92, }, + { -0.25, 0.19, 0.73, 0.57, }, + { -0.28, 0.14, -0.91, 0.16, }, + { -0.30, 0.07, 0.49, -0.79, }, + { -0.31, 0.01, 0.26, 0.89, }, + { -0.31, -0.06, -0.83, -0.40, }, + { -0.29, -0.12, 0.86, -0.35, }, + { -0.26, -0.18, -0.31, 0.87, }, + { -0.22, -0.23, -0.44, -0.82, }, + { -0.16, -0.27, 0.90, 0.22, }, + { -0.11, -0.29, -0.77, 0.52, }, + { -0.04, -0.31, 0.12, -0.92, }, + { 0.02, -0.31, 0.60, 0.71, }, + { 0.09, -0.30, -0.93, -0.03, }, + { 0.15, -0.28, 0.64, -0.67, }, + { 0.20, -0.24, 0.07, 0.92, }, + { 0.25, -0.19, -0.73, -0.57, }, + { 0.28, -0.14, 0.91, -0.16, }, + { 0.30, -0.07, -0.49, 0.79, }, + { 0.31, -0.01, -0.26, -0.89, }, + { 0.31, 0.06, 0.83, 0.40, }, + { 0.29, 0.12, -0.86, 0.35, }, + { 0.26, 0.18, 0.31, -0.87, }, + { 0.22, 0.23, 0.44, 0.82, }, + { 0.16, 0.27, -0.90, -0.22, }, + { 0.11, 0.29, 0.77, -0.52, }, + { 0.04, 0.31, -0.12, 0.92, }, + { -0.02, 0.31, -0.60, -0.71, }, + { -0.09, 0.30, 0.93, 0.03, }, + { -0.22, 0.23, -0.44, 0.82, }, + { -0.26, 0.18, -0.31, -0.87, }, + { -0.29, 0.12, 0.86, 0.35, }, + { -0.31, 0.06, -0.83, 0.40, }, + { -0.31, -0.01, 0.26, -0.89, }, + { -0.30, -0.07, 0.49, 0.79, }, + { -0.28, -0.14, -0.91, -0.16, }, + { -0.25, -0.19, 0.73, -0.57, }, + { -0.20, -0.24, -0.07, 0.92, }, + { -0.15, -0.28, -0.64, -0.67, }, + { -0.09, -0.30, 0.93, -0.03, }, + { -0.02, -0.31, -0.60, 0.71, }, + { 0.04, -0.31, -0.13, -0.92, }, + { 0.11, -0.29, 0.77, 0.52, }, + { 0.16, -0.27, -0.90, 0.22, }, + { 0.22, -0.23, 0.44, -0.82, }, + { 0.26, -0.18, 0.31, 0.87, }, + { 0.29, -0.12, -0.86, -0.35, }, + { 0.31, -0.06, 0.83, -0.40, }, + { 0.31, 0.01, -0.26, 0.89, }, + { 0.30, 0.07, -0.49, -0.79, }, + { 0.28, 0.14, 0.91, 0.16, }, + { 0.25, 0.19, -0.73, 0.57, }, + { 0.20, 0.24, 0.07, -0.92, }, + { 0.15, 0.28, 0.64, 0.67, }, + { 0.09, 0.30, -0.93, 0.03, }, + { 0.02, 0.31, 0.60, -0.71, }, + { -0.04, 0.31, 0.13, 0.92, }, + { -0.11, 0.29, -0.77, -0.52, }, + { -0.16, 0.27, 0.90, -0.22, }, +}; + +static const struct line_info line_table[LINE_COUNT] = +{ + { 0, 1, 0, }, + { 0, 29, 0, }, + { 0, 148, 0, }, + { 0, 176, 0, }, + { 1, 2, 0, }, + { 1, 149, 0, }, + { 1, 177, 0, }, + { 2, 3, 0, }, + { 2, 120, 0, }, + { 2, 178, 0, }, + { 3, 4, 0, }, + { 3, 121, 0, }, + { 3, 179, 0, }, + { 4, 5, 0, }, + { 4, 122, 0, }, + { 4, 150, 0, }, + { 5, 6, 0, }, + { 5, 123, 0, }, + { 5, 151, 0, }, + { 6, 7, 0, }, + { 6, 124, 0, }, + { 6, 152, 0, }, + { 7, 8, 0, }, + { 7, 125, 0, }, + { 7, 153, 0, }, + { 8, 9, 0, }, + { 8, 126, 0, }, + { 8, 154, 0, }, + { 9, 10, 0, }, + { 9, 127, 0, }, + { 9, 155, 0, }, + { 10, 11, 0, }, + { 10, 128, 0, }, + { 10, 156, 0, }, + { 11, 12, 0, }, + { 11, 129, 0, }, + { 11, 157, 0, }, + { 12, 13, 0, }, + { 12, 130, 0, }, + { 12, 158, 0, }, + { 13, 14, 0, }, + { 13, 131, 0, }, + { 13, 159, 0, }, + { 14, 15, 0, }, + { 14, 132, 0, }, + { 14, 160, 0, }, + { 15, 16, 0, }, + { 15, 133, 0, }, + { 15, 161, 0, }, + { 16, 17, 0, }, + { 16, 134, 0, }, + { 16, 162, 0, }, + { 17, 18, 0, }, + { 17, 135, 0, }, + { 17, 163, 0, }, + { 18, 19, 0, }, + { 18, 136, 0, }, + { 18, 164, 0, }, + { 19, 20, 0, }, + { 19, 137, 0, }, + { 19, 165, 0, }, + { 20, 21, 0, }, + { 20, 138, 0, }, + { 20, 166, 0, }, + { 21, 22, 0, }, + { 21, 139, 0, }, + { 21, 167, 0, }, + { 22, 23, 0, }, + { 22, 140, 0, }, + { 22, 168, 0, }, + { 23, 24, 0, }, + { 23, 141, 0, }, + { 23, 169, 0, }, + { 24, 25, 0, }, + { 24, 142, 0, }, + { 24, 170, 0, }, + { 25, 26, 0, }, + { 25, 143, 0, }, + { 25, 171, 0, }, + { 26, 27, 0, }, + { 26, 144, 0, }, + { 26, 172, 0, }, + { 27, 28, 0, }, + { 27, 145, 0, }, + { 27, 173, 0, }, + { 28, 29, 0, }, + { 28, 146, 0, }, + { 28, 174, 0, }, + { 29, 147, 0, }, + { 29, 175, 0, }, + { 30, 123, 0, }, + { 30, 150, 0, }, + { 30, 240, 0, }, + { 30, 292, 0, }, + { 31, 124, 0, }, + { 31, 151, 0, }, + { 31, 241, 0, }, + { 31, 293, 0, }, + { 32, 125, 0, }, + { 32, 152, 0, }, + { 32, 242, 0, }, + { 32, 294, 0, }, + { 33, 126, 0, }, + { 33, 153, 0, }, + { 33, 243, 0, }, + { 33, 295, 0, }, + { 34, 127, 0, }, + { 34, 154, 0, }, + { 34, 244, 0, }, + { 34, 296, 0, }, + { 35, 128, 0, }, + { 35, 155, 0, }, + { 35, 245, 0, }, + { 35, 297, 0, }, + { 36, 129, 0, }, + { 36, 156, 0, }, + { 36, 246, 0, }, + { 36, 298, 0, }, + { 37, 130, 0, }, + { 37, 157, 0, }, + { 37, 247, 0, }, + { 37, 299, 0, }, + { 38, 131, 0, }, + { 38, 158, 0, }, + { 38, 248, 0, }, + { 38, 270, 0, }, + { 39, 132, 0, }, + { 39, 159, 0, }, + { 39, 249, 0, }, + { 39, 271, 0, }, + { 40, 133, 0, }, + { 40, 160, 0, }, + { 40, 250, 0, }, + { 40, 272, 0, }, + { 41, 134, 0, }, + { 41, 161, 0, }, + { 41, 251, 0, }, + { 41, 273, 0, }, + { 42, 135, 0, }, + { 42, 162, 0, }, + { 42, 252, 0, }, + { 42, 274, 0, }, + { 43, 136, 0, }, + { 43, 163, 0, }, + { 43, 253, 0, }, + { 43, 275, 0, }, + { 44, 137, 0, }, + { 44, 164, 0, }, + { 44, 254, 0, }, + { 44, 276, 0, }, + { 45, 138, 1, }, + { 45, 165, 1, }, + { 45, 255, 1, }, + { 45, 277, 1, }, + { 46, 139, 1, }, + { 46, 166, 1, }, + { 46, 256, 1, }, + { 46, 278, 1, }, + { 47, 140, 1, }, + { 47, 167, 1, }, + { 47, 257, 1, }, + { 47, 279, 1, }, + { 48, 141, 1, }, + { 48, 168, 1, }, + { 48, 258, 1, }, + { 48, 280, 1, }, + { 49, 142, 1, }, + { 49, 169, 1, }, + { 49, 259, 1, }, + { 49, 281, 1, }, + { 50, 143, 1, }, + { 50, 170, 1, }, + { 50, 260, 1, }, + { 50, 282, 1, }, + { 51, 144, 1, }, + { 51, 171, 1, }, + { 51, 261, 1, }, + { 51, 283, 1, }, + { 52, 145, 1, }, + { 52, 172, 1, }, + { 52, 262, 1, }, + { 52, 284, 1, }, + { 53, 146, 1, }, + { 53, 173, 1, }, + { 53, 263, 1, }, + { 53, 285, 1, }, + { 54, 147, 1, }, + { 54, 174, 1, }, + { 54, 264, 1, }, + { 54, 286, 1, }, + { 55, 148, 1, }, + { 55, 175, 1, }, + { 55, 265, 1, }, + { 55, 287, 1, }, + { 56, 149, 1, }, + { 56, 176, 1, }, + { 56, 266, 1, }, + { 56, 288, 1, }, + { 57, 120, 1, }, + { 57, 177, 1, }, + { 57, 267, 1, }, + { 57, 289, 1, }, + { 58, 121, 1, }, + { 58, 178, 1, }, + { 58, 268, 1, }, + { 58, 290, 1, }, + { 59, 122, 1, }, + { 59, 179, 1, }, + { 59, 269, 1, }, + { 59, 291, 1, }, + { 60, 420, 1, }, + { 60, 478, 1, }, + { 60, 567, 1, }, + { 60, 570, 1, }, + { 61, 421, 1, }, + { 61, 479, 1, }, + { 61, 568, 1, }, + { 61, 571, 1, }, + { 62, 422, 1, }, + { 62, 450, 1, }, + { 62, 569, 1, }, + { 62, 572, 1, }, + { 63, 423, 1, }, + { 63, 451, 1, }, + { 63, 540, 1, }, + { 63, 573, 1, }, + { 64, 424, 1, }, + { 64, 452, 1, }, + { 64, 541, 1, }, + { 64, 574, 1, }, + { 65, 425, 1, }, + { 65, 453, 1, }, + { 65, 542, 1, }, + { 65, 575, 1, }, + { 66, 426, 1, }, + { 66, 454, 1, }, + { 66, 543, 1, }, + { 66, 576, 1, }, + { 67, 427, 1, }, + { 67, 455, 1, }, + { 67, 544, 1, }, + { 67, 577, 1, }, + { 68, 428, 1, }, + { 68, 456, 1, }, + { 68, 545, 1, }, + { 68, 578, 1, }, + { 69, 429, 1, }, + { 69, 457, 1, }, + { 69, 546, 1, }, + { 69, 579, 1, }, + { 70, 430, 1, }, + { 70, 458, 1, }, + { 70, 547, 1, }, + { 70, 580, 1, }, + { 71, 431, 1, }, + { 71, 459, 1, }, + { 71, 548, 1, }, + { 71, 581, 1, }, + { 72, 432, 1, }, + { 72, 460, 1, }, + { 72, 549, 1, }, + { 72, 582, 1, }, + { 73, 433, 1, }, + { 73, 461, 1, }, + { 73, 550, 1, }, + { 73, 583, 1, }, + { 74, 434, 1, }, + { 74, 462, 1, }, + { 74, 551, 1, }, + { 74, 584, 1, }, + { 75, 435, 1, }, + { 75, 463, 1, }, + { 75, 552, 1, }, + { 75, 585, 1, }, + { 76, 436, 1, }, + { 76, 464, 1, }, + { 76, 553, 1, }, + { 76, 586, 1, }, + { 77, 437, 1, }, + { 77, 465, 1, }, + { 77, 554, 1, }, + { 77, 587, 1, }, + { 78, 438, 1, }, + { 78, 466, 1, }, + { 78, 555, 1, }, + { 78, 588, 1, }, + { 79, 439, 1, }, + { 79, 467, 1, }, + { 79, 556, 1, }, + { 79, 589, 1, }, + { 80, 440, 1, }, + { 80, 468, 1, }, + { 80, 557, 1, }, + { 80, 590, 1, }, + { 81, 441, 1, }, + { 81, 469, 1, }, + { 81, 558, 1, }, + { 81, 591, 1, }, + { 82, 442, 1, }, + { 82, 470, 1, }, + { 82, 559, 2, }, + { 82, 592, 2, }, + { 83, 443, 2, }, + { 83, 471, 2, }, + { 83, 560, 2, }, + { 83, 593, 2, }, + { 84, 444, 2, }, + { 84, 472, 2, }, + { 84, 561, 2, }, + { 84, 594, 2, }, + { 85, 445, 2, }, + { 85, 473, 2, }, + { 85, 562, 2, }, + { 85, 595, 2, }, + { 86, 446, 2, }, + { 86, 474, 2, }, + { 86, 563, 2, }, + { 86, 596, 2, }, + { 87, 447, 2, }, + { 87, 475, 2, }, + { 87, 564, 2, }, + { 87, 597, 2, }, + { 88, 448, 2, }, + { 88, 476, 2, }, + { 88, 565, 2, }, + { 88, 598, 2, }, + { 89, 449, 2, }, + { 89, 477, 2, }, + { 89, 566, 2, }, + { 89, 599, 2, }, + { 90, 101, 2, }, + { 90, 109, 2, }, + { 90, 562, 2, }, + { 90, 584, 2, }, + { 91, 102, 2, }, + { 91, 110, 2, }, + { 91, 563, 2, }, + { 91, 585, 2, }, + { 92, 103, 2, }, + { 92, 111, 2, }, + { 92, 564, 2, }, + { 92, 586, 2, }, + { 93, 104, 2, }, + { 93, 112, 2, }, + { 93, 565, 2, }, + { 93, 587, 2, }, + { 94, 105, 2, }, + { 94, 113, 2, }, + { 94, 566, 2, }, + { 94, 588, 2, }, + { 95, 106, 2, }, + { 95, 114, 2, }, + { 95, 567, 2, }, + { 95, 589, 2, }, + { 96, 107, 2, }, + { 96, 115, 2, }, + { 96, 568, 2, }, + { 96, 590, 2, }, + { 97, 108, 2, }, + { 97, 116, 2, }, + { 97, 569, 2, }, + { 97, 591, 2, }, + { 98, 109, 2, }, + { 98, 117, 2, }, + { 98, 540, 2, }, + { 98, 592, 2, }, + { 99, 110, 2, }, + { 99, 118, 2, }, + { 99, 541, 2, }, + { 99, 593, 2, }, + { 100, 111, 2, }, + { 100, 119, 2, }, + { 100, 542, 2, }, + { 100, 594, 2, }, + { 101, 112, 2, }, + { 101, 543, 2, }, + { 101, 595, 2, }, + { 102, 113, 2, }, + { 102, 544, 2, }, + { 102, 596, 2, }, + { 103, 114, 2, }, + { 103, 545, 2, }, + { 103, 597, 2, }, + { 104, 115, 2, }, + { 104, 546, 2, }, + { 104, 598, 2, }, + { 105, 116, 2, }, + { 105, 547, 2, }, + { 105, 599, 2, }, + { 106, 117, 2, }, + { 106, 548, 2, }, + { 106, 570, 2, }, + { 107, 118, 2, }, + { 107, 549, 2, }, + { 107, 571, 2, }, + { 108, 119, 2, }, + { 108, 550, 2, }, + { 108, 572, 2, }, + { 109, 551, 2, }, + { 109, 573, 2, }, + { 110, 552, 2, }, + { 110, 574, 2, }, + { 111, 553, 2, }, + { 111, 575, 2, }, + { 112, 554, 2, }, + { 112, 576, 2, }, + { 113, 555, 2, }, + { 113, 577, 2, }, + { 114, 556, 2, }, + { 114, 578, 2, }, + { 115, 557, 2, }, + { 115, 579, 2, }, + { 116, 558, 2, }, + { 116, 580, 2, }, + { 117, 559, 2, }, + { 117, 581, 2, }, + { 118, 560, 2, }, + { 118, 582, 2, }, + { 119, 561, 2, }, + { 119, 583, 2, }, + { 120, 150, 2, }, + { 120, 232, 2, }, + { 121, 151, 2, }, + { 121, 233, 2, }, + { 122, 152, 2, }, + { 122, 234, 2, }, + { 123, 153, 2, }, + { 123, 235, 2, }, + { 124, 154, 2, }, + { 124, 236, 2, }, + { 125, 155, 2, }, + { 125, 237, 2, }, + { 126, 156, 2, }, + { 126, 238, 2, }, + { 127, 157, 2, }, + { 127, 239, 2, }, + { 128, 158, 2, }, + { 128, 210, 2, }, + { 129, 159, 2, }, + { 129, 211, 2, }, + { 130, 160, 2, }, + { 130, 212, 2, }, + { 131, 161, 2, }, + { 131, 213, 2, }, + { 132, 162, 2, }, + { 132, 214, 2, }, + { 133, 163, 2, }, + { 133, 215, 2, }, + { 134, 164, 2, }, + { 134, 216, 2, }, + { 135, 165, 3, }, + { 135, 217, 3, }, + { 136, 166, 3, }, + { 136, 218, 3, }, + { 137, 167, 3, }, + { 137, 219, 3, }, + { 138, 168, 3, }, + { 138, 220, 3, }, + { 139, 169, 3, }, + { 139, 221, 3, }, + { 140, 170, 3, }, + { 140, 222, 3, }, + { 141, 171, 3, }, + { 141, 223, 3, }, + { 142, 172, 3, }, + { 142, 224, 3, }, + { 143, 173, 3, }, + { 143, 225, 3, }, + { 144, 174, 3, }, + { 144, 226, 3, }, + { 145, 175, 3, }, + { 145, 227, 3, }, + { 146, 176, 3, }, + { 146, 228, 3, }, + { 147, 177, 3, }, + { 147, 229, 3, }, + { 148, 178, 3, }, + { 148, 230, 3, }, + { 149, 179, 3, }, + { 149, 231, 3, }, + { 150, 207, 3, }, + { 151, 208, 3, }, + { 152, 209, 3, }, + { 153, 180, 3, }, + { 154, 181, 3, }, + { 155, 182, 3, }, + { 156, 183, 3, }, + { 157, 184, 3, }, + { 158, 185, 3, }, + { 159, 186, 3, }, + { 160, 187, 3, }, + { 161, 188, 3, }, + { 162, 189, 3, }, + { 163, 190, 3, }, + { 164, 191, 3, }, + { 165, 192, 3, }, + { 166, 193, 3, }, + { 167, 194, 3, }, + { 168, 195, 3, }, + { 169, 196, 3, }, + { 170, 197, 3, }, + { 171, 198, 3, }, + { 172, 199, 3, }, + { 173, 200, 3, }, + { 174, 201, 3, }, + { 175, 202, 3, }, + { 176, 203, 3, }, + { 177, 204, 3, }, + { 178, 205, 3, }, + { 179, 206, 3, }, + { 180, 237, 3, }, + { 180, 240, 3, }, + { 180, 300, 3, }, + { 181, 238, 3, }, + { 181, 241, 3, }, + { 181, 301, 3, }, + { 182, 239, 3, }, + { 182, 242, 3, }, + { 182, 302, 3, }, + { 183, 210, 3, }, + { 183, 243, 3, }, + { 183, 303, 3, }, + { 184, 211, 3, }, + { 184, 244, 3, }, + { 184, 304, 3, }, + { 185, 212, 3, }, + { 185, 245, 3, }, + { 185, 305, 3, }, + { 186, 213, 3, }, + { 186, 246, 3, }, + { 186, 306, 3, }, + { 187, 214, 3, }, + { 187, 247, 3, }, + { 187, 307, 3, }, + { 188, 215, 3, }, + { 188, 248, 3, }, + { 188, 308, 3, }, + { 189, 216, 3, }, + { 189, 249, 3, }, + { 189, 309, 3, }, + { 190, 217, 3, }, + { 190, 250, 3, }, + { 190, 310, 3, }, + { 191, 218, 3, }, + { 191, 251, 3, }, + { 191, 311, 3, }, + { 192, 219, 3, }, + { 192, 252, 3, }, + { 192, 312, 3, }, + { 193, 220, 3, }, + { 193, 253, 3, }, + { 193, 313, 3, }, + { 194, 221, 3, }, + { 194, 254, 3, }, + { 194, 314, 3, }, + { 195, 222, 3, }, + { 195, 255, 3, }, + { 195, 315, 3, }, + { 196, 223, 3, }, + { 196, 256, 3, }, + { 196, 316, 3, }, + { 197, 224, 3, }, + { 197, 257, 3, }, + { 197, 317, 3, }, + { 198, 225, 3, }, + { 198, 258, 3, }, + { 198, 318, 3, }, + { 199, 226, 3, }, + { 199, 259, 3, }, + { 199, 319, 3, }, + { 200, 227, 3, }, + { 200, 260, 3, }, + { 200, 320, 3, }, + { 201, 228, 3, }, + { 201, 261, 3, }, + { 201, 321, 3, }, + { 202, 229, 3, }, + { 202, 262, 3, }, + { 202, 322, 3, }, + { 203, 230, 3, }, + { 203, 263, 3, }, + { 203, 323, 3, }, + { 204, 231, 3, }, + { 204, 264, 3, }, + { 204, 324, 3, }, + { 205, 232, 3, }, + { 205, 265, 3, }, + { 205, 325, 3, }, + { 206, 233, 3, }, + { 206, 266, 3, }, + { 206, 326, 3, }, + { 207, 234, 3, }, + { 207, 267, 3, }, + { 207, 327, 3, }, + { 208, 235, 3, }, + { 208, 268, 3, }, + { 208, 328, 3, }, + { 209, 236, 3, }, + { 209, 269, 3, }, + { 209, 329, 3, }, + { 210, 270, 4, }, + { 210, 330, 4, }, + { 211, 271, 4, }, + { 211, 331, 4, }, + { 212, 272, 4, }, + { 212, 332, 4, }, + { 213, 273, 4, }, + { 213, 333, 4, }, + { 214, 274, 4, }, + { 214, 334, 4, }, + { 215, 275, 4, }, + { 215, 335, 4, }, + { 216, 276, 4, }, + { 216, 336, 4, }, + { 217, 277, 4, }, + { 217, 337, 4, }, + { 218, 278, 4, }, + { 218, 338, 4, }, + { 219, 279, 4, }, + { 219, 339, 4, }, + { 220, 280, 4, }, + { 220, 340, 4, }, + { 221, 281, 4, }, + { 221, 341, 4, }, + { 222, 282, 4, }, + { 222, 342, 4, }, + { 223, 283, 4, }, + { 223, 343, 4, }, + { 224, 284, 4, }, + { 224, 344, 4, }, + { 225, 285, 4, }, + { 225, 345, 4, }, + { 226, 286, 4, }, + { 226, 346, 4, }, + { 227, 287, 4, }, + { 227, 347, 4, }, + { 228, 288, 4, }, + { 228, 348, 4, }, + { 229, 289, 4, }, + { 229, 349, 4, }, + { 230, 290, 4, }, + { 230, 350, 4, }, + { 231, 291, 4, }, + { 231, 351, 4, }, + { 232, 292, 4, }, + { 232, 352, 4, }, + { 233, 293, 4, }, + { 233, 353, 4, }, + { 234, 294, 4, }, + { 234, 354, 4, }, + { 235, 295, 4, }, + { 235, 355, 4, }, + { 236, 296, 4, }, + { 236, 356, 4, }, + { 237, 297, 4, }, + { 237, 357, 4, }, + { 238, 298, 4, }, + { 238, 358, 4, }, + { 239, 299, 4, }, + { 239, 359, 4, }, + { 240, 327, 4, }, + { 240, 416, 4, }, + { 241, 328, 4, }, + { 241, 417, 4, }, + { 242, 329, 4, }, + { 242, 418, 4, }, + { 243, 300, 4, }, + { 243, 419, 4, }, + { 244, 301, 4, }, + { 244, 390, 4, }, + { 245, 302, 4, }, + { 245, 391, 4, }, + { 246, 303, 4, }, + { 246, 392, 4, }, + { 247, 304, 4, }, + { 247, 393, 4, }, + { 248, 305, 4, }, + { 248, 394, 4, }, + { 249, 306, 4, }, + { 249, 395, 4, }, + { 250, 307, 4, }, + { 250, 396, 4, }, + { 251, 308, 4, }, + { 251, 397, 4, }, + { 252, 309, 4, }, + { 252, 398, 4, }, + { 253, 310, 4, }, + { 253, 399, 4, }, + { 254, 311, 4, }, + { 254, 400, 4, }, + { 255, 312, 4, }, + { 255, 401, 4, }, + { 256, 313, 4, }, + { 256, 402, 4, }, + { 257, 314, 4, }, + { 257, 403, 4, }, + { 258, 315, 4, }, + { 258, 404, 4, }, + { 259, 316, 4, }, + { 259, 405, 4, }, + { 260, 317, 4, }, + { 260, 406, 4, }, + { 261, 318, 4, }, + { 261, 407, 4, }, + { 262, 319, 4, }, + { 262, 408, 4, }, + { 263, 320, 4, }, + { 263, 409, 4, }, + { 264, 321, 4, }, + { 264, 410, 4, }, + { 265, 322, 4, }, + { 265, 411, 4, }, + { 266, 323, 4, }, + { 266, 412, 4, }, + { 267, 324, 4, }, + { 267, 413, 4, }, + { 268, 325, 4, }, + { 268, 414, 4, }, + { 269, 326, 4, }, + { 269, 415, 4, }, + { 270, 333, 4, }, + { 270, 364, 4, }, + { 271, 334, 4, }, + { 271, 365, 4, }, + { 272, 335, 4, }, + { 272, 366, 4, }, + { 273, 336, 4, }, + { 273, 367, 4, }, + { 274, 337, 4, }, + { 274, 368, 4, }, + { 275, 338, 4, }, + { 275, 369, 4, }, + { 276, 339, 4, }, + { 276, 370, 4, }, + { 277, 340, 4, }, + { 277, 371, 4, }, + { 278, 341, 4, }, + { 278, 372, 4, }, + { 279, 342, 4, }, + { 279, 373, 4, }, + { 280, 343, 4, }, + { 280, 374, 4, }, + { 281, 344, 4, }, + { 281, 375, 4, }, + { 282, 345, 4, }, + { 282, 376, 4, }, + { 283, 346, 4, }, + { 283, 377, 4, }, + { 284, 347, 4, }, + { 284, 378, 4, }, + { 285, 348, 5, }, + { 285, 379, 5, }, + { 286, 349, 5, }, + { 286, 380, 5, }, + { 287, 350, 5, }, + { 287, 381, 5, }, + { 288, 351, 5, }, + { 288, 382, 5, }, + { 289, 352, 5, }, + { 289, 383, 5, }, + { 290, 353, 5, }, + { 290, 384, 5, }, + { 291, 354, 5, }, + { 291, 385, 5, }, + { 292, 355, 5, }, + { 292, 386, 5, }, + { 293, 356, 5, }, + { 293, 387, 5, }, + { 294, 357, 5, }, + { 294, 388, 5, }, + { 295, 358, 5, }, + { 295, 389, 5, }, + { 296, 359, 5, }, + { 296, 360, 5, }, + { 297, 330, 5, }, + { 297, 361, 5, }, + { 298, 331, 5, }, + { 298, 362, 5, }, + { 299, 332, 5, }, + { 299, 363, 5, }, + { 300, 330, 5, }, + { 300, 479, 5, }, + { 301, 331, 5, }, + { 301, 450, 5, }, + { 302, 332, 5, }, + { 302, 451, 5, }, + { 303, 333, 5, }, + { 303, 452, 5, }, + { 304, 334, 5, }, + { 304, 453, 5, }, + { 305, 335, 5, }, + { 305, 454, 5, }, + { 306, 336, 5, }, + { 306, 455, 5, }, + { 307, 337, 5, }, + { 307, 456, 5, }, + { 308, 338, 5, }, + { 308, 457, 5, }, + { 309, 339, 5, }, + { 309, 458, 5, }, + { 310, 340, 5, }, + { 310, 459, 5, }, + { 311, 341, 5, }, + { 311, 460, 5, }, + { 312, 342, 5, }, + { 312, 461, 5, }, + { 313, 343, 5, }, + { 313, 462, 5, }, + { 314, 344, 5, }, + { 314, 463, 5, }, + { 315, 345, 5, }, + { 315, 464, 5, }, + { 316, 346, 5, }, + { 316, 465, 5, }, + { 317, 347, 5, }, + { 317, 466, 5, }, + { 318, 348, 5, }, + { 318, 467, 5, }, + { 319, 349, 5, }, + { 319, 468, 5, }, + { 320, 350, 5, }, + { 320, 469, 5, }, + { 321, 351, 5, }, + { 321, 470, 5, }, + { 322, 352, 5, }, + { 322, 471, 5, }, + { 323, 353, 5, }, + { 323, 472, 5, }, + { 324, 354, 5, }, + { 324, 473, 5, }, + { 325, 355, 5, }, + { 325, 474, 5, }, + { 326, 356, 5, }, + { 326, 475, 5, }, + { 327, 357, 5, }, + { 327, 476, 5, }, + { 328, 358, 5, }, + { 328, 477, 5, }, + { 329, 359, 5, }, + { 329, 478, 5, }, + { 330, 421, 5, }, + { 331, 422, 5, }, + { 332, 423, 5, }, + { 333, 424, 5, }, + { 334, 425, 5, }, + { 335, 426, 5, }, + { 336, 427, 5, }, + { 337, 428, 5, }, + { 338, 429, 5, }, + { 339, 430, 5, }, + { 340, 431, 5, }, + { 341, 432, 5, }, + { 342, 433, 5, }, + { 343, 434, 5, }, + { 344, 435, 5, }, + { 345, 436, 5, }, + { 346, 437, 5, }, + { 347, 438, 5, }, + { 348, 439, 5, }, + { 349, 440, 5, }, + { 350, 441, 5, }, + { 351, 442, 5, }, + { 352, 443, 5, }, + { 353, 444, 5, }, + { 354, 445, 5, }, + { 355, 446, 5, }, + { 356, 447, 5, }, + { 357, 448, 5, }, + { 358, 449, 5, }, + { 359, 420, 5, }, + { 360, 390, 5, }, + { 360, 447, 5, }, + { 360, 480, 5, }, + { 361, 391, 5, }, + { 361, 448, 5, }, + { 361, 481, 5, }, + { 362, 392, 5, }, + { 362, 449, 5, }, + { 362, 482, 5, }, + { 363, 393, 5, }, + { 363, 420, 5, }, + { 363, 483, 5, }, + { 364, 394, 5, }, + { 364, 421, 5, }, + { 364, 484, 5, }, + { 365, 395, 5, }, + { 365, 422, 5, }, + { 365, 485, 5, }, + { 366, 396, 5, }, + { 366, 423, 5, }, + { 366, 486, 5, }, + { 367, 397, 5, }, + { 367, 424, 5, }, + { 367, 487, 5, }, + { 368, 398, 5, }, + { 368, 425, 5, }, + { 368, 488, 5, }, + { 369, 399, 5, }, + { 369, 426, 5, }, + { 369, 489, 5, }, + { 370, 400, 6, }, + { 370, 427, 6, }, + { 370, 490, 6, }, + { 371, 401, 6, }, + { 371, 428, 6, }, + { 371, 491, 6, }, + { 372, 402, 6, }, + { 372, 429, 6, }, + { 372, 492, 6, }, + { 373, 403, 6, }, + { 373, 430, 6, }, + { 373, 493, 6, }, + { 374, 404, 6, }, + { 374, 431, 6, }, + { 374, 494, 6, }, + { 375, 405, 6, }, + { 375, 432, 6, }, + { 375, 495, 6, }, + { 376, 406, 6, }, + { 376, 433, 6, }, + { 376, 496, 6, }, + { 377, 407, 6, }, + { 377, 434, 6, }, + { 377, 497, 6, }, + { 378, 408, 6, }, + { 378, 435, 6, }, + { 378, 498, 6, }, + { 379, 409, 6, }, + { 379, 436, 6, }, + { 379, 499, 6, }, + { 380, 410, 6, }, + { 380, 437, 6, }, + { 380, 500, 6, }, + { 381, 411, 6, }, + { 381, 438, 6, }, + { 381, 501, 6, }, + { 382, 412, 6, }, + { 382, 439, 6, }, + { 382, 502, 6, }, + { 383, 413, 6, }, + { 383, 440, 6, }, + { 383, 503, 6, }, + { 384, 414, 6, }, + { 384, 441, 6, }, + { 384, 504, 6, }, + { 385, 415, 6, }, + { 385, 442, 6, }, + { 385, 505, 6, }, + { 386, 416, 6, }, + { 386, 443, 6, }, + { 386, 506, 6, }, + { 387, 417, 6, }, + { 387, 444, 6, }, + { 387, 507, 6, }, + { 388, 418, 6, }, + { 388, 445, 6, }, + { 388, 508, 6, }, + { 389, 419, 6, }, + { 389, 446, 6, }, + { 389, 509, 6, }, + { 390, 453, 6, }, + { 390, 510, 6, }, + { 391, 454, 6, }, + { 391, 511, 6, }, + { 392, 455, 6, }, + { 392, 512, 6, }, + { 393, 456, 6, }, + { 393, 513, 6, }, + { 394, 457, 6, }, + { 394, 514, 6, }, + { 395, 458, 6, }, + { 395, 515, 6, }, + { 396, 459, 6, }, + { 396, 516, 6, }, + { 397, 460, 6, }, + { 397, 517, 6, }, + { 398, 461, 6, }, + { 398, 518, 6, }, + { 399, 462, 6, }, + { 399, 519, 6, }, + { 400, 463, 6, }, + { 400, 520, 6, }, + { 401, 464, 6, }, + { 401, 521, 6, }, + { 402, 465, 6, }, + { 402, 522, 6, }, + { 403, 466, 6, }, + { 403, 523, 6, }, + { 404, 467, 6, }, + { 404, 524, 6, }, + { 405, 468, 6, }, + { 405, 525, 6, }, + { 406, 469, 6, }, + { 406, 526, 6, }, + { 407, 470, 6, }, + { 407, 527, 6, }, + { 408, 471, 6, }, + { 408, 528, 6, }, + { 409, 472, 6, }, + { 409, 529, 6, }, + { 410, 473, 6, }, + { 410, 530, 6, }, + { 411, 474, 6, }, + { 411, 531, 6, }, + { 412, 475, 6, }, + { 412, 532, 6, }, + { 413, 476, 6, }, + { 413, 533, 6, }, + { 414, 477, 6, }, + { 414, 534, 6, }, + { 415, 478, 6, }, + { 415, 535, 6, }, + { 416, 479, 6, }, + { 416, 536, 6, }, + { 417, 450, 6, }, + { 417, 537, 6, }, + { 418, 451, 6, }, + { 418, 538, 6, }, + { 419, 452, 6, }, + { 419, 539, 6, }, + { 420, 480, 6, }, + { 421, 481, 6, }, + { 422, 482, 6, }, + { 423, 483, 6, }, + { 424, 484, 6, }, + { 425, 485, 6, }, + { 426, 486, 6, }, + { 427, 487, 6, }, + { 428, 488, 6, }, + { 429, 489, 6, }, + { 430, 490, 6, }, + { 431, 491, 6, }, + { 432, 492, 6, }, + { 433, 493, 6, }, + { 434, 494, 6, }, + { 435, 495, 6, }, + { 436, 496, 6, }, + { 437, 497, 6, }, + { 438, 498, 6, }, + { 439, 499, 6, }, + { 440, 500, 6, }, + { 441, 501, 6, }, + { 442, 502, 6, }, + { 443, 503, 6, }, + { 444, 504, 6, }, + { 445, 505, 6, }, + { 446, 506, 6, }, + { 447, 507, 6, }, + { 448, 508, 6, }, + { 449, 509, 6, }, + { 450, 510, 7, }, + { 451, 511, 7, }, + { 452, 512, 7, }, + { 453, 513, 7, }, + { 454, 514, 7, }, + { 455, 515, 7, }, + { 456, 516, 7, }, + { 457, 517, 7, }, + { 458, 518, 7, }, + { 459, 519, 7, }, + { 460, 520, 7, }, + { 461, 521, 7, }, + { 462, 522, 7, }, + { 463, 523, 7, }, + { 464, 524, 7, }, + { 465, 525, 7, }, + { 466, 526, 7, }, + { 467, 527, 7, }, + { 468, 528, 7, }, + { 469, 529, 7, }, + { 470, 530, 7, }, + { 471, 531, 7, }, + { 472, 532, 7, }, + { 473, 533, 7, }, + { 474, 534, 7, }, + { 475, 535, 7, }, + { 476, 536, 7, }, + { 477, 537, 7, }, + { 478, 538, 7, }, + { 479, 539, 7, }, + { 480, 513, 7, }, + { 480, 597, 7, }, + { 481, 514, 7, }, + { 481, 598, 7, }, + { 482, 515, 7, }, + { 482, 599, 7, }, + { 483, 516, 7, }, + { 483, 570, 7, }, + { 484, 517, 7, }, + { 484, 571, 7, }, + { 485, 518, 7, }, + { 485, 572, 7, }, + { 486, 519, 7, }, + { 486, 573, 7, }, + { 487, 520, 7, }, + { 487, 574, 7, }, + { 488, 521, 7, }, + { 488, 575, 7, }, + { 489, 522, 7, }, + { 489, 576, 7, }, + { 490, 523, 7, }, + { 490, 577, 7, }, + { 491, 524, 7, }, + { 491, 578, 7, }, + { 492, 525, 7, }, + { 492, 579, 7, }, + { 493, 526, 7, }, + { 493, 580, 7, }, + { 494, 527, 7, }, + { 494, 581, 7, }, + { 495, 528, 7, }, + { 495, 582, 7, }, + { 496, 529, 7, }, + { 496, 583, 7, }, + { 497, 530, 7, }, + { 497, 584, 7, }, + { 498, 531, 7, }, + { 498, 585, 7, }, + { 499, 532, 7, }, + { 499, 586, 7, }, + { 500, 533, 7, }, + { 500, 587, 7, }, + { 501, 534, 7, }, + { 501, 588, 7, }, + { 502, 535, 7, }, + { 502, 589, 7, }, + { 503, 536, 7, }, + { 503, 590, 7, }, + { 504, 537, 7, }, + { 504, 591, 7, }, + { 505, 538, 7, }, + { 505, 592, 7, }, + { 506, 539, 7, }, + { 506, 593, 7, }, + { 507, 510, 7, }, + { 507, 594, 7, }, + { 508, 511, 7, }, + { 508, 595, 7, }, + { 509, 512, 7, }, + { 509, 596, 7, }, + { 510, 542, 7, }, + { 511, 543, 7, }, + { 512, 544, 7, }, + { 513, 545, 7, }, + { 514, 546, 7, }, + { 515, 547, 7, }, + { 516, 548, 7, }, + { 517, 549, 7, }, + { 518, 550, 7, }, + { 519, 551, 7, }, + { 520, 552, 7, }, + { 521, 553, 7, }, + { 522, 554, 7, }, + { 523, 555, 7, }, + { 524, 556, 7, }, + { 525, 557, 7, }, + { 526, 558, 7, }, + { 527, 559, 7, }, + { 528, 560, 7, }, + { 529, 561, 7, }, + { 530, 562, 7, }, + { 531, 563, 7, }, + { 532, 564, 7, }, + { 533, 565, 7, }, + { 534, 566, 7, }, + { 535, 567, 7, }, + { 536, 568, 7, }, + { 537, 569, 7, }, + { 538, 540, 7, }, + { 539, 541, 7, }, + { 540, 570, 7, }, + { 541, 571, 7, }, + { 542, 572, 7, }, + { 543, 573, 7, }, + { 544, 574, 7, }, + { 545, 575, 7, }, + { 546, 576, 7, }, + { 547, 577, 7, }, + { 548, 578, 7, }, + { 549, 579, 7, }, + { 550, 580, 7, }, + { 551, 581, 7, }, + { 552, 582, 7, }, + { 553, 583, 7, }, + { 554, 584, 7, }, + { 555, 585, 7, }, + { 556, 586, 7, }, + { 557, 587, 7, }, + { 558, 588, 7, }, + { 559, 589, 7, }, + { 560, 590, 7, }, + { 561, 591, 7, }, + { 562, 592, 7, }, + { 563, 593, 7, }, + { 564, 594, 7, }, + { 565, 595, 7, }, + { 566, 596, 7, }, + { 567, 597, 7, }, + { 568, 598, 7, }, + { 569, 599, 7, }, +}; + + +static const char *hyperball_defaults[] = +{ + "*observer-z: 3", + "*delay: 20000", + "*xy: 3", + "*xz: 5", + "*yw: 10", + "*yz: 0", + "*xw: 0", + "*zw: 0", + ".background: black", + ".foreground: white", + "*fpsSolid: true", + "*color00:#FF66BE", + "*color10:#FFA300", + "*color20:#BEDC00", + "*color30:#12FB00", + "*color40:#00F9BE", + "*color50:#12D5FF", + "*color60:#BE9AFF", + "*color70:#FF5FFF", + "*color01:#FF5BAA", + "*color11:#F09200", + "*color21:#AAC500", + "*color31:#10E100", + "*color41:#00DFAA", + "*color51:#10BFFF", + "*color61:#AA8AFF", + "*color71:#F055FF", + "*color02:#EE529A", + "*color12:#D98400", + "*color22:#9AB200", + "*color32:#0ECB00", + "*color42:#00C99A", + "*color52:#0EADE7", + "*color62:#9A7DFF", + "*color72:#D94DE7", + "*color03:#DA4B8C", + "*color13:#C67900", + "*color23:#8CA300", + "*color33:#0DBA00", + "*color43:#00B88C", + "*color53:#0D9ED3", + "*color63:#8C72EA", + "*color73:#C646D3", + "*color04:#C84581", + "*color14:#B66F00", + "*color24:#819600", + "*color34:#0CAB00", + "*color44:#00A981", + "*color54:#0C91C2", + "*color64:#8169D7", + "*color74:#B641C2", + "*color05:#B94078", + "*color15:#A96700", + "*color25:#788B00", + "*color35:#0B9E00", + "*color45:#009D78", + "*color55:#0B86B3", + "*color65:#7861C7", + "*color75:#A93CB3", + "*color06:#AC3C6F", + "*color16:#9D6000", + "*color26:#6F8100", + "*color36:#0A9300", + "*color46:#00926F", + "*color56:#0A7DA7", + "*color66:#6F5AB9", + "*color76:#9D38A7", + "*color07:#A13868", + "*color17:#935900", + "*color27:#687900", + "*color37:#0A8A00", + "*color47:#008868", + "*color57:#0A759C", + "*color67:#6854AD", + "*color77:#93349C", + 0, +}; + +static XrmOptionDescRec hyperball_options [] = +{ + { "-observer-z", ".observer-z", XrmoptionSepArg, 0 }, + { "-delay", ".delay", XrmoptionSepArg, 0 }, + { "-xw", ".xw", XrmoptionSepArg, 0 }, + { "-xy", ".xy", XrmoptionSepArg, 0 }, + { "-xz", ".xz", XrmoptionSepArg, 0 }, + { "-yw", ".yw", XrmoptionSepArg, 0 }, + { "-yz", ".yz", XrmoptionSepArg, 0 }, + { "-zw", ".zw", XrmoptionSepArg, 0 }, + { 0, 0, 0, 0 }, +}; + +XSCREENSAVER_MODULE ("HyperBall", hyperball) diff --git a/hacks/hyperball.man b/hacks/hyperball.man new file mode 100644 index 00000000..241ff689 --- /dev/null +++ b/hacks/hyperball.man @@ -0,0 +1,88 @@ +.TH XScreenSaver 1 "" "X Version 11" +.SH NAME +hyperball - 2d projection of a 4d object +.SH SYNOPSIS +.B hyperball +[\-display \fIhost:display.screen\fP] +[\-foreground \fIcolor\fP] +[\-background \fIcolor\fP] +[\-xy \fIfloat\fP] +[\-xz \fIfloat\fP] +[\-yz \fIfloat\fP] +[\-xw \fIfloat\fP] +[\-yw \fIfloat\fP] +[\-zw \fIfloat\fP] +[\-delay \fIusecs\fP] +[\-window] +[\-root] +[\-mono] +[\-install] +[\-visual \fIvisual\fP] +[\-fps] +.SH DESCRIPTION +The \fIhyperball\fP program displays a wireframe projection of a hyperball +which is rotating at user-specified rates around any or all of its four axes. +.SH OPTIONS +.I hyperball +accepts the following options: +.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 \-mono +If on a color display, pretend we're on a monochrome display. +.TP 8 +.B \-install +Install a private colormap for the window. +.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 \-delay \fImicroseconds\fP +How much of a delay should be introduced between steps of the animation. +Default 20000, or about 0.02 seconds. +.TP 8 +.B \-xw \fIfloat\fP +.TP 8 +.B \-xy \fIfloat\fP +.TP 8 +.B \-xz \fIfloat\fP +.TP 8 +.B \-yw \fIfloat\fP +.TP 8 +.B \-yz \fIfloat\fP +.TP 8 +.B \-zw \fIfloat\fP +The amount that the ball should be rotated around the specified axis at +each frame of the animation, expressed in 0.001 radians. These should be small +floating-point values (less than 50 works best.) Default: xy=3, +xz=5, yw=10. +.TP 8 +.B \-fps +Display the current frame rate and CPU load. +.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 2000 by Joe Keane. 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 +Joe Keane diff --git a/hacks/hypercube.c b/hacks/hypercube.c new file mode 100644 index 00000000..ab131b19 --- /dev/null +++ b/hacks/hypercube.c @@ -0,0 +1,571 @@ +/* xscreensaver, Copyright (c) 1992-2008 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. + * + * This code derived from TI Explorer Lisp code by Joe Keane, Fritz Mueller, + * and Jamie Zawinski. + */ + +#include +#include "screenhack.h" + +#define POINT_COUNT 16 +#define LINE_COUNT 32 + +#define ANGLE_SCALE 0.001 + +struct line_info +{ + char li_ip; + char li_iq; + char li_color; + char li_pad; +}; + +struct point_state +{ + short old_x, old_y; + short new_x, new_y; +}; + +struct hyper_state +{ + char hs_stop; + char hs_icon; + char hs_resize; + char hs_redraw; + Display *hs_display; + Window hs_window; + float hs_two_observer_z; + float hs_offset_x; + float hs_offset_y; + float hs_unit_scale; + int hs_delay; + GC hs_color_gcs[8]; + GC black_gc; +#if 0 + double hs_angle_xy; + double hs_angle_xz; + double hs_angle_yz; + double hs_angle_xw; + double hs_angle_yw; + double hs_angle_zw; +#endif + double hs_cos_xy, hs_sin_xy; + double hs_cos_xz, hs_sin_xz; + double hs_cos_yz, hs_sin_yz; + double hs_cos_xw, hs_sin_xw; + double hs_cos_yw, hs_sin_yw; + double hs_cos_zw, hs_sin_zw; + double hs_ref_ax, hs_ref_ay, hs_ref_az, hs_ref_aw; + double hs_ref_bx, hs_ref_by, hs_ref_bz, hs_ref_bw; + double hs_ref_cx, hs_ref_cy, hs_ref_cz, hs_ref_cw; + double hs_ref_dx, hs_ref_dy, hs_ref_dz, hs_ref_dw; + struct point_state hs_points[POINT_COUNT]; + int roted; +}; + +static const struct line_info line_table[LINE_COUNT]; + +static const char *hypercube_defaults[] = +{ + "*observer-z: 3.0", + "*delay: 10000", + "*xy: 3", + "*xz: 5", + "*yw: 10", + "*yz: 0", + "*xw: 0", + "*zw: 0", + ".background: black", + ".foreground: white", + "*fpsSolid: true", + "*color0: magenta", + "*color3: #FF0093", + "*color1: yellow", + "*color2: #FF9300", + "*color4: green", + "*color7: #00FFD0", + "*color5: #8080FF", + "*color6: #00D0FF", + + 0 +}; + +static XrmOptionDescRec hypercube_options [] = +{ + { "-color0", ".color0", XrmoptionSepArg, 0 }, + { "-color1", ".color1", XrmoptionSepArg, 0 }, + { "-color2", ".color2", XrmoptionSepArg, 0 }, + { "-color3", ".color3", XrmoptionSepArg, 0 }, + { "-color4", ".color4", XrmoptionSepArg, 0 }, + { "-color5", ".color5", XrmoptionSepArg, 0 }, + { "-color6", ".color6", XrmoptionSepArg, 0 }, + { "-color7", ".color7", XrmoptionSepArg, 0 }, + + { "-xw", ".xw", XrmoptionSepArg, 0 }, + { "-xy", ".xy", XrmoptionSepArg, 0 }, + { "-xz", ".xz", XrmoptionSepArg, 0 }, + { "-yw", ".yw", XrmoptionSepArg, 0 }, + { "-yz", ".yz", XrmoptionSepArg, 0 }, + { "-zw", ".zw", XrmoptionSepArg, 0 }, + + { "-observer-z", ".observer-z", XrmoptionSepArg, 0 }, + { "-delay", ".delay", XrmoptionSepArg, 0 }, + { 0, 0, 0, 0 } +}; + + +static void set_sizes (struct hyper_state *hs, int width, int height); + +static void * +hypercube_init (Display *dpy, Window win) +{ + XGCValues gcv; + Colormap cmap; + unsigned long bg_pixel; + int delay; + float observer_z; + + struct hyper_state *hs = (struct hyper_state *) calloc (1, sizeof(*hs)); + hs->hs_display = dpy; + hs->hs_window = win; + + observer_z = get_float_resource (dpy, "observer-z", "Float"); + if (observer_z < 1.125) + observer_z = 1.125; + /* hs->hs_observer_z = observer_z; */ + hs->hs_two_observer_z = 2.0 * observer_z; + + { + XWindowAttributes wa; + XGetWindowAttributes (dpy, win, &wa); + cmap = wa.colormap; + set_sizes (hs, wa.width, wa.height); + } + + delay = get_integer_resource (dpy, "delay", "Integer"); + hs->hs_delay = delay; + + bg_pixel = get_pixel_resource (dpy, cmap, "background", "Background"); + + if (mono_p) + { + GC black_gc; + unsigned long fg_pixel; + GC white_gc; + + gcv.function = GXcopy; + gcv.foreground = bg_pixel; + black_gc = XCreateGC (dpy, win, GCForeground|GCFunction, &gcv); + fg_pixel = get_pixel_resource (dpy, cmap, "foreground", "Foreground"); + gcv.foreground = fg_pixel ^ bg_pixel; + white_gc = XCreateGC (dpy, win, GCForeground|GCFunction, &gcv); + hs->hs_color_gcs[0] = black_gc; + hs->hs_color_gcs[1] = white_gc; + } + else + { + int col; + + gcv.function = GXcopy; + + gcv.foreground = get_pixel_resource (dpy, cmap, + "background", "Background"); + hs->black_gc = XCreateGC (dpy, win, GCForeground|GCFunction, &gcv); + + for (col = 0; col < 8; col++) + { + char buffer[16]; + unsigned long fg_pixel; + GC color_gc; + + sprintf (buffer, "color%d", col); + fg_pixel = get_pixel_resource (dpy, cmap, buffer, "Foreground"); + gcv.foreground = fg_pixel; + color_gc = XCreateGC (dpy, win, GCForeground|GCFunction, &gcv); + hs->hs_color_gcs[col] = color_gc; + } + } + + hs->hs_ref_ax = 1.0, hs->hs_ref_ay = 0.0, hs->hs_ref_az = 0.0, hs->hs_ref_aw = 0.0; + hs->hs_ref_bx = 0.0, hs->hs_ref_by = 1.0, hs->hs_ref_bz = 0.0, hs->hs_ref_bw = 0.0; + hs->hs_ref_cx = 0.0, hs->hs_ref_cy = 0.0, hs->hs_ref_cz = 1.0, hs->hs_ref_cw = 0.0; + hs->hs_ref_dx = 0.0, hs->hs_ref_dy = 0.0, hs->hs_ref_dz = 0.0, hs->hs_ref_dw = 1.0; + + { + double xy; + double xz; + double yz; + double xw; + double yw; + double zw; + double cos_xy, sin_xy; + double cos_xz, sin_xz; + double cos_yz, sin_yz; + double cos_xw, sin_xw; + double cos_yw, sin_yw; + double cos_zw, sin_zw; + + xy = get_float_resource (dpy, "xy", "Float") * ANGLE_SCALE; + xz = get_float_resource (dpy, "xz", "Float") * ANGLE_SCALE; + yz = get_float_resource (dpy, "yz", "Float") * ANGLE_SCALE; + xw = get_float_resource (dpy, "xw", "Float") * ANGLE_SCALE; + yw = get_float_resource (dpy, "yw", "Float") * ANGLE_SCALE; + zw = get_float_resource (dpy, "zw", "Float") * ANGLE_SCALE; + + cos_xy = cos (xy), sin_xy = sin (xy); + hs->hs_cos_xy = cos_xy, hs->hs_sin_xy = sin_xy; + cos_xz = cos (xz), sin_xz = sin (xz); + hs->hs_cos_xz = cos_xz, hs->hs_sin_xz = sin_xz; + cos_yz = cos (yz), sin_yz = sin (yz); + hs->hs_cos_yz = cos_yz, hs->hs_sin_yz = sin_yz; + cos_xw = cos (xw), sin_xw = sin (xw); + hs->hs_cos_xw = cos_xw, hs->hs_sin_xw = sin_xw; + cos_yw = cos (yw), sin_yw = sin (yw); + hs->hs_cos_yw = cos_yw, hs->hs_sin_yw = sin_yw; + cos_zw = cos (zw), sin_zw = sin (zw); + hs->hs_cos_zw = cos_zw, hs->hs_sin_zw = sin_zw; + } + + return hs; +} + + +static unsigned long +hypercube_draw (Display *dpy, Window window, void *closure) +{ + struct hyper_state *hs = (struct hyper_state *) closure; + int this_delay = hs->hs_delay; + +#ifdef HAVE_COCOA /* Don't second-guess Quartz's double-buffering */ + XClearWindow (dpy, window); +#endif + + { + int icon; + int resize; + char moved[POINT_COUNT]; + int redraw; + int stop; + int delay; + + icon = hs->hs_icon; + resize = hs->hs_resize; + if (icon || !(hs->roted | resize)) + goto skip1; + + { + float observer_z; + float unit_scale; + float offset_x; + float offset_y; + double az, bz, cz, dz; + double sum_z; + double ax, bx, cx, dx; + double sum_x; + double ay, by, cy, dy; + double sum_y; + struct point_state *ps; + int old_x; + int old_y; + double mul; + double xf; + double yf; + int new_x; + int new_y; + int mov; + + +#define compute(as,bs,cs,ds,i) \ + az = hs->hs_ref_az; bz = hs->hs_ref_bz; cz = hs->hs_ref_cz; dz = hs->hs_ref_dz; \ + ax = hs->hs_ref_ax; bx = hs->hs_ref_bx; cx = hs->hs_ref_cx; dx = hs->hs_ref_dx; \ + ay = hs->hs_ref_ay; by = hs->hs_ref_by; cy = hs->hs_ref_cy; dy = hs->hs_ref_dy; \ + sum_z = as az bs bz cs cz ds dz; \ + observer_z = hs->hs_two_observer_z; \ + unit_scale = hs->hs_unit_scale; \ + sum_x = as ax bs bx cs cx ds dx; \ + sum_y = as ay bs by cs cy ds dy; \ + ps = &hs->hs_points[i]; \ + mul = unit_scale / (observer_z - sum_z); \ + offset_x = hs->hs_offset_x; \ + offset_y = hs->hs_offset_y; \ + old_x = ps->new_x; \ + old_y = ps->new_y; \ + xf = sum_x * mul + offset_x; \ + yf = sum_y * mul + offset_y; \ + new_x = (int)rint(xf); \ + new_y = (int)rint(yf); \ + ps->old_x = old_x; \ + ps->old_y = old_y; \ + ps->new_x = new_x; \ + ps->new_y = new_y; \ + mov = old_x != new_x || old_y != new_y; \ + moved[i] = mov; + + compute (-, -, -, -, 0); + compute (-, -, -, +, 1); + compute (-, -, +, -, 2); + compute (-, -, +, +, 3); + compute (-, +, -, -, 4); + compute (-, +, -, +, 5); + compute (-, +, +, -, 6); + compute (-, +, +, +, 7); + compute (+, -, -, -, 8); + compute (+, -, -, +, 9); + compute (+, -, +, -, 10); + compute (+, -, +, +, 11); + compute (+, +, -, -, 12); + compute (+, +, -, +, 13); + compute (+, +, +, -, 14); + compute (+, +, +, +, 15); + } + + skip1: + icon = hs->hs_icon; + redraw = hs->hs_redraw; + if (icon || !(hs->roted | redraw)) + goto skip2; + + { + int lc; + const struct line_info *lip; + int mono; + Window win; + + lc = LINE_COUNT; + lip = &line_table[0]; + mono = mono_p; + win = hs->hs_window; + + while (--lc >= 0) + { + int ip; + int iq; + int col; + struct point_state *sp; + struct point_state *sq; + int mov_p; + int mov_q; + GC erase_gc; + GC draw_gc; + int p_x; + int p_y; + int q_x; + int q_y; + + ip = lip->li_ip; + iq = lip->li_iq; + col = lip->li_color; + lip++; + mov_p = moved[ip]; + mov_q = moved[iq]; + if (!(redraw | mov_p | mov_q)) + continue; + + sp = &hs->hs_points[ip]; + sq = &hs->hs_points[iq]; + + if (mono) + { + erase_gc = hs->hs_color_gcs[0]; + draw_gc = hs->hs_color_gcs[1]; + } + else + { + erase_gc = hs->black_gc; + draw_gc = hs->hs_color_gcs[col]; + } + + if (!redraw) + { + p_x = sp->old_x; + p_y = sp->old_y; + q_x = sq->old_x; + q_y = sq->old_y; + XDrawLine (dpy, win, erase_gc, p_x, p_y, q_x, q_y); + } + + p_x = sp->new_x; + p_y = sp->new_y; + q_x = sq->new_x; + q_y = sq->new_y; + XDrawLine (dpy, win, draw_gc, p_x, p_y, q_x, q_y); + } + } + + skip2: + stop = hs->hs_stop; + hs->roted = 0; + if (stop) + goto skip3; + + hs->roted = 1; + + { + double cos_a; + double sin_a; + double old_u; + double old_v; + double new_u; + double new_v; + + /* If you get error messages about the following forms, and you think you're + using an ANSI C conforming compiler, then you're mistaken. Possibly you're + mixing an ANSI compiler with a non-ANSI preprocessor, or vice versa. + Regardless, your system is broken; it's not a bug in this program. + */ +#if defined(__STDC__) || defined(__ANSI_CPP__) + +#define rotate(name,dim0,dim1) \ + old_u = hs->hs_ref_##name##dim0; \ + old_v = hs->hs_ref_##name##dim1; \ + new_u = old_u * cos_a + old_v * sin_a; \ + new_v = old_v * cos_a - old_u * sin_a; \ + hs->hs_ref_##name##dim0 = new_u; \ + hs->hs_ref_##name##dim1 = new_v; + +#define rotates(dim0,dim1) \ + if (hs->hs_sin_##dim0##dim1 != 0) { \ + cos_a = hs->hs_cos_##dim0##dim1; \ + sin_a = hs->hs_sin_##dim0##dim1; \ + rotate(a,dim0,dim1); \ + rotate(b,dim0,dim1); \ + rotate(c,dim0,dim1); \ + rotate(d,dim0,dim1); \ + } + +#else /* !__STDC__, courtesy of Andreas Luik */ + +#define rotate(name,dim0,dim1) \ + old_u = hs->hs_ref_/**/name/**/dim0; \ + old_v = hs->hs_ref_/**/name/**/dim1; \ + new_u = old_u * cos_a + old_v * sin_a; \ + new_v = old_v * cos_a - old_u * sin_a; \ + hs->hs_ref_/**/name/**/dim0 = new_u; \ + hs->hs_ref_/**/name/**/dim1 = new_v; + +#define rotates(dim0,dim1) \ + if (hs->hs_sin_/**/dim0/**/dim1 != 0) { \ + cos_a = hs->hs_cos_/**/dim0/**/dim1; \ + sin_a = hs->hs_sin_/**/dim0/**/dim1; \ + rotate(a,dim0,dim1); \ + rotate(b,dim0,dim1); \ + rotate(c,dim0,dim1); \ + rotate(d,dim0,dim1); \ + } + +#endif /* !__STDC__ */ + + rotates (x,y); + rotates (x,z); + rotates (y,z); + rotates (x,w); + rotates (y,w); + rotates (z,w); + } + + skip3: + /* stop = hs->hs_stop; */ + delay = hs->hs_delay; + if (stop && this_delay < 10000) + this_delay = 10000; + } + return this_delay; +} + + +static Bool +hypercube_event (Display *dpy, Window window, void *closure, XEvent *e) +{ + struct hyper_state *hs = (struct hyper_state *) closure; + if (e->type == ButtonPress && e->xbutton.button == 2) + { + hs->hs_stop = !hs->hs_stop; + return True; + } + return False; +} + +static void +hypercube_reshape (Display *dpy, Window window, void *closure, + unsigned int w, unsigned int h) +{ + struct hyper_state *hs = (struct hyper_state *) closure; + set_sizes (hs, w, h); + XClearWindow (dpy, window); +} + + +static void +set_sizes (struct hyper_state *hs, int width, int height) +{ + double observer_z; + int min_dim; + double var; + double offset_x; + double offset_y; + double unit_scale; + + observer_z = 0.5 * hs->hs_two_observer_z; + min_dim = width < height ? width : height; + var = sqrt(observer_z * observer_z - 1.0); + offset_x = 0.5 * (double)(width - 1); + offset_y = 0.5 * (double)(height - 1); + unit_scale = 0.4 * min_dim * var; + hs->hs_offset_x = (float)offset_x; + hs->hs_offset_y = (float)offset_y; + hs->hs_unit_scale = (float)unit_scale; +} + + +/* data */ + +static const struct line_info line_table[LINE_COUNT] = +{ + { 0, 1, 0, }, + { 0, 2, 0, }, + { 1, 3, 0, }, + { 2, 3, 0, }, + { 4, 5, 1, }, + { 4, 6, 1, }, + { 5, 7, 1, }, + { 6, 7, 1, }, + { 0, 4, 4, }, + { 0, 8, 4, }, + { 4, 12, 4, }, + { 8, 12, 4, }, + { 1, 5, 5, }, + { 1, 9, 5, }, + { 5, 13, 5, }, + { 9, 13, 5, }, + { 2, 6, 6, }, + { 2, 10, 6, }, + { 6, 14, 6, }, + { 10, 14, 6, }, + { 3, 7, 7, }, + { 3, 11, 7, }, + { 7, 15, 7, }, + { 11, 15, 7, }, + { 8, 9, 2, }, + { 8, 10, 2, }, + { 9, 11, 2, }, + { 10, 11, 2, }, + { 12, 13, 3, }, + { 12, 14, 3, }, + { 13, 15, 3, }, + { 14, 15, 3, }, +}; + +static void +hypercube_free (Display *dpy, Window window, void *closure) +{ +} + +XSCREENSAVER_MODULE ("HyperCube", hypercube) diff --git a/hacks/hypercube.man b/hacks/hypercube.man new file mode 100644 index 00000000..25943709 --- /dev/null +++ b/hacks/hypercube.man @@ -0,0 +1,97 @@ +.TH XScreenSaver 1 "6-dec-92" "X Version 11" +.SH NAME +hypercube - 2d projection of a 4d object +.SH SYNOPSIS +.B hypercube +[\-display \fIhost:display.screen\fP] [\-foreground \fIcolor\fP] [\-background \fIcolor\fP] [\-color[0-7] \fIcolor\fP] [\-xy \fIfloat\fP] [\-xz \fIfloat\fP] [\-yz \fIfloat\fP] [\-xw \fIfloat\fP] [\-yw \fIfloat\fP] [\-zw \fIfloat\fP] [\-observer-z \fIint\fP] [\-delay \fIusecs\fP] [\-window] [\-root] [\-mono] [\-install] [\-visual \fIvisual\fP] +[\-fps] +.SH DESCRIPTION +The \fIhypercube\fP program displays a wireframe projection of a hypercube +which is rotating at user-specified rates around any or all of its four axes. +.SH OPTIONS +.I hypercube +accepts the following options: +.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 \-mono +If on a color display, pretend we're on a monochrome display. +.TP 8 +.B \-install +Install a private colormap for the window. +.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 \-delay \fImicroseconds\fP +How much of a delay should be introduced between steps of the animation. +Default 100000, or about 1/10th second. +.TP 8 +.B \-observer-z \fIint\fP +How far away the observer is from the center of the cube (the cube is one +unit per side.) Default 5. +.TP 8 +.B \-color0 \fIcolor\fP +.TP 8 +.B \-color1 \fIcolor\fP +.TP 8 +.B \-color2 \fIcolor\fP +.TP 8 +.B \-color3 \fIcolor\fP +.TP 8 +.B \-color4 \fIcolor\fP +.TP 8 +.B \-color5 \fIcolor\fP +.TP 8 +.B \-color6 \fIcolor\fP +.TP 8 +.B \-color7 \fIcolor\fP +The colors used to draw the line segments bordering the eight faces of +the cube. Some of the faces have only two of their border-lines drawn in +the specified color, and some have all four. +.TP 8 +.B \-xw \fIfloat\fP +.TP 8 +.B \-xy \fIfloat\fP +.TP 8 +.B \-xz \fIfloat\fP +.TP 8 +.B \-yw \fIfloat\fP +.TP 8 +.B \-yz \fIfloat\fP +.TP 8 +.B \-zw \fIfloat\fP +The amount that the cube should be rotated around the specified axis at +each frame of the animation, expressed in 0.001 radians. These should be small +floating-point values (less than 50 works best.) Default: xy=3, +xz=5, yw=10. +.TP 8 +.B \-fps +Display the current frame rate and CPU load. +.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 1992 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 , 6-dec-92. diff --git a/hacks/ifs.c b/hacks/ifs.c new file mode 100644 index 00000000..099b0d1c --- /dev/null +++ b/hacks/ifs.c @@ -0,0 +1,532 @@ +/* Copyright © Chris Le Sueur and Robby Griffin, 2005-2006 + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be included +in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR +OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +OTHER DEALINGS IN THE SOFTWARE. + +Ultimate thanks go to Massimino Pascal, who created the original +xscreensaver hack, and inspired me with it's swirly goodness. This +version adds things like variable quality, number of functions and also +a groovier colouring mode. + +This version by Chris Le Sueur , Feb 2005 +Many improvements by Robby Griffin , Mar 2006 +Multi-coloured mode added by Jack Grahl , Jan 2007 +*/ + +#include +#include +#include +#include +#include + +#include "screenhack.h" + +#undef countof +#define countof(x) (sizeof((x)) / sizeof(*(x))) + +typedef struct { + float r, s, tx, ty; /* Rotation, Scale, Translation X & Y */ + float ro, rt, rc; /* Old Rotation, Rotation Target, Rotation Counter */ + float so, st, sc; /* Old Scale, Scale Target, Scale Counter */ + float sa, txa, tya; /* Scale change, Translation change */ + + int ua, ub, utx; /* Precomputed combined r,s,t values */ + int uc, ud, uty; /* Precomputed combined r,s,t values */ + +} Lens; + +struct state { + Display *dpy; + Window window; + GC gc; + Drawable backbuffer; + XColor *colours; + int ncolours; + int ccolour; + int blackColor, whiteColor; + + int width, widthb, height; + int width8, height8; + unsigned int *board; + XPoint pointbuf[1000]; + int npoints; + int xmin, xmax, ymin, ymax; + int x, y; + + int delay; + + int lensnum; + Lens *lenses; + int length; + int mode; + Bool recurse; + Bool multi; + Bool translate, scale, rotate; +}; + +#define getdot(x,y) (st->board[((y)*st->widthb)+((x)>>5)] & (1<<((x) & 31))) +#define setdot(x,y) (st->board[((y)*st->widthb)+((x)>>5)] |= (1<<((x) & 31))) + +static float +myrandom(float up) +{ + return (((float)random() / RAND_MAX) * up); +} + +static const char *ifs_defaults [] = { + ".background: Black", + "*lensnum: 3", + "*fpsSolid: true", + "*length: 9", + "*mode: 0", + "*colors: 200", + "*delay: 20000", + "*translate: True", + "*scale: True", + "*rotate: True", + "*recurse: False", + "*multi: True", +# ifdef HAVE_COCOA /* Don't second-guess Quartz's double-buffering */ + "*doubleBuffer: False", +#else + "*doubleBuffer: True", +#endif + 0 +}; + +static XrmOptionDescRec ifs_options [] = { + { "-detail", ".length", XrmoptionSepArg, 0 }, + { "-delay", ".delay", XrmoptionSepArg, 0 }, + { "-mode", ".mode", XrmoptionSepArg, 0 }, + { "-colors", ".colors", XrmoptionSepArg, 0 }, + { "-functions", ".lensnum", XrmoptionSepArg, 0 }, + { "-no-translate", ".translate", XrmoptionNoArg, "False" }, + { "-no-scale", ".scale", XrmoptionNoArg, "False" }, + { "-no-rotate", ".rotate", XrmoptionNoArg, "False" }, + { "-recurse", ".recurse", XrmoptionNoArg, "True" }, + { "-iterate", ".recurse", XrmoptionNoArg, "False" }, + { "-multi", ".multi", XrmoptionNoArg, "True" }, + { "-no-multi", ".multi", XrmoptionNoArg, "False" }, + { "-db", ".doubleBuffer",XrmoptionNoArg, "True" }, + { "-no-db", ".doubleBuffer",XrmoptionNoArg, "False" }, + { 0, 0, 0, 0 } +}; + + +/* Draw all the queued points on the backbuffer */ +static void +drawpoints(struct state *st) +{ + XDrawPoints(st->dpy, st->backbuffer, st->gc, st->pointbuf, st->npoints, + CoordModeOrigin); + st->npoints = 0; +} + +/* Set a point to be drawn, if it hasn't been already. + * Expects coordinates in 256ths of a pixel. */ +static void +sp(struct state *st, int x, int y) +{ + if (x < 0 || x >= st->width8 || y < 0 || y >= st->height8) + return; + + x >>= 8; + y >>= 8; + + if (getdot(x, y)) return; + setdot(x, y); + + if (x < st->xmin) st->xmin = x; + if (x > st->xmax) st->xmax = x; + if (y < st->ymin) st->ymin = y; + if (y > st->ymax) st->ymax = y; + + st->pointbuf[st->npoints].x = x; + st->pointbuf[st->npoints].y = y; + st->npoints++; + + if (st->npoints >= countof(st->pointbuf)) { + drawpoints(st); + } +} + + +/* Precompute integer values for matrix multiplication and vector + * addition. The matrix multiplication will go like this (see iterate()): + * |x2| |ua ub| |x| |utx| + * | | = | | * | | + | | + * |y2| |uc ud| |y| |uty| + * + * There is an extra factor of 2^10 in these values, and an extra factor of + * 2^8 in the coordinates, in order to implement fixed-point arithmetic. + */ +static void +lensmatrix(struct state *st, Lens *l) +{ + l->ua = 1024.0 * l->s * cos(l->r); + l->ub = -1024.0 * l->s * sin(l->r); + l->uc = -l->ub; + l->ud = l->ua; + l->utx = 131072.0 * st->width * (l->s * (sin(l->r) - cos(l->r)) + + l->tx / 16 + 1); + l->uty = -131072.0 * st->height * (l->s * (sin(l->r) + cos(l->r)) + + l->ty / 16 - 1); +} + +static void +CreateLens(struct state *st, + float nr, + float ns, + float nx, + float ny, + Lens *newlens) +{ + newlens->sa = newlens->txa = newlens->tya = 0; + if (st->rotate) { + newlens->r = newlens->ro = newlens->rt = nr; + newlens->rc = 1; + } + else newlens->r = 0; + + if (st->scale) { + newlens->s = newlens->so = newlens->st = ns; + newlens->sc = 1; + } + else newlens->s = 0.5; + + newlens->tx = nx; + newlens->ty = ny; + + lensmatrix(st, newlens); +} + +static void +mutate(struct state *st, Lens *l) +{ + if (st->rotate) { + float factor; + if(l->rc >= 1) { + l->rc = 0; + l->ro = l->rt; + l->rt = myrandom(4) - 2; + } + factor = (sin((-M_PI / 2.0) + M_PI * l->rc) + 1.0) / 2.0; + l->r = l->ro + (l->rt - l->ro) * factor; + l->rc += 0.01; + } + if (st->scale) { + float factor; + if (l->sc >= 1) { + /* Reset counter, obtain new target value */ + l->sc = 0; + l->so = l->st; + l->st = myrandom(2) - 1; + } + factor = (sin((-M_PI / 2.0) + M_PI * l->sc) + 1.0) / 2.0; + /* Take average of old target and new target, using factor to * + * weight. It's computed sinusoidally, resulting in smooth, * + * rhythmic transitions. */ + l->s = l->so + (l->st - l->so) * factor; + l->sc += 0.01; + } + if (st->translate) { + l->txa += myrandom(0.004) - 0.002; + l->tya += myrandom(0.004) - 0.002; + l->tx += l->txa; + l->ty += l->tya; + if (l->tx > 6) l->txa -= 0.004; + if (l->ty > 6) l->tya -= 0.004; + if (l->tx < -6) l->txa += 0.004; + if (l->ty < -6) l->tya += 0.004; + if (l->txa > 0.05 || l->txa < -0.05) l->txa /= 1.7; + if (l->tya > 0.05 || l->tya < -0.05) l->tya /= 1.7; + } + if (st->rotate || st->scale || st->translate) { + lensmatrix(st, l); + } +} + + +#define STEPX(l,x,y) (((l)->ua * (x) + (l)->ub * (y) + (l)->utx) >> 10) +#define STEPY(l,x,y) (((l)->uc * (x) + (l)->ud * (y) + (l)->uty) >> 10) +/*#define STEPY(l,x,y) (((l)->ua * (y) - (l)->ub * (x) + (l)->uty) >> 10)*/ + +/* Calls itself times - with results from each lens/function. * + * After calls to itself, it stops iterating and draws a point. */ +static void +recurse(struct state *st, int x, int y, int length, int p) +{ + int i; + Lens *l; + + if (length == 0) { + if (p == 0) + sp(st, x, y); + else { + l = &st->lenses[p]; + sp(st, STEPX(l, x, y), STEPY(l, x, y)); + } + } + else { + for (i = 0; i < st->lensnum; i++) { + l = &st->lenses[i]; + recurse(st, STEPX(l, x, y), STEPY(l, x, y), length - 1, p); + } + } +} + +/* Performs random lens transformations, drawing a point at each + * iteration after the first 10. + */ +static void +iterate(struct state *st, int count, int p) +{ + int i; + Lens *l; + int x = st->x; + int y = st->y; + int tx; + +# define STEP() \ + l = &st->lenses[random() % st->lensnum]; \ + tx = STEPX(l, x, y); \ + y = STEPY(l, x, y); \ + x = tx + + for (i = 0; i < 10; i++) { + STEP(); + } + + for ( ; i < count; i++) { + STEP(); + if (p == 0) + sp(st, x, y); + else + { + l = &st->lenses[p]; + sp(st, STEPX(l, x, y), STEPY(l, x, y)); + } + } + +# undef STEP + + st->x = x; + st->y = y; +} + +/* Come on and iterate, iterate, iterate and sing... * + * Yeah, this function just calls iterate, mutate, * + * and then draws everything. */ +static unsigned long +ifs_draw (Display *dpy, Window window, void *closure) +{ + struct state *st = (struct state *) closure; + int i; + int xmin = st->xmin, xmax = st->xmax, ymin = st->ymin, ymax = st->ymax; + int partcolor, x, y; + + + /* erase whatever was drawn in the previous frame */ + if (xmin <= xmax && ymin <= ymax) { + XSetForeground(st->dpy, st->gc, st->blackColor); + XFillRectangle(st->dpy, st->backbuffer, st->gc, + xmin, ymin, + xmax - xmin + 1, ymax - ymin + 1); + st->xmin = st->width + 1; + st->xmax = st->ymax = -1; + st->ymin = st->height + 1; + } + + st->ccolour++; + st->ccolour %= st->ncolours; + + /* calculate and draw points for this frame */ + x = st->width << 7; + y = st->height << 7; + + if (st->multi) { + for (i = 0; i < st->lensnum; i++) { + partcolor = st->ccolour * (i+1); + partcolor %= st->ncolours; + XSetForeground(st->dpy, st->gc, st->colours[partcolor].pixel); + memset(st->board, 0, st->widthb * st->height * sizeof(*st->board)); + if (st->recurse) + recurse(st, x, y, st->length - 1, i); + else + iterate(st, pow(st->lensnum, st->length - 1), i); + if (st->npoints) + drawpoints(st); + } + } + else { + + XSetForeground(st->dpy, st->gc, st->colours[st->ccolour].pixel); + memset(st->board, 0, st->widthb * st->height * sizeof(*st->board)); + if (st->recurse) + recurse(st, x, y, st->length, 0); + else + iterate(st, pow(st->lensnum, st->length), 0); + if (st->npoints) + drawpoints(st); + } + + /* if we just drew into a buffer, copy the changed area (including + * erased area) to screen */ + if (st->backbuffer != st->window + && ((st->xmin <= st->xmax && st->ymin <= st->ymax) + || (xmin <= xmax && ymin <= ymax))) { + if (st->xmin < xmin) xmin = st->xmin; + if (st->xmax > xmax) xmax = st->xmax; + if (st->ymin < ymin) ymin = st->ymin; + if (st->ymax > ymax) ymax = st->ymax; + XCopyArea(st->dpy, st->backbuffer, st->window, st->gc, + xmin, ymin, + xmax - xmin + 1, ymax - ymin + 1, + xmin, ymin); + } + + for(i = 0; i < st->lensnum; i++) { + mutate(st, &st->lenses[i]); + } + + return st->delay; +} + +static void +ifs_reshape (Display *, Window, void *, unsigned int, unsigned int); + +static void * +ifs_init (Display *d_arg, Window w_arg) +{ + struct state *st = (struct state *) calloc (1, sizeof(*st)); + int i; + XWindowAttributes xgwa; + + /* Initialise all this X shizzle */ + st->dpy = d_arg; + st->window = w_arg; + + st->blackColor = BlackPixel(st->dpy, DefaultScreen(st->dpy)); + st->whiteColor = WhitePixel(st->dpy, DefaultScreen(st->dpy)); + st->gc = XCreateGC(st->dpy, st->window, 0, NULL); + + XGetWindowAttributes (st->dpy, st->window, &xgwa); + ifs_reshape(st->dpy, st->window, st, xgwa.width, xgwa.height); + + st->ncolours = get_integer_resource(st->dpy, "colors", "Colors"); + if (st->ncolours < st->lensnum) + st->ncolours = st->lensnum; + if (st->colours) free(st->colours); + st->colours = (XColor *)calloc(st->ncolours, sizeof(XColor)); + if (!st->colours) exit(1); + make_smooth_colormap (st->dpy, xgwa.visual, xgwa.colormap, + st->colours, &st->ncolours, + True, 0, False); + + /* Initialize IFS data */ + + st->delay = get_integer_resource(st->dpy, "delay", "Delay"); + st->length = get_integer_resource(st->dpy, "length", "Detail"); + if (st->length < 0) st->length = 0; + st->mode = get_integer_resource(st->dpy, "mode", "Mode"); + + st->rotate = get_boolean_resource(st->dpy, "rotate", "Boolean"); + st->scale = get_boolean_resource(st->dpy, "scale", "Boolean"); + st->translate = get_boolean_resource(st->dpy, "translate", "Boolean"); + st->recurse = get_boolean_resource(st->dpy, "recurse", "Boolean"); + st->multi = get_boolean_resource(st->dpy, "multi", "Boolean"); + + st->lensnum = get_integer_resource(st->dpy, "lensnum", "Functions"); + if (st->lenses) free (st->lenses); + st->lenses = (Lens *)calloc(st->lensnum, sizeof(Lens)); + if (!st->lenses) exit(1); + for (i = 0; i < st->lensnum; i++) { + CreateLens(st, + myrandom(1)-0.5, + myrandom(1), + myrandom(4)-2, + myrandom(4)+2, + &st->lenses[i]); + } + + return st; +} + +static void +ifs_reshape (Display *dpy, Window window, void *closure, + unsigned int w, unsigned int h) +{ + struct state *st = (struct state *)closure; + XWindowAttributes xgwa; + + /* oh well, we need the screen depth anyway */ + XGetWindowAttributes (st->dpy, st->window, &xgwa); + + st->width = xgwa.width; + st->widthb = ((xgwa.width + 31) >> 5); + st->height = xgwa.height; + st->width8 = xgwa.width << 8; + st->height8 = xgwa.height << 8; + + if (!st->xmax && !st->ymax && !st->xmin && !st->ymin) { + st->xmin = xgwa.width + 1; + st->xmax = st->ymax = -1; + st->ymin = xgwa.height + 1; + } + + if (st->backbuffer != None && st->backbuffer != st->window) { + XFreePixmap(st->dpy, st->backbuffer); + st->backbuffer = None; + } + + if (get_boolean_resource (st->dpy, "doubleBuffer", "Boolean")) { + st->backbuffer = XCreatePixmap(st->dpy, st->window, st->width, st->height, xgwa.depth); + XSetForeground(st->dpy, st->gc, st->blackColor); + XFillRectangle(st->dpy, st->backbuffer, st->gc, + 0, 0, st->width, st->height); + } else { + st->backbuffer = st->window; + XClearWindow(st->dpy, st->window); + } + + if (st->board) free(st->board); + st->board = (unsigned int *)calloc(st->widthb * st->height, sizeof(unsigned int)); + if (!st->board) exit(1); +} + +static Bool +ifs_event (Display *dpy, Window window, void *closure, XEvent *event) +{ + return False; +} + +static void +ifs_free (Display *dpy, Window window, void *closure) +{ + struct state *st = (struct state *) closure; + + if (st->board) free(st->board); + if (st->lenses) free(st->lenses); + if (st->colours) free(st->colours); + if (st->backbuffer != None && st->backbuffer != st->window) + XFreePixmap(st->dpy, st->backbuffer); + free(st); +} + +XSCREENSAVER_MODULE ("IFS", ifs) diff --git a/hacks/ifs.man b/hacks/ifs.man new file mode 100644 index 00000000..c95dce8d --- /dev/null +++ b/hacks/ifs.man @@ -0,0 +1,111 @@ +.TH XScreenSaver 1 "" "X Version 11" +.SH NAME +ifs - draws spinning, colliding iterated-function-system images +.SH SYNOPSIS +.B ifs +[\-display \fIhost:display.screen\fP] +[\-visual \fIvisual\fP] +[\-window] +[\-root] +[\-no\-db] +[\-delay \fInumber\fP] +[\-detail \fInumber\fP] +[\-colors \fInumber\fP] +[\-functions \fInumber\fP] +[\-iterate | \-recurse] +[\-no\-rotate] +[\-no\-scale] +[\-no\-translate] +[\-fps] +.SH DESCRIPTION +The \fIifs\fP program draws spinning, colliding iterated-function-system images. +.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 \-no\-db +Disable double-buffering. +.TP 8 +.B \-delay \fInumber\fP +Per-frame delay, in microseconds. Default: 20000 +.TP 8 +.B \-colors \fInumber\fP +Number of colours to use. Default: 200 +.TP 8 +.B \-detail \fInumber\fP +In \fI\-iterate\fP mode, number of times to randomly iterate the +functions, in thousands. In \fI\-recurse\fP mode, number of times +to apply functions (recursion depth) before drawing each point. +Default: 9 +.TP 8 +.B \-functions \fInumber\fP +Number of functions to be iterated. Default: 3 +.TP 8 +.B \-iterate +Calculate by iteratively applying the functions in a random order, +usually faster than \fI\-recurse\fP. This is the default. +.TP 8 +.B \-recurse +Calculate by recursively applying all combinations of the functions. +This is the historical behavior and may produce neater output than +\fI\-iterate\fP. +.TP 8 +.B \-no-rotate +Disable the rotation component of the functions. +.TP 8 +.B \-no-scale +Disable the scaling component of the functions. +.TP 8 +.B \-no-translate +Disable the varying translation component of the functions. +.TP 8 +.B \-no-multi +Turn off multi-coloured mode, only one colour is used to colour the whole set. +.TP 8 +.B \-fps +Display the current frame rate and CPU load. +.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), +.BR ifs (MANSUFFIX) +.SH COPYRIGHT +Copyright \(co Chris Le Sueur and Robby Griffin, 2005-2006 + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be included +in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR +OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +OTHER DEALINGS IN THE SOFTWARE. +.SH AUTHOR +This version by Chris Le Sueur , Feb 2005 +Many improvements by Robby Griffin , Mar 2006 diff --git a/hacks/images/6x10font.xbm b/hacks/images/6x10font.xbm new file mode 100644 index 00000000..0bdcd9cc --- /dev/null +++ b/hacks/images/6x10font.xbm @@ -0,0 +1,190 @@ +#define font6x10_width 1792 +#define font6x10_height 10 +static unsigned char font6x10_bits[] = { + 0x00, 0x80, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, + 0x20, 0x10, 0x7e, 0x00, 0x00, 0x00, 0x40, 0x20, 0x10, 0x00, 0x04, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0x00, 0x00, + 0x86, 0x03, 0x01, 0x00, 0x00, 0x00, 0x04, 0x00, 0x40, 0x20, 0x18, 0x00, + 0x04, 0x08, 0x82, 0x44, 0x41, 0x00, 0x00, 0x04, 0x08, 0x82, 0x42, 0x80, + 0x20, 0x28, 0x00, 0x14, 0x01, 0x82, 0x40, 0x51, 0x00, 0x00, 0x02, 0x04, + 0x41, 0x81, 0x00, 0x00, 0x04, 0x08, 0x02, 0x05, 0x40, 0x00, 0x00, 0x04, + 0x08, 0x02, 0x40, 0x40, 0x20, 0x00, 0x00, 0x14, 0x01, 0x82, 0x40, 0x01, + 0x00, 0x00, 0x02, 0x04, 0x01, 0x00, 0x00, 0x00, 0x2a, 0x00, 0x55, 0xe2, + 0xe0, 0x08, 0x10, 0x00, 0x89, 0x04, 0x01, 0x00, 0x20, 0x10, 0x00, 0x00, + 0x00, 0x00, 0x40, 0x20, 0x10, 0x00, 0x04, 0xcc, 0x00, 0x00, 0x61, 0x00, + 0x00, 0x04, 0x85, 0x82, 0x20, 0x11, 0x10, 0x10, 0x02, 0x00, 0x00, 0x00, + 0x00, 0x40, 0x08, 0x04, 0xc7, 0x07, 0xf1, 0x61, 0x7c, 0x1c, 0x0e, 0x00, + 0x00, 0x02, 0x10, 0x38, 0x1c, 0x84, 0x87, 0xe3, 0xf1, 0xf9, 0x38, 0x22, + 0x0e, 0x4e, 0x24, 0x10, 0x89, 0x38, 0x1e, 0x8e, 0x87, 0xe3, 0x13, 0x89, + 0x44, 0x22, 0x91, 0x8f, 0x23, 0xe0, 0x20, 0x00, 0x10, 0x80, 0x00, 0x00, + 0x02, 0x60, 0x00, 0x02, 0x04, 0x48, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x86, 0x60, 0x90, 0x54, + 0x2a, 0x95, 0x4a, 0xa5, 0x52, 0xa9, 0x54, 0x2a, 0x95, 0x4a, 0xa5, 0x52, + 0xa9, 0x54, 0x2a, 0x95, 0x4a, 0xa5, 0x52, 0xa9, 0x54, 0x2a, 0x95, 0x4a, + 0xa5, 0x52, 0xa9, 0x54, 0x00, 0x04, 0x00, 0x03, 0x10, 0x21, 0x38, 0x00, + 0x0e, 0x0e, 0x00, 0x00, 0x70, 0x00, 0x08, 0x00, 0x09, 0x84, 0x00, 0xf0, + 0x00, 0x00, 0x06, 0x06, 0x60, 0x30, 0x20, 0x10, 0x08, 0x04, 0x45, 0x03, + 0xa0, 0xe0, 0x39, 0x3e, 0x9f, 0xcf, 0x87, 0x40, 0x50, 0x00, 0x1e, 0x0a, + 0x02, 0x41, 0xa1, 0x00, 0x00, 0x1c, 0x04, 0x82, 0x02, 0x40, 0x08, 0x38, + 0x08, 0x04, 0x85, 0x42, 0xa1, 0x00, 0x00, 0x08, 0x04, 0x85, 0x82, 0x20, + 0x50, 0x28, 0x06, 0x0a, 0x02, 0x41, 0xa1, 0x50, 0x00, 0x00, 0x04, 0x82, + 0x42, 0x81, 0x00, 0x28, 0x00, 0x84, 0x4a, 0x22, 0x10, 0x08, 0x28, 0x08, + 0x8b, 0x04, 0x01, 0x00, 0x20, 0x10, 0x00, 0x3f, 0x00, 0x00, 0x40, 0x20, + 0x10, 0x00, 0x04, 0x03, 0x03, 0x80, 0x90, 0x00, 0x00, 0x04, 0x85, 0xc2, + 0x51, 0x29, 0x10, 0x08, 0x84, 0x08, 0x01, 0x00, 0x00, 0x40, 0x14, 0x86, + 0x08, 0x84, 0x11, 0x10, 0x40, 0x22, 0x11, 0x02, 0x01, 0x01, 0x20, 0x44, + 0x22, 0x0a, 0x49, 0x44, 0x12, 0x08, 0x44, 0x22, 0x04, 0x44, 0x22, 0x10, + 0x89, 0x44, 0x22, 0x91, 0x48, 0x84, 0x10, 0x89, 0x44, 0x22, 0x11, 0x88, + 0x20, 0x80, 0x50, 0x00, 0x00, 0x80, 0x00, 0x00, 0x02, 0x90, 0x00, 0x02, + 0x00, 0x40, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x81, 0x80, 0xa8, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x82, 0x04, 0x10, 0x21, 0x04, 0x00, 0x11, 0x09, 0x00, 0x00, + 0x88, 0x00, 0x14, 0x04, 0x04, 0x03, 0x00, 0xb8, 0x00, 0x00, 0x04, 0x09, + 0x40, 0x20, 0x10, 0x00, 0x1c, 0x0e, 0x87, 0xc3, 0xe1, 0x50, 0x44, 0x02, + 0x81, 0x40, 0xc0, 0xe1, 0x70, 0x38, 0x24, 0x11, 0x87, 0xc3, 0xe1, 0x70, + 0x00, 0x32, 0x91, 0x08, 0x20, 0x12, 0x79, 0x44, 0x00, 0x00, 0x00, 0x00, + 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x40, 0x08, 0x00, + 0x22, 0x0e, 0xd5, 0x63, 0x10, 0x08, 0x10, 0x08, 0x0b, 0x03, 0x01, 0x00, + 0x20, 0x10, 0x00, 0x00, 0x00, 0x00, 0x40, 0x20, 0x10, 0x00, 0x84, 0x00, + 0xe4, 0xf3, 0x11, 0x00, 0x00, 0x04, 0xc5, 0xa7, 0xa0, 0x28, 0x10, 0x04, + 0x08, 0x05, 0x01, 0x00, 0x00, 0x20, 0x22, 0x05, 0x08, 0x42, 0xd1, 0x08, + 0x20, 0x22, 0x19, 0x87, 0x83, 0xf0, 0x41, 0x20, 0x32, 0x11, 0x49, 0x40, + 0x12, 0x08, 0x04, 0x22, 0x04, 0x44, 0x21, 0xb0, 0x99, 0x44, 0x22, 0x91, + 0x48, 0x80, 0x10, 0x89, 0x44, 0x14, 0x0a, 0x84, 0x40, 0x80, 0x88, 0x00, + 0x00, 0x8e, 0x86, 0xc3, 0xe2, 0x10, 0x78, 0x1a, 0x06, 0x4c, 0x84, 0xb0, + 0x68, 0x38, 0x1a, 0x96, 0x86, 0xe3, 0x11, 0x89, 0x44, 0x22, 0x91, 0x0f, + 0x82, 0x40, 0x48, 0x44, 0x22, 0x91, 0x48, 0x24, 0x12, 0x89, 0x44, 0x22, + 0x91, 0x48, 0x24, 0x12, 0x89, 0x44, 0x22, 0x91, 0x48, 0x24, 0x12, 0x89, + 0x44, 0x22, 0x91, 0x48, 0x24, 0x12, 0x89, 0x44, 0x00, 0x04, 0x8f, 0x20, + 0xa2, 0x20, 0x1c, 0x00, 0x15, 0x0d, 0x09, 0x00, 0xb8, 0x00, 0x08, 0x04, + 0x02, 0x04, 0x10, 0xb9, 0x00, 0x00, 0x04, 0x49, 0x42, 0x20, 0x20, 0x10, + 0x22, 0x91, 0x48, 0x24, 0x12, 0x49, 0x04, 0x02, 0x81, 0x40, 0x80, 0x40, + 0x20, 0x10, 0x24, 0x93, 0x48, 0x24, 0x12, 0x89, 0x44, 0x32, 0x91, 0x48, + 0x24, 0x12, 0x89, 0x24, 0x1c, 0x0e, 0x87, 0xc3, 0xe1, 0xf0, 0x38, 0x1c, + 0x0e, 0x87, 0xc3, 0x60, 0x30, 0x18, 0x1c, 0x0d, 0x87, 0xc3, 0xe1, 0x70, + 0x00, 0x3c, 0x91, 0x48, 0x24, 0x12, 0x79, 0x44, 0x00, 0x9f, 0x4a, 0x22, + 0xe0, 0x78, 0x00, 0x3e, 0x0d, 0x01, 0x01, 0x00, 0x20, 0x10, 0x00, 0x00, + 0x00, 0x00, 0x40, 0x20, 0x10, 0x00, 0x04, 0x03, 0x43, 0x41, 0x38, 0x10, + 0x00, 0x04, 0x80, 0xc2, 0x41, 0x10, 0x00, 0x04, 0x88, 0xcf, 0x07, 0xf0, + 0x01, 0x10, 0x22, 0x04, 0x06, 0x23, 0x31, 0x69, 0x20, 0x1c, 0x16, 0x02, + 0x41, 0x00, 0x80, 0x10, 0x2a, 0x11, 0x47, 0x40, 0xf2, 0x78, 0x04, 0x3e, + 0x04, 0xc4, 0x20, 0x50, 0xa9, 0x44, 0x1e, 0x91, 0x87, 0x83, 0x10, 0x51, + 0x54, 0x08, 0x04, 0x82, 0x80, 0x80, 0x00, 0x00, 0x00, 0x90, 0x49, 0x24, + 0x13, 0x79, 0x44, 0x26, 0x04, 0x48, 0x82, 0x50, 0x99, 0x44, 0x26, 0x99, + 0x49, 0x40, 0x10, 0x89, 0x44, 0x14, 0x11, 0x84, 0x81, 0x80, 0x01, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x84, 0xc2, 0xc1, 0x41, 0x00, 0x24, 0x00, + 0x13, 0x8a, 0xc4, 0xe3, 0x99, 0x00, 0x00, 0x1f, 0x8f, 0x03, 0x10, 0xb1, + 0x10, 0x00, 0x0e, 0x86, 0xe4, 0x74, 0x99, 0x10, 0x22, 0x91, 0x48, 0x24, + 0x12, 0xc9, 0x05, 0x1e, 0x8f, 0xc7, 0x83, 0x40, 0x20, 0x10, 0x2e, 0x95, + 0x48, 0x24, 0x12, 0x89, 0x28, 0x2a, 0x91, 0x48, 0x24, 0xa2, 0x78, 0x14, + 0x20, 0x10, 0x08, 0x04, 0x02, 0x41, 0x45, 0x22, 0x91, 0x48, 0x84, 0x40, + 0x20, 0x10, 0x22, 0x93, 0x48, 0x24, 0x12, 0x89, 0x7c, 0x32, 0x91, 0x48, + 0x24, 0x12, 0x89, 0x44, 0x22, 0x0e, 0x55, 0xa2, 0xe3, 0xf0, 0x00, 0x08, + 0x09, 0xcf, 0xe1, 0xc0, 0xe3, 0xfd, 0x00, 0x80, 0x1f, 0x00, 0xc0, 0x3b, + 0xfc, 0x7e, 0x04, 0xcc, 0x40, 0xf1, 0x11, 0x00, 0x00, 0x04, 0xc0, 0x87, + 0xa2, 0xa8, 0x00, 0x04, 0x08, 0x05, 0x01, 0x00, 0x00, 0x08, 0x22, 0x04, + 0x01, 0xe4, 0x03, 0x99, 0x10, 0x22, 0x10, 0x00, 0x80, 0xf0, 0x41, 0x10, + 0x1a, 0x1f, 0x49, 0x40, 0x12, 0x08, 0x64, 0x22, 0x04, 0x44, 0x21, 0x10, + 0xc9, 0x44, 0x02, 0x91, 0x02, 0x84, 0x10, 0x51, 0x54, 0x14, 0x04, 0x81, + 0x00, 0x81, 0x00, 0x00, 0x00, 0x9e, 0x48, 0x20, 0xf2, 0x11, 0x44, 0x22, + 0x04, 0xc8, 0x81, 0x50, 0x89, 0x44, 0x22, 0x91, 0x80, 0x43, 0x10, 0x51, + 0x54, 0x08, 0x19, 0x02, 0x82, 0x40, 0x00, 0x44, 0x22, 0x91, 0x48, 0x24, + 0x12, 0x89, 0x44, 0x22, 0x91, 0x48, 0x24, 0x12, 0x89, 0x44, 0x22, 0x91, + 0x48, 0x24, 0x12, 0x89, 0x44, 0x22, 0x91, 0x48, 0x24, 0x12, 0x89, 0x44, + 0x00, 0x84, 0x82, 0x40, 0xf1, 0x21, 0x48, 0x00, 0x15, 0x40, 0x02, 0x02, + 0x98, 0x00, 0x00, 0x04, 0x00, 0x00, 0x10, 0xa1, 0x00, 0x00, 0x00, 0x00, + 0x09, 0x86, 0xc2, 0x08, 0x3e, 0x9f, 0xcf, 0xe7, 0xf3, 0x79, 0x04, 0x02, + 0x81, 0x40, 0x80, 0x40, 0x20, 0x10, 0x24, 0x99, 0x48, 0x24, 0x12, 0x89, + 0x10, 0x26, 0x91, 0x48, 0x24, 0x42, 0x08, 0x24, 0x3c, 0x1e, 0x8f, 0xc7, + 0xe3, 0xf1, 0x05, 0x3e, 0x9f, 0xcf, 0x87, 0x40, 0x20, 0x10, 0x22, 0x91, + 0x48, 0x24, 0x12, 0x89, 0x00, 0x2a, 0x91, 0x48, 0x24, 0x92, 0x89, 0x64, + 0x00, 0x84, 0x8a, 0x87, 0x20, 0x11, 0x00, 0x08, 0x02, 0x04, 0x80, 0x40, + 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x40, 0x20, 0x00, 0x08, 0x04, 0x00, + 0x40, 0x21, 0x90, 0x00, 0x00, 0x00, 0x80, 0xc2, 0x51, 0x49, 0x00, 0x08, + 0x84, 0x08, 0x81, 0x01, 0x20, 0x04, 0x14, 0x84, 0x40, 0x04, 0x11, 0x89, + 0x08, 0x22, 0x08, 0x02, 0x03, 0x01, 0x20, 0x00, 0x02, 0x11, 0x49, 0x44, + 0x12, 0x08, 0x44, 0x22, 0x84, 0x44, 0x22, 0x10, 0x89, 0x44, 0x02, 0x95, + 0x44, 0x84, 0x10, 0x51, 0x6c, 0x22, 0x84, 0x80, 0x00, 0x82, 0x00, 0x00, + 0x00, 0x91, 0x49, 0x24, 0x13, 0x10, 0x78, 0x22, 0x04, 0x48, 0x82, 0x50, + 0x89, 0x44, 0x26, 0x99, 0x00, 0x44, 0x92, 0x51, 0x54, 0x14, 0x16, 0x01, + 0x81, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x84, 0x82, 0xc4, + 0x41, 0x20, 0x70, 0x00, 0x11, 0x8f, 0x04, 0x00, 0x88, 0x00, 0x00, 0x04, + 0x00, 0x00, 0x30, 0xa1, 0x00, 0x00, 0x00, 0x8f, 0x04, 0x05, 0xa2, 0x44, + 0x22, 0x91, 0x48, 0x24, 0x12, 0x49, 0x44, 0x02, 0x81, 0x40, 0x80, 0x40, + 0x20, 0x10, 0x24, 0x91, 0x48, 0x24, 0x12, 0x89, 0x28, 0x26, 0x91, 0x48, + 0x24, 0x42, 0x08, 0x44, 0x22, 0x91, 0x48, 0x24, 0x12, 0x49, 0x44, 0x02, + 0x81, 0x40, 0x80, 0x40, 0x20, 0x10, 0x22, 0x91, 0x48, 0x24, 0x12, 0x89, + 0x10, 0x26, 0x99, 0x4c, 0x26, 0x63, 0x89, 0x58, 0x2a, 0x00, 0x15, 0x82, + 0xe1, 0x70, 0x00, 0x3e, 0x02, 0x04, 0x80, 0x40, 0x00, 0x10, 0x00, 0x00, + 0xc0, 0x0f, 0x40, 0x20, 0x00, 0x08, 0x84, 0xcf, 0x47, 0x11, 0x68, 0x00, + 0x00, 0x04, 0x80, 0x82, 0x90, 0xb0, 0x00, 0x10, 0x02, 0x00, 0x80, 0x00, + 0x70, 0x04, 0x08, 0x9f, 0x8f, 0x03, 0xe1, 0x70, 0x08, 0x1c, 0x06, 0x07, + 0x01, 0x02, 0x10, 0x10, 0x1c, 0x91, 0x87, 0xe3, 0xf1, 0x09, 0x38, 0x22, + 0x0e, 0x43, 0xe4, 0x13, 0x89, 0x38, 0x02, 0x8e, 0x88, 0x83, 0xe0, 0x20, + 0x44, 0x22, 0x84, 0x8f, 0x03, 0xe2, 0x00, 0x00, 0x00, 0x9e, 0x86, 0xc3, + 0xe2, 0x10, 0x40, 0x22, 0x0e, 0x49, 0xc4, 0x11, 0x89, 0x38, 0x1a, 0x96, + 0xc0, 0x83, 0x61, 0x21, 0x28, 0x22, 0x90, 0x0f, 0x86, 0x60, 0x00, 0x54, + 0x2a, 0x95, 0x4a, 0xa5, 0x52, 0xa9, 0x54, 0x2a, 0x95, 0x4a, 0xa5, 0x52, + 0xa9, 0x54, 0x2a, 0x95, 0x4a, 0xa5, 0x52, 0xa9, 0x54, 0x2a, 0x95, 0x4a, + 0xa5, 0x52, 0xa9, 0x54, 0x00, 0x04, 0x4f, 0x23, 0x42, 0x20, 0x40, 0x00, + 0x0e, 0x00, 0x09, 0x00, 0x70, 0x00, 0x00, 0x1f, 0x00, 0x00, 0xd0, 0xa0, + 0x00, 0x00, 0x00, 0x40, 0x82, 0x07, 0xf1, 0x38, 0x22, 0x91, 0x48, 0x24, + 0x12, 0xc9, 0x39, 0x3e, 0x9f, 0xcf, 0xc7, 0xe1, 0x70, 0x38, 0x1e, 0x11, + 0x87, 0xc3, 0xe1, 0x70, 0x44, 0x1c, 0x0e, 0x87, 0xc3, 0x41, 0x08, 0x34, + 0x3c, 0x1e, 0x8f, 0xc7, 0xe3, 0xf1, 0x39, 0x1c, 0x0e, 0x87, 0xc3, 0xe1, + 0x70, 0x38, 0x1c, 0x11, 0x87, 0xc3, 0xe1, 0x70, 0x00, 0x1e, 0x16, 0x8b, + 0xc5, 0x02, 0x79, 0x40, 0x00, 0x80, 0x0a, 0x82, 0x20, 0x11, 0x00, 0x00, + 0x02, 0x04, 0x80, 0x40, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x40, 0x20, + 0x00, 0x08, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x20, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x82, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x44, 0x00, + 0x00, 0x09, 0x00, 0x00, 0x00, 0x00, 0x02, 0x10, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x02, 0x00, 0x40, 0x00, 0x38, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x10, 0x00, 0x00, + 0x00, 0x84, 0x83, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x09, 0x44, + 0x00, 0x00, 0x15, 0x82, 0x20, 0x11, 0x00, 0x00, 0x1e, 0x04, 0x80, 0x40, + 0x00, 0x10, 0x00, 0x00, 0x00, 0xe0, 0x47, 0x20, 0x00, 0x08, 0x04, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x38, 0x00, 0x00, 0x06, 0x00, 0x00, + 0x00, 0x00, 0x02, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x08, 0x38}; diff --git a/hacks/images/amiga.xpm b/hacks/images/amiga.xpm new file mode 100644 index 00000000..ed31447b --- /dev/null +++ b/hacks/images/amiga.xpm @@ -0,0 +1,269 @@ +/* XPM */ +static char *amiga_hand[] = { +/* width height num_colors chars_per_pixel */ +" 209 258 4 1", +/* colors */ +". c #000000", +"# c #6666cc", +"a c #cccccc", +"b c #ffffff", +/* pixels */ +"bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb.......................................................................................................................................................bbbbbbbbbbbbbbbbbbb", +"bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb.......................................................................................................................................................bbbbbbbbbbbbbbbbbbb", +"bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb.........................................................................................................................................................bbbbbbbbbbbbbbbbb", +"bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb.........................................................................................................................................................bbbbbbbbbbbbbbbbb", +"bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb.....###################################.....aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.....###################.....bbbbbbbbbbbbbbbb", +"bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb.....###################################.....aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.....###################.....bbbbbbbbbbbbbbbb", +"bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb.....###################################.....aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.....#####################.....bbbbbbbbbbbbbb", +"bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb.....###################################.....aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.....#####################.....bbbbbbbbbbbbbb", +"bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb.....###################################.....aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa....................aaaa.....#######################.....bbbbbbbbbbbb", +"bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb.....###################################.....aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa....................aaaa.....#######################.....bbbbbbbbbbbb", +"bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb.....###################################.....aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa....................aaaa.....########################.....bbbbbbbbbbb", +"bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb.....###################################.....aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa....................aaaa.....########################.....bbbbbbbbbbb", +"bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb.....###################################.....aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.....##########.....aaaa.....##########################.....bbbbbbbbb", +"bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb.....###################################.....aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.....##########.....aaaa.....##########################.....bbbbbbbbb", +"bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb.....###################################.....aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.....##########.....aaaa.....############################....bbbbbbbb", +"bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb.....###################################.....aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.....##########.....aaaa.....############################....bbbbbbbb", +"bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb.....###################################.....aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.....##########.....aaaa.....#############################.....bbbbbb", +"bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb.....###################################.....aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.....##########.....aaaa.....#############################.....bbbbbb", +"bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb.....###################################.....aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.....##########.....aaaa.....###############################.....bbbb", +"bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb.....###################################.....aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.....##########.....aaaa.....###############################.....bbbb", +"bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb.....###################################.....aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.....##########.....aaaa.....################################.....bbb", +"bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb.....###################################.....aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.....##########.....aaaa.....################################.....bbb", +"bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb.....###################################.....aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.....##########.....aaaa.....##################################.....b", +"bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb.....###################################.....aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.....##########.....aaaa.....##################################.....b", +"bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb.....###################################.....aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.....##########.....aaaa.....####################################....", +"bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb.....###################################.....aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.....##########.....aaaa.....####################################....", +"bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb.....###################################.....aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.....##########.....aaaa.....####################################....", +"bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb.....###################################.....aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.....##########.....aaaa.....####################################....", +"bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb.....###################################.....aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.....##########.....aaaa.....####################################....", +"bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb.....###################################.....aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.....##########.....aaaa.....####################################....", +"bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb.....###################################.....aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.....##########.....aaaa.....####################################....", +"bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb.....###################################.....aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.....##########.....aaaa.....####################################....", +"bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb.....###################################.....aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.....##########.....aaaa.....####################################....", +"bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb.....###################################.....aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.....##########.....aaaa.....####################################....", +"bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb.....###################################.....aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa....................aaaa.....####################################....", +"bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb.....###################################.....aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa....................aaaa.....####################################....", +"bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb.....###################################.....aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa....................aaaa.....####################################....", +"bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb.....###################################.....aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa....................aaaa.....####################################....", +"bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb.....###################################.....aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.....####################################....", +"bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb.....###################################.....aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.....####################################....", +"bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb.....###################################.....aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.....####################################....", +"bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb.....###################################.....aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.....####################################....", +"bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb.....###################################.....aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.....####################################....", +"bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb.....###################################.....aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.....####################################....", +"bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb.....###################################..........................................................................................####################################....", +"bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb.....###################################..........................................................................................####################################....", +"bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb.....###################################..........................................................................................####################################....", +"bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb.....###################################..........................................................................................####################################....", +"bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb.....#################################################################################################################################################################....", +"bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb.....#################################################################################################################################################################....", +"bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb.....#################################################################################################################################################################....", +"bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb.....#################################################################################################################################################################....", +"bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb.....#################################################################################################################################################################....", +"bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb.....#################################################################################################################################################################....", +"bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb.....#################################################################################################################################################################....", +"bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb.....#################################################################################################################################################################....", +"bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb.....#################################################################################################################################################################....", +"bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb.....#################################################################################################################################################################....", +"bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb.....#################################################################################################################################################################....", +"bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb.....#################################################################################################################################################################....", +"bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb.....#################################################################################################################################################################....", +"bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb.....#################################################################################################################################################################....", +"bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb.....#################################################################################################################################################################....", +"bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb.....#################################################################################################################################################################....", +"bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb.....#################################################################################################################################################################....", +"bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb.....#################################################################################################################################################################....", +"bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb.....#################################################################################################################################################################....", +"bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb.....#################################################################################################################################################################....", +"bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb.....#################################################################################################################################################################....", +"bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb.....#################################################################################################################################################################....", +"bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb.....#################################################################################################################################################################....", +"bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb.....#################################################################################################################################################################....", +"bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb.....#################################################################################################################################################################....", +"bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb.....#################################################################################################################################################################....", +"bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb.....#################################################################################################################################################################....", +"bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb.....#################################################################################################################################################################....", +"bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb.....#################################################################################################################################################################....", +"bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb.....#################################################################################################################################################################....", +"bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb.....#################################################################################################################################################################....", +"bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb.....#################################################################################################################################################################....", +"bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb.....#################################################################################################################################################################....", +"bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb.....#################################################################################################################################################################....", +"bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb.....#################################################################################################################################################################....", +"bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb.....#################################################################################################################################################################....", +"bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb.....#################################################################################################################################################################....", +"bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb.....#################################################################################################################################################################....", +"bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb.....#################################################################################################################################################################....", +"bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb.......#########################..................######################################################################################################################....", +"bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb.......#########################..................######################################################################################################################....", +"bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb..........#########################..bbbbb.............####################################################################################################################....", +"bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb..........#########################..bbbbb.............####################################################################################################################....", +"bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb.....bbb.....##############.............bbbbbbbbbbb..bbb.........................................................................................................#############....", +"bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb.....bbb.....##############.............bbbbbbbbbbb..bbb.........................................................................................................#############....", +"bbbbbbbbbbbbbbbbbbbbbbbbbbbb......bbbbb.....##############...........bbbbbbbbbbbbbbb..bbbb......................................................................................................#############....", +"bbbbbbbbbbbbbbbbbbbbbbbbbbbb......bbbbb.....##############...........bbbbbbbbbbbbbbb..bbbb......................................................................................................#############....", +"bbbbbbbbbbbbbbbbbbbbbbbbbb.....bbbbbbbb.....##############.....bbb...bbbbbbbbbbbbbbb...bbb....bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb.....#############....", +"bbbbbbbbbbbbbbbbbbbbbbbbbb.....bbbbbbbb.....##############.....bbb...bbbbbbbbbbbbbbb...bbb....bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb.....#############....", +"bbbbbbbbbbbbbbbbbbbbbbbb....bbbbbbbbbbb.....##############.....bbb...bbbbbbbbbbbbbbb...bbb....bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb.....#############....", +"bbbbbbbbbbbbbbbbbbbbbbbb....bbbbbbbbbbb.....##############.....bbb...bbbbbbbbbbbbbbb...bbb....bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb.....#############....", +"bbbbbbbbbbbbbbbbbbbbbbbb....bbbbbbbbbbb.....##############.....bb...bbbbbbbbbbbbbbbb...bbb....bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb.....#############....", +"bbbbbbbbbbbbbbbbbbbbbbbb....bbbbbbbbbbb.....##############.....bb...bbbbbbbbbbbbbbbb...bbb....bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb.....#############....", +"bbbbbbbbbbbbbbbbbbbbbbb...bbbbbbbbbbbbb.....##############..........bbbbbbbbbbbbbbbb...bbb....bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb.....#############....", +"bbbbbbbbbbbbbbbbbbbbbbb...bbbbbbbbbbbbb.....##############..........bbbbbbbbbbbbbbbb...bbb....bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb.....#############....", +"bbbbbbbbbbbbbbbbbbbbbbb...bbbbbbbbbbbbb.....##############...........bbbbbbbbbbbbbbb...bbb....bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb.....#############....", +"bbbbbbbbbbbbbbbbbbbbbbb...bbbbbbbbbbbbb.....##############...........bbbbbbbbbbbbbbb...bbb....bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb.....#############....", +"bbbbbbbbbbbbbbbbbbbbb...bbbbbbbbbbbbbbb.....##############.............bbbbbbbbbbbbb...bbb....bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb.....#############....", +"bbbbbbbbbbbbbbbbbbbbb...bbbbbbbbbbbbbbb.....##############.............bbbbbbbbbbbbb...bbb....bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb.....#############....", +"bbbbbbbbbbbbbbbbbbbbb...bbbbbbbbbbbbbbb.....##############..........b....bbbbbbbbbbb...bbb....bbbb####bbbb#####bbbbb########bbbbb###bbbbb###bbbbb########bbbbbbb########bbbbbbbbbbbbbbbbbbb.....#############....", +"bbbbbbbbbbbbbbbbbbbbb...bbbbbbbbbbbbbbb.....##############..........b....bbbbbbbbbbb...bbb....bbbb####bbbb#####bbbbb########bbbbb###bbbbb###bbbbb########bbbbbbb########bbbbbbbbbbbbbbbbbbb.....#############....", +"bbbbbbbbbbbbbbbbbbbb...bbbbbbbbbbbbbbbb.....##############........bbbbb................bbb....bbbb####bbbb####bbbb####bbbbb###bbb###bbbbb###bbbbbbbbbbb####bbb###bbbbb###bbbbbbbbbbbbbbbbbb.....#############....", +"bbbbbbbbbbbbbbbbbbbb...bbbbbbbbbbbbbbbb.....##############........bbbbb................bbb....bbbb####bbbb####bbbb####bbbbb###bbb###bbbbb###bbbbbbbbbbb####bbb###bbbbb###bbbbbbbbbbbbbbbbbb.....#############....", +"bbbbbbbbbbbbbbbbbbbb...bbbbbbbbbbbbbbbb.....###########........bbbbbbbbbb.............bbbb....bbbb####bbbb####bbbbbbbbbbbbb###bbb###bbbbb###bbb############bbb###bbbbb###bbbbbbbbbbbbbbbbbb.....#############....", +"bbbbbbbbbbbbbbbbbbbb...bbbbbbbbbbbbbbbb.....###########........bbbbbbbbbb.............bbbb....bbbb####bbbb####bbbbbbbbbbbbb###bbb###bbbbb###bbb############bbb###bbbbb###bbbbbbbbbbbbbbbbbb.....#############....", +"bbbbbbbbbbbbbbbbbbbb.bbbbbbbbbbbbbbbbbb.....#########........bbbbbbbbbbbbbbbbbbbbbbbbbbbbb....bbbb####bbb#####bbbb####bbbbb###bbb###bbbbb###bbb####bbbb####bbb###bbb#####bbbbbbbbbbbbbbbbbb.....#############....", +"bbbbbbbbbbbbbbbbbbbb.bbbbbbbbbbbbbbbbbb.....#########........bbbbbbbbbbbbbbbbbbbbbbbbbbbbb....bbbb####bbb#####bbbb####bbbbb###bbb###bbbbb###bbb####bbbb####bbb###bbb#####bbbbbbbbbbbbbbbbbb.....#############....", +"bbbbbbbbbbbbbbbbbb...bbbbbbbbbbbbbbbbbb.....########........bbbbbbbbbbbbbbbbbbbbbbbbbbbbbb....bbbbbb#####b####bbbbbb########bbbbbbb#########bbbbb########bbbbbbb####bb###bbbbbbbbbbbbbbbbbb.....#############....", +"bbbbbbbbbbbbbbbbbb...bbbbbbbbbbbbbbbbbb.....########........bbbbbbbbbbbbbbbbbbbbbbbbbbbbbb....bbbbbb#####b####bbbbbb########bbbbbbb#########bbbbb########bbbbbbb####bb###bbbbbbbbbbbbbbbbbb.....#############....", +"bbbbbbbbbbbbbbbbbb...bbbbbbbbbbbbbbbbbb.....#####........bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb....bbbbbbbbbbbb####bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb###bbbbbbbbbbbbbbbbbb.....#############....", +"bbbbbbbbbbbbbbbbbb...bbbbbbbbbbbbbbbbbb.....#####........bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb....bbbbbbbbbbbb####bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb###bbbbbbbbbbbbbbbbbb.....#############....", +"bbbbbbbbbbbbbbbb....bbbbbbbbbbbbbbbbbbb.....###........bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb...bbbbbbbbbbbbbb#####bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb#####bbbbbbbbbbbbbbbb.....#############....", +"bbbbbbbbbbbbbbbb....bbbbbbbbbbbbbbbbbbb.....###........bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb...bbbbbbbbbbbbbb#####bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb#####bbbbbbbbbbbbbbbb.....#############....", +"bbbbbbbbbbbbbbb...bbbbb.bbbbbbbbbbbbbbb..............bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb...bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb.....#############....", +"bbbbbbbbbbbbbbb...bbbbb.bbbbbbbbbbbbbbb..............bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb...bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb.....#############....", +"bbbbbbbbbbbb....bbbbbbbb....bbbbbbbbbbb.....bbb...bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb.....bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb.....#############....", +"bbbbbbbbbbbb....bbbbbbbb....bbbbbbbbbbb.....bbb...bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb.....bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb.....#############....", +"bbbbbbbbbb...bbbbbbbbbbbbb.....bbbbb...........bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb....bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb.....#############....", +"bbbbbbbbbb...bbbbbbbbbbbbb.....bbbbb...........bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb....bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb.....#############....", +"bbbbbbbb....bbbbbbbbbbbbbbbb................bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb...bbbbbbbbbbbbbbbbbbbbb###bbbbb#####bbbbbbbb######bbbbb########bbbbb###bbbbbbb###bbbbbbbbbbbbbbbbbbbbbbbb.....#############....", +"bbbbbbb...bbbbbbbbbbbbbbbbbbbbbb.........bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb...bbbbbbbbbbbbbbbbbbbbbbbb####bbb###bbbbbbbbbbb####bbbb####bbbb####bbb#####bbb#####bbbbbbbbbbbbbbbbbbbbbbbb.....#############....", +"bbbbbbb...bbbbbbbbbbbbbbbbbbbbbb.........bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb...bbbbbbbbbbbbbbbbbbbbbbbb####bbb###bbbbbbbbbbb####bbbb####bbbb####bbb#####bbb#####bbbbbbbbbbbbbbbbbbbbbbbb.....#############....", +"bbbbb...bbbbbbbbbbbbbbbbbbbbbbb......bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb...bbbbbbbbbbbbbbbbbbbbbbbbbbb########bbb####bbbb####bbbb####bbbb####bbb#############bbbbbbbbbbbbbbbbbbbbbbbb.....#############....", +"bbbbb...bbbbbbbbbbbbbbbbbbbbbbb......bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb...bbbbbbbbbbbbbbbbbbbbbbbbbbb########bbb####bbbb####bbbb####bbbb####bbb#############bbbbbbbbbbbbbbbbbbbbbbbb.....#############....", +"bbbbb...bbbbbbbbbbbbbbbbbbbbb..b..bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb...bbbbbbbbbbbbbbbbbbbbbbbbbbb####bbb###bbb####bbb#####bbbb####bbbb####bbb###bb###bb###bbbbbbbbbbbbbbbbbbbbbbbb.....#############....", +"bbbbb...bbbbbbbbbbbbbbbbbbbbb..b..bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb...bbbbbbbbbbbbbbbbbbbbbbbbbbb####bbb###bbb####bbb#####bbbb####bbbb####bbb###bb###bb###bbbbbbbbbbbbbbbbbbbbbbbb.....#############....", +"bbbb...bbbbbbbbbbbbbbbbbbbbb....bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb....bbbbbbbbbbbbbbbbbbbbbbbbbbb###bbbbb###bbbbb#####b#####bbbbb########bbbbb###bbbbbbb###bbbbbbbbbbbbbbbbbbbbbbbb.....#############....", +"bbbb...bbbbbbbbbbbbbbbbbbbbb....bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb....bbbbbbbbbbbbbbbbbbbbbbbbbbb###bbbbb###bbbbb#####b#####bbbbb########bbbbb###bbbbbbb###bbbbbbbbbbbbbbbbbbbbbbbb.....#############....", +"bb...bbbbbbbbbbbbbbbbbbb.....bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb.....bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb###bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb###bbbbbbb###bbbbbbbbbbbbbbbbbbbbbbbb.....#############....", +"bb...bbbbbbbbbbbbbbbbbbb.....bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb.....bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb###bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb###bbbbbbb###bbbbbbbbbbbbbbbbbbbbbbbb.....#############....", +"bb...bbbbbbbbbbbbbbbbbb.bb..bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb....bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb#####bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb###bbbbbbb###bbbbbbbbbbbbbbbbbbbbbbbb.....#############....", +"bb...bbbbbbbbbbbbbbbbbb.bb..bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb....bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb#####bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb###bbbbbbb###bbbbbbbbbbbbbbbbbbbbbbbb.....#############....", +"....bbbbbbbbbbbbbbbbb.....bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb...bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb.....#############....", +"....bbbbbbbbbbbbbbbbb.....bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb...bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb.....#############....", +"....bbbbbbbbbbbbbb.....bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb...bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb.....#############....", +"....bbbbbbbbbbbbbb.....bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb...bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb.....#############....", +"....bbbbbbbbbbbb..bb.bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb...bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb.....#############....", +"....bbbbbbbbbbbb..bb.bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb...bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb.....#############....", +"....bbbbbbbbbbb.....bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb...bbbbbbbbbbbbbaa........bbb.......aaa........abbbbbaa..........a..........baa..abb................bbb.......abbbbbbbbbb.....#############....", +"....bbbbbbbbbbb.....bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb...bbbbbbbbbbbbbaa........bbb.......aaa........abbbbbaa..........a..........baa..abb................bbb.......abbbbbbbbbb.....#############....", +"....bbbbbbbbbbb.bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb...bbbbbbbbbbbbbbbbba...bbbbbbb.aabbbaa...bba.....aabbbbba...aabbbbba....abbb....abbbbb...aabba...bbbbbbb.aabbbbbbbbbbbbb.....#############....", +"....bbbbbbbbbbb.bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb...bbbbbbbbbbbbbbbbba...bbbbbbb.aabbbaa...bba.....aabbbbba...aabbbbba....abbb....abbbbb...aabba...bbbbbbb.aabbbbbbbbbbbbb.....#############....", +"....bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb...bbbbbbbbbbbbbbbbba..........abbbbb...aabbbaa.....abbbba...bbbbbbba....bbba....abbb....bbbbba..........abbbbbbbbbbbbbbb.....#############....", +"....bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb...bbbbbbbbbbbbbbbbba..........abbbbb...aabbbaa.....abbbba...bbbbbbba....bbba....abbb....bbbbba..........abbbbbbbbbbbbbbb.....#############....", +"....bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb...bbbbbbbbbbbbbbbbba...bbbb.aabbbbb......aabbb.....abbbb...abbbbbbb...aabaa.....abb...bbbbbbba...bbbb.aabbbbbbbbbbbbbbbb.....#############....", +"....bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb...bbbbbbbbbbbbbbbbba...bbbb.aabbbbb......aabbb.....abbbb...abbbbbbb...aabaa.....abb...bbbbbbba...bbbb.aabbbbbbbbbbbbbbbb.....#############....", +"....bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb...bbbbbbbbbbbbbbbbba...bb..abbbbbbbbbbbbbbbbbb.....abbaa...bbbbbbaa...aaa..a....a...bbbbbbbbba...bb..abbbbbbbbbbbbbbbbbb.....#############....", +"....bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb...bbbbbbbbbbbbbbbbba...bb..abbbbbbbbbbbbbbbbbb.....abbaa...bbbbbbaa...aaa..a....a...bbbbbbbbba...bb..abbbbbbbbbbbbbbbbbb.....#############....", +"....bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb...bbbbbbbbbbbbbbbbba.....aabbbbbbbbb..bbbbbbaa...aabbb...aabbbbbb...aa...aab.......bbbbbbbbbba.....aabbbbbbbbbbbbbbbbbbb.....#############....", +"....bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb...bbbbbbbbbbbbbbbbba.....aabbbbbbbbb..bbbbbbaa...aabbb...aabbbbbb...aa...aab.......bbbbbbbbbba.....aabbbbbbbbbbbbbbbbbbb.....#############....", +"....bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb...bbbbbbbbbbbbbbbbba...aabbbbbbbbbbb..abbbba...aabbaaa...bbbbbbba.......abbb.....aabbbbbbbbbba...aabbbbbbbbbbbbbbbbbbbbb.....#############....", +"....bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb...bbbbbbbbbbbbbbbbba...aabbbbbbbbbbb..abbbba...aabbaaa...bbbbbbba.......abbb.....aabbbbbbbbbba...aabbbbbbbbbbbbbbbbbbbbb.....#############....", +"....bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb...bbbbbbbbbbbbbbbbba..abbbbbbbbbbbbb........aaabbaa........aaaaa......aabbbb.......abbbbbbbbba..abbbbbbbbbbbbbbbbbbbbbbb.....#############....", +"....bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb...bbbbbbbbbbbbbbbbba..abbbbbbbbbbbbb........aaabbaa........aaaaa......aabbbb.......abbbbbbbbba..abbbbbbbbbbbbbbbbbbbbbbb.....#############....", +"....bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb...bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb.....#############....", +"....bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb...bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb.....#############....", +"....bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb...bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb.....#############....", +"....bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb...bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb.....#############....", +"....bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb.............................................................................................................................................", +"....bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb.............................................................................................................................................", +"....bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb............................................................................................................................................", +"....bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb............................................................................................................................................", +"....bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb....b....bbbbbbbbbbbbbbbbbbbbbbbbb........bbbbbbbbbbbb...bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb", +"....bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb....b....bbbbbbbbbbbbbbbbbbbbbbbbb........bbbbbbbbbbbb...bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb", +"....bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb....bbbbb...bbbbbbbbbbbbbbbbbbbbb........bbbbbbbbbbbbb...bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb", +"....bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb....bbbbb...bbbbbbbbbbbbbbbbbbbbb........bbbbbbbbbbbbb...bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb", +"....bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb....bbb........bbbbbbbbbbbbbbbb........bbbbbbbbbbbbbbb...bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb", +"....bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb....bbb........bbbbbbbbbbbbbbbb........bbbbbbbbbbbbbbb...bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb", +"....bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb.................bbbbbbbbbbbb........bbbbbbbbbbbbbbbbb...bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb", +"....bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb.................bbbbbbbbbbbb........bbbbbbbbbbbbbbbbb...bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb", +"....bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb.........bbbbbb...bbbbbbbbbb........bbbbbbbbbbbbbbbbbb...bbbbbbbbbbbbbb........bbb............bbbbbbbb.....bbbbbbbbbbbbbbbb.........bbbbbbbb", +"....bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb.........bbbbbb...bbbbbbbbbb........bbbbbbbbbbbbbbbbbb...bbbbbbbbbbbbbb........bbb............bbbbbbbb.....bbbbbbbbbbbbbbbb.........bbbbbbbb", +"....bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb..bb.bbbbbbbbbbbb...bbbbbb........bbbbbbbbbbbbbbbbbb...bbbbbbbbbbbbbbbbbb.....bbbbbbbb.....bbbbbbbbb.......bbbbbbbbbbbbbb.............bbbbbb", +"....bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb..bb.bbbbbbbbbbbb...bbbbbb........bbbbbbbbbbbbbbbbbb...bbbbbbbbbbbbbbbbbb.....bbbbbbbb.....bbbbbbbbb.......bbbbbbbbbbbbbb.............bbbbbb", +"....bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb..bb.bbbbbbbbbbbbb...bbbb........bbbbbbbbbbbbbbbbbbb...bbbbbbbbbbbbbbbbbb.....bbbbbb.....bbbbbbbbbb........bbbbbbbbbbbb.......bbb.......bbbb", +"....bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb..bb.bbbbbbbbbbbbb...bbbb........bbbbbbbbbbbbbbbbbbb...bbbbbbbbbbbbbbbbbb.....bbbbbb.....bbbbbbbbbb........bbbbbbbbbbbb.......bbb.......bbbb", +"....bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb..bb.bbbbbbbbbbbbbbb...........bbbbbbbbbbbbbbbbbbb....bbbbbbbbbbbbbbbbbbb.....bbbb.....bbbbbbbbbbbbbbb.....bbbbbbbbbbbbbbbbbbbbbb.....bbbbbb", +"....bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb..bb.bbbbbbbbbbbbbbb...........bbbbbbbbbbbbbbbbbbb....bbbbbbbbbbbbbbbbbbb.....bbbb.....bbbbbbbbbbbbbbb.....bbbbbbbbbbbbbbbbbbbbbb.....bbbbbb", +"....bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb..bb...bbbbbbbbbbb...........bbbbbbbbbbbbbbbbbbbbb....bbbbbbbbbbbbbbbbbbb.....bbb.....bbbbbbbbbbbbbbbb.....bbbbbbbbbbbbbbbbbbb......bbbbbbbb", +"....bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb..bb...bbbbbbbbbbb...........bbbbbbbbbbbbbbbbbbbbb....bbbbbbbbbbbbbbbbbbb.....bbb.....bbbbbbbbbbbbbbbb.....bbbbbbbbbbbbbbbbbbb......bbbbbbbb", +"....bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb....bbb......bbbbb..........bbb.....bbbbbbbbbbbbb...bbbbbbbbbbbbbbbbbbbbb.....b.....bbbbbbbbbbbbbbbbbb.....bbbbbbbbbbbbbbbbbbb......bbbbbbbb", +"....bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb....bbb......bbbbb..........bbb.....bbbbbbbbbbbbb...bbbbbbbbbbbbbbbbbbbbb.....b.....bbbbbbbbbbbbbbbbbb.....bbbbbbbbbbbbbbbbbbb......bbbbbbbb", +"....bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb.......bbbbbb..................bbbbb...bbbbbbbbbb...bbbbbbbbbbbbbbbbbbbbb.........bbbbbbbbbbbbbbbbbbbb.....bbbbbbbbbbbbbbbbbbbbbb.....bbbbbb", +"....bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb.......bbbbbb..................bbbbb...bbbbbbbbbb...bbbbbbbbbbbbbbbbbbbbb.........bbbbbbbbbbbbbbbbbbbb.....bbbbbbbbbbbbbbbbbbbbbb.....bbbbbb", +"....bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb....bbb.....................bbbbbbbbbbb..bbbbbb...bbbbbbbbbbbbbbbbbbbbbbb........bbbbbbbbbbbbbbbbbbbbb.....bbbbbbbbbbbb.......bbb.......bbbb", +"....bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb....bbbbbbbbbbbbbbbbb.......bbbbbbbbbbbbb.bbbbb...bbbbbbbbbbbbbbbbbbbbbbb......bbbbbbbbbbbbbbbbbbbb...........bbb...bbbbb.............bbbbbb", +"....bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb....bbbbbbbbbbbbbbbbb.......bbbbbbbbbbbbb.bbbbb...bbbbbbbbbbbbbbbbbbbbbbb......bbbbbbbbbbbbbbbbbbbb...........bbb...bbbbb.............bbbbbb", +".....bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb....bbbbbbbbbbbbbbbbb.......bbbbbbbbbbbbb.bbb....bbbbbbbbbbbbbbbbbbbbbbbb.....bbbbbbbbbbbbbbbbbbbbb...........bbb...bbbbbbb.........bbbbbbbb", +".....bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb....bbbbbbbbbbbbbbbbb.......bbbbbbbbbbbbb.bbb....bbbbbbbbbbbbbbbbbbbbbbbb.....bbbbbbbbbbbbbbbbbbbbb...........bbb...bbbbbbb.........bbbbbbbb", +"bb...bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb....bbbbbbbbbbbbbbbbbbb..b...bbbbbbbbbb..bbb...bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb", +"bb...bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb....bbbbbbbbbbbbbbbbbbb..b...bbbbbbbbbb..bbb...bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb", +"bb...bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb....bbbbbbbbbbbbbbbbbbbbb....bbbbbbb.....bbb...bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb", +"bb...bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb....bbbbbbbbbbbbbbbbbbbbb....bbbbbbb.....bbb...bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb", +"bb...bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb....bbbbbbbbbbbbbbbbbbbbb.bb........bbb......bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb", +"bb...bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb....bbbbbbbbbbbbbbbbbbbbb.bb........bbb......bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb", +"bb...bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb....bbbbbbbbbbbbbbbbbbbbbb..b..........bbb..bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb", +"bb...bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb....bbbbbbbbbbbbbbbbbbbbbb..b..........bbb..bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb", +"bb...bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb....bbbbbbbbbbbbbbbbbbbbbbbb........bbbbb.bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb", +"bb...bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb....bbbbbbbbbbbbbbbbbbbbbbbb........bbbbb.bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb", +"bb...bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb...bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb..b....bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb", +"bb...bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb...bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb..b....bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb", +"bb...bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb...bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb...bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb", +"bb...bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb...bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb...bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb", +"bb...bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb...bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb...bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb", +"bb...bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb...bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb...bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb", +"bb...bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb................bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb...bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb", +"bb...bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb................bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb...bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb", +"bb...bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb...............bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb...bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb", +"bb...bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb...............bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb...bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb", +"bb...bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb...bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb....bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb", +"bb...bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb...bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb....bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb", +"bb...bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb...bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb....bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb", +"bb...bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb...bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb....bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb", +"bb...bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb...bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb...bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb", +"bb...bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb...bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb...bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb", +"bb...bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb...bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb...bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb", +"bb...bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb...bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb...bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb", +"bb...bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb...bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb...bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb", +"bb...bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb...bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb...bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb", +"bb...bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb...bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb.....bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb", +"bb...bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb...bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb.....bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb", +"bb...bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb...bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb......bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb", +"bb...bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb...bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb......bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb", +"bb...bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb...bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb........bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb", +"bb...bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb...bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb........bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb", +"bb...bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb...bbbbbbbbbbbbbbbbbbbbbbbbbbbb...bb...bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb", +"bb...bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb...bbbbbbbbbbbbbbbbbbbbbbbbbbbb...bb...bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb", +"bb...bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb...bbbbbbbbbbbbbbbbbbbbbbbbbbbb.....bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb", +"bb...bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb...bbbbbbbbbbbbbbbbbbbbbbbbbbbb.....bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb", +"bb...bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb...bbbbbbbbbbbbbbbbbbbbbbbbbbbb...bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb", +"bb...bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb...bbbbbbbbbbbbbbbbbbbbbbbbbbbb...bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb", +"bb...bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb...bbbbbbbbbbbbbbbbbbbbbbbbbbbb...bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb", +"bb...bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb...bbbbbbbbbbbbbbbbbbbbbbbbbbbb...bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb", +"bb...bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb...bbbbbbbbbbbbbbbbbbbbbbbbbbbb...bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb", +"bb...bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb...bbbbbbbbbbbbbbbbbbbbbbbbbbbb...bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb", +"bb...bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb...bbbbbbbbbbbbbbbbbbbbbbbbbbbb...bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb", +"bb...bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb...bbbbbbbbbbbbbbbbbbbbbbbbbbbb...bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb", +"bb...bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb...bbbbbbbbbbbbbbbbbbbbbbbbbbbb...bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb", +"bb...bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb...bbbbbbbbbbbbbbbbbbbbbbbbbbbb...bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb", +"bb...bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb...bbbbbbbbbbbbbbbbbbbbbbbbbbbb...bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb", +"bb...bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb...bbbbbbbbbbbbbbbbbbbbbbbbbbbb...bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb", +"bb...bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb...bbbbbbbbbbbbbbbbbbbbbbbbbbbb...bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb", +"bb...bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb...bbbbbbbbbbbbbbbbbbbbbbbbbbbb...bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb", +"bb...bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb...bbbbbbbbbbbbbbbbbbbbbbbbbbbb...bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb", +"bb...bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb...bbbbbbbbbbbbbbbbbbbbbbbbbbbb...bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb", +"bb...bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb...bbbbbbbbbbbbbbbbbbbbbbbbbbbb...bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb", +"bb...bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb...bbbbbbbbbbbbbbbbbbbbbbbbbbbb...bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb", +"bb..................................................................................bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb", +"bb..................................................................................bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb", +"bb..................................................................................bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb" +}; diff --git a/hacks/images/apple2font.xbm b/hacks/images/apple2font.xbm new file mode 100644 index 00000000..a1b04e35 --- /dev/null +++ b/hacks/images/apple2font.xbm @@ -0,0 +1,41 @@ +#define apple2_font_width 448 +#define apple2_font_height 8 +static unsigned char apple2_font_bits[] = { + 0x00, 0x04, 0x85, 0x82, 0x30, 0x10, 0x10, 0x10, 0x02, 0x02, 0x00, 0x00, + 0x00, 0x00, 0x1c, 0x04, 0xc7, 0x07, 0xf1, 0xe1, 0x7c, 0x1c, 0x0e, 0x00, + 0x00, 0x01, 0x08, 0x38, 0x1c, 0x84, 0x87, 0xe3, 0xf1, 0xf9, 0x78, 0x22, + 0x0e, 0x48, 0x24, 0x10, 0x89, 0x38, 0x1e, 0x8e, 0x87, 0xe3, 0x13, 0x89, + 0x44, 0x22, 0x91, 0xcf, 0x07, 0xf0, 0x01, 0x00, 0x00, 0x04, 0x85, 0xc2, + 0x33, 0x29, 0x10, 0x08, 0x84, 0x0a, 0x01, 0x00, 0x00, 0x40, 0x22, 0x86, + 0x08, 0x84, 0x11, 0x10, 0x40, 0x22, 0x11, 0x00, 0x80, 0x00, 0x10, 0x44, + 0x22, 0x8a, 0x48, 0x24, 0x12, 0x08, 0x04, 0x22, 0x04, 0x48, 0x22, 0xb0, + 0x89, 0x44, 0x22, 0x91, 0x48, 0x84, 0x10, 0x89, 0x44, 0x22, 0x11, 0xc8, + 0x20, 0x80, 0x01, 0x00, 0x00, 0x04, 0xc5, 0xa7, 0x80, 0x28, 0x10, 0x04, + 0x08, 0x07, 0x01, 0x00, 0x00, 0x20, 0x32, 0x04, 0x08, 0x42, 0xf1, 0x08, + 0x20, 0x22, 0x11, 0x02, 0x41, 0xf0, 0x21, 0x20, 0x2a, 0x91, 0x48, 0x20, + 0x12, 0x08, 0x04, 0x22, 0x04, 0x48, 0x21, 0x50, 0x99, 0x44, 0x22, 0x91, + 0x48, 0x80, 0x10, 0x89, 0x44, 0x14, 0x0a, 0xc4, 0x40, 0x80, 0x21, 0x00, + 0x00, 0x04, 0x80, 0xc2, 0x41, 0x10, 0x00, 0x04, 0x08, 0xc2, 0x07, 0xf0, + 0x01, 0x10, 0x2a, 0x04, 0x06, 0x23, 0x01, 0x79, 0x10, 0x1c, 0x1e, 0x00, + 0x20, 0x00, 0x40, 0x10, 0x3a, 0x91, 0x47, 0x20, 0xf2, 0x78, 0x04, 0x3e, + 0x04, 0xc8, 0x20, 0x50, 0xa9, 0x44, 0x1e, 0x91, 0x87, 0x83, 0x10, 0x89, + 0x54, 0x08, 0x04, 0xc2, 0x80, 0x80, 0x51, 0x00, 0x00, 0x04, 0xc0, 0x87, + 0x22, 0xa8, 0x00, 0x04, 0x08, 0x07, 0x81, 0x00, 0x00, 0x08, 0x26, 0x04, + 0x01, 0xe4, 0x03, 0x89, 0x08, 0x22, 0x10, 0x02, 0x41, 0xf0, 0x21, 0x10, + 0x1a, 0x9f, 0x48, 0x20, 0x12, 0x08, 0x64, 0x22, 0x04, 0x48, 0x21, 0x10, + 0xc9, 0x44, 0x02, 0x95, 0x02, 0x84, 0x10, 0x89, 0x54, 0x14, 0x04, 0xc1, + 0x00, 0x81, 0x89, 0x00, 0x00, 0x00, 0x80, 0xe2, 0x91, 0x49, 0x00, 0x08, + 0x84, 0x0a, 0x81, 0x00, 0x00, 0x04, 0x22, 0x84, 0x40, 0x04, 0x11, 0x89, + 0x08, 0x22, 0x08, 0x00, 0x81, 0x00, 0x10, 0x00, 0x02, 0x91, 0x48, 0x24, + 0x12, 0x08, 0x44, 0x22, 0x84, 0x48, 0x22, 0x10, 0x89, 0x44, 0x02, 0x89, + 0x44, 0x84, 0x10, 0x51, 0x6c, 0x22, 0x84, 0xc0, 0x00, 0x82, 0x01, 0x00, + 0x00, 0x04, 0x80, 0x82, 0x80, 0xb1, 0x00, 0x10, 0x02, 0x02, 0x40, 0x00, + 0x20, 0x00, 0x1c, 0x8e, 0x8f, 0x03, 0xe1, 0x70, 0x08, 0x1c, 0x07, 0x80, + 0x00, 0x01, 0x08, 0x10, 0x3c, 0x91, 0x87, 0xe3, 0xf1, 0x09, 0x78, 0x22, + 0x0e, 0x47, 0xe4, 0x13, 0x89, 0x38, 0x02, 0x96, 0x88, 0x83, 0xe0, 0x20, + 0x44, 0x22, 0x84, 0xcf, 0x07, 0xf0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xfe}; diff --git a/hacks/images/atari.xbm b/hacks/images/atari.xbm new file mode 100644 index 00000000..b24c43e7 --- /dev/null +++ b/hacks/images/atari.xbm @@ -0,0 +1,6 @@ +#define atari_width 16 +#define atari_height 16 +static unsigned char atari_bits[] = { + 0x60,0x00,0x94,0x00,0x00,0x01,0x12,0x02,0x88,0x0f,0x80,0x0f,0xe0,0x3f,0xf0, + 0x7f,0xf0,0x7f,0xf8,0xff,0xf8,0xf7,0xf0,0x77,0xf0,0x7b,0xe0,0x3f,0xc0,0x1f, + 0x00,0x07}; diff --git a/hacks/images/atm.xbm b/hacks/images/atm.xbm new file mode 100644 index 00000000..ee5fcdfa --- /dev/null +++ b/hacks/images/atm.xbm @@ -0,0 +1,246 @@ +#define atm_width 223 +#define atm_height 130 +static unsigned char atm_bits[] = { + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0x3f,0xfc,0x0f,0xfc,0x0f,0xfc,0x0f, + 0xf0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x3c,0x3c,0x0f,0x3c,0x0f,0x3c,0x0f,0x3c,0xfc,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x3c,0x30,0x0f,0x3f,0x0f,0x3f,0x0f,0x3f,0xff,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x3c,0x03,0xcf,0x3f,0xcf,0x3f,0xcf,0x3f,0xf0,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xfc, + 0x03,0xff,0x3c,0xff,0x3c,0xff,0x3c,0xf0,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3c,0x03,0x3f, + 0x3c,0x3f,0x3c,0x3f,0x3c,0xf0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3c,0x00,0x0f,0x3c,0x0f, + 0x3c,0x0f,0x3c,0xf0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3c,0x00,0x0f,0x3c,0x0f,0x3c,0x0f, + 0x3c,0xf0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0xff,0x00,0xfc,0x0f,0xfc,0x0f,0xfc,0x0f,0xff, + 0x0f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0xe0,0x07,0x1e,0x78,0xfe,0x7f,0x00,0x00,0xe0,0x07,0xff,0x3f,0x00,0x00,0xfc, + 0x0f,0xff,0x3f,0xff,0x0f,0x0f,0x3c,0xfc,0x03,0xf0,0x0f,0xff,0x3f,0x78,0x1e, + 0x1e,0x78,0xe2,0x61,0x00,0x00,0x78,0x1e,0x3c,0x3c,0x00,0x00,0x0f,0x3c,0x7c, + 0x3c,0x3c,0x3c,0x0f,0x3c,0xf0,0x00,0x3c,0x3c,0x3c,0x3c,0x1e,0x78,0x1e,0x78, + 0xe0,0x01,0x00,0x00,0x1e,0x78,0x3c,0x30,0x00,0x00,0x0f,0x3c,0x3c,0x30,0x3c, + 0x3c,0x0f,0x3c,0xf0,0x00,0x0f,0x30,0x3c,0x30,0x1e,0x78,0x1e,0x78,0xe0,0x01, + 0x00,0x00,0x1e,0x78,0x3c,0x03,0x00,0x00,0x3c,0x00,0x3c,0x03,0x3c,0x3c,0x0f, + 0x3c,0xf0,0x00,0x0f,0x00,0x3c,0x03,0x1e,0x78,0x1e,0x78,0xe0,0x01,0x00,0x00, + 0x1e,0x78,0xfc,0x03,0x00,0x00,0xf0,0x03,0xfc,0x03,0xfc,0x0f,0x0f,0x3c,0xf0, + 0x00,0x0f,0x00,0xfc,0x03,0x1e,0x78,0x1e,0x78,0xe0,0x01,0x00,0x00,0x1e,0x78, + 0x3c,0x03,0x00,0x00,0x00,0x0f,0x3c,0x03,0x3c,0x0e,0x0f,0x3c,0xf0,0x00,0x0f, + 0x00,0x3c,0x03,0x1e,0x78,0x1e,0x78,0xe0,0x01,0x00,0x00,0x1e,0x78,0x3c,0x00, + 0x00,0x00,0x0f,0x3c,0x3c,0x30,0x3c,0x1c,0x1c,0x0e,0xf0,0x00,0x0f,0x30,0x3c, + 0x30,0x78,0x1e,0xfe,0x7f,0xe0,0x01,0x00,0x00,0x78,0x1e,0x3c,0x00,0x00,0x00, + 0x0f,0x3c,0x3c,0x3c,0x3c,0x3c,0xf0,0x07,0xf0,0x00,0x3c,0x3c,0x3c,0x3c,0xe0, + 0x07,0xf8,0x1f,0xf8,0x07,0x00,0x00,0xe0,0x07,0xff,0x00,0x00,0x00,0xfc,0x0f, + 0xff,0x3f,0x3f,0x3c,0xc0,0x00,0xfc,0x03,0xf0,0x0f,0xff,0x3f,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0xe0,0x1f,0xc0,0x00,0xff,0x00,0xff,0x00,0x00,0x00,0xc0,0x00,0xff,0x3f,0xff, + 0x3f,0xfe,0x3f,0x0f,0x3c,0xff,0x03,0xc0,0x00,0x0f,0x3c,0xff,0x3f,0x78,0x78, + 0xf0,0x03,0x3c,0x00,0x3c,0x00,0x00,0x00,0xf0,0x03,0xf1,0x30,0xf1,0x30,0x7c, + 0x3c,0x3f,0x3c,0x3c,0x0f,0xf0,0x03,0x3f,0x3c,0xf1,0x30,0x1e,0x60,0x3c,0x0f, + 0x3c,0x00,0x3c,0x00,0x00,0x00,0x3c,0x0f,0xf0,0x00,0xf0,0x00,0x3c,0x30,0xff, + 0x3c,0x3c,0x3c,0x3c,0x0f,0xff,0x3c,0xf0,0x00,0x1e,0x00,0x0f,0x3c,0x3c,0x00, + 0x3c,0x00,0x00,0x00,0x0f,0x3c,0xf0,0x00,0xf0,0x00,0x3c,0x03,0xff,0x3f,0x3c, + 0x3c,0x0f,0x3c,0xff,0x3f,0xf0,0x00,0x1e,0x00,0x0f,0x3c,0x3c,0x00,0x3c,0x00, + 0x00,0x00,0x0f,0x3c,0xf0,0x00,0xf0,0x00,0xfc,0x03,0xcf,0x3f,0x3c,0x3c,0x0f, + 0x3c,0xcf,0x3f,0xf0,0x00,0x1e,0x00,0xff,0x3f,0x3c,0x00,0x3c,0x00,0x00,0x00, + 0xff,0x3f,0xf0,0x00,0xf0,0x00,0x3c,0x03,0x0f,0x3f,0x3c,0x3c,0xff,0x3f,0x0f, + 0x3f,0xf0,0x00,0x1e,0x60,0x0f,0x3c,0x3c,0x30,0x3c,0x30,0x00,0x00,0x0f,0x3c, + 0xf0,0x00,0xf0,0x00,0x3c,0x30,0x0f,0x3c,0x3c,0x3c,0x0f,0x3c,0x0f,0x3c,0xf0, + 0x00,0x78,0x78,0x0f,0x3c,0x3c,0x3c,0x3c,0x3c,0x00,0x00,0x0f,0x3c,0xf0,0x00, + 0xf0,0x00,0x3c,0x3c,0x0f,0x3c,0x3c,0x0f,0x0f,0x3c,0x0f,0x3c,0xf0,0x00,0xe0, + 0x1f,0x0f,0x3c,0xff,0x3f,0xff,0x3f,0x00,0x00,0x0f,0x3c,0xfc,0x03,0xfc,0x03, + 0xfe,0x3f,0x0f,0x3c,0xff,0x03,0x0f,0x3c,0x0f,0x3c,0xfc,0x03,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}; diff --git a/hacks/images/blocktube.xpm b/hacks/images/blocktube.xpm new file mode 100644 index 00000000..4ca07c7e --- /dev/null +++ b/hacks/images/blocktube.xpm @@ -0,0 +1,320 @@ +/* XPM */ +static char * blocktube_xpm[] = { +"256 256 61 1", +" c None", +". c #060606", +"+ c #929292", +"@ c #424242", +"# c #5A5A5A", +"$ c #CACACA", +"% c #7A7A7A", +"& c #B6B6B6", +"* c #A6A6A6", +"= c #626262", +"- c #1E1E1E", +"; c #8A8A8A", +"> c #666666", +", c #E2E2E2", +"' c #262626", +") c #464646", +"! c #6A6A6A", +"~ c #969696", +"{ c #2E2E2E", +"] c #6E6E6E", +"^ c #7E7E7E", +"/ c #4A4A4A", +"( c #DADADA", +"_ c #9E9E9E", +": c #C2C2C2", +"< c #AEAEAE", +"[ c #525252", +"} c #3A3A3A", +"| c #828282", +"1 c #767676", +"2 c #D2D2D2", +"3 c #BABABA", +"4 c #EEEEEE", +"5 c #868686", +"6 c #8E8E8E", +"7 c #727272", +"8 c #121212", +"9 c #9A9A9A", +"0 c #363636", +"a c #5E5E5E", +"b c #A2A2A2", +"c c #565656", +"d c #AAAAAA", +"e c #B2B2B2", +"f c #4E4E4E", +"g c #1A1A1A", +"h c #EAEAEA", +"i c #BEBEBE", +"j c #C6C6C6", +"k c #3E3E3E", +"l c #CECECE", +"m c #D6D6D6", +"n c #323232", +"o c #2A2A2A", +"p c #DEDEDE", +"q c #222222", +"r c #E6E6E6", +"s c #161616", +"t c #F2F2F2", +"u c #0A0A0A", +"v c #0E0E0E", +"@@k}}0nn{ooqq-gg-k1~9~~+6;;5||^%117]]!>==a##c[[f//)@@k}}0nn{oo'qq-ggs888vuuu8}1~bd&jprrr,pp((mm2ll$$j::i33&&ee>====aa#####cccc[[[[[[[[ff[f[f[f[f[[f[[[[[[cccc#####aaa===>>!!!!]77111%%%^|||5;;66++~999_bb", +")@kk}00{{o''qq-gq)%99~++66;55|%^%177!]!>==a##c[ff/))kkk000{{{'q'---sssvvu8vsn]*:l(p,rhh,,,ppmm2ll$$j:jii333ee<<=>>!]]]]]771%%^^^|555;;6+~+~9_9__", +"@kk}0nn{ooqq-ggs'[|~9~+6;;5|^^%177]]!>==a##c[[//))@@k}}0nn{oo'qq-ggs8s8sg'{@>d(4hhhhrr,,p(((22ll$$jjii333&&e=a##c#c[[[[f[ff/f/f////)/)//////////fff//f[[f[[c[c####aaa====>!!!]7771%%%%|||55;;66++~99_", +"@k}}0n{{{''q--g-{a;9~~+6;;5||%%%17]]!>>=aa#c[[ff/)@@k}}nn{{o''qq-gggq'{})f#!~l4t4t4hhrr,,pmmm22ll$j:::i3&eee<>>!!]]]]1711^^^||55;;6++~~99_", +"kk}0nn{oo'qqggsg0!6~+++6;;||^%%177!!!>=a##c[[f//)@k}}}00n{ooqq--qqon@f#=>]]^ac[ff////)/@))@@@@@@@@@@@@@@@@)@)))/)/)////f[[[[ccc###aa==>>!!!]]771%%^|||555;;++~~9", +"@}}}0n{oo''---s-k1~~~+6;;55|^^%177!!>==aa##cff/)))@k}0nn{o{'ooon}@[a=7771]76:r4t4hhr,,,p(((222$$jj::ii33eee>!!]777111%%^|55;;66++~~", +"k}}nn{{o'qqgggsq/%~~~+6;5||^%111]]!>>=a#cc[[f//)@@k}00nn{oo{n0@[=]7%%%%117%924tt4hrr,,p((mmlll$jj::i33&&e<>>!]]771%%%^^|55;;66+~", +"}k000noo''q-gsgq[5~++66;55|^^%177]]>>==aac[[ff/))@kk}00nn0k)c>]%^^|^^%11]7^<(t44hhrrrppp(m2ml$$$::i333eee#/)@kkkk}kk}}}}k}kk}}kkkkk@kk@k@@@)))//f/f[[[[[c##aa==>>!!!]]711%%%^|55;;6+++", +"}}nn{{o'qqqgg8s'c5~++;;;5|^%%177]!!>=aa#cc[ff/)@@k}00n00@fa]%||55||^%%71]]|3,tt4hhr,,((mm2l$$$:::ii3&&eec/kk}}00}0}000000000}0}0}}}}kkkk@@@)@))///f[[[ccc##aa==>!!!]]]11%%%|^555;6+", +"}}}nn{{oqqg-gsgn>;~~+6;;|5|^%117!!!>==a##ccf//)@kkk}k@/a!%5;66655|^%%11771+jh444hr,,,p((2m22l$$j::33&&&<<#/k}00n0n0n0nn00n0n0000}0}}}kk}@@@))))//ff[[[cccaa==>>>!]!]7711%^^||5;;66", +"00nn{o''q-ggs8s0]6++6;;5|^^%17]]!!>==##c[fff))@@kkk@f#]|;6666;;|||^%%17]]%b244hhrr,pp(mm2l$$$:::i33&eeedd*bb__9~~+66;;555||^^^^%^^||;69e2,rr,,p,(p((m222ll$$$j:j::ii33&3&eeee!!]7711%%^^|55;;", +"}00n{oo'qq-ggsg@1+~+66;5||%^%177]!>==a##cc[/f))))f#>1;+~~~++6;55|^^%117]]|<,44hhr,r,(((m22ll$j::ii3&&<c@}nn{{{{{{{{{n{nnnnnn0000}}}}kk@@@)))//f[[c[##aaa=>>!]]]7711^^^||;5;", +"00n{{o'q--gs88-/%+++;;55|^%117]!!>>aa#cc[ff//))/#]^;+~99~++66;55|%%%177]7;3,44hhr,pp(mm2l$$j::i3&&e<c)0noooooo'oooooo{{{{{nnn00}0}}kk@@)))///f[[ccc#a===>>!!]771%%^^|55", +"0n0{oo''q-ggssq[|++66;5|^^%%17]]!>==aa#c[[f/f[a]|~_bb__~~~66;5||^^%177]]16jh4hh,,,p((mml$ljj:i33&ee!!]]7171^^||55", +"0n{{o'qqggs888qc|+66;55|^%1177!!>>=a##[[fffca]|+_bbb_99~++6;;5|5^^%1177]%_lhhhr,pp((22$$$::i33eee[k{q'qqqqqq''''oooo{{{{nnn0}}}}k@@@))//f[f[c##aa===!!!7771%%^||", +"0nn{o''q--gs8s{a;~+;;5||^^%17]]!>>=aa##ccc>759bd*dbb__9~++66;55^^%117171|dmhhrr,p(m22$l$::i33ee>>!]]711%^^|5", +"nn{oo'qqggssvsn>;6+;;5|^%%177]!!==a##cc#=]59*ddd**bb99~~+6;;5||^%%1%771^63pr,,p((m2$$j::i3&&<>!!!]711%%^", +"nn{{o''--gs88s0];+6;555|^%117]!!>==aa#=]59dee<<<**b_9_9++6;;55^^%1%1%^^59iprrppm2ll$j:i3&ee!!771%%^^", +"nno''qqggs88vs0]66;;5|^^%117]]!>==aa=!^+*<&ee!!!]]71%%", +"n{{{'qq-ggs88s@%666;5||^^%77]!!>>==!^~d&33&ee!!]771%%", +"n{oo'q--g88vvg/%66;55|%%%1]]!!!==!7;be&33&ee<!!]711", +"{{o''q-gggs88-f^666;|||^%11]]!>!759e3i:ii&&e>]]]771", +"{oo'qq-gs88v8-f^;;;5|^%%%77]!!]^6d&::ii33eedddbb_9~~++;;555||||566~bd&i:$$$::i&&edd**__99+++66;;555|55555;;5;;66+~~_bb**d<<[}qg88ssssg-g-qqq'ooonnnn}}kkk@@)/fffcc##a==>!!]77", +"{{o''--gs8vvvqc|6;;55|^%117]]^;b&:$jj:33&ee!]]77", +"{o'qq-ggss8v8o=56;5|^^%17]7%^~d:jjj:i33ee;;;5||^%%%%^6*3$$$$j:ii&&ed**b_9~~+6;;;;;;6;++~9bd<&3i:::i33&e>>!]]", +"o''q-ggss88ssn>5;;5|^^%%^5~!!", +"{oo'q-gs8gssqk];6;55555;~di$lll$::i3&e>!]", +"o'qq-ggggg-qo)75;6;;66~_e:$l$$::i&ee<*b_9~~++;;;5;;;;;++~99_b*d!", +"{o''--gg-q'n@a^6+~9~9*fn-8888sgg--qq''{{{0n}}}k@))f/[[[###=>>>", +"'qqq-gq-'{}/#1+9_b*de3:j$$$:i3&&c}q88v8ssgg--qqooonn00}}k@@)//f[c###a=>", +"oo'--q-onk[!1+b<<&3i:j$$j:ii3&edd*b__9~+666;;;;;66+++~9~_b**d<>", +"''q-q'o0/#75~*e&333ii:iii3&e^;bfogsss-gqqq'o{{n0}}kk@)/f[[[c#aa", +"q''nkc]59_**<*ddd***b*bb___99~~~+66;;;;55555;55;;;66+++~99_bb*dd<<>>>====>>19jm22ll$$j::i3&&&edd**__9~~+6;55|^^%117]]]]7]771%^|56_bb<$(,,,,pppp(((p(p((p,,,rrrrrh44ttrld577!=/n-s8gsg-qq'o{{nn0}kk@@)/f[[c##", +"oo{0[>%69bbbb*b*b**bb___b_9_99~+++66;;;;55555;;;66666~~~~99_bb***<<>===aaaa]_jmm22l$$$j::ii3ee<==aa#ac##!_$mm2ll$j::ii3&3eee>==#acc[c7d$m2ll$$jj::i3i&&&<<1|5|5555;;6+6++++~++~+++++++6666;;;;5555|55||5|5|55555;;66666~~~9_*d1%^%^%^|||;;;66;+++++~+~+~+++++6+66;;;;5;5555||5|||||5||||5;;5;66+~bb*dee&&333333&&&eee<>>aa#cc[[c1dl2llllj$j::33&&ee<!>>>!];3mp((2m2l$$jj:::jjj$j$$$l2m((ppp,rhh444,&57]7111![nqgg-q'oo{nn0}k@@)/ff[c", +"qn@/=>!>>!>!]]711%%^^|5|;5;;6;6+66++6666++;;66;;555|5||||^^|^%^^^^^^^%%|55;++~__*dd==accc[[[>_:lll$$jjjiii3&&ee<<***bb_999++66;;55|^^%117]]!!>>>=!!5i(((m(l$$j::ii:iii::jj$$lll2mm(p,,rhh44h2*^177%%%!c0'-qqqo{{n00}}k))//f[[", +"q{@/c####a#a==>!!!777%%%^|||;55;;;;6666;666;;6;;;5;555|5||^^^^%%%%11111%%%^|5;6+~__b***<<<<<==a=>|e(p(22l$$j:iii3iiii:::jj$ll2mmm(pp,rh444,i;77711%%][}qqqqqoo{nn0}}k@)/f[[", +"'nk)c#c[cc##aa=>>]!!7111^^^||55;;;66666+666++6++666;6;;5;|5||||^^%^%%%111%^^|5;;6+~9_bb**d<<<<=aacc[ff=;&$llljj::iii&&&e<>==#=1dl(((2l$:i33&e3e&333i::jj$$ll2(p(p,rrhh4h2b%771%%%^7c}'qq'o{{n0}kk@))//f[", +"qnk@/f//fff[cc#aa=>>!]]]11%^^^|555;;;666++6++6+++6+6666;6;;;5||^|%%%111111%%%^^|5;;+~99__bb**ddddd***bb_99~+6;5|^%177!!>a=#c[[fa;e:jjj$:i:33&&ee=aa#a!9j((m2l$ji3e&aaac[[#|>>==a#=^el(m2lji&eed<!!]171%^||55;;;+++~~~~999999~99~~~~+++66;;;55||^^%%%1%1%%^%^|5566++~~_9_bbb*b*bbbbb__9~~+66;|^^%7]]]==a#[[c%b&3::i::i33&&e<>==aa#a!+32(22l:&dd**dd<>!!]11%^^|5;66+~+~~99_99__9____9_99~9~+~+++;;;5||^^^%%%%1%%^|55;;66+~99_9_bbb*bbbb*bb___~~+6;;5|^^17!!==##[#!6*&3::i::ii3&eee<>==aa#a7~3$2lj3d_9___b*ddee&&33i::$$l2m((pp,rrh4,e|7771%^^||51a@{oo{{n0}kk@)/ff", +"okcc[[f/[[[c#[#aa=>>!7]7%%%|5|;;6++~~9999b___*bbb_b____999~++++;;;55|^^%%1%%1%%%%^^|5;;6++~999___bbbb_bb__999~++6;;|^^117]>>aac#=^+b<&333i3&&&e<==aa##a]5bee>=]!!]77%%%|55;6+++9~9b_bbb***b**b*b*bb__9999~+++;;;5||^^^%%%%%^%^||5;5666+~~999___b_bbbb____999~+6;55^^11]]>=a#ca]5~b<&iii33&e&e>==aa##a>7%^^%^|;6~~9bb*d<==>!>!7]]17%^^||;;;++~999_bbbb*********bb*bb_99~~++66;55|^^%%%1%11%%%^^^55;;66++~999_9_______999~~+++6;55||%17]]!>aaa>15+bd<&333&ee<>>>=aa#aa==>!!7^5;+~99_**dee&&3i:jjjll2m((,rrhhhm*%!]]71%^||5;;%#k{onn0}kk@))/", +"1%17!!>!!!>!!!]!]7771%%%^||;;6+~~99bb*b**d**dddddd***bb__99~+++6;;5||^%%%1%%1%^%^||55;;66+~~~9999______b___9999~~+6655|^^17]!>=aa=!15+_d<&&33eee==>=aaaaa=>]]%|566+9__**d=aa=!156_*dee&e<<>>==>>==>>>!]1%^56++9__**<>]15+_d===>=>!]71%||56+~9__**<!%|69*d!!]!]71^|5;66~9_bb*d>]%569*d<!!=>!7]%%||;;6++~9~99____9__9_99999~9~~~+++666665555|^%%77]!>>=a=>!]%|69bd>>==>!7^5+9bd<<>=a####]^55++~9__bbbbbbb*bbb_b___999~~~~++666;66;6;555^^%%11]]!>>=====>!7^569bdd/k}k@)", +"6;55|^%%%%1171|6+~*d<&3i:::::i::333&e&<>=aa#c[#]5+9_b*dddd<>===>!]1^;+9bdd<<<**b___9~~~6666;;555||^^^%%%11177777717%1%%%||5;;6++99_b*d<<&&3i:::$llmm(pp,rh,:6!!]771%^^|5;;6++99_95=/@@))", +";;5|^%%17717]75~bde33:jjjj:jj:ii3&&e<==a##c[[f[!;_bddddd>====a=>!]1^5~9b**dd***_99~~+++6;6;55||||^%^%%%%11%%11%111%%%^^||5;66~~99bb**d!!771%^|||;6++~99_9^=)k@)", +"6;55|^%1177]]75*&3j$$$llll$$:::i33&&e>aa##[[ff[!+dee&&&&eee<<==a===>]1%5;~_*dddddb*b__~~~++6;66555||||^^^%%%%11%%1%%%%%^|||5;;;+++99_b*dde&&3i3:j$$22m((p,rrp&|!!!771%^^||;;6+~~9__b~%a/)@", +";5||^%%11]!!!!5d:j$222llll$j::333ee>=a##cc[f/)/a+<&&33&&&ee!>==aaa==!!7^56~_**d*d*___99+~++66;;;;55|^|^^|^%%^%%%%%%%%^^^|55;;66+~9_9bb*dd!!]]71%%||5;;6+~~__bb+7[))", +";;55|^%177]]!]5elmm(mmm22l$$j::3&3e<==aa====>!7%|;+9_*ddd**b__99~~++66;;;5555|||^^^^%^^^%^^^^^||||55;6++~~9_b**d>!]71%%^|55;;+~9_9_**b+][/", +";;|^^^11]]!>>>^d2(pmm(m22l$j:ii3&ee>aa#cc[f//))f|<:::ii3&eeedd*bb__9~++6;;555||^^%1%1117]]7]!]!!!!!!>>>>>==a#a#a==!!7%|;~9_**d**b_99~~+++666;;;5|5|||^|||^^^|^^||||555;6;66~+~9__bbddd<&&i3:jj$$22m((p,r,j~]>>!]]71%%||5;66+~9__b**b5>f", +"65;5^%%117!!>>%dmr,,p((mll$$:jii3&e<aa#c[[ff))f7djj::ii3&&e<>!!>>>===a=aaa#a=>]71^;69bbddd**bb99~~~++666;;;;5;||5||^|||^|||||||55;;6;++~99__***d!!]711^^|55;6++~99_b*ddb5=", +";5||^%177]]!>=7b2,,p((m2ll$j::33&ee==a#cc[f//)@)>_ij:i333ee!>>=>===a==aaa==aa####aaa=>]7%56~9_b*d*bbb99~+~++666;;;55;5|5|5|||5||||5555;;;;++++~_9__bdd<=!!]]11%%^|5;;6++99_bb*dd_|", +"6;5||^%%77!!!>7_lr,,p(m22$$$j:ii3&e=====aaaaaaa####a#####a=>!7%|;+9b**ddd*bb_99~~~~6++6;6;;;;55|555|5555555;;;6+6+~~999b***ddee&&3ii:$$$22mp(p,,2b7=>>!]77%%^|55;6++~9_bb*dd==>+:p,p((m22$jj::i3&&eedd*bb99~+66;5||%%%1]]!!>==a#c[[f//)))[|e::i33&ee>=>==####c##c#cc#ccc[ccc##a=>]7^5699bb***bb9_~~~~++6666;;;;555;555;5;555;;;6666+++~~9___b*dddee&33i::j$$l22m(p,pj~]=>>!!7711^^|5;;6+~~9_bbdd<!5:pr,p(m22lljj:i33&ed=aa#c[[f//@@/1*:::ii3&&e<<**b__99~~66;;55||^%177]!!!>>a##aa##ccc[ccc[cccccccc#a=!]1^5+~_**dd**bb__99~~~~++6+6;;6;6;;;;5;5;5;;;;;66++~~9999b***d>=!!]711^^|55;6+~~9_bb*d<<&e", +";55|^%117]!!>=>^&(pp(mm2l$$j:ii3&e&=a##cc[f//))@@=~i:i33&ee=>>=##cccc[[ff[ffffffff[[c#a=!]%|;~9_b***bbb__99~++~++666+;6;;;;;6;6;6;66666++++~~____bb**dd==%dm,,p((22l$j::i33&<===a#[cff//@@)#;e::i33&ee=aaa##cc[[[[f/f/f//fff[[c##=!7%|;~9bb*ddd*b__99999~~~+++6+6+6666;666;6666+6+~+~~999__b**<>!]7111%^|5;666~~9_b**d<<&&", +";;||^%%17]!!>=a79lpppmm2ll$j::i3&&e=a###[[ff/)@kk/%diii3&&e<>=a##cc[[fff///)//)/))/f[ca=>]%|;+9_b***bbbb__99~~~+~+++6+66666+666+66+++~++~~999_bbbbd*dd>=!~jp,(pmm2$ljjii33ee<>==acccf///)@@/>_3:ii&ee<=aaa##c[[[f/ff//)))@))//fc#=!7%|;~9bb***d*b______999~9~+~+~++++6+6+6++6++++~~9~9_9_b*d*>!]7711%||55;6+~~99bb*<<53(p((222$$j::i33ee>>=aa#cccfff/))))@@@@@k@)/c#a>]%|;+9_bb*b*bbb_9_9999~~~9+~+++++~+~+++~~~+9~~99___bb*bbddd<!!]71%%^^55;66+~99_bbdd=>^&(,(p(2l$ljj:i3&&e=aa#cc[f//)@kkf%diii3e&e<=>=aa##[c[fff))@@@)@@@)@/fc=]7^56~9b*******b_b____9_99~9~~~~~~+++~+~++~~~~9~_99__bb*d*d<!!]771%%|55;;6+~99_b*dd>aa#cc[ff))@@k}@>93333ee==a#a#c[[[f//)))@kkk}k@@)f#a!1^56+9_b****bbb__9_9_9999~~9~9~~~9~+9+999~99999_b_bbbb*dd<!]771%%^||;;6++99__b*d<==aacc[fff/)@@k@c;ei3&&ee>>>=a###cc[fff//)@@@kkk@)/fc>]%5;+9_b*****bbbbbbbbbb__9_999~~~~~~9~9~~~999_9_9_bbb*ddd<aa=>!!!]711%^||5;6++~9__bb*d>=a#>5i(((m22$jj::i3&ee=aa#cc[f/))@kk}})1*&3&&eedd**b_99~+++6;;|||^^%%71]]]!>===a###c[[[f//)))@kk}kk)/[#>]%56~9__bbb**bbb________b99_9__9_9_9999__99_9__bbb****d!!]711%%||55;6++~9_bb*dd=aa#cc[ff)))@}}@=93i3&&e<===a##cccfff//)@@@k@k))[c=!1|;+~_bb***b**bb*b*bb*bb_bb__99_99999_999___bbb_bbb**ddd!]]]71%^||55666+~99bb*dd<&e&", +";5||^%177]!!>=a#a7dl(mm22l$j::333&e>==#ac[[f//)@kk}}k[5<&&ee>=aaa##[[[fff/))@@@@@@//[#>]%|;+99bbb**bb**bbbbbbbbb_____b___b_b_____b__bb****d*dd<<!]771%%^|55;6++~99_bb*dde&&", +";;;5|^^%17!!>>=aa]_lpp(mll$$j::3&&e>==aac[[f//)@@kk})7b333ee>==aa##cc[f////))@))//[#>!1^5+~9_bb*****bbb*b*b**bb**bbb_b_________b_b*bbbb***d<<<!!]71%%%^55;;6+~~___**d==a#=;im(mmll$jj:i3&&eaa##c[[f/))@k}}}ka+<&&ee==aa##cc[[ff//))))//fc#a!7%|;+99_b*bb*b*b*b*b**b**bbbbbbbbbbbbbb**b*bbb*d*ddd#c##a==>!!]77%%^^||;;6++~9__b*dd=a#=|&m(mm2ll$::ii3&&e=>a#ccc[ff/@@kk}00f%d&&&e>>=a##c[c[f/f//)/f/fc#=!]%|;6~9_************d**dd*dd**bbbbbbbbbbbbbb*******ddd>!]]771%^^|5;;6++~99_b**d==a##1*l(mmll$$::i33ee<==aa#c[ff//)@k}}00@=9eee<!!]777%%^||5;;6++99bbb*d<=aaa>~j(m22l$jjj:i&3eeddbbb_9~~~66;5||^%177]]!>>=a#c[[f/)@)@k}}0}[|d&&&>=a#a#c[[f////f/f[ca=!]7%|5;+9_bbb**d**ddd*ddd!!]]71%%^||5;6++~999_b*dd==aa#ccfff/@@kk}0nnk!9eee==a#c[[ff/////ff[[#a>>]%%|;66~9_b_b*******ddddd<==aaa===>>!!771%1^|^55;6++~9_bb*ddeee&3", +"6;;5|^^%11]!!!==##a1<2mmm2$$j::ii&&e=aa##[[f///@@k}}00}c;deee==>>>=>>]]]]771%%^5|;;6+~~99_b*d<>=a###!9$m2lll$j::33ee<=aa#cc[f/))@kk}}nnn@7_ee>=a#c[[ff/////f[[[ca==!77%^|5;6~~99__bbb***dd=>>>>]!]71%^%^||5;6+~99_bb*dee&&3", +"66;|5^%%177]!>==a##=;immmll$j:iii3eedddbb_99~~+6;;55^%%17]!!>>=a##[c[/f))@@}}0nn}#;de<<<***b_99~~6+;55||^%171]!!>=a##cc[[f////ff[[#aa>!!7%^^5;6++~9__bbb__bb*=aacca%el2ml$$jj:333&&eddbb_99+++;;5|^^%117]!!>==a##[[[//@@@k}}0nnn)]_!>>>!!!!]]711%%^|55;6+~~_b**d==aa#c]bl(22ll$:::3&ee==a##c[ff//)@kk}00n0}#;de<>!777%^|55;;;+66+6;;5^%%;9*e&&&ee&e=a##cc=6:222l$$:iii3&e>=a##c[[f//@@kk}00n{n@]9!]711%%^|||5||^^%1]!=a=]|~*>>>>>>!>!!]]771%^|||;6++99_*dde&", +"+6;;||^%117]!!=>a##c=^e2m2$$jjj:33eee==##cc[ff)))@}}}0000ka;*>a##cc[f[f/f////ff[fccc#aa>>>!!]]111%%%%1777!=ac[)))[>^+_dee&e&e&eeeee!>======>=>>!!!]]717%%^55;6+~9_b*==aa#[#]bj22llj::i33&e<==aa#[[[///@@@k}}0000}f19**bb9~~+6;;5^%%7]!!>=a##c[[ff/f/)/////ffff[[[c#c#a===>>!>!!!!!!>aaccf)@k}0}kfa159b<==aaa###cc#cccc#a#aa===>!!]77%1%||5;++~__*d<", +"66;;||^^%77]!]=>aaccc=6i222$$j:ii3&&e>=aa#c[[f//@@kk}k}k@)f>6*b*__~+6;5|%^177]!=>aaacc[[[ff/ffff/ffff[[fcc[c##a##aaaa=a=aaa#c[f//)@k}00nnn0)[=1569b*d**b__~+65|^%777!]!!>!=>>====aa#c#c[c[[[ffffff/fffff[c[c##aaa>>>>!!771%^^5;6+~~_b*<", +"66;;||^%%17]!!==a##[ca%e$2ll$jjiii&eedd**b_9~~+66;55|^%117]]!>=a#c#[ff/))@kkk}kkk@fc>^9_9~++;;||^117!!!>=a#cc[[fff///)))///////fffff[[[[cccccc[cc[fff//)@k}}}}nnnnnnn0k)[a!%|5;;;||%77!>=accc[fff/f////))))))@@)@@@k@@k@@@)))))///fff[[c###a==>>]]77%%^||;6+~_b*", +"+6;;5|^^1177!!>>=a##[c]b$22l$$::i33&eedd*b__9~++;6;||^^%177!!>===a##c[ff/))@@@@@/fc=!^699~+6;||%%17!!>=aa#a#ccc[ffff/ff///////f//ffffffffffffff/////))@@kkk}0n00n{n{{{{n00@)fc#a#aacc[//)))@@@@@@@kkkkkkkkk}kkkkkkkkk@@k@@@@@))/f//[[[ccc#aa==>!!]771%^^5;6+~9_b", +"+6;55|^^1177!!==a##c[[a6illl$$::i3&ee=a#c[c[ffff//////)))/)///////))/)))))))))@)@@kkk}}}}}000nn0n0nnnn{nn000}k}}k@kk@kkkkk@}k}k}kkkkkkkk}kk}kk}kkkkk@kk@@@@@)))///fff[c[c##a==>>!]]71%%^|;;6~9_", +"++6;55|^%%7]]]!>=a##[c#1d$2l$jj:i333ee<<**b_99+++;;5|^^%%1]]!!>=aa#ccff/)/))//[[#=>7%|5;;;5|^%117]!!==aaa##c[[[[ff/f////////))/))))//)))))@@)@@)@@@@@k@k}}}}0000nnnnnn{0{nnnn0n0}}}}}}k}kkkk@k@k@kkkkkkkk@kk@kk@k@k@k@)))))///f/fff[[[cc#aaa===>!!]7771%^||;6+~_", +"+66;5|^^%177!>>>=a##[[[>~illljjji33&e=a##[[f///))/)/f[#=!!1%^|5|||^%%17!!>>==###ccc[fffff//)//))))))))))@@@@)@@@@@@@@k@@kkkk}k}}}}}}00}000n00n00}00}}}}}}kkkk@k@@@@@@@k))@@@@@@@)@@@@k@k@@@@@@@@))))/f/fff[[[ccc#a#===>!!!]77%%^^55;+~9", +"+66655|^%%17]]!>==#ccc[#|&ll$$j::i3&ee>=a#cc[ff///ff[[#a=!!%1^|5|5|%%%7]]]!!==aaa##ccc[[fff//f/////)//)))//))))))@))@)@)@@@@@@@k@k}}}}}}000}00000}00}}}}kk@kk@@@@@)@)@@))@@)@))))@@)@)@))))@)))))/)//f/fff[[[c[##a#a=>=>>!!]7711%^||5;6+~", +"+66;55|^%%17]!!>=aa#c[fc7b$l$$j::33&ee!]1%%^|%^%^1%1]]!>>>>a#a#cc[[[[ffff////))/))))/)@))))@)))@)@)@@@@@@@@kkkkkkk}}k}}0}00}}}kkkk@@k@@)))))/)))))))))///))))/))))))@)))))))/)////fff[[[[cc#c#aaa==>!!!!]]7111%^||56++", +"~~66;5||%%17]]!>==##cc[f=+i$l$jj:ii3&ee<<*bb__9~+6655|%11]!!>=##c[[ffff[[[c#a=>!77%%%%^^^^11777]!!>>a==###c#c[c[fffff/fff/f/////f//////)////)//)//)@@@@@k@}kkk}}}k}}}kkkk}@@@@)@@))//))/////////)///f/////f/////)////f/ffff[f[[[c#c#a#aaa=>=!!!!]77711%^^||5;;6~", +"++6;55|^%%17]!!>=>a#cccf[1<$$lj::i33&e>!771%%%%11%1177]!!!>>=aaa###cc[[[[[fff/f///fff///f/f/f/f//////)/))/))@)@@@@@kkkkk}kk@kkk@)@@)@)//////ff//f//f//ff/f[/fff[fff/ff/////////ff[f[[[ccc###aa===>>>!!]]]7711%%%%^^|5;6+", +"~++6;5||^%117]!!=aaa#[f[[!~j$$$j:i3i&ee##[c[fffffccc#aa>!]!7771%%^%%1%77]]]!!>>>>=>=a#a##c#cc[ccc[[[c[[[[c[[c[c[[[[[fffff/f////))))@@@@@@kk@k@k@@)@@)/)/////ff//f[ff[[ff[f/[ff[[[[[[[[c[f[[[fff[[[[[ccc##aaaa=>>=>!!!]]]]771%1%%%%^||55;;6+", +"~~66;55^^%11]]!!>=a##cf[f#|&$$$j:i33&e<!!]777711%111177]]!]!>>===a=aa####c#ccccc[cc[cc[ccc[[cc[[[[[ffff/f//)/)))))@@@@)@@)@)@)@/f///ffffff[c[[f[ffffff[[[[c[[[[c#ccc[c[[[[[[[[[ccc###a#a===>=!>!!]]]71111%%^%^^|^||5|;66+", +"9++6;55|^^%17]!!>>=##ccff[]_j$ljj:ii3&e=a#ccf[fff[[[[c##===!]!771111%11111717]]!!]!]!>>=====a=aaa###aa##a#aaaa#a##c#cccccc[[[f/ff//)))))))@@@@@))//f//fff[[[c[[f[[[[c[[ccccf[c[[[cc#cc##a##a###c#cc##aaaa==>>!!!]]]77711%%%^^|^|||55|5555;;;6+", +"9~+6655|^%1177!!>==#accf[f=;&$$j::i3&&ed*b__9+6;||%1]!!=a##[[ffff//f[[[c##a===!!!!]]77117111711777!]!!!!!!!>>>=>=====aa====aaaaa#a#####cc[[c[ffff//////)))@/)))////f/[[[[c[[[[ccccccc[c[[[[[cc[[[cccc#a#a#=aaa#a###aaa#aa==!>!]!]]777111%%%^^||55;;55;;;5;5;;;6+", +"~+++;;5||^^11]]!>==a#c[c/f[7*j$$$:i33ee=>!]]7771117111717771777]7]!!]]!!!>!!>>!>>>>>>=====a=aa###c#c[[[[[[fffff/////)))f///ff[[[[[cccc#cccccccccc#ccc[[ccc######aa==>>=>=======>>!!]]]]7711%%^|||55;;;;6666++++66+666+++~", +"9~++6;5|^%%17]]!!==aac[cf/[a+3$jj:i3&ed*b_9~+;5^%17!>=a#c[[[f////f[ff[[[####a==>>>!!]]771111%1%%%1%11111777]7]]]]!!]!!!!!!>>>>>==a=aaa###cccc[[[[[f//ff///f/f/ff[[[ccc################cccc[ccc#ccc##aa====>>!!>!!>>>>!!!]]]717%%%^||||55;;66+6~~~~99999~+~+++++~", +"99++66;5||^111]]]>=a#a#[[f/#^>a##cc[f[fffffff[[cc[c#aa===>>!>]]]]77111%1%%^^^^%%%%^1%1%111177777]!]]!!!>>>>=aaaaa###ccc[[[[[[[ffff//ffff[[[cccc####a###########a##c#ccc[##a#aaa==>!!!!]]!]]!!]!]7771%%^^||5|5;;6++++99999_bbbbb_bb999~~99", +"~~+66;55|%%%77]!>>==#cc[[[ff>~ijji3&ed*b9~6;5^17]!>=a#cc[fff//ff//fffff[[[ccc#aaa===>!!!]]7]71%%%^^||||^^^%^%%%111117777]]]]!!!>=>==aa######ccc[[[[[[fffff[[[ccc####a#aaa#aaaaaaaaa######cccc##c#aaa==>=>!!]]]7]]7]]]7771%1%%^|||;;;66++~9~99bbbb****d***bb__99_", +"_9~~6;65||^%%77]!>>=aa#cff[[a5>>!!!!771%|;;;;5;555||^^^^%%1%111777]]!!>!>>=>===aa####ccc[[[[[[[[[[[ccc####aaaaaa====a=aaaaaa####ccc#c#aa#===>>!]]77111%711711%%%%||555;6;6++~~999_b*b*ddd==##c[[[f////////)/////ff/[[[[[c[cc##aa#a====>>!7^5;6;;;55||||^^%^%%1777]]!!!!!>=>===aaa#a#####cccc[[[[c[cc##aa=a==>>>>======a===aaa###c####a##=a>==>!!!]]7111%111111%%^^|||5;;666++~~9___b**dd<<>>aa#c[[cca!6ei3&<*_9~65|^17]!>>a##cc[f[[ff/////////////f//ffff[f[ffff[[f[[[cc##]5+++66;6;555|5|^^%%%171777!]!!!>>====aaaa#####cccccc#c#ca#aa==>======>=>======a=aaaa##c#####=a==>!!]]7111%%^%^^^%%%^^^||55;;;6+~~99__b***dd==aa#cccc=]|b&&<*b9+6;|%%7!!==###c[[[f//////)))/))))@)@))))@)))@))))))))@@@@@))f!|6++66;;;55||^%%%%%1777]]!!!>>!>>====aaaa####ccc#c###a#a===>=>!!>>>=!>>>>>>===aaa#####caaaa===>>!!!]711%%%^%^%^%%%^||5|5;;;6++~~99__bb*dd<>=a#c###=!%;_<==a##c[[f[f/f////))/))))@))@@@@@k@@kk}}}}00n00n{nn0/>5+++++6;;;5|5||^%%%%177777!]]!>>>======aaaaaaa##a##aa====!>!>>>>!!!>>>>=====a=aaaaa#cac#aa==>>]!]7771%^|||5||^^^^^|5|5;;6+++~~99__bb*dd<=aa###==]|6~*db_~+;5^%7]!!>=a###cc[[fff///)))@@)@@@@kkkkkk}}}}}0}0nn0{n{ooo'qqqoka^++6+66;;5|||^^%%11177]]]!!!!!>>>====a=aa######aa===>!!>!!]]!]!!>!>!>!>>>===a=a#####a##===>!!]!]71%%%%||||||||||||55;;66+++~~99__b**dd==#a#=>]1;+_b*b9++6||%%7]!!===##ccc[[ffff/////)))@)@@@@kkkkk}}00nnn{o{o''qqqq-ggq}a|6~+66;;555|^^^%%%1117777]!]!!!>!=>===aa==aaa=====!>!!]!!!!!!!!]!!>!>>>>=>a=aa=#####a===>>!!]7771%^||555;5;5||||55;6666+~~9__bb****d==aaa=>1^;~__99~+;|^%17]!>>=aa##cccc[[f/f///)/)))@@)@@@kk}}}0}0}0nnnooo'qq--ggs88gn#%;+66;;555||^^%%%11177]]]!!!>!>>>>>>==aaa=====>!>]]!!]]7]7]]]!!!!!!!>>>=>===aaaa##a#a>=>!!!]71711%^||55;5555|5555;;6++~~~999_bb*ddd==a=!]^5+9___9~;;5|^%7]]]!=>==aa#ccc[[c[[[f[fff/ff/)))@@)@kk}}000n{{o'''q-g-sss88g0#^;+666;555||^|^%%%1171777]]]!!!>>>=>>>=>=>=>!!!]!!77]7]]]]]!]!]!!>>>>>>=====a##a#a===!>!]]771%^^|5|;;6;6;;;;5566;6++~~~99_b*b*dddeee&33i::jj$l$l2mmmm((", +"_b99~+6;;55|%%1177!!>===>!7^5+~99~++;5^%117]!!>==aaaaa###ccc[[[[[[[[fffff///)@@@@k}}000n{{o'qq-ggg8888vsn#%;6;;;55|||^%^%%11177]]]]!!!!!!>>>>=>=>=>>!!]]7777777177]]]]]!!!]!>>========a#aaaa==!!!]77711^^^||5;;;66;;;;;;66++++9999_bb**dd<==>!]%56~~~9++6;55^^1777!]!>>====aaaaa#a#a####cc#c[[[ff/f/)@@kk}}nnn{oo''q-gggs8vvvs{c%;666;;;|5||^^%%%%1111177]]]]!!!>>>>>>!!]!]]77771777]]]]]]]!!!!>>!>>>>====aaaa#a==>!!]7711%^%^|5;;;6+666;66;;6++~~999bbbb**===!7%56+~~+66;5|^%%17]]!!!>!!>=>>>========aa=aa###cc[ff//)))@k}}0n{{oo''q-gss8888vv8{c%;;;555|||^^^%%%%17777]7]!!]]!!!!>!]!!!771771171711777]]]]]]]!!!>>>>>=====aa=a=>>!]!]]7111%^|||5;;6+6++;;6666++~~~99_bb**dd<>>!]%|;6~~+~+;;55|^%1%17777]]!]]]!]]]]]!!!!!>>>===###cc[ff//@@k}}00n{{o'qqq--gssvvvuvs{c1;;6;;555||^^%%%1%11777777]!]]!!]]!]777711111111777]7]]!]]!!!!!!!>>>!!>===a#===>!!7771%%^^^||55;66+~+++++++~~~99_bbb**ddde<&e&33ii:jjj$ll2m2(pp,,(l", +"*bb_9~++6;5;|^%^17]!>==!]1|;;+~++6;;||^^%%11177777771777777777]]]!!!>===a##c[[[//)@@k}}0n{oo''q--ggss8vvuuu8{[15;;;55|||^^^%%111111]7]]]!]!!]]]7]]1%1%%%%1%1111777]7!]]]]!!!!!!=>>>>>=>=a==>!]]]717%%%^^||555;66++++++++++~999__b**ddde>!]1^|;6++++66;;|5||%^^%%^%^^^^^|^^^^%%%1%177]]!!>==aac#[ff/))@kk00nnn{{'qq-ggs8888vuuu8o[7|;;555||||^^^%^%111117777]7777]7%%%%%%%%1^117777]]]!]!!!!]!!]!!!!]!>>>a====>!!]711%%%^||||55;66~~+~~~++~~99__bb***dd=>!7^|;+6+66;555||||^^|^^^|5||5|55|||||^%%117]]!!>==aa#ccfff)@@kk}}nn{o'''q--ggs8vvvuu.u8o)>^;5;5|||^^%^%%%%177117777]771111%%%%^^^1%1%1777]]7]]]7]]]!!!!!!!!!!>>=a=>=>!!7]711%%^^||||||5;+~~+~~~+~9999_bbb**d", +"!]]%^5;666666;655555555;;;;6666+6;6;;5|||^^%%117]!!==a##[[[///@@k}00nn{{o''q--gsss8vvuuuuv')!|66;;5|5||^^^%%%%%1111711111%%^^^^|^%%^1%7177]]7!]]]]]]]]]!!]]!]!!!>=>>=!!!77111%%^^^|||555;66+~9~99999__bb***d<<!71^|;;666;;;55555;;;66++++~~+++++66;;5||^^%777]!!==a##c[[f//@)@k}0nn{{oq'q---s888888s8--'}#%~b_9+;5||^%^%%%1111777171%^%%^|^^^^%%^1%717]]]]!]]]7]7]]]]]]]]]7!!!==>=>!!]711%%%^^^^^^^|5;;6+~9~99999__bbb*dddaaa", +"!!7%^5566;;66;;;;;66+~~99____9_99~~+66;;5||^%%17]!!>==a##c[ff//@k}k}00{o{oqq-ggggsgsqo0@@f[c=^_3ji&>>=>!!77711%%^^|||||||^|56+~9_9_9__bb**ddd<>>!]7%^5|5;;5;5;55;;66~9_b_bbbb_b_99~~++6;;||^%1177!!>===##ccff)/))k}00nn{oo'qq-gg--{}/ca>!]]]]16d$ppmli<_65|^%%%%1%%%%^^||||5|^||^%%111177]!]!]]71717777]77717]]!!>>>>]!]7711%%%^^%^%%^^^|;6+~999____bbb*ddd<77%11177711;*j,hh,($&b+5|^^%^%^^^||5|5||||%^^^%%777]]!]]7]7777777711111777!!!!>>>!]771%%%%^^||^^^%%^|5;6~9_b_b_***dd<<=!!]7%^^|555555555;5;6+bd<<<==a#c[ff/)@@k}00nnooo'''{@c!1^^%^%%1177771|9ip4t4hpl3*65^^^|^||5|5555|||^^%%1%17]]]]!!777111111711111%177!!]>!!!]7771%%%^%^^%%%%11%|5;+~9__bbb**ddd#c##a==>", +"e=aa#cc[[//)@kkk00nnooq'nf>%|5|5|^^%%11777]1%+e2r4tth,$&96|5|5555;;;5||||^^^%%1]7]!!]]]]77717111%%%%%%11177]>!!>!]77%%%^%^^%%%%1111%^56+9_bb**dd<<>", +"=a##c[[f/))@k}}0{{o{{}[]|5;5|||^%%%11777]7]1|b:p4ttthmi*6;5;;6;;5;55|||^%^%1177]]!!]7711%%%%%1%11%^%%%1]]]!!]!!771711%%%^%%7177171^|5+~9bbbb*dd<!", +"&<!!]71%%||^5||||%^%7]!!=!6d333&&<===##c[ff/)@@k}000{{}[75;;5;5|^^^^%%%1777]]]1^+<$,4t4h,$e~+6666;;5|5||^^^%%17]!]!!!]]11%1%%%%^%^^^%^%11%7]]!!]]]71%%^^^^^^%%177]711|56~_bbdd!!!", +"ee<!>!]71%%^%^^%%%11]>=#c[[]~e3&&&==###[ff/)@@k}0nn0}c7;6+6;555|^^%%1111777]]]]159imhtt4rl&_+++66;5|||||^^%1777!!!]!]7%^^%%%^%^^^^||^^^117]]!!]]771111%%%%177]!!!]77%|;+9b*ddd<cc[cc##a===>!!", +"eeeddbbb_~+65|%1]!!>]]711%%^^^%^%%7!!>ac[f/[1b&i&e&e<!>]71%%%^^|^|^^||^^||%^177]]]]7771%%^^%%%11]!!!!!]7%|569_bd!!]]", +"&ee!!]7111%%%177]!>a#cf/)@@c|*33&e<==aac[ff/)@@k}00)>5++++6;;;|||^%%%%1171777]7]]]7|~ej(,p2:d~+6;5|55||^^%^11]]!>!!]1%%|||^|^|||^55|||^^^177!!]]711%1%%^%117!!!>>>!]]%|;9bb*d!!]]", +"&3ee]!]]771%%%1%1]]!aac[//))@/>+<33&&<=a###c[f/))@k}k[1+99+666;555|||^%%%1%17177]]]]]71|9&$2$id96;5|55|5|5^^11]!>>>>!77%^|^|||5|5|5||5|||^%17777]111%%^%^%%%7]]>==a=>!7%|6~_*<<&e333iii::jjjll$$&_|!a[[[[c#a#a=>>>!]]]1", +"3&eedddbb9~65^%7!!!!!!]]771717]]!>=##[f//@kk}f]9e3&ee=a#c[[f/)@@k}@a5999~+6;6;55|^^^%%%111117777]]!7]]159d<]1%^|5||5|5555;;5;;|||%%177]]77111%%%%11]!>=aaaa=>!7^5+9bd!!!]77", +"33eee!]]71771177]!==#[[f//@)kkk[%b&3&&e>==aa#[[ff)@@kf7~99~++66;;55|||^|%^%%117177]777!]777^5++~+6|5555555^^^17!>==a!!1%^|5;5;;55;;556;5;5^|%17717711%^^%^^%77!>==aaa==>]1|+_*>!]]]77%", +"33&eedd**_~65^%7]!!!>!!]]77]7]!!=a##c[f/)@@@k}k#|*&&eeed**bb999~+66;55|^^%117]]]==aa#c[ff/@)@#^9__9~++6;;555^|^^%%%%%%711117]7]]]]!71^^|5;555;;;5;||^1]!=aaa!7%^|55;;5;;5;66;6;;;5||^%7777111%%%%%%1]!>=##c#c#a=!1^6~bd<&33iii::jjieb5]#f//fff[[cccaa===>>!!]71%", +"i33&eed*__9+;|%7]!!!!]!]7777]!!>>=#c[[[//))@k}k@>+e&3&e<!>=a##ccf//@)#5_b99~~666;55|5||^^^%%%1%111711777777177^^||5;;5;;;55|%%]>a##=>]%||5;;;6;;66;;6;6;;;5^%%1%111%%%^^%%11]!==a##c##a=!]%5~_de&3:i:jj:3e_5]#f/f//f[ccc#aaa>=>>!]]711%%", +"i3&eee=aa##c[[f/)@@k}}})!9<&eea##=!1%5;;;;;66;6666+++66;55%%17117%%%%%%%17]>a#ccccccc#a!756_*<&3::i3&*+^!#f/))//ff[[c###aa=>!!!!]]7%%^", +":ii3&<=aa##c[ff//)@kk}k[1*&3&ee>=aac[[///=;bb_9~~666;;55|||||^^^%%%%%1%%1111111%%^|||;;6;;66;;5^^7>a#[#=!1^55666+66+6++++++666;||^%%1%%%^^%^^^11!>=##[[[[cc#a>7^+9*<&33&<_51=cf/))/ff[[c[####a=>>!!]]]11%%|5", +":i3&&eedb_~+5|%1]!>>>!!!!]!!!>=>=aa#cc[[f/))@k}}}kc|b&&&e==a#cc[f/=5bb_9++666;5555||^|^^^%%^%%111111711%^%||5;;;6++6+66;|%7!c[f[=]%|;;666+++++++~+~~+6665|^%%11%%%^^%%%7!>a#c[[[[[[[c#a!7|~bdd*_;%>c/)@@))///f[[[[c##aaa=>!!]]771%^|;", +"iiii3e====aa#cc[ff/))@k}}@a;d&&eee=#ccc[[cc[cc#>]|;+~6^!#f/@)@))/f/f[[[c##aa==>>>!!!]771^^5;;", +"::ii3&ed*b9+5|%17!!!>>>!!!!!>!>=>==aa#ccff/))@kk}}0@=+d&&e==a#c[[#%9_99~66;;;55|5|55|||^^^|^%%%^1%%%%^|||;;;+6~+~~~+++;5%!#f@)fa!%|;6++++~~~~~~~9~~~~+65||%%%^%%^^^^%1!!=#c[[f[ffff[[[a>]7]>af)@kk@@@)))//f[[cc####==>>!!]]7111^^5;+", +"j:i33&e!!>>>>aa#cc[ff/))@k}}k/]~<&e&edd**b_99~+~+6;55||^%%117]!!>=a##[c7+__+6+666;;;;555|||^|^^^^|^^%^%%^^||5;;;++~+~~~~~++;|1>#@}{0@c>7^56++~~9~99999_99~+66;||^^^|^|^^%%7]>a#c[[[[cc[[f[[ccc[//@kkk@@@))//ff[c[cc##a====>!]]]771%^||6++", +"jj:3iie<*b_~65^1]!!!>>!!!>!!!>!>>===aa#cc[[//)@@k}}0}/!+>=a#a!|++~666;;;;555||5|5|55|^^^^^^^^^^^||;66+++~999_99~~65%>[}{q-qo})c=!1|5;+~~9999_9_9~6;;||%%%^^|%^%%7!=#c[[[[[f[f[f//)@@}}}}kkk@@@))//fff[ccc##a==>>!!]77711%^|56+~", +"$j::3&&e==aacc[[f//)@@}k}kf%be&eee>==a>%56;;6;;;;;;;5;555|||^||||^^^^||5556;+++~999999999+651=f}'s8v88-'{})f#=]7^5;66+9~~++655|||||^||^^1]>=a#cc[cccccfff)@@kkk}@k@@))//ff[[[cccaa==>=>>>!!]7711%^|;;+99", +"$$jj:3&edb9~65^%77!!!!!!!!!!!!!!!!!>==a##[[ff//)@@k}00}c^be&e<>!!!]7711%%^|;;+9_", +"$jj:ii3e==a##cc[f//)@kk}}}k#|bee&e>>!]]7771%^%|556+~__", +"$jjj:33&<*b~65^%77]!!!!!!!!!!]]]]]!!>===##c[f[//))@kk}0}k#|*eeee!!!!]]1111%%|5;6+9__", +"ll$j::3&==a##c[ff//@)k}}00@a;d&ee#c[[cc#a#=a#c[[ff)))@)//fff[[[cc#c#aa==>>>!!]7111%%^|55;6~~9_*", +"ll$$::33f0'-gs88ssssssggsgggg-g-'{0)[=!1%%^^^|^%%1]>ac[[[c##aaaa##[[f//))))///ff[[[cc###aa==>!!!!]]771%%^^55;+~9_bb", +"ml$l$:i3ed*_+;5|%17]]]]]]]7771%1%177]!!>>aa##c[[/f//)@k}}0}/]~>!>!]]]711%^%^^556++~9_b*", +"m2l$$:33edb9~65^%%77]]!]]]7771111177]]!>>=aa##[[ff/)@@kk}00})]+<&&ee<]1%%^^^%%1]!a#[[[c#aa==>=aa#[[ff////ff[[[cc###aa===>!!!]]]711%%%^|5;;+~99_**", +"22l$$::i&<*_~65|%1%77]7]777111%^%^%17]!]>=>=a##ccf///))kkk}0})]+acc[c##a>!>>>==##c[[fffff[[cc###aa==>>>!]!]]111%%%^|55;6+99_b*dd", +"mm2l$j:3&<*_~6;|^%1777]7]771%%%%%%1117]!!===a##[[[[//))@kk}0}0/]+deeee<!711%%17]!=ac[[[#a==>!>>==a#c[[f[f[[[[cc###a====>>!]]7]711%%^^||55++~~9bb*d", +"mm22$$::&==a#a#c[ff//)@kkk0}0)]~<&e&<]]1111117!>#cc[#a=>!]!]]>>=accc[[[[c##aaaa===>>!!]!]771%1%%^^||56++~9_bbbd<", +"mm22l$:i3<*b~+65|%%11777711%%^^|^^%%177]!!!===##cc[ff/))@@kk}}0})]+<&&ee<!]7777]!>ac[[cca=!!]!!!!>=a#cc[cc[ccc##a===>>!!!]]]7711%%^|||5;6++~9_b**dd", +"p(mml$$:3&<*_~6;|^%%11711%^%||5|5|^%^%117]!!>==a##cc[ff//)@kk}}}k)]~d&3e&!!]7]]]!=a#ccca=>!]777]!!>=a#c#cc##aaaa==>>>!!!]7711%%^^^|||;;;++9__bb*d<<", +"((mm2$$:3e!]!]!!>=#[[[c#=!!]717]!!>a###ccc###a====>!!!!]]77111%%^^^||5;6++99_b**dde", +",p(mm2$ji&===a##cc[ff/)@kkkk0}}/!+d&&&&&<<<>a#c[c#=>!7711117!>>=a#a#a#a====>>]!!]77111%%^%^^|55;66+9~9_b**dd==aa#c[[fff//)@k@}k}k/>5b&&&&e<<>==##[[c#a>!7711717]!>=aaa#aaa==>>>>!]]]77711%%%^^|||5;6++~9__bbdd<==aa##cc[f/)))@kk}00k)a5*&3&&&e>>==a#cccca>]71%%%^17]]>>=aaa===>>>!]]]]]771%%^^|^||||;;;6~~_9bb*dd<<&&", +",,pp(2l$:ieaa##cc[f[f/))@@@k}0}k#|b&3&&&&&<<<!7%%^%^117]!>==aa==>>>!!!]]77711%%%^^^||||;;6++~9_bb*dd<>>a##cccf/ff/)@kkkk}k@a|*&3i&&e&ee<<<]7%^^|^^%1]!>>>>=>>>!!]]]777%%%%%^|^||||5;;6++99_bb*dd>==a##ccc[ff///)@kk}}}@c%9ei33&3e&&ee<<>>=>>!!!!]771711%%%^^||||55;66+~9__bb**<>>==aacc[[ff/))))@kk}k)[7~<33i33&e&e&eeee<<!!]]]771711%%^^|||||||55;;6+~~__**d<<==aa##c[[[[f/)@@@kk}}@f7~<3ii3i&3&&eeeeeee==aa###cfff////))@@k}@/>;d&ii3i33&&3&&eee&eee<>=aa###c[[f//))@@@kkkk/a5b3:iiii333&3&&e&&e&&e&!>=>=a##ccc[[[f//)))@kk})#%9ei:::iiii3i333&&&eee&eeee&eeeeeeeeee&&&&ee&e<=>=aaac#c[ff///))))@kk@[76<3::iiii3333333333&33&&e&&&e&eeee&e&&33&eeee]%^|5;;66;5|%%17777771%%^^^||||55555|;;;;6+~~99bb*dd=>==#a#ccc[[f//))@))@@@/>;d3jj::j:::i:i333333&3333&&3&&3&3&333&eee>=>a#a#cc[[[ff/f/@)@))@/#^_&:j:j:::i:::ii3iii33333333&&&3333i3&e<</)//////////f////f/f[ffff/@@@@@@)//ffff[[c#=!7%^566++666;|^%%%%%%%^^|^||55;;5;55;5;;;6++99_bbbddeee&33i3i:", +"!>]63(rrp(2$:i&e>=>>a#a##c[[[f/)/)/@@@@)c1~===aa##cc[c[[ff/f))))@)[>5b3:j$jj$jj::j:::iiiiiiiii3iiiii3ee<[ffff[/fff[ff[f[[[[[c[[[[//))@@)))//fff[[#a!!1^|;;++++++;55^^^^%^^|||55;;6;;;;;;;;;66+~99_bb*d<!^*l,,p(l$:i&==aaa##c[[[ff//f)))))fa%9&jj$$jj$jjjjj:jj::j:::::i:ii3ee]5emp((2$:i&===aa###c[c[[[////)))@)[>5*i$l$$l$$$j$j:$jj::::::::ii3e=>=aa###ccc[[[[/f/////[=%9&j$l$l$$$$$$jjj$$j$jjj:i3e]1^|;6~~~~99~~66;|5555;66666++66++6++66~~~99_*b*d19i(pm2$:i3eddbb_9_9___b*ddd*d*b_b_99~+++66;;5|||^^%%7777]!!!>====a####cc[[cff/f//))fc!6<:$$2lll$lll$$$$j$$j::i&ed**b9_9_bb*d]%^5;6+~999~~+6;;5|55;;;;6+++++66+;;666++~9__***d<=aa#c[///)/))//[cca=!7%|;++~~~9999~~66;;;6;66+++++++~6+++6+~~~___*b*<<=>=aa##ccc[c[[fff/f/f[c!5*i$m2lm2llllll$$jii&<*b99~~~9____*d&&:$l$ll$$$$l$i~]=####aaaa=aaaaaa=======a##c[f/)/))//fff[ca>!7%|56+~999_99~+666;;6;6+++~~+~++666++6+~~9_bb*dd>===a=aa###cccc[[[f[f/f[=1+>>>>=>>!>!>>=#c[[/////f/fcc#a>]1^566~9~_____9~~+666+++~+~~~9~+~~++++~~9__bbddd>====aa##ccccc[[[[[[f[c!^_&$22m222lllji3edb_~~+++~~~~9_bdei:$$l2ll2l2lje;!===a===>>=====>=>>>>!>!===#c[f///)///f[c#a>]1^566+~9999999~~~+66+++~~9~~~~++++++++~~9_bb*ddee&&3i:jj$$2l22m", +"^%%11]]]]^+elmml$:i33&eee<<<<=====aa###c#cc[[f[f[[a75b32m((m2l$:3<*_9+++6666++~~9bde&j$2m2mmlml2$*%>>=>>>=>>=!!!!!!!!!]!!]]!!=aac[f//f/ff[c#a>!7%|5;~~999b_bb_99~~~~~~99_99999~~~~++~99__b**d<>====aaaa##c#ccc[c[c[[c=76dil2m2$ji&d_~++666666+++~9b*e3j$2m22mmmm2:_7>>>>>!>!!>!>!>!!!!!]!]]]!!>a#c[[f//fff[[c#>!]%|;6+~999_____99~9~~~~999999~~~++~~++99_bb*dd<<&&33::j$$ll22mm(", +"|^%%%17]]7^6*jlml$$::ii33&&&3&&333333&eee>>>>=a=aa#####cc[c[c[#>^9ejl$j:edb~6;;;66;66;;++__deijl2m(((m(m236]!!!!]!!!!]]]!]]]7]]]777]!!>=a#[[[ff/f[[ca=>]1^|;+~99___bbbb_9_9999999_999999~~~~999__bb*dde&&3i::jll22mm((pp", +"||%%%77]]]1|~ejl2l$$j::3i33&3333i33333&ee>>>=>=aaa=aa#aa##cccc[ca!^~<3&e*_+66;;5;;;;666++~9*e:j2mm((p((ml<5]]!!!!!]]!]!]]]7]]77]7717]]!>a#[[fffff[[c#=>]7^5;++~99__bbbbb____999_9999~~~~~~~+999_bb*ddd<&&3::j$l22mm(((m2", +"5||^%%11777%;b3lm22l$jjj::iiiiiii:iii333&&e>>==a=aa#######c#c##=]^+bb96;;||555;;;;;;;+~_*!]%|5;+~_9_b_bbb*bbbb____9_____9999~~99__bb**dee&33i:$l$22mm((mli<", +"5|^^%%11]771^6*3$22l$$$j::::::i::::iii33&&ee<<>>>======aaaaa###cc##=!%5;5|55|5;5;55;;;;++_de:$m((,,,pp(i~%]7]7777177717717771111%%117!!=a#ccff[[[c#a=!]1|56+~999_bbbb*bbb______99999~~~9~9~9_bb**ddee&3i:j$$l2mm22$3*;1", +"5;55|^%11777%5~>======aaaaaaa##a=!]1^^^|555;5;;555;6~9b&:lm(,p,,,,2<511711717711111%1%%%%^^%^%%1%7]>=##cccc[caa=!]7^|66+~___bb**d*ddb**bb____9_9__9___b_bb**<>>=====aaaaaaaa=>!]1%||555;;5;5;55;+9*&:l(prrrrr,$b^111111%%11%%%%%%%%%%%^%^^^%%7]!=a#c[[[cc##=>]1%|;6+~99_9_bb***d*b*bbb_b___99_999___bb**d!>>>>>>====>>>>!71^^|;;;;5;5555;;+9*&:l(,,rrhr(3+^%1%%%%1%^%%%^%^^^^|^||||5^^%17!>=###c#c##=>]71^5;+999_9bb**ddd*dd***b*bbbbbbbbb*****d<<>>>>==>=!]]71%|556;;6;;5555556~*&$mprrhhhrld;^^%%%%^^%^^^^^^^^^^||||||||^^11!>=a##c###a=>!7%^5;++99999__bb*d**ddd***b*b*bbb*bb***ddd!!!!]%^|5;;;6;;555|5|||;~b&j2p,hhhhp:~|%^^|^|^^||||||||555||5555;;5|^7]!>aa###aa==>!1%|56+~9999__b**dda#####aaa=", +"+66;;5||^^%117771%56b&$mp((((m(m2m2ll$$$j:j:33i&&&&<=aa###a=>!]7^|56++~~~~999__bbdddddddddddddddddddd<]71^56+~99+~++~9__b**dd<<<<<<<<<<<<<", +"~+++6;55||^%%1777711^|+*imp,,ppp((mm2lll$$$j:jiiii&&ee<!!71%|;6++~+++;66~~9__b**dd<<<ac#[cc###aa=>>>", +"+~+++66;55||^^%171771%^;b3m,rrr,ppp(mmmll$$jj::i33i3&&&e====>!!]1^|;6+~9+6;;;;;6++~__b**a##c##a#a==>>>!]", +"1;~++66;55||%^%%777]]711|~&2p,,,,p(((mm22ll$$j:j:i33&&&&=>=>!!]1%|56++~665|||||5;;++~9_b**dda#c#c##aa===>>>!!", +"c%6+++66;;;|5^^%%117777]7%+elprr,,,p((mm22llj$$::::ii3&&&eeedddd**bbb__9_9~~~+~++66;;;;;55||5|||||^^%^%%^^^|5;6+~9999++6;;;55|^^%%1177711%][@)fa!1%55;;6+++++++~+~~~~~~~99~9~+6;|%7]!!>>!!!]11^|;6+~~+;5|^%%%^^556+~9__bbb*****=###c#aaa==>>!!]]]", +"k#%6~++6;;;5||^%%1177]!]!!75b:pr,,,ppp((m2l2$ll$:j:ii3333ee&e!!]]7%^|;+++~65^%77]!]]11^^5566~~~99________99~+5|1!>a##c####=a==>>!!!]7", +"0)a^6~~++;;;5||^^%%1777]]]]]^bjprrr,,pp(((m22l$$$j:j::i3333eeee<!>>>!]77%^||;;;6666++++6+;;|^]!==####aa===>!!!]]]717", +"n0@a%6+++6;;;5||^%%%17]]!!!!!%_j,rr,,pp((mmm22ll$$jj::ii3333&eee<<]7|55;6~~~~999~++;|%17]]]]]]7%^|56+~~+;5%]!=a##cc#a=>>!771%^^^^^||||^^17]!>=#####aaa==>=>!!!]]]11", +"000@a^+~+~+6;;;|||%%%1177]!!!!%_:prrrr,,pp(mm222ll$$$:j::i33&3&ee<)-vvuuvuvuvvuvv88sgqq'n})fc#a>71%^^;6++655^%17]]777%%^|;6++6;|%7>#c[f/f[f[c#aa=>!!!7711111177]!!=aaaa#a=a=>>>!]]]]77111%", +"00n0@#%6+++6;;;5||^%%117]]]]!!>^_:(rrr,,p,(((m22ll$$$jj:::ii3333&e]7%^%%%177]]7711^|5;;;^7=#cf@kk@@@)///[c[##aa==>>>>>!>===aa#####a#===>>>!!!]77111%%", +"k}}00)a%+~+++6;;55||^^%%117!!>!!1~3mrrrr,p,(m((mm22l$$$j:::ii33&3&&ec/@@}k}}kk@))f/f[cc###a=a=a=a==aaaaaa##a===>>>!]!!77711%%^^", +"}}0nn0@#%6+++6;;55||^^%%17777!]]]76<2rrrr,r,p((mmm22l$$$$jj::ii333&&eeee11111777771%^^5||%]a[)}}00}}kkk@)))//ff[[[[c##c####cc####aaa==>>!!!]]]71111%%^^", +"@kk}}n}@#1;++~+66;;5||^^%1%7]]!!!!76e2,rrr,,ppp((mm2m2ll$jjj:j::i3i33&&&&ee<)osssssgsgssssggssssggg-gggg-gggg---qqon}/c!!1%%1171111%^||5^%!#f@k}0}kkkk@@@)//f/[f[ccccc#ccc#####a===>>>!!]]]]7171%%^^||5", +"@kk}000}@c]56++6;;55||^%%%11777]]!!1;d$prrrr,pp(((m222llll$lj::::ii33&&eeee<<<<<*d****bbbb___999~9~9999_bbddddb*99+6;||^^^^%^|^^5^%>)oqgggggsgggsgsgg-g-gg-gggg-g------qqqq'{n@f#>!7777711111%%^%%]>[/@k}0}}}kk@@))////fff[f[[[ccc###aaaa=>=>>!!!]]77111%%%^^||5", +"@@kkk}0}k)c75++66;;;555||%^%%1]]!]]]7|b$prrrrrr,,(p(mmm2lll$$$j:::iiiii33&&e&e<<<</n'g---gg-g------gg-g-----qqq-qqqqqqqqq'{{0k/#=]]71111711^^^^^1]>#f)k@kkk@@)))))//fff[[[ccccc####aaa=>=>>!]!!]]7711%%%^||5|55", +"@)@k}}}}k@/a7|;6;;55|||||%^%%171777]]7|b:prhr,,,,pp((mm22l2l$l$$:j::i33333&&e&eee<<<>>!!]]]7]1111%^^^^|5|;;", +"/)@@@kk@))[#>7|56;;;555|||%^%%17%7177%%|9&m,hhh,,,,,pp(mmm2ll$l$$$$jjj:iiii33&&&eee<<<<!]777171%11%17>a[f@@@@@))))//f/fff[ccccc##aaaaa=>>>>!!]!]]771%1%^^^^||5556;6", +"//)@@k@@)/[a>]%^55|5|||^^|^^^^%1117%71%%5_3m,rhhr,,pppppmm2m2l$ll$jj:j:::i33i33&&&eee<>!!]!]77771%%%^||||5;;;;6", +"f//)))@)/[#>!7%^^|5||||5|^^%%%%%%%%1%^^%^59&l,rrrrrr,pp(p((mmm22$$l$$jjj::::3i333&&&e&eeee<<<[}{{o'ooooo'o'o'ooo'o'ooooo{{o{{ooo{{{{{n{n{{n0}k)fca=>!]]77771117!>a[f/))/////ffff[[[[cc###aaa====>>!!]]]]77111%^^^%|||55;;;66++", +"ff/))))/[ca!]71%^^^|||^^|^|^^^%%%%^%%%||5;69e$prhrrrr,rppp((mm2m2lll$$$$jj:j:::3iii3&e&&eeee<<<[k{oooooooooo{ooooo{o{{ooo{oo{oo{{{{{{{nnn{nnnnn0}k)f#a=>!!!!]]77]!>a#f//)///ff/f[[[[[cc#c####a===>>!>!!!]]]771%1%%%^^|||5;5;;++++", +"[[ff//f[ca>!]1%%%^^^^|||^|%^%%^^%^%^|||555++be$(rhrhrr,,p,p(pm(mm22l2l$$$j$:::i:ii333i&&&&ee&e!!]]7]]]!]>a#cf///fff[[c[cc#####aaa=>>=>>>!!]]]]171%1%%^^^|5555;;;66+++~9", +"[[f////c#=!]]1%%%^^^^^^^^|^|^^^^^^|^||556;++9*ejm,rhrrrr,,,(p((mmmm222l$$$$$jj:j:j:i3i333&3e&&eee&&3&33&e!>=#fk}nnnnn{0{{n{nnn{{nnnnnn{nnnnnnnnnn0n0n0000000}}}}}k@/[c#==>>!!]!!!!=acf//ffff[[[c[cc####aa=====>!!!!!!]77771%%1%^^||||55;;66++++~9", +"c[[fff[ca=!]771%%%^^^^|^|^^^^^|^|^|5|55;;++9_b<&j(,,rrrr,r,,,ppp((mmm2222$$$$$$::::::iiiii3i3&&3&&&&33&e<*_~;5^%1]]]!!>>>a#f@}0n00n00n00n0nnn00nnnnn00n0n00}0}0}0}0}}}}}}}k}kk}kk@)fcaa=>>>!!!]!==#[[fff[[c[#cc####aa=a==>>>!!!!!]777711%%%%^|||555;6666+++~9999", +"#c[fff[#a=!!]71%%%%%^^^^^^^^^^^^|^||55;;6+~9_*deij(,rrrrrr,,,,pp(p((mm22222ll$lljjjjjj:i3iiii3&3i3i3ii&ed_~65|%177]!]>==acf@kk}00}00}00000000n0}0}00000000000}}}}}}}}}}}k}kkk@k}k@@/f[##===>>>>>=a#c[ff[[[ccc###aaaa======>!!!]]]77717%1%%^^^||||5;;;666+~+~999_", +"##[[f[[#==]]]111%%%^^%^|^^^^^^||^5|555;6++~9_bde3:$mprrhrrr,,p,,pp(pp(((mml2ll$$$$$$j::jjj:iiiii3iii33ed_96;^%77]!!!==>#cf/@@kk}k0}}}}}k}}k}}k}}}}}}kkkkk}kkk}}}kkkkk@@@@@@)@@@@@@@/fc#a===>>>>>>a#c[f[[c###aaaaa===>=>!!!]!]]]7171%1%%^^^||5|55;;666+~~~~99___b", +"a#cffffca#>!>!]77111%%%^^^|^^^^|||^55;;;++~9_bd<&i:lmp,rrrrrr,p,ppp((((m(mm2m222l$$$$$jj::::::i::::ii&<*~+5|^%77!!!!>=a#[//@@}k}k@kkk}}}k}kk}k}kk}k}}}}}}kk}kk@kkkk@k@@k@@@@)@@@@@))/[cc##a==a=aa#c[f[[[c####aa====>>!!!!!!]]777111%%%%^^|||55;;;;66++~~~999__bb", +"a#c[ff[caa=>>>]!]7771111%1%^^^^^^^5|555;;6~99b*de&:jlmpprrrr,,r,,,ppp((p(((mmm2ll2ll$$$$$$$jj:j::::i&ed_~;|%17]!!!>===#[[f))@@)@kk@k@@k@k@@kk@kkk@@@@@@@@@@@@@@))))@)@)))))/)//)@@@)/f[c#aaaa=aaa##c[[cc#a====>>=!!>!!]]7]7771111%%%^^||5|55;;;66+++~~~99__bb***", +"=#c[//ff[[ca#a==!>>!!!]7777111%%^%^^^||55;6~~9bd>!!!!!]]]771711%%%^^^^||555;;6;6+++++9999__bb**d", +">ac[f/)/[f[cfc##caaa===>>=>]!]771111%%^^||5;6~9_*<<&i$l2m(p,r,,,p,,,pppp(p(((mmm(m2m222lll$$$$$$$:i&>>=a#cc[ff///))))))//@)))))@))))))//)))))//)/f/////////f/f[f/f))))//[[cc##a#a#acccc[caa==>>!!]!!]]]7771711%%^%%|^55555;;6;66+~+~99_99__**b**dd", +"=ac[/@@k@@)/@)///f/fff[[c[[#aa=>!!]]]]7]71%^|56+~b*>=aaccff///f////)/)/////)///f))/))////////////ff/ffffffff[[ff//))/)/f[[cc#c###c[[[[c#a=>!>!!!!]]7]7171%1%%%^^^||||5;5;;666++++~~99__bbb**ddd<", +"!=#[))kkk0}k}}k}}k}0}}}k}kkk@)/fc##==>>!!!!]71%|5;~9bde3i$$22mm(((((mm(2m2m2mmmmmm222mm22l2l$$$$j3e*965^%77]]]!]!!>>>=a#[c[fff/ff/ff/f///ffff///fffffff/ffff[ff[ff[[f[[[[cccc[[[[///)ff[[cc#####c#cc#ca==>!]]]]77777111%%%^^^||||555;;;666++~~~999__b_b*b*dddde<", +">=#c)k}0n{n{oo{oooo'oooo''ooo{{n0k@))f/[[c#aa>>771^|6~_*<&3i:j$$$lllll2$l$lll2$l2222llll2l$l$$$i3e*9+5^%171]]7]]!]>>>=aacc[[f[[f[[fff[fffffffffffffffffffffffff[[[[[[cc[[[[ccccc[ff//)//ff[[cccccc[[[c#=>!!!]]7]777111%1%%^^^||5|5;5;;;66+++~~~999__bbbbd*d<<!!777111%%%%^%^^||||555;;;66+++~+~~99___bbb***dd<<!%^;6~_*d==aaccccccccc[[cc[c[[ccc[c[[[cc[[cc[c[cc[cccc#cc######a#a###c[f////fff[[[ccc[c[##a=!!]777711%%%%^|^||||555;;;666+++~~9~999__bbb*dddd<1%5;~9_b*bb**bb___bbbb*d*d!>=aaaa############c###cc######c#########a#a###aaa#a=aaa===a#cc[ff/f/[f[ccccccc#c#=>]711%%%^^^^^|||555;;;6666+++~~~9999__bb**bddddd<]1|;6~~+~~9~+~+6~++6+++~~~~~~~+6;|^111111111717717]]7!!!=>aaaaa#a##a#########a############a##a###aaaa#a=aa========a#c[[f///fffff[[[[[c##=>!]7%%%%%%|^^|||5555;;;6;6++++~~999___bbb***dd=#[/)@}k0000nnnnnnnn{{{{oq'qqq--ggss8s88v88v8vsssgqoon0@/ca>7%^5;;;5;;5;;5555;555|555|^^^1%111177777117177]77!]!>>====aa=a=aa=aaa=aaaa#aaa=aaaaaaa=a=aa=======>===>=>>=>>>==aac[fff/ff[[c[cccc##a=!]11%^^||||555;5;;;666++~+~~~999___bb***ddd<==>>======>=======>=a=aaa====================>=>>=>!>>>>=a#cc[ff///ff[f[c[c##a=!]1%%^|||||5|5;;66;66+++~~~99999_b_bbb***dd<]1%^^||^^^|^^^^^^%%%11%11111111171117117]77]]]!!!!!!>>!>>>>==>>=>=====>=>>>>>=>>=>=>>>>>>>!!!]!!!!!]!!!!!>>=a#c[[f[ff[f[cc[cccaa=!71%^5|55;;;66;666++~+~~~99_9_bb*b***dd<!!!!>!!>>!!>!>>>>=>>!>>!>>>>>!>!!>!!!!!!]!!!!!!>>==aa#c[[f[ffff[f[cc#ca==!]%%|||55;;;;666++++~~99999____bb**dddd<>=a#acc[[[[[[//))@@kkk}}0nnn{{''qqq--qgggs8ss888s8sgg-qon0@/[a>]1^^||||^|^|||^%%^%%%^1%111%1111%77711777]77]]]!!]!]]]!!!!!!]!!!!]!!]]!!!!!!]]]]]!]]!]!]!]]]]]!]!!]!!>=a###cc[[[[cccc#c##aa=!!1%||5666;66+++~+~~99999__bb****ddd>===aa#cc[c[[ff/))k@k}}}0nnnn{ooo'qqqq---sgssss88ssgg-''n0k)[#>]1^||||||^^|||^|^^%^%^^^%^%111%%117%711777]777]]]]]]7]!]]!]]]]!]]]!]!!]]!!]!!]]]]]]]]]]]]!]]!]!!>>>==a##c[[[[[[[[[[cc##aa>!!7%^55;;66+6+++~~~~~99___bbb***dddd<<!>====aa#cc[[ff/)/)@)@}}}00nnn{ooo''qqq-q---ggggggssggq'oo0}@f#>7%^|||||||^^^^^^|^^^%%%%%^%%11%1%1%%111%1117171777]77777]7]]77]77]777]77777777]7]777]]777]]!]!!>=>aa####ccccccc#aaaaa==>!]1^5566++~+~~~99_____b_b*b****dd<>===a##cc[[[ff/)@)@kk}}0000n{{ooo''qqqqqqq-g-----g--qq'{0}@[a!]%|^|||||||||^^^^^|^^^%^%^^%%%^%%%%^1111%1%71171717711717777777777777777]7]7777]]77]7]]]!!!>>>==aa##cccc[cc#c###a===>!]]1%55;6++~+~~9~999_bbbbb***ddd<<<>===a###c[[[/ff/)))@@kk}00nnnn{ooo'o''q'qq''qqqqqq''q''o{0}/[a]7^^||^||^|^|||^|^^^^|^^^^^|^%^^^^%^^^%%%%%%%%1%1%1171717711111111777171111777177777]]]]!!!>====a########aaaa===>>]!]71%|56+~~~~_9_9___bbbb**ddd<<===aaa##cc[fff//))@k@@kk}00nnn{{oooo'o'''ooo{ooon{{{{{{{n0k/ca>7^^5|5|5||^||^^||^^||^|^^|^^^^^%^%^^%^^%%1^1%111%1%11111111171111117777171777]7]]]!!!!>>>=aaaaa#a##a#a#a===>=>!]!]7%%^5;6~99999____bbb***ddddde>=>a##c#c[[[ff///))@@k}k}0}00nnn{{o{o{{{{o{{nnnn0}}0}}}}}kk@fc>!71^^^|||||^||^^^|^^^^^^^^^^^^|^|^%^%^^^^%^%^^%1%1%%%%1111%%%%1%111%11117111777777]]!!!>>>==aa=aaa===>>>>!!]]]77%%%|5;6~~9__bbb*******d==>=a###c[c[[/ff/@)@)@@kk}}00n0nn{{{{{{nnnnn}}k}@@)@)))))/)//[a>!1%^^|||||||||^^|^||^^^^^^^%^^^|^^^^%^^^^%%^^%^%1%1%%%%1%11%11%1111111777777]]]!!!!!>>=============>>!!!!]]711%%^|5;+~99__b_bbb**dddd<<<====a#a#cc[[f/ff/)@@@@}k}}}00n00nnnnnnn00}}}k@)/)f[[cc#c####c#=>]7^%|^|^^^^^^|^^^^^^^^^^^^^%%%%^%^^^^^^||^^^^^^^^^^^%^^^^%^^%%%%%%1%%1111771]77]]!!>!!>>>=>>!>!]]!]]7711%%^^^|5;;++9__b*b**ddd>==aaa#ccc[cf//f//)))@@kk}k}00}000n}00}}}@@@)/[[c#aa>>!>!!]]!]]]]11^^|55|||^^^^%%^%%%%%%%^^%%%%%%1%1%11%%%^%^^^%%^^%%%%^%%^%%%%%%11%11711777]]]]!!!!>!>!!>!!!!!]]]717%%%^^||5|;6++9_bb**ddddd<<>=>=aaa#cc[c[[f//)))@@@@@kk}k}k}}}0}}}k@@/f[[ca=>!]]11%^%^%^^^^|^^|||||55555||55|5||||5||^|||^^^%1%%1%711711%%%^%%^^^^%%%%^%%%1%%1%%%%1117777]]]]!!]]!!]]]7]771111%%^^^|555;6;+~9_bbdd + up <0, 1, 0> + right <1, 0, 0> + look_at <0, 0, 0> +} + +sphere { + <0,0,0>, 2.5 + texture { Blood_Marble + scale <2, 2, 2> + rotate <0, 20, 0> } + finish { Dull } +} + +light_source {<6, 1, 0> color White} +/* light_source {<6.1, 1, 0> color White} */ diff --git a/hacks/images/bubbles/blood1.xpm b/hacks/images/bubbles/blood1.xpm new file mode 100644 index 00000000..8a1c184d --- /dev/null +++ b/hacks/images/bubbles/blood1.xpm @@ -0,0 +1,75 @@ +/* XPM */ +static char *blood1[] = { +/* width height ncolors chars_per_pixel */ +"10 10 58 1", +/* colors */ +" c #000000", +". c #250000", +"X c #415050", +"o c #013232", +"O c #000606", +"+ c #0E2E2E", +"@ c #60C0C0", +"# c #002020", +"$ c #102222", +"% c #4D5454", +"& c #043737", +"* c #000505", +"= c #65A0A0", +"- c #7ED6D6", +"; c #196969", +": c #0C4545", +"> c #642525", +", c #385C5C", +"< c #002525", +"1 c #6D8686", +"2 c #354F4F", +"3 c #5A7D7D", +"4 c #030A0A", +"5 c #001E1E", +"6 c #71B1B1", +"7 c #274E4E", +"8 c #287373", +"9 c #0D1A1A", +"0 c #053333", +"q c #001717", +"w c #374343", +"e c #000303", +"r c #070000", +"t c #537272", +"y c #520B0B", +"u c #0C3636", +"i c #297D7D", +"p c #AF5C5C", +"a c #003737", +"s c #010000", +"d c #042727", +"f c #0C3C3C", +"g c #000202", +"h c #042020", +"j c #419A9A", +"k c #420707", +"l c #064949", +"z c #071212", +"x c #1D4F4F", +"c c #154747", +"v c #000101", +"b c #264747", +"n c #002828", +"m c #000707", +"M c #364949", +"N c #001414", +"B c #002121", +"V c None", +/* pixels */ +"VVV*.drsVV", +"VVkuxi;yoV", +"Vv:8jtpbd<", +"Vac,@-=Mfn", +"VOuw3612$q", +"V.z7X%ji+B", +"V#0u>7c9&N", +"VVeo4l0hVV", +"VVVrm5grVV", +"VVVVVVVVVV" +}; diff --git a/hacks/images/bubbles/blood10.xpm b/hacks/images/bubbles/blood10.xpm new file mode 100644 index 00000000..e9c8c69e --- /dev/null +++ b/hacks/images/bubbles/blood10.xpm @@ -0,0 +1,159 @@ +/* XPM */ +static char *blood10[] = { +/* width height ncolors chars_per_pixel */ +"60 60 92 1", +/* colors */ +" c #000000", +". c #020F0F", +"X c #000D0D", +"o c #7F9A9A", +"O c #571010", +"+ c #70D0D0", +"@ c #000606", +"# c #121111", +"$ c #001313", +"% c #236060", +"& c #1F0000", +"* c #002020", +"= c #002D2D", +"- c #637777", +"; c #001919", +": c #206D6D", +"> c #163535", +", c #020707", +"< c #023535", +"1 c #437878", +"2 c #044444", +"3 c #001212", +"4 c #022121", +"5 c #091E1E", +"6 c #1D2B2B", +"7 c #114040", +"8 c #000B0B", +"9 c #366E6E", +"0 c #7ACBCB", +"q c #0D4949", +"w c #021A1A", +"e c #233737", +"r c #171E1E", +"t c #6A8D8D", +"y c #474D4D", +"u c #2F3C3C", +"i c #000404", +"p c #354F4F", +"a c #0A2828", +"s c #012929", +"d c #364646", +"f c #5B6767", +"g c #0F0202", +"h c #001E1E", +"j c #183C3C", +"k c #325C5C", +"l c #000A0A", +"z c #053333", +"x c #115959", +"c c #022626", +"v c #031D1D", +"b c #001010", +"n c #0C1515", +"m c #102626", +"M c #AF5C5C", +"N c #033030", +"B c #2E0808", +"V c #285151", +"C c #001616", +"Z c #4A5858", +"A c #0C3C3C", +"S c #5AB0B0", +"D c #7FB0B0", +"F c #000202", +"G c #000F0F", +"H c #176464", +"J c #001C1C", +"K c #031515", +"L c #081010", +"P c #713232", +"I c #1E1F1F", +"U c #4F6666", +"Y c #000808", +"T c #420707", +"R c #064949", +"E c #001515", +"W c #322525", +"Q c #0D3232", +"! c #154747", +"~ c #328181", +"^ c #000101", +"/ c #023E3E", +"( c #085151", +") c #204E4E", +"_ c #906D6D", +"` c #060D0D", +"' c #063B3B", +"] c #000707", +"[ c #050202", +"{ c #609393", +"} c #4A9191", +"| c None", +/* pixels */ +"||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||", +"||||||||||||||||||||||||GXXJccsNcCF@G|||||||||||||||||||||||", +"|||||||||||||||||||||]l$^XXGEh*$]ls/'R(((RzalNxB((RNh4<=<&[BE||||||||||||", +"||||||||||||8XX3$;NR2NN'R(x(75LQxOA5L`,li.*J*=shY|||||||||||", +"|||||||||||iEs=X@KN2zcaQ(xx77mQdH7#5Qq7z4K,l^E*GXi||||||||||", +"||||||||||ls<<<4XK4aaQQAqqmrm6HPxjr7qqx(N4w`l3$3@Fi|||||||||", +"|||||||||GB&B<2/v`LL5Q>rm>>>!%9:)m7)xxHOxq<4.K=sCGbE||||||||", +"||||||||bN&mTgBWzaQQ#mr6))%)%%~~VIjHHH%WHyO(zKlCNl*m[|||||||", +"|||||||Cg==m2szT(uOx>mj%V%:VV:1~VeV:%HkOpxHT(4w3s<3BBh||||||", +"|||||||gbbmreedpy1}S{{{ooD00-0Doo-f-UU1kpu66mmn544c=*^*w|", +"||G]Xlh22cLA!rrI)kpy1t}{{ttooD0__+0{tffU11pue6e6rmL`v=4ElCC|", +"||Ci8FX/Ranq!rrjVpdy1-ttt-ttoo00_++D{fUUZyuuujj>mm5,4=J$Fl;|", +"||$]J*@22cLQQ>r6uudyZUU--f---oD0__+DtfUZZZpue666m5Ll.sCC|i*|", +"||;3*J^N2wLmmrre6udpZZZZff--toD+_oD{-fUZZ9pde6rmmnLLw<=h$X;|", +"||;bJ$l/N.n5mr6j)uddyZUUff-ft{D0_+S{t--119kVejrr55LLN<<=s*]|", +"||h$XXcB3`Lnn#>jVVdupZUUU---fft{S_SDS}}}}~:)e6r#5L,vc/))%VeppdZUUUUUZZU-}-_-PyPyPP:)m#nm4Kl4C4g**&|", +"||lg@*&=X.4wLQ>7!)V6dpdZyZZZZZZZUU1}}__PPW~H7r#5Q4vilX*g*CG|", +"|||g@s&=EXv4Lm7!77jIuduuyyZZZZZZZZZk11~~PPy%7rmA'avll3cc$3||", +"|||33$r<;Y.w`5Aq!j666eedkkkkZyyyyddpk9:%%:P)Q5AqR/cii]=cXw||", +"|||XXXcgNXlKvz7q!!jmII6uVpk999pdduuddkVV):Hj#Q(6I64$lb=c;X||", +"||||8CJ=B4KKzRRqq!>m6I6)%k:999kdud)eu)V))r755AWBIAs$FXs& |||", +"||||^X*mNN*czA((qAQ>76j)%:::%::)eVu6e))Hyxm#m7BT2=h]FF**]|||", +"||||@Y*sNN=Nzj>6rr!VOu)(QLa'IQc;XYlJwXY||||", +"||||||@|FJ==&&&/ccNj>mQquOeORN`4s'NCl8b*#&L|||||", +"|||||||^|^E;N[Bm c #000C0C", +", c #163535", +"< c #286E6E", +"1 c #437878", +"2 c #001212", +"3 c #010909", +"4 c #040202", +"5 c #360505", +"6 c #2B8181", +"7 c #616767", +"8 c #000B0B", +"9 c #366E6E", +"0 c #021A1A", +"q c #171E1E", +"w c #474D4D", +"e c #77CBCB", +"r c #000404", +"t c #012929", +"y c #364646", +"u c #264A4A", +"i c #0F3D3D", +"p c #516A6A", +"a c #325C5C", +"s c #6CA2A2", +"d c #2B3E3E", +"f c #262222", +"g c #001717", +"h c #115959", +"j c #002424", +"k c #040707", +"l c #043535", +"z c #031D1D", +"x c #192C2C", +"c c #000303", +"v c #0F1515", +"b c #AC6A6A", +"n c #001010", +"m c #150707", +"M c #062323", +"N c #0D2020", +"B c #5AAAAA", +"V c #001D1D", +"C c #054646", +"Z c #0C4343", +"A c #031616", +"S c #060F0F", +"D c #000909", +"F c #033030", +"G c #001616", +"H c #4A5858", +"J c #142323", +"K c #042727", +"L c #489191", +"P c #000202", +"I c #000F0F", +"U c #0C0707", +"Y c #0B4B4B", +"T c #001C1C", +"R c #0B2A2A", +"E c #713232", +"W c #205C5C", +"Q c #233434", +"! c #194B4B", +"~ c #7B7070", +"^ c #262D2D", +"/ c #0D3232", +"( c #000101", +") c #023E3E", +"_ c #637979", +"` c #003535", +"' c #001414", +"] c #382A2A", +"[ c #609393", +"{ c #213E3E", +"} c None", +/* pixels */ +"}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}", +"}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}'8#o>'22>Pc}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}", +"}}}}}}}}}}}}}}}}}}}}}}}}}}}ccP#I2=---jGIcoo2+v}}}}}}}}}}}}}}}}}}}}}}}}}}", +"}}}}}}}}}}}}}}}}}}}}}}}}c(8##G=g+gno22o(G` mNtjj}}}}}}}}}}}}}}}}}}}}}}}", +"}}}}}}}}}}}}}}}}}}}}}}D}D#Vt=t-+22>>8o88jtC45UX5F=V}}}}}}}}}}}}}}}}}}}}}", +"}}}}}}}}}}}}}}}}}}}}nGDr'F`),Z)`-zA...A=jt)))f5m Xf++}}}}}}}}}}}}}}}}}}}", +"}}}}}}}}}}}}}}}}}}V8I#cgt`C54$^CC)lF&kAF)55XXCC)^X 4`jj}}}}}}}}}}}}}}}}}", +"}}}}}}}}}}}}}}}}}cGIcP+t`QQ)CQ@Y@Y))K3&l!5^]YCFjt``` `$m}}}}}}}}}}}}}}}}", +"}}}}}}}}}}}}}}}##88PIg-)^CFll)@]h@/NvSih5YlMKF033&jjt))`=G}}}}}}}}}}}}}}", +"}}}}}}}}}}}}}}8D++#2GK`YCKMl)Yh@YZiNvZd]YRSvMz0A34++8IjtVgD}}}}}}}}}}}}}", +"}}}}}}}}}}}}}}nj-jn83Kl)lRF/ZhhhZ//viy%YRvR/YYZlK0.k3c2'+PDP}}}}}}}}}}}}", +"}}}}}}}}}}}}8j/```j23zKFRli/ZYY,JvJ,%]%YRNi!Yhh@F&&koo2g2##Pc}}}}}}}}}}}", +"}}}}}}}}}}}o-mX``)lzkS0Sv///NJJxxx!W%%hiqi!hhhw;@iRzk.Aj-VcnI2}}}}}}}}}}", +"}}}}}}}}}}n-5$5C55YlMNRRvN,q,!!!!WWW96W{^uW%%%;$;$d@CAkA&t+#==&}}}}}}}}}", +"}}}}}}}}}G-$F$55C)UCZhhZqJq,!!W#}}}}}}", +"}}}}}}}tD#+>23.zFYdwW%%HfE69a91LLEELL19ww91L~E666Ha%%WZvS0lCCF2=tI}}}}}}", +"}}}}}}To#=+o3kSRZYh%a%%HHE6199LL[wB[L1pHH1LEEEL616%%%h/vS0lC^)-P`t2}}}}}", +"}}}}}}M8DVrg3SlCh%yw%%<6LwL1LLLBbbB[p_pHp[B~LEL_66W!WWRvSNR)$5f=2mX}}}}}", +"}}}}}o=#2>T&zRC;$%OE%<<66EELL[BbbB[__7Hp_B~E_E_L6g+}}", +"}}8otR-/f]CFNvvJJQ{Q^ywH1BBssssseeeb_:ees__777HHppaa^^QQJqvRZl&tF`=cTVo}", +"}}#>gjjFm^CFSvRRqfQ^ddyw1[BBs[ssseeeebeesss_77ppp1aay^QQ,Jvv/FKt-`j#'TG}", +"}}>8I22j`5CMSR/,qf^QOaHw1[[ss[[ssssseb:esss_7__p11aad^^Q,JvvSA&K-j+c>g'}", +"}}+(P##+-XCMviY,J^^uaaww1[[[[___sssse:_eees[_7ppp9aydQQQiJNRSS0tF+GcP2g}", +"}}Ur8o#Dt$CKvZYiqJ{OOyyH1_[[[_____ssee:bees[77ppHwydddQQiRNRNkAF-G2P(2G}", +"}}m82T=(j5)MS//,xJ^dddOwHpp___7____sse:bees__ppHHHay^QQQxRNNSSk&-'GcP>2}", +"}}48G=V#&5l0SR/RJJQ^^yaHHHHp777____ssebbess__HHHH9aOd^^qJNvSSS.K`tV22PG}", +"}}UDG+2c=$tSSNNNqx{{ddyywHppp77___[ssebb*Bs[_pp119aauQ{xqNNvvS&l``t=jDg}", +"}}UDo''I``S3AvvNq,{uudydwHpppH__77__[s*~*BBB[[11L19OdQQJvvNSS0&``)`- g8}", +"}}S''##=Uj4ASSSvqi!uaaydaHHHpp____77_[B*7bbBB[LLLL6WuQJqqvvSSAzF)`55t=#}", +"}}>+GDDjJ&30SkvvN!W!WWudOawHpp_p___77_[B*7b7E[EEE76o##}}}}}", +"}}}}}}}(8'VMXX`$$5CFRFRZZ]hYYuwfyWi,i,xJqJ!h;$hu@ivzl),x-+28D8gj+>}}}}}}", +"}}}}}}}crD#=-tJ5 $)tMFFlC$@ZYh;;vhii,i,/R,Zhvd^]ClS0Kt)`=>#onVmm+U}}}}}}", +"}}}}}}}}}#P#+VtU $)lttlC]]/R/ZYY^5hYYYZiiZ@^$$;])0.0&KF=+n>o2tVVU}}}}}}}", +"}}}}}}}}}}#P#2'F`XUJ))fk5)l&N/YZ@$^$5YYZZY]vv5U5l.0&K&t=+g>gVz+2}}}}}}}}", +"}}}}}}}}}P((#oD2=j`X5/$5)FtSS&l/ZCiZ]$YY{^^)Ck$,t4At&==g>##+VUg}}}}}}}}}", +"}}}}}}}}}}rP}#PrIVjF-j--&0.4.k00&MKlCf5UiCFR)]f)&rGj=go8(c#2mAr}}}}}}}}}", +"}}}}}}}}}}}c#}P(#>D>Ggn+2344444.A.S0KFFlFM&&l))t2o=+g##P#(2VSD}}}}}}}}}}", +"}}}}}}}}}}}}8D8>>c#r(D>#8P#3#443k43A0300AzKKjt=2#G+o#(cPD#8G }}}}}}}}}}}", +"}}}}}}}}}}}}}>nG'g+>}D8r#2VVV+A.3.V-KA3ro+&&V+GD8++>#PP}#Dr>}}}}}}}}}}}}", +"}}}}}}}}}}}}}}ogm=g'8D#D88+j+T=28IgjtjG>#8G++g8#I+ncDn+2'>r}}}}}}}}}}}}}", +"}}}}}}}}}}}}}}}344VT+g22PD2'I2GIrDGTj=GorrIgo>P2>#P8Gg+ U}}}}}}}}}}}}}}}", +"}}}}}}}}}}}}}}}}}8ImVVVgoD#>#D8r(82G+jjT28#Prr#Pr#2+mTm2}}}}}}}}}}}}}}}}", +"}}}}}}}}}}}}}}}}}}#(8+U VGn'nDDP}D2V=jjt+GDPr#8oGT +o 8}}}}}}}}}}}}}}}}}", +"}}}}}}}}}}}}}}}}}}}}c}82T4+g2o}#ccr8G'+TnD}DD8'TU2228}}}}}}}}}}}}}}}}}}}", +"}}}}}}}}}}}}}}}}}}}}}}P}##8VU=V2I>882I#P(r(#Ig0gIno}}}}}}}}}}}}}}}}}}}}}", +"}}}}}}}}}}}}}}}}}}}}}}}}(((#2+UUVGoo8nD#DDrc(D2Sr}}}}}}}}}}}}}}}}}}}}}}}", +"}}}}}}}}}}}}}}}}}}}}}}}}}}}>c8InGUG222oD88o>#P}}}}}}}}}}}}}}}}}}}}}}}}}}", +"}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}k8(}(rD>4 8}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}", +"}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}", +"}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}" +}; diff --git a/hacks/images/bubbles/blood2.xpm b/hacks/images/bubbles/blood2.xpm new file mode 100644 index 00000000..6a5c531f --- /dev/null +++ b/hacks/images/bubbles/blood2.xpm @@ -0,0 +1,101 @@ +/* XPM */ +static char *blood2[] = { +/* width height ncolors chars_per_pixel */ +"12 12 82 1", +/* colors */ +" c #000000", +". c #002E2E", +"X c #250000", +"o c #000D0D", +"O c #212A2A", +"+ c #000606", +"@ c #213030", +"# c #636A6A", +"$ c #072A2A", +"% c #445C5C", +"& c #4D5454", +"* c #163535", +"= c #000505", +"- c #052E2E", +"; c #041616", +": c #044444", +"> c #76C1C1", +", c #0C4545", +"< c #767F7F", +"1 c #002C2C", +"2 c #000B0B", +"3 c #030404", +"4 c #280404", +"5 c #385C5C", +"6 c #354F4F", +"7 c #001111", +"8 c #347272", +"9 c #6E3B3B", +"0 c #71B1B1", +"q c #000A0A", +"w c #270C0C", +"e c #001717", +"r c #253838", +"t c #418888", +"y c #013C3C", +"u c #192C2C", +"i c #000303", +"p c #164040", +"a c #032A2A", +"s c #520B0B", +"d c #001010", +"f c #435555", +"g c #0C3636", +"h c #8EAFAF", +"j c #282A2A", +"k c #515C5C", +"l c #1B5555", +"z c #002A2A", +"x c #2B3030", +"c c #4F3939", +"v c #AF5C5C", +"b c #003737", +"n c #010000", +"m c #001616", +"M c #042727", +"N c #0C3C3C", +"B c #030F0F", +"V c #002323", +"C c #0C4949", +"Z c #011A1A", +"A c #176464", +"S c #0F0000", +"D c #001C1C", +"F c #8A5B5B", +"G c #419A9A", +"H c #064949", +"J c #041919", +"K c #001515", +"L c #071212", +"P c #031B1B", +"I c #044040", +"U c #0F4E4E", +"Y c #242424", +"T c #031414", +"R c #063B3B", +"E c #2B5C5C", +"W c #396363", +"Q c #182525", +"! c #001414", +"~ c #506969", +"^ c #002121", +"/ c None", +/* pixels */ +"////!IByn///", +"//qV$UAp-7i/", +"//.w&8F89,:/", +"/z4cGv#05Qj1", +"/bgrt>h c #102222", +", c #4D5454", +"< c #163535", +"1 c #043737", +"2 c #4F6363", +"3 c #73C8C8", +"4 c #044444", +"5 c #001212", +"6 c #0C4545", +"7 c #767F7F", +"8 c #360505", +"9 c #000B0B", +"0 c #003939", +"q c #385C5C", +"w c #6D8686", +"e c #000404", +"r c #001111", +"t c #5AABAB", +"y c #001E1E", +"u c #71B1B1", +"i c #274E4E", +"p c #0D1A1A", +"a c #2B3E3E", +"s c #053333", +"d c #121515", +"f c #270C0C", +"g c #418888", +"h c #374343", +"j c #031D1D", +"k c #020505", +"l c #192C2C", +"z c #000303", +"x c #537272", +"c c #120E0E", +"v c #001010", +"b c #062323", +"n c #282A2A", +"m c #040000", +"M c #0C1515", +"N c #515C5C", +"B c #1B5555", +"V c #002A2A", +"C c #2B3030", +"Z c #4F3939", +"A c #000909", +"S c #001616", +"D c #042727", +"F c #247B7B", +"G c #074E4E", +"H c #0C4949", +"J c #011A1A", +"K c #55A1A1", +"L c #000F0F", +"P c #042020", +"I c #419A9A", +"U c #064949", +"Y c #1D4F4F", +"T c #000101", +"R c #286A6A", +"E c #044040", +"W c #693030", +"Q c #001B1B", +"! c #0C4141", +"~ c #031414", +"^ c #011212", +"/ c #172121", +"( c #002828", +") c #2B5C5C", +"_ c #000707", +"` c #343A3A", +"' c #AA7979", +"] c #506969", +"[ c #002121", +"{ c #213E3E", +"} c None", +/* pixels */ +"}}}}}[[rV8}}}}", +"}}}yjb#>pb~v}}", +"}}.0a/RF)Wf~.}", +"}}e6R+Ixg+BME}", +"} U=CW*w3KiOnJ", +"}f4Ohtu'7Nh/P%", +"}J1<`]:u32`lk_", +"}A&cRox-,ZRdL(", +"}e^b!nqhh)YG_9", +"}};E;X@{lfM0A}", +"}}T(ms!cH8(5j}", +"}}}JeQSDLA}r}}", +"}}}}}9L5z$}}}}", +"}}}}}}}}}}}}}}" +}; diff --git a/hacks/images/bubbles/blood4.xpm b/hacks/images/bubbles/blood4.xpm new file mode 100644 index 00000000..1642318a --- /dev/null +++ b/hacks/images/bubbles/blood4.xpm @@ -0,0 +1,116 @@ +/* XPM */ +static char *blood4[] = { +/* width height ncolors chars_per_pixel */ +"20 20 89 1", +/* colors */ +" c #000000", +". c #002E2E", +"X c #250000", +"o c #000D0D", +"O c #212A2A", +"+ c #013232", +"@ c #571010", +"# c #0D5858", +"$ c #000606", +"% c #196A6A", +"& c #60C0C0", +"* c #002020", +"= c #2E6E6E", +"- c #0A1616", +"; c #77D3D3", +": c #000C0C", +"> c #549393", +", c #001919", +"< c #002626", +"1 c #043737", +"2 c #000505", +"3 c #052E2E", +"4 c #044444", +"5 c #012A2A", +"6 c #001212", +"7 c #385656", +"8 c #0C4545", +"9 c #030404", +"0 c #001818", +"q c #142525", +"w c #485858", +"e c #000404", +"r c #340909", +"t c #739999", +"y c #264A4A", +"u c #094B4B", +"i c #001E1E", +"p c #040E0E", +"a c #000A0A", +"s c #648D8D", +"d c #053333", +"f c #001717", +"g c #418888", +"h c #374343", +"j c #040707", +"k c #031D1D", +"l c #000303", +"z c #070000", +"x c #AC6A6A", +"c c #120E0E", +"v c #001010", +"b c #6A7878", +"n c #0C3636", +"m c #000909", +"M c #003737", +"N c #446666", +"B c #042727", +"V c #002323", +"C c #295555", +"Z c #000202", +"A c #0E2A2A", +"S c #287878", +"D c #63A8A8", +"F c #042020", +"G c #567777", +"H c #001C1C", +"J c #8A5B5B", +"K c #419A9A", +"L c #064949", +"P c #001515", +"I c #194B4B", +"U c #1D2E2E", +"Y c #2D8686", +"T c #3C1B1B", +"R c #123A3A", +"E c #023E3E", +"W c #693030", +"Q c #3C5656", +"! c #242424", +"~ c #2C3939", +"^ c #0C4141", +"/ c #031414", +"( c #063B3B", +") c #020909", +"_ c #000707", +"` c #364949", +"' c #001414", +"] c #213E3E", +"[ c None", +/* pixels */ +"[[[[[[[_ v*m35[[[[[[", +"[[[[[62EX4B1zE 5[[[[", +"[[[[P:+B#^A^ndjPo[[[", +"[[[3rTnAIIS!%T@/+A[[", +"[[Xm/r%S=gJhYYT85fa[", +"[[ F8`SWKJGNxKyqBz<[", +"[P&x;bDs`](Lst;DbN7OqF.*", +"[_$BnOhNGbDxsw`Uq)fl", +"[6 c #002D2D", +", c #000C0C", +"< c #163535", +"1 c #6F8989", +"2 c #020707", +"3 c #000505", +"4 c #052E2E", +"5 c #012A2A", +"6 c #385656", +"7 c #040202", +"8 c #2B8181", +"9 c #040F0F", +"0 c #093838", +"q c #000B0B", +"w c #033232", +"e c #001818", +"r c #485858", +"t c #092424", +"y c #425252", +"u c #739999", +"i c #490D0D", +"p c #030A0A", +"a c #001E1E", +"s c #142B2B", +"d c #71B1B1", +"f c #8DA5A5", +"g c #6EC5C5", +"h c #001717", +"j c #013C3C", +"k c #002424", +"l c #031D1D", +"z c #1B5C5C", +"x c #011B1B", +"c c #000303", +"v c #0F1515", +"b c #AC6A6A", +"n c #120E0E", +"m c #001010", +"M c #282A2A", +"N c #5FA5A5", +"B c #606E6E", +"V c #054646", +"C c #225252", +"Z c #003737", +"A c #001616", +"S c #241F1F", +"D c #042727", +"F c #0C3C3C", +"G c #1E4747", +"H c #011A1A", +"J c #000F0F", +"K c #3E8787", +"L c #5E3030", +"P c #042020", +"I c #0F0000", +"U c #4E9090", +"Y c #031515", +"T c #8A5B5B", +"R c #000808", +"E c #041919", +"W c #0C5C5C", +"Q c #001515", +"! c #233434", +"~ c #000101", +"^ c #3C1B1B", +"/ c #044040", +"( c #637979", +") c #085151", +"_ c #2D6B6B", +"` c #364949", +"' c #002121", +"] c #0C4747", +"[ c #213E3E", +"{ c None", +/* pixels */ +"{{{{{{{{{c#'>Jon{{{{{{{{", +"{{{{{{{Q*j/l9'jS e{{{{{{", +"{{{{{#qh+w))vWw4pkjA{{{{", +"{{{{qZklD0@v=@[W42m#c{{{", +"{{{Qw&IW-Y&=r__KT`_8LS]PV4{{", +"{{tapV`=KKKb.rNL8Cs-&';{", +"{{5Z&WL8U1bNBddbXM-0Mj>{", +"{;7Iiz=81dTguugbyXG%);~n", +"{*Z^0v!6KNgffd1(O`S-F4ox", +"{q*i9<+6.NuugguB.6+-9DHe", +"{q'&9<+:rBB(dbdOy`!s9PA,", +"{R*ZY-[[y.BBuTdUKC!v9Z$e", +"{nHlx-Cz`yO.OUTLLL--YHIH", +"{q'kY9@I", +"{{h;YV]&j4V]i@<%]:VE0,m;{{", +"{{{c#m$%/9wV^)M255'#a{{{", +"{{{{q,3RqR77EED5#oc3 {{{", +"{{{{{pahc*ARkoJ,,qx{{{{{", +"{{{{{{{{xh{cQx{qIm{{{{{{", +"{{{{{{{{{,JImRoc{{{{{{{{", +"{{{{{{{{{{{{{{{{{{{{{{{{" +}; diff --git a/hacks/images/bubbles/blood6.xpm b/hacks/images/bubbles/blood6.xpm new file mode 100644 index 00000000..031f8030 --- /dev/null +++ b/hacks/images/bubbles/blood6.xpm @@ -0,0 +1,128 @@ +/* XPM */ +static char *blood6[] = { +/* width height ncolors chars_per_pixel */ +"30 30 91 1", +/* colors */ +" c #000000", +". c #002E2E", +"X c #214B4B", +"o c #2F5252", +"O c #013232", +"+ c #094747", +"@ c #115C5C", +"# c #186666", +"$ c #0E4F4F", +"% c #314040", +"& c #70D0D0", +"* c #000606", +"= c #270808", +"- c #8B6A6A", +"; c #1F0000", +": c #002020", +"> c #4F0E0E", +", c #000C0C", +"< c #001919", +"1 c #3E9191", +"2 c #0F0A0A", +"3 c #636363", +"4 c #000505", +"5 c #437878", +"6 c #044444", +"7 c #2E3232", +"8 c #001212", +"9 c #010909", +"0 c #1D2B2B", +"q c #360505", +"w c #023B3B", +"e c #093838", +"r c #485858", +"t c #002525", +"y c #5C9393", +"u c #011C1C", +"i c #121C1C", +"p c #274E4E", +"a c #163A3A", +"s c #813D3D", +"d c #000A0A", +"f c #053333", +"g c #121515", +"h c #396666", +"j c #021919", +"k c #001717", +"l c #040707", +"z c #000303", +"x c #070000", +"c c #502A2A", +"v c #226666", +"b c #001010", +"n c #021F1F", +"m c #718282", +"M c #1B5555", +"N c #AF5C5C", +"B c #5C7777", +"V c #042727", +"C c #0C3C3C", +"Z c #5AB0B0", +"A c #002323", +"S c #374F4F", +"D c #000202", +"F c #021111", +"G c #000F0F", +"H c #444B4B", +"J c #1E1F1F", +"K c #002929", +"L c #2E7777", +"P c #000808", +"I c #0A2C2C", +"U c #001515", +"Y c #233434", +"T c #315C5C", +"R c #154747", +"E c #2D8686", +"W c #000101", +"Q c #000E0E", +"! c #085151", +"~ c #1C3D3D", +"^ c #042C2C", +"/ c #0C4141", +"( c #080F0F", +") c #172121", +"_ c #516767", +"` c #003535", +"' c #7FC2C2", +"] c #6D9696", +"[ c #001414", +"{ c #020202", +"} c None", +/* pixels */ +"}}}}}}}}}}}}G,tKtDG}}}}}}}}}}}", +"}}}}}}}}}A}<:GU4Wt;;Kn}}}}}}}}", +"}}}}}}}}G4K/;!6Vn=xww .}}}}}}}", +"}}}}}},,[O6^+@/(@C(l{::KP}}}}}", +"}}}}}d``,VIe+I)#@i+@^j9[4z}}}}", +"}}}}b;q=feg)XvMLo~#v#>f9O:x}}}", +"}}}}b`u^X>#vvLLcSTvL>#@IfK=}}}", +"}}}kuFk/S@>Lh1H1rh31E##g^64k}}", +"}}[W4[+pTLE11]ZBryNsEX~gV=6t,}", +"}}2U`=@#cE1sZZ]3]ZNmT70i/0J8g}", +"}};`q7>MLBsN'&]m]ZZNHhX)+>2Kk}", +"}8q`=!R~YT1ZZ-&&Zm]y_SX)CC6KdG", +"}*.q+i)07S5Z]Z&-&]33_h7agCVw}2", +"}G,n6(R)XS5y]m]&-'m35SYYi(uAdk", +"}[u*6(e)%%rBBBBZ-&m_rSYY)(Fk}:", +"}J^DK }", +"}}*:O.f+ee~#cHppJYR@gif=`[P[,}", +"}}}D2wkVAQ[[}}}", +"}}}}4Wz:)O^j9VI+>qflVn:Q}nz}}}", +"}}}}}d,4D,,*{9ljuuVt*kW}, }}}}", +"}}}}}},;k,d<<88.b9 c #084242", +", c #030505", +"< c #3E9191", +"1 c #163535", +"2 c #474E4E", +"3 c #011D1D", +"4 c #000505", +"5 c #57A6A6", +"6 c #052E2E", +"7 c #033939", +"8 c #360505", +"9 c #2B8181", +"0 c #012323", +"q c #000B0B", +"w c #366E6E", +"e c #033232", +"r c #021A1A", +"t c #233737", +"y c #0A0E0E", +"u c #171E1E", +"i c #002525", +"p c #6A8D8D", +"a c #77CBCB", +"s c #000404", +"d c #5FBABA", +"f c #739999", +"g c #0A2828", +"h c #012929", +"j c #364646", +"k c #001111", +"l c #030A0A", +"z c #5C9999", +"x c #0C5151", +"c c #000A0A", +"v c #332525", +"b c #2B3E3E", +"n c #064B4B", +"m c #262222", +"M c #173E3E", +"N c #0E1E1E", +"B c #192C2C", +"V c #AC6A6A", +"C c #062323", +"Z c #5C7777", +"A c #001616", +"S c #051111", +"D c #042727", +"F c #4A0909", +"G c #776D6D", +"H c #7FB0B0", +"J c #000202", +"K c #000F0F", +"L c #042020", +"P c #0F0000", +"I c #001C1C", +"U c #260606", +"Y c #713232", +"T c #5A6767", +"R c #000808", +"E c #021717", +"W c #135959", +"Q c #385959", +"! c #194B4B", +"~ c #000101", +"^ c #044040", +"/ c #264747", +"( c #0F0C0C", +") c #2B5C5C", +"_ c #000707", +"` c #003535", +"' c #343A3A", +"] c #495F5F", +"[ c #182525", +"{ c #245858", +"} c #0C4747", +"| c None", +/* pixels */ +"||||||||||||||||cX&&J|||||||||||||||", +"||||||||||||sq%;+k&XA $hi|||||||||||", +"||||||||||kR&`1^:&K&i7^8 m+|||||||||", +"|||||||||As+`O>xx^DL!Oneh` U||||||||", +"|||||||c+_A`nC^W}-Nb}yCrl+ci3R||||||", +"||||||c@`0lDg-}xu[**@M}W6LXk&%s|||||", +"|||||k88FnCg(11!!#w{O{*oo'>,L+;L||||", +"|||||he7LF/.!b##))Y)t##Y'Wv6,`+8||||", +"||||Ic:&rUo*2##w=JX|||", +"|||I_+ly>W)*]9wU/*'Y9<25VzpTzdHV5Q'O[N-OFh:$|", +"||y`mmboW*oYY2dVHfpfddV52w/t[xvU-sL|", +"||;P8$FWW!{wz5dVHaHfpzz5]Q{/uxnO^s;|", +"||i`-m-NutbQ<5daaVHapppZ]Q'mug-7eXE|", +"|_A0$>S@ut'j=5zffaaaffT]]QjO1N@D:i&A", +"|+J%:>SxuO)2=zppffapaHZ]TQ'tMNyreAJA", +"|$k;i^S-BOb.]TZTZpHHaHZ]2QtOBNS,:AJ&", +"|PA&;hSNubbj2]TTZpHVdzZZ=Q/buNSL`h0E", +"|y&%P,Syu!)jQ2]ZZTp5TV5<<9/[uSy378h_", +"||A+7lrNNW#..j]TZT]Z5GZY'o{[ygEE3P3|", +"||;i`X3S-M!bbj'2222]]=<n--M!*o#))O/OWWv@N}F6+4_&||", +"|||_IUm$8>6>xF**o!MBuMWv!gg$7;cRX_||", +"||||s4:u 7C6nxxFyM11g}(OnSD7;%k$+|||", +"|||||4_&`P7mF7N}xtFx}v(PerDh+X3+||||", +"|||||s|JK0::0KKrLD>8M67m0A;X~_$s||||", +"||||||ccX4~Xq%%,,lrrEDi;%+4sRc |||||", +"|||||||X$Aq%q++;qAhA%A+qKkc+&s||||||", +"|||||||||K33X%_q~&+0&_s4s&$$||||||||", +"||||||||||sqI+&|ssA+k|c&P&c|||||||||", +"||||||||||||~~kP3Xcccs~&s|||||||||||", +"||||||||||||||||c|sX |||||||||||||||", +"||||||||||||||||||||||||||||||||||||" +}; diff --git a/hacks/images/bubbles/blood8.xpm b/hacks/images/bubbles/blood8.xpm new file mode 100644 index 00000000..44cc05ec --- /dev/null +++ b/hacks/images/bubbles/blood8.xpm @@ -0,0 +1,143 @@ +/* XPM */ +static char *blood8[] = { +/* width height ncolors chars_per_pixel */ +"44 44 92 1", +/* colors */ +" c #000000", +". c #214B4B", +"X c #250000", +"o c #000D0D", +"O c #0D4B4B", +"+ c #7B6868", +"@ c #013232", +"# c #094747", +"$ c #4A5C5C", +"% c #283434", +"& c #002727", +"* c #190101", +"= c #000606", +"- c #121111", +"; c #236060", +": c #213030", +"> c #4F0E0E", +", c #77D3D3", +"< c #000C0C", +"1 c #206D6D", +"2 c #242222", +"3 c #7FA6A6", +"4 c #163535", +"5 c #474E4E", +"6 c #000505", +"7 c #263E3E", +"8 c #437878", +"9 c #001212", +"0 c #5DA5A5", +"q c #2E4C4C", +"w c #000B0B", +"e c #021A1A", +"r c #135C5C", +"t c #001818", +"y c #171E1E", +"u c #739999", +"i c #452A2A", +"p c #001111", +"a c #5B6767", +"s c #001E1E", +"d c #022D2D", +"f c #183C3C", +"g c #032424", +"h c #134E4E", +"j c #000A0A", +"k c #374343", +"l c #6ABABA", +"z c #618D8D", +"x c #043535", +"c c #192C2C", +"v c #000303", +"b c #AC6A6A", +"n c #044242", +"m c #021212", +"M c #0D2020", +"N c #0A0606", +"B c #718282", +"V c #0C1515", +"C c #113E3E", +"Z c #002A2A", +"A c #348B8B", +"S c #5C7777", +"D c #2E0808", +"F c #142323", +"G c #000F0F", +"H c #021E1E", +"J c #001C1C", +"K c #0B2A2A", +"L c #081010", +"P c #2E7777", +"I c #020A0A", +"U c #4F6666", +"Y c #305858", +"T c #000808", +"R c #041919", +"E c #001515", +"W c #002222", +"Q c #0D3232", +"! c #020303", +"~ c #000101", +"^ c #032828", +"/ c #085151", +"( c #396A6A", +") c #7C3232", +"_ c #0C4141", +"` c #385F5F", +"' c #003535", +"] c #343A3A", +"[ c #001414", +"{ c #033B3B", +"} c #4A9191", +"| c None", +/* pixels */ +"||||||||||||||||||||||<|||||||||||||||||||||", +"||||||||||||||||=Tv6wZZtvtss-|||||||||||||||", +"||||||||||||||vvsWZEoG=op&N**Qs|||||||||||||", +"||||||||||||=j<@n*>n^eR9dn_>> !XJ|||||||||||", +"||||||||||~96=Z##n#//{KR#X%#xW'@ *V|||||||||", +"|||||||||~EoEd#x^{//OQV/>QLRLG=HjZWE||||||||", +"||||||||=d's6^xKCCrhK-O1OMQh/{HLT<[6~|||||||", +"|||||||&X{{{GLLKQMFc4rPr4CrrY]_K=mdtp<||||||", +"||||||DXcX/>xO_yyC;1.;A1:.115>rD/RG&pd-|||||", +"|||||eJsnHHirDrOr;1PYP)(%Y;;(irirxG^{oDJ||||", +"|||||e6WsR^D>1>PP;P8A)+8k`AAP))2>#g^4d<[||||", +"||||!wsoIHCr);$:P`8A)}AU58z]AA$11QLHn{sM9|||", +"||||[E~mR#]k11PaAAA0b}SS$}5}SAP..KVgx*cTX|||", +"|||E[=&x>>-2PPP})}0b0zaSzla)S8q%:y-Qn>nZ&W||", +"|||X&ZiDO/ri))A+50bl0zSz,lbb0`k]:FFC/=>'<&||", +"||s*'Di%-kr1))a)+l+,luBBlllbB$``.7FC/%*2:2H69DJ||", +"||||J^ys&{O/_Q444;1P111%.%:.r1rMV_D2dt=vW9||", +"||||j&d'@{nnQQCrk)i);.7:::frr-hVKiX{&Tj6o|||", +"|||||e&yNX>nxK#r.ri2rfCcFc..>r_Lx>{WGv<9=|||", +"|||||vv&ZD*{gKx:hO]>rC44KQrD%Odm^{^j-iO_O>D=nGR&ds99WEo||||", +"|||||||~ojs@D':dg=gd{QO>fD{#={!&Ws<6E*j|||||", +"|||||||j|vwjttJo!!!LLRdx{^exnWGs[T=6sN||||||", +"||||||||op9 c #043737", +", c #020707", +"< c #123131", +"1 c #000505", +"2 c #437878", +"3 c #001212", +"4 c #360505", +"5 c #000B0B", +"6 c #366E6E", +"7 c #021A1A", +"8 c #226E6E", +"9 c #051313", +"0 c #280404", +"q c #0B2626", +"w c #385C5C", +"e c #022727", +"r c #67C2C2", +"t c #171E1E", +"y c #6A8D8D", +"u c #474D4D", +"i c #000404", +"p c #001111", +"a c #5B6767", +"s c #256060", +"d c #8D6A6A", +"f c #001E1E", +"g c #000A0A", +"h c #332525", +"j c #2B3E3E", +"k c #053333", +"l c #270C0C", +"z c #115959", +"x c #253838", +"c c #002424", +"v c #031D1D", +"b c #192C2C", +"n c #093030", +"m c #63A9A9", +"M c #054646", +"N c #113E3E", +"B c #000909", +"V c #5C7777", +"C c #033030", +"Z c #285151", +"A c #001616", +"S c #4A5858", +"D c #142323", +"F c #000202", +"G c #000F0F", +"H c #0C0707", +"J c #001C1C", +"K c #713232", +"L c #154747", +"P c #000101", +"I c #023E3E", +"U c #000E0E", +"Y c #085151", +"T c #0F4E4E", +"R c #82C2C2", +"E c #1C3D3D", +"W c #204E4E", +"Q c #060D0D", +"! c #063B3B", +"~ c #032121", +"^ c #000707", +"/ c #003535", +"( c #343A3A", +") c #050202", +"_ c #021616", +"` c #012C2C", +"' c #364949", +"] c #001414", +"[ c #609393", +"{ c #0C4747", +"} c #4A9191", +"| c None", +/* pixels */ +"||||||||||||||||||||||||||||||||||||||||||||||||||", +"|||||||||||||||||||ii5Ae/`:oi1Ge||||||||||||||||||", +"||||||||||||||||i^i]ffAAp5B^$4 4/::|||||||||||||||", +"||||||||||||||o3Bf//MI:o99g3$/I!lH)f:|||||||||||||", +"||||||||||||BBU1o`M4#YMM>eX`Y4){ICn 4:f|||||||||||", +"|||||||||||1]PPo/@I>IYYYC~_MHMIIc3`:/D0:||||||||||", +"||||||||||io$UACYk~>Yz{{n-z(>Q-~v9ioU3:op|||||||||", +"|||||||||g`/`3XCkeN>TzED&Lsz->NYY!~9ggpA^|||||||||", +"||||||||c#4/Ic,_QqNqtDbbW+OLDLzz(WNeg3f`pUB|||||||", +"|||||||-)n4H4Me>n&qDWssZs+8E@sO8K'Z*Yv=9CP`:||||||", +"||||||fColIeIEj4TM$opg||||", +"|||||$=AoX9ez*OOSK+s6+}yd}2SS6}a++6uOOeQ`M/G4=||||", +"||||pBo]givNTO8O%K+26+mK}VV%a}d(}++OOT-QeMMCBti|||", +"||||#PoA77{*O*88+}a}}mdmyVVSVydy}}8WEN&-e!44$:#|||", +"|||1e1]e!044*h8++}K}}ymm[aVymydK}2'j@b&D>MhM`i)o||", +"|||oqfI#4LzOOhh2+VKmmdmm[V[rRmddmw'j@@DqNYH#Ioc#||", +"|||04/4@N&WzzKKKdKSdrdmmyy.mrrrdmSw6WxbD{Yh4#:^:||", +"||J~HI#H4**zW882}mmrRdRRRyy.mmmrm2u6sZ@DNYYhH`Pfo|", +"||ot#/M0TYLEExjw2+mmrRdRRRRy.ymm}au''Z@tN{MM/eFoJ|", +"||p#D#<@!--t@jjwS}mmmRrRd.RmyVyVaSSw(@@DD>!C`/53o|", +"||1f`I4I~QqD@x('SymmmymRRRRRy[aaSS2w'@@b--k~e/f5f|", +"||1=3:#M9qND;xwwuV}m[yyymR.RmyVaaV2w(@@<--9v`:31A|", +"||FB13;IQNLt@Zs'u2}yyVyyyRRRRR[aaaS'(jxEDqQ7Cfp|A|", +"||=of14!9n>b;xj'u%aVVaVVymRdrmya%SS'@x@bD-9ieAAi3|", +"||gooFICQqDtbxx'uuSSaaVyymrdrmVa%S6wWx@DD9Q_/C$o1|", +"||g3A34QQ--&EZW'(S%VSVaaymmdmm}y222wW@b&-QQc//`#p|", +"||ogF`C,_Q&tLWsZ(wSSVVVVaV[madmm}}2+Z@Dt&Q,_I/)cf|", +"||oB3/`g_,--TWsZ@''SaaVVS%VymSdKKKKKsEt&-~99f$4f&|", +"||35o#civv9nENWZ@''uuSSSSSSV2+}ddK@+O<&-n~vgU$0$o|", +"||^ofH`Xi~Qn{LEx;jj(wSSSSuSSSS62+aKKWq-NIC91U::3Q|", +"|||f1C/]i79eNLL<;@@jww66w''''''ssss'L&>YN!91|too||", +"|||1]f CX,eM{TLED;@xsZ666w'''@jZZWOzqqY4@{{N<<<@Ws88888jWZ@xWWOOn&nN0MCoBi$#1||", +"||||i$~`CCk!M!>>>TzOKh8sZZx@x;LzO*z-&NH4>:Bgi]5|||", +"||||^=f C##;M>C>{zlzsZ*sEE@DtEzzlWT-~M0>c3B1gi=|||", +"||||||=ott/i4kee>{W{z**W<<,C!>ep=gf$=||||", +"|||||Pi|Acl)4>eCM*N>{zj@T{{N>{@lhL~7c``o^Gfv |||||", +"|||||||iF3AC4#bN0M>7e{{4Y4{{{*44,IXve:$o=o:J5|||||", +"|||||||PP5i3://C>evggeeekMlhlIkh4>i~cf3B|A)5||||||", +"||||||||g|FiBBA]o=ii,,_X_eC>C~c>>vU$A1P1=fH|||||||", +"|||||||||==ppBP=1iG39,iXvei=3c::oPo]|FFPP=||||||||", +"||||||||||]#JoBiBgo$ffUp$eoUB3Jog1oG1G33i|||||||||", +"||||||||||| Hfo]]|B=UAiUAc$]B^p51giBA7Qg||||||||||", +"||||||||||||BF3)&op3^g|5ofc:oGFi1Go)p)g|||||||||||", +"|||||||||||||||i=AfApFi1^3p3BiB=A#pGB|||||||||||||", +"||||||||||||||||iF|U##A]==p^^FPgH31|||||||||||||||", +"|||||||||||||||||||=i=pA9A355pgi||||||||||||||||||", +"||||||||||||||||||||||||||||||||||||||||||||||||||", +"||||||||||||||||||||||||||||||||||||||||||||||||||" +}; diff --git a/hacks/images/bubbles/blue.pov b/hacks/images/bubbles/blue.pov new file mode 100644 index 00000000..86d1ff8d --- /dev/null +++ b/hacks/images/bubbles/blue.pov @@ -0,0 +1,22 @@ +#include "colors.inc" +#include "shapes.inc" +#include "textures.inc" + +/* The following make the field of view as wide as it is high + * Thus, you should have the -W and -H command line options + * equal to each other. */ +camera { + location <5.8, 0, 0> + up <0, 1, 0> + right <1, 0, 0> + look_at <0, 0, 0> +} + +sphere { + <0,0,0>, 2.5 + texture { Blue_Agate + scale <0.7, 0.7, 0.7> } + finish { phong 1 } +} + +light_source {<6, 1, 0> color White} diff --git a/hacks/images/bubbles/blue1.xpm b/hacks/images/bubbles/blue1.xpm new file mode 100644 index 00000000..8bdd9b2f --- /dev/null +++ b/hacks/images/bubbles/blue1.xpm @@ -0,0 +1,64 @@ +/* XPM */ +static char *blue1[] = { +/* width height ncolors chars_per_pixel */ +"10 10 47 1", +/* colors */ +" c #000000", +". c #2A2A47", +"X c #2E2E4E", +"o c #1D1D30", +"O c #1B1B2E", +"+ c #0C0C12", +"@ c #0A0A10", +"# c #17172A", +"$ c #25253E", +"% c #12121E", +"& c #20202F", +"* c #141423", +"= c #2F2F4E", +"- c #1A1A2C", +"; c #333355", +": c #1D1D2B", +"> c #282843", +", c #303051", +"< c #111122", +"1 c #161620", +"2 c #0A0A14", +"3 c #25253F", +"4 c #2B2B48", +"5 c #2F2F4F", +"6 c #101020", +"7 c #18182B", +"8 c #353558", +"9 c #15151E", +"0 c #191925", +"q c #13131F", +"w c #0D0D19", +"e c #151524", +"r c #343456", +"t c #1F1F34", +"y c #0C0C14", +"u c #0A0A12", +"i c #494967", +"p c #23233B", +"a c #0C0C17", +"s c #292944", +"d c #121223", +"f c #BCBCD7", +"g c #1A1A2E", +"h c #0B0B15", +"j c #262640", +"k c #171724", +"l c None", +/* pixels */ +"lll13p32ll", +"llw.5=5j0l", +"l->6;r;5p2", +"l9:5Of8,7t", +"lh#=;id=s*", +"la$4XgX4$1", +"lq%ks<&3tq", +"lleo1q1oyl", +"lll+eue@ll", +"llllllllll" +}; diff --git a/hacks/images/bubbles/blue10.xpm b/hacks/images/bubbles/blue10.xpm new file mode 100644 index 00000000..5c589501 --- /dev/null +++ b/hacks/images/bubbles/blue10.xpm @@ -0,0 +1,157 @@ +/* XPM */ +static char *blue10[] = { +/* width height ncolors chars_per_pixel */ +"60 60 90 1", +/* colors */ +" c #000000", +". c #0D0D1A", +"X c #2A2A47", +"o c #282845", +"O c #151525", +"+ c #303050", +"@ c #111121", +"# c #2E2E4E", +"$ c #0F0F1F", +"% c #1D1D30", +"& c #0E0E17", +"* c #0A0A13", +"= c #25253E", +"- c #23233C", +"; c #21213A", +": c #10101C", +"> c #262638", +", c #121221", +"< c #2F2F4E", +"1 c #2D2D4C", +"2 c #333355", +"3 c #282840", +"4 c #2E2E49", +"5 c #0F0F1A", +"6 c #1F1F2D", +"7 c #0D0D18", +"8 c #0B0B16", +"9 c #282843", +"0 c #262641", +"q c #11111F", +"w c #0F0F1D", +"e c #19192A", +"r c #323253", +"t c #040408", +"y c #212135", +"u c #1F1F33", +"i c #08080F", +"p c #23233A", +"a c #212138", +"s c #10101A", +"d c #181825", +"f c #25253F", +"g c #202030", +"h c #2B2B48", +"j c #181828", +"k c #141424", +"l c #313151", +"z c #2F2F4F", +"x c #1C1C2F", +"c c #1A1A2D", +"v c #18182B", +"b c #161629", +"n c #202036", +"m c #1C1C32", +"M c #090912", +"N c #13131F", +"B c #11111D", +"V c #2A2A46", +"C c #131322", +"Z c #2E2E4D", +"A c #38385A", +"S c #343456", +"D c #151527", +"F c #06060B", +"G c #1B1B30", +"H c #0C0C14", +"J c #DDDDEB", +"K c #494967", +"L c #23233B", +"P c #0C0C17", +"I c #1C1C2A", +"U c #292944", +"Y c #0A0A15", +"T c #161624", +"R c #141422", +"E c #0E0E1C", +"W c #2B2B49", +"Q c #121223", +"! c #1E1E32", +"~ c #0B0B12", +"^ c #090910", +"/ c #07070E", +"( c #15151F", +") c #222239", +"_ c #202037", +"` c #1E1E35", +"' c #262640", +"] c #696985", +"[ c #151522", +"{ c None", +/* pixels */ +"{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{", +"{{{{{{{{{{{{{{{{{{{{{{{{F&N,eOeeRj7&q{{{{{{{{{{{{{{{{{{{{{{{", +"{{{{{{{{{{{{{{{{{{{{{:7e8x((!uuqbD,8xjH[{{{{{{{{{{{{{{{{{{{{", +"{{{{{{{{{{{{{{{{{{/de8q&((a))cxP@CP78d%x*&B{{{{{{{{{{{{{{{{{", +"{{{{{{{{{{{{{{{{Fdcxx(I)p-=v..E=.d=Id!nn!x&dF{{{{{{{{{{{{{{{", +"{{{{{{{{{{{{{{{Hex(P)d-=fkL@@kLOI00'fwbu)T*NO:{{{{{{{{{{{{{{", +"{{{{{{{{{{{{{*Pc!vCwq%6099@wIe@`'0O990'==pE(!cjB{{{{{{{{{{{{", +"{{{{{{{{{{{{8jMPnP:c)09UVC$$hIC0_CgVVU90'E`[n!qeR{{{{{{{{{{{", +"{{{{{{{{{{{B:c,Tp,.k9UVhhWW-1U1@@hyWhhVUg)6=p(b8eR{{{{{{{{{{", +"{{{{{{{{{{i:8vOL)E$$VhhW111ZZZZZLc111Whgkv6'=Lc.*eH{{{{{{{{{", +"{{{{{{{{{&exEvLLEE:ghW11ZVXcfg>>@_=>Z1Ox,,`6d=LcxPe/{{{{{{{{", +"{{{{{{{{qj:7.Ldv9UXhW1Z#zvvmz0r%hv_D+z2>0vGcl+gcWcg)L30'x)n%eO{{{{{{", +"{{{{{{NjP:a:m0pEhW1Zz++lrr>9W>2ce_vmhlym0yCgCg60=.ad8MN{{{{{", +"{{{{{^/N%njBq9UmW1Z<+ygr22@z+vkx222<2rvQggy>OhU9k.)nCMT/{{{{", +"{{{{{NP8javv6U601Z$`WWk<2ccQk%SSSS1222+mkzkcv2QbVk+zZ1WhwL'=)nj*T^{{{", +"{{{{qiMqOx;x9V6Q@L0vlf@22Xvc>SS9uSQ>vODZb2Sv9SSSSS>2>SSkvvrl+23k`3AAAA>cSSS2Vkrl+zZ1,w6E[=)n8cii{{", +"{{{qdw8:[O@EE@g1g0D@Dg22ck`!rlKKKAASS2v=rl+z#1;EvE:=pnd.di{{", +"{{{CjMb[D@k9g@D1#61vc#2Skx)>A]]]]KAASS2Lkl+z#1f`vI=wLa!eOC{{", +"{{~Ne8([emI9I6$1#zzD@1DSxlAK]]JJ]]KASS2vvl+z#1@,v6xcLau(*R~{", +"{{&8e5uaaBu96h`6#z+lD`bSS24]JJJJJ]]ASS2l@@>z#1bL$0k.dauxMO&{", +"{{s[D7PIC)69Vhv9gz+le@OSbuA]JJJJJ]]AAS2o__@kZ1gvxw$@RadN:/s{", +"{{:Te%8aBm:gV6IG@e+ll_>2cg]]JJJJJ]]AA2vzVDG=g1$;EGEb_d&P:s&{", +"{{:T(%uaLC':x,=Q1=y+lm`2m!4]]JJJJ]KAuhcc+@v9g1WhgEEC,ad8e:7{", +"{{:TexuaLp'qv,@@V-g+lf_2hxKK]]]J]]KyvbvG@@oyg1hXU)DBLaqkqR:{", +"{{:&eP8ap=',v@kxjg<+mbkr2ke4KAK]]KAvQrrlyyr4KAASk@yl++z#Z1WhV90.d)nPTMs5{", +"{{s[s,8P)L='9LEwy1Z@@W+lLk3S<2!ASS2>mk++z+,`k+#@hllll++_`Z#G#@vWc+zzz<#ZZ$gWhXUUII=@OP8%(8/:F{", +"{{{HRM78Pn)Lw.,IUVXh,$D1ZZZ#DQ`<<#ZZZ11D@EXVU90'=e8qbxe:*^{{", +"{{{FqTj8Pxa[nDEg9UUXx@$W111ZZDhZZZ11)cm;@,UU90'=Ln878(eM&H{{", +"{{{F:[dk88naqkcC09IUUmG@9g311_$g11WWWC$LIE000I=-)a88xcdi:/{{", +"{{{{5HTi8*!nCvC='09O$$k`,6WWWgVDWWWhhheVU9G.)q-maneOceT~5{{{", +"{{{{MH[H58duk8d-='0EEwggVXXhhIE,hhXXVgUU90=L..Pwn(.Oed[7F{{{", +"{{{{t5NT7Mc!qDIp-NTE.099UUUVgd@@EVUUg0g0C'fB@v!Eux.:jTNFF{{{", +"{{{{{HHRMMBx!YTa))E.@'00999dC`cxm999IL@q-w=Lddcc!x8:DR:H{{{{", +"{{{{{t&qM*McxkYna)POB='''00CgbEjp0006I6==-L)an,%xcMR[/&F{{{{", +"{{{{{{i5:OReNM7dnax8.d===''.xCD=%'''===-L))anuY8c(P*HFt{{{{{", +"{{{{{{{H:/&seb&xe`n85)LL-==xvC.w====-LL))an`,kBHe:i/FF{{{{{{", +"{{{{{{{FH:NOd[M.Y!u7kqTd)pPP`kx-LLLp))).Tnu8CDcPdN/&FF{{{{{{", +"{{{{{{{{i&iiO:MC.x%!8D8c(a:PD[N%)))a(anPu!%d:858HN://{{{{{{{", +"{{{{{{{{{^&:N/Mdecxx%&8c`dq.:aaannnn`u8*%xxcMi7/M:&t{{{{{{{{", +"{{{{{{{{{{^7HH/[djec(*je!:.duuuuuu!!!(5((cesOqqi/7^{{{{{{{{{", +"{{{{{{{{{{{FHsqC[Td&MRB(xPPN%Nj%%%%(c8ccNjs/*8&FH^{{{{{{{{{{", +"{{{{{{{{{{{{F/57/7*i:MeeH.scxxxxxccceeej~CiC*^~*/{{{{{{{{{{{", +"{{{{{{{{{{{{{F*^5FiR[TDd*P8eee:eeeejjdDiMMFHFFtF{{{{{{{{{{{{", +"{{{{{{{{{{{{{{{i^H~:qNR[OT8&RM*dsHTTO[RNi:^FtF{{{{{{{{{{{{{{", +"{{{{{{{{{{{{{{{{FFF75:BqN~////HRsRRNNqFH5*/tF{{{{{{{{{{{{{{{", +"{{{{{{{{{{{{{{{{{{tFi^755H*F8i&BBB::557H*tF{{{{{{{{{{{{{{{{{", +"{{{{{{{{{{{{{{{{{{{{{Fi*~^^HFF^&H7HH^*tF{{{{{{{{{{{{{{{{{{{{", +"{{{{{{{{{{{{{{{{{{{{{{{{FFtttFi^^iFFF{{{{{{{{{{{{{{{{{{{{{{{", +"{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{", +"{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{" +}; diff --git a/hacks/images/bubbles/blue11.xpm b/hacks/images/bubbles/blue11.xpm new file mode 100644 index 00000000..81be233f --- /dev/null +++ b/hacks/images/bubbles/blue11.xpm @@ -0,0 +1,169 @@ +/* XPM */ +static char *blue11[] = { +/* width height ncolors chars_per_pixel */ +"72 72 90 1", +/* colors */ +" c #000000", +". c #282845", +"X c #191929", +"o c #151525", +"O c #303050", +"+ c #2E2E4E", +"@ c #0F0F1F", +"# c #1D1D30", +"$ c #29293F", +"% c #17172A", +"& c #2F2F48", +"* c #0E0E17", +"= c #1B1B31", +"- c #272740", +"; c #181824", +": c #25253E", +"> c #10101C", +", c #1E1E2D", +"< c #0C0C18", +"1 c #1C1C2B", +"2 c #1A1A29", +"3 c #262638", +"4 c #121221", +"5 c #1A1A2C", +"6 c #161628", +"7 c #333355", +"8 c #24243C", +"9 c #151520", +"0 c #202038", +"q c #0B0B16", +"w c #282843", +"e c #262641", +"r c #151523", +"t c #0F0F1D", +"y c #1B1B2C", +"u c #19192A", +"i c #323253", +"p c #131324", +"a c #040408", +"s c #111122", +"d c #212135", +"f c #1F1F33", +"g c #23233A", +"h c #10101A", +"j c #0A0A14", +"k c #25253F", +"l c #12121F", +"z c #202030", +"x c #0E0E1B", +"c c #2B2B48", +"v c #181828", +"b c #141424", +"n c #313151", +"m c #2F2F4F", +"M c #1C1C2F", +"N c #1A1A2D", +"B c #0B0B11", +"V c #202036", +"C c #22223B", +"Z c #11111D", +"A c #0D0D19", +"S c #2A2A46", +"D c #171726", +"F c #131322", +"G c #111120", +"H c #2E2E4D", +"J c #38385A", +"K c #343456", +"L c #151527", +"P c #06060B", +"I c #0C0C14", +"U c #DDDDEB", +"Y c #494967", +"T c #080810", +"R c #23233B", +"E c #0E0E19", +"W c #0C0C17", +"Q c #292944", +"! c #2D2D4B", +"~ c #0E0E1C", +"^ c #2B2B49", +"/ c #1E1E32", +"( c #18182C", +") c #07070E", +"_ c #222239", +"` c #1E1E35", +"' c #090913", +"] c #696985", +"[ c #2C2C49", +"{ c None", +/* pixels */ +"{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{", +"{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{T'o*DDZooI){{{{{{{{{{{{{{{{{{{{{{{{{{{{{{", +"{{{{{{{{{{{{{{{{{{{{{{{{{{{)ZWqyMMMlMMMM>u56TF{{{{{{{{{{{{{{{{{{{{{{{{{{", +"{{{{{{{{{{{{{{{{{{{{{{{{lDvxM#r;;DVVAq<(xFb#Mx'>F{{{{{{{{{{{{{{{{{{{{{{{", +"{{{{{{{{{{{{{{{{{{{{{{oXyq(6lV0___2W>5qxMN0;x'yD*{{{{{{{{{{{{{{{{{", +"{{{{{{{{{{{{{{{{{I5M/Ax_r<8k--2wxG>`R4b5oxw--2_;R_l6/Mv6{{{{{{{{{{{{{{{{", +"{{{{{{{{{{{{{{{TFy#f2Ab=Zo,wwQb`toS1f=b8-1QQww-e:2Nx9f#Gvl{{{{{{{{{{{{{{", +"{{{{{{{{{{{{{{*'Aqx00AxozwwQSSzS@o[X(k%FSbcSSQww-8x_00`6yvF{{{{{{{{{{{{{", +"{{{{{{{{{{{{{F>E;MyR_b(4wQSSc[[[!!!d!!6@@[[[cSS,DV_k8R;4WWXr{{{{{{{{{{{{", +"{{{{{{{{{{{{T'ru/`R44b4~SSc[[!!!HHHHHHo6%!!![[czbMt-r:R=qjxXI{{{{{{{{{{{", +"{{{{{{{{{{{)vMGE#RAAxGGDc[[!!Hz`(p6Qwgm8[0HH![@6G~@2G2:0MA>MvB{{{{{{{{{{", +"{{{{{{{{{{lvyAV4R2x8FQSc[!!HHm5%G6LGN(bC=NCmHHy(p@`tD(e:2M9XW>l{{{{{{{{{", +"{{{{{{{{{ID5x#qx8;>wQSc[!!HmmOmC8c=(3y0NspkOmmHwp@G@~w-kyA0f#5'Z{{{{{{{{", +"{{{{{{{{{*uu#'5jA0>6edz~8[!HHmOOnnii3+sp37#3[Ls=cnncee3o0Xbz,-e2#0fj5IB{{{{{{", +"{{{{{{{Iu'/V=8V-w,N[[!HmOdLni77%%`w(b(777737inmmb#3Qz,cQw-4b_V9tZr{{{{{{", +"{{{{{{BF5WD0`4AwQzk[!Hmw`+6z773(`S63KKK777777ie%ommH!,cSQ>RMR0`xWDl{{{{{", +"{{{{{{r*'j(MA02wQbNXy=bLspSs77LCp(=3KKKbL#573d(mLOm+H![cQ_F28_;M4'r{{{{{", +"{{{{{ID5q6q4A%wQ1kesp%C.3^pS77LL=N`KKK3L3NM33wpN`SmmH![cGR1e:R09DvD*{{{{", +"{{{{{FDqxtqRVtwQ:6Gp=wednc0b77[iVKKKKK$K3s!$pCse6OOmH![d`Gw-:8_V#WvF{{{{", +"{{{{B)u'5q4((_wSc[@G_`G33n=77K(c3KKKKKK3K3KK3+6zinOmmH!,0,w-k8_VM4uEq{{{", +"{{{{lhBqq/#NAM/Sc[RsS-%`ppb775bkbJ3JJJJ63KKK7#6!inOOzH!FbtQ~,8g09q5Dl{{{", +"{{{{FvxjF<#VAG6%w[!y(b%p6L37Kp(pw&$nYYJJ&KKKK76L3nOOmH!FN=FN~8R0`AZ(:N%=t@!H(H%sp077Kpb(_nnYY]]YJJKKK7Ls3nOOmH!0teF2>r8_V9W>rB{{", +"{{{>)u'o/ARx`wQ4SS!HmG8Rsi(7K(-$S]Y]]]]]YJJKK7$LsnnOmH!G4~G1/`8_V/9'oB{{", +"{{{lTux9#_FA2w:~d%!Hm3c6p=S7KVJJJ]]UUU]]]YJKK738N3OOmH!FvR_1M/l_V/9'Zl{{", +"{{{l*'x;0_%1fwQ:Q@,HmOOnL6p7K$7$]]UUUUUU]YJJK73ksC#OmH!@e~%Nbxx_0fMqTl{{", +"{{PlDoj9;9~`2wQScC(6mOOn6p+7K(/Y]]UUUUUU]]JJK7$(NCwz3H!5p~_4Fpo_0yM**lB{", +"{{IEDW#j026`1XQSc`ppQmOnzkc7SK/]]]UUUUUU]]JJK7(CCs-CNH!yR0L(GAM_0buW*EI{", +"{{*ZD*#90_#Av211zS@CNsOnnpL7HwVJY]UUUUUU]YJJKpO!0`seFH![F~tNG:GA0jBI>Z*{", +"{{*lD5MfV_81eD-4G%%=Q_OOn%s73O53]]UUUUU]]YJMpssLmGG=0z![cSkss%AxVAM'DEB{", +"{{*TD5M/V_R2e,%s~G@QNCmO3Qsw7SMJ&Y]]]]]]YJ#Sp7p6bG.cH![[cSQNGtR_VuF5T)P{", +"{{BZh9WGV_R:e4R~GFMF$+mO=sGi73budJYJY]]YJJ%N(innd3d+H!,XwQwGx1R_qjM''B){", +"{{B)>>'qA0g8k-pGL(-z!Hmsm8%ni76(fi&3&JYJJKpN=nnOOmmH!![gSQw-xxg0EoA9oTB{", +"{{PIhE4Wt0_8:ezxGG4,wHHcGk4nnspdKy!m3JJKK7dkLnOOmmHH![ccSQw2%;_0;j*uhWI{", +"{{B)oXjBjx_R:e-v_0~F[!H!Gs5OdL(d!zC86KK77inwpzOmm+H![[cSQwGD=l_0fAWXo)T{", +"{{aZovFjAj_R8k-woNps[!!3ebwOObcLnp`C6iiinnOzcF:m+H!![c-SQw,1M<_V/b5v*IB{", +"{{P>FDq6450_8:e-zRSGc[!!6p@mOepk`(GFnnnn$OOOO8`+H!![ccSQw-e;@20`/ZIh))P{", +"{{{ETDFDu>;_R8k-kx_~c[[!![6mmy`GbG8vOOO3OOOmm,s3!![[cSQ,z-kN6Myf#WWB)E{{", +"{{{*'o'q*bV0_8:e@e-XSc[[!o!H+mm0ss`GpOOmmmmm+HLb![[cSQQ11e8Goob/Moq)**{{", +"{{{I>r'qxjlV_R8,62bQSScczN`!HH33,`(p=zmmm+HHH!bp[,cSSQw-e:;AAqZjM>FZlI{{", +"{{{BBFDFqjqV02x<`f2wQSScw@-!!!HHH8=@wHHHHHH!!!os@`zSQw-ek:R_qGb6yuoq>B{{", +"{{{{Plo>*Mo;V;qE{{{", +"{{{{PZlDloG*`0;WG84--w,1RC_=s=dz[!!8@b!![[[[cS4CzzG`z21:8R_0jjFyuDqZP{{{", +"{{{{ThIovx*6/V4qMx:ke-zR@~~C=4,c[[[zSN[[[ccccz,QQwN%N:l6(;0VuZM5voBha{{{", +"{{{{{*>FDx''9flx/R8:keyG=F>1X1SccccF~_ccccSSSzQQww,FAA>>AlV9b'5XDF>*{{{{", +"{{{{{ahIo't'b/fq0fR8:kFA4wwQQQSSSS1G~_@SSSS1sbyw--e;0Mt#4tfjyAuDolBB{{{{", +"{{{{{{*PFb6'F#/(M0_R<(=xt--wwwQQQ1zNGt`bQQQz(t-vo4:Flx#>Wr/#4IvoFZT{{{{{", +"{{{{{{PBl)xTuM#9j;0_;GuAAke---wwGp>_o~t,www1MoGtur8Rg_0*M9#vWB'rlEB{{{{{", +"{{{{{{{IBloT'5M#ulV0_>W95jWllPPP{{{{{{", +"{{{{{{{{BElhq>uqAyoF:::888RRg_00Vf*4AW5uo)lBqP{{{{{{{", +"{{{{{{{{{IEB)oDuD'xj/fq>4x2vgRR;;f<0V88888RRg__>9VVfj>j959DBql)a{{{{{{{{", +"{{{{{{{{{)I>PloDq'FE9#/AbAMAl__qot;rbx;gg__f000j;f/9'Pa{{{{{{{{", +"{{{{{{{{{{TIPlFolTDXMM#/;>4tMVy5A/;r;__000;VVVjq//#MFqI>)WIl>Ia{{{{{{{{{", +"{{{{{{{{{{{TIhlB*'ru5yMM#A>4bfyvjqffffffff///5>D99y5u>ol*))*IT{{{{{{{{{{{", +"{{{{{{{{{{{{{TPI>lFooDvuF'lqMMqj'##>vv#####xxIy>WuvT4B'TPP)T{{{{{{{{{{{{", +"{{{{{{{{{{{{{{aB*)llThTTBqo55yv'hMMMMMMMMM>j55uXvDoBWTP*)T){{{{{{{{{{{{{", +"{{{{{{{{{{{{{{{PBIP)EB*ooDDvvx'95555555555uuvvDB*BTT)*BPPP{{{{{{{{{{{{{{", +"{{{{{{{{{{{{{{{{{Ta)T)llFrooDo'TDvv>''vvvvDDDoITlTPTqPPa{{{{{{{{{{{{{{{{", +"{{{{{{{{{{{{{{{{{{aPPPE>lllFrro''T'TBrr'hoohrFlI'PBP)BP{{{{{{{{{{{{{{{{{", +"{{{{{{{{{{{{{{{{{{{{aPI*E>>lllBTB))*IF*FFFlllBBBE*PTa{{{{{{{{{{{{{{{{{{{", +"{{{{{{{{{{{{{{{{{{{{{{PaPPTEE>E*PT)>*lllZZ>>EE*IBaP{{{{{{{{{{{{{{{{{{{{{", +"{{{{{{{{{{{{{{{{{{{{{{{{PPaBII*PBBPPBEEEE**IIBBPP{{{{{{{{{{{{{{{{{{{{{{{", +"{{{{{{{{{{{{{{{{{{{{{{{{{{{PPaaPaTPaTIIBBBBaPP{{{{{{{{{{{{{{{{{{{{{{{{{{", +"{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{aaaaaPPPPaP{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{", +"{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{", +"{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{" +}; diff --git a/hacks/images/bubbles/blue2.xpm b/hacks/images/bubbles/blue2.xpm new file mode 100644 index 00000000..c4ce92dd --- /dev/null +++ b/hacks/images/bubbles/blue2.xpm @@ -0,0 +1,90 @@ +/* XPM */ +static char *blue2[] = { +/* width height ncolors chars_per_pixel */ +"12 12 71 1", +/* colors */ +" c #000000", +". c #323252", +"X c #303050", +"o c #0F0F1F", +"O c #1B1B2E", +"+ c #17172A", +"@ c #1F1F35", +"# c #181824", +"$ c #25253E", +"% c #10101C", +"& c #20202F", +"* c #0E0E1A", +"= c #292945", +"- c #141423", +"; c #242436", +": c #2D2D4C", +"> c #333355", +", c #313153", +"< c #0D0D15", +"1 c #24243C", +"2 c #262641", +"3 c #232334", +"4 c #3C3C5D", +"5 c #19192A", +"6 c #303051", +"7 c #111122", +"8 c #1F1F33", +"9 c #08080F", +"0 c #212138", +"q c #12121F", +"w c #0E0E1B", +"e c #1E1E2E", +"r c #2B2B48", +"t c #2F2F4F", +"y c #1C1C2F", +"u c #18182B", +"i c #353558", +"p c #15151E", +"a c #1C1C32", +"s c #26263F", +"d c #13131F", +"f c #0F0F1B", +"g c #2A2A46", +"h c #131322", +"j c #2E2E4D", +"k c #0F0F1E", +"l c #343456", +"z c #151527", +"x c #1F1F34", +"c c #0C0C14", +"v c #494967", +"b c #23233B", +"n c #FFFFFF", +"m c #0C0C17", +"M c #141422", +"N c #2D2D4B", +"B c #0E0E1C", +"V c #161627", +"C c #333354", +"Z c #141425", +"A c #1E1E32", +"S c #1C1C30", +"D c #0B0B12", +"F c #18182C", +"G c #090910", +"H c #222239", +"J c #0F0F19", +"K c #1B1B28", +"L c #262640", +"P c #151522", +"I c None", +/* pixels */ +"IIIIO1wKAIII", +"II9bgNjN-ba2&0I", +"I5uo;Fil,Ns5", +"If8ezCn47:ZS", +"ImLSaZv+3ewy", +"IhbH:@6X:=Vm", +"IcA$kegr=q5D", +"IIM#*sVsbxmI", +"IIGPp%xApqGI", +"IIIIJDcdJIII", +"IIIIIIIIIIII" +}; diff --git a/hacks/images/bubbles/blue3.xpm b/hacks/images/bubbles/blue3.xpm new file mode 100644 index 00000000..dd9ad7a2 --- /dev/null +++ b/hacks/images/bubbles/blue3.xpm @@ -0,0 +1,104 @@ +/* XPM */ +static char *blue3[] = { +/* width height ncolors chars_per_pixel */ +"14 14 83 1", +/* colors */ +" c #000000", +". c #2A2A47", +"X c #282845", +"o c #111121", +"O c #2E2E4E", +"+ c #1B1B2E", +"@ c #0A0A10", +"# c #17172A", +"$ c #101019", +"% c #181824", +"& c #21213A", +"* c #10101C", +"= c #20202F", +"- c #0C0C18", +"; c #161628", +": c #07070F", +"> c #24243C", +", c #0B0B16", +"< c #282843", +"1 c #11111F", +"2 c #0F0F1D", +"3 c #1B1B2C", +"4 c #19192A", +"5 c #151526", +"6 c #303051", +"7 c #111122", +"8 c #19192D", +"9 c #23233A", +"0 c #212138", +"q c #0E0E18", +"w c #0A0A14", +"e c #272741", +"r c #23233D", +"t c #202030", +"y c #1E1E2E", +"u c #2B2B48", +"i c #181828", +"p c #28283B", +"a c #2F2F4F", +"s c #2D2D4D", +"d c #1C1C2F", +"f c #18182B", +"g c #353558", +"h c #15151E", +"j c #191925", +"k c #24243D", +"l c #13131F", +"z c #11111D", +"x c #0D0D19", +"c c #262642", +"v c #151524", +"b c #2E2E4D", +"n c #343456", +"m c #06060B", +"M c #0C0C14", +"N c #494967", +"B c #23233B", +"V c #FFFFFF", +"C c #0C0C17", +"Z c #292944", +"A c #0A0A15", +"S c #2D2D4B", +"D c #0E0E1C", +"F c #1A1A2B", +"G c #373758", +"H c #181829", +"J c #161627", +"K c #141425", +"L c #313152", +"P c #121223", +"I c #1E1E32", +"U c #1C1C30", +"Y c #18182C", +"T c #222239", +"R c #11111B", +"E c #1E1E35", +"W c #0F0F19", +"Q c #0D0D17", +"! c #0B0B15", +"~ c #1B1B28", +"^ c #262640", +"/ c #2C2C49", +"( c None", +/* pixels */ +"(((((vTx-I((((", +"(((CDZ5E=Z>5((", +"((4k.bKLobY2M(", +"((jZJYXnLPb=z(", +"(i>U#3KNg7a#>i", +"(12uasNVNptY2Q", +"(h>oyc4NGLb=%;", +"(i0e/O&L6o/ei$", +"(l+;<8y^Sr<>w!", +"((l,fe<;A$(", +"((WHIUxB9~qRW(", +"(((mv1xqdF:@((", +"(((((qQ*zq((((", +"((((((((((((((" +}; diff --git a/hacks/images/bubbles/blue4.xpm b/hacks/images/bubbles/blue4.xpm new file mode 100644 index 00000000..f8a2ee2b --- /dev/null +++ b/hacks/images/bubbles/blue4.xpm @@ -0,0 +1,116 @@ +/* XPM */ +static char *blue4[] = { +/* width height ncolors chars_per_pixel */ +"20 20 89 1", +/* colors */ +" c #000000", +". c #282845", +"X c #303050", +"o c #111121", +"O c #2E2E4E", +"+ c #1D1D30", +"@ c #17172A", +"# c #212137", +"$ c #2F2F48", +"% c #101019", +"& c #181824", +"* c #25253E", +"= c #10101C", +"- c #1A1A29", +"; c #2F2F4E", +": c #2D2D4C", +"> c #1A1A2C", +", c #161628", +"< c #333355", +"1 c #07070C", +"2 c #141426", +"3 c #313153", +"4 c #0D0D15", +"5 c #090911", +"6 c #22223A", +"7 c #13131E", +"8 c #0D0D18", +"9 c #1D1D2B", +"0 c #0B0B16", +"q c #282843", +"w c #1D1D2E", +"e c #131324", +"r c #040408", +"t c #111122", +"y c #1F1F33", +"u c #08080F", +"i c #161620", +"p c #0A0A14", +"a c #272741", +"s c #25253F", +"d c #0E0E1B", +"f c #2B2B48", +"g c #0C0C19", +"h c #292946", +"j c #2F2F4F", +"k c #101020", +"l c #1C1C2F", +"z c #1A1A2D", +"x c #2A2A40", +"c c #18182B", +"v c #09090F", +"b c #15151E", +"n c #1C1C32", +"m c #191925", +"M c #24243D", +"N c #13131F", +"B c #1F1F2E", +"V c #2A2A46", +"C c #171726", +"Z c #151524", +"A c #131322", +"S c #0F0F1E", +"D c #38385A", +"F c #343456", +"G c #1F1F34", +"H c #1B1B30", +"J c #0C0C14", +"K c #DDDDEB", +"L c #494967", +"P c #23233B", +"I c #0C0C17", +"U c #292944", +"Y c #161624", +"T c #141422", +"R c #2D2D4B", +"E c #181829", +"W c #161627", +"Q c #0B0B12", +"! c #18182C", +"~ c #222239", +"^ c #202037", +"/ c #11111B", +"( c #1E1E35", +") c #0D0D17", +"_ c #0B0B15", +"` c #262640", +"' c #696985", +"] c #2C2C49", +"[ c None", +/* pixels */ +"[[[[[[[=_iyWlT[[[[[[", +"[[[[[JimsoPasGp/[[[[", +"[[[[=&8hfMRffh9i-[[[", +"[[[E8cVRjn;Wj]`9m=[[", +"[[N=nd:X3q<^fnAB*mN[", +"[[>8q,kW<2FeFeXR9M0u", +"[Nbn9:j:lLK'F@X:czGT", +"[Y0nVHX^z'K'DjHRd,8%", +"[)_M@l;,<$LLe3;wUmT5", +"[T=Pae:kG;W3oj:w9do4", +"[vI#*GfnOkzjOSfU*gi/", +"[rC0kA-nqRSR]6a9~0C1", +"[[N57P&aUVtVBas@G/N[", +"[[uZN&lm*gW`*M~G>Qr[", +"[[[)ZA+WiIN~iI+_J1[[", +"[[[[JACTlNE+>>%_4[[[", +"[[[[[uQNZ8QJZN5r[[[[", +"[[[[[[[1QJ5)v1[[[[[[", +"[[[[[[[[[[[[[[[[[[[[" +}; diff --git a/hacks/images/bubbles/blue5.xpm b/hacks/images/bubbles/blue5.xpm new file mode 100644 index 00000000..a58adcc6 --- /dev/null +++ b/hacks/images/bubbles/blue5.xpm @@ -0,0 +1,122 @@ +/* XPM */ +static char *blue5[] = { +/* width height ncolors chars_per_pixel */ +"24 24 91 1", +/* colors */ +" c #000000", +". c #2A2A47", +"X c #303050", +"o c #2E2E4E", +"O c #1F1F32", +"+ c #1D1D30", +"@ c #08080E", +"# c #25253B", +"$ c #1F1F35", +"% c #25253E", +"& c #20202F", +"* c #0E0E1A", +"= c #0C0C18", +"- c #292945", +"; c #161625", +": c #121221", +"> c #2F2F4E", +", c #2D2D4C", +"< c #1A1A2C", +"1 c #333355", +"2 c #07070C", +"3 c #090911", +"4 c #0B0B16", +"5 c #282843", +"6 c #262641", +"7 c #11111F", +"8 c #2C2C4A", +"9 c #BABAC8", +"0 c #19192A", +"q c #151526", +"w c #323253", +"e c #040408", +"r c #0C0C13", +"t c #08080F", +"y c #212138", +"u c #1C1C29", +"i c #0A0A14", +"p c #272741", +"a c #25253F", +"s c #12121F", +"d c #0E0E1B", +"f c #1E1E2E", +"g c #181828", +"h c #2F2F4F", +"j c #101020", +"k c #1C1C2F", +"l c #18182B", +"z c #161629", +"x c #333356", +"c c #07070D", +"v c #1E1E34", +"b c #0F0F18", +"n c #1C1C32", +"m c #24243D", +"M c #22223B", +"N c #11111D", +"B c #0D0D19", +"V c #2A2A46", +"C c #2E2E4D", +"Z c #0F0F1E", +"A c #38385A", +"S c #06060B", +"D c #0A0A12", +"F c #494967", +"G c #10101B", +"H c #0C0C17", +"J c #292944", +"K c #161624", +"L c #141422", +"P c #242435", +"I c #2D2D4B", +"U c #0E0E1C", +"Y c #1A1A2B", +"T c #161627", +"R c #141425", +"E c #313152", +"W c #121223", +"Q c #1C1C30", +"! c #1A1A2E", +"~ c #0B0B12", +"^ c #090910", +"/ c #15151F", +"( c #222239", +") c #202037", +"_ c #0F0F19", +"` c #0D0D17", +"' c #262640", +"] c #151522", +"[ c #0F0F1C", +"{ c #2C2C49", +"} c None", +/* pixels */ +"}}}}}}}}}c4kQkYL}}}}}}}}", +"}}}}}}}s!smBd*uTO0}}}}}}", +"}}}}}t+BN5LqOm-5%*+s}}}}", +"}}}}t0MRV{ICCzI{LpMi`}}}", +"}}}`ddN.I>>.P!a>RZpB+N}}", +"}}}Yy'UIhEw:18nE6)&'y<}}", +"}}]iB5!n::qlxR$jXPXf,{-pT$H_", +"}D;iy=uV5ICm5CCIZVp%4z;D", +"}}r[O4%pZMf{V{.&-lsK0Y~}", +"}}`LLl(lZ5JujLJZqL+]:;^}", +"}}}NLlKy*%'(T''%My$/HS}}", +"}}}@S;L+RB(ZRM(yg/L__e}}", +"}}}}^S]0/sG$$$OG/0sc^}}}", +"}}}}}2SD;g3<<<0gbtr2}}}}", +"}}}}}}}S_s~crLsD_t}}}}}}", +"}}}}}}}}}2e^^~^2}}}}}}}}", +"}}}}}}}}}}}}}}}}}}}}}}}}" +}; diff --git a/hacks/images/bubbles/blue6.xpm b/hacks/images/bubbles/blue6.xpm new file mode 100644 index 00000000..8073d341 --- /dev/null +++ b/hacks/images/bubbles/blue6.xpm @@ -0,0 +1,128 @@ +/* XPM */ +static char *blue6[] = { +/* width height ncolors chars_per_pixel */ +"30 30 91 1", +/* colors */ +" c #000000", +". c #2A2A47", +"X c #131323", +"o c #303050", +"O c #2E2E4E", +"+ c #1B1B2E", +"@ c #19192C", +"# c #101019", +"$ c #181824", +"% c #25253E", +"& c #12121E", +"* c #10101C", +"= c #292945", +"- c #141423", +"; c #2F2F4E", +": c #10101F", +"> c #2D2D4C", +", c #333355", +"< c #202035", +"1 c #1A1A2F", +"2 c #24243C", +"3 c #22223A", +"4 c #2E2E49", +"5 c #0D0D18", +"6 c #0B0B16", +"7 c #282843", +"8 c #11111F", +"9 c #0F0F1D", +"0 c #19192A", +"q c #151526", +"w c #323253", +"e c #040408", +"r c #111122", +"t c #08080F", +"y c #161620", +"u c #14141E", +"i c #212138", +"p c #10101D", +"a c #0E0E1B", +"s c #2B2B48", +"d c #181828", +"f c #161626", +"g c #2F2F4F", +"h c #0B0B11", +"j c #18182B", +"k c #161629", +"l c #333356", +"z c #07070D", +"x c #202036", +"c c #1E1E34", +"v c #1C1C32", +"b c #26263F", +"n c #24243D", +"m c #1F1F2E", +"M c #0D0D19", +"N c #2A2A46", +"B c #262642", +"V c #252537", +"C c #131322", +"Z c #2E2E4D", +"A c #363658", +"S c #151527", +"D c #06060B", +"F c #0C0C14", +"G c #DDDDEB", +"H c #0A0A12", +"J c #080810", +"K c #23233B", +"L c #0C0C17", +"P c #1C1C2A", +"I c #292944", +"U c #0A0A15", +"Y c #121220", +"T c #141425", +"R c #313152", +"E c #1E1E32", +"W c #1C1C30", +"Q c #28283F", +"! c #222239", +"~ c #202037", +"^ c #11111B", +"/ c #0F0F19", +"( c #0D0D17", +") c #090913", +"_ c #262640", +"` c #696985", +"' c #151522", +"] c #424262", +"[ c #212131", +"{ c #2C2C49", +"} c None", +/* pixels */ +"}}}}}}}}}}}}Du00-5&}}}}}}}}}}}", +"}}}}}}}}}z@8yi!+8L6WUp}}}}}}}}", +"}}}}}}}}@y!2%K:KPB%k!Uq}}}}}}}", +"}}}}}}6)xp!7N9sC~[N7_>ZZK>>s-m%@HF}}}}", +"}}}}&*M$7.{Zgjg;S:gZ9_Y%$5&}}}", +"}}}}^0$9.{ZoRW~,BWR[{[KB+x@}}}", +"}}}tWd8={Zo[,roTl,,j[iq=T!Cf}}", +"}}F@6Y78%:c>,7~lV@,kXg>sKnxUh}", +"}}'UpjI{vrVkl7AAQQljRoZPIb!C'}", +"}}f6'8a[[SS,@cw]]AljwoOijpK$f}", +"}h0u0PP9OgrS+A`G`]A,joOrj+KcHh", +"}#fLCmNj[o0qkAGGG`A,~rZmW9-$^#", +"}^ucKb+n>VRcv4`GG]c1oj[{[aY$0(", +"}^06K_jTd;vT,@]]`AXRV;>fIaK-LD", +"}##6!%7aVZ:o3Q;EA,vogZ{.mn!Wdh", +"}DfTy2BWq>CVYTOsRRos=BMi^#(", +"}D'Ly!%SPs>VOOj1ggOZ[s=P%q6yzz", +"}}&dLixa7=W9>>ZsZ>!v:=7bK6605}", +"}}/f6ECCb79XY{{N{{s0=W!2i0+f/}", +"}}e&5+&P2$M7I=[ra=mmC%8Ecad&z}", +"}}}5))WUiLpb_BmaKBmmnKiYW)'5}}", +"}}}}*505@xaK2njM%n2K!xYp0tD}}}", +"}}}}tt-)aW66ypf&!!yxcW*/F^z}}}", +"}}}}}JFzf@udEacccEE/u@-&zJ}}}}", +"}}}}}}D/zU*0F#++++@0htHhz}}}}}", +"}}}}}}}}Jh&--6-H#f--the}}}}}}}", +"}}}}}}}}}et(/H65p^/(HD}}}}}}}}", +"}}}}}}}}}}}}zeettzz}}}}}}}}}}}", +"}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}" +}; diff --git a/hacks/images/bubbles/blue7.xpm b/hacks/images/bubbles/blue7.xpm new file mode 100644 index 00000000..384d3361 --- /dev/null +++ b/hacks/images/bubbles/blue7.xpm @@ -0,0 +1,132 @@ +/* XPM */ +static char *blue7[] = { +/* width height ncolors chars_per_pixel */ +"36 36 89 1", +/* colors */ +" c #000000", +". c #2A2A47", +"X c #151525", +"o c #2E2E4E", +"O c #0F0F1F", +"+ c #1D1D30", +"@ c #17172A", +"# c #1B1B31", +"$ c #181824", +"% c #25253E", +"& c #21213A", +"* c #0E0E1A", +"= c #1C1C2B", +"- c #292945", +"; c #1A1A29", +": c #121221", +"> c #2D2D4C", +", c #161628", +"< c #26263B", +"1 c #333355", +"2 c #05050A", +"3 c #282840", +"4 c #090911", +"5 c #151520", +"6 c #2E2E49", +"7 c #0D0D18", +"8 c #282843", +"9 c #262641", +"0 c #252536", +"q c #0F0F1D", +"w c #2C2C4A", +"e c #1D1D2E", +"r c #19192A", +"t c #323253", +"y c #131324", +"u c #303051", +"i c #111122", +"p c #08080F", +"a c #212138", +"s c #0E0E18", +"d c #0A0A14", +"f c #25253F", +"g c #23233D", +"h c #12121F", +"j c #2B2B48", +"k c #181828", +"l c #141424", +"z c #2F2F4F", +"x c #1C1C2F", +"c c #1A1A2D", +"v c #0B0B11", +"b c #18182B", +"n c #07070D", +"m c #202036", +"M c #0D0D16", +"N c #11111D", +"B c #2A2A46", +"V c #262642", +"C c #171726", +"Z c #131322", +"A c #111120", +"S c #2E2E4D", +"D c #38385A", +"F c #343456", +"G c #151527", +"H c #212136", +"J c #1F1F34", +"K c #DDDDEB", +"L c #0A0A12", +"P c #494967", +"I c #23233B", +"U c #10101B", +"Y c #0C0C17", +"T c #292944", +"R c #161624", +"E c #2D2D4B", +"W c #0E0E1C", +"Q c #1A1A2B", +"! c #030307", +"~ c #1E1E32", +"^ c #1E1E35", +"/ c #0F0F19", +"( c #0B0B15", +") c #262640", +"_ c #696985", +"` c #151522", +"' c #212131", +"] c #2C2C49", +"[ c None", +/* pixels */ +"[[[[[[[[[[[[[[[[4sCR([[[[[[[[[[[[[[[", +"[[[[[[[[[[[[hkx`$m7Y*lx4Z[[[[[[[[[[[", +"[[[[[[[[[[L=x5&gq**AI;Ja~dp[[[[[[[[[", +"[[[[[[[[[Q~*`g9;*qIlX89&Ih~k[[[[[[[[", +"[[[[[[[77Ua*'8B'O]b@.jB89*aJ=Z[[[[[[", +"[[[[[[p`~I::BjwESSSX@Ewjlq`I(*M[[[[[", +"[[[[[h=mI*Z.]>ScAGcl#&S=yJC);5Yh[[[[", +"[[[[[r+NeA.wSzubiEt.iju%^yb8%*Jr[[[[", +"[[[[4da,HW]Szuttoy10G#tj9Xr'9;adM[[[", +"[[[LcCJ7-fEz^,10^,FF111VXzEj-IIJYh[[", +"[[[C((78=9yI0y1G#^F00x0y^zSwA=%aCC[[", +"[[4rc:b8jO&A0#1b0FFFFF<,tuzEa8)&xr([", +"[[ZUZ+7,8>b@,cZWIJhZ[", +"[[nd~IJ-B>zgibF9BP__PDF3itz>:A~gm5R[", +"[[sUa@J-TezuGyF1_KKK_DF9@l*axp[", +"[MC+a,=-jyTu'.B~_KKK_DFbI9c>IGAxarsM", +"[sCxmg)9A@-uti0c_KKK_DyizAaEj)i7mxCL", +"[4/YmI)IAx3z#A1l0PP_D@bt0HSe88*I(x4n", +"[2/:q&%'A:8SA:tyFE)8u.t^,ttuj%o>w3Tex&~csv", +"[[pZr$Iff&jw>,zJlguuuuzi>wj-'f,=+Yn[", +"[[U4*h&g,lBj'^S0eb#zzSSl]jB8)$7NxZh[", +"[[2XsXm(I;8--IXE>'>>>Er#,A89%I7xc(/[", +"[[p(k7~:x%)'OW#e]wBw]jje-cchbarxkv![", +"[[[/XqlJaI%Z:8-BB=WOBBi=9)aq:J=rXL[[", +"[[[2hUr+da$r7)98AqXq88xArgIax+Y4hL[[", +"[[[[spZcd$m7*g%)el,;))%gI&mJYcYhn[[[", +"[[[[[/nCC*~(:;II$YmggII&5mddcC(n[[[[", +"[[[[[p2ZhCx+$:x=7$$&a$md~+Z(p(U![[[[", +"[[[[[[4vp`kQ5,+U(JJJJ~QC5Qqhns4[[[[[", +"[[[[[[[!shppLRck/xxxxUcrkXY2nn[[[[[[", +"[[[[[[[[[!phZXC4Ck4kkCCMh2(2[[[[[[[[", +"[[[[[[[[[[!(/UhvLp(sZhh4/2![[[[[[[[[", +"[[[[[[[[[[[[2!(sL24//s(Ln[[[[[[[[[[[", +"[[[[[[[[[[[[[[[[!!2n![[[[[[[[[[[[[[[", +"[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[" +}; diff --git a/hacks/images/bubbles/blue8.xpm b/hacks/images/bubbles/blue8.xpm new file mode 100644 index 00000000..d2c36b11 --- /dev/null +++ b/hacks/images/bubbles/blue8.xpm @@ -0,0 +1,142 @@ +/* XPM */ +static char *blue8[] = { +/* width height ncolors chars_per_pixel */ +"44 44 91 1", +/* colors */ +" c #000000", +". c #303050", +"X c #1D1D30", +"o c #17172A", +"O c #08080E", +"+ c #25253B", +"@ c #0E0E17", +"# c #1B1B31", +"$ c #25253E", +"% c #10101C", +"& c #2B2B47", +"* c #0C0C18", +"= c #1C1C2B", +"- c #292945", +"; c #242436", +": c #2D2D4C", +"> c #5C5C7A", +", c #161628", +"< c #07070C", +"1 c #05050A", +"2 c #151520", +"3 c #22223A", +"4 c #2E2E49", +"5 c #282843", +"6 c #262641", +"7 c #0F0F1D", +"8 c #2C2C4A", +"9 c #BABAC8", +"0 c #19192A", +"q c #151526", +"w c #131324", +"e c #111122", +"r c #212138", +"t c #272741", +"y c #25253F", +"u c #161623", +"i c #23233D", +"p c #12121F", +"a c #10101D", +"s c #202030", +"d c #0E0E1B", +"f c #2B2B48", +"g c #181828", +"h c #121222", +"j c #2F2F4F", +"k c #101020", +"l c #1C1C2F", +"z c #353558", +"x c #333356", +"c c #202036", +"v c #090912", +"b c #24243D", +"n c #40405F", +"m c #0F0F1B", +"M c #1F1F2E", +"N c #0D0D19", +"B c #2A2A46", +"V c #282844", +"C c #262642", +"Z c #171726", +"A c #111120", +"S c #2E2E4D", +"D c #0F0F1E", +"F c #1D1D2F", +"G c #1F1F34", +"H c #0C0C14", +"J c #1E1E2C", +"K c #0C0C17", +"L c #0A0A15", +"P c #0E0E1C", +"I c #2B2B49", +"U c #1A1A2B", +"Y c #333354", +"T c #313152", +"R c #222236", +"E c #1E1E32", +"W c #1A1A2E", +"Q c #18182C", +"! c #28283F", +"~ c #090910", +"^ c #222239", +"/ c #202037", +"( c #11111B", +") c #1E1E35", +"_ c #0F0F19", +"` c #0D0D17", +"' c #1B1B28", +"] c #090913", +"[ c #171724", +"{ c #11111E", +"} c None", +/* pixels */ +"}}}}}}}}}}}}}}}}}}}}}}H}}}}}}}}}}}}}}}}}}}}}", +"}}}}}}}}}}}}}}}}Hppl[XXXXLUNu}}}}}}}}}}}}}}}", +"}}}}}}}}}}}}}}g(qmcr^**7*Nl[XL%}}}}}}}}}}}}}", +"}}}}}}}}}}}}glKr'3$W,hP3y$$N*ra{g}}}}}}}}}}}", +"}}}}}}}}}}{UEo'7Zt5hdhrPhA5tdb^*E(u}}}}}}}}}", +"}}}}}}}}},qNK*#t5-BqgBPD0MB-5th{^GKZ}}}}}}}}", +"}}}}}}}}OKN^Qb5-&f8:::SMw08f&-lJ$^K]Z}}}}}}}", +"}}}}}}}Zl%l7NWsf8:S:oQReVfS:eqPP7$q,2O}}}}}}", +"}}}}}}u=L,$D-B8:SjjjV:#.okRjShkDJt$QGp_}}}}}", +"}}}}}@U2Z=NPB8:Sj.wWeQT-6Cs.!h6fq56QrEU<}}}}", +"}}}}}g0c{'=P8:Sj.TT+/!xFyq6Tqf;3hs5yocL{}}}}", +"}}}}2U2m{'-b:SjWFTYeS#8xxxYTw/SSsf-bP^[K2}}}", +"}}}}%LdG$5JADee6.xx3QsxxoE-,/h.j:8BPy32]@}}}", +"}}}pU7dkh-seqysqwx!I&zz!zq+,ho.jS8r5tbr@pp}}", +"}}}O]LWQb-fwieeVwx3xzzzz;zxxqRT.s:r-Z$^ZWH}}", +"}}~ZLG[W7kh:Mkk6+xiqX4nnnzzx8;T.j:Wt)h3c*Z`}", +"}}p0L[,,5gk:j3/o!xV3z>>>>nzx-fT.j:6-=/3c(Kp}", +"}}@0l=UJ5qhUj!+e5xX4>999>nnx;oU.j:3q7#7rXLh}", +"}}v0EEkP5Bs)j.T3#x^n>9999>nxxe30;:,ehd{rE_2}", +"}}%2KrFassMq=.TRfxYn>999>>nxoQ)B;:o3lW7rl(v}", +"}}uUEr3'=bhWy-.qox,!n>99>n;,Qek#k:fBdG'r0h@}", +"}n>nnY;T.;j:Ms-=r3mhHm<", +"}}m20W^$t3#qBSWQFTf;!!!nzx/0T.jS:8B5'W^cL@2}", +"}}@g]K^b65Q78:kq;.k!+BqxYT;W8jS:8f-5[)^Gdg<}", +"}}OZuKr3$t=6y8::Q.keWqTTT..l5S:8fB5t$*rEv_<}", +"}}%q0LF^b6P/sf8B,j,ohh;..jjjoM8fB-J6WX{XNN%}", +"}}~2@KKr3pWq-BfftSS;=krjjSSSs#qB-56$*hqlvO@}", +"}} c #333355", +", c #07070C", +"< c #242439", +"1 c #282840", +"2 c #22223A", +"3 c #0F0F1A", +"4 c #0B0B16", +"5 c #282843", +"6 c #090914", +"7 c #262641", +"8 c #11111F", +"9 c #0F0F1D", +"0 c #2C2C4A", +"q c #19192A", +"w c #040408", +"e c #1F1F33", +"r c #08080F", +"t c #1C1C29", +"y c #25253F", +"u c #23233D", +"i c #10101D", +"p c #202030", +"a c #2B2B48", +"s c #292946", +"d c #181828", +"f c #313151", +"g c #2F2F4F", +"h c #1C1C2F", +"j c #1A1A2D", +"k c #18182B", +"l c #09090F", +"z c #161629", +"x c #07070D", +"c c #202036", +"v c #0D0D16", +"b c #0B0B14", +"n c #090912", +"m c #11111D", +"M c #2A2A46", +"N c #171726", +"B c #151524", +"V c #131322", +"C c #2E2E4D", +"Z c #38385A", +"A c #343456", +"S c #151527", +"D c #212136", +"F c #DDDDEB", +"G c #0A0A12", +"H c #494967", +"J c #10101B", +"K c #0E0E19", +"L c #292944", +"P c #141422", +"I c #242435", +"U c #121220", +"Y c #2D2D4B", +"T c #1A1A2B", +"R c #161627", +"E c #141425", +"W c #313152", +"Q c #121223", +"! c #1E1E32", +"~ c #0B0B12", +"^ c #090910", +"/ c #15151F", +"( c #222239", +") c #202037", +"_ c #1E1E35", +"` c #0D0D17", +"' c #262640", +"] c #696985", +"[ c #151522", +"{ c #11111E", +"} c #2C2C49", +"| c None", +/* pixels */ +"||||||||||||||||||||||||||||||||||||||||||||||||||", +"|||||||||||||||||||xVU;[Jhhh9qnP||||||||||||||||||", +"||||||||||||||||PdUU!ecDD4.h4.4@3=P|||||||||||||||", +"||||||||||||||PJh4/K(2uU==.uu[UKc!{JG|||||||||||||", +"||||||||||||vdh/c(%&yuR9$2ct7'yE8(c6hKJ|||||||||||", +"|||||||||||4;@4o=8i75BuoppE(&L57'&uh{@z[||||||||||", +"||||||||||366Dj.k7LsMTSd}k}o*aMsL7S*tD=KR|||||||||", +"|||||||||rhh82Vc5sMa0YY-CCC+EY0aMsyi&2=.SN||||||||", +"||||||||RhRSu..2Va0YC@jEokXEySV7Eo7t(_hr,||||", +"|||||~//c!+59p0CgXIWWIEE)k<>>hWW5kIpI*M59_(`T[||||", +"||||Jn6hVotLU0-p;sS<>QS2EAAA>>>W57gO-0ML+.(34d~|||", +"||||[;==oR5qMSook$Ek>SE_AAASoz>oo_XgCYaU2'uD46[|||", +"|||3B6;=E9LM7k20<@5:>k@AAAIAh:I5ESWXO-}_@7u(e6Nv||", +"|||Uq64!kksa0oMoSg5>AQEAZZZ:}AAjjpWXYC2Qs*&2cqqU||", +"|||Uq6K2Voy5YRCokk:>jSj##HHZ:AA>QESe#H]]]ZZA>@WWXgCoU9t+u(!nN~|", +"||JN4/[oi5*pQCggjo$>hf#]]F]]]ZA>A:H]FFFF]HZ>zSoosCY7Ey.9h`UJr|", +"||xdhe(@i*V*yk$XWWo>&!]]FFFF]HAkyM$oUC0V7kSo%Ui{G|", +"||bdhe(u2*hojo5VXko>7uHH]]F]H#u$_oS2V-0as.zueKPnx|", +"||xdq4D2DPkokkDgX$oW>$pZHH]HZIQWWXIgCY*uL.h2DPUnn|", +"||x3n=D2&799kS-C$okWWS:Dg1ZZAIoIWXgC-0aM57S2D44Nr|", +"||{Nn6e(u'5h_5YC2oEXs5:k}kA>>W5EXgOCY}Ms*V@(cR[N,|", +"||JNnV4(2&7*jV}YCs)Xg2IM0qWWWWXo2OCY}ap57&((e`T`~|", +"||3[.44%2u'io9a0YRSgIzooEXXIXXggECY0aM'5'z=c!8/x3|", +"||vP`=Vc(u&.h8Ma0M$CO0aoajXgggOC7Q0aMs5t&9e;@/r{v|", +"||G{Ni4=DhVkt5sMakjY-CCOojgOCC-Yq97Ms57'uodR6Tr{G|", +"|||i[{nSc%_(U75sM9u(pY--o0---Y0o$jS*57'&2(hkJd^i||", +"|||vUNGG!cjkk'75S9k7M*00IEI00}aSU*L.u9%m(c.mTNx~||", +"|||wJ[K4KekU2&'7oo9PDMaa'9paaMM*s55tV=k=D{9;d[Jx||", +"||||`UNV4@{;(2P%9U55LsMM*o$pMsp5ep'yic9=e/nqNUG|||", +"||||xr^nKh@4D(=9.d'775po5j7N55N$V_Uu@({e@qnbPi^|||", +"|||||v{[4q/q/c(US%&y''7i..877''y&u2((cKBh`Nrmw||||", +"|||||wK`i3T49ecD422uu&&(Ei;y&&uu22(Dce=iT=rbw,||||", +"||||||^3`Pd6n6!qiqU%228U(huu222((%ce6q4Tdbr~,|||||", +"|||||||~~rB3n3q@!==_/%.S%U((((/c=/!@dn{nbU3w||||||", +"||||||||~3riP/T;h@ize/4eccccc_e!hhh;Ti4b,3~|||||||", +"|||||||||,v{iNNqT/q;@6q!!!!!!@@Gh4{qGbUr^~||||||||", +"||||||||||wKwUGmnNd;;;6hhqhhhh6;qdNKnx3w,|||||||||", +"|||||||||||xbxxxPNNNd=qqTTTqqqdNNm`xxlwr||||||||||", +"||||||||||||w,v~mUP[BNGPrGN~RNB[PGK^xw,|||||||||||", +"||||||||||||||wwv3im{xrrinPPUU{mi3vx,|||||||||||||", +"||||||||||||||||,wwv`xGww~ii3^`v~l,|||||||||||||||", +"|||||||||||||||||||,,w,www~~G^w,||||||||||||||||||", +"||||||||||||||||||||||||||||||||||||||||||||||||||", +"||||||||||||||||||||||||||||||||||||||||||||||||||" +}; diff --git a/hacks/images/bubbles/glass.pov b/hacks/images/bubbles/glass.pov new file mode 100644 index 00000000..c1897714 --- /dev/null +++ b/hacks/images/bubbles/glass.pov @@ -0,0 +1,27 @@ +#include "colors.inc" +#include "shapes.inc" +#include "textures.inc" + +/* The following make the field of view as wide as it is high + * Thus, you should have the -W and -H command line options + * equal to each other. */ +camera { + location <5.8, 0, 0> + up <0, 1, 0> + right <1, 0, 0> + look_at <0, 0, 0> +} + +sphere { + <0,0,0>, 2.5 + texture { Glass + scale <0.7, 0.7, 0.7> + rotate y*clock + normal {bumps 0.4 scale 0.1} + finish { Shiny } +# finish { phong 0.4 } + } +} + +light_source {<6, 7, 0> color White} +light_source {<6.1, 1, 0> color Blue} diff --git a/hacks/images/bubbles/glass1.xpm b/hacks/images/bubbles/glass1.xpm new file mode 100644 index 00000000..0c17ea4d --- /dev/null +++ b/hacks/images/bubbles/glass1.xpm @@ -0,0 +1,79 @@ +/* XPM */ +static char *glass1[] = { +/* width height ncolors chars_per_pixel */ +"10 10 62 1", +/* colors */ +" c #000000", +". c #27274E", +"X c #29293F", +"o c #2C2C63", +"O c #353579", +"+ c #242447", +"@ c #222245", +"# c #25253E", +"$ c #1C1C3F", +"% c #2B2B47", +"& c #252544", +"* c #222251", +"= c #323264", +"- c #212146", +"; c #37374B", +": c #22223D", +"> c #252536", +", c #232337", +"< c #34346C", +"1 c #303068", +"2 c #26264A", +"3 c #5D5D97", +"4 c #363674", +"5 c #2C2C6A", +"6 c #2E2E5B", +"7 c #242451", +"8 c #343464", +"9 c #3C3C6F", +"0 c #353572", +"q c #38386B", +"w c #242454", +"e c #181831", +"r c #28285B", +"t c #37377A", +"y c #20203F", +"u c #26265C", +"i c #4C4C60", +"p c #383874", +"a c #333379", +"s c #444458", +"d c #272756", +"f c #32326E", +"g c #30306C", +"h c #40407F", +"j c #292944", +"k c #212150", +"l c #323271", +"z c #2D2D76", +"x c #21213F", +"c c #25255A", +"v c #35356D", +"b c #313169", +"n c #2C2C6E", +"m c #18182C", +"M c #232344", +"N c #292961", +"B c #202037", +"V c #1C1C33", +"C c #242452", +"Z c #45456F", +"A c #242455", +"S c None", +/* pixels */ +"SSSiZZZsSS", +"SS;8v39=;S", +"S%6q5lp<6,", +"SxrfOt4go2", +"S$bunzaNrM", +"SeAc5hg1d-", +"Smykw0r*@V", +"SSB7C.k+:S", +"SSS>j&X#SS", +"SSSSSSSSSS" +}; diff --git a/hacks/images/bubbles/glass10.xpm b/hacks/images/bubbles/glass10.xpm new file mode 100644 index 00000000..f62e3d26 --- /dev/null +++ b/hacks/images/bubbles/glass10.xpm @@ -0,0 +1,155 @@ +/* XPM */ +static char *glass10[] = { +/* width height ncolors chars_per_pixel */ +"60 60 88 1", +/* colors */ +" c #000000", +". c #41416E", +"X c #1F1F46", +"o c #2C2C63", +"O c #404066", +"+ c #28285F", +"@ c #212137", +"# c #2E2E68", +"$ c #25253E", +"% c #2C2C3E", +"& c #24244A", +"* c #4A4A62", +"= c #35357F", +"- c #252558", +"; c #26264F", +": c #404083", +"> c #22224B", +", c #2D2D63", +"< c #2B2B61", +"1 c #21212C", +"2 c #343463", +"3 c #2F2F68", +"4 c #2D2D66", +"5 c #30305F", +"6 c #31316D", +"7 c #4C4C6D", +"8 c #2A2A45", +"9 c #2D2D69", +"0 c #3E3E73", +"q c #22223D", +"w c #2A2A5C", +"e c #28285A", +"r c #333372", +"t c #212149", +"y c #171728", +"u c #2C2C4D", +"i c #34346C", +"p c #32326A", +"a c #303068", +"s c #242445", +"d c #2A2A62", +"f c #2D2D5B", +"g c #292957", +"h c #232351", +"j c #26264A", +"k c #B3B3D1", +"l c #282838", +"z c #2D2D5E", +"x c #3A3A78", +"c c #343472", +"v c #252556", +"b c #30306E", +"n c #27275B", +"m c #1B1B38", +"M c #35356C", +"N c #58588B", +"B c #262653", +"V c #282841", +"C c #1D1D40", +"Z c #13131F", +"A c #242454", +"S c #1B1B2A", +"D c #2B2B68", +"F c #4C4C85", +"G c #2D2D6D", +"H c #20203F", +"J c #1E1E3D", +"K c #333376", +"L c #505064", +"P c #3636B1", +"I c #383874", +"U c #272756", +"Y c #191931", +"T c #353553", +"R c #2A2A66", +"E c #2A2A52", +"W c #3E3E55", +"Q c #464674", +"! c #292933", +"~ c #3A3A68", +"^ c #22224D", +"/ c #1C1C33", +"( c #242452", +") c #222250", +"_ c #484868", +"` c #212145", +"' c #353573", +"] c None", +/* pixels */ +"]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]", +"]]]]]]]]]]]]]]]]]]]]]]]]LLLLLLLLLLLLL]]]]]]]]]]]]]]]]]]]]]]]", +"]]]]]]]]]]]]]]]]]]]]]*L**L777LLL7LL7*LLL]]]]]]]]]]]]]]]]]]]]", +"]]]]]]]]]]]]]]]]]]**L_777_77L77777777__L7*L]]]]]]]]]]]]]]]]]", +"]]]]]]]]]]]]]]]]W***7777_777_7777Q777_77_***W]]]]]]]]]]]]]]]", +"]]]]]]]]]]]]]]]****_W_O7QQQ_Q.Q7.7.OQ.Q_7_WO*W]]]]]]]]]]]]]]", +"]]]]]]]]]]]]]*W_OW_____QQ.O_QF...QQ~..Q_.OOOOWWW]]]]]]]]]]]]", +"]]]]]]]]]]]]WW*W~OW~.__.Q...~..._0.N..~.O2OOOO*WT]]]]]]]]]]]", +"]]]]]]]]]]]TTWTT~W~.O~~..OFF.0~Fk00.~..~~O~O~~WWWW]]]]]]]]]]", +"]]]]]]]]]]WWOW5~T~~~~O~~0iFN~NNFFFO~.2200~~2TWWWWTW]]]]]]]]]", +"]]]]]]]]]TTWWT~~5~~2~2~00NNNNN0N##Q~00222~225W~WTW%%]]]]]]]]", +"]]]]]]]]WTWWTTTT522~~~M2MiNN0NNN~Nki0I~M2p22~555TTT%T]]]]]]]", +"]]]]]]]%TTTTuff5f220paapiMkNQNN0~I:MiiMpr2p,Ef255TuuTT]]]]]]", +"]]]]]]]8TTTuf522ff~i2aipp9F~NNxNN0~FFxp2o5f25fz25uu8TT]]]]]]", +"]]]]]]%8qTEuf55B2fp5,ipopbIFMkNkNFIx:i9Mi,4ap5gfff5E%V!]]]]]", +"]]]]]!l8$T$Ef5ff22ii6pIiM0kF0N6bNFxrMp3+i,MpppEffEEEq8%%]]]]", +"]]]]]!uVu&E52f2,ffpi4apipcN:F:r:FNFc'xMr'3paM4vffjEEVu8T]]]]", +"]]]]1u8suu;Ef555aM~3<'6'9bxbFcrNNNxKI:66'#iipzfwff;uqu@@1]]]", +"]]]]1@qsuj;g5U,-z5a3b'6cGKx'FK'NFFFrb:x64#iMp5fpfB`&usqqS]]]", +"]]]]18;mH&>ff^e43ip6#39'xNK==PrKKNQIcxx'oo'i+25p5E&j&j$@S]]]", +"]]]11Ysjjs&;gUg,#93prGr9rxxr==PK=xk'rx'b93o#i<5z55g;$8H/S1]]", +"]]]@/Yq>E^f;awoM'b'Ir9GRGPrrPKKxP=:'rGrr4r#pppU,U5BvE`YyYy]]", +"]]]1@@8;EUff,2w'II3b9bcbxrr=P:N=PPKxrr=Gop6Mapze-;5;^EmyZ/]]", +"]]S1y&H(uXgUew34ii6'#''=Kr6==rx=KPP''rr6do6'MaznogfgX`jH@1Z]", +"]]Z@@8`Hff5Bnn4a3o3I'x'P=+bP=xxP9PP:=rr'9Ro6M#z(<2f2&`ss/ZZ]", +"]]1yY&s`wfUpdAw#DAp99'brcxP=PPKPG==xxxxxG+66o33pdAzgCE`mYyy]", +"]]Y@Y`sHEfg2-wd3pdM6brbr'=9RPPP==K9''xcI'or'6op,g^mmHYZ]", +"]]ZymC&;&>ww^gev4d+64#9r'=:GPK=PKr:9bRo33463-+Awz>U;;&HYyZZ]", +"]]ZyJm`J&^get),e-n446roRrKKrP==xN=9'bG9#owd4,o-#5A^^&E`@YZZ]", +"]]ZyYJH&st>`)n>AUvn-4o66D9r:kKP:Kx=oF6+4o44a4eww)U^B>`C`HY@Z]", +"]]]/yyH`mv^UA^w<)--p4oKx#'r4=:xQNk9Gx+++44o64(ehB>XHsYmy]]", +"]]]ZyyJ&s;;g&;ap<--+-66'oob6I4x6r3NI:9ooo4e43dw-(;>t`tm/yZ]]", +"]]]ZZymJs&wfC;e<4+dw-+966x3663#QxI9'r6no44vvUe)(X`Jm/mmYyy]]", +"]]]]yyYJJJm(C;vtet)Avn46ox4d6#k#F#4#`gBe^(e+A+pw,#ooMo+kNw'+xM4+nA))ewBtC`m@@YyS]]]", +"]]]]Syyy@CHsHCev^>)+4e@Y/1S]]]", +"]]]]]Sy/@HYJ;`XU(hv-XUe>wveA)4v+-(--++-vAU-A-(ht>((g^Xtq;m/1y1]]]]", +"]]]]]]1yYYHmCJqt((^&^UawvvAAwAEeewn-(w(>>;(AftsHt$$mYY1]]]]]", +"]]]]]]]S1Y@qJX$X`tth&hv)(^-v-wEh-A(4<;A-jt;(Xt$qmmJml1]]]]]]", +"]]]]]]]1l@/mCJVss`^->;h&&>ev^hewe-(;v;(h&&sJss$JmmJ@S1]]]]]]", +"]]]]]]]]1@@@@HXX&t(X(veA(^&;(;;(Ah^()(h&^tstHlV!q@/l1]]]]]]]", +"]]]]]]]]]l@@m/J@`XVt&^A(w^j^h;&^>jj>>>>&t`>&X$$@q@l1]]]]]]]]", +"]]]]]]]]]]l1!qHs$s8j>&(^&&&(^(A(U>&jjjuu&ts`H@q1@@1]]]]]]]]]", +"]]]]]]]]]]]1@@lV$$%ss&ts&uuuu8&tju88V(st`$sV@V@!l!]]]]]]]]]]", +"]]]]]]]]]]]]11l@l$8j&V8sjj88^&jj^s8s8Vst`$$$qlll1]]]]]]]]]]]", +"]]]]]]]]]]]]]1!/qVqVH8VsV$&t&u888>tVsHV&V8ll$ll1]]]]]]]]]]]]", +"]]]]]]]]]]]]]]]!11lVqVV888VjV8s88s88Vl$Vq%$ll!]]]]]]]]]]]]]]", +"]]]]]]]]]]]]]]]]!1!ll$$8VVVVs88Vjss$VVlll%l!!]]]]]]]]]]]]]]]", +"]]]]]]]]]]]]]]]]]]11l$%l%V$%$%%Vll%%VVl!l!1]]]]]]]]]]]]]]]]]", +"]]]]]]]]]]]]]]]]]]]]]!l%%V!llllV!!l!l!!!]]]]]]]]]]]]]]]]]]]]", +"]]]]]]]]]]]]]]]]]]]]]]]]!!!!l!ll!!!!!]]]]]]]]]]]]]]]]]]]]]]]", +"]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]", +"]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]" +}; diff --git a/hacks/images/bubbles/glass11.xpm b/hacks/images/bubbles/glass11.xpm new file mode 100644 index 00000000..afdc4fe7 --- /dev/null +++ b/hacks/images/bubbles/glass11.xpm @@ -0,0 +1,167 @@ +/* XPM */ +static char *glass11[] = { +/* width height ncolors chars_per_pixel */ +"72 72 88 1", +/* colors */ +" c #000000", +". c #54548E", +"X c #4A4A6D", +"o c #25254C", +"O c #323266", +"+ c #3B3B68", +"@ c #23234D", +"# c #29293F", +"$ c #242444", +"% c #3E3E78", +"& c #2C2C63", +"* c #2A2A61", +"= c #28285F", +"- c #353579", +"; c #2E2E3D", +": c #242447", +"> c #25253E", +", c #363673", +"< c #2B2B47", +"1 c #30306D", +"2 c #26264C", +"3 c #29295C", +"4 c #252558", +"5 c #464675", +"6 c #21212C", +"7 c #262652", +"8 c #343463", +"9 c #2F2F68", +"0 c #4A4A68", +"q c #2D2D66", +"w c #22223A", +"e c #262655", +"r c #282843", +"t c #2A2A5C", +"y c #28285A", +"u c #2F2F6E", +"i c #2D2D6C", +"p c #23234B", +"a c #171728", +"s c #1F1F47", +"d c #2C2C4D", +"f c #32326A", +"g c #2C2C64", +"h c #2D2D5B", +"j c #292957", +"k c #232351", +"l c #B3B3D1", +"z c #222246", +"x c #282838", +"c c #252556", +"v c #27275B", +"b c #323273", +"n c #1B1B38", +"m c #35356C", +"M c #33336D", +"N c #242451", +"B c #27274A", +"V c #22224F", +"C c #2E2E5E", +"Z c #333384", +"A c #1D1D40", +"S c #13131F", +"D c #353572", +"F c #242454", +"G c #1B1B2A", +"H c #2E2E61", +"J c #3D3D80", +"K c #21214A", +"L c #3F3F6E", +"P c #20203F", +"I c #3636B1", +"U c #48485C", +"Y c #191931", +"T c #353553", +"R c #2A2A66", +"E c #1F1F3A", +"W c #343473", +"Q c #2A2A52", +"! c #323271", +"~ c #292933", +"^ c #3C3C56", +"/ c #313169", +"( c #2B2B63", +") c #3D3D64", +"_ c #1C1C33", +"` c #2D2D68", +"' c #1F1F43", +"] c None", +/* pixels */ +"]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]", +"]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]000000UU00U]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]", +"]]]]]]]]]]]]]]]]]]]]]]]]]]]U00U00000000000000U]]]]]]]]]]]]]]]]]]]]]]]]]]", +"]]]]]]]]]]]]]]]]]]]]]]]]UU00U00U000000U00000U0000]]]]]]]]]]]]]]]]]]]]]]]", +"]]]]]]]]]]]]]]]]]]]]]]UUU00XXXXXX0XX00XXXXX0000U00U]]]]]]]]]]]]]]]]]]]]]", +"]]]]]]]]]]]]]]]]]]]]0^00X00XX00XX0XX0XXX5X0X0XXX0U0U0]]]]]]]]]]]]]]]]]]]", +"]]]]]]]]]]]]]]]]]]UUUUU0^0))X555XX5LLXXXX))XXLXXU0UU)UU]]]]]]]]]]]]]]]]]", +"]]]]]]]]]]]]]]]]]UU0UU0)00)05LXLX5X5LLLLLLL5XL50L00UUU^^]]]]]]]]]]]]]]]]", +"]]]]]]]]]]]]]]]U^)U)^))))))X.55L))L55XX5XLLLXmL0)+))))^^^T]]]]]]]]]]]]]]", +"]]]]]]]]]]]]]]^UU^^^)^++L)))LL)L.L+m)LLL5555LLLL))C)++^U^^^]]]]]]]]]]]]]", +"]]]]]]]]]]]]]^T^^^^+^++5)++)LL)5lLLLm5l.%LLmmL)mmL+))8+^^^U^]]]]]]]]]]]]", +"]]]]]]]]]]]]^^^^^C+^+++++)+mLLm5lLL...5lL+mLLO+LL)++8C^^^^^T^]]]]]]]]]]]", +"]]]]]]]]]]]TT^^^+^^C8++++8mmLm5l.lll%l.9.LmLL888/mmC+C^+^dT^;;]]]]]]]]]]", +"]]]]]]]]]]TT^^^^+^^h888+mm8mOm%L.55...%fD.mmmmmm89O8++C^CTTT^~T]]]]]]]]]", +"]]]]]]]]]T;TT^TCCCCCCC8mmmm8Ofml..L.l%mml.LmmmmLmmmOCC8CC+T^TdTT]]]]]]]]", +"]]]]]]]]]T;TBTPdQhhjh8Omm91m/mDD%.l%%lM1.l%DMDfm=HmHmqfOOjQChCQQr#;<]]]]]]", +"]]]]]]~<<#dzphOhCHhhhf9Dqq/m91%ll...1-,...D9L%/qm9ff/,qtjCh2Qdr>d66]]]]]", +"]]]]]]#T#BdB7QC8O9HChmmmH/mm,1!Di`JW1.l..J1b5mfbm9M9qq*j4hh2QQ$Bdd>]]]]]", +"]]]]]6;r>rQBoehhhCH/mmHqqDDb!ib-,..uD.l..-b!.,b1b9mf/fHH9HQjBB6]]]]", +"]]]]]Sx>BBQB7NhhyHetCHm91m11!bb-1JWb-.JJl.,!%JDuqq9mD9Hhhfh7'$Q:B>E6]]]]", +"]]]]Gw'2hjhhH*H9m,DDD,uRu1!u-b-IIJ.JZIZ-,W!i-uqm9bmOm9jHyhhe@:'nSSYG]]", +"]]]aaYE<7oQNheh9&9mmDM1Dq,,!WD!1-IZ%J-II--%,-b!1(911,99Hj**eO@zp2PYSaG]]", +"]]]SYEB$eBo@jjt4gqqmmM,D/D,WZ-u`-ZZb-ZiZII,-!!DM*q(bmm9HtqqhhhpzoBPESG]]", +"]]]S_>r$2QChCe3v*999g`M,,,,bIb=ubIJ--IRIIIJJW!DWiR=19m9hy4fChHooB::aaY]]", +"]]S6aa::ozhheHq4cv9`44991-!!!W-ZZII--IbbII-%----i=(!m*9qfy&jhh'7B'Aaa_S]", +"]]a_Yn::zoQhjm**k(qM=q19u!ubb,ZbiZiIIIZbbi-D,-D%D*i-b/qf9H=NOhP7QzaE_aG]", +"]]Sa_az'P2QhjHh4yf9/9,-11!ubWWZbiZIZZIIIIb---,D-,1iWMbqq((vHHOrBpBYnAa_]", +"]]S6waP'2sQjjhyV*fq*ff!!u!!uuuibIIIRRZIZZZIIbb--D!i(1,qq/qFeoeB''$_naYS]", +"]]SSw__'psQe&ej*y&g&M=R11!!iiRRZ-b-RRb=ZIIZZub-uu`==9,*FHCkjK7P''nazSaY]", +"]]aaPw$AzNQ@Vy/&h(/f`v*!--1RRiu-ZbZibZI--IZ-IZZi*=*4qfgv9hFhCh@:zPYYSSS]", +"]]SaPYYnANKKAhHk4//=*vR`-,1iubZbiiubZIIIZ-iZWZ!1Rg`=9`9f*=hHte7''PBP_SS]", +"]]S_6_nn'@Ktehhsk*q=1(R1M1*iJWZbiZRIIIbZu=*R!-iu`W`M9=q&hjHhjK@QAn'AEaS]", +"]]SaY_p$PQ2Nh&@7yey91((u`g`ub-IbIbbbIIbZZuR`J!q`1111=K4Fcytee7e@7na_EaS]", +"]]SSaYno::2@hHA7hyF=v4&9R9RR-,Z-uZbbIIJ1ZZZ-u*q1q=(1(&(c*&jKN77'2PEESYS]", +"]]SGYnAz:'7@eeKkFHy=4(99MD9*R1W.!ZIZ-WDi.`-b-R`q&==vq&&=q/hKkNoppPEYESS]", +"]]]aSnAA:'z@@@Kc4KFe44qW,-biR11JZZ.JJiZZZ(u,i1!`9qv3tcq=4ttsNezoAn_aaa]]", +"]]]Sa_a_n''A@eNkskeKFc*q(b!`iub.-Zl-lI.Zi9.u*(`R`qqq=y*=kNj@e7z'A'P_aS]]", +"]]]SSYYnnAKsNeKk@thFF==Rq(qb11WJlIJ.Z...i1-I*=(=q/(99tNecNeoj@A'n:YASa]]", +"]]]SS_aAoPAeKjhKeqHvcc44*11D,==.mq-9l...lR`bq/&=*q39M9vqeeeoeszQpA_Y_S]]", +"]]]]SSYn'P2ojhozj/mq=y33Nq1WDq(1%9%qJ,!(%.Z!!9(qgq3y=*=jN4oeAzA'zY_aS]]]", +"]]]]SaanYnBzjhKzeeyq4&==4y*11919J.D,9%D*m1bW1vv(q93Fecyk@s'sAnwnnYYSS]]]", +"]]]]SaaE_PnAn@A'hkKtKNVccv=1Mq%q(J,,l1J.q(9q4Fv==&tVFF3NtsKPPP>wnYaaS]]]", +"]]]]]SY_Y_nnEEzAsj7t@eNy3cc19y.fg.*(gv,,%3J=gf&*vv=kkVy4j@Kn'AExn_aa]]]]", +"]]]]]SG_aYw'Ar'As*e@pKv(qvyH*Fm=3m=9%*%q3=(**9/9qF@VNkthe'zz'@EE__aS]]]]", +"]]]]]]aGY_wnAPnPANNKVKk*q==(ykN444(,9yFc*4q*yvcq&vyyjNNjN$P'AKaYYG6]]]]]", +"]]]]]]GY66nPYAp7zAjtkyc4=FNy3c=gcccf&Ft4v433cceFk4c@y@VeAsAzz'_E_a6]]]]]", +"]]]]]]]66__AAnAz''FyKNFeh4F*=F=4eNHvyv4ccVec4ce@@z@KVjyp'zK#pnYEYE]]]]]]", +"]]]]]]]a6YnYPnAAPPKNNN2@@7Hq4ccFkF4FQ433=v4NvFo@@2FKjjK::'wP>nnE_G]]]]]]", +"]]]]]]]]a_6nn>nAP$sK'NKookeykkkc4N4cQ7yyc4H=jNe4BoNeeKK>>PnnnA6E6]]]]]]]", +"]]]]]]]]]666_AAA>$:''@NyK2k@NN@4y4N444vFkOy37@c@2KpzAzz>EEnn>A6G]]]]]]]]", +"]]]]]]]]]6x666_PP'':zzkk@NyNKNN@kNe7NFtyeN@N@KKoKK$zz$>x>xPE_w66]]]]]]]]", +"]]]]]]]]]]66w6wEAPPpzzz'@ec4yek22kk7277N7VN@@N@@N':Kz'#>xwwxEx6]]]]]]]]]", +"]]]]]]]]]]]6w6___PEKAprKppNN@e@Bo@@7KNk@>wEwx666]]]]]]]]]]", +"]]]]]]]]]]]]xwExwA$>$>#@@K@@opoo@NNNFNeNooBBBBBBpz:$'PE>6wx66]]]]]]]]]]]", +"]]]]]]]]]]]]]6Ew6#>>#r#$$op:p:BBBBBBpKoBB<$w#>x~~~]]]]]]]]]]]]", +"]]]]]]]]]]]]]]~6~~E##$#r$r<>BpB<<:K2B@z:<w>#E~~6]]]]]]]]]]]]]", +"]]]]]]]]]]]]]]]6~xw>>w#r:$rwrBB$p:2B<:>#>>#>xx~6]]]]]]]]]]]]]]", +"]]]]]]]]]]]]]]]]];x6E#>#>#;r:##BzzoBr<r>xx#xxx]]]]]]]]]]]]]]]]", +"]]]]]]]]]]]]]]]]]]~~_~x#>>#>rrrrBr##:rw;6~]]]]]]]]]]]]]]]]]", +"]]]]]]]]]]]]]]]]]]]];~>~x>>#>#rxxwx#xx~]]]]]]]]]]]]]]]]]]]", +"]]]]]]]]]]]]]]]]]]]]]]~~x>xx;###;xx;<#>#x#;###~~;;~]]]]]]]]]]]]]]]]]]]]]", +"]]]]]]]]]]]]]]]]]]]]]]]]~6#~xxxxx#;~~~#xx;#;xx~~~]]]]]]]]]]]]]]]]]]]]]]]", +"]]]]]]]]]]]]]]]]]]]]]]]]]]]6x;;;~xx#~~;~x~~T~~]]]]]]]]]]]]]]]]]]]]]]]]]]", +"]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]~6;~~~~;~~~]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]", +"]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]", +"]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]" +}; diff --git a/hacks/images/bubbles/glass2.xpm b/hacks/images/bubbles/glass2.xpm new file mode 100644 index 00000000..56359490 --- /dev/null +++ b/hacks/images/bubbles/glass2.xpm @@ -0,0 +1,95 @@ +/* XPM */ +static char *glass2[] = { +/* width height ncolors chars_per_pixel */ +"12 12 76 1", +/* colors */ +" c #000000", +". c #25254C", +"X c #23234A", +"o c #212148", +"O c #2E2E62", +"+ c #29293F", +"@ c #272754", +"# c #414188", +"$ c #20202C", +"% c #2E2E68", +"& c #242447", +"* c #25253E", +"= c #B9B9ED", +"- c #6767A3", +"; c #2B2B47", +": c #29295C", +"> c #252544", +", c #29295F", +"< c #1F1F3E", +"1 c #2F2F68", +"2 c #2D2D66", +"3 c #30305F", +"4 c #4C4C6D", +"5 c #2B2B53", +"6 c #2F2F6E", +"7 c #34346C", +"8 c #3B3B55", +"9 c #303068", +"0 c #2C2C64", +"q c #26264A", +"w c #5D5D97", +"e c #363674", +"r c #3C3C66", +"t c #252556", +"y c #30306E", +"u c #3E3E54", +"i c #2C2C6A", +"p c #4C4C68", +"a c #20204A", +"s c #2E2E5B", +"d c #343464", +"f c #16162C", +"g c #292938", +"h c #333384", +"j c #3C3C6F", +"k c #1E1E37", +"l c #38386B", +"z c #242454", +"x c #31316E", +"c c #181831", +"v c #232349", +"b c #272739", +"n c #23234C", +"m c #37377A", +"M c #1E1E3D", +"N c #313174", +"B c #3C3C78", +"V c #383874", +"C c #1B1B33", +"Z c #40407F", +"A c #292944", +"S c #212150", +"D c #2D2D76", +"F c #191937", +"G c #313169", +"H c #22224D", +"J c #18182C", +"K c #2D2D65", +"L c #232344", +"P c #292961", +"I c #27275F", +"U c #242452", +"Y c #484868", +"T c #262657", +"R c #242455", +"E c None", +/* pixels */ +"EEEE4pppYEEE", +"EEurr7wlj8uE", +"EE5@OywB733E", +"E;nK%-NV0dvk", +"EA39eIm#i%s&", +"ELSGm6DhP03c", +"EMnRVxZ612UC", +"EfFatB=%,:n.zqXk$E", +"EEEEb+;*bEEE", +"EEEEEEEEEEEE" +}; diff --git a/hacks/images/bubbles/glass3.xpm b/hacks/images/bubbles/glass3.xpm new file mode 100644 index 00000000..c7464308 --- /dev/null +++ b/hacks/images/bubbles/glass3.xpm @@ -0,0 +1,112 @@ +/* XPM */ +static char *glass3[] = { +/* width height ncolors chars_per_pixel */ +"14 14 91 1", +/* colors */ +" c #000000", +". c #27274E", +"X c #383858", +"o c #2E2E62", +"O c #292967", +"+ c #3535A1", +"@ c #272751", +"# c #23234D", +"$ c #29293F", +"% c #353579", +"& c #272754", +"* c #20202C", +"= c #2E2E3D", +"- c #242447", +"; c #25253E", +": c #3E3E67", +"> c #1C1C3F", +", c #6767A3", +"< c #2B2B47", +"1 c #29295C", +"2 c #2B2B61", +"3 c #29295F", +"4 c #1F1F3E", +"5 c #2F2F68", +"6 c #2D2D66", +"7 c #222251", +"8 c #2D2D69", +"9 c #33335B", +"0 c #37374B", +"q c #22223D", +"w c #28285A", +"e c #2B2B53", +"r c #2C2C36", +"t c #424266", +"y c #232337", +"u c #525265", +"i c #32326A", +"p c #1B1B2F", +"a c #303068", +"s c #232351", +"d c #363674", +"f c #3C3C66", +"g c #252556", +"h c #27275B", +"j c #363663", +"k c #4C4C68", +"l c #2E2E5B", +"z c #29294C", +"x c #27274A", +"c c #252548", +"v c #16162C", +"b c #292938", +"n c #353572", +"m c #38386B", +"M c #4C4C85", +"N c #2F2F83", +"B c #20203F", +"V c #313174", +"C c #333379", +"Z c #444458", +"A c #272756", +"S c #47477C", +"D c #32326E", +"F c #1B1B33", +"G c #30306C", +"H c #40407F", +"J c #23233E", +"K c #141422", +"L c #343473", +"P c #2D2D76", +"I c #2E2E6D", +"U c #40406E", +"Y c #21213F", +"T c #8080BA", +"R c #25255A", +"E c #1B1B39", +"W c #35356D", +"Q c #262651", +"! c #18182C", +"~ c #373786", +"^ c #2B2B63", +"/ c #202037", +"( c #1C1C33", +") c #242452", +"_ c #484868", +"` c #1F1F43", +"' c #2C2C5D", +"] c #3535DD", +"[ c #262657", +"{ c #242455", +"} c None", +/* pixels */ +"}}}}}k_uk_}}}}", +"}}}Z9:UUUft0}}", +"}}=ejW,TSio9X}", +"}}99liMDMDalx}", +"}/&oOOC+Md5'.(", +"}!lgR%C~]%n3.!", +"}J.23LCP]VRoQE", +"}F@{1DHNI835#p", +"}K..36GiS^[A>v", +"}}yYsmh23)wBp}", +"}}*Y`))[Q74q*}", +"}}}bYxzc<-;;}}", +"}}}}}b$<;r}}}}", +"}}}}}}}}}}}}}}" +}; diff --git a/hacks/images/bubbles/glass4.xpm b/hacks/images/bubbles/glass4.xpm new file mode 100644 index 00000000..dc5cc769 --- /dev/null +++ b/hacks/images/bubbles/glass4.xpm @@ -0,0 +1,118 @@ +/* XPM */ +static char *glass4[] = { +/* width height ncolors chars_per_pixel */ +"20 20 91 1", +/* colors */ +" c #000000", +". c #4A4A6D", +"X c #25254C", +"o c #23234A", +"O c #252538", +"+ c #1E1E3B", +"@ c #2A2A61", +"# c #353579", +"$ c #272754", +"% c #2E2E3D", +"& c #21214E", +"* c #2E2E68", +"= c #242447", +"- c #3E3E7B", +"; c #222245", +": c #2B2B5B", +"> c #1C1C3F", +", c #444459", +"< c #9090C8", +"1 c #292931", +"2 c #26264F", +"3 c #252544", +"4 c #31317E", +"5 c #21212C", +"6 c #2F2F68", +"7 c #30305F", +"8 c #262655", +"9 c #31316D", +"0 c #1A1A32", +"q c #252536", +"w c #2B2B53", +"e c #46467E", +"r c #2F2F6E", +"t c #2C2C36", +"y c #212149", +"u c #303068", +"i c #232351", +"p c #272741", +"a c #44446E", +"s c #353552", +"d c #23233D", +"f c #363674", +"g c #12121F", +"h c #3535BF", +"j c #181828", +"k c #2A2A68", +"l c #29295D", +"z c #27275B", +"x c #58588B", +"c c #22224C", +"v c #2E2E5B", +"b c #303074", +"n c #29294C", +"m c #242451", +"M c #27274A", +"N c #292938", +"B c #282858", +"V c #353572", +"C c #1E1E37", +"Z c #38386B", +"A c #262656", +"S c #242454", +"D c #212147", +"F c #36366C", +"G c #2D2D6D", +"H c #222241", +"J c #313149", +"K c #505064", +"L c #4C4C60", +"P c #2C2C65", +"I c #1E1E40", +"U c #383874", +"Y c #32326E", +"T c #1E1E2C", +"R c #30306C", +"E c #373780", +"W c #323271", +"Q c #2D2D62", +"! c #3C3C6A", +"~ c #35356D", +"^ c #191937", +"/ c #33336B", +"( c #343462", +") c #2A2A41", +"_ c #2B2B63", +"` c #292961", +"' c #202037", +"] c #252549", +"[ c #1F1F43", +"{ c #2C2C5D", +"} c None", +/* pixels */ +"}}}}}}}LL.KKLK}}}}}}", +"}}}}},L.a.a.a.,,}}}}", +"}}}}ss(!axZ-ZZ!(,}}}", +"}}}sss(Z~XuuzfG4bb#G`Pz:;0", +"}j]ccAl*fGEbr6Rl{2Ig", +"}g0>S8zYG<-4R_u:AcDC", +"}g^o>@@l9R*UW_8z[^^j", +"}}j>I8&zSzVlz*i:;c0}", +"}}50IycAASwlmcmyy+5}", +"}}}''[m8m22i&X=Odq}}", +"}}}}'p)Xononpy3)q}}}", +"}}}}}tqp)M33))d1}}}}", +"}}}}}}}t%NNtNt}}}}}}", +"}}}}}}}}}}}}}}}}}}}}" +}; diff --git a/hacks/images/bubbles/glass5.xpm b/hacks/images/bubbles/glass5.xpm new file mode 100644 index 00000000..e7af604e --- /dev/null +++ b/hacks/images/bubbles/glass5.xpm @@ -0,0 +1,120 @@ +/* XPM */ +static char *glass5[] = { +/* width height ncolors chars_per_pixel */ +"24 24 89 1", +/* colors */ +" c #000000", +". c #27274E", +"X c #2F2F6D", +"o c #25254C", +"O c #2E2E62", +"+ c #2A2A33", +"@ c #35354B", +"# c #20203D", +"$ c #24242D", +"% c #272751", +"& c #1E1E2A", +"* c #2E2E68", +"= c #242447", +"- c #181824", +"; c #25253E", +": c #424257", +"> c #242436", +", c #202049", +"< c #2F2F68", +"1 c #4A4A68", +"2 c #2D2D66", +"3 c #30305F", +"4 c #31316D", +"5 c #4C4C6D", +"6 c #2A2A45", +"7 c #2C2C72", +"8 c #2D2D69", +"9 c #2B2B53", +"0 c #333372", +"q c #2F2F99", +"w c #424266", +"e c #26265B", +"r c #34346C", +"t c #32326A", +"y c #1B1B2F", +"u c #303068", +"i c #21214C", +"p c #2C2C64", +"a c #282860", +"s c #333364", +"d c #17172E", +"f c #B3B3D1", +"g c #222246", +"h c #5D5D97", +"j c #2B2B5C", +"k c #3A3A64", +"l c #252556", +"z c #1B1B35", +"x c #30306E", +"c c #2A2A68", +"v c #3E3E6B", +"b c #4F4F75", +"n c #2B2B62", +"m c #2E2E5B", +"M c #323276", +"N c #22224F", +"B c #292938", +"V c #333384", +"C c #1D1D40", +"Z c #13131F", +"A c #282858", +"S c #38386B", +"D c #262656", +"F c #242454", +"G c #272739", +"H c #1F1F45", +"J c #28285B", +"K c #23234C", +"L c #37377A", +"P c #3B3B56", +"I c #46466E", +"U c #4A4A5E", +"Y c #3636B1", +"T c #383874", +"R c #242449", +"E c #323271", +"W c #3E3E80", +"Q c #34345F", +"! c #2A2A3E", +"~ c #35356D", +"^ c #313169", +"/ c #22224D", +"( c #18182C", +") c #2D2D65", +"_ c #262654", +"` c #242452", +"' c #27274B", +"] c #353573", +"[ c None", +/* pixels */ +"[[[[[[[[[UU5555U[[[[[[[[", +"[[[[[[[:5511151I1U[[[[[[", +"[[[[[::wvIIwIIvSww:@[[[[", +"[[[[P:kkkSrvhhSsvkPPP[[[", +"[[[@@QQ3~srhfSvrSssk@@[[", +"[[[69j_sO2xvhfTtr<3P3@[[", +"[[;'%sOrO~E84hxr~unm9';[", +"[[6=KA)t*EhVM]TWp]s^R'z[", +"[-z.mn~]XxMqbYT820~Om=-&", +"[-6%3eu8]MaYLqWE84*Dmo=y", +"[(g.ADuTX0VVVYM]T]2nO'd-", +"[-g`Np^eLcX77MVVaepj3=dZ", +"[(R%j%Jn8Xq7qVcE44eJ_/d-", +"[(#HKlFeT74VWVXx=;K/o`F`''Rgz>&[[[", +"[[[[[&>#=#'=6/og;;>$[[[[", +"[[[[[[[+G;!=6=;GGB[[[[[[", +"[[[[[[[[[$!B++++[[[[[[[[", +"[[[[[[[[[[[[[[[[[[[[[[[[" +}; diff --git a/hacks/images/bubbles/glass6.xpm b/hacks/images/bubbles/glass6.xpm new file mode 100644 index 00000000..05abe353 --- /dev/null +++ b/hacks/images/bubbles/glass6.xpm @@ -0,0 +1,128 @@ +/* XPM */ +static char *glass6[] = { +/* width height ncolors chars_per_pixel */ +"30 30 91 1", +/* colors */ +" c #000000", +". c #25254C", +"X c #23234A", +"o c #35354B", +"O c #2A2A5E", +"+ c #3A3A71", +"@ c #24242D", +"# c #3535A1", +"$ c #1F1F49", +"% c #404066", +"& c #BFBFDC", +"* c #2E2E7C", +"= c #2E2E68", +"- c #242447", +"; c #2C2C66", +": c #181824", +"> c #25253E", +", c #21213A", +"< c #2A2A50", +"1 c #4A4A62", +"2 c #252558", +"3 c #292948", +"4 c #363679", +"5 c #1F1F3E", +"6 c #343463", +"7 c #353585", +"8 c #2C2C5B", +"9 c #4C4C6D", +"0 c #27274C", +"q c #28285A", +"w c #3F3F56", +"e c #19192A", +"r c #5D5D91", +"t c #2F2FB0", +"y c #34346C", +"u c #525265", +"i c #303068", +"p c #2A2A62", +"a c #232351", +"s c #191930", +"d c #34345B", +"f c #2F2F60", +"g c #3A3A78", +"h c #2B2B5C", +"j c #494980", +"k c #343472", +"l c #3A3A64", +"z c #2C2C6A", +"x c #27275B", +"c c #1B1B38", +"v c #35356C", +"b c #2E2E5B", +"n c #24243A", +"m c #27275E", +"M c #323276", +"N c #31316B", +"B c #4D4D62", +"V c #282841", +"C c #292938", +"Z c #13131F", +"A c #38386B", +"S c #242454", +"D c #31316E", +"F c #2D2D6D", +"G c #46466E", +"H c #2C2C65", +"J c #272756", +"K c #30306C", +"L c #40407F", +"P c #292944", +"I c #212150", +"U c #2A2A3B", +"Y c #202045", +"T c #323271", +"R c #2D2D62", +"E c #40406E", +"W c #292933", +"Q c #21213F", +"! c #1D1D3B", +"~ c #2A2A55", +"^ c #22224D", +"/ c #424273", +"( c #232344", +") c #262654", +"_ c #1C1C33", +"` c #1F1F2C", +"' c #242452", +"] c #1D1D41", +"[ c #353573", +"{ c #262657", +"} c None", +/* pixels */ +"}}}}}}}}}}}}uuuuuuu}}}}}}}}}}}", +"}}}}}}}}}BB999B999919u}}}}}}}}", +"}}}}}}}}BBw%GGGGGGGG9w1}}}}}}}", +"}}}}}}w1lwE1GElEGGGl%%%1o}}}}}", +"}}}}}w%ddlll/jArj%E6+ldwww}}}}", +"}}}}wwodd6Avvr+rA&+A66ldooo}}}", +"}}}}oob68A6yNjrgrAjNRbfhd>bb6yD+v&/Drgv=yvie}", +"}}_QY$.)'2{<{'pS0)$>!5n}}}", +"}}}}@,,YX''q'.'0S^Ia^-QVQ_`}}}", +"}}}}}CWQ>P^'X.^SJ..0X(5Qn`}}}}", +"}}}}}}@nCP-P03^0^3P-Y>>n@}}}}}", +"}}}}}}}}@nQVPVV(3PV>Q>C}}}}}}}", +"}}}}}}}}}@nUU>>UCUVCC@}}}}}}}}", +"}}}}}}}}}}}}WWCCWWC}}}}}}}}}}}", +"}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}" +}; diff --git a/hacks/images/bubbles/glass7.xpm b/hacks/images/bubbles/glass7.xpm new file mode 100644 index 00000000..f9c3178d --- /dev/null +++ b/hacks/images/bubbles/glass7.xpm @@ -0,0 +1,133 @@ +/* XPM */ +static char *glass7[] = { +/* width height ncolors chars_per_pixel */ +"36 36 90 1", +/* colors */ +" c #000000", +". c #27274E", +"X c #2F2F6D", +"o c #4A4A6D", +"O c #2E2E62", +"+ c #41416E", +"@ c #3C3C73", +"# c #2A2A5E", +"$ c #313172", +"% c #404066", +"& c #28285F", +"* c #353579", +"= c #414188", +"- c #28284B", +"; c #2E2E68", +": c #2B2B47", +"> c #2C2C3E", +", c #484860", +"< c #29295C", +"1 c #27275A", +"2 c #282851", +"3 c #3C3C54", +"4 c #333355", +"5 c #1F1F3E", +"6 c #48487A", +"7 c #2D2D66", +"8 c #11111C", +"9 c #262655", +"0 c #282843", +"q c #333372", +"w c #2F2F99", +"e c #212149", +"r c #1F1F47", +"t c #1A1A38", +"y c #34346C", +"u c #303068", +"i c #242445", +"p c #2C2C64", +"a c #2D2D5B", +"s c #292957", +"d c #272755", +"f c #26264A", +"g c #333364", +"h c #17172E", +"j c #242448", +"k c #B3B3D1", +"l c #282838", +"z c #2D2D5E", +"x c #161623", +"c c #1C1C40", +"v c #252556", +"b c #24244B", +"n c #1A1A2A", +"m c #252559", +"M c #58588B", +"N c #363663", +"B c #22224C", +"V c #2B2B62", +"C c #33336D", +"Z c #2E2E72", +"A c #242451", +"S c #333384", +"D c #242454", +"F c #2B2B68", +"G c #2D2D6D", +"H c #222244", +"J c #3636B1", +"K c #383874", +"L c #1B1B33", +"P c #2A2A66", +"I c #23233E", +"U c #1D1D38", +"Y c #292933", +"T c #3A3A68", +"R c #262651", +"E c #313169", +"W c #4F4F62", +"Q c #22224D", +"! c #28283F", +"~ c #292961", +"^ c #252532", +"/ c #2D2D51", +"( c #1F1F2C", +") c #222250", +"_ c #484868", +"` c #3D3D7B", +"' c #1F1F43", +"] c #20203A", +"[ c #353573", +"{ c None", +/* pixels */ +"{{{{{{{{{{{{{{{{WWWWW{{{{{{{{{{{{{{{", +"{{{{{{{{{{{{WWW_WW_W_W,WW{{{{{{{{{{{", +"{{{{{{{{{{_Wo_o_oo_o+__o__W{{{{{{{{{", +"{{{{{{{{{,,__%+ooo++++o++_,3{{{{{{{{", +"{{{{{{{3,3%T+%+%MT%+6+++%4T333{{{{{{", +"{{{{{{333TNNTT+yM@M6+T@N@TN3333{{{{{", +"{{{{{333T3NgTgg`M6M`[yyTNgN4O433{{{{", +"{{{{{>:/aNagu7gKMM``ETENXaOaN4/:{{{{", +"{{{{>f//OdaEOEOX6TMMC`y7y;OOaaO0>{{{", +"{{{Y:/jg4zau7Eu`kMXKM[@EyEE7sa20/^{{", +"{{{>I/bazOyO7[$Z[M[k6$MqqyEOu/f:-I{{", +"{{n:5'BaQ7uy;F*M*S$*kK*`pX7gEaj/:U^{", +"{{^hjs2dsuFC$X~SXSSS=[$[V7EOgdd.5L!{", +"{{x]R2azpy[X7[[$*S=J*`*$VXKus~gH.Lh{", +"{{L0.OOj!Hb0:e:500l>^{{{{{{{{", +"{{{{{{{{{{>IlI:!!i:00I0^llY{{{{{{{{{", +"{{{{{{{{{{{{Y>lll>Y!l>^YY{{{{{{{{{{{", +"{{{{{{{{{{{{{{{{^Y^>Y{{{{{{{{{{{{{{{", +"{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{" +}; diff --git a/hacks/images/bubbles/glass8.xpm b/hacks/images/bubbles/glass8.xpm new file mode 100644 index 00000000..913d248e --- /dev/null +++ b/hacks/images/bubbles/glass8.xpm @@ -0,0 +1,140 @@ +/* XPM */ +static char *glass8[] = { +/* width height ncolors chars_per_pixel */ +"44 44 89 1", +/* colors */ +" c #000000", +". c #25254C", +"X c #323266", +"o c #212148", +"O c #2E2E62", +"+ c #3A3A71", +"@ c #23234D", +"# c #242444", +"$ c #2C2C63", +"% c #2A2A61", +"& c #404066", +"* c #212137", +"= c #26265D", +"- c #1B1B31", +"; c #1E1E2A", +": c #242447", +"> c #181824", +", c #191932", +"< c #252558", +"1 c #404083", +"2 c #464675", +"3 c #363679", +"4 c #1F1F3E", +"5 c #343463", +"6 c #2F2F68", +"7 c #45456D", +"8 c #2D2D66", +"9 c #30305F", +"0 c #3535B0", +"q c #31316D", +"w c #4C4C6D", +"e c #2A2A45", +"r c #2C2C72", +"t c #222251", +"y c #22223D", +"u c #28285A", +"i c #212132", +"p c #333372", +"a c #2F2F99", +"s c #1A1A38", +"d c #21214C", +"f c #292957", +"g c #2D2D5E", +"h c #343472", +"j c #2A2A68", +"k c #27275B", +"l c #35356C", +"z c #2E2E5B", +"x c #323276", +"c c #262653", +"v c #242451", +"b c #31316B", +"n c #4F4F64", +"m c #292938", +"M c #13131F", +"N c #242454", +"B c #1F1F45", +"V c #22223E", +"C c #4C4C85", +"Z c #2A2A5D", +"A c #A9A9BF", +"S c #21214A", +"D c #38385D", +"F c #292941", +"G c #17172C", +"H c #272756", +"J c #2A2A4F", +"K c #212150", +"L c #242449", +"P c #2A2A3B", +"I c #353553", +"U c #2A2A52", +"Y c #3E3E55", +"T c #2E2E6D", +"R c #40406E", +"E c #292933", +"W c #464660", +"Q c #1D1D3B", +"! c #3A3A68", +"~ c #313169", +"^ c #2D2D65", +"/ c #3D3D78", +"( c #2B2B63", +") c #27274B", +"_ c #2D2D68", +"` c #212145", +"' c #1D1D41", +"] c #353573", +"[ c None", +/* pixels */ +"[[[[[[[[[[[[[[[[[[[[[[n[[[[[[[[[[[[[[[[[[[[[", +"[[[[[[[[[[[[[[[[nnWnwnnnwnnnn[[[[[[[[[[[[[[[", +"[[[[[[[[[[[[[[Wnwww7nwwwwww77nw[[[[[[[[[[[[[", +"[[[[[[[[[[[[Wn7n777ww77ww777wwWWW[[[[[[[[[[[", +"[[[[[[[[[[WW&7&w&77777R7777777&&&YW[[[[[[[[[", +"[[[[[[[[[YWY!Y!7&RRRR&&7!72R&R!&!YWY[[[[[[[[", +"[[[[[[[[Y&I!Y!&!!!+2C7R2AR+l!+!&!YYYY[[[[[[[", +"[[[[[[[IYY!!9!!!!+/AAA/C8+++XX!X5Y&DYI[[[[[[", +"[[[[[[PDY99999!!!X]AC/C++AlllblX959DDJI[[[[[", +"[[[[[IIIJz95z52^65lCCAqC+lClX8999zzDJ9eP[[[[", +"[[[[[eFJezgc9X9b~$q+/2CCA+1l6lO669f9zzFF[[[[", +"[[[[Ee)#fz995b]6+O]ACC6hCCq+qO6b+6U9UJ4)I[[[", +"[[[[IFJUU9z9O+~^]3qhj3qAA1T26p6b6ggzUJV)F[[[", +"[[[>JLU)H9%Hz66qqpx31x]CCCp1+88lq9f9c:U:e;[[", +"[[[*4y#BfzK66l~T_313x0xx3Cp33T$q%96OUH)UV*[[", +"[[>-Q.fV@^Zlqq]_T%xxxx333Cppp_q6669f9ZU#,-;[", +"[[M-ecUfz^Ol]qp_hppp33C1033xx(~6]~c%cfoc-M>[", +"[[>*:.fUH=$6bq]+]aTp01xr003q]q%ql^9^zHB:`Q*[", +"[[*GV:gf6=k6=%6]Tp31a0xxx0333]=p666ZHX')GG-[", +"[[>G'4UUX[", +"[M>*oBfKZ^Z~q[", +"[[>-):.c%cZ<^=T__x1aTx10xpjT8qqq[", +"[[M4##)vfK%u<$8q8jp1xxrqx_xp_8==O$=XKH.c-,>[", +"[[>-V`B@cNtH@>so.Uz`glZu==q]%q]C3q%ATq($^Z^%cHco'`-G>[", +"[[[M,s4`H'HKt=kO%+q^x6qA(j8==%6vu<@''Bys,>[[", +"[[[>G-s**`@ccNu%k~<6+(68qZ=b^%=tKufosB*Q;>[[", +"[[[[>-i'VVKv@d%%%uv=<6qZkk%Zub< c #343463", +", c #2F2F68", +"< c #30305F", +"1 c #22223A", +"2 c #262655", +"3 c #31316D", +"4 c #2A2A45", +"5 c #3E3E73", +"6 c #28285A", +"7 c #2B2B53", +"8 c #333372", +"9 c #27274F", +"0 c #1F1F47", +"q c #424266", +"w c #2F2FB0", +"e c #34346C", +"r c #32326A", +"t c #303068", +"y c #242445", +"u c #2D2D5B", +"i c #292957", +"p c #232351", +"a c #191930", +"s c #26264A", +"d c #393956", +"f c #242448", +"g c #B3B3D1", +"h c #202044", +"j c #2D2D5E", +"k c #3A3A78", +"l c #1E1E42", +"z c #30306E", +"x c #24244B", +"c c #27275B", +"v c #1B1B38", +"b c #35356C", +"n c #58588B", +"m c #2D2D64", +"M c #292960", +"N c #242451", +"B c #282841", +"V c #292938", +"C c #38386B", +"Z c #414156", +"A c #242454", +"S c #272739", +"D c #4C4C85", +"F c #23234C", +"G c #21214A", +"H c #22222D", +"J c #313174", +"K c #505064", +"L c #17172C", +"P c #222244", +"I c #3636B1", +"U c #383874", +"Y c #1B1B33", +"T c #212150", +"R c #353553", +"E c #2A2A66", +"W c #23233E", +"Q c #323271", +"! c #464674", +"~ c #2E2E6D", +"^ c #292933", +"/ c #1D1D3B", +"( c #22224D", +") c #2B2B63", +"_ c #343479", +"` c #1D1D2A", +"' c #353573", +"] c #3B3B65", +"[ c #262657", +"{ c None", +/* pixels */ +"{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{", +"{{{{{{{{{{{{{{{{{{{&KKKKKKKKKKKK{{{{{{{{{{{{{{{{{{", +"{{{{{{{{{{{{{{{{K&K:K&::KKK:::K&&KK{{{{{{{{{{{{{{{", +"{{{{{{{{{{{{{{&Z&:K:::::::::::K::::&K{{{{{{{{{{{{{", +"{{{{{{{{{{{{Z&&&:qq:!!:!.!:!:q!]:::Z]Z&{{{{{{{{{{{", +"{{{{{{{{{{{ZZ&Z:q:]!!.q.n..!.C..!:]qqqZ&{{{{{{{{{{", +"{{{{{{{{{{ZZdd]]].q.!]n.C..5!...].q]]]ZZZ{{{{{{{{{", +"{{{{{{{{{RZRd]Z]]]]C.Cn5!.5g.CC]b5C]]>C>]>C5C>begDDnDknC5UCrt>]]D@rrrkgnnD55r5r>CU>><7<mbr3bkn55QDg83brXe<3r><7<<,uutbm>r3-nnDQknnkekr3,emb6u>UUrQEQz'J_wkn_IJk8%J)e,btbi[iuF9vaL`{", +"{{#YPWxf9i6Xrbb3'3'__J'*__*+w''Qb%m3'eX6)=jxhsf#`{", +"{{##WPh>uiMXr@MmU'U+JEJw__++w-k_'z%M33m6jsff#o#{", +"{{YYaol7i6NctXQ%3QQ~~~**JM~+IIJz__zM3Uc>i22fhoY;a{", +"{{aWfo(9Tirm@rmcQkQM~JI+IJI**w_*_EMM),ct6juFPPY##{", +"{{LYaaFG0jFTr=mM3_E~z+~+E_I*+EJ_zz@M,m3M=(N9GhW#Y{", +"{{##LhPfFGpcp=2m'D8%%Q_-IQ~z!Qkz3mmcXc)=i06GFoaY#{", +"{{##aaxh02A0ATccmm3%%'8J--'_)+3M%)@t)6jp2x2hhho`#{", +"{{###Ph0G22Nm2AAM3,_m!DJnn3g3~Qe)M@X3XXN9f(hxW;##{", +"{{{#Lvh9ijhirrM[=c,',m3%kD-@J*'3))m6cXiNN2flovaa{{", +"{{{#LahPh20i(6TccXMz@@nn@3DbmD'2MMt2Acp2ovhB;a#`{{", +"{{{`#`v/;;G02=Fp=X23=n@nmXMkMUMrXMc6TA[2(vh;1Y##{{", +"{{{{`LL;oyo0X9FT)X==AD=C3'mMce6XX3[pN2jNPG(v`Y`{{{", +"{{{{H`YWvoif0=pc66A=[tcAXMA2cMMANAc2cpNolG2vo`H{{{", +"{{{{{HaY;/ohhiGNN6=mA=2pc[cC222[N(f(pi0hFBoY;;{{{{", +"{{{{{#`YaWhofp((9(i[pA6A27[=6X6ip(9N=hfPov/aY#{{{{", +"{{{{{{#HHvoofPhF[9pFNF6[p[62NN[9N9xfohWo;voHH{{{{{", +"{{{{{{{^aS;/hGhNh[22NN9N99NAFpTN(x(f0PVSW1;H{{{{{{", +"{{{{{{{{^HvYWho4GfN(2(9(N(p(4xFFsxPGhW1;;`^{{{{{{{", +"{{{{{{{{{La1PBB$hfGxs9FFxNF(9ffFPfPfoWWS^`{{{{{{{{", +"{{{{{{{{{{HVVBWyBsssFs4fsfFf44yfsF/y1BSSH{{{{{{{{{", +"{{{{{{{{{{{HV1S;Bf4o4yGh944x(yyWWo$WS1^S{{{{{{{{{{", +"{{{{{{{{{{{{HS`S$W4B44B44y44BBBWSW$WVH^{{{{{{{{{{{", +"{{{{{{{{{{{{{{VVV1WB$4BB4$BWBWVSVSB1H{{{{{{{{{{{{{", +"{{{{{{{{{{{{{{{{$^SVVWS$VVBB$$SS^^V{{{{{{{{{{{{{{{", +"{{{{{{{{{{{{{{{{{{{^^$VVB^$VVVV^{{{{{{{{{{{{{{{{{{", +"{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{", +"{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{" +}; diff --git a/hacks/images/bubbles/jade.pov b/hacks/images/bubbles/jade.pov new file mode 100644 index 00000000..7c1cb023 --- /dev/null +++ b/hacks/images/bubbles/jade.pov @@ -0,0 +1,24 @@ +#include "colors.inc" +#include "shapes.inc" +#include "textures.inc" + +/* The following make the field of view as wide as it is high + * Thus, you should have the -W and -H command line options + * equal to each other. */ +camera { + location <5.8, 0, 0> + up <0, 1, 0> + right <1, 0, 0> + look_at <0, 0, 0> +} + +sphere { + <0,0,0>, 2.5 + texture { Jade + scale <0.7, 0.7, 0.7> + rotate y*clock } + finish { phong 0.4 } +} + +light_source {<6, 1, 0> color White} +light_source {<6.1, 1, 0> color White} diff --git a/hacks/images/bubbles/jade1.xpm b/hacks/images/bubbles/jade1.xpm new file mode 100644 index 00000000..49bac3bf --- /dev/null +++ b/hacks/images/bubbles/jade1.xpm @@ -0,0 +1,76 @@ +/* XPM */ +static char *jade1[] = { +/* width height ncolors chars_per_pixel */ +"10 10 59 1", +/* colors */ +" c #000000", +". c #69E169", +"X c #35CB35", +"o c #149914", +"O c #179317", +"+ c #158B15", +"@ c #148914", +"# c #148514", +"$ c #0F890F", +"% c #0D830D", +"& c #0F730F", +"* c #0F6F0F", +"= c #0E6B0E", +"- c #077307", +"; c #0E630E", +": c #0B630B", +"> c #026502", +", c #046104", +"< c #0A550A", +"1 c #0B530B", +"2 c #065306", +"3 c #054F05", +"4 c #074B07", +"5 c #064706", +"6 c #003700", +"7 c #042B04", +"8 c #011901", +"9 c #21B621", +"0 c #1AAC1A", +"q c #18A818", +"w c #17A217", +"e c #189E18", +"r c #127C12", +"t c #107C10", +"y c #0F7A0F", +"u c #0B800B", +"i c #0E720E", +"p c #0A760A", +"a c #106A10", +"s c #0F6A0F", +"d c #0A6E0A", +"f c #0B620B", +"g c #0D580D", +"h c #076007", +"j c #045E04", +"k c #015E01", +"l c #015201", +"z c #034803", +"x c #044604", +"c c #083E08", +"v c #014601", +"b c #044004", +"n c #063606", +"m c #052E05", +"M c #013401", +"N c #042404", +"B c #002600", +"V c #022002", +"C c None", +/* pixels */ +"CCC4=#*4CC", +"CCf#eopjsC", +"Cm@$uu>khg", +"C5yw-.90:6", +"CaO,iXqx+5", +"CMrtz3%l&1", +"CV;*td&v6n", +"CCcbx2<;8C", +"CCC7BcmNCC", +"CCCCCCCCCC" +}; diff --git a/hacks/images/bubbles/jade10.xpm b/hacks/images/bubbles/jade10.xpm new file mode 100644 index 00000000..89fbd028 --- /dev/null +++ b/hacks/images/bubbles/jade10.xpm @@ -0,0 +1,158 @@ +/* XPM */ +static char *jade10[] = { +/* width height ncolors chars_per_pixel */ +"60 60 91 1", +/* colors */ +" c #000000", +". c #22B922", +"X c #1CB11C", +"o c #1AA71A", +"O c #169F16", +"+ c #159715", +"@ c #179317", +"# c #149114", +"$ c #108B10", +"% c #108710", +"& c #138113", +"* c #108110", +"= c #127D12", +"- c #137513", +"; c #0F7B0F", +": c #0C790C", +"> c #0F6F0F", +", c #0E690E", +"< c #0A6F0A", +"1 c #087108", +"2 c #0F650F", +"3 c #0E630E", +"4 c #0B670B", +"5 c #0B610B", +"6 c #086508", +"7 c #0D5B0D", +"8 c #0B5D0B", +"9 c #085F08", +"0 c #095909", +"q c #075B07", +"w c #0A550A", +"e c #025F02", +"r c #055505", +"t c #0A4B0A", +"y c #094709", +"u c #074907", +"i c #034F03", +"p c #084508", +"a c #074107", +"s c #014901", +"d c #024302", +"f c #063B06", +"g c #013F01", +"h c #053705", +"j c #053305", +"k c #013901", +"l c #013301", +"z c #022D02", +"x c #022902", +"c c #032703", +"v c #022102", +"b c #021B02", +"n c #011701", +"m c #001100", +"M c #000B00", +"N c #1FA81F", +"B c #19AA19", +"V c #18A418", +"C c #189A18", +"Z c #129412", +"A c #148A14", +"S c #148614", +"D c #0C820C", +"F c #117811", +"G c #0B7C0B", +"H c #117211", +"J c #0E740E", +"K c #0E720E", +"L c #0A760A", +"P c #0E6C0E", +"I c #0F6A0F", +"U c #086A08", +"Y c #046A04", +"T c #0D580D", +"R c #036403", +"E c #0A520A", +"W c #0B4E0B", +"Q c #025A02", +"! c #065206", +"~ c #084E08", +"^ c #015401", +"/ c #034C03", +"( c #083E08", +") c #024602", +"_ c #044004", +"` c #053005", +"' c #042404", +"] c #002400", +"[ c #011E01", +"{ c #9AE59A", +"} c None", +/* pixels */ +"}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}", +"}}}}}}}}}}}}}}}}}}}}}}}}xtzWtfEhlyx]c}}}}}}}}}}}}}}}}}}}}}}}", +"}}}}}}}}}}}}}}}}}}}}}`hfa7llzwgudtu_y7ah}}}}}}}}}}}}}}}}}}}}", +"}}}}}}}}}}}}}}}}}}jxl_I3II>FF!l5P>g!u7Taalv}}}}}}}}}}}}}}}}}", +"}}}}}}}}}}}}}}}}jlEu3lgdF,Hqq)_~))/&5w!Hklftj}}}}}}}}}}}}}}}", +"}}}}}}}}}}}}}}}(T7u/Pg2/PS=;4sSli=)q>r)0_gu~lh}}}}}}}}}}}}}}", +"}}}}}}}}}}}}}jfuugw8qq&4J;AJ>usius9ri44)//!PIwyz}}}}}}}}}}}}", +"}}}}}}}}}}}}xz77g555qF;SAAC#AK^L9#PJqqSl22a_ax}}}}}}}}}}", +"}}}}}}}}}}ff~0-_FS;@A*C*:CV%A4LL5KSJ:&6SOoA1OBL#JUegARLAAkkyx}}}}}}}}", +"}}}}}}}}xyEI5~&dk``}}}}}}", +"}}}}}}}xk705-&F0eH!57pc}}}}", +"}}}}'l`Ew!/rA9R^k<$BLD+VDJr+iGDB.X%RRe+r*iegS#@S9HrFI3Thb}}}", +"}}}}`l7d)>3s=6U&e$oDJLDXGYBO$B.X.Z+or.4qi@r<%L+%)R$BqZ....{{{NCJAVBBLeDLL###*r&F==5wEa]c}", +"}}vxawI~5!qs@J^6^RRYZXVGKV.NAC..AACZB%GBL;)k/KS=K*<^gADCOD:+BVXYq&G+DYRYZXBAOGo&i^@SFJF!0wlhcn}", +"}}n`zT~l855FJ@Sr^,=QGO$QLXX$1RYVXODQQCLV$%L^^56ASq&,323ly([}", +"}}mvzW_w3H8P=&6ee~^Uo%GeQGDXRRLOBVYq$L)uIklh`][b}}}", +"}}}}M[vp]kl_3H_5F&>AK4rr;<*AACi0-Hkztkyvh'M}}}", +"}}}}}'zhzlluTul!HF4&Jq/_qH4rs~q<=/FP>/&qPS4J=FF4q5iKS5HI!>8,~I3wlzf[vn}}}}}", +"}}}}}}}'cjyzh7EwuggHI,45=F>54F&44)i4JF7!54PI7IwTWzhxvn}}}}}}", +"}}}}}}}Mcb`(jfT7wdI72w,0I40,&/5i,400>5~-2PwEw~pytph[vM}}}}}}", +"}}}}}}}}Mb'j(hWT7E_klu7g)Ig/Pg!00/5iw!!25w3~TpElncvvn}}}}}}}", +"}}}}}}}}}MbnchWEaw7T~_pEu0ddppt)d0!0HWIwT7apTtlxzccn}}}}}}}}", +"}}}}}}}}}}Mc``fyfllfkhkd2EE2ku2tuI7)ku2Eklfpp(zz`'n}}}}}}}}}", +"}}}}}}}}}}}Mbb[x(xytWk7l3EkawI3l~ukWw7Ttlfyy(cjj'm}}}}}}}}}}", +"}}}}}}}}}}}}Mbb`xzxahlfTp_(Ek_lk7Wa`Tplhhfa(c[''M}}}}}}}}}}}", +"}}}}}}}}}}}}}Mmn[cfjhthyaffh]kTWWWaah(xxxf(h[vbM}}}}}}}}}}}}", +"}}}}}}}}}}}}}}}mmvz`fhh]]`(ytt((xyc````(fz''bm}}}}}}}}}}}}}}", +"}}}}}}}}}}}}}}}}MMm'`j`xx`zhz]`zncbfc`x`cnbnM}}}}}}}}}}}}}}}", +"}}}}}}}}}}}}}}}}}}MMnnnmmc']]vn[bvbvc`vvmMM}}}}}}}}}}}}}}}}}", +"}}}}}}}}}}}}}}}}}}}}}Mmnnbnnnmnnvbv'vmmM}}}}}}}}}}}}}}}}}}}}", +"}}}}}}}}}}}}}}}}}}}}}}}}MMMmmnnmmmMMM}}}}}}}}}}}}}}}}}}}}}}}", +"}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}", +"}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}" +}; diff --git a/hacks/images/bubbles/jade11.xpm b/hacks/images/bubbles/jade11.xpm new file mode 100644 index 00000000..b9b53401 --- /dev/null +++ b/hacks/images/bubbles/jade11.xpm @@ -0,0 +1,171 @@ +/* XPM */ +static char *jade11[] = { +/* width height ncolors chars_per_pixel */ +"72 72 92 1", +/* colors */ +" c #000000", +". c #22B922", +"X c #1AA71A", +"o c #159F15", +"O c #199719", +"+ c #169916", +"@ c #159515", +"# c #159115", +"$ c #129512", +"% c #158715", +"& c #148314", +"* c #108910", +"= c #118111", +"- c #117D11", +"; c #107910", +": c #0A7B0A", +"> c #0E730E", +", c #0F6F0F", +"< c #0A770A", +"1 c #0E6B0E", +"2 c #0A710A", +"3 c #0E690E", +"4 c #0F650F", +"5 c #067106", +"6 c #0E630E", +"7 c #0B630B", +"8 c #0B610B", +"9 c #0D5B0D", +"0 c #0B5D0B", +"q c #085F08", +"w c #046104", +"e c #075B07", +"r c #0B530B", +"t c #025F02", +"y c #075507", +"u c #025B02", +"i c #035503", +"p c #054F05", +"a c #074707", +"s c #084508", +"d c #024D02", +"f c #074107", +"g c #034703", +"h c #014501", +"j c #014101", +"k c #053505", +"l c #023902", +"z c #042B04", +"x c #012F01", +"c c #022902", +"v c #022702", +"b c #022302", +"n c #011F01", +"m c #011901", +"M c #000D00", +"N c #1CB41C", +"B c #1FA61F", +"V c #19AA19", +"C c #148A14", +"Z c #108E10", +"A c #108610", +"S c #0C800C", +"D c #107610", +"F c #117211", +"G c #106A10", +"H c #0B6A0B", +"J c #0C660C", +"K c #076C07", +"L c #086608", +"P c #046804", +"I c #0A5A0A", +"U c #036403", +"Y c #0B560B", +"T c #0B4E0B", +"R c #085008", +"E c #025802", +"W c #084C08", +"Q c #074A07", +"! c #025202", +"~ c #014A01", +"^ c #083E08", +"/ c #044004", +"( c #063C06", +") c #063806", +"_ c #013E01", +"` c #053005", +"' c #013601", +"] c #033203", +"[ c #022C02", +"{ c #011401", +"} c #9AE59A", +"| c None", +/* pixels */ +"||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||", +"|||||||||||||||||||||||||||||||)^kfWfck(z)||||||||||||||||||||||||||||||", +"|||||||||||||||||||||||||||^sT`')sfY9a/rsrsWkk||||||||||||||||||||||||||", +"||||||||||||||||||||||||`x[]Q6rgG)a48,,4agY_v9rT`|||||||||||||||||||||||", +"||||||||||||||||||||||[(lQ9466FFF,IYjg,,F/l_c6(c'x[|||||||||||||||||||||", +"||||||||||||||||||||cWWa6vRphG39dJy;_lFpdy=,Q~Y/'4kTs|||||||||||||||||||", +"||||||||||||||||||bs96Wa8gxgp1%&-&7Fd'!~/%e>>re0fgar9kz|||||||||||||||||", +"|||||||||||||||||)rrgQ6Fe;dy7H-H>eC8g3epFJqDe7QIlQgGG9f`||||||||||||||||", +"|||||||||||||||cfTl9v0I87e!eHC#AA>,,w!I/!C'Ce>C>&==F,G9fck||||||||||||||", +"||||||||||||||z[r/GRe7ye-@@+C=@A@<--J0!ww,E-p=!>D8'9yh_Wrbk|||||||||||||", +"|||||||||||||kW'sG3,7J-@2>C=P2@C=P>CwPh/@E22+l81!i/&[r__T/zv||||||||||||", +"||||||||||||)W_YrF/>=>-@C=C@2<++#PJ=<EPUP!Ed08Qiqhhhd/9l)c|||||||||||", +"|||||||||||^f'4r6Y&1%@-C=22o@X*:@XCte#e5E7E2PAAA2-8!8!/j_l9rT^||||||||||", +"||||||||||zsfGYe9&7!~';=QPSXV#-dd22=HPVoNU8:@Z#V@X2E/'dxyeF,a^c)||||||||", +"||||||||cs'94Jd8q~IE;#X+5+KS:SFiC3jFG4scv|||||||", +"|||||||zvf9IFp0q2-!w#o+CUANNo*PXV5:@;=ie-D-FyG9rsn|||||", +"||||||)(rY87JdJC>w>w+KZoo+Vo.Sd;oJoU@SoNo=d#y2++CC@yH,7Y99f^|||||", +"|||||nk)9ape,h&JL!w&<#Not5:ZV5dP5CNZoV..$SU2UChHN;tCe<==>=~3yF,G9W^b||||", +"|||||^f9gre33;C2LPH,SoNA5o@<:1uCJd~L>D17Gascn|||", +"||||zWf68gYⅆ_ePXZ#SoVVo+Ze5*SZN@%%X..oK@$VZeUt7''J;=-8aG9f`|||", +"|||bcxf4agY~l~q2we2Xo+oXNoS5@:oS.OOO.OO%=%5NNo;ag`zcm||", +"|||z(Q/R_Q0ayH=;ow#5SXN$NNN:e5S;O.}}}}.O%9S.VVS:X>EdXEE_ww~3D>JIW]W)cb||", +"|||`k9/W_fd,iC=@+2g;t5*5Z.VotPCB.}}}}}}.OB+o.NSPPoNt5P_1/I@!%eJIgs9szc||", +"||mnWW6R~h7h!;@+CCEup,EPSVNApA...}}}}}}}..BN.V*N:P55A&y78p99x(v{|", +"||nks9a9lj0h!e++@@@5Z.55$B.}}}}}}}}}OAoVZ5USS5*oZw++o@SUC$N.A,;F.BWPK$oV:ZN$Po;2qyH&D37gsrTkzb|", +"||m`[f'/Q,;d=%HHww2@!C:XX$oP8:+XooP.PAHC@H5ZV@VNo$A#~uL#CA=>H1eYR_ls`kb|", +"||{z)'fa_9ph8&&;H=;E@uUXXNZt:XV+VX<.0:Z5NUPS+VXNooZ2H7g!CC=>,,eI6alxkkm|", +"||Mzc`9QgY7h,%>CC;HE~AES@@XS+oNVXZNhA<$$ZPPoPVVVZ+AD%>qww1EwwX:oU+U:St=PP<$NNZPeS*E;=/ee%D-DF,96Q(xnb||", +"|||v^nff'/9F7-&%~%id1+!u,wXPElKwtE+EeUS@uJoS$Zwp22H_&W!=e&D;;7WWr9fv{n||", +"|||mk^Tf(sWFF7;-,,8Wl'g3w=+SP+hXwwu+tp:SEA#PC#P_g>lp_~~!H->3FQ')asTcnm||", +"|||Mbk)Wlv/6,eejRhWl'a!i=@oA<u<2!Lqd--~H,-1y,664TrxWzvM||", +"||||vz`TT'WgFee;aR''Fiii-o+##oCSXX+2XCyH>@7#I/%P2=JeiH%%;ggg464'(Wsbn|||", +"||||bz`'T]_'IG6jhh=,~J2q-++;wH2wZoXCC&-%78p(RTYYcx)n)zn|||", +"||||mmzkTxrfQFy_GR/8&~>-C=@A>222#o+o+w_h7I;A2J=CH!HJ,eyfId'fl_Q9c^bzM|||", +"|||||mbkssx_969~Gjdd!hJ-D&@+A=;@@+o+;2=rpq2LJ2#LeCdR!lrpFe4''c9lk`nm||||", +"|||||{mn^xz_6/GhGYe3,8,%>LHH;C;A+@++;22iiw!3r!=-H!;_'hpFF3(lxl)sn)Mm||||", +"||||||nb^snlx_QrlRI;-D&&17e_3wH;-=@C2CC=JL!1,eCC&8Fad08,,rg_9'ck`zm|||||", +"||||||Mvk)))''r4Wxg3FF7&,e~,hiq2qH&=HL>>qJ~F/yD%-y,p7F4099R]xWxs)nm|||||", +"|||||||bbz^(cr9Y69Yrg3F;Jed/heH%>DC@;eq>>ee!7>%7jQp-3rY6G4Ylz^`z{n||||||", +"|||||||{mb`)ksQrWRl9QGI-,>y;he1&>J-;D-H7ee!,->elGpF7I4W996r[z`cm{M||||||", +"||||||||mvkkWx[99QR_/v~,G8I07FDDH7>-%1,e%p7,>JadyFFFFG4499fczknbm|||||||", +"|||||||||bzb^^c)996YRrWFF,F,,-,8,7ey7dy,ye87,pdF3G6IY49aQsf(^nb{||||||||", +"|||||||||MbMz^cbf99r9l('/_rWdI3yphl-833738y0Ifp488GYlYQTW))kbzmM||||||||", +"||||||||||Mnbc^cfrrsrYr/G_fs'0IWg,'jdpgFy7g40(F99rR6R9fTkvvmnb{|||||||||", +"|||||||||||M{nc`kWTfsr9rr'R((90g_/f_(__rIR8G6YIY99_WfTT`cz``vm||||||||||", +"||||||||||||Mmnk^)sf(x'/lW'/Q4rG(g_Q4x/r4Ygl/94RlxklTs^bzkzb{|||||||||||", +"|||||||||||||{{zmzzc)cx'nlfx_4Wl)/9GG/lGRlbQ999ss'fWf^nkkzmM||||||||||||", +"||||||||||||||Mbmzb`cmxx['sl9rs_c_TrfWf9r_9Q_sfWTTss^zvnbnM|||||||||||||", +"|||||||||||||||Mmmzzbks(Wf^Wr'xWTxc`Ts99Tfx)x[xcck^^znzbmM||||||||||||||", +"|||||||||||||||||M{mmb)k)fkk(TTf)c]Ws(sss(fcnvv`kk^bn{n{||||||||||||||||", +"||||||||||||||||||MM{bkz`^`czcc(ss(s((xkv)`cvz)^)v{mm{M|||||||||||||||||", +"||||||||||||||||||||MMmb`kzzcz`zkkvc```nmb)c`b`zz{{{M|||||||||||||||||||", +"||||||||||||||||||||||Mmnmm{mzzvzcznbn)`bnvk`zmmMMM|||||||||||||||||||||", +"||||||||||||||||||||||||MMmm{b{mmzmb{Mmm{mnvb{MMM|||||||||||||||||||||||", +"|||||||||||||||||||||||||||MM{mMmm{mm{mmmm{{MM||||||||||||||||||||||||||", +"|||||||||||||||||||||||||||||||MMMMMMMMMMM||||||||||||||||||||||||||||||", +"||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||", +"||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||" +}; diff --git a/hacks/images/bubbles/jade2.xpm b/hacks/images/bubbles/jade2.xpm new file mode 100644 index 00000000..53b4d19b --- /dev/null +++ b/hacks/images/bubbles/jade2.xpm @@ -0,0 +1,96 @@ +/* XPM */ +static char *jade2[] = { +/* width height ncolors chars_per_pixel */ +"12 12 77 1", +/* colors */ +" c #000000", +". c #35CB35", +"X c #1AA71A", +"o c #158B15", +"O c #148914", +"+ c #158715", +"@ c #137513", +"# c #107710", +"$ c #0F6D0F", +"% c #0E6B0E", +"& c #0E690E", +"* c #0F650F", +"= c #0E630E", +"- c #0A5F0A", +"; c #036703", +": c #0B570B", +"> c #075D07", +", c #0A550A", +"< c #0C4F0C", +"1 c #0A510A", +"2 c #045704", +"3 c #065106", +"4 c #074D07", +"5 c #074B07", +"6 c #094709", +"7 c #063B06", +"8 c #073907", +"9 c #033D03", +"0 c #033B03", +"q c #053505", +"w c #003D00", +"e c #053105", +"r c #003700", +"t c #042904", +"y c #012301", +"u c #011501", +"i c #1CB41C", +"p c #17A217", +"a c #189E18", +"s c #189A18", +"d c #119011", +"f c #128A12", +"g c #0F8C0F", +"h c #148214", +"j c #138013", +"k c #0F7A0F", +"l c #0B800B", +"z c #0A7A0A", +"x c #0A780A", +"c c #0A760A", +"v c #0B720B", +"b c #0F6A0F", +"n c #0A6A0A", +"m c #056C05", +"M c #056A05", +"N c #076407", +"B c #0D580D", +"V c #0A5C0A", +"C c #046404", +"Z c #075A07", +"A c #045E04", +"S c #055605", +"D c #035003", +"F c #015201", +"G c #B1FFB1", +"H c #034803", +"J c #044604", +"K c #074007", +"L c #083E08", +"P c #024402", +"I c #044004", +"U c #013A01", +"Y c #052E05", +"T c #042C04", +"R c #012A01", +"E c #000A00", +"W c None", +/* pixels */ +"WWWW=&9jrWWW", +"WW8IosxC-PRW", +"WW@FCp>Sx3$W", +"WeJ5;livmaZK", +"WI2HgfGsMw+B", +"W,ZNdp.dcsh:", +"W c #0E750E", +", c #0F730F", +"< c #0F6F0F", +"1 c #0F6D0F", +"2 c #0E6B0E", +"3 c #077307", +"4 c #0E630E", +"5 c #0B630B", +"6 c #0A5F0A", +"7 c #085B08", +"8 c #0A550A", +"9 c #0B530B", +"0 c #0C4F0C", +"q c #094F09", +"w c #045704", +"e c #0A4D0A", +"r c #065306", +"t c #0A4B0A", +"y c #065106", +"u c #015901", +"i c #054F05", +"p c #074B07", +"a c #084908", +"s c #084508", +"d c #064706", +"f c #074107", +"g c #073907", +"h c #033D03", +"j c #053505", +"k c #063306", +"l c #042B04", +"z c #042904", +"x c #011D01", +"c c #011901", +"v c #21B621", +"b c #1CB41C", +"n c #FFFFFF", +"m c #18A418", +"M c #189A18", +"N c #149C14", +"B c #149014", +"V c #0F8C0F", +"C c #128612", +"Z c #148214", +"A c #138013", +"S c #107C10", +"D c #0A760A", +"F c #0F6A0F", +"G c #0A6A0A", +"H c #0C660C", +"J c #0A660A", +"K c #0B620B", +"L c #0C600C", +"P c #056A05", +"I c #066806", +"U c #076407", +"Y c #0D580D", +"T c #076007", +"R c #046404", +"E c #0A5A0A", +"W c #095409", +"Q c #035003", +"! c #034C03", +"~ c #034803", +"^ c #044604", +"/ c #083E08", +"( c #024402", +") c #053805", +"_ c #023802", +"` c #012E01", +"' c #042604", +"] c #022802", +"[ c #042404", +"{ c #022002", +"} c #011E01", +"| c None", +/* pixels */ +"|||||qGT#yLg|", +"||xjhErHr48t'|", +"|||[])f9_et[||", +"|||||z'}kc||||", +"||||||||||||||" +}; diff --git a/hacks/images/bubbles/jade4.xpm b/hacks/images/bubbles/jade4.xpm new file mode 100644 index 00000000..3a7201c7 --- /dev/null +++ b/hacks/images/bubbles/jade4.xpm @@ -0,0 +1,116 @@ +/* XPM */ +static char *jade4[] = { +/* width height ncolors chars_per_pixel */ +"20 20 89 1", +/* colors */ +" c #000000", +". c #1CB11C", +"X c #1AA71A", +"o c #179B17", +"O c #179517", +"+ c #149914", +"@ c #158B15", +"# c #158715", +"$ c #138913", +"% c #148514", +"& c #108710", +"* c #127D12", +"= c #0D830D", +"- c #127912", +"; c #0F7B0F", +": c #107710", +"> c #0F730F", +", c #0E730E", +"< c #0F6F0F", +"1 c #0F650F", +"2 c #0E630E", +"3 c #056B05", +"4 c #086508", +"5 c #0D590D", +"6 c #046704", +"7 c #0B570B", +"8 c #085B08", +"9 c #026302", +"0 c #075907", +"q c #074B07", +"w c #094709", +"e c #084508", +"r c #064706", +"t c #014F01", +"y c #034903", +"u c #014B01", +"i c #024302", +"p c #073907", +"a c #B4F0B4", +"s c #023D02", +"d c #033903", +"f c #003700", +"g c #022B02", +"h c #042504", +"j c #011901", +"k c #001100", +"l c #010D01", +"z c #2CC42C", +"x c #21B621", +"c c #1CB41C", +"v c #22AA22", +"b c #1AAC1A", +"n c #18A818", +"m c #17A217", +"M c #189E18", +"N c #149014", +"B c #119011", +"V c #108210", +"C c #0B800B", +"Z c #0B7C0B", +"A c #117211", +"S c #0B720B", +"D c #0F6A0F", +"F c #087408", +"G c #0C6A0C", +"H c #0A6C0A", +"J c #067006", +"K c #0B620B", +"L c #0D5E0D", +"P c #076007", +"I c #0A540A", +"U c #025E02", +"Y c #055405", +"T c #084E08", +"R c #094A09", +"E c #055005", +"W c #015201", +"Q c #074207", +"! c #083E08", +"~ c #014601", +"^ c #063606", +"/ c #052E05", +"( c #013201", +") c #032803", +"_ c #002400", +"` c #022002", +"' c #011C01", +"] c #011601", +"[ c None", +/* pixels */ +"[[[[[[[/Q(sRw^[[[[[[", +"[[[[[!qiD;%*<8q^[[[[", +"[[[[pDH,FVo,P>#1Q[[[", +"[[[wKH%FM%+9FNU0Dp[[", +"[[!L(WmZ.J8mH3XEqL_[", +"[[/Y$W&=C+Cc9YUNP-5[", +"[`L2S6ox$cmxZJBMt-5j", +"[^r#;mmbFvz@xCbXKGf/", +"[w5~N3%B&zaz=6FZu,2p", +"[gDYO49c,vz@nbro@Arj", +"[_Ty*H@o+.V=3bZt%-Ih", +"['(A*W;6yUEJ=yWW>EI`", +"[kQf8-:NHOSOHH;42I)k", +"[[`d2K<4;@HP>#~0fd^[", +"[[l^5dy<84:0,A c #0E670E", +", c #0E630E", +"< c #056F05", +"1 c #056B05", +"2 c #0D5B0D", +"3 c #0A5F0A", +"4 c #046704", +"5 c #0A550A", +"6 c #0A530A", +"7 c #0A4D0A", +"8 c #0A4B0A", +"9 c #055105", +"0 c #015701", +"q c #074107", +"w c #014901", +"e c #014501", +"r c #073907", +"t c #014101", +"y c #033D03", +"u c #053705", +"i c #063306", +"p c #053105", +"a c #042904", +"s c #011501", +"d c #8DF08D", +"f c #1CB41C", +"g c #1AAC1A", +"h c #17A217", +"j c #189A18", +"k c #159C15", +"l c #199419", +"z c #159615", +"x c #148A14", +"c c #128A12", +"v c #148614", +"b c #108610", +"n c #0F760F", +"m c #0F720F", +"M c #0A6E0A", +"N c #0B680B", +"B c #0A660A", +"V c #0B620B", +"C c #0C600C", +"Z c #0D5E0D", +"A c #0D580D", +"S c #0A5C0A", +"D c #046404", +"F c #075E07", +"G c #046204", +"H c #0A580A", +"J c #075A07", +"K c #0B500B", +"L c #025C02", +"P c #045604", +"I c #074A07", +"U c #054C05", +"Y c #025002", +"T c #074607", +"R c #044604", +"E c #073C07", +"W c #044004", +"Q c #013C01", +"! c #033603", +"~ c #003800", +"^ c #052E05", +"/ c #042C04", +"( c #013001", +") c #022C02", +"_ c #012A01", +"` c #022602", +"' c #012201", +"] c #011E01", +"[ c #011A01", +"{ c #000E00", +"} c #000A00", +"| c None", +/* pixels */ +"|||||||||E^TA6Tu||||||||", +"|||||||8,9>Ny9+w~7||||||", +"|||||`!SVFonLW~n+$Zu||||", +"||||r5Wmxoj4&mD03Fe2_|||", +"|||aW>YM0j+#D&Q&XRvV_s||", +"|||q$FYjDzhGFgPo&b9Q*p||", +"||r5Nxn1kkUBofGb+Pjl*2E|", +"||pZRoIX4o%fff;c1-jLJSq|", +"|`qR!;;kfe3V9qCHIu'{||", +"||||}uT(yWKR>5R2y!Eis|||", +"|||||}/i88((KA()_Ea{||||", +"|||||||}^/pi^]r'as||||||", +"|||||||||{[s[[s}||||||||", +"||||||||||||||||||||||||" +}; diff --git a/hacks/images/bubbles/jade6.xpm b/hacks/images/bubbles/jade6.xpm new file mode 100644 index 00000000..02aefe94 --- /dev/null +++ b/hacks/images/bubbles/jade6.xpm @@ -0,0 +1,128 @@ +/* XPM */ +static char *jade6[] = { +/* width height ncolors chars_per_pixel */ +"30 30 91 1", +/* colors */ +" c #000000", +". c #73E573", +"X c #23BD23", +"o c #20A920", +"O c #17A317", +"+ c #1A991A", +"@ c #159B15", +"# c #159115", +"$ c #129512", +"% c #158B15", +"& c #138713", +"* c #108710", +"= c #117F11", +"- c #127912", +"; c #0E790E", +": c #0D730D", +"> c #0F6D0F", +", c #0E690E", +"< c #0F650F", +"1 c #086F08", +"2 c #0E630E", +"3 c #0B670B", +"4 c #0B610B", +"5 c #0A5F0A", +"6 c #0B5B0B", +"7 c #0B570B", +"8 c #085908", +"9 c #035703", +"0 c #055305", +"q c #094909", +"w c #074B07", +"e c #044F04", +"r c #024D02", +"t c #044904", +"y c #014301", +"u c #073907", +"i c #013F01", +"p c #063306", +"a c #013901", +"s c #042D04", +"d c #012701", +"f c #012101", +"g c #011D01", +"h c #011901", +"j c #011501", +"k c #001100", +"l c #010D01", +"z c #1CB21C", +"x c #19AA19", +"c c #189E18", +"v c #189A18", +"b c #159615", +"n c #119011", +"m c #148814", +"M c #108C10", +"N c #138213", +"B c #127C12", +"V c #0D840D", +"C c #107C10", +"Z c #0D7E0D", +"A c #117611", +"S c #0A7A0A", +"D c #107010", +"F c #106A10", +"G c #0C6E0C", +"H c #087408", +"J c #0A660A", +"K c #056C05", +"L c #0D5E0D", +"P c #066806", +"I c #076407", +"U c #0D580D", +"Y c #076007", +"T c #036403", +"R c #0A540A", +"E c #045C04", +"W c #094E09", +"Q c #015401", +"! c #044604", +"~ c #064206", +"^ c #073C07", +"/ c #053605", +"( c #013C01", +") c #013601", +"_ c #033203", +"` c #012E01", +"' c #022A02", +"] c #042604", +"[ c #042404", +"{ c #000A00", +"} c None", +/* pixels */ +"}}}}}}}}}}}}d`qR)''}}}}}}}}}}}", +"}}}}}}}}}p)FFD-`>iwU~f}}}}}}}}", +"}}}}}}}}Uw><,=J&ryDy(w)}}}}}}}", +"}}}}}}d6i48;m:#69)aYN80Rp}}}}}", +"}}}}}uWA-C%v;O%S5GP9592q}}", +"}}[sRrmTa*S@Z9eZXVTb=E&#Y9FUg}", +"}}u<0!%;KxTz@OOzX*xYKECTY84Ug}", +"}}/FRm:Q@nxMKKx%X1zH1nv)(A-W/}", +"}j`!er;PKOzxHAX..oXnxx&y4A,)^k", +"}[qL4rm#xJSxVX...%X$Z1Z,im4D^p", +"}gRWL0Y=HZ#zMo...+T@VnvEmmyFfs", +"}f~F48#QQTnO:X%X%+xSH!GI%N6!Us", +"}[^~,,NI#POH*@SzHz$@c#x=m,rWq[", +"}j`W65:&Q=SMHz1KzZ9SMHQI&N22qg", +"}lp)63B~rCc&t#OeVGVZTQwr:A!Rgj", +"}}f~/D0`~Qmcbvvv8;iQGr9Cy5L7W/f}}}", +"}}}}{[^WL~`L!(>065R042URhfj}}}", +"}}}}}{pu^_() c #0A710A", +", c #0F650F", +"< c #067106", +"1 c #0E630E", +"2 c #0A690A", +"3 c #086908", +"4 c #0B5F0B", +"5 c #0B5B0B", +"6 c #026302", +"7 c #0C4F0C", +"8 c #094D09", +"9 c #025502", +"0 c #004D00", +"q c #024302", +"w c #063706", +"e c #023502", +"r c #022D02", +"t c #042904", +"y c #012901", +"u c #022302", +"i c #011F01", +"p c #011901", +"a c #001100", +"s c #000B00", +"d c #4FD64F", +"f c #1CB41C", +"g c #1AAC1A", +"h c #18A618", +"j c #17A017", +"k c #189A18", +"l c #159615", +"z c #148A14", +"x c #108E10", +"c c #148414", +"v c #108810", +"b c #0D7E0D", +"n c #117611", +"m c #107210", +"M c #0A760A", +"N c #0E6A0E", +"B c #0E680E", +"V c #0A6E0A", +"C c #0B620B", +"Z c #046A04", +"A c #0D580D", +"S c #056405", +"D c #075E07", +"F c #0A560A", +"G c #075A07", +"H c #095409", +"J c #0A520A", +"K c #025E02", +"L c #055605", +"P c #065206", +"I c #015A01", +"U c #084808", +"Y c #035003", +"T c #054C05", +"R c #074607", +"E c #B1FFB1", +"W c #074207", +"Q c #034803", +"! c #083E08", +"~ c #024602", +"^ c #033E03", +"/ c #043C04", +"( c #023A02", +") c #053205", +"_ c #023602", +"` c #052E05", +"' c #013201", +"] c #011C01", +"[ c #011601", +"{ c None", +/* pixels */ +"{{{{{{{{{{{{{{{{!WWw`{{{{{{{{{{{{{{{", +"{{{{{{{{{{{{`rUJNR4;RFyJ){{{{{{{{{{{", +"{{{{{{{{{{y818qNTL^mT$UF_wR{{{{{{{{{", +"{{{{{{{{{JQ1GTC&-zQGmDDU(QNW{{{{{{{{", +"{{{{{{{`JNGL&@z@@&B9K9Y9neP^Jw{{{{{{", +"{{{{{{w^H^$&zzVk#2MKIS904L~qq/y{{{{{", +"{{{{{tWF4C0*TbgMS%gZX23v@DNzF88`{{{{", +"{{{{{A,1N0$#IZ<&*fVgf4l#l>q0LmRy{{{{", +"{{{{yAn5V9#lSjgj<2Dx+LfxMk*P0':,w{{{", +"{{{uR,P0*9Mq+ff6Z6XZ6%Xvh<@bGnmNJi{{", +"{{{w4P:cSKMXK=gTf$ZIZj90G51Wp{", +"{{tW4F0*Gh#+h+Gvx@z.+lhDKx2Lz*Q,,/U]{", +"{{[t7JTPN^c-z@->#kk^C*>%2V;L5e(Uyua{", +"{{{[!t1NNG;;-V**kl*>L9H$V*eYm!'wia{{", +"{{{a)weJ8QnC;0~DDcV-D0qn&:C,48'rw]{{", +"{{{{p)wU8(U5:P~N-&nVDY&GNn58AJ`y[{{{", +"{{{{{t!yA188mn;;;DCLP4:TN1FAUW!u{{{{", +"{{{{{su!WJJJNWe5QeTQPQ5m588Wwyi[{{{{", +"{{{{{{si!U/e/eTJ/(,q,Qq,/)7!`t[{{{{{", +"{{{{{{{s[uy'rRARy8WWJ4^W7R!tus{{{{{{", +"{{{{{{{{{a]www/7w'UURW]y)!]i{{{{{{{{", +"{{{{{{{{{{s]``y))y`)pw)`t[s{{{{{{{{{", +"{{{{{{{{{{{{s]a[p[ap[iuas{{{{{{{{{{{", +"{{{{{{{{{{{{{{{{sssss{{{{{{{{{{{{{{{", +"{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{" +}; diff --git a/hacks/images/bubbles/jade8.xpm b/hacks/images/bubbles/jade8.xpm new file mode 100644 index 00000000..22585981 --- /dev/null +++ b/hacks/images/bubbles/jade8.xpm @@ -0,0 +1,143 @@ +/* XPM */ +static char *jade8[] = { +/* width height ncolors chars_per_pixel */ +"44 44 92 1", +/* colors */ +" c #000000", +". c #35CB35", +"X c #19A719", +"o c #169B16", +"O c #159715", +"+ c #159115", +"@ c #129512", +"# c #158715", +"$ c #148514", +"% c #108B10", +"& c #127F12", +"* c #0F7B0F", +"= c #127312", +"- c #0F750F", +"; c #0C790C", +": c #0A770A", +"> c #0D6D0D", +", c #0C690C", +"< c #067106", +"1 c #0D650D", +"2 c #0E630E", +"3 c #0B630B", +"4 c #0C5F0C", +"5 c #0B5B0B", +"6 c #075D07", +"7 c #025F02", +"8 c #065706", +"9 c #025702", +"0 c #084D08", +"q c #035103", +"w c #064706", +"e c #074307", +"r c #034903", +"t c #014B01", +"y c #073F07", +"u c #063D06", +"i c #053105", +"p c #023502", +"a c #013301", +"s c #022D02", +"d c #022B02", +"f c #022702", +"g c #022302", +"h c #011F01", +"j c #8DF08D", +"k c #21AC21", +"l c #1CB41C", +"z c #1BAE1B", +"x c #18A418", +"c c #17A217", +"v c #199419", +"b c #148A14", +"n c #118E11", +"m c #148214", +"M c #108610", +"N c #0E820E", +"B c #127A12", +"V c #0D7E0D", +"C c #0C720C", +"Z c #0F6A0F", +"A c #076C07", +"S c #0A660A", +"D c #0A600A", +"F c #046804", +"G c #0D580D", +"H c #076007", +"J c #046404", +"K c #0A580A", +"L c #075A07", +"P c #095409", +"I c #0A520A", +"U c #035C03", +"Y c #0B4E0B", +"T c #065206", +"R c #064E06", +"E c #084808", +"W c #024602", +"Q c #034203", +"! c #063A06", +"~ c #014201", +"^ c #033E03", +"/ c #043804", +"( c #003E00", +") c #053405", +"_ c #013801", +"` c #052E05", +"' c #013001", +"] c #011C01", +"[ c #011801", +"{ c #011401", +"} c #000E00", +"| c None", +/* pixels */ +"||||||||||||||||||||||!|||||||||||||||||||||", +"||||||||||||||||id_^I2^I0K)yy|||||||||||||||", +"||||||||||||||)Q22Z>>T44=(0puas|||||||||||||", +"||||||||||||/IP0e=TZmDP5BrDr3ZQa)|||||||||||", +"||||||||||`YWLZrZ6**,53BPL3SmWEZ2Y[|||||||||", +"|||||||||sI2r33b$+b;;DQ1UWq&S-8WL0Ke||||||||", +"||||||||uw5T-m*Vb>V+C>FJrmVLQ8#WW((wd|||||||", +"|||||||y_PW$&bVC:O+:XN>WFWJCb*bqt4r_a)||||||", +"||||||y42RB3q9H9boN7CA%zRr>qVxnCczoV7FLT3;oO*H&42)|||", +"|||`!QT&#CS->o;J:zWoXOll@@HxS+,L4G`||", +"|||!GZW>8bo,:zn%l%Uoxllnx;;#...#=Xl%HF9O9QZT#=re!)|", +"||gE2(LW**oL1rWpy|", +"||!I20_wHNoCJ(UL#WT2'`|", +"||ye)5T#68,+:x~:XFzk.jjjvk:cB=T2E!|", +"|]`_003Wq1UHXFmUoc@(VXlvl;lL%ooxnnX;NCCm5P!Gh|", +"||`'eQDL&bN--9Oo%7XolFCn14C#DZ>ZYY`|", +"||hEIa4ZmBq69vHo+bUF7<7%n9FU$mT>&BK2efh|", +"||dfeyw=3Z'5aT$*XF(UWmPQSSbOCHHvoN&+WNFHOSmBD02E04')i||", +"|||ggY)^40wrr#&-+bmvoo;oZJSHbHt0q2=rZee))g||", +"||||gyhp_5d5B&&S9>H*MOCb*H>T#$q>T5Z0aaYf)|||", +"||||giepaI0(3>&DWt8-C&>S>HtP-&>T=LZK_h'){|||", +"|||||[)Y)IG_f(B-RWH$S#->3H6mD_T34045sfg[||||", +"|||||}`y'!54PP==BBB1>1Z83R1>~=Z2P2QY/!h{||||", +"||||||{h!sE52QEY0(Zrr'L1L5RLr2420EEsfg[|||||", +"|||||||}]`iYY5PQee=WWpdW502s2K5eII!d`h||||||", +"||||||||{`dyyppQaEII^P0sZ0)G4ad!eii`[|||||||", +"|||||||||[{dgEy/sGEYpE^_IQppuEYYy]g}||||||||", +"||||||||||}{ii)y!eEaiuYEEy/iyd)`]h}|||||||||", +"||||||||||||}f``)di`!d!d[fe`f`]]{|||||||||||", +"||||||||||||||{{[{ggfffh[[``]{}|||||||||||||", +"||||||||||||||||}}}{[][]hg]{}|||||||||||||||", +"||||||||||||||||||||||}|||||||||||||||||||||", +"||||||||||||||||||||||||||||||||||||||||||||" +}; diff --git a/hacks/images/bubbles/jade9.xpm b/hacks/images/bubbles/jade9.xpm new file mode 100644 index 00000000..6fde7487 --- /dev/null +++ b/hacks/images/bubbles/jade9.xpm @@ -0,0 +1,149 @@ +/* XPM */ +static char *jade9[] = { +/* width height ncolors chars_per_pixel */ +"50 50 92 1", +/* colors */ +" c #000000", +". c #22B922", +"X c #199919", +"o c #169916", +"O c #179317", +"+ c #129512", +"@ c #149114", +"# c #158715", +"$ c #108B10", +"% c #108710", +"& c #128312", +"* c #137D13", +"= c #117F11", +"- c #127912", +"; c #107B10", +": c #0D7F0D", +"> c #107710", +", c #0B7B0B", +"< c #0C770C", +"1 c #0F6F0F", +"2 c #0C690C", +"3 c #0D650D", +"4 c #0E630E", +"5 c #0B610B", +"6 c #096309", +"7 c #0B5B0B", +"8 c #085F08", +"9 c #075B07", +"0 c #025F02", +"q c #025B02", +"w c #065306", +"e c #064D06", +"r c #094709", +"t c #024D02", +"y c #074307", +"u c #014901", +"i c #014501", +"p c #063906", +"a c #013D01", +"s c #063306", +"d c #013901", +"f c #033503", +"g c #033103", +"h c #042B04", +"j c #022D02", +"k c #022902", +"l c #022502", +"z c #012301", +"x c #011F01", +"c c #011D01", +"v c #011901", +"b c #000D00", +"n c #4FD64F", +"m c #1CB41C", +"M c #1FA61F", +"N c #1AAC1A", +"B c #18A818", +"V c #16A016", +"C c #159615", +"Z c #148A14", +"A c #118E11", +"S c #0D840D", +"D c #117211", +"F c #0E740E", +"G c #0F6A0F", +"H c #0A720A", +"J c #0C6E0C", +"K c #0A6E0A", +"L c #0A6A0A", +"P c #0A660A", +"I c #056E05", +"U c #0D5E0D", +"Y c #046804", +"T c #0D580D", +"R c #036403", +"E c #0A580A", +"W c #085808", +"Q c #0A540A", +"! c #0B500B", +"~ c #084E08", +"^ c #035603", +"/ c #094A09", +"( c #035203", +") c #035003", +"_ c #054605", +"` c #B1FFB1", +"' c #073E07", +"] c #044004", +"[ c #014001", +"{ c #052E05", +"} c #011401", +"| c None", +/* pixels */ +"||||||||||||||||||||||||||||||||||||||||||||||||||", +"|||||||||||||||||||kzjsaTTg/rrp{||||||||||||||||||", +"||||||||||||||||kkf!44QQDw4D]~Qf/rh|||||||||||||||", +"||||||||||||||zT_E77wtitG1j5w*wg~!Upr|||||||||||||", +"||||||||||||{/Ue57_iG#1*Z#_-591iW[deU'p|||||||||||", +"|||||||||||hT]EW59-8FOoL]^*]^Z)F2G55D4rz||||||||||", +"||||||||||j~_u795&OO&OVHwG-R^o#Gt>PdW[G/s|||||||||", +"|||||||||'geDi>#F=;=K@@ReIHa^RLu5(u&i-]'aj||||||||", +"||||||||pfG4wP#ZZ>HBVZAVYWqY0BY:=>F^ewuar/c|||||||", +"|||||||'/U5i-G>#F7%BV@iN,oV*6^u%NH0Y.,HmBB.mB+R)=t&9IROK0GfG7UQrl||", +"|||sk44u1)&X=uAN$S.V)+B.oN..$[0RoIAR<*0&8^2GG!yv||", +"|||h74i4itod=S$:mm+,I$Sm%Z..+8+ouH,CI;Fd_P**w4Ts||", +"||vrQ4eie6>Ke@NVN.Am:+HXM..->I.VSPIIq*3[Fu#-G_ykz|", +"||}k!_i77F;VJHAVV.N9H=#.nnnM-..N$IONBqwY5G#13dpjz|", +"||s'a_QuQZ&XRiXHHBVARB.n```n.OV.$00R3Wag/h|", +"||zg/U[3]P&@=^Z#*1G_Qy'|", +"||{s/]4iJ*8uqXJRVNV0mBBOX.;DN,BoCVA=*YXFJ2&557]gs|", +"||x'/]Quw#Z6&65RNNCPCmNoR7SIOY%mB+V%w1OO*>*W5!fr{|", +"||{j!~TGe#FO=tW[KSV<$NB:VV+A$Rt*t-(W;OVVquYJZ%eIAw;S@^^L(5dZ9F--_7Q/hc|", +"||bxjys]4797~aa*^Zo=K<,A0RRYq9q:H^q*5u5#9*GdQg/z}|", +"|||lsQ/r7Wwja]uP0ooZO=oBZ^aF@5#>oKZ8^F*1u[4d/!'x||", +"|||lzgk~]1t1i]DJLZX;8L=VVSVi^6=(KO6Z*2u[a4eU/hcx||", +"|||}cvffd5e[[w)t*;OZ%&oVo;(uOKH6@6#Zuj[D]d'7k'l}||", +"||||cxyzad4Dt>&1&FP(;F%ZOK=J8^FGZ*ti[e51djpgpph|||", +"||||}vksddQe45*3#J)~^LPK;P>;8)Du;#WDWD44!fflpsv|||", +"|||||lhpp'44/faG>5ef^F>FZ;PLF99*>-4GWQQ44gzsxl||||", +"|||||blxrg/QE]Da15WwGF>5##>5uW1>Dt1DD7UUTsshzb||||", +"||||||}l{'r/47e[1415-539t5tDWwG7wDG7Q4/Q/'hl}|||||", +"|||||||bxs'pQ~E]Ukyd_7i[7wWt7wQi1574~Qrpvzlc||||||", +"||||||||bxsp/rrT!_/4eE][7r_QQU4]QETa'!s{h{c|||||||", +"|||||||||}hx''pda]d]U~!e~e'7Ua444fpg!ykhh}||||||||", +"||||||||||}c{zzkkfp'7_pyT_TU/k~rr!!rrz{lb|||||||||", +"|||||||||||}bllpsrp!pg/rgyTQQ'fxjlp'xcz}||||||||||", +"||||||||||||bcxhhpplls///''cxg{s'pslvcb|||||||||||", +"||||||||||||||bbxlzzhhsshkhhczs{{v}cb|||||||||||||", +"||||||||||||||||b}cvxvvhcv}}cvhx}bb|||||||||||||||", +"|||||||||||||||||||bbb}}vx}vcbbb||||||||||||||||||", +"||||||||||||||||||||||||||||||||||||||||||||||||||", +"||||||||||||||||||||||||||||||||||||||||||||||||||" +}; diff --git a/hacks/images/chromesphere.xpm b/hacks/images/chromesphere.xpm new file mode 100644 index 00000000..fe13632e --- /dev/null +++ b/hacks/images/chromesphere.xpm @@ -0,0 +1,350 @@ +/* XPM */ +static char * chromesphere_xpm[] = { +"256 256 91 1", +" c None", +". c #7774CC", +"+ c #BBBAC6", +"@ c #F1E89C", +"# c #E1D89D", +"$ c #9E9DB2", +"% c #AFBCEA", +"& c #ACABB5", +"* c #DDD8B4", +"= c #CEC2D8", +"- c #9CADEC", +"; c #EBE8B9", +"> c #92A1EA", +", c #D3D2DB", +"' c #A0AEE6", +") c #E3F7F6", +"! c #E6D4ED", +"~ c #E7E7CF", +"{ c #C7C2D7", +"] c #E4CC86", +"^ c #CBB699", +"/ c #A2A1E1", +"( c #B6C7F3", +"_ c #DDDEE3", +": c #D1C5E0", +"< c #B08F81", +"[ c #EFF2E8", +"} c #ADAEDC", +"| c #C3D4F6", +"1 c #E0C68A", +"2 c #E1CBF1", +"3 c #E0E3E7", +"4 c #9FA1D3", +"5 c #8183B7", +"6 c #B3B2BF", +"7 c #D1CCE5", +"8 c #E8E8E2", +"9 c #9A95AE", +"0 c #D9CCA2", +"a c #C8C4EA", +"b c #DBBF8E", +"c c #CED7E0", +"d c #BCA192", +"e c #C3C0B6", +"f c #A8B1ED", +"g c #A6A4B4", +"h c #C2BDD3", +"i c #C9CED8", +"j c #898CDA", +"k c #C8C8D6", +"l c #CFD4F6", +"m c #D0C6D8", +"n c #BCBCE7", +"o c #EEEEEA", +"p c #CCCBC9", +"q c #AEADBD", +"r c #B7B6D9", +"s c #9D93DA", +"t c #DACBE7", +"u c #E7DDED", +"v c #D8D8DC", +"w c #8D90BE", +"x c #C7C6CA", +"y c #ABA1E7", +"z c #C6C5F2", +"A c #D7D6CA", +"B c #DAD8E7", +"C c #F6F9E8", +"D c #BBB3EB", +"E c #DAD6F1", +"F c #C8C8E6", +"G c #D6D2E8", +"H c #D1CCF0", +"I c #DAC6ED", +"J c #D3B291", +"K c #E9E7EE", +"L c #CFCDD6", +"M c #C5CEF5", +"N c #CEC0BE", +"O c #D9E7F9", +"P c #B7B6C2", +"Q c #D1AD8B", +"R c #C1C0CB", +"S c #DFDECA", +"T c #C8C2E6", +"U c #A5A4C4", +"V c #B8AFE6", +"W c #C5BCE8", +"X c #D9DEF2", +"Y c #D2C5EA", +"Z c #F0DA91", +"PPPPP++++R+RRRRR{xxxpppLLLL,,,,,,,,,,77:FTWWWWWWTTTTWTTTTTTTYaYYaHYaHaaTTWWDDDVVyyy/sy}VDWa77vBvBBvvvvvv,A,,,,LLLLLLLLpppppppkpxkkxxxxRRRR+++++PPPPPPPPP666666666666666666666666PP++hhhhhh{h===:m:m:Y:YYYYYYYYYY=Y=Y=:====={{{hNhh++PPP66qqq&&&&&&qq&qqqqqqqq666", +"66PP+PP+++e+eRexx{xxkpkppLLL,,,,,,v,7G7FTTTWWWTTWWWWTWWTTTTTTYzaHYzHaYYTWWnWWDV}VyysyyyVWTYFGGvv___Bvv,,v,,,LLLLLLppppkpkkkkkixkpkxxxRxRR+R+++P+PPPP66666666666666666666666P6666PPP++hNhN===hTT==m:::Y:Y=Y=Y====YYY:Y:Y=={T===hhhNh++P66qqq&&&&&&&&&&&&qqqq66qq6", +"PPPPP+P++++++RReRxxxxpkLi,L,,,,,,,,vL77:TWWhWWWTTTTWTTWTTWTTTTYTz7aYFzazTWDDDDVVyyyysyyVDWa77GBvvv_vvvv,Av,,,,,,iLLLiLpkkipkpkpxkxxxxRx+R+++++PP666PP6PP6666qqqqqqqqqqqq66666666PP++hhNhhhh===T:::77:7YYYI=I=IY=I===I=:===={h=NhNh++PPP666q&&g&&g&qq&qqqq6qq66q6", +"66PP+P++++eReRRRx{xxppLppp,p,,,,,,G,,G7F{TWWWWWWWWWTWTTYWTWYTzYTHzYFHYYTTWWWDVVVVyysyyyVnTaFGvBBSuvvvGv,,,,Ap,Lp,LppppppikpixixxxkxxxxRRRRR+++PPPP6P6P666666666666666666666P6666PPP+hhhhW==hh==F:7::Y::YI=YIWIWY=I=Y=:=Y=={=TNWNhhe++P666qq&&qg&q&&&&&&qqqq6qq66", +"6P66P^P+e+++ReRexxxxkppLLL,,,A,,,,,,G77YTTWDWWWWWWWTWWWTYYWTYWYTYHHTzzYTTWWWDDVyVyysyyVVDWT:7BBvB_vuvAvAv,,,Lp,p,LLpLkppppkipxkxxxxRRReRR++e++PPP6P6P6P6666666666666666666666666PP+e+hhNNh=======::7Y7YY=IY=III=I=I=I=::===={hhhNh+^++P6q6q&&q&&&&&&&&&q&qqq6qq6", +"P66PPP+++++e+RRRRRxxxppLLp,,,,Av,,,,,7FkTWrWrDDhWWWWWWWWWWaWWaTTzYzYYYzTTTDDWVVVVyyysyyVDTT7G,Bv_vvvBvv,,A,,,,LLLLpLkLpkkpxkxixixxRxxxRRRR++++PPP6P6PP6PP666666666666666666P66666PPehhhWhh=W=T::Fm7m7YYYWIWIWIWIY=I=::Y===={===hhN++PP6666q&&&&g&&&&&&&&&&6qq666", +"6P6PPPPPe+e+RRexxRxxxppiLpp,,,,,G,,G,77TWWWDWWDWWWWWWWWWTWWaWWWYaYFzFYzTWTWrDVVVyyyssyyVrWT7GBB___v_vvvv,,,,,p,p,LLLipppkixipixxix(eRRxeRR++R+PPPP6P6P666666666666666666666666666PP++NhN=h={={m==:=Yt:YYII=II=II=I=I=I=:=T=={=NhNh++++^6qq6&&&&&&&&&&&&q&&6666q6", +"66P6PP+++++e+RRRRxxpkxppLLA,,,,v,,,,,7:mW=rWDDrDWDWWWWWWWWYWWWzWTzzYzFYYTWWWDVVVVyyysyyVDTTY7Gvv___vBvv,AA,,p,p,LLpLpipkxpixxxixxxixRe(RR+R++++PPP6PP6P6666666666666666666666^66PPPh+hhhN{==T=T::::::tYY==IW=IW=Y=I=I=Y===={=Whhhhe+PP666q6&&&&&&&d&&&qd&&&&6q66", +"P66PP6PPe+++eRRxRxxxpkpLLLLLA,,,vv,L,7aFWWDDDDWDWWDWWWWWWWWYWWYaYTzYzzTzWWDWDDVVyyyysyyVDWz7GvB_SB_vvvvv,cA,,,pipLippkipkpiiixxxiexe(eeeR++++P+PPP66666P666666666666666666^66q666^PhhNhhhhh====F=YtYYYIIIIIII=II=Y=Y=I=Y=m==m=N=hhNP++P666&&&d&g&&&&&&&qqq&d6&6q", +"666PPPPPP+e+ReRRxRxkxppp,,p,,,,v7,G,777WWWDVDDDWVWWWWWWWWzWWYWWWWYTTaYzYTTWWDVVVVyyysyyVDWT77GBB___Bvvv,A,,,p,LLLLpLppkpixxxxiixxxxxe(eRR+e+++PPPPP6P6P6666666666&66&666qq666P66PPPP+hhN===h=T:=Y:::II==IWIWIWYYII=I:==:=={m{hNhNhh++^P6666q&qg&&gg&&&&&&qqqqqq6", +"66P6PP+P+++eRReRx{xxxpppp,,L,,,v,,,,GF:WWDDVVVDDDDDWWWWWWWWWWWzWWzYaTTTzWWWWDVVVyyyssyyVDWT77Bv_!vSBvvvvG,,,L,L,pppLpppkipxixxxixxxexeRRe%+++P+PPP666666666&^&&6P66^qq&P666666666P+hhNhhh==h={:=Y:I:YIYY=IIIII=Y=I=I=I=Im=T==WNhhhh+++P66&6&&q&&&&&&&&&&&qq&qq66", +"666PPPPP+++++RRxexxkpkppi,LA,,v,,vG,L7FWW^DVVVDDDWDWDWWWWWWWWWWWaWzWzYTTYWDDWVVVyyyyssyVrWT7GGvv__!_vv,,A,A,,,,LLLpkpkppppixpixxixiRxe(e+e++++PPPP6P666666666PP66666PPP666666666PPPP+hhh=hh====mI::tII=II=IWIWIWI=:Y:=:==m==={WNNhe++PP6666q&&&&g&&g&&d&&&qq66qq", +"6666PP+PePe+e+RRRxxxpppLp,,,A,,,G,,G77FWDDVVVVVDDDDWWWWWWWDWWWWWzWYWaaazTTWWDDVVVyyysyyyDWT7Gvuv__vSB_vAv,,,pppLLpLLppxkkxxixxiexRx(eeeeR+e++P+PP6P66666666&6&6&6&6&6666q^666666PPehhhNNh====:=:=I:YYIYY=YI=III=II=I:=Im=={===Nhhhh^+P^66&qq&&g&g&&g&&&&&&q&&qqq", +"6666PP+PP++R+eRRxRxxkxppA,,,,,,,GG,77a=WWVVVVVVVDDDDDWDWWWWWWWWWWzWzWYWTWWWDWDVVyyyyssyVDWT77Gv___BuvvBA,,,,A,,LLLpkkpkpxixxixxxixxxe(Re%++++PPPPP6666P666P66666666666666666^666P+Pehhhh=={T{:m:::ItIIYI=II=I=IYIYI=IY==Ym={kTNWNhh+++P6666q&&&g&&g&g&&d&&q&q666", +"6666PPP++++e+ReRxxxxpkpppp,A,A,,,G,,7FWWDVVVyVVVDDDWWWDWDWDDWWWWWWWYWzWYWWWWDDVVVyysysyyrWW7GBBv__vv_vBvA,,L,L,pLLLLpipkxipxixiexxxxReeRe++++P+PP6P66666666&666&6&666666q666q6666P+h+NNhh=={T=::Y::YYI=IYY=II=I=I=Y:=I===:==={=Nhhh++P+P66&&&d&g&&g&g&&&&&q&&6&q", +"6666PPPPe++eR+ReRRxxxppp,,,,,GA,G,,77Y=WDVdVyVVVVDDVDWDWWWWDWDWWWWzWzWTWTWDWWDDVyyysssyVDWT7GvuBSu__vvvvAA,,,,LLLpLkpppixxxixxxixx(xe(e%e+ePePPPP6P6666666666&66666&66666666P666P+++hhh={=h==:=LI:IIIIYYYIYY=IYYYI=I:=Y=:Tm={=hhhNh+++P^666qqqg&g&&g&g&&d&&qqqq6", +"66666PP6P+++eRRRxxxxkkipipL,,,vv,G,,LaWWVDVyVyVVVDDDWWWWDDWDDWDWWWWWWWzWWWWWDDVDVyyyyssyVDT:7G_uB_S!vvvv,,,LpLpLLiLpkkkipxxiixxxxxexeeeeR%++PPPPPP66P66666666666666&&666q666666^6P++hhhNW=h=T=Y:YIt:YI=IYIIYYII=IY:ImIm=m{=={=N=hhhh++P666&q&&&&&&g&&gg&&&&&&qqq", +"&&666PP+P++++eRRRR{xpppLL,,,,v,G,,,77Y=DDVyVdyVVVVDDDVWWWWWWDWDDWWWWWaWaWWWWWDVVVyysysyyVWW7GvvB_vuvuvvvAA,A,,,pipikppixxixxxxixxie(Rx%ee+ePe+PP6PP66P6&66&66&6&6&666&66^66666P6PP++hhNh=h===:=:t:YtII=II=YI=YIYI=I====:=m{{={hNNhNe+++P666q&&&g&g&&g&&gg&&&qqqq", +"66666PPP++e++ReRxxxxpppLL,p,,,v,GGL77TWWVVyVyyVyVVVDWDWDWDWDWDDWDWWWWWWWWWWWDDDVyyyyssyyVnWF7BB__B_vvvvv,c,,LpiLLippkpiixipxixxxe(xxeeee%e%+PPPPPP66P6666^&66&6&66666666q66666P66P+hhRhh=W==T:::YIYYYIYYIIYIIYYII:III:::=m={N{hhhhh+hP+P66qq&&&&dgg&g&&&g&&&&q6q", +"666666PP+P++e+ReRRRxkpp,pL,,,,,G,GGLY=WDVVyyVyVVVVVDDDWDWDDWDDDDWWWWWWWWWWWWWDVVVyyysssyVDT7GG_u___vBvvvAA,,,LLpppikixxxixxixxiiexxxe(Reee+ePePP6PP66P66666&66666&6&6q666^66666PPP++hWNhN=hT:=:mIYttYYII=YI=YII::I==m:=mm{==h=hNNW^e++P6^666&&g&&&&g&g&gqd&&qqqq", +"66666PPPP+e+eRRRxxxxxppL,,A,A,,G,GL77=WDVyyyyyVyVVVDDDWDWDDDWDWDDWWWWWWWWWDWWDWVVyyyssyyVDT7GvB_3___!Av,,,,,,pppkpkpixixxixxiexxxxxeRee%+++PPPPPPP666666&66&666^&66&6666q6666666^++heh{h=T==::Y7YI:II:YYIYYIYYYI::I=ImI=m=====Nhhhhh++^P6q6&&&&ggg&g&g&&&g&&&&qq", +"&6666PPPP++R++eRRx{pppipLL,,,v,G,GG7Y=WVVVyyyyVyVVDDDDWWDWDDDDDDWDWDDnWWDWWDWDDVVyyysssyVWW:7vu_Su_vBv,vA,,LLLipipixxxxixxxixixxx(ie(Ree++PePPP6P6P6666666666&&&6&^66q66666666PP6PPhhNh=h=={F::mtYttYYIIYIIYIYI:II:::===mm={hNWNhNh+e++P6666&&&&gggggg&gg&&&&qqq", +"&&66666P+P++eRRRexxxkpLLLL,,,,,,G,G7:WWVVyydyyyVyVVVDWDDDDDDDDDDDDWWDWWWWWWWWDDVyyyysssyVDT77GB___S_vvv,A,,p,pppkpxixxxxixxxeixxxeexxeRe(eP%Pe6P66P6666&&66&66666&6&6666666^666PP++h+hh=h===:FY:YYYI:YYYIYIYIYYY::I=I::=={==hhhNhhh++++P666&&&&&&g&g&g&&g&d&&qqq", +"666666PPP++++eRRRRxkpppiA,,,,v,,tL77TIWVVyyyyyyyVVVDDDWWDWDDDVDVDWDDWDWDDWWDWWDVDyyyssssVnWFGB__u__vBvvv,,,,LLkpixxxxiexxxxp(exxx(xe(R+e+ePePPP6e6666P66^6&66666&6&66666666666P6PP+hhN{h=W===:::IIttIYIYIIYI=I:IImI::=::mm={==hhhW^+R+P^6666&&&gggg&dggg&g&&&&&q", +"&&66666PePe+eRRRx{xxxpppL,,,,,GAGGLtTWDVVyyyyyyVyVVDDDDDDDVVDVVDDDDDWDDWDWDWWDDVVyyssssyyDWY7Eu3_u__vv,,,,,pLipkiipkxxxixx(xxx(exxexeeR%e+PPPPP6P6P6666&&666&6&P666&6666666666P6PP^hhh=h={Tm::t:Y:Y:I:I:IIIIII:IIm:Im=m={k{{{Nhh+Rhr++++66&&&dq&&ggggg&g&&&&&&qq", +"&6&6666PP+++++exexxkppLL,,,,,,,,G77:IWDVyyysydyyVVVDDWDWDDVVVVVDDDDDDWDDWDWDWDDVVVysssssVDW7GBB_3__vvvvA,,L,i,kpxxkkxx(xxxxxexxxxe(e(ee+e%e+PePPP666P6666&666666&66&66q^6666666PP++Rh=h=====F:=7tIIYtIYIYIYYI:tImImI:m={m={NhhNh++Ph+P+6^66&&&&gggggg&g&ggg&&&&&", +"q66666PPP+e+eR+xRxxxLpLLL,,,,G,,G,77WWDVyy$$UVh{7m:===WWhn+rPhrhrPnh{{", +"=YYYYaH7777FaYTYF7l7lHHHaa7FzYzYHWVyDH3K[[oK888833~_u~uSvvAvSSSS3SSSv*S~~o[CCCCCCCCCCCCCCC@C;o~~~;~o~S_AcppRxe++++R++++++++r+kkFkii,GB3o[Co[oKuXK3XcE,M7c7,i7FFFF:TFFFTn6}}UU'U}UU&66rhRrUU49www59ww9www>w$r!KK!Zuutp+y$sw9$s4s$9$99$U6{mL7L777GL7L:::{{+rr+R+h{", +":F:aF7777G777HFHF77G77GGGGHHHHGHEHYVVHuKoo[ooo8~u3uS3_SAAAAvAcASSSSvSS*So;@@CCCCCCCCCCCCCC[;;~~3~~~S3SSpixxe++++RRRRxRR+(+%R+nRRkkkFMX3Ko[ooCoKKoK3Bl,7c7G77MH7F=TWWWWkTrq}UU4UU}rrnxik%&4$ww5w555wwwwwww99Nuu!t2*!Lh6g9Uq}}U$>94444yrhkk:ptLtGtG7t777:T{+hhWR{k", +"YYY:YLGcG,GE,G7GHHHG,7,cEllLlGBEBGHWDzB3Kooooo88~3~_~_3v,Ac,A,AAvAAAASSSoo[CCCCCCCCCCCCCC@C;~~S~SSSSScAAiex+++++exxkixkxxxRR+RRnRRkkiGXKoooooooKKK3BiG7lL777LHGFTTWnnrn(r}}&UUU'&6%RzkR6U$www55555www55wwwsqu!*m0ImNhhm7hhRq4$$$$$4U&rh=L:mtG!!tttttY7YY=WT{TFTF", +"TYaHGGBGc,ccEEBBlG7l7lHHHYH77EXXBXElTzEuKK[[[[[83S3S3~3SAAA,ppp,AAAASS*;[[@@CCCCCCCCC@@@CC;[o~~~AAv*pipppee++PeRxxii,iiikx(x(RRFiilGvX3KKK3uKK33XXXBGccLFMFFFLMHTYTWWWWnn+nfr}}}}rhRFFn}-$ww555w55w5ww5jww$VN=mG!S!GuK,r6r+&4wws9sUUr{W{{mmm!2!2!ttIIIY=FTFTTTT=", +"WTYHGEvGBGGvEX_XBBGHHzWDnWFHGEEXuXuEHzHEK8[[[[[o8~38~3SSA,,pApppAS*SSSS;CCCCCC@C@C@C@@[C@[[C@[SpSSScpppppe++eeRxxiAAA*Aipxxxkkzk7lvX33K3uEEEEuu3XEll7GliaFMFFFFkz7MRr}6}r%nhn6rr=FF7Fk+}&>$ww5555wwwww5ww9$$46tKo[Kt6y$$yqnU$s>w$$4Wtm==m7tt!!!222tIII=WI=TYYYWY", +"WWHH7,77LL7,,GGGLlHFDVyVDDWzHHEEXuXX_kkE3Koo[C[88~3~o8~SSS*ApAiAAS~~~~o@C@@@@C@C@CCC;**;;@[;[;A*SS**ppxeeee++exxAiAAAAAckxx(xkkxzRxF,llElEEllEXXXBcG,l77klGFkFTRkzk%Pf&'U}rnDWT=YYF{{nnr'$>wwww555wwwwwjjjsw96G!!AhU9$s$4}F}$$$>s$$rGGtttILtGt=t2E2IIIII=YYWYWWW", +"WWWt777FFFFM7liM7FFTWWnDzWWzHHlE3u33KGF73Kooo[C;8~3~[o~~SScAiA0c*;Co;o;[CC@C@@@@C@@@[;~;~;;;;SSS;SAAppeeee+eeepxppAAvvAAkxRxx(kR+nRRFGFznDWHMHHE3EBl7iFFFccFz(nn(hznrf&4U}qrhWTYI:Th+r6&'$4>w55555wwwwj5555js}qqh{U9sws4}T,i}U4U44}+tuu!,tm=WWrr=tttIIYIYWWWWWWD", +"WWTaYH7HFFFFMFF7aTTaMHHHHHzYXEBEXKKKK3LG38o[[[[[oo~~~3~3~SS*AcA,;[o@[C@C@C@)@)[;@C;[;;~;[;[[;;S~;***#iiexe+(eppppp,,pAAxkRR++kkxnRRFizn}}ynnnWzlEXXElGl,MEXizRn+n%r6}'/4'}}rWYT=:YYF{r}f&4$>>wwwjww>www5555jww9VW}$>ww$4$&FclFP'UqD{mmt!2YNW+6}nYYtYtIIIIWIWWWWW", +"WYYHFaaYzTTTTzTYzzHHHzTzMMaHHGX33Koo[KBv38o[C;Coo;o~~S~~~SSAp*p*S;;[@CCCCC@;;@@[@;@[@[;;@C@C@~SS~SS*i#ipxeeeiAAppep0pAApxR(+Rx(xRRF7ET}y}DWnnWzGEEXXBEllcBXGikznRn%r'&44U6rWTFF7777777{rfq-gU>w>wU44>jjj5j5jww4}Usjjj55jj$/$sU6F}}rh==WN!!t+DD+T7::7ttIYIWIWJIDW", +"zYFYYYTTzzWWWDDDTzFHMzzaaHMzllX3u33KK[K33~o~oo;oo8~~SSSS~SS*A0AA**S;;@@@[;;;;S@)@CCC[@[;@[;;;#S**#c**p#p0pppiA**i0LALA_SAAiiiikkkiiGG}/yDzHHHMEXBlEEllGlElGclFHMi(knnn%VfznnnnnT{T::77FRrqUU'U-44U>j555..jw9sU}4jj....5jjwswjs46}6{xt22!!uutI::7t27t7YWIIWWIWWIW", +"aHHHFYzWTzWWnVnzEElGEizTnWzHElcXuBXK88K33~~8o;o~ooSSSSSSS~~~AAAA*A*S#;C@@;;**S;@C@C@@;@;@@;;;****p0ep0i#c0*i#S~SSSv*SSSS_SS_A,LiL,XE}5synHXXEGlllXlllM7FFFHHlHHHElMkFR(kznfU4U'}'nTY7tFrVf}}}f6''/w5......j4zWs5.......w>sjjwss4q7_vuuuuu!u!!!2!G!ttt:T=WIIWIWI=", +"FHFaazTzazznWDHGX3XXEXEllEllcEGlEBEXK333K38oo[C;C[~S~SAAA*S~~**SS**SS;;;;;;S###[@@;*#;@[;;;S#A0p00p#0p#i*eeeexpA~;~~SSS~3~3vAvvv~3{$sDHHlllBXcGllHllMH7MMFHllznzMFz(nn+n(n'4/-U4/UnHYY7{n6f&'}44>jjj.....jUz%>5.......jwj5jjjs$y=GuvmtA!!!!u!!!!2ttt7YTYW=YYYTTT", +"aaH7HaYzzzWnnnHHlEXXElEllEXEXlGllGEE33B=V99gSu;[[[;v~SSAA*S;;~*SSS**S;;;*;##**;@S###;[C@@;#**0A0*p#p#pe0epeP6&epSS~S~3*cp~~S_SSS33uBBBXcl7lElllHMMFH|lMlGHzTzzVs}zTnnnz{nr'//'f>44nzY::Wrrf}}-4$>wjjjjjj>%nU$j5.....5jj55j5jw$nEuEt7WVqrG!G!77H222ttHYTHYYzYaaFz", +"FHFFFFzzznDnnzHHMllllXlEEEXHzznnWTGGah6VUD:_u~o;;S*S~SAAp*~;;;#S;***0*#S@S@S@;;00;@C@@@;@S##0#*####p#0c00i06&&PexpePq$$$+RkkP+vBSB,GG,cAMiMlMFzznzzzFlEHzzHzHHHTDDDnnnzznrD}/}'/-yrYzaTzn'}U'/>4'->>>->>>//>j>jjjj>>jj5jjj>w/nEHV//9s/nFrq}q}qDhWIItHY7HHHHHzTTa", +"MHHHHFaWn%nnnn(zzzMMFlllXHnVVzWT+ncE_BGB_K8o;~;SSvAA*AA#S;;[@;;;;S#*0A##;@#@;@@@;##@@@@####*#*#S#*##p00#e&g&&Q$g+eh&$9g&s55swPEEBvLkkRRFkFMLMFnn%n%zFMlMHHHlHlllXHWVDWzHHTznDVfVfrnzaTznV'U/'U-''f-->%%4>wwjjw>>>->>->jjjjj>nz'swws>w}/4UVW=WW=tt7TttYYHGHHHTWWT", +"HHMMMHHzznnnDzHzMzzMllHMHzV/VlXKKK33_38K8~~88KAAASA*S~;~;@[@)@;;@;**0*##@;@;@;;@;@@@@@;#*#*##;##c#p##0eee0e^pp^0exp0tN=NmuSu~pAAv,vizTT(xMilFM(zzMlllMlHlHMYMHzGlEzzHHlHzWWnnrr(TzHWD}f%z}4/////'U-U>Ufr>s>s>>>>>4'F(>jjjjs>jj5jj4nf/s}ntGu!!2!2GtITtYYtYHYYYYYY", +"lHHHFHHHMn%z%zMHllHMMll(n%nnzlXOKoo33K8333vv,NLpAS;;;S;;;;@@@@C@;;;#;#;;@;@@@@@@@@C@C@@@###*########ieP$9w$^e^e0xb*~SAAAS*AAA0,*v,vvv,zzFMFMFFzMFMlXEl|lHzMHEHzzzzzHMzHzHzzzzzWTzTWD}}}z%f-/>-/''U-4-->'}'%n%(%>>$>->j5.5j>s>ysyTzaEH}rHG!EEEHzWGGTnWTTHa7lHHHHH", +"MFFzMz(zzMMMH(z%n%zzMlEXlHXMFMEBXuoK~_SSSvve&9Nm0A~SS;S;;;;@[@@@;@#@@@#@@@@@@@C@@@@@@@@@##0^&6#@##0gwd&^^e0ep#S@SS*0p0pNxxpAvSAvvA,,,GkFiFFFMMlHXElllMzMnnDDfnzMHzzzWYnzzHYznnzzazznDDn%%f-/-/-/'ffr'}ffDVUU-'>wjjjjjj5j>%n'rFMBuuElT+nFHEW}U/}DnnDDnDrnz(HMHHHH", +"FMMzzzzz(Hl|MMMzz%(zMMMMllHlHFlBlcK883vS3SvBuAAAPNSS#;;;;;S#@;@#;@C@@@@@@@@@@@@@@@@#@@##@@#0##000eg&1]#1e&^e@@;@;@[@;;*0pA0AASuSSAA,_vLFkiMkMl|MEllll(fnD%DD%zHMHlMMlHznzMzTzzzHMFF((fff''f'--/-f%fff}}fnzf/>4>>->>5jj>j>%lXMr'rlEHzzzzz(nD'/>>'f%%/-'f%Dff%(nz(", +"%zz((z(MM((zMM||z(zn(%MllXlXXlclvG38o~3SvLep,3S*SSSSS#S;;@;#@[@@##@@C@@@@@@@@##@@@@@@@##@##@#]#0#]1^000@]##00#@;@@@S;SS00p0A*S~SSSAvAvi733BcllElXHXXXXMllMMzMlMlllHllMMlHMzMFFMFFMFznnfff'''/'-f(''f/}}nzFn}U'4>>>>>((%'(f--/>>>44>44--4>>>>///>>>>>//>>->'ff%fn", +"%(Mz(MMMz((MzMlM(((M((M|lXXXXXlE3X3_v3SA,,,Am0eex0S#*#S#@;@@@@####Z#Z@@@@@@@#^1]@@@@#@@#@ZZ##@#@@@]]#]#@@@Z##Z;@@;@@ZS*pApA0GAt*vSSS_Bv,c3BcMllllMlXXllXXl(n(HMll|MMl|lclMz|MMMMFM((((%%ff------%M(rfTFcXc|(z(|c%(-(|((MM('-->>>>>>->-->>>ff-f-%%((%%%%%%%%(%(M(", +"((((|(((MFMMl|llllcMM|XcXXXKOcBB33_vAAvA!AeeeL0p0A*#*#@S##*###0]]##]ZZ@Z@@@]]###]Z#Z]ZZ]#]]ZZZ]]######Z#@@ZZ@@#*Z;@SSZS*00t0S0*uSuSA_Sv,,cX_clclcXXXcc|||llMlX||M|||MM||MMMM(MMM(zz(|(%%(((((%%%f'(|XXXXM%fff%((%%%%%%f'->>-->>----%-----%-%((%%%%(%%%%(M(((|||M", +"XXc||XXOOXOOOOOOO|X|XOOXOOXcO3XX333S_SL,AA!AAAtA*0!#0*0000b0^bb010]]1b1b]1]]]]]11]111bb1111bbJb]]bb111111bNb^b01211IbNbmpmpNN=L0L*SSvSv,c_X_XcXXOXXOOOOOXOOOXOX|XXXcccX|ccXX||ccc||||||((|||||(||i((((|((((((((|(|((||||%(%(%%%(((|((||||||||||c|||||||||ccXcXXX", +"))))O)O)O))))))))))))O)O)Oo)8333~vvv_v,LLL,0NNmNNNNNNJN^JPQJqQ&dddddQddddd>-------%(%---%-%((|(%(%%(-'(((|||||||", +"%(((((((||(((((((((||||||(Mc3XBB33S,,pALmApmA0NN^0ZSZ;ZuZ0ZZZZZZZ@Z]]ZZZZZZZZ@Z]Z@ZZZ@@@ZZZ@@@ZZZ]]ZZ@ZZ]##Z@@Z;Z**##0*uZ0!0t#;**Su*AAAAiicccX|iM(cXXlc|X|||||||||((M|||((|||((||(i||(|(%%%---%%-%(%(|cOc|'--(O|(%-|(||(--->>-->->------------%((((((%((((((((%(", +"%%(MM((((%(|M|(((((||||MMlcXBcccvvS3S~SS,,0pLpee0SZ;;Z@@;@~Z#Z@#Z#@@@@@@@ZZZ]Qd1@@@@ZZZ@Z@Z]]]ZZZZZb1##]@]01bb@@@uZ#*ZS*****0*SS;*~SS_vvAcAiOXXc7l(l|l|cXX(|(M(||l((MFl|||(|||(x(((x(%%%%-%----%%%--&'%|cc(%((6'%--%c(-(->->->>>>>>--->>>>----->>>>w>>---f%-%%%%", +"(M((MMzzM%zMMXlMM((MM||M(llclL,,ivv_88_8,+eA*SSSSo;o@SZu@@;Z*Z@@]0#@@@@@@@@@@Z@Z@@@@@@ZZZ]ZZZ]Z#]00^Q0####0;S#@@@@#Z*;;Z~SSALA*S;oSASALpi,cv_iXcXXXXlX(((MMM(lll|zznzMHzi|kMi(R(R(x((((%-%-----%-''>>>&'P%&->>-->>w>'('->->-%%-(-->>>>->>>w>>->>>>>>->>-----ff-%", +"zzzzzz(MHllzfnM(((((MMHH|MXli,lBBc_~3A+eev*SSS*p^0~ZS;;ZS#;Z#;@@@@@@@@@@@@@Z@Z@@@@@Z@Z@@#]#]#]#]e0^g^###0e^&e;;@;@;;@;;*00p00AASSSAA_vv,FxiiikllFllllMHfDDD}}DMMHMWzzYzWzlFzzz(n((kx(%%---------''%%----e(-->>w>>w55www>----(%%|cOc|c|||(--->-'((---%%%%%%%%(%(%", +"MFMzznzzMHMzznnnV}DzzlMllllMFGXHm_88A{tpxxPx+q6epS~SS#;;@@;;@@@Z@@C@@@@@@@@@Z@@@@@Z@@@ZZ@@#1g$^###1&<5d000e10##SZ;SZA0NxeeppxAAAA0tm{xkxzR(x(|lllcMllH(zz(DDDD(zHzznzWzzzFMnnznnTzF(r%%(%''-->>--&''''-'%--$-->w5j>5>ww>>(>%(|c);cc6P+i*|6-g>'(%%'f'%%%n(n((MzzM", +"HlHMzMznnz%znz(znD(HMHlnnTF7l7BBK88~88Sc,R}&9qmR^*S#S#S@[@@@;@@@@@@@@@@@@@@@@@@@@@@@@@@@#####1^0##@##^$99<$6^ex*;;S**#x0pepepAApx,pxxFkikRh(kFFF7HllllHMzz(nMlHM(znWWYYYzYzznnzzTzznf6%(i'U-g>$-''-g>g-''-%'(%>>jw>>55.5ww>>--6(iic|+ciGvBikxr}6%n(znWWTzlHHzzHH", +"HHHMHHzznnn(nzzMlHznzVrfyfVnB_3AA3~~3vSSS_A,+xA*S~S**S;@C@@;@;@@@##ZZ#Z@@@@@@@@@@@@@@@@@@#############e^&g<&6^^e^e^x*SS*~~SS*A*pApLxkiLMk(RFzFz(RzzzzMHMlllHllEHFllznzzYzzzWnn%n(WMF%}'r(%4>>>-'%U--$>'6>$>g-->>>-|(>j55w>>ww55>6M%}4}FHG!EBGBE2HTYYzHHHHHHHHzYH", +"MHlHzzzzzznzzzzzzWMMMMHWDs/zE33838~~vS~~~~~;;~**A*A#S;;@;;;@@[@@@@#####@@@@@@@@@@@@@@@@@@######0####0000^e0#ee#*A^eppee6Pe+A3~AppSSL{kkx(Rn(R(zzz(TnnzMHlHlllXlllElHnWzzzzzn(DVfDrWMFRnnnrU4444-%6-4q%%>>wwwww>>>--%>>j>w>-->5jj'U>s>'VhHEHGE!!!GEtHtIIIYHHHHHzY", +"MFFHzznnzz(zz(nnnnHlHFMzn}VzzEXK3B_u3u3~~~o~uSALpAA*SS;;;;;C@@C@;####0##@@@@@@@@@@#Z@@@@@####00##0####ee0ee&&66^xe+Np6$9gP+w5wPmS3vALkxhRRn+nTzTnnnnnTFHlHEHMGEXEHzWnnnnzznnDff}'/'VzzHMnf'4>4444'U4f%&$>w>jw>>>>->>wjj>5>>xX%>jjj>'}Us/D}UVnHHt2!2tIIIHHHYHYHYY", +"HHzzazWWnzWzzzzMzWzHMHzz(y}rDyWynGLi6rkB~~o8~S;~A0pA*0A*S;@;;@;;;*##00###@@@@@@@@@#@@@@@####0#0#######00##0e^^&+e^eeqg9w9gq6P6{+evAA,v7iF7MF,Fznznnz(zMMEllHHzHzWDDDWnWzznDy-/y'y//(FhDTTn}rn'/>//>$>>ww-%wwjwwww>>jj55w55w${cR&44s/}MTUV}}Uyrt2GtttHYYIttHHHYHH", +"HHTTWzznDnnzzMMlGEHHHHHHEXMHMHHWk77+V}y}TG3u~o~;~~**AA0p0S;;;;SS#ce0p###@####@#####@@@@###@###e###;##p0ee###*AP^ep0S*AApeq&mAtLLLA,AvcBcc7iFFFFT(zzzFzMHGHlHHzHWDyVnznnnn%D/'fy/-/4THTIYrrnnf'4>wjjj5j5j>%(fw5...555j55.5jw>&lK!H7ny/DGu!tHEGtG!!tHtHHHHHGHHHHzH", +"aaHzHYzWznnzzHHElEElHHlHXllH7G7GHl_XBn9..5s9P~[;[~~~SA,0p*S;S;*###p#c#;##@#@####@@##@@@@@#####e#ie#i#p#eeepp0ePP+L*SSSS~SSS*AAAAvS333v7F7l77ilG7FiMilMFlFHFHFHHMDWzzT(nnnrn}/>/>/>Un7YHYnfn}UU'/>wj5.....9r%>5.......j>j55j>j$D27kxL,7!!uuu!u!!!EHYYzYzzFzHHMFHa", +"7aHHzHHHzDDWzHHBXXBll7llHHlGlGiiGGvBBB3mN7v,3o~)C;);S*Ai0p;S#**c#c####S;;#*#####;;;#*;;)#@##ce#e0eee0eieeeeeeee0p0A~S;S;SSSS,ALALASS,hs.sVzFFccGGBEBEGFFFFFMlllEllHMaTnr%n%DU4$s'}DTHY7Wn}'}4/'}'>w......5$n(>5......5j>jj>jw4}tu!!uKuuuu!!G!!!!!tTWWannTFTYYaF7", +"HHFYzzazHWWWzHEEEEE,7l77M7kMGl7l,B_3_3K33K8o[;;;C;SSSA*AA*S;;**#c#|#c#SS;#c#c#c#;;;;#0#;;;;@##i#e#epe0i0p0p0p0A*S~S*SSSS~~SAppppLki,cEBWjw/VzHl7llcBcGlFFFlHHMHFlHiFFnDrffnz%rVnDrWFt7t{r}}}'&'44->j..5.jjj$>>j5......jwwj5>>4qnt!!!uKuu!utGtu!!G7mWTY=W=YYYzYHH", +"HHFaTTaWznDDWzHElll7FkFFTnTF7GGGcXK3883K_3S3~~[[[~SAcAAA*S;)*c#c#c0#c@S;;;#*#c#;;))@;c###)@;;##i0ie0ee#e#pi*0AAAASSSAAA,S~SA,pkkkxR{k77GW//ynWzFFHBEBH7lM7li7MGFFzkzT%V}}}'D(FMzRnWm77:nr}}}U>$w>$>>j55.5jjww->>55....5>www9444}r==II!uut7{=:G!!Et7t7tITYTTYzTF7", +"zaazYzazWWWDDWzH77kMkFFkFFFF,lcEBu3KK33Su~3~_~~~~3S*A*cSSS#c#i#i#|#c#S;;;);S;**;@@)@)@O##@O;S####i#c#epi0exppA0ApA,ppxNxpvALxxRkkhnRhkkFTV/yyVDnTTFllclG7MFFF7FFh%rrr}}//UUfrTTzFFY77Tnr}44//sjj5wwj>j5555jwww-->j>>jj5>Rn%%'4U}6W^N2!!7TPV6:7T=t77YIIIYIYYTYTTa", +"FFaazTzWWnzWWnWFM7FkFkTFFTRzFEcB_33K_3_3333~3SO~~3ScSSS3SSc*pip#c0#c;;;)@;;;;S;S;@)@C@)@)#;#O#Sc##c#c#ippepexpppppxeee{exLLe++PrRR+(hRkkzWV}VfWnnnFGBE,cG7FFiMkRnrrr6}}U//}U}rRFY7t7{hrf&4444w555jjwwj55..jw>>&(>wjw>>%Rl7PU$4U}nWtu!t:hrrqD=thW7t7tttIIYYYWYTT:", +":F7FYHazzTTWTTTaFFFzFFFzRzTFl7GBKKoKB,__~8~3~~~8~3~ScSSS~S*c0ipc#cS*;)@)));O;SS;@C@)@);;;;;;;;;#c##c#c0epeexeeexxpixeRexxLpR+rPP%RRP%%rnTFnyy/rTnz7lBlG,MFkMHkznnrrnnnrVUUU}qr{TF7Ytkn+r}'$>wjj555j>wjj5w5j9%ixi%>>ww9UktU$44s$4&Hu!!Gt==DPVh:tt2t2t2IIIIYYY=TYY", +"77kiF:F7FFFTTTTTFFFFFFFFTzklEiBXKKKB7,u3K388ooo88~3~SSO~SSc0cpp#S;S;;;)@C@)@cS;S;;)@)@;S;O;;);S;;SS#c0ppexeeeeeexxppxxexpLLkR+%PP%+rPrr%RFHz7zzFl7GBBc7ikFkilkxn+nnRznr}}U}}rn{TWF:777FRrq$9wwwjjwwwwwjww>$$RX[[A6w$w>$+r$s99>$shGtm2!ttt=hh=t22222222IIIIYYTYYH", +"L777kFkFF77FFFTnhn{TTnRnTFFFFFX3333Fkl_uKK88[8~88~~3~~SSS*c#pie|*O;~;;;@;;;;#SSSS;@@);;S;;O#;O;SO;S#c0pppeee+++eeeixxxpxxiikxR+6r+%+%r+nkFiki7,GlBBXcGiFFkFkFRnRRzFFknr}}}VDnhrPV6rhmFkr}U>wwjj5jjwww5jww$r++p!uSSc%$94V4w>wwww$hWPPNtGt!!22!!!!!222IIIYYYIYYYHt", +"lGi7i7k7kkL77FFWDDDDWnTTTz7F7GBXBXGzWE333Koo[[o~3888[~ScSccipii#c;);~SSSS~OSSOS;S;~)@;SO;S;;O;SS;SSccpepeee+ePPP+eipxipppiiixR%Prr+++RFFi7,H,GG7cX3BG7,iFiMkR(+n+TFYFWWrr+hn6}}&U}}6nxx%q49w5w55wwwww55ww4R7=mtpR&rxz6&UU9wwww9>UDqVPWt!uuu!u!!2!222IHIIIYWIWIH7", +"7GGGG77LGG7BE77WWDDDDDDWzYF7BXEB_GaWaGB3K8K[[8~O~O~~~OSSc#c#ipppi*~~~~S;S;O;;;O;);;;);;;c#O;S;;c;c#c#ipixiee+PP++++exxppxpiikR++6%+nnklBGGGcEBBXu3XBEc,FikkFkFRF{77FWWWWWhn}}444UU}qr(xxr&>wwwww5wwwwwww94tu2N=:hq$$4r&&'>99www9$gy&&6Nm!u!u!!!!!2ItIIY=YIIITHH7", +",,G,ccG,G,GvBG7FThrDDrDWFHlGEBBEEHzTYEB3K8ooo33SS3~_O~ScSc*ippppi*S~S~SO;;);O;);;));;);ciS;;);O;OScc*i0xxxeeP++P+++RRxxxipixkR%+r+nRRxMiGGEBX_33Ku3BBEB7lkFkFFFFF7tFWhW{Th+UU$$$$4q}6+RF(64$wwwwwwwwwww9$U7uuttp7h}$$$>4g$>99w9s4Uq&VVNm2!!!!!!2!!tY==YY==TYYYHt", +"7,G7G77L7,,GBG77YYTWWDWz7l7GEcEGGFWzHE_33oK88~333_S~3ScAiipiepeppcSOSSS~O;;););)C@C));)SSO;););;;;#iiiipix+ee+++++R++RxxRxx(R++rrr+%hnR{FiGBBKK3KK33uBBEi,kFkkkF:7F:kTTTThr}U4$444$U'U}PhF+'$>wwww9w9w$44U^!u~u!!ph}$www9$99>w9$$UU6PhNm0!2!!2tttt:::==W=YT=YYt7", +"7iLL,77,77L7LG77i7FkTWWT77,GGGG7HTnzHEBKKooK33v3_S3_~cAAppiipeippAA*SSSS;););)@C[CC@C[@;S);)@);O~SSc0*i0ieee+e++P+e+R+RRRRRP+rPrPr6r++nRFFGEXKKKKK333XBBiliiMkFkFmF=FT{h{hrqU444U4$$4g&UP(R6$9wwwww9w4$4U$}=!KKKu!m+q$9www9w99>94$U}h{ktt,tttttmmmkhhh{h=W=YYYY:", +":77777L7FFFLG7FH77Y:TFTTai77L7lFzrW7lB3KooK8K_vAv_v_*cipppppixpipiccccSc;);;[;[C[CCCC)C[);C);;~~ScS*ci*ccxixRee+++P%+PP%+%66q6}q6}6PnRx{FLcBuKoKKKXGEBEGGi,LLFFk{Whk{FRh+++}&&U&U4$4U4Uqq+%&>$9www5w5w94U4d6N!KoKKuLkP&$$w9w9ww9w99gr{{LpmmpppLmkk{hr++h+hhTFY:7", +":F7:77:7:TF7777a7FL77:TaTFii77HaWnWGBuO8oo833_vccAvvc,pxxpxixppiApAAAcc*S~[~[[[CCCCCCCCCCCC@[~SSSScSScSSAiixxeRR+P6PP66P66q'g&&}&}rr+RzkF7lBX3KK3HHGBc,L,li7,iFRRRnhh{n++r+q}q'qU4gU&UUq}6qg$9w5555555w9$$$UdWIuKoooKGxq99wwwwwww9w$4q6V6PPDPrhr+hh+r+%P+hh{7:YY", +"::T77Y7aTFFFF777777L7kFakF7FaHFWDW7E_338KoK83Bv,,cAA*ippxpipippAAippcAccS~~~;@CCCC@CCCCCCCC)~~OScSScSSSSA*iiixR+e%P6%66}q&qU&'q}6r+nR(ii77G,GXX3X77GGL7ikkilikRn+r+++hhn+r6q&q}&&g4U&'&qq6qg$9955555555w$4Ug$$dN2!uooKuL+g$99wwwww99$$$$U$ggU&&&UUq6Pr+nhRx7F7:Y", +"Y7YFTF=Y:::L7F7F7F77FmkTkTF:zHWDDTluKKKKO8K3Kvvv,cvcvcpixppipipc*cpp0iAAc~oo8[CCCCCCCCCCCCCC[~~S3Sc~333SccAiixxRR++66qqq}qq&q}66%h(R{kFl,i7iLGGEBlcBGkkxkkk77nPr66rrP%+++r6}'&q'q&&U&&qq}q&4$ww555.555ww$U4$$$$V^NI!uooKuxPg99999$ww$9$$$$y$UygUUU&}&rRxxzkmF::Y", +"F:F:Y=FFFFF77777F:kTFk{TWTWTYWDyDzGX33KKKK833_vAGvvvAiixipiAiAccSAAiAiicA388;[CCCCCCCCCCCCC[[[~~3~3S3~OS~SS*ciixRRR++PrPP6rrPr+++hhRRkpM,li7iiii,,LLkFRh{kFk{+%6666P++h+%6q&Uq66}&U&&}qqq&Ug$9w55555555w9g&$99$&V+^NI!KKK~!N&$99$9$$9$s$99$g$gUUUUUU&&6nhkkF:7F:", +"YYaFaTY:77F7k7k7kFTWhWWhWhnnWDyyVYEuKKKK8O33_B_vvv_X_AiipipiipSA_vcAAA,AA~~[[[CCCCCCCC[[[[CC[[[8~8~o~8~S333_AAiiixxRR%++%+%+Rn+nnnRnnRFkG,lkFkFiL7kik{Rnhkk++r+rr6%PrR+++r}&}&}PP6q}666}q&Ug$ww555.555ww9g&$$9$gqD+^WN2uKKKK!p+&$9999$9$$s99$$$gUggU&'6+Rhmk7YY:", +"HFYY:YFaFkm77k7k:kTkWWnWDVVVyys/rzXXKKOKK33__3B___vvvAiippiiAic_SvAi,i,cSSoo;[CCCCCCC[[CCCC[[o8o8)8o[)888~~~3_SAcciikxhRR+R+Rn+++n+nRx{,i,iikiiLkkk{RRhRRk{hr6PP+++rRRxn+6}&U&q6V66Prr6q&'ggg9<5555555ww4&UU$$$Ud6VW^NN2uuKKKuB7kr&U$U$99$$$s$$$$UUU&qPP+kk:777:", +"77FTF=:::Fkk7kmkF{T{WrDVyyyyssssWYEXKKoKKK33_3____3_vvAiciipAiA_3S_AAA,AS8o[o[CCC[[[CC[CC[[[ooo~o~o8oo~[8o8o8~3Sv_v,iixRRnR+n+%+rP+%+R(GcGliFLFiikk{RRnRhRRhPrr+r%RRR(R++rq}&'q6Prr++6r6&&gg$$ww55555599g&Ug$$yqV&V^DWN=!!uKKuuu!t:hDg&U$9$$$9$U$ggU&q6+h{km7:7Y", +"77m7:77F7777k:kkk{hWhrrVVVyyyssyDHEXKoKoK3u___3__3_3__AA,A,cpc,v333vAAv__~oo[C[CC[ooo[;oCCC[[o8~3~8~8o~883o8888~3__cLFxxRR+%++P6rr6+r{ki,,iLikikkkRRhRRRR{RR++++RRRRxRx(++}q&&qP6PRn+P6&'gg$$$$w<5599w$$ggg$gg&qq66D^W^I]!uuuKuuKuutthhVqU$$$$$$$$g&'6+R{kLL77t7", +"77L7k7LL77k7k7kmkThWrWrrWhTWWWyyWMB3KoK8K33___33_S_3__vA,c,A,Avv~383vvvS3~ooo[CCCo~u!Suoo[[[oo~33~3~8O~83~88oo8833SB,ikx%RR++%P6}P}n+RFil,iLikkkkk{Rn+nRxxRRhhhR(x(x(RRR+P6}&}qqrP+hr66&&ggg$$$9999w9$$g$$g$g&qVP6PP+W+=I!uKuKuuu!uttmmer6&yg$$UgUg&q%+Rkk7,777t", +"Lk7p7L77L7LFpkmk:kkT===:Y7GtHtDDnHEuOKoo33B_Bvvv__S333_vv,AccAv333K~33S3_8;ooo[oKuW&qhtu[[[[o88~33_S3S_333O888oo83_vcikxxR+++PrP+r+rRzkGvEc,i,,LkkxxRRRzRkkkxxRRxxxxxk(RR%Pq'qqP6++PPqqUg&ggg$$$9999$$g$g4$&g&q6P++NDNWN2uuuKuuuuu!LmhP66q&$g$g$U&U&q6PRxkL7L777", +"LLLLL,,,,7LLkkkkk:kkLML,GBX_BGaWTHE3KKKK33BvGvB,v__333S_vA,AAvv_8~K8883~3K8oo~ut=DyjsNv~o[[[oo83S__A__v_S33388Ko883vALikz(RR%Rrr+++RRkicBBvEccBcLFkkkkxkxkkxzkkxxkkkxRkR+PP6q6q66rPP66q&gUgggg$g$$$$$g$$$ggU&VP6^WhhNN==2uuuuu!!!!!0=6qgUgggg$UggU&qq6P+RRkL7pLp", +"LFiLiLiikikkkkkkkkkLk7i,cB_BXBEHYGEu3KK3_B,7777cvGB__33__BvvvvS33K88888388ooouAL{PVyTuo[oooo8883~_vAcAvv__338Oo8[88_v,LpkR(RRnRRnnRkki,vBcB_u_3BGLkkkxxzxxx(xxxkkkkkRxxR++PP6q6666r66q&q&ggggg$ggg$g$ggg$gg&qPPh+hNNhNN2!uuu!!!!*!2Y^V&g$$U$$g$$ggU&qq66+RRkk7kL", +"LkkkkLLLkkkRxxx{kkkLkLLGvB_B3_BGHEEXuXBEHFFkiG,GcLGvBK~___vv_vBu3~8o[oo88888o8_B,YW=Bo[[o~~8838K3S_A,,,,vS3383o8o88__cc,ipkkx(RRR{{FL,,cGvBX3X3_B,LiFkxRRxxxx(xkkkkkxRxR+P66666666P666q'&&g&ggggg&ggg$$g$ggqPDNhhNW===m!uuuu!!!22!tth&gg$$$g$U$$$gU&U&q6+RRRxkkk", +"xkkkkkkkx{Rkkkxkkkkkki,,vvv3B3KBXEEuXuBHFFTa77,GGG77,B33K___vSS3338o[[ooo8ooo8K_BGYGKCC[8833S33333_A,,,,Avv_333KK883_Bv,LiikkLiFiki,,,,,vv__u3BBB7kkkRhRxkkxRxxkkkkxR(x+PrP6r666q6666&q&'&g&ggg&&&&&gg$g&&qD^hh{N{mmmI!uuuu!!0Im0ptI^q$$$$$$$$g$$$$U&qqqP+RRRRxk", +"kkx{R{x{Rx{{xxzxkkkLkL,,vvv3_3K3uXBuEEEHWFFFF7GGG,77kGBKK3___3_3~388oC[[[oo~o8Kuv77uK[[[8~_S__333S3vA,pi,cAvv_O38KKK3_vc,Lc,L7,,GG,GGvG,vBB_B_Bc,,kkRRRhR{xkkxkkkxRxhRxRPP666666666}66qq&&&gggg&&6P6&g$gg&Ph{{N{{mmmt0!uKuu!IINhNkmm=Vgg$$$g$$g4gggg&qq6P+RRRRxx", +"RRRRRRRR(xRxxxxkkkkk,,Accvvv_KKK3uuX3BH7777GBvcB,GGkTT7B3KK8_S33388oo[CCo[8o883BB,Gu[[Co833vvvS333_SvAi,,,cA___33O8K33__vBvBBBBEcBc,vcvB,cvBBvv,ikkRRRnRxkkkkkxxkRxRxRR++rPPr666qqP66&&&&&&gg&&&PRRPPqgg&6+mN=mmmpmt2!uuu!2tNh+66PR=N6gg$g$$$$$$gU&U&&66P+RRRR{R", +"RRh++R++RRRRRzxxkLik,,vvAvv__3KKKOuXuXEEEvvvvBvE,,77ThTHu8KKK33K888oo[[Co[o8K33B777u[ooo833SAAGSS333vA,,p,,cAv333338K8K33___3__uBBBBBG,,,c,v,G,Lkk{RhRRRzkkxkk(RxRRRxRRrPP6666}qqq6q6qq&&g&ggg&66eRR+6qq6h{pLptpIttt*uuuu!20{+P6qqPhNDdU$$$g$$g$gUg&Uq66++h+RhRR", +"xRRR+++++RR(xxxkkkL,L,,,cvvB_OK3KK333_BBc,,,,v,vBGE7YWrW,338K88KK88K[[CooK883uBGGHG3oo8888_vv,vAvv3v3_AcA,cvv__333K3KK8KKK33uu_B_BvB,vc,7L,,,,kLkkRRRRRxkkkxRRRnRxR(RRR+PrPr66q&&&qq&q&&&g&gg&&6+Rx{{hPP+{mmtLt0tAt!!uKuut:{NP6qqqq6hhqg$$$$$$$$g4&&qqq6+%RR+RRR", +"RR+++R+R+RRRxRkkppi,c,Avcvv___333KKKK3BBv,,,L,GvvBv,GFWWWtXK8K88oooo[[[oK33_Bv,G77BKoo88833_v,LvvvS_S_vAvAv_v__333K38KoKKKKK3_3X__BvB,,,Lkikiikk{x{RxxzkikxxRRR+R(ekxR++P666q6&&U&&qq&'&&gggg&&6+k:tt=NWNtLtLtttttt!uuuu!0mh+6q&&&&&qP6gg$$$ggUgggU&q6PPP+R%RRRR", +"RRRR++++++++nx{kpiL,,,,,vv_vu333KuK33u_B,Lii,,,,vvBcG7FTWFGuK8Kooooooo[KuuBEE7777LB3o888333vv,A,AAvvvvvvv_vv__333333O88KKK3vBv,G,,c,LLLikikikkkkxRRzRxkkxxRR++++RhRx(R+PP66P6q&gUU&&&&&&'g&gg&6+h=LLttI=mLtttt,!A!!!uuu!t=h+Pq&g&g&&qPrq$$$$$$$ggg&&qq6P+R+R+RxR", +"x(RRRR++++RR+xRxki,i,i,,cA____u_33uu_BvLi77iii,,cvBBvG7FWa7_KK[ooKoooooKBEB7G7FF7FEK[o833~S_vv,,i,cvvv__v___3_33u33_3OK33B_c,,,,iLLL7i7kxkxzkxRxRRRxkkkxRRh++++++RRRR++66666qq&&ggU&&&&&&&&&&q6hNmt!G2ttt!A!A2A2!v!uuuuutNh66qqg&gggg&6qg$$$$$$gg&Uq66PPPR+RR+(R", +"xRx(xRRR+R+RRRxxppp,,,,,vvv_BB_33_33_BGLikkk7,7LGvvBBEGHTYHE38ooo[o[oKK3B777TWTTW7BKoo~3__3vvAc,,,cAcA,cvAvvvSuv_B_BvBv_Bv,LLkkkkkkkkkxkRRRxxR(RRRRRRxxnR+++PPP+++RRx+P666}qq&Uggg&qqq&&&&&q66PhNIL!2u!!!t!!!!v!!!!!uuu!LhP6q&g&ggggggqqgg$$gggU&g&&6qPP+++RRx{x", +"xRxexxRRRRRxRxxki,ii,,A,cvv___B____u_v,7kpkkki,,,,cB_XBEHz:G3Ko[oooo[KKuE7WWWDDWW7BKoK8S3___vvcA,L,L,,,AccAvvvvvvvvvvvvvv,Lkkk{{{xxxR{RxRRRR(RRRnRRRnh++++P6PPP+++RRR%66q66qq&gggg&&q666&&&&6P+W=It!!!!!!!G!!!!u!uuuuu!!mP6&&Uggggggggg&qgg$$$ggU&&qq66PP++RRxkx", +"xxRxkRxxRxxRxxki,,AAiAccvcvvvv_vu_vvB,,pkkkkiLiLL,v_v_3XHHFGBKKo[[[[KK3XGanrDDDDrHuKo883_S_vvvA,,Ai,iiiL,,,vcvvvv,,v,,,LLkxxkRhRRhhnRh+%R%+RRRRRRhhRR++PP666P6PP+++++PP666qq&UggggUqq66666q66DhNmL!2!!!!u!!!!!!!!!!uu!utNPq&g&Uggg$$$$ggUgggg$g$&U&&qq66++Rh{k{k", +"Rxxxxxx(xxxxxii,,cAc,,AvAcvvvvvvv__vvGLkkkkkiLLL7,cv_333EHHHE3Ko[oo[oKuBGYD}yyyyVTXKo88_____Acvc,,LLLLppL,LL,cc,,,LL,LiikkRhRRh++R+R++++++R++RRRR+++++PP666q6q6P++++RPP6666q&&ggg&&q66%6q66V^WN=It!!!2!!!!!u!u*!!!!uu!!LNqq&gggg$g$$$$gg&ggggggg&&U&q666++R{{m{{", +"RRRRRxexRRxxkppLc,,L,,,i,,,,c,AvvvvvvLLkxkpkkFii,L,vB33uuBHGGuKooooKK3uBGYDyy$yyyTE8o8~3_S_vvvvA,,,iLLiikp,,,,,,,,,LkiikkRRRhR+%+++++R++%+P%RR%RRR+PP66qqqqqq666P++++P666Pq'&Ug&Ug&q6PP666V+PWNmtt22!!2!!!u!!!!u!!!u!!!mh&gggg$$$$$$$$$gggggg$g&&&&&qq6P+hN{mxx{", +"+RRRRxRxRx(xkiLLLLipkkppkpiLLLLvvvvGALkkxxkkpLik,,vvB383XBEGHE3KooooK3uElYWyssssyWGKoK8__vcAcvcvc,,ipLpiikL,,,,LLiiLkk{{RR%++%++P%P+rPP+PP++RRRR%PP6qqqqqqqq&qqqP++++P6P66qq&&&g&Uq6PPP+PP^+WN::t2!22!2!!!!u!!!!!u!uu!tmP&ggg$$$$99999$gg&g&g&gU&&&&&6&6+{====RR", +"++RRe(RRReRxxxipikxkxxkxkkkpii,L,vGvLLkkkxkpkk7LLL,v_33KKBGHGuuKKoKKKuXGHzDysjjssDH3o833__vvGv,vA,,,,iLLpLiLLLLiLLLkk{xRRR++PPPPPP66r6P6P%P+%R++6%66'&&'&&&qqq666++PPP6rPP6&&&U&&&q6PPW^+W+NW==tt22!!222!!!!!!!u!!!!!!L{P&gg$g$$$9$9$$$$&g&g&g&&&&&&&q6Phh==mhhR", +"+++++eRRRRRRxxxxxxRRRRhxxxxxkkLLLA,v,Lkxxkkkpkii,L,,B3KKKuBGGXu3KKKKKXBEHaWys.5jsVTu8K~__vvvAv,,cA,p,piLLLi,,,,iLLikx{Rn+rPPrP6}66666666PP++++%P66qqq&ggg&U&&&qqPP%P666PPP6qq&q&&&q6rhhWhhW^==tt222222!22!!!u!!!!!!!*2tN6&g$$$$9$9$99$ggg&&g&g&U&&&&&qqPhN==m{R+", +"P+++RRRRRRRRRkxxxRRxRRRh{xR{kpiL,,c,ikk{xxkxkpLLL,cvv33KK3XGGGXuKKK33uBG7TWyy...jyWE3K8_S_vc,,,,A,i,i,LiiikkkiiLiikk{RR++Pr666666f6'66fqPPP%++P6&&&g'g&Ug4&U&qq6P++PP66PP666qqq&&&6P+hNWNW=Y:mtt22!22222!!!!!u!!u!!!!Am+qgg$$$$$$999$9$$&gg&&&gqg&&&qq6PhW==WN+R", +"PPP+P++RRRRxRR{xx(RRxRxRRxRxxxkpLL,L,kkxk{kkkkiiLL,vv3K8K3uGGGXuu3KKuXEEHTWVyj..5yDt3K83__vvcc,,cAA,,,,LL,iLpLkpkpkkxRn+%PP66r6qqq6qqq66P%PP+P6'&&ggg$ggggggU&qq6P+6P66PP666qqqqqqqP+h=====:IItt!222222!2!!!!!!!!u!A!tx+q&g$$9$9$9$9$$gg&&ggg&&&&&&&&q6+Nh==hh+P", +"+PP+++++RRxRx(xRRRRR+RRRRhxR{xkpi,,,iikkxxkkkkLL,,,v_3KKo3EEEGGX33u3uuBHHYDVs<...sVzuoo3_vvvA,,,,c,ip,i,LLLiLkLkkkkkxR+++Pf66'66qqqq'qq6P6P%+P6'UgggggUg$gU&&&&6P6P6666P66q6q66q6q6P+W{==Y=I:It222222222!!!!!!!u!!!2LmNP&g$$$$9$$999$$$$&gg&&Ug&U&&&q66+h==W=h++", +"PPPP++R+R+xRRRxRRRRRx+RRR+RRRxkxpi,LLikxkxkkpkkiL,,B_38KKKX!EGGEuXu3EBBHHYWVys....yWG3K83Svvvc,,,AAc,,piiLLkikkkkkkxxRR+PPP66qqqqqqqqq666P+P+6&&gg4$$$$g$g$gU&q&PPP6q66666q666666qPPhN=Y:tItII22I2222222!2!!!!!!!vGAtxh6&g$$$$99$$$9$$g&&&ggg&g&&g&&&66h+=W=Whr+", +"PPP+P+++RRRxxRRxRRRR+RRRRRRRRRkkkLL,LkxkxxkkkkLL,,cvXKKKK3uXEGHEXuXXuBEHHWIDys<..jsDY383K3_vA,,,i,A,p,i,LLkLpkkxpkkzRR+PP%66'6qq'&&&&'&'P6+P%6&ggg$g>$$$$$g$&&qqP6Pq666q6q66666q6P6PhWm=IY:It2II22I22222!!2!!!2!!!ttmN+&gg$$$9$9$99$$$gg&$gg&&&&&&&&&6PrNW=WNh+P", +"P6PPPP+PR+RRxRRxRRRRRRRRRR(RxRRxi,i,,ikxkxkkpkkL,,vB38ooKKXEGGtGEEuXXEEHHTWDVys..ssVWu3K33_vvcAc,,,cL,LLL,i7LkkkkkxxkRn+PP666qqq&&'&&666PPPP6&&gg$$$$$$$$gg$&&&q666q6q66qq666P+P6PP+N{m:YtIIIIII2II22222!!2!2!0GAGtLxhP&&g$$$$$9$$$$$g$ggggggUg&&&q&q66+hN===WhP", +"PPPP+P+++R+RRxxRRRRRRR+RRRRxRRxxkp,i,LikxkkpkLLi,Gv_3KKKK3uBEGGGEEEuEEGHYYWDys c #244484", +", c #795C50", +"< c #2B4384", +"1 c #304D78", +"2 c #5D5B58", +"3 c #FCFCF4", +"4 c #1B3363", +"5 c #8DD9F0", +"6 c #233C7B", +"7 c #74BADE", +"8 c #D0C89D", +"9 c #5F6859", +"0 c #827B78", +"q c #233C6D", +"w c #2C3C65", +"e c #28448C", +"r c #2C447C", +"t c #2C3C7C", +"y c #FFFFFF", +"u c #1C346C", +"i c #243466", +"p c #334971", +"a c #2C3C74", +"s c None", +/* pixels */ +"55555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555", +"555555555555555%5555555555555555555555555555555555555555555555555555555555557555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555", +"5555555%%5%%%%%%%%%%%%%%%%5%%%55555555555555%55%%%5%%%555555555555555555555555555%%%5555%%55555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555", +"555555%%%%%%%%%%%555555%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%555%%55555555555555555555555%%55555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555", +"555555%%5555555555557555555%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%555555555555555%%%%555555555555%5%555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555575555555555555555555555555555555555555555555555555555555555555555555555555", +"55555555555555555555%%%5%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555755555555755575555755555555", +"55555555577555555555555%%%%%%%%%%%%%%%%%%%%3%%%%%%%%%%%%%%%5%%%%3%%%%%%555555555555555555555555555555555555555555555555555%555%5555555555555555555555555555557557775555755555555555555555555555555555555777777555557577557577775555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555557555555555555555555555555555555555555555555555555555555555755555555555555555555555", +"5555555555555555%%%%%5%55%3%%3%3%%%%%%%%%333%%%%%%5555%%%555%%%%%%%%%3333333%%%%%5555555%555%%555555555555555555555555555555555%55%55555555555555557777777777:77777777777755757777777777777777777777777777::7777777777777:::::77777777775575555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555557777777777555755555555555555555555555555555555555555555555555555555555555555555555555555", +"55555555555555555%%%%%%3%%%%3%%3%3%%%%%%%333333%%%%%%%%%%%5%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%5555555555555555555555555%%%%5%%%%55555555555555777::>>>>>$:$$$6q$6r<>>::::77777777777777777777:7::>$rrrrqq$q$q-$$$>>6$>>$r<::::::::::7777577757555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555777777755555555555555555555575555575777777777775557555555555555555555555555555555555555555555555755555555555555555555555555", +"5555555555555555555555%%3%333%%3333%%%%%%%3%%%%%%33333%%%%%%%%%%%%%%%%%%%%%%%%%%%55555555555555555555555555%5%5%%%5555%%%55555%%5555577777::::::$u-rr<<<$$q$6qq-qq-q666qqq--<:<::>:::::$$>::::$$<<:rr11:1$r$:::::1::::::<<:::::::777777777775555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555557777777755555555555%5555555775555555557777777777575555555555555555555555555555555555555555555555555555555555555555555555555", +"55555555555555555555555%%%%%3%%333%%%%%%55%%%%%%%%3%33%%%%33%%%%%%%%%%%%%%%%%%%%%%555555555555555%%%%%5555%5555555555555555555577::11qrr6u.11107700775555577777:0::::::>$quuuqqq qu.qrqurq1:::::<::11::75577777777:7::::::-6::77777::7:$q:77777::7755%55%%%%%%%%%55557777::::::1:rtrttrt$rrrraqq$<<<::777777755555777::11r1<$$rr$$$6:<<::::::1::::::7:7777777::::::::::::1:::1::771::::7777777777777777777777777777777777555555577577777757577777777755577555777775555557777757775555555555555555555555555555555%555555555555555555555555555555555555555555555555", +"5555555555555555555555555555555%%%%%%%5%%%%%5%%%%%55%%%%%%55%%%55555555555555555555555555555555555555555555577::::::1:1<$r1r1q 1775555555555%7755775555555557777011r--$$<7557555%%%55%%577%%%%%%%%%%%%%%%%%%%3%55%%%%%%57777:7777::::::::::77:1666$q---66q100000011p*001007700777000075555555557711$1075575%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%33%%3%%%%%557777777777:16q6666$6$6$r1<$$$p000757770101ip1;0w22000075%%%%%%57011$---<175%33%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%3%%%%%%%33%33%55577777:1q6rrrrrrar$rr1$qqq--q-q-q$$rr<1<$$<>>>775555555%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%3%%33333333%33333333333333+%55577:1rrrrrrrrrr$aaq6r$rrrrr<16--1:77555%%%%%%%%%%%%%%%%%%%%3%3%3%%%333333333333333333333333333%577757:w11rrrrrrrrrr$r$tqrrrr<<$a111r1<1111 a12221;000122;20000071:7771<$$$>>6>$6<1:555555777775%%%%%%%33333%33333333333333333333333333333333333%%%%57::rrrrrrrr$rrra$qaqar$rrrrrrrrrrrrrrrrrrrrr<$1<1pp<1r<100000:<<<001::1q1p11101000rrr11r.p000;p1ar w11:77701rq6>>>$>>$>>$6>><<$$>---q->1:75%3%%33%3333333333333333333333333333333333333333%5771111r$rrrrrr$r$qqqqqrrrrrrrrrrrrrrrrrrrrrrr<$$>$>$6r<6t>e::e::7777577::0;;07007087%%==%%%%5555%%%%%%%%555555555555%%%%%%%%%%%%55%%%5", +"55%%5%%%%555555%%5%%%%%%%5%%5%%%%%%%%5%%%3%5555%55%%5%55555755555555555577:>$$$6q-q-q-6$t<111111100111111aq16$6>$>6$>>$>>6>>>$>>>>>66-u:7533%33333%3333333333333333333333333333333333333%57::1rrrrrrrrrrrr$qaqqr$rrrrrrrrrrrrrrrrrrrrrrrrr1$rr$rrr1r$r<16>6>6>6>$>>>$>>>>$>$$>>><<$rrr:::::::7777::::7775555%%5%%5%3++++yy++yy+3%33%++++++333%%%%%%%%%%%%%%%%", +"3+3%5555%%5555555%%55%%%%%%%%%%%%5%%%5%%%5%%%%%%55%%%5555555557:111>$$666<$$$qq10000000001:r$rqqqq6qq6$6111rq$qq<:111< q2000001ruq11121-$::::1777::-6>$>$>$>>>>$>6>>$>>>r><$r$t$:5%33%33333333333333333333333333333333333858000;11rrrrrrr$r$rr$$rtqq$6r$rrrrrrrrrr$rrrrrrrrrrrr1rr<1>>12::::::ra::::7777777::::2;;::::::::::77757007000878%%%5%3+++++++++++++++++++++++", +"5%%55555555555%%577777777775%%%%%%57:77:::::::::<<1::111:::::1$6$$>6r$$$$$$$6q1000000001101001<:<$r16>6>>6>>><$>>>$$>$$>$<175%33333333333333333333333333333333333%7711000rrrrrr$rrrrrrrrrtqqqta$rrrrrrr$rrrrrrrrrrrrrrr<$>>-$6q-6q--qq-qq6>:::::775%%%%%%%5555%%%7075555", +"4rr 177777777557::::$uqq.w1:17557:$---6-66>>6>>>>>$6>>>666>>6>>>>$>$>$$$$$tq100000002<10000000001:001100;1.aa11100;0;1up21.qqqq2;0;;r19;;;;01ppp05%7:$q--6$$>$>>$>$>r>$>><$<$rt>:775%33333333333333333333333333333333%%%8800121rrrrrrrr$rrrrrrrr6$qqa$t$rrr$rrrrrrrrrrrrrrrrr$rr$rrrrrrrrrrrrr::>>0000000001:001::>$$r6:<$r6qa11p1r1aqii44wwX4444ii4", +"pp.44rr$$$$$$$>>><><><<>>><><<><>$>>>$>$<>$$>$$6$6tt1100201u1100000000000000*0;90:qqqq.a1:1*a12;16><>$<$<>>$>$>r$::71:053333333333333333333333333333333335000;77::6rrrrrrrrrrrrrrrrqq6q$rr$rrrrrrrrrrrrrrrrrrrrr$>$$t$$6$66$$$$aqq-qq.qu....444ui.i4wp", +"211u.qqq66$666666q$6r$r$6666r111*111:1<<$$>$>$>$>>$>$$$<><><>r$>r>$$$tq66$$q$qqqa1qqq$q111010000009;;9999901$rr6qqqw.q1099*91$qaw1222;0000;00002;0,08570770:::66$<$>><$<$<$<$<$>rr$:::17333333333333333333333333333333%%%%5:u:071rrrrrrrrrrr$rrrr6r$qqqt$rrrr$rrrrrrrrrrrr$r$r$rrrr$rrrr$rr$$$rr1p121pp22021<$<1<1<<<<<1>66>r$$$$6$6$6111w11$<$>$>><$<$>r6>7777:7533333333333333333333333333333%075755711prrrrrrrrr$rrrrrrr$aqrt$rrrrrrrrrrrrrrrrrrrrrrrrrr$rr$q.q. 1wi111ar qww44444", +"uuu.qqqqtq$tqr$6$$r666$<0000;29;;;;;;;;;;;00;999999;;111::<$6q$111111200010:11011099111$q1101************12*92:awr$10911po*****rr$<><$<$>$<:77:1p7%33333333333333333333333333333+33357:1rrrrrrrrrrrrr$rrrr$6aqqrrrrrrrrrrrrrrrrrrrrrrrrrrrrrr$r1r120@;9;000000000000000011111r$>r><>r>>><$$66-q$17%3333333333333333333333%%3+%%%5777:6qr$><$>>$r<110%333333333333333333333333507121wa66trrrrrrrrrrrrrrrrrrrrrr6qr6rrr$rrrrrrrrrrrrrrrrrrrrrrrrrp12;;;OO*99O9;;9;9;;;000000000000000011rrrr10011rr<:00000;0000000000000@@;;;;;,;;;000pr0@@000;,;;,,;,;;;,;;,,,,2,O,2OOOOOOOOOOOOOOOOOOOOOOOOO,2000,;;&;,,,,OO0=888888080&@,,,O,,,,,2;;,,O22222,,,O,2;;;;;;0000;00;;00000000000000000000000000", +";;000;*qq quqqqqqq$quqp;2;22222222200099222099O22929O2299**99999999999999999*999999999999999*9***999*oo9999*****99;9999**99******9;110020000$r$>$>>r>r<:1205+3333333333333333333+y%01qqqt$rrrrrrrr$rrrrr$rr$rrrrrrr$r$qaqrqrrrrrrrrrrrrrrrrrrrrrrr$rr$rp;@;99*9O999;;;;;999;9;;00;000000000002arr102ar<000000000000000000000;;;,;;;;;;@@00pr;;@@;;;;;;,;;;;;;22,;,,O,,2O,,OOOO99OOOOOOOOOOOOOOO2OO,,;;@022OOOOOOO2O,;080888808&,;;;O2,,,,,,,;,O,,,,2,,,,,,;;;;;;;;;;;;;00;00000;0000000000000;00000", +"000;000p10::<-qqqquqr1<.wp*oo*229;2922929999999*92999999999999999;9999*9999999***99111992999999*99999*o*999*****99922;99O99*******9;;1122011q6a$66qqqqr1100X;00;;08%777::6rr>r>$>$$<::008+33333333333333+%%%%%51qtrrrrrrrrrrrr$1<$$$$$$$<<$$r$r$rr6qq6rrrrrr$r$rrrrrrr$rrr$rrrr-1*1*9*9999*9**999999999***9**929**O99******22;00111rrqqq$6t$q6qq-10000;;0001XX0070:rr6$$>r>r<$r:75773+33333333333+3%7:711aqrrrrrrrrrrrrr11001rp12p1;001$rrr$rqq$q6rrrrrrrr$rrrrrrr$rrrrrrrr$p0;99OO929;@@@0;;;0;;,;9;;,;;000pa1<111<100000000000@@00;;0@;;0;;;;;;;;,,,;;,;;;;;;;;;;@@@;,,;99;;;;O,,O,,,92,29O99,9,99OO9O9OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO2OO8808388;0&8@O,,O,,;,;,,,,,,,O,,,,,OO,;;;;;;;,;2;0008@08888&@0;2;;0;;00;;0;;00", +"2u**p1;000012p...wp0;0;0;;22922***9**9292*O*;9OO999*9999999;999999999*9*99******::$***9**9**9****************o*****9999***********20rp;11:$qqtq$611:1:1000*O;;00:>uw111r$$$$r>$>r>rrap017+33333333333%50111qq$rrrrrrrrrrrrrr$111;000;000070;16$rt$6qqarr$rrr$rrrrrrrrrrrrrr$rr$$p;@OOOOOO9;;;0;ar6$1;;;;9;@99;0;01rr11aa1000000;0000@0@;;;;;;;;;;;;;;;;;OO;;9;,;;;;;;;;;;;;,;;29999929,99,9,,99229O9O9O9OOOO99O9OOOOOOOOOOOOOOOO9OOOOOOOOOOOOOOOOO,,@08=8808&8;,O00,,OO2,,,O,,,,O,,,,,,2,;;;2O2;O00O,0800088@;0;;0;;;;;0;;;00;0;", +"..4uu4ip20144uii..41p1*p*wp222**O*2**22*Oo;0080O*999999*999999999999*9999*9*********9999****99*9****oo*******o***oo***************11 1;0000:-$rqq10011*200100000007$.r$$tr><>$r$r$ta11%+3333333333%7-tr$rrrrrrrrrrrrrrrrrrr<<10000755%5711rr$rqqqqr6rrr$rrrrrrrrrrrrrrr$$$$r2;@,*O9OO9;;@;02$$r20;999,;2;;;@9;011100020000;000;;;;;9;99;;9;,;;;9;;,O,,,,,,2;,;,99;;;;29;999299999O,9,,,,,O99999O2OO99O9O9OOO9O9OOOOOOOOOOOO9OO,,OOOOOOOOOOOOOO*22O;8&8%=388%888800800;;;;,,,,,,,,,,,,OO2O,,O;20&,O58=888088&0;;;000000;002pXi", +"u4.4u.uuiw..w .i...iuuuuu.w2O2*O*90*9O;100%78%5700O2O9999*9999;9,99999999**99**9999********99999****9***o**o******oo************111 120001*211qqrr1rqqq.p20000000,01<66$>>$>r>r>r112992**O9O0009O998%8000&88800002OOOO99999999999*99**9***999***991****99***O******ooo****o#***o*2**9*9***rqqqqrq11 r<1rrqqr<$r>rrrr::8+3333+333571rrrrrrrrrrrrrrrrrrrrrrrrrrrta1<1t6q$>>>$>r>rtr$t::73+33+33+%7rqrrrrrrrrrrrrrrrrrrrrrrrrrrrrr$$6$rrrrrrr$r6qq qqrqr$rr$rrr$rrrrrra2;;,999OOOOO9;;;016$rr@@;9O92292222;@,,,9;;@;@@@;;;@;;;;;99999999999999O99,OOOOOO,999;;;;9999,,99,OO99O9O9O99O9OOO99O9O999OOOO9OOOOO9OOOOOOOOOOOO2OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO;@083y38%3%8880;;02O,;0;,8,03+==8,,OO0,XXO20;;;;;0%%8880000100#", +"..4i4......i..ii..ir0222222O****OO99;28%;O*99;009000&08870000;O02999999999O******9***9*9999*1-#1*****O***ooo*ooo*********9*aqq6q6qq6qqqq6wqqqr1ra;;000;001quuu4iw1r$q$$<$<>>>$$t$$1*************oo*oo**oooo***2>>>r>t>$>>><>$>r$<>r<$<>$>r><$><><>r><<$<<<$><><<><><>r<$><><><r<<><<<$r$rr$r$rrrr>rrrrrrrrrrrrrrrrrrrrrrrr$rrrrrrrrrrrrrrrrrrrqr1*99***p. q q$qtq61191a;@2;900qp01r$p;;r1@,,9O9,OOO99999O999,,,9OO999O999OO9999O9OO999O*OOOO,;,9999992999999999999O9O9OO99O9999O9OOOOOO22O9OOOOOOO,OO,,OOOOOOOO2OOOO2O9;00;O880080888@200,0888&0080808;98%=0*waarqrqtrr$tr6$rrrr$rr6$OOO7+8022i4i.i....4i4.4..4..4i.4i", +"...4i.....................44r1002w4.1*..uiu........i.......4ii4****;*OO;0080*O90009O****99,99*99*9***o*9*****oo**oo*o**o*****999*11qqa66qqa6$qwrq$q2;2;;222;;;p;;;;;,;0;:6>>r>r<><$<<$rrrrrrrrrrrr>rrrrrrrrrrr$rrr$rrrr$rrara2;9O9*.. q$q10;;p-p;9;;0;r11$rr0@,;;,;,,9999OO9*O999O9999OO9O9;9O99OO9OO9999O999O999OOO;,9,,99999,9,,9999,9OOOO9O9OOOOO,99OOOOOOOOO99OOOOOOOOOOOOOOOOOOOOO2O9OO,,;;08088&888008808808&00;058000O,838&;wq6$r$r$tqr$t$6r$t$6$q$6a2OO53&&OO1w......4..4..4i4i.4..4..", +".4.i4.4........i........ir1100144u ..u....4.u.......iii.iu....i4w*2**9O2;0280;2**O**99***999999**99**oo*9****o*ooo****o******9999;911$qqqqq$qq11qq1;;222,222;;220;;;2;;;1<>$r><<$<<<<$r$rr$rr$r$rrr$r$rrr<$rrrr$rrrrrrrr$>r<$$><>rr$rr$rrrrr$r$rrrr$<r1111p9O99*.q #29;*0;p;pr6$$rr$r19,,,,,9,,O9999OOO9OOO9999O99O999O9999O9999,9,99,9*OO9O9O99,@,@@@@;,,;@@@,,;;,,;,999,;,,,,,,,9OOOOOOO29OO,OOO,OOO,O2OO2OOOOO282;;OOOO;00;088800888=8808=88==8=80888;*w1rt$qrr$rtr6rr6rt$$$r$r$$r2O0=@O;,,w4.... ..4....4..4.4..4.4.", +"4i4.4i..ii...i...i4..w11w.ii............4..4.......i..i4..u.i.4..i.wiX**O*OOOO*99229OOO99*O****OO**************oo***ooo**oooo**O**;;122;;;;a q 12;;,2222OOO*o2,,9p;;;;;;,20011r6$666$t$r$$$r$r$r<$r$rrrrr<$rrrrr$rrrrrrrrrrrrrrrrrrrrrrrrrr$rrrrrrrr*9991**O9;*w u222*21p161r*2;21;,,9,OO9OO9OO,99OOOO9O9999999999,9O9,,99,9;@9,@@;,,9999O,,,9,,@@@@@@@@@@@@,@@,;;,;;;,,,@@;@@,@,,OOOOO2;,9;00O0O;0OOO,OOOOOOOO001090O;,O002888800888&@0;,@;;,,0&80O,,Oop*1$r6$qrr$a$t$r$$rt$t$t$r6*O8&,OO22p4..i. . ....4..4.4..4.4..", +".4..ii..i.i.......1ai.ii..........................u......ui......4r1#4***9OO*O*29O200;09O29O9*O***29*********o#*oo*o#****oo******9;22;;2;;; ...20;2OOOOOO*****2OO****22;2;2*20p$66qrr$r$r$t$rrrr$rrrrr$r$rrrrr$<>r$r$$rr$6*,2au q..........4...4.4.4.u.4....", +"..4....u.ui.i.....i......................u....................4..4.i.4.4iq*900900****O*O*90009O929*2**9************o*9o****o**oO**O*******2*******o***o*o*****o**O*O;9;0;;;;p*a1p.qq$rr$rtr$rrrr$rrrrrrr$rrrr11$12O9OOOOOOOOOOOOOOOOOOOOOOOOO9O9OOOOOOO,O,,,OO,,,,@;;,99O9;;9@@@@@@@@&@&&&&@&@@@@@@@&&&&&&&&&&&&&&&&&&&&&&@&&&&&&&&&&&&&&@@&8&8&&8@O;00,@;&880;O,,;,,,,@;0&888%8@@@@@@,;,,;888888,,,,,,@,,@,O;,,,2*,8@O2rr,O;r$r><>r$<<>$$6$qq.q...........u.4....u...4...", +"u.u.uuuuu...........................................u.........4.....4.4.4.4uw292X**O*****O*o0070***O992******************#****O***o********oo**OO**O***O**oO***pp*22ww11iii4w0;;;201q6$t$r$rr6rrrrrrrrrrrr$r$r$rrrrrrrrrrrrrrrr$rrrr>:<$6r66qqqq......u.u.u...u.u...u...u.", +"...u...................................................4........4..4.4....4.44*9*oO*9**O***;*O00OO**O999*************************$:-$******o****O*O**ooO*o**9*o*OO2;p44iiii 00;;;0;1rqa$r6rt$rr$r$r$rr$rrrrrrrrrrr$rrrrrrrrrrrrrrrrr<$<$>r><>>$<$$$$qqqq.uu.u.u.....u....uu..uuuu", +".u...u.u............................................................4.4.4..4i4X992*9929*9**;*O*oooO9*O9O*999*2********o**o*****p6::>--$o******o****oOoO**OOO****OO214ii..iiw12122021< qqqaq66r6rqr$rrrrr$rrrr<$rr$rrrrrrrrrrrrr$$t$6qququq..uuu.uuu..u.uuuuuu.u.", +"..u......................................................4..4..4...4.4...i.i4i4o990;99OO*2*O**2**o*O**O*999999***************ooq1**$-$$#*OO*****o*o**oO*Oo**O**OO,;*. i.ir ii4i4a1i10. aarqt$6$a$a$trrrrrrrrrrrrrrrrrrrrrrrrrtap,2$<r><<$>r$r6$6qqq.quuq.u.u.u...u......u.u", +".u.u.u..............................................................4.4.i4.4i44o99999222**o*00*000*o*O*O*O9**999*****************OO**9;91******o***oo**OoooO****9O2;111 1riiiiiiiii... wa aaqqq6qq$6r$rrrrrrrrrrrrrrrrrrrr<<<$<>r>r>$$<$r6qqqququ.u.uuuu.u.u..u.u.u.u.", +"u.u..............................................................4.4.i.....i4i4*;9909OOO*00000800000*o***OOO*99******************OO**$121::1$1OO****OOoo*OOOO**O*9**2*2111#ii.iiii...... w qqqqqqqqqtr$rrrrrrrrrrrrrrr<<<<<$r>r<$<>$<$t$6qqqq.u.qququ................", +"...............................................i....4..u....u..u....i.4uiui4i442;900999**20000800;000o00o*O****O*o*************O***o:$9;9*>>11oOO99OO**o*OOOOO*9ow1**9**w4i..iii....... ..... . q qaq$qr$rrrrrrrrrrrrrrrrrr2;1>><<<11r<$>$<$t$$6qqquuq.qu.q.qu..............", +".u.u............................................i.i...............4..4.i4i4.iii*;9999999O**00008000802*7*oO***o********************o-99991$$992***1*******OO*o#w4.*;p.i4ii.i................... .. qqqa6rrrrrrrrrrrrr<;,;211<<<><><$<>r>>r>$$>r$66qq ..q.qq..................", +"...........................i.i..............4.i....u..uu.u.u........i..4i4.4iiw99OO9,9999O2990000;08O008;***O***********O****OO****$>*99*9*pOO91##>#********w4i4i.p#4.i...4........................ . qqqr$rr$rrrrrrrr$<$$>$<$$6r$qqqqqu.q....................", +"................................................i.............u..4.4..4.4.iii.i9999999999999;9220;880;0000**O*O********************$>**9*9O2**>1******oooo*$4i....44........................... .. .... qrqtrr<$<<$$$$<$>r$6qqq u...........u..u..u..u..", +"..u............................................4............u.......i..4.444i4i*99O99;999999;0;O000;0;00080*OO**O9*******O*********1$**O*O1::>1***o***oO*O91...ii....................................... . qa$t$rrrr$<2@,,O;,,,,,OOOOO9*. 4;24ip;;@@2*4i4X2@,;;;;;;,@@@wiiiiw*922oXiiii.44;&&@@&&&8&;www4909&8&&&&&&&&&&&&&&&@&@@@@&&@@&&&8&00&888&&&&&@@@@@@@&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&@&&&&&@,200OOOOOO9OOOO,OO,,2p6r<$<r>$>$$$$6r$rt$66qqqq..........u.............", +"..........................................................u.......4.iui.4..4ii4o9922990;99;99@8;28000985050o*OO999**99**O*O*O**************o*****o*ooo*O*oow.4........................................... . qq66$rrrrrr<$rr*;;,,;;,,,;;,;2*w . . .*2i.iw;;@&02w44*&@;@@@@@@&&&;2**;;@&&&&0;*w*op;@@&@&&@@&8&0 .p1q9&&&&&&&&&&&&&&&&@&&@@@@@@;888000&8&@&@@@@@&&@@@@&0&&&&&&&&&&&&&&&&&&&&&&&&&@&&@@&&&&@&,,,,OOO,O22OO,OOO,,,*6rrrr$r$$6tq6q6$6r6qqququ..........u.u..u..u...", +"...u..............................................4.............ii.i4iu..iu.4.i*2*0099;;;;29;@8&O8%80o28800OOO*99999999**O*OO*********O***O******ooo*O*o#.4i...4......................................... . qqaq6r$rrrrrrrrr<$<<<<<<<<<$r$$$tqqaq .. ...............................u..u..u..u........", +"...............................................................i.......i.4.......ui.4.4.4.4.4..4.u4p14.4X;O,OOO*O****4...4u.u.uiu..u..u.4woooo4uuu4.. .u...................................... ....... . . . . . . ..w. . .. ....iw4w=88&&&8&&&&&&888&88888=88888&&&@&&&&88&8888&&8888&@&88&88888888=88888&&&&&p rr0;;@@&&&&&88&88&888&8888&&090piwXwXwXwwX.4w;@;@@,@@,@@@@;,,@@@@@@&@@@;;;00;;2O,O,O,OOO,,,OOOOOOO,,OOOOOOO929991$rrr*,2r<<<rrrr<1;,,O9,OO2OOOO9992OOOOpqq#2X.i.w. w wqaarqarqrq$qqqw . . . ... . ... ....................u..u...u...........", +"..u..............................w# ..........4................i..4...4.u.u.u..u.u.444.4.4.u.uu.uu4u.u.u4i2***oOOo****wu4.4u.44o*oo*.u...u..u...u.oooo..iu..u....................................... ... .. . .... . . .... ...i..42==88&8=8=8888888888888888&&88888&&&8888&&88888&@@@@888&8888888888888888&8&@@pwi*000&&&&&88&888888888888880pXww. w..wiwXwiX.X442,,@@;9,@@@@@@@@@@&01rrrr1rr12,;,O,,OOOO2999O92Op. .#*pi....w wqw$wqqqa q .. .. . . ...... ..................................u....u....", +"................................i4*1............i....................4..u.....u.u..u..4.4.u.uu.u4..4.u..uuX9***Ooo*oO*o4.u..uuiooo*ou..u.........u.i...4oo*oo....................................... . ... . .. . . . .........wi.i4;=8888888=8888888888888888888888&&&&&888888888888&&@&88888888888888&88888&&&;p.w4p&&&@&&888888888888888888wiww w wwww.w.wwXwwi2@,@@,,@@@@@@@@@@@1rrrrr6$aaqaq qq q q q q q q . w .2,9O999,999999,,;;;,;,,,,@@@;;@@;210&@@@@&@@@@@0w.w w w w w.ww w w. w w . w w ww ww.w.wwww ww.ww.w.ww..ww w.w wwXw.ww.w.w.X.iwwo9;;@;2pwXwiXw@@@@;,2222,@piX*44.Xwii.iw1wwpp1X*pi... . . . . ...............................................", +"............................................u....u..u.u4.......i.i4444i4iii4i4i4i4i4.4i4.4444u.444.u.u4u.4.u.u...u..u..u.u..4...44.4.i4.4...u4;*ooo*oo**o*oooooooooo*oooo**o**o**O*******1::>rtrr6rqqqqqq qq q . q . . w229,O;,,,,,92,,,;;;;,,,@@@@@@;@@2r<0@@;@@@@@&@;#.ww ww#w w w w ww w w ww w www ww.w w.ww ww.wwww.w w.wi w.w .wiw....w...w*4*,,@,9pX4Xw.i;@&@,O22O2@;w4w;o*;;2iiiiw*wiwp;@@;*wp*.... ..... w.w..... ..................................4.......", +"........................................u.....u.......4..4.u.i..i.iiii4ii4ii4iii4i4i4.4.44.4.44..4u.u..uu.4.u.uu.uu.4.u.u..4.4....4..4i4..i.4p2oooo*o***ooo**oooo*o*oo*ooo*o*******o**O****:1#a$qtqaaqaqqq q q q q q qq q q . .*;;,;,,;,;9,,;,;;;;@@,@@@@@@@@@&2<0@@@@@@@@@@@p.ww ww w # ww.w w w w ww. w w ww .w w.www.ww.ww.w.www. w.ww. .w www X .iw..X.i*oX9O@@@9w;wiXwX;&@;O2,,@;iii*&@@;**p2ppi*w4***;@9;w 1po*wi.. . ww.ww..w .....................u...............u....", +"................................................u...u...........4.i4i4ii4ii4i.4....4..44..444u.4.4.4.4.4.u.u.u..u.uuu.4.4u444i...4.44.4.i4..4;2oooo*oo*o***o*o*oo*oooooo*ooo*oooo*o**********oo#1>t$qqqq q . .. q .p0;;9;,,,99,;9,,,@@@@@@@@@@@;,@@20;@@@@@@@@@;p.wwwww w w w. w.w w w w w w ww w .w .w.ww w w.w w.w w ww..w.wwwiw..Xw.w.w.ww...4p.2@O,@,202.pw42&&,O,,@@24ii2@@@p4Xw*p#4Xi4wp4w**;w4#*OO9*pw.i.i...pp ..p# ........................................", +"...................................................u..u....u..i...ii4ii4i4i..4..4..4..i.4.4.444444..4.4.u.u.u.u4.uuuu..u.44.44444.444i.i4..i400ooooo*o*ooo*ooooooooo*oooooo*oooo******oo*O*o**OO*:$ qqqq w q q . . q q q .*@,;;,,,,,,,,,@@@@@@@@@@@@@@@@@@@@;@;@@@@@@p.wwww ww.w w w w w.w w w w w w w w w. ww.ww ww wwww w www.w .w w..w..ww..wi.X..XpX;,,@@@0*#9wiw;;@;@@@&2i.w@@*;;wii4X2*w;;;2iw2,;2#**99*OO92w ..... ...ww*w i............................u.u......", +".........................................u.u..u.....u..u.u.u.u...i.4i4ii4i4i4.4..4i4.44.i444.4.4..4..4.u.u4..u.u...u.u.4...44i444.4.4.4.i.i44p*o*oooo***oooo*oooooo*oooo**ooo***o***o*OOoO**Oo*O*1O21121 q . q . . 4*0;,,,,,,,;,@,@,@@@@@@@@@@;@@@@@@@@;@@@@&;.w wwww w ww w w w w w w w.w w w.ww wwwww. .ww w ww w..w. ww.w.w..wi X ..w ...iXXX;;@@@2iwwwwi4X*ww2@;*iw.*;w,@*iXii2;w2*X;w4p;2;99O**O**O9O91a.... ...iw##w.....................................", +"......................................u..qu.q........u.u.qu.u..i.....i4ii4ii.i.4.i4i4.i44i.4444444.4.4u.u..4u.u.uuu.u.4.44.4444i4444.4.4i.4i4q1ooooooooo*ooo*o*oooooooooo**o****oooo*o**O******29O,;;,&&;#.. . .q q w. . i*;;,,,,;,,,,@@@@@@@@@@@@@;@@@@@@@@@@@@&@*.www www w. w w.w w..w w.w w www w w ww w w w www. .wwww. ..w.w .w..w.w..wiw .w.Xiiw;@;@2iw.X.w..i.iXp..wiw4;*w@;wXi.44iiii4wwiXiw29999*O*OOOO**1ri.i...4p*p......................................", +".................................uquq....u...u..u...u.u.u..u.u.4..4....4iii4i4i.i4i4..4i44444.44.u4.4...4.u..4.4u.4u.4.4..44i4444i4..i.4i4i4#00oo**o*ooo**o**oooo*ooo*oo*oooooo*oo*oo****OO***O*OO,,,O,@@;r..... . .... . . . . . 2;;,;;,,,,,@@@@@@@@@@@@@;;@@@@@@@;@@&@;ww.w.www ww ww.w w w.w w . w w w w .w. ww w.www .ww.w..w.w.www.w..ww...w.. . ...i.X.X2;@94iiwwiwX..wwiwwiwi#0oX*;p.wiXiXiXiiXwwwXw4.p*9*****o*OO91..#ww##9*ii ............................u......", +"........................................u..qu......uq..uq.....u.....i.4iii4iii4i4i4i4i4i4iii.444444..4.4..i4.u4.44.4..4.4.4i444i444.4.ii4i44p80oo*o*oo*ooooooo*ooo*ooooooo***o*o****oOo*****OOOOOO22,O,@@@211$.w . . .. . .w...q$1;;;,;,,,,@@@@@@@@@@@@@@;;@@@@@@@@;@@02w.w.w w w w w .w .w.w w.w ww w w w w w . w w. w.....w.w.w.w.w.ww..Xww.w.. .w.w iiwi4**2o*w.i.iiiwi.w.X.wwwpp4XpwwiXiiiiii.iw1p#2iX441********2O9*p#**11pX4..1.4.................................", +".................................u..u..q........u....u....u....u..4..ii4X4i4i4..i4i4i44444.4..4.4.4.44.u4.u.4..4.4..4..4.4444444i44.i4i4..44X0;oo*oooooooooo*oo*ooooooooooooo**oo**********OO*OOOOOOO,O,@@,2**$i .... . . . . w. $r;,;,,,9,@@@@@@@@@@@@@@@@2@@@@@@@@@@;@0ww.w.w wwww ww w w w w w .w w w w ww www w. w...w.w. www.w w.w.w.w...w.w.w. ..wii..iiX2@;;2ww**pwpw w.i.XwiwXXiX.i.XiXiXiXi.i4124.ii$*O*****O**O;;#iw#.i...i#1ww................u...............", +".....................................qu..u.q........q..u...u..........4i4ii.4i.4i4i4i4i4i44.4.44444u.4.4.4.4..4.u..4..4..4i4i444444i4i.4...4.00ooo*oo*ooooooooo*ooooooooooo*oooo***o***oo*OOOOOOOOOOOO,,@@,OO;1iw. . . q . . .2;;;,@,,@@@@@@@@@@@@@@@@;0@@@@@@@@@@@0p..w.www w w w.w www.w w w ww w w w w w . ww.. wwww... ..w.w.w.w.w.w.w.w.w.w.wwiX...i..iww2,@@;@@@0;*wiwwwi.iXwwXiiXiiww.iX.i*piiXii..i1*22*******O;*4i4ii......iw*. ..............................", +"............................................u......u..uq.u.u.........4iiii4i4i..4i4i4i4444i4.4...4..4.4.4.4..4.4.4.4i4..4i.4444ii..44.ui....u410oo**o*oooo*oo****oo**oooooooooo*o*********O**OOO2OOOOOO;;,OO,@1.. . . . . i#@,;,,@,@@@@@@@@@@@@;@@@@0@@@@@@@;@@@0w w.w w ww www w.w w w w.w .ww w w w w.w.wwww ww w.. .ww.www. w.w. w.ww.w.w.w....w....iwiiiXp**O;@@;;;pwww#wwwwX.wpwow2pwwwpi2wiiii..iw92;;9O**1#p*O2pi.. i.....iw*.##..............u..............", +"....................................u.................uq........4...4.i4i4iii4.4..i4.44iii4i4i4.44.4.4.4.4.4.4..4.44.4.4.4.4i4i44..4..........4;2o;9o*oo**o*****ooooooo*ooo***o***o*****Oo*OOOO2OOOOOO,OOOO,,;* .. . . . w . w ..w;@,,@,;@@@@@@@@@@;;,@;;@;;@;@@@@@@@@0w. w www w w w . ww w . w .w w w . w..w w ww.. ww.w.w.www.... w. . w..w.w.w..w.w.wiwiwii.iii4.4wo*w222*;;;;*p;;2**w*;2*XXiXXXi.X...iiwpw4p;,;;q4iX*O;w4 # ......4w#...w ..........................", +".....................................................q..u...4.....i4ii4i4iii4i.i..4.i4i4..i4i4.444.u4.4.4.4.4.4..4...4..4.4i4.4.iu4.....4.4...u10o2*o**o*o*oo***o*o*o*ooo*o*o*o*ooo**ooo*o*OOOO,O,OO,OOOO2O,,,Oi.. . . . .p0;;@;,,@@@@@@@@@@;@@@;;@;;;@,;@@@@@@@24w w ww.## w .w w w ww w w w www .w w w w.www w. . ww.wwwww.w.w w ..ww.w.w.w.. ...ii.i.X.w....wiii.iii.wpwX29wwXXX2;2wXiXiiiXiiiXi...i.i.ipp**i. iw**;pw#i.w.i.......pw...........................", +"..................................................uq..uq..u...4......4.ii4i4i.4i4..i.44i4.4i4i4..44.44.4.4.4.4..4..4u.4.44i4.4..4i...u4........41*ooo*oo*oo*o*o*oo*ooo*o*o**o*oo******OOO*OoOOOO,OOOOO22O**O@@*iw.. . ... . . . . . . i000;;@;;@@@@@@@@@@;,@@;;;;;0@00@@@@@@;w.wwww.w.ww ww w. w w .w w w w w. w w..ww. w. ww w w.w.w.w.w.wwww.w.wiw...w.w.iii.iiwi.i.w.wiw..i.ii.w;9iw4*@X4iXX.iXii.iii.i.i.....4i.4.w..i#*2;*#Xii..i......ww#w.........u...............", +"............................ .......................qq.q.uq.......4.i..4i.4i4iii..4.i4i4i4.4.4...44u4.4.4.4.4.44..444.4.4.4..i.4..u..u.....u...u10ooooo**ooo**oooooo*o*o*o***ooooo****OOOo*OOOO,OO,O2OOOOO22,2i.... . . . . .. . . . .4*0@;;@;@@@@@@@@@@@@;@@;;;;;@00;@@@@@@@;i w..w. w w ww w w w w w w. w ww . ww.w.w .www. w.www w ww. .w..w.ww.w.w...w..w.w..wiw....X....i.i...X..i...iXwwwpXiXXiiXiXiXX.iiwiiw.ii.i.i#w.....iiiX*X.wwi........4.#p....w.4.......u..........", +".......... ....................................u......u....u........4....ii4i4i4.i.4ii4i4.4.4i.4.44444.4.4.4.444.444.4.4.i.4u4..4.4.u.u..u...u..40;;*oooo*oo***oo*ooooooo***o***o***ooOO*OOOOO,,OOOOOOOOO*O*p4..X. . . . . ... . . .. .. . . ..p@,;@@0@&0;@@@@@@@@;@;@;;;;@00;@@@@@@@;.w.1ww .w.w.. .w w w w w w w.w. ww. ww w.www.w.www..w.wiw..w.www..w.w.X .w.ww...w.......X.w.wi...ii.wi...iwii.iiX.XXX**w1p...q ii.i.i.*o....iii..4.w.wr.i......wwu.......w...u..............", +"....................... .............u. .u............ququ.......4.i...i4.4..4ii.4ii4ii4i4.4.4.i..4.44..4.4.4444..444.4.44..4.4..u...u.u...u...u4a02OOoooooo***oooooo*ooo**ooOo**oo*oOOOOOOOOO,OOOOOOOOOO99#.. .. . . . . . . . ..40&;,,@@,;@&@@@@@@@@@;;;;;;;0@10@@@@@;@;iw.##w. w .pp.w w w w w w w . w. w ww www.ww w .wwww.w.www.w.www.w wiw...ww.w..w. .wi.w.w.w...i.i.wiw.w.iii.i......iiXiXXXw*p2;;*2*1iii..i19*i............i.i..i.... w.......i...4...u....u..u...", +"................ ...... ..................q.u...q..uq.q.q...............44...4i4iii4ii4i4i4.i4i4.4.4.444444444444.444444..44.4..4.u.u....u.u.u...400o9oooooo*Ooooooooo*o*oo*oOO*oo**OOOOOOOOO,OOOO2OOOOOO,;.... . .. .. . . . . . . 408@;,;&0@,@&&@@@@@&@@@;@;;;;;;00@;@@@;&;i w.wwr. wu90w w w w . w . w w www.w. www.w wwww w..wiw.w...wi. .....w.i..w..X...X......w....i.i..i..iii.iXiXiiiX4*;@,;;9;9pi.ii.419*#.. ........iii.i.................4.................", +"........................................u......u.....qq.uu.....u.......4..4.4.4i4i4ii4i4i4..4.4i4.4444.4444.44.4..4.4.4.4u..4..4...u....u...u....4u022ooooo**oo*o*oooooooo***OO*o***OOO*2OOO,,,OOO2OOOOO2;*u . . w. . . . ..8&,;&&&&@@&&&&@@@@@&@@;@;;;;;0;0;;;;@@@;.ww ww..200*. www w w www w w. w. wwww ww wwww.w ww w w ww.w.w wwX. w..w.w..w . ....wX. ....w..X.X.w.w.w.i...i..i.wiX4w2,@;;,92*p....i4*;9p4i. ......ii....................w....4.......u.u...", +".............................................q..q.quu..uq..qu.......u.4.4..4.44444ii4i44i4.4.4.4.4...44444.4444444444444..4..4444.4....u..u...u.4.410O**oooo*o*oo*ooO*oOOOoO*OOO**OOOOOOOOOO,,,,,O2OOOO,,w... . .. . . . . . . w42&;;@0&&&&&&&&@@&&@@@@;;;@@;;;;09;;;0;00;iw ww w iw00024 w w w w w. w w w www www www w www.w.w.ww. ..w.....w. .. .......wi.w..w...w......X.w.ii.iXiiiw*22iq*,,,;;,2922wi.ii4;@92* ........i....i................i......4...........", +"...................................................quqq.quq..q.........4.4..i...44i4i444i4i.4.4i4.44.4....4..44444i4.4.4.4444u4.4..4.4.....u.....u4<02Ooo*oooo*oooOOO*OOOOOOOOOOO**OOOOOO,,,,,,,,;OOO22;2u. . .. . . .w w . . . 408@;00&00&&&&&&&&@@@;;@@;@;;@;;;;;;;@0000w w ..i#0000; .w ww w w w w.ww w w.ww ww w w w.w.w .w.w.w ww.ww w.. .. . .w.. w..w... ..w.w.w......wi..wip2OO;2*2,@,;;,,2p4iiiii40@O,@*.......i...i................4wwi4........u.......", +".....iw ............ ...............................q...q.uuuqq..u....4.4..4.4.4..ii44i4444...4i44444444.4.4.44444444444444.4.444.4..u.4.u..u.u.u..4:02*00o9ooooooOO2OOOO2OOOOOOOO**OOOOOO,,,,,,,;O2OOOO2.. . .. . . .. .w.... . . . . . ..o88&000000&&&@&&&&&@,;;0@@;;;9;;;;;;00000r. w w.#*;;;000w ww w w w w w w ww www.ww w w.ww www.wwww. .w...ww....w .w. .......... ... .. .w....X.w..i...i.1;,,,,,,@,,;;;,,,@2.4i.i4@@O,,2q.........i...................#ii...4.4.4.4.4..u.", +"......iww ...................................qqq...qq.qu.q..q..u...4...4..i...4.4.4i4i44i4i.44.4.4.4444.4.4444i4i444.4.4.4.4.4......i4....u......u.u410;;00;*o9oOOOOOOOO,@;,OOOOO***OOOOO,,,,,,,,,O,OO;2*.. . . . . . . w . . ..i*=8&@0000&&&&&&&&&&@@@@@;;;;@;;;;;;000771.ww w.90;000&0w.w w w w a ww ww ww ww.www w wwww w.w ww.w .w..w .w. w.w..w . ..w. w . .. .. ...X..w..i..iwiir19,,,,@,2,,,@,@,,,,,;*i.4#@@O999 i. .......i..................www4...4.4.4.4.u4#r", +"..........................................ra...qu....q. ..uuu.q.u...u..u.uiui44.4i4444i44444444444444.4.44.444444.444444444..4u.uu4..u4.u.u.qq...q..4<00008;*0;oOOOO,;,,@@@;,,OO**O*OOOO,;;;;O,,OOOO,,91 . . . . . ... . . . . . . .. . . wi1=&&000&&&&&&&&&&&&&&&&0;;@;;;;;;;0077:1.w w.#00;000&0 w a w # w w w ww www w w wwww...w.. . . . w. ...w.w..... w...... .. ..wi..XiiX...iiip;;;,@@,,,,,@@@@@@@,@@@@2pu;@O;;99*............................... i.4..4.4.4....w ", +"........................................u..wrr .uq .q...u...q......u.u.u..u.4.i4i4i4.444.4i44.4.4.4.4..4u44.4i4i44..4.4....4..4....4u....u...u.q.q..q4.100002;;;OO22,,,;@@@@;,;*OOO*OOOO9;;,2*9O,OOOO2O*. . . . .. ...i*=&&@&&&&@&&&&&&&&&&&&@@&@;@;@;;;;0701..w ww .1;;000002.w www aq a w w . . .w. ww w www.w.w .wwwwwww w w .w . w... w .....w...w. .w..w..w.i...iXiwXi4w,@,@,,,,,@@@@@@@@@@@@@@,,2OOO,;,O1 .i...........................iw4.i4..4.4.44p1i4", +".....................................q.......ar qqqu.qu...q..u.u....q..u.u....u.4..444i444444444u4444u4.4.444444444444.u4.4u.4.u..4..u....u.uuu........4410;9OO;2O22;;;@@&@@;;;*OOOO22O2;;;2O*OOOOO2OOOp.. .. . . .... ....... . . .. . .40800&@0&&&&&&&&&@&&&&@&&&@@@;@;;000o.ww w .1;;;;0&&p w qa w q a w w . w w www . w w w.ww ..w .ww.w .. .. . . .........X.w.w... ..w...w.X...iiiX42@@@@@@,,,@@@@@@@&@@@@@@@@OOO,,,O*9w.......... ........... .......i.4.4.4.4.4..i ..", +".....................................w.. ..... qw#qu..u..q.qu..q.....u.u....u.uu...4...44.4.4.4..4.4.u4444.44i4i4..4....4.u..4..4.......u...u.. .u..u....u4:009O00*2;@;@&@&&0@;;2*OOO,,2;;;;;;OOOOO2OOO9w.. . ... . . . . . . . wio8&&&&@&&&&&&&&@&&&&&&&@@@@@0;;;@9p. w w w w#00;;000. q aqqqqa wqww w. w w . w .ww w w ww. ww. wwwww.w w .w w...................... i.ww....Xiiu442&@@@@@@@@@@@@@@@@@@@@@@@@,,2;,99,O;*w............. ..u.........u.4iwi4.4.4.4.4.4i..", +"........................................r....u....q .q.uquuu.q...u.....uu..u..u..u4.4.44.44444.444444u4uu.44.444.44.4.44u.4.4.4...u.u.....u..q.u.q.u....u.440000000;;;;@@@&@@&@,22OOOOO;;;,;;OO;9OO2OOO*q. .. . .. . . .... ....... . . . .. . .. .. .w.w408&@&&&&&&&&&&&&&&&@&@&&&&@@@;;9w.wwww w w 0000082. aqq6qa r#qw w w w w .w ww wwww w .w w.ww . ... . . .w....w........... . .w.w..w.w.4i#1;@@@@@@@@@@@@@@@@@@@@@&@@@@@@@@,,;9OO,,2*r ..................$ ...u.....4.4.4.4.4.44.", +"4..........................................u.....u q quuuqq.q.u.q..u....u.uu...u.....u.44i.4.4..4.4.4.444.444..4...u.u..4.u..4.4......u....u...qu.u........40&;70*02@,@@&&&&&@;;2;;;2,,;;,,,OOOOOOO9O991... ... . . . . . .. . . . . w . . ..w&&&&&&&&&&&&&&&&@2@&&&&&@@@;;@*.w w w w w.*;;0000p # $q #rq*r wqw ww.w w w ww wwwww w w www wwww.w w.. .w.w .w. ..w. ..w.. . .. ....Xii qp;;@@@@@@@@@&@@@@@@@@@@@@@@@@@@@@@@@,O;,;,,,,,2. .q..........u.....*p4.w...i..4.4.4.4.4.4.", +".......... ..............q.................u.uuq.....q.qqu.quq..u........u...u.u.u.u.u..44444..4.44444.4.u..44444.u..4u.4u.4444.4u.uuu.uu.....q.u.uu.u..u..40&0&500*,;@@@&&&&@@;2;@;9292O22OOOOOOOOO2O,w...... . . . . .. ... .... ... . .... . ... .. . . . ..w . .498&@&&&&&&&&&&&&@0&&&&&@@@@@;;;w w wwww w0@;0@00w rq www 11 qwqw wq w w w w w.w w ww w w w w..w w . .w ..... w w .. ....w... ...... i4w;@@,,,,@@@@@@@@@@@@@@@@@@@@@@@@@&@@@@,OO,,,,OOO,pu aq..qqu.u.......4.**i. ..4.4.4.4.4.4....", +"............. ..............q.u..............uqquq.q.ququ..quq.uqu...u..u4.u..u.u......u44.4.4u.4..4.44..4.444...u.u.u4u.4.4.4.4...uu.qu.....uq.quu.....u4i4;80,&092;@&@@&@&&0&;2;@;;22OO*O*OO99OOOOO,p.... . .w. . . . . . .. .w . . . w w .w..408&&&&8888&&&&&&&&&&&0@&@@@;0@p w w w w.200;;0&9. a wq q q w a a a w w w www w w w w w www ww .w . . w. . .w . w ..w.. . . ...p;&&&,,,,,,@@@&@@@@@@@@@@@@@@@@@@@@&&&@@,OO,,,,,,O,2q..w ...q.u...........ppi............4..4.4", +"..4 i....... ...............q...i.i.......quq..qquuuuu .uuqu...u.quuu.u..u4.4.4u.u.uuu.4..4..44.4.4444.4.4.4.4444u4u44444.44444.uuu.uu.....u.uqu.qu......i40&0;;2,2O,@&&&@&&@,;22;;;9**22O*OOOOOOOOO9.... ... .. .. . . .... .. . . ..... . . . .. . . .. .... . . ..w.4280&&8888&&&&&&&&&&@&&&&0&@;@0p w# w w .*0;,;@0p w q a a qaqw q a w w w w w ww w w w.ww.w . .w .w . w .. . . .. . ......4*88&&&&@@@O@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@,O,,,,,,OOO;p. ..q.qquqq........u.w....4.........4.4.", +"4....u...................q.u......i........q...u..q..qu.q.q.qu..u....u.u.u.4..4.4...uuuu.444.4.u4.4.4.4.u4.4444u.u4.44.4.4.4.4.4....u u.u......qq...u..4i4i4000;@;;O2O;@@@&&&@2;;;;;;2*29OOoOOOOO,9O;p.... . . .. . . .. . . . . . . . . .. . . .w.w w w ..w40=&&&888&&&&&&&&&&&@&&&&00@0@0* w w ww #0;;900ww q#a q qwq awqa# w a a w w w w w www . w ww.w. w. w .w . .w .. ..... w.w..w..i*&&&&&&@@@@@@@@@@,@@@@@@@@@@@@@@@@@@@&@@@,,,,,,,,O99;2u .....u.u.u.u.................u......4.4", +".....................u.....uu....iu......u.........q.qu .uqq.uu.q.u.qu.4.4.4.444.4u....u..444u..4u.i.44.444.4u4u..u.u4..44444444iu..u....u..u....uuiui.4.4w0020&;22,;,;@&@@@;;22;;0222;2***OOOO22**#u .. . .. . . .. . . .. . . ..... . . .. . . . ..w. . .w i4;=8&&&&&&&&&8&&&&&&&@&0&&@0;@&;.ww #wwq ww;0;0&;.# wwqwwwq rw # # qwqw w w. w ww w w. .w w .w w . . .w . ...w .w .w. .... ....u0&&&&&&@@@@@@@@@@,@@@@@@@@@@@@@@@@@&&@@&@,,,,,,;,,OOO,*w.....qqqqqu...............u..........4.", +"..4..u.u.u.u........u......u..u......4............u.qu.. ..u.u..q......u.4.4..44.4.4.4u.4.44.4..4.4.444.4u4.444.u.u4.4u4.44.4.4.4.......u......u.u..4.4iii4w8020@;2O;,@@&@;;,;29;;;;OOO*2*OOOO**w4uu.. . q . . . .. . . . . . . . .w.w . . . . . .w. .w . .. .ip8=&&&&&&8888&&&&&&&&&&&&0@0&0w w r w arrq20000p a a w qq q a qw w w a qw w w w wwww . ww.w w . . . w. . .. ....w..wX.w.X.40&@&@@&&@@@@@@@@,@@@@@@@@@@@&&@@&&&&&&&&@@,,,,,,,OO,,O,O q...q.u.u.u.u.........................", +"....u.u.................u...u.u.u...4.4i.....u.......u.uu.q.uqq.q.u.qu.u..4.4.4.4.4.4.4..44.444444444.44u4.44.u4u4..u444.4.444444.4.4.u..u4...u.u..u.4i4i44p&00;0;O2@@@&&;OO2O2;2;292Ooo*oO**#qu.... q q . . . w.. . . . . . . . .... . .. . .w . . w.. . . ...i48=&&8888&88&&&&&&&@&&&&&&02ri w#a waarrrr$10p#a a a a a q a a qq q wa w w ww.ww w . ww ... . . w. w. w w. . .. ...wii.iw1&@@@@@&&@@,,@@&@@,@@@@@@@@@@&&@&&&&&&&@@@@,,,,,O,,,,,O9* ....qqqu.............4......4..4..u..", +".u......u...........q..........u....iu.4..i........uquq.u.u.u..u...u....4..4.4.4.4.4.4.4..44.4.4.4.444.4.u4.i4.u4uu4.4.4.44u4.4.4..4...u4...ui4..u4...4i4i4#&0;0@2,;,@@&@,OO0;2OO;;;;****OO*.i........ q . . ..... . . . . . . . . . . . . . . w. . .w. . .w. .w.4088&&888888&&&&&&&&&&&&&&0i ww w ra$rar>wppi...... qqq6qqq qqqqqq. .... . . . . .. . .. ....... ..... .. . . .w . . wqar$r<<<>>rrr$rr$rrrrrr$r<<<<<<<<<;,@&&&&&&&@@@;@24.......q.......u...u............2wiu.4u..", +"..u....u.u.u4.u.u.uuquq...qu.q..q.q.qqqq.ququqqqq-q-qqq..uu..4......u...u.uu..uuuu.uu.u.u.uu...uuuuuuuuuuuuuu.4u4u.4u.4u4444.44444444.44..4.4.4i..4.4i44i0;0O@@@@@@@@@@@@@&&;;1u.uu.... qq qq6$t6qqaqqqqqq . ... .. . .... . ...... . . ...... .. .. .. . . . . q $r$r<<<<<<<>><<$rr$<$<<1<<<<<<<<<<<<><<<<<:<<r>>$-q..u.....u..uu.u.u..uu.u.uu.u.u.uuu.uu.uuuuuuuu.u.u.uu4u.uuu4u.4uu44.4.444444.4i44i4.4.4i.4i.4iiw;@2;90@@@@@@@@@@@@@@&@&;u.... .qqqq$$$r>$<$$6qqqqq ... . . .. . . ..... .... . . . . . . . qqrr<><<<<><<><><<<<<<><<<::<:<<:<$>>>$>>>66-q.............u.u.u..uuuuuuuuuuu.uu.uuuuuuuuuuuu.uuuuuuuu4u4uuu44u4444.4.4..4i4.4.4.4..4i.iii42@;0000@@@@@@@@@@@@@&@&;i.... q qq6$>r<<>r>r6qqqqqq.. . . . .. . .. ..... . . .... .. . . .. . .. .. . qar$<<<<<<<<><<<<<<<<<<<:<<::<<<:<$6>>$>>>>>>>>>>$6q ...u.u...q.q.u.uu.u..uuu.u.u.uuu.uuu.uu.uuuuuuuuuuuuuuuuu.4.44.4.4.444.4.4.4.4...4.4...4i4i4*@;0;0@@@@&@@@;@@&&&@;2.u.... qq6$$>r><$<>r$6qq uq. . .... . . .. . .... . . . .... . . .. . . . . a r$<><<<<<<<<<<><<<<<<<:<<:<<<:<<<$rrr$r<<<<6>$>>>>>>>>>>6>$6q.......quqq.q........uquuuuuu.uuuquu.uuuuu.u.uu.uuuuuuuuuuu4..uu444.44.4.i4.4..i4.4.4.4.i4i4X@80;@@&@@@&@;0@0ppwXuu.... qq6$>r><><>$qq q.q. . . . .. . ... .. ...... ........ ... ..... .w. ... qr$<<<<<<<<<><<<<<<><<<<><<<<<<<<<<:<>rrq q w w w w q q w q a . . .. .q. . .. . . . . . . q .... qqq.a#u..u1a. ......u.................u.u.u....uwOOp-666", +"qqqq666q66qqq..q..quq.qq6-qqqqqqqquqqqq6$>6>>>>>>>>>>>>>>>-q ...qqqqq6-q.q.qquq... uqu.uuu.u.uuuu.uuuuuuuuu..uu.uuuu.uu4.4.4.44.4444..4..4..4.4.i.i4ii4O@02@@@&&&&&@@&004uqu..... qq$$>$<>><><><>$q qq .. . .... . . .. .... . . ............. .. w . .w . . a$r><<<<<<<<<<<><><<<<<><<:<<<<<<<<<$>>>>>>>>>>>>$66qq qqqqq6$6qqq-q6qq-qqquq.uuu.uuuuuuuuuuu.u.uuuu.u.uuu.4uu4uu44444i44...i.444.4u....4.4iii4,802@@0@@@@&@;@&04...... qq6$$>>>>>>>><>>>r6q q qq . . . . .. ....... ...... .......... . . . . .. . qa$r<<<<<<<<<<<<<<<<<<<<<<<rrqq w w w w w w w w w q . w . . . . q . ... . .... . . . q. . . . . . ..q q.2;;9; .. ..q.......u..........uu.uu.u4*O29wpq6>6r6", +"rrrrrr$r6t66qqqqq.qq.q q-$$>$$$66--6-qqqq-$$>>>>>>>>>>>>>>>>6qqq6-q66>$6--666666qqqqqququuu.q.uquuuu.uuuu...u.u.uuuuuuuu4.4...4.4.4i........4.4..iiii4X,80;@00@@@@@;4**a........ q6$$<<<<<<><>>><<>$qq . . . . . . . . .. .......... .. . . . . . w $r<><<<<<<<<<<<><<<<<>$$", +"6$6$6$6$$$r6666qqq.qqqq6$$>6>>>>>>$$6--qqq66>>>>>>>>>>>>>>>>>666$$6$$6>>666$6$>666-qqqququuu.u...q.u.u.u.u.u.uuuuuuuuuu44..u4..44.i4.i4..4i4...4..4.i4w;*0;@00&&;@@;p14........ qq$$>$>>>><><><>><$$qq .q .. . . .. .. ...... ................ .. . .. . . . ... qqr<<<<<<<<<<<<<<<<<<<<<>$6$t", +"$6>6>6>6>6>$>6$66-qqq 6$$>><>$>>>>>>>>$6666$$>>>>>>>>>>>>>>>>>>>>>>>>>>>>><>>>6>>66-q qquq.uuquuu.uu.uuuu.u.uuu4.uuuuuu.uu...u...44....i.....4...i.ii422p0,@;0@0;@@@22u........qq$$><<<<<<><><><>><$6q q . . . ....... ..... .. . . . . . wqr><<<<<<<<<<<<<<><<<><<<<<<>>$", +"6r$>$>$>6$>6$>>>$$6qqq6>>>>>>>>>>>>>>>>66>$>>>>>$>>>>>>>>>>>>>>>>>>>>>>>6>$6>6>>6>>$66qqqqquu.uuquuu.u.u.u.uu.uuu.uuuuuu..u.u...u......4..i.4..i4..ii.*X0;@@@@@;@;12wu........qqq$><>>>>>><><><>>>><6qq . . . .. .. .. .... ....... . .. . .. . . .. . .. qa$><<<<<<<<<<<<<><<><<<<<<<$6q.q.......u........4*0;O,*66$>6>>$>6$6", +"$>>6>6>6>>6>>>>>>6$$6$>>><>><>>>>>>>>>>>>>>>>>>$>>>>>>>>>>>>>>>>>>>>>>>>>>6>>>>6>>>6>66-qqququuuuu.u.uu.uuuu.u.uuuuuuuuu.u....u...........4....u.....i**0;@@0&@@@;0$4.......q q66$><><<<<><><><><><>$qqqq . . . . . . .. . . . q r$<<<<<<<<<<<<<><<<<<><<><<<>$qqq.qu.......u.u.uu*;OO,;r6$>>>$>>6>>>", +"6>>>$>>>$>>$>>>>>>6>$6>>>>>>><><>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>6>>>>>>>>>>6>>>6>>>>>$66qqq.q.uuuuu.u.u.uu4.u.u.u.uuuuuuu.u.u.u...................4.42220;@0@@@0;;.u.......qqq$$>><>$>>>>><>><><><<>$qq . . . . .... .. ..... . . .. .. . . .. . a$qrr<><<<<<<><<<<<<><<><<<<<><<<<>>>6qqqquu..u........w;OO2;16>6>6$6>>$6$>", +">$>$>$>$>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>$>>>>>>>>>6>>>>>>>>>>>>>>>>>6>>>6>>>6>6>>>6$6qqqq.qu...uu.u.u.u.u..uuuuuuuu.......qq-qq ..i.i....i....4w2w0;;;;;;@;iu.... qq qq6$6$$>$<<<<<><><>><><><>$qqq . . . . .... .. . . . . . qa$r><<<<<<<<<<<<<<<<<<<<<><:<<<<$aqw a rw #w#awa a a qwqw w wq w qarrr><>>>66qqqq.........q...121<6>6>>>>>$>>>>>", +">>$>>>$>>>>>>><>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>$>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>6>>6>>>>>6>$>6-qq.-..u.uu.u.u..u.4u.uuuuuuuu..u.u...q6qqq....u...u......;;002;;@@0@a44....qqqqq66$$<><<$>>>>>><>><<<><<>$$q .. . . ... .... .... .. .... . .... . . . . qar<<<><<<<<<<<<<<<<<><<><<<<<<<>>>>>>6qqqqqu....qqqqqq-pr66$6>$>>>>>>>>>>", +">>>>$>>>>>>>>>>>>>>>>>>>>>>>>>>>>>><>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>6>6>6>>66>6>6>>>6>$666qq.q.uu.u.u.uu.uuu.u.uuuuuu..u4..uqq666qqq ....q.. qup*280;0;;@00011. qqqq6$$$<>>r$<$<<<<<><>><>><<><<>$q . ... . ..... . .. . . . . w . . . aar$<<><<<<<<<<<<<<<<><<<<<><:<<<<$ra w a a w wawa a a a a w wa a a q#qaarawq# w w w w w www w w w qaq q q . . . . q q qqqq6>>><><>>>>>qqq.q...qqqqqqq6->>>>>>>>>>>>>>>>>", +">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>6>>>>>>>>>>>6>>>>>6>>>>>>>>>6>6>>6>>>>6>>>>>>$6qqqq...uu..u..u.4u.uuuuuuuu.u..u..uq-6666qqqq qqqqqqqquX07;2,;,@@@9::.qqq6$$>>>>r$<>r>>>$><><><><>><<><>$qq . .. .. .. ... .. .. ..... . . . .. qr$<><<<<<<<<<<<<<<<<<<<><<><<><><<>>>>>><>>>>>6qqq q.qq-6q6q6>$6>6>>>>>>>>>>>>>", +">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>6>>6>>>>6>>>6>>>6>6>>>$66-qqq.u4.u.4u.u.4uuuuuu.u..4u...u.qq666$66q-qq6qqq66-X,0800,,;@0@;1rqq6$$6><><$><>r>r><><><>>><>r$qq. .. . . ... .... .. . . . qaa6r<<<>e<><<<<<<<><<<<><<><<<<<:<><<>>><><><>>>>>>>>$q-qqqqqq6-6$$6>>>>>>>>>>>>>>>>>", +">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>><>>>>>>>>>>>>>>>>>>>>>>>>>>>6>>>>>>6>6>>>6>>6>6>>>6>>>6>>>>>6>>>6qq ...u..u..4uu.u.uuuu..u.4.4.u..qq6$6$$$6-666q6$66p;;80,;,;0@@*-6$$$$$>r$$>$<>r>$>r><>><>r><<<<<6$q q . . ... .. ..... .. .. .... . . . . . . qaa$r<<<<<<><<<<<<><<<<><<><<<<><:<<<<<<><><>>>>>><><><>>>$6qqqqqqqr6>>>>>>>>>>>>>>>>>>>>", +">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>><>>>>>>>>>>>>>><><>>>>>>>>>>>>>>>>>>>>6>>6>>>>6>>>6>>>6>>>>>6>$6qq ..uu..u.u4.u4uuuuuuu.......4..qq66$6$$6$$66$r$6r;;70;@@;0@;t>$><<>>r>><$>>r>r><$r><<><><><><>$$q q . . . . . . . .. . . .. qqa$r$<<<><<><<<<<<<<><<><<><<><:<:<><<>>>e>>><>e>>>>>>>>6qqqqqqr6>6>>>>>>>>>>>>>>>>>>", +">>>>>>>>6>>>>>>>>>>>>>>>>>>>>>>>>>>>>>><>>>>>>>>>>>>>>>>>>>6>>>>>>>>>>>>>>><>>>>>>6>>>6>>>>>>>>6>>6-q..uu.u4.uu..u.uu.u.uu.u..u..u..q66$$>$>>>>>>>>$6*080,;;;@1r$>>$>>$>>>$>>$>>$<$<<$<$<><$>>><$<<<><$raq . ... . . . ... .. .. ... .. .. . . $ar$r><><<><><<><<<<<><<<><<><<<<<:<<:<:e<<<<<<<><<>><>>>>>><>>>>>>>>$-q-qqq6>>>>>>>>>>>>>>>>>>>>", +">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>><><>>>>>><>>>>>>><><>>>>>>>>>>>>6>6>>>>6>>>6>>6>>6>>>>>>>>>>>>>>>>$>6-qq..u.uu.4uuuuuuu.u..u.u......uq6666$>$>6>$>>6>6*00;,,;006>>$$>><>>$>1r1<$<>><>$<$<<<><<<>><<<><><$taq . . . .. . .. . . . . wqqq$r><<<<><<:<:<<<<:<<>e<:<::<:<:<<<:<<<<$rrrrar#qaqwqa w awawaw w w awawaw#qwaw w wwww w w w w a a qaqaar$rr$$$$rr6rt$$$$$r6$6r6qqqqaaqqqqqqqqqqqqqqqqqqqqqqq qqqqq qaq q qqq6$>>><><><>>e<>>>>>>>e><>><>>>>>$6q-q-6$6>>>>>>>>>>>>>>>>>>>", +">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>><>>>>>>>>>>>>>>>>>>>>>>>>6>>>6>>>>>>>>>>>>6>6>>6>6>666qqu.uuuu.uuuuu.4.u4uu.u.u4...u.qq666>>>$>>>>>$>>a20&,;@@01->>>>$>>>>r222<$>$$<$<$<><><<>><>><><><<<<>:<><><<>:<><<<r>><>><><$<<>r>>>>><>e<>>>>>>>>>>e><>>>>>>66qqqq66>>>>>>>>>>>>>>>>>>>>", +">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>><>>>>>>>>>>>>>>>>><>>>>>>>>>>>>>>>>>>>>>>>>6>>>>>>>>>>>>>>>>>>>>>>>>>6-qquuuu..u.uu..u.uu..u.4....u..qq-6$>$>>6>>6>6>6rw;0;;;;;2>6>$>><>>$<r><><>$<>r>><><<>><><<<>><<$rqqa . ... . . . .. . . . qaa$$<><<<<><<<><:e:<<<<><<<:<:<:<><><><><><><><>><>><>e><<><<$><><><<<<><<<><>>$>>>>>>$><<><>>><<><><>>>>>>>>>>>><>e>>e>>>66q-qqq$>6<>>>>>>>>>>>>>>>>>", +">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>><>>>>>>>>>>>>>>>>>6>>>>>>>>>>>6>>6>>>>>>>>>6>>>6>>66-qq..u.u.u.uuuu.u.u4.u.uu...u.uqq-$6$>6>>>>>$6>6r200;2;@@p->>$>$<>>>>>><><>$<><>>><>>>>>>>><><<>$$r$qqqq . .... . . . .. . . .q qa$r$<><e<<><<ee<<<<:<<><<>:<:<:<:<:e>e>e>e>e>e>e>e><<>e<<<><<><>:e:><<><<>>><><<<>>e>>>>>ee>>>>>>>>>e>ee>e>e>>>>6qq-q-6>><>>>>>>>>>>>>>>>>>", +">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>6>>>>>>>>>>>>>>6>>>>>>6>>66-qu.uu4uu.u.uuu.u..u.u.u.u.....qq-66$66>$>6>>$>6a;0;22;@0116>>$><>>$>>r><>>$<>><><<>>>><><><><>>><<>$>$r$qqq q q . qqaqa$r$<><<><<<><<:<:<<><:<:e><<:<<><<<:<::::<::<<<<<<<:<:<><><><><>e>e>e:ee><>><>>><>><>><>>:<>eeee>e>>>>>>e>>><>>e>>>>>>-q-qq6>>>>>>>>>>>>>>>>>>>>>", +">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>6>>>>>>6>>>>>>>>>6>>>>66>6>>>>6666-qu.uu4u.u.u.u.uu.u4u.4.4.u.u..q-$6-66>>$>6>$>>6a*2;;;;001<>>>>>>>$<>>$>r>>$>>>>>>>><>>>>>>>><<><><<>$r6qaqqq qaqqaqaaqqqqq qq q . aqaq$$<$<><<><>e<<<><<><<<<><<<<<<<><<<><<<:>:e:eee<><>><>>e>e>ee>e<>>>>><>>:><>e>e:<::e>>>>>>e>>>e>>>>>>>e>>>e<<>>>>6qqq-6>>>>>>>>>>>>>>>>>>>>>", +">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>6>6>>>>>>>>6>>>>>>>>>>>>6>6>66-6qqu.u..uuuuu.u..u4..u.4......q.qq-6666$6>>6>6>>>6aa;;21rrr$r>$>>>>>$<><>$r><><><>><>><><><><>><><>><$><<$$6aqqqqaqqa6q6qq6qqqqqqqqqq qqq qaqaqq$$$>r<<<<><<<<:<<><<><<>:<<<><<<<><><<<<><:<<<<>:<<<:<:><<<e>>eee<<>><>>e:>e>e>>>e>e>e>e>>e>e>e>>>>>e>e>>>e>>>>>>>6-q-66>>>>>>>>>>>>>>>>>>>>>", +">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>6>>>>>>>>>6>6>>6>6>>>>>>>>66-qq..uu.u.u.uu4..uu..u.u4.u....uqqq66666$>>>>>>>>>>66<>>6><$><>>>$>>$>>>>>><>>>><>>>>>>>>>><><><><><<>><>>$$$$$r$rr$r$r>$$$rr$$$6qqq6qqqqaqaaq6q$rrr>r<><<<<<<><><<><><<<<<<><<<<<><<<<><:<<<:<<:<::<:<:<::<:<:<::::<:<:<:<<<<::<:<::<::>e><<<><><><><<<<<><>>>e>>>>>>e>e>e>e>e>>>:>>>>>>>e>>e>e>e>>>>>ee>>>6qqq6>>>>>>>>>>>>>>>>>>>>>>", +">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>6>>6>>>>>>>>>>>>6>6>6>6>>666-q..uuuuuuuu.u.4uu.u.4....uq.qqqqqq6$66>6>6>>>$>>>>>>>>>$>$>>$>>$>>>>>>>$><><>>><>><><><>><><><><>><<><<<<<<<$<><<<<>r<<<><r$>$$r$$r$>$$$$$rr$<<<<<<<<><<<<<><<<<<<<<<<<<><<<<<><<<<<rr$rrrawr q $ a#aaa$awr a$q$$r$rr$r<<><<<<<<:e<:>e<>ee:e><><<:>e>e><><<<e>e>>:>:e>:>:>e>>>e>e>e:<>>>>>e>e>>>>>$66q66>6>>>>>>>>>>>>>>>>>>>", +">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>6>>>>6>>6>>>>>>>>>>>$66-qquuuuuuuuu.uuu..4u..u.uq q-q--6666$$$>>>>>>>>>>>>>>>$>$>r>><<<>r>$>><><$><>><>><>>><><<><><><><<<><<<><>>>>><<<><>>>>><><><><>><>>><><<<<<<<><><><<<<<<<<<<<<<<><<<<<<<<><<<<><<<>:<:<<:<:<::<::<:<::<:::<:::<:<:<::<:e:<:<><<<e<>e<:<:<<><><<:e><><><>>e>e>e>e>>e>e>e>ee>e>>e>><<>>e>ee>>>>ee>e>>>>$6-666>>>>>6>>>>>>>>>>>>>>", +">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>6>>>>>>>>>>>>>>>>>>>>>>>>6>6>6>6$66-qqquuqqquu.uuuu.uu..u..qqq-666$6$>>>>>6>6>>>>>>>>>>>>>$><>>$<>>>>>>><>>>><>><>><>><><<>><><<<<<>e><><<<<<<<><<><<<><><<><>><<$<<><><>><><>r<<><<<<><><<<><<<<<<><<<><<<<<<:<:<:<<<<:<:<:<<::<::::<::<::::::<:::<::<:<:<:<<<<<<<<<<:e<:<::<:<:ee<>:<:e<:<::>e>e>ee>e>e>:>>e>>e>>e><>e>>e>e>>><>>>$666$$6>6>>6>>>>>>>>>>>>>", +">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>><>>>>>>>>>>>>>>>>>>>>>>>>><>>>>>>>>>>>>>>>>>>>6>>6>>>>>>6>>>>6>>>>>>>>>>>>>666---qqq.qqququuu...u..uqqq666$>>>6$6>>>>>>>$>>>>>>>>>$>>>$><>>>$<><><>><>><<>><>>>><>><<><><><><><><<><<<><><><><><>>><><><><<><<<<><<><><><><><<<<<<<<<<<><<<<<<<<<<><<><<><<<<:<<:<::<::<<:<:<::<:::<::::::<::<::<:::<:::<:<<<>r$r$rrr<<<>rrr$rr<><<::<<:e:<:::e::::::::<:::::<<<<<<:e:<:>:e<><>ee<:<e>eee>e<>><>>e>><>>>ee>>>>>>>$6666>666>6>6>>>>>>>>>", +">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>6>>>>>>>>>>>>>>>>>>>>>>>6>6>6>6>6>6>6>6666-qqqqqqqqquuu.u... q6$>>>6>$>>>>>>>>6>>>>>>>>>>>>>$><>$<$<>><$<><>><>>><>>><><<<<>><><><><><><><<><><><<<<<<<><<><><><><<<><<><<><><><<><<<><<<><><<<<<<><<<<<<<<<><<<><<><<<:<:<:e<<<<<<<<<><<ee:e<<:<:e:<:>e<>e>e>>ee>>e>e>e<>e>>>>>>>>>>$6666666>>6>>>>>>>>", +">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>6>>>6>>6>>>>>>>>>>>>>>>>6>6$6-66-q-qqqu.u.uuuqq66>>>>>>>>>>6>>>>>>>>>>>>>>>>>>>>$>>>>>>$><><<>>>><>>>><>>r<<><<><><><><><><<><><<<<><><>><><><><><><>><<><<><><<<<><<><<<><><<<<<<<<<<<<><<<<><><<:><<><:<<<:<<<:<:<::<:<<<<:<:<:::::<::::::<::<::::::::::<:::::<::e:::::<:<::e:e<:::::::<:ee:ee<::e:<:e<::><><<<><<>>>e<>>>>eee>>>>>6>>$66$666>>>>>>6>>>", +">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>6>>>>>>>>>>>>>>>6>6>6>6>6>6>6>>>$>6>$666-qqqqq..qqq6$$>>>>>>>>>>>>>6>>>>>>>>>>>>>>>>>>>>$>><:>>>>><><>>><><>>>>><<><><><><><><<>><><><><<<<><><><><><><><><><<>><<<><><<<><<><<<<><<<<<<<<<<<<<<<<:<<<:<::::::>:<:<:ee:e:ee>e>ee>>><>e>e>>>>e>>>>e>>e>>>>>>>>>>6666$666>6>>>>>", +">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>6>>>>>>6>>>>>>>>>>>>>>>>>>>>>>>>>6>>>>6>>>>66-qqqqq-q6$>>>>>6>>>>>>>>>>>>>>>>>>>>>>>>>>><><1:>>>>>>>><>>>><>>><>><><><><><><>><<><<><><><>><><><><><><><><><><<<><><><><><><<<<><<><<><><<<<<<<:<<:<:<<:<:<e:<><><<><<><<><><<><>>>>e>e>>>>>>>>>e>>>>>>>666-666666>6>>>", +">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>6>>>>6>>>>>>>$>>6>>>>>>$6-q6666>6>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>66::0:111>><>><><>><<>><>><><><><><><<>><>><<<><<><><><><><><><><><<<<><<><<<><<<<<<><><><<><<<<<<::<<:<:<:<<:<<:<:::::::::::::::::::::::::::::::::::::::::::::<:::::::::::::::::::::::::::::::::e::::eee:eeee:eeee::::<::ee>e::eee:<>e>e><>>>e>>>>>>>>>>>ee>>>>>>>66-qq-666$$>>", +">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>6>>>>>>>>6>>>6>>>>>>>>>>>>>>>6$>6$>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>$:<:$777700<>>>>><>>>>>><><><>><><><><><><>><><<>><><><><><><><><><><><<><><<$<><><><><<><<<<><><e<<><<<<<<<<<><<><><<><<>e<<<>e6><<<<<><<><><><><><><><<>>>>>>>>><><>>>>>>>>>$66q-qqq666>>", +">>>>>><>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>e>>>>>>>>>>><>>>>>>>>>>>><>>>>>>>>>>>>>>>>>>>6>>6>>>>>>>>6>>>>>>>>>6>>>>6>>6>6>>>>>>>>>>>>>>>>>>>>>>>>>>>$>$>$$10777:1<<1<>>>>><>>>>>>>><><><><>e><><><><<><>><><><<><><><><><><><><><<<<><<<<<><<><<<<<<><<<<<<:::<:e<:<>><<:<<<<<<<<<<<<<<><<<><e<<><<<><<><<<><>::r<><<>e:<><><>e>e>>>>>>>>>>>>>>>>>>>>>>>>>>666q-qqq6$6", +">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>e>>>>>>>>>>>>>>>>e>>>>>>>>>>>>>>>>>>>>>>>>6>>>>>>6>>6>>>>>>>>>>>>>>>6>>>>>>>>>>>>>>>>6>>>$>>$>$>$>-:5%7:::e>>>e<><>>>>>>>><>><><><><><<>e><><><><><><<><><><><><><><><<><><<>r><><<<><<><><:<<<:<:<:::<:<:::<::::::::::::::e::::e:::e:::e:::ee:e:e:::::::e:e<:<$<<<1<<$><::::::::e:::e:::e:ee:e:e:ee:e:ee:e::e:e::e::><<:<:<<<<$><<<<01-::-6-6$6><<<-6>:::::><<<<<>r<>$666-6<><<-----u0%1--6$<$<><::1e::::::<>><<><>e>e><>e>e>><>e<><>>>>>>>>>$66$66$>>", +">>>>>>>>>>>>>>>>>>>>>>>e>>>>>>>>>>>>>>>>>>>>>e>>>>e>>>>>>>>e>e>ee>ee>>ee><><>>>>>e>e>e>e>>>e>>>>>>>>>>>>6>>>>>>>>>>>>>>6>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>$>>66-$:55887::e>e<>>>>><>><>><><><><><><<><<><><><><><><><<<><<><><>><<<<<<><<<<<<<::::e:<<:>617$6666-><<11>>q<055%55770:116$1755%%77:::--6$>$-11::170-qqr:707777%777::::>--q-6tr<>><>>>e>>>e>>>>>>>>><>>>>>>>>>>>>>6>>>", +">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>ee>e>>>>e>>>e>>>>ee>>>>ee>e>e>e>>ee>>>>>>>6>><>>>>>>>>6>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>6>$>$>$$::17+=7::::::<<:e:<:<>>><><>>><><><>e>e<>><>e>e><<><><><><><<><><>><><><<><<<><<<<<>:<:<<<:<:e<:::<:::::::::::::::<::::::::e:::::::ee::e:e::::<<<><<$:015y+yy+y++3701<<<<>>>>><<<::::e:e::eee:ee:e::e:::700077%+5707755%%%5%%7%+y+++++++++%55%yyy+++3%577755%553%%++++5777yy++y++y+yy+3%%55777:<$--6e::::::::>>e<><>>>>>e>><<<>>><>>><>>>>>>>>>>>", +">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>e>>e>>>e>>>ee<>ee>e>e>ee>>>>>>>>>>>>6>>>>>6>>>>>>>>>>>>>>>e>e>e>>>>>>>>>>><>>>>>>>>$>$>>>66:717+%1:::::::eee>ee>>>>><>e<<><><><><<<>e<><>e<<<<<><<><<<><<><><<><><><<<><<<><><<><::<<:<<<:<::<::<:::<:::::<::<::<::::::::e:::ee:<:e<:<::e::<>111007%05++%+yy++yy+++y%%%557777770:1:1::e:::::ee::<::1:7%%+++3+++yyyyyyyyy+yyy++++y+++y+++yyy++++yyyyyy+y++++yy+y++yyy++yy+yyyy+y+yyy++y+yy+y+++3%577:$--q6$r-><><>>>>>>>>>><>>>><>>>>>>>>>>>>>>>>>", +">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>e>e>e>>e<>>eee<>e>ee>ee>e>e>>ee>e>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>e>>>>>>>>>>>><>>>>>>$>6>6>---6rqu03%0::::::::e<:ee>e<>><<>:e<e>e>e<<>e>e>e><><><><><<><><<><<<<<<<<<<<<:<<:::<::<<<<:::<::<:<::::<:<<:<<:::<:::::::e:1:<<11<:<::1e<<07%++++yy++y+y++yyyyy+yy+y++yyy+yy+++++3+7<::e:e:e:e<7%%+++yyy++++++y+yyyy++++y+++yy++++yyyy+yy++++yyyyyy++y+++++++++++++++++yy+yyy+yy+y+++++++++++yy++y3%57:::$:<--q-66><>>>>>><<>>>>>>>>>>>>>>>>>", +">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>e>>>>>ee>>eeeee>e>>ee>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>e>>>>>>>>>>>>>>>>>>>-6$>-:77:-:$0++3%%:::::::::<><><><><<<><<<><><><<<><<<>e<><<>><><><><<><<<<<><<<><<:e0%371<<1<:1:73y+yyyyyyyyyyyyyyyyyyyyyyy++yyy+++yyy+++++yyyyy++++yyyyy+++yy++++++++++yyyyyyy++yyyyy+++++++++++++y+++++3%%+5777771$--66<><><>>>>>>>>>>>>>>>>>>>>", +">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>e>>eee:ee>eeeeeee>eee<>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>><>e>>>>>>>>>>>>>>>>$::66::%35::%%+++33%7:ee><<<>e>e><:e>e>e<><<<><><<<<><<><<<><:<<:<:<<<><<$tr>>>>>>>>6>>>>>>", +">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>e>>><>eee>ee:eee>e>e<:ee>e>e:>ee><>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>e>e>>>e>>e>>>>>>>>>>>>>$>11$-q1753%05++++33+57:e::e::<:<>:<<<><<><<<:><<<<><<<><><<<><<>e>e><><><<><<<<<6->1<-<<6<:$$611><<>1rr11111080570110557785%%5577010100755%%+++yyyyyyyy++3yy+yy++yyyyyyyyyyyyyyyyyyy+yyyyyyyyyyyyyy%%5::::5+yyyyyyy++++yyyyyyyyyyyyyyy++++yy++yyyyyyyyy+++yyyyy+yyyyyyy++yy++++++++++++++++yy++yyyyyyy+y+333++++++++yyyyyy++++y++++yy+++%%5757777:u--6>$>>$>$>>>>><", +">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>><>>>>>>>>>>>>>e>e>e:eee>ee:eeeeee>e>><>>>>>>>>>------>->>>>>>>ee><<>>><>>>>>>>>>>>6<:<:::177%%+513+++3333%7:>:::::::>e<:<<>eeee<<><:<:e<:><:<:ee:<:<<<<<><<>r6-q17%%%1qr1571110016>>$6>>>>>>", +">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>><>e:>ee>e>>e><><>><>>>><><>>>>6q170:00:01<><>>>>>>>>><>><>>>>>>>>-->$a17%577%%++%17++++++%%7:<:<:::>:::ee>e:><>:e><<e<<<<<$6-q-$:017++++%50%y=%33%%%57%3y++yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy+y++yyy+yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy57:773+yy+yyyyyyyyyyyyy++yyyyyyyyyyyyyyyy+y++yyyyyyyyy+yyyyyyyyyyyyyyyyy++++++++yyyy++++++yyyyyyyyy++++3++3++++++++++++++yyyyyyyyyyyyyyyy+y++++++376>>>>>>>>>>>>", +">>>>>>>>>>>>><><>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>><>>>>>>>>>><>><>e><>e><>->>>>>>>><>e>e>ee><>-$><<>>$<$6::1108855701-----$:6>:>->-6>>$><$--:016$<1<17777501$0+++++++%5::::::e:::<:<:<::e<>e<<<><<>$>>>>>>>>>", +">>>>>>>>>>>><>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>><>>>>>6-6-17:>$-6>>>$---->----6-6--:7:$-------u187777%3%%%757775775%%7777:$>>-u-:7771$:57177:::075%++++++++%77:::::::::::e:e::>:<::<:<<<<<<<<<><>$<$-17%3++++++y+++++++y++++y++yyyyyyy+y+y+y++yyyyyyyyyyyyyyyyyyyyyyyyy++yy+y+y+y++y+yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy+++yyyyy+yyyyyyyyyyy++yyyyyyyyyyyyyyyyyyyyy+yyyyyyy++yyyyyyyyyyyyyyyyyyyyyyyyyy++++yy++++++++yyyyyyyyy+3+y++++++++yyyyyyyyyyyyyyyyy+yyyyyyy3%8%016><>>>$>>>>>>>", +">>>>>>>>>>>>>><>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>6----666>-::::08%%%705%5577:::7::7:::::5+%57:77770000%%%%++++yyyy+++yyyyyy+++3%%%5773+55%575%%%33+++++y++++++3351<::::e::::::::::e:::e:e::<::<:e:<>$>>>$>>>>>>", +">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>$6----u--$<:0701:77:%++++3+++y+++++y++++++++++++++++++y+yyy+++++++++++++++++++++++++++++yyyy++++yyyyy++++y+++++3++++333%%0-$<><:::::::::::::e::::6>$>>$>>>$>>>>>>>", +">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>6$6-66$--><:::175%5%++++++333++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++333%%%57::>>>>ee::::::::::::::::::<::e:<:<:e<<<<<<<<$$r::0557%3%3+++++++++++++++++++++++y+y+yyyy+yyyyyyy+yyyyyyy+yyyyyyyyyyyyyyyyyyyy+y+y+y++y+y+yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy+++yyyyyyyyyyyyyyyyyyyyy++yyyyyyyyyyyyyyyyyyyyy+yyyyyyyyy++++yyyyyy++yyyyy+++yyyyyyyyy%16u->><>>>>>>>>$>>>>>>>>>", +">>>>>>>$>>>>>>>>>>>>>>>>>>>>>>>>$>>>>6-<::::775%%+++++yyyy++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++3333%%%%%%%%555777::::>><$>$>>>$>>$>>$>$>>>>>", +"><>>>>><><><>>>>>>>><>>>$6>>-->-----u:700000%++yy+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++3%%%%%%%5%55555555555%%5557777::>6-$<:07%%%++++++++++++++++++++++++++++++++++++y+y++++y+yyyyyyyyyyyyyyy+++++yyyyyyyyyyyyyy+y+y+y+y++y+yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy+yyyyyyyyyyyyyyyyyyyyyyyyy++yyyyyyyyyyyyyyy+yyyyyyyyyyyyyy+++++yyyyyy++yyyy+++y++yyyyyy+y0u6rr$$6$$><$>>>$>>>$><><", +">>><><>>>>6---------u---$$1575%557::77075575%+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++%%5%555%5%5%%55%55555%55%%5555557:::>>>$>6>>>>>>><>>$r:775%3++yyy+++++++++++++++++++++++++++++y+++++y+++++++++yyyyyyyyyyyyyy++y+y+y+y+yyyyyyyyy+y+y+y+y++y+y++y+yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy+yyyyyyy+yyyyyyyyyyyyyyyyyyyyyyy++yyyyyyyyy+++++yy++yyyyyy+++++++++++++++yy++yy++yyyyyy++37<-u17:::->>>$>>$>>>>>>>", +"><>>>$--><:0777777777755%%%+++yyyy+++3%3+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++%%%5%%%5%5%5555555%5555555555%%%5557777777755%55%555%3yy++++++++++++++++++++++++++y++++++++++++++++++y+y+y+y+yyyyyyyyyyyyyyy+yyyy++yyyyyyyyyyyyyyyyyy++y+y++y++yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy+++yyyy++++++++yyyyyyyyyyyyyyy+++%5550<1<<>------>$>$><>", +"---6<1075%++++++++yyyyy++yy++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++%%%333%%5%5%%%55555%55555555%%333++yyyyy+++++yyyyyyy+++++++++++++++++++++++++++++++y+++++++y3+++++++++y+y+y+yyyyyyyyyyyyyyyyyyyy+y+yyyyyyyyyyyyyyyyy+y++y+y++y++yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy+yyyyy+++yyyyy+++yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy+++yyyyy++++++++yyyyyyyyyyyyyyy++++++++%%%%555770:<$-----", +"0775%3y+yyy+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++3333%%%%%5%555%%%%%%%5%5%%5%%3++++++++++++++++++++++++++++++++++++++++++++++++++++++3+++++++++++++++++++y+yy++yyyyyyyyyyyyyyyyyyy++yyyyyyyyyyyyyyyyyyy+y++y+y++y+y+yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy+yyyyy+++yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy+++yyyyy++++++++yyyyyyyyyyyyyyy+++++++++++yy+++yy3%%7701:", +"y+yy+y++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++3%%%%%5%%%%%%3%%33+3%5%%%%%%%%%+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++yyy++yyyyyyyyyyyy+y++++yyyyyyyyyyyyyy+y++y+y++y+y+yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy+yyyyyyyyyyyyyyyyyyyyyyyyyyyy+yyy+++yyy+++yyyyyyyyyyyyyyyyyyy+yyyy++yyyyyy+yyy+yyy++++++++++++++++++yy++++yy++++yyy+++++++y+++++++++y+yyyy++y", +"+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++3+++++++++++++++++++++++++++++++++++++++++++++++++++33%%%%%%%%%%%%%%%%%%3++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++y++y+y+++y+++y+yyyyyyyyyyyyyyyyyy+y+yyyyyyyyyyyy+y+yyy+y+y+yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy+yyyyyyyyyyyyyyyyyyyyyyyy++yyyyyyyyyy+yyyyy++++++yy++++++++yy++++yy++yyyyy+++++++yyy+++++++++++++y++", +"++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++33%%%%%%%%%%++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++y++++++++++++y++y+y+++y+y+y+yyyyyyyyyyyyyyyyy++yyyyyyyyyyyyy++yyyy++y+yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy++++yyyyyyyyyyyyyyyyyyyyy+yyy++yyyy++yyyyyyyyyyyyyyy+++yyyyyyy+++yyy++++++yy++++++++++++++++++yyy+++++++++yyy++++++++++++++++", +"++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++y+yy++++y++++++++++++++++++++++++++++++++++++++++++++++++++++++++++yyy+++++y+++++y+++y+++++++++++++y++++++yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy++++yyyyyyyyyyyyyyy+yyyyy+yyy++yyyy++yyyyyyyyyyyyyyy+++yyyyyyy+++yyy++++++yy++++++++++++++++++yyy+++++++++yyy++++++++++++++++", +"+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++yy++++++++++++y+++++++y+++++y++++++++yy++++y+yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy++yyyyyy++yy++yyyyyyyyy++++yy+++yyy++yyyyyyyyyyyyyyyyyyyyyyyyyyy+yyyyyyyyy+yyy++yy++++++++yy++++++yyy+yyy+++++++++++++yyy++++++++++", +"+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++yy++++++++++++++++++++++++++y++++++++yy++++++yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy++yyyyyy++yy++yyyyyyyyy++++yy+++yyy++yyyyyyyyyyyyyyyyyyyyyyyyyyy+yyyyyyyyy+yyy++yy++++++++yy++++++yyy+yyy+++++++++++++yyy++++++++++", +"++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++yyyy++++++++++++++++++yy++++yy++++yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy++yyyyyyyyyyyy++++yyyyyyy+++yyyyy+++yyyyy++++++yyyyyyyyyyyyyyy+yyyyy+++++yyyyy++++++++++++++++yy+++++++++++++++++++++++++++++++++yy++++", +"++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++yyyy++++++++++++++++++yy++++yy++++yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy++yyyyyyyyyyyy++++yyyyyyy+++yyyyy+++yyyyy++++++yyyyyyyyyyyyyyy+yyyyy+++++yyyyy++++++++++++++++yy+++++++++++++++++++++++++++++++++yy++++", +"++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++yyyyy+yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy+yyy++++++yyyy++++++++++yy++++++++++++++++yyy++++++++++++++++++++++++++++yyy+yyy++++++++++++++++++++++++yyyy++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++", +"++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++yyyyy+yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy+yyy++++++yyyy++++++++++yy++++++++++++++++yyy++++++++++++++++++++++++++++yyy+yyy++++++++++++++++++++++++yyyy++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++", +"++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++", +"++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++", +"++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++", +"++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++" +}; diff --git a/hacks/images/ground.xpm b/hacks/images/ground.xpm new file mode 100644 index 00000000..6f654af1 --- /dev/null +++ b/hacks/images/ground.xpm @@ -0,0 +1,227 @@ +/* XPM */ +static char *ground[] = { +/* width height ncolors chars_per_pixel */ +"128 128 92 1", +/* colors */ +" c #B4A589", +". c #C4B19C", +"X c #C4AD9C", +"o c #AC896A", +"O c #BCA994", +"+ c #BCA594", +"@ c #8C7451", +"# c #A49579", +"$ c #604929", +"% c #9C8D71", +"& c #AC9D84", +"* c #AC9984", +"= c #CBB195", +"- c #553D21", +"; c #AC9973", +": c #AC9573", +"> c #AC9173", +", c #BC987C", +"< c #BCAE93", +"1 c #6C5434", +"2 c #8B7659", +"3 c #CCB59C", +"4 c #947D5B", +"5 c #C4B194", +"6 c #94795B", +"7 c #C4AD94", +"8 c #C4A994", +"9 c #BCA98C", +"0 c #C4A48A", +"q c #8C7153", +"w c #BCA58C", +"e c #AD917A", +"r c #BCA18C", +"t c #B4A184", +"y c #B49D84", +"u c #AC997C", +"i c #AC957C", +"p c #745D3B", +"a c #A48D74", +"s c #A48974", +"d c #CBBBA4", +"f c #796143", +"g c #947D64", +"h c #D7C2A9", +"j c #8C795C", +"k c #A48963", +"l c #7B694B", +"z c #7C654C", +"x c #C4A98C", +"c c #BCA584", +"v c #BCA184", +"b c #B49D7C", +"n c #B4997C", +"m c #A4916C", +"M c #8F7E5E", +"N c #A48D6C", +"B c #A4896C", +"V c #D3BDA4", +"C c #A18569", +"Z c #9C8164", +"A c #9C7D64", +"S c #826C51", +"D c #846749", +"F c #DFCDB6", +"G c #D4B89E", +"H c #9C8567", +"J c #665032", +"K c #846D4C", +"L c #CCAE96", +"P c #947455", +"I c #7C6544", +"U c #A3987E", +"Y c #C4A584", +"T c #A49175", +"R c #765F41", +"E c #948165", +"W c #B89E85", +"Q c #D4BEA7", +"! c #B4A98E", +"~ c #837154", +"^ c #9C7D5C", +"/ c #AC8D6F", +"( c #957955", +") c #CCB798", +"_ c #AC9E7F", +"` c #6F5839", +"' c #A49184", +"] c #C4AC8C", +"[ c #C2B397", +"{ c #9C896B", +"} c #B4967C", +"| c None", +/* pixels */ +"p`Rpq4n}v6PkgK4by3}v=Y>nj9ZJ=n42Zv~DHBqS~SZl`jBHxvL=HZ=337kn@H@nZK`DJ$$fgb9=dV7hFFHExcn:LAv5yT5d7=@utB:ir>:cynnv>k", +"``zfIZ}}n^^oqjZvnwi>LLvvgnHR#d9+3VcSJ$~Ey}v:BZHn@SZHSSSIE@1qBBLn0x:{c7.xk>{^KN4qRSpJJ16uc3V)8dFF*i7YnHvkbvyyv57x6NuNnyv:Tt }vvo^", +"pD(KSNk>6:ooHuy]8 hbTlf~l4,obvN6qP4~zRlf1RqKHnE}bby=vttyioB:@kBk}4HgHp$jv{]5btyFFFd=i:IH/Wty7wyLL>b9wbwxvNu]TbLN@", +"IDiNj^6qD]^(geVGGh9K1fbN>46S@Miel{9t22Kffk/>b>@Dz>zpD~lR$R:w H6>>vccnNBs>}}Zn/vn>n>bqKK:R@:4ga&XQd3bN@H/6G7=Gwiiinvxnay{jNytKb>@", +"J1Bn>{KqpHnKpl>9=3nBD$2x]nn{T{N4STch3 q2fP@pk6B@RDK2{4fR11Z:aEua>b>BEZTkBi=aki:>>>:}N>@S22ZEH6{ONZHgKK:PbN}}4BB:TnT:6>46D({xv:n]w_ay35Hl6RN{;#yvtwuy}9b tn#tNqH@", +"B:4BH>>6Hxt>qfDeB/DBR$HyaeBnxxBlp@$J@R>5*Tu:HZ4Z~KEj24Ma{Nz11RIRH/qKS6tkmxknv>5nntm4g(B>jHN>xy5wc}y .33Hc>@4>N{:59uuHae53{:4HZHa", +"HHAZm;>}(xhnv6ayv}I$R$67BNBHvntkI_41p`Rj577yBK@4t@lqSH>6qqbHR11$qNqD@:>kZbZ^3vnAbT>>f1pHyvHS>Zxx]x7V>NHv:gqp6x3LB073GcI$$RH:i}B>yVVu3G]ETE4%w5.5BRfnTff1p~K>q>^K:K1D^$$JKnkiv}Cv7nBg>xw`$-DBBqR6Kg=738Oxt33>v/:6442&5euwBeEEH~Zg6}H", +"Z>>6uTBK`DBwLy73=Gh:1-1KNNn>ivhF h5hTt yatx9=t6K(Hll1JJ`B^Z(KvHl@HJ$$f/BvvoBB>7>P6w]D1$pHHCD^^Dniy3 7ivw/cbcmB{Bw3tb7uy*jHgZ^4BZ", +"ZgbH`I46IKz1{n3V9bGFvPKki>nc87FF<5=33DqS~DflI4^/Bfk4HDPl@@pPpqNCKCk}HH6H/opSfZ^CB6^`(Rzt35bS4BNBB57n9yrt}xi6ib{BiB6K^", +"{N#vlIpIKZnjPz>dbn6:]b>:xw:wh3hFh373w+553x=xw>Ck6IDZJ-fS6K}(1KHZNBi4:PqI1Rv^^Z>Z]vHHnBZZHA`qR1J`~12it3Nc7}niTrHE3.nBvvtT37P:vB1I", +"KK4;9TiiSKbx:DIjb>1pbbb05=iEd3d333937w09>Hw3vnkAZz(DR`1{f$$1p$>oB:i^ZZHkq1CP^kCK>xvcv>ovuB6f1J1`jqaOwysqux9NKJ]3HjtyaH978T7d>6}H@RpPP/N6tnyvyq^aH4SpJJK4A{a{2bDKNv6H4jS-pg6Zlj12:>gy{z$", +"tBH6Ee4qaavN=/4`;x=]3.c#bn3V d..3FOZrcs]VcBv9LnbZg^R`1fBfRlD6qK^(KZ64>q1RDDp^ko0y{Nuyv>uE{:EK11f6Huyug@@ff4DR`j~~1`Jl~5NynauVV#E", +"VVX0 u BZB5yvnH@4Nw3<.d55nvFXdFFdhh HgTc5h]G.0>ZNH>}HNq}~DIjZoNb61KBNayKpJ`1Ko2nwwycBw*yeHttHKRI2EvOuyuyH4aT%giTi{%~6zT{*}%ET&hF", +" w3wu#HDR>wwxBEi9]7.&5&8bfHXFFFQ3Fd>:Tw=uHH3wYB(o}k{BRHkKRD/>64kf$l@6c7amNf-`1D%9n:>{MKEiwbEw96~ _T.wwVhQ&E6aeygH%TT&", +"Uaw.VOaHf`gvwcB:]5vNcuuaH2gEcnK{y%j O* rr3hVO#%HNeg2a_E{", +"3ii*8.X.TpzAyyyn3cZB4k@1jjRjgOhhy FFQycEn3xBn:H/}vfj~ZKK~Dl2H6T< 2JKfq2quBZN@{BE{awhaDTNTHzIiEkH4ENyynqREd.XO%T v>v5xiiHs4jgE9T&", +"<+%gTO3d5hV XwysTy>4Zc=tvSEZw9>@DIp1`Tuc96SEyr5:tj*O#w:*uOHST=76EgjquZii ", +"&a%Uy.Oh3*u w*#2Tub@@>vm^>;nHahh.*3XX5w V7Gn]7G3Byn=b>HKS2Z6:>D~a hFVX7 ytT643ZBpJR4n{$-1p--RKBNZj`Z6 %&gE{iHj~jBNqgyir#* ~4> 3&", +"u&&.U T&5BHty<7y7t9_NmHbZ(ba>>r.V3.9i{;gi6y=cEHaq~m>wHHIMDS66gHTwH%%yO%#*%%HE%MEiTau !..dgzb *%", +"&!.Q& .7x5H0w<..=5ut3T~B(~vvaws5 .ydd7TmBvx]3:1lKpZmcwZl#Df2jql~]>&7 &t73X.y--l^KH:9GVPffJ$-----$1Rs~z<%Eyh+.i&%@E2SETXd..U~2Tt*", +"%&OX.&nwyGv w 9<7iE{3={uvjK>f6{& X< FFtv4kb=d]@1{lJDjjzl&O~HHEqD4Zy!d+Ei.dVdj4{{IayL=x^P,P1-$$$----`61j*TayyTSRRHEiT%%9&& !%%7*u", +"j% .7Ow7sar5Oy**9y:j@9]Gn{qu:y3w.XFr]Y^>k@1R%2$---$R$`Z2zagi#S@l2T.%2%STXdyxwFddVh5Ua95Bv}4 5v~bkkkg{Sg*w igzqJPA~~zah.3&dVEahhdd7tn3=k:}>KI:@$---JSzSgl14q&iH#`Rz%HzRJEw%&jz% ", +"'%E OX3.3 y*%23..uabp`B@cacmyBn8%T3V33yvHH>6%iaT]]YB]wnn9v3V56DJIP6EMEdT+7w3a2h.hFFh*u3Gxv=x`B>2pRERZka~f2j~#B{cZH$$-$JRJ~jT*T>i", +"%E%*.XVV8 HTgetiy3i>fJHqut]Tjz{t*U33HZgpD/{E2E>u5 H:v{wyvy9Vv6$$q6Jf{#Q7&9L7VBdd..hhbjg)=uxVZB3]tgnj62kBlq6yyt(4wcl----`$JE%ua T", +".U&.U. .79HgH@Z6IttvBo4fZHO3%j.Vb=tcnnBv+0cDJ>wlS 33QiEwsc93V.X 3iHRq3yhh3=.359<]a9T]vB$$zNcnT>l$$-J~@g{eiatH", +"QhXX 7tO3Ow4qR^^pZ~Bnnbq%gH3!Z .da5x# w>H2~%dr>LK(pI>nHHBDnVXGLk4x39+V3w3<3yZu3 T!7.<=BpBn'OO<7.3V9Vt.~KxcR-$gSi7y={$f4aj~2THgj#", +"OdO hdddh3rH6qk^6nc/nvhcvyedOe yFhXtXd*itETyOB>v4D$J@}]9aR6wdVt=y0rOd38wyE>{JytZ--$R6r3FxDPyir TT*&aa", +"%TO*T.dd.d3vNMPKIlvnb=GtS6N&ywr>wwZq%tE27yT8uKvx3:@`>Hv3]BjN.5.3dy*8]hy%3V7na6H%#ruy3ek$--127nB{xaZB1$`zlZbZ@IN;uy 3_a9b wER_3t>", +"wegqS%i<7.7.i@@K2RzjeHc94i9{TB3O{g4R1JRB{iTN{k6KG]B@n}3VhVu", +"cBzzz2Tr 7wy:qRfNSgitq;xgZxeTZwxaZ@I1$JEZ:NEAHPK.=ukv}G.hh35jgSTgHZqn3F3t>HD`6pzpDD1:H53($RKn>Sp6BBZIJ-16z$g/k=:Ziy7wt.dy#*.H&>{", +"K1JJ$~O>{HyETmDf]t9aBZH=NDgHZgZO46^@@Ip6{v4DIDN}i3LvYwh3dhd7bB6ZHHN@DaV3ywY>pKJ`pB^Kn>Th=kK1`6KDvcNnDJ-1I6pJDfZq@qa%Hsyy *iyTZ3t", +"bmI$`qvHqfgkNu:4D(I1fDq>b{6R`HEtqJ(>av9Vct=m^v0tjTnHv>dFQhFc]:Yv80yCqKzq@{Y}K-$pJDfKn=]55VnI$$pRv,n^>(@Dp-1$---`@(Ei+T4ZHBzq@p y", +"=FvPDfqkKD>;>t=tf^Lvv]vxDn3.h+ 5{qKPqE=a21Jzq$p4o^KRRl@KIR@Zi7.=;tg:`JIkH4Z^P^K^41--J$ZHyXw6@RzD66I>j", +"w==Lk1$1Rq]xN{w].tG9@/`D^vvx(KNvat>KIjDD{vv(p>HB{cGYqyhQd7uN@f`q47yH1-pP--$K>:{lplIHz~t3@nxiFh7BffRpZ@>K:vo>zR2I``6}yu^S1zp6KP9=", +"Tw3Vx>4D4R6Nv7y73{t3^6fpDNmN^q^3>B3:jR1`@PNcB}NkNy7wZqMH7Vw3wg6Z2TVwuK--$$1Kvx64ERD9t5T>6@cn5XbwY^pKkfBKN=R4Bidv^1RqyeqDpRlKIR@>", +"_ acxiV=xgZ:tr95nE@vc@(plgB:k}6kn=xw:HH=LVc~<9c7x6:yGvBp$I:q^Z26{GLc9v@6bE:PZ$-`$fPDTh39V9{q4f$K@K@^HKfK4>K4(>6$z4Bf~Iu>jbMqf>cH4j1K={w", +"j{K@y_rTBb]vwbE6HfKkn,x]ynyykNv:FVhV% wwc04nyV5kD$$D`1@@6Rxx3x]Bq4Rq`A$-$JPkfghhnYTWx=;q]GVFFFhd39>H>vxwFvD$--pqH6B4vnQ.0>4S$$qT6J$pP^p14Awydh{5=ZNpK6@^>6Hkv>vv^^{Tg@IEjjbAB{n>Bu{H#:@R@f", +"`1q@~ZE2lEty4tntB4DK~>n}nHu5Z4=GwFhFdh.cyi93h5FG@p$$6v=AI4lSBTa>4Rl1Pn0}>ZP^4KpDy53G2K3nIPJpKD4iT:=v/vb^ZH{qDK2{xiHKEHayVd7F]U{N", +":@k1(@~g4: tKN@H6:Jp(H}oZii TZ4=#Fh.9 35rt5hdV)V5:Hnt{=>mm`p1$JREk4Ipwn0E}ooZEDqR{nM`lv=kkll@Kn99bib=vy4D$1-f1pJj/@~@DJD>*x9d3;V", +"nun:2DyiTdVy#VwtcFh9353Fhb>vK(Z6>@q~l$I@6k4DZoAp7^Cev>qJ`5cppH;nvxv>iNk4BiauO3x:{1-$@#SHwZDlK$$RK _3V@a", +"==@^pRHH:wT73cNk`Dn/NNnY>;4K&7::;B3VbNdrg@vF]V797c}^=H4@RKHb5tZHBBuv^DRDRH0Zfs]:Ipitlpp@//w}8]>>q63h ayVWBkPKE97tv7rbc2fI@gw_{lK", +":x}bn>Hbttvy3L]L@DvxH:YvkN1p>iau]]a99t37cq(vxn:>qn=,nL>;wOB>y7h9e:vBa4J$$S4PfD@b1JRKIpfDin}nNn5]CqhF.ui8c>IRJ$EFODu7eu9NT6JKx{16", +"qkB,xi=xbi:vV3hVnDkL=wvv>vP@it B:t:Nmvbq;N>Ax9icBnxV==t=t0T6EHtr]07w}9Z`l9THPIzbZf-$H$JlkbB4uawwNq7d.waE7=:6J$JOyf{vqB9w#{Sz9cD1", +"I6>>vix7vNEahVGhc^Dnwwbc>]N> 75N4Nng^H;@^4qq>0]vvxx3G3w=rt;:4~Bu7v8xwV]g6G3tkKZb:I-$H$pf2B^Z:Ttt}q&XV7~`uGtbf1-ESJ@a6ax7ni@l>:Dp", +"fD}v:nsy7vKKi3u3V7By9=B:}cxvwMEN46cZDI:Tl$--(Bvbv]dw)3iyv>nxt# tVwvt3hhY1uFx=BrnnP1$pPo@(ko>bnN7>42%8NBl`HZybR--J(H4k6>wa{qKIqlp", +"1Kk}CHnex5BqfT3wdhwnitKE@k/HE{TNv}v}a^Z>lJ--pfn=rc3573yyv4P47Vww88.73dht$zyV3>}3]Y{D@nB4:vx/kp1Abxzj*w3t$J1quy--`b56>6fk>{qDJpk$", +"AK@kZ:n:B0nnKfutr3.wkT{smj(Ei.bl^}}vc:@JDKH2(>>vL=0777VV3cNDP*5yv95dhdhG@```ZYwV73=>pN=btxnk:p$4(Tw.Bf$H3]ovvyeB:c9tV]t;xu6jju}awe9y*7.&:DDpkFhVhYKpcwrnvkL:K4ND{y3au5]c>nRJ--Htbu6qq6N(p1IpZ}", +"vuw]:>:HbvLb]]c:<= T>Ni 3bHan.tH1(DRk^LP-IxY^>Z5=}HZTZ=xG]yhy{z@>iA~Bvss 7V3NRJEV*VV9Evc3>:>vYt0P1$1yw@~Z61n4f`zj{yNn:KILbzzu:Bv", +".54a~.blKvH6(^opD>c`I4c:n>cN6b9xy2yd3uNR>fjDZ0.8v3hxNp1t3w3FX>e}~/K(KRBwH$-qbba{l$KNMzExu9Lt59i5.uty=^k", +"5 wur:yZNuvr==3V377tv.35t7*{EEnwKlN;tm(,k(^K--S6^k4nc{]5=cBq7V.3>eg``KH>9bc>Gv}KfTynQhvsZ64PIf11=7S$-@NtbszSjS``9uyw97.F.B", +" y7w9TiAuOrr=3.35VubT85. tyja{:g@mk9cnY^fD1--`K>kI67n=G37tgyOyyxybj`f64b>va3vc>zKiidF=vEkD@DD1$=7al-z>>wvSl%B~$6~:vO.ET>wZe 7i5HaBT#9*9hV 5vyNycuc9}YK-$I$fDpbv:{b}:c83x7yisarc9cBRsN>>n=n=Y3vHix.dxbN4I1f@p$]3VVq`i9nrwaau.q6KHNw5O3dF33nZ:9", +"tui<.dngES*eqBHcuy3.ut%5#y5*5wu8yev:c]^4NlJRfpDR^bL:L=q^>07<y9xnv]3cr..37ybYDp4B`KNTwVvNcHZV7S`j_Ht:6Tt{OyQd bHur", +"i T9<.8bvT80i%9w3ttiTv9tH +5tT79hO=n}:4Hc=vvkRpp@:x}YvK@K> VdhOT2ttg88x7irayyy0n.VV3b93V3Exvkyt4p4lJN{HH-Jj7yE`j6gyi6vZ3*3.OtT;T", +"t7U .570nyn=xwut=yyZHNit*w3F73)8wVVxcNm@hVFhmN4k(;k^,/^ID(`t# UyTHnB{yvrHeEw7w0333.wx9n93+cV]vgEIIRJ9:DAJ-J_yaa#{@u qi@HfiV5bm:@", +"*i&&w..5vZ2HyAl{x9it}/#i5d_yb_tw%wVLx=](n:GFND@4@K>qn3GbH>f4t3<9ylIHgfR6~l>H&#yZi7=t5ygN3]=V73dbn4HqVvDa]*S~up~%Oyzq`qmH`qddiHB>", +"7O3*%w3GV7262@l6Ncbxv0]tw39wwy%933hG=GhnJJIc]4^IfR&=YGGG:mnAt3~Bg30BcLxh 5h3NH:@nT-J%!FUnyEEHaRRR-~IKz7Vd3>x", +"5g{T#Tx]r]vw6~DR@@>;:>tyaT8hVQ.dF=3b]43cp$J^xx]:{_b3nt>/v}644Ed33Lp---$Du#vcawwr{wcVhFVnb>yO%a9h8N}AbnR$J`dFD23OaZ2E2`@uuM2a 57c", +"iE{TbmyvityGZIl1E@jNu>:naBy@DKE3=V=@---RHtex0uy=7*3OVdFVvv>vBE2dFF c=xiHv7F;K1^YY/YHG37iNvvPffRHTEu3Lcf-$4ruEvnBg8Gn%7G %avv}uh7Ba35x]>>nvvjJzHaaSqicvyEj%E8.tT#T{>", +"t794KNBBtybiFVwqfHvcv=bv}>TMiw3vb353rn:T]ckk^bNHK677wHv:v4KDEc~6H Vn$$1Sdt77B~MslIa=3:BaBbwhwYvF5t>n6N>3Vn2N@@SIE>u*lzwyEt9..b@6", +" 79ulB>u57iEuvvBARg>B/tv7vcN%s#ntv3t3tuNvth5bY]bq4n7.39icc;:@uy>*c3]Zp6Hi&v]9:NHHg6Zu]0nnnv6>99c/ZZ=tb>q6(4T@H6plfREi{uO73cZZ", +"H4]tHBw7.V5it33>4ZNa]vy=3ir9yNnHxvc>x3]w:T>=V7ni4B89y yyvvaBjKnBG7tbTqZTTH4>i:5u{{P4S~N>o4nTqHDEbx3>kHvB>>44BA>v&;64jjy<3tnrw93=0N:wtu4>6l6@jgi@Hu:cig>>97vvb4ZEva(Evn3d7wT}N4nvn6>YaeHs7h3nkPl_>]nB:HB95=tm>Twd.3.ya4H@", +"AHA{{{wr99itt3QFdVT>pKBBvv35ywx}cx9ycw99=w>yytZ{{DJ1>{:ZfPN>578n0x:x=bE6aNg>N .3hhZBBbtw7>inb}i(]4}BZ>cnwyuZq=w>7ddV<]#nn", +":n8r2MlK2:2gTa53uc0ayaNcxv]9aLuBBEI>NHtKp~6.btB}npHc9xwc:ntc wb{tcnc~tHk:>EnvxtnvN:LK>]d3VFF33", +"v>=GzlRfI{4^Eg3.TT=}M2@1v5it]yniT:cxT#T{nxbc]:xbN>n@ZmN:;ZlKTgBBvypDTbwvxw:vv9X5*n@~JRgNbv85>]yyuTmc{xl4NAn>TbYccbvZkn(Hv3.dFF.5", +"wnu3EH@lp25w{Hxx%E33tZllINg:tr0ycywyxytTq@^SGcvuNa>HKH3Nt=@~`1l6N>:g:>>i9VwcuTyx3w9bf4BBx>wLi}73wx@ib:>TtB:ycuvvbY}(46v4T]wtFFww", +"V5>uKKuHaHn7w0x7ni 3h3Mn~KB>TBu7Oc:Ni#wtRp4ZNH>b>N:NN4>v77mbEqEHq@5=0xn7=xFVxnZaG757B4~q:>ynw8wr38B:9nv99t>b]BcL:kK^k}b:44aR h75", +"37HN1fa/=vPbBx xyxG7iwaTc6P2ZHs :Tsq6gt9I@bn@EH>wcyB:^>9G3HSV99xb4}v5wny7ay3]y>BrG9tc}IqNBBGw3Vwn0}c]]:ntTEa0b^]:PDP/wv::itqNVV5", +"TbH@EHZ@N^RAD2G7=73]t=7>n>Z@4ZS{9ivrZag{N};4@>::uvv}:c]hhFdt.9cb>H]tV3:aTw5h=vnNqy=hO8a2@6piLuw7b::TycrNyyHuy5~B]>4k>n=3N>v~pT5x", +"q4@KN{jHon@^ZDiNbG7.{Tn>Y:v:Tu>y.9yr:vcaZ~ZEH6u9nnYbNxtxdhdhdV :at3=3FOuwh3Qx]BaT>b3cr>BzpffT4iuw9 v9twt< tv5aqbcncZ6axTKHNI~bx", +"BEMqj4@@H/nZo@NMzH59TDH:g^4:uT]xty}naZ9x>q9=b_y3NvY>k;>>3.37d5yy97hF3Fh.tOG5e:6D6p@jl6H>{6>P2B:TB>75ryeby73iu{H64bcv2fS46lZb>Znw", +"bt>_aa6jqjb/Z4Zu@~yTxH:y44qlE@6txyNu>{/yvBDNy573i63vK@>aLN4HiEHuEtbEuNE~fBEqT=x>>>Nmvc}SNn=d3bK=L@P>}x7cuw=i{7h59<9VF=T=]baBN>66lJ$D@>;ZnPq@ZAgyiHTj@ZTt6SZ@BRpy_fK2{iT:TBZiE", +"E%5]T9HEHTub~~_#u9&Tv5^{c9B:{a%eb]9;N:by]xt=n]FF5@(=ckb,yw7uEu@RE85t]v97v}t={TqpqZbv:b46Z6ydyn5Tnag{4N24@RTvqlfjBHTiynaE", +"2~wRJH=hMp^w07,}:c:KZ9sI4]i:TkZn]:twN>TBHut=G>aaN^nBb7vnc .ci5bBy{g>w46fpK(IfIDiZH:55%T", +"~~uuuv3xHH%T)U4}w=9wvbnyB6{i80]:bvT:>bw4a3ysa <~2", +"Sj_wyac7xt5hFUZ)#E.u=cNv>T{@$JKK^n]<3hhTRJcMJ---glSSTyvy=5tnjqR(:>:>>b}:tv G7nGc>inE2%73vy=Y9vjeN1iVwe>N9B9=jT5y:D$$(`@DgmajE.ES", +"E{#*5MuVw]mFFF#iFhFhE9^6pp@(1J`pKc)6qpKB>v3yGrTxbNo77ywO3O{:LG:>HH~-Ki:ER~12>m63]5NI1p^>^H>twa<9~", +"E~{T<75F.FHN:.3tVhFF*8bN$$pI11Rl@GFV&Tng>4Bb>41SHNwxyw3w5]6qZb3Oy.xTK@xZ>H@R`$1JKS9g>,uawn==iPK:}4uv995 #", +"U{fzHT4 FFRf$Rb379dF3GV=$-$$J1EKK;G=m=xb4lH>l`IP^I~abBwtb4yy7ybgE/39HBa:vvx7=VG7bnDKuw>yxy^pqc0a>j{~l`Kf >wy%eaEOVwnI6=<99bH;:B9", +"&u~lH:E{FFlM`l9FV&y3VV==p$1IJR4l`Ib9NTb;E{EH4RS^Nqjiwvvxx>3539b{@g]57ba>:uxx]d5c}x@2MHe}nvgppiLrcBtu#4EIEay9#*t%w3=vqzx]cncNBu{>", +"]<9T#x>km3dFd.FF55nTvn]h95])tbfpJJ(n4f4vN={Rb}/>bbj%bnBv=8uwGOgHZ@{i)79vt:T>n5x=vc3TlRA}g{K1`jivYv3VFhv{E#id.3 T&%d3vjvt7}bvvcN{", +"VcOZ{iKKKt9hFFVV 3b:Rp]F3FhhFFTl`l4N{@@:@guf^xn}kxUy9iS~ejI2=VTNaN~S{i7ywvbvHbv]aEd3*aqDZK2$Kv>aCevw.V0T:aavO.5%att7hH::aA", +"c:a~zj~6vbzE.Fhu{bB@llbhVhhFFFF N77nB/NHRRlz:N:k4H3.3G{g@~~fH:L=vw>N&y3rby5xb8]7}EH.V3cZNf1$pb>N>Z}kgvOw2a>TzE.5M iaddygH@Z^4(~f", +"6N5u~lE4v3yuT%y:4K>wh3V.FFFFFFhVvbx9vx/mSJ`$BT1ppDunBb:]ZRD14P{>}>95wtwwwrwxw707=={u8:t57y1-$K:{v>(@Rj8n6f1qJJHTa:>H.d3x^^p@@f$$", +"JpT]>Tj@HV5xHE{vc@:7FFhuhh33FF.ha4ccnt::ZzElf4$1@Ig>2HZu5T@IqaH:bkNv7yyvO.58vunv=w7ytiitw3n~pKB{n>n/>}ia#f-$J$j{S~Ti7.7iiBEp1p1J", +"E~: Gbbi%09c__@;==h5OV.E{ciwdhFVug>5t=kk4ktaM`-$B@gBHEi{Vh]Kpgb#(^642i>Hyayu}ZZHx=<3F.gExw=Y^B7w:cVxB6~ivE$-`l@4uTtyO7VG9>5HI@K1", +"Nu#y3c ]v7thFVMp5=FFV5.H2u5F3h5V3G:ucnNkkknZ;I$`Dgi=9va#;>b@l1HtKHT{Rq{>gSHyo^6qZa3..yaEBE>vnywOcjV=naawh7jIzpfaE57wyv>vHu@Jpz^TX57>{4MN^l$IHqHt&2jSeD2genB6qKD5_O**Bg6kvyw77cqwV=ctuMRK4t3hVdv{Bk(R$$p@2wd7wzHzRR6v7BZ61v h75t@Pvtv{y]L>2:xv:y&9.9vHjgJ2yi7tHi=]8G.5bi", +"KgTTTa<57_@K=VbnNwVwiiEH]53 t:Yh{SZBE#7<5V.iiN2Eca*.aHx7]h7.3c", +"6Euuy{4Mc5_ywhh.77{nx:Ti8%ywdh!UU~M_9tuT>rrwvBDeabvNkAH&37]nmrOQ3VxH=BN4KIKi<7G=vy53&*]zj5<9twdO.OaE Va~_mTj%58c>w7rD@y", +"iN_O5<;9=] VFhVdy7{jHE_y# jlcxx=vnp{GF5yFF7Ovk:V_BSK`Db& 5hFFVcn!hdhX*2 OZ97w7>mpppHE~_9yu{EM`2yz2tN:a twyhh&S]i$pt]ujHn}vTV5n>9", +"{HT#<3;N4aHqqti9dFFF.hTqtic&&Tst#{yv0{b{{j454aZ:vtnMJR~`zvATm9y#Hd5w~ycZ6@{wwmN>v7Vyu>3", +"t955.d {{b:B@{wdFFFh=BKEu5.9yj6TEDfggEwtcH7nv x4Hc2J1`SK4BbNNu7TTa~R{2K:TE47bT:>vy%>6{", +"tw< d. E~&w.FdU.hd<]3V.nHzZt.FFFF=kEi 3<&tA~4@`$DEanu T:bn7=NN92```qq(n::am5 2Ej`jIR{tulT;nkZbi6aSH", +"O. g TU 7ddXdFd.33]335dVHH@R@E*FFFFF99)5 h59cED$$`R%irwwO>i:5G5v53UD2N6Pnn{u:vtSatlRS~lt5%gu:/^TcB/Ha", +"&95TEE9:H@u5FV93dEzavH6@IP~:H4I1f{{9:nvy:x", +"yT 5 dUjlM{&9[QFh9nny.MgtVw>S4Kl@N9h]a9<9Hb]>{6q@@enH61`6gjg=FFF&!hhhFd3V*z`EtbHrnTaby>H5=bgj~5y=xEftttNHSR$lj~ljTH*t5tv]5yb0=ac", +"&yZv%dd{~%{9U9 .3=Y/7h*Pi.bTjfplKKa t*{{>HNvu:NH6qB7wrHzD4@@nhFFhhFddFd]Vj--it7G3uv87HKR`$$`HEREO.##crv93=>twv", +".56gTOdd#%E#&%9un}}b3d7w5FYnjjl@^B9{{Tu>4SNN42ZH1@3vVxvfzg@@^TFFFd!~Ud.atHH~6A#8753i#mgSII4@`-l9y+V.Bg/S61R---Eu@j%t*#>{9>yvyyw3", +"=3:u{#Xh.y{t3& bTTbcx3B>k9tubBjnNjuiiEEH~S:uH~Hn6DNqZIAp$1z@AZQFh!EJEdE^BM~zBBZTaBie5t_~zf@j2l`fai3hxnkaKI1$MfKi{E%j%&UjH>nty79v", +"n}bwttt..3.#3tj2>E>HyH4gqHt79uZic46EqZ~&lIEvw#uy:Bqp1IN4$-Rq^~#dhh%JlEzlNKElPZS6e6>ZE~Nt.d0v{4qK@K:{j;vT&#j#. :uP=7.Vx", +">a}u 9 .<tF.ctw4{6ii:Ty5.x:nTm@^Huy{Tc9 jEd<_:Iv5t57", +"trtw!9O.*EBjEw..jJ`9:kNHn4IBv=tN%st3)9vwbBat79w9OhVw#Gbi59t&N%{{ty#tv5nb7<>@Hb:x@qNnm>H@~Eg4S6N^I`wvvqnookBgT_<H@4La4#4j{TeB{4NN66ZPJ]>ABi{DEN!{K{y a{v{bv>33>v=79y>9t2KEkNk>4BbvaT{&t yuibviPpDREx4pHuj@Ti~au5y]t4H]LL...< MMH6.np4dd Onvkq@j", +"oBt.OwTH;4# <{n5ER}^vuxwyx3wTx]9N>{}HB^q98w:Ey*twtw7i}mI$-j(qKIzNfKNi9GG]]m6jZaZgHb6EEj~%iMy:ZaHO95hv>vxn3<..d>HN@>B$-j*d5BbbtN4", +">vtyyu4qEEi9QOG]{p>AvLwV5y0xyct3c]v=>HvyFVh3i{iaavu9yn5vKR.]>ZD@tN`ppEb]vbycr@l`p1Hq2jl2T9nt78u=OVQFVvn>& TTxd.u>Bv]@`$zyOK@{B59", +"~279T{Z~HEa75w==N@{q4LOw=7>>N:T]tnu=v^vGdFhd aZ%BA~gn>y9_KwFyvZ}:;1J``/Yx=:_=aE~R`6vuEH>yy>H.3wi5Vta:vv>&. % 339xN:}v:S`Mbajm>av", +"ZRu5a4BEg@:3 {w3NZ~Dz:iEy8vbauBy=:EtbZc)xFhd9*E6>24j>nu&nITF9xBBb:KplI4vn95txTHHDI479ub:vuZ6y.{6w3cg{:nn*3.v9VV=c:Zin=#KM:NE>ng>", +"aj`MH6iY{E>wvu:9=5KDqf{Hnutc:uHNhtK2uNB5>hh.7t gsjKl4Tiaa@l4]L:Z3ryng6^n>:V]>2~T>:>B]vt>uyn@2MSDNtGvn>:Y8dyybV9v>u6:n95ijH6Hn{>Z", +"jS`SjHPgj4Nvyutv33w6cZPANN{n&{n2:c4@TNlyyyV3wT3xuySRS6jMb:KR$Rnih733b6kv553tjK@H4nkDaB}cHN9utZ@ql2Bty>:>tuH>jH759ZB/9BN{~6BNv{BH", +"u4Hg{ippIRN>7c33yu=:uYD@2gHgtEE~KiHB#:E:Ts5VvT9tuyn_S6{HHN>a~D1pVh3VwB2nnuttKNakq6^p(^B]n6n{GuIzpjqIN}>Hni4ZjNy<=i^4/NTyNHNgNvyT", +"tuuyNB11f$^nv=<3vc35/vB/@66qwuMalP46>uE#v7b<]n9c7_bvA6{%H{BTc;f$2.*7G7a;anuuH6KK@knk^>{wwZTHfpnNycv^atn>:n5hVv>^lv{]:kiBTvtt", +"4HE4ZH`-p1Pk~uV=]nniyw Eu;~fHNau%inb>ivc@t9ByyB;u3=HEitN@J@V9.F9nbavn{@11`pfkDD4b]ng%e33=DIZ:LvGvi}cyi3&u=xxuB=E/NkNYyc&:", +"4jKSD^f$JpP(1Ja5wiqm>N{a9cHw73*b3mp45ynmZK`1`$pJ1l{vxv%24tvNZf6/nnv77n=&vu{}v>9KNH4:oBivvt7" +}; diff --git a/hacks/images/hmac.xpm b/hacks/images/hmac.xpm new file mode 100644 index 00000000..a34737b1 --- /dev/null +++ b/hacks/images/hmac.xpm @@ -0,0 +1,52 @@ +/* XPM */ +static char *happy_mac[] = { +/* width height ncolors chars_per_pixel */ +"32 32 13 1", +/* colors */ +" c None", +"- c #000000", +". c #777777", +"X c #CCCCFF", +"o c #555555", +"O c #00BB00", +"+ c #6666CC", +"@ c #CCCCCC", +"# c #DD0000", +"$ c #888888", +"% c #FFFFFF", +"& c #444444", +"* c #222222", +/* pixels */ +" ", +" -------------------- ", +" -@@@@@@@@@@@@@@@@@@@@- ", +" -@@@@@@@@@@@@@@@@@@@@@@- ", +" -@@@&&&&&&&&&&&&&&&&@@@- ", +" -@@&XXXXXXXXXXXXXXXX%@@- ", +" -@@&XXXXXXXXXXXXXXXX%@@- ", +" -@@&XXXX+XXX+XX+XXXX%@@- ", +" -@@&XXXX+XXX+XX+XXXX%@@- ", +" -@@&XXXXXXXX+XXXXXXX%@@- ", +" -@@&XXXXXXXX+XXXXXXX%@@- ", +" -@@&XXXXXXX++XXXXXXX%@@- ", +" -@@&XXXXXXXXXXXXXXXX%@@- ", +" -@@&XXXXX+XXXX+XXXXX%@@- ", +" -@@&XXXXXX++++XXXXXX%@@- ", +" -@@&XXXXXXXXXXXXXXXX%@@- ", +" -@@&XXXXXXXXXXXXXXXX%@@- ", +" -@@@%%%%%%%%%%%%%%%%@@@- ", +" -@@@@@@@@@@@@@@@@@@@@@@- ", +" -@@@@@@@@@@@@@@@@@@@@@@- ", +" -@@@@@@@@@@@@@@@@@@@@@@- ", +" -@@@@@@@@@@@@@@@@@@@@@@- ", +" -@@@@@@@@@@@--------@@@- ", +" -@@@@@@@@@@@%%%%%%%%@@@- ", +" -@@OO@@@@@@@@@@@@@@@@@@- ", +" -@@##@@@@@@@@@@@@@@@@@@- ", +" -@@@@@@@@@@@@@@@@@@@@- ", +" ---------------------- ", +" -oooooo&&&&&*********- ", +" -........oo&&&&******- ", +" -$$$$$$$$...oo&&&&***- ", +" -oooooooooooooooooooo- " +}; diff --git a/hacks/images/jigglymap.xpm b/hacks/images/jigglymap.xpm new file mode 100644 index 00000000..46278955 --- /dev/null +++ b/hacks/images/jigglymap.xpm @@ -0,0 +1,350 @@ +/* XPM */ +static char * jigglymap_xpm[] = { +"256 256 91 1", +" c None", +". c #020202", +"+ c #191516", +"@ c #B8ACB4", +"# c #72788F", +"$ c #9C7B77", +"% c #E8D6D7", +"& c #9C929F", +"* c #2B2729", +"= c #E2CACB", +"- c #64504D", +"; c #D6C2C5", +"> c #B58E8A", +", c #8F706C", +"' c #CCACA8", +") c #807686", +"! c #9090A0", +"~ c #776863", +"{ c #B79F9E", +"] c #CCB2B5", +"^ c #908A97", +"/ c #433B3E", +"( c #ADA4AE", +"_ c #806966", +": c #8E7677", +"< c #9C8387", +"[ c #A99EA8", +"} c #CDA398", +"| c #8F8694", +"1 c #D3B6B0", +"2 c #AE9192", +"3 c #C19E9D", +"4 c #B18981", +"5 c #BAB3B8", +"6 c #4D464A", +"7 c #8A8292", +"8 c #DEBDBA", +"9 c #AA8989", +"0 c #6A6E84", +"a c #EEE6E8", +"b c #A59AA6", +"c c #7F7284", +"d c #DABBB8", +"e c #EEE2E2", +"f c #755D58", +"g c #B59593", +"h c #A69194", +"i c #816F6E", +"j c #9F8A8F", +"k c #E5D0D1", +"l c #967C7F", +"m c #C3ABAB", +"n c #D3BEC2", +"o c #E2C6C3", +"p c #C4998D", +"q c #686B79", +"r c #867988", +"s c #B7A4AD", +"t c #5B667D", +"u c #77696E", +"v c #C0A39F", +"w c #A68582", +"x c #C3B4BB", +"y c #7F7D93", +"z c #89716C", +"A c #EBDBDC", +"B c #A495A3", +"C c #B89A99", +"D c #CDB7BD", +"E c #AD7C6F", +"F c #9A7E84", +"G c #BEA6AE", +"H c #DAAEA4", +"I c #8F7A84", +"J c #D3B9BB", +"K c #9F7168", +"L c #D3B2B2", +"M c #AE9AA2", +"N c #98716D", +"O c #94828A", +"P c #86727A", +"Q c #777181", +"R c #786E71", +"S c #C3ADB6", +"T c #D6ADA0", +"U c #DCC4C5", +"V c #6A5D63", +"W c #A67D76", +"X c #C6A5A1", +"Y c #58555C", +"Z c #776266", +" **6KEEE4>pp}pppp>4EEEKN/* ", +" **//_E4>4pTT}TH}THHHHHHHH}T}}}}}}ppp>EE_//** ", +" /-f_4pppp}H}H}}TT}HHTHHHHHHHHHHHTTH}H}}}}}}p}pp>Kf-/ ", +" *-_KE}pp}}}H}}}}}H}}}}T}}}}}}}}p}p}p}}p}}}T}HH}H}}p}}}}}TpEK-* ", +" -K>4pH888oHH}H}H}HH}}}p}pp}}}T}}p}}}p}p}ppppp}pp}}}HHH}}}}T}p}HHH}E-* ", +" */E}}H8ooo8HHHHHHHHHHHHTTTTHHTTTTT1}T}}TTTHTTT}}Xp}pp}ppppp}}}}}}p}}'}THT>6/ ", +" /f_}H8kkko888H8HHHH8oo888H88888ddH8d8od88dHHHHTT}}vvpXvpvpv}vpCgp{3v3}p}3}}}}}}Kf6 ", +" fKHoookkkoo8o888Hoooooo88888ooookkk%kokkoooo8d11]'T''vvvv{v{v{v{3{{C{{{{CCCppp}}}}33KK ", +" *f>Hkkook%kkkkkokkoko88888okkk%A%AAA%%k%kook==oo88d11L''T'T111dX}X'vvvCCCCgCggp{gppCp}'}}}pp_* ", +" /}To%kooo%%AAAAkkooooooooA%AAAAAA%%%%%%%A%A%%k%%%oo8dd1T'T]x'''1111'Xvvv{vvC{gCC{g{CMCCgg333}3ppE6* ", +" fpooko8kk%AAAAAkooo8okkkkkkAAAAAAeAAAAAAAAA%%k%kk=kood111]'mmm@mXm@m@@v{{v{{{pg{gg{gCCgCCCgggCC3}}pHWf ", +" 6E'k%%kkkkAAAA%koo8ok%%AAAAA%AAAAAeeAeeeeeeAAAA%%kk=oo8d1''mv]xm@mv@vvsvsv{vvvvv{{gCCgMCgCCCgCgg>gCggp33TwK- ", +" /}kAAkoAkAkkkoo88ooAAAAAAAAAAAAAAAAAeeAeAAAA%%k%kkkk=o8o8d1]''mmmmmmm'x]'mmXXvvvv{{v{C{CCCggg2CgCCpCg>ggCgC3}}p/ ", +" 6pkAAAoA%%%oo88oo%AAAAAeAAAAAAeeAeeeeAAAAAA%Ak%kkkko=o=ooo=oo;ddnn11]L']']m@vmmmXmXvvv{{v{{{{{v{CC{C{}}Cgg2CCggg33E/ ", +" f2=AA%k%%A%kokk%AAAAAAAAAeeAeAeAAAeAA%A%%k%AAAAokoo8888ooo88o8dnd1dd11T''mmxv@smm''X''mmmvX'Tmm}T''vv{{}T}TXCppgCCgp3p$f ", +" 6gkekA%%AAAkk%AAAAeAAAAAAAeeeeAeAeAAAAAA%%%%%%AA%koo888888888d1dn11d1d11'T']xm'']x1ddoU1'Txm''1T1;oo8;81''1T881T}}T}vCgggpw- ", +" *_AAA%eeAe%kkAeeeeeAeAAAAeeeAeeeeeAeAAAAAAA%kooo88888dHTT1T111mxmx]18o8o88;d1d;8==%%doo===oo=oookdd8o=k%%ko8=ook8d1HTH8oT}C>>p-* ", +" *VoAAk%eAAAk%AeeeAeeeAeeeeeAeeeAeeeAAAAA%A%%oooo8H811TT1dd111111'x'm1d1o8doo8UU8ok%%%AAAAA%%%%%===%%kkk%%A%kood1H1HTH1THd8o8dTv2>p/ ", +" /xeA%%AeAA%%AAAeAeeAAeeAeAeeeeeeeeeAAA%%%%oooooo88881188od8o888nUdndnd88;ddUoo=k=%%%%%%%kkoo%===ooo8ddd8==8oko81Tp}pppp}}TTdH1THTm>g$* ", +" v;eA%eeA%AAAAAAeAeeAeeeAeeeeeeeeeeAAAAAAkkooooo88oo8oooUodoo8UUUUUooo8U88ddd8o=k%%kko8d'TTT}}vT1}Tv}pv'TTT}}}TT1TTXpvpp>>p>pTHH}}}Hd32w$ ", +" BeAAeaeeeeAA%AeeeeeAeeeeeeAeAAeA%%A%ooooooooo8oooo8oUUooooooood88oooo===kk=oo===kkk%==odTmX}v}ppgp44h494222gppp}}111TTT}TT}ppp>p}}}ppp1TC2w- ", +" YjAAAeaeeAAAAeeeeeeeeeeeAAAAAAeeA%%%kokoooookkkokkooooookokooko=ooooo=k=k====ooo=okkk===1T}pgpppgp>444wj94w>>pppppp}}TT'}pppp}}}pppp}p}pp}T3g>f/ ", +" ReAeeeAAeeeeeeaeeeeeeeeeeeAA%AAAAAA%%%kkk%%%A%k%k%kkkkooookkkkk%ko==kkk%k%=o81TTTTTTTTT1o1TppC>>g>>>44wwwww4>4pp}}}}pvppvv}}}pppppg>p>4p44>p}}p>>6 ", +" 65kAeAAAAeeeeeeeeeeeeeeeeAeAA%%AAAAA%%AAA%%%AAkk%k%kkkkooookkkkkk%%kk==k%k%=koHT}}}}}X}ppppgg244wEWWWWwWwWWWWww9Cpppv}pppp>>}}TT}vXp>4444>>4E>4p}}gw,* ", +" Yaea%AAAAeeaeeeeeeaeeeAeAAAAAAA%A%%%%%AAAAAAA%k%o%%kkkoookokkokokkooooo88d18181TTpp}p}vppg>424w44EE44EEE>p}}g4/ ", +" /YeAeAA%AAeeeeeeeeeeeeeAeAAA%%%%%k%%%%%%%kk%kk%k%k%kkooookk%%%%kkkkoooo8dHTHHHH11TTTT}TT}}vg>wWWE$KK$,K,K,$$$$EKE$Ww44ppCCvvX}v}'T1}}ppppp}}>2WWWKKEEpp3g4/* ", +" /naAAeAAAAeeeeeeAeeeeAeeAAkkk%kkoko%%A%kkoooookk%kkkkooooo%%A%%%k%%koo88HH}}}}}TTT}TT1188Ud1}pgww$E$E$$K,K,K,KKK$WWwW49g4ggCpvpppCp{}}>>2>>>p}vp>wEKNNKE4}pg$* ", +" *;%eeeAAAeeeeeeAAAAAAA%kkkokoo%AA%AAkooo888oookkkA%kkkooooo%%%%kkkkkkooo81T}}p}pp}T}TT1d1d1d1T}ppgg444W$,,,K_,,K,EWww944gppvppgpg>24>Cp44444j42gpp>4WK,KKNKE}gl ", +" *aaeA%%AeeAAAAAAAAAAAk%kooooo%%kokk%%koo88d8oooookkooo8o8okk%%%%kkkkko8d1TTT}}ppppvX}}'TT1T1TTXvppgp>4>4h44WKEEE$E44ww4gww4>g4>>}T}g4E$KK,,,Ep3> ", +" *5aAaA%%AeeAeeee%kkk%%%kkAo%AAA%%%kk%%%kk==o;oUUoooooooo8oooook%k%koood1T}}pp4h>w4w44>4>4>44>>22h4p>g>>>>44w44wEEWEEwww4g}vT}T'TT}vCgh4wwWWwww4>>gg}}Tp>>4EEEKK_K4>g, ", +" 5aeAkk%%%kAAAeA%kokkkkkkkAk%AAAA%AAAA%%koo;;;11;1nd1d11dd;dooooooooo8dTT}}ppgp2294944>gg>2449wwwEWw$EEWW$$E$$E$$E>>w>>>4>pggv'T'1}XXvCg>>4W2449wgg44gp}g>>>44EEE_,K>>~ ", +" neAkokkkko%AeeA%kkkkk%%%AAAAAAAAAe%A%%%o=1d515151511111111118888o8dd88dTTppppCgCg4h9>>>ggg4h4wwWW$EK$KK$KKK,KK_,K,$WWwwwEE$$K4>22>gggpvpCggw>ggp4ggpp}g>>>wE>>4p4EKf,w2: ", +" *neAkoo8o%AAAeAAAAA%%%AAAAAAAAAe%%%%%oood1151515n51515T51'n11;d888ddddd188d1d1d18111ddUUU8dddd1'}g>44hEW$KK,K,N,K_K_K$KWE$$E$K,,z__z__,w9w<$Ww4>pgpppgpv}T}pp4>p>4EE4K__E9: ", +" ^Aeko8HHoAeAAAAAAeAAAAAAAAAAk%%%kooookooU115151515n515111n1111;8881888888o88d1oUo=ooUooo=oooddd1T}pC>44wWW$KNNK,,K_z,z,K$$K$NNK,_z_,__,,zzz_~z,$:$:>2>4pppp}p}T}pp>WEEKK__K4gf ", +" [eAo8TH8oA%AA%AAeAeAeAAeAAAAoookooo18dd1;1551151xx151x1n1n1n1;UUoo88ooo8o8o8od88oUooUooo===ooddddT'vv>hwww$E$$NNK,KKK,,,KK,,__________,_zz,zz___z_,z,:$KwWwWgp>>p}pp>wEEKK_,K4pf ", +" &A%oTTHokAokkk%AeAeeeAeAAAA%%k88d1dd11151551x51x1xxxx15x5n1nd1d8Uooo8TTT1TmTTTTT'''1''''T1TTmT{}pv{pg>hwEKEEKKKfN4>f ", +" b%%d}}okooookoo%AAAAAeAA%Aooo8d111115n5n51x151x5Dxn51xnx1n1n1;UooooodTT1TTvmv}TTmm'vmmmXmXTmXvvCCpppg>44wO$$$,K,,K_,_______f_f~_f____z__z,zzKN:Kz,,,z:zKN$,,zz__~_~_z_~zK,,KKK___49Z ", +" jAkT}Toooookoook%%AAeeA%oo8od1n1n115nn5n151x51x1xxxxxxxx15n1n1ddooo8o8TTTmTX}m}'TTm}X}v}vCCCpgggh>4444wW<$$K$,,zK_,_K__K_z_,f____f__R~~~z_zzN:NzKK,zzz:zzzNKKK,z_i~~~ZZi~_,___KK___43Z ", +" b%oT}H8okokookko%%AAeAA%koooo111x55n5151xD151xx1x'xx15151D1x1n1;o;;oo8dTTvmmXmTT;Udd1111X}p2WWEE$K:Kz,_z,Kzz_,_________ff__f___f_fZ_~~R~~z__zK$$N,KK$,K$$zzzN,_K,zzz~_~~~___,___,_f__4p~ ", +" ^A8}}Hoooooook%AA%eAeAAA%kU8;nn1xnD5Dx1xn5nxDx]5]x]]m]m]xx51511n;;=;ooUo;o88o8;;okkkoo=o11m}pwW$KK,K,K,z__zzz__z__z_____f_ff_ffZZ__Zf~~R~__zz,,$$KK$K$K$WW$$KKKK,,zz,___~_____KKfKKK___KpV ", +" B%1pTdo=k888=oAAeeAA%eAoo8;;nnn1xD515n5Dx515D5]]x55]xxxDxD'x1DDn1;;;;ooooooo=k=k=kkkokooo8dTvv4wW$EKKK,,_z___zz_z_____~f_f_fZ~_Zff,~~___i_z_z_z,:$KK$EwwwwW<$WKKK,K_z______Zz__,KKK,KK__~_>Z ", +" ^%}pT8oko88oo%AAAAAA%%kko;nnn1xDxD5nxxxDxDDxx]x]m'x5]m]xDxD5DxDnn1;;=;=oko=k=k%AAAAA%%A%k=ood11{{h4E$$E$,,zz,,z_z__~_z__,f_Z~~~_fZZ_~~_i~__ii_z_zzz,,K$l$$wWw>gpEKKKNz,___f_______,K,,KK__Z,4Z ", +" *%'p1okodT8ok%%%%%%A%%ooUd1511DxDxDxxx1xDxDxDxx]x]S]]xxDxxxnxDn;;oU==kk%A%AAAAAA%A%%%kkkooo811'Xpg>wwE$$$$,K,z,K_zzz__z_z___Z_~Z~Z_~~_f__ii_z~__~zz,K,KK$l$E$W4ppg4wWK,zz_~ff~~~______________4 ", +" xT}1=8d11dok%ooooooood11111D51xnxDx15Dx5n5xDDx]x]xDDJD1nnDn1n;;oo==kkk%%AAAAAAAA%%k%%kkkoood1Xvv>4>wwE$$$$K,Kz,K,zz,_zRR_i_Zff~~fZffZZff~~~~~~~~~~__KK,,,_zzz$4gpp>wwW$Nzi_~~~_Z~_~f_f,____f_f_, ", +" m]'8=81111U==oooU1d1111xnxDxxn5D5D5nxDxDD51xxxxDxxxDJJn1nn1nJ;;;oo==kk%%kAAAAAA%A%kkkkkkodd11Tv{C>44wWW$$:$K,Kz,,z,,_,_ii___Z~VZ~f~fZf~f~f~~~~~~~~~_~~~~___i_zzKNWw$$WW$:z_z__~~_~~_~_f___fZfZfZZE ", +" ,T}8=1]'511;==d11111151x1xnxDx5DxDDxDxDxxxDxxDDxnDnnnn;nnJJnnn;Uoo===%k%%%AAAA%%%kkkooooUdT}pCg4wwWWW$E$$$,K_K,zz,,z,,zii_fZf~~Zffff~fffff~~~~~~~~~~~R~__~__~_zzzzzKWK$N,Nz_iii_Z~ff~f__Z_,_ZZfff_,z ", +" Np';;1]x''11n111111]1D1x15J5DDn5n5D5DxDxx1xnnn;nnnx;;=U=ooooooo=koko=k%%%%%AA%AAk%kkkokooddTmpCghwwWwW$E$$$KK_K,,zz,zz,z__ifZZZ~Zffffffffffffffff~~~~~~~~_~~__z,zzzz,KNNNzzz__fz__~~f~Zff_____fffff_KZ ", +" *'Td1'x'51mxDxx5Dxnx1nxDxD1xD5Dx5nxD5nxxnxxxDn;UU;nn;;;==oooooooooo==ookkk%%AAAAAk%%oooddTT}g4www<$$$KKKKK,K_K__z_z______i_Z_ZfZZfffZfVfffffffff~f~~~~~f~~~ff_f__NN,NNNN$,N,i_z~f~~~~~_Z~ff_,_,_fV-ffZ, ", +" T'8n'5m1mxmxxDDDDD1nxDDDxDDx1DDD55DDxxDxxxDxnn;;;;;;==k%k=k==U===okooookk%%%%AA%%%kkoo811Tvp44wwW$$$:Kz,,K,K_,_,__z_z_z___Zf_~ZZf~fffVVVffffVfVfff~f~fZZ~f~ff_fKK,KNNNNKEwwK,z__Zf_~~~~Z~f~~,KNzff-VVffZ ", +" *3T1nm'mmxm]m1x5DxDx11D]xnxnxnxxDDnx5DDx5D5xDxxxnnnnnnU;====;;;;;o;UUoo8ooooo%kkkokoooo81TT'vpgg4ww$,Kzz,zzz_z,K__zz___z_zi__Z~~f~fffffVVYfffYVfVff~ZZfZ~_f~~_____z,$K$K$$WwwNK,__~__f~~~~~~f~~,$$~fff--fff* ", +" *wL1x]mxmmxmx'5]1x1D]]1x1D11DD5DxD55xD5x15xxxxDDx555xxDnn;;kUo;;;;;oU;ooo8ook%k%kkkkoooo81TTv}pp>444$:Kzz,z,z,,z_K__i__i___i_Zf_~Zf~~ffffVVfVfVVV~ff~f_f__z~~f~~___,,N$4$$Kz_z___________~~~~~ZZ~~~~~fff~VVfVVVVVVVff~Z_ZZf~Z~~~~f_zzz,:$$Ww4w$$N,,_z___~~~~f~~~_Z__~ZffYYVV-Z_* ", +" *X]]mxm@vm@vv'5mxmmxx]]Dm]x]x]xxD1Dnn;;;n;;k;;;;nn;nnnnnUUU;;;UUoooookooo8o8o8oooooooooo88d811111TTm}vg>h$,K,z_zzR~i~~___~i~~~Z~~~~~ff~ffV~fVfVVVVfffffZfZZf~Zfff~~f~_zzzzKNE$w$K,,,z______Zf_~~fZf_f~fffVfY-Vff,/ ", +" $']5xmvmssv@mmm]m1]]x]xDxxx]5DxD;k=kk;k==%kkk=;=;;=U===;=;UUU=;U=oooUooooo888o888o8o8o8o8dd818111'm'v}g4h$K,,z__i~~R~i~___~~~~V~~~~~~f~fff~VV~Vf~VfffffffZZVVVZZfZ~Z_iz,z,$WW$:z_,__z_______fZ__Zf__Z~fffVVY-YVVff ", +" -v5]]m@@{vsm@@m]xxx]m'xDx]xxDnn;=kkkk%%kkk%kkk==;=;;====;=;UU;n11111d1d111T1TTTT8HHHHHTdddTT1TTTTT}'}mvp24$$KK,zziii~_~i~_~~~~~~~~~~~~~~~~~~R~f~~~~~f~VfZ~VZVZVVf~f~Z__,z,,$www:,,,,,_z__z___iz,_f~~~~ffVfVYVV---ff/ ", +" 6]xxx5mm@v@s5x5m]'m]]xxxDxxDnx;;;kkk%k%kk%kkk;k=;=;==U=UUU=;;dJ111111111111TTTTTTTTTTHH181dTTTTTTTTT}m'}ph4l:,,,z_z__i_~~i_f~~~~~~~~~~~~~~~~RRRfZ~~~~~~~~f~~V~V~~Rii~i::$::K$Ww$:,,zz,____Kz,,N$,$z___~fff-VVY-Y---ff* ", +" ~@]xx@mv@@@5m5m5xxDSx]mDDxDxnD;;=;k%%k%k===kk==k===U=UU==;U8dd1111111111111vTvT}TTTTTTTTTTTTT}T}}'}}p{{pg9w$KK_K,zzz_i~z~i__~~~~~~~~~f~~~~~~RR~Zf~~~~~~~~qZV~V~Z~RRRRRz:>4hp{pppppppppppgpppgg2h44ww<$$::z,,_,,,,,,zz__iiiiiz_i_~~__~~~~~R_f_ZRR~R~RR~ZZ~ZZZ~~~Ri~RR_,z,$$$WwwWNK,_,,,_z_zzzz,l>m9Kz_~fV-VfYV-YVYYY-fZ ", +" l5xx5m55@5@mS55SmJnnD1]]SxSm'mxx5xx5xxDxD5xx'm'Xm'}XXXXXXvXXvvvp}pppgg>>>p{pg4>pp{pppppppppp>g>gw4h4wO$$l::zz,,,,_,zzzz,z_i~i_zzziii_~_iizz_~if____R~R~~~ZZ~~ZZuRRiiz_iizziii__$W$:N,,,_,_z__zzz,:4X2$:z_~~VffVY-YYYYYYY-f ", +" *Bm]5m5m55@5m5S5x@Dnnn;DSSm]'m']'}'m]]'mTx1]1'X'XmXXXvmXvXXXXv3pCppCp{C>>4{gpp>>>gp{pppp>gggg424hwww<$:$::zzzzz__zzzzz_zz_iiiRi_z_____i___iii___f__~RRRR~~fZ~~f~~~_ii_z_____z_iizzK,______z_zii,WW$W4>4$_~ffVfVVVVYYVYY-YY- ", +" *I@xSS55@55x555S@S@]]Jn]]m@m@mmmmm'mxm'T'']]]x'''T1L11T1T111'1T]''Xvvppp{p{p{pggg>p>g>4h4w44444wWW$$lzzzz__zi__zz~__,_z_z_z_iz____~i_~Z~~~~~___Zff_~~~~~~~~ZZ~~fuR~~_R~_~~_~~z_iiz:,,,________iz$42>>{vgwz~fffVfV-V--YYYY-YV- ", +" /@]S]5@@m@m@SSS5x5SSm]]SmGGmGmm]5'm'mxm51]x1111111d188dd1ddd111d1'T''p}}TXmvvpppg>44h4wjw$wwwj4>pv{h:~fVVVfVVYVYYYYYYYYV* ", +" *2mxDS555@@55@@55SS5mmm]m@G@vsGmmx5xxx']mx1x;n;;kk=kkkkkkk==kk===oU8ddd11'Tv}vvp>g>>4hwwjwW<$O$<$$$KKzz__iRRRRRRz~RRRRi_~ii__ffZ~~~~~~f~ffff~VfZZZVVVfVffffffVfVZ~_z,__f~ffff~~~~~_______~_~f~_iz$hvTvv'{2$z~fVVVVVYVYYYYYYYY-f ", +" -@5DD@@m@555@m5S@55@Sm@m@mGGm@mm55xxxxDxDJDx;;;Ukkkkkk=k==kkkkk==oodUdd11'Tm}v{p>p>>44wwjwW<<h4hhwhwWgh44w4wwwwwwwl$,KNIll$$<<h22jjj:$:~~VVVVYYYYYYYY- ", +" 65D55555555S55x5xn5xD5x5x]]]xxDxDx]D1]DDn1n8;;UU;8d111LTTT''T'TX''mXT''}T1TTTT111TTTT'mmm}vmvppgp>2>g4wwwwwwwww<<<$w4h49ww:2g4jj<94z~VVYVVtYYYYYYY* ", +" y;555@55xx5x55555nn5nxxxxmSx']]1]1]]1]1n1dddddddddd11TT'''T'T''TXv}}}}mXm}'m}mXXmTmvvpvp{pg>2h4ww4wjjwgg24444wjO$$N::,:::,,ziiiR~~~~Z~ZZffffVVffZfffff~~~Rz:lz_~~~fZVVVVVZ~~~~_iR~~~_iW$jg2>gh224wwwEwwj<$w<$Wwhh4hww9h4g>p222424w<$lN,:zzzzzzi__i~ZZ~ZfZZfVfVfVZZVZfffVVfZ~~i:::iZZ~~VVVVVVZ~uRR_,z~fZ_i::j9ww4g{g{C42>2g{mv4z~VVV~VVtYYYYY6 ", +" ~@S@5x5@x5x55x55555xxxxXv3v{vXXXXmmTL11ddddddddddd8d11TT'T''T'''TXXppp}XXv}}m}vvvv}vCC>2gh444www$w444994wwh4wwWwO$E$$$O$$l$O$:K$$$$$$$$$$$$EwwWWW2h4wwww$$E$$$$$l$$$$$,$lll$:$$$$$$$wwWW$2h4h4h4jwwWWw$Mhhhhhjj>>>Cv1dd11m34N_ziRzz:,:ll$l$:4gv}9lI$l:NziR~~iii~~R:>vX''v{2WN___i_iiizizzz:NW9{Cj$zzN$w:i~~Z~R~u~~:<>2h929>>{vXX{gh<,z_____iz_iiiiz,Wwg{w$:zKK9j2g994j4>vvXXvC9<$i_~i_i_zzi__z,NWwgCj$zzN$wjjzZZuiZ~_i,<9h9li~Rzjww2><99F:~~ilF::)RuciZ* ", +" /@5555555;;n;k%k=;;====%%%%%%%%%AeeeeeAk%%k%k%k%kAAAA%%%%%%%AAAAe%%%%%===UooU;11T'15mmvm}mm}v{{C>gh>42h4wwwhwwlOI::)zRRRRRRPizz:)z::IIIIIr:O7|^^O^^O^^2j>2w<,:$<<<$l$lO<{X'{{Cj<<2ghhww<<$ll:$$$$w$<h22hjjjh4wwwwwww9jw$:,zzNNlj9g9$zzzz,z,,zz,z,,,:iR~VVtVVVVVZZZ~_RRiiR~~~zz:Il<ww<<$$:::::ljjj29<:zz_iiizzllII::F4>pCvppvg>24wwj<<<$<<$$l:lO$$4jjhh2>>2jw:zi_zi_,:lI:II:O<$<>pCCvvpg>94wwj<<<<4jjjh2>>29<:,_z__zzzFllI:l$F<<99jjj9j9jC{v'T}C24h4hhbhhh^j99wjwwwOllIz:zii_zz$$l:::::zl::RRRRRRRRiRRRR~~~~uuuZZui)IF|hjj&<h4h2hhhhCgh99w<$2M3X'mGg22www:IIlhgh4jj<<<hwwO<hwwjhj&B&j!jjjhhMgMvvXm']11]ms{gj$:::l$$llIIl:IllIIIrrIII:,P:y77yyyyO7O7IlFFr:PiQcQR)IFFI)r))#)cc00q0000Rqu0qQcR0c7cryuqqRr", +"=kn;=kk;AkAAA%%%%%kko===o8Ud1T'1m}vC{{C{gCCgMMg{pXm111''mXv}Xvv{vvv''T111]XXv{vv{pCgh22ww<$jjwh4hw<<$l$lN$$l$:$wlFFllI$l$$l:$K:Il24whhh22{vXm'''x1111Tmv{{vCC2gv{Xm}''T''m}vvv{g2h44jhC{[s{{vXmmXXv{vXX']11X{gjjll:::z:N,::II::IlIIP:rIII::r:rlII7y7O7yO77O7y))y#))#)77yycQ)Q)##u0qQQQ0uQQQPrI7iQ:2h2v'X''x''11111mX}{vCC2g{vvvX'T'T1'1''mvCgghh4hjjwj4hjjj<$l$l<<2h9942Cvv{{51nxm@v5m5'1111T}mmX{vvpvX'5111n;;=Un1mvpvv{gghgMghhjhOl$O<<>h4j92CXv{{51xxm@{mmmT111''m'}'p{v3{X']111;;;=;;1XXvv{vChhggghhjj<$l$<294j42CXv({mn1xmvv15mxD11'T'mmmvv{vvXX1511;;;=;;1'vvv{{p2hhMghhjjl44wwW92CCC3vXmm'v32>99wj<<>ppgg49w22gCgC33vvX{C9jWw<$l$ll$zzziii~iRRiRiRizPIIrIr::::F<:PRRQcRRRRRilF<jj<<<<<:PRRiPRRRRRQIF<wwwwww9j2g[{3X'11L]L1;dL]1]T'T1L11LLJ1dJJ]']L]1L]'X'Gv>wPPRRRPRRRRuilFjjII|OyQRiR0", +"=nU=;n1555@(5m51]1mXv{v{mv@@@@@M(((ssG@Gvm1k%%%==11dk%AAAAAAeA%AAAAe%AAA%A%A%%kk=oo8d1111111xXvv{CCC{{C{pgg22hww44gvX''XXv{g2w<ghliR~uRiiiRQR)P:::P)F4jw944{vXvvpC>9w<$lOOl:lzzz,ziz:z:z:,,,:::Pziiiz:P):):OO^&hB{3{CggM2222G'LL]'''''G33XX'''Xv{g2>gggXX']DJL]LS'LD]XCg222ghI_~u~~RiPii:IIPP,:POjlQ#RQ<", +"~=U=UUUo155mmm']5mvpgCg{g{M{MssssssGGS]]']JUo==;U88ookk%%AAAAAA%%%A%%k%%%%%%k=ooo888111T'1m'vvp>h2g24p{CCg>>>44h9h4gCC>>g9wgh2>gpCCCg>g>>49999gC3C>24w<g3mDJJLSm''''C29wh2g9:_VZV~~uz:IFjF,P::r7j7c#RR ", +"*U==UU==;xmmm]mxmmvCggMgggg{sv@@mmmmm]1]]]1;UUU;;d;UU=k%kA%AA%%k=%%%k=kkk%k%k=UUd8d11T'm'x'vv{g>h224gpCCCg>2>24h99hggg2>hww$l:II::::zziRRiRi)P)PrPP):r:r:):ll>CCCgg2g2>229999jjwW$l::z)iPPiPPPzRi)RiRRP:IrI)))I7|7Irjj9hB!<$O7^jj2vGGMg&jjh2M3333vCg2999hj92gg99jjll,P::F>CC{g2g2222>9999jjwW$lI,i)PPPPicPiiRQRRRRP:::r):):7777:jj9hBjgC{g>CC}ndd1JJ1ddd8d1''Xm{X'm''T'11ndnnU;n]v3v{v'T111no;Ud111'''vvvpgh4jjwwjwhhvvvvvvChwwjjh99wwO$IIz:z,zRRRRiPP:):PzP:rr7||7II7|7O77||||^hhB&h^jjjhMv{{gMBBh>9CCgggpv''m']]L'']1L''Xmp3{}vvXmm1]111d;;J'v{CpCv'T111n11111TT1Tmmv{C22jj<<|wjg{}XX'v{C9wCggggM{{X{{C{v{vvvvmXvv{C{vvvv{vXm'TxLJn]Xv{>C{vT111TmmXXX''111''mvC24jj<$$C>gggg{vvvvpC3v3vXpv}v3CC{{{vpv{XX'L]]JD1mv3>gCv''111X'''m''11Tx'mv{h>jggCC{{{{{{{{vv3vvpCggp{p{pCvvXXT''JD]mvv>C{X'11'1XXX'X''1111'mvCghhj>422222Mggg99hggg>2g{{33vmm'm}v{{CCmx11x''XXXXvX1dU81'v{ggg2gg>h<>g>>wO$OO<<>>2w<$$jhhBBhh!<h42g9jC{vvGX''G{h9hjjj9hjjj<<hMBC{{ChjF<92M{M922g{CMgggggv{2gg{GB|rQqtY ", +" {1([({Cghjhbb[bB&&j[[[{{([M{{[(((ssm@@51xxm5]Jn;UnL]nn;;=U;UU==;==%k==;nDxxmmmx555vm(@(ssss@Gs5]n1m1DJS'vX'1dd]SSSDnJ]mm333mS1n;8Uoo;811LL1LL]]L]''s@G']1DDL]SS{{({svG@vvG'Ldd8;=;=U;JLL]11]'mD11]L'GvXX3GG3GSXL]SG3SX3C2>h9hMggG3MM2>2MvC2CC{sB|rQttt ", +" 61mg{v{Mh^hhbbb&&&&b[[({[[Ms{((((sv@@5]xxx'm]1n;U81]J;;U;=;=;U=;=k%k=;;n]S]SSm]5m5@s(((GssssGsxx;J]]1J]'X''Jn8xSmSSJD]GG333']J;Uo==oU8dJLJJLL]]L''mv{s']dJJL]SSsssGGX'S'X']LJddn=;UU81LL]1]''X11D]T'X{vXv{s3G]XL]'G3'33CBh&99MCC{MC2299M3ChMMBB&|rQtt* ", +" /m]{{v{ghj&b&&&&&^j&[{{(s({vs(((@@@vmmmxx]xxDD;;U;JJnn;;;;;UU=;=;====;;nDxxxm5m@5@X@sGs@mS@@GG]JnJDdnUnJ'''D1d]S@SD;nJxSXXG']D;UU==oUUJL]LL''m]]L''GmG]LJJDL]DDm'mS]JJJLD]JJdd8;UU;nn1]]]'m''m'''mXXv3C3{33XXS]]]G33G33g92gv'}']11]11Uooo=====oo8ddd8UkkAAA%AA%AeAAAAAAAAAAA%AA%%AAAAAeAA%Akk=kk%%%%%%%AA%A%%%%kk=U;;nU;UdDJ'XX33{C{333C{2g2gggv333GDn;UUUJ]XvCg2949hjhhhB2CMC{C{{sCgBjjF2>2>3v333]nUUUUJLXvg22wwWjjwjjBh>MgMMgMg22j9{3333]DU=UUJ]X3C29ww9jgGGXGGLJJnnJLS3MBh>jj99wjjj92222922gG''XX]LdLL]''Mgh<2gCXXSSXL]L]SSGXghjM2922gXXGGGC33vssg2222MCsGCC333C{MM&hF<7:PPcPRQccccPcIIPccPPPcc))ccc))yy)#RQQQQ)#y##))Q##c)###0000####0#Q###yy77|^jj&bBh&||7rrOB&7Q0y77qY ", +" /bb&B&^jhCCCg3]']}vvC{X'mmT'x11dUUUU===oU8JL]]G333XX]LDL]]LDJ;k==UU8nLDL;nxDn;;;JJDJdJd]]ss[{(sGsG33333GsC{C92BBB222ggg{[gCC33Cggh&&CvmX{{CgCv1oU;JJ;=o88dLS'33333X]]DLD]LDJn=k=U88nL]];nDDn;;;JDJJJdd]Sss{[{ssG@33G333{CCC22BhB>22MMC{{MC333{MMBh&29jjjjhBB|<<||||7)cQcQcQQ##yy7|^|&&BM[GSSSSSSSsB|!(r ", +" bb!!!!!!!b!!!bbb((G([[(@(@@xDn;;nnnnDDDDnDnDDn;k%%AAA%A%%%%%%k%k%kk%k%%k%%%%k%%%%k%%%%%%AAA%%%k;k;=DLXX3ssM22jjj2hBM22>2292jjjjjj<jjj http://www.blakeramsdell.com + +; A poor attempt at brick out with no player involved. Maybe someday I'll +; let you play it, or you can view this as an exercise for the reader to put +; in a paddle that is user-controlled. + +; I guess this is Copyright (C) 2007 Blake Ramsdell, and you have a license to +; do whatever you want with it, just tell me what you did and give me a +; mention. If you want to sell it, and you make a billion dollars, then good +; for you. You might at least throw a party and invite me. + +; The gist of it is pretty simple -- you have a ball, and the ball has an X +; and a Y velocity. When it hits something, it bounces off of it. If the thing +; that it hits is not a wall, then it erases it. Pretty dead-simple behavior. + +; I don't like the vertical movement -- there's a shortcut in here somewhere +; to make it less computationally expensive I think. Right now it just does a +; two byte add and subtract of $20. + +; The ball motion is also a bit weird looking. I don't know if this is an +; artifact of the simulation environment combined with a normal tearing +; artifact related to refresh or what. + +; Blake Ramsdell, May 2007 + +init: + lda #$fe + sta $2 ; X velocity (0 = fast, ff = slow) + ; (low bit is direction, 0 = down or right, 1 = up or left) + lda #$ee + sta $3 ; Y velocity + +drawbox: + lda #0 ; Use $0-$1 as a screen address for drawing the field + sta $0 + lda #2 + sta $1 + + ldx #$20 ; Loop $20 times +boxloop: + lda #2 ; Line color (red) + sta $1ff,x ; Top line + sta $5df,x ; Bottom line + ldy #0 + sta ($0),y ; Left line + ldy #$1f + sta ($0),y ; Right line + + cpx #$1 ; If we're just before the bottom line... + beq noblocks ; Don't draw any blocks there + + + lda #3 ; First block for this row, Cyan in color + ldy #$17 ; It's at X position $17 + sta ($0),y ; Draw it + + lda #4 ; Second block for this row, Purple in color + iny ; It's at the next X position + sta ($0),y ; Draw it + + lda #5 ; Third block for this row, Green in color + iny ; It's at the next X position + sta ($0),y ; Draw it + + lda #6 ; Fourth block for this row, Blue in color + iny ; It's at the next X position + sta ($0),y ; Draw it + + +noblocks: + clc ; Get ready to increment the row, clear the carry for add + lda $0 ; Get the low byte + adc #$20 ; Add $20 to it for the next row + sta $0 ; Put it back + lda $1 ; Get the high byte + adc #0 ; Factor in the carry + sta $1 ; Put it back + + dex ; Decrement the loop counter + bne boxloop ; Do it again unless it's zero + + ldx $2 ; Load the X velocity + ldy $3 ; Load the Y velocity + + lda #$44 ; Pick a start point + sta $0 ; Ball position low + lda #$02 + sta $1 ; Ball position high + +drawball: + txa ; Preserve X + pha + lda #1 ; Ball color (white) + ldx #0 ; Clear X for indirect addressing for writing to screen + sta ($0,x) ; Draw the ball + pla ; Restore X + tax + +decloop: + dex ; Decrement the X velocity + beq updatexpos ; If it's zero, time to adjust X + dey ; Decrement the Y velocity + bne decloop ; If it's not zero, loop, otherwise fall through to adjust Y + +updateypos: + txa ; Preserve X + pha + jsr clearball ; Put background over the current ball position +updateyposnoclear: + lda $3 ; Get the Y velocity + and #1 ; See if it's down + bne moveup ; If not, then it's up, otherwise fall through to down + +movedown: + clc ; Prepare for moving to the next Y line and doing the add + lda $0 ; Low byte of the current ball position + adc #$20 ; Next row + sta $0 ; Put it back + bcc ycollision ; If no carry, go on to check for collision + inc $1 ; Had a carry, fix the high byte of the address + bne ycollision ; Z flag is always clear ($1 will never be zero) + +moveup: + sec ; Prepare for moving to the previous Y line and subtracting + lda $0 ; Low byte of the current ball position + sbc #$20 ; Previous row + sta $0 ; Put it back + lda $1 ; High byte + sbc #$0 ; Factor out the carry + sta $1 ; Put it back + +ycollision: + ldx #0 ; Prepare for indirect read + lda ($0,x) ; Get the current pixel at the new ball position + bne ycollided ; If it's not zero (the background color) then we hit + ldy $3 ; Otherwise, load up the current Y velocity + pla ; Restore the X velocity + tax + jmp drawball ; Back to the top + +ycollided: + cmp #$2 ; Border color? + beq ycollided2 ; If so, then we just bounce, don't eat a brick + + ; Erase brick + lda #0 ; Background color (black) + sta ($0,x) ; Erase it + +ycollided2: + lda #1 ; Get ready to change direction + eor $3 ; Flip the low bit on the Y velocity (change direction) + sta $3 ; Put it back + jmp updateyposnoclear ; Go back to make sure we didn't hit anything else + +updatexpos: + jsr clearball ; Put background over the current ball position +updatexposnoclear: + lda $2 ; Get the current X velocity + and #1 ; See if it's right by testing the low bit + bne moveleft ; If not, move left + +moveright: + inc $0 ; Move right + bne xcollision ; Z flag is always clear + +moveleft: + dec $0 ; Move left + +xcollision: + ldx #0 ; Prepare for indirect read + lda ($0,x) ; Get the current pixel at the new ball position + bne xcollided ; If it's not zero (the background color) then we hit + ldx $2 ; Otherwise, load up the current X velocity + jmp drawball ; Back to the top + +xcollided: + cmp #$2 ; Border color? + beq xcollided2 ; If so, then we just bounce, don't eat a brick + + ; Erase brick + lda #0 ; Background color (black) + sta ($0,x) ; Erase it + +xcollided2: + lda #1 ; Get ready to change direction + eor $2 ; Flip the low bit on the X velocity (change direction) + sta $2 ; Put it back + jmp updatexposnoclear ; Go back to make sure we didn't hit anything else + +clearball: + lda #0 ; Background color (black) + tax ; Clear X for indirect + sta ($0,x) ; Black out the ball + rts ; Return to caller + diff --git a/hacks/images/m6502/byterun.asm b/hacks/images/m6502/byterun.asm new file mode 100644 index 00000000..848b5c9f --- /dev/null +++ b/hacks/images/m6502/byterun.asm @@ -0,0 +1,100 @@ +; testing byterun compression + +start: + lda #logo + sta $1 + lda #$00 + sta $2 + lda #$02 + sta $3 + +decrunchLoop: + lda $3 + cmp #$6 + bne moreWork + rts +moreWork: + ldy #0 + lda ($0),y + cmp #$ff + bne notCrunched + iny + lda ($0),y ; repeat # + sta $4 + iny + lda ($0),y ; color + ldy $4 +drawLoop: + ldx #0 + sta ($2,x) + jsr nextPixel + dey + bne drawLoop + jsr getNextByte + jsr getNextByte + jmp decrunchLoop +notCrunched: + ldx #0 + sta ($2,x) + jsr nextPixel + jsr getNextByte + jmp decrunchLoop + +getNextByte: + inc $0 + lda $0 + cmp #$00 + bne notHi + inc $1 +notHi: + rts + +nextPixel: + inc $2 + ldx $2 + cpx #$00 + bne notNextLine + inc $3 +notNextLine: + rts + + +logo: + dcb $ff,43,1,$f,$f,$f,$c,$f,$f,$f,$ff,24,1,$c,$f,$c,0 + dcb $c,$f,$c,$ff,24,1,0,$f,$c,0,$c,$f,$c,$ff,24,1 + dcb $c,$f,$c,0,$c,$f,$c,$ff,24,1,0,$f,$c,0,$c,$f,$c + dcb $ff,24,1,$c,$f,0,0,$c,$f,$c,$ff,24,1,0,$f,$c,0 + dcb $c,$f,$c,$ff,24,1,0,$f,$c,0,$c,$f,0,$ff,24,1 + dcb 0,$f,$c,0,$c,$f,0,$ff,23,1,$f,0,$f,$c,0,$c,$f,0,$f + dcb $ff,22,1,$c,0,1,$c,0,$c,$f,0,$c,$ff,21,1 + dcb $f,0,0,1,0,0,$c,1,0,0,$ff,21,1,$c,0,$c,1,$c,0 + dcb $c,1,$c,0,$c,$ff,19,1,$f,0,0,$f,1,$c,0 + dcb $c,1,$f,0,0,$f,$ff,17,1,$f,0,0,0,1,1,$c,0 + dcb $c,1,1,0,0,0,$ff,16,1,$f,0,0,0,$f,1,1,0,0 + dcb $c,1,1,$f,0,0,0,$f,$ff,13,1 + dcb $c,0,0,0,$c,1,1,1,$c,0,$c,1,1,1,$c,0,0,0,$c + dcb $ff,10,1,$c,0,0,0,0,$c,1,1,1,1,0,0 + dcb $c,1,1,1,1,0,0,0,0,0,$c,$ff,8,1 + dcb 0,0,0,0,$c,1,1,1,1,1,0,0 + dcb $c,1,1,1,1,1,$c,0,0,0,0,1,1,1,1,1 + dcb 1,1,1,1,0,0,$c,1,1,1,1,1,1,1,$c,0 + dcb $c,1,1,1,1,1,1,$f,$c,0,0,$ff,18,1,$f + dcb $ff,53,1,0,$f,1,0,0,0,0,0,$f,1,$c + dcb $c,1,1,1,$c,0,0,0,1,1,0,$f,$f,1,1,1 + dcb 1,1,1,1,$c,0,0,1,1,1,0,$f,1,1,$f,0 + dcb 0,$f,1,1,0,$f,1,$c,$c,1,0,$f,1,1,1,1 + dcb 1,1,1,1,0,$f,0,$f,1,1,0,$f,1,1,$f,$c + dcb $c,$c,1,1,0,1,1,$f,0,1,0,$f,1,1,1,1 + dcb 1,1,1,1,0,1,$c,$f,1,1,$c,$f,1,1,0,$f + dcb $f,0,1,1,0,$f,$f,0,$f,1,0,$f,1,1,1,1 + dcb 1,1,1,$c,0,$c,0,0,1,1,0,$f,1,1,0,$c + dcb $c,0,$f,1,0,$f,0,$f,1,1,0,$f,1,1,1,1 + dcb 1,1,1,0,$c,$f,$f,0,$f,1,$c,$f,1,$c,$c,$f + dcb $f,$c,$c,1,0,1,$f,$c,1,1,0,$f,1,1,1,1 + dcb 1,1,$f,0,1,1,1,$c,$c,1,0,$f,1,0,$f,1 + dcb 1,$f,0,1,0,$f,1,0,$f,1,0,$f,$ff,16,1 + dcb $f,$ff,5,1,$f,1,1,1,$f,$ff,38,1 + + diff --git a/hacks/images/m6502/cellular-30.asm b/hacks/images/m6502/cellular-30.asm new file mode 100644 index 00000000..24395616 --- /dev/null +++ b/hacks/images/m6502/cellular-30.asm @@ -0,0 +1,67 @@ +; Rule 30 cellular automata +; by D.S. + + lda #1 + sta $20f + +l3: + lda #2 + sta 3 + sta 5 + sta 7 + lda #1 + sta 9 + sta 6 + lda #255 + sta 8 + lda #0 + sta 2 + lda #32 + sta 4 + ldx #30 +l1: + ldy #31 + +l2: + lda ($2),y + ora ($6),y + eor ($8),y + sta ($4),y + dey + bpl l2 + + lda $2 + adc #32 + sta $2 + lda $3 + adc #0 + sta $3 + lda $4 + adc #32 + sta $4 + lda $5 + adc #0 + sta $5 + lda $6 + adc #32 + sta $6 + lda $7 + adc #0 + sta $7 + lda $8 + adc #32 + sta $8 + lda $9 + adc #0 + sta $9 + dex + bpl l1 + + ldy #31 +l4: + lda ($2),y + sta $200,y + dey + bpl l4 + + jmp l3 diff --git a/hacks/images/m6502/cellular-600.asm b/hacks/images/m6502/cellular-600.asm new file mode 100644 index 00000000..db5497c9 --- /dev/null +++ b/hacks/images/m6502/cellular-600.asm @@ -0,0 +1,209 @@ +; Code 600 cellular automata - by D.S. + lda #1 + sta $22f + +l3: + ldy #29 + +l2: + lda $220,y + adc $221,y + adc $222,y + tax + lda rule,x + sta $201,y + dey + bpl l2 + + ldy #$c0 + sec +ll2: + lda $503,y + sta $523,y + sta $53b,y + lda $504,y + sta $524,y + sta $53a,y + lda $505,y + sta $525,y + sta $539,y + lda $506,y + sta $526,y + sta $538,y + lda $507,y + sta $527,y + sta $537,y + lda $508,y + sta $528,y + sta $536,y + lda $509,y + sta $529,y + sta $535,y + lda $50a,y + sta $52a,y + sta $534,y + lda $50b,y + sta $52b,y + sta $533,y + lda $50c,y + sta $52c,y + sta $532,y + lda $50d,y + sta $52d,y + sta $531,y + lda $50e,y + sta $52e,y + sta $530,y + lda $50f,y + sta $52f,y + tya + adc #$df + tay + bcs ll2 + + ldy #$e0 + sec +ll3: + lda $403,y + sta $423,y + sta $43b,y + lda $404,y + sta $424,y + sta $43a,y + lda $405,y + sta $425,y + sta $439,y + lda $406,y + sta $426,y + sta $438,y + lda $407,y + sta $427,y + sta $437,y + lda $408,y + sta $428,y + sta $436,y + lda $409,y + sta $429,y + sta $435,y + lda $40a,y + sta $42a,y + sta $434,y + lda $40b,y + sta $42b,y + sta $433,y + lda $40c,y + sta $42c,y + sta $432,y + lda $40d,y + sta $42d,y + sta $431,y + lda $40e,y + sta $42e,y + sta $430,y + lda $40f,y + sta $42f,y + tya + adc #$df + tay + bcs ll3 + + ldy #$e0 + sec +ll4: + lda $303,y + sta $323,y + sta $33b,y + lda $304,y + sta $324,y + sta $33a,y + lda $305,y + sta $325,y + sta $339,y + lda $306,y + sta $326,y + sta $338,y + lda $307,y + sta $327,y + sta $337,y + lda $308,y + sta $328,y + sta $336,y + lda $309,y + sta $329,y + sta $335,y + lda $30a,y + sta $32a,y + sta $334,y + lda $30b,y + sta $32b,y + sta $333,y + lda $30c,y + sta $32c,y + sta $332,y + lda $30d,y + sta $32d,y + sta $331,y + lda $30e,y + sta $32e,y + sta $330,y + lda $30f,y + sta $32f,y + tya + adc #$df + tay + bcs ll4 + + + ldy #$e0 + sec +ll1: + lda $203,y + sta $223,y + sta $23b,y + lda $204,y + sta $224,y + sta $23a,y + lda $205,y + sta $225,y + sta $239,y + lda $206,y + sta $226,y + sta $238,y + lda $207,y + sta $227,y + sta $237,y + lda $208,y + sta $228,y + sta $236,y + lda $209,y + sta $229,y + sta $235,y + lda $20a,y + sta $22a,y + sta $234,y + lda $20b,y + sta $22b,y + sta $233,y + lda $20c,y + sta $22c,y + sta $232,y + lda $20d,y + sta $22d,y + sta $231,y + lda $20e,y + sta $22e,y + sta $230,y + lda $20f,y + sta $22f,y + tya + adc #$df + tay + bcs ll1 + + jmp l3 + +; Rules, uncomment only one line of the following. +rule: + dcb 0,2,0,1,1,2,0 ; CODE 600 +; dcb 0,2,1,0,2,0,0 ; CODE 177 +; dcb 0,1,2,0,2,0,1; CODE 912 \ No newline at end of file diff --git a/hacks/images/m6502/colors.asm b/hacks/images/m6502/colors.asm new file mode 100644 index 00000000..2097f7ad --- /dev/null +++ b/hacks/images/m6502/colors.asm @@ -0,0 +1,46 @@ +; submitted by Anonymous + + jmp $700 + *=$700 + ldx #0 + ldy #0 + ;init screen + lda #0 + sta $0 + sta $3 + lda #2 + sta $1 +loop: + lda colors,x + bpl ok + inc $0 + ldx #0 + lda colors,x +ok: + inx + sta ($0),y + iny + bne ok2 + inc $1 + lda $1 + cmp #6 + beq end +ok2: + jmp loop +end: + inc $3 + lda $3 + and #$3f + tax + ldy #0 + lda #2 + sta $1 + sty $0 + jmp loop + +colors: +dcb 0,2,0,2,2,8,2,8,8,7,8,7,7,1,7,1,1,7,1,7,7,8,7,8 +dcb 8,2,8,2,2,0,2,0,2,2,8,2,8,8,7,8,7,7,1,7,1,1,1,1 +dcb 1,1,1,1,7,1,7,7,8,7,8,8,2,8,2,2,255 + + diff --git a/hacks/images/m6502/crunch6502.asm b/hacks/images/m6502/crunch6502.asm new file mode 100644 index 00000000..56ea5070 --- /dev/null +++ b/hacks/images/m6502/crunch6502.asm @@ -0,0 +1,292 @@ +;; Show "6502" on the screen waving up and down. +;; Jeremy English 29-December-2007 +;; +;; Each digit is stored as a pattern of vertical bits. +;; For example: +;; +;; 111111 This is the digit six. We think of the digit +;; 111111 by it's column pattern. The column patterns +;; 110000 are labeled at the bottom of the example. +;; 110000 Pattern B is 1100110011. The basic algorithm +;; 111111 is that we get the pattern, paint the first +;; 111111 bit (1 foreground, 0 background) then dec y +;; 110011 and get the next bit. +;; 110011 +;; 111111 The pattern for each digit is: +;; 111111 6 = AABBCC +;; ------ 5 = DDBBCC +;; AABBCC 0 = AAEEAA +;; 2 = CCBBDD + +;; Addresses $0 and $1 are used by the paint subroutine. +;; Addresses $2 through $6 are used by the display pattern subroutine +;; Address $7 is used in the main loop +;; Address $8 through $1a are used for the start positions +;; Address $1b is used by the display pattern subroutine +;; Address $1c is used as the color row offset. +;; Addresses $d0 through $ef store the font table + +jmp init_font_table +start: + +;; Initialize the pointers to the start position. +lda #y_start_pos1 +sta $c +lda #y_start_pos2 +sta $e +lda #y_start_pos3 +sta $10 +lda #y_start_pos4 +sta $12 +lda #y_start_pos5 +sta $14 +lda #y_start_pos4 +sta $16 +lda #y_start_pos3 +sta $18 +lda #y_start_pos2 +sta $1a + + +lda #0 ; start position to use +sta $8 + +main_loop: +inc $1c ; increment the color offset. +inc $1d ; increment the starting x position +ldy $8 ; load the current start position index +ldx $b,y ; get the lsb from the table +txa +sta $9 ; store the msb of the start position pointer +iny ; move to the next position in the table +ldx $b,y ; get the msb from the table +txa +sta $a ; store the lsb of the start position pointer +iny ; move the index up by one +tya +cmp #$10 ; have we looked at all 16 start positions? +bne store_idx ; if not then keep the index and store it +lda #0 ; set the index back to zero +store_idx: +sta $8 ; save the index back in memory + +ldy #0 +lda #$ff +sta $4 ; initialize the column to FF +display_loop: + inc $4 ; increment the column + ldx $d0,y ; load the lsb from the font table + stx $2 + iny + ldx $d0,y ; load the msb from the font table + stx $3 + sty $7 ; save y in memory + jsr dis_pat ; Jump to the display pattern subroutine. + inc $4 ; increment the column + jsr dis_pat ; Each pattern gets painted twice so we have a thicker font + ldy $7 ; get y out of memory + iny ; increment the index + tya + cmp #$20 ; Did we display all of the columns? + bne display_loop ;if not continue +jmp main_loop +rts + +init_font_table: + ;;Setup a table in the zero page that contains the string "6502" + lda #pattern_a + sta $d1 + lda #pattern_b + sta $d3 + lda #pattern_c + sta $d5 + lda #pattern_null + sta $d7 + lda #pattern_d + sta $d9 + lda #pattern_b + sta $db + lda #pattern_c + sta $dd + lda #pattern_null + sta $df + lda #pattern_a + sta $e1 + lda #pattern_e + sta $e3 + lda #pattern_a + sta $e5 + lda #pattern_null + sta $e7 + lda #pattern_c + sta $e9 + lda #pattern_b + sta $eb + lda #pattern_d + sta $ed + lda #pattern_null + sta $ef + jmp start + + +;; Display a pattern on the screen. The pattern to use is +;; stored at $2 and $3. The current column is stored at $4. +dis_pat: + ldy $4 ; Load the current column into y + lda ($9),y ; Get the start position for y + tay + sty $5 ; Store the starting position in memory + ldy #0 ; We have 12 bits that need to be painted +dis_pat_loop: + lda ($2),y ; get a bit from the pattern + pha ; save the color on the stack + tya ; move the index into the accumulator + clc ; clear the carry + adc $5 ; add the starting position to the index + sty $6 ; store the index + tay ; The calculated y position + ldx $4 ; The x position is the current column + pla ; pop the color off of the stack + beq go_paint ; black just paint it + clc ; get rid of any carry bit + sty $1b ; save the y coordinate + tya + clc + adc $1c ; add the color offset + and #$7 ; make sure the look up is in range + tay ; move the new index into y so we can look up the color + lda color_row,y ; if not black get the row color + ldy $1b ; restore the y coordinate +go_paint: + jsr paint ; paint the pixel on the screen + ldy $6 ; get the index out of memory + iny ; increment the index + tya + cmp #12 ; Have we looked at all of the bits? + bne dis_pat_loop ; if not then continue looking + rts ; else return from the subroutine + +;; Paint - Put a pixel on the screen by using the x registry for +;; the x position, the y registry for the y position and +;; the accumulator for the color. +paint: + pha ; Save the color + lda yl,y ; Get the LSB of the memory address for y + sta $0 ; Store it first + lda yh,y ; Get the MSB of the memory address for y + sta $1 ; Store it next + txa ; We want x in the y registry so we transfer it to A + tay ; and then A into y. + pla ; Pop the color off of the stack + sta ($0),y ; Store the color at the correct y + x address. + rts ; return from the subroutine. + +;; Paint uses the following two tables to look up the +;; correct address for a y coordinate between +;; 0 and 31. + +;; Y cord MSB +yh: + dcb $02, $02, $02, $02, $02, $02, $02, $02 + dcb $03, $03, $03, $03, $03, $03, $03, $03 + dcb $04, $04, $04, $04, $04, $04, $04, $04 + dcb $05, $05, $05, $05, $05, $05, $05, $05 +;; Y cord LSB +yl: + dcb $00, $20, $40, $60, $80, $a0, $c0, $e0 + dcb $00, $20, $40, $60, $80, $a0, $c0, $e0 + dcb $00, $20, $40, $60, $80, $a0, $c0, $e0 + dcb $00, $20, $40, $60, $80, $a0, $c0, $e0 + +;; A zero is on the end of each pattern to clean up +;; residue left by waving. +pattern_a: + dcb 0,1,1,1,1,1,1,1,1,1,1,0 + +pattern_b: + dcb 0,1,1,0,0,1,1,0,0,1,1,0 + +pattern_c: + dcb 0,1,1,0,0,1,1,1,1,1,1,0 + +pattern_d: + dcb 0,1,1,1,1,1,1,0,0,1,1,0 + +pattern_e: + dcb 0,1,1,0,0,0,0,0,0,1,1,0 + +pattern_null: + dcb 0,0,0,0,0,0,0,0,0,0,0,0 + +;; Table that store the current start position +;; of each y column. +y_start_pos1: + dcb 10,10,9,9,8,8,7,7,6,6,7,7,8,8,9,9,10,10,9,9,8,8,7,7 + dcb 6,6,7,7,8,8 + +y_start_pos2: + dcb 9,9,8,8,8,8,8,8,7,7,8,8,8,8,8,8,9,9,8,8,8,8,8,8 + dcb 7,7,8,8,8,8 + +y_start_pos3: + dcb 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8 + dcb 8,8,8,8,8,8 + +y_start_pos4: + dcb 7,7,8,8,8,8,8,8,9,9,8,8,8,8,8,8,7,7,8,8,8,8,8,8 + dcb 9,9,8,8,8,8 + +y_start_pos5: + dcb 6, 6,7,7,8,8,9,9,10,10,9,9,8,8,7,7, 6, 6,7,7,8,8,9,9 + dcb 10,10,9,9,8,8 + +color_row: + dcb $7,$8,$9,$2,$4,$6,$e,$3,$d,$5 diff --git a/hacks/images/m6502/demoscene.asm b/hacks/images/m6502/demoscene.asm new file mode 100644 index 00000000..fdd9361f --- /dev/null +++ b/hacks/images/m6502/demoscene.asm @@ -0,0 +1,457 @@ + +start: + ldx #0 +c:lda bottombar,x + cmp #$ff + beq init + sta $4e0,x + sta $5e0,x + inx + jmp c +init: + jsr initDraw + lda #0 + sta $10 ; scrptr + sta $11 ; txtptr +loop: + jsr drawMain + jsr putfont + jsr scrollarea + jmp loop + +scrollarea: + ldx #0 +g:lda $521,x + sta $520,x + lda $541,x + sta $540,x + lda $561,x + sta $560,x + lda $581,x + sta $580,x + lda $5a1,x + sta $5a0,x + inx + cpx #31 + bne g + rts + +putfont: + lda $10 ; scrptr + cmp #0 + bne noNext + inc $11 + ldx $11 + lda scrolltext,x + tax + lda fontSize,x + sta $10 +noNext: + dec $10 + ldx $11 + lda scrolltext,x + cmp #$ff + bne notResetText + lda #0 + sta $10 + sta $11 + rts + +notResetText: + asl + tax + lda fontlookup,x + sta $2 + inx + lda fontlookup,x + sta $3 + lda #fonts + adc $3 + sta $1 + ldy $10 + lda ($00),y + sta $53f + tya + clc + adc #6 + tay + lda ($00),y + sta $55f + tya + clc + adc #6 + tay + lda ($00),y + sta $57f + tya + clc + adc #6 + tay + lda ($00),y + sta $59f + tya + clc + adc #6 + tay + lda ($00),y + sta $5bf + rts + +initDraw: + lda #picture + sta $21 + lda #$00 + sta $22 + lda #$02 + sta $23 + ldx #$0 + rts +drawMain: + ldx #0 + lda ($20,x) + cmp #$ff + beq done + sta ($22,x) + inc $20 + lda $20 + cmp #$00 + bne n1 + inc $21 +n1: + inc $22 + lda $22 + cmp #$00 + bne done + lda $23 + cmp #$05 + beq done + inc $23 +done: + rts + +picture: + dcb 0,0,0,0,0,0,0,0,0,$b,$b,$c,$f,$f,$f,$f + dcb $f,$b,0,0,0,$b,$b,$c,$c,$f,$f,$b,0,0,0,0 + dcb 0,0,0,0,0,0,0,0,0,$b,$c,$c,$f,$c,$f,$f + dcb $b,$b,$b,$b,$b,0,$b,$b,$c,$f,$f,$c,0,0,0,0 + dcb 0,0,0,0,0,0,0,$b,0,$c,$b,$f,$c,$f,$f,$c + dcb $c,$b,0,$b,$c,$c,$c,$f,$f,1,$f,$c,$b,0,0,0 + dcb 0,0,0,0,0,0,0,0,$b,$b,$c,$c,$c,$f,$f,$f + dcb $c,$c,$c,$c,$c,$c,$f,$c,$f,$f,$f,$f,$b,0,0,0 + dcb 0,0,0,0,0,0,0,$b,0,0,$b,$c,$c,$f,$f,$f + dcb $f,$c,$f,$f,$f,$f,$f,$f,$f,1,$f,$f,$c,0,0,0 + dcb 0,0,0,0,0,0,0,0,0,$b,$b,$b,$c,$f,$f,1 + dcb $f,$f,$c,$f,$f,$f,1,$f,$f,$f,$f,$f,$f,0,0,0 + dcb 0,0,0,0,0,0,0,0,0,$b,$b,$b,$b,$c,$f,1 + dcb $f,$f,$f,$f,$f,$f,$f,$f,1,$f,$f,$f,$f,$b,0,0 + dcb 0,0,0,0,0,0,0,0,$b,0,$b,$c,$b,$c,$c,1 + dcb 1,$f,1,$f,1,$f,1,$f,$f,1,$f,$f,1,$b,0,0 + dcb 0,0,0,0,0,0,0,$b,$b,$b,$c,$c,$b,$c,$f,1 + dcb 1,1,$f,$f,1,$f,$f,1,$f,$f,$f,$f,1,$c,0,0 + dcb 0,0,0,0,0,0,0,$b,$b,$c,$c,$c,$b,$c,$c,$f + dcb 1,1,1,$f,$f,1,$f,1,$f,1,$f,$f,1,$c,0,0 + dcb 0,0,0,0,0,$b,$b,$b,$c,$c,$c,$f,$c,$c,$f,$f + dcb 1,1,1,1,$f,$f,$f,1,$f,1,$f,$f,$f,$f,0,0 + dcb 0,0,0,0,0,0,$b,$c,$c,$c,$f,$c,$f,$c,$f,$f + dcb 1,1,1,1,1,$f,$f,1,$f,$f,$f,$f,1,$f,$b,0 + dcb 0,0,0,0,$b,$b,$b,$c,$c,$f,$c,$f,$f,$c,$f,$f + dcb 1,1,1,1,1,$f,$f,$f,1,$f,$f,$f,1,$c,$b,$b + dcb 0,0,0,0,$b,$b,$c,$f,$c,$f,$f,$f,$f,$f,$c,$f + dcb 1,1,1,1,1,$f,$f,$f,1,$f,$f,$f,$f,$f,$b,$b + dcb 0,0,0,0,$b,$c,$c,$c,$f,$f,$f,$f,$f,$f,$f,$f + dcb $f,1,1,1,$f,$b,$f,$f,$f,1,$f,$f,$f,$f,$b,$b + dcb 0,0,0,0,$b,$c,$c,$f,$c,$f,$f,$f,$f,$f,$f,$f + dcb $f,$f,$f,$c,$b,$f,$f,1,$f,$f,$f,$f,$f,$f,$c,$b + dcb 0,0,0,0,$b,$b,$c,$c,$f,$c,$f,$f,$f,$f,$f,$f + dcb $c,$c,$b,$c,$c,$f,$f,1,$c,$c,$f,$f,$f,$f,$c,$b + dcb 0,0,0,0,$b,$b,$c,$c,$c,$f,$f,$f,$f,$f,$f,$f + dcb $f,$f,$f,$f,$f,1,$f,$c,$b,$f,$c,$f,$c,$f,$c,$b + dcb 0,0,0,0,0,$b,$c,$c,$c,$c,$f,$f,$f,$f,$f,$f + dcb $f,$f,$f,$f,$f,$c,$b,$c,$c,$c,$f,$f,$c,$f,$c,$c + dcb 0,0,0,0,0,$b,$b,$c,$c,$c,$c,$c,$f,$f,$f,$f + dcb $f,$f,$f,$c,$b,$b,$c,$c,$c,$f,$c,$f,$f,$f,$c,$b + dcb 0,0,0,0,0,$b,$b,$b,$b,$c,$c,$f,$c,$f,$f,$f + dcb $c,$c,$b,$b,$b,$c,$b,$b,$c,$c,$f,$c,$c,$f,$c,$c + dcb 0,0,0,0,0,0,$b,$b,$c,$b,$c,$c,$c,$c,$c,$c + dcb $b,$b,$b,$b,$c,$b,$b,$c,$c,$f,$f,$f,$c,$c,$c,$b + dcb 0,0,0,0,0,0,0,0,$b,$b,$b,$c,$c,$c,$c,$c + dcb $c,$c,$b,$b,$b,$b,$c,$c,$f,$f,$f,$c,$c,$c,$c,$c + dcb $ff + + +fontSize: + dcb 5,5,5,5,5,5,5,5 ;abcdefgh + dcb 2,5,5,5,6,6,5,5 ;ijklmnop + dcb 6,5,5,4,5,6,6,6 ;qrstuvwx + dcb 6,5,2,3 ;yz.[SPACE] + +; +; a=0, b=1, c=2, d=3.... +; + +scrolltext: + dcb 0 + + dcb 14,13,11,24,27 ; "only " + dcb 03,04,15,19,07,27 ; "depth " + dcb 12,0,10,4,18,27 ; "makes " + dcb 8,19,27 ; "it " + dcb 15,14,18,18,8,1,11,4 ; "possible" + dcb 26,26,26 ; "..." + dcb 19,7,8,18,27 ; "this " + dcb 8,18,27 ; "is " + dcb 19,7,4,27 ; "the " + dcb 5,8,17,18,19,27 ; "first " + dcb 3,4,12,14,27 ; "demo " + dcb 12,0,3,4,27 ; "made " + dcb 8,13,27 ; "in " + dcb 19,7,8,18,27 ; "this " + dcb 4,13,21,26,26,26,26,27 ; "env.... " + dcb 7,14,15,4,27 ; "hope " + dcb 24,14,20,27 ; "you " + dcb 11,8,10,4,27 ; "like " + dcb 8,19,26,26,26,27,27 ; "it... " + dcb 22,22,22,26 ; "www." + dcb 3,4,15,19,7,26 ; "depth." + dcb 14,17,6,27,27,27,27,27 ; "org " + + dcb $ff ; end of text + +fontlookup: + dcb $00,$00 ;a + dcb $20,$00 ;b + dcb $40,$00 ;c + dcb $60,$00 ;d + dcb $80,$00 ;e + dcb $a0,$00 ;f + dcb $c0,$00 ;g + dcb $e0,$00 ;h + dcb $00,$01 ;i + dcb $20,$01 ;j + dcb $40,$01 ;k + dcb $60,$01 ;l + dcb $80,$01 ;m + dcb $a0,$01 ;n + dcb $c0,$01 ;o + dcb $e0,$01 ;p + dcb $00,$02 ;q + dcb $20,$02 ;r + dcb $40,$02 ;s + dcb $60,$02 ;t + dcb $80,$02 ;u + dcb $a0,$02 ;v + dcb $c0,$02 ;w + dcb $e0,$02 ;x + dcb $00,$03 ;y + dcb $20,$03 ;z + dcb $40,$03 ;. + dcb $60,$03 ;" " + +fonts: + dcb 0,1,1,0,0,0 + dcb 1,0,0,1,0,0 + dcb 1,1,1,1,0,0 + dcb 1,0,0,1,0,0 + dcb 1,0,0,1,0,0 + dcb 0,0 + + dcb 0,1,1,1,0,0 + dcb 1,0,0,1,0,0 + dcb 0,1,1,1,0,0 + dcb 1,0,0,1,0,0 + dcb 0,1,1,1,0,0 + dcb 0,0 + + dcb 0,1,1,0,0,0 + dcb 1,0,0,1,0,0 + dcb 0,0,0,1,0,0 + dcb 1,0,0,1,0,0 + dcb 0,1,1,0,0,0 + dcb 0,0 + + dcb 0,1,1,1,0,0 + dcb 1,0,0,1,0,0 + dcb 1,0,0,1,0,0 + dcb 1,0,0,1,0,0 + dcb 0,1,1,1,0,0 + dcb 0,0 + + dcb 1,1,1,1,0,0 + dcb 0,0,0,1,0,0 + dcb 0,1,1,1,0,0 + dcb 0,0,0,1,0,0 + dcb 1,1,1,1,0,0 + dcb 0,0 + + dcb 1,1,1,1,0,0 + dcb 0,0,0,1,0,0 + dcb 0,1,1,1,0,0 + dcb 0,0,0,1,0,0 + dcb 0,0,0,1,0,0 + dcb 0,0 + + dcb 1,1,1,0,0,0 + dcb 0,0,0,1,0,0 + dcb 1,1,0,1,0,0 + dcb 1,0,0,1,0,0 + dcb 1,1,1,0,0,0 + dcb 0,0 + + dcb 1,0,0,1,0,0 + dcb 1,0,0,1,0,0 + dcb 1,1,1,1,0,0 + dcb 1,0,0,1,0,0 + dcb 1,0,0,1,0,0 + dcb 0,0 + + dcb 1,0,0,0,0,0 + dcb 1,0,0,0,0,0 + dcb 1,0,0,0,0,0 + dcb 1,0,0,0,0,0 + dcb 1,0,0,0,0,0 + dcb 0,0 + + dcb 1,0,0,0,0,0 + dcb 1,0,0,0,0,0 + dcb 1,0,0,0,0,0 + dcb 1,0,0,1,0,0 + dcb 0,1,1,0,0,0 + dcb 0,0 + + dcb 1,0,0,1,0,0 + dcb 0,1,0,1,0,0 + dcb 0,0,1,1,0,0 + dcb 0,1,0,1,0,0 + dcb 1,0,0,1,0,0 + dcb 0,0 + + dcb 0,0,0,1,0,0 + dcb 0,0,0,1,0,0 + dcb 0,0,0,1,0,0 + dcb 0,0,0,1,0,0 + dcb 1,1,1,1,0,0 + dcb 0,0 + + dcb 1,0,0,0,1,0 + dcb 1,1,0,1,1,0 + dcb 1,0,1,0,1,0 + dcb 1,0,0,0,1,0 + dcb 1,0,0,0,1,0 + dcb 0,0 + + dcb 1,0,0,0,1,0 + dcb 1,0,0,1,1,0 + dcb 1,0,1,0,1,0 + dcb 1,1,0,0,1,0 + dcb 1,0,0,0,1,0 + dcb 0,0 + + dcb 0,1,1,0,0,0 + dcb 1,0,0,1,0,0 + dcb 1,0,0,1,0,0 + dcb 1,0,0,1,0,0 + dcb 0,1,1,0,0,0 + dcb 0,0 + + dcb 0,1,1,1,0,0 + dcb 1,0,0,1,0,0 + dcb 0,1,1,1,0,0 + dcb 0,0,0,1,0,0 + dcb 0,0,0,1,0,0 + dcb 0,0 + + dcb 0,1,1,0,0,0 + dcb 1,0,0,1,0,0 + dcb 1,0,0,1,0,0 + dcb 0,1,0,1,0,0 + dcb 1,0,1,0,0,0 + dcb 0,0 + + dcb 0,1,1,1,0,0 + dcb 1,0,0,1,0,0 + dcb 0,1,1,1,0,0 + dcb 0,1,0,1,0,0 + dcb 1,0,0,1,0,0 + dcb 0,0 + + dcb 1,1,1,0,0,0 + dcb 0,0,0,1,0,0 + dcb 0,1,1,0,0,0 + dcb 1,0,0,0,0,0 + dcb 0,1,1,1,0,0 + dcb 0,0 + + dcb 1,1,1,0,0,0 + dcb 0,1,0,0,0,0 + dcb 0,1,0,0,0,0 + dcb 0,1,0,0,0,0 + dcb 0,1,0,0,0,0 + dcb 0,0 + + dcb 1,0,0,1,0,0 + dcb 1,0,0,1,0,0 + dcb 1,0,0,1,0,0 + dcb 1,0,0,1,0,0 + dcb 1,1,1,0,0,0 + dcb 0,0 + + dcb 1,0,0,0,1,0 + dcb 1,0,0,0,1,0 + dcb 1,0,0,0,1,0 + dcb 0,1,0,1,0,0 + dcb 0,0,1,0,0,0 + dcb 0,0 + + dcb 1,0,0,0,1,0 + dcb 1,0,0,0,1,0 + dcb 1,0,1,0,1,0 + dcb 1,1,0,1,1,0 + dcb 1,0,0,0,1,0 + dcb 0,0 + + dcb 1,0,0,0,1,0 + dcb 0,1,0,1,0,0 + dcb 0,0,1,0,0,0 + dcb 0,1,0,1,0,0 + dcb 1,0,0,0,1,0 + dcb 0,0 + + dcb 1,0,0,0,1,0 + dcb 0,1,0,1,0,0 + dcb 0,0,1,0,0,0 + dcb 0,0,1,0,0,0 + dcb 0,0,1,0,0,0 + dcb 0,0 + + dcb 1,1,1,1,0,0 ; z + dcb 1,0,0,0,0,0 + dcb 0,1,1,0,0,0 + dcb 0,0,0,1,0,0 + dcb 1,1,1,1,0,0 + dcb 0,0 + + dcb 0,0,0,0,0,0 ; . + dcb 0,0,0,0,0,0 + dcb 0,0,0,0,0,0 + dcb 0,0,0,0,0,0 + dcb 1,0,0,0,0,0 + dcb 0,0 + + dcb 0,0,0,0,0,0 ; " " + dcb 0,0,0,0,0,0 + dcb 0,0,0,0,0,0 + dcb 0,0,0,0,0,0 + dcb 0,0,0,0,0,0 + dcb 0,0 + +bottombar: + dcb $b,$9,$b,9,8,9,8,$a,8,$a,7,$a,7,1,7,1,1 + dcb 7,1,7,$a,7,$a,8,$a,8,9,8,9,$b,9,$b + dcb $ff + diff --git a/hacks/images/m6502/disco.asm b/hacks/images/m6502/disco.asm new file mode 100644 index 00000000..bc69d703 --- /dev/null +++ b/hacks/images/m6502/disco.asm @@ -0,0 +1,23 @@ +; DISCO DISCO +; submitted by Anonymous + +start: + inx + txa + sta $200, y + sta $300, y + sta $400, y + sta $500, y + iny + tya + cmp 16 + bne do + iny + jmp start +do: + iny + iny + iny + iny +jmp start + diff --git a/hacks/images/m6502/dmsc.asm b/hacks/images/m6502/dmsc.asm new file mode 100644 index 00000000..9dfd7dde --- /dev/null +++ b/hacks/images/m6502/dmsc.asm @@ -0,0 +1,108 @@ +; By DMSC - daniel.serpell@gmail.com +; +; This demo was programmed in ACME: +; http://www.esw-heim.tu-clausthal.de/~marco/smorbrod/acme/ +; +; If you want the source code, send me an email :-) +; + + dcb 76, 94, 11,133, 32,162, 8,160, 8,145, 16,136,208,251,165, 16 + dcb 24,105, 32,133, 16,165, 17,105, 0,133, 17,165, 32,202,208,231 + dcb 96,230, 48,165, 48, 41, 63,133, 48,170,189,106, 6,170,189, 8 + dcb 3,105, 1, 41, 3,157, 8, 3,138, 73,231,170,189, 0, 2,105 + dcb 1, 41, 3,157, 0, 2,165, 48, 73, 63,170,189,106, 6, 73,224 + dcb 170,189, 8, 2,105, 1, 41, 3,157, 8, 2,138, 73,231,170,189 + dcb 0, 3,105, 1, 41, 3,157, 0, 3, 96,224,192,160,128, 96,225 + dcb 64,193,161,226,129, 32,194, 97,162,227,195,130,228, 65,163,196 + dcb 98,229,131,164,197,230,231,132,165,198, 99, 66, 33, 0,199,166 + dcb 133,100,167, 67,134,101,135, 34, 68,102,103, 69, 35, 70, 71, 36 + dcb 1, 37, 38, 39, 2, 3, 4, 5, 6, 7,166, 48,189,198, 6,170 + dcb 254, 24, 3, 73, 7,170,254, 16, 3, 73,231,170,254, 24, 2, 73 + dcb 7,170,254, 16, 2, 96, 0, 32, 1, 33, 64, 2, 65, 34, 96, 66 + dcb 3, 97, 35, 98, 67,128, 4,129, 36, 99,130, 68,160, 5,161,131 + dcb 100, 37,162, 69,132,192,163,101, 6,193, 38,194, 70,164,133,195 + dcb 102,224, 7,225, 39,165,226,196,134, 71,227,103,197,166,228,135 + dcb 198,229,167,230,199,231,166, 49,189, 21, 7,170,189, 0,160,157 + dcb 0, 5,230, 49, 96,195,227,194,162,228, 97,226,128,129,130,225 + dcb 64,161,163,224, 96,160,193,196, 32, 98,192, 65, 0,131,229,164 + dcb 33, 99,197, 66,132, 1,230, 34,165, 67,100,198, 2, 3, 68, 6 + dcb 35,133,166, 5,101, 4,199, 7, 36,231, 69,134,167, 37, 38,102 + dcb 135, 70,232, 71, 39,103,136,200,168, 8, 11, 10,169,233,104, 9 + dcb 12,137,201, 13, 40, 44, 72, 43,170, 42, 45, 41,105, 73,202, 14 + dcb 138,234, 74, 75,106,203, 76,171, 46, 77,235,107,139, 15,108,172 + dcb 174,140,173,141,142,204,109,206,207,205, 78,175, 47,236,239,143 + dcb 237,238,110,240,241,111,208, 16, 79,176,209,242, 48,144,243, 80 + dcb 177,244,112,210, 17, 49,178,179, 52, 53,147, 18, 81,211,145, 19 + dcb 146, 51, 85,180, 20, 54,113,148, 22, 50, 84,212, 21, 55,115,245 + dcb 83,114,116, 23, 82, 86, 88, 89, 87,118,117,119,149,213, 56, 57 + dcb 181,214, 90,121,122,150,151,182,183,215,246, 58,120,247, 24,153 + dcb 184,152,216, 25, 26, 59, 91,248,123,185, 27, 60,217,154, 28, 92 + dcb 249, 29,155,186, 61,218, 93,124,250,187, 30,251, 62,156, 94,125 + dcb 219,188, 31,252,254,220,253, 63,126,255,157,221, 95,159,191,222 + dcb 127,189,223,158,190,165, 66, 41,224,208, 72,165, 66, 24,105, 1 + dcb 41, 31,133, 66,165, 67,240, 7,198, 67,169, 0, 76, 97, 8,198 + dcb 69,240,247, 16, 37,166, 64,230, 64,189,177, 9, 16, 15, 41,127 + dcb 133, 67, 73,127,208,228,169, 1,133, 70, 76, 42, 8,170,189,117 + dcb 8,133, 69,234,234,189,181, 8,133, 65,166, 65,230, 65,189,245 + dcb 8,133, 68,165, 66, 24,105,224,133, 66,166, 66,169, 1,102, 68 + dcb 42,157, 0,160, 96, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 2 + dcb 3, 2, 3, 3, 3, 3, 3, 1, 2, 3, 1, 5, 3, 3, 3, 3 + dcb 3, 2, 2, 3, 3, 5, 4, 3, 3, 5, 4, 4, 4, 3, 3, 4 + dcb 4, 1, 3, 4, 3, 5, 5, 5, 4, 5, 4, 4, 3, 4, 4, 7 + dcb 4, 4, 4, 2, 1, 0, 3, 6, 9, 12, 15, 18, 21, 24, 27, 30 + dcb 32, 35, 35, 38, 40, 43, 46, 49, 50, 52, 4, 55, 55, 60, 63, 65 + dcb 68, 71, 73, 75, 78, 78, 33, 83, 86, 89, 94, 98,102,106,109,112 + dcb 116, 94,120,123,127,130,134,139,144,148,153,157,161,164,167,171 + dcb 178,171,182,186, 5, 56, 68, 56, 36,124, 4, 76, 84, 36, 68, 84 + dcb 40, 24, 40,124,100, 84, 88, 56, 84, 72, 76, 80, 96, 40, 84, 40 + dcb 36, 84, 56, 44, 28,124, 36, 24, 24, 36,124, 24, 52, 16, 60, 80 + dcb 24, 37, 30,124, 32, 28,188, 1,190,124, 24, 36, 60, 32, 28, 32 + dcb 28, 24, 36, 24, 63, 36, 24, 36, 63, 60, 16, 32, 52, 44,120, 36 + dcb 56, 4, 60, 56, 4, 56, 4, 56, 57, 6, 56, 44, 52, 36, 12, 48 + dcb 208, 48, 12,252,164,164, 88,120,132,132, 72,252,132,132,120,252 + dcb 164,132,252,160,128,120,132,164, 56,252, 32, 32,252, 8, 4,248 + dcb 252, 48, 80,140,252, 4, 4,252, 64, 60, 64,252, 64, 48, 8,252 + dcb 120,132,132,132,120,252,144,144, 96,120,132,134,133,120,252,144 + dcb 144,108, 68,164,164,152,128,252,128,248, 4, 4,248, 4, 8,240 + dcb 224, 28, 16,224, 28, 16,224,204, 48, 48,204,140,148,164,196, 0 + dcb 0,133, 41, 10, 28, 29, 63, 63, 63,136, 15, 10, 28, 29, 14, 27 + dcb 63, 63, 63,132, 55, 17, 18, 28, 62, 18, 28, 62, 10,136, 27, 14 + dcb 10, 21, 21, 34,143, 15, 10, 28, 29,142, 39, 40, 48, 50,149,145 + dcb 10, 23, 13, 62, 23, 24, 32,136, 28, 24, 22, 14,136, 11, 14, 10 + dcb 30, 29, 18, 15, 30, 21,128, 14, 15, 15, 14, 12, 29, 28, 63, 63 + dcb 63,144,159,255, 55, 17, 18, 28, 62, 18, 28, 62, 10, 21, 21,129 + dcb 15, 24, 27, 62, 23, 24, 32,136, 11, 34, 14, 63, 63, 63,141, 63 + dcb 63, 63, 11, 34, 14,150,159,143, 11, 34, 62, 39, 48, 54, 38, 2 + dcb 0, 0, 7, 63, 5, 63, 2, 9, 11, 34, 62, 39, 48, 54, 38, 2 + dcb 0, 0, 7, 63, 5, 63, 2, 9, 11, 34, 62, 39, 48, 54, 38, 2 + dcb 0, 0, 7, 63, 5, 63, 2, 9,143,159,255,169, 0,133, 42,169 + dcb 1,133, 44,133, 45,169, 0,133, 32,169,160,133, 33,165, 42,133 + dcb 43,162, 15,160, 15,145, 32, 24,101, 44,230, 44,136, 16,246,165 + dcb 32, 24,105, 32,133, 32,165, 33,105, 0,133, 33,169, 1,133, 44 + dcb 165, 43, 24,101, 45,133, 43,230, 45,202, 16,215,169, 0,133, 32 + dcb 169,160,133, 33,169,224,133, 34,169, 3,133, 35,169, 0,133, 36 + dcb 169, 4,133, 37,169,240,133, 38,169, 3,133, 39,169, 16,133, 40 + dcb 169, 4,133, 41,169, 15,133, 46,160, 15,177, 32, 74, 74, 74, 74 + dcb 170,189, 62, 11,209, 34,240, 18,145, 34,145, 36,170,152, 73, 15 + dcb 168,138,145, 38,145, 40,152, 73, 15,168,136, 16,221,165, 32, 24 + dcb 105, 32,133, 32,165, 33,105, 0,133, 33,165, 34, 24,105,224,133 + dcb 34,165, 35,105,255,133, 35,165, 36, 24,105, 32,133, 36,165, 37 + dcb 105, 0,133, 37,165, 38, 24,105,224,133, 38,165, 39,105,255,133 + dcb 39,165, 40, 24,105, 32,133, 40,165, 41,105, 0,133, 41,198, 46 + dcb 16,150,230, 42,165, 42, 41, 63,240, 3, 76, 95, 10, 96, 0, 11 + dcb 12, 15, 1, 15, 12, 11, 0, 11, 12, 15, 1, 15, 12, 11, 0, 11 + dcb 12, 15, 1, 15, 12, 11, 0, 11, 12, 15, 1, 15, 12, 11,169, 1 + dcb 162,255,134, 16,162, 1,134, 17, 32, 3, 6,169, 2,162, 7,134 + dcb 16,162, 2,134, 17, 32, 3, 6,169, 3,162, 7,134, 16,162, 3 + dcb 134, 17, 32, 3, 6,169, 31,133, 66,169, 0,133, 70,133, 67,133 + dcb 64,169, 1,141,109, 8,169, 0,141,114, 8,169,160,141,115, 8 + dcb 169, 63,133, 48,169,128,133, 49,169, 3,141,109, 8,169, 0,170 + dcb 157, 0,160,232,208,250, 32, 33, 6, 32,170, 6, 32, 6, 7, 32 + dcb 21, 8,165, 66, 73, 31,208, 13,173,109, 8, 24,105, 2, 41, 3 + dcb 105, 3,141,109, 8,165, 49,208,221,173, 17, 7, 73, 1,141, 17 + dcb 7,165, 70,240,209, 32, 29, 12, 32, 91, 10,169, 31,133, 66,169 + dcb 0,133, 70,133, 67,141,109, 8,169, 0,141,114, 8,169, 3,141 + dcb 115, 8, 32, 29, 12, 32, 21, 8,165, 66, 73, 31,208,247,173,115 + dcb 8, 73, 7,141,115, 8,165, 70,240,235, 76, 94, 11,169, 0,170 + dcb 157, 0, 2,157, 0, 3,157, 0, 4,157, 0, 5,232,208,241, 96 + diff --git a/hacks/images/m6502/dragon-fractal.asm b/hacks/images/m6502/dragon-fractal.asm new file mode 100644 index 00000000..ce05ad4c --- /dev/null +++ b/hacks/images/m6502/dragon-fractal.asm @@ -0,0 +1,49 @@ +;; dmsc +;; +;; PostPosted: Thu Dec 13, 2007 11:57 pm Post subject: Dragon curve +;; fractal +;; +;; +;; Hi! +;; +;; This draws the dragon curve fractal (really a "twin dragon"): + +lda #0 + sta $0 + +lop: + lda $0 + sta $1 + lda #3 + sta $6 + lda #232 + sta $5 + + ldx #0 +lpN: + lsr $1 + bcc nos + lda $5 + clc + adc tL,x + sta $5 + lda $6 + adc tH,x + sta $6 +nos: + inx + lda $1 + bne lpN + inx + txa + ldy #0 + sta ($5),y + + inc $0 + bne lop + rts + +tL: + dcb 32, 31, 254, 190, 128, 132, 8, 8 +tH: + dcb 0, 0, 255, 255, 255, 255, 0, 1 diff --git a/hacks/images/m6502/fullscreenlogo.asm b/hacks/images/m6502/fullscreenlogo.asm new file mode 100644 index 00000000..6f9b079b --- /dev/null +++ b/hacks/images/m6502/fullscreenlogo.asm @@ -0,0 +1,107 @@ +; +; draw image +; + +start: + lda #logo + sta $1 + + lda #$00 + sta $2 + lda #$02 + sta $3 + + ldx #$0 +l: + lda ($0,x) + sta ($2,x) + + inc $00 + lda $00 + cmp #$00 + bne notReset1 + inc $01 +notReset1: + + inc $02 + lda $02 + cmp #$00 + bne notReset2 + lda $03 + cmp #$05 + beq done + inc $03 +notReset2: + + jmp l +done: + rts + +logo: + dcb 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1 + dcb 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1 + dcb 1,1,1,1,1,1,1,1,1,1,1,1,1,6,6,6 + dcb 6,6,6,6,1,1,1,1,1,1,1,1,1,1,1,1 + dcb 1,1,1,1,1,1,1,1,1,1,6,6,6,6,6,6 + dcb 6,6,6,6,6,1,1,1,1,1,1,1,1,1,1,1 + dcb 1,1,1,1,1,1,1,1,6,6,6,6,6,6,6,6 + dcb 6,6,6,6,6,1,1,1,1,1,1,1,1,1,1,1 + dcb 1,1,1,1,1,1,1,6,6,6,6,6,6,6,6,6 + dcb 6,6,6,6,6,1,1,1,1,1,1,1,1,1,1,1 + dcb 1,1,1,1,1,1,6,6,6,6,6,6,6,6,6,6 + dcb 6,6,6,6,6,1,1,1,1,1,1,1,1,1,1,1 + dcb 1,1,1,1,1,6,6,6,6,6,6,6,6,6,6,6 + dcb 6,6,6,6,6,1,1,1,1,1,1,1,1,1,1,1 + dcb 1,1,1,1,6,6,6,6,6,6,6,6,6,6,6,6 + dcb 6,6,6,6,6,1,1,1,1,1,1,1,1,1,1,1 + dcb 1,1,1,6,6,6,6,6,6,6,6,6,6,6,6,1 + dcb 1,1,1,6,6,1,1,1,1,1,1,1,1,1,1,1 + dcb 1,1,1,6,6,6,6,6,6,6,6,6,6,1,1,1 + dcb 1,1,1,1,1,6,6,6,6,6,6,6,6,6,6,6 + dcb 1,1,6,6,6,6,6,6,6,6,6,1,1,1,1,1 + dcb 1,1,1,1,1,6,6,6,6,6,6,6,6,6,6,1 + dcb 1,1,6,6,6,6,6,6,6,6,1,1,1,1,1,1 + dcb 1,1,1,1,1,6,6,6,6,6,6,6,6,6,1,1 + dcb 1,1,6,6,6,6,6,6,6,6,1,1,1,1,1,1 + dcb 1,1,1,1,1,6,6,6,6,6,6,6,6,1,1,1 + dcb 1,6,6,6,6,6,6,6,6,1,1,1,1,1,1,1 + dcb 1,1,1,1,1,6,6,6,6,6,6,6,1,1,1,1 + dcb 1,6,6,6,6,6,6,6,6,1,1,1,1,1,1,1 + dcb 1,1,1,1,1,6,6,6,6,6,6,1,1,1,1,1 + dcb 1,6,6,6,6,6,6,6,6,1,1,1,1,1,1,1 + dcb 1,1,1,1,1,6,6,6,6,6,1,1,1,1,1,1 + dcb 1,6,6,6,6,6,6,6,6,1,1,1,1,1,1,1 + dcb 1,1,1,1,1,2,2,2,2,2,1,1,1,1,1,1 + dcb 1,6,6,6,6,6,6,6,6,1,1,1,1,1,1,1 + dcb 1,1,1,1,1,2,2,2,2,2,2,1,1,1,1,1 + dcb 1,6,6,6,6,6,6,6,6,1,1,1,1,1,1,1 + dcb 1,1,1,1,1,2,2,2,2,2,2,2,1,1,1,1 + dcb 1,6,6,6,6,6,6,6,6,1,1,1,1,1,1,1 + dcb 1,1,1,1,1,2,2,2,2,2,2,2,2,1,1,1 + dcb 1,1,6,6,6,6,6,6,6,6,1,1,1,1,1,1 + dcb 1,1,1,1,1,2,2,2,2,2,2,2,2,2,1,1 + dcb 1,1,6,6,6,6,6,6,6,6,6,1,1,1,1,1 + dcb 1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,1 + dcb 1,1,1,6,6,6,6,6,6,6,6,6,1,1,1,1 + dcb 1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2 + dcb 1,1,1,6,6,6,6,6,6,6,6,6,6,1,1,1 + dcb 1,1,1,1,6,1,1,1,1,1,1,1,1,1,1,1 + dcb 1,1,1,1,6,6,6,6,6,6,6,6,6,6,6,6 + dcb 6,6,6,6,6,1,1,1,1,1,1,1,1,1,1,1 + dcb 1,1,1,1,6,6,6,6,6,6,6,6,6,6,6,6 + dcb 6,6,6,6,6,1,1,1,1,1,1,1,1,1,1,1 + dcb 1,1,1,1,1,6,6,6,6,6,6,6,6,6,6,6 + dcb 6,6,6,6,6,1,1,1,1,1,1,1,1,1,1,1 + dcb 1,1,1,1,1,1,6,6,6,6,6,6,6,6,6,6 + dcb 6,6,6,6,6,1,1,1,1,1,1,1,1,1,1,1 + dcb 1,1,1,1,1,1,1,1,6,6,6,6,6,6,6,6 + dcb 6,6,6,6,6,1,1,1,1,1,1,1,1,1,1,1 + dcb 1,1,1,1,1,1,1,1,1,6,6,6,6,6,6,6 + dcb 6,6,6,6,6,1,1,1,1,1,1,1,1,1,1,1 + dcb 1,1,1,1,1,1,1,1,1,1,1,1,6,6,6,6 + dcb 6,6,6,6,6,1,1,1,1,1,1,1,1,1,1,1 + dcb 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1 + dcb 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1 + diff --git a/hacks/images/m6502/keftal.asm b/hacks/images/m6502/keftal.asm new file mode 100644 index 00000000..efb29829 --- /dev/null +++ b/hacks/images/m6502/keftal.asm @@ -0,0 +1,82 @@ +; awfully slow.. be patient + +init: + ldx #0 + stx $0 + inx + stx $2 + stx $3 + inx + stx $1 + +loop: + lda $2 + cmp #$20 + bne notIncF2 + inc $3 + lda #0 + sta $2 +notIncF2: + inc $2 + +; CALCULATE START + + lda $2 + sta $f1 + lda $2 + sta $f2 + jsr multiply + + lda $f4 + sta $f8 + + lda $3 + sta $f1 + lda $3 + sta $f2 + jsr multiply + +; CALCULATE STOP + + lda $f4 + clc + adc $f8 + + lsr + lsr + lsr + lsr + lsr + ldx #0 + sta ($0,x) + inc $0 + lda $0 + cmp #$00 + bne notNextY + inc $1 + lda $1 + cmp #6 + beq exit +notNextY: + jmp loop +exit: + rts + +multiply: + lda #0 + sta $f4 + sta $f5 + ldx #8 +a:asl $f4 + rol $f5 + asl $f2 + bcc b + clc + lda $f4 + adc $f1 + sta $f4 + bcc b + inc $f5 +b:dex + bne a + rts \ No newline at end of file diff --git a/hacks/images/m6502/matrix.asm b/hacks/images/m6502/matrix.asm new file mode 100644 index 00000000..0ec27a7c --- /dev/null +++ b/hacks/images/m6502/matrix.asm @@ -0,0 +1,67 @@ +;;Matrix :) + +loop: + lda $fe + and #$1f + tay + tax + lda matrix,y + sta $1 + tay + lda #0 + jsr paint + inc $1 + lda $1 + and #$1f + sta matrix,y + tay + lda #5 + jsr paint + lda $fe + and #$1f + tay + tax + lda matrix,y + sta $1 + tay + lda #$d + jsr paint + lda $fe + and #$1f + tay + tax + lda matrix,y + sta $1 + tay + lda #$5 + jsr paint + jmp loop + +paint: + pha + lda yl,y + sta $2 + lda yh,y + sta $3 + txa + tay + pla + sta ($2),y + rts + +yh: + dcb $02, $02, $02, $02, $02, $02, $02, $02 + dcb $03, $03, $03, $03, $03, $03, $03, $03 + dcb $04, $04, $04, $04, $04, $04, $04, $04 + dcb $05, $05, $05, $05, $05, $05, $05, $05 + +yl: + dcb $00, $20, $40, $60, $80, $a0, $c0, $e0 + dcb $00, $20, $40, $60, $80, $a0, $c0, $e0 + dcb $00, $20, $40, $60, $80, $a0, $c0, $e0 + dcb $00, $20, $40, $60, $80, $a0, $c0, $e0 + +matrix: + dcb 5,16,19,19,17,26,10,14,11,4,1,2,20,1,8,30 + dcb 17,26,19,19,31,21,11,19,3,24,4,24,13,8,8,26 + diff --git a/hacks/images/m6502/noise.asm b/hacks/images/m6502/noise.asm new file mode 100644 index 00000000..32447d77 --- /dev/null +++ b/hacks/images/m6502/noise.asm @@ -0,0 +1,16 @@ +; static noise + +start: ldy #$ff + ldx #$0 +loop: lda $fe + sta $200,x + and #$7 + sta $300,x + and #$3 + sta $400,x + and #$1 + sta $500,x + inx + dey + bne loop + rts diff --git a/hacks/images/m6502/random-walk.asm b/hacks/images/m6502/random-walk.asm new file mode 100644 index 00000000..4c3bd15d --- /dev/null +++ b/hacks/images/m6502/random-walk.asm @@ -0,0 +1,82 @@ + ;; Jeremy English Dec 11 2007 + ;; Random walk + lda #16 + sta $0 ; The current x pos + sta $1 ; The current y pos + lda $fe ; Get random color + sta $5 ; Store the color + lda $fe ; Amount of time to use this color + sta $6 + +loop: + ldx $0 + ldy $1 + lda $5 + jsr paint + jsr walk + dec $6 + bne loop + ;; get a new color + lda $fe + sta $5 + ;; get a new duration + lda $fe + sta $6 + jmp loop + +walk: + lda $fe + and #3 + cmp #0 + beq right + cmp #1 + beq left + cmp #2 + beq up + jmp down + +right: + inc $0 + jmp done +left: + dec $0 + jmp done +up: + dec $1 + jmp done +down: + inc $1 + jmp done +done: + lda $0 + and #31 + sta $0 + lda $1 + and #31 + sta $1 + rts + +paint: + pha + lda yl,y + sta $2 + lda yh,y + sta $3 + txa + tay + pla + sta ($2),y + rts + + ;; Y cord MSB +yh: + dcb $02, $02, $02, $02, $02, $02, $02, $02 + dcb $03, $03, $03, $03, $03, $03, $03, $03 + dcb $04, $04, $04, $04, $04, $04, $04, $04 + dcb $05, $05, $05, $05, $05, $05, $05, $05 + ;; Y cord LSB +yl: + dcb $00, $20, $40, $60, $80, $a0, $c0, $e0 + dcb $00, $20, $40, $60, $80, $a0, $c0, $e0 + dcb $00, $20, $40, $60, $80, $a0, $c0, $e0 + dcb $00, $20, $40, $60, $80, $a0, $c0, $e0 diff --git a/hacks/images/m6502/random.asm b/hacks/images/m6502/random.asm new file mode 100644 index 00000000..9ff5d2d2 --- /dev/null +++ b/hacks/images/m6502/random.asm @@ -0,0 +1,11 @@ +loop: lda $fe ; A=rnd + sta $00 ; ZP(0)=A + lda $fe + and #$3 ; A=A&3 + clc ; Clear carry + adc #$2 ; A+=2 + sta $01 ; ZP(1)=A + lda $fe ; A=rnd + ldy #$0 ; Y=0 + sta ($00),y ; ZP(0),ZP(1)=y + jmp loop diff --git a/hacks/images/m6502/random2.asm b/hacks/images/m6502/random2.asm new file mode 100644 index 00000000..c209f9f7 --- /dev/null +++ b/hacks/images/m6502/random2.asm @@ -0,0 +1,11 @@ + lda $fe ; A=rnd + sta $00 ; ZP(0)=A + lda $fe + and #$3 ; A=A&3 + clc ; Clear carry + adc #$2 ; A+=2 + sta $01 ; ZP(1)=A + lda $fe ; A=rnd + ldy #$0 ; Y=0 + sta ($00),y ; ZP(0),ZP(1)=y + jmp $600 diff --git a/hacks/images/m6502/rorschach.asm b/hacks/images/m6502/rorschach.asm new file mode 100644 index 00000000..c5591f0f --- /dev/null +++ b/hacks/images/m6502/rorschach.asm @@ -0,0 +1,124 @@ +; "Rorschach test" +; Not at all what it was supposed to be, +; but it turns out pretty cool and can +; create some interesting patterns. + + lda #8 + tax +dr: + sta $3cb,x + sta $40b,x + dex + bpl dr + sta $3f3 + sta $3eb + + lda #1 + sta $3ec + + ldx #255 +mk: + lda $fe + sta $1200,x + lda $fe + sta $1300,x + lda $fe + sta $1400,x + lda $fe + sta $1500,x + dex + cpx #$ff + bne mk + +; smooth it + + ldy #0 +re: + lda #1 + sta $3ec,y + + ldx #255 +sm: + lda $1201,x + adc $11ff,x + adc $1220,x + adc $11e0,x + lsr + lsr + sta $1200,x + + lda $1301,x + adc $12ff,x + adc $1320,x + adc $12e0,x + lsr + lsr + sta $1300,x + + lda $1401,x + adc $13ff,x + adc $1420,x + adc $13e0,x + lsr + lsr + sta $1400,x + + lda $1501,x + adc $14ff,x + adc $1520,x + adc $14e0,x + lsr + lsr + sta $1500,x + + dex + cpx #$ff + bne sm + iny + cpy #7 + bne re + + lda #1 + sta $3f0 + + ;copy it + + clc + ldx #255 +cp: + lda $1200,x + lsr + lsr + tay + lda colors,y + sta $200,x + + lda $1300,x + lsr + lsr + tay + lda colors,y + sta $300,x + + lda $1400,x + lsr + lsr + tay + lda colors,y + sta $400,x + + lda $1500,x + lsr + lsr + tay + lda colors,y + sta $500,x + + dex + cpx #$ff + bne cp + rts + +colors: + dcb 0,0,0,0,0,$9,$9,1,1,0,0,0,0,0 + diff --git a/hacks/images/m6502/santa.asm b/hacks/images/m6502/santa.asm new file mode 100644 index 00000000..be475020 --- /dev/null +++ b/hacks/images/m6502/santa.asm @@ -0,0 +1,142 @@ +start: +ldx #0 +cs: +lda $2000,x +sta $500,x +dex +bne cs + +stx $20 + +loop: + +inc $20 +lda $20 +and #$7f +tay +and #$1f +tax +lda sinus,x +tax + +d: + +lda #0 +sta $1e0,x +sta $2e0,x +lda $1000,y +sta $200,x +lda $1080,y +sta $220,x +lda $1100,y +sta $240,x +lda $1180,y +sta $260,x +lda $1200,y +sta $280,x +lda $1280,y +sta $2a0,x +lda $1300,y +sta $2c0,x +lda $1380,y +sta $2c0,x +inx +iny +txa +and #$1f +bne d + +jmp loop + +; 32 ($20) long +sinus: +dcb 0,0,0,0,$20,$20,$20 +dcb $40,$40,$60,$80,$a0,$a0,$c0,$c0,$c0 +dcb $e0,$e0,$e0,$e0,$c0,$c0,$c0 +dcb $a0,$a0,$80,$60,$40,$40,$20,$20,$20 + +*=$1000 +santa: +dcb 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 +dcb 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 +dcb 0,0,0,0,0,0,0,0,$a,$a,0,0,0,0,0,0 +dcb 0,0,0,0,0,$a,$a,0,0,0,0,0,0,0,0,0 +dcb 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 +dcb 0,2,2,2,1,0,0,0,0,$9,$9,$9,$9,0,0,0 +dcb 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 +dcb 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 +dcb 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 +dcb 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 +dcb 0,0,0,0,0,0,0,0,$a,$a,$a,0,0,0,0,0 +dcb 0,0,0,0,0,$a,$a,$a,0,0,0,0,0,0,0,0 +dcb 0,0,0,0,0,0,$9,$9,0,0,0,0,0,0,0,0 +dcb 0,1,1,2,2,0,$9,$9,$9,$9,$9,$9,0,0,0,0 +dcb 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 +dcb 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 +dcb 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 +dcb 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 +dcb 0,0,0,0,0,0,$a,$a,$a,$a,$a,$a,0,0,0,0 +dcb 0,0,0,$a,$a,$a,$a,$a,$a,0,0,0,0,0,0,0 +dcb 0,0,0,0,0,0,0,$9,$9,$9,0,0,0,0,0,0 +dcb 0,1,2,2,$9,$9,$9,$9,$9,$9,$9,0,0,0,0,0 +dcb 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 +dcb 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 +dcb 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 +dcb 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 +dcb 0,0,0,0,0,0,0,0,0,$a,$a,$a,$a,$a,$a,$b +dcb $b,$b,$b,$b,$b,$b,$a,$a,$a,$a,$a,$a,$b,$b,$b,$b +dcb $b,$b,$b,$b,$b,$9,$9,$9,$9,$9,$9,$9,$9,$9,$9,$9 +dcb $9,2,2,$9,$9,$9,$9,$9,$9,$9,0,0,0,0,0,0 +dcb 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 +dcb 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 +dcb 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 +dcb 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 +dcb 0,0,0,0,0,0,0,0,0,$a,$a,$a,$a,$a,$a,$a +dcb $a,0,0,0,0,0,$a,$a,$a,$a,$a,$a,$a,$a,0,0 +dcb 0,0,0,0,0,0,0,$9,$9,$9,$9,$9,$9,$9,$9,$9 +dcb 2,2,$9,$9,$9,$9,$9,$9,$9,$9,$9,0,0,0,0,0 +dcb 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 +dcb 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 +dcb 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 +dcb 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 +dcb 0,0,0,0,0,0,0,0,0,$a,$a,$a,$a,$a,$a,0 +dcb $a,$a,0,0,0,0,$a,$a,$a,$a,$a,$a,0,$a,$a,0 +dcb 0,0,0,0,0,$a,$a,0,0,$9,$a,$9,$9,$9,$9,$9 +dcb $9,$9,$a,$9,$9,$9,$9,$9,$9,$9,$9,0,0,0,0,0 +dcb 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 +dcb 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 +dcb 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 +dcb 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 +dcb 0,0,0,0,0,0,0,0,0,$a,0,$a,0,0,$a,0 +dcb 0,$a,0,0,0,0,$a,0,$a,0,0,$a,0,0,$a,0 +dcb 0,0,0,0,0,$a,0,0,0,$a,0,0,0,0,0,0 +dcb 0,$a,0,0,0,0,0,0,0,0,0,0,0,0,0,0 +dcb 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 +dcb 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 +dcb 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 +dcb 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 +dcb 0,0,0,0,0,0,0,0,$a,$a,0,$a,0,0,$a,$a +dcb 0,$a,$a,0,0,$a,$a,0,$a,0,0,$a,$a,0,$a,$a +dcb 0,0,0,0,0,0,$a,$a,$a,$a,$a,$a,$a,$a,$a,$a +dcb $a,$a,$a,$a,$a,$a,$a,$a,$a,$a,$a,0,0,0,0,0 +dcb 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 +dcb 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 + +*=$2000 +dcb 0,0,0,0,0,0,0,0,0,0,0,0,1,1,0,0 +dcb 0,0,0,0,0,0,0,0,0,0,0,0,$c,1,1,1 +dcb 0,0,0,0,0,0,0,0,0,0,0,1,1,1,$a,$a +dcb 0,0,0,0,0,0,0,0,0,0,$c,1,1,1,1,1 +dcb 1,1,$c,0,0,0,0,0,0,0,0,0,1,1,0,0 +dcb 0,0,0,0,0,0,0,0,$c,1,1,1,1,1,1,1 +dcb 1,1,1,1,1,$c,0,0,0,0,0,1,1,1,1,0 +dcb 0,0,0,0,0,0,$c,1,1,1,1,1,1,1,1,1 +dcb 1,1,1,1,1,1,$c,0,0,0,0,1,1,1,1,0 +dcb 0,0,0,0,0,$c,1,1,1,1,1,1,1,1,1,1,1 +dcb 1,1,1,1,1,1,1,1,$c,0,0,1,1,0,0 +dcb 0,0,$c,1,1,1,1,1,1,1,1,1,1,1,1,1 +dcb 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1 +dcb 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1 +dcb 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1 +dcb 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1 + \ No newline at end of file diff --git a/hacks/images/m6502/selfmodify.asm b/hacks/images/m6502/selfmodify.asm new file mode 100644 index 00000000..f7bb6462 --- /dev/null +++ b/hacks/images/m6502/selfmodify.asm @@ -0,0 +1,12 @@ +; A very simple example of +; self-modifying code +; and code entry points + + lda $fe + sta $1001 + jmp $1000 + + *=$1000 + lda #$00 + sta $3ef + jmp $600 diff --git a/hacks/images/m6502/sierpinsky.asm b/hacks/images/m6502/sierpinsky.asm new file mode 100644 index 00000000..6a679062 --- /dev/null +++ b/hacks/images/m6502/sierpinsky.asm @@ -0,0 +1,131 @@ +; 6502 assembler Sierpinsky Triangle ver.2 +; by Magnus Wedmark 2007-05-02 +; This program is especially written for +; the 6502asm.com competition and +; uses the 32*32 pixel display used in that +; virtual platform. The sierpinsky +; fractal is one of the simplest to +; implement. Here is a walk-through: +; 1) Specify 3 points that form a triangle +; 2) Choose one of them as a starting point +; 3) Choose one of them as targetpoint randomly +; 4) Set the new current position half-way +; between the current point and the target +; point. +; 5) Goto 3 + + LDX #0 + LDY #0 +new_rnd: + LDA $FE ; random 0-255 + AND #3 ; only 0-3 left + CMP #3 + BNE good_rnd + JMP new_rnd +good_rnd: +; random = 0-2 + PHA +; transform X and Y values according to: +; X=X/2+(P*8) and Y=Y/2+(P*16) + ASL + ASL + ASL + STA $F3 ; P*8 + PLA + AND #1 + ASL + ASL + ASL + ASL + STA $F4 ; (P AND 1)*16 + TXA + LSR + ADC $F3 + TAX + TYA + LSR + ADC $F4 + TAY + JSR set_point ; use and restore regs + JMP new_rnd + +set_point: ; uses both X,Y,A and restores them + PHA ; backup all reg-value (X,Y,A) + TXA + PHA + TYA + PHA + PHA + PHA ; triple Y push, two for int. use + STX $F2 ; transfer X to Y using $F2 + LDY $F2 + LDA #0 + STA $F0 + LDA #$2 + STA $F1 ; set base vector to $200 + LDA #0 + PLA ; transfer the pushed Y-coord to A + AND #$07 ; the value %0000'0111 + ASL + ASL + ASL + ASL + ASL + CLC + ADC $F0 + STA $F0 + BCC no_carry + INC $F1 +no_carry: + CLC + PLA ; transfer the pushed Y-coord to A + AND #$18 + LSR + LSR + LSR + ADC $F1 + STA $F1 + + CLC + TYA + ADC $F0 + ADC $F1 + + LDA #1 ;1 = white for trouble-shooting + JSR set_toning_point ; use for shading + STA ($F0),Y ; set pixel + PLA ; restore all reg-value (X,Y,A) + TAY + PLA + TAX + PLA + RTS + +; sub routine to shade the current pixel ($F0),Y +; lighter on a scale: $0, $B, $C, $F, $1 +; Black, DarkGrey, Grey, LightGrey, White +set_toning_point: + LDA ($F0),Y + CMP #$00 + BNE not_black + LDA #$0B + RTS +not_black: + CMP #$0B + BNE not_dgrey + LDA #$0C + RTS +not_dgrey: + CMP #$0C + BNE not_grey + LDA #$0F + RTS +not_grey: + CMP #$0F + BNE not_lgrey + LDA #$01 + RTS +not_lgrey: +; white stays white + RTS + diff --git a/hacks/images/m6502/softsprite.asm b/hacks/images/m6502/softsprite.asm new file mode 100644 index 00000000..eab6d678 --- /dev/null +++ b/hacks/images/m6502/softsprite.asm @@ -0,0 +1,132 @@ +; software sprites +; by PJP + +loop: + ldx $90 + inx + stx $90 + + lda #4 ; *** NUMBER OF SPRITES + sta $3 + lda #0 + sta $4 + +multiple: + lda $90 + clc + adc $4 + tax + + lda sinus,x + ldy cosinus,x + asl + tax + lda ypos,x + sta $00 + inx + lda ypos,x + sta $01 + ldx #0 + lda #5 ; **** HEIGHT OF EACH SPRITE + sta $2 +draw: + lda image,x + sta ($0),y + inx + iny + lda image,x + sta ($0),y + inx + iny + lda image,x + sta ($0),y + inx + iny + lda image,x + sta ($0),y + inx + iny + lda image,x + sta ($0),y + + + tya + clc + adc #28 + tay + inx + dec $2 + bne draw + + lda $4 + clc + adc #18 ; *** DISTANCE BETWEEN SPRITES (FROM TABLE) + sta $4 + + dec $3 + bne multiple + + jmp loop + +; SINUS (AND COSINUS) + +sinus: + dcb $0e, $0e, $0e, $0f, $0f, $0f, $10, $10, $10, $11 + dcb $11, $11, $12, $12, $12, $13, $13, $13, $14, $14 + dcb $14, $14, $15, $15, $15, $16, $16, $16, $16, $17 + dcb $17, $17, $17, $18, $18, $18, $18, $19, $19, $19 + dcb $19, $19, $1a, $1a, $1a, $1a, $1a, $1a, $1a, $1b + dcb $1b, $1b, $1b, $1b, $1b, $1b, $1b, $1b, $1b, $1b + dcb $1b, $1b, $1b, $1b, $1b, $1b, $1b, $1b, $1b, $1b +cosinus: + dcb $1b, $1b, $1b, $1b, $1b, $1b, $1b, $1b, $1b, $1b + dcb $1a, $1a, $1a, $1a, $1a, $1a, $19, $19, $19, $19 + dcb $19, $18, $18, $18, $18, $18, $17, $17, $17, $17 + dcb $16, $16, $16, $15, $15, $15, $15, $14, $14, $14 + dcb $13, $13, $13, $12, $12, $12, $11, $11, $11, $10 + dcb $10, $10, $0f, $0f, $0f, $0e, $0e, $0e, $0d, $0d + dcb $0d, $0c, $0c, $0c, $0b, $0b, $0b, $0a, $0a, $0a + dcb $09, $09, $09, $08, $08, $08, $07, $07, $07, $06 + dcb $06, $06, $06, $05, $05, $05, $04, $04, $04, $04 + dcb $03, $03, $03, $03, $03, $02, $02, $02, $02, $02 + dcb $01, $01, $01, $01, $01, $01, $00, $00, $00, $00 + dcb $00, $00, $00, $00, $00, $00, $00, $00, $00, $00 + dcb $00, $00, $00, $00, $00, $00, $00, $00, $00, $00 + dcb $00, $00, $00, $00, $00, $00, $00, $01, $01, $01 + dcb $01, $01, $01, $01, $02, $02, $02, $02, $02, $03 + dcb $03, $03, $03, $04, $04, $04, $04, $05, $05, $05 + dcb $05, $06, $06, $06, $07, $07, $07, $07, $08, $08 + dcb $08, $09, $09, $09, $0a, $0a, $0a, $0b, $0b, $0b + dcb $0c, $0c, $0c, $0d, $0d + + dcb $0e, $0e, $0e, $0f, $0f, $0f, $10, $10, $10, $11 + dcb $11, $11, $12, $12, $12, $13, $13, $13, $14, $14 + dcb $14, $14, $15, $15, $15, $16, $16, $16, $16, $17 + dcb $17, $17, $17, $18, $18, $18, $18, $19, $19, $19 + dcb $19, $19, $1a, $1a, $1a, $1a, $1a, $1a, $1a, $1b + dcb $1b, $1b, $1b, $1b, $1b, $1b, $1b, $1b, $1b, $1b + dcb $1b, $1b, $1b, $1b, $1b, $1b, $1b, $1b, $1b, $1b + dcb $1b, $1b, $1b, $1b, $1b, $1b, $1b, $1b, $1b, $1b + dcb $1a, $1a, $1a, $1a, $1a, $1a, $19, $19, $19, $19 + +; 5x5 BYTES + +image: + dcb $0,$0,$0,$0,$0 + dcb $0,$c,$c,$c,$0 + dcb $0,$c,$1,$c,$0 + dcb $0,$c,$c,$c,$0 + dcb $0,$0,$0,$0,$0 + +; YPOS LOOKUP TABLE + +ypos: + dcb $00,$02,$20,$02,$40,$02,$60,$02 + dcb $80,$02,$a0,$02,$c0,$02,$e0,$02 + dcb $00,$03,$20,$03,$40,$03,$60,$03 + dcb $80,$03,$a0,$03,$c0,$03,$e0,$03 + dcb $00,$04,$20,$04,$40,$04,$60,$04 + dcb $80,$04,$a0,$04,$c0,$04,$e0,$04 + dcb $00,$05,$20,$05,$40,$05,$60,$05 + dcb $80,$05,$a0,$05,$c0,$05,$e0,$05 + diff --git a/hacks/images/m6502/spacer.asm b/hacks/images/m6502/spacer.asm new file mode 100644 index 00000000..bdecbb57 --- /dev/null +++ b/hacks/images/m6502/spacer.asm @@ -0,0 +1,235 @@ +; "spacer", move a space ship through an +; endless tunnel. You die once you hit +; the walls. +; +; Controls: +; +; W - move up +; X - move down +; Any other key will stop the ship +; +; Ps: this game runs awfully slow =) +; + +start: + jsr init + +loop: + ;; jsr drawShip + jsr drawMap + jsr genMap + jsr readKeys + jmp loop + +;-- + +drawShip: + lda $82 ; mychange +; asl + tay + + lda ypos,y + sta $00 + iny + lda ypos,y + sta $01 + + ldx #42 + lda ($00,x) + cmp #0 + beq noCrash + cmp #5 +; bne crashed +;my changes +noCrash: + lda #5 + sta ($00,x) + + lda $60 + cmp $61 + beq ret + + lda $61 + asl + tay + lda ypos,y + sta $00 + iny + lda ypos,y + sta $01 + lda #0 + ldx #42 + sta ($00,x) + + lda $60 + sta $61 +ret: + rts + +;-- + +crashed: + lda $fe + sta ($00,x) + jmp crashed + +;-- + +readKeys: + lda $ff + cmp #119 + bne notUp + dec $60 + rts +notUp: + cmp #120 + bne noMove + inc $60 +noMove: + rts + +;-- + +init: + ldx #0 +drawLogo: + lda bottomLogo,x + sta $500,x + inx + cpx #0 + bne drawLogo + + lda #10 + sta $60 + sta $61 + + ldx #0 + lda #$c +c:sta $200,x + sta $400,x + dex + cpx #0 + bne c + + lda #16 + sta $80 ; origin + ldx #15 +set: + sta $81,x ; target + dex + bpl set + rts + +;-- + +drawMap: + lda #0 + sta $78 + lda #32 + sta $79 + lda #192 + sta $7a + lda #224 + sta $7b + + ldx #15 +drawLoop: + lda $81,x + sta $82,x + tay + lda ypos,y + sta $00 + iny + lda ypos,y + sta $01 + + lda #$c + ldy $78 + sta ($00),y + iny + sta ($00),y + + ldy $7b + sta ($00),y + iny + sta ($00),y + + ldy $79 + lda #0 + sta ($00),y + iny + sta ($00),y + + ldy $7a + sta ($00),y + iny + sta ($00),y + + inc $78 + inc $79 + inc $7a + inc $7b + inc $78 + inc $79 + inc $7a + inc $7b + dex + bpl drawLoop + rts + +;--- + +genMap: + lda $80 + cmp $81 + beq done + lda $80 + clc + sbc $81 + bpl plus + bmi minus +done: + lda $fe + and #$f + asl + sta $80 + rts +minus: + dec $81 + dec $81 + rts +plus: + inc $81 + inc $81 + rts + +ypos: + dcb $00,$02,$20,$02,$40,$02,$60,$02 + dcb $80,$02,$a0,$02,$c0,$02,$e0,$02 + dcb $00,$03,$20,$03,$40,$03,$60,$03 + dcb $80,$03,$a0,$03,$c0,$03,$e0,$03 + dcb $00,$04,$20,$04,$40,$04,$60,$04 + dcb $80,$04,$a0,$04,$c0,$04,$e0,$04 + dcb $00,$05,$20,$05,$40,$05,$60,$05 + dcb $80,$05,$a0,$05,$c0,$05,$e0,$05 + +bottomLogo: + dcb $0,$0,$0,$0,$0,$0,$0,$0,$0,$0,$0,$0,$0,$0 + dcb $0,$0,$0,$0,$0,$0,$0,$0,$0,$0,$0,$0,$0,$0 + dcb $0,$0,$0,$0,$0,$0,$1,$1,$1,$6,$1,$1,$1,$0 + dcb $0,$6,$1,$1,$6,$0,$0,$1,$1,$1,$6,$0,$1,$1 + dcb $1,$0,$1,$1,$1,$6,$0,$0,$6,$1,$6,$0,$6,$0 + dcb $1,$0,$6,$1,$6,$1,$6,$0,$1,$0,$1,$0,$6,$0 + dcb $6,$1,$6,$0,$6,$0,$1,$0,$6,$1,$6,$0,$0,$6 + dcb $1,$1,$6,$6,$1,$1,$1,$0,$6,$1,$0,$0,$1,$0 + dcb $1,$6,$0,$6,$6,$1,$1,$1,$0,$6,$1,$0,$6,$1 + dcb $0,$6,$6,$6,$6,$6,$1,$6,$1,$1,$6,$6,$6,$1 + dcb $1,$1,$1,$6,$1,$6,$6,$6,$6,$1,$6,$6,$6,$6 + dcb $1,$1,$1,$6,$6,$6,$6,$1,$1,$1,$1,$e,$1,$1 + dcb $e,$6,$6,$1,$1,$6,$1,$6,$1,$1,$1,$1,$e,$1 + dcb $1,$1,$1,$6,$1,$1,$6,$1,$6,$6,$6,$1,$1,$1 + dcb $6,$e,$1,$1,$6,$e,$6,$1,$1,$e,$1,$e,$6,$1 + dcb $1,$1,$6,$e,$1,$1,$1,$e,$1,$1,$6,$1,$6,$e + dcb $e,$e,$6,$e,$e,$6,$e,$e,$6,$e,$e,$6,$e,$e + dcb $6,$e,$e,$6,$e,$e,$6,$e,$e,$6,$e,$e,$6,$e + dcb $e,$6,$e,$e diff --git a/hacks/images/m6502/starfield2d.asm b/hacks/images/m6502/starfield2d.asm new file mode 100644 index 00000000..4c26efe4 --- /dev/null +++ b/hacks/images/m6502/starfield2d.asm @@ -0,0 +1,50 @@ +; 2d starfield +; Submitted by Anonymous + +i:ldx #$7 +g:lda $fe + and #3 + adc #1 + sta $0,x + lda $fe + and #$1f + sta $20,x + dex + bpl g +f: + lda #$ff + sta $10 + delay: + nop + dec $10 + bne delay + + lda #$00 + sta $80 + lda #$02 + sta $81 + ldx #$7 +l:lda $20,x + pha + clc + sbc $00,x + and #$1f + sta $20,x + lda $20,x + tay + lda #1 + sta ($80),y + pla + tay + lda #0 + sta ($80),y + lda $80 + clc + adc #$80 + bne n + inc $81 +n:sta $80 + dex + bpl l + jmp f + diff --git a/hacks/images/m6502/wave6502.asm b/hacks/images/m6502/wave6502.asm new file mode 100644 index 00000000..b40ea66c --- /dev/null +++ b/hacks/images/m6502/wave6502.asm @@ -0,0 +1,164 @@ +;;; 6502 logo Jeremy English 12-January-2008 + +start: +ldx #0 +stx $20 +lda #5 +sta $21 +lda $fe +sta $22 + +loop: +dec $21 +lda $21 +beq randcolor +jmp pastrandcolor + +randcolor: +lda #5 +sta $21 +ldx #33 +inc $22 +lda $22 +and #7 +tay +rl: +lda $1000,x +beq pastcolor1 +lda color_row,y +sta $1000,x + +pastcolor1: +lda $1040,x +beq pastcolor2 +lda color_row,y +sta $1040,x + +pastcolor2: +lda $1080,x +beq pastcolor3 +lda color_row,y +sta $1080,x + +pastcolor3: +lda $10c0,x +beq pastcolor4 +lda color_row,y +sta $10c0,x + +pastcolor4: +lda $1100,x +beq pastcolor5 +lda color_row,y +sta $1100,x + +pastcolor5: +lda $1140,x +beq pastcolor6 +lda color_row,y +sta $1140,x + +pastcolor6: +lda $1180,x +beq pastcolor7 +lda color_row,y +sta $1180,x + +pastcolor7: +lda $11C0,x +beq pastcolor8 +lda color_row,y +sta $11C0,x + +pastcolor8: +lda $1200,x +beq pastcolor9 +lda color_row,y +sta $1200,x + +pastcolor9: +inx +txa +and #$3f +bne rl + +pastrandcolor: + +inc $20 +lda $20 +and #$3f +tay +and #$1f +tax +lda sinus,x +tax + +d: + +lda #0 +sta $2e0,x +sta $3e0,x +lda $1000,y +sta $300,x +lda $1080,y +sta $320,x +lda $1100,y +sta $340,x +lda $1180,y +sta $360,x +lda $1200,y +sta $380,x +lda $1280,y +sta $3a0,x +lda $1300,y +sta $3c0,x +lda $1380,y +sta $3c0,x +inx +iny +txa +and #$1f +bne d + +jmp loop + +; 32 ($20) long +sinus: +dcb 0,0,0,0,$20,$20,$20 +dcb $40,$40,$60,$80,$a0,$a0,$c0,$c0,$c0 +dcb $e0,$e0,$e0,$e0,$c0,$c0,$c0 +dcb $a0,$a0,$80,$60,$40,$40,$20,$20,$20 + +color_row: +dcb $7,$8,$9,$2,$4,$6,$e,$3 + + +*=$1000 +dcb 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 +dcb 0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,0,0,1,1,1,1,1,1 +dcb 0,0,1,1,1,1,1,1,0,0,1,1,1,1,1,1,0,0,0,0,0,0,0,0 +dcb 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 +dcb 0,0,1,1,1,1,1,1,0,0,1,1,1,1,1,1,0,0,1,1,1,1,1,1 +dcb 0,0,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 +dcb 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,0,0,0,0 +dcb 0,0,1,1,0,0,0,0,0,0,1,1,0,0,1,1,0,0,0,0,0,0,1,1 +dcb 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 +dcb 0,0,0,0,0,0,0,0,0,0,1,1,0,0,0,0,0,0,1,1,0,0,0,0 +dcb 0,0,1,1,0,0,1,1,0,0,0,0,0,0,1,1,0,0,0,0,0,0,0,0 +dcb 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 +dcb 0,0,1,1,1,1,1,1,0,0,1,1,1,1,1,1,0,0,1,1,0,0,1,1 +dcb 0,0,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 +dcb 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1 +dcb 0,0,1,1,1,1,1,1,0,0,1,1,0,0,1,1,0,0,1,1,1,1,1,1 +dcb 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 +dcb 0,0,0,0,0,0,0,0,0,0,1,1,0,0,1,1,0,0,0,0,0,0,1,1 +dcb 0,0,1,1,0,0,1,1,0,0,1,1,0,0,0,0,0,0,0,0,0,0,0,0 +dcb 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 +dcb 0,0,1,1,0,0,1,1,0,0,0,0,0,0,1,1,0,0,1,1,0,0,1,1 +dcb 0,0,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 +dcb 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1 +dcb 0,0,1,1,1,1,1,1,0,0,1,1,1,1,1,1,0,0,1,1,1,1,1,1 +dcb 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 +dcb 0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,0,0,1,1,1,1,1,1 +dcb 0,0,1,1,1,1,1,1,0,0,1,1,1,1,1,1 + diff --git a/hacks/images/m6502/zookeeper.asm b/hacks/images/m6502/zookeeper.asm new file mode 100644 index 00000000..b3e3bd21 --- /dev/null +++ b/hacks/images/m6502/zookeeper.asm @@ -0,0 +1,109 @@ +; We all love zookeeper !!!! +; muhmi Nov 13, 2007 9:45 am + +ldx #0 +lda #0 +hupsu: +sta $200,x +sta $300,x +sta $400,x +sta $500,x +bne hupsu + + +lda #1 +ldx #0 +fill: +txa +tay +lda seko,x +tax +lda kuva,x +sta $200,x +lda kuva_0,x +sta $300,x +lda kuva_1,x +sta $400,x +lda kuva_2,x +sta $500,x +tya +tax +inx +bne fill + +rts + +seko: +dcb 46,93,219,97,168,170,196,63,204,201,206 +dcb 56,238,25,2,186,209,191,138,226,80,128 +dcb 58,171,81,115,42,44,102,193,69,231,107 +dcb 78,5,218,103,11,13,221,130,149,16,227 +dcb 105,213,232,182,17,255,27,190,205,137,192 +dcb 222,233,94,52,229,96,18,220,202,122,166 +dcb 43,153,131,246,177,4,70,22,7,86,173 +dcb 141,151,164,32,143,40,156,185,121,132,165 +dcb 62,249,252,139,154,251,85,236,12,134,245 +dcb 184,39,195,119,242,244,162,74,1,77,51 +dcb 33,75,35,76,34,10,89,47,189,237,71 +dcb 159,9,38,101,180,116,147,140,183,157,123 +dcb 14,19,126,199,100,45,241,28,125,210,155 +dcb 41,254,31,144,55,247,111,95,57,53,223 +dcb 152,108,203,36,214,37,113,200,66,67,197 +dcb 29,250,20,212,68,87,207,163,145,211,48 +dcb 136,24,98,215,169,83,124,224,181,187,142 +dcb 84,240,54,110,234,59,243,79,50,30,114 +dcb 6,178,0,172,148,146,179,120,60,225,65 +dcb 230,208,15,72,117,248,198,106,129,92,127 +dcb 175,160,49,216,176,133,64,109,112,82,90 +dcb 235,104,158,194,8,161,167,88,91,174,23 +dcb 73,118,150,3,99,61,217,26,239,21,253 +dcb 135,188,228 + +kuva: +dcb 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1 +dcb 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1 +dcb 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0 +dcb 0,0,0,0,0,1,1,1,1,1,0,0,0,0,0,0,0,0,1,1,1,1,1,1 +dcb 1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0 +dcb 0,0,0,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,1 +dcb 0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,0,0,11,11 +dcb 11,0,0,0,0,0,0,1,0,0,0,11,11,11,0,0,0,0,0,1,1,1,1,1 +dcb 1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 +dcb 0,0,0,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0 +dcb 0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1 +kuva_0: +dcb 1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 +dcb 0,0,0,0,0,1,1,1,1,0,0,0,0,1,1,1,1,1,1,1,1,1,1,1 +dcb 1,1,1,1,1,1,1,1,1,1,0,0,0,0,1,1,1,0,0,0,0,1,1,1 +dcb 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,1,1 +dcb 1,0,0,0,1,1,0,0,0,0,0,0,0,1,1,1,1,1,0,0,0,0,0,0 +dcb 0,1,15,0,0,0,1,1,1,0,0,0,1,0,0,0,0,0,0,0,0,0,0,1 +dcb 0,0,0,0,0,0,0,0,0,0,15,0,0,0,1,1,1,0,0,0,1,0,0,0 +dcb 0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,15,0,0,0,1,1 +dcb 1,0,0,0,1,0,0,0,0,1,1,1,0,0,0,1,0,0,0,1,1,1,0,0 +dcb 0,0,15,0,0,0,1,1,1,0,0,0,1,0,0,0,0,1,1,1,0,0,0,1 +dcb 0,0,0,1,1,1,0,0,0,0,1,0,0,0,1,1 +kuva_1: +dcb 1,0,0,0,1,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0 +dcb 0,0,15,0,0,0,1,1,1,0,0,0,1,0,0,0,0,0,0,0,0,0,0,1 +dcb 0,0,0,0,0,0,0,0,0,0,15,0,0,0,1,1,1,0,0,0,1,1,0,0 +dcb 0,0,0,0,0,1,1,1,1,1,0,0,0,0,0,0,0,1,1,0,0,0,1,1 +dcb 1,0,0,0,1,1,1,1,1,1,1,1,1,1,1,0,1,1,1,1,1,1,1,1 +dcb 1,1,1,0,0,0,1,1,1,0,0,0,1,1,1,1,1,1,1,1,1,1,1,0 +dcb 1,1,1,1,1,1,1,1,1,1,1,0,0,0,1,1,1,0,0,0,1,1,1,1 +dcb 1,1,1,1,1,0,0,0,0,0,1,1,1,1,1,1,1,1,1,0,0,0,1,1 +dcb 1,0,0,0,1,1,1,1,1,1,1,1,1,15,15,15,1,1,1,1,1,1,1,1 +dcb 1,1,15,0,0,0,1,1,1,0,0,0,1,1,1,1,1,1,1,1,1,15,15,15 +dcb 1,1,1,1,1,1,1,1,1,1,15,0,0,0,1,1 +kuva_2: +dcb 1,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1 +dcb 1,1,1,0,0,0,1,1,1,0,0,0,1,1,1,1,1,1,1,1,1,15,15,0 +dcb 15,15,1,1,1,1,1,1,1,1,1,0,0,0,1,1,1,0,0,0,1,1,1,1 +dcb 1,1,1,1,1,15,15,0,15,15,1,1,1,1,1,1,1,1,1,0,0,0,1,1 +dcb 1,0,0,0,15,1,1,1,1,1,1,1,1,15,15,0,1,1,1,1,1,1,1,1 +dcb 1,1,1,0,0,0,1,1,1,0,0,0,0,15,15,15,15,15,15,1,15,1,1,1 +dcb 1,1,15,1,15,15,15,1,1,15,0,0,0,0,1,1,1,0,0,0,0,15,15,15 +dcb 15,15,15,1,15,1,1,1,1,1,15,1,15,15,15,1,1,15,0,0,0,0,1,1 +dcb 1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 +dcb 0,0,0,0,0,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0 +dcb 0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1 diff --git a/hacks/images/mac.xbm b/hacks/images/mac.xbm new file mode 100644 index 00000000..95f6839b --- /dev/null +++ b/hacks/images/mac.xbm @@ -0,0 +1,14 @@ +#define mac_width 25 +#define mac_height 32 +static unsigned char mac_bits[] = { + 0x00, 0x00, 0x00, 0x00, 0xFC, 0xFF, 0x7F, 0x00, 0xFE, 0xFF, 0xFF, 0x00, + 0x0E, 0x00, 0xE0, 0x00, 0xF6, 0xFF, 0xDF, 0x00, 0xF6, 0xFF, 0xDF, 0x00, + 0x76, 0x7D, 0xDD, 0x00, 0xF6, 0xFE, 0xDE, 0x00, 0x76, 0x7D, 0xDD, 0x00, + 0xF6, 0xFF, 0xDF, 0x00, 0xF6, 0xDB, 0xDF, 0x00, 0xF6, 0xE7, 0xDF, 0x00, + 0xF6, 0xFF, 0xDF, 0x00, 0xF6, 0x83, 0xDF, 0x00, 0xF6, 0x7D, 0xDE, 0x00, + 0xF6, 0xFF, 0xDD, 0x00, 0xF6, 0xFF, 0xDF, 0x00, 0x0E, 0x00, 0xE0, 0x00, + 0xFE, 0xFF, 0xFF, 0x00, 0xFE, 0xFF, 0xFF, 0x00, 0xFE, 0xFF, 0xFF, 0x00, + 0xFE, 0xFF, 0xFF, 0x00, 0xC6, 0x3F, 0xE0, 0x00, 0xFE, 0xFF, 0xFF, 0x00, + 0xFE, 0xFF, 0xFF, 0x00, 0xFE, 0xFF, 0xFF, 0x00, 0xFE, 0xFF, 0xFF, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xFC, 0xFF, 0x7F, 0x00, 0xFC, 0xFF, 0x7F, 0x00, + 0xFC, 0xFF, 0x7F, 0x00, 0x00, 0x00, 0x00, 0x00, }; diff --git a/hacks/images/macbomb.xbm b/hacks/images/macbomb.xbm new file mode 100644 index 00000000..76aba4a6 --- /dev/null +++ b/hacks/images/macbomb.xbm @@ -0,0 +1,474 @@ +#define macbomb_width 448 +#define macbomb_height 126 +static unsigned char macbomb_bits[] = { + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x01,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x80,0xf9,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x9f,0xf9, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x9f,0x19,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x98,0x19,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x98,0x19,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x98,0x19,0x00, + 0x00,0x00,0x40,0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x98,0x19,0x00,0x00,0x00,0x00,0x20, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x98,0x19,0x00,0x00,0x00,0x80,0x10,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x98,0x19,0x00,0x00,0x00,0x04,0x08,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x98,0x19,0x00,0x00, + 0x00,0x10,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x98,0x19,0x00,0x00,0x00,0x40,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x98,0x19,0x00,0x00,0xe0,0x03,0x50,0x01,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x98, + 0x19,0x00,0x00,0x10,0x8c,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x98,0x19,0x00,0x00,0x08, + 0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x98,0x19,0x00,0x00,0x08,0x00,0x10,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x98,0x19,0x00,0x00,0x08,0x40,0x22,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x98,0x19, + 0x00,0x00,0x7f,0x20,0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x98,0x19,0x00,0x00,0x7f,0x10, + 0x82,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x98,0x19,0x00,0x00,0x7f,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x98,0x19,0x00,0xc0,0xff,0x01,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x98,0x19,0x00, + 0xf0,0xff,0x07,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x98,0x19,0x00,0xf0,0xff,0x07,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x98,0x19,0x00,0xf8,0xff,0x0f,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x98,0x19,0x00,0xf8,0xff,0x0f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x98,0x19,0x00,0xfc, + 0xff,0x1e,0x00,0x00,0x00,0x00,0x00,0x07,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x98,0x19,0x00,0xfc,0xff,0x1f,0x00,0x00, + 0x00,0x00,0x80,0x09,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x60,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xc0,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x98,0x19,0x00,0xfc,0xff,0x1d,0x00,0x00,0x00,0x00,0x80,0x81, + 0xc7,0xb6,0xcd,0x00,0x78,0x80,0x63,0xc6,0xf1,0x78,0xfc,0x07,0x78,0x6c,0x9b, + 0xc7,0x06,0x1e,0x0e,0xc7,0xcc,0xb6,0x79,0xf8,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x98, + 0x19,0x00,0xfc,0xff,0x1d,0x00,0x00,0x00,0x00,0x80,0xc3,0xcc,0x71,0xcc,0x00, + 0xc4,0xc0,0x64,0x66,0x62,0xcc,0xcc,0x0c,0xcc,0x1c,0xc7,0xcc,0x01,0x33,0x93, + 0xc9,0xcc,0x71,0xcc,0xcc,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x98,0x19,0x00,0xfc,0xff, + 0x1d,0x00,0x00,0x00,0x00,0x00,0xc7,0xcc,0x30,0xcc,0x00,0xf8,0xc0,0x61,0xe6, + 0x60,0xcc,0xcc,0x0c,0xcc,0x0c,0xc3,0xcc,0x00,0x33,0x83,0xc1,0xcc,0x30,0xcc, + 0xcc,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x98,0x19,0x00,0xfc,0xff,0x1f,0x00,0x00,0x00, + 0x00,0x00,0xce,0xcc,0x30,0xcc,0x00,0xcc,0x80,0x63,0xc6,0x61,0xfc,0xcc,0x0c, + 0xfc,0x0c,0xc3,0xcc,0x00,0x33,0x83,0xc1,0xcc,0x30,0xfc,0xcc,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x98,0x19,0x00,0xfc,0xff,0x1e,0x00,0x00,0x00,0x00,0x00,0xcc,0xcc, + 0x30,0xcc,0x00,0xcc,0x00,0x67,0x86,0x63,0x0c,0xcc,0x0c,0x0c,0x0c,0xc3,0xcc, + 0x00,0x33,0x83,0xc1,0xcc,0x30,0x0c,0xcc,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x98,0x19, + 0x00,0xf8,0xff,0x0f,0x00,0x00,0x00,0x00,0x80,0xcc,0xcc,0x30,0xcc,0x0c,0xcc, + 0x40,0x66,0x26,0x63,0x8c,0xcc,0x0c,0x8c,0x0c,0xc3,0xcc,0x00,0x33,0x93,0xc9, + 0xcc,0x30,0x8c,0xcc,0x0c,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x98,0x19,0x00,0xf8,0xbf,0x0f, + 0x00,0x00,0x00,0x00,0x00,0x87,0xc7,0x30,0xf8,0x0c,0xf8,0x80,0xc3,0xc7,0xc1, + 0x78,0xcc,0x0c,0x78,0x0c,0x83,0xc7,0x00,0x1e,0x0e,0x87,0xcf,0x30,0x78,0xf8, + 0x0c,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x98,0x19,0x00,0xf0,0xff,0x07,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0xc0,0x08,0x00,0x00,0x00,0x06,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x98,0x19,0x00,0xf0,0xff,0x07,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0xc4,0x04,0x00,0x00,0x20,0x06,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x98,0x19,0x00, + 0xc0,0xff,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x78,0x00,0x00,0x00, + 0xc0,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x98,0x19,0x00,0x00,0x7f,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x98,0x19,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x98,0x19,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x98,0x19,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x98,0x19,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x98,0x19,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x98, + 0x19,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x98,0x19,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x98,0x19,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x98,0x19,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x98,0x19, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x98,0x19,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x98,0x19,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x98,0x19,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x98,0x19,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x98,0x19,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x98,0x19,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x98,0x19,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x98,0x19,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x98,0x19,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x98,0x19,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x98, + 0x19,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x98,0x19,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x40,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x98,0x19,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xc0,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x98,0x19,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0xc0,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x98,0x19, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0xc0,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x98,0x19,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xc0,0x07,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x98,0x19,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xc0,0x0f,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x98,0x19,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0xc0,0x1f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x98,0x19,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xc0, + 0x3f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x98,0x19,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xc0,0x07,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x98,0x19,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0xc0,0x06,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x98,0x19,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x40,0x0c,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x98,0x19,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0c, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x98,0x19,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x18,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x98,0x19,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x18,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x98, + 0x19,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x98,0x19,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x98,0x19,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x98,0x19,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x98,0x19, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x98,0x19,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x98,0x19,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x98,0x19,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x98,0x19,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x98,0x19,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x98,0x19,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x98,0x19,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x98,0x19,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x98,0x19,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x98,0x19,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x98, + 0x19,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x98,0x19,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x8c,0x0f,0x00,0x00,0x8f, + 0x1f,0x00,0x00,0x00,0x00,0x00,0x98,0x19,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x8c,0x19,0x00,0x80,0x19,0x0c,0x00,0x00,0x00, + 0x00,0x00,0x98,0x19,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x8c,0x19,0x00,0x80,0x19,0x06,0x00,0x00,0x00,0x00,0x00,0x98,0x19, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x8c,0x19, + 0xf8,0x81,0x19,0x0f,0x00,0x00,0x00,0x00,0x00,0x98,0x19,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x8c,0x19,0x00,0x80,0x19,0x18, + 0x00,0x00,0x00,0x00,0x00,0x98,0x19,0x00,0x00,0xf8,0xff,0xff,0xff,0xff,0xff, + 0x0f,0x00,0x00,0xc0,0xff,0xff,0xff,0xff,0xff,0xff,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x8c,0x19,0xf8,0x81,0x19,0x18,0x00,0x00,0x00,0x00, + 0x00,0x98,0x19,0x00,0x00,0x06,0x00,0x00,0x00,0x00,0x00,0x30,0x00,0x00,0x30, + 0x00,0x00,0x00,0x00,0x00,0x00,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x8c,0x19,0x00,0x80,0x19,0x18,0x00,0x00,0x00,0x00,0x00,0x98,0x19,0x00, + 0x00,0x03,0x00,0x00,0x00,0x00,0x00,0x60,0x00,0x00,0x18,0x00,0x00,0x00,0x00, + 0x00,0x00,0x06,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x8c,0x19,0x00, + 0x80,0x99,0x18,0x00,0x00,0x00,0x00,0x00,0x98,0x19,0x00,0x80,0x01,0x00,0x00, + 0x00,0x00,0x00,0xc0,0x00,0x00,0x0c,0x00,0x00,0x00,0x00,0x00,0x00,0x0c,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x8c,0x0f,0x00,0x00,0x0f,0x0f,0x00, + 0x00,0x00,0x00,0x00,0x98,0x19,0x00,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x80, + 0x00,0x00,0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x98,0x19,0x00,0x40,0xf8,0x00,0x00,0x18,0x00,0x80,0x01,0x01,0x00,0x42,0x01, + 0x00,0x00,0x00,0x00,0x00,0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x98,0x19,0x00,0x40, + 0x98,0x01,0x00,0x18,0x00,0x80,0x01,0x01,0x00,0x22,0x02,0x00,0x00,0x00,0x00, + 0x00,0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x98,0x19,0x00,0x40,0x98,0xf1,0x70,0x3c, + 0x1e,0xdb,0x03,0x01,0x00,0x42,0x44,0x41,0x11,0x51,0x15,0x14,0x10,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x98,0x19,0x00,0x40,0x98,0x99,0x99,0x18,0x31,0x87,0x01,0x01, + 0x00,0x22,0x22,0x22,0x22,0x22,0x22,0x22,0x10,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x98, + 0x19,0x00,0x40,0xf8,0x98,0x39,0x18,0x3e,0x83,0x01,0x01,0x00,0x42,0x41,0x44, + 0x10,0x11,0x11,0x11,0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x98,0x19,0x00,0x40,0x98, + 0xf9,0x71,0x18,0x33,0x83,0x01,0x01,0x00,0x22,0xa2,0x82,0x20,0x22,0x22,0x2a, + 0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x98,0x19,0x00,0x40,0x98,0x19,0xe0,0x18,0x33, + 0x83,0x01,0x01,0x00,0x42,0x44,0x00,0x11,0x11,0x11,0x01,0x10,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x98,0x19,0x00,0x40,0x98,0x19,0xc9,0x18,0x33,0x83,0x01,0x01,0x00, + 0x22,0x22,0x20,0x22,0x22,0x22,0x22,0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x98,0x19, + 0x00,0x40,0x98,0xf1,0x70,0x30,0x3e,0x03,0x03,0x01,0x00,0x42,0x44,0x41,0x41, + 0x11,0x11,0x14,0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x98,0x19,0x00,0x40,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x10, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x98,0x19,0x00,0x80,0x00,0x00,0x00,0x00,0x00,0x00, + 0x80,0x00,0x00,0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x98,0x19,0x00,0x80,0x01,0x00,0x00,0x00,0x00,0x00,0xc0,0x00,0x00,0x0c, + 0x00,0x00,0x00,0x00,0x00,0x00,0x0c,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x98,0x19,0x00, + 0x00,0x03,0x00,0x00,0x00,0x00,0x00,0x60,0x00,0x00,0x18,0x00,0x00,0x00,0x00, + 0x00,0x00,0x06,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x98,0x19,0x00,0x00,0x06,0x00,0x00, + 0x00,0x00,0x00,0x30,0x00,0x00,0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x03,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x98,0x19,0x00,0x00,0xf8,0xff,0xff,0xff,0xff,0xff,0x0f, + 0x00,0x00,0xc0,0xff,0xff,0xff,0xff,0xff,0xff,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x98,0x19,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x98,0x19,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x98,0x19,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x98,0x19,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x98, + 0x19,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x98,0xf9,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0x9f,0xf9,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff,0x9f,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x01, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff}; diff --git a/hacks/images/matrix1.xbm b/hacks/images/matrix1.xbm new file mode 100644 index 00000000..59e55d97 --- /dev/null +++ b/hacks/images/matrix1.xbm @@ -0,0 +1,1260 @@ +#define matrix1_width 320 +#define matrix1_height 377 +static unsigned char matrix1_bits[] = { + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfb, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xf3, 0xff, 0x9f, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x5f, 0xfd, 0xff, 0xf7, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe7, 0xff, 0xb7, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xf5, 0xff, 0xff, 0xff, 0x1f, 0xff, 0xff, 0xde, 0xff, + 0xb7, 0xf6, 0x7f, 0xe9, 0xff, 0xb7, 0xff, 0xff, 0xff, 0xff, 0xbf, 0xff, + 0xff, 0xf9, 0xff, 0x9f, 0xff, 0xff, 0xf1, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf9, 0xff, 0xff, 0xff, 0x5f, + 0xfe, 0xdf, 0xfb, 0xff, 0xdf, 0xfd, 0xff, 0xd1, 0xff, 0xef, 0xff, 0xff, + 0xff, 0xff, 0x7f, 0xff, 0xff, 0xeb, 0xff, 0xbf, 0xfe, 0xff, 0xf3, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf1, + 0xff, 0xff, 0xff, 0x17, 0xff, 0x7f, 0xad, 0xff, 0x37, 0xed, 0xbf, 0xea, + 0xff, 0xdb, 0xff, 0xff, 0xff, 0xff, 0xdf, 0xfe, 0x7f, 0xfb, 0xff, 0xdf, + 0xff, 0xff, 0xf4, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xf5, 0xff, 0xff, 0xff, 0x3f, 0xfd, 0x7f, 0x8d, 0xff, + 0x6f, 0xfd, 0xdf, 0x4a, 0x7f, 0x57, 0xff, 0xff, 0xe0, 0xff, 0x1f, 0xff, + 0xff, 0xf6, 0xff, 0x5f, 0xfd, 0xdf, 0xa1, 0xff, 0x1f, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf6, 0xff, 0xff, 0xff, 0x87, + 0xfe, 0x6f, 0xd6, 0xff, 0xb7, 0xf5, 0xaf, 0xcd, 0xff, 0xdd, 0xff, 0x7f, + 0xd9, 0xff, 0x97, 0xfe, 0x7f, 0xfb, 0xff, 0x7f, 0xff, 0x7f, 0xf5, 0xfe, + 0x5f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xbf, 0xfd, + 0xff, 0xff, 0xff, 0x5f, 0xfe, 0x6f, 0x4e, 0xff, 0x2d, 0xec, 0x6f, 0x7b, + 0xff, 0xb5, 0xfe, 0x6f, 0xf7, 0xff, 0xff, 0xff, 0xff, 0xf6, 0xff, 0x7f, + 0xfd, 0x6f, 0xc1, 0xff, 0x1f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0x7f, 0xfa, 0xff, 0xff, 0xff, 0x0f, 0xff, 0x7f, 0xca, 0xff, + 0x4b, 0xf5, 0xdf, 0xed, 0xff, 0xd7, 0xfe, 0xff, 0xde, 0xff, 0x57, 0xff, + 0x7f, 0xfc, 0xff, 0x5f, 0xfc, 0xbf, 0x54, 0xff, 0x5f, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f, 0xff, 0xff, 0xff, 0xff, 0x3f, + 0xfd, 0xef, 0xde, 0xff, 0x5b, 0xe8, 0x5f, 0x5f, 0xff, 0xbe, 0xff, 0xdf, + 0xfa, 0xff, 0xef, 0xff, 0xff, 0xfc, 0xff, 0x7f, 0xfd, 0x7f, 0xc2, 0xff, + 0x1f, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f, 0xfc, + 0xff, 0xff, 0xff, 0x17, 0xff, 0xbf, 0xeb, 0xff, 0xa6, 0xf6, 0x57, 0xf4, + 0xff, 0x6b, 0xfd, 0x7f, 0xee, 0xff, 0xff, 0xff, 0x3f, 0xfd, 0xff, 0x7f, + 0xfc, 0xff, 0xb9, 0xff, 0x5b, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xef, 0xff, 0xff, 0xff, 0xff, 0x3f, 0xfd, 0x7f, 0xdf, 0xff, + 0xa7, 0xd4, 0x7f, 0xd5, 0xff, 0xab, 0xfd, 0x6f, 0xfe, 0xff, 0xf7, 0xff, + 0x7f, 0xf8, 0xff, 0x7f, 0xf9, 0xbf, 0xf1, 0xff, 0x1f, 0xfb, 0xff, 0xff, + 0xff, 0xdf, 0xfd, 0xff, 0xff, 0xff, 0xaf, 0xfe, 0xff, 0xff, 0xff, 0x4f, + 0xff, 0xff, 0xff, 0xff, 0xf5, 0xfc, 0xdf, 0x4d, 0xff, 0x6f, 0xff, 0x7f, + 0xa9, 0xff, 0xff, 0xff, 0x7f, 0xfd, 0xff, 0x7f, 0xfe, 0x7f, 0x4e, 0xff, + 0x20, 0xe0, 0xff, 0xff, 0xff, 0x00, 0xe2, 0xff, 0xff, 0xff, 0xdf, 0xff, + 0xff, 0xff, 0xff, 0x1f, 0xff, 0xff, 0xff, 0xff, 0xc7, 0xfc, 0x7f, 0xcb, + 0xfe, 0x57, 0xfd, 0x7f, 0x7a, 0xff, 0xff, 0xff, 0xff, 0xfc, 0xff, 0x7f, + 0xfc, 0xff, 0xcc, 0xff, 0x22, 0xe5, 0xff, 0xff, 0xff, 0x48, 0xe0, 0xff, + 0xff, 0xff, 0xaf, 0xfe, 0xff, 0xff, 0xff, 0x5f, 0xff, 0xff, 0xff, 0xff, + 0xe5, 0xf4, 0xff, 0x4d, 0xff, 0xad, 0xf7, 0x6f, 0xd5, 0xff, 0xff, 0xff, + 0x7f, 0xfa, 0xff, 0x7f, 0xfd, 0x6f, 0xce, 0xff, 0x88, 0xe0, 0xff, 0xff, + 0xff, 0x12, 0xe5, 0xff, 0xff, 0xff, 0xdb, 0xff, 0xff, 0xff, 0xff, 0x1f, + 0xfe, 0xff, 0xff, 0xff, 0x89, 0xec, 0xaf, 0x7d, 0xfd, 0x6d, 0xfd, 0x5f, + 0x89, 0xfe, 0xff, 0xff, 0x7f, 0xfc, 0xff, 0x7f, 0xf8, 0xff, 0x7d, 0xff, + 0x3f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xb7, 0xff, + 0xff, 0xff, 0xff, 0x5f, 0xff, 0xff, 0xff, 0xbf, 0x00, 0xf4, 0x7f, 0x57, + 0xff, 0x57, 0xfb, 0xff, 0x62, 0xff, 0xff, 0xff, 0xff, 0xfb, 0xff, 0xdf, + 0xff, 0x7f, 0xef, 0xff, 0x97, 0xff, 0xff, 0xf7, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xdb, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0x5f, 0xcc, 0xfe, 0xaf, 0xf6, 0xaf, 0xce, 0xfe, 0xff, 0xff, + 0x7f, 0xf5, 0xff, 0x7f, 0xfd, 0xff, 0xff, 0xff, 0x1f, 0xfe, 0xff, 0xfd, + 0xff, 0xff, 0xff, 0xff, 0xfb, 0xff, 0xf7, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0x55, 0xfd, 0x6f, 0xab, 0xff, 0xbf, 0xfd, 0xaf, + 0xcb, 0xff, 0xff, 0xff, 0xff, 0xf7, 0xff, 0xdf, 0xfe, 0xff, 0xff, 0xff, + 0x5f, 0xff, 0xff, 0xeb, 0xff, 0xf7, 0xff, 0xff, 0xef, 0xff, 0xd9, 0xff, + 0xff, 0xff, 0xff, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xa7, 0xfa, 0x6f, 0x61, + 0xff, 0xef, 0xf5, 0xbf, 0x8e, 0xfe, 0xff, 0xff, 0x7f, 0xf5, 0xff, 0xbf, + 0xfd, 0xff, 0xff, 0xff, 0x1f, 0xff, 0x7f, 0xf3, 0xff, 0xff, 0xff, 0xff, + 0xfb, 0xff, 0xf3, 0xff, 0xff, 0xff, 0xff, 0x1f, 0xff, 0xff, 0xff, 0xff, + 0xdd, 0xff, 0xbf, 0xf5, 0xff, 0xaf, 0xfe, 0x57, 0x30, 0xff, 0xff, 0xff, + 0xff, 0xef, 0xff, 0xd7, 0xff, 0xff, 0xff, 0xff, 0x5f, 0xff, 0xff, 0xe9, + 0xff, 0xff, 0xff, 0xff, 0xe2, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0x5f, + 0xff, 0xff, 0xff, 0xff, 0xab, 0xfa, 0xff, 0xe5, 0xff, 0xbf, 0xf5, 0xff, + 0x32, 0xfc, 0xff, 0xff, 0xff, 0xd3, 0xff, 0x9f, 0xfe, 0xff, 0xff, 0xff, + 0x5f, 0xfe, 0x7f, 0xfd, 0xff, 0xff, 0xff, 0xff, 0xe7, 0xff, 0xea, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x57, 0xff, 0xff, 0xfd, + 0xff, 0xff, 0xff, 0xdf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfa, 0xff, 0x9f, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfb, 0xff, 0xff, 0xff, 0xff, + 0xfd, 0xff, 0xf6, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xde, 0xfe, 0xff, 0xf5, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xb3, 0xff, 0xbb, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf6, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0x6b, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xfd, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f, 0xff, 0xff, 0xff, + 0xff, 0xbb, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfb, 0xff, + 0xef, 0xff, 0xff, 0xdf, 0xff, 0xff, 0xfe, 0xff, 0xdf, 0xff, 0xef, 0xfe, + 0xff, 0xfd, 0xff, 0xbf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xea, 0xff, 0xab, + 0xff, 0x7f, 0xed, 0xff, 0xbf, 0xfe, 0xff, 0xfb, 0xff, 0x6b, 0xfb, 0xff, + 0x75, 0x7f, 0xb5, 0xf5, 0xff, 0xeb, 0xff, 0x77, 0xfd, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xdd, 0xff, 0x7f, 0xff, 0xff, 0x5b, 0xff, 0xb7, 0xf5, 0xff, 0x5b, + 0xff, 0xdb, 0xf6, 0xff, 0x6f, 0xff, 0x6f, 0xff, 0x7f, 0x7b, 0xff, 0xdf, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xb7, 0xff, 0x5f, 0xca, 0xfe, 0x02, 0xff, 0x2f, 0xca, 0xff, + 0xaa, 0xfc, 0xff, 0xc3, 0x7f, 0x53, 0xfb, 0xbf, 0xa0, 0x7f, 0xaa, 0xf2, + 0xaf, 0xca, 0xff, 0x53, 0xf2, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x42, 0xfe, 0xff, 0xca, 0xff, 0x46, + 0xfe, 0x7f, 0x96, 0xfe, 0x67, 0xe9, 0xff, 0x13, 0xff, 0x67, 0xfb, 0xff, + 0xaa, 0xfe, 0xda, 0xf6, 0x7f, 0x8a, 0xfe, 0xd3, 0xf6, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x0b, 0xfc, + 0x2f, 0x56, 0xff, 0x95, 0xff, 0xaf, 0xcc, 0xfe, 0x52, 0xf6, 0xff, 0xc2, + 0x7f, 0x59, 0xfd, 0xff, 0xe0, 0xff, 0x56, 0xfd, 0xaf, 0xd6, 0xff, 0xab, + 0xfd, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x6f, 0xff, 0xff, 0xff, 0xdf, + 0xff, 0xff, 0x53, 0xf7, 0xef, 0x6f, 0xfd, 0x1f, 0xff, 0xbf, 0xbd, 0xfe, + 0xff, 0xed, 0xff, 0x1f, 0xff, 0xf7, 0xfb, 0x3f, 0xbf, 0xff, 0xff, 0xea, + 0xaf, 0x3e, 0x7d, 0xbb, 0xe1, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x5f, + 0xfe, 0xff, 0xff, 0x47, 0xfd, 0xff, 0x77, 0xfd, 0x5f, 0x5d, 0xff, 0x57, + 0xff, 0xef, 0xd7, 0xfe, 0xea, 0xea, 0xff, 0xaa, 0xff, 0x5a, 0xff, 0xaf, + 0xfa, 0xff, 0x5f, 0xfb, 0xdf, 0x6b, 0xff, 0xf5, 0xf9, 0xff, 0xfd, 0xff, + 0xff, 0xff, 0xff, 0x8a, 0xff, 0xed, 0xfe, 0x57, 0xf7, 0x7f, 0xdd, 0xea, + 0xaf, 0xff, 0xfe, 0x1f, 0xfe, 0xdf, 0xdf, 0xfe, 0xff, 0xec, 0xff, 0x9c, + 0xff, 0x43, 0xf4, 0x3f, 0x6b, 0xff, 0xff, 0xfa, 0xbf, 0xae, 0xfe, 0xb7, + 0xd3, 0xff, 0xf1, 0xff, 0x5f, 0xfc, 0xff, 0xfb, 0xfe, 0xaf, 0xeb, 0xff, + 0xe8, 0xff, 0xf7, 0xfb, 0xdf, 0x56, 0xff, 0x5f, 0xff, 0xff, 0xaf, 0xff, + 0xdf, 0xfa, 0xdf, 0x5a, 0xff, 0x0a, 0xff, 0x5f, 0xf5, 0xff, 0x7f, 0xff, + 0xaf, 0xbb, 0x7f, 0xfd, 0xf8, 0x7f, 0xf5, 0xff, 0x7f, 0xfc, 0x5f, 0xd5, + 0xff, 0xba, 0xf6, 0x5f, 0xbd, 0xff, 0xbd, 0xfa, 0xaf, 0x5f, 0xfd, 0x5f, + 0xfd, 0xff, 0x7d, 0xfe, 0xff, 0xe8, 0xff, 0x9a, 0xff, 0x53, 0xea, 0x3f, + 0x57, 0xff, 0x7f, 0xf5, 0xbf, 0xb6, 0xfe, 0xd3, 0xe3, 0xff, 0xe1, 0xff, + 0x7f, 0xfd, 0xff, 0xed, 0xff, 0x6a, 0xed, 0xff, 0xf0, 0xff, 0xf7, 0xf5, + 0xdf, 0xbe, 0xfe, 0x1f, 0xff, 0xff, 0xc7, 0xff, 0x0f, 0xfe, 0x5f, 0xad, + 0xff, 0xbf, 0xf1, 0x37, 0x98, 0xff, 0x7f, 0xfe, 0x6f, 0xc8, 0xff, 0x7a, + 0xf9, 0xff, 0xff, 0xff, 0xdf, 0xfe, 0x17, 0xfb, 0xff, 0xd5, 0xfa, 0xff, + 0x0f, 0xfd, 0x5f, 0xfe, 0xaf, 0xff, 0xfe, 0x5f, 0xff, 0xff, 0x4f, 0xff, + 0x9f, 0xd4, 0xff, 0x9d, 0xfe, 0x73, 0xf5, 0x77, 0x29, 0xfe, 0xef, 0xfe, + 0x7f, 0x49, 0xfd, 0xe3, 0xe1, 0xff, 0xfa, 0xff, 0xff, 0xfd, 0x37, 0xee, + 0xff, 0xad, 0xd5, 0xff, 0x36, 0xff, 0xff, 0xf4, 0xdf, 0x56, 0xff, 0x1f, + 0xff, 0x7f, 0xf1, 0xff, 0xff, 0xfa, 0x1f, 0x4b, 0x7f, 0xff, 0xf1, 0x1f, + 0x9f, 0xff, 0xbf, 0xfe, 0xcf, 0xb6, 0xff, 0x0f, 0xf5, 0xff, 0xff, 0xff, + 0x7f, 0xff, 0xaf, 0xfd, 0x7f, 0x5b, 0xeb, 0xff, 0x97, 0xfe, 0x87, 0xff, + 0xaf, 0xbf, 0xfe, 0x5f, 0xfe, 0xff, 0xd3, 0xff, 0xff, 0xe7, 0x3f, 0x5a, + 0xfd, 0xff, 0xd5, 0x7f, 0x1b, 0xfd, 0xef, 0xfe, 0xbf, 0x6e, 0xfe, 0x4b, + 0xd1, 0xff, 0xff, 0xff, 0xff, 0xff, 0x2f, 0xfb, 0xff, 0x76, 0xfb, 0xff, + 0x97, 0xfe, 0x8f, 0xfe, 0xdf, 0x5e, 0xff, 0x9f, 0xff, 0x7f, 0xf9, 0xff, + 0xdf, 0xec, 0x97, 0x8d, 0xff, 0xbf, 0xf1, 0x17, 0x5f, 0xff, 0x5f, 0xff, + 0xd7, 0xdb, 0xff, 0x8f, 0xf5, 0xff, 0xff, 0xff, 0xff, 0xff, 0x5b, 0xed, + 0xff, 0xad, 0xd6, 0x7f, 0x2f, 0xff, 0xaf, 0xff, 0xaf, 0x7b, 0xfd, 0x1f, + 0xfd, 0x7f, 0xd6, 0xff, 0xfb, 0xdb, 0x5f, 0x3b, 0xfd, 0xfd, 0xf3, 0x7f, + 0x1a, 0xff, 0xdf, 0xfa, 0x2f, 0x3f, 0xfd, 0xff, 0xf2, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xbf, 0xa9, 0xff, 0x55, 0xf5, 0xff, 0xf0, 0xfe, 0x6f, 0xff, + 0xdf, 0xae, 0xfe, 0x5f, 0xff, 0x6f, 0xfa, 0xff, 0xbe, 0xea, 0xbf, 0x8a, + 0x7f, 0x7f, 0xe9, 0x9f, 0x5f, 0xfd, 0x6f, 0xff, 0xdf, 0xaa, 0xfe, 0x5d, + 0xf5, 0xff, 0xf7, 0xff, 0xff, 0xff, 0xff, 0xf4, 0xff, 0x76, 0xdb, 0x5f, + 0xd9, 0xff, 0xdf, 0xff, 0x5f, 0xff, 0xfe, 0x1b, 0xfd, 0x7f, 0xb6, 0xff, + 0xf5, 0xef, 0xff, 0x2a, 0xfd, 0xea, 0xf3, 0x3f, 0x1b, 0xff, 0x5f, 0xff, + 0xbf, 0xef, 0xfe, 0xfb, 0xf1, 0xff, 0xfe, 0xff, 0xff, 0xfe, 0xff, 0xd4, + 0xfe, 0xd6, 0xf6, 0xff, 0xf2, 0xff, 0xbf, 0xff, 0x6f, 0x4a, 0xff, 0x4e, + 0xeb, 0x8f, 0xda, 0xff, 0x54, 0xf8, 0xbf, 0x9b, 0xfd, 0x33, 0xfc, 0x3f, + 0x55, 0xff, 0xcf, 0xff, 0x57, 0x4a, 0xff, 0x57, 0xee, 0xff, 0xf1, 0xff, + 0x5f, 0xfc, 0xff, 0x2f, 0xff, 0xff, 0xff, 0x87, 0xff, 0xff, 0xd7, 0xff, + 0x7f, 0xca, 0xff, 0x1d, 0xfe, 0x2f, 0xb6, 0xfe, 0xe9, 0xea, 0xff, 0x2b, + 0xff, 0x66, 0xea, 0x3f, 0x55, 0xfe, 0x9f, 0xff, 0x7f, 0xce, 0xfe, 0x5f, + 0xfa, 0xff, 0xf3, 0xff, 0xff, 0xfc, 0xff, 0x2f, 0xfd, 0xff, 0xff, 0xaf, + 0xfe, 0xff, 0x7f, 0xff, 0xff, 0x7d, 0xff, 0xeb, 0xf5, 0xdf, 0x6a, 0xff, + 0xaf, 0xfe, 0xff, 0xb6, 0xfd, 0xdb, 0xff, 0xff, 0xed, 0xff, 0x6f, 0xff, + 0xdf, 0xf5, 0x7f, 0xd5, 0xff, 0x7f, 0xfd, 0xff, 0x9f, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xaf, 0xff, 0xff, 0xeb, 0xff, 0x5b, + 0xed, 0xbf, 0xda, 0xfe, 0xb6, 0xfd, 0xff, 0x6f, 0xff, 0x5b, 0xfd, 0xff, + 0xdb, 0xff, 0xdf, 0xff, 0x7f, 0xd5, 0xff, 0xb7, 0xfe, 0xff, 0xeb, 0xff, + 0x9f, 0xfa, 0xff, 0xff, 0xff, 0xff, 0xff, 0xef, 0xff, 0xff, 0xff, 0xff, + 0x7f, 0xf5, 0xff, 0xae, 0xfb, 0xeb, 0xeb, 0xff, 0x6f, 0xff, 0xff, 0xb5, + 0xfd, 0xb7, 0xff, 0x7f, 0xed, 0xff, 0xff, 0xff, 0xff, 0xef, 0xff, 0xdb, + 0xff, 0xff, 0xfe, 0xff, 0x9f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xaf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f, 0xbf, 0xff, + 0xff, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xbf, 0xff, + 0xff, 0xfd, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xbf, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xf7, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xef, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xef, 0xff, 0xff, 0xef, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xfd, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfb, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xed, 0xff, 0x7f, 0xff, 0xdf, 0xfd, 0xff, + 0x7f, 0xff, 0xbf, 0xfd, 0xff, 0xbe, 0xfd, 0xbf, 0xbd, 0xff, 0xff, 0xfe, + 0xbf, 0xbf, 0xff, 0xdd, 0xfe, 0xff, 0xb7, 0xff, 0xdf, 0xfb, 0xbf, 0xfd, + 0xff, 0xff, 0xfb, 0xff, 0xff, 0xff, 0xff, 0xff, 0xbf, 0xf2, 0xff, 0xd6, + 0xff, 0x77, 0xeb, 0xff, 0xeb, 0xda, 0x75, 0xeb, 0xff, 0x6b, 0xfb, 0xf7, + 0x76, 0xfd, 0xab, 0xdb, 0x77, 0x75, 0x7d, 0xb7, 0xfb, 0xbf, 0xdd, 0xbe, + 0x7a, 0xf7, 0xef, 0xf6, 0xbf, 0xfe, 0xef, 0xd7, 0x57, 0xff, 0xd7, 0xff, + 0xff, 0xd1, 0xff, 0xbf, 0xfe, 0xdf, 0xb6, 0xff, 0xaf, 0xfb, 0xd7, 0xee, + 0xff, 0x6e, 0xeb, 0xd7, 0xd6, 0xff, 0x6f, 0xfb, 0xdf, 0xaf, 0xff, 0xb6, + 0xf6, 0xff, 0xb5, 0xff, 0xeb, 0xed, 0xbf, 0xed, 0xff, 0xd5, 0xad, 0xbf, + 0x7e, 0xfd, 0xbf, 0xfe, 0x5f, 0xf5, 0xff, 0xd5, 0xff, 0xb7, 0xed, 0xff, + 0xdb, 0xee, 0xaf, 0xb5, 0xbf, 0xb5, 0xfd, 0xaf, 0xad, 0xfe, 0xdf, 0xee, + 0xab, 0x7e, 0xfd, 0xeb, 0xfe, 0xbf, 0xdb, 0x7e, 0x6d, 0xbb, 0x6f, 0xfb, + 0x7f, 0xfb, 0xfb, 0xd7, 0xd7, 0xff, 0xad, 0xff, 0x7f, 0x4d, 0xff, 0x0b, + 0xfd, 0x2f, 0x1a, 0x7e, 0x53, 0xd1, 0x55, 0x2d, 0x7e, 0x63, 0xe1, 0x3f, + 0x9a, 0x7a, 0x51, 0xd1, 0x9f, 0x2a, 0xfd, 0x8d, 0xf5, 0xbf, 0x46, 0xfd, + 0xd8, 0xf4, 0x5f, 0xd4, 0xff, 0x68, 0xc3, 0x17, 0x1f, 0x7e, 0xb3, 0xf0, + 0xaf, 0xcb, 0xff, 0x26, 0xff, 0x57, 0x4b, 0xff, 0x6a, 0xf5, 0xc7, 0x9a, + 0xff, 0x5a, 0xf5, 0xab, 0x55, 0xfd, 0x6a, 0xf5, 0x47, 0x2f, 0x7e, 0x8b, + 0xfe, 0xff, 0x6a, 0xff, 0x6a, 0xf4, 0x6f, 0xfb, 0xbf, 0xfa, 0xea, 0x45, + 0x95, 0xff, 0x52, 0xf5, 0xaf, 0xce, 0xfe, 0xaf, 0xfa, 0xdf, 0x5e, 0xfd, + 0xfc, 0xd5, 0xbf, 0x37, 0xfd, 0xf5, 0xe5, 0x5f, 0x5f, 0xff, 0xfa, 0xcb, + 0x6f, 0xed, 0xfd, 0xaf, 0xfd, 0xff, 0xdb, 0xff, 0xda, 0xed, 0x7f, 0xfe, + 0xff, 0xe0, 0xc2, 0x3f, 0x3f, 0xfd, 0xfc, 0xe1, 0xdf, 0xad, 0xff, 0x77, + 0xff, 0xaf, 0x1b, 0x5f, 0xea, 0xf7, 0xcb, 0x9f, 0x7e, 0xb3, 0xf9, 0xb7, + 0xfb, 0x3e, 0xec, 0xfe, 0xdf, 0x5f, 0xff, 0x8f, 0xff, 0xff, 0xb7, 0xbf, + 0x35, 0xff, 0xbf, 0xfa, 0xff, 0xda, 0xe9, 0x27, 0x15, 0x3f, 0xf5, 0xf5, + 0xaf, 0x4d, 0xff, 0x4f, 0xf5, 0x7f, 0x5b, 0xff, 0xfc, 0xd7, 0x5f, 0x3d, + 0xff, 0xef, 0xe1, 0x6f, 0xaf, 0x7d, 0xfd, 0xcb, 0xaf, 0x3a, 0xfd, 0x9f, + 0xff, 0xff, 0x6f, 0xff, 0xd5, 0xfc, 0x7f, 0xfe, 0xff, 0x70, 0xe3, 0x2f, + 0x5f, 0x7f, 0xec, 0xe5, 0x5f, 0xd1, 0xff, 0xe5, 0xfc, 0x17, 0x17, 0x3f, + 0xfd, 0xff, 0xeb, 0xef, 0x7a, 0x35, 0xfe, 0xbf, 0xe6, 0x7f, 0xfc, 0xfd, + 0xaf, 0xad, 0xfe, 0xcb, 0xfe, 0xff, 0xeb, 0xff, 0x26, 0xff, 0x7f, 0xfb, + 0xbf, 0xaa, 0xe4, 0xd7, 0x14, 0x7f, 0xfd, 0xdb, 0x6f, 0x93, 0xfe, 0xcf, + 0xfc, 0x3f, 0x55, 0x7e, 0xe9, 0xff, 0xaf, 0xbf, 0xfe, 0xf7, 0xfe, 0xdf, + 0xd6, 0x7f, 0xe9, 0xff, 0x5f, 0xeb, 0xfe, 0x8f, 0xff, 0xff, 0x5f, 0xff, + 0x4a, 0xfd, 0x7f, 0xfe, 0xff, 0xe1, 0xc9, 0xb7, 0x3d, 0xfd, 0xfc, 0xf7, + 0x5f, 0xf5, 0xff, 0xf5, 0xf5, 0x3f, 0x8d, 0x7f, 0xfc, 0xff, 0xd7, 0xdf, + 0xfd, 0x02, 0xfe, 0x37, 0xe8, 0x7f, 0x7e, 0xd5, 0xaf, 0x9a, 0xfe, 0xaf, + 0xff, 0xff, 0xe7, 0xff, 0x25, 0xff, 0x7f, 0xfe, 0xff, 0x1c, 0xf2, 0x6f, + 0x48, 0x5f, 0x7e, 0xeb, 0xaf, 0x96, 0xfe, 0xaf, 0xed, 0x37, 0x1b, 0x7d, + 0xfd, 0xff, 0x5f, 0xbf, 0xfd, 0x4b, 0xfa, 0xb7, 0xc2, 0x7f, 0xfc, 0xfb, + 0xbf, 0xd6, 0xfe, 0x8f, 0xfe, 0xff, 0x6f, 0xff, 0x45, 0xfd, 0xff, 0xf4, + 0xff, 0x50, 0xa3, 0xd7, 0x1a, 0x7f, 0xf4, 0xdf, 0xdf, 0xe0, 0xff, 0xea, + 0xf6, 0x3f, 0x2d, 0x7f, 0xfc, 0xff, 0xeb, 0xbf, 0x7e, 0x25, 0xff, 0x1f, + 0xe8, 0x5f, 0x7d, 0xd5, 0x57, 0x55, 0xff, 0xaf, 0xff, 0xef, 0xb7, 0x7f, + 0x15, 0xff, 0x7f, 0xfe, 0xff, 0x1a, 0xe5, 0xd7, 0x58, 0x7d, 0xfe, 0xf5, + 0xaf, 0x85, 0xfe, 0x05, 0xec, 0xef, 0xdd, 0xfa, 0xf4, 0xff, 0x57, 0xff, + 0xfd, 0x6d, 0xea, 0xff, 0xe7, 0x7f, 0x74, 0xd5, 0xaf, 0x7f, 0xfd, 0x8f, + 0xff, 0x5f, 0xef, 0xff, 0xf5, 0xf4, 0xff, 0xbe, 0xfe, 0xb0, 0xeb, 0xb7, + 0x17, 0x7f, 0xfc, 0xd5, 0xdf, 0x7e, 0xff, 0x56, 0xf4, 0x5f, 0xbf, 0x5e, + 0xfe, 0xfb, 0xef, 0xaf, 0xfe, 0xbb, 0xfe, 0xb7, 0xf6, 0x7f, 0xfd, 0xf8, + 0x5f, 0xad, 0xfe, 0xaf, 0xff, 0xf5, 0xab, 0xff, 0xaa, 0xfc, 0x5f, 0xfa, + 0xbf, 0x5d, 0xe3, 0x6f, 0xad, 0x7f, 0xfa, 0xeb, 0xdf, 0x4a, 0xfd, 0xe8, + 0xa3, 0xbf, 0xb6, 0xfd, 0xd5, 0xd7, 0x57, 0x9d, 0xfe, 0xf5, 0xd5, 0x5f, + 0xd7, 0x7f, 0xd5, 0xcb, 0xdf, 0xdd, 0xfe, 0x8f, 0xfe, 0x47, 0x6f, 0xff, + 0xed, 0xeb, 0x7f, 0x36, 0xfc, 0xf8, 0xcb, 0xd7, 0x0d, 0xfe, 0xd6, 0xf5, + 0x57, 0xfb, 0xbf, 0xda, 0xea, 0x6b, 0x5f, 0x7f, 0x7e, 0xed, 0xef, 0x5f, + 0x7f, 0x53, 0xdb, 0xb7, 0xfd, 0xff, 0xf6, 0xf5, 0xab, 0xb7, 0xfd, 0xaf, + 0xff, 0xd7, 0xe5, 0xbf, 0xb6, 0xfa, 0x7f, 0x5f, 0xff, 0x7a, 0xf3, 0x57, + 0xa7, 0x7f, 0x7d, 0xf1, 0xdf, 0x56, 0xff, 0xb0, 0xe3, 0x6f, 0x7b, 0xfd, + 0xe9, 0xed, 0x56, 0x1b, 0x7d, 0x7b, 0xdb, 0x77, 0xff, 0x7f, 0xbd, 0xd7, + 0xbf, 0xbe, 0xfe, 0x2d, 0xfb, 0x87, 0xa7, 0xff, 0xfa, 0xd6, 0x7f, 0x3a, + 0xfc, 0xe8, 0xa3, 0xef, 0x0e, 0xfd, 0xea, 0xe5, 0xbf, 0xfb, 0x7f, 0xe5, + 0xa8, 0x07, 0x00, 0x7f, 0x17, 0xfa, 0x83, 0xe0, 0x7f, 0x84, 0xf0, 0x07, + 0xe8, 0xff, 0x03, 0xfc, 0x87, 0x06, 0x7a, 0x83, 0xf6, 0x3f, 0xf8, 0xff, + 0xe0, 0xe1, 0x07, 0x40, 0xbf, 0xfa, 0xe2, 0x03, 0x1b, 0xff, 0x13, 0xfe, + 0x7f, 0xc2, 0xfe, 0xa8, 0xe1, 0x57, 0x55, 0xff, 0x4b, 0xf5, 0x17, 0x45, + 0xff, 0x90, 0xd2, 0x4f, 0xf9, 0xff, 0xab, 0xea, 0x1f, 0xae, 0x7e, 0x15, + 0xfc, 0x6f, 0xe9, 0x7f, 0xa5, 0xa7, 0x4f, 0x15, 0xfc, 0xe8, 0xa6, 0x4f, + 0x37, 0xff, 0x46, 0xfa, 0x5f, 0xc8, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xeb, 0xff, 0xff, 0xff, 0xff, 0xbf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf7, + 0xdb, 0x5f, 0xb5, 0xff, 0x7f, 0xff, 0x77, 0xfd, 0xff, 0xef, 0xf7, 0xdf, + 0xfe, 0xff, 0xb7, 0xfe, 0xff, 0x6f, 0xfd, 0xed, 0xfb, 0xff, 0xfb, 0x7f, + 0xfb, 0xef, 0xbf, 0xed, 0xff, 0xf7, 0xfb, 0x7f, 0x7f, 0xff, 0x7f, 0xff, + 0xff, 0xff, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xdf, 0xff, 0xff, 0xff, + 0xff, 0xfb, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xbf, 0xff, 0xff, 0x7f, + 0xff, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xef, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xef, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xbf, 0xfe, 0xff, 0xff, 0xff, 0xaf, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xbf, 0xfd, 0xff, 0xf7, 0xff, 0xff, 0xff, 0xff, 0xdf, 0xff, 0x7f, 0xbb, + 0xff, 0xff, 0xfe, 0xdf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xf7, 0xff, 0xee, 0xff, 0xd7, 0xff, 0x57, 0xff, 0xff, 0xdf, 0xff, 0xff, + 0xf5, 0xff, 0xff, 0xff, 0xff, 0xaf, 0xff, 0xdf, 0xfe, 0x6f, 0xed, 0xff, + 0xff, 0xf6, 0xef, 0xf7, 0xff, 0xed, 0xed, 0xbf, 0x5d, 0xfd, 0xf6, 0xed, + 0xb7, 0xed, 0x7e, 0xdb, 0xde, 0xff, 0xdd, 0xfe, 0x97, 0xfe, 0xef, 0xff, + 0xff, 0x3b, 0xfc, 0xff, 0xff, 0xff, 0xff, 0xff, 0x03, 0x70, 0xff, 0x26, + 0xf6, 0x8b, 0xd0, 0xff, 0x02, 0xf8, 0x13, 0x08, 0x3f, 0x72, 0xf1, 0xa5, + 0xae, 0xbe, 0xd8, 0xd2, 0x0f, 0x0e, 0xfd, 0xe4, 0xe0, 0x2f, 0x22, 0xff, + 0xc7, 0xff, 0x5f, 0xff, 0xff, 0xaf, 0xfe, 0x7f, 0xd1, 0xff, 0xff, 0xff, + 0x57, 0x62, 0xff, 0x8f, 0xfe, 0x1f, 0x55, 0xff, 0x53, 0xd1, 0x97, 0x22, + 0x7d, 0xe4, 0xd3, 0x8f, 0x3e, 0xfa, 0xea, 0xa5, 0xab, 0x2c, 0xfa, 0xc8, + 0xaa, 0xef, 0x24, 0xfc, 0x4f, 0xfd, 0xdf, 0xfe, 0xff, 0x2f, 0xfe, 0xff, + 0xf1, 0xff, 0xff, 0xff, 0x87, 0xa8, 0xff, 0x2a, 0xfa, 0x4b, 0xf0, 0xff, + 0x8b, 0xf2, 0x27, 0x88, 0x7f, 0xb9, 0xe8, 0xab, 0xaf, 0xba, 0xb8, 0xd2, + 0x4f, 0x4e, 0xbd, 0xf2, 0xe0, 0x1f, 0x82, 0xfe, 0xa5, 0xff, 0xb7, 0xff, + 0xff, 0xbf, 0xfe, 0xff, 0xf5, 0xff, 0xff, 0xff, 0xbf, 0x5b, 0xfd, 0xf5, + 0xe3, 0x9f, 0x57, 0x7e, 0xf5, 0xf2, 0xc7, 0x3a, 0x7e, 0xf4, 0xe9, 0x8f, + 0x3d, 0xfe, 0xe9, 0xe7, 0x8f, 0x3d, 0xfe, 0xa8, 0xa7, 0xff, 0x3e, 0xfd, + 0xcf, 0xff, 0x3f, 0xfd, 0xff, 0x3f, 0xfc, 0xff, 0xaa, 0xff, 0xff, 0xff, + 0x6f, 0xaf, 0xbe, 0xae, 0xf8, 0xa7, 0xae, 0xff, 0x56, 0xd9, 0xd7, 0x88, + 0x7f, 0xfd, 0xf5, 0xaf, 0xaf, 0x7e, 0x5a, 0xb1, 0xaf, 0x56, 0xfb, 0xea, + 0xf2, 0x57, 0xab, 0xfe, 0xe7, 0xff, 0xbf, 0xff, 0xff, 0xbf, 0xfe, 0xbf, + 0xd5, 0xff, 0xff, 0xff, 0x5f, 0xfd, 0x7a, 0xfc, 0xd5, 0xdf, 0xbe, 0xfc, + 0xfd, 0xf7, 0xc7, 0x1a, 0x7e, 0xeb, 0xe1, 0xaf, 0xbe, 0xfd, 0x18, 0xe7, + 0x7f, 0x4a, 0xff, 0xdb, 0xec, 0x7f, 0xcf, 0xfe, 0x87, 0xff, 0xbf, 0xfa, + 0xff, 0x7f, 0xfe, 0x7f, 0xce, 0xff, 0xff, 0xff, 0x6f, 0xaf, 0x7d, 0xfa, + 0xeb, 0xaf, 0x5b, 0x3f, 0xb5, 0xfd, 0xd7, 0x58, 0xff, 0xfe, 0xf5, 0xdf, + 0xbf, 0xfe, 0x5a, 0xb1, 0xaf, 0xd6, 0xff, 0x76, 0xfd, 0xaf, 0xcd, 0xff, + 0xd7, 0xff, 0x7f, 0xfb, 0xff, 0x2f, 0xfd, 0x7f, 0xae, 0xff, 0xff, 0xff, + 0xdf, 0x7d, 0xff, 0xf4, 0xdb, 0x3f, 0xfb, 0xfe, 0xf6, 0xeb, 0xc7, 0x39, + 0xff, 0xea, 0xe5, 0xaf, 0xf6, 0xfe, 0x10, 0xe3, 0x7f, 0x8c, 0xfe, 0xef, + 0xe8, 0xff, 0x9f, 0xfe, 0xc7, 0xff, 0xff, 0xf6, 0xff, 0x7f, 0xfe, 0xff, + 0x4c, 0xff, 0xff, 0xff, 0x3f, 0xaf, 0x3a, 0xfd, 0xd6, 0xd7, 0x86, 0xff, + 0x03, 0xfd, 0x7f, 0xea, 0xbf, 0xfe, 0xf9, 0xdf, 0x9f, 0xff, 0x9a, 0xea, + 0xff, 0xf1, 0xff, 0x15, 0xff, 0xbf, 0xd2, 0xff, 0xd7, 0xff, 0xff, 0xfd, + 0xff, 0x3f, 0xfd, 0x6f, 0xff, 0xff, 0xff, 0xff, 0xf7, 0xdd, 0x7e, 0xfc, + 0xdd, 0xbf, 0xae, 0x7e, 0x2b, 0xf7, 0xff, 0x78, 0xff, 0xfa, 0xd1, 0xbf, + 0x7a, 0xfd, 0x12, 0xca, 0x7f, 0xd3, 0xff, 0x17, 0xfd, 0xff, 0xed, 0xff, + 0x87, 0xff, 0xff, 0xd3, 0xff, 0x7f, 0xfe, 0xff, 0xef, 0xff, 0xff, 0xff, + 0x1f, 0xa2, 0x7f, 0xfd, 0xeb, 0x57, 0xd0, 0xff, 0x6f, 0xf8, 0xff, 0xfa, + 0xbf, 0xee, 0xf5, 0x6f, 0xcf, 0xbf, 0xf4, 0xe2, 0xff, 0xfa, 0xff, 0x5f, + 0xff, 0xff, 0xf1, 0xff, 0xd7, 0xff, 0xff, 0xe6, 0xff, 0x2f, 0xfb, 0xff, + 0xff, 0xff, 0xff, 0xff, 0x3f, 0xa8, 0x7e, 0xe8, 0xdb, 0xdf, 0xb2, 0xff, + 0x6d, 0xe1, 0xff, 0xf0, 0x7f, 0xfd, 0xf1, 0x7f, 0x5d, 0xff, 0xc1, 0xd4, + 0xdf, 0x4a, 0xff, 0x5f, 0xfe, 0xbf, 0xb5, 0xff, 0x4f, 0xff, 0xff, 0xd7, + 0xff, 0x3f, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xb7, 0x62, 0x7f, 0xbd, + 0xf5, 0x2f, 0xe9, 0xfe, 0xb7, 0xfa, 0xff, 0xfa, 0xff, 0xfa, 0xd5, 0x6f, + 0xd7, 0xff, 0x74, 0xe1, 0x7f, 0xf5, 0xff, 0x1f, 0xff, 0xff, 0xf2, 0xff, + 0xd3, 0xff, 0xff, 0x6f, 0xff, 0xbf, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, + 0x6f, 0xef, 0x7f, 0xb3, 0xd2, 0x6f, 0x8f, 0x7f, 0xbd, 0xd1, 0xff, 0xf4, + 0xff, 0xd6, 0xf1, 0x7f, 0x5c, 0xff, 0x65, 0xed, 0x7f, 0x8e, 0xfe, 0x5f, + 0xfd, 0x7f, 0x2c, 0xfd, 0xc7, 0xff, 0xff, 0xef, 0xff, 0x3f, 0xfe, 0xff, + 0xff, 0xff, 0xff, 0xff, 0x5f, 0xfd, 0xff, 0xd2, 0xf1, 0xaf, 0xd5, 0xde, + 0xf6, 0xfa, 0xbf, 0xfa, 0x7f, 0x7d, 0xf5, 0x7f, 0xc7, 0x7f, 0xe3, 0xf4, + 0x57, 0xed, 0xff, 0x1b, 0xff, 0x5f, 0x7b, 0xff, 0xd7, 0xff, 0xff, 0xdb, + 0xff, 0xbf, 0xfa, 0xff, 0xff, 0xff, 0xff, 0xff, 0x37, 0xeb, 0xff, 0x0f, + 0xef, 0x2f, 0xbf, 0x7c, 0xac, 0xe1, 0xff, 0xd0, 0xff, 0xd5, 0xf6, 0x7f, + 0xf1, 0xff, 0xda, 0xd5, 0x0f, 0x1b, 0xfc, 0x57, 0xfd, 0x7f, 0x2a, 0xfa, + 0x87, 0xfe, 0xff, 0xbf, 0xfe, 0x37, 0xfe, 0xff, 0xff, 0x7f, 0x55, 0xf5, + 0xaf, 0xfe, 0xff, 0xa5, 0xfe, 0x8b, 0x16, 0x7f, 0x74, 0xf5, 0xbf, 0xfa, + 0xff, 0x76, 0xf5, 0xff, 0xaa, 0xff, 0x6b, 0xf5, 0xaf, 0x2e, 0xff, 0x1f, + 0xff, 0x57, 0xb6, 0xfe, 0xd7, 0xff, 0xff, 0x57, 0xff, 0xaf, 0xfe, 0xff, + 0xff, 0xff, 0xfb, 0xef, 0x2f, 0xea, 0xff, 0x55, 0xd0, 0xaf, 0x7e, 0xfc, + 0x54, 0xf1, 0xbf, 0xd2, 0xff, 0xd6, 0xf7, 0xff, 0xe1, 0xff, 0xea, 0xeb, + 0x8d, 0x3a, 0xfa, 0x37, 0xf5, 0xdf, 0x2c, 0xfe, 0x47, 0xfd, 0xff, 0x1f, + 0xff, 0x3f, 0xfe, 0xff, 0xff, 0x5f, 0xab, 0xfa, 0xf7, 0xfd, 0xff, 0xb3, + 0xf4, 0x6f, 0x57, 0xbf, 0x6b, 0xff, 0x6f, 0xfd, 0xff, 0x2b, 0xfd, 0xff, + 0xfe, 0xff, 0xef, 0xf6, 0x7f, 0xef, 0xfe, 0xab, 0xfe, 0xbf, 0xf6, 0xfe, + 0xbf, 0xff, 0xff, 0x5f, 0xff, 0xd7, 0xff, 0xff, 0xff, 0x7f, 0xad, 0xca, + 0x4f, 0xf5, 0x7f, 0x53, 0xd1, 0xdf, 0xfe, 0xfa, 0xde, 0xee, 0xff, 0xaa, + 0xff, 0xef, 0xf6, 0xff, 0xd5, 0xff, 0xfa, 0xee, 0xcb, 0xae, 0xfe, 0xb7, + 0xfd, 0xef, 0xaa, 0xfe, 0x57, 0xfd, 0xff, 0x5f, 0xfe, 0xaf, 0xfc, 0xff, + 0xff, 0xff, 0xd9, 0xf6, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xff, 0xff, 0xff, + 0xfb, 0xff, 0xff, 0xff, 0xff, 0xbf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xef, 0xff, 0xff, 0xff, + 0xff, 0x5f, 0xff, 0xff, 0xff, 0x5f, 0xab, 0xea, 0xff, 0xff, 0xff, 0xf7, + 0xff, 0xff, 0xff, 0xff, 0xbf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf7, 0xff, + 0xbf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xfd, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xbf, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfb, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xdf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xaf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xbb, 0xff, 0xff, 0xff, 0xff, + 0xad, 0xff, 0xff, 0xff, 0xbf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf7, 0xff, + 0xf7, 0xff, 0xff, 0xf6, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xfa, 0xff, 0xff, 0xff, 0xcf, 0xfe, 0xff, 0xff, 0xff, 0xff, 0x67, + 0xff, 0xff, 0xff, 0xff, 0x12, 0xff, 0xff, 0xff, 0xcb, 0xfe, 0xff, 0x17, + 0xff, 0xff, 0xe8, 0x7f, 0xf8, 0xff, 0x5f, 0xf8, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xef, 0xff, 0xff, 0xff, 0x8f, 0xff, 0xff, + 0xff, 0xff, 0xff, 0x67, 0xff, 0xff, 0xff, 0xff, 0x27, 0xff, 0xff, 0xff, + 0x8f, 0xff, 0xff, 0x3f, 0xfe, 0xff, 0xd3, 0xff, 0xd2, 0xff, 0x7f, 0xe1, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf0, 0xff, 0xff, + 0xff, 0xbb, 0xff, 0xff, 0xff, 0xff, 0xff, 0xdf, 0xff, 0xff, 0xff, 0xbf, + 0xf8, 0xff, 0xff, 0xff, 0xbf, 0xff, 0xff, 0xd7, 0xff, 0xff, 0xfd, 0xff, + 0xef, 0xff, 0xff, 0xf5, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xe9, 0xff, 0xff, 0xff, 0x6f, 0xfd, 0xff, 0xff, 0xff, 0xff, 0x97, + 0xfe, 0xff, 0xff, 0xff, 0x55, 0xff, 0xff, 0xff, 0x57, 0xfd, 0xff, 0x5f, + 0xff, 0xff, 0xd3, 0xff, 0xea, 0xff, 0xff, 0xd5, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xf1, 0xff, 0xff, 0xff, 0xaf, 0xff, 0xff, + 0xbf, 0xff, 0xff, 0xbe, 0xff, 0xdf, 0xff, 0xbf, 0xf8, 0xff, 0xdf, 0xff, + 0x6f, 0xf7, 0xff, 0xaf, 0xff, 0xbf, 0xfd, 0xff, 0xb7, 0xff, 0x7f, 0xf1, + 0xff, 0xbb, 0xfd, 0xff, 0xff, 0xff, 0xdd, 0xff, 0xff, 0xd7, 0xff, 0x57, + 0xfd, 0x5f, 0xd5, 0xff, 0x77, 0xf5, 0xef, 0xaa, 0xfe, 0x7b, 0xfd, 0x6f, + 0x57, 0xff, 0xbb, 0xea, 0xdf, 0xde, 0xff, 0xbf, 0xfe, 0x7f, 0xab, 0xff, + 0xed, 0xea, 0xff, 0xf5, 0x7f, 0xb7, 0xf7, 0x57, 0xd5, 0xff, 0xbb, 0xfe, + 0xff, 0xfb, 0xff, 0xbe, 0xff, 0xb7, 0x7d, 0xff, 0x6e, 0xff, 0xbf, 0x5b, + 0x7f, 0xaf, 0xff, 0xbf, 0xec, 0x7f, 0xef, 0xff, 0xaf, 0x75, 0xff, 0xd5, + 0xff, 0xef, 0xf6, 0xff, 0xb7, 0xff, 0xff, 0xf1, 0xff, 0xed, 0xfa, 0xff, + 0x77, 0xff, 0xef, 0xff, 0xff, 0xd7, 0xff, 0x45, 0xf8, 0x2f, 0xc1, 0xfe, + 0x51, 0xd0, 0x37, 0x62, 0xff, 0x62, 0xf4, 0xaf, 0x58, 0x7f, 0x29, 0xd0, + 0x2f, 0xc1, 0xfe, 0x1f, 0xfe, 0xdf, 0xc4, 0xff, 0xb6, 0xe8, 0xff, 0xd3, + 0x7f, 0x09, 0xd2, 0x87, 0xcc, 0x7e, 0x29, 0xf4, 0xff, 0xff, 0xff, 0x92, + 0xfe, 0x5f, 0xa4, 0xbf, 0xb2, 0xf4, 0x2f, 0xa9, 0x7f, 0x55, 0xf5, 0x1b, + 0xea, 0xff, 0x52, 0xf4, 0x5f, 0xd4, 0xff, 0xab, 0xff, 0x5f, 0xc9, 0xff, + 0xeb, 0xfc, 0xff, 0xf9, 0xbf, 0xa4, 0xe8, 0x8b, 0xcb, 0xff, 0x52, 0xfd, + 0xff, 0xdf, 0xff, 0x27, 0xec, 0x6f, 0x09, 0xfd, 0xa6, 0xe0, 0x6f, 0xa2, + 0xfe, 0x53, 0xed, 0xbf, 0x50, 0xff, 0x63, 0xd1, 0x5f, 0x45, 0xfd, 0x17, + 0xfd, 0x7f, 0x93, 0xff, 0xaf, 0xe9, 0xff, 0xf1, 0xff, 0x11, 0xa9, 0x1f, + 0x4a, 0xdd, 0x53, 0xf5, 0xff, 0xff, 0xff, 0xde, 0xfa, 0x9f, 0xbe, 0x7e, + 0xfc, 0xf5, 0xc5, 0xaf, 0x3f, 0xbc, 0xf1, 0x7f, 0xff, 0x5f, 0xbc, 0xf6, + 0x6b, 0xbb, 0xff, 0x5f, 0xff, 0xff, 0xed, 0xff, 0x22, 0xff, 0xff, 0xe9, + 0xbf, 0xee, 0xf6, 0xf7, 0xbe, 0x7f, 0xfc, 0xf8, 0xff, 0xff, 0xff, 0xdb, + 0xfa, 0xbf, 0x3b, 0xfc, 0xb4, 0xe9, 0x4f, 0xad, 0xfe, 0x74, 0xeb, 0x7f, + 0xf5, 0xff, 0x7a, 0xf5, 0xaf, 0xb6, 0xfe, 0x1f, 0xff, 0xff, 0xcf, 0xff, + 0x0f, 0xfd, 0xff, 0xd3, 0xff, 0xaa, 0xd5, 0x97, 0x6d, 0x7e, 0xd9, 0xe1, + 0xff, 0xff, 0xff, 0xa2, 0xec, 0xd7, 0xae, 0x5e, 0xfe, 0xff, 0xe7, 0x5f, + 0x7f, 0x08, 0xf0, 0xef, 0xfa, 0x3f, 0xf4, 0xfa, 0xdf, 0x5f, 0xff, 0x5f, + 0xff, 0xff, 0xcb, 0xff, 0x25, 0xff, 0xff, 0xf4, 0xff, 0x5d, 0xf7, 0xdf, + 0xde, 0x7f, 0xfe, 0xf5, 0xff, 0xff, 0xff, 0xae, 0xf8, 0xaf, 0x3f, 0x7d, + 0xf4, 0xf5, 0x47, 0x77, 0x7f, 0xa1, 0xe2, 0xbf, 0xfb, 0x7f, 0xd5, 0xea, + 0xaf, 0x7e, 0xfd, 0x1f, 0xfd, 0xff, 0x9f, 0xff, 0x4b, 0xfa, 0xff, 0xf1, + 0x7f, 0x75, 0xcd, 0xbf, 0x3d, 0x7d, 0xf4, 0xf1, 0xff, 0xff, 0xff, 0xa2, + 0xee, 0x9f, 0xbe, 0x7e, 0xfd, 0xff, 0xd5, 0x9d, 0x5f, 0x0a, 0xf9, 0x7f, + 0xfd, 0xff, 0x0a, 0xfa, 0xdf, 0x5b, 0xff, 0x5f, 0xff, 0xff, 0xcf, 0xff, + 0x87, 0xff, 0xff, 0xf5, 0xff, 0xad, 0xf6, 0xab, 0xb7, 0x7e, 0xbd, 0xf5, + 0xff, 0xff, 0xff, 0xf8, 0xf8, 0xfb, 0x36, 0x7e, 0xe8, 0xef, 0x87, 0xb7, + 0x7e, 0x7a, 0xeb, 0x7f, 0xeb, 0xff, 0x53, 0xea, 0x2f, 0x7f, 0xfd, 0x1f, + 0xff, 0xff, 0xcf, 0xff, 0xbd, 0xf4, 0xff, 0xd1, 0xff, 0xba, 0xcd, 0x6f, + 0xef, 0x7e, 0xf4, 0xe5, 0xff, 0xff, 0xff, 0xaa, 0xee, 0x4f, 0xaf, 0x7e, + 0xbd, 0xfd, 0xd7, 0x56, 0x7f, 0xec, 0xfd, 0xdf, 0xfa, 0xff, 0xfe, 0xf5, + 0xef, 0xad, 0xfe, 0x5d, 0xfb, 0xff, 0xad, 0xff, 0xa6, 0xfc, 0xff, 0xf5, + 0xff, 0x6a, 0xfb, 0x9f, 0xbf, 0x5e, 0x5d, 0xf9, 0xff, 0xff, 0xff, 0xf9, + 0xec, 0xaf, 0x3c, 0x7a, 0xf5, 0xeb, 0x97, 0xd7, 0x7e, 0x59, 0xeb, 0xbf, + 0xbb, 0xff, 0x57, 0xf7, 0x5f, 0xdf, 0xfe, 0x1f, 0xf7, 0xff, 0xcf, 0xff, + 0xdd, 0xda, 0xbf, 0x65, 0xff, 0xaa, 0xca, 0x77, 0xad, 0x7d, 0xf4, 0xf1, + 0xff, 0xff, 0xbf, 0x04, 0xf2, 0x0b, 0xc1, 0x7f, 0x05, 0xd8, 0x2f, 0x08, + 0xff, 0x82, 0xf0, 0x57, 0x64, 0xff, 0xdb, 0xfc, 0x0b, 0x2a, 0xfa, 0x22, + 0xfc, 0xaf, 0xda, 0xff, 0xe8, 0xe0, 0x6f, 0xd0, 0x7e, 0xd9, 0xcc, 0x0f, + 0x0e, 0xfe, 0x03, 0xfe, 0xff, 0xff, 0xff, 0xa8, 0xc0, 0x2f, 0x95, 0xfe, + 0x53, 0xf1, 0x7f, 0x21, 0xfd, 0x2b, 0xf5, 0xaf, 0xc0, 0xff, 0xb7, 0xf5, + 0xaf, 0x4e, 0xfe, 0x47, 0xe9, 0xff, 0xb5, 0xff, 0xd9, 0xaa, 0x5f, 0x85, + 0xff, 0xb2, 0x99, 0x4f, 0x5d, 0xfc, 0xaa, 0xf4, 0xff, 0xff, 0xff, 0xef, + 0xff, 0xff, 0xed, 0xff, 0xbe, 0xff, 0xef, 0xff, 0xff, 0xdf, 0xff, 0x7f, + 0x7f, 0x7f, 0xad, 0xfe, 0x7b, 0xff, 0xfb, 0x7d, 0xff, 0xaf, 0xfa, 0xff, + 0xef, 0xf7, 0xff, 0xfd, 0xbe, 0x7d, 0xef, 0xfb, 0xee, 0xff, 0xdf, 0xff, + 0xff, 0xff, 0xff, 0x5f, 0xff, 0xb7, 0xff, 0xff, 0x77, 0xf7, 0xbf, 0x6e, + 0xff, 0xfb, 0xf6, 0xef, 0xfd, 0xff, 0xab, 0xfe, 0xef, 0x5d, 0xff, 0xef, + 0xf6, 0x7f, 0xeb, 0xff, 0xfd, 0xfe, 0xbf, 0xf7, 0xff, 0xef, 0xfd, 0xdf, + 0xbf, 0xff, 0xfb, 0xfe, 0xff, 0xff, 0xff, 0xfb, 0xfd, 0xff, 0xfd, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xdf, 0xff, 0xff, 0xf7, 0xff, 0xda, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xaf, 0xfa, 0xff, 0xff, 0xfb, 0xff, 0xdf, + 0xff, 0xfd, 0xdf, 0xff, 0xfe, 0xfd, 0xdf, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xfd, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xf7, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xef, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f, 0xff, 0xff, 0xf5, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xfe, 0xff, 0xff, 0xff, 0xaf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfd, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0x57, 0xff, 0xff, 0xf1, 0xff, 0x77, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0x5f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xdf, 0xfe, 0xff, 0xf3, + 0xff, 0x5f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xcf, 0xff, 0xff, 0xf4, 0xff, 0x2f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x5f, 0xed, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xbf, 0xbb, 0xff, 0x1f, 0xff, 0xff, 0xd1, 0xff, 0x5f, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xb7, 0xdb, 0xff, 0x5b, 0xed, 0xaf, 0xb6, 0xff, + 0x57, 0xfb, 0xf7, 0xfe, 0x7f, 0xff, 0xfe, 0xd7, 0xb6, 0xfd, 0xfa, 0xed, + 0x5b, 0xdb, 0xbf, 0x7d, 0xfb, 0xff, 0xee, 0xff, 0xc7, 0xff, 0xff, 0xf5, + 0xff, 0x1f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xaf, 0x52, 0x7f, 0x97, + 0xd1, 0xbf, 0x66, 0xff, 0x5f, 0xea, 0x0f, 0x40, 0x7f, 0xd8, 0xf4, 0x1f, + 0x2e, 0xbe, 0xa9, 0xa3, 0x27, 0x17, 0x7e, 0xe9, 0xd1, 0xaf, 0x48, 0xfd, + 0x1f, 0xff, 0xff, 0xf1, 0xff, 0x3f, 0xfd, 0xff, 0xff, 0xff, 0xff, 0xff, + 0x8b, 0xf4, 0xff, 0xa5, 0xfa, 0x17, 0xab, 0xff, 0x96, 0xed, 0xaf, 0xca, + 0x5f, 0x7d, 0xfa, 0x4b, 0x4d, 0x7d, 0xfa, 0xea, 0x97, 0x45, 0x5f, 0x7c, + 0xf5, 0x5f, 0x52, 0xff, 0xcf, 0xff, 0xff, 0xf5, 0xff, 0x4f, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xaf, 0xa1, 0xfe, 0x8f, 0xd1, 0x77, 0xa6, 0xfe, + 0x17, 0xeb, 0x2f, 0xc8, 0x7f, 0xf4, 0xea, 0x4f, 0x1a, 0xfa, 0xd0, 0xc5, + 0x17, 0x2f, 0x7f, 0xe9, 0xd1, 0xdf, 0xc4, 0xfe, 0x0f, 0xff, 0xff, 0xe1, + 0xff, 0x9f, 0xfe, 0x7f, 0xbb, 0xff, 0xff, 0xff, 0x0f, 0x1e, 0x3f, 0x78, + 0xf4, 0x9f, 0xd8, 0xff, 0xea, 0xfa, 0xef, 0xff, 0x7f, 0xdd, 0xf6, 0xaf, + 0xaf, 0xfe, 0x5a, 0xf3, 0x2f, 0xe5, 0x7f, 0xbe, 0xf2, 0xaf, 0xcb, 0xff, + 0xab, 0xff, 0xff, 0xf5, 0xff, 0x1f, 0xfd, 0x6f, 0x76, 0xff, 0xff, 0xff, + 0xff, 0x7e, 0x7c, 0xed, 0xf5, 0x3f, 0x59, 0xff, 0xa5, 0xd6, 0x5f, 0xb5, + 0x7f, 0xf9, 0xf5, 0x8f, 0x3a, 0xfe, 0x58, 0xa3, 0x7f, 0x4f, 0xff, 0x71, + 0xfe, 0x5f, 0x9d, 0xfe, 0xaf, 0xfe, 0xff, 0xe9, 0xff, 0x5f, 0xfd, 0xdf, + 0x6c, 0xfe, 0xff, 0xff, 0x57, 0x1b, 0x7f, 0xbc, 0xed, 0xbf, 0xfe, 0xff, + 0x27, 0xfb, 0xbf, 0xfe, 0x7f, 0x5f, 0xfb, 0x7f, 0xef, 0xff, 0x17, 0xef, + 0x5f, 0xf8, 0x7f, 0x73, 0xfa, 0xff, 0xd1, 0xff, 0x8b, 0xff, 0xff, 0xf5, + 0xff, 0x9f, 0xfe, 0x8f, 0xc1, 0xff, 0xff, 0xff, 0x6f, 0x7f, 0xfc, 0xf4, + 0xfa, 0x3f, 0xfb, 0xff, 0x4d, 0xf6, 0xbf, 0xfd, 0xff, 0xfa, 0xeb, 0x6f, + 0x5d, 0xbd, 0x3a, 0xea, 0xff, 0xe9, 0xff, 0xd3, 0xf6, 0x5f, 0xf3, 0xff, + 0xaf, 0xff, 0xff, 0xe1, 0xff, 0x3f, 0xff, 0x2f, 0x0b, 0xfd, 0xff, 0xff, + 0x5f, 0x2a, 0x5f, 0x2d, 0xea, 0xbf, 0xfe, 0xff, 0x93, 0xfd, 0x6f, 0xff, + 0xbf, 0x7e, 0xf5, 0xbf, 0xd6, 0xff, 0x4a, 0xfb, 0xbf, 0xb8, 0xff, 0x8f, + 0xfe, 0xff, 0xa8, 0xff, 0x8f, 0xff, 0xff, 0xf5, 0xff, 0x9f, 0xfd, 0xcf, + 0xe8, 0xfe, 0xff, 0xff, 0x5f, 0x2c, 0x7e, 0x74, 0xfa, 0x3f, 0xfb, 0xff, + 0x77, 0xd1, 0xff, 0xf6, 0xff, 0xea, 0xed, 0x7f, 0x9e, 0xff, 0x1a, 0xd4, + 0xbf, 0xf2, 0xff, 0x8b, 0xff, 0xdf, 0x76, 0xff, 0x2f, 0xff, 0xff, 0xe9, + 0xff, 0x1f, 0xff, 0xdf, 0xdf, 0xff, 0xff, 0xff, 0xb7, 0xf1, 0xff, 0xab, + 0xeb, 0xbf, 0xff, 0xff, 0xae, 0xee, 0xaf, 0xde, 0x7f, 0xbd, 0xf5, 0x7f, + 0xe5, 0xff, 0x55, 0xf5, 0xff, 0xd8, 0xff, 0xaf, 0xfe, 0x7f, 0xfa, 0xff, + 0xcf, 0xff, 0xff, 0xf5, 0xff, 0x5f, 0xff, 0xff, 0xf7, 0xff, 0xff, 0xff, + 0x2f, 0x53, 0xff, 0xb7, 0xfa, 0x2f, 0xd5, 0xff, 0xda, 0xe2, 0x7f, 0xaa, + 0xfe, 0x75, 0xd1, 0xff, 0xd2, 0xff, 0xe7, 0xec, 0x2f, 0x57, 0xff, 0xd7, + 0xff, 0x57, 0x2a, 0xfd, 0x1f, 0xff, 0xff, 0xf1, 0xff, 0x1f, 0xfe, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xdf, 0xff, 0xff, 0x7f, 0xf5, 0x37, 0xff, 0xff, + 0x65, 0xe9, 0x5f, 0x5d, 0x7f, 0xd5, 0xfa, 0x7f, 0xe9, 0xff, 0x52, 0xf5, + 0x5b, 0xe3, 0xff, 0xda, 0xff, 0x5f, 0xd7, 0xfe, 0xcf, 0xff, 0xff, 0xf7, + 0xff, 0x5f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xbb, 0xf6, 0xff, 0xef, + 0xd7, 0x6f, 0xb4, 0xff, 0xad, 0xc3, 0x7f, 0xd5, 0xfe, 0xb5, 0xd1, 0x7f, + 0xd3, 0xff, 0xe7, 0xec, 0x37, 0xa7, 0xfe, 0x57, 0xff, 0x7f, 0xba, 0xfe, + 0x1f, 0xfd, 0xff, 0xed, 0xff, 0x3b, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xaf, 0xfd, 0xff, 0xbf, 0xfc, 0x07, 0xe3, 0xff, 0x1a, 0xfe, 0xff, 0xf2, + 0xff, 0x47, 0xf5, 0xff, 0xfd, 0xff, 0xbf, 0xff, 0x47, 0x17, 0x7f, 0x90, + 0xff, 0x2f, 0xc4, 0xff, 0xa7, 0xff, 0xff, 0xfb, 0xff, 0x4f, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0x0f, 0xf6, 0xff, 0xff, 0xd0, 0x57, 0xee, 0xff, + 0x5b, 0xfc, 0xff, 0xd2, 0xfe, 0x9f, 0xe1, 0xff, 0xd5, 0xff, 0xf6, 0xfa, + 0xcf, 0x46, 0xff, 0x82, 0xff, 0x7f, 0x91, 0xfe, 0xff, 0xfe, 0xff, 0xff, + 0xff, 0xdf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xab, 0xfe, 0xff, 0x2f, + 0xf1, 0xff, 0xf7, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf6, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xbf, 0xff, 0xff, 0xff, 0xff, 0x77, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xef, 0xfd, 0xff, 0xff, 0xf7, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xbd, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xbf, 0xff, 0xff, 0xbf, 0xfd, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xf7, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xbf, 0xfd, 0xff, 0xff, + 0xef, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf7, 0xff, 0xff, 0xfe, 0xff, 0xff, + 0xff, 0xfb, 0xff, 0xff, 0xff, 0xff, 0x6f, 0xfb, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0x5f, 0x55, 0xff, 0xff, 0xff, 0xff, 0xfa, 0xff, + 0xd7, 0xff, 0xff, 0xff, 0xff, 0x6f, 0xf5, 0xff, 0xf4, 0xff, 0x8b, 0xf6, + 0xff, 0xff, 0xff, 0x57, 0xff, 0xff, 0xfa, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0x7f, 0xed, 0xff, 0xff, 0xff, 0xff, 0x52, 0xfe, 0xff, + 0xff, 0xff, 0xd7, 0xff, 0x7f, 0xfd, 0xff, 0xff, 0xff, 0xfa, 0xef, 0xff, + 0xfd, 0xff, 0x2f, 0xf6, 0xff, 0xff, 0xff, 0xff, 0xf5, 0xff, 0xd7, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfd, 0xff, 0xff, 0xff, + 0x5f, 0xef, 0xff, 0xff, 0xff, 0x7f, 0xf1, 0xff, 0x87, 0xfc, 0xff, 0xff, + 0xff, 0xa4, 0xb0, 0xff, 0xf8, 0x7f, 0xb3, 0xfd, 0x7f, 0xad, 0xff, 0x06, + 0xfe, 0x7f, 0xcd, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x6f, + 0x42, 0xff, 0x0b, 0xfe, 0x3f, 0xb1, 0xfe, 0xff, 0xff, 0xff, 0xb5, 0xff, + 0x97, 0xf4, 0x6f, 0xbb, 0xfe, 0xe0, 0xe2, 0xff, 0xfa, 0xff, 0xe6, 0xf2, + 0xff, 0xbf, 0xff, 0x55, 0xe8, 0xff, 0xdb, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xdf, 0x48, 0xff, 0x4b, 0xfe, 0xbf, 0x82, 0xfe, 0xff, + 0xff, 0x7f, 0xf1, 0xff, 0x26, 0xfe, 0xff, 0xef, 0xff, 0xaa, 0xf0, 0xff, + 0xf8, 0xff, 0xb3, 0xfd, 0xff, 0xde, 0xff, 0x87, 0xf6, 0x7f, 0xcd, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x3f, 0xe5, 0xfe, 0x2f, 0xfd, + 0x5f, 0x48, 0xff, 0xff, 0xff, 0x6f, 0x82, 0xfe, 0xe7, 0xfd, 0x2f, 0x88, + 0xfe, 0xe6, 0xed, 0xff, 0xf2, 0xff, 0xa6, 0xeb, 0xff, 0xfd, 0xbf, 0x38, + 0xa5, 0x7f, 0x4b, 0xff, 0xef, 0xfd, 0xef, 0xf6, 0xff, 0xff, 0xff, 0x4f, + 0x24, 0xfe, 0xfb, 0xff, 0xdf, 0xc0, 0xfc, 0xff, 0xff, 0x5f, 0xca, 0xff, + 0x75, 0xff, 0x5f, 0xd1, 0xff, 0xab, 0xf4, 0xff, 0xfc, 0x7f, 0xb1, 0xfd, + 0xff, 0xbf, 0xff, 0x8a, 0xf2, 0xdf, 0xea, 0xff, 0x7f, 0xef, 0xbf, 0xdf, + 0xff, 0xff, 0xff, 0x2b, 0x59, 0xfd, 0xaf, 0xff, 0xaf, 0x54, 0xff, 0x5f, + 0xff, 0xdf, 0x7e, 0xff, 0xe7, 0xff, 0x7f, 0x37, 0xfd, 0xa7, 0xfd, 0xff, + 0xf0, 0xff, 0x96, 0xfe, 0xff, 0xff, 0x7f, 0xd5, 0xaa, 0xff, 0x8e, 0xff, + 0xd7, 0xdb, 0x27, 0x10, 0xfe, 0xff, 0xff, 0x6f, 0x8a, 0xfd, 0xff, 0xff, + 0x5f, 0x22, 0xfe, 0xff, 0xff, 0x6f, 0xeb, 0xff, 0xde, 0xff, 0x57, 0x6f, + 0xff, 0x75, 0xfc, 0xff, 0xfa, 0x3f, 0x8c, 0xf5, 0xff, 0xff, 0xff, 0x62, + 0xf7, 0x5f, 0xeb, 0xff, 0xad, 0xfa, 0x47, 0x45, 0xff, 0xbf, 0xff, 0x5b, + 0xd7, 0xfe, 0xff, 0xff, 0x3f, 0x00, 0xfe, 0xaf, 0xfe, 0x5f, 0x5f, 0xff, + 0x75, 0xfd, 0xaf, 0xaa, 0xfe, 0xc7, 0xe9, 0xff, 0xf8, 0x7f, 0x99, 0xfe, + 0xff, 0xff, 0xbf, 0x67, 0xad, 0xff, 0x4e, 0xff, 0xdb, 0xd5, 0x4f, 0x90, + 0xfe, 0x77, 0xfb, 0x5b, 0xcc, 0xfa, 0xff, 0xff, 0xaf, 0x92, 0xfe, 0xff, + 0xff, 0xef, 0xf6, 0xff, 0x80, 0xff, 0xdf, 0xde, 0xfe, 0x1f, 0xfd, 0xff, + 0xff, 0x7f, 0x74, 0xf1, 0xff, 0xff, 0x7f, 0xd5, 0xd5, 0x5f, 0xf5, 0x7f, + 0x73, 0xfb, 0xff, 0x5f, 0x7f, 0x89, 0xf0, 0x77, 0x5a, 0xff, 0xff, 0xff, + 0x1f, 0x40, 0xff, 0xdf, 0xfe, 0xaf, 0xfe, 0xff, 0x15, 0xfd, 0xbf, 0xbb, + 0xfe, 0x2f, 0xfd, 0xff, 0xf5, 0x7f, 0xd5, 0xd1, 0xff, 0xff, 0x7f, 0xa5, + 0xbd, 0xff, 0xa5, 0xfe, 0x53, 0xf5, 0xaf, 0x1b, 0xfd, 0x93, 0xf2, 0xd7, + 0xd2, 0xfa, 0xff, 0xff, 0x2f, 0xc2, 0xfe, 0xbf, 0xff, 0xdf, 0xd5, 0xff, + 0xe6, 0xff, 0x57, 0xad, 0xff, 0x15, 0xff, 0xff, 0xfe, 0xff, 0x8b, 0xf4, + 0xff, 0xff, 0xff, 0x54, 0xd2, 0x5f, 0xd4, 0x7f, 0x7c, 0xfe, 0xff, 0x5f, + 0xff, 0x7e, 0xff, 0x2f, 0x5e, 0xff, 0xff, 0xff, 0x5f, 0x05, 0xff, 0x6f, + 0xfd, 0xbf, 0x5e, 0xff, 0xa7, 0xfe, 0x5f, 0x55, 0xfd, 0x37, 0xf5, 0xff, + 0xf5, 0xff, 0x7f, 0xf5, 0xff, 0xff, 0xff, 0x41, 0xf4, 0x7f, 0x41, 0xff, + 0x54, 0xea, 0xff, 0x1f, 0xff, 0xed, 0xf6, 0xef, 0x54, 0xfd, 0xff, 0xff, + 0x7f, 0x80, 0xff, 0x0f, 0xfe, 0x57, 0xd5, 0xff, 0xea, 0xff, 0xef, 0xae, + 0xfe, 0x4f, 0xfd, 0x7f, 0xfd, 0xff, 0x2d, 0xf6, 0xff, 0xff, 0x5f, 0x8a, + 0xaa, 0x7f, 0xea, 0x3f, 0x75, 0xfd, 0xff, 0x5f, 0xff, 0xff, 0xff, 0x1b, + 0x5b, 0xff, 0xff, 0xff, 0x5f, 0x15, 0xff, 0x5f, 0xfd, 0xff, 0x71, 0xff, + 0xa7, 0xea, 0xaf, 0xa0, 0xff, 0x1f, 0xff, 0xff, 0xf1, 0xff, 0xfd, 0xfc, + 0xff, 0xff, 0xff, 0xbb, 0xf6, 0xff, 0x6f, 0x7f, 0x63, 0xf5, 0xff, 0xff, + 0xfe, 0xdf, 0xff, 0x7f, 0x4e, 0xfd, 0xff, 0xff, 0x7f, 0xc2, 0xfe, 0x07, + 0xfe, 0xbf, 0xe4, 0x7f, 0xe5, 0xff, 0x5f, 0x55, 0xff, 0x95, 0xfa, 0x7f, + 0xfa, 0xbf, 0x36, 0xf7, 0xff, 0xff, 0xff, 0x6a, 0xed, 0x7f, 0xfd, 0xff, + 0xb5, 0xf5, 0xff, 0xff, 0xff, 0xff, 0xff, 0x4f, 0xaa, 0xff, 0xff, 0xff, + 0xdf, 0xa4, 0xff, 0x5f, 0xfd, 0xff, 0xd5, 0xff, 0x08, 0xc0, 0xff, 0xff, + 0xfe, 0x17, 0xec, 0xff, 0xf8, 0xff, 0x75, 0xfe, 0xff, 0xff, 0xff, 0x1f, + 0xfd, 0xff, 0xff, 0xff, 0xaf, 0xd7, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0x62, 0xff, 0xff, 0xff, 0xbf, 0xda, 0xfe, 0x0f, 0xfe, 0xff, 0xf1, 0xff, + 0xa2, 0xea, 0xdf, 0xde, 0xff, 0x47, 0xfd, 0xff, 0xfa, 0x7f, 0x8b, 0xf6, + 0xff, 0xff, 0xff, 0xab, 0xfe, 0xff, 0xff, 0xff, 0xdb, 0xfa, 0xff, 0xff, + 0xff, 0xff, 0xff, 0x7f, 0xf5, 0xff, 0xff, 0xff, 0x5f, 0xad, 0xff, 0x5f, + 0xfe, 0xff, 0xf5, 0xff, 0x88, 0xe4, 0xff, 0xff, 0xff, 0x17, 0xf9, 0xff, + 0xf0, 0xff, 0x22, 0xfe, 0xff, 0xff, 0xff, 0x9f, 0xfa, 0xff, 0xff, 0xff, + 0xb7, 0xeb, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xa5, 0xff, 0xff, 0xff, + 0xbf, 0x52, 0xff, 0xaf, 0xfb, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xff, 0xff, + 0xff, 0xff, 0xfe, 0xff, 0xfa, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f, 0xff, 0xff, 0xf7, 0xff, + 0xdb, 0xf5, 0xff, 0xff, 0xff, 0xdf, 0xff, 0xff, 0xfa, 0xff, 0xaa, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xaf, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xf5, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xef, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xdf, 0xff, 0xff, 0xfe, 0xff, 0xbf, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xfb, 0xff, 0xff, 0xff, 0xff, 0xf6, 0xff, + 0xef, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f, 0xd7, 0xfe, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xbb, 0xfe, + 0xdf, 0xf5, 0xff, 0x6d, 0xfd, 0xff, 0xff, 0xff, 0x7f, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xbf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0x7d, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xaf, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xef, 0xff, 0x7f, 0xff, 0xff, 0xd7, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xeb, 0xff, 0xff, 0xff, 0xff, 0xea, 0xff, 0x75, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xeb, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f, + 0xff, 0xff, 0xf7, 0xff, 0xff, 0xff, 0xaf, 0xfe, 0xff, 0xfa, 0xff, 0x3f, + 0xfb, 0xff, 0xff, 0xff, 0x5f, 0xfd, 0xff, 0xdf, 0xff, 0xbf, 0xb7, 0xff, + 0xdb, 0xfd, 0xff, 0xea, 0xff, 0xff, 0xff, 0x17, 0x10, 0xfe, 0xff, 0xff, + 0xff, 0xff, 0xff, 0x97, 0xff, 0x7f, 0xdd, 0xff, 0xff, 0xff, 0x8b, 0xff, + 0x5f, 0xfc, 0xeb, 0xd5, 0x7e, 0xfd, 0xff, 0xff, 0x7f, 0xcb, 0xff, 0x7f, + 0xff, 0x7f, 0xed, 0xff, 0x57, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0x42, 0xfc, 0xff, 0xff, 0xff, 0xff, 0xff, 0x1f, 0xfe, 0xff, 0xd5, 0xff, + 0xff, 0xff, 0x5f, 0xff, 0x7d, 0xe9, 0xdf, 0xb7, 0xf5, 0xff, 0xbf, 0xfe, + 0x5f, 0x77, 0xff, 0x1f, 0xff, 0xbf, 0xeb, 0xff, 0x3d, 0xff, 0xff, 0xea, + 0xff, 0xff, 0xff, 0x87, 0xb5, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x5f, + 0xff, 0x5f, 0x7f, 0xff, 0xff, 0xff, 0xaf, 0xbf, 0xfb, 0x7e, 0xf5, 0x2f, + 0xbf, 0xfa, 0xff, 0xff, 0xff, 0xee, 0xff, 0x5f, 0xfd, 0x7f, 0xdf, 0xff, + 0x2b, 0xfd, 0xff, 0xfd, 0xff, 0xfb, 0xff, 0x0f, 0xa5, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0x1f, 0xfe, 0xff, 0xca, 0xff, 0xff, 0xff, 0x6f, 0xbd, + 0xde, 0xfa, 0xed, 0x3f, 0xf5, 0xfe, 0x7f, 0xff, 0x97, 0xeb, 0xff, 0x1b, + 0xff, 0xff, 0xea, 0xff, 0xbf, 0xff, 0xff, 0xfa, 0xbf, 0xbf, 0xfd, 0xaf, + 0xf1, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xd7, 0xff, 0x5f, 0x7f, 0xff, + 0xff, 0xff, 0xdf, 0xff, 0x7d, 0xf7, 0xfb, 0xab, 0x5e, 0xff, 0xdf, 0xff, + 0x7f, 0xae, 0xff, 0x37, 0xeb, 0xff, 0xda, 0xff, 0x55, 0xfd, 0xff, 0xff, + 0x7f, 0xf5, 0xe9, 0x0f, 0xa3, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x1f, + 0xfe, 0xff, 0xca, 0xfe, 0xda, 0xfe, 0x5b, 0xad, 0xfe, 0xbc, 0xd6, 0xdf, + 0xda, 0xfe, 0xbf, 0xfe, 0xbf, 0xeb, 0xff, 0x9e, 0xfe, 0xff, 0xfd, 0xff, + 0xaf, 0xff, 0xff, 0xff, 0xff, 0x7e, 0xf6, 0xaf, 0x69, 0xff, 0xbf, 0xff, + 0xff, 0xff, 0xff, 0x5f, 0xff, 0x5f, 0xff, 0xff, 0xff, 0xff, 0xaf, 0xbf, + 0x7b, 0x6b, 0xfd, 0xb5, 0xad, 0xff, 0x7f, 0xff, 0xff, 0xfd, 0xff, 0x10, + 0xa0, 0xbf, 0xaa, 0xff, 0xb9, 0xfa, 0xff, 0xf7, 0xff, 0xe8, 0xd5, 0x5f, + 0xd2, 0xfe, 0xbf, 0xfe, 0xff, 0xff, 0xff, 0x1f, 0xfd, 0xff, 0x94, 0x7f, + 0x55, 0xf4, 0x57, 0x55, 0x5f, 0xad, 0xd5, 0xaf, 0xb5, 0xfe, 0xbf, 0xfe, + 0x7f, 0xff, 0xff, 0xa2, 0xea, 0xbf, 0xf5, 0xff, 0x69, 0xff, 0xff, 0xff, + 0xbf, 0xfa, 0xf6, 0x6f, 0x68, 0xff, 0x6f, 0xff, 0xff, 0xff, 0xff, 0xaf, + 0xfe, 0xbf, 0xeb, 0x7f, 0x75, 0xff, 0xb7, 0xda, 0x7e, 0x75, 0xf5, 0x5b, + 0xd7, 0xff, 0x2f, 0xfe, 0xff, 0xfb, 0xff, 0x0a, 0xe0, 0x7f, 0xef, 0xff, + 0x6b, 0xff, 0xff, 0xff, 0xff, 0xe8, 0xeb, 0x5f, 0xc9, 0xff, 0x7f, 0xfd, + 0xff, 0xff, 0xff, 0x1f, 0xff, 0x7f, 0x5e, 0xff, 0x56, 0xf4, 0x6f, 0xab, + 0xde, 0x4d, 0xd6, 0x6f, 0xad, 0xfe, 0xbf, 0xfe, 0xff, 0xff, 0xff, 0x5f, + 0xff, 0xff, 0xfa, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7b, 0xed, 0xff, + 0x71, 0xff, 0x9f, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xfd, 0xff, 0xe9, 0xff, + 0xb3, 0xe9, 0xff, 0x5d, 0x7e, 0xdb, 0xcb, 0xbf, 0x98, 0xff, 0x57, 0xfe, + 0xff, 0xff, 0xff, 0x3b, 0xff, 0xff, 0xdb, 0xff, 0x57, 0xff, 0xff, 0xff, + 0xff, 0xea, 0xdb, 0xbf, 0xd3, 0xfe, 0x3f, 0xfe, 0xff, 0xff, 0xff, 0xb7, + 0xff, 0xbf, 0xdb, 0xff, 0x66, 0xd3, 0x5f, 0xb3, 0xfc, 0xb7, 0xde, 0xff, + 0x12, 0xfd, 0xdd, 0xff, 0xff, 0xff, 0xff, 0xaf, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0x7e, 0xf5, 0xff, 0x64, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0x6f, 0x44, 0xff, 0xdb, 0xf8, 0xff, 0x1a, + 0x7f, 0xf5, 0xf5, 0x5f, 0x5f, 0xff, 0xd3, 0xfe, 0xff, 0xff, 0xff, 0x7f, + 0xfd, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xd2, 0xc3, 0xff, + 0xc9, 0xff, 0xff, 0xff, 0xff, 0xfa, 0xff, 0xff, 0xff, 0x7f, 0xd1, 0xfe, + 0xab, 0xd3, 0xdf, 0x76, 0xfc, 0xd7, 0xd5, 0x7f, 0x15, 0xff, 0xb7, 0xff, + 0xff, 0xff, 0xff, 0xaf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0x6d, 0xf5, 0xff, 0xb1, 0xfe, 0xff, 0xff, 0xff, 0xfe, 0xff, 0xff, + 0xff, 0x7f, 0xc4, 0x7f, 0xdb, 0xf8, 0x7f, 0x2d, 0x7f, 0x7d, 0xf5, 0xdf, + 0x2e, 0xfd, 0xea, 0xfa, 0xff, 0xff, 0xff, 0x6d, 0xed, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xaa, 0xc5, 0xff, 0xc5, 0xfd, 0xff, 0xff, + 0xff, 0xe8, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xb6, 0xf6, 0xaf, 0x2d, + 0x7a, 0xf5, 0xdd, 0xd7, 0x2a, 0xff, 0xdb, 0xf7, 0xff, 0xff, 0xff, 0xb7, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x26, 0xe9, 0xbf, + 0xb9, 0xfe, 0xff, 0xff, 0xbf, 0xf8, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f, + 0x75, 0xfa, 0xdf, 0x5a, 0xfe, 0xbe, 0xf6, 0x5f, 0xaf, 0xfe, 0x55, 0xfd, + 0xff, 0xff, 0xff, 0xbe, 0xea, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0x25, 0xa3, 0x7f, 0x21, 0xfe, 0xff, 0xff, 0xff, 0xea, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0x6d, 0xf6, 0xbf, 0xb7, 0xdc, 0xfd, 0xd6, 0xf7, + 0x1a, 0xfd, 0xef, 0xeb, 0xff, 0xff, 0xff, 0x40, 0xf2, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xfa, 0xff, 0x6f, 0x44, 0xff, 0xff, 0xff, + 0x7f, 0xf8, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f, 0xf7, 0xff, 0xef, 0x3d, + 0x7f, 0x7f, 0xea, 0xdf, 0x5f, 0xff, 0x55, 0xfd, 0xff, 0xff, 0xff, 0x4a, + 0xe2, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xd6, 0xff, 0xff, + 0x14, 0xfc, 0xff, 0xff, 0xff, 0xe9, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xde, 0xff, 0xff, 0x3f, 0xfc, 0x7f, 0xce, 0xff, 0x5f, 0xfe, 0x2f, 0xf0, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xfd, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0x4f, 0xfd, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xfb, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xfd, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xfd, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xff, 0x7f, + 0xfd, 0xff, 0xf5, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xaf, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0x7f, 0xfd, 0xff, 0xff, 0xfe, 0xff, 0xfa, 0xff, + 0xff, 0xff, 0xff, 0xfe, 0xff, 0xff, 0xfd, 0xff, 0xe9, 0xff, 0xff, 0xff, + 0x5f, 0xff, 0xff, 0xf7, 0xff, 0xff, 0xff, 0xff, 0xd7, 0xfe, 0xff, 0xff, + 0xff, 0xdb, 0xff, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xbf, 0xff, 0xff, 0x5f, + 0xff, 0xff, 0xef, 0xff, 0x7f, 0xff, 0xbf, 0xff, 0xff, 0xff, 0xfe, 0xbf, + 0xf7, 0xff, 0xff, 0xff, 0xff, 0xfa, 0xff, 0x5f, 0xfd, 0xff, 0xea, 0xff, + 0xff, 0xfd, 0xff, 0xff, 0xff, 0x77, 0xff, 0xff, 0x6d, 0xff, 0xbf, 0xfd, + 0x7f, 0xfb, 0xff, 0xff, 0xfa, 0xff, 0xfa, 0xff, 0xeb, 0xfa, 0x7f, 0xfd, + 0xff, 0xff, 0xf5, 0xff, 0xdd, 0xff, 0xdf, 0xff, 0xff, 0xf7, 0xff, 0xbf, + 0xff, 0xbf, 0xfd, 0xff, 0x05, 0xff, 0x5f, 0xeb, 0xff, 0xaf, 0xff, 0xff, + 0xf7, 0xfd, 0xf7, 0xf7, 0xff, 0xee, 0xff, 0xdf, 0xff, 0xbf, 0xf5, 0xff, + 0xf7, 0xff, 0xff, 0xf5, 0xff, 0x5f, 0xff, 0x7f, 0xf5, 0xff, 0x7d, 0xfd, + 0x7f, 0xfd, 0xff, 0x7f, 0xfd, 0xff, 0xd2, 0xff, 0x2f, 0xfa, 0x7f, 0xdf, + 0xff, 0xfb, 0xfe, 0xbf, 0xae, 0xff, 0xaf, 0xde, 0xff, 0xf9, 0xff, 0xbf, + 0xfe, 0x7f, 0xab, 0xff, 0x5e, 0xf5, 0x7f, 0xff, 0xff, 0x7f, 0xfd, 0xff, + 0x96, 0xff, 0xf7, 0xfb, 0xdf, 0xf5, 0xff, 0xab, 0xff, 0x5f, 0xff, 0xff, + 0xea, 0xff, 0xff, 0xf6, 0xff, 0xd6, 0xff, 0x3f, 0x11, 0x7c, 0x91, 0xf0, + 0x57, 0xd7, 0x7f, 0xd5, 0xfb, 0xb7, 0xed, 0xff, 0x75, 0xff, 0xdf, 0xe9, + 0xff, 0xab, 0xff, 0xdf, 0xf6, 0xfe, 0xed, 0xfe, 0xbf, 0xed, 0xff, 0xbf, + 0xff, 0x7f, 0xd5, 0xff, 0x9f, 0xfe, 0xdf, 0xde, 0xff, 0xaf, 0xff, 0x3f, + 0xa1, 0xfc, 0x27, 0xa2, 0x7f, 0xbd, 0xfe, 0xaf, 0xf6, 0xbf, 0x5d, 0xff, + 0xd7, 0xea, 0x7f, 0x5b, 0xff, 0x7f, 0xf5, 0xdf, 0xd6, 0xff, 0xad, 0xf5, + 0xff, 0xfa, 0xff, 0xd6, 0xfe, 0xef, 0xfe, 0xff, 0x6a, 0xff, 0x7f, 0xfb, + 0xff, 0xda, 0xfe, 0xff, 0xfc, 0x7e, 0xfc, 0xdb, 0x07, 0x01, 0x7f, 0x10, + 0xf1, 0x47, 0x02, 0x3f, 0x20, 0xf4, 0xdf, 0xed, 0xff, 0xcd, 0xff, 0x7f, + 0x5b, 0xff, 0xf7, 0xfe, 0x5f, 0xd1, 0xff, 0x15, 0xfd, 0xaf, 0xd0, 0xff, + 0x26, 0xfa, 0x5f, 0xa0, 0x7f, 0x83, 0xff, 0xbf, 0xd0, 0xfa, 0xe8, 0xf7, + 0x2f, 0x52, 0xfd, 0x22, 0xd2, 0x0f, 0x54, 0x7d, 0x45, 0xd1, 0x5f, 0x90, + 0xfe, 0x0b, 0xd4, 0x5f, 0xc2, 0xfe, 0x05, 0xe8, 0x2f, 0xf2, 0xff, 0x45, + 0xff, 0x3f, 0xe8, 0xff, 0x85, 0xff, 0x6f, 0xf9, 0xff, 0x4a, 0xff, 0xff, + 0xea, 0x3e, 0xfd, 0xea, 0xf7, 0x1f, 0xbf, 0xfb, 0xf9, 0xf7, 0x1f, 0xff, + 0xfd, 0xf5, 0x7f, 0x61, 0xff, 0x26, 0xfc, 0x6f, 0x54, 0xff, 0x96, 0xf6, + 0xff, 0xa2, 0xff, 0x1f, 0xfa, 0xff, 0xb3, 0xff, 0x1f, 0xfd, 0xff, 0xd1, + 0xff, 0x0f, 0xfd, 0x3f, 0x5a, 0x7f, 0xf5, 0xdf, 0x2f, 0x5d, 0x7f, 0xd7, + 0xf1, 0x3f, 0x5b, 0xff, 0xb3, 0xf1, 0xff, 0xeb, 0xff, 0x5f, 0xf7, 0xff, + 0xf1, 0xff, 0x5f, 0xfe, 0xff, 0xf4, 0xff, 0x57, 0xff, 0x7f, 0xd1, 0xff, + 0x57, 0xf7, 0x5f, 0xe9, 0xff, 0xd5, 0xff, 0xaf, 0xd5, 0x7d, 0xfc, 0xff, + 0xbf, 0xb7, 0xff, 0x75, 0xff, 0xd7, 0xb6, 0x7f, 0xdb, 0xfe, 0x6f, 0xf1, + 0xff, 0x9f, 0xfd, 0xff, 0xb5, 0xff, 0x97, 0xff, 0xdf, 0x4e, 0xff, 0xe7, + 0xf4, 0x7f, 0xce, 0xff, 0xd7, 0xfc, 0x7f, 0x4e, 0xff, 0x53, 0xfa, 0x3f, + 0x5b, 0x7f, 0xfd, 0xff, 0xb7, 0x6e, 0x7f, 0xef, 0xea, 0x7f, 0x6f, 0x7f, + 0xf7, 0xf6, 0xff, 0xd5, 0xff, 0x1f, 0xff, 0xff, 0xf1, 0xff, 0x1f, 0xfd, + 0x7f, 0xca, 0xff, 0xa6, 0xfc, 0x6f, 0xab, 0xfe, 0x66, 0xfa, 0x7f, 0xcd, + 0xff, 0x7b, 0xfe, 0x7f, 0x05, 0x7f, 0xfc, 0xff, 0xdf, 0xb5, 0xff, 0xb9, + 0xfe, 0xaf, 0xf5, 0xff, 0x55, 0xff, 0xff, 0xf1, 0xff, 0x5f, 0xff, 0xff, + 0xf5, 0xff, 0x5f, 0xff, 0x6f, 0xae, 0xfe, 0xed, 0xe9, 0x7f, 0xce, 0xff, + 0xe7, 0xea, 0x5f, 0x9d, 0xfe, 0xd2, 0xf4, 0xaf, 0x55, 0xfe, 0xec, 0xfd, + 0x3f, 0xe5, 0xff, 0xa3, 0xfc, 0x3f, 0xc6, 0xff, 0x65, 0xfa, 0xff, 0xf3, + 0xff, 0x5f, 0xfe, 0xff, 0xe1, 0xff, 0x1f, 0xff, 0x5f, 0xc5, 0xfe, 0xa5, + 0xfc, 0x4f, 0x4a, 0xfd, 0xaa, 0xec, 0x37, 0xca, 0xbf, 0x55, 0xde, 0x37, + 0xea, 0x5f, 0xfa, 0xf7, 0x2f, 0xeb, 0x7f, 0x5b, 0xf6, 0xb7, 0x75, 0x7f, + 0x5b, 0xfe, 0xff, 0xd9, 0xff, 0x1f, 0xff, 0xff, 0xf5, 0xff, 0x5f, 0xff, + 0x6f, 0x9c, 0xfe, 0x45, 0xd1, 0xbf, 0x4c, 0xff, 0x45, 0xe9, 0xef, 0x14, + 0xfd, 0xa2, 0xf8, 0x6f, 0x58, 0xff, 0xd4, 0xd6, 0x7f, 0x46, 0xff, 0x72, + 0xfe, 0x2f, 0xe5, 0xff, 0x63, 0xed, 0xff, 0xf1, 0xff, 0xbb, 0xfe, 0xff, + 0xd5, 0xff, 0x1f, 0xfe, 0x5f, 0xc3, 0x7f, 0xab, 0xee, 0x6f, 0xca, 0xfe, + 0xb6, 0xec, 0x5f, 0xca, 0x7e, 0x5b, 0xf6, 0x97, 0xea, 0x7d, 0xab, 0xf9, + 0x97, 0xf5, 0xfd, 0x53, 0xed, 0x3f, 0xab, 0xfd, 0x5a, 0xfe, 0xff, 0xf5, + 0xff, 0x0f, 0xff, 0xff, 0xf1, 0xff, 0x5f, 0xff, 0x8f, 0x3e, 0xfa, 0x68, + 0xc9, 0x4f, 0xbb, 0xfc, 0x50, 0xcb, 0x4f, 0xbb, 0x7e, 0xd4, 0xe5, 0xa7, + 0xb5, 0xff, 0x53, 0xd1, 0x7f, 0x57, 0xff, 0x76, 0xdb, 0x6f, 0x77, 0xff, + 0xf7, 0xd5, 0xff, 0xd1, 0xff, 0x5f, 0xfd, 0xbf, 0xf3, 0xff, 0x9f, 0xfe, + 0x4f, 0x15, 0xff, 0xda, 0xf2, 0x8b, 0x16, 0xff, 0xfa, 0xe2, 0x8b, 0x16, + 0x5e, 0xb5, 0xf8, 0xd7, 0xee, 0xfe, 0xaa, 0xf2, 0x57, 0xdf, 0xfe, 0xed, + 0xed, 0x5f, 0xad, 0xbd, 0x5a, 0xdb, 0xdf, 0x79, 0xff, 0x1f, 0xf7, 0xff, + 0xd4, 0xff, 0x5d, 0xfb, 0x8f, 0x3e, 0xfa, 0xb0, 0xa3, 0x9f, 0x36, 0xda, + 0xa0, 0xa5, 0x9f, 0x76, 0x7a, 0xf4, 0xd1, 0x87, 0x88, 0xfc, 0x4f, 0xff, + 0x0f, 0x14, 0x7d, 0x50, 0xd1, 0x27, 0x2b, 0x7d, 0xb0, 0xe2, 0x5f, 0xd1, + 0xfe, 0x2a, 0xfd, 0xbf, 0xb1, 0xfe, 0x15, 0xfd, 0xab, 0x55, 0xbe, 0xea, + 0xe2, 0x4b, 0x2f, 0x7e, 0x7a, 0xe9, 0x4b, 0x0f, 0xbd, 0xac, 0xf4, 0xea, + 0xa0, 0xfc, 0xdf, 0xfe, 0x53, 0x55, 0x5d, 0x55, 0xd5, 0x8b, 0x94, 0x7e, + 0x45, 0xd9, 0x7f, 0xd1, 0xff, 0x97, 0xea, 0x77, 0xd1, 0xff, 0x97, 0xea, + 0x0f, 0x2f, 0xfa, 0xd8, 0xc6, 0x17, 0xad, 0xfc, 0xe2, 0xc3, 0x0f, 0x3d, + 0xbe, 0xf4, 0xd1, 0x87, 0xaa, 0xfc, 0x9b, 0xff, 0x17, 0x15, 0x7f, 0x51, + 0xd1, 0x2f, 0x2d, 0x7d, 0x71, 0xd1, 0xdf, 0xa5, 0xfe, 0x1d, 0xed, 0x5f, + 0xa3, 0xfe, 0x15, 0xfd, 0xff, 0xfe, 0xff, 0xf7, 0xfd, 0xff, 0x7f, 0xff, + 0xbd, 0xfe, 0xff, 0xf7, 0xfd, 0x5b, 0xff, 0xfb, 0xfb, 0xff, 0xa7, 0xfe, + 0xef, 0xef, 0xfd, 0xee, 0xff, 0xf7, 0xdb, 0xff, 0xae, 0xff, 0xbf, 0xfe, + 0xff, 0xeb, 0xff, 0xff, 0xfe, 0xff, 0xff, 0xf6, 0xdb, 0xb6, 0xfe, 0xb6, + 0xed, 0xaf, 0xee, 0xbf, 0xf7, 0xdb, 0xdb, 0xbe, 0x7f, 0xff, 0xf5, 0x6f, + 0x57, 0xfd, 0x8f, 0xff, 0x7f, 0xbd, 0xff, 0xbb, 0xf6, 0x5f, 0x7b, 0xff, + 0xfb, 0xf6, 0xff, 0x55, 0xff, 0xbf, 0xfa, 0xdf, 0x55, 0xff, 0xd7, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xbf, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xef, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0x7f, 0xff, 0xff, 0xfa, 0xff, 0xdb, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xfb, 0xff, 0xff, 0xf7, 0xff, 0xdf, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x4f, + 0xf5, 0xbf, 0xfa, 0xff, 0xff, 0xfe, 0xff, 0xeb, 0xff, 0x5f, 0xf5, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xab, 0xff, 0xff, 0xd7, 0xff, + 0xbf, 0xfe, 0xff, 0xff, 0xff, 0xbf, 0xfa, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xbb, 0xff, 0x7f, 0xff, 0xff, 0x6f, 0xff, 0x7f, 0xfd, + 0xff, 0xeb, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xdd, 0xff, 0xef, + 0xff, 0xff, 0xee, 0xff, 0xab, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xff, + 0xff, 0xff, 0x5f, 0xff, 0xbf, 0xed, 0xff, 0x6b, 0xf5, 0xff, 0xfa, 0xff, + 0x7f, 0xfd, 0xff, 0xaa, 0xff, 0x2f, 0xf5, 0xff, 0xee, 0xff, 0xff, 0xff, + 0xff, 0x7b, 0xff, 0x5b, 0xff, 0xff, 0xed, 0xff, 0x6f, 0xfd, 0xff, 0xee, + 0xff, 0xff, 0xf5, 0xbf, 0xff, 0xff, 0xfb, 0xff, 0x57, 0x5b, 0x7f, 0x57, + 0xfe, 0x7f, 0xed, 0xff, 0xaf, 0xff, 0xbf, 0xf7, 0xff, 0x5b, 0xfe, 0x5f, + 0xbb, 0xff, 0xff, 0xff, 0xdf, 0x96, 0xff, 0xef, 0xff, 0xff, 0xf6, 0xff, + 0xdb, 0xf6, 0x5f, 0xb7, 0xff, 0xaf, 0xfe, 0x57, 0xfd, 0xff, 0x0f, 0xfe, + 0xbf, 0xea, 0xfe, 0x56, 0xf6, 0xff, 0xfb, 0xff, 0xdf, 0xfe, 0x7f, 0x6d, + 0x7f, 0xd7, 0xfe, 0x7f, 0xef, 0xff, 0xff, 0xff, 0xbf, 0x15, 0xfe, 0x5f, + 0xfd, 0xff, 0x5d, 0xff, 0xdb, 0xfe, 0xff, 0x6e, 0x7f, 0x5f, 0xff, 0x6f, + 0xfb, 0xff, 0xb7, 0xfc, 0x4b, 0x1b, 0xfb, 0xab, 0xfe, 0x7f, 0xed, 0xff, + 0xb7, 0xff, 0xbf, 0xeb, 0xff, 0x55, 0xfa, 0xbf, 0xb5, 0xff, 0xfd, 0xfb, + 0x37, 0x4b, 0x7f, 0xab, 0xf7, 0xb7, 0xea, 0xff, 0xbb, 0xdb, 0xb7, 0xbb, + 0xff, 0xbd, 0xfa, 0x97, 0xee, 0xff, 0xe5, 0xfa, 0x8f, 0x36, 0xfe, 0x7a, + 0xd5, 0xff, 0xb5, 0xff, 0xaf, 0xfa, 0x7f, 0xad, 0xff, 0x5f, 0xfb, 0x7f, + 0x6b, 0xff, 0xf7, 0xef, 0x2f, 0x4b, 0xfd, 0x76, 0xd5, 0xaf, 0x5f, 0xfd, + 0x72, 0xf5, 0x57, 0x6b, 0xfd, 0xeb, 0xa5, 0xbf, 0xfa, 0xff, 0xcf, 0xf4, + 0xaf, 0x5d, 0xbf, 0xd6, 0xfa, 0x57, 0xed, 0x7f, 0xab, 0xfe, 0xaf, 0xf5, + 0xfe, 0xaa, 0xfe, 0xdf, 0xfa, 0xff, 0xde, 0xf5, 0x37, 0x15, 0x7f, 0xfd, + 0xfe, 0xb7, 0xb6, 0x5f, 0x77, 0xdb, 0xaf, 0xaf, 0xbf, 0xaa, 0xf6, 0x17, + 0xd7, 0xff, 0x65, 0xfd, 0x5f, 0x7b, 0xfa, 0xd4, 0xd1, 0x3f, 0x15, 0xfe, + 0xd2, 0xe1, 0xbf, 0x16, 0xff, 0xeb, 0xe1, 0x5b, 0x0b, 0xfe, 0xb0, 0xe5, + 0xc7, 0xb7, 0x7d, 0xd1, 0xd1, 0xa7, 0x2f, 0x7e, 0xec, 0xf1, 0xa7, 0x1e, + 0xfd, 0xf2, 0xc2, 0x7f, 0xa4, 0xfe, 0xef, 0xf4, 0xd7, 0xae, 0x7d, 0x72, + 0xe9, 0x57, 0xaf, 0x7f, 0xbb, 0xfa, 0xab, 0xad, 0xbe, 0x5a, 0xf5, 0xaf, + 0x5d, 0xff, 0xfa, 0xf2, 0x57, 0x4d, 0x7f, 0x7e, 0xf1, 0x47, 0x9b, 0x7f, + 0x75, 0xd5, 0x57, 0x57, 0x7f, 0xd8, 0xf5, 0x2f, 0x52, 0xff, 0x5a, 0xfd, + 0x8f, 0xbc, 0x7d, 0xd2, 0xf3, 0x5f, 0x1a, 0xfd, 0x62, 0xd1, 0x5f, 0x1b, + 0x7f, 0x75, 0xd1, 0x6f, 0x15, 0xfd, 0x47, 0xed, 0xc7, 0xfa, 0x7c, 0xf4, + 0xe5, 0x57, 0x1f, 0x7d, 0xf4, 0xf1, 0x47, 0x1f, 0xfe, 0xdb, 0xd5, 0x7f, + 0x7f, 0xfd, 0x4b, 0xf4, 0x2b, 0x7b, 0xfb, 0xb6, 0xd8, 0xc3, 0x6f, 0x7f, + 0xfe, 0xfb, 0xa3, 0xef, 0x7e, 0xdd, 0xff, 0xd3, 0xff, 0xff, 0x65, 0xfc, + 0xd7, 0xad, 0xff, 0xfd, 0xf9, 0xef, 0x5f, 0xff, 0xff, 0xf5, 0xff, 0x5f, + 0xff, 0x76, 0xeb, 0xd7, 0xd5, 0xfe, 0x97, 0xfc, 0x0f, 0x76, 0x7d, 0xd5, + 0xf1, 0x97, 0x5f, 0x7d, 0xf4, 0xd5, 0xc7, 0x5e, 0x7d, 0xf8, 0xd2, 0x47, + 0x2f, 0xfd, 0xcf, 0xec, 0xc7, 0xba, 0xba, 0xea, 0xd1, 0xaf, 0x1e, 0x7f, + 0xea, 0xd1, 0x4b, 0x5d, 0xfd, 0xc7, 0xfc, 0x3f, 0xbf, 0xfd, 0x36, 0xe9, + 0xaf, 0xfb, 0xfd, 0x8e, 0xf5, 0xe7, 0xff, 0x7e, 0xfd, 0xeb, 0xd7, 0xbf, + 0x7e, 0xfd, 0xef, 0xd7, 0xff, 0xfe, 0x17, 0xff, 0xd7, 0x6d, 0x7d, 0xff, + 0xf5, 0xeb, 0x5f, 0x7f, 0xfd, 0xf5, 0xf7, 0x1f, 0xff, 0x75, 0xfd, 0xef, + 0x6d, 0xfd, 0xeb, 0xf2, 0x8f, 0x5e, 0xfb, 0xba, 0xe1, 0x47, 0xdf, 0x7a, + 0xdc, 0xdf, 0xc7, 0xff, 0x7a, 0xfc, 0xda, 0xc7, 0x5f, 0xfd, 0x5f, 0xfa, + 0x87, 0x5a, 0x7f, 0xf9, 0xf1, 0xaf, 0x1f, 0xfd, 0xf6, 0xf1, 0xaf, 0x5f, + 0xff, 0xc7, 0xf4, 0x3f, 0xbf, 0xfd, 0xdf, 0xe3, 0xbf, 0xf7, 0xbe, 0x56, + 0xf5, 0xd7, 0x5f, 0x7f, 0xf5, 0xd2, 0x57, 0xaf, 0x7d, 0xf5, 0xeb, 0x57, + 0xbf, 0xfd, 0xa2, 0xec, 0xd7, 0xdf, 0xfe, 0xee, 0xf5, 0xd7, 0x5e, 0x7f, + 0xfd, 0xd5, 0xd7, 0x1f, 0xff, 0x1f, 0xff, 0x57, 0x09, 0xff, 0xf2, 0xea, + 0xaf, 0xbe, 0xfa, 0xec, 0xd4, 0xc7, 0x7e, 0x7d, 0xfc, 0xf7, 0xc7, 0x5f, + 0x7f, 0xfc, 0xab, 0xc7, 0xb7, 0xfd, 0xe7, 0xfc, 0x47, 0x5a, 0x7d, 0xfd, + 0xd1, 0xdf, 0x1f, 0xff, 0xb5, 0xf1, 0x57, 0x5d, 0xfe, 0x37, 0xfd, 0x3f, + 0x5b, 0xfe, 0xd7, 0xe3, 0xdb, 0x7f, 0x7f, 0x5b, 0xf1, 0xd7, 0x5b, 0x5f, + 0xdd, 0xaa, 0x57, 0xbf, 0x7e, 0xb5, 0xdd, 0x57, 0x5f, 0xff, 0x55, 0xf5, + 0xd5, 0xbd, 0xfd, 0xda, 0xf5, 0x6b, 0x5d, 0x7f, 0xff, 0xf5, 0xef, 0x9f, + 0xff, 0x1f, 0xff, 0x2f, 0xaa, 0xff, 0xed, 0xeb, 0x1f, 0x55, 0x7c, 0x7a, + 0xf3, 0x2f, 0x57, 0x7e, 0xf5, 0xf5, 0xd7, 0x2a, 0xfd, 0xb6, 0xf1, 0xd7, + 0x5a, 0xfe, 0xea, 0xc5, 0x17, 0x17, 0xff, 0xb7, 0xf1, 0xaf, 0x1b, 0xfd, + 0xb2, 0xe5, 0x5f, 0x35, 0xfe, 0x5f, 0xfb, 0x6f, 0x6d, 0xff, 0xad, 0xe2, + 0xc7, 0x3e, 0x7f, 0x74, 0xf1, 0xf7, 0x1e, 0xff, 0x5a, 0xf1, 0x5f, 0x9f, + 0x7f, 0xfb, 0xf2, 0x5f, 0x8f, 0xff, 0xf8, 0xf2, 0x2f, 0x5d, 0x7f, 0xf5, + 0xfa, 0x5f, 0x57, 0x7f, 0xdb, 0xf8, 0xb7, 0x4f, 0xff, 0x1b, 0xff, 0x1f, + 0xfb, 0xff, 0x6b, 0xeb, 0x8f, 0x40, 0x7d, 0xe5, 0xd5, 0xaf, 0xe0, 0xff, + 0x4b, 0xfe, 0xff, 0x60, 0xff, 0x07, 0xfe, 0xff, 0xb0, 0xfe, 0xff, 0xff, + 0xef, 0xc0, 0xfe, 0x07, 0xea, 0x7f, 0xa4, 0xff, 0x93, 0xf6, 0x3f, 0x68, + 0xff, 0x27, 0xec, 0x25, 0xeb, 0xbf, 0xc8, 0xe0, 0x17, 0xe5, 0x7f, 0xb8, + 0xf2, 0xff, 0xd4, 0xfe, 0x17, 0xf5, 0xaf, 0xea, 0xff, 0xaa, 0xfa, 0xaf, + 0xea, 0xff, 0xf7, 0xef, 0xb7, 0xea, 0xff, 0x52, 0xfd, 0x1f, 0xe9, 0xff, + 0x43, 0xfa, 0xbf, 0xa4, 0xff, 0x46, 0xfc, 0x97, 0xfe, 0xff, 0x62, 0xf5, + 0x57, 0x44, 0x7f, 0xf1, 0xf2, 0xbf, 0xe1, 0xff, 0x4f, 0xfe, 0xbf, 0x40, + 0xff, 0x2f, 0xf6, 0xbf, 0xa0, 0xff, 0xff, 0xff, 0xaf, 0xa4, 0xff, 0x07, + 0xf5, 0x3f, 0x41, 0xff, 0x4b, 0xf6, 0x3f, 0x61, 0xff, 0x4f, 0xf9, 0x27, + 0xfd, 0xff, 0x6a, 0xe1, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xfd, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfb, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xd7, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xf7, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xdf, 0xfe, 0xff, 0xff, + 0xfe, 0xff, 0xfa, 0xff, 0xbf, 0xff, 0xff, 0xff, 0xff, 0x5f, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xff, 0xff, 0xfd, 0xff, 0xf7, 0xff, + 0xff, 0xff, 0xff, 0xfe, 0xff, 0xff, 0xfd, 0xff, 0xf5, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0x6f, 0xff, 0xff, 0xff, 0xff, 0xf7, 0xfe, 0xff, 0xff, + 0xff, 0xb7, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xbf, 0xff, 0xff, 0xff, + 0xfe, 0xff, 0xfd, 0xff, 0xff, 0xff, 0xbf, 0xff, 0xff, 0xbf, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xbf, 0xfa, 0xff, 0xff, 0xfe, 0xbf, 0xf5, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xfa, 0xff, 0xff, 0xfb, 0xff, 0xeb, 0xff, 0xff, 0xff, 0x7f, 0xfb, + 0xff, 0xff, 0xfa, 0xff, 0xf5, 0xff, 0xff, 0xff, 0xff, 0xfd, 0xff, 0xaf, + 0xff, 0x7f, 0xfb, 0xff, 0x06, 0xfd, 0xbf, 0xf7, 0xff, 0xd7, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0x7f, 0xf7, 0xff, 0x5f, 0xfd, 0x7f, 0xed, 0xff, + 0x75, 0xff, 0xff, 0xfe, 0xff, 0xbf, 0xff, 0x7f, 0xdb, 0xff, 0xfb, 0xfe, + 0xff, 0xf5, 0xff, 0xaf, 0xff, 0xbf, 0xea, 0xff, 0x57, 0xfa, 0x7f, 0xef, + 0xff, 0x5f, 0xfd, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf6, 0xff, 0xff, + 0xfd, 0xff, 0xab, 0xff, 0x77, 0xfd, 0xff, 0xf5, 0xff, 0x7f, 0xfd, 0xff, + 0xf6, 0xff, 0xd7, 0xff, 0xbf, 0xfb, 0xff, 0xfb, 0xfe, 0x7f, 0xff, 0xff, + 0xda, 0xff, 0xef, 0xfd, 0xff, 0xb7, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xdd, 0xff, 0x5f, 0xff, 0x7f, 0xfd, 0xff, 0xdf, 0xff, 0x7f, 0xfb, + 0xff, 0xd7, 0xff, 0x5f, 0xdb, 0xff, 0x7f, 0xfd, 0x7f, 0xd7, 0xff, 0xd7, + 0xff, 0xef, 0xd5, 0xff, 0x5b, 0xfd, 0x5f, 0xeb, 0xff, 0x6f, 0xff, 0x6f, + 0x6b, 0xff, 0xb7, 0xfd, 0xbf, 0xf5, 0xff, 0x77, 0xfb, 0xff, 0xab, 0x7e, + 0x7b, 0xf5, 0xff, 0xeb, 0xff, 0x5f, 0xfd, 0x7f, 0xfb, 0xff, 0xeb, 0xff, + 0xff, 0xfa, 0xff, 0xaf, 0xff, 0xbf, 0xee, 0xff, 0xb7, 0xff, 0xff, 0xfd, + 0xff, 0x5d, 0xff, 0xff, 0xbf, 0xff, 0xfe, 0xf7, 0xff, 0xdb, 0xff, 0x5d, + 0xff, 0x5f, 0xdd, 0xff, 0xeb, 0xff, 0x7f, 0xfd, 0xff, 0xbf, 0xff, 0xff, + 0xee, 0xff, 0x5f, 0xff, 0x5f, 0xa0, 0xff, 0x22, 0xfd, 0x2f, 0xe8, 0xff, + 0x06, 0xfa, 0x17, 0xd1, 0xff, 0x45, 0xfa, 0x07, 0x04, 0xfd, 0x03, 0xf0, + 0x5f, 0x90, 0xfe, 0x27, 0xe8, 0x7f, 0xa1, 0xfe, 0x0a, 0xf4, 0x6f, 0xf1, + 0xff, 0x07, 0xff, 0xbf, 0xe8, 0xff, 0x25, 0xfe, 0x6f, 0xf5, 0x5f, 0x85, + 0xfe, 0xb7, 0xba, 0xff, 0x2a, 0xfd, 0x5f, 0xf4, 0xff, 0x13, 0xfd, 0xa7, + 0x2b, 0xbf, 0x22, 0xf5, 0xb7, 0x62, 0x7f, 0x85, 0xf6, 0x57, 0xc4, 0x7f, + 0x23, 0xf7, 0x7f, 0xe8, 0xff, 0x56, 0xff, 0x7f, 0xf2, 0xff, 0x87, 0xff, + 0xbf, 0x8f, 0xfe, 0x7f, 0xf5, 0xef, 0xe6, 0xff, 0xfb, 0xea, 0xdf, 0x47, + 0xff, 0xfe, 0xec, 0xaf, 0xf8, 0x7c, 0xfc, 0xd1, 0x0f, 0x5f, 0xfc, 0xf8, + 0xc5, 0x8f, 0x3f, 0x7a, 0xfc, 0xd4, 0xff, 0xf3, 0xff, 0x1f, 0xfd, 0xff, + 0xe5, 0xff, 0x3f, 0xff, 0x6f, 0xd5, 0x7f, 0x6d, 0xfe, 0xdf, 0xa5, 0xff, + 0xd7, 0xfc, 0xbb, 0xf6, 0xff, 0xeb, 0xfa, 0xdf, 0xa8, 0x7c, 0xb5, 0xf2, + 0xaf, 0x95, 0xfe, 0xaa, 0xf2, 0xaf, 0x2a, 0x7e, 0x55, 0xf1, 0xff, 0xe9, + 0xff, 0x9f, 0xff, 0xff, 0xf2, 0xff, 0x1f, 0xff, 0xbf, 0x4f, 0xff, 0x6d, + 0xf6, 0x5f, 0x6f, 0xff, 0xbd, 0xf5, 0xef, 0xa6, 0xff, 0xae, 0xfa, 0xbb, + 0xf9, 0xfc, 0xfc, 0xff, 0x1f, 0x3f, 0xfd, 0xf8, 0xc3, 0x8f, 0xbe, 0x7e, + 0xf4, 0xf5, 0xff, 0xd3, 0xff, 0x3f, 0xff, 0xff, 0xf5, 0xff, 0x5f, 0xfe, + 0x6f, 0xe0, 0x7f, 0x23, 0xfe, 0x35, 0xe0, 0x7f, 0x03, 0xfc, 0x37, 0xe0, + 0xff, 0x45, 0xec, 0x17, 0x52, 0x3a, 0xfd, 0xfa, 0xc7, 0x2a, 0xfe, 0x92, + 0xea, 0xaf, 0x25, 0x7e, 0x55, 0xf1, 0x7f, 0xf9, 0xff, 0x17, 0xff, 0xff, + 0xf1, 0xff, 0x9f, 0xff, 0xaf, 0x84, 0xfe, 0x86, 0xf4, 0xaf, 0x44, 0xff, + 0x56, 0xe9, 0xaf, 0x4a, 0xff, 0x8d, 0xf8, 0x77, 0xd4, 0x7c, 0xd4, 0xd7, + 0x8f, 0xaa, 0xfc, 0xb2, 0xd2, 0x8f, 0x5a, 0x7a, 0xac, 0xe2, 0xff, 0xf1, + 0xff, 0x3f, 0xfd, 0xff, 0xd3, 0xff, 0x1f, 0xff, 0x8f, 0xff, 0x3f, 0xfc, + 0xfe, 0xc7, 0xff, 0xff, 0xb8, 0xfe, 0xd3, 0xf7, 0xbf, 0xf8, 0xef, 0xcd, + 0x58, 0xff, 0x59, 0xf9, 0xaf, 0xde, 0xbf, 0xa8, 0xfb, 0x4f, 0xb7, 0x5f, + 0xd9, 0xfd, 0xff, 0xf5, 0xff, 0x9f, 0xff, 0x7f, 0xf9, 0xff, 0x57, 0xff, + 0xaf, 0xaa, 0xfe, 0xb8, 0xf5, 0xd7, 0x52, 0xff, 0xf2, 0xea, 0x87, 0x56, + 0xff, 0xb2, 0xfa, 0xdb, 0x71, 0xfd, 0x63, 0xd1, 0x8f, 0x32, 0xfd, 0x69, + 0xab, 0x8f, 0xaa, 0x7e, 0x54, 0xeb, 0xff, 0xa1, 0xff, 0x1f, 0xfd, 0xff, + 0xd1, 0xff, 0x1f, 0xfe, 0x8f, 0xaf, 0x7f, 0x6d, 0xff, 0x47, 0xef, 0xff, + 0xdc, 0xfd, 0xd7, 0xeb, 0xff, 0xd8, 0xf6, 0x6d, 0xaa, 0xfd, 0x8e, 0xff, + 0x8f, 0xed, 0x7e, 0x5a, 0xf5, 0x4f, 0x77, 0x7b, 0xb5, 0xfd, 0xbf, 0xf5, + 0xff, 0x9b, 0xef, 0xff, 0xf9, 0xff, 0x5f, 0xff, 0x2f, 0xa9, 0x7e, 0x54, + 0xe8, 0x57, 0xa5, 0xfe, 0xa8, 0xd4, 0x97, 0x86, 0xfe, 0xb2, 0xd4, 0x8b, + 0xa4, 0xfc, 0x2f, 0xf5, 0x7f, 0x2a, 0xfe, 0x52, 0xe3, 0x5f, 0x0c, 0x7e, + 0x65, 0xd1, 0xff, 0xa2, 0xfe, 0x1b, 0xfa, 0x5f, 0x91, 0xfe, 0x15, 0xf4, + 0xcf, 0x4a, 0x7f, 0x2d, 0xf7, 0xc7, 0xa4, 0xff, 0xb4, 0xf4, 0x47, 0x75, + 0xff, 0xac, 0xf4, 0x55, 0x68, 0xfd, 0x4b, 0xff, 0x4f, 0xad, 0xfe, 0x65, + 0xe5, 0x3f, 0xa5, 0xfe, 0x52, 0xf1, 0xaf, 0x74, 0xff, 0x96, 0xed, 0xb7, + 0x69, 0xff, 0xae, 0xfb, 0x5f, 0x77, 0xfd, 0x75, 0xfd, 0xbf, 0x6f, 0xff, + 0xad, 0xed, 0xff, 0xd5, 0xff, 0xab, 0xed, 0xdf, 0x6f, 0xff, 0x5f, 0xfd, + 0xff, 0xdb, 0xfe, 0xdf, 0xfd, 0xff, 0xdf, 0xff, 0x7f, 0xff, 0xff, 0xd7, + 0xff, 0x77, 0xfb, 0x7f, 0xef, 0xfe, 0xb7, 0xf6, 0xff, 0xaa, 0x7f, 0xaf, + 0xfb, 0x6f, 0xb5, 0xff, 0x77, 0xfb, 0x57, 0x5f, 0xff, 0x7e, 0xf7, 0x6b, + 0xdb, 0xff, 0xaf, 0xff, 0xbf, 0xf6, 0xff, 0xb7, 0xee, 0x7f, 0x75, 0xff, + 0xab, 0xff, 0xaf, 0x6c, 0xff, 0xad, 0xee, 0xdf, 0xda, 0xff, 0xed, 0xfd, + 0xaf, 0x7f, 0xff, 0x7a, 0xeb, 0xef, 0x7e, 0xff, 0xae, 0xef, 0xdf, 0xfa, + 0xff, 0xd5, 0xfe, 0x6f, 0x77, 0xff, 0xab, 0xfe, 0xff, 0xad, 0xff, 0xef, + 0xfd, 0xff, 0xed, 0xff, 0xef, 0xfa, 0xff, 0xed, 0xfe, 0xef, 0xfd, 0xff, + 0xdb, 0xfe, 0x5f, 0xf7, 0xff, 0xfd, 0xff, 0xff, 0xff, 0xff, 0xef, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x8f, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xdf, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xdf, 0xff, 0xff, 0xff, 0xff, 0xfd, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xed, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xdf, + 0xff, 0xff, 0xff, 0xff, 0x6f, 0xbf, 0xff, 0xdf, 0xff, 0xff, 0xff, 0xff, + 0xbf, 0xff, 0x7f, 0xfb, 0xff, 0xef, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xef, 0xff, 0xff, 0xef, 0xff, 0xef, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0x0f, 0x4a, 0xff, 0x77, + 0xfd, 0x3f, 0xff, 0xff, 0x7f, 0xfc, 0xff, 0xe8, 0xff, 0xaf, 0xfb, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xef, 0xff, 0xff, 0xdd, 0xff, + 0xaf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf8, 0x87, 0xfe, 0xff, 0xff, 0xff, + 0xaf, 0xaa, 0xff, 0xaf, 0xff, 0xef, 0xfe, 0xff, 0x7f, 0xff, 0x7f, 0xfd, + 0xff, 0xdf, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xed, + 0xff, 0xff, 0xf7, 0xff, 0xdb, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xa5, + 0xff, 0xff, 0xff, 0xff, 0x2f, 0xaa, 0xfe, 0xbd, 0xfa, 0xbf, 0xfb, 0xff, + 0x6f, 0xfe, 0xff, 0xe8, 0xff, 0xb5, 0xf7, 0xff, 0xff, 0xff, 0xbf, 0xff, + 0xff, 0xff, 0xff, 0xaf, 0xfe, 0xff, 0xad, 0xff, 0xaf, 0xfe, 0xff, 0xff, + 0xff, 0xdf, 0xf4, 0x4f, 0xff, 0xff, 0xf7, 0xff, 0xeb, 0xd4, 0xff, 0x46, + 0xfd, 0xff, 0xfa, 0xff, 0xdf, 0xfd, 0x5f, 0xb7, 0xff, 0x57, 0xfe, 0xaf, + 0xaa, 0xff, 0x77, 0xff, 0xff, 0xff, 0xff, 0xbb, 0xff, 0x7f, 0xfb, 0x7f, + 0xdb, 0xff, 0xaf, 0xca, 0xff, 0xbf, 0xff, 0xb7, 0xfd, 0xff, 0x67, 0xfd, + 0xaf, 0x61, 0xff, 0x1d, 0xfd, 0xdf, 0xf6, 0xff, 0xaf, 0xff, 0xff, 0xee, + 0xff, 0x57, 0xfc, 0xbf, 0xf7, 0xff, 0x5f, 0xff, 0xff, 0x6d, 0xff, 0x6f, + 0xfb, 0xef, 0x6b, 0xff, 0x57, 0xfa, 0x7f, 0x4f, 0xff, 0x5b, 0xed, 0x7f, + 0xef, 0xff, 0xe7, 0xf5, 0xdf, 0xce, 0xbe, 0xf5, 0xf6, 0x7f, 0xed, 0xff, + 0x55, 0xff, 0xaf, 0xfa, 0xff, 0xad, 0xff, 0x7f, 0xed, 0xff, 0x2f, 0xff, + 0x7f, 0xdb, 0xba, 0xba, 0xed, 0x5b, 0xaf, 0x5f, 0xfd, 0xfd, 0xab, 0xbb, + 0xbf, 0xf6, 0xbb, 0x57, 0x75, 0xbf, 0xba, 0xeb, 0xaf, 0x9d, 0x7e, 0xdb, + 0xfe, 0xff, 0xba, 0xff, 0xbf, 0xfa, 0xff, 0xaa, 0xff, 0xb7, 0xfa, 0xef, + 0xaa, 0xff, 0x3f, 0xff, 0xff, 0x56, 0xff, 0xf5, 0xed, 0xdf, 0xbd, 0xfe, + 0x5a, 0xf5, 0x6f, 0xaf, 0xfe, 0x6d, 0xeb, 0x6f, 0xed, 0xff, 0x76, 0xdb, + 0xef, 0xc6, 0xff, 0x56, 0xfb, 0xaf, 0xf5, 0x7f, 0x53, 0xff, 0xaf, 0xf5, + 0x7f, 0x6b, 0xff, 0x5f, 0xfb, 0xff, 0x47, 0xff, 0x6f, 0xb5, 0x7e, 0xbb, + 0xfa, 0xb7, 0xd7, 0xbe, 0xfe, 0xf6, 0xaf, 0x7b, 0x7f, 0xf5, 0xb6, 0x5f, + 0x6b, 0x7f, 0xf5, 0xf6, 0x9f, 0x14, 0xfc, 0xd0, 0xea, 0x2f, 0xa6, 0xfe, + 0x66, 0xf2, 0x3f, 0x46, 0xff, 0x6a, 0xea, 0x5b, 0x26, 0xff, 0xdf, 0xfd, + 0x5f, 0x4e, 0xfd, 0xf2, 0xd5, 0x8f, 0xde, 0x7e, 0xd4, 0xf5, 0x2f, 0x57, + 0xfd, 0xd9, 0xe2, 0x3f, 0x15, 0xfd, 0xe9, 0xe2, 0x6f, 0x42, 0xbf, 0xaa, + 0xec, 0xb7, 0xa5, 0x7f, 0x59, 0xee, 0x53, 0xab, 0x7f, 0x51, 0xfa, 0x97, + 0x65, 0xff, 0xbe, 0xf7, 0x6f, 0xd5, 0xbe, 0xfc, 0xf6, 0xab, 0xaf, 0x7f, + 0x7d, 0xfd, 0xcb, 0xdf, 0x7e, 0xf7, 0xfd, 0x37, 0x7f, 0xff, 0xb6, 0xdd, + 0x6f, 0x08, 0xfc, 0xa1, 0xec, 0x2f, 0x4d, 0x7f, 0xd3, 0xf8, 0x57, 0xa6, + 0xfe, 0x73, 0xf5, 0x37, 0xcb, 0xfe, 0xb7, 0xfe, 0x5f, 0x8c, 0xfe, 0xe8, + 0xea, 0x0f, 0x3d, 0x7d, 0xf4, 0xe5, 0x0f, 0xbd, 0xfe, 0xaa, 0xeb, 0x3f, + 0x5b, 0xfd, 0xed, 0xf5, 0x8f, 0xbf, 0x7e, 0xff, 0xfb, 0xc5, 0x57, 0x7d, + 0x7c, 0xd5, 0xc7, 0x1f, 0x5f, 0xdc, 0xf1, 0xc7, 0x1d, 0xbf, 0x40, 0xe0, + 0x8b, 0xab, 0xfe, 0xfb, 0xeb, 0xff, 0xef, 0xde, 0xbb, 0xfa, 0xff, 0xd7, + 0xfe, 0x67, 0xfc, 0xef, 0xfe, 0xfe, 0xa7, 0xfc, 0xaf, 0x3e, 0xfe, 0x68, + 0xd3, 0x4f, 0x1f, 0x7f, 0xf9, 0xf1, 0x57, 0x3b, 0xfd, 0xbc, 0xe5, 0x97, + 0x5f, 0xfd, 0x14, 0xc5, 0xaf, 0x3b, 0xfc, 0x6a, 0xef, 0xaf, 0xae, 0x7e, + 0xfd, 0xf7, 0xaf, 0xbe, 0xfe, 0x1f, 0xfd, 0x2f, 0x15, 0xfd, 0x2f, 0xfd, + 0x8f, 0xbb, 0xfe, 0xfb, 0xed, 0xe7, 0x5f, 0x7f, 0xee, 0xf5, 0xc7, 0x4f, + 0x3f, 0xfd, 0xf9, 0xe7, 0x1d, 0xff, 0xff, 0xff, 0x8f, 0x56, 0x7f, 0xfb, + 0xe9, 0xd7, 0xbf, 0x7f, 0x7b, 0xf5, 0xd7, 0x6f, 0xff, 0x57, 0xff, 0x3f, + 0x9b, 0xff, 0x97, 0xff, 0xaf, 0x3f, 0xfc, 0xaa, 0xeb, 0x47, 0x1b, 0x7d, + 0xfc, 0xd1, 0x57, 0x1f, 0x7f, 0xf4, 0xd1, 0x8f, 0x5b, 0xff, 0xef, 0xfe, + 0x9f, 0x35, 0xfa, 0xd6, 0xdb, 0xbf, 0x76, 0xfd, 0xea, 0xed, 0xaf, 0x6e, + 0xfd, 0x1f, 0xfa, 0x6f, 0xa2, 0xfe, 0x1f, 0xfd, 0x8f, 0xad, 0xfe, 0xfe, + 0xf6, 0xd7, 0x5f, 0x7f, 0xad, 0xf5, 0xe7, 0x5d, 0x7f, 0xdd, 0xf5, 0xe5, + 0x1f, 0xff, 0xbb, 0xff, 0xa7, 0xba, 0xfe, 0x7d, 0xf7, 0xcf, 0x5f, 0x7f, + 0xbf, 0xfa, 0xdf, 0xdf, 0xfe, 0x5b, 0xff, 0x3f, 0x64, 0xff, 0x57, 0xff, + 0x2f, 0x3f, 0xfd, 0xe9, 0xad, 0x97, 0x16, 0x7f, 0xf8, 0xf1, 0x47, 0x2f, + 0x7e, 0x74, 0xf1, 0x8f, 0x56, 0xfd, 0x1f, 0xff, 0x0f, 0x2e, 0xfe, 0x69, + 0xd5, 0x5f, 0x5a, 0xfd, 0xf4, 0xeb, 0x5f, 0xba, 0xfe, 0x57, 0xff, 0xd7, + 0xff, 0xff, 0x5f, 0xff, 0xcf, 0xaa, 0xbe, 0xb6, 0xf3, 0xc7, 0x5b, 0x7f, + 0x55, 0xf5, 0xd7, 0x9a, 0x7f, 0xd5, 0xf2, 0xd3, 0x2f, 0xff, 0x97, 0xfe, + 0xaf, 0x5a, 0xff, 0xf6, 0xea, 0xaf, 0xb7, 0x7e, 0x5b, 0xf5, 0xaf, 0xaf, + 0xfd, 0xdf, 0xff, 0xbf, 0xf6, 0xff, 0x55, 0xff, 0x5f, 0xc0, 0xfe, 0xe0, + 0xa4, 0x3f, 0xc2, 0xfe, 0x13, 0xed, 0x9f, 0xa0, 0xff, 0x15, 0xfe, 0x37, + 0xe0, 0xff, 0xbf, 0xff, 0x5f, 0x41, 0xfd, 0x07, 0xa2, 0x7f, 0x04, 0xfa, + 0x13, 0xd0, 0x7f, 0x00, 0xfa, 0x02, 0xfe, 0x2b, 0xfd, 0xff, 0x47, 0xfe, + 0x7f, 0x55, 0xbf, 0xaa, 0xe0, 0x97, 0xe8, 0x7f, 0x4b, 0xfe, 0x37, 0x75, + 0x7f, 0x43, 0xf5, 0x9f, 0xa4, 0xff, 0xff, 0xff, 0x37, 0xd4, 0xff, 0x55, + 0xe9, 0x7f, 0x50, 0xfe, 0x42, 0xf5, 0x7f, 0x2a, 0xff, 0xad, 0xff, 0x97, + 0xfa, 0x7f, 0x95, 0xff, 0x6f, 0xc2, 0xff, 0xe0, 0xa5, 0x3f, 0xa9, 0xff, + 0x4b, 0xfa, 0x7f, 0xe0, 0xff, 0x2b, 0xfe, 0x3f, 0x64, 0xff, 0x5f, 0xff, + 0x6f, 0x42, 0xff, 0x07, 0xa2, 0x7f, 0x45, 0xfa, 0x97, 0xd0, 0xff, 0x20, + 0xfa, 0x05, 0xff, 0x3f, 0xfb, 0xff, 0x15, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xfd, 0xff, 0xdf, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xaf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xfe, 0xd7, 0xfe, 0xff, 0xf6, 0xff, + 0xff, 0xbf, 0xff, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xbf, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xd5, 0xff, 0xbf, + 0xfb, 0xff, 0x56, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xf7, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xef, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf7, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xbf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xdf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xef, 0xb5, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xbf, 0xe2, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xaf, 0xff, 0xbf, 0xaa, 0xff, 0xfb, + 0xff, 0xa7, 0x9e, 0xff, 0xff, 0xff, 0xff, 0xfb, 0xff, 0xff, 0xff, 0xff, + 0xbf, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xef, 0xab, 0xff, 0xee, 0xff, + 0xff, 0xf7, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f, 0xff, 0xff, 0xdf, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0x97, 0x25, 0xfe, 0xff, 0xff, 0x7f, 0x7f, + 0xff, 0xff, 0xff, 0xff, 0xef, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfa, + 0xe2, 0x5f, 0xef, 0xff, 0x6f, 0xfb, 0xff, 0xff, 0xff, 0xdf, 0xfe, 0xef, + 0xff, 0xff, 0xd7, 0xff, 0x5f, 0xd5, 0xff, 0xed, 0xff, 0xc3, 0x96, 0xff, + 0xbf, 0xff, 0xd7, 0xdb, 0xff, 0xff, 0xff, 0xff, 0x7f, 0xff, 0xff, 0xff, + 0xff, 0xdf, 0x7f, 0x47, 0xab, 0x9f, 0xb7, 0xff, 0xfd, 0xed, 0x6f, 0xdb, + 0xff, 0x8f, 0xff, 0x0b, 0xfe, 0xff, 0x4f, 0xfb, 0x7f, 0xf6, 0xff, 0xb3, + 0xff, 0x57, 0x2b, 0xff, 0xff, 0xfa, 0x23, 0x24, 0xfa, 0x7f, 0xff, 0xff, + 0x0b, 0xfa, 0xbf, 0xff, 0xaf, 0xd7, 0xbf, 0xe5, 0xe1, 0xd7, 0xaa, 0x7f, + 0xaf, 0xf6, 0xf7, 0xff, 0xfe, 0xcb, 0xfe, 0x2f, 0xff, 0xff, 0xd6, 0xff, + 0x1f, 0xab, 0x7f, 0xf3, 0xff, 0x53, 0x9b, 0xff, 0xbf, 0xfe, 0x2b, 0x81, + 0xfe, 0xd7, 0xff, 0xff, 0x4f, 0xff, 0xd7, 0xff, 0xaf, 0xce, 0xbf, 0xb8, + 0xfc, 0x9f, 0xf7, 0xbf, 0x90, 0xa0, 0x0d, 0x00, 0xff, 0xbf, 0xdb, 0xdb, + 0xfa, 0x7f, 0x0b, 0xd5, 0x7f, 0xf7, 0xff, 0xd5, 0xdb, 0x8f, 0x60, 0xfd, + 0xbf, 0xff, 0xff, 0x7e, 0xff, 0x2d, 0xf4, 0xf7, 0x97, 0xff, 0x9f, 0xff, + 0x87, 0xef, 0xbf, 0xd4, 0x7c, 0x9b, 0x55, 0x3f, 0x44, 0xb2, 0x27, 0x22, + 0xfd, 0xd6, 0xfe, 0x6f, 0xff, 0xbf, 0xcd, 0xfa, 0x37, 0xdb, 0xff, 0xf5, + 0xfd, 0xc5, 0xaa, 0xff, 0xbf, 0xfd, 0xdf, 0xeb, 0xff, 0x17, 0xff, 0xfd, + 0x95, 0xff, 0xd7, 0xff, 0xaf, 0xcb, 0x7e, 0x79, 0xed, 0xaf, 0xb6, 0x3d, + 0x11, 0xc9, 0x8f, 0x14, 0xbf, 0xbf, 0xd6, 0x5f, 0xfd, 0x7f, 0x15, 0xed, + 0x3f, 0x75, 0x7d, 0x63, 0xd7, 0xa7, 0xa0, 0xfe, 0xff, 0xfe, 0xff, 0xb2, + 0xff, 0x55, 0xf4, 0xf7, 0xaf, 0xfe, 0x9f, 0xfe, 0xb3, 0xcd, 0xbf, 0xdc, + 0xf4, 0x03, 0x91, 0xfe, 0xd7, 0xfc, 0xc7, 0x9f, 0x7f, 0x00, 0xe1, 0x8b, + 0xf6, 0x5f, 0x8b, 0xf1, 0x15, 0x53, 0x7f, 0x29, 0xd0, 0x53, 0x1f, 0xf6, + 0xaf, 0xfe, 0x6f, 0xfb, 0x7d, 0xad, 0xf5, 0xf3, 0xd5, 0xff, 0xe3, 0xff, + 0xd3, 0xd6, 0xff, 0xf2, 0xec, 0x55, 0x0a, 0xfe, 0x67, 0xfd, 0xd7, 0x2d, + 0xbd, 0x8a, 0xc8, 0x2f, 0xfa, 0xbf, 0x4d, 0xd5, 0xaf, 0x52, 0x7b, 0x0b, + 0xc5, 0x8d, 0x95, 0xfc, 0x7f, 0xfb, 0xff, 0x6d, 0xf7, 0x5b, 0xb3, 0xa7, + 0xaf, 0xff, 0xaf, 0xff, 0xbf, 0xf2, 0xbf, 0x7d, 0xe2, 0x9f, 0xeb, 0xff, + 0xbb, 0xff, 0xc3, 0x9e, 0xff, 0xa5, 0xef, 0x6f, 0xfb, 0xbf, 0xcd, 0xf1, + 0x35, 0xab, 0xbd, 0xed, 0xfe, 0x57, 0xed, 0xff, 0xbf, 0xff, 0x55, 0xb1, + 0x7d, 0xea, 0xcd, 0xeb, 0xf1, 0xff, 0xe3, 0xff, 0x6f, 0xd5, 0xff, 0xfa, + 0xe8, 0x97, 0xbb, 0xff, 0x57, 0xfd, 0xaf, 0x5f, 0xfe, 0x9e, 0xda, 0xbb, + 0xf5, 0xff, 0x96, 0xd5, 0xaf, 0xd2, 0xfe, 0x7a, 0xfa, 0x2d, 0x55, 0xfd, + 0x7f, 0xfd, 0xdb, 0x54, 0x7b, 0x5e, 0xcb, 0xa7, 0xab, 0xff, 0xd7, 0xff, + 0x7f, 0xf1, 0xbf, 0xbe, 0xea, 0x9f, 0xad, 0xff, 0x5f, 0xff, 0xc7, 0x1f, + 0x7f, 0x87, 0xeb, 0xaf, 0xfa, 0x5f, 0xcb, 0xf0, 0x35, 0xb3, 0xb6, 0x2e, + 0xff, 0xb7, 0xde, 0xfe, 0xbf, 0xff, 0x6f, 0xd1, 0x7d, 0xe6, 0xeb, 0xf7, + 0xf3, 0xff, 0xe7, 0xff, 0x7f, 0xe9, 0xff, 0xfb, 0xa9, 0xab, 0xd6, 0xff, + 0xd7, 0xff, 0xa7, 0x57, 0xff, 0xfb, 0xda, 0x6b, 0xfe, 0xbf, 0x9a, 0xd5, + 0x3f, 0xed, 0xff, 0x7b, 0xfd, 0x2f, 0x20, 0xff, 0x3f, 0xfc, 0xff, 0xff, + 0x7f, 0xeb, 0xce, 0x7f, 0xd5, 0xff, 0xf5, 0xfa, 0xbf, 0xf9, 0x3f, 0x5d, + 0xfc, 0x9f, 0xfb, 0xff, 0xdb, 0xff, 0xe5, 0x1f, 0xff, 0xab, 0xdb, 0x5b, + 0xfe, 0xdf, 0x86, 0xf4, 0x2f, 0xb7, 0xbf, 0xae, 0xff, 0x97, 0x12, 0xff, + 0x9f, 0xfe, 0xbf, 0xf2, 0xbe, 0x65, 0xcb, 0xdf, 0xf5, 0xff, 0xb7, 0xfe, + 0x7f, 0x42, 0xff, 0xf7, 0xef, 0xaf, 0xab, 0xff, 0x6f, 0xff, 0x97, 0x5e, + 0xff, 0x5f, 0xf1, 0x8f, 0xf7, 0xff, 0xad, 0xd5, 0x7f, 0xeb, 0xff, 0x8f, + 0xfe, 0xef, 0xdf, 0xff, 0x7f, 0xfe, 0xff, 0xdd, 0xbf, 0xfe, 0xed, 0x7f, + 0xfa, 0xff, 0xed, 0xe1, 0x5f, 0xf8, 0x3f, 0xb5, 0xfa, 0x97, 0xad, 0xff, + 0xf5, 0xff, 0xc7, 0x97, 0xff, 0xd2, 0xf9, 0xa3, 0xfa, 0xbf, 0x8e, 0xfd, + 0x17, 0xfb, 0xff, 0xab, 0xff, 0x57, 0x55, 0xff, 0x2f, 0xff, 0xff, 0xf5, + 0xbf, 0xea, 0xed, 0x6f, 0xfc, 0x7f, 0x6d, 0xf5, 0x7f, 0xc5, 0xfe, 0xdd, + 0xfe, 0xbf, 0xf6, 0xff, 0xaf, 0xff, 0xad, 0x3d, 0xfd, 0xaf, 0xd2, 0x9f, + 0xfe, 0xfe, 0xad, 0xeb, 0x7f, 0xab, 0xff, 0x8f, 0xff, 0xef, 0x6f, 0xff, + 0x3f, 0xfe, 0x7f, 0xf7, 0xff, 0x6d, 0xd7, 0x7f, 0xfd, 0xff, 0xf7, 0xf1, + 0x8f, 0x2f, 0xbe, 0x68, 0xff, 0x97, 0xab, 0xff, 0xea, 0xff, 0xc7, 0x16, + 0xbf, 0x6a, 0xfa, 0xab, 0x82, 0xfe, 0x8f, 0xff, 0x43, 0xfb, 0xff, 0xfb, + 0xff, 0x7f, 0xa5, 0xff, 0xef, 0xff, 0xdf, 0xf9, 0x3f, 0xf4, 0xf0, 0x5f, + 0xfd, 0xbf, 0x28, 0xd8, 0x97, 0x8a, 0xfa, 0x5a, 0xff, 0x1f, 0xf5, 0xff, + 0xf6, 0xff, 0x57, 0x55, 0xff, 0x75, 0xfa, 0xaf, 0x51, 0xfb, 0xaf, 0xfe, + 0xcf, 0xd7, 0xff, 0xd6, 0xff, 0xff, 0x65, 0xff, 0x37, 0xfd, 0xff, 0xf6, + 0x7f, 0xb9, 0xf5, 0xb7, 0xff, 0x7f, 0xb3, 0xd2, 0xf3, 0xff, 0xfe, 0xd7, + 0xff, 0xdf, 0xad, 0xbf, 0xfe, 0xff, 0xd7, 0x5f, 0x5f, 0x7d, 0xff, 0xfb, + 0xdd, 0xfb, 0xa7, 0xff, 0xf5, 0xfa, 0xff, 0xfb, 0xff, 0xbf, 0xe6, 0xff, + 0xd5, 0xff, 0x7f, 0xfa, 0xff, 0x1f, 0xff, 0xd3, 0xff, 0x3f, 0xdd, 0xcd, + 0xd7, 0x7f, 0xff, 0xf6, 0xff, 0x1f, 0xf5, 0xff, 0xf5, 0xff, 0xdf, 0xfe, + 0xdf, 0xfe, 0xff, 0xaf, 0xbf, 0xfe, 0x9f, 0xff, 0xdb, 0xef, 0xff, 0xfe, + 0xff, 0xff, 0xea, 0xff, 0xcf, 0xff, 0x7f, 0xf7, 0xff, 0x9b, 0xfe, 0x67, + 0xff, 0x7f, 0x6a, 0xd7, 0xf3, 0xbf, 0xfb, 0xb7, 0xff, 0x97, 0xb7, 0x7f, + 0xfd, 0xff, 0xe7, 0x5f, 0xff, 0x7e, 0xfb, 0xfb, 0xab, 0xff, 0x8f, 0xff, + 0xfd, 0xf7, 0x7f, 0xf7, 0xff, 0xff, 0xe3, 0xff, 0xe5, 0xff, 0xbf, 0xf5, + 0xff, 0x5f, 0xff, 0xeb, 0xff, 0xbf, 0xb6, 0xcb, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xfd, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xbf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xef, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xfb, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfb, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }; diff --git a/hacks/images/matrix1.xpm b/hacks/images/matrix1.xpm new file mode 100644 index 00000000..82038fce --- /dev/null +++ b/hacks/images/matrix1.xpm @@ -0,0 +1,392 @@ +/* XPM */ +static char * matrix1_xpm[] = { +"320 377 12 1", +" c None", +". c #000000", +"+ c #030E03", +"@ c #081E08", +"# c #0B2A0B", +"$ c #165016", +"% c #1B641B", +"& c #217A21", +"* c #5AD25A", +"= c #279027", +"- c #81DD81", +"; c #2BA02B", +"..........................+.++++++............+.+.+.+.+..........++++@@@@@++++........++@@@@@++..........+.++++.....................................+.++..............+++@@@@@+++........++@@@@@++.............++++++..................................................................................................++@@@+++.", +"..........................++++@@++++.........++++++++++.+........++@@#@###@@++.......++@@###@@+++........++++++++..................................++++++++...........++@##$##@++.....+.++@#####@+++...........+++@++++..............................................................................................++@@@#@@++.", +"........................+.+@@###@@++......++++@@@@@@@@@+++.....+.@@#$%%%%%$##++....+.+@##&&%##@+++.....+++@@@@@+++..............+.+................++@@@@+++..........+@##**%$$@++......+@$$%**##@++.........+++@@#@@+++..............................................................................................+@#%&%#@+.", +".........................+@###$$#@@++......++@@#@#@#@#@@+++.....++#$%%%&&&$$#@+....++@##$&==$$#@+++...+++@#####@@+...........+.+++++++.+........+.+@@####@++........++@@#$**%%$@++.....++@$%&**$#@@+........+.@@##$##@@+............++++.+..........................................................................++@#$&&&$@@.", +".......................++@@$%**-%$@@+....+++@#$&&$$$&&$#@++....++@#&&=;=;;&%$@+..+.+@@$&=***&%$##++...++@#%&=&&#@@+..........+++@@@@@@++........+.+@#&&&$$@++.......++@#$%**%%$@+......++@$%%**%$#@++.....+.++@#$***$#@+++........++++@@++..........................................................................++@$$***$#@.", +"........................+@#%&-**%%#@++....+@#$%&=%%%=&%$#@+....+@@#&=;=;;;&%%#@...+@##$==*--=&%$#@+.+++@##&===&$@@++........++@@#####@@++........+@#$&==%$@++......++@#%&&;=%#@@++......++@$$;;&&%#@++....++@@#$$***%##@@++.......++@#@@@+++........................................................................+@#$%***$#@.", +"........................+@#%%*-*&%#@++..+++@$$%==%%%==%$#@@..+.+@#$===;;;;=%%#@.++@@#$%==-**==%$#@+..+@@#$===;=$#@++......+++@##$$$$$#@@++.....+++@#$===%$#@++......@@#%&=;=$#@+.+......+@@#$=;&&%#@++....+@@##$%***%$$#@@+......++@##$##@++........................................................................+@#$%***$#@.", +"........................@@#&=---=&#@++...+@@%%&*-=&&--&%%@+...+@@#$==;=;;;&&%#@..+@#&==;;;;;-*&%$@@.++@$%%====&&%#@++....+.+@#$==-*-=&#@+.......+@#%&*-*%%@++.......@@$=====$#@++........+@#$&=;==$@@++.+++@%%&%&*-*&%&%$@+....+.+@@$***$@@+.......................................................................+@@#&===&$@+.", +".......................++@$==*-*==$@++...+@@%%&-*&&&*-&%$@@..++@#$$==;=;;;=&%$@.+@#$&=;;;;;;-*&%$@@.++@$%&=====&%#@++....++@@#$=;--*;=#@@+......+@#%%*-*&%@@+.....++@#$==;=&$@@+.........+@@$&==;=$#@....+@@%%&&&***&%&&%#@......+@#$***$#@++......................................................................+@#$==;==##+.", +"........................@##&&-*-=&##++...+@#%&&**&&&-*%%$@+..+@@%%=;;*****;;=$#.+@@$;;;&=%%%==%%$@+.+@@$%&======&$@@++....+@$%&;;%%%=&$@++.....+@@#=;==&$#@++.......@#$=;==&#@+...........@@#&====$#@++.++@#%&=**---**&&%#@.....+@@#%***$$@++...........................+.+.++.++.+.+.............................++@#$**%%$#@+.", +".......................++@$&=-*-&&$@@....++@%%&**&&&*-%$$@+..+@#%&=;;*-***;;;$#.+@#$;;;=&&%&&=%%$@+.++@$%&=======$#@++...++@$%&;;&%%&&#@@+......@@$==&&%$@@+......++@#$***%$#@++..........+@#$%***$#@++..+@@%&&****-**=&%@@...+++@#$%*-*%$#@+++........................+++++++++++++++............................+@#$$**&%$@@+.", +"........................@@#&&--*=&$@++..++@@%%&**&%&**%$#@+..+@#%&=;;**-**;;=$#.+@@$;;;&=%&%=&%$$@@.+@@$%%=======$#@@++..++#$%&;;%%%&%#@+++....++@#&=&%%#@+.+......+@#%***%$@@+..........+.@#$$-**%#@+...+@@%%=***-***&&%@@..+++@@#$%***%$##@@+......................+++@@#@@#@#@#@@@++.........................+++@#$%**%$#@+..", +".......................++@$&=*--=&##++...+@@$%%&%%%%&&$#@++..+@#%&=--;;;-*;;=$#.+@@$==;**;=;&&%$#@+..+@@$$===;==&&%$@++..++@$%&**%%%$$#@@++....++@#$%###@@+.......++@#%***$$@++............+@$$***$$@++..++@#$%&&-*-&&%$#@+..+@@#$$%%*-*%%$##@@......................+@@###$$#$#$#$##@@.........................++@#%&&;=$$@@+..", +"........................@@#&=*-*=&#@+.....+@$$$%%#$$&%#@@+..+.@#%&=**;;;*-=;=$@.++@#&==**=;=&&%$##@..++@#$===;===&%$@++.+.@@$%%**%%%$$$#@@+.....++@$$#@@++.........@@#$*-*%$@@............++##%*-*%#@+....@@#$%&&*-*&&%$#@+.+@@#$$%%%*-*%%%%$#@.....................+@@#$$$%$%$%$%$$$#@.........................++##&&&;=$#@+...", +"........................+@#$%***%$#@++....++@@@#@#@@#@@@++..++@#$%%**&=&**%%$#@.++@#$$%==;;;**==%#@..+@@#$==;;;==%$#@++.+++@$%%-*;;;%%%%%@@......+++@@+++..........+##%***$#@@............++@$$***%##++...+@#$%*-&&&**%%$@+.+@#$--*---*--*-*-$#.....................+@#$--*-*--*-*--*$#.........................+@#$;;;&&#@@++..", +"........................+@##%*-*%$#@+......++@@@@@@@@@++.....+@#$%&**&&&-*%%$#@..+@@#$%&&;;;**==&#@.+.@@#$=;;*;==%$#@++..+@#$%&--;;;&%&&%@@.....+.+++++..+........++##$***%##++...........+@@#%***%#@+...++@#$%**&&&-*%$$@+.+@$$*--*-*--*---*%#.........++++++......+@$$*--*--*---*--%#..........+.+.+.........+@#$&;;;$$@+++...", +".........................+@$$***$#@++........+..+.+.+++..+..+@@#$%%*-&&&**%%$#@..+@@#$%&&;;;**===$#.+.@@#$==;;;;=%$$#@...+@#$%&**;*;&&=&%#@...........+...........++@$$*-*%##@+...........+@#$%***%#@@....+@#$%**&&%**%%#@+.+@#$-*---*-*-**--$#.......+++@@@@+++....+@#$-*--*--**--*-$#.........++++++.......+.@@#%&;;;$#@+.....", +"........................+@@#$***%#@+...........+.+.+........+@#$*---*-*---;;=#@.++@#%&=%&%&%==;;;$#..+@$%&&&*;;;;==&#@+.++@#&&=;;***-*===#@........+..............++@#$***%$@@++.........+.@##%-**$#@++..++@#$$&&$$%&&$$#@+.+@@#$%$%%**-%%%$$#@.......++@@#@@@+++....@@#$$$$%$$%%$%$$#@.......++++@@@+++......+@#$=;=&&$#@++....", +".........................+@#$***$#@++.......................+@#%-*-*--*-*-;;=#@.++@#&&&&&%&%&=;;;##.+++$$%&&;;;;;==&##+.+@#$&====***--;==##.......................++@#$=;;&&#@++.........++@#&&;;=%#@++...++#$$%%###%%##@++..+@@##$%%-**%%$$##@.....+++@#%&&$#@+.....+@@##$#$$#$#####@@.......++@@#@@@++......+@#$=;&&&#@++.....", +".........................++##$%$#@@+........................+@##&&=;;;;;==%$##@.+@#$=;;**=;;**;==$@..++@#$$%;;;&&==&$@+.++#$;;;=====**&%%#@........................+@#$==;=&##++..........@@#&&;;=$#@+.....+@@@@@##@#@@@@+...++@@##$%*-*%$##@++......+@##&&&%$@@.+...++@@@@@@#@@###@@@+......++@$$&&%#@++...++@@#$=;&&%#@+......", +".........................++@#$$$#@@..........................+@#&&&;;;=;==%$#@+.+@##;;;*-=;;**==&#@..+++@##$==;%&===##+.+@#$;;;=&&&=*-&%%$@.......................+++#$&=&==$#@++.......++@#$=;&=%$@++......++@@@+++@@+++......++@#$$***%$#@++......+@@#$===%$@@+......++@+@+@+@+++++.+......+@@$%&&&#@@+...++@$$&**$$#@+++.....", +"..........................@@#$$$#@++........................+@@#%&&*;=;;==$#@++..+@#&&===*-*==%$#@@....+@@$$=;=%&==&$@+.+@@$;;;&=&=&-*&&%$@.........................+@#%&=;;$#@++.....+.++@#$=;=&%#@++.....+.+.++++.+++.........+@@$$-**$#@++.......+@#%%***&%@@+.........+.+.+...++.........+@#$%==&$#++...+@#$%%**$$@@+.......", +".........................++##***##++.........................+@#%&&;;;;;&&$#@++.++@#%%&&=*--=&$##@+.....+@##;;;;;==&##+.+@@$&;=-*--*;;*-*$#........................++@#%&&;=%$#+++......+@#$%=;&&%#@++............+...+..+.......+@#$***$#@++......++@#%&--*%%@+++...........................+@#&&**-##@++..+@@&&===$#@++.......", +"..........................+@#***#@++........................++@#$&&;;;;;&&$@@+....+@@@@#$***%#@++.+.....++@#==;====&#@+..+@#&==--*--;=*--$#..........................+@#$%**%%$@+......++@#%&**%$#@+.............................+@@$***$#@+.......++@#===&&$#@++..........................+..@@%&-**$@++...+@#&====$#@+........", +".........................++@##$#@@++.........................+@#$&&;;;=;=&#@++..+++.+@@#$===$#@++.......++@##$$$$###@++.++@@#$$$$%$$$%$$##@.........................++@@#$**%%$@++.....++@$%%**$$@@++............................++@##$##@++.+.....++##===&&##@+.............................++@#$$$##@++...+@#&===&#@++........", +"..........................++@@@@@++.........................+.@@$%&;;;==&&#@+......+.+@##=&&$#@+.........++@@#@###@@+++...+@@@#####$#####@@...........................+@#$**%$$@+.......+@$$%**$#@++..............................+@@@#@@++........++@#==&%%#@++..............................+@@@###@@+....@@#%&&%$#@+.........", +"...........................++@@@++............................+@$$%=;===&%#@++........+@#&&%#@+++.........+++@@@+@+@+......+@@@@#@@@#@@@@++..........................+++@##$##@+++......++@#####@++................................++@@+@+..........@@#$%$##@++................................++@@@+++.....+@#$%%$#@@++........", +"............................+.+.+............................++@@###$$$###@++........+++@##@@@..............++.++++..........+++++@++@++++.............................+@@@@@@+++........++@@#@@++..................................+.++..+.........+@@$$#@@+++..............................+..+.++++......++#$$%##@+..........", +"..............................+................................++@@#@##@@@@+...........++@@@+++..............+................+++.+..+..................................++@@+++.........++++++++++..................................................++@##@@++...............................................++@@@#@@++..........", +".....++++++++++...........+++++++............++++++@++++........+.++++@++++++...........+++++++++.......+++++@@++++++..........+++++++++++....+++++@+@+@+@+++.........++++++++++.........+++++++++.+............................................................................................................+.+.+.+.........", +"...+.++@@#@@@@++++.....++++@@@@@++++.......+++@@@@#@@@@+++......++@@@@@#@@+++..........+.+@@@@@+++....+++@@@#@#@#@@@+++.........+@@@@#@@+++.+++@@@@#@#@#@@@@+++.....+++@@@@@@@++++......+.+@@@@@@@++++...........................................................................................................+++++++++.+....", +"...+++@@##$##@@@++....++@@@#####@@.+.......++@@##$$###@@+++..++++@@#$$$###@@@++........++@@###@@++..+.+@@##$$#$#$##@@+......+++@@@###$##@@+.++@##$#$$$#$$###@++...+++@@##$$###@@+++.....++@@##$##@@@++........................................................................................................++++@@@@@@@@++....", +"..++@@#$%=&=%$#@@++..++@@#$%%&&&#@++.....++@@##&%===&%##@@+....@@##%&&==&&##@@+......++@@#%%%%%#@++..+@#$$&&=&==&&%%@@+.....++@@#$$==&&%$@+.+@@%%&==&=&==&%%#@+..+++@##$%&&=%$##@++...++@@#$&&&&%$#@@++......................................................+..............................+.+..............+.+@@###$###@@+++..", +"..+@@#$%%===%%$#@@+..+@##$$&&==&$#+++....++@#$$&=====&$$#@+.+++@#$$&&===&&$$#@@.......+@#$%%&&%$@@+.++@#$%=======&&%#@+.....+@##$%%====&$#@.+@#&&&=======&&%#@+..++@#$$%&===%%$$#@@....+@#$$===&&%$##@+...................................................+.+++++.+......................++.+++++............++@@#$$%$%$$##@++..", +"++@@$%&**;;;**%%$@+.+@@#=;;*-***$#@+....++@#%&=**;;;**=&&#@..+@#&&=**;;;**=&%#@......+@#$%-*-**$#@+.++@$%&**;;;;;=&&#@+...++@@$%*****;;=$#@.@@$=;;;;;;;;;;;;$#@.++@#%&=**;;;**=&%#@..++@#$**=;;;;;;;#@+..........+.....................+.................++++@+@+++.....................+.++@+@+++.+.........++#$%*******%$#@++.", +".+@#%%&**;;;**&&%#@..+@$=;;-*--*%#@++...++@#=&=**;;;**==&#@..+@#&==*-;;;-*==&#@......+@#%%--***$#@+.+@#%%&*-;;;;;==%#@+...++@#%%--***;==$#@.@@$=;;;;;;;;;;;;##@.++@$&==**;;;**==&#@..++@#$**;;;;;;;;$#@........+.++++.+..............+.++++..........+.+++@@@###@@+....++++++++++++++...++@@###@@@+++........+@#$%*--*-**%%$@@+.", +"+@@#%&&**;;;**&&%#@.+@@#==;--*-*$$@+....+@@$&==-*;;;*-===$@.++@#&==**;;;**===$#...+.+@@#%&*--**%#@+.+@@%&&**;;;;;=&&#@+...+@#$%&*--**;;=$#+.+@#=;;;;;;;;*;;;$@@.+@@$&==**;;;**==&$#.++@#$%**;;;;;;;;$#@......+++@@+@++............+.++@@+@+++.......+.++@@##$$#$#@@....+++@+@+@@+@++++..+@###$$$##@@++++....+@@#%%**-*-**%%%#@+.", +"+@#$;;;=&%%%=&;;;$#..+@##$%%%***$$@@+....@@#;;;&&%%%&=;;;$#.++@#%==%%%%%==;;;##.....+@#$=;===**$#@@.+@#%&&;;&%%%&%%##@+.+.+@#$**===%%%$##@+.+@##$$$$%%%==;==$#+.+@#$;;;=&%%&==;;;$@.++@$%&;;%%%%&***%$@......++@@##@@@++..........+.+@@##@@+++......++@@##$%&***%$@..+++@@@#@#@#@#@@@@+.+@#***==$$##@@++.+...@@$%&;;%%%;;;;=$@@.", +".@#$;;;&&%$%&=;;;$#..++@##$$%*-*%#@+.....@@#==;%%$$%&=;;;$#..+@@%%&%%$%%&=;;;$#...+++@#$=;;=;**%#@+.+@#$&=;;%&%&%%$$#@+..+@#$%**===%%%$$@@+.++@@####$$%==;==#@@.+@@$;;;==%%%&=;;;$#.+@@%%&;;%%%%%***%$#.....++@##$$##@++...........@@###$$#@++..+.++@@@#$$%&&***%%@.+.@@#$#$$$$$$$$##@+.+@#***;=%%$$#@@++...++#$%&;;%%%=;;;;$#@.", +"+@#$;;;&&$$$%&;;;$#...++@@#$%***%##++....+@@#$#$$$$%==;;;$#..++@###$$$%%**;==$#....+@#$%**&&&**%#@+.++#%%&*-*-***=&%#@+.++@$%&**=====%$$@@+.+.++@@@##$%;;&&%#@@.+@#$=;===%%%==;==$#.+@@%%&;;%%$%%***%$@.....+@@%%***##+++........++@@%&***##@+..+.+@@#%%=;;;;&%%$@@.++@#&&=&&===&&=&&#@.+@@#$$==***&%##@@++.++@$$%&=%%%&&;;;$#@.", +"+@#$;;;&%$$$%&;;;$#.....+@#$$-**%#@@....+++@@@####$$=;;;;$#...++@@##$$%%**;==$@...+@@#%%**&&&**$$@@.+@#$&=**-*--*=&&#@+..@#$%&**===;=%%$#@+..++++++@#$$;;&&%#@+.++##==;=;%&%;=;==$@.+@@%&=;;%%$%%***%$#.....+@#%&***$#@+..........+@#%&***$@@++.++@@##%&;;;;;&%%#@+.+@@#&============#@..@@#$%==--*=&$$#@@+.++@#$%%&%$%&=;;;$#@.", +"+@#%;;;=%##$%&;;;$#....+++@$%***$$@++....+++@@@@#$$%==;;=#@..++++@@#$%%%**;==##...+@#$%%**&&&**%##+.++@$%&***-***==&$#@.++#%%&**=====&%%##+.....+++@@$%;;&%$@@..++@$==;==&%%==;==##.+@#$%&;;%%%%%***%$#.....+@#%&***$#@+..........+@#%&***$#@.+.+@@$$$&&;;;;;%$$@@+.+@#$==;=;=;;=;===$#..++@##==**-=&%$$##@.++@#$$%%%$%&&;;;$#+.", +"+@#%;;;&%$#$%&;;;%#......@@#$*-*%#@@.......+++@##%&&**&&%#@.....+@@%%*---*&&%$@..++@#&====&&&**%$#@.++@$$%=;&%&=;***$#@.+@@%&&*****;;***$#@.......+@#$%**%$#@++..@##%%&-*-*--*&&%$@..@@%%=**%%%==-*-%$@....++@#%&=;=$@@++........+.@#%&=;=$#@+..@@#==;**===%$##@@+..+@#%=;;;;;;;;;;;=$#...++@##$%%&;;***%$@...+@@##$%&&**;=&$@@.", +"+@#$;;;&%$#$%&;;;$#......+@$$***%#@@........++@#$%&&**%%$#@....++@@%%--***&%%$#.++@#$&==;=&%&**%$#@.++@##%==%%%==***$#@.+@#%&&*-***;;***$#@.....++@@$$%**$$@@+..++#$%&&**-****&%%$@..+@$%&**%%&==---%$#.....++@$%==&##+.+........+++@$%==&#@++..@#$=;;*-==&$$#@@++..+@#$;;;;;;;;;;;;;$#...+++@#$%%%;;***&%#...++@@$$&&&**==&#@+.", +"+@#%;;;&%##$%=;;;%#.....+@@#%*-*$$@++......++@#%%-*-&&%#@@+...+.+@@#$%%&=;;;=$#..+@#$*-*;;;;=-*&&%#..++@###$#$$%%***%$#.+@@%&&**&&&&&***%$@......+@#%&=;;$#@++..+@@$;;;=;&&&;;;;;$#.++@#$$;;-*-;;***%$@.....++@@####@@++...........+@@#####@+...@#$;;;**=&&$##@++...+@#%&====;=;==;==$#....++@@#$%&;;-**&%#....++@#$***=&%$#@@+.", +"+@#$;;;&&$#$%&;;;$#......@@$$***%#@@+......+@@#%%*-*&&##@++...++@@@##$%%=;;;;$#..+@#$***;;=;;**=&%#..++@@#####$$%***%$#.+@#%%=*-%%&%%***%$#......+@#%&&;=$#@++..+@#$;;;;=&%&=;;;;$#.+.+@#$=;--*;;***%$#.....+++@@##@@+............+.+@@#@@@+++..@#$;;;**=&&%$#@++.+.+@$$===;=;=;==;==$#....++@##$%%;;*-*&%#....++@#$*-*&%$##@++.", +"+@#%;;;&%$$$%=;;;$#.....++##%***%$@+++....++@#$&&*-*&%$@@++..++@@@###$$%=;;;;$#.++@$$*-*;;=;=-*=&&#.++@@#@##@#$$%***%$@.+@@%&&**&%%%%***%$@.....++@$&=&;=$#@+...+@#$;;;;=&%%=;;;;$#..++@#$==*--;;***%$@.......++@@@@+++............+++@@@@++....@#$=;;**=&&$$#@@++..+@#%====;=;;;=;;=$#...++@@#$$%%;;***&%@.....@@#$***&%#@@+...", +"+@#$;;;=%$$$%&;;;%#...+++@#$%*-*%$#@++..+++@$$%**===%$#@@+...+@@%%%##$$%&=;;;$#.++@$%=;;;;;;;-*==&$.+@@$%%####$%%-*-%$#.+@#$&&**%%%%%*-*%$#.....+@@$&=;==##+++..+@#$;;;=&%%%&=;;;$#..+++@#$%%&&&&***%$@......+++@@@@+++............+++@@@@@+....+@#$$%&&***;;%$#@@+.+@#$=;;;;;;;;;;=;$#.+++@##&&*-*;=%%$$#@.....+@#$===%$#@++...", +"+@#$;;;&&%$%&&;;;$#..+.+@@#$%***%$#@@++..+@#$%%-*==&%$#@@++.++@#%%&$$$$%&=;;;$#..+@#$==;;;*;;*-==&$.+@#%&%%$$$$%&***%$@..@@%%&-*%%%%%***%$@.....+@#$====&$@++...+@#$;;;=&%%%&=;;;$#...+@@#$%%%&&&***$#@.....+.@@@@##@+++...........+@@@##@@+++..++@##$%&***;;%$$#@+.+@#$=;=;;;=;=;;==$#..+@##$&=**-==%$#@@@.....+@#$===$#@+.....", +"+@#$;;;=&%%%&&;;;##..++@@#$%%-*-%%$#@@+.++@#%%&*-===%%$##@+.+@##&&&%$%$%&=;;;$#..+@#$==;;;;;***;=&$.+@#%&&%%$%%%&*-*%$@.++@$%&**%%%%&***%$@.....+@#$=;==&#@+....+@#$;;;=&&%%==;;;$#...+@##$%%&&&&***$#@.....++@#$$###@++.........+++@##$$##@++...++@@#%%***;;&%$$#@.+@#$&======;=====$#.+@@$$%&=*-*==##@@++.....+@#$===$#@++....", +".+@#%&&**===**&&%#@..+@@%%&==-**==&%%@@.+@@$*****;====&%$@@.+@#$***;;===**;==$@...+@##$$&&;;=-*==&$.+@#&==**===**;;;$#@..+@##%*-;;;;;-**%$@.....+@#$***%$#@++...+@@$==;**===**;==$@..++@#$=====**;==$#@......@@%%***#@+++.........+@#%&***#@++....++@@#$$$%==***%$@.++@##$$$$$$$$$$$#@@.+@#***;;%%%$##@@++.....++@@$==&$#@+.....", +"++@@%%&**=;=**&%%#@..+@#%&&==*--===&%#@.+@#$***-*;;===&&%#@.+@#$***;;==;**==&#@...++@##$%&=;;**=&&#.+@#&==**===-*;;;##@.+++@#$**;*;;;***$#@.....+@#$***$##++.....@@#&==**;==**==&#@.++@#$$===;=**==&#@+....++@#%&***$#@+........++@##&&***$@@+....+.+@@@#$$&=***%$@..++@@##########@@@+.+@#***;;%$$##@++........+@@$&=&$@@++....", +".++@##$&&;;;=&$$@@+.++@#&&=;;;;;;;=&&#@.+@#$=;;;;;;;;;==&#@.++##%&%;;;;;;=%$#@@....++@##%&=;;;;==&#.++@#$%==;;;=;%$$#@+...+@##%%=;=;;&&%$#@.....+@#$===$#@+......+@##$%==;;;;=%$#@@..+@$$%;;;;;&&%$#@@+.....+@@%&;;=$#@++........+@#$**=&&$@++........+@@@##$$$$##@...++++@@@@@@@@@@@++.+@##$$$$##@@@++.........++##&==#@@......", +".+.+@##%&=;=&&$#@@+..+@#&&==;;=;;==&&@@.+@#%==;=;;;;;==&%#@.++@#$%%;=;=;==$##@+....+.+@#%%;=;=;==&#..+@@#$==;;;==$$@@@...+.+@#$%===;=%%$#@+.....++@#==&$@@++......+@##$==;;===$##@+..+@#$%==;=;&%###@++.....+@@%%===$@@.........++@#$**=&%##++.......+.++@@@@###@@+....+++.+++++++.++.+.++@#$###@@@++.+.........++@#&=&#@@......", +"..++@@#$%===%%#@++...+@@%&&===;====&%#@.+@##==========&&%@@...@@$$%=====&&##@+......+++@$%=====&&%#..++@##&=====&##@@.+....++@#$&====%$$@++......@@#%&&#@++......+.+@##&=====&##@++..++#$$=====%%#@+++.......@@$%==&#@+++.......+@@$$**&&%#@+............++@@@@+@++.......+..............++@#@@@@++..............@@#%&%#@++.....", +"....++@@##$###@++.....+@##$$$$$$$$###@+.++@##$$$$$$$$$$##@+...++@###$$$$$#@@++.......++@@##$$$$###@...++@###$$#$#@@++......+++@@##$####@+++......+@@#@#@@+..........+@###$$$##@@++...++@@##$$###@@@+.+.......+@@####@@+.........+@#%%==$##@+++..............+.++..+.........+....+.......+++++++.................++@@#@@++.+....", +".....++@@@#@@@++.....+++@@#@#####@#@@++..++@@@########@@@@+..+.++@@@####@@@++.........++@@#@####@@+.....+@@@@##@@@++.........++@@@##@@@+++........++@@@++...........+++@#@#@#@@++......+@@#@###@@++.........+.+@@@@@@++.........++#$$&&##@++.................+..............................+++.+.................+@@@@@+.......", +".....+.++@@++++.+.....++++@@@+@@@@++++....++@@@@@@@@@@@++......+.++@+@+@@++.+...........++@+@+@++++......++@@+@+++...........+++@++@+++...........+++++++............++++@@@+++..+....+.+++@@+++++.............++@@++.+.........++@@@##@@@+........................................................................+++++........", +"......++++++++..........+.++...+.........+.+.++++++.+.............++.++.+.+.+....+.++++.++..+..+......+.+++++++++++.+....+.++++++++.++.+............+.+.+..+........+.+++..+.+++..+....+.+.++++++.+.........+.+++++++++......+.++.++.+.+.+.+.+......+.+++.+.+..+......+.+........+.+..+....+.+.+...++..+..........+.+.++........", +"..+.++++@@@+@+++......+.+++++@++++........++@+++++++++++.........+.+++++++++++...++++++@+++++.+.......+++++++@++++++.+....+++++@+++@@++++++......++++++@++++++...++++@+++++++++++++...++++++++++++++++........+++++++++++++.+.+++@++++++++@++.+.+..++++++@+++++.......++++++..+.+++++++...++++++++.++++++++......+.++++++++.....", +"..+.++@@####@@+++.....+++@@@@@@@+++.....+++@@@#@#@#@@@+++.......+++@@@#@@@@@+++.+@@@@#@@#@#@@++.+...+++@@@#@#@#@#@@@+++.+++@@@@#@#@@#@@@@++....+.++@@@@@@@@@+++..++@@@@@@@@@@@@#@@+.+.++@@#@#@#@#@@++++....+++@@@#@#@#@@@++.+++@@@@@@@@@@@@@@++..+++@@@#@@@@@++.....+++@@@@@++++++@@@@+.+++@@@@+++++@@@@@++....+.++@@@@@@+++....", +"...+@###$$$$$#@+++....++@@##$###@@+.....++@##$#$$$###@@++++...+++@@####$####@@+.+@##$#$$#$##@@@++...++@##$#$#$$$#$##@++.++@###$#$$$$#$$##@@...+++@@###$#$###@@+.+@@###$###@#######@.++@@####$$#$###@@++.....+@@##$#$$#$##@@..@@###$###@######@+..++@##$#$$##@@++....+@@@###@@+++@@###@@.++@@###@@@@@#####@@...+++@@@#####@@+++..", +".+++##%==***%%#@++..+.+@$$%&&&&&#@@+....+@@%&&&&&=&&&$##@+....++@@$$&&&=&%%%$$@.@$$&&&&=&&&&%#@@++..+@#%&&=&=&&=&&&&#@+.+@#%&&=&&&&=&&&&%$@...++@@$$&&=&&%%%$$@.+@$%&&&&&$$$&&=&&%$.++@%%&&=&=&=&%%%@++...+++@%%&&&&=&&&%$@.+@$%&&&&&$$$&&&&%#@..+@#%&&&&=&&$#@++...+@$%&&&##@@@##&&&%$.+@#%&%%$#@#$%&&&$$@...++@#$%&&&%%#@@+++.", +"..@@#$%=;-**&&#@@+...+@#$%&====&$#@++...+##&========&%$#@@+.++@@##%%=====&&%%%@.@%%========&&$##@@+.@@#&&=========&&$@@.+@#&============%%#.++@@##%%=====&&%%$#.@@$%&===&%$%&===&%%.+@#%&&=======&%%#@+....+@#%&=======&%$@.@@$%====&%%%&===&#@.++@#&======&%$@++...@@%%&&=$$#@#$%&=&%$.@##&&=%%$##%%=&=%%@.++@@##%%&==&&$##@@+.", +"++@#$%%;;**-&=$#@++..+@@%%&=====$##+++..@@$&===;=====%%%#@@.+@@#$$&&=====&&&&%#.#%%===;=====&%$$#@+.@#$&====;==;====$#@.@#$&===;=;==;===&%#.+@@#$$&%=====&&&&%#.@#%&=====%%%=====%%.+@#%&&========&%#@+...++@#%&========&%#.@#%%=====%%%====&$#.+@@#&=======%$@@+...@#%&===%$$##$%===&%.@#$===&&$$$&&===%%#.+@@#$$%&====&%$$#@@.", +"++@#&==;==&&**%$#@+..+@#&&=**-*-&%#@+...@#$;;;**;;;;;***$#@.+@#&&=**;;;;;***==$.#%&***;;;;;;;***$#@.@#$;;;-*;;;;;-**%$@.@#$;;;**;;;;;***;=$.+@#&&=**;;;;;-**==$.@#%&***;;%%&;;***&%.+@#%&=;;-*-;;==%#@+....+@#&=;;;*-;;;&%#.@#%&**-;;&&&--;;=$#.+@#$==;-*;;=%$@+++..@#%&*-*==$$%&=-*-&%.@$$*****%%$&=-**=%#.+@#&&=**;;;;;***$#@.", +"+@##&==;==&&**%$#@+..++@&&=**-*-=&$@@+..@#$;;;-*;;;;;***$#@.@##===**;=;;;*-*;=$.#%=*-*;;;;;;;***$$@.@#$;;;**;;;;;*-*%$@.+#$;;;-*;;;;;***;=$.@##===**;=;;;**-;=$.@#%&*-*;;&%%;;-*-&%.++#%&==;*-*;==&%@@+...++@#&&=;;**;;;&%@.@#%&***;;&&&*-;;=$#..@@$==;*-;==%$@++...@#&=--*==$%$==-*-&&.@$%**-**%%%==*-*&%#.@@$&==**;=;;;***$##.", +".@#$;;;&=&==**&%%@+..+@@#$%;;;;;;=$#@+..@@$%==;;&&&&&***%$@.@#$***&&%%$%%===;=$.@$%;;;=&%%%%%***&%#.+##%==;;%%%%%***%$@.@##&&=;;%%%%%=====#.@#$***=&%%$%%===;=$.+#$%;;;=&%%%==;;;%$.++@##$%%***%%$##@+.....++@#$$%&;;=&&$#@.+#$%;;;==;;;;;%%$#@.++@#$%%**&%%##@+....@#$%*--;;%%%;;*--%%.@#$;;;**&&&%&***%%#.@#$***&&%%%%%***&%#.", +"+@#$;;;==&=&**&%%#@...+@#$%;;;;;;=$#@++.+@#%&=;;&%%%&***%$#.@#$***&&$$$#$=====#.@$$;;*&&$$$%%***=&#.+@$%&&;*%&%&&***%$@.+@#%&=;;&%%%%=&===#.@#$***&&$$$$$=====$.+@$%;;;==%%%&=;;;$$.+++@##%%*-*%$$@@@+.....+++@##$%;;=&%$#@.+@$%;;*&&;*;;;%##@+..++@#$%**%%$#@++....@#%%-*-;;&%%;;-*-%%.@$%;;;-*===%&***%$#.@#%***&&$$$%%***=&#.", +"+@#$;;;&&=&=**&&%@@..++@#$$;;*;;;;$$@++.@@#%&=;;%&&&%***%$@.##%***&%$####%&&==#.@#%;;;&&$$#$%***&&#.+@#%&=;;&%%%%***%#@.+@#%&=;;%%%%%&=&==#.@#%***&%$###$&====#.@@#%;;;=&%%%=&*;;%#...+@@#$%***%$#@++........+@@#$%;;&&%#@+.@@#%;;;&=;;;;;$#@@+...+@##%**%$$@@+.....@#%%*--;;%&=;;--*%$.@#%;;;-*&&&&%-**%%@.@#$***&%$##$%***&&$.", +"+@#%;;;;=**-*-&%%#@..++@#$%**&=&**%$#@+.+@#%&&*-===;;-**%$#.@$%***%$#@@@######@.@#%;;;&%$###$===;=$.+@#%&&;;&&&**%%$#@@.+@#%&&;;&&%**%%$##@.@$%***%%####$$%%$$#.+@#%;;;;;===;;;;;$$....++@$$*-*$$#@.+......+..+@@#%;;=&%#@+.+@#%;;;*****&$$#@++...++@$$**%%#@+++....@@%%*****&&&*****&$.@#$;;*=;;;;&%***%$#.#$%***%$##@#$=====$.", +"+@#%;;;==-*-**&&%#@..++@$$&**&&&-*%$$@+.+@@%&=**=;=;;-*-%$#.#$%***%$#@@+@@@#@@@.@#$;;;&%##@#$=====$.+@#$&=;;&&&**&%$#@+.+@@%&=;;&%&**%$##@@.#$%***%$####$%$%$##.+@#%;;;=;=;=;;;;;%#....+@@#%***%#@++......+.++.@@#$;;&%%#@+.@@#$;;******%%#@++.....@@#%**%$#@++.....@#$%**-**&&&**-**%$.@#%;;;;=*;;%&-**%$@.#$%***%$#@@#$==;==#.", +"+@#$;;;;;;;;;;=%%#@..+@@%%&;;&&%;;=%%#@.+@#%%&*-;;;;;***&%#.#$%*-*%##++++++@@++.@$$;;;&%##@##&==;=$.+@#%&&--**-**%$##++.+@#%&&--*-***$$#@++.#$%*-*%$###&&===%%@.+@#$;;*;;;;;;;*;;$#.....+##%***%#@@.....+++++@+@@$$;;&&%#@+.+@$$;;;*-*-*&%#@@.+....+@#%**%$#@@++++..+#$%***;=*-*;=***%$.@#%;;;&&***=&***%$#.@%%***$##@@##&&=;=$.", +"+@#%;;*;;;;;;*&&%#@.++@#%&=;;&&&;;&&%#@.+@#%&=**;;;;;*-*&%$.#$%***$$@@+.+++++++.@#%;;;&%##@@$&&&;=$.+@#$&&-*-****%$#@@+.+@@%&&-*-*-**%#@++..#$%***%$##$&====&%#.+@$%;;;;;;;;;;;;;$#.....@@#$-**$$@++....++@@@@@@@$$;;&%%@@+.+@#%;;**-***&%$@@+....+@@#$**%%#@@@@@++.@#$&***=;-*-=;-**%$.@#$;;;&=***&&***%$@.#$%***%$@@@#$&&=;=$.", +"+@#$;;;==*-***==&#@.+@#$%&=;;&%&;;=&%##.+@#%%&-*;;;;;*-*=%$.#$%***%$@@+++++@+++.@#$;;;&%#@###&==;=$.+@#%&&*-*-***%%$#@@.+@#%&&-*-*-**$##++..@%%***%$##$&====&%#.+@#$;;*;;;;;;*;;;%#.....+@$$*-*%#@@.....@@##$#####%;;&&%#@+.+@#$;;;**-*-&%$#@@+....+@$$**%$$#@@@@@+.+#$%***==-*-==***%$.@#%;;*&&***=&***%%@.#$%*-*%##@@#$&==;=$.", +"@@#%;;;;;**-**===##.++#$;;;*-*-*--;;=$@.++#%&&;;%%%%%;==;=$.#$%*-*%$#@++@@@@@@+.@$%;;;&%##@#$&&=;=#.+@#%&=;;=&&**&%%%$@.+@#%%=;;&&&**$#@+...@$%***%%$$$;;***==$.+@#%;;;==%&%&=;;;%#...++@##%***%$@+++...@#$===####%;;&%%#@+.+@$%;;;===;=**%$#@+...++##%**%$$##%%%#@.@#$%*-*&%;;;%&***%%.@#%;;;=====;;-**%$#.@$%***%$#@@#$===;=$.", +"+@#$;;;&==;=;;==&#@.@@#$;;;-*-*-*-;;=%#.+@#%&&;;%%%%%===;=$.@$%***%%##@@##$###@.@#$;;;&%$###$&====$.+@#%%&;;=&=**&&%%%#.+@#%&&;;=&&**$@@+.+.@$%*-*%%$$$;;***==$.+@$$;;;=&%%%&=;;;$$....++##%***$$#@.+.+.@$$;;;%$$$%;;=&$#@+.+@#$;;*&===;**&%$#@...+@@$%**&%$$$&&%$#.+#$%***&%=;;%%*-*%$.@#$;;;=====;;***%$#.#$%*-*%%$##$$=;=;=#.", +"@@#$;;;====;;;==&$@.+#$%*-*==&&&&&***%$.@@#%&=;;%%$%%;;=;=#.##%;;;==$$###&==&&#.@$%;;;&&$$$%%***&%#.+@#%&=;;%&%&%=====#.+@#%&=;;&%%%%#@++...@$$;;;=&%$%%%;;;;=$.@@$%;;;&&%$%&=;;;$$...+@@#$%*-*%$#@@++..@$%***%%$$%**&%%@++.@@$%;;;&=%%&;;==&#@..++@##%**%%%%$***$#.@#%%***%%%$%%&***%$.@#%;;;&&%%%***-*%$#.@$$;;;=&$$#%%***&%$.", +"+@#%;;;=&;==;;==&#@.@#$%***=&&&&==*-*%$.+@$%&=;;&%%%%=;;==$.@#$;;;==%$$%%====&#.@$%;;;=&$$$%%***&%#.+##&&=;*%&%&&=====$.+@$%&=;;&%%%$#@++...@#$;;;;=%%%%%;==;=$.@@$%;;;=&%$%&=;;;%$.++@@#$$%*-*%$$#@++..@$%***%%%%%**&%%#@..@@$%;;;=&&%%;;===$#..+@@$$%**&%%%%***%$.@#%%***%%$$$%%***&$.@$$;;*&=%%%***-*%$#.@#$;;;;=%%$%%*-*%%#.", +"+@#$=;;==&&%=&&%$#@.@#$&*-*=&&&&&=***%%.@#$&&=;;%%%%%;=;;=$.@@$;;;==%%%%%====&#.#$%;;;&=%%%%&***%$#.@@$&&&;;&%&&%===;=$.@@$&&=;;&%%%$#@+....@@$;;;==%%%%%=;===#.@#$%;;;&&%%%&&*;;%$.++@#$$%%***%%$$#@@+.@$%*-*&&%%&**&%$@++.@#$%;;;&&%%%;;===%#.++@#$%%**&&&&%***%$.@#%&***%%$$$%%***%%.@#%;;;&&%%%**-**%$@.@@$;;;==%%%&&***%$@.", +"+@@#&==;=%&%=&%%$@@.@#&=--***&&&**---=&.@#$*-*--*-*-****%$#.+@#%%&;;*-***;;;%$#.#&=---**-*-*-;==$#@.@#$**-*-*-*-***-;=$.@#$**--*-**%%@@+....+@#%%&*****--;;;%$#.@#&=--***%%%****-=&.+@@&==-----**==&@@+.@#$=;;*-***;;$$@@++.@#&=---**%%%&=-*-=&.+@#$*-*--****-*--$$.@#&=--*==$#$=;---=&.@$%*-*-*%%%==---%$#.+@#%%&******-===$#@.", +".+@#$%&***-***%$$@+.@#&=*--**&%&**--*=&.@#$-***-*-**-***$$@.+@@$%%;;**-**;;;$$@.#&=-*-***-*-*;==##@.@#%*-*-*-*-**-**==#.@#$*-***-*-%%@+++...+@@$%%**-****;;;%$@.@#&=*--**%%&-*-**&&.+@#&==***-*-*===@@+.@@#===-**-*;=$#@++..@#&=-*-**%$$%%*-*=&.++#$-*-*-****-*-*%#.@#&=*--==#$#==-*-=&.@#%*--*-$$$==**-$$@.+@@$%%***-***=&&#@@.", +"+++@#$%*******%$#@+.@#$$%%%%%$$$%%%%%%#.@@$$%&%&%%%%%%%$$@@..+@@##$$%%%%%$$##@@.@#$%%&%&%%%%%$$##@+.@@#%%%%%%%%&%%%%$$#.+@#%%%&%%%%$#@+......+@@##$$%%&%%%$##@@.+#$$&%%%%$$$%%%%%%#.+@@$$%%%%&%&%%$#@@..+@##$$%%&%&$$#@@+...+@$$%&%%%###$$%$%$$.++@#$%%%%%&%%&%%%##.@@$%%%%%$###$$%%%$$.@@#%%%%%$#$$$%%%##@..+@@##$$%%%%%$###@+.", +".++@@##$$%%%$$##@+..+@#$$$%$$###$$%$$$#.+@#$$%$%$%$$$$$##@+..+++@###$%$%$$##@@+.@@#$$%$%%$%$$##@@++.+@@$$$%%%%%$%$$$$#@.@@@$$%$%%$##@+++.....++@@@#$$$%$$###@@+.+@#$$%$$$###$%$%$$#..+@#$$$%%$%%%$$#@++.++@@#$$$%%%##@++....@@#$$$$$$##@@##$$##..+@@$$$%%%$%%$%$$#@.+@##$$$$##@###$$$##.+@#$$$$$#@@##$$$#@+..+++@###$$$$$##@@++.", +"...++@@##$$$##@@++..++@###$##@#@######@..+@####$###$###@@++..++++@@@#####@@@+++.+@@###$#$####@@@+.+.++@###$###$######@+.++@###$##$#@@+.........++@@@######@@++..++@###$##@@@######@.+++@@###$#$$###@++..+++@@@#$#$#@@@++....+@@##$###@@+@@###@@.+++@#####$#$#$###@+.++@#####@@+@@#####@.++@#####@@@@@##@@++...+++@@@#####@@++...", +"....++@@@@#@@@++++...++@@@@@@@++@@@@@@+..+++@@@@@@@@@@@+++.......++@@@@@@@+++...++@@@@@@@@@@@@++.+...++@@@@@@@@@@@@+@++..+++@@@@@@@++............++@@@@@@++++....++@@@@@@+@+@@@@@++...++@@@@@@@@@@@++.....+++@@@@@@@++.......++@@@@@++++++++@@+...++@@@@@@@@@@@@+++..++@@@@@+++++@+@@++..++@@@@++++++++@++.......++@@@@@++++....", +"....+.++@++@+++......+.+++++.+++++++++....++++++++++.++..+.......+..+++++..........+++++@++++..........++++@+++@+++++.+...++++++++..+...............++++++........+.+++++++.+++++++...+.++++++@+++++..........++++++.........+.++++++....++.+.......+++@+++++++++.+..+.+++++++.+.+++++.....+++++...++++..+........+.++.+........", +"...+.+.++++.++.............+.+.+.+.........+.+.+..+.+..............+.+++..+........++.+++.+..+.+..........+......+.+......+..+.+..+..+...+......+.+.+..+.+.+.....+...+...+...++.+......+.+.+...+.+.++.+......+.+.+.+.++..........++@@@@@@++.+...+.+++++++................+++@@@@@++.+..........+.+++++..........................", +"..+++++++++++++++........++++++++.+......+.++++++++++++..........++++++++++++.....++++++++++++++++...++++++++++++++++++...++++++++.+.+++++....+++++++.+.+++++++...+++++++++++++++++....+++++++++++++++......+++++++++++++++....+++@#####@@++.....++@@@@++++...........+.++@@#####@@.+.........+++@+@+++.........................", +"+++@@@@@@@@@@@++++.....++++@@@@@@++++....++@@@@@#@@@@+++.......+++@@@@@@@@@@+++.+++@@@@@@@@@@@@@+++..++@@@@@++@+@@@@@++.+++@@@@@++++@@@@@@+.+++@@@@@+++++@@@@@+..++@@@@@@+@@@@@@@@+..++@@@@@@@+@@@@@@@+..++++@@@@@@@@@@@@++.....+@#%%&&%$#@+++..+@@####@@++............++@#$&&&%%#@+..........+@@@#@@+++........................", +".@@###$#$#$####@@++...+++@@#######@@+++.+@@@#$#$######@@++...+++@@@##$#$###@@++..@@@###$$#$$####@++.+@@######@@######@@.+@@@####@@@@@#####@.+@@@#####@@@@#####@.+@@#######@@######@.+@@######@#@######@...+@@###$#$#$####@@....+@@$&&==&$#@@....+@#&==%$@+++...........+@##$&=&&&##@+........++@#%%%#@+++.......................", +"+@##$$%$%$$$$$$#@@+.+.+@@#$$$%$$$##@@++.@@#$$$$%$%$$$##@@++...+@@#$$$%$%$$$$#@@.+@#$$%$$%$%$%$$$#@+.+@##$$$$###$$$$$##@.+@#$$$$$$####$$$$$#.+@#$$$$$####$$$$$##.@@#$$%$$$$$$$$$$$$#.@@#$$$$$$$$$$$$$$$#.+++@##$$%$%$%$$$$#@...++@#$***;;%$#+++..+@#===%%#@++..........++@#$%;;***$#@+.......++@#$%&&$#@++.......................", +"@#$**********==&#@@..+@#$$==*****%%$@@+.@#&=********==$##@+.++@#$$**********$#@.@#$*************$#@.@#$*****%%%==***=&#.@#&=***==$#$==***=&.@#&=***==$$$==***=&.@#&=*****%%%*****&&.@#&=*****%%%*****=&..@@#===**********$#....+@#$--*;;%##++...+@#%&&==$@@+...........+@#%%;;***$#@++......+@#$%-**%$@+++......................", +"@#%***-*-*-**===$#@.+@@#$%;;*****&&%#@+.@#&=**-*-**-;=%$#@@.++@#%%**********$$@.@$%**-**-***-***%$@.@$%*****%%$;=***=&#.@#&=***==$$$=;***=&.@#&=***;;$%$;;***=&.@#&=**-**&&&**-**=&.@#&=**-**&%&*-***=&.+@##=;;**-*-*****%$...++@$$**-;;$$#@.+..+@#%&===$#@+..........+.@#$%;;-**%#@+.......+@#%%*-*%%#@++......................", +"@$$*-*******-=;=$$#.+@#$%%;;-*-**&&%$#@.@#==-****-**;;%%$#@.+@#$%%**-*-*****%$@.@$%***-*-*-***-*%$@.@#%**-**%%%;;*-*==$.##==*-*;=$$$==-**==.##==*-*;;%%%;;*-*==.@#==***-*%&&-**-*==.@#==-**-*&&&***-*==..@#$=;;*-**-*--**%$....+@$%***%%#@@+....+@#%&&;;$#@@+.........+.+@##%%***$$@@....+.+@@#%&*-*%%#@++......................", +"@#$&==;;=&&&&;;;=&#.@#$=;;==&&&=&***%$@.@#$%***==&&&;=;;;#@.+@#=;;;;&&&==*-*%$#.@$%***&&-*-&=***%$#.@#%***=&$$$%%***&%#.@#%&***%%$$$%%***&%.@#%&***&&==&&&***&%.@#$%-**;;%%%;;***%%.@#$%***;=%&%;;***%%.+@#$;;;==&&&;=***%#...+@@#$*-*%$#@+.+...++@#$%**%$#@@..........+++@#$%*-*%#@++.....+@#$==;;;;=$#@+......................", +"@@#&==;;&&&&=;;;==$.@#$;;;;=&&%&=*-*%$#.@#$%***==&&&;;;;;$#.@#$==;;;&&&&&*-*%$@.#$%-**=&**-&&***%$@.##$***&=$$$%%***%%#.@#%%***%%$#$%&***%%.@#%&***&%===%&-**%%.+#$%*-*=;&&&=;*-*%$.@#$%**-=;&%&=;*-*%$..@@$;;;===&&;;-**$$....+@$%***%$#@+......+@@#$**%%$@@++.........++@#$%***%#@++....++@#$==*;;;;$#@++.....................", +"+@#%&=;;%%$$%===;=$.@$%***&%$$$%%;;;==#.+#$%;;;=&%%%&=;;;$#.@#$;;;==%%%%&=;=%$@.@$%***%&-**&%-**%$#.@$$;;;&&$##$%***%%#.+@$%;;;&%$#$%%;;;%#.@#$%***&&*-*&&***%%.+@#$%&=**=;=*-&&&$#.+@#$&&=;;&&&**&&%$#.+@@$&==&&%&&**&&&$@....@@#$***$$@+++......@@#$====&#@++..........++@#%***$$@@.....+@#$%**&&&**$$#++.....................", +"@@#%&=;;%%$%$===;=$.@$%*-*&%$##$%;;;==$.+@#%;;;&=%%%&=;;;$#.@@$;;;==%%%%%;==$#@.@$%***&%-*-%&***%$@.@#%;;;&%###$%***%%@.@@#%;;;%%$##%&;;;$$.@#%%*-*=&*-*=&-**%$.+@@#%&&*-=;;**&&%#@.+@@#%%=;;&&&**&&%#@..@@#&&=&&&%&*-&&%#@...++@$%*-*%#@@........+@#$&===&$#@+..........++@$$-**%#@@....+.@#$%**%&%**%$#@+.....................", +"+@#%%=;;%%$$%&==;=$.@$%***&%####$;;;;=#.+@#$;;*&=%%%=&;;;$#.@@$=;;==&%%%%;==$$@.@#$***%%**-%%***$$@.@#$;;;=%$###%***%$#.+@#$;;;&%$$$%&;;;$#.@@$%***&=-*-&&***%$..+@#$%&**;=;-*&%%#@..+@#%%&;;&&&**&%%#@..+@#%&&%&%&&**&%%#@....+@$%*-*%##++........+@#&====$#@++..........+@#%**-$$@++...++@#$%**%%%**$$@@+.....................", +"+@#%&=;;%%$%%;==;=$.#$%***%$#@@#$===;=$.@@#%;;;;====**;=&$@.@@#%&&***-*==&&%$#@.@##$%%%%-**%%%%$#@@.@#%;;;&%#@#$$***%$#.+@#$=;;==$$$&=;;;$#.@#$%***;=--*;;***%$.+++@#$%==*-*==$$#@+..++@#$%;;**-;;$$#@+.++@@##$$%;;;;;$$#@+....@@#$***%#@@.........++@#$=;;&&##+++.......+@@#$***%#@@......@#$$&=$%$&&%$#++.....................", +"+@@%%&;;&%%%%=;=;=#.#$%***%##@@#$&=&;=$.+@#%;;;;;===**;==#@.+@#%&&*-**-==%%%$@@.+@@#$%%%**-%%$$$@@+.@#%;;;&%$#@$%***%$#.++@$=====%$%&=;==$@.@#$%***;=---;;***%$..++@@#$&=-*-&=$$@@+...++@#$;;-**;;$#@++...+@@#$$%;;;;;$#@@+...+@@#%***%#@+..........+@@$==;=&$#@+.........@@$%***%#@@....+++#$$%%#$#&%$##++.....................", +"+@#%&=*-*****;;;%%#.@$%***%$####$&==;=$.@@#%;;;*****;;%%$#@.+@##$%&%;==*****$#@.++@@@#$%***%$##@@++.@#%;;;&%###$$***%$@..@@#%&&;;%%%;;&&%#@.+#$%*****&&=**-**%%...+@##%=;;;;;=%#@@+....+@@$%%**-%$$@@+.....+@##&&***%%$$@@+...+@@#%***%##@..........++@#$%%**$#@+++.......+@$%**-$$@++.....++@@###@@##@@@+......................", +"+@#%&&-*-*-**;;;%$#.#$%*-*&%$$#$%;;;=&$.+@#$;;;***-*;;%$##@.+@##$$&%==;*****$#@..++@@#$%*-*%$#@++...@#$;;;&%####%***%%@..+@#%&&;;%%%;;&&%#@.+#$%*-***==&-****%$..++@#$$=;;;;;=%$#@+.....@@#%%-**%$#@++...+++@#$&=***%%$##@@....@@$$*-*$$@++..........+@@$%%**%##@+.......+@@#$***%#@@.....+++@+@+@@@+@@+++....++.+++++.+++++.+..", +"+@#%&&*-**-*-;;;$#@.@$%***&%%$$%%;;;=&$.+##%;*;****-;;%%$@@.+@#$$%&&===*****$$@....+@##%***$$#@+.+..@#%;;;&%$##$%***%$#.+++@$%&;;&%&;;&%%@@.@@$%***-*&&=*****%$.++@@#$%;=*;;==%$#@@....++@#$%*-*%$#@+.....+@##$&=*-*%%%$##@....+@#%***%##+++..........+@@$$;;%%$@@+......+@#$%***%#@@........++++.++++++....+.+++++++++++++++++.", +"+@#%&=;;=&&&&%$$#@@.@#$=;=**=&===*-*%%#.+@$$;;;==&&&**=%%#@.@#$;;;%%%%&&&***%$#...++@#$%*-*%$#@+.+..@#$;;;&&$$$$%***%$@..++@#$%**&&&**%$#@+.+@#%;;;-*&&&*-;;;%#.+@@$%&&**&&&**=&&#@.....+@#$%***%$#@++..+++@#$%**===%%;;=$#....+##$*-*%$#@+...........+@@#$;;&%$#@+....+.+@#$%-**$$@++..........+......+....+++@@@@@@@#@@@#@@@+.", +"@@#%&=;;&&&&%$##@@+.@@#==;**==&;=-*-%$#.@@$%;;;&&%&&-*&&&$#.@$$;;;%%&%%%&***%$@..+++@#$%***%$#@@+...@#$;;;&&%%%%%-**%$#...++##$**&&&**$#@++.@@#%;;;**&&&*-;;;%#.+@#$&==-*&&&-*=&&$#....+@@$$%*-*%$#@@+...+@#$%%-*===%&;;;%$...++@$$***%$#@@++..........+@#$=;&%%#@+....+.+@#$%**-$$@++......................+@@###$$###$#$###@@.", +"@#$=;;**;==&%##@+++.+@##%%;;-*-;;&&&&%#.@#%&**-;=%%%;=***%$.@$%-*-;====;=-**%$@...+@#$&=--*&&$#@++..+@#&==;;=====;;;$#@...++@#$==*-*;=$$@++.+@#$;;*;;&%&;;*;;$#.@#%%-*-;;&&&;;*-*&%...++@#$==-*-&&$#@++.++@#=;;**=;===***%$...++@#%*-*==$#@+..........+.@@$%&;;;$#@.....@@#$&=***%#@+.......................@#$%%&&&&&&&&&=&%%@.", +"@#$=;;**;==%%#@++...+@#$$%;;-*-;;&&&&%#.@#%&***=;%$%=;***%%.#$%*--=;====;-**%$@..+@@$$==**-=&$#@+++.@@#%&=;;====;;;;$#@....+@#$==*-*==$#@+..+@#%;;;;;%%&;;;;;$#.+#%&--*;;%&%;;*-*&%..+++##%&=-**=&$#@++.+@@$==;*-=;===-**%$....+@#%***==$$@@++..........+@#%&;;;$#@....++#$$==-**%##++......................@$%&&&==&&&&&===&%#.", +"+#$=;;**===%$#@++...++@%%=*-;;;*****&%#.@#%&***;=%$%==***%%.@$%-*-;====;=***$#@..+@@$$==-*-&=%$#++..+@#%&&;;;====;;;$#@....++@#&=**-==#@@++.+@#$;;;;;%%%;;;;;$#.@#%&*--;;%&&;;-**&%...+@#$$==*--=&%$#++..@@#=;;*-==;==***%$...+@@#$*-*==%$#@+..........++@@$%***%#@....+@#$%==***$#@+.......................#$%&============&&$.", +"@#$=;;;;;;;%%@++....++@$%&*-;;**-***&%#.+#%&;;;;;$$$%%;;;&%.@#$===;;;;;;;&&%$#@...+#$$;;;;;;=%$#@++.+@@##%;;;;;;;&&%#@+....++@#%&;;;&%#@+...++@#&====$$$====&$@.@#%&;;;;;%%%;;;;;&%....@#$%;;;;;;;%$#@+.++##&&=;;;;;;;;;;$$....+@#$=;;;;%$#@++..........++@#$***$#@....+@#$%;;;;;$#@++......................#%&;;;;;;;;;;;;;;;#.", +"@#$=;;=;;;=%$@++.....@@$%&*-;;;*****&%@.@@%%;;;==$##$$=;=%%.@#$&====;;;;;%%%#@+.+++@#$=;;;;;=$$#++....@@##==;;;;;%%$#@+....++@@$%=;=%%#@+...++@#&&&&&$#$&&&&%#@.+@%%;;;;;$%$;;;;=%%..+++#$$=;;;;;=$$#++.++@#&&=;;;;;;;;;=$#....+@#$==;;;%%#@+...........++@##***$#@...++@#$%;;;;;$#@+.......................#%&;;*;;;;;;;;;;;=$.", +"+@##$$$$$$$#@@+......+@@#$%%%%%&&%%%##@.+@###$$$##@@##$#$#@.@@###$$$$$$$$$#@@++...+@@##$$$$$$#@@+.+..+.@@##$$$$$$$#@@+......++@##$#$#@@+++...+@@##$##@#@#####@+.+@###$$$$####$$$$#@....+@@#$$$$$$##@@++..++@##$$$$$$$$$$$#@....++@#=====%$#@++..........+.+@#$$$#@@....+@#$%=;;;=##+++......................@%%;;;;;;;;;;;;;;=#.", +"++@@@####@@@@++.+.....+@@#$$#$#%$%$$#@+.++@#####@@@@@@@#@@@.++@@#########@@@+++....+@@@#####@@@++......++@@######@@@++......+++@@##@@@++......++@@@@@@@@@@#@@@+.++@@###@#@#@#@####@.....+@@@#####@@@+.+...++@@@####$####@@@.....+@@#$$$##@@+.............++@@#$$@@+.....+@@#$$$$##@++.......................@@##$$$%%%%%%%$$$#@.", +".++@@@@@@@@+++........++@@#$###$#$##@@+..+++@+@@@+.++++@@@+..++@+@@@@@@@@@+++.....+.++@@@@@@@++.........+++@@@@@+@+++..........+++@@@++.......+++@+@+++++@++++...++@+@@@+@++@@@@@++....++++@@@@@@@++.+.....++@@@@@@@@@@@@++.....++@@@##@@@+++.............++@@#@@+.....+++@@@#@#@@++........................@@@###############@.", +"....++++++++...........+++@+++@@@@@@++.....+++.+.+..++.+.+.....+.+++++.+.+..........+..++++.++...........+.+++++++.............++.+...+..........+.+.....+.........++++++++++++.+........+.+.+++++.+..........+++++++++.+........+++@@@@+++................++++++.+......+++@@@@+++.........................+++@@@@@@@@@@@@@@++.", +"........+.+...+..........................+++++++.+.......................................+.+++++................................+.+++++++.........................++++++...................+.+++.+............+.+.++++.........++++++...............++++++++.+..................................................................", +"......+.++++++..........................++++@@@+++......................................+.@+@+@++++..........................++++@@@@@@@+++.....................+++@@@@+++................++@+@+++.............+++@@+++......++++@@@++++............+++@@@@@++..................................................................", +"......+++@@+++..........................+@@#@##@@++.....................................++@@##@@@++..........................++@@#######@++.....................+@@@##@@@+++............+++@@#@#@++..........+++@@#@@@@++....++@@##@@@+...........+++@@###@@@++.................................................................", +".....++@@@##@+++........................+@##$$$#@@++...................................+@@##$$$#@@+.........................++@##$$$%$$##@+.....................+@##$$$#@@+..............+@###$##@++..........+@##$$#@@++...++@##$$$#@@++........+.+@@#$$$$$#@++................................................................", +".....+@#$%%%#@++........................@#&&***%$@+++..................................+@#$**===#@+.............+.........+.+@##==;*****$#+.....................@#&&***%$@@++..........++@@%&***#@@+........++@@$***&%@@++..+@#$***=&#@+++.......+++#$%*****##@+......................................................+.........", +"..+.+@@$$&&%$#@++............++++.......@#&=***%$#@++..............++.+.++.+.........++@@$$**=;=##@.......+.++.+.+.........+@@#%==;*****$#@........+.+.+++.+....@#&=***%$#@++...........+@#%&***$#@++........+@#$***&%#@+...+@#$***==$#@++.+......+@$$%*****$#@+.......+.+.+.+++.+..+.......++.+.+.+.+.............+.+.+.+......", +"....+@@%%*-*%$@+++....+.++++++++++......@#$%;;;&%#@@++++........+++++++++++++......+.++@@#%&=;;;$#@....+.+++++++++.+.....+++@#%&***&&&&%#@@...+.+++++++++++++++.@#$%;;;&%#@@+++.........+@#%&;;;$#@.......+++@@#$;;;&%#@++..++#$&&=;;##@++++++.....+@#$%&***$#@++......+++++++++++++++...++++++++++++++..+.....+.++++++++++.....", +".....@@%&*-*%$#@+......+++@@@@@@@++++...+#$%;;;&&$##@@++++.....+++@@@@#@@@@@+++....+++@@#$$==;;;$#@..+.+++@@@@@@@@++.....++@#$&=*-*=&&%%#@+..+.+++@@@@@@@@@@@++.+#$&;;;&&$#@@@++++.....+@@#%&;;;$#@++......++@#$%;;;&%#@+...+@@#&&=;;%##@@@@++....++@@$%&***$$@+.....+@+@@@@#@@@#@@@++...++@@@@@@@@@@@+++.....++++@@@@@@@@++++..", +"...++@@%%-*-%%#@++...+++@@#######@@++...+#$%;;;=&%$###@@@++.+++@@@####$#$##@@++.+++@@@##$$%&=;;;$#@..++@@@###$###@@@++...+@##$&=***&&&%%#@+..++@@@###$$#$###@@@.@@$%;;;=&%$$##@@++...+.+@#$%&;;;$#@+.....++@@#$$%;;;&%#@@....@@#&&=;;%$####@@@+....++@#%&*-*%#@@....++@@####$#$##$##@@+.++@@##########@@+++.+.+@@@###$###@@@+...", +"....++@#$=;===#@+...+.+@#$$%&&&%$$@@++..@@#%;;;==&&&%%##@@+..+@@##%%&&&&&%%%#@+..+@@##%%&&==;;;;%#@.++@@##%%&&%&%$#@@++.+@@$%&;;;;;==&&%#@+.++@@##%%&%&&%&&%$$@.+@#%;;;==&&&%%#@@++....@@#$&===&$#@++...+.@@$%%&====&&$@++..++@#%&&;;%%$&%%%$@+.....+@##%***$$@++...+@$$%%%&&&&&&%&%##@.+@$$%&%%%&&%%%#@@++.++@@##%%%&&&%$#@@++.", +"....++@@#&===&$@@...++@@$$%&&&=&%%#@@++.+@$%;;;=====&&$$#@@.+@@#$%%&&&&=&&&%$#@.+@@$$%&&=&===;;;$#@.+@@$$$&&&=&=&$$##@+.+@#%%&;;;*;==&&%#@@.+@@$$$&&&=&&&=&=%$#.+@$$;;;====&&%$$#@+..++@#$%&===&$#@++...++@#%%&&====&%$#@+..++@#%&&;;%%%&&%%%#@.....++##%***%#@@....@@$%&&&&=&=&&&&&$#@.@#$%&&&%%&&=%%$$#@+.+@@$$$&&&=&&&$$##@+.", +".....++@##$$&&#@++...+@#===*******%##++.+@#%;;;-******;==#@.@@#==;**;;;**-*-$$@.+@#===******-;;;%#@.@@#===**;;;**;==#@@.+@#===****-;;==&#@+.+@#==;**;;;-****=&#.@@#%;;;-******&%%@@...+@#$%;;-**%#@+.....+@#&==;;*****$#@+...+@#%&=;;&=&*-==&#@......+##%*-*$$@++...@#&=************==#.@#&=***;;;;;**&%%@@.@@#==;**;;;**;==#@+.", +".....+++@##$%%#@++..+@@#=;;*******%$#@+.+@#%;;;-****-*;;=$#.@#$=;;*-;;;-*-*-%$@.@#$=;;*-***-*;*;$#@.@#$=;;*-;;;-*;;=$#@.+@#&=;**-**;;;==#@+.@#$=;;**;;;-*-**=&#.+@$$;;**-***-*=&&#@...+@#$%;;*-*%#@@.....+@#&==;;*****$#@+..++@#%%&;*&&=*-==&#@.....++@#%***%#@++...@#&=*-*-***-*-**==#.@#&=*-*;;;;;-*=&&#@.@#$=;;*-;;;-*;;=$#@.", +".......++@@@%%@@+....@@$==;*******%$$@+.+@#%;;;*-*****;;;$#.@#$=;;*-;;;**--*%$@.@#$=;;******-;;;%#@.@#$=;;***;;**;;=$#@.+@#&==***--;;=&&#@+.@#$==;-**;;-*-**=&#.+@#%;;;*******=&&$@...+@#$%;;-*-$$@++...++@#&==;;*****$#@++..++#%&&;;==&-*==&#@....+.+##$***$$@@....@#&=***-*-***-**==$.@#&=*-**;*;;**=&&$@.@#$=;;**;;;**;;=$#@.", +"........++@@@@@++...++#$%&&=====**&%%@@.+@#$;;*;;%%%&&***%$.@$%***=&&%%&&*-*%$#.@$%***&=%%&;;;;;$#@.@$%**-&=%&&=&***%$@.++@#$%==;;;%%$$#@@+.@$%***=&%%&;;;;;%$#.+@#%;;;;;%&%==;;;$#....@@#$$%***%#@++....++@##$%%%&&**%#@++.++@#%&&*****==%$#@@.....++@$%*-*%#@@....@#$%;;;==;;;=;==;=$.@#$%;;;;;&%&==;;;$#.@$%***==%%&&&***%$@.", +"..........++++++.....@@$%%&=====**&%%#+.+@#%;;;;;%%%&&-**%$.@$%***&&$%$&&*-*%#@.@$%**-&&%%%;;;;;%#@.@$%***=&&%&&=*-*%$@.++@#$$&=;;;%$##@@+..@$%***=&%$%;;*;;$#@.+@#%;;;;;%%%==;;;$#....++@#$%-**%##+......++@@##$%%%**$$@+...+@#$&=***-*=&$$#@+......@@#$***$$@+....@@#%;;;===;=;;==;=$.@@#%;;;;;%%%==;;;$#.@$%*-*&&%$%&&-**%$#.", +"...........++....+..+@#$;;;**;;;--&&%@@.+@#%;;;&&%$%%%***%$.@$%*-*%$$##$$%&%$#@.@$%***%%$$%&=;;;$$@.#$%---****-**--*%$#.+.+@#$===;=$$#@+++..#$%***==%%%;;;;;%#@.+@#$;;*&&$$%%&;;;$#....++@#$%***%#@@......+++@@@#$%%**%#@@...+@#%&&*--*-&%$#@++......+@$%*-*%#@@....+@$$;*;===;;====;=$.@@$$;;;=&$$%%=;;;$#.@$%***%$$$$%%***%$@.", +".............+......+@#$;;;*-;*;**&&%#@.@@#$;;;&&$$$$%***%$.#$%***%$$###$%%%$@@.#$%***%%$$$&=;;;$#@.#$%-*-**-*-***--%$@..++@#$===;=$#@++....@#%*-*==%%&;*;;;$#@.+@#%;;;&&$$$&=;;;$#.....+@##%***%$@+++........++@#%%**$#@+..++@#%%=**-**&%$#@++.....+@##$***%$@+++..@@#%;;;&==;=;===;=$.+@#%;;;&&$$$&&;;;$#.#$%***%$$##$%***%$#.", +"....................+@#%;;***;;;--&&%#@.+@$$;;*&&%$$%%***%$.@$%***%$$####%$%##@.#$%***%$$$%&&;*;%#@.#$%-*-*****-*-*-%$#..++@#$==;==%#@@++.+.@#$===*******;*;$#@.+@#%;;;&&$$$%&;;;%#.....+@#$$*-*$$#@+.+......+.@@#$%**$$@++..+@#%&&**-*-&%$##++...+.+@@$%***$$#@+.+.+@#%;;;==;=;====;=$.+@$$;;;&&$$$&&;;;%#.@$%***%$$$$$%***%$#.", +"....................@@$%***&&&&&**&&%#@.@@$%;;;;;%$%&=*-*%$.#$%*-*=&$###$%%%$#@.@$%*-*==%%%;;;;;%##.@$%***;;=&&&==;=%#@..++@#$===;=$$#@+++..@@#&==*-*-*-*;;;%#@.@@#%;;;&%$$$%=;;;%#.+.+++@#$%***%$#@@+.....+.++@#$$%**$#@++.++@#%&=;;=;=**%$#@+..+.+@@#$%*-*%$#@@+..@@#%;;;&&;=;;===;;$.@@$%;;;&&$$$&=;;;%#.@$%*-*=&$$$&=-**%$@.", +"....................@@$%***%&%&%**&&%$@.@@$$;;;;;%%%==***%$.@$%***=&%$$$$&&%%$@.@$%**-&&%%%;;;;;$$@.#$%*-*==&=&=&;==$$@..+@##%==;=;%$##@@+..+@##%%&&&&&==;;;$#@.@@$$;;;&&$$$&&;;;%$...+@@#$$%-**%$$#@@+..+.+@@@@#$%&**$$@+..+@@#%&=;*=;;**%%$#@...+@@#$$%*-*%$$#@@+.@##%;;*&=;;=====;=%.+@$$;;*&&$$$&&;;;%$.@$%**-==%%%&=***%$@.", +"....................@@$%***%&%&&**=&&##.@#$%;;*;;&%%==*-*$$.@#%***==%%%%%&&&%%@.@$$***==%%&;*;;;%$#.@#%**-;;&&&=&;;=$#@.+@@#$%===;=%%$$#@++.++@@#$&&&&&==;;;$#@.@#$%;;;&%%%%%=;;;$$.++@@#$$%%*-*%%$$#@+..+++@##$$%%&**$#@++..@#$&&=;;;=;**&%%$#..++@#$$%%***%%$$#@+.+#$%;;;=&=;;;===;;$.@#$%;;;&&%$%&=;;;$$.@#%***==%%%==*-*$$@.", +"....................+@$%*-******-****$#.@@&=***-*-**-*===$#.@#$===**********&&#.@#$==;********-*=%#.@#$===*-*-******%#@.+@#&=;*-*-***==&#@+..++#$$&&===;;;;=$@@.@#&=--*-*%%%**-*-&&..+@@&==*-*--**==&#@...@@$%%&&=;;;;$#@+..+@#$***;;%&%--***&%..+@@&==-*---**==&#@.@#%=*-*;;;==-*;=*-&.@#&&*-***%%%**--*=&.@#$===*******===$#@.", +"....................+@#$**-*-*-**-***$#.@#%=-*-*******==&#@.@@#&==-******-**&%@.@@#&==*-*-*-**-*&&#.+@#&==*****-****$#@.+@#&=;**-*-**==&@@+..+@@$%&====;;;==#@@.@@&&*-***%%%***-*&&..+@#&=;**-*-**==&@@.++@#%%&&=;;;;;$@@++.+@#$***=;%%%-*-**&&.++@#&=;**-*-**==&@@.@#&=*-*;;=;=**=;**&.@#&=**-**%%%***-*&&.@@#&==**-*-*-==&#@+.", +"....................+@@#%%%&&&&&%&&%%##.@@$%%&&&%&&&&%%$##@.+@##$$%%&%&&%&%%$#@.+@##$$&%&&&&&&&%%#@.+@##$$&%&&&&%%%$#@@.+@#$%%&&&&&&&%%$@@+.+@#$%;;;;;;;;%$##@+.@#$%&&&&%$$$&&&&%%$..+@@$$%%&&&&&&%%$@@..+@#&==;;;;;%%#@++..+@##&%&%%$$$&%&&&$$..+@@$$%&%&&&&&%%$@@.+@$%&&&%%%%&&&%%&&%.@@$%&&&&&$$%&&&&%%$.+@##$$%&%&%&%%$##@+.", +".....................@@@$$%$%%%%%%%%$#@.+@#$$%%%%%%$%%##@@+.++@@##%%%%%%%$$$#@@.++@@#$$%%%%%$%%%$#@.++@@##%%%%%%%$$$@@+.++@$$%%%&&%%%$$#@+..+@#$%;;;;;*=;$$#@+..+@#$%&%%%$#$%%%%%$#..++@#$$%%%%%%%$$#@+..+@#&==;;;;;%$#@+....+@#%%%$$$##%%%%%$#.+.@@#$$%%%%%%%$$#@+.@@#$%%%%%%$%%%%%%%$.+@#$$%%%%$##%%%%%$#.+++###%%%%%%%##@@++.", +".....................++@##$$$$$$$$$$#@+.+@##$$$#$$$$$##@@++..++@@@#$$$$$$$##@@+..++@@@$$$$$$$$$$##@..++@@@#$$$$$$##@@++.++@##$$$%%%$$###@+..++#$%=;;;;;=&$#@+++.+@##$$%$##@@$$$$$##..++@###$$$$$$$###@+.++@@&==;;;;=$#@++...+++@$$$##@@##$%$$##...+@@##$$$$$$$###@+.+@@#$%$$#$#$$$##$$#.++##$$$$$#@#$$$$###..++@@##$$$$$##@@++..", +"......................+++@@@@@#@#@@@@++..++@@@@#@@@@@@+++......+@@@@@@@@@@@@++.....+++@@@@@@@@@@@++....+@@@@@@@@@@@@+....++@@@@@@@#@@@@++.+.++@@#$$$$$$$#@@++....++@#@@@@@@@@@@@@@+....++@@@@@#@@@@@++...+@@##$$$$$##@@.+.....++@@@@@+@@@@@#@@+....+@@@@@@#@@@@@++..++@@@@@@@@@@@#@@@@@..++@@@@@@@@@@@@@@@+....+.@@@@@@@@@++....", +".......................++++@+@@+@@++++....+++++@+@@++++.+........+++@+@@++++.+.....+.+++@+@@+@+++++......+++@+@++++.+.+..++++@@@@@@@@+++.....++@@@######@@++.....++++@@+++++@@+++++....+.++@+@+@+++++.....++@@#####@@+++.....++++@++++.+@+@++++.....+++@@+@@+++++...+.++@@@++++@++@@+++..++++@@++++++@+@+++....+.+++@++++.......", +"......................................................................................................................................................................................................................................++++++..........+.+++++++........+.++++++.................................................", +"....................................................................................+.+..+........................................................................................................................................++++@@@@++.+.........++@@@++........+.++@@@@++.+..............................................", +"....................................................................................+.++++.........................................................................................................................................+@@@$$#@@+........+++@#$$@@++......+.@@@$$@@@++..............................................", +".................................................................................+.+++@@@++++....................................................................................................................................++@@##%%#@@++........+@#$%$#@+........+@##%%##@@++.............................................", +"..................................................+..............................+.+@@@#@@+++....................................................................................................................................+@##$$%%##@.+......++@@$%%%#@@+.......+@@#%&$$##@++............................................", +".....+.+...+................+.++.+.+.+......+.+..+...................+.+..+.......+@#$$&&#@++.+.........++......+...........+..+..+...+...+.......+...+.....+.......+.++...+.+.+.......+..+.....+....+.......+.+.++.+.+.+.......+@@#====&#@++........+@#$***$#@+.......+@@#&====#@++............................................", +"..++++++++++++++........++++++++++++++.....++++++++++++++........++++++++++++.+.++@@$%%&=##@@+++......++++++..+.++++......+++++++++++++++++..++++++++.+.++++++..+.++++++++++++++....+.++++++++.+++++++.....+.++++++++++++.......+@#$=;;&&#@++.+......+@#$***$#@++.......+@#&&;;=$#@++...........................................", +"+++@@@@@@@@@@@+++++...++++@@@@@@@@@+@++...+++@@@@@@@@@@+++.....+.+++@@@@@@+@++...+@#%%&;;$$#@@+++.+.++@+@@+++++@@@@++++.+++@@@@@@+@+@@@@@@+..+++@@@@+++++@@@@@+..+++@@@@+@+@@@@@+++.+++@@@@+++++@@@@@++...+++@@@@@@@@@@@+++....++@#$***%$#@+........++@#%***%#@+.......++@#$%***$#@+............................................", +"++@@####$#####@@+++.+.++@@##########@@+.++@@@##@#@#####@@++....++@@@#######@@@+.++@#%&&;;%$$##@@++..@@@#@#@@@+@@@#@@@++.++@@#####@#@#####@@.+@@@###@@@@@@@##@#@.+@@#####@#@####@@++.@@@##@#@@@@@@##@@@@...+@@@####$####@@@+.....+@#%***%##@+........++@#%*-*$$@@.......+++##%***%#@++..........+.+..............................", +"+@#$$$%$$$%$$$##@@+..+@@##$$$%$%$%$$$#@.+@@#$$$$$$$$$$$##@+....+@@#$$$%$$$$$#@@.+@#$&&=;;%%%$$#@@++.@##$$$##@###$$$#@@+.+@#$$$$$$$#$$$$$$$#.+@##$$$$#####$$$$##.+@##$$$$$#$$$$$$#@+.@##$$$$##@##$$$$$#@.++@@#$$$%$%$%$$$#@@....++##$***%$@++........++##$***%#@++........@@#%***%#@+.........++.+++++++.+.+.....................", +"@#%&***;;***;;%%$@@.+@@$%%;;***;=***&&#.+@#&==**&&&**;;=#@+..+++#$$=;***;====#@.+@#$***-******%$#++.#&&***$$##$**===#@+.@#%&*****%%%*****&%.@#&&***==$$$=&***&&.@#$*****%%%*****$#@.#&&***=&$#$&=***&%#.++@#==;*******===#@...+.@#$%*-*%##++........++@$%***%#@@.........+@$$-*-$$#++.....++++@@@@+@++@++++.....................", +"@#&=***;;***;;&%%#@.+@#%%&;;***;;***&&#.@@#==;**==&**;;=$#@...@@#$%;;***;;;==$@.+@$%**-*-*****%$#@+.#&&***%%$$$**;==$@@.@#&=*****%&%*****=&.@#&=***==%$%==***=&.@#$*****%&%*****$#@.#&&***==$$$==***=&#..@##==;*******;==#@....+@#$%***%#@+..........@@#$***$$@++........@@#%***%$#@++....++@@@#@##@##@#@@+.....................", +"@#&=***;;***;;=&%$@.@#$%&&;;***;;***=&#.+@#==;**===**;;;$#@.++@#$%%;;***;;;;=$#.+@#%***-******%$#@..#&=***%%$$$**;;=$#@.@#&=*****&&&*****=&.@#&=***;=%%%;;***=&.@#$*****&&&*****$#@.#&=***==%%%==***=&#.++#$=;;*******;==#@....+@#%%-**%##++.........@@$%*-*%#@@.........+@#%*-*&%#@++..++@@##$$$$$$#$$###@.....................", +"@#$%***-*=&=;;***$#.@#$***;;=&=*-***%$#.@@#%%&*****=&;==$#@..+@#==;**==&;;;;;$@.+@#$==;;;=&&&%##@++.#%%***&%$$$&=;;;$#@.@#$%***==%&%;=***%$.@#%&*-*&&;;;&&***&%.@@$&&=**&&&**=&&$@@.#$%***==%%%=;***%$@.+@##;;;==;=;*-&&%#@...++@#=;***%#@+.........++@#$***$$@++.......+@@$$***;=##++...+@#%&&**===%%;;=##.....................", +"+@$%;;;==%%%%%***%$.#$%***&%%%%==;;;%$@.+@@$%&*-*-*&&===##+..+@#=;;**&=&;;;;=$#.+@@$&==;;=&%%%#@@+..#$%***&%$$$==;;;$#@.+#$%***==&%&==-**%$.@#%&***&&;;;=&-**%%.@@#%&=**&%&**=&%#@+.@#$&==**%%%**==&$#@..+@$=;;;===;*-&%%#@...+@@$==***$$@++........++@$%*-*%#@++........+@#%***;=##++..+@@$%&&**===%%;;;$#.....................", +"+@#$;;;==$%$%&*-*%$.@$%-*-%%%$%&=;;;%#@.++@#$%**&&%%$$$##@+.++@#%&&*****&=&&%#@.++@#%&=;;%%$##@@+.+.@#%;;;&%$$$&&;;;$#@.+@#$&==;;%%%;;==&$#.@##%;;;==--*&=;;;%$..@@#$$==***=&%$#@@+.+@$&&=**&%%**=&&##+.+@@#%%&&&--*==%$#@+....@@#=;***%#@+..........@@#$***$$@@........++##$***;=#@++..+@#$***==**-**;==$#.....................", +"+@#%;;;==%%%%&***%$.#$%***%%%%%=;;;;$#@.++@#$%**&&%$##@@@++.++@#%&=**-**=&&&%$@.++@#%&=;;%$##@@++.+.@$$;;;&%##$%&;;;%#@.++@$%&=;;%%%;;&&%$@.+@$$;;*==*-*==;;;$#..+@#$$&=*-*=&%##@++.+@@$%%*-=&=**&%$@@+..+@@$%%&&***=&$$#@+....+@#%%***%##+.+........@@$%*-*%#@@........++@$$***%%#@++..+@$%***==***-*;;=$@.....................", +"+@#%;;;-*=&=;;***$$.@$$***;;=&=*-;;;%#@..+@@#%**&%%##@@@++..++@#%&&*****==&&%##.++@#%&&;;%$##@@@++..@#%;;;&%$$$&&;;;$$@..@@#%&&;;%&%;;=&%#@.+@#%;;;==-*-=&*;;$$.++@@#%&=***=&$$@@+....+@#$==*--==$#@+....+@#$%%&&--*=&%##@+.....+@#%-**%#@++.........@@#$***$$@+.........@@#%*-*$$@++...+@#$-**==-****===#@.....................", +"+@#%;;;-*===;****$#.@#$***;;===-*;;;%#@..+@#$%**&%%##@@+++..++@#%%&&=;=;**;;=$#.++@@%&&;;%$$###@@@+.@#$;;;&&$$$&&;;;%#@..+@@$%%**&&%**%$#@@.+@#$;;;;;*****;;;$#..+@#$$==***==%##@++..++@#$==-*-==##@++...+@@$%%**;=;&%&%$@@....++##%***%##++.........+@$$*-*%##++........+##%***%#@++...+@@#%%%$$%%%&&%$$#@.....................", +"+@#%;;;;;***;=&%%#@.+@#%%&;;;;;;;;;;$$@.+@@#$%**&%%$#@@++....@##%&&&&;=;**;;;$#..+@@%%=;;%%$$$$##@+.@#%;;;&&%%%&&*;;%$@...+@#$%**&&&**$$@@+.+@#$;;;*;*****;;;$#.+@@#$%==-**==%$#@@+...+@@$&&*-*%%#@+....++@#$%&**=;=&%&%%#@....++@#$*-*$$@++........+@@#%***%#@+........+@@$$-**$$@@.....+@@$$$$$$$$$%$$#@+.....................", +"+@#%;;*;;***;=%$$@@.+@@$%%;;;;;;;;;;%#@.+@#%&&-*==&&%##@++...@@$;;;;;=====***%#..+@@$%&*-==&;;=&&#@.@#$;;;;;&&&;;***%%@..+++@#$==**-==$#@++.+@#$&==*-&&&--==&$@.+@#&&=**&&&**==&#@+..+@@#$==;;;$$@+++....+@$==;**=====;;=$@....++@$$***%##@+.........+@#%***$#@@+........+@$$**-$$@++....++@@@@@@#@##@@@@++.....................", +"+##%;;;&=%%%$$$#@@+..+@@#$$%%%&==*;;$$@.+@#&&=**==&&&$#@+++.+@#$;;;*;===;=--*%$..++@$%&**===;;==&#@.@@#=;;;;&==;;***%%#....+@#$==-**;=$#@+...+@#&&=-*&&&**=&&#@.+##&==**&&&**==&#@@.++@#$%=;;;=%##+.....+@##=;;-*====;;;;$#.....@@#$***%%@@++.......++@#$;;;%#@+.......++@#$%***$#@+......+++@@+@+@@@@@+++......................", +"+@$%;;;==%%$$#@@@++.+++@@@#$$%%&&;;;%##.@@$&&=*-===&&$$#++..++@$;;;;;=====*-*$#..++@#$%**===;;==&#@.+@#==;;*&=&;;***&$#...++@@$==***==#@@+..++@#%&&**%%&-*&&%#@.@@$===-*&%&**===$@@.+@#$%%;=;;;$#@++....++@$==;**====;;;=$#.....+@#%***%$#@++.......++@#$=;=$#@+.......++@#%%***$#@++.........+.+.+.+.+..+......................", +"@@$%;;;=&%$$#@@+++.....++@@#$$%==;;;%$@.@#$*****;;;**%$#@++.+@@#==;=;*****&&%$#...+@@#$&&***;;&%$@@.+@##$%;;***;;***&%@.....+@#$%;;;%$#@+....+@@$%%==%%$==%%$@@.@#$***;;&%&*****$#@.@##***-****$#@++....+@@#===*******===#@....++@@$***%%#@++........++@#===#@+++.....+.@@#%%***$#@+.......+.......+.+..........................", +"@#&=--***=&&#@++.......+.+@#%=&**-*-&&#.+##*****;;;**$$#++...+@#&&===*****%%%#@....+@@#%&***==%$$@+.++@##$=;***==***%%@.....++@#$;==$$@@++...++@#$%&&$#$&&%$$@+.+##***;=%%%*****##+.@#$***---**$#@+......+@#&==*******==&#@.....+@@#%%%==$#@++.......++@##$##@+.......++@##==&%%#@@+............................................", +"@@&&**-**=&%@@+.........++@#%&=**-**=%#.+@##$$$$$$$$##@@+.+.++@@##$$$$$$$$$#@@+...+++@@##$$$$###@@+..++@##$$$%$$$$$$##@.....++@@##$##@@+......+@@@#########@@++.+@##$$$$$##$$$$##@+.+@#%&&&&&&%$@@+.....++@@##$$%$%$$$$##@@......+@@$$%&&##@+.........++@@@@@+++.......+@##&&%$$@@+.............................................", +"@#$%&&&&&%$$@++..........++@$$%&&&&&%$@.++@@##$#$####@@++.....+@@@@########@@@......++@@@####@@@++....+++@@####$####@@+......++@@@#@@@+........++@@@@+@@@@@++++.++@@###@#@#@###@@@+.+@#$%%%&%%%#@+........+@@@######$###@@+.......+@@####@@+++........+.+@++++.........++@@####@@++.+...........................................", +"+@#$%%&&%$$#@+++.........++@#$$&%&&%$#@..++@@@@@@@@@@++.......+++@@@@@@@@@@++.+......+++@+@@@@+++.......++@@@@@@@@@@@++.......+++@+@++.+........+.+++++.+++++...+++@@@@@@+@@@@@@++..+@@$%%%%%$$@@++........++@@@@@@@@@@++++......++++@@@@@++...........+..++............++@@@@@+++..............................................", +"+@##%$%$%##@@+...........+++@##$%$$$$#@..+.++++++++++.+........+..++++@++.+.+.........+.++++++..+.......+..++++++++............+.+.+..................+...+......+..+.++.+.++.++.+....@@@@#@#@@@+..........+..++++++++++..........++.+++++...............................+++++++................................................", +"+++++++++++++++...............................+.++.+.+...............+..+................................+.+....+.+...........++.++..............+.+++++++++................................+.+.+................+..+...........................................................................+.+.............................", +"+++++++++++++++................................+++@+++..............++++++++...........................++++++.+.+++++.+........+@+++++...........++@@@@@@@+++.+...............+.........+.++++++++.+...........++.+++.........................................................................++++++++..............+..+........", +"+++++++$$+$$$@@+.............................+++@@@@@+++........++++@@@@@++++.......................++++@@@@@+@+@+@@@++.....+++@@@@@++........+++@@@######@@@++........+.++.+.+.........+.++@+@@++++........+.++++@+++++....................................................................+++++@@@+++++........++++++++++.....", +"@++++$$%%%%$$%$$+...........................+.+@##$##@++.......+.+@@@@###@@++........+.+....+.+.+....++@#####@@@@###@@+......+@##$#@@++......+.+@@#$$$$$$$$#@@+......+++++++++++.+.....++@@@@##@#@@++++......++@@@@@@@+++..................................................................+++@@#@#@#@@+++......+++@@@@@@++++...", +"@++$%%%===%$$%%%%...........................++@##===$#@++......++@@$$%%%%%#@@++...++++++++..++++++..++@#%%%%%$#$%%%%$#@....+++@#===$@@+......++@@#&&*****==&#@+....+.++@+@+@@@@+++...+++@@#$$%%%$$#@@++....+.+@#$$%%##@++................................................................+++@@#$$%%%$$#@@++...+.+@@@#####@@++...", +"@++%%=********=%%+............+.............+@@$$;;;$##@+++...+++##$%%&&%%##@+.....++@+@+++@+@+@+++.+@##&=&&%%$$%%&&%$@.....+@#$;;=$#@+.......@@#$==*****===#@@...+.++@@#@@@@@#@@+..+.+@##$%%%&%%$$$@@+.....+@@$$%%%%$#@++................................................................+@##$%%%&%%$$##@+....+@@#$$$$$$#@@+++.", +"##$%=**********=%$.........+..+...........+++@#%&***&%##@++...+@@$$*******%$#@+.+++@####@@@@@####@+.+@#%***-*%&&*-***$$.....+@#$***$#@++....++@$%%**====;;;;$#+...++@##$%&##$==#@++.++@@%%&*******&%%#@...+++@#&==&=**$@@++.........+...+..........+.+..+.++............................++@@%%&*******&%%#@....+@#==*****$$#@.+.", +"@##%=******-*-*=%$+.......+.+++++.+......+.@@#$&&-**&%$##++...+@#$%*******%%#@+..+@@$$$$$#$#$#%$$@+.+@$$-*-*-&%&-*--*%#....+@@#%***%#@+.....+@@$%&**=====;;;##@....++##$&&#$#==#@++.+@@#&&=*******=&&#@....+@#$==&=&**$#@+.......+.+.+.++++++++...++++++++++++++.+......................+@@#&&=*******=&%#@...+@@#==*****%$#@+..", +"@@$$**---*******%%+.......+.++@++++......++@#$$&&*-*&&%$#@+.+.+@#$%*****-*%$#@+..+@#$%%%$%$%$%%%$#@.+@#%*-**-&&&*-*-*%#.....+@$$*-*$$@@.....+@#$%&-*===;=;;;#@@....++#$$%&##$==#@++.+@#$&&=*******=&&$#..+++@#$=====**$#@++......++@+@++@+@++++.++++@@@@@@@@@@@@+++............+........+@#$&&=*******==&$#....@@#=;*****%$#@+..", +"+@#%*****-----**%$........+@@@##@+++....++@#%&=*****-*&%$@+..+@@%%&**&%%%%$##++.++##==;*******;==##.+@#$&&=**%&%**=&&$#....++@#%***%#@++....@@#&&=*-===%&&%%$@+...++@@##$$###$$#@+..@@$%***;;***;;***$$...+@#$$;;;;;**$$@++....+++@@#@#@@#@#@@+.++@####$#$#$###@@++.........+.+..+..+...+##%*****-**;;***%$...++@#%%%&&&&$##+++.", +"+@$$******----**%%+.....+.+@###$#@+++...++@#&&=*-****-%%$@@..+@#%&&**%%%%$$#@++.+@#$=;;*******;;=$#.++@#&&=**&%&**=&&#@....++@#%***%#@++....@#$&==*-===&%&&%#@+.....+@@@##@@#$#@@++.@#$%***;;*-*;;***%$...+@#$%=;;;;**%##++....+@@##$#$$#$$###@.+@##$$%$%$%$%$$$#@+...+++++++++++++++...@#$%********;;***%$....+@@$%%%%$%##@++..", +"+@#%***-**-*-***%$.......++@$%%%$@++....+@#$=;;==%%%;;&%$@+.++@#%%=;;%$$##@@++..++#$=;;;;===;;;;=$#..+@#$%%**===**%%$#@....++##$-**$$@+.....@#$***==***;;&%%#@+.....++@@@@@+@@@++...@#&=;;;-*===;;;===&..++@$%&;;&&&**%$#@+..++@@#%&===%%;=;%%@.@#$*************$#@...+++@@@@@@@@@@@++..@#&===;**===**====&.....+@@@#####@@++.+.", +".@#%************%+......++@@%%%&%#+++...+@#$;;;==%%%==%%$@+..+@#&&&;;&%$##@@+...+@#$=;;;;&&=;;;;=$#.+.+@#%%**===**%%#@@....++@#$***$#@@+....@$%***;=-*-;;&&%##+........++.++++++..+.@#&=;;;**===;;=;==&..+@@%%&;;=&=**%$#@+..+@@#$==;=;%%;;;&%#.@#$*************$$@.+++@@#####$####@@@+.@#&====-*===*-=;==&.....++@@@@@@++++....", +".@#%***-**-*-*-*%+.......+@@%&&%%#@+....+@#$;;;=&%%%==%$#@+.+@##&&=;;%%%$#@+++..+@#$;=;;;===;;;;;$#..++@#$%**===**%$$@+.....+@#$*-*%#@+.....@$%***=;**-;;&&%$@@...........+...+.....#$&=;;;-*===;;====&.+.@@$%&;;&&&-*%$#@+.+@@#$$==;;;&&;;;&%@.@#$*************%$@..+@##$$$%$$%$$$##@+.#$===;=**===**====&.........+++++++.....", +"+@#%*****----***%$.......+@#$$%%%#@++...+@#$;;;=&%$%%$$#@@+.+@#$***-****%%@++...+@#$;;;&&%&%==;;;$#..++@#$%=;---;;%$#@+....++@#$&&&$#@++....@#%**-;;===;;***%#@........+............@$=;=;;**%%%=====;=...+@$%%;;;;;;;&%$@+.+@#%&&**&&&;;;;;$$@.+@#%%&&&&&&=&***%$#.+@@&&=**********##+.@#=;===-*;;;;;===;=.....................", +".@$$****-*******%$......++@#$%%%%#@++...+@#%;;;&&%%%$%$#@@+.+@#$*-*-****&%@@++..+@#$;;;==%&%==;;;$#....@@#$;;*-*;;%$#@+.....+@#$&&&$#@+.....@#$***;;&=&;;-**%$@.....................##=;;;;**&&%&====;=.++@@$$%;;;;;;;%%$@+.@@$&==-*&=&;;;;;$#@.@@#$%%%%%%&&=***%$@.+@@&&=**********$#@.#$=====*-;*;;;===;=............+........", +"+##%*-*****--***%@.......+@#&====##++...+@#$=;;;;&&&==%$#@+.+@#$&&&*-==&$$#@++..+@#$;;;;;&=&;;;;=$#..+.@#$%==-*-==%$#@+.....+@#$;;;$#@++....+@@$%&;;-**;=-**%$@.....................@#%&**********;;;&%..++@$%&*******%%$@+.@#$***=;===*-&&%$#@.++@@####$#$$%***%$#.+@@$%%&&&&&&&&&%#@+.@#&&;;;-*===;;;;;&%.....................", +"+##%***---******%@......+@@$&====$@@++..++#$=;;;;&&&;;%%#@+..@@$%==**&=&%$#@@++.+@#$=;;;;===;;;;;$#...+@#$%=;*-*;=%$#@+....++@#$;;;$#@+.....+@##$%%%=&=*-;;;$#@.....................@#%&**-**-*-**;;;&%..++@#%%*******%%$@+.+#$***=====**&&%$@@..+++@@@@@##$%***%$@..@@$$%%%&&&&&%%$#@+.@#%&;;;**===;*;;;&%.....................", +"+##%*----***--**$#......+@#$**-*-$$@+...++@#==;;;==&;=%$#@+.+@@$%&=*-==&%$##@@+.+@#$=;;;;&==;;;;=$#...+@#$%==-*-=;%$#@+....++@#$;;;$#@++....+@##$%%%&&=*-;;;$#@.....................@#%%*********-;;;&%..++@#$%*******%$$@+.@#$**-=;===-*=&%$#@..++++++++@@#$***$$@..+@##$%%$%$%%$$$@@+.@#%&;;***===;;;*;&%.....................", +"@+$%**-*****-***%$......+@#%***-*%#@@....+@#$%%;;-*-;;%$#@+..@#$&==**%%%%$%$$@@..@@$==;*****-*;==$@...+@#$%=&-*-&&%$#@+.....+@$$***%#@+.....+@#&==&&%&%**=&&##+.....................+@#%=;;;;;;=*;;;=$#...+@#$$%&&=&&&$$@@+.@@#&&=**=&=;;;;;$#@......+++++@@#%%%$@@..++@@@@@######@@@+..+@#$=;;**===**;;=$#.....................", +"@+%%******-*****%$......+@$$***-*%##+...+++@#$%;;-*-;;$#@@+.+@#$&==-*&%%%%%%%#@.++@$===*******;==#@...+@#$%&&*-*=&%$#@+....++@#%***$$@@.+...+@$&==&&%%&**&&%#@+.....................+@##=;;;;;;;;;;;=$#..+.+@##%%&%&%$##@++.+@#%&&**=&=;;;;;$#@..........++@@$$$#@+..+.++@@@@@@+@@@++...+@#$==;**===**;==$#.....................", +"#+$%=**********=$$.....++@#%*-*-*%#@@.....+@@##%%***%$$@@+..+@$$*-**-********%#.++@#%%%%%%$%$%%%%#@..++@#%%**-*-**%%$@+.....+##$***%#@++....@@$==;&&%&%**&%$#@+.....................++@#$%&==***;;%%$#@...+++@@@######@@++..+@@#$%==;;;&&;;;&%#...........+@@@@@@++...+++.+.+.+++++.....++@#$%%==***=;%%$#@.....................", +"#+%%==********=%%#......@@#$***-*$$@++.....++@#$%*-*%$#@++..+@#%*-*-******-**$#.++@@$$%$$$#$#$$$$@@..++@$$&**--***%$$@+.....+@$%*-*$$@+.....@##;;;*******%$$@++.....................+++@#$%&=***==%$#@@....+.+@@@@@@@@+++.+..+@@#$&==;=&%;;;&%#............++@@+++........+.+......+....++@@#$%==***;=%$#@@.....................", +"@+$%%%%&&%%&&%%%##......+@#$*-*-*$#@++......+@@#$***$#@++...+@#$**-*-********$#...+@#####@#@#@$##@+...+@#$%***--**%$#@+....++@#$***%#@++....+@$=;;*-*****$$@@+.......................++@##$&&***=&$##@+.....++.+++@+++++.....++@@#&&===%%;;;%$@.............+.+.+.........................+@##$&=***=&$$#@+.....................", +"@++$$%%$$%%$$%$+#@......+@#$==;==$#@+........+@@#%%%##@+....+@#$%&&&&&&&=&&%%$@...++@@@@@+@++@@@+++..++@##$%&&&&&%$$#++....++@#$***$#@+.....+@#%%&==&&&%%##@++.........................++@##$$$$$##@@+.........++.+............+@@##$$#$#$#$##@...............+............................+@@@#$$$$$##@+++.....................", +"+#####$##$#$$###@+.....+++@#&&===$@@++.......++@#$%$#@+.+...++@#$%%%%&%&%&%%$#@.....++++++.++.+++.....++@##%%%%%%%##@++.....+@#$***$#@++....+@@$%%&&&&%$##@++........................+..++@@@####@@++...........................+@@@@@#@#@#@@@+.............................................++@@@####@@++.......................", +"+@@@@@@@@@@@@@@+++.......@@#&&=&&#@++........+.+@@@@@++......++@@##########@@@+...+......+......+......++@@@######@@++.....++@@$%%%$@@+.....++@#$$%%%%$$#@++............................+.+@@@@@@+@.+............................++@@@@+@+@@+++.............................................+++@@@+@@++++.......................", +".........................++@#####@@+...........+++@+++........++@@@@#@#@@@@@+++......+................+.++@@@@@@@@+++.+......+@#%%$#@+.......++@@@@#@#@@++...................................+..++.+..............................+....++++.++...................................................+++.++.........................", +"........................+.++@@#@@@+.............+.++..+.......+.++++++++@++++..............................++++++++.........+++@#$$@+++......+.+@@@@@@++++.+.................................+......................................+.....+........................................................+............................", +"......++++++++................................+++++++++..........++++++++..................+................................+++++@+@@@+@++.................................................+.++++...............................................++@@@@@@@+..........+@@@@@@++...........++@@#@#@@@++............................", +"....+++@@@@@+++...............+.............+++@@@@@@++........+++@@@@@@+++...............+.+................................+@@@@#@#@#@@@+..............................................++++@+@++.............++++.+...........................+@@##$##@+++........@@##$##@+++.....+...+@#$#$$##@@+++.++.......................", +"....+@@#$$$#@@++...........+..+.+...........+@@#$$$$#@@++......+@@#$$$$#@+++..........++++++++...........................+++@@@$$%%%%%%$$@@..............................................++@@###@@++.........+.+++@++++.........................+@$%===$$@++....+...@$%===$$@++..++++++.@$$=====%$#@+++.+++..........+.++.......", +"..++@@#$%%%$#@@+...........++++++.+.......++@@#$%%%%$@@++....+++@#$%%%$$#@+++..........+++@@@+++........................+.+@@##%%%%&%&%%%#@............................................+++@@$$%$@@+.........++@@@@@#@@+++.......................@@%%===%$@@+++.++++.@%%===%$@@++++++@@+.@$%=;;;=%%$@@+++@@@.........++++++++....", +"..++@#$$%&%%$#@@++.......+.+@@@@@++........+@#$%%&&%%##@++....+@#$%%&&%%$#@++.......+++@@@#@@@++.+......................++@##$%%&&&&&&&&%#@............................................++@##$%%%#@@+........++@##$#$##@@++......................@#%&;;;%%@@+.+++@+@.#%&;;;%%#@+++@@#@@@.@%%=;;;;%%$#@@@@@@@.......+.+@@@@@++....", +"+++@#$;;&=&;=$#@+.+.......+@@$$$@@++......++@#=;&&=;;%$#@++...@@#=;&==;=%$#+++.......+@@$$$&%@@.+.....+...+.............+@@$==;**---*-***$#..........................................+.+@#$&=*-*$#@++.....++@@#%&===%%#@+++.....................@@%%***&%#@+++@@@##.@%%***&%#@@@@#$$=&@.@&=&===;==&##@#$%&$........+@@###@@+....", +".+@@#$;;===;;$##@+......++@@#%$%#@@++......+@#=;===;;%$#@....++@#=;===;;%$$@+.......++@#%%%&&@@+......+++++.+..+++++....+@#$=;;***-*-****$#............................................+@##&=*-*$#@+......++@##&&;=;&&$#@++...........+.........@#%%***&%#@@@@@#$$$.#%&***&%#@@@#$$%=&#.#%&===;===&$##$$&&%........+@#===#@++...", +"++@$%&;;%%&;;%%$@++....+.@@#$***$#@++++....@@#%&&&&;;%$#@++...@@#%&&==**%$#@++.....++@#$=;;%$#@+.....++++@++++++++@+++..@@$%-*-&&**-;;=&&$@............................................++@#$%***$$@++....++@#$%;;%&&;;%$#@+...+.++++.+.++.+.....+##%;;;&%#@@@#%%&=&.##$;;;&%###$$===%%#.@$$&&=**&&%$$%&&==$.......++@#===#@++...", +"++@$%&;;&%&;;&%$@++..+.+@@#$$***%$#@@++...++@#%&%&&;;%##@.+...+@$%&===**%$#@++......+@#$;;=%$@+++...++@@#@#@@@@@@#@#@@+.@@$%-*-&=-**;;=&%##.........+++++..............................++@#$%*-*%#@++....++@$%%;;&&&;;%%$@+.+.+++++@++++++++....+@$$;;;&%$#@##&&&==.@$%;;;&&$##$%=;;&%#.@#%&==**&&&%$&&===$.......+@@$%&%##++...", +".@@$%&;;&%&;;&%$@+..+.@@@#$%%-**%$$#@@+....+@#%&&&&;;%$#++...+@@#%&&==**%%#@++.....++@#$=;=$#@++....+@##$$##@@@##$$##@+.@#$%*--&&*-**;&&%#@........+++++++++............................+@#$%***$$#++.....@@$%&;;%&&;;%%$@@.++@@@#@@@@@@@@+++...@@$%;;;&&$###$&&===.@#%;;;&&$$$%%;=;%%#.##$&==-*&&&%%&====#.......+@@$%&%$@++...", +".+@#$%;;=&=;;%$#@+..++@#$%%&&*-*&&&%$#@...++@#$%;;;&%$#@@+....+@#%%===;;&%$@++......+@#$$%%##@+.....@@%&=;=%$##$**&=&#@.+#$%-*-&=**-;;=&%#@......+.+@@@#@@++............................+@@$%*-*%##++...+.@@$%&;;&%&;;&%$@@.+@@$%$$#$$$$$#@@++..@@$%;;;&%%$$&&;=;%$.#$%;;;&&$%$;====$$#.#%=&&===;===&;;;%$#.......+@#$%&&$#@+...", +"++@@#$;;&&&;;$##@++.+@@#%&&&&-**=&&&%#@....@@#%&;;;&&$#@+++..++##%&===;;%%$@@.+.....++@#$$#@@+......@#&=;;;%%$#$**===##.@@$%--*==-**;;&&%#@.......+@@#$##@@++............................@##%***%$@@+....++@$%&;;%&&;;&%$@+.+@#%%&$$%$%%%$#@@++.@#$$*;;&&%%%&&;;=$$.@$%;;;&&%%%;;===%$#.#&&&&==;=;;&==;=%##.....++@@#$;;;$@@++..", +"..+@##$%&=&%$##@+...+@#$*****---*****$$...++##;;;;=;=%$#@+...+@@$**&==;;&%$@++......+++@@@@@++......@#$%***&%$$$&=;;;$#.+@#$=;;***-*;;=%%#@.....+++@$%=;=#@@+..........................++@#%&-*-&%#@+....++@$$%;;=&=;;&$$@+.+@#=;;;=&&&**%%$@@+.@#&=;;;;;===;;===%$.#==;;*;;;;;;;;;;=&#.@%%;;;;;===;;;==%#@......+@#$%;;;$#@+...", +"..++@#$$&%&$$@@++...+@#$*******-*****$#...+@@$=;===;;%$#+++..+@##**&&=;;%%#@++........++++++........@#%&***&%$$$==;;;$#.+@#$==;**-*-;;&&%#@......+@#%%;;;$#+++..........................+@#%&*-*&%#@++...++@#$&;;===;;%$#@+.@##;;;;;&&&**&&%#@@.@#&;;;;;;===;;;==%$.#&;;;;;;;;;;;;;;==$.@$%;;;;;===;;===%$@...+++@#$&=***$#@++..", +"...++@##%%%##@++....+@#$*****---*****$#....@@$=;=====%$#@.+...+@#**&&&;;%$#@++.........+.+.+........+#$%***&%$$$==;;;$#.+@@$==;***-**;&&%@@......+@#%%;;=$#@+.........+.++.+..........+.+@#%%*-*%%#@++...++@#$%;;=&=;;%$#@+.+##=;;;;==&-*&&&$#@.@#&&;;;;;;=;;;;==$$.#&=;;;;;;*;*;;;;==$.@$%;;;;;===;*===%$@....+@##$==***$#@++..", +"....++@@@@@@@++.+...++@#$$%%%***%%%$$#@...++@#%%&=&&&##@++...+@@#$%&&&%%##@+........................@@$%;;;&%$$$&=;;;$#..+@##$%&=***;;&%%#@....+.++#%&***$@@++........++++++...........+@@#%&%&&&%#@@.+...+@#$$==;;;=&%$@@+.+@#$%&**;=;==-**%$@.@@#$%%%&&;;;==***%$.@#$%%&=;=;===&&&**$.@@#$%%&&***==***%$@...+@##$%==-**$#@+...", +".....+++@@@+++......++@@##$%%*-*%%$##@@...++@@$%%&%%%#@+++....+@@#$%%&%$#@@++.......................+@#%;;;=%$$$%&;;;%#..++@@#$%&-*-;;=&%#@......+@@%%***##++.......+++@@@@@++.........+@@#%%%%%%%#@@+....+@@$%&==;===$$#@+.+@#$%%**;=;==***%%#.+@@#$$%&&;*;==-**%$.@#$$%%=;=;===&&&**#.+@@#$%%&***==-**%$#..++@#===;;&&%$#@@+..", +".......++.++..........+@@#$$%;;;%$##@++....++@@#####@@++.......+@@@##@#@@++.........................@@#%;;;&&%%%&=;;;%#....+@##%%**-;;&%%#@......++@##$###@+.........+@@####@+++........++@@@###@@@++....++@$%&*******&%$@+.+@#$%&;;;;;&=*-*&%#.++@#$$%;;=====***%$.@@$&==;;%%%%&;;;&%$.+@@##%;;=====***%$#..+@@$=;;;;%%%$#@@++.", +"........+.............+@@@#$%;;;%$#@@++....++++@@@@@@+++........+@@@@@@+++..........................+@#%;;;;;&&&;;***%$....++@#$%****;=%%@@.......++@@##@@+++.......+@##==&##@+.........+++@@@@@@@+++.....+@$$&**-*-**%%$@+.+@#$%%;;;;;=&*-*%%@.++@#$%%;;=====*-*&$.@##&&&;=%%$%%;;;&&#.++@#$%;;=====*-*%%@..+@#$=;;;;&%%$##@@+.", +"....................+.+@@##%%;;;%%##@++......+++++++++.............++++++...........................@@#$;*;;;&=&;;***%$..+.+@@#$%*-*;;=&%$@........+++@+@++.......+.+@#$=;=$#@@...........+++++++++......++@#%%*******%$$@+.+@#$%&;;;;;&=***%%#..+@#$%&;;=====***%%.@#$&==;=$$$%%*;;&%#.+@##%%;;=====***%%#..+@#$;;;==%%$&=$$#@.", +"....................+.+@$%%&&==&&%%$$@+.........+...................................................+@#%;;;;;&=&;;***%$...++@#$%&*-**;==&$@.........+.++.+.........+@#%&***%%#@++............++.....+....++@@##$$%$$$$##@++.+@$=;;;;=&&*-==&$#@..+@#&;;==;==;;*-*&%.@$%;;;%%$$$=;===&%#.+@#==;=====;;*-*&&#..+@#$;;;=&%%%==%$$@.", +".....................@@#%%&&&=&=&&%%$@@..........+..................................................@@#$;;;*****;;***=&..++@#$%&&*-*;;;==$#.......................++@#%&*-*&%#@+...........................++@@###$###@@+++.@@$;;;;;&&&**=&&$@@.+@@#==;&=====;***=&.@$$;;;%$$$%====&&%#.@@#==;&=&=&=;*-*&&#...@#$=;;;;&&&;;&%$@.", +"....................++@#%&&&=&=&&&&%%#@.............................................................+@#%;;**-***;;***&%..++@$%%**********$#........................+@#%&***&%#@++..........................+++@@@@@@@@@++...@@$=;;;;&&&**&%%#@+..@@#===&&=====-**&&.@$%===$$#$$=;===%%#.+@#===&&&&&==***=%#.+++#$=;;;;&&&;;&%$@.", +"....................+@#$*************$#.............................................................@@#$;;;=&%%%$$$$$##..++@$%&***-******%#.......................+@@$&=-**&%#@+.............................+.+++@+++.+....@@#%=&%%%%%&%$##@++.++@#$%%$$$$$%%***&%.@$$$%$###$$**===**#.+@#%%%$$#$$%%***&&#..++@#==;;;&&=;;&%%@.", +"....................++##*************##.............................................................+@#$;;;&&$$$#$###@@...+@#$%**********$#........................+@#==*-*&%@@++..............................+..+.+.......+@#%%%##$$$%$##@+++.++@@$$$##@##%%***&%.+#####@@##$**===**#.++@$$$#####$%***%%@..++@#$$%*******%$#@.", +".....................+@##$$$$%%$%$$$##@.............................................................+@@$;;;%%@@+++.+++....+@@##$$%%%$%$$##@........................+@#$%&&&$##+.+...........................................++@@@##@#@@#@@@+++....+@@@@@@@@@###$$#@.+@@@@@@+@@##$$$$$#@..+@@@@@+@@@###$$##@...++@#$$*******$##@.", +"....................+++@@##$####$###@@+.............................................................++@#%%%##@++............@@###########@@.......................+++@$$&&%$@@++.+..........................................+++@@@@+@+@@+++.......++@@++++++@@#@#@@..++@+++++@@@###@#@@.+.++@+++++@@@#@#@@@...++@@##$$$%$$$#@@+.", +"......................++@@@@@@@@@@@@@++.............................................................++@#$$%#@@+...........+.+++@@@@@#@@@@++........................++@##%%%@@++................................................+.++++++.++.+..........++++++++@@@@+...+.++...++@++@@@@+..+..+++...+++@@+@++.....++@@#######@@+..", +"......................+.++++@+@+++++++..............................................................+++@$$$@@.+...............+++@+++++++...........................++@@@@@@@+.................................................+......+.....................++..+..............+++...+.............+.+++........+.++@@@@@@@+++..", +"...++@@@@@@+.+.............++@@@@@@++........++@@@#@@++........+++++@@@@@+++........+.+..+.+..+........+.@@####@@+++...........+.++.+.+++.+.......+.+.+.+.++.......++@@@@@@++...............+@@@#@@++.........@@@##@@++........++++++++++++........++@@@@@+++.............+.++@@@@@@+++......++@####@@+++.........+..+..+.++....", +"...+@#$%&#@@++............++@##$&%#++.+....+.+@#$%&%#@++........+@@######@@++.+.....+.+++++++++........++@$%&&&##++..........+++@++@+@+++++.....+.+++@+@++++++.....+@@%&$##@++...........+++@@#%%##@++.....+++@#%%&##@++......+.++@@@@@@@@+++......+@##&&#@@+++...........+.+@@#&%##@++....+.+@#$===$#@+++......+.+++++++++++...", +"+.+@@#$&&$#@++..........+++@@$$%&&#@++......+@@$$&&&##@++.....++@@#$%$$$$#@@++....++++@@@+@+@++++.....++@#$%==&$#@++.......+++@@@@@#@@@@@@+.....+++@@@@@@@@@+++...++@#&&$$$@@++.+.......+.+@@##=&$##++.....++@@$&&&$$@@++.....++@@@##@@#@@@@++...+++##$&&##@@+.+..........++@@#$&&$#@+......+@#$$===%$#@+......++@+@@++@+@+++++.", +"..++##$==$$#@@++.........+@@#%%%&&@@+.....+++@#$%===$#@+++....+@@#$%%%%%%$#@+.+....+@@@@#@#@@@@++.....++@#%&===%#@++......+.+@#$$$$$$%$$$#@..++++@##$$$$$$###@+...++@#&=%%$#@@++.....+..++@@#$$==$##+++..+.+@##$===%$#@@+....++@@#&&$$$%&$$#@++...++##$==$$#@@++.........++@@#$$==$$#++...+++@#$%;;=%$#@@+...+.+@@@@#@@@@#@@@++.", +"...@@#$&==&&#@+........++@@$$=;;%$#@++...+.@@#$;;;;=&%@@+...+++@$%&*****;=$#@+...++@#$$&&##$&&@@++...++@@$&=&&&&%@@++.....++@#$%%%%&%%%%%$#..++@@##$%%%%%%$$$#@...+@##%%;;;$$@@++.+...+++@##&====$#@@+...++@@#&&=;;;;$#@+++..++@#$==%%%&=%$$@++...++@#$&===&#@@+++...+.+++@@#&&==&$#@++...++@#$;;===;;$#@++...+@#$$%%##$%%$$#@+.", +".++@@#$====&#@@+.....+.+@@#$%;;;%$@@.+...++@@$$;;;;;&%#@+.+..+@#$%&***-*;=$#@+....+@#$%&=$$$=&#@+....++@#$===&&%%@++......++@#%%&&&&&&&&%%#.++@##$%%&%&%&%%%$$#.+++@#$%%;;;%$##@@+..++@@@##$&===&$$@@++..+@@#$&=;;;;;$$#@++.+@@$%%==&&&==&%%#@+...+@##$====&$#@@+++..+.++@##$====&$#@@....+@@#$;;;==;;$##@+.+++@#%%&&%$$&&%$#@+.", +"+.+@$%%%&===$#@++.....++#$$&&&=&$#@++....++@$%&==&&&&%#@++..++@#%&=&==;=&%#@+++..+@@$%%==%%%%%#@++..++@$$%&==;=$$@+++.....+@@$***-******--$.+@@%%%**********==#.++@$$%&&====&%$$@++.++@#$%%&===&&%%$@@+.+@@$%%==&&&==&%%@@+.+@#$%&===&&==&&%#@@.+++@#%%%&;==%%$##++...++##$%&==;&%%$#@+.++@@$%&&=&&===&%$@+..+@@$%%==%&%==&%%@@.", +"++@@$%%&&;==$#@++...++@@#$%&===&%##+++...+@#%%&===&&&%#@+...++@#&&=&=;=;%%##+.+..+@@$%&==&&%&$#@++..+@@$%&&=;=;$$@@+......+@##***----***-*$.@@#%&&****-*-***;=$.@@#%%&=&=====&&%$#@.@@#%%&&&;=;&&&&%##@.@@$%&&;=&=&;==&&$#@.@##%&&====&;=&&&$#@..+@@$%%&&;=;&%%$#@+.+++@#$%%&;=;&&%$#@@..+@#%%&==&&&==&%%#@..+@#%&&==&&&==&%%#@.", +".+@#$%&&&=;=$$@@+.....@@$%%====&%$@@+...++@#%&&;===&&%#@++...@@#&&==&;=;%%#@++..++@#%%&==&&&&%#@+...+@#$%&===;=%$#+++.....+@#$==-**==%&%;;$.@#$***==%%%%%;;=;=$.@#$****-*****-*-$$@.@#$***-******-*-%#@.@#$****-*****-*-$$@.@#$***-******-*-%#@.++@#%%&&&;;=&&%%$@@..+@@$%%&&;=;&&%%$@@.++@#%&&==&=&;=&&%#@.++@#%&&==&&&==&&%#@.", +".+@#==;**---&%#@+...++@#&=;**-*-%%#@++...+@#&=;**-*-&%#@++...@@#==;*-*--&%$@++...+@#&=;*-*-*&%$@@.+.+@#==;**-*-&%#@++......@#$==*-*;=&%&;;$.@#$***=&%$$$%=====$.@#$*-*-*-*-**--*%$@.@#$****-***-*--*%$@.@#$*-**-*****-*-%$@.@$$****-*****--*%$@..+@@&==***-***==&#@..+@#&==**-*-**;=&#@..+@#&=;**-*-**;=&#@.++@#&=;**-*-**;==#@.", +"++@#&=;-**-*&%#@++...+@#&==-*-*-&&#@++..++@#==;**--*&%$#++..++@#==;*-*-*&%$@++..++@#==;**---&%$@++..+@#&==**--*&%#@+.....++@#$==-*-==&%&;;#.@$$***&&$###$===;=#.@#$%&&;;%%%%%***%$@.@#$%=&;;&%%&%***%$#.@##&&=;;&%&%%***%$@.+#$&&=;;&%&%&***%$#.++@#&==-*----*==&@@.++@@&=;***--**==&@@.++@#&==**-*-**==&#@..+@#==;**---**==&#@.", +"..@@#$%=;*-*==$#@++..++@#$%==**-==$#@+....@@#$%==*-*==$#@++...@@#$%==-**==$#@++..++##$%=;*-*==$#@++.++@#$%=;-*-=&$#@++....+@#$**;;;;;;;;%%#.@$%***%%###@#$%$%$#.+@#%&=;;&%%%%***$$@.+@#%&&;;&%%&%***$#@.+@#%&&;*%%%%&***$#@.+@#%&&;*%%%%&***%#@..++@#$%%%***%%%$#@+..+@@#$$%%***%%$$#@+..++@#$%%%*-*%%%$#@@.+++@##%%%***&%$$#@@.", +"..+@##%=;*-*==$#@++..++@@$$=;-**;=$#@++...+@@$%=;**-;=$#@++...+@##%==*-*==$#@+...++@#$%=;*-*==$#@++.+++@$%==*-*==$#@+.+.++@@$$**;;;=;;;=%$#.@$%*-*%$#@@@@#$$$$@.+@#%&=;;%%%;;=&&$#@.+@#%&=;;%%%;;==&$#@.+@#%&=;;&%%;;&&%$#@.@@#%&&;;&%%;;&&%$#@...@@@#$$%*-*%$$#@@+...+@@##%%*-*%%$#@@+..++@@##%%***%$$#@@+...+@@##%%*-*%%$#@@+.", +"..+@#$%**&&&-*%$#@+..++@#$%-*&=&-*%$#@+..++@#$%**&=&-*%$#@+.+++@#$%**&&&**%$#@+.++@@$%&**&&&-*%$#@+.++@#$%**&=&-*%$#@++..+@#$%**;;;;=;;;%$#.#$%***%$@+++@@####@.+@#%%&;;&%%;;=&&#@+.+@#%&&;;&%%;;&&&#@@.+@#%%&;;&%%;;&&%#@@.+@#%&&;;&%%;;&&%#@@....+@@#$%***%$#@@++....+@@#$%*-*%$#@@++..+.+@@#$%-*-%$#@@++..+.+@@#$%***%$#@@++.", +"++@#%%&**%&%**&%%#@..+@#%%&**%&%**&%%#@..+@@%%&**%&%**&%%#@..+@#%%&**&&&**&&%#@..+@#%%&**&&%**&%%#@.+@#%%&**&%&**&&%#@+.++@$%%;;;;;*-**-%$@.@$%***%$#@@+@@@@@@+.+@#%&=;;&&%;;&&%#@+.+@@%&=;;%&%;;=&%#@+.+@#%&=;;%&%;;&%%#@+.+@#%&=;;%&%;;&%%#@+.....+@##%*-*$$#@++......+@##%***$$#@++....+++@##%***$$@@+......++@#$$-**$$@@+...", +"++@#%&&**&%&**&&%#@.++@#%&&**&%&**&&%#@.+@@#%&&**&%&**&&%#@.++@#%&&**%%%**&&%#@.++@#%&&-*%%&**&&%#@.+@#%&=**%&%**&&%#@+.+@#%%&;;;;;-*-**%$@.@$%***%$$##@#####@@.+@@%&&-*;;;**%%##@+.+@#%&&--;;;**%$$#@+.+@@%%=*-;;;-*%$#@@+.+@@%%=*-;;;**%$#@@+.....++@$$*-*$$@++.......++@$$***$$@++.......++##$*-*%#@@........++@$$***%#@@....", +"+@@$=;;-*;;;-*;;=$#.+@@$=;;*-;;;-*;==$#.+@#$=;;-*;;;-*;;=$@.+@@$=;;-*;*;-*;==$#.+@#$=;;*-;;;-*;;=$#.@#$=;;*-;;;-*;==$#@.@@#==;*-***===&&$#@.@$$***&&$$#$$%%%%$@.+@#$&&**;=;**%%$#@@.+@#%&&**;=;**%%$#@+.+@#%&&**=;;**%%$#@@.+@#%&&**=;;**%%$#@@.....+@@$$***%#@@+.......+@@#%*-*%#@@+.......++@$%***%#@@........+@@#%*-*%#@@+...", +"+@#$==;-**;;-*;;=$#.+@#$=;;*-;;;-*;;=$#..@#$=;;***;;-*;;=$#.+@#$=;;*-;;;**;;=$#.+@#$=;;***;;-*;;=$#.@#$=;;***;;**;;=$#@.@#$==;***-*;==&&$$@.@#$***==%%$%%&=&&%#.+@#%&=**===**%%$$#@.+@#%&=**=;=-*%%$$#@.+@#%&=**===**%%$$#@.+@#%%=**===**%%$$#@.....++##%-**%$#++.+.....++#$$***%$#+++......+@@#%***%$@@++.......@##%***%$@+++..", +"+@#%;;;**;;;*-;;=$#.+@#%=;;*-;*;**;;;$$.+@#$;=;-*;;;*-;;;$#.+@#%=;;**;*;-*;;;$$.+@#%=;;*-;;***;;=%#.@#$=;;-*;;**-;;=%#@.@#$=;=-*-*-===&&$$#.+#$&==**;;;;;***%%@.+@#%&&**;=;*-&%%$$@.+@#%&&**===**&%%$$#.+@#%&&**;;=*-%%%$$@.+@#%&&**;=;*-&%%$$@....++@#$%***%##@@.+..+.++@#$%*-*$$#@++....+++@#$%-**%$#@+++...+++@#$%*-*%$#@+++.", +"@#$%***;;=;==;***%$.@#$%***;;===;;***%$.@#$%***;;=;=;=***%$.@#$%**-;;===;;***%$.@#$%***;;====;***%$.#$%***;;====;***%$#.#$%***&&=;=;=%&%==#.+@#%&&**;;;;;***&%@.@@$%&=;;%&%=&=====#.@@#%&=;;&&&====&==#.@@#%&=;;%&%====&==#.@@$%&=;;&%&&&==&==#..+++@##$%*-*%%##@++...++@##$%***%$##@++..+++@#$$%*-*%$##@++...++@##$%***%$$#@++.", +"@#$%*-*;====;;*-*%$.@#$%-*-=;====;-**%%.@#$%-*-=;===;=-**%%.@#$%***;=====;*-*%$.@#$%-*-=;===;=-**%$.#%%*-*;====;;*-*%$#.#$%***&&;=;=;%&%;=$.+@#%&&**;;*;;***%%@.@@$%&=;*%&%=&==&;=$.@#$%&=;;&%%&&=====$.@#$%&=;*%&%=&=====$.@@$&&=;;&%&=&=====$..++@#$$%%*-*%%$$#@+.+++@#$$%%-*-%%$$#@@...+@##$%%***%%$$#@+.+.@@#$$%%-*-%%$$#@+.", +"@#&=-*-;;&&&;;-*-=&.@#&=*-*;;&&&;;*-*=&.@#&=*-*;;%&&;;--*=&.@#&=-*-;;&&&;;*-*=&.@#&=*-*;;&&&;;*--=&.#&=-*-;;&&&;;*-*=&#.#&=*--==**-**;;;-*$..+@##%%&***;=&%$##@.@$$*****;;;;;***==$.@#$***-*;*;;;***;=$.@#$*****;;;;;***;=#.@#$***--;;;;;***;=#.++@@%&=;;-*-;;=&%@@..+@@%&=;;-*-;;=&%@+.++@#%&=;;---;;=&%@@..+@@%&=;;-*-;;&&%@@.", +"@#&=*-*;;&%&;;*-*=&.@#&=*-*;;&%&;;--*=&.@$&=*-*;;&&&;;*-*=&.@#&=-*-;;&%&;;-*-=&.@$&=*-*;;&%&;;-**=&.#&=*-*;;&%&;;-*-=&#.#&=-**;=-***-;*;*-$...++@#%&;;;=&$#@++..@#%***-*;*;*;***;=$.@$$****-;;;*;***;=$.@#%***-**;;*;***;=$.@$$*****;*;*;***;=$..+@#&&=;;---;;=&&#@..+@#&&=;;--*;;=&&#@..+@#%&=;;-*-;;==&#@..+@#%&=;;--*;;==&#@.", +"@#&&-*-;;%%&;;-*-=&.@#&=-*-;;%%&;;*-*=&.@#&=*--;;%%&;;*-*=&.@#&=**-;;%%&;;*-*=&.@#&=-*-;;%%&;;-*-=&.#&=**-;;%%&;;*-*=&#.#&=-*-==*-***;;;**$...++@#%&;;*=&#@@+...@#$***-*;;;;;-**==#.@$$*****;;;;;-**==$.@#$*****;;;;;***==#.@#$***-*;;;;;-**==#.++@#%==;;**-;;==%#@.++@#%==;;*--;;=&&#@.++@#&==;;*--;;=&%#@.++@#&==;;*--;;=&%#@.", +"@#$%&=&=&%%%&&=&&%%.@#$%&=&=&%%%&&=&&%%.@@$%&=&=&%%%&=&=&%$.@#$%&=&=&%%%&=&=&%$.@@$%&=&=&%%%&&=&&%%.#$%&==&=%%%&=&=&%%#.#$%&&&&&&========&#....@@#&=***%$#@+....@@$&&&=======&=&%%#.+@$&&==;======&&%%#.@##&&==========&%%#.@@$&&========&=&%%#..+@@%%&&==&==&%%%@@.+++#$%&==&====&%$#@..+@@$%&==&=&=&&%%@@..+@@$%&&=&===&&%%@@.", +"+@$$&%&&%$$$%%&&%$#.+@$$&%&&%$$$%%&&%$#.@@$$&%&&%#$$%&%&%$$.+@$$%&%&%$$$%&%&%$$.@@$$%&%&%$$$%&%&&$#.@$$%&%&%#$$%%%&%$$@.@$$%&&%%%&%&&=&=%%#....+@#&=***$$@@++...+@#%%&=&&&&&&&%&$$@.@@#%%&&&&&&%&&&%$$@.+@#%%&&=&&&&&%&&$$@.+@#%%&=&&&&&&&&&$$@..++@$$%&%&&%&&%%$@+...@@$$%%&&&%&%%$$@+...@@$$%%&&&&&%%$$@+...@@$$%%&&%&&%%%$@+.", +"+@@######@@#######@.+@@@#####@@#######@.+@@#######@#######@.+@@######@@@######@.+@@######@@#######@.@@#######@######@@@.+@######$#$##$####@...+++@##$$$#@@+.....++@###$#$####$###@@.++@###$#$#$######@@.++@######$#######@@.++@####$#########@@..+++@@####$####@@@+...+@@@####$#####@@+...+@@@######$###@@+...+@@####$#####@@@+.", +".++@@@@@@@@@@@@@@@@..++@@@@@@@@@@@@@@@@..++@@@@@@@@+@@#@@@+..++@@@@@@@@@@@@@@@+..++@@@@@@@@@@@@@@@+.++@@@@@@+@@@@#@@@++.++@@@@@@@@@@#@#@@@+....+++@@#@#@@++......++@@@@@@#@#@@@@@++..++@@@@#@#@#@#@@@++..++@@@##@@#@#@@@@++..++@@@@#@##@#@@@@++....+@@@@#@@#@@@@++...+.++@@@@@@#@@@@++..+..++@@@#@#@@@@@++...+.++@@@@@@#@@@@++..", +"..++++++++++++@+++...++++@+++++.+@++++...+.+++@++.+++++++++..+.++@+++++++@+++++..+.++@++++.+++@++++.+.++@+++++++++++++...+.++@+@+@@+@+@@++.......+@@@@@++.........+++@@@+@++@++++.+...+++@+++@++@++++.+...+++@+@@+@+@+++++....+++@+@+++++@+++++...+..++++@++@++++......++++@@++@++++.++...++.+++++@+@+++.+......+++@@@+@@++++.+.", +"....+..+...++..+........++@@@#@@@@@@++.....+++###@@++..............++@@#@@+++.......+++@####@+++.......+++@@#@@#@@@@++.......+..+.+..+...................................++.++.+.+.....++@@##@@+++.............++@@#@@+++.......+.@@####@+++.........+.++.+.+.+.............++@@##@+++......+......................+++++++......", +"..+++++++++++++.......+++@##$$$$###@@++....+@@#$###@@+............++@@#$##@+++......+@@#$$$##@++.......++@###$$#$##@@++......++++++++++..............................+.+++++++@+++.....+@@#$###@++...........+.+@@##$@@++.......++@#$$$##@+++......+.++++++++++...........+.+@@####@++......+++++.++.............+++@@@@++++....", +"+.++@@@@@@@@++++++...+.+@@%%===&%&&%@@+...++@#&&&&%#@++..........++@#$$==$#@+......++@#$=;=&%#@++.....++@#%%===&%&&%@@+....+++@@+@@@@++++..................+.........+++@@@@@##@@++..+.+@#&&&&%#@+++.........++@#$$==$#@++.....+@@#$;=;&%#@+.+......++@@@+@@@+++.+........++@#$$==$#@++.++++@@@@@+++.............+@@##$#@@+++...", +".@@@@#########@@+++..++@##&&=;=&&=&%#@+....+@#&===&##++..........+@@$$%;=$#@@......+@@$%;;;&%$@@++....+@@#&&;=;&&&&%#@+....+@@##@@###@@++.........+.......+..+....+++@@#@##$#$$#@@+....+@#&===&##+++......+.++@@$%%;=$#@++.....+@#$$;;;&%$@@+++..+++@@##@@###@@@++......+.+@@$%%;=$#@++..+@#@#@#@@@+++.........++@@#$$%%##@++...", +"+@##$$$$$$$$$###@@+..+@@#$&&;;;=&=&&#@+...++@#&====$#@+++.....+.++@#$%%;;$#@++....++@#$%;;;=&$#@+.+.+++@#$&&;;;&&=&&@@+...++@@$$$##$$##@@+....+++.++....+.++.+..+.+@@@##$$$$%%%$#@+..++@##&====$#@@++++..+.++@@#$%%;;%$#@++..+++@#%%;;;=&$#@@+.....@@@$$$##$$##@@++..+.+++@@#$%%;;%$#@+.+@@#$$$$##@@+++........++@$$%%%%$$#@@++.", +"+@%&=;;;;;;;==$$$@@.++@$$%;;;;;**&%$#@@...++@#$%=;=%$#@++.+.....+@#$;;;&%$#@++....++@$====&;=%$#@++..+@#$%;;;;;**&%$@@+...++@#==%%%==%$$@++..+.++@++++.++++++++..+@@#$%&;;;;;***$#@..++@#$$%;;=%%#@@+++..++@@##$;;;&%$#@@++..+@@#$=;&=&;;%%$@@+.+++@#$==%$%==%%$@@+..+++@@##$;;;&%$##@+.+@#==;;;&%%#@++.+....+++@#$;;***;=$#@++.", +"@@%&;;;;;;;;;;%%$#@.+@#$%&;=*;;**&%%#@@...++@#$%;;;&%#@@++....++@@#$;;;&&$#@++...++@@$=;&&=;;%%$@++..+@$$%=;;*;**%$$#++..++@##;;%%%=;%%$@@+..++@@@@@+++++@@@@@+.++@#$$&=;;;;;***$#@.++@@#$%%=;;&%$##@@+.++@@##$%;;;&&%$$@@+.++@#$$=;&=&;;&%%#@@.++@#$$;;%%%==&%%#@+.++@@@##$%;;;&&%$#@@.@#$;;;;;=&%$@@@++.....+@@$$;;*-*;;$$@@+.", +"@#$%***;;====;***$$.+@#%%&;;;;***&%%$#@..++@@#$%=;;%&$#@@++.+.+@@#$%;;;&&$$#@++..++@#$=;=&&;;&%$@@+..+@$%%;;;;;**&%$@@+..+@@#$;;&&&;;&%%@@+.+.@@$%%#@@@@@#%%$@@.@@#&==**===*****%$@.+@#$$%%%;;=&%%$$##@.+@##$$%%;;;&&%$$##@.+@##%%;;&&&;;%&%$#@.+@#$$%;;%%%;;&&&$#@.+@##$$%$%;;;=&%%$##.@@#==;**==&%$#@@++...+@@$%&**&&&**&%$@+.", +"@#%&***;====;=*-*%$.@#$;;;;;&%&==;;;&%#.++@##$&=;;;;=%$$@@+..+@@#$&=;;;=;%$$@@+.++@#$%==;;;;;%%$#@+.+@@#$%==;*;;;%%$#@+.++@#$%&=;;;;;%%%#@+.++@#%%%$#@@###%%%#@.@#$===**===**-**%$#.@@#==;;;%%%==;;;%%@.@@#=;;;;%&%==;;;&%@.+##=;;;;&%%==;;;&%@.@##=;;;;%%%==;;;&%#.@@%%==;;;&&&;;;;;&%.@##==;**==&&%$##@@+..+@@%%&**&&&**&%%@@.", +"@@%%***=;====;***%$.@#$;;;=;%&%;=;;;&%#.++@#$%&=;;;;;&%$##+.+@@$$$&=;*;;;%%%##+.+@##$%&=;*;;;&%%$@@.+@#$%%==;;;;;&%%##@.+@##$%==;;;;;&%%$#@..@##&&&$$$#$$%&&&#@.@#$=;;**===***-*%%#.@#$;;;;;%%%==;;;&%#.@#$;;;;;%%%==;;;&%#.@#$;;;;;%%%==;;;&%#.@#$;;;;;%%%==;;;&%#.@#%&;;;;;&&&;;;;;&%.+##===-*===&%%$$#@@...@#$&&**&&&**&%%#@.", +"@#$%;;;=&%%%%%;;;=&.@#$*****&&&==-**&%#.+@#&==**===;=***%#@.+@#&==**====;***%#@.@@#==;;;====;***$$@.@@#==;;;;===;***%#@.@@#==;;;====;***$#@.++#$***;=%$%=;***$@.@#%***&&=&&;;;;;=&#.@#$***;=%%%&=***&%#.@#$***;=%$%&=***&%#.@#$***;=%$%&=-**&%#.@#$***;=%$$&=-**&%#.@#%&**-;;%%%;;-**&%.+@#%&=*-*****;;=%#@.++@#%%&;;&&&-*=&%@@.", +"@#$%;*;&=%%%%%*;;==.@#$***-*&&&&=*-*&%#.@#$&=;**====;***%$#.@@$==;**===;=***%$#.@#$=;;;;====;*-*%$#.@#$=;;;;===;=-**%$#.@#$=;;;;===;=-**%$#.+@#$***;;%%%=;***#@.@$%**-&&&=&;=*;;==$.@#%***;=$$$%&-**&%#.@#$***;=%$$%&*-*&%#.@#%***;=%$$%&***&%#.@#%***;=$$$&&**-&%#.@@%%*--=;%%%;=-*-%%.@@#%&&-*-**-*;;;%$#..++#%&=;;&=&-*&&%#@.", +"@#%=*****=&&%%&==;=.@#%***-*&&&&=***&%#.@#$=;=**=&&;=*-*%$#.@#$=;=**&&&=;*-*%$#.@#$=;;;;&&===***%$#.@#$=;;;;&&&;=***%$#.@#$=;;;;&=&=;*-*%$#..+@#$%%**;;;**%%$#@.@$%***&&;;;&&===;=$.@#$***==$$$%&*-*&%#.@#%***==$$$&&***&%#.@#$***==$$$&&*-*&%#.@#$***==$$$%&***&%#.+@#%=;;;=&%%;=;;;$#.+@#%&&;;%%%%&;=;==#..+@@%&&;******&&%#@.", +"@#&&-*-**=&&$%&==;=.@#%;;;;;;=;%&*-*%%@.@$%***&&$$$%%;;;=&#.@$$***&&%$%$%;;;=&#.@$%***=&%$%%%;;;=&#.@$%***=&%$$%%;;;=&#.@$%***==%$$%%;;;=&#.++@#$%&*-;;;-*&%$#@.#$%***%%;;;=&===;=$.@$%;;;=&$#$$%***%%#.@#%;;;=%$##$%***%$#.@#%;;;&&$##$%***&%#.@#%;;;=&$#$$%***%%#.+@#$==;;=&%%;;;;;$#.+@#%%=;;%%%%%;=;;=$..+@#%&=;;***-*=&%$@.", +"@#&&**-**=&&$$&=&;=.@#%;;;;;=;;&%***%$#.@#%*-*&%$$$$%;;;==$.@$%***&%$#$$%;;;==$.@$%*-*&&$$#$%;;;==$.@$%*-*&&$$$$%;;;==$.@$%*-*&%$$#$%;;;==$..++@#$%***;;-*%$$@+.#$%***&%;;;&&===;=$.@#%;;;&%$##$%***%$#.@#$;;;&&$##$%***%$#.@#%;;;&%$##$%***%$#.@#%;;;&%$##$%***%$#..+@#%%%**==&**&%$##.+@#%&&;;&%%%%=;=;=$..+@@%%&;;****-&&&$#.", +"@#%&***;=%%%$$&&=;=.@#$;;;==***%&***%$#.#$%***%$##@#$===;=$.@$%***%$####$===;=$.@$%***%$####$===;=$.@$%***%$##@#$===;=$.@$%***%$####$&==;=$...@@#$%=;*-*;=%$#@@.#$%***&%;;;%&===;=$.@#%;;;&%##@#%***%$@.@#%;;;&%####%***%$@.@#%;;;&%##@$%***%$#.@#%;;;&%#@##%***%$@.++@#$%%**=&=**%%$@@.+@@%&=;;%%$%%===;=$..+@#%&=;;&%%==***%#.", +"@#%&***;=&%$$$===;=.@#%;;;=&*;;&=***%$@.#$%***%##@@#$&=&;=$.@$%***%$@@@#$&=&;=$.#$%***%$#@@#$&==;=$.#$%***$$#@@#$&=&;=$.#$%***%##@@#$&&=;=$.+.@@#$%==--*==%$#@+.#$%*-*%&;;;%%===;=$.@#$;;;&%###$$***%$#.@#$;;;=%###$$***%$#.@#$;;;&&####%***%$@.@#$;;;=%$###%***%$#..++@#$%**&=&**%$#@+.+@#%%=;;&%%%%;==;=$..+@#%&&;;&%%==***%$.", +"+##%;;;&&$$$$$&====.@#%;;;==;;*&=***%%@.#$%***%%#@##$=;;==$.#$%*-*%%##@#$=;;==$.@$%*-*%$#@##$==;==$.@$%-**%$#@##$=;;==$.@$%***%%#@##$=;;==$..+@#%&&**;;;**&%%#@.@$%*-*;;&&&&%;;;==$.@#%;;;&%$##$%***%$@.@#%;;;&%$##$%***%$@.@#%;;;&%$##$%***%%@.@#%;;;&%###$%***%$@...++##$==*--==$#@++.+@#%&=*-;;;;;***&%#..+@@%&=;;%%%%%***%$.", +"+##%;;;=&%$#$%=====.@#%;;*&&=&=;****%%@.#$%-*-%%$##$%=;;==$.@$%***%%#$#$%=;;==#.@$%***&%$##$%;;;==#.@$%**-&%$##$%=;;==$.#$%***%%$##$%=;;==$.++@#%%&*-==;-*&&%#@.#$%***;;==&%%;;;==$.@#$;;;&%$$#$%*-*%$@.@#$;;;&%$#$$%***%$@.@#$;;;&%$#$$%***%$@.@#$;;;&%$$#$%***%$@...++@#$=;-*-==$#@++.+@#%%=**;;;;;-**&%#..+@#%&&;;%%%%%***%$.", +"@@$%;;;&&%$$$%=;==&.@#%;;;&&&==;;***%$#.@$%***&%$$$$%;;;==#.@$%*-*&%$$$$%;;;==$.@$%-**&%$$$$%=;;==$.@#%***&%$$$$%;;;==#.@$%*-*&%$$$$$;;;==#..@@#%&=**=;=**&&%#@.@$%*-*;;&=&&%;;;==#.@#$;;;&&$$$%%***%$@.@#$;;;&%%$$$%***%$@.@#$;;;&&$$$$%***%$@.@#$;;;&&$$$%%***%$@....++##$%*-*%$$@+++.+@#%&&-**;;;;***%%#.+@@#%&=;;%%%%%***%$.", +"@##%*-*==%&%&&***%%.@#%***==%%%;;--*%$#.@#$=;;;;&%&&&***%$#.@#$;;;;;&%&&&***%$#.@#$=;;;;&%&&&***%$#.@#$=;;;;&%&&&***%%#.@#$=;;;;&%&&&***%$#.+@#$***==%%%==***$@.@#$;;;*-&&&&&***%$#.+#$&==;;%%%&&***$$@.+#$&==;;%%&&&*-*$$@.+#$&==;;%&%&&***%#@.+#$&==;;%%%&&***$$@....+@#$%&***&%$#@++.@#$&==**;;===%%%##@.+@#$&==;;=====***%$.", +"@#$%***==&&&&&-**%$.##$***==%&&;;-*-%$@.@#$===;;&&&&&***%$#.@#$=;;;;&&&&&***%$@.@@#==;=;&&&&&-**%$@.@#$===;;&&&&&***%$@.@@$==;;;&&&&=***%$#..@#$***&%$$$&&***#@.@#%;;;**&=&==-**%$#.+@#&==;;&&&&=***$#@.+@#&==;;&%&&=***$#@.+@#&==;;%&&&=***$#@.+@#&==;;&&&&=***$#@.+.+@@#$&&-*-&%$#@@+.@@$&&=-*=====%$##@+.+@@$&&;;;=====-**%$.", +"@#&=*-******-*==&$#.@$%**-**&%%==***%$#.+@#$%%;;*****=&%$#@.+@#$%%;;****-=&&$#@.+@#$%%;;*****&&&$#@.+@#$%%;;*****&&%$#@.+@#$%%=;*****=&&$#@..+@#$%%$$####$%%$##.@#$=;;;;*****=&&$#@.+@#$%%****-**===$#@.+@#$%%***-**-===$#@.+@#$%%****-**===$#@.+@#$%%****-*-===$#@...+@$$&****-**%%$++.@$%****-=;=$$##@@++.+@$%**-*-==&*****$$.", +"@#==***-****-*&&&#@.@#%*****%%%&=***%$@..@@$$%==-*-**&&%#@+.+@@$$%=;*-***=&&#@@.+@##$%=;**-**&%%#@@.++@$$%=;*-*-*&&%#@@.+@@#$%=;**-**=&&#@@.++@#$$$#@@@@##$$$@@.@@$===*;*-***=&&#@+.++@#$%*****-*==&#@@.++@#$%*******=&&#@+.++@#$%**-***-==&#@@.++@#$%**-****==&#@+.+.+@$%%**-**-*%%$@+.@#%**-**==&$#@@@++..+@#%*****&==-****$#.", +"@#&=*****-***-&%%#@.@#$***-*%$$&&***$#@.++@##$==*****%%$#@+..+@##$==*****&%%#@+..+@##$==*****&%$#@+.++@##$==*****%%$#@+..+@#$$==*****&%%#@+.+++@###@@+++@@###@+.@@#===;;*****&%%#@+.++@##$*******=&&#@+.++@##%***-***=&&#@+.++@##$*******=&&#@+.++@##$*****-*=&&#@+...+@#%%*******%$$@+.@#$*****=&&#@@+.....+@#$*****&&&*****##.", +"@@#$$%$%$%$%$$$##@+.@##$$$$$$###$$$$#@@...+@@#$$$$$$$$#@@++..++@@##$$%$$$$#@@++...+@@##$$$%$$##@@+....+@@##$$%$$$$#@@+...++@@##$$%$$$$#@@+....++@@@+++++++@@@++.+@#%&&%%%$%$$$#@@++...+@##$$%$%$$$##@++...+@@#$$$%$%$$##@@+...+@##$$$$%$$$##@++...+@##$$$%$$$$##@@+...++@##$$%$%$$$#@++.@@#$$%$$$##@@+.+....+@@#$$$%$$$$$$$$##@.", +"+@@######$#####@@++.+@@#####@@@@@##@@@+....+@@@##$###@@@+.+...++@@########@@@......+@@#######@@@++.....++@#######@@@++.....+@@########@@@+.....+.+++....+++++.+.+@@%%%########@@@+....++@@@#######@@@+....++@@########@@++....++@@####$###@@@+....+++@####$###@@++....+++@@#######@@@++.+@@@#####@@@++.......+@@############@@+.", +".++@@@@#@@@#@@@@++...++@@@@@@+@+@@@@++......++@@@@@@@@++.+......+++@@@@@@@++.+......++@@@@@@@@++.......++++@@@@@@@++........+++@@@@@@@++........+............+..++@@@@###@@@@@+++.......+@@@@@@@@@@++.......++@@@@@@@@@++.......++@@@@@@@@@++.......++@@@@@@@@@++.......++@@@#@@@@@++....+@@@@@@@@++.........+++@@@@@@@@@@@@@++.", +"...++++++@++++...+...+.++++++.+.+.+++.........++++++++...........+.++++++++............++@++++...........+.+++++++...........+.+++++++++..+.......................+@@@+++@+++++...........++@+@+++..+........++++@+++++.+........+++++++++..+.......+.+++++++++.+......+.++++++@++..+......+++++++............+.+++++++++++++...", +"....++++++..................+.++++.+............+++.+....................+...............................+++++++++..................................................+.+++++...................+++++.+..........++.++.+...............................+.+++....................+++++.+..........++.+++.+.........................", +"....++++++++................+++++++..........+++++++.+............++..+.+.................................++@@@@+++................................................++++++++.+...............+.+++++++.+.......+.+@+++++...........+................+++@++++++...............+.+++++++..........+++++++..........................", +"..+.+@@@@@+++............++++@@@@@+++........+@@@@@@+++........++.++@+@++++...........+.++..+............+@@####@++.................................................+@@@@@@+................+++@@@@@++........++@@@@@+++..........+..++.+...........++@@@@++................+++@@@@@++......++++@@@@@++..........+.+.+.++.......", +"...+@##%%#@@++............++###%%@++.......++@@@%%%@@+..........++@@@@@@#@+++......++++++++++++........+++@$%&&&#@++..............................................++@##%%@@@+............+..++@#%%##@++......++@#$%%@@++.......+++++++.++++.+.....++@##%%@@@+............+..++@#%%##@++.......@@#%$%@@++........+.++++++++.+....", +".+++@#$%&##@+++........+++@@#$$%%@@++......++@#$%%%#@@+......+++@@#$$#$#$#@@++...+.+++@+++++++++........+@@$%==&##@++.............................................++@#$%&##@@++............+@@##&%$#@++......+@@#%%%$#@+++...+.+++@++++++++++.....++@#$&&##@@+.............+@@##&%$#@++....+++@##&%%#@@++.....+.+++@+++++@++....", +"...@@#$&&$$#@++..........@@#$%%&&#@+......++@#$$&&&$#@+++.....+@@##$%$%$$$#@+++.+.++@@@#@@#@@@+.+.......+@#%%===$#@+........+.+.+...+.+.+............+.+.+.+......++##$&&$$#@+++.........+++@@$$&&$##+.....+++@#$&&&$##@+.....++@@@@@@@@@@@++......@@#$&&$$#@++..........+++@##$&&$#@++.....+@#$$&&&$#@++......++@@@#@@@@@@+++..", +"...+@#$===&&#@++......+++@#$=;;%$@@++.....+@@#=;;;;%%@@+.....++@$%&*****;=$#@+..+++##$%%###%%@@+.......++@#&=&&%%%@++.+..+.+++++++++++++........++++++++++++.+....++@##===&&#@+++.........+@#%&&==$@@+......+@#%&;;;;=#@@+..+++##$%%###%%##@++.....+@##===&&#@+..........++@#%&&==$#@++...++@@#=;;;;%$@@++...++@@$$%%###%%@@.+..", +"..++@@#====&#@@+.....+.+@#$%;;;%%#@+....+++@#$;;;;;&%#@++....+@@%%&*****;;$$@++..+@#$$&&$$$&&#@++.....++@@$&=&&&%%@@++..+.++@+@+@++@+@+@+++....++++@@@@@@+@+++.....+@##====&$#@+++......++@##&&&;=$#@++....+@@#%=;;;==$#@++..+@#$$&&$$$&%$##@++...++@@$&==&&#@@+........++@##%&===#@++.....+@#$;;;;;&%#@+.....+@##$&&$$$&&@@+...", +"..++@#$%%===$#@++....++@@#%%=&&%#@@++....+@#$%&=&&&=&#@++....+@#%&=&&;;=&&$#@++..+@#$%%&%%%&%#@++......+@#$&&=;=$$@@....++@@#####@@#####@@+.++++@@#########@@++...++@#$%%===$$#@++....++@@@$$==;%%##@+...+++@#$==&=&=&%$#@+.++@#$$&&%%%&&%$#@++....+@@$%%==&$@@+........+@@$%===%$#@++...++@#$%&=&&&&%@@++....+@#$%%&%%%%%#@++..", +".++@@#$%%;;=$$@@++....@@#$%&==&%$#@+....++@$$%&=&&&=&$#@+...++@#%&=&&=;;&%$#@+..+@@$%%&=&&&&&$@@+....++@##$&==;=%$#@++..+@@#$$$$$$$$$$$$#@@..+@@@#$$%$%%$$$$@@+..++@@#$%%;;=%%##@@+...+@@##%%==;%%$##@+...+@##$==&&&=&%$$@+..@@#$%&&%%%&&%$$@++...++@#$%&==&$#@+......++@@#$%=;=$$@@+.....++#$%==&&&&%#@+....++@#$%&=&&&&%#@+...", +".++@#$%%&=;=%$#@@+..++@#$%&&===%$#@@++..+@@$%&==&&&==$#@++..++@$&&=&==;==&$#@++.+@#$%%==&&&&&$#@++...+@@#$%==;=;%$##+++.+@#$%%%%$%$%%%%%$#@.+@@#$$%%%%%%%%%$##+..+@@#$%%&=;=&%$$#@@.++@@#$$%&;=;&%%$#@@..+@@#$%===&&==%%$#@.+@#$%%==&&&=&%%$#@+...++@#$%&===$#@+.......+@#$%%=;=$#@++.....+@#$%&=&&&&%#@+....++@#$%=&&&%&%#@+...", +"++@#&==-**-*;;$#@++.+@#&&=*-***;;$#@+.+.+@#&==*-***;;$#@+++.+@@#===*-*-*;;$#@++.+@#&==**-**;;$#@++..++@#&==**-**;;$#@++.@#$***-*;;;**-**=&#.+@#&&&****-***-*%#@.++@#&&=*******=&&#@..+@#&&=***-***==&#@.++@#&==****-**==&#@.@@#&==***-***==&#@@..+.@$$%-**-*$#@++....++@#$%**-**%$@@.....++@$%&*-*-*%$@+++...++@$%%-**-*%$@@++..", +"++@#&==*-*-*;;$$@@+.+@#&=;*-*-*;;%##@+..@@#===-*--*;;%$#@+...@@#==;*-*-*;;%$#@+.+@#==;-*-*-;;%$#@+...+@#&==-*-*-;;$$#@+.@#$***-*;;;***-*==$.@#$&==*--*-**-**%$@.+@#$&==*--*-**===$#.+@#$&==*-*-*-*==&$#.+@#$&==-*-*-*-===$#.@#$&==-*-*--*===$#@..+++#$%*-*-*%#@++.....++$$%**-*-$#@@......+@#$%*-*-*$$#++....++@$%%*-*-*$$@@.+..", +".@@#&&=&&&&&**&%$@+.+##&&=&&&&&**&%$@++.@@#&&=&&&&&**&%$@++.++##%&&&&&&&**&%$@+.+##&&=&&&&&**&%$@++.++@#&==&&&&&**&%$@+.@#$&====--*=&&&&**$.@#%***==%%%==---%$#.+@#$**-==&%&=;***%#.+@#%***==%&%==***%#.+@#$***=;%&%;=***%$.@#%***==%&%;=-**%$@....@@#$%%***$$@+......++@#$%%***%$@++.....+@@#$%%***%#@++.....++@#$%%***$$@++...", +"++##&==&=&&&**&%%@@.+@$&&=&&&&&**&%%@@..+##&==&&&&&**&%%@@+.++@$%&=&&&&&**&%%@@.+@$&&=&&&&&-*&%%@@+.+@@$&&=&&&&&**&%%@@.@#$&==&=**-&&&&&-*$.@$%***=&$$$&&*--%$@.+@#%***;=&%&==-**%$.@@$%*-*==%&%==-**%$.+@#%**-==&%&=;*-*%$.@$%*-*;=&%&==***%##...++@@#$%*-*%#@@......+++@#$%*-*$#@++......+@@#$%*-*%##+......++@@#%%*-*%#@@....", +"+@@$&&=&&&&&**&&%#@.@##&===&&&&**&%%#@+.@##&&=&&&&&**&&%#@+.++##&&&=&&&&**&&%#@.@##&&==&&&&**&&%#@+.++##&&==&&&&**&%%#@.@#%&&==&--*=&&&&*-$.@$%***%%###$$&&&$#@.+##%*-*==%&%;=***%$.@#$%**-==&%&==-**%$.+##%***;=&%&==***%$.#$%**-==&%&=;-**%$@.....+@#$%***$$@++......++@#$%***%$@@......+++@#$%***$$@++.......+@@$%***$$@+....", +"+@#$===**-*---&%%@@.@#$&==**-*---&&%@@+.@#$&=;**-*---&%%@@+.+@#$&==*-*----&%%@@.@#$===*-**---&%%@@+.+@#$===**-*---&&%@@.#$%;;;*-**-;;;;;-*%.#$%***%$$##$$&&%$#@.@@$%*-*;;;;;;;--*%$.@@$%-**;;;;;;;*-*%$.+@$%--*;;;;;;;-**%$.@$%-*-;;;;;;;*-*%$@....++@##%*-*%##++......++@@$%***$$@++.+....++@##%*-*%##++......++@##%*-*%##++...", +"+@#$==;*-*-**-&&%#@.@#$===*-*-**-&&%#@+.@#$===*-*-**-&&%#@+.+@#$=;=**-***-&&%#@.@#$===**-***-&&%#@+.+@#$===-*-**-*&&%#@.#$&;;;-*--*;;;;;-*%.@$%*-*&&%%$%$%%%%$#.@#$%-*-;;;;;;;*-*%$.@#$%*--;;*;;;;*-*%$.@#$%**-;;;;;;;--*%$.#$%*-*;;;;;;;*-*%$@.....+@@$%***$$@@++......+@@#%*-*%##@++......+@@$%***$$@@++......+@@$%***%$@@++..", +"+@$%**-&&%&&;;=&%#@.@$%*-*&&%&%;;=%%#@+.@$%**-&&%&%;;&&%#@+.+@$%**-&&%&&;;=&%#@.@$%**-&&%&&;;=&%#@+.+@$%**-&&%&%;;=%%#@.$=;;;;%&*--=;=====$.@#$==;**=;=;;***&&@.@@$%-*-;;=====;==%$.+#$%-*-;;=;=;=;==%$.@#$%--*;;=====;==%$.#$%-*-;;====;=;=%$#...+++@#$%*-*%$#@+++....++@#$$***%$#@++....+++@#$%*-*%$#@++...++++@#$%*-*$$#@+++.", +"@@$%***&&&%&;;&&%#@.@$%*-*&&%&&;;=&%$@+.@$%***&&&%&*;&&%#@+.@@$%***&&&%&;;&&%#@.@$%***&&&%&;;&&%#@+.@@$%***&&%&&;;=&%#@.#==;=;&%*-*;;=;=;=$.+@#=;=-*;;;;;***=&#.+#$%*--;;;;=;=;;=%$.+#$%*-*;;;====;;=%$.@@$%-*-;;=;;=;=;=%$.@$%--*;;;=;=;=;=%$@...++@##$%***%$##@++...++@#$$%-**%$##@++...++@##$%***%$##@++...++@##$%***%$##@++.", +"+@$%**-%&%&&;;=&&$#.#$%***&&%&%;;=&%$#@.@$%*-*&&%&%;;=&&$#+.@@$%*-*&%&%&;;=&&$#.@$%*-*&%&%&;;=&&$#+.+@$%**-%&%&&;;=&&$#.#=;=;=&%-*-=;===;=$.@@##$%==***;===&$#@.+@$%-*-;;===;==;=%$.+@$%-*-;;=;=;=;==%$.+@$$--*;;=====;;=%$.@$$*--;;==;==;==%$@.+.+@@$$%%-**%%$##@+.+++@@#$%%*-*%%$##@+..++@@$$%%*-*%%$##@+..++@@$$%%-*-%%$##@@.", +"@@$%***;;;;;-*;;;$#.@$%**-;;;*;--;;;$#@.#$%***;;;;;--;;;$#@.@@$%***;;;;;--;;;$#.#$%***;;;;;--;;;$#@.@#$%***;;;;;--;;;$#.$==******-***;;;**$.++@##$&=***;==&&$#@.@@#$;;;**;;;;;*-*$$.+@#$;;;**;;;;;-*-$$.+@#$=;;*-;;;***-*$$.@#$;;;**;;;;;-*-$$@..+@@%&==;*--;;=&%@@..+@@%&==;-*-;==&%@@..+@@%&==;-*-;;=&%@@..+@@%&==;*-*;;=&%@+.", +"@@$%*-*;;;*;-*;;;$#.@$%***;;;;;-*;;;$#@.@$%**-;;;*;*-;;;$#@.+@$%*-*;;;*;-*;;;$#.@$%*-*;;;*;*-;;;$#@.+@$%*-*;;;*;*-;;;$#.#==*****-*-**;;;**#..+@@#$&&***;=&&%#@+.+@@$=;;-*;;;;;-*-$#.+@@$=;;**;;;;;-**$$.+@@#==;**;;;**-*-$#.@##=;;*-;;;;;-*-$#@..+@#%&=;;*-*;===&#@..+@#%&=;;*-*;;=&&#@..+@#%&=;;*-*;===&#@..+@#%&=;;*-*;===&#@.", +"+@@$&=&;===;====&$@.@#$&&==;=;=====&$@@.@#$&&=====;&===&$@@.+@@$&&==;=======&$@.@#$&&==;==;&===&$@@.+@@$&===;==;&===&$@.#$%=====&%&=====%$#...++@#%%;;;==%##@@+.++@#$$%&====;=&%%$@..+@#$$%====;==&%%#@.++@##$%&======%%$$@.+@#$$%&====;=%&$$@@..+@@%%&=======&&%#@..+@#%%&========&%#@..+@@%%&=======&&%#@..+@@%%&=;=====&&%#@.", +"+@@#%&&=========&#@.+@#%&&=====&&==&#@@.+@#%&&=====&&=&&#@+.+@@#%&&=====&&=&&#@.+@#&&&=====&&=&&#@@.+@@#%&&=====&&=&&#@.@$$=====%%%====&$#@....+@#$%;*;=&$#@+....++@##$&&=====%$$#@.+++@##$=======%$$#@.+++@##$&&=====%$$@@.+@@##$&&=====%$$#@+..+@@%%&=;=====&%%#@..++@$%&=;=====&%%@@..+@@%%&=;=====&&%@@..+@@$%&=======&&%@@.", +".+@#%%&&&=&&&%&&%#@.+@#%%&&&&&&%%&&%#@+.+@#%%&&&=&&%%&&%#@+..+@#%%&&&&=&%%&&%#@.+@@%%&&&=&&%%&&%#@+.++@#%%&&&=&&%%&&%#@.@##&&&&&$$$&&&&&##@...++@#==***%%#@+.+....++@##%&&&&&&$$#@+...++@##%&&&&&&$$#@+...++@@#%&&=&&&$##@+..++@##%%&=&&&$$#@++..++@$$%&=&=&=&&%$@+.+.@@$$%&=&==&&&%%@@..++@$$%&=&=&=&%%%@+...@@$$%&=&===&%%%@+.", +".++@@###$$$#$####@@..+@@##$$$$#$###@@++..+@@##$$#$$#$###@@+.+.+@@##$$#$#$####@+.++@@###$#$$#$###@++..++@@###$#$#$####@@.+@@#############@@+...++@#==***%$@@+.......+++@@##$###@@@++...+++@@##$$####@@++...+.+@@@#######@@++...++@@########@@++....++@@##$#$$####@@+...+@@###$#$#$###@@+...++@@##$#$$#$##@@+...++@###$$##$###@@+.", +"..++@@#@@@@#@#@@@++.+++@@@@@@#@@@@@@+++.+++@@@@@#@@@@@@@++...+++@@@@@#@#@@@@@++..++@@@@@#@@@@@@@++....++@@@@@#@#@@@@@++.++@@@#@@@@@@@@@@++.....+@@#$$$$##@++.........+@@@@@#@@@+++......++@@@@@#@@@@++......+++@@#@#@@@++.......++@@#@#@@@@++....+.++@@@@#@#@#@@@+...+.++@@@@#@#@@@@@+...+.+@@@@@#@@@@@@@++..+.++@@@@#@#@@@@@++.", +"...+.++@+@+@+++++.....+.++@++@+@+@+++....+.++@+@+@@@++++.+....+.+++@+++@+@+++....+.++@@+@+@@++++++.....+++@@+++@+@+++.....++++@++++@+++++.+.....+@@####@@++...........+++@++@+++..........+++@+@+++..........+.++++@+++.+........++++@+@++...+....++++@@+@+@+@++++.....+.++@+@+@+@+++.+.....++@@+@@@@+++..+....+.++@+@+@@@+++.+.", +"..++++++++++++++++.........+.+.+.+..+.........+.....................+.++.+..+.........+++++++.............+.++++.+.+.....................................................................+..+.+.................+.++++.+.........+.++++..+......................................................................................", +"++++@@@#@@@@@@@+++.......+++++++++++.......++++++++................+.+++++++........+++@@@@@++...........++++++++++.+....................................................................++++++.................+++++++.+........++++++++..................................+..+++++++...++@@@@@@++..............................", +"++@@###$$$#$$##@@@.....+.++@@@@#@@++++...+.++@@@@+++...............+++@@@@+++.......++@@###@@@++........++@@@#@@@@@+++..................................+..............................+++@@@@+++..............++@@@##@++......+.+@@@#@@+++.............+..................+.+@@@@@++...+@@#$$##@+++............................", +"+@##$%$%%$%$$%$##@+....++@@##$####@@++....++@@###@@++.............++@@###@@+++.....++@##%$%##@++.......++@@#$#$###@@+++....+..+..+.+++.+............+.++..............................+++@@###@@+++...........++@@####@+++.....++@@#$###@++.........+..+..++.+.+...........++@@####@+++.@##$%$$##@+...............+++++.+++.+...", +"@@%&*****;=;**=&%@@...++@@#&&&&%&&##@++..++##$==$##@++..........+.+@##$**$#@++.....+@@%%***%%@@++......+@@$%===%%%%$@++....+++++++++++++.........+.+++++++................+.++.........+##$==$##@++.........+.+@#%%&=&#@++....++@#$%=;=##@+.........++++++++++++..........++@##$**$#@++.@#$*-*;=$@@++..........+++++++++++++++..", +"@#%&***-*;;;**=&&#@..++@##$==&=&=&$##++..++@$$=;%$#@@+...........+@@$$%**$#@+....++@@#%&***&%#@+++...+++@#%&=;=&%%%%@++..+++@@@@@@@@@@@+++........+@@@@@@+++...........+++++++++.+...++@#$$=;%$#@@++.+.....+++@@#%&&==$@@+..+++@@#%&;;;$#@@++....+++@@@@@@@@@@@++++..+.++++@@#$%**$##@+.@$$-**;;$#@+++.........+++@@@@@@@@@@@++.", +"@#%&***-*;;;**==%#@..+@@#$%=;&====$##++..++##%=;%%%#@@++.......++@@#%%%**$$@@.....+@#$%&*-*&&$#@+.....+@#$%&;;;&&&%%@@+..++@@########@@@++......+++@##$#@@+..........++++@+@@+@@+@+..++@#$%;;%%%##@@++..++++@@@#$&====$#@++.++@@#$&&;;;%$#@@++...+@@@##########@@+...++++@@##%$%**%$#@+.@#%*-*;;$$#@@+++....+++@@@##########@@+.", +"@#&&===;;-*-;;%%$#@.+@@#&&=;;***=;$#@+...++@#$%&;;;$#@+++.....+++@#$=;;&&$#@+++..++##%;;&&&;;$$@+++..++##$;;;;;**%%$@++.++@#$$==$$$&=%$#+++....+.@@$%===#@+++.......++@@@##@####@@@.++@##$$%&;;=$##@@++.++@@###%%;;;%%$#@@+.+@#$$%;;===;=$#@@++.++@#$%%=&$$$**$#@@+.++@@@###$;;;&&%$#@@.@#$&&=;;%$##@@@+++..++@@##$**$$$==%%$#@.", +"@#%&===;;-*-;;&%$#@.+@#$===;;*-*;=$#@@...++@#$&&;;;%$#@++.....++@#$%;;;&%$#@+.+..+@#$%;;&%&;;%$#++...+@#$%;;;;***%$$@+..++@$%%==%%%==%%$@+......+@@$%===$#@+......+++@@##$$$$$$$##@.+@@#$%%&&;;;%$$##@+.+@@#$$$%%;;;%%$$#@@.@##%%%;;==&;;$$#@++.+@#$%%&==%%%**$$#@+.+@@#$#$$$;;;&&%$$$#.+@#%&=;;%%$$$##@++..+@##$$%**$%$==&&%$#.", +"+#$%;;;=&&&&-*===$@.@#%&=;;&&;=;;=%$@@+..+@##$==;;;=&$#@++...++@#$&=;;;;=$#@@+..++@#$%=;;;;;=$$#@++.++@##%=;;;;;;%$#@++.++##%%=;=;;;=$$#@++....++@#%&***$#@++.....++@@$&=========%%.@@%&==;%%%%%;==&%#@.@@%%===%%%%%;;=&%#@.@%&=;;&&%&%;;=&&#@+.@@%&=;;%%$%%=;=&&#@.@@%%==;&&%%%=&;;=%%.@##%&=;;=;===%$$@@+.@@$&=;===%$%===;=&%.", +"@@$%;;;=&&&&*-;==$#.@#%&;;;&&;;===%##@+..+@#$%=;;;;==$$#@@+.++@##%==;;;==%$#@@+.+@#$%%;=;;;=;%$#@@+.++@#$%=;;;;==%$$@@+.+@#$%%;=;;;=;%$#@@+....+@@$&&*-*$#@+++..+++@#$$==;;;==;;=&%.@#%&;;;%%%$%;===&#@.@#%&;;=%%$%%=;==&#@.#%&=;=&%%%%;;==&#@@.@#%&;=;&%%%%;;==&##.@#%&;=;&&%%%&=;;=&%.+@#%&&;*=;=;=%%%#@+.@#%&=;;==%$%==;;=&%.", +"+@$%;;;&&&&&**=;=$#.@#&&=;;&&=;;;=%$#@@.+@#$$%==;;;=;%$##@+.+@#$$%;=;;;;;%$$#@+.+@#$%%;=;;;;=%%$#@+.+@#$%%;=;;;;;%%$#@+.+@#$%&=;;;;;=%%$#@+.+.++@##&=***$$#@+++..+@#$$%==;;;;;;;;&%.@#%&=;;&%$%$;;===$#.@#%&=;;&%$$%;;===$#.#%&;;;&%%%%;;===$@@.@#%&;;;%%$%%=;===$@.@#%&;;;==$$%=&;;;&%.+@#%&=;;=;;;;&%%$#@.@#%&;;;==%$%==;;;&&.", +"+@#$=;;****--*-**%#.@#%&*****;=;**;=&#@.@@#;;;**==;**;;=$@@.@@#;;;**===**;;=#@@.@@$=;;**;==**;;=##@.@@$=;;**===**;;=$@@.@@$=;;**=;=**;;;##+.++@@#$$%%&&%%$###++.+@@#=;;**===**;;;%$.@#%&***&%$$%=;;;;$#.@#%&***&&$$$=;;;;$#.#%&***&&$%$;;;;;$#@.@#%&***&&$$%;;;;;$#.@@%%***==%%%==*-*%%.+@#%&&--;;;;;*--%%#.@@%%***==%%%==-**&$.", +"@@#$===*-*-**-***%$.@#%&**-**;=;**===$@.@#$;;;**;==**;;;$#@.@#$;;;**=;=**;;;$#@.@#$;;;**;;;**;;;$#@.@#$;;;**=;=**;;;$#@.@#$;;;**;=;**;;;$#@.+@@#$$%%%&&%%%$$#@@.+@#$;;;**=;=*-;;;$$.@#%&***&&$$$;;;;;$#.@#%&***&&$$$;;;;;$#.#%&***&&$$%=;;;;$#@.@#%&*-*&&$$$=;;;;$#.+@#$==;;;%%%;;===$#.+@@%&&**&&%%%;;;;=$.+@#$==;;;%%&;;===$#.", +"+@$$==;*-*-*-*-**%$.@#%&*****;=;**;==$#.@#$;;;-*===*-;;;$#@.@#$;;;**===**;;;$#@.@$$;;;**===*-;;;$#@.@#$;;;-*===**;;;$#@.@$$;;;**==;**;;;$#@.+@##%%%&&%&&%%%%$#@.+@$$;;;-*;=;**;;;%#.@#%%***&%$$$=;;;;$#.@#%&***&%$$%=;;;;$#.#%%***&%$$$=;;;;$#@.@#%&***&&$$$;;;;;$#.+@##===;;&&%;;;=&$#.+@#%&&**%%$%%;;;==$.+@@$&==;;&%%;;;=&$#.", +"@@$%*-*==%%%%&*-*%$.@@#%;;;==%%%&=;;;$#.#$%***&&%%%&&***%$@.#$%***&&%%%&&-**%$@.@$%*-*&%%%%%&***%$#.#$%***&&%%%&&-**%$#.@$%*-*&&%%%&&-**%$#.@@&&-**-*-*-***-*$#.@@$%*-*&&===*;-**%$.@@$%;;;&&$$$&=;;;$#.@@#%;;;&&$$$%=;;;$#.@$%;;;&&$$$&=;;;%#@.@@#%;;;&%$$$%=;;;%#..++@#%%**&&&-*%$#@+.+@#$&=;;%%%%%&=&;=$...+@#$%**&=&**%%#@+.", +"+@$%***=&%%%%&***%$.+@$%;;*==%%%&&;;;$#.#$%*-*%%$$$%&*-*%$#.@$%*-*&%$$$%&**-%$#.#$%***&%$$%%&*-*%$@.@$%*-*%%$$$%&***%$@.@$%**-%%$$$%%***%$@.@@&&*-*-*---*-*-*$#.+#$%***&&===;;-**%$.+@#%;;;&&$$$%&;;;%#.+@$$;;;&%$$$&&;;;%#.@#%;;;&%$$$%&;;;$#@.+@$$;;;&&$$$&&;;;$#..++@@#%;;*-*;;$$@@+.+@#%&&--=&=&&*-*&%#...+@@$$;;***;;$#@@+.", +"@#$%***%%$$$%%***%$.@@#%;;;=&$$$&=;;;$#.#$%***%%$$$%%***%$@.#$%***%$$$$%%***%$@.#$%-**%%$$$$%***%$@.#$%***%%$$$$%-**%$@.#%%***%%$$$%%-**%$@.+@#$$$%%%%%%%%%$$@@.@@%%*-*&=;;;&&***%$.@@#%;;;&%$$$&=;;;$#.@@#%;;;&%$$$%&;;;$$.@#%;;;&%$$$%=;;;$$@.@@#%;;;&%$$$%&;;;%#....+@#$=;***;=$#@+..+@#%&&**===&&*-*&%#....+@#$=;*-*;=$#@+..", +"@@$%***%%$$$%%*-*%$.+@#%;;;&&$$$&&;;;%#.#$%***%%$$$$%***%$#.#$%***%%$$$$%***%$#.#$%***%$$$$%%***%$#.#$%***%%$$$%%***%$#.@$%***%$$#$%%***%%@.+@@##$$%%%%%%$###@+.@@$%***==;;;&&***%%.+@#$;;;=&$$$&&;;;%$.+@#%;;;=&$$$&&;;;%#.@#$;;;&%$$$%&;;;%#@.+@#%;;;&%$$$&&;;;%#...++@#$&&--*&%$@@+..+@@%&&**-**-*;;;%$#...++@#$&&*-*&%$#@++.", +"@#$%*-*%%%$$%%***%$.@##%;;;&&%$$&=;;;$$.@$%***%%$$$%%***%$@.#$%***%%$$%%%***%$@.@$%***%%$$$%%***%$@.#$%-**%%$$$%%***%$@.#$%***%%$$$%%***%$@..++@@#$$%%%%$$#@@@+.@#$%***&=;*;%%-**%$.+@#%;;;&&%%%&=;;;$$.+@#$;;;&&$%$&=;;;$$.@#%;;;&&%$%&=;;;$$#.+@#$;;;&&%$%%=;;;$$..+++@#$&&*-*%%#@+...+@#%&&*-*-*-*===$#@..+++@#$&&-*-%%#@+...", +"+@$%***==%%%=;***%$.+#$%;;;=&%$%&&;;;%$.#$%***==&%%;;*-*%##.@$%***==%%%=;***%#@.#$%**-==&%%=;*-*%##.@$%***==%%%=;*-*%#@.@$%**-==%%%=;***$$@..+.+@@#&=*-*$#@@+.+.+@$%*-**-&&&;;***%#.+@#$;;;==%%%=;;;;%$.+@#$;;;;=%&%=;;;;%$.@#$;;;;=%%%=;;;;%##.+@#$;;;;=%%&=;;;;%$...+@#$$=;;;;%$@@++..@@#%&=;;&%%%%%$##@+...+@#$$==;;;$$@+++..", +"@@#$***;;&&&=;***%#.@#$%;;;&&%%%&&*;;%$.@#%*-*;=&%&==***$#@.@#%***;;&&&=;***$#@.@#%***;=&%&;=***$#@.@#%***;;&&&;=***$#@.@#%***;;%%%=;***$#@...+++@#&=*-*$#@+.+..@#$%*****&&&=;***$#.++##;;;;=&&&;=*;;%$.+@@$;;;=;%&&;=*;;%$.@@#;;;=;&&&;=*;;%$#.+@@$;;;=;&&%;=*;;%$.++@@#$%==;;;$$@+....@#$%&=;;&%%%$##@@++.++@@#$%=;;;;%##++...", +"+@#$&==**-*-*-=&&$#.@#=;---*-%%&*-*-*=&.@#$&&=**-*-*-=&&$@@.@#$&==***-*-*==&$#+.@#$&==**-*-*-=&&$@@.@##&==***-**-=&&$#@.@#$&&=**---**==&$@@....++@#$%==&$#@+....+@$%;;;-***-**=&&$#.++@#%%&********-*=&..+@#%%&********-*=&.+@#$%&********--=&#..+@#$%&***-****-*=&..+@#==;--***%#@++...@#$;;;-*;==$##@@++...+@#==;*-***%#@+....", +".@@#%&&**-*-**=&%#@.@#&;*-*-*&&&*-*--==.+@#&&&-*-*-**=&&#@+.+@#%&&**-*-**&&%#@@.+@#%&&-**-***&&&#@+.@@#%&&**-*-**=&%#@+.+@#&&&**-*-*-&&%#@+.....+@@$%&&&#@+.+...@@#%;;;*--*-*-&=%#@..+@@$%%**---***--==.++@@$%%**-*-**---==.+@##%%*-*--**-*-==#.++@@$$%****-**---==.+@@$==;**-**$#@++...@#%;;;-*;==$#@++.+..+@@$==;-****$#@@....", +".+@#%&&***-***&&%#@.@#==**--*%%%*-*-*=&.+@@%&&****-**&%%#@+.+@#%%&***-***&&%@@+.+@#%%&**-*-**&%%#@+.+@#%&&**-****&&%#@+.+@@%&&**-*-**&&%#@+.....++@#$&&%#@@.....+##%;;;-***-**&%%#@..++@#$%*******-*-=&..++@#$%**-*-***-*=&..+@##%****-***-*=&#...+@#$$**-*-***-*=&..@@$==;-****$#@+....@#$;;;**;==#@@+......@@$==;*-***$#@+....", +"+++@@#$$$$%$$$$#@@+.@##$$%$$$$$$$$%$$$#.++@@#$$%$%$$$$#@@++.++@##$$$$$%$$$##@++.++@##$$$$%$$$$#@@++.++@@#$$$$$%$$$#@@+..++@@#$$$$%$$$$#@@++......+@@#@##@++.....@@%%;;;%%%$%$$$#@@+...++@@#$$%$%%$%$$$#...++@@#$$$%$%$%$$$#..++@@#$$%$$%%%$$$#@...++@##$$$%$$%%$$$#.++@#=======&$#@++...@#$&=;===&&#@++.....++@#=======&$@@+....", +"..++@@#####$###@@@+.+@@###$###########@.+++@@####$####@@@....++@@###$#####@@++...++@@####$#$##@@@+..+++@@###$#####@@@+..+++@@####$####@@@.+.......++@@@+@.+.....+@%%===$$$#$###@@@....+++@@#######$###@...++@@@######$####@...++@@###$####$##@@....++@@###$#$##$##@..@@#&&==&=&%#@+.....+@#&&===&&&#@++......@@#&&===&&&#@++....", +"...+++@@@@@@@@@+++...+@@@@@@@+@@@#@@@@+...+++@@@@@@@@@++.+....+++@@@@#@@@@+++.....+++@@@@@@@@@+++.....+++@@@@#@@@@+++.....+++@@@@@@@@@++.+.........+++++.+......+@@#######@@@@@++.+.....+@+@@@#@#@@@@@+......+@@@#@#@@#@@@+....+++@@@@@@#@@@@++.....++@@@@@@@@@@@@+..++@##$$#$##@@+.....+@@#$#$$###@@.+......++@##$#$###@@+.....", +"....+.++@+@+++++......+++@++++++++@++++....+.+++@+@+++++.......+.+++++@++++.+......+.+++@++++++.+......+.++++++++++.......++.++@+@@+++++...............+.........+@@@#@@@@+@+++++........+.++++++@+++++........+++++@++@+++.....+.++@+@++@++++........+++@+@@@+++++...+@@@@@#@@@@+......++@@@@#@#@@+++........+@@@@#@#@@++......", +"........................+..+..+++++@@@++......+....+.+........................................................................+...................+++++++...........+++++++++++.+.......+.++.............++@@@@@@@@@@@@++++.........................................................................+++++.......................", +".........................+.+++++@@###@@@...+.+.++.+.++..+......................................................................+..................++@@@+++.........+++@@@@@@@@+++.....++++++++...........+@@####@#####@#@++........................+.+.++.+.+++.+.................................+++++++++.....................", +"......+...+.+.+.......+++++@+@@@##$$$$#@...+++++++++@++++...........+..++++++.+...........+...............+.+++++.+.......+++++++++.............++@@##@@@+.........++@@@#####@@@+.+...++++@@++.+.........@#$$$$$$$$$$$$##@+...........+++.+......+++++++++++++++++++........+....................+++@@@#@@+.....................", +"..++++++.+.+++++.....++@@@@##@##%%***==#..++@##@@@#@##@+++.....+.++.+++++@+@+++...+.++++...+.+.++..+......+++@++++.......++@@@@@@++.............++@#%&&#@+++......++@@%&%%%%%%%@++....+@@#$#@@++.........#$***=======***##@+.........+++++++.....+@@@@@@#@#@@@@@@@++.....+....+................+.++@#$$%%@@+........+++.+.......", +".+++@+@+++++@+@++.+..@@@###%$$$$%&***==$.++@##$###$#$##@++....++++++@@@@##@#@@++.+++++++++@+++++++.....+.++@#@#@@++++....@@######@+++..........++@##==&##@++.+.....@@#&&%&&&&%%@@+....@@#$$%#@@++.+.+....#%***;;=;=;;***$#@+.......++@@@@@@+.+...@@###$#$###$#$###@+.....+.++++++++++.....+.....+@@#%%%&%#@@.....+++@+@++.......", +".+@@@#@@@+@@@#@@++...@#$$$%%%$%$&&***;=$.+@@#%%$$$$$%%$#@++..+@@@@#@###$#$$$##@+.+@@@#@#@#@@@@@@@+++....++@##$#$#@@+++...@##$$%$$#@++........++@@##$===$$#@@++...++@@$==&&===&%#@++..+@##$%%$#@@++++.+...$%***;;;;=;;***$#@+.......++@@###@@+....@#$$%$%$%%%$%$$$##@...+.+@@@@@@@@++.+...+.++..++@#$%%&&&$#@....+++@@#@@+++.....", +".@@#%%%#@@##&&$##+++.$&&===**=&==;***==#.@##%**&&%=====#@@+..@###$#$$%%%=====$#@.@@#$$#$#$#$$$$##@@+.+.+@@#$***&%#@@++++.#&=****-##@+........+@@##$%***%$##@@@++..+@#$**==;;&&&#@++..+@#$%*-%%$@@@++++++.$%***=;===;;***%$@+......++@#&&&%$@+++..#*******-*****-*=&@..+++@@####$##@@++...++++.++@#$%*****%$#....++@#$%%#@++.....", +".@#$%&%####$&=$$@@+..%===;=--====;***=&#.@#$%**&&&=;;;=$#@@+.##$$%$%%&&&=;=;=$$@.@#$%%%$%$%$%$$$$#@@.+++@@$%***&%$##@@++.#&=**--*$#@++.......@##$$%%*-*%%$$$#@@+.++@#%**==;;=&&#@@+..@@$%%-*&%%#@@@@@@++.$%-*-;;==;=;*-*%$@@......++@#&==&%@@+...#*****-*-*-*-**-&%#..+++##$$$%$$$#@@++..@@@++++@#%%**-**%##...++@@$%%%##@++....", +".#%&***%$$$%**%$#@+..%=;***==&&&**&&&$$#.@$%%**&&&=;===%$#@+.#**-*-*******-*-=&#.#$******-**-*-*=&#@.+@##$$$===&=%%%$$@@.#$%=;;==%$@@+.......$%===;=*-*;=;==%$@+.@@#$%**&&;;=&%$#@+..@@$%&**&%%#$$$$$$@@.$%*--;;*****;;;$$#@......+@#$===%$#@+...@#$$%%%%;;;%%%%%$$@.++@#%%;;*-**&&%#@++.%%$#@@@@#&=*-*%%$#@....+@#&&**%$@+.....", +".#&&***$$%%%**%$#@+..%=;***;=&&&**&&%$#@.#%%&*-&%&;;===&%#@@.$***--*******--*==#.#$***---*-*-*--=&#@.@##$%%%;;;==&%%%%#@.@$%=;=;=%$#@++......%%==;=;-*-=;;;=&%#@.@##$%**&%;;=&&$##@@.@#%%&**&%%%$%%%%%#@.%%--*;;***-*;;;%$#@......++##===&%@@+...@##$$%%%;;;&%%$$##@.+@@#%&;;-*-*=&&##@+.%&$#@@@@$&=***%%#@+..+++##&&**%$@@+....", +".#&=***%%%%%**%$#@+..$=;*-*==&&&*-&&&$#@.$%%&**&&&=;===&%$#@.#**-*-**-*-**-*-=&#.#$*-*-****-*--*==$@.#$$%%%%=;===&&&&%#@.@$$=;=;=%$$@@+......%%;=;=;*-*;=;;;&%#@.#$$%%**&&;;&&&%$##@.@#%&&-*&&%%%&&&&%#@.%%-*-;;*-***;*;%%$#.....+++#$==;%$#@+...@@###$%%;*;%%%$$$#@.+@#$&=;;**--=&&$$@@.&&%$####$==-*-%$#@+...+@#$&=*-%$@+.....", +".$**;;;=&=&=**$#@++..$%&***%%%%&-*===$#@.%***--******-***%$#.##$$%%**;;;**&%%$#@.$%***&&%%%%%***%%#@.$%*****-*-***-***$#.@$%*-***;==#@++.....&=;;;;;**-=;***==##.&&==;*-;=**;;;;=%%$.#$;;;**-*-*-*****##.==***;;==;;;*-***$$......+@#$===%%@@..+.@##$$$&&;;;&%%%%&%#.@#%&;;=;;;;%***&%#@.%&**$###$&&;;;%#@++..++@#$**==$#@++....", +".#**;;;&=&&=**%#@++..#%%***%%%%%**;==$#@.&****-******-***%$$.@##$%%**;;;**%%$#@@.$%***&&%%%%%***%$#@.%&***-*---*--*-**$#.@$%**-**;;=$@@+.....&;;;;;=-**;;*-*==##.&==;=-*=;*-;*;;=&%$.#$;;;****-*--*-**#@.==*-**;;;=;;-****%$......+@@$==;%%@@+...#$$$$%&&;;;&%%&&&&#.@$&&;;==*;;%***&&$@.%&**$$#$$&&;;;$#@++..+@@#$**=&##@++....", +".#$$&&=;;***=&$#@+...#&==;=$$$$%*-***%$#.#%&&-*&&&;;===%%##@.@@@#$$&=;;;%%$##@@+.$$*-*=%$$#$%***%%#@.#$%&===***&%===;=$#.@$%===;;;;=##++.....&===;%&***%%***==$@.&===;**=;**;;;=;&&%.$%;;;&&&&&**&%%$$#@.&&;;;**====;==;==$#.....++@#$===%$#@.+..%&====;;*--;=;===&#.#$**%&;;=&&%===**$#.$%**&%$$%**===$#@+...+++#%**%%##@++....", +".@##&&&*;***&&$@+++..$&&;==$$$$%-****%%#.#%&&**&%&==;==%$#@+..+@@#$==;;;%$#@@++..#%***&&$##$%***%$@+.@#%&&==*-*&%====;$#.#$%&==;;;==$@@+.....&====%&**-%&-**=&$@.&====-*=;**;;;;=&%%.$%;;;&&&&&*-%%%$#@+.&&;;;**=;=;==;==&$@.......@#$==;%%@@.+..%=====;;-**;=;===&$.#$**&&;;&&&%===**$#.#$**&&$$%**==&#@++....+@#%**&%$#@@++++.", +".+@#%%&;;***=&##@+...#&====%#$$%*****&%#.#%%&*-&&&;;===$#@@+.+.+@#$&=;;;%#@@+++..$$*-*&%###$$***%$#@.@#$%&&=*-*%&===;=$#.#$%===;*;;=#@@......=====&%*-*&%***==$@.%&===**=;**;;;==&%$.$%;;;&&&&&**%%$@@++.%&;;;**;==;=;===&#@.....++@#$=;=%%@@+...%=====;;*-*;=====&#.$%**&&;;=&%%&&=**$#.##**&%%%%**==&#@@...++@@$%*-%%$###@@+..", +".+@@$$%;;-*-%%##++...$====&$$$%%**;;==&#.@$%%-*%&&=;===$#@+....+@#$&==;=$#@++....$%***&%$##$%***%$#@.+@#$$==;;;%&;;;==$@.$=;;;;**%%$#@+.+.+..&=;;;;;*-*=;-*-=&$@.#$%%%-*&&;;=&&$$##@.&=%%%%%=;=;;$$@@+++.$%=;;--*--*-***%$#@.....++@#$***%$@@+...###$$%%%;;;%%%$$##@.%&;;&&**%%$$&&=-*$$.@#$$$%&&=**%$#@@+...++@#%&;;%$==%$$@@++", +".++@#$%;;**-%%$#@@+..$=;==&%$%%%**====&#.@$$%-*&&&=;===#@@++...+@#$&=;==#@@+.....$%*-*&%$##$$***%%@@.+@@#%&=;;*&%;;;=&#@.$=;;;;**%%$#@@+++.+.==;;;;;-*-;;***=&$@.@#$%%**&&;;=&&$##@@.&&$%%%%;=;;=$#@++...#$;;;**-**-*-**%##@......+@#%***%$#++...@####$$%;;;%$###@@+.%&;;&&**%%$$===**%#.+@@$$$&==**$$@@+....++@#%=;;%%;;%%$$@@+", +".+@@$%%***-*;;%$#@@+.$==&=&%$&&=;=%%$##@.@$%&**&&&;===&$#@+...+@@#$;;&%%#@+......#%***&&$#$$%***%$@@.+@##%;;;;=&=*-*%%#@.#;;***;;%%$#@@@@+++.%%===%&*-*%%;;;&%#@.##%&&**%&;;&&%#@@++.####$%%-**%%#@+++...#$==;&&%&%&=;;;%#@+.....+@@$%***$$@++...+@@@@#$%;;;%$#@@+++.&=;;==;;%$$$==;;;$#.+@@#$%***&%$#@+++...@@#$=;&=%$&&***$$@+", +".+@#$%%**-**;;%%$##+.#=====%%&=&==%###@@.@#%%*-&&%==;==#@@...++@#$%;;&%$@@++.....$%*-*&&$$$%%***%%#@.@@#$%;;;=;&&***&$#@.$;;***;;&%$$###@@@+.$%&&&%%***&%;;;&%#@.@#&&&**%%;;=&%#@@+..@@##$%&***%$#@@.....@$=;;&&&%&=&;;;$#@+....++@#$%***%#@@....+++@@#$%;;;%##@++...&&;;;=;=$$$%=;=;;$#.++@$$%***&%#@@+.....@#$%=;&&%%&&***%$#@", +".@##$%&*-**-;;&%%$#@.#&====%%=====$#@@++.@$%%**&&&=;==&$@@+..+@@#$%;;%$$@@.+.....$$***=&%%%%%***%$@+.@#$$%;;;=;&&***%$#+.$;;****;%%%$%$$$##@.#%%%&%%*--%%;;;%$@@.#$&&=**%&;;&&%#@+...+@@#$%&*-*%$@++.....@#&==%&%%&&=;;;$#@+...++@@#$%*-*$#@+....+.++##%%;;;$#@++....&&;;==;;%%$$;=;;;##.+@#$$%***%$#@+......##$%;;==%%&=***%%#@", +".##$***==%%%**--*=&#.#$%***;;;;;&%#@@+++.@#%%*-===;;;=&$@@...+@#&====$$@@+.......$%*-*;;;;;;;*-*%$#@.#$==;===&=*-;;;$#@+.$%%;;;;;*-***===&&@.@@##$$%***%%%$$#@@+.$%***&&$%;;=%%@@++..+@@#$;=&&%$#@++.....@##$$%&;=;**;;=$#@+..++@@#$==;;;$#@++....++##$==;;;%#@+.....#%****&%%$%;***%$#@.@##%;;=;=$#@@.......$%==**;;;;*----;;$#", +".#$%***=&%%%**-*-=&#.@$%***;;;;;%$@@+.+..@#%%-*===;;==&$@++..@#$===;=$#@+........$%***;;;;;=;***%$@+.$$=;;==&&&--;;=$#@+.#%&;;;;;-****====&#.+@@@#$%***%$##@@@++.$%***&&$%;;&%%@@++..@@#$%=;&%%#@+++.....+@@##%%==;**===#@+...++@#$%=;;;=$@@++....++##%=;;;;$#@++....#$****&&%%%;***$$@@.##%%;;==&#@@+.......%&=;**;;;;***-*;;$#", +".%**&&%$$$#$$%&=&&%#.@##%%&==&&%$#@+++...@#%%**;=;;;=&&#@@...@%&==;%$#@+++.......#$;;;&%$%$%%===$$@+.=====$$$$%=&%%$#@++.#==&&&%%&&&;=;;=&%@.+++@##%**-%$#@@@++..;;&&&%#$$==%%$@++...+#%&&&&$##@++.......++@@#$$;;;-*&%$#@++.++@#%&=**%$$#@+.....+++#$$;;;;;$#@+.....@#$$&%%%***=%$$##@+.$%**=&%$##@++.......%%**;;====%&===**$#", +".$**%%%##@@##$&&&%%@.+@#$%&==&%%#@+++....@#$%**;=;;;=&%#@+...@%&=;=$$@@++........#$;;;%$$$#$$&&&$#@+.====&$$$#$&&%$$@@+..#==%%%$$%%%=====%$#.+.+@@#$***$#@@+.....=;&&&$###&&%%#@++...@@%&&&&##@+++.........++@#$;;;**%$$@+++..+@#&==**$$#@+++....+.+##$;;;==##@+.....@@##%%$%***=$$#@@+..%%**&&$#@@+++.......$%*-=;=;==%%&&&**$@", +".$**%$$@@@@@##%%%$$@.++@$$$&&%%$@@+......@#$%**===;;&%%@@.+..@%%==&$#@++.........@#===$$#@@##&&%$#++.&&&&%#@@##%%$#@@++..#&&%$$##$%%====&%$@....+@#$***$#@+.+....==&%%@@@#&&$##@+....+@%%&%$#@++............+@@#=;;**%$#@++..++@#%&=**$#@@+.......++@#$=;===#@+......++@@$$#$***&##@@+.+.%%**&%#@@++.........$%**====&&$$%&&**##", +".#$###@@+++++@@@#@@+.++@@@####@@@++......+@#$&&%%$%$##@@+....@@#####@+++.........@##$##@@@@@@@##@+++.#####@@@@@@@@@++....@@###@@@#@###$###@@....++@#$%%#@++......#####@@@@@#@@@++....+@####@@++.+...........++@##$$$$#@@+++...+@#%%&$##@@+.........+@@#$#$##@@++......++@@@##$#$#@@++....%%$$##@@+++.........##$$$$$#$######$##@", +".@@@@@+++..+++@@@@@+...++@@@@@@@+........++@#%&######@@+++...+@@@@@@++...........+@@@@@@+.++@@@++++..@@#@@@++++@@@+++....+@@@@+@@+@@@#@#@@@+.....+@#$$#@@+.+.....@@#@@++++@@@+++.....++@@@@@++...............++@@####@@++....+++@$%%##@@+...........++@@##@@@++........++++@@@##@@++.....$%###@@++...........@@####@#@@@@@@#@@@@", +".++@@+++......++.+.......+++@+++.........++@@@#@#@@@@++++....++++@@+.+...........++++@++..+.+.++++...++++++.+..+...+.....+++++.+..+++@@++++.....++++@@@@+++......@+++.+..++.+++........++++.+.................++@@@@@++++....+.+@@#@@@++............++++@+@@++...........+++++@@@+.+.....@@@@@++.............+@@@+@@@+@++++@@@++"}; diff --git a/hacks/images/matrix1b.xbm b/hacks/images/matrix1b.xbm new file mode 100644 index 00000000..c84d2871 --- /dev/null +++ b/hacks/images/matrix1b.xbm @@ -0,0 +1,307 @@ +#define matrix1b_width 160 +#define matrix1b_height 182 +static unsigned char matrix1b_bits[] = { + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f, 0xff, 0xff, 0xf7, 0xef, 0xff, 0xff, + 0xff, 0xff, 0xdf, 0x7f, 0xff, 0xfd, 0xff, 0xff, 0xff, 0xff, 0xff, 0xdf, + 0xff, 0x7f, 0xff, 0xfa, 0xef, 0x9f, 0xbf, 0xff, 0xff, 0xf7, 0xff, 0xff, + 0xff, 0xfd, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x3f, 0x7f, 0xfb, + 0xd1, 0xf7, 0xff, 0xff, 0xfe, 0xff, 0xef, 0x7f, 0x7f, 0xfc, 0xf7, 0xff, + 0xff, 0xff, 0xff, 0xef, 0xff, 0x7f, 0x7f, 0xff, 0xeb, 0xd7, 0x5f, 0xff, + 0xfd, 0xff, 0xef, 0xff, 0xfe, 0xf9, 0xf7, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0x3f, 0xff, 0xff, 0xeb, 0x6f, 0xff, 0x7f, 0xff, 0xff, 0xef, 0xff, + 0xfe, 0xfc, 0xf5, 0xff, 0xff, 0xff, 0xff, 0xf7, 0xff, 0x7f, 0xff, 0xff, + 0xd5, 0xbf, 0x5f, 0xff, 0xfa, 0xff, 0xef, 0xff, 0xfe, 0xfb, 0xc1, 0xff, + 0x1f, 0xfc, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe5, 0xd7, 0xbf, 0x7e, + 0xfd, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf7, 0xff, 0xff, 0xff, 0xff, 0xfd, + 0xff, 0xff, 0xff, 0xff, 0xed, 0x37, 0xff, 0xff, 0xf2, 0xff, 0xef, 0xff, + 0xfe, 0xff, 0xf7, 0xff, 0xff, 0xff, 0xff, 0xfd, 0xff, 0x7f, 0xff, 0xff, + 0xf5, 0xcf, 0xbf, 0xbe, 0xfa, 0xff, 0xff, 0xbf, 0xff, 0xff, 0xf7, 0xdf, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xf6, 0xff, 0xdf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfd, 0xfe, + 0xff, 0xff, 0xff, 0xff, 0xf5, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xaf, 0x9f, 0x7f, 0xfd, + 0xeb, 0x5f, 0x9f, 0xfe, 0xf5, 0xea, 0xd7, 0x5f, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xfb, 0xbf, 0x3f, 0xff, 0xf2, 0xd7, 0xbf, 0xbf, 0xff, + 0xfc, 0xdf, 0x2f, 0x7f, 0xfd, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xeb, + 0xeb, 0x7f, 0xff, 0xff, 0xfd, 0xaf, 0xdf, 0x7e, 0xff, 0xeb, 0xfb, 0xdf, + 0xfd, 0xff, 0xff, 0x5f, 0xff, 0xbf, 0xff, 0xf6, 0x7f, 0x7f, 0xff, 0xf7, + 0xcf, 0x6f, 0x9f, 0x7e, 0xfa, 0xff, 0x57, 0xdf, 0xfd, 0xfd, 0xef, 0xff, + 0xdf, 0x7e, 0xfd, 0xef, 0xfb, 0x7f, 0xff, 0xf9, 0xf7, 0xbf, 0x7f, 0xfd, + 0xfa, 0xef, 0xcf, 0xbf, 0xfe, 0xfe, 0xff, 0xf3, 0xbf, 0xff, 0xfb, 0xf7, + 0xb7, 0x7e, 0xff, 0xfd, 0xd7, 0x67, 0xff, 0x7d, 0xf3, 0xff, 0x5f, 0xbf, + 0xfc, 0xff, 0xff, 0xe7, 0x6f, 0xfd, 0xf3, 0xf7, 0xff, 0x7f, 0xff, 0xfe, + 0xff, 0x97, 0xff, 0x7e, 0xf7, 0xf7, 0x7b, 0xbf, 0xfe, 0xff, 0xff, 0xdf, + 0xbf, 0xfe, 0xfe, 0xfb, 0x6b, 0x7f, 0x7f, 0xfd, 0xaf, 0x3f, 0xfe, 0xfd, + 0xf6, 0xff, 0xeb, 0xff, 0xfc, 0xff, 0xff, 0xbb, 0xff, 0xfd, 0xfa, 0xff, + 0xdf, 0x5f, 0xbf, 0xf6, 0xea, 0xaf, 0xaf, 0x7e, 0xfb, 0xfb, 0xaf, 0x5e, + 0xff, 0xfd, 0xf7, 0x7f, 0xff, 0xff, 0xff, 0xf7, 0xbf, 0x7f, 0xfd, 0xfe, + 0xff, 0xbf, 0xbf, 0xff, 0xfa, 0xfb, 0xdf, 0xff, 0xff, 0xff, 0xef, 0xff, + 0xff, 0xdf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfb, 0xfb, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0x7f, 0xff, 0xff, 0xfb, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xd7, 0xdf, 0xbf, 0xff, 0xfb, 0xdb, 0xaf, 0x7e, 0xfd, 0xf7, 0xf7, 0xdf, + 0xff, 0xfa, 0xfd, 0xf7, 0xef, 0xff, 0xfb, 0xff, 0xaf, 0x3f, 0x7f, 0xf4, + 0xab, 0x77, 0xbf, 0x7d, 0xf3, 0xd5, 0xb7, 0x3e, 0xfe, 0xf5, 0xd5, 0xcf, + 0xdf, 0x59, 0xf7, 0xea, 0x9f, 0x5f, 0xbf, 0xf7, 0xde, 0x5d, 0x6f, 0xfd, + 0xfe, 0xde, 0x7b, 0xbf, 0xff, 0xff, 0xee, 0xf7, 0xcf, 0xbe, 0xf5, 0xdf, + 0xbb, 0xff, 0x7e, 0xf5, 0xfe, 0x7b, 0xef, 0xde, 0xf5, 0xfe, 0x6b, 0xbf, + 0xff, 0xf5, 0xf5, 0xef, 0x9f, 0xb9, 0xf6, 0xdc, 0x97, 0x5f, 0x7f, 0xf3, + 0xfe, 0xff, 0x5f, 0x7f, 0x7f, 0xdf, 0xaf, 0xbf, 0xff, 0xff, 0xf1, 0xff, + 0x4f, 0x7c, 0x75, 0xff, 0x57, 0xff, 0xfe, 0xf6, 0xfe, 0xfb, 0x1e, 0x7e, + 0xf8, 0xfc, 0x77, 0x3f, 0xff, 0xff, 0xe5, 0xef, 0x5f, 0xfd, 0xf2, 0xee, + 0xaf, 0x0f, 0xbd, 0x7b, 0xff, 0x77, 0xff, 0xff, 0xff, 0xce, 0xdb, 0xff, + 0xff, 0xfd, 0xfb, 0xf7, 0xef, 0xdd, 0xf5, 0xbe, 0x77, 0xdf, 0x7d, 0xf7, + 0xfd, 0x7f, 0x5f, 0xbd, 0xfe, 0xdd, 0xbb, 0x3e, 0xbf, 0xfb, 0xd6, 0xaf, + 0xae, 0xb9, 0xf3, 0xef, 0xef, 0xaf, 0x3c, 0xf5, 0xab, 0xa9, 0xef, 0x7e, + 0xff, 0xeb, 0x77, 0xdf, 0x5f, 0xfd, 0xfe, 0x67, 0xef, 0xbd, 0xfb, 0xda, + 0x9f, 0xef, 0xfd, 0xfd, 0xfb, 0xef, 0xaf, 0xbd, 0xfe, 0xff, 0xef, 0x5f, + 0xfe, 0xfd, 0xad, 0x5f, 0xdf, 0x7f, 0xf7, 0xfb, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xf7, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0x7f, 0xff, 0xff, 0xff, 0xeb, 0xbf, 0xbf, 0xfa, 0xeb, 0xab, 0xef, 0xbe, + 0xfb, 0xde, 0xbb, 0xef, 0x7e, 0xf5, 0xf9, 0xf7, 0x7f, 0xff, 0xfd, 0xff, + 0x87, 0x3f, 0x7d, 0xfa, 0xcb, 0x03, 0xcf, 0x7d, 0xe7, 0x9a, 0x33, 0xde, + 0xf8, 0xf4, 0xfb, 0xff, 0x7f, 0xfe, 0xfd, 0xff, 0x7b, 0xef, 0x9e, 0xff, + 0xee, 0x6d, 0xef, 0xbc, 0xf7, 0xda, 0x77, 0xaf, 0xbd, 0xf3, 0xfb, 0xf7, + 0x7f, 0xff, 0xff, 0xff, 0xff, 0xee, 0x7d, 0xf3, 0xdd, 0x4f, 0xff, 0x7d, + 0xff, 0xd2, 0xaf, 0x7f, 0x7f, 0xff, 0xfb, 0xef, 0xff, 0xfe, 0xfa, 0xff, + 0xb7, 0xf7, 0xfb, 0xfa, 0xf5, 0xeb, 0xef, 0xbd, 0xf7, 0xd4, 0xd7, 0x3f, + 0xff, 0xf5, 0xfb, 0xff, 0x7f, 0xff, 0xff, 0xff, 0x87, 0xef, 0xbf, 0xfa, + 0xcd, 0xcf, 0xef, 0xfd, 0xfe, 0x95, 0xaf, 0x7f, 0xfe, 0xfd, 0xfb, 0xdf, + 0x7f, 0xff, 0xff, 0xff, 0x77, 0xaf, 0x7d, 0xfd, 0xe7, 0xff, 0xff, 0xfc, + 0xfd, 0xcc, 0xbf, 0x7f, 0xff, 0xfe, 0xfd, 0xff, 0xff, 0xfe, 0xff, 0xff, + 0xef, 0x3f, 0xbd, 0xea, 0xde, 0xcf, 0xdf, 0xfd, 0xfa, 0xed, 0x67, 0x7f, + 0xff, 0xf4, 0xfb, 0xbf, 0x7f, 0xff, 0xff, 0xff, 0xf3, 0x5f, 0xbe, 0x7b, + 0xea, 0xef, 0xef, 0xfe, 0xfd, 0xdd, 0x3b, 0x3f, 0x7f, 0xeb, 0xfb, 0x7f, + 0x7f, 0xff, 0xff, 0xff, 0xef, 0xdf, 0x7c, 0xf7, 0xef, 0xdf, 0xbf, 0xff, + 0xfd, 0xff, 0x77, 0x7f, 0x7f, 0xff, 0xf7, 0xff, 0xff, 0xfe, 0xff, 0xd4, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xbf, 0xff, + 0xff, 0xbf, 0xff, 0xff, 0xfa, 0xff, 0xfb, 0xbf, 0xff, 0xfe, 0xfe, 0xe7, + 0xff, 0xff, 0xff, 0xff, 0xdf, 0xff, 0xbf, 0xff, 0xff, 0xbf, 0xff, 0xff, + 0xfa, 0xff, 0xf7, 0x7f, 0xff, 0xfa, 0xfd, 0xcf, 0xff, 0xff, 0xff, 0xff, + 0xef, 0xff, 0x7f, 0xff, 0xff, 0x7f, 0xff, 0xff, 0xfe, 0xfb, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xdf, 0xdf, 0xff, 0xff, 0xff, 0xff, 0x5f, 0xfe, 0xf0, + 0xc5, 0x8b, 0xaf, 0x7e, 0xf4, 0xc7, 0x85, 0x5f, 0xff, 0xf8, 0xea, 0xdf, + 0x1f, 0xbc, 0xfa, 0xf5, 0xff, 0x1f, 0x3f, 0x7b, 0xed, 0x77, 0x4f, 0x7d, + 0x7b, 0xd5, 0xb7, 0xbf, 0xff, 0xfd, 0xeb, 0xdf, 0x47, 0x5e, 0x7b, 0xd5, + 0xff, 0xff, 0x7e, 0x67, 0xdd, 0xd5, 0xcf, 0xfc, 0xfe, 0xed, 0x77, 0x7f, + 0xff, 0xfb, 0xe3, 0xdf, 0xff, 0x7a, 0xf7, 0xde, 0xff, 0x0f, 0xfe, 0xf7, + 0xfe, 0x7b, 0x2f, 0xfe, 0x7f, 0xd6, 0xbf, 0xbf, 0xff, 0xfb, 0xf9, 0xdf, + 0x5f, 0xff, 0xfd, 0xee, 0xff, 0xff, 0xbc, 0xf6, 0xfc, 0xdb, 0xcf, 0xfd, + 0xfe, 0xeb, 0x77, 0x7f, 0xff, 0xfb, 0xe7, 0xdf, 0xff, 0xba, 0xeb, 0xdd, + 0xff, 0xcf, 0x7e, 0xf5, 0xeb, 0x9b, 0x6f, 0xbe, 0xfe, 0xdd, 0xbb, 0x3f, + 0xff, 0xff, 0xed, 0xcf, 0x4f, 0xbf, 0x77, 0xd5, 0xff, 0x9f, 0x7d, 0xfb, + 0xd7, 0x37, 0xdf, 0xfe, 0xfa, 0xfb, 0x73, 0x7f, 0x7d, 0xfd, 0xdd, 0x9f, + 0xff, 0xba, 0xf6, 0xf7, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xf7, 0xff, 0xbf, 0xff, 0xff, 0xff, 0xff, 0xdf, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xdf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf3, 0xdf, + 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xeb, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xff, 0xdf, 0xbf, 0xff, 0xff, 0xff, + 0x93, 0x3f, 0xbc, 0xf4, 0xd3, 0x87, 0x6f, 0x3d, 0xe2, 0x9a, 0x13, 0x6f, + 0xf9, 0xf0, 0xf3, 0xdf, 0x7f, 0xff, 0xff, 0xff, 0x73, 0xe7, 0x7e, 0xfb, + 0xf9, 0xfb, 0xe7, 0xbf, 0xf7, 0xce, 0xf7, 0xe7, 0xbc, 0xfb, 0xfb, 0xdf, + 0x7f, 0xff, 0xfe, 0xff, 0x6f, 0xcf, 0x7d, 0xfe, 0xd3, 0xef, 0x6f, 0xfd, + 0xfd, 0xb5, 0x8f, 0xaf, 0x7f, 0xfd, 0xf3, 0xdf, 0x7f, 0x7e, 0xf1, 0xff, + 0xb3, 0xbe, 0xfe, 0xff, 0xe9, 0xf7, 0xff, 0x7f, 0xfb, 0xea, 0xe7, 0xbf, + 0xfe, 0xfa, 0xff, 0xdf, 0xff, 0xbf, 0xff, 0xff, 0xd7, 0x7f, 0x7d, 0xfe, + 0xdf, 0xef, 0x6f, 0xfd, 0xf6, 0xcb, 0xcf, 0xbf, 0xff, 0xfe, 0xf3, 0xdf, + 0x7f, 0xff, 0xff, 0xff, 0xf7, 0xff, 0xbe, 0xff, 0xd5, 0xaf, 0xdf, 0xfc, + 0xfd, 0xfd, 0xb7, 0xdf, 0x7f, 0xf5, 0xff, 0xff, 0xbf, 0xff, 0xff, 0xff, + 0xeb, 0xff, 0x7d, 0xfa, 0xeb, 0xbf, 0xbf, 0xfd, 0xff, 0xef, 0x7b, 0x9f, + 0x7f, 0xf9, 0xfb, 0xff, 0x7f, 0xff, 0xff, 0xff, 0xf7, 0x7f, 0xfd, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xef, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0x8b, 0xff, 0xff, 0xfd, 0xf7, 0xff, 0xff, 0xfd, + 0xfe, 0xe9, 0xff, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xff, + 0x01, 0xff, 0xff, 0xfd, 0xe7, 0xff, 0x4f, 0xfd, 0xfd, 0xeb, 0xff, 0x5f, + 0xfe, 0xfa, 0xff, 0xff, 0xff, 0xff, 0xf8, 0xf7, 0x83, 0xff, 0x7f, 0xfa, + 0xfd, 0x57, 0xdf, 0xfe, 0xfe, 0xfd, 0xff, 0x8f, 0xfa, 0xfb, 0xff, 0xff, + 0xff, 0x3f, 0xea, 0xfb, 0x01, 0xff, 0xff, 0xfb, 0xfb, 0xb7, 0xbf, 0xfc, + 0xfd, 0xe9, 0xff, 0xbf, 0xfe, 0xfa, 0xf7, 0x4b, 0xff, 0x7f, 0xfa, 0xff, + 0x83, 0xff, 0xbf, 0xfe, 0xfe, 0x6f, 0x9f, 0xfe, 0x7e, 0xea, 0xff, 0xcf, + 0x7d, 0xfb, 0xdd, 0x97, 0xff, 0xff, 0xea, 0xff, 0x03, 0x7f, 0xff, 0xff, + 0xf1, 0x6f, 0x3f, 0xff, 0xff, 0xca, 0xff, 0x1f, 0xfb, 0xfa, 0xeb, 0x7f, + 0x2f, 0xbd, 0xfc, 0xff, 0x81, 0xff, 0x7f, 0xfd, 0xfd, 0xbb, 0x3f, 0xff, + 0xfe, 0xf7, 0xff, 0x4f, 0xfe, 0x7c, 0xea, 0xbf, 0xff, 0x7f, 0xeb, 0xff, + 0x03, 0x3f, 0xfe, 0xf9, 0xea, 0x57, 0x7f, 0xfe, 0xfd, 0xcf, 0xff, 0xdf, + 0xfd, 0xfb, 0xdd, 0xff, 0xff, 0xff, 0xfa, 0xff, 0x81, 0x3f, 0xff, 0xfe, + 0xa8, 0xff, 0x3f, 0xff, 0xfe, 0xf2, 0xff, 0x3f, 0xff, 0xff, 0xeb, 0xff, + 0xff, 0x7f, 0xfd, 0xff, 0x01, 0x7f, 0xff, 0xfd, 0xeb, 0xff, 0x7f, 0xfe, + 0xfe, 0xfd, 0xff, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfd, 0xff, + 0x9b, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xfb, 0xef, 0xbf, 0xff, 0xff, 0xef, 0xff, 0xff, 0xfd, + 0xfb, 0xff, 0xff, 0xff, 0xe9, 0xff, 0xff, 0x7f, 0xff, 0xff, 0xff, 0xf7, + 0xff, 0xff, 0xfe, 0xff, 0xdf, 0x7f, 0xff, 0xff, 0xf7, 0xff, 0xff, 0x3f, + 0xf9, 0xff, 0xff, 0x7f, 0xff, 0xfd, 0xff, 0xf7, 0xef, 0xbe, 0xff, 0xff, + 0xf7, 0x3f, 0xff, 0xfe, 0xf3, 0xef, 0xff, 0x3f, 0xfd, 0xff, 0xff, 0x7f, + 0x7f, 0xff, 0xff, 0xff, 0xf6, 0x7b, 0xed, 0xff, 0xdf, 0x7f, 0xfe, 0xfd, + 0xff, 0xff, 0xdf, 0x7d, 0xf4, 0xff, 0xff, 0x7f, 0xff, 0xfa, 0xff, 0xd7, + 0x5f, 0xff, 0xfd, 0xf7, 0xff, 0x0f, 0xfd, 0xfe, 0xfa, 0xff, 0xef, 0xfe, + 0xfc, 0xf7, 0xff, 0x3f, 0xff, 0xff, 0xf2, 0xbd, 0x76, 0x5d, 0xfb, 0xff, + 0xff, 0x7f, 0xfd, 0xff, 0xf7, 0xff, 0xdf, 0xfd, 0xf5, 0xf7, 0xff, 0xff, + 0x7f, 0xf9, 0xcf, 0x77, 0xdf, 0xfb, 0xf2, 0xf7, 0xff, 0x7f, 0xff, 0xff, + 0xff, 0xff, 0xef, 0xff, 0xfc, 0xff, 0xff, 0xff, 0xff, 0xfc, 0xca, 0x5f, + 0x7f, 0xff, 0xf6, 0xfd, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xaf, 0xf8, + 0xf1, 0xff, 0xef, 0xff, 0xff, 0xfb, 0xef, 0x77, 0xee, 0xfd, 0xf5, 0xfb, + 0xff, 0x5f, 0xff, 0xff, 0xff, 0xff, 0x9f, 0xff, 0xfa, 0xff, 0xef, 0xff, + 0xff, 0xff, 0xfa, 0x5f, 0x7f, 0xbf, 0xf3, 0xf5, 0xff, 0xbf, 0xfc, 0xff, + 0xff, 0xff, 0x7f, 0xff, 0xf3, 0xff, 0xcf, 0xff, 0xff, 0xff, 0xf7, 0xff, + 0xfe, 0xfa, 0xf7, 0xef, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfb, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xff, 0xff, 0xbf, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xef, 0xbf, 0xff, 0xfb, 0xe9, 0xff, 0xff, 0xff, 0xed, 0xfb, 0xef, 0xbf, + 0xff, 0xfb, 0xfb, 0xef, 0xff, 0xfe, 0xfa, 0xff, 0xdf, 0x7f, 0x7f, 0xff, + 0xfb, 0xd7, 0x5f, 0xff, 0xf4, 0x85, 0xaf, 0xbf, 0xfe, 0xfa, 0xd6, 0xdf, + 0xbf, 0xff, 0xff, 0xeb, 0xc7, 0x9f, 0xff, 0xfc, 0xf3, 0xef, 0x9f, 0x7f, + 0x76, 0xff, 0x51, 0x4f, 0x5e, 0xf9, 0xe4, 0x57, 0x3f, 0xbd, 0xf8, 0xf5, + 0x9f, 0x3f, 0x7e, 0xf9, 0xe7, 0x8f, 0x3f, 0xff, 0xfa, 0xfe, 0x7f, 0xff, + 0xbd, 0xf7, 0xdd, 0xdf, 0x7f, 0xff, 0xf9, 0xe7, 0xef, 0xff, 0xff, 0xfd, + 0xf9, 0xf7, 0x5f, 0x7f, 0x75, 0xff, 0xd7, 0xaf, 0xfe, 0xfe, 0xf7, 0xcf, + 0xbf, 0xff, 0xfd, 0xfb, 0x2f, 0x9f, 0xbc, 0xfa, 0xcb, 0x0f, 0xdf, 0x7e, + 0xf1, 0xfc, 0xb7, 0xbf, 0x7f, 0xfa, 0xed, 0xdf, 0x7f, 0xff, 0xfd, 0xf7, + 0xa3, 0xaf, 0x7e, 0xea, 0xe5, 0xb3, 0x4f, 0xbd, 0xfe, 0xee, 0xd7, 0x5f, + 0xff, 0xfd, 0xfa, 0xdf, 0x3f, 0xff, 0xfd, 0xfb, 0x6f, 0xae, 0x79, 0xf5, + 0x9d, 0x67, 0xce, 0xbc, 0xf5, 0xdb, 0x57, 0x7f, 0x7d, 0xf7, 0xd5, 0xdf, + 0x7f, 0xff, 0xfd, 0xf7, 0x33, 0xef, 0xbc, 0x77, 0xd4, 0x3b, 0x6f, 0x9d, + 0xec, 0xeb, 0x3b, 0xc7, 0x9e, 0xf2, 0xac, 0xc7, 0x3f, 0x7f, 0xfc, 0xf3, + 0x77, 0xcf, 0x3d, 0xeb, 0xdf, 0xf3, 0xee, 0xbd, 0xfb, 0xfb, 0x67, 0x5f, + 0x7d, 0xf7, 0xed, 0xbf, 0xff, 0xfe, 0xf5, 0xef, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xfb, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f, 0xff, 0xff, + 0xff, 0xff, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfb, 0xff, + 0x7f, 0xff, 0xff, 0xff, 0xff, 0xdf, 0xfe, 0xfe, 0xfb, 0xef, 0xdf, 0xfe, + 0xfe, 0xff, 0xbf, 0xbf, 0xff, 0xfe, 0xf7, 0xef, 0xff, 0xff, 0xff, 0xfb, + 0x53, 0xbf, 0xfe, 0xfd, 0xf7, 0xaf, 0x5f, 0xff, 0xfb, 0xff, 0x2b, 0x7f, + 0xff, 0xfa, 0xef, 0x7f, 0xff, 0x7e, 0xfe, 0xeb, 0x7b, 0xef, 0xfd, 0xfe, + 0xed, 0xdf, 0x7f, 0x7f, 0xfd, 0xde, 0x97, 0xef, 0xbd, 0xf7, 0xda, 0xab, + 0x4f, 0xbd, 0xfd, 0xf7, 0xe7, 0x8e, 0x7d, 0xf3, 0xdb, 0x5b, 0xdf, 0xfc, + 0xf3, 0xfa, 0xbb, 0xce, 0x3d, 0xf7, 0xde, 0x7b, 0xee, 0x7b, 0xf5, 0xeb, + 0x73, 0xff, 0x9c, 0x7f, 0xed, 0x7b, 0xe7, 0x9f, 0xff, 0xeb, 0xf9, 0xff, + 0xfc, 0xfb, 0xae, 0xbf, 0xdf, 0x7e, 0xff, 0xe5, 0xe7, 0xaf, 0xbd, 0xeb, + 0xbe, 0xfb, 0xef, 0x3a, 0xf7, 0xe3, 0xab, 0xee, 0xbd, 0xf7, 0xdf, 0x7b, + 0xbf, 0x7e, 0xeb, 0xdf, 0x7b, 0xb7, 0xbc, 0xff, 0xde, 0xbd, 0xee, 0xbf, + 0xff, 0xed, 0xfb, 0xff, 0xfd, 0xf3, 0xde, 0xbd, 0x3f, 0x7f, 0xfb, 0xcd, + 0xf7, 0xee, 0x3d, 0xf7, 0xfe, 0xf7, 0xef, 0xbd, 0xeb, 0xdb, 0x53, 0xd7, + 0xbd, 0xf7, 0xdd, 0x77, 0x7f, 0x7f, 0xf6, 0xdd, 0x53, 0xaf, 0xfe, 0xf9, + 0xe5, 0x5b, 0x5f, 0xfd, 0xfa, 0xff, 0xb7, 0xbf, 0x7e, 0xf9, 0xeb, 0x97, + 0x3f, 0xbf, 0xff, 0xd5, 0x97, 0xdf, 0x7c, 0xfb, 0xeb, 0xdf, 0x7f, 0xff, + 0xfa, 0xff, 0xaf, 0xbf, 0xfe, 0xfa, 0xe5, 0xb7, 0x7f, 0x7e, 0xfe, 0xdd, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfb, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xbf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xef, 0xff, 0xff, 0xfe, 0xe3, 0xf7, 0xff, 0xff, + 0xff, 0xff, 0xdf, 0xff, 0xfe, 0xfd, 0xff, 0xef, 0x7f, 0xff, 0xfd, 0xff, + 0xff, 0x5f, 0x7f, 0xfb, 0xfd, 0xdf, 0xbf, 0xfe, 0xff, 0xfb, 0xff, 0xbf, + 0xff, 0xfe, 0xfb, 0xff, 0xff, 0x7f, 0xff, 0xfb, 0x8f, 0xbf, 0xff, 0xfe, + 0xe5, 0xcb, 0x3f, 0x7f, 0xe9, 0xc3, 0x4b, 0x7f, 0xfe, 0xf0, 0xe5, 0xcf, + 0x3f, 0xff, 0xfc, 0xf7, 0xf7, 0x6f, 0xbf, 0xfc, 0xf7, 0xdf, 0xff, 0x5e, + 0x76, 0xee, 0x37, 0xcf, 0xbd, 0x77, 0xd6, 0xcf, 0x3f, 0xff, 0xfd, 0xf3, + 0xaf, 0x5f, 0xfe, 0xf9, 0xed, 0x97, 0xaf, 0xfe, 0xec, 0xde, 0x73, 0x4e, + 0x39, 0xf6, 0xcc, 0xdf, 0x7f, 0xff, 0xfd, 0xf7, 0x4b, 0x4f, 0x3f, 0xfc, + 0xe2, 0xd5, 0x5f, 0x3d, 0xea, 0xfe, 0xd3, 0xaf, 0xbe, 0xf5, 0xf6, 0xdf, + 0x7f, 0xff, 0xfe, 0xf7, 0xeb, 0xaf, 0xfe, 0xfb, 0xee, 0xb3, 0xdf, 0xff, + 0xf8, 0xd2, 0x57, 0x8f, 0x3d, 0xf5, 0xd6, 0xdf, 0x7f, 0xff, 0xf9, 0xf7, + 0x97, 0x6f, 0x9d, 0xfa, 0xe5, 0xaf, 0x57, 0x9e, 0xf6, 0xfb, 0x33, 0x7f, + 0xfd, 0xea, 0xec, 0xd7, 0x5f, 0x7f, 0xfd, 0xf5, 0x7f, 0xdf, 0xff, 0xfb, + 0xdf, 0xbb, 0xdf, 0xfd, 0xfd, 0xf3, 0xff, 0xff, 0xff, 0xff, 0xef, 0x5f, + 0x7f, 0xfd, 0xfb, 0xef, 0xff, 0xff, 0xff, 0xff, 0xfd, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xef, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0x93, 0xbf, 0xff, 0xff, 0xff, 0xef, 0xbf, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xfb, 0xff, 0xff, 0x5e, 0xff, 0xff, 0x9f, 0x7f, 0xfe, 0xfe, + 0xf7, 0xdf, 0xbf, 0xfe, 0xff, 0xff, 0xff, 0x7f, 0xff, 0xfa, 0xf7, 0xff, + 0xff, 0x7f, 0xff, 0xff, 0x6b, 0xaf, 0x7f, 0xff, 0xfb, 0xd7, 0x7f, 0xbf, + 0xfe, 0xfb, 0xdf, 0xef, 0xff, 0xff, 0xfe, 0x5b, 0xdf, 0xfe, 0xfe, 0xee, + 0x2f, 0xbf, 0xfe, 0xfa, 0xeb, 0xb7, 0xdf, 0xfe, 0xf9, 0xf7, 0xb7, 0x5e, + 0x5d, 0xf7, 0xd6, 0xfb, 0xef, 0xfa, 0xf5, 0xdd, 0x8b, 0xc7, 0xbe, 0xfd, + 0xec, 0xab, 0x4f, 0x3d, 0xfb, 0xfd, 0x97, 0xef, 0xbf, 0xfd, 0xfe, 0xbb, + 0xbf, 0x3f, 0xff, 0xee, 0x7b, 0xbe, 0x3d, 0xf3, 0xdd, 0x7b, 0xef, 0x3d, + 0xf7, 0xa3, 0x77, 0xdf, 0xbd, 0xeb, 0xee, 0x77, 0xbf, 0xfe, 0xf2, 0xfb, + 0x3b, 0xef, 0xbd, 0x77, 0xce, 0x3b, 0xef, 0xbc, 0xf3, 0xfe, 0x2b, 0x7f, + 0xff, 0xff, 0xdb, 0xfb, 0x7f, 0x7f, 0xfb, 0xf3, 0x73, 0xdf, 0x3d, 0xf7, + 0xdc, 0x73, 0xcf, 0x3d, 0xf7, 0xf7, 0x73, 0xee, 0x7d, 0xf7, 0xfe, 0xaf, + 0x7e, 0x7f, 0xfa, 0xf7, 0xd7, 0x6f, 0xbd, 0xf4, 0xeb, 0xaf, 0x3f, 0xff, + 0xfa, 0xff, 0xc7, 0x5f, 0xbc, 0xf2, 0xc5, 0x37, 0x9f, 0xbf, 0xff, 0xfb, + 0x1f, 0xcf, 0xf9, 0xfd, 0xe5, 0xaf, 0x5f, 0x7e, 0xf9, 0xfb, 0x97, 0xdf, + 0xf9, 0xe5, 0xd5, 0x57, 0x3e, 0xbf, 0xfe, 0xf2, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xdf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfd, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xbf, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfb, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xfb, 0xdf, 0xff, 0xbf, 0xf2, 0xff, 0xfb, 0xff, 0xff, 0xfb, 0xff, + 0xff, 0xaf, 0xbc, 0xfa, 0xef, 0xbf, 0x7f, 0xbf, 0xfe, 0xfb, 0xd7, 0xdf, + 0x9f, 0xfa, 0xef, 0x95, 0xfe, 0xff, 0xfb, 0xff, 0xb7, 0xcf, 0x7e, 0xfd, + 0x80, 0x23, 0xbf, 0xbf, 0xff, 0xd3, 0xf7, 0x5f, 0xbf, 0xf1, 0xff, 0xff, + 0x3f, 0xfd, 0xf3, 0xfb, 0xbb, 0xef, 0x1e, 0xf5, 0xfa, 0x3b, 0x0f, 0x3c, + 0xff, 0xd8, 0x93, 0x4f, 0x9a, 0xfc, 0xf7, 0xaf, 0x9f, 0xbd, 0xfb, 0xfb, + 0xcf, 0xef, 0x79, 0xfb, 0xf7, 0x7b, 0xbf, 0xfb, 0x7d, 0xc7, 0xd7, 0xfe, + 0x7e, 0xeb, 0xff, 0xd7, 0x77, 0xfb, 0xfd, 0xff, 0xd7, 0x6f, 0xbc, 0xfb, + 0xf7, 0x39, 0x9f, 0xbd, 0xfe, 0xd3, 0xd3, 0xae, 0x3e, 0xf9, 0xf7, 0xdb, + 0xde, 0xbb, 0xfd, 0xfd, 0xcf, 0xff, 0xbf, 0xfe, 0xff, 0x7b, 0xff, 0x7e, + 0xff, 0xd2, 0xff, 0xff, 0xff, 0xf6, 0xe7, 0xff, 0xb7, 0xfd, 0xfe, 0xef, + 0xe7, 0xd7, 0xff, 0xfb, 0xfd, 0x3b, 0x5f, 0x1d, 0xff, 0xfb, 0xab, 0xbf, + 0xbf, 0xfa, 0xf7, 0xdf, 0xdf, 0xfd, 0xfe, 0xd5, 0x3f, 0xbe, 0x7e, 0xfd, + 0xff, 0xdb, 0xff, 0xfe, 0xf5, 0xf7, 0xfb, 0xff, 0xff, 0xfd, 0xff, 0xef, + 0xef, 0x7e, 0xff, 0xcd, 0xf7, 0xdf, 0xbf, 0xfe, 0xfd, 0xfb, 0xef, 0xff, + 0xf6, 0xfb, 0xff, 0xdf, 0xff, 0xfd, 0xfb, 0xff, 0x7f, 0xbf, 0xff, 0xfe, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xef, 0xff, 0xff, 0xff, 0xdb, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff }; diff --git a/hacks/images/matrix1b.xpm b/hacks/images/matrix1b.xpm new file mode 100644 index 00000000..0260763a --- /dev/null +++ b/hacks/images/matrix1b.xpm @@ -0,0 +1,227 @@ +/* XPM */ +static char * matrix1b_xpm[] = { +"160 182 42 1", +" c None", +". c #000000", +"+ c #030E03", +"@ c #061406", +"# c #081E08", +"$ c #0B2A0B", +"% c #0F390F", +"& c #165016", +"* c #1B641B", +"= c #217A21", +"- c #279027", +"; c #34BB34", +"> c #2BA02B", +", c #5AD25A", +"' c #81DD81", +") c #A7E7A7", +"! c #124412", +"~ c #144A14", +"{ c #175517", +"] c #144814", +"^ c #0E330E", +"/ c #010401", +"( c #0E340E", +"_ c #1E6F1E", +": c #3EA63E", +"< c #40B140", +"[ c #399639", +"} c #0E360E", +"| c #64D564", +"1 c #185A18", +"2 c #144C14", +"3 c #6ED86E", +"4 c #1A5F1A", +"5 c #77DA77", +"6 c #134713", +"7 c #124112", +"8 c #4DC24D", +"9 c #3CA03C", +"0 c #0F380F", +"a c #0C2C0C", +"b c #124212", +"c c #081D08", +".............+@#@+.....@@@@+....+#$$%#@....@$%#@....+@@+..................+@+......@$%%#+...+$%%#+.....+@@@................................................@$$#+", +"............@#%&$@...@#$$$$##...@%&**&#@.@@%*=&##..@@$$$#.......+@@......@$$##....@#&-*$@...#%=*%@....@#%%$#......@@......................................@#**$@", +".+..+..+..+.#%-;*$@..@%***=&#@.@#&=--*%@.#$*>;=&#@+#%*=&$@.+..##%%$@.+..@#*=&#@.+.@%*-*$@...@&=-&$@.++#%->&$@.+..+#$#@.+..+..+..+..+..+..+..+..+..+..+..+.#%->&@", +"...........+#*>,=$+.@$&--->*%@@@%*>>>=&#@$*->;>*$@+$&=-=%#...@#&=-*$@...@%=>*#+..+#*-=%#.+..@$*-=%@++@&*>;=*$@..+$*=%@...................................+#*--%@", +"..+..+......#*;,=%@.+$*>>-;*%@+$&-;,;-*#@%=--->*%@@%*--=*$@..#&=--=$@..@#&--&#...+$=-=%+.....#&--%#.+#*-,'>=%#..#%->*#@..+..+..+..+..@@.+..+..+..+...+...+%=-*$@", +"...+..++....#*;'=%@+.$*--->*$++$*-;;,>*##%=>--=*%@@%*---*%@.@#&=-=&%#@..#&*&%@...+%->*#@.....#%-;&#.+$&-;';=%@@@#&>;*%##..+..+..+..@#$$$$$#++..+...+....@#&--&$.", +"........+..@#&>,=$+..#%&&&&$@+@%*>;>,=*#@%*>>>-*%@+#&=--=%#++$*>>=*%#@..+$%$@..+.+%-;*#@.+...@%-;&#..#&=;,>*%@@%*-;'>=&#..........@%*=====&#.....+...+..@%*=*$@.", +".+.+........@&-;*$@..+##$##@..+%=>;>;=%@@#&=--;-&#@#&->>=&#.+$*>;>-*%+@..+++.....@%-;*#...+..@%-;*#..#%=-->*%@@&>;,',;=#..+.+@+..+@&;>,,;;=#.+..+++....+$*-=%#@.", +".....+.+.+..@$->&@.........+..@%>,;,,=&#@$*=-->-*#@$&=>>-*%.@$=>;;;-&@...........+%=>=$@.....#&->&@@.@%***=&#@@$*=;,==&#...@$%$@..+$**=***&#...@@##@.+.@%==*$+..", +"............+$&*%@.+..........@%->>>>*$@@%=>>>;-&#+@%*---=%@@&=->>;-&#.....+.+...+$*-=%@..+..$&--%@..+#$$$$#@..##&=,*%#++.@#**&#++.@#$$$$##+...@&&%@..+$*>*%@...", +".+......+.+..$&=$@...+...+....+$=>>>=&@++$*-;;-&$@.+#&=--=$@@%->;;;>*#@.+.....+...#&=-&#+...+%==*%+....@+@++....@%->&@@...@%->*#+....@@.@..+.++#*-*$+.@%=-*$@...", +"...+.+.......@&=$@....+...+...@$*->-=%@.+#$%=-*$@...+$***&$+@$&=>>--*#...+.+......+$*-*%@..@#%-=&#..............@#*=%@...@$&-=%@....+.+........$&=*#+.#&==%@.+..", +"..........+..@#$@...+.......+..#&=-=*$@...+#&*%@.....#$$$#@.+@$%%%%%$@.......+.+...@%=&#@...@%*&#@..+........+...@#$@++...#&*&$@+........+.....@$%#++.#%*&$@....", +".+...+.+.......++.+....+.+......#%%%$#.....@$$#++....@@@@@.....@@@@@++.+..@.+...+...###@....@@##@++...+..+.+..+..+.+......@#%#@...+...+....+.+...++...+$%$@..+..", +"..@@###@@..+@@@@@+..+.@####@@...@#$$#@@.....@##@@.+@@#####@.....@###@.+###$#$@+..+@@###@@+..+###@@.....+...........+..+.+..++..................+....+...@@@@+...", +".@#%&*%$@..@$%*&#+...@#%**&%#@@@$%**&%#@...@$&&%@++#%&**&&#.+.@$%&*&$@@%&****&#+.@$%**&%#+.@#%&*%$#.+....+.+...+..............+.+...+..+.+.......+.....@#$&%$#@.", +"+#&=---*$@@$*>;>%#..@$*=-->*%@+#*=->>*%@.+.#&>>=#+@$*>>--*%+.@#&->-=%##&=----=%@+$*=-->*%@.@%=-==*%+.........+......+....+..@@#@@.+.....+..+@@##@@..+.@#&=>>*%#.", +"@%=->>>=&#@$=>,;*#..+$=>>>;-*#@$*>>>;-*#..@%=;;-%@@%=;>--*$+.#%=;,>=%@#*=-->>-%@@%=;>>;-*#@#*>>->-&@..+@@#@....+.+@@#@+...+@#%&&$@.@@@###@++@%&&%#@+..+$*;;;>*$@", +"@%--===-*#+#%*>;&#@.@$*===--*#@$&**=>-*#+@#&->;-%@#%=;>-=*$@+$*>>-=&$@@#%%*=-=%+@%--==--*##%=-==>>*#..@$&&$@.....@$&&$@..@#$&=--&@@#%&&&&%$@#*-==&%#@.@%*-=---%@", +"#%--**=-*$..@%-;*#..+#$%%*--*#.@$%*=;>*#.@$*>->-%@@%=;,;>=%@@$=,>-=*$@.@#$%==*$+#%=--=--*#@%=-=*>,*#+.@&--&@.+...@&->%@@@#%==--*$@@$*=-=-=&#@$*->>*%$@+#&=*=--%@", +"#&-=&&=-=#+.@%-,&$+..@@$&=;=&#..#%=;;-*#+#&=>-;-&@@%*=->;;%#@%=;;;>>%#..@#&--%#.@%->;,;-*#@%=>-=;;*#..@%==%@...+.@%=-%@.#&=;-=&%@@@&=>>->-*#@+$&->>>&#+@$&=>>=%#", +"#%--*%=-=#+.@%-;*#@...#%-;-&#+++@%&---*#@%-;>-;>*#+#%&&*>;*##%=;>-;;*@..+$&-*%+@#%=>->>-*#@$*>;;;,*#@..$%%#@.....@#%%$@@$*-,-*&#@.@&-->>->=#.@#%*-;;*#.@#&>>=&$+", +"#%--*&=-=#+.@%-;&$...@%=>;*%@..#%%&*--*#@%=;>>,>=$#$%%%*>;*@#%=,*=>;*#+.@%*-*$+.@&--==--=#@@%=;>;;*@.+.@$$@+...+.@@##@.+#&=>>=&$@@@&=->>>-*$.+$&-->>*#..#&;>&$+.", +"#%=-===-*#+@$*-,=%#+@$*>;>*%#@@$**&=--=$@$*>-;,;=%@&**&=>;*#@%*;==>;*#..@&=-&#.+@%->-=--*$+@%*=-;>&#..@#%%#@.....+$%%#@.@$&=>>-*$@#%==----*#@%&=>>=%$+..@%==%@..", +"@%*-->>=&@@#&=>;-*%@@&>,>>-*%+@%>>--;=&#+@%&=>;;*%@&=>->>-%@@#*>>-,>&#..@&>-%#..@%=>>>;-&#@#%-->>-%@..@%=-%@+...@#&--%@..+#%*=>-&@@#%&&&&&$@#*--=*%#+...@%=*#@..", +"+#%*=--&$@@$*-->-=&@@%->>--=%#@$=----*$@.+#$*->-*#@$*->-=&$..@$*---=%@+.@%-*$+...#%=---*$@@#&---*%#@.+@%=-%@....+%=>=%@....@#%&&$@.@@@#@#@@@@%&&%#@+.+..@%*&#+..", +".+@%&*&#+.+#&&==**$@@$&===**%@.#%&*=&%@...@@%&=*&@.@$&=*%$@+.@@%&*&%#+..@#&%#+.+.+#%**&%@.+#%&*&%#@...@$&&$@+...@%==&#@+.....@@#@@..........+@##@.....+.+$%%@...", +"..@@###@...+##$$$##..@$$$$%##...@#$$$@@....@##$#@@.@@#$$@@..+.@@#$#@@....@@@++....@@$$#@@..+@$#$@......@#$@@..+.+$&%$@...+....................@..+++.....@#@++..", +"..++##@@....@@@@@.++.@@##@@@+.+..@@@@@@.@@@+@@@@...@@@@@@@@..@@@@@@@@....@@@@@++.+@@@@@@@+.@@@@@@@@+...@@@@@@.@++@#@@@@..@@@@@@..+.@@@.@@@@@.@@@+++@+.+..+@@+...", +"++#%&&%@@+.@$$%%@@..@#%%%%$@@..@@$%%$$#@#$%%%%#@@.@#%%&%%$@.@#%%&%%%$@@@@#%%%$#@@#$%%$$%$@@#$%%%$$@@.+@$%%%%#@@#%%$$%$#@@@$%%$#@..@$$$#+#$$@@#$###%$#+++@$$$$#@.", +".@%=>>=%@.@#&===%@..#&=-==*&#+@@%*===*&$%==-==*%#.$&==-=-=%@@&=-=--=*#+#%*===*&#$&==*&==*$#&*---*&$@.@$&=-==&#$&=-**==&@@%*-==%#@+$&=*%$&=*%$&=*%&==&#+#%**=&%#+", +"+%*->>>&$@+#*-,;*$@@$*>;>>->%@#%=->->>=%&->>----%@$*-;>>>>&@$*-;>->>=$#%=>>>>>=%$=>>=*->-%@&*-;;-*$@.+%*-;>-*$$*>>-->-*#@%=>;-&$+.$=;-*&=;-%%=>>=*>>=##%=>>->-%#", +"@%=-->,*$@.#&->;=&@.$*->>->;&$$=>>=*->=%%->-==>;*$$*->--;;*#$*->-=->=$%=>-==->=%$*>>==->-%@$&='>*%#..@#&*->-&#$*>>->>=&@@$*>>=%@@.$*',==>,>&%=;;==;;*#$=>-==>;*#", +"@&----,=%@+@&=>>-&#@#&=>--;,*$%-;=%%&=*$%=>=*&-;=$@&=>==>>&@@&=>=-==*$%-;=&&===$#*->==>>=$@@#*;-&#@...@#&===%@$&>>>;-%$@+$&->&$@.@@*;,>=>'>%%=>;>->,*$%-;=&&-;=$", +"#&->;,;=&@@#&->-;*%@#%=,->,;*$&-;*$@#$#@$=-=%%*-=%#%=>>;-*%@@%=>>>-*$@%>;*%%**&##&->>->>*$.+$*,-$@...@@#%==*$@#&-',,*%@..@%--&@@..$*,,>;;,-%%=->>>;;*$%-;*$%*-=%", +"#%->>,;=&@@$*--->=&##&=;>>>;=%%-;*$@@@@@$=-=%$*=-%#%=,,'>&$@#%=,,,-%@@%-;=%*--*$#&-;->>-=$..+&;-%@+.@#$#%==*$+#&-;,'-%#..@%--&$#@@$&;;,,>,-%%*>-;;;,*#&-;*$%*=-%", +"#&->>;;-&##%-;;,;-*$#&=>==->=%&->*%##%##%*-=%%*-=$$&=>>>-*&@#&=>>>=$++%-;=&=>;=%#&->==->*$++#*;-%@@+$*=&%=-*$@#&-->->*%@.@%--*&*&@$*,>---;-%%=-->>;;*$%->*$%=-=%", +"#%->-->-&##*>,-->,-%$&=>==->=%%=>-&&&**#%=>=&*-;=$#&=-----=$$&=>-=&#@+$=--*=->=%$*--==->=%.#$*,>&$++%->=*--*#+#*->=->-&#.#&->*=>=%#*,>==*,>%%=-==-,,*$%=>=**-;=$", +"#%=>---=%#$=';-=>,-%$=>,>->>*$$&=---=-*$%-;>->>>&#$*>;>>>>-$$=>;>=%#..$&->>->-*$$*;>==->-%@%*-,>=&#+$=;>->-&@.$*;>-*->=%@%=;'->,=%%=>>*&=;>&%=;-=-;;*#$&->-->>&#", +"+$&->;>*$@$*>>-*-;=%$*>>>>>-&#@$&=>--*%#%->>>>-*%@$*->>>>>*$$*>>>=%@..@$&-->-=%#$*>>=*>>=%#%*->;=&$.$&=>>-*$@.$*>>*&*-=%@%-->>>>=#$*--&&*>=%%=>-&*=-&@@%&=>>=*$@", +".+#%**&%@.@%%&%%&&%#@%&*&&&%$@@@#$&&%%#@#%*&&&%$@.#%&&*&&&%@@$&&&%#@...@$%%&%%@+@%&&%%&&%#@$%&&*&%@.@#%&&%$@..#%&&%$$%%#@#&&*&&&%@#%%%$#%%%#@%&&$%%%#+.@$%%&%$+.", +"..@@#$@@@.@@##@@@@@+.@####@@+...+@###+..@@##$#@@.+.@@##$#@@+.@##@@+.+....@##@@..+@###@##@@.@@$###@....@###@.+.@@#@@@#@@..@@$####@@.@###@@##...@@@@@@+....@@@@+..", +".+@@@#@@.....@@@@....@@@@@@.....@@@@@@...#@@@@@@@..+@@@+@@+..@@@@+@@@..@@@+@@@+..@@@@+@@@..@@@@@@@@...@@@@@@@...@$$$$@..@@#@@.......@#$$$@+....@@@@.............", +"@#%&%%%$@..@#$$%$#@.@$%&%%$@#..+@%%%%$#@@$%&%&%%@+@$$%$$%$$@@$$%##$%$#@#$%##$%$@##$%$$%%$@@$$%$$%%$@@@#%%&%%$@..$&=*%#@+@%&%@@...+.@#%*=&$..+..@%&$@+.......+...", +"$*->>>=*%@@#%=--*&$@$&->>-=%#@+#%-->--%@$*>->>>-%@$&--&*=-&$$*-=*%=-=%$*-=&%*-=%$*--=*--=%$*--=*--=%@$*=>>>-*$@+%-;-&#@.@&*=$@+....@$&-;=%@...#%=-&#@.+.+.....+.", +"$=>,,,>=&##%*->,>=%@$=;,,;>*%@#%*;;;,;*#%-,,',,,*#%=,;*=>,=$$=;>*&=;>%%=;;==-;>&$*;,-=;,>%$=-'>=;'>%#%=;;,;,-%.@%-,=%#..@%*-&$@..+.@@&*,-%@..+$&-;*$@....+......", +"$*--==--=%%*>-==>>*$$*;>-=--*$#*->-=>>*#&->-,>;>*$%=;=&*>;*$$*;>*&=;-%%*,>>>-,-&$&>;-->;=%$&;>-->;=%#%---->;=$.@%-;&$@+.@$*-*%@.....@#*,=%@..@%=->-&@.+...+.+...", +"#&=-**=--%%-,=&&=>=$#&--==>>*$$*--===-&#%->=;,>,&#%=-=&%-,*#$&--*&*-=$$*;,;,-;-%@%=>;>;-&#@%*--->-&#@%*==->=&@.@%-;*#....@%=-*$@.....#&;>%@+.@%--->&#+..........", +"#&=>===-=%&->=%%*--%$&->--;-*#$&=;;--=%@$&==,-=*$@$=-=%&-;*##&--*&=-*$$*,;,,-'-%@#%=;,-*$@.#%=>'>&$@@#%&=>>*%@.@%-'&$.+..@$&==&$@.+..#*;-%@..@%***=&#@+...+.+...", +"@&=;,,;-*$%-,*&%*-=%#&>>,,>=%@@%*->>,>&@@#%&,-&%#@%*-=%%-,*#+$*-==-=&##*>,;>;,-%@#%*>>-&$@.@$*>,=%#..@%&-,=&$@.@#-;*#@....@$*-=%@....@&'-%@..@#$%$%$@.....+.+...", +"#&=,;;>=%#%=;-=*->=$#&>;;;;=%#$&==->,>*#.@$*;-&@+.%*-=&&-,&#@#&=---*%@$&,,>-';-$@$*->>>*%@..@&>;*%@..@%=>;=*%$.@%-;&$+.....#%==&$.+.@#*>-%@+..+++++.+.@@@@#####.", +"#&->>=*%$@$&->,>>,*$$*>>-=;>*%%=>-==;,*#.@$*,>&$@.$*--==-;&#.@%->>>&#@#%-;-=;>=$#&-'>-;>=$.@#&-'*%@+@$*>,-->=%.@%-;=%@..+...$*==%@..@%*,-%@..+....+..@#%%&%&&&%@", +"$*>,-=%#..#%=,;,,-*$%=,>==-;-%&-'-->,-&#+#&-,>*$@.#&=--->-%@.@$*>'-%@.@%--==--*$$*,>-=>)-%@@%=;,=&@@@$=;;->;-%.@%-,=&$......@&=>%@..#&-;=%@..........+%*======*$", +"%*=--*%@.+@%*>>>,;*##&--*%*-=%$*---=-=%@@#%=--*%@.@#&=--=*$@..@%=-*$@.+%*=*&==&##&--=*=-=%..%*=-=&#+@$*-----*$+.$*--&$@...+.@%=-&@+@$&--=%@+..+.+..+.+%=>>--->=%", +"@$%&%%#@...#%*****%@@$%%%#$%%##$%%%&%$#..@$%&%%#@..@#%%%%%@..@+#%%%@@..@%%%$%%#@@$%%%%%&%#..#%&%%$@..@$%&&%%%@..#%**%$@+....+@%&#@..#%**&#...........@%**====*&#", +".@@@#@@....@@$#$$$@..@@#@.@@@..@@#@@@@.....@##@@+...@@#@@@.....@@@@@+..@.@@+.@@..@@#@@@@@+.+.@@#@@....@@@##@@@..@@#$@+.......@##@....#$$@@.+....+.....@#$$$$$%$@", +"..+.@@@+.+.+...+..+@.@#@@...+.+.+...+.+.+..+@@@@@........+.+...+@#@@@..+........@@#@@........@@@@.+....@@#@..+.@@#@@...+.+@@@@@..+...........+....+....+.+++....", +"...@#$#@............#%&%#@..................@%&%#@+.+........++$%&&&$@.......+.+@%&%#@......@$%%$@..+..@%&%@@.@#&&$@.....@#&&&$@...+.....+..........+...........", +"..@$**%@...+.@.@....$*>-%#@.....+..@.@.....@%=-=%+...@@+@....+#&->;-%@.+.+@.@...$*>-%#@+.+..@&--%#....@$=-*$@.@%->*$@....@%=;>&@.....+@.@..+.+@@......+..+.@@.+.", +".+@%=,*$@..@@#$##@.+#*>-*%$@@+.@@#$#$#@.+@@#%=>-%@.@@##$#@.++#%*;;-*%@.+@##$$##@$*--*%#@@...#&--&@+..@#%=>=$@.@%=-*%$$@+.@#*>'*#.+.###$$#$@.+####$$@@..+@#$##@+.", +"..@$=-*%+.@@%&**&$@@#&->=*&%#@@#%&***&%@@#%**->-&@@#%&**&%@.@%*-,-=*$@@#%&****%##*->=*&%@@.@$*--%@@.@#&*--=%@.@%*-=&*&%@..@%-;&#..#%******%@@%*&&*&$#@+#%&**&%@.", +"...#%**%@.@$*->;-&#@#&->,,,=&##&=,->;'&@#&=>;,;-&@#&=>>>-*%@#&=;,;-*%@#&=>>>,>*$#&>>,;;*%@+@%=>;&#..+$*->'>&@.@$*--->=&@..@%=,*#@.#=>'>,'>*$$=>>-->*%##&=>>>-*%@", +"...@@%%#@.@%->',>*%@#&>;;>;>=$%=>,=>'>*#%=>'>;>-%@%=;,>;;-&@@&-,;>-*#@%*>,-;,;*$#&-,>;,=*#.@%*;;&#..@$&=>,>&@.@$*->;>=&@..@%-;&#+.$=,,,;,;=%%=;;--;-&$%=>;>>;-&#", +".+...@@@+.@%=->>'=%@#&->===,-%%-;-**->*#%-;-=->-&#%=,;>>,,*#@#&->=&%@@%->>==,-*##%->=*--*#.+#&-'*#...@$%&=;&#.@$*>,)-&$@+.@%='*$..#&--->>>-%$&->==--*$%-;-*=>;*#", +"..........#&-,;;,=&@#&--=&=,=%&-,*%%**%#%-,*&*--&#&>';'',>*#@@%--=$@..%=,>>>;-%@#&--**=>*$..@%-;&$@...@@%*,&#.@$*;,>=&@@..@%--&$@.#&--->---%$&--**=-=$&-;=**>;*#", +".+.+.....+#*>;-=,-&##*->=*=,-%%=,-*&**&$%=,-=->-&#%=,>->>>&#@#&--=&$@.#&=>,;;-&@$&--**=>=$@@$&-,*%@+..@#%*>&@.@%*>-'>*%@.@$&-'*%@@#*->->---%$&>-**=-=$&-;-**;;*#", +".....+....#*,>>>,-*$$*>'>>>,*%%=>>----*#%=>>->,>*$%=;>>>;>&@@%*>;-=&#.@$*=----%@$*,>=*>>=%@#&=,'=*%@.@%&*=>&#.@%->--,-*$@#&=,;=*$@#*>>->>>-&$*>;==-;=%%=>>>>>;&#", +".......+..@%-;>>>>*#$&-;>>>=&#$%=>>>>-&##&=>>>;>&##%=>>>>=%@@&=>>>-*#@@$*=---*$@#&;>=*-;=%@#*=-'>*%@@%*-->=%@.@&--=*>>=%@#*=>,>*%#$*>-=->--&$*>>-*>;-%#&=>>>-*%+", +".+.+.....+@#%&****%@#%&&**&$#@@#%&**&%$@@@%&**&*%@@#%***&&#@@$&*=*&%@.@%*---*%#.#%**%%**&#+@%&**&%$++$*--=&$@.@#&&%%&*&@.#%&***%$@#%**&&*&&$#%&*&%**&#@#$&**%$@.", +".....+.....@#$#$$#@..@#####@.+..@##$#@@...@##$##@@..@@$##@@..@##$##$...#$%%%$@..@@#$#@#@@@.@+###$@@..@%%%%#@...@######@@..@##$#@@.@##$####@@@@###@##@@.@@#$##+..", +".......+...+....+.+.+........................@.......................+...@.@..+........@...............@@.+......@@@#@.+..+@#@@....@@@@@+.......................", +".+.+..................+....+..+.......+.+.@#@@....+........+............+......................+...+.........+...@$%%#@....@%&$@+..+#%%$@@...........+.+....+...", +".....+.+.+.+..+@........+.@.....+.+......@%&%#@+....@+.+.....+@+.+.@.+.....+..+.+.+@.+.+.+.+.........+...@+....+@%**&#@...@$*-%#...+#&**%@.+.+.+.+......+.+...+.", +"@@#$$$#@@..@@$#$$#$.+@#$$##$@...@##$$#@.@$&=*%$@..@##@@##@@.@@#$###$#@@##$@@##$.@@#$##$$@.@@$$@@$$@..@@$$#$#@...@&>-%@.+.+@%-,&#.+..@&--&@.........+............", +"#%****&%#@@#$&****%@@$&*&*&&#@.@#%&*&&%@@%->-=*%@.$&*%$%&%$@#%**&&**&$#%*&%%&*&$#&**%&*&%@$&*%%%&*%@@#%&***&%@..#*>-%#....@%->*#....@%-;&$....@@@@@@....+.+.+...", +"$=>;>;-=&@$&*-;>;;*$#&=>>>>=%@+#%=>;--&#@&>','>*$@&>>*&->=%@$*;;-=>'-%%*;>=*=;>%%=>;=-'>%#&>>-&=>;*#@%=-';'=&@+@$*)-%@.....%-;*$.+..+%-'*$@+.@$$%$%$#@..........", +"$*',---'*%%=;-->';*##&=);>>=%#@%*>'>>-*$@&->>==&@@&-'**=>-%#$*'>-=>,-%%='>---'-&$*>'-->-%@%-,-=-;'&#@%-->-,*&@.@$=,=%@+.+.@%-'&#....@%-;=%@.@$*=-===&@+....+....", +"+&->-=*,-%&='===>>&#@#&,>=*&$.@$=>,,>=&@@%=--*%$@.%=>=&*--&@@$=-==--=$#&>>>,->-%##*-,;=&$@#&->->-=%@@$*->,>*%@.@#=,>%@....@%=;*#.+..+%-,-$@.@&>;;;;-*#..+....+..", +"#&>,>--;=%%->-->>>&@@$*>=*$#@.@$*>,>>-*@@$*-=&%##.%=-=**--&@@%*--=>=%@#&>>,;>;=$@$&-,>=%@.@$&>)>=%@.@$*=;>-&%@.+$*>-%@....@%-,&#....@%->*#@.@&--->>=&@.....+....", +"@&-;>,-=&##&=-->>-&#@%*,=*%#@.@%*->>>;=$@$*--**&%@%*>-*->>*#.#%=>>>*$@#%->;>,>*##%*>,;-&$@.#%=,>&#..@$*>,--*&@..#&,-%@+.+..%=>&#.+..@%-'&$.+.#&&%&&%#@+.+...+...", +"#&->-*&%#@@#%&==>-*##&-,==*$@.@%->>>>)=$.#&-;--=%#$&->--';*@.@$=>,=%@.@%*>>->=&#$*-;->>-%@@%*>>=%@+.@%=,>>--*#..#&>-%#@...@%==&@...@@&--&@...@@@@@@@@........+..", +"$*;;-*%#@..@#$*-;>*#$*-,>>=%@.@%=->>>=&#.@$*>>-*%@@%&->>>>*#..#%==*$@.@#&=**=*%@#=>-=-;>%@$*,>,=%@..@$=>>,;=&#+.@%-=&#@.+..@&&$@....#&=-%@.......+......+.+.....", +"#*>>=*#@....@#&=>>*#@%&&&&%#@.@@%%**&%#@..@$&&%$#..@$%*&*&$@..@#$%$@...@#$$$%#@@@%&%%%&&#@#&==*&#.+.@#%&*&&%$@...#%&%@@....@##@@+..@@%&%$@+.+.......+........+..", +"@%&*&$@@.+...@%&*&%@.@#@#@@@....@@###@@.....@#@@@...@#+###@.+..@@@@.+....@@@@@...@#@@#@@@.@#%%%$@.....@@###@@.....@@@@..+.........+.+@@@@......+......+.........", +".+@@...........@@@.....@@@@+......@@@.+.+.......+...@.@.@@.....@@@@.....@@#@#@..............@@@@@.......@@.@.+.+.............+..............+..@@@@.....+.+..+..", +".+#!~{]^/..+.......+...@$%#@..+.@#$$$@@...+.......+#$$$#$%#@+.@#%$@.+.+@#%&*&%#@...@@@@@+...@#$$$@@+.+.##$@@..........+.+.+.....+........+....@#$$##@...+@##@+..", +".(_:<[[_}+...+..+....+#%*-&$@..@#&===%@.@@@#@@@@@@@%*=**==&#..@%=*%....#&=,>>=%@+@@#$#$$@.@@%&==*%$@.@@%&*&$...+.+.+.........+....+.+.+.....@@%&==*%$@.@#%&*%$@.", +"+&<,,||<1.....@@.....@$*>,=%#@.#%->,>*$@@#%&&&&&$@#&>,>->)=$..#*;-%@..@%*>>->=%@..#%&%&&#@@%=>;);=&@.@$&-->&$.....@.@@@..@@@@@@@..........+.@$=>;';=&#.+%=>>=%@.", +".2,3333,4+.+.@#$$@+.@$*-,;>*$@@#&>>-=&#@@$*->>-=&@@%-;>>'-*$+.#&,=%@+.$&-'>-==$@.@#%%%%%@.#&>,,;;>=$.@%=->'&#@..#$$%$$$@@$%&%&%%$.....@@....$&>',,;>=$@+$*--*%@.", +".2,|,55,4...@#%&%@..@%=->>>*%@@$*>-*&$@.@%->>>;>*$@$*>>-,=%#..@%;-%@..%=>;)>-*$@+.@##@$@@+%*>;,>>>-%@#&=--;*#@.$$&=***&@$*->;>>-&@+@$#$$$#@@$=-,;-'>=%..@%%%$#+.", +".6,|,|||%...@$&*%#..@%--===&$@@%->>=%#@.#%---->-*$@@&-,>;*$@+.#&>=%@+.%-'>,>>-%@.....@...@%=>,>>>>=%@#&-->>*$@@%&-----&#$*>';',;&#@$&*=***$@%=->;>;>=&...@@@++..", +".2,,33|,1+.+.%*=&#@.@&--=**&$@@&-,,>&$@.@&->-=->=#.@%*,)>*$@..@%-*%@.@#*>>>>,'&#...+......%=;,,>>--%@#*=;;'*%@$*-;->>=&@@%&&*=-'*##%*->>>-%@%=>;,>>-=%@.........", +"+6||3||,7...#%->=$@.@%=>---*#@@%=;>-*$@.@%->>->>*#.#%=,,=*%@+.#&-=$@..#%==-;;=%@+....+....$*;,;,;>=%@#&-,;-*%@$='->>;=%@@@#$$&->&#@$&*==*&$@$*>;;>;>-%@...+.+...", +".&|5|,5,2...#&,)-%@.@#&->'-&#@#%->,==&&@@%=>>,;-*#.@%=>)-*$@..@&>-%@+.#&===-;=%@........+.#%=>>>;>*%.@%&===%#@@&='->>-&@....@$&*%@@@$$$$$$@+@&->;>;-*$..........", +".48,,|,8{+..#&,,=%@..@$&>;*%@.#&,,,>,>=$@$&*****%@@#&-,'>*%@+.#*'=%@..#*->>;-&#@+.+..+....@$&=>,-*%@.@@$%%$#@+@#&=----&@.....@#$@...@@@@+...@$&=>;>*%#+.+..+..+.", +".4=9999_0...@%-,-%@...@%*-%#..@$->>>;>*#+#$%$#$$#@.@%*-'>&$.@.@%>-%@..#*=,>>*%@............@$&=-*%#@..@.@@@@...@%&*&**&#+.+....+.............@$&=-*%#+..........", +".ab2222ac+..@%==&#@+...@$%$@+.@#&&*&&&%@..@.@..@...@#%&&&$@.+.#%-*$@..@$**=&%@.....+.+.+....@#$%$@@+............@#$$#$@+........+.......+.+...@#%$$#+....+.+....", +"......+......@$%#@......@@@.....@##$$@@..+.....+.+..+@@##@....@#&%@@+..@#$##@...+........+....@.@.....+.+..+.+......+@....@+.+.....@.+.......++++@....+.....+...", +"+.@@##@..+.........+.+@####.+...@###@.......+@..............+.@#$$$$@........+...............@@@@..+....@..............+@$%%@@..+@@%%$@...+.@$%%$#@..........+..", +".@#%&&%@...+.@@@@....@#%&&%#@.+@$&&&$@.+.+.@@#@@.+.......+...#$&****%#...........+.+.+.+...+@$%&#@.....##$#@..+.+.+.....$&=*%@@.+@%*=&#@@@#@%*-=*$@@#@+.+.@@++..", +"+#%*=*&$@....@$%$@...@$*==*%@..#&===&$@...@#%&$@...+.+......#%=->);>*#+.+..+.+.............@@&=-&@.+.@#%**&$@.......+...$*>-&#@#$#&=>*$#$%&$&=--=&$%%$...+#%$@..", +"@$*-=-*&#+..#%*-&$@+.@%*=-*%#..#&=-;*$@...@%**%@...@@@@@#$@+#&>,>,,>*#.........+.......+.+.@#&-;&#...$%*=-=&#@..@@..@.+.#*>>&$#&*%&->=%%***#%=->=*&*=$@.++%*&#@.", +"@$*-=-=&@.@@%&>'&&#@.@$*=-*%@+.#&=-'&%@+..@%=*$@+.@%&%$$&%$@#*',;,>=&#...+@#@....+.+........@&-'&#@..#&--=-*%@@#$$$$#@..$&--*%&*=%%=-=&*=-*$%=-;-====$...@%*&#@.", +"@#%=-=&%@.@$=-;'>=&#.@%*--*%@..$&---*%@...@$%$@...$*--&&--*##&>;,'>=&#+..@$&%$.......+...+..#%=,*$@+@#&=---*%@@&*****%#.$*>-=*=-=%&=--==--*$%=->----&#@.@#&-*$@.", +".@$&**%@+.@%>'',;;=$.@%=--*%@..$=---&$@+...@@@..+.$*;>**--*##%->,,>=&#..@#&-*$#.............#&>,&$@..@&=---*$@#&--->-*%@%*->----=%&-->>>>-=%%==>->>-&@@+#%=>-%@.", +"...#$$@@..@$&=-'-=&#.@%***&$@+.#&=**%#............#&>-**=-=$@$&=;,>=&#+.@#*-=$@.+.+@#@.+..+@#&*=&$@..@%=>>-&$@@&=>>>;>&##&*=-->;-%%*=----->%$&==;;;;*#.@%*-;=%@.", +"+...@@..+..#$&--*%#@..@$%%#@...@#%$%@@.+.+.+.+..+.$&>-==->=$.@$*-'-=&@...@%&%@....@$&%#@....@#$%$#@+.#&-',;*%@@%=>->,,&#@$&=->-'-%$*=-==---$#$&->-;;*#@#*--=*%#+", +"..+........+%*=-*%#@...+@@@......+@@..............#&>>---'-%@@$&-,;-*#....@#@.....#&-=%@..+...@.@....@%*->-&$@#&=---;>&#@%*---='>%%*-=**->*$#%=---;,*#+%*--**&%@", +"........+.@$*=->-*%$.......+.+.......+........+.+.#%-',>>>-%@@&=;,;>=#+......+.+.@$='-&@...........+.@@%%&%#@.$*--->>=%@@$===--;>&%*=*&=--*$$&===->'=#+$*->--=&@", +"+.+..+....@%->,>'>*#.+.........+.......+.+.+......#%=-=*&*%#.@&=>-';=$..+........@$*'>&#+...+.+.+.......@@@..@@&**&*&$@+@$&&&&*>>%$%&%%=---$@%&%%&->*#+#&=>>>=&@", +"........+.@#&&&&&&%#...+.........+................#%**%$#@@..@#&*&&&%@....+......@#&**%@.................+....@#$$$$#@+..@##@#%%&#@#@@#$&%%#@@$#@$%%%@.+#&=--*$@", +"..@.@+.....@@#$#$#@......@.+.+....++.+......+.+.+..#%%$@.......@####@.+......+.+..@%%$@...+.....@.+.+.+.+.++...@.++@@.....@@@@@@@......@###...@.@+@#+...+@%%%$@.", +".@#%%#@.+....@#%%#@+.+@#%&#@...+@#$%#@.+.+@@@@@@..+@$%&%#@+...@@@@@@@@..+@#@@@@..@#&%#@@....+@%%$#+...@#&%#@...@@@#@#@+..@@$%@@..+..+@@$%$@@..@#&&$#++..++@@@@@.", +".@$&*%#@....@#%**$@..@@&*=&@@..@%&**&$#..@#$$#$@@..@$*=*$@..+@@%%%%%%@.@@$%%%$#@.@$**%#@+...@#%*&$@..@#%==%#@+.@$&%&&%@..@$&&&#@.....@$&=&#..@#%==*$@+.+#$#$$#@+", +".@%*=*%@+.+@#%==&$@.@@%*--*$@.@$&-;>=%@..@%&&&&$@.@#%===%@...@$======$@#%*===*&$@#%*-=&$#@@@%&==*&@@@$&*--=%#@@$&===**$@.@%*==%$@.@@#%*==%$..@%*--=&#++#%&&&*&$@", +"@$&=--%#@..#%*--&#@.+$*---*$@.+$=->>*%@.@#*===*$@.@%*->=%@+..@%>')>'>%$&='>;;,=$$&=->>-=%@#&*->>-=%@#&=>>>>=%@$&->>>--%@@$&=--=&$@.@%*->=*$@@$&=-->*%@+$*-=--*&@", +"+$*>',*#@.@#*-'>=$@.@$*>',=%@.@%=>),*%@.@$*>'>=%@.#&=',-&@...#&-'>--=%%-;=**=-*%%=;'-';>&#%=,,>';>&#%=>'-',>&#$=;'>,;>&#@$*-;,>=%#@#*-';>=&@@$=-;,;=&@+$*>;,;=&@", +".$&--)-%#+@$&=,'-%@..$&-;)-&@..$&-;'-&@.@$&-,)-%@.@#*-'>*$@+.@&>,>>-*%%=)=%$%*&##&=-==-'&@#%=-=->;&@#&->==>>&@$&=>==>;&@+@&=>'-*$@+$%=>,-*$++#&=>,-*$+@#&=>;-*$@", +".$&>;-;&$@@#*->->*%@.$&>->>*$@@#&-;->*%@@$&>->>*%@@%*;>;-&@@@$*,->,>*$%-;*$#$%$##&=>=--*%@#&=-==-=%@#&=-=--=%@@&=>=--*%@.@#&>;*%@..@$&>;*%@..@#&>;*%@..@$&>,*%@.", +"+%*>;-'=&@@%=>,-'=&#@$=>,-'=&@@%*-,-'=&@+%=>,-'=&##&=,-;>=$@#&*;;,';*#&*'=%%%%%@@%*,>>-*$@@&=,>>-*%@#%=,>>-&$@@&*,>>-&$@..@%-;&$@...+%-;*$@...@$-;*#+...@%-;*#+.", +"@&-,,-,-=##%-;;>,-*$#&-,;>'-=#@&-'>;,-*$#%-;;>;-=$%=>,>,>-%#$*>,;--=&@%=>-===-&$#&=;->>*%##&=>>>>*%##&=>->>*%@@&=>-;-*%@..#&-,&$@+..@&-,&$@+..#%-;&$@..+@%>;*#@.", +"#*>;>->,-%$&,;>->'-%$&;,>--'-%$*>,>->'-%$*>,>->,-%&=,>->,;*#%=,>>>--=$#&=>>>>>*#$&=,-->-=$$&->----=$$&=,----=$$*->->--=$@@$&-'=%$@.@%&-,=%#@.@$*-,=%$@.@%&>;=%#@", +"%*',-=>'-&%=,>-=>'>&%='>-=>'-&%=,,-=>'>&$='>-=>'-&&>'---,,*$&>,-',>>>%@$&='>=*$@$=,;->;,=%%='>>>'-=%%=,>>>>,=$%=,'->;;=$@#*-,,-*&@@#&-,,-=%#@$&-,,-*&@+#*=,,-=%#", +"$*>>=*=;-%$*;>=*=>-%$&,>=*->-%$*->=*->-%$&,>=*=>-&&->-**->=$&=>->;>>-%.@#*>>*$@.#*-,>->>*#$*>;-->>=$$*>>>-->*##*-,-->>*#@$&=>>-*&@@#&=->-*&@+$&=-;-=%#.$*=-;-*&@", +"@%&&%%&&&##%&&&%&*%$#%&&%%&&&$@%&&%%&*&$#%&&&%&*&#$&*&%&&&%#$&&&*&**&@.@$*=*$@..@%&*&&*&%#@%&**&*&%##%***&&&%#@%&*&&*&%@+@%&*&&&$+.#%&&*&&$@.#%&&&&&$@.#%&*&&&$+", +"@@######@@@####@#$#.@@#$####@@@+$#@###@@@@######@@@####$$$#.@#####$##...@#$#@....@@$$#$#@@.@$$$###@..@#$$$$##..+#$$$$#@@..@@#$#@@..+@#$$$@@..+@@###@+...@#$$#@@.", +".+@@@@@@...@#%%%%$#...#%%#@......@$%%@@...@$%%$@...@#$%%%$#...@@#@@.+.+......+...+.@@@@@@..@#%%$@......@#%$#@...@$%%$@....@@@@@+......@$%#@+..@@+++......@@$@+@.", +"@#$$%$$#@..@$*-==*$@.@$&=&$@..+.@#&**$@..@#&==&$@..@%*=-=*$@.@@$$$##@........@...@@#%%%%#@.@$*=&#@@+..@#&**$@+.@$&==&$@.+@@$$$$#@+...#$**%@@@$$$#@+++...@$%&%#+.", +"@&*=*=*&$#@$&->>-*$@.@%*=*%#@...@%=-*$@+.@%*--*%#.@#&->>-*#@.@$*&**%@.+@$@@.@@@.@#%**=>-&@@#%*-*&#@.@@$%=-*%#@@@%=--*&$.+@%*&&&&$@@@#%&==&$@@&*=&%#@.+.#$*--=%#+", +"$&,>>-->*$#&=->;-=%@.@%*--*%@..@%&--*%#.@@&=---*$@@%*->;-*#@.#&====*$@@#&%$$$%$@#&=>>>,'*@#%**-=*&$#@%&*--=*%@@%*-=--*&@@&*=====%@@$&*=--*&#$*-;-*%#@+.#&->>>*$+", +"$*;;---,=%%*>>=->-*$@%*->--=%@#%*-->-=%@@%*-->-=%@#%*->>-=%@#%*->--=%@@%=**%*=*#%*>;-;,>*#$*>-==--*#$*--*=>-*$$*--==>-*$$*>-*=>>*$$&->-=>>=%$&-,>-=&$@.#*->>;=%@", +"$=>>-=*>-&%-;,-=>,=#$&-;-->>&#$&-;-->>&#$*---->>*#$*->--;>&#$*----;>*@@%->-=--*$%=,--->>=%%-;-**>'*$%=,-**>,=$%-;-**>,=$%-;-**>;=#$*;>==>;-%#&*,;;>-*#@$*->>,=&#", +"%=,,>=*--&%->>--;;*$%=,=**>>=$%->-**>>=$%-,=**->=$%-,=**->=$%-,=**->=$@$*>,>'*%#&-,*-----%%=>=&&>;*#%->=&&>>*#%=>=&&>;*#%=>=&&>,&$@%->-=>-*##&=-===>=$@$*-;,;=&#", +"$=>,-**=-&%=>>>->,*$%=,=%%=-=%&-'=%%=-=%%=,=%&=-=%%=,=%%=-=%%=,=%%*-=$@#%=,,>*%#%=,---=--%%=-=%&-,*$$=-=%&-,*$%=-=%%-,*#%=>=%&='*#@$&->>;*%@@%=-===>=%@$*=-->;=%", +"$&>-=&*=-&%=>->>,;*#&-;*%%=>=%%->=%%=>=%&->=%%=>=%&-;*%%=>=%&-;*%%=-=%@$*-;>,=%#%-,--==>=%%=-=%&-,&#%*-=%&-,&#%*>=&&-;*#$=-=&&-;*@.@%=;,-&#@#&=;-->;=$@#=====,-%", +"$*>>=*=>-%%->-=-;'*#$=,=**->*%%=,=**->=$%=>=**->=$$=,=**->=$%=;=**->=$@%=>-->-*#%=,>--->=$$*--**-;*#$*-=**>>*#$*-=*=-;*@$*--**-,&#.@$*>,=%#@$&=,>>>-&#@%=--==;-%", +"$=,,>->,*%%-,>=-,>*#$&=->>;>&#$&=->>;>&#$&=->>>>&#$&=->>>>&#$&=->>;>&#@%==*&*-&#%*>;>>;>&##&=>>>,-%@#&=>>>,-&@#&=>>>;-&@@&=>>>;-&@.@%=,,-&$@$=;,-=*&#@@&-;>>;,-%", +"%*-'>'>=&#%=>;**>;&#@$&=;>-*%@@%&=;>>*%@@$&=>,>*%@@$&=>'-*%@@$&=,>>=$@@$%%##$%%@#*->;;>=$@@$&>,>-=%@@$*>,>>=$@@$*>>,>*$@@$*>;;>=$@.@%=>,>*%@%=>;=*$@+.@&-;-->>=$", +"#%&&&&&&#@#%&&%$&%#@.@#%&&%$@..@$%&&&$@..@$%&&%%@..@$%&%%$@..@#%&&%%@..@@@@@@@@@#%*&&&&$@..#$&&&&$@..@#%&&&$@..@$&&&%%@..@#&&&%%@.@@$%&&&$@+#%&&%%@...@#&&&%&&$@", +"@@##$#@@@.@@@@@@@@@...@#@##@....@@@@@@....@@@#@@.....####@.....@@@@@............@#$$##@@.....@#$@@@...@###@@@....@@#@@@...@@##@++...@###@@@..@#@@#.....@@@@#@@@.", +"..@@@@.......+@@@@.+.+.@@@@.+....@.@.@+...+.....+....@##@.+.........+.............@@@@..+......@@@@+...@@@@.+.........+...@@@@.........@@@@...@.@@@.+...........", +".@#%$#@.+....@#%$@....@$%%#...+.@##$#@.....@@@@....+@#&%$@...+........+.+.+.+.+..@#%%#.....+..@$%$@....@%%$@...+@@.@@...+.#$%#..+.+...@$%$@.+.+#%%#@....@@@@@@..", +".@$&*%#...+.@$&*%#...@#&**$@...@%&**&$@+@@#$###@+...#%==%@+....+..+..............@$&*%#@+....@$&*%@+..@%**&$@..@#$$###...@$&&%#.....+@$%*%@@..@%**%#@..@@#$#$@@.", +".@#*=*%#...@$&==%#.+@#%--=&#+.@#&-;;=&#.@#&*&*%#...@$&==&$@.@@######@...@#$##@@.+@$*==%#@...@#&*=%#..+#&=-=%#+@#&*&&&$$..@$*=*%@....@#&=*%@..@$*=-*$@..@%&&&&$+.", +".@%*--&$+..#%=-=%#..@%*---*$..@%=->>=%@.@%*===*$@+.@%=--*$@.@%&&%&&&%@@#%&*&*%$..#%*=-*%$@@@%&=>=&$.@@%=---*%@@%&====&$..@$*--%@+..@#&=-&$.+.@%=>-*#@..#%*-=*$@.", +"@$*->,=&#@#%=>,>*$@.@&->'>=%@+@$=>>)-&#@@&->'>=%@.@#*-;'-%#@$*-;--'>=$$&=-,>)>&#@$*-;'>=&#@$*->)>=&#@$=-,;'-&##&=,>'>=%@.@%=;;&#...@$=;;*#@..@&-;;*$@.+@&-;;*$@.", +"+$=->>;*$@#&---;-&$.#&=>>;-&#.@%=-->;*%@#&-->;-&@.@%*---;*%@$=>>)>->>%%='-=-,>*@#&>,-->,=$#*;;-->,=$#&>;---,=%%='-->;>&#.@$*>'&#.+.@$*>,&#...@$*>,&#@..@$*;;&#@.", +"@%=->-)=%##*->>)>*#@#*->>'>*$.@%=->>,=%##*->>'>*$@@%=>>-)=%#$=--,,--)&%='=&*=-&@#&;,---,-%#&,,>--)-%#&,,---'-%%='>--,)*$..#%-;*#...@#%-;*$..++#%-,&$....@%-;*$..", +"#&>;,,>=&#%=;,;,>*$@%=>';,>*$@#&>,,;;=&@%=>;;,>*$@#&>';>;=&#&=>,';>>>%%=>-===-&#$*',-->;=%$*'>>>>>-$$*'>>->;=%&-'-->>-*#..#&-,&$@+..#%-,&#@..+#&-;*#@..@#&-,&#@.", +"$*;>-->=&#%=;-->>*%@%-;-->-=%@#*;>-->=&#%=,-=>>*%@#*>,-->=&$*>--''>>-%$&->;>>>*##&;'>>->=%#&,';->>=%#%,';>>>=%%='>->>-*#.@$&-,*%#@.@$&-,=%#+.@$&-,=%#@.@$&-;=%#@", +"#*>,->,-*$%-'--,>-%#%-;--;;=%@$*>,->)-*$%-;->>,=%@$*>>>>'-*$*>,;'>;>-%@$&='>-=%@#&-,>>>,=$#%->>>>;=%#%->>>'>-%%*>;>>,>&#@#&->'=*&@@#&->,=*&@+#&->,=*&@+#&-;,=*%#", +"#%==-=-=*##&=-=--=%@#*=--=-=$@@%*-==-=*$$&--=--*%@#%=-===-&#%*===--=*#.@$*;>*%#..#%=-===&#@#&=--==&#@#&*-===&#@%&=-==*$@@#&=---*&@.$&=->==%@@#*=---*&@+$&==>-=&@", +"+#&&*&*&%@@%&*&&&%#@@%&*&&&&#@@#&*&*&&%@@%&**&&&#.@#&&**&&%@#%&&&&&&$@.@$=>=&@...@$%&*&%#@.@#%&*&%#@.@#%&*&%#..#%&&&&$@..#%&&*&&$@.#%&&**&$+.@%&**&&$+.#%&*&*%$@", +".@##$$##@..@@$$#$#@..@#$$#@#....@#$$#@@..@##$##@@...###$##@.@###@#@@@...@$&%#@.+...@@##@@...@+$##@@...@@####.@..@#$##@+...@#$$$@@+..@#$##@@.+.@##$$@@+..@#$$##@+", +"+@@$$#$@@....@@@@@....@@@.........@@@@....@@##@.+....@@@@@...........+...@...............+..@@@@...+....@@@@....@.@@@.................@@@@..@@#@@...............", +"@$***&*&$+.@@$%%$#@+.@#$$@@.+.+..@#%$#@+..@%&%$@..+.#$%%$#@.......@......@..@+...+.........@@$$#@......@#$%#@.+@@%%$#@+.+.....@..+...@@$%$@@@&&&#@+......+@@@@..", +"$*>,>>;=%#.@%&==*%#@@#&*&%@.....@#%==$@..@%*>-&$@..@$*==*&#+.@#####@@+.+.@#$@@.....@+@@@.+.@%**%$@.+.+@#&**%@.@@%*=*%@...#@$$#$@@..+@@%*-&@@%=>-%#@+.+.#@#####@.", +"%=>>,,,=&@@%&->;-%#..#%==*%@...@#&=-*%@.+#&=>>*%@..#&=>>-*#@@#%&&&&%@...@$**$@+.+.@#$%$%$#@#&*==&$#.@$$&*-=&#@#%&=--*%@@@$&&&&=&#@@$$%&=-*%@$=->&%$@@.@#%**&&&%#", +"#*->->>-*#$&-->>-&$@@#&=--*$$.+#%=->*%@@@$*-->=%#@@$&->>-&#.@%*=-==&#...$&->&#...@$&*=***$#&*====*%@#&*=*==*%#%*-====*#@#&-=**-=%@#&*====-*%$&=>-**&$.#&===*=-*%", +"$&->>>'>*$%*>>>>>*$@#%*>>--&$@#%*->>-*#@#&=>>>-*$@#%=>>>-*$@#&=>>>-*$@@@$*>>*$@.@$&-->>-=%%*>-=*--*#%*--*=--&$&->=*=>=%@$=>-=*--&#$&>-==->=%#&=>>--=%##&>>==->=%", +"#&-;,',,=%%=,,>>;-&#$*>;->;-%#$*>,->;-%#$=>,->;-%@$*>,->;-%#$=>;->;-%@@%&=--=&%@@&-;>>'>=%%*;>**--*$%=;>**--*$&-,=*=--&@%=;>**--*$@&---=->*$#%=,==->=%#&--==->*$", +"#*>>==-,-%#&>;-=->*$&='-==>,&$%->-==>;*#%=;-==>;*$%-;-*->,*#%='-==>'*#$&>-'>)>=##&>,-->,-%$&>-**=-*##*>-=&=-=$%=>=&*-=&@#*>-**=-=#@#&->>;*%@@%=;-=>>=$+#&->>>*%@", +"$*,-=*=,=%$&--=*=-=$%-,***>,&$%>'*&*>,&$&-,***>'&$%-,=&*>'&$%-;***>;&#@%*====&%#$*'>>>-,=%$&--**=>=$$&--**=-=$%=>=**--&@#&--**=-*$.@%=>,=&@@@&=,>>;>*#+@%*;;-%#.", +"#&,>=&=,-%$*--**=-=%&=,-*=-,&$%=,-*=-,*#%=,-==>,&$%=,-*=>;*#&=,-*=>,*@@#%&=-&%@@#*;,>-=,-%#%--=*->=%#%--*=->=%%*--*->>&#@&--==->=%@@%*-,=$@.#&=,,>-=%@.@$=>;*$@.", +"#&-;>>;>=$$=,>-=>,-%%=,>>,>>%#%=>;>;;-%#%=>>>>,-%#%=>>>,>>%#%=>;>>,=&@.@#&->&@..$*>,;;>>*$@%=>>>,;-%#%=>>>;,-%$&->>;;'*#@$*>;>;'-%@$*>;>&#+.$*->-*&%@++$*-;>*#..", +"@%*>>';=&#$=>'-=-'-%#&=>>,>*%@#&*,>,>=$@#&=>';>*%@#&=,>,>=$@#&*'>'-=$@..@$**%@..#&-,;,,=&@@#&->;>'>%@#&->,>'-%#$*>>,>,=#@$&=>'>,-%@%=>'>&+.+$*-;-*$@..+%=;,>&#@.", +"+@%%&&%%#@#%&&%&&&%#@#%*&&%%@.@#%%&&%$@.@#%&&&&$@.@#%%&&&$@+@#%%&&%$@@...@$#@+..#&=**&%%#..@#%&*&&&#.@#%&&&&%#.@$&&&&&%@.@$%&&&&&#@%=-=*%@..$&=-*&@@..+$====$+..", +"..@@###@...###@@@##@.@@####@...@@###@@@...@@#@@@@..@######....@@##@@..+...@@.@..@$%$$##@@.+.@@###@@@..+@@####@...#####@....@###@@@.@$%%$#.+.@$%%$#@....@$%$$@+..", +"......@.....@@@@$%%#...@@@@@.+.....@....+.........+.........+.@.@........@#@@.....@##@#@@...@#.@....@$%%$%%$@@.+.........+..@.@....+.............@@#@.+.........", +".@#@@@+@..@@##$$&-=%@@$###$@....@.@@@#@@.@@@.@@+.....@#@@....@##@@.+...@@#&%#@...@#&&&&$@..$#%#@...+#*-=*===%@.....@@@.+@@#$#$#$#@..........+...@#%%%@...+@+...+", +"@#$#@#$##.@%&***=;>*##&*&&&%@@.##$%%%&%@@#$#$$#$@@+.@$&%$@@+#%&&%@@...+@#&=*%#@.+@%===*&#.@#%*%#@@@.%=,>>>>,&@.+..#%$#@.#&***=**&$.+@##$$@@..@.+#%==*$..@#$#@...", +"@%**%%=&#@%=->>->,-&#&=>=--*%@#&=*==--=%#&*=**=*%#@@$*--&%#@#*;>=%@...#%&=;-*&%@@#*>--=&#+@$*>*&$##@%-'->>,>&@...@%**%@.$->,>)>>=&@@#%**&%@+##@@$*'>=$@+#%*&#@+.", +"$=;-&=>*$#%=,;--;-*%$*>;->-=&$%->',','-&%=;,)>')=%#%&=>>=**$#*>>-%#..+%*=-),>-*$#%*,->=*%##%='-=***$%-'>;,,>*%.+.@%=*%@.@%**=-==&%@#&->)>=%#%&%$%=,>*#..#*-=%@..", +"%-;-=-;&$@%=;-==,-*%%-,,>,,>=%#*->'>>-*%%-'-=->,&$$=>',,,;-%#*>'>=$@.@%=>>'>>;=%%*-,-,--*%$*-'>,,>-%&>'>;;>;-&@..@%==%#.#%**>>=**%#&=-;;>>*%%=*%&=>=$@.@%=>=%@..", +"#*=-;;-&@.$=>=*=>,-%%=;;->>-*$@#&=->=&$#%=,=**-,*$$*--,>>>-&#*>>>=%@.+%---;;;'=&%=-,-'>-=*%*----,-*%%->,>>>>-%...#%-=%@@$*=->'-==&$=----=>>&%--*&;-*$@.@%--*$@..", +"@$*-;,=%@+$=-**=,;=&$*;>---*%@.@%*=-&$@.%-,*&&-,&##%*-,---=%$*->>=$@.@%---,;,;=%%*-,-,-==&%*-=->-&#@%=;,;;;>=$@+.#&>=%@.$*==;;==*&%-->-==-,%$*=*=,*%#..@%--*&$@+", +"@$&-,,-%#@%===*=>=*%#&>>---*$@.@$*==%@..%=,=&&=,*$+$&->>>>=%%->,>*%#@@%=-=,,>;=%$&=>--=*%#$&&=>-*$@.$=>>,>'>*#...#&,-%$.@$%&=-*%$#%=->-**->&#%*=--&#@.@$&-====%#", +"@%*>,;-*&$$=--=-=&%$#&>>---&$..#&==&#..@%-'=&*>,&#@%*-->;,*$%-,;-=*%$#$**='>=-&$#&->=-=&#@@$%=>-&@..#*=-=->-%#..@$=>-%@.@@#&=-&$@@%->>=*=>-&@$&-,*%@..#%=-==;,*$", +"#*>>==>,>&$*>>--*%@@@&-;>--*$.@%*=*%#..+$-;--->>*$$*==->>-%@$=->-,>-*&#$%*;-*&$#%->-*-=%#.@$&==&#@..@$&*->>=%@.@$&--*#@..@$=--&#..$=;-==>>*##&=-=%#...$=>>>>;,-%", +"%-=*%&*==%#%*-=*%@@.@&->>-=&@+#&==%#@...$*-**&=-&$%==&**=*#@$*=**=--*%@@$&;-%#@@%==&&=&$@.@%**%$@..+.@$&-,-*#@.#&=>=%#..+@%*-=%@..#&**->=*$#%=-*&#@..@%=;>-==->&", +"$*&$#@#%%$@@%&&%#@..@%===*&$@.#%&&$@+..+#%*%$$%%$@$&&$$%%#@.#%%%%&**&$..@%=*$@..%&&#$%%#@.@$%%#@......@$*=*%@@.@%==%#....@#&*&$@..+@$%&=&#@@%*=%#@...+$*=**&%**%", +"@$#@..+@#@..@###....@#%&%$$@+.@#$#@.....@#$@.@##@.@#@@.@@@..@#@@@#$##..+@#%$#@..@#@@@@@@...@##@....+.+.#$$##..@@$%$#.+..+.@$#$@.....@#$$#@..#%$@......@$$%$##$$#"}; diff --git a/hacks/images/matrix2.xbm b/hacks/images/matrix2.xbm new file mode 100644 index 00000000..6911ade7 --- /dev/null +++ b/hacks/images/matrix2.xbm @@ -0,0 +1,1260 @@ +#define matrix2_width 320 +#define matrix2_height 377 +static unsigned char matrix2_bits[] = { + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xaf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xd5, 0xff, 0xab, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x57, 0xff, 0x5f, 0xed, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x57, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x5f, 0xff, 0x7f, + 0x53, 0xff, 0x45, 0xff, 0xff, 0xfd, 0xff, 0xff, 0xff, 0xff, 0xf6, 0xff, + 0x9b, 0xfe, 0xb7, 0xf4, 0xff, 0xef, 0xff, 0x7f, 0xf5, 0xff, 0xff, 0xff, + 0x97, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xd7, 0xff, 0xff, 0xc1, 0xff, 0x45, 0xff, 0x7f, 0xfd, 0xff, 0xff, + 0xff, 0xff, 0xfb, 0xff, 0x8d, 0xff, 0x17, 0xd5, 0xff, 0x75, 0xfd, 0x7f, + 0xfb, 0xff, 0xff, 0xff, 0x8f, 0xfc, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0x0b, 0xfd, 0xbf, 0xa2, 0xff, 0x8b, 0xfd, + 0x5f, 0xe9, 0xff, 0xef, 0xff, 0xbf, 0xa0, 0xff, 0x02, 0xf4, 0x2f, 0xe0, + 0xff, 0x2a, 0xf5, 0x5f, 0xd0, 0xff, 0xff, 0xff, 0x03, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfa, 0xff, 0x85, 0xff, 0x7f, + 0xf1, 0xff, 0x4a, 0xfe, 0x7f, 0xec, 0xff, 0xb7, 0xfe, 0xff, 0xe8, 0x7f, + 0x81, 0xfe, 0x0b, 0x69, 0x7f, 0x21, 0xfa, 0xbf, 0xe8, 0xff, 0xff, 0xff, + 0x0f, 0xfd, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xee, + 0xff, 0x0a, 0xf4, 0xbf, 0xa0, 0xff, 0x0f, 0xfd, 0x5f, 0xf1, 0xff, 0x5b, + 0xfb, 0x5f, 0x42, 0xff, 0x0a, 0xe8, 0x27, 0xc0, 0xff, 0xaa, 0xec, 0x5f, + 0xa0, 0xff, 0xff, 0xff, 0x47, 0xfd, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xbf, 0xf0, 0x7f, 0x8a, 0xfa, 0x5f, 0xf4, 0xff, 0x43, 0xfe, + 0x3f, 0xe8, 0xff, 0x01, 0xfe, 0x3f, 0x51, 0xbf, 0x00, 0xf2, 0x15, 0xea, + 0xbf, 0x00, 0xf4, 0x2f, 0xf0, 0xff, 0xff, 0xff, 0x1b, 0xfa, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xbf, 0xe8, 0x7f, 0x01, 0xd2, 0x7f, + 0xd0, 0xff, 0x1f, 0xfa, 0xdf, 0xa0, 0xff, 0x85, 0xf4, 0xaf, 0x40, 0xff, + 0x02, 0xd0, 0x07, 0xa0, 0xfe, 0x52, 0xe8, 0xbf, 0xa0, 0xff, 0xff, 0xff, + 0x4f, 0xfa, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xbf, 0xe8, + 0x3f, 0x01, 0xf2, 0x2f, 0xfa, 0xff, 0x0b, 0xfd, 0x7f, 0xe4, 0xff, 0x52, + 0xf4, 0x3f, 0x54, 0xb7, 0xb0, 0xf0, 0x45, 0x00, 0xbf, 0x00, 0xfa, 0x2f, + 0xe8, 0xff, 0xff, 0xff, 0x37, 0xec, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0x6f, 0xf0, 0xff, 0x10, 0xf4, 0x7f, 0xd4, 0xff, 0x2f, 0xf6, + 0xdf, 0xa2, 0xff, 0x27, 0xf4, 0x2f, 0x41, 0xff, 0x0a, 0xa9, 0x05, 0x40, + 0xfd, 0x52, 0xd4, 0x5f, 0xa0, 0xff, 0xff, 0xff, 0x1f, 0xf6, 0xff, 0xff, + 0xff, 0xdf, 0xb6, 0xff, 0xff, 0xff, 0x3f, 0xa8, 0x3f, 0x00, 0xf2, 0x2f, + 0xf8, 0xff, 0x2b, 0xfa, 0xff, 0xf4, 0xff, 0x12, 0xfa, 0x17, 0xa8, 0x7f, + 0x51, 0xf0, 0x07, 0xa4, 0x7f, 0x21, 0xea, 0x2f, 0xe8, 0xff, 0xff, 0xff, + 0xff, 0xe8, 0xff, 0xff, 0xff, 0xb7, 0xda, 0xfe, 0xff, 0xff, 0xcb, 0x50, + 0xfd, 0x0b, 0xdd, 0x5f, 0xec, 0xff, 0x2f, 0xfa, 0x7f, 0xa7, 0xff, 0x55, + 0xd4, 0xaf, 0x42, 0xff, 0x0a, 0xd0, 0x25, 0x00, 0xfe, 0x4a, 0xf1, 0xbf, + 0xa0, 0xff, 0xff, 0xff, 0x5f, 0xf0, 0xff, 0xff, 0xff, 0xab, 0xaa, 0xff, + 0xff, 0xff, 0x57, 0xa8, 0xbf, 0x82, 0xea, 0x6f, 0xf4, 0xff, 0x2f, 0xfa, + 0xff, 0xeb, 0xbf, 0x56, 0xfa, 0x0b, 0xf0, 0xbf, 0x42, 0xda, 0x07, 0xa0, + 0xff, 0x73, 0xfe, 0x2f, 0xe8, 0xff, 0xff, 0xff, 0x7f, 0x51, 0xff, 0xff, + 0xff, 0x05, 0x00, 0xfa, 0xff, 0xff, 0x05, 0x00, 0x7a, 0x21, 0xf8, 0x3f, + 0xe8, 0xff, 0x2f, 0xfc, 0xff, 0xff, 0x7f, 0x01, 0xe8, 0xb7, 0x40, 0x7f, + 0x80, 0xf4, 0x2b, 0x85, 0xfe, 0xae, 0xfb, 0xbf, 0xa0, 0xff, 0xff, 0xff, + 0x5f, 0xd0, 0xff, 0xff, 0xff, 0x07, 0x00, 0xfd, 0xff, 0xff, 0x03, 0x00, + 0x7f, 0x11, 0xfe, 0x2f, 0xfc, 0xff, 0x37, 0xf6, 0xff, 0xff, 0xbf, 0x0c, + 0xfa, 0x1b, 0xe8, 0x5f, 0x02, 0xf6, 0x2b, 0xe0, 0xfe, 0xff, 0xff, 0xaf, + 0xf8, 0xff, 0xff, 0xff, 0xbf, 0xc1, 0xff, 0xff, 0xff, 0x03, 0x00, 0xfe, + 0xff, 0xff, 0x07, 0x00, 0xfa, 0x42, 0xe8, 0x7f, 0xe8, 0xff, 0x1f, 0xfa, + 0xff, 0xf7, 0x7f, 0x02, 0xd4, 0x2f, 0x40, 0x7f, 0x10, 0xe9, 0x17, 0x05, + 0xff, 0xff, 0xff, 0xbf, 0xe8, 0xff, 0xff, 0xff, 0xff, 0x64, 0xff, 0xbf, + 0xff, 0xbb, 0xfb, 0xff, 0xdf, 0xff, 0x5b, 0xd9, 0x7f, 0x73, 0xff, 0x2f, + 0xfc, 0xff, 0x0b, 0xfa, 0xff, 0xff, 0x5f, 0x80, 0xf0, 0x05, 0xa8, 0x5f, + 0x44, 0xf5, 0x05, 0x00, 0xfd, 0xff, 0xff, 0x7f, 0xe8, 0xff, 0xff, 0xff, + 0xff, 0x89, 0xff, 0xdf, 0xff, 0x57, 0x95, 0xfe, 0xf7, 0xff, 0x6f, 0xa0, + 0xfe, 0x55, 0xf0, 0x5f, 0xe0, 0xff, 0x37, 0xfc, 0xff, 0xff, 0x7f, 0x02, + 0xd4, 0x07, 0x41, 0x5f, 0x50, 0xd0, 0x07, 0x00, 0xfb, 0xff, 0xff, 0xdf, + 0xf0, 0xff, 0xff, 0xff, 0xff, 0xc2, 0xfe, 0x4b, 0xfd, 0xff, 0xff, 0xff, + 0x8b, 0xfe, 0x57, 0xf8, 0x7f, 0xfd, 0xff, 0x5f, 0xfc, 0xff, 0x17, 0xef, + 0xff, 0xff, 0x3f, 0xa1, 0xf0, 0xa3, 0xf8, 0x3f, 0x02, 0xf8, 0x5b, 0xa2, + 0xfe, 0xff, 0xff, 0x7f, 0xfd, 0xff, 0xff, 0xff, 0xff, 0x0d, 0xfb, 0x8f, + 0xfe, 0xff, 0xed, 0xff, 0x4b, 0xff, 0xbf, 0xa0, 0xff, 0xbf, 0xff, 0x7f, + 0xd0, 0xff, 0x17, 0xfa, 0xff, 0xff, 0x7f, 0x11, 0xd0, 0x8d, 0xa8, 0xff, + 0x20, 0xd0, 0x2f, 0x00, 0xff, 0xff, 0xff, 0xff, 0xd6, 0xff, 0xff, 0xff, + 0xff, 0x4b, 0xff, 0x4b, 0xff, 0xdf, 0xff, 0xff, 0x45, 0xfb, 0xdf, 0xf8, + 0xff, 0xff, 0xff, 0x2f, 0xd5, 0xff, 0x85, 0xfe, 0xff, 0xff, 0x5f, 0x82, + 0xe8, 0x47, 0xf4, 0x5f, 0x00, 0xe8, 0x17, 0xa1, 0xfd, 0xff, 0xff, 0xbf, + 0xfa, 0xff, 0xff, 0xff, 0xff, 0x8e, 0xfc, 0x0f, 0xfa, 0xff, 0xff, 0xff, + 0x0b, 0xfe, 0x7f, 0xe8, 0xff, 0xff, 0xff, 0xff, 0xe0, 0xff, 0x2f, 0xfa, + 0xff, 0xff, 0x7f, 0x00, 0xd2, 0x05, 0xe8, 0x7f, 0x13, 0xea, 0x7f, 0x08, + 0xff, 0xff, 0xff, 0xff, 0xf0, 0xff, 0xff, 0xff, 0xff, 0x07, 0xfe, 0x05, + 0xff, 0xff, 0xff, 0xff, 0x8a, 0xfe, 0xbf, 0xf8, 0xff, 0xff, 0xff, 0x3f, + 0xb4, 0xff, 0x82, 0xfe, 0xff, 0xff, 0x5f, 0x00, 0xf0, 0x27, 0xf9, 0x7f, + 0x81, 0xf2, 0x17, 0xc0, 0xff, 0xff, 0xff, 0x5f, 0xf8, 0xff, 0xff, 0xff, + 0xff, 0x4f, 0xfd, 0xdf, 0xfd, 0xff, 0xff, 0xff, 0x27, 0xfa, 0xff, 0xee, + 0xff, 0xff, 0xff, 0xff, 0xc3, 0xfe, 0x4b, 0xff, 0xff, 0xff, 0xbf, 0xbe, + 0xff, 0xdf, 0xf6, 0xff, 0x0f, 0xfd, 0xbf, 0x24, 0xfa, 0xff, 0xff, 0xff, + 0xf7, 0xff, 0xff, 0xff, 0xff, 0x2b, 0xfd, 0x77, 0xff, 0xff, 0xff, 0xff, + 0x2b, 0xfe, 0x7f, 0xf7, 0xff, 0xff, 0xff, 0xbf, 0x62, 0xff, 0x42, 0xff, + 0xff, 0xff, 0xff, 0xd5, 0xfa, 0xdb, 0xff, 0xff, 0x8b, 0xff, 0x2f, 0x80, + 0xff, 0xff, 0xff, 0xff, 0xfa, 0xff, 0xff, 0xff, 0xff, 0xbf, 0xfe, 0xdf, + 0xff, 0xff, 0xff, 0xff, 0x1f, 0xfd, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xa3, 0xff, 0x8d, 0xff, 0xff, 0xff, 0x7f, 0xff, 0xdf, 0xff, 0xfa, 0xff, + 0x4f, 0xfd, 0x7f, 0x65, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xaf, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0x6b, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xfa, 0xff, 0xf7, 0xff, 0xff, 0xff, 0xff, 0x6f, + 0xff, 0xff, 0xff, 0xff, 0xfb, 0xff, 0x5f, 0xb5, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xbf, 0xfa, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xdf, 0xff, 0xad, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xdf, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xf7, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xf6, 0xff, 0xdf, 0xfd, 0xff, 0xfe, 0xff, 0xff, 0xff, + 0xff, 0xdf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0x7f, 0xfd, 0xff, 0xf7, 0xfd, 0xbf, 0xaa, 0xfe, 0xd5, + 0xff, 0xdf, 0x6b, 0xff, 0xef, 0xff, 0xb7, 0xdd, 0xff, 0x77, 0xff, 0xff, + 0xef, 0xff, 0x57, 0xff, 0xff, 0xea, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xaf, 0xeb, 0xff, 0x5a, 0xdf, + 0x57, 0xd5, 0x7f, 0xed, 0xff, 0x6f, 0xb5, 0xff, 0x6a, 0xff, 0xbf, 0xed, + 0xff, 0xaa, 0xfb, 0xbf, 0xea, 0xfe, 0xdd, 0xfb, 0x7f, 0xbb, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7b, + 0xb0, 0xbf, 0x07, 0xf5, 0x2f, 0x04, 0x7a, 0xa1, 0xfa, 0x1b, 0xc0, 0xfe, + 0x93, 0xfe, 0x57, 0xd0, 0xbe, 0x0b, 0xdc, 0xff, 0xa8, 0xff, 0x05, 0xfe, + 0x5f, 0xd5, 0xfd, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0x4f, 0xaa, 0xff, 0x50, 0xfd, 0x0b, 0xa1, 0xbe, 0xa8, + 0xfe, 0x8f, 0x94, 0xfe, 0xca, 0xff, 0x1b, 0x52, 0xff, 0x40, 0xf7, 0x5f, + 0xa2, 0xbd, 0xa2, 0xfa, 0x2f, 0x40, 0xff, 0xff, 0xeb, 0xff, 0xff, 0xff, + 0xfb, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x0b, 0xc0, 0x5e, 0x02, 0xe0, + 0x0f, 0x00, 0xda, 0x00, 0xfd, 0x2b, 0x80, 0x7e, 0x03, 0xfa, 0x47, 0x00, + 0x5f, 0x02, 0xe8, 0xff, 0x00, 0xfe, 0x02, 0xea, 0x2f, 0x80, 0xfe, 0x5f, + 0xfd, 0xff, 0xff, 0xbf, 0xba, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x0b, + 0x40, 0x7f, 0x00, 0xf4, 0x0b, 0x00, 0x7e, 0x04, 0xf6, 0x0f, 0x80, 0xfe, + 0x81, 0xfe, 0x25, 0x40, 0x7f, 0x00, 0xf0, 0x2f, 0x80, 0x5f, 0x00, 0xe8, + 0x57, 0x80, 0xfe, 0xff, 0xab, 0xff, 0xee, 0xff, 0xed, 0xff, 0xff, 0xfa, + 0xff, 0x6f, 0xff, 0x0f, 0x40, 0x5f, 0x02, 0xd0, 0x0b, 0x89, 0xfa, 0x00, + 0xf9, 0x57, 0x80, 0xda, 0x02, 0xfd, 0x07, 0x00, 0x5d, 0x02, 0xd4, 0xff, + 0x10, 0x7d, 0x11, 0xf2, 0x07, 0xa6, 0xfe, 0x2b, 0xe0, 0x57, 0x77, 0x5f, + 0xa0, 0xff, 0x5f, 0xff, 0xff, 0x77, 0xff, 0x85, 0x46, 0x3f, 0xb0, 0xe8, + 0x8f, 0xec, 0xbe, 0x16, 0xdc, 0x9b, 0x46, 0xfe, 0x22, 0xee, 0x85, 0x5a, + 0x3f, 0x68, 0xf1, 0x5f, 0xa8, 0x3f, 0x48, 0xb1, 0x8f, 0x88, 0xfe, 0xde, + 0xc0, 0x6d, 0xd5, 0x7e, 0xa8, 0xfa, 0xef, 0xfa, 0xff, 0xaf, 0xfb, 0x0b, + 0x09, 0xda, 0x08, 0xf1, 0x27, 0x54, 0xff, 0x8a, 0xf0, 0xaf, 0x88, 0xfe, + 0x02, 0xfa, 0x07, 0x2a, 0x7f, 0xa0, 0xd0, 0xff, 0xd0, 0x5f, 0x50, 0xe0, + 0x0b, 0x46, 0xff, 0x03, 0xfc, 0x07, 0x00, 0xbf, 0x02, 0xfa, 0x3f, 0xdc, + 0xff, 0x05, 0xfe, 0x8b, 0x45, 0x7f, 0xa4, 0xd0, 0x2b, 0xf6, 0xff, 0x42, + 0xf4, 0x0b, 0x40, 0xfb, 0x22, 0xfa, 0x23, 0xab, 0x1f, 0xb4, 0xfe, 0x5f, + 0xe8, 0x7e, 0xb4, 0xf0, 0x0f, 0x55, 0x5d, 0x0d, 0xd4, 0x4b, 0x52, 0x7d, + 0x05, 0xdd, 0x17, 0xf0, 0xff, 0x0f, 0xfd, 0x05, 0x15, 0x5d, 0x50, 0xe8, + 0x17, 0xfa, 0xbf, 0x15, 0xa8, 0x57, 0x00, 0x7e, 0x43, 0xea, 0x05, 0xf4, + 0xff, 0xa0, 0xf7, 0xbf, 0xb0, 0x3f, 0x54, 0xa1, 0x8b, 0x54, 0xff, 0x02, + 0xfa, 0x05, 0x02, 0xff, 0x02, 0xd4, 0x1f, 0xfa, 0xff, 0x85, 0xfe, 0x87, + 0x82, 0x7d, 0x04, 0xf2, 0x2f, 0xfa, 0xff, 0x80, 0xe8, 0x0b, 0x40, 0xff, + 0x52, 0xf8, 0x27, 0xb5, 0x5f, 0xd8, 0xfa, 0xdf, 0xf8, 0x5f, 0xb0, 0xf0, + 0x0f, 0xd2, 0x5f, 0xa0, 0xfd, 0x07, 0x00, 0xda, 0x97, 0xe0, 0x6f, 0xfa, + 0xff, 0x0f, 0xfd, 0x0b, 0x48, 0xbe, 0x22, 0xd4, 0x5d, 0xb4, 0xbf, 0x00, + 0xd0, 0x0f, 0x96, 0xbd, 0x01, 0xd2, 0x15, 0xe8, 0x7f, 0x82, 0xff, 0x7f, + 0xd0, 0x5f, 0x54, 0xd0, 0x47, 0xe8, 0x3f, 0xa0, 0xfe, 0x45, 0xa0, 0xff, + 0x15, 0xa8, 0x2f, 0xfa, 0xff, 0x4b, 0xff, 0x05, 0x05, 0x5f, 0x00, 0xf2, + 0x6f, 0xfa, 0x5f, 0x10, 0xd4, 0x83, 0xc2, 0xfe, 0x50, 0xf0, 0x07, 0xf0, + 0xbf, 0xa2, 0xfe, 0x5f, 0xf8, 0x7f, 0x74, 0xd1, 0x5f, 0x61, 0xbf, 0x40, + 0xfd, 0x13, 0x09, 0xfa, 0xaf, 0xa0, 0xff, 0xfd, 0xff, 0xf7, 0xfd, 0x07, + 0xc0, 0xbf, 0x50, 0xd0, 0x5f, 0xe4, 0xbf, 0xa4, 0xe0, 0x0d, 0xba, 0x7f, + 0x02, 0xd1, 0x85, 0xaa, 0xff, 0x05, 0xfb, 0xbf, 0xd0, 0x3f, 0x90, 0xe0, + 0x6f, 0xf0, 0x9f, 0x50, 0xff, 0x03, 0x40, 0xfd, 0x15, 0xa0, 0x5f, 0xff, + 0xff, 0xbf, 0xff, 0x05, 0xa0, 0x5e, 0x08, 0xf0, 0x5f, 0xf0, 0xbf, 0x90, + 0xf4, 0x87, 0xdb, 0x5f, 0x22, 0xd0, 0x43, 0xfa, 0x7f, 0x85, 0xfe, 0xdf, + 0xf8, 0x5f, 0x54, 0xf1, 0x7f, 0xa1, 0x7f, 0x40, 0xed, 0x57, 0x15, 0xfe, + 0xab, 0xc0, 0xff, 0xfe, 0xff, 0x7f, 0xff, 0x8b, 0xc0, 0x7f, 0x50, 0xa1, + 0x7f, 0xea, 0x7f, 0x48, 0xc8, 0x05, 0x7d, 0xbd, 0x00, 0xe0, 0x05, 0xad, + 0xfd, 0x03, 0xf4, 0x7f, 0xc8, 0x7f, 0xb0, 0xa0, 0x5f, 0xf1, 0xbf, 0x06, + 0xfa, 0x01, 0x00, 0x7f, 0x05, 0xfc, 0xff, 0xef, 0xff, 0xd7, 0xff, 0x0b, + 0xba, 0x5f, 0x94, 0xf0, 0x2f, 0xf0, 0x5f, 0x50, 0xe8, 0x8b, 0x16, 0xbf, + 0x00, 0xf4, 0x43, 0x95, 0xff, 0x2a, 0xf6, 0x2f, 0xe8, 0x5f, 0x54, 0xf0, + 0xff, 0xd1, 0xff, 0x13, 0xd4, 0x17, 0x80, 0xfa, 0x02, 0xea, 0xbf, 0xfa, + 0xff, 0xff, 0xfe, 0x0f, 0xc5, 0x3e, 0x40, 0xd0, 0x7f, 0xa5, 0xbf, 0xa8, + 0xe4, 0x07, 0xaa, 0x7a, 0x82, 0xa0, 0x07, 0x5a, 0xbd, 0x0b, 0xd8, 0xdf, + 0xb0, 0x3f, 0x54, 0xd1, 0xbf, 0xd8, 0x7f, 0x05, 0xf5, 0x85, 0x44, 0x5f, + 0x01, 0xfd, 0xaf, 0xfe, 0xff, 0x4b, 0xff, 0x85, 0xf0, 0x5f, 0x34, 0xf1, + 0x5f, 0xf0, 0xbf, 0x20, 0xf0, 0x85, 0x2a, 0x3d, 0x20, 0xf4, 0x41, 0x45, + 0xfd, 0x4a, 0xfa, 0x2b, 0xa8, 0xbf, 0x50, 0xf0, 0xff, 0xe2, 0xff, 0x5f, + 0xc0, 0xf7, 0x76, 0x7d, 0x68, 0xfb, 0x3f, 0xe8, 0xff, 0x8f, 0xfc, 0x0f, + 0x84, 0x7e, 0x00, 0xa8, 0xbf, 0xd1, 0xbf, 0x08, 0xec, 0x0b, 0x00, 0x5e, + 0x01, 0xd5, 0x17, 0x08, 0x7e, 0x01, 0xa0, 0x97, 0x40, 0x7d, 0x02, 0xd4, + 0xff, 0xf2, 0xff, 0xab, 0xe0, 0x5f, 0x5b, 0x3f, 0xa0, 0xff, 0x2f, 0xfa, + 0xff, 0x05, 0xfe, 0x4b, 0xa0, 0x3f, 0x21, 0xf4, 0xff, 0xd0, 0xbf, 0x00, + 0xf4, 0x0f, 0x8a, 0x7e, 0x90, 0xfe, 0x03, 0x01, 0x5f, 0x48, 0xf0, 0x13, + 0x48, 0xbf, 0x42, 0xfa, 0xbf, 0xd1, 0xff, 0xff, 0xfe, 0xfb, 0xfe, 0xff, + 0xef, 0xff, 0x5f, 0xd0, 0xff, 0x8f, 0xfe, 0x5f, 0x42, 0xfd, 0x85, 0xea, + 0x7f, 0xe5, 0xff, 0x02, 0xfd, 0xb7, 0x40, 0x5f, 0x02, 0xf5, 0x7f, 0xa0, + 0xba, 0x02, 0xa0, 0x0f, 0x80, 0xfe, 0x12, 0xf5, 0xff, 0xf4, 0xff, 0xbf, + 0xd3, 0xff, 0xff, 0xbf, 0xfa, 0xfe, 0x57, 0xf8, 0xff, 0x45, 0xff, 0xb7, + 0x90, 0xbe, 0x02, 0xfa, 0xdf, 0xf0, 0xbf, 0xa4, 0xfe, 0x5b, 0xa0, 0x7b, + 0xa2, 0xfe, 0x17, 0xa4, 0x7f, 0x00, 0xf4, 0x43, 0x20, 0xbf, 0x82, 0xfe, + 0xff, 0xe9, 0xff, 0xff, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0x3f, 0xd1, + 0xff, 0x1f, 0xf6, 0x7f, 0xa5, 0xff, 0xab, 0xfe, 0xff, 0xeb, 0xff, 0x0b, + 0xf5, 0x7f, 0x49, 0x7f, 0x89, 0xfe, 0xbf, 0x88, 0xbe, 0x4a, 0xd1, 0x17, + 0x8a, 0xfe, 0x2b, 0xfa, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xdf, 0xff, 0xff, 0xd9, 0xff, 0xd7, 0xff, 0xbf, 0xb5, 0xff, 0x55, 0xfb, + 0xff, 0xfe, 0xff, 0xea, 0xff, 0x5f, 0xed, 0xbf, 0xb5, 0xff, 0xaf, 0xf6, + 0xff, 0x6a, 0xfd, 0xfb, 0xeb, 0xff, 0xef, 0xff, 0xff, 0xf6, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f, 0xe9, 0xff, 0xff, 0xff, 0xff, + 0xef, 0xff, 0xff, 0xff, 0xff, 0xeb, 0xff, 0x7f, 0xff, 0xff, 0xfb, 0x7f, + 0xef, 0xfe, 0xff, 0xdd, 0xff, 0x7f, 0xef, 0xaf, 0x7a, 0xff, 0x5b, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xbf, 0xff, + 0xff, 0xbf, 0xff, 0xff, 0xfd, 0xff, 0xb6, 0xff, 0xff, 0xff, 0xff, 0xb7, + 0xff, 0xff, 0xff, 0xff, 0xf7, 0xff, 0xff, 0xff, 0x7f, 0xd7, 0xfb, 0xff, + 0xbf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xfb, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xbd, 0xff, 0xff, 0xff, 0x7f, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfb, + 0xf7, 0xff, 0x7f, 0xff, 0xff, 0xff, 0xef, 0xdb, 0xff, 0xff, 0xff, 0xdf, + 0xff, 0xbf, 0xff, 0xfb, 0x7f, 0xff, 0x7f, 0xff, 0xff, 0xbf, 0xff, 0xff, + 0xff, 0xdf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xda, 0xbf, 0xbe, 0xdd, 0x55, 0xdf, 0xff, 0xaf, 0xea, 0xfb, 0x7e, + 0xfd, 0xaa, 0xfa, 0xf7, 0xaa, 0xfd, 0xb6, 0xdd, 0xdf, 0xeb, 0xff, 0x55, + 0xd5, 0xdf, 0x55, 0xff, 0x5f, 0xf5, 0xaf, 0xd5, 0xff, 0x5f, 0xf5, 0xff, + 0xd5, 0xff, 0x6f, 0xff, 0x7f, 0xef, 0xff, 0xd5, 0xed, 0xff, 0xd7, 0xf6, + 0x77, 0xfb, 0xaf, 0x56, 0x5f, 0xbb, 0xff, 0x5f, 0xed, 0x5f, 0xbb, 0xed, + 0x6b, 0xfd, 0xbf, 0xb6, 0xfd, 0x57, 0xdd, 0xfb, 0x6b, 0x6d, 0x7b, 0xfd, + 0xff, 0xd5, 0xb6, 0x7f, 0xed, 0xfe, 0xb5, 0xfb, 0xbf, 0xd0, 0xbe, 0xe8, + 0xe2, 0x43, 0x2d, 0xfd, 0x1f, 0xa0, 0x15, 0x05, 0xbd, 0x00, 0xfa, 0x27, + 0x90, 0xbe, 0x50, 0xd0, 0x17, 0xa0, 0xbe, 0x00, 0xc2, 0x97, 0x00, 0xfe, + 0x16, 0xa2, 0x0b, 0xc2, 0xfe, 0x06, 0xe1, 0xbf, 0x41, 0xff, 0xaf, 0xfe, + 0x2f, 0xd2, 0x5e, 0x64, 0xb2, 0x51, 0x17, 0xfd, 0x83, 0xea, 0x87, 0x52, + 0xbd, 0x24, 0xfd, 0x13, 0x89, 0x9e, 0x54, 0xd5, 0x51, 0xa9, 0x9f, 0x94, + 0xf0, 0x0b, 0xa4, 0x7a, 0x83, 0xd0, 0x4b, 0x71, 0xbf, 0x22, 0xe8, 0xdf, + 0xa8, 0xff, 0x02, 0xfa, 0xaf, 0x40, 0xbf, 0xa8, 0xc1, 0x85, 0x4a, 0xfa, + 0x2f, 0xa0, 0x25, 0x04, 0x5c, 0x40, 0xf4, 0x0f, 0x40, 0x5f, 0x20, 0xa0, + 0x0b, 0x40, 0xbd, 0x00, 0xa2, 0x4d, 0x01, 0xfc, 0x2a, 0x84, 0x25, 0x80, + 0xfd, 0x49, 0xa2, 0xbf, 0x40, 0xfe, 0x05, 0xea, 0x0b, 0x10, 0x1a, 0xa0, + 0xe0, 0x81, 0x06, 0xfa, 0x0b, 0xe8, 0x03, 0x05, 0x3d, 0x00, 0xfe, 0x45, + 0x08, 0x1f, 0x10, 0xd0, 0x09, 0x44, 0x1e, 0x00, 0xa0, 0x07, 0x00, 0x5e, + 0x00, 0xa0, 0x05, 0x88, 0x5e, 0x00, 0xe0, 0x2f, 0x20, 0x7f, 0x05, 0xf9, + 0x0b, 0x84, 0xbe, 0x48, 0x80, 0x05, 0x11, 0xfc, 0x57, 0xa0, 0x0f, 0x01, + 0xba, 0x12, 0xf9, 0x17, 0x40, 0x5d, 0x50, 0xa0, 0x03, 0x01, 0x7a, 0x80, + 0xc0, 0x05, 0x40, 0xba, 0x00, 0x80, 0x03, 0x02, 0xfa, 0x00, 0xa0, 0xbf, + 0x00, 0xdf, 0x51, 0xd0, 0x83, 0x22, 0xba, 0x48, 0xf0, 0x05, 0x05, 0xfd, + 0x57, 0xfc, 0x13, 0x08, 0xdf, 0xc0, 0xfd, 0x57, 0xfa, 0x5f, 0x94, 0xb0, + 0xa3, 0x2a, 0x1e, 0x5a, 0xf4, 0x87, 0x4a, 0x3e, 0xa8, 0xe2, 0x91, 0x15, + 0x5a, 0xa8, 0xd4, 0x17, 0xe8, 0x7f, 0x01, 0xea, 0x0b, 0x1d, 0x5c, 0x10, + 0x80, 0x03, 0x02, 0xfa, 0xbf, 0xd0, 0x2f, 0x10, 0x7a, 0x45, 0xff, 0xbf, + 0x40, 0x7f, 0x20, 0xd1, 0x09, 0x0d, 0x3a, 0xa0, 0xc8, 0x0b, 0x05, 0xbd, + 0x68, 0xa1, 0x87, 0x2a, 0x7c, 0x48, 0xe0, 0x5f, 0x80, 0xde, 0xa0, 0xd0, + 0x83, 0x0d, 0x76, 0x48, 0xe0, 0x41, 0x01, 0xff, 0x2f, 0xfc, 0x37, 0x00, + 0x7f, 0xe1, 0xff, 0x5b, 0xf8, 0x5f, 0x54, 0xd0, 0xc3, 0x25, 0x3a, 0x55, + 0xe0, 0x85, 0x48, 0x1f, 0xa8, 0xa0, 0xa1, 0x17, 0x5e, 0x20, 0xb4, 0x17, + 0xe0, 0x7f, 0x04, 0xf0, 0x89, 0x2e, 0xb8, 0x10, 0xa2, 0x07, 0x04, 0xf8, + 0xdf, 0xe8, 0xaf, 0x08, 0xfa, 0x44, 0xfd, 0xff, 0xd0, 0x3f, 0x00, 0xe1, + 0xbb, 0x1e, 0x7a, 0x43, 0xe8, 0x5f, 0x04, 0xba, 0xe8, 0xc2, 0xef, 0x1a, + 0xb4, 0x80, 0xe0, 0x2f, 0x8a, 0x7e, 0x01, 0xc1, 0x43, 0x17, 0x3e, 0x08, + 0xa0, 0x01, 0x42, 0xff, 0x37, 0xfc, 0xbf, 0x00, 0xbf, 0xe2, 0xff, 0x5f, + 0xd8, 0x3f, 0x20, 0xf0, 0x8d, 0x16, 0xba, 0x25, 0xb4, 0x17, 0x42, 0x1f, + 0x6c, 0xe2, 0xf7, 0x0f, 0xb6, 0x10, 0xb4, 0x2b, 0xc1, 0x5f, 0x00, 0xf0, + 0x93, 0x2d, 0xd8, 0x00, 0xc2, 0x47, 0x08, 0xfa, 0xdf, 0xe8, 0x5b, 0x00, + 0xfd, 0x40, 0xdf, 0xbf, 0xe8, 0x5f, 0x00, 0xa0, 0x23, 0x2d, 0xf8, 0x05, + 0xe0, 0x6f, 0x00, 0x7a, 0xf2, 0x41, 0xbf, 0x3f, 0x58, 0x40, 0xe0, 0x0f, + 0xa4, 0xbe, 0x22, 0xd0, 0x43, 0x2f, 0xbe, 0x08, 0xe1, 0x01, 0x00, 0xfa, + 0x5a, 0xec, 0x9f, 0x00, 0x7d, 0x65, 0xfb, 0xbf, 0xe8, 0x7f, 0x04, 0xf1, + 0x0b, 0x2d, 0xfe, 0x02, 0xb4, 0x37, 0xa0, 0x1e, 0xba, 0xe0, 0xff, 0x0b, + 0x3e, 0x00, 0xf4, 0x05, 0x05, 0x7f, 0x01, 0xd0, 0x23, 0x1b, 0x74, 0x10, + 0x42, 0x87, 0x08, 0xfe, 0x77, 0xf4, 0x6f, 0x40, 0xfe, 0xa2, 0xad, 0xbf, + 0xf0, 0x3f, 0x10, 0xd0, 0x45, 0x2a, 0xf4, 0x07, 0xe8, 0x2d, 0x80, 0x3e, + 0xd0, 0xa2, 0xf7, 0x3f, 0xb8, 0x00, 0xa0, 0x27, 0x42, 0x5d, 0x00, 0xe2, + 0x93, 0x0b, 0x3a, 0x80, 0xe0, 0x41, 0x08, 0xbb, 0x18, 0xf4, 0x2b, 0x14, + 0xbf, 0xa0, 0xa1, 0xaf, 0xd8, 0x5f, 0x44, 0xd1, 0x03, 0x0a, 0xfa, 0xa2, + 0xe4, 0x27, 0x8a, 0x9e, 0x7a, 0xa2, 0xb7, 0x0b, 0x1e, 0xac, 0xf4, 0x03, + 0x00, 0x7f, 0x82, 0xf0, 0x03, 0x3d, 0xda, 0x20, 0xa1, 0x87, 0x10, 0xfc, + 0xea, 0xf8, 0x0f, 0x01, 0x7a, 0xa5, 0xc6, 0x7f, 0xe8, 0x5f, 0x50, 0xe0, + 0x09, 0x36, 0xfc, 0x07, 0xa8, 0x2b, 0x40, 0x3a, 0xa8, 0xc1, 0xdd, 0x2e, + 0x38, 0x51, 0xc8, 0x0b, 0x00, 0x5a, 0x20, 0xa1, 0x83, 0x05, 0x7a, 0x20, + 0xa0, 0x41, 0x0d, 0x5f, 0x10, 0xec, 0x05, 0x14, 0xfb, 0x42, 0x61, 0x2f, + 0x70, 0x3f, 0x54, 0x70, 0x43, 0x05, 0xf6, 0x55, 0xe4, 0x81, 0x0a, 0x5f, + 0x68, 0xe0, 0x43, 0x0b, 0x1e, 0x49, 0xe4, 0x41, 0x15, 0x7b, 0x22, 0xf0, + 0x15, 0x0a, 0x5c, 0x80, 0xc2, 0x05, 0x15, 0x74, 0xa8, 0xb0, 0x27, 0x05, + 0xfc, 0x42, 0x82, 0xdf, 0xa8, 0x5f, 0x20, 0xd1, 0x13, 0x12, 0xfc, 0xab, + 0xd0, 0x23, 0x44, 0x3a, 0xa1, 0x42, 0x8b, 0x0a, 0x7a, 0xa8, 0xd0, 0x07, + 0x02, 0x7c, 0x11, 0xd1, 0x87, 0x0a, 0xbf, 0xa8, 0xe0, 0xc5, 0x05, 0x3f, + 0x20, 0xec, 0x01, 0x05, 0xbf, 0x24, 0xe1, 0x2b, 0xa8, 0x5f, 0xb4, 0xd0, + 0x81, 0x09, 0xff, 0x2f, 0xd4, 0x91, 0x0a, 0xbd, 0x28, 0x61, 0x43, 0x42, + 0x1e, 0x48, 0xd4, 0x81, 0x12, 0xbf, 0x54, 0xf8, 0x17, 0x40, 0x7a, 0xa0, + 0x80, 0x01, 0x15, 0xf4, 0x00, 0xa0, 0x45, 0x02, 0xf4, 0x05, 0xa0, 0x07, + 0x00, 0x3d, 0x00, 0x80, 0x0f, 0x80, 0xfa, 0x07, 0xa0, 0x07, 0x00, 0xfa, + 0x00, 0x80, 0x0b, 0x80, 0xba, 0x00, 0xa0, 0x01, 0x00, 0x74, 0x01, 0xd4, + 0x0b, 0x40, 0x5f, 0x50, 0xe8, 0x01, 0x05, 0xba, 0x08, 0xa0, 0x41, 0x43, + 0xfe, 0x05, 0xa8, 0x13, 0x80, 0x1f, 0x50, 0xd0, 0x03, 0xc0, 0xfe, 0x05, + 0xa0, 0x01, 0x00, 0xba, 0x00, 0xc0, 0x05, 0x40, 0xbf, 0x00, 0xa0, 0x01, + 0x05, 0x7d, 0x01, 0xfa, 0xff, 0xb5, 0xbf, 0xdb, 0xd5, 0x6f, 0x5f, 0x7d, + 0xa5, 0xea, 0x5f, 0xad, 0xfa, 0x5f, 0xed, 0xaf, 0xd6, 0x5e, 0xb5, 0xea, + 0xff, 0x5a, 0xff, 0x7f, 0xeb, 0x57, 0xd5, 0x7e, 0x57, 0xb5, 0xff, 0xba, + 0xfd, 0xaa, 0xea, 0x6f, 0xab, 0xfa, 0x03, 0xea, 0xaf, 0xda, 0xfd, 0x6c, + 0xf5, 0xd5, 0x53, 0x7f, 0xb5, 0xf6, 0xe5, 0x57, 0xff, 0x4b, 0xed, 0xb7, + 0x6a, 0x7f, 0xd5, 0xb6, 0x57, 0xd5, 0xff, 0x57, 0xf5, 0x5b, 0x55, 0xff, + 0xb5, 0xd6, 0x2f, 0xd5, 0xbf, 0xb6, 0xf6, 0x55, 0xad, 0x7e, 0xad, 0xfb, + 0xff, 0xed, 0xff, 0xfb, 0xdb, 0x6f, 0xbf, 0xfd, 0xab, 0xda, 0x5f, 0xbb, + 0xfd, 0xdf, 0xfe, 0x5f, 0xd5, 0xbf, 0x7d, 0xeb, 0x7f, 0xfb, 0xff, 0x7f, + 0xad, 0xdf, 0xad, 0xfd, 0xaf, 0xf5, 0xff, 0xfd, 0xff, 0x5b, 0xab, 0xb7, + 0xb7, 0xff, 0xd7, 0xfe, 0xff, 0xfe, 0xff, 0xfe, 0xfd, 0xff, 0xdf, 0xff, + 0xfd, 0xff, 0xf7, 0xdf, 0xff, 0xff, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xfb, + 0xff, 0xff, 0xff, 0xdf, 0xff, 0xf7, 0xee, 0xff, 0xff, 0xfd, 0xf7, 0xfe, + 0xff, 0xff, 0xfb, 0xff, 0xff, 0xfb, 0xfb, 0xfe, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xf7, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xef, 0xf7, 0xef, + 0xff, 0xff, 0xdf, 0xff, 0xdf, 0xff, 0xff, 0xff, 0xfd, 0xff, 0xff, 0xff, + 0xfb, 0xff, 0xff, 0xdf, 0xff, 0xff, 0xff, 0xdf, 0xdf, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0x7f, 0xff, 0xff, 0xee, 0xff, 0xff, 0xf6, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf7, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xef, 0xff, 0xff, 0xfb, 0xff, + 0xff, 0xdf, 0xff, 0xeb, 0xff, 0xfb, 0xff, 0xff, 0xdd, 0xff, 0xff, 0xff, + 0xff, 0xef, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xbf, 0xff, 0xfe, 0xff, 0xff, + 0xff, 0xff, 0xfe, 0xff, 0xfb, 0xff, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xbf, + 0xff, 0xbf, 0xfa, 0xff, 0x7f, 0xf5, 0xbf, 0xfa, 0xbf, 0x5d, 0xff, 0xd7, + 0xee, 0xbe, 0x6d, 0xf5, 0xd7, 0x7b, 0xbf, 0xba, 0xdd, 0xaf, 0x5d, 0xfb, + 0x55, 0xef, 0x5f, 0xf5, 0xff, 0xaf, 0xf7, 0xff, 0xfe, 0xff, 0xd5, 0xfb, + 0xff, 0xff, 0xff, 0x8b, 0xfe, 0xff, 0xa4, 0xff, 0xff, 0xc3, 0xff, 0x48, + 0xff, 0xb6, 0xf5, 0xbb, 0x77, 0xf7, 0xb6, 0xbf, 0xfb, 0xae, 0xdf, 0x6f, + 0xf7, 0xf7, 0xee, 0xfe, 0xee, 0xfa, 0xed, 0x5d, 0xff, 0xda, 0xda, 0x5f, + 0xab, 0xff, 0x6f, 0xd5, 0xff, 0xff, 0xff, 0xcd, 0xff, 0x2f, 0xb4, 0xff, + 0xbf, 0xf0, 0x5f, 0xea, 0x5f, 0x55, 0xf5, 0x55, 0x95, 0x3d, 0xd5, 0xd0, + 0x95, 0xb6, 0x7a, 0x74, 0xa9, 0x95, 0xa6, 0x3e, 0x29, 0xeb, 0x57, 0xea, + 0xff, 0x6b, 0xd5, 0x6f, 0xb5, 0x7f, 0x29, 0xed, 0xff, 0xff, 0xff, 0x07, + 0xfa, 0x7f, 0xc0, 0xff, 0xff, 0xa4, 0xbf, 0xa0, 0x7f, 0x00, 0xd0, 0x01, + 0x02, 0x1a, 0x20, 0xc0, 0x01, 0x05, 0x1c, 0x50, 0xc0, 0x03, 0x0a, 0x5a, + 0x00, 0xa0, 0x0d, 0x80, 0xbe, 0x02, 0xc0, 0x1b, 0x40, 0xdd, 0x00, 0xa0, + 0xff, 0xff, 0xff, 0x82, 0xfe, 0x2f, 0xf0, 0xff, 0x5f, 0xf0, 0xaf, 0xa0, + 0x1f, 0x00, 0xf4, 0x01, 0x01, 0x1c, 0x10, 0x64, 0x89, 0x02, 0x1a, 0x54, + 0xd0, 0x09, 0x01, 0x3a, 0x00, 0xf0, 0x07, 0x80, 0x7e, 0x01, 0x60, 0x4f, + 0x40, 0x7f, 0x04, 0xa0, 0xff, 0xff, 0xff, 0x8b, 0xfa, 0x5f, 0x40, 0xff, + 0xbf, 0xca, 0xbf, 0xa0, 0x7f, 0x00, 0xd0, 0x05, 0x04, 0x35, 0x41, 0x80, + 0x03, 0x09, 0x5c, 0x50, 0x82, 0x03, 0x0a, 0x5c, 0x00, 0xa0, 0x0b, 0x40, + 0xbb, 0x04, 0xc0, 0x15, 0x00, 0x5d, 0x01, 0xc0, 0xff, 0xff, 0x7f, 0x01, + 0xfe, 0x5f, 0xfc, 0xff, 0x57, 0xf4, 0x7f, 0xa1, 0x1f, 0xa8, 0xd0, 0x45, + 0x45, 0x3e, 0x28, 0xf0, 0x41, 0x08, 0x1d, 0x54, 0xd1, 0x8b, 0x0a, 0x36, + 0x94, 0xd0, 0x83, 0x0a, 0x5a, 0xa4, 0x70, 0x87, 0xaa, 0x5e, 0x50, 0xea, + 0xff, 0xff, 0xff, 0x0b, 0xfa, 0x6f, 0xd0, 0xff, 0xbf, 0xe8, 0xff, 0xc2, + 0x7f, 0x00, 0xf0, 0x03, 0x04, 0x5a, 0x50, 0xa1, 0x05, 0x09, 0x75, 0x68, + 0xd0, 0x03, 0x55, 0x5c, 0x00, 0xd1, 0x0d, 0x81, 0x7c, 0x20, 0xc0, 0x0b, + 0x04, 0x34, 0x90, 0xa0, 0xff, 0xff, 0x7f, 0x21, 0xfa, 0x5f, 0xfc, 0xff, + 0x17, 0xfc, 0x5f, 0x63, 0x5f, 0x52, 0xd5, 0x15, 0xa5, 0x3e, 0x01, 0xf4, + 0x43, 0x00, 0x3d, 0x34, 0xe1, 0x85, 0x0d, 0x5e, 0x84, 0xd0, 0x87, 0x14, + 0x3e, 0x94, 0xf4, 0x81, 0x2b, 0x3c, 0xaa, 0xe8, 0xff, 0xff, 0xff, 0x42, + 0xda, 0x5f, 0xe8, 0xff, 0x9d, 0xf4, 0xff, 0xa1, 0x7f, 0x21, 0xf1, 0x27, + 0x02, 0x7f, 0x11, 0xd0, 0x85, 0x10, 0x5a, 0xd0, 0xb0, 0x17, 0x2b, 0x34, + 0x08, 0xd1, 0x4b, 0x0a, 0x5a, 0x20, 0xa1, 0x87, 0x0c, 0x9a, 0x50, 0xd0, + 0xff, 0xff, 0xbf, 0x52, 0xfa, 0x2f, 0xfc, 0xff, 0x17, 0xfe, 0xff, 0xa2, + 0xbf, 0x90, 0xf4, 0x2b, 0xa1, 0xbb, 0x00, 0xfa, 0x05, 0x08, 0x3f, 0x34, + 0xd0, 0x85, 0x0d, 0x3e, 0x84, 0xd0, 0x8b, 0x02, 0x7d, 0x54, 0xf0, 0x81, + 0x2e, 0x5c, 0xb4, 0xf4, 0xff, 0xff, 0xff, 0x52, 0xf4, 0x7f, 0xe4, 0xff, + 0x0f, 0xfa, 0xff, 0xc2, 0x7f, 0x03, 0xdb, 0x1f, 0x40, 0x7f, 0x0b, 0xf5, + 0x43, 0x00, 0xd8, 0xd0, 0xea, 0x87, 0x2e, 0xf4, 0x0a, 0xf5, 0x57, 0x80, + 0x5e, 0x80, 0xa0, 0x43, 0x17, 0x34, 0x50, 0xc0, 0xff, 0xff, 0x7f, 0xb3, + 0xfe, 0x4f, 0xf8, 0xff, 0x85, 0xff, 0x7f, 0x61, 0xff, 0x41, 0xfd, 0x17, + 0xe0, 0xff, 0x81, 0xfa, 0x01, 0x08, 0x7f, 0x54, 0xf0, 0x85, 0x06, 0xbe, + 0x8a, 0xfa, 0x55, 0xa0, 0x7e, 0x22, 0xf0, 0xa9, 0x1b, 0x3e, 0x0a, 0xf4, + 0xff, 0xff, 0xff, 0xed, 0xf7, 0x5f, 0xf4, 0xff, 0x27, 0xfa, 0xff, 0xa3, + 0xbf, 0x0a, 0xfa, 0xff, 0xa8, 0xff, 0x0a, 0xfc, 0x07, 0x42, 0xbc, 0x20, + 0xd4, 0x0b, 0x2d, 0xfa, 0x07, 0xdd, 0x0f, 0x52, 0x5b, 0x01, 0xa0, 0x03, + 0x2d, 0xb4, 0x40, 0xd0, 0xff, 0xff, 0xff, 0xff, 0xfe, 0x6f, 0xfc, 0xff, + 0x02, 0xff, 0x7f, 0xa1, 0xff, 0x86, 0xfe, 0x2f, 0xe8, 0xbf, 0x82, 0xf6, + 0x01, 0x01, 0xbe, 0x10, 0xf2, 0x85, 0x27, 0xfa, 0x8a, 0xff, 0x03, 0x50, + 0xfb, 0x02, 0xf8, 0x83, 0x25, 0xba, 0x00, 0xd4, 0xff, 0xff, 0xff, 0xff, + 0xff, 0x3f, 0xe4, 0xbf, 0xc7, 0xfe, 0xff, 0xc2, 0xbf, 0x09, 0xea, 0xdf, + 0xd0, 0x7f, 0x01, 0xd8, 0x07, 0x04, 0xfa, 0x52, 0xf8, 0x0b, 0x1a, 0xfc, + 0x07, 0xfa, 0x0f, 0x10, 0x7d, 0x01, 0xa0, 0x0b, 0x16, 0xbc, 0x00, 0xe8, + 0xaf, 0xaa, 0xfd, 0xff, 0xff, 0x2f, 0xf8, 0xff, 0xe0, 0xff, 0x7f, 0xe1, + 0x5e, 0x44, 0xfa, 0x3f, 0xd8, 0x5f, 0x51, 0xea, 0x41, 0x01, 0xbf, 0x40, + 0xde, 0x8b, 0x0b, 0xfe, 0x82, 0xff, 0x85, 0x96, 0x5e, 0x50, 0xd1, 0x85, + 0x00, 0xff, 0xaa, 0xe4, 0xed, 0xdd, 0xfe, 0xff, 0xff, 0x5f, 0xd4, 0xbf, + 0x45, 0xff, 0xff, 0xa2, 0x5f, 0x08, 0xe8, 0xdf, 0xe0, 0x7f, 0x20, 0xd0, + 0x07, 0x04, 0xfd, 0x13, 0xf4, 0x07, 0x24, 0xf4, 0x0d, 0xfa, 0x07, 0x09, + 0xb8, 0xa2, 0xe0, 0x0b, 0x49, 0x74, 0x17, 0xa0, 0x07, 0x44, 0xfa, 0xff, + 0xff, 0x6f, 0xf4, 0xff, 0xe4, 0xff, 0x5f, 0xc1, 0x3f, 0x40, 0xf4, 0x17, + 0xb0, 0x1f, 0x10, 0xd0, 0x05, 0x05, 0x7f, 0x81, 0xfe, 0x0b, 0x01, 0x7f, + 0x85, 0xfa, 0x05, 0x40, 0x5e, 0x10, 0xd0, 0x05, 0x00, 0xfe, 0x83, 0xe8, + 0x23, 0x09, 0xfd, 0xff, 0xff, 0x3f, 0xd0, 0xbf, 0xa0, 0xff, 0xff, 0x60, + 0x5f, 0x14, 0x50, 0xb7, 0xc0, 0x5e, 0x40, 0xc0, 0x05, 0x02, 0xfa, 0x0b, + 0xfa, 0x0b, 0x88, 0xfc, 0x03, 0xfc, 0x0b, 0x15, 0x38, 0x64, 0x51, 0x4b, + 0x80, 0xfd, 0x2e, 0xa0, 0x13, 0x41, 0xfc, 0xff, 0xff, 0x2f, 0xe8, 0xbf, + 0xe8, 0xff, 0x5f, 0xa0, 0x3f, 0x00, 0xf0, 0x2f, 0x68, 0x5f, 0x28, 0xd4, + 0x03, 0x41, 0xff, 0x02, 0xfd, 0x8b, 0x42, 0x7e, 0x81, 0xee, 0x8b, 0x00, + 0x1a, 0x30, 0xd0, 0x23, 0xc4, 0xfe, 0x07, 0xe0, 0x03, 0x00, 0xf2, 0xff, + 0xff, 0x7f, 0xa0, 0x7e, 0xe8, 0xff, 0xbf, 0xc4, 0x5f, 0x00, 0xd4, 0x2f, + 0x80, 0x3f, 0x50, 0x40, 0x57, 0x16, 0xfd, 0x8b, 0xfe, 0x2f, 0x90, 0xff, + 0x09, 0xfa, 0x2f, 0x40, 0x5c, 0x48, 0x80, 0x0b, 0x00, 0xfe, 0x1b, 0xa1, + 0x03, 0x00, 0xfa, 0xff, 0xff, 0x2f, 0xb4, 0x5f, 0xe8, 0xff, 0xaf, 0xe0, + 0x3f, 0x40, 0xf2, 0x17, 0xe0, 0x1f, 0x54, 0xf0, 0x13, 0x93, 0x7f, 0x85, + 0xfe, 0x17, 0xc0, 0xbf, 0x02, 0xfa, 0x4b, 0x10, 0x5f, 0x7e, 0xd4, 0x05, + 0x40, 0xff, 0x97, 0xe8, 0x03, 0x80, 0xf8, 0xff, 0xff, 0x7f, 0xc0, 0xff, + 0xf0, 0xff, 0x7f, 0xa0, 0xfe, 0xbf, 0xfd, 0xff, 0xbf, 0xff, 0x55, 0xd7, + 0xef, 0xef, 0xfe, 0x7b, 0xfb, 0xff, 0xbf, 0xfd, 0xed, 0xff, 0x7f, 0xef, + 0xba, 0xaa, 0xeb, 0x0b, 0x81, 0xfe, 0xaf, 0xb6, 0xfb, 0x7f, 0xff, 0xff, + 0xff, 0x2f, 0xf2, 0xbf, 0xfe, 0xff, 0x2f, 0xf5, 0xbf, 0xaa, 0xfd, 0xaf, + 0xea, 0xbf, 0xfe, 0xfd, 0x7f, 0x77, 0xff, 0xdf, 0xff, 0xaf, 0xea, 0xff, + 0xb7, 0xfe, 0x5f, 0x6b, 0xff, 0xff, 0xfa, 0x57, 0xed, 0xff, 0xff, 0xfb, + 0x57, 0xd5, 0xfd, 0xff, 0xff, 0xff, 0xbb, 0xff, 0xf5, 0xff, 0xff, 0xd5, + 0xff, 0xff, 0xef, 0xff, 0xff, 0xff, 0x77, 0xef, 0xef, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xfb, 0xff, 0xff, 0xff, 0xfb, 0xff, 0x5b, + 0xaa, 0xfe, 0xef, 0xfe, 0xff, 0x7f, 0xff, 0xff, 0xff, 0xbf, 0xda, 0xff, + 0xfe, 0xff, 0x7f, 0xfd, 0xff, 0xdf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xdf, 0xff, 0xff, 0xff, 0xff, 0xfd, 0xff, 0xff, 0xfb, + 0x7f, 0x7f, 0xff, 0x6f, 0xef, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xf7, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xef, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x5f, 0xff, 0xff, 0xbf, + 0xff, 0xfb, 0xff, 0xff, 0xfe, 0xff, 0xff, 0xf5, 0xff, 0xff, 0x7f, 0xf5, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xdb, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xef, 0xf5, 0xff, 0xdf, 0xfa, 0xaf, 0xff, 0xbf, 0xeb, 0xff, 0xff, 0xbe, + 0xff, 0xff, 0xdf, 0xaf, 0xfe, 0xff, 0xff, 0xff, 0xea, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xf6, 0xff, 0xff, 0xff, 0xb7, 0xfe, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0x2b, 0xfd, 0xff, 0x57, 0xff, 0xea, 0xff, 0xff, + 0xfa, 0xff, 0x7f, 0xd3, 0xff, 0xff, 0x7f, 0xb2, 0xff, 0xff, 0xff, 0x7f, + 0x6b, 0xff, 0xff, 0xff, 0xff, 0x7f, 0xdb, 0xff, 0xff, 0xff, 0xdf, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x0f, 0xf4, 0xff, 0x0f, + 0xfa, 0x83, 0xfe, 0xbf, 0xc0, 0xff, 0xdf, 0xc0, 0xff, 0xff, 0x5f, 0x80, + 0xfe, 0xff, 0xff, 0xdf, 0xc0, 0xff, 0xff, 0xff, 0xff, 0xdf, 0xa0, 0xff, + 0xff, 0xff, 0xab, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0x05, 0xf6, 0xff, 0x0b, 0x7a, 0xc1, 0xff, 0xdf, 0xe8, 0xff, 0x7f, 0xd0, + 0xff, 0xff, 0x7f, 0x80, 0xef, 0xff, 0xff, 0x7f, 0x60, 0xff, 0xff, 0xff, + 0xff, 0x7f, 0xc0, 0xff, 0xff, 0xff, 0x8d, 0xfe, 0xff, 0xef, 0xff, 0xff, + 0xed, 0xff, 0xff, 0xff, 0x0f, 0xfd, 0xff, 0x8b, 0xfe, 0x85, 0xfe, 0x7f, + 0xd0, 0xff, 0x5f, 0x51, 0xdf, 0xf7, 0x5f, 0x0a, 0xfa, 0xff, 0xef, 0xff, + 0xd0, 0xff, 0xbf, 0xfb, 0xff, 0x5f, 0x61, 0xff, 0xff, 0xff, 0x87, 0xfe, + 0x7f, 0xf5, 0xff, 0x57, 0xff, 0xaf, 0xb6, 0xff, 0x85, 0xfe, 0x5f, 0x45, + 0x7a, 0xc1, 0xff, 0x5f, 0xe8, 0xff, 0x55, 0xd0, 0xef, 0xfa, 0x7f, 0x81, + 0xfe, 0x5f, 0xf5, 0x5f, 0xa8, 0xfe, 0xef, 0xdd, 0xff, 0x77, 0xb0, 0xff, + 0xda, 0xff, 0x82, 0xfe, 0xdf, 0xbb, 0xfe, 0xbb, 0xd5, 0x7b, 0xdb, 0xfa, + 0x0b, 0xf5, 0xef, 0x0d, 0xfe, 0x05, 0xea, 0xff, 0xa0, 0x7d, 0x5f, 0xc1, + 0x77, 0xad, 0xbe, 0x0a, 0xf4, 0xbf, 0xfb, 0xfe, 0x40, 0xeb, 0xbb, 0xea, + 0xbe, 0x55, 0xc1, 0x7f, 0x77, 0xff, 0x0d, 0xfa, 0x6f, 0xc8, 0x7f, 0x89, + 0xd4, 0x0f, 0x41, 0xfa, 0x8d, 0xfd, 0x2b, 0x42, 0x7f, 0xa1, 0xfa, 0x5f, + 0xaa, 0xff, 0x41, 0xf0, 0x0b, 0xc9, 0xbf, 0x80, 0xfa, 0xab, 0x48, 0x3f, + 0x28, 0xfd, 0x8f, 0x54, 0xff, 0x0a, 0xf0, 0xaf, 0x50, 0xff, 0xc1, 0xff, + 0x5f, 0x22, 0xdd, 0x25, 0xd1, 0x5b, 0x92, 0xfc, 0x87, 0xfe, 0x5f, 0x0a, + 0xfa, 0x0a, 0xfa, 0xff, 0xc0, 0xbf, 0x16, 0xd0, 0x55, 0xa4, 0x7a, 0x05, + 0xd0, 0x2f, 0xa2, 0xdf, 0x00, 0xd2, 0x2b, 0x42, 0x7b, 0x93, 0xd0, 0x5f, + 0x8a, 0xff, 0x8b, 0xfe, 0x07, 0x00, 0x7e, 0x00, 0xc0, 0x05, 0x00, 0xf4, + 0x85, 0xfe, 0x0b, 0x40, 0xbf, 0x00, 0xf9, 0x5f, 0x60, 0x7f, 0x02, 0xd2, + 0x03, 0x00, 0x5e, 0x00, 0xf4, 0x05, 0x20, 0x7d, 0x80, 0xe0, 0x05, 0x00, + 0x5a, 0x00, 0xd0, 0x17, 0x40, 0xfd, 0xf2, 0xfe, 0x0f, 0x80, 0xba, 0x02, + 0xa0, 0x07, 0x00, 0xf8, 0x0b, 0xff, 0x0f, 0x0a, 0xfa, 0x01, 0xe8, 0xbf, + 0x84, 0xbe, 0x00, 0xe0, 0x05, 0x00, 0x7a, 0x00, 0xd0, 0x07, 0x00, 0xbe, + 0x00, 0xa0, 0x0b, 0x40, 0x7e, 0x00, 0xe0, 0x2f, 0x00, 0xfe, 0xab, 0xff, + 0x83, 0x00, 0x5a, 0x00, 0xd0, 0x05, 0x00, 0xfa, 0x8d, 0xfd, 0x4b, 0x40, + 0xbf, 0x00, 0xfd, 0xbf, 0xe0, 0x5f, 0x00, 0xf0, 0x03, 0x80, 0x3e, 0x41, + 0xfa, 0x05, 0x80, 0xb7, 0x10, 0xb0, 0x0b, 0x00, 0x3a, 0x00, 0xf8, 0x2b, + 0x40, 0x7f, 0xf3, 0xff, 0x0f, 0x2c, 0x7c, 0x68, 0xa2, 0xa7, 0x2a, 0xfa, + 0x87, 0xfe, 0x3f, 0x81, 0x7c, 0xd1, 0xf5, 0xdf, 0xa8, 0x7f, 0xa9, 0xa0, + 0x0d, 0x2d, 0xf4, 0x0e, 0xea, 0x83, 0x16, 0xfc, 0xa0, 0xc2, 0x07, 0x2d, + 0x5c, 0x54, 0xa1, 0x17, 0x2a, 0xfd, 0xff, 0xff, 0x83, 0x26, 0x36, 0x24, + 0xf0, 0x05, 0x00, 0xfa, 0x85, 0xfe, 0x2f, 0x41, 0x7e, 0xa9, 0xfe, 0xbf, + 0xf0, 0x5f, 0x48, 0xf0, 0x03, 0x04, 0xfa, 0x02, 0xfd, 0x41, 0x02, 0x3d, + 0x48, 0xa2, 0x85, 0x06, 0x36, 0x24, 0xd0, 0x0b, 0x80, 0xff, 0xbf, 0xff, + 0x0d, 0x1b, 0x58, 0x50, 0xa1, 0x93, 0x24, 0xfc, 0x0b, 0xff, 0xdf, 0x80, + 0xfe, 0xd1, 0xff, 0xbf, 0xa8, 0x7f, 0x50, 0xa1, 0x0f, 0x35, 0xfa, 0x4f, + 0xf6, 0x07, 0x00, 0xfd, 0xa0, 0x81, 0x5b, 0x3b, 0x58, 0xd0, 0xe0, 0x27, + 0x01, 0xfc, 0xfb, 0xff, 0x87, 0x0a, 0x7e, 0x54, 0xf0, 0x0b, 0x20, 0xfe, + 0x8d, 0xfd, 0x6f, 0x90, 0x3e, 0xe9, 0xff, 0x5f, 0xe8, 0x5f, 0x34, 0xf0, + 0x8b, 0x1a, 0xfc, 0x45, 0xfa, 0x01, 0x00, 0x5d, 0xa8, 0xe0, 0x4f, 0x0b, + 0x3e, 0x5c, 0x70, 0x13, 0x20, 0xff, 0xff, 0xff, 0x05, 0x35, 0x34, 0x68, + 0xa1, 0x87, 0x0a, 0xf4, 0x87, 0xfe, 0x5f, 0x01, 0xf5, 0xd0, 0xfe, 0xbf, + 0xd0, 0x3f, 0x50, 0xd1, 0x0b, 0x04, 0xf4, 0x17, 0xfc, 0x47, 0x10, 0xba, + 0xc0, 0x82, 0xab, 0x36, 0x58, 0x50, 0xd1, 0x17, 0x00, 0xfd, 0xff, 0xff, + 0x87, 0x16, 0x3a, 0x54, 0xf0, 0x21, 0x00, 0xfe, 0x0a, 0xf7, 0x57, 0x88, + 0x7e, 0xe9, 0xff, 0xd7, 0xd8, 0x5f, 0xb4, 0xd0, 0x0b, 0x40, 0xfe, 0x8a, + 0xfe, 0x45, 0x0a, 0xbf, 0xa0, 0xe0, 0x4d, 0x0b, 0x5e, 0x14, 0xd0, 0x0b, + 0x15, 0xfe, 0xff, 0xff, 0x0b, 0x08, 0x5c, 0x50, 0xa1, 0x07, 0x52, 0xb4, + 0x85, 0xfa, 0x2d, 0x40, 0x7a, 0xa9, 0xff, 0x5f, 0x60, 0x7f, 0xa8, 0xe0, + 0x0d, 0x00, 0xbe, 0x05, 0xea, 0x13, 0x01, 0xda, 0x20, 0xa1, 0xa7, 0x15, + 0x5a, 0x60, 0xe0, 0x27, 0x0a, 0xf5, 0xff, 0xff, 0x8b, 0x0a, 0x5e, 0x54, + 0xb0, 0xa1, 0x10, 0xf6, 0x82, 0xfa, 0x27, 0x04, 0x7f, 0xe1, 0xfd, 0x2b, + 0xa8, 0x1f, 0x24, 0xb1, 0x87, 0xaa, 0xf7, 0xaa, 0xfc, 0x85, 0x08, 0x7b, + 0xa0, 0xa0, 0x25, 0x0a, 0x3a, 0x28, 0xb0, 0x25, 0x11, 0xfd, 0xff, 0xff, + 0x0f, 0x80, 0x1a, 0x20, 0xc0, 0x05, 0x04, 0x78, 0x00, 0xd0, 0x0b, 0x08, + 0xb8, 0x91, 0xfe, 0x07, 0x00, 0x3d, 0x50, 0xc0, 0x0b, 0xc0, 0x7e, 0x00, + 0xd0, 0x07, 0x40, 0x3e, 0x00, 0xc8, 0x03, 0x80, 0xbc, 0x00, 0xc0, 0x07, + 0x00, 0xfe, 0xff, 0xff, 0x47, 0x00, 0x5e, 0x50, 0xd0, 0x45, 0x00, 0x3c, + 0x22, 0xf8, 0x01, 0x06, 0xfe, 0x90, 0xea, 0x13, 0xa1, 0x1f, 0x00, 0xd0, + 0x0b, 0x6a, 0x3f, 0x02, 0xf4, 0x05, 0x00, 0x3f, 0x00, 0xe0, 0x0b, 0x00, + 0x5e, 0x00, 0xd0, 0x01, 0x00, 0xff, 0xff, 0xff, 0x5f, 0xd5, 0x3b, 0x55, + 0xd5, 0x2b, 0x55, 0xf5, 0x95, 0xea, 0xaf, 0xda, 0xfa, 0x01, 0xf8, 0xaf, + 0x94, 0x5e, 0xf5, 0x4a, 0x4f, 0x80, 0xfe, 0x29, 0xe9, 0xab, 0xea, 0x5e, + 0x5b, 0xfd, 0x57, 0xd5, 0xff, 0xaf, 0xaa, 0xaf, 0xaa, 0xfa, 0xff, 0xff, + 0x6f, 0x69, 0xbf, 0x52, 0xf2, 0xa5, 0x94, 0x7a, 0x91, 0xfa, 0x8b, 0x56, + 0x7f, 0x05, 0xed, 0xab, 0xe4, 0xbf, 0x32, 0xf2, 0x37, 0xc0, 0xbe, 0x8a, + 0xfa, 0xaf, 0x6a, 0x7f, 0x49, 0xb6, 0x5b, 0x65, 0x7b, 0x21, 0xf5, 0x8b, + 0x64, 0xff, 0xff, 0xff, 0xff, 0xaa, 0xdf, 0xfa, 0xdd, 0x5b, 0xbb, 0xfe, + 0xde, 0xf6, 0x77, 0xbd, 0xfc, 0x03, 0xf8, 0x6f, 0x5b, 0xdf, 0xed, 0xda, + 0x5f, 0x22, 0xff, 0xab, 0xf6, 0xbb, 0xea, 0xff, 0xb6, 0xfd, 0x6f, 0xb5, + 0xff, 0xdf, 0xda, 0x77, 0xbb, 0xff, 0xff, 0xff, 0x7f, 0xff, 0xff, 0x5f, + 0xed, 0xdf, 0xdf, 0xff, 0xd7, 0xfe, 0xdf, 0xdf, 0xff, 0x12, 0xed, 0x7f, + 0xfb, 0xff, 0x7e, 0xff, 0x6f, 0x90, 0xff, 0xfe, 0xff, 0xdf, 0xff, 0xbf, + 0xb7, 0xff, 0x7f, 0xff, 0xff, 0xdb, 0xff, 0xbf, 0xdb, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xfb, 0xff, 0xff, 0xfb, 0xff, 0xff, 0xff, 0xfb, 0xff, + 0xff, 0xdf, 0xfa, 0xff, 0xdf, 0xff, 0xf7, 0xef, 0xbf, 0x6f, 0xff, 0xb7, + 0xfb, 0xff, 0xfb, 0xff, 0xff, 0xfe, 0xff, 0xef, 0xff, 0xff, 0xee, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xdb, 0xff, 0xab, 0xff, 0x7f, 0xef, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xee, 0xfe, + 0xdf, 0xff, 0xbf, 0xfd, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0x7f, 0xd3, 0xff, 0xab, 0xfe, 0xaf, 0xee, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xbf, 0xf7, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x6d, 0xff, 0x97, 0xff, 0xff, 0xf4, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0x6f, 0xe8, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x5f, 0xe0, 0xff, + 0x85, 0xfd, 0x5f, 0xf0, 0xff, 0xdf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x3f, 0xfd, 0xff, 0xfe, + 0xff, 0xff, 0xff, 0xff, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xa8, 0xff, 0x8f, 0xfe, 0x7f, 0xa4, 0xff, 0xf5, 0xfa, 0xaf, + 0x6e, 0xff, 0xea, 0xfa, 0xb7, 0x5f, 0xff, 0xea, 0xf6, 0x5f, 0xdf, 0xfe, + 0x57, 0xd2, 0xaf, 0xef, 0xff, 0xb5, 0xfd, 0xaf, 0xab, 0xff, 0x57, 0xf5, + 0xff, 0xff, 0xff, 0xff, 0xff, 0x5f, 0xe8, 0xff, 0x85, 0xfe, 0x5f, 0xf1, + 0x7f, 0xaf, 0xde, 0xeb, 0xb7, 0xbb, 0xbe, 0xde, 0xdb, 0xd5, 0x5b, 0x7b, + 0xbb, 0xf7, 0xdb, 0xfe, 0x2a, 0xf8, 0x7b, 0xf5, 0xbf, 0xae, 0xed, 0xeb, + 0xfa, 0xff, 0x7a, 0xbf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xd0, 0xff, + 0x0b, 0xff, 0x7f, 0xa1, 0xff, 0xb2, 0xea, 0x57, 0xad, 0x7e, 0x53, 0xeb, + 0xad, 0x6e, 0x7d, 0xad, 0xea, 0x9b, 0x6e, 0xbb, 0x57, 0xa2, 0x97, 0x55, + 0xff, 0xd5, 0xfa, 0x5f, 0xad, 0x7a, 0x4b, 0xe5, 0xff, 0xff, 0x7f, 0xdb, + 0xfd, 0x5f, 0xf8, 0xff, 0x8d, 0xfd, 0xbf, 0xf1, 0xbf, 0x00, 0xe0, 0x01, + 0x03, 0x5c, 0x50, 0xf0, 0x01, 0x03, 0x1c, 0x40, 0xc0, 0x05, 0x05, 0xfc, + 0x00, 0xf0, 0x83, 0x60, 0x5f, 0x40, 0xd0, 0x01, 0x80, 0xbe, 0x00, 0xa0, + 0xff, 0xff, 0xdf, 0xbd, 0xf6, 0xbf, 0xd0, 0xff, 0x87, 0xfe, 0xff, 0xa0, + 0xff, 0x04, 0xa4, 0x01, 0x15, 0x5a, 0x00, 0xa0, 0x05, 0x09, 0x3a, 0x20, + 0x50, 0x07, 0x1a, 0x7a, 0x03, 0xa0, 0x17, 0x80, 0x7f, 0x10, 0xf2, 0x07, + 0x40, 0xfe, 0x02, 0xc0, 0xff, 0xff, 0x7f, 0xd5, 0xfe, 0xaf, 0xf8, 0xff, + 0x85, 0xfe, 0xbf, 0xb0, 0xbf, 0x00, 0xe0, 0x49, 0x05, 0x3d, 0x50, 0xf0, + 0x41, 0x05, 0x1d, 0x10, 0xc0, 0x23, 0x07, 0x7e, 0x01, 0xf0, 0x05, 0xe0, + 0x5e, 0x00, 0xf0, 0x01, 0x00, 0x5b, 0x00, 0xd0, 0xff, 0xff, 0x5f, 0x08, + 0xd0, 0x7f, 0xd0, 0xff, 0x0b, 0xff, 0xff, 0xc1, 0xff, 0x22, 0xa1, 0x03, + 0x04, 0x75, 0x21, 0xd4, 0x05, 0x10, 0x5a, 0x44, 0xb1, 0x07, 0x15, 0xf9, + 0x53, 0xa4, 0x07, 0x04, 0x7d, 0x08, 0xda, 0x0f, 0x0a, 0x7c, 0x50, 0xa2, + 0xff, 0xff, 0x3f, 0x04, 0xf4, 0x2f, 0xf8, 0xff, 0x85, 0xfd, 0xbf, 0xd0, + 0xbe, 0x02, 0xe1, 0x85, 0x02, 0x3d, 0x11, 0xf2, 0x45, 0x10, 0x5d, 0x50, + 0xd0, 0x85, 0x12, 0xfd, 0x0a, 0xf2, 0x03, 0x01, 0x5f, 0x0a, 0xea, 0x05, + 0x02, 0x1e, 0x08, 0xb0, 0xff, 0xff, 0x7f, 0x81, 0xa0, 0x3f, 0xd0, 0xff, + 0x8f, 0xfe, 0x7f, 0x81, 0xff, 0x15, 0xd8, 0x15, 0x45, 0xfe, 0x02, 0xfa, + 0x03, 0x00, 0x7a, 0x22, 0xe4, 0x07, 0x0d, 0xfe, 0x77, 0xe8, 0x57, 0xa0, + 0xfe, 0x4a, 0xf8, 0x8b, 0x28, 0x74, 0xa8, 0xd0, 0xff, 0xff, 0x5f, 0x00, + 0xf0, 0x17, 0xf8, 0xff, 0x85, 0xfe, 0xbf, 0xe1, 0xff, 0x02, 0xd5, 0x07, + 0xa2, 0x7f, 0x83, 0xba, 0x45, 0x12, 0x3f, 0x11, 0xf2, 0xc1, 0x05, 0xfb, + 0x1d, 0xf4, 0x05, 0x80, 0xbe, 0x2b, 0xfe, 0x0b, 0x0e, 0x1a, 0x54, 0xd0, + 0xff, 0xff, 0x7f, 0x20, 0xa1, 0x7f, 0xd1, 0xff, 0x0b, 0xff, 0xff, 0x50, + 0x7f, 0x17, 0xe8, 0x37, 0x80, 0xfe, 0x09, 0xfa, 0x07, 0x00, 0xdd, 0xa0, + 0xd0, 0x07, 0x16, 0xbd, 0x6b, 0xd2, 0xab, 0x24, 0xff, 0x2e, 0xf4, 0x8f, + 0x28, 0x7c, 0x24, 0xe1, 0xff, 0xff, 0xbf, 0x95, 0xf5, 0x5f, 0xf8, 0xff, + 0x8d, 0xff, 0xbf, 0xd0, 0x7f, 0x81, 0xf4, 0x2b, 0xe5, 0xbf, 0x82, 0xde, + 0x03, 0x00, 0xfd, 0x12, 0xfe, 0x45, 0x03, 0xfd, 0x2d, 0xf8, 0x05, 0xa0, + 0xfb, 0x0b, 0xf6, 0x05, 0x04, 0x36, 0x20, 0xf0, 0xff, 0xff, 0xff, 0xea, + 0xfa, 0xbf, 0xd0, 0xff, 0x87, 0xfa, 0x7f, 0xe1, 0xff, 0x2a, 0xa8, 0x2f, + 0xa0, 0xfe, 0x01, 0xf0, 0x05, 0x11, 0xfe, 0x42, 0xf0, 0x05, 0x14, 0xfe, + 0x2a, 0xe4, 0x07, 0x14, 0xfe, 0x6e, 0xf8, 0x0b, 0x00, 0x7c, 0x00, 0xa0, + 0xff, 0xff, 0xff, 0xbe, 0xfe, 0xdf, 0xf8, 0xff, 0x85, 0xfe, 0xbf, 0xb0, + 0xbf, 0x00, 0xe0, 0x2f, 0xa0, 0x5f, 0x50, 0xf4, 0x27, 0x84, 0x7f, 0x01, + 0xfe, 0x03, 0x85, 0x5f, 0x20, 0xfa, 0x41, 0x82, 0x7f, 0x03, 0xea, 0x07, + 0x40, 0x3f, 0x05, 0xf0, 0xff, 0xff, 0xff, 0xf7, 0xdf, 0x7f, 0xc8, 0xff, + 0x0b, 0xff, 0xff, 0xd1, 0xff, 0xa0, 0xa8, 0xbf, 0xe8, 0x7f, 0x20, 0xd0, + 0x15, 0x22, 0xfd, 0x8b, 0xfa, 0x05, 0x00, 0x7a, 0x04, 0xf4, 0x87, 0x00, + 0xfa, 0x2a, 0xb0, 0x0b, 0x44, 0x7d, 0x41, 0xd2, 0xff, 0xff, 0xff, 0xff, + 0xff, 0x5f, 0xe8, 0xff, 0x8d, 0xff, 0x5f, 0xd0, 0x3f, 0x08, 0xe0, 0xb7, + 0xa0, 0x5f, 0x12, 0xfa, 0x07, 0x85, 0x7f, 0x01, 0xfe, 0x85, 0x22, 0x3f, + 0x21, 0xfa, 0x05, 0x04, 0x7f, 0x03, 0xf4, 0x8b, 0x72, 0xbf, 0x2f, 0xd0, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xd0, 0xff, 0x4b, 0xfd, 0x7f, 0xe1, + 0xff, 0x01, 0xa4, 0xbf, 0x40, 0x7d, 0x40, 0xc0, 0x5b, 0xa2, 0xfe, 0x0f, + 0xfb, 0x03, 0xc0, 0xff, 0x02, 0xed, 0x27, 0x40, 0xfd, 0x01, 0xd0, 0x0b, + 0xdc, 0xff, 0x55, 0xe1, 0xff, 0xff, 0xff, 0xff, 0xff, 0xbf, 0xd8, 0xff, + 0x8f, 0xff, 0xaf, 0xf0, 0xbf, 0x00, 0xf0, 0xbf, 0x10, 0x5f, 0x50, 0xf0, + 0x2f, 0xab, 0xff, 0xc5, 0xff, 0x41, 0xb0, 0xbe, 0x80, 0xfe, 0x13, 0x48, + 0x7f, 0x82, 0xd0, 0x85, 0xd6, 0xff, 0x37, 0xb0, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xef, 0x62, 0xff, 0xf7, 0xfe, 0x7f, 0xd4, 0xff, 0xfe, 0xdf, 0xff, + 0x00, 0xfd, 0x76, 0xf7, 0xf7, 0xf6, 0xff, 0x5f, 0xfd, 0x77, 0xd7, 0xff, + 0xbf, 0xfd, 0xef, 0xb7, 0xfe, 0xfb, 0xfe, 0x07, 0xf0, 0xff, 0x0f, 0xc0, + 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f, 0x65, 0xff, 0xbb, 0xff, 0x2f, 0xf7, + 0xff, 0xab, 0xea, 0xbf, 0x54, 0xbf, 0xde, 0xfd, 0xbf, 0xbf, 0xfd, 0xf7, + 0xff, 0x5f, 0xfb, 0xff, 0xd6, 0xff, 0xbf, 0xba, 0xff, 0x2d, 0xeb, 0x01, + 0xf4, 0xff, 0x2b, 0xd1, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfb, 0xff, + 0xff, 0xff, 0xff, 0xfa, 0xff, 0x7f, 0xff, 0xff, 0xab, 0xfe, 0x7b, 0xf7, + 0xff, 0xff, 0xff, 0xdf, 0xff, 0xf7, 0xfe, 0xff, 0xff, 0xff, 0xf7, 0xef, + 0xff, 0xff, 0xfe, 0xaf, 0xda, 0xff, 0xaf, 0xd4, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xdd, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xff, 0x7f, + 0xbd, 0xff, 0xff, 0xff, 0xff, 0xef, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xfd, 0xff, 0xff, 0xff, 0xab, 0xfe, 0xff, 0xbf, 0xea, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xdf, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xdf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xd7, 0xf7, 0xff, 0xff, 0xff, 0xff, 0xdf, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xfb, 0xff, 0xff, 0xff, 0xff, 0x57, 0xf5, 0xff, 0xff, 0xff, 0xb7, + 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0x7f, 0xfd, 0xff, 0xef, 0xff, 0xb7, 0xf6, 0xfe, + 0xff, 0xff, 0xff, 0xfa, 0xff, 0xdf, 0xff, 0xff, 0xff, 0xff, 0x7a, 0xbf, + 0xff, 0xfd, 0xff, 0xbb, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0x6b, 0xff, 0x5f, 0xd5, 0xff, 0xff, 0xff, 0x2b, 0xd5, 0xff, 0x77, + 0xff, 0xdb, 0xb7, 0xff, 0xff, 0xff, 0x5f, 0xdf, 0xff, 0xd5, 0xff, 0xff, + 0xff, 0x7f, 0x4b, 0xe5, 0xdf, 0xd6, 0xff, 0x96, 0xea, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xae, 0xfa, 0xff, 0xb5, 0xff, 0x6b, 0xff, + 0x07, 0x60, 0xff, 0xaf, 0xff, 0x2f, 0x15, 0xfd, 0xff, 0xf7, 0xbf, 0xe8, + 0xff, 0x86, 0xfe, 0xff, 0xff, 0xbf, 0x00, 0xa0, 0x7f, 0xf5, 0x7f, 0xab, + 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x4b, 0xff, 0x97, + 0xd0, 0xff, 0x7a, 0xfb, 0x05, 0xd0, 0xff, 0x8b, 0xfd, 0x85, 0x95, 0xff, + 0xb6, 0xfd, 0x2b, 0xd5, 0x7f, 0xc3, 0xff, 0xff, 0xff, 0xff, 0x02, 0xc0, + 0x5f, 0x80, 0xfe, 0x02, 0xe0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0x22, 0xfc, 0x2f, 0x00, 0xfd, 0x29, 0xfd, 0x47, 0x45, 0xff, 0x27, + 0xff, 0x05, 0x02, 0x7a, 0xfb, 0xf6, 0x1f, 0xa0, 0xfe, 0x05, 0xfd, 0xff, + 0xff, 0x5f, 0x00, 0xd0, 0x0f, 0xc0, 0xbf, 0x00, 0xfa, 0xff, 0xff, 0xff, + 0xf7, 0xff, 0xff, 0xff, 0x7f, 0x01, 0xff, 0x0b, 0xa0, 0x7d, 0xb9, 0xfd, + 0x05, 0xa0, 0xfe, 0x85, 0xff, 0x03, 0x02, 0xbd, 0xaa, 0x7a, 0x07, 0xc0, + 0xbf, 0x40, 0xff, 0xff, 0xff, 0x7f, 0x00, 0xa0, 0x7f, 0xa0, 0xff, 0x04, + 0xa0, 0xff, 0xff, 0xff, 0xbd, 0xea, 0xbf, 0xed, 0xff, 0x43, 0xea, 0x4d, + 0x08, 0xfe, 0x29, 0xfe, 0x47, 0x02, 0xff, 0x0f, 0xfd, 0x05, 0x01, 0xfe, + 0x2a, 0xd5, 0x3f, 0xa0, 0x7e, 0x05, 0xea, 0xff, 0xff, 0x9f, 0x00, 0xb0, + 0x2f, 0xb5, 0x5f, 0x00, 0xf0, 0xff, 0xff, 0xbf, 0xd6, 0xfe, 0xab, 0xfd, + 0x7f, 0x41, 0xfc, 0x07, 0x00, 0x77, 0x6d, 0xfb, 0x13, 0x40, 0xf7, 0x85, + 0xff, 0x27, 0x45, 0x5f, 0x00, 0xf0, 0x97, 0x82, 0x5f, 0x80, 0xfa, 0x7f, + 0xf5, 0x7f, 0x00, 0xd0, 0xdf, 0xca, 0x7f, 0x00, 0xa1, 0xff, 0xff, 0x7f, + 0xa9, 0xea, 0xdf, 0x56, 0xff, 0x02, 0xf4, 0x05, 0x00, 0xfc, 0xbb, 0xff, + 0x4d, 0x25, 0xfd, 0x0b, 0xfd, 0x0b, 0x80, 0x7a, 0x00, 0xd0, 0x6f, 0x55, + 0x7e, 0x01, 0xe8, 0xff, 0xfb, 0x9f, 0x00, 0xd0, 0xff, 0xfa, 0x1f, 0x22, + 0xa8, 0x57, 0xed, 0x5f, 0x00, 0xb0, 0x01, 0xc0, 0x7f, 0x51, 0xfa, 0x23, + 0x82, 0xf6, 0xfb, 0xff, 0x27, 0x00, 0xff, 0x8d, 0xfd, 0x2b, 0xa2, 0x5f, + 0x50, 0xf4, 0x7f, 0x85, 0x5f, 0x28, 0xf4, 0x3f, 0xd8, 0x7f, 0x00, 0xd0, + 0xff, 0xff, 0xbf, 0x00, 0x82, 0xff, 0x77, 0x5f, 0x00, 0xe0, 0x8b, 0x52, + 0xfb, 0x02, 0xd4, 0x0b, 0x10, 0xfc, 0xff, 0xfb, 0x15, 0x00, 0xfa, 0x07, + 0xff, 0x17, 0xc4, 0x3e, 0x01, 0xa0, 0xdf, 0x22, 0xbd, 0x92, 0xf0, 0x7f, + 0xf5, 0x1f, 0x00, 0xd0, 0x7f, 0xef, 0x1f, 0x24, 0xd0, 0x8b, 0xa8, 0x5f, + 0x00, 0xf0, 0x8b, 0x40, 0xbf, 0x22, 0xfa, 0x41, 0x02, 0xfa, 0xff, 0xff, + 0x07, 0x08, 0xfd, 0x8b, 0xff, 0x1b, 0xa1, 0xbf, 0x50, 0xf0, 0x6f, 0x81, + 0xbd, 0x28, 0xb8, 0x5f, 0xf9, 0x7f, 0x00, 0xe0, 0xff, 0xff, 0x7f, 0x01, + 0x84, 0x05, 0x00, 0x3e, 0xa8, 0xaa, 0x0b, 0x8a, 0x7c, 0x81, 0xe8, 0x13, + 0x04, 0xf8, 0xff, 0xff, 0x45, 0x22, 0xfe, 0x4d, 0xfd, 0x2f, 0x40, 0x5f, + 0x10, 0xa1, 0x7f, 0x00, 0xfe, 0x9b, 0xe8, 0xbf, 0xaa, 0x3f, 0x00, 0xf0, + 0xff, 0xff, 0x1f, 0x08, 0xc2, 0x07, 0xa0, 0x1f, 0x94, 0xfc, 0x0b, 0x00, + 0x7e, 0x01, 0xfc, 0x81, 0x02, 0xfd, 0xff, 0xff, 0x05, 0x02, 0xf7, 0xa7, + 0xff, 0x2b, 0xf0, 0x7f, 0x54, 0xf0, 0x1f, 0x10, 0x5f, 0x49, 0xe8, 0x5f, + 0xf9, 0x7f, 0x00, 0xa0, 0xff, 0xff, 0x7f, 0x40, 0xd0, 0xa5, 0x2a, 0x7f, + 0xe8, 0xeb, 0x4f, 0x24, 0xda, 0x02, 0xea, 0x0b, 0x00, 0xfa, 0xff, 0xff, + 0x03, 0x40, 0xfd, 0x0b, 0xfd, 0x9f, 0x00, 0x3f, 0x00, 0xd0, 0x7f, 0x85, + 0xfa, 0x10, 0xf0, 0x7f, 0xd0, 0x3f, 0x00, 0xf0, 0xff, 0xff, 0x1f, 0x20, + 0x60, 0x57, 0x52, 0x1f, 0x6c, 0xfd, 0x4b, 0x00, 0x7e, 0x22, 0xf4, 0x0b, + 0x40, 0xfa, 0xff, 0xff, 0x45, 0xa0, 0xfe, 0x8d, 0xff, 0x0b, 0xe8, 0x5f, + 0x20, 0xd8, 0x57, 0x41, 0xbf, 0x04, 0xfa, 0x5f, 0xda, 0x7f, 0x00, 0xd0, + 0xff, 0xff, 0xbf, 0x02, 0xd0, 0x57, 0xa9, 0x7f, 0xf4, 0xff, 0x2f, 0x24, + 0xfa, 0x01, 0xfa, 0x05, 0x00, 0xfd, 0xff, 0xff, 0x83, 0x40, 0xff, 0x07, + 0xfd, 0xaf, 0x40, 0x7f, 0x12, 0xe1, 0xbf, 0x00, 0x7d, 0x29, 0xe8, 0x7f, + 0xe0, 0x3f, 0x00, 0xd0, 0xff, 0xff, 0x7f, 0x20, 0xd4, 0x7f, 0xff, 0x5f, + 0xfd, 0xff, 0x05, 0x02, 0x7d, 0x95, 0xfa, 0x87, 0x12, 0xfd, 0xff, 0xff, + 0x03, 0xb4, 0xff, 0x8b, 0xff, 0x2b, 0xa8, 0x5f, 0x00, 0xf8, 0xa5, 0xa4, + 0xbd, 0x00, 0xfd, 0x2f, 0xf4, 0x7f, 0x00, 0xe0, 0xff, 0xff, 0xdf, 0x02, + 0xe0, 0xef, 0xdb, 0xff, 0xf6, 0xff, 0x0b, 0x88, 0xfe, 0x4a, 0xfe, 0x2d, + 0x40, 0xfe, 0xff, 0xff, 0x07, 0x52, 0xfd, 0x0b, 0xfd, 0x5f, 0xc0, 0x7e, + 0x01, 0xd0, 0x17, 0x05, 0xfe, 0x01, 0xf6, 0x5f, 0xa1, 0xff, 0x00, 0xb0, + 0xff, 0xff, 0xff, 0x90, 0xfa, 0xff, 0xff, 0x7f, 0xff, 0xff, 0x83, 0xc0, + 0xfe, 0xef, 0xef, 0x2f, 0x48, 0xff, 0xff, 0xff, 0x2b, 0x09, 0xff, 0x85, + 0xff, 0x0b, 0x60, 0x5f, 0xbc, 0xfa, 0x05, 0x00, 0xbf, 0xc2, 0xff, 0x6f, + 0xf0, 0x3f, 0x00, 0xc0, 0xff, 0xff, 0xff, 0x07, 0xf6, 0xff, 0xff, 0xff, + 0xfd, 0xff, 0x0b, 0x49, 0xff, 0x7b, 0xff, 0x57, 0xa1, 0xff, 0xff, 0xff, + 0x17, 0x00, 0xfd, 0x0f, 0xfd, 0x2f, 0x40, 0xbf, 0xa7, 0xed, 0x05, 0x00, + 0xfa, 0x45, 0xfa, 0x3f, 0xa0, 0xff, 0x00, 0xd0, 0xff, 0xff, 0x7f, 0x05, + 0xf5, 0xff, 0xff, 0xff, 0xff, 0xff, 0x43, 0xe1, 0xff, 0xff, 0xff, 0x3f, + 0xd0, 0xff, 0xff, 0xff, 0x1f, 0x80, 0xfe, 0x85, 0xff, 0x2b, 0xa4, 0xff, + 0xfa, 0xf6, 0x03, 0x00, 0xff, 0x46, 0xff, 0x2f, 0xf0, 0x3f, 0x00, 0xc0, + 0xff, 0xff, 0xff, 0xfb, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f, 0xbd, + 0xff, 0xbf, 0xff, 0xff, 0xef, 0xfd, 0xff, 0xff, 0xef, 0x2a, 0xff, 0xaf, + 0xfe, 0x2f, 0x51, 0xff, 0xff, 0xff, 0x57, 0x55, 0xfd, 0xd5, 0xff, 0x7f, + 0xa0, 0xff, 0x00, 0xe0, 0xff, 0xff, 0xff, 0x5f, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0x57, 0xef, 0xff, 0xff, 0xff, 0xaf, 0xfa, 0xff, 0xff, 0xff, + 0xb7, 0xc4, 0xff, 0xab, 0xff, 0xbf, 0xda, 0xff, 0xdf, 0xff, 0x55, 0xa5, + 0xff, 0xd7, 0xff, 0x2f, 0xfa, 0xbf, 0x54, 0xa2, 0xff, 0xff, 0xff, 0xf7, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0x6a, 0xfb, 0xaf, 0xff, 0xef, 0xf6, 0xff, + 0xff, 0xfb, 0xbf, 0xda, 0xfe, 0xbf, 0xff, 0xff, 0xd0, 0x7f, 0x55, 0xea, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xf7, 0xff, 0xff, 0xff, 0x7f, 0x77, 0xff, 0xff, + 0xff, 0xff, 0xf7, 0xff, 0xff, 0xff, 0xdf, 0xff, 0xff, 0xfd, 0xff, 0xbf, + 0xfe, 0xff, 0xdd, 0xfd, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xf7, 0xff, 0xff, 0xf7, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xed, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xed, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0x7f, 0x55, 0xff, 0xbf, 0xfa, 0xff, 0xd5, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xfb, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f, 0xbb, + 0xfa, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f, 0xff, 0xff, 0x7f, 0xfd, 0xff, + 0xff, 0xff, 0x5f, 0xfd, 0xff, 0xff, 0xff, 0xbf, 0xf5, 0xff, 0xef, 0xfe, + 0xff, 0xee, 0xff, 0xff, 0xff, 0xef, 0xfe, 0x7f, 0xfd, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xbf, 0x8a, 0xff, 0xff, 0xff, 0xff, 0xfb, 0xff, 0x7f, 0x65, + 0xff, 0x8b, 0xff, 0xff, 0xff, 0xff, 0xab, 0xff, 0xff, 0xfb, 0xff, 0x7f, + 0x01, 0xf7, 0x3f, 0xf0, 0xff, 0x43, 0xff, 0xff, 0xff, 0xbb, 0xff, 0xff, + 0x55, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x52, 0xea, 0xff, 0xff, 0xff, + 0xbf, 0xff, 0xdf, 0xd2, 0xff, 0x57, 0xfa, 0xff, 0xfe, 0xff, 0x5f, 0xfa, + 0x7f, 0xfd, 0x7f, 0x5b, 0xc9, 0xbf, 0x17, 0xfd, 0xbf, 0x60, 0xff, 0xff, + 0xff, 0xaf, 0xfd, 0x5f, 0xf4, 0xff, 0xff, 0xff, 0xff, 0xff, 0x5f, 0x10, + 0xf5, 0xff, 0xff, 0xff, 0xd7, 0xff, 0x6f, 0xf4, 0xff, 0x52, 0xff, 0xff, + 0xf7, 0xff, 0x45, 0xfb, 0xff, 0xe8, 0xdf, 0x6e, 0x10, 0xef, 0x6e, 0x70, + 0xfb, 0x89, 0xff, 0xff, 0x7f, 0x13, 0xea, 0xff, 0xa0, 0xff, 0xff, 0xff, + 0xff, 0xff, 0x7f, 0x00, 0xd0, 0xff, 0xff, 0xff, 0x4d, 0xfd, 0x3f, 0x42, + 0xff, 0x05, 0xf4, 0xbf, 0xfa, 0xff, 0x06, 0xec, 0xbf, 0xf8, 0xbf, 0x36, + 0x82, 0xa3, 0x57, 0xb4, 0xbf, 0xa0, 0xff, 0xff, 0xff, 0x85, 0xfc, 0x5f, + 0xd0, 0xff, 0xff, 0xff, 0xff, 0xff, 0x5f, 0x00, 0xf2, 0xff, 0xff, 0xff, + 0xa7, 0xff, 0x17, 0xc0, 0x7f, 0x45, 0xfc, 0xff, 0xd8, 0xff, 0x25, 0xf4, + 0xff, 0xea, 0x5f, 0x5a, 0x50, 0x57, 0x3d, 0x70, 0xf5, 0x82, 0xff, 0xff, + 0xff, 0x45, 0xe0, 0xbf, 0xe8, 0xff, 0xff, 0xff, 0xff, 0xff, 0xbf, 0x84, + 0xa0, 0xdf, 0xfe, 0xfe, 0x0d, 0xfc, 0x5f, 0x54, 0xff, 0x03, 0xf5, 0xbf, + 0xf0, 0xff, 0x82, 0xe8, 0xbf, 0xf4, 0x3f, 0x94, 0x48, 0x07, 0x17, 0x3c, + 0xbc, 0xe0, 0xff, 0x6e, 0xbf, 0x24, 0xf4, 0xbf, 0x68, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xbf, 0x80, 0xd0, 0xeb, 0x57, 0xff, 0x97, 0xff, 0x57, 0xd0, + 0x7f, 0xa5, 0xfe, 0x57, 0xd8, 0x7f, 0xa1, 0xf4, 0x7f, 0xf5, 0x7f, 0x22, + 0x91, 0x57, 0x2a, 0x34, 0xd2, 0x92, 0xbf, 0xdb, 0xfb, 0xa2, 0xd4, 0x6f, + 0xd0, 0xff, 0xff, 0xff, 0x7f, 0xf7, 0x7f, 0x02, 0xd0, 0x5f, 0x6d, 0xfb, + 0x17, 0xfa, 0x2f, 0xa4, 0xff, 0x83, 0xf4, 0xbd, 0xa8, 0xfe, 0x45, 0xd0, + 0xbf, 0xe8, 0x5f, 0x52, 0xc0, 0x13, 0x1a, 0x34, 0x59, 0xc0, 0xdf, 0x5a, + 0xfd, 0x82, 0xf0, 0xbf, 0xf8, 0xff, 0xff, 0xff, 0xff, 0xfb, 0x5f, 0x82, + 0xd0, 0x05, 0x17, 0xfc, 0xdb, 0xfe, 0x57, 0xa4, 0x7f, 0x15, 0xfe, 0x07, + 0xa0, 0x7f, 0x25, 0xfc, 0xdf, 0x50, 0x7f, 0x11, 0x12, 0x97, 0x48, 0xb8, + 0xd0, 0xa2, 0xb7, 0x54, 0xbe, 0x45, 0xd4, 0x7f, 0xc8, 0xff, 0xff, 0xff, + 0x7f, 0xb5, 0x7f, 0x01, 0xc1, 0x07, 0x09, 0xfa, 0x5f, 0xff, 0x2f, 0x50, + 0xff, 0x0b, 0xf5, 0xab, 0x48, 0xfa, 0x85, 0xe8, 0x7f, 0xd0, 0x7f, 0x81, + 0x90, 0x0b, 0x24, 0xbc, 0x24, 0xa1, 0x2f, 0x04, 0xfe, 0x22, 0xf4, 0x17, + 0xe8, 0xff, 0xff, 0xff, 0xbf, 0xe8, 0x3f, 0x41, 0xf8, 0x45, 0x15, 0xfd, + 0xff, 0xff, 0x37, 0xca, 0xff, 0x42, 0xf4, 0x05, 0x00, 0xff, 0x4b, 0xfe, + 0xbf, 0x60, 0xdf, 0x08, 0x40, 0x27, 0x00, 0x70, 0x00, 0x80, 0x17, 0x08, + 0xfa, 0x83, 0xe8, 0xbf, 0xd0, 0xff, 0xff, 0xff, 0xff, 0xe8, 0xff, 0x00, + 0xc0, 0x05, 0x0a, 0xfd, 0xef, 0xfb, 0x5f, 0x40, 0xff, 0x0a, 0xf8, 0x07, + 0x00, 0xfd, 0x5d, 0xf5, 0xbf, 0x50, 0x7f, 0x41, 0x41, 0x03, 0x00, 0x34, + 0xa1, 0xc0, 0x15, 0x02, 0xfb, 0x20, 0xf4, 0x5f, 0xe8, 0xff, 0xff, 0xff, + 0x5f, 0xe0, 0x5f, 0x02, 0xf4, 0x83, 0x0b, 0xfd, 0xff, 0xff, 0x17, 0xca, + 0xbf, 0x45, 0xfe, 0x05, 0x00, 0xfd, 0x4f, 0xff, 0x7f, 0x05, 0xfd, 0x08, + 0x80, 0x17, 0x84, 0xd0, 0x04, 0x20, 0x87, 0x88, 0xbe, 0x0f, 0xf9, 0xb7, + 0x52, 0xff, 0xff, 0xff, 0xff, 0xa8, 0x7f, 0x11, 0xf5, 0x47, 0x0a, 0xfa, + 0xff, 0xff, 0x7f, 0x51, 0xff, 0x17, 0xf9, 0xab, 0x70, 0xff, 0xff, 0xfe, + 0x5f, 0x81, 0xbf, 0x00, 0xfa, 0x45, 0xa1, 0x7e, 0x00, 0xb5, 0x03, 0x44, + 0xfd, 0x41, 0xec, 0x3f, 0xe9, 0xff, 0xff, 0xff, 0x5f, 0xe8, 0x3f, 0x81, + 0xfe, 0x01, 0x0b, 0xff, 0xff, 0xff, 0x5f, 0xd5, 0xff, 0x45, 0xfd, 0x5f, + 0xa8, 0xff, 0x77, 0xff, 0x6f, 0x05, 0x7c, 0x21, 0xa8, 0x27, 0x08, 0x58, + 0x10, 0xea, 0x0b, 0x81, 0x7e, 0x05, 0x60, 0xff, 0xfe, 0xff, 0x57, 0xff, + 0xff, 0xfb, 0xff, 0x00, 0xf5, 0x47, 0x04, 0xfd, 0xff, 0xff, 0xff, 0xfb, + 0xff, 0xbf, 0xff, 0xb7, 0xb0, 0xff, 0xff, 0xff, 0x37, 0x89, 0x5f, 0x11, + 0xe9, 0x05, 0x8d, 0xbe, 0x80, 0xe8, 0x83, 0x40, 0xff, 0x01, 0xfc, 0xef, + 0x77, 0xff, 0xfb, 0xff, 0x7f, 0xfd, 0x5f, 0x82, 0xfe, 0x01, 0x01, 0xfd, + 0xff, 0xff, 0xff, 0xfd, 0xff, 0xff, 0xff, 0x5f, 0xd4, 0xfb, 0xff, 0xff, + 0x17, 0x12, 0xfa, 0x00, 0xd0, 0x0b, 0x29, 0x58, 0x28, 0xb4, 0x0d, 0x00, + 0xf5, 0x06, 0xe8, 0x7f, 0xff, 0xff, 0x0f, 0xfd, 0xff, 0xff, 0x7f, 0x01, + 0xff, 0x07, 0x04, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xdf, 0xfd, 0xb7, + 0x68, 0xff, 0xff, 0xff, 0x17, 0x01, 0x3f, 0x90, 0xd8, 0x07, 0x16, 0xbd, + 0x00, 0xd4, 0x47, 0x0a, 0xfe, 0xf6, 0xef, 0xff, 0xff, 0xff, 0x85, 0xff, + 0xff, 0xff, 0x3f, 0x81, 0xfa, 0x01, 0x21, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xf7, 0xff, 0x97, 0xa4, 0xff, 0xff, 0xff, 0x17, 0x04, 0x7d, 0x21, + 0xa2, 0xab, 0x54, 0x54, 0x20, 0xe1, 0x2f, 0x00, 0xfa, 0xad, 0xfa, 0xff, + 0xff, 0xff, 0x0b, 0xfc, 0xff, 0xff, 0x7f, 0x80, 0xf6, 0x05, 0x00, 0xfa, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x2b, 0x21, 0xfd, 0xff, 0xff, + 0x17, 0x25, 0x3f, 0x01, 0xc1, 0x15, 0x54, 0x38, 0x08, 0xe1, 0x0b, 0x0a, + 0xfb, 0xff, 0xfe, 0xff, 0xff, 0xff, 0x82, 0xfe, 0xff, 0xff, 0x5f, 0x22, + 0xfa, 0x41, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x8d, + 0x28, 0xff, 0xff, 0xff, 0x2f, 0xc0, 0xde, 0xa0, 0xa4, 0x0b, 0x59, 0xb4, + 0x90, 0xa8, 0x7f, 0x69, 0xfe, 0xdf, 0xff, 0xff, 0xff, 0xff, 0x0b, 0xfd, + 0xff, 0xff, 0x5f, 0x00, 0xf4, 0x6f, 0x17, 0xfa, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0x03, 0x00, 0xfd, 0xff, 0xff, 0x17, 0xa0, 0x7f, 0x50, + 0xab, 0x47, 0x6c, 0x37, 0xa8, 0xea, 0xaf, 0x2d, 0xfb, 0xff, 0xff, 0xff, + 0xff, 0xff, 0x02, 0xfd, 0xff, 0xff, 0x3f, 0x00, 0xfa, 0x7f, 0x13, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x03, 0x00, 0xff, 0xff, 0xff, + 0x7f, 0x6f, 0x7f, 0xd1, 0xed, 0x05, 0xf4, 0xba, 0xd0, 0xef, 0x7f, 0xfb, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x0b, 0xfe, 0xff, 0xff, 0x7f, 0x00, + 0xd4, 0xff, 0x0d, 0xfd, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xdf, 0xfd, 0xff, 0xff, 0xdf, 0xf5, 0xbf, 0xed, 0xee, 0xef, 0x7f, 0xff, + 0xfe, 0xfa, 0xff, 0xbf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x4d, 0xf7, + 0xff, 0xff, 0x5f, 0xff, 0xff, 0xff, 0x57, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xab, 0xd4, 0xfe, 0xff, 0xff, 0x7f, 0xff, 0xff, 0xfb, + 0xff, 0x7f, 0xf5, 0xbf, 0xed, 0xff, 0xff, 0xff, 0xfe, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xab, 0xfd, 0xff, 0xff, 0xff, 0xa5, 0xfa, 0xff, 0xaf, 0xfd, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xef, 0xff, 0xfd, 0xff, 0xb7, 0xff, 0xff, 0xff, 0xdf, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x8f, 0xfe, 0xff, 0xff, 0xff, 0xfe, + 0xff, 0xff, 0xbf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f, + 0xf7, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x5f, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0x7f, 0xff, 0xdf, 0xf5, 0xff, 0xff, 0xff, 0xff, 0xfb, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xbf, 0xfb, 0xff, 0xd7, + 0xff, 0xdf, 0xfe, 0xff, 0xbf, 0xf7, 0x5f, 0xd5, 0xff, 0xaf, 0xfe, 0xbf, + 0xfe, 0xff, 0xff, 0xfe, 0x57, 0xb5, 0xff, 0xf7, 0xff, 0xff, 0xfe, 0xff, + 0xff, 0xff, 0x7f, 0xbd, 0xff, 0x57, 0xff, 0x5f, 0xfb, 0xff, 0xbf, 0xfa, + 0xef, 0xae, 0xfe, 0x8d, 0xfa, 0x37, 0xff, 0xff, 0x7f, 0xfc, 0xf7, 0xff, + 0xff, 0x2b, 0xff, 0x6f, 0xf5, 0xff, 0x5f, 0xf9, 0xdb, 0xea, 0x7f, 0xbd, + 0xfe, 0xbf, 0xd0, 0xff, 0xff, 0xff, 0xbf, 0xef, 0xff, 0x9b, 0xfd, 0x3f, + 0xfd, 0xff, 0x6f, 0xfd, 0x37, 0xe3, 0xff, 0x46, 0xff, 0x97, 0xfa, 0xff, + 0x57, 0xfe, 0x5f, 0x84, 0xfe, 0x8f, 0xfa, 0x2f, 0xfe, 0xff, 0xaf, 0xfc, + 0x5b, 0xaa, 0x5b, 0x95, 0xf7, 0xbf, 0xd4, 0xff, 0x5b, 0xfb, 0x5f, 0x69, + 0xff, 0x8b, 0xfe, 0xaf, 0xdd, 0xff, 0x3f, 0xf6, 0x2f, 0x95, 0xfe, 0x8b, + 0xfa, 0x3f, 0xed, 0xff, 0x5f, 0xea, 0x2f, 0xca, 0xff, 0x22, 0xf5, 0xff, + 0xa0, 0xff, 0x15, 0xf5, 0x4b, 0xd2, 0xbe, 0x4a, 0xfc, 0x7f, 0xe1, 0xff, + 0xf7, 0xfe, 0xdf, 0xa4, 0xff, 0x16, 0xfb, 0x3f, 0xf2, 0xff, 0x57, 0xfa, + 0x07, 0xa1, 0x7f, 0x41, 0xfa, 0x2b, 0xf4, 0xff, 0x05, 0xfe, 0x2b, 0x41, + 0x7e, 0x03, 0xfc, 0x17, 0xf8, 0xfd, 0x16, 0xfa, 0x01, 0x00, 0xbe, 0xa0, + 0xf6, 0x2f, 0xb4, 0xff, 0x32, 0xfa, 0x17, 0xa0, 0xff, 0x03, 0xfd, 0x5f, + 0xf8, 0xff, 0x0b, 0xfd, 0x57, 0x14, 0xfd, 0x02, 0xfc, 0x3f, 0x69, 0x7f, + 0x57, 0xf5, 0x4f, 0x14, 0xfb, 0x25, 0xa1, 0x6f, 0x82, 0xfe, 0x85, 0xaa, + 0x0b, 0x80, 0x1d, 0x04, 0xf8, 0x7f, 0xc1, 0xfd, 0x53, 0xd5, 0x7f, 0x00, + 0xfd, 0x15, 0xea, 0xbf, 0xa0, 0xfe, 0x57, 0xf6, 0x13, 0x42, 0x3f, 0x52, + 0xea, 0x8b, 0xa8, 0xbf, 0x01, 0xfa, 0x0b, 0x42, 0x5d, 0x20, 0xf4, 0x2b, + 0xa2, 0x3e, 0x24, 0xe8, 0x41, 0x15, 0x1c, 0x00, 0xfc, 0x5f, 0x54, 0xff, + 0x4a, 0xfc, 0x0f, 0xaa, 0xff, 0x4a, 0xf4, 0xaf, 0xd4, 0xff, 0x0d, 0xf5, + 0x07, 0x80, 0x7e, 0x01, 0xd0, 0x2f, 0x42, 0x7d, 0x55, 0xd1, 0x07, 0x00, + 0xba, 0x00, 0x80, 0x07, 0x00, 0xf4, 0x00, 0xa0, 0x93, 0x2a, 0x3a, 0x05, + 0xf4, 0x7f, 0xa1, 0xfe, 0x27, 0xe2, 0xff, 0x00, 0xfd, 0x07, 0xf5, 0x7f, + 0x41, 0xff, 0x4b, 0xf2, 0x27, 0x20, 0x5f, 0x20, 0xfa, 0x05, 0x20, 0x5f, + 0x00, 0xf8, 0x41, 0x00, 0xba, 0x00, 0xe0, 0x05, 0x00, 0x3e, 0x00, 0xa0, + 0x83, 0x17, 0x1e, 0x21, 0xfd, 0x2f, 0x88, 0xff, 0x12, 0xf9, 0x17, 0x54, + 0x7f, 0x51, 0xf0, 0x5f, 0x54, 0xff, 0x0d, 0xba, 0xaf, 0xd4, 0x7e, 0x02, + 0xd0, 0x07, 0x80, 0x7e, 0x01, 0xd0, 0x8f, 0x4a, 0xbd, 0xb0, 0xd4, 0x8b, + 0x4a, 0xba, 0xa8, 0xd4, 0x77, 0x15, 0x38, 0x0a, 0xe8, 0xbf, 0x20, 0xfd, + 0x05, 0xe4, 0xbf, 0x00, 0xfd, 0x07, 0x6a, 0xbf, 0x00, 0xfd, 0x03, 0xe0, + 0xb7, 0xd0, 0xbf, 0x8b, 0xfe, 0x77, 0x68, 0x7f, 0x85, 0xfe, 0x83, 0x04, + 0xbe, 0x88, 0xd0, 0x8b, 0x04, 0xbf, 0x48, 0xd0, 0xd5, 0x2f, 0x5e, 0x00, + 0xfc, 0x2f, 0x00, 0xff, 0x02, 0xf0, 0x5f, 0x80, 0xff, 0x02, 0xf0, 0x2f, + 0x40, 0x7f, 0x09, 0xf9, 0x5f, 0xe8, 0xff, 0x05, 0xf5, 0x5f, 0xd1, 0xff, + 0x0b, 0xf5, 0x0f, 0x8a, 0xba, 0x50, 0xe4, 0x0b, 0x4a, 0xba, 0xa0, 0xe8, + 0x77, 0x1f, 0xb8, 0x10, 0xe8, 0xbf, 0xc8, 0xff, 0x0b, 0xfd, 0x2f, 0xa0, + 0xfe, 0x03, 0xed, 0xaf, 0xa0, 0xff, 0x03, 0xec, 0xbf, 0xe8, 0xfe, 0x82, + 0xff, 0x57, 0xd8, 0x7f, 0x85, 0xfd, 0xa5, 0x42, 0xff, 0x24, 0x68, 0x47, + 0x82, 0xbe, 0x10, 0xe4, 0xff, 0x27, 0xbe, 0x00, 0xec, 0x17, 0x60, 0x7f, + 0x81, 0xea, 0x37, 0xa8, 0x7f, 0x81, 0xfc, 0x2f, 0xa8, 0x7f, 0x81, 0xf6, + 0x6f, 0xe8, 0xff, 0x8f, 0xfc, 0xff, 0xe8, 0xff, 0x8b, 0xfe, 0x1f, 0x08, + 0xfc, 0x82, 0xe4, 0x2f, 0x08, 0xfe, 0xa5, 0xa8, 0xff, 0x3f, 0x74, 0x08, + 0xe8, 0x2f, 0xa4, 0xff, 0x22, 0xfa, 0x2f, 0xa2, 0xff, 0x22, 0xf4, 0x37, + 0x62, 0xff, 0x2b, 0xfa, 0xbf, 0xe8, 0xff, 0x8a, 0xfe, 0x5f, 0xf0, 0xff, + 0x8b, 0xfe, 0x2f, 0x40, 0xbf, 0x02, 0xf0, 0x37, 0x40, 0x77, 0x01, 0xe8, + 0xab, 0x05, 0x3a, 0x00, 0xd5, 0x2d, 0xc5, 0xbd, 0x22, 0xf4, 0x2b, 0xc1, + 0x7f, 0x11, 0xfe, 0x2f, 0x42, 0xbf, 0x40, 0xfc, 0xff, 0xf0, 0xff, 0x0b, + 0xff, 0xbf, 0xa8, 0xff, 0x86, 0xfe, 0x5b, 0x80, 0xfc, 0x45, 0xa8, 0x2f, + 0x82, 0xfc, 0x06, 0xd0, 0xff, 0x3e, 0xdc, 0x05, 0xe0, 0x17, 0x21, 0x7f, + 0x11, 0xd4, 0x17, 0x24, 0x7d, 0x52, 0xd0, 0x07, 0xa1, 0x7e, 0x21, 0xe2, + 0x5f, 0xd8, 0xff, 0x8d, 0xfd, 0xdf, 0xe8, 0xff, 0x8b, 0xfe, 0x2f, 0x8a, + 0xbe, 0x02, 0xe4, 0x2b, 0x40, 0x7e, 0x43, 0xf4, 0x83, 0x02, 0x76, 0x20, + 0xa0, 0x05, 0x84, 0x5e, 0x20, 0xf2, 0x05, 0x85, 0x5f, 0x41, 0xfa, 0x15, + 0x84, 0x5f, 0x10, 0xf8, 0x6f, 0xe0, 0x7f, 0x87, 0xfa, 0x6f, 0xe8, 0xff, + 0x86, 0xf6, 0x55, 0x00, 0xdd, 0xa4, 0xa8, 0x4b, 0x88, 0xbe, 0x00, 0xa0, + 0x2b, 0x15, 0xba, 0x0a, 0xd4, 0x17, 0x00, 0x7d, 0x02, 0xd0, 0x17, 0x00, + 0x7c, 0x00, 0xc0, 0x07, 0x00, 0x7a, 0x41, 0xd0, 0x3f, 0xb8, 0xfe, 0x01, + 0xff, 0x37, 0x50, 0x7f, 0x03, 0xfd, 0x03, 0x4a, 0x3d, 0x84, 0xe8, 0x11, + 0x45, 0x36, 0xaa, 0xb4, 0x09, 0x80, 0x1e, 0x81, 0xc2, 0x05, 0x80, 0x5e, + 0x00, 0xe8, 0x05, 0x80, 0x1f, 0x00, 0xf0, 0x81, 0x80, 0x1e, 0x00, 0xe8, + 0xab, 0xa0, 0x7f, 0x8b, 0xd4, 0xaf, 0xd0, 0xdf, 0x8a, 0xea, 0x93, 0x04, + 0x3e, 0x51, 0xa0, 0x47, 0x0a, 0x9d, 0x40, 0xc8, 0x07, 0x00, 0x7a, 0x24, + 0x40, 0x03, 0x15, 0x3a, 0x48, 0xa1, 0x43, 0x12, 0x7a, 0x28, 0xa1, 0x07, + 0x14, 0x7a, 0x28, 0xa0, 0x07, 0x40, 0x3f, 0x00, 0xf4, 0x03, 0x40, 0x7d, + 0x00, 0xf4, 0x01, 0x00, 0x1a, 0x00, 0xe0, 0x01, 0x00, 0x3a, 0x00, 0xe0, + 0x03, 0x40, 0x1f, 0x00, 0x42, 0x83, 0x00, 0x1b, 0x00, 0xb0, 0x01, 0x00, + 0x1d, 0x04, 0xb0, 0x41, 0x02, 0x1f, 0x00, 0xd1, 0x2b, 0x08, 0xfd, 0x02, + 0xe8, 0x2f, 0x08, 0xbf, 0x02, 0xf0, 0x05, 0x00, 0x5c, 0x00, 0xa0, 0x03, + 0x00, 0x3c, 0x10, 0x40, 0x5f, 0xb1, 0x3d, 0x00, 0x80, 0x01, 0x05, 0x5c, + 0x64, 0xc0, 0x05, 0x05, 0x38, 0xa0, 0xc0, 0x03, 0x04, 0x38, 0x50, 0xa0, + 0x07, 0x40, 0x5f, 0x00, 0xf2, 0x05, 0x40, 0x5f, 0x80, 0xf4, 0x01, 0x20, + 0x1f, 0x00, 0xa4, 0x09, 0x00, 0x1e, 0x01, 0xe2, 0x57, 0x90, 0x1f, 0x04, + 0xa1, 0x01, 0x01, 0x1a, 0x20, 0xd0, 0x01, 0x05, 0x1d, 0x10, 0xa0, 0x01, + 0x05, 0x1d, 0x10, 0xa0, 0xad, 0x4a, 0x7f, 0xa5, 0xea, 0x2f, 0x95, 0xfd, + 0x2a, 0xda, 0xaf, 0x0a, 0x7a, 0x55, 0xe1, 0xa7, 0xaa, 0xfa, 0x94, 0xa8, + 0xbf, 0xc0, 0x7f, 0x51, 0xaa, 0x25, 0x44, 0x5c, 0x20, 0x80, 0x05, 0x01, + 0x5c, 0x40, 0xc0, 0x05, 0x02, 0x58, 0x44, 0xc0, 0x97, 0x50, 0x7f, 0x29, + 0xf5, 0x93, 0xa0, 0x7f, 0x89, 0xfa, 0x8b, 0xa4, 0xbe, 0x12, 0xf4, 0x2b, + 0x84, 0x5e, 0x44, 0xea, 0x7f, 0xd1, 0x3f, 0x88, 0xa2, 0x23, 0x25, 0x5f, + 0x2a, 0xf5, 0xa5, 0x54, 0x5f, 0x6a, 0xfa, 0xa5, 0x52, 0x5f, 0x32, 0xf5, + 0xff, 0xee, 0xff, 0xd7, 0xfd, 0x7f, 0x7f, 0xff, 0xef, 0xed, 0xf7, 0xb6, + 0xff, 0xed, 0xbb, 0xdf, 0x77, 0xff, 0xbb, 0xeb, 0x7f, 0x41, 0xdf, 0xf7, + 0xfd, 0x95, 0x4e, 0x5a, 0xd1, 0xd2, 0x15, 0x97, 0x5a, 0xb1, 0xa2, 0x95, + 0x16, 0xbd, 0x54, 0xa9, 0x5f, 0xf7, 0x7f, 0x7b, 0xff, 0xdf, 0xdb, 0xbf, + 0x75, 0xff, 0xbf, 0xb7, 0xbf, 0xbd, 0xfd, 0x77, 0xb5, 0x7f, 0xdb, 0xfe, + 0xbf, 0xfd, 0xff, 0xb6, 0xee, 0xdf, 0x6b, 0x7f, 0x7f, 0xfd, 0xf7, 0xd5, + 0x7e, 0xdf, 0xfe, 0xf7, 0xdb, 0xbf, 0xf6, 0xfd, 0xff, 0x7f, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfb, 0xfe, 0xfb, 0xf7, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xfb, 0xff, 0xeb, 0xff, 0xff, 0xff, 0x77, 0xff, 0xff, + 0xf5, 0xdb, 0xbf, 0xff, 0xff, 0xfb, 0xf7, 0x5f, 0xf7, 0xfd, 0x7f, 0xef, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xdf, 0xff, 0xbf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xfb, 0xff, 0xff, 0xef, 0xb7, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xea, 0xff, 0xb7, 0xff, 0xff, 0xd7, 0xff, 0xfb, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xbf, 0xf5, 0xff, 0xef, 0xfe, 0xbf, 0xfa, + 0xff, 0xbf, 0xfb, 0xdf, 0xda, 0xff, 0xff, 0xff, 0x7f, 0xda, 0xff, 0x7f, + 0xfb, 0xbf, 0xfa, 0xff, 0xff, 0xff, 0xbf, 0xfa, 0xff, 0xb5, 0xff, 0x7f, + 0xf5, 0xbf, 0xde, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xd7, 0xb6, 0xff, + 0x5b, 0xff, 0x6f, 0xff, 0xff, 0xaf, 0xfe, 0xd7, 0xf6, 0xff, 0x57, 0xf5, + 0xdf, 0xea, 0xff, 0xdf, 0xed, 0x2f, 0xfd, 0xff, 0x6f, 0xf5, 0x7f, 0x41, + 0xff, 0xc7, 0xfe, 0xff, 0x83, 0xfe, 0x6b, 0xfd, 0xff, 0xff, 0xff, 0xad, + 0xfd, 0x2f, 0xc0, 0xff, 0x07, 0xfa, 0x5f, 0xea, 0xff, 0x5f, 0xf4, 0x2f, + 0x41, 0xff, 0xbd, 0xdf, 0x5f, 0xea, 0xff, 0x6f, 0x75, 0x17, 0xed, 0xff, + 0x75, 0xff, 0x5f, 0xf0, 0xff, 0xa2, 0xff, 0xbf, 0xd0, 0xbf, 0xa8, 0xee, + 0xff, 0xff, 0xff, 0xf7, 0xfe, 0x8b, 0xd2, 0xfe, 0x12, 0xff, 0x6f, 0xf8, + 0xff, 0x0b, 0xfe, 0x0b, 0xd1, 0xff, 0xd6, 0xe4, 0x37, 0x40, 0xff, 0x5f, + 0xc0, 0x3f, 0xf4, 0xff, 0xd6, 0xfa, 0x5f, 0xa1, 0xff, 0x45, 0xed, 0xff, + 0xa2, 0xff, 0x00, 0xf9, 0xdf, 0xff, 0xff, 0x55, 0xeb, 0x2f, 0xa0, 0xff, + 0x0d, 0xf4, 0x5f, 0xd4, 0xff, 0xaf, 0xf4, 0x57, 0x40, 0xbd, 0x05, 0x80, + 0x1f, 0xe0, 0xff, 0x15, 0xf0, 0x8b, 0xb4, 0x7f, 0xa1, 0xec, 0x2b, 0x48, + 0x7f, 0x15, 0xfd, 0x5b, 0xd0, 0x5f, 0x00, 0xec, 0xeb, 0xaf, 0x7f, 0x45, + 0xfc, 0x17, 0x80, 0x7e, 0x45, 0xfd, 0x5f, 0xf1, 0xff, 0x05, 0xfe, 0x1b, + 0xa0, 0xfe, 0x04, 0xa0, 0x27, 0x85, 0x7e, 0x4f, 0xa4, 0x5f, 0xd0, 0x7a, + 0x25, 0xf4, 0x4f, 0x82, 0xdd, 0x07, 0xea, 0xaf, 0x52, 0xbd, 0x40, 0xa0, + 0xd7, 0x5a, 0xfd, 0xa2, 0xf4, 0x6f, 0xa1, 0xfe, 0x22, 0xf4, 0xbf, 0xd0, + 0xfe, 0x2b, 0xf5, 0x4f, 0x84, 0xbe, 0x20, 0xc2, 0x17, 0xa4, 0xfe, 0x45, + 0xe0, 0x45, 0xa8, 0x5e, 0xa1, 0xa8, 0x25, 0xc8, 0x7e, 0x02, 0xed, 0xb5, + 0x90, 0x5e, 0x20, 0xe4, 0x55, 0x4f, 0xbf, 0x20, 0xf4, 0x2b, 0x90, 0xbe, + 0x02, 0xf5, 0x57, 0x50, 0x7f, 0x15, 0xfd, 0x25, 0x40, 0x5e, 0x00, 0xa1, + 0x0b, 0x42, 0x5f, 0x15, 0xa4, 0x03, 0x02, 0x7d, 0x48, 0xe0, 0x0b, 0x05, + 0xba, 0xa8, 0xa0, 0x07, 0x04, 0xba, 0x00, 0xa0, 0x47, 0x35, 0xdd, 0x88, + 0xa0, 0x0f, 0x00, 0xdc, 0x48, 0xa0, 0x8b, 0x04, 0xbd, 0x00, 0xa0, 0x0b, + 0x15, 0x7a, 0x50, 0xa0, 0x27, 0x41, 0xbf, 0x00, 0xb0, 0x01, 0x85, 0x1c, + 0xa0, 0xd0, 0x03, 0x04, 0x1e, 0x40, 0xe0, 0x01, 0x0b, 0x1d, 0xa8, 0xa2, + 0x03, 0x05, 0x7f, 0x40, 0xe8, 0x01, 0x05, 0xbf, 0x40, 0xb0, 0x0b, 0x84, + 0x5e, 0x50, 0xe0, 0x03, 0x04, 0x1e, 0x48, 0xc2, 0x17, 0x04, 0x7d, 0x00, + 0xe4, 0x45, 0x02, 0xba, 0x50, 0x42, 0x8b, 0x2a, 0xba, 0x68, 0xa1, 0x0b, + 0x04, 0xbc, 0x00, 0xa0, 0x47, 0x02, 0x5d, 0x28, 0x40, 0x0f, 0x48, 0x58, + 0x10, 0xc0, 0x05, 0x01, 0xb4, 0x80, 0x48, 0x0b, 0x05, 0x74, 0xb0, 0xa0, + 0x13, 0xa0, 0x1f, 0xaa, 0xe4, 0x03, 0x91, 0xbe, 0xd8, 0xe0, 0x83, 0x06, + 0xba, 0x50, 0xa0, 0x8b, 0x97, 0x1e, 0x14, 0xc3, 0x2b, 0xa0, 0x5d, 0xa8, + 0x62, 0x83, 0x06, 0x5e, 0xa8, 0xe2, 0x83, 0x1a, 0x3e, 0x68, 0xe2, 0x83, + 0x00, 0x3f, 0x0a, 0x80, 0x0f, 0x40, 0x3e, 0x40, 0xa8, 0x4b, 0x04, 0x7b, + 0xa8, 0xa2, 0x0d, 0x2d, 0x7c, 0xe8, 0xc2, 0x87, 0x2a, 0x74, 0x01, 0x40, + 0x17, 0x40, 0x3f, 0xd0, 0x80, 0x03, 0x2b, 0x38, 0xd0, 0x41, 0x05, 0x2d, + 0x34, 0xb0, 0x41, 0x0b, 0x0a, 0x34, 0xb0, 0xa0, 0x43, 0x20, 0x9f, 0x5a, + 0xe4, 0x2b, 0xa2, 0x5d, 0xe8, 0xa0, 0x83, 0x27, 0x1e, 0x68, 0xe2, 0x85, + 0x0e, 0x3e, 0x08, 0xe3, 0x17, 0xa0, 0x1f, 0x7d, 0xe3, 0xd1, 0x1b, 0x1e, + 0x7d, 0xa1, 0xa3, 0x17, 0x3a, 0xbd, 0xa2, 0x8b, 0x80, 0x3a, 0x0d, 0x48, + 0x07, 0x46, 0x3f, 0xa0, 0xe8, 0x17, 0x40, 0x7f, 0xb0, 0xc2, 0x8f, 0x1a, + 0xf4, 0xb0, 0x41, 0x87, 0x2a, 0x34, 0x28, 0x00, 0xaf, 0xa0, 0x7e, 0xa8, + 0x81, 0x87, 0x2e, 0x58, 0xd0, 0xc2, 0x89, 0x2e, 0x3a, 0xe8, 0x81, 0x07, + 0x11, 0x3c, 0x70, 0x81, 0x43, 0x21, 0x1f, 0x2a, 0xe8, 0x5f, 0xf4, 0x3f, + 0xd8, 0xe0, 0x81, 0x0e, 0x3e, 0xb8, 0xe0, 0x83, 0x0e, 0x1e, 0x05, 0xe1, + 0x2b, 0xa8, 0x1f, 0xea, 0xe2, 0xa1, 0x2e, 0x5e, 0xfa, 0xa2, 0xc5, 0x37, + 0x1a, 0x75, 0xe1, 0x05, 0x01, 0x1e, 0x2d, 0xa0, 0x03, 0x46, 0xbd, 0x00, + 0xa4, 0x2f, 0x40, 0xdf, 0xb0, 0x42, 0x0f, 0x2b, 0xda, 0xd0, 0xa2, 0x0d, + 0x2b, 0x3a, 0x28, 0x84, 0x0f, 0x82, 0x3e, 0xf0, 0x41, 0x83, 0x1b, 0x34, + 0xd4, 0xa2, 0x83, 0x1a, 0x5c, 0xd8, 0x82, 0x87, 0x20, 0x34, 0xd0, 0xc2, + 0xc3, 0x42, 0xbf, 0x00, 0xf0, 0xb7, 0xe8, 0x7f, 0xd8, 0xe0, 0x83, 0x15, + 0x7a, 0xd8, 0xe0, 0x8b, 0x0d, 0x1a, 0x20, 0xe0, 0x23, 0xa0, 0x9e, 0x5c, + 0xa0, 0x93, 0x0a, 0x3a, 0x68, 0xc2, 0xa1, 0x0e, 0x5a, 0x68, 0xe1, 0x05, + 0x14, 0x3e, 0x59, 0x60, 0x05, 0x22, 0x5e, 0x40, 0xa4, 0x7f, 0xb0, 0xbf, + 0xa0, 0xa2, 0x0d, 0x0a, 0x5c, 0xa0, 0xa2, 0x0b, 0x2a, 0xbc, 0x10, 0x41, + 0x0f, 0x02, 0x3f, 0xa0, 0xa2, 0x03, 0x2d, 0x3c, 0xa9, 0xa1, 0x0b, 0x29, + 0x3c, 0xa8, 0x82, 0x0b, 0x00, 0x34, 0xa4, 0xa2, 0x43, 0x81, 0x7f, 0x25, + 0xb0, 0x17, 0xa8, 0xbf, 0x28, 0xb0, 0x87, 0x4a, 0x7f, 0x28, 0xb0, 0x8b, + 0x0a, 0xbf, 0x48, 0xe0, 0x43, 0x85, 0x5e, 0xa8, 0xd0, 0x85, 0x04, 0x5f, + 0x20, 0xe0, 0x85, 0x04, 0xb6, 0x48, 0xf0, 0x05, 0x2a, 0xbe, 0x50, 0xa0, + 0x05, 0x24, 0xda, 0x0b, 0xc8, 0xbf, 0xd0, 0xbf, 0x90, 0xe0, 0x0b, 0x04, + 0xdc, 0x90, 0xc4, 0x0f, 0x04, 0x7a, 0x90, 0x40, 0x07, 0x15, 0xfb, 0x00, + 0xc0, 0x0b, 0x09, 0xba, 0x90, 0xa4, 0x0b, 0x0a, 0x7d, 0x20, 0xa0, 0x4b, + 0x04, 0xba, 0x80, 0xc2, 0x03, 0x01, 0xff, 0x4a, 0xe0, 0x0b, 0x40, 0xbf, + 0x00, 0xbc, 0x17, 0xc2, 0x7e, 0x04, 0xf0, 0x03, 0xc0, 0x5f, 0x02, 0xe8, + 0xeb, 0xad, 0x3d, 0x22, 0xfa, 0x57, 0x40, 0xbf, 0x04, 0xf0, 0x27, 0x40, + 0xbd, 0x02, 0xf5, 0x0b, 0x02, 0xba, 0x44, 0x80, 0x07, 0x04, 0xfa, 0x1f, + 0x42, 0x2f, 0x80, 0xfd, 0x04, 0xe0, 0x4d, 0x00, 0xdf, 0x01, 0xec, 0x5f, + 0x01, 0xfd, 0x01, 0xa0, 0x57, 0x5f, 0xff, 0x04, 0xe8, 0x0d, 0x40, 0xfb, + 0x02, 0xda, 0x4f, 0x40, 0xff, 0x04, 0xd8, 0x0b, 0x2a, 0xfa, 0x01, 0xa0, + 0x83, 0x04, 0xff, 0x57, 0x60, 0x17, 0xe8, 0x7e, 0x02, 0xfc, 0x0f, 0xc0, + 0xff, 0x00, 0xf4, 0x0b, 0xc0, 0x7f, 0x04, 0xe4, 0xf7, 0xd7, 0x7f, 0x05, + 0xed, 0x2f, 0x50, 0x7f, 0x01, 0xec, 0x2b, 0x50, 0x7f, 0x05, 0xda, 0x8b, + 0x0a, 0xbe, 0x00, 0x80, 0x7f, 0xeb, 0xfd, 0xbf, 0xdb, 0x6f, 0xaf, 0xff, + 0xf7, 0xfb, 0xf7, 0xbb, 0xfe, 0xfe, 0xff, 0xff, 0xfa, 0xfe, 0xf7, 0xa9, + 0xbf, 0xff, 0xff, 0xeb, 0xfa, 0xff, 0xd7, 0xff, 0xff, 0xfb, 0x6f, 0xd7, + 0xfb, 0xf7, 0xfd, 0x5f, 0x57, 0xfb, 0xbf, 0xfd, 0x57, 0x5b, 0xff, 0xdf, + 0xfa, 0xbf, 0xf5, 0xff, 0x5a, 0xfd, 0xbf, 0xec, 0xff, 0x4b, 0xf5, 0xaf, + 0xae, 0xff, 0x35, 0xf5, 0xff, 0xff, 0x7e, 0x5d, 0xff, 0xaf, 0xfa, 0xff, + 0xaa, 0xfe, 0x7f, 0xfd, 0x7f, 0x55, 0xff, 0xd7, 0xfb, 0xfd, 0xaa, 0xd5, + 0xff, 0xff, 0xff, 0xff, 0xef, 0x7f, 0xdf, 0xff, 0xef, 0xff, 0xff, 0xfb, + 0x7f, 0xff, 0xff, 0xff, 0xfb, 0xff, 0xff, 0xef, 0xff, 0xff, 0xff, 0xf7, + 0xff, 0xff, 0xef, 0xff, 0xff, 0xff, 0xff, 0x6f, 0xff, 0xff, 0xfd, 0xff, + 0x5f, 0xff, 0x7f, 0xff, 0xbf, 0xfb, 0xff, 0xff, 0xff, 0xef, 0xf7, 0xff, + 0xff, 0xfe, 0x7f, 0x7f, 0xff, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xbf, 0xfb, + 0xff, 0xff, 0xff, 0xff, 0xfb, 0xff, 0xff, 0xff, 0xbf, 0xff, 0xdf, 0xf7, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfb, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xbf, 0xff, 0xff, 0xfe, 0xff, 0xff, 0xfb, + 0xff, 0xff, 0xff, 0xef, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xef, 0xff, 0xdf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xbf, + 0xff, 0xff, 0xbf, 0xff, 0xff, 0xff, 0xff, 0x7f, 0xff, 0xbf, 0xfe, 0xff, + 0xbf, 0xfa, 0xff, 0xff, 0xff, 0x7f, 0xff, 0xf7, 0xfe, 0xff, 0x6f, 0xfd, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xbf, 0xab, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xaf, 0xff, 0xf7, 0xff, 0xff, 0xff, 0xfd, 0xff, 0xff, 0xff, 0x8b, + 0xff, 0x97, 0xff, 0xff, 0x5f, 0xff, 0xff, 0xff, 0xff, 0x8b, 0xff, 0x1f, + 0xff, 0xff, 0x7f, 0xee, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe8, 0xff, + 0xff, 0xff, 0xbf, 0xea, 0xff, 0xd7, 0xfd, 0x3f, 0xf5, 0xff, 0x2f, 0xfe, + 0xff, 0x7d, 0xff, 0xaf, 0xfa, 0x3f, 0xf5, 0xff, 0xb7, 0xf4, 0x7f, 0xf7, + 0xff, 0xae, 0xfe, 0xb7, 0xf6, 0xff, 0xaf, 0xfa, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xbf, 0xf0, 0xff, 0x6f, 0xfb, 0xdf, 0xb6, 0xff, 0x97, 0xfe, 0xbf, + 0xfa, 0xff, 0x7f, 0xf5, 0x5f, 0xaf, 0xff, 0x85, 0xff, 0x97, 0xfe, 0xff, + 0x5f, 0xfe, 0xd7, 0xbb, 0xff, 0x43, 0xff, 0x97, 0xf6, 0xff, 0x37, 0xfe, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xdf, 0xd4, 0xff, 0x75, 0xff, 0xb7, 0xd2, + 0xff, 0x95, 0xfe, 0x2f, 0xba, 0xff, 0x57, 0xf6, 0xbf, 0xd2, 0xff, 0x0b, + 0xfa, 0x3f, 0xf1, 0xff, 0x0b, 0xf5, 0x3f, 0x4d, 0xff, 0x0a, 0xf5, 0x3f, + 0xf8, 0xff, 0x0d, 0xf5, 0xff, 0xfd, 0xff, 0xff, 0xff, 0x3f, 0xa2, 0x7f, + 0xd7, 0xf4, 0x2f, 0x40, 0xfd, 0x07, 0xf6, 0xdf, 0xe8, 0xff, 0x0f, 0xfc, + 0x5f, 0x55, 0x7f, 0x05, 0xfa, 0x17, 0xbc, 0xff, 0x4f, 0xfe, 0x95, 0xe6, + 0x7f, 0x83, 0xfe, 0x97, 0xda, 0xff, 0xa7, 0xfe, 0x5f, 0xef, 0xff, 0xbb, + 0xfd, 0x5f, 0xf1, 0xff, 0x53, 0xf6, 0x37, 0xa0, 0xff, 0x02, 0xfa, 0x3f, + 0xe8, 0xff, 0x4b, 0xff, 0xbf, 0xa4, 0xff, 0xa3, 0xfc, 0xff, 0xe1, 0xff, + 0x8b, 0xfa, 0x2f, 0xa1, 0xfe, 0x25, 0xfa, 0x7f, 0xe8, 0xff, 0x0a, 0xf4, + 0xef, 0xda, 0x7e, 0xed, 0xd6, 0xff, 0x48, 0xff, 0x25, 0xf9, 0x9f, 0x14, + 0xfe, 0x53, 0xf5, 0xef, 0xaa, 0xff, 0x0b, 0xf4, 0x2f, 0xa2, 0xfb, 0x15, + 0xf6, 0x5f, 0xb8, 0xff, 0x8d, 0xfa, 0x57, 0x55, 0xbf, 0x20, 0xfa, 0x0b, + 0x52, 0x7f, 0x4b, 0xff, 0xab, 0x6a, 0x5f, 0x55, 0xdb, 0x2f, 0xe4, 0x7f, + 0x25, 0xdd, 0x57, 0x40, 0xff, 0x12, 0xfa, 0x3f, 0xe0, 0xff, 0x4a, 0xff, + 0x7f, 0xc9, 0xfe, 0x47, 0xd9, 0xbf, 0xc0, 0xff, 0x8b, 0xfc, 0x15, 0x41, + 0x7f, 0x15, 0xd6, 0xbf, 0xa8, 0xbd, 0x85, 0xd4, 0x5f, 0x92, 0xfd, 0xaa, + 0xe0, 0x5f, 0x11, 0xfd, 0x43, 0xe8, 0xbf, 0x14, 0xfd, 0xa2, 0xd4, 0x57, + 0x55, 0xfd, 0x8b, 0xe8, 0x5f, 0xa0, 0xfe, 0x02, 0xec, 0xdf, 0x60, 0xff, + 0x0b, 0xec, 0x07, 0x20, 0x5b, 0x00, 0xf0, 0x05, 0x80, 0x5e, 0x00, 0xe8, + 0x05, 0x80, 0x1e, 0x00, 0xa8, 0x17, 0x80, 0xbf, 0x02, 0xf4, 0x0b, 0x80, + 0xbf, 0x02, 0xf0, 0x1f, 0x00, 0x7f, 0x01, 0xf4, 0xbf, 0x80, 0xff, 0x17, + 0xf4, 0xbf, 0x80, 0xff, 0x0e, 0xf4, 0x25, 0x00, 0xbe, 0x00, 0xd4, 0x07, + 0x20, 0x7f, 0x01, 0xf2, 0x07, 0x00, 0x7a, 0x00, 0xc0, 0x6f, 0x20, 0xfe, + 0x02, 0xd0, 0x3f, 0x20, 0xfd, 0x01, 0xe8, 0x37, 0x80, 0xfe, 0x03, 0xd0, + 0xdf, 0xe8, 0xff, 0x85, 0xff, 0xdf, 0xf8, 0xff, 0x83, 0xff, 0x03, 0x15, + 0x5f, 0x54, 0xd1, 0x45, 0x05, 0x55, 0x50, 0xd0, 0x05, 0x15, 0x1a, 0x0a, + 0xe9, 0x13, 0x8a, 0xbf, 0x50, 0xf5, 0x0b, 0x8a, 0xbe, 0x50, 0xf5, 0x0b, + 0xa5, 0x3e, 0x50, 0xf5, 0x7f, 0xb0, 0xff, 0x0f, 0xf9, 0x7f, 0xa0, 0xff, + 0x0f, 0xfa, 0x45, 0x04, 0x3a, 0x10, 0xe0, 0x03, 0x12, 0x3c, 0x24, 0xa1, + 0x0b, 0x2a, 0x3c, 0x02, 0x42, 0x0f, 0x22, 0xfa, 0x42, 0xd0, 0x17, 0x21, + 0xff, 0x12, 0x50, 0x2f, 0x11, 0xfe, 0x22, 0xd0, 0x5f, 0xd8, 0xff, 0x85, + 0xfe, 0x5f, 0xf8, 0xff, 0x85, 0xff, 0x05, 0x05, 0x1d, 0x90, 0xb0, 0x81, + 0x02, 0x5f, 0x10, 0xf0, 0xd7, 0x2b, 0x1a, 0x12, 0xf0, 0x13, 0x11, 0x3f, + 0x50, 0xea, 0x05, 0x94, 0x5d, 0x40, 0xf5, 0x03, 0x84, 0x5f, 0x42, 0xf5, + 0xff, 0xe8, 0xff, 0x0b, 0xfd, 0xbf, 0xd0, 0xff, 0x0b, 0xfd, 0x03, 0x00, + 0x7d, 0x00, 0xc0, 0x07, 0x00, 0x3a, 0x80, 0xc0, 0x0d, 0x1d, 0x3a, 0x00, + 0x41, 0x27, 0x80, 0xfe, 0x02, 0xe0, 0x2f, 0x00, 0xbe, 0x02, 0xd0, 0x2f, + 0x20, 0x7d, 0x01, 0xd0, 0x5f, 0xe8, 0xff, 0x8d, 0xff, 0x5f, 0xd8, 0xff, + 0x8d, 0xfd, 0x05, 0x00, 0x1d, 0x00, 0xe8, 0x01, 0x00, 0x3d, 0x00, 0xf0, + 0xe7, 0x06, 0x1c, 0x00, 0xa0, 0x2b, 0x40, 0x5d, 0x00, 0xf4, 0x05, 0x40, + 0x7f, 0x00, 0xe8, 0x03, 0x00, 0x5d, 0x00, 0xe8, 0x7f, 0x50, 0xff, 0x06, + 0xfa, 0xef, 0xe0, 0xff, 0x06, 0xfe, 0x93, 0x04, 0x7d, 0x4a, 0xd0, 0x57, + 0x12, 0xbd, 0x24, 0x80, 0x9b, 0x2a, 0x3a, 0x12, 0x0a, 0x0f, 0x15, 0xbe, + 0x52, 0xa1, 0x2b, 0x16, 0xba, 0x52, 0xa1, 0x2f, 0x15, 0xfe, 0x52, 0xd1, + 0x4f, 0xd8, 0x7f, 0x83, 0xff, 0x37, 0xb8, 0x7d, 0x83, 0xfb, 0x05, 0x04, + 0x1d, 0x42, 0xd0, 0x01, 0x00, 0x1d, 0x04, 0xe8, 0x01, 0x00, 0x9d, 0x00, + 0xc1, 0x03, 0x12, 0x76, 0x00, 0xd1, 0x27, 0x11, 0x5d, 0x21, 0xb1, 0x23, + 0x12, 0x5b, 0x90, 0xe0, 0xb7, 0x60, 0xff, 0x0d, 0xd4, 0xaf, 0x50, 0xdf, + 0x0a, 0xdc, 0x43, 0x01, 0xbd, 0x10, 0xd0, 0x27, 0x05, 0x7c, 0x41, 0xd0, + 0x0b, 0x00, 0x3e, 0x14, 0x0a, 0x2d, 0x09, 0xbd, 0xb2, 0xd0, 0x0b, 0x0a, + 0x7c, 0x90, 0xc0, 0x0d, 0x09, 0xbc, 0x42, 0xa0, 0x07, 0x08, 0x5f, 0x80, + 0xf2, 0x23, 0x40, 0x7f, 0x80, 0xf2, 0x05, 0x00, 0x5d, 0x00, 0xe8, 0x01, + 0x00, 0x1f, 0x00, 0xd0, 0x47, 0xd0, 0x1b, 0x00, 0xc0, 0x07, 0x00, 0x5e, + 0x00, 0xe0, 0x05, 0x00, 0x5f, 0x00, 0xf0, 0x07, 0x00, 0x3f, 0x00, 0xf0, + 0x2b, 0xa0, 0x7d, 0x01, 0xf4, 0x0f, 0x10, 0x7f, 0x05, 0xd4, 0x05, 0x00, + 0x5f, 0x00, 0xd2, 0x07, 0x80, 0x7e, 0x20, 0xf0, 0x2f, 0x82, 0x3e, 0x00, + 0x00, 0x03, 0x00, 0x7a, 0x00, 0xa0, 0x05, 0x00, 0x7a, 0x00, 0xc0, 0x03, + 0x00, 0x7a, 0x00, 0xa2, 0x07, 0x21, 0x3f, 0x08, 0xf2, 0x45, 0x42, 0x5f, + 0x20, 0xf2, 0x57, 0xf2, 0x7d, 0x25, 0xf5, 0x55, 0xd2, 0x5e, 0x09, 0xdd, + 0x6f, 0xd0, 0xbf, 0xaa, 0xd2, 0x4b, 0x52, 0x5f, 0x44, 0xfa, 0x47, 0xa5, + 0x5f, 0x2a, 0xf5, 0xa5, 0xa4, 0x5f, 0x52, 0xf8, 0x57, 0x88, 0xfe, 0xa2, + 0xe8, 0x17, 0x50, 0xff, 0x8a, 0xf4, 0x2b, 0x48, 0xdf, 0x82, 0xfc, 0x2f, + 0x40, 0xff, 0x42, 0xf6, 0x5f, 0xd1, 0xff, 0x80, 0xa0, 0x87, 0x00, 0x7d, + 0x11, 0xd0, 0x25, 0x00, 0x7d, 0x00, 0xd0, 0x0b, 0x08, 0x7d, 0x04, 0xd2, + 0x17, 0xe5, 0xbf, 0x08, 0xfe, 0xa7, 0x4a, 0x77, 0x42, 0xfa, 0x2f, 0xe5, + 0xff, 0x52, 0xfe, 0x2b, 0xf5, 0xbf, 0x52, 0xfe, 0x7f, 0xc0, 0xbf, 0x74, + 0xea, 0x53, 0xd4, 0x3f, 0x94, 0xfa, 0x97, 0xaa, 0x3f, 0xad, 0xfa, 0xa7, + 0xa2, 0x3f, 0x51, 0xf9, 0xef, 0x5a, 0xff, 0xf7, 0xf5, 0x7d, 0xf5, 0xff, + 0x7d, 0xf7, 0xdf, 0xfb, 0xff, 0xbf, 0xff, 0xff, 0xdd, 0xff, 0xbf, 0xff, + 0xbf, 0x41, 0xff, 0xaf, 0xbb, 0xef, 0xb7, 0xfe, 0xdb, 0xee, 0x6f, 0xeb, + 0xfe, 0xd7, 0xfe, 0xdd, 0xed, 0xfe, 0xaf, 0xee, 0x7f, 0xff, 0x7f, 0xbb, + 0xff, 0xaf, 0xbf, 0x7f, 0x57, 0xfb, 0xff, 0xbe, 0xff, 0xea, 0xf7, 0x5f, + 0xef, 0xff, 0xd5, 0xf7, 0xbf, 0xfd, 0xff, 0xfa, 0xfd, 0x7f, 0xfd, 0xff, + 0xdf, 0xff, 0xf7, 0xfb, 0xff, 0x7a, 0xef, 0xff, 0xfe, 0xff, 0xfa, 0xff, + 0xf7, 0xef, 0xff, 0xff, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xef, 0xfb, + 0xff, 0xbf, 0xff, 0xff, 0xfd, 0xff, 0xff, 0xff, 0xff, 0xd6, 0xff, 0xef, + 0xff, 0xff, 0xef, 0xff, 0xfb, 0xfd, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xdf, + 0xbf, 0xff, 0xdf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xbf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xed, 0xff, 0xff, 0xff, 0xff, + 0xd7, 0xff, 0xfb, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfb, 0xff, 0xff, + 0xbf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf7, 0x7f, 0x6b, 0xff, + 0xff, 0xff, 0xff, 0x7f, 0xf5, 0xbf, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xfa, + 0xff, 0xeb, 0xff, 0xff, 0xaf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xdf, 0xfa, 0xff, 0xd5, 0xfe, 0x5f, 0xff, 0xff, 0x5f, 0xfb, 0xbf, + 0xfd, 0xff, 0xbb, 0xf5, 0xff, 0xff, 0xff, 0xff, 0xaa, 0xdf, 0xff, 0xff, + 0xff, 0xff, 0xbf, 0xd6, 0xff, 0x5d, 0xff, 0xff, 0xf7, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xbf, 0xd6, 0xff, 0x57, 0xff, 0xef, 0xfd, + 0xff, 0xff, 0xfe, 0xef, 0xaa, 0xbf, 0x4a, 0xaa, 0xff, 0xff, 0xff, 0x5f, + 0xa0, 0x17, 0xfa, 0xff, 0xff, 0xff, 0xdf, 0xf0, 0xff, 0xc2, 0xff, 0xff, + 0x8a, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x93, 0xf0, 0xff, + 0x05, 0xfb, 0x37, 0xf6, 0xff, 0x57, 0xfa, 0x37, 0xe2, 0x7f, 0x00, 0xe0, + 0xbf, 0xaa, 0xff, 0xff, 0xc0, 0x2f, 0xda, 0xff, 0xab, 0xfa, 0xbf, 0x48, + 0xff, 0x93, 0xfa, 0xff, 0x47, 0xff, 0xff, 0xff, 0xff, 0xf5, 0xff, 0x55, + 0xf5, 0xaf, 0xa8, 0xff, 0x85, 0xfc, 0x1f, 0xfa, 0xff, 0x2f, 0xf4, 0x9f, + 0x54, 0xbf, 0x42, 0x90, 0xd7, 0xf7, 0xff, 0x57, 0xe0, 0x2b, 0xed, 0xff, + 0xfa, 0xdf, 0xaf, 0xd0, 0x7f, 0x91, 0xff, 0x5f, 0xa1, 0xfb, 0x6a, 0xff, + 0xbf, 0xfe, 0x7f, 0xff, 0xff, 0x03, 0xe8, 0x7f, 0x05, 0xfe, 0x17, 0xed, + 0xff, 0x55, 0xfe, 0x57, 0xa0, 0xbb, 0x00, 0xc0, 0x17, 0xa4, 0xfa, 0x5a, + 0x54, 0x57, 0xd0, 0x7a, 0x13, 0xe8, 0x37, 0x42, 0xfd, 0x06, 0xda, 0xbf, + 0x91, 0xbe, 0xbf, 0xfb, 0xff, 0xd0, 0x7f, 0x01, 0xf4, 0x5f, 0x40, 0xff, + 0x52, 0xea, 0x6f, 0xb0, 0xff, 0x0f, 0xf5, 0x2f, 0x40, 0xbe, 0x02, 0xd2, + 0x93, 0xa2, 0x7f, 0x03, 0xd0, 0x1b, 0x78, 0xbf, 0x41, 0xf2, 0x1b, 0xa0, + 0x5f, 0x43, 0xeb, 0xab, 0xa0, 0xfa, 0xd2, 0xfa, 0x5f, 0xe8, 0x7f, 0xb1, + 0xf4, 0x0b, 0xa0, 0xbf, 0x42, 0xfa, 0x37, 0xd8, 0x7f, 0x05, 0xfd, 0x3b, + 0x10, 0xbf, 0x00, 0xd0, 0x05, 0x06, 0xf8, 0x94, 0xe8, 0x43, 0x05, 0x78, + 0xb0, 0x84, 0x07, 0x15, 0xf8, 0xa8, 0xa0, 0x4f, 0x14, 0x3a, 0x00, 0xdc, + 0xff, 0xa0, 0xff, 0x06, 0xba, 0x5f, 0x64, 0xff, 0x02, 0xf4, 0x2f, 0xa0, + 0xff, 0x03, 0xfa, 0x97, 0x44, 0x78, 0x51, 0xa1, 0x41, 0x45, 0xbd, 0x02, + 0xe4, 0x01, 0x05, 0x3d, 0x92, 0xd0, 0x25, 0x15, 0x3d, 0x50, 0xd4, 0x0b, + 0x96, 0x38, 0x49, 0xf4, 0x5f, 0xe8, 0xbf, 0x02, 0xea, 0x0b, 0xa0, 0xbf, + 0x02, 0xfd, 0x2b, 0xd2, 0xbb, 0x80, 0xfa, 0x1f, 0x04, 0x5e, 0x40, 0xe8, + 0x15, 0x0a, 0x5c, 0x00, 0xa8, 0x4b, 0x92, 0xdc, 0x40, 0xc2, 0x87, 0x04, + 0xdc, 0x40, 0xa1, 0xaf, 0x28, 0xba, 0x00, 0xd4, 0xbf, 0x60, 0x7f, 0x01, + 0xf1, 0xb7, 0x48, 0xdd, 0x11, 0xa2, 0x57, 0xa0, 0x7e, 0x0b, 0xd4, 0x25, + 0x11, 0x59, 0x22, 0xd1, 0x05, 0x03, 0x3e, 0x00, 0xe9, 0x01, 0x11, 0x3e, + 0x78, 0xd1, 0x05, 0x06, 0x3d, 0x68, 0xd0, 0x05, 0x0e, 0x58, 0x20, 0xe0, + 0xab, 0xaa, 0x5f, 0x10, 0xd8, 0x05, 0x04, 0x7f, 0x80, 0xf0, 0x05, 0x00, + 0x5f, 0x40, 0xf0, 0x07, 0x00, 0x3c, 0x00, 0xd0, 0x83, 0x10, 0xba, 0x68, + 0xe4, 0x07, 0x05, 0x7b, 0x40, 0xa0, 0x85, 0x2a, 0x5c, 0x50, 0xa1, 0x0f, + 0x28, 0xfa, 0x04, 0x42, 0x57, 0x51, 0x5d, 0x40, 0xe0, 0x07, 0x00, 0x3a, + 0x20, 0xd0, 0x07, 0x05, 0x7a, 0x00, 0xa0, 0x25, 0x04, 0x5d, 0x00, 0xe8, + 0x13, 0x8a, 0x1f, 0x28, 0xb0, 0x13, 0x41, 0x1b, 0x70, 0xd0, 0x43, 0x05, + 0x3d, 0x54, 0xd0, 0x03, 0x07, 0x3a, 0x40, 0xe0, 0x9b, 0x94, 0x3d, 0x10, + 0xb0, 0x05, 0x02, 0x5f, 0x10, 0xf0, 0x05, 0x00, 0x5f, 0x50, 0xf8, 0x07, + 0x01, 0x5d, 0x20, 0xb2, 0x07, 0x02, 0x3a, 0xa2, 0xe4, 0x2f, 0xa4, 0x7e, + 0x54, 0xa1, 0x07, 0x16, 0x7e, 0x68, 0xa1, 0x0f, 0x2a, 0xba, 0x00, 0x82, + 0x05, 0x00, 0x5c, 0x48, 0xc1, 0x43, 0x15, 0x3a, 0x48, 0x81, 0x83, 0x16, + 0x3a, 0x24, 0xa1, 0x43, 0x14, 0x3a, 0x94, 0xc0, 0x2b, 0xa1, 0x1f, 0x59, + 0xe8, 0x0b, 0x41, 0x3f, 0x50, 0xf0, 0x41, 0x13, 0x1b, 0x54, 0xf0, 0x85, + 0x2a, 0x5c, 0xa0, 0xe2, 0x07, 0x00, 0x5d, 0x74, 0xf1, 0x41, 0x05, 0x1d, + 0x74, 0xf0, 0x41, 0x05, 0x1d, 0xb4, 0xd0, 0x85, 0x02, 0x1f, 0xa4, 0xf0, + 0x1f, 0x44, 0x7f, 0x80, 0xa4, 0x3f, 0xd0, 0x5f, 0x68, 0xa1, 0x07, 0x0d, + 0x7d, 0x50, 0xa1, 0x0b, 0x16, 0xba, 0x08, 0x80, 0x55, 0xd5, 0x3e, 0x94, + 0xa0, 0x87, 0x1a, 0x7e, 0x94, 0xc1, 0x47, 0x1b, 0x7d, 0x50, 0xc1, 0x47, + 0x16, 0x7d, 0x58, 0xc0, 0x17, 0xe0, 0x3f, 0x00, 0xf0, 0x2f, 0xe8, 0x7f, + 0x34, 0xf0, 0x45, 0x03, 0x5d, 0x54, 0xf0, 0x87, 0x0a, 0xbe, 0x08, 0xe1, + 0xdf, 0x54, 0x1f, 0xb4, 0xd0, 0x41, 0x0b, 0x1d, 0xd4, 0xf0, 0x41, 0x05, + 0x1d, 0x5c, 0xf1, 0x05, 0x13, 0x1d, 0xd4, 0xf0, 0x7f, 0x51, 0xff, 0x22, + 0xa4, 0xdf, 0x90, 0x3e, 0x50, 0xd1, 0x07, 0x15, 0x7e, 0x50, 0xd1, 0x0b, + 0x2a, 0x74, 0x10, 0x40, 0xb7, 0xd2, 0x7f, 0x50, 0xd1, 0x07, 0x15, 0x7a, + 0x68, 0xa0, 0x07, 0x15, 0x7c, 0xa0, 0xa0, 0x45, 0x05, 0x7d, 0x28, 0xa2, + 0x1f, 0xe8, 0x3f, 0x00, 0xf0, 0x3f, 0xe0, 0x1f, 0x14, 0xf0, 0x41, 0x01, + 0x1f, 0x48, 0xf0, 0x85, 0x02, 0xbe, 0x40, 0xa4, 0xbf, 0xf0, 0x5d, 0x14, + 0xd0, 0x45, 0x01, 0x5f, 0x20, 0xd0, 0x45, 0x05, 0x5f, 0x54, 0xb0, 0x03, + 0x15, 0x1e, 0x48, 0xd0, 0xff, 0x40, 0xff, 0xaf, 0xa4, 0xef, 0x88, 0xbe, + 0x40, 0xa1, 0x07, 0x14, 0x7d, 0x20, 0xd0, 0x0b, 0x14, 0xba, 0x90, 0xc0, + 0xff, 0xa0, 0x5f, 0x50, 0xe1, 0x05, 0x0a, 0x5c, 0x54, 0xe2, 0x05, 0x00, + 0x5d, 0x20, 0xc0, 0x45, 0x05, 0x75, 0x20, 0xe1, 0x5f, 0x50, 0x7f, 0x95, + 0xb0, 0xbf, 0x80, 0x1e, 0x00, 0xfc, 0x01, 0xc0, 0x1f, 0x08, 0xfa, 0x09, + 0x80, 0x7f, 0x01, 0x60, 0x5f, 0xe8, 0x7f, 0x00, 0xb8, 0x07, 0x40, 0x7f, + 0x00, 0xf8, 0x07, 0xa2, 0x7e, 0x00, 0xfa, 0x01, 0x04, 0x3c, 0x01, 0xf8, + 0xbf, 0x00, 0xfd, 0x17, 0xc0, 0xff, 0x00, 0x3e, 0x10, 0xea, 0x01, 0xa2, + 0x1e, 0x00, 0xec, 0x03, 0x40, 0xfd, 0x04, 0xa0, 0xff, 0xf5, 0xbf, 0x02, + 0xe4, 0x2b, 0x80, 0xbe, 0x02, 0xa2, 0x2b, 0x00, 0x5d, 0x05, 0xe0, 0x03, + 0x02, 0xf9, 0x08, 0xd2, 0xbf, 0x40, 0xff, 0x9f, 0xe0, 0x5f, 0x40, 0x1f, + 0x00, 0xfa, 0x01, 0xa0, 0x1f, 0x00, 0xf6, 0x83, 0x80, 0xbe, 0x02, 0xa0, + 0xbf, 0xe8, 0xbf, 0x00, 0xf2, 0x0b, 0xa0, 0xbe, 0x00, 0xf8, 0x05, 0xa0, + 0x7f, 0x00, 0xfa, 0x01, 0x05, 0x3c, 0x00, 0xf8, 0xff, 0x10, 0xfd, 0x2f, + 0xa8, 0x7f, 0x11, 0xbd, 0xef, 0xfe, 0xdf, 0xdb, 0xff, 0xed, 0xfb, 0x7d, + 0xfd, 0xff, 0xf6, 0xa5, 0xff, 0xff, 0x7f, 0xdf, 0xfd, 0xf7, 0xdf, 0x7f, + 0xdb, 0xf7, 0xff, 0x6d, 0xff, 0xdf, 0xf7, 0xfd, 0xf5, 0xff, 0xdf, 0xef, + 0xbf, 0x8a, 0xff, 0x97, 0xe2, 0x7f, 0x49, 0xbf, 0xaa, 0xf7, 0x6b, 0xed, + 0x5d, 0xb7, 0xfe, 0xaf, 0x56, 0xff, 0x57, 0xd2, 0xff, 0xfd, 0xff, 0xd3, + 0xfe, 0x3f, 0xe9, 0xff, 0x5b, 0xfd, 0xaf, 0xf6, 0xbf, 0x65, 0xfd, 0x97, + 0x2e, 0xfd, 0xaa, 0xfa, 0xff, 0xf5, 0xfe, 0x7f, 0xdd, 0xff, 0xb6, 0xff, + 0xff, 0xfe, 0xff, 0xfb, 0xff, 0xed, 0xff, 0xff, 0xfd, 0xff, 0xff, 0xad, + 0xff, 0xef, 0xff, 0xbf, 0xef, 0xff, 0xff, 0xfe, 0xff, 0xff, 0xff, 0xfd, + 0xff, 0xdf, 0xff, 0xff, 0xfb, 0xff, 0xff, 0xff, 0xff, 0x5e, 0xff, 0xdf, + 0xef, 0xff, 0xf7, 0xff, 0xfb, 0xff, 0xdf, 0xff, 0xff, 0xff, 0xfe, 0xb7, + 0xff, 0xff, 0xbd, 0xff, 0xff, 0xff, 0xff, 0xfd, 0xff, 0xdf, 0xff, 0x7f, + 0xef, 0xff, 0xff, 0xbf, 0xff, 0xff, 0xff, 0xfb, 0xff, 0xff, 0xef, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xfd, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfd, 0xff, 0xff, + 0xff, 0xff, 0xaa, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xd6, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xef, 0xff, + 0x7f, 0xef, 0xff, 0xff, 0xff, 0x57, 0xbf, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xf7, 0xff, 0xff, 0xff, 0xff, 0xff, 0xb7, + 0x6d, 0x7f, 0xfb, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0x5f, 0xfd, 0xdf, 0xda, 0xfe, 0xef, 0xff, 0x6d, 0x49, 0xfd, + 0xff, 0xff, 0xdf, 0xfd, 0xff, 0xff, 0xff, 0xff, 0xbf, 0xfd, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xba, 0x82, 0x5f, 0xaf, 0xff, 0xbf, 0xfd, 0xff, 0xff, + 0xff, 0xdf, 0xff, 0xdf, 0xff, 0xff, 0xcb, 0xff, 0xaf, 0xa2, 0xff, 0xea, + 0xff, 0x07, 0x00, 0xff, 0xff, 0xfd, 0xef, 0xae, 0xfe, 0xff, 0xff, 0xff, + 0x57, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xbf, 0x57, 0x21, 0x77, 0x6b, 0xfb, + 0xee, 0xee, 0xff, 0xfb, 0xff, 0xf7, 0xfe, 0xb7, 0xfa, 0xff, 0x8f, 0xfe, + 0x3f, 0x54, 0xff, 0xd7, 0xff, 0x0b, 0x0a, 0xfa, 0x7f, 0xff, 0xbb, 0xb5, + 0xfb, 0xef, 0xff, 0xff, 0x5f, 0xf5, 0xdf, 0xff, 0xaf, 0x56, 0xff, 0x52, + 0x81, 0x3f, 0xd5, 0x7f, 0xb7, 0xea, 0xaf, 0x5e, 0xff, 0x5b, 0xff, 0x5b, + 0xff, 0xff, 0x42, 0xf7, 0x2f, 0x81, 0x7f, 0xd1, 0xff, 0x0b, 0x80, 0xff, + 0x5f, 0xfb, 0x2b, 0x55, 0xfd, 0x7f, 0xed, 0xff, 0x4b, 0xf4, 0xeb, 0xfe, + 0x5f, 0xcd, 0x3e, 0x00, 0x80, 0x2f, 0x84, 0xbe, 0x55, 0xb0, 0xb7, 0xd2, + 0xfa, 0x87, 0xd4, 0x07, 0xfa, 0xbf, 0x0f, 0xfa, 0x3f, 0xa2, 0xfe, 0xa6, + 0xed, 0x05, 0x09, 0xfa, 0xbf, 0xd8, 0x07, 0x00, 0xf8, 0xab, 0xfe, 0xf7, + 0x17, 0xf8, 0xbf, 0xff, 0x97, 0xa6, 0x9e, 0x42, 0xa1, 0x17, 0x45, 0xbf, + 0x0a, 0xd2, 0x9b, 0xaa, 0xfe, 0x0a, 0xfe, 0x05, 0xfa, 0xff, 0x80, 0xab, + 0x27, 0xd0, 0x7f, 0xc3, 0xee, 0x87, 0x00, 0xfd, 0x2f, 0xfa, 0x05, 0x00, + 0xfa, 0xaa, 0xeb, 0xbd, 0x05, 0xfc, 0x8b, 0xfe, 0x0b, 0x4b, 0x7f, 0x20, + 0xa8, 0x17, 0x81, 0x3a, 0x00, 0xa0, 0x07, 0x00, 0xb9, 0x05, 0xc1, 0x97, + 0xf4, 0x3f, 0x05, 0xd0, 0x2f, 0x02, 0xfd, 0x41, 0xb5, 0x0b, 0x04, 0xfd, + 0x3f, 0xfa, 0x6f, 0x51, 0xfd, 0x05, 0xf4, 0xd3, 0x17, 0xf5, 0x87, 0xfe, + 0x07, 0x82, 0x1f, 0x90, 0xe4, 0x15, 0x94, 0x1e, 0x80, 0xc0, 0x0b, 0x00, + 0x7c, 0xa5, 0xf4, 0x0b, 0xfe, 0x9f, 0x00, 0xd0, 0x2b, 0xd2, 0x5f, 0xa4, + 0xd2, 0x05, 0x00, 0xfd, 0x17, 0xfa, 0x37, 0x51, 0xbd, 0x02, 0xb0, 0xeb, + 0x02, 0xfd, 0x13, 0xff, 0x15, 0x49, 0x7d, 0x40, 0xa8, 0x27, 0x22, 0x3a, + 0x00, 0xa0, 0x0b, 0x00, 0x5a, 0x09, 0x48, 0xb7, 0xd0, 0xbf, 0x08, 0x41, + 0x17, 0x01, 0xf9, 0x82, 0x94, 0x0b, 0x00, 0xf5, 0xbf, 0xf4, 0xaf, 0xa0, + 0xf6, 0x01, 0xd4, 0x93, 0x0d, 0xfa, 0x87, 0xf6, 0x07, 0x44, 0x5f, 0x59, + 0xa0, 0x01, 0x00, 0xda, 0x12, 0xfa, 0x85, 0x16, 0x3b, 0x00, 0x42, 0x17, + 0xf4, 0x9f, 0x80, 0xd0, 0x03, 0x00, 0xbc, 0x00, 0xc0, 0x01, 0x02, 0xf8, + 0x2f, 0xfa, 0xb5, 0x90, 0x3a, 0x88, 0xc0, 0xc9, 0x06, 0xff, 0x45, 0xff, + 0x05, 0x82, 0x7f, 0x50, 0xc8, 0x05, 0x00, 0x7a, 0x05, 0xa8, 0x0b, 0x14, + 0x5c, 0x00, 0x80, 0x0f, 0xd0, 0x3f, 0x08, 0x80, 0x13, 0x41, 0xf2, 0x00, + 0x80, 0x07, 0x20, 0xfa, 0x2f, 0xfa, 0x2f, 0x41, 0xd8, 0x02, 0xa1, 0x47, + 0x13, 0xfa, 0x87, 0xfd, 0x57, 0xd0, 0x3f, 0x59, 0x60, 0x27, 0x95, 0xfd, + 0x85, 0xff, 0x87, 0x16, 0x5f, 0x92, 0xc2, 0x0b, 0xe8, 0x5f, 0x84, 0xd0, + 0x01, 0x00, 0x3a, 0x28, 0xfa, 0x81, 0x04, 0xf9, 0x37, 0xfa, 0x01, 0x10, + 0x3a, 0xa0, 0xc4, 0x05, 0x85, 0xff, 0xe1, 0xfe, 0x9f, 0xa0, 0xde, 0xa8, + 0x80, 0x15, 0x82, 0x7e, 0x17, 0xfa, 0x0b, 0x0d, 0x7a, 0x01, 0x91, 0x57, + 0xf0, 0x3f, 0x89, 0x82, 0x2b, 0x82, 0xb0, 0x48, 0xa4, 0x0b, 0x50, 0xfc, + 0x9f, 0xec, 0x95, 0x80, 0x58, 0x44, 0x41, 0x8b, 0x02, 0xfd, 0x06, 0xff, + 0x57, 0xa0, 0x7f, 0x54, 0xa0, 0x17, 0x91, 0xfe, 0x83, 0xff, 0x8b, 0x16, + 0xbd, 0x84, 0xc8, 0x15, 0xb2, 0x1f, 0x04, 0xd0, 0x03, 0x20, 0xba, 0x20, + 0xfa, 0x03, 0x04, 0xf6, 0x2f, 0xf4, 0x01, 0x90, 0x5c, 0xa2, 0x4a, 0x4f, + 0x45, 0xff, 0xe3, 0xf5, 0xbf, 0xa0, 0x5f, 0xb0, 0x88, 0x2f, 0x44, 0xf7, + 0x25, 0xfd, 0x87, 0x14, 0x7a, 0x0b, 0x81, 0x07, 0xe8, 0xbf, 0x80, 0x80, + 0x2f, 0x83, 0x3d, 0x14, 0xf6, 0x1d, 0x00, 0xfd, 0x37, 0xfc, 0x7f, 0xa1, + 0x36, 0x44, 0x81, 0xaf, 0xc0, 0x7e, 0x01, 0xea, 0x2f, 0xa8, 0x7f, 0x9a, + 0xc8, 0x13, 0xa2, 0xff, 0x86, 0xff, 0x05, 0x16, 0xff, 0x81, 0xe0, 0x05, + 0xfa, 0x3f, 0x00, 0xe0, 0x25, 0x50, 0x3f, 0x8b, 0xfa, 0x07, 0x02, 0xfd, + 0x1f, 0xf6, 0x5b, 0xd1, 0x1f, 0xa2, 0xc8, 0xb7, 0x64, 0xff, 0x61, 0xf4, + 0xdf, 0xc0, 0x5a, 0x48, 0x68, 0x0f, 0x89, 0xfe, 0x65, 0xff, 0x0b, 0x0d, + 0xf8, 0x82, 0xa0, 0x07, 0xac, 0xbd, 0x0c, 0x91, 0x17, 0x82, 0xfd, 0x15, + 0xfd, 0x0b, 0x11, 0xfe, 0x2f, 0xfa, 0xbf, 0x60, 0x5d, 0x40, 0x43, 0x6f, + 0xd0, 0x7f, 0x29, 0xa1, 0x2f, 0x00, 0x7d, 0x4a, 0xee, 0x17, 0x89, 0x7f, + 0xa3, 0xff, 0x8b, 0x0a, 0xbf, 0x22, 0xb0, 0x85, 0xea, 0x5f, 0x82, 0xd0, + 0x07, 0xd1, 0xbf, 0x85, 0xfe, 0x4f, 0x05, 0xf7, 0x2b, 0xfa, 0xdf, 0x70, + 0x1f, 0x64, 0x41, 0x3f, 0xe8, 0x5f, 0x41, 0xb0, 0xb7, 0x40, 0x5d, 0x20, + 0xf0, 0x2f, 0x44, 0xfd, 0xa5, 0xff, 0x0d, 0x12, 0x7a, 0x41, 0xc1, 0x07, + 0x50, 0x7a, 0x0d, 0xc1, 0x2b, 0x82, 0x7e, 0x17, 0xfd, 0x0b, 0x10, 0xfd, + 0x17, 0xfc, 0x7f, 0xd1, 0x5f, 0x40, 0xc1, 0xdf, 0xa0, 0xbf, 0x28, 0xc1, + 0x17, 0x0c, 0x74, 0x11, 0xfd, 0x2b, 0x42, 0xbf, 0xe0, 0xff, 0x07, 0x00, + 0x3d, 0x28, 0xf8, 0x13, 0x00, 0xba, 0x85, 0xfe, 0x05, 0xd1, 0xff, 0xc5, + 0xff, 0x7f, 0x85, 0xfe, 0x15, 0xfe, 0x17, 0xd0, 0x3f, 0x28, 0x70, 0x17, + 0xfc, 0x5f, 0x00, 0xa0, 0x0b, 0x09, 0xf8, 0x01, 0xfd, 0x17, 0x80, 0xdf, + 0xa4, 0xff, 0x05, 0x09, 0x5d, 0x02, 0xd0, 0x0d, 0x88, 0xf0, 0x07, 0xf5, + 0x47, 0x43, 0xff, 0xa5, 0xfe, 0x5f, 0x01, 0xff, 0x0b, 0xea, 0x7f, 0xe1, + 0x7f, 0x50, 0xd1, 0x2b, 0xe8, 0x3f, 0x01, 0xc0, 0xa3, 0x56, 0xbd, 0xa4, + 0xfe, 0x1b, 0xd1, 0x3e, 0xf0, 0xff, 0x87, 0x4a, 0x1d, 0x79, 0xfa, 0x47, + 0x45, 0xfa, 0x8b, 0xff, 0x41, 0xd1, 0xbf, 0xd0, 0xff, 0x77, 0xa1, 0xfd, + 0xc0, 0xff, 0x2f, 0xf8, 0xbf, 0x15, 0xdc, 0x0b, 0xff, 0x1f, 0x48, 0x45, + 0x05, 0x5b, 0xf4, 0x0b, 0xfd, 0x2f, 0x84, 0xdf, 0xea, 0xff, 0x1b, 0x2d, + 0x5e, 0x54, 0xed, 0xa5, 0x0a, 0xfc, 0x8b, 0xfa, 0xab, 0xab, 0xff, 0xaa, + 0xff, 0xbf, 0x41, 0x7f, 0x0b, 0xfd, 0x5f, 0xa0, 0x7f, 0x15, 0xf5, 0x47, + 0xf5, 0x5f, 0x00, 0x89, 0xe3, 0x5f, 0xfb, 0xe2, 0xff, 0x17, 0xe0, 0x7f, + 0xf8, 0xff, 0x8f, 0x97, 0x1f, 0x5d, 0xf6, 0xa7, 0xa5, 0xfa, 0x8b, 0xfe, + 0xe1, 0xe9, 0x7f, 0xf2, 0xff, 0xff, 0xe0, 0xff, 0xc1, 0xff, 0x6f, 0xfa, + 0xff, 0x0d, 0xfd, 0x01, 0xff, 0x3f, 0xaa, 0xc1, 0x5f, 0xfb, 0xfe, 0x5f, + 0xff, 0xbf, 0xbe, 0x7e, 0xef, 0xff, 0xef, 0xfd, 0xfe, 0xfe, 0xfd, 0xff, + 0xbf, 0xfe, 0xaf, 0xff, 0x5f, 0xdf, 0xff, 0xdd, 0xff, 0xff, 0x5f, 0x7f, + 0xb5, 0xff, 0xdf, 0xea, 0xff, 0xf7, 0xfe, 0xf7, 0xff, 0xdf, 0xd5, 0xfe, + 0xf7, 0xbf, 0xff, 0xfb, 0xff, 0x2b, 0xeb, 0xbf, 0xfb, 0xff, 0x7b, 0xbf, + 0x5f, 0xef, 0xff, 0xeb, 0xd6, 0xff, 0xab, 0xff, 0xf7, 0xf7, 0xff, 0xff, + 0xff, 0xff, 0xea, 0xff, 0xf5, 0xff, 0xff, 0xfe, 0x7f, 0xbf, 0xff, 0x5b, + 0xff, 0xff, 0xfe, 0xd7, 0xff, 0xff, 0xff, 0xef, 0xff, 0xff, 0xfd, 0xff, + 0xff, 0xff, 0xef, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xbf, 0xf7, 0xff, 0xff, 0xff, 0xff, 0xbb, 0xff, 0xff, 0xff, + 0xff, 0xef, 0xff, 0xf7, 0xff, 0xff, 0xdb, 0xff }; diff --git a/hacks/images/matrix2.xpm b/hacks/images/matrix2.xpm new file mode 100644 index 00000000..3b1e7746 --- /dev/null +++ b/hacks/images/matrix2.xpm @@ -0,0 +1,393 @@ +/* XPM */ +static char * matrix2_xpm[] = { +"320 377 13 1", +" c None", +". c #000000", +"+ c #081E08", +"@ c #0B2A0B", +"# c #165016", +"$ c #1B641B", +"% c #217A21", +"& c #279027", +"* c #2BA02B", +"= c #5AD25A", +"- c #81DD81", +"; c #E0F7E0", +"> c #A7E7A7", +"...........................++++++................+..+............+++@@###@@+++.......+++@###@++............+.++......................................+.+.+.............+@#####@+........+@##$##@+...............+++++.................................................................................................++@@#@@+..", +"..........................++@@#@@++..........+++++++++++.........+@##$$$%$$#@++......++#$$%$$#+++.........++@+@+++..................................++++++............++#$%&%$#@+......+@#$%%%$#++............+++@@@+++...............................................................................................+@#$$$#@+.", +"........................+.@@$$%$$@@+.......++@@#@#@#@#@@++.....+.+#&**====&%$@+.....++#$&=-=&$#@+.......++@@##$#@+................................++@###@@+..........++#$&;;=*&#++....++#&*=;;&$#++...........+@#$$$#@+.............................................................................................+++#%===$#@.", +"........................++@$%*&*%$@++.....++@#$$%$$$%$##@++....++@$*====-=**%#+....++#$&*->-*&%#@++....++@#$%%%$#@++...........++@+++++..........++@#$%%$#@+........++@$&*;;==*#++....++#&==;;*&$@+.........++@#$%&&$#@++..........+.+++.............................................................................+#$&---&$@.", +"........................+@$*=;;;=*$@+.....++$%&=-***-=&%$++....++#%=->>>;;==*#@...++#$&->;;;-=*%$++....++#%=----%#@+.........++@@###@@++.........+@$%=--*&#++.......+@#%&=;;=**#++....++#**=;;**%#@+.......++@#%&;;;&%#@++.........++@@@++..........................................................................++$&*;;>&$@.", +".......................++#$*=;;;=*$#+....++#%**>-=*=>>**%#+....+@$&->>>>;;-=*$@..++@$%*->;;;>-**%@+...++#$&-->>-&$@++.......++#$%%%%%##++.......++#$&->-=&$@+......++@$==->>*&$@+......+@$**>;-==$@++.....++@#%&*;;;*&$#@++.......+@#$$$#@+........................................................................++@$*=;;;*%#.", +".......................++#&==;;;==%#@....++#&*=>>===>>=*&#+...++#$&->>>>;;-==%#..+@$%*=>>;;;>-=*&#@...+@$%*->>>>*%$@+.....++@#$%****&%$@+.......+@#&*>>>=*$@+......+@#%=->>>*%$@+.....++@#%*>>>-=%#@+....++@$$&*=;;;=*&%#@+......++#$&&&$#@+.......................................................................++#%*=;;;*$#.", +".......................+@#%->;;;>-&$++...+@$*=-;;---;;==*#@...+@#&*>>>>>;;-==%#.+@#%->>;;;;;;;==*#@..++#**=>>>>-==$@+.....++#$&>>;;;>-%#++......+@%*=;;;==$@++......@$&->>>-*$#+........+#%*->>>>&$@+....+@#*====;;;====*#@......+#$&;;;&$@+.......................................................................+@$&-->>>*$@.", +"........................@$&->;;;>-&$@+..++@$==-;;---;;-=*$@..++#%&*>>>>>;;--=&$.+@$&->>;;;;;;;-=*$@..+@#*==>>>>>-=%#@+....+@$%*>>;;;>>&$@......++#%==;;;=*$@+......+@%*>>>>-&$@+.......++@#&->>>>&$#+....+#$==-=-;;;-=-==$@.....++#%*;;;*%#++......................................................................+@$&->>>-%$@.", +".......................+@$&->;;;--&$@...++@%*=-;;-=-;;==&#+.++@#=--;;;;;;;;>>*%.+#$&;;;->===>-==*#@.++@#*=->>>>->-&$@+...++#&==;;===--%#@+.....+@$&>>>--*%#++.....++#$*>>>>-%#++.........@#%->>>>*%#+...++@$=--;;;;;;;-==$#......@#&*;;;*&#@+...........................+.+.+.+..++...............................+@#&*;;==*%#+.", +".......................++$&=-;;;>=&#@+...+#$==-;;=-=;;=*&#+..+#$==-;;;;;;;;>>*&.+#$*>;;->===>-=*&#+..+@#*==>>>>>>-&%#@+..+@#*==;;===--%#@+.....+@#&>>--=&$@++......+#%*;;;=&%#++.........+#$**;;;*%#++..++#$==-;;;;;;;>-=$#...+++#$&=;;;=&$#++.........................+++@+@+@@++@+++............................+#$&*;;==&$@+.", +".......................+@$&->;;;--&$@...++@$*==;;===;;=*%@+.++#$=->;;;;;;;;>>*%.+@%&;;;->===--=*&#@..+@#&==>>>>>>>*%$@+..+@#*==;;==*-=%#@++.....@#%->===$#@+......+@#&*;;;=&$@+.........++@$&=;;;*&#@....+@#=--;;;;;;;-==$@..++@#$%*=;;;=*&$#@+......................++@@##$#$#$$$##@@+..........................+@#%*=;;=*%#++.", +"........................+#&->;;;>-%$++...+@#*========-&%#@+.++#%==-;;;;;;;;>>*$.+@$&>>>;;>>>-==*%#@...+@$%*>>>>>>-==*@+..+@$&==;;==**&%$@@+.....+#$*=&%$#@+........+#&*;;;*&$@+..........+@$&*;;;*&#++..++@#%*==-;;;--=*%#@..+#$%&**=;;;=**&%$@......................+@$$%&&&&&&&&&%%$@.........................+@#&=-->>*$#++..", +".......................+@#%->;;;>-%#@....++#&**=*&&*==%#@+...+@$=->;;;;;;;;>>&$.+@#%->>;;>>>-==*&$@..++@#%*>>>>>>>==*#+..+@#**=;;===**%%$@+....++@#&&$#@+++.......+@#&*;;;*&$+...........++$&*;;;*&$+....++#$**--;;;-=**%#@.+@#%**===;;;===**%$.....................+@$%****=**=****&%$.........................+#$*>;;-=&$@+...", +"........................+#$*=;;;=*%@+.....++@#$$$$$$$##@@+..++#%&==;;---;;==*%#..+#$&*=--;;;;;--=%#...+@#%*->;;;>>**%#+..+@#*==;;;;;====*$@......+@@#@@@+..........+$&*;;;*&#@...........++$&*;;;*&#@+...++#%*=;;---;;=**#+.+#%*;;;;;;;;;;;;;*%.....................+#%*;;;;;;;;;;;;;*%........................++#%*;;;==%#@+...", +"........................+@$**;;;=&$#++....++@@@#@@@@#@@+....+@#%**=;;---;;=**%#.++@$&**->;;;;;>>-%$...+@#%*>>;;;>>=*%$@.++@$*==;;;;;==-==$#......++++++...........++#&*;;;*&$++..........++$&*;;;*&#+.....@@&*=;;---;;=*&#+.+#&*;;;;;;;;;;;;;*%............+........+#&*;;;;;;;;;;;;;*&........................+@$&*;;;==$@+....", +"........................+@#&*;;;*&$@........++++++++++++....+@#&*==;;---;;==*%#..+@$%*==-;;;;;>>-&$..++@#%*->;;;>>=*&$@.++#$*==;;;;;==--=%#.......+++.+...........++#&*;;;*&$@+..........+@$&=;;;*&#+.....+#%*=;;===;;=*&#+.+#%*;;;;;;;;;;;;;*%........+++++++......+@%*;;;;;;;;;;;;;*%........++++++.........++#$==;;;*&$@++...", +"........................++#&*;;;*%#++...........+.+.+.......+@%*;;;;;;;;;;;>>%#.++#%==-=-===>-;;;*$..++@*==--;;;;>>>-%#.+@#&=>>>>;;;;;>>-&#.......................++#&*;;;=&$@+..........+@$&*;;;*&#@+...++@%**=-***-=*&%@+.+@$%**===;;;===**%$.......++@@##@+++....+@$%***=*=*=*=***%#......+++@###+++.......+@$&>>>--&$@+.....", +".........................+#$*;;;*$#+........................+#%*;;;;;;;;;;;>>$#.+@#%=->=-===--;;;&%..++@&*==-;;;;;>>-%$.+@$&->>>>;;;;;>>-%#.......................++#&*;;;=&%@+..........+@$*=;;;*%#+....++@$&*==&&&==&%$@+..+@$%&**=;;;=**&%$@.......+@#$$$$#++....++@$$&&&&&&&&&&%%#@......+@#$$$$#@+......++#%*>>--=%$@+.....", +"........................++@$&***%$@+........................+@$*=--;;>>>>>=*&$@.+@$&>;;;;;>;;;>>>*$...+@#$%*=>>>==>>-&#.+@$*;;;-->->;;===&$........................+#%*>>>-=%#@+........++#%=->;>*%#+.....++@###$#$#$$##+++..++@#$&*=;;;=*&$#@+......++#$===&&#++....++@####$#$$#$$##@+.....++#&*===$#+.....++@$&*>;-==$@+......", +".........................+@#%***%#@+........................+@$%=--;;>>>>>**$#@.+@%&>;;;;>>>;;>>-&$..+.+@#$&*>>>==>>-&$.+#$*>;;>-->-;;-==%#.......................++@$&>>;-=&$@+.......++@$&=-;>>*$#++.....++@@@@@@@@@@++.+....+@#$&=;;;**$#@+.......+#$&---=&#@+......+++@@@@@@@+++++......+@$&=---%$@+....+@#&*=;;=&%#@+......", +".........................++#%***%$++.........................@#%=--;;>>>>>*%#@+.+@$&>;;;;>>>;;>>-%#...+++@$%*>>>==>>-&#.+#$&>;;->-->;;===&$........................+@$&=->>>&%@++......++#$*>>---&$@+........+++++.++++.+.......+@#&*;;;*&$@+.......+@$%*>>-=*$@+........+......++++.......++#$*=>>-&$@+....+@$&==;;*&$@++......", +".........................+@#%;;;%#@.........................++#%==-;;>;;--&%@++.+@#&=-->>;;;>>**%#@.....++@$&>;;;;>>-%#.+@$&>>>;;;;;;;;;;*%.........................@#%=->>>*&#@+......+@#%*>>>-=%#@..........+.+.....+.........++#%*;;;*%#++.......+@%*=;;;=*$@+...........+...............+@%=-;;;&$@+....+#%=-->>*%#@+.......", +".........................++#%;;;%#@+.........................+@$==-;;;;;--&$@+...+#$==-->;;;>>*%$#+......+@$%>>>>>>--$#..@#%->>;;;;;>>;;;&%.........................+#$==->>*&$@++.....+@$&*>>-==$@++............................+@$&;;;&$@+.......+@#%==;;;-*$@++.........................++@$=-;;;&$@++...+#%=>>>-*$@+........", +"..........................+#$%%%$@++........................++@$*=-;;>>>>-%$@+..++++#$%*=;;;**$#++........+#$%&*&*&%%#@..+@#%&***=******&%#.......................+.++#%*=;;==*#+.....++#*==;;**%#@+.............................+@#%&&&$#@+........@#&>>>--*%#@+...........................+@#$&&*&$#@.....+#%-->>-%$@+........", +"..........................++##$#@@+..........................+@$*=-;;>>>-=%#+......++#$&*;;;*&#@+........+++@#$$$$$##@+..++@#$%&%&&&&&&%$#@.........................++@$%*;;==*#++....++#*==;;*&$@+...............................+@##$$#@+........+@$%>>--=&$@+.............................+@#$%$$#@++....@#%=-==*$#+.........", +"...........................++@@@++...........................++#&*=>>>>>-=$#++.......+@#%=-=$#@+...........+@@@##@@@++...+++@@@###$######@+..........................++#%&;;=*&#+.....++@&*=;;&$#++................................++@@@+++........++#&->===$#++.............................+++@@#@++......+@$===*%#@+.........", +"............................+++++............................++@#$%&&*&&%$#++.........+@#$$$#@+..............+++++++++......++++@+@+@+@+++............................+@#$%%%$#@++.....+@#$%&%%#@+..................................+++.+..........++#%*=&%$#@++...............................+++++++......+@#***%%@++.........", +"..............................................................++@##$$$$$##@++..........+@@##@++................+.+............+.+.+.+.+................................+@##$##@++......++@##$#@@+.....................................+............++@#**%$#++..................................+.+.........++@#$##@@+..........", +"......+++@@++++.........+.+++@++++..........+++@+@@+@+++.........++++@@@+++.............+++@+++........+++@@@@@@@++++............++++@@++.....++@+@@@@@@@@+++.........+++@+@+++...........+++@@+@+..................................................................................................................+.+.........", +".....+@@##$##@+++.......++@@####@+..........++@###$$##@++.......++@#$#$$$#@++..........+@@@##@+++.....++@###$$$$$##@++.........+@@##$###@@+..+@@#$$$$$$$$##@@+......++@@##$###+++.......+++@#####@+++............................................................................................................+++++@++++.....", +"..+++@#$%%&%%$#@++....+@@#$%%%%$#@++......++@#$%%&&&%%$#@++...++@#$$%&&&%%$#@++......++@#$%$%$#@+...+.+@#$%&&&&&&&$$@@......+++@#$%%&&%$$@+.++#$%%&&&&&&&&%$#@....+++##$%%&%%$$@@+......+@#$%%%%%$#@@+.........................................................................................................++@######@@++....", +"..++@$$*=->-=*%$@++..++#$%&*=---%#++.....++@#$&==>>>==&$#@+...+@#$&==>>>==%%#@+......+@#%*====$#+....+@%&*->->->>==*$@+.....++#$%&*->--=%$@.+#$==->>>->>>===$#+...+@#$&*=->-=*%$#@+....+@#$&---==&%$#++.......................................................................................................++@$$%&&&%%##++...", +"..@@$%&==>>>==&%$@+.++#$&**==>--&%@+.....+@#%&*-->>>--*&%#@..+@#%&*-->>>--*&%#@.....++#%&===-=%$@+..+@#%*=>>>>>>>--=$#+.....@@$&**=>>>>-*$@.+#%=-->>>>>>>--=%$@..+@#$&*==>>>==*&%#@..++@#%&*>>>--**&$#+....................................................++++++.........................++++++.............++#$%&******%$#@+..", +".+@$*==;;;;;;;==*$@.++#%>;;;;;;;*%#+....++#$=->;;;;;;;>-=%#.+@@$=->;;;;;;;>-=%#.....+@$*=;;;;;*$#++.++$*==;;;;;;>>-=%#+...++@$*=;;;;;>>>*%#.@$&>>;;;;;>;;;;>&$@.+@@%=--;;;;;;;>-=$#...+#$*;;>>>;;;;>&$@..................................................+++@#@@@++......................++@@#@@@++..........+@$**;;;;;;;=*%#++.", +".+#$===;;;;>;;-==$#.+@#&>;;;;;;;*&#@+...++$%->>;;;;;;;>>-%$..+#%-->;;;;;;;>>-%$....+@#%==;;;;;*%#+..+@$*=-;;;;;;;>>-%#+...+@#%*=;;;;;;>>*%#.@$&>>;;;;;;;;;;;&%@..@$%->>;;;;;;;>>-&$..+@$%*;;;;;;;;;;&%@.........++++.................++++++...........+++@@#$$$$##@.....++++++++++++....+@@$$$$$#@@++.......++#%*=;;;;;;;=**$@+.", +"+@#%=--;;;;;;;-==%$..@#%>>;;;;;;*&#+.....@$&->>;;;;;;;>>-&$.+@#%->>;;;;;;;>>-&$....+@#%==;;;;;*&#++.+#$==-;;;;;;;>-=%#+..++@%&=-;;;;;>>>&$@.+#%>>;;;>>;;;;;;*%@.+@$&->>;;;;;;;>>-&$.++@$**;;;;;;;;;;*%$.......+@@@@@@++.............++@#@@@+..........+@@$$%&&*&%#@....+++@@@@@@@@@+@+..+@$%&*&&%$#@@++.....+@#&*=;;;;;;;==*%#@.", +"+@%&>;;--===--;;>&$..+@$&**==;;;*&$@....++$%>>;--===--;;;*%..@#%=--=====->;;>&$....+#$*>;>>>;;*&#@..+#$==-;;======*&$#+..+@#%*;;>>>===*&%#@.+@$%&****==>>>>>&$@.+@%*>;;--===->;;;*$.+@#*==;;=====;;;=&$.....++@#$$%$#@+............+@##$$$#@+.......+@@#$%&--;;;=*$..++@##$$$$$$$$$##@+.@#$;;;>>*&&$#@++....+@#*==;;===>>;;>&$@.", +"+@%*;;;--***--;;;*%.++@@$&**=;;;*%$++...+@#%>>>==**=--;;;*%.++@#=-==**==->;;;*%...+@#%*>;>>>;;*&#++.+@$==-;;-=====**$#+.++@$**;;>>-===*&$@+.+@@$$%%&&*=>>>>>&$@.+@$&;;;>-===--;;>*$.+@$*=-;;=*=*=;;;**$.....++#$&&&&$#@+..........+@#$%*&&$#@+....++@#$%***--;;;=*#..+@#%%&&&&*&&&&%%#@.+#%;;;>>=**&%$@@+...+@$*=-;;===>>;;>*%@.", +"@#%*;;;-=***==;;;*%...++##&*=;;;=%$++....+@$%&&&&&**>>;;;*$..+@#$%%&***=;;>>>&$..++@%*=;;-=-;;*&#@..+#$*=-;;;;;;;>-=%#@.+@#*==;;>>>>>=*&$@+..++@@##$%**;;-==%#@.+#$*>>>>>===>>>>>&%.+@$==-;;=*=*=;;;=*$.....+@$==;;;&$@+..........+@$==;;;&$@+...++@#%*=>;;;;===&%#..@#$-->>>>>>>->--%#.+@$&*=>>;;;-=%$#@@..++#**=--=*==-;;;*$#.", +"+#%*;;;-=*&*==;;;*%....++#$**;;;*&#@.....+@@#$$$%&*=>>;;>*$...++##%%&*==;;>>>&%..+@#&*=;;---;;*&$++.+#$==-;;;;;;;--=%$+.+@$*=-;;>>>>-==*$#+...++++@#$&*;;-==$#+.+@$&>>>>>===>>>>>&$.+@$==-;>=*=*=;;;=*$....++#$=-;;;*$#+.........++#$=-;;;*$#+..++#$%&==;;;;;==*%#@.+@$&->>>>>>>>>>>-%$.+@#$&*>>;;;--*&%$#@.++#%*====*==-;;;*%#.", +"+#%*;;;-=&&&==;;;*%.....+@#&=;;;*&$++.....++@##$%&**>>;;>&$...++@@$%**==;;>>>&$..+#$*==;;=-=;;*&$@+.+@#*==;;;;;;;>--&$@.+#$==-;;>>>>>===%$@.....+++@$&=;;-=*$@+.+@$&->>>>===>>>>>&$.+@$*=-;;==*==;;;=*$....++@%=-;;;*$#+.........++#$=-;;;*$#+..@@$%**=-;;;;;=**#@+.+@$&>>>>>>>>>>>>>&$..+@#$&->;;;>-=**%$@.++@%&*==**==-;;;&%@.", +"+#&*;;;==&%&==;;;*%......@#&*;;;*&#@.......++@#$%==-;;===%#....++@$==;;;;;-==&$.+@$%-->>>-=-;;=*$@+.+@#&*=>>===>>;;;*%#.+@$==-;;;;;;;;;;*$#......+@#%*=;;**$#++.+@$&==-;;;;;;;===&$.+@$*==;;===>>;;;=*%.....+#$*=>>>&%@++.........+#$==>>>*$@@..@$%>>>;;>>-=*&%#@++.@#&*>>;;;;;;;;;;>*%...+@#$&*===;;;;;=*$..++@#$&*==-;;>>>&$@.", +"+#%*;;;==&%&==;;;*&......@#&*;;;*&$++.......+@#%*=--;;==&$@....++@#*=;;;;;===&$.+@$&->>>>=-=;;=*%$@..+@%&*>>===>>;;;*&#.+#$==-;;;;;;;;;;*%#......+@$&*=;;*&$@+..+@$&===;;;;;;;-==&$.+@#*==;;===->;;;=*$....++@$*=>>-%$@...........+@#*=->-%$@...@$&>>;;;>--*&%#@@...@#&*>>;;;;;;;;;>>*&....+@#$&*==;;;;;==$..+++@$%*=--;;>>-%#@.", +"+#&*;;;==&&&=-;;;*%.....+@#&*;;;*&#@........+#$*=;;;-=*&$@@....++#$%&===>>;;>&%.+#%*;;;;;>>>;;-==$@.++@#$%%&&&*==;;;=*$.+@$==-;;-====;;;=*$......+@$=-->>*%#@+..+@$&>;;>>=-=>>;;>&%.++#$**>>;;;;;;;;=*$......+##%%%%$@++..........++@$$&%%$@++..#&*;;;;;---*&$#+++..+#&*>>>>>>>>>>>>>*%....++@$%*==;;;;;-=%....+@#%*;;;--**%$@+.", +"+#%*;;;==&&&=-;;;*&......@$&*;;;*&$@......++@$%==;;;-=&%#++...++@#$$&*==>>;;;*%.+#%*;;;;;>>>;;>-=%#.++@#$%%%$%&*=;;;=*#.+#$==-;;=====;;;=&$.....++#%=--;>*%#++..+#%*;;;>>===>>;;;*%..+@#%*>;;;;;;;;;=*$.....+++@#$$#@@+............++##$###@.+..#%*;;;;;---*&$#@+...+#&*>>>>>>>>>>>>>*$....++#$&**=>;;;;-=%.....@#%*;;;-=*%##++.", +"+#&*>;;-=*&*==;;;*%.....+@$**;;;=&$@+.....+@#%*=-;;;-=%$@++..++##$$$%&*=>>;;;*%.@#&*;;;;;>>>;;>-=%#.++##$$$$$$&*=;;;=*$.+@$==-;;=====;;;=*$.....+@#&=->>>*$@+...+@%*;;;>>===>>;;;*%...+#%&>>;;;;;;;;=*$......++@#@#@@+.............+++@##@+++...@%*>;;;;>-==*&$#@++.@#&*>>>>>>>>>>>>>*%...+@@$%**==;;;;;==$....++#%*;;;==%$@++..", +"+#%*;;;-=*&*==;;;*%....++#$&=;;;**$#++..+++#&*=;;>>-=&%#@++.++@$*==&&&**--;;;*%.+#&*;>;;;;;;;;>>-&#.+@#*==&&%%&*=;;;=*$.+#$*=-;;==**=;;;=*$.....+@$&>>>>-&$@++..@#%*;;;--===--;;;*%..+++$%*===---;;;*&#.......+@@###@++............++@@###@+....+#$&*=--;;;;>*&%#@+.+#&*>>;;;;;;;;;>>*%.+++#$%==;;;>>=**&$#.....+#%*>>>*&$#++...", +"+#$*;;;-==**==;;;*$...++@$%*=;;;=*&$@@+..+#$*==;;>>-=*&$#@+.+@#%===*&**=--;;;*%.+#&*>>;;;;;;;;>>-&$.+#$===**&**==;;;=*$.+@$==-;;=====;;;**$....++#$*>>>>-&$@+...+@%*;;;--===--;;;*%...+@#%**=-==-;;;*%#......+@#$%$$#@+...........++@#$$$$#@+...+@#$%*==;;;;;==&$#@.+#%*>>;;>;;>>>>>>*%..@#$&*--;;;>>**&$#@....++#$*>>>*%#@+....", +"+@$&>;;--===--;;>&$..++#$%**=;;;=**%$@+.+@#%*==;;>>-=**%#@@.+@$&==-=**=*--;;>*$.+@%&>>>;;;;;;;>>-&#.+#%==-==**===;;;=&$.++#*==;;=====;;;=*#.....+#$*>>>>-%#++...+#$*>;;--=*=--;;;&$..++@$%*===--=;;;*%#.....++#$%&&&$#++..........+@#%&*&%$#@...++@#$%==;;;;;==*&$#.+@$&>>>>>>>>>>>>-&$.+@$&*=->;;;>-&%##++.....+@$*>>>*%#++....", +"++$%==-;;>>>;;--=%$.++@$*==>>;;;>>-==$@.+#$*;;;;;>>>>>==*$@.+#%*;;;>>>>>;;>>>&$.++#$&**=->>>;;>--&$.@#$-->;;>->;;;;>*%#.++#$**;;;;;>>;;;**#.....+#%*;;;**$#+....+@$&->>;;>>>;;>>>&$..+@$%*->>>>;;>>>&$@....++@#==;;;&$@+.........+@#%==;;;&#@+....++@#$&***>>;;;=*#.++#$%&&&*&**&*&&%$#.@#$>;;;;===*&$#@++.....++@$&->-&$@+.....", +"++@$*==;;>>>;;==*$@.++#$==>>>;;;>>-==$#.+#%*;;;;;>>>>>--=$#.+#%*;;;;;>>>;;>>-%#.++@#$&*==>>>;;>--%$.+#$=>>;;>>>;;;;>&$@..+@#%*;;;;;;;;;;*&#.....+#%*;;;*&$++....++#%->>;;>>>;;>>-%#..+@%&*>>>>>;;>>-%$@.....+#$==;;;&$@+.........+@$&=-;;;&$@+......+@#$%&*--;;;=*#.+++@#$%$%$%$%%$$##+.+#%>;;>>=*&%$#@++.......+@$&->-&$@+.....", +".+@#$&*=->;>>-*&%#@.++#%=->;;;;;;;>-=%#.+#%*>;;;;;;;;;>-=%#.+@$%===;;;;;>>**%$#...++@$%==>;;;;>>-%$.+@#%*=>>;;;>>=*&$#@...+@$%==>>>;;-==&$@....++@$&>>>*%#++....++@$%*=>>;;;>>**%$@.++#&*=>>;;>--**%$@+....++#$==>>>*%#++.......++#$*;;->=&$@+........+@#$$&&**&%$#...++@@@#@###@#@@@++.+#$****&%%$#@++.........+@$&->-&$@+.....", +"..+@#$&==>>>-=&%#@+.++#%=>>>;;;;>>>--$#.+#%*>>;;>;;;>>>--%#..+#$*==>>>>>>>*&$@+....++#$==>>>>>>--%#.++#$%*->>>>>>*&%#@+...++#$**>>>>>==*%#@.....+@$&---&$@++.....++@$%*->>>>>>*&$#+.++@%*=>>>>>==&%##++.....+@$*=>>>&$@+........++#%*;;--=%#@+........+++@##$$%$$@@...+.+++++++++++++...+@#%&&%$##@+++..........++#%---%#@+.....", +"...+@#$*=>>>==$#@+...+@$==->>>>>>>-==$@.+@%&>>>>>>>>>>-==$@.++@$&*=>>>>>--%$#@+....++@#**>>>>>-==$@..++@$%-->>>>-&$#@+.....+@#%*-->>-=*&#@+.....++#$=--$#@+.......++#$%-->>>--%$#++.++@%&*>>>>>=*%#@++.....++@#*=>>-%#@+........+@$&*;;-==$@+...........+++@@#@@@+..........+..+.+.......+@##$##@+++.............@#$===$#+......", +"....+@#$%%&&%$#@+...++@#$%&&*&*&*&&%$#@.++#$%&&**&**&*&%$#@..++@#$%&*&*&&%#@++.......+#$%&&&&&&%$#@...++##%&&*&&%$#+++......+@#$%&&&&%$#@++.....++@#$$$#@+........+++#$%&&&&&%$@+++..+@@$%&&&&&%$#@++.......++##$%%$$@+.........+@&*=->*&%#@+............+++++++++........................++@@++++...............+@#$$$#@+......", +".....++@##$$##+++.....++##$$$%$%$$$$@@+..++##$$$%%$%$$$##++...++@@##$%$$$##++......+.++@#$$$%$$##++....++@##$$$##@++.........+@@##$$##@@++.......++@###@++..........++@#$$%$##@++.....++@@$$$$$#@+++.........++@#$##@++........++@%**-=&$#@+.................+.+..........................++.++..................++@@#@@++......", +"......++@@@+@++.......+++@@#@#@#@@@++++..+++@@#@#@#@#@@++++.....++@@@@@@@+++...........++@@@#@@+@+.....+++@@@#@@@+++..........++@@@@@@+...........++++++..............++@@@@@@++.......++@@@@@@+@+...........++++@+@++..........++@$$$$$#+++.......................................................................+++++........", +".........................+.+.+.+...........+.++++.+.+................++++.+.......+++.+++.+............+.+++.++++.+.........++.+++.+++.+............++++.+.........+.++.+....+.++.+......+.++.++++.+..........+.+++.+++.+......+.+++...+.++..+......+++.+.+............+...........++.+.....+........++............+..+.........", +"......+++++++...........++++@+@+++........+++@+@@@@@+++...........++@+++@+++++..+++++@+@@@@@++........++@+@@@@@@@@++++...++++@@@@@@@@@@+@+........+++@+@@+@++++..++++@+@+++++@+@+++.....++@+@@@+@+@++.........+@+@@@@@+@++....++@+@+@+++@++@++....++++@@@@+++.........++@+@+..+..++++++...+++++++.+++++@+++.......++++@+++......", +".....++@####@@++......++@@##$###@+......++@@#$$#$$###@+++.......++@@#$$####@@++.+@##$$$$#$##@@++....+++@#$#$$$$$$#$@@+...+@@##$$#$$$#$###@+.....++@@#######@@++..+@###$###@###$###@..+++@##$#$$$$###@@.....+++@##$#$#$###@+.++@###$###@######@+.++@##$#$####++......++@@###@++++@@####@.++@@###@++@@#####@+.....++@@####@@+.....", +"..+++@#$$%%$$#@+.....++@#$%%%&%$#@+.....+@#$%%&&&&&%%$#@++....+++@#$%%&&&%%$$#@.@#$%%&&&&&%%$#@++...+@#$%&&&&&&&&&%$#@+.+@#$%&&&&&&&&&&%$#@...++@@#$%&&&&%%$$#@.+@#$%&%%%$$$$%%&%$#..++##$%%&&&&&&%$#@@....++#$$%&&&&&&%$#@.+@#$%%%%%$$$%%%%$#@.++#$%&&&&&$$#@+.....+@#$$%%##@+@##$%%$#.+@#$$%$$#@##$%%%$#@...+++@#$%%%%$##++...", +"..++@#%%***&&$#@+....++#&*=----=%#@+....+#$=----->--=*%$@++...+@#$**-----==***#.#**---->---==%$#@++.+#$=----->-----=%#@.+#$=--->->->->--=*#...+@#$**-----==***#.@#**-----***-----**..+@#*==---->--==*$@....+@#*=-->->---**#.+#**-----***---==$#.+#$=-------&%#++....@#**--=&%###%&-=-**.+#$==-=*$$$*==-=**#...+@#$**---==%$#@+..", +"..+@%&*>>;;;-=$#++...+@$*==>>>->&%#@+...@$%-->>>>>>>-=*&$@+.++@$$&*=->>>>=-==*$.$*=->>>>>>>-=*&$#@+.@$%-->>>>>>>>>--&$@.@$%-->>>>>>>>>>-==$.++@#$&*=->>>>=-==*$.@$*=->>--*=*-->>-=*.++@%==->>>>>>>-==$@...++#%==>>>>>>>>=*$.@$*=>>>>-=*=->>--%#.@#%=->>>>>-=&#@+....@$==-->*&$$$&*-->=*.@$&---==&%%==->>=*$..@@#%&*=->--=&&$#@+.", +".+@#&*=>;;;;-=&$@++..+@$===>>>>>*&$@+...@$&->>>>>>>>>==*%#@.+@$%&*=->>>>>---==%.$==>>>>>>>>>-=**%#@.@$&->>>>>>>>>>>>*%#.@$&->>>>>>>>>>>>==%.+@$%&*=->>>>>---==%.#$==>>>>>===>>>>>==.++#$==>>>>>>>>>-=$#...++#%=->>>>>>>>==$.#$==>>>>>===>>>>-&$.@$&->>>>>>-=*#@+....#$==>>>=*&%&*=>>>==.#$*->>==***==>>>==%.+@$%&*=->>>>-=**%#@.", +"++#$*==>;;;;>-*%#++.++#$=->;;;;;-=%#++..#%*;;;;;;;;;;;;;*$#.@#%-->;;;;;;;;;;>>&.%=-;;;;;;;;;;;;;&%#.#%*;;;;;;;;;;;;;=&$.@%*;;;;;;;;;;;;;>>&.@#%-->;;;;;;;;;;>>&.@%=-;;;;;===;;;;;-=.++#$=->;>;;;;>>-=%#...++#%->>;;;;;;;==$.#%=-;;;;;=-=;;;;>*%.@$&>>;;;;;>=*$@+....#%=-;;;>>***->;;;-=.#&*;;;;;=**>>;;;-=%.+#%-->;;;;>;;;;;&%#.", +".@#%=->>>---;;=&%@+..+@$=->;;;;;>=&$@+..@%*>;;;;;;;;;;;;*%#.@$&->>;;>>>>>;;;>>&.$=-;;;;;>>;;;;;;*&$.@%*>;;;;;;;;;;;;=*$.@%*>;;;;;;;;;;;;;>&.@$&->>;;;>>>;;;;>>&.#$=-;;;;;===;;;;;-=.++@$==->;;;;;>--=#@...++@$=->>;;;;;;-=$.@$=-;;;;;=-=;;;;>&$.@$&>>>;;;>>=*#++....#%=-;;;>>*=*>>;;;-=.#&=;;;;;===>>;;;-=%.@$&->>;;;>>;;;;;*&$.", +"+@$&->>>>---;;=*&#+.++@$%*=;;;;;>>*$@+..@$&=--;;=====;;;=*$.#%*;;;--=*=*=>>>>>&.$&=;;;--==*==;;;-=%.@#&=--;;=====;;;**$.@$&=--;;=====>>>>>*.#%*;;;--=*=*=>>>>>&.@$&*;;;-====--;;;=&..+@#$&**=;;;==*&$#@....+@#$&**=;;--=&%#.@$**;;;--;;;;;=*&$#.+#$&*=;;==*%$@@.....#%==;;;;;===;;;;;==.#&*;;;;;=--==;;;=*%.#%*;;;--==*==;;;-=%.", +"@@%*;;;--->-;;-==$#...+#%&=>;;;;>>*%#++.+#%=--;;=====;;;=*$.#%*;;;-=**&**->>>>&.#&*;;;-=****=;;;-=%.@#%=--;;=====;;;=&$.+#%==-;;=====--->>%.#%*;;;-=*****>>>>>&.@$&*;;;--=*=--;;;*&...+@#$&*=;;;=*%$#@+....++@#%&*=;;--=&$@.@$&*;;;--;;;;;**%#@.+@$%*=;;==*%#++.....#$*=;;;;;===;;;;;=*.#&*;;;;;---==;;;=*%.#%*;;;-=****=;;;-=%.", +"+#%*;;;>>;;;;;-==$@..++#$**>>;;;;>*&$@+.@#%==-;;=====;;;=*$.$&*;;;-=&%$%&=-->-%.#&*>;;-=*&&**;;;>-&.@#$==-;;=====;;;*&#.@#%=--;;=*===>-->-%.$&*;;;-=&%%&*-->>>%.+#**;;;--===--;;;*&....+@#%&=;;;**%#+++.....++@#$**;;-==&#@.+#&*;;;--;;;;;*%$@+..+@$**;;=*&#@++.....#%*=;;;;;===;;;;;=*.#&*;;;;;>->==;;;=*$.$&*;;;-=&%&**;;;>-&.", +"+#%*;;;>>;;;;;-==%#..++#%*=;;---;;=*%@+.+#$==-;;>>>;;;;;=*%.$*=;;;=*%$###$%&%%#.#&*;;;-=&%$&*>>>>>&.+#%==-;;==-;;==*&$@.+#$==-;;===;;=**&$$.$*=;;;=*&%$%&*=***$.+#%*;;;>>>>>;;;;;*&.....+@$&*;;;**$@+.......+++@$&*;;-==%#+.@#&*;;;;;;;;=**$@++..+@$&*;;=*&#@.+.....@%*=;;;;;-=-;;;;;=*.#%*;;;>>;;;==;;;=*$.$*=;;;=*%$$%*>>>>>&.", +"+#&*;;;;;;;;;;-==$#..+@#**=;;---;;=*&#+.+#$==-;;>>>;;;;;=*%.$*=;;;=*$#+@@###$#@.#&*;;;==%$$%*->>>>&.+#$==-;;=-=;;==*$#@.+#$==-;;===;;**&$#@.$*=;;;=*%$%&**==*&$.+$&*;;;>>>>>;>;;;*%.....+@$&*;;;*&#@+.....+++++@#&*;;-==$#+.+#&*;;;;;;;;=*%$@+...++#&*;;=*%#@+......@%*=;;;;;-=-;;;;;=*.#&*;;;>>;;;==;;;=*$.$*=;;;*&$##%*->>>>&.", +"+#%*;;;;;;;;;;-==%#..+@$*=-;;===;;-==$@.+#$==-;;;;;;;;;;==%.$*=;;;*&$@+++@@@@@+.#%*;;;==%$#$&-->>>*.+#$==-;;;;;;;=*%$@+.+#$==-;;;;;;;**$#@+.$*=;;;**%$%=----==$.+#%*;;;;;>;;;;;;;*&......+$&*;;;*&$++...++++@@+@#&*;;-==$#+.+#%*;;;;;;;;==&#@+...++$&*;;=*%#@+@++...@$*=;;;>>;;;>>;;;=*.#&*;;;--;;;--;;;=*$.$*=;;;**$##$&-->>>*.", +"+#&*;;;;;;;;;;-==%#.+@#%==-;;===;;-==%#.+#$==-;;;;;;;;;;-=&.$*=;;;*&$@+++++++++.#&*;;;==%##$&-->>>*.+#$==-;;;;;;;=*%$@+.+#$==-;;;;;;;*%$@++.$*=;;;=*%%&->>>-==%.+#&*;;;;;;;;;;;;;*&.....+@#&*;;;*&#@....+@##$###$&*;;-==$#+.+#&*;;;;;;;;==&$@++..++#&*;;=*&#@#@@@++.@%*=;;;>>;;;>>;;;=*.#&*;;;--;;;--;;;=*$.$*=;;;*&$@#$&-->>>&.", +"+#%*;;;>>;;;;;>>-&$.+@$&=--;;===;;--=&$.+#%==-;;;;;;;;;;-=&.$*=;;;=&$@+++@@@@++.#%*;;;==%$#$&=->>>*.+#$==-;;;;;;;=*&%##.+#$==-;;;;;;;*&#++..$*=;;;**&&*->>>>==%.+#&*;;;;;;;>;;;;;*&......@$&*;;;*&$++...+#$%&%%$$&*;;-==$#+.+#&*;;;;;;;;-=*%#@+..++#&*;;=*&$$$$##@+.@$*=;;;>>;;;>>;;;=*.#%*;;;--;;;--;;;=*$.$*=;;;=&$##$*-->>>*.", +"+#%*;;;>>;;;;;>>-%#.+#%*>;;;;;;;;;;>>&$.+@$==-;;=====>>>>>&.$*=;;;=*%#@@@##$$#@.#&*;;;==%$$%&-->>>&.+#$==-;;---;;===**#.+#$=--;;---;;*%#+...$*=;;;==&&*;;;;;>-&.+#&*;;;--===--;;;*%.....++$&=;;;*&$@+...#%*>>>&%%**;;===$#+.+#&*;;;>->>>;;=*%#@...@$&*;;=**%%===$#@.#$*=;;;==;;;==;;;=*.#&*;;;-->>>;;;;;=*$.$*=;;;=*%$$%*>>>>>&.", +"@#%*;;;-->>>;;>>-&$.+#%*;;;;;;;;;;;;>*&.+#%==-;;==*==>>>>>&.#*=;;;=*&$#$$%&%%$#.#&*;;;==&%%&*->->>&.+#%==-;;---;;-====%.+#%==-;;---;;&$@+...#*=;;;=****;;;;;>>&.+#&*;;;--=*==-;;;*&.....+@$&*;;;=&$@+...#&*;;>*&&*=;;-==$@+.+#&*;;;-->>>;;==&$@.++@$&*;;==**&===%$@.@%*=;;;==>>>==;;;=*.#%*;;;>->>>;;;;;=*%.#*=;;;=*&%%&*>>>>>&.", +"+#%*;;;->>>>;;>>-%#.@$*=;;;>----->;;;=*.@#%=--;>===*=>>>>>*.#%*;;;>-*&%%&-----$.$&*;;;-=*&&*=;;;==%.+#%=--;;===-=>>->-&.@#%==-;;====*%$@+...#%*>;;>-=**==>>>>>*.@$%=;;;-==*=--;;;*&...+@@#%*=;;;=*%#@@+.$*=;;;==**=;;-=*$#+.+$&*;;;>-===;;>--&$..+#%*=;;===*=;;;=&#.@%*=;;;==*=*==;;;=*.#&*;;;--===;;;;;=*$.#%*;;;>-*&**=;;;==&.", +"+@$&>>>>>===>-==*$#.@$*=;;;---=---;;;=*.@#&==-;;==*==>>>>>&.#%*;;;>>*****>>>>-%.$&=;;;--=**==;;;==$.@#&==-;;====->>>>>&.@#&=--;;====*%#++...#%*>;;>>=====>>>>>&.@$&*;;;-==*==-;;;=&...+@$%&*=;;;=**%#@+.$&=;;;=====;;===#@+.@$&=;;;--===;;>>-&%.+@$%*=;;=====;;;=&$.#%*=;;;==***==;;;==.#&*;;;--===;;;;;=*%.#%*;;;>>=**==;;;=*%.", +"+@#&->>>>===--==*$@.#%*=;;;>--=-->;;;==.@$&=--;>=====>>>>>&.#$&>;;>>=====>>>>-%.$&=;;;-======;;;=*$.#$&=--;;=====>>>;>*.@$&=--;;==*=&$#+....@$*>;;>-=====>>>>>&.@%&=;;;-==*=--;;;**..+@#$**==;;;==*&%#@.#&=;;;=====;;==*#@+.#$&=;;;--*==;;>>>*&.@#%**=;;=====;;;=*#.#&*=;;;=*****=;;;=*.#&*;;;-====;;;;;=*$.#$&>;;>-=====;;;=*$.", +"++#%*=-;;;;;;;=**#@.#%->;;;;;---;;;;;>-.#&*;;;;;;;;;;;;;=*%.+#%===;;;;;;;;;>=*$.%--;;;;;;;;;;;>>*&#.#%*;;;;;;;;;;;;;>>&.#%*;;;;;;;;==#@+....@#%*=-;;;;;;;;;;=*$.#%--;;;;;===;;;;;>-.++@$-->;;;;;;;>>-$@.#%&>>;;;;;;;;*&$#++.#%->;;;;;==*=-;;;>-.@%&;;;;;;;;;;;;;**#.#%->;;;>>*&*->;;;>-.#&=;;;;;**=>>;;;=*$.+#%===;;;;;;;>>-*%#.", +"++@$*==;;;;;;;=*&#+.#%->;;;;;===;;;;;>-.@&*;;;;;;;;;;;;;*&$.+##**=;;;;;;;;>>*&$.$=>;;;;;;;;;;>>>%$@.#&*;;;;;;;;;;;;;>>%.@%*;;;;;;;;==$@++...+@$**=;;;;;;;;>>*&$.#$->;;;;;===;;;;;>-..+#$->>;;;;;;;>>-$#.@$&>>>;;;;;;>&%#++..#$=>;;;;;=**==;;;--.@$*;;;;;;;;;;;;;*&#.#%->;;;>-&&&>>;;;>-.#%*;;;;;***->;;;*&#.+##**=;;;;;;;>-=%$@.", +".+@#&*=>;;;;;;=*%@+.@$&*=====***=====**.@$%*===========*&$#..+##%&**=====**&%#@.$%&==========**%$#+.@$%*============**$.@#%*======*&$#++....++##%&**=====**&%$@.@$&*=====&**=====*&.++@#&*=========*&#@.+#$%**=====*&%#@+...@$&*====*&&%&**=**&.@#%*============%$@.@$&*===**%%%**==***.@$&*===**%&&*==*&$#.++@$%&**====**&%$@+.", +"..+@#$%&*===**%$#@+.@#%&*****%%%*****&%.+#$***********&&$#+.+++@#$%%*****&%$#@+.@$%*****=***&&$$#@+.+#%&**=*=*=*****&%#.+#$&***=***%#@+......++@#$%&*****&%$#@+.@#%&*****%%%&****&%..+@#$&&**=*==**&%#@.++##%&**=*=%%#@++...@#%&*****$##$%&**&%.+#$&***=*=**=**&$#+.@#%&***&&##$%&***&%.+#%&****$$$$%&**$#+..++@#$%%*****%$#@++.", +"...+@#$%%&*&%%#@@+..+@$$%&%%%###%%&%%$$.+@@%%&&*&%&%%%$$@++...+++@#$%%&%%##@@++.+@#%&&*&&&&%%##@+.+..+#%%&&&&&&&&%%%$$@.+@#%%&&&&%$#@++......++++@##%&&%%$##@++.+@#%%&%%%###%&&&%$#...+@#$%&&&&&&&%$#++..++@##&&&*&##@++....+@#%%&&%$#@@@#$$$$#.++#%%&&&&&&&&&%%#@+.+@$$%&%$$@@@$$%%$$#.+@#%%&%$#@@##%$$#@+..+.++@#$%%%%$##@++..", +"....++@###$###@++....+@@####@@@@@####@+..++@######@##@@@++......+++@@###@@@+++..++@@#######@@++++...+++@@#########@@@++...+@######@+++..........+++@@#@#@@+++...+++@####@@@@@@@##@@....++@#@###$##@@@+....+++@@####@@+......+++@#@##@@++++@@@@+..++@###########@++..++@@#@#@@@+++@@@@@+..++@@@@@@+++@@@@+++.....+++@@@#@@+++....", +"......++@@@@++++......+++++++++++++++++...++++++++++++++.+........+++++++++.......++++@++++++++.......+++++@+@++++@++.....++++++++++.............+.++++++++......++++++++++++++++++....+.++++@+@@++++......++++++++++........+++++++++..+.++++....++++@+@@+@+++++.....+++++++.+++++++++...+++@+++.+.++++..........++++++++......", +"....+...+.+..................................+..+...+.................+..............+..+.+.+............+.........+...........................+..........+..........+.+........+.........+......................+.+.+...........+++++@++........++++@++..................++++++++..............+++++...........................", +"..+++++@+@++++++..........++@++++++.......+++++@+@++++...........++++@+@+@+++......++++@++@++@++++....+++++++.++++++++....+++++++.+.+++++++....++@+++++.+++++++...+++++++++++@+++++...+++++++++++@+@+++.....+++@++@++@++++.......++#####@@+.....++@####@++..............+++@#$###++...........++@@@@+++.........................", +"++@@#####$####@@+......+++@@####@@++....++@@########@@@+.......++@@########@+++..+++@###$##$##$#@@+..+@@###@@@@@####@@+.++@@###@@@+@@####@+.++@@###@@++@@@###@+.++@@#####@@#@####@@.++@@#####@@#@####@@...++@@#####$####@@+....++@#$%%%%##@.....+@#$%%$$@++.............+@#$$%%%$#@+.........++@#$$$#@+.........................", +"+@#$%%&&%&%&%$$#@++...++@#$%%%&%%$#@++..+@#$%%&&&&&%%$#@++....++@#$%%%&&%%%$#@+.++@#$%&%&&%&&%%%$#@.+@#$%%%$$$#$$%%%$#@.+@#$%%%$$###$$%%$%#.+@#$$%%$$###$$%%$%#.+@#$%%%%%$$$%%%%%$#.+@#$%%%%%$$$%%%%%$#..++@#$%%&&%&&%&%$#@....++#$===--&$#++...+@%->>*&$@+............++#$&=-===%#++........+@#$===%#@+........................", +"@#%&*****=****&%$@+.+++@#%%******&%$@@+.@$%&********&&$#@++.+.+#$%&********&%#@.+@$%&*****=**=**&%#.@$%&****&%&&****&%$.@$%&****%%$$&&***&%.@$%&****&%%%&****&%.@$%&*****&&&*****&%.@$%&*****&&&*****&%..+#$%&*******=**&%#....+@$&=----*&$@....@#%->>=*%#@............+@%&*->--=&$@+.......++#%&===&$#@........................", +"@%*;;;;;;;;;;>>-%$@..+#$&*>>;;;;;==*$@+.#$->;;;;;;;;>>*&%@+..@@$&*;;;;;;;;;;*%#.+#%*;;;;;;;;;;;;;*&.@%*;;;;;=**>>;;;>-%.#$->;;;>>&&&>>;;;--.#$->;;;>>*&&>>;;;--.#$->;;;;;===;;;;;>-.#$->;;;;;===;;;;;>-.++#%>>>;;;;;;;;;;*%...++#%*;;;;>=&$@++..+#%=-->>&$@+..........++@&*=;;;;;*$#+......++@$*=;;;=*$@+.......................", +"#&*;;;;;;;;;;>>>&%#.+@$&*=>>;;;;;-==%$@.$%->;;;;;;;;>>=*&$@.+@$&*=;;;;;;;;;;*&#.+#&*;;;;;;;;;;;;;=&.#&*;;;;;===>>;;;>-%.#%->;;;>>***>>;;;>-.#&->;;;>>*=*>>;;;>-.#%->;;;;;===;;;;;>-.#%->;;;;;===;;;;;>-.+@$&>>;;;;;;;;;;;=&...++#%*;;;;>**$@+...+#%=-->>*$#@..........++@&*=;;;;;*%#++.....++#%==;;;=*%#++......................", +"#&*;;;;;;;;;;>>>=&$.@#%*==>;;;;;;--=&%#.#%->;;;;;;;;;>==*%#.+#$*==;;;;;;;;;;=*$.@$*=;;;;;;;;;;;;;**.$&=;;;;;===>;;;;>>%.$%>>;;;>>***>>;;;>>.#%->;;;;>===;;;;;>-.$%->;;;;;-=-;;;;;>-.$%->;;;;;-=-;;;;;>>.+#$&>>;;;;;;;;;;;=&...++$&*;;;;;*&$@++..+@$==->>*&$@++.........+@%*=;;;;;*&$+......+@$%==;;;==&#@+......................", +"@%*->>;;-----;;;>-%.@$&>>;>>-----;;;=&$.#%*=;;;>>--->>;>>&$.@$&>>>;;-----;;;=&$.@$*=;;;--;;;--;;;=*.#&*;;;>-***==;;;==%.#%==;;;==&&*==;;;==.#&==;;;-=>->=-;;;==.#%*=;;;>>===>>;;;=*.#%*=;;;>>===>>;;;=*.+#%*>;;>>--->>;;;**...++#&=;;;=**$@+....+@#%**;;=*%#@.........+++#$&*=;;;*&#@.....++@$&>>;;;>>&$@++.....................", +"@$&=--;;-====;;;>>&.#%*;;;>>===--;;;=*%.#$*=;;;>>-=->>;;>*$.@$&>>;;;-----;;;=*#.@$*=;;;--;;;--;;;=*.#&*;;;--*&**=;;;==%.#%*=;;;==&&**=;;;=*.#%==;;;-=>>>-=;;;==.@$*=;;;>>===>>;;;=*.@$*=;;;>>===>>;;;=*.+@$&>;;>>--->>;;;*&....@#&*;;;=*%#@++....+@$&*;;==*$@++.........+@#%*=;;;*&#++.....@#%*>>;;;>>*%#+......................", +"+#%=--;;==*=*>>>>>&.#&=;;;-=****=;;;>-%.@$&*;;;--===--;;;*%.#$*;;;>>=====>>>**#.@#*=;;;==;;;==;;;=&.#&*;;;-=*%&*=;;;=*%.@$&=;;;==&%&==;;;**.#$*=;;;--;;;--;;;=*.+#%*=--;;;;>;;--=*$.+#%*=--;;=-=;;--=*%.+@$&->>-==-=;;--=*$....@#&*;;;**$@+......++#%*->>-=%#@...........+#$&=;;;*&#@....++@%*=;;===;;=&%@+.....................", +"@#%==-;;=***=-->>>*.$&=;;;==&&&**;;;>>&.@#&*;;;-====--;;>*%.@%&>;;>-=====>>>*&#.@#**;;;==;;;==;;;=&.#&*;;;==&%%&*;;;=*%.@#%*;;;==&&&==;;;*&.#%*=;;;--;;;--;;;=*.+@#%==-;;>>>;;-==%$.+@#%==-;;-=-;;-==%$.+@$%-->=-==-;;-==%#...++#&*;;;*&$@+.......+@#&->>>>*%#++.........+@$&*;;;*&$++....+@%&=;;-==;;**$@+.....................", +"+#$==-;;=***=->>>>&.$*=;;;==%$$&*;;;>>&.+#&*;;;--===--;;;&$.@$&>;;->=====>>>*&#.@#&*;;;==;;;==;;;*&.#%*;;;-=%$%&*;;;=*$.+#%*>;;==&&&==;;;*%.@$*=;;;--;;;--;;;=*.++#$*=-;;>>>;;-=*$#.++#$*=-;;=-=;;-=*$@..+#$==-=-==-;;-=*%@...+@#&*;;;*&$++.......++#$*=;;;*%$++..........@#&*;;;*&$++...++#%**;;===;;=&%@+.....................", +"+#$=--;;===*=>>>;>*.$*=;;;=&%##$*-->>>*.@#&*;;;>>-->;;>>>&$.@#%==-;;;;;->===&$@.+@#&*====;;;====*%$.#&*;;;==&$$**;;;=*$.+#$*>>>>-***-->;>*%.@%*=;;;>>;;;;;;;;=*..+@#%&=->;;;>>**%#@..++#%&*;;;;;;;*&$#@.++@#$&**=>;>;;**%#@...++$&*;;;*&#@.........+@$*=;;;=&$@+..........@$&*;;;*&#@....++@%*=--***--**%@+.....................", +"+#$==-;;=====>>>>>&.$*=;;;*&$##$&-->>>*.+#%*;;;>>>>>;;>>-%$.+#%*=-;;;;;>>===*$#.++##&&**=;;;=***&$@.#%*;;;-=%$%&*;;;=*%.+@$&->>>>=*=--;>>&$.@$*=;;;>>;;;;;;;;=*...+@$&*->;;;>-*&$@+..++@#%*;;;;;;;*%#@+...+@#$&*=>;;;;*&#@+...++$&*;;;*&$++........+@#%*>>>-=%#++........++#&=;;;*&$++....+@%%*==&&&==*&%@+.....................", +"+#$==-;;;;;;;;;;=*%.#*=;;;=*&$%%*->>>>&.@#&*;;;;;;;;;;==&%#.+#$&*===>>>;;;;;*%#..++@#$&*=;;;=*&$#@+.#&*;;;==&$$**;;;=*$.++#%==-;>=*=;;--=%#.@$*=;;;;;>->;;;;;=*..++@$&*>>;;;>>*&$@+....+@$&==;;;=*&$@+....+@#%&=-;;;==*%$#+....@$&*;;;=%$@..........+#$*>>>--&$@.........+@#&*;;;*&#@.....++@#$$$$#$$$$#@++.....................", +"+#$==-;;;;;;;;;;=*$.$&=;;;==&&&**;;;>-&.+#&*;;;;;;;;;;=*&$@.+#$&**==>>>;;;;;*%#..+++@#%&=;;;**$#@++.#%*;;;==%%%&*;;;=*$.++#$==-;;===;;-==%#.@$*=;;;;;->-;;;;;=*..+@#$&=>>;;;>>**$#@....+@#%*=;;;=*%#@+....++#%*--;;;=**&$#@...++#&*;;;*&#@..........+@$&>>;--&$@++........@#&*;;;*&$++.....+++@@@@@@@@@+++.......+.++.+.+++.+...", +"+#%==-;;;;;;;;;>*&#.#**;;;===**==;;;>-&.@#&*;;;;;;;;;;=*&$#.@#%**===>>>;;;;;*&#....++#$&=;;;=&$#++..#%*;;;==&%&*=;;;=*$..+@#*==;;===;;==*$@.@$&=;;;;;-->;;;;;=*.++@$&*=>>;;;>>=*&$@....++#%*=;;;**%#+....++@$%*->;;;==**&%#....@$&*;;;*&$++..........+@$**=;;*&$#++......++$&*;;;*&#@.......+++@+++++++++....+++@@+@+@+@++@++++.", +"+#%=--;;----==*&%#@.#%*>>>;;--->>;;;=*%.+$&*;;;---=-;;--=%$.#%*>>;=======;;;=*$....++#%&=;;;=*$#++..#%*;;;-=****=;;;=*$..++#%**;;==-;;=&%#+.+#&*;;;;;--=;;;;;*%.+@$%==-;;===;;--=%$....+@#%*=;;;=*$#++...+@#&*=;;>>>==;>>*%....+#&*;;;=&$@+...........+@$&*;;==&#@+.....++@$&=;;;*&$++..........++.++.......++@@####$###$$#$#@+.", +"@$&=--;;---==*%%#@+.@$*>>>;;->>>>;;;=*%.@$&=;;;--===;;--=&$.#&*;;;=======;;;=*$....+@$%*=;;;=*%#@+..#$*;;;-==**==;;;=*$...+@#&*;;---;;*%$@+.@#&*;;;;;=--;;;;;*&.@#%*-->;;=--;;>--*%....+@$&*=;;;=*%#@+..++#$*==;;>>>==;;>*&...++$&*;;;**$#++.........++@$&*;;==*$#+.....++#%&=;;;*&#@.......................@@$$%&&%&%&%&&%&$$#.", +"@$&>>;;;>>>==%$#@++.@#%->>;;>>>>>;;;=*%.@%==;;;>>===>>;;;=*.$*=;;;>>->>>>;;;=&$...++#%*--;;;-=*%#++.@$&=>>;;>>->>;;;*%#...++#%*->;;;>>*%#++.+#%*;;;;;===;;;;;*&.@$*=;;;;;-==;;;;;==....+#%*->;;;-=*%#++.++#&->>;;>>>>-;;;=*...++#&=;;;=*&#@+...........+@$*>;-==%$@.....+@#%*=;;;*&#@.......................@&&===--=-=-=---=*$.", +"@$*>>;;;>>>=*%#@++..+#%&==;;;;;;;---==$.#$==;;;>>=*=>>;;;=*.#*=;;;>>>->>>;;;**#....@$%*>>;;;--*%$@+.+#%=--;;>>>>>;;>*%#...++#$*->;;;>>*%#+..@#%*;;;;;===;;;;;*%.#%=-;;;;;-=-;;;;;==..++@$&*>>;;;--*%$@+.+@$&>>;;;>>>>>;;;=*....@#&*;;;>-*%#++..........+@$%=-;;>&$@....++#%*->;;;*&#++......................#**--->>---->>>>-=%.", +"#$*>>;;;>>>=*%@++...+@$&*=;;;;;;;---==%.#$==;;;>>=**>>;;;=*.$&=;;;>>>>>>>;;;*&#..++@$&*->;;;>-*&$@+.+#$==-;;>>>>>;;>&$#....+@#&->;;;>-&$@+..+#$*>;;;;=*=;;;;>*$.#%==;;;;;===;;;;;==...+@$&*>>;;;>-**$@+.+@$&>>;;;>>>>>;;;=&...++#&*;;;>>*&$@+..........++#%==;;;*%#....+@$&*->;;;*&$+.......................$*=-->>>>>>->>>>-=&.", +"@%*>;;;>;;;=*$@+....+@$*=-;;;;;;;;;;-=$.#$=-;;;;>****=;;;==.#&*>>>>;;;;;;--=&$#...++$**>;;;;;>=*%@+.++#$**>>;;;;;-==%#@....++#%==;;;==%#++..+@$&-->>-***>>>--&$.#$=-;;;;;===;;;;;==..++#%*=;;;;;;;**%@+.++#%-->;;;;;;;;;>*&...++#%*;;;>>=*%@++..........+@$**;;;=&#...++@%&=>>;;;*%#++......................$==;;;;;;;;;;;;;;>&.", +"@$&>>>>>>>>=*#@+....+@#*==;;;;;;;;;;==%.@#==>>>>>&%%**>>>==.#%&-->>>;;;>>==*%#+...+@#%*>>;;;>>*&%@+..+@#$*>>;;;;>==*$@+.....+@$*=>>>=*$@++...+#$=--=-&&&=---=$#.@$*=;;;;>*=*>>;;>==...+@%&*>>;;;;>**$@+.++#$=--;;;;;;;;>>*%....+#%*>;;;;=*&@+...........+@#%*;;;*&#...++#&*=>;;;;*&#++......................$=->;;;;;;;;;;;;;>&.", +"@#$&&****&&%$@+......@#*==;;;;;;;;;;==$.@#$%&**&%$$$$%&&&%$.+#$%&&*******&%$#@+...++@#%&&****&%$@++..++@#$&&****&&%$#++.....++#$%&&&%$#++...++@#$%&%%$$$%%%%$#@.@#$&&***&&%&&&**&%$...++@$%&*****&%##++..+@#$&&********&&%#...++#$&>>>;>=*%#++...........+#%&;;;*%#...++@&*=>;;;>*$#+.......................$*=>>;;;;;;;;;;;>>%.", +"+@@$$$%%%$$#@++......+@#%&===*=====*&$#.++#$$$%$$#@@##$$$#@.+@@$$$$$%%$%$$#@+++....++@#$$%%%$$#@@.....+++##$$%%%$##@@+......+++##$$$##@+.....++@#####@@@##$##@+.+@##$$%$$##$$$%$$$#....++@#$$%%%%$#@++...++@##$$%%%&%%%$$#@....+@#&->>>>**%@++...........+@#%***%#@...++@%&*>>>>>%$@+.......................#$%&************&%$.", +".++@#@#@#@@@++.......++##%**&&**=***%#@..++@@@#@@+++++@@@@+..+++@@##@##@@@@++.......+++@@##@#@++.+......++@@@#@#@@@+..........++@@@@@++.......+++@@@++@++@+@+++..++@@#@#@@@@@@##@@+...+.++@@@##@@@@++.....+++@#@######@#@++.....+@$%&&&&%##++.............+##&&&##+....+@#$%&**&%$#++.......................@##$$%%%&%&%%&%%%##.", +".+.+++++++++.........+++@#%&$$%&&&%%#@+...+++++++++.+.++++....++++++++++++..+.........++++++++++........+.++++++++.+............++++...............++..+++.+.....+++++++++++++++++........+++++++++.........+.++++++@++++.......++@#$$%$#@@+..............++@$$$@++......@@#$$$%##++........................++@@##########@#@@+.", +"..........................................++++++..........................................++++++................................++++++++++.......................+++++++...................++++++................+.+++........++++++.................++++++++...................................................................", +".......++++++............................+@@@#@@++.......................................++@#@@@++.............................++@@#####@++......................+@@##@@++................++@@@+@+..............++@@@@++....+++@#@@@+..............+++@@###@++..................................................................", +"......++@##@@+..........................+@#$%$$#@@+....................................++@#$$$$#@++..........................++@@$$%%&%%$#@.....................+@#$$$$$@++..............++#$$$$#@+............+@#$$$$@@+...+@#$$%$#@++............+@@$$%%$$#@+.................................................................", +".....+@@$$$$#@+.........................@#%&&**%$@++...................................+@#$&&*&%$@+..........................++#$%******&%#.....................@#%&**&%$@++............++#$%&&%$#++..........++#$&&&&$#++..@#$&&*&%$@+..........+++#$%&***&$#++................................................................", +"....++@%&===$#@+........................@$=>;;;=&$@+..................................++#%*;;>>>%$@.........................++#$&>>>;;;;;&%.....................@$=-;;;=*#@+............+@$==;;;&$@+..........+@$%;;;==$@+..@%&;;;>-%#@+..........+@%*=;;;;>&$@+................................................................", +".....@$&*=-=&%#++.........+..++.........#%->;;;=*$#++................++.++............+@$&*;;>>>&$@........+...+.+.........++@$&*>>;;;;;;&%.........+.+.+.+.....#$->;;;=*$#++..........++#$==;;;&$#++........++#$*;;;==$#++.@%*;;;>>&$@+++........+@&*=;;;;;*%#++.....+...+.+...+..........+.++.+.++..............+...+.........", +"...++@$*=;;;=&$@+.......++++++@+++......#$*=;;;==&$@@++.........+++++@+@+++++.......+++@$%*->;;;*%@......+.++@++++++.......+@#%=-;;;---==&$......+++@+@+@+@+++..#$*=;;;-=&$@@++........++#%==;;;*%#+.........+#$&*;;;-=%#++.@$&-->;>*%#@++++.+...+.@#$*==;;;*%#++....++++@+@+@@+@+++......++++++++++@++.........+.+@@++@+++.....", +"....+@$==;;;=*$@+......++@@#####@@++....@$*=;;;-=&%$#@@@++....+++@####$#$##@+++...+++@##%**->;;;*%#.....++@###$###@+++....+@#$&--;;;--===%#...+++@@##$######@@+.#$*=;;;-=*%$#@+++......+@$%=-;;;*%#+.......++@#$**;;;==%#@..@$&=>-;;*&$$###++.....++@$&=-;;;*&$+....++@#####$######@++...+@@#########@@++.....+++@@##$###@+++...", +"....+@$*=;;;=*&#++....++##$%%&%%$#@@+...@$&=;;;--**&%$$#@++.+.+@#$$%%&%&%%%$#@+..++@#$$&&*=->;;;*%#..+++@#$$%%&%%%$#@++...+@$&*->;;;---=*%#..++@#$$%%%&&&&%%$#@.@$&=>;;--**&%$$@++....++@$&=-;;;*%#+......++@#%&*=;;;-=%#@..+$%=->;;**&%$$$#@++....+@#%==;;;*&#@+...@#$$%&&&%&&&%%$$@@..+@#$$%%%%%%%$$#@@+...++@#$$%%%%%$$#@++..", +"....+@#&*>>>>>%#@....++#%&*=====*&$#++..@#&*;;;>>---==%%##+.+@@$$&===-=-====$#+.+@@$%%==--->>;;;*&#...@@$%%====-==&%$#+.++@$*==>>;;;>>-==%#.+@@$%&===-===-==*&#.@#&*;;;>>--===%$#@+...+@$&*-->>-*%#@......+@#*==-->>>-=&$@+.+#%==-;;=**====*#@+.....+@$&=;;;*&#+....#&*====--===-==%$#+.@#&*====*=====%$#@+.+@@$%%===--==&%$#++.", +".....+@$&->>>-&#@+..++#$&*=-->--=*&$@@..+#&*;;;>>->-==**%$@.+@$%**==->----==&%@.+@$%**==->->>;;;*&#.++#$%**==>----**%$@.++#%==-;;;;;>--==%#.+@$%&*==-->-----=*$.+#&*;;;->>->==*&$#@...+@$&*->>--*%@+.....++#$*==>->>--=&$@+.+#%==-;;===--==*%#+.....+@$&*;;;*&$@....$*===---->-----*&$@.#$*=---==->-==*%$#@.+@$%**==-----**%$@@.", +".....++#$%**--%#++..++#%>>>;;;;;;;*&$@+.@#&*;;;;;;;;;;>>>%$.@$%>>>;;;;;;;;;;*&#.@$%>>>;;;;;;;;;;*%#..@#%>>>;;;;;;;>>>%$..@@%->>;;;;;;;>>-%#.@$%>>>;;;;;;;;;;--%.@#&*;;;;;;;;;;-==$@..++@&*=;;;;;*%#@+.....@#%->>;;;;;;;*%#+.+@$==-;;---;;>>-%#+.....++$&*;;;*&#++...%=-;;;;;;;;;;;;>-%#.#%--;;;;;;;;;;-==$#.@$%>>>;;;;;;;>>>&#@.", +".....+++#$%&==%#++..+@#&>>>;;;;;;;=*%@@.+#%*;;;;;;;;;;;>>&$.@$&>>;;;;;;;;;;;=*$.@$&>>;;;;;;;;;;;*&#.+#$&>>;;;;;;;;;>>*$.++#%->>;;;;;;;>>-%#.@$&>>;;;;;;;;;;;>-%.+#%*;;;;;;;;;;--=%#..++#&*=;;;;;*&#@.....++#%->>;;;;;;;*%#+.+#$==-;;---;;>>-%#@......@#&*;;;*&$++...%->;;;;;;;;;;;;>>&$.#%->;;;;;;;;;;--=%#.@$&>>;;;;;;;;;>>&$@.", +".......++@#$=*#@+...+@$&>>;;;;;;;;=*&#+.+#&*;;;;;;;;;;;>>*%.#%*>>;;;;;;;;;;;=*$.#%*>;;;;;;;;;;;;*%#.+#&*>;;;;;;;;;;>>*%.++#$-->;;;;;;;>--$#.#%*>;;;;;;;;;;;;--%.+#&*;;;;;;;;;;>-=&$...+@%*=;;;;;*&#+.....++#$=->;;;;;;;*%#+.+#$==-;;-->;;>>-$#+.....+@$&*;;;*&#@....%=>;;;;;;;;;;;;>>&$.#%=>;;;;;;;;;;>--&$.#%*>;;;;;;;;;;;>*&#.", +".......+++@@###++....@$&==->>>>>;;-=*$@.+#&*;;;;;===--;;;=&.$&=;;;--====-;;;=&$.$&=;;;--===;;;;;*&#.+$&=;;;--===>-;;;=&..+@#&*=->;;;=**&%#@.$**;;;--===>;;;;=&%.+#&*;;;;;===>>;;;&$...++@$&*=;;;*&$@......+@#$&&**===;;*&#@.+#$==-;;;;;>-=&%$@+......+$&*;;;*&$++...$*=;;;>>>>>>>>>>>*$.#$*=;;;;>===->;;>&$.#**;;;--===--;;;=&$.", +".........+++@@++....+@$&===>>>>>;;-==$@.+#&*;;;;>=*=--;;;=*.$&=;;;-=***=-;;;*&#.$&=;;;-==*=>>;;;*%#.@$&=;;;->===->;;;=*...@@$&*->;;>=*&%#@+.#*=;;;-==*=;;;;>=&$.+#&*;;;;>===->;;;*%....+@$%*=;;;*&#@+.....++@#$%&&===;;*&#+.+#$==-;;;;;--*&$#++.....+@#&*;;;=%$@....$&*;;;>>>>>>>>>>>&%.@$&*;;;;>=*=->;;;*%.$*=;;;-=***--;;;=&$.", +"..........+.++.+....+@%&>;;;;;;;;;-==$#.+#%*;;;--***==;;;=*.$*=;;;=**&&&*===*%#.$*=;;;==**==-;;;*&#.@$*=;;;;;;;;;;;;;=*...++#%*>>>>>*&$#@++.$*=;;;=***==-;;;*&$.+#%*;;;--***=-;;;*%....++@%&=;;;*&$+.......+++@##%**=;;*&#+.+#$==-;;;;;-=*%#@+.......@$&*;;;*&#@....$&*;;;-->>>>>>>>>*%.@#&*;;;-==**--;;;*%.$*=;;;=*****=;;;=*$.", +"....................+#%*>;;;;;;;;;-==$#.@#&*;;;-==***=;;;=*.$*=;;;=*&$%%&===&$@.$*=;;;=****--;;;*%#.@$*=;;;;;;;;;;;;;=*...++#%&->>>>*%$@++..$*=;;;=****--;;;*&#.+#&*;;;-=***=-;;;*%.....+@$&*;;;*&$@+........++@@#**=;;*&#@.+#$=--;;;;;==&%#+++.....++$&=;;;*&$@+...#&*;;;>->>>>>>>>>*%.+#&*;;;-=***=-;;;*%.$*=;;;=*&&&*=;;;=*$.", +"....................+#&*;;;;;;;;;;-==%#.+#&*;;;--***==;;;=*.$*=;;;=*&%$%%*=*%$#.$*=;;;==***--;;;*&#.@%*=;;;;;;;;;;;;;=&...++@%*>>>>>*&#@++..#**;;;>-===;;;;;*%#.+#&*;;;-=***=-;;;*&...+++#$*=;;;=&$@++.........++#%*=;;*&#+.+#%==-;;;;;==*%$@+.....++@$&*;;;=&$@++..#&*;;;-->>>>>>>>>*$.+#&*;;;-=***=-;;;*&.$*=;;;=**&**=;;;=*$.", +"....................@#*=;;;=====;;-==%#.+$&*;;;;>==*--;;;=*.$&=;;;-=*&%&&===*&#.$&=;;;--*==;;;;;*&$.@$*=;;;>>--->->>>*&...+@#%*>>>>>*&$#@++.#$*>>>;;;;;;;;;;*&#.+$&*;;;-=*&*==;;;*&....+@#%&=;;;**%#@++.......++@#&*=;;*%#@.@#%=--;;>>>;;=*&#@+....+@#%*=;;;**%$@++.$%=;;;>->>>>>>>>>*&.@$&*;;;-=***=-;;;*&.$&=;;;--***--;;;=*$.", +"....................@$*=;;;=====;;--=%$.@$&*;;;;;=*=->;;;**.#**;;;>-*****====*#.#**;;;>-===;;;;;*&$.@#*=;;;>>---->>>>*&..++#$&*>>>>>=*&$$@+.@$%->>;;;;;;;;;;*%#.@$&=;;;-=***=-;;;*&..++@#%&*=;;;=**%#@@.....+++@@$&*=;;*&#+.@#&==-;;>>>;;=**%#@..++@$%&*=;;;=*&%#@+.$&*;;;-->>>>>>>;>*&.@$&=;;;--***--;;;**.#**;;;--=*=->;;;**#.", +"....................@#&=;;;=====;;--=&$.@%&=;;;;;===->;;;*&.#**;;;>-==*==-===*$.#**;;;>-===;;;;;=&$.@#&*;;;>>----->>>*%..+@$%*=>>>>>==*&%#@.+#$&*==---->>;;;*&#.@$&=;;;===*===;;;=&.++@#%**==;;;==*&%#@....+++##$&*==;;*&#+.@$&=--;;>>>;;===&%#..+@#%&*==;;;==*&%#@.$&=;;;>->>>>>>>;>=&.@$**;;;-==*==-;;;=&.#**;;;>-===>>;;;*&#.", +"....................@#&*;;;;;;;;;;;;;*%.@%=-;;;;;;;;;;>>>*%.#$*>>>;;;;;;;;;;-=$.#$*>>>;;;;;;;;;;--%.+#%*>>>;;;;;;;;;;*&.++#$->>;;;;;;;>>-$@.++#$&*==--->-;;;*%#.#$=-;;;;;===;;;;;--..+#$=>>;;;;;;;>>-$@....+@#$%&*===;;*%#@.#&*;;;;>==-;;;;;-=$..+@$->>;;;;;;;>>-$@.%=-;;;;;>>;;>>>;;-=.@$=-;;;;;===;;;;;--.@%*>>>;;;;;;;>>>*%@.", +"....................+#&*;;;;;;;;;;;;;*%.#$=-;;;;;;;;;;>>-%$.@$%->>;;;;;;;;;;-=$.@$%->>;;;;;;;;;;-=$.+@#%->>;;;;;;;;;;*%.++#%->>;;;;;;;>>-$#..+@$&*-->>>;;>>>&$@.#$--;;;;;===;;;;;-=.+@@$->>;;;;;;;>>-$@..++@#**===>>>;>*%#+.@&*;;;>>===;;;;;-=$.++#$->>;;;;;;;>>-$#.$--;;;;>>>;;>>>;;-=.#$--;;;;;*==;;;;;-=.@#%->>;;;;;;;>>-%$@.", +"....................+@$&*===-=-=-=-==%$.@$*=======-===**%$@.+#$%**==========&%#.+#$%**===-===-===&$..+#$%**==-=-====*%#.++@$*===----===**$@.++@$&*->->>;;>>>%$@.@$*==--==***=-====&..+#$&*===--====**$@..++#%===->;;;;>&$@+.@$&====****==--=*&$..+@$&*===--====**$@.$*==--=====-======&.@$**==-==***=-====&.+#$%**=======**%$@+.", +"....................++#$***========**$#.+#%**========*%%##+.++@#%&*======**&%#@.++@#%&*=====*==**%#.+++@#%&*======**%$#.++@#**========*&%#@.++#&*=;;;;;;>=*&$@+.+#%*====*&%&====**%...@#%**=======**%#@..++#%=>>;;;;;=*%#@+.+#%*==**%%&*====&%#.++@#&**=======**%#@.#%*====***==*=*==*%.@#%*=====&&&====**%.++@#%&*=====*%%##++.", +"....................+++@%%&********&&#+.+@$%&*&&&**&*&$#@++..+@@#$&&*****&&%#@+..+@@#$&&*&*****&%$@...+@@#$&&***&*%$$@+..+@@%&&**=*=**&%$@+.++@%*=>;;;;>>*&%#@+.+@$%****&$$$&***&%$..++@$%%&*****&%%$@+..++#%->>;;;;;=*$#+..+@#***&%$#$&****%$@...+@$%%*&****&%%$@+.@$%***&&&***&&&**$$.+@$%&&***$#$&****%$.+++@#$&&***&*$#@++..", +"......................++@####$#$#$##@@+.++@###$#$#$###@+++.....++@####$####@@++....++@####$######@+.....++@####$####+++...+@@#$#$$$$###@++...+@%**>>;;;>-&$#++..+@@#$$$##@@###$###@...+++#####$#$##@++...++#$=->;;;>>*%#@.+.++@####@@@@##$$##@+...++@@##$$#$$##@++..+@###$####$#$#####@.++@###$##@#######@@...+++@######@@+++...", +"......................+.++@@@@@@@@@@++....++@+@@@@@+@+++.......++++@@@@@@++++......++++@@@@@@@@+++......++++@@@@@+++++.....+++@@@@#@@@@+++..+++@$%&****&&$#@++...+++@@@@++++@@@@+++...++++@@@@@@@@+++++...+@#%&&***&&%#@+.....++@+@++++@@@@++++.....++@+@@@@@@+@++..+++@@@@@+@@@@@@++++..+++@@@@@+++@@@@+++....++++@@@@@+++.....", +"................................................................................................................................................................................................................................................................................................................................", +".....................................................................................+.+............................................................................................................................................+++++@+............++++++.+.........+++++++.................................................", +".....................................................................................++++++........................................................................................................................................++@@##@@++.........++@###@+.........+++###@@++...............................................", +"...................................................................................++@@#@++.......................................................................................................................................++@#$**$#@+.........+@#&&&#@+........+@#$**$#@++..............................................", +".................................................................................+++##$$$#@++....................................................................................................................................++#$$&*=%$#++.......++#$*=*$#++......++#$%*=%%$#++.............................................", +".....+....+...................+..................+.+..............................+#%**-=%#@+..................................+.......................................+....+.............+..................+..+................+#$%**==%$#+........+@$&===&$@+.......+#$&==*&&$@++............................................", +"..++++@+@+++@++.........+++++++@++++++......+++++++++++++.........+++++@+++++...++@$&*=--&$#@+++.......+++++...++++++.....+++++++++++++@+++...++++++++.+++++++.....+++++++++++++++....+++++++..++++@+++....++++++@@+@+++........+@$%>>>--%#@+........+#$*;;;*$#+.......+@#%=->>>%$@+............................................", +".++@@########@@@+......++@@#########@++...+++@##@#@@###@@++.....+++@#######@+++..+#$==-;;*&%##@++....+@@@#@@++++@@#@+++..++@####@@@@#####@+..++@@##@@+++@#@##@@...++@###@@@@@###@++..++@#@#@@@++@#@#@@@..+++@#########@@+.......+@$*>>>--%#@+.......++#%*;;;*%#++......++#%-->>>*$@+............................................", +"+@#$$%%%&%%%%$$#@++.+++@#$$%%&%&%%%%$#@..++##$$%$%$%$%%$$#@....++@#$$%%%%%$$#@+.+@#%==-;;=**%$$@++..+@#$$$$##@##$$$$#@+.+@#$%%%%$$$$$%%%$$#.+@#$%$%$$####$%$$$#.++@#$%%%$$$$$%%%$#@.+@#$$%$$#####$$%$$#..+##$%%&%&%%%$$##++....++#%*;;;=&%@+........++#&*;;;*&#+.......++#%&=;;;*%#@............................................", +"@#%&*********&&$$@+.++@$$%**********&$#..+@#%&***&*****&%$#...++@$%&*******&%$@.+#$*=--;;===*&%$#++.@#$&**&%$$$$&&*&%$@.@#$&*****&&&*****&%.@#%&***&%%$$&&***&$.+@#%%****&&&****&%#.@#$&***&%$$$&&***&$.+@$%&*********&%$@+....++#%*;;;**$@++.......++#&*;;;*&#@........+@$&*;;;*&#++........++++++++.+++.......................", +"#$=-;;;>;;;;;>==*$@.+@$*==>;;;;;>;;;-=$.++#%->>;;---;;;>>%$...+@%&*>;;;;>>>>>%#.+#%*;;;;;;;;;;**%@+.#$=-;;;=*%%&;;>>>%$.#$=-;;;;;===;;;;;-=.#$=-;;;>-*&*->;;;-=.+@%*;;;;;===;;;;;*%.#$=-;;;>-&&&->;;;-=.@#%>>>;;;;;;;>>-%#+....++$&*;;;*&$@+........++$&*;;;*&$++.......+@$**;;;*&#+......+++@@@#@@@@@@@@++.....................", +"#%--;;;;;;;;;;==*%#.+#$===;;;;;;;;;;>-%.+@#%>>>;;>->;;;;>&$..+@#&*=;;;;;;;>>>&$.@#**;;;;;;;;;;=*&@+.#%=>;;;=*&&*;;>>>&$.#%->;;;;;===;;;;;--.#%--;;;>>*=*>>;;;--.+#%*;;;;;===;;;;;*%.#%--;;;>>***>>;;;--.@$&>>>;;;;;;;>>>%$+.....@#&*;;;*&#++........++#&*;;;*&#++........+#&*;;;*&$@......+@##$%$%$$$$$$##+.....................", +"#%=>;;;;;;;;;;--=&$.@$&==-;;;;;;;;;;>=%..@#%>>>;;>>-;;;;>*$..+@$**=;;;;;;;;>>&$.+#&=;;;;;;;;;;=&%@+.#%->;;;==***;;;>>*$.#%=-;;;;;==-;;;;;>=.#%->;;;>>===>>;;;>-.+#%*;;;;;-=-;;;;;*%.#%--;;;>>=**>>;;;>=.@$&>>;;;;;;;;;>>%#@...++#%*=;;;*&#@..........@$&*;;;*&#@........++#&*;;;=*$#@...++@#$%&***&&&&&&%$#.....................", +"@%*=;;;;;>-->;;;;*%.#$*;;;;;->-;;;;;=*%.++#%*=-;;;;;-->>>*%.+@#%>>;;;->-;;;;;*%.+#$*>>>;;---==&%#@+.@%*=;;;-=&**>>;;;*%.@%*=;;;>>===>>;;;=*.#%=-;;;-=;;;--;;;==.+@$&=->;;=-=;;>-=&$.#$*=;;;>-===>>;;;=*.#$&>;;>>>>>;;-==%#+....+#%==;;;*&#++........++#&=;;;*&$++.......++$&*;;;==%#++..++#%==-;;>>>==>>>&%.....................", +"@%*=;;;;;--->;;;;*%.#&*;;;;;---;;;;;=*%..+@$*==;;;;;-->>-&$..@#%->;;;>->;;;;>&$.+@$&->>;;--==*%#@++.@$*=;;;==*&*->;;;*%.@$*=;;;>>===>>;;;=*.#$==;;;--;;;--;;;=*.++#%==-;;-=-;;--=%#.@$*=;;;>>=*=>>;;;=*.@$&>;;>>>>>;;-=*$#+...+@$%>>;;;*&#@..........@#&*;;;=%$@.........@#&*;;;>>&$@+..+@$&=->;;>>>==;;>*%.....................", +"@$&*;;;>-=*===;;;=*.$&=;;;=====>>;;;*&$..++#%*=;;--=***&%$#.++#%=--;;;;;---==&$.+@#&=--;;=**&$#@++..@$&*;;;==&&*=-;;;*%.+#$*-->;;===;;>-=&%.@$**;;;>>;;;>-;;;=&..+@#%*=->;;;>>**%$@.+#$*-->;;===;;>-=*%.+#%*==--;;;>-=*%#@+...++$&>>;;;*&#@.........++#&*;;;*&#@........++$&*;;;>>&#@+..+#&*;;;>>;;;;;;>>*$.....................", +"@$&*;;;>-=**==;;;=*.$*=;;;==**=--;;;=%$...+@$&*;;-==*&%$##+.++#%==-;;;;;>--==&#.++#%==-;;=*%$##+++..@#&*;;;==&&&==;;;*&.+@$&=->>;===>;--=&$.@#&*;;;->;;;--;;;*&..++#$&*->;;;>-*&$#+.+@$&=->;;===;;>--&$.+#$*==--;;;>-*&%#++...+@#&>>;;;*&#++.........@$&*;;;*%$++.......++#&*;;;>>&$++..+#&*;;;>>;;;;;;>>&$.....................", +"+#&*;;;>======;;;**.#*=;;;==*==>>;;;*%#...@@%&=;;-==&$##@++.+@#%=--;;;;;->-==&$.++#$=--;;**&$$#@@++.+#&*;;;==***=-;;;*&.++#$=-->>===;;--=$#.@#&*;;;>>;;;>-;;;*%..++@$&*->;;;>>*&$@+..+@#&==;;-->;;=*&$@.+@$**=--;;;->*&$#++....+#%*=;;;*&$+.........++#&*;;;*&$++.......++$&*;;;=*%#++..+#%*;;;--;;;;;>>>%$.....................", +"+#%*;;;;;-=-;;;;;*&.#&*;;;;;---;;;;;*&#..++#%&=;;==*&$#@@++..@#%==--->>>;;;>>&%..+#$*=-;;=*&&%$$#@+.@#%*;;;-=***=-;;;*&..+@$&*=;;===;;=*%#@.+#%*;;;;;;;;;;;;;*%..++#$&*>>;;;>>**$#+..+@#%*=;;>--;;=*%#+.+#$*==;;>>>-===*$@+....+@#&*;;;*&#@.........++$&*;;;*&$++.......++$&*;;;*&$@+...+@$%===*=======**$@.....................", +"+#&*;;;;;>>>;;;;;*$.#$*;;;;;>->;;;;;*&#..+@#%*=;;===&%$#++..+@#%==--->>>;;;>>*%.++@$==-;;==***&&$#@.+#%*;;;-====--;;;*&..++#%*=;;=--;;*&$@+.+@%*>;;;;;;;;;;;>*%..+@#&*=>>;;;>>=*%$@...+@#&*>>;;;>>*&$@+.+#$*==;;>>>====*%#@....+@#&*;;;*&$++........++#&*;;;*&#++.......++$&*;;;*&$++...++@#&**%%&***=&&%#@.....................", +"+#&*;;;;;;;;>>===%#.@#%===;;;;;;>;;;*%#.++#%==-;;>--==%$#++.+@$&>;;;;>>>>>;;;=&..+@$*==;;--->>>--$#.+#%*>>;;;-=-;;;;;=*...+@#&*>>;;;>>*%#@+.+@$&-->;;-=-;;>--&$.++#%=->;;-=-;;>-=%#....@#%*>>;;;>>*%#++.@#&->>;;>>>>>;;>&$@....++$&*;;;=&$@+........++$&*;;;*&#@........++$&=;;;*&#@.....+@@##$$$$$$%$$#@@+.....................", +"+#&*;;;;;;;;>>=**#@.+@$&==>;;;;;;;;;=%$..@#%=->;;>>--=*%$@+.+#$*>;;;;>>>>>;;;*&..+@#&==;;>>>;;>--%#.+@$&>>>;;---;;;;;=*...++@%&>>;;;>>*$#+..+@#&=->;;=-=;;--=&#.+@#&->>;;=-=;;>>-%$....+@%&>>;;;>-&$@++.@$&>>;;;>>>>>;;>&$@....++$&*;;;*&$@+........++#&*;;;*&#++.......+@$&*;;;*&#++.....++@@@+@@@@@@@+++......................", +"@$&*;;;>-===*&&%##+.+@@$$&**===--;;;*&#.+@$&=->;;>>---*&$@+.+@$&>;;;;->>>>;;;*&...+#&*=;;>->;;>>-$#.++#%>>>;;---;;;;;==...++@$%->;;;>-&$@+...+#%==-;;===;;--=%#.+@$&->>;;==-;;>>-&$..++@$%*>>;;;*&$@++..@$&>>;;;>>>>>;;>*$@.....+#&*;;;=*$@+........++#%*>;;*%#+.......++@$*=;;;*%#@.........+++.+++++++........................", +"@$&=>;;>-=**&%$#@++..++@#$%&**=--;;;**$.+@$*;;;;;;;;;;=&%@+.+@$&->>>>;;;;;--=&$..++@#%*--;;;;>==*$@.++#$%*=;;;;;>>;;;==....++#%*=;;;=*$#+...++@#*==>>=*=>>=**$@.@@%*>;;;;===;;;;;*%.+@#$**=>>;;>*%#++...@#&->>;;;;;;;>>-&$@....++#%*;;;=*%#@+........+#$*>>>*$#++......++#%*=;;;*%#+...............+............................", +"@$&=;;;--=**%$@+++....++@@#%**=->;;;=&$.+@%&>;;;;;;;;;*&%@+.++#%-->>>;;;;;===$#...++@$%==;;;>>=*&#@..++#$%&>;;;;>>;;;==.....+@#&*>>>*&#@+....++#%**--&&&--**&@@.+@$&;;;;>===>;;;;&$.+@%&;;;;;;;;*%#+....+#%-->;;;;;;;>>-%#@.....+@$&;;;=*%#@++.......+@$%>>>%$@+.......+@#&*=;;;&%@++...........................................", +"@%=-;;;;;>-=$#@+........+@#$=->;;;;;-=%.++#$%********&%$@+..++@#$&&&******&%$#@....++@#%&&**&&%$#@+...+@@$%&*********%$.....++@#%%&%$$@++....+++##%$%$%$%%$$#++.+@#$&&**&&%&&**&&$#.+@$*;;;;;;;;*%#++...+@#$&********&&%#@+.....+@$%===>>&%#+.........+#$%%%$@++......++#%&->===%$@+............................................", +"@$--;;;;;--=$@++.........+#$=->;;;;;--$..+@#$$%&&%%%$$#@@+...++@#$$$%%%%%$$##@+.....++@#$$%%$$##@++....++@#$$%%%%%%$$$@......++@#$$$#@++......++@@###@#@##@@+++..+@#$$%$$$$$$%%$$#@.++#%*=======$#@.....++@#$$%&&&&%%%$#@++......+@#***--&$#++.......+++@#$#@@+........+#$&-==*&$@+.............................................", +"#$**----==*&#@+..........+@#&*==----**$..+++@########@@++.....+++@@#@#####@@++.....+.+++@@#@#@@++.......+++@@#######@@+.......++++@@+++..........++++++++++++....+++@@##@@@@@@##@++..+@#**=*=***#@++.....++@@@#######@@+++.......++##%%%$#@++..........++@+@++........+++##$%%$##++.............................................", +"+@$%**=**&%$++...........++@$%&*=***&$@...+++++++@+++++........+.++++++++++...........+.++++++............+++++++++++++........++++++.............+++.+.+++........++++++++++++++....++@#$$$%$$#@+.........+++++++++++++........+.++@@###@@++............++.+..........+++#@###@++..............................................", +"................................................+.+++.+.................+................................+......+..+...............................++++@++++....................................................................................................................................................................", +"................................................+++@@++............++++++++............................+++@+++.+++++++..........+.++.............+++@######@@++...........................+++++++...............+++++........................................................................+.++++++...............+...........", +".......@@@@@...................................+@#####++.........++@@###@@++..........................+@@###@@@@@##@@++........+++@@++..........++##$$%%%%$$#@+............+.+.........+.++@@@@@@+++..........+++@@@@++......................................................................++@@##@@++...........++++++++......", +"......@@$$$$@@.................................@#$%&%$#@+.......++@#$$$%$$#@++.......+..........+....+@#$$%%$$#$$$%$$#@......+.@#####@+........++@$%&*****&&$$@.......++++++++@++......++@##$$$$##@++........+@@#$#$##@++..................................................................++@##$$$$##@@+.......++@@####@@++....", +"...++$$$$$$%$$++.............................++#$&>>>&$#@.....+.@@$&*====*%#@+....+.+++++.+.+++++...+@#%====*&%&*===*$#.......@@$%&%$@++.......+#$%--;;;;;>>-%#....+++@@#@@#@#@@++....+@@$$**==&&$$@@+.....+++#%&***&%#@+.................................................................+@@$$&*==&&$##@+.....++@$$%%%%$##++...", +"..@$%%=====-=%%$..+.........................++@$&*;;;*&$#@+...++@$%*======&%#@+...++@@@@@+@@@@@@@++.+@$&=--=-***=====&$......+@$%>>>&$@+.....++@#%*->;;;;;>>-&$.....+@##$$#$$$$#@+...++#$%**====**%$#++....++@$&*===**%#++...............................................................+@#$&&=====**%$#@+...++@$%&****&%$#@+..", +".@%&&==>>>>>>=&&%@@.............+...........+@#%==;;;==&$#+...+@$&*;;;;;;;=*%@+..++#%&&$$#$#$$&%%@@.+#&*;;;;;===;;;;;*&......+#%&>>>*$#+.....++#&*=;;>->>>;;>&$...++@$&&==%%%>>$#@..++#$==-;;;;;;-==$@@....+@#%->-->;;&$@+..............................+..+.+.+........................++@$==-;;;;;;-==$@+...++#%->;;;;;**%@++.", +".@%*=>;;;;;;;;=*%@.........++++++.........++@#%*=-;;;==*&$@..++#$*=;;;;;;;=*&#+.++@#&**&&&%&&&**&$@.@#&=;;;;;-=-;;;;;*&.....++#%*;;;*%#++....+@$*==;;>>>>>;;;&$....+@%&*=-%&&>>%#@+.+@#%=--;;;;;;--=%$@...++@$&->->>;;*%#+.........++++.+++++......+++@++@@+@++++.......................+@$%=--;;;;;;--=%$@...++$%>>;;;;;=*&@+..", +".#&*>;;;;;;;;;>*&#.........++@@@+++.......+@#%&*--;;;-==&%#..++#&*=;;;;;;;=*%@+.++#%*==**=**=*==*%#.+#&*;;;;;-=-;;;;;*&.....++#&*;;;*&#+....++#%*=-;;>>>>>;;>&$....+@$&*==%&&>>%#++.+#%*=>-;;;;;;>--&%#...+@#%*>>>>>;;*%#++.....++++@@@@@@@@@++..++@@###########@@+.....................+#$*=>>;;;;;;>--&%#...+@#%>>;;;;;=*%@@..", +".$&=>;;;;;;;;;>=&$.......++@#$$$$@+......++#$=--;;;;;;;==*#..+@$*=-;;=====*&$@+.+@$&>>>;;;;;;;>>>%$.+@%&-->;;===;;>>-*$.....++#&*;;;*&#@....+@#&=->;;>>>==-==&#...++@$$%&&%$%**$#@..@#**;;;;;;;;;;;;=&$...+@%&=>>>;>;;*%$@......+@#$#$$$$$$$#@@..+@#$$%%&%&%&%%%$#@.....................@#**;;;;;;;;;;;;=&#....+#%*======*&$@++.", +".$*=>;;;;;;;;;>=*$.......++#$%&&$#++.....+@$%=--;;;;;;;-=*$..+#$===;;==***%%#@+.+@$&>>;;;;;;;;;>>&$.+@#&=->;;===;;--=&$.....++#&*;;;*&#++...+#$*-->;;>>>=====%#....++##$%%##$&&#@+..#%*=;;;;;;;;;;;;=*$..++#%*=>;;;;;;=&$@+...++@#$&&&&&&&&&%$#.++#$&*******=***&$#....+.+++@+@+@+@+++..#$*=;;;;;;;;;;;;=*$...++@$*=====*%$#@...", +".$&=>;;;;;;;;;;=&$......++@#*===*#@+.....+@$*>;;>>===>>=**#.++#%==-;;*=*&%##++..+#$*>;;;;>--;;;>>*%..+#$*==;;>>>;;==*$#.....++$&*;;;*%$+....+#&*;;;>>;;;;;===%#.....++@@@@@@@#@@++..#%-->;;;;>>;;>>>--%..+@#*==;;---;;=*%@+..++@$%=->>>==>>>==#.+#$*;;;;;;;;;;;;;*%....+@@@########@@@+.#%=>>>>;;>>;;>>>>-%....++@#$$%$%$##+++..", +".$*=;;;;;;;;;;;=*$.......+@$=====$@++....+#$*;;;->===>>==&#.+@#%==-;;==*&$#@++..+#%*>;;;;->-;;;>>*$.+.@#&*=;;>>>;;=*&$@.....++#%*;;;*&#++...+#&=;;;>>;;;;;===%#......++++@++++++....$%->;;;;;>>;;>>>>-&..+@#*==;;---;;=&%@+.++@$%&->>>>==;;;==$.+#%*;;;;;;;;;;;;;*&..++@@$$$%%%&%%%%$@@.$&->>>>;;>>;;>>>>-&.....++@@###@@@++....", +".%*=;;;;;;;;;;;=*%......++@$*====%#+.....+#%*;;;>-*=*>-=*&@.+@$&=--;;==*&%#@+...+#$*>;;;;>--;;;>>*%..++#%*=;;>>>;;=*%#+......@#%*;;;*%#+....@$&=;;;>>;;;;;-==&$.......+.+.+.+++.....$&->;;;;;>>;;>>>>-&...@$*==;;---;;=*&#@.+@#%**>>;;;==;;;==$.+@%*;;;;;;;;;;;;;=*...@#$%*********&&$#.$&->>>>;;>>;;>>>>-&.......+++++++.+.....", +".%*=;;;;;;;;;;;=*%.......@@%**==*%#@....++#%*;;;--=**=*&%$@.+#%*;;;;;;;;=*$@+...+#%*;;;--===--;;>*%...+@$&*>;;;;;>=*%#+......+#%*--=*%#++...+#&*;;;;;---;>;;;**.....................$&>>;;;;;==>->>>>>&.++@#&*=;>;;;;>==&#@.+#%=--;;---;;;;;*&$.+@$%===-------;;;=*.++@$=->;;;;;;;;;;&$.#&>;>>>;;;;>>>>>>>&.........+.++........", +".%*=;;;;;;;;;;;=*%......++#$*====%#@+....+@%*;;;-===*=**%$#.+@&*;;;;;;;;==$@++..+#%*;;;->===>-;;;*%..++@$&*>;;;;>>=*%#+......+#$*=--*$#+....@#&*;;;;;>->;;;;;=&.....................$&>;;;;;;==>->>>>>&..++#**=;;;;;;>==*#+.@$&=->;;---;;;;;*%#.++#$**======--;;;=*..+@$-->;;;;;;;;;;&$.$&>>>>>;;;;>>>>>>>&.....................", +".$*=;;;;;;;;;;;=*$......++#%=->>-%$++...++#$*>;;;;==->>=*%@.+@$*=--;;>--=&$#++..+@%*>;;;;>--;;>;>*%...+@%*=>>;;;>>=*%#+.....++#$*;;;*%#+....+@$*==-;;;;;>>;;;=&.....................#&=-;;;;;;;;;;;;-=&..+@#&==;;;;;;;=**#@.@%&;;;>>>>>;;-==&$@..+@#$%$%%%&**=;;;=&.++@$*===-----=-==&#.#&=-;;;;;>>;;;;;-=%.....................", +".%*=;;;;;;;;;;>=*%......+@$&->>>>&$@++...+@$&>>;;;--->>=*&#.+@$&=--;;>--**$#@++.+#%&>;;;;->-;;;;>*$..++@$*=>>;;;>>=*%#+......+#%*;;;*%#+....+@#%*==;;;;;>>;;;=*.....................#%=-;;;;;;;;;;;;==%..++#**=;;;;;;;==&#@.#%*;;;>>>>>;;--=*$@...++@@####$%**;;;=*..+@#&*==========*$#.#$==;;;;;>-;;;;;==%.....................", +".$*=;;;;;;;;;;>=*$......+@$&->>>>*%@+....+@$&>>>;;>--;>=*&@.+@$&=->;;>>-=*&%$@@.+@%*>;;;;>--;;>>>*$..++#%*=>>;;;>>=*%@@.....++#%*;;;*%#++....+#$*==;;;;;>>;;;=&.....................@$==;;;;;;;;;;;;==$..++@&*=;;;;;;;=*&#+.@$*;;;>>>>>;;-==*$#.....++++@+@$%*;;;*&..++@%&&*=====*=**#@.#$*=;;;;;>>;;;;;==$.....................", +".$&=;;;;;;;;;;>=&$.....++#$*>>;>>*%#@.....+#$&==;;;;;;;**$@.+@$*-->;;====****$#.+@$&>>;;;;;;;;;>>&$..++@%&=--;;;-==*%#+......@#&*;;;*&#@....++@$&**==->-;;;;>*%.....................@#%*>;;;;>>;;;;>*%#..++@$&*==---==*&$@+.@$&-->;;->-;;;;;*%#......+.++++@#%===&$...+@@#$#$$$$$$$$#@+.+$&*>>;;;>>;;>>>*%#.....................", +".$*=>;;;;;;;;;>=*$......+#%*>>;>>*%#+.....+@#%*=>;;;;;>*&$@.+#%&->>;;========%$.+@$%>>>;;;;;;;>>>&$..++#%*==>;;;>-**%#+......@#&*;;;*&#@....++#$&*=*=---;;;;;*%.....................+#$&>>>;;>>;;>>>&$#...+@#$&===-==*&%#@+.+#$==-;;-->;;;;;*&$...........+@#$***$#....+++@@@#@##@@@+++.+@$&>>>;;>>;;;>>&$#.....................", +".#&*>;;;;;;;;;>*&#......+#%*;;;;;*%#@+.....+@#$**=;;;=*&$@+.+#&*;;;;;;;;;;;;;*%..+#%*====*****==*%#..++#&*=;;;;;;;=*&#+.....++#&*;;;*&#++...+@$&>>>--===;;-=*$@.....................+@#%*==>>;;>>==*%#+....+@@##%%&%%$#@++..+@$%**>>;;>-=;;;-=$............++@###@+.....++++++++++++++..+@#%*==>>;;>>==*%#@.....................", +".@%*=>;;;;;;;;=*%@.....+@#&*;;;;;=&#@+.....++@#%**;;;=&%#++.+$&=;;;;;;;;;;;;;*%.++@$&****&&&&&**&$@..++#&*=;;;;;;;==&#+......+#%*;;;*%#++...+@$&>;;;;;;;;;=*&#@......................+@#%**>>;;>>**%$@+.....++@@#####@@@+...++@#%*->>>>==;;;==$.............+@@@@++........+.+.+.+.......+@#%**>>;;>>**%#@+.....................", +".@%&&==>>>>>>=&&%......+@#&*;;;;;*&#@+.......+@#&*;;;*%#@+..+#%*;;;;;;;;;;;;;*%...@@%%&%%$$$$$&&%@+..++#&*=;;;;;;>=*&#+.....++#%*;;;*%#+....+@$&>;;;;;;;;;*&$@+......................++@$%*--;;>-*&$@++......++++++@++++......+##%=->>>==>>>==#...............++++.......................++@$%*--;;>-*&%@++.....................", +"..@$%========$%$@.+.....+#%*;;;;;*%#+........++@$&===%$#++..+@$&==--------===%$...+@@@#@@@@@@@@@@++...+@$&*==--=-=*%$@+......+@$%===%$@+....++#%===>----=*&$#++.......................++@#$%&**&&$#@++.........++++++..........+@#$%&&&%&&&&%##...........................................++@#$%&&*&&$#@++......................", +"...++$$$$$$$$$++.......++#$*>>>>>*%#++........+@@$***$#++...+@#%*==========**$#....++++++.+.+++++++..++@#$&*=====*&$$++......++#%*=*$#++....++@$**=--===*&$#@+.........................++@@#$$%$##@++.........................+++@#$#$$$$$$$#@@............................................++@@#$%%$##@++.......................", +".......@$$$@@............+#%=---=%#@+..........++##$#@@+.....+@#$$%%%%%&%%%$$@@.....++++......+........+@##$%%%%%$#@@+........+@#&&*#@++.....+@#%**===**&$#++............................++@@##@@+++............................+++@@@@@@@@@@++..............................................++@@@@#@++.........................", +"........................++@#$%&%%#@+............+++@@++.......++@##########@@++.........................++@@####@#@++..........+@##@@+........++##$$$%$$#@++...............................+++++++................................++.+.+.+++++.................................................+++++.+..........................", +"..........................+@#####@++.............++++.........+++++@@@+@@++++............................++++++@+++.+.........+.++++++.........++@@#@#@@+++..................................+.+.................................................................................................+.+............................", +".....+++@+@+++..............................+++++@+@++...........+++++@+++...................................................+++@@@#@#@@+++................................................++++++................................................+@+@@++............+++@+@+.............++@@@@@@++..............................", +"....++@@###@@++..............................+@#####@@+.........++@#####@@++................+..............................+++@#$$$$$$$$#@+...............................................++@@@@+++...........+.++.+............................+@#####@++..........@#$###@+............@#$$$$##@@+..................+.+........", +"...++@$%***$$@++.............+.............++@$$***&%#@+.......++@$%***&&@@+............++++++............................++@#$&*=====***#@.............................................++@@$&&%#@+.........+++@@@@@++..........................@$$&&%$#@+..........#%%&%$#@+...........#$%&&&&%##@+.....+.........+++@+++......", +"...+@#%&=*=*%$@++..........+++@@++.........+@#%&===**$#@+......+@#%&===**$#@+.........++@@#@@++..........................++#$%&=*========%#............................................+++#$%***$#++.......++@@##$###@@.........................#*=->>*&#+++.....+..*=>>>*&#@+..++++@.+.&*>>>>>**%#++++++++.......++@###@++.....", +"..+@#%**===**%#@+.........++####@++........+#$**==-==&$#++.....+#$**==-==&$#++.......++@#$$$$@@+........................++#$&&*==------==%$............................................++#$%*===%$@+.......+@#$%&&&%$#@+........................$*=>>>=*$@+...+++++.*=>>>=*$@++++@#@@@+.*=>>>>>==&$@@@@@#@@.......@@#%%$$@+.....", +".+@#%&>;>->;>&%#++.......++##&&&$#+.......++#%>>->-;>=*%@+....++#%>>---;>=*%@+......++##***-=#@+........................+@$&>>>;;;;;;;;;;*%............................................+#$&->;;;*$#+.....++@#%==>>>==%#@++......................$==>>>=*%@@+++@@@@@.==>>>=*%@@+@##$$$#@.*=>>;;>==*%####$$##.......+#%>>>$#++....", +".+@$&*;;>>>;;*&$@++......+@$%==*%$@++.....+@#%>>->>;;=*%@++...+@#%>;>>>;;=*&@@......+@#%*==-=$@+......+++++....+.+++....+#%*>>>;;;;;;;;;;*%............................................+#$&->;;;*%#++....+@#$&-->>>-=&%#@+......................$==;;;==$#+@+##$%%#.==;;;==%#@##%&&--$@.=-->>>>>--%$$$%==*&......+@#%>>>%$++....", +"++#&==;;===;;==*#++....++@#%&;;;*%#@++.....@#%==---;>=*%#++...++$%=-->>;;=*%#++.....+@%*>>>=*$#++....++@@@@@+++@@@@@@+..@$&=;;;--;;;;;--=&$............................................+@#%*=;;;*&$+....++@&*=;;===;;=*%#++....+++++.+.++.......$==;;;==%#@@#$$&*&$.==;;;-=%$##%**=--$#.=-->>>>>>-&%&&*--=*......+@$%===&#@+....", +"+@#*==;;===;;-=*#@....+@@#%&*;;;**%#@@.....@#%==---;;**$@+....++#%==>>>;;=*&#++....++#%*>;>**#@+....+@##$$$##@@##$$##@@.@$*=;;;--;;;;;--=&$.........++++.+..............................+#$**;;;*&#@....+@#&==;;--=;;==&#++.+++@@@@@+@@+@++.....$&*;;;-=%$##$===>>$.&*;;;==&$$%*>>>==%#.&*-->;;-==**==->>*$......+@$&===&$@+....", +".@#*==;;===;>==*#++..++#$%**=;;;=*&%$#@...++#%===-=;>=&$@++....@#%=--->;;=*&#++....++#%*>>>*&#++....+#$%&&&%$#$%%&&&%$@.@$*=;;;--;;;;;-==%#.......+++@@+@..............................++@%&=;;;=&$@+...+@#&==;;-==;;==*#@+.++@##$########@++...#&=>;;-=&$$$&=-->-%.&*;;;-=&&&*=>>>==$#.%*>->;;--=**--->>&$......+#%&=-=&$@+....", +"++#%*=>;---;;**%#+...@@$*==--;;;--==*$@...++#%*=;;;==*%$@+....+@#%==>>>;;==&#@......+@%&*=*%$@+.....@$=->>>**%$&;;>--$#.@$*=;;;>-;;;;;--=$#......+@@##$##++.............................+@$&=;;;*&$@+...+@$*==;;===;;-=*$++.+@$***&&&&&*&$##++..$&*;;;-=*%%&*--->>%.&=;;;-=*&**=>>>==$#.&*->>;;---==->->>&$....++@#&*>;>*$#+....", +".+@$%*>;---;;*&$@++.+@$&==---;;;---==&$...+@#%==;;;==*%#@+.....@$%==->>;;==*#@+.....++$%&*&##++.....#$--;;;==&&*;;>>>&$.@#*=;;;->;;;;;-==%#.....++@$%&&%$#@............................++#$**;;;=*$@+...++#*==;;===;;==*#@+.@#$===**=*===&%$#++.$&=;;;-=***==>>>**%.&*;;;-==*=>>>>-**%#.=---->>>>>--;;>**$#....++#%&=;;;*%#+....", +"..+#$%*=---=*&$@++..+@%*;;;;;;;;;;;;;*%....@$&>;>>>;>=*%@++..++@$&>;---;;=**#++.....+++####@++......#%==;;;==&&*>>;;>&%.+#%*>;;;;;;;;;-==$#.....+@#*=>>>%#@.............................+#$==;;;==$#++..++#%*=;;->-;;=*&#++.@$%>;;>>-=-;;==*$@@.%**;;;-===*-->;;*&$.*=;;;-====;>>>-=*%#.=-->->>>>>-->;;*&$@...++#$&->;;;*%#++...", +"..++#$**===*&$#++...+#%*;;;;;;;;;;;;;*%...+@$&>;>>>>>=*&@+....+@$&;;->-;;=*&#++......+++@++++.......@$*=;;;-=***>>;;;*%.+#%*>>;;;;;;;;-==$#....++@$*=;;;&$#++...........................@#%=-;;;==%#+...+@#%*=;;---;;=*%@@..@$&>;;;>---;;-==%#@.%->;;;;>>>>;;>>>=&$.->;;;>;;;;;;;;;>-%$.*=;;;;;>>>;;>>>=*$@..+@#$&*->;;;*%#++...", +"..+++#$&==*&%@@+....+@%*;;;;;;;;;;;;;*%...+@#&>;>>>>>**%@++...+@$%;;---;>=*&@+..........+++.........#$*=;;;==&&*->;;;*%.+@#%->>;;;;;;;-==$#.....+#%==;;;*$#+..........................+.@#%==;;;==%#@+...+@%*=>;->-;;=*%@+..@$%>;;;;---;;--=*$#.%->;;;;;>>>;;>>-=&#.->;;;;;;;;;;;;;>>&$.*=>;;;;>>>;;>>>*&#@..+@$&*=>>;;;*%#+....", +"....+@@##$$#@@+.....++#%&**==;;;===*&%#....@#$==----=&$#++.....+#$*==--==&$#@++.....................@$**;;;-=*&*=-;;;*%.++#$&**--;;;;;===$#....++@$==;;;&$#+..............++...........+@#%=-=-===%$@+..++@$&*->>>>>-*&$#++.+#%*==;;>>>>>;;;=*$.$=-;;;>;>>>;;>>>=&$.->;;;;;;;;;;;;;>>&%.&*>;;;;>>>;;>>>=*$+.+@#%->>;;===&$#@+...", +".....++@@@@@++......++@#%&*==;;;=**&$#@....+@$**=====$#@++....++@#%&===**%#@+.......................+#%*;;;-=***--;;;*&..++#$%*--;;;;;-==$#.....+@$*=>>;&#@+...........++@++++.........+@#$*=====*$#@++.++#$&=->>>>>-=&$#++.+#%*==;;>>>>>;;;=*%.$%&*==-=;;;>>;;;=*$.&**==>>>>>>>-=-;;*$.$%**==-;;;>>;;;=*$@.+@$&>>>;;===*%##++..", +".......++++.+........++@#%%*=;;;=*&$#@+...++@@$$%%%$$#@+.......++@#$$$%$$@@++.......................@#&*;;;--===--;;;*&...++@$%*=;;;;;-==$#.....+@#$%&&%$#@+..........+@@####++........++@#$$$$%$$#@+...++#&==;;;;;;;==*#@..+@$&==;;;;;--;;;==$.@$%&*===;;;>>;;;=*$.$&===>>>>>>>--=;;&$.#$%**=-;;;>>;;;=*$@.+@%&>>;;;==**&%##++.", +".........+...........++@#$%*=>;;=&%$#@+.....++@@###@@+++........+++@#@#@@++.........................+#&*;;;;>-=->;;;;=&....++#%&=;;;;;-==$#......+@##$$$#++..........++#$%%%$#++........+++@####@@+++...+@#**=;;;;;;;==&#++.+#$*==;;;;;>>;;;==$.+#$**=;;>>>>>;;;=*$.$&=--;>=*===;;;-=&$.@#%*=;;>>>>>;;;=*$#.+#%*;;;--==*--**%#+.", +".....................++@#$&*=;;>=*&$#@+......+++++@+++...........+++++++++..........................+#&*;;;;;---;;;;;=*.....+@$&=;;;;;-==$#........@@@@@++...........+@$&->>%$#++.........++++@+++++....++@**=;;;;;;;=*&@@..@#%*==;;;;;--;;;=*$.+#$**=;;->>>>;;;=*%.$&=->>>=**==;;;-=&#.@#%**;;>>>>>;;;=*%#.+#$*;;;--===>>=*&#+.", +".....................+@#**===---==**&@@........++.+.+..............+.++.............................+#%*;;;>;>--;;;;;=*....+@$%*=;;;;;-==&#.........+++++...........+@$%*>>>*%#@+..........+.+.+.........+@#%&&******%%#@+..@$&>>;;;---;;>>-*%$.+#%*==;;>>>>>;;;=*%.%&->->>****=;;;==%#.@$&*=;;>>>>>;;;=*%#.+@%&>;;;>==-;;==*#@.", +"....................+@#$===--->---==*$#.............................................................+#&*;;;;;;;;;;;;;-=..++@$%*==;;;;;>>-&$........................++@$==;;;==$@+........................++@@$%%&&&%$$#@++..@$&>;;;;---;;--=&$@.+#%->>>>>>>>>;;;-=%.*=>;;==***>>>>-==%#.#%->>>>->->>;;;-=%#.+@$&>>;;;---;;-=*$@.", +".....................@$%==-->-->--==*%#.............................................................+#%*;;;;;;;;>>;;;-=...+@$&*=-;;;;;>>-*%.........................@#%==;;;==%#++.........................++@@#####@@+++...@$&>;;;;==-;;-==$#@.@$%>>>-->>>>>;;;--%.&=;;>=*&**>>>>>==%#.$%>>>>->->>>;;;--&#.+@$%>>>;;---;;==*#@.", +"....................+@$*;;;;;;;;;;;;;*$.............................................................+#&*;;;--==*****&&$..+@#*==;;;;;;;;;;*&.........................+#%=-;;;==%#+..........................+++++++@++++.....+#%=--**=====*&$#@+.+#%->>--->>>>;;;-=%.&*>>>**%&*>>->-==%$.#%->>-=-=->>;;;-=%#..+#$**=;;;;;;;=*%#+.", +"....................+@$&;;;;;;;;;;;;;&$.............................................................+#%*;;;-=*%$####@@+..++#&==;;;;;;;;;;*&........................++#&->;;;-=$#++............................+.+..+........+#$*==&&*****%$#@++.@#%*==**&&*==;;;-=%.&****%$%**;;>>>;>%$.#%*==*&&&*==;;;-=%#.++@#%**;;;;;;>*&$@+.", +"....................++#%%***********&$#.............................................................+#%*;;;==%##@++@++...++#&*=;;;;;;;;;;*%.........................@#%->;;;==$#+...........................................++#$$$$$#$$$$#@++...+@#***$%$%%*=>;;==$.%&%%%$#$%*>>>>>>;%#.@#***$$$$%**;;;==$@...+@#$&&*****&%$@@..", +".....................+@#$$%&&&&&&&%$$#@.............................................................+@#%===&%#@+..........+@#$&&********&%#........................++#$*=---*%$@+...........................................+++@@#@@@@@@@++++...++@########$%&*&%$#.@@###@@@#$&&&*&&%$@.+@######@$$&&&&%$#@...++@##$%%%%%$#@+.+.", +".....................+++@###########@++.............................................................++#$***%#@+...........++@##%%&&&&&%%$#@.........................+@$&*===&$@+..............................................++++++++++++.......+++@+++++@##$$$$@@.+++++++@@#$$$$$$#@@.+++@@++++@@$$$$$@@+......+@@#####@@++...", +".......................+++++@+@+++++++...............................................................+@#&*&#@++............++@@########@@@+..........................+@%&==*$#@+..............................................+...................++++++++++@@@@@++.++++++..++@@##@@@++..+.+.++.++++@#@@++........++++++++++....", +"...+++@@@@++...............+++@@@@++..........++@@#@@+...........+.++@++++..............................+++@####@++............++++++++.+.........+++@+@+@+++++....+++@@@@++................++@@@@@+..........++@#@@@...........+++++++++++........+++@@@++..................++@@@@++........++@@####@+.........++++++++++++....", +"...++##$##@++..............++@##$##@+........++##$$$#@+..........+@@@###@@++...............+.............+@#$%%$$@++.........+++@+@@@@@@@++...++++@@########@++....++##$$#@++..............++@##$#@@++.......+@#$$$#@@+........++@##@##@#@@++......+@@#$$#@++...............++@##$#@@+.......++#$%%%$#@+.......+++@#@@@@@@@@++..", +"..++#$&==$#@@.............++#$&&==#@++.....+++#%&===$#@+.......++@#&&%%$%$@@........+++@+++++++........++@#**---&$@+.......++@@##$#$#####@@....+@#$%&****&&%$$@...++@$==&%%@@............+++@#%==%$#++.....+++#$===&%#++......++@#$$%$$$$$#@@+.....+#%%==$$@++.............++@#%==&$#++....+++#%*->-&%#@.....+++##$$$$#$$$$#@@+.", +"..+@$%*--&%#@++..........+@@$&**--$#@.......+@$&*---&$@+......++##%******&#@++.....++@@@#@@@@@@+.......++@%*=>>-*%#++.......@@&&********&&#..+@@#%&*=====***&%#...++#$=-**&$@@+...........@@$%&--*%$++.....++#$&->-*&$#++....++@$%--***==*&%@+....++$%*--&%$@++...........++@$%&--*%$@+....++@$**>>>=&$#++....+@%&&==%%%==*&%@+.", +"..++$&*>>**%#@+.........++@$%===--$#+......+@$%*=>>-*%#@+....++@$%&=====**%#@+....++@#$$$$$$##@@+......+@#%==>>>*&$++.....++#$**========**$.+@#$%**=====-===**$..++@$%==;;>*&$#@++....++@#$%-->>>*%$@++..++@$%=->>>;>&%#@+...+@$%&>>=*=--=**#@+..++@$%*->**%$@++.........+@@$%&*>-*%$++....+@$%*=>>>=*%#@+...+@#&*==-***--**&#@.", +"..+@#%*->>-=$#++......+++@#&*>>>=*$@++....++#%&>;>>>==$@++..+.@#*==;;;;;;>&$#+...++@%&*=-%%%--$@++....++@$&->---==$@+......@#%====-=-=====&.+@$===;;;;;;;;;;>>%..+@#%&==;;;=*%$#@+..++@@$$&*->>>-*&$@@...@@$%*=-;;;;;*&$#@..+@#**=->--->>===%#+...+@#%*->>-=%$#+++.....+++#$%-->>-*%#@+...++#%&>;>>>;;&%#@+.++@$*==>>===->-=*$@.", +".++@$%*->>>-&$@.+.....++@$%*=;;;=*$@+....++#$&*;;;;>-=$@+....+@$*=-;;;;;;>*$#+...+@#%*=--***--$@++....+@#%*->---=*$++....++@$&>;;;;;;;;;;;&.@#%==-;;;;;;;;;;>>&.+@#&*==-->---=*&#@+.++#&**==>>>--=**$@+.+@$*==>>--->>-=*$#+.+#$*==>>--->>-==%$@...+@$%*->>>-*%$#@++...++@#$%*->>>-*%#@+...+@$&*;;>>>;;*&$@+.++#%===>>--->>-==%#.", +".++#&*==->>>&$#+.....++@$&*=->--*&#@++...+@#*=->>---==%#++..++#%=---->>>==&$@++..+@#**=>>=====%#+....++#&*=->>>>*&$@++....+#$*;;;;;;;;;;;;*.#$*;;;->=====>>>>>&.@#&==--->>>>>===&$@.@$%===-->>>---==&$@.@$%=-->>->->>--=&%#.@$&==->>>->>>--=*$#..+@$*===->>>==**%#+..++#&**=->>>-==*&#@..+#$*=-->--->>-==$@.++#$==->>=-->>-==%#.", +".+@$*===->>>*%#@.....+@#&*=-->>-*&#@.....+#$*=->>->-==$#++..+@#%=->->>>>=*%#@....+#$*==>>-===*%#@....+@$*==->>>>*&$@+.....+@%*->;;;>>===;;*.#%*;;;--*****>>>>>&.#%&;;;;;;;;;;;;;=&#.@%*;;;;;;;;;;;;;=&#.@%*;;;;;;;;;;;;;=&#.#%*;;;;;;;;;;;;;=&#.++#$*==-->>>-==**$@..+@$&==-->>>-===*$@.++#%==->>--->>-==%#.++#%->>;;;;;;;>>-%#.", +"++#$*==-->>>*&$@+....+@$**=->->>*&$@++..++#%==->>---==%#@...++#&=->-->>>==%#@+..++#%*==>>---==%#++..++#$*==->>>>=&$@+....++#$*>>;;;>>===;;*.#%*;;;>=*%%&*->>>>&.#%*;;;;;;;;;;;;;=*$.@%*;;;;;;;;;;;;;=*#.#%*;;;;;;;;;;;;;=*$.@&*;;;;;;;;;;;;;=*$.++#$->>;;;;;;;>>-$#.++#$->>;;;;;;;>>-$#.++#%->>;;;;;;;>>-%#.++#$->>;;;;;;;>>-$#.", +"++#%->>;;;;;-=%#++..++#$->>;;;;;-=%#++..++#%->>;;;;;-=%#@+..+@#%>>;;;;;;-=&#@...++#%->;;;;;;-=&#@+..++#%->>;;;;;==%#++....+#%*>>;;;>>=-=;>&.$*=;;;=*&$#$%***=*$.@$&=--;;=====;;;**#.@$&=--;;=====;;;**$.@$&=--;;=====;;;**#.@%&=--;;=====;;;=&$..+#$->>;;;;;;;>>-$#..+@$->>;;;;;;;>>-$#.++#$->>;;;;;;;>>-$#..+@$%&*==;;;==**%#@.", +".+#$->>;;;;;==&#@+...+#$->>;;;;;==&#++..++#$->>;;;;;-=&$@+..++#%->>;;;;;-=&#@+..++@%->>;;;;;-=&$++..++#$->>;;;;;-=&#@....+@#%*;;;;;>>;;;=*&.#*=;;;=*%#@@#&&**&$.@$&=--;;=====;;;=&$.@#&=--;;=====;;;=&#.@$&=--;;=====;;;=&$.@$&=--;;=====;;>=*#..+@#%&*==;;;==**%#@.++@#%&*==;;;==*&%#@..+@#%&*==;;;==*&%#@...+@$%**=;;;=*&%##+.", +"++@$%*=>>;;;>>&$@+..++@$&*=>>;;;>>&$@+...+@$&*=>>;;;>>&$@+...+@$&*=>>;;;>>&$@+...+@$&*=>>;;;>>&$@+...+@$&*=>>;;;>-&$@+...+@$&*;;;;;>>;;;=*%.$&=;;;=*$@@@@$%$%%@.+#%==-;;=====;;;*&#.+#%==-;;=====;;;*&$.+#%==-;;=====;;;*&#.+#%==-;;=====;;;*&#..++@#%**=;;;=*&%#@+..++@#%&*=;;;=*&%$@+..++@$%**=;;;=**%##+..+.+@#%*=;;;=*%#@++.", +"..+@$&*>>;;;>>*%#@...++@$&*>>;;;>>*%#++...+@$&=>>;;;>>*%#@...++@$&*>>;;;>>*%#@....+#$&*>>;;;>>*%#++...+@$&*>>;;;>>*%#+..++@%&=;;;;;>>;;>=*$.$*=;;;*&$@++++@@@@+.+#$==-;;===>;>--&%@.+#$==-;;===>;>--*$#.+#$==-;;===>;--=&$@.+#$=--;>===>>--=&$#...++@#%*=;;;=*%#@@....++@#%*=;;;=*%#@++...++@#%*=;;;=*%#@++...+++@$&*;;;*&$#++..", +".++@$**;;---;;*%$++...+@$**;;---;;*%$++..++@$&*;;---;;*&$++...+@$**;;---;;*%#@+..++#&*=;;---;;*%$++..++@$**;;---;;*%#@+.+@$*==;;;;;;;;;;=*$.$*=;;;*&$@++++@@@++.+@$==-;;===;;--=$#+.+@$==-;;===;>--=$#+.+#$==-;;===;;===$@+.+#$==-;;===;>-==$@+....++@$&*;;;*&$#++.....++#$&*;;;*&$#++.....++@$&*;;;*&$#++......+@$&*;;;=&#@+...", +".++#$*=;;=-=;;=&$@+..++@$&=;;---;;=&$@+..++@$**;;---;;=&$@+..++@$&=;;---;;=&$@+..++#&*=;;---;;=&$@+..++#$&=;;---;;=&$@+.+#%*==;;;;;;;;;;=&#.#*=;;;=*%##@@####@@.+#$==-;;;;;;;=*&$@@.+#$==-;;;;;;;=*&$@+.+#$==-;;;;;;;=*%$@@.+#$==-;;;;;;;=*%$@+....++@$&=;;;=&#@+.......+@#&=;;;=&#@+.......+@$&=;;;*&$@+.......++$&*;;;*&$++...", +"++@$===;;===;;-==$@..+@%*=-;;===;;-==$@..+#$==-;;===;;===$@..+#$===;;===;;-==$@..+#$==-;;===;;-==$@.++@$===;;===;;===$@.@$%->>;;;;;>>--=*&#.$&=;;;=*&%$$$%%$$#@.+#$==-;;;;;;;=*%$@+.+#$==-;;;;;;;=*&$#+.+#$==-;;;;;;;=*%$@+.+#$==-;;;;;;;=*%$#+.....++#&=;;;=&#@+.......+@#&*;;;*&$++.......++$&*;;;**#@+.......++#&=;;;*&$++...", +"+@#%=--;;===;;-==%$.+@#%==-;;-==;;-==%$.++#%==-;;===;;-==%$.+@#%=--;;===;;-==%#.+@#%=--;;-==;;-==%$.+@#%==-;;===;;-==%$.@$*>>>;;;;;>>>--*%$.#&*;;;-=**&&&====*#.+#$==-;;>>>;;=**%$@.+#$==-;;>>>;;=**%$@.+#$==-;;>>>;;=**%$+.+#$==-;;>>>;;=**%$@....++@$&*;;;*&$@++......+@$&=;;;*&$@+.......+@$&=;;;*&$@+.......+@$**;;;*&$@+...", +"+@$&>>;;;;;;;;;>>&$.+@$&>>;;;;;;;;;>>&$.+@$&>>;;;;;;;;;>>&$.+@$&->;;;;;;;;;>>&$.+@$&>>;;;;;;;;>>>&$.+@$&>>;;;;;;;;;>>&$.#&*>>>;;;;;>>---**$.#%*;;;>-=*=*=---==$.+#%==-;;>>>;;===*&$.@#%==-;;>>>;;===*&$.@#%==-;;>>>;;===*&$.+#%==-;;>>>;;==**&$...++@#%*=;;;=&%#@+....++@#%&=;;;=*%#@+....++@#$**;;;=*$#@+.....+@#%*=;;;=*%#@+..", +"+#%*>;;;;;;;;;;;>*&.@$%*>;;;;;;;;;;;>*&.+#%*>;;;;;;;;;;;>*&.+#&*>;;;;;;;;;;;>*&.@$%*>;;;;;;;;;;;>*&.+#%*>;;;;;;;;;;;>*&.$&=;;;=->>>>>===>>&.@$&-->;;;;;;;;;;==%.@$&=--;;===>->-->>%.@$&=--;;===>---->>%.@$&=--;;===----->>%.@$%=--;;===--->->>%...+@#$&*=;;;=*&$#@+...+@#$&*=;;;=*&$#@+...+@#%&*=;;;=*&$#@+..++@#$&*=;;;=*&$#@+.", +"#$*=;;;>>>>>>>;;;=*.@$*=;;;>>>>>>>;;;=*.#$*=;;;>>>>>>>;;;=*.@$*=;;;>>>>>>>;;;=*.@$*=;;;>>>>>>>;;;=*.#$*=;;;>>>>>>>;;;=*.%*=;;;-=>>>>>===>>*.@#%=--;;;;;;;;;;=*$.@$&=--;;===-->>>>>&.@$&=--;;===->>>>>>&.@$&=--;;===>>>>->>&.@$&=--;;===>>>>->>&..++#$&*==;;;==*&$#@.+.@#$&*==;;;==*&$#+..++#$&*==;;;==*&%#@..++#$&*==;;;==*&$#+.", +"#%*=;;;>>>>>>>;;;=*.#%*=;;;>>>>>>>;;;=*.#%*=;;;>>>>>>>;;;=*.#%*=;;;>>>>>>>;;;=*.#%*=;;;>>>>>>>;;;=*.#%*=;;;>>>>>>>;;;=*.%->;;;>>;;;;;;;;;;*.+#$==-;;;;;;;;;;=*$.#&*;;;;;;;;;;;;;>>&.#&*;;;;;;;;;;;;;>>&.#&*;;;;;;;;;;;;;>>&.#&*;;;;;;;;;;;;;>>*.++@$==-;;;;;;;--=$@..+@$==-;;;;;;;>-=$@.++@$==-;;;;;;;--=$@..+@$==-;;;;;;;--=$@.", +"#%->;;;;;===;;;;;>-.#%->;;;;;===;;;;;>-.#%->;;;;;=-=;;;;;>-.#%->;;;;;=-=;;;;;>-.#%->;;;;;===;;;;;>-.#%->;;;;;=-=;;;;;>-.%->;;;>>;;;;;;;;;;*.++#$&*==;;;>>==**$#.#&*;;;;;;;;;;;;;>>&.#%*;;;;;;;;;;;;;>>&.#%*;;;;;;;;;;;;;>>&.#&*;;;;;;;;;;;;;>>&.++#$=->;;;;;;;>-=%#.++#$=->;;;;;;;>-=%#..+#$=->;;;;;;;>-=$#.++#$=->;;;;;;;>-=%#.", +"#%->;;;;;-=-;;;;;>-.#%--;;;;;-=-;;;;;>-.#%->;;;;;===;;;;;>-.#%->;;;;;===;;;;;>-.#&--;;;;;-=-;;;;;>-.#%->;;;;;===;;;;;>-.%--;;;>>;;;;;;;;;;&..++@#&==;;;>>*&%#@+.#%*;;;;;;;;;;;;;>>&.#&*;;;;;;;;;;;;;>>&.#&*;;;;;;;;;;;;;>>&.@&*;;;;;;;;;;;;;>>&.++#%=->;;;;;;;>>=$#.++#%=->;;;;;;;>--$#.++#%=->;;;;;;;>>=%#.++#%=->;;;;;;;>>=$#.", +"#%--;;;;;===;;;;;--.#%->;;;;;===;;;;;--.#%--;;;;;===;;;;;--.#%=-;;;;;===;;;;;--.#%=>;;;;;===;;;;;>=.#%--;;;;;===;;;;;--.$*=---=--->-->>>--&....@#%==;;;>-&#@+...@$&=-->>-->-----=*%.@$&=-->>-->-----=*%.@$&=-->>->->----=*%.@$&=-->>>--->---=*%..+@$*==->->---==*$#..+@$*==->->---==*$#.++@$*==--->->-==*$@..+@$*==->->---==*$#.", +"#$*=-----=*=--->-=*.#$*=-----=*=--->-=*.#$*=-----*===----=*.#$*=-----*===----=*.@$*=-----=*=-----=*.#$*=-----*===----=*.#&*======-=-----==$...++#%->;;;=*%#++...+#$===----=---==*&#.+#$==----=-=--==**#.+#$==----=-=--==*&$.+#$==-----=-=-==*&#.++@#**===-=-===**#@.++@#**====-=-==**#@..+@#**===-=-===**#@.++@#**===-=-===**#@.", +"@#&*=-===*&*=====*&.@#&*=-===*&*=====*&.@#&*=-===&&*==-==*&.@$&*=-===&&*==-==*&.@$&*=-===*&*==-==**.@#&*=-===&&*==-==*&.@#$%%%%%&%&&&&&&%$#....+#$=-;;;*&#@+....+@#$%&&&&&&&%&&%$$@.+@#$%%&&&&&&%&&%$#@.+@#$%%&&&&&&%&%%%#@.+@#$%%&&&&&&%&&%$$@..++@#$%%&&&&%%%$#@+..++@#$%%&&&%&%%$#@+..++@#$%%&%&&%%%$#@+..++@#$%%&&&&&%%$#@+.", +"+@#$%%%%$$$$$%%&%$$.+@#$%%%%$$$$$%%&%$$.+@#$%%&%%$$$$%%&%$$.+@#$%%&%%$$$$%%&%$$.+@#$%%%%$$$$$%%%%$#.+@#$%%&%%$$$$%%&%$$.+@@######$##$#$###@....+@#%&**&%$#++....++@@###$#$#$####@@+.+++@##$#$#$#$###@@+.+++@##$#$#$#$###@@+..++@##$#$#$#$###@@+...++@@####$#$##@@++...++@@#####$###@@++...++@@###$#$###@@+....++@@@########@@++.", +"++@@#####@@@#####@+.++@@#####@@@#####@+.++@@#####@@@#####@+.++@@#####@@@#####@@.++@@#####@@@#####@@.++@@#####@@@#####@+.++++@@+@+@@@@@@@+++.....+@#$$$$#@++.......+++@@@@@@+@@++++...+++@+@@@@@+@++@++...+++@+@@@@@+@@+@++...+++@+@@@@@+@++@++.....+++++@+@+@++++......++++@@@+@@+++++.....++++@+@+@+@++++.....+++@+@@@@@++++...", +"........................++++@@@+@++++.......+++@@@+++...............+++@@+++.........++@@#@@@+..........++++@@@@+@+++.....................................................+.++++.+......++@@@@+++...............+++@+@+.+........++@@##@@+...................................+++@+@+.........+....................+++++++.......", +"..++++++++++++..........++###$$$$###++.....++#$$$##@+..............+@@#$$#@+........++@#%%%$#@++........++##$#$$$###+++.........+..++..................................++++@@@@++......++@$$$##@++............+++@#$$#@+........++@#%%%$#@++............+.+.+...............++@#$$@@++.....+++++++................+@@###@++.....", +"++@@#######@@+++.......+@#$%&&&&%%$$#++....+@#&&&%$#@+............++@$$&&$#@+.......+@#%&**%$#@+......++@#$%&&&&%%$$@@......+++++++++++.............................+++@@####%$$@@+....+@$&&&%$#@+............++#$$&&$#@+.......+@#%&**%$#@+........+++++++++++............++#$$&&$#@+...++@@#@@@+++............++@$%&&&$@@+....", +"@@$$%%%%%%%$$##+++...+++#$==>>>==-==$@+...++#$=---=$#++..........++#%&*>>&%#++.....++#%*>>>==$#++.....++#$==>>>==-==$@+....+++#$@@###@@++.........................++@@#$$%%%&*&&$@+...++#$=---=$#++..........++#%&*>>&%#++.....+@#%*>>>==$#++......++@#$@@@$#@+++.........++#%&*>>&%#++.++##$%$%$#@@+..........++@$%**=*%%#@++..", +"#$%&*******&&%$$@++...+##%=->>>----=$#+...++#%->---&$@+..........+@$&==>>*%$+......+@$**;;;-=&$@++....+@#%=->>>----=$@+....+@#$%$$$%%##@++.....++++......++++.+...+@#$%&&****==*%#@...++#%->---&$@++........++##&==>>*%$++.....+@$**;;;-=&$@@+.....+@#$%$$#%%$#@++......+++#$&==>>*%$++.+#$&&**&&%$#@+.........+@$%**===*&%#@+..", +"#==>;;;;;;;>>**&$#+.++@$%*--;;;-->-=%#+....@#%->>>-*%#@+........+@#%*==;>*%$++....+@#%*=;;;--*%#++...+@#%&--;;;-->-=$#+...++#$&&%&%**%$#@+....++@+@+++..+++@+++.++@$$&=-;;;;>;;;&$@...+@$%->>>-*%$@+++....+++@$%*==;;*&$@++..++@#&*=;;;--*%$@++..++@#$&&%%&&*%$$@++...+.++##%*==;;*&$@+.@#%>>>;>-==$#@+.+.....+@#$*>;;;;;>&%#@+.", +"$==;;;;;;;;>>==*%$@.+@#&*=>;;;;;;==*%#@...++#$*=>;>=*$@++......++#$&>>;-=&%#++.....@#&>>--->>=*&@++..+@&*=>;;;;;;==&$@+...+@$%>>=*=>>=*&#@..+.+@####@+++@##$#@+.+@$%**--;;;;;;;;*&#.++@#$&*=>;>=*%$@@++..++@#$%*>;;-=*&$#++..+@#%*>>---;>=**#@+..+@#%&>>*=*>>==*$@+..++@@#$%*>>;-=*&$#+.@$&>;;;;--=%$#@++....++@$&*;;;;;;;*&$@+.", +"%*=;;;>>>>>>>;;;*&#.+@%*==>>;;;;;===&$@..+.@#%&=>>>==&$@++....++@$&*;;;-=*%#@+...++#$&>>->-;>=**#++.++#&*=>>;;;;;=**$@+..++#$&>>===>>==*#@+..@@$*=*$##@##$=**$@.@#%->>;;>>>;;;;;=*$.++#$&**=>;>==*%%$#+.++#$%&**;;;--**%$#@.+@#%&*>;->-;>===%$@.+@#%**;>===>>===%$@.++##$%&**;;;-==*&$#.@$&>>>;;>--=*$$@@++.+.@#*==;;=--;;==*$+.", +"%*=;;;>>>->>>;;;=*$.@#%===;;;;;;;===&%#..++@$%*=>;>==&%$@@+..++@$%&=;;;==*&$@@...+@#%*>>-->;;==*$@+.++#&==>>;;;;;==&$#+..+@$%*>;===;>-==$#+.++#%===&%$$$%&===%#.@$&->>;;>>>;;;;;=*$.+#$&*===>;>==***%$#.+#$%**==;;;-==**&$#.+#$&*=>;---;;-==&%#.+#$&*=;;===>>-==*%#.@@$%&**==;;;--=**&$.@$&>>>;;>--==&&$#@+..+@$*=-;;-==;;-=*$@.", +"%==;;;>>>>>>>;;;=*%.@$&>;;>>===>>;;;==$.@#%->>;;>>>>>;;;*&#.@#%->>;;>>>>>;;;*&#.@#&->>;;>>>>>;;;*&#.@#&>>;;;->>>>;;;*&#.@#&>>>;;>>>>>;;;*&$.+@$%=--**&&&**--=&#.#%*>>>;;>>>;;;;;=*%.@$%>>>;;===>>;;>==$.@$&>>;;;===>>;;>==$.@$&>;;;;===>>;;;==$.@$&>>;;>=*=>>;;;==$.@#==>>>;;-==;;;;>==.@#&>>>;;>>>-=**&%$#.++#$==-;;-=-;;-==$@.", +"$*=;;;--=====;;;>-%.#%*>;;>>===>>;;;-=$.@$&->>;;>>->>;;;=*$.@$&->>;;>->>>;;;=*$.#$&>>;;;>->>>;;;=*$.#$*>>;;;>->>>;;;=*$.#$&>>;;;>->>>;;;=*$.+@%*;;;>>**=>>;;>&$.#&*;;;----->>;;;>-&.@%*>;;;;==*>>;;;-=$.@$*>;;;;===->;;;-=$.@%*>;;;;=*=>>;;;-=$.@%*>;;;;=*=->;;;-=%.#$==>>;;;==-;;;;;-=.+$%=--;;;;;;;;;>*&$..+@$==-;;---;;-==$#.", +"$&=;;;--=*=*=;;;>-&.#%*;;;;;-=-->;;;-=%.#%*>>>;;--->>;;;=*%.#%*>>>;;--->>;;;=*%.#%*>>;;;--->>;;;=*%.#%*>;>;;--->>;;;=*%.#%*>;;;;--->>;;;=*%.+@$*>;;;>===>>;;;&#.$*=;;;----->>;;;>-&.#%*;;;>>=*==-;;;==%.#%*;;;>-=**--;;;==%.#%*;;;>>==*=-;;;==%.#%*;;;>>=**=-;;;==%.#%=-;;;>>===>>;;;==.+#%=--;;;;;;;;;;=*$..+#$==-;;---;;-==%#.", +"%=-;;;;;---=*->>>>&.#&*;;;;;-=---;;;==%.#&=;;;-=***==;;;>-&.#&*;;;-=***==;;;>-%.#&=;;;--***==;;;>-&.#&=;;;-==**==;;;>-&.$&=;;;--***==;;;>-&.+@#%*==;;;;;;;==*%#.$*=;;;==;;;-->>>>>&.#%*;;;-=*%&*=;;;=*%.#&*;;;-=*%&*=;;;=*%.#&*;;;-=*&&*=;;;=*%.#&*;;;-=*&&*=;;;=*%.@#%*>>;>>===>>;;;*&.+#$==-;;=====>>>>>&..+@$==-;;;;;;;-==%#.", +"%=-;;;;;--=*=-->>>*.#%*;;;;;>>>==;;;=*%.$&=;;;-=*&&**;;;>-&.$*=;;;==*&&**;;;>-&.$&=;;;-=*&&**;;;>-&.$&=;;;-=*&&**;;;>-&.#&=;;;-=*&&**;;;>-&..+#%&==;;;;;;;=**$@.$*=;;;==;;;-->>>>>*.#&*;;;-=&%%**;;;=*$.#&*;;;-=&%%&*;;;=*$.#&*;;;-=&%%&*;;;=*$.#&*;;;-=&%%&*;;;=*$.+#%*>>>>>===>>;;>*%.+#$==-;;=====>>>>>&.++#$==-;;;;;;;--=&$.", +"%=-;;;;;--=**->>>>*.$&*;;;;;>>;==;;;=*$.$*=;;;*&%##%&-->>>*.#*=;;;*&%##%&-->>>*.$*=;;;=&%##%&-->;>*.#*=;;;=&%##%&-->>>*.$&=;;;*&%##%&-->>>*.++@#&*=;;;;;;;=**#@.$*=;;;==;;;-->>>>>&.#&*;;;==&$%&*;;;=*$.#%*;;;-=&%%&=;;;=*%.#%*;;;==&$%**;;;=*%.#%*;;;-=&%%&=;;;=*%.+@#%*==;;---;;==*%#.+#$==-;;=*=*=>>>>>&.++#$==-;;;;;;;--=&$.", +"%=-;;;>>===**-->>>*.#%*;;;>>;;;==;;;=*$.$*=;;;=&$##$&-->>>*.$**;;;=&$#@$&=->>>*.$&=;;;*&$##$&-->>>*.$**;;;*&$##$&-->>>*.$*=;;;=&$##$&-->>>*...@#%*=>>;;;>>=*%#+.$*=;;;=-;;;==->>;>*.#&*;;;==&$%**;;;=*$.#&*;;;==&$%&*;;;=*$.#&*;;;==&$$**;;;=*$.#&*;;;==%$%&*;;;=*$..+@$*==;;>->;;=**$@.+#$==-;;==*==>>>;>*..+@$==-;;===>>;;;*&.", +"%==;;;>>==***-->>>&.#&*;;;--;;;->;;;=*$.$*=;;;*&$#@$&-->>>&.$*=;;;*&$##$&=>->>&.$*=;;;=&$@#$&-->>>&.$*=;;;*&$@#$&-->>>*.$*=;;;*&$@#$&-->>>&.+.@#%**>>;;;>>=&%$@.$*=;;;==;;;==>>-;>&.#&*;;;==%$$**;;;=*$.#%*;;;==%$$**;;;=*$.#%*;;;==%$%**;;;=*$.#&*;;;==%$%**;;;=*$..++@#%*>>;;;>-*%#@+.+#$==-;;=====>>>>>&.++#$==-;;===->;;;=*.", +"$&=;;;-=**&&*>>>>>*.#&*;;;->;;;--;;;=*$.$*=;;;=&$##$&-->>>*.$*=;;;**$##%&-->>>*.$*=;;;*&%##$&-->>>*.$*=;;;=&$##$&-->>>&.$*=;;;=&$##$&-->>>*..+@$==-;;>>>;;-=*$@.$&=;;;;;>--==;;;>>*.#%*;;;-=&%%&*;;;=*$.#%*;;;-=&$%&*;;;=*$.#&*;;;-=&$%&*;;;=*$.#%*;;;-=&$%&*;;;=*$...++#$&>>;;;>>&%@++.+#$==-;;;>;>>;;;-=&.++#$==-;;=*===;;;=&.", +"$&*;;;--*****>>>>>&.#&*;;;-----;;;;;=*$.$*=;;;==&%&&*>;>>>&.#&=;;;==&%&&*>;;>>&.#*=;;;==&%&&*>>;>>&.$&=;;;==&&%**>;>>>&.$*=;;;==&%&&*>;;>>&.+@#%==-;;>>>;;-==%#.$&=;;;;;>--==;;;>>&.#&*;;;==%%%&=;;;=*$.#%*>;;==&%&&=;;;=*$.#%*;;;==&%%**;;;=*$.#&*;;;==&%%*=;;;=*$....+@$&*=;;;=*%#@+..+#%==-;;;;;;;;;;==$.++#%==-;;===*=;;;=&.", +"#**;;;-==***=>>>>-%.#%*;;;--->-;;;;;=*%.#&=;;;==****=>;;>-%.$&=;;;==****=>;>>-&.#&*;;;==****=;;>>-%.#&*;;;==****=;;;>-%.#&=;;;==****=;>;>-%.+@#%==-;;>>>;;--=&#.$&=;;;;>>--==;;;>-%.@$*;;;==****=;;;**#.#$*>;;==***==;;;=&$.@$*;;;-=****=;;;=*$.@$*>;;-=****=;;;**#....+@$%*=;;;=*%$@+..@#%=--;;;;;;;;;;=*$.+@#%==-;>=====;;;=*.", +"$*=;;;>-====-;;;=*%.#&*;;;-->--;;;;;=*$.#%*>>>;>===--;;;=*%.#%*>;;>>===--;;;=*%.#%*>>;>>===-=;;;=*%.#%*>>>;>====-;;;=*%.#%*>>>;>===-=;;;=*%.+@%*;;;>-=*=--;;>&$.#&*;;;;;-----;;;=*%.@$&->>;;====-;;;*&#.@$&->>;;=====;;;*&#.@$&->>>>====-;;;*%#.@$&->>;>====-;;;*&#....+@$&==;;;==&$#++.@$&=->;;>>>>>==*&%#.+@$&=->;;---->;;;=&.", +"%&=;;;>>===--;;;**$.#&*;;;->===;;;;;=*$.@$&>>;;;--=--;;;=*$.@$&>;;;>--=--;;;=*$.@$&>>>;;-=---;;;=*$.@$&>>;;>-=---;;;=*$.@$&>>;;;-=---;;;=*$.+@%*;;;-=***=-;;;%$.#%*;;;;;---->;;;=*$.@#%->>>;==---;;;*%#.@#%->>;>===--;;;*%#.@#%->>;;===--;;;*%#.@#%=>>;;==---;;;*%#..++@$%*=-;;;-=*%$@+.#%*-->;;>>>>-**&$#@.+#$*-->;;>->>>;;;=*.", +"%->;;;;;;;;;;>--*%#.#**;;;;;===->;;;=*$.@#%*==>>;;;;;--=&%#.@#%*==>;;;;;;>--&%#.+#%*==>;;;;;;--=&%#.@#%*==>;;;;;;--=&%#.@#%*==>;;;;;;>--&%#.+@#%*==*&%%%&*==*%#.#%*>>>;;;;;;;>--&%#.+#$*==;;;;;;;>>-*$#.+#$*==;;;;;;;>>-*$#.+#$**=;;;;;;;>>-*$#.+#$*==;;;;;;;>>-*$#..++#&==;;;;;;;=**#+.#&*;;;;;>>>**&%##++.+#&=;;;;;>>>;;;;;*%.", +"%->;;;;;;;;;;--=%$@.#**;;;;;===--;;;*&$.+@#%*=>>;;;;;-==%$@.+##&*=>>;;;;;--=%$@.+@#%*=>>;;;;;-==%$@.+@#%*=>>;;;;;-==%$@.+@#%*=>>;;;;;--=%$@..+#$&**%$###$%***$@.@$&>>>;;;;;;;--=%$@.++#%*=;;;;;;;>--&$@.++#%*=;;;;;;;>--%$@.++#&*=;;;;;;;>>-&$@.+@#%*=;;;;;;;>>-%$@..++#&==;;;;;;;==&#+.#&=;;;;;>>-*%$#@++..@#&*;;;;;-->;;;;;*%.", +"$=>;;;;;;;;;;-==$#+.#%*;;;;;***=-;;;*%#.++#$&*>>;;;;;==*$@+..+#$&*>>;;;;;===$#+.++#$&*>>;;;;;==*$@+.++#$&*->;;;;;==*$@+.++#$&*>>;;;;;===$#+.+.@#%%%#@@+@@#%%%@@.@$&->>;;;;;;;===$#+.++@$&*;;;;;;;>-=$#+.++@%&*;;;;;;;>-=%@+.++@%&*;;;;;;;--=$#+..+@%&*;;;;;;;--=%@+..++#&*=;;;;;;;=*&#+.#%*;;;;;--=%#@++....+#&*;;;;;---;;;;;&$.", +"$%&***=**=***&&$#++.@#%&****&%%%&**&%$@..++@#$&******&%##++.+++##$&******&%$#++..++@#%%******&%##++..++@#$&******&$$@@+..++@#$&******&%$#++...++@@@+++.+++@@@++.+#$====*=****&%$#@+..+@@$%&******&&$#@+..++@#%&*******%%#@+..++@$%&**=***&&$#@+..++@#%&*******%%#@+...+@#$&*******&%#@+.@#%&*****&%#@++.....+@#%&***********&$#.", +"@#%%&%&&&%&&%$$@@++.+@$$%%%$$##$$$$$#@+...++@##%%&%%$##@++....++@#$$%&&%%$##+++...++@#$$%&%%$##@++....++@#$$%&%%$$#@++....++@##%%&&%%$##@++....++++++...+++++++.+#$*==&&%&&%%$#@@+....++@#%%&&&&%$$#@+....+@##%%&&&&%$$#@++..+++@#$%%%&&%$$#@++...+@##%%&&&&%$$#@++....+@#$$&&&&%$$#@++.+@$$%&%%$##@++.......+@$$%&%%%$%%%%%$#@.", +"+@@#####$####@@++...++@@####@@++@@#@@++....+++@@#####@@++......+++@@#####@@++......+++@######@@++......+++@######@+++......+++@@#####@+++.......+.+.......++....++@##$$$#####@@+.......++@@#######@+++......++@######@@+++.....++@@#######@+++......++@######@@+++....++++@@#####@@+++..++@@#####@+++........++@@######@####@++.", +".++++@++@+@+++++......++++++.++++++++.......+++++++++++.........+++++++++++.+........++++++++++.........+.+++++++++.........+++++++++++.........................+++@@@@@@+++++++.........++++@+++++.........++++++++++++........++++@+@++++.........++++++++@+++........+++++@+@++++......+++++++++............+++++++++++++++..", +".....+++++....................++.+..............++++......................................................+++++@+...................................................++++++....................+++++............+++++.................................+++++....................++++++............++++............................", +"....+++@@+++................++++@@++...........+++@@++...........+..+.+..+...............................++@###@@++.................................................+++@@+++.................+++@@@++..........+++@@++..............................+++@@+++.................+++@@++++........++++@@++..........................", +"..+++@####@+................+@####@++........++@####@@...........+++@+@@+++...............+.............++@#$%%$#@+...............................................+.@@####@+.................+@####@@+........++#####@+...........+....+..+.......+++@####@+.................+@####@++........+@####@@+...........+....+.+......", +"...+$$%==$#@++...........+++@$%%==#@++......++@#$*=*$#++.......+++#$$$##$#@++........+++++++++...........@#**--=%#@+...............................................+#$%==$#@++.............++@#$==%$#++......++#$*=*$#@+.........++++++++++........+$$%==$#@++.............++@#$==&$#++.....++@#$*=*$@++.........++++++++++.....", +".+++#%&==&%#@+...........++##&&*==##+.......+@#%&===%#@+......++@#$&&&&&&%$@++.....+++@@@@@@@@++.......++@$*=>>-%$@++............................................+++$%&==&%#@+.............+@#$&==&%$++.....++@$%===&$#@.......+++@@@@+@@@+@++...+++#%&==&$$@+.............+@#$&==&%$++.....+@#%&===%$@+.......+++@@@@@@@+++....", +"..++$%*--*&%#@+..........+@#%**===$#++.....++#%&*--=*%#@+....++@$%&*=****&%#@+....++@##$$######++......++#%==>>>&$#@.........+......+................+...+........++$%*--*&%$@+...........+@#$&*--*%$++.....+@#%*=--*&$#++....++@##$#######@+++...++$%*--*&%#@+...........+@#$&*--*%$++....++#%&*---&%#++.....++@##$$######++...", +"..++#$&->>-=%#++........++#%*>>>=*$#++.....+@$%>;;;;=*$@+....+@#**=;;;;;;>*%#++...++$&&==%%%==#@+......++#%=>=-===#++.....+++++++++++++++........+++++@+++++......++@$&->>-=$#@+.........++#$==->>&$#++....++#$==;;;>>%$@+....++$%&==%$%==%%#++...++#$&->--=$#++.........++#$===>>&$@++....+@$%>;;;;=*$@+.....++$%&==%%%==#@+...", +"..++@$&->>--&$@+.......++#$**;;;=*$@+....++@#%*>;;;;==%#++...+@$*=-;;;;;;>*%$+...++#%&*==&*&-=$#++.....+@$&->--==*$@++....++@@#@@@@@@#@@+++....+++@#@#@##@@@++....++#$&->>>-&$#@+.......++#$&=-->>&$#+.....+@$%=-;;;>>&$#@+..++@%&*==&&&==&&$@+...++@$&>>>>-%#++........++#$&=-->-%$@+....++#$*;;;;;==$@++...++@%&*==&*&-=$#++..", +"..+@#%&==>>>&%#++.....++@$%==>--**$@+.....+@%&=---==>-%#@+..++#%=---->>>-=*$#++..+@#&*==-=====%$@+....+@#$*=->>>*&$@+...++@$%%%%$$$%%%%%#@+.+.+@@#$%&&%%%%$$@@....++#$&==>>>=&$#@+....++@#$&*>>>==*$#@+..+++#$*->-----=&%@+..++#%&*--====-**%#+....+@$&==>>-&$@+.......++@$&*>>>**$#++....+@%&*->----=$#++...++#%**--=====$#++..", +".++@$%*==>>>*&$#++...++##%*=->>-=&%#++...+@#&*=----=>-&$@+...@#%=->-->>>-=*%#+...+@#&*=---==-=&$@+...++@$&*->>>>**%#++..+@$%&***&&&*****%$#.++@#$%&***=****&$#+..++@$%*==>>>=*&%#@+..++@#$&*=>>>==*&$@+...+@$&*>>--->-=*&#@..+@$&*=-====--=*&$@...++#$&==>>-*$#+......++@#&*=>>>*&$@+....++@%*=->--=-=$#+....++#%*=--=====%#+...", +".+@#%**==>>>=*%#@+...+@#%&*--->-=*&$@+...+#$*==>>=-->>*%#++.++$%=->-->>>--&%#@..++#$*==>>--->-&$#++..+@#%*=->>>>=*&$@++.@#%*====**=*===**%$.+#$%&*========**&$@..+#$%**==>>>==**%$@..+#$%**==>>>==**%$@.++#$%**>>--->-==*%#.++#$*==->===>-==*%#...+@#%*==>>>*%#++.....+@#%&==>>>*&$@+....++#&*=->--=-=$#+....++#&*=->-=-==$@++..", +"++#$=->;;;;;;>*%#++.++@%=>>;;;;;;>&%#@+.++#%=>>;;;;;;;*&#@+.++$&->>;;;;;;;*&#@+.++#%->>;;;;;;;*&#@+.++#$-->;;;;;;>*%#++.@%*;;;;;;;;;;;;;--%.@#%---;;;;;;;;;;*&#.+@#%=->;;;;;;;>--%#.+@#%=->;;;;;;;>--%#..@#%->>;;;;;;;>>-%$.+@$&=->;;;;;;;>>-%$..++@&*=;;;;;*%#+......+@&*=;;;;;*&#+.....++#&==;;;;;*&$@+....++#&==;;;;;*&$@+...", +"++#%->>;;;;;;;*&$#+.++#%->>;;;;;;;*&$@+.++#&->>;;;;;;;=&$#+.+@#&>>>;;;;;;;*&$#+.+@#%->>;;;;;;;**$#+.++#%->>;;;;;;>*&$#+.#%*;;;;;;;;;;;;;>-*.@$&->>;;;;;;;;;;=&$.+@$&->>;;;;;;;>>-&%.+#$&>>>;;;;;;;>>-*$.+@$&->>;;;;;;;>>-*$.+#$&>>>;;;;;;;>>-*$...+@&*=;;;;;*&#@+.....+@%*=;;;;;*&#@+....++#&*=;;;;;=&$@+....++#&*=;;;;;=&$@+...", +"+@#&=->---=-;;==*#+.+@$&=->---=-;;==*#+.+@$%-->-----;;==*#+.++#%=-----=-;;-=*#+..@$&=->-----;;-=*#+.+@#&=->-----;;==*#+.#$*-->>-;;;-----;;*.#**;;;>>===>>;;;=*$.+#%*;;;>>===>>;;;*&.+#**;;;>>===>>;;;*&.+#%*;;;>>===>>;;;=&.+#**;;;>>===>>;;;=&...++#$**=;;;*&#+......++#$**=;;;*&#@......+@#%**=;;;*&$@+.....+@#%&==;;;*&$@+...", +"+@$&-->----=;;-=*$@..@#&-->----=;;-=*$@.+@$%=->--=-=;;-=*$@.+@$%==>----=;;-=*$@.+@#&-->--=-=;;-=*$@.+@$%-->--==-;;-=*$@.#%*-->--;;;--==-;;*.$&=;;;-=***--;;;=&$.+$%*;;;>>=-=>>;;;=*.@$&=;;;>>=-=>>;;;=*.+$%*;;;>>=-=>>;;;=&.@$&=;;;>>=-=>>;;;=&...++@$&*=;;;*&$++.....++@#&*=;;;*&$++.....++@$&*=;;;*&#++.....++#$%*=;;;*&#@....", +"+@$&-->--=--;;-==$#.+@$&-->--=--;;-==$#.+@$&-->--=--;;-==$#.+@$&=----=--;;-==$#.+@$&-->--=--;;-==$#.+@$&-->-----;;-==$#.#%*->>->;;;---=-;;*.$*=;;;=**%&&*--=*%#.@$**;;;>>===>>;;;=*.@$*=;;;>>===>>;;;=&.@$**;;;>>===>>;;;=*.@$*=;;;>>===>>;;;=*....++@%&=;;;*&#@.......+@#$&=;;;*&#@.......++#%&=;;;*&$@.......++#%&=;;;*&$++...", +"+@$&->>;;;;;;;-==$#.+@$*->>;;;;;;;-==$#.+@%&>>>;;;;;;;-==$#.+@$&->>;;;;;;;-==$#.+#$&->>;;;;;;;-==$#.+@$*->>;;;;;;;-==$#.$*=;;;;;;;;;;;;;;;*.$*=;;;=*&%%&*=-=&$#.@#*=;;;;;;;;;;;;;=&.@$*=;;;;;;;;;;;;;=&.@#*=;;;;;;;;;;;;;**.@$*=;;;;;;;;;;;;;=&.....+@$&*;;;**#@+.......+@$&*;;;*&$@+......++@$&*;;;*&$++.......+@$&*;;;*&$++...", +"@#%*>>>;;;;;;;-==%#.@#%*>>>;;;;;;;-==%#.+#%*>>>;;;;;;;-==%#.+#%*>>>;;;;;;;-==%#.+#%*>>>;;;;;;;-==%#.@#%*>>>;;;;;;;-==%#.%*=;;;;;;;;;;;;;;;*.#*=;;;==&&%&&=*=*%#.@$*=;;;;;;;;;;;;;=&.@$*=;;;;;;;;;;;;;=*.@$*=;;;;;;;;;;;;;=*.@$&=;;;;;;;;;;;;;=&....++@%&=;;;*&$@+......++@%&=;;;=&$@+......++@%&=;;;*&$@++.....++#$&=;;;*&$@+...", +"+$*=;;;-====;;-==$#.+$&=;;;-====;;-==%#.@#*=;;;-====;;-==%#.@#&=;;;-====;;-==%#.@$*=;;;-====;;-==%#.+$&=;;;-====;;-==$#.&>>>>>==;;;>>>>>>>*.#&*;;;--=**=*===**$.@$*=;;;;;>>>>>>>>=&.@$*=;;;;;>>>>>>>>=&.@$*=;;;;;>>>>>>>>**.@$*=;;;;;>>>>>>>>=&...++@#%&=;;;=*$#@+.....+@#%&=;;;**$#@+.....+@#%&=;;;=*%#++.....+@#%**;;;=*%#@+..", +"@#&=;;;=--==;;-==%$.@$&=;;;=--==;;-==%#.@$&=;;;=--==;;-==&#.@#*=;;;=--==;;-==%#.@#&=;;;=--==;;-==&#.@#*=;;;=--==;;-==&$.&>>>>;==;;;>>>>>>>*.#%*>>>;;;>>>>;;;>=$.@$&=;;;;;>>>>>>>>=*.@$*=;;;;;>>>>>>>>=*.@$&=;;;;;>>>>>>>>=&.@$*=;;;;;>>>>>>>>=&...++#$&*=;;;=*&$#@+..+++#$&*=;;;=*&$#@+..+++#$&*=;;;=*&$#@+..+++#$&*=;;;=*&$#@+.", +"@$*=;;;-====;;--=&$.@$*=;;;-====;;--=&$.+$*=;;;-====;;--=&$.@$*=;;;-====;;--=&$.@$*=;;;-====;;--=&$.@$*=;;;-====;;--=&$.&>>>>>==;;;>>>>>>>*.@$%>>>;;;;;;;;;;--$.@$&=;;;;;>>>>>>>>**.@#&=;;;;;>>>>>>>>*&.@#&=;;;;;>>>>>>>>=&.@#&=;;;;;>>>>>>>>=&.+++#$%**=;;;==*&$#@..++#$%**=;;;==*&$#@..++#$%**=;;;=**&$#+..++#$%*==;;;=**&$#+.", +"@$&=;;;;;;;;;;;;>*%.+$&=;;;;;;;;;;;;>*%.@#&=;;;;;;;;;;;;>*%.@#&=;;;;;;;;;;;;>*%.@$&=;;;;;;;;;;;;>*%.@#&=;;;;;;;;;;;;>*%.&>>;;;;;;;;;;;;;;;*.+#$&*=->;;;>>>--*%$.+#%*;;;;;;;;;;;;;*&.@#%*;;;;;;;>;;;;;=&.@#%*>;;;;;;;;;;;;*&.+#%*;;;;;;;;;;;;;=&..+@#=-->>;;;>>--=$@.++@#=-->>;;;>>--=$@.++@#=-->>;;;;>--=$@.++@#==->>;;;;>--=$@.", +"+#&=;;;;;;;;;;;;;*%.+#&=;;;;;;;;;;;;;*%.@#&=;;;;;;;;;;;;>*%.@#&=;;;;;;;;;;;;;*%.+#&=;;;;;;;;;;;;>*%.@#&=;;;;;;;;;;;;;*%.%->;;;;;;;;;;;;;;;&..+@#$*=>;;;>>-==%#@.+@$&>;;;;;;;;;;;;*&.+@$&>;;;;;;;;;;;;*&.+@#&->>;;;;;;;;;;*&.+@$&>;;;;;;;;;;;;*&.++#$=->>;;;;;>>-=$#..+#$=->>;;;;;;>-=$#..+#$=->>;;;;;;>-=$#..+#$=->>;;;;;>>-=$#.", +"@#$&-->>>>>>>>>>-&$.@#$&-->>>>>>-->>-&$.+#$&-->>>>>>-->>-&$.+#$&-->>>>>>-->>-&$.@#$&-->>>>>>-->>-&$.+#$&-->>>>>>-->>-&$.%*=>>>>>-==>>>>>=&%...++#%==;;;>-*%$@++.+@#%&*=->>>>>>===&$.++#%&*=>>>>>>>==*&$.+@#$&*=->>>>>>==*%$.+@#$&*=->>>>>>==*%$..+@$==->>>>>>>--=%#.++@$==->>>>>>>--=%#.++@$==->>>>>>>--=%#.++@$===>>>>>>>--=%#.", +"+@$%=-->>>>>-->>-&$.+@$%==->>>>>-->--&$.+@$%=-->>>>>-->--%$.+@$%=-->>>>>-->--&$.+@$%=-->>>>>-->--&$.+@$%=-->>>>>-->--%$.#&*->>>-===>>>--&%$...++#%*=;;;>-&$@++...+@#$&*=->>>>>=*&$#.++@#%&*->>>>>>=**$#...@#$%&=->>>>-=**$#..+@#$&*=-->>>>=**%#..+@$*==>>>>>>>-==$@..+@$*==>>>>>>>-==$@..+@$*==>>>>>>>-==$#..+@$*==>>>>>>>-==$#.", +"++@%*==------=-==$#..@@$===-----==-==$#.+@@%*==-----==-==$#.+@@%*==-----==-==$#.++#$*==-----==-==$#.+@@%*==-----==-==$#.#$&==---***=---=%$@...+@#%->;;;==%#@+.....+@@$$==----=*&%#@...+@#$%=-----=*&%#+...++@$%==----=&&$#+...+@@$$==----=*&%#+.++@#&*=->-----==*#@.++@#&*=->-----==*#@.++@#&*=->-----==*#@.++@#&*=->-----==*#@.", +".+@#$$%&&&&&&&%%$#@..++##%%&&&&%&%%%$#@..++#$%%&&&&%&%%%$#@..++#$%%&&&&%&%%%$#@..++#$%%&&&&%&%%$$#@..++#$%%&&&&%%%%%$#@.+#$$%%%%%%$%%%%$#@@....+#%->;;;=&$@+.......++@#$$%&%&%$##++....++##$%%&&&%$$@@+...+++@#$%%&&%%$#@++....++@#$%%%&%%%#@@+...+@#$%%&&&&&%%$$#+...+@#$%%&&&&&%%$$#+...+@#$%%&&&&&&%$$@@...+@#$%%&&&&&&%$$@+.", +"..++@##$#$$$#$##@++...+@@@##$#$#$###@++...++@@##$#$#$###@@+...++@@##$#$#$###@++..+++@@##$#$#$###@++...++@@#$#$#$$###@++.++@#$###@#######@+....++@#%&**&%$#++........++@@##$####@++......++@###$###@@++......+++@###$###@++......++@@###$##@@++....+++###$$$$$$##@++...+++###$$$#$$##@++...+++###$$$$$###@++...+++###$$$#$###@++.", +"..+++++@@+@@@@+@++.....+++@+@@@+@+@+++....++++@+@@@+@@+@++....++++@+@@@+@+@+++....++++@+@@@+@@@+@+....+++++@@@@+@@+@+++..++++@@@+++@@@++++.....++##$%%$$@@+...........++@+@@@+++.+.......+++@@@@@++++........++++@@@++++..........++@@@@@+@+.+.....++++@+@@+@@+++......++++@+@@@@@++++.....+++@+@@@@@@++++.....++++@@@@@@@+@++..", +"..++++@@+@++@+@+.+.........+.+.+.+............+.+......................+..+............++++@++.............+.+++++........................................................................+.......................++.+...............+++.+......................................+.+......+++@++++...............................", +".++@##########@@++........+++@+@++++.........+++++++..................++@++++.........++@##@@++............++@+@+@++++.................................................................++++++++.................+++@@@++..........++@+@@++...................................++++@+++...++@####@++..............................", +"+@#$$%&&*&&%&&$$#@+....+++@###$###@+++.....++@@##@@++...............++@####@+........+@#$%&&$#@+.........++@#$#$###@+++................................................................+@####@+...............+++###$$@@.........++@#$##@@+................................+.+@###@@+...+#$%&&%$#@+.............................", +"+#$&***==***=**%$#+.....+##$%%&%%%##++....++@#$%%$#@++.............++@$$%%$#@++.....+@#$&***&$#@+.......+@@$%%&&%%$$#@+......+.+..+.++.............+.++..............................++@#$$%$#@++..............@@$%%&%$@++......++#$%&&%$#++.........+.+.+..+.+............+@@$$%%$#@++.@$%*=**&$#++...............+.+.+.+.+....", +"@$==;;;;;>;>;;--=$@..+++@$%--=-=-=&%#++....+$%&>>*&$@@...........+.@#$&*;;&%#++.....+@$*=;;;=*$@++......+@$*=>>>===**#+....+.++@+++++@+++..........+++@+++...........................++$%*>>*&$#++..........+++#$===>-%#++....+++#$*=>>>&$#++.....+.+++@++@+@++++.......+.++@%&*;;&%#++.#%*;;;;>&$@++...........+++++@+++@+++...", +"#$=-;;;;;>;>;;>-=$#..++@$%&>>-----*%$++...++$&*>>=*&$@++.........++@$&*=;;*%$+....++@#&=-;;;-=&#@+....++@#%==>>>====*#@....+@@#########@+++......++@#$##@++..........+.+++++++++....++@$&*>>=*&$#++........+++@$%==->>%$@+....++@$%==;;>*%$@++....+@@#########@@+.......++@@$&*=;;*&%@+.#&*;;;;>*%#@+..........++@##########@@+.", +"#%=-;;;;;;;;;;>>=%#..+#$%**>>>>>>-*&$@+...++$&*>;==*%$@+.........+@$%*==;;*&$++...++#$&=-;;;-=&$#++...++#$&==;;>-=-==$@..+++##%%%%%%%$$$@++......+@#%%%%$@@.........+++@@#@#@#@@@++.+@#%*=>;==*%$#@@+....++@@#$%&--->>&$#++..+@@$%*=-;;;=*%$@++.++@##$%%%$%%%%$#@@..++++@@#$%*==;;=&%#+.#&*;;;;;*&$#@@++....+++@#$%%%%$%%%%%##@.", +"#%=->>>;;;;;;;==*%#.+@$%-->>>;;;;>*%#++...++#%*==;;>*%#@+.......+@#%*>;;-=*$#@....+@$**>;=-=;;*&$++....@$&*>;;;;;;=*&#@..++@&**->*&*>>**&@+....++@#**>>-&#@++......++@#$$$$%$$$$#@+.@#$%**==;>>*%%$@@++.++@#$$&*=>;;==*%$@+.++#$&*=;;>>->>&%#@+.+@#%*==>-***;;&%$@+.++##$$%&&>>;-==*&$#.@$&=--;;==**&%$#@++.+@@$$&&;;***>-==*$#.", +"#$=-->>;;;;;;;==&%#.@#%*->>;;;;;>>*%#@+..++@#%&=-;;;**$$@+.....+@#%&*;;;-=*%#++...+@%*=>;=-=;;=*$@+..++@%*=>;;;;;;=**#+..++#*==>>=*=>>=*&#+.....+@$*=>>>&$#+.....++@#$%&&**&**&&%$@.#$&**==-;;;=*&&$#@+.@#$%&**==>;;==*&%$@.@#$&*==;;->>>>=&%$@.+#$&===>>*==;;**%#@.+#$%&&***;;;=-=**%$.@#%=--;;>>>>>=*&#@+.+#$%***;;=**>>===&%.", +"@$*=;;;----=;;>>-&$.@$=->>;-->>>>>*&$@+...+@#&*>>;;;>>&$#@+...+@#%&>>>;;>>*%$@+..+@#%*=>>;;;>>*&%#+...+@$&*>>;;;>>=*%#@.++@#&*=>>;>>>>**%#+....+@#%=-;;;*%#++....+@#$%->>>>>>>>>=*#.$*=>>>=====>>--=$#+.@$*=>>>==*==>>>-=$#.@#==>>;=====>>>-=$#.@$==>>>===*=>>>-=%#.@#==>>>--===-->>>==.+#$==-;;>>>>>==*&#@.@#==>>>>-=*=>>>>>==.", +"@$&=>;;--=--;;>>>&$.#$==;;;-->>>>>=&$#+.++@#%**>>;;;>>*&%#@.+++#$&*>>;;;>>**%#@..+@$**=>>;;;>>=*%$@..+@$%*=>>;;;>>=*&$@..+#$*==>>;;;>>=*%$@....+@$%=-;;;*%$++...++#$&*>>>>>>>>>>-=$.$=->>>==**=>;>>-&#@.#$==>>>==*=*>;>>-%$.#%==>>;=====>;>>-&#.#$==>>>==*==>;>>-%$.#$==>>;--=*=->>;>==.+#$==-;;>>>;>-==&$#.#$==>>;>>*=*>>;;>-=.", +"@#&=;;;---=-;;>>>*%.#%=-;;;-->>>>>=*&$@..+#%&*=>>;;;>>=*&$#.++#%&*=>>;;;>>=*&$#.+@#%*==>>;;;>>=*&%#.++#%**=>>;;;>>=*&%#.+@#%*==>>;;;>>=**%#..++@#$&--;;;*&$#@++.+#%&*=>>;;;>>;>>==$.%=-;;>==**=>>>>-&$@.#%=->;>==**=>;>>-&$.#%=-;;;=====>;>>-&$.#%=-;;>==*==>;>>>&$.#%=->;>>==*=->;;>-=.+#$==-;;;;;;;;;;=*$.#%=-;;>>-=*=>>;>>-=.", +"@#%*->>;;;;;;;;;;=&.#%==;;;;;>>>;;>>-%#.+@$&>;;;;>>>;;;;>&$.+@$&>;;;;>>>;;;;>&$.+@$&>;;;;>>>;;;;>&$.+@$&>;;;;>>>;;;;>&$.+@$&>;;;;>>>;;;;>&$..+@#%&*===-=**&%$@+.@$&>>;;;>>>;;;;;**$.%==;;;==***>;;;;*%#.#%==;;;==**=>;;;;*%.#%==;;;-=**=>>;;;*%.#%==;;;-=***>;;;;*%.@$*=;;;>>===->;;;=*.+#$==-;;;;;>;;;;==%.@$=-;;;>-=*=>>;;;==.", +"+#%*>>>;;;;;;;;;;=&.#$=-;;;;;>>>;;>>-&$.+#$*;;;;;>>>;;;;>*%.+#$*;;;;;>>>;;;;;*%.+#%*;;;;;>>>;;;;>*%.+#$*;;;;;>>>;;;;>*%.+#%*;;;;;>>>;;;;>*%.+@$$**===-===***&$@.#$*;;;;;>>>;;;;;*&$.$=-;;;-=***>>;;;*%#.#$=-;;;-=***>>;;;*%.#$=-;;;-=***>>;;;*%.#$=-;;;-=***>;;;;*%.@$%*>>>;>===;;>>>*&.+#$==-;;=====;;;>>&.@$*=;;;>>===->;;;=*.", +"+$%*>>>;;;;;;;;;;=*.#$==;;;;;>>>;;>>>&$.+$%*;;;;;>>>;;;;;*%.+$%*;;;;;>>>;;;;;*%.+$%*;;;;;>>>;;;;;*%.+$%*;;;;;>>>;;;;;*%.+#%*;;;;;>>>;;;;;*%.@#%&*=====-====**%#.$%*;;;;;>>>;;;;;=&$.$==;;;-=***>>;;;*%#.@$==;;;-=***>>;;;*%.@$==;;;-=***>>;;;*%.#$==;;;-=***>;;;;*%.+#$&->>;;===;;>>-&$.+#$==-;;=**==>;;>>&.@#%*>>>;>===;;>>>*%.", +"@#*=;;;>>====-;;;=*.@$&*;;;>>===--;;;*%.@#*=;;;-==*===;;;=*.@$*=;;;===*===;;;=*.@$*=;;;===*===;;;=*.@$*=;;;-==*==-;;;=*.@$*=;;;-=*====;;;=*.@$=-;;;;;;;;;;;;;&%.$*=;;;=->>>;;;;;=*$.$&*;;;-=***--;;;*%#.@$&*;;;==*&*=-;;;*%.@$&*;;;==*&*=-;;;*%.@$&=;;;-=***=-;;;*%.+@#%*==;;=--;;==*%#.+#$==-;;==**=>->>>*.+#$&->>;;===;;>>-&$.", +"@$*=;;;--=*===;;;=*.+$&=;;;>>=*==-;;>*%.@$*=;;;==***==;;;=*.@#*=;;;==***==;;;=*.@$*=;;;==***==;;;=*.@$*=;;;==***==;;;=*.@$*=;;;==***==;;;=*.@$=-;;;;;;;;;;;;;&$.#*=;;;-=>>>;;;;;=&$.$&=;;;-=*&*=-;;;*&#.@#&*;;;-=*&*=-;;;*&.@#&=>;;==*&*=-;;;*&.@#&*;;;-=&&*=-;;;*&..++#%*=;;---;;=*&#+.+#$==-;>===*=-->>>&.+@#%*==;;=--;;==*%#.", +"@#*=;;;==****=;;;=*.@#&*;;;-=***--;;;*%.@#*=;;;=*****=;;;=*.@$*=;;;=**&**=;;;=*.@$*=;;;=*****=;;;=*.@#*=;;;=*****=;;;=*.@#*=;;;=**&**=;;;=*.+#%&**=======*=*&%#.$*=;;;>-;;;==;;;=*$.#%*;;;-=***=-;;;*%#.+$&*;;;-=*&*=-;;;*%.@#&*;;;==*&*=-;;;*&.@#&*;;;==*&*=-;;;*%..++@$%*>;;;;;>*&#@+.+#$==-;;---==;;;-=&..++#%*=;;---;;=*%#+.", +"@$*=;;;=****==;;;=*.+#&*;;;--***=-;;;*&.@$*=;;;=**&**=;;;=&.@$*=;;;=*****=;;;=*.@$*=;;;=**&**=;;;=*.@$*=;;;=**&**=;;;=*.@$*=;;;=**&**=;;;=*.+@#$&&**====***%$#@.$*=;;;--;;;==;;;=*$.#%*;;;-=***--;;;*&$.+#%*;;;-=***==;;;*&.+#%*;;;-=***==;;;*&.+#%*;;;-=***==;;;*&....+#%*=-;;;-=&$@+..+#%==-;;;;;;;;;>=*$...+@$%*>;;;;;>*&$@+.", +"@#*=;;;===**==;;;=*.@$&*;;;--***--;;;*&.@$*=;;;==***==;;;=*.@$&=;;;==***==;;;=*.@$&=;;;==***==;;;=*.@#*=;;;==***==;;;=&.@#*=;;;==***==;;;=*.++@##%**====*&$$#@+.#*=;;;>-;;;==;;;=*#.#%*;;;--*=*--;;;*&#.@#%*;;;-==*==-;;;*%.+#%*;;;===**=-;;;*&.@#%*;;;===**=-;;;*&...+@#&*=-;;;=*%#+...+#$=--;;;;;;;;>>*&#...++#$*=-;;;-=&$@+..", +"@#&=;;;>>===->;;;**.@$*=;;;-==*==-;;;=&.@#&*;;;>>===>>;;;*&.+$&=;;;>>===>>;;;*&.@#&=;;;>>===>>;;;*%.@#&=;;;>>===>>;;;*&.@#&=;;;>>==*>>;;;*%..+++@$%=-;;;*%$@++..$**;;;;;-=->;;;;*%#.#%*>;;>>===>>;;;=&$.+#%*>;;>>===>>;;;=&.+#$*;;;>>===>>;;;=&.+#%*>;;>>===>>;;;=&..+@#$&*>>;;;=&$@+...+#%==-;;;;;;;>>>*%@....+#%&--;;;==%#@+..", +"@#&*;;;>>===>>;;;*&.#%&=;;;-==*=--;;;=*.+#&=;;;>>===>>;;;*%.@#&*;;;>>===>>;;;*%.@#&*;;;>>===>>;;;*%.@#&*;;;>>===>>;;;*%.@#&*;;;>>===>>;;;*%....+@#%=-;;;*%#++...#*=;;;;;-==>>;;;*%#.@$&>;;>>===>>;;;=*%.+@$&>;;>>===>>;;;=*.+@$&>;;>>===>>;;;**.+@$&>;;>>===>>;;>=*..+@$&*=>>;;;*&$@+...@#%=--;;=====**%$#@..++#%&*>>;;;=&$@++..", +"+#$*=->;;;;;;;>--*$.#&->;;;;;===;;;;;>-.+#$&-->;;;;;;;>--&$.+#$*=>>;;;;;;;>--&$.+#%&-->;;;;;;;>--&$.+#$&-->;;;;;;;>--&$.+#$*=->;;;;;;;>-=&$.....+#$==>>-&$@++...$&*;;;;;;;;;;>-=&$#.+#%*==;;;;;;;;;;>-%..@#%*==;;;;;;;;;;>-.++#%*==;;;;;;;;;;>-..+#%*==;;;;;;;;;;>-.+@#%->>;;;;;*&#+....@$&=--;;===**&%##++..+@$&*=>>;;;*&$@+...", +"+@#&=--;;;;;;;--=&#.#%>>;;;;;===;;;;;>-.+@$%=--;;;;;;;--=%#.+@$%=--;;;;;;;--=%#.++$%=--;;;;;;;--=%$.+@$&=--;;;;;;;--=%$.+@#&=--;;;;;;;--=%$....++@$&=---%$@+....$&*;;;;;;;;;;--=%#@.+@$&==;;;;;;;;;;>-%..+@$**=;;;;;;;;;;>-..+@$&*=;;;;;;;;;;>-.++@$&*=;;;;;;;;;;>-.+@$&>>;;;;;;*%#@....#&*>;;;;>>>*%$#@++..+@#%->>;;;;;*&#+....", +"++#$==-;;;;;;;-==$@.#%->;;;;;===;;;;;>-..+#$==-;;;;;;;-==$#..+@$==-;;;;;;;-==$#.++#$==-;;;;;;;-==$@..+@$==-;;;;;;;-==$@.++#$==-;;;;;;;-==$@.....++#&*===$#++....#&*;;;;;;;;;;-==$@+.+@#%&=;;;;;;;;;;>-%..++#%*=;;;;;;;;;;>-..++@%&*;;;;;;;;;;>-..++#%&*;;;;;;;;;;>-..@$&>>;;;;;;*%#+....#&*;;;;;>>-&$@++.....@$&>>;;;;;;*%#++...", +".++#$%&***=***&%$#@.@$%*******&******&%.+++#$%&***=***&%$#+..+@#$%&***=***&%$#+..++#$%&***=***&%$#@.++@#$%&***=***&%$#@..++#$%&***=***&%$#@......+@@$$$$#@+.....$==>>>==*=***&%$#@+..+@#$%****=**=**&%$..+++#$%****=**=**&%...++#$%****=**=**&%...++#$%****=*****&%.++$%->>>>>>-&$@+....@$&>>>>>>--%#++.....++#&->>>>>>-&$@+....", +"..++##$%&&%&&%$#@@+.+#$$&&&&%$%$%&&&%$$...++##%%&&%&&%$#@@+...++##$%&&%&&%$##++...++##%%&&%&&%$#@@+...++##$%&&%&&%$#@@+...++##%%&%&&&%$$@++.......+@@##@+++.....#*=->>**&&&&%$$@@+....++##$%&&%&&%&%$$@...+++##$%&&%&&%&%$$...+++##%%&&%&&%&%$$....++#$$%&&&&&&&&$#.++#%--->---=$#@+....@#%-->->-==$#+......+@#$--->---=$#++....", +"...++@@#######@@++..++@@######@######@@....++@@@#######@++.....++@@#######@@++....+++@@@######@@++.....++@@#######@@++...+.++@@#######@@+++.....+..+++++++......##%&&%%$$$###@+++......++@####$#$###@@+.....++@####$#$###@@.....++@@###$#$###@@.....++@####$#$####@..+@#$&&&&&%%#@+.....+@#%%&&&&%%#@++......+@#%%&&&&%%#@+.....", +"...+.++++@+@++++.+...++++@++++++++@+@++.....+++++@+@++++.+.....+.++++@+@+++++........++++@@++++++.......+++++@+@++++.......+.+++@@+@+++++...........+++.........+@##$###@@++++++........++++@+@+@@@++++......++++@+@+@@@+++.......+++@+@+@@@+++........++++@+@+@+++...+@##$$$$##@++.....+@@#$$$$$##@++........+@#$$$$$##@++.....", +"..............................+++@@@#@@+...........................................................................................................++@+++............+++@++++++++.........+...............++@@###@####@@+++...........................................................................+++++.....................", +"...........................++++@#$$%%$$@......++++.++++.......................................................................+..................++@#@#@++.........++@@@#####@@++........+++++...........+@#$%%%$%$$%$%$#@+..........................+..+.+.+......................................+++@@@+++....................", +"......+......+.........+++@@@@##$%&**&%$....+@+@++@@@@++++..........+.+++++.+...............................+++++..........++++++++..............+@#$$$#@+.........+@@$$$$%$%$#@+......++@@#@@+..........@#%&&********&&$#+............+.+.........++@++@+@+@++@+++................................+@###$##+....................", +"....+++++..+++++.....++@@#$%&$$%==;;;>-%...++#$%###$$$$@+.......+..++@@@@@@@++......+.++.++..+............+@@@@@++.......++@@###@@+.............+@#%=-=%#@+.......++#$========*#@+.....+##%&&#++.........#%*;;;>>>>>>;;>&$@+.........+++@+++.....+@@###$#$#$##$##@@+.............................++@#&**=*$@........+++.........", +"..++@@@@+++@@@@@+.+..@@#$$%**&&*==;;;>>&..+@#$&*%$%&&&%#@++...++@+@@@##$$$$##+++...+++@+@@@+@+@++++.....++@##$$##@++.....+@#$%&%$#@+............+@$&->-&$#+++......@#%--==--===$#++...++$$&=*%@@.+.......#&*;;;>>>>>;;;;*%#+.......++@####@++....@@$$&&%&&%&&%&%%$#@.......+@+++++++.............+@#%**===%$......+@@@@+++......", +".++@#$$$#@@#$$$#@+...#$%&**==**==-;;;>>&..+@$%*=&*&*=**$#++..@@##$#$$%&&&*&&$#@+.++@#$$$$##$#$###@+....++@#$&&&&$#@+++...@#%&***&%#@+........++@@#&*>>>*&$#@+++....@$&->-->---=$#++..++@%&*==&$@+++++....$*=;;;;;>>;;;;;*%#@.......+@#$%%$$@++...@$%***=**=******&%#....++@@#####@@++....++++.+.++#%&==--=&%....++@##$$#@+......", +".+@#%=*=$$#%-=&%$+++.&*-->>;;>-->>;;;>-&.+@%&*;;=-=>>>>&$@+..#$%%&&&&==>>>>>&%#+.+@$&&&&&&&&&&%%$$@+...++#%*;;;==%$#@+++.#$->;;;;&$@+........+@#$$*=;;;=*&%$#@++..+#%*;;>>;;--=%#++...+#%*=;;=*##@@@++++.$&=;;;>>>>>>;;;=&$+......++#$---=*#@+...#%;;;;;;;;;;;;;;-=#...++@$%%%&%%%#@@+...++@++.++@$*=;;;;;=*.....+#%***$#++.....", +".@#%*===&%%*--*&%@+..*=->>>;;>->>>;;;>-%.+#%*=;;--->>>>*$#@+.$&***=*=-->>>>>*&$@.@#%*==*=***=****%#@.++@#$&*;;;-=&%$$#@+.#$>>;;;;*%#@+.......@#$%*==;;;=***&%$@+..+$&*;;>>;;--=%$@+..+@#&*=;;=*%$#$###@+.$*=;;;>>>>>>;;;=&$@......+@#&->-==$@++..#%;;;;;;;;;;;;;;-=$..++@$&&**=**&%$#@+..#####++@#%==;;;;;=&.....+$*===&$#++....", +".#%==;;;*&*=;;=*%@+..**>>;;>>---;;---*&$.@$**=;;=-=>>>>=*$#+.%;;;;;;;;;;;;;;>-%$.@%&;;;;;;;;;;;;--%#.@#$%&*=>>>>-===*&#@.#$&=>>>>*&$@+.......#*=->>>;;;>>>>>=*$@.+@$**;;==>;--=&$#@+.+@$*=-;;=*&&****&#@.%*=;;;;;;;;;;;;*&%@......+@$&>>>=*$@+...@$%**===;;;====**%$.++@$*=;;;;;;-==$#++.$*=&%#@@$%->;;;==&$.....@%=-;;=*#++....", +".#%=-;;;=*==;;=*%@++.&=>;;;>>---;;--=*%#.#%*==;;-=->>>>==%$@.&;;;;;;;;;;;;;;>-%#.#%*;;;;;;;;;;;;>-%#.#$&*=*=>>>>-====*%#.@$&=>>>>=*%#++......$==>>>>;;;>>;>>==$#.@#&*=;;--;;---*&$#@.+#%===;;==**====*%#.%*=;;;;;;;;;;;;=*%#......+@$&>>>=*%@@...@#%%*===;;;==****%#.+@$%==;;;;;;--=&$#+.$==**$##$&->;;;=*&#....+@&=-;;=&#@+....", +".$&--;;;====;;=*%@++.&*>;;;>>-=-;;-==&%#.$&==-;;=-=>>>>==&%#.%;;;;;;;;;;;;;;>-%#.#&*;;;;;;;;;;;;>>%$.$&*====>>>>>--===&$.@$&*>>>>=*&$#+......%==>>>>;;;>>;;;==%#.#%*==;;==;;---**&$#.@$%==-;;-========&#.%==;;;;;;;;;;;;=*&$......+@%&>>>=*%@+...@#$%&**=;;;=*=**&%$.@$%*=-;;;;;;>--*&$@.%=-==%$$%&->;;;=*$#....+@&->;;=*#@+....", +".$&>;;;;--=-;;*%#@+..%*==;;=====;;>>>*$#.==;;;;;;;;;;;;;;=*&.%&*===;;;;;;===*%#@.$&=;;;--====;;;=*&#.*=;;;;;;;;;;;;;;;&$.@$&=;;;;>>-%#@+.....&--;;>>;;;>>;;;>-&$.$->>>;;>;;;;;;>>=**.@$*>;;;;;;;;;;;;;%$.&->;;;;;>>;;;;;;>=&.....++@$*>>>=*%@++..#$$%**==;;;=======$.#%==>>>>;;==;;;-=%#.%=-;;*%%%*--;;;*&$@...+@#*;;>-*$#++....", +".#%;;;;;----;;*%#++..$%==;;=**==;;>>-*%#.*=;;;;;;;;;;;;;;=*%.#$%&*=;;;;;;==*%$#+.$&=;;;-==**=;;;=*$#.==;;;;;;;;;;;;;;;*%.@$&=;;;;;>>&$@+.....&->;;>>;;;>>;;;>>&$.%->>>;;>>;;;;;;>==*.#%*;;;;;;;;;;;;;;%$.&->;;;;;>>;;;;;;>=&......+@%&>>>=*$@+...$%&**==-;;;=====-=%.$&-->;>>;;==;;;-=&$.%=-;;*&&&*--;;;*%#+...+@#*;;-=&$#++....", +".#$&*---;;;;--*$#++..#&=->>****=;;;;;=*$.$*==-;;-=->>>>=*&$#.@@$%&*--;;=**%$#@++.$&*;;;-=***=;;;=*%#.%&=-->>;;;==>>>;>*%.@$&=->;;;>>&$@+.....&->>>==;;;==;;;>-&$.&->>>;;>>;;;;>>>-==.$&=;;;=---;;-==*&%#.%--;;;;;>>>>>>>>-*%......+#$*>>>=*%@++..==->>>>;;;;>>>>>>-&.%*;;==;;--==->>;;*$.$&*;;==***;;>>>*$#+...+@%=;;=*&$#++....", +".@#%*==-;;;;--&$@+...$&=->>*&**=;;;;;=*%.$%==-;;=-=>>>>*&%#@.++@#%*->;>=*%$@@++..$&*;;;-=*%*=;;;=*$@.$%==->>;;;==>>>>>*$.@$*=->;;;>>&$@+.....&->>>==;;;==;;;>>&$.%->>>;;>>;;;;;>>-=*.$*=;;;=-==;;===&%#@.%=-;;;;;>>>>>>>>-&$......+#%*>>>=*$@+...==>>>>>;;;;>>>>>>-%.&*;;==;;-=*=->>;;*%.#&*;;-=**=;;>>-%$@+..++#&=;;=*&%##@++..", +".+@#%==-;;;;>=&$@++..$&-->>**&*=;;;;;==%.#$*==;;-=->>>>*&#@+..++#$*--;;*%$@++....$&*;;;-=&%&*;;;=*$#.@$*==->;;;==>>>>>&%.$%*=->;;>>>&#@+.....&->>>==;;;==;;;>-&$.$=>>>;;>>;;;;;>>==*.$*=>;;-=--;;=**$@@+.%=-;;;;;>>>>>>>>-%$......+#%*>>>=*%@++..===>>>>;;;;>>>>>-=%.&=;;--;;-=*==>-;;*%.@$&;;=====;;>-=%#+...+@$&=;;=**&%$##++.", +".++##%*=>;;;=*&$@++..$&>>>-****=;;>>>>-%.@$*==;;=-=>>>>&%#++...+#$*->>>*%#+++....#*=;;;==&%**;;;=*$@.@#%**>-;;;==;;;>-&$.$&>>;;;;==*%#@+.....&->;;;;;;;;;;;;>>&$.#%*==;;==;;>--**%%$.$--=====>>;>*&$@@+..$&*>;;;;;;;;;;;**$#.....++#%*;;;=*$@+...$%&&**==;;;==**&&%#.==;;==;;=***-->;;*&.@#%&*=*---;;=*%$@+...@#$=-;>=*>>**&$@++", +"..+@#%*=>;;;==*%#@+..$&>>>-***==;;>>>>-$.@#**=;;-=->>>-&$@++..++#$*->>-&#@+......$&=;;;-=&%&*;;;=*$@.+@$&*->;;;==;;;>-&#.$&>>;;;;==*$#@++++..%->;;>;;;;>>;;;>-&$.#$*==;;--;;--=*%$#@.$--**=*=>>>>*%#@+...#&*>;;;;;;;;;;;=&$@......@#&*;;;=*$@+...###$%**=>;;=*&%$##@.=-;;==;;=*&*->>;;*&.+@#$%**->-;;*&$@++..+@$%=-;;=*>;==*&$@+", +"..+@$&*=;;;;;;**&##+.$&>>--==--->>=**&%#.@#&==;;-=->>>>&$@+...+@#&*>;==%#++......$&*;;;-=*&*=;;;=*$@.+@$&*;;>>>=-;;;=*%#.$*;;;;;;=*&%$#@@@++.%==->==;;;==;;;-=%#.@$==-;;==;;-==%$#@+.@$$%&*==;;==%#@+....@%*>>;--==>-;;;*%$+.....+@$**;;;*&#@+...+@@#$%*=;;;*&%##@++.--;>>>;>*&**>>>;;*%.++@#$&=;;;-=*$#@+...@#%*>;--*=--;;;*&#@", +".+@#$*==;;;;;;==*%$@.$&->>-=*-->>>**%$#@.+#&*=;;=-=>>>-&$@+..++#$&*;;=*#@++......$&*;;;-=***=;;;=*$#.@$%*=;;>>>--;;;=*%@.%*>;;;;;==**%%%$##@.$*==-==;;;==;;;==$#.@$==-;;==;;--=%#@+..@@#$%&==;;=*$#++....@$&>>>--==>-;;;*&#+....++#$**;;;*&#@.....++@#%*=>;;**##+++..=-;;>>>>****>>>;;*%..+@#$*=;;;==%#@+....#$&*>;--===-;;;=*%#", +".@#$&*==;;;;;;===*%$.#%->--==->->-*%##++.+#&==;;=-=>>>-&$@+..@@$&*=;;*&#@+.......$&*;;;--====;;;=*$@.#%&*=;;>>>-=;;;=*$@.$&>;;;;;===****&%$#.#&*==*=;;;==;;>=*$@.#%=--;;==;;===$#+...+@##%*==;;=&$@+.....@#%->>-===>-;;;*$#+....+@$&*=;;;*%#++....++#$&*=;;;*%#+.+...=-;;>>;>=**=>>>;>&$.+@@$%*=;;;=*$#++....$&*=;;--==--;;;=*%#", +".#$&*;;;>>==;;;;;-=$.#$*=;;;;;;;==%#@++..+#&*=;;>>>;>>-&$@+..@$%-->>>&$@++.......$&=;;;;;;>>>;;;=*$@.$&>>>>>---;;;;>*%#+.$&==;;;;;;;;;>>--=$.@#$$%*=;;;==**&%$@+.$&;;;--==>;-=*$@++..++@$&*>>-=&$#++.....+@$%&*==>>;;>>>&$#+..++@$%*>>;;;*%#++...+++$%*->;;;*%#@+....&*;;;;====>>;;;=*%#.@#$&*;;>>>*%#@+.....*=>>;;;;;>;;;;;;>*%", +".$%*=;;;->**;;;;;>-%.@$&*;;;>;;;=*$#+++..+#**=;;>>>;>>-%$++..#%&->>>>$#++........#&=;;;;>;;>;;;;=*#@.&*>>>>>=--;;;>>&$@+.$&==;;;;;;;;;>>>>-%.+@@#$&=;;;=*&%$#@++.%*;;;-=**>;-=*$@+...+@#%&*>>=*%#+++.....+@@#$&==>>;;>>-%$@+..+@#%**>>;;>&$@+.....+@$&*>>;;;*%#+.....%*;;;;-===>>;;;*&$@.@$&*=;;>>-&##+......==>>;;;;;;;;;;;;;*$", +".&=;;===**&**=---==$.+#$&==>>-==*$#++....+#&*=;;>>>;--=%#@...$==>>>=*$@+.........#%*>;;==**==->-*&#+.>>>>>=****>>==*%#@+.#&>>=====-=>>>>>==$.+.+@@&*;;;*&%#@@++..%>---**&*>>==*#@++..+@$==---*%#@+........++@#$&*>;;;==*%#+..++@$=->;;=**$#++....++@$&=>;>>>*%#++....$%&*====;;>>=**%$#+.$*=;;--**%$#++......*=;;>>>>>>==->>;;*%", +".*=;;===%%$%&*==-=*$.+@#%*=>>===%#@++....+#%*=;;>>>;--=$#++..$*=>>>*&@+..........#%*>;>=*&&&*---*%#+.->>--&&&&*--**%$@+..#%->==*&===>>>>>=*$...++@%*;;;*&#@++.+..&>--=&%$&--=*&#@+...+@$=--==&#@++.........++@#%*>;;;=*&#@+..++#%-->;;*&%#@+.......@$&*>;>>>&$@+.....@#%&*=**;;>-*&%##++.$*=;;--*%$#++.......==;;>>>>>-==---;;*$", +".&*;;=*&##@##%===**#..+@#&*--=**#@++.....+@%*=;;>>>>-=*$@+...#*=>>-*%@+..........@$%>>>*&%$$%===&$@+.->-==%$$$$==&%$@++..#$--**%%**=-->--=*#.....+$*;;;&%#++.....%>===$$#$==*&%@+....+@#=====$@+............++@$%>>;;**%#++...+#%=->;>*%#@++......++$%*>>>>-%#++.....+@##&*&*;;-=&%#@++..$==;;==%##++........**;;>>>--=*&==-;;&$", +".$%%&%$#@@++@##$$$#@..++@#%%%%$##++......++#$&--=***&%$#++...#$%%&%$#+...........+@$%&%%##@##$%$#@++.$&%%%##@@##$##@+++..@#$$%####$%%&&&%$#@.....+#%=*=%#@++.....#%%%##@@#$$$#@++....++##$%$##+..............++#$&&**&$#@+...++#$===*&%#@++.......++@#$%*&&%$@+.......++@##$%&*&%$#+++...$*=**&%#@++.........$&&***&&&%%%%&&&%$#", +".@#$##@@++.+++@@#@++....++####@@++........+@#%==&%&&$#@++....+@#$##@@............+@@####@+++@@#@@++..##$##@+++@@@@@++....+@##@@+@@@#$$$$##@@.....+##&&*##++......@#$#@@++@@#@@++......++####@+................++#$$$$#@++.....+@#*==%$#@++..........+@#$$$$#@+++......++++@##$$$#@+++....#**&%$#@++..........##$%$$$$$##@##$$##@", +".++@@@+++....+++++++....+++++++++.........++@##$$$#@@++++....+++@@@++.............++@@@++++++++++++..@+@++++.++++++......++++++++++@+@@@@+++.....++@###@++.......+@@++++.+++++.+......++++++++.................++@@#@@++......++##$##@@++...........+++@@@@@++............++@@#@+++......@####@+++...........+@@#@@#@@++++@@@@@+"}; diff --git a/hacks/images/matrix2b.xbm b/hacks/images/matrix2b.xbm new file mode 100644 index 00000000..9b897461 --- /dev/null +++ b/hacks/images/matrix2b.xbm @@ -0,0 +1,307 @@ +#define matrix2b_width 160 +#define matrix2b_height 182 +static unsigned char matrix2b_bits[] = { + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f, 0xff, 0xfe, + 0xc3, 0x8f, 0xbf, 0xff, 0xff, 0xf7, 0x0f, 0x1f, 0xff, 0xfd, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xcf, 0xff, 0x1f, 0xbe, 0xf2, 0xa9, 0x43, 0x1f, 0xff, + 0xfd, 0xeb, 0xd7, 0x2f, 0x7f, 0xfc, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc7, + 0xff, 0x5f, 0x7c, 0xe8, 0xa1, 0x07, 0x3e, 0xbe, 0xf8, 0xe3, 0x87, 0x3f, + 0xfe, 0xf0, 0xe3, 0xff, 0xff, 0xff, 0xff, 0xcf, 0xff, 0x1f, 0x1f, 0xf2, + 0x80, 0x91, 0x0f, 0x7d, 0xfa, 0xf1, 0xd7, 0x3f, 0x1d, 0xf0, 0xf5, 0xff, + 0xff, 0xff, 0xff, 0xa7, 0xff, 0x3f, 0x7c, 0xf0, 0x82, 0xa3, 0x3e, 0x7c, + 0xf0, 0xe7, 0xc7, 0x7f, 0x7e, 0xe0, 0xd3, 0xff, 0xff, 0xff, 0xff, 0xe7, + 0xff, 0x1f, 0xbf, 0xfb, 0xa0, 0x03, 0x8f, 0x3a, 0xfd, 0xfd, 0xe7, 0x3f, + 0xbe, 0x74, 0xa0, 0xff, 0x07, 0xfc, 0xff, 0xf1, 0xff, 0x3f, 0xfe, 0xff, + 0xc5, 0x17, 0x1e, 0x7a, 0xe0, 0xff, 0xc7, 0x7f, 0xbc, 0xf0, 0x80, 0xff, + 0x0f, 0xf8, 0xff, 0xe3, 0xff, 0x3f, 0xff, 0x7f, 0x80, 0x23, 0x1e, 0x1c, + 0xf0, 0xff, 0xab, 0x3f, 0x7f, 0xfb, 0xa2, 0xff, 0xaf, 0xfa, 0xff, 0xf8, + 0xff, 0x7f, 0xfe, 0xff, 0xa1, 0x07, 0xbe, 0x38, 0xe1, 0xff, 0xc7, 0x3f, + 0x7c, 0xf7, 0xe7, 0x8f, 0xff, 0xff, 0xf8, 0xf1, 0xff, 0xbf, 0xff, 0x7f, + 0xe4, 0xa1, 0x3e, 0x3a, 0xe8, 0xff, 0x57, 0x5f, 0xff, 0xff, 0xf1, 0xd7, + 0xff, 0x7f, 0x7d, 0xfc, 0xff, 0x3f, 0xfe, 0xff, 0xc1, 0x8f, 0x7f, 0x7a, + 0xe1, 0xff, 0x8f, 0x3f, 0xfe, 0xff, 0xe7, 0x8f, 0xff, 0x7f, 0xf9, 0xf9, + 0xff, 0xff, 0xff, 0xff, 0xf4, 0xc7, 0xff, 0xbf, 0xff, 0xff, 0x5f, 0x8f, + 0xff, 0xff, 0xff, 0xe7, 0xff, 0xff, 0x7f, 0xfe, 0xff, 0xff, 0xff, 0xff, + 0xeb, 0xdf, 0xff, 0xff, 0xff, 0xff, 0xdf, 0xff, 0xff, 0xff, 0xff, 0xaf, + 0xff, 0xff, 0xff, 0xfe, 0xff, 0xff, 0x7f, 0xfb, 0xff, 0xff, 0x5f, 0xff, + 0xf5, 0xf6, 0xff, 0xbf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0x4b, 0x2f, 0xfe, 0xf4, 0xd2, 0x1f, 0x5f, 0xfc, 0xeb, 0xc4, 0x4b, 0x3f, + 0xfd, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf5, 0x87, 0x8e, 0x1f, 0xe8, + 0xc0, 0xa7, 0x07, 0x3a, 0x70, 0xd0, 0x03, 0x4f, 0xfc, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xe2, 0x83, 0x0e, 0xbe, 0xe0, 0x82, 0x0f, 0x1f, 0xfc, + 0x60, 0x81, 0x0b, 0x1e, 0xf8, 0xff, 0xff, 0x5f, 0xbe, 0xaf, 0xfe, 0xc0, + 0x29, 0x3e, 0x3f, 0xe5, 0x94, 0x83, 0x47, 0x3d, 0xfa, 0xc5, 0x21, 0x46, + 0x7c, 0xfd, 0xd3, 0x17, 0x57, 0x1d, 0xfa, 0xc4, 0x53, 0x3e, 0xfd, 0xe2, + 0x87, 0x17, 0x0f, 0x58, 0xf0, 0xcf, 0x4b, 0xce, 0xf8, 0xf4, 0xc7, 0x87, + 0x0e, 0x78, 0xf0, 0xca, 0x11, 0x1e, 0x7f, 0xe9, 0xa1, 0x83, 0x4f, 0x3c, + 0xf4, 0xe3, 0x03, 0x0f, 0x7c, 0xfc, 0xf3, 0x52, 0x17, 0x7c, 0xe5, 0xc5, + 0x73, 0x3e, 0x7e, 0xf1, 0x8b, 0x13, 0xde, 0x58, 0xe0, 0xc7, 0x27, 0x5e, + 0xf0, 0xfd, 0xef, 0xc1, 0x4f, 0x78, 0xe1, 0xd3, 0x21, 0x3e, 0x7f, 0xfc, + 0xc6, 0x02, 0x6f, 0x3c, 0xf1, 0xf1, 0x12, 0x0e, 0xfc, 0xff, 0xff, 0x49, + 0x07, 0xf9, 0xe8, 0xf1, 0x43, 0x3e, 0x7a, 0xf0, 0x8c, 0x03, 0xce, 0x58, + 0xe2, 0xe3, 0x43, 0xbe, 0xf8, 0xfa, 0xeb, 0x8b, 0x1e, 0x58, 0xf4, 0xe3, + 0x0b, 0x07, 0x1c, 0x6a, 0xc0, 0x0b, 0x15, 0x3c, 0xf0, 0xf3, 0x09, 0x0e, + 0x7e, 0xfc, 0xe3, 0x2f, 0xf7, 0x1f, 0xfd, 0xfb, 0x97, 0x2e, 0x38, 0xe8, + 0xa2, 0x2f, 0x96, 0xfc, 0xe2, 0xe6, 0x97, 0xbf, 0xfc, 0xf8, 0xc7, 0xbf, + 0xbe, 0xfd, 0xfe, 0xf3, 0xaf, 0xaf, 0x5e, 0xf1, 0xd5, 0x4f, 0x5f, 0x7f, + 0xfc, 0xfb, 0xa7, 0x0f, 0xff, 0xfe, 0xf1, 0xff, 0xff, 0xbf, 0xff, 0xfb, + 0xff, 0xff, 0xfd, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfd, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xf7, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f, 0xff, + 0xff, 0xff, 0xbf, 0xff, 0xff, 0xff, 0xbf, 0xff, 0xff, 0xfd, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xd7, 0xaf, 0xff, 0xfa, 0xab, 0xd5, 0x6f, 0x7d, + 0xf5, 0xd5, 0xb5, 0x5e, 0xbd, 0xeb, 0xd6, 0xd5, 0xdf, 0x7b, 0xeb, 0xf5, + 0xa7, 0x0f, 0x0f, 0x74, 0xa1, 0x41, 0x07, 0x0c, 0xe0, 0xa2, 0x51, 0x26, + 0x7c, 0x70, 0xc8, 0xa1, 0xa3, 0x18, 0xf5, 0xd2, 0x07, 0x1f, 0x3c, 0x60, + 0x85, 0x02, 0x0e, 0xbc, 0x60, 0x81, 0x03, 0x0e, 0xf8, 0xe0, 0x80, 0xc3, + 0x47, 0x31, 0x61, 0xc1, 0x91, 0x0e, 0x1e, 0x71, 0xa8, 0x11, 0x47, 0x18, + 0x62, 0xa4, 0x11, 0x5e, 0x7d, 0xb1, 0xc4, 0xe5, 0x87, 0x18, 0x60, 0x84, + 0x83, 0x3e, 0x3c, 0xa2, 0x94, 0x32, 0x8e, 0x3a, 0xe5, 0x8c, 0x53, 0x3e, + 0xfe, 0xe3, 0xc4, 0xc7, 0x0f, 0x18, 0x65, 0x9c, 0x03, 0x8f, 0x5a, 0x70, + 0xfe, 0x29, 0x16, 0x5e, 0x38, 0xaa, 0x01, 0x1e, 0x7f, 0x79, 0xf0, 0xf3, + 0x87, 0x18, 0x70, 0xc6, 0x03, 0x1e, 0x5a, 0x60, 0xfa, 0x71, 0x16, 0x3a, + 0x70, 0x8c, 0x03, 0x3e, 0xee, 0xf1, 0xc0, 0xa7, 0x0f, 0x98, 0x60, 0x9c, + 0x09, 0x0b, 0x3c, 0x25, 0xae, 0x29, 0x4e, 0x1c, 0x7d, 0xc2, 0x29, 0x3e, + 0x1f, 0x69, 0xe0, 0x63, 0x0b, 0x19, 0x32, 0x86, 0x23, 0xa6, 0x28, 0x62, + 0x98, 0x69, 0x8a, 0x38, 0x79, 0x8c, 0x53, 0x3e, 0x1c, 0xf1, 0x0a, 0x07, + 0xae, 0x98, 0x60, 0x9c, 0x83, 0x07, 0x18, 0x68, 0xc4, 0x00, 0x07, 0x1a, + 0x7e, 0x80, 0x01, 0x0e, 0x9d, 0x7c, 0xc0, 0x11, 0x43, 0x19, 0x71, 0xc0, + 0x0f, 0x97, 0x58, 0xe1, 0x81, 0x13, 0x57, 0x38, 0xf8, 0xab, 0x53, 0x2c, + 0x38, 0xf0, 0x9a, 0x23, 0x8f, 0x30, 0xe3, 0xc9, 0xeb, 0xef, 0xbb, 0xfe, + 0xff, 0xed, 0xaf, 0xdd, 0xfe, 0xf5, 0xba, 0xdf, 0xff, 0x7f, 0x6d, 0xab, + 0xf7, 0x5f, 0xff, 0xf7, 0xbf, 0xbf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0x7e, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xfd, 0xef, 0xff, 0xff, 0xff, 0xef, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xdf, 0xfe, 0xfe, 0xff, 0x57, 0xbf, 0xbe, 0xfa, + 0xd7, 0xad, 0xae, 0x7a, 0x6b, 0xdd, 0xab, 0xae, 0x7a, 0xf5, 0xe2, 0xe9, + 0xbf, 0xfe, 0xfa, 0xff, 0x41, 0x17, 0x0d, 0x78, 0xc1, 0x03, 0x43, 0x0c, + 0x65, 0x84, 0x10, 0x46, 0x98, 0xe0, 0xf9, 0xf5, 0x1f, 0xff, 0xfc, 0xff, + 0x02, 0x16, 0x3c, 0xe0, 0x80, 0x03, 0x8e, 0x18, 0xc2, 0x94, 0x23, 0x8c, + 0x38, 0xe0, 0xe1, 0xd3, 0x3f, 0xfc, 0xf0, 0xff, 0x25, 0x46, 0x98, 0x32, + 0xc9, 0x48, 0xa2, 0x98, 0x72, 0x80, 0x21, 0x47, 0x38, 0xe5, 0xf9, 0xe5, + 0x5f, 0x3e, 0xf8, 0xff, 0x53, 0xc6, 0x39, 0x62, 0x88, 0x03, 0x46, 0x39, + 0xc2, 0x92, 0x07, 0x8e, 0x7a, 0xe0, 0xe1, 0x87, 0x7f, 0x7c, 0xea, 0xff, + 0x21, 0xa6, 0x18, 0xf0, 0xe0, 0x4b, 0xe7, 0x9c, 0x72, 0x80, 0x43, 0x1f, + 0x5c, 0xf9, 0xfa, 0xe7, 0x3f, 0x7f, 0xf9, 0xff, 0x07, 0xa6, 0xb9, 0xe0, + 0x85, 0x4f, 0x87, 0x38, 0xe2, 0x80, 0x0f, 0x3f, 0xfd, 0xf0, 0xf1, 0x0f, + 0x7f, 0xfc, 0xf7, 0xff, 0x21, 0x4b, 0x18, 0xba, 0xc0, 0x8b, 0x67, 0x7c, + 0xb8, 0x84, 0x43, 0x1f, 0x3f, 0xf4, 0xfa, 0xcf, 0x3f, 0x7e, 0xff, 0xff, + 0xa3, 0x07, 0x38, 0x60, 0x8a, 0x4f, 0x87, 0x78, 0xf1, 0x08, 0x0b, 0x3c, + 0xbc, 0xe0, 0xe1, 0x1f, 0x7e, 0xfc, 0x7f, 0xd2, 0xc1, 0x0f, 0x0d, 0x61, + 0xc0, 0x83, 0x4f, 0x7c, 0x78, 0xc0, 0x21, 0x2e, 0x3e, 0xe4, 0xf8, 0x5f, + 0x1f, 0xff, 0xbf, 0x88, 0x8b, 0x1f, 0x38, 0xc6, 0x82, 0x0f, 0x1f, 0xf8, + 0xf0, 0x8d, 0x21, 0x1e, 0x7a, 0xe0, 0xe1, 0x3f, 0x3e, 0xfc, 0x7f, 0x80, + 0xf5, 0x17, 0xbc, 0x7f, 0xfd, 0xf7, 0xef, 0xff, 0xff, 0xfe, 0xef, 0xff, + 0xde, 0xed, 0xd1, 0x3f, 0x2f, 0xff, 0x7f, 0xa9, 0xff, 0xff, 0xfd, 0xfd, + 0xff, 0xbf, 0xff, 0xff, 0xff, 0xfd, 0xdf, 0xfe, 0xff, 0xff, 0xff, 0x7f, + 0xff, 0xfe, 0xff, 0xf7, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xdf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xdf, 0xff, 0x5f, 0xff, 0xff, 0x5f, 0xff, 0x7f, 0xe9, 0xff, 0xf5, 0xbf, + 0xfe, 0xf9, 0xfa, 0xd7, 0xff, 0xff, 0xff, 0xff, 0xc7, 0xff, 0x1f, 0xff, + 0xff, 0x2f, 0xff, 0xff, 0xe0, 0xff, 0xf0, 0x1f, 0x7f, 0x39, 0xfc, 0xc3, + 0xff, 0xff, 0xff, 0xff, 0x0f, 0x7f, 0x3f, 0xfc, 0xeb, 0x1f, 0xbe, 0xfe, + 0xe8, 0xd7, 0xd3, 0x3f, 0xfe, 0xf1, 0xe8, 0x4f, 0xdf, 0xbe, 0xfd, 0xfb, + 0xcf, 0x97, 0x1e, 0x75, 0xd5, 0x23, 0x57, 0x1d, 0xf0, 0xa8, 0x41, 0x1f, + 0x3f, 0x78, 0xd5, 0xc7, 0x23, 0x5d, 0x79, 0xe5, 0x1f, 0x0f, 0x3c, 0xe0, + 0x80, 0x05, 0x0e, 0x78, 0x61, 0x81, 0x03, 0x3e, 0xfe, 0xe0, 0xc0, 0x8f, + 0x07, 0x18, 0xe0, 0xc0, 0xff, 0x0f, 0x1a, 0x60, 0xc0, 0x01, 0x07, 0x38, + 0x68, 0xc0, 0x21, 0x17, 0x3f, 0x78, 0xc4, 0xcf, 0x07, 0x2c, 0x32, 0xc4, + 0xff, 0x2f, 0x3a, 0x66, 0x8c, 0x11, 0x4e, 0x79, 0x79, 0x86, 0x23, 0x3e, + 0xfd, 0xe3, 0xd0, 0x8f, 0x4f, 0x38, 0xe2, 0x88, 0xff, 0x07, 0x3c, 0xa1, + 0xd6, 0x19, 0x07, 0x78, 0x7c, 0xc4, 0x13, 0x1e, 0xff, 0x79, 0xf1, 0x57, + 0x03, 0x19, 0x61, 0xc6, 0xff, 0x4f, 0x34, 0x65, 0x98, 0x21, 0x8e, 0xf0, + 0xf4, 0x40, 0x73, 0x3e, 0xfc, 0xe3, 0xa0, 0x8f, 0x2f, 0x38, 0x66, 0x8c, + 0xff, 0x87, 0x18, 0x60, 0xc4, 0x11, 0x07, 0x1a, 0x68, 0xc5, 0x01, 0x0e, + 0x7d, 0x79, 0xc4, 0x43, 0x83, 0x94, 0x20, 0xc0, 0xff, 0x1f, 0x39, 0xe9, + 0x80, 0x07, 0x5e, 0x78, 0xe1, 0x89, 0x53, 0x2c, 0x78, 0xe1, 0x88, 0x07, + 0x8a, 0x98, 0xe2, 0xd2, 0xff, 0xaf, 0xae, 0xfa, 0xef, 0xb5, 0x5f, 0xbf, + 0x7c, 0xe0, 0xb5, 0xdf, 0x3f, 0x78, 0xd7, 0xdd, 0xb7, 0xbe, 0xee, 0xf5, + 0xff, 0xff, 0xfe, 0xff, 0xfd, 0x7f, 0xff, 0xff, 0xff, 0xeb, 0xff, 0xff, + 0xfe, 0xfa, 0xff, 0xfb, 0xff, 0xfd, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xef, 0xdf, 0xdf, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xf3, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xf5, 0xcf, 0x5f, 0xff, 0xff, 0xff, 0xb7, 0xbf, 0xff, 0xf6, + 0xf7, 0xa7, 0xef, 0x7e, 0xf7, 0xff, 0x6f, 0xdf, 0xfb, 0xfd, 0xe3, 0x8f, + 0x3f, 0xfe, 0xff, 0xff, 0x55, 0x57, 0x5c, 0xf5, 0xca, 0xc1, 0xd6, 0x5a, + 0xb5, 0x84, 0xa9, 0x56, 0x1d, 0xf5, 0xf1, 0xcf, 0x1f, 0xff, 0xff, 0xff, + 0x01, 0x16, 0x38, 0xe0, 0x81, 0x03, 0x87, 0x18, 0x60, 0x98, 0x03, 0x86, + 0x30, 0xe0, 0xe3, 0x4f, 0x3f, 0xbd, 0xea, 0xff, 0x01, 0x87, 0xb8, 0xd0, + 0x88, 0xc5, 0xa7, 0x18, 0xa1, 0x80, 0x25, 0x86, 0x18, 0xf8, 0xf8, 0x97, + 0x3f, 0x5e, 0xe4, 0xff, 0x23, 0x26, 0x38, 0xf5, 0xa1, 0x4b, 0x4f, 0x39, + 0xa2, 0x82, 0x47, 0x9f, 0xb8, 0xf0, 0xe1, 0x97, 0x7f, 0x3c, 0xe0, 0xff, + 0x51, 0x42, 0x7c, 0x7c, 0xc0, 0xe5, 0x47, 0xb9, 0xf8, 0x90, 0x8b, 0x07, + 0x5e, 0xfc, 0xf1, 0xcf, 0x1f, 0x9f, 0xf4, 0xff, 0x03, 0x4e, 0xb8, 0xf4, + 0x84, 0x85, 0x0e, 0x78, 0xf1, 0x80, 0x07, 0x3e, 0x3c, 0xe0, 0xe3, 0x8f, + 0x3f, 0xbe, 0xeb, 0xff, 0xc3, 0x0f, 0x3c, 0xf8, 0x80, 0x07, 0x4f, 0x78, + 0x78, 0xc9, 0x22, 0x1f, 0x1f, 0xf1, 0xf9, 0xcf, 0x3f, 0xff, 0xff, 0xff, + 0x49, 0xff, 0x38, 0xe8, 0xa4, 0x17, 0x1e, 0xf1, 0xf4, 0xc9, 0x03, 0x0e, + 0x3d, 0xf0, 0xe3, 0x9f, 0x3f, 0xfe, 0xff, 0xff, 0xe1, 0x1f, 0xf8, 0xfb, + 0xdb, 0xdf, 0x7f, 0xfd, 0xff, 0xff, 0x7f, 0x27, 0xbf, 0xf7, 0xeb, 0xef, + 0x4f, 0xff, 0xff, 0xff, 0xcb, 0xff, 0x7a, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xfe, 0xfb, 0xfb, 0x6f, 0xff, 0xfe, 0xef, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xef, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfa, + 0xeb, 0xff, 0x57, 0xfd, 0xff, 0xab, 0xff, 0x7f, 0xff, 0xfd, 0xff, 0xff, + 0xff, 0xbf, 0xfd, 0xff, 0x0b, 0xfe, 0xff, 0xe9, 0xaa, 0xff, 0x4f, 0xf5, + 0xf4, 0xc0, 0x57, 0xaf, 0x7e, 0xf5, 0xff, 0xff, 0xff, 0x7f, 0xf4, 0xe9, + 0x01, 0xfc, 0x7f, 0xf1, 0xc1, 0x53, 0x0e, 0xf8, 0xfc, 0x83, 0x6f, 0x0f, + 0xf8, 0xf0, 0xff, 0xef, 0xff, 0xbf, 0xe0, 0xc1, 0x03, 0x7e, 0xbf, 0xe8, + 0xe8, 0x01, 0x47, 0x7c, 0x79, 0xc8, 0x57, 0x07, 0x3c, 0xfa, 0xd5, 0x5d, + 0xff, 0x1f, 0xf8, 0xf5, 0x01, 0x7c, 0x3e, 0xe0, 0xd1, 0x07, 0x9e, 0xf8, + 0xf8, 0x80, 0xff, 0x0f, 0x78, 0xe8, 0x93, 0x03, 0x6e, 0x3d, 0xc0, 0xeb, + 0x01, 0x5c, 0x3f, 0x75, 0xf4, 0x11, 0x0e, 0xfe, 0x7e, 0xa0, 0xff, 0x43, + 0x38, 0x70, 0xc0, 0x01, 0x9e, 0x0a, 0xe0, 0xff, 0x03, 0x7e, 0x3e, 0xea, + 0xe0, 0x53, 0x3e, 0xfa, 0xf8, 0x81, 0xff, 0x0f, 0x79, 0xe1, 0x84, 0x5f, + 0x16, 0x58, 0xe4, 0xff, 0x03, 0x1c, 0x3f, 0xf0, 0xd0, 0x01, 0x0f, 0x7e, + 0x7c, 0x82, 0xff, 0x07, 0x38, 0x78, 0xe0, 0x37, 0xae, 0x1e, 0xf0, 0xff, + 0x01, 0x3e, 0xfc, 0xe0, 0xa9, 0x03, 0x3e, 0xf8, 0xf8, 0x8a, 0xff, 0x17, + 0xfa, 0x72, 0x85, 0xff, 0xfe, 0x7d, 0xe0, 0xff, 0x03, 0x1c, 0x7f, 0x7d, + 0x80, 0xb7, 0x0e, 0xfe, 0xfc, 0xa0, 0xff, 0x2f, 0x7e, 0xff, 0xc0, 0x7f, + 0xbf, 0x9f, 0xf8, 0xff, 0x01, 0x3e, 0xfc, 0xf1, 0x80, 0xef, 0x5f, 0xfc, + 0xf9, 0xe2, 0xff, 0xaf, 0xfc, 0xff, 0x8d, 0xff, 0xff, 0x7f, 0xf5, 0xff, + 0x01, 0x3c, 0xff, 0xff, 0xff, 0xff, 0xbf, 0xff, 0xfe, 0xf4, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x13, 0x7e, 0xff, 0x7f, + 0xeb, 0xff, 0xbf, 0xfd, 0xff, 0xef, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xff, 0xff, 0xff, 0xff, + 0xfa, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xbf, 0xff, 0xff, + 0x8b, 0xff, 0xff, 0xf9, 0xd5, 0xdf, 0xff, 0xdf, 0xe2, 0xff, 0xff, 0xbf, + 0xbe, 0xfd, 0xff, 0xf1, 0xd3, 0x2f, 0xfe, 0xff, 0xa7, 0xbf, 0x3e, 0xf4, + 0xe1, 0xaf, 0xff, 0x3f, 0xe8, 0xff, 0xff, 0x2f, 0x7f, 0xfa, 0xff, 0xf4, + 0xe3, 0x8e, 0xf6, 0xf3, 0x05, 0xbf, 0xfe, 0xf8, 0xc5, 0x9f, 0xff, 0xbf, + 0xe0, 0xff, 0xff, 0x3f, 0x7e, 0xf0, 0xff, 0x61, 0xc7, 0x29, 0xc4, 0xe7, + 0x53, 0x2f, 0x3d, 0xf9, 0xe1, 0xcb, 0xa7, 0x1a, 0xe8, 0xff, 0xff, 0x1f, + 0x1f, 0x79, 0xf5, 0x39, 0x22, 0x9c, 0xf2, 0xf5, 0x07, 0x0f, 0x78, 0xf0, + 0x89, 0xff, 0x8f, 0xb8, 0xe8, 0xe5, 0xff, 0x3f, 0x3c, 0x71, 0xc5, 0x51, + 0xc6, 0x1a, 0xe4, 0xe3, 0xef, 0x07, 0x78, 0xfa, 0xe4, 0xef, 0xa3, 0x18, + 0xf0, 0xf3, 0xff, 0x5f, 0x3f, 0x74, 0xd0, 0x00, 0x03, 0x8c, 0xf0, 0xf0, + 0xff, 0x3f, 0xfd, 0xf4, 0xe5, 0xff, 0x4f, 0xb9, 0xe0, 0xe3, 0xff, 0x3f, + 0xfc, 0x78, 0x81, 0x13, 0x0a, 0x18, 0xe8, 0xe5, 0xff, 0x2f, 0x7d, 0xff, + 0xff, 0xff, 0x87, 0xf8, 0xf8, 0xfd, 0xef, 0xdf, 0x1f, 0xe8, 0xc8, 0x0a, + 0x27, 0xb9, 0x70, 0xd8, 0xff, 0x3f, 0xfd, 0xff, 0xfd, 0xff, 0x0f, 0xf8, + 0xe0, 0xfb, 0x8f, 0xff, 0x7f, 0xf9, 0x81, 0x23, 0x46, 0x38, 0xe2, 0xc8, + 0xff, 0x87, 0xfc, 0xff, 0xff, 0xff, 0x07, 0xb8, 0xe0, 0xff, 0x47, 0xff, + 0xff, 0x3e, 0xe4, 0x01, 0x53, 0x8d, 0x70, 0xa0, 0xff, 0x0f, 0xf8, 0xff, + 0xff, 0xff, 0xaf, 0x7b, 0xe0, 0xff, 0x8f, 0xff, 0xff, 0xff, 0xca, 0x2b, + 0x66, 0x98, 0xe2, 0xe3, 0xff, 0xbf, 0xfd, 0xff, 0xff, 0xff, 0xcf, 0xbf, + 0xea, 0xff, 0xa7, 0xff, 0xff, 0xff, 0xff, 0x5f, 0xbf, 0x7e, 0xf5, 0xed, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xdf, 0xff, 0xfb, 0xff, 0xdf, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xfe, 0xfd, 0xff, 0xff, 0xf7, 0x7f, 0xff, 0xfe, + 0xff, 0xff, 0x7f, 0xff, 0xff, 0xf7, 0xef, 0xff, 0xfe, 0xfe, 0xf6, 0xfb, + 0xff, 0xff, 0xfd, 0xff, 0xd7, 0xff, 0xfc, 0xf8, 0xe2, 0xff, 0x3f, 0xbe, + 0xea, 0x8a, 0xd7, 0xdf, 0xfc, 0xf8, 0xd5, 0xc7, 0xbf, 0xfc, 0x74, 0xc9, + 0xe3, 0x2f, 0x3e, 0xfa, 0xa9, 0x93, 0x4f, 0x7f, 0x68, 0xa1, 0x4b, 0x3f, + 0x5f, 0x74, 0xa9, 0xd7, 0xbf, 0x3e, 0xf8, 0xd2, 0x87, 0xaf, 0x7e, 0x78, + 0xe1, 0x27, 0x1f, 0x7d, 0x60, 0x04, 0x03, 0x07, 0xb8, 0xe0, 0xc0, 0x8b, + 0x2e, 0xf8, 0xe2, 0x80, 0xcb, 0x0f, 0x3f, 0xf9, 0xd0, 0xc3, 0x2f, 0xbf, + 0x68, 0xda, 0x21, 0x06, 0x1c, 0x30, 0x80, 0x03, 0x0f, 0x1d, 0xe8, 0xd2, + 0x03, 0x1f, 0x3c, 0xf0, 0xe2, 0x07, 0x0f, 0x7c, 0x60, 0xac, 0x25, 0x9e, + 0x38, 0x72, 0x95, 0x8f, 0x3e, 0xba, 0xf0, 0xe3, 0x87, 0x2f, 0x7e, 0xf9, + 0xa1, 0x8b, 0x1f, 0x5e, 0x30, 0xfe, 0x83, 0x47, 0x5c, 0xf1, 0xc0, 0xcb, + 0x2f, 0xfd, 0xfc, 0xf1, 0x97, 0x1e, 0x78, 0xe8, 0xc5, 0x27, 0x5e, 0x3a, + 0x60, 0xd8, 0x13, 0x0f, 0x3a, 0x70, 0xd1, 0x8f, 0x3f, 0xff, 0xf4, 0xe3, + 0x01, 0x47, 0x1a, 0x71, 0xa0, 0x81, 0x06, 0x1c, 0x74, 0x56, 0x85, 0x16, + 0x1d, 0x75, 0xa4, 0x4f, 0x1f, 0x7d, 0xf9, 0xf3, 0x03, 0x0e, 0x38, 0xe0, + 0x80, 0x03, 0x0e, 0x98, 0x60, 0x80, 0x11, 0x4e, 0x38, 0xe0, 0x84, 0x8b, + 0x3f, 0xfe, 0xe8, 0xc3, 0x11, 0x86, 0x18, 0xa2, 0x84, 0x11, 0x46, 0x08, + 0xe0, 0xc0, 0x01, 0x02, 0x18, 0x60, 0x80, 0x03, 0x0e, 0x38, 0x70, 0xa0, + 0x23, 0x8c, 0x30, 0x60, 0x08, 0x23, 0x8c, 0x58, 0xe5, 0xe3, 0x43, 0x0e, + 0x39, 0xe5, 0x90, 0x97, 0x5e, 0xba, 0xe4, 0xc5, 0xa9, 0x26, 0x9d, 0x66, + 0xa9, 0xa9, 0xa6, 0x5a, 0xf1, 0xf9, 0xad, 0xb7, 0x5a, 0xba, 0xea, 0xab, + 0x57, 0x7d, 0xf5, 0xb2, 0xbb, 0xff, 0xfd, 0xfd, 0xff, 0xef, 0xef, 0xfe, + 0xff, 0xeb, 0xff, 0xff, 0xff, 0xf7, 0xdf, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xdf, 0x7f, 0xff, 0xeb, 0xbf, 0xbf, 0xff, 0xff, 0xff, 0xbf, 0xdf, + 0xff, 0xfd, 0xfb, 0xff, 0xff, 0xfe, 0xff, 0xff, 0xdb, 0x1f, 0xfc, 0xfc, + 0xef, 0xa7, 0x3f, 0xf8, 0xfb, 0xff, 0x6f, 0x1f, 0xff, 0xfb, 0xe3, 0xb7, + 0xff, 0xbc, 0xfe, 0xe5, 0x41, 0x2f, 0x3d, 0xf6, 0xe1, 0x47, 0x8f, 0xbe, + 0xf6, 0xff, 0x05, 0x9f, 0x7f, 0xf8, 0xf2, 0xd7, 0x5f, 0x2e, 0xfd, 0xf1, + 0x09, 0x0e, 0xf8, 0xfc, 0xd3, 0x47, 0x1f, 0x7c, 0xf0, 0xad, 0x0b, 0x36, + 0xfa, 0xf0, 0x81, 0x16, 0x5e, 0x38, 0xf9, 0xc2, 0x21, 0x53, 0x1a, 0x70, + 0xc0, 0x12, 0x87, 0x1c, 0x55, 0xca, 0x20, 0x06, 0x1c, 0x65, 0xa4, 0x41, + 0x03, 0x0d, 0xf4, 0xc8, 0x01, 0x46, 0x38, 0x61, 0x89, 0x01, 0x0e, 0x38, + 0xe0, 0x88, 0x03, 0xce, 0x18, 0x61, 0x88, 0x11, 0x4e, 0x78, 0xe0, 0xc1, + 0x32, 0x06, 0x19, 0x63, 0x86, 0x39, 0xe2, 0x88, 0xe3, 0xe0, 0x48, 0xa2, + 0x2c, 0x73, 0xd6, 0x29, 0x8f, 0x1c, 0x65, 0xc0, 0x41, 0x0e, 0x98, 0x66, + 0x9c, 0x71, 0xc6, 0x19, 0xe7, 0xc3, 0x49, 0xc6, 0x18, 0x63, 0x8a, 0x31, + 0x1e, 0x38, 0xe1, 0x8a, 0x39, 0x22, 0x8c, 0x23, 0x96, 0x28, 0xa6, 0x98, + 0xe2, 0xa0, 0x01, 0xa6, 0x2c, 0x65, 0xcc, 0x29, 0x5f, 0x1f, 0xe4, 0x90, + 0x51, 0xa6, 0x18, 0x64, 0x88, 0x51, 0x86, 0x18, 0xe2, 0x84, 0x51, 0x86, + 0x2c, 0xe2, 0x88, 0x29, 0x3e, 0x7c, 0xe0, 0x92, 0x01, 0x07, 0x1c, 0xf1, + 0xa4, 0x03, 0x17, 0x5d, 0xb4, 0xac, 0x01, 0x4f, 0x5c, 0x78, 0xc0, 0x03, + 0x0f, 0x1e, 0x7a, 0x80, 0x81, 0xce, 0x78, 0xe8, 0xc1, 0x0b, 0x2e, 0x78, + 0xf0, 0xdd, 0x03, 0x1e, 0x78, 0xe0, 0x83, 0x07, 0x2e, 0x18, 0xfc, 0x88, + 0x7f, 0xb7, 0x7f, 0xf7, 0xf6, 0xef, 0xdf, 0xbf, 0xfd, 0xff, 0xfd, 0xef, + 0xbf, 0xfb, 0xfa, 0xfb, 0xbf, 0xff, 0xff, 0xf7, 0xed, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xbf, 0xff, 0xff, 0xff, 0xeb, 0x7f, 0xff, 0xff, 0xff, 0xff, + 0xff, 0x7f, 0xff, 0xfe, 0xff, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xef, 0xff, 0xfe, 0xff, 0xff, + 0xef, 0xff, 0x7e, 0xfd, 0xeb, 0xff, 0x5f, 0xfe, 0xff, 0xff, 0xef, 0x7f, + 0x7d, 0xfd, 0xff, 0xef, 0xff, 0xfd, 0xfd, 0xff, 0xd3, 0xbf, 0xfe, 0xf4, + 0xea, 0xb7, 0x3f, 0xff, 0xff, 0xff, 0xd3, 0x7f, 0xfe, 0xf4, 0xed, 0xd3, + 0xbf, 0x7e, 0xfc, 0xf5, 0x8f, 0x3f, 0xbd, 0xf8, 0xa1, 0xa7, 0x5f, 0xfe, + 0xf6, 0xf7, 0x8f, 0xff, 0xfc, 0xf8, 0xa9, 0x8f, 0x7f, 0xfc, 0xf0, 0xe5, + 0xd3, 0x17, 0x3f, 0x7a, 0xe4, 0x8b, 0x2f, 0x9d, 0x75, 0xd5, 0x53, 0x0f, + 0x3e, 0x72, 0xe5, 0xe7, 0x1f, 0x5f, 0xfc, 0xea, 0x07, 0x1f, 0x7c, 0xf0, + 0xc0, 0x0b, 0x0f, 0x1d, 0xe0, 0x80, 0x07, 0x1e, 0x74, 0xe0, 0x80, 0x87, + 0x2f, 0xbe, 0xf4, 0xe1, 0x81, 0x46, 0x1c, 0xf1, 0xa2, 0x21, 0x4f, 0x5c, + 0x22, 0xc2, 0x21, 0x45, 0x18, 0x62, 0x84, 0xcb, 0x1f, 0x7f, 0xfc, 0xf2, + 0x97, 0x0e, 0x38, 0xe1, 0xa4, 0x07, 0x0e, 0x18, 0x64, 0x9c, 0x03, 0x8e, + 0x38, 0xe2, 0x88, 0x4f, 0x3f, 0xfe, 0xf8, 0xe3, 0x01, 0x57, 0x5e, 0xb8, + 0xc0, 0x91, 0x96, 0x2c, 0x60, 0xd2, 0x01, 0x06, 0x18, 0x60, 0x80, 0xc7, + 0x3f, 0x7f, 0xfc, 0xf5, 0x2b, 0x46, 0x18, 0xe1, 0x88, 0x93, 0x8e, 0x8c, + 0xe0, 0x80, 0x43, 0x0e, 0x39, 0xe4, 0x90, 0x0f, 0x2f, 0xfc, 0xf0, 0xc1, + 0x01, 0x0f, 0x38, 0x70, 0x80, 0x01, 0x06, 0x28, 0x60, 0xa1, 0x09, 0x06, + 0x18, 0x60, 0x80, 0x83, 0x0e, 0x3a, 0xe8, 0xd0, 0x03, 0x0c, 0x39, 0xe1, + 0x92, 0x47, 0x1e, 0x19, 0xe5, 0xe3, 0x8b, 0x3e, 0xfa, 0xe8, 0xa3, 0x17, + 0x5e, 0x78, 0xe1, 0xc2, 0xaf, 0xbf, 0xbe, 0xfa, 0xea, 0x55, 0x57, 0xbd, + 0xfa, 0xf1, 0xaf, 0xaf, 0x7e, 0xfd, 0xf5, 0xa5, 0xaf, 0xbe, 0xfa, 0xd5, + 0xff, 0xff, 0xfd, 0xf7, 0xff, 0xff, 0xff, 0xff, 0xfb, 0xf7, 0xff, 0xff, + 0xff, 0xfb, 0xef, 0xff, 0xff, 0xff, 0xff, 0xff, 0xdf, 0xff, 0xff, 0xff, + 0xdf, 0xdf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xbf, 0xff, 0xff, 0xa9, 0xbe, 0xfe, 0xfe, 0xfb, 0xbf, 0x5f, 0xfd, + 0xff, 0xff, 0xff, 0xbf, 0xff, 0xfb, 0xf7, 0xff, 0x7f, 0xbd, 0xfe, 0xff, + 0x01, 0x17, 0x3d, 0xfe, 0xc7, 0x83, 0x3f, 0xfa, 0xff, 0xf7, 0xff, 0x47, + 0xff, 0xf8, 0xd2, 0xb7, 0xbf, 0x0a, 0xff, 0xed, 0x03, 0x2e, 0xfc, 0xf8, + 0xcb, 0x0f, 0x1f, 0x5c, 0xe8, 0xf5, 0x57, 0x1f, 0xbe, 0xf1, 0xd1, 0x27, + 0x37, 0x3c, 0xf4, 0xc9, 0x91, 0x86, 0x3e, 0xf8, 0xe0, 0xa3, 0x2f, 0xba, + 0xf2, 0xe3, 0x8b, 0xa6, 0x2c, 0xb2, 0xc4, 0x28, 0x47, 0x15, 0x68, 0x94, + 0x03, 0x0e, 0xf8, 0xe0, 0x83, 0x07, 0x1d, 0x3c, 0xe4, 0xd2, 0x13, 0xa6, + 0x5c, 0x62, 0x88, 0x23, 0x8e, 0x78, 0xe0, 0x88, 0x01, 0x82, 0x2c, 0xb0, + 0xc0, 0x01, 0x86, 0x18, 0x70, 0xd5, 0x00, 0x43, 0x1c, 0x61, 0xc4, 0x10, + 0x46, 0x1c, 0x65, 0xc8, 0x53, 0x8e, 0x98, 0x62, 0x0a, 0x2b, 0x8e, 0x38, + 0x62, 0x80, 0x09, 0x8e, 0x38, 0xe6, 0x8c, 0x53, 0x9e, 0x38, 0xe2, 0x81, + 0x29, 0x46, 0x38, 0x65, 0x94, 0x51, 0x46, 0x99, 0xe5, 0xd2, 0x21, 0x63, + 0x9c, 0x61, 0x94, 0x31, 0x2e, 0x5e, 0xd0, 0xea, 0x53, 0x8e, 0x31, 0xe2, + 0x88, 0x23, 0x8e, 0x38, 0xe2, 0xe5, 0x03, 0x86, 0x38, 0xe5, 0x88, 0x43, + 0x1e, 0x3e, 0xf0, 0xe1, 0x01, 0x4b, 0x1c, 0x70, 0xc4, 0x82, 0x46, 0x18, + 0xd0, 0xf3, 0x10, 0x4f, 0x1c, 0xe0, 0x80, 0x13, 0x0e, 0x9f, 0xf6, 0xe2, + 0x0b, 0x06, 0xb8, 0xe0, 0x81, 0x0b, 0x1e, 0xba, 0xf0, 0xe7, 0x01, 0x0f, + 0x78, 0xc1, 0x0b, 0x07, 0x1c, 0x1e, 0xfc, 0xe0, 0xf7, 0xef, 0xfd, 0xfe, + 0xfe, 0xb7, 0xef, 0x7e, 0xff, 0xfd, 0xf9, 0xbf, 0xfd, 0xfe, 0xea, 0xdf, + 0x47, 0x5f, 0x7e, 0xf9, 0xdf, 0xdf, 0xff, 0xfb, 0xf7, 0xff, 0xff, 0xff, + 0xf5, 0xff, 0xab, 0xff, 0xff, 0xfb, 0xff, 0x7f, 0x7f, 0xdf, 0xfd, 0xf7, + 0xff, 0xff, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0x7f, 0xf5, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xdf, 0xf2, 0xfb, + 0xff, 0xff, 0xff, 0xbf, 0xff, 0xfb, 0x87, 0xff, 0x1f, 0xf2, 0xff, 0x77, + 0xff, 0xff, 0xeb, 0xff, 0x77, 0xaf, 0x70, 0xf4, 0x97, 0xab, 0xbf, 0x7e, + 0xfd, 0xe2, 0xa7, 0x9e, 0x3f, 0xe0, 0xef, 0x95, 0xfe, 0xff, 0xd6, 0xfb, + 0x33, 0x03, 0x38, 0x72, 0xc0, 0x55, 0x1d, 0x0d, 0x7e, 0xf1, 0x83, 0x8f, + 0x1e, 0xf1, 0xe3, 0x01, 0x2e, 0xda, 0xc3, 0xf9, 0x93, 0x4f, 0x5a, 0x68, + 0x80, 0x03, 0x2e, 0x3a, 0xfd, 0x80, 0x15, 0x16, 0x31, 0xe0, 0xcf, 0x8f, + 0x1d, 0x5c, 0xe1, 0xe3, 0x81, 0x87, 0x18, 0x60, 0xa2, 0x01, 0x07, 0x38, + 0x3c, 0x80, 0x81, 0x0e, 0x19, 0xd0, 0xe3, 0x45, 0x06, 0x95, 0xf1, 0xf9, + 0x8b, 0x4e, 0x58, 0xea, 0xe9, 0x73, 0x14, 0x32, 0x7c, 0x4a, 0x05, 0x45, + 0x18, 0xe4, 0xc7, 0x82, 0x8c, 0x38, 0xe9, 0xe9, 0xcb, 0x67, 0x34, 0xf2, + 0xf2, 0x11, 0x0f, 0x19, 0x7d, 0x82, 0x01, 0x25, 0x1e, 0xe0, 0xf3, 0x41, + 0x46, 0x18, 0xe9, 0xe8, 0x87, 0x86, 0x58, 0xf0, 0xf1, 0x23, 0x9e, 0x38, + 0x7a, 0x40, 0x57, 0x57, 0x7e, 0xf2, 0xc7, 0x9f, 0x87, 0xf2, 0xf8, 0x8a, + 0x0b, 0xa7, 0x3e, 0xfa, 0xfc, 0x31, 0x07, 0x1c, 0x5a, 0x49, 0x83, 0x1f, + 0x1f, 0xf2, 0xe5, 0xc7, 0xa3, 0x78, 0xfc, 0xc8, 0x23, 0x0c, 0x5c, 0x70, + 0xf9, 0x03, 0x96, 0x34, 0xe0, 0xe3, 0x51, 0x5f, 0xff, 0xe0, 0xe3, 0x4b, + 0x8f, 0x58, 0x7c, 0x80, 0x29, 0xaf, 0x3f, 0x7c, 0xfc, 0x51, 0xa3, 0x1e, + 0xd1, 0xf1, 0x99, 0xc7, 0x7f, 0xf4, 0xf8, 0xc7, 0x27, 0x1e, 0x3f, 0x84, + 0xfb, 0x5d, 0xff, 0xf2, 0xfe, 0x77, 0x6f, 0xfd, 0xeb, 0xf7, 0xdb, 0xbf, + 0xff, 0xf9, 0xf1, 0xd7, 0x5f, 0x5f, 0xff, 0xba, 0xff, 0xff, 0x3f, 0xff, + 0xff, 0xfb, 0xff, 0xbf, 0xff, 0xfb, 0xfd, 0xff, 0xff, 0xff, 0xfe, 0xff, + 0xff, 0xff, 0xff, 0xbb }; diff --git a/hacks/images/matrix2b.xpm b/hacks/images/matrix2b.xpm new file mode 100644 index 00000000..9c7ddb5a --- /dev/null +++ b/hacks/images/matrix2b.xpm @@ -0,0 +1,233 @@ +/* XPM */ +static char * matrix2b_xpm[] = { +"160 182 48 1", +" c None", +". c #000000", +"+ c #061406", +"@ c #0B2A0B", +"# c #081E08", +"$ c #030E03", +"% c #165016", +"& c #1B641B", +"* c #0F390F", +"= c #217A21", +"- c #279027", +"; c #34BB34", +"> c #5AD25A", +", c #2BA02B", +"' c #81DD81", +") c #E0F7E0", +"! c #A7E7A7", +"~ c #040E04", +"{ c #0E350E", +"] c #155015", +"^ c #1B651B", +"/ c #114011", +"( c #0D320D", +"_ c #227C22", +": c #45B245", +"< c #7ADB7A", +"[ c #80DC80", +"} c #8BDF8B", +"| c #52B552", +"1 c #217B21", +"2 c #0B280B", +"3 c #1A5F1A", +"4 c #4EB74E", +"5 c #C6F0C6", +"6 c #D5F4D5", +"7 c #77D777", +"8 c #D9F5D9", +"9 c #83DB83", +"0 c #DDF6DD", +"a c #8EDE8E", +"b c #268C26", +"c c #248624", +"d c #77D877", +"e c #54C954", +"f c #51B051", +"g c #0A270A", +"h c #0C2E0C", +"i c #144C14", +".............+@@#$....$+#+++....$@%&&*#$..+@%&*#$....+##+.................##+......+%=&*$..$*&=%+......+#@#$...............................................#%%*$", +"............+*=-&@+..+*%&%&*@+.+#=;>>,%+.+@=>'-%#+.+#%==*#.....+++++....+@%=%#....+*-)>=#..#=>)-*#....+*&-%#+....+$#......................................+%>'&+", +".$..$..$..$$@-!);%+.+@=>>;',%+.+*;!!)>=+$@&>))',%+.#%;''=@+.$.#%&&%@+.$.#%;',*+.$$@->!,&+..+&,)>-@+.$#*=')-%@+.$.#%%*+.$..$..$..$..$..$..$..$..$..$..$..$$@=')=#", +"...........$*;!)'=#.+*;!!')>=+.@&>!!)';@#&>!))!>=+$@-'!!;%+..#%;'!>&+...@-')>%+..$%>!!-*+..+*-!!>%$.$*,>!)>;&+..+%>!=@...................................$*;!!=#", +"..$..$.....+%>!)'=#.#%>!!')>=++*>!)))!>*@=!!!'!>=++*;'!!'=@.+*,'!''&#..+*>!!,*+..+%>!'&#....#&'!>&+.#%>!))!',#..#&'),*+.$..$..$..$..+++++$.$..$..$...$...#&'!>&+", +"...$..$$...$*>!)'=#.+%>!'>);%+#&>!))))>*@=)!'>';&+$*,'!!!,%+$*;!!>>&@+..*;'>&#...#&');%#....+%,)'&#.+%>!)))'-#+@%-!);=*$.$..$..$..+@*%%%%%*$$..$...$....+%,''-*$", +"........$..$*;!)'&+.$*-;,,>&@.+%>!)))!>*#&'!!!'>=#$@&>!!!>=$$*;!!';-%+.$@&=%@$...#='),*..$..$*,)'=#.+*->!)';&+#&>>!)'>,@..........#&>>>>>>,@.....$...$..*=!!;%+.", +".$.$........@=');%#..+@****@$.#&;!!')>-@+%->!))!;*.@&>))!;=+#%;!))>',@..$##+..$..#='),*+....$*,)'=#..@-!!');=$*-))))))'*.$..++$$..*-))))))'*.$..$$.....+%,)!,@$.", +".....$..$...#&')-*$...$$$$$$..@-!))))!>@#&>'''!)'*$@,>!))';@#='!)))!>@...+......$#=');%+...$$%,)'&#.$@->>,',%$#&;>!)'>,@...#*%*+.$#&;>>>>;-@..$@*%@+.$.@=!!>%+..", +"............+%,;=@............@='!)!!>=#@=!)!!)!>*$#&-'!'!>@@=)!!!)';*......$....+&>!>&#$...#&>)>&#..#*%&%&%#$$#%-!);=*+..+*,>-*$.$#%%%%%%*+..#&;>&+..#%,)>-@...", +".$...$.$.$..+*;>&#.$..........#&>!)!!-*+@=!!)!)',#.+@&>!'!>@@=!!!!)'>*.$.....$...$*;!!-@$..$*-!'>%$...$##$++$...@&')-*+.$.#='!;%$...$.$.++..$+@-'!=@..@->),%#.$.", +"..$.........$*>'%#...$..$..$..+%>!))'=@.+*,>!)'=*$..$*,''>-#+%>'!'''>*..$.$......$@->!;&+..+&;!>-@+.............+%>'=@...$*;!!;*+............$@-''&#+.*;!!=@....", +"........$.$..#*%@+............#*;!!!'&+..$@&>!=*$...$#*%%%*+$#%&====%+......$.$...+*-)>=+..#&>)-*+..$........$...#*%@+$..+*>'>&#$.$.$.$...$...+@%%@+$.*,>;%+....", +"$..$.$........++$.$.$.$.$..$..$#%===&@#....#%&*#......$#++$...++####+.$.$..........#%=&*#..+*&=%#.....$.$..$..$...++$....$@=,&@$...............$+#$...#&=&@$$...", +"..+@**@#+.$.+@**#.....#**%*#+...#@*%*#$....+@*@#+.$+@*%%*@+....+#***#$$@*%%%%@#$.$$@***#$...+#***++......$.....$.$.....$..............$...$.$.......$...++##++..", +".#*=;>,&@$$*&-;>%#..$#%,>>;&*+.#%->>;&*#..+*=;;%+.+*=>>>>,*+..#*=;>;&+@=;>>>>;%$.#%=;>,&*+.+*&>;,&*$$.$....$........$..........$.$.$...$......$.$......#*&==%@+.", +"$*,'!)!;&+#&'!!!-@$.#%>!!)!>-##%>!!)!>-#..@='!!=@$#=>)))!'&+.#*,!!!!-#*>!))!!!=+#%>'!)!>-#$@='!!!'&+.........$.$.$.....$.$.$+#*@#$..........+@*@#+..$.+*-'!!>=@$", +"#&'!)!)';@#&!))),*$.#=!!)))!>*#&'!)))!>*.$*;!))-*$@-')))!'&$$@=>))!!=#*>!)!)))-+#=!!)))!>*#%,)))))-@...#@@#+......#*@#.....@*&-,&#.+@@@@@@@.@&,-&*#$..#&;)))!>&+", +"@-)!>;')'*+*=,!)-*+.#&''>;')'*#%>>;>!)'*.#&'!!),*$@,')''>,&+#%,)!'>,%+#%=-,'!!=+@=)!'>')'*@=>)>>!);*$.#&-,%#.....#&-,%#..+*&,>!);@+*=,,,--&+*>)!>,&@+.#=>)>'!)-#", +"*-)!;,>)'*.+*-'),*$.$@&=-;!)'*.@%=,>)!>*+*,!!'),*$*->)))!'=+@->)!!';%+.#@*='!>&+@=!!'>!!>*@,');;!);*.+@,!)=*$.$.+*,!)=*.@%=>))!;&##=!!!!!!'@#&,!)!>=%+#&;>;>!)-@", +"*-)!;->)'*$.#='),*+..+@&,>)';@.+@-'!)';*#&'!'');%+#&;!'!))-@@,'))))!=@.$+*-!'-*$@=>!)!)';*@=>)>>!);*.+@-'!=@$....*,!!=@.*;'!!';&@+*-!)))))>*.@&;'!!!;@+@&,>!!!=+", +"*-)!;->)'*..#='),*...$*-')',%#.+*&>'!!>**-))!!)>,##*=,,;!);@@,')''!);*..+%>!'&#.@=!!!'!)>*#%,!!)));*..#%--%#..$..#%--%+.&'))'>=*#.*,!!!!!!>*.$@=;!))>*.$*-)!>,%+", +"*-)!;->)'*$.@='),%+$$@=>!)>=@$+*==-;!)'**-)))!)!;@#%-=&,!);*@,')>>!);*..#='!>%+.@-)!'>!)'*$@='!!));@..+@*%@+.....+@*%@+.%>!!!',&@+*,!!!!!!>*+@%,'!!!>*.$*-)',%#.", +"@=)!>;>)'*.@%-!);=*$#%;!)';=*+#&>>,;')'*@-!))))!>@*,>;-;!);*@->)>>!);@$$*=!!>*+.@-)!'>')'*$#&;>'!)-@$.+*==*+..$..#%=&*+.@%->))';&#@-!)!!!!>*#&,'))>-%+.$@=!>&@..", +"#&>!!!)',@#%;'!)!>-#*=)))!!>-#*-)!!!)!>@#%,>!!)!>**,!)'!))-##%,))!)),@..*-)'-@$.@=!!!!)!>@$%-'!!!!=#.$@-')=#....+*,!)=#..+*=,'!);@#%--,,,-=#*>)!>;=*#..+@=!>%+..", +"$*=>'!'-%+#&'!))!';@*-!)))!';@#&>!)!!,&#.#%,'!)!>@@&;!!!',%+.@&>!!!>=+.$@=!>&#..+*-'!!!,&+#&;!!'>-%+.$@-!!=@+...#&'!'=@....@%=-,&#.#@****@#$@=,-=%@+....#='>*+..", +".$*=>>;%#.+*;>''>>=+#=>'>'>>=++*=>>>>&@$.$#&;>>>=+$@&>>>,%#..$*=>>>=*+..#%;-*$$..#%,>>>&@$+*->>>=*#..$#&>>%#.$..@-'';*+$....+@*@@.....$$$...$*%*@+..$...+%,=@...", +"..$#*%*+$$.#*%%%%%@$+@*%&%%*@$.+@*%%*@$..$$#*%%*@$.+#*%**#.$..$@*%*#+$.$$#*@+.....+@%%*#$..+@%%*@+.$..++**#$...+#&,-%#...$....$+.............$$$........$#@@+$..", +"...+++$.....+###+....+#@###$.....+####+.+##@##+....+#@#@##+.$+##@#@#+....+###+++$####+###+..###@@#+...$#@#@##..##@+####..+####$..$.+++.++##+.+#+$+##++...++#+...", +"$+#%&&%#..$#%==&*$$.#%==-=&*#..+@%===&%+*&=-==%@$.#%==-==&*$#%=-=-==%+.+@%===&%+#%==&%&=&@+@%==-=&*+.$@%====%+#%==&%==%+#%===&*+..#%&%*@*&&@#%&%**&=%+.+@%==%@+.", +".@&;''>%#.+*;'!'=*$$*;'!!!>-*++*=;'!'>;@=>!!!';=*+*;'!!!!'=+*;'!!!!'>@+*=;'!'>;@%;''>;'!>%#%>'!!!>-+.#%>!!!!;@*;!!>;!';@*,!!!>&#..%;!>=&-''%*;'>=,>';@+*=;'';=*$", +"+%;'))'-*$+%>!))>&#.%>))))!!=#*,>!!!!!'%,!))!)!!=@%>)))))),@%>))))))!%*,>!)!)!'%%>))'>))!=#%>!!)!',@.#&'!)))'*&>))'>))'*%>!))'=#.$&>)!>,')!=&')!;>!)>**,>!)!!!=@", +"#=!!'');=++*;!))!=@.%>!)''!);@&')!>>'!!%-!)!>'!)>**>!)''!);*%>!)''!!!%&')!>>!!!%%;)!'>!)!%+*->!)';&+.+*,>!!!,@%;)!!!)'-#*->)';%+..&>))'>))!&='))>'!)>*&')!'>!)>*", +"*-)!!))',#$*-'))!,%$*,')>'!);*=')>-=,''*=')'--')'%*,')>>!!,@*,')>>'''*=')>-->''**,)!'>!)'%.+*-!),&@+..#*-'!>=+*,)!!)!-%++%,)>=@+..&;))!>))!%&'))!'!);*=')>--')'%", +"*-)))))',@$*,!!')>=+*,')!)));*=!);&@*%%#&')>=&>!!%*,')'!!;&+*,')'!'-&#=!);=-;>,**-))!!))'*..#='),*$.++#@='!>&$*-))));=@.$*,);&#+..%;))!'))!%&')!)!!);*=!),&&>!!%", +"*-)))))';@#&>!!>)';@*,')))))>%=!),%##@#+&')>&&>'!%*,')))!-%+*,')))'=@$=!);=>!!>**-))))))'%..#='),*$.@%&%='!>&$*-))))>=@$$*,);=**@$%;))))!)!%&')')!!);*=!),%&>'!%", +"*-)!!))!>@*-!))))!>*@,')'>'!!%=!);&*%&%#&')>==>'!%*,')'!!>,@*,')'!'&+.=!)>-'))'%*,)!'>')'*..#='),%+.&>!--'!>%$*,)!!!);&+$*,)>-,>&+%;)!!)>)!%&')'!!));*=!);==>!!%", +"*-)!!')',@%;)!''!)!%*;')>;'!!%&')'-=>''*=')',,')>**;')>''''%*;')>>,*$$&')';>'!!%%,)!>;')'%$#%-!);=@+=!)>;!!>%$*,)!'>)';*#&;)>;');@%;)!>;>)!&&')'>!));*&')',,!)>%", +"#&'!!'!>=#&>))''!)!=%>!)''!!'%%>!!''!!'*-!)!''!);@&>!)''!!!%%>!)'>-@..%>!!''!!'*%>)!'>!)!&+*;'!)'>=+&')''!',*$&>)!'>!!'&*;')''!);@&>)!;,>)!&=')!;'));*%>!!''!!;*", +"+%;')));&+%>!!'>!!'&%>!!!!!!-@@&,'!!!'-@-'!!!!''&+&>!!!!!!'*%>!!!>=#$.@&,'!!!'-@%>!!';!!'&+%>!!!!'-#*,'!!!;%#.%>!!>,;!'&*>!!!!!!-#%>!';-'!'&%>!!,;'!-@@&,'!!'>&+", +".#%=;>,&*$*=,-=&-,-*@&,,,,-=*++@*&-,=&*+*=,,;,=%@$@=,;;;,-=#@=,;,=*+$.+@*=,,-&*+*=,-=&-,-*$*&-;;;-%+#*=,;-%#$.*=,,=*&==*@=,;;,;-%+*=,-&%=-=*@=,-%%=-%++#*&--=%@$", +"..+@***#$.$@**@@@*@+$#***@@@+...+#@*@#+.+@***@#+$.$#@****@#$.#***#+.....+#@@@#$.+#**@@@@@+.+#@***@#..+#@*@#...+#@*@++@@$$#*****@+.+@@@###@@++#@@#+@@+$..+#@@#+..", +".+#+##++.....++++$...+#+#++...$.+++#+++..$#+###++..+#+$++#+..+++$$++++.++++$+#+$.+##++++#+.++#++++++..++###++...+@**#$..+@*@+.......+@**@$...$.+@@#+............", +"@%&===&%#$.#*%&=%*+.@%&===%*+..#*&&=&&*+#*&=====%+#%&&%%&&%+@%&&%*%&&#@%&&%*%&&#@%&&&%&&&#@%&&&%&&&#+@%&====%+.$@-;>&@+.@->=*+..$..+@=;;-@+...+*-,%#...$....$...", +"%>!!!!'>&++%-'!!',*+%>!!!!'=*++%-'!!!'=#@='!!!!!>*%>!!,>'!>*%>!';='!'&%>!';-'!'&%>!!>;!!'&%>!!>;!!'&#&''!!!!>*.#%>!!,%+.*;''=#.....#%;!!>%+$.$@='!,%+....$....$.", +"&'))))!!;**->!))!'-@&'))))!>-@*->)))));@*;))))))'%='))>'))!*&!)!>,!)!=&'))'>!)!=&'))!>))!=&'))!>))!=@=!)))))!%$#=')!,*+.@,>!-%+..$.+%;))'=+..+*;!)>&#$.$........", +"%;')'>!)!%&')!>>!)>*&;)!''!)>*%>!)''!);@%;)!!)')!%=')',,!)>*&>)!;->)!&&>)!'!')!&%;)!'>!)'%%;)!'>!)'%@=!!''!)'%.#=');&#+.+%,)'=@+...+@&;)'=#$.#&'!)!-*$..$.$.$...", +"*,')>,>!!%=!)>--')!%*,)!>>')'*%>)!>>'!,@*,)!!)>)!%&')>=-');**,)!;->)'%&;)!!)')!%@=>!)!)',*@=>!!')',@#&''>')',@.#='),%+...@='!>&+....$%,)'=#.$@-!!>),%$..........", +"*,')>;'!!%=!);&&>!!%*-)!'')!>**;')!!''=#@=>>!)>',*&')>==');**=!!>,')>*%;)!!)))!%$*-'))!;&#+*-')!);&++*-;'!);&+.#='),*$...+%;)!-@$....*,)'=#.+@->>;',%$....$.$...", +"*,')!!))>*=!);==>!!%*-)))))>-@*=;'!))!-@+@&-!);=*+&')>==');*#&>!'>)';@%;))!!))!%$@=>))!,%+.+%;!)>=@..#&;!)'-%+.#='),*..$..*=!!>*+.$.$*,)'=#..#*&&%=%@+.$....$...", +"*,')!!!!-@=')'>>!)'%*,))!!)>-@%,>>'!)),@.+*=!);&#.&')>--!);*+*;!!>)>=+*;))!'))!%#%,'!!!>=#.+*-!);&+.+@=>!)>>,@.+='),*+....$%,!'=*$..+*,)'=#...+####+$.+#*@*@**@+", +"%>!)'';=*+%>!)!!));*%;)!'>)!>*=')'''!);*.+%,!)>=@.%>)!>>!);@.@='!!)-%$*-))!'))'%*,!)!>)!>%.$%,!)>=@.#&>!)!')'%.#=');&#..$.$#&'!>&+..#&;)'=+$.$........*=,,,,,,=@", +"%>))!'-*#.@->)))!'>*%>))';!)!%=!)!!!)),@$#=>!)'-%$*,')!!))-@.#%>))!-@$*-))!>))'*&>))!>))!=+#=>))'-%+#=!))!!)!%.#=')'-*+....+*;!!=#$$*-')'=+....$....$.=>'!''!!>*", +"%>)!!'=@..@=>)))))>*%>))>-;)'=&>!!))!>=#.#=>))!,%$#%,!))!>&+.$@,!)>&#.#&''>,'';@%>))'>))'=$@-'))),%$#&'!))))>%.+&')!;%+.....@='),@.#&;!)'&#......$....,!))))))!%", +"*&---=*+$.+&;!!!!!;@@&--&%&==@*&=-,--&*+.+*=-,-&#$$#%=-,=&@+..#%==&@$.+*&=&%&=%+*&--===-=*.+*=-,-%@$+*&-,,,-=#.+%>!!;&#$....+%>'=#.#%;!)>%+$........$.=>''''''>*", +"+#@@@@$...+@%-=-,-%++#@@#++@@$$#@*@@@++...$#@@@#$...+@@@@#...$.+@@+$...$+#+###+$+#@@@@@*@+.$$@@@@#$..+#@***@#+..#%==%@+...$..@&=*+.$@%=-&@+..$.$.$....@*&&&&&&%#", +"...+++$........$....$@*@+.............$.$..$$@@@+...$..........+#@**@+..........+@*@+........#@@#.......##@+..+@*@+......++@*@#.....................$...$.......", +"$.+@%&*+.$.$.$..$...*=-=*#......$.$.$......+*=-=*+.......$.$.$+*&-,,=#.$..$.....*=-=*#......#%=-%#.$...#%--%#$*=-=*+....+#%=,-%#.$...............$........$.....", +"..#&>'=@$....$$$.$.$%')!-@+.$.....$$+......#=')!=+..$+.+$....$@='!))'*....++++..%')!=@+.$.$$@,!)=@$..$$*=)!,@$%')!=@+$...#-!))-@$..+.++.+.$.$++$$+..$....$.+.$..", +"..@-!);%+..+@*%%@+..%;)!;&*@+.$+@*%%%*#+$+@%=>))-#..#*%%*@+..#%;!)'>;@.+@*%%%%@+%;)!;&*#$..+*;!)-*...$#&,)!;*.%;')-&**+..+%;!)-*+.@*%%%%%*+.$@*****#$.$+@*%%*#+.", +"..#='!'&#.$*=;>>-%#.*,)!'>;=%+#*=;>>>;%+#*=;>'))-@+@&,>>>=%++*;'))!',@#*=;>>>>-@*,)!!>;&*+.#&>!!-*$..@&;!!!;*+*;');;;,*+..@-!),*..&,'>>>',%$*-';;';&*+#*=;>>,&*$", +"$.$*=>'&#$#&'!))!-*$*-))))!';@*;'!)))!,@*;'!))))-@#&'!)))!;@#&'!)))!;@*;'!))))'**-))))!>-#+@-'))-*+.+*,')))'&$@,')!!!!&+$.#='),*+.,!!))))!;@&')!!)!>-@*;'!))!'&+", +"...+@%;%+.#='))))>&+*-)))!))'*&'))!!));*&'))!)))-@*,!)!!))'*#%'!))!',@&>))!)))'**-)))!)!>*.@=')),*..$*-'!!)'&+*,')!!!'%$..#='),*+.,!)))))!>*&')))!)!>*&>))!!)!,@", +"$...$#@#..#='!!!)',#*-))';')!%=!)>,;'!,@=!)>;'))-@%;)!!'!)!%.@=>!!;=*+=!)>;'));**-))'>')!*.+*-!),*+..#*&->!'=+*,'))!>=*+..#='),*..=')!!!!!>*%-))';')'*=!)>;>!);*", +"..$.....$.*-)))))',@*-)!>,>)!%=!);==,>=#=!)>,>!)-@%;))))))!%.#&>!!-%#.=!)>;>!)-@*-)!;,')'*.+@='),%+...$#*,!'=+*,'))!;&#$..#='),%+.=')'!!!!>**,)!;,')'*=!);-,!);*", +"....$.....*;)!'')';@*,))';')!%=!)',-;>,@=!)';')),*%;))!'!!'%.@&>!!,&@+%>!)))))-@*,)!;,>)'%.#%-!);=@+..$#*-!'&+*;')!!'-%$$+%-!);=@$=')'!!!!>%%,)!;,')'%=!)',>!);@", +"........$.*;)!'')!>*%>))!'!)'%&')!''!'>*&')!'!))>**,))!!!!'*+%>!!!'>=+@=;''!!)-@%>)!'>')!&+%;'!)'>=+.+@%=;!'&+%>!)'!!',@$*;'!)'>=+-!)!!!!)'%%;)!'>!)!&&')!'!))-#", +"$.$..$....@-!!!!!!>*%>!!!!!',@*,'!!!!!>@*,'!!!!!>*#&>'!!!!>*#%'!!!!',#+%,'!!!!=$%>!!';!!'&#%>!!!!',+$@->'!)>%+%>!';'!!>*+%>!!!!',#,'!!'!'!'&%>!!>;!!'&*,'!!!'>&+", +"........$.#*-;;;;;=#@=;;;;;&*+#*=,;;;-%+#*=,;;;;=#+@%-;;;-&#+*-;>>;-%+#&;)))'-%+@=;;-=;;-*$*=,;;;-%+$*;!))!-*$@-;-&-;;=#+*-,;;;-%+%,;,,;,;,**=;;,=;;,*#*=,;;-%@$", +"..$..$.....+@*****@$+@*****#$..+#****@#$.+#*****@$..#@****#+.#@*%%**#.+*->'',%#.#@%*@@***+.#@****@#$$@=>'';%+$$@**@***@$.$@*%***#.#********++@******@+.+#***@+$.", +"........$.....$.$...........$..........$.$+$......................................................................+++$.....+++$$....+++$..............$.........", +"$.$..$.............$...$.......$.........$#*@+....$......$...$..$...$.........$..........$.......................#*&&*+$...#&=*$...+*&&*#................$......", +"..+..+..$.$....+........++..$....$.$....+@=,-*+$....$.$........+......$.$.$.....$.$+.$+....$.+.$.$.$.$+.+.$.$.$.+%-;;%+...+*,>&@$..+%,;-%#$.$.$.$.$...$.....$.$.", +"+@*%%**@$..+@*%%**@$$+@**@**@+..+@*%**#$+%;!!=%@+.+@*@##@*#++@**@@*%*+$@**@#***+.#**@@**@$+@**@#**@+$#*%%%%@+...@=!!;*+...#&')-*+..$*;!!=@...............$......", +"*-;;;;,=%+#%=,;;;;-@+*-,,,;,=@$#%-;;,,=+@='!!>,&*$*-,-&&,,=#*-;;,-;;,**-;,=&-;,*#&,;,-;;-@*-;,=&-;,*#=,;;;,-%+.+*-)'=@+...#='),*....@=')-*+...++#++++.$...$.$...", +"&!)))))'-@*,>)))))'*#&!)!!))>*$*-!)))!>@*,)))));%$&')!,-)!'*&'))!'))!=&'))';!)!=*-))!>))!*&!))>,!)!=*>!))))!&+.$%,)'=#..$.#='),*+$..#=!),%..+@%&&&&&%+..........", +"%>)))!))'*&!!)!!))>*#&>!))!!>*#&')!!))'**-!)!!'-*$%>)!;,!)'*%>))'>!)!&&!)!!!')!&@=')!')!>*%>))!;!)!&%>)!!)!>&+.#&>)'=#....#='),*$...#=')>&#.#&''!'>'>*$.$..$....", +"%,))';')!%=!)'>!)),*$*-!!';,=@+&'!))!';@#='!!,=%#.*,)!;-')'**-'!!>)!>*%,)!!)!)!%+%,'!)!;=+*-')!>)!>**,''))'-*+.#=!)'=#$...#='),*..$.#=')!=#.*-))))!)>*.......$..", +"*-))'>')'%=!)'>'))-@.@=!!>=%@+#&>!))!'>*#&>!'-&%@+*-)!;,>)'%#%>!'>)>-@*-))))!)'*$@=>))!,%$+%;!!')>=#@=>!)!>-*+.+&>)'=+..$.#=')-*+...#=')>&#.@-!'!!!';@...$.$....", +"*-)))!)!>*%>!)!)))-@+%,!!>,&@$#&'!!!))'*+%>!!>>;=#*-)!'>!)'%$*='!!),%$@-!))!))>*+%;!!!!>=#.+='))!,%$*,')!'''&+.$*,)!=#....#='),*+...#='),*+.#*----,=%+$.....$...", +"*,))!!';=+@&;'!!)),@#&>!)''-%$@=))!!!)'%$*,!!!)!;@@=!)!'))!&.#%>))!=@.#&>!!>)';@@=')!')!>*+#&>))>&@$%>!)!!))=+.$*,)'=@....#&')-*+..+@=')-*+..+@@@@@@+........$..", +"%;)!',=%@$$@%=,'!),*@=))))),%$#='!!))';*$#&>!)!>=++%-'))!)!=.$@=');%+.$*;'';!;=+@=))'>))'*#&'!))-*$.*>!))))!=+.$#-)!-*+.$.+%>!=#+..$*-!)-@$....$.+....$.$.$.....", +"%'))!>%#....#&>!))'*+%=,,--%@.+*==---=%+.$#%=-=&*+.#*=----=@..+*==%#+.$#*&&%&%@+#%=-==--=##=!!!!=@+.#%-,,,-=*+.$#%>>>&+...$@&=*+...+&>';&#.$.................$..", +"*->>;=@$....$@=;>>-@$#@***@#$..+#@@**#+..$$+@@@+$...+#@***@+...+#@+$....$#++#+$.$+@*@@@*#$$*=--=@$..$#@***@#+...$@%&%@+....$##+..$.+@%&%@$...$......$...........", +".......$.$..............#@#+.....+++#$...........$.+#++$##+.$...$+..$...$#@**@+$.............+++$.......++$..........$.$......$..........$....+++++...$.$.+.$.$.", +".~{]&^/~...............+%=&*+$..#*&&%*+$..+.....+.$*&=%%&&%+..++**@$..$$@&-,,-&+...++##+$$.+#*%%*@+...+@%%*#+.$..........$.................$.+#*&&*#+...+@**@+..", +"(_:<[}|12$.$.$.$.$.$.$#%-)'=*$.#*->>>=*+.#@@@@@@#$@=''>,>>,*..+*,'&@..$#&>!))!>@$+@%&%&%@.+*&,>>,&@+.+@=;>,%#...$..$.......$..$.$.$.$.......+*=;'>,=*+.#*-,,=%#.", +"345)))643....$+++....+*=>)!;=++@=!)));&+#*,-==-,=#*,))!>))'%..#&')-*+.+%;!)!!)'*.+%->=>>*$@&>!))!'&#.#%>!!)-@....++++++$.+##@@@#$......$.$..@&>!))!'&+.#&!))!-@.", +"_78)))87_...+#%%*+..+*->!))';@$%;!!'',%$#=!!!!!';@@-!)!>)!>*..#='),*..@=>!)!''>@.+*=,=,-*.*,!))))!,@.@='!!)-*+..@%%%%%*++*&=====%+..$.+$$$..*,!))))!,@.#&>''>=@$", +"_90))))a_$..+*;'=#..$%>)!'!';@#&>!';-%@.*=!))!))>*+&;!!')>-@$.#=')-*$.*,))))!>;@..#***%*#.&')))))!'*+*;!!!);%$+@&>!>>!;@@=!!!!!!'*.+@*%%%*@+&'!))))!!*.+@&--&*+.", +"ba)))))ab...#%;>,*..+&')'>>>-#@='!!>-*+.*-))!'))>*$*-')!);&+..+&'!-*$.*;))!))'>*...++$+$..=!))!!!!!%$*;!!!);&+@=;!!!!)>*@-!!))))!%+*-;'>>>-@=!!)))!!!%..+#@@++..", +"ca)))))ac$..#&>',*+.+%')'>>;=#@-!)))>%#.*-)!'>!)'*$@='))!;&+..+&>!-*..*-!))!))!%$.......$.=!))!!!!!%+*,!)))'=+%>!)'!)!-@#%,>>>')!%+%>!))!!>#=!!)))!!!%.....+....", +"ca)))))ac$..#='!>%+.+%>!)'!'-#@='!)';&@$@-))!'))>*$@-'))!;&+..+&')-*..#&;!))!)!%..........&>))))))>*$*,!)))>=+%')!!)!>=#.#*%%&,)!%+*,>>>>>-#&>)))!))>*..........", +"ca))))8dc..$*-!!>&+..*=>)))'=+@=')!>>;-@@=!))))!>*$@->!)';&+$.+=')-*$.#%,>'!))!*..$.$.$...*-!))))!-@$@=>''>-%$*>')'!))-@..$$+@&>;*.+*%&&&&*+*-!))))!-@$.$.$..$..", +"_90)))87_$.+*-))'&#..+*=;)!,%+*,))))))'*+&;>;;;>-#$*-!)))>=$..+&')-*+.@=!!!')>-#........$.#%;'))';&+.+@%==&*#.@&,!!'!)>*.....$@%*+$.+####++.#%;'))';%+.....$....", +"345)))643..$*-))'&#$..+*-!>&#.@-!!!!!!>*.@%&%%%&*+$@-'!!!;&+..+%>!=@..#=!!!!!-*+$.........$@&,'';&@$..$##@#+...#%;>>>!,@$......++...........$@&,'';&@+..........", +"(_e<[[f_g..$@='!>%+....#*=&@$.#%-;;;;,&#.+##$$+#+$$#%=;;,&*+..+@=;%#..+*,>>;-%#...$.$...$..+#*%%*#$...........$+#*%%%%*+..$.............$....$#*%%*#$..$..$.$...", +".~hi&]{~....+@&&%#.$....+##+...#@****@#+............+@**@#$....+@@#.$..+*%%%@+...............$+++...$......$.....$$$$$$......$...$.$.$....$....$++$..........$..", +"..+@**@$.$...........$+@**@$....+***@+........+.............$$#*%%%%*+........$.$...$...$....#@@#+....$+++..............@**@+.....@**#......@%%*@$...$..$.+$....", +"$+*=;,&@+....+##+$...$*=;;=*+$.+*=;;=*+...$+@*@$$.$.........$@&,;>>;-#...............$.....+#%-,%#...$@*%**+$.$.$.......&>'=@+$.+.,';&#$++++=>>;=@++#$...#**@+..", +"$*=!'!>%#.$.+@&=%+.$.#&''!>=#..#&''!>=#$..#*-,=@....$.$.$...@=''!!!!>*$.$.$.$...$.$.....$..+%,'!=@$.+#%;'>-*+.....$.$...-'!;%#+@@+>!'-@@%&%+;!!';&*%&@...*,>%#..", +"#&;)'!!,@+.$#&'!-*#..#&''!'-@+.#&'!)!-*+..@='!-@+.+@@@##@@@.*,)!!))!'*...............$.....$%,!)-*..#%;!'!!-@+.+++$$+.$.,!)'&@%=,#>)!;%&,>;#>'!!'=->'%$.+*;'=@..", +"#=>)>!';*$$*&,!);-%+.#&>'!'=@+.#&>!)!,*+.+*-!>&#..*=,-&&,-&#%;)!!))';@...+@@@.$...$.....$..$@=!),*+.@=>)'!!;*$#*%%%%%@$.=')'=&;!!*,)!;=;!',@-')!>,''>*..+&;'=@..", +"$%-!'!!=@$#=''!)!!;@.#&>)!>=@..#='!!!;*$..#&-&*+..%')!,-)!'**;)!)))',@..@%-,%+.......$.....$*-!);%+.#=>)>!!;*$*,>;;';=*$=')',;'!>*,)!';'!>-@>'!!!'!'-@.+*-!)-*..", +".@%,>;&*$.@-))))))'*.#=)!!'-@+.@=)'!!,*+..++@#$...%>)!;,!)'**=!))))',@.+@-!)=@+.$.$.....$...*,!)>&#.#&;)'!!-@.%'))'!!>&#;!)!'!!!;*'))!!))!;*>))!!)!'=++*=>))-*+.", +".$+*&&@+..+&;>!)'>-@.+&>'';&#..#%>>';&++....$.....%,)!;,')'*#%,>!))>,@.$@,!)=*......+++....$*,''>&@.#%,!!!>=*$@,')!!!);*,'!!!))!;*'!))))!!>*-!!!!)!'=+#&'!!'=*+.", +"...$#+$..$+@&-');=*+.+@&==%@...+@%&&%#+...$...$...*-)!'>!)'%.#%-!))',@..#%-,%#.....@%%*+$..+@%==&*+.#=>)))';*+@=>))!!)>*%-;')!));*=>'!''!!>*%->!)!)!=#@-!)';;=*$", +".$........$#=;'!>-%+..$####.$...$###+...........$.*-))!'))!%.$*=!))',@...+@@#..$.$+%>!=*+....##@++..#%,!!!'-@.*,')!!!);**->)!!));*='!',>)!;@*-')!!)!-@@-)!'>!;=+", +"....$.$...#&>''''>=@..................$...$.$.....*-))))))!&+#=;!))!'*$.....$....+@,!)>%+........$..$#*&==%*#.%>))'!!>=#*>!!!!))'*;)';,!!';@&'!!!!)!;@@=!)!')>=+", +".$......$.#=))))))!*$.....$...$...............$...*-)!>,--=@$*;!))))'%...........$*;!)'&+..$.........$+###+$..*,',;>;=*$*,'>>'!)'*,';=,!!!;*&''>>')!;@+%,!)));%+", +"..........+%=,,,,-=+..$.....$...$.$..$.$..........@=!'-*+++.$@=>''''>*.$....$....+*,!!;%+....$...$............#*%%%%*@+.#&=&&=>';@&&%%=>>>,#*=&&&-'>=+.#%=---%#$", +"..$.$.$.$.$+@*****#+....$.................$.$...$.+%,=*+.....+@%&==&*+...$....$...+&;>&@.$.........$.......$.$.$$++++...$####@*%*$###+@%%%*++##+#*%%@$..$@**@#$.", +".+@%*#$......+@*%@$.$.+@%%*+.$..+#**@+.$.....+......+*&&*+$...+#@@@##+.++@****@+.+@%%#$....$.+#%%@+..$+@%%@$...+#****#$..$@%%#$.......+*%*#...+*&=%#.$.$#*@@@@+.", +".#&';%#$$...$@=,'%#..+@=>!&@...@*-,--*+..+@@*@@#...$@-''-@+..$@&--==&#+#%->;>,=#$#%>,=@+....+@&>'&#..+*=!>=@+.$@&>-,,&@..#&;;&@$$....#*='-*+.$@=>!,%+.$@=,-=;=*+", +".#=>'>%+..$+@&>'>%+..#&'!!;*+.+*,!!!!=@.+@&,,='*#$.#%;'';*+..#&>>''>'*@-;!!!!!!@+*=>)'-%@$+@&-!!>=@++*-'!)'=*.#&;!>'';%+$@&>'>&*+.$+#%,>'-*+.#&>!!!=*$#%;''>'>=#", +"$*->!!=@..$@&;!!,*+.$*-'!!'%#.#&>!!!!=@+$*,!'>>&+.+*->!!,%+..@=))))))%%'!!''!!!%*,''!!''&+*,>'!!'>=+*,'!!!!'=#%;'!!!!'=#$*,>!!>-%+$@=,'!';&+$%;'!'!>=+#&>!!'!';@", +"#%>'!!,%+.+%;'!!,%+.#&>!!!>&#.#&'!!!>&#.#&>'!'>&#.#%>'!!;%+.+@-!))'>)%&')'=->''%&!))))));@%!))))));@%'))))));@&'))))));@#&'!))!',#+%'!))!',##&'!)!)!;@#&'!)))',@", +"$%'!))'=#.+%'!))'=@.#%'!))'=@.#&'!))'=#.#%'!))'=#.#%'!))'=#.$*-)))!!>*=!);&*=-,#*;')>>!),@@;')>>!),@*;')>>!),@%;')>>!);@$*,>!)';=#+*,>!)';=#+*,>!)';=#$@&,!)>-%+", +"$@='!)!-*.+@='!)!-*$+@='!)!-*.+#='!)!-*.+*-'!)!-*+$@='!)!-*.#&;)))));*=!),%#@**+*,')>'!!=#*,')>'!!=@*,')>'!'=#*,')>'!'=#.#*-!);&@..#%-!);&@+.#*-!);&@$.+@='),%#.", +"+*,!!');&+$*-!!');&+$*,'!');&++*,!!');&+$*;!!');&++*,!!');&+*,'))))!;@=!);&*%%*+*,')!)!,%+*,')!)!,%$*,')!)!,%+*,')!)!,%$.$#=!);*+...@='),%+...#='),%+...#='),*$.", +"#&'!!')';@#&'!!')';@#&'!!')';@#&'!!')!;@+&'!!')';@#&'!!')!;@%>!)))!'-*=')!-,;>;@*,')!)!;=#*,')!)!;=#*,')!)!;=#*,')!)!,=#.+@='),%#$.+@=!),%+$.+@='),%+$..@='),%+.", +"*,))))))'%*,))))))'%*,))))))'%*,))))))'%*,))))))'%*,))))))'%=!)'!!'>!%%>!)))))>*%;')>'!'!*%;')>'''!*%;')>'''!*%;')>'''!*.@&,!)>=*$.@&,!)>=*$.@&,!)>=%$+@&,!)>=*+", +"&>))!'!)!&&>))!'!)!&&>))!'!)!&&>))!'!)!&&>))!'!)!&&>))!'!)!&;!)!)))))%@->!))!!,@&'))))))!%&'))))))!%&'))))))!%&'))))))!%#%>!)))',#+%>!)))',#+%>!)))',#+%>!)))',#", +"&'))!>))!=&'))!>))!=&'))!>))!=&'))!>))!=&'))!>)))=&'))!>))!=,!!'!!!)!%$#=>))>&@$%>!)!!!!'*&>!)!!!!'*&>!)!!!!'*%>!)!!!!'*+%>!!!!'-@+%>!!!!',@#%>!!!!',#+%>!!!!'-@", +"%;''>;''>%%;''>;''>%%;''>;>'>%%;''>;>'>%%;''>;''>%%;''>;>'>%%,;;;>>>;@.+&')'=@$.@=;>>>>;=#@=;>>>>;=#@=;>>>>;=@@=;>>>;;=#+*=;>>;,&++*=;;;;,&++*=;;>;,&++*=;>>;,&+", +"#*&&%%&&%##*&&%%&&%##*&&%%&&%#+*&&%%&&%@#*&&%%&&%##*&&%%&&%##@*******+.$@&=&*+..$@******@$+#******@$+#******@$$#******@+.+@****@#+.+@****@#$.+@****@#..+@@***@#$", +".+$++++.....#*%%**#..$@%%@+..$...$@**#....+*&%*+....#*%%**#$....$$$..$.............$+#@@+..$@%%@+......+@**#$...+*&&*+......+$$.......#*%@+..$#++........@**#$..", +"@%&&&&%*+.+#%;'>>;*+.+%>>-@+....$@=;;%+..+@='>-@+..#%;'>>;*+.+#*@**#$....$....$..+@%&&-=*+.+%>>-@+....$@=;;%+..+*='>-@+..+@*@**#+....#%-'=@$#*&%%@$$.$.+@&,;&*+.", +"=>!!!'>-%++%-')!'>&+.#&'!>&#.$..#&>!>&#..#&;)!>&#.+*=')!'>%$.#%-=--%@$.#@#+$#@#++*=>!!!!=#.@&'!>&@+$.+@&>!'=@+$#&;)!>&@+$#%-=--&@+.+#%->!-%+*;''>-*$$..#%>!!'=*$", +"-!)!!!!!-@@->!))!>=#+#&;!',*#..#%-)!;&#.+@=!'!',*$#&;!))!,%$+*=!>'';*++*,=%*%,=+*,'!!)));@#%-;)';&%+#%=,)!>-%+#&,!'!'>&+#&,!>''>&+#%&-')';=#%>!)'>=*#+$*,!!!)>&+", +",!)!'!!)>*%>!!'!!!>@*-'!!!!!=#*-'!!!!!=#*,')!!!!-#*;!)!!!!-#*,')'!!!-@#='>,-;';@&>!)!!))>**;'!''!!;@*;!!''!!>@*>!)>'!!>@*>!)>'!!>**;'!!'!!>&*>!)!!>;&#+%>!!>)',#", +"-!)!>>!)!%&'))>'!)>*&>!)''!)>*&>!)''!)>*&'))''!)>*&'))''!)>*&'))''!)>*@=!)''!!>@=!)'!!!)!%&')!;>!)>*&')!;>!)>*&')!;>!)>*&')!;;!)>*%>!)'>!)!&*,')!!))>*+%>!!!)',@", +";!))'>>!!%&'))!'!)>*=!)>--')!%=!)>--!)!%=!)>--')!%=!)>--')!%=!)>--')!%#&;!)))>=#=!)>)!'!!%&')>=-');*&')'--');*&')>--');*&')'--');**='!'>!!>**,')>>'!!%#%>!)))';*", +";!)!>;>!!%&')!)!!);*=!),&%>'!%='),&%;'!%=!),%&>'!%='),%&>'!%=!),%&>'!%$*-'))!;&+=!)>)!'!!%=')>=-');*&')>==');*&')>=-');*&')>=-');*+*,'!!);=#*,')>>'!!%+%>!!'!)'%", +"=!)',,>!!%=')'!!));*=!);&&>!!%=!);&=>!!%=!);&&>!!%=!);&&>!!%=!);&&>!!%+%>!)!)>-#=!))!'!)!%&')>=-');*&')>=-');*&')>=-');*&')>=-');*.#%>!)'=@$*,')!!!)'*#&>!!>>)!%", +"=')';;'!'*&')''!));*=')';;')'*=')';;')'%&')';;!)'*&')';;!)'*=')';;!)'*@='!!'!!>@=!))''!)'*%')';;!),@%>)';;!);@%')';;!);@%>)';;!),@.$%,!)>=@.*;')))!!;@#&>!!>>)!%", +",!)!'!!!,@=')!>'));*%;!)!!!!,@%;!!!!!!,@*;')!!!!,@%;!)!!!!,@%;!)!!!!,@@=!';->!>@&'))!!!!,@*,')'!!!-@*,')'!!!-@*,')'!!!-@*,')'!!!-@+@->!)!,%$&>!)!';-%+*-!)!!!)'%", +";)))))!>&+='));>!)-@@&;!))!>&+@&;!))!>&+#&;!))!>&+@&;!))!>&+@&;!))!>&++%-=%*&-&+%>!)))!>&+#&;))))'&+#&;))))'&+#&;)))!'&+#&;)))!'&+$*,!)))>=$&'))!>&*+.*,))!'))'*", +"%-,;,,-&@$*=--=&--%+$@%-,-=%@$+@%-,,-&@$$@%=,-=%@$$@%=,-=%@$$@%-,,-&@$.#@@+$#@@+*->;,,-&*$$@%-,,-=*$$@&-,,-=*$+@%-,,-=*+$@&-,,-=*+.#%=,,-=*$*=,-=%#+..#%-,----=#", +"#@****@#$.$#**##@@#+.+##**@#$..$##**@#+..$+@**@#$..$+@**@++..$##**@++...$+...$..#@*%**@#...$#@***#+...#@**@#+..$#@***#$...#@**@#$..$##**@#$.$#**@+$...$#@**@**#$", +"..+@@+........+##+.....+#@+.....$.$$$...............$#**#$........................#@@+........+#@#$....+#@+...............+@@+...$....+#@#+....+#@+.............", +".+%-=*+.$...++*&,*+...#*=-%+.$.$#*%%%#+...+++#+..$..#&,>%#............$....$..$..+%-=*+$.$...$#%,&@$$.+@=-%#....+#+#++..$+%-=*+......$#%,&@$..+*=-*#..$.+#+##+..", +"$#&>>-*+....+*-;>%#$.+*=>'-*+.+@&,;;,&@$.#*%%%%@+..+@,'!=*+.$.+.$.+.$...$.+.+...+#&>>-*$.....#%,'-*$..@&>',%+$.#*%%*%*#+$#&>>-*+.$...#%-'-*+.$*=>'=*+..#*%%%%@+.", +".#%>!'=@.$.+@='!;%+.$#&>))>&#.+%;!))!-*$+@-;;,>%#..+%;'';*+..@**@***#+.+#****@+..#%>!'=*+..$#%;'!=*+.+%;!)!=*$+@=;;-'-%$.#%>!!&#...$#%;''=#.$#&'))>%#.+@=;;,>%#.", +"$@=;'!,%#.$@&;'';&#.+*,''>!=@.#&'''!'-*.+*,>!>'=@.+@=>!!,&#.@&,,--,,&##*&,,;,-%+$@=;'!;=*+$@&-'!>-%++@=>'!';&++%,>>>';=+.#%;'!=*...#*-'!,%+.$@->'''&+.$*->'>>&+.", +"#%>!))!=*+#%>!))!-*$#&'!))),*$#='!)))-*+#&'!)))-*+#%>!))!-*+%'!!!!!!>**,'!!!!!,@#&>!))!',@#&>!))!',@#&'!)))';@@='!)!)';@+@-'))-*+$.@-')),*$.$*,')!;%+.$*,')!;%+.", +"#='!!')>=+#='!!')>=+#='!'')>=+#&'!!')>=+#='!'')>=+#&'!'')'=$&>!!)!!')%&')!'!));**-))!'!)'%*,))!'!)'%*-))!'!)'**,))!'!)'*.#&;!),*$..#&;!),*+..@&;!),*$..@=>!),%+.", +"@='!!!)',@#='!!!)',@@='!'!)',@@='!!!)',@@='!'!)',@@='!!!)',@&>!!)!!')%=!)>-,>'-@*,))!'!)!%%;))!'!)!%*,))!'!)!%%;))!'!)!%.$@-!),*+..+*=!),*$..+*-!),*+..+*=!),*$.", +"*,!!!!)',@*,!!!!)',@*,!!!!)',@*,!!!!)',@*,!!!!)',@*,!!!!)',@,!)!)))))%=!)>,,;>-@%;))))))'%%;))))))'%%;))))))'%%;))))))'%.+@=!),%+..$@=!),%+$.$@=!),%#..$*='),%+.", +"*;)!>>)';*%;)!>>)';@*;)!>>)';@*;)!>>)';@*;)!>>)';@*;)!>>)';*>!!>))!!!%&>!)!!!)'*%;)))!!!'%*;)))!!!'%*;)))!!!'%*;)))!!!'%$@&,!)>=*$+@&,!);=*$$@&,!);=*$+@&,!);=*+", +"*;))))))'**;))))))'**;))))))>**;))))))'**;))))))>**;))))))'*>!)))))))%@&;'))!'-@@-))))))'%*-))))))'%*-!)))))'%@-))))))'%+%>'))!',#+%>'))!',#+%>'))!',#+%>'))!',#", +"*='!!!!!>**='!!!'!>*@='!!!'!>*@='!!!'!>**='!!!'!>*@='!!!'!>*='!!''!!;*.#&>))>&@$#%->!!!>,@#%,'!!!>-@+%->!!!>-@#%->!!!>-@+%>'!!!',#+%>'!!!',#+%>'!!!',@+%>'!!!',@", +"+%-;>>>;=#+*,;>>;;=##%,;>>;;=##%,;>>;;=#+%,;>>;;=##%,;>>;;=#%-;>-,>;%+.#&')!-*$..#*=;>;=%+.#%->>;=%+.#*-;>;=*+.#*=;>;=%++*=;>>>,&++*=;>>>,&++*=;>>>,&++*=;>>>,&+", +".#@**%**#+.##*****#+.##*****#+.##*****#$$##*****#$.##*****#$+#**@***#..+*&-=*+....$#***@+...+@***#+...+#***@+...$#***@+..+@***%*#$.+@***%*#$.+@*%%**#$.+@*%***#$", +"$@*****@#....####+....+##+.........#+#$....#**@$.....+#@@++.$.................$..........$.++#+$...$....+@#+.....+#@#.................$+##$$#***#...............", +"@=,;;,;-%+.+@%===*#..+*&&*#......+@%=%#+..#%-,=*$$..#*=-=&*$..++.++..$...$++....$.........$#%=%#+......#%=-*+.$.#%==%#.$..$++.++.$..$+#%=%#$*-;-%#...$...+$+$+..", +"%>)))))',#+@&>'''-*+.#=>'-*+$.$.+@=;)-*$.+*,!)>&@..+*,'!>>=+.+@%****#+..+#%%@+....++++++..#%,!;=*+.$.+#%;>!&@..#%,!!-%#..#*%*%%@+...#@&;)-%$&'))-*#....+@*%*%*@+", +"&'!))))'-@#&>!!)!-*+.#&>!!-*$...#&>!!-*$$#=>!!!-*$$#=>))!>=++@-;>-!-%+.+#&>>&#+..+@%&&&%*+*=;'!>=%#+#*&-'!'-%+#%-'!!!-*+@&,>;,!=*+#*%=>!!;=#%>!)>,=%#+@*=>>->;=@", +"%>!!!!)';@%>!!!!!,%+$@=>!)'=*++#&>!)!-%+$*-'!!!,&+$@='))!;=++*,'!'!;&+.$*,!)-*+.+*=!'!'';@=>'>'''>%+%;'>>'!!-@%;'!''!',#%;''>>!',@*;''''''>&*,')!!';&+*;'!';!!'&", +"*;)!'')!'*&>)!!!!>=##&;'))!>-@#&;'))!>-@#&>!))!>-@#&;!))!>-@#&>!))!>-@+@&;!)-&@+*->!!!!!'*,!!>,'!!=#&>!';;)!>*&>)!>>!!'*&>)';>)!>*&>!!>;')'&*,'))))!;*&>)!>;!)!=", +"*-!)))))!%&>)))!)!>**=)))!))'**=)))!))'**-)))!))'**=)))!))'**-)))!))'*@&,>>>;,=#&'))!))),*,!)>,>))-@%>)!;,!)'*%>)!;,!)'*&>)!;,))'**-!)'>)!'%*,')'>!)'%%;))'>!)'%", +"*;)!''')!%%;))'>')'**;)!>>')!%*;)!>>')!%%;)!>>')!%%;)!>>')!%*;)!>>')!%%>!))))!>*=!)'!)));*=')',>!)-@*,)!;,')'**;)!;,')'*%;)!;,')'*#&;!!')>-@*,')>;'!!%*='!!>)';*", +"*;)!;,>)!%*,)!>,')'**;)!,,;)!%%;)!,,;)!%%;)!,,;)!%*;)!,,;)!%*;)!,,;)!%*-;>''>>-@=!)')!!);*&')',;!)-@*-)!;,>)'**,)!;,>)'%*-)!;,>)'*$#=>))!-*$*,')!'!)>*$*-'!!);&+", +"*;)!>;')'%%,)!>,')'%*;)!>;')'%%;)!>;')'%*;)!>;')'%*;)!>;')'%*;)!>,')'%#*&,''-&*$=')!!!!);@&')';>!),@*-)!>;')'**-)!>;')'%*-)!>;')'%$@=>!);&+.*,'))))!,@.#&>!)'=@.", +"*-!)!'!!'*&>))'>!)!&*,!)!'!!'**-!)!'!!'**-!)!'!!'**-!)!'!!'**-!)!'!!>*.$*,!!-@+.='))!!)!-@*;!!'!))>*#='!!'!)!&@='!!'!)!&#='!!'!)!&#%>!)),*$.*;')>>;-%+$*-'!);%#.", +"#&>!)))';#&!))!>)))=#&>!)))',@#&>!)))',@#&>!)))',@#&>!)))',@#&>!)))',@.$#=>'&#..='))))!>%+@=>)))))'*+*,!)))))=+*-')))))=+*-')))))=#=!)))-*..&'))!>&*+.#&!)))-*+.", +"$@&-,,,=%+*=,,--,,-*+@&-,,,=%+$@&-,,,=%+$@&-,,,=%++@&-,,,=%+$@&-,;,=*+..$@%%@+..-'!;;,-&*$$@&-,,,,=@$#%=,,,,-*.#%=,,,,-*.#%=,;,,-*#&'!!'&@$.*>!!';*$..#&'!!'&#..", +".$#@***#+.+#***@**@+.$##***@+..$#@***#+..$##***#+..$#@***@+.$$#@***#++..$$#++.$.*&&&%*@#$..$#*****#$..+@****@+..$#****@+..+@*****+$@&==&@$..@%==&%#+..$@&==&@$..", +".............$+@*%&*.$.++$+$............$.........$............$........$#*@+....$#@***#+...$#+.....$*%&&&&%@+............$.$$$..................$+@@#..........", +"..##+$#+..+#*%&&;'',.$*%*%%*+...++#@@@#...+++$$......#@@#..$+#**@+....$.#%;-*$...+%;;;;&#..+*&%#....#=''''''=#....+##+..+#*%%%*%*#$.........$...+#&=,%.$..++....", +"+@%&**&%#+@&-;;;'))>.@&>-,;=*$+*%%&---%@+#%%%%%%*+$$@%--&@+.+&,;=*+.$.+#*-!>=*#$$#=!'!',*$+@=>;*#++$@;))!!))-*..$+*==*#$#=,;;;;;,&..+@%%*@+.$+++#%;>'-..+*%%@.$.", +"+&>>=-',%+%>!)!'!)!;+&;)''!>&#*,;>'!!!,%+&>>>;>;-*$@%,)!;=%@@;!)'&#...+&->)!;,&@.*-)!)';%+$*,!!-&%%@*;))!!));%...#&''-@$@>!)))))!-.#%,;',=*+#%%#*,!));..+=';%#..", +"@;!);>);%#%'))'')';&@->)''!',%*)))))))!&#-))))))'&@=;;!!'>;&#='!'-*+..*>!!))!!>%+&;)>)'>=*+&>!!;;>;&*;))))));&..$@=!'-@.+&->!)>;,&+*,!))!>=**>,%%>))>=..#;!!=#..", +"*>))'>),*+*>!!>>)!>&%'!)!)))'-*>'!))!',%@;)!''!)>&%'!!)))!!=+=')!'&#..%!)!))))'=*'')!))!>-#=!))!!!!=%'))))))!,..+@=!'-@+@&-;!)>>>-@,!!)!!)>&*'!-=>!),%.+*'!>&#.$", +"@-''))!=*+@;!',;))'=*>')'!!';&#%=>!!;=*#*,)!;,!);&%>'!)!!!!-+='))!=@..%'!>)!!)!=*'!)!))!'>*;)!!!!'>&*')))!!!!-...*-!'-@$&>''))!'!>*'!!!>'!)=*;)>,'!!=*.+%!!,&@$.", +"+*,>))>=@$*>!>,;))!,@->)''!>=@.#&>!'=@+.@,)!;-');%#=>!)!'!!=@,')!'=@.$%'!')!!)!=*>')'))!>,*>!''!',%#*>)))!!!'&.$.*-!'-@$&>''))''',%!!!!;>!)-#=!>>!!>&+.@=!';,&*+", +".@&;))'-%#*>!>;>)'',+=>)''!>%#.#&>!>*+..*;)!;-');%+%,!)'!)'&*'))!;&@#+*')!)!!)'=#->)>)';&*@>,;'!>&#.@-!)!!)),%..+*,)!=@.#%=,');=%*=!!!',>!)-+*=;!!'=@$+%;!'>!'=@", +"+%->)))>,%@>!'>'!,&*+=>)''!>%$+*=''=@$..*,)!>;!);%#=;)!'!);%*>))!;-=&**;>>)!!)>%#,')>)',*$+*&;!!-@$.+=!!>'!)-*..#&,)'&#..#%-'),%#$=!!!','!)-$@&;)!,*+.@=!!>>!);&", +"@=')!>))!,#=')))>&@++=;)!!!>%$#='!>%#..$@;)))!));**>!!'!)!-@*;!))))!',+%=;)!;-&@*')';)>-@$$*=>';%#..+*=;'!!!=@.#%-!)'%+.+#=>!)-*$.%')!>'!);&+&,)!'&#..&'!)))))!-", +"%!!>--;''-+%,''>=@+.$&;)!)',*$*>!'=#....@-)!;;>'-*=!!;,>';%#@>'>>>!!'-++@-)'=*#+*'',-!>=@$$%>'>%#....#*=>)!;%++@,!);=@$.+#=')!-@$.@=;>'!',&@*;)',&#$..&!)!!''!)-", +"*>>=*@%,-&.#%,;=*#..$%,!'>;=#.@,>,%+...$+&>;&%-,&#&>;&%=-%#+#-,==,>>;&..+='>%#..*>,%%,=*+.$*,,=#....$.+*,'>=@$$*,''=*+...#%,>>%+..$@%=>>-%#$*>';%@$$..%>'>>,,>'&", +"+**#+$+#@#..#**#+....#%,=&*#$.$@*@+..$..$#**###@#$#**#+###$.$@@##@*%*#..+*=%@$..+*@##@#+...#**#...$....+*%*#+..#&,%@+.....#*%*#$...$$@*%@+$.#=&*#$....#*%%%*@**@"}; diff --git a/hacks/images/matrix3.xpm b/hacks/images/matrix3.xpm new file mode 100644 index 00000000..ef42f81d --- /dev/null +++ b/hacks/images/matrix3.xpm @@ -0,0 +1,692 @@ +/* XPM */ +static char * matrix3_xpm[] = { +"512 598 91 1", +" c None", +". c #020202", +"+ c #020602", +"@ c #020A02", +"# c #061606", +"$ c #071E07", +"% c #061206", +"& c #020E02", +"* c #061A06", +"= c #0A220A", +"- c #0B310E", +"; c #0E3E12", +"> c #0A260A", +", c #0E2A0E", +"' c #134A16", +") c #0E5A0E", +"! c #104616", +"~ c #124E1A", +"{ c #166A12", +"] c #127212", +"^ c #1E921A", +"/ c #168A16", +"( c #1A5E2A", +"_ c #165626", +": c #227232", +"< c #3A965A", +"[ c #268A3E", +"} c #227A37", +"| c #1E662F", +"1 c #1E6A32", +"2 c #227E3A", +"3 c #16320E", +"4 c #36822A", +"5 c #4A9E72", +"6 c #4AAA6E", +"7 c #42862A", +"8 c #4DAE7B", +"9 c #1A3612", +"0 c #224616", +"a c #264E16", +"b c #32621E", +"c c #1A3E12", +"d c #265A1A", +"e c #367622", +"f c #3E7626", +"g c #5A8636", +"h c #4A962E", +"i c #669A3E", +"j c #82AE52", +"k c #3E9222", +"l c #4AA232", +"m c #66AA3E", +"n c #6ABA3E", +"o c #82BE4A", +"p c #76AA4A", +"q c #96BE5E", +"r c #1A9E1A", +"s c #22BE22", +"t c #2AD62A", +"u c #6AEE8A", +"v c #4AEE4A", +"w c #50CE94", +"x c #26CB26", +"y c #26D226", +"z c #1EAE1E", +"A c #2ADE2A", +"B c #2AE62A", +"C c #2EEE2E", +"D c #56F24A", +"E c #66F65E", +"F c #127E12", +"G c #42EE42", +"H c #3AEE3A", +"I c #2B9F4D", +"J c #3EBA6E", +"K c #2AAA4E", +"L c #56F262", +"M c #66C29E", +"N c #68D6B2", +"O c #52BE8A", +"P c #3CAE67", +"Q c #2A9646", +"R c #6AC6AA", +"S c #6ACAA2", +"T c #C2D672", +"U c #B2D26A", +"V c #4EAA2E", +"W c #9ECE5A", +"X c #5EB632", +"Y c #62C299", +"Z c #8ACA4A", +"..............................................................................................................++@@@@@@+++....................+@@@@@@@+........................................................................................................................++@@@@@@+....................+@@@@@@@+................................................................................................................................................................................................+@@@+.......", +".............................................................................................................+@##$$$$$#%@+..................+&##$$$$#&+......................................................................................................................+&#$$$$$#%+..................+&#$$$$$#&+..............................................................................................................................................................................................+&#$#%+......", +"............................................+@&%#***%&@+...................+@@@@@@@@@+....................@##=--;;;;;;;->$%@...............%#>-;;;;;-,*&+...................+&%&&@+............................................................@&@@+.......................@%*--')))!;-=%@+..............%*-;;!!!!;-*&+.....................+&%###%@+............................................................................................................................................................@#$-;;;-=*@+...", +"............................................%**==,-->=*%@.................@%*$$$$$$$*##%&+................%$--;~'))){))!;-=*&.............&#--;)){)~!--=#@...............+&###$$**%@+........................................................@%**$*##&@....................&=,;']^^/])';,*@.............&$-;)){//]);-=#@+...................@#*==>=*#%@.........................................................................................................................................................&*>;!~))!->*@...", +"...........................................+%**===,,>**%%+..............+@&%************%@+..............@#*,;!~~))())_';-=*@............+%*=-;~({_~;-=**%+.............+&%*$**$**%@+........................................................&&#*$*#$%%+...................@*=-!:<<[_~!-,#@.............@=-;'(}[<}_-=*#@+..................@%#**>>>*%%&+.......................................................................................................................................................+%$=-!)))!-,$@...", +"..........................................+&*$>,-;;-->$$%+..............@&$$$$>$$$$$>$$*#%&@.............@#>-;'((|(||1(~!--$%+..........+&**,-;_:}2(~;->$#&@............@%*$=>>=>$$#%+......................................................+&$*>=>=**%@..................@&*>3_456<:(~;,*@............+&=;!(:786<(;,$*%+.................@&#*>---,>$##@+......................................................................................................................................................@%*-;_|1|(;-*&...", +"..........................................@*=,90abbba3,*$&+............@%#*,333333333393>$#@+............&*,cdbbeeff4febd0;=*+.........+@%>-cabfghifbdc9=$#&+.........+&%$,39c09c3,=$@.......................++@@@++.......................+&#,39c993=*%+................+&*=3;bijjifbac,*@............@&=;adfijjifc9>*#@................+%*>,9abdac3*$&+......................................................................................................................................................&*>9aefggfa;=%...", +".........................................&*=;abgijjigbc9=#@...........@%*,c0db{b_0_db:bdc3=$&+..........&%=9de47kkklllk4ebac=#........+%$>c'be7mnonphebd03=*&+.......+&%=3cd:eeee(a3=*@....................+&&*=*$*##%@+..................+%*30d:1e(d09=%+..............+&$>9cdfmqom7bd09*&............@*>9db4ioqpgbac3=%+..............@#*>;afgmiifac,*%+...................+@&%#&@+........................................................................................................................+&*,;abipnpif03#+..", +"........................................&$-~]rstuuuvws/{;-*+........+&#-;)]rsxyszrrssysz/{';$&........+%=-;{/yABCCBCACCtyz^];,+......+%,;!{/sABDvuEvBAsrF{~-$&......@#=-;)/zxBBAAs^{!-*&.................@%$,-;;;!;;;-,*&+...............@*-;)/zytAsr/{;$%+............+%>;~F^sxAvGAs/]);>*+...........@*-~F^sxGvHAsrF);>%+...........@%$-;~]IxDuvDJ/{';>$%@...............&%$>----,$&+......................................................................................................................&=-~]^sADEDtKF',@..", +"........................................&=;~FIyHDEvDAsr]~-$&........+#,;)]/zsABxszssAAysrF);-#+.......@#--!]ryBCBCBCCCBBxsrF~,%.....@#>-!)]ryAHGEuELHBxzrF);-#.....@#*-;'{/yBACBByr]!;,*&...............@#=--!!)))))~!;-=%+.............+%=-!]rsBBBtz/];,*@............&=-;]^zxABCByrF);-=%@...........+#=;)FrsACBBysrF~-=#@.........&#>-;!{/KyDDDGAz])';-,=&.............&%=>;;!;;->=%@.....................................................................................................................&=;~]rJAGLDGs])>&..", +"........................................&#=-~][6MNNOP[{!->#&........+%*-;)(F^rI^/FF/IrQ/])'-=%........+&>,;~]^rIzKzKsKzr/F(~;=@.....&*>,;!)][IKOwNwOPKQF|~;,*&.....@#$>-;~]/rrzKr/F)->*%@..............+&*=--''~___~';,=*%@.............+&*,-']/rKr/F_!-*%@............@*=-!{2QIIIQ/(;->*&+.............&%=-!(}^IIr/[]);>$&@.........&*>,-;!(1-a|75RNNR5}('-*#@........@&$-!__:[55<}1}}5554|~;-=%+.......&#*,-_1[QQQIIIIIQ[}1('-*@....+&$=-!(:}[QI68OOO66<}(_;-=&.....+%*=;;_|[[QQQ[2|~!->#&.............+@%$-;~(:f774e1_;,$%@.............@#$,;_:<865[1_;,$&@............@#>-~|}}[QQ[|~;>*%@...............&**-'(}[Q[[}|_;=*%@........+&*,;;c~(e#@+...................................................................................................................+&$>3~|}@....@#>-abe7khhlmVmmjqqjgedc9>&.....@*>;adbe47k4k77ebac,*%+...........+&#*,9a:gijqqqjgea3=#@.............@*=;0bgpqUqifdc,$&+............@*,cde7kk777ba3>#&+...............@**,0de4kh7hfb0,$%@........&*,;abbbefiqUUqi4bbbba;,#............@&$3afjjjifc,*&+...................................................................................................................@%=,;df7hhh4fd3*@...", +"........................................%*9c:kiqTTTWjl7bc>$&........&$>0d:4ijWqoikhmqTqp7eb0,#+......&*=9cde4hlVVVVmVXVVk72b',&...+&*3a14klVVVVVVVXqWWoi7bdc>#+...+&$3cde4k*&+..........&*=3;d:75jqTTWomk:03=%+...........+&*30b4iqqUWpgba3*%+...........+%=30e[llVVlke_9=*&+...............+#=3cb4kllVlked;,$@.......@%=3d1e47hlpWUUWjhkk44ed9$@..........+%$,cbgqUWqgbc,$&...................................................................................................................&*,9dehllllheac=%...", +".......................................+$-~]zxCDuuEEvAyr{;,*+.......*-!{rsxADEEGABBGuEuGsz/{;=@....+%$;~]/zsAACGHvGvGGHCCAyz/~$...%>;~FzAABCCCBCCCCGvDHtsz/{;$@...&$-~]rzxBCCBCCCCBAs/{;-$%.........@*-')FrstCGLuDvGHtzF~->&...........&=-~FzyBGDEGAs/{;,*@...........&=-~FztACBABxr]'-=@................+*-'{^stBCBCBs/);,*+.....@#,;)/zytBHHDEEEEvvBBtyz^{-#..........@$-;{IxDEEDyI{!-*@.................................................................................................................@$-'{rxAGCAtsr]~-%...", +".......................................@#;~]ryADEEEEvBs^]!-#@......+%-;]^zyBHLLvCAAHvuDHsz/{!*+.....#-;{/zsACCBGLLLLLLGCCBBs/)=+.+*,;~FstCCCBCBtyxytBAAysz/{;*+..+%=-~]rstAABACBBBCtxr]'->*&........@=-)F^syBCCAAxyAAAzF~;=%..........+%-;)FsBACCBAs/]~->#+...........@=;)FzACCCBBs/{;,#+.................@$;)FsABCCCAs/{!-*&.....+$-;)/syBHLLEEuEuELGCBxs/);*.........+#,;~{IALLLDyzF);=%+...................................................+...........................................................@#>;~]IAGvHysz/{;-*+..", +".......................................+@*-;12IOSNSS8I});,*@........@*,;{F2IPwwPI[QIOwO<2|);,%......&=,!{F^IKKJwwNuNwwwJsKr}_;%...@*>;~FIKzKrI^/2F/[QQ^2]|);=&....&*>-!(]/^IKrKrKrrr^]'-=*%@........@*=;)]}^IKIQ2}}/[/]'-**@..........+@*=;(/QIQQ[[]);-*#+............+#>-~2PJwJK[]~;=#@...................&$-!{/IJJwP[(;,=#@......&$,;)F[QPwNwNuNNuNwJI^F);,#.........&**,;~:5wwNO<1_;,$%+............................................+@+++@@&@@@@@@@@+++................................................@#$-;):5wJP[F_!->#+...", +"........................................&*=;_2g8RNNR6[:(;=*&........@#=-~(1[5OO6[2}<6M6<|_;-=@......@*,;_1}[QKKOwNNNNSw6KQ[:_-#...@#*-':[IIIQ[[21::}22}:__!->&....+&*,;_(12[[QQQQQQ[2|~->$#@........+%>9'(}}QQQ}:1111|~;>$%&...........@#>-'|[2}}:(~;,*#+.............@%=-_26OYO<:_;,$%@...................@*,3~|[8YS6<(->$&+......@%=-'(14KONNNSNNNSO5[}(~-*&........@&#>,3_|*$%@...........................................&%###%#%#%#####%##%@...............................................&#=,9_1#@........@#=3adb4impifffgpjigdc9>$&.....+&*-;d:4kimpoqWUUUWoplkkea-%...@$*3c:7hhhhhg7feef4febbac3=%....+&*,;a(be7k7h4h7<44ba;>=$%+.......@#>9abe4hik7ebbbbba-=$%%+..........@&*-cde4ebddc->%@+.............@#=9dgjWWjiea3=*&....................+&=-cbgqqUqgb;,$&+......@%*,cd:fijqUTTTTUqji4eda-*&......+@%**>3caegqWWjiba;9==**@........................................+@%$>>>=>=========***%@.............................................+&$>90dfippgba;3*&+....", +".......................................+%*30|7ijTTTUpl4d0=*&........&*>c_be4hiig4ee7iiifdc3=%@......&=3abfhlXqZZZoZWUUZnXVk4d3#...@%$3aehVVlnnnVllhkkk4eba09=%.....@*>3ad:4khllIlVllk7eda9=*&+......&*>0db4hmnmh4}ee:(ac3=$#&.........+@#>,0debdaa93,*#@..............&*>9dhoWWZifd0,$@.....................%,cabgqUWqifa3=#+......@#$,cab4hmoqTTTUZnmk4bdc,*@.....+#*=,c!a(b7mqUUqi7bdcc33=#+.....................................@%#=,333;0cc0;0c;cc;c9,>*%...........................................@%$,;de4hlnmhedc,*%.....", +"........................................#-']rxBLuEuEvts/);=%........&$3)F/rzssszrrzsyxs/{!-,#+.....+#-~]rxAGvEEGHHvLEEEGCCts^)$...&$-;{rxCCHvvDGBBCCBAysr/{'-=+....@#,;~F^sACCCCCCACCtyz/]',#@.....+*,;{/zsAGDvtyszrr^F{~;-,=@.........@#=;)F/^])';;-*&..............+*-;(^JvEELtK/{;>#....................+#-~2IyEEEEtK]~3=@......+*-;~]^zxACLEEEELGByz/]~;=&....@*--~)F^rzsxGEEEEHssr^F])!,#....................................@*-;~){]{/^^////////FF]{);=@.........................................@*>;)FzsxABCAs/]_;$%.....", +".......................................+*-;_^stDEEELGAs/)-=&.........%,'{F^/rrr/FF/rzz^]);-*@+.....@*-~{rsAAGLLvCBCHLLLGCCAsF'*+..@#,;)/stBBHvGHCCCCCCBsz/{);>%....@#=-!{/stCCCCCACBBAxz/]!-$&....+@*>;{/zsAvLDBxsszr//F]~!-=#.........+&=-!]]])!;-$%++..............@*-;)^xGEEuAs/);-&....................@$-'{IxGEEDAz]~-#+.......#=;~]^zyBHvLEuLGCBxz^]~;$@....%--!{/IzsJyAvEuELGAtyssr/);*...................................+#-;']/rKzzzsssKszszszzK/])-#.........................................%*-;)/sABCCBys/)!-$+.....", +"........................................+*-;~:[PSNNOP}|!-=#@.........+&$-;;;~!!;;;;!'~'-,$#@.......@%>-'(][QPwwJKKKJwwOIQ}F{;>@....+*>-~{F2[QPPKKKKKJJKI/})!-*@....+&*=,;)FQrKKKzKzrr/F{~;>*%+....++%*=;~:2-;([OwNO<:~;=*@....................+%>-!(-;_]QPOJ86PPJJPQ}{);,#.....&$-;|[68OJOYSNNNNNOOO665[_-*...................................+&=-!1<588866666O6666668<}_,%.........................................&*=;~]/IrIQQ2{!-=*@......", +"........................................+&*=;_:==,>====>,,*$%&+........@%*>;~(|[5OO6<[[-ab5RRRRRNSNNSNNNRNNRM5b9#....................................#=3af6MMNMNNRNNMNRNNNRRMg(-#.........................................&$,;_:[IIQ2:(;-$#&+......", +"........................................+&*>30biqUUjgbc9=*@.............@&*##**$#$*$#$#%@..........@%$=9cdbgpqqmg7giqqjgbbac,%+.....%*>>30dbef7hhlmmoZoik7e09#.....+@#$=90:7hhVmmlkh4edac-=#@......+&$=cabfiqUUjmll74eeeeb_c=#...............+++++...................+&*,9agpWWqgb;,>#@...................+@#*,;dgjWWjib;,$&.......+@#*,cabijqpg7fgjqjibdac=&+...+%>3agjqTTTTTTTTTTTTTTTTUifc#...................................+#>;dgjTTTTTTTTTTTTTTTTTUibc&........................................+#=30b4hhkkeba-=#@@.......", +".........................................@$=3abiqUUqib03>#&..............+@@@&&&%&&&%&&@...........&*,9abe7kpqWjlkipqWoi7e|a3$+....+&*=3c0|e47klVVXXZZoXVk7ea>@.....&*,3cdeklVmXXmVlkke|dc3=%......@#=90d:7iqWWZonXlhk7kk71a9#+......................................+%$-0bgjWUWifa9>*&+...................%*,90eioWUqibc3*%........@#>-0dfioZp57kipWqi4bac>*+...@#>!cgjTTTTTTTTTTTTTTTTTTjf0*...............+@%%%%%@+...........+%30agqTTTTTTTTTTTTTTTTTTjb0#.......................................@#$9a14kVVVk4(c3$&@........", +"........................................+%=;~FIADEDDyQ);-*@..................+@@@@@@@@+...........&=-!{^xtvDEEEEvGHDuEDHtyz^)-%...+&=-;)F^sxxxtACCCHGLGHCBAs/!#....@$,~{FzsABCHCHCCCCtxszF);$+....+#,;)FrsxHvvvDvvDGGCHABts/'>@.....................................+&*-!{ryuEEEtKF)'-$@..................+$-;)FrtLEELAK{!-$@......+%=3!{^ztvvHxssyHvGAs/]~3>@...&=30|.............+&*>--;-->$%@+........+#,~e5wuuuuuuuuuuEuuuuuuSX[0$...............+&##**%&+..............+$-!{^sAACCCAs/)!-*@........", +".........................................&--'{rwvLLGy/{;>#+......................+...............+%>;)FKGLuEEuEuELEEEEEGCAyr);%...+*=-~]rzxAAyAAytBACCCBCCBs/)$....&>;{FrsxBBCBGBCCCBCBtsr]!,%....&*,;)/syBACHHvLLLELLHCBBs/),@......................................&=-;)[stvvDAs^{!-=#+.................+*-!)FIyGLLDxr{'-$&.......&$-~{/rsyAyzzrzxAxsr/{~-=&...+#,;~]rsXxwvLEEEEEEGtxxss^]!*+...........+#*,;!~~!;--=*@.........&>;~FrVsXsXxxXxXxxxXsssz/{;#..............@#*=>-,-=#@.............&$;)]zAACCBByzF);,#@........", +".........................................+%*-;|QJYw6[(;>#@........................................&*>;(<8NNNSNNNNNNNNNwJKI/|;=&...+%$=-~]//^^/////^[QIKKKKrF'-#....+*=;~{]F/QIJJKKKzKzIr/|!-*@....@#=-'1/QIIKKJJwwwNNNwKKr/(;*.......................................+&$,;_25PJPI[]~-,$&+.................+&*,;(2;~(:]11_~_)|2](~;->#@.....+%=,-c~(||e[6wNSR542:b(a!->&...........+&#$>-!~)~'-,*#&..........@$>3!!))()d|((|(dd)0_!';-%+.............@&**>=,==*$%+............&*>;~F^IrrQ/F(;-*#@.........", +"..........................................@#*-cb<55<1;,*%+........................................+%*-0:58OMRSRRRwMMRO85[}|~-=+...+&*>;_1}[Q<<<[[}[[Q5KIIQ[(!,&....+&*-;!_(|}[QKIIQQQQQ[}|;,$@....@#$-'_}[QQQQIPJYORNSO5[2:~-#+......................................+&%*,!([#&@.................@#$-0(1[--c_(:5RNSO<:d~!;->=%+...........@&#=-'(|1|_!->*@..........+%*=>,3,-3c;c-33----,,>=*%+............+&$=,-;;;-,*#&...........+&*=-!|[QQ}}}(~-$#@..........", +"..........................................@#*>cabebb0->*&.........................................+%*,;dfg5i5mm8mm8m5ig7:da9=#+...@%*,cd47>,,-,,==>,,3,=*$#%+........+&**>,39afiqUUjiba09-=$%+...........+&*$,9~bee:bd;,*%+..........+&***>=>=>=,=>===>=>*$*#@.............@%>ccadbda;,$%+.........+&#>=cae4hhfebd0,*%+..........", +"..........................................+%$,-0dbbd93=$&..........................................@=,3df7hlVVXXXVmVlVh4ba;3=%....+*>30ekVlXoZWommXnZZZmVh4b0,@.....@&**-99_b4hVVVkkkcd4lVVVllhhhlmoWUol7f1d9$+.......................................@#$9'b4klllk7eac=$&................+%=3017klllk7:a9>#@...........&&#*$>$*$$#$*=$$*%&+..........+&#*,90dfiqUUqifd;3=$&@............@*$-9d:kkkk4bac>$&...........@&#$*$*$*$***$*$#*##&@@+............+#=;abe474ed9=*%+........+#>30~ehmpl7eda9=$&+..........", +".........................................+@*,;_{/^^2{'3,#.........................................+#=c_}zxtAHHCCCCCCCCts^F';>#....+$-'{^yCCCvLvvvGGvGvGBtxrF',%.....+&*>;')]^stCACAyAACBAs/)3%...+#-;{/sCCCBCBCBBCCvLEDHysz^];&.......................................@#,'{^stAACCAs/{;-=&..............+%>;~FzAACCBts^]!-$&...........@&##$>,=*#&##$=*%&+............@#$3!|[KwEEEvAKF);->%+...........+$-;)]ryBHHBAs/{;-#+...........+@%%#%##*=#%#&&&&#%&..............+%-;)FrsABAsr{!-$&.......&=-~]/rsALGtJ/F);-*%...........", +"..........................................@*-;'FQzr/{!;,%+.........................................%,;'FryACBHBCCCBCBAyzF)'-=&+....%=;)^sACCBHGLLLLLGCAtzrF)',@.......@#-;)]^sAACBAABCABAz/);*+..@#>;)/stBCCCCCCCBGGLLGHCAsr{;%........................................%=;)FzyBCACAs/{!-=*&.............&=-;)/zACAABAz/);>#&.............+@&%%%&&@.@%%%+...............@*-;)FztLELDxr{~-=#@............&$;~]^sAvLvHts/);,=&..............+.+.+@+++..+.+++...............+*-!{/zxACBAzF~;=%.......#=;~FrzxtGvAz/{~;$%............", +"..........................................+&*-;|[I<[(-=*@..........................................&*>-'{F[IKPKKKKzKrQ/]'->$%+.....@%=-)]F2/QIKOwNNwPQ[])';=*&.........+#=-!)F^KzKrrrrKr/F'->@....+#=;)F^KKKJJwwOwOOOOJJO6P2~-&.........................................&*-')F/rIzI/{~;>#@@............+@#=-!(FrKz^//]'->*@...................+.........................+#>-!1-~1[6wNSJI2(;,$&+..............................................@*-!{FQKJJP[_->*@.......&*>;~:2QIPI<:~;,>%+............", +"...........................................@#=c15O8<|;>#@..........................................+%*-;_|2}QIIKIIIQ[}|_;-*&+.......@$=-;~_((:[8RNN6<:(!-=**%@..........+#*=;(2QIIIQQQ[[2(;-*@....+@*>;(}[<5YRMMNMMO6P6YRR62a,&.........................................+*=-'(:2QK<[1~;-*#+............+%*,;~|}<<<[:_~;,*&+..............................................@*>9_78YR840->$&+.............@#=-~1[56O852(!-*&+...............................................+#>;(2<8YR6ea-=%@.......@#=-_:2[[<[:(;,*&+.............", +"...........................................@#=0bijjib3$%@..........................................+%*>9abe47hlllhh<7ebd9>$&+.......+%*=-339cafiqqqpfd0->$&@............+%$*3_e47477744ebd3=$@....+&*=9a:47ijUUqTqqjiimjqqjg0-+..........................................&*,9cdfgjpieda;>#@............+%$>;dbgppi7ba;,$%@...............................................@#=3agiqjifc3*#@.............@%#=9af7giig7ba3>#&.................................................#=9aegjqqpfa,*%@.......@*=cdf77h77ba;>*&+.............", +"...........................................@#>9agggfa9*#&..........................................@#$3c(e4klVVVVlVVlkea9,*&........+@&%#*>>9abhmooifa3>*%&.............+%#>3cdee44ee:bbd03$%@.....@#>,0dbfggiijjjiih4ggjggb3=&..........................................@#=-caemoom7eda3*@............&#,cdb7loZp7ba9,*%+...............................................+%$,9dggggd0,$&+.............+&*-c|4ll5hhfd09=*@+................................................%=9cbggiggb0,$%+.......&$,0|7klllke_3=$@..............", +"...........................................&$30ab1bd09>#@..........................................+$-'{/zxtCCCCCCCBBtzF~-=#........@@@&#$--!{/xtHCxK]~-=#@.............+%$,;!)]F///F]()~'->#@.....@#>-!(]}[4hhhkhkQ^^Ik7fbd0,@..........................................@*,;!{rtvvtJz^])-%...........+&=;{/zsADLGK^{!->#@...............................................+%$30_|::(a;-$&+.............%=-'{rxCBBAxzF);-=@.................................................%>;~{:474bdc->#+......+%-!{rxAAAAs/{;-*@..............", +"............................................%$-;;'';--$&...........................................+&>;)/rsAACCCCCABByzF~-=@.............+#>;'FzAAxs^]~-=%................%*,;!~'))))~';;->#&+......@#,;;~))){){{]{F]{){(__;,*@..........................................+%=-'(^JGGAsr/{!>#+...........@*;)F^syBwAzF);-#&+................................................+*,-;!'~;;-$%+..............@*,;]rtABxsz^]!;>%+.................................................+#-;!))))~;--#+........*-;{rsyByszF);>#+..............", +".............................................+%*====%&+..............................................%=-~{]FQrKKrIrr^F|'-*&+..............@#=-!{//2]';,$#@.................+&%*=====,,=***@+..........@#$>,--------;-,-,-=,=#+............................................+%*>;~1241(~'-,%+.............@=-;!(14}:~;,#&+...................................................+&#*>=>*#&@.................&*=;)FFFF1)!;>*%+....................................................&#$>-,,==#&+.........&=,;)]FFF{);->*@...............", +"..............................................+&&%%&@+...............................................+#-;;~(|}}2}221(~!-**@................@**-'_(_!->#&+....................@&#*&%%&&%#&+.............+@&##*****==*=>***$#&+..............................................+@**-99'c-->$%&+.............+@*=,,-cc3-=#&+......................................................+&&#%&@+.................+@#>>;_(_!--,$%%+......................................................+&&&%##&@...........@#=-;_((_!-->%@+...............", +"................................................+..+.................................................+@#,-3cc_db_d_0!;-,*@+.................@#=-9;3-=$%+......................++++.+@@++.................++&%%%%%%#%%%&&@@@+................................................+%**>>,,=**%@+..............+@&#*$>>>**%%@..........................................................+@+....................@&*=3ccc9,>*#@+.........................................................+++@++............+%*39ca_cc,=*&.................", +"......................................................................................................+&**=,,3993,>>==>*%&..................+@%*>=>**%&+..................................................++@@@@@@+++@@.......................................................&***$*#%&+.................+%%#%#%%*%&@+.................................................................................+%*=-9c->=*%@+............................................................................+&#>3999c,,*#&.................", +"........................................................................................................&#*$$>>$#&&@%#*#@.....................+%***#&@+.......................................................................................................................+&%%#%&@+...................@@&@%&&@++....................................................................................@&*$>>>*%#&..............................................................................+@&#$>>==**%@+.................", +"............................................................................................................++++......+...........................+......................................................................................................................................................................................................................................................+.++++++..................................................................................+.+++++.+....................", +"................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................", +"................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................", +".............++@@@++..........................................................++@@&@@++....................+@@&&&&&@@@@@+.......................+@@@@@++...................++@&&&%@@@@++........................+@@@@@++................++@@&&&&&&&&&@@++....................+@@&&@@@++....................+@@@@@@@@+...........................................................................................................................................................................................................", +"..........+&&#*====####@+.................+@%#######@+...................+@####==,=>=*##&+...............+&#*$===>===**%&@.....................@&**$*$*#%@+............+@###==>>,,,>>=*##%@+.................+@#****===###&@........+@###==>,,,,,=,,=>=*#&+...............+@#*====>$**&&@.................@%%**$>$=**#&++................................................................................................................................................................................++@@@@++...............", +".........@#=>-;!~~)!!;-,$*%@+..........@%*$>-;;;!;;;>$#&@..............+&#>-;;;)){)~!;;-,$%@+..........+@$>-;!){{))~!;;-,=#+.................+&*,-;;;;;--$#@.........@#$,-;!)){)))))))!;;-$#@..............+&$=-;;!!~))!;--=%+....+&$>;;!')){{{{))){)~!!;,=%@..........+%*$-;;!)))~';;->=#&+............+%$,-;;!~~~!;--$$%@+...........................................................................................................................................................................+@#$=>>,>$****&+.........", +".......&%#*-;!))]F]])~!;--=*@.........%#=-;;'))))()~';>*&@............@#*,-;'){]//F]{)'!--=*%@.......+&#=,-;'{F//^F]{)~;;->$%+..............@%=--!~))))';-=*&.......@#=;;~)]F///////F]{)';-=%............@%#=,;;!)){]]]]));-=&....@#>;!)]FFFF////F///]{)~!-=*&........@#$--;~)]F/F]{)~';->*%@..........+#*,;!))]]]]))!;--,*&.........................................................................................................................................................................@&#*=---;-;-;---=#&........", +"......+&#*$>;;~{]1]1(~;;,>**@+......+@%$*=-;!))(({{);,$%&+............@**=--~){]}/}]|)~;-,>$#@.......@&#*>-;!)]1F}F:{();-,=*#@..............&#$,;!~)~)~!;,*&@......+&$=-;')(F}:}11F:]|_)~;-*&...........+&#*>>-;!)(]F1]()~;-*&...+&$=-')({:F}F}F}F}F}]_)~;-*#@......+@&#*>-;!~(]1F1{)!;-,>$#&.........+&**>-!)({{]|)~!;-=>#%+.......................................................................................................................................................................+&&*$>,----;--->=>*#+.......", +"......@%**--;(_:}[}211_!-=>$#+......+&**,-;!((1}2}}(~3=#&+...........@#$>--!_|}}[[[}}2(~;-,=*@.......+%*>-;;_|}}[[[}}:(!;-,=*&.............@#*=-'_((111(!->$&+.....@%*>;!((}}[[}[[[[22:1(!->%+..........@%*$=-;'_(}}[[}21(!-=@....&*>;_(|}}[[[[}[}[[}}:1(!->#+......+&%*,-;;_|:}2}21(_';--=*&+........+%*>-;_(}}2}:11_'-,=*#@......................................................................................................................................................................++%#*=,;;;!!!!;;3-=$*#@......", +".....+&*>,cabff77hk77ebba9,=*@......&#>3;adbeggghigeb;,*%+..........+&*=9cabf7ghhhhhhg7bda;,>&......+&$=3cabf7g7h4hh4g7bda9,=&.............@$>-cbegggg7eb;,=&+....+&#=,;abfghhhhhh7k77eeba-=*+..........@*=3;0befgghhh77fba;>%....&*3cbef77k7hhhh7hh774ebd9=*@.....+&#>,;adbefgkh7k74fbba;3=*@........&$,cabff74k74febba09=*&........................................................................................+..................................................+@++.......................+@#$,3cdbbebeebbb0;,=*&+.....", +"....+&=-cabegmmmVVVVmpm7ebac>#.....+%=-'b47kmmoononm7d9>#&..........%*>cd:47lmnmVlVVXnml7eba,#+.....%*,0(e77lpmnVVVmXmmh7eb03$+...........+#=cabgijjjjji7b9>*&....@%$-0de7lpnXlVVlVVVlkk4b0,*&.........@#>9abgipppoonXVVk4b0,#+..+*,c{4hIhlVVVhVVVlVVVllkea9=&.....&#>3abe4hmmmmVVVmpml7eedc>%.......@#=9dgiimlVVVlVlkk7}d0,#+....................................................................................+@%%#%%@+.........................................+@&%*%#&@+.....................&#>90bgippjjppppi7bac,>#+....", +"...+%>;)FrzyHvvvHCHHHDGtysrF~-&....&=;)/sABHvEuEuEuvs^);,*+.......+@=-~]zytHGDvvHCHGvvvHBAsr{-%....+$-)FzyBBvDLDGCHGDDvHAys/)-%..........+#-;{^swEEuEEEDy^{;-%....#=-)]rstHDEDHCCCBCBCCAsr{!-%.......+&$-~{^syuuEvEvDGCCBy^]!=+.+%-']zxCCCCCCCCBCCCBCBCCts/);=+...@*-!]rsAAHGDGHCHHHvvGCtsr]!>.....+%*-'{rxDvGCCCCBCCCCBtz]',&.................................................................................@%*$>----->$*&.....................................&#*=---;-->*#@+.................+#-!{/zxDuuuuEuDuHtsrF);,#+...", +"...@#-;)/zstHDLvBCBCGLDCtxz/);#...+&=;)ryBCHDEEuEEEuA/{;,*@.......+#=;)/sACBGLLGCBCHDLvHCAyr];*....@*;'/sABHGLLvHCCvLLGCCBsr(;#..........@$;~]rstuEEEELDA/{!-#+..+#,;)/zsyHLLvGBCCCCCCAAxr{;-%.......@*,;)FKsHEEEuLLLGCCBxr]!$+..&>!]ryBCCCCCCCCCCCCCCBCBs/);>&..+%=-)FzyACGvLvHCCCvDLGCCAz/'=@....@#,;'FIAGvvCCBCCBCCBCBs/);*...............+@&&&@+............................+@%%&@+.....................+&##,--;!~~!!;->%..........@&&&&&&&&&&&&&&&&@........&#=--;!'!~!;-,=##&...............&$-!{^sADEEEuEuELEAsz/]~-=%...", +"...&*=-!(F[QPJwJJKKJJwOPI/F|;>#....+#=;)2/IPOSNSNSNOQ|!-*&+........&*=;)F^IKJwwJPKKJJwwPKI^]'-&....@%>-)F^IKJOwJPKPJwwOPKr^]!-&..........&*>-~:[6YNSNNwO<1;,=@....&*,;~][QPOwOPKKKKKzrr^F);,*&......+&*$-!)2Q6MNNNNwwJKI^F);,%...+&=;{FrIKQKKKKKKKKJJsKKr});>&....@*>;)F[rIJJwJJKKJJwwJKIrF(;*.....&#=-;(25wwJKKKKKzKsKKK/(!-#..............+@%###%&@..........................+@&&##%&+..................+@&%**=--;!!~'';->#.........+@&&%%%%%%##%%%%%%&+.......@%*,--!'~'!;-,=**#@+.............%*,-!(25OwNNNNNSwOP[2]);-*&...", +"..+&*>-'(}[QQ66;_1:[<88RNNS67(;-=&.........&#=-_}[Q<5665Q[[Q586PIQ[1~-%....@%*-'_}[Q<55<[[[%.........+&*>;~|2<6ORMRS8<(;=*&....@$=-__1}<6JPI[[2[[[[}|(!-=#@.......@#>-~:7<88OOO659~(}<66,-;!_{2ee1_c-$+.......+&%%###$$$$$$$$$$###%@......@#>-ab1e:1(~!-->**#&@+..........+&*>-!(1Q5O866868O8<[21(',*@...", +"...&*,;de7khhh77ebef4ghhhhhed9%.....@**3c~abffgjqUWjgbc-*&.........@$=-aehhhh77feebe77ihlhhea3%....@#*,0df474eeebeef7hllkh4ba,&.........@#=,0behhihimjZqgb9=*%....@*=3abf4hhik7eeeeee:bba;->*@.......%*,;agpjjmiig44febda93=#&....&*=3c0a_dddbbbee7hklkh4e03*@....@*=3de7hhlkh4fef47hhilkh4b;%....@#*-cdbehhl4eeebe4ipqZpiba9#...........+@%$*>,,>=$*#@......................@&$*==>,=$#&+..............+&#$==-9cabfgjjjpgd9,@......+@&$$>>======,=====**$*&.....@#,cgipjpg7bbacc,,=$%@+..........&*,;abf7hihgffghhlihh7e09>%...", +"...&*9a|kVVVlhk4eebe4khVVVlkbc$+....@#*=,90adffpqUWqgb03=%.........@*>3d4klhk4f1b|eekhllVll4b;#....+%$,cdef4eebee1e7hllVVVl4d3#........+&*,;aehlVVV6XoZqibc3>&+..+@$,cde7kllVlhk444444e|d!9=$@......%#30dfioZoV5l*@....@%$=,3c090!a(b14klVVVlkea9=%....%$30_7VVVVVhk4ee4khlVVVlke0>+...@*,0de47lVlk4e1ee7loWWqm7d9*+..........@*=33aadd09,=#@....................&*=39cadda93*#@...........+%*==3c'd(147hmoWZjifa9#.....@&#,3c0c0aadadadaaaa0c9,$&....&*3agqqZnXlk4e:bdcc,=$#@.........&=3ade4kVVh7fe4klVlVVl71a,*+..", +"..+$-'FrtCBCBBxszrrzstBBCBByz{,+.....%#--!_|/QsGLEuDyI{;-#+.......+&=-!{rsxszzrrrrzstACCCCCxr(>....+#>;)]//rzrzrrzsxAHHHCCAs^)=.......&*=-~]rsAHHBCBHvLDAK];-#+..+&,;)/zyAHGGGGGGHHHAAysrF);-%.....&>;)FQxGuLGGBCBAtxsz/F{!->%....+&*=--;;!'){F^rxtBCCABxr{'-*+..@$-;{rsCCBCCAtxsssxCACCCAyz];&...#-'{^zxtCCCtsszzssCvEEvts^(-.........+%$-~{/rxxsz/~;,*@.................@#>;~]/rsyys/);-*@........+%*--~)]/rsyyAACHvGGHsrF!*....@*-;)F/rrrzzzsszszzzzr/F{;$+...&=c1KAGGGCCBHtAAsrF{!;->#@......@#-~]^zstACtxsssACCCCBCAr]',@..", +"..+*;~]zyCCCBBysrrrrzyABCCCxr{-+......@#--!){^KtLLELxr)!-=&........&$-;'{F////^^//rsABCCCCAyr)=+...+@#-;)){]F/^/rzsAGvGCCABs/)=+......&=-!)/ztvvGCBBCGLLtz]~-=@...#=;)/zsACLELELLLLLGHAxz/{;-#....@#-']^zxHvLvBCBCCBAyzr/]';,#.....+@**>-;-;''{/rsACAABts^)!,#...+#-'{/sBCCCACAysssAACCCCCtz];%..+#-!]rzyABBBAszzrsstGLELHs/{=@........+*-!{/ztHLLtK]'-*#.................@$-;]/sxGGDAK]!-,%......+@%#-;!)FrsxBABCCCCAAysrF)-#...&*=-!]rsyAAyyAAABAAAAtAsz/)-%...@=-!{^zsyBCCLLLvAxrF)!;--=&+....@*-!]/rzyAAAsszsytBBCCCxzF'>&..", +"..+&=-!][KzKI^/]_)({]F^IKzK^|;*........+%*=-'(25SwwOQ|;-*%+........+@#$=--;;;;!'~){F^IzKKKr2(;*......@%*=,--;~)(|12IJwwJKK^F)-%.......&*>-!(2KOwJIQQIJwO<1!-=&....@*>;)][IPwwNNNNuNNwJIQF(!-*&....+&=;'{2[PwwJKKIrKrQ/2()!->*&.......+&&#$**>-;~{FrKzr^FF~;=$+....@*>;)FQrKKKrQ/FF/^rKzKIr^1!$+..+&*-!{F/rIKK^2]1112IOwwO52(;*..........%$-'{[#@..................%=-'|[POwwO4_-=*&.....+@&**=--!{F[rKzKzKKI^}}1_;>%+...+%*>-)F//rrrrrrrKrr^rrrQ/(;=@....&==-c(]}QKJwNNwJQ}{~;;,=$%+....+&#=;~)]FF//}]]2/^rKKKK^{~-#...", +"...&$-!([QIIQ[|(~';_(|}[IIQ2(;*+........@%*-9_1,,;;'(|}QQIIIQ1~-%......+&%#*==-;'_(11<6OOPIQ[|!-%......+&$,-'(|<6O8<}}[5O8<1'-*%+...@%*-;(1[6MNSNNSNNNY6Q[}(;-*&.....&*-'_|[@+....@%*-;|[[QQQQ[}1:12[QQQQ[}_;*....&*,-_(}}QIQ}:|((1:<6RSO<:~;*+........+@*=;(2--;!(1}QIIKIIQ[}((';>*@....@%$=-_:[QQQQQQQQQQQQQ[Q[}(!,%....+&*=-;~1}Q8YNNR8<}((~;-,=*%....+&#>=;!_(1||((((:2[QIIQ2(;>%+..", +"..+&*3cb7hkhk4ba!ccadb44hhk4d;#.........+&#=30biqWWjgdc,*@...........+@%%#*$=>,;aab17khlhh4d9=&.......+&&%*=,;abffgiqqomk7fd9=&......@%*39abfipomh77gpqjib09=&....@%*,;abeioqWUUUqWqopih7fa;=#....+%=3abb7pqqomikhkhk77fbd;,*@...........@&%$*3cde75h7b|a;=$@.....+#$3cb47khikiggeggiklkh7e03#....&*,;abe4hkh7bbbbbfijWWqifa3*.........+&*,cdfijZqpga9>$@.................+&*-0bfijZqpea3*&+.....@#*=9aadbf77hhhhhh7fbaa;9=#+....@#>-9df7,9ae7ijqqqpg4febba0,=#+....@&*>99aadbbb(bbe77khhk4dc=&...", +"..+*=9_e#+...........+@##$>>-ca|e4hmnnVlk4b0=&.......+@%$=-9dfgijjqWUZmlk4ba3%......&*-;be7klmmmh7klnZqiedc,#....@%$30db4hmMnppjoonZXopmib09#+...+#=c(e7hmZWZooonmVlmmpigd9,%..........+@&#*,c_b7mnmhfda3=*@.....@#>9~b4khmnooojjjjoomlk4ed9*+...@*>0d:4hmnnk7ee47hpZUTqpgdc*+........+%>3ab7hXnnm7d9=%&.................+%*3a14lnnnm7a9>$@.....&*>;de77hmpXmVVVkk41d0c9=*&+....@*=9deklVVVVVVVVVVVVVVVVk4d9#......@#$=900e7ipppmVVimiigedc>@.....@#=,9c0_d1ee4hlmnXVVh4bc3#...", +"..&=;~/ztCCCAAsr/F]/zstCBCBxzF,+.........&>-_:IAEEEvyQ{;-$@............+%*=-;~{^zyAAvvvAAszF);&........&*>-~]rsHuuuuEEvGtysrF'$....+#>-)]zyBACCCBBAAAGLDts/]!>@...&*,;)F/zxBGHtAxtHBGLLDDtKF',&...%-!{^sxCGDEEELLDGHHGDvvyK]!=+.........@&#>;~{/zxGvvtz/{;-=&.....&>;)]^zxtGuEuuuEEuEDGHxxz^(>+...+=;{/zxAvDDHysyyBBGEEEuDs^(-.........&#-']rsACHHyr]'-=%+................@*-!]rsABHHxK]~-=@....+*;~FzxCAHGvDHBCBxs^F{!;;-$@.....&,;)/ztCCCCBCCCBCBCCCBCCBs^(>......@%>,;~{FrssAAHHHHDvDHxz/~$.....+%=-;!)]/zsxttGDDGHCts/)-*+..", +"..@=;'FzACCCCtsrF]]/zsABCCBAr{,+.........&=;)FKxLLELyr)!-=%.............&*>-~)/rxABHGvvAsz/]'>&.......+@*,;~]rJxuuuuELvAAxsrF)=+...&$-')/sACCCBCCAAtBGLLHsr]);%...@*=;!)F^stAxszsyxCCGLLDGzF)-#...&-;{rsAAGLELLvvGHCHvLLEtz]'>+.........+%>-;)F/syHGGyz]);-#+....+%>;)FzsABHGvDLuDLLLGHAyyz^{-+...+%;)FzsAHGGHtAABCHvEEuuGs^),@........+*>;)FzstAts/)!-*&+................+%=;)/zsAAxs/);-#@....+=;)FsACCHLLLGCBBsr/]~';-=#+....+#,;)FsAACBCCBCCCCCCBCCCCBxr)=+.....+%*=-;']/rssxACCGLLLGAs/)=+.....+%>-;)]/zxBCCGGGACAyr]'-*...", +"..+%>-']QKKKr[F|_;'_]/QzKKK/:!*..........@%=-!:5wNNOQ|'->#@.............@%=,;~:[6OOJ8P<[1)'-,#........+@&#>-;_:4h5lPPJPKIQ/})-%....+#>-!:QJwOJJzKrIIKOww6[})!-&....@&$=-;'){]:|(1]F[IJwww6}(;,&..+@=>;)F[IPwwO6PPIQIKOwww5[_;*...........@%>-!(:}QPPI}(;-=*&......@*,;)}^IIKPJ66P6P6JJPKr^/|;$.....@=-')12IPJOJJJJPJJwNNR5}(;*.........+@%>-;~){{{)!->#@+...................&=-;~){]{)!-=#@.....+%-;)/IKKJwwwPK^/F|';-=$%&+......@*=;)F^IrKKKKKzKKzKKKKzIr2);%.......+&%$>-;_(]2/QKJOwNwOI2{;%.......+%*=-'([IJJJ6PPQ[F{);,*&...", +"...&*-'|[QII[}1_;-;__:}QIIQ2(;*+.........@$*-0(%@.........+%#*==9'_b124<%...@%>,_(}[6YM6<[}[22<6YSY51~;$+..........+%*-'(:}[Q<[1!-=#&+......@#>;_1[QQ$#&+....................@&*=------>*#@+......&=;~1QIKPOYO6[}}|~;;==*%@.......@#>-!(2[Q[QQQIQIIQQQQQQQ[:~-#........+&#*=-;'~|:[IPOSNS8<:_-%........@%#=-_28YRO6<}|(~;,>*&+...", +"..+%*,cd4hhlk4bbaccad:77hlh4b;#..........@$=30bgqWWjgd;,$%@............@#*=9abfiqTUqigba;,*$%@.......+&%*$$>=,90abbe7hhllkhea-#.....&$-cbiqUqomhhhhlmjqqpkfba9%....+@%*$=>,,,,-39aabfiqWqp7d0,&..+&$>90bfgmqqjffbfbf7pqWqpfd9=@..........@#*3abe77h47bc9$*&......+@*=3dekhlhhhhefff7hhlllk7bc$+....@&#$-cdfhiqTTTqpmnqWWqifa;#..........++&%*$>>==**#&+.....................+@%*$>>=*=$$%@......+&=cae4lVnoqomg4fbbc;,$#&@.......@*,cabf7khhhhhhhhhhkhhhk4ea3#.......+@&$*=3cadbe7hmoWTUjiea3%........+%$>3agjUUqi7bdcc,=*&+....", +"..+#=9~ekVVVlk4:dd(bb4kVVVVk|0*+.........@*>3aeiqWWqiba9=$&+..........+#*-c_b7ijqTUqm71dc3>*&@.......+%*>=,3-3c0dbe4kVVVVVl7b9%....+#>caepqUWZXXVVVVXZWWolh7b0*....+%*>,,3--3,-90_bbhpZWWpgba,%...&*-0(e4lpWqjif4eefhpZWZpgb03&..........&*30(47khllk:a3=#@.......%*30(7VVXVVVhk444klVVlVVkea,@....+&#=,cd4kmqTTTZnXXZWWZi7d9*+..........+@%#*=,>=>$#&@.....................+&%#$==>>$*%@+.......#>cd4hVVXZZoXlh74:ba;3>*%+......&*3cbeQllllVVVVVVVVVlVVlh4d9%.......+&*=,90dbe44hVXoWUWoi4d9#........@#*,9bgqWWZp7edc-,$%@.....", +"..&=;)FztCBCAAszr/^rzxACBCBtz],+........+#-;(FKtEEELtK/);=#&.........+%-!)]rstGLLELGtsrF);->#@......%=-;)){))~)]//zyACBCCBBs^{=...+%=;{^KtEELvCCBCCCGLEEvHByz]-...+%>;!)({~~~'!~{/rzyGEEEvyrF!*...%-;)^sxAvEvvtsssssyGEEEHsr];%.........@$-~FzxACCCAyr]~;=#......+*-~]ryCBCCCBAyssstCCCCCCBzF;&....@%$-;)/zyAGDEEEGHvLEELHK^(>+..........+&#>,-;---=$*@....................+&#$=,---;-,=@........#;)FzxABHGvGGHHBAyzr]{!;>*&.....%,;)/stACCCBCBCCBCCCCBCCBsr(>......+*=-')F/zytHAHBHGvDGGxzF!*........@=-;(^yGvDDCsrF~;-=%+.....", +"..&>-~FzyCCCCByzr^^rzytCCCCyz{,+.......@#=-!{/sALLEGAs/);->*&.......@#-!)F/KAGvGGHHBys^]);-,%+.....+#>;)]//^]{{]/^zsxBCBCCAy/)=+..+#,!{^sABHHCCCCCCCGLELGCBtsF-@..%>-!{F//F))~~){/rKxGLLLDxz]'*..+%>!)/zyBHLvGyszzssyGLLuGyr];#.........&>-)FzABAACBxr]'-#@.......*-!{rxBCCCCBAxsssyBCCBCCtz];&....+%#>-!{^zsAtHACBCCGLLDts/)=+..........+%**>--;--,*#%+....................&#*>---;---=%........@=;)FrzsxACCvGLvHBBsrF{~;-=%....%=;)/zACCCACCCCCCCCCCCCCBx^(=+....&#=;;)]ryAGLLGHCCBBtssr/)-%........+%-;)}sAHHAxs/]~->%+......", +"..+#=-~]QKKKK/[F|{(]F2/IKKK/]!*......+@&%*,-!_25wNNO<1(;-=*%@......@&%=;~(][8wwJPII[2]~;-,**@......@#*-!):]|(~'))(]F/rIzKKr[);#....@#,;_][IKKJKJJJJsJwwwJPK/F)=...&*>;~{]|(~'';!'(1:Q6SNS8[|!-#...+#>;):2IPwYPQ}2F:}Q6wNw6[|'=+.........&*=;)F^rKKrQF(;=$&+.......&=-;(^IzKKrr//FFFF/IzKKKr:'=......+&$>,;~1:22[[Q^QPwwww5}~-%...........+&$**=>=,>$*%&+....................@%#$>>,>>=$$%+........%=-;!)(]2QIOwwwwKK^])~;-,*&....&$=-']^zKzKzKzKKKKKKKzKrI/);%....+%*=,-!(FQPONNNJPI[2]_~;;-*+........+@*,;_:QIII2{!;,*%+.......", +"..+@>,;(}QIIQ[}:1((_:22QQIQ2_-#+......@%$>,-0_15YSS8<1_;->$*&+.....+&$>-~(|}5YR6>$&+.....@#>-c(|:1(~_~__(1:[QQKIQ2~-%....+%*,c_:[QIIQKIPKPPOSROI[[1'$+..@*=-__|:1(~~~___(1[8YNR8}(;=@....&=-!(145YY5}1(|(:48YSY5e_;*+........+@*>3!|[[QQ[2:~->%@........%*,;_}QIQIQ[}||||}2QQIIQ[1;*+.....+@**=-;_((||:2}[56SS87(;=#...........+%#>>-,-===$%@+....................@%**=>--->**%@........+&#>,-;~(:<6wwwJPQ[:(~';,>%....+%$-'(}[QQQQIIIQQQQQQQQQ[{~-#....+%*>-;'_:[5OSNS8<2:_!c-=$*&..........@*$-!|}[Q2|~->*%+........", +"..+@*,;de4hhhh7feb:bf77hkh7ea,%.....+@#**,;cabfiqTUqiebac3>=#@.....@%*3cdffgjqUjih74fbba;3==%@.....@*=9abf7ff1bdbdbf4ghhlkkea-%.....@#=9abe77khlllmmoqWqjihfb0>...@*=3_beeeebbbdbbffgjqWqpfdc>@....@*,;abgiqqigebebfgpqWqmed9*..........&*,;af75hhkfb'-$%@........&*=caekhlhhg7febf47hhllh7bc*......+&*>=3cdbeeef77gmjZqogd9=%..........+&*=-;0a0!c3>$%@...................+&*>,9;a~c0,=*%+........+&#*>39ab7iqqopmkh7fbd0;,*+...@%*,;a:f44747777k4k74774fba,%...+@$,cabbf7kmjqqqp7fd03-,*#&+..........@*$9cb77k4ba3>#&+........", +"...@*>9aekhVVmmikkkhlmmVlhkb03#.....&#*-0ad:4gijUTTqph7e1dac,#+....&*,0bgimjqWWomVlkkk4ebdac>#+...+#=-aeimmmikk4[4khmXXXVVh4d3%.....+%>-0dbe7khllXVXZZUWoVlk4a$+..&$-'b4khilihk7kkimpnZoqifa9=@....@*>cad4pqWjlkhhklmoUWWpgb0=+........+%*,cbgmXnmh4bc3=%@........&*-c(4hVVXXmmh,0a1477kkhlmmnonomgbc>&..........+%>9abeggged9=$%@.................+%*,;_b7gigedc>%&.........@%#$>90df4iimVVVVmmiifbc3#...+#*=3adbe4e4e44e4e4e4eeeba;>&...+#>0bgiiihlVmjjihfba3,=*#&+..........+&*=3_eklh7:a;=*#+........", +"...&*-!]^sxBGGvGBBBHGvvHAxs/{;*.....#,;)/zsyBBHvuEuEvHABxsr]~,&...&$-~2swDLLEEEGHCCCBCAtsz^]!,&...%>;)/sHDDGHABCCABHvDvGCCAzF!*......&=;!)]/rzxBBBCBvLELGCCAs]*..+#-!]zxACHvGHHBBHGDDGGHHAI]'-&....%=-;_FItEELvCACACGLEEvtJ/{-&.........*-!{rxDDvvyz/);-#@........%>;)/sABHHLGvCCACHvDGHCAxr{,@....+#,;)]rsAABACBHvGDGBHAz2)9$.........+#-!{rsAvDvwV]!-=%................+#>;~FzxAvDDwz1;-#@........+#*=-;~|:/rKsxAHGDDGGyzF'*....%=-;!)]F///F/////F//FFF{!;-&...%>!2yGDGvHHBtysKr/{~;--$#@...........+#,;~FzxBBxzF);,*+........", +"...@=,;)/zstAGvvBCCCGGvAAsz/);*+...+*-;]/zyABCCvEEEDGCCBAxz/);*...%>;~FsHGLLLLLvCCCACBCBAxzF)-#...&=;)}swGLvGCCCCCCHGvGBBtxr{-#......+*$;;)]FrsxBCCCCvLLHCCyr)*..+#,']ryBAHvvGBCCHGLvGCBAs^)!>@...+@#=;;{IyGvvHHHCCBHGGLDAzF),@........+%-;{QyvLvGs^{~-=#+........@>-!]ryABBvvGHCCCGGvHCBysF)>@....%$;'{/ryACCCCCHvvHCCtxr{!-&.........@#-~]rxtGvDHy/)-=#+...............%=-;{/sAGHDDGsF'-=%........++&#*>-;){F/rstttGGDGyzF)$+...+@*=;;'_)){{){({{{){))~;;-*+...#,'FJtvvHCAyszr/F)~!->#&+.............%=-!]ryBByzF~;>%+........", +"....&%*-;~(:[-'{F/QrIKPJOOOPKzrr/});=%...+#>;_2<8JOwOJJJzKzKzzr^/F);=&...+%*-~1QI5PKKKKKKKPJPPI[F{'-$+.......@&#==-!)]/^IKKJJJJKKr[];#...@%=;~{/[IPJPKKKKPJJIQ[F{~-$%.....+&%$=-_1,;')12[<<<}:_;,@......+@#**,-=,-,->>>->-,,==*#@....&*,014<<[Q}:(~';;->=*@+...............@*>-!{//r2{!,=%+.........", +".....&#*=-;_(2[QQQIQ<[21_!->*%......&*=;(:2[QIIIIPPPIIQQ[}:~-$@...+@=-c|[&.........+%%==-;_1}[IIIIKI>3a(:}QQIIII[Q}}:(!-=%..........@%=3!|[<<2(;,>#@...........+&*=-;!(1[QQIIIQI*&.....@*>;!(|}QQIQII<[}1(_';,=#&..........+%*,;(1[<<<[|!->#@...............+%*=-_45O65Q4:_;=*&...............+&#$>=,,;cca_a_9->#+.......++&%%%**%**$$$%$#%%#%&@+....+&*,90_____;;->=**%@++................+@#=-!:22}_->*&..........", +".....+&#$>,3abe4hhhh7ffdc9,**&......@*=9(ee77hhlkhkhkhk77f:a3$&...+&*90b4khhhhlllhlk5kh47f1a-*&....+%*-9adbf7hhhkhhhh4eda9-=#&..........@&$$-0_b47khhlhhk77eb3%....+#$>-9ab47hhlhhhh4bd03,>*@.........@#=-cabf7hhhhh74bbda9,*&..........+%*,cdf74fdc=*&@............@#*=39ab47hhhlhhh7e003>*%@.....@*=90dbf4hhhhkk7edcc-=$*&+...........&*=cdb47hh4b0,*%+...............+%$=9agjqpk7fb03=#@.................+@#**$>-33999,$*&..........@+++@@@@@@@&@&@+++........+@#=,399333,==$*&&@....................@#=3a14fb_3$*@..........", +".....+@%*>,9cde7kllk74:dc3=*@.......&*-0be7kllVVVVVVVVllk4edc=@...+%=-cb4hlVVllVVVVVVIl9a|7klVVVVlk7|ac9,*%+.........+#*=3ade4kklllh4ebd03**@..........+&*,cde44e0;,$#@............+@%*=90d4klVVlllk7|a33=$#@.....@#>3cd:[klVllhk4ed03>>*%&+...........@*,cae4kkk4b;,$&@...............&#=9afioZol7e|a3>#@...................+@***===,*=**#&............++.+.....................@&#=9993,,,$**&@+.....................@*>3ab44ea9=*&..........", +"......+%#>-')F^zxxtxzr/]'-=#+.......#=;~FrsstttBAABBtAAyyzr]'-&...@$-')/zxtAAAAtBtBABtAysz/]!-&.....@*9'{F^rsxtAtAAAyzrF~;3$@...........+@*=-~]^zsAtBttAxszrF~*....+@#>-')/zsttAAtAxzF)!;-=%...........%=-;)]rzxtAtxsz^/]_;=*@...........#,;~F^zr^{'-=#+..............@*-;)FrsxABAAtyz/)!;-#&......@#-')F^zxxAttysr^F);->*&@............+$;)]/zsxsr/~;=#+..............+*-!{FztvvHtsz/{;-=@....................+&%*$>,,=$$%&@.....................................@#*=----->,=#&+......................+&$-!{/rr/{!-=%..........", +"........@#--!)]F/rr^F{{~;=#+........+#-!){/rrzszzzszzzzr/F]);$@...+%,-~)Frzzszzszszszzzr^F]';*+......%$;!){{Frzzszzzr/]);->%+............+@*-;'{F/rzzzzzr/F])-@......@%>-~)F/rzzrrr^F)'->*%+..........+&%*-;){F/rrr^/F])';-*&+...........&$>;'{]]{~;,%+................@$;;)]/rrzzzr/F)';-##+......+%=;!){Frzzrr/FF));;$#@+..............&>;){F///]);-$@...............@$-']/syBBtz/F{';$%+......................++@%&%#&+++.......................................@%%*=>=*=#@+.........................+%>;')]])~-=#@..........", +"..........&**=--;;;;-->=*@+.........+@*=--;''~~))')~)!!;;-->*&.....+&*>--;~~~)~~~)'~)~'~;;-=*&........+%*=---;!~~)~~!;-,=*%+...............@%$=--;'~~)~'!;;-,%.........@%$>-;;!~';!;--$#@+..............++@*=---!;!;-,--$#&+..............@#==---,=*&...................@#*>--!!~~!!;--$#%+..........+##---;'~';;;--=##+.................+@%=---;-->=#@+...............+%*-'(1}[[2)!--$#+...........................................................................++.+@&@++.............................@#$>-->=$@+...........", +"..........+@@%%%**#%%%&@++...........+@&#**=,,,=$>$>>,===**%&........@%*>>=,-,---$$=$==$=**#&..........+@&##=>,>-,>>=$#&&@+.................+@%#====,>>>=**#%@..........+&***$=$$**%%&@+..................@@@%*%***#*%%&@..................+@%%%*#%@.....................+&%*=>=>$*#%%&@+.............+&%*>>=>>==**%%&.....................@&#**#%%%&@@.................+**-;;~((!;,=*&+...................................................................................................................+%#*%**&+............", +"...........+..++@@@++++...............+@@&&%#%%&++@@&#%&&&@+..........@&%#####%%%&@+@+@%&&+...............+&&%%&%###%&&+......................++%%#%%###%&&@+.............@%%%#%@+@+++.....................++.+++++++.+......................@&@@@++.....................+@+@@#&&@@++++.................+@&%%#%&&&&&++......................++&@@++.+...................+@&*=>,,,=*%%&+.....................................................................................................................@@&@@+..............", +".............................................++.....+++...+.............+.....++........+.....................++....................................+....+..................+...............................................................................................+..+............................+.+++..............................+.........................+++.+++++++++..........................................................................................................................................", +"...........................................................................+................................................................................................+.+.................................................................................................................................+..............................+................................................................................................................................................................................", +".............++@@&@@@@....................................................+@@+.+.........................................................................................++@@@@&@@@@++...................++@&&@@@@++@+.....................................................................................+@@@@@@@+........................+@@@@&@@+................................+..........................................................................................................................................", +"............+@%#&%%&&%@...................++++.........................+@&+&@@@@@@+.........................++++@+++++++++.............+@@@@@+@+.......................++&&@&&&%%&&&@@@+..............+@@@@&&%&&&&&&&&+.......................++.+@+....................++@@++....+.+@&@+...............+++@&&&&&&&&+.......................+&@&&&&&&++...............+@@+@@+++++++@++@@+................++@@@+++............................................................................................+..@+..............", +"..........+@&%#*$*###%@+................+@&&%&@@&&&@+.................@&%&%&%%&&&&&%&++....................++@&%&%&&&&&&&++.........+@@%&&%&&#&&&@@@+.................@&%&&%%&%%%#%%&%@&@+...........+@&&%%%###%%%%#*#%&@+..................+@&&%%&&&@@@++............+@&#%%%&@@@@&%&&&%&@@@.........+&&&&&&&&%%%%&&&&@+...................&%&%%&%%%%%&@+...........+@&&&%%&&&&&&&&&&%&&%&+............+&&%&%&##&@@@@+...............@@@+............@&&@@@+..........@@@@@@+.....@&@@@@++..................@&&%@&@.............", +".........+%%#*$=>===$**&+..............+@&###$****##&@..............+@%#$$*$$$$$****#%&@+.................+&%%#$$$$**#####&+.......@%#%*$*$$*$*$**#*&@+.............+@&#**$$$**=*=*$$$$#%&++.........&%###*******$>$=****#%@+.............@&%%##*$$$***#%&++........@&#*$*$*#$#%#%#*#*##$%%#@........@%%#$$****$*$*$*###@@+..............+@&*#******$$*#%%&@......+@@%##***$#$###$####$#*#&+..........&%*#**$**$$*%%%&+.............@%%%#%&@+......+@@##%%#%+.......+&#%#%%%&@@+@@&#%%#*%%@@.............+@&%$####*&@@..........", +"........&**=,990aaa0c9,**@+...........+&#*==,3333,,==#%............+&*>>33c9cc0cc33,,>*$%@+.............+@#*=,>,,3933,,=,>$*&.....+#=>3339ccccc3933=>*#&+..........+&*>=3393c99c;ccc9933,=*&+......@%*=,,-39ccc0009c9cc933==#+..........+@#*=>,3333333,,>=*#@......&#$=>=333-,=,=>>>,,,3,-,=*+......@%*>>,,339cc9cc333>=$*%&............@##>>33c9ccc939-3>>*#+....@%$==,,3933,,,>==,,,,,,>=*@.......+%*=,3399cc93,=>*#&+..........+%*=>,=>==##&@@@@%*$=>,,=*#+.....@#*=>,,>***%#*$==>,,,>=>#&...........+&**>=,,,===$*%+........", +"......+#,;'){]/rrzzr^F{;-$#@.........@#>;;~))]F]]{{~!--&+.........+#=-!){]FFF/^^/]]{))!;,$#&+.........+&#>-;')){{]FF]{{)))';;#+...#-;))FFFF///FFF]{)~;--*&+.......&*,;~)]FFFF/F/^/^/FF]])~;,#+....@*-;~){{FFFF//^^//FF//]{)!-$+......+&%$-;'~){{FFFFF]{))~!;=@....@=;'){{{F]]{))~~)){{{{{{{);$+...@%=;;)){)]]////FFF{{))!;,=@..........&$-;~){]/F////FFF{));,#...+#-;~){{]]]]{))~~)){{{{{)'-*+.....&*-;~)]FFFF^/]])~;-$%.........+#,;!~{{{)~;->=*==--')){{)!-*...@%=-!)))))';;---;'){){{))';=@.......&#*=-!!)){{{{))!;>$%@+.....", +"......%=-')]/zxtBHHAxr/);,=*&........@=;~{]F/rzzrr//{'->%.........&$-;{Frzzzzsssszrr/F{~;--*&........@#*,-~)]F/rrrzzz///FF]]~-&..@>']F^rzzzssszzzrr/F)'--=%+......%=-']/rzszszszssszzzzr^F~;$&...+#>-)]//zzsszzssssszzszz/F]),%......@#==;!{]//zzszzr///F]]);=+...#-']F/rrzzrr/F]]]F/rrrrr//]-@..+**-~]F^/rzzzssszszr//F]~;=#+........+#=!)F//zzzzssszzzr/]]!$...+$;)]//rrzzr//F]]F//rrr//]'-%....+%>-)F/rzzzzsszr/F)!-$#+.......#>!)]//r//]);;,-,-;~)F^r//F),&..%=-!{F/^/F])~;;!)]F/rr//F]);%......&#*,;))F/^rr^//F)!;-=*#@....", +".....+&*=;!(F[KJwwwOI}{'-=#%@.......@%*-;)(]}}/2/[F]~;-**+........@*=-)]}/2/[/^/Q/[/2{)';,=*&........@#$=-;~_F}/2^Q/[/}]1{_)'-&..&=;){F/2//Q//[/[/}/|);-=$#@.....+&=,;)]}//Q/Q/Q^/rQ//[/F{!-=&....&*-;(F//[//Q/Q//Q//[/[/F])!>&.....@%#>=-;)_F}/[/Q^[F]1]_)~;$@..+%,;)(]}//[/2F|_)|]}//^[/F]_-@..+%*,;)]F2//Q^I/Q/Q//}]|);-*@.........+#$-~{FF[//[/Q/^[//]|~-*...@#-!):F[^[^[}]|(({]}/[//]);=&....+&*-;(F/2^/[/Q/[F_~;,*@+.......&>;~(]:F/})';->>>,-!)]2/2F(~-&++%=,;)]}F:](~!;--!)]1F[FF|);-%.....+&**=-;)(FF}/2F1{~;->$*#&+...", +"....+&$*-;~(}Q56MSSO5[|_->*%@.......+*=-'~|:2[Q[Q[[1(;,>#&........@*=;_1[[Q[Q[QQQ[[[}1(~;->*%+......&**=>-;~1:}[[Q[[[}1}1|((!-%..@,'_(:[Q[[Q[QQ[[[}}:(!--,$*%.....%*-;(1}[[[[QQQ[Q[Q[2[}1|~-=%....&*,!(:[[[QQQ[[QQ[QQQQ[[}|(;-&....+&*$=--!_12}QQ[[[[}}:11(_;=&..+#>;~1}}[[Q[[:|(((:}[[[[2}|(-@..+%$=;_|}}}[[Q[QQQ[[}}1|(!,*%.........@%=-~(::[[[[Q[Q2[[}1(~-#...&$-;(1}2[[[[21(|(|:22[[[1(;=&....+&*>!(}[[Q[QQ2[}}1_;,$%+.......%=-~|:}}}}|_'--=>-;~(1}2}11~-&.+%*,;_122}1|(!;-;'_|2[2[}|('-&.....&#$>,-!_|:}[[[}21('--,$*%+...", +"....@%>,;adb4hloqWqqpgfbc->%@.......@$>-adee77hkhgheba-=*%+......+&>,cdf77hhhhh7hh7k74bbba;,*@.....@%$>9;adbf77kkkhk7h77ffeba;%..@>adf47hhhhhk7hhh77febaac,=*+...+#>3abf7khhkhhhhkkhhhkh7fdc=#....#=9aefhhhhkhhh&..@*30de77hhh74febbbe7hhhhh7ed3@..+&$-cdbe77kkhhghhhh77fbdc9*%.........&*=3a:f7hk*&...", +"....&*,cde4khllnoZqqoml7b03>#+......&*30(e4klXpppnpm7bac>*&+......#=9d4klVVmXmVllVVlliligfbc,#+...+%=-!d:e7hilllllVlVlmimlkkea$+.&>de7hmpXmVVVllllllhhhg7fdc=#...+$,0|49de7lXppmVlk4447ippmVVk4dc*....&*,c(4#&......+#3a14hmnpmh7eb_a~db47mmppl7bc#.@$;abhlXXmmihebb|e7hlmmmiked9#...@#=ccd:f4hihllllVllhhg7fa9,#+..", +"..+%=-!]ryBACCCHGHHGGvGxz/{;,#......%>!]rxtBGDLEEuEvAyrF~-$@.....+>;{^sACAGGLGHCCCCBCGGvvAJF),#...%-;{/syBHGDvHBCCCHHHGvvvHAx/-&.&;/stvDLvvHBCCBBBBCCHGvGwzF'>@.+%-~]rtCCHvDLGHCCCHHGvLDDtJr];%..&,~FzyCCHvvGGHCCCCHHGLLvGCtsF-..+*-~FrsABGGGGHACCCHGvDuvGAAs)*.+*;)/stGGLDvHCBxssyACHGLvDGtsF>+.&=-~FzsAACCGvuvEDHCACCxzF);$@........%-;{ryBCCCBGDLvGCBCBxz{,+..$!]rstGLDLDHCCBAtBvuLvHBBxr(-...&$3~]rxACHGLDHHCCAsz/~;*#+.....+=!]zxBDELvGCAsr^rzxAHvELEvAz(=+@-{/ztvuDDvGtyzzzstHDELLGAyr(>..+#-']rsyBHGvGHBCCCCHHDvGwz]~,&..", +"...%>;~]zxBCBCBCCCBCGDLAs/]~;*+....+%,;]rsAAGGLLELuuvts/);,%.....@>!{rxBBCGvLvHCBCCCCGLLDvs^);%..&$-!]zxCBGGvvCCCABCCGLLLvHBy^;+.&;/sBGLLLGHCCCCCCBCHGDDDts/{;#..%,~FryACBvLvGCCCCABHvEuEGyr];#..&,']zyACHGLLGBCCCCCCGGLvGCBsF-@.&>;)/sBBHGvGGBCCAACGvDDLGHAs)%..%;)/zAGLLLvCCAAysxBCCvLLLvHsF-++@$-']rsABACHvLELLGBBBAyzF'-#+.......+%-;]rsAAACCGGLvHCCBByr]-+.+$;{/sAGLLLGBCABABHGLuvCBtsr)=+...*-!]ryBCHLLLvCBBAsrF)-$&+.....+>~FzyGLuELHBAxzrrsyAGLuEuvtz]$+@,(/JAGLDuELGAszsyBAGLELvHsr)=+.+*-)FztCCGvGGCCCABBCGLDvtzF);#..", +"...%*-;)FrIKzIrIrQIIJwOP}|';=#......+#=;)][QIJOwYwwOPI[{~->#.....+#=;)FQKKJJwJPIIQIKKJwwwOQ(;,%..@*,-_2KJJJJJPIQQQQQQPJOOJPK/)=..@>_}QPOwOJKIIrIrIQrIJwNw8<|'-&..@#>')/QKKJJJPIQQrIIIJwNSP[|'-&...#-!{/IQKJOJPIQIQrQIJJOJJKIF~#+.&*-!1QPJJJJPPIQQQQQIPJOOJKI};&..@=-~:[PJwOJPK^/FF2^IKJOwO8<2_$...@*,;){F/[QIJNNNOII^/F]);-#+.........+#=;)]F/[QKPJJJPKIr/F_;*...%>;(2QPOOJJKKzrIIKPwJPIQ/:);#....@*-;)F[/IJSwOKQ^/]);-*&........*-~1[6YNNNOKI/F]1/QIJwNNN8<1!%.+$;)29!(|Q-'(}[QI5P<22:::}[8YSY64(c=@...%=-!|}[Q-;!~|:[6YSY8<:|(!;->*@..........+@**-;~((:}QKPQQ[[2_~;>&...@$-'(}QIP6K;_1;_b47hlhh4eeeefgmoWWjgba-&..+*>cbiqqqpg7bbd_0aade77hhk7e9@..+*9ab45lmi74bb(ddbbgiqWWoied3%...@*3cdef4hlihf:b:bfgpqWqpfd;=&..+@*,cdefkhlk7e:bbbbef7k4h74b,+..&*3agpqWqmgfbb_a_adbf7hhhk7e3@..@%=9ab4klllk74:b|be7kkllhhed9#...+@%$=,39abfiWUqpgbd0;>=*#@...........+%#=,9c~db7hhhk4f:d0-=&...@$39df7llmih4hlmmVlhhfdac-=#+.....@&$,30dfiqjpfbdac,=*&.........%,cafgqTTTqik7eb1fkimqTTTjfd3@.+*3ab7hlmoWqji774ffgiqWqjgba3#..@#-cfiqWqpgfed(ddbbgiqWqogfd3%..", +"..+&=3cekVVVllQkkkkmnWopk4ea9=%......&*>90de4lmXXXVVVlhed03$&+...+%*,9de7klVVlk74444hpZWWoiea3%..&*9afpZWWoV7ebd_000ae4kkhhh49&..+$cdekVXXml74bdddde4pZWWomkb0#...&>9'bekkllXlk44e44hnZWWpgb0,&...&=30bekhlVVl7e}eee4khkhllk13@..&=9dgoWWZnl4eddaaad:7kllllke9@..@$>cdekhVVVlhk4ee4[klVmVlh4d;#....+@%$,9cdbgpWUWjg:da3,$$&+...........++%$>,90de7lVlhk4ed09$&...@*30d4lVXXVlllVnXXVVl4d03,>%.......&*=90dfmoqmgeba;,$#@........+#-0dgiqTTTWnVk774klXoUTTUjgb9&.+*;aekVXXqWUomlhk74inWWWohed9%..+#3afpZWZnl7eb0addb7nZWWomke0*..", +"..&$;~]zyCBCCCCBCCHHvEDGAyz/);#.....&*=-)]^zxCHHGHHCCCBsr])-$@...+$-;)/ztBCCBCAAtAtABHEEELtsF'%..*,)FKAEELGAsz/{))~){/zsxyxxz)@.+&-)FzxCCBCBysr/]{F^sHDLLGHtzF=..+%-!{rsACCHHAtxssxtAGLLDAK/'-%..+#-!{rstCBCCAxsssyxyABAAttyr;@.+*;(^xDLLvGtsr/{)){FrstAABAy^'@..@>;)FzACCCCCCtyxsxAACHGHBts/)*.....+#,-;~FrsvuEEvyI/('-=*@.............+&$-;!)/zxBCCAAxzF);-&..+*-;(/stCHCHCCHHHGHBCts/(;;>#+......&=-!)2KALDGsz^]_;>*%........@,!]rswEuuuEvHAAABBCHDEuuuus/;&.+=)FzxCCHDEEGHBCCtytvEEEGAz/)$..@>)/JtEEEGtsr^]{)FrsHvELGHts/-+.", +"..@=;)FztCCCCCCCGvGLLLLHtxz/);*+...+@*,;']^zAHGGHCCCGGCyz/);,#...+#-;)/zyACGvGCBBBBBCvLLLLAz/;&..#;)^sHDLLvAs^F)'!;!'{F^^rrrF;&..%-)FzABCCCtxz^F{){/zAAHGBCBs]-@..%-!]/syACBCCAyxABHGHHCAs/{!,@...#-;]rsAABCAByyxytCCAAtszrr{-@..*;FryGLLDHyz/]))')]^zsyyxyz/;@..&=-~FzxCBCCBCBBBBBCCCBCCCBs/)$......&*>-~{^stLELGsrF);,*@+..............@#=-!)]ryACCBtszF);=%...#>;)/sABCBCGvGGvGvCtyrF);-=&.......+*-;)/KtGLtyr]]~->$@........@$!]^stEEEELLHCAAACHvEEEEDGs/;@.+=!FzyCCHvGGCCCCABAAHLLLLAsF)$+.@-(^sGLLvGyz^])'){FzACHHCCBsF-@.", +"..+&=-):rKKzKKKJwNNNNNw8Q2]);=&.....@%*=-'|}PJwJIQIKJwOQ1(!-=%....+*=;)]/IKwwwJKzrKKJwNwNO<}~>@..%,;([6www6Q:);->=>>,-;;;;;;-*+.+&*-_]QIKKr^F|);;--!(2IIKIIr[)=...@*,;)F/QrKKKQ^[I8wJKQ2}(!-=%....@=,;)F^rIzKrQ/}IPOJI/]()!;-*...%-':....#=-~:/KKKKzKKrIrIzKKJKKKI2)-%.......&*$-;_26wNS6[_'-=%@................+@#*=-;)/IKzI^F|'-=%@...&*=-'FQKJJwwwwvwwwK[]);-=*%.........@#,-_:5OwP[1~;>*#&+........+%>!(2%....++&$,;~(}+..@,9_15YSY6}_;-=*$###$$$>>>$*#...@*-;(}QIIQ2|_;->=,;_:}QQQQ[}_$+..@#=-!(:[#@...+@#=;_(2[*&...%-0|[8SSO5:_9-,--3;_((|((~!-*+...@$-;(2QIIIIIQIQIQQQKIIKI[:!=@........@*=-c15YSY5}~-=$%+.................&%$$>-~|[QQ221(;->#+...&*>-'(}IIJwNNNNNSO<1(!-=#%+.........+%*-;b<8O<:(;-$$%@+.........%>-a:[ONNNNwO6<[<;([QIKIIIPPJP<[[[8YNM6[_;-%..@$c(26YSO5:_;->*=,9_12[QQQ[:!*..", +"...&*,0b4hlllllppoojoomi4fba3=&.....@&$-0dbfkmmkgffgipmgfba;,#+....%*30bb7ijWqplhlhVmjUUUjgfa>+..&,cdfpqUqpfd9->#%%%%%##$*$$&@...&*30b4hhh74bac,,==3cbf7kkh7fd$..+&*=9abe7ijqjjjjjqqqifda9,*#@...+@*=;_bf7iqqjjjjjqqjgbac,=*&+...&3abgjWUqibdc-,,;0dbeeeebda3*...+@*30d4hlmmllklhllhlVmmlh7e0$+.......+@%=90biqWqpea9*#&..............+@@@@%*$3c_e4hk4ebdc,*%....@*=9ab7hmmZZUUUUWqifdc-$#&@.........+&*,cbijqiea9-**#%+.........&>9abgjWUWqoppjjjppooWUWqif0*..+#3;b7hllhhhmjoopi7gpqWqjgbc3&..@=cbfpqWqiea33>$=,3adf77kk7e0$..", +"..+%=9~ekVVXVXlXXXXnXXXVk4edc=%....+&$,cd14klVVlkkkhlVVlke:ac=@...+#=;a:4hmZWZoXVVXVXZWUUqp7b9&.+&3ab7pWUUjgdc9*#%&&&%%%#$*%%@...@=ca:kVVVlk}d;3,>33a:7khlll7b>+..&$3c_e4ijUTUUWUTUWqifb09,>#@....&$=0dekijWUTUUUUUWoiea9,$#@...+%;afioUUqp4bac99a14kkkhk74|a,@...%=9_bklXXXXXVVlVVVVXnnXVhea>+........@$>3aepqWWpgd;3*&...........+@&%#$*$*$,9ab4hllk7eba9=&+...@#3;dekVXnZUTTTUUqm7bac,*#@.........+%*-0eioqp7ba9,>$##%@+.....+#,9d4ioWUWZXnoqUUqnnoWWUZp7a=+..#,a1kVVVhhlmZWZonlmnWUWogea3%..+>abhpWWZpfac3==>,3a:4kllVl7d=+.", +"..&=;~FzABHGHHCBHHGBGGGHAys^{;*....@*-'{^sxBBHCCBAtACHCBAys/);#...&>;)/zxtHvEEGHBCCBHGEEELGxz(%.+*!]rsGDEEtJ^]~-,*%%%#$#*$*$$&...#-)FztBBCAAs^{~!;;)]zyACCCAx^;+..%-;{/zxHDEEEuEEEEEvGs^]);-,%...+%-;{/stHDuEuuuEEEELyI{'-=%+...+=)/ztDEEDAJ/]))]^sACCBCCByz/;&..+*;)/ztBHHHBCCCCCCCHCCHCCtz];@........%,;_:KHuEEGs[{!,#.........+&#>---;--;-!)]rsABBBxsr]'-*+..+&=;)/stCHvLEEEEEELGys^{';=#+........%>3!{ItEGGszF(!;----=*&+...@='{/stDuDLvHGLEEEEvGvLEELGJ/-@.+>!]zxCCCCBBGLEEvvHHvLELvAKF~*..@;FKyGLELGs/_~;;;')/zxtCCBCx^-@.", +"..&>-)FzACBCBCCGBLLLvLvCCBxr{;*+..@#-;)FzsAACCCCBtABCCCCBxs/{;*+..&=;)FzsAHLLGHCCBCCCvLEEGHyr{#..*']IsGLELHsr]~;,$#%###*$*>*%&..+&;'FzyCCCCxs/{!;;!)FzxBBBBCy/;+.+%-!)/sttGEuEEEELELLtsr/)~;-*+...*-!]^sytEEEEEEEEEEGx^)!-=&+....>~[sAGLELAs^]{)]rsAACCCCAxz/'*...%;)FzyCCBGCCCCBBCCCBGBCCAsF-&.......+%>;)FItELuHs^);-%+........&$--;!)~~';;')]rsBBCAysrF~-*....%,;)FzABCCLLEEEEELHtzr]~;-$@........%,;)FKyGLtyr/{~;;;----=&...+*;)^sBLLLLvCHLEuELvBGLLEvts^;@.@>!FryCCHCCCCGLLLHBBGLLLvtzF)$+.&-FrxGELuHs/{';-;~{/zABACBAy^;+.", +"..@*=-_]QKKJKKPJwNNNNwwJKr/|'-&...+&=-!)2^rKKJJJKKPPJJJKK/}{;-%...&%=;_]}[IOOJPKIIIIKJOwOOPI}'*++%-!([8www6Q|!-=*%&&%##*$###&@...@=-~FQKKKI/F(;-,,--!]/rrrKr/)>...@*-;)1^QPORSMYwwwNOK[1{~!-,%....@*,;(F[Q6YRSMMMSwwOQ(;-*#+.....#;~:+........@$=;_25SNw6[(;-$&.........&*,-!!)~!;----!{/IKr^^F|'-=%....@%=;)FQKKJJwwSwwwO8KQ1);->$@........@#>-~:5OO6[|)';->--;--=&....%>;_:IOwNwJII6wOYOPIPwwww6[)=+..$-'F[KKJKIIKJJwJPKPJwNwJ<2),&..@=~1[6wNw52);->=,-;)F^rrKzI/_>..", +"..&#=-;|[QIIIIIPOwwNwwOP<[}(;$%...@%$>;(2[$#%%##$$**$$#&...@>-!|}QIQQ2|~;->>,-'(:}[QQ[2'*+.+@$=;_1:[~|[6SSO<:(_!'_|}QIPOO8PQ}(;%...&*-;(}QIIIIQ[22}}[[-~15YSY8}(;=*&+........&=-;_1:}(!;---;_1QQQ[:|('-*%+...+$,-!|[IIII5I55686665[(!-=*&........+%=-c|<8O51(~!---;~~!;,#+..+&=,a|7OSNY8<[<58P<[[<6SSO5}~>+.@#>;(2QII$=-;_:}QQQQ[2~=+.", +"..@#=-0b4hhlhhhVmpojjomlkh4bc$@...@&=,cb7hlmoqUUUUqTUUqjmlhfd,%...+%*-0bef7hhhf1bbbbe7hhhkhkfa,++&=cafiqUqpfba3,***#*==-3==>*&...@=9cb4klhhf1a0-,,-9abf7....&*=9abe4khlhk77ipjpg0-*#@......%,0bgjWWqifbdaaab4hmoqZqpi4ec*..+&*90bfkllhh74eb:bf47hlhhkea,%.......@&*=9cfiqWqifd;3*&+........%,;de4hk7ba;;9cdekhk7eba;-*%+...+#=cab7hmmlhh@...%>9abgjWUqige7khkh7fijWUqif0>..+#30d7hhlhhkhhhhhhlpoWUqjgbc,+..+$0dgiqUqieba;3=,3cde7h5hk7e0*..", +"..@*>3a1kVVVVVlVVVXXXXXVlhk:a>@..+%$,cdfhmnoqWUqUUUqUUWqnmVke0#...&$,9d14klVVk7e:e:e47+.&,cbfpoZojh4bdc;,>,9cdddda'0>+.+&>c_ekVVVhk4ed~c;0a17hmlllhfa$..+@*-cde4klVVlhkklmonmhk[44e(,@...@*-01e7klVlVhQ4hmppfa,$#@......%9dbhjWWqmhee|b1e4lVnZZZnVh4a*..@#99d:kVVVllk44eee4klVVXlhedc%......+@$>3cdfpqUWjgba9>$%@.......%9ab7lmml7:bb(bekm6Vkke|03$%+...&*3cdekVXXmlhhhklmnonmh4|dc$@......+#=3cdfmoZphebb{de7hhhfd9*..+&-0(fmoWWZpk47khhk44ioUTqp7b,+..#-0:kVVVVlhkhkhlmXnZWUWohfa>@..@>cbgpqWWphe1d!09~dehVmmVVke0*+.", +"..%>;~]ztCBCCCBCCCCCBCCCBCyz/!$...*3)]rxGDDLvDDvvvvvvvDvDvvts]>+.@#-')^zyAACCByszzzzstCCCCCBy/;++%;)}stvvvHCAsr/])))]/zxyyszF~&+@*;{^zACBCCAxsr///^rstGvDGAxz{-..+%-'{/sxACCCAByxABHHBBCCBAAz~&..+#-']rstACCCCtyxxAAs[(;,*&.....+*;FrxHGDHHAyszzrzstCCGGBvCAs]*..#>'{/zACBCCCtxszzsxACCCCCAsr{=......#$-;~F^sHEEEGxr/{!->$&+....+>)/stGGvGtszr^rsAGvGBysr]!,*+...#-!]rstCHBCBCAtytCHGGBBAsr];#.....+#=;'{/KAEDHxsszzzsADHGyI{=+.+$;{rsALEEDGysssssssxtDEEEGs/;+.+='FzxCCCBCCBxxyACGDLEEEvyKF;@..%!{^zAGGGHCxsr/F]/rstDGvHByz]-..", +"..@$-)FzyBCCCBCCCCCCCCBCCBtzF'$+..#;)FzyvLELvCCBBABBCCCvLELGz]=..+*-!]^syBCCCBAyzzzzyAAACACBx^-@.#-~FryCCCBCAAz//F]F/zABBABxz~&+@*;]rstCCBCBysr^//rssHvLLvAy/{=+.+%-!]rsABCCCCAxyyytABCACBBAz)&...#-)FrsACCCCAAxssssrF~;=*@......*!{/sACCCBCAyszzzssxCCCCCCAs)%.+%-!]rsACCCAAByszrzytBCCCCAsr{-+....#>-;~{/IsGLEuvyr/{)'->*@....+=)/sAvLLvAyzzrzstvvvAxzr]!-#+..+#;~]rsACCCCCBByxyxCBCCBCtzF'=+....&$-;){/JAGLHAszzzsytDLDtz{-+.+$!]rstvLLLBxszzrzzssBHLLvGs/;@.@=)FzACCCCBBxyssxALLEEEuvtzF;%..%-)/zyCCCCCByz///rzxHLLLvAsr{,+.", +"..+%=-~]QKKKKrIrIrIrIKrIr^/|!-&..+&>;_:+.@>-'{^KzKKKr//|_({(F//rrrr[];@.+#,!{FQKKKzI//1|{1|}QPwwwJI2);%..+&=-']/^IIKPKQF//2/^^rKrzIr};&..+%=;)F}^IrKKI^F2::1)!-*%@.......&=3_]QKKKKKr[F1F:F2/rKKzKIr};&..&$-;)F/KKzKr^/F]]]/^IKKKKI/|;*...++%=,-;'_:[6RNw8Q1(';-,*#@.....*;_25wwww@..+*-':^KKsKKr^211||2[6wNwJ<2)-%..", +"...&*-;(}[QIQQ[[[222[[[[}:(~-=&...%>-_1[8SNRO5[[2}}}[<5OMNR5e!&..+%>-!|}[Q-;~(b:45MNR872|(~;->*%+...+&,~|<8SRO5[2e:1[56O5[|('-=%@....&>-'(}QIPI..+%>;_2+..#-~|[IIP5<[2:(123a17khh9afiqTTUqjmg7f47imjWUTUjg0%...&=;dfipjjqqjjijiijijpppmhf|9%..+%*,0be47kkhiiiiiiiiikhh7eea-+.+%3abgijqqjjpppiiijijjjpmiba9>@...%>9bgipjjjqjpjijijipppppi4f9@...#>9bgipjjqjjjiigebac=*@........+%=9ab47himmiiiiipiiiihh44ba>..+&*9abgijqjjpigfbbfgipjZojpge0*...@#*9adbfgijqTTTqjigfeba9=*@...+%,0dgmjojpjpiiiippmieba;,*%@....&=;aegpjqjjpigebbee7lmpjpied=+...@*=9afgijqUUqjimippjqUUqjf0$...#3cbgiqTUqig:bacade4iqUUUjgb,+.+%3abgjqojjigfbbfgmjWTTTjgbc,&...&*30be7himppiiiiijjpppmgba;#+..", +"..+@*>-0b4kllmVl5ihhihh7f|dc3#@...%-afhjqTTTWWZmhk7lpZUTTTTqhb#..+#,0biqqUUUUUTqUTqUWWZWZXifd9#...&$,cd1e4hlVnqqUUWqonmVll7|a,@..#;b4mqUTTUWUqUTUUUUWonmlhba9$+..+#3afiqqUUUUTqUUUUUWWWWWonl40%..+%9afpqWUTUUUUUqoifbc,$&.........&$9!be4hmoWWWWqqUUqXXllk410$@..%,cd4ioUUUWWZph447moWWUWWqp4b=+.+&*-a1khiqqTTTTTTUZpmhked9*&....%>9afkmXnqqUUWWZoXmked03>$@+....#,ab7pqTTTUWom4e1e4hioWWWqm4c&..+%$9agjqUqTTTUWWqWqUUTTTUjg0=+.+%,_ehjWTTUol7ed~ab7hjqTTUqmf9+..$9d7pqUUUTqjhfefkljqTTTqiba3#...&$,9de4kmoZZWWWqWqWomVl7bc3*+..", +"...&=-;)/zsAHGDvvvvvvvHtsr/{!>+..+$!FzxvEEEEEEDGAxxBGDEEuEEEA^-+.@=;|IwEEEEEEuuuuuEuEEELEvxz:'$...&*-!{^zzxACGDEuEEELvCCAxs^{-@..*)rsGvEuEEEEuEuuuuuEDCAts/(;>+..+>~2stEEEEEEEuuuuuEEEEEEvHts]*..@=~}zGuEEEEEEuEEvAs/{3>*+........&>;)F/zsHvEEEEEEuEEvHCBxz/(-+.@*;{^xBDEEEEELHxssxGvEEEEEDHxF>..+*-)FsABGDuuEEuEuEEGHAAs/)-*....#,'{rxBHHDEuEuEEGCBsr]);>=@.....$;]zxGEEEEEEvAJrrrzsADuEEDtsF=..+%-!1VNEuEuEEEEEEEEuEuEuuZz:-..+>~FsAGEEEDDHxz/]F^sAGEEEEDts)#.@>~/zHEEEEEuGJrrzytGLuuuuXI];*...&=;~]/rstDDEDEEEEEvvHAyzF~;=@..", +"...&*>;~{/zytvvvuLuLLvvAsrF);#+..+$;{rsAtDvDGHHtszsxAtGuvuvAx^;@.@=;{/JtvtHvvDvDvHGGGGHGAAz/]!*...+&>;)]/^zsxBtHGGGAHBAyyz/])-@.+%!FzxyvvGDAGDtDvHvtCBtyz^]~;$+..@=!{rwtGGGNvDDDGGGvtHHAHBtsr(=+.+$!{IytGGvGGvvGHwsr])-$@+........@#-!)F/rsxGtGHGGGGBABtsz/]~=@..&-)/zxAHDvGHGxyzzJytHGHHHBtz]>+.+*-~]rsxttGDDEuDvGGBBAsr]!-#+...%-;)FzsxttHHHHHGHAxz/);,$&+....+%;{^sytvvNGvAsr/F//zsxGtGtyz(*...#>;]zXHvDDGuGGHHHGGDDDDAy^(=+.+$;]rsAHvvGAxs/]){FzyAtDHNAyr)%++>;{^JtvNvHGxz^/^zyytGGGxzF{;*...+%-;)]/rsytGtHGtHGAAszrF{!-#+..", +"...+&&$,-!_:Q5JOJOOOO66[|_;-*+....%=;~(:}e}}}}::{(((:}}4}2221~=+.+%=-~{e2442}4}}ee}e2}2}:1(;-*&.....&*=-;;))1:2e}}2}22]()~;;>%+..+*;'|ee24[44[eee24}e:{();-=*&...+%=-'{ee}4}4}}4}4}[4}2}}:](~-&..+&=-!1e}f[}4}}e2:1~;,$@...........+#=,-;!(|:ee}4}}}2:{))';-=%...+%-'(|}42}}e2:1(({:}f}}}22:);%...&*,;)1]2}e:}424[4[}F]{';,#@.....%=--~)1:e}}4[[}2:(~;->#@......+&=-~{:e4[}}}e1~;;;'~(|e1e:|_-@...@$>-~{:ee}}}}[}2}4}4}}}e1'-#..+%>;~{::e222:(~;;;;~(1ee}}:|'>+.+#=,~{e}}ee2:(~!~)({:e}e|_;-=&.....&=,-;;)11:e}24}}2:(~'--=#@...", +".....@%*>,-0_::4[[[[22:_;->*&+....@*>-;0____(__!;9;c'_______'-%...+#>3c~__(((((_((_(___a!;-,*%......@%##*>-9;;'_d____'!;-,=**&...+%*-3c__(((({((d___!!;->=*$&+....@%=-c~__(((((((((((d____';-*+...&*=-c__((((d(_~!9-**@@............+&**>>-9c_~_(((_'!;--==#%.....%=-9a__d(__a!;-990__((_(_!;$+...+%*,-c~~__|(((((|((~!;-=*&+.....@%$>=-;!___((|(~;;-=*%&........@*=-9~__(d__~;-==>>-9;00~!;-#+...@&#>-9'___d((((((((((__~;-=@...@*>-9!____~';-===--30'__~!c-#...@$>-c~___'_!;-,--3;!'_~!-=*&......+@&**=--cca_____~;-,==*#@....", +"......+@**=-30aabbbba009,,*#+......&$,3390a00cc93>-339000c9c;,%....&*=330c00aaa000c009cc3,=$%@......+@@%#$==,39c000ccc3-=$$#&@....&*>-39900aaaaa0c0c93->>$#%@.....+&*,39ccaaa0aaaaa000909c;3$#....@#$>9990a0a0a0c9>>$%+...............&&#$=-,99cc090c93>>$$&+.....@#=-3900a00;39,>33909000993#+....@#$,-9cccaaaaaada00;3>*#@......+@%$$>3390aaaaac-=>$#@+........@*$-339cacc9c-,>*$*>>,9993,=&....+@%*-93900caaaaaaaaaacc;3=#+...+&$=,339ccc9->$**=>,-39cc3,=&...+%$>99c0c993=>*>>=,93c93,*%@.......+@%$*>=-,999cc9;3,>$%&+.....", +".......+@**=,3300a00039>=$#%@......@%$>9933099-,==>=>3333999,$&....+#$=3,9339993,3cc999,>=**&+.......+@@&#$$>,,333399,==**&@+.....@#*=,999cc90ccc939->,***@@+......&%*-93990;99990c33393-3,=*&.....@*$,-93ccc9c93,,*%@.................@&#**,,99999-3=>***&+......+&*>-93999333==>==399,3393=#.....+@**>3,9999cc0ac0c-3,=#%+.......+&%**>,999cc0c->=*#%@..........&#*,99ccc9-,,**$#$*===-3,>*&.....@&**,93339990c000;cc99,=*&+....@%$,,399,-,==*#*$=,,-9,3,>*@....@&==9339-3,,*$**>*=,,,>$$&.........++@%*$=>3993-3,=**%&.......", +"........&**>-3;!'__'!9->*#&&+......+&$>--;;!;;,>>$$---;-;;-;-*+.....@#$>=>----,----;;;--$$%#@............@#=>--;-;;-;-$*##&@......+%*$,-;;;!!;!;;;-;--=$#%@+.......+&*,-;;;;;;;;;!;;;-;,-3-,*&.....@#$=-;;;;;;;';-,=%+..................+&*$=,-;-;---,=##%@+......+&#>--;;'';--,=,,--;;-;---$&.....++#*>-3-;;'!!'~!;;;--=#@.........+&#%$=,;'';!;--**%@...........+%$>-;;;;;--=$%%%##==>,-->%+.....+&#$-->-;;;;!;!;;!;!;--=$&.....+%#>-,-->-=**##%#$=-,----$%.....+&$,--;---$$*#$*=>>=-,>=%&............+%=,----33->$##&@.......", +".........@##*$===>----$%@+++........+&%*==$=>**&@@@&#*$=**=*#&+.....+@&@&@&@@&&@@%==$#*#&++.+............+&&%#$>-,>>##@++.+.......+++%#$$$>>=>===*=$**%+............+@&$=>--->=>=>---,==**%%&@......+&%**$==>==$#*%@+.....................+.@#$=-,->=%@+...........+&%**$$=,=>***##%*$=-,>$%&+......+@%#*>>=>$>>---->,>*&+.............++%$>>--==$#&++.............+&#*$===$*%&++++.@@#%%%*&+........+&**#%*==========$*$%#@+......+%#==$%&@@@++++@&#%**$$*%+.......+%*=$-=*%++++@%&%%%%#&&+.............+&%**=$**%@@...........", +".............++@+@%&&@+................+..+.........+..++++++.....................+.+++......................+.+@&+@......................+++@++++.+....................@@&&&@.+.+@&&@+..++..............++++@++..............................++@@&++.................+...+@@++.....++++&@++.............++.++@&#%&&@&@@...................@+@@++....................+.+++++++........+...+.................++++++.++++.+.+.............+............++................++@@.......+.++......................+.....+.............", +"................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................", +"................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................", +"...........................................................................................................................................................................................................................................................................................................................................................................++@+@@+@++.................++@&@++............................+@@&%%*#*##%&+...........................+.............................................", +".......+@&&&&%####&&&&@+....................+@&&&&&&&@+................@&&&&&@+++@&&@@+.....................+@&%%&&@++..+.............+&&&&%%#&&&@+++@&&@+................+@@+.......+@&&@+..............+@&@+.........................+@&&&&@+.....+@@&@+..............+@+...+++...+&%&&@@+..........+@&&&&@+...+&&&&&&&%@+.............+@&&&&&&&&&&&&+................+%$--;-;-;---$*&+..........+%*=>>-,$#&@+........................@#>-;!'''''!;-$&+..................+@&%*#**#%@..........................................", +".....+%#*==$>===$>$=>=*#%&@...............@%#**=*=*=*%&@.............+%**=**==$*#*=*$*&@.................+&#$*=*>>==##**%#@+.........&##=$>$>=>==*$%$$**$#%@+.......@%##*#$**#%%#####$==*$##&.......+%#*#$==*##&@@@&%####*##@........@#$***=**&@@@@&&*=**$##&+......@%##*#$#*##*#####$=*==*#&+.......+%*=>=*=######*===$>**#@..........+%#==$>=>=>====*$$##&+..........@#,-'){]]F{{);;,*%+........@#$--;;;--==*&@.....................+&*,-!)]FFF]])~;-$&+................@#*=,,-,>=*%&.........................................", +"....+@%*$$=**=$===>*$>**#%%+............+&&%*$$>$>*$$##%@+..........@&%$$>>>=>=>=$>=*$#&+...............+@&%*$=*=$=>=$$**$&@.......++%$$**=**=>>>>>=$>>$$*#@+......+@%*$**==**&&%%*****>$**%%+.....@@%#****$$#%%&%&&**==$==*&+.....@&&%*>>$$*$%%&&&%%$$>$=*$%@.....+&%*$=*=$=******>*$>$$>**%+......+&***$>*>=**#$$*$*=*>>**&........+@&**$=*$=>*>>$>>$*=*$#@..........@#=-!){]]1](~;->$%@........&*=---;;-->*#@+.....................@%*>-;){]}F({)!-=#@.................@#$>=,-->$$%&+........................................", +"...+%*$>==,------,-,,=>***%%+..........+@&%*$===,=,,=>**#%@........+&#$=,,-,---->,=>>***#@.............@%#$$>=>-----,,=>=*$%&......+#**=>,>--;-------====$$%@......@#$$=>,>>>$$$*$*>=>>==>=$#@.....&#*$>=,>===*#$##$*>>>=>>>=@.....&#$$>===,>***#$#$$====>==*&.....&#$>=>>>,>,=>>>>=>==,,=,=*%.....&**=,>,=,=>>$=*=>=>>,==,=#+......+&%%**=>--,--,---,,=>=**%..........&*=;_|}}[221(!-=*%@.......+&*,;_((~~;->$%@.....................@%$=-;_|}}}2}|_-,*&+................@#*,-;';;-*#%@........................................", +"...@#*=39cc00c000cc9c9c3,=*#&+........+&#$>,3cc9cc9933>=$*%@+.....+&*=,3ccc0c0;9cc9993>=$*&+..........@%*==39cc0c0c0ccc93,=*#@....+&*>,399c;0aaacaac0ccc33=$%+....+%*=>3399933=>=>,9399c93,==&....+*$=339cc9933=*>*>=33c39933%....@%*=339c9393>=*=*=339c9c93=#....@*==9ccc;999933339c999c993=%....@*=,399c99c3939339c39cc993=&.....+@#$$>339c0c0c0c0ccc9993=*@........+%>3abgiimk7fba;>*&+........%*3abe7ebdc3$%&+...................+&*>-;0bf7iiiigb0-=%+...............@%$,;a_bba0,*#%+.......................................", +"..+#=c0_bbeeeeeeeeeeb|bdd09>#@.......+#=,99adb|eebe:bdac33>*&+....@$3c_bbbeeeefeeeb|bdcc3=*#@........&*=39ab1beefeeeeeb:bda3=#+...@#-9db:eeeefeefeffeeebbd03=%....%#3c_bb:b:bda9c!a(b1eb1da09$@..+%=-'db1beb{b~0c39c!d|b:b|b03&..+#>c'db:be1b_acc9c~db:b1bbdc>@..+#=9~d|beeebe|bd_db|be1be1b0>+..+%=cadb:b:eb:b(ddd1be1beb1b0,+....@%*,cc~dbeeeeeeeeeeeb:bd03%.......+@*>9bgoqZonVl4bac>$&+......+#,0|7kkk7e{03>*&...................+#*,ca14;{^stAGttGtHHGHAGtGAGty/{;$+..@-;{/sAtGtGtsz^^rzyyABGAtszF;#..@=']rsABtHtAys/]{]^zyAAGHAAsF,+.@,!FrytAHtAtsr/FF/rsxBBHAAyz],++#,)FzytHtAGtAtsszsyAGAHtGAyz)&..@-'FzytBGtHtHyszzsxAAGtGtAyz{=...@$-;)/zsxxtHAGGAGHtGAHHAx/{=+......&#-;{rwvuELGHBxr])->%@......&>;{^sCCCAys/);,=@.................+@=-'{/zyACGvEEvxI{'-$+............+*-!{/zxGGGts/{'-*&+.....................................", +".+*;(/xGLLELuEuLEELELHCBAs/{!>@....&*-;)]^zyACGLLLELLAxzrF)'-*+..+$!FzyCLLLLuLEELLLLHByz/{);-$+....&*-!)/ryHLLLLLELELLLLDHs/);*..&,)FKALLEuLEELLLELELELLLts/)-+..%-)/KtDLELLGCszrzyBBGDLLHBxr)=+.%,)/sBHLLLGCByz/F/zxAHDDLGHyr;@+*-)/sAGvLLvCByzr/rsACHDLLvHy^;@+#;)/stHLLEEELHAxsxHDLEELLGAx{#..@-(ryBGDLEELvHtssxGLELLELGCx/-+..%>-!]zyBCHLLLuELuEELLLLLAz];@......@=-~{IxEEELGBBsr]~;>%+......&$;)/zyBBCBxr]'-=&..................&$-!]/zyBCGLLLDAr{!-#&............%$;~]^JALLLGyrF~-=*@.....................................", +".+%-'1@....&*=-;){FrKJwwNwNwwPI[F('-=&...+#-)}QPwwNNNNNNNNNwJKQF_~;-=*+...+&*>-!|}...&=;([8wwNNNwPQ1FF[IKJwNwJP^]!%..%=;(/IJwwNwJI^F_)|FQKJwNNwJIF-++&,;{[IJwNwwJK^2]{F[IKJwNwwJI]>+.&,'{[KOwNwNNwJI[[IPwNNNwNwK[~&..+*;{[IOwNNNNwJI}[QPwNNwNwwP/(=...&*--~FQKKwwNwNNNNNNwNNww8[_-@......@%>;':%+............&*=;~:[8SNw8Q:);,*#@.....................................", +"..#=c(!|Q5YNNNNSNNNSSO8[Q11(!;>*&...+&*=;~(1<8YSNNNSNNwNNNR67(;,@..&=c_e5YNNNNNNNNNNNNNNNNS841;*+..&=3a28YNNNSO5}1(|}Q5OSNSO<[|;*..@>-~}<8YNSOPQ}|___1[+.&=3(}<6SNNNNR8<}}46ONNNNSOP[!&...*;(2+.+&*>;_1[IIPYNNNNSNNNNNNNY84_,@......+%*-a1'_:2[QQ[('->*&...................+%$>-!_:}5OSSO<1!-*#@...........+&*>-~_[5YNR6[|~;>$&@.....................................", +"..#>cbfijqoooooojojojpih574ba;#...@*=3abbf7hhmpjqjqojpiiieba3*+...#,0b4iqUUWWoqqjjopmhh4eeba3*@...@#>3abe7hpoqjqjqjoqqWUWjgbc3&..&=0dgmqWUWqqTTTTTUqqWWUWjgdc$+..@>3aepqUWWqmgebdbe4hjWUWji4bc$..@>9afgpqUUqi7fbd0dbfhpqUWqmgb>+.%=3dehpWUUomh7feeefkipqUUqigb>+.&=3degjqUUWqqigfegijqWUTUji4c&..+*;dfgjWUUUqqigff7ijZWUUWjif0>...&*=;deklVmoqqjqqqqqWUUUqpfd=+......@#*-cbgqUWqgfd03>$&@........+&$=;a|e4iikfa3=$#+..................+&%$=39degjWWqibc9$#+...........@#=3;dfgijqqpgebc3$#@.....................................", +"..&,cdeimXnnnnmmVlmlmmVVVVhkea$+..%=9d1kklllllmlmVmmmnoqojhba>+..+%-cd7ioWUWonXmmmlVVVVllh710,%..+&*,c17klVXXXmmmmXmnZUUUqhfa9%+.@3cb7pZUWqojqTTTUqpnoWUWogea>+..&=9d7pWWWZml7eb|be7hnqUWol4bc%..&=cdehnWWWom4ebddb:ehpWWUZmh|,++&>cdehnWWWomhkkkkkkklnWUWZm7b,+.&>caehoWUUWonVk444lnoZWUUoi40&..+#9aehjWWWWonlk74klXnZWUUolfd$...&=30bklVVXmmmmlmmpooWUWWjgd,+......@#>90eiqUUqifdc3=#@..........+*>30aehmomgea03=%...................+%$>-0aeiqUTqifa3=%&...........&=-9deklXnnXXVk4b03=%+....................................", +".+*3':rxBCBCBCBBAAtACCBCCCCAxF=..+$!{^sBBCBCBCBAtyAACHDEEvAs/;&..+$!{/stvELLGHBCABBBBCBCBCBs/'$..+*;)/sACCCCCCBAtBBCCvEEEDyK/'$.+*!]ryDEELvGHvuEEEEGGDLELGxKF-@..%;_/sGEEDDHtsz^^rrsyDDEEGts^)>+.%-~FzyHDEEGByzr/F/rsyBDEEvHs/;++%;)/sAGEEEDHABBABBBtBGEEEvHs^;@.%-~]^sGEEELGHBAxAtAHGLEEEDtz0%..@-)]ryGvEEvvHAtyytBHvDEEEGAz(-...#-!]rxCCCBCBCCABCCHGDEELGs2!&......@$3)FKtEEEDts/{'-=@..........+*-;~]^xGDvtsrF);-#+.................@#=-;{FzxvEEEAKF~-=%.........+&$-'{rsACGvHHCCByz]);=&....................................", +".+%-!)^sBACCCCBtyyyyABCCCBCCxF$..+>;]zyCGHCCBAxyssxytHGGvvAsr~%..+*;{/zAHvGvHCCtAxyBBBCCCCBy/)=+.+>;{/sACBCCCCAAyxxtBHGLvHxzF'*+.*!FzJGLLLvHAGEEEEGCCGLELvyz];@..*;)}zAGGGHCBsr/F/rzxBLLLvys/)$..@>'FrsBGGvGtsz^F{FrzyAGGGGtsF-@.*-)FzxHLLLGCBACGGHBBAvLLLLAsF-+.&>!{^KxGLvvvHCBBBCCBHvvGvHx^~&..@=;]/ztGvvGCBCBxyACCCGGGDAs/)$+.+%-!]ryBBCCCCBABABBHGvvvHtzF-&......@$;~FKAGLLLAz/);-*&...........&=-!)}stGCByzr]';$%+................+&*,;)FItGLEEtzF~;=#+........@*,;)]zACHHCCBHCHBzF);-*&...................................", +"..@$,;)][IIzKK^FF]]]F^rIKrKzQ~%...$-~2IOwwJKQFF1{{]F[QPPPPIQ};@...&=-~|[KPJJKI^//}F/^IrKzKr[{;%..+#,'{/IKKKKrQ//2FF[/IPPP<2{~-&..&-;1[6wNwJI+..@>;(:IPJKIQ/2)';!~1[Pwww8Q:);%...#>'(1IKJPKQ[]_~!'(12QPKJK[:!*+.&=-~{[PwwNJPIIJwwwPIIJwwNOI2)>@.+%>-'{}[IPJwwJJKKKJwwJP<<[:'=+...#=;~1}Q#@.........@#$,!_:3ae4hlik44ebb:bf47hlhhed3#...&=9de7hlhh47ebbbbbefhk74bcc$&..@>;afpqqqpggiqUTqiggpqWqpfd0*...@*30b7hhhkfbd;3,-cafiqWqpgdc3&..+%*,;dfhhhhfedacccabe4hlh7eac#..&*30dfiqUWqigiqUTqjiipqUWjgbc*...+%$=90df7ijWqpllmoqqpgfbdc,%....+%*,9abb47hhk4f7gppqmgfba9-&....+&*,cdbf44eeeeefgpqqpgfba9>%.......+&*3abiqUUjgd3,$&@..............&*>cab77h47fba9=*&...................@*>9dgjUWqib0-=%@.........+%=-9dfiqjifffipjpfbc3>*@...................................", +"..&#=9ab4klV6lk4:bbb:4klllll7d#...*cd7mqWUoi4bac399c(4lVVVVlkb=+..&$=9aellXXmlkk7447hklVVll7d9%..+#>9dellVlVVhhk77447kllh4edc,%..&*3abioZZm7gpqUTUjghmoZqpgdc$+..&=30ekVlVlk4bac99cd4mWWZjhba,#..@#$30d4lVVVk4f1dd_be4lVVVl4d3%..@=9cb4pZUWoXVjqTTUjmljZUWZifa*....&*>30de4moZZnmmnqWZphfbdc>%....+&*=3abe4hVllhhhlnZomhebdc>%.....%*,cd|4f444447kloqoj7fbac=&........%=caeiqTTqib0,=$@..............+&=30b4kllVk41a9>#+.................+&$,cbgjWTqjfa9>$@.........@#>90b7moom7e4inopgbac=*@...................................", +"..@=;~FzstACBBxszzrrzxtCBCCCyF$..+-{^sHEEEGts^{~''~)/sACCBCAxr;@.+%-;)/sACHHHBBCBtACCHHCCCAs^)=..+$;~FzyACCHvGHGHAABAAAAtsrF(;%+.#-;(^JtHGtxywEEuuGyxAHGAsQ{~>+..#-~FztCCCCAsr])~~{/JtEELvyKF'*..@=-;{^sBBCBCAxzr^rzxtCCBCts/'*++#-~]^sHvEEDHGvEEEEEHHGEEEvAz}-....&=-!)F^stHDDvGvDvDvAsz/]~;#.....@$-!)/rsACCHGGvvDvGtsr/]'-%.....#>;!{F^rzzsxABCBHGvtsr/{!-&.......+$;~FKtEEEDxI{;-$@..............+&=;)FzsACCCxsr]';#@................&#-;([JDEEEwz4);>%.........&=;_]^ztHHtszzxCGAsr])3,&...................................", +"..@*;~FryABCCBAxzzzzsyBACCBBt]*..+-(/stGLLGAzF)!;;;{/ztCCCCCAr;@..*-!)/sBBBCCCBCACCCGLGHCCAz/'*+.+#-!{/sABHGLLuEELGBBBBAyzrF~-*..@>;~)/rsssssGLEEDwxssssz^]';=@.+%-)/zACCCBxs/]~'){^sAvLDGxrF'$+.+#>;)/stCBCBBAsrrrzyBBBCABzF'*..#-~]rJtLLLLGHLuEuEGGCGLLLLtz],+..+&*=-;{FrsACGLLELvGBxz^]);>%+....+@#-~)/zxBBHLLLLvGAyz/{~-$&....+&*-;')]F/rzABCCCBCByz/{~;$@.......&,-~{IyLLEDyr)!-$@...............@%-;)/zAABCBts/]!,$#@..............@>-;{^sHLDDHz]!;,#.........@$-']/zstxszrrzsAyz^]~;$&...................................", +"..+&>-~{F^IKKKIQ2[2[^QrKrKzIF~&...$'([6wwwOQ|';,>,-;)][/IrIrQ]-+..@*,;)}rKKKJsKKKKKJwwwJIr/]~-&..+&*=;)]FQIJYwwwNwOJKr^^[F(!-*&...&>=-;'(1::[5ONSwP4:|((_!;,*@...@$-)FIKzKr^F(~---!(26wwYP[|~-%...+#=-)F^rIzIr^/]1]F^rKKzI/F~-@..@=-!{[PwwNwJJOSNNNwJwwwNwOK2~*.....&*>=-!(F[IPwNNwJPQ2]~;->*+.......+%$-;)}IKJwNNwOPI2(!->*@.......+#$,-;~)|F^KKJKKKQ}(!;>$#........&*>-!1%@.........+&=-;~((F1(___(]1](~;-$%+...................................", +"...&*-;(|}Q58O85<5<5<,>=-!(}[[QQQ2),+..&#=-~:QKIIPPOJJ8PJ6PKQ[:1~3*&...+*=-;'(|[<5888O888855<-9'~(|[OSRY5:('!;-,=*&@...+#-;|[&....@#-;_:}[[QQ[:(((}[Q[[[2:_,#+..@*-c_:5OwNwOO86M86OJOYNNSO7|!*.....+@*>,-~_}QP66O65<[1_'-=*&+........+#=-'(:Q5YNNM6Q:(!-=*@.........+%*=,;~(1Q6JJ8I[}1~;,>*&........&*==cd30abbf77h5imnqZqqqqifc9$&....+%#*==99afgqWUjib_09->$%&+.....%-cb4hh54fba9->3;afiqWqpfb0=@....&**3a|f44hkhfebbe7hk4feda-#....&>9afiqWUWWqjmgiipqWUWUWjgba*.....+&*=-9ab7hhm6m6lhkfdc9=*%.........+&*>9abfiqqUqifba;,$#@.........@&#=-;ab7ijWqjifbda;3=*%........@#>,cbijUWjgdc,*&..................@%*,9adbeijjgbc,$*@+..............@*,;bgpWWqibc9>#@..........+&%*>>,-=>,>==,-==>*#&+....................................", +"...&=3ae4kmqUTTTUTUUWZXXVl7ed,@..+*0d7pqUUql7:da'00db[kVVlVhkb,+.+%$,9_4hVXXZZWUUUUWnll41bac3=&..+@*>330d|e47kklVXoWWUUWWjga9=&.....+&#$>-cdfiqUUqpfdc3>$#%@.....@$3~ekVVVlke(c9399afpZWWpgea3%....@#>3ab44klV.....+%*,9abeklVVVVVVVl4edc3=#+.........@*=cab4iqUTqpebac,*&+........+@#>>3a:7hnZWUom4e|d03,=#@.......&*=9abiZUUoibc9=#+..................@*=90d:7moomfdc3>*+.............+#*30dgjWUqjfa9=*@..........++&%#*$$$$*$***$>$#%&+.....................................", +"..@$;~FryAHDEEEEEEEEELCCCAsrF-&..&-(^sGvEELHxszr///rsAACCBCAxr'&.+*,!)/stHHHGEEEEEEEGHAAsrF)'-%...#>;~{F^zsxytCCCBGLELEELGsQ{;#......+#>9')FztLEELAK^{~;=$&+.....%,~FzABCCBAsr]{~)]^stEELvyzF'*...+&=-!]^sxACCBAxsxACCBtysr{!,@..@=!{^stEEEEEELGBBADEEEEEEGAK]-...+%$-;~{/rxACHHHCCBCCxs^]);-&........+#,-~]^sGuEEEGK^]~;,*+........@*,;')FztAGLEEvHssz/F{~!,#.......&=;~FKAuEELyK]~-=%..................+#-;(F^stGvAs^F{!-$@...........+#-;~{rxGEEvAKF!;>%............+&#%#**###*##*==*%+..........+++++&&&&%@+++&&&&%@+.......", +"..&$;)FzxtHvLEELLELLGGCCAAzF)-@..@>)/KyvvGHHHAssrzzsxCCGGCCCsF;@+@*-'(^sBBHHCvvvvLvLvGCAsz/]!-#..+%-;{FrzssyxABABCCvGLLLLvyr]'*......+%>-;_]IyLEEEts/]~-,#&+.....%-)FzyCCCBtsr/]{{F^JHLLLHxrF'*....@#=;)/zsACCCAyyABCCCysr/{!*@..@>;{/sAvLvuELLHBBCHLELLLvvxz]=+..@*>-!)]rzyCHCHCCCCCCBsz/{!-*.........&=;!{^KtLEELts/]~->%+.......+#=-;'{^sBCGDLDvAxszsr/])!$+......+*-~{ItLvEDAr]~;=*&..................&$;;{/ryBCBsz/]);-#...........+#-;)FKyvDEutz]~;,#...............+@@@+.+++@@@&&@.........+@&*#%##$$$**#%##$$$**####+...", +"..@%>-~1//IPKJ6KI5I5..+&$-!)2IKJJKJKPQKPPOwJK[F|~;=%...%>;'F[Q/^/F/F^[QIIPJwNw8<1~-#.......@*=-;~:#&@......@=-~]QKzKrQ/F__~~(1[Pwww8Q|~-%.....@#=-!)]QPJJK^^QKJJK[])!->&...+#=-_:QPJJwwNwPIQIJwNwwJPP[{;%...@$=-;)(F[IJwJPIIIPJwKQ/|);-#.........&#=-;_:%@......................................+@&%#$$$*=*$$$$>$==*>>$**%#@...", +"..@$=-!(:2QI5I<[[[222|(_;;-,*%+..+%=3'|[QI5OOJ5Q[[QQ<6YSN6<:_;%...&*-;_:QIII-'(:}Q5OY8<[}Q6OOP<}2|'-$+........@%>-!_1*&.......+@%*,-!(:$>*@...", +"..@*=9ab44hiVih777ffeda933**%&....&*=9affhimqomiiikhipqqqjgf09#...%$90bfhmmmi44feffipjjphg7ba;%...%3ab4immh7eeeeeeffgpZWWjgbc3&......+%*=3;dfijUUjifac9>*&@......+&=;dekhhk74febbbbfgiqqoifd;,@......+%$>-0fippmiiimjpgbc3>$&+...+%$-cdfhlmmoophf77ioqqmmk7ea>&...&=-cdfgiijqqpg7fgiqqpmigfbc,@........&*=9abfgqTUqifd0->$#+.......@*$90dbgiqqjmhh74f7hmlihfa,+......+#*30bgqWWjied0->*&+...................@*>-0b4474eeda-$%..........+@%>-9abgqWWqiba-$%+.....................................+@*=,339c0aac0c;9000c0cc99,>#...", +".+%>;a:khVmnonmlhkk4ed09,>$#&@....@$>9ade4lmXoZqoqoXVmppppi4b0*+.+#-0b4inooonmh74efhmonoXopifa>+.+=9bfmoqqjmkhkkkkklmoWUWniea3%.....+&*>30begjWTUWph4dc3>$&+.....+#=90eklllllhkkkhkhlmnnXifa9=%......+@*=3abhXnopqooXmkea9=#%+....%*30b7VlXonnmhk4kVnoonXXlfa3&..@#30bfijqqqqnmlkkhmnoooqqphea*.......&*=9ab4ijqTTUjgeb03,*%+.....+&$-a17hmjWWomVllhhlmoZom7b9%......@&$3cfiqUUqmh4{a3>*@...................@#=3~b4klllk7|a3#+.........@#=-0dekmqWUqpea9=#@......................................#,;ad(b1ee2ee:e:eeee4ee:bdc>@..", +".+*;)/stCCHvDvvCCCtxz/('--#%+.....&=3~{FrsxBHDEEEuvGCCCCCAAsrF=+.&>!]rsADEEEGHAtszsxAHGDLvvts/;@.@-]rJGuEEuGCCCBACACCDEEEDyKF'*.....%=-~{/zyBvuEEEvttzF{;-$&+....+*-~]rxACBCBCCCCBBBBHHHCtz]~,&......+&>;~FryCGLEuEDGBxrF_;=%....+*-!]ryCCGHGBBBxsxBHBGGHCts/!*..&,)/zxuuEEEvHBtAttBHHvEuEvAsF-.....+&=-;)/zxADEEEEGBxz/)'-$&.....%>;~/stBCvEEDHCCBCCHGLvDHxr{*.....+%=3'{ItEEEEGAtz/{!->&..................@*-'{/zxACCByz/),#........+$-!{/zytGLEEEwz:~;=&.....................................@-)FrzsyxAABtxtyxtyBtBBByxz/~#..", +"..#;)/sACCCvLLGBCABsz/);-$#.......&=;!(/rsyBCvLELLLvBGBCCCAyr{,@+&-!]rxHGLLLGCCAszzsBBHvLLLGxr;@.@-{rsGuEELGCCBCCCCCHLEELGtr]!*....+%,;)]^stCGEEEuvCxz/{!->*@....+$-']rsAACACCBBBCCCCCCCCyr]',&.......@$-!{ryABvEELvHAs^{~-=&....+%-~]ryCCBCBCBysytBCCCBCCBzF!#..#-)/sAvEEELGBBAyytBBCvLEuDAs/-+....@#=-~{/sACDuEuLvByz/{!->#@...+#>;)^sBCCHLLLBCCCCBHLELDvyr)=......&*-!{IAvELLGCAsrF);-*&..................%=;)FzyBCCCBs/);%........&$;)]/zyCGLLEDtzF~-=@.....................................#;(/zyyABABCCBBABBABBCCABysr)>..", +"..&=;_FrKJJwwwJKKr^}{';=$&+.......@&$-;)12KJwwOOJOwwwwwwJJI[]!*..+*-!{2IJwwwJKI/F|]}^IPJwwOP[|-+.+$;([6YNNwPKKIKrKIKKJwwOP[(!>&....+&*>;~{FQKJwNNSJKQ/(~;=*%+.....&*,;)]/^rKzKzKKrIKKKKKI^|'-%.........@*,;':QKOwSwOKQF'--*&@.....&=-;{/QKsKKKI/}FFQzKsKKK/F~>@..@=-_1<6SNNwJKI^//^IKJJwNwOI[)$.....+&*,;!)2^IJwNNwOKQF_~-=#@.....&*,;)FQKKwwwOPKKzIKKJwww6[|;&......@#$-;1;_(}<6MMOPPJYwNSSYYO<}(-&..+%=;_1#&@.....@#=,;~(1[QIIIQQIQQQQ[[}|~-=%.........@&*,;(}[P8OO5[}_;=*%@......@#*-!|[QQIIQ[:((|}[QQIQQ2(;*+..&*3!12@......+%*>,_25OOPPQ[}('-,$%+..................+&#$-0|4OwY84_->&........@*>-'(1[QP68O6[d;,*&......................................&-!(1}[QQIIIQIQQQQIQIQQQQQ}:!*..", +"..&=9ab4hlllmVllhh41ac,$@+.........@#=3abfijWqqmmpZWUUWWWjied3&...&=cdb7kllmlhkfdaa_dbehhli7fd>+.+%>;dfg5i5hkllllhhhhh74fba9,#......+%>-0a:7hlm5mPlh7eda;,*%+.....+&*$,-c_e75hlhllhhh74ebd;=*&........+@&*>9ab4h5l5hfba9>#@.......+%*=cde47777ebdade777k77e0c*...+*3abfh5mmllh4:bb:7hlllmlh7ba*......@*,30be7kllmmmlk7fba;>*&.....@#*-cde47hlmllhlhlhlVllh7ba>........&*>9abhhmlhhkfba;=$#@..................+&%$=9dgpWWpga-*&........@*,90(e4hlVllhea3>*&+.....................................&3abe7h5lihl5ll5h5l5lk5khh4e0$..", +"..&=9d:kllVlVVVVVh7ed0,*&..........+%>c_bfhqWWoXXnZWWUWWWom7b3@...%>cde4hVlVVhked00c0b:7llkked,+.+%-9de7khllVllVlVVVlk4fbba9=&......@%$99dbklVVVVVVlk4ba9,$%+......+%*=-9abkhVVVlVlVhk4eba9,*@.........@%$=9abfkllh74|ac=*@.......@&*>9de4k7k4ebaaab47774eba3%+..+%3~bf4hVlVllkebbe4hVVVVVk7b0*......@#=;adekVVVVVVVlk4bac3*&.....@&$,0de7klVVVVVVVVVVVVVl7b0$+.......@*-9aehVVXVVkke(09=#@...................@%*>9agoqZjga9=&.......+%=,cd:4lVVVXVl7d0,$#+.....................................%9(eklVXXXXVVVVXVlVlVXVXVVl4d$..", +"..%,!]/zsAytyAAtAsz/]);=&..........@*-~{/rxtvvHABBHvLvLGvtJrF-&..+*-~]/rzyxtysz/])~){{^zsssz/{,+.@$9_{/rzssxxyAAtBBtysr^F{~;=#......@#>;'{/zsttBtAtxsrF{~;$%+.......&*--')FrsxAABBAAxsr/]);>#+.........@#>-;)F^zsssz^F)!-=%.......+&$;!{/rzzrr/]{)]F/rrrr^F);#...+*;(F^zsyAAtys^/F/rsxtAtysrF~=......@=-!{F^sxttAtAtyz^]{';=#+....@%=;'F/rsxAABABAABtAAAtyz/)=+.......&=-~FzxACCBCBxz/{~-=&...................@#=-!|IxvGxI{~,&.......@*-!{FzsACCCCBtsF);>*@.....................................*'/zxBCCHCBCBCCCCCCCCBCBCCBsF-..", +"..@$;')F/rrrrrrrr^F)~;-%+...........%,;~)FIzsssssxyAAByyyz/])-@..+&,;~){F/rrr/F)~;;;!){]F/F]{!=+..#-;~_{]/^rrrrrrrrrr^F{)!;,=&.......&$-;!)]/rrrrrrr/])!;=%+........+@*,-!)]/rrrrrrrr/F)~'-$@...........&#>;!){F/F/]{~!-*#@........@*,;'){]F]{)'!!!))){{)));,%+..@#-!))]//rrrr/]))){F/rrrr/])-@......+&>-!']/rrrrrrr/F))!;,$&+.....@&=-')]/^rrrrrrrrzrrrr^F);=........@%-;)^yABBBBtsrF{!,*@....................+*=;~F^rzrF);,&.......+%-;)F/sAAABAByr]!-=#@.....................................*'FrstAACCCCCCBCCCCACBCBCAtz{=+.", +"...@#=>-;;'''!'!;;;,=*#+.............@#=,-~(|(()()]]]F]:{)!-$%.....@#=>--;;';;--,>>>>=--;-;->*&...+%*,,--;;''!'~~~'!!;;-=**&+.........+%$=>-;;'''''!;-,##&+...........@&*=,-;;'!''''!;--==%+............+@&**>--;-;--==*++..........+&$=,---,-,>====->>->,=$%.....@#$>,-;;'';;;--->-;;;';!;-,%.........%*>=-;;'!~!'!;-->$*&+.........@#$--;;!!'~~~)~'~~'!;;-$&.........+*=-')]FF]]{)~;->%+......................@#==;!__';,=%.........+%*-;!)]F}F2]{~;=*@+......................................&=;~){]F}F2/2//[/[/[/2F2FF{)>@..", +"....@%***>>>,>>>=>$$#&+..............+@**=-;;!;;;;'~_'~!'c-=*&.....+@%**=>>=>=>*%&&%%$***=*=#&......&&*$===,=,,>=>,>==**#%+............+&#$*>>,,,>=>=*#%+...............&%%*>=,>,,>=>=*#&@+...............++&*#*$=***#%@.............+@%%***$%#**#&#%**##&%&+......+&%**$=====*=**$**>==,==$%@.........+&%$*$>,,>,=>=**#%@............+&%**=>,,=------==>=*#@...........@%>=--;;;;-,=**%+.......................+@#$=,-9->$&+..........@#*$,-;;;';;-,=*&+.......................................+#$>--;;!!!~~_~~_~_'__~!';;>#...", +".....+@##**$***$*#%@@+.................&**=,99->>-9;c9c33>>$%@.......+@%###$###%@..+@@%&%*##%+......++@%#**$***$***$*#&@@+..............+@&%**$**$*$$%@+.................@@&$*$$**$%%%&@+...................+@%&#**#&&@@...............@@&#&#&@+++..+@@+++..........+@&%#####&&&&@&&&##%#%%&+...........+@&%##$*$$*$$#&&@+..............+#**$*$*$*$******#&&+...........@&$*==,-,>>$*#%@+........................+&#$==>=#%@...........+@%#$*,,,-,,=$#&+........................................+%***=,,-33-339-9333,333-,>=#...", +".......+@&%&##%%%%&@...................@@%#**>**$*,>,,,>>=#&@.........@%%%&&%%&&+....@+@@@&&@.........+++@@&&%%&&@&@@@+.....................@&&##%&&&&@...................+++&&@&&@@@@+......................++@@@@@@@@..................++@+........++...............++..++++++.+.++.++.+...............++@&&@&@&&@&&@+.................+@&@%&&&%&&&%%&@@+.............+@%##*==*=*#%&+..........................@&%&###%&+..............+&&%*$=$**#%&@..........................................+@%***>$*=$========$=**=**%+...", +"..........+@&&@&&&@....................+.@%#&%%&%%#****%%#&+..........+&&%@&@@+@+....+....................++.++..............................+@&&&@@%&@.......................+++++.+.........................+.++.+..+.......................................................................................++@+@+.++....................++++++@@+++.+................@&%##%#*#%#&+++..........................+&&&&&@+..................++@%%*#%&@+.............................................+&%%**#*##%*%#*#*#**#*#%&....", +"..............+.....................................+..+..............+++++++..................................................................+..+++++.................................................................................................................................................................................................................+++.++++.................................+.+...........................+........................................................+....+.+.+...+..........", +"................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................", +".................................................................................................................................................................................................................++++@+++.......................................................................................+...............................................................................................................................................................................................................", +".....................................................................++@%%&%@++..................................................................+@&&&&@@+....................................................+&%*#$#$*##&+.........................................++&&&&&@++..............................+&%%%&@+...........................+@&&@+.................+@&%&%&@+..........................++&%%%&%&&+............................................................................................................", +"..............+&&%&&@@.............................................@%#===>,>=*&@...............................................................+&*$=====*#%&@..............................................@&#*=,,3-3,3,,=*%@.....................................+&#*=,,3,=*#@+..........................+@#*===>=*%+......................+@#*=>=*##@+............@%#*=,3,=*#%@......................+@&*==,,3>==*%...........................................................................................................", +"...........+%$$,----=$&+..........................................%=-;;~){)));->%@...........................................................+%=,;;~){))!;->$&...........................................@%=-;')){{{]{{{)';,$@...................................+#--;!)){)~;;,*&+......................+@*>-;;'~~~;>$&+..................+&$-;!)))!;-,*&+........+%$,;!~){))!;-=&...................+@#--;)){{{{)~!-#@.........................................................................................................", +"...........%$--;!~'!-,*&+.........................................%>;~)]//^^])!->#@..........................................................%$-;!{F/^/F]);-=#..........................................+#=-!~{F//rrrr//F)~;=%...................................+#-!))F^/^F)!;-=%+.....................+*=;!){]FF])'-=%..................&$-;)]F//])!--=&+.......&*-;~{F^//F)!;-$%+................+&*--!)]^/r^^/F);-#&........................................................................................................", +"..........+%*--;!''!-,$#@.........................................&=;~(2[5*@.........................................+@*=>;!(F}[QPPP<&...................................+%-;)|}<<<[('-,$%+.....................@#=-!~1[;(4<;~}[5QQ}(!->*&+................+&#=-;(1Q#&@........................................................+%=,c(4565Q[}(;-*%.........................................+%#$-;(}[QI8OOYYO67(;=@...................................+$-~1[58O652~;,=#&....................+&#>;~:[5Y65e;-$%@...............+@%$-!f58O6<:~;>$%@......+&$-c(9;abe4fbd0-*#+........................................&>cb7ijqqjgfa;,$%&+.......................................................@#=3cbijomih4ea3*#........................................+&*==;ae4iimjqqoqqpgb9>&...................................@$9afgmqZoigbc->*%+....................&*=cdfipqqjga3>#@...............+%#$-agjqqjifdc,*&@.......@*-0fgjqjmi4ba->#%@...............+&=39abgjqqWWqjf09*%........................................................................................................", +".........&*,cdegmppi4b09=#@.....................+@@@+............+#30bflXnZnl4:ac,**&+...............................+.....................&*=,cabhmnXVVl4b03#+...................+++.................&%>9cd7hmnnonnnnnpiga3>#....................++@+...........&=9dekmnoXmkedc3>*%+...................#*9ab7lXoYmgdc=*@...............&%=,cd4mnZnl7:a9>$@......+%*30binnXXVk4ac,=#&@+..............@*,0ab7mnZWUWpgdc,#+......................+@++............................................................++...............", +".........*-']rsHDuEDxz/);=*@.............+&%%%*%$=*$#&+...........*;{/zxHHHHCxs/{~;->$%%@+..............+@&###*****$**$*%&@..............@%$,-')/KxACBCCCxr]'-&..........+%#*#***%#$*#@+............@#=-!{/ztGvELvGHHBBAsQ{'-*+.........+&%###**#*$*$$*##%%&+....#-)FrsCCGCHAyr]);--*%@+..............+@=-~FrxBCHBHs^{;,&.............&#=-;~]QyAHHBHxzF~-=%......+$,!(/sBHBHCAs/)';,=#$#%%@..........&$3'(/KxADLELDx[{;-&............+%###*#***$=$$****%%%@........+&###****#*#*#*##*&+..................+%##*$*=$#*%&+.........", +"........+#-!]rytDuEuAs/{;-=&...........&%#*=,--->----=#&@+.......+*;)/zyBBBCABsrF)';--,**%@+...........@%*==,----;-----,-=#%@..........@%#*,;;~]FryACCCCBAzF),&.......+&&#$>,-------->=#@..........@%*,;)]rxAGLELLHCAAysz/{;-#.......+&%##=>,-------------,*#@..+&-!FryACCBBBxs/{~!---=#&@+...........@#-;)FrtABCCAs/);-#+...........@%*,-!)FryCBCCAyzF);,%......+#-;)FzxBCCCByr]);;-->-,=*&.........@#-;)]rsAHLLLGyr]!-#+.........+%#$=,----;;----;----,*#&......+%#=>-,-,--------->=$%&@+..........@&%%$$----->--,,=#%&+......", +".........&*-!1[5wNNw52|!-*#@.........++&%*$>==,-=,,==$$$%@+.......@=;'][rKKKIr^}{~;-->,=*$%&..........+&*#=>=>,--;-----===*%@+.......+&%%*$=-;;~{][^IKKKK/]!-$+.....+@&###$=,>---->,>=**#+.........@%$=-;)][IJwNwwPI^^[F1);=*&......+@&#$$>>,>--;;----->==>$*@...@*-!(FIKzKKr^F|)';-,=*$#%@+..........@%*-;~]2rKKKIF(;,*&............@#$>-;~(][IKzKQF]~-=*&.......&*>-_]}^IKKK^F_;--,,=>>**&+.........+%$-;(1QPwNwO[_!-*@.........+&**=>==>-----;------,>$*@......@%#$=,,,,=>=>>>=>,,>**%&+........+@%%*#==>,,---,,,=$*%%@+.....", +"........+&*=3!b<6OY6<2('->%@.........+&%$>---;;;;;;;--=**%@.......&=-!_:QIIIQ[}:((~;;;->$*$#&+.......+&*$>>--;;;!!~~~;;;-,=*%@......+&%*$=--;;__(:}[QIIIQ[(!-#+.....@%#$*>---;;!!;;-;-,>*#@........@#=,-;_:[Q5OOO6<[}}1|(!-=*@.....+@%$**=,--;!!!~~!!;;;;--,$&...+#=;_|[QIIQQ[2:(_~!;--=$#%@..........&$>,;_|}[[IQ[:~-=*@...........@#*=-c!_(:}QIIQ[}(!->#@.......@#>,;(:}[[QQ[|~!;;;;;--,>*@..........&%=-;(}5MNR87_;=*&.........+*=,---;;;!'~!!!;!!!;;-,*#+.....@*=---;;3;-;;;;;;---=*$%&+.......+&#$$=,--;;'!;;;--,=$*%@.....", +".........&%$39afgipig7ea-*%@........+&#*=9;aaa|bbbdda0c,>#&+......&*,;de7hllhh74febb_aa;3==$%@.....+&#$==3;aa_bbbbbbbbdda0->*@.....+&#$=,-;adbbeef7khhllh7bc-%.....@%$*>,3;aadbbbbdda0;,=$*@......+%$,cadb47llmXmmhh74eeba9=#@.....@%*$>,3caddbbbbbbbbbddacc3#...+&*30b4hllhh744eebbda;3=$*&+........+&*=30db47hk74ba->*&+.........+&$>3cadbee7khh47fbd9=*@.......@&$=ca1e4kkh4bbda~dad0a03=&..........+&*>9cbiqWWjgdc,*&........@%>9;aadaddbbbbebbbbbbda;,=&....+#,30a~d_ddaaddbddda09==*%@......@%#*=,-;aa_dbbbbb~cc,>$%&.....", +".........@%*>90b7llVlh4bc3*@........@%>-cab1e444k774eeda3=*&......@*3cb4lVVVVlllkhkk74ed~093=%+....%*=,ca(be4444kkkkk7444bac,#+....%$,;'a(be47kkhhlllVVVVke_3*+...+%*,;'0_b4444k74k44:da03==%+....@*=cd1ekhVlXXnXXllhkk4ed;,*&....@%=99!ad1e4477kk7k7k7k74:d0$+...%>9_bklVlVllhkhkk74eba09,$@........&*>c0(e7kllll4edc,$%+.........@#>9a1e4[kkllhllkk4ba9=#+......@#*30b44kllVk4eee447ee:ba3$+..........&*,9afmqWWogbc9>%+.......&=9_be44747khhkkkk77474eda3$+...%=9_be47744e4474744e|dac3=*&....+%*,;'a_be4447kk74eedac3,#&....", +".........@*=-;~/KxtAABsr{!,%.......&*,;)/rsxAAHBHBBAAAs/{!--%+...+#-'{rxBCCBHHHHHHHBBAAyzr/{!,&...@$;!{/rsxyBCCBBBBCHAHAByzF)-%...&>;~FrzsAtCBHHBHHHHGBCCtzF'>+...&,;)/rzsxABCBCCBBBtxsr/]~;>&....%-']rsxACGHHvvvGHCCBBts^{;,*...+#-;{/rzsAACBCBBCCHACHABtyr];+..+$;)FzxCCCHHGHHHHABBAsz^F)!>&......&$-!{/rytCCHHHts^{;-*&........@#-;{^zxtACACHHHHHAAz/);>&......%=-;{^stACBCByxsyAACAysz/);%..........#=;~]KtEEELyI{!-$@......@=;{/zytBBCBHBCHBCBCCBAAAsr]!#..+>!]rsxABABtAyABABAAAxzrF]~-$+..+%-;)FrzsytBBBBBACCAysz/]);>&...", +".........+&*,-')]rzsyxs/);,#+......&=-~]zytBHGGLGLLLGLBs/)!-$&....&>!{^sACCHvvLLvGLLLLGCBts/);*...%-!)/sxBCHvHCCCBGvLLELuGs^{;*..+%-;]rytBCvGLLvLLLLLGHBCAzF),@..+$-!]rytBCvvHCBCBvDGCBAsr]~-*+..+*-!FzxCCHHLLLLLLGBCBCAxr{'-#+...*-~FzyABBvGCCCBHvLLvLLGHts/-@..+$;)FzyCCCGLLLGLGLLGHAyzrF);*......+=-'(/zxBCHvLLHxr{!-=@........+#-;]rxABCCCBGLvLvGHs/);>#......@*-;{rsyBCCCBBABCHLvHBAxr{;*.........+&>;~]IAvEuvyr]!-=&......@=']zyCHLLLLGLLGLvLLLLLGGBxr{>+.+='FzxCGLLGCBCCCCCCvHHAsr/]!>&..+*-!{rytBCGGHCBCCHGGCBtsr]'-#...", +"...........+%*=-;'~{]F]);=#@.......@*>-~FQKKJwwNwNwNwwOQ|!->*&....@$=;)/IKKJwNwNNNwNNwwJKK/F!-%..+%=-~F^KKJwwwJJKJwwNwNNw8<|~-&...&=-)F^KKJwNwNwNwNNNwJJKIF'-*...+%=;)2^IKJwwwJsKJwwwJJz/}';,%....&=-~F^IKJwwNuNwwJJzKzr/|;-*&....%>;(/IKKwwwwJzJJwNwNNNwJK[)-+...%>;_]QKJJwwNNNNwNNwwPI}F(;,#.......%>-;)]/IKwONNOI|;-*%+.........@$-;{/rIzKJJwwNNwwOQ1;,*&.......&$,;)F/^IzJKrQ/PJwwJPr2{!=#..........@#>-':5wNwOQ|'-$#+......+#-)FQJwNwNNNNNNwNNwNwNwwPIF~$..+*;)2IJwNNwJsKsKsPwwwJK^}]~-=@..+%=;)FQrPJwwwJsKJwwwJKKr1);,%...", +"............+@**>--'_(_;,*&+.......@#*-~1[QPJwwwNNNNNRO41';-*@....@%>-~:[QI6ONNNwNNwNNYPK<[1~-%...#=;_1[%...#,9_1[QPPwNNNNNNNNSOJPP[|!-%+...#=;_1QIPJYSO8PKPOSOOII[:_;,#+...@*='(}QIJwNNNNNROKIQQ[}(;=#@...+#-;(}[IKJYwJPKP8RNNNNNw8Q}_=+...&>-'_}QIJONNNwNwNNNR6Q[1(!,%.......&#--~(}QI8SNNR<1;,*&..........@*=;(}2QQIKJwwwNNSO7_->*@......+@*=;_(:}Q=3c_a9>$&........&*=9de4hinqZWZZZWZqogeac9>&....@#=3a:7lVmoWUWWqZWqqommlhfd3%...%,;dfhlmXqqqmlhmpqUTTTTjgb0>&...%,;bfkimpqWZqZoWWUWjXmk7bc-#...+#-cbfkmmooWqpmlmoqopmlh7d;,%....@*=;de7hpoWWUUUqpi<77e1a9=%@...@*-ab7himqqqqphmpqUUTUWqphf0=....@*30d4hlmnqWWWZWqWWqmh7f:a3#.......&*,30df7ipWTUqgbc9$%+.........@$=9d1447hlmoZqZWWjgd3>*&......+@#=3ab:4hiVihhiijqqp77bd9>&..........+&*,cbgqWqjgd;,*&........%>cb4mnqWUUUUUUWWUUUUUZjmgea>..+%-0b7pqWUWqnmmmlmmoqoi47eb0,@...%>9bfkimpoqpmhlmpqopmlh4dc,#...", +"..............+@#*>999;3=%@........@$3'dekklXnooZooZZWqm7edc3#+...@*>c04hVXnnqZooppnXooonomhea>+.+$9aehmnonZopmhhhmnqTTTTqiea9#..+$9dfhXnonoononnooZooXVVhe_3*+...$9dflpnonooXXmlVXnoooonkfd9*+...@#>cabfklnooZWqqmhk4eeda3>*+...%,cb7innooooXmllmoZZZZZnmked>+...%=3a1kVlXnXZononnnooXVlh4:c$+......@*=9cd:7kjqUTUifa3=%+.........+&>30dbe4khlpnooZWqib0,*&+.....+&*>0_e7klnooXpnjqoolkeba3=&..........@$>9afiqUWqgb03=%.......+#3ab7lnZZZZZZZZZZZZZZZoXVVkb,+.+#,ab7loZZZonXmmllmnnnVVkked,#..+$cdeiXXonZoXlhklXnoonomifdc=+..", +"...............+%#>---;-=*@........%,!]/zxtBCCCCCHCDLLvAysrF',&..+&>;)/sAHHvGvCHAyyAHBHGLDDtsF;+.+-{^sGDDLvGHBtxxsAAvLuuuuxKF;$..+-(rsGvLLvHHAtxtCCvCHHCBAzF'=+..+-]rxGvEEDGHHAAABCBHGvDDGxr]-+...%*,;)FrsxHHGGvGCAssr/F{~;-$+...$~FztHDvDvHHtysAAHHGGGHCAs^(-@..+*-~]zABCBCCBHBAtAHBHHBCCxzF-+......@=-;~{/zsGEuEuwz{'-=&.........+%=-'){F^rzsytBCvLvtI]'-*+.....&*-;{^sxBGvLLEvLDvHAys^]);>&..........@$;)FztEEEvxI{'-*.......&=;{FzxCHBGHGHHvCHCGvGGHHBCyr;@.+=!{/ztHHHGBHCCtxtAHHCHCBAs^)$..@-{rsHDEDGCHBxysAACCGvLDHyr];#..", +".................@%#$**%#@+.......+#-;]^zsyBCCCCCCCCLLLHxszF)-%...#>;)/stCBCCCCtssssxACLLELGs^-@.+-(/sHLLLvCttzzzzsytGEuEGy/{!*+.@-]rxHLELvBBysssxACCCBCCtzF)-@..&-{IyGLLLLHCBBABCCCCLLEuGyr{-@...@*,;~{/rsACBCCCCyz/F])!;-$@...+$'FzAvLLLGCtyszsyACCGCCCxzF),+...%;)]zyCCCCCCBxssyxBBCCCCAz]-@......+%$-;){^sAvEDvtr]~-=&..........+%>-;!){F/rzsytGLLyz])-#@.....+$-!)^zyBHLLEEEELGAAsr/{!-$@..........&=-~}KAvEEvyr]'-#+......+=;~{rtABCCBCCCCBCCCCCBCCCCt^;@.+=;)]rtACBCCCBAysstABBCCCBy/)=+.@-]rxGLELvBAxszzsytCvEDLGyrF~*..", +"...................+@.+............@=-'{F^/KKJJJsKJJwwRPQ2]_-=@...@$>;~/IKKKKrI/2]1F2[IOwww6}(-...$'([6wNwJQ}F{)_){:}QP65<2_;=@..+=!([6wNwJQ[2]1]2^rKKKKKQF)-*...@>'1<8NNNwwJJPJKJOJwwNNR8[|'=.....@%*-;!1F^IrKzKI/:);;,=*%&.....#-_:-;(:5ONwO5|!->*+...........@&##=>--'_(]2[POO<1!->%.......@=-;)F[IJwNNNNNw8Q}|_;;,*%............%>-~:5wNwO<('-=@........&=-'(2IJJsKKKKKKzKKzKKzIKrQ],+..%=-'(/IKsKKrI/F]}F^IrKKKr[);%..+=;1[6wNwPI2]]|{]2}Q8www6Q|~-%..", +"...................................&$,;(2QIKPOOP6IKPYSM5[:_!-*@...@%=-~1[IIQQ[21((((|:48RSO5:'=+.+*9_15YNR841_~;;-;~_|1}}1_;,*&...*c(}POSY541(__(_:[[IIIQ[|!3*+..+=;(g8NSNNMYYRRRSSSSNNNR64(;*+.....@#*=;~1}QQQQQ[1_;-=*%@+......%-;(78SNY8<[}1|1}QIIKIIQ2(;,%....%$>;(1QIK..+&*-;(:QIIIQ[}1_(((:2[III[:~-%..+*0d}6YSY52((~~~~_1[5RSY84(;-&..", +"..................................+&*-0b4hlmoWWqnmmpqWqigfba3$@...@#=-ab7hlhg4fbbaaddbgpqWqie0>..+$9depqWqpfbaac93990dbbbd0c,*@..+$cdfpqWqpfbbdaddb47hllh7ba,#...+=cbgjTTTTUUUUTTTTUUTTTTjgbc=......@%$>9a174hhkk4ba;,$#&+.......@=;dgpqWqnih4fffghmpmmlhfd;=#....&$,;d4hlli4febaadbe4hhlh7b0*.........@%*=3;bgjWWqgb0-=%@...............+@%#*,;0bfpqjgd9,*&......+@*=30bf7pqTTTTTqigba0-$#&@...........&*>90bgqUWjgdc>*&+.......@$=;0ehlmhhk7khhhhhhhh7hhhfd>...&*,;0e7hlhh4:bdadb:47hhlhea3%..+*cdgiqWqifbaacccadfiqWqpfbc,&..", +"..................................+#=9~ehVXXZWWZonnoWUWph7:dc=&...%*30d4lVVXVk7e:bbb|fhpWWZpgd,+.+=0b7pWUWogeba09-3cadb:bbac3$&..+=abgjZWZpkebdbb:4klVXXlhe_9*+..@,0fgqTTTTUUTUTTTTTTTTTTqgb0=+.....@%*,cdekllVllked9,=$%@.......&>3a7poqZonpmmimmnZZnnXVkb03%....&=3aekVVlVk4e|bbbe4klVVlh4a>@........+#$39abioWUqpfdc,*&+...............@&$>,cab7pZqib09$&+.....@#$3'be7hnWTTTTUWp74b_93=%@..........+&*,9afiqWWoieac>*@.......&*,cd4hVlVlllllVVVVhllllllkb,+..@*3ab4lVVVhk4ebdb:fkkVVVl7b9*..+=0bhnWWWphbbda_ade4pZWWpiba3#..", +"..................................%-;)^stHvvDvDvBCHvLEEGBxz^{;%...*-~]rsAHHGHCAyzrrrssHGEELGs/;+.@,]QsHvELGtsr/])!~){/rzrrF)!-%..@-FryGEEEGAszrrrsxtACHGHts/)=+..@-2IwuEEEEEELELEEEEEEEEuuJr:-@.....%=-;(^sACBCBCts^{'-->#@......#9~FrAHHHGDDuvDEDEDDGGGHyr{!>+..+*-']zxCCCCAtsz^/rzstACCCts/;#........@=-!(/zyEEEDtK^]~;=#+.............+&*=;!{/rsHDvtKF'3$@.....&*-;{^stAGLEEEEEEGAtz/{!;=%+........+#>-'{[stEEEvxK/{;-=&.....+%-;{/sACCCCCCBBCBCCCBCCBCCtr;@.+#-)FrxACCBBBxzr^rzxABCCBCyr(>..@-FIxvLELHysr^^/^rzxGLEEGyKF'$..", +".................................+%-~]rxHvLLvGHCCCCHLELGCys/);*+.+#;)FrsACBCBCBxsrrzsxCvELuGs/;@.@-{rJGLELLAyz^])~))F/rzzrF{~;*..&-{IsHLuLvAyszzzsyBCCBHCAsF)-@..@;]rxuEEELvvBHCHCGGvLDvGts/(-@....+%>-!)/sAABCBCAs/])!-=*%&.....%,;{^sABCGvLLDuvELLvvHCBtr]'=+..+*;)FzyCCBCByzrr^/zsACBCBBs/~*.......@#=;~{/KtGDEEAs/]~;-=*+...........@&*=-;){/zJtGDyr]~-*&.....&=-'{rstCBGvLLvvvvGCxrF)'-$@.......@&$-;~]^JALEuvAzF{!;,*&.....*-;)^sBCBCCAACCCCCCACBCCACxz;@.+#;)FryBCCCCtysrr/zttBCCCBtr{=+.+-{ryGLEEvAxzr^^rzyAvLLLGxr]'*..", +".................................+&=-~1QJwwwJI[^[/QIJOwPQ[F_!,&...&=;'{/QKKKKzK^FF]2^IPwwNwP}(>+.+$;([PMNNOIQ}|)';'!)1F2]]_~;=&..+>;1[8wNNOII/2FFFrKzKKKKQF_;*+..+>~:QJwNNwJKKIIIQIQIIIIKQ:);*......@*=-!)FIrKKKrIF|~;->$$&@.....+#=-'{F}QI8886O8JOOJJKKK^]!-%...+%=-~]/KKKrQ/F1){(F/QrKKKr[);%......+&**,;!(2-;'_2PwNNO<}_!-,=*@.....&=-;_/KKJKKrrIzKKzKzIrKzKK/F,+.+&,;)][rKJKK^2F(((]F^IKzKK^]'*..+=;1[8wNNOPQ/](||}[POwNwJQ|',&..", +"..................................&$-;148wSO54}::1}[6OO<[}|(;-%...%=-'_:[IIPI-;(:[QQQQQ[2(~;--=*#&......@%>,3!(|2[[<[[[[<-;'~1$#@.........@%$$$=>-;~(1[6M67|;-*@......&*$,;(1}[QIPPI>-;_(:$#+....%==;_}[IPP+..&*-;(1QIPP<[2()_((}}[QIIQ2|;$+..$;_28YNYO<[}:1(1:[QORSM52(;$+..", +"..................................&*9cbgpWWqpgf7ffggjqqphffbc,%...%=-0dfhmmpXmihffffghmoqWqib0$...%,abiqZqnmh7ffbbbbff7f7fbba-@...*9afiqqWjikffff7hmmnmmi4fdc>+..+$3afpqWqqmihg77g7ghhilhfbc,#.....&*=,;abf7hhlikh7bbdc09,*#+.....+&*=-30dbffff7777hhhlhhedc=&....#>;db7ilihgffb(dbef7hiVihfd9*....+@**,-0adbggqTTqigbbaa;3$&........+%**,,9;cadbfgmjjgd;,$&......@*=9abf7hhlmikhhmoWqigfbd09%......@%*-;cabffiqTUqifb_ac9>*@....&=-0dfhlmmlh4hhhhhhhhh4hhhhb,+..%=;abehmmmi47bbddbf7hilik7ba=...%3afiqqqjmg4feff7gipWqqpfd9$+..", +"..................................&=3aegoWUWommimmmoqWWopmi7d;%...%,0b4hmnoZZooppmimmpooZqjif0$+.+#3aeiXoZoXmmiiiiiiiiimmhkeb9#..+%;aeinZoonmmmiimpoZooonmked,+..+%9afioZZooonpppmXmmXnnmhea9*+...@*=9_beklmjononpmih74eda3*&+.....@#$,c0de4k+....@&=3_be7gijqWTTqjih74eda,#+...%,0d4hmoonmVlllVlnnnnVVVnpm49+.+#,ab4hmnonnmiheee7lmXooonh4b,@.+#3afmnZZonXmliiimXXoqZqifac*+..", +"..................................&,']ryDuEEuvLDuvvuEEEEDDHxI(>+.+$!]zABDDEEEuLEuvuDEvDGGGAs[)=..+>;{/yBHHvLvLDDGLvGLDLDGGByr{=..@=~{rsCHHGLLuvvvDDEEEvEEvAs^'&..@>!{rxHHDvvEEDuDuDDDDDvDAsF'=+..+%-!]rxAHGLEuEuEDDDGHtAs^);$@.....&=-'{/rsxtCACCCCCCCCBBs^);$+..@-)^xtvuLuEuvGxssxtDvEEuEvty/;+...%,;)^stBHGuuuEuEuuDHAAxr{-#.....+$-']/rzsyxBBBACHHCs/);-#+....+$;'FsADLDGHCAtxtAEuEEEGGtxz~%...+#-;{rytBvuuuuEuEuEvABts/)-%..+=;FrtHvEELvHCCCCCGvuvGHHvDDJ(@.@>'/ztHDuEEvDGtssstvDuEuEEGtz~@.+>!{rxBHBGLvuvvvDvuDvHGHtr1~,@..", +"..................................@>;{^sGvuEuDuLDuLLEEuLGuDyr{-..+>;FrxHGLLELuDDLDDLLLGHCByzF'$+.+*;)FzyACHvLLLLvuDLGuDuDvtxr{>+.+$;)FsxBCGGDLLuLuLLLLLuuvBxr;&..+*;)/sxACHvDvLDLvuLuDDDutzF'>@...*-~]zyBBHvLLEEuuuDGCCAyr);-%.....%=-~]/zsBBBCCBBCCCBCBxzF';*+..+>)rsAGuEuvuDGyssyAvDLvuuDHxr-+..+#>;)^xBBHvEuEEuEEDGHCAyz]!$+....&$;)FrsxAABCBCCCBCts/);>#+....@$;~}zwvGvHCBAtssxvEuuvuDGAz]$...@$-']zxBAGvEEuuEEuvvHCAyr)-*..+$~FzAAGLLLGCBCCCBGvvvHCHvvvx)&.+>)/sAHGDLuuLLAxsxAGvvuEuLHAr~&.@*;)/ztACHGLLLuLuDLvvCCxs/);$@..", +"...................................%=-!|[5P666J68O666JO86P<4(;%...#,!1}<588O666686668PIQ[2]_;=&...&*-;):/[<56P8P6K8668P8P<[:~-%...&$-;)]}[I6686JO8O8O6O6P,;~|/^rKzKzKzKKKr^/F);,=@...+*-(:Q<6O6J65<[::2Q566J665Q})>....@$>;)F[[IP6OOY6O66PII/F(;=%.....&*>;_F///rIzKKKKIQ[|!,$#@......&>-'1QP6PII^/F::4<668OPPI[];&....&$-!{F[Q<66OYY6OO8PIQ/]);#@..+%>!12<6686IIQ^QQQIPPPQQIPP<4;+..%-'][QP66J6PP[}:2[-;'_1:2}}}[[[[}[}2:1(;-=@...+&*,-'_(|22[[4[[[[[[4[[:(';*+...@#*--;_(|}}[[[4[[[}}111_;,*&+...@#=-!(|:}42[<[[[[[}:1(~;,*&.....@#=-;_1}QQQII;(1[[QIIIIIIQ[:(!-=%@.......&*>-!b}2}21(__~__:2}}[4[:_!>@....@**-;_(|}}}}727[4[21|(~;=#+...@$-!(:2[[[2:11|1}}4}}2::}}}_,@..&=-!(:}[[[[4}:___|2[4[[[}:(;=...@#*,-;__|:}[}[[[[}e1(_;9-*#@...", +"...................................+%*,300dbbbbfbfbbbbbfbba0,*&...&*,90abbbbbfbbebbbbbda9c-=*&....+&*=,,390dbbbbbbbfbbbdda;-=*+...+&*>=390abbbbfbfbbbbebbba9-#.....&#>,33cadbbbfbfbbbddaac3=#@....@%>-9addbbfbffffbfbbda;9=&+.....@#=3ade45llhllmmlh7edcc,$*@.....&=3cabbffbbbd000adbbfbbbbd0-&....@#$$3c0adbbb1fbfbebbda09=*@.....@*>cdf7hhhhllllk4ba;>$&+.......@%$-;abbbbdaaa9c0abbbfbbba;*.....+#$,30addbbbbfbebbbbdac3$%....@*,cadbbfbbb(b(dbbebbbbbbbba=..+@*,c0dbbbffbbd000abbbfbbbda9#....&#$,-3cadbbbbbbbbba0;3=>#&....", +"....................................&#*,ca_dbbbb:bebfb:bbba9-=&...@$>3;adb1bb(bb|b:bbdac9,=$*@.....+&#*,-9c0bbebe:b1bbdacc3,=%+....+%**>-cadbbb:bbb:b|b:bdac3#+....@##$,,30ad:b:bbebbdaac3,$#@....@%*>c0ab1b:eeeef1bbaa09,*%......@*>c_b4kVVllXXXXml4ed09>*%+.....%*,cadbeef1ba'9c0ab|be:bda0>&....@&%>,9caab1bbb:b:bbdac;3=%+.....&*=0b43;0adbb:b:bbebbaa0;,=&...+&*>-cab1be1dbddddbb:bdddb:dc$+..@*=30adb:bb:ba0330db:b1bd_0,%....@%*$=399abbfbbb1b003,=>*%+....", +"....................................&$=3;_(]//[//[///[///F{~-$@...@$-;~(]2/2F]F}////2]_';3,*%+.....+&#$>-;!)]2//}^//2F:{_';->%......&#*--;)]/[////[//}///](';=@....+&#$33;~(]/}////2F1_~';-=#+....@#,-'))F2/^/rzr^^/F{)~!;-%+....+&=-)F^sxBCCCABCBAAsr]~;-*#@.....%-3!){F/^^/](~';~{F//}//F)!,&....+%#-;'~){F2^/[F[//F{)~!;-#+....+#-;)/sxAABCCBABxzF)!-*&........@%*-!{F/F])_!;;;'_]/^^^F]);*......@*>-!~)]F[/[/////F{)!';>%...+%=-;~(F^^^/F]]]]]F//F{{{]F:)=...@#>;~{F}//[FF{)'~)F}/[FF()~;#.....&#>--;_)]F[//[/]{';;-$#&+....", +".....................................&$=-;!))))_){{{{{()))!;=%+...+&*,;!))))))){)()))~;--,#&..........@*>>;;~))){){){))!;;-=%+.......+&*$-;))))_({))){){)~!;-$@.....++%*>,;!)){({){))~;;--$&+......@#--;!))|)]]{F]]{)~;;-$%%+.....&*,;)]/zsysxysyssr/]);,*&+......+#,-!))(]{)~!;;;;!_{){)));;*+......@%=-;!~){){{{_{))~';->#@......%$-~]^zzsyyxyyzrF{~-=#+.........@*>-~)))~!;----;'~)(]){);,%.......@#>,;!~)){){({)))!;;,$%+....&#=-;~){{)))~'~!))())'!!)))-#+...@*-;!))){)_)!;;;!)_))))~;;$@......+&%$,-!))_){)~);-=#*%@......", +"......................................+@@&#==-,->-=,>--===##@.......+@#*==,==>=>->>==>*%&&+.............@&#$$>>>>=>>>$**%&&+...........@@@&$=,,>=>,>=>====#&@+.........++@%#$=>=>$>$$$%%%&@+........+%***>>->--,-,->>=##&++........@#=>-;~)))))))));;,=*&+..........&#$=,,>>==>****==>=>==>*%+........+@@##==>==-,>>>===#&+........+&*=--'~))))))';-,=*&@...........+%*====>*$$*#**>=>,->$*%%+.........&#*==>>->-,-=>>=**%+......+@@#*==->->=>====>>>,===$**&......+&**=>>,,,==****>>->===##@...........@##=,-$=$**%@@..........", +"........................................++@@@@&@&&%@%&&%@@@+..........++@&@&&&&&&%&&@@+....................+@&%&&&%&@++...................++&@%%%%%%&&&@&@@+..............+@@@&&&%&@+.+.............+++&&&%&&&&%%%&&%&@+.............@%%%**$====>=**%%&@.............+@&&&%&&@@@@@&&&%&@&@@+............+.+@@&&&@&%&@&@@@............@&&%%##$$***$#%&&@..............++@&%&@@@+@@@&&##%%%@++............+&&&#%%##*%#&&@&+..........+.@&%&*#%%%%%&&&&@&%%@@+++.......++@&%%&%@&@@@&&@&@&&&@@+..............@@@@%@+++.............", +"..............................................+...+..........................+........................................................................+...........................+........................+++...++...................++..++++++++++......................+....................................+...+...................++++..+++.+++.............................+@@@@@++.................+..+@&@&&@@@.+..............+++@&&@@+@++.+...+....................................................+...................", +".....................................................................................................................................................................................................................................................................................................................................................................................++............................+............................................................................................................", +"................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................", +"................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................", +".................................................................................................................................................................................................................................................................................................................................................................................+@@++..........................................................................................................................................", +".............................................................................................................................................................................................................................................................................................................................................................................+@&#*$==#&@.....................+%#***%@...................+@#***##@+..............................................................................", +"............................................................................................................................................................................................................................................................................................................................................................................@%%*$3c99>=*&+.................+&#=3999=*&.................@%#=9c;,=#%@@............................................................................", +"........................................................................................................................................+@@&%#&@+..........................................................................................................................................................................................................................&**>,30dda9>=*%+...............@%#,;addac,*%...............&*=>3cdd093=>*%+..........................................................................", +"......................................................................................................................................+%*=>----=#%&@.....................................................................................................................................................................................................................+%>-!~)]Frr/)';,#&..............+#-;)]/rr/{!-=@.............@*-;')Frr/])~;->%@.........................................................................", +".....................................................................................................................................@&*>-;;!'!--$*%&....................................................................................................................................................................................................................%>-!)]F/rzr/)!--*@.............+%$-!]rzssr]~;-#.............@*--!)/zsz/F])!--#@........................................................................", +".....................................................................................................................................@%$,-;;'~'-,$%&@...................................................................................................................................................................................................................@#=,;~|F}}/}(;-=*&...............&*>-_2IPIQ|;-*%..............&*>,;)F2/}F|);,*#@........................................................................", +"....................................................................................................................................+&$=-;!~(1(!-*$%@...................................................................................................................................................................................................................@#*,'(}[[[}:~;=#&+...............&*=9_48OO5:!,=%+.............+#*=-_|[[[[}1~->#&........................................................................", +"..........++@++................................+@++@@@++@++..............++++...................................++++...............+@#>-ca(beeea;,$*#&++................++..............................................................................................+@@+++.....+@@++..................................................+@+++@@++++++++...............%$>;dfhhhhfea9>$&+...............@$>9dgqqqjea-=%+..............&$=3abfhkihed;=*%+.......................................................................", +"......+@&#***######*##&&@+...............+&&%###********%##&+..........@&%*#&##%*#%#%%%&&@+................+@&&##*##%#&&&@+........+%*30d:44kkkedcc,=*#&@............+@%%#%@+.....+@&%%@+............+@%#%#%%%%&&%&&%##*%#%%@........@@&%%%#&&@++...+@&%%%%@.........+@%#%**#&&&&&%#%**#&+..........+@&%%%&&&@++..+&%%%%%%&+...........+@&#%************%@+............+&=3abhmonV7:d;=*&+..............+%*,0biqWWqgdc>*&.............@%#>3d:7innXifa9>*@.......................................................................", +"...+%%=----;-;;;;;-;-;->$#%&@+........+%##=---;-;;-;-;---,,$#+.......@%*=,-;------;-;-;--$*@+............@%$=,--;-;;-;--->$%@......&$-~]rzytBBBsr/{)!;-=$%+.......+%*=>----$##%%##$----,=*%%@.....+&%$>-;>-;---->--,--;;--;->&.....@%$=,--;-->=*=###$-------*@.....&*$$--;----,->---;--;-$*@+....+%%$>------==#$#$$>-------$%+.......@&#>---;-;;;;;;-;--->*&+.........+%$;'FstEvvHs^]);>%..............+&=-'1KtEEEDxI{!-%.............&*=;!{^stDDDGs/)3,%.......................................................................", +"...@#,-;!!~~~'))''~!!!!--,>*#@.......@#*=-;;!!!~'~~~~'~'!;;->%.....+%$>--;''!!!!!!!!!!!!;-,=%+.........@%*>,-;;''~!!!!!;;;--=&.....#,;)FzsyBBCAyz/F{)!;-,=#%+....@*--;;;;;;-->,>$---;;;;--,*#&....@#=-;;!~'!~!!;;;;;!!!!~!!;-=@...&$>--;!!!!;--->----;;!!!;;,#+...&$>-;;''~'';;;;;;'!~';;-==#+...@$,-;!!!!;;---=-,-;;!!!;;--=&......@#>--;'''~'~))~~~''!;--=#@.........%,-~FJAvuvHs/{';=&..............+*=-!{IAGELGyr]!-#+............+&=-')FJALLLGs/);=#.......................................................................", +"..+%*=-;'!!~~~'~'~~'';;--=$$%@......+&*$>>-;;'!!'~!!~~~'!';-,#.....+%*,-;;;;;;;;;;!''';;--=*%+.........@#$>,-;!!!~!';';;;--=*&....+%*,;)F/QrKzK^/:{)~!;-=$*%@....@*=,-;;;;-->==>*>--;;;;-=>$%@....@#*,;;!'!!'';;--;;!!'!'!!;-$@...@*>,--!'';;-->==>>--;!!!;;-*@...&*=,-;!!!!;;---;!''!!!;-=$#@...&*=,-;';!;-->===>,-;!!!!;--=&......&#=,-;;!!~~~)_~'~!;;;-,>*@.........@*,-~[6www5}_;-=%+..............+&#>-'15wNwO<('-=&..............+&*,;!2IOwwO[_;>*@.......................................................................", +"..+%=-;_(1111|({:1:1(((';--=*%+.....&$*,-;;~((1::111({:1{|(!;*@...+#*>-;~_)|{1)__)(||(((~;->#@.........&*=--!~(1{::|)((__~;->%+...@%>-c|}<=--c_|)(~!;,*#@....&*>;!(b|{b1||_!!!_b{1b1{1_'-#..+&*,;;_(b||(~;;---;;~(1b1)~;-&..+&=-!~(b:1b1)~!!_)|b:1b|~;=#@..+%,;;~1b11(_;-->,-;~({11b(!;,#.....@%*>-!~((1:1e1e:11{1(~!;=*@.........&*,3ae5MSY5:~-=#&...............+@#*-;(3;aabe4gimppikgiijiigbd9&...@#=,adf7giiiffefgihig4edc3*&........@#>3cabe4iijpig7fffeba-*@...@#>9aeijqqqqqjjjjppigba9,*%+...%,cbegipied03-3cafgig7fba;=*@...+#,;dbgijppijgebdbeipppijigbc*..+#>cdegimiigebaa0adbegipiigbc*..+#=cbgimjpiigbbbfgpijmiiea9*@..+%3abgiipigebac9;0degiijigba;*....@%$=cabf7gijpjpjjjpig7fbd9>@........+#*-cafpqUqiea3=%@...............+&#$9cbijWWjgd9=*&................%=3cbiqUqjgdc-$@...............+@&#&%###&%&@&@@@++.....................................", +"..&,cb4ioqWZomXXoWWonVlkeeba9=%....%=3cde47hVXoqWZnmVXqWWomhe0*..+@*>c(7klmoqomkhhmqZnmVh7bc3#+......&*=3cd:4hmoZWWoXVVllkkea,&...&*3abioWWUTTUUWWWWWqmgba9>%@...#cb4ioqqqmebda0dfiqopVhkedc=%+...*9dfkmqqWWWqoi777iqqWWWWomhb,+.+*cdehpqWqomh7eb{b4hhpqWWjmhb,+.+*3agjqqWWWoi7f7ijqWWUWjib9,#...$_ehmpWWonh7ed_db4hmoqWnphea>+...@*=-aeklVoZqWWWqWWWqnVhkea>#........@*,9abgjWUUpfa9>$@................@*=90fiZWWogbc3$%+..............+#=9afjqUUqibac>#+...........+&&#*==>>===>=*==>=**#&....................................", +".+$!]zxHGDEEvCGDDEDvDBCAtsz/{;$...%,;{/rsxACCGDEEEvGGvELEDHts/-..+*-;]rtCCHvDvHCCCGDEGHBCyz]',&.....%$-!)/rstBHGvEDDHCBCCBtsF~$..+%-~FKtvEEEEEEEEEEEEEGyzF);-%..+>{zyADEEvGxzr/^^sAEDGHCAy/{;,@..+=)^yBGDEEEELDHxtAGDEEEEEvvAz'@.+-(rxBGDEEDCCAszzsyBCHvEEvHtz;@.@-)^JDEEEEEEHAxyBDLEEEEDwr:;=..+,FsAGvEEvvCAszrrstBHvEEDDAx/;@...%,;)/sACCGLEEEEEEEEDGHCtzF!$........#,;)/ztDEEvGKF~;=&................%,;~FItEEEvyr]~-$@..............@$3~:KwEEEvAs/{;-*@........+%#,-;;'))~)))~~'~~~!;;;-%+..................................", +".+*!]zyCGLLLvGGHLvDLHCCCCAyzF~$+.+*-)]rsxBCCCCGGDvGvCvLLLvHAs],+.+%-']rtACHDLvGCCCvvvGCCBAzF);*....+%-!)F/zyBCHvLGLGHCCCBCBs/)$+..#-~]IyvLEEEuEELLLvLvAxrF);$@...>(ryCHDLDHysrr^rKtHvHCCBxr]!-#..@,)/sBHLELLLDHAByAHGLLLLLvHAr;@.+-)^yBGLLLLBCByssstCCGLLLvHAz;@.@=)^sGvvLLLvHAABCvLLLDvGtr{;$+.@-FstHLLLDHCAyzzzyACBLLLLGBsF;&...%-')/sBBCGGLLLLLLLLLvBBAsF;*+......+#-!{/syGLLEAsF~;,%................%,;)FKyLLELyr]~-=&..............@$;~FztLEuLts/]~-=#+.......%=-;!~)]F///FFF]{]]]])~;;,&..................................", +"..&>;{}IJwwwwwwJJJJJPKJKJKI[|;*...%>;~2IKKPsPJPJJJJwwwwwwOP[]~$..+@*=;{F^QPwwwwwJJJJJPsKK^F~-=&....+&>-~{F[IKJwJJJJJKKKzKzI/)-%...@*-;([8JOwOOOOJ6PP85Q|~!-=%....$;{2IJwwwP[2{((1:QPJJKKr^{!-*@..+*;)}QPwwNwOJPI[/[IPOwwNNwK[1-...*;)}IJwNNwKIr/Q^^QIKJwNwwP[{=+.+*-_}<6JOwwwPI[QKOwwOJ65[(;,#..+$!:[PwwwwJKI/F:F[IKJwwwwPQF~=....@*-;(FIKKJJJJJJwwwwwJKQ/]'-&.......+&$-!|[5OwNw6}~->*@................&*=-~2-_e5wNwwPQ:!->%@.......+&*=-!~)|}[[}}:]_))_]]1)!-$@..................................", +"..&$-!|28OwwwOO6<[[QQQIPOO8<|;*...#>c([8Ow65QQQ[[IP6OYRwO6<1_,#...&#>-!(12>#&+...&,_|[8RRM5[1(_a_(:[QQKIQ2(;,*@..+%=;(15OSwO8...%>c~:2Q56YO6[}[3c|%..................................", +"..+#,cdfhmppppig7fbee7hpqWqigc>...%-abiqWWoi7fffef4mmpnmni4b0,#...@%*,;abfijWUWWqqmg44774ea3=#......&$3ae7hmnqZpikhhhhlhhk7ba,%...@#*,;df7kkhlhh4eebbba9,*$&@....#>cbfpqZqmg:bdaabb77hhlkfb;,*@...#,9abijqZomk7feef47inqWqjgbc*..+*,cbfpjWWji47hlmhhghpqWqpgfc$...%=9adefhponig4gijopi7fbac=*@..+#>cafgmmmjppgfbeginjXmihfdc,&.....%=-a17hhhhhhilmmoqqigbba-=&.......@**3ae7moWWqiec9*&+................@%*30biqqUjgd9-*&...............+%=30biqWWomhea->%@.......&*>9~bf7gpjopihg77f77kh7b0,&..................................", +"..+#,cdfhVVXXVVkeeeee4hnWUWj7b,@.+*9dgpqUWqm441eef4hVVVXVV7ba3%...@#$>9ab4ioWWWqopi4ffeeeda9>&+....+&=3deklloZWonpmmVlVlVh7:c3&...@#$,0dekhlVVVkkeeb_a09,>#&+....&30b7mXoomk4bddbb4klVVVVk1a9*@..+@=;abhXoonmVlk4e4kVmnoZophb0%..+%90d7mXZonVlmmoonmllpoZZnhfd$+..&*,cabeglnoommmmoXXh7bdc3>#@...@=90:7klXnZom744ioZZmVh7ba9=%....+#=9ae7klllVmnjoooqqi7edc3*@.......&$>9dellZWWqpfac>$@................@*>30fiqUWqgb03>&+..............@#>9ceiqWWZXl4dc=*&......+&=3afhmmmnZoononpmmlVVVl4d9#..................................", +"..+$;~FzACCCCCBxszrzzsADEEEvy^!@.@-(^svuEEDHsszzzsxACCCCCBs^{;*...@#=;'{/sADLvvHHAszr^//])~;-%....+%=-~FrxBHGvEEDvDvHCCCAts^{;*...@*,;)FzxBCCBCtxz//(~';-,$&@....#;)/sBGBCCtsz^/^rsxACCCAAz]~-%..+#-'{/sACBGCBBxssstCCHHHCtz2~*..@>!)/zAHGHHHBvDuEEGHBHHHGHyr],...+$-!)FrzxHHvDvDGGHBsz/{~;-=@...&$!{^sxtHGvDHtyttDDDHAts/(!,&....&=-!{/zxytBCHEEuDDHHxz/]~;>&.......@=-~FsAHGLEvAJF)3=@................&>;~:QAEEEvyI]'-=@.............+#=;~{rtDEEDGts/~->*+.....%-;{^xHuvvGGHGvDuEuDvHCAAs/)*..................................", +"..@$;)FztCBCBCCBszszsyAGLELGx^;&.+-{/JAvELvHxsszzsyCBCCCCBs/);*+..+#=-!)/ztvDDCAxsz^F]{))!;-$%....+*=;'FrsACvLLEuLLvCABAAyz^{!*...&*=-'FryABCCBAsrF{)!;-,=*%+....%-(/ztCCBBysr]FF^zyACCCCxzF)-%...&$;~FryBCCCCBAssyABBCBAysr];*..+#;)FzyBBCHCHGEEELGCCCBCCtsr)=+..+*-;)]/zstCGLLEvHAxs^]);-$%+...+#>~FrzyAGLLvCACHGGHByzr]~-#+....&$-;)FrzsyABHLELLGCtsrF]~;$@.......@#-!{ryAvLEDHzF~;=&................%>;)FKALEuDxr]';*@..............%=;)FKALLLGAyz]'-$&+.....%-']IyGLLLvBCvLLEEELvHBCBs/'$..................................", +"..+&=-):^KKJPJJIQ/}[/QKOwww82(-+..#;)25wwwOPQ/[[/QIJJJJKKr[);$&....+%$,-!1QJwJK^}]_~;-->>**#@+.....&#>-'{/^KJwNNNNwwPK^^//F(;-%...+&*>-~{F/rIzI/})!;->==$%&@+....@>;)2rKKKI/F(_')(]F^QKKz[F';=@...+&=-'(]/^IKKrQFF//IzKr^[F);=&..+&=-~]^KKJJKKJYSNNOPKKJsKIF(;%....@*=-;'{2QKJwNNwPI}F~;-->%+.....+@*-')|}I6OJOOJOJJ5[F(!;$&+.....+&*,;~{]FF[Q8wNNwJKQF1~;-*%.........+%=-~:QOwww6}_->#@................+#=-_:@...............@*>;~:5wNwOQ}(;-$&.......@=-!|&.....@**-;d46Y8<}1(';>=*$*$%@.......@#*,;(|}[KOwwSwOOP>$*$%&@....+%-'([QIIQ2|(~!!(|}}QQIQ}|~,*+....@%=-!(|}[QI<}}:1[-;_2Q88RRRY8<}(;->*&+.......@$*-;_(|}4<6YSSO5[}|_'->>&+.........@*>-_e6RSO5:;-=#@................+&*-;b*$##&@.......@#*,;abefgimVmXmpnjmih7ebc,&...+@%*-;dbe4khk4bd0;-,=>***%@....+%>cb7hhh77ebddadbe4khlh7ba3#.....+%*,;abb7ipmg4ffhppifbdc9=&....%*,;afhhllllpqWUUqqjpmmh7ea,%....@%$,;0de7ipWWWjmkfba;,>$&+.......+%$,;af7ijUTUqigea9,*%@........@**-cdbfgijjjjpmh7ebbdc9>*+.........@#=3afjqUqiec3**@................+%*,0bgqUWjgdc=$@................#*-0biqWqjfd3=#&+.......+&*,cbgggheeffgigihi77b1dc-#...................................", +"..+#=9aehVVXoWZZnpnmXnXooXpgb;%+..&=3afinnnXVlVVlmnZZoXXVh4b0,%....+#>,;afhoZoikeed!c3>**%%+.......&*,9abe4kkklVVVXXZZZnVlk4d9#....@#*3ab4[hlVlkeb(a~c09c3>=*&...+*9_ekVVVlk7ee1b:4khVXVVk4dc=@....+@*=3adfhnZomhkhmoom7ba;=$%....&*,017lVXmXnnZWUUWWZoXXVhea3&...@#$,30_e4hVoWWWZmlk4dac,=#@.......@#=99bekmqUTUqmkba9=$&........+&$,9'b:7ioZonXVlh444ee{ac=#........+&*>3afjWUqpfac,*%@...............+*,30fiqUUqgbc3*&...............+#,9aeiWUWogb03=&.........&#=90bbfbbbbbffefff4ebdac,%+..................................", +"..+$;)/zACCHHHGvvDvvGHCHtysQ{!*...@>c{^sxtGCHCCCCCHGGCCBCByr]'*...+#,;_]^stDLDAAssr/{);-,*$@.......#-')/zxtBCACBCHCGvLGvHHBy^{=....&=-!{^sxACHHAyszzrrr^F])!-$+..@='FztCCCCCAyssssytBGGGHAsr]-#.....&*-;{FrxHvvHHBHGDDtK/{'-$%....*-!{^xACBGvvLLLLLEELGHBCtzF;%...%>;'{/rxtCGLEELDGHByz/]);-*+......%=-'(/stCGEEEDys^{;-#@........@#-'{/zstCDLvHHCCCAxtyyzr{;*........@*,;)2JGEEEGK/{;,*@..............+%=;~]KtDEEvyQ);-%...............%-;_[VwEEEvJr]~-*+........@*,;_1///}//}/}//^//^F]);-%...................................", +"..&*-)/sABCCCCCGvLvvGCAtsz/F)-*+..@*,!]/zsyACCBBCBCCBCCCCAsr]!$+..&=-~]/zyALLGCBtxsz/]~;-,*&.......#-!]rxBBCCCCCCCCCBHGGGLGtr(>+...+%-;(^zyAHGGCBtyyAAyxzr/]!>%..+>'FzyCCCBCBByyxABCCGvLGHyrF~#.....+#=-!{[zABGvvLvGHHAzF);-$@...+%,;{/sABCBGLLvCHGLELLCCAAz{;@..+*-!{/zsACGGGHHHHGGCAAsr]~-$%.....@#--']rsACHGvGtsrF);$#+........&=-~FzyACvGLvCCCCACBBBAtz/~=+.......&*,;)/KALvuts/)'-=%...............%=-;]KyvvLvy/);-*+.............+%>!{/sALELGxrF~-*.........+%$-!~)){))){)]){]]]))~',*&...................................", +"..+#=-~FIKJJJKKKP6PPIQ/:{)!;-#&....@#>c'){F2^QrQIrKKKJJJzI}{!-&...&*=-)|};){}IJwwJKIrQrKrI/[]_-=@..+*-!{/KzKzKzrQ^/rIKJwwwwJQ:)-&......+%*=-~:QIPwwwNwKI2(!-=%+.....+*=;~]/IKJwwwPIQIJwNOPI^/{;*+..+&=-']/QKJwwJQQIPJwwKI/2);,*@.....+#=--~{[IIKPKKQ}(;-$&+.........@*=;'FQKKwwwwKKrKrrzzKzr[{;*.........&*-;_}8Mww6}_;->*@...............@#$-;1>>>=->-,--,--==*#+....................................", +"..+&,-~|[QIQQQ[[}21:|(_~9--**%......&#$>-;!((|11:}2QQIPPI[}_;>&...+$>;~:2[5OYO6Q[[22:(!;>$#&+......%*-;|[QIIPPIIQQQQQI6YNNY<:;*+....@%$-;(|[5OYP$&.....&*>-;_1}[III-~|[#@..............@&*-9_:5OSR8ea-=#@.............@@&%%&&&@&%*#$$#%%@@+.....................................", +"..+%,;ab4hhlhh7ffbbda0c99>$#&@......@%*$=3390addbee44ilmlke0c,%...@*,0bf7kpqWqmhk774ebac3=#&+.....+#*,0|45lllmlhhkhhhipqUUjibc*.....@&*,3adfiqoplkhkhhkk74e03*@...&$,0b4hhhVlih7hhhlmoWWqpgba-@.......+%*,9af4ijWZopl7b0->*&.......@#*30bf7ijqjgffgiqqphfeb;,*+...%=;dfghioqqigf7ioqomhh7bc,*&....&%=3adbe7hilllh4bc-**@..........@#=-ae7hmjqWomhhhh5hllkked9#.........@*$,0fiqWoiedc-*#&+..............@@#>3abkhh7bc3*%@.............+&#=3cdfiqWqpf0-*#@.................+..+.+@@&&&&+.+.......................................", +"..+#,a14lVXlllh7e:bdac9,=**#&........+@#$$>-cadb:e4khVVVVl7ba3#...%,9d7kmmoZWqoVlhlmh7ed03=#@.....@&$-c:kVVVVXlXmnmnnnnjqqjgb9%.....+%*=3cbfinonmnmXXVVlk71a9=@...@*,9de4kVmXnmmmlmVXZWWWoke03#........@*>9ae7lnoZZnh41c,*#@.......&%>3a1f4inomh7egmoomk4ed03*@..+*3afkXmooZomk74loWZonmi7bc,%...+#>cdeghimpnXonXhea9>#&..........&*>9deklXnWZqnnmXmnXmVVl4d9*.........@#>3a7pWWWphbac>$#@..............+%$=3aekllkb0,>#@.............@#*>9db7mZWWjgd9>*@........................++++...........................................", +"..#-)/zxAHHHCCCtssr^]);-,=#&@.........+&*=-;!{FrzsABCHHHHBAz/)=..+*;(/yvDDuLEvGGCHGGvAs/]~-=%.....&#-;)^xCCCCCHvvDvvDvvvGGxK2)$......%=-;~]/stGGDLGvHCCtxz^]!-@..+%>;~{FrstCHvLDDGGHHvLELDts/'*........&#-!{/zxHHHHAszF);-#+.......%$-'{/zsxAHAyzzzyHBAssr/);$@..+>)/sGDDvvvHAAxxHvvEvvvHy/(;*...&,~]KtDvDEEEDvDDAKF';=*+.........%>-~FstCCGLEvvLDvDDvHCCAs/!$.........@$-!{KAvDDGyz^{!-=%+.............+%=-;{rxtys/);>*&............+#=-!)/zxGDLLAK:)3=&.......................................................................", +".+*;)^sAGvLLLvGCBssr]~--*&+............+&*>-!{/zxxCGGvLLLvBtr(>+..*;)^JGGvDvLGHCCAHvGxz/]~-$&+....+#=;)/sAACBCBGGDLvLDGAxsz^];#......+#,-!~FzstGvGvGCBtyzr/);*+...+$-;'{FrstCCvGLvHCBGvLGGAzF!#.........#>-;{/zxBBAyz/]~-$%+.......+%--)]^rsttyzr^rsxAxsr/])-$+..@='1zwGLDHCAAssstGvLLDDvy^);*+..#-'/swvLvuuuEuvutz]~->&+.........&=-']ztACHvLLLvLLGLGHBAxz];*+........@*-;)[sAHBAAyrF~;,#@..............@*>;~]rzz/{!-=#+............+#-;'_rsABAGAyr{;-#+.......................................................................", +"..%-;|[PONNwwwwJK[}]~;$#@................@#$,;)F[IPwwNwNNwKQ]'*...@=-~1<56P6PIIQQQ<<<2(!--*&.......&#=-')]F/[[[Q565655<[1();-$@.......@%*=,-_(}Q<85IQ2F{)~!-=&.....@#$=-;)1/[I5P6I$&+.........+%*-;!){{]{)!'!({]1))~;-*&....%,!|[55KIQ[/]1:}<55655[:0-*&...@$-~2I8JOOOOOO8P<1'-=#+...........%*,;)]}^-;|2Q[[}1(!-=*+........................................................................", +"..&$;_}[POSSSYO5Q}:~;>*&+.................&*=3~(}[IOwSNSY852(;*+..+%*-c_(1|||1((((|(a'9->*&.........@%*,-;;~_(((|111|1(_;--,*@.........@&#$=--ca||1_(!;;-->=&+......+&*=>-;_((|111((((|||_;-,#+..........&%$==-;!'!c->=#+............+#**,--;---->--;---,==#&+....&$>9'_|1((~~';;0_1111(_9-*#+....&=9a14[[2<<[<[}|';=*@............+%*>-;;_(111|||1111(_';->*&...........+%#-9!_((|(~;-**%+................@%#>$>>=$*&@...............@%=>;'||1(_~;-$*@.........................................................................", +"..&*3abfgimipi5g4b1a9=#@..................@#=3cdbfgiipipii4ba3%....&%$,,3c00000ccc;c9,>*%&+.........+%#*>,-39ccc;cc0;cc99>**%+..........@&#$>>,39;0cc,,>$*##@.........&#$=>39cc0c0c00;c;993>*&...........+@%$$=,-3,>=$#&..............+%#$*===*=$>>*,,=>$##&+.....@%*>,99cccc3-,,399ccc39=>*&.....&$,0abfbfffffbbd;3*%+.............+%*$>,99c0000c0c0cc9,,=*&+............&%$33c00a0c=>$&@..................@@#%%%%%@.................+&**,9'ac0c9,>#%+.........................................................................", +"..&=30d:47hhhkk4ebd03$%@..................@#$,0ab|47khhhh7fba3#....@%**,,-99c9c939,,,=*#&+...........@%***==,,,3>--3>-,,,*$#@............@%%$*=,,,,,,,****&+...........+&#$,,3-399933,33->=**@............+&#$$>$>==**%+...............@@&##$**%*##*#%*#%%@@......@%#*=,3,,,,,>>=>,,,9,,>$*#&....+&*39dbeeeeeeeeba9>*&+..............@%*$=,3,-3-399c99,,=*$#&............+@#*$=>--3-,>*%&+...................@@@&&&+..................+@#$=,3-93,,=*%+..........................................................................", +"..#,;)]^zssyyxsz^F])!-*#+.................@#=-~{F^zssysxssrF(;*....+&#$>3,9;;;;-,---->=#+............@%%#*>>--,333-3,---=*#&+............+&#*=>,>,3---=*##&+...........+&*=>--,--;;3;,-,-=$%#+............+@#**===$$#&&+.................+@&%%%%&&&@#%##%&++......@&##*>------>==-----3-,=##@.....%>;_F^rIrrKr^^/{~3$&...............@#%*$------->-;;---$###@............+&**=>------,$%+.....................+.++.....................@#=>--->--=#%&+..........................................................................", +"..@*,!)]/^zzrz^/{{~;>*&...................+&*>;~){F^zrzz^^/{'-&.....++@#*$$*#*#$$$**%%@+...............+++&***=$$==$$*#%#&@+...............+&%%%$$*$##@+................++&%%***$****$**&@@+...............+@&%%#%&@.+..........................++.+..++...........+.+&&%*%*%%##%%%#%%*%##&+......+%>;)({{]]]{{()~->#+.................++@&#**$#$=$****%%+................+&&&%*#$***%+.................................................+&**#$$**&@+............................................................................", +"...+@#*=---;;;-->$$%@++......................+&#=>--;--;---=$%+............+.+.+.+.+........................+.+..+.................................+.........................++...+...++.................................................................................+.++..+..++..++............+@#*$=$=$>=**#&+.......................++.+..+..+.+........................+.++........................................................+..+.+...............................................................................", +".....+++++++.+@+.................................+..+@@+@+++....................................................................................................................................................................................................................................................................................................................................................................................................................................................................", +"................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................", +"................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................", +"...+@&&&&&&&&&%&&&&&&&@+........................................................+...........................................................................................................................................................+&*%%%%*%%%@+.......................................................................................................................................................................................................................................................................", +"..+&*%#**#*$$>*=*$=>=**&+....................................................&%#%###%&+........................@&&&&%&@+................................................@&%%%@+.....@&%%@+.................+&#####&@+....................@&#$>>---->-,=*#@+.................................................+@&&&&&&@+........................+@@@@+.......................................................................................................................+@%&%%&@+............................................", +"...+&&&&&&%#*-,>=>,--==%@..................................................++@%#***%#%@......................+@#%%#%%%@@+.............................................+@#%%%#%%@@&@@&&%##&&@+..............@%**#%##&@+..................+&#*$>==,=,=,>=*$&&@..............................................+@@&%%##%%&@+.....................@@+@&%%&+.....................................................................................................................+@@%&%##&@++..........................................", +"...@&&&&%#*=3;;;-;!;c;-,*@.................................................+&#**>>=>**&@...................++&#*$$$$$*#%&@...........................................+&#*$$$$$*##%###$#$*$*%@.............@%#$$=>>*#%+.................+@**>,----;----->=$*&@............................................+&&%####$$#%%%&....................@%%%#%%%&+...................................................................................................................@&%%##$$*$#%@@+...................+@&@@@@@+............", +"..+&&&%#$,c0adbddaddaaa0;,#+..............................................+&%$>,3c93,>#&+................+@%**$=,,,->>*$%@+........................................+&&#$,-3,,,,=$*$>=>,,,=>$#+...........+&*=3-c33>*$@+...............@%#>=39aad~dddaaa;9,>$@................+++++++++@+...............+&%*$$>>,=,=>>**#@+................+@%$**===$$*&+...............................................................................................................++&#$*>==,====*#%@+...............@&#*$#$#**#&@+.........", +"..@%%*>30_b|447744eb:b:ebd9$..............................................@%>,ca1e1bac,$%+..............+%*=3ccaaadada03=$&+.......................................@%$,9!adddaa0ccccaaadaac9=#...........&$=3~be:bac=*@..............&%$>3'be7giiiiig74eba3=#+............+&%%#####*#*%%@+............+%$=>39;aadaaac;9,*#&@.............+#*-900a00c3=**&............................................................................................................+@%*$-90caaaaa00c3=*#&.............&#**>=3=3,,==*#%@.......", +".+#=>-)FrzyxBCCHABAxxxxxsz/~%...........................................+#=-!)FzyBByrF);>*@...........+&#,;'{F^rzzzzzr/{!;-*@..........@&%%%%%@+....+%#%%%@+......@#-;)Frzszszz/F]F/rzzzzr/])>@........+&#-'{rxBAxr]~-=@...........+&=-;']/sBGGDvNvGGABAsr);>&..........+&#=,,-,,,,-----$$%@........+%$>-!)]/^rrzzrr^/]{!;-=%+..........&*-;)]//rr//])!-=%+.........................................................................................................@#>-;')F/rrzzzrr/F{~;->%+.........@%>-;!)){)){))!;-=$&......", +"..%==;)rzyAGGvLGLGvGvGGCtyz{>...........................................@#-;)FrsACCtzF)!->#&+.........@*>-')FrzsxAtxxsrF)'-=#.........&#=$>>>=*#%&%##$=>>==#&.....%>-;{rsBAtAxszr^/zsxytAyz/{;#.........%=;'FsABCBzF~;>#............#,-!)/sAHGGDDvDDvHCBAr]!-#.........@&*>-;;;;;--;;'!!;-=#+......+&*>;')]/rssxxyxszr^F]);-$@.........&*,;)]/rzzszrr/{!-$&+.......................................................................................................@*=-!'{FrzssyyyxzzrF])!;,%........+#>-!){F//^^/^F{~;->*&.....", +"..%$=-~][IJwwwwNNwNwNwwwK[F~>@.........................................+&#=-;_2IJJJKQ|~;-=*&@.........@%*-;~2QIPIPJKPI[|!;-*%........&%#**=*$$**#**$***=$=$*#+....&*,-~}IJJJJPK[}]2[IPPPJKI}_-%.........%*,;)[KJJK})->*&...........+#=;!~:[PJJJJJJJJJJKKrF~-=%.......++&%*=,-;!;;->-;~~'-,*%+.....+&&$,;;~1}QIKPKPKPIQ}:)';,$@.........@#*-'(F2F/[/QQ[(!>*&+.......................................................................................................@*=-;~):[IPIKPPKI<[1(~;-=%.........%=,;)12Q<<3~(}5OwY6[1_;-,*#%@.......@#$>-!176OYwOYYOO5}(!-=#+......@@#>,-,--->=>*>=>>,---,=%@....@*,;(78OYRRM6<}:}<8YSMRR8[(;*.........@$>3([OOO84~-=#@...........+*,;~(:<6O85<<<<-;~()!--;_{:(!,$%+.....@&#*,;(12<8OYOMwYYO8<}1(~3=%........+&*>-'|}[[}2Q565}'-$#@......................................................................................................@&$>;__1[58OYOYOMOO6[:(_;-#+........&$-~:[<8OOOYO5}('->*@+....", +"..&*,;abgpqWUUWUWUUTUTUWoifbc*.......................................+&#$=-cdbgmqUWoifba;3>*&+.......@#=,;afiqWWWUWWWqjgba9=*+.....+%**3900cc;c3939399;c0cc3*@....&*3cbgqTTTTTqigffiqTTTTUqgb3#........+&*,;bgqWqjgd9=%@..........+%=-;dbgpqojlhhhhhkhll7ec9*%........@&*=-;adbba!c;deee0-*%@.....@#$=;abf7iqWWWWUWWWqp74bdc>%.......+@%*-cde47777ipqjga9=#@...........................................+++....+++++..............................................+&#*30defkjqWWUWWWWqji7ebc-%........+#*9afimqWWWWWqgba;>*&.....", +".+&-,0d4moWUTTTUUUUTTUTUqnhfd,@...............+@&%&@+................@#=,c~be7ijUUUomh4|d0c>$&.......@*>3abfpZWUUWUUUWjhed;3*&.....@#*-;d(bb:bbd(ddd(dbb1ddc3#....&$9cepqUTTTTUjhgijWTTTTTqib9%........+#=3abiqUUoib03>&..........%#>cdbehpWWnmlllllVVVVkea-=&........@%$,c0dbee(0cab4ked3$#@....+&*3ca:7klnZWUUUWUUWWnVkked9*.......+%$,9_ekllQllVoZqib9,*%................+@+++++&&@@@@@@+........+@&%%&#%###**###%&&&+........................................@*=9cd4khmnWWUUUUUUWZXhk410,@.......&#,c|7lnZWUWUWqmed03=&.....", +".+%-!{^sGDEEEEEEEEEEEEEEEvts^'&.............&&**>-=$$#&@...........+&*-!{FrzyBHDEEEEHAAsz/]'-%......@#-'{FzyGLELLLLEELGsrF);-%.....&>-~]rsssxysxsxsysyyxssrF~;&...%-'1IwDEEEEEuvAttvuEEEEEEAI)=........&$-)FKAEEEDyr]~-$+........@=-!{^zxAvEEDCBCCCCBCCCAz]~;*........&*-;)]/rzr/{)]^sxzF~-=%....&>-~]rsBHHGvLLLEELLLLDHHAtrF-&.....&*=-~{^stACACBHGLvyI{'-=@............&#*$>=$*$=>,,,>==**&.....+@#=,---;;;;;;;;;;;--,>*%&+....................................%,;)FsyCCGLLEELELELLvGHAAs/($.......#-;)^yAGLLLLLLGtz}{!-=@....", +"..%,;{/sHLEEEEEEEEEEEEEEELBsF;&............@#>=---;--=*%@..........@#-;)FrsACGLLEEELELGtsrF);*+.....@>;)FrKxCLLGCCCAHAys/{';$&....+#-')/stBBHHGGGGGGGHCCBAs/);*...%>;)^sAGGvvLvHByAHLEEvvGts/)*.......+&=-']KtGLuLxr]!-$&........@$;~FrsyCvLLLCCCABABAAAxzF~-*+.......@%-;))]F^/])))Frr/]!-=&....#,!{/stGGGLCvGLLLLLGHGvGGts/~#.....&*-;){/sACCCCCBvLDAr]~-=%..........+%*=--;-;-;--;;;;---=#&...+%==-;;'!!))))))))~~~!'--=*@...................................+%-!{/sGvGLLLLEELLLGGGGLGHtz{,+.....+#>-)/zyBBCBHCHAsr]);,*&....", +"..+#>;_48wNNNuNuNuNuTuNSNw52)=+............@&$>=,---,$$%@+.........@%$-!{/[IJwwNwwNwNwwI[|);,%.....+@*>;)12QPwwPQ[2}}}|(!;=*%+....+&$-!{/rKKwwwwNwwwwwJJzI^]!-&...+#=-~|}QIPOwOPQ[QPOwOKIQ}|!-@........@#>-':-;)]/IKzKKKJJwO<1~-=#@.........+&%**,,----;----;--,,>*@...@%$=,-;!!!~~)_)~~)~!;;;--*$@.................+.++..............+%=-~:IJwwwNuwNuNwwJJJwwwOK})=.......+%*-'(]}22[}}22(~;,>$&+....", +"...&>c_}5RwNNNNNNTuNTNNNSO<:~=+............@#*=---;;-,*%&+........+&%=-!(}[*@.........+%-9_e[,,=**=---,=*%@+....@=-!(}%@.........@%$>--;'!!!!!'!_~~;;--*@...+*=-;_(1b:1::b:1:111{|1_c-*&..............++@@%&&%&&@@@+........%=;_|<6OwwwwNwOwwOJJJOOw8<:~>+.......+#=-;___((___~;-=$#@+.....", +"...@=9afpqWUUTTUTTTTTTTTUjibc$.............&$>3caa_ac9>#&@........+%$=;de4hhlmmiigiimmiged0;=@.....@%$,;dbf7imi7fbaa0;93,=#&+.....@#*3ab7hllVnmmmmmmnmmllk7ec3&....@%$3;dbfgpqqmh4gmjqpgfbdc,*.........@%$,9bgqWWjgd;=$&.........+#-0fipjojppjjojpih7e:bba3=%@...........@%**$$$$***>>>$#&@.....+&=9abgkmmXoqqppppmlmllmmmkge0*.....@%>c0bb4hhk77khpqjib09>$&........+%*=3cdbbeeebbdbeefbba0-%...&*-cbgiijijijpijpijpiiigbc,#........+@@&%&%###**#**#%%#%+.......#,0bfhimmnqWqopmmmooommmikfb>.........&*=-,cc;cc993,>**&++.....", +"...&=9d4oZUUTUTUTTTTTTTUWZif0#............&%=-ab1eee1a3$#@........@*=9abklVlVVlh744khVl74:d0,#.....+*=3a|4kklVlh4:ba!99,>$#@......@*>9aekVlVXVXVllVVVXlXVVhed3#....+%*>ca|ehnZZpllVXZZnhebac,#+........@#*-0biqUWqgb03=%.........&,0bgpZWZoXXoWWWZnllhk4|dc,$@............+@%%#%%%%##**#&+.......%,017lVmXXoWWZnVVVVlXXVVVlh4d=....+%>-~be4klVVlhhVoZqi7dc3*&.......&#*3;a:4khkhkk4ekklll7eb0*..+%,0biqqWWWWWWWWWWWWWUWWjgbc$@......@%**===,,,,333,,,,>==*%+....+#;_eklVVVnZWWoXVmnoWonmVVlhe9&........+%*=,=,,,>-,,***&+.......", +"...#-_/JGEEEEuEEEuEuEEEEELw/!#...........@#,;)Fzzsssr/'-*#+......+%=;)FztBCHCBBtsssxACBxsr/);*.....&>;)/zxACCCCBxsr/{);;-,*&......%>;)/sACCCCCCCCCCBCCCBCBBs^)=....+%*-!{/zxvDDGHCHvDEvxz^]~;$@........&=3c(kAEEEGxQ);-=&.......+*!FztDLELDHGvEEEELHCAtyz/{~-%..............+@@@&%&&%&%&@........*!]zxCBCCHDvEGHHCCCCCCCCCCCxr;....@$-~FrsxCBCCACBHGDDAs^{~-$@....+%>;;)]rxACCBCBAyyABCCCAxr{-..+$!{IxEEEEEEuEEEEEEEELEEDyKF!#....+&*,-;!))))(){]]{)))~';->*+...&,)/sABCCCGLELGHBCHDEEGHCCBAs{#.........&#*$>,----==**&@........", +"..+%-_/sHLLDEELEEuuEuEEEEvy^;%...........+#,;)/zssxszF);>*@.......&=;)FzACCCACByszzytBtsz^]);*+...@#-;)/sACCCCCAAssr/{~;-=*@.....+%-;)/sACCBCCBCBABCCCCCCCAs^)$+...+&>-;)/zsHLvvCHCvGvHyz/]~-*+.......+&$-;{rJvLuvy/{;-$@........$'FKAGLLLvCHvLEELGCBCBAxr]);*+...................++.++.........+='/zACCCCCGLLvBCACCCCCCCBCAA^-+...@*-)FrstABCCCACCGLLts/]~;=@....%=-;~]/zyCCCCCCAAABCACAAyr{=+.+$;{kyHGvLDvLDDDLDLvLLLLDAzF)$....@#-;'~{]F//^^^/^/^//F])~;-#...&!{ryBCCCCHGLLGCCCGvvvCBCCCAs{$...........+@@%***%##%&@.........", +"...&=;_[6wNNNuSNuuSuSuNNNw<1;&............&*-;~]FFFF|)-,*&........+#=-):rKKKKI^/2F:F}//]_~;=*%....@#>-':QKJJJwJJKII[1);,$%@.......@*--~FIKzKKIrI^rQrIKKKKKr});%.....+%*,;!1[!1QOwNwwJPJJOOJJPKJKPI[_;,%...................................*;)F/KKzKJwwwOKQ/QrIKIIrIKr^|>+....&*-!(]/QzKzrKIKJOJ<2{';=&.....%=-;!):[IKJKIrIrrrKzKzK/F_;*...%=;_}<5P6P6J6666JOJwwNwO<})-#....&%=;')|}}-~1}[[2(!-=%@.........@>9_48SwYOPII<%+...+&*-;(1}Q5OP<[[[QQIIIII[}('-%...@#>3_12}[[[[[[[[[Q<6YwS6<1!,%...+&$>!(|2<66OOOOOY8Y6YY6<(3=%...+#;(}QQQQQ5OSYOPIIIIPIIQQQQ[}-+.................................", +"...&=9afpqWUUUTTTTTTTTUUWqgb0*............&*=3cadbbbda-=#&+.......+%=3ab7klhk4fe1bbdbbdac9>$#&....@#$9agpqWUUTUWWqqpgba-$#@.......@$>-a:7hlhh74feeee7khhlhhe09%......+%*,3abfhpqTTTqmh4bdc3=%@..........&%>90bffffdc,>#@.........@*30fiqWqjmkhkhhhhlpqWWqiea3#...................................%>0b7hllmmooqpif4e4khkkhkhk4b>....+&*,;a(efhlllmlVlmh7eba;=%+...+#,;de7gpjqoi44775ilhlh7ba;=%...@%$3cadbbbbbebfff7gpqWWjgba3#...+#$-abf7ijqqqqqqWqWqqqjif0,%....*9de4hkhkijWWqpmmlllkhhhkhkf9+.................................", +"..+%,0d7jWUUUUTTTTTTTTUUWqmfc*............@*30de47744(0,$%+.......+*=9_}kVVVll<7444444e:dc9,*&....@*,3afpoqqUUUWZZom4eac,*%+......@*,ca4llVlVVhkk7kkllVVVlh4d3%.......&=3cdeklnqTTTqXVk4bac>$&..........@$>9dekhk7eac=*&.........@*,cbgpnnnXmnmpmmmXnWUUqp7b9*+..................................%301klmnnnZZWZpmilimmVVllll7b=+...@%$3adb4hXnXnXonXnXh4:ba9$@...%=3dfimmoooomlllmXnnVllk:d9,&...@#*,30aadddddbbbe4hmZWWqmfd3%...@%>9aeehlXoZoZZoZoZoZojibc>%...+*0bQkhhlVXqUUonnXXVVVVllllkec&.................................", +"..&>;(^JvEEEEEEEuEEuEEEELDyI)*...........@#-~FzyBCCAxz]~->#+......&=;~FzACBCCCCBAytABAAsrF{!-*....&$;_2zyHHGDEEEGBCAsrF);-=%+....+%>;)/sACCCCCCABBCABCCCCCAs^)$......@$;)]^stBGLEEEEvCAsrF)!-%.........+#-;)^stCAAzF);,*@........&=9~:^zxAHCHvDDGGGHDEEEDts^{,+.................................+*;{/sAGDvDEEEELvLEGvvvHCCCAsF-+...&*,!{^zxBDLEDvLEDDvAsz^]!>@..+*;{^xGvDvvGCCCCBHDDDCAysrF~;*...@#$,3!~_))_{]]]F^zsGDEEvAK^)=...&$-!]/zsxAACCCBCBBCHBByK2~9$...+=)/sACCBHGDEEDHHCBCCHCCCBBtz~%.................................", +"..&-!{/svLEEEuuuuuEuEEELELy^'*...........&>;)/sACCCCBs/);,#@......@=-'FzyACCCCACBBBBACAyz/{'-#+...+=-~]rstCCGLLvCCBxzrF{!--*&.....#-')/zACCBCBCCCCACCCCBCCAs/)=+.....&=;)FrsACvLEEELCCtsrF);-%.........&$-')/sBCCtz/);-*+........@*-;~]^zsxtABHGGGGLLGGGGAzF)=+..................................*;{^sAGLDEELLEEuLEuLLvBCCAAs/-+...&*,;)/ztAvLLLELLELvHxzr]!>@...*-{QyDLLLGCBCCBCHLLGCAxzr])-*+...@#=>--;;;;!'))]F/sALLLDAz/)>+..+#>!{/rzssyyxAAAAAtxysz^]'-%+..+=~/zyBCCBHLLvGCBCCCHCBCCCByr'&.................................", +"..@*,;([6NNSuuuuNuNuSNuwNO<|-&..........+%*-;1[KJJJJPQ|!->&+.......&$,!{^rKzKzKzQ/rrIKr/]_!-=&.....&=-'(F[IKJwwJIIQ[]|';-==*#+....+*,;)2rKKKKzKzrKrKzKsKKKr})-%......@*=;!(F[KPwNNNwPK^/('-,*&.........@&*-;_/IKzI}~->*&.........+%=,-;~(]F22[QQIPwwwwJKI[(!-#...................................%$;)}QJwNwNwNNNNNNNNNwJKzK/F!*....+&*=-~(25wwNNNNwNwOK}:)!-%....&=;($$=>>-'_}$%@....+&=-!1}QKIPPI-9'(11:::1[[>;_1[6OwwwwwMO6[1_!;=%....&=9~[8ORY8PIQQQ<6YY8<[}1~;-*&......+.++@&&&%%#$==9_26OO52(;-%.....@*>--;'______(_((_~!!;-=#+....#=;_|[QKPOwSwP9agpqTTTTTTTTUTTTTUWjgb;%..........+&*-aepqWUTTqiec9=@........@#$,9d:f4hhmpjjjjmk7eda9>*&.....%*,;dbf7ioqqpgeebbba~0;3,*&+....&*,cb7khlmpojjjoojopmhk7b0,&......@$=-cdbf7ijUTUji7ebdc-=*@.........+&$-cdgmjjiea9=#@..........@*=;abbfeeeeef7gjqqpik4b03*@...................................+%=9abgmjnpnoXpnnooqomlhh7:a3%.....@&$=3cdfgiiiVimiihfda9,*&....&*-0fgmppjjpih7hippm5k74bc9=&............+@@&&%$=,0bfgggba9=&....+@%*=>--;99cc9;cc;cc9-,$#@.....&*-0de7hmXoWqplhhippnmmlkfb0*..................................", +"..&*,abgjUTTTTTUUUUTTTTUUqmfa$..........@*,0a7jZUTTTUjfa9>#+.......@&*>9ad:ekVXqUUUqoml4bc9,*&....+%=3db[klmoWZph44eee:b|bd03=+....&*9aeklVXoZZWZWWWUWZXVlkea,&......@*>cabekhpqUTTqmh[ebac>$@.........@#=3abioZWoib03=%..........&=caekkkk444e47loWZnhkf(c,>&...................................+%=90b7lXXXVXXXXmXnnXXXVV7e03&.....+%*,90abe44hhhhh7fbac9,*&....@=,9d44lXoZoXlhlVVXXVVVhedc=&...............+@%%$,9abfebd;,*+.....+&%#$*==>,-,-,,,3,,==$*@......&*=3dekVVnZZZnmlVXZZnXXVh4d9*..................................", +".+*-'FztvEEuEEELEuEEEEEELvtK]-+.........&,;{QsDEEEEuuuz});>@.......@%=-;)]/zyBHDEEEEDCxz/)!->%....@>;)FztCHHvEEvAAxyysxysyz^{;%...@*,']zxBBCGLLELLEELDGHCAyr{;%.....+#-;)FrsxBGDuuEEGAtsrF{;-%.........@*-']rtLEvvyr]~-=@........+$;{rsBCCCAxxsxxHvDDGByz/);,#...................................@#-;)FztBCCCCHCBHCGHCBCBBx^{-%.....+#*-;~)F^zzsssszr^:(';-*&....@$9~FrsAHGDvGBBBCCCBCCCBsr{!$................+&#=-'(F//F(!-*+......@#*>=,-----,-,>---,$#&+......#,;~FzxBCCDDvDHHBGvDvGCCAz/~>..................................", +"..*-']IyBLLELLLLELELLELLvHyzF-+.........#,!{[sHLEEEEEtzF~;,#........+@*,;)]^zyBGuEELHtsr]~;-$+....#-!]^sBvLLEEELvHGHGGHGvHAs/'$...@*,;{/sxtABCCCBCAAHHABtys^),%.....&#-!)/rxBGLEEEELLGBsz/]'-*.........&=-~]IyGLLvtr]~-=&........&>;]ryBAACBByxyAAvLvBtsrF);=&...................................+#=;']^sABCCCCCLvvCBCCByxzF),+.....+@*=-;!){F/F////F{)';-$%@....@$-'(/rsxBHCCCBCCACCCCCCyzF)=+.................@#>;')())!;=%.......++&&%####%*#%%#%**%%+........&$-!)/zxyBCCGGGvvvvGCBAysr{;#..................................", +"..&=-~1}IPwwNNNNNNNNuwwwP<}(;$..........@*=;_[6wNNSNN8}_;=*@.........+@#=,-!)1QPwNwO<2{);,*%@.....@=-!|-;~1}[IKKKKzI^QrKKKK/}_;*...................+&*=,-==#%@................+...+....+...........+@*=-'){F[QKPJwwwwsKI[F{)!-*+..................................", +".+%*,;(1}Q#@...........+&#=,;_1-''___~~';;;;;;'__';;=&......@%*,;_|[8MNNNNNNwY52(~;-*@..........@*-'b*****$*#%@+.........@%*=-;(:}[[QQQ[21[QIIQ[:(;*....................+@&%%%&&+.......................................+@*=>-!~|1[IJwNwOPQ}:_!;-=%+..................................", +"..&*>;_b:f7g5iiiiii30be47k774eef4hhkeba3#......................+@++............................................@#>,30defimqqqpi7e(a0->*&...................................", +"..@#=3abb}ef7474477777feba09=@..........@#>9afpqWUqUqifc3>%@.............@#$,cdgpqjifc3>*&........@*>cdfpqqWWWWqZoZoZZZZZopgb3%......@*>>-9-3-,,,>>>=-9;93-$*@......@#$>90bfmoqqUUWWqoi7dac>$@.........+%*,cbiqUWqgbc3*@..........&=cdeklVnZWWqZZZooifd;9>*@........................................+@#$>99abegmpopi4ed~33=#@..............++@&@&&@+................+&#=,9ade444eeb|e4774edc3%......................................................................+%*>330de4imjnmh4bda3,*#@...................................", +".+&=-;)/^rrzrQ^QrKrrKrr^])!;-@..........%=-!:rtGvvvDGyQ{!-=&.............@*,9!{rxtyP^|;3=&........&>3~:rxtGGHHGHGHHHHGHHHAtKF'*......+%$------->======-;--=##@......@#,-')FQstGGGvGGAAsK/{~-=@........+@=3c{IxDEEGx[);,%.........+*-~FrsyBHGGvHHHBAxK/{';>#@.........................................+%*,;!)]/rzsKzK/]_~;--#+...............+@@@++...................@%>;!){]/^///FF/^/^/F{~;#.......................................................................&*--;')F/zsszKr/{)~;-*#@...................................", +"..&$-;)_]]///FF///^^//F]);;-#+..........@*-;)^stCBCCtsr);-$&..............%$-;'F^zz/{';-%+........&*-!)/rssxsxxxyxxAttxxssr/(;#.......+@&*$$$*$####%&%%*#*%@........+#=-;~_FrssxsxsxssrF])!-#@.........@#,')QyGGLvs/);,#+.........#-!]/zsxtBBBAAyssrF{!;,#&...........................................+@#=;;!){]FFF]{~';->%+..........................................+%=-;;)){{)))))){)))!;$@........................................................................@#>--!~{]1FF]{)!;->%@.....................................", +"..+&$=--,;-;;;;;;;-!!;;,-=*%+............&*=-~][^QrQ^F_;,*@...............+@#>,;~~~!-,*&+..........+%=-;'(({{{{]]]]]]]1{()~'-*+............++.@+...+.+.+.............+%**,-;!(({1{1{({~;-,=*@...........&*,;([58P52_-=*@..........@#=-!)1]F////}/1(~;-=*&...............................................+@##=>-------=$$%@..............................................@%$*=>>-->>->,--=>=*&..........................................................................@%$*==>--,3--->$#&+......................................", +"...@%#%%%%#%#%%#**$***%%%&@+.............+%$=;_|:}12|~;>*&+.................+&*>>-->>#&+............+&#>,-;--3;;;;3;-;;;--->*&+........................................@%**=--;-3--;---=**%&+...........@#$,c(}[2:_;,*&............@#>-;!__(|(((_~';,=*@+..................................................&&##**=***#%@+................................................+@%%%#&&##%###%$#%&+............................................................................+@&#%#*$***%&&@+.......................................", +"......++++++..+++...+++..+................&*$,caa_da09,$&@...................@&*#**%%&&..............@%#*$=,,,,=,,,-,>=>=**%&...........................................@%##*$=,,,>===$$%@++.............&*>9adbbdc9>%@...........+@%#>,339;000cc3-=$%&......................................................++&@&@@&++........................................................+.+@&&@%@@@@+.................................................................................++@&&&&@@+.........................................", +"..........................................+&#=,,99399,=*&.....................@&%%%&@@...............+&%#***$=*>=*******#*&@+............................................+@&#****$***#*&@+...............@%=,00bdac=*%@............+@%*$>,,3>,,,,>**&@..........................................................+..................................................................++@+.........................................................................................+@+.............................................", +"..........................................++&%=>>-,=>>*%+......................+@@@+..................@@&##%#%%#%%%***#%#%&.................................................@%#%%####%%@.................+&#=-;~~';=*%+.............++%**$$>==>=**##%@..........................................................................................................................................................................................................................................................................", +"............................................+++++@@@+++..........................+......................+..+.++.++++++.+.......................................................++.+..+...................+++@&%##&&@+...................@@++@@+@++..............................................................................................................................................................................................................................................................................", +"................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................", +"................................................................................................................................................................................................................+...++...............................................................................................................................................................................+@&&&&@+.......................+@&&@+..........................+@%%%%%%&@+.................................................", +"............+@&&&&&@@+......................................................@&%&%%%%&@+...................+&&%&&&&@++....................................................................................+@&&%#####%*####%&@..................................................................................+@@@@+..............................................................................+%##==,,>$$%@+.................+%%$=,3>$*%@+....................&%$>3-3333=$##&@..............................................", +"..........+@#=>333,>*#@...................................................@#*=,3--33=*%@................+@*=>-3333==#@+.................................................................................+%*=,3,39;9c;9c9;33$%+.............................................................................+&%***$*#@+............................................................................#=,ccddddac3=#@................%>9cadddac3=#@+.................+*3caddb{b(a0c,=*&+............................................", +"........+%=,;~{]]]{';->#@...............................................@#=-;){]{F]]);->%+............+&=-;~{]FFF])!-$*@+.......................+&&&@+................................................+%$,;')]F/^^^^r^^//F{~-#...........................................................................@%$>-;'~!!;,*&+....................@%##**%%@+...........................................%>']/rsxysr/]'-$%+.............&,)Frzxxxz^F);$#@.......+@+.....+$~]/zxyxAxysrF]~;,##@@@@@+.....................................", +"........%=-;']F/r/F]~;-=#@.......................@@@+..................@#>-!)]Frr^//]);-=#@...........&=>;!{]//^//])!-=*%@..................+&%%##==*#@.............................................@#$>-;;)F^rrzzszzszzr//{;=+.........................................................................@&*,-!){{])!;-=@.................@%#*$=>,>,==##@........................................+%-)FrstBAAxrF);,*&+............&-]rzxBBBxzF]~-=*@..+@&%##$#&...@,{/zyBBCCBBxsr/]~-,*$#%%*#*&..................+@@&@+...........", +"......+&*=,-!)(]]{_);-,=*@...................+@&@&&&@+.................&*=,-!){]]F]_);-=$%@..........+&$=-;~{|F1]|)~;-$*@@..................+&%#$$$>*#&+...........................................++%$==-;!)]F]FF/FF/}FF]_'-%.........................................................................+&#*>-;!)))~;=*$@................+&#$$=>=,,-=>**%&.......................................+%=;)F/rrKr/F_'-=#@++....@@+....@$;{F/rKr^/|!;=*%&@+@%%%#***%+..+$;)]/rzzzzK^F]_~;,*#%%%#$$*%.................@@%&%&&@+.........", +"......@&#=-;!_(|||1(_;->*&+..................@%#*$$*#&+...............+%#>-!_(||::11('-,**&+.........@%*>;~((|::||((!-,$#@+................+&%***===>*#%+..........................................@%*=,;!~((:}}4}44[}4}}:1!-#+........................................................................@#*$,-!_|||('->%&................@%*=,--;;;;--,$*&&.......................................%=;_|2QI<<}|_;=$%&@.@+@&@%&@...+$!(}[QI<[:(!->$%%&%##$==>>=#@...*!(:[QQIIIQ[}|(~;,>*$$$*===#+...............+&##$#$#%&+........", +"......&*$-0dbeeefeeebd;,>*@.................+%*>333,>$&@..............+%*=cdbefeef4eeba;,=%@.........&*=9abeee4444ebbc9>*&+...............@&*>339cccc>*%@.........................................+%$>90abefgipjjjjijijipigb;#........................................................................+&#=-cabfgiigbc-*#+..............+&#$3;adbdbdaa;3>$#@......................................%=3ab7ipmphfd0,*#&@@&&&##$$*+...*cbfimpmi7ba;=$##%#*=,9cc09=@..+$0be47hhkhh77eedc->**=339cc-&..............+&**====$$%@........", +"....+&#>-0|7klhklkklk4d03=*@...............+#*3caadac,$#@.............@#$90ekkkkhklVk4edc3>%+.......+%*-c|khlkhkllhk2bac>*&..............+&=>;ad(bbedc3$&+........................................&*=3_e7hlmoqqqTTTUUUWWqqpgd,@.......................................................................&#>30degmqUqjgb9,*&+............@#*=3!be7kkkk4ebac,*%@.....................................#,0beinZZomke0;,$##%#*>>333,*..+>_bkmoZZXh4b0-==*=>3;adb4ebc#..+>dek-~{/stHDuEuw^{'-#@..........+&=-;~{^stBCBCCAAsr]);,$@...................................+*;{/stDEEDHtz/);-,---;!){FF]-@.+-FzxHLELvAs^{';;;!~{FrzsAyz],..@;FsxACCCACCCCCByrF{))F/rsxsr;@............+*-~]zssrF)-=%.......", +"...@*-!)F/sACBBAABBCCAz/]);-#@...........&=,;!]zxHAxr{;->*%+..........&=;~FztABABABCAAs^])-=&.......&$-']ryBBACBCHGByz/])-=&............&*-!)/zyAAtsz]~-=&..........+&%%%##%&@@...+@%%##&+.......@$;']rAGGvLvDvEEEEEEvvGGvtsF;%.......................................................................&=-;)FzyCDEEDtr]~-=&..........@*>-~{FzxBBABBABBts/{~;=#+...................................#;)FzyBHHGHyz/);;--;')]F/rr/;@.@-]/stGGGHAsr]~;;')]/zsyAyyz{>+.@-FrytAACCCCBBBAsz/F]/rzsAAxr;@............&=;)/sAAx/);=*@......", +"...@%>;!(][rKrr//^rKzQ/()~->&+..........+&*=-;(Q6wwP[~;,*#&@..........@#>-~{/^^/^rIzK^F)!->*@........&*,;)F^^rIKJwwKQ]_;-*%@............&#=-~]/rrr^F(!-$%+..........@&%#%#*%%%%&@@&&%&%#%&@......&*,;)}6wNNw6IPwSNSwOPKIIQ4:~=+.......................................................................+%*=-'(}%@..........@#=-;){/rKr/^^rrKr/]);-=&............+++.....+..............+&=-'([IKPKI[F~;>>=>,-~(]F[^F-@.+$;_:QKPKKQF_~;--;~)F//^//F{;$..@=;)]F^QKJwwJK^/F](_({F//r^/(=+............@#>;_F^^/(;,#%+......", +"...@%*-'(12QQQ221}[Q[[}1(~-*&+.........+@#$>-c(7OSM64(;->*#%&.........@#*,;_11222}[QQ[(~--*&........+@*,;_|2[2QQIOO84_!-=$#@...........+@*$-!|[IQ[1(~->*&+.........@&##*$=$$*####*###$$>$$%%+....+&>3_b5MNNM5<5YSNSO6I-!~|}QQ[2222QQQ}|~!-=%+.......++@@@@@&@@@&@&@@+...........@*-;_|[IQI[}(_;->>=,;_|:}}[1-@.+*,'1}QII[[}(!;--;_(:[QQQ}1_-%...#-;(|}[QPOO8<2::(((|:}2[[[2~>.............&*,-_|221~-=*&+......", +"...@#>9adefkhh7e1f7hh74bda3$@.........@%*=,90dfiqWWjgba;9>*##+........+%*,9_be:e447hkfba9,*&........+&*-9abe477hpoqpgbac=$%@............@*=30b4h<7edc3$%&..........&**>-33->==**$*>>,-33,,=#&....+%,cafiqTTqigijUTWqolh77bbc3%.................+++++...................................................+&*,9abijUUjgb0-$%@..........&*,;ab:7kh7fee44hh4bba;=*+......+&&%#$#%*&%%%##%&%@+.........&*,cde4hhk74bd03>>>3adee477f9@.+$,0b4khhh4ebd00cadbf#%+......", +"...+*>9abeklVVh74kkVll7eba9=&.......+%*=-9cdbbgpWUWqm7ed~c93*%........@#$-0be47kkkllkk1a;3*&+.......+#*-cd:4kkllXoonhedc9=%&............&*>3_e4khk:ac,*#@.........&*,c!ad(da093,=,3cddbddac3$&...+#-cbfjUTTTjmmqUTTWZnVhk41a-#+...............@&##%&@+..................................................&>,cafiqWUWieac,*@..........@*9'be4kllIk[kklVlk4:ba9*&....+%*>,3333,=,,-3,-,,=*%@........&>9ab4lVVVlk7ed'c;0d|47kh@......+&=-'{/zxBBBCCCAsrF~;-*@.......@$-;)/zsABCBHHvHtszF);=*+...........#>;~]^ssyz/{~;=#+........+=;{/zsxAxzr/])~)]zxAtxszr]!$+..+$!1QJwuuTEGHHvEEEEGHCAtyrF~,@.............@#>>---->$*%@..............................................+%-;{FzADEEEtKF);,*+........@$-~]rzyACCAtyxBACCByz^]~-#...&#-;){FF]]{){{]]]]{)';-=%@.....+*;)FzsCCCCAAyzz^//rzxtCCCAxz'&.+-~^zACCCCCyyzrrzstACCCCAsz/(>..@;FrsttBCHvGGHCACBAABCACBys^(=............%,;~]rzyyyrF)-=%......", +"...@$-;)]rsABCBBBBBCAAz/]);>#+....&*>-')/rzsxABvEEELHBAxyzr{);#.......#=-!]^stACCBBtxz/{~;,=%.......&$-;)/zxBACCBCBCBsr/);>*@...........&=-;{F^rr/]~;-*@.........&>'FryABBBAxr/F){/JGLHCBts/)-%..+$!]^svEEEuvBGLEEEvGCBBAxzF'>@............@#>-;;'~;;->=#+..............................................%-;)FKAvLEuAzF);,#+........@#-~]^syBBCByxtABBCBxsrF~,%...&=-!{/rrr/FFF/F//r/F{';->#&....+*;)FrxBCBCBAxszrrrsyABACAys/;@.@-]^stCCBCAAxszzstBCACAAAsrF)=+.@;/sAACBACCCCCCCACBBCBCAAxrF~$+..........+#-;)FryBBtzF);,#+.....", +"....@**,-'{/IrrQ^^rI^/1~;-=#+.....@%*=-~1/QQQIKONSNwJPIrQ[2(!>%.......&$=-!(/IrKKzr^/F(;-=*%@.......@%>-;|2[rIrKKKKI^F]);,$%+............%$=-;~)~;-,*#+..........@*-)F^IzsKK^F|)!!([PJJKKr/{!>&..+#=;_25MNNwJJJwNNwwJKzQ/F{~-#............+&*=,;!!!;;->#&+.............................................+@==;!:$&+.......@**-a:<5>#&+............#-9(2<8OJ8[:(_~~_1<5IKQQ[|;,%...@=-c(}56O68OYNNNSOPIQ[2|(;-%+...........+&*,;!(1:1~;=*$&..............................................@$,-a|;(1[Q5IIIQ[[[}:[[[QQQQ[}(;>..+$;|}[-!(1QI=3~a|:e2f1d_0->>#&.......+%$,0eiqqWWWWUTTTTTWqWWqjibc$.......@*=9_ek9afh5lnoqWUTTUqmhk7ebb9-%...........@%#>9ad:777ea;=#%+............................................+@*,;dfiqTUqpgdc-*%+........@&$>30_b4hhh<77khhh4bdc-=&+...+%=;d7hhhhk74ff7ijji7bda9=$&....%>0bfhhllh5lkh777hh..+>dekhllmmlklkhlklllhlhlhk4b0$..+*cd:7khhlhlkkhkhh9dioonlhkllVk[edc9>%@................+@&&&@@+.............+#3ab7mZWWqmhfbdbbekhVVVll4d3#..+&*-9dehlVnZWUTTTUWnVlk441a3#+..........@#>9~beklVlkea3$%@............................................+&>3abgiqTTWp7ea9>#&........@%#=9!beklVVllllVVlkeda9=*+...&=,0|kllVVVVhkkhXqZjl741ac>#+...%-aekVVVVXlVVVVVlVVVVVlllked,+.+,bklVVXlXXXVVXVXXVVXV6Vlll7b>+..=0b4kVVXVVVVllllVVXVlllk4bc3%.........&#>-ab4kmoZZohbc>*%+.....", +"......+&$-;_{F^zzr^]{~;>=%@.......&$-~FKGLEEuEEEEEuEEEEEEvvAk(>......+*-!]rxBCACBCCCByz^{'->&+......&=-!2JDvGBBCCCCAsz/);-*%................+@@@&@+..............%,!]rsHvELvHxsz^rrsACCCCCAs^'$...%,;)/ztACHvEEEEEEEDHCBxsr]~,@..........&=-)FrsABCCtzF~->&............................................%$-~FrxGDEEEGxzF);,*@.......@#=-~]^stBCCCCCBCBBxs^{~-=@...%-!]ryCCCCCCCACHvDEGHAAsr])-%..+$;FzxBCCCCCCBCCBCBCCCCCCByzF;@.@;/xBCBCCBCCCCGHHHHBCBCCBCBy^;@.@,(^zxCBCCCCCBBCBCHHHBCCAsrF'*.......&%>-')/zACHLLEDxQ{;-#@.....", +"........@#,;;){F/F])';-$%&........@$-!{IxtBHGGLuEuEEEvGHGGGs^)=+......#-;)rsABBABBABAsrF)!-#&.......&=-!FztBABBABBAyz/{);=%......................................@$!{/stHvGGAyzrr^rsAACBCCBs/)$+..+$-!]rsytCHGDuEEELvCCAAsr]!>@..........&$-)FzyBCHHBzF~;=#+................+@&&@+....................+%>;']rsyGDGGAszF~;-*&.......+#=;~{/zyBCACACBCCByz/]~-$&...%-!)^yACBCGHCCBCHGvvvHHBs/{!*+.+>;]/syABACBCBCCCCCCBCCCGCAz/;@.@-FzxBBBCBCCCBCBHCHCCCCCCCCAz!@.+-)FrstBACBCCCvCGHBBGGHCCyrF!*.......%,;;)]/sACHLvLDy/{;,*+.....", +".........+%*=,-;---=>#&+...........%*=-~1:}}[2$@+.......+#*>;d:2[////FF]_!-=*&+......................................+%>;_:QKPJKI[2{(((]/QKKKKI/~-%....@#=-;){][[IJwNwNwJKK^/F|!-%...........+&*-~][PwwwK['-=%@................+@@&&&@+...................+%*>-'1}[4[[<[2]'-=$%@........+%=-;){FQrKzKzKKrQF]_;-=%+...@#=;'{F[IJwwJKKKIPPOwwwJQ:'-%...#=-;){FF/2/Q^QKKKKKKPwwwOK}(=+.+*;~]FF//QrKKKKKKKKII/QIIJOP}-...%-;')]F/2^QPJwwwJJPwwwwJQ1~-%......+&=-;!)1/IKJOSO8Q(;>$&......", +"...........&&%*****%&@+.............&*=,3c!_(12-c_((||:((!;==$#+........................................%$-;(}QIIQ[}|(__(_:}[III[:_-&.....@%$>,;!_12<6SNYOPIQ[}|(;>#+...........&*>;_1Q6O65|;>%&................+&######&+..................+&**-;~((||||1(_'->*#+.........@*=;!_:[QQ,;_(:QKOOPIQQI..+%,-!__|:}[QIQQQ[Q[Q[22[<885|>+..@%*--'_(|:[-'(::[Q<<555[1~->*%+.....", +"............+@%%&&&++...............+&$>=,90abfgpqjpgbd093-=*&........+@#$,3c_____0_cc,*#@+...........+#$>99aa_0dac3-$*&&.........................................&$,cdfhhlh7f1bdddde47hlhhed,%......@%*=-30dfgjUUUqplk4fbd0>%............&$=30dfgigfd9>&+................+&$*$*>$*&+..................@#*=9;aaaaaaaac3=$#&.........+%=,;ab7gmmmmpmmii7bac3*%+...+&=39abbginXmlhhhkimWUWqifd9#...+%*=,;0adbe47hhmlikhijWWqpf0>...&=9adb:f47hh77774477777hmigb$...@#$>,30d:f7imjnpmiljWUqjgbc,&.....@%*-cb47hhhhh7efbbc9=**+.....", +"..............+@+.+..................@%*>99adbehmnnmkfda93=*#@.........&#**>999c9cc99,$*%@.............@*==--c9c3-9,$*%@..........................................%*3c|7lVVllk742ee47hVVmXlkb0*.......@#$,90bfioWUUWnVlk7e|a9#+...........@%$,c0abbbac,*&................@*>,9c0c93>*%+................+&%$=33393!93-9>$#@@.........@*=0d:7inqZWZZWqZXi7ed03#+...@#>30d|4klmXVXVllllnWUUqp7bc$...@&#*3cad|ekhlVVVVVlVnZWUZpgb,+.+%-9_b4kklVhlk7e4f4kklVVllkgd=+..&#*>3c!b4klVmXXVllXoWUWjhea9#....+&*>cb4hVlVVVl[4eedac3>*#+....", +".....................................%>-3;!)FrstCCCAyz/]~;-,$%.........+%#=>--;;;;;;--$#&@.............+%$---;;;;-->=#&...........................................*-'{rxBCCCCCBtyyxABBHHGGGtz{-.......&==;!)/zxvEEEEDHCAysr]~>@...........@#=,c!a_a09c3=#...............@=-;)Frzr/{';>*@................@&*>--;;;;;;-->=*&+........@%-;]/zxGvEEuEEEEELHszr]'-@...%=-~]^zsyCCHBCCCCBHvEEEEGyr{-...@#=-;(FrzstBCBCBCCCHHLEEEGs^;@.+=;~FzxACCCCAxszzzsxACCBCAxz],+..&=,-!)FrxBCCCBCHCHBvEEEDAs2)*....@$-'{ryBCCBCCAysszr/{~!;-*@...", +"....................................+%=-;;!)]^sABBCBxz/]~;;,=&+.........+&&#$---->>$$%%++...............+%%#*$$=>-=*&+...........................................+*-;{^yCCCBCCABBABBCCBLLLGAzF,+......&*,-!)FIyGLEELvCCBAsrF',@............+%=,-;!;;--$#@+.............+#>;)Frytyz/)!-=#.................@%#*,>,-,->>$##&+.........+%>!(/zstvLEEuEEELLtxz/]!>&...&>;~]/zsyACBCCCBCCBGLEELtsr{=+...@$-!{FrzyBCCCCCCCCBHLLuLGyr;@.+$;)FryBACBAAszzrzzyBBCCBByz]-+.+%$-;~]^zyACCCCCCCCCvLELGts/)$+...+=-~]ryBCCCCCBtszzr//])~;-*...", +".....................................&#*>--!_(FQIKKI/}_~;->*%@............++@@&@%%&+++....................++.+++@&&@..............................................%=,;)/IJJsKzKrrrrrKJJwwwOP}~=.......&#*>-;):Q6NNwOJJKr^/1);*...............+&%**##%&@+...............@#=-;(/KKK/|';,*%...................++&&@&&&@++.............+&%=-!(2<6OwwOwOwOJ<:(~;-&+...+#=-~(F[QKKzKKKKKKKJwwwO<2(!*.....&=,;)]F/IrKKrIrIIKPwwNw6[|-+.+*,;)F[rrIrI/F|{(]:[IPPKIr}];*...@%=,;'|F^IKKrIIKrKKwwNwO<}_;%.....%=-'{/IKKKrI^/}]:F}F|)!;,#...", +"....................................+@#>-;!!(1}}Q[Q221(~!;-,*@.................+..................................................................................&*=;_}QPPKIKIQ[[[[IKJwwSO<|!*+.....@&#$,-!_|46RNNYJP-~14P66<:~;-=%+......................+....................+%*=-c~12<[<<<[<421~;-,*&.....&,;_:}[[QIIIQ[[<866665<}(!,%.....@*,;~1}[QQQQQQQQQIKOSNR84_,+..%-!_:[QQQ[21__~(|}[QIIQQ}:_;#...@#>-!(}}[Q[QQ[QQQ,93caddd0daaa;9,=*%@....+#>cb4khllhhk777iqqomh7eb03=&....+&*-0b44hkkhhhhkhhhmoWUqpgb,+.+%9abf;df7kkk4k7k7khhmjWTUjgfd9%.....@*,;dekhlhk7f:ebef7kebd03*...", +"...................................+&$,cd:44[kkhkllkkk4ee:da3#+..................................................................................................+%*,cb4lXVXoZZqZoonXXZZWWZphb,+....+%$,cabe7hmqUTUZoXXmVlhea,@.......................................&$>9dehpWUWoi4dc3*&.............................................&#%>=99990c0c399,>*$%@+....&$9d4hVlVVVVlkhhXoWomhk4ba3$&....+#=9_ekVVlklhllhlVlnZWUWol49@..*cd:kllVh4:bddbe4hlllllkkeb0*..+&*3ceklllIlhkklkhVXZWTUqm7e0*.....&*3!b[lVl6VVhk47kIllk4eda>@..", +"..................................+%>-~]rsytBACCCACBBBAyysr/)-%..................................................................................................@=-'{^sBHHGLLEELDvvHBvLEEDHtr;@...+%=-~]/zxAGvLEEEELGvGGGHs/!#......................................+#-;)/stvEEEDBsr{!-=@............................................+%#=3-cc00~0'0;;3-=*@.....+*-)FstCCCCBCBBABGvLGAysz/);>&....%>;~/sABBCABACBCBCHGEEELvAs)@.@-(^zxBCBxzr//F/zxACCCBCAtyr(-...#-']ztBCAABAAtACACHGEEEDHxz{=....+#,!]rxCCCCBCCBAAACCCBxs/];%..", +"..................................+*>;)/stCCCCBCBCCCCCCCBCxz]!$..................................................................................................@$-!)rxCBHGGGvGvGHHABBHHGHxsF;+...+%=;)/rsAHLLEEEELLLLLLLGx^~*......................................@#>!{/sBvvELGHsr]'-=&.............................................++%$,>----;->--$*%@+......*;~FzABBCBBBAtyAAHGtysr/]~-$+...+%,;~FstAAAyyAtBABBABLLLLvAz)&.+,{/zyAAAsr/]]F^zyCCBCBCCCtsF,+.+%>;]ryAAAyysssyxAABvLLLvCyr(=+...+#=;)^stCCCCCCBBBBCBCAysrF;#..", +"...................................%*,!|5JwwwwwwwwwwwwwwwOK[(-%..................................................................................................+&*-;)}rPJKP5;)|}QJwNNNuNwNNNNwwO<|;&.......................................%*-~1[IOwNwOK}(!-*#+.................................................&@@&#&#%&@@++.........@$-;(F^^^//FFFF2[[[2|)~;-=%@.....@#=-')FFF]]]]]]]]/2IJwNwJQ1-@..*;')]]]]{!;;;;_:QJJJKIKKJPQ($...@*=;)FFFF]]))){]FFQPwNwJI[]!*....+&#=;)F/rIKsKKIrIKKzKI/F(~,+..", +"...................................@$=9|IOOYYwYwYwSwOwYOOM84_-#...................................................................................................&$=-_:QQI#+.....+&*=;_|[5OwwSNNNwwwSwR84~,&.......................................&$,;(}<8RSR6[:~-=$%+......................................................+................+&=-!(::(__~___(||(~;-,=*#%+.....+&#=-!!(_';;-;;!!_145OYO52(-+.+&=-;;;!;--==,-c([6OPQQQ<865_$+..+&*-;~__!;;;;-;;~(}<6wY8<:~-&.....+&#=-_11[%...................................................................................................@#=3a:7hlh7fbd0c033->>===#%+.......&*>3cafgijjjjjjjjpjppgfc=+.......................................@$>;af7ijqjigb0-*%&+.......................................................................+&*,;00_a9,390000a0;3=>$#&&.......&%$,99cc9-,=,,-3cabgimigea$...&*>,3,-,,>**>-3afgii7f47iiga#....&#>390099>>-=,-90bgiipgfa03&.....+@%>,;adbgjqZqqWqZqjgba9,%...", +"...................................+%$,3dbffg777g7gg7g7gfgba3=&...................................................................................................@*>-aehlVh4eb09,>*%&%&&&&&.........@#$,-0affg7g7g7g7ggffb09*........................................@%>3db4hmpihedc->#&.........................................................................&#>>999999,9,3,;99,>>*&@+.........&*=--9,->>>*$>-90cdfffba3*+..+**=>>$=**$$=*33abfbebbfbbd3#....+%*,93>-=>**>=,330abffba03=@......@#$=30aehoZWWZWWWZoibc9>#+..", +"...................................&*=39ad12F4///F///[F::1dac>%..................................................................................................+%=-!]rytBxr/]_9,#%+................@#=-9'_1]}/[//F2FF1:(d!9$+.......................................%=-!]/zsxtys^]~;=*&........................................................................+&#=>-;;;;------;--,==*&++.........@#$--->===>===--;~a(b{(!3%....%*==-=,==**=,9ca_|{]]{|1da,%....+%*=>--==>=*=,-;;'ad(1{_';-&......@#=-;_(FIyGHHHHHGCxKF~;,#...", +"...................................+&#=-;!~){())))))({))~~;--#+...................................................................................................&*,;)FrszzF{~;-*%...................+&$-;;!~~'~)))))~)~~;;-#+......................................+&#>;)F/zsysr/);-$&+..........................................................................+%$>,>->,=,=>$$$*%%%+.............+%*#*#$**=$**=,--;;';;;>&....+&%*%$##%&%#*=,-;;''''!!!->@.....+&%#**%%@&&#%$->-;;!;;;-,#+.......+%>,;')F/rrrzzrrr^])'-*+...", +".....................................+@%*>==-->===,-->>,===*&+....................................................................................................@%#=-'){{)'->=*++.....................+@%#==,>=>>=,,>,>=#%&+........................................+@#=-;'({]1)'-=*&+.............................................................................+@@@&&&@&@&&+.++.+...................+@@@@&&@@#*&%*$*%%@........+.++.+....@%#*$*#***#$#@...........+++...+.+&%&%*$*%%&&+.........+&%#$>3;;!;!!c!;;-==#@....", +".......................................+@@&&#%**#*%%%##%#%&@@.....................................................................................................+@&#=-';!!;=$%@+........................++@%##$*%$##%%%%@.............................................+%*$--;;;-==%@......................................................................................+.....................................+++++...+......................+&@+@++.+++......................+.++..+................+@%#*=>=======**&@.....", +".........................................+++@@@@@&@@@@@@++...........................................................................................................@%*,,,=*%&++............................+@@@@+@@+...+...............................................+&&%%#%*%&%@..............................................................................................................................................................+.......................................................+@&&%%##%%%%@@+......", +"...............................................+..++...................................................................................................................++@@@++.+...........................................................................................+++++.++..........................................................................................................................................................................................................................+.+.......+........", +"..........+++@++++.............................@@@+@@@+@+....................++++@@++.........................+++++++..................................................++@@&&&@@&@@++...........................+.......................................................+@+@@@@@@++............................+++@@@++....................+++&&&@++.....................................................+++++++................................+++++++++..................++&#$$$#&++..........................................", +".......+&*>=-,-->$*&+........................@#*$=>----=*#+...............+%*$------>*%+................@&%%#*$$>>>>$*#%@..............................................+@#=,-;!;;-,>$#%+.....................@+@@&@@@@@@&&@...........................................+##>>,--,==$*&.........................+%*>>,-,>>$#@................&*>--!;--=*#@................@&&&%%%##%%%%%@+...............+%*==----=*#%@.........................+&#*$---->>*#&@.............+%$>-)~))~;>$*#&+.............................+........", +".......+#*-;!~';-=$%@+......................+@%=,-;;~'~;**@...............+*=-;!)));-=*@...............+&%#*$=,>>>>>,=$##@..............+++++++++@@++++...............+&%=-;'))({)!->$&@...................+@%%&&%%%%&%&&&&++..............++@@@@&&@@+@&@+............+%*,;'~!;-,=*#+........................&#*--!~;--=$#+..............+%=-;')~!--=*%+...............@&%&#$%%#*#$##*&+..............+#*,-!~';-***&+........................+%*=>;!';;-=$%@.............@#,-!)]1|)';=*#%+................++++@++.++@@@+........", +".......&*=-;~(1_;-=$#@......................@%$>-;;((1~;=#@..............@#*>;!((||_;-*#&..............+&$$=-;;;;;;;-,=*%&..............+@&&%%%%%&&%&&&@..............+&#>-!(|221|';>*#+..................+&##*#*#**##$####%@.............+@%##**##*##%%%&+...........@#*-!(1(~;-->*&......................+&%$=-;((_!-,*%&.............@%*>;_(||(!-,>*&+.............&&%#$$*>>$*$*>$*#%@+............&*>-;~|(~-=*$#%+.....................@&%#*=-;(1(;-,=#@............@#>-;~|}[[:_!-=*%@..............+@&%%&&&&&&%&&&&&.......", +"......@%$=90deeba;,*#%+...................+@#*=3ca_bbedc,*%+............+&$=30abeeebc9=*%+............@%#*>3;aaaaaaaa;3>*#@............+&&##***######%%&+.............@%*,;abe474edc3*#@.................@%*=>>>=>>,,=>>==>>#+..........+@%#**>>==>=>==*$$&+..........@#*-abeb_a0;,>*@+...................+%#*>,;abeba;3>#&+...........@&*>3abeeebda3>$%+............+%#$=3-3-3>3-33,,=>#&+..........@%*=3ade:dc9=$*#@+...................+&%#$>3cdbeb_c3=#@...........+%*,;ade77kfbd03=*@.............@%%%#$*#%%#%####&%@+.....", +"......@$=,;de4k4bdcc,*%+.................+&*=,ca1ee444:a3>%+...........+&$=9~b}7khk[b~c,$#@..........+%=,99dbe44eeee:bac,=#&..........+#*=>,-3-,,==,,-=$*@...........+&*>3_b2khlhk4(c3*#@..............+%*,30caaaaaaadaaaacc>#........++&#=>3ccaaaaaaac93,,=#+.......@%$,c(4444e|dc3=*&+................+&**,9ca(ekk4|a9=>#@..........&#>-9a{4khkke|d93=*&..........@%*>-ca1bd~aa_dbdaa93=#+........+&#>3;de[7eb~ac,>*&+..................&%$>3;a(e4k4ea;3=&..........+&*,9a14khllk41d03=#+...........&*=>,,,,=*>>,,3-==>*#@....", +".....+&>;;)FsxBAxsr/{;-*@...............+#=-')FrsAAtysr]!->&..........@$>;~]rsABBCCAsr]~-=*+........+%>;)]/zxACBHHtAAyr/);,*+........@#-;~){]FF{~~){]F{;-=&.........+&=-;{^sxCACBtyrF);=#+...........+&*>;){/^rrrrzrrrzrr^/F)-@....+&%$$--!~{F^^rrrr^/F]]{)!,%.......%=-'{/syAtAxz/{);-$%+.............@#=-;~]rzxyBByr]);-=*+.......+%=-;)]rsyCACAAyrF);-*@........@#=-!)/zyyzzrrzsxsr^F{!,#@.......&$,-~)/stBAssrF);->#&+..............+%=,;!{/zsxAAyz/{'-#+.......+@#=;~FrsACCCCCBxzF)!-#@........@#,;~){{]])!!~)]]]{)~;-=&...", +"......#--!)/zAABBAsrF)-=&...............%=-;)F^stBAByz/{'-=%+........&*>-!{/sBACCCBBAz/);-*&.......@%*-)]rzyHvLLLLLHCAsr]~-=%........&=-'{F^rzr/]{]/zz/);,*&........@*=-~]rxBABBBBys/{;-#&...........@%=-!]/rzzzzssssszszzz/];#....@#=,-;~)]/rzzzzzzzzr/FFF)!>+.....@#-;'{/zyABCByz/]~;-=#@.........@&##$-;!]^stBBABxrF);-,*&......@#=,;'{rstBACCCAByr]~;>*&@.....+&=-!)FryttyszsxyAxsr/F)-=%......+&*=;'{/zACBBAxzF);-,#&@...........+@#*--!)/sytBBByrF);-=&.......@*=-')^sBAACACBCByr]~;-#@......+&>;']F/rr/F{)]//r//F]~;>#...", +"......&*,-;)]^rrIr/F_;=*&..............@%*,-!)]/rKzr/]~;-*&+........+&#=,-~{/rKzKzKr/}{!-*%+.......@#*=;~]}QPwwwNwwOJI/|!-=&@.......+&*,;!)]}/}])')]}F(;-*%+.......+&$=-;)]^rrr/^^FF(;,$%@...........@%$>-']}/[Q[/^Q/[[^[/}:_;&....@#*,--'~(]}/[/[/[/22F:|();*......@#>,;'(]F^KzK/F|~;-==*%+.......+&#*$>--;)]/rrrI^/|);->$%@......@&*=-;~]/rIzKzKKr/]_;-=$&@.....@#>,;~(]^r^^/}//rr^/F|)',*&.......@#$=-')F/rrIr/})!-=>$#&+..........@%**,-;)]/rrrr//(~;=*%+.......@#*=-~{/IzKrKzIzI/F~;>=*@......@&*,;'_{]2]|)~){F2F{_~;>*&...", +".....+%>>;!_|2}[[[[1_-,*&+............+&$>-;~(|}[[Q}|_;-$#&+........+@#>-!~|}QQQQQ[[2:~;=$&+.......+&$,;_(:[;!(|22}|((((||);=$%+.......@&*>-;_12[Q[Q[21(~;$%@+...........@%*>c(}<<55555<555<555@....+%$>;;__:}}QQQQ}|(!;-->*&.......@#*$-;;!~(1}[Q[[21(~!;,*%@.....+&$>-;'(1}[Q[QQQQQ2|(~;-*#@.....&*=-'(|1[[[[}2}[[[[}1|_;,$%+......+#*,;;_|}}QQQ[21~;;,=*#@.........+&#$>-;!(1[[QQ[2:(!-->#@.......&*>-;~(}[QQ[[[QQQ[|~;->*@......@#$>;_(|:}}1(((|:}::(_;-=&...", +"....+&#>3cddb:f7k77fb0-$*+............@%>9cabbe4777fda-=$%@.........@%*3;dbef4k47444f1dc,$%+.......@&$,;dee47hhihihh4ed0-*#%+.......@*=3cadee77fbbbbbba;=*%+.......&#=3cad1f4<7<47bdc9=%&+...........@#*9agiqqqUqUqWqqqqqqUqgb*..+&#>9adbfijjqqqqqqqqqqqjpgfd,&...@&*-;aab:f477hk774ebdac9=#+.....@&$,3;adbbe74h<474fbbda9>*&.....@#,9!db:7477447k7h7febac,*&....+%=3;0bee4h4h44e7777eeedc-=%+.....+@$$-cdbbe44k774fbda;3=*#+.......+&#=-30abb74*@.....+@#=-0_b:477[7444h77ebba3=&.....+&$>-0dbef77feeee474ebba;=#...", +"....@%=3adee44kcd1e7Illlhk4k7eb03=#@......+@$=3ae4khhklVVVVh7edc3>#&+......+%*,cd:e4klkk[444e1dc,$%@......@%=30d144khlVVVh71a;>*%@...........@*,3agoWUTTTTTTUUWWUTTTjb>..@#>3~b47hpZWWWWUUUUUUWWZnXhea*..+#>3abe47kkhhhllVlhh774eda,#+...@*>-adee47kklllllhhkk74edc3$@...+#3cde47khlllhhkllllkk74ba3$+...&#,cde4khllllllh5lllhh471a9=%....+&*=30d|e44k;)]rzxACCCCCBByrF);-$&.......&=-!]rsyBCCCCCCCCBsr]~-=&.......#,-)/sABCCBCCCCCCAzr]~->%@......%=-~]rsxBCBCBCCCByz/{!-*&......%-;)FzsABCBCCGCByz^{',$%+..........&-;(/stGLEEEEvHBCCBAHBAx/-@+#-~FPtvLGGCHBAyyxAtCCCCCCCAs/,++*-'FsGGLLLLELLLLLLLLEELutzF),&.+*;'/sGGLLuLLLLLLLLLEuEEExr]!=+.+*;)/JGGLLLLELLLLLLLLEEEvwzF)=+.+$;{/JGLLLDELLLGLLLLEEuEDwr{;*+...&=-']/zsABBCCCHCCBBAxsz^]!,%....@#,;)FrzyxBCCCCCCCCBysz/{!-#....#=;~FzsABCCCCCBCCCCCAAxzF)-%...+#>;)FzyBBCCCCCCCCCCCBtyzF),&..", +"....@*-!{}/IKJJwwwwOI}_'-=&.........&$=;(F[IKJwwwwOPQ}(',=#+.......@%=-'][rKJJwwwwOPI[{;->*@.......@*=-)/QrKJwwwwwOPI2{~;=$&.......@*>-)]/QKJwwwwOJKIF{~->#@......@*-!(}/IKJwwwwwJI}{!-*&@...........@*,;~2QPONNNwJKI/[[[rIK/(=++&=-)[8wwwJKI/}]1|1:[QrKKIIr})*.+&>;_[6wwNwNNNwwwNwwNNNNS6}(;=@..&,;_[8wwwwNNNwwwwwNNNNNS52~-%...&=;(QOwNwNNNNwwwwwwNNNNw5}_;%...%-':QJwwNNwNNwwwwwwNNNNw5{~-%....+%*,'{/[IKJJwwwwwwJKK^[]~-$@....+%*,!{F[QKJwwOwwwwJJI/[]~-$@....@#=-']/IKJJwwwwwwwJJKr/F_-$+....&#=-)]^rKJJwwOwwwwJJzI/F(;$+..", +"...+@$>;(}QI6YMNRNRY52(;,*&+........@%-;(2[<6YMNNMN65:(;,$%@.......+%$,'|}[I6OSSNNS8<1('-*#@.......@*=-!:[QKJMMNRNN6<1(~->&@.......@%*-'1}QIPOSYMNM8<:(!-=#@......@$>;(2[IPOMNNNMY5}(;,$#@...........+$>-a1[<8SNNS8&+........@#=;de4hjqWTTTTqjeba-=#&.......+&*,0b47hpoWUTTTqieba;>$@.......+%*3a|44ipqUTTTTjifba3>&@.......@%*3a:fhhjqWTTTTjifba9=#@......@*>cde4hmoWUTTTqigbc3$%@...........@*=9afgmjWUWqpi77fe47k7bc%..&>cdgpqWqmgeba99-90def7774fb3#..@*,cdfgg5i5mgggffggijUWqieac*@..&*-cdf7hhi5mi77fgggiqWWjiea9#...&$-9dfg5ilmmi77777giqWWqgfc9#...&=3abekhi5mmh77777gjqUWjiba-&....+&*>cdeehpjqUTTTTTqjikfb_3#......@*,;de4hmoqWUTTTqqji4fba,#.....@%*,0be7hpoqUTTTUWjmi7fba,#.....@%*3a|f7lpoqTTTTTqqph74b0,#...", +"....+&>3cbe7mooWUTTWjl71c3>#+......+@#>3!be7mjqWUTTUoi71c3=&+.......@*=;db4hmnoUTTTWmh71a3*#+......+@*,9db4kmoqUTTUqmk4103>&+......+%$,cde4hXnqTTTTqmk4(c3*&+.....@#*30df7lpoTTTTUjh4(03>%+.........@&$-0b4mooqZoonVVllkkkk4b;#..#3aehoWWZmhedc93339cbe4444ed9&..@%-;ab4khVVVI74ef}4ioWWqifd9=@..&*,cae7khlVlhkf44k#+.....+&*,;~]rztAvDEEuuGHxzF~;>%.......+$-;)FrstCvvEEuEGBtzF);>%+......&=-;(F^stHvLEEELHBxz]';$@......@*>-!{FrsAHvEEuuEGAyr]~->%+....@*>-~]rstHvDEuEuvHyzF);=%+.......+#=-~]rxDDDvGGHCCCCCCCtsz/'$+.*~FKADEEEtxrF)';;;'~]/rrrr/]!%..&$3_FrsBACCBAysssxBAGvLGxKF_-&..&=;_FzsACBCCAyssytAHvLLGyI{;$...&=9_FzyACBHHAxssxxBGvvvGyQ{;$...%-;)/zxtCCHGAxssxtBGvLvGsQ{;*.....&=-;~{/rzswvEEEEAxsK^F{!3*......+*,;~{F^zstGEEEvGysr^])!-*.....@%$-;){F^zstDEuEvAysI/])'-=@....@&$,;~)F^KxtuEEEEHyKr^]);-*+..", +".....@$-')]zyCCvLEELGHAs/)'-=&......%=>;'{/zyCGvLEDvvCBs/);-*&.......#=;~]/sACHDvELLvHAzF);-$&......@*-;!{/zABGvuELGGCAzF);,#......@#=-!)/zsBCvLEEEvGCtzF);,*@....&$*-;{/zyBGLEuEvvHAs/)!-=%+......@*-;)/KAvLvCCBCCBCCCCCBsrF'*.+>'/ztvLEuHsr]);;--;;)]F/^^F)-%..+$-!FrxABCCCAyssxACCCBCts^{!,@..@$-'FryAACCCAxssyBCCBCCAs/);*+..&=-)FryAACCBByssyBCCCBBszF);*+.+#>;)FzyABBCCAyssyBABCCtxzF);*+....+%=-;'{F^zstEEEuAsr/F)!;,%+......@#-;!){/zsHLEuDAsz^])!-,%+....+%#=-;')F/KyHLEuDAzr^])';,%+.....@#>-;;)]^zyGEEuHAsz/]);;,%...", +".....+#>-;_1QJJJP6P6JOPQ|~-=*&......+%*>-!_2*@......@#*,-!)2KJJJP68JJJI[('-=%+.....+%$=-!):[KJJJ866JOJK}('-=$@....@%#=-;(2QJJJJ888JOKQ1';=*%@......&*>-;(:5JwwJsKsKKKKsKKr2{~-%..%-_:$*$$=-;;!!'!-$+...&=-'1F/QIKK^/2F[rKKIQ^[{~-=%...+#=-'{F^rIKrQF2F[IKrIQ^}{!-=%...@$=;~{F^IKKKI/}/^QKIQ^[1(;-$&...@*>;_1/[rIKKQ/}2^IKIQ^2:);-#@......+&#==-;_(45wwNO<}(!;->$#+.........%$=-;;1[5MNNO<}(';-=*%+......+@%*>,-;~1[8wNw6<:_';-*#&........+&*>=-;_|[6wNw6[1)!;-=*&+...", +".....+&=;!_:<6O5<[4<8Y6<1~!3=#+.....@&$=;'_:58Y5-'(}<6O5<[Q56Y6[1~;-*&.....+&%$,;~(156O5<[Q<6O841~;-=@.....+&#>;!(1[6OO5<[[56Y5[(!;-*&....+&*>-!(1<8O6<[Q<6Y8<:('->#@......@#>3!_:Q6JPPIII6666665<:_;=@..#,!b[6MSO<:~;=*##%#$*=,>,=>>&+...%*,;__}[QQQ[}::}[QQQ221~-=&+....&*,;_:22QIQ[}11}[*#+...........@%$=-9_e5YRY5}_;-=*%+.....", +"....+%=-cdbfiqqmgffgpqjifbd03*@....+&#>3cdbgiqqpgffgjqjieba0,#+.....@%=-adbgpjqigffijqjifba0,#.....+&*=3adbgmqoige7ijqpiebd;,%......@*,;abegpqoig7fijqjgfba;,#+...@#=30dbfiqqpgffgpqoiebbc3=#+.....@*,;abb7imlliVmoqUWWqqifd9>@..%3cbgjWWqifa;,=$###*$>=>>=**@....%*-cdbe4hmhh4}f7hhh7feda3>&.....%*-cde44hmi74e44hlhhfed03$&....+%*-9db44lih4ff475ihfedac3*&+....&=,cde4hhli7fee4hlhfeda9-*&..........@#$>90biqUUjgb03=*#@............@**>30biqWqpfbc3>*%@...........@%#$>-0fiqUqjfa0-*%&............+&#=9;0fiqUqifdc,*%@......", +"...+&#>0de7hnoZph[7koZZnh7edc,&....+%*30be7hpZophkkinWZph4ed9>&....+#>3a(e7hnZZnh4hloWomh4edc$@....@#>9abekkpZqXhhhloZomk7ed9$+....+#=3_b47koWqmh7hmqZom74bd9$@...&*9c(e7hnoqnhkkhoZqnl72dc,*&....@*>9d:44lVlXVXXoZUUUUUqjgb0,&..#3aeioWWqp7bd03-,>,,3-3-3-,*%....&*,~b4klmonmlllhnnXh7:dc3=#+....&=-a|ehlmoomllhVnnmh4eda3=#+...@#>3_b4klXoomllhmonmkebac,>&....+%=9a1ekhnonmlllmnpl71bac-$%+.........@%*,cafiqUUjiba;,$%+............@%$,9dfiqWWjgba9=#%+............@#*390fpqUUjgb9,>#+.............@%$>0bfjWUWjgd;,>#.......", +"..+#,;~FzxAHGELvHABHDEDGCtxz]~=...+#=;~FzxCCGELvGBAHDEvGCtyr];$...+#,;)/zAAHGEvvCAAGvLvGAAsr];#...+#,;)/syCHvELvHAHHDLDHCtsr{;%...+#-;{^stBGvEEvHtAvLLvHAAsr{;%..&=-)FzyBHGDEDHBBHvEvGBAyzF)3$+..+*-']rstBBHGGGGHGDEEEvDvts/{;%..*_FztGELDHssr/{)~~){{{]]{{);>+...*-!{^stHvLLvGCCGvvvtszF{~;>&...@$-~FzstGvuEvHCGHvDvtsr/]~;=&...&=-~FrstHvLLvHBHvvvGxz^]);-=@...@=-~FzsAHGLLGACCGDDGyz^]);,=@.........@*,;(/KtEEEDyI]~-=*@...........+&=,;)}ztEEEGJr{~-=*@............&>,;(FKtuEEvJ/(;-*+.............&$3;(}JtuEvvs});-$+......", +"..@#-;)^sBCBGLLLHCCHLLLHCCAs/)>+..&$-;]^yBCCGLEvHCCHLLLHCBts/)>+..+*-~]rxBCHvLLvCCHGLELHCCtsF!*...&$-!]rxBCCLLLvHHGGLLGCCBtzF'=...&=-~]zyBCHLLEvBCHGLEGCCBtzF'$++%>!)/sACBvLLLHCBCLLLGCBAs^)!>&..&$;)FztBCHLLLLLLvGHCHHHAyr]),%..*;FIyGLLLHAszrF]]]FF/rrrr/F),&..+*-!]^syAGLLvBCCGvLvAsr/]~;-*+..+*;~FrxAAGLLvCCBGvLGysr/]);>%...&=-~]zsAAGLLGCCBGLDGyzrF)~;,%...%=;~FryxHvvLvCCBGLLtxz/F)~;-#.........@$-;)/KAuEEDxr]!;=#+............&*-;)FPALEEvy^{'->$@............&*,!)/JALEvGs^);-$+.............@$-;)/VALuuGs/);-$&......", +"..+&=-!{/IKPwwNwwJKJwNwJJKr/|;*...@#=-!]/IKJwwNwJJKJwNwJJzQF(;*...+%=-!]/IKJwwNwJJJJwwwJJKr});%...&*>-~FQrPJwwNwJJJJwNwJKKrF_;#...&*,;'FQKKJwwNwJJJwwNwJsK/F)-%..@*-'{/IzJwwwwwJJJwwwJJzr}{!-*@..&*=;(/rIKwwNwNuNwJPKQIQ[2(~;$+..@$;([6wwwJIQ}]|)~)1]}}}/2F_'>+...&=-!)F[IJwwJKKKJwwO<}]_~;->&...+&=-'1/[KJwwJPKPJwwOQ}:_~;-=&...@*>-~12QIJwwJPKKJwO8Q}|)~;-=&...@#>-~]2QIOwwJKKPJwwPQ:{(!;,*&..........@*-;_e5wNwOQ|'->#@.............@&*,;~}5wNwJ<|!-=*%@............@%*,;~26wwwJ[|;-=%@..............&=--)26wNw6[(;,>#@......", +"...&$,;(}QI5OSSOJPIPYSSOK#+...&*-;(:2<8OO6III6YY6[1(__;3=%...+%=-~_:[<8YO6I<<8OY6}1((~;-=#...@%>-!(:}<8YO8III6OY54:(_~;-=%..........&*=-c|5YSR84(;-=#&.............@%$=9_|#&+...........+@#$=-a:5YSY84(;-$$@+............+&*>-a15YSR5e_;,*%&......", +"..+&=3cb7hmmjZqommlmjqqoplh7d9*...@*=9ab4hmmoqqqpmmpoqoXmlhfbc*....#=-cbkhmmoWqomlmmqWqommhfd3%...@$=9af7immoqoopnmjqqZXmlhfdc$...@*=9aekimmoqWjmmpoqWopmlgfd9#..@$3cdfilpoqWopmmnqWWomlh7bc3*@..@*3cb7himjqWWUUqqjih77febba0$+...%>0d7hilpopmhk77khimjjjifbc$+...@*-cdefgpoomlkhmpqjgfbbdaa9*+..+&*3cdffhpoomihhmjqpgfbbdda3*...+%*-0de4hpoomihhmjqpgbbbbac3#...@%=3cde4ipoomhhimjqigfbbbaa-&........+@%*,9abiqWWjgb;3=$#+...........+&%>-cafiqUqjgd0->*%@...........+&#>-cafpqUqjg_c9=$&+...........@&*$3;dfiqTqjeb03=#%+.....", +"..@=-'b7inXoYZoXXVVVnZZoZomifd=+..@*-!b7mXoonZZnnXXXnoZooonlfd,+..@$3ab7mnnooZnnXVVXnoZoooXie0$...%=9~b4mXonZZoXXXXnoZoooonhfa=+..#>c_bhmnXoZZonXXXnnZXZnomkea*+.%-0d4iXooZZoXXVXnooqZooXi4dc,&..%30d7inXoooqoqqZoXVlk7k444e_9%..+%>9de4lmnZZoXVVVVVXZZWZph:a,@..+#,cdb4klXnXmlhklnopmhkk44ed,&..+*=9~b4klXnXVlhhmmnmVkk444e_=+..&*>9ae4hlXonVllhmnjmik7444e0$+..&$,0de4klXXXmhklmnomlk4444:a$........@*=33adgiWUUoiea03,=*@.........+@*>,30bfpqUUogedc3>=&+.........@#*>,0abgjUUWjged;3,$#@.........@&$=39abgjWUWjhbdc93*#@....", +".+*;)FzxHEEDDCCBCBCCHHGDLEDHs/'@.+$;)FzyvLLLLvHGCBCCBHvLvLDGs/;@..*-)/zyDEELvvvCBCCCCGvvLDDts/;@.+=!{/sADvEEvGCCBHCBCGGLvLDAsF;+.+=!{/stvEEvGGHHCBCHBvvLLLDtKF-@+$'FzxGvDEDvHCBCCCBGGDLEDGyrF!$++$'FzxGDDDvGHHGGGHBCCAxyyAAAz{=..+#-!]rstAGDLDHHCHHHHLEEvGyzF;%..%,'{^zxABHvBHtAttBHCCBBBABxr{*.+*-;(/zytBHGHBABtCCCCCBCCABxr;@.+*-!)/zxABCHHBttAtCHBCCBCBBy^;+.+*-~FrsyBCHGCCAxtACHHACCBAty/;+....+&#=;'){FrsHuEELtsrF{)'-$@.......&#>;!)]/rxGuEEvtK^]{~'-#+......+&$,;'{F/zsvuEEDAz^]{'!-=@......+%=-;~)]/zyGEEEvxzr/]);-$&...", +".+#;)/zyvLELLGCCCCCCCBGGLEuGxr;&.+$!(/KtLEEEGCCBCCCCCCBLEEDHxr~&.@$!{^KtLLELLCCCCCCCCBvLLuLGyr;@.+>;{/stLLLLLCCCCBCCCBCLEEuGs^;@.+>;]/KGLEELLCCBCCCCCCGLEELHs/;@+*)^zyvLELLCCCCCCCCCCGELuvxzF)$++=)/zAGLELGBBCBCBGCCABAtABCCsF-+.+%-!{rzyAHGGGGCGvBBCGGvvtsr]-&..#-']rsACCBGGCAtyABCCBCCCCCAs{>++%;~]rsACCBCCCBtytBBCCCBCCAAr~&..*;)]rsACCBHHCBAxBCCCCCCCCBAr;&.+#;)FzxCCCBHCAtyABCBCCCCCCCxr;@....&*=;!{F/rzxHLEuEBxzr/])!-#......&#>-~{F/rKyGEEuLByz^/]);,#......+*>;!)]^KsxGLEEGtsr/F]);>#......@=>;~]F/zzxvLELuAszr/]);=#...", +".+%>;(2....%$-')]}QIPJwwwwJJKPI5<21_-$+..&>;)}IPJwwwwJIrIrIKKJJJJKzQF'*.+&,-~}'1[5MNNYOPQQ2}2[QIPRNNR6<|,+..%-~|[5MNNSOKQQ2}}[QIORNNR8[|-+.%-(}-9~|:[QPJJJPQ[}:(_0,$#+...%,9_25OYwSYw8PKIIIIPOwwO6<[|!*..%=;_26OYYSSY8PPPIKPKOwYOPI[(-@..&=3_48OSYYwYJ5KIIIPKOYwO6<[)>+..#=9(48OSMSNY8PKIIIPJOwwOP<[(=....+%$>-_(}}[Q58SNNR8IQ[}1(;-#+.....&#>;_|2}[<58SNNR6;_|:[Q<5MNNNM6;_|}[[Q6MSNNY6QQ}}1(;=&...", +"..%>cbfiqUTUqmlkfee4kimqUTUqif9@..%,cb7iqUTUjmkkfee4hhmqTTUjie3+.+%3ae7mqUTUomh74ef7hlpqTTUjhf-+..#-0bgjUTUUjpk7eee4hloqTTUjgb3+..*9afhpWTTqomh4eee4hloqTTUjgb,@+%cd7iqUUUqmkkfef4hhpqUTUqigd3%+.#;bgiqTTWjmmjWUUUUWWopnpjWqid>.....+&#$,cabfhmmVmikfbac3>*&.....@>;dgjWWUUUWopmmmpmnqWWZni71c*..%,0bgjWWUUUWqmmmmmppqWWZjl7b3+..&=cbgqWWUUUWqnlmmmnoZWWZni4b>+..#,0bgqWWUUUqopnpmppoqWWZph4d>....+&*,;defkh5mqTTTTjmkh74ba-*@.....@*=9de4khlpqTTTqjlhh4fba-#.....+%*,;de47klpqTTTqjlhk74ba-#......&*,cde47klpqTTTqplh77eba3#...", +"..%,abhmqUUUqXll7444lVXZUTUqm7c@.+#,a:hXqUTUZnVh444kllnWTTUoVec@..#3_ehpZTTUnXVk74kklVnWUTWoie9+.+%3d4ipWUTUZXVk447klXnWTUUom49@.+*;b4ljWTTWoXVk447hVXoUUUWome9+.*;e4moUUUZnVl7447lVXqUTUqmkbc#..*cehjqUUWZmmoWTUUUUWZnnXoUqjb,......@#$,cdeklVXXXlhed03=*&+.....%=9bgoWWUUUWZnnnXnnoZUWWoVhec#..%3abiZWUWUUWoXVXXnnZZUWWnmke9@.+&,;bioWWUUUWZnXXXnnoZWWZnVkb,+..%9cbioWUUUUZonnXnnnZWUUZoVkb,+...+#*3ab4khVlnqTTTUoXVlhk4dc=&....+%*3a:7kllVnqTTTWoXVlkke(9$+....@#>3ae7klVVXqTTTUoXVVkked3$+....+#=9_e7hlVmnqTTTZXVVVkkea,*+..", +".+*!]rstvEELDHCtysyxACHLEEEDHs)%.+=']zyHvEELDHBBsssxCHGDEEEGAs)&.+=!FzyHvEEEDHCAxsxtCCGDEELGAs~&.@=~FzAHDDEEvGCAssxtACGDEEEGtz!@.+='/ztvLEEEGBCtssxAAHvEEELvtz'%+=_rxAvvEEvGCtysxxBCGDEEEGHxr{=++>(rxGDEEEDGHvDEEDLEDGGGCGDDwe,+.....@#,c)/sxBHGvGHxzF~;,=@......%-_/xHvLEEEvGHCGCHCvvLLvGByr)*.+*;]IsGDLLLLLGCBCBCHvLELLGCxz'&.+*;_/xGvLDLvvvBCCCCCGvLLvvAy/-@.+*!1IyDLLLEELHBCCCCHvLELGGAs/-+..+&=-!{rxtACCHvEEEEvGBCBxs/)3%....&=-'{rstCCBGDEEEEGBCCBxs/)-%....&$-~FzxAACCGvEEELvCCCAyzF~-&....@$-~FztACCBGDEEEEvBCCAyzF~,@..", +"..$;)/zyAGHHBBAyszssABAAHBHtxz)&.+*;{/sxBACHACBxsssytAAAHHHtyr~&.+=;{/stAHGGCCtyszsttABBGHHBs^~@.+$!]rsxAHHHBBtxsssyAACAHAHts^'@.@>;]rstHHHHCBAysssyBACAGGAty^;@+$)^zyAHAHBCAysszyAABCAHHAxs^)$++>)^sxtHHBCBACCBCCHBCCBCBCHtsF-......@$-;)/sBHGLvvtsr{'->%+......&>!1ztCCCHGCCBCCCBCCCHHCAyz/'*+.#;)/sABCCCCHCCCCCCCCCCCCBxsF;@.+%;']zACCCHHCCCBCBCCCCBHCByzF-+.+*;)/stCBHCHBCCCCBCCCBHCBAyz]-+...@*-;)rzyABBACAHHHCABtyyzF),%....@%>;]/zyABCCBGGGHBCABxsrF)-&....+*-;]/syBAACHHGGHACAAxsrF',&....+*-~]rsttBBCAGGGACBBtysr]~>&..", +"..@=-_(:}[[[Q^/F]{]]F2[[[Q2}:_,+..&>;~(}2[[Q[^/F]|{]F/[[2[[2{_-...%>;~1:[[[[[^F]{(]{F[/[[[}2]~=+.+%>;_1:}[2[^^/F{{{]/[^[[[[2{~>..+#,;_11}[2[[^FF{{]]2[[[[[[}{~=+.%-~(:}[[Q[//F{){]F2[^[[[2]{',&..%-~1:}[[[[//[^QQQQIIrIrQ^[}_-%.......@*,;(2IJwwwJQ:_;-=%+.......+%-;(:}[Q[III^rrQ^Q/QQ[[/:(~>@..+*,;(2[/QIQQrQQ^Q/QQQQ[/2](!$...@=,;_:[[QQIIQ^Q^I/Q^QQ^[2F(;$...&*,!(2[/IIIIQrQrQ^QQQQQ[F:)!*.....@*,;~]]F/^[Q[[[[Q^/FF]_!-$+.....@#=;))]F/[^QQ[Q[Q^//F{(!-*+.....+#,;){]F/[^2Q[[Q^[/F]])!-#+.....@*-;)]]F/[Q[Q2QQQ//FF])!,&...", +"..+#,-!_(_(||(__!!!!~(((|((_!,*+..@%=3'~((((|(__!!!'__(|1((_!-%+..&*-;!___|||((';;!__((((|(~';*...@*-;!_((1(((_'!!!'_((((((_';*+..#*-;'_((1(((_'!!!__(|_||(_!-%.+@=-!~_(|(1__!;;!!~(_((((_';;$+..&>3;~_(||(__((({|||:::::|(_;=@.......@%*-'(}<668<:~;,$%@.........@*>;~)(|::::1111:|:||((_~;-#+..+%*-;~_(1|1:|:1]|1{|||__~';-%+...&#-;~(((::1::1:|1|1(|(__!;-#+..+#*-;~((11::11|1:||||||(_~;>%.....+&#=;;__(((||1|||1((~~'-=@.......@*>;''_((_||1||(((_~';-$&.......&#,;;__((|1|1|||(((_!;-#&......+&*--!__((|||1(|((((~~;-*&...", +"...&*>33cc0;0cc9-9939c90cccc9=&...+%$>,9900c0c99-333c9c909cc3=&...+&*,39cc;c0;9-3--9cc009ccc9,#....&*,33c90090c933333000c9c9-=&...@%=,39;9c09cc93339ccc0c0;c-#+..+*>339c090099--3999cc09093,=#+...#,-39cc0cccca00a0c~a_aac0c3%........+@#*9;abbffba3,>#&+..........%$,39c!a_aaaa0c'0a0!0cc93=&....@%$>;c9_aaaa~aa~c00000cc9-=&....@&=3-c0cc'a'a~a~0cc000c99,*@....&#>>;cc0aaaa~cc0'0000c099,=&......+%$=,330900~a0;0cccc-3=*&.......&*$=333c0c0~a000;9c;3,=#+.......@%$,339cc0c000aa0cc33,>&+.......&%>,3939c0a0000!;c993,>%@...", +"...+&#=,,3,3,3>->,=,3,9,3-3,,=&....@%*$>-,>-3,-,>,,,,3,-39,,>=&....@#$=,-,33>3-,>>==>>-3-3-,=*@....@#*=,,9>>-,,,,>,=,>>>--,3>*&...+&#*=,,9-,-3-=,==>,,-,3,3==%+...%*=,-,,-,>-,$>>,,9,,3-,,>**@....@#>>-,-,99399999999933-9,>=#+.......+%%*=3-00a003,**%+...........+%*>-933339;939333;93-,=**&....+%#$,>3-33;993999-3-3-,=>*#@....+&%*>--939-39c9-3--3>-,-=*#+....+&#>,,-3-3;999993--3,9>-=$%+.......+%*=>,,-33399939-,=>$*&........+&#$$=,-,-33993339,=>*#@.........&***,>-333-3333-9,,>$*&.........&#*=>-9--939,-33,-,>$%&....", +"...+@%$->---------,-------->-$&....@%=>=---,-----,>>-------->*@....+&**-,----,-,>,=>->-----,>#@....+&%$>----,---,----3----->>#+....+&#$>--------,-->------->=%....&**>------>,==>----------#%+....@#$>--->----;;;;;;;;;;;--,#@.........@&#=-;;!cc;;-*%&............+%$>--;;;;-;;;-;;,----,$#&@.....@#$,--;-;;;;;;;;-;-----==#@.....+%*>---;;;;;;;;-;-;---->#&......@#$>---;;;;;;;>-;-;>--->*#+.......+#$>-----;-;;-;----=#&+.........@#*=,------;;;---->=*%@.........+%#$>---;,;;;;--,-->##@.........+#*>-,--;;-;-;---->=*%@....", +".....+&%**%*%*%#%**#%#***#*#&@.....+&&%***$**#%#%%##%*$###%*%&+.....++&%##*#**%%#%##%****%**%@.......++&**$**%*%**%**$$**%%*#@......+.@&##$*%*%%%&%#**#**#**#&.....+%##$$***%%%%##%*#$*##%%%+.......@%%%*=*$*$#$*=$$>>====*%@...........+@#$==>>>>##&+..............+&%**$$===$=$*#$>*#*%%@++.......+&*%#$$***$==*#=$=$**%%@+........@%#*=====$*$$>$=#**%%&+........+&#**$*$=$##$=*#=$$*%%##@..........+@%%*#*$=***$$**%%@+...........@%#**$==$**$*#**%#@+++.........+.++%%##*$$$$$=$*%%%&+............&%%*$==$=$===$#%#%&+.....", +"...........+..++..+.+.+++.++............+.+.+.+++....++++...............+.+.++........+.+..................++.+..+.......++.............+....+..+....++++.+.............+..+.++.+..+.++++..................+.+.++.+..++++..................+++++++........................+++...++..++.++..............+...++.+.++.......+..............+++++......++..+++.................+.++...+...++.................+.++.++.+....++....................+..+.++..+....................++........++...................+..+++++.+.++.+........", +"................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................", +"................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................", +"..........................................+@&%%%**%%&++++..................@&%&@+...............................+@%%%@+.....................+@#****&+.......................+@&%%%%%%&++................................................................................................................+@%%#*%%@+.............................+@%%%%@+....................@%%****%@+............................................................+@%%&++........................................................................", +"...................++...................+&=-;!))~{)'!--,-=$&+..........+%*=-~);;--=*&+.......................%*=>;''!-,$%&+.............+%**=-~({~);->*&+..............+%*>>-;!))))'~!-->>*&+..................................................................................+++.+@&&@+.............+&*-;!')!;-,$%@+......................@%$,;;;~!-,%&+...............@#,!))())'-,*%@+...................+++..............................+%*>>;;';-=*%@................................................+%*****%&+...........", +"......@&%%&%##%%&%#%%%&@+.............+%#>-;))F/^//F])))'!--#@.........%>-;)]]]~)';--%+....................+%=>;!)]]])~-,*&+............&$-;!]/^//])~;-*%+............+%*-;!))(F/FFF]]))';-=%+...........+&%&#%%%#%&%%@+....................................................+@%#*###**==###@..........@$-;~]]]{)~'-,*@.....................+#>-;!)]]]~;-*%.............+#$-!)F/r/F])!-,*%@..............+&%##*%%%##%%%@.....................+&$-;!))))';-=*&...........@&%&&@+...........................+@#$>--;--*##&@........", +"......@&%$#%**#$*#*$#%%&@.............+#*=-;)_]}/}F]_()))!-=*@.........&*-;~{{1{)~;-=#+....................@%>=;;'{]]~'->$&............+@*=-;)F//}]{';-*&+............@%*=;!)(]1F}]({_()~;>*%+..........+@%#%###%*$#%%@+..................................................+@&&#%#*#*$$=>**%%+........+&*=-!){({()!-=*@+..................+&&*,-;!){{)!->*%+...........+@%*,;)]}/}F();->*@+.............+@%##%#%%%%*%&&@+....................@*=-;!)({{';,*%@..........+&###$%%&@@........................&%*>,--;-,$##%@+.......", +".....&%#$*>$**>**=$*$*##%&+..........+&%$>;~(:}[2[}}:1}1(~;>*@........+&$=;(1}}1}('->#@...................+%#=-;~(1}}1!-=*&............+#$,-~|}Q[Q}|(!->*&+..........+&#$-;(|}[[[[}21::1(!->#@..........@#$$$*#*$**$$$#%@................................................@%&#$*$=>,>---->**%@.........@#>;_|}2}21~;>$#@..................@&#*-;~(|}[1_;,$#@...........+%$,-;_}[QQ[:(~;=$#@............+&%#**$*$$$$$$$#%&+..................&#$>;'_(}}1(;-$#&.......+&&%*$$$*$*#%%&......................+&*>,--!;;-,=$#%@.......", +"...+&*$*>=333333,-3,,>=*$$#&+........&%*=-0de44hhh74f44fedc-*&........+&$,cbe7774e~9-*#+..................@*$-;adbe74ea9=*%...........+&%>-0df75kh7eba;,$%@..........+%*>9abe4hhhk7eeeeeba-=#@........+@%*=,,,>=>,-=,>**%+.............................................+@%$*=>,,-3cc90c0c>=*&........+@#=;de4774e_c,*#%@................+&#$=;0dbe47edc3**@+..........@#*-cab4khkkeedc3$$%@..........+&#*$,-,==*=,-==>**%@+...............@%*>3a~be47eb0-=#&+.....+&$$>,,3>,>=**##@....................+%*=,;0ad_dc93=$#&+......", +"...&=,3cc_a_d~dd_dddaa0c3,==*&......&%>,30_e7klVVlllhhhk4|a3=%........@#=9'e[lllhkea93*&+................+%$30d|e4klhedc3*#+..........+&>3ad:klVVVlk4:dc,$%+........+%*,3a14kkllVVlhkkk4edc>*@........+*$,;!aac;cc0aa993>*%..........................................@%#=>39ccadd(bbbee1da9=#+.......&$=99b4klllk7d09=*#&+.............+&**3c_be[kll4e_;3=#+.........+%$-0d:4klVVVk4ed03=>#&........+&*>>;0~aac;c!aa0933==#+...........++&#$>ca(e4kkVked03=*@.....%*,3ca0_daac9-,=*%+.................+&#-0dd1ef4ee(a03=*#+.....", +"..+*!{F^zssssssxsssssz/F]{)!-$+....+$-')]/zxBCBCCCBHCCBysrF~-=+......+%>-']rxBACCAyr]);>#&+.............@%,;)/zyyBACts/{'-=@.........+#$;)/zyACCBCCCxs^F';>#+......@#,;~]/sACCCCCCCHHCAyz^);,%.......+#>-~Frzr^/F/rzz/F{)!-#+.........@@@&&@+.........+@@@@+........@*-;!){F^rssssyyAABBxrF!-&.....+%$-;)]rstBCCAyz/{~;-=#%@+.......@%#=-;;)FrsxAACBxr/{';,*@......+&*,;)FzyACCCCCBAyz/])!-=@......+%*-;)]rzzrFFF^zzrF]{);-#+........+&$=,;;~]rsytBCBts/]);-#....&>-)]rzssssz^FF{~;,$%+..............@#,;)/zstBBHAAxsrF);-*&+...", +"..%-~FrsxBACCBBBBAABAAyz//]{;-%...+#=;)]/rsBCCCCCCGvGHBxs^{~;>%......@#=-!{/zxBCBAyz/]~->*&+............#>-~FryABCBtyz/);-=#+........@#,;]ryABBACCCABxz/]~-$#+.....+*-!{/ztACCCBCBHGGBtsrF)-,#.......%*-;)/ytyzzzzxAysr/F);>%........&%$>==*%%@+..+@%%#*$***&......@$>;!)]/zsABBBBACCGLDGy/{;$+....@*>;~)FrzyAACCBxr/)!--=**&......&*=--;;){/yBCCBBxsrF)!--=%......%>-;~{rsABBAAAACBAsr/]);>#+....@&*,;']rsyysr/zsyyyzr/]);=%......@%#*=-;;~{/stCBBBAsr/{~;-*+..+%-!]ryBABAAAxzr/]~->*%+............@#=-!]rxBCGGLLHCAs/{';,*@...", +"..@$;)F^IzKsKsKzKzKzzKr^F1(~;>&...+&*,;)1F[rKKJJJJwwwJQ2F)~-=*@......@&$>-;){/rzKzQF|';>>#&@..........+@#>,-)FrKzzr^F|);-*#@.........@#=-~F^rKrrrrKzr[]_~;,$%@.....+#,;!)]/IKzPJJJwwwI[]_!-=%@......+&#=-']^r//1FF/rQ/]()!-*#+.....+@&#*$$>$*#&@@@@&%#*****#%+....+&*=-;~{F/QrzKzKsJJwwwO<|!>%....+@%$=-!~{]F^KzrI/F{~;-,>*%&......@%$==--!)]/Izzrr/F|)!;-=*&.....+%*>-;~]/rKrrrIrKzr[F]);->#+....@&$=-;)]/Ir/F|F/rr//F|);-=&.....+&#*$=>-;;']/rzKzr/F])!;-$*+...&=-)F^zKzKzKr/F|);-=*#&@...........@#=,;']^IJwwwwwKK^]~;-*#@...", +"..&$-!(2%&+.......+&#$,!|}Q[[[}[QQQ}:(~;>*%+......&=;'(|}[IKIPPPOOO<}(_;-$%@......@%$$-;|[Q[}:|2[QQ}:(~;,$%@......+%#>----=*#%%&%##*>--->>*@....+%*-;((:}<$&+....@%$=>--;'_|[QIQQ22|1~_;->*%+....@%*,-!_|2QQ[[22QQQ[}:(('-=$&...+&#*,;!_:[Q[:|1|}[[[}1|(!-=#+....&#*>=---;!_|}QIQQ[[1|(_;-=*&..+%*-!1[QIPPP5Q[}1(~-,$$#%@.........+&*>-;(1*@...", +"..&=9abgmqoqnmlhkhh-;abe4h*%@........+#*>,90be45h-0:4hk7747hkh7ebdc-*#@.....+#=;adb44hllmVmoojifbac-$%+.....+&#=>;ab7h744f77<77ebdc3$#@......&*=9caa09=$*$#**$39aaac,=@...+&=,cbefgmjjphkhmoqWWWWqifa3#....@#>9!adb:ee44kk44eebdda;33*@....&*>-caadbbe7kk<774ebbbdcc,$@...+%$=90dbe7,;adbe7hkf:bb44h774eed0-*@...@%$,9;aa_dbb:77=**&+........+%=3cdbgioopigimjoigbda3$&...", +"..#=;_ehnZWZoXVVllllVlXoWUWpgb,+.+%=-a:4kklVVVlllmXnXVVkk74|dc#.....&%=,39d:4klVVVlhk4eda93$#+......@*=,-c_e4kVVVVllk4e(d03>%+.....@#*>3abekllVlllVVVk4:ba93*&....+&*,c~b}7lVVXXXXXXXl7:ba9,*&.....+*=,ca14>33;abebd0,#...%*30b4klVoZZnmllXZZUUTUqp7b0$+..+#>9de4k7kkkkk7k7kkkkk74e(a9*...@#>9a|44kkkk9ad|e47k7kkkllllIVlkkk4410>+.+&=3aeklmnZWoXVkk44bd0c3=$%+.......&*,0de4hmZomlhlmoZni4ed0>%...", +"..*;{^stDEELDCCCCBCCCCHLEEEGs^!@+&=;{/sBCCCCCBAtxABCHBHCCAAsr{=+..+%=-;~]FzsABBCCBCCAysz^F);-%.....&=-!){/ryABCCCCCCCxsz/F)!,&....+#-;~{/zxtCCCCBCCBCBysr^{~-*+...%>;!{/rsxBCCCGBGCGHAxsrF{!-$+...@*-;~]/zxACBCBBCCCCtysz^]~;#.....#-;)^zsszrF{)~~))]FrzssrF'>+..*-)FzACCHGLEGHCHHDEEEEEDGsrF-#..%-!]rxBCBCCAAysyyBBBACAAAsr],+.+$-!]zyBABCCAAyxxABBCCBCBAyr],+.+%-~FzxBBCCCCAyssxCCCCBCAtsr];+++$;'FztBCBCCAxsssxACCACCAtsr{=+.+$;{/zxBBBBBCCABABCCCCCCBAAs^;@.+*;']ztCHGLEvHCCBtysr/F{)!;=&......*-']^zxBvLDHBACHDLDBxzr]!>+..", +".+$-)/zAGGLGGCCABBABBABGGLDGA^'%+%,')^yBCBCCBCByttBCCCCCCCBxr{-+..@*,-~]/rsACCCCCCCCCCAysr]);$+...@*-!)F/rsACCBHHCCCBCyysrF~;=+...%,-!)FrzyCBCCHHBCCCCAysz/{!>%..@#-;)]rzsACCBCCCCCCBBAysr]~;>&..+#=;~{FrsABACCCCCCBCCAyszF);$+...+$-~]ryBBxzr/F]{]//zsABAs/)=+..*;)FstBGCvGvHCCBCGLLELELtxrF~#..#;~FsBCCBCCCAsssytCCCCCCByz{-@.&$;)FsACCCCCBAyssyACCCCCBBxz{-+.+*;)/sCCCCCBBysssyABBCHCCBxr{;%.+>;{/sCCCCCCByszsyBCCCBCCByr{-..+=']rsBCBCCCCBBAAtBCCBCCCCByz~@.+*-~]ztBCvLLLGCBCCAxszr/F)!-$@.....%-!]rstAGGvCBBBCLLGAysrF'=+..", +"..#,;~:[IJJJJIrI^^^^[QQPJJ6KQF-@.@*-'(QJwwwwJJrQ//QrPJwwwJK[{;*...+&=-!(F[IKJJKKKzKKzKJKIQ|~-=+...@#>;~]}[QKJJJKJKKKKKPPK[:!-*@...&=,;~|F^QrKKKKPKKKKJJPKQ|~;=@..@#*-!(F[/rKKKKKKKKKKJJKI[|!-=@..@**,;)]}^rKzKKKKKKKKJJPI[('-#.....%=-~2IJPKQ2F|))(]}QIJPJQ1;*...&=;)[PJwwJPPIIIIKPJwJOOJPQ})-%+.&,-)[KwwwJKr[FFFF[IKJwwJK^]~=+.@%,;([JwwJJKr/FFFF^IKJwwJK/1!=...%,;(QKwwJJKr^F]F2^IJOwwJK[]!=@..%-;1QJwwJKKr[F1F2/IJwwwJI[{;*..+#-']/IJwwwJJzQ//F^IKJwwwJKQ(-+..&=-;{/QKJwNNwwwJJJJIQ/}]);-*+....+&=-!)}[QPJPIQQQPwwOK/}{~-#...", +".+%*-'_:QKPPQQ[}:1||11}Q5PIQ[1;@+@#=-(<6OwSSY8<[}}[[<6OSYO<}(c#...&$>;_1}Q5JOPPQQQQ-'|[QQIIIIIQQQIIK8MMO<:'-*@..@#>-~|}QQIIQQQ[Q[QQP8OYO<1!-$+...+&=3(78OOOI<}:_((2[QKOOO5:c*+..&=c([6wSOP<[[[}[[IIIPPP3_46OwOP5[:(_(11[KOYYO52(;*+.+%>,d[OYwOP<[1(((|}[8JSYO<}(;=@..%=;(<6OwOP<2|(_(|2Q5YYYO<}(;*+..&>;_1<8YNYO%+..", +"..&=90bfimpXik77eb:bbbfgillhhfc@++#>cbgqWWUUUji7ff44hpWUUqieb;%...&=-cbf4hmoqomk7khhljqWWjgbc3&..+&*-ab4khmoZomh4khhmpZWWjgbc>%..+*>3ae4;ae7hlhllkhk7khhmjWWqpfdc>@..@*,;df70bgjWUqpg477774hhlmmlik74b9%+.&=3dgqWWZp57ebadd1fiqWWqm7bc*+.+&>9dgjWWqnk7ebad1b7iqUUqi7bc*...%>cbgqWZqmh7ed0ddbgmqWWqieb;=@.+%>cbiqWWomk4bd_abegpqWUqiedc%...&=9abgjqUqqik4:bb47hpqqWqiea>...&*>-abfgiqqUWqqqqqqmllh7fbc3&.....@*,;def4hihhghijqUjifed0-#...", +"..#,cdehmoZoopnlk7444e4hmVVVhk0%.@*,ceiZWUUTUZmhkkkhlnWUUqpkba*+..#,0(4hVVnZZomlhkllXoWWUoifd9*..@*3cb4hlXXZZnmhkklVVoWUWoiedc#..&*3017lVlVVVlhkhhlVVoWUWjhea3#..@=3a:7VVVVVVVhkhklVmqWWWjhba3#++&=3a:klXVVVVVlhkhlVXoUUWjgba3%...+&*9cegmnmnnmlhhhmXonmmigbc#+..%9afioWUWpikkllVlllVmmVVVVkea*..&,cbioWWZnVke1bdbf7pqUUZj4ea>+.@$>cbiZZWZnVk4|bdbfkmZWUqmhba$+..%3cbioWWZnV+.%;)FzAHGGCCCCtyttBBCGvLvvAs^)=++#;)/ztHHGBCCAAxxxtACGDLvGts/)*..#;)/stHHHCCCAAAxytBHvDEDGAz/'*...+#>;_2rsyGDEvGBAHvDLGAys[{'=+.+=)/stLLELGAtACCCCBCBCCBCBCBs/,++*!{rtvLLDGCts^/^^zsHEEEEvxz]-@.@>'{zyvLLvvCtz^//rzxHvEEDGyr{-+..*!{KtGvLGHCtzr/FrsyGDEEEGyz];%.+=!{rtvDvGHBxs^/^rsyHvEEDHxr]-...%>;(^sACHGCHCAysstACCHHHHxr(>...%,;)/zytCBHHAyyyyAAACBCCCBsF-....+*-~]rytBBGvvDLEEEELHtxz/);&..", +".+$;]ryHLLEEEELGCBtxszsxABCCBy]#+&>']ryCCCCHGCBCCCABAHLLELAsr{=+.+>)/zAHLvvHCtszzzssAABHGHCAz{-+.%;)/sAGLvGHCxyzzzssxACHHHBxz]>++%;{/sAGDLGCBtsszssxxCCHHCAyr{=+.&;{/sHvLLGCAAszzzsyABBHHCAyr(>++*;]rsHGLLCCAAsszzsxAAHHHCtyr)=...+#=;~]^zsAGLLGHCHDLLvAsr/{;$..+>_/KAvLLvHyABACACBABCCCCCCAs]-@+=!FryCCCCCAyz/]F^rstGELLHyr]-@.@=;{rxCBCCCAsz/{{FrstGLLLtsr],+.+$;]ryCCCCBAyzF]]FrstLLEGHyr];%+@$!]zACHCCCByr/FF/KsALLLLtsr{=+..&=;)FzyCBCBCCBtyxyCCBCCCAs^)=+.+#,')/zsABCBAyssszsyBACCCCAy^-@...+#-)]zsACCCHLLLEuEEGHByz/{;*..", +"..%,!1[IONNNNNwJKQ/FF{]/^QrIr[~%+@*-!]QKKJsPKKKKKKr[QPwNwOP}(;*...*-(}PwNwwI[/:()(]{2QKKKKIr}_=+.@,;(}PwwwJI[F]()({]2QKKKKKQF_=..@>'1[6wNwJK^F]{){)F}QKKKKIQF~*++&-!|Q6wwwJI^F]()({]2QKKKKI^]'*..%-!:QJwNwJI^F])))(][IKKKKI/1'*....@%=,;~1}+++*=;([KKJKI^}|~;;'(2;1^IKJrI/:{';;'(25wNwOP}|!>@..%-;|[KKKKQ/}('!!~{25wwwOK2(;*....&$-;(F/^IPJJKI/^IJJJKI^2]~-#...@*,;)F2^IKKr[2]:F:/QrIKKzI^{=+...+%*-!]F/rKKJwwwwNwNOPI/2{~-&..", +".+%=;(1<6SSNNYJ5[221__(|}[[[Q[!&+@#=c_}QQIIIIKIPP5Q[[5OSS8<|_-%..+%-0:5YSS6[:('!';;_(2[QIIQ[2(>+.@=9_15OwY6[1(!;;;'~(}[QIQQ[}~>+.&=;_ePRNS6[1(_!;;;~(}[QIIQ[1~=+.&=;(}6RNR8[:__'';!_12QQIIQ[1~$+.&,c(46SNY5[1(~;;;;_(}QQIQQ[:;*.....@#=,3!125OwYOO6OY8<1(~;-*&...%-01c_}QIIQ[}(~---;_1QOSSO<1_3*@..&,9(}QIQQ[1(~---;~{+.@$cdfiqWqpgba9-9-90ae7hkhh7fd=+.&=cdfpqWqpfb_c-3-30de7khkhkfa=..&,cbfjqWqifba;3-33cde7khhhkf0$+.@,cbgpqWqifd0;9--3cde47hkk7ea*.....@#*,9cbfhioqWUqjpigba0->*&..+%3abgjWWqi7f7hlh74ff74hkhh4e0*.+&=3afkhlk7edac,--9dgjWWqieac#...%=9afkhhh7eda3-,9;bgjWWqgea3%...%=cdfhhhh4:b03,>9abgqqWjgbac*@.+&,0d4hhhh4edc3,,-0bijWWjiba3#....@%#=3aab7ioqmi4hioqpgeda9,#+...@#*9abe4hhhkfbbbdbb47khhhkfd>.....%*3cdb47hhlhhg7gimpjjjpgd3%..", +"..#,cbflnWWWoXlh4ee1bbb4kklllka&.@*30|7lXVVVVVnZonmhhXZUWZifdc%...$0d4pZWWjhbac33,39deklllllkb,+.&,cbgpWWWphba99>,-c(ekkllllkb,+.&,ab7pWWZj7ba99>-99beklllVl7b>+.%30egnWWWp7b~93-,3cb4kkllVh7d>+.#9aegoWUZpfdc9,3,9adekklVll4d>+....&*>30d14hmnWTUUoXVk4bac3*&...$9demoUUZphkklVll[4kklllllh40*+.&=cd4lVVVh4e0;339abhoZWqm7dc*+.+%,;b4lVVVk41ac39cabioWWqmfdc*...%3cb4VVllk71ac3-caeiZUWZm7d9=+..#3cb7VVllh4|dc-39abiZWWoifd3%....+@*>-0db4poZnVllmoZohedc9=#....@*=;a14klVVlk42ee44klllVll7b,+...+&=-ab4kkVVVl744..@-{rsHLELvyr]);;;~)/ztAABBCtr'@.%;]/yHDEEGyKF)!;;'{^stCCCBBx^;&+*!FIxvEEEGyrF_';;~{^stCCCCBy/;@+*_FKxDEEvtJ^]_!;;~]^sACBBCAy/;@+*~FzAvELLHK^(~;;;~]rstCCCCAs/-@...+*-;)FrsxBHGEEEEGGHAsr/{~-*...>)/zAEEEEGCCBCCCAyxxACCCCCts]-++*;{FsBBCCAyz/(~)(/rxDEEvtJ^(-+.@$;{^sBCBCCyzF{'){/zyvEEvHs^{=+..*;{rxBCCCAtz/(~~)FzADEEDts^)-&.+$!]rxBCCBByz/(~~)2zAEEEvtK^)=....+@#=-']^ztDvGGGGGDDHxIF);>#....#-;)/zxACHHHBtyyyxAAHHBCCAsF-+...+*3~FrytACCCAxssxAHHLELvtKF-+.", +".+%-~{rsACCCCBtyzrr^^^zsBCACBx]#@&>!]ryCCCCCBCBCBHCBCHLLLLAs^(=+.+-F^JtLLLvxz/)~;'~]^sACCCBBA^;&+*!]rsGLELvxz/)~;'~{/sAACBBCyr;@.*;FrsGLLuGyrF)!;')]rsBACCABx/;@.*;FryvLELHsrF)!;'){rsBBBCBBx/-+.='FKxGLLLAsrF)!;!)]ryBBACCBx/;&..+%=-~]/zxBGvvGvHvGvvCxsr/);*+.+=)}stLuELGCACCBABxyABBBCCCBsF,++*;)^sBCCCBxz^])){/KAGLLLBs/{=+.@=;{/xBCCCByz/])){/KtvLLLts/(>+.+$!{ryBCCCBxz/])){/KtLLLuAs^{-&++>!]ryCCCCtxrF{)){/KAvLLLAzF)>+.....@*-')]KyBGGLELLGHts/{'->%+..+&,;)/zyBHGLGCBCBBCCGGLvGCyzF-+...+*;~]zsBBBCCAysssxxCGLEDHsF-@.", +"..@=-;(2IKJKKr^FF()))(]}rIrKr['%+@*-!]/KKJKKIrIKKPKPJwwNww52(;#..+=;([8SNwO<11~;--;!)/rzzKzI^],++&,'([6wNw8Q})';-;;'{/rKzzKr/(>+.&>!1[6wNw6Q1(';--;']/rKzKzr/)=+.&,!1<6wNY8Q|);;--;~]/IzKzKr/(>++%-_:;)/IKzK^/](~;;!(2!{/KKKK^/|)';;!(}PONwOI2_,%......+@*=-'(}IPOwNNSJ<[]_;=*%@...+@*,;):/QJwwwJJzzKsJwwwwJI[{-*.....&>-~]FQrIKr^F:F:F[KOwww<2_=..", +"..@*=-~|[IIIQ[2:__~;!_1}[QQ[Q};@.@#=c(2QIP5Q[[[[[QIIJOwNS6<:_-%...*;_:5RSR8[:(~;;-;~(}[QIIQ[2~>+.@=c_15YSM821~!;;;;~(}QQIQQ[1'$+.&>cd}8RSY6[1(!;-;;_(}QQIQQ[:!*+.&=c_28YSR6[|(';-;;_1}QIIQQ[:'$+.&-;(48RRY5}1~!;-;!_|}QIIIQ[|!*+...@#>-'(|[#...#-~1-~:[IQQ[}(('!;'_:[OSSO<{~-%+..&>;_}QI0bgpqWqigbbaaa0ad:7hilk77d9%...+&*,;ab7gijqoihhimqjpi7fba>#...%-cbgjqWqomlh774eee4hillkhfd3&..&=3abkhhh74bbdaaabbijWUqiba3%...&>9a:7hhh7ebbaaaadfgjWWqiba3%...@=3abkhhk7eeddaaabfgoWWjiba-%...%=3aekhhk7f:daaaabeiqWWjgba-&........@*=-caegpUUUjieba9,$%&+....@#=;abfgpqWWomllhlmpqqopfba,%....@*=3cdee7hh<7ebbbefgjZWqgfc$..", +".+%>30d4mnonmlk74ee:e47hmnXmhe9@.+$3abhnnnplhk774klVXoUTUqifdc*...$9abinoZnVk74e:1e47lpXoml7ea*+.@=9afioZonlk44e1e24khnnnmh7ba$..&=3dfioZoXVk7e:e1e47lpnnmh7ba*+.@=9afmnooXlk4ee:eeekinonmh4bc*..%,3dfmoqonlk4e:1eef7lXnnmh4dc#...+*=3afimXnonnlkkhmnonmmmgbc*+..&,0bgpZZZoooml9_ehIVlll74eee:f7mqWWqifc3#...&=c_ekVVllhkeee1efhmqWWoifa3%........@$>9a(e7pWUUqi7:d03**%@....%=9ab4klpWWZonXVVVVXmpigfac,&...&#=30(4[lllVl+.", +".+*;~]^svvELGHBtyysxxABvDEDHxz~%@&,!]zxDvvDHCAxyxxBCGDEEEEts[)=..+=!:rxHCHHCCAtyyxxAAHDDLvts/_>+.&-~]rxHvHHCCAAyxyxAAGvDvvAs/_>+.#-~|IxHCHBHCBAxyxyAAvDLvvtz/)=+.%-'FzyBGCHBCAyxxxttBGvvDGtz^)*..&9~FztHHHBCCAyyxxAtHGDLDHxKF'*..+%-;{ryvvvvGHtysssxCHGvvGGK],+.+*c)/sAHGGGLvvHAAAAAHGvDDtyrF;$..%,~]rxACCCCAAyssxyAGDEEGtK/~=+..%-'FzyACCBCAyxsxxtAGEEEEtIF~>...%-)FzyCCCBCAtysyyAAHDEEvyI{;$+.+#-)/zyCCCCBAxsssytBGDEEvyI{'$.......@*-!)FrsAGuEELAxz^]~;,*%...+>!{/syAHGEELGBCCBCCByssQF)!,%...%>;~FzxtCCCBCCBBBCCAvDEEvGKF-+.", +"..*;)FzxvLELLCCCBBABBCHvLvvGs^~&+%-']IADLLGvCByyyABCHvEEEuAsF)>+..$;(/stCBCCCCCABBCCCGvLGGyz/)=+.@>!{rsABCBCCCABBACCHGvLvGxzF~$++@>;)/ztCCCCCCABBBBCHvvLvHyzF'*..@>'{ryBCBCCCCABBCCCCHvDvHsz];*+.&,;]rtACCCCCCCBBCCCCGLvGtsr]!*...+$!{/JGDvHAxszrrzsytHGvDAK{=+..*;)^sBCBCvDLGCCCCCCGLLLLAs/{;%+.@>;]^sAABBCCCABABCCHGGLDyr]'>+.+&>;{rsBBBCCCBAxACCCGvLLDyr{!$+..%,!]ryAAACCCBBABACCHvLLvxr);*+..%-']rxAACBCCCABABCBGvLLGxr{;*.......%>;~]/stHLLEELHAsrF);-,#@..+=;]/sBCCvLLLHCCCBBAxsrF{)!-$+...#-;)FzyCCBCCCCCCBBCCvLELDts/-@.", +".+&>;(:+.@=-~15wNNNwJKIFF/^IPwwNNY52(;%...&$-~1F[^QKKKJPJPJJJJP6P<}(!-#...@$-~]2^QrKKKJJPJPJJOP6P<2(!>&..+&*-'(F[^QrKKKJJJPJJ868P<:(;>&...#>;)]2^QrKKJJJKJPJJPP65Q:_;>@..+#=;~F}^QrKKKJPJKJJJJJ6PQ:_;,&...+&=;_}[5<<[2{_'~~)]}[<5<4(;*...&>;)2rKKJJJJJJJJJJJJO685[:);=+...&=-)]F^QKJJJJPJ6JJJJJJP[_;-&...@*=-)]/^IKJJJJPPJJJOOJ6P[(;>&...+%=-)]/^IKJJJJPJJJJJJJJK[_;=%...+*=;)]/^KJJJJJPJJJOJJJ8K}_->&.......#>-;~:QIJwNwNNOPQ}(~;,*@....*-~]QPJJwNwwJKKrQ/2{~~;-==*@....&*-!([IJJwwwJJKrKKJJwNNwO5:_$..", +"..%=;(2-!(|:}QKPOOYYYYY65Q[2(;-*@...@*=-;(_:2QKPOOOYYOO6<[}|_;-#+..+@$=-!((1}QKPOYYYYYO5Q[}(~9-#+...@*>-'((12QIKOwOMYY86<[2(_;>#+....@#>3a(1:((';;->--c'(111_c-#+..&*,'([QIIPK6OYSYSYYO8<[2|~-=%+...&*=-'(([5OwYYYRSRYO6<<[|~-=&....&*,-'_|}POYYRMRYYY8P<<41'-#+...+%*,-'(:[6OwYYYRRYYO6<<4|;,>@...+&*=;~(|[6wYSRRRRRROP<<}('-#+......+&,;~(158MRNNNNMY5}|_;-*@...+%-_:0b7ioWUUUUUUWWWUTUqpg7ed0,%..+*-cbiqWUUUWjgeb1e4hmqWWjgba-%....&$,90_(e7hmqWUUUWqmhfbd09*%+....&*,90_be4hmZUUUWWWph4fd09=%+....%*,-0a1e7lpZWUUUWqigbbdc3=%....+%*,9a_bekhpWWUUUUqigfba0-$&....+%>=9cdbehinqUUUUWqmgffdc3*%.....@%*,;00aa;3,>>$==,30caa03=%...&*,cbf7hhmmnoWUUWWqoi47bd9-#@....@#>>9adfioWWWUUUUWjmh4fd0,$&....@#>,;abfpqWWUUUWWWjihffac=#.....&*=-9abepqUUUUUUWWjih4fac=$&....&*$-9abgpqWUUUUUUqjik7fa3=%.......+#,cabfiqWTTUUTTWjgeda-=@...@#,0fiqWUUUWjmk4eba;3==$#&@......@*-;bijWUUUWqph7hpqWUWWWjgb3%..", +"..%,0ekmoWWUUTUUTUUUUTWph4edc>%..@#30fiZWWUUWoifebf7hnZWWqibc>%....+%=-0adekVpZUUUUWZph4edc->&....+&$=-0adehVnZWUUUWZjh7eb09>#.....@*=39abfhVnZUUUUWZmh4bdc,=&....+&*,90ab4kXnZUUUUUZm7f1d9,=%.....@*,-0d14kVoZWUUUWZmh4edc,=&....+@#$,9c00c9>=*$$$$,,900093*&...&>>017llVXnXZWUUUWWomh4edc,$@....+%*--cdfpZWWUWUUUWZmhkebc,*&....@&*,30d7pZWUUUUUUWomkked9=%+....@%$=9cdgmWWUUUWUUUomh4ed9>#+....@#*39cb7oZUUUUUUUWoVh7ed9=&.......@*3cde7pZWUUUUUUUoiebac=&...@>9aepZWUUUWZVlk4ba3>$$%@........@*,cbiZWUWUWZphhlpWUWUUWqgd3#..", +".+*;{rsAGLLvLLEELELELEvtxKrF)3*.+&>;(/yDvELEvvyz^^rsxHvLDGs[);*....+%=-!)]rsAHDDELEDDtsI/F_;-#.....@=-;!)FrstHGLELLLvHxzr/);>#.....+*-;!)FrxAHGLDEELGtJr/]_;>%....+&$-;~)FzsBHDLEDLvvtsr/{~;$&.....@$-!)F/zyAGGLLELDDAsz^F~->&....+&#=-;''';-->=***>,3;!!~;;>%...%>;)^sBCCCCHHLLLLLLHtsz/]'-=@....@%$-'_]rxDLLvLLLELHAtszF~-$&....@%$3;(FKALLLEELLLLGBxsrF~;*+....@#>-')FzADLELLLLDDGBAsz]~-$+....@#>;')FKADLLvLLEELGAysr]',$.......&=;~F^sAvLLELLELvHxz/]);%...@,;{rxDELLLDGtAszF);-$#@+.......+%>;_/sGvLLLDGHttAADDLLLDHK:-#..", +".+*;~FrsxBABBBBAHABBBtwsrF])',&..+*;):rsAttAtsz/]]F/rsytxs^{',&.....+%=;!)FrzsyAAAAtxsr/{)!-=&+....+&$-;!)]/zsABABtAysr/])',$@......+#>;;)F^zsAABBAAsz^F{';,%+......+#=;')FrzsABAAtAyz/F{~;,%+.....+@$-'){FrzsABBAtAysrF{)',%+......+&#--;;--$%%&&##=>--;;->#+...@=;'/zytAtytBCBBBAtyz/F{~;,#+.....+#=;!(FKyABBBBBtAysr/]);,#+.....+#>;;(/zyABAHBBBAxsr/F)!,%+.....+%-;!{2zxAABBBBBxyzr/])-*&......@%>;'{^zAABBBBABxyzr/]);,&+......@#,;)]/KytBAABAtysr/{);>%...@$;)1ryAABAtssr/])!->#+..........@$-'{rsAABBAyszzzsxAAAyxz/)-&..", +"..@#=-;~)({|{|11:1|((()a!;-,*&+...@*,-!_(((((_!;---;;~_(_~;-=#+.......@*=-;'~)((1(((_~;;->=&@........@&*=--;'~)((((((_!;-,=%+........+@*=,-;'_((((((_!;--=*&+.........+%=,-;~)(({(((__!-->*%.........+%*,--'~_((((((_~!--=*&.........++&&&%&@@++..+.@&#$***%@....+&>-']FFFF{){{{{{(((~;;->$&+........@#$,-!_({({({((__';--$&+.......+@#=,;!_(((11{_()_!--=#%+........@*=-;'()(({{{1))~!;-,*@........+&*=,;~(((1111((_~;;-=%@........+&#*=--!)({|{(1(((!;-,*%+...+@#,;!_((((((~!;--=#&+...........+&*=-;_()(|(((_~__)((((~0-=%...", +"...@#*=--------;;;-99---,**%&+....+%*=>,--,3--,==***=,,-,>**&+.........+%#*=>--;;3---,=**%@++.........+@%*>>>------,,,,**#&............+#*=>,-,-----,>**#%++...........@%#$>>,---9,-->>**&+............@%*>>,------>-,>=*#&+.........................++++++.......@%=-!___!;--->---,--=**#&@..........+&#>>,,--------,>>*%&@..........@@*$>>--------,,>=*%+..........+@%**,-----;----=>$$#&..........+@&%>,>----;9---==**%&...........+&#*==-3-----3-,,=*#%......+&*$>=-----,->**#&&..............+%**>>---------,3----,==*#@...", +"....+%#*$*>*>,>>,,==>$$***#%@.......&%*$$=$**$$######***$$%&@...........+&%***>=>>=$>$*&&@+.............@&#**$>>$>==$$$*&@+.............@&%##$*>>>$>*$*&@+..............@&#**$$**>*$=**&@+.............+&&%**$>$>$>$***%&@.........................................@*=39333,>=,=*$==$$*&&&+............+@&#$*>*=$$$$*=**#&+.............&*$$$>**$>>>**$*%@..............&%*$$====,>*>***%&+............@@%*$$=>>=-=*>**#%@.............@%#$***,*,$$*$$*#&@+........@%*$$>$$>*=$*&@.................@%%#***$>$=$>>**=$*$=*$%@....", +"......@&*$*$***********%%@++.........@@%*#****%&@&&@&%&%%#&+..............+@#*##$***%*&+.................+++&##%**##**%++..................+%#$****%*#@+.................+@&%$$$$*$*##+..................+@@%%#*****$*%%@..........................................+@**>>,=$>$$***##**%&+................@&#***$=****#&@++..............+&##*****###$*%&@@..............+@%**##*$#**##&@@...............+&%#*#***%$$%$#@@+.............++@%#$$**$=*$*%&@@+..........+&%*%**%*#%@+...................+@&#*$*****#*$*****##&@.....", +".......+@%&%%%%**##%%&@................+&&%%%&@+..+..+.+@&@.................&%%&%%%%&@+...................+.+@%%&%%&&%&.....................+@#####%%@+...................+@@%######%%+.....................&&%%&%&&%%&&+...........................................+%*$$*%%%%**#%%%%&@+..................+&%#%%*%%#&@+...................@%&#**%%%&%%&+.................@&&%&%&%%%%&&+...................+&%%%##&&#&&&+................++&&&&%&#%*##@...............+@#%%#%&#&+......................+&&&%&%&%&&%%&%&#%%&+.....", +"..............+.+........................+...................................+.+................................++++++......................................................+@&&&&&&@...........................+.+...................................................++++++.++++++..+......................++++.++.........................+.++++..........................++..............................++.......+.......................+.+.+.......................+..+............................+.+.++++..+.+..........", +".............................................................................................................................................................................++++++++........................................................................................................................................................................................................................+..................................................................................................................", +"...........................................................................................................................................................................+@@@@&&@&+.......................................................................................................................................................................................................................+++.................................................................................................................", +".........+@@@@@++.................................+@+@+........................+@++........................................................................................+@%####%%&+...................................................................................+++@+@+..................................+@@@@++....................+@@@++++....................................................++@@+++.................................+@++@++.........................+@+............................................", +"........+&%##**#&@+...........................+@&%%**%%@...................+@%%*#*#&+.....................................................................................+%$*,,>,=>$%@.................................................................................@%##**#*%+..............................+&####%##&+.................+@***$*#&@+.................................................@&*#*$#%@+..............................@&#****%%+.................+@&%#%**%@...........................................", +"........&=--;;;;-$#&+.......................+@#=--;;;;,$&+...............+%=--;!;;;>$%@...................+&#******%%&@..................................................+#-;'~{){)!;=#+..............................................................................+%=--;;;;--*&+..........................@%*=-;;';--$#@..............+&==-';';;>##@..............................................+&=>-;;;;-$#@...........................@&*>-;;;;--*@..............+@#=-;;;;;-=%+.........................................", +".......%$-;!)]])!-,=#@....................+&#*-;;~)]]);>*@..............+%>>;')]]]~;,*&................+&&#$$-------->*%+.................+@@&&&@+..++...................%=;'{F/^//]~-$#+.............................................................................@*,-!~{])!;-=&.........................+&*=-;)]])~;-=#@.............@*,;~)]]]~;-*#&................+@&@@@@@+@@@.................&$>;!)]{);-=$+.........................&*$--~)]{~!->$&............+%==-;){]{)'-$%+.................+@@@@@@@&&@+...........", +"......+&#=-;!)(~;,=$%@+...................+&#*=--;~)~;-*%@..............@%$=-!){_)'->*&................@%%#>=->>,,,,->=#&+..............@@@&&&&&@@@@@@+.................+%*-;)(F[F});,*%+............................................................................+&*>-;!)();,=$%+........................@&#*,-'))';-=$#@............+&*$-;')_)'-=$%@..............@@&@&&&&@@@@@&++..............+%$=-;~_)!-=**@.........................@%$>-;)))';-**&+...........+&*=,-~)))!;>*%@................++&&&&&&&&&&@+..........", +".....++%*$-;_((_;->*#&+..................+%#*$>;!~~((',$#+.............+&$=-;~~(1(!-=*%+..............+@#*>,-;;;-;;-;-,=*#@............+@&%#%%%&&&%&&&@@................@%*,;_1}}[1(;->*&............................................................................+&#$>;'((_;-,=#&+......................+&#$>-;_((_;->*&+............@%*=-;((1(~;-**&+............++&%%#&%&&&&&%&%@@+............+%*>-!(11~;->*#+.......................+&#*=-'~|(~-,>#%+..........+@%$>-;_(|(~;,$#%+..............+@&&##%&%%%%%%&@+........", +"......@%*>-cdbbda;9,$#@+................+@%$>-cadbbb_a-*#@............@%#$,;adbeebdc9=*@.............+&%$=,9cdddadaaa0;3=$%+..........+@%$$$=**$$#$$##%@+...............@#>3cdb4774ba3>$#+...........................................................................@%*>,;0beba!93=%&+.....................@#*=-;abbbd!3>*&.............&#>,;abeebd0;>*#&...........+%%#$***$###$#*###%@+...........@%*>-cbbeda;9,*%.......................@*>>-cabbb_c-*#%+..........+%*=-;0bbebbc9>*#&.............+&%#$$$$*####*$$#&+.......", +"......@#>=cae[k4ee(ac=$&................+%=,3'be4444ea9>*&............@%*-ade47kkke(a9=*&............&*,30~bf7ggkgg74ebac=$#+.......+@%=,3ccc93=,33cc3=#@...............@*,cd47kkk74bac=*@...........................................................................@%$>90b4444e{ac3*%@...................&*=30db14k4ea93$&............&*>3ab47kkk4eda3=*&.........+%*>-cc093,,,3cc-3=*$&+..........+#$,ca:474eeda9$%....................+%*>9aa|e4k4ba9>*&@.........+%*>9d:27kkk41d93$%@...........+%*,39c'c3-,,-c99=#@+......", +"......@*-;)FzxCAAAsz]~-=%+............+%*>;~]rsACBAsrF'-,#+..........@$-;)/sACBABAAsr]!-=@..........&=-~]/zstGvvvvGHAAsr]~;=%......@#=-;){/^rF{)){F//{;-$@............+&$-']ryBCCAyszr]!>#+............+&&&&&&%@@@&&&&&%@+.................+@&%%%%&%&&&%@+...........@#-;~{^xABAxyz/);-#%+...............+&=-~{/zyyAAAs/);-#..........+%=-']rstBBCCAAs^);-$@......+@#-;~{F/r/])))]/^F)~;-$%+.........@=-;)]zxCAAxsr]!-#.................+&*,;~]rzyABByr{~->*@........+%>;!]rxBCCBBAsr]~-,#+.........&*-;)]F/^^{)))]//F~-$&+.....", +"......&*,;~FzyACBBts/);-*@............&#=-!]/zACBBtsr]~;=#+.........@#>-']rxBBCCCCAxrF~;=#+........+%=;)/zsAHvDLDLDvCCyz/);,%+.....@*,;)]/rzzrF]]FrzrF~-=%+...........@#>-)/zxBABAyyzrF~-$&.........+&##$$>>>$*$$$*>$$$**%+............+@###*====>,=>>$**&@@.........+#>-!)rsBACBAyr]~-,*#@..............&*-;)FzxyBABtz/);-%+.........+#=;)]zyBCBCBCCxz]~;,%+.....+*>-'{F/zzr/F]F/zz^])!;-$&.........&#-;~FzyBCAByzF)-$%................@*>-!)/zytBBAsr{'-$&+........&=-;)/sBCCCBCAyz/);,#@........+#,-~)F^zsz^F]F/rz/);>*+.....", +"......&%$=-!{/^rrr//(;,=*@...........+&#=,-~{F/rKr^F(~->$@.........+&#=,;~]/rKKrIrr/1);>#&+.........&*-!):[QP8JOOOJJKI/])!,*@......+%*-;'(]F}F{_){{F]);>*@+...........@#=,;)F/r^r/^FF|~->%@........++&#*****=$*##$***=$***%@+..........&&%**>>>>=>>=*=$*$#@@.........+&*>-;)F^rrrr[]);-=#%&+............@#*,-!)F/rrrQ/]';=*&..........@#*,;)F/rIKzIrr/F);-$%+.....+#*,-!){F}F|_({{FF{)';,>#%+........+&$>-~]F^rrr/F~;>*&................&$=,;~{F/rr^/F~->#&.........@%*=-!(/QrKrIrI/F);-$#+.........@*=-;')]FF]_((]F1);=*&+.....", +"......@%#>,;_(2}[Q[}(;->#&+.........+@%#$,;~_:2[[21_~-,*%&.........+&$>-;_(2[[[[[[[}:_-=$&+.........&$=;(:1[[<<*@.......&*=;'(_:1:|(|(:1_!-*#%+...........+%$=;~1}2[[Q[}(~;-*#@........@%#*$,>,,>,,===>,,>,,>=**%+.......+@&#*$>=,,--,-,->,>=*$&+.........@#=-;_(:2[Q[[1~!;>*#&+...........&**=-;~(}[[[2}|~;,>*&.........+&#>,;_}[[[[[[[[2|~!-,*&.....+%$,-;~_|}::(((|111(~;-=*%+........+@#=-'~112[[}|_-,$&...............+&*>-;~|}[[[:|~;,*#+.........+&$,;'(1[[[[[[21|~->*@..........@*>-;_(|::|1((_|(_->#&......", +"......&#*=-cdb:e7hk4ba;,*%@..........@$*,-0d:f4474eda9,$#@.........+&*-;0dbe474f4e74eb0,>#@........+&$,;def4747khhhk4fbd;>$#@......@#=-cabbeeeeee1eeba;>$%+..........+&*>-cab44*#+.....+&##$>,3cccc;c00;09cc3=*%@........&%$$-;ad1f4kk7fbac9=>*&+........+&%*>,;abb47=%+.......+&$*,90bf74444477f:bac9=&.....@%$,90abbeebbbb:febbaa9>*%@........+&$=-0d1ee774edc,*%...............@%*-cabe4<74bd0->%&+.........@%$,;0be4744ff4eba3>*&.........+@#=-cabeefeeeebeda;=*@......", +"....+&%=>c'dbe43cadb(bbddddd(b(bbd(ac9=#.....&**,39c_dbb:b1b:b(bbda03>#+......&*$=3cd1eekhlVhk4:dac3>$%.......@#*,3;a_b}kklllh4e1dac3=%.......@*=,3a(4hIlhkkk*@........@%*,ca|e4#+.............&*>3;db2klllkedc3=$&..........@%=3~be7klhkkkk4e(03*&.........+%*>9abe4kkk77744ed9,$&......", +"....&=,;)]^zsxtBCCHAAsr]);-$&......@*-~{/rsxACACCBtxr/{;--%+......+*-!{rzyACCCABCCCAts/{!-$&......@#,;{^sACCBCCCCHGBCAsrF~;,*+....%,;)FrssAACHBBCCCAxz/);-#+.......+%-;!{/rstCCCHCBAxz/{~->%+....+$-!{/zsssssszszssssssssz^]'>@...%>-')]F/zzssyyxsxyssssz/{!,&.....&$-;~]/rsyyCCHBCBAyzr/]);-%.....@*-;~{F^zsAACHCCAAxsz^]);-%.....@*-;)]/zyACACABHCBBAszrF);%...+*;']/zsyBBBABABBCBxyzz/]'-*+......@*,;~{^zytACBCxzF);=&............&$;'{FrsxtCBAAz/);-$@..........#,;)FrstBCABBBBys/{;-%.........&*-!)FrstCCCCBByxz^);-%......", +"...@%=-)]rsyBGvGLGLHCAs/{!-,#+....+%-;]/zsAHvGLvGHCByrF);-$%+.....&=-)FzyBBGGLLGvHCCBy^{'->*&.....@=-;{/xtCCCGLLvLGHCCxz]);,*&....&-;)/zyBCCvvGLGCCCAz/);-$&.......@$-;]/zyACvvLvLvCByzF)!-=#@...&=;)/sAHGGHHAAAAABHGGGGHAxr];#..+%-;)FrzstCHGHGGGGGHGGGts/);*....+#=;~]/zytBGGvGvvGHCtxzr/);$+...@#=;']rzstCGvGLLvGGHAyszF);*....@#,;)FrsACGvGLvLGvvGCBys/{;*+..%>;)FrxyBCGvvLGLGHHCAAsrF~-=%......&*-~)/rxGGLvvGHs/);>#...........@*,;)FzyHGvLLGHs^{!-#@..........%-'{/zxBGGLLLGHxz/);=#+........&=-']/zxBGGvGvHAyz/);>#+.....", +"..+@%*,;{}QKJwNwNNNwJKr:);-$%+....+&=-)][QKwwNNNNwJKI/_;->*&+.....&*>;(/QIJwwNNNwwwKr[{'-=*&@......&*=;)/IrKwwNwNNNwJK/}~;,$#&...+@*-'{/IKJwwNNNwwJJr[('->*&......+@*=-'][IKJwNwNNwwKI/('-=$%+...@=-_}POwwNNwJJzKJJwwNNwwJI[{;%..@%>-~|F^IPwwwwwNNwNwwNNY5}~-#....+#*-;(F[IPwwNNwNwNwwPI/}]~-%....@#*-!)}/IPwwwNwNNNwwJKQ/1'-#....@%=-;1/QIJwwwNwNNNwwJKI^]'-%...%*>;(FQIPwwwNNNNNwwJKI^});-*@......@#>;!(25wwNNNw6[_-=*@...........@#=-!(2IOwNNNwJ[|'-=&..........+@*-!)1QPwNNwNwJQ1~-=#&.........@%>-'(:[6wNNNNwP[|~->$&......", +"...@&$=;(}[<8OSSwSSOOPQ}(;-=$&.....%=3~1}Q5OYSwwSwOP<[(!-=$#+.....@*=;_}[Q5OSwSNSOOPQ[|~;-$#@.....+@*>-_:[QI6YSNNwYO6KQ:(;-=*@....@$>;(}[<8OSSNSSYOP<}(~-=$&.......@%=-_1}Q5OOSwSSYO6<[1';-*%@...@*-015OwRNSYO8KPPOOwYMRY65[:;*..@*,9_1[Q<6YSSRRMRSSSNNNY51~-%+...@*>-'1}[<6OYNNNwSwYOP53!:}[<6OwSSNwwSSOP<<[:~;$+...@$>-~1}#&...........+&>-;_|<8YNNNM64~-=$&...........@*=-;(15OSNNNR52(;-$@+.........+%*-'_(}5OSNNNR5}_;-*&++.....", +"...@#*,;de47iipppmpmppmgbd0-*&....+%=;a:7hhipppppmpppied0;=*@....+&$>cae4hiipppjjpppmgfda3>*@......@%>30|f7h5ppppjpmppi7bd;3*&....@*>cde4hipppppppjppheda3=#+......@%=-ae44hippppppjnmifba;,*@...@*3cbgippjjjoqqqjXppppppppmga$+.@*-afgppppjjjppippjqUTTqjed9*....@*=9dgijjjopjppijjpompppgfc=+...&*-0dgijppjjpjipijjjXppigbc=+..+@*,!bgipjojjjjpijjojopppgb0=...%>9afippjojppippjjojjjpied9,&......+&#>9cdfipqqTWjgd9>#&...........+&*-30dfimqWTWjgac,*&...........@#$-90deijqUUqjea9,$@...........&%=-0abgijqUUqpba;,*&.......", +"...&%>3a14klll5hilhmooomked03*@...+#-0bekkllhh5ihmXZomhe|ac>&.....%*,cb4kcd:47khhhhhilXoZXi7edc,&...+@>3a17kh5h5hihimoZom7eda9*&+.....&*>c(4kll5hhh5hmnooph4bdc=&..+&=3ab7lVVVXmqWUWWnmlhhhmmoqib>+.%,0bgpqZZomlggf4ghVjUTTTjgb0$+..+%*90bioZWqnmmhihhVVXZZWZngb3%..+%,9dfpoWZoXm5hhghhVnoZWZpgd3#..+%=3afmqZWonm5hghhlmnoZWqngb,@.+%3afioZWZnm6ihghlmnoWWWoiea3#.......@*=-9abfgjWUWqgb03=&............@*$,cabegpWUUjgbc3*&...........+&*,,0abfijWUWjgb;=*&...........@%$=3;abfipWUWjgb9,$&.......", +"..+#,;~]zyAACCCBBABBDDvHxsr/~-%..+#-'FryBACCBBtBBBGvDGAyz/{;-@....*-'{rsACCCABABAHHLDvtyz/{;>&....&#-;{/zxtBCABBtABGDLDAxzr]!-@..+%-)/zyABCBAABBBAvEvGtszF);$&...+&=-!]rsACCCBBABBAGLDGAyz^]'>@..#-~FrxBCCCCCDEEEEGABBBBCvEEwQ-&+*!]zADEELGCAsI^rzsAHuuEuuV/{,+..@=3~FKtEEELvCAAyxABBGDEEEvAr(=++#-!{/sGEEELHCtyyyyBAGDEEEvyr($+.&=3)FsHvEELGCBtyxAACCLEEEGyr'@.+=)/stEuELvHCAyxAAHGvEEEvxK]'=.......@#>3'(}rsGLEuvyI{!-$+...........@#>-'(FKsGuEuDy[{'-*@..........+%=-;!|2ryGuEEvs^{;-#...........@&=,;~|/zyvuEuGK^);-#.......", +"..+*>;)/ztBCABCCABBBGLvGAxz/);*+..%-)]ryABBCCBBBACHLLGBss^]!-#...+*;!]ryBBBBBABBBCGLLGBys/{!-#+...&$,;(/zyBABCBABBCHGLGBAsrF~-#..+*;)FzyBBCCBCBABHvLLHAxz^);-#....%>-~]rxAABCCBBBACGLLvBxsr]!-%..%;)FryBACCCCvEEELvCBtAABGvEA^;++$)FztHLLLGAsr/FF^rsxtuvGtz/)>@..@$;)FKALELLCCBAxyyACCLLELvtz]>++*-~]rsGLEEGHCBAxxyACHLLELGtr{=..&>;_/KGLELGHCCAxyACCCGLLuGx^;&.@-)/JALEELHCCBxyxBCBvELEDAzF'$+.......@$-;~]^JtLEEvxr]'-$&...........@#*-;)F^stLLuvyr{!-=&..........+&*=-;)]QsGLEuGs^{!>#+...........+%>-;)FIsGLEDHs/{!>%.......", +"...%=-;(F^QrKIKKPKPJwwwPQ}]);$&...&=-~]FrIKKKKIPIPwwwOI[F(!-*&....&=-!(//rIKKKIPI8OwwPI2F)!-=@....@&=-;)F/QrIKPKPIPOwwOP[/]_-#&..+%=;~]/QrKKKIKIPPwwMJQ[F);,*%....@*=-!(/^IrIKKIPKPOwwOI}F|'-=&..@=;_]/QrIKPJMNSNwJIIQrIIJMY81>+.%-_:-!)25wNwOQ|!->&@............@&$>-!([8www8[|!-$#@...........+%#*=-'(}6www6[(;-*%+............+%$>-!|[6wSSP}(;,$@.......", +"..+&*=;_:2[Q5688Y6YRMNM5[:)!-$&..+%=-;(}[QI66OM8MMMNM6[}|(;=*&....%>-'(}[QI686M6YMRNM8[21_;=*&....@#*-;(1}[Q868R6RMRNRO52|_;-$@...#,-_|}[Q58OY8OORRNR5[:__-=#@....@%$-;(}[Q<8O6Y6YYMNM6<2|(;=*@..%,;_1}QQI66MRNNNR8KQQQ<<8MM5b=..&-!(<8SSO<}(_;;-c!_d|:21(~;-%+...#=3a15RNNOPIQQ[QQQI5ONNS8[(c*..&*-c_e5RNNOPI,-_|5MNR8e_;>$&+............+@**--a15YNR5e~->%@.......", +"...&>,cdekhimqUUUTUUTTqjgfba3=&...%=;0b44iioqUUUUUTTqjgfbd0,*&...+#=3ab77imqWUUTUUTTUjgfbac>*&....+#*-0bekhipWUUUUUTTTqifbbc3$@...%>;de4himqqUUUqTTTUjgeba9=*@....@*=9ab4ghijqUUUUUTTTjgfe_0,%@..&-0be4hhmoqTTTTTUjmhkhlmjWqib>++&,0bgjWWqigbbdacaadbbefbbac-*...+#-cdfjqTTqpl5lkhhllmjUTUjgb9#..&*-0dgpqTUqpVlmlhllhmjWTUjgd;%+.@$-0dgjUTWqmll5hhlhlpqUUqpg0,+.+%3afiqTTWjVh5hhhllloqTUjiba3#.........@%*>3cfijUWjgd9-*#@.............@%$=-abiqUqjgdc-*#@.............@#*,3afiqUqpf09,$#@.............@$$,9afiqUqpea;,$%+......", +"..+#=caehlmnoqWqUqUqUUqjh7ed9=&...#,0b7hmmnoqUUqUqUUUqik4b!9>%...@$9a|7lVmnqWqUqUWWUqji7e1c3>&....&*3cdehmmXoqWqUqWWWUqph7:a9=&..+*3ae7lVmXqWqWWWWWUqjh7ed;3*&...+&*-0b7kVmoqWUqWqqUUWolkf1a9>@.+*0(43cdfpqUUjiba9,*%@............&#=,caeiWUUogbc9,*&@............@*>30dgpqUWjgba9=*&+...........+&*=-abgpWUWjgb09=#@......", +"..&>!{/stGGLvDDDDDDDDvDGAys^{;*..+>)/ztvLvDDDGDDDvDvvHBxsrF'-=@..%-)/sxDDDvvDDDvvvvDDGCtsr]!-#...+#-~FzyGGvLvGvDvvvvDvvHByz/)-%..@-)/stvDDLGvDDvGvvDGGCtsr{'-%...+*-)FzAvvvvDDvvDDvvDDGBtsrF~-#.@,/sABBCBCGvDEEuEELHCBCBHHvGx[;++%9)/sAGDvDvGHABBABABHGHGtAzF;+..%-~]QJvuuEEGHCBCBCCCHGGDDHyz],+.#-_FQsuuEuEvHHGHCCCCCGvDvHxr{=++*;_FKxuuEEEGBCCCCCCCHGDvvHsr!@.@-(/JGuEEEvHBCCCCHBHGGvvHAz/_>.......+%*,-~{^sGLEEvAK/)'-,*&..........+#,;~{/JtEEEvAK])'-=*@.........+@#-;~]rsGEEEvyrF);-=%+.........+&*-;~]rsGEEEGsrF);-=%+....", +"..%-!FrxGLLLvCAAAxAACCBCBts^);*+.+,)^JALuEGHBtyytBACBCABszF);=&..&;{/sHGLLvHCtAyytCHCBAAsr]~-*+...*;)FKtvLLLvCBtAxAACCCCAxz/);*..+,{rsHLLLvCBAtxAACCCCAAs^{!-*+...*;)/stvLELGBAAxtBBBCCCAxzF)-%.@-FsBCCCCBCtALEEEEvBCCCCCCCAy^-@.#-~:rxBCHvvLGCCCCCCHvvDLGAs^-@..&-~]^sGEEEEvCCCCCCCBBCCBCAsr{=++&-~FrsGEEELGCCBCCCCCCCCBCtsr(>++#;)FryvuEELGCCBCCCCBCCCCCBs^'&.+,{^KvuEELvCCCCCCCCBCCCCAxz/)=+......&#=-;)]^JtLEEvAz/{~;,=*&........@#>-')F/JALELvAzF{!;-*%+.......+%*=-;)FrJtLEuvxzF{'->*@........@%*>-;)FrsGLuuGy/F)'-,*#@...", +"..@>-~1[8wwwJ<^[/[/QIKKI^/F|!-%..+*;(2PwNNOKQ/[/[^IKKKrQFF(;-*@..@=;(28wNwOII[/[[[KJKK^^/1~-=%....&=;_2&.+=)}rIKKKIrQQ6SNSNOJKKKKKKKI[)$+.@#>;_F[II8OwJJJsJzKJJOwJPQF)=+..+*-!([6SNSNJJKzKKKzKKKKKKI[|!*..@*-'|46SNSwJJzKKKKIKKKKKKQ}{!%.+@*-!|7ONSNwJKKzKKzKKKKKKIQF_-+.+*;(}5NSNNwJKKzKKKzKKKKKI[]);*......+&**,-;'(2PYwwO<}(!--=*%@.......+@#=-;!)1[8YNwOQ:)!-,=*&+.......@%*=--;'|[6Mww8Q1_!-,=$%+.......@&#>--;~1[6www6[|_;--=#%@...", +"..@*,0(48SSR8[}}:}2}&..*;:[QIII3!(|}Q56OJOO6PI,9~((f5MNR6[:(~;-,$*@.......@%*>-;~_1}5RNR841(!;-,*#@......+@#$,;;_(|45MNM84|(~;->>*@...", +"..@*,0dgpqWqji74777hppplk74ea3#..+%3afiqWWqig77ggiijjpih7eb;3*&..&>cafiqUWqih7777gmpjph47ed0,#....&=9cbgjUUqph7777gipjjih74ba-%..+$cdgiWUqji47777gjjjmh77edc=%....&=3afiqWUqig7777hijopik74b0,&++$0ekimpppmipjTTTUqjmmhhhmmiga$...@*$>3cabf4imqWZomlhhh74ba0,#...@*=30bijjqjopmlkhhlhlmpjpied3#..+#=9abijqjoopmlklhhhlpjppied9#..+%=30bijqqojjpikhlmppojopgf0,+..%>0bgjqqqjoXmklhhlhmjjjigbc3%.....+&*>;abbbfgjqTTqigeeb~c3*%......+%*=;0abffgjqTTqigebdac9$&......+%$-cabbefijqTUji7fbba0-=@......+#*,;abbffijUTqqifeb_a;,$&...", +".+&=901gnWUWZmVVVVmnoWZoXVl7bc*+..$cbemqUUWoXVVXnnqUUoXVlked9>%+.@>0bgpZUWZnVVVVVmoUWqnVlkea,*+...#=cdfiqWWWnmVVVVXXWUWXmVk7d9#..+=0bgjWUWZXVlVVVnoUWqXllkba3#+..+#30dfmqWUWnXVVVlmoWUqnVVhed3#..=d4kXnZZWqWWUTTTUWZZnXVXnooib$+..+&*=,30(ekVnZWWZnVlhk771ac=%...@#>30b7mnXoZZoXXVVVVXnWWWjgbc%..+%$30bhVnnoZZoXXVlVVnoWUqjgb;#..@#$90bgmmXoZWZnXlXXZZWWUqp7d,+.+#,3dfinnXZZonXVXlVmoWUUqiba-#.....@#>9_e4khlmoUTTUoVlkk7:a9#+.....&*=0d:7kkVmqUTTWpVhkk4ba3#+.....@#,9de7khlmqUTTWnVlk72ba3#+.....%*9cb27khlmqUTUqnVlk74ba,%...", +"..#-']rxvEEEGHCCHHHvEELGHCCxr]=+.+=(^stDEEvvHHCGGvDEEDHHCtz/),*..#;{^stEELvvHCCHGvDEEDvCCtz/'=@...#3~/ztDEELDCCBCGGDEEEGCCAy^)=..@-]rsGLEEGHCCHGHGvEELvCAAz]'=+..+*;_/zAEEELvHCHHGvDEEEvHBAs/'$+@-FsAGDLELELEEEEEEEEvGCHCGDDxe,....&=-;!)/zyBvLEEvGCBCAxz^{~-#...@$-;(^sACHLLEvGBCBCHHvEEEDJ/)*..@*-!|^sACHGvLvCCCCCCvDEEEDP^(=++&=-9_}ztCHGvLvHCHGvDEEEEEwse-+..*9_FzxCGvDLLGCCCCHHDEEEuwr{9$....+#-'{^sACBCHvEEEEGHCCAAs/);&....+$-!]rsACACGDEEEEGHCCAAs/)-&....+$-~]rxABCBGDEEEEGCCCBAs/),&....+*-']rxABCBHDEEELHCCCAAz/~>+..", +"..%>'{^KAGvvHCCCCBHHGGGHBCAyr(=+.+=)FKAAHGHCCCCBCBGGGGCBBAzF~;%+.@>)FKyBGvvBCCCCBHHGGGCCCyzF'>+..+%-']QyAGvHCBCCCBHGGvGCBBAs/)$+.+-_/sxGvGHCCBCBHHGvGGCCBxr]'>@...%-~FKxHGvGBCBCBHBHGGGCCCAz/'*++>]zyBHGGvGvGvDvDvvGHHBCCCGtz{$+...+&*>;)]rstHCvGGCCBysr/]';>%...+%$;)FryAAAHGHCCCCBCCGvHvAzF;%...&$-)FzyAABHHHCBCCCCHHGGtxzF;#..@#=;']^syACHHHCCCCHGGvvGGxz{-+.+#-!)^sxABHGvHCBCCCCHvGvtJ/);*+....*-!)rsyABCBHvDvGCCABBtsr);*....+$-']rsyBCCBHvLvGCBCBBxs/);*....@$-~]rsxBACCGvLvGCBCBBts/);%....+#;~FrsyBBCCGvLvHBCCBBtsF)=+..", +"..+%=-'1}QQQIKIKIKKKIIKKIrQF);*..+%>;):[[IIKKKKKKKKIIIIrQ/|!-=@+.+%>;(}[QIIIQIKKKII@......+%*>;)]2IKJJKKI/F{~;-$#@+....+&*>;~(]22QIIKKIKKKIQ[4e1d;$+...+%*,;~)]2^QKIKKKKKrQQ[72b';$+..+&#$,-'){:[QQIIIKKIIIQ4}e|_,*....%=;!)]F}[QIIKKKKIIQ442e(!-*@.....@*-;)]F^QrIIIIIIKIrr^/F_;*@.....%=,;)FF^QrIIIIIKKIzr^/])-*@.....#=-!{FFQ^KIKIIIIKIr^^/])>$+....+&=-!{F/QrIKIIIIKIrrr//]'-*...", +"...@%*-9(1}[}Q[[Q[[QQQ[[Q[}(',&...@*,9_|2}[[2[Q[Q[[}[[[Q}:~->#@...+*-c_|:2[[[[[Q[Q[[}[[[}|!-=%+...+&*>3~(:}[[[QQ[QQ[[[[[[2:_;=&...&*-0(12}[[Q[Q[Q[[[[[[}}(!-*%+...+*$,9_|22[[[[[Q[Q[}}[[[}|~3*&..%,;_(}[[Q-;(1[IP6IQ[2('-=*%+........@#=--;'(:}2[[Q[[[[::(__c-#+....+&**-;;~|2[Q[[[Q[Q[}1__!->@.....+&*==-;~(:2[Q[[[QQ4:|_~;3>&....&**--;!(:}[[[[/[Q[}:(_!c-*#+.....@#=-'_|}}[QQQQQQ[Q[221_!-$@.....@%=;'_|}}QQQQQQ[Q[[}}|_;-#+.....@$=;~(:2}[QQQQQQ[Q[}}|_;-%......@#=;'((:[[QQ&+..", +"...+%$-;abeef777k7777744f4ea;=%....%$30dbe477777774fff44eb'-=%+....&=30bbf47777774ffefffebc,*@.....+#$,00bff4777777fffef4eb03*@...@#>9abee44777774feee4eed;,$&....+&*$30deef47k77774ffffeeba-*&..&>9cdb74477ffbdbbf47774fb0c=#........@#$9abfipoomhfba;=*&+.........+@#>>39abef7477774bba09,*@......@%#$,9;db47777477feda0c=$&......@%$*=39abef77k774fbdc03,*&.....&#>>,30dbf4777774ebdac->#@......@%=-0d(b47777777747f:bdc,%......@%*-0ab:f7777777744f:bdc,#......@#>3addee7777777744eebd;>#......+%>30db:f477777h47fe:bdc>%...", +"...+&*=9adbee4477744eeeeeeba9=&....&=3cdbee447744febeeeebdc,*&.....%*90dbee4474744ee:eef|dc3=%......@=,cdbbee4444744ebeeee|09=@...@*=3adbeef477744eeeeeeba9,*&....+%#$30abeee47777eee:eeeed09*@..@*,c'befeeeebdddbbeeeee:d03=%+......+@*,;b7lnZWWXie1c3>#@...........@&%=>90dbee4444febda;9,*@......+@#*>,9abee4444efebda;3,*@.......@&#$>9adee444eefebac9,*%+.....+&#=,9cdbee4774eebda03>*%+......+%$30adbe47k77k774eebbac,%+.....@#>30adbe47k7k7k44ef1bd0,#+.....+%*-00dbe47k7kk774eebbd0>&......+#=30adbf4k7k7k7k44bbbac=&...", +"....@$-;){]F]^rrzrr/^FFFFFF)',%...+&=;~{{]/^rzrrr^^/]FFFF)'3=%.....#=;~{{F/rrrrrrr^F///FF{';>#.....+&=-')]FF^rrrrr^///]FFF{);=@...@#-;~{]]/F^r^rr/^F/F/FF)'-$@.....&#$-'){{//^rrrr^^FFFFFF{';=%..&=-;~{FF/FFFF(({{]/F/FF](!;>&.......+#=;{rxBGDvDvtz/);-#+...........+&%$,-~)]FF^^F/FF{_);3>#@......+@%#>-;~{F/rr^//FF]()!3$#@.......+@#>-;~)]]///F/FF{)!;-=%.......@#$-;!){{F/F//]F]{)';-*&.......+&$-')){F/^rrrzrr///]])!-%......+#>;~){]]^rr^rrrr//FF{)~,*......+*=;~){{F/rrrrrrrr//]])'-#.......%,;~)]]F^rzr^rrr^/F]])'-%...", +"....+&*-;!')))(FF{{{{{)))'';>*@....&#=;;~~)]F]F]]{){))'~!'-,$&.....@$--;')){{{{{{]{){))~~;;-=&......&#>-;!~){{]{({{{{))'~~;;>%+....@%=;;!~~){{{]{]{){))~''-$%+......+#,-!~~')){{]{]{)())~'!->#+...%=-;!'_)~)'~'~!''~~~~'~;->*@.......+%=-)FzxBtHGyz/]~;=#+.............+@#,;!'))){{))'~;--,%&.........+@#=;;!)){{{)))~~;;->%+..........@#$-;!~)))))))'';-,$%+.........@#=-;!)'))))))~;;->*&+........&#=--'!_){{(]{]{))~)!'-=%......+@#$,;!!)){{]{]{{{))~'!->&+......+#$-;!~){{{{{F{{){)~!;->%+......@#$;;!~_{{{{(){{))~!!;;$&...", +"......+@#==>-,,-----,->==$*&@.......+@%%==>>------,,=>>==**&++......+&%#$=,--------=>=>==*%&@........@@##$==,-,---->-=>>==#%@.......+@%===,=>----,->,===***@+.........&%*===>,,>,,---=====*%@......@##=>=,=,=====>=>=,>=>*%@..........+%*>;~(::|:b_;-=#&@.................@*$=>>>,>=,=>$%&@.............+@%$==---->=>==$%@++............@@@&*===,=>==$*%&&+............+@#*=>====>==>$%%@+...........+@%**>=>-----,-,-==*=*+.........+@%*=>=>->--,,,,===*$%@.........++%*===,,------>>,=*$&&+........++%$>=>----->-->===$#%@+...", +".........+&&&%&&%&%&%&&&%&+............@+&&%&&&%%%%%&%%%&&+...........++@&%%*#%%%&##%&&&&@+...........+.+@&&&&%&&&%&&#%&&@+...........++&#%%%&&%&%&%%%%&%&+............@&&##$#%##%%#%*%%&@+..........&&@&&%&%%&%%&%&%&&&&&+.............@#$=--3;,-$*%%&+..................++@&@%%&%%%&@@+.................+@@&@&%&#%&&@+...................++@&&&#%%%@+++.................@&&%#%#%&%@@+................+@%&%%&%%%%##%%%%%@@+............+@&&%&%&&#%%%#%&@+.............+&&&&%%*#%#&&&&@&&.............+++@&&%%#%&&##%#%&&+......", +"................+.+.++..........................+..+.....................++.+..++++.+.......................+.+...++..+.+.................++.+.+.++.......................++@@++@@@@+@++..............+..++.......+......+...............++@%%%#%&+++........................+..+.+..+.......................+..+.++.+............................+...........................+.++.+......................+++++.+.++@@....................+..+++..+......................++++.+++@@+++.........................++.++............", +"................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................", +".........+..+++.+............................................................................................................................+.+..................................+.............................................................................................................................................................................................................................................................................................................................................", +".....+@&#%##***#%*#*#*####&@+................+@@@@@@@@+........................................................+@@&@@++....................@%%#%###%@......................+@@&&%%&&+++++......................................................................................................................................................+&&%%%&@+..................@@&&%&@+..............................................................................................................................................", +"....+@&&****==,===*=>=**%%%@+..............+@@&&&&&&&%&@+................++&@@++..............................+@&&%&&@@@..................@&#**=***#&+....................+@&&%&&&&&&&&@+................................................................................................................+@@@@@@..............................+@@&&&&&@@+................+&&%&%%&@@+...............................................................+@@++...........@%######&&+..................................................", +"...+&%#$$>,,--;--------=$$##@.............+&&####*#*#%#%&@..............@&#&%%#&@+............................+@&%##%%#@&................@&#*$>>,>=*#&+...................&%#$#$*$####%%&@...............................................................................................................@&%%##%&............................+@%##*#$*#&+................@&%%*#*##&%@...........................................................+@%%%&#&@.........@**=>---=>*%@.................................................", +"...@#$*,39;ccaaa000c0cc;,=**&............+&##*==>>>>=***%&+...........+&%#$$$*$*&&+.........................+@@%#**=>*$%&+..............+&#$=33999->$*&+................+&#$*==>,,==*=*$#%+............................................................................................................+@%#*=*=$*&+..........................&%$*$>=>>*#&+.............+@&*$>>>>=>*%@+........................................................+@#*=$>*$*&+.......&%*=3;acc93>$*@................................................", +"..+#=3cad:beee4e:e1eeeebdac3$@..........@&*>3ccaac09cc9,>**@..........@%=>3cc03,>*#@........................+%$=,-0aac3=*%@.............%$,90~be:bdcc,>#@...............&*>3c'adaaaccc33,**@..........................................................................................................+&*$-9c;c3,=*%+.......................@*>3c9cc0c3>*&.............@#=,99aaac93>*@.......................................................@&*=,caaa9,>%+.....+%=-0dbfee|acc=*&...............................................", +"..&,!]/zxAGAGAGAAAAtABttsr^{;$+.......@%=-;']/rrzrr^rr/{~;-=%.......+%=-!)FrrrF{~;->%+.....................@$-;!)FzsyrF'-,*@..........+%>;)]rsyAHysrF);,*&............+%$-'{/rssszz^//FF]~-=%+.............+....+@&&%&@+......................+@&&&@+................................................+#>;!{FrrrF)~;>$%@...................@#>;)]F/rrr^{!-=%+.........+%$-')F/zssz/)!;=%....................+++..+@@@@@@+...................&#>-;~{/sys^{!-*&+...&,'{/stGAAAsrF)-=%+......................+&%%%&%&@&&&%&@@+......", +".+#;)/zAGLLLELLGCCCCGGLCByz/)-%......@#=--!]/sttyxysssz/)';-#&......@*-')FrstxrF)~;-$%+...................@#>;~)FIyvGy/);-=%..........&$-!{/sAGLLLAs/]!-=*&...........&$-!)FzstABAxzzrrr/]',#@........@%###%#####**$***#&...................@##**$**#@............................+@@+...............&$-!)FzytsrF)!;-=*&................+&#$-!]/zsytxs/);,*@........+%=-;)FrsAABxzF~;-$#..............+&####*####=$$$$*#@+................&*=-;'{/KAGAsF~;-*&...@>']KwuEEvCAs/{!-=#@..................@&%##$$$>*=$*$>**$*#&+....", +"..&,;(}IJwNwNNNwJKJJwwwJI/F_;>&......@%==-;~]/^r^^/^Q/F{!-,$%+......@&*-!)F/r^/_~;->*&+..................+%*=-'~(}5OO<1'-*%@.........@%*>-~12PwwwwP[]~;=*&@...........&*>-~{F^rKrr//}F{]_~-$%+.......+@%*********>*$$**##+................+@&**>*>***&+........................+@@@&&@++............+%*,;~)F^rQF_~;->**@...............+@@**>-~]F/^rr/]'-=#@.......+&%*=-;)F/rKzIF(!->*%+............+@%*******$****=**#&@+.............+@&$$=-;!1[8O6[_;>=*@...+*;~}6wNwwJK/{!-=*%&+.................@@%#****$$*$**$>****&@....", +"..%=;_:[8ONNNNYOPIKPJwO6Q2:_;>%.....+&$$--;(1[Q[[Q[QQ[:(!-=*&+......+%$,3~|}[[:1('-,>*&..................@%*>;!((2<66<(;,$%+.........@#*=;'(}>,,,>>==,,=>$*#%@...............@%$$>,--->$$%+.....................+&%%%%%%%%&@+..........&#$,-!_:[[}1(_'-=$*%&+............@%%#$>-;_(2}[[[[(;-$#@.......@&#>,-!(:}QQIQ}|';,$$&+.........+&#*$$>>,,,>=>>,,,,>*##@+..........+@%%#*=--9_|46O54_;->*&....%-~b5RSYOPQ[('->$#%&+...............@###$>,-,,=,=,>,=,>>**&+...", +"..&=cafgmjoqqWqoojpooomi7f|a3=&....+&#=,;ad:fk*@.......@&#>-0be77efeba;>>#@................@#$=-0dee7ipigd0-$#+........+&$>30bbgipjqpigeba3>*&..........&*=-0dee75hl5iggfebdc,*&......+@#$=,9c;0c9939c0cc3,=*@+.............+%*=3c0aac9=*#@...................@&%%###******##%&@......+&*$-90db7774ebba;,>=#&@.........@@%$$*=,9abf7<774ebc-=*%+.....@#$=,30dee4khkh7eba;=>#&+........@#$=3399;ccc339caaa03*$#@.......+&&%%$$$>,;abbfgipifdc9>*&....%,0bgjqjplh7bac3=$*&&+............+@%$*==c0aa0999900c999,=#@...", +"..%,cb4hlXXnnooqWWWZqnXlk4bac=%....@*=-0be7klVVXooZnmVke_9,*&.......+%*,9abeQkllkkedc3=#&+.............&%*,3ab4khhlihfdc3=#&........@#=3;d4khVlmmmllk4(a9=%+........+&=3cdekVVVXVXnXni4:b03$&......+#>-0a(b4ee(ddd|e2bdac,$&+...........@**,0d|e444d0,*&+................+#*$=>-33-333333,==#+.....&*$-9ad|e[kkhlk7ed093>=*%+.....@%**>,39;ad:4klVlk7e1dc3>#&....+#=3;adbekIlVlVVlk7edc3,**@......@*=,;!dd:e4:b(ddfgigfac3=#+.....+&*==>,3330dekhlllih4ed03,#+..+#,cb7imXXVlk4b_cc3,,**%+.........&%*>,99abgii7bdd1e4ee{da03*+..", +".+*;]rsBBCBCCBGvEEEEEGHAxsr/);*...@$;'{/sABACCHGvLELGCAz/);-=@.....+%$,;~FrsxAABCByzF)!-$#@..........+&*-;)]rstCBCCBxz/)'-*#@......+#,;)FryACBBAtBBCByz/{;=#@......+#-;)FrsACBCCHGDLvAsr^{!>%.....&#>;)F/zxtAyzzzsxAAxz^])-#@..........+*,;~FrstBBtz/~;=#@.............@%=-;;~){]]]]]]]]])~!;$+..+#=;;){/rzsxACBCCAsr/]{)!;,%+...+#>-!~{]]F^rstCBCAAyzz/F)';=&...&-!)F^zsxACCCCACCBBxr/{~;,$@....@$-!)//zsxyBAszzzyGDGsI]);-%....+*>-'~)){]F/ryACBCCAAsz//]{;#...*c_FQtAAHCCtyzrFF]{)!;-=%&.....+&$-;~)]F/sHvGysrrsxBBxysr/{;#..", +"..*!)^syBCCCCCCGDvuvvGBCAyz/];*+..%,!)/zAACCCBBGvLvHHCts/{';>&......&=-;)]rxBCCCCBAsrF);-=#+.........&*,-!]/zyCCCCCAyzF{!->%@......&$-!{/zyBCCCBBACCAyz/{;-*@......&$-!)FzxBCCBCHGvvGtsrF{;,%.....%$-~]/rsyBAByyxyBBAyzrF);=&..........&*,;)FzxCCCCs/);-*@...........+&#=-;'{]F^rrrrrzrrr/F{)-%..&$-!)]/zssxyyABBBBAxzr/]]~;,&...&>-')]/rrzzssyABABBxxsz/]);-#..+=;)FrzsyABAABACBACCAsrF]~-=%....&=;)FrssxBBAByzzzxtGGAz/]);$@...&>;~)F///rrrzyABBBABtxszrrF),+.+*-!{^sACBCCCxyszrr/F])';-*%.....%-;){//zsytGGtzzzsACABtAsz/)=..", +"..&,;)]/QKKKKII<$@......@*=,;~]}rKzKzKrQ/|~-,*%@........+&*=-;)F/IrKzKKr[});-=$%@......@*=-!)]/QKzKKzKzKr2])!-*#@......@*>-;'{/IKzKKJKJPKQ1(';>$@.....@%*-'){F/rrKrrrrzr^F]_~-,*@..........@%$-!)2IJwwJI1!-=%@...........+%*=-;~{{}//[/[/[/[/}F_);%..&*-!)1F[/Q//F/////^/^[F:{~-=&...@=-;){1/[/}FFFF//^QrQ/[F|~;=%...$;)|FQrrIr^/^//^rrKrQ/1)',*&...+%=;~{2^rrrr/FF1::[,;)F/QKKzKrI/Q^^}](~';,*&....+%>-~_F2[QII5<[1]F//rKrrrQF{~>..", +"..@*-;_1[QIQQQ[[[24<8YY6-;~12[QIIII[[}1~;->*&+......+&#$>-'(}[QIIIIQQ[:~'->*%@.....+&*,-!_(}[QQIQQIQQ[}(!;,>*&+.....@#*=-'(1[QKIIIII,;~(1}QQQQQIIQI[1(';-$#&..........@#=-;(:QPYS8<(;=$#@..........+&#$>-;(1[[QQQQQ[QQQQ[}:(;*..&*-'(2}QQQ[}||((|1[[QQ[}:~;>%...&*-'_:[2Q[21_|(1|:2QQQ[21~;=&..+%;(::[QQ[[2::|:12QIQ[[2|!-=%+...&=-_|2[QQQ[}1(1(1:[QQQ[}:_;=%...@$;__}[[QQ[}21|||:2[[QQ[Q}|_>+.+&*=3~(}2QI5KIQQQQQ2}((~;->#+....#=;_12QQQQQQ[2(((1[[QQI[[[:_=+.", +"..@*-cde4hlhh77ff47gjqWjmh7ed3#..+%=9d:4hhlhk447hhhhhk4edc-=*&.....+&*,;0de4khhlllhh4ebcc,=*&......+#*,9;a:77hhlllhh4fbac9>$#+....@#>-cabbehkhllhlhh7fbac3>$%+....+&*>-;abekhllllllh7fbda;=$%+....@%=30db:7kkhl5kl5k7eba;3>*&.........+%*=9abfijWUqib0,**&+.........&#*-90abekkh5hhlhhkhhhkfba*+.%*3abf7+..@*>-abe44lmmhhhhkhk4bbba;>*@....#>cde47klhhh4fbdbe4khhlhh4ed>+.", +"..@*30d4kVVllhhhhhhmqWWomVl7ba$+.+*-0b4klVVVlhhlVVVlVlh4ed0c,#+....@$9cd1e7klVVVVVVVhke:d0c>$&....+#=9cd|e7lVVVVVVlVVk4e(a;3*&....@*,cd1e[hlVVVVVVXVVk4e1ac3$%....@#>9a|e4klVVVVVVVVVk4ebdc3$&....&>-cd147hlVVVVVVVVlk4eba3=#+.......+&*>3c_ehmoWWqied;3>$#@.......@%=30d1e[hlVVVVVVVVVXVVlked$..&,cd}klVXVlk41b|bekhlVllk4b9$+.+&,9(eklVVVh741b|beklVVllk4b9*...=a1khVVVlh7eeee}klVVlVk7e'3=%...#-014kVVVVh72e:be4hVVVllked9#...@=ab4;'{]^zxtHvGGxK^])!;,=&+....@$-;{/sxBAHGHCCBCGGvHBCCCyzF,++*;{/stAGGGHAssrrrsyCCCCCCyz]-%.+*;{/sAHGGGCAxzrrrsxACCCCByr(-+.@-FztAvvvHAAsszzsxCCCBCBAz/~;#..+$!]rsAGGGGAAszrzzxtBBCCCAx^)=...&-{^sAHvGGHCtyszzytBCHGvvAy^'@..%,;{/sxBHGvHHCCCCBCHHHGtsr]'$..+>!]rsAHGvHHCByszsyACHGvvHAxr'#.", +"..&,;)FzyCCBGvLLLLuEuEEEELGGsF-@.%,!]rxBGLLLLLvGCCCCGLvCCAxr{!*..@*-~]zyCCCGLGBCCBGGvGBCByr]!-%..&$;~FztCCGGvGCCCCGLvGCCAs/);>%..@=;{/sACCGGLGCCCBHLvHCBBs/);=+..&>;{/yACCvGLvHBCCGLGCCCAy/{;$@..%-;]rxBCBGGLvBCCBGLGCCAAzF)-*....@#$=;!)]/rzsytBAAsz^F)~!;,$@....%>;~]zyCCGvvvHCCCCLLvCBCBxz{-@+*;)/sAGvLvHByzrrrsyABCCCBtz]!%.+*!{rsAGvLLGBysr^/zyCCCBCByz]-+.@-]zyHGLLGCyxzrzzyACCCCCtsF);*+.+>;]ryBvLLLHAyzrrzsACCCCBByr(>+..@-(/sAHGGGBCCyszsyACCGvDGAs/;@..#,;)/zyAHLLLHCCCABBHvDuvAsr{=+.+$!{/stHGGGCCCyszsyBCHvvGGBsF;@.", +"..&*=-~{/IKKwwNNNNuNSuNNNNwP[_>+.@*,;{}IOwNNwNwwJKKJwwwJKI/]_-#..@*>;)/IKJJwwwJKKKJwwwJzK/:~-=&..@*,;)/IKJJwwwJKKJJwwwsKK/|;-*@..&=-'{^KzJJwwwJKJJJwwwJzI/{!-%...&=-']/IKJJwwwKKKJJwwJJzI/{!-%...@=-!{/KKJwwwwJKKJwwwwsKz/_;>#....&%$=-;~)_{]2F[/[/}F(()';->$&....@*,;)2rKJJwwwJKKJJwwwJKKr}{;#+.&>;)2IJwwwJI[F(((]^IzKzKK^]',&.+&=;(}IJwwwJI[F|{(F[rKzKzK^{;*..+>_:[PwwwwKQ/|{]][rKKzKKr});=&...#-!([KONNwPI/}{){F/IKzKzI/(;*....#-'(}IPPPKKK^/}F/QIKPPPI[1'$...@$=;)F[IPwwOI[^[^[QIPPJPIQF'=...&=-~1}IPPJKKrQF2/[QKPPPPI[1;$..", +"..@#>-'(}[QI6MNSNSNNNNNSNSY6}_=@.@#,;_:<8wNNNww6KIIIOwOPIQ[:'-%..+*,3~}QKIJwYOPIQI8OOOPII[:!-*@..@*=;_2QKIJOw6IQQIPwJOPKQ[1;-$@..@*-;(}QIKJwOOIQQIJYw6PII2(;>#+..+$,;(2IIPOwY6IQQ#+..@=-'12QIKJJw6IQIKJwOP5KQ}_;>%....@$=>-!_((|::::e::||{(_(';-=%....%=-;~}QIIOOYJPI-!|25MwY6[1((___:QQIIIQ[|;=@..%=;~:[6RwO6[}(_~_(}QQKIKQ}(;*+.+*;(}5Oww8<}|(___:[QIQKIQ:!-$&...#=9~:-'1}QQIQIQ[2|}}QIII&..@$,cd7immpojmh47hmpoppmm7ec3>@+.&=cabgijppommhh7gmjqjpmm4ba-*...@$3cb7lmpjqoph47hppoppmi7b0-%...&>9degmppnommk77ipooXpmi7bc,#...+@*39cbffggggggggggggfgeebc,#....&=9ab7impoqqpmkhljoqoommkfa,%..@>30beiooomgebdad(e7hhllk4b;=@..&$3cbgmoooi7fb_ddbe7hhllk4b3*..+*cdfijqophfbb0ad:4hhllk7ea3=&...%>9abgmoqoigebdadbekhlllhe_3#....@#=-cbe7hhlih7ff7iilh74bdc,%...@#=3abf7ipji7bb(bbefhhhhh4fd=....@%$9abe47ili44ee7ilih7fbd9$@..", +"..&*9ab7ioqooojjjiipipjWUUUpgb,+.@%>3a1kmnnZnnXlh47hlXXXVVl4b9*++&>9deiXoZojmik477hmnoZoomgba,&..&,cdfiXZZnXmik777kmpoZZop7b0,&..@,cb7moqZommh4474kmpoZoom7b0$@.+&-0b7mooZopmh7777hmnoZZom4d0=+.+%-ab7moqZnpmh777khmpooZnifdc$+...#-!bfijjjojqqqqqqojjjjjjif0=+..+#,cdeioqZoppmVVVXnZZZZqomhb0%..&*9cb7lnnnVh7e|bdbeklVVVVkea3&..&=9~b7lnXnlh4ebdbb}klVVVlk:0*+..*cdehXnnXlke1bbbe7lVVVVl4dc>%...%=90:4mnnXlk4ebdb14klVVVVkb0*....+&$>c_bekmnXm5hkipoph4bdc9=&...@*>9a:4kmnnmh4eeee4khVVVll7d>+....@*,0abekmXnmhhhlnnmh4bdc3#...", +"..#-~FrxGvEEvGCAxJsJxAGvEEEvxr!&+&*-!]^sAHHGHHBtysssABCBCCCyr(>+.*!]/sHDELDHxsszzzsyAGDEEvtzF)$+.%;]rsGDEEvHtsszzzstHvEELDAzF~$++*!]rsHvEvvAyszzzssyCvvEEHyz]-@..*'FrxGEEvvAyszzzssACDLEGGxr]-@..*~FzADEEEvtyszzzzstHvEEvHsr]-@..+>'/syvuuEEuEuEuEuEEEEuuuNs4-@..%-!]rsHDEEvHBCCCBCGHDLEEEvAK]-.+#,')^stHBHCAysrr/rsxBCCCCtzF;%.+#>;{/stGHHCtxzr^rrsxACCCBAz],+.+=~/ztHHHHAysz^rrzxtCCCCAs^{;*..+#-'{^sABHBCyyzr^rrstACBCCyz(>+...+@*,;~]/stvGGHvGGDGGyz/{;-*@..+#>;)/zxAGvLGAAyxyxyAGvHHAtsF-+.....%>;)FrsAvGvGHvHGvAsrF);-#...", +"..%-~]zyGLLGvCxxsszzsstvLLLGy^;%.+*-~]rsCCBHCCBysszsxAACCCCyr),++%!]rJtLELGAssrrrrzsAGLELLAz/)>++#!{rJtLELGtyzr/rrzstHLELutzF)$+.*!FrxGLELvAszrrrzzstHLLuvxzF;@.+*!FryGLEDDyszrr/rzstHLLDGyr{-+..*'/KxHLLuGAszr/rrzsxvLLLGsr{-+..+=~FzxAGHuDvuDuEuuuvuDDvDAz]-+..&-~]rsHLELvCCBBCCCCBCLEELGtz{=@.&=;)FzACCBCBxsrr^rzytCCCCAzF;#+.&-~_/zACBCAAszr/^rzyBCCCBAz]-@.+>~]zyBCBCBxsr/^/zsyBCCCBs/);*+..%-']^sBCCCAAxzrr/rsyBCCCCxr{-.....+%=-;)FzyCGvLLLLGHts/]~-*@....%,')/zyBGLLLBBABBBAGLLEvByr]>+.....@*;!{/zyCCGLLLvGCAzF);-$&...", +"..@=;'1Q8wNwPI2F||]1:2Q6wNw8[(,@.+%$-;{2rKJKKQ^/]]]:F^IKKKK^{!*.+&-'1[6wNwO<2]((((1:[PwwNO<1_-%..@-!{[8Yww8Q}{1((({:[PwwwO<:_,%.+#-~1[8www6Q2:((({1:[PwNw8Q|;=+..&-~1Q6wNwP[}](((({2[6Sww6[1~>..+%-):QOwNw642{()({:2Q6wNw6[(!=+...%>;_|e472<<<<-']QKKKrr/2{()|]/^QKKKr}~-@..@*-;):QKzKI^/]1(({]F^QKKKQF_=+..&>;1[KzKIr2F1){)]F/IzKKIF{!-%...&*-;)}IKKKr^}]((({F2/KKKz/];#.......&*=-;1[IKwwNNwJKQ](;-$+.....@*-;)2[QPYwwJKKKrIKJYNwOI}(;*......+@*,;_|[IJJNwNwKI[|!-,*&+...", +"..&*-c(46YSY5}1(____(|}5YSM52_>+.+&#=-'1[IIIQ[}|(~_(:}[QIQQ2_;%+.@=;~:5ORY8[|((~___11+..%,c(}6YYY54((_____|}8YSY54_;*+..%-c146YMO52___!~~(128YSY5}(;$@...@*>3c!a_|b|||1::1|||d__!;-$&+..@$-c_15YSSO+.+%=;_}QIIQ2}(____(|}QQIQQ}_;=%...@$=-~:[III[21____((}2[I;~|[<6RNSO5[:(;-$%+.....@%*-!(1[5ORYO8865868OOO5[|_-&.......@#*>;_:2@.+&#=3ab7hlhh4fbdaad:e4khlk4bc*..&=cafiqWqpgbbd0aaabfiqWWjgba-%..%>cdeiqWqpgbdaaadabfiqWWjgbc,%..&,cdfjqWqpfbdaaaadbfiqWqpgbc$+..&,0bgpqWqigbdaaaadbfpqWqpfbc*+..&3cbgpqWqifbaaccadbgpqWqigdc*....+%*>,,30aadbbbbbbbda033,-=*@...@*>cdfiqWWjihhhllh77gpqWWjgbc*+.+#*-cd4hlh<74ed_ad:f4khlk7e03%..@#*3cb7+..#9abhoWWZp7f:dd(befhpWWZp4b0$+....@%#=,390dbeef77febdc9,,=*#@...@*30bgmWWWZXmlmXXVhhhpWUWoifa*..@%>9a:kVVVlhk4e1eeekklVVVkebc*+.+*>-a:kVVVIlk4eb|e}khVVVVked>@..%,914llVVh74e:b1e[kVVVVl4ba3#...&*>9a}kVVVlk72b::e4klVVVVk:a>+.....+&#>-0d1kijUTUoi4da9>#&......&$=c_e7hmqUUUTUUUUWoVlh7eac=&......@%$=3'be7ljWUUjieb0->%@.....", +"..*-_FryvEELvAxyzzzzsyBGLEEGx^c%.@=-~]^sBCCCCBAszrrzsBACCCCyzF;@+#;{/sGDELGAAyszzzsxBGLEELxK{~$+.%;]rsGLELvAtssrzzstAGLELGyI];*+.*!:rxGEEEvAxyzzzzsxBvEEEvyQ(-@..*;FKxDEEEGAxszzrzsxHvEEEGy^(-+..*)FztDEEEvAyszrrzsxHGEELGsI{,+....@&**39~(/rsttHGAJrF(!;,=*#@..+#-~]^sGLEEvvGGHBGCCBHvEEELyr_>.+@=-~]zyCBCBCtysszsxBCBCCCAsr(=+.&=-~]zyCCCCBAxszzsyACCCCCAs/;@.+*!{^yCCBCBAtsszsytBCCBCCyr])=+..&=;)FzBCBCCCtyszssyACBCCBxzF;+.....&=,;)F^stCCvEvHtz/{!-#@.....+#-;{/sxCHGDEDDDvDvvHAxsrF)!,@.....+#=-!)FrsAHvEvDGsrF);>*&.....", +"..#-'FrxHLLLvCCtxsssACCvLLLGsr;@+@*;)FryACBCCBtxzzzsytCCCCCAs^;@+#;]^stLLLGCCAysssACCvLEEDyr{;*+.%;{/sGvLLDCBAxssxABCGLLLvy^{;#.+*;FrJBLELDCCAxsssABCvLEEvs/),@.+*!]ryGLLLGCBAsssxACHvLLuHs/)=+..*!FIyGLLLGHAyszsstCCHLDuts/(-@.....+@*=-;)FzACGuLLAr]~;-$#&+....&>']rsGLEEELLvGCCACCBvLLLGy^)*+.&$-']rxBCCCCCAyssxACCCBCCBsr{>++&$;~]rxBBCCCAAyxsytBBCCCCAsr;&.+$;)^sACCCCCBxsssxCCBCCCAxr]'>+..%=;~FzxCCCBCBAsssAACCCCBCAs/;@....@*=;!{/ryACCCHHtyzF);>%@.....@=-!{/sAABCHCHtAyxysszrF])!,#+.....@*,;~]/zyBCCCHHtsr]~-=%+.....", +"..@*,;(}6OwwJJKI^[[QQKJJwwOP[_>+.+#,;)][rKJKKIr[F1]F2^KJJJKQF_-+.&=;_25ONwwJKKr[^QQKPwwwYJ[(;>&+.@$;_}5OwwwJKKQ[[^IKJJwwwP[_-$@..&=;(2PwwwOJKrI[[[IKPJwwO8[(;*+..&=;(}6OwwwJKrQ[[[IKJOwwO5}~-*...@$!([6wwwOJKI[[2[IKJwwwO5}~;#.......+&%*=-'1[PJwwO<|!-=#@.......+#-!([5wwNNNwwPQIIKKJwwww6[_-&..+&*=;)/IKzKKKrQ/[QrKJJJJKK[{;*..+&$-!{^IKKKzKr[/^QrKJJJJKI/{-+.+%=-~F^KKzKKKI/[QIKKJwJJK/:';%...@#=-~]QKzKKzKrQQ^QrKJJJJKr}_-.....@#*--'{F[QKPJKKI2(!-=%+......+#=-'{F^IKKJII[22::{(~!;-==%+......@#>-;)(FQKKPJKKQ1);,$&@......", +"..@#=-c|[P8OJ8P85555888OO654|;*..@#=;_1<5O6O8554:1|}[586OO8<}(,@++*=;([58888P855556666668<1!-$&..+*,!([P8PJP8K655566PO6O5<|;-#+..@#-0|[586O88P555586O8888[1;,%...@*,;|[PPJ6P8K5555668O886[1c>#+..@#-~1<588J885555556P6JP54(;=%+.......+&&$=;(:[88854(-=*@.........%=;_1<6OOwSSY655568PP6P5<:!$@...+&$=;(}[QIPPP5<556PPOYO8<[|!#...@#*-~|}[Q-!(|}<88J6J6<}_;>#&........%,;_(}[QP6P5Q}}:|_!;->=**@........&*=-~(:}<66OJ68Q:!-=%@.......", +"...&*,caf7hipoWWUUqTUqqjih7bd9#+.+$,cb7pqUTTUqqigbfgpqUUUUqjge-+++$=9abghimjqWUqoUqUqjmh7fd9,#@..+%=cab7ilpoqWqUqUUqqpli4fd9,#...+&=cae7hipoqWqUqUUqqjih4bd3=#...&*,3cbghinoWWWWqWWWqji77bac=%...+%,;df7hipqWqTTqTqWqpih7ba9=&.........+&*>3abe7i5fba9>#@........+#=9ab75mmoUUUWqWUqWqpmh7fd9$+...+&*>-adefipqqWqqqqWqWUUUjied*....&*>cabe7ijqqqqWqWqWWUUUjie9@..+#*,cdbegpqqWqqqqWqWUUTqjgbc*....+%$,;ab:gijqZqqqqWWWWUUqjge3+...+%*3abfgijUUUqWqifa3=#@.......+#=;de7hijqqoih7f|a93=*$%%@.......+%>3ae47ijqUqWqoie03$#@.......", +"...&*,9ab4klnZUTTTTTTTWolk4b09#..+*3dfljqTTTTTqjk77ijUTTTTTZm4c@.+&>-a1ekhXWUTTTTTTUUomh7fac>*@...&$-ab4hkXZWUTTTTTUWolk7eac=#+..+%>3ab4hloWTTTTTTTTWolh7ea9>&...@#=9a|4kVpZWUTTTTUUWolh7ba9=%...+%>9ae7hlnWUTTTTTTUWXVh4ba3*&..........@$=3~be77<7ba3**@........+#=!aekVVXoWTTTTTTTUWolh7:a9*.....@#=3ade7mZWUTTTTUUWUTTTWphb,+..+&$=9~be4mZWUTTUUUUUTTTTqm7a&..@%>,c!b4koWUUTTTUUUUTTTUjl7d>+...+%*=9adb7mZWUTTTTUUUTTTUqm4c@...&*-017lVmoUTTTUWogdc>*&+......@*,a|kVXXZUUZXVlkeac,>$&&+........%$,a|7lVnZUTUUUqpfa9=*@.......", +"...&=3!|^stBGDELEEEEEEEGAys/{;$+.&>'FsBvEEEuEEuDtxxBDuEEEuEEGx(#+@%>;(/stAGvEEEEEEEEEvAAszF~-#@...%>;(/zxtGvEEEEEEEEEGBxsr{'-$+...%-;{^zxAGEEEEEEEEEDvtysr]!-#...&=,~{^sxCGLEEEEEEEELvAxs^{!,%...+*3']rstBHDEETEEEEEEDAxs/{;-#.........+%=-!{/zxyxs^('-*@........@>;)FzxCCHGEEEEEEEEEEvHtsr1!$+....&=,;{FrstDEEEEEEEEEEEEEEDtr;@...&=-'{FrsHvEEEEEEEEEEEEEEGx{%..@#,;')FzxDEEEEEEEEEEEEEEEHs/-+...+%$,!{FrsGvEEEEEEEEEEEuEEAx)&..+%-!]zxCCHDEEEEEEGs2)3,*+......&-!]zxACCvEEvHCBtzF);-*&+........+*-~FztCHGEEEEEEvGKF~;>&.......", +"...+#-!{/zsAtGDuuuuuDvGHyxz/)-#..@-~FzxBDEuuuuuttssxGuuuEuuHAz)&.+#>-~]rsytGDEuuEuuvGBysz^{!-$+...%>;)FrzttGDvEuuuDvHHtyz/);-%@..+%=;)FrzytGvEuuuEuDvtysr/{;,%+..+#-;)/zsAAGuEuuEuvvGHyyz/);#@...+%-;)/zyAtGLEuuuuvuvAyszF);=&..........@$-;)]/zssrF);-#+........&,;)/zABCBGvEEuEuuEuvtxsz/];*.....+%>-;]/zyGGLvEELLDDEuuuvty/;@...+%$-']^zxGGEuEuEEvEEuuuGAx)&...+#>;~{^stGDvEEEELvEEuuDAts]-+.....&>;)]/KxGvvuEEuEDEEuuDGAs)&...#-!]zyACHDvEDDDvts/~;=#+......@>']ryCCCHvvGHCByr{!-=#+..........#-!FzAABHvEEELDDxz]~-*@.......", +"....+%*-;~(:}4[k$+.....+#=-!~):24<<5kh<7[42:)~;-=%@...........+%*-;')))~;>*#@.........+#,;(F[KKKP<<<<<<<<[[2:(~;-$+.......%$=-;~1}[<-;00_~__d___a';-,>*%+......+%%*--99aa~__a__a~!;--=*&+.......+#=,-;0aaa~_da_d_~;-,=*%@.....+@%#=--;0aa_0~__~_~!;-,=*@......+@%*$-3c~a~ad_d____';->=*&@.............+&%$>>,->$$%@...........&>;~12QQQ[}:|(_d(d_a~;-->$&+........&#*=-90_a________d__a!-$+......@&**=-90a_a_a__(_d~__~;;#+.....+&**>9c0a__d(a____d__';-$@.......+&#=,-90_a__d__d__d~_'!-#+...@%>-!:}[[QQ#+........", +"......+%**==->,3999033,-,>$*%@....+%$>,3,9c99993-3,3333333333=@.....@%#*$=-393399933,9-=**#@........+&%$>,,3339033333,,=$*%@........+&#*$,,3,939c09333==$$*@.......+@%#*$,-9-cc999333,==$$%+.......+&##*=,,-339c9333,,>>$#%@...............@&****#*%&+............%,;_bbf4fbbaaa0909933,=**&@.........+&#*$,,33,3333399c3933=&........+&%*$,,3333333909993,,=&......+@%$*=,,339cc99333cc93,*#+........+@%*>,>339999c9c3c093,#@....@&*-9def44fffffba0,$&..........@#>cdbe4777febbda-*%&............@#=-abef44f4ffeba;,*&+........", +".......@&##==->,,>-33>,=$*%%@......@&*>=>,3--,>=>=,=>>,,=>==**@......+%%**=,=,3-9,>,>==$*#@+.........+%#%$=,>9,3,,>,>,=$#%%+.........@%%**==,=9-9>-3,=>**%&+........+@%#**==,9-9,,,=,=>*%&@.........+@%$$*=>,=-39,,>>,$$&%@.................++&&%%&@+............+&*99addbddc0c933-9,>,*$#%&...........+&#***>,>,,,,,,-3,,>=$&.........+@&*=>=,,,,,3,39>>,>>*@........@&#$*>>3-3,-,,,39,,=$*@...........&%*=,=,--9-39,,3,3,=#+....+&*>9aadbbe|bbda03=*&..........&*=99dbbbbebddaa9>>#@+............&#=3!dbbbebddaac9**@.........", +".......+@&##$>---,,-,,,>=#&&+......+&#=,>,33>>==$==>3-,-3,,-$%........@&#%*>,,-,3--,,==*%&+...........@%%#*>>3,-3--,,>=#%@&...........&&##=>-,--3->,,==#&@@..........+&&%#=>>-,-3,,,,==#@+..........+&&#*>=>,3,,3--,,,=*%&+...................++@@@+..............&$,;!''_~~'!!;---,,>,=$#&+............+%#**$,,,-3--3-,,>,=*&..........+@##$>-33333-3-333>=#@........@&@#*=,-,-,3-3--,-,,=#+...........+&#>=>3,3-,9-3-,,>==%......+%>;;)~]{{(){);';,*&..........&$>;;))(]{{{();!;-$%+.............&=-;;'){({({~~!;-=%+.........", +".........++@%#**#$$*%#%#@@+..........@%%#$#*###%%&##%%$$**%%%+........+..+&%%#*$***%##%%+.................&&###%#**%%%&&++...............@&#%##*%%#%#%&+++.............+++@%%%#%%%%%%%&@+............@&@@@%$$*$$$**##%%&+........................+.................&*==-,-,->=>=>***%#%%&+...............+.+@%%##%%****#%##%&..............+@%%%%%*##*****%%@...........++&%%*$*****#*$%%%&@..............@&*#*$#$===**#%#%&+.......@#$>=-,,---,=-=$#@............&*$>,,->-;---->#%&@+..............@*=>-,---->-->$*%@..........", +".....................+.+.................+......+........+..................+.....+............................+..+........................+++....+.............................++++...........................+.....................................................+.+.+.++++.+.++.+................................++..........................++.....+.....................+...+...+.+.....................+..+++++..+............+++++@@+@+.+.+...............+++++@@++++..+++..................+..+++@@@+.+...............", +"................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................", +"................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................", +"......................................................+@%%%%@.......................................................................................................................................................................................................................................................................+&%%%%%%#%%%%#%%#%@+........................................................................................................................................................................", +"................................................+&%**=>-;;;--$%...........................................................................................................................................................................+@*****#%+...................@%***$$**$**$*#%@.................+@@+.....................+#>,;;;!;;;;;;!!;!;;->=*#&.......................................................................................................................+@&%%%%+.....................................", +"........................................+@@&%%%##*=--;!)))~~;-*+.........+@@&&@+@@&%%@+..................................................................................................................................................+%=>----=##@.................&#*=,---;;-;--->=*%@..........+&%%%#**#@....................%,;~))))))))))))))))'!;,=#@...........................................++@@@@++..+@@@+..........................................................@%#*=$>=$##@...................................", +"......................................++@&&&%#***$>,-;~)(()';-*+.......@@%&%%&&&&&%%%&@+++...........................++...............................................................................+++@@&&+...........................@#$,---,=**@+................@#$>,----------,>$%@..........@%%&#*$$#&@+..................%-;)(((()~~~_~)_~)((~!-=>%@.......................................+@@@&@&&%&@&@@@@&%@@@@+.....................................................+%#*$>>,==**@...................................", +".....................................+&%###$>*$$>=--!(17<7}:(;$+......&&##*#####***$$$#%&+........................++&@@@@+...................................................++&&@@+.................@&%#&%#&#&+........................@#$,-;~!;->#&................+&#=-;!!!!!!!!!;;-=#@..........@&#$*>,=*#&@+................+$;b}4<4}::::|:::2}4[7:_9=$@...................+@+................@%%#%###*#$#*#######%##%&+...................................................@%*>--3;;;-*%+..................................", +".....+++@@+......+@@@@+.............@%**$$=,333333;abeijqjpgfd-+.....+#*>>,>=*==,>>,==*$%&+..................+@@@@%&##$#$%&@+..............................................@&%%##%%&+..............+&***$*>$*$&@+......................+&$=3cbebdc,*#&+..............+%*,0dbbbbbbbbbddc-$&+.........&%$=3c99,>$%&+...............@-agjjqjihh777774hijqjjec-*&+.................+@&&&&++...........+*$***>=>,>,=>>==>>===$**%&+.................................................+#*=9;a0ddac>*@..................................", +"....@&#*%%#%@@@&%%%####&...........&=>,339caada_addb4hjWWWoPl49&....+#=,9cc0999c90c00c9,**&..........++@@&&&&#*$=>=,33,3,>**&+......+@@&&&&&@+.++@@@@@@@@+...............+&*==,,>==$#%++..........+%$,39399393>*&+....................+%$=3014k7edc-=#&@............+#=3cd4444444744eedc=#&........+#>3cadd~a-=>*&+..............#9biqWWZoVVVVVVVVVoZWWqgb9,*@...............+%*$=****&@.........+#=3-ccc0c0c0cc9c0c00;c93,>*&................................................&*=30dbbeeeed;,#@.............+@#%&&+.............", +"..+#=---;--,=$*==---;;->%@........&>!){]]F/rzzrrrrrsxBGLELGHAs)#...&*-;~]/^^F]F]///^//]);-=%+......+#*$>-,,--;;!~~)){{]{{)!;-*+....&*$>,--,-,>=>>---->->,$%@............+%>;!){{{{)'-,$$@+........#-!){]FF/FF{~;,*&+................+&$-;!)/zABBxrF)';-=%@..........%>;~FzAABAABBCBBys/{'-*@......+#-;'{/rzz^{~;->#&@+...........-]KALEELvCBCCBCCCHGLEELxQ(;-#+............+&$>;;!''!;-=%+.......&,~{]F/^/^^^^/^/^^^^///]{)!;*+........+@%**$*$$*$$**#%@+....................%>-!{FrssyAtsr])-*+.........@%*>>;---=%+...........", +"..%>-;')~~';--,,-;~))~!--*&+......#;{F/rrzzyytyzzssyBCvLLLvHBz)%..&=-;~]rsysrr/rrrzzzzrF);>*&.....+#=-;-;;;!'~)){]F//rrr/F{);=%...&=--;!!!;;;;!!;;;!;!;;---$#&........+##-;~]/rr//F{!;-=*#@......+=!{F/zsxxssQ]~->*@...............&$--;!)]/xACCAsrF)!--=##+.......&$-;)/yACCBABCBCBAsr]!-=#+.....@>;!)]rsyyz/])!-,$*#%%@@+.....+,FztDLLLHCCCCCCBCCGLLLGyI]~-%.............&*-;!){{))~;-*&+......$~FrsssxyxyxyyAyyxxyyxJsrF{'=+.......+&*,---;-;;;;--=$*@+.........+@@@.....%$-!)FrxtCCCCAs/{!>+........&*=-;'~)~;-=#&..........", +"..%==;!~~);-=>*=-;~)();-=*%@......$;(]}/[/IPJJII[//QKKOwNwwKQF;&..@*=-;([PPI[FF2/[/Q^QF(;,*$&.....+#=---;;;;'~))){1F:/[F}F(~-=#...@*=-;;;;;;;;;;;;!!!!;;-->*%&+.......@#*=-':#@..............+#*==--;~:IJwwKQ|);;-,=**&+......+%$,;1IJJKKrKzzr//F]'-**&+.....@$=-!)}<66<:(!;,>$*#&&&&@+.....>~}PwwNwJJKKIIrKKKwwNNw<2~->&............+&*>-~({{{)~;,*%+......#_[K6OJOJOJOOwOOOJOOJOO6<}|!$+......+@%$>>>-----;--,=*#&&+........@&&&+...+%*>-'([PJwJwwPQ:)-*........+&#$>-'~~!;,*#&+.........", +"..#=-;_(1(';>=>,-;)1:(~;-*%@.....+>_12[[QQ<6YY8<[[[QQPOwwYP<2(=+..@$,-~|5665[:::}Q[QQQ}|!->*%+....%=-3;'~~~_~((1::}[QQQQQ[1_;-&...&$>3'_(_~~~~~~~~_____!;;-=>#@......+%*=-;(48OY6<}(~;,=**#%&....+=!|[5OYMSSR5:c-**@..............&*=,-;!~(}**&@.......+&%%%&@+@&%$=;~|[6YRSSO6Q|'-%+.......+%$=-!~(((;->*&@.........", +"..*30df4gebc99-9!df7gedc-=$&.....+>b47hhimpjqjmi74hhiXpjopm7e0=+..@=3cdeijqp7ff47hhhkh4ea;,=*@....%3abefeegffgggggiiipipiigb0;%..+&>0affgefffegeeffegefebbc3,*&....+@%**,9abgpjopi7bdc;9-,>*%@+..@,0b7ioqqUqqjfa9>*&..............#,90ad_begiqUUji7bbbdaa;3>*&.....@#*9ceiqqphkhk,>==$&@...$cfiqTTUjmilimmmmpooWqjgba9=#+...........@&$-0be47fedc-$&@......*agipjjojqqqqqWWqqqjqjjjigbc*+....+@%$>3;adbbeefebbac9,>#&+......@$,==#%%&%#*,0dfgjWUUWjpgd0>%+.......@#*,;dbfeed;-=#&.........", +".&,a17ipjmged~adbfipnhedc3*%+....&c:klXnZoooojmhhhlmoonXmm7fba>+..#,0de7pZZnhhQhlVlVVlI7edc9=%+...>bgpjjjqjjqjooooooZZWWqqmhfd=+.+=cbgppjjjjjjqjjjqjqjjjig4bc,%+..+%*=3;cade7mXnmlkk4eb(daac,*@..@>ab7lmnooopi7ba3>*&............@,a:e47kkkloUTTWphhkkk4e|a9>%+...&*=3cd7mqZXlllVVVlk4edc3>*&.....#,cdb4ijWqpheeba'aaaaaaa09>*@.+=afjqTTTqXXXoooooZooXomhed03*@...........@$=cdekllk2ba9=$@......%3dfggghiiiipoooopimiiiggba0$.....@%>3cd:ekhijjqjjg7e|d9-*&.....+>adac-****$,3~e7mZUTUjpgfd9-%........&*,cbe7imigba9=&.........", +".$~rsBGvDvAsrrrrzsHDDys/{~3$&....%(rtBGvLELvGHCBAACDLvGHtxsr/)-+..=)/zsxGLEDBttAACCCCCCtxrF);,#..+;VwEuuETuuuEDDLLvLEDuuEEDAxr;@+&;{IxvDEEEEEuuEuuuuEUuuuGAz]~$+..%>;~)]/rrsxBCCBCCAyyzzzrr]);*+.%;{^stCBCBHCBxKF(!-=&...........=]rsABBBBHHvEuEEGHBCBBABsr]~>@..+*;!)F^sHDDGBBABCBBtys/])'-$&...+,!]/zytGLLHtszr^//^rrrrr/]'-%++;2suuuuEDHGDvEEELEGGHGCyz^{'-%..........+#-;{/sBBAtyzF~;,%+.....#9_b}^rKsssyHCHHHAAsssKzQ2]~,+...@$-;)FzstAHDEuuuDvBtyr]~;,#@...&!rz/]);;-3;!)^stGEEEEGys^]~3%+......@*-']/yAHDDtz/);$@........", +"+={rxHDLLLtJrrzzsyHGvAJ/{';=@....%!zABHLLLLGCCCBBBCGLLHAAsz^]'=@.+>(^zsAGLLGtyABCABCCAACyz/{!-*+.@~zGDEEEEEEEEEEEEEELEEEuLvHy^;@.#-]zAuEEuEuuEEEEEEEEEEEEGtz/'$+.&=;~)F/rzzsyBCCCCCCByssszr/);*+.&-)/zyACCCCCByr/]'-=#@.........+-]zyABCBCCCLEEEEGCCCBCCBxz/)>%..%,!))FrsGDLGBABCCCABAsr/)~;;*%..%,!]rzyBvLLCAyszzrzzzsszzrF~-#+&-^svEEEEvGCvLLLEELLCBBCts/F);%..........@*=;)/stBCBxrF);$%......&-;))F/^rzsytCBCCAyszKr/F])!>+...#,-')/sABCHvLEEEuDHByz/{';=#+..&~^sr/{!;;;;']ryBHvvELHsKF);,%......&*,;~]rxBvLvAs/{;>&........", +".*;1IPJwwOP[:F1F2QPwOK1);-=%+....+-(/IJwNwNJKrQ^/QIOwwPI^2F(;-*+..>~F}[KOwYOIQIrKKKKKKKK/}]~;,%..+-15OYRNSNNNNwNNwNNNSNSNS6I})>+.&=':8wNNNNSNNSSRNNNNNuSMPQ2)-%..@=;'(|:}}2[IKKPKKKKI^QQQ/}{!-%..@=;_]^IKKJKKI[]{~;-*%+..........=):/rKzKzKJONNNwJPKKKJzI/F);=%..&,;!_{}QPOwPIQIKKKr^^/F{~;--=&..@=-~]2[IOww8I[[[222[Q[[/[1)-=&.+,{[6SNNNwJJwwNwNwwwwwJJI[:(;-&..........+%#,;_//Kr^F{)->#+......+$>-;;!)_|F2QKJJKQ2}]]())';-#....%=-;_]/^IzJwwNSNROKIQ}{);-*#+..+-]F}]~;-->--!|/IPwNwO5[(!-=#+......+&*=;_FQPJwO5}_-=%@........", +"+*_25PJOJ8<42:::2[6O6<(0-=#@......$~:[5OSNY6<}}:}}<6RY6Q[}1_;=&..+>(4<56YMSY855586JO86885<}_;-*+..*_:<<5558RRNSOOOwwNSO855[:(9*++@,015MNNMO88556558pMSNNM<}(~-#+.&>;(:4<<<5558OO8886656555<1_-&..+$-'|[58O8J65Q}1(!-$$+.........+$'1[QQQIIIPJMNNR6II6JJPK[:_;=%+.*;_(1:}[6YY6(45MNNROPIPOOOOOOJOOYJ5<4:~-%+.........+&*>;_1[Q[2:(;-*%+......+#*=-,;!_(|}[IKIQ}11((((__!-*+..+%=-!(}[QI#+..@-(24[2d;->,-!(1[<6OO8<|!3=*@.......@%$,;(}5P8654_9-$%+........", +".=dijjXmmlh774474ijqjgd9=$%@......$0begoqWqmfeb|bfgjqqpi74ea;=%...3fpjqqUTTUqWqqZqWqWUWqojgfac*+..%,cadbffgpqqon6mnqqjigffba9,#+.@3afiqWqjig7ffffffgjqUqjgba;,&..%3agijqqqqqqTUTUUUqUqUqWqjib9%..+$3abijqUWWqomh7fb;=*@+.........*d47hklllhmjWUUqpmmoWqqpifb;=%.+>0ee77hiqqWpimpoqjmmk5h74bbd;*+.@>0b4hhmoqUUqUqUqUqUqqqWjje0=&.+3egpqUUWjmmlhilllmoqUUWqqjgb0*+..........@*>;de77771d03*&.......+#,9c0aaabef7kl5h4e1bbbbbbb0,@..@$-abf4hhkhlmmmmiipoqopgf_0,*@..+,bgijiga;--9ade7glli5fd;,*#@.......@#$,;bijjmigba9>*%+........", +"+$biqZnVVVVlkkhhhVoZoibc,*%+......*014loZWZm7eeeefioWWnmVh7ba3*+.@9gpWWUUTTTUWWWWUWUTTUWWomfb0>+..%=990dbfgmoZXXVXnZZXifbdac-=%..%cbgjWUWohk4eeebffgpqTWjied0>#..%cbhpZWWUUTTTTTTTUUTTTTUWZpe0$+.@=cb7pqUUUUZZXlVbkVVVVVlVXoWUUWoXnZWUWoVh:a,&.+,:7kllVXoUUonXoWWZnnXVVVhke1d=++#3d4hVXXZZWUUUTTTTTTTUUWWjgc,&+@9elnWUUWZnXVVVVVXXoWUUWWWoif0$..........+%*30b4hVlkeb_9=%+......%90_db1be47klVXmVhk4444k[74(9#..&3a:7klVVVVVXXXVlhmoWZomkfbc=@+.@3ekpWoibd00~de4kllVVl7b0,>#@......+&*=3cfpqZnl7109,*&@........", +"+=eJtHCCCCCCCHHGGvvGHx^(;-*@......>{ryAGGvGtszrrrsxvuEDvGHtz/)-@.@;KtGvLEEEEDLvDDGGDDEDDDHyrF{;@..#>c'_1/IsAvGvGCHGHvAsr/](!3,&.+$)/sHEEEvHyszr^^rzsvLELvtz/{;*++$_^sAHvLvEEEEEEEEDEEDEvLvDtz:,+.&;(/sAHLDELvDHCCBzF);=%........+;^AACCCCCCHvEEELGHGDEEEDHtsF'=@&;ztBCCCGvEEvGHGEEvGGHHCBAAys^;@+>(rsBCCHBGLGDvEEEEEEDDvDGAIbc%+&~sBHDLDLDvGHHBCCBHGDvvvDDHtr{-+.........@$-!{rxBCBtsrF)-=@.....+-]rzsxsyABCBHvvvGHAtBBBBBAxr)$.+=)/ytHCCACCBHCBCBAHGDvvGGAzF;#+.@'^xGLvHsr/F/zsACHCCCAs^(;-*@......@#>-'FVADDGts/(!;,=%@.......", +".=)FrsxtBCCCBHvLLGGCxz/';=#+.....+-{zxCCCCByzrrrrzyvuEELLGAsr{-+.+-]zABHvEELHCCCBCCCCCCCxsr:);=+..&=,-!)]/rsACCCCCCByzrF(~!--#@..#~/sHuLLvAysr^]FFrsGLLLvys/(;$+.%;]rsyBCCCHvEEEEEHAACCCHCBtr(-@+&-{/zxBCCCCCCBCCtz/~->%+.......@;rtCCBCCABAGLLLLBAAvLELvBAs/)*+@'rtCACBCvLLGBHvLLvCCCCBCCBAs^;%@,]rxBCBCCCCCCCCGLELGtxysz/F~-#+&~rACBCCvvLvHBCCCCCBCCCCCCBs/~*..........%=-~]ryABCAsrF';=&.....@;/sBBBAABACCGLEELGCCCACCCByr)$++>{rxDGHABCCCCCBAyyACBCHGvHJF;#+.@;/sGvLtxzr^rztGLGHCCAs/);-%+......+#=-!FstLLAyzF{~;->*+.......", +".&>-'(]2^rKJJwwNwwJQ[:~->#&.......$'2^rIKII/1((((1<8wNNwNw6[1'=@..*;]2[IJwwPI//IrKzKKKI/F{~;,=%+...+&*=,;!|}QKKsKKr[](~--==*%+...+>~:5wNwJI[](';;'([6wwwJQ:~->&..+*-~(2[^IKKJNNNRPQ[QIIIKKI[{'$+.@,;(][QIKKKKJsKKQF)-,*@.........-1/IrIrI/^QJwNNOPQKONNwJKQ2);%.+-|^rrrKPOwwJJJwwwwJJsKKKrQ/F)-@+$']/KKKzIQ^Q^^IPOwO<[::|_';>*+.+-1^IKKJJwwwJKKzKKKKKKKKKQ[F~,&..........+%>-!{/^Kr/F{~->&+.....+-]^rrIrrKKzJwwNNwJKKzKrKrr^];*+.*;:5OwPIQrKKI^Q/[/^QIKPwwJ[_-%...>!26OOPQ21||}*$%@+......", +".+&=-;~1:2...#c_|}46MM522}}QQIQQ[[:(!3=*&+.....+&**-;~|}[QQII[1_;->*#%&.....+*0:5MSR6[:(!---'_:@+*!(2QIIQQ}}}}}[&..+%-(<8O52:(((1<8YOIQ21_-=*@+........@*>-~:5MO**#&+.....", +"..@$>9abbf4hmoWUWqmgba3=$#@.......*cb477kk7edaaadbgpqWWWqjmgba>+..#3abbgpqqjgff7hhhhhk7ed9,=*&+......+%$,3ab4khlhh4:a-,**%@.......=aepqTqjgfd99-9c0fiqWqpgbc3=&...&*3cab:f7hmqqWji7f7khhhhkfac#+.&>cde47khkmppmhked;,*#@.........=b7khkkk74gpqTUqiggjWWWpi7ba3&..*cbe777kpqqnimponmmhhh77eeb_c$++*0bf7hk74eeef47ijpigbac;>$$%@...=ae4kllmoWWopmmmimmmmihh7ba9#+..........@&$,cd7kih7:dc,*#+......=dbef44777k5pqWWjmh774444e|a-%++>cfijpi47kllh7ebbb:e4hijqpga>@...&,0gipgfebbbeijqji7f10-=*@........+#$,9dfiqjieb_ac;3->>*%@....", +"..@*=3ad:4kVnoWUUWphedc3=#@.......=d4klllhke1dddbehjZWZXonXh4b,+..%9a|fhjqUjhh7kllVlllk4dc9$$&.......+#*30(e7kVVVlkba3=$%+.......@,dgpWTWohfb_c99abfpqWZog:ac,%...@*,cade4klmXZoni4khlVlVlh4b9$.+%cb4khVlVXnZomh7edc,$#@........+,1kllVllllVoWTUqpmmqUUWomk4d9#.+%cdb44kioWZXVVXnnXVlkk4ebdac3#++,b47[77k447khlhVnXm4ba0,=#&@...+>deklVXnWUUWWqqqZqooooXi7b~,=@..........@$=3afinoni7ba3>*@.....+*cad|beee[7hmXoonlh74eebbdac=@.@,b7lnnVlhmnom44e:ee7khXZWjgd9#...%>cbggefee4kkmoZol7eac,*&+.......+%*=9dekmopiffe4e|d_a9,>#@...", +"..&>-'{F^stCHvEEEuvyz/{~;,$@.....+;rxBCBBCAszrrrzsyHLLvvCCCAy^;&..$~FrzyDuEvAtBBCCCCCCtz/);-=&.......@=-'{/stCCCCAx^{!-=&........&'QsvEEuvAsz^{)(]^JtLLEvtz/(;*+..&,-')]rstCCCGGGAttBBCBCCAs/)>++=]zABCBCCGDDGCyzrF);-=%&@......+;zAACCCCCCGDuEEEGHHEEEELCAs/)=.+%!{/rzsyvEDDHACCCCCBAxz^]{~!-*+@'ryyssssssxtCBCCHAtz/{~3=*&+....-(rsACCGEELEuEEEEDEEEvDtz/{'-%+.........%>-~FKtvuvHsr]~-=%+.....*-~({1F//zsxBCGGBtsr^/F]{)!;=&.@!rACHCCACvDDAxzzrrsABHvvEvxr(>+..%,0(2^^zzsABBHLDGxzF)!;=#+......+&=-;{^stCHAAssyBtysr/F)~->%+.", +"..%=,;)FrzACGvLEEEGxzrF);->#@....+;^yACBBAAxzrrzsstGvGHBCBBAsr;@.+*'F^zxvuDGBAAABACACAAz]';,$&.......&>-!{/sAACAAAs/_;-$+........&!/xGuELGAyz/]))F^zALELHAK/);*...@*-;~]/sBACCCCGCAACCCHBCyzF;*++={sABCCHHGGGGtsz/]);--=*%&&+...@;ryCCCCCCAHGEEEEvBHvLLGvByz/!*+.#-']/zsxvGLHACBCBCCAysrF)';;,&.@;^zzrrrzzssBCCCCBByr]~;,$&+....+=)^sBCCHGDDuEvuDuEuELvvAK]~;,&..........%>;)/sGLLvtJr]~-#@......@,!'~~){F/rsxCCCCyz^F))'!;>=#+.&~zxACBCCBHGHttzrrrytCCCvvGy[~*...+$;')F/rzxACCGHGAJ/]';,$@.......+*>-'{rsBCBByxstBBByyzr/)!-$@.", +"..@#*-;'{}IJwwNNNw6I[2(!;-=*%+....-(/IrrIr^/]|F2/[IPPKI[/F]])!$+..%-~(148OwPIQ/IrzKrKr^])-=$&+.......@*=-!)}rrK^^F]'->#@.........+>_[8wNwOI[:)';!_([PwwwOQ:)-=&...+&$,-!{/rKKsKJKQQIJJwwPIF{!>%+.#!FIKJwwwwwJPQ2F(~;,=>$#%&&++..+>(/^IrQrQQIJNNNYPIIIJJJKI2{!-#..@=-'(F}QPwOPIQrKIzQ^F]);-,=#&+.+*;~)~'){]F[PJwJJI[]_;,*%@+......&,)FQKKKKPP555I5666OJJP[{!-=#+..........%*-;([6wwwP[(;-*&+.......#=>==--!_(F^KKKr[])!--==#&@...@-:^KKKKIKKPP<2|||]FQrKKJPI2(,%+...%*=-')(2IPJwJP5[1~;-=%+........@#$=;)]QrIrQ[F2/^KKPPIQ1~;,*@.", +"..@*$,;_(2<8SNNNSSO>&+...+*~:[Q[[[2:|(|1}[[QQ[:|_!;--=%+..&>;~125YY522}}[QQQQ[}(;->*@.......+%$>-;(2[Q[}11'-=#%@.........+>~:5MSM6[}|_!!~_(}5ORY6}|0->&...+%=>-;(:[III%..%;_[IJOwwJPIQ}:__'3->=*$$##%&+..*!(12[[[2}[5YNSO<}2Q**&+.....&31}QIIQQQQIQ}((~~(}[QQQII[:0,@....@#>,;;(:*&+.........@*=-;(}[QQ[}}(|12[6OYO5:_c,*+.", +"..@$=-cabeiqWTTTUqolh4bbac9>#&...+$~b747hk7f:bef774747bdc-,,=*&+..&=9abeiqqjg7fe7khhh7fb93*#+.......@%*>;ab4k<7:b_c-=#&+.........+$0fpqUWjg7bdaaadbfiqWqpgba3=@...@#=,;abeklhhkhh77gpqWqpgba9=@..#cbhmnWWWqnmh4ebda09--,-=*$#%+..#9dbeeeeebfiqWUjiff7hlh4eb03*@..@*3cbf4gpqjiff7hh74ebd9-$*&......%$>=-;adbgjqWqjfda3=*%+........+*cb7khk74ffeeff77hhlhkfa3=*@..........@*=9c_gpqWqif03=*@........+&%##*>-cab4hhl7:a3,*$%@......%9b4khhkkhhh7fbdadbf7hkhhh7b0=&....@%*3;abeiqWqpgba;,$*&..........@$3;dbekk44eebb:fhpqWqigdc-=&+", +"..#=30(e4hpqUUTUUWoXVhk4e1d'-*...+=aeklVllhk747klklll7e_9,,$$#@...&,0de7pWqoikkk*&......+%=3ca|4kllk4bd03>*&+.........@3dgjWTWoVh44eee}4hpqWWohbac=&..+%>9ad|eklVVVVVllhVoZWZnkb'3=&..*a4hXnZWWZZXlh74feebb_aa'0c-=&..#9ab:ee4e47pWUUqih7hlVlked!3*&..&3014khlnqomh4hllVkkeb03=#@+.....&*=>90d:7hjWWWpgba3$*&+........+*cd4khhk774447khkVVVVl4dc,$&.........%*=,;aehpWUqpbc3$$@........+@@%*>,ca14kVVVledc,>#&+......%ceklVXVVVVVl4ebb1e7lVVVVV7b0>&....&$3;abe7pZWZnhe_9,=#+..........*,0_b4hVllhk7[47hmoWWWohfd0-%.", +".@>!)/sAAHGvLELDvLDvvGGGAts^{-@..@-{rytCHGHCAACCCCCAAsr]!c->=*@...*;{/zxGEEvHBBACCCCCBtz/);-%......#>;)/rsyBCCxz/F)!-#@..........&'/JHuEEvHAAAtxAtAAGEEEDxK/)-#+.@=)]rzsxBBCCCCCCHHvGvLvGs^{!-%.+>{zACHLDvvvGHHHHHBBtysszzr/]'$+.%;{F//rzzzxGEEEuGxxtAAxs^F);>#++>)/sAHHGGvGtxxBCCCBys^{;-=%......#>-;'{/sxCHDLLts^{;,=%.........@,~FrsyyxxyAttBACHCHCCts/);-&.......@%>-;)FrsAGDDvAK]~3=&+........&%=,;']rsyBCCBts/);-*@.......#~rsAHGGGGCAtxszzzytHHGHBAs/)-#...@$;~]^zytGGDDHs/{~c=&..........+-{FzsABHHHCCBABAGDDuEEvHtz/)=+", +".#;)FzyDDGGHCBBtBHGLLLEuDGAs/;&.+&-)/zAGvGvGCCCACACByzF);->=*@+...*;{/zsHuDvHCCCCCCCBBys/);=&.....+*-)FzyAACAByr/]'-*+...........%!/sHDELLHCCCBCACCCvLELHAKF);#.+%;{/stBCCCCCCACCGLLDHCCxzF);$&++=]rsxCCCCCCCHGDLLLLLCCABAxsr{>++&>;'){]//zstuLEvtsszzzr/]'!-=@.+={zxHLGvGHAysstCBBBxzr)'-*&+.....%,-;~]rsBBCCBAsr]';>#@.........@>!)]/rzzsAABBCCvvvBCBAz/)-=@......@#>-;~{/sBCCHHHyr]'->&.........@%>-')/ztBCCCCAs/);=%+.......@;/sALLGLGHByszzzsAHvLGGAsr]'-&...%,;)FzxACCCCAyzF);-#+..........@;FzxtCGGvGBCBCCGLEEEEuLvByr),+", +".%-~_[6OwwPKQ[2F2QIwwNNNwOKQ{-@..+*-~1QPOwwJJzKKzKr/])!-=$#&+.....&=;~|[8MwOKIrKKzKKrI/F~->%+......#-'(/QrzIr^F)!-=$@.............-([PMwwJPKKKKzKzKPJwwwJ[|~-*@..&-'|/rzKzIrr^/QIJwYwPKI[1!-=#+..&;~F[rKKJzJKJwwNwwwwJKKIrI/]'*...&*=,--!_126wwwO<21_)~;;-=>#@...$'2;'{}^KKKIIQ:(;,=#+...........+-(2^KJJwwJJKzKJJwNNNSNwJKQ1;$+", +"+*;b4<5665<}:((_(|4558O685<:~=@...%=;~|<586KIIQQQ[2:('-*#%@+......&*-!(}5YY6IQQQIIQQ[2}(;-*&+.....@*;~|}[Q[[21(;->#@+............+$;1<6OOPIQ[2[22[[Q5J88<}_0-*@.+#;(:2QQQ[}}::::[5885Q22(~-=*@+..&>~|}[[Q[Q[Q<5688OOPPIQQ[[}|;*+..@%#$$=,-!1>>*#&++..+>~1[566P[}((_(2Q[2}|(!-*#@.......%*,;_(1}2[}|(~;->*&+............+&#==-;!(|}QQIORS6Q[}1_3=%@.......&#>-;_(}-;):[QIIIQ[|'-*#@.........%-~:<5665Q2:}[4[<<<5P<[|~3,*&....#3'14[$#&............@-_2Q5POJJKIIIIIPP6OMMMO6P[|;*.", +"+>bgppig74bbdaaccadfegiiig7ba>@...&*390be777hk444e:(93=#%&+.......@*3cbeiqZpmhhhlhhk74:a;=*&......&,abe7hh44e(03=$&@+.............*9bglmlh7eb|b|b1be4hih7ba;=%@.+*0e77k74eb(dd_bf7gg7fbda9>$#+...@3ae747f4eeeffhghillllhh44ed;*...++&%#*>3cbijUWqgb09>$$*%@+.....,b7ghhg7fd000de474:ba;,*%@+......&=;abbee4e|ac-->$%+..............+&*$>-9_bf%&...........+&#=9cdeklllhh4bc,*$@.........&=3abbffefbfgjjqpi7febdc3-=%.....>0bgppm44ebd~;=$*&@............+,d7ioonmmlhhhkh77ghi5ipojifc*.", +".,fpqoik4ebac9999ccabf4Q4[f:a,...+&#>30d:f4h#%+..............*0bklVVh7e|bddadbb4khk4ba9,$+..=bkhlllk4|ddaadbe774eb(09=*&+...%317kk44eebbee477klVVlVll7edc%....+@@%>=90fiWWUjgb03,$*%+......@3ellhk74ed0c00b774ebd03*&+.......%,0|447k4ed03,=*%++...............+&#*-9abklVXoWWjheba9,$%@+.....@*>3de4lmoZoied09>*#@...........+&$,9'b4llVVVVkbc3>%+.........@*,90abeebe7pZWWom7ebac9,*#@+...@,b7pqoml7:d09,>*%%+............@,bgjWWoXVVVlllk747[hhlnoZpf0*+", +"@;IwDDAsz/F)';;;;'~1/zsyxszr]-+...@$,;~F^zsyBAtysz/]'-=#&+........&;~F^sGLLGCCCCCCBCtxzF)3$@......={rstBBBts/F~;-*&+..............>)^sACCtsr/F]{){]^zyyys^F~9=@.+-ryBAAAsz/F]({{Fzssz^F]);-=%....%~/xAyszrr^/F/zssxAACCCBAxz/_=+....++#>-'{IyDEEux[_93=#+.......@'sBCBxys^]'!~{rsxsz/]~;=#+.......*;{rsyyxsz/)!-,*&+.................@#$;!{/sBBHGEDHxz^]~;>*&......%>;)/stCHDDDyrF)!-=#@...........+%=-~{^sBCCCCBs^)'-#+.........@=-;'_//r/rJtDLEvts^](!93=%@....@'rxHDLGtsr])!-,=*&.............@!^xHEvGHCCBBCCtysssxtAGvEtI|=+", +"+;rtHAxKr/{!;;---;'~{/rzzrr/{-@...@%=-~{//rssyszz/F);-$+..........@>']^sAGGHBBCBACBAyzr]'-$+.....+=)/zyAAAyzF{!-$#@..............+$;FzAAttr^{{'!!~)]^zssr/{!,#@.+-Fsxyyyzr{'~'~~]FrzrF(~;-$&+....@;/zxszr/F](]F^rzyABAAAttzrF~=+......+$-;)/yGGGxzF)-,#++.......@'ryAxszrF)!;!)/zsz/])!-$+.......+*;{Fzsssz/{';,*%@...................@$-;~FzABCCGGts/F)'-#%+.....+#=;)FzyACHGtJ/{!,>#+............+&=-')/stBBABAs/);=%+.........+&*>;!{FFFFryHDGttI])!;,#@+.....&'^sAGGAyzF);--=*@..............&;/stvvHAABBBtxyzr^zzyytGtw^)=+", +"+$ae2e1_!;-=*#%#***=-;!~~~!;-%.....+&*,-;;')))))~';,#%+............#,;~1[;))){])~;-*#@+................&=;)]]])~!--=>>,--!)()';-*&+...#-)){{)~;-,,=,,-;'!;;->*#+.......$;~))~!;;---;!')){{F]]]{)~;>@........@#=-~:[<<410-*#@..........$!]])))!;>=>,-;))~;--=*&+........+$-!~)))~;-=*&+......................@%*,;)]F[[[[e1';-=#@+.......@%=-']F^[Q[e(;-=#&................&*>-!(]]F]]{);-$%@............+&*=-;;;;_:}[7}:~;-=*&+.......+-)2[Q4}(~;-=**&+................=~(e4[[}2FF]]])~~!~))1224:~,%.", +".&>;;c3,,$$#%+.++@&&**>,=>=*#@......+@&*==------,>>#@..............&*=-'(:::(__'_~!;--,*%@........+*==-----,>*%+..................+#>--;--,==**%*#**=,>>>=%&+....+*,-----,=*###**=>==*##&+........&=,---,===*$>>,,--;;;;--,,=%+........+&*=-0_((a9=*#&+..........+$-----,*$#%#$=>>>=*%%@+.........+@#,-->>->**@+........................@#$=-;!!_~ac3,$#%@.........@%$-;~(||(c99,*#+..................@*=,-;;;;;--=*%&...............&%**>>,-9cc009,$#&@+........+=_(__ac3,=**&+.................+#=9'__a!'!;;;-;--,-,--;0;3>>%+", +".+#*==**$#%&+......+@&**$**%&.........+&&*$*******%@...............@&*>9cdba9333333,==$#%@.........@%$$$>=*$$%@....................&*==,=>>*#@@@&&%#*$*##&&@+.....@#$=$*$$%%&&&&&####&@+..........@&**$**##%##*#*$**==,>>$$**@..........@&$>9c009=*$%@............#**=*$*%%@@&&%****%%&+............&**$*$$%%@..........................+&%*>,,3933=>$#%@..........+@#=-0adac3->*%@+..................+&%$==,-,,=**#@+...............++&%%#**=,-3,=**%&+..........=0a033,==*%&....................@#=,9,333-,,,=>$$*$*=>,===$*@.", +"..&*#$**%&&+........+@&&@&@+............+@%#****#%@+...............+&#*,99c993,>,===*#&&&@.........@%%*#*$*%@@+....................+&%##$##&@+..++@@&@&&@@+.......+&##*#&&&+@++..+++.++............&%%%&&&@&@@@@&&#*******%&&...........+%#=>33,>=$%&+............&**#*&@@....+@@&&@&@+.............+&###&@@++............................&#**====>**%%%@..........+@&*,90cc3==*%@+....................+@&#*******#&@...................+&&%##$*==**&@...........+%33,,==$#&@.....................+%*=====$=$=*$**#$%##**>*$*&+.", +"..+&%%%#&@+............+.+...............+@&%#%&&@+.................+&**=>>>=$*****##&&&&...........+&&&%#%%+......................+@&%&&&&+..........++@@+.........@&&&&&++.......................@@&@++.......+@%&#**%&&&@+...........+&&&%***$%#&@+............&&&&+........+++..+.................@@@+++..............................@&%#****%%#&@@+............+%*>>=>$**@+......................+@&&%###*%##@+....................+@&&%#%**%%+.............&$$$$**%@+.......................&#***#%%*#*%&%&&@@%&%**%#&@..", +"....+++................................................................++@@++++.+.++......................+.............................+..........................................................................+.+++....................++++.+..........................................................................................+.++++++...................+.+@+++++................................++.............................++++................++....+...........................+++.++.+.++++.+..++++++...."}; diff --git a/hacks/images/molecules/adenine.pdb b/hacks/images/molecules/adenine.pdb new file mode 100644 index 00000000..354056c4 --- /dev/null +++ b/hacks/images/molecules/adenine.pdb @@ -0,0 +1,37 @@ +HEADER Adenine: Vitamin B4; Purine base nucleotide +COMPND jb09aden +AUTHOR Created by Dave Woodcock at Okanagan University College +AUTHOR email:woodcock@okanagan.bc.ca +AUTHOR Date revised: Mon Sep 18 15:35:27 2000 GENERATED BY BABEL 1.6 +HETATM 1 C 1 0.000 0.000 0.000 1.00 0.00 +HETATM 2 C 1 1.394 0.000 0.000 1.00 0.00 +HETATM 3 C 1 2.084 1.211 0.000 1.00 0.00 +HETATM 4 N 1 1.337 2.342 -0.002 1.00 0.00 +HETATM 5 C 1 -0.017 2.313 -0.003 1.00 0.00 +HETATM 6 N 1 -0.710 1.149 -0.001 1.00 0.00 +HETATM 7 N 1 -0.391 -1.291 0.006 1.00 0.00 +HETATM 8 C 1 0.731 -2.049 0.010 1.00 0.00 +HETATM 9 N 1 1.843 -1.276 0.007 1.00 0.00 +HETATM 10 N 1 3.485 1.257 0.004 1.00 0.00 +HETATM 11 H 1 -0.567 3.254 -0.004 1.00 0.00 +HETATM 12 H 1 -1.347 -1.630 0.010 1.00 0.00 +HETATM 13 H 1 0.738 -3.139 0.017 1.00 0.00 +HETATM 14 H 1 3.799 2.220 -0.037 1.00 0.00 +HETATM 15 H 1 3.839 0.818 0.847 1.00 0.00 +CONECT 1 2 2 6 7 +CONECT 2 1 1 3 9 +CONECT 3 2 4 4 10 +CONECT 4 3 3 5 +CONECT 5 4 6 6 11 +CONECT 6 1 5 5 +CONECT 7 1 8 12 +CONECT 8 7 9 9 13 +CONECT 9 2 8 8 +CONECT 10 3 14 15 +CONECT 11 5 +CONECT 12 7 +CONECT 13 8 +CONECT 14 10 +CONECT 15 10 +MASTER 0 0 0 0 0 0 0 0 15 0 15 0 +END diff --git a/hacks/images/molecules/adrenochrome.pdb b/hacks/images/molecules/adrenochrome.pdb new file mode 100644 index 00000000..c4cbef29 --- /dev/null +++ b/hacks/images/molecules/adrenochrome.pdb @@ -0,0 +1,55 @@ +HEADER Adrenochrome: a nerve cell transmission inhibitor, and hallucinogen +COMPND adrenochrome +AUTHOR Created by Dave Woodcock at Okanagan University College +AUTHOR email:woodcock@okanagan.bc.ca +AUTHOR Date revised: Tue Aug 29 08:56:34 2000 GENERATED BY BABEL 1.6 +HETATM 1 C 1 0.000 0.000 0.000 1.00 0.00 +HETATM 2 C 1 1.400 0.000 0.000 1.00 0.00 +HETATM 3 C 1 2.056 1.235 0.000 1.00 0.00 +HETATM 4 C 1 1.351 2.436 -0.011 1.00 0.00 +HETATM 5 C 1 -0.047 2.437 -0.027 1.00 0.00 +HETATM 6 C 1 -0.714 1.206 -0.013 1.00 0.00 +HETATM 7 O 1 -0.597 -1.046 -0.002 1.00 0.00 +HETATM 8 O 1 -1.918 1.181 -0.023 1.00 0.00 +HETATM 9 N 1 2.243 3.571 -0.065 1.00 0.00 +HETATM 10 C 1 1.825 4.648 0.846 1.00 0.00 +HETATM 11 C 1 3.553 3.011 0.321 1.00 0.00 +HETATM 12 C 1 3.538 1.506 -0.050 1.00 0.00 +HETATM 13 H 1 4.088 0.906 0.675 1.00 0.00 +HETATM 14 O 1 4.023 1.295 -1.381 1.00 0.00 +HETATM 15 H 1 1.962 -0.934 -0.006 1.00 0.00 +HETATM 16 H 1 -0.608 3.370 -0.059 1.00 0.00 +HETATM 17 H 1 1.674 4.250 1.849 1.00 0.00 +HETATM 18 H 1 0.895 5.089 0.489 1.00 0.00 +HETATM 19 H 1 2.596 5.418 0.873 1.00 0.00 +HETATM 20 H 1 3.683 3.101 1.400 1.00 0.00 +HETATM 21 H 1 4.364 3.531 -0.190 1.00 0.00 +HETATM 22 H 1 4.963 1.501 -1.423 1.00 0.00 +CONECT 1 2 6 7 +CONECT 1 7 +CONECT 2 1 3 15 +CONECT 2 3 +CONECT 3 2 4 12 +CONECT 4 3 5 9 +CONECT 4 5 +CONECT 5 4 6 16 +CONECT 6 1 5 8 +CONECT 6 8 +CONECT 7 1 +CONECT 8 6 +CONECT 9 4 10 11 +CONECT 10 9 17 18 19 +CONECT 11 9 12 20 21 +CONECT 12 3 11 13 14 +CONECT 13 12 +CONECT 14 12 22 +CONECT 15 2 +CONECT 16 5 +CONECT 17 10 +CONECT 18 10 +CONECT 19 10 +CONECT 20 11 +CONECT 21 11 +CONECT 22 14 +MASTER 0 0 0 0 0 0 0 0 22 0 22 0 +END diff --git a/hacks/images/molecules/bucky.pdb b/hacks/images/molecules/bucky.pdb new file mode 100644 index 00000000..30f5b1f4 --- /dev/null +++ b/hacks/images/molecules/bucky.pdb @@ -0,0 +1,156 @@ +HEADER Buckminsterfullerine: Bucky Ball +COMPND bucky +AUTHOR +GENERATED BY SYMAPPS 1.0 +ATOM 1 C 0.994 0.523 -3.137 +ATOM 2 C 0.418 -0.689 -3.232 +ATOM 3 C 1.239 -1.587 -2.654 +ATOM 4 C 2.172 0.376 -2.500 +ATOM 5 C 2.323 -0.928 -2.202 +ATOM 6 C 1.297 -2.968 -0.779 +ATOM 7 C 0.727 -2.610 -1.946 +ATOM 8 C -0.608 -2.733 -1.813 +ATOM 9 C -0.863 -3.172 -0.565 +ATOM 10 C 0.315 -3.321 0.074 +ATOM 11 C -1.429 -1.836 -2.393 +ATOM 12 C -0.916 -0.814 -3.106 +ATOM 13 C -1.675 0.277 -2.878 +ATOM 14 C -2.657 -0.070 -2.024 +ATOM 15 C -2.506 -1.376 -1.724 +ATOM 16 C -1.096 1.488 -2.779 +ATOM 17 C 0.239 1.614 -2.915 +ATOM 18 C 0.658 2.557 -2.049 +ATOM 19 C -0.417 3.018 -1.381 +ATOM 20 C -1.503 2.359 -1.834 +ATOM 21 C 1.833 2.405 -1.409 +ATOM 22 C 2.596 1.319 -1.640 +ATOM 23 C 3.167 0.957 -0.474 +ATOM 24 C 2.760 1.823 0.475 +ATOM 25 C 1.935 2.717 -0.104 +ATOM 26 C 3.314 -0.348 -0.175 +ATOM 27 C 2.899 -1.293 -1.041 +ATOM 28 C 2.384 -2.314 -0.328 +ATOM 29 C 2.486 -2.003 0.979 +ATOM 30 C 3.063 -0.788 1.074 +ATOM 31 C -2.321 0.938 2.198 +ATOM 32 C -1.237 1.597 2.651 +ATOM 33 C -0.417 0.699 3.231 +ATOM 34 C -2.170 -0.366 2.497 +ATOM 35 C -0.993 -0.514 3.135 +ATOM 36 C 1.671 -0.268 2.871 +ATOM 37 C 0.916 0.824 3.104 +ATOM 38 C 1.430 1.846 2.390 +ATOM 39 C 2.506 1.386 1.722 +ATOM 40 C 2.653 0.079 2.018 +ATOM 41 C 0.609 2.745 1.813 +ATOM 42 C -0.727 2.622 1.945 +ATOM 43 C -1.298 2.984 0.779 +ATOM 44 C -0.315 3.332 -0.075 +ATOM 45 C 0.863 3.183 0.564 +ATOM 46 C -2.378 2.321 0.325 +ATOM 47 C -2.896 1.302 1.038 +ATOM 48 C -3.315 0.358 0.172 +ATOM 49 C -3.062 0.797 -1.076 +ATOM 50 C -2.485 2.012 -0.982 +ATOM 51 C -3.159 -0.945 0.470 +ATOM 52 C -2.593 -1.310 1.637 +ATOM 53 C -1.837 -2.402 1.409 +ATOM 54 C -1.939 -2.714 0.103 +ATOM 55 C -2.759 -1.815 -0.477 +ATOM 56 C -0.658 -2.546 2.045 +ATOM 57 C -0.238 -1.605 2.914 +ATOM 58 C 1.097 -1.482 2.780 +ATOM 59 C 1.503 -2.349 1.832 +ATOM 60 C 0.418 -3.010 1.379 +CONECT 21 25 +CONECT 26 27 +CONECT 2 3 +CONECT 1 4 +CONECT 7 8 +CONECT 8 9 +CONECT 9 10 +CONECT 27 28 +CONECT 28 29 +CONECT 29 30 +CONECT 26 30 +CONECT 6 10 +CONECT 11 12 +CONECT 3 7 +CONECT 8 11 +CONECT 3 5 +CONECT 1 17 +CONECT 5 27 +CONECT 12 13 +CONECT 13 14 +CONECT 14 15 +CONECT 11 15 +CONECT 16 17 +CONECT 6 28 +CONECT 4 5 +CONECT 18 21 +CONECT 1 2 +CONECT 4 22 +CONECT 17 18 +CONECT 18 19 +CONECT 19 20 +CONECT 16 20 +CONECT 21 22 +CONECT 23 26 +CONECT 6 7 +CONECT 2 12 +CONECT 13 16 +CONECT 22 23 +CONECT 23 24 +CONECT 24 25 +CONECT 36 40 +CONECT 41 42 +CONECT 33 37 +CONECT 38 41 +CONECT 33 35 +CONECT 31 47 +CONECT 35 57 +CONECT 42 43 +CONECT 43 44 +CONECT 44 45 +CONECT 41 45 +CONECT 46 47 +CONECT 36 58 +CONECT 34 35 +CONECT 48 51 +CONECT 31 32 +CONECT 34 52 +CONECT 47 48 +CONECT 48 49 +CONECT 49 50 +CONECT 46 50 +CONECT 51 52 +CONECT 53 56 +CONECT 36 37 +CONECT 32 42 +CONECT 43 46 +CONECT 52 53 +CONECT 53 54 +CONECT 54 55 +CONECT 51 55 +CONECT 56 57 +CONECT 32 33 +CONECT 31 34 +CONECT 37 38 +CONECT 38 39 +CONECT 39 40 +CONECT 57 58 +CONECT 58 59 +CONECT 59 60 +CONECT 56 60 +CONECT 10 60 +CONECT 29 59 +CONECT 30 40 +CONECT 24 39 +CONECT 9 54 +CONECT 15 55 +CONECT 14 49 +CONECT 20 50 +CONECT 19 44 +CONECT 25 45 +MASTER 0 0 0 0 0 0 0 0 60 0 0 0 +END diff --git a/hacks/images/molecules/caffeine.pdb b/hacks/images/molecules/caffeine.pdb new file mode 100644 index 00000000..830e75ec --- /dev/null +++ b/hacks/images/molecules/caffeine.pdb @@ -0,0 +1,54 @@ +HEADER Caffeine: Trimethylxanthine; a cardiac stimulant and diuretic +AUTHOR Created by Dave Woodcock at Okanagan University College +AUTHOR email:woodcock@okanagan.bc.ca +AUTHOR Date revised: Fri Sep 29 14:53:27 2000 GENERATED BY BABEL 1.6 +HETATM 1 C 1 0.000 0.000 0.000 1.00 0.00 +HETATM 2 C 1 1.392 0.000 0.000 1.00 0.00 +HETATM 3 N 1 2.076 1.164 0.000 1.00 0.00 +HETATM 4 C 1 1.373 2.321 -0.003 1.00 0.00 +HETATM 5 O 1 1.978 3.365 -0.017 1.00 0.00 +HETATM 6 N 1 0.017 2.344 0.003 1.00 0.00 +HETATM 7 C 1 -0.710 1.202 0.002 1.00 0.00 +HETATM 8 O 1 -1.915 1.218 -0.006 1.00 0.00 +HETATM 9 N 1 -0.404 -1.287 -0.019 1.00 0.00 +HETATM 10 N 1 1.830 -1.279 -0.020 1.00 0.00 +HETATM 11 C 1 0.715 -2.048 -0.031 1.00 0.00 +HETATM 12 C 1 -1.795 -1.761 -0.044 1.00 0.00 +HETATM 13 C 1 3.546 1.178 -0.016 1.00 0.00 +HETATM 14 C 1 -0.690 3.634 -0.013 1.00 0.00 +HETATM 15 H 1 0.720 -3.138 -0.055 1.00 0.00 +HETATM 16 H 1 -1.813 -2.850 -0.090 1.00 0.00 +HETATM 17 H 1 -2.307 -1.428 0.860 1.00 0.00 +HETATM 18 H 1 -2.302 -1.352 -0.918 1.00 0.00 +HETATM 19 H 1 3.894 1.455 -1.011 1.00 0.00 +HETATM 20 H 1 3.929 0.190 0.239 1.00 0.00 +HETATM 21 H 1 3.911 1.904 0.710 1.00 0.00 +HETATM 22 H 1 -1.557 3.583 0.645 1.00 0.00 +HETATM 23 H 1 -0.027 4.428 0.329 1.00 0.00 +HETATM 24 H 1 -1.020 3.851 -1.029 1.00 0.00 +CONECT 1 2 2 7 9 +CONECT 2 1 1 3 10 +CONECT 3 2 4 13 +CONECT 4 3 5 5 6 +CONECT 5 4 4 +CONECT 6 4 7 14 +CONECT 7 1 6 8 8 +CONECT 8 7 7 +CONECT 9 1 11 12 +CONECT 10 2 11 11 +CONECT 11 9 10 10 15 +CONECT 12 9 16 17 18 +CONECT 13 3 19 20 21 +CONECT 14 6 22 23 24 +CONECT 15 11 +CONECT 16 12 +CONECT 17 12 +CONECT 18 12 +CONECT 19 13 +CONECT 20 13 +CONECT 21 13 +CONECT 22 14 +CONECT 23 14 +CONECT 24 14 +MASTER 0 0 0 0 0 0 0 0 24 0 24 0 +END diff --git a/hacks/images/molecules/capsaicin.pdb b/hacks/images/molecules/capsaicin.pdb new file mode 100644 index 00000000..fb88f09b --- /dev/null +++ b/hacks/images/molecules/capsaicin.pdb @@ -0,0 +1,49 @@ +HEADER Capsaicin: 8-methyl-N-vanillyl-6-nonenamide; Pepper; a mucous membrane irritant +AUTHOR Marvin +REVDAT 1 05-MAY-09 0 +HETATM 1 C UNK 0 3.607 -1.127 0.361 0.00 0.00 C+0 +HETATM 2 C UNK 0 4.334 0.075 0.158 0.00 0.00 C+0 +HETATM 3 C UNK 0 3.650 1.279 -0.101 0.00 0.00 C+0 +HETATM 4 C UNK 0 2.246 1.299 -0.172 0.00 0.00 C+0 +HETATM 5 C UNK 0 1.494 0.118 0.015 0.00 0.00 C+0 +HETATM 6 C UNK 0 2.190 -1.085 0.285 0.00 0.00 C+0 +HETATM 7 O UNK 0 4.263 -2.208 0.588 0.00 0.00 O+0 +HETATM 8 O UNK 0 5.598 0.109 0.186 0.00 0.00 O+0 +HETATM 9 C UNK 0 3.863 -3.458 0.839 0.00 0.00 C+0 +HETATM 10 C UNK 0 0.011 0.136 -0.126 0.00 0.00 C+0 +HETATM 11 N UNK 0 -0.660 -0.367 0.987 0.00 0.00 N+0 +HETATM 12 C UNK 0 -2.024 -0.105 1.237 0.00 0.00 C+0 +HETATM 13 C UNK 0 -2.604 -0.886 2.327 0.00 0.00 C+0 +HETATM 14 O UNK 0 -2.896 0.656 0.691 0.00 0.00 O+0 +HETATM 15 C UNK 0 -3.159 -0.033 3.504 0.00 0.00 C+0 +HETATM 16 C UNK 0 -3.849 -0.911 4.584 0.00 0.00 C+0 +HETATM 17 C UNK 0 -4.419 -0.081 5.764 0.00 0.00 C+0 +HETATM 18 C UNK 0 -5.132 -0.923 6.711 0.00 0.00 C+0 +HETATM 19 C UNK 0 -4.516 -1.628 7.675 0.00 0.00 C+0 +HETATM 20 C UNK 0 -5.206 -2.525 8.600 0.00 0.00 C+0 +HETATM 21 C UNK 0 -4.662 -3.972 8.454 0.00 0.00 C+0 +HETATM 22 C UNK 0 -5.081 -2.006 10.057 0.00 0.00 C+0 +CONECT 1 2 6 7 +CONECT 2 1 3 8 +CONECT 3 2 4 +CONECT 4 3 5 +CONECT 5 4 6 10 +CONECT 6 5 1 +CONECT 7 1 9 +CONECT 8 2 +CONECT 9 7 +CONECT 10 5 11 +CONECT 11 10 12 +CONECT 12 11 13 14 +CONECT 13 12 15 +CONECT 14 12 +CONECT 15 13 16 +CONECT 16 15 17 +CONECT 17 16 18 +CONECT 18 17 19 +CONECT 19 18 20 +CONECT 20 19 21 22 +CONECT 21 20 +CONECT 22 20 +MASTER 0 0 0 0 0 0 0 0 22 0 44 0 +END diff --git a/hacks/images/molecules/chlordecone.pdb b/hacks/images/molecules/chlordecone.pdb new file mode 100644 index 00000000..c49e754a --- /dev/null +++ b/hacks/images/molecules/chlordecone.pdb @@ -0,0 +1,49 @@ +HEADER Chlordecone: Kepone, an insecticide and fungicide +COMPND al1113 +AUTHOR Created by Dave Woodcock at Okanagan University College +AUTHOR email:woodcock@okanagan.bc.ca +AUTHOR Date revised: Tue Aug 29 17:54:52 2000 GENERATED BY BABEL 1.6 +HETATM 1 C 1 0.000 0.000 0.000 1.00 0.00 +HETATM 2 O 1 1.206 0.000 0.000 1.00 0.00 +HETATM 3 C 1 -0.741 1.303 0.000 1.00 0.00 +HETATM 4 C 1 -0.875 1.738 -1.482 1.00 0.00 +HETATM 5 C 1 -0.879 0.377 -2.249 1.00 0.00 +HETATM 6 C 1 -0.745 -0.666 -1.117 1.00 0.00 +HETATM 7 C 1 -2.247 0.958 -0.112 1.00 0.00 +HETATM 8 C 1 -2.380 1.999 -1.247 1.00 0.00 +HETATM 9 C 1 -2.237 -0.385 -0.887 1.00 0.00 +HETATM 10 C 1 -2.379 0.045 -2.350 1.00 0.00 +HETATM 11 C 1 -3.162 1.358 -2.394 1.00 0.00 +HETATM 12 Cl 1 0.142 3.061 -2.080 1.00 0.00 +HETATM 13 Cl 1 -0.299 2.574 1.159 1.00 0.00 +HETATM 14 Cl 1 -2.803 3.653 -0.734 1.00 0.00 +HETATM 15 Cl 1 -3.272 1.132 1.330 1.00 0.00 +HETATM 16 Cl 1 -3.275 -1.723 -0.285 1.00 0.00 +HETATM 17 Cl 1 -4.883 1.128 -1.986 1.00 0.00 +HETATM 18 Cl 1 -2.936 2.229 -3.931 1.00 0.00 +HETATM 19 Cl 1 -2.805 -1.246 -3.509 1.00 0.00 +HETATM 20 Cl 1 0.141 0.211 -3.696 1.00 0.00 +HETATM 21 Cl 1 -0.301 -2.317 -1.612 1.00 0.00 +CONECT 1 2 2 3 6 +CONECT 2 1 1 +CONECT 3 1 4 7 13 +CONECT 4 3 5 8 12 +CONECT 5 4 6 10 20 +CONECT 6 1 5 9 21 +CONECT 7 3 8 9 15 +CONECT 8 4 7 11 14 +CONECT 9 6 7 10 16 +CONECT 10 5 9 11 19 +CONECT 11 8 10 17 18 +CONECT 12 4 +CONECT 13 3 +CONECT 14 8 +CONECT 15 7 +CONECT 16 9 +CONECT 17 11 +CONECT 18 11 +CONECT 19 10 +CONECT 20 5 +CONECT 21 6 +MASTER 0 0 0 0 0 0 0 0 21 0 21 0 +END diff --git a/hacks/images/molecules/cocaine.pdb b/hacks/images/molecules/cocaine.pdb new file mode 100644 index 00000000..30c826f7 --- /dev/null +++ b/hacks/images/molecules/cocaine.pdb @@ -0,0 +1,93 @@ +HEADER Cocaine: Carboxylicacid methyl ester, an anesthetic +COMPND al3078 +AUTHOR Created by Dave Woodcock at Okanagan University College +AUTHOR email:woodcock@okanagan.bc.ca +AUTHOR Date revised: Wed Aug 30 12:33:12 2000 GENERATED BY BABEL 1.6 +HETATM 1 C 1 0.000 0.000 0.000 1.00 0.00 +HETATM 2 C 1 1.399 0.000 0.000 1.00 0.00 +HETATM 3 C 1 2.099 1.211 0.000 1.00 0.00 +HETATM 4 C 1 1.400 2.423 -0.002 1.00 0.00 +HETATM 5 C 1 0.001 2.423 -0.007 1.00 0.00 +HETATM 6 C 1 -0.700 1.213 -0.005 1.00 0.00 +HETATM 7 C 1 -2.156 1.218 -0.022 1.00 0.00 +HETATM 8 O 1 -2.759 0.175 -0.044 1.00 0.00 +HETATM 9 O 1 -2.806 2.379 -0.075 1.00 0.00 +HETATM 10 C 1 -4.168 2.239 0.272 1.00 0.00 +HETATM 11 C 1 -4.872 3.590 0.031 1.00 0.00 +HETATM 12 C 1 -4.061 4.678 0.674 1.00 0.00 +HETATM 13 O 1 -4.560 5.346 1.542 1.00 0.00 +HETATM 14 O 1 -2.741 4.690 0.497 1.00 0.00 +HETATM 15 C 1 -2.091 5.352 1.560 1.00 0.00 +HETATM 16 C 1 -6.281 3.587 0.659 1.00 0.00 +HETATM 17 N 1 -6.101 3.424 2.109 1.00 0.00 +HETATM 18 C 1 -7.084 2.348 0.212 1.00 0.00 +HETATM 19 C 1 -6.737 1.277 1.267 1.00 0.00 +HETATM 20 C 1 -5.765 1.998 2.226 1.00 0.00 +HETATM 21 C 1 -4.304 1.831 1.755 1.00 0.00 +HETATM 22 C 1 -7.322 3.768 2.857 1.00 0.00 +HETATM 23 H 1 -0.544 -0.944 -0.002 1.00 0.00 +HETATM 24 H 1 1.944 -0.944 0.000 1.00 0.00 +HETATM 25 H 1 3.189 1.211 0.001 1.00 0.00 +HETATM 26 H 1 1.945 3.367 -0.004 1.00 0.00 +HETATM 27 H 1 -0.544 3.368 -0.019 1.00 0.00 +HETATM 28 H 1 -4.624 1.481 -0.363 1.00 0.00 +HETATM 29 H 1 -4.942 3.777 -1.041 1.00 0.00 +HETATM 30 H 1 -2.425 6.389 1.609 1.00 0.00 +HETATM 31 H 1 -2.320 4.851 2.501 1.00 0.00 +HETATM 32 H 1 -1.014 5.330 1.395 1.00 0.00 +HETATM 33 H 1 -6.802 4.513 0.416 1.00 0.00 +HETATM 34 H 1 -6.806 2.035 -0.795 1.00 0.00 +HETATM 35 H 1 -8.152 2.564 0.250 1.00 0.00 +HETATM 36 H 1 -6.275 0.397 0.819 1.00 0.00 +HETATM 37 H 1 -7.641 0.988 1.803 1.00 0.00 +HETATM 38 H 1 -5.872 1.638 3.249 1.00 0.00 +HETATM 39 H 1 -3.995 0.793 1.881 1.00 0.00 +HETATM 40 H 1 -3.664 2.470 2.364 1.00 0.00 +HETATM 41 H 1 -8.166 3.167 2.523 1.00 0.00 +HETATM 42 H 1 -7.551 4.823 2.706 1.00 0.00 +HETATM 43 H 1 -7.155 3.591 3.920 1.00 0.00 +CONECT 1 2 2 6 23 +CONECT 2 1 1 3 24 +CONECT 3 2 4 4 25 +CONECT 4 3 3 5 26 +CONECT 5 4 6 6 27 +CONECT 6 1 5 5 7 +CONECT 7 6 8 8 9 +CONECT 8 7 7 +CONECT 9 7 10 +CONECT 10 9 11 21 28 +CONECT 11 10 12 16 29 +CONECT 12 11 13 13 14 +CONECT 13 12 12 +CONECT 14 12 15 +CONECT 15 14 30 31 32 +CONECT 16 11 17 18 33 +CONECT 17 16 20 22 +CONECT 18 16 19 34 35 +CONECT 19 18 20 36 37 +CONECT 20 17 19 21 38 +CONECT 21 10 20 39 40 +CONECT 22 17 41 42 43 +CONECT 23 1 +CONECT 24 2 +CONECT 25 3 +CONECT 26 4 +CONECT 27 5 +CONECT 28 10 +CONECT 29 11 +CONECT 30 15 +CONECT 31 15 +CONECT 32 15 +CONECT 33 16 +CONECT 34 18 +CONECT 35 18 +CONECT 36 19 +CONECT 37 19 +CONECT 38 20 +CONECT 39 21 +CONECT 40 21 +CONECT 41 22 +CONECT 42 22 +CONECT 43 22 +MASTER 0 0 0 0 0 0 0 0 43 0 43 0 +END diff --git a/hacks/images/molecules/codeine.pdb b/hacks/images/molecules/codeine.pdb new file mode 100644 index 00000000..36a79fa8 --- /dev/null +++ b/hacks/images/molecules/codeine.pdb @@ -0,0 +1,93 @@ +HEADER Methylmorphine: Codeine, a cough reflex inhibitor +COMPND al3083 +AUTHOR Created by Dave Woodcock at Okanagan University College +AUTHOR email:woodcock@okanagan.bc.ca +AUTHOR Date revised: Wed Aug 30 12:33:12 2000 GENERATED BY BABEL 1.6 +HETATM 1 C 1 0.000 0.000 0.000 1.00 0.00 +HETATM 2 C 1 1.400 0.000 0.000 1.00 0.00 +HETATM 3 C 1 2.107 1.211 0.000 1.00 0.00 +HETATM 4 C 1 1.445 2.445 -0.038 1.00 0.00 +HETATM 5 C 1 0.048 2.457 0.012 1.00 0.00 +HETATM 6 C 1 -0.629 1.242 0.047 1.00 0.00 +HETATM 7 C 1 -2.076 1.497 -0.256 1.00 0.00 +HETATM 8 C 1 -2.718 0.335 -1.023 1.00 0.00 +HETATM 9 C 1 -2.362 -0.955 -0.251 1.00 0.00 +HETATM 10 C 1 -0.830 -1.234 -0.281 1.00 0.00 +HETATM 11 C 1 -1.864 2.827 -1.015 1.00 0.00 +HETATM 12 C 1 -2.785 1.642 1.099 1.00 0.00 +HETATM 13 C 1 -2.549 0.335 1.888 1.00 0.00 +HETATM 14 N 1 -2.944 -0.846 1.100 1.00 0.00 +HETATM 15 C 1 -2.815 -2.080 1.892 1.00 0.00 +HETATM 16 H 1 -3.800 0.464 -1.011 1.00 0.00 +HETATM 17 C 1 -2.286 0.268 -2.470 1.00 0.00 +HETATM 18 C 1 -2.002 1.392 -3.142 1.00 0.00 +HETATM 19 C 1 -1.354 2.572 -2.453 1.00 0.00 +HETATM 20 H 1 -2.774 3.428 -1.022 1.00 0.00 +HETATM 21 O 1 -0.789 3.474 -0.352 1.00 0.00 +HETATM 22 H 1 -1.514 3.472 -3.047 1.00 0.00 +HETATM 23 O 1 0.051 2.305 -2.404 1.00 0.00 +HETATM 24 O 1 2.148 3.606 -0.170 1.00 0.00 +HETATM 25 H 1 1.942 -0.944 -0.064 1.00 0.00 +HETATM 26 H 1 3.196 1.191 -0.044 1.00 0.00 +HETATM 27 H 1 -2.856 -1.789 -0.750 1.00 0.00 +HETATM 28 H 1 -0.570 -1.581 -1.281 1.00 0.00 +HETATM 29 H 1 -0.575 -2.018 0.429 1.00 0.00 +HETATM 30 H 1 -3.852 1.800 0.945 1.00 0.00 +HETATM 31 H 1 -2.368 2.484 1.653 1.00 0.00 +HETATM 32 H 1 -3.143 0.370 2.801 1.00 0.00 +HETATM 33 H 1 -1.498 0.252 2.165 1.00 0.00 +HETATM 34 H 1 -3.495 -2.034 2.743 1.00 0.00 +HETATM 35 H 1 -1.796 -2.189 2.261 1.00 0.00 +HETATM 36 H 1 -3.075 -2.943 1.279 1.00 0.00 +HETATM 37 H 1 -2.526 -0.630 -3.039 1.00 0.00 +HETATM 38 H 1 -1.938 1.338 -4.229 1.00 0.00 +HETATM 39 H 1 0.396 2.184 -3.295 1.00 0.00 +HETATM 40 C 1 2.068 4.090 -1.493 1.00 0.00 +HETATM 41 H 1 2.413 3.325 -2.189 1.00 0.00 +HETATM 42 H 1 1.038 4.360 -1.728 1.00 0.00 +HETATM 43 H 1 2.699 4.974 -1.590 1.00 0.00 +CONECT 1 2 2 6 10 +CONECT 2 1 1 3 25 +CONECT 3 2 4 4 26 +CONECT 4 3 3 5 24 +CONECT 5 4 6 6 21 +CONECT 6 1 5 5 7 +CONECT 7 6 8 11 12 +CONECT 8 7 9 16 17 +CONECT 9 8 10 14 27 +CONECT 10 1 9 28 29 +CONECT 11 7 19 20 21 +CONECT 12 7 13 30 31 +CONECT 13 12 14 32 33 +CONECT 14 9 13 15 +CONECT 15 14 34 35 36 +CONECT 16 8 +CONECT 17 8 18 18 37 +CONECT 18 17 17 19 38 +CONECT 19 11 18 22 23 +CONECT 20 11 +CONECT 21 5 11 +CONECT 22 19 +CONECT 23 19 39 +CONECT 24 4 40 +CONECT 25 2 +CONECT 26 3 +CONECT 27 9 +CONECT 28 10 +CONECT 29 10 +CONECT 30 12 +CONECT 31 12 +CONECT 32 13 +CONECT 33 13 +CONECT 34 15 +CONECT 35 15 +CONECT 36 15 +CONECT 37 17 +CONECT 38 18 +CONECT 39 23 +CONECT 40 24 41 42 43 +CONECT 41 40 +CONECT 42 40 +CONECT 43 40 +MASTER 0 0 0 0 0 0 0 0 43 0 43 0 +END diff --git a/hacks/images/molecules/cyclohexane.pdb b/hacks/images/molecules/cyclohexane.pdb new file mode 100644 index 00000000..db7b5f0f --- /dev/null +++ b/hacks/images/molecules/cyclohexane.pdb @@ -0,0 +1,151 @@ +HEADER Cyclohexane: 1,2,3,4,5,6-hexaisopropylcyclohexane +COMPND al3063 +AUTHOR Created by Dave Woodcock at Okanagan University College +AUTHOR email:woodcock@okanagan.bc.ca +AUTHOR Date revised: Sun Sep 3 10:20:00 2000 GENERATED BY BABEL 1.6 +HETATM 1 C 1 0.000 0.000 0.000 1.00 0.00 +HETATM 2 C 1 1.565 0.000 0.000 1.00 0.00 +HETATM 3 C 1 2.185 1.436 0.000 1.00 0.00 +HETATM 4 C 1 1.565 2.409 1.058 1.00 0.00 +HETATM 5 C 1 0.011 2.333 1.199 1.00 0.00 +HETATM 6 C 1 -0.636 0.914 1.102 1.00 0.00 +HETATM 7 C 1 2.238 -0.920 1.062 1.00 0.00 +HETATM 8 C 1 3.676 -1.279 0.632 1.00 0.00 +HETATM 9 C 1 1.540 -2.282 1.218 1.00 0.00 +HETATM 10 C 1 2.217 2.309 2.471 1.00 0.00 +HETATM 11 C 1 1.987 3.605 3.278 1.00 0.00 +HETATM 12 C 1 3.745 2.126 2.455 1.00 0.00 +HETATM 13 C 1 -0.726 0.166 2.473 1.00 0.00 +HETATM 14 C 1 -1.806 -0.942 2.413 1.00 0.00 +HETATM 15 C 1 -1.162 1.048 3.662 1.00 0.00 +HETATM 16 C 1 -0.814 3.472 0.513 1.00 0.00 +HETATM 17 C 1 -0.477 3.821 -0.947 1.00 0.00 +HETATM 18 C 1 -0.663 4.782 1.320 1.00 0.00 +HETATM 19 C 1 -0.573 0.185 -1.439 1.00 0.00 +HETATM 20 C 1 -2.077 0.514 -1.474 1.00 0.00 +HETATM 21 C 1 -0.420 -1.124 -2.240 1.00 0.00 +HETATM 22 C 1 2.365 2.070 -1.423 1.00 0.00 +HETATM 23 C 1 3.380 3.248 -1.378 1.00 0.00 +HETATM 24 C 1 2.947 1.067 -2.454 1.00 0.00 +HETATM 25 H 1 -0.308 -1.011 0.219 1.00 0.00 +HETATM 26 H 1 1.866 -0.481 -0.919 1.00 0.00 +HETATM 27 H 1 3.219 1.312 0.276 1.00 0.00 +HETATM 28 H 1 1.800 3.418 0.741 1.00 0.00 +HETATM 29 H 1 -0.171 2.602 2.221 1.00 0.00 +HETATM 30 H 1 -1.683 1.071 0.864 1.00 0.00 +HETATM 31 H 1 2.274 -0.432 2.031 1.00 0.00 +HETATM 32 H 1 4.296 -0.395 0.523 1.00 0.00 +HETATM 33 H 1 3.659 -1.819 -0.314 1.00 0.00 +HETATM 34 H 1 4.129 -1.913 1.395 1.00 0.00 +HETATM 35 H 1 1.366 -2.731 0.241 1.00 0.00 +HETATM 36 H 1 0.598 -2.162 1.743 1.00 0.00 +HETATM 37 H 1 2.167 -2.946 1.814 1.00 0.00 +HETATM 38 H 1 1.784 1.476 3.021 1.00 0.00 +HETATM 39 H 1 0.931 3.795 3.446 1.00 0.00 +HETATM 40 H 1 2.426 4.454 2.754 1.00 0.00 +HETATM 41 H 1 2.462 3.505 4.254 1.00 0.00 +HETATM 42 H 1 4.206 2.819 1.750 1.00 0.00 +HETATM 43 H 1 3.992 1.100 2.194 1.00 0.00 +HETATM 44 H 1 4.144 2.311 3.452 1.00 0.00 +HETATM 45 H 1 0.232 -0.273 2.732 1.00 0.00 +HETATM 46 H 1 -1.609 -1.663 1.627 1.00 0.00 +HETATM 47 H 1 -2.784 -0.492 2.238 1.00 0.00 +HETATM 48 H 1 -1.828 -1.479 3.361 1.00 0.00 +HETATM 49 H 1 -1.986 1.697 3.365 1.00 0.00 +HETATM 50 H 1 -0.323 1.642 4.019 1.00 0.00 +HETATM 51 H 1 -1.487 0.415 4.488 1.00 0.00 +HETATM 52 H 1 -1.870 3.206 0.555 1.00 0.00 +HETATM 53 H 1 -0.618 2.957 -1.586 1.00 0.00 +HETATM 54 H 1 0.544 4.192 -1.014 1.00 0.00 +HETATM 55 H 1 -1.151 4.606 -1.289 1.00 0.00 +HETATM 56 H 1 0.380 5.094 1.338 1.00 0.00 +HETATM 57 H 1 -1.015 4.632 2.341 1.00 0.00 +HETATM 58 H 1 -1.262 5.567 0.860 1.00 0.00 +HETATM 59 H 1 -0.035 0.957 -1.972 1.00 0.00 +HETATM 60 H 1 -2.246 1.523 -1.106 1.00 0.00 +HETATM 61 H 1 -2.630 -0.201 -0.864 1.00 0.00 +HETATM 62 H 1 -2.439 0.465 -2.501 1.00 0.00 +HETATM 63 H 1 -0.991 -1.924 -1.768 1.00 0.00 +HETATM 64 H 1 0.625 -1.418 -2.300 1.00 0.00 +HETATM 65 H 1 -0.791 -0.971 -3.254 1.00 0.00 +HETATM 66 H 1 1.430 2.438 -1.818 1.00 0.00 +HETATM 67 H 1 4.327 2.902 -0.962 1.00 0.00 +HETATM 68 H 1 3.011 4.079 -0.782 1.00 0.00 +HETATM 69 H 1 3.557 3.619 -2.388 1.00 0.00 +HETATM 70 H 1 2.183 0.367 -2.790 1.00 0.00 +HETATM 71 H 1 3.780 0.521 -2.010 1.00 0.00 +HETATM 72 H 1 3.306 1.606 -3.330 1.00 0.00 +CONECT 1 2 6 19 25 +CONECT 2 1 3 7 26 +CONECT 3 2 4 22 27 +CONECT 4 3 5 10 28 +CONECT 5 4 6 16 29 +CONECT 6 1 5 13 30 +CONECT 7 2 8 9 31 +CONECT 8 7 32 33 34 +CONECT 9 7 35 36 37 +CONECT 10 4 11 12 38 +CONECT 11 10 39 40 41 +CONECT 12 10 42 43 44 +CONECT 13 6 14 15 45 +CONECT 14 13 46 47 48 +CONECT 15 13 49 50 51 +CONECT 16 5 17 18 52 +CONECT 17 16 53 54 55 +CONECT 18 16 56 57 58 +CONECT 19 1 20 21 59 +CONECT 20 19 60 61 62 +CONECT 21 19 63 64 65 +CONECT 22 3 23 24 66 +CONECT 23 22 67 68 69 +CONECT 24 22 70 71 72 +CONECT 25 1 +CONECT 26 2 +CONECT 27 3 +CONECT 28 4 +CONECT 29 5 +CONECT 30 6 +CONECT 31 7 +CONECT 32 8 +CONECT 33 8 +CONECT 34 8 +CONECT 35 9 +CONECT 36 9 +CONECT 37 9 +CONECT 38 10 +CONECT 39 11 +CONECT 40 11 +CONECT 41 11 +CONECT 42 12 +CONECT 43 12 +CONECT 44 12 +CONECT 45 13 +CONECT 46 14 +CONECT 47 14 +CONECT 48 14 +CONECT 49 15 +CONECT 50 15 +CONECT 51 15 +CONECT 52 16 +CONECT 53 17 +CONECT 54 17 +CONECT 55 17 +CONECT 56 18 +CONECT 57 18 +CONECT 58 18 +CONECT 59 19 +CONECT 60 20 +CONECT 61 20 +CONECT 62 20 +CONECT 63 21 +CONECT 64 21 +CONECT 65 21 +CONECT 66 22 +CONECT 67 23 +CONECT 68 23 +CONECT 69 23 +CONECT 70 24 +CONECT 71 24 +CONECT 72 24 +MASTER 0 0 0 0 0 0 0 0 72 0 72 0 +END diff --git a/hacks/images/molecules/cytosine.pdb b/hacks/images/molecules/cytosine.pdb new file mode 100644 index 00000000..e7031790 --- /dev/null +++ b/hacks/images/molecules/cytosine.pdb @@ -0,0 +1,33 @@ +HEADER Cytosine: Pyrimidine base nucleotide +COMPND jb09cyto +AUTHOR Created by Dave Woodcock at Okanagan University College +AUTHOR email:woodcock@okanagan.bc.ca +AUTHOR Date revised: Fri Sep 29 12:35:29 2000 GENERATED BY BABEL 1.6 +HETATM 1 C 1 0.000 0.000 0.000 1.00 0.00 +HETATM 2 C 1 1.398 0.000 0.000 1.00 0.00 +HETATM 3 C 1 2.070 1.227 0.000 1.00 0.00 +HETATM 4 N 1 1.356 2.375 0.001 1.00 0.00 +HETATM 5 C 1 0.004 2.350 0.002 1.00 0.00 +HETATM 6 N 1 -0.667 1.176 0.001 1.00 0.00 +HETATM 7 O 1 -0.611 3.389 0.004 1.00 0.00 +HETATM 8 N 1 3.477 1.271 0.003 1.00 0.00 +HETATM 9 H 1 -0.548 -0.942 0.000 1.00 0.00 +HETATM 10 H 1 1.954 -0.938 0.001 1.00 0.00 +HETATM 11 H 1 -1.681 1.178 0.002 1.00 0.00 +HETATM 12 H 1 3.791 2.109 0.480 1.00 0.00 +HETATM 13 H 1 3.844 0.453 0.477 1.00 0.00 +CONECT 1 2 2 6 9 +CONECT 2 1 1 3 10 +CONECT 3 2 4 4 8 +CONECT 4 3 3 5 +CONECT 5 4 6 7 7 +CONECT 6 1 5 11 +CONECT 7 5 5 +CONECT 8 3 12 13 +CONECT 9 1 +CONECT 10 2 +CONECT 11 6 +CONECT 12 8 +CONECT 13 8 +MASTER 0 0 0 0 0 0 0 0 13 0 13 0 +END diff --git a/hacks/images/molecules/dna.pdb b/hacks/images/molecules/dna.pdb new file mode 100644 index 00000000..a0606710 --- /dev/null +++ b/hacks/images/molecules/dna.pdb @@ -0,0 +1,972 @@ +HEADER DNA: Deoxyribonucleic acid +ATOM 1 O ??? 1 4.674 19.391 -10.106 +ATOM 2 C ??? 1 4.459 17.981 -9.876 +ATOM 3 C ??? 1 5.288 17.571 -8.673 +ATOM 4 O ??? 1 4.895 17.956 -7.317 +ATOM 5 C ??? 1 5.700 16.166 -8.515 +ATOM 6 O ??? 1 6.993 16.174 -7.868 +ATOM 7 C ??? 1 4.606 15.591 -7.605 +ATOM 8 C ??? 1 4.489 16.741 -6.607 +ATOM 9 N ??? 1 3.143 16.925 -5.903 +ATOM 10 C ??? 1 3.127 17.319 -4.578 +ATOM 11 O ??? 1 4.173 17.497 -3.993 +ATOM 12 N ??? 1 1.955 17.554 -3.958 +ATOM 13 C ??? 1 0.773 17.466 -4.621 +ATOM 14 N ??? 1 -0.393 17.691 -3.955 +ATOM 15 C ??? 1 0.722 17.134 -5.985 +ATOM 16 C ??? 1 1.945 16.843 -6.625 +ATOM 17 P ??? 1 7.833 14.873 -7.879 +ATOM 18 O ??? 1 6.913 13.703 -8.299 +ATOM 19 O ??? 1 9.116 15.075 -8.639 +ATOM 20 O ??? 1 8.137 14.505 -6.390 +ATOM 21 C ??? 1 9.093 15.196 -5.586 +ATOM 22 C ??? 1 8.913 14.574 -4.231 +ATOM 23 O ??? 1 7.518 14.735 -3.865 +ATOM 24 C ??? 1 9.081 13.086 -4.262 +ATOM 25 O ??? 1 10.078 12.703 -3.397 +ATOM 26 C ??? 1 7.686 12.473 -4.029 +ATOM 27 C ??? 1 7.063 13.543 -3.201 +ATOM 28 N ??? 1 5.563 13.566 -3.134 +ATOM 29 C ??? 1 4.657 13.394 -4.141 +ATOM 30 N ??? 1 3.380 13.664 -3.752 +ATOM 31 C ??? 1 3.485 14.024 -2.465 +ATOM 32 C ??? 1 2.474 14.525 -1.574 +ATOM 33 O ??? 1 1.309 14.806 -1.867 +ATOM 34 N ??? 1 2.958 14.808 -0.289 +ATOM 35 C ??? 1 4.279 14.700 0.121 +ATOM 36 N ??? 1 4.596 14.961 1.424 +ATOM 37 N ??? 1 5.242 14.292 -0.749 +ATOM 38 C ??? 1 4.801 13.971 -2.035 +ATOM 39 P ??? 1 10.462 11.185 -3.172 +ATOM 40 O ??? 1 9.914 10.272 -4.247 +ATOM 41 O ??? 1 11.949 11.216 -2.975 +ATOM 42 O ??? 1 9.792 10.862 -1.765 +ATOM 43 C ??? 1 10.265 11.478 -0.528 +ATOM 44 C ??? 1 9.204 11.248 0.526 +ATOM 45 O ??? 1 7.918 11.627 0.016 +ATOM 46 C ??? 1 9.052 9.838 1.036 +ATOM 47 O ??? 1 9.614 9.642 2.306 +ATOM 48 C ??? 1 7.597 9.524 0.982 +ATOM 49 C ??? 1 6.965 10.887 0.744 +ATOM 50 N ??? 1 5.832 10.810 -0.183 +ATOM 51 C ??? 1 4.534 11.009 0.257 +ATOM 52 O ??? 1 4.306 11.269 1.440 +ATOM 53 N ??? 1 3.534 10.905 -0.642 +ATOM 54 C ??? 1 3.770 10.552 -1.926 +ATOM 55 N ??? 1 2.773 10.591 -2.855 +ATOM 56 C ??? 1 5.043 10.250 -2.374 +ATOM 57 C ??? 1 6.091 10.396 -1.479 +ATOM 58 P ??? 1 9.660 8.226 2.989 +ATOM 59 O ??? 1 9.518 7.127 1.928 +ATOM 60 O ??? 1 10.794 8.089 3.999 +ATOM 61 O ??? 1 8.355 8.291 3.834 +ATOM 62 C ??? 1 8.139 9.269 4.865 +ATOM 63 C ??? 1 6.937 8.745 5.644 +ATOM 64 O ??? 1 5.814 8.819 4.753 +ATOM 65 C ??? 1 6.948 7.295 6.225 +ATOM 66 O ??? 1 6.417 7.199 7.512 +ATOM 67 C ??? 1 6.148 6.464 5.250 +ATOM 68 C ??? 1 5.222 7.503 4.599 +ATOM 69 N ??? 1 4.918 7.267 3.140 +ATOM 70 C ??? 1 5.599 6.623 2.107 +ATOM 71 N ??? 1 4.919 6.594 0.951 +ATOM 72 C ??? 1 3.772 7.259 1.254 +ATOM 73 C ??? 1 2.598 7.558 0.439 +ATOM 74 O ??? 1 2.404 7.232 -0.737 +ATOM 75 N ??? 1 1.575 8.214 1.141 +ATOM 76 C ??? 1 1.613 8.566 2.471 +ATOM 77 N ??? 1 0.502 9.125 3.046 +ATOM 78 N ??? 1 2.702 8.309 3.210 +ATOM 79 C ??? 1 3.753 7.669 2.570 +ATOM 80 P ??? 1 6.301 5.803 8.277 +ATOM 81 O ??? 1 6.480 4.589 7.476 +ATOM 82 O ??? 1 7.156 5.937 9.499 +ATOM 83 O ??? 1 4.740 5.694 8.620 +ATOM 84 C ??? 1 3.911 6.858 8.929 +ATOM 85 C ??? 1 2.515 6.690 8.311 +ATOM 86 O ??? 1 2.653 6.561 6.911 +ATOM 87 C ??? 1 1.684 5.487 8.712 +ATOM 88 O ??? 1 0.539 5.815 9.516 +ATOM 89 C ??? 1 1.353 4.792 7.399 +ATOM 90 C ??? 1 1.556 5.869 6.393 +ATOM 91 N ??? 1 1.967 5.365 5.052 +ATOM 92 C ??? 1 3.193 4.822 4.658 +ATOM 93 N ??? 1 3.258 4.448 3.362 +ATOM 94 C ??? 1 2.043 4.779 2.883 +ATOM 95 C ??? 1 1.417 4.673 1.562 +ATOM 96 N ??? 1 2.034 4.100 0.514 +ATOM 97 N ??? 1 0.156 5.177 1.374 +ATOM 98 C ??? 1 -0.498 5.699 2.441 +ATOM 99 N ??? 1 -0.077 5.807 3.720 +ATOM 100 C ??? 1 1.230 5.336 3.901 +ATOM 101 P ??? 1 -0.488 4.701 10.028 +ATOM 102 O ??? 1 0.013 3.297 10.287 +ATOM 103 O ??? 1 -1.183 5.233 11.229 +ATOM 104 O ??? 1 -1.483 4.559 8.784 +ATOM 105 C ??? 1 -2.385 5.609 8.332 +ATOM 106 C ??? 1 -3.291 4.910 7.309 +ATOM 107 O ??? 1 -2.610 4.636 6.060 +ATOM 108 C ??? 1 -3.923 3.568 7.700 +ATOM 109 O ??? 1 -5.162 3.352 7.126 +ATOM 110 C ??? 1 -2.961 2.582 7.123 +ATOM 111 C ??? 1 -2.754 3.200 5.763 +ATOM 112 N ??? 1 -1.583 2.605 5.066 +ATOM 113 C ??? 1 -0.368 2.242 5.588 +ATOM 114 N ??? 1 0.486 1.776 4.665 +ATOM 115 C ??? 1 -0.189 1.878 3.525 +ATOM 116 C ??? 1 0.183 1.571 2.180 +ATOM 117 N ??? 1 1.377 0.958 1.920 +ATOM 118 N ??? 1 -0.730 1.786 1.174 +ATOM 119 C ??? 1 -1.964 2.218 1.475 +ATOM 120 N ??? 1 -2.439 2.500 2.716 +ATOM 121 C ??? 1 -1.479 2.331 3.718 +ATOM 122 P ??? 1 -5.924 1.982 7.353 +ATOM 123 O ??? 1 -5.172 0.938 8.012 +ATOM 124 O ??? 1 -7.186 2.593 7.897 +ATOM 125 O ??? 1 -6.252 1.347 5.938 +ATOM 126 C ??? 1 -6.944 2.135 4.921 +ATOM 127 C ??? 1 -6.715 1.372 3.651 +ATOM 128 O ??? 1 -5.286 1.133 3.458 +ATOM 129 C ??? 1 -7.407 0.057 3.644 +ATOM 130 O ??? 1 -8.489 0.026 2.771 +ATOM 131 C ??? 1 -6.310 -0.990 3.438 +ATOM 132 C ??? 1 -5.156 -0.150 2.865 +ATOM 133 N ??? 1 -3.757 -0.647 3.037 +ATOM 134 C ??? 1 -2.979 -0.923 1.905 +ATOM 135 O ??? 1 -3.374 -0.727 0.747 +ATOM 136 N ??? 1 -1.687 -1.340 2.116 +ATOM 137 C ??? 1 -1.144 -1.494 3.381 +ATOM 138 O ??? 1 0.074 -1.754 3.445 +ATOM 139 C ??? 1 -1.948 -1.227 4.501 +ATOM 140 C ??? 1 -1.422 -1.319 5.892 +ATOM 141 C ??? 1 -3.248 -0.795 4.314 +ATOM 142 P ??? 1 -9.378 -1.306 2.603 +ATOM 143 O ??? 1 -9.127 -2.221 3.726 +ATOM 145 O ??? 1 -8.753 -2.007 1.349 +ATOM 146 C ??? 1 -8.460 -1.252 0.127 +ATOM 147 C ??? 1 -7.623 -2.192 -0.688 +ATOM 148 O ??? 1 -6.477 -2.562 0.073 +ATOM 149 C ??? 1 -8.255 -3.511 -1.016 +ATOM 150 O ??? 1 -8.724 -3.527 -2.285 +ATOM 151 C ??? 1 -7.224 -4.587 -0.757 +ATOM 152 C ??? 1 -6.004 -3.753 -0.494 +ATOM 153 N ??? 1 -4.890 -4.263 0.346 +ATOM 154 C ??? 1 -3.627 -4.303 -0.238 +ATOM 155 O ??? 1 -3.413 -4.052 -1.439 +ATOM 156 N ??? 1 -2.559 -4.547 0.575 +ATOM 157 C ??? 1 -2.672 -4.694 1.927 +ATOM 158 O ??? 1 -1.603 -4.845 2.510 +ATOM 159 C ??? 1 -3.962 -4.607 2.537 +ATOM 160 C ??? 1 -4.169 -4.666 4.067 +ATOM 161 C ??? 1 -5.072 -4.416 1.690 +ATOM 162 P ??? 1 -9.083 -4.896 -2.982 +ATOM 163 O ??? 1 -9.692 -5.915 -2.114 +ATOM 164 O ??? 1 -9.784 -4.333 -4.195 +ATOM 165 O ??? 1 -7.769 -5.544 -3.501 +ATOM 166 C ??? 1 -6.988 -4.787 -4.548 +ATOM 167 C ??? 1 -5.787 -5.605 -4.680 +ATOM 168 O ??? 1 -5.186 -5.816 -3.381 +ATOM 169 C ??? 1 -6.160 -6.983 -5.172 +ATOM 170 O ??? 1 -5.775 -7.049 -6.554 +ATOM 171 C ??? 1 -5.475 -7.989 -4.170 +ATOM 172 C ??? 1 -4.470 -7.095 -3.471 +ATOM 173 N ??? 1 -4.143 -7.481 -2.064 +ATOM 174 C ??? 1 -2.880 -7.900 -1.674 +ATOM 175 O ??? 1 -1.981 -8.028 -2.497 +ATOM 176 N ??? 1 -2.644 -8.106 -0.357 +ATOM 177 C ??? 1 -3.593 -7.906 0.580 +ATOM 178 N ??? 1 -3.294 -8.029 1.897 +ATOM 179 C ??? 1 -4.887 -7.515 0.234 +ATOM 180 C ??? 1 -5.144 -7.290 -1.118 +ATOM 181 P ??? 1 -6.271 -8.185 -7.504 +ATOM 182 O ??? 1 -7.612 -8.682 -7.077 +ATOM 183 O ??? 1 -6.109 -7.701 -8.887 +ATOM 184 O ??? 1 -5.255 -9.348 -7.127 +ATOM 185 C ??? 1 -3.864 -9.233 -7.443 +ATOM 186 C ??? 1 -3.265 -10.503 -6.982 +ATOM 187 O ??? 1 -3.388 -10.408 -5.569 +ATOM 188 C ??? 1 -3.913 -11.848 -7.400 +ATOM 189 O ??? 1 -2.906 -12.861 -7.541 +ATOM 190 C ??? 1 -4.865 -12.134 -6.218 +ATOM 191 C ??? 1 -3.937 -11.700 -5.115 +ATOM 192 N ??? 1 -4.370 -11.653 -3.684 +ATOM 193 C ??? 1 -5.572 -11.359 -3.092 +ATOM 194 N ??? 1 -5.502 -11.208 -1.750 +ATOM 195 C ??? 1 -4.184 -11.405 -1.464 +ATOM 196 C ??? 1 -3.484 -11.398 -0.187 +ATOM 197 O ??? 1 -3.973 -11.294 0.939 +ATOM 198 N ??? 1 -2.117 -11.651 -0.293 +ATOM 199 C ??? 1 -1.432 -11.934 -1.458 +ATOM 200 N ??? 1 -0.114 -12.247 -1.341 +ATOM 201 N ??? 1 -2.059 -11.968 -2.664 +ATOM 202 C ??? 1 -3.452 -11.687 -2.620 +ATOM 203 P ??? 1 -2.430 -13.413 -8.952 +ATOM 204 O ??? 1 -3.259 -14.642 -9.185 +ATOM 205 O ??? 1 -2.433 -12.356 -10.046 +ATOM 206 O ??? 1 -0.882 -13.756 -8.697 +ATOM 207 C ??? 1 0.079 -12.685 -8.383 +ATOM 208 C ??? 1 1.266 -13.194 -7.564 +ATOM 209 O ??? 1 0.999 -13.349 -6.166 +ATOM 210 C ??? 1 1.851 -14.504 -7.958 +ATOM 211 O ??? 1 3.274 -14.536 -7.758 +ATOM 212 C ??? 1 1.034 -15.479 -7.076 +ATOM 213 C ??? 1 1.061 -14.732 -5.783 +ATOM 214 N ??? 1 0.018 -15.063 -4.744 +ATOM 215 C ??? 1 0.371 -15.193 -3.394 +ATOM 216 O ??? 1 1.555 -15.059 -3.043 +ATOM 217 N ??? 1 -0.605 -15.422 -2.469 +ATOM 218 C ??? 1 -1.903 -15.490 -2.823 +ATOM 219 N ??? 1 -2.850 -15.626 -1.852 +ATOM 220 C ??? 1 -2.311 -15.339 -4.167 +ATOM 221 C ??? 1 -1.315 -15.115 -5.135 +ATOM 222 P ??? 1 4.029 -15.922 -7.818 +ATOM 223 O ??? 1 3.416 -16.861 -8.809 +ATOM 224 O ??? 1 5.487 -15.559 -8.011 +ATOM 225 O ??? 1 3.714 -16.639 -6.402 +ATOM 226 C ??? 1 4.699 -16.656 -5.290 +ATOM 227 C ??? 1 4.464 -17.877 -4.385 +ATOM 228 O ??? 1 3.153 -17.818 -3.885 +ATOM 229 C ??? 1 4.685 -19.342 -4.849 +ATOM 230 O ??? 1 5.420 -20.114 -3.884 +ATOM 231 C ??? 1 3.295 -19.890 -5.050 +ATOM 232 C ??? 1 2.531 -19.057 -4.020 +ATOM 233 N ??? 1 1.056 -18.734 -4.183 +ATOM 234 C ??? 1 0.273 -18.422 -5.264 +ATOM 235 N ??? 1 -1.031 -18.317 -4.953 +ATOM 236 C ??? 1 -1.093 -18.575 -3.620 +ATOM 237 C ??? 1 -2.226 -18.671 -2.719 +ATOM 238 O ??? 1 -3.418 -18.578 -2.959 +ATOM 239 N ??? 1 -1.866 -18.877 -1.414 +ATOM 240 C ??? 1 -0.581 -18.991 -0.915 +ATOM 241 N ??? 1 -0.396 -19.286 0.409 +ATOM 242 N ??? 1 0.472 -18.926 -1.725 +ATOM 243 C ??? 1 0.163 -18.734 -3.100 +ATOM 244 O ??? 1 -6.680 -19.825 7.699 +ATOM 245 C ??? 1 -6.306 -20.194 6.315 +ATOM 246 C ??? 1 -5.053 -19.445 5.920 +ATOM 247 O ??? 1 -4.418 -19.699 4.659 +ATOM 248 C ??? 1 -4.994 -17.972 6.135 +ATOM 249 O ??? 1 -3.710 -17.604 6.687 +ATOM 250 C ??? 1 -5.163 -17.510 4.681 +ATOM 251 C ??? 1 -4.498 -18.548 3.817 +ATOM 252 N ??? 1 -5.087 -18.713 2.382 +ATOM 253 C ??? 1 -4.235 -18.653 1.283 +ATOM 254 O ??? 1 -3.023 -18.634 1.498 +ATOM 255 N ??? 1 -4.753 -18.618 0.009 +ATOM 256 C ??? 1 -6.087 -18.707 -0.208 +ATOM 257 N ??? 1 -6.569 -18.815 -1.491 +ATOM 258 C ??? 1 -6.991 -18.809 0.869 +ATOM 259 C ??? 1 -6.468 -18.783 2.177 +ATOM 260 P ??? 1 -3.519 -16.827 8.069 +ATOM 261 O ??? 1 -4.231 -15.537 8.035 +ATOM 262 O ??? 1 -3.821 -17.708 9.240 +ATOM 263 O ??? 1 -1.956 -16.549 8.073 +ATOM 264 C ??? 1 -0.947 -17.650 8.003 +ATOM 265 C ??? 1 0.325 -17.111 7.352 +ATOM 266 O ??? 1 0.066 -17.132 5.962 +ATOM 267 C ??? 1 0.613 -15.669 7.661 +ATOM 268 O ??? 1 1.856 -15.388 8.203 +ATOM 269 C ??? 1 0.265 -14.853 6.465 +ATOM 270 C ??? 1 0.285 -15.854 5.380 +ATOM 271 N ??? 1 -0.824 -15.536 4.452 +ATOM 272 C ??? 1 -2.113 -15.141 4.752 +ATOM 273 N ??? 1 -2.810 -14.728 3.684 +ATOM 274 C ??? 1 -1.957 -14.896 2.652 +ATOM 275 C ??? 1 -2.142 -14.574 1.260 +ATOM 276 O ??? 1 -3.179 -14.132 0.774 +ATOM 277 N ??? 1 -1.001 -14.804 0.451 +ATOM 278 C ??? 1 0.192 -15.336 0.902 +ATOM 279 N ??? 1 1.184 -15.515 0.002 +ATOM 280 N ??? 1 0.382 -15.672 2.205 +ATOM 281 C ??? 1 -0.729 -15.444 3.059 +ATOM 282 P ??? 1 2.293 -13.866 8.376 +ATOM 283 O ??? 1 1.086 -13.042 8.626 +ATOM 284 O ??? 1 3.396 -13.816 9.377 +ATOM 285 O ??? 1 2.922 -13.420 7.025 +ATOM 286 C ??? 1 4.007 -14.108 6.407 +ATOM 287 C ??? 1 4.054 -13.498 5.013 +ATOM 288 O ??? 1 2.780 -13.607 4.393 +ATOM 289 C ??? 1 4.326 -12.019 4.962 +ATOM 290 O ??? 1 5.715 -11.793 5.178 +ATOM 291 C ??? 1 3.795 -11.615 3.565 +ATOM 292 C ??? 1 2.647 -12.603 3.423 +ATOM 293 N ??? 1 1.244 -12.133 3.536 +ATOM 294 C ??? 1 0.427 -12.102 2.410 +ATOM 295 O ??? 1 0.835 -12.492 1.323 +ATOM 296 N ??? 1 -0.850 -11.713 2.533 +ATOM 297 C ??? 1 -1.391 -11.421 3.723 +ATOM 298 N ??? 1 -2.628 -10.831 3.762 +ATOM 299 C ??? 1 -0.649 -11.574 4.913 +ATOM 300 C ??? 1 0.708 -11.938 4.796 +ATOM 301 P ??? 1 6.336 -10.366 5.128 +ATOM 302 O ??? 1 5.449 -9.428 5.909 +ATOM 303 O ??? 1 7.745 -10.482 5.620 +ATOM 304 O ??? 1 6.290 -10.020 3.569 +ATOM 305 C ??? 1 7.055 -10.811 2.615 +ATOM 306 C ??? 1 6.734 -10.308 1.217 +ATOM 307 O ??? 1 5.297 -10.192 1.100 +ATOM 308 C ??? 1 7.286 -8.975 0.718 +ATOM 309 O ??? 1 7.393 -8.945 -0.714 +ATOM 310 C ??? 1 6.225 -7.973 1.221 +ATOM 311 C ??? 1 4.974 -8.794 0.845 +ATOM 312 N ??? 1 3.773 -8.455 1.602 +ATOM 313 C ??? 1 3.640 -7.981 2.890 +ATOM 314 N ??? 1 2.384 -7.801 3.240 +ATOM 315 C ??? 1 1.667 -8.192 2.129 +ATOM 316 C ??? 1 0.216 -8.383 1.898 +ATOM 317 O ??? 1 -0.692 -8.327 2.724 +ATOM 318 N ??? 1 -0.115 -8.589 0.569 +ATOM 319 C ??? 1 0.807 -8.696 -0.461 +ATOM 320 N ??? 1 0.345 -8.866 -1.749 +ATOM 321 N ??? 1 2.149 -8.691 -0.209 +ATOM 322 C ??? 1 2.524 -8.455 1.086 +ATOM 323 P ??? 1 7.575 -7.564 -1.471 +ATOM 324 O ??? 1 7.955 -6.449 -0.479 +ATOM 325 O ??? 1 8.741 -7.728 -2.458 +ATOM 326 O ??? 1 6.254 -7.373 -2.307 +ATOM 327 C ??? 1 6.024 -8.272 -3.442 +ATOM 328 C ??? 1 5.019 -7.727 -4.455 +ATOM 329 O ??? 1 3.633 -7.467 -4.002 +ATOM 330 C ??? 1 5.448 -6.462 -5.147 +ATOM 331 O ??? 1 5.043 -6.461 -6.529 +ATOM 332 C ??? 1 4.765 -5.380 -4.322 +ATOM 333 C ??? 1 3.522 -6.055 -3.759 +ATOM 334 N ??? 1 3.349 -5.765 -2.284 +ATOM 335 C ??? 1 4.280 -5.485 -1.291 +ATOM 336 N ??? 1 3.718 -5.218 -0.101 +ATOM 337 C ??? 1 2.389 -5.311 -0.337 +ATOM 338 C ??? 1 1.210 -5.068 0.470 +ATOM 339 N ??? 1 1.297 -4.554 1.713 +ATOM 340 N ??? 1 -0.018 -5.382 -0.038 +ATOM 341 C ??? 1 -0.107 -5.816 -1.309 +ATOM 342 N ??? 1 0.900 -5.988 -2.198 +ATOM 343 C ??? 1 2.136 -5.713 -1.640 +ATOM 344 P ??? 1 4.958 -5.104 -7.365 +ATOM 345 O ??? 1 5.978 -4.099 -6.859 +ATOM 346 O ??? 1 5.021 -5.615 -8.756 +ATOM 347 O ??? 1 3.560 -4.533 -7.033 +ATOM 348 C ??? 1 2.362 -5.321 -7.154 +ATOM 349 C ??? 1 1.273 -4.376 -6.720 +ATOM 350 O ??? 1 1.389 -4.141 -5.316 +ATOM 351 C ??? 1 1.322 -2.993 -7.366 +ATOM 352 O ??? 1 0.329 -2.831 -8.391 +ATOM 353 C ??? 1 1.333 -1.991 -6.194 +ATOM 354 C ??? 1 0.897 -2.852 -5.006 +ATOM 355 N ??? 1 1.537 -2.528 -3.709 +ATOM 356 C ??? 1 2.863 -2.388 -3.374 +ATOM 357 N ??? 1 3.059 -2.100 -2.081 +ATOM 358 C ??? 1 1.825 -2.100 -1.562 +ATOM 359 C ??? 1 1.312 -1.785 -0.242 +ATOM 360 N ??? 1 2.105 -1.419 0.792 +ATOM 361 N ??? 1 -0.035 -1.681 -0.088 +ATOM 362 C ??? 1 -0.863 -1.975 -1.112 +ATOM 363 N ??? 1 -0.516 -2.341 -2.360 +ATOM 364 C ??? 1 0.871 -2.352 -2.537 +ATOM 365 P ??? 1 0.096 -1.455 -9.141 +ATOM 366 O ??? 1 1.403 -0.827 -9.454 +ATOM 367 O ??? 1 -0.784 -1.681 -10.328 +ATOM 368 O ??? 1 -0.708 -0.618 -8.042 +ATOM 369 C ??? 1 -2.026 -1.063 -7.621 +ATOM 370 C ??? 1 -2.460 -0.283 -6.398 +ATOM 371 O ??? 1 -1.482 -0.424 -5.323 +ATOM 372 C ??? 1 -2.702 1.209 -6.627 +ATOM 373 O ??? 1 -4.034 1.463 -6.980 +ATOM 374 C ??? 1 -2.262 1.804 -5.316 +ATOM 375 C ??? 1 -1.039 0.909 -5.075 +ATOM 376 N ??? 1 -0.210 0.993 -3.836 +ATOM 377 C ??? 1 -0.736 1.017 -2.546 +ATOM 378 O ??? 1 -1.957 0.851 -2.314 +ATOM 379 N ??? 1 0.164 1.108 -1.498 +ATOM 380 C ??? 1 1.538 1.199 -1.677 +ATOM 381 O ??? 1 2.250 1.226 -0.672 +ATOM 382 C ??? 1 2.054 1.179 -2.992 +ATOM 383 C ??? 1 3.521 1.367 -3.242 +ATOM 384 C ??? 1 1.153 1.065 -4.071 +ATOM 385 P ??? 1 -4.609 2.928 -7.269 +ATOM 386 O ??? 1 -3.623 3.841 -7.848 +ATOM 387 O ??? 1 -5.862 2.588 -8.032 +ATOM 388 O ??? 1 -4.884 3.503 -5.838 +ATOM 389 C ??? 1 -5.822 2.805 -4.954 +ATOM 390 C ??? 1 -5.829 3.570 -3.680 +ATOM 391 O ??? 1 -4.506 3.511 -3.227 +ATOM 392 C ??? 1 -6.172 5.046 -3.735 +ATOM 393 O ??? 1 -7.441 5.291 -3.123 +ATOM 394 C ??? 1 -5.006 5.747 -3.052 +ATOM 395 C ??? 1 -4.274 4.597 -2.370 +ATOM 396 N ??? 1 -2.767 4.703 -2.324 +ATOM 397 C ??? 1 -2.085 4.842 -1.117 +ATOM 398 O ??? 1 -2.678 5.024 -0.043 +ATOM 399 N ??? 1 -0.697 4.808 -1.172 +ATOM 400 C ??? 1 0.014 4.669 -2.366 +ATOM 401 O ??? 1 1.237 4.636 -2.312 +ATOM 402 C ??? 1 -0.682 4.595 -3.576 +ATOM 403 C ??? 1 0.027 4.511 -4.924 +ATOM 404 C ??? 1 -2.079 4.607 -3.526 +ATOM 405 P ??? 1 -8.018 6.766 -2.948 +ATOM 406 O ??? 1 -7.635 7.566 -4.152 +ATOM 407 O ??? 1 -9.476 6.706 -2.680 +ATOM 408 O ??? 1 -7.320 7.281 -1.652 +ATOM 409 C ??? 1 -7.634 6.745 -0.332 +ATOM 410 C ??? 1 -6.740 7.536 0.578 +ATOM 411 O ??? 1 -5.356 7.300 0.129 +ATOM 412 C ??? 1 -6.992 9.072 0.483 +ATOM 413 O ??? 1 -7.500 9.642 1.681 +ATOM 414 C ??? 1 -5.648 9.640 0.010 +ATOM 415 C ??? 1 -4.683 8.515 0.475 +ATOM 416 N ??? 1 -3.379 8.489 -0.149 +ATOM 417 C ??? 1 -2.166 8.504 0.541 +ATOM 418 O ??? 1 -2.158 8.517 1.779 +ATOM 419 N ??? 1 -1.010 8.423 -0.184 +ATOM 420 C ??? 1 -1.042 8.316 -1.562 +ATOM 421 N ??? 1 0.083 8.179 -2.370 +ATOM 422 C ??? 1 -2.249 8.284 -2.244 +ATOM 423 C ??? 1 -3.426 8.372 -1.520 +ATOM 424 P ??? 1 -8.072 11.149 1.769 +ATOM 425 O ??? 1 -8.359 11.946 0.569 +ATOM 426 O ??? 1 -9.253 11.131 2.697 +ATOM 427 O ??? 1 -6.842 11.901 2.427 +ATOM 428 C ??? 1 -6.195 11.442 3.679 +ATOM 429 C ??? 1 -4.912 12.282 3.817 +ATOM 430 O ??? 1 -3.876 11.994 2.873 +ATOM 431 C ??? 1 -5.090 13.728 3.629 +ATOM 432 O ??? 1 -4.492 14.502 4.643 +ATOM 433 C ??? 1 -4.542 14.026 2.249 +ATOM 434 C ??? 1 -3.391 13.126 2.230 +ATOM 435 N ??? 1 -2.856 12.707 0.897 +ATOM 436 C ??? 1 -3.473 12.442 -0.319 +ATOM 437 N ??? 1 -2.637 12.015 -1.293 +ATOM 438 C ??? 1 -1.436 12.007 -0.688 +ATOM 439 C ??? 1 -0.127 11.608 -1.179 +ATOM 440 O ??? 1 0.172 11.212 -2.291 +ATOM 441 N ??? 1 0.874 11.683 -0.204 +ATOM 442 C ??? 1 0.686 12.119 1.100 +ATOM 443 N ??? 1 1.749 12.103 1.939 +ATOM 444 N ??? 1 -0.519 12.555 1.528 +ATOM 445 C ??? 1 -1.544 12.446 0.633 +ATOM 446 P ??? 1 -5.127 15.894 4.858 +ATOM 447 O ??? 1 -5.425 16.629 3.561 +ATOM 448 O ??? 1 -6.250 15.527 5.754 +ATOM 449 O ??? 1 -4.002 16.793 5.584 +ATOM 450 C ??? 1 -3.238 16.255 6.678 +ATOM 451 C ??? 1 -1.830 16.039 6.216 +ATOM 452 O ??? 1 -1.871 15.509 4.883 +ATOM 453 C ??? 1 -0.873 17.253 6.173 +ATOM 454 O ??? 1 -0.153 17.520 7.416 +ATOM 455 C ??? 1 0.090 16.942 5.027 +ATOM 456 C ??? 1 -0.595 15.819 4.260 +ATOM 457 N ??? 1 -0.730 16.057 2.785 +ATOM 458 C ??? 1 0.227 15.578 1.903 +ATOM 459 O ??? 1 1.293 15.046 2.291 +ATOM 460 N ??? 1 -0.055 15.614 0.600 +ATOM 461 C ??? 1 -1.197 16.106 0.107 +ATOM 462 N ??? 1 -1.457 15.971 -1.213 +ATOM 463 C ??? 1 -2.157 16.670 0.937 +ATOM 464 C ??? 1 -1.890 16.634 2.320 +ATOM 465 P ??? 1 0.085 19.035 7.891 +ATOM 466 O ??? 1 -1.103 19.918 7.465 +ATOM 467 O ??? 1 0.455 19.118 9.333 +ATOM 468 O ??? 1 1.304 19.503 6.967 +ATOM 469 C ??? 1 2.588 19.092 7.215 +ATOM 470 C ??? 1 3.346 19.369 5.986 +ATOM 471 O ??? 1 2.968 18.509 4.924 +ATOM 472 C ??? 1 3.325 20.751 5.383 +ATOM 473 O ??? 1 3.907 21.749 6.266 +ATOM 474 C ??? 1 4.203 20.393 4.162 +ATOM 475 C ??? 1 3.516 19.074 3.711 +ATOM 476 N ??? 1 2.407 19.227 2.697 +ATOM 477 C ??? 1 1.165 19.783 2.799 +ATOM 478 N ??? 1 0.472 19.784 1.639 +ATOM 479 C ??? 1 1.290 19.206 0.763 +ATOM 480 C ??? 1 1.097 18.852 -0.624 +ATOM 481 O ??? 1 0.123 18.893 -1.321 +ATOM 482 N ??? 1 2.227 18.334 -1.206 +ATOM 483 C ??? 1 3.438 18.092 -0.570 +ATOM 484 N ??? 1 4.500 17.628 -1.280 +ATOM 485 N ??? 1 3.571 18.322 0.734 +ATOM 486 C ??? 1 2.483 18.897 1.373 +CONECT 1 2 +CONECT 2 1 3 +CONECT 3 2 4 5 +CONECT 4 3 8 +CONECT 5 3 6 7 +CONECT 6 5 17 +CONECT 7 5 8 +CONECT 8 4 7 9 +CONECT 9 8 10 16 +CONECT 10 9 11 12 +CONECT 11 10 +CONECT 12 10 13 +CONECT 13 12 14 15 +CONECT 14 13 +CONECT 15 13 16 +CONECT 16 9 15 +CONECT 17 6 18 19 20 +CONECT 18 17 +CONECT 19 17 +CONECT 20 17 21 +CONECT 21 20 22 +CONECT 22 21 23 24 +CONECT 23 22 27 +CONECT 24 22 25 26 +CONECT 25 24 39 +CONECT 26 24 27 +CONECT 27 23 26 28 +CONECT 28 27 29 38 +CONECT 29 28 30 +CONECT 30 29 31 +CONECT 31 30 32 38 +CONECT 32 31 33 34 +CONECT 33 32 +CONECT 34 32 35 +CONECT 35 34 36 37 +CONECT 36 35 +CONECT 37 35 38 +CONECT 38 28 31 37 +CONECT 39 25 40 41 42 +CONECT 40 39 +CONECT 41 39 +CONECT 42 39 43 +CONECT 43 42 44 +CONECT 44 43 45 46 +CONECT 45 44 49 +CONECT 46 44 47 48 +CONECT 47 46 58 +CONECT 48 46 49 +CONECT 49 45 48 50 +CONECT 50 49 51 57 +CONECT 51 50 52 53 +CONECT 52 51 +CONECT 53 51 54 +CONECT 54 53 55 56 +CONECT 55 54 +CONECT 56 54 57 +CONECT 57 50 56 +CONECT 58 47 59 60 61 +CONECT 59 58 +CONECT 60 58 +CONECT 61 58 62 +CONECT 62 61 63 +CONECT 63 62 64 65 +CONECT 64 63 68 +CONECT 65 63 66 67 +CONECT 66 65 80 +CONECT 67 65 68 +CONECT 68 64 67 69 +CONECT 69 68 70 79 +CONECT 70 69 71 +CONECT 71 70 72 +CONECT 72 71 73 79 +CONECT 73 72 74 75 +CONECT 74 73 +CONECT 75 73 76 +CONECT 76 75 77 78 +CONECT 77 76 +CONECT 78 76 79 +CONECT 79 69 72 78 +CONECT 80 66 81 82 83 +CONECT 81 80 +CONECT 82 80 +CONECT 83 80 84 +CONECT 84 83 85 +CONECT 85 84 86 87 +CONECT 86 85 90 +CONECT 87 85 88 89 +CONECT 88 87 101 +CONECT 89 87 90 +CONECT 90 86 89 91 +CONECT 91 90 92 100 +CONECT 92 91 93 +CONECT 93 92 94 +CONECT 94 93 95 100 +CONECT 95 94 96 97 +CONECT 96 95 +CONECT 97 95 98 +CONECT 98 97 99 +CONECT 99 98 100 +CONECT 100 91 94 99 +CONECT 101 88 102 103 104 +CONECT 102 101 +CONECT 103 101 +CONECT 104 101 105 +CONECT 105 104 106 +CONECT 106 105 107 108 +CONECT 107 106 111 +CONECT 108 106 109 110 +CONECT 109 108 122 +CONECT 110 108 111 +CONECT 111 107 110 112 +CONECT 112 111 113 121 +CONECT 113 112 114 +CONECT 114 113 115 +CONECT 115 114 116 121 +CONECT 116 115 117 118 +CONECT 117 116 +CONECT 118 116 119 +CONECT 119 118 120 +CONECT 120 119 121 +CONECT 121 112 115 120 +CONECT 122 109 123 124 125 +CONECT 123 122 +CONECT 124 122 +CONECT 125 122 126 +CONECT 126 125 127 +CONECT 127 126 128 129 +CONECT 128 127 132 +CONECT 129 127 130 131 +CONECT 130 129 142 +CONECT 131 129 132 +CONECT 132 128 131 133 +CONECT 133 132 134 141 +CONECT 134 133 135 136 +CONECT 135 134 +CONECT 136 134 137 +CONECT 137 136 138 139 +CONECT 138 137 +CONECT 139 137 140 141 +CONECT 140 139 +CONECT 141 133 139 +CONECT 142 130 143 145 +CONECT 143 142 +CONECT 145 142 146 +CONECT 146 145 147 +CONECT 147 146 148 149 +CONECT 148 147 152 +CONECT 149 147 150 151 +CONECT 150 149 162 +CONECT 151 149 152 +CONECT 152 148 151 153 +CONECT 153 152 154 161 +CONECT 154 153 155 156 +CONECT 155 154 +CONECT 156 154 157 +CONECT 157 156 158 159 +CONECT 158 157 +CONECT 159 157 160 161 +CONECT 160 159 +CONECT 161 153 159 +CONECT 162 150 163 164 165 +CONECT 163 162 +CONECT 164 162 +CONECT 165 162 166 +CONECT 166 165 167 +CONECT 167 166 168 169 +CONECT 168 167 172 +CONECT 169 167 170 171 +CONECT 170 169 181 +CONECT 171 169 172 +CONECT 172 168 171 173 +CONECT 173 172 174 180 +CONECT 174 173 175 176 +CONECT 175 174 +CONECT 176 174 177 +CONECT 177 176 178 179 +CONECT 178 177 +CONECT 179 177 180 +CONECT 180 173 179 +CONECT 181 170 182 183 184 +CONECT 182 181 +CONECT 183 181 +CONECT 184 181 185 +CONECT 185 184 186 +CONECT 186 185 187 188 +CONECT 187 186 191 +CONECT 188 186 189 190 +CONECT 189 188 203 +CONECT 190 188 191 +CONECT 191 187 190 192 +CONECT 192 191 193 202 +CONECT 193 192 194 +CONECT 194 193 195 +CONECT 195 194 196 202 +CONECT 196 195 197 198 +CONECT 197 196 +CONECT 198 196 199 +CONECT 199 198 200 201 +CONECT 200 199 +CONECT 201 199 202 +CONECT 202 192 195 201 +CONECT 203 189 204 205 206 +CONECT 204 203 +CONECT 205 203 +CONECT 206 203 207 +CONECT 207 206 208 +CONECT 208 207 209 210 +CONECT 209 208 213 +CONECT 210 208 211 212 +CONECT 211 210 222 +CONECT 212 210 213 +CONECT 213 209 212 214 +CONECT 214 213 215 221 +CONECT 215 214 216 217 +CONECT 216 215 +CONECT 217 215 218 +CONECT 218 217 219 220 +CONECT 219 218 +CONECT 220 218 221 +CONECT 221 214 220 +CONECT 222 211 223 224 225 +CONECT 223 222 +CONECT 224 222 +CONECT 225 222 226 +CONECT 226 225 227 +CONECT 227 226 228 229 +CONECT 228 227 232 +CONECT 229 227 230 231 +CONECT 230 229 +CONECT 231 229 232 +CONECT 232 228 231 233 +CONECT 233 232 234 243 +CONECT 234 233 235 +CONECT 235 234 236 +CONECT 236 235 237 243 +CONECT 237 236 238 239 +CONECT 238 237 +CONECT 239 237 240 +CONECT 240 239 241 242 +CONECT 241 240 +CONECT 242 240 243 +CONECT 243 233 236 242 +CONECT 244 245 +CONECT 245 244 246 +CONECT 246 245 247 248 +CONECT 247 246 251 +CONECT 248 246 249 250 +CONECT 249 248 260 +CONECT 250 248 251 +CONECT 251 247 250 252 +CONECT 252 251 253 259 +CONECT 253 252 254 255 +CONECT 254 253 +CONECT 255 253 256 +CONECT 256 255 257 258 +CONECT 257 256 +CONECT 258 256 259 +CONECT 259 252 258 +CONECT 260 249 261 262 263 +CONECT 261 260 +CONECT 262 260 +CONECT 263 260 264 +CONECT 264 263 265 +CONECT 265 264 266 267 +CONECT 266 265 270 +CONECT 267 265 268 269 +CONECT 268 267 282 +CONECT 269 267 270 +CONECT 270 266 269 271 +CONECT 271 270 272 281 +CONECT 272 271 273 +CONECT 273 272 274 +CONECT 274 273 275 281 +CONECT 275 274 276 277 +CONECT 276 275 +CONECT 277 275 278 +CONECT 278 277 279 280 +CONECT 279 278 +CONECT 280 278 281 +CONECT 281 271 274 280 +CONECT 282 268 283 284 285 +CONECT 283 282 +CONECT 284 282 +CONECT 285 282 286 +CONECT 286 285 287 +CONECT 287 286 288 289 +CONECT 288 287 292 +CONECT 289 287 290 291 +CONECT 290 289 301 +CONECT 291 289 292 +CONECT 292 288 291 293 +CONECT 293 292 294 300 +CONECT 294 293 295 296 +CONECT 295 294 +CONECT 296 294 297 +CONECT 297 296 298 299 +CONECT 298 297 +CONECT 299 297 300 +CONECT 300 293 299 +CONECT 301 290 302 303 304 +CONECT 302 301 +CONECT 303 301 +CONECT 304 301 305 +CONECT 305 304 306 +CONECT 306 305 307 308 +CONECT 307 306 311 +CONECT 308 306 309 310 +CONECT 309 308 323 +CONECT 310 308 311 +CONECT 311 307 310 312 +CONECT 312 311 313 322 +CONECT 313 312 314 +CONECT 314 313 315 +CONECT 315 314 316 322 +CONECT 316 315 317 318 +CONECT 317 316 +CONECT 318 316 319 +CONECT 319 318 320 321 +CONECT 320 319 +CONECT 321 319 322 +CONECT 322 312 315 321 +CONECT 323 309 324 325 326 +CONECT 324 323 +CONECT 325 323 +CONECT 326 323 327 +CONECT 327 326 328 +CONECT 328 327 329 330 +CONECT 329 328 333 +CONECT 330 328 331 332 +CONECT 331 330 344 +CONECT 332 330 333 +CONECT 333 329 332 334 +CONECT 334 333 335 343 +CONECT 335 334 336 +CONECT 336 335 337 +CONECT 337 336 338 343 +CONECT 338 337 339 340 +CONECT 339 338 +CONECT 340 338 341 +CONECT 341 340 342 +CONECT 342 341 343 +CONECT 343 334 337 342 +CONECT 344 331 345 346 347 +CONECT 345 344 +CONECT 346 344 +CONECT 347 344 348 +CONECT 348 347 349 +CONECT 349 348 350 351 +CONECT 350 349 354 +CONECT 351 349 352 353 +CONECT 352 351 365 +CONECT 353 351 354 +CONECT 354 350 353 355 +CONECT 355 354 356 364 +CONECT 356 355 357 +CONECT 357 356 358 +CONECT 358 357 359 364 +CONECT 359 358 360 361 +CONECT 360 359 +CONECT 361 359 362 +CONECT 362 361 363 +CONECT 363 362 364 +CONECT 364 355 358 363 +CONECT 365 352 366 367 368 +CONECT 366 365 +CONECT 367 365 +CONECT 368 365 369 +CONECT 369 368 370 +CONECT 370 369 371 372 +CONECT 371 370 375 +CONECT 372 370 373 374 +CONECT 373 372 385 +CONECT 374 372 375 +CONECT 375 371 374 376 +CONECT 376 375 377 384 +CONECT 377 376 378 379 +CONECT 378 377 +CONECT 379 377 380 +CONECT 380 379 381 382 +CONECT 381 380 +CONECT 382 380 383 384 +CONECT 383 382 +CONECT 384 376 382 +CONECT 385 373 386 387 388 +CONECT 386 385 +CONECT 387 385 +CONECT 388 385 389 +CONECT 389 388 390 +CONECT 390 389 391 392 +CONECT 391 390 395 +CONECT 392 390 393 394 +CONECT 393 392 405 +CONECT 394 392 395 +CONECT 395 391 394 396 +CONECT 396 395 397 404 +CONECT 397 396 398 399 +CONECT 398 397 +CONECT 399 397 400 +CONECT 400 399 401 402 +CONECT 401 400 +CONECT 402 400 403 404 +CONECT 403 402 +CONECT 404 396 402 +CONECT 405 393 406 407 408 +CONECT 406 405 +CONECT 407 405 +CONECT 408 405 409 +CONECT 409 408 410 +CONECT 410 409 411 412 +CONECT 411 410 415 +CONECT 412 410 413 414 +CONECT 413 412 424 +CONECT 414 412 415 +CONECT 415 411 414 416 +CONECT 416 415 417 423 +CONECT 417 416 418 419 +CONECT 418 417 +CONECT 419 417 420 +CONECT 420 419 421 422 +CONECT 421 420 +CONECT 422 420 423 +CONECT 423 416 422 +CONECT 424 413 425 426 427 +CONECT 425 424 +CONECT 426 424 +CONECT 427 424 428 +CONECT 428 427 429 +CONECT 429 428 430 431 +CONECT 430 429 434 +CONECT 431 429 432 433 +CONECT 432 431 446 +CONECT 433 431 434 +CONECT 434 430 433 435 +CONECT 435 434 436 445 +CONECT 436 435 437 +CONECT 437 436 438 +CONECT 438 437 439 445 +CONECT 439 438 440 441 +CONECT 440 439 +CONECT 441 439 442 +CONECT 442 441 443 444 +CONECT 443 442 +CONECT 444 442 445 +CONECT 445 435 438 444 +CONECT 446 432 447 448 449 +CONECT 447 446 +CONECT 448 446 +CONECT 449 446 450 +CONECT 450 449 451 +CONECT 451 450 452 453 +CONECT 452 451 456 +CONECT 453 451 454 455 +CONECT 454 453 465 +CONECT 455 453 456 +CONECT 456 452 455 457 +CONECT 457 456 458 464 +CONECT 458 457 459 460 +CONECT 459 458 +CONECT 460 458 461 +CONECT 461 460 462 463 +CONECT 462 461 +CONECT 463 461 464 +CONECT 464 457 463 +CONECT 465 454 466 467 468 +CONECT 466 465 +CONECT 467 465 +CONECT 468 465 469 +CONECT 469 468 470 +CONECT 470 469 471 472 +CONECT 471 470 475 +CONECT 472 470 473 474 +CONECT 473 472 +CONECT 474 472 475 +CONECT 475 471 474 476 +CONECT 476 475 477 486 +CONECT 477 476 478 +CONECT 478 477 479 +CONECT 479 478 480 486 +CONECT 480 479 481 482 +CONECT 481 480 +CONECT 482 480 483 +CONECT 483 482 484 485 +CONECT 484 483 +CONECT 485 483 486 +CONECT 486 476 479 485 +END diff --git a/hacks/images/molecules/dodecahedrane.pdb b/hacks/images/molecules/dodecahedrane.pdb new file mode 100644 index 00000000..94b2d2fb --- /dev/null +++ b/hacks/images/molecules/dodecahedrane.pdb @@ -0,0 +1,87 @@ +HEADER Dodecahedrane +COMPND al3056 +AUTHOR Created by Dave Woodcock at Okanagan University College +AUTHOR email:woodcock@okanagan.bc.ca +AUTHOR Date revised: Sun Sep 3 10:20:00 2000 GENERATED BY BABEL 1.6 +HETATM 1 C 1 0.000 0.000 0.000 1.00 0.00 +HETATM 2 C 1 1.540 0.000 0.000 1.00 0.00 +HETATM 3 C 1 2.016 1.465 0.000 1.00 0.00 +HETATM 4 C 1 0.771 2.369 0.000 1.00 0.00 +HETATM 5 C 1 -0.476 1.465 0.000 1.00 0.00 +HETATM 6 C 1 -0.476 -0.655 1.309 1.00 0.00 +HETATM 7 C 1 -1.246 0.404 2.118 1.00 0.00 +HETATM 8 C 1 -1.246 1.714 1.309 1.00 0.00 +HETATM 9 C 1 -0.476 2.774 2.119 1.00 0.00 +HETATM 10 C 1 0.770 3.179 1.310 1.00 0.00 +HETATM 11 C 1 2.016 2.774 2.120 1.00 0.00 +HETATM 12 C 1 2.786 1.715 1.310 1.00 0.00 +HETATM 13 C 1 2.785 0.405 2.120 1.00 0.00 +HETATM 14 C 1 2.016 -0.655 1.310 1.00 0.00 +HETATM 15 C 1 0.769 -1.059 2.118 1.00 0.00 +HETATM 16 C 1 0.770 -0.250 3.428 1.00 0.00 +HETATM 17 C 1 -0.476 0.655 3.428 1.00 0.00 +HETATM 18 C 1 2.015 0.656 3.429 1.00 0.00 +HETATM 19 C 1 0.000 2.119 3.428 1.00 0.00 +HETATM 20 C 1 1.539 2.119 3.428 1.00 0.00 +HETATM 21 H 1 -0.389 -0.536 -0.866 1.00 0.00 +HETATM 22 H 1 1.929 -0.535 -0.866 1.00 0.00 +HETATM 23 H 1 2.645 1.669 -0.866 1.00 0.00 +HETATM 24 H 1 0.771 3.031 -0.867 1.00 0.00 +HETATM 25 H 1 -1.105 1.670 -0.867 1.00 0.00 +HETATM 26 H 1 -1.105 -1.521 1.105 1.00 0.00 +HETATM 27 H 1 -2.264 0.073 2.321 1.00 0.00 +HETATM 28 H 1 -2.264 2.044 1.104 1.00 0.00 +HETATM 29 H 1 -1.105 3.639 2.324 1.00 0.00 +HETATM 30 H 1 0.771 4.249 1.105 1.00 0.00 +HETATM 31 H 1 2.645 3.640 2.327 1.00 0.00 +HETATM 32 H 1 3.804 2.046 1.106 1.00 0.00 +HETATM 33 H 1 3.803 0.073 2.325 1.00 0.00 +HETATM 34 H 1 2.645 -1.522 1.106 1.00 0.00 +HETATM 35 H 1 0.769 -2.130 2.322 1.00 0.00 +HETATM 36 H 1 0.771 -0.912 4.294 1.00 0.00 +HETATM 37 H 1 -1.106 0.451 4.294 1.00 0.00 +HETATM 38 H 1 2.644 0.453 4.295 1.00 0.00 +HETATM 39 H 1 -0.387 2.655 4.295 1.00 0.00 +HETATM 40 H 1 1.928 2.654 4.295 1.00 0.00 +CONECT 1 2 5 6 21 +CONECT 2 1 3 14 22 +CONECT 3 2 4 12 23 +CONECT 4 3 5 10 24 +CONECT 5 1 4 8 25 +CONECT 6 1 7 15 26 +CONECT 7 6 8 17 27 +CONECT 8 5 7 9 28 +CONECT 9 8 10 19 29 +CONECT 10 4 9 11 30 +CONECT 11 10 12 20 31 +CONECT 12 3 11 13 32 +CONECT 13 12 14 18 33 +CONECT 14 2 13 15 34 +CONECT 15 6 14 16 35 +CONECT 16 15 17 18 36 +CONECT 17 7 16 19 37 +CONECT 18 13 16 20 38 +CONECT 19 9 17 20 39 +CONECT 20 11 18 19 40 +CONECT 21 1 +CONECT 22 2 +CONECT 23 3 +CONECT 24 4 +CONECT 25 5 +CONECT 26 6 +CONECT 27 7 +CONECT 28 8 +CONECT 29 9 +CONECT 30 10 +CONECT 31 11 +CONECT 32 12 +CONECT 33 13 +CONECT 34 14 +CONECT 35 15 +CONECT 36 16 +CONECT 37 17 +CONECT 38 18 +CONECT 39 19 +CONECT 40 20 +MASTER 0 0 0 0 0 0 0 0 40 0 40 0 +END diff --git a/hacks/images/molecules/dthc.pdb b/hacks/images/molecules/dthc.pdb new file mode 100644 index 00000000..d8688ac8 --- /dev/null +++ b/hacks/images/molecules/dthc.pdb @@ -0,0 +1,107 @@ +HEADER Tetrahydrocannabinol: Delta 9-THC, an hallucinogen +ATOM 1 O UNK 0 -1.791 -1.420 0.434 +ATOM 2 C UNK 0 -0.536 -1.012 0.033 +ATOM 3 C UNK 0 0.565 -1.346 0.828 +ATOM 4 C UNK 0 1.855 -0.978 0.446 +ATOM 5 C UNK 0 2.038 -0.295 -0.757 +ATOM 6 C UNK 0 0.940 0.052 -1.556 +ATOM 7 C UNK 0 -0.363 -0.272 -1.148 +ATOM 8 C UNK 0 -1.599 0.113 -1.985 +ATOM 9 C UNK 0 -1.568 1.523 -2.537 +ATOM 10 C UNK 0 -2.681 2.231 -2.781 +ATOM 11 C UNK 0 -4.068 1.708 -2.479 +ATOM 12 C UNK 0 -4.085 0.222 -2.091 +ATOM 13 C UNK 0 -2.892 -0.061 -1.162 +ATOM 14 C UNK 0 -2.908 -1.421 -0.435 +ATOM 15 O UNK 0 1.151 0.702 -2.747 +ATOM 16 C UNK 0 -2.610 3.628 -3.338 +ATOM 17 C UNK 0 -2.824 -2.642 -1.364 +ATOM 18 C UNK 0 -4.125 -1.570 0.485 +ATOM 19 C UNK 0 3.056 -1.332 1.325 +ATOM 20 C UNK 0 3.365 -0.156 2.260 +ATOM 21 C UNK 0 4.569 -0.467 3.158 +ATOM 22 C UNK 0 4.872 0.726 4.074 +ATOM 23 C UNK 0 6.079 0.425 4.969 +ATOM 24 H UNK 0 0.400 -1.896 1.747 +ATOM 25 H UNK 0 -1.626 -0.566 -2.849 +ATOM 26 H UNK 0 -4.720 1.866 -3.352 +ATOM 27 H UNK 0 -4.004 -0.399 -2.997 +ATOM 28 H UNK 0 2.079 0.837 -2.898 +ATOM 29 H UNK 0 -3.163 4.315 -2.681 +ATOM 30 H UNK 0 -2.839 -3.562 -0.762 +ATOM 31 H UNK 0 -3.995 -2.460 1.119 +ATOM 32 H UNK 0 -4.210 -0.687 1.134 +ATOM 33 H UNK 0 2.828 -2.232 1.917 +ATOM 34 H UNK 0 2.480 0.048 2.884 +ATOM 35 H UNK 0 4.349 -1.356 3.772 +ATOM 36 H UNK 0 3.994 0.938 4.706 +ATOM 37 H UNK 0 6.286 1.290 5.618 +ATOM 38 H UNK 0 3.036 -0.022 -1.076 +ATOM 39 H UNK 0 -0.602 1.973 -2.755 +ATOM 40 H UNK 0 -5.037 -0.005 -1.590 +ATOM 41 H UNK 0 -2.881 0.709 -0.374 +ATOM 42 H UNK 0 -1.565 3.966 -3.407 +ATOM 43 H UNK 0 -3.058 3.644 -4.342 +ATOM 44 H UNK 0 -1.884 -2.619 -1.933 +ATOM 45 H UNK 0 -3.674 -2.652 -2.061 +ATOM 46 H UNK 0 -5.048 -1.683 -0.102 +ATOM 47 H UNK 0 3.928 -1.546 0.687 +ATOM 48 H UNK 0 3.578 0.739 1.654 +ATOM 49 H UNK 0 5.449 -0.681 2.531 +ATOM 50 H UNK 0 5.086 1.616 3.462 +ATOM 51 H UNK 0 5.873 -0.453 5.600 +ATOM 52 H UNK 0 6.967 0.224 4.351 +ATOM 53 H UNK 0 -4.467 2.295 -1.638 +CONECT 1 2 14 +CONECT 2 1 3 7 +CONECT 3 2 4 24 +CONECT 4 3 5 19 +CONECT 5 4 6 38 +CONECT 6 5 7 15 +CONECT 7 2 6 8 +CONECT 8 7 9 13 25 +CONECT 9 8 10 39 +CONECT 10 9 11 16 +CONECT 11 10 12 26 53 +CONECT 12 11 27 40 13 +CONECT 13 8 12 41 14 +CONECT 14 1 13 17 18 +CONECT 15 6 28 +CONECT 16 10 29 42 43 +CONECT 17 14 30 44 45 +CONECT 18 14 31 32 46 +CONECT 19 4 20 33 47 +CONECT 20 19 21 34 48 +CONECT 21 20 22 35 49 +CONECT 22 21 23 36 50 +CONECT 23 22 37 51 52 +CONECT 24 3 +CONECT 25 8 +CONECT 26 11 +CONECT 27 12 +CONECT 28 15 +CONECT 29 16 +CONECT 30 17 +CONECT 31 18 +CONECT 32 18 +CONECT 33 19 +CONECT 34 20 +CONECT 35 21 +CONECT 36 22 +CONECT 37 23 +CONECT 38 5 +CONECT 39 9 +CONECT 40 12 +CONECT 41 13 +CONECT 42 16 +CONECT 43 16 +CONECT 44 17 +CONECT 45 17 +CONECT 46 18 +CONECT 47 19 +CONECT 48 20 +CONECT 49 21 +CONECT 50 22 +CONECT 51 23 +CONECT 52 23 +CONECT 53 11 diff --git a/hacks/images/molecules/dynamite.pdb b/hacks/images/molecules/dynamite.pdb new file mode 100644 index 00000000..b16dc642 --- /dev/null +++ b/hacks/images/molecules/dynamite.pdb @@ -0,0 +1,47 @@ +HEADER Trinitroglycerin: Dynamite, an explosive +COMPND jb09trin +AUTHOR Created by Dave Woodcock at Okanagan University College +AUTHOR email:woodcock@okanagan.bc.ca +AUTHOR Date revised: Tue Sep 19 21:46:02 2000 GENERATED BY BABEL 1.6 +HETATM 1 C 1 0.000 0.000 0.000 1.00 0.00 +HETATM 2 C 1 1.540 0.000 0.000 1.00 0.00 +HETATM 3 C 1 2.063 1.449 0.000 1.00 0.00 +HETATM 4 O 1 3.467 1.429 0.127 1.00 0.00 +HETATM 5 N 1 4.015 2.776 -0.152 1.00 0.00 +HETATM 6 O 1 4.998 3.268 0.635 1.00 0.00 +HETATM 7 O 1 3.773 3.351 -1.351 1.00 0.00 +HETATM 8 O 1 2.004 -0.755 1.098 1.00 0.00 +HETATM 9 N 1 2.641 -0.291 2.107 1.00 0.00 +HETATM 10 O 1 3.090 -1.154 3.047 1.00 0.00 +HETATM 11 O 1 2.879 1.030 2.268 1.00 0.00 +HETATM 12 O 1 -0.458 -1.330 -0.079 1.00 0.00 +HETATM 13 N 1 -1.911 -1.339 -0.361 1.00 0.00 +HETATM 14 O 1 -2.745 -2.029 0.450 1.00 0.00 +HETATM 15 O 1 -2.357 -0.902 -1.560 1.00 0.00 +HETATM 16 H 1 -0.365 0.561 -0.860 1.00 0.00 +HETATM 17 H 1 -0.369 0.458 0.918 1.00 0.00 +HETATM 18 H 1 1.886 -0.486 -0.912 1.00 0.00 +HETATM 19 H 1 1.620 2.013 0.821 1.00 0.00 +HETATM 20 H 1 1.793 1.925 -0.943 1.00 0.00 +CONECT 1 2 12 16 17 +CONECT 2 1 3 8 18 +CONECT 3 2 4 19 20 +CONECT 4 3 5 +CONECT 5 4 6 7 +CONECT 6 5 +CONECT 7 5 +CONECT 8 2 9 +CONECT 9 8 10 11 +CONECT 10 9 +CONECT 11 9 +CONECT 12 1 13 +CONECT 13 12 14 15 +CONECT 14 13 +CONECT 15 13 +CONECT 16 1 +CONECT 17 1 +CONECT 18 2 +CONECT 19 3 +CONECT 20 3 +MASTER 0 0 0 0 0 0 0 0 20 0 20 0 +END diff --git a/hacks/images/molecules/glycol.pdb b/hacks/images/molecules/glycol.pdb new file mode 100644 index 00000000..202d0e12 --- /dev/null +++ b/hacks/images/molecules/glycol.pdb @@ -0,0 +1,27 @@ +HEADER Ethylene Glycol: Ethane-1,2-diol, Anti-freeze +COMPND al2034 +AUTHOR Created by Dave Woodcock at Okanagan University College +AUTHOR email:woodcock@okanagan.bc.ca +AUTHOR Date revised: Tue Aug 29 17:54:52 2000 GENERATED BY BABEL 1.6 +HETATM 1 C 1 0.000 0.000 0.000 1.00 0.00 +HETATM 2 C 1 1.542 0.000 0.000 1.00 0.00 +HETATM 3 O 1 2.027 1.347 0.000 1.00 0.00 +HETATM 4 O 1 -0.485 -1.347 -0.041 1.00 0.00 +HETATM 5 H 1 -0.360 0.537 -0.878 1.00 0.00 +HETATM 6 H 1 -0.367 0.494 0.900 1.00 0.00 +HETATM 7 H 1 1.902 -0.512 -0.893 1.00 0.00 +HETATM 8 H 1 1.908 -0.520 0.885 1.00 0.00 +HETATM 9 H 1 1.743 1.800 0.802 1.00 0.00 +HETATM 10 H 1 -0.202 -1.823 0.747 1.00 0.00 +CONECT 1 2 4 5 6 +CONECT 2 1 3 7 8 +CONECT 3 2 9 +CONECT 4 1 10 +CONECT 5 1 +CONECT 6 1 +CONECT 7 2 +CONECT 8 2 +CONECT 9 3 +CONECT 10 4 +MASTER 0 0 0 0 0 0 0 0 10 0 10 0 +END diff --git a/hacks/images/molecules/guanine.pdb b/hacks/images/molecules/guanine.pdb new file mode 100644 index 00000000..229b6545 --- /dev/null +++ b/hacks/images/molecules/guanine.pdb @@ -0,0 +1,39 @@ +HEADER Guanine: Purine base nucleotide +COMPND jb09guan +AUTHOR Created by Dave Woodcock at Okanagan University College +AUTHOR email:woodcock@okanagan.bc.ca +AUTHOR Date revised: Tue Sep 19 21:46:02 2000 GENERATED BY BABEL 1.6 +HETATM 1 C 1 0.000 0.000 0.000 1.00 0.00 +HETATM 2 C 1 1.392 0.000 0.000 1.00 0.00 +HETATM 3 C 1 2.082 1.215 0.000 1.00 0.00 +HETATM 4 N 1 1.339 2.346 -0.001 1.00 0.00 +HETATM 5 C 1 -0.017 2.313 -0.003 1.00 0.00 +HETATM 6 N 1 -0.709 1.149 -0.003 1.00 0.00 +HETATM 7 N 1 -0.392 -1.291 -0.028 1.00 0.00 +HETATM 8 C 1 0.730 -2.047 -0.044 1.00 0.00 +HETATM 9 N 1 1.842 -1.275 -0.028 1.00 0.00 +HETATM 10 O 1 3.285 1.253 -0.010 1.00 0.00 +HETATM 11 N 1 -0.723 3.523 -0.019 1.00 0.00 +HETATM 12 H 1 1.811 3.244 -0.007 1.00 0.00 +HETATM 13 H 1 -1.347 -1.629 -0.048 1.00 0.00 +HETATM 14 H 1 0.738 -3.137 -0.077 1.00 0.00 +HETATM 15 H 1 -1.640 3.377 -0.427 1.00 0.00 +HETATM 16 H 1 -0.213 4.205 -0.570 1.00 0.00 +CONECT 1 2 2 6 7 +CONECT 2 1 1 3 9 +CONECT 3 2 4 10 10 +CONECT 4 3 5 12 +CONECT 5 4 6 6 11 +CONECT 6 1 5 5 +CONECT 7 1 8 13 +CONECT 8 7 9 9 14 +CONECT 9 2 8 8 +CONECT 10 3 3 +CONECT 11 5 15 16 +CONECT 12 4 +CONECT 13 7 +CONECT 14 8 +CONECT 15 11 +CONECT 16 11 +MASTER 0 0 0 0 0 0 0 0 16 0 16 0 +END diff --git a/hacks/images/molecules/heroin.pdb b/hacks/images/molecules/heroin.pdb new file mode 100644 index 00000000..ddb4014d --- /dev/null +++ b/hacks/images/molecules/heroin.pdb @@ -0,0 +1,107 @@ +HEADER Diacetylmorphine: Heroin, an opiate +COMPND al3084 +AUTHOR Created by Dave Woodcock at Okanagan University College +AUTHOR email:woodcock@okanagan.bc.ca +AUTHOR Date revised: Wed Aug 30 12:33:12 2000 GENERATED BY BABEL 1.6 +HETATM 1 C 1 0.000 0.000 0.000 1.00 0.00 +HETATM 2 C 1 1.400 0.000 0.000 1.00 0.00 +HETATM 3 C 1 2.108 1.210 0.000 1.00 0.00 +HETATM 4 C 1 1.452 2.447 -0.065 1.00 0.00 +HETATM 5 C 1 0.055 2.457 -0.018 1.00 0.00 +HETATM 6 C 1 -0.624 1.244 0.041 1.00 0.00 +HETATM 7 C 1 -2.081 1.501 -0.201 1.00 0.00 +HETATM 8 C 1 -2.725 0.343 -0.973 1.00 0.00 +HETATM 9 C 1 -2.367 -0.953 -0.210 1.00 0.00 +HETATM 10 C 1 -0.836 -1.236 -0.253 1.00 0.00 +HETATM 11 C 1 -1.913 2.852 -0.934 1.00 0.00 +HETATM 12 C 1 -2.752 1.623 1.177 1.00 0.00 +HETATM 13 C 1 -2.503 0.306 1.943 1.00 0.00 +HETATM 14 N 1 -2.936 -0.856 1.147 1.00 0.00 +HETATM 15 C 1 -2.820 -2.103 1.920 1.00 0.00 +HETATM 16 H 1 -3.807 0.473 -0.972 1.00 0.00 +HETATM 17 C 1 -2.256 0.283 -2.408 1.00 0.00 +HETATM 18 C 1 -1.948 1.398 -3.085 1.00 0.00 +HETATM 19 C 1 -1.494 2.675 -2.413 1.00 0.00 +HETATM 20 H 1 -2.820 3.452 -0.859 1.00 0.00 +HETATM 21 O 1 -0.799 3.480 -0.318 1.00 0.00 +HETATM 22 H 1 -1.885 3.520 -2.982 1.00 0.00 +HETATM 23 O 1 -0.083 2.674 -2.462 1.00 0.00 +HETATM 24 O 1 2.142 3.620 -0.142 1.00 0.00 +HETATM 25 H 1 1.942 -0.945 -0.044 1.00 0.00 +HETATM 26 H 1 3.198 1.180 -0.006 1.00 0.00 +HETATM 27 H 1 -2.866 -1.782 -0.712 1.00 0.00 +HETATM 28 H 1 -0.588 -1.599 -1.250 1.00 0.00 +HETATM 29 H 1 -0.574 -2.010 0.465 1.00 0.00 +HETATM 30 H 1 -3.823 1.785 1.052 1.00 0.00 +HETATM 31 H 1 -2.320 2.456 1.731 1.00 0.00 +HETATM 32 H 1 -3.068 0.334 2.874 1.00 0.00 +HETATM 33 H 1 -1.444 0.211 2.184 1.00 0.00 +HETATM 34 H 1 -3.492 -2.057 2.778 1.00 0.00 +HETATM 35 H 1 -1.799 -2.234 2.280 1.00 0.00 +HETATM 36 H 1 -3.099 -2.953 1.298 1.00 0.00 +HETATM 37 H 1 -2.414 -0.639 -2.967 1.00 0.00 +HETATM 38 H 1 -1.797 1.313 -4.161 1.00 0.00 +HETATM 39 C 1 3.076 3.567 -1.091 1.00 0.00 +HETATM 40 O 1 2.786 3.826 -2.230 1.00 0.00 +HETATM 41 C 1 4.523 3.509 -0.695 1.00 0.00 +HETATM 42 H 1 5.012 2.691 -1.224 1.00 0.00 +HETATM 43 H 1 4.600 3.345 0.380 1.00 0.00 +HETATM 44 H 1 5.008 4.450 -0.954 1.00 0.00 +HETATM 45 C 1 0.390 3.733 -3.117 1.00 0.00 +HETATM 46 O 1 0.845 3.595 -4.223 1.00 0.00 +HETATM 47 C 1 0.417 5.083 -2.459 1.00 0.00 +HETATM 48 H 1 1.199 5.692 -2.913 1.00 0.00 +HETATM 49 H 1 0.619 4.970 -1.395 1.00 0.00 +HETATM 50 H 1 -0.547 5.574 -2.594 1.00 0.00 +CONECT 1 2 2 6 10 +CONECT 2 1 1 3 25 +CONECT 3 2 4 4 26 +CONECT 4 3 3 5 24 +CONECT 5 4 6 6 21 +CONECT 6 1 5 5 7 +CONECT 7 6 8 11 12 +CONECT 8 7 9 16 17 +CONECT 9 8 10 14 27 +CONECT 10 1 9 28 29 +CONECT 11 7 19 20 21 +CONECT 12 7 13 30 31 +CONECT 13 12 14 32 33 +CONECT 14 9 13 15 +CONECT 15 14 34 35 36 +CONECT 16 8 +CONECT 17 8 18 18 37 +CONECT 18 17 17 19 38 +CONECT 19 11 18 22 23 +CONECT 20 11 +CONECT 21 5 11 +CONECT 22 19 +CONECT 23 19 45 +CONECT 24 4 39 +CONECT 25 2 +CONECT 26 3 +CONECT 27 9 +CONECT 28 10 +CONECT 29 10 +CONECT 30 12 +CONECT 31 12 +CONECT 32 13 +CONECT 33 13 +CONECT 34 15 +CONECT 35 15 +CONECT 36 15 +CONECT 37 17 +CONECT 38 18 +CONECT 39 24 40 40 41 +CONECT 40 39 39 +CONECT 41 39 42 43 44 +CONECT 42 41 +CONECT 43 41 +CONECT 44 41 +CONECT 45 23 46 46 47 +CONECT 46 45 45 +CONECT 47 45 48 49 50 +CONECT 48 47 +CONECT 49 47 +CONECT 50 47 +MASTER 0 0 0 0 0 0 0 0 50 0 50 0 +END diff --git a/hacks/images/molecules/hexahelicene.pdb b/hacks/images/molecules/hexahelicene.pdb new file mode 100644 index 00000000..52162c51 --- /dev/null +++ b/hacks/images/molecules/hexahelicene.pdb @@ -0,0 +1,90 @@ +COMPND Hexahelicene +AUTHOR Created by Dave Woodcock at Okanagan University College +AUTHOR email:woodcock@okanagan.bc.ca +AUTHOR Date revised: Fri Sep 1 09:41:05 2000 GENERATED BY BABEL 1.6 +HETATM 1 C 1 0.000 0.000 0.000 1.00 0.00 +HETATM 2 C 1 1.404 0.000 0.000 1.00 0.00 +HETATM 3 C 1 2.104 1.206 0.000 1.00 0.00 +HETATM 4 C 1 1.402 2.413 -0.064 1.00 0.00 +HETATM 5 C 1 0.002 2.407 -0.063 1.00 0.00 +HETATM 6 C 1 -0.705 1.209 0.071 1.00 0.00 +HETATM 7 C 1 -2.102 1.180 0.220 1.00 0.00 +HETATM 8 C 1 -2.847 2.295 0.643 1.00 0.00 +HETATM 9 C 1 -4.192 2.360 0.266 1.00 0.00 +HETATM 10 C 1 -4.858 1.229 -0.190 1.00 0.00 +HETATM 11 C 1 -4.166 0.012 -0.273 1.00 0.00 +HETATM 12 C 1 -2.782 -0.001 -0.086 1.00 0.00 +HETATM 13 C 1 -2.082 -1.204 -0.224 1.00 0.00 +HETATM 14 C 1 -0.685 -1.210 -0.107 1.00 0.00 +HETATM 15 C 1 -2.318 3.332 1.420 1.00 0.00 +HETATM 16 C 1 -1.206 3.177 2.264 1.00 0.00 +HETATM 17 C 1 -0.519 4.289 2.729 1.00 0.00 +HETATM 18 C 1 -1.052 5.582 2.503 1.00 0.00 +HETATM 19 C 1 -2.286 5.716 1.895 1.00 0.00 +HETATM 20 C 1 -2.936 4.583 1.371 1.00 0.00 +HETATM 21 C 1 -4.216 4.717 0.815 1.00 0.00 +HETATM 22 C 1 -4.881 3.585 0.350 1.00 0.00 +HETATM 23 C 1 -0.789 1.905 2.707 1.00 0.00 +HETATM 24 C 1 0.400 1.759 3.421 1.00 0.00 +HETATM 25 C 1 1.155 2.887 3.765 1.00 0.00 +HETATM 26 C 1 0.669 4.165 3.443 1.00 0.00 +HETATM 27 H 1 1.945 -0.947 -0.019 1.00 0.00 +HETATM 28 H 1 3.191 1.206 -0.002 1.00 0.00 +HETATM 29 H 1 1.942 3.359 -0.131 1.00 0.00 +HETATM 30 H 1 -0.523 3.350 -0.198 1.00 0.00 +HETATM 31 H 1 -5.918 1.264 -0.433 1.00 0.00 +HETATM 32 H 1 -4.698 -0.901 -0.555 1.00 0.00 +HETATM 33 H 1 -2.617 -2.140 -0.409 1.00 0.00 +HETATM 34 H 1 -0.142 -2.150 -0.180 1.00 0.00 +HETATM 35 H 1 -0.520 6.457 2.886 1.00 0.00 +HETATM 36 H 1 -2.751 6.690 1.806 1.00 0.00 +HETATM 37 H 1 -4.715 5.680 0.815 1.00 0.00 +HETATM 38 H 1 -5.917 3.654 0.008 1.00 0.00 +HETATM 39 H 1 -1.407 1.021 2.524 1.00 0.00 +HETATM 40 H 1 0.734 0.774 3.725 1.00 0.00 +HETATM 41 H 1 2.090 2.777 4.328 1.00 0.00 +HETATM 42 H 1 1.225 5.042 3.772 1.00 0.00 +CONECT 1 2 2 6 14 +CONECT 2 1 1 3 27 +CONECT 3 2 4 4 28 +CONECT 4 3 3 5 29 +CONECT 5 4 6 6 30 +CONECT 6 1 5 5 7 +CONECT 7 6 8 8 12 +CONECT 8 7 7 9 15 +CONECT 9 8 10 10 22 +CONECT 10 9 9 11 31 +CONECT 11 10 12 12 32 +CONECT 12 7 11 11 13 +CONECT 13 12 14 14 33 +CONECT 14 1 13 13 34 +CONECT 15 8 16 16 20 +CONECT 16 15 15 17 23 +CONECT 17 16 18 18 26 +CONECT 18 17 17 19 35 +CONECT 19 18 20 20 36 +CONECT 20 15 19 19 21 +CONECT 21 20 22 22 37 +CONECT 22 9 21 21 38 +CONECT 23 16 24 24 39 +CONECT 24 23 23 25 40 +CONECT 25 24 26 26 41 +CONECT 26 17 25 25 42 +CONECT 27 2 +CONECT 28 3 +CONECT 29 4 +CONECT 30 5 +CONECT 31 10 +CONECT 32 11 +CONECT 33 13 +CONECT 34 14 +CONECT 35 18 +CONECT 36 19 +CONECT 37 21 +CONECT 38 22 +CONECT 39 23 +CONECT 40 24 +CONECT 41 25 +CONECT 42 26 +MASTER 0 0 0 0 0 0 0 0 42 0 42 0 +END diff --git a/hacks/images/molecules/ibuprofen.pdb b/hacks/images/molecules/ibuprofen.pdb new file mode 100644 index 00000000..48d3dbae --- /dev/null +++ b/hacks/images/molecules/ibuprofen.pdb @@ -0,0 +1,72 @@ +HEADER Ibuprofen: Advil/Motrin, an anti-inflammatory +AUTHOR Created by Dave Woodcock at Okanagan University College +AUTHOR email:woodcock@okanagan.bc.ca +AUTHOR Date revised: Fri Sep 1 09:41:05 2000 GENERATED BY BABEL 1.6 +HETATM 1 C 1 0.000 0.000 0.000 1.00 0.00 +HETATM 2 C 1 1.399 0.000 0.000 1.00 0.00 +HETATM 3 C 1 2.098 1.212 0.000 1.00 0.00 +HETATM 4 C 1 1.391 2.419 0.004 1.00 0.00 +HETATM 5 C 1 -0.008 2.417 0.005 1.00 0.00 +HETATM 6 C 1 -0.712 1.206 -0.003 1.00 0.00 +HETATM 7 C 1 -2.224 1.136 -0.009 1.00 0.00 +HETATM 8 C 1 -2.900 2.504 -0.232 1.00 0.00 +HETATM 9 C 1 3.611 1.210 -0.042 1.00 0.00 +HETATM 10 C 1 4.094 0.909 -1.477 1.00 0.00 +HETATM 11 C 1 5.635 0.868 -1.503 1.00 0.00 +HETATM 12 C 1 3.590 1.996 -2.450 1.00 0.00 +HETATM 13 C 1 -2.686 0.573 1.305 1.00 0.00 +HETATM 14 O 1 -3.846 0.297 1.466 1.00 0.00 +HETATM 15 O 1 -1.792 0.321 2.277 1.00 0.00 +HETATM 16 H 1 -0.539 -0.948 -0.004 1.00 0.00 +HETATM 17 H 1 1.943 -0.945 -0.009 1.00 0.00 +HETATM 18 H 1 1.930 3.366 -0.006 1.00 0.00 +HETATM 19 H 1 -0.533 3.371 0.004 1.00 0.00 +HETATM 20 H 1 -2.536 0.461 -0.807 1.00 0.00 +HETATM 21 H 1 -2.546 2.944 -1.165 1.00 0.00 +HETATM 22 H 1 -2.676 3.171 0.600 1.00 0.00 +HETATM 23 H 1 -3.980 2.365 -0.292 1.00 0.00 +HETATM 24 H 1 3.986 0.442 0.635 1.00 0.00 +HETATM 25 H 1 3.990 2.181 0.277 1.00 0.00 +HETATM 26 H 1 3.707 -0.061 -1.792 1.00 0.00 +HETATM 27 H 1 5.991 0.094 -0.823 1.00 0.00 +HETATM 28 H 1 6.034 1.834 -1.192 1.00 0.00 +HETATM 29 H 1 5.978 0.645 -2.513 1.00 0.00 +HETATM 30 H 1 3.941 2.975 -2.122 1.00 0.00 +HETATM 31 H 1 2.500 1.993 -2.477 1.00 0.00 +HETATM 32 H 1 3.970 1.793 -3.451 1.00 0.00 +HETATM 33 H 1 -1.689 -0.648 2.383 1.00 0.00 +CONECT 1 2 2 6 16 +CONECT 2 1 1 3 17 +CONECT 3 2 4 4 9 +CONECT 4 3 3 5 18 +CONECT 5 4 6 6 19 +CONECT 6 1 5 5 7 +CONECT 7 6 8 13 20 +CONECT 8 7 21 22 23 +CONECT 9 3 10 24 25 +CONECT 10 9 11 12 26 +CONECT 11 10 27 28 29 +CONECT 12 10 30 31 32 +CONECT 13 7 14 14 15 +CONECT 14 13 13 +CONECT 15 13 33 +CONECT 16 1 +CONECT 17 2 +CONECT 18 4 +CONECT 19 5 +CONECT 20 7 +CONECT 21 8 +CONECT 22 8 +CONECT 23 8 +CONECT 24 9 +CONECT 25 9 +CONECT 26 10 +CONECT 27 11 +CONECT 28 11 +CONECT 29 11 +CONECT 30 12 +CONECT 31 12 +CONECT 32 12 +CONECT 33 15 +MASTER 0 0 0 0 0 0 0 0 33 0 33 0 +END diff --git a/hacks/images/molecules/lsd.pdb b/hacks/images/molecules/lsd.pdb new file mode 100644 index 00000000..7d248303 --- /dev/null +++ b/hacks/images/molecules/lsd.pdb @@ -0,0 +1,104 @@ +HEADER Lysergic acid diethylamide, a potent hallucinogen +AUTHOR Created by Dave Woodcock at Okanagan University College +AUTHOR email:woodcock@okanagan.bc.ca +AUTHOR Date revised: Fri Sep 1 09:41:05 2000 GENERATED BY BABEL 1.6 +HETATM 1 C 1 0.000 0.000 0.000 1.00 0.00 +HETATM 2 C 1 1.397 0.000 0.000 1.00 0.00 +HETATM 3 C 1 2.012 1.258 0.000 1.00 0.00 +HETATM 4 C 1 1.246 2.433 -0.052 1.00 0.00 +HETATM 5 C 1 -0.155 2.405 -0.125 1.00 0.00 +HETATM 6 C 1 -0.773 1.155 -0.096 1.00 0.00 +HETATM 7 N 1 -2.065 0.769 -0.378 1.00 0.00 +HETATM 8 C 1 -2.092 -0.602 -0.503 1.00 0.00 +HETATM 9 C 1 -0.810 -1.103 -0.242 1.00 0.00 +HETATM 10 C 1 -0.159 -2.415 -0.700 1.00 0.00 +HETATM 11 C 1 1.178 -2.555 0.075 1.00 0.00 +HETATM 12 C 1 2.056 -1.321 -0.019 1.00 0.00 +HETATM 13 H 1 0.916 -2.675 1.126 1.00 0.00 +HETATM 14 N 1 1.899 -3.768 -0.346 1.00 0.00 +HETATM 15 C 1 3.394 -1.430 0.057 1.00 0.00 +HETATM 16 C 1 4.101 -2.765 0.134 1.00 0.00 +HETATM 17 C 1 3.115 -3.899 0.470 1.00 0.00 +HETATM 18 H 1 4.565 -2.960 -0.830 1.00 0.00 +HETATM 19 C 1 5.121 -2.704 1.237 1.00 0.00 +HETATM 20 O 1 4.720 -2.413 2.335 1.00 0.00 +HETATM 21 N 1 6.434 -3.000 1.089 1.00 0.00 +HETATM 22 C 1 7.305 -2.925 2.274 1.00 0.00 +HETATM 23 C 1 7.755 -4.340 2.686 1.00 0.00 +HETATM 24 C 1 7.047 -3.307 -0.215 1.00 0.00 +HETATM 25 C 1 6.736 -4.755 -0.646 1.00 0.00 +HETATM 26 H 1 3.094 1.350 0.014 1.00 0.00 +HETATM 27 H 1 1.757 3.398 -0.079 1.00 0.00 +HETATM 28 H 1 -0.732 3.319 -0.249 1.00 0.00 +HETATM 29 H 1 -2.858 1.432 -0.658 1.00 0.00 +HETATM 30 H 1 -2.917 -1.177 -0.924 1.00 0.00 +HETATM 31 H 1 0.025 -2.349 -1.772 1.00 0.00 +HETATM 32 H 1 -0.811 -3.260 -0.484 1.00 0.00 +HETATM 33 H 1 4.015 -0.538 0.044 1.00 0.00 +HETATM 34 H 1 2.844 -3.840 1.524 1.00 0.00 +HETATM 35 H 1 3.586 -4.865 0.286 1.00 0.00 +HETATM 36 H 1 6.768 -2.468 3.105 1.00 0.00 +HETATM 37 H 1 8.181 -2.318 2.047 1.00 0.00 +HETATM 38 H 1 8.376 -4.772 1.903 1.00 0.00 +HETATM 39 H 1 6.879 -4.969 2.844 1.00 0.00 +HETATM 40 H 1 8.332 -4.283 3.609 1.00 0.00 +HETATM 41 H 1 8.129 -3.199 -0.132 1.00 0.00 +HETATM 42 H 1 6.693 -2.606 -0.971 1.00 0.00 +HETATM 43 H 1 5.663 -4.894 -0.765 1.00 0.00 +HETATM 44 H 1 7.103 -5.451 0.107 1.00 0.00 +HETATM 45 H 1 7.230 -4.962 -1.595 1.00 0.00 +HETATM 46 C 1 2.198 -3.813 -1.786 1.00 0.00 +HETATM 47 H 1 2.586 -2.854 -2.128 1.00 0.00 +HETATM 48 H 1 1.292 -4.053 -2.342 1.00 0.00 +HETATM 49 H 1 2.936 -4.591 -1.982 1.00 0.00 +CONECT 1 2 2 6 9 +CONECT 2 1 1 3 12 +CONECT 3 2 4 4 26 +CONECT 4 3 3 5 27 +CONECT 5 4 6 6 28 +CONECT 6 1 5 5 7 +CONECT 7 6 8 29 +CONECT 8 7 9 9 30 +CONECT 9 1 8 8 10 +CONECT 10 9 11 31 32 +CONECT 11 10 12 13 14 +CONECT 12 2 11 15 15 +CONECT 13 11 +CONECT 14 11 17 46 +CONECT 15 12 12 16 33 +CONECT 16 15 17 18 19 +CONECT 17 14 16 34 35 +CONECT 18 16 +CONECT 19 16 20 20 21 +CONECT 20 19 19 +CONECT 21 19 22 24 +CONECT 22 21 23 36 37 +CONECT 23 22 38 39 40 +CONECT 24 21 25 41 42 +CONECT 25 24 43 44 45 +CONECT 26 3 +CONECT 27 4 +CONECT 28 5 +CONECT 29 7 +CONECT 30 8 +CONECT 31 10 +CONECT 32 10 +CONECT 33 15 +CONECT 34 17 +CONECT 35 17 +CONECT 36 22 +CONECT 37 22 +CONECT 38 23 +CONECT 39 23 +CONECT 40 23 +CONECT 41 24 +CONECT 42 24 +CONECT 43 25 +CONECT 44 25 +CONECT 45 25 +CONECT 46 14 47 48 49 +CONECT 47 46 +CONECT 48 46 +CONECT 49 46 +MASTER 0 0 0 0 0 0 0 0 49 0 49 0 +END diff --git a/hacks/images/molecules/menthol.pdb b/hacks/images/molecules/menthol.pdb new file mode 100644 index 00000000..c4186885 --- /dev/null +++ b/hacks/images/molecules/menthol.pdb @@ -0,0 +1,69 @@ +HEADER Menthol: Mentha arvensis oil +COMPND menthol +AUTHOR Created by Dave Woodcock at Okanagan University College +AUTHOR email:woodcock@okanagan.bc.ca +AUTHOR Date revised: Fri Sep 1 09:41:05 2000 GENERATED BY BABEL 1.6 +HETATM 1 C 1 0.000 0.000 0.000 1.00 0.00 +HETATM 2 O 1 1.431 0.000 0.000 1.00 0.00 +HETATM 3 C 1 -0.501 1.458 0.000 1.00 0.00 +HETATM 4 C 1 -2.042 1.485 -0.004 1.00 0.00 +HETATM 5 C 1 -2.576 0.746 1.240 1.00 0.00 +HETATM 6 C 1 -2.072 -0.710 1.236 1.00 0.00 +HETATM 7 C 1 -0.528 -0.726 1.258 1.00 0.00 +HETATM 8 C 1 -0.005 -2.181 1.381 1.00 0.00 +HETATM 9 C 1 1.486 -2.197 1.780 1.00 0.00 +HETATM 10 C 1 -0.183 -2.997 0.081 1.00 0.00 +HETATM 11 C 1 -2.539 2.945 0.003 1.00 0.00 +HETATM 12 H 1 -0.367 -0.497 -0.898 1.00 0.00 +HETATM 13 H 1 1.761 0.410 -0.806 1.00 0.00 +HETATM 14 H 1 -0.129 1.968 -0.889 1.00 0.00 +HETATM 15 H 1 -0.127 1.969 0.888 1.00 0.00 +HETATM 16 H 1 -2.409 0.987 -0.903 1.00 0.00 +HETATM 17 H 1 -3.666 0.750 1.224 1.00 0.00 +HETATM 18 H 1 -2.229 1.249 2.142 1.00 0.00 +HETATM 19 H 1 -2.440 -1.211 0.342 1.00 0.00 +HETATM 20 H 1 -2.455 -1.222 2.119 1.00 0.00 +HETATM 21 H 1 -0.200 -0.175 2.139 1.00 0.00 +HETATM 22 H 1 -0.565 -2.673 2.176 1.00 0.00 +HETATM 23 H 1 1.633 -1.600 2.680 1.00 0.00 +HETATM 24 H 1 2.100 -1.796 0.975 1.00 0.00 +HETATM 25 H 1 1.794 -3.223 1.980 1.00 0.00 +HETATM 26 H 1 0.434 -2.578 -0.713 1.00 0.00 +HETATM 27 H 1 -1.228 -2.993 -0.228 1.00 0.00 +HETATM 28 H 1 0.127 -4.026 0.261 1.00 0.00 +HETATM 29 H 1 -2.165 3.462 -0.880 1.00 0.00 +HETATM 30 H 1 -2.178 3.451 0.898 1.00 0.00 +HETATM 31 H 1 -3.629 2.960 -0.005 1.00 0.00 +CONECT 1 2 3 7 12 +CONECT 2 1 13 +CONECT 3 1 4 14 15 +CONECT 4 3 5 11 16 +CONECT 5 4 6 17 18 +CONECT 6 5 7 19 20 +CONECT 7 1 6 8 21 +CONECT 8 7 9 10 22 +CONECT 9 8 23 24 25 +CONECT 10 8 26 27 28 +CONECT 11 4 29 30 31 +CONECT 12 1 +CONECT 13 2 +CONECT 14 3 +CONECT 15 3 +CONECT 16 4 +CONECT 17 5 +CONECT 18 5 +CONECT 19 6 +CONECT 20 6 +CONECT 21 7 +CONECT 22 8 +CONECT 23 9 +CONECT 24 9 +CONECT 25 9 +CONECT 26 10 +CONECT 27 10 +CONECT 28 10 +CONECT 29 11 +CONECT 30 11 +CONECT 31 11 +MASTER 0 0 0 0 0 0 0 0 31 0 31 0 +END diff --git a/hacks/images/molecules/mescaline.pdb b/hacks/images/molecules/mescaline.pdb new file mode 100644 index 00000000..7143a221 --- /dev/null +++ b/hacks/images/molecules/mescaline.pdb @@ -0,0 +1,71 @@ +HEADER Mescaline: Peyote, an hallucinogen +COMPND jb12mesc +AUTHOR Created by Dave Woodcock at Okanagan University College +AUTHOR email:woodcock@okanagan.bc.ca +AUTHOR Date revised: Wed Sep 20 16:26:54 2000 GENERATED BY BABEL 1.6 +HETATM 1 C 1 0.000 0.000 0.000 1.00 0.00 +HETATM 2 C 1 1.398 0.000 0.000 1.00 0.00 +HETATM 3 C 1 2.098 1.213 0.000 1.00 0.00 +HETATM 4 C 1 1.399 2.424 -0.005 1.00 0.00 +HETATM 5 C 1 -0.001 2.422 0.013 1.00 0.00 +HETATM 6 C 1 -0.700 1.211 0.014 1.00 0.00 +HETATM 7 O 1 -2.062 1.209 0.026 1.00 0.00 +HETATM 8 C 1 -2.564 1.047 -1.282 1.00 0.00 +HETATM 9 O 1 -0.682 -1.180 -0.024 1.00 0.00 +HETATM 10 C 1 -0.867 -1.664 1.288 1.00 0.00 +HETATM 11 O 1 2.078 -1.180 -0.002 1.00 0.00 +HETATM 12 C 1 2.225 -1.657 -1.321 1.00 0.00 +HETATM 13 C 1 2.154 3.735 -0.007 1.00 0.00 +HETATM 14 C 1 2.388 4.190 1.447 1.00 0.00 +HETATM 15 N 1 3.124 5.464 1.464 1.00 0.00 +HETATM 16 H 1 3.188 1.207 0.000 1.00 0.00 +HETATM 17 H 1 -0.549 3.364 0.023 1.00 0.00 +HETATM 18 H 1 -2.231 0.093 -1.690 1.00 0.00 +HETATM 19 H 1 -2.208 1.859 -1.916 1.00 0.00 +HETATM 20 H 1 -3.653 1.064 -1.252 1.00 0.00 +HETATM 21 H 1 -1.432 -0.938 1.873 1.00 0.00 +HETATM 22 H 1 0.101 -1.837 1.758 1.00 0.00 +HETATM 23 H 1 -1.419 -2.603 1.248 1.00 0.00 +HETATM 24 H 1 2.775 -0.929 -1.917 1.00 0.00 +HETATM 25 H 1 1.244 -1.825 -1.765 1.00 0.00 +HETATM 26 H 1 2.777 -2.597 -1.303 1.00 0.00 +HETATM 27 H 1 1.574 4.490 -0.538 1.00 0.00 +HETATM 28 H 1 3.114 3.603 -0.507 1.00 0.00 +HETATM 29 H 1 2.966 3.432 1.976 1.00 0.00 +HETATM 30 H 1 1.427 4.321 1.944 1.00 0.00 +HETATM 31 H 1 2.590 6.179 0.982 1.00 0.00 +HETATM 32 H 1 4.024 5.350 1.012 1.00 0.00 +CONECT 1 2 2 6 9 +CONECT 2 1 1 3 11 +CONECT 3 2 4 4 16 +CONECT 4 3 3 5 13 +CONECT 5 4 6 6 17 +CONECT 6 1 5 5 7 +CONECT 7 6 8 +CONECT 8 7 18 19 20 +CONECT 9 1 10 +CONECT 10 9 21 22 23 +CONECT 11 2 12 +CONECT 12 11 24 25 26 +CONECT 13 4 14 27 28 +CONECT 14 13 15 29 30 +CONECT 15 14 31 32 +CONECT 16 3 +CONECT 17 5 +CONECT 18 8 +CONECT 19 8 +CONECT 20 8 +CONECT 21 10 +CONECT 22 10 +CONECT 23 10 +CONECT 24 12 +CONECT 25 12 +CONECT 26 12 +CONECT 27 13 +CONECT 28 13 +CONECT 29 14 +CONECT 30 14 +CONECT 31 15 +CONECT 32 15 +MASTER 0 0 0 0 0 0 0 0 32 0 32 0 +END diff --git a/hacks/images/molecules/methamphetamine.pdb b/hacks/images/molecules/methamphetamine.pdb new file mode 100644 index 00000000..0cf567d8 --- /dev/null +++ b/hacks/images/molecules/methamphetamine.pdb @@ -0,0 +1,88 @@ +HEADER Methamphetamine: D-Desoxyephedrine +ORIGX1 1.000000 0.000000 0.000000 0.00000 +ORIGX2 0.000000 1.000000 0.000000 0.00000 +ORIGX3 0.000000 0.000000 1.000000 0.00000 +SCALE1 0.100000 0.000000 0.000000 0.00000 +SCALE2 0.000000 0.100000 0.000000 0.00000 +SCALE3 0.000000 0.000000 0.100000 0.00000 +ATOM 1 C 1 0.729 4.473 -1.914 1.00 0.00 +ATOM 2 C 1 -0.451 3.821 -2.014 1.00 0.00 +ATOM 3 C 1 -0.995 3.421 -3.398 1.00 0.00 +ATOM 4 C 1 -0.293 3.722 -4.513 1.00 0.00 +ATOM 5 C 1 1.052 4.465 -4.399 1.00 0.00 +ATOM 6 C 1 1.529 4.816 -3.184 1.00 0.00 +ATOM 7 H 1 1.115 4.756 -0.934 1.00 0.00 +ATOM 8 C 1 -1.251 3.478 -0.743 1.00 0.00 +ATOM 9 H 1 -1.947 2.896 -3.478 1.00 0.00 +ATOM 10 H 1 -0.678 3.440 -5.492 1.00 0.00 +ATOM 11 H 1 1.618 4.708 -5.298 1.00 0.00 +ATOM 12 H 1 2.481 5.342 -3.104 1.00 0.00 +ATOM 13 C 1 -0.489 3.986 0.496 1.00 0.00 +ATOM 14 N 1 -1.279 3.647 1.750 1.00 0.00 +ATOM 15 H 1 -1.378 2.398 -0.674 1.00 0.00 +ATOM 19 H 1 -2.229 3.957 -0.790 1.00 0.00 +ATOM 20 H 1 0.489 3.507 0.542 1.00 0.00 +ATOM 21 C 1 -0.310 5.512 0.398 1.00 0.00 +ATOM 22 H 1 -1.403 2.587 1.817 1.00 0.00 +ATOM 23 C 1 -0.528 4.148 2.972 1.00 0.00 +ATOM 24 H 1 -0.401 5.229 2.903 1.00 0.00 +ATOM 25 H 1 0.451 3.670 3.019 1.00 0.00 +ATOM 26 H 1 -1.094 3.905 3.871 1.00 0.00 +ATOM 27 H 1 0.229 5.871 1.275 1.00 0.00 +ATOM 28 H 1 -1.288 5.991 0.352 1.00 0.00 +ATOM 29 H 1 0.256 5.755 -0.501 1.00 0.00 +TER 30 +CONECT 1 2 +CONECT 2 1 +CONECT 2 3 +CONECT 3 2 +CONECT 3 4 +CONECT 4 3 +CONECT 4 5 +CONECT 5 4 +CONECT 5 6 +CONECT 6 5 +CONECT 6 1 +CONECT 1 6 +CONECT 1 7 +CONECT 7 1 +CONECT 2 8 +CONECT 8 2 +CONECT 3 9 +CONECT 9 3 +CONECT 4 10 +CONECT 10 4 +CONECT 5 11 +CONECT 11 5 +CONECT 6 12 +CONECT 12 6 +CONECT 8 13 +CONECT 13 8 +CONECT 13 14 +CONECT 14 13 +CONECT 8 15 +CONECT 15 8 +CONECT 8 19 +CONECT 19 8 +CONECT 13 20 +CONECT 20 13 +CONECT 13 21 +CONECT 21 13 +CONECT 14 22 +CONECT 22 14 +CONECT 14 23 +CONECT 23 14 +CONECT 23 24 +CONECT 24 23 +CONECT 23 25 +CONECT 25 23 +CONECT 23 26 +CONECT 26 23 +CONECT 21 27 +CONECT 27 21 +CONECT 21 28 +CONECT 28 21 +CONECT 21 29 +CONECT 29 21 +MASTER 0 0 0 0 0 0 0 6 26 1 52 0 +END diff --git a/hacks/images/molecules/morphine.pdb b/hacks/images/molecules/morphine.pdb new file mode 100644 index 00000000..57ae154d --- /dev/null +++ b/hacks/images/molecules/morphine.pdb @@ -0,0 +1,87 @@ +HEADER Morphine, an opiate +COMPND al3058 +AUTHOR Created by Dave Woodcock at Okanagan University College +AUTHOR email:woodcock@okanagan.bc.ca +AUTHOR Date revised: Wed Aug 30 12:33:12 2000 GENERATED BY BABEL 1.6 +HETATM 1 C 1 0.000 0.000 0.000 1.00 0.00 +HETATM 2 C 1 1.400 0.000 0.000 1.00 0.00 +HETATM 3 C 1 2.106 1.211 0.000 1.00 0.00 +HETATM 4 C 1 1.444 2.446 -0.039 1.00 0.00 +HETATM 5 C 1 0.047 2.458 0.013 1.00 0.00 +HETATM 6 C 1 -0.629 1.243 0.051 1.00 0.00 +HETATM 7 C 1 -2.081 1.500 -0.228 1.00 0.00 +HETATM 8 C 1 -2.727 0.342 -0.999 1.00 0.00 +HETATM 9 C 1 -2.363 -0.953 -0.239 1.00 0.00 +HETATM 10 C 1 -0.832 -1.231 -0.285 1.00 0.00 +HETATM 11 C 1 -1.885 2.839 -0.975 1.00 0.00 +HETATM 12 C 1 -2.772 1.631 1.137 1.00 0.00 +HETATM 13 C 1 -2.525 0.318 1.912 1.00 0.00 +HETATM 14 N 1 -2.930 -0.855 1.119 1.00 0.00 +HETATM 15 C 1 -2.790 -2.096 1.899 1.00 0.00 +HETATM 16 H 1 -3.810 0.470 -0.978 1.00 0.00 +HETATM 17 C 1 -2.300 0.287 -2.447 1.00 0.00 +HETATM 18 C 1 -2.022 1.415 -3.116 1.00 0.00 +HETATM 19 C 1 -1.406 2.612 -2.428 1.00 0.00 +HETATM 20 H 1 -2.795 3.439 -0.953 1.00 0.00 +HETATM 21 O 1 -0.796 3.478 -0.328 1.00 0.00 +HETATM 22 H 1 -1.616 3.510 -3.009 1.00 0.00 +HETATM 23 O 1 0.011 2.407 -2.414 1.00 0.00 +HETATM 24 O 1 2.143 3.606 -0.184 1.00 0.00 +HETATM 25 H 1 1.942 -0.943 -0.066 1.00 0.00 +HETATM 26 H 1 3.195 1.192 -0.045 1.00 0.00 +HETATM 27 H 1 -2.861 -1.784 -0.739 1.00 0.00 +HETATM 28 H 1 -0.580 -1.568 -1.291 1.00 0.00 +HETATM 29 H 1 -0.568 -2.021 0.414 1.00 0.00 +HETATM 30 H 1 -3.842 1.788 0.997 1.00 0.00 +HETATM 31 H 1 -2.350 2.469 1.692 1.00 0.00 +HETATM 32 H 1 -3.107 0.346 2.833 1.00 0.00 +HETATM 33 H 1 -1.471 0.235 2.174 1.00 0.00 +HETATM 34 H 1 -3.461 -2.058 2.757 1.00 0.00 +HETATM 35 H 1 -1.767 -2.205 2.257 1.00 0.00 +HETATM 36 H 1 -3.054 -2.955 1.282 1.00 0.00 +HETATM 37 H 1 -2.529 -0.612 -3.019 1.00 0.00 +HETATM 38 H 1 -1.956 1.362 -4.203 1.00 0.00 +HETATM 39 H 1 0.343 2.320 -3.313 1.00 0.00 +HETATM 40 H 1 2.435 3.917 0.680 1.00 0.00 +CONECT 1 2 2 6 10 +CONECT 2 1 1 3 25 +CONECT 3 2 4 4 26 +CONECT 4 3 3 5 24 +CONECT 5 4 6 6 21 +CONECT 6 1 5 5 7 +CONECT 7 6 8 11 12 +CONECT 8 7 9 16 17 +CONECT 9 8 10 14 27 +CONECT 10 1 9 28 29 +CONECT 11 7 19 20 21 +CONECT 12 7 13 30 31 +CONECT 13 12 14 32 33 +CONECT 14 9 13 15 +CONECT 15 14 34 35 36 +CONECT 16 8 +CONECT 17 8 18 18 37 +CONECT 18 17 17 19 38 +CONECT 19 11 18 22 23 +CONECT 20 11 +CONECT 21 5 11 +CONECT 22 19 +CONECT 23 19 39 +CONECT 24 4 40 +CONECT 25 2 +CONECT 26 3 +CONECT 27 9 +CONECT 28 10 +CONECT 29 10 +CONECT 30 12 +CONECT 31 12 +CONECT 32 13 +CONECT 33 13 +CONECT 34 15 +CONECT 35 15 +CONECT 36 15 +CONECT 37 17 +CONECT 38 18 +CONECT 39 23 +CONECT 40 24 +MASTER 0 0 0 0 0 0 0 0 40 0 40 0 +END diff --git a/hacks/images/molecules/nicotine.pdb b/hacks/images/molecules/nicotine.pdb new file mode 100644 index 00000000..d429efec --- /dev/null +++ b/hacks/images/molecules/nicotine.pdb @@ -0,0 +1,59 @@ +HEADER Nicotine, an insecticide +COMPND nicotine +AUTHOR Created by Dave Woodcock at Okanagan University College +AUTHOR email:woodcock@okanagan.bc.ca +AUTHOR Date revised: Fri Sep 1 09:41:05 2000 GENERATED BY BABEL 1.6 +HETATM 1 C 1 0.000 0.000 0.000 1.00 0.00 +HETATM 2 C 1 1.400 0.000 0.000 1.00 0.00 +HETATM 3 C 1 2.082 1.223 0.000 1.00 0.00 +HETATM 4 C 1 1.361 2.420 -0.060 1.00 0.00 +HETATM 5 C 1 -0.037 2.388 -0.103 1.00 0.00 +HETATM 6 N 1 -0.698 1.182 -0.064 1.00 0.00 +HETATM 7 C 1 2.135 -1.320 0.103 1.00 0.00 +HETATM 8 H 1 -0.543 -0.944 0.043 1.00 0.00 +HETATM 9 H 1 3.168 1.256 0.062 1.00 0.00 +HETATM 10 H 1 1.886 3.375 -0.067 1.00 0.00 +HETATM 11 H 1 -0.604 3.318 -0.148 1.00 0.00 +HETATM 12 H 1 2.087 -1.661 1.139 1.00 0.00 +HETATM 13 N 1 1.561 -2.374 -0.749 1.00 0.00 +HETATM 14 C 1 3.616 -1.255 -0.318 1.00 0.00 +HETATM 15 C 1 3.943 -2.708 -0.713 1.00 0.00 +HETATM 16 C 1 2.580 -3.434 -0.690 1.00 0.00 +HETATM 17 C 1 1.359 -1.946 -2.144 1.00 0.00 +HETATM 18 H 1 4.247 -0.910 0.502 1.00 0.00 +HETATM 19 H 1 3.736 -0.608 -1.187 1.00 0.00 +HETATM 20 H 1 4.627 -3.166 0.001 1.00 0.00 +HETATM 21 H 1 4.371 -2.732 -1.715 1.00 0.00 +HETATM 22 H 1 2.475 -3.968 0.255 1.00 0.00 +HETATM 23 H 1 2.490 -4.135 -1.520 1.00 0.00 +HETATM 24 H 1 2.299 -1.632 -2.594 1.00 0.00 +HETATM 25 H 1 0.648 -1.122 -2.190 1.00 0.00 +HETATM 26 H 1 0.956 -2.781 -2.717 1.00 0.00 +CONECT 1 2 2 6 8 +CONECT 2 1 1 3 7 +CONECT 3 2 4 4 9 +CONECT 4 3 3 5 10 +CONECT 5 4 6 6 11 +CONECT 6 1 5 5 +CONECT 7 2 12 13 14 +CONECT 8 1 +CONECT 9 3 +CONECT 10 4 +CONECT 11 5 +CONECT 12 7 +CONECT 13 7 16 17 +CONECT 14 7 15 18 19 +CONECT 15 14 16 20 21 +CONECT 16 13 15 22 23 +CONECT 17 13 24 25 26 +CONECT 18 14 +CONECT 19 14 +CONECT 20 15 +CONECT 21 15 +CONECT 22 16 +CONECT 23 16 +CONECT 24 17 +CONECT 25 17 +CONECT 26 17 +MASTER 0 0 0 0 0 0 0 0 26 0 26 0 +END diff --git a/hacks/images/molecules/novocaine.pdb b/hacks/images/molecules/novocaine.pdb new file mode 100644 index 00000000..0051f05d --- /dev/null +++ b/hacks/images/molecules/novocaine.pdb @@ -0,0 +1,81 @@ +HEADER Procaine: Novocaine, a local anesthetic +COMPND al3080 +AUTHOR Created by Dave Woodcock at Okanagan University College +AUTHOR email:woodcock@okanagan.bc.ca +AUTHOR Date revised: Wed Aug 30 12:33:12 2000 GENERATED BY BABEL 1.6 +HETATM 1 C 1 0.000 0.000 0.000 1.00 0.00 +HETATM 2 C 1 1.399 0.000 0.000 1.00 0.00 +HETATM 3 C 1 2.099 1.211 0.000 1.00 0.00 +HETATM 4 C 1 1.398 2.422 0.001 1.00 0.00 +HETATM 5 C 1 -0.001 2.421 0.002 1.00 0.00 +HETATM 6 C 1 -0.702 1.211 0.002 1.00 0.00 +HETATM 7 N 1 -2.104 1.210 0.003 1.00 0.00 +HETATM 8 C 1 3.511 1.212 0.000 1.00 0.00 +HETATM 9 O 1 4.107 2.255 -0.002 1.00 0.00 +HETATM 10 O 1 4.172 0.056 0.011 1.00 0.00 +HETATM 11 C 1 5.562 0.269 0.112 1.00 0.00 +HETATM 12 C 1 6.275 -1.096 0.162 1.00 0.00 +HETATM 13 H 1 -0.542 -0.946 0.000 1.00 0.00 +HETATM 14 H 1 1.942 -0.945 -0.001 1.00 0.00 +HETATM 15 H 1 1.940 3.368 0.001 1.00 0.00 +HETATM 16 H 1 -0.544 3.367 0.004 1.00 0.00 +HETATM 17 H 1 -2.613 0.334 0.002 1.00 0.00 +HETATM 18 H 1 5.776 0.831 1.021 1.00 0.00 +HETATM 19 H 1 5.912 0.827 -0.758 1.00 0.00 +HETATM 20 H 1 5.949 -1.682 -0.697 1.00 0.00 +HETATM 21 H 1 5.984 -1.614 1.076 1.00 0.00 +HETATM 22 N 1 7.741 -0.935 0.107 1.00 0.00 +HETATM 23 C 1 8.433 -2.206 -0.184 1.00 0.00 +HETATM 24 C 1 8.171 -3.279 0.896 1.00 0.00 +HETATM 25 C 1 8.301 -0.239 1.281 1.00 0.00 +HETATM 26 C 1 8.683 1.204 0.891 1.00 0.00 +HETATM 27 H 1 -2.613 2.087 0.004 1.00 0.00 +HETATM 28 H 1 9.505 -2.021 -0.249 1.00 0.00 +HETATM 29 H 1 8.091 -2.587 -1.146 1.00 0.00 +HETATM 30 H 1 7.118 -3.559 0.896 1.00 0.00 +HETATM 31 H 1 8.444 -2.898 1.879 1.00 0.00 +HETATM 32 H 1 8.770 -4.162 0.675 1.00 0.00 +HETATM 33 H 1 9.205 -0.743 1.624 1.00 0.00 +HETATM 34 H 1 7.579 -0.223 2.098 1.00 0.00 +HETATM 35 H 1 7.804 1.747 0.546 1.00 0.00 +HETATM 36 H 1 9.424 1.176 0.092 1.00 0.00 +HETATM 37 H 1 9.105 1.714 1.757 1.00 0.00 +CONECT 1 2 2 6 13 +CONECT 2 1 1 3 14 +CONECT 3 2 4 4 8 +CONECT 4 3 3 5 15 +CONECT 5 4 6 6 16 +CONECT 6 1 5 5 7 +CONECT 7 6 17 27 +CONECT 8 3 9 9 10 +CONECT 9 8 8 +CONECT 10 8 11 +CONECT 11 10 12 18 19 +CONECT 12 11 20 21 22 +CONECT 13 1 +CONECT 14 2 +CONECT 15 4 +CONECT 16 5 +CONECT 17 7 +CONECT 18 11 +CONECT 19 11 +CONECT 20 12 +CONECT 21 12 +CONECT 22 12 23 25 +CONECT 23 22 24 28 29 +CONECT 24 23 30 31 32 +CONECT 25 22 26 33 34 +CONECT 26 25 35 36 37 +CONECT 27 7 +CONECT 28 23 +CONECT 29 23 +CONECT 30 24 +CONECT 31 24 +CONECT 32 24 +CONECT 33 25 +CONECT 34 25 +CONECT 35 26 +CONECT 36 26 +CONECT 37 26 +MASTER 0 0 0 0 0 0 0 0 37 0 37 0 +END diff --git a/hacks/images/molecules/olestra.pdb b/hacks/images/molecules/olestra.pdb new file mode 100644 index 00000000..b155d2f4 --- /dev/null +++ b/hacks/images/molecules/olestra.pdb @@ -0,0 +1,913 @@ +HEADER Sucrose octaoleate: Olestra-like non-hydrolyzing fat +COMPND jb15oles +AUTHOR Created by Dave Woodcock at Okanagan University College +AUTHOR email:woodcock@okanagan.bc.ca +AUTHOR Date revised: Wed Sep 20 16:26:54 2000 GENERATED BY BABEL 1.6 +HETATM 1 C 1 0.000 0.000 0.000 1.00 0.00 +HETATM 2 C 1 1.543 0.000 0.000 1.00 0.00 +HETATM 3 C 1 2.023 1.465 0.000 1.00 0.00 +HETATM 4 C 1 1.448 2.115 1.276 1.00 0.00 +HETATM 5 C 1 -0.094 1.986 1.258 1.00 0.00 +HETATM 6 O 1 -0.446 0.620 1.189 1.00 0.00 +HETATM 7 O 1 -0.682 2.630 0.148 1.00 0.00 +HETATM 8 C 1 -0.713 4.011 -0.142 1.00 0.00 +HETATM 9 C 1 -1.600 4.135 -1.401 1.00 0.00 +HETATM 10 C 1 -1.324 4.924 0.946 1.00 0.00 +HETATM 11 O 1 0.576 4.533 -0.389 1.00 0.00 +HETATM 12 C 1 0.436 5.938 -0.395 1.00 0.00 +HETATM 13 C 1 -0.617 6.269 0.681 1.00 0.00 +HETATM 14 C 1 1.756 6.671 -0.084 1.00 0.00 +HETATM 15 O 1 2.227 6.278 1.183 1.00 0.00 +HETATM 16 O 1 -1.499 7.264 0.209 1.00 0.00 +HETATM 17 O 1 -1.029 4.475 2.250 1.00 0.00 +HETATM 18 O 1 -1.000 3.465 -2.486 1.00 0.00 +HETATM 19 C 1 -0.514 -1.457 -0.089 1.00 0.00 +HETATM 20 O 1 -1.922 -1.490 0.008 1.00 0.00 +HETATM 21 O 1 2.044 -0.707 -1.115 1.00 0.00 +HETATM 22 O 1 3.434 1.488 -0.024 1.00 0.00 +HETATM 23 O 1 1.870 3.459 1.361 1.00 0.00 +HETATM 24 C 1 -2.482 -2.432 -0.753 1.00 0.00 +HETATM 25 O 1 -3.315 -2.099 -1.556 1.00 0.00 +HETATM 26 C 1 -2.336 -3.895 -0.434 1.00 0.00 +HETATM 27 C 1 -3.583 -4.668 -0.927 1.00 0.00 +HETATM 28 C 1 -3.416 -6.194 -0.736 1.00 0.00 +HETATM 29 C 1 -4.686 -6.939 -1.212 1.00 0.00 +HETATM 30 C 1 -4.492 -8.472 -1.146 1.00 0.00 +HETATM 31 C 1 -5.779 -9.194 -1.608 1.00 0.00 +HETATM 32 C 1 -5.580 -10.727 -1.651 1.00 0.00 +HETATM 33 C 1 -6.868 -11.389 -2.094 1.00 0.00 +HETATM 34 C 1 -6.933 -12.683 -2.447 1.00 0.00 +HETATM 35 C 1 -5.725 -13.593 -2.433 1.00 0.00 +HETATM 36 C 1 -6.164 -15.030 -2.794 1.00 0.00 +HETATM 37 C 1 -4.957 -15.993 -2.791 1.00 0.00 +HETATM 38 C 1 -5.423 -17.419 -3.153 1.00 0.00 +HETATM 39 C 1 -4.225 -18.393 -3.146 1.00 0.00 +HETATM 40 C 1 -4.700 -19.818 -3.505 1.00 0.00 +HETATM 41 C 1 3.344 -0.983 -0.999 1.00 0.00 +HETATM 42 O 1 4.098 -0.665 -1.882 1.00 0.00 +HETATM 43 C 1 3.844 -1.849 0.124 1.00 0.00 +HETATM 44 C 1 5.081 -2.680 -0.284 1.00 0.00 +HETATM 45 C 1 5.532 -3.506 0.946 1.00 0.00 +HETATM 46 C 1 6.768 -4.378 0.668 1.00 0.00 +HETATM 47 C 1 7.108 -5.157 1.969 1.00 0.00 +HETATM 48 C 1 8.283 -6.109 1.808 1.00 0.00 +HETATM 49 C 1 8.489 -6.845 3.177 1.00 0.00 +HETATM 50 C 1 9.603 -7.867 3.101 1.00 0.00 +HETATM 51 C 1 9.838 -8.686 4.139 1.00 0.00 +HETATM 52 C 1 8.989 -8.622 5.392 1.00 0.00 +HETATM 53 C 1 9.509 -9.601 6.463 1.00 0.00 +HETATM 54 C 1 8.612 -9.509 7.718 1.00 0.00 +HETATM 55 C 1 9.090 -10.491 8.808 1.00 0.00 +HETATM 56 C 1 8.155 -10.395 10.033 1.00 0.00 +HETATM 57 C 1 8.599 -11.385 11.130 1.00 0.00 +HETATM 58 C 1 3.954 2.643 0.391 1.00 0.00 +HETATM 59 O 1 4.364 2.722 1.520 1.00 0.00 +HETATM 60 C 1 3.833 3.903 -0.422 1.00 0.00 +HETATM 61 C 1 5.113 4.138 -1.254 1.00 0.00 +HETATM 62 C 1 5.001 5.470 -2.030 1.00 0.00 +HETATM 63 C 1 6.274 5.721 -2.868 1.00 0.00 +HETATM 64 C 1 6.142 7.042 -3.658 1.00 0.00 +HETATM 65 C 1 7.424 7.302 -4.480 1.00 0.00 +HETATM 66 C 1 7.292 8.604 -5.302 1.00 0.00 +HETATM 67 C 1 8.567 8.842 -6.080 1.00 0.00 +HETATM 68 C 1 8.673 9.819 -6.994 1.00 0.00 +HETATM 69 C 1 7.518 10.739 -7.321 1.00 0.00 +HETATM 70 C 1 7.962 11.764 -8.388 1.00 0.00 +HETATM 71 C 1 6.793 12.704 -8.749 1.00 0.00 +HETATM 72 C 1 7.240 13.712 -9.829 1.00 0.00 +HETATM 73 C 1 6.069 14.649 -10.192 1.00 0.00 +HETATM 74 C 1 6.510 15.654 -11.277 1.00 0.00 +HETATM 75 C 1 1.563 4.034 2.524 1.00 0.00 +HETATM 76 O 1 0.994 5.094 2.507 1.00 0.00 +HETATM 77 C 1 2.204 3.624 3.820 1.00 0.00 +HETATM 78 C 1 1.081 3.461 4.864 1.00 0.00 +HETATM 79 C 1 1.646 2.985 6.219 1.00 0.00 +HETATM 80 C 1 0.495 2.893 7.242 1.00 0.00 +HETATM 81 C 1 0.991 2.293 8.574 1.00 0.00 +HETATM 82 C 1 -0.180 2.239 9.577 1.00 0.00 +HETATM 83 C 1 0.252 1.529 10.878 1.00 0.00 +HETATM 84 C 1 -0.909 1.516 11.848 1.00 0.00 +HETATM 85 C 1 -1.007 0.609 12.832 1.00 0.00 +HETATM 86 C 1 0.023 -0.485 13.013 1.00 0.00 +HETATM 87 C 1 -0.255 -1.246 14.326 1.00 0.00 +HETATM 88 C 1 0.758 -2.396 14.494 1.00 0.00 +HETATM 89 C 1 0.465 -3.168 15.798 1.00 0.00 +HETATM 90 C 1 1.443 -4.352 15.937 1.00 0.00 +HETATM 91 C 1 1.138 -5.136 17.229 1.00 0.00 +HETATM 92 C 1 -1.640 3.717 -3.628 1.00 0.00 +HETATM 93 O 1 -1.012 4.078 -4.590 1.00 0.00 +HETATM 94 C 1 -3.121 3.488 -3.752 1.00 0.00 +HETATM 95 C 1 -3.553 3.549 -5.232 1.00 0.00 +HETATM 96 C 1 -5.083 3.368 -5.331 1.00 0.00 +HETATM 97 C 1 -5.545 3.449 -6.801 1.00 0.00 +HETATM 98 C 1 -7.080 3.295 -6.870 1.00 0.00 +HETATM 99 C 1 -7.563 3.372 -8.334 1.00 0.00 +HETATM 100 C 1 -9.099 3.230 -8.385 1.00 0.00 +HETATM 101 C 1 -9.579 3.302 -9.818 1.00 0.00 +HETATM 102 C 1 -10.886 3.239 -10.119 1.00 0.00 +HETATM 103 C 1 -11.934 3.095 -9.037 1.00 0.00 +HETATM 104 C 1 -13.340 3.036 -9.669 1.00 0.00 +HETATM 105 C 1 -14.403 2.883 -8.561 1.00 0.00 +HETATM 106 C 1 -15.815 2.830 -9.181 1.00 0.00 +HETATM 107 C 1 -16.867 2.668 -8.064 1.00 0.00 +HETATM 108 C 1 -18.283 2.619 -8.671 1.00 0.00 +HETATM 109 C 1 -2.001 7.975 1.218 1.00 0.00 +HETATM 110 O 1 -3.001 7.595 1.768 1.00 0.00 +HETATM 111 C 1 -1.156 9.034 1.872 1.00 0.00 +HETATM 112 C 1 -1.534 10.432 1.344 1.00 0.00 +HETATM 113 C 1 -0.625 11.493 2.001 1.00 0.00 +HETATM 114 C 1 -0.976 12.902 1.479 1.00 0.00 +HETATM 115 C 1 -0.062 13.955 2.143 1.00 0.00 +HETATM 116 C 1 -0.432 15.365 1.636 1.00 0.00 +HETATM 117 C 1 0.472 16.432 2.289 1.00 0.00 +HETATM 118 C 1 0.070 17.801 1.786 1.00 0.00 +HETATM 119 C 1 0.739 18.910 2.133 1.00 0.00 +HETATM 120 C 1 1.947 18.864 3.043 1.00 0.00 +HETATM 121 C 1 2.466 20.301 3.261 1.00 0.00 +HETATM 122 C 1 3.707 20.302 4.178 1.00 0.00 +HETATM 123 C 1 4.204 21.750 4.364 1.00 0.00 +HETATM 124 C 1 5.448 21.780 5.275 1.00 0.00 +HETATM 125 C 1 5.933 23.236 5.440 1.00 0.00 +HETATM 126 C 1 -1.676 5.203 3.160 1.00 0.00 +HETATM 127 O 1 -1.395 6.362 3.326 1.00 0.00 +HETATM 128 C 1 -2.722 4.564 4.031 1.00 0.00 +HETATM 129 C 1 -3.529 5.657 4.765 1.00 0.00 +HETATM 130 C 1 -4.616 5.007 5.648 1.00 0.00 +HETATM 131 C 1 -5.417 6.088 6.405 1.00 0.00 +HETATM 132 C 1 -6.505 5.421 7.274 1.00 0.00 +HETATM 133 C 1 -7.276 6.485 8.085 1.00 0.00 +HETATM 134 C 1 -8.342 5.803 8.967 1.00 0.00 +HETATM 135 C 1 -8.999 6.835 9.859 1.00 0.00 +HETATM 136 C 1 -10.265 7.250 9.698 1.00 0.00 +HETATM 137 C 1 -11.161 6.729 8.595 1.00 0.00 +HETATM 138 C 1 -12.519 7.460 8.650 1.00 0.00 +HETATM 139 C 1 -13.450 6.941 7.534 1.00 0.00 +HETATM 140 C 1 -14.810 7.665 7.610 1.00 0.00 +HETATM 141 C 1 -15.745 7.150 6.496 1.00 0.00 +HETATM 142 C 1 -17.110 7.866 6.583 1.00 0.00 +HETATM 143 C 1 2.842 7.281 1.802 1.00 0.00 +HETATM 144 O 1 2.205 8.253 2.118 1.00 0.00 +HETATM 145 C 1 4.220 7.092 2.370 1.00 0.00 +HETATM 146 C 1 4.473 8.156 3.459 1.00 0.00 +HETATM 147 C 1 5.893 8.017 4.051 1.00 0.00 +HETATM 148 C 1 6.113 9.105 5.125 1.00 0.00 +HETATM 149 C 1 7.536 9.013 5.717 1.00 0.00 +HETATM 150 C 1 7.731 10.123 6.772 1.00 0.00 +HETATM 151 C 1 9.153 10.065 7.368 1.00 0.00 +HETATM 152 C 1 9.319 11.173 8.385 1.00 0.00 +HETATM 153 C 1 10.461 11.337 9.067 1.00 0.00 +HETATM 154 C 1 11.643 10.413 8.868 1.00 0.00 +HETATM 155 C 1 12.819 10.884 9.749 1.00 0.00 +HETATM 156 C 1 14.028 9.942 9.572 1.00 0.00 +HETATM 157 C 1 15.194 10.418 10.464 1.00 0.00 +HETATM 158 C 1 16.397 9.465 10.312 1.00 0.00 +HETATM 159 C 1 17.555 9.936 11.217 1.00 0.00 +HETATM 160 C 1 18.753 8.973 11.081 1.00 0.00 +HETATM 161 C 1 19.907 9.437 11.992 1.00 0.00 +HETATM 162 C 1 7.637 -11.294 12.332 1.00 0.00 +HETATM 163 C 1 8.066 -12.287 13.432 1.00 0.00 +HETATM 164 C 1 -3.503 -20.792 -3.494 1.00 0.00 +HETATM 165 C 1 -3.976 -22.215 -3.853 1.00 0.00 +HETATM 166 C 1 2.094 -6.341 17.349 1.00 0.00 +HETATM 167 C 1 1.786 -7.131 18.637 1.00 0.00 +HETATM 168 C 1 5.336 16.589 -11.634 1.00 0.00 +HETATM 169 C 1 5.771 17.593 -12.721 1.00 0.00 +HETATM 170 C 1 7.177 23.279 6.350 1.00 0.00 +HETATM 171 C 1 7.661 24.734 6.509 1.00 0.00 +HETATM 172 C 1 -19.327 2.450 -7.548 1.00 0.00 +HETATM 173 C 1 -20.747 2.406 -8.149 1.00 0.00 +HETATM 174 C 1 -18.044 7.350 5.470 1.00 0.00 +HETATM 175 C 1 -19.412 8.057 5.560 1.00 0.00 +HETATM 176 H 1 -0.368 0.553 -0.864 1.00 0.00 +HETATM 177 H 1 1.874 -0.482 0.920 1.00 0.00 +HETATM 178 H 1 1.632 1.978 -0.879 1.00 0.00 +HETATM 179 H 1 1.826 1.557 2.131 1.00 0.00 +HETATM 180 H 1 -0.503 2.395 2.180 1.00 0.00 +HETATM 181 H 1 -1.766 5.183 -1.654 1.00 0.00 +HETATM 182 H 1 -2.562 3.672 -1.182 1.00 0.00 +HETATM 183 H 1 -2.404 5.015 0.817 1.00 0.00 +HETATM 184 H 1 0.079 6.263 -1.372 1.00 0.00 +HETATM 185 H 1 -0.107 6.607 1.580 1.00 0.00 +HETATM 186 H 1 1.568 7.745 -0.111 1.00 0.00 +HETATM 187 H 1 2.495 6.425 -0.844 1.00 0.00 +HETATM 188 H 1 -0.089 -2.043 0.726 1.00 0.00 +HETATM 189 H 1 -0.191 -1.883 -1.040 1.00 0.00 +HETATM 190 H 1 -2.226 -4.025 0.643 1.00 0.00 +HETATM 191 H 1 -1.448 -4.280 -0.936 1.00 0.00 +HETATM 192 H 1 -3.732 -4.461 -1.987 1.00 0.00 +HETATM 193 H 1 -4.457 -4.327 -0.372 1.00 0.00 +HETATM 194 H 1 -3.242 -6.413 0.317 1.00 0.00 +HETATM 195 H 1 -2.560 -6.535 -1.319 1.00 0.00 +HETATM 196 H 1 -4.902 -6.654 -2.241 1.00 0.00 +HETATM 197 H 1 -5.527 -6.653 -0.579 1.00 0.00 +HETATM 198 H 1 -4.259 -8.767 -0.123 1.00 0.00 +HETATM 199 H 1 -3.666 -8.756 -1.799 1.00 0.00 +HETATM 200 H 1 -6.047 -8.844 -2.605 1.00 0.00 +HETATM 201 H 1 -6.588 -8.955 -0.918 1.00 0.00 +HETATM 202 H 1 -5.310 -11.089 -0.659 1.00 0.00 +HETATM 203 H 1 -4.783 -10.967 -2.355 1.00 0.00 +HETATM 204 H 1 -7.781 -10.795 -2.125 1.00 0.00 +HETATM 205 H 1 -7.896 -13.091 -2.754 1.00 0.00 +HETATM 206 H 1 -5.275 -13.588 -1.440 1.00 0.00 +HETATM 207 H 1 -4.997 -13.243 -3.164 1.00 0.00 +HETATM 208 H 1 -6.618 -15.028 -3.785 1.00 0.00 +HETATM 209 H 1 -6.898 -15.374 -2.065 1.00 0.00 +HETATM 210 H 1 -4.502 -16.000 -1.801 1.00 0.00 +HETATM 211 H 1 -4.222 -15.655 -3.522 1.00 0.00 +HETATM 212 H 1 -5.875 -17.411 -4.145 1.00 0.00 +HETATM 213 H 1 -6.163 -17.753 -2.425 1.00 0.00 +HETATM 214 H 1 -3.773 -18.402 -2.155 1.00 0.00 +HETATM 215 H 1 -3.486 -18.063 -3.876 1.00 0.00 +HETATM 216 H 1 -5.150 -19.810 -4.498 1.00 0.00 +HETATM 217 H 1 -5.441 -20.147 -2.777 1.00 0.00 +HETATM 218 H 1 3.046 -2.532 0.416 1.00 0.00 +HETATM 219 H 1 4.102 -1.216 0.975 1.00 0.00 +HETATM 220 H 1 5.884 -2.006 -0.580 1.00 0.00 +HETATM 221 H 1 4.829 -3.337 -1.117 1.00 0.00 +HETATM 222 H 1 4.717 -4.156 1.264 1.00 0.00 +HETATM 223 H 1 5.773 -2.820 1.759 1.00 0.00 +HETATM 224 H 1 7.605 -3.757 0.345 1.00 0.00 +HETATM 225 H 1 6.511 -5.083 -0.123 1.00 0.00 +HETATM 226 H 1 6.244 -5.737 2.294 1.00 0.00 +HETATM 227 H 1 7.378 -4.451 2.755 1.00 0.00 +HETATM 228 H 1 9.158 -5.517 1.539 1.00 0.00 +HETATM 229 H 1 8.056 -6.812 1.007 1.00 0.00 +HETATM 230 H 1 7.572 -7.372 3.439 1.00 0.00 +HETATM 231 H 1 8.718 -6.129 3.967 1.00 0.00 +HETATM 232 H 1 10.222 -7.926 2.206 1.00 0.00 +HETATM 233 H 1 10.647 -9.413 4.074 1.00 0.00 +HETATM 234 H 1 7.960 -8.886 5.148 1.00 0.00 +HETATM 235 H 1 9.015 -7.611 5.799 1.00 0.00 +HETATM 236 H 1 10.534 -9.341 6.725 1.00 0.00 +HETATM 237 H 1 9.481 -10.616 6.068 1.00 0.00 +HETATM 238 H 1 7.586 -9.753 7.443 1.00 0.00 +HETATM 239 H 1 8.644 -8.493 8.111 1.00 0.00 +HETATM 240 H 1 10.108 -10.239 9.105 1.00 0.00 +HETATM 241 H 1 9.070 -11.507 8.415 1.00 0.00 +HETATM 242 H 1 7.136 -10.633 9.726 1.00 0.00 +HETATM 243 H 1 8.182 -9.380 10.429 1.00 0.00 +HETATM 244 H 1 9.611 -11.139 11.453 1.00 0.00 +HETATM 245 H 1 8.585 -12.399 10.730 1.00 0.00 +HETATM 246 H 1 3.697 4.738 0.262 1.00 0.00 +HETATM 247 H 1 2.973 3.837 -1.086 1.00 0.00 +HETATM 248 H 1 5.244 3.316 -1.956 1.00 0.00 +HETATM 249 H 1 5.973 4.181 -0.585 1.00 0.00 +HETATM 250 H 1 4.873 6.289 -1.322 1.00 0.00 +HETATM 251 H 1 4.136 5.428 -2.692 1.00 0.00 +HETATM 252 H 1 6.415 4.896 -3.567 1.00 0.00 +HETATM 253 H 1 7.137 5.781 -2.205 1.00 0.00 +HETATM 254 H 1 5.987 7.867 -2.962 1.00 0.00 +HETATM 255 H 1 5.288 6.976 -4.332 1.00 0.00 +HETATM 256 H 1 7.592 6.466 -5.158 1.00 0.00 +HETATM 257 H 1 8.273 7.389 -3.801 1.00 0.00 +HETATM 258 H 1 7.117 9.443 -4.629 1.00 0.00 +HETATM 259 H 1 6.453 8.510 -5.991 1.00 0.00 +HETATM 260 H 1 9.432 8.207 -5.887 1.00 0.00 +HETATM 261 H 1 9.620 9.946 -7.519 1.00 0.00 +HETATM 262 H 1 7.205 11.266 -6.419 1.00 0.00 +HETATM 263 H 1 6.685 10.153 -7.709 1.00 0.00 +HETATM 264 H 1 8.285 11.232 -9.283 1.00 0.00 +HETATM 265 H 1 8.793 12.353 -8.000 1.00 0.00 +HETATM 266 H 1 6.474 13.244 -7.858 1.00 0.00 +HETATM 267 H 1 5.958 12.114 -9.129 1.00 0.00 +HETATM 268 H 1 7.559 13.171 -10.720 1.00 0.00 +HETATM 269 H 1 8.073 14.304 -9.450 1.00 0.00 +HETATM 270 H 1 5.753 15.194 -9.302 1.00 0.00 +HETATM 271 H 1 5.234 14.057 -10.566 1.00 0.00 +HETATM 272 H 1 6.824 15.110 -12.168 1.00 0.00 +HETATM 273 H 1 7.346 16.246 -10.905 1.00 0.00 +HETATM 274 H 1 2.891 4.405 4.144 1.00 0.00 +HETATM 275 H 1 2.753 2.690 3.706 1.00 0.00 +HETATM 276 H 1 0.360 2.729 4.502 1.00 0.00 +HETATM 277 H 1 0.578 4.420 4.999 1.00 0.00 +HETATM 278 H 1 2.396 3.692 6.575 1.00 0.00 +HETATM 279 H 1 2.104 2.004 6.094 1.00 0.00 +HETATM 280 H 1 -0.293 2.257 6.838 1.00 0.00 +HETATM 281 H 1 0.092 3.890 7.420 1.00 0.00 +HETATM 282 H 1 1.792 2.910 8.980 1.00 0.00 +HETATM 283 H 1 1.366 1.285 8.397 1.00 0.00 +HETATM 284 H 1 -1.010 1.689 9.134 1.00 0.00 +HETATM 285 H 1 -0.503 3.254 9.807 1.00 0.00 +HETATM 286 H 1 1.090 2.062 11.326 1.00 0.00 +HETATM 287 H 1 0.555 0.509 10.641 1.00 0.00 +HETATM 288 H 1 -1.682 2.279 11.759 1.00 0.00 +HETATM 289 H 1 -1.860 0.654 13.508 1.00 0.00 +HETATM 290 H 1 1.020 -0.047 13.053 1.00 0.00 +HETATM 291 H 1 -0.037 -1.180 12.176 1.00 0.00 +HETATM 292 H 1 -1.264 -1.658 14.297 1.00 0.00 +HETATM 293 H 1 -0.170 -0.560 15.169 1.00 0.00 +HETATM 294 H 1 1.769 -1.990 14.531 1.00 0.00 +HETATM 295 H 1 0.675 -3.076 13.646 1.00 0.00 +HETATM 296 H 1 -0.557 -3.546 15.772 1.00 0.00 +HETATM 297 H 1 0.580 -2.498 16.650 1.00 0.00 +HETATM 298 H 1 2.466 -3.977 15.971 1.00 0.00 +HETATM 299 H 1 1.331 -5.015 15.078 1.00 0.00 +HETATM 300 H 1 0.108 -5.493 17.202 1.00 0.00 +HETATM 301 H 1 1.269 -4.481 18.090 1.00 0.00 +HETATM 302 H 1 -3.652 4.262 -3.197 1.00 0.00 +HETATM 303 H 1 -3.371 2.511 -3.339 1.00 0.00 +HETATM 304 H 1 -3.052 2.758 -5.791 1.00 0.00 +HETATM 305 H 1 -3.275 4.517 -5.650 1.00 0.00 +HETATM 306 H 1 -5.575 4.153 -4.757 1.00 0.00 +HETATM 307 H 1 -5.358 2.397 -4.919 1.00 0.00 +HETATM 308 H 1 -5.072 2.653 -7.376 1.00 0.00 +HETATM 309 H 1 -5.259 4.415 -7.219 1.00 0.00 +HETATM 310 H 1 -7.548 4.093 -6.294 1.00 0.00 +HETATM 311 H 1 -7.365 2.332 -6.447 1.00 0.00 +HETATM 312 H 1 -7.105 2.569 -8.910 1.00 0.00 +HETATM 313 H 1 -7.275 4.333 -8.761 1.00 0.00 +HETATM 314 H 1 -9.553 4.035 -7.808 1.00 0.00 +HETATM 315 H 1 -9.385 2.270 -7.955 1.00 0.00 +HETATM 316 H 1 -8.852 3.405 -10.623 1.00 0.00 +HETATM 317 H 1 -11.195 3.293 -11.162 1.00 0.00 +HETATM 318 H 1 -11.879 3.949 -8.362 1.00 0.00 +HETATM 319 H 1 -11.753 2.177 -8.477 1.00 0.00 +HETATM 320 H 1 -13.398 2.184 -10.347 1.00 0.00 +HETATM 321 H 1 -13.526 3.954 -10.227 1.00 0.00 +HETATM 322 H 1 -14.340 3.732 -7.880 1.00 0.00 +HETATM 323 H 1 -14.217 1.964 -8.007 1.00 0.00 +HETATM 324 H 1 -15.880 1.984 -9.865 1.00 0.00 +HETATM 325 H 1 -16.006 3.752 -9.729 1.00 0.00 +HETATM 326 H 1 -16.797 3.511 -7.377 1.00 0.00 +HETATM 327 H 1 -16.675 1.743 -7.519 1.00 0.00 +HETATM 328 H 1 -18.353 1.777 -9.361 1.00 0.00 +HETATM 329 H 1 -18.478 3.545 -9.212 1.00 0.00 +HETATM 330 H 1 -0.105 8.848 1.652 1.00 0.00 +HETATM 331 H 1 -1.308 8.997 2.950 1.00 0.00 +HETATM 332 H 1 -2.576 10.642 1.584 1.00 0.00 +HETATM 333 H 1 -1.400 10.458 0.262 1.00 0.00 +HETATM 334 H 1 0.416 11.272 1.765 1.00 0.00 +HETATM 335 H 1 -0.761 11.465 3.082 1.00 0.00 +HETATM 336 H 1 -2.016 13.126 1.716 1.00 0.00 +HETATM 337 H 1 -0.839 12.933 0.398 1.00 0.00 +HETATM 338 H 1 0.978 13.741 1.894 1.00 0.00 +HETATM 339 H 1 -0.189 13.915 3.224 1.00 0.00 +HETATM 340 H 1 -1.473 15.574 1.885 1.00 0.00 +HETATM 341 H 1 -0.309 15.403 0.553 1.00 0.00 +HETATM 342 H 1 1.512 16.236 2.027 1.00 0.00 +HETATM 343 H 1 0.356 16.395 3.372 1.00 0.00 +HETATM 344 H 1 -0.793 17.892 1.125 1.00 0.00 +HETATM 345 H 1 0.403 19.871 1.743 1.00 0.00 +HETATM 346 H 1 2.729 18.261 2.583 1.00 0.00 +HETATM 347 H 1 1.666 18.429 4.003 1.00 0.00 +HETATM 348 H 1 1.680 20.901 3.718 1.00 0.00 +HETATM 349 H 1 2.733 20.734 2.297 1.00 0.00 +HETATM 350 H 1 4.496 19.701 3.725 1.00 0.00 +HETATM 351 H 1 3.443 19.879 5.148 1.00 0.00 +HETATM 352 H 1 3.412 22.349 4.815 1.00 0.00 +HETATM 353 H 1 4.461 22.170 3.391 1.00 0.00 +HETATM 354 H 1 6.241 21.182 4.827 1.00 0.00 +HETATM 355 H 1 5.192 21.369 6.251 1.00 0.00 +HETATM 356 H 1 5.138 23.834 5.886 1.00 0.00 +HETATM 357 H 1 6.186 23.646 4.463 1.00 0.00 +HETATM 358 H 1 -2.234 3.917 4.760 1.00 0.00 +HETATM 359 H 1 -3.391 3.970 3.410 1.00 0.00 +HETATM 360 H 1 -3.999 6.312 4.032 1.00 0.00 +HETATM 361 H 1 -2.855 6.243 5.391 1.00 0.00 +HETATM 362 H 1 -4.143 4.340 6.369 1.00 0.00 +HETATM 363 H 1 -5.294 4.431 5.018 1.00 0.00 +HETATM 364 H 1 -5.887 6.762 5.689 1.00 0.00 +HETATM 365 H 1 -4.741 6.657 7.044 1.00 0.00 +HETATM 366 H 1 -6.034 4.719 7.961 1.00 0.00 +HETATM 367 H 1 -7.201 4.881 6.631 1.00 0.00 +HETATM 368 H 1 -7.762 7.185 7.405 1.00 0.00 +HETATM 369 H 1 -6.577 7.027 8.721 1.00 0.00 +HETATM 370 H 1 -7.858 5.057 9.599 1.00 0.00 +HETATM 371 H 1 -9.075 5.305 8.334 1.00 0.00 +HETATM 372 H 1 -8.416 7.259 10.676 1.00 0.00 +HETATM 373 H 1 -10.661 7.994 10.389 1.00 0.00 +HETATM 374 H 1 -11.324 5.660 8.731 1.00 0.00 +HETATM 375 H 1 -10.692 6.909 7.628 1.00 0.00 +HETATM 376 H 1 -12.360 8.530 8.520 1.00 0.00 +HETATM 377 H 1 -12.985 7.281 9.620 1.00 0.00 +HETATM 378 H 1 -13.603 5.869 7.659 1.00 0.00 +HETATM 379 H 1 -12.992 7.129 6.563 1.00 0.00 +HETATM 380 H 1 -14.657 8.738 7.488 1.00 0.00 +HETATM 381 H 1 -15.267 7.476 8.582 1.00 0.00 +HETATM 382 H 1 -15.891 6.077 6.614 1.00 0.00 +HETATM 383 H 1 -15.293 7.348 5.524 1.00 0.00 +HETATM 384 H 1 -16.964 8.939 6.466 1.00 0.00 +HETATM 385 H 1 -17.561 7.667 7.556 1.00 0.00 +HETATM 386 H 1 4.947 7.200 1.566 1.00 0.00 +HETATM 387 H 1 4.294 6.092 2.798 1.00 0.00 +HETATM 388 H 1 3.737 8.034 4.255 1.00 0.00 +HETATM 389 H 1 4.363 9.148 3.021 1.00 0.00 +HETATM 390 H 1 6.629 8.137 3.256 1.00 0.00 +HETATM 391 H 1 6.005 7.031 4.501 1.00 0.00 +HETATM 392 H 1 5.382 8.976 5.924 1.00 0.00 +HETATM 393 H 1 5.977 10.088 4.673 1.00 0.00 +HETATM 394 H 1 8.269 9.137 4.920 1.00 0.00 +HETATM 395 H 1 7.673 8.038 6.185 1.00 0.00 +HETATM 396 H 1 7.001 9.993 7.571 1.00 0.00 +HETATM 397 H 1 7.579 11.095 6.302 1.00 0.00 +HETATM 398 H 1 9.884 10.192 6.570 1.00 0.00 +HETATM 399 H 1 9.304 9.100 7.851 1.00 0.00 +HETATM 400 H 1 8.493 11.861 8.565 1.00 0.00 +HETATM 401 H 1 10.536 12.152 9.787 1.00 0.00 +HETATM 402 H 1 11.947 10.429 7.821 1.00 0.00 +HETATM 403 H 1 11.362 9.399 9.150 1.00 0.00 +HETATM 404 H 1 12.509 10.880 10.795 1.00 0.00 +HETATM 405 H 1 13.103 11.896 9.462 1.00 0.00 +HETATM 406 H 1 14.343 9.946 8.529 1.00 0.00 +HETATM 407 H 1 13.743 8.930 9.859 1.00 0.00 +HETATM 408 H 1 14.872 10.428 11.505 1.00 0.00 +HETATM 409 H 1 15.489 11.425 10.168 1.00 0.00 +HETATM 410 H 1 16.727 9.459 9.273 1.00 0.00 +HETATM 411 H 1 16.099 8.457 10.601 1.00 0.00 +HETATM 412 H 1 17.219 9.951 12.254 1.00 0.00 +HETATM 413 H 1 17.860 10.940 10.923 1.00 0.00 +HETATM 414 H 1 19.093 8.960 10.046 1.00 0.00 +HETATM 415 H 1 18.446 7.968 11.372 1.00 0.00 +HETATM 416 H 1 19.573 9.448 13.030 1.00 0.00 +HETATM 417 H 1 20.221 10.440 11.703 1.00 0.00 +HETATM 418 H 1 20.748 8.752 11.891 1.00 0.00 +HETATM 419 H 1 6.625 -11.535 12.006 1.00 0.00 +HETATM 420 H 1 7.653 -10.282 12.735 1.00 0.00 +HETATM 421 H 1 9.075 -12.048 13.767 1.00 0.00 +HETATM 422 H 1 8.046 -13.303 13.036 1.00 0.00 +HETATM 423 H 1 7.378 -12.215 14.274 1.00 0.00 +HETATM 424 H 1 -2.762 -20.465 -4.223 1.00 0.00 +HETATM 425 H 1 -3.052 -20.802 -2.502 1.00 0.00 +HETATM 426 H 1 -4.423 -22.213 -4.847 1.00 0.00 +HETATM 427 H 1 -4.714 -22.551 -3.124 1.00 0.00 +HETATM 428 H 1 -3.123 -22.895 -3.842 1.00 0.00 +HETATM 429 H 1 3.124 -5.987 17.380 1.00 0.00 +HETATM 430 H 1 1.964 -6.995 16.486 1.00 0.00 +HETATM 431 H 1 0.758 -7.491 18.610 1.00 0.00 +HETATM 432 H 1 1.921 -6.484 19.504 1.00 0.00 +HETATM 433 H 1 2.464 -7.981 18.713 1.00 0.00 +HETATM 434 H 1 5.023 17.135 -10.744 1.00 0.00 +HETATM 435 H 1 4.500 15.996 -12.005 1.00 0.00 +HETATM 436 H 1 6.079 17.053 -13.616 1.00 0.00 +HETATM 437 H 1 6.604 18.192 -12.354 1.00 0.00 +HETATM 438 H 1 4.935 18.248 -12.965 1.00 0.00 +HETATM 439 H 1 7.973 22.680 5.906 1.00 0.00 +HETATM 440 H 1 6.926 22.873 7.330 1.00 0.00 +HETATM 441 H 1 6.871 25.336 6.956 1.00 0.00 +HETATM 442 H 1 7.919 25.143 5.532 1.00 0.00 +HETATM 443 H 1 8.540 24.757 7.153 1.00 0.00 +HETATM 444 H 1 -19.255 3.289 -6.856 1.00 0.00 +HETATM 445 H 1 -19.135 1.523 -7.009 1.00 0.00 +HETATM 446 H 1 -20.826 1.565 -8.838 1.00 0.00 +HETATM 447 H 1 -20.947 3.334 -8.684 1.00 0.00 +HETATM 448 H 1 -21.476 2.286 -7.348 1.00 0.00 +HETATM 449 H 1 -18.187 6.275 5.583 1.00 0.00 +HETATM 450 H 1 -17.597 7.553 4.497 1.00 0.00 +HETATM 451 H 1 -19.276 9.132 5.443 1.00 0.00 +HETATM 452 H 1 -19.866 7.853 6.529 1.00 0.00 +HETATM 453 H 1 -20.065 7.687 4.770 1.00 0.00 +CONECT 1 2 6 19 176 +CONECT 2 1 3 21 177 +CONECT 3 2 4 22 178 +CONECT 4 3 5 23 179 +CONECT 5 4 6 7 180 +CONECT 6 1 5 +CONECT 7 5 8 +CONECT 8 7 9 10 11 +CONECT 9 8 18 181 182 +CONECT 10 8 13 17 183 +CONECT 11 8 12 +CONECT 12 11 13 14 184 +CONECT 13 10 12 16 185 +CONECT 14 12 15 186 187 +CONECT 15 14 143 +CONECT 16 13 109 +CONECT 17 10 126 +CONECT 18 9 92 +CONECT 19 1 20 188 189 +CONECT 20 19 24 +CONECT 21 2 41 +CONECT 22 3 58 +CONECT 23 4 75 +CONECT 24 20 25 25 26 +CONECT 25 24 24 +CONECT 26 24 27 190 191 +CONECT 27 26 28 192 193 +CONECT 28 27 29 194 195 +CONECT 29 28 30 196 197 +CONECT 30 29 31 198 199 +CONECT 31 30 32 200 201 +CONECT 32 31 33 202 203 +CONECT 33 32 34 34 204 +CONECT 34 33 33 35 205 +CONECT 35 34 36 206 207 +CONECT 36 35 37 208 209 +CONECT 37 36 38 210 211 +CONECT 38 37 39 212 213 +CONECT 39 38 40 214 215 +CONECT 40 39 164 216 217 +CONECT 41 21 42 42 43 +CONECT 42 41 41 +CONECT 43 41 44 218 219 +CONECT 44 43 45 220 221 +CONECT 45 44 46 222 223 +CONECT 46 45 47 224 225 +CONECT 47 46 48 226 227 +CONECT 48 47 49 228 229 +CONECT 49 48 50 230 231 +CONECT 50 49 51 51 232 +CONECT 51 50 50 52 233 +CONECT 52 51 53 234 235 +CONECT 53 52 54 236 237 +CONECT 54 53 55 238 239 +CONECT 55 54 56 240 241 +CONECT 56 55 57 242 243 +CONECT 57 56 162 244 245 +CONECT 58 22 59 59 60 +CONECT 59 58 58 +CONECT 60 58 61 246 247 +CONECT 61 60 62 248 249 +CONECT 62 61 63 250 251 +CONECT 63 62 64 252 253 +CONECT 64 63 65 254 255 +CONECT 65 64 66 256 257 +CONECT 66 65 67 258 259 +CONECT 67 66 68 68 260 +CONECT 68 67 67 69 261 +CONECT 69 68 70 262 263 +CONECT 70 69 71 264 265 +CONECT 71 70 72 266 267 +CONECT 72 71 73 268 269 +CONECT 73 72 74 270 271 +CONECT 74 73 168 272 273 +CONECT 75 23 76 76 77 +CONECT 76 75 75 +CONECT 77 75 78 274 275 +CONECT 78 77 79 276 277 +CONECT 79 78 80 278 279 +CONECT 80 79 81 280 281 +CONECT 81 80 82 282 283 +CONECT 82 81 83 284 285 +CONECT 83 82 84 286 287 +CONECT 84 83 85 85 288 +CONECT 85 84 84 86 289 +CONECT 86 85 87 290 291 +CONECT 87 86 88 292 293 +CONECT 88 87 89 294 295 +CONECT 89 88 90 296 297 +CONECT 90 89 91 298 299 +CONECT 91 90 166 300 301 +CONECT 92 18 93 93 94 +CONECT 93 92 92 +CONECT 94 92 95 302 303 +CONECT 95 94 96 304 305 +CONECT 96 95 97 306 307 +CONECT 97 96 98 308 309 +CONECT 98 97 99 310 311 +CONECT 99 98 100 312 313 +CONECT 100 99 101 314 315 +CONECT 101 100 102 102 316 +CONECT 102 101 101 103 317 +CONECT 103 102 104 318 319 +CONECT 104 103 105 320 321 +CONECT 105 104 106 322 323 +CONECT 106 105 107 324 325 +CONECT 107 106 108 326 327 +CONECT 108 107 172 328 329 +CONECT 109 16 110 110 111 +CONECT 110 109 109 +CONECT 111 109 112 330 331 +CONECT 112 111 113 332 333 +CONECT 113 112 114 334 335 +CONECT 114 113 115 336 337 +CONECT 115 114 116 338 339 +CONECT 116 115 117 340 341 +CONECT 117 116 118 342 343 +CONECT 118 117 119 119 344 +CONECT 119 118 118 120 345 +CONECT 120 119 121 346 347 +CONECT 121 120 122 348 349 +CONECT 122 121 123 350 351 +CONECT 123 122 124 352 353 +CONECT 124 123 125 354 355 +CONECT 125 124 170 356 357 +CONECT 126 17 127 127 128 +CONECT 127 126 126 +CONECT 128 126 129 358 359 +CONECT 129 128 130 360 361 +CONECT 130 129 131 362 363 +CONECT 131 130 132 364 365 +CONECT 132 131 133 366 367 +CONECT 133 132 134 368 369 +CONECT 134 133 135 370 371 +CONECT 135 134 136 136 372 +CONECT 136 135 135 137 373 +CONECT 137 136 138 374 375 +CONECT 138 137 139 376 377 +CONECT 139 138 140 378 379 +CONECT 140 139 141 380 381 +CONECT 141 140 142 382 383 +CONECT 142 141 174 384 385 +CONECT 143 15 144 144 145 +CONECT 144 143 143 +CONECT 145 143 146 386 387 +CONECT 146 145 147 388 389 +CONECT 147 146 148 390 391 +CONECT 148 147 149 392 393 +CONECT 149 148 150 394 395 +CONECT 150 149 151 396 397 +CONECT 151 150 152 398 399 +CONECT 152 151 153 153 400 +CONECT 153 152 152 154 401 +CONECT 154 153 155 402 403 +CONECT 155 154 156 404 405 +CONECT 156 155 157 406 407 +CONECT 157 156 158 408 409 +CONECT 158 157 159 410 411 +CONECT 159 158 160 412 413 +CONECT 160 159 161 414 415 +CONECT 161 160 416 417 418 +CONECT 162 57 163 419 420 +CONECT 163 162 421 422 423 +CONECT 164 40 165 424 425 +CONECT 165 164 426 427 428 +CONECT 166 91 167 429 430 +CONECT 167 166 431 432 433 +CONECT 168 74 169 434 435 +CONECT 169 168 436 437 438 +CONECT 170 125 171 439 440 +CONECT 171 170 441 442 443 +CONECT 172 108 173 444 445 +CONECT 173 172 446 447 448 +CONECT 174 142 175 449 450 +CONECT 175 174 451 452 453 +CONECT 176 1 +CONECT 177 2 +CONECT 178 3 +CONECT 179 4 +CONECT 180 5 +CONECT 181 9 +CONECT 182 9 +CONECT 183 10 +CONECT 184 12 +CONECT 185 13 +CONECT 186 14 +CONECT 187 14 +CONECT 188 19 +CONECT 189 19 +CONECT 190 26 +CONECT 191 26 +CONECT 192 27 +CONECT 193 27 +CONECT 194 28 +CONECT 195 28 +CONECT 196 29 +CONECT 197 29 +CONECT 198 30 +CONECT 199 30 +CONECT 200 31 +CONECT 201 31 +CONECT 202 32 +CONECT 203 32 +CONECT 204 33 +CONECT 205 34 +CONECT 206 35 +CONECT 207 35 +CONECT 208 36 +CONECT 209 36 +CONECT 210 37 +CONECT 211 37 +CONECT 212 38 +CONECT 213 38 +CONECT 214 39 +CONECT 215 39 +CONECT 216 40 +CONECT 217 40 +CONECT 218 43 +CONECT 219 43 +CONECT 220 44 +CONECT 221 44 +CONECT 222 45 +CONECT 223 45 +CONECT 224 46 +CONECT 225 46 +CONECT 226 47 +CONECT 227 47 +CONECT 228 48 +CONECT 229 48 +CONECT 230 49 +CONECT 231 49 +CONECT 232 50 +CONECT 233 51 +CONECT 234 52 +CONECT 235 52 +CONECT 236 53 +CONECT 237 53 +CONECT 238 54 +CONECT 239 54 +CONECT 240 55 +CONECT 241 55 +CONECT 242 56 +CONECT 243 56 +CONECT 244 57 +CONECT 245 57 +CONECT 246 60 +CONECT 247 60 +CONECT 248 61 +CONECT 249 61 +CONECT 250 62 +CONECT 251 62 +CONECT 252 63 +CONECT 253 63 +CONECT 254 64 +CONECT 255 64 +CONECT 256 65 +CONECT 257 65 +CONECT 258 66 +CONECT 259 66 +CONECT 260 67 +CONECT 261 68 +CONECT 262 69 +CONECT 263 69 +CONECT 264 70 +CONECT 265 70 +CONECT 266 71 +CONECT 267 71 +CONECT 268 72 +CONECT 269 72 +CONECT 270 73 +CONECT 271 73 +CONECT 272 74 +CONECT 273 74 +CONECT 274 77 +CONECT 275 77 +CONECT 276 78 +CONECT 277 78 +CONECT 278 79 +CONECT 279 79 +CONECT 280 80 +CONECT 281 80 +CONECT 282 81 +CONECT 283 81 +CONECT 284 82 +CONECT 285 82 +CONECT 286 83 +CONECT 287 83 +CONECT 288 84 +CONECT 289 85 +CONECT 290 86 +CONECT 291 86 +CONECT 292 87 +CONECT 293 87 +CONECT 294 88 +CONECT 295 88 +CONECT 296 89 +CONECT 297 89 +CONECT 298 90 +CONECT 299 90 +CONECT 300 91 +CONECT 301 91 +CONECT 302 94 +CONECT 303 94 +CONECT 304 95 +CONECT 305 95 +CONECT 306 96 +CONECT 307 96 +CONECT 308 97 +CONECT 309 97 +CONECT 310 98 +CONECT 311 98 +CONECT 312 99 +CONECT 313 99 +CONECT 314 100 +CONECT 315 100 +CONECT 316 101 +CONECT 317 102 +CONECT 318 103 +CONECT 319 103 +CONECT 320 104 +CONECT 321 104 +CONECT 322 105 +CONECT 323 105 +CONECT 324 106 +CONECT 325 106 +CONECT 326 107 +CONECT 327 107 +CONECT 328 108 +CONECT 329 108 +CONECT 330 111 +CONECT 331 111 +CONECT 332 112 +CONECT 333 112 +CONECT 334 113 +CONECT 335 113 +CONECT 336 114 +CONECT 337 114 +CONECT 338 115 +CONECT 339 115 +CONECT 340 116 +CONECT 341 116 +CONECT 342 117 +CONECT 343 117 +CONECT 344 118 +CONECT 345 119 +CONECT 346 120 +CONECT 347 120 +CONECT 348 121 +CONECT 349 121 +CONECT 350 122 +CONECT 351 122 +CONECT 352 123 +CONECT 353 123 +CONECT 354 124 +CONECT 355 124 +CONECT 356 125 +CONECT 357 125 +CONECT 358 128 +CONECT 359 128 +CONECT 360 129 +CONECT 361 129 +CONECT 362 130 +CONECT 363 130 +CONECT 364 131 +CONECT 365 131 +CONECT 366 132 +CONECT 367 132 +CONECT 368 133 +CONECT 369 133 +CONECT 370 134 +CONECT 371 134 +CONECT 372 135 +CONECT 373 136 +CONECT 374 137 +CONECT 375 137 +CONECT 376 138 +CONECT 377 138 +CONECT 378 139 +CONECT 379 139 +CONECT 380 140 +CONECT 381 140 +CONECT 382 141 +CONECT 383 141 +CONECT 384 142 +CONECT 385 142 +CONECT 386 145 +CONECT 387 145 +CONECT 388 146 +CONECT 389 146 +CONECT 390 147 +CONECT 391 147 +CONECT 392 148 +CONECT 393 148 +CONECT 394 149 +CONECT 395 149 +CONECT 396 150 +CONECT 397 150 +CONECT 398 151 +CONECT 399 151 +CONECT 400 152 +CONECT 401 153 +CONECT 402 154 +CONECT 403 154 +CONECT 404 155 +CONECT 405 155 +CONECT 406 156 +CONECT 407 156 +CONECT 408 157 +CONECT 409 157 +CONECT 410 158 +CONECT 411 158 +CONECT 412 159 +CONECT 413 159 +CONECT 414 160 +CONECT 415 160 +CONECT 416 161 +CONECT 417 161 +CONECT 418 161 +CONECT 419 162 +CONECT 420 162 +CONECT 421 163 +CONECT 422 163 +CONECT 423 163 +CONECT 424 164 +CONECT 425 164 +CONECT 426 165 +CONECT 427 165 +CONECT 428 165 +CONECT 429 166 +CONECT 430 166 +CONECT 431 167 +CONECT 432 167 +CONECT 433 167 +CONECT 434 168 +CONECT 435 168 +CONECT 436 169 +CONECT 437 169 +CONECT 438 169 +CONECT 439 170 +CONECT 440 170 +CONECT 441 171 +CONECT 442 171 +CONECT 443 171 +CONECT 444 172 +CONECT 445 172 +CONECT 446 173 +CONECT 447 173 +CONECT 448 173 +CONECT 449 174 +CONECT 450 174 +CONECT 451 175 +CONECT 452 175 +CONECT 453 175 +MASTER 0 0 0 0 0 0 0 0 453 0 453 0 +END diff --git a/hacks/images/molecules/penicillin.pdb b/hacks/images/molecules/penicillin.pdb new file mode 100644 index 00000000..54732f54 --- /dev/null +++ b/hacks/images/molecules/penicillin.pdb @@ -0,0 +1,89 @@ +HEADER Penicillin G, an antibiotic +COMPND al3077 +AUTHOR Created by Dave Woodcock at Okanagan University College +AUTHOR email:woodcock@okanagan.bc.ca +AUTHOR Date revised: Wed Aug 30 12:33:12 2000 GENERATED BY BABEL 1.6 +HETATM 1 C 1 0.000 0.000 0.000 1.00 0.00 +HETATM 2 C 1 1.542 0.000 0.000 1.00 0.00 +HETATM 3 C 1 1.415 1.509 0.000 1.00 0.00 +HETATM 4 O 1 2.209 2.398 -0.083 1.00 0.00 +HETATM 5 N 1 0.066 1.475 0.061 1.00 0.00 +HETATM 6 N 1 2.125 -0.528 1.243 1.00 0.00 +HETATM 7 C 1 2.235 -1.858 1.457 1.00 0.00 +HETATM 8 O 1 2.669 -2.251 2.509 1.00 0.00 +HETATM 9 C 1 1.827 -2.860 0.414 1.00 0.00 +HETATM 10 C 1 1.446 -4.153 1.098 1.00 0.00 +HETATM 11 C 1 0.143 -4.328 1.578 1.00 0.00 +HETATM 12 C 1 -0.216 -5.521 2.214 1.00 0.00 +HETATM 13 C 1 0.729 -6.540 2.373 1.00 0.00 +HETATM 14 C 1 2.034 -6.363 1.902 1.00 0.00 +HETATM 15 C 1 2.393 -5.168 1.268 1.00 0.00 +HETATM 16 S 1 -0.818 -0.450 1.519 1.00 0.00 +HETATM 17 C 1 -1.605 1.127 1.810 1.00 0.00 +HETATM 18 C 1 -1.800 1.394 3.317 1.00 0.00 +HETATM 19 C 1 -2.966 1.138 1.082 1.00 0.00 +HETATM 20 C 1 -0.629 2.147 1.173 1.00 0.00 +HETATM 21 C 1 -1.351 3.368 0.682 1.00 0.00 +HETATM 22 O 1 -1.537 3.505 -0.499 1.00 0.00 +HETATM 23 O 1 -2.048 4.114 1.557 1.00 0.00 +HETATM 24 H 1 -0.466 -0.363 -0.916 1.00 0.00 +HETATM 25 H 1 1.982 -0.387 -0.919 1.00 0.00 +HETATM 26 H 1 2.409 0.115 1.973 1.00 0.00 +HETATM 27 H 1 2.660 -3.033 -0.268 1.00 0.00 +HETATM 28 H 1 0.971 -2.493 -0.151 1.00 0.00 +HETATM 29 H 1 -0.596 -3.536 1.454 1.00 0.00 +HETATM 30 H 1 -1.232 -5.657 2.584 1.00 0.00 +HETATM 31 H 1 0.449 -7.470 2.868 1.00 0.00 +HETATM 32 H 1 2.772 -7.155 2.030 1.00 0.00 +HETATM 33 H 1 3.412 -5.032 0.906 1.00 0.00 +HETATM 34 H 1 -0.839 1.345 3.829 1.00 0.00 +HETATM 35 H 1 -2.470 0.644 3.739 1.00 0.00 +HETATM 36 H 1 -2.233 2.384 3.459 1.00 0.00 +HETATM 37 H 1 -3.586 0.322 1.454 1.00 0.00 +HETATM 38 H 1 -2.811 1.012 0.010 1.00 0.00 +HETATM 39 H 1 -3.480 2.082 1.263 1.00 0.00 +HETATM 40 H 1 0.108 2.446 1.919 1.00 0.00 +HETATM 41 H 1 -2.798 4.548 1.098 1.00 0.00 +CONECT 1 2 5 16 24 +CONECT 2 1 3 6 25 +CONECT 3 2 4 4 5 +CONECT 4 3 3 +CONECT 5 1 3 20 +CONECT 6 2 7 26 +CONECT 7 6 8 8 9 +CONECT 8 7 7 +CONECT 9 7 10 27 28 +CONECT 10 9 11 11 15 +CONECT 11 10 10 12 29 +CONECT 12 11 13 13 30 +CONECT 13 12 12 14 31 +CONECT 14 13 15 15 32 +CONECT 15 10 14 14 33 +CONECT 16 1 17 +CONECT 17 16 18 19 20 +CONECT 18 17 34 35 36 +CONECT 19 17 37 38 39 +CONECT 20 5 17 21 40 +CONECT 21 20 22 22 23 +CONECT 22 21 21 +CONECT 23 21 41 +CONECT 24 1 +CONECT 25 2 +CONECT 26 6 +CONECT 27 9 +CONECT 28 9 +CONECT 29 11 +CONECT 30 12 +CONECT 31 13 +CONECT 32 14 +CONECT 33 15 +CONECT 34 18 +CONECT 35 18 +CONECT 36 18 +CONECT 37 19 +CONECT 38 19 +CONECT 39 19 +CONECT 40 20 +CONECT 41 23 +MASTER 0 0 0 0 0 0 0 0 41 0 41 0 +END diff --git a/hacks/images/molecules/salvinorin.pdb b/hacks/images/molecules/salvinorin.pdb new file mode 100644 index 00000000..6ac445b2 --- /dev/null +++ b/hacks/images/molecules/salvinorin.pdb @@ -0,0 +1,92 @@ +HEADER Salvinorin A: A dissociative hallucinogen, kappa opioid receptor agonist +ATOM 1 O 0 -1.578 3.509 1.054 0.00 0.00 O+0 +ATOM 2 O 0 -0.661 -3.341 -1.950 0.00 0.00 O+0 +ATOM 3 O 0 -0.961 -0.736 -2.292 0.00 0.00 O+0 +ATOM 4 O 0 0.223 4.284 1.789 0.00 0.00 O+0 +ATOM 5 O 0 4.133 -2.520 1.067 0.00 0.00 O+0 +ATOM 6 O 0 4.305 -2.225 -1.047 0.00 0.00 O+0 +ATOM 7 O 0 -5.473 1.972 2.519 0.00 0.00 O+0 +ATOM 8 O 0 -1.864 -4.598 -3.067 0.00 0.00 O+0 +ATOM 9 C 0 1.875 -0.263 -0.355 0.00 0.00 C+0 +ATOM 10 C 0 -0.335 1.379 -0.322 0.00 0.00 C+0 +ATOM 11 C 0 0.290 -0.090 -0.402 0.00 0.00 C+0 +ATOM 12 C 0 0.295 2.080 0.949 0.00 0.00 C+0 +ATOM 13 C 0 2.416 0.613 0.838 0.00 0.00 C+0 +ATOM 14 C 0 2.218 -1.798 -0.082 0.00 0.00 C+0 +ATOM 15 C 0 1.854 2.057 0.955 0.00 0.00 C+0 +ATOM 16 C 0 -1.892 1.349 -0.054 0.00 0.00 C+0 +ATOM 17 C 0 -0.312 -1.076 -1.312 0.00 0.00 C+0 +ATOM 18 C 0 1.427 -2.783 -1.008 0.00 0.00 C+0 +ATOM 19 C 0 2.599 0.182 -1.678 0.00 0.00 C+0 +ATOM 20 C 0 -0.152 2.242 -1.623 0.00 0.00 C+0 +ATOM 21 C 0 -0.102 -2.502 -1.056 0.00 0.00 C+0 +ATOM 22 C 0 -2.483 2.720 0.438 0.00 0.00 C+0 +ATOM 23 C 0 -0.364 3.344 1.274 0.00 0.00 C+0 +ATOM 24 C 0 3.632 -2.188 -0.023 0.00 0.00 C+0 +ATOM 25 C 0 -3.721 2.668 1.259 0.00 0.00 C+0 +ATOM 26 C 0 -4.516 3.764 1.594 0.00 0.00 C+0 +ATOM 27 C 0 -4.363 1.580 1.857 0.00 0.00 C+0 +ATOM 28 C 0 -1.768 -3.894 -2.073 0.00 0.00 C+0 +ATOM 29 C 0 5.353 -2.949 1.401 0.00 0.00 C+0 +ATOM 30 C 0 -5.577 3.309 2.365 0.00 0.00 C+0 +ATOM 31 C 0 -2.903 -3.782 -1.178 0.00 0.00 C+0 +ATOM 32 H 0 -0.032 -0.494 0.566 0.00 0.00 H+0 +ATOM 33 H 0 0.021 1.488 1.831 0.00 0.00 H+0 +ATOM 34 H 0 2.176 0.125 1.788 0.00 0.00 H+0 +ATOM 35 H 0 3.509 0.668 0.818 0.00 0.00 H+0 +ATOM 36 H 0 1.806 -2.023 0.910 0.00 0.00 H+0 +ATOM 37 H 0 2.250 2.682 0.154 0.00 0.00 H+0 +ATOM 38 H 0 2.226 2.485 1.891 0.00 0.00 H+0 +ATOM 39 H 0 -2.454 1.020 -0.933 0.00 0.00 H+0 +ATOM 40 H 0 -2.074 0.590 0.706 0.00 0.00 H+0 +ATOM 41 H 0 1.574 -3.811 -0.660 0.00 0.00 H+0 +ATOM 42 H 0 1.827 -2.744 -2.026 0.00 0.00 H+0 +ATOM 43 H 0 2.260 -0.386 -2.545 0.00 0.00 H+0 +ATOM 44 H 0 2.509 1.228 -1.923 0.00 0.00 H+0 +ATOM 45 H 0 3.681 0.081 -1.611 0.00 0.00 H+0 +ATOM 46 H 0 -0.558 1.749 -2.507 0.00 0.00 H+0 +ATOM 47 H 0 -0.638 3.215 -1.562 0.00 0.00 H+0 +ATOM 48 H 0 0.868 2.520 -1.836 0.00 0.00 H+0 +ATOM 49 H 0 -0.497 -2.735 -0.061 0.00 0.00 H+0 +ATOM 50 H 0 -2.764 3.279 -0.460 0.00 0.00 H+0 +ATOM 51 H 0 -4.357 4.736 1.321 0.00 0.00 H+0 +ATOM 52 H 0 -4.064 0.605 1.821 0.00 0.00 H+0 +ATOM 53 H 0 5.360 -3.151 2.472 0.00 0.00 H+0 +ATOM 54 H 0 6.112 -2.193 1.186 0.00 0.00 H+0 +ATOM 55 H 0 5.605 -3.873 0.875 0.00 0.00 H+0 +ATOM 56 H 0 -6.323 3.886 2.756 0.00 0.00 H+0 +ATOM 57 H 0 -3.222 -2.742 -1.105 0.00 0.00 H+0 +ATOM 58 H 0 -2.636 -4.143 -0.184 0.00 0.00 H+0 +ATOM 59 H 0 -3.759 -4.370 -1.521 0.00 0.00 H+0 +CONECT 1 22 23 0 0 NONE 65 +CONECT 2 21 28 0 0 NONE 66 +CONECT 3 17 0 0 0 NONE 67 +CONECT 4 23 0 0 0 NONE 68 +CONECT 5 24 29 0 0 NONE 69 +CONECT 6 24 0 0 0 NONE 70 +CONECT 7 27 30 0 0 NONE 71 +CONECT 8 28 0 0 0 NONE 72 +CONECT 9 11 13 14 19 NONE 73 +CONECT 10 11 12 16 20 NONE 74 +CONECT 11 9 10 17 32 NONE 75 +CONECT 12 10 15 23 33 NONE 76 +CONECT 13 9 15 34 35 NONE 77 +CONECT 14 9 18 24 36 NONE 78 +CONECT 15 12 13 37 38 NONE 79 +CONECT 16 10 22 39 40 NONE 80 +CONECT 17 3 11 21 0 NONE 81 +CONECT 18 14 21 41 42 NONE 82 +CONECT 19 9 43 44 45 NONE 83 +CONECT 20 10 46 47 48 NONE 84 +CONECT 21 2 17 18 49 NONE 85 +CONECT 22 1 16 25 50 NONE 86 +CONECT 23 1 4 12 0 NONE 87 +CONECT 24 5 6 14 0 NONE 88 +CONECT 25 22 26 27 0 NONE 89 +CONECT 26 25 30 51 0 NONE 90 +CONECT 27 7 25 52 0 NONE 91 +CONECT 28 2 8 31 0 NONE 92 +CONECT 29 5 53 54 55 NONE 93 +CONECT 30 7 26 56 0 NONE 94 +CONECT 31 28 57 58 59 NONE 95 +END NONE 96 diff --git a/hacks/images/molecules/sarin.pdb b/hacks/images/molecules/sarin.pdb new file mode 100644 index 00000000..ae030286 --- /dev/null +++ b/hacks/images/molecules/sarin.pdb @@ -0,0 +1,43 @@ +HEADER Sarin: S Enantiomer, a chemical warfare agent +COMPND al3023 +AUTHOR Created by Dave Woodcock at Okanagan University College +AUTHOR email:woodcock@okanagan.bc.ca +AUTHOR Date revised: Wed Aug 30 12:33:12 2000 GENERATED BY BABEL 1.6 +HETATM 1 P 1 0.000 0.000 0.000 1.00 0.00 +HETATM 2 F 1 1.779 0.000 0.000 1.00 0.00 +HETATM 3 C 1 -0.611 1.725 0.000 1.00 0.00 +HETATM 4 O 1 -0.599 -0.840 1.463 1.00 0.00 +HETATM 5 O 1 -0.599 -0.841 -1.466 1.00 0.00 +HETATM 6 C 1 -1.898 -1.369 -1.304 1.00 0.00 +HETATM 7 C 1 -1.817 -2.772 -0.672 1.00 0.00 +HETATM 8 C 1 -2.555 -1.476 -2.694 1.00 0.00 +HETATM 9 H 1 -0.248 2.240 -0.890 1.00 0.00 +HETATM 10 H 1 -0.248 2.239 0.891 1.00 0.00 +HETATM 11 H 1 -1.701 1.724 0.000 1.00 0.00 +HETATM 12 H 1 -2.510 -0.718 -0.679 1.00 0.00 +HETATM 13 H 1 -1.372 -2.712 0.320 1.00 0.00 +HETATM 14 H 1 -1.203 -3.414 -1.303 1.00 0.00 +HETATM 15 H 1 -2.818 -3.194 -0.591 1.00 0.00 +HETATM 16 H 1 -1.961 -2.124 -3.339 1.00 0.00 +HETATM 17 H 1 -3.561 -1.885 -2.595 1.00 0.00 +HETATM 18 H 1 -2.613 -0.482 -3.136 1.00 0.00 +CONECT 1 2 3 4 4 5 +CONECT 2 1 +CONECT 3 1 9 10 11 +CONECT 4 1 1 +CONECT 5 1 6 +CONECT 6 5 7 8 12 +CONECT 7 6 13 14 15 +CONECT 8 6 16 17 18 +CONECT 9 3 +CONECT 10 3 +CONECT 11 3 +CONECT 12 6 +CONECT 13 7 +CONECT 14 7 +CONECT 15 7 +CONECT 16 8 +CONECT 17 8 +CONECT 18 8 +MASTER 0 0 0 0 0 0 0 0 18 0 18 0 +END diff --git a/hacks/images/molecules/strychnine.pdb b/hacks/images/molecules/strychnine.pdb new file mode 100644 index 00000000..ecb0762b --- /dev/null +++ b/hacks/images/molecules/strychnine.pdb @@ -0,0 +1,101 @@ +HEADER Strychnine: Nux Vomica +COMPND al3061 +AUTHOR Created by Dave Woodcock at Okanagan University College +AUTHOR email:woodcock@okanagan.bc.ca +AUTHOR Date revised: Wed Aug 30 12:33:12 2000 GENERATED BY BABEL 1.6 +HETATM 1 C 1 0.000 0.000 0.000 1.00 0.00 +HETATM 2 C 1 1.395 0.000 0.000 1.00 0.00 +HETATM 3 C 1 2.124 1.193 0.000 1.00 0.00 +HETATM 4 C 1 1.414 2.398 -0.067 1.00 0.00 +HETATM 5 C 1 0.014 2.401 -0.115 1.00 0.00 +HETATM 6 C 1 -0.709 1.203 -0.087 1.00 0.00 +HETATM 7 C 1 1.911 -1.410 0.160 1.00 0.00 +HETATM 8 N 1 -0.471 -1.291 -0.057 1.00 0.00 +HETATM 9 C 1 -1.720 -1.604 -0.472 1.00 0.00 +HETATM 10 O 1 -2.589 -0.778 -0.359 1.00 0.00 +HETATM 11 C 1 0.645 -2.239 -0.189 1.00 0.00 +HETATM 12 C 1 -1.941 -2.698 -1.483 1.00 0.00 +HETATM 13 C 1 -0.687 -3.549 -1.797 1.00 0.00 +HETATM 14 H 1 0.525 -3.093 0.477 1.00 0.00 +HETATM 15 C 1 0.573 -2.674 -1.656 1.00 0.00 +HETATM 16 H 1 -0.775 -3.908 -2.822 1.00 0.00 +HETATM 17 O 1 -0.654 -4.641 -0.904 1.00 0.00 +HETATM 18 C 1 0.221 -5.671 -1.313 1.00 0.00 +HETATM 19 C 1 1.595 -5.446 -0.726 1.00 0.00 +HETATM 20 C 1 2.356 -4.403 -1.088 1.00 0.00 +HETATM 21 C 1 3.723 -4.222 -0.464 1.00 0.00 +HETATM 22 C 1 1.893 -3.351 -2.072 1.00 0.00 +HETATM 23 H 1 0.431 -1.791 -2.279 1.00 0.00 +HETATM 24 H 1 1.803 -3.769 -3.074 1.00 0.00 +HETATM 25 C 1 2.942 -2.222 -2.062 1.00 0.00 +HETATM 26 C 1 3.199 -1.816 -0.595 1.00 0.00 +HETATM 27 C 1 2.322 -1.641 1.618 1.00 0.00 +HETATM 28 C 1 3.109 -2.956 1.512 1.00 0.00 +HETATM 29 N 1 3.783 -2.911 0.202 1.00 0.00 +HETATM 30 H 1 3.212 1.188 0.059 1.00 0.00 +HETATM 31 H 1 1.957 3.343 -0.078 1.00 0.00 +HETATM 32 H 1 -0.520 3.349 -0.172 1.00 0.00 +HETATM 33 H 1 -1.798 1.219 -0.127 1.00 0.00 +HETATM 34 H 1 -2.263 -2.218 -2.408 1.00 0.00 +HETATM 35 H 1 -2.740 -3.355 -1.139 1.00 0.00 +HETATM 36 H 1 0.290 -5.733 -2.400 1.00 0.00 +HETATM 37 H 1 -0.163 -6.618 -0.935 1.00 0.00 +HETATM 38 H 1 1.974 -6.159 0.006 1.00 0.00 +HETATM 39 H 1 4.483 -4.272 -1.243 1.00 0.00 +HETATM 40 H 1 3.923 -5.012 0.260 1.00 0.00 +HETATM 41 H 1 2.578 -1.363 -2.625 1.00 0.00 +HETATM 42 H 1 3.871 -2.566 -2.519 1.00 0.00 +HETATM 43 H 1 3.898 -0.980 -0.573 1.00 0.00 +HETATM 44 H 1 1.464 -1.724 2.285 1.00 0.00 +HETATM 45 H 1 2.987 -0.840 1.943 1.00 0.00 +HETATM 46 H 1 2.413 -3.794 1.551 1.00 0.00 +HETATM 47 H 1 3.833 -3.042 2.322 1.00 0.00 +CONECT 1 2 2 6 8 +CONECT 2 1 1 3 7 +CONECT 3 2 4 4 30 +CONECT 4 3 3 5 31 +CONECT 5 4 6 6 32 +CONECT 6 1 5 5 33 +CONECT 7 2 11 26 27 +CONECT 8 1 9 11 +CONECT 9 8 10 10 12 +CONECT 10 9 9 +CONECT 11 7 8 14 15 +CONECT 12 9 13 34 35 +CONECT 13 12 15 16 17 +CONECT 14 11 +CONECT 15 11 13 22 23 +CONECT 16 13 +CONECT 17 13 18 +CONECT 18 17 19 36 37 +CONECT 19 18 20 20 38 +CONECT 20 19 19 21 22 +CONECT 21 20 29 39 40 +CONECT 22 15 20 24 25 +CONECT 23 15 +CONECT 24 22 +CONECT 25 22 26 41 42 +CONECT 26 7 25 29 43 +CONECT 27 7 28 44 45 +CONECT 28 27 29 46 47 +CONECT 29 21 26 28 +CONECT 30 3 +CONECT 31 4 +CONECT 32 5 +CONECT 33 6 +CONECT 34 12 +CONECT 35 12 +CONECT 36 18 +CONECT 37 18 +CONECT 38 19 +CONECT 39 21 +CONECT 40 21 +CONECT 41 25 +CONECT 42 25 +CONECT 43 26 +CONECT 44 27 +CONECT 45 27 +CONECT 46 28 +CONECT 47 28 +MASTER 0 0 0 0 0 0 0 0 47 0 47 0 +END diff --git a/hacks/images/molecules/sucrose.pdb b/hacks/images/molecules/sucrose.pdb new file mode 100644 index 00000000..2a75f22f --- /dev/null +++ b/hacks/images/molecules/sucrose.pdb @@ -0,0 +1,97 @@ +HEADER Sucrose: Sugar +COMPND nat0013 +AUTHOR Created by Dave Woodcock at Okanagan University College +AUTHOR email:woodcock@okanagan.bc.ca +AUTHOR Date revised: Fri Sep 1 09:41:05 2000 GENERATED BY BABEL 1.6 +HETATM 1 C 1 0.000 0.000 0.000 1.00 0.00 +HETATM 2 C 1 1.542 0.000 0.000 1.00 0.00 +HETATM 3 C 1 2.041 1.457 0.000 1.00 0.00 +HETATM 4 C 1 1.414 2.181 1.207 1.00 0.00 +HETATM 5 C 1 -0.117 2.034 1.128 1.00 0.00 +HETATM 6 O 1 -0.472 0.668 1.149 1.00 0.00 +HETATM 7 H 1 -0.566 2.548 1.978 1.00 0.00 +HETATM 8 O 1 -0.572 2.607 -0.076 1.00 0.00 +HETATM 9 C 1 -1.867 3.149 -0.193 1.00 0.00 +HETATM 10 C 1 -1.993 3.815 -1.579 1.00 0.00 +HETATM 11 C 1 -2.960 2.084 -0.002 1.00 0.00 +HETATM 12 O 1 -2.117 4.104 0.816 1.00 0.00 +HETATM 13 C 1 -3.516 4.220 0.978 1.00 0.00 +HETATM 14 C 1 -4.167 2.959 0.369 1.00 0.00 +HETATM 15 H 1 -0.368 0.500 -0.896 1.00 0.00 +HETATM 16 H 1 1.901 -0.501 0.899 1.00 0.00 +HETATM 17 H 1 1.728 1.949 -0.923 1.00 0.00 +HETATM 18 H 1 1.774 1.726 2.130 1.00 0.00 +HETATM 19 H 1 -1.836 3.065 -2.355 1.00 0.00 +HETATM 20 H 1 -2.981 4.259 -1.698 1.00 0.00 +HETATM 21 H 1 -3.133 1.511 -0.914 1.00 0.00 +HETATM 22 H 1 -3.871 5.100 0.441 1.00 0.00 +HETATM 23 H 1 -4.821 2.452 1.081 1.00 0.00 +HETATM 24 C 1 -3.859 4.364 2.474 1.00 0.00 +HETATM 25 O 1 -5.279 4.442 2.639 1.00 0.00 +HETATM 26 O 1 -4.897 3.325 -0.807 1.00 0.00 +HETATM 27 O 1 -2.638 1.202 1.079 1.00 0.00 +HETATM 28 O 1 -0.995 4.834 -1.694 1.00 0.00 +HETATM 29 C 1 -0.513 -1.453 0.003 1.00 0.00 +HETATM 30 O 1 -1.944 -1.459 -0.055 1.00 0.00 +HETATM 31 O 1 2.039 -0.690 -1.152 1.00 0.00 +HETATM 32 O 1 3.468 1.480 0.101 1.00 0.00 +HETATM 33 O 1 1.772 3.567 1.189 1.00 0.00 +HETATM 34 H 1 -3.396 5.270 2.866 1.00 0.00 +HETATM 35 H 1 -3.480 3.504 3.024 1.00 0.00 +HETATM 36 H 1 -5.622 5.216 2.180 1.00 0.00 +HETATM 37 H 1 -5.302 2.544 -1.199 1.00 0.00 +HETATM 38 H 1 -2.661 1.671 1.919 1.00 0.00 +HETATM 39 H 1 -1.056 5.255 -2.558 1.00 0.00 +HETATM 40 H 1 -0.180 -1.958 0.910 1.00 0.00 +HETATM 41 H 1 -0.118 -1.977 -0.868 1.00 0.00 +HETATM 42 H 1 -2.305 -1.058 0.741 1.00 0.00 +HETATM 43 H 1 1.728 -0.261 -1.956 1.00 0.00 +HETATM 44 H 1 3.781 2.391 0.099 1.00 0.00 +HETATM 45 H 1 1.428 3.987 0.394 1.00 0.00 +CONECT 1 2 6 15 29 +CONECT 2 1 3 16 31 +CONECT 3 2 4 17 32 +CONECT 4 3 5 18 33 +CONECT 5 4 6 7 8 +CONECT 6 1 5 +CONECT 7 5 +CONECT 8 5 9 +CONECT 9 8 10 11 12 +CONECT 10 9 19 20 28 +CONECT 11 9 14 21 27 +CONECT 12 9 13 +CONECT 13 12 14 22 24 +CONECT 14 11 13 23 26 +CONECT 15 1 +CONECT 16 2 +CONECT 17 3 +CONECT 18 4 +CONECT 19 10 +CONECT 20 10 +CONECT 21 11 +CONECT 22 13 +CONECT 23 14 +CONECT 24 13 25 34 35 +CONECT 25 24 36 +CONECT 26 14 37 +CONECT 27 11 38 +CONECT 28 10 39 +CONECT 29 1 30 40 41 +CONECT 30 29 42 +CONECT 31 2 43 +CONECT 32 3 44 +CONECT 33 4 45 +CONECT 34 24 +CONECT 35 24 +CONECT 36 25 +CONECT 37 26 +CONECT 38 27 +CONECT 39 28 +CONECT 40 29 +CONECT 41 29 +CONECT 42 30 +CONECT 43 31 +CONECT 44 32 +CONECT 45 33 +MASTER 0 0 0 0 0 0 0 0 45 0 45 0 +END diff --git a/hacks/images/molecules/thalidomide.pdb b/hacks/images/molecules/thalidomide.pdb new file mode 100644 index 00000000..f3edb72d --- /dev/null +++ b/hacks/images/molecules/thalidomide.pdb @@ -0,0 +1,65 @@ +HEADER (S)-Thalidomide, a teratogenic enantiomer +COMPND jb03stha +AUTHOR Created by Dave Woodcock at Okanagan University College +AUTHOR email:woodcock@okanagan.bc.ca +AUTHOR Date revised: Mon Sep 18 15:35:27 2000 GENERATED BY BABEL 1.6 +HETATM 1 C 1 0.000 0.000 0.000 1.00 0.00 +HETATM 2 C 1 1.402 0.000 0.000 1.00 0.00 +HETATM 3 C 1 2.128 1.197 0.000 1.00 0.00 +HETATM 4 C 1 1.396 2.389 -0.011 1.00 0.00 +HETATM 5 C 1 0.003 2.388 -0.010 1.00 0.00 +HETATM 6 C 1 -0.728 1.196 0.001 1.00 0.00 +HETATM 7 C 1 -0.415 3.783 0.056 1.00 0.00 +HETATM 8 O 1 -1.550 4.177 0.150 1.00 0.00 +HETATM 9 N 1 0.698 4.553 0.096 1.00 0.00 +HETATM 10 C 1 1.812 3.785 0.053 1.00 0.00 +HETATM 11 O 1 2.946 4.181 0.146 1.00 0.00 +HETATM 12 C 1 0.702 6.005 0.319 1.00 0.00 +HETATM 13 C 1 1.020 6.278 1.801 1.00 0.00 +HETATM 14 C 1 1.130 7.799 2.000 1.00 0.00 +HETATM 15 C 1 2.180 8.336 1.068 1.00 0.00 +HETATM 16 O 1 2.814 9.307 1.391 1.00 0.00 +HETATM 17 N 1 2.428 7.747 -0.124 1.00 0.00 +HETATM 18 C 1 1.757 6.647 -0.538 1.00 0.00 +HETATM 19 O 1 2.022 6.158 -1.607 1.00 0.00 +HETATM 20 H 1 -0.535 -0.949 0.010 1.00 0.00 +HETATM 21 H 1 1.938 -0.949 0.010 1.00 0.00 +HETATM 22 H 1 3.217 1.203 0.020 1.00 0.00 +HETATM 23 H 1 -1.817 1.201 0.022 1.00 0.00 +HETATM 24 H 1 -0.272 6.423 0.067 1.00 0.00 +HETATM 25 H 1 1.968 5.808 2.060 1.00 0.00 +HETATM 26 H 1 0.228 5.873 2.432 1.00 0.00 +HETATM 27 H 1 1.408 8.016 3.031 1.00 0.00 +HETATM 28 H 1 0.173 8.268 1.775 1.00 0.00 +HETATM 29 H 1 3.142 8.141 -0.727 1.00 0.00 +CONECT 1 2 2 6 20 +CONECT 2 1 1 3 21 +CONECT 3 2 4 4 22 +CONECT 4 3 3 5 10 +CONECT 5 4 6 6 7 +CONECT 6 1 5 5 23 +CONECT 7 5 8 8 9 +CONECT 8 7 7 +CONECT 9 7 10 12 +CONECT 10 4 9 11 11 +CONECT 11 10 10 +CONECT 12 9 13 18 24 +CONECT 13 12 14 25 26 +CONECT 14 13 15 27 28 +CONECT 15 14 16 16 17 +CONECT 16 15 15 +CONECT 17 15 18 29 +CONECT 18 12 17 19 19 +CONECT 19 18 18 +CONECT 20 1 +CONECT 21 2 +CONECT 22 3 +CONECT 23 6 +CONECT 24 12 +CONECT 25 13 +CONECT 26 13 +CONECT 27 14 +CONECT 28 14 +CONECT 29 17 +MASTER 0 0 0 0 0 0 0 0 29 0 29 0 +END diff --git a/hacks/images/molecules/thymine.pdb b/hacks/images/molecules/thymine.pdb new file mode 100644 index 00000000..b58f8a6f --- /dev/null +++ b/hacks/images/molecules/thymine.pdb @@ -0,0 +1,37 @@ +HEADER Thymine: Pyrimidine base nucleotide +COMPND jb09thye +AUTHOR Created by Dave Woodcock at Okanagan University College +AUTHOR email:woodcock@okanagan.bc.ca +AUTHOR Date revised: Tue Sep 19 21:46:02 2000 GENERATED BY BABEL 1.6 +HETATM 1 C 1 0.000 0.000 0.000 1.00 0.00 +HETATM 2 C 1 1.399 0.000 0.000 1.00 0.00 +HETATM 3 C 1 2.068 1.228 0.000 1.00 0.00 +HETATM 4 N 1 1.356 2.377 -0.004 1.00 0.00 +HETATM 5 C 1 0.004 2.350 -0.006 1.00 0.00 +HETATM 6 N 1 -0.667 1.176 -0.004 1.00 0.00 +HETATM 7 O 1 -0.611 3.385 -0.006 1.00 0.00 +HETATM 8 O 1 3.272 1.261 0.006 1.00 0.00 +HETATM 9 C 1 2.173 -1.300 0.014 1.00 0.00 +HETATM 10 H 1 -0.549 -0.941 0.006 1.00 0.00 +HETATM 11 H 1 1.840 3.268 -0.003 1.00 0.00 +HETATM 12 H 1 -1.681 1.178 -0.004 1.00 0.00 +HETATM 13 H 1 1.632 -2.055 -0.555 1.00 0.00 +HETATM 14 H 1 2.293 -1.638 1.044 1.00 0.00 +HETATM 15 H 1 3.155 -1.146 -0.433 1.00 0.00 +CONECT 1 2 2 6 10 +CONECT 2 1 1 3 9 +CONECT 3 2 4 8 8 +CONECT 4 3 5 11 +CONECT 5 4 6 7 7 +CONECT 6 1 5 12 +CONECT 7 5 5 +CONECT 8 3 3 +CONECT 9 2 13 14 15 +CONECT 10 1 +CONECT 11 4 +CONECT 12 6 +CONECT 13 9 +CONECT 14 9 +CONECT 15 9 +MASTER 0 0 0 0 0 0 0 0 15 0 15 0 +END diff --git a/hacks/images/molecules/viagra.pdb b/hacks/images/molecules/viagra.pdb new file mode 100644 index 00000000..243a0386 --- /dev/null +++ b/hacks/images/molecules/viagra.pdb @@ -0,0 +1,133 @@ +COMPND Viagra +AUTHOR Created by Dave Woodcock at Okanagan University College +REMARK from a model provided by Dr Eric Walters +AUTHOR email:woodcock@okanagan.bc.ca +AUTHOR Date revised: Mon Oct 16 12:17:54 2000 GENERATED BY BABEL 1.6 +HETATM 1 C 1 0.000 0.000 0.000 1.00 0.00 +HETATM 2 C 1 1.398 0.000 0.000 1.00 0.00 +HETATM 3 C 1 2.105 1.207 0.000 1.00 0.00 +HETATM 4 C 1 1.417 2.427 -0.037 1.00 0.00 +HETATM 5 C 1 0.017 2.422 -0.014 1.00 0.00 +HETATM 6 C 1 -0.692 1.216 -0.005 1.00 0.00 +HETATM 7 H 1 -0.545 -0.944 0.023 1.00 0.00 +HETATM 8 H 1 1.939 -0.946 0.029 1.00 0.00 +HETATM 9 H 1 -0.531 3.364 -0.022 1.00 0.00 +HETATM 10 C 1 2.100 3.733 -0.053 1.00 0.00 +HETATM 11 N 1 3.453 3.848 -0.302 1.00 0.00 +HETATM 12 C 1 4.091 5.067 -0.302 1.00 0.00 +HETATM 13 C 1 3.259 6.246 -0.033 1.00 0.00 +HETATM 14 C 1 1.897 6.080 0.190 1.00 0.00 +HETATM 15 N 1 1.310 4.840 0.169 1.00 0.00 +HETATM 16 O 1 5.271 5.168 -0.544 1.00 0.00 +HETATM 17 H 1 4.029 2.992 -0.569 1.00 0.00 +HETATM 18 N 1 3.538 7.572 0.006 1.00 0.00 +HETATM 19 N 1 2.406 8.264 0.248 1.00 0.00 +HETATM 20 C 1 1.373 7.363 0.369 1.00 0.00 +HETATM 21 C 1 4.863 8.163 -0.230 1.00 0.00 +HETATM 22 H 1 4.799 9.247 -0.133 1.00 0.00 +HETATM 23 H 1 5.200 7.907 -1.235 1.00 0.00 +HETATM 24 H 1 5.570 7.774 0.501 1.00 0.00 +HETATM 25 C 1 -0.079 7.701 0.624 1.00 0.00 +HETATM 26 C 1 -0.226 9.225 0.805 1.00 0.00 +HETATM 27 H 1 -0.415 7.190 1.526 1.00 0.00 +HETATM 28 H 1 -0.680 7.372 -0.224 1.00 0.00 +HETATM 29 C 1 -1.702 9.584 1.072 1.00 0.00 +HETATM 30 H 1 0.112 9.732 -0.099 1.00 0.00 +HETATM 31 H 1 0.383 9.550 1.649 1.00 0.00 +HETATM 32 H 1 -1.796 10.663 1.198 1.00 0.00 +HETATM 33 H 1 -2.043 9.083 1.978 1.00 0.00 +HETATM 34 H 1 -2.315 9.264 0.229 1.00 0.00 +HETATM 35 O 1 3.461 1.164 0.124 1.00 0.00 +HETATM 36 C 1 3.859 0.886 1.450 1.00 0.00 +HETATM 37 C 1 3.396 1.998 2.414 1.00 0.00 +HETATM 38 H 1 4.947 0.824 1.480 1.00 0.00 +HETATM 39 H 1 3.443 -0.069 1.771 1.00 0.00 +HETATM 40 H 1 3.774 1.788 3.414 1.00 0.00 +HETATM 41 H 1 2.307 2.037 2.446 1.00 0.00 +HETATM 42 H 1 3.786 2.959 2.077 1.00 0.00 +HETATM 43 S 1 -2.443 1.230 0.022 1.00 0.00 +HETATM 44 N 1 -3.045 -0.296 -0.555 1.00 0.00 +HETATM 45 C 1 -4.498 -0.382 -0.345 1.00 0.00 +HETATM 46 C 1 -4.996 -1.765 -0.804 1.00 0.00 +HETATM 47 N 1 -4.674 -1.957 -2.227 1.00 0.00 +HETATM 48 C 1 -3.222 -1.855 -2.442 1.00 0.00 +HETATM 49 C 1 -2.728 -0.471 -1.980 1.00 0.00 +HETATM 50 H 1 -5.005 0.395 -0.919 1.00 0.00 +HETATM 51 H 1 -4.725 -0.254 0.715 1.00 0.00 +HETATM 52 H 1 -6.076 -1.822 -0.662 1.00 0.00 +HETATM 53 H 1 -4.513 -2.539 -0.208 1.00 0.00 +HETATM 54 H 1 -2.998 -1.979 -3.502 1.00 0.00 +HETATM 55 H 1 -2.707 -2.629 -1.872 1.00 0.00 +HETATM 56 H 1 -3.222 0.303 -2.569 1.00 0.00 +HETATM 57 H 1 -1.651 -0.407 -2.135 1.00 0.00 +HETATM 58 O 1 -2.929 2.282 -0.818 1.00 0.00 +HETATM 59 O 1 -2.893 1.442 1.364 1.00 0.00 +HETATM 60 C 1 -5.177 -3.257 -2.700 1.00 0.00 +HETATM 61 H 1 -4.954 -3.372 -3.760 1.00 0.00 +HETATM 62 H 1 -6.257 -3.305 -2.557 1.00 0.00 +HETATM 63 H 1 -4.703 -4.065 -2.142 1.00 0.00 +CONECT 1 2 2 6 7 +CONECT 2 1 1 3 8 +CONECT 3 2 4 4 35 +CONECT 4 3 3 5 10 +CONECT 5 4 6 6 9 +CONECT 6 1 5 5 43 +CONECT 7 1 +CONECT 8 2 +CONECT 9 5 +CONECT 10 4 11 15 15 +CONECT 11 10 12 17 +CONECT 12 11 13 16 16 +CONECT 13 12 14 14 18 +CONECT 14 13 13 15 20 +CONECT 15 10 14 14 +CONECT 16 12 12 +CONECT 17 11 +CONECT 18 13 19 21 +CONECT 19 18 20 20 +CONECT 20 14 19 19 25 +CONECT 21 18 22 23 24 +CONECT 22 21 +CONECT 23 21 +CONECT 24 21 +CONECT 25 20 26 27 28 +CONECT 26 25 29 30 31 +CONECT 27 25 +CONECT 28 25 +CONECT 29 26 32 33 34 +CONECT 30 26 +CONECT 31 26 +CONECT 32 29 +CONECT 33 29 +CONECT 34 29 +CONECT 35 3 36 +CONECT 36 35 37 38 39 +CONECT 37 36 40 41 42 +CONECT 38 36 +CONECT 39 36 +CONECT 40 37 +CONECT 41 37 +CONECT 42 37 +CONECT 43 6 44 58 59 +CONECT 44 43 45 49 +CONECT 45 44 46 50 51 +CONECT 46 45 47 52 53 +CONECT 47 46 48 60 +CONECT 48 47 49 54 55 +CONECT 49 44 48 56 57 +CONECT 50 45 +CONECT 51 45 +CONECT 52 46 +CONECT 53 46 +CONECT 54 48 +CONECT 55 48 +CONECT 56 49 +CONECT 57 49 +CONECT 58 43 +CONECT 59 43 +CONECT 60 47 61 62 63 +CONECT 61 60 +CONECT 62 60 +CONECT 63 60 +MASTER 0 0 0 0 0 0 0 0 63 0 63 0 +END diff --git a/hacks/images/molecules/vitaminb6.pdb b/hacks/images/molecules/vitaminb6.pdb new file mode 100644 index 00000000..c21654b9 --- /dev/null +++ b/hacks/images/molecules/vitaminb6.pdb @@ -0,0 +1,56 @@ +HEADER Pyridoxine: Vitamin B6 +COMPND c8h11no3 +AUTHOR Created by Dave Woodcock at Okanagan University College +AUTHOR email:woodcock@okanagan.bc.ca +AUTHOR Date revised: Fri Sep 1 09:41:05 2000 GENERATED BY BABEL 1.6 +HETATM 1 C 1 0.000 0.000 0.000 1.00 0.00 +HETATM 2 C 1 1.399 0.000 0.000 1.00 0.00 +HETATM 3 C 1 2.095 1.214 0.000 1.00 0.00 +HETATM 4 C 1 1.381 2.418 0.018 1.00 0.00 +HETATM 5 C 1 -0.018 2.390 0.005 1.00 0.00 +HETATM 6 N 1 -0.688 1.189 -0.006 1.00 0.00 +HETATM 7 C 1 -0.754 -1.311 0.010 1.00 0.00 +HETATM 8 O 1 2.079 -1.180 0.011 1.00 0.00 +HETATM 9 C 1 3.608 1.210 0.001 1.00 0.00 +HETATM 10 O 1 4.077 1.576 1.303 1.00 0.00 +HETATM 11 C 1 2.102 3.747 0.058 1.00 0.00 +HETATM 12 O 1 1.197 4.767 0.493 1.00 0.00 +HETATM 13 H 1 -0.583 3.322 0.008 1.00 0.00 +HETATM 14 H 1 -0.438 -1.905 0.867 1.00 0.00 +HETATM 15 H 1 -0.543 -1.858 -0.909 1.00 0.00 +HETATM 16 H 1 -1.824 -1.114 0.078 1.00 0.00 +HETATM 17 H 1 2.145 -1.522 -0.886 1.00 0.00 +HETATM 18 H 1 3.977 1.922 -0.737 1.00 0.00 +HETATM 19 H 1 3.973 0.214 -0.250 1.00 0.00 +HETATM 20 H 1 5.040 1.579 1.315 1.00 0.00 +HETATM 21 H 1 2.472 3.988 -0.939 1.00 0.00 +HETATM 22 H 1 2.940 3.690 0.753 1.00 0.00 +HETATM 23 H 1 1.650 5.617 0.520 1.00 0.00 +CONECT 1 2 6 7 +CONECT 1 2 +CONECT 2 1 3 8 +CONECT 3 2 4 9 +CONECT 3 4 +CONECT 4 3 5 11 +CONECT 5 4 6 13 +CONECT 5 6 +CONECT 6 1 5 +CONECT 7 1 14 15 16 +CONECT 8 2 17 +CONECT 9 3 10 18 19 +CONECT 10 9 20 +CONECT 11 4 12 21 22 +CONECT 12 11 23 +CONECT 13 5 +CONECT 14 7 +CONECT 15 7 +CONECT 16 7 +CONECT 17 8 +CONECT 18 9 +CONECT 19 9 +CONECT 20 10 +CONECT 21 11 +CONECT 22 11 +CONECT 23 12 +MASTER 0 0 0 0 0 0 0 0 23 0 23 0 +END diff --git a/hacks/images/molecules/vitaminc.pdb b/hacks/images/molecules/vitaminc.pdb new file mode 100644 index 00000000..d7a7d6a2 --- /dev/null +++ b/hacks/images/molecules/vitaminc.pdb @@ -0,0 +1,47 @@ +HEADER Ascorbic Acid: Vitamin C +COMPND vit-c +AUTHOR Created by Dave Woodcock at Okanagan University College +AUTHOR email:woodcock@okanagan.bc.ca +AUTHOR Date revised: Fri Sep 1 09:41:05 2000 GENERATED BY BABEL 1.6 +HETATM 1 C 1 0.000 0.000 0.000 1.00 0.00 +HETATM 2 C 1 1.512 0.000 0.000 1.00 0.00 +HETATM 3 C 1 1.927 1.264 0.000 1.00 0.00 +HETATM 4 C 1 0.730 2.091 0.015 1.00 0.00 +HETATM 5 O 1 -0.382 1.359 0.113 1.00 0.00 +HETATM 6 O 1 0.759 3.270 0.261 1.00 0.00 +HETATM 7 O 1 3.197 1.690 0.245 1.00 0.00 +HETATM 8 O 1 2.283 -1.055 0.386 1.00 0.00 +HETATM 9 H 1 -0.390 -0.463 -0.907 1.00 0.00 +HETATM 10 C 1 -0.565 -0.653 1.264 1.00 0.00 +HETATM 11 H 1 0.050 -1.475 1.629 1.00 0.00 +HETATM 12 O 1 -0.674 0.397 2.229 1.00 0.00 +HETATM 13 C 1 -2.028 -1.077 1.106 1.00 0.00 +HETATM 14 O 1 -2.543 -0.906 2.429 1.00 0.00 +HETATM 15 H 1 3.383 1.620 1.187 1.00 0.00 +HETATM 16 H 1 2.156 -1.784 -0.228 1.00 0.00 +HETATM 17 H 1 -0.774 1.222 1.738 1.00 0.00 +HETATM 18 H 1 -2.112 -2.110 0.766 1.00 0.00 +HETATM 19 H 1 -2.545 -0.402 0.425 1.00 0.00 +HETATM 20 H 1 -2.081 -0.175 2.830 1.00 0.00 +CONECT 1 2 5 9 10 +CONECT 2 1 3 8 +CONECT 3 2 4 7 +CONECT 4 3 5 6 6 +CONECT 5 1 4 +CONECT 6 4 4 +CONECT 7 3 15 +CONECT 8 2 16 +CONECT 9 1 +CONECT 10 1 11 12 13 +CONECT 11 10 +CONECT 12 10 17 +CONECT 13 10 14 18 19 +CONECT 14 13 20 +CONECT 15 7 +CONECT 16 8 +CONECT 17 12 +CONECT 18 13 +CONECT 19 13 +CONECT 20 14 +MASTER 0 0 0 0 0 0 0 0 20 0 20 0 +END diff --git a/hacks/images/molecules/vx.pdb b/hacks/images/molecules/vx.pdb new file mode 100644 index 00000000..8b653cb1 --- /dev/null +++ b/hacks/images/molecules/vx.pdb @@ -0,0 +1,92 @@ +HEADER VX: a chemical warfare agent, cholinesterase inhibitor +COMPND VX +AUTHOR Created by Dave Woodcock at Okanagan University College +AUTHOR email:woodcock@okanagan.bc.ca +AUTHOR Date revised: Fri Sep 1 09:41:05 2000 GENERATED BY BABEL 1.6 +HETATM 1 C 1 0.000 0.000 0.000 1.00 0.00 +HETATM 2 C 1 1.541 0.000 0.000 1.00 0.00 +HETATM 3 O 1 2.000 1.333 0.000 1.00 0.00 +HETATM 4 P 1 3.580 1.768 -0.723 1.00 0.00 +HETATM 5 O 1 3.908 3.507 -0.453 1.00 0.00 +HETATM 6 C 1 3.536 1.434 -2.522 1.00 0.00 +HETATM 7 S 1 5.089 0.633 0.149 1.00 0.00 +HETATM 8 C 1 6.652 1.113 -0.581 1.00 0.00 +HETATM 9 C 1 7.173 2.394 0.105 1.00 0.00 +HETATM 10 N 1 8.475 2.827 -0.436 1.00 0.00 +HETATM 11 C 1 9.247 3.677 0.492 1.00 0.00 +HETATM 12 C 1 9.948 2.776 1.531 1.00 0.00 +HETATM 13 C 1 8.388 4.729 1.230 1.00 0.00 +HETATM 14 C 1 8.465 3.210 -1.863 1.00 0.00 +HETATM 15 C 1 9.881 3.493 -2.414 1.00 0.00 +HETATM 16 C 1 7.562 4.422 -2.181 1.00 0.00 +HETATM 17 H 1 -0.362 0.520 0.887 1.00 0.00 +HETATM 18 H 1 -0.367 -1.026 0.006 1.00 0.00 +HETATM 19 H 1 -0.363 0.510 -0.892 1.00 0.00 +HETATM 20 H 1 1.902 -0.524 -0.885 1.00 0.00 +HETATM 21 H 1 1.904 -0.507 0.894 1.00 0.00 +HETATM 22 H 1 2.728 2.007 -2.976 1.00 0.00 +HETATM 23 H 1 3.367 0.370 -2.691 1.00 0.00 +HETATM 24 H 1 4.485 1.727 -2.970 1.00 0.00 +HETATM 25 H 1 6.489 1.278 -1.644 1.00 0.00 +HETATM 26 H 1 7.377 0.311 -0.444 1.00 0.00 +HETATM 27 H 1 7.282 2.161 1.162 1.00 0.00 +HETATM 28 H 1 6.438 3.191 0.006 1.00 0.00 +HETATM 29 H 1 10.030 4.205 -0.044 1.00 0.00 +HETATM 30 H 1 10.539 2.021 1.012 1.00 0.00 +HETATM 31 H 1 9.216 2.282 2.169 1.00 0.00 +HETATM 32 H 1 10.608 3.383 2.151 1.00 0.00 +HETATM 33 H 1 9.041 5.368 1.825 1.00 0.00 +HETATM 34 H 1 7.675 4.243 1.895 1.00 0.00 +HETATM 35 H 1 7.847 5.345 0.515 1.00 0.00 +HETATM 36 H 1 8.094 2.362 -2.434 1.00 0.00 +HETATM 37 H 1 10.574 2.735 -2.048 1.00 0.00 +HETATM 38 H 1 10.223 4.483 -2.116 1.00 0.00 +HETATM 39 H 1 9.853 3.454 -3.503 1.00 0.00 +HETATM 40 H 1 7.928 5.308 -1.665 1.00 0.00 +HETATM 41 H 1 6.533 4.222 -1.886 1.00 0.00 +HETATM 42 H 1 7.584 4.609 -3.255 1.00 0.00 +CONECT 1 2 17 18 19 +CONECT 2 1 3 20 21 +CONECT 3 2 4 +CONECT 4 3 5 6 7 +CONECT 4 5 +CONECT 5 4 +CONECT 6 4 22 23 24 +CONECT 7 4 8 +CONECT 8 7 9 25 26 +CONECT 9 8 10 27 28 +CONECT 10 9 11 14 +CONECT 11 10 12 13 29 +CONECT 12 11 30 31 32 +CONECT 13 11 33 34 35 +CONECT 14 10 15 16 36 +CONECT 15 14 37 38 39 +CONECT 16 14 40 41 42 +CONECT 17 1 +CONECT 18 1 +CONECT 19 1 +CONECT 20 2 +CONECT 21 2 +CONECT 22 6 +CONECT 23 6 +CONECT 24 6 +CONECT 25 8 +CONECT 26 8 +CONECT 27 9 +CONECT 28 9 +CONECT 29 11 +CONECT 30 12 +CONECT 31 12 +CONECT 32 12 +CONECT 33 13 +CONECT 34 13 +CONECT 35 13 +CONECT 36 14 +CONECT 37 15 +CONECT 38 15 +CONECT 39 15 +CONECT 40 16 +CONECT 41 16 +CONECT 42 16 +MASTER 0 0 0 0 0 0 0 0 42 0 42 0 +END diff --git a/hacks/images/noseguy/nose-f1.xbm b/hacks/images/noseguy/nose-f1.xbm new file mode 100644 index 00000000..ea1a93bc --- /dev/null +++ b/hacks/images/noseguy/nose-f1.xbm @@ -0,0 +1,46 @@ +#define nose_f1_width 64 +#define nose_f1_height 64 +static unsigned char nose_f1_bits[] = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xff, 0xff, 0x07, 0x00, 0x00, + 0x00, 0x00, 0x40, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, + 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x04, 0x00, 0x00, + 0x00, 0x00, 0x40, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, + 0x00, 0x04, 0x00, 0x00, 0x00, 0xf8, 0xff, 0xff, 0xff, 0xff, 0x3f, 0x00, + 0x00, 0x08, 0x00, 0xc0, 0x1f, 0x00, 0x20, 0x00, 0x00, 0x08, 0x00, 0x30, + 0x60, 0x00, 0x20, 0x00, 0x00, 0xf8, 0xff, 0x0f, 0x80, 0xff, 0x3f, 0x00, + 0x00, 0x00, 0x02, 0x02, 0x00, 0x82, 0x00, 0x00, 0x00, 0x00, 0x03, 0x01, + 0x00, 0x84, 0x01, 0x00, 0x00, 0x00, 0x81, 0x00, 0x00, 0x08, 0x01, 0x00, + 0x00, 0x80, 0x80, 0x00, 0x00, 0x08, 0x02, 0x00, 0x00, 0x80, 0x40, 0x00, + 0x00, 0x10, 0x02, 0x00, 0x00, 0x40, 0x40, 0x00, 0x00, 0x10, 0x04, 0x00, + 0x00, 0x40, 0x20, 0x00, 0x00, 0x20, 0x04, 0x00, 0x00, 0x60, 0x20, 0x00, + 0x00, 0x20, 0x0c, 0x00, 0x00, 0x20, 0x20, 0x00, 0x00, 0x20, 0x08, 0x00, + 0x00, 0x20, 0x20, 0x00, 0x00, 0x20, 0x08, 0x00, 0x00, 0x10, 0x20, 0x00, + 0x00, 0x20, 0x10, 0x00, 0x00, 0x10, 0x20, 0x00, 0x00, 0x20, 0x10, 0x00, + 0x00, 0x10, 0x20, 0x00, 0x00, 0x20, 0x10, 0x00, 0x00, 0x10, 0x40, 0x00, + 0x00, 0x10, 0x10, 0x00, 0x00, 0x10, 0x40, 0x00, 0x00, 0x10, 0x10, 0x00, + 0x00, 0x10, 0x80, 0x00, 0x00, 0x08, 0x10, 0x00, 0x00, 0x10, 0x80, 0x00, + 0x00, 0x08, 0x10, 0x00, 0x00, 0x30, 0x00, 0x01, 0x00, 0x04, 0x18, 0x00, + 0x00, 0x20, 0x00, 0x02, 0x00, 0x02, 0x08, 0x00, 0x00, 0x20, 0x00, 0x0c, + 0x80, 0x01, 0x08, 0x00, 0x00, 0x60, 0x00, 0x30, 0x60, 0x00, 0x0c, 0x00, + 0x00, 0x40, 0x00, 0xc0, 0x1f, 0x00, 0x04, 0x00, 0x00, 0xc0, 0x00, 0x00, + 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, + 0x00, 0x00, 0xfe, 0xff, 0xff, 0xff, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x0f, 0xc0, 0x0f, 0x00, 0x00, + 0x00, 0x00, 0x40, 0x10, 0x20, 0x10, 0x00, 0x00, 0x00, 0x00, 0x20, 0x60, + 0x30, 0x20, 0x00, 0x00, 0x00, 0x00, 0x20, 0xc0, 0x18, 0x20, 0x00, 0x00, + 0xc0, 0x7f, 0x10, 0x80, 0x0d, 0x40, 0xe0, 0x01, 0x70, 0xc0, 0x18, 0x00, + 0x05, 0x40, 0x1c, 0x06, 0x10, 0x00, 0x0f, 0x00, 0x05, 0x80, 0x07, 0x08, + 0x08, 0x00, 0x06, 0x00, 0x05, 0x80, 0x01, 0x08, 0x08, 0x00, 0x18, 0x00, + 0x05, 0xc0, 0x00, 0x10, 0x04, 0x00, 0x30, 0x00, 0x05, 0x30, 0x00, 0x10, + 0x04, 0x00, 0x00, 0x80, 0x08, 0x18, 0x00, 0x20, 0x04, 0x00, 0x00, 0x80, + 0x08, 0x00, 0x00, 0x20, 0x04, 0x00, 0x00, 0x40, 0x10, 0x00, 0x00, 0x20, + 0x24, 0x00, 0x00, 0x40, 0x10, 0x00, 0x00, 0x22, 0x24, 0x00, 0x00, 0x40, + 0x10, 0x00, 0x00, 0x22, 0x44, 0x00, 0x00, 0x40, 0x10, 0x00, 0x00, 0x11, + 0x84, 0x01, 0x00, 0xc0, 0x18, 0x00, 0xc0, 0x10, 0x08, 0x00, 0x00, 0x80, + 0x08, 0x00, 0x00, 0x08, 0x30, 0x00, 0x00, 0x80, 0x08, 0x00, 0x00, 0x04, + 0xe0, 0xff, 0xff, 0xff, 0xf8, 0xff, 0xff, 0x03, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; diff --git a/hacks/images/noseguy/nose-f1.xpm b/hacks/images/noseguy/nose-f1.xpm new file mode 100644 index 00000000..7c1e79cc --- /dev/null +++ b/hacks/images/noseguy/nose-f1.xpm @@ -0,0 +1,74 @@ +/* XPM */ +static char * nose_f1_xpm[] = { +"64 64 7 1", +" c #000000 m #000000", +". c #000000 m #FFFFFF", +"X c #BEBEBE m #000000", +"o c #FFFF00 m #000000", +"O c #EEEE00 m #000000", +"+ c #A020F0 m #000000", +"@ c #7D26CD m #000000", +" ", +" ", +" ", +" ", +" ", +" ..................... ", +" .XXXXXXXXXXXXXXXXXXX. ", +" .XXXXXXXXXXXXXXXXXXX. ", +" .XXXXXXXXXXXXXXXXXXX. ", +" .XXXXXXXXXXXXXXXXXXX. ", +" .XXXXXXXXXXXXXXXXXXX. ", +" ........................................... ", +" .XXXXXXXXXXXXXXXXXX.......XXXXXXXXXXXXXXXX. ", +" .XXXXXXXXXXXXXXXX..ooooooo..XXXXXXXXXXXXXX. ", +" .................ooooooooooo............... ", +" .OOOOOOO.ooooooooooooooo.OOOOO. ", +" ..OOOOOO.ooooooooooooooooo.OOOO.. ", +" .OOOOOO.ooooooooooooooooooo.OOOO. ", +" .OOOOOOO.ooooooooooooooooooo.OOOOO. ", +" .OOOOOO.ooooooooooooooooooooo.OOOO. ", +" .OOOOOOO.ooooooooooooooooooooo.OOOOO. ", +" .OOOOOO.ooooooooooooooooooooooo.OOOO. ", +" ..OOOOOO.ooooooooooooooooooooooo.OOOO.. ", +" .OOOOOOO.ooooooooooooooooooooooo.OOOOO. ", +" .OOOOOOO.ooooooooooooooooooooooo.OOOOO. ", +" .OOOOOOOO.ooooooooooooooooooooooo.OOOOOO. ", +" .OOOOOOOO.ooooooooooooooooooooooo.OOOOOO. ", +" .OOOOOOOO.ooooooooooooooooooooooo.OOOOOO. ", +" .OOOOOOOOO.ooooooooooooooooooooo.OOOOOOO. ", +" .OOOOOOOOO.ooooooooooooooooooooo.OOOOOOO. ", +" .OOOOOOOOOO.ooooooooooooooooooo.OOOOOOOO. ", +" .OOOOOOOOOO.ooooooooooooooooooo.OOOOOOOO. ", +" ..OOOOOOOOOO.ooooooooooooooooo.OOOOOOOO.. ", +" .OOOOOOOOOOO.ooooooooooooooo.OOOOOOOOO. ", +" .OOOOOOOOOOOO..ooooooooooo..OOOOOOOOOO. ", +" ..OOOOOOOOOOOOO..ooooooo..OOOOOOOOOOO.. ", +" .OOOOOOOOOOOOOOO.......OOOOOOOOOOOOO. ", +" ..OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO.. ", +" .OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO. ", +" ................................ ", +" ", +" ..... ...... ", +" .+++++. .++++++. ", +" .+++++++.. ..+++++++. ", +" .++++++++.. ..++++++++. ", +" ......... .++++++++++.. ..++++++++++. .... ", +" ...+++++++.. ..+++++++++++. .+++++++++++. ...++++.. ", +" .+++++++++++....@+++++++++++. .+++++++++++@....++++++++. ", +" .+++++++++++++..@@+++++++++++. .++++++++++@@..++++++++++. ", +" .+++++++++++++++..@++++++++++. .+++++++++@@..++++++++++++. ", +" .+++++++++++++++++..@+++++++++. .++++++++@..++++++++++++++. ", +" .++++++++++++++++++++++++++++. .+++++++..++++++++++++++++. ", +" .++++++++++++++++++++++++++++. .+++++++++++++++++++++++++. ", +" .+++++++++++++++++++++++++++. .++++++++++++++++++++++++. ", +" .+@.++++++++++++++++++++++++. .++++++++++++++++++++.+++. ", +" .+@.++++++++++++++++++++++++. .++++++++++++++++++++.@++. ", +" .+@@.+++++++++++++++++++++++. .+++++++++++++++++++.@@+. ", +" .++@@..+++++++++++++++++++++.. ..+++++++++++++++++..@@++. ", +" .++@@++++++++++++++++++++++@. .@++++++++++++++++++@@++. ", +" ..@@@@@@@@@@@@@@@@@@@@@@@@@. .@@@@@@@@@@@@@@@@@@@@@@. ", +" ........................... ....................... ", +" ", +" ", +" "}; diff --git a/hacks/images/noseguy/nose-f2.xbm b/hacks/images/noseguy/nose-f2.xbm new file mode 100644 index 00000000..0e255768 --- /dev/null +++ b/hacks/images/noseguy/nose-f2.xbm @@ -0,0 +1,46 @@ +#define nose_f2_width 64 +#define nose_f2_height 64 +static unsigned char nose_f2_bits[] = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xff, 0xff, 0x07, 0x00, 0x00, + 0x00, 0x00, 0x40, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, + 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x04, 0x00, 0x00, + 0x00, 0x00, 0x40, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, + 0x00, 0x04, 0x00, 0x00, 0x00, 0xf8, 0xff, 0xff, 0xff, 0xff, 0x3f, 0x00, + 0x00, 0x08, 0x00, 0xe0, 0x0f, 0x00, 0x20, 0x00, 0x00, 0x08, 0x00, 0x18, + 0x30, 0x00, 0x20, 0x00, 0x00, 0xf8, 0xff, 0x07, 0xc0, 0xff, 0x3f, 0x00, + 0x00, 0x00, 0x02, 0x01, 0x00, 0x81, 0x00, 0x00, 0x00, 0x00, 0x83, 0x00, + 0x00, 0x82, 0x01, 0x00, 0x00, 0x00, 0x41, 0x00, 0x00, 0x04, 0x01, 0x00, + 0x00, 0x80, 0x40, 0x00, 0x00, 0x04, 0x02, 0x00, 0x00, 0x80, 0x20, 0x00, + 0x00, 0x08, 0x02, 0x00, 0x00, 0x40, 0x20, 0x00, 0x00, 0x08, 0x04, 0x00, + 0x00, 0x40, 0x10, 0x00, 0x00, 0x10, 0x04, 0x00, 0x00, 0x60, 0x10, 0x00, + 0x00, 0x10, 0x0c, 0x00, 0x00, 0x20, 0x10, 0x00, 0x00, 0x10, 0x08, 0x00, + 0x00, 0x30, 0x10, 0x00, 0x00, 0x10, 0x08, 0x00, 0x00, 0x10, 0x10, 0x00, + 0x00, 0x10, 0x10, 0x00, 0x00, 0x10, 0x10, 0x00, 0x00, 0x10, 0x10, 0x00, + 0x00, 0x10, 0x10, 0x00, 0x00, 0x10, 0x10, 0x00, 0x00, 0x10, 0x20, 0x00, + 0x00, 0x08, 0x10, 0x00, 0x00, 0x10, 0x20, 0x00, 0x00, 0x08, 0x10, 0x00, + 0x00, 0x10, 0x40, 0x00, 0x00, 0x04, 0x10, 0x00, 0x00, 0x30, 0x40, 0x00, + 0x00, 0x04, 0x10, 0x00, 0x00, 0x20, 0x80, 0x00, 0x00, 0x02, 0x18, 0x00, + 0x00, 0x20, 0x00, 0x01, 0x00, 0x01, 0x08, 0x00, 0x00, 0x60, 0x00, 0x06, + 0xc0, 0x00, 0x08, 0x00, 0x00, 0x80, 0x00, 0x18, 0x30, 0x00, 0x0c, 0x00, + 0x00, 0x80, 0x00, 0xe0, 0x0f, 0x00, 0x04, 0x00, 0x00, 0x80, 0x01, 0x00, + 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, + 0x00, 0x00, 0xfe, 0xff, 0xff, 0xff, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x0f, 0x00, 0x00, + 0x00, 0x00, 0xff, 0x00, 0x04, 0x10, 0x00, 0x00, 0x00, 0xe0, 0x00, 0x07, + 0x02, 0x10, 0x00, 0x00, 0x00, 0x30, 0x00, 0x8c, 0x01, 0x20, 0x00, 0x00, + 0x00, 0x0c, 0x00, 0x90, 0x00, 0x20, 0x00, 0x00, 0x00, 0x04, 0x03, 0x60, + 0x00, 0x20, 0x00, 0x00, 0x00, 0xc2, 0x00, 0xc0, 0x00, 0x20, 0x00, 0x00, + 0x00, 0x42, 0x00, 0x00, 0x01, 0x20, 0x00, 0x00, 0x00, 0x21, 0x00, 0x00, + 0x02, 0x20, 0x00, 0x00, 0x00, 0x21, 0x00, 0x00, 0x06, 0x20, 0x00, 0x00, + 0x00, 0x21, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, + 0x00, 0x40, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, + 0x00, 0x02, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, + 0x00, 0x40, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, + 0x00, 0x18, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, + 0x00, 0x10, 0x00, 0x00, 0x00, 0xc0, 0xff, 0xff, 0xff, 0x0f, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; diff --git a/hacks/images/noseguy/nose-f2.xpm b/hacks/images/noseguy/nose-f2.xpm new file mode 100644 index 00000000..228cd2d7 --- /dev/null +++ b/hacks/images/noseguy/nose-f2.xpm @@ -0,0 +1,74 @@ +/* XPM */ +static char * nose_f2_xpm[] = { +"64 64 7 1", +" c #000000 m #000000", +". c #000000 m #FFFFFF", +"X c #BEBEBE m #000000", +"o c #FFFF00 m #000000", +"O c #EEEE00 m #000000", +"+ c #A020F0 m #000000", +"@ c #7D26CD m #000000", +" ", +" ", +" ", +" ", +" ", +" ..................... ", +" .XXXXXXXXXXXXXXXXXXX. ", +" .XXXXXXXXXXXXXXXXXXX. ", +" .XXXXXXXXXXXXXXXXXXX. ", +" .XXXXXXXXXXXXXXXXXXX. ", +" .XXXXXXXXXXXXXXXXXXX. ", +" ........................................... ", +" .XXXXXXXXXXXXXXXXX.......XXXXXXXXXXXXXXXXX. ", +" .XXXXXXXXXXXXXXX..ooooooo..XXXXXXXXXXXXXXX. ", +" ................ooooooooooo................ ", +" .OOOOOO.ooooooooooooooo.OOOOOO. ", +" ..OOOOO.ooooooooooooooooo.OOOOO.. ", +" .OOOOO.ooooooooooooooooooo.OOOOO. ", +" .OOOOOO.ooooooooooooooooooo.OOOOOO. ", +" .OOOOO.ooooooooooooooooooooo.OOOOO. ", +" .OOOOOO.ooooooooooooooooooooo.OOOOOO. ", +" .OOOOO.ooooooooooooooooooooooo.OOOOO. ", +" ..OOOOO.ooooooooooooooooooooooo.OOOOO.. ", +" .OOOOOO.ooooooooooooooooooooooo.OOOOOO. ", +" ..OOOOOO.ooooooooooooooooooooooo.OOOOOO. ", +" .OOOOOOO.ooooooooooooooooooooooo.OOOOOOO. ", +" .OOOOOOO.ooooooooooooooooooooooo.OOOOOOO. ", +" .OOOOOOO.ooooooooooooooooooooooo.OOOOOOO. ", +" .OOOOOOOO.ooooooooooooooooooooo.OOOOOOOO. ", +" .OOOOOOOO.ooooooooooooooooooooo.OOOOOOOO. ", +" .OOOOOOOOO.ooooooooooooooooooo.OOOOOOOOO. ", +" ..OOOOOOOO.ooooooooooooooooooo.OOOOOOOOO. ", +" .OOOOOOOOO.ooooooooooooooooo.OOOOOOOOO.. ", +" .OOOOOOOOOO.ooooooooooooooo.OOOOOOOOOO. ", +" ..OOOOOOOOOO..ooooooooooo..OOOOOOOOOOO. ", +" .OOOOOOOOOOO..ooooooo..OOOOOOOOOOOO.. ", +" .OOOOOOOOOOOOO.......OOOOOOOOOOOOOO. ", +" ..OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO.. ", +" .OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO. ", +" ................................ ", +" ", +" ......... ", +" ........ .+++++++++. ", +" ...++++++++... .++++++++++. ", +" ..++++++++++++.. ..++++++++++++. ", +" ..++++++++++++++++. .@++++++++++++. ", +" .++++@..+++++++++++..@@++++++++++++. ", +" .++++..++++++++++++++..@++++++++++++. ", +" .+++@.+++++++++++++++++.@+++++++++++. ", +" .+++@.+++++++++++++++++++.@++++++++++. ", +" .+++@.+++++++++++++++++++..++++++++++. ", +" .+++@.+++++++++++++++++++++++++++++++. ", +" .++++++++++++++++++++++++++++++++++++@. ", +" ..@++++++++++++++++++++++++++++++++++@. ", +" .@@+++++++++++++++++++++++++++++++++@. ", +" .@@++++++++++++++++++++++++++++++++@@. ", +" .@@@++++++++++++++++++++++++++++++@. ", +" ..@@@++++++++++++++++++++@@@++++@@. ", +" ...@@@@@@@@@@@@@@@@@@@@@@@@@@@@@. ", +" .............................. ", +" ", +" ", +" ", +" "}; diff --git a/hacks/images/noseguy/nose-f3.xbm b/hacks/images/noseguy/nose-f3.xbm new file mode 100644 index 00000000..77a40ef0 --- /dev/null +++ b/hacks/images/noseguy/nose-f3.xbm @@ -0,0 +1,46 @@ +#define nose_f3_width 64 +#define nose_f3_height 64 +static unsigned char nose_f3_bits[] = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0xff, 0xff, 0x03, 0x00, 0x00, + 0x00, 0x00, 0x20, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, + 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x02, 0x00, 0x00, + 0x00, 0x00, 0x20, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, + 0x00, 0x02, 0x00, 0x00, 0x00, 0xfc, 0xff, 0xff, 0xff, 0xff, 0x1f, 0x00, + 0x00, 0x04, 0x00, 0xf0, 0x07, 0x00, 0x10, 0x00, 0x00, 0x04, 0x00, 0x0c, + 0x18, 0x00, 0x10, 0x00, 0x00, 0xfc, 0xff, 0x03, 0xe0, 0xff, 0x1f, 0x00, + 0x00, 0x00, 0x81, 0x00, 0x80, 0x40, 0x00, 0x00, 0x00, 0x80, 0x41, 0x00, + 0x00, 0xc1, 0x00, 0x00, 0x00, 0x80, 0x20, 0x00, 0x00, 0x82, 0x00, 0x00, + 0x00, 0x40, 0x20, 0x00, 0x00, 0x02, 0x01, 0x00, 0x00, 0x40, 0x10, 0x00, + 0x00, 0x04, 0x01, 0x00, 0x00, 0x20, 0x10, 0x00, 0x00, 0x04, 0x02, 0x00, + 0x00, 0x20, 0x08, 0x00, 0x00, 0x08, 0x02, 0x00, 0x00, 0x30, 0x08, 0x00, + 0x00, 0x08, 0x06, 0x00, 0x00, 0x10, 0x08, 0x00, 0x00, 0x08, 0x04, 0x00, + 0x00, 0x10, 0x08, 0x00, 0x00, 0x08, 0x0c, 0x00, 0x00, 0x08, 0x08, 0x00, + 0x00, 0x08, 0x08, 0x00, 0x00, 0x08, 0x08, 0x00, 0x00, 0x08, 0x08, 0x00, + 0x00, 0x08, 0x08, 0x00, 0x00, 0x08, 0x08, 0x00, 0x00, 0x08, 0x10, 0x00, + 0x00, 0x04, 0x08, 0x00, 0x00, 0x08, 0x10, 0x00, 0x00, 0x04, 0x08, 0x00, + 0x00, 0x08, 0x20, 0x00, 0x00, 0x02, 0x08, 0x00, 0x00, 0x08, 0x20, 0x00, + 0x00, 0x02, 0x0c, 0x00, 0x00, 0x18, 0x40, 0x00, 0x00, 0x01, 0x04, 0x00, + 0x00, 0x10, 0x80, 0x00, 0x80, 0x00, 0x04, 0x00, 0x00, 0x10, 0x00, 0x03, + 0x60, 0x00, 0x06, 0x00, 0x00, 0x30, 0x00, 0x0c, 0x18, 0x00, 0x01, 0x00, + 0x00, 0x20, 0x00, 0xf0, 0x07, 0x00, 0x01, 0x00, 0x00, 0x60, 0x00, 0x00, + 0x00, 0x80, 0x01, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, + 0x00, 0x80, 0xff, 0xff, 0xff, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x1f, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x08, 0x20, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x08, 0x40, + 0xe0, 0x00, 0x07, 0x00, 0x00, 0x00, 0x04, 0x80, 0x31, 0x00, 0x0c, 0x00, + 0x00, 0x00, 0x04, 0x00, 0x09, 0x00, 0x30, 0x00, 0x00, 0x00, 0x04, 0x00, + 0x06, 0xc0, 0x20, 0x00, 0x00, 0x00, 0x04, 0x00, 0x03, 0x00, 0x43, 0x00, + 0x00, 0x00, 0x04, 0x80, 0x00, 0x00, 0x42, 0x00, 0x00, 0x00, 0x04, 0x40, + 0x00, 0x00, 0x84, 0x00, 0x00, 0x00, 0x04, 0x60, 0x00, 0x00, 0x84, 0x00, + 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x84, 0x00, 0x00, 0x00, 0x02, 0x00, + 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0xc0, 0x00, + 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x02, 0x00, + 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x20, 0x00, + 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x08, 0x00, + 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00, 0xf0, 0xff, 0xff, 0xff, 0x03, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; diff --git a/hacks/images/noseguy/nose-f3.xpm b/hacks/images/noseguy/nose-f3.xpm new file mode 100644 index 00000000..15d70df2 --- /dev/null +++ b/hacks/images/noseguy/nose-f3.xpm @@ -0,0 +1,74 @@ +/* XPM */ +static char * nose_f3_xpm[] = { +"64 64 7 1", +" c #000000 m #000000", +". c #000000 m #FFFFFF", +"X c #BEBEBE m #000000", +"o c #FFFF00 m #000000", +"O c #EEEE00 m #000000", +"+ c #A020F0 m #000000", +"@ c #7D26CD m #000000", +" ", +" ", +" ", +" ", +" ", +" ..................... ", +" .XXXXXXXXXXXXXXXXXXX. ", +" .XXXXXXXXXXXXXXXXXXX. ", +" .XXXXXXXXXXXXXXXXXXX. ", +" .XXXXXXXXXXXXXXXXXXX. ", +" .XXXXXXXXXXXXXXXXXXX. ", +" ........................................... ", +" .XXXXXXXXXXXXXXXXX.......XXXXXXXXXXXXXXXXX. ", +" .XXXXXXXXXXXXXXX..ooooooo..XXXXXXXXXXXXXXX. ", +" ................ooooooooooo................ ", +" .OOOOOO.ooooooooooooooo.OOOOOO. ", +" ..OOOOO.ooooooooooooooooo.OOOOO.. ", +" .OOOOO.ooooooooooooooooooo.OOOOO. ", +" .OOOOOO.ooooooooooooooooooo.OOOOOO. ", +" .OOOOO.ooooooooooooooooooooo.OOOOO. ", +" .OOOOOO.ooooooooooooooooooooo.OOOOOO. ", +" .OOOOO.ooooooooooooooooooooooo.OOOOO. ", +" ..OOOOO.ooooooooooooooooooooooo.OOOOO.. ", +" .OOOOOO.ooooooooooooooooooooooo.OOOOOO. ", +" .OOOOOO.ooooooooooooooooooooooo.OOOOOO.. ", +" .OOOOOOO.ooooooooooooooooooooooo.OOOOOOO. ", +" .OOOOOOO.ooooooooooooooooooooooo.OOOOOOO. ", +" .OOOOOOO.ooooooooooooooooooooooo.OOOOOOO. ", +" .OOOOOOOO.ooooooooooooooooooooo.OOOOOOOO. ", +" .OOOOOOOO.ooooooooooooooooooooo.OOOOOOOO. ", +" .OOOOOOOOO.ooooooooooooooooooo.OOOOOOOOO. ", +" .OOOOOOOOO.ooooooooooooooooooo.OOOOOOOO.. ", +" ..OOOOOOOOO.ooooooooooooooooo.OOOOOOOOO. ", +" .OOOOOOOOOO.ooooooooooooooo.OOOOOOOOOO. ", +" .OOOOOOOOOOO..ooooooooooo..OOOOOOOOOO.. ", +" ..OOOOOOOOOOOO..ooooooo..OOOOOOOOOOO. ", +" .OOOOOOOOOOOOOO.......OOOOOOOOOOOOO. ", +" ..OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO.. ", +" .OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO. ", +" ................................ ", +" ", +" ......... ", +" .+++++++++. ........ ", +" .++++++++++. ...++++++++... ", +" .++++++++++++.. ..++++++++++++.. ", +" .++++++++++++@. .++++++++++++++++.. ", +" .++++++++++++@@..+++++++++++..@++++. ", +" .++++++++++++@..++++++++++++++..++++. ", +" .+++++++++++@.+++++++++++++++++.@+++. ", +" .++++++++++@.+++++++++++++++++++.@+++. ", +" .++++++++++..+++++++++++++++++++.@+++. ", +" .+++++++++++++++++++++++++++++++.@+++. ", +" .@++++++++++++++++++++++++++++++++++++. ", +" .@++++++++++++++++++++++++++++++++++@.. ", +" .@+++++++++++++++++++++++++++++++++@@. ", +" .@@++++++++++++++++++++++++++++++++@@. ", +" .@++++++++++++++++++++++++++++++@@@. ", +" .@@++++@@@++++++++++++++++++++@@@.. ", +" .@@@@@@@@@@@@@@@@@@@@@@@@@@@@@... ", +" .............................. ", +" ", +" ", +" ", +" "}; diff --git a/hacks/images/noseguy/nose-f4.xbm b/hacks/images/noseguy/nose-f4.xbm new file mode 100644 index 00000000..03ff1dcc --- /dev/null +++ b/hacks/images/noseguy/nose-f4.xbm @@ -0,0 +1,46 @@ +#define nose_f4_width 64 +#define nose_f4_height 64 +static unsigned char nose_f4_bits[] = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0xff, 0x01, 0x00, 0x00, + 0x00, 0x00, 0xc0, 0x03, 0x00, 0x1e, 0x00, 0x00, 0x00, 0x00, 0x38, 0x00, + 0x00, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x03, 0x00, + 0x00, 0x80, 0x01, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x00, 0x00, + 0x00, 0x00, 0x08, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x30, 0x00, + 0x00, 0x10, 0x00, 0x80, 0x1f, 0x00, 0x40, 0x00, 0x00, 0x08, 0x00, 0x60, + 0x60, 0x00, 0x80, 0x00, 0x00, 0x08, 0x00, 0x10, 0x80, 0x00, 0x80, 0x00, + 0x00, 0x04, 0x00, 0x08, 0x00, 0x01, 0x00, 0x01, 0x00, 0x04, 0x00, 0x08, + 0x00, 0x01, 0x00, 0x01, 0x00, 0x02, 0x00, 0x18, 0x80, 0x01, 0x00, 0x02, + 0x00, 0x02, 0x00, 0x68, 0x60, 0x01, 0x00, 0x02, 0x00, 0x02, 0x00, 0x88, + 0x1f, 0x01, 0x00, 0x02, 0x00, 0x02, 0x00, 0x08, 0x00, 0x01, 0x00, 0x02, + 0x00, 0x02, 0x00, 0x10, 0x80, 0x00, 0x00, 0x03, 0x00, 0x06, 0x00, 0x60, + 0x60, 0x00, 0x80, 0x02, 0x00, 0x0c, 0x00, 0x80, 0x1f, 0x00, 0x40, 0x01, + 0x00, 0x14, 0x00, 0x00, 0x00, 0x00, 0x20, 0x01, 0x00, 0x28, 0x00, 0x00, + 0x00, 0x00, 0x90, 0x00, 0x00, 0x50, 0x00, 0x00, 0x00, 0x00, 0x48, 0x00, + 0x00, 0xa0, 0x01, 0x00, 0x00, 0x00, 0x26, 0x00, 0x00, 0x40, 0x1e, 0x00, + 0x00, 0xc0, 0x11, 0x00, 0x00, 0x80, 0xe1, 0x03, 0x00, 0x3c, 0x0c, 0x00, + 0x00, 0x00, 0x0e, 0xfc, 0xff, 0x83, 0x03, 0x00, 0x00, 0x00, 0xf0, 0x01, + 0x00, 0x78, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xff, 0x0f, 0x00, 0x00, + 0x00, 0x00, 0x80, 0x03, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x80, 0x02, + 0x00, 0x14, 0x00, 0x00, 0x00, 0x00, 0x60, 0x04, 0x00, 0x12, 0x00, 0x00, + 0xc0, 0x7f, 0x10, 0x04, 0x00, 0x22, 0xe0, 0x01, 0x70, 0xc0, 0x18, 0x08, + 0x00, 0x61, 0x1c, 0x06, 0x10, 0x00, 0x0f, 0x30, 0xc0, 0x80, 0x07, 0x08, + 0x08, 0x00, 0x06, 0xc0, 0x3f, 0x80, 0x01, 0x08, 0x08, 0x00, 0x18, 0x00, + 0x02, 0xc0, 0x00, 0x10, 0x04, 0x00, 0x30, 0x00, 0x05, 0x30, 0x00, 0x10, + 0x04, 0x00, 0x00, 0x80, 0x08, 0x18, 0x00, 0x20, 0x04, 0x00, 0x00, 0x80, + 0x08, 0x00, 0x00, 0x20, 0x04, 0x00, 0x00, 0x40, 0x10, 0x00, 0x00, 0x20, + 0x24, 0x00, 0x00, 0x40, 0x10, 0x00, 0x00, 0x22, 0x24, 0x00, 0x00, 0x40, + 0x10, 0x00, 0x00, 0x22, 0x44, 0x00, 0x00, 0x40, 0x10, 0x00, 0x00, 0x11, + 0x84, 0x01, 0x00, 0xc0, 0x18, 0x00, 0xc0, 0x10, 0x08, 0x00, 0x00, 0x80, + 0x08, 0x00, 0x00, 0x08, 0x30, 0x00, 0x00, 0x80, 0x08, 0x00, 0x00, 0x04, + 0xe0, 0xff, 0xff, 0xff, 0xf8, 0xff, 0xff, 0x03, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; diff --git a/hacks/images/noseguy/nose-f4.xpm b/hacks/images/noseguy/nose-f4.xpm new file mode 100644 index 00000000..b5c6fcbf --- /dev/null +++ b/hacks/images/noseguy/nose-f4.xpm @@ -0,0 +1,73 @@ +/* XPM */ +static char * nose_f4_xpm[] = { +"64 64 6 1", +" c #000000 m #000000", +". c #000000 m #FFFFFF", +"X c #BEBEBE m #000000", +"o c #FFFF00 m #000000", +"+ c #A020F0 m #000000", +"@ c #7D26CD m #000000", +" ", +" ", +" ", +" ", +" ", +" ", +" ", +" ", +" ", +" ", +" ", +" ", +" ", +" ", +" ............... ", +" ....XXXXXXXXXXXXXXX.... ", +" ...XXXXXXXXXXXXXXXXXXXXXXX... ", +" ..XXXXXXXXXXXXXXXXXXXXXXXXXXXXX.. ", +" ..XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX. ", +" .XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX. ", +" .XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX.. ", +" .XXXXXXXXXXXXXXXXXX......XXXXXXXXXXXXXXXXX. ", +" .XXXXXXXXXXXXXXXXX..XXXXXX..XXXXXXXXXXXXXXXX. ", +" .XXXXXXXXXXXXXXXX.XXXXXXXXXX.XXXXXXXXXXXXXXX. ", +" .XXXXXXXXXXXXXXXX.XXXXXXXXXXXX.XXXXXXXXXXXXXXX. ", +" .XXXXXXXXXXXXXXXX.XXXXXXXXXXXX.XXXXXXXXXXXXXXX. ", +" .XXXXXXXXXXXXXXXXX..XXXXXXXXXX..XXXXXXXXXXXXXXXX. ", +" .XXXXXXXXXXXXXXXXX.X..XXXXXX..X.XXXXXXXXXXXXXXXX. ", +" .XXXXXXXXXXXXXXXXX.XXX......XXX.XXXXXXXXXXXXXXXX. ", +" .XXXXXXXXXXXXXXXXX.XXXXXXXXXXXX.XXXXXXXXXXXXXXXX. ", +" .XXXXXXXXXXXXXXXXXX.XXXXXXXXXX.XXXXXXXXXXXXXXXX.. ", +" ..XXXXXXXXXXXXXXXXXX..XXXXXX..XXXXXXXXXXXXXXXX. . ", +" ..XXXXXXXXXXXXXXXXXXX......XXXXXXXXXXXXXXXXX.X. ", +" .X.XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX.XX. ", +" .X.XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX.XX. ", +" .X.XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX.XX. ", +" .X..XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX..XX. ", +" .XX....XXXXXXXXXXXXXXXXXXXXXXXXX...XXX. ", +" ..XXXX.....XXXXXXXXXXXXXXXX....XXXX.. ", +" ...XXXXXX................XXXXX... ", +" .....XXXXXXXXXXXXXXXXXX.... ", +" ................... ", +" ...oooooooooooooooo.. ", +" .+.oooooooooooooooo.+. ", +" ..+++.oooooooooooooo.++. ", +" ......... .+++++.oooooooooooooo.+++. .... ", +" ...+++++++.. ..++++++.oooooooooooo.++++.. ...++++.. ", +" .+++++++++++....@+++++++..oooooooo..++++++@....++++++++. ", +" .+++++++++++++..@@+++++++++........+++++++@@..++++++++++. ", +" .+++++++++++++++..@+++++++++++.++++++++++@@..++++++++++++. ", +" .+++++++++++++++++..++++++++++. .+++++++++..++++++++++++++. ", +" .++++++++++++++++++++++++++++. .+++++++..++++++++++++++++. ", +" .++++++++++++++++++++++++++++. .+++++++++++++++++++++++++. ", +" .+++++++++++++++++++++++++++. .++++++++++++++++++++++++. ", +" .+@.++++++++++++++++++++++++. .++++++++++++++++++++.+++. ", +" .++.++++++++++++++++++++++++. .++++++++++++++++++++.@+@. ", +" .@+@.+++++++++++++++++++++++. .+++++++++++++++++++.@+@. ", +" .@@+@..++++++++++++++++++++@.. ..@++++++++++++++++..@++@. ", +" .@@+++++++++++++++++++++++@@. .@@+++++++++++++++++++@@. ", +" ..@@@@@@@@@@@@@@@@@@@@@@@@@. .@@@@@@@@@@@@@@@@@@@@@@. ", +" ........................... ....................... ", +" ", +" ", +" "}; diff --git a/hacks/images/noseguy/nose-l1.xbm b/hacks/images/noseguy/nose-l1.xbm new file mode 100644 index 00000000..bc38b020 --- /dev/null +++ b/hacks/images/noseguy/nose-l1.xbm @@ -0,0 +1,46 @@ +#define nose_l1_width 64 +#define nose_l1_height 64 +static unsigned char nose_l1_bits[] = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xff, 0xff, 0x07, 0x00, 0x00, + 0x00, 0x00, 0x40, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, + 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x04, 0x00, 0x00, + 0x00, 0x00, 0x40, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, + 0x00, 0x04, 0x00, 0x00, 0x00, 0xf8, 0xff, 0xff, 0xff, 0xff, 0x3f, 0x00, + 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x08, 0x00, 0x00, + 0x00, 0x00, 0x20, 0x00, 0x00, 0xf8, 0xff, 0xff, 0xff, 0xff, 0x3f, 0x00, + 0x00, 0xf0, 0x03, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x0e, 0x0c, 0x00, + 0x00, 0x80, 0x01, 0x00, 0x00, 0x03, 0x30, 0x00, 0x00, 0x00, 0x01, 0x00, + 0x80, 0x00, 0x40, 0x00, 0x00, 0x00, 0x02, 0x00, 0x40, 0x00, 0xc0, 0x00, + 0x00, 0x00, 0x02, 0x00, 0x20, 0x00, 0x80, 0x00, 0x00, 0x00, 0x04, 0x00, + 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x10, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x0c, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, + 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x08, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x10, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, + 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x08, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x10, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, + 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x10, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x10, 0x00, 0x10, 0x00, 0x00, 0x01, 0x00, 0x00, 0x18, 0x00, + 0x20, 0x00, 0x00, 0x01, 0x00, 0x00, 0x08, 0x00, 0x40, 0x00, 0x80, 0x00, + 0x00, 0x00, 0x08, 0x00, 0x80, 0x00, 0x40, 0x00, 0x00, 0x00, 0x0c, 0x00, + 0x00, 0x01, 0x20, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x06, 0x18, 0x00, + 0x00, 0x00, 0x06, 0x00, 0x00, 0xf8, 0x07, 0x00, 0x00, 0x00, 0x02, 0x00, + 0x00, 0x00, 0xf8, 0xff, 0xff, 0xff, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x0f, 0x00, 0x00, + 0x00, 0x00, 0xff, 0x00, 0x04, 0x10, 0x00, 0x00, 0x00, 0xc0, 0x00, 0x03, + 0x03, 0x10, 0x00, 0x00, 0x00, 0x30, 0x00, 0x0c, 0x01, 0x20, 0x00, 0x00, + 0x00, 0x08, 0x00, 0x98, 0x00, 0x20, 0x00, 0x00, 0x00, 0x0c, 0x03, 0x60, + 0x00, 0x20, 0x00, 0x00, 0x00, 0xc2, 0x00, 0xc0, 0x00, 0x20, 0x00, 0x00, + 0x00, 0x42, 0x00, 0x80, 0x00, 0x20, 0x00, 0x00, 0x00, 0x21, 0x00, 0x00, + 0x01, 0x20, 0x00, 0x00, 0x00, 0x21, 0x00, 0x00, 0x01, 0x20, 0x00, 0x00, + 0x00, 0x21, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, + 0x00, 0x40, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, + 0x00, 0x02, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, + 0x00, 0x40, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, + 0x00, 0x18, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, + 0x00, 0x10, 0x00, 0x00, 0x00, 0xc0, 0xff, 0xff, 0xff, 0x0f, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; diff --git a/hacks/images/noseguy/nose-l1.xpm b/hacks/images/noseguy/nose-l1.xpm new file mode 100644 index 00000000..5240e27b --- /dev/null +++ b/hacks/images/noseguy/nose-l1.xpm @@ -0,0 +1,74 @@ +/* XPM */ +static char * nose_l1_xpm[] = { +"64 64 7 1", +" c #000000 m #000000", +". c #000000 m #FFFFFF", +"X c #BEBEBE m #000000", +"o c #FFFF00 m #000000", +"O c #EEEE00 m #000000", +"+ c #A020F0 m #000000", +"@ c #7D26CD m #000000", +" ", +" ", +" ", +" ", +" ", +" ..................... ", +" .XXXXXXXXXXXXXXXXXXX. ", +" .XXXXXXXXXXXXXXXXXXX. ", +" .XXXXXXXXXXXXXXXXXXX. ", +" .XXXXXXXXXXXXXXXXXXX. ", +" .XXXXXXXXXXXXXXXXXXX. ", +" ........................................... ", +" .XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX. ", +" .XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX. ", +" ........................................... ", +" ......OOOOOOOOOOOOOOOOOOOOOOOOOOOOO. ", +" ...ooOOOO..OOOOOOOOOOOOOOOOOOOOOOOOOOO.. ", +" ..oooOOOOOOO..OOOOOOOOOOOOOOOOOOOOOOOOOO. ", +" .oooOOOOOOOOOOO.OOOOOOOOOOOOOOOOOOOOOOOOOO. ", +" .ooOOOOOOOOOOOOO..OOOOOOOOOOOOOOOOOOOOOOOOO. ", +" .ooOOOOOOOOOOOOOOO.OOOOOOOOOOOOOOOOOOOOOOOOOO. ", +" .ooOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO. ", +" .ooOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO.. ", +" .oooOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO. ", +" .ooOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO. ", +" .ooOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO. ", +" .ooOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO. ", +" .ooOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO. ", +" .ooOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO. ", +" .oooOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO. ", +" .oooOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO. ", +" .oooOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO. ", +" .ooooOOOOOOOOOOOOOOo.OOOOOOOOOOOOOOOOOOOOOOOOOO.. ", +" .ooooOOOOOOOOOOoooo.OOOOOOOOOOOOOOOOOOOOOOOOOO. ", +" .oooooooOOOOOoooo.OOOOOOOOOOOOOOOOOOOOOOOOOOO. ", +" .oooooooooooooo.OOOOOOOOOOOOOOOOOOOOOOOOOOO.. ", +" .oooooooooooo.OOOOOOOOOOOOOOOOOOOOOOOOOOOO. ", +" ..oooooooo..OOOOOOOOOOOOOOOOOOOOOOOOOOOO.. ", +" ........OOOOOOOOOOOOOOOOOOOOOOOOOOOOOO. ", +" .............................. ", +" ", +" ......... ", +" ........ .+++++++++. ", +" ...++++++++... .++++++++++. ", +" ..++++++++++++.. ..++++++++++++. ", +" ..++++++++++++++++. .@++++++++++++. ", +" .++++@..+++++++++++..@@++++++++++++. ", +" .++++..++++++++++++++..@++++++++++++. ", +" .+++@.+++++++++++++++++.@+++++++++++. ", +" .+++@.+++++++++++++++++++.@++++++++++. ", +" .+++@.+++++++++++++++++++..++++++++++. ", +" .+++@.+++++++++++++++++++++++++++++++. ", +" .++++++++++++++++++++++++++++++++++++@. ", +" ..@++++++++++++++++++++++++++++++++++@. ", +" .@@+++++++++++++++++++++++++++++++++@. ", +" .@@++++++++++++++++++++++++++++++++@@. ", +" .@@@++++++++++++++++++++++++++++++@. ", +" ..@@@++++++++++++++++++++@@@++++@@. ", +" ...@@@@@@@@@@@@@@@@@@@@@@@@@@@@@. ", +" .............................. ", +" ", +" ", +" ", +" "}; diff --git a/hacks/images/noseguy/nose-l2.xbm b/hacks/images/noseguy/nose-l2.xbm new file mode 100644 index 00000000..1a2e77f1 --- /dev/null +++ b/hacks/images/noseguy/nose-l2.xbm @@ -0,0 +1,46 @@ +#define nose_l2_width 64 +#define nose_l2_height 64 +static unsigned char nose_l2_bits[] = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xff, 0xff, 0x07, 0x00, 0x00, + 0x00, 0x00, 0x40, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, + 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x04, 0x00, 0x00, + 0x00, 0x00, 0x40, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, + 0x00, 0x04, 0x00, 0x00, 0x00, 0xf8, 0xff, 0xff, 0xff, 0xff, 0x3f, 0x00, + 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x08, 0x00, 0x00, + 0x00, 0x00, 0x20, 0x00, 0x00, 0xf8, 0xff, 0xff, 0xff, 0xff, 0x3f, 0x00, + 0x00, 0xf0, 0x03, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x0e, 0x0c, 0x00, + 0x00, 0x80, 0x01, 0x00, 0x00, 0x03, 0x30, 0x00, 0x00, 0x00, 0x01, 0x00, + 0x80, 0x00, 0x40, 0x00, 0x00, 0x00, 0x02, 0x00, 0x40, 0x00, 0xc0, 0x00, + 0x00, 0x00, 0x02, 0x00, 0x20, 0x00, 0x80, 0x00, 0x00, 0x00, 0x04, 0x00, + 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x10, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x0c, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, + 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x08, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x10, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, + 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x08, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x10, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, + 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x08, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x10, 0x00, 0x10, 0x00, 0x00, 0x01, 0x00, 0x00, 0x18, 0x00, + 0x10, 0x00, 0x00, 0x01, 0x00, 0x00, 0x08, 0x00, 0x20, 0x00, 0x80, 0x00, + 0x00, 0x00, 0x08, 0x00, 0x40, 0x00, 0x40, 0x00, 0x00, 0x00, 0x0c, 0x00, + 0x80, 0x00, 0x20, 0x00, 0x00, 0x00, 0xe4, 0x00, 0x00, 0x03, 0x18, 0x00, + 0x00, 0x00, 0x26, 0x03, 0x00, 0xfc, 0x07, 0x00, 0x00, 0x00, 0x12, 0x0c, + 0x00, 0x00, 0xf8, 0xff, 0xff, 0xff, 0x11, 0x10, 0x80, 0x1f, 0x00, 0x00, + 0x00, 0x00, 0x08, 0x20, 0x60, 0x60, 0xc0, 0x07, 0x00, 0x00, 0x04, 0x40, + 0x10, 0xc0, 0x20, 0x08, 0x00, 0x1f, 0x02, 0x40, 0x08, 0x00, 0x21, 0x10, + 0xc0, 0x60, 0x02, 0x40, 0x04, 0x00, 0x12, 0x20, 0x20, 0x80, 0x02, 0x20, + 0xc2, 0x00, 0x14, 0x40, 0x18, 0x00, 0x03, 0x20, 0x22, 0x00, 0x0c, 0x80, + 0x04, 0x03, 0x02, 0x10, 0x12, 0x00, 0x08, 0x80, 0x86, 0x00, 0x04, 0x10, + 0x12, 0x00, 0x10, 0x80, 0x42, 0x00, 0x18, 0x08, 0x12, 0x00, 0x10, 0x40, + 0x42, 0x00, 0x00, 0x04, 0x02, 0x00, 0x20, 0x40, 0x42, 0x00, 0x00, 0x04, + 0x02, 0x00, 0x00, 0x20, 0x42, 0x00, 0x00, 0x02, 0x04, 0x00, 0x00, 0x20, + 0x02, 0x00, 0x00, 0x01, 0x04, 0x00, 0x00, 0x20, 0x02, 0x00, 0x00, 0x01, + 0x08, 0x00, 0x00, 0x20, 0x04, 0x00, 0x80, 0x00, 0x10, 0x00, 0x00, 0x20, + 0x0c, 0x00, 0x80, 0x00, 0x60, 0x00, 0x00, 0x10, 0x08, 0x00, 0x40, 0x00, + 0x80, 0xff, 0xff, 0x0f, 0x30, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xc0, 0xff, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; diff --git a/hacks/images/noseguy/nose-l2.xpm b/hacks/images/noseguy/nose-l2.xpm new file mode 100644 index 00000000..5fcd2f75 --- /dev/null +++ b/hacks/images/noseguy/nose-l2.xpm @@ -0,0 +1,74 @@ +/* XPM */ +static char * nose_l2_xpm[] = { +"64 64 7 1", +" c #000000 m #000000", +". c #000000 m #FFFFFF", +"X c #BEBEBE m #000000", +"o c #FFFF00 m #000000", +"O c #EEEE00 m #000000", +"+ c #A020F0 m #000000", +"@ c #7D26CD m #000000", +" ", +" ", +" ", +" ", +" ", +" ..................... ", +" .XXXXXXXXXXXXXXXXXXX. ", +" .XXXXXXXXXXXXXXXXXXX. ", +" .XXXXXXXXXXXXXXXXXXX. ", +" .XXXXXXXXXXXXXXXXXXX. ", +" .XXXXXXXXXXXXXXXXXXX. ", +" ........................................... ", +" .XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX. ", +" .XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX. ", +" ........................................... ", +" ......OOOOOOOOOOOOOOOOOOOOOOOOOOOOO. ", +" ...ooOOOO..OOOOOOOOOOOOOOOOOOOOOOOOOOO.. ", +" ..oooOOOOOOO..OOOOOOOOOOOOOOOOOOOOOOOOOO. ", +" .oooOOOOOOOOOOO.OOOOOOOOOOOOOOOOOOOOOOOOOO. ", +" .ooOOOOOOOOOOOOO..OOOOOOOOOOOOOOOOOOOOOOOOO. ", +" .ooOOOOOOOOOOOOOOO.OOOOOOOOOOOOOOOOOOOOOOOOOO. ", +" .ooOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO. ", +" .ooOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO.. ", +" .oooOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO. ", +" .ooOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO. ", +" .ooOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO. ", +" .ooOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO. ", +" .ooOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO. ", +" .ooOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO. ", +" .oooOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO. ", +" .oooOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO. ", +" .oooOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO. ", +" .ooooOOOOOOOOOOOOOOo.OOOOOOOOOOOOOOOOOOOOOOOOOO.. ", +" .ooooOOOOOOOOOOoooo.OOOOOOOOOOOOOOOOOOOOOOOOOO. ", +" .oooooooOOOOOoooo.OOOOOOOOOOOOOOOOOOOOOOOOOOO. ", +" .oooooooooooooo.OOOOOOOOOOOOOOOOOOOOOOOOOOO.. ", +" .oooooooooooo.OOOOOOOOOOOOOOOOOOOOOOOOOOOO. ... ", +" ..oooooooo..OOOOOOOOOOOOOOOOOOOOOOOOOOOO.. .++.. ", +" ........OOOOOOOOOOOOOOOOOOOOOOOOOOOOOO. .+++++.. ", +" .............................. .+++++++. ", +" ...... .+++++++++. ", +" ..++++++.. ..... .++++++++++@. ", +" .+++++++++.. .+++++. ..... .+++++++++++@. ", +" .++++++++++++. .++++++. ..+++++.. .++++++++++@@. ", +" .++++++++++++++. .++++++++. .+++++++++. .@+++++++++@. ", +" .++++..++++++++++. .+++++++++. ..+++++++++++..@++++++++@@. ", +" .+++.@@++++++++++..@++++++++++. .+++++..+++++++.@@+++++++@. ", +" .++.@+++++++++++++.@@+++++++++. ..++++.@@++++++++.@@+++++@@. ", +" .++.@++++++++++++++.@+++++++++. .++++.@+++++++++++..++++@@. ", +" .++.@++++++++++++++.@++++++++. .++++.@+++++++++++++++++@. ", +" .@++++++++++++++++++.@+++++++. .++++.@++++++++++++++++@@. ", +" .@@+++++++++++++++++++++++++. .++++.@+++++++++++++++@@. ", +" .@++++++++++++++++++++++++@. .+++++++++++++++++++++@. ", +" .@@+++++++++++++++++++++++@. .++++++++++++++++++++@@. ", +" .@@++++++++++++++++++++++@. .+++++++++++++++++++@. ", +" .@@@+++++++++++++++++++@@. ..+++++++++++++++++@@. ", +" ..@@@@@@@@@@@@@@@@@@@@@. .@@@+++@@@++++++@@@. ", +" ..................... ..@@@@@@@@@@@@@@.. ", +" .............. ", +" ", +" ", +" ", +" ", +" "}; diff --git a/hacks/images/noseguy/nose-r1.xbm b/hacks/images/noseguy/nose-r1.xbm new file mode 100644 index 00000000..3e410634 --- /dev/null +++ b/hacks/images/noseguy/nose-r1.xbm @@ -0,0 +1,46 @@ +#define nose_r1_width 64 +#define nose_r1_height 64 +static unsigned char nose_r1_bits[] = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0xff, 0xff, 0x03, 0x00, 0x00, + 0x00, 0x00, 0x20, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, + 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x02, 0x00, 0x00, + 0x00, 0x00, 0x20, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, + 0x00, 0x02, 0x00, 0x00, 0x00, 0xfc, 0xff, 0xff, 0xff, 0xff, 0x1f, 0x00, + 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x04, 0x00, 0x00, + 0x00, 0x00, 0x10, 0x00, 0x00, 0xfc, 0xff, 0xff, 0xff, 0xff, 0x1f, 0x00, + 0x00, 0x00, 0x01, 0x00, 0x00, 0xc0, 0x0f, 0x00, 0x00, 0x80, 0x01, 0x00, + 0x00, 0x30, 0x70, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x0c, 0xc0, 0x00, + 0x00, 0x40, 0x00, 0x00, 0x00, 0x02, 0x00, 0x01, 0x00, 0x40, 0x00, 0x00, + 0x00, 0x03, 0x00, 0x02, 0x00, 0x20, 0x00, 0x00, 0x00, 0x01, 0x00, 0x04, + 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x30, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x08, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, + 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x08, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x10, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, + 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x08, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x10, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, + 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x08, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x08, 0x00, 0x18, 0x00, 0x00, 0x80, 0x00, 0x00, 0x08, + 0x00, 0x10, 0x00, 0x00, 0x80, 0x00, 0x00, 0x04, 0x00, 0x10, 0x00, 0x00, + 0x00, 0x01, 0x00, 0x02, 0x00, 0x30, 0x00, 0x00, 0x00, 0x02, 0x00, 0x01, + 0x00, 0x20, 0x00, 0x00, 0x00, 0x04, 0x80, 0x00, 0x00, 0x60, 0x00, 0x00, + 0x00, 0x18, 0x60, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0xe0, 0x1f, 0x00, + 0x00, 0x80, 0xff, 0xff, 0xff, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x1f, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x08, 0x20, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x08, 0xc0, + 0xc0, 0x00, 0x03, 0x00, 0x00, 0x00, 0x04, 0x80, 0x30, 0x00, 0x0c, 0x00, + 0x00, 0x00, 0x04, 0x00, 0x19, 0x00, 0x10, 0x00, 0x00, 0x00, 0x04, 0x00, + 0x06, 0xc0, 0x30, 0x00, 0x00, 0x00, 0x04, 0x00, 0x03, 0x00, 0x43, 0x00, + 0x00, 0x00, 0x04, 0x00, 0x01, 0x00, 0x42, 0x00, 0x00, 0x00, 0x04, 0x80, + 0x00, 0x00, 0x84, 0x00, 0x00, 0x00, 0x04, 0x80, 0x00, 0x00, 0x84, 0x00, + 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x84, 0x00, 0x00, 0x00, 0x02, 0x00, + 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x80, 0x00, + 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x02, 0x00, + 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x20, 0x00, + 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x08, 0x00, + 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00, 0xf0, 0xff, 0xff, 0xff, 0x03, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; diff --git a/hacks/images/noseguy/nose-r1.xpm b/hacks/images/noseguy/nose-r1.xpm new file mode 100644 index 00000000..17423bc7 --- /dev/null +++ b/hacks/images/noseguy/nose-r1.xpm @@ -0,0 +1,74 @@ +/* XPM */ +static char * nose_r1_xpm[] = { +"64 64 7 1", +" c #000000 m #000000", +". c #000000 m #FFFFFF", +"X c #BEBEBE m #000000", +"o c #FFFF00 m #000000", +"O c #EEEE00 m #000000", +"+ c #A020F0 m #000000", +"@ c #7D26CD m #000000", +" ", +" ", +" ", +" ", +" ", +" ..................... ", +" .XXXXXXXXXXXXXXXXXXX. ", +" .XXXXXXXXXXXXXXXXXXX. ", +" .XXXXXXXXXXXXXXXXXXX. ", +" .XXXXXXXXXXXXXXXXXXX. ", +" .XXXXXXXXXXXXXXXXXXX. ", +" ........................................... ", +" .XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX. ", +" .XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX. ", +" ........................................... ", +" .OOOOOOOOOOOOOOOOOOOOOOOOOOOOO...... ", +" ..OOOOOOOOOOOOOOOOOOOOOOOOOOO..OOOOoo... ", +" .OOOOOOOOOOOOOOOOOOOOOOOOOO..OOOOOOOooo.. ", +" .OOOOOOOOOOOOOOOOOOOOOOOOOO.OOOOOOOOOOOooo. ", +" .OOOOOOOOOOOOOOOOOOOOOOOOO..OOOOOOOOOOOOOoo. ", +" .OOOOOOOOOOOOOOOOOOOOOOOOOO.OOOOOOOOOOOOOOOoo. ", +" .OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOoo. ", +" ..OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOoo. ", +" .OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOooo. ", +" .OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOoo. ", +" .OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOoo. ", +" .OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOoo. ", +" .OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOoo. ", +" .OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOoo. ", +" .OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOooo. ", +" .OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOooo. ", +" .OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOooo. ", +" ..OOOOOOOOOOOOOOOOOOOOOOOOOO.oOOOOOOOOOOOOOOoooo. ", +" .OOOOOOOOOOOOOOOOOOOOOOOOOO.ooooOOOOOOOOOOoooo. ", +" .OOOOOOOOOOOOOOOOOOOOOOOOOOO.ooooOOOOOooooooo. ", +" ..OOOOOOOOOOOOOOOOOOOOOOOOOOO.oooooooooooooo. ", +" .OOOOOOOOOOOOOOOOOOOOOOOOOOOO.oooooooooooo. ", +" ..OOOOOOOOOOOOOOOOOOOOOOOOOOOO..oooooooo.. ", +" .OOOOOOOOOOOOOOOOOOOOOOOOOOOOOO........ ", +" .............................. ", +" ", +" ......... ", +" .+++++++++. ........ ", +" .++++++++++. ...++++++++... ", +" .++++++++++++.. ..++++++++++++.. ", +" .++++++++++++@. .++++++++++++++++.. ", +" .++++++++++++@@..+++++++++++..@++++. ", +" .++++++++++++@..++++++++++++++..++++. ", +" .+++++++++++@.+++++++++++++++++.@+++. ", +" .++++++++++@.+++++++++++++++++++.@+++. ", +" .++++++++++..+++++++++++++++++++.@+++. ", +" .+++++++++++++++++++++++++++++++.@+++. ", +" .@++++++++++++++++++++++++++++++++++++. ", +" .@++++++++++++++++++++++++++++++++++@.. ", +" .@+++++++++++++++++++++++++++++++++@@. ", +" .@@++++++++++++++++++++++++++++++++@@. ", +" .@++++++++++++++++++++++++++++++@@@. ", +" .@@++++@@@++++++++++++++++++++@@@.. ", +" .@@@@@@@@@@@@@@@@@@@@@@@@@@@@@... ", +" .............................. ", +" ", +" ", +" ", +" "}; diff --git a/hacks/images/noseguy/nose-r2.xbm b/hacks/images/noseguy/nose-r2.xbm new file mode 100644 index 00000000..1fdd6b49 --- /dev/null +++ b/hacks/images/noseguy/nose-r2.xbm @@ -0,0 +1,46 @@ +#define nose_r2_width 64 +#define nose_r2_height 64 +static unsigned char nose_r2_bits[] = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0xff, 0xff, 0x03, 0x00, 0x00, + 0x00, 0x00, 0x20, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, + 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x02, 0x00, 0x00, + 0x00, 0x00, 0x20, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, + 0x00, 0x02, 0x00, 0x00, 0x00, 0xfc, 0xff, 0xff, 0xff, 0xff, 0x1f, 0x00, + 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x04, 0x00, 0x00, + 0x00, 0x00, 0x10, 0x00, 0x00, 0xfc, 0xff, 0xff, 0xff, 0xff, 0x1f, 0x00, + 0x00, 0x00, 0x01, 0x00, 0x00, 0xc0, 0x0f, 0x00, 0x00, 0x80, 0x01, 0x00, + 0x00, 0x30, 0x70, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x0c, 0xc0, 0x00, + 0x00, 0x40, 0x00, 0x00, 0x00, 0x02, 0x00, 0x01, 0x00, 0x40, 0x00, 0x00, + 0x00, 0x03, 0x00, 0x02, 0x00, 0x20, 0x00, 0x00, 0x00, 0x01, 0x00, 0x04, + 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x30, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x08, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, + 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x08, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x10, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, + 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x08, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x10, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, + 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x08, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x10, 0x00, 0x18, 0x00, 0x00, 0x80, 0x00, 0x00, 0x08, + 0x00, 0x10, 0x00, 0x00, 0x80, 0x00, 0x00, 0x08, 0x00, 0x10, 0x00, 0x00, + 0x00, 0x01, 0x00, 0x04, 0x00, 0x30, 0x00, 0x00, 0x00, 0x02, 0x00, 0x02, + 0x00, 0x27, 0x00, 0x00, 0x00, 0x04, 0x00, 0x01, 0xc0, 0x64, 0x00, 0x00, + 0x00, 0x18, 0xc0, 0x00, 0x30, 0x48, 0x00, 0x00, 0x00, 0xe0, 0x3f, 0x00, + 0x08, 0x88, 0xff, 0xff, 0xff, 0x1f, 0x00, 0x00, 0x04, 0x10, 0x00, 0x00, + 0x00, 0x00, 0xf8, 0x01, 0x02, 0x20, 0x00, 0x00, 0xe0, 0x03, 0x06, 0x06, + 0x02, 0x40, 0xf8, 0x00, 0x10, 0x04, 0x03, 0x08, 0x02, 0x40, 0x06, 0x03, + 0x08, 0x84, 0x00, 0x10, 0x04, 0x40, 0x01, 0x04, 0x04, 0x48, 0x00, 0x20, + 0x04, 0xc0, 0x00, 0x18, 0x02, 0x28, 0x00, 0x43, 0x08, 0x40, 0xc0, 0x20, + 0x01, 0x30, 0x00, 0x44, 0x08, 0x20, 0x00, 0x61, 0x01, 0x10, 0x00, 0x48, + 0x10, 0x18, 0x00, 0x42, 0x01, 0x08, 0x00, 0x48, 0x20, 0x00, 0x00, 0x42, + 0x02, 0x08, 0x00, 0x48, 0x20, 0x00, 0x00, 0x42, 0x02, 0x04, 0x00, 0x40, + 0x40, 0x00, 0x00, 0x42, 0x04, 0x00, 0x00, 0x40, 0x80, 0x00, 0x00, 0x40, + 0x04, 0x00, 0x00, 0x20, 0x80, 0x00, 0x00, 0x40, 0x04, 0x00, 0x00, 0x20, + 0x00, 0x01, 0x00, 0x20, 0x04, 0x00, 0x00, 0x10, 0x00, 0x01, 0x00, 0x30, + 0x04, 0x00, 0x00, 0x08, 0x00, 0x02, 0x00, 0x10, 0x08, 0x00, 0x00, 0x06, + 0x00, 0x0c, 0x00, 0x0c, 0xf0, 0xff, 0xff, 0x01, 0x00, 0xf0, 0xff, 0x03, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; diff --git a/hacks/images/noseguy/nose-r2.xpm b/hacks/images/noseguy/nose-r2.xpm new file mode 100644 index 00000000..f1eea0a7 --- /dev/null +++ b/hacks/images/noseguy/nose-r2.xpm @@ -0,0 +1,74 @@ +/* XPM */ +static char * nose_r2_xpm[] = { +"64 64 7 1", +" c #000000 m #000000", +". c #000000 m #FFFFFF", +"X c #BEBEBE m #000000", +"o c #FFFF00 m #000000", +"O c #EEEE00 m #000000", +"+ c #A020F0 m #000000", +"@ c #7D26CD m #000000", +" ", +" ", +" ", +" ", +" ", +" ..................... ", +" .XXXXXXXXXXXXXXXXXXX. ", +" .XXXXXXXXXXXXXXXXXXX. ", +" .XXXXXXXXXXXXXXXXXXX. ", +" .XXXXXXXXXXXXXXXXXXX. ", +" .XXXXXXXXXXXXXXXXXXX. ", +" ........................................... ", +" .XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX. ", +" .XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX. ", +" ........................................... ", +" .OOOOOOOOOOOOOOOOOOOOOOOOOOOOO...... ", +" ..OOOOOOOOOOOOOOOOOOOOOOOOOOO..OOOOoo... ", +" .OOOOOOOOOOOOOOOOOOOOOOOOOO..OOOOOOOooo.. ", +" .OOOOOOOOOOOOOOOOOOOOOOOOOO.OOOOOOOOOOOooo. ", +" .OOOOOOOOOOOOOOOOOOOOOOOOO..OOOOOOOOOOOOOoo. ", +" .OOOOOOOOOOOOOOOOOOOOOOOOOO.OOOOOOOOOOOOOOOoo. ", +" .OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOoo. ", +" ..OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOoo. ", +" .OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOooo. ", +" .OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOoo. ", +" .OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOoo. ", +" .OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOoo. ", +" .OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOoo. ", +" .OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOoo. ", +" .OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOooo. ", +" .OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOooo. ", +" .OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOooo. ", +" ..OOOOOOOOOOOOOOOOOOOOOOOOOO.oOOOOOOOOOOOOOOoooo. ", +" .OOOOOOOOOOOOOOOOOOOOOOOOOO.ooooOOOOOOOOOOoooo. ", +" .OOOOOOOOOOOOOOOOOOOOOOOOOOO.ooooOOOOOooooooo. ", +" ..OOOOOOOOOOOOOOOOOOOOOOOOOOO.oooooooooooooo. ", +" ... .OOOOOOOOOOOOOOOOOOOOOOOOOOOO.oooooooooooo. ", +" ..++. ..OOOOOOOOOOOOOOOOOOOOOOOOOOOO..oooooooo.. ", +" ..+++++. .OOOOOOOOOOOOOOOOOOOOOOOOOOOOOO........ ", +" .+++++++. .............................. ", +" .+++++++++. ...... ", +" .@++++++++++. ..... ..++++++.. ", +" .@+++++++++++. ..... .+++++. ..+++++++++. ", +" .@@++++++++++. ..+++++.. .++++++. .++++++++++++. ", +" .@+++++++++@. .+++++++++. .++++++++. .++++++++++++++. ", +" .@@++++++++@..+++++++++++.. .+++++++++. .++++++++++..++++. ", +" .@+++++++@@.+++++++..+++++. .++++++++++@..++++++++++@@.+++. ", +" .@@+++++@@.++++++++@@.++++.. .+++++++++@@.+++++++++++++@.++. ", +" .@@++++..+++++++++++@.++++. .+++++++++@.++++++++++++++@.++. ", +" .@+++++++++++++++++@.++++. .++++++++@.++++++++++++++@.++. ", +" .@@++++++++++++++++@.++++. .+++++++@.++++++++++++++++++@. ", +" .@@+++++++++++++++@.++++. .+++++++++++++++++++++++++@@. ", +" .@+++++++++++++++++++++. .@++++++++++++++++++++++++@. ", +" .@@++++++++++++++++++++. .@+++++++++++++++++++++++@@. ", +" .@+++++++++++++++++++. .@++++++++++++++++++++++@@. ", +" .@@+++++++++++++++++.. .@@+++++++++++++++++++@@@. ", +" .@@@++++++@@@+++@@@. .@@@@@@@@@@@@@@@@@@@@@.. ", +" ..@@@@@@@@@@@@@@.. ..................... ", +" .............. ", +" ", +" ", +" ", +" ", +" "}; diff --git a/hacks/images/osx_10_2.xpm b/hacks/images/osx_10_2.xpm new file mode 100644 index 00000000..eeb78731 --- /dev/null +++ b/hacks/images/osx_10_2.xpm @@ -0,0 +1,298 @@ +/* XPM */ +static char *osx_10_2[] = { +/* width height ncolors chars_per_pixel */ +"468 256 35 1", +/* colors */ +" c #000000", +". c #A9A9A9", +"X c #9D9D9D", +"o c #959595", +"O c #6B6B6B", +"+ c #595959", +"@ c #E8E8E8", +"# c #E4E4E4", +"$ c #E2E2E2", +"% c #E0E0E0", +"& c #DEDEDE", +"* c #DCDCDC", +"= c #292929", +"- c #D4D4D4", +"; c #D0D0D0", +": c #CECECE", +"> c #CCCCCC", +", c #CACACA", +"< c #848484", +"1 c #4C4C4C", +"2 c #363636", +"3 c #E3E3E3", +"4 c #E1E1E1", +"5 c #DFDFDF", +"6 c #DDDDDD", +"7 c #2A2A2A", +"8 c #D9D9D9", +"9 c #242424", +"0 c #D1D1D1", +"q c #CFCFCF", +"w c #CDCDCD", +"e c #1A1A1A", +"r c #101010", +"t c #BDBDBD", +"y c #060606", +/* pixels */ +"&55555555&5555555&&&555555&555555555555555555&5555&5555555555555&5&5555555&5&555555555555555555555555555555555&55555&555555555&555555555&555555555555555&5555&55&5555&5555&555555&5&55555&55555555555555&5&&5555555555&5&&555&5&55&5&&5555555555555555555555555555&5555555&&5555555&555555555&555&&&555555&&55555555555&55&55555555555555&&555555&5&&555555&5&55&555&5&555555&5555&5&5555&&&5&5555555555555&&&5555555&5555555555555555&555&5555555555555&5555555&5555555555555555&55", +"555&555&5555555&5555&5&55555555555&55555&55555&&55555555555&555&55555&&555&55555555&555&555&555555555555555&55555&555555555555&555555&555&55555555&555&&55&555555555&5555555555555&555555&555555555555&&555555&5555&555555&555555555555555&5555&5555555555&555555555&&55&5&555555555&55&5555&55&555555&55555&5555555&55555555&5&55&5555555&55555555555555&55&55&&&5555&55555555555555555&5555&555555555&555&555555&555&555&&&555&&555&555555&&5555&55555&&55555555&555&5555555555&55", +"555555555555555&5555555555555555555&5555555555&55555555555555555555555555555555555555555555&5555555555555&55&5555&55&555&555&5555&555555555&55555555555555555555555&&5&&5&&5555555555&55&55555&555555555555555555&&&&55&5&5555555555555555&5&55555&55&5&555555&5555555555555555&555&55&55555555555&555555555555&55555555555555&&&&5555555&555555555&&5&555&55555&5555&5555555555&5&5555&55555&5555555555&5&555&555555555555555555555555555&555555555555&55&5&&5555555&555555555555&5", +"5&55&5&55&55&5&555&55555&&&5&&55&555&555555555&555555555555555555555555555555555&5555555&5555555&5555555&5555555555&55555&&5555&5&55&5&55&555&55555&55555555&5555555&&555555555&555555555555&5555&55555&555555&5555555555555555555555555&555555&5555555555555555555&5&5&555555555555555555&555&55&555555555555555555&55&5&5555555555555555&5555&555555&&55&55&5&&55555&55&55&5555&5555555&&&5&55&5&555555555&55&5555&55&&5555555555555555555555555555555555555555555&5555&5555&&5555", +"5&555&55555&&5&55555&555555555555555&&55&&55&55555&55555&55&555&555&555&&&555&555&5555&&&55555&5555555555555555555&&5&5555555555&555&55555555&55555&555555555555555555555555555555&5&55&55555555555&5&5&55&5555555555&&5555&5555555&555555&55555555&5555&55&55555&5&55555555555&555555555&5&55555555&555&5&555&55555555&555&555555555&555&555555&&5555&555555&555555&5555555&5&55&555&5555555555555555555&555&5555&5555555555&55&555&55&55555&555&555555&555555555&55&55555&&55&5555", +"5555&55555555&55555555555555555555&&55&55555555555555&&55&&5555555555555&5&5&5&555&55&555555&555555555555555555&5555&55555555&5555555555&5555555555555555555555555555&5555555555&5555555555555555&5555555555555555555555555&5&55555555555555&&555555&55555&55&55555555&55555555&5555555555555555555&&555&5555555555&555555&555&&5555555555&55555555&5&5555555&5555&5555&5555555&555555&5555555555&5&555555555555555&555555555555555555555&&5555&555555555555555&5555555555555&5&5555", +"5555555555555&55555555555&5555555555&5555&555555555555555555555&5555555555&55&5555555&555&5555&5555555&5555555555&555&55555&55&5&5555555&55&5555555&55555555&5&&5555555&555555555&5&555&55&555&555555555555555&5555&55&&5555555555&5555&&555555555&55&5&55&5&5555555&555&5&55&55555&5555555555555&5&55&555555&5555555555555&555555555555555&&5555&5&55&55&5555&555&5555&555555555&&5555&5555555555&&5&55&5555&5&5555555555&5555&55&55&&5555&55555555&5555555&555555&55555555&5555555", +"&55555555555&555555&555555&55&555555&&55555555555&5&&5555555555555&55&555555555555&5555&555555&5555555&&5&55&55&555555555&555555&555555555555555&5555555555555&5555555555555&555555&555555&5&5555555&55&&5555555555555&5&55555555555555&55&55&&555555555555555555&&55&5555555555&5555555555555555555&&555555555555&&55&555555&&5&5555&5&55555&5&55555555555555555&5555555&55&55555&555555555555555555555555555555&55&555555&5555&5&55555&5555&555&5555555555&55&5555555&&&555&555555", +"55&55555&555555555&55555&555555555555555&5&555555&&55&&&555&555&5555555555555555555&555&55555&55555555&&&55555&555&5&55555555555555555555&555555&5&&&&55555555555555555555&555555555&55&555&5555555555555&5555555555&555&55&&555555&55555&5555&55555555&555&5555555&5555555&555555555555555&55555555555555555555&5555&5555555555&55555555555555&5555&&&55555555555555555&5555555555555555555555555555555555555&55555&&55555&5555555&&&5555555555555&555&555555555555555555&&&5555555", +"&&55555&&5&5555555&555555555&55555555&5&555&55&555555555555555555&&55555555555555&555555555555&555555555555&555&&&5555&5555555&&555&5&5555&5555555&5555555555555&555&555&555555&5555&55555&55555555555555&&5555&5&&5&55&55555555&5&5555&&55555&5&5555555&&555&5555&5&5&5&555&555555555&555&55555555&555555&55555555555555555555&55555&555555555555&55555&55555&&55555555&&55555555555555555555555&&&555555555&&55555&555&55555&5555555555555555555555&555555555555555555555555555555", +"555&555&5555555555555555&5555&&555555555555&55555&5555&55555555&5555555555&55555&5555555555555555555555&55&&555555555555555555&&&55&&&5555&555555555555&55555&55555555&555555555&&55&5&5555&555&555555&5&55555555&555&555555555&555&5&&555&55&555&&&&555555&5&5&55555&&&555&5&55555&&55555555&55555&5&555555555555555555&&55&555555&55555&55555&55&55555555555555&5555&55&55&5&5555555555555555&5555&55555&&55555555555555&555555555&555555555&555555&5555&55555&&&555555&&5555&5555", +"55555555555555&5555555&555&55555&5555555555555555555&5555&5555&55555555&5555&55555&5&&&55555555555&5555555555&55555&55555555555&5&55&5555555&&5&5555555&&&5555555555&5&&555&5&5&555&5555555&55&5555&555555555&55&55&555&5&555555&55&5555&555555&5&55555555&&&555&5555555&55&55555555&&55555555555&55555555555555&5555&55555&5555555&555&55&55555555555555555&555555555555555&&5&&555555&555555555555&5555&555555&55555555&&5555555555555555&&5555555555555555555555&555555555555&555", +"&5555&55555555555555555555&5555555555&5555&&&55555555555555555555&555555555555&555555&&5&55&555555&55555&55&55&555555555555555&5555555555&5555&555555555&55555&5&5555555&55555555555555555&5555555&5&55&555555&&&5555555&5555555555555&55555555555&5&55555555555555555555555&5&5555555&5555&5555&555555&55555555555&&55&&5555555&55555&&555555555555&&55&55&55&&55&555555555555555&555555555&5555&55555&&5&55555555&55555555555555555&5555&555&5555555&55&5555555&55555&&55&5&555555", +"555555555555555555&5555555555&55&555555&55555&555555555555&55555555555&&&5&55&55555&55555555&&&55555555555555&55555555555555&55555&&555&&555555555&55555555&5555555555555&555555555&5555&555555&&5&5&5555&5&5555555&55555&55&555555555555555&5&55555555&&555555&55555555&555555555555555&5555555555555555555555555555&55&&5555555555555&5555555555555&&5&5&55&55&555&5555555555555&&5&5555555555555555555&5&555555&555&555555555555555555555555555&5555555555&5555555555555555555&55", +"5555555&5555555555555&55&555555555&55555555&55555&555&555&&5&5&55&55&&555&&5&55&555555555&&5555555555555&5&55555&&555&555555555&&55555555555&55555555&5555555555555&&555555555555&5&5&555555555&555555&5555555&555555&5&55&&555555555555555555555&&5&5&555555555555555555&5&5&&55555&5&5&5555555555555555&&5555555555&&5555&5&5&5&555&55&5555555&5&555555555555&5555&5555555555555555555&5555&5555&5555&5555&&55&555555&55555555555555555555&5555555555555555&555&55555&55555&55&&&5", +"&5&55&5555555555555&555555555&555555555555&5555555&55&555&555555555555555&5555&5555555555555555555555555&555555555555555&5555&55555555555555&55&5555&55&&&55&555&55555&&&555555555555&5555&&5555&&55555555&&55555&5555&555555555555555&&&5555&5555&5555555&555&&&5&55&5&5555&5&555555&55555555555&55555555555&555&555555&5555&555555555&55555555&55&555&55555&55&&55555&555&55&&&55555555&555555555555555555555555555555555555&555555555555&5555555555555&555555&&&55&&55555&5555555", +"55&5555&&&&555555&55555564655%%5&5%%646%5&55555555555555&55&55555555&&55&5555&&56%45&%65&5&&5555555555&&5555&555&555555555&5&555555&55&&55555555555555555&&555&&555555555&55&5&555555&55555555&55555&555&55555&555&5&5555555&5&55&&55555555&55555555&55&5*45&56%55&4%&%655&5%&%55&4&5&%&5555555555&&56%&&555555555555555555555&&555&555&6*%565555555555555%5&&5%&5&*5%555&555&5&5&55555&5555&5555&36%&555%&&%*4555555555&5555555555&&55555555&55&555&55555555555555555&5555555555555", +"&5&5&5&5&5&&55&5&5555555%4%%66#65&653&6555555555&555555&5&5&&5555&&55&55&555555&36&5*45&55555555555555&555&5555555555555555555&55&555&55555555&555&555555555555555555555&5555&55&&5555&555&555&55555555555&55555555555555555&5555555555555555555555555&55%66%&%55$4*&%*46%55&%65%&556%*%555555555&4$&&%5&5555&5555&5&5&&555555555&555555%5%56%6%55&55555&5&5%#*5%6535*&&55555555&555555&5555&555548%6%%6555&%5&4&555555555555&5555555555555555555&&55555555555&55555&55555555&&55555", +"555555&555555555&5555&556&%&&5*%4&3&*4%&5555&55555&&&5555555&5555555555555&5555&546%3*%%555555&55555555555&&55&555555&55555&555555&555555555555&55555&5555555555&555555&555&55&55&55&5&555555&5555&&55&&&55&555555&5555555&555555555&&55555555555555555&48%4%5$64*%&$&%%%&5$4*&%6$%*54455555&555&%&&6%$&&55555&555&555555&5&&5&&5555&555&&65$&5&&5555555&%%6&*$*55&654%65555555&5555555555&555&5%6&456%4*&4%*%%&&5&&555&5555&5555&555&5555&55555&555555555&5555&&55555555555555555&5", +"&5555555&55555&5&555&&5&4%5564&%6*&$546655&5555&5555&55555&555&555&5&555555&&55&*5%&*3&6&555&5555555&&55&&55555555555555555&5&55555555&555555555&5555&555555555&55555555&5555&555555555555555555&555555&5555&5555555&55&5555&5555&5&555&5555555555&555556#65*$&554645&&5&%5*6#*%5&554&&555&55&55$6&%5%*%5555&5&555555555555555555555&555535*6&%&55555555%*&%5%5464%54&6%555555555555555&55555555&%*4%&*&34*5%6%&555555&5555&5&5555555&555&5555555&5&55555&5&5&5&5555555&5555&5555555", +"555555555555555555555&&5&68%466&5#6%%*5%55555555555&555555&55&555555555&555555555%5656&%55555&55555&555&555&5&55555&&5555&55555&555555&55&5&55&555555555555&&55&55555&5555555&555555555555&555555&555&&555&5&5555555&555&55555&5&55555555555555555555&&5&*%&$5&%65&65%$655%%5&5&%6%%65545555&5556%5&55545555&5&5555555&5555555&555555&55*5&45%6%555&&&55&45*5&6555&55&&45&5&555555555555555555&555356%4%*65*4&5%5&5&5555555&555555555&5&5555555555&5555&5&55&&55&5555555555555&55555", +"55555555555&5&555555555&4%#&66%5%86&%5&5555&555&555555&&5&5&555&55555555555&555565*%5$4&&5555&&5555&&5555&555555&555&5&5555555555555&5&5555555&5555&5&555555&5555&555555555555555555&5555555555555555&&5555&55&555555555555555&&5555555555&55555555&5555%4555&%&4&%*%%*%$6*%56356%%5$*#*&5555&5555845%&&&555555555555555&&55555555555555%55&655*&&555555%56$55%&4*&$6645&55&555&555555555555&555$*64&&4*$&#&*4%555&&5&5555&5&5&555&55&55555555&555555&55555555555&5555555&5555555555", +"55555&55555555555555555564*55%5%4%5%5%&45555&555&555555555&55&5555555555555555&554%66&*5555&55&5&55&5&55555&555555555555555&5555&5&&5&55555&5555&55555555&&&555555555555555&&5555555555555555&55555555555&55555555555555&555&5555555&&55555555555555555&6556655%66&46&%55*$6%*%&5$565%*5555555&546%%6&%5&5555&&555555&5555555555555555&5%65%&53555555&5&55&&&%5%54%%%5&555555555555&&&5&555555555%%&55*4&%*%&%555&5&5&55555555555&55555555&55&555&5555555555&5&55555555&55555&&&5555", +"5555555555555555555555555<<&%&5X<&6$*5%&5&55&55&5&&555&5&5&55555555555&555555555%+=$*46%55&555&55&55555&&5&&5&&555555555555555&55555555555&5555555555555&5&5555555555&5555&555&555555555555555555555555&5555555&55555&55&55555&555555555555&5555&&5555555*%$t+5&%$oO&%5&&%6&557+5&6%55+=&5&5&555&%& o$&&555555555555555555555&5&555555555X %5&6%55555555*36&%++++.%5*%655555&55555555&555555&55&&&%6%5% o&%555&%&5&5555&55555555555555555&&555&555555&555&55&5555&5&555555555&55&55&", +"&5&55&555&5555&5555555556X .$4wr.%5%*%656%465%5&555*$&%%%&%&%5&5%*$*5%*4$5&%555%*+756545&.t&5%*%554645*&5555*536%*%%66%*555%*t.55%&5%5*4466466%o:*%%55%&%&$6%%*%*446%55&64&%455%&4&%&%55%&3&*%*5*44&%55565$&55*%5&5%&5&%%*$%&*%555&.t5&555%6%5&5555%6%54555%X 46&6+75645&5&55%=+%&%%&4+=*4%*35&5&%% X5&%&5%&55%%%5&%65%&&&4&$55%654*:o%5&X 5&545&465&&%*465%& 1+2 <5%636&%&556555555%&*%&%%5%6*4&&5%5*% o&*$6%&5&55%55&.t%&%oq%55&6%65%5&55&555%5555555&555555&&555555&555&555&55555", +"&&555&5555&55555&55&5555%&17*511&6&4oo45%&&6%555563554&*&..56&4%..*$$&%to4%*45wo;+7645%6%=+64*%5oX6%*545556$5o*%6to653*%.o0&3+7&&&%qoX4*&%4*.w6 o365*4&5&&6&5&66tXt4&6&5%44%*5655tt*4%465&.ot5&&tXt$6&&&3tX56qX,5&5&&:ot&555&4&5%&&7+*&4%>o:&%&%55oA*56$5X &%4&+=566%oX5%*&7+6%&wX,+7%&6&&%64..& o5$5.X,5%&5*&&$5%*5%645..5%65*63o 55%o $to%6%5%to5%%6%&45 o&527*&%oo&*4$&%%65&%*636&Xt$*55%*.q56%3* X;Xt&&%5$5*65&5=+*%5 X6&5%,X.*555%5qX,5*5&5&555&555555555&5&&55555&555555555", +"55555&555&55&55555555555&&t Xtrw%*.r9er.5&7+5&+=556&&%+71er1%%>eer1%*41ree,&4< =r9=&%&63+ o4.reer.%%&%*$=1e=551re9q*%er72%o +5Or7re%%+92=.7 64&6y.35>r<&o 24w e0*e+3* 7,$Or%5 o54=+%57+56t t5+2%$=rt555&&&55%%o ++++7=6$r+6%+r&&=+%, X&w2=&65&4*1=56X o61755o t5&w .%5*&%=+5$%22oo174t 1>6%&+=5%&55.o X4+=555* X4*$&%%1e%5rt62154512$X *%$ o4o 56%%&&%. t*4*5215%&124X 54* o%5=+%6 o55% o5 X*57+*%=+%5OeXoO 557+56%56%455%%o ++++7=5.y:5%, .%=+&$6X &%&6 otyt=<12.e&o ===7.6+=6&%&*$&6 o5%4 o& X%4=+%&7+3%* X&*+=$5*X *5 X$*=+&555555555555555555&555555555555&5&55", +"55&55555555555555555&5&5&55%=+5%5. :*60 .4=+4&1=%5%55&+7*$o %%r<56$*$11&56%6+=#5$+=%$*&%3=+%6. q63w .&&5*#=+%5*11%4*5$5%*< .$+=646r1*# o&+755%5 o4&&&4&5=19o6%21%4*125X 55: o*X *4*%545t t*&%*21%4*125X 5%% o36=+4& o4%t t$ X64e+3*7+555X .5%>4. .%.r=655&&&72%&5r+%6+r%%&45&7+55$o .45w5w&%> .6+r4&$ <&t X%+=4645 <&&&&554%,t:,=+;0-o+8*&6&5o %65%+=%%r+45+r5%=+%. .&.r756$*5%22461 o6175%X t%Orr&%rr<&5+7&&o 54%5%&o t&5X *45 o5o .&%w5556%% o5&$*5r+6&+r*42r25t rt45=24&5q6+7%5%6$6$& +65+e6% <5< +*4=1464 <&6t X&&=1&5 o%&=+%55&&555&5555&5&5555555555555&5555555", +"&555555&5&&5555555&555555%5%=+%&&%.reer.&5< 7e1=56645&+=5%o 5&52r7rO5%O 7e2%42r=e1=565%55< 7.&.r9er.4*%5&57+6%6&O =92%.y7r2$5tye<%1r7==r.+=%&551r=&&5556&r<6$6&1r=r1&$&err< o4o 5555&555.rr7y531y7r15&X &55 o%67+54 7rer.*51r92=+q0< 9Xw9+>00+ 888***o &&%5+755.reer.5%=+552y=91=&%&55&.r9r< o%>=r7r<5&. 15$2 w&%+7%*X 5&5565%er15X &5& o5%O =92&%665% X&5%6$.reer.&4O <6&r9&%5ter7r.6+7%635%&65 7rer.561re27+6%< 7.&1r=%%Or=r=w65 X557+*555&555555555555555&5555555&55555555", +"555&&5&5&&&5&5&&5555&5555565%&8355%6XX*5%&*tX%5$5$5*5%*56%%*5%5%tX>556#wot5*6#.X*4*5%%*&4&to%4*$oo54*5$*56&%*&%5*:Xt*%&qX.%6&&qo0%&..%;o64&&%55&..$%&%55tr4%6$*%tot54*%&Xt555545&55&555553oo6&65tot*$55&&%556%%&&65 oto88--0XX-0:-ww.o;:qq->:0:q;0-0---8**64&&4*%oo&5%&5%5%6.o5%&$&&%&%5wot6#&&35.o,%36$&5%64&55%%665564%64%%%%ot5&5%5655&5&qXt6#535&%5*%*$5645oo555&%%84$4%*%56%.X&6$56&55*$5&4o6to%%*#*..65&$55to$5*..456>X.64%&556&4&45&&&&55555&55555555555555555555555&5", +"555555&5555&55&5&55&55555%66564%&$*6555$%&3*5%&*6%%5$6#645%6*%5&5654%5&5&%$5%&*5%5%&%5&%&663*6&5%*&5565&&55*#%*4%$*$5%4*%6%&535%**4&636*55%5&&556%6%%&*41+5*%&4%54%&&%6&5&6%5564555&55&&*%54553%&65%&&5&$6&546*565* o8-;w:,:,,,q>www;w;;q;0;0-0w;:wq,w::;,>w>;0-8*8*5&6465%%&$6%5*36%46%5*%6565*%55*5%&5%$$*&$&556455%*564&5%55%56&*$54563%%*5%*%65%6&4**556&5&4&565&&*%&4$*5555&6%5%%%&&45%4&%%45$4*55%6&$*555558$55&*54&*3&&5%&5$64%*54*&%5&&%555555555555&55555555555&5555555&555", +"&555555555555555555555555%5&45*&$&54&5%656&&&*%44&%4*55%65644*$545$*%6&5%%6%&6$%5&565%4&%&&63&45*4%&%45%&%5&6&&%*5$845&$%5&%**$5*4%%%65%&5656%6455&*5%%&O:66&4&656&%4*%4%%%55%5&5555&555%6&&4&*&&3%*&4&&664&555**-0+.q:q0>0q;;qwqq-q:;>:::qq::>qw0>;;:;>:0ww:qqwq::0-886*$&5%&$65%65%&5%*%45$%6$*4%64%%5*55&%%&%%546454%3*%%5556%6$566%%&&%*3%8#&&45&%6%%&%546&*%&4%6%4*&*5%%&6&%#*46*&5%&55*$%5*%**45%6$4%646*45%56%$%&65$*5%%5646%6%4$*54*4%&&5&5&&5&555555&555555&5&555555555&555", +"5555&5&&5555555555555555%&6565#5666$65%&%$*4&5&556554&6&54&&&$&&*&548$$**4*&6%$*%4*#&55%*%4&*5654%*%655&*55%5636%6%%%5&&*555$5&5548&%*%&554%5&%*55&$6*$&3&5$*%$&6455%6&5&6&5&46$5&555&555566&54%5*5%%5*454*%888-0:;,;w,;w0;;>;0;;:,;::;;;q>0qw;q;w::w;:q;w0q00w:w,w>00-8**&*563%&%&5%5%5%&&*555&4&55565%#6%55*$*4*85%6&%6$*3&6%465&54%&555645&6&%%*&4&&5&%56*535&55*%6%$4&%4*454&%465%%%&%%%5%*5%%&%66*35853*3555%5$6&6&54%5%&&&%6&%5&&*55%&&5*$5&5555555555&&5555555555555555555555", +"5&55555555555&55555555555%5*$65655$*$5*%&*$55&%5&$%*5$%5%*$55&5%%6%64&&4%&%%$664&6%*5%5*55&5$%*%6&5&$&&%466&$5&46556*5%*456&&65%*5$6&%55%*&6&$&3%56&5&$&6%6455*4565%%645636$5*%&55555555%6$*%&564&%5*63&6*6--q,w>:,0;w0;;:;qw->:;w0qq:w;wqqwq;q::q0w;ww::qq:q:w0q:0:,:,>>--654*5545$*%%6&%6$55&%5&455646*46%&56%*%45%6%6564&%%%6%4564&5*5%&6&&$5*4&4&5%*656356&5%&&4&5&6585*$5%&5&4*64&&556%5&55&8%%B%%46&&%&5&&46%4%6%*5645464%*$%6$5&8$553*5555555&5&&55555&55555555&555555&5&5", +"555&555&5555555&55&55555&%&%X.&4%&5%5546*$*55$5&%655&%*%5%6555&&6%56$&55&%&566%56%%56*54&%&6&&6&%*%%*#55&%&56%5&4%6536%%564&546646&%&5%6&$&54%6566$&%5&&%3&&*55&%&46564&%**646&555&5555554555&&455*&$6**--00:,;:q>0:q00,q;>w0:q;>0w:w0:w;q-qw;>;wqq0>;:q::;;wqqqw00w->ww::0q--8&66%535&3%&554655%&*4&$*%&*%5%556&655&4&$%&$&*%5%56456%55&6454&5546$*%&63%6%6&%&%553*%%*%%6%%556%%5&$&%5&%*5455%5%$%*4565%*&5&%%&6&%&6%4455*5&5555646%%%$%*6%6&&&5555&&5&55&555555555&55555555555&", +"5&5&5555555555&55555555555wreeo5&%65%6$5555&4&5%564556%&6555&%*%&55*&&&&%56$*$5655%&4%66o 6%455%*3*$%&5%%*%&%555655%&%&655&55&455&%%&5%%5o 5*%%6%4*456&4&&%&55&&&%55%&&56%46&%%&555555555&&555%*6%466&8-0q:>;q0::q:;+9:0:q:;:qwq;q>q::::++++Xq;qq;q>0;,;qqq>0;w;;>:;:;;qq;>w:q88*5&565%&+7556%&5&4&6$*%&&36&6&&5%5%5556&6554&%*%55646&%5%4*5655&55%6%$&655&&5%6645&%$*3*&%5*4%%&%6%565&%&$&5%*%&&%&%&&55%65655&%6%6%%&&%66556455&4&&55%*5556&%5%&55555&5555555&55&5&555&555555555555", +"555&555555555555&555555565Oe5&%54654*55&55&4*4&5%5%&5%555*$&6$&555&%5&%5555&%%55&%6%%*%&o 555555&%55%6%5&5%456&5655&4*&$&46%5%64&4&65%*%5o %6&464*3&5%4&5&%%64*%%*%%6&%5&5$64&$5&4*$5%%6&%&4&&&$&*5&80:q:;w;:qqtoqw:+9:qqwq:qqq:;:;:q:;; 2+2 <;:qw0qw;;w:q;;:qot:0::wqqq:q;q:q:.X8*65*5%+=%55%%&5%48$%&5qo&5%t.55%645&6%554&63*5%*46&6%5555555555555&55555555555555555&5555555&555555555555&555555555&55555&55555&5555555555&5&5555&5555&555&55555555555555&55&5&5555555555&&55555&5", +"555&&555555555555555555555+=36%4wo.*$555*q.*%5%5&>o.5%*50o:%%*%56&45%&>o,#*5565o55:oo$66o 5555555*oX*$&&&Xt*5464to.44%$oo%%%&64&ot45&*%otX *%%>X.56%36&%&&oo*5&&65%o3&*5%&5&.X66%*#*tt&%:o;855$tXt8;w>Xot;:w:;:o ,0:+=,XX,-qw;XXww;0:qwq o:q2=w;;qo.:wwqtoXq;: o:;wqXo.q0,:>tX>+=;;***%6+75.X*45&&535&$&o 55&+=5*4&&.o0655&6%ot5%&5$&4&455555555&&55&5&55555555555555555&5555555&55&55555555555555&&5555&5555&&5555555555&555555&5555555555555555555&555555&5&555555&&5&55555555555&", +"555555555&555555&5555555&+ +8:17;:Xy9rOqq< 9eo:= ;>re9 -**6+919r9,4+=*%X %5 7o +$:=r=y<%&=1e= <6*$&6%4*5&55555555555555&5&5555&55555555555555555555555555&555555555555555&5&555555&555555555&5&5555555555555555555555&5555555&5&5555555555&55555555", +"5555&5&55&55&555555&5555%%+=54t o*%=15$ =:5635&&=1&45%t t5+2$Or%$*rtt t6+2*&7rt5&w&5> o4o 55555&+954%54r<%Xr5&1e:6r+56+r%5=r.*1=*$e+6%+ &%=+6&56&55&5r+64+r64=rt$*%%&6+ <5:rO&o 1%%t t%+256 <0:>,o t0wq:q;,;o q0;+ O;< ;>22qtrXw0;>qq o:OrXq;rO:orww91:;q:, o0,0twq19q: 9tq0+9>:0,q0-+ <*wrO&+7#6o 55X *%&+=%5617%6X t5=r.%1=%$6&55*$555555555555&&55&&5555555555555&55555555&5&555555555&555&5&55&555555555555555&5555555555555&5555&5555555555&&5&5&55&555555555555555555555555", +"55555555&5555555&&555555%6+7*&Oe&45 o*<25O9oXO $%=+%5%54.o o6X 5&5&&5< O*56. ooX X&r<%&%&. >5%q .&=1%%+7&t t%5o $*1yX545$655. :5%; .*=+&%%*%$%+=446+75o %*&OeXXO *-re.:qq. 2tq;,-::;o wq>+e0:o q;yOooe+qw:0qq r.qqX ooo o;2row:0; o:0>wto2=w: o::q+9;>q:w,q+=6&%+=$+=65o *%o 356+7*&5r<4%*eO5=1%5+7*&5565%%55555555555&&55555555555555555555555555555555555&555&&555555555&555555555555&555&555555&5555555&55555&555555555555&55555555&55555&5&&5555&55", +"555555&5&5555&555555&555%*+=%5+7%5&o %* X54565%6,1 9t*+r=77=%5214=<&+r7=7=6%=+4%*.rr7 o#o &5&&55%OrrX%X 77==.$ X555&o &%65 o%7+6&+=4X 6&%o 8%:1 et%&%&$o %*65 o47+4%5%6*&+7&&$+=%o 64%+r====0>.= 2q;:or O:0>q>wo ::;+9:qo wq e9=9O;,;wq: +9q:0:w:0+9***+=5+75$o $5o &%*+=%&5 X&&%7+%7+&5+=5%%%&&%*555555555555555555555&5555&555555&55555555555555555&555555555555555555&55555&555&5&555&&555555555&5555555&55555&&555555555555555555555&55555", +"5555&&555&5555555&555&55&%+=&5Oe5%% .5=+%%+7&o 655X %*5%,e2$56%*. :54w .*=+&&&%%5&+7&5521&X 655Or5*-q,qw:XrO0:0;O Xq:q;-o q;:+9:;o 00rO0qq>q->0:; o0OyX>. .:>0;,-0te2q0 o;,Or.>+=:w oq>0+9qqq:0;:+9w-8125+=5&< 65o 5&5+75%&r<56%eO&=+#*+7555*%*4555555&&55&55555555&5555555555555555555&555&55&555555&555&55555555&5&5555555&55555&55555&55&55555555555555555&555&5&&555555555555&55&555555&5", +"&55555555555&55&555&5555%&+7*4t o6$71%6 o&55%%6%>5412%>rO&5w%%&rr+45>rO5&:667+5%5 <%t o%o 555&55>%65+ew%6;*r+&5+r4%=+55+756yO6w7 %6w5%12555%%*e+5%+r657+4654&5%+rt%:r<%o %55>rOqwtw0t;:eOqtw;t X:q:q:o .q:+=;:o :>+rtq:tqqw;:: oq>2etw92q;qt0tw;120w O:0+ew;29:0 oq:>+rq::qq>0+r.qtr<&+96w9 55o t5%+r5551=45o t67+&%+=56X+54*%5555555&55&&55555&5&555555&5555555555555555555555555&55555555&555555&555&5555&55&55&55&555555&555555555555555555&5555555&555&55555555555&&&5", +"55555&&5&55&5555&555&55556+756545*Xre=r5%7+5%51r77=r.o %65%5&Or= <%*ter7r.*q=r=r.6.reer.&%=+55+7*4< =rO %&2eer.&64%5&.re9r.%&=+5546&&5+rr=r236o 448*ore9rw;r9ret0Xr=r2w;q:;>0er1;+9qqo :::2r9r+;:;::q oq>te2q.er=rXq2eerXqq1r9q.ree1 1: o>q;.yeO;;qqq+rr9r208trerO &%&er15tre<5w=e=r<557+5%+=$*+ %&%65555&555555555&555555&555555555&&555555555555&5&5555&5555555&&5555555555555555&55555555555&55555555555&555555555&5&5555555&&5555555&55&5&555", +"&55&5&55&555&55&555&&&55%5&*%5&%qo.64**46%*%6%55%.o;&%&%6o.6*%656%*4$%&X.5&&54$*&5..*;X55&64&%5%4tXt**365.o%%&&5.X,&4%*Xo54665%&%5%5*%tX,3&466.X:%%565%%5*XX6%555*%5*5$&%+7$ot66$655880;;oXqqwqoo;:,0toXq:q;;0w:wo.0:0;w::;:;:.otw0;q;wq:q:q:wq0w-Xo;q::Xot::qqXX0qtot-X.::wq;:qtot;w;qw..;o.;q-8,o>$&5&%$ot*&>X0*54.Xw65454*5&553*%%65&&555&555&55555555555555555&555555555555&55&5&555555&55555555&5555555555&55&555&55555&5&5&5555555&&&&5555555555&5&5&555555&555555555555&5&555", +"&55555&555555555555&5555555456%6&%665$46$63&*%%5&5&6%*#&%%64%&6%45556&4**$*%6&*#4&65&65%6%*&#*&%&*44$45%*358%54&*&#*4&5%$66%55&&&%65%%6&5*556%$&%*4&&5%645&5664&6#*45%4&&+=6&%$5&%%880,::w:;qq:w:>0;>0w0q;;w:>qwwq:q:>w;;q:q;;>q,-,qww0;;>;qqq>qw;:qw:,-;qwq;qw;;qq;wq:w;q0:wq;;:;>>;::;qq:::;w:q-8&6%4&6&%%5%5%8%%%%5%5*%&&%6%56456%$6%555555555&5555&55555&555555&555&5555555&5555&5555555555555555555555&555555555555555&5555&&555&555555555&55&&&5555555555&&55&555555555555&555", +"5555&555555555&5555&5555%6&5&3555*5$6%5%*65*465%4&4&4%&&5*46&%%&55355%5%5%%5$54&*4$5*3&64&%%6%55%%&%&&65%65%%5&5%584%*$&*$&54&%5*4$&%64%4*%4*5555%5$%656&456%554%55*%%&%5o<555*%6%8-;,q:;q0::>w0q;;:q:;:;w:0w:;w0:q;:;;::q;w;:0q;q;:-:;,:w>>>>0;;0>w:q0>>q0;>wqq>qqqqqq-:>;;;>:>q;;;w0::;>::q,::wq-85*&45&4*%4654&&5%&55&%$655*%56555&*%5555555555&5&&5555555555555&&55555555&55555&555&5555555&5&555555555555&5555&5555&&55555555555555&555555&5555&55555&5555555555&55555555555555", +"555&555&55555555555555&&635*%*%&4548*566$%*5%6%&*5655&%%63&5$6656$*54%5%4&*%&66%%&*%*536&%*%5&%%5*46$45%6$*%%5%5&&$&45%*45&&&&&436*$*&&&%*%545455566*%&%6%5*4*6&5&&45565%%6%5%%5**-w>q:q:,q;>00:qq>0:>q>:q0,0;w;q>;:qq>;;q;:,q0>0w:q:qw:wq:0qq>wq>;;q:qw0>;q;;;q0w;0q;>q:0:>:q:;qq>;0>:;:0q;:0;,:q,-6&64%453*%55&466%5*%546&$*4555%56%$65555&555555&55&5555555&555555555555&5555&55&5555555555555555&555555&55555555&555555555555&&55555555555555555555&55555&555&&55&&5555555&55&5&", +"555&&55&555&55&5555555553*5$55&%&653%545*&4%*%4645*45*4&&&6%&6%4&5%5$&&5*65%&%5&5$&$3*55&&&%%655%5&6*%&&4&4&5*4546%66%&%*$*53$*&5%4&%466&#&6*$*4%%5%$5*5%*53*35554$5*4$&5&%*%&&680,>;;wwq>q0:ww00q:::q;0qqw:0,0q:0::wqq::;;w;0>;>;q;>>0;0*888-0:,0;,0wq;>-w>q,q::q:,::qw>q,0;>q;;;:;w-wq:;:w:>0::0:w:86&55*6&54*5555&4*4&&5%546%&4664**%555&555&55&555555555&55555&5&55&55&5555555555&555555555555&&5555555555&555555&&55&55&55555&5555&5555555555&55&55555555&555555&555555&5555&55", +"555&5&55555555555&55&5555&5853&5%6555*%&555645&4*%&&54*%&&663&65*3*5655&&3&64*%6%&*65%&&5%%555%5*5&%%*4%%*5%*$*55&&3&&&45%&66%&%&&54*$555*63%&%%5&56*6$**4&5%554%*%&556%%&4%&5*80>:00,:;w0q:0ww>w:0w;q:>:w;q,0q>:0qwq:wq:wqwqww:qww;0,-8#%#@44--;>:0ww>w:>;00qqw>;;;;w;:;q0>:->qqw;wq>:0qw0qqq>;q>:wq;-5&5545&*$&&6456&%$*3&*&&%%%%$&6%55555555&5&55&5&55555&5555&55&5555555555&5555555&555&&55&&5555555&555&5&5555555555555&5&555&55&555&5&5555555555&555555&5555555555555555555555", +"5555555555555555555555&5&%5%&$6%&%55&%56&%5&%*$5645554%6&54*&5%6%6$56%5%%6555%%&6$55%&5%&%&&466%5555*3*&55&%%6%55&%*545*%&3655%64&*5%5&&5%%*5&&&55%5&$6%&46%56%&6%6554&5&5&548-qw;0,;;:q:;::>0qqq0>:qqq:0>:;:wq;;:q;:q;w:q0>;;w;:;q>:08$33#$###80wqw;;:;qq:q>:-:;:;>;;wqq;w0:w;qqq;q:;0:;wqqw:::0:qq;w;866%&5&4*53&65&$*5&&554655&&*4555&55555&5&5555&&555555555555555555555&555&5&&55555&&555555555555555&&555555555555&55&55&555555&55555555555&5&&5555&555555&&55555555&55&5&5555", +"5&555&555&5555&55555555555555&555&555&55&&55555555555&55555555&5555555555555555555555&55&&555555555555555&55555&55555555555555555555&55555&5555&555&5&5555&55555%5555555%65%6-;:qq::qqqqqq::qqqqqqqqqqq::::q:q:qq::qqqqq:::q::::;w;w:-6#@######&-q>;:wq::q:q::::q:qqqqqqqq:qqqq::qqqqq:qqqq:qq::qq::::::-6%5&55&55555555555&5555555555&5555&5&555&555&5555555555555&55555&55&5&55&5555555555555&&55555&5555555555555555555555555&55&555&&55&5555555555&5555555555555555&55555&555555", +"5&55555&&5555&5&55555&55555555&55555555555&55555555555&55&&5555&555555555&&555555&&555&5555555555555&555555555&55555555&5555&555555&5555555&55&55&&55555555&55555555&555&&5*-;q:qq:qqq::qq:qq::qqq::qqq:q:q:qqq:q::::::qqq:q:qqqq:qw:8%####33@#%8q>qqwqqq:q:q:q:qqq:qqq:qq:qq::qq::q:qq:qqq:::q::::qqq:q;-655&&%55&55555&&555555555555&555555&555555&55555555555&555&55555&5555555555&55555&&&5&5555&55555555555555555555555&5555&555555555555555&5555&5&555&55555555555&555555&5555", +"555&55555&55555555&555&&5&555&&5555555&5555555&55&55&55555555&55555555555555&55&5&55555555555&55555555555555&5&&555&5555555555555555&55555&55&5555555555555555555555555565*-;w:;q::q:q::qq:::qq:qqq:qqq::q:q:q:qqq:q:::qqq::qqq:qwq>q*3@########8qw:qq::q:q::qqqq:q:qqq::qqq:qq:q:::qq:qqqq::qqqqq:qq:q:>;-6555%&5555555555555555555&555555555&&55555555555555555555&5&5555555&55&555&55&&55555&5555555555&5555555555&&5&555555555555&&5555&5555&&555555&55555555555&5&55555555555&&", +"555555555&55555&55555&5555555555&555555555555555555555555555555555555555&&555555555555555555&555555555555555555555555555555555555555555555555&55555&&55555&555&5555555&55*8;q:qqq::::::qq::qq:q:q::qqqq:q:qqq:q:qq::q:q:q:::::q:qq:,q&#@#3##3#@#*;,w:qq:qqq:q::::q:qqqqq:q:::::qqqqq:qqqq:::q:q::qqqqqqq:w;-*%565555555&555555&5555555&555&55555&5555&5555555555555&555555&5555&5555555&&&555555&&&555555&55555555555555&55555555555555555555&5555555555&&55555&55&555555&5555555555", +"555&5555555555555&555555555555555555555555&5&5&55555555&&555555&555555&5&&5555555&&555&5&55555&5555&555555&555555&&555&5&5555555555&5555555555&555555555555&555555555%45&-;q:q:qq:qqq:q:qqqqq:qqq:qqqq::q:qq::qqq:qqqqqqq:qq:::qq:q,:&######$3##&;,w:qq:q:qqq::qqqqqq:qq:q:::qqq:::qqqqq:q:qq:q:qqq:q::q;qw;-*55555&&5555555&55555555555&&55555555555555&5555555&55555&&5&5555&5&55555&55555555&555&5555&5555555555555&5555555555555&55&&5&5555555555555&&55555555555555&55&55&&555&", +"5555555&5&5555555555555&5555555555&555555555555555555555&&5&5555555555&&5&55555555&555555&5555555555555555555555555555555555&5555&&5555555555555555555&&5555&55&555&5556-0w:qw:qq:qqqqqqqqqq:q::qq:q::qq:qq:qq:q:qq:q:qqqq:::q:qq:q,q6######3#@#&;,w;:q:qqq:q:qq:qqqq:q::qq:qqq::qqqqq:q:q::qqqq:::qq:qqq;qwq-*%5&5555&555&&555555555&5555&555555555555555555555&55555555&5&&5555555555555&&55&55555&5555555&5555&55&5&5555&5&55555&5555555&5555&&55&555&555555555555555555555555555", +"55555555555555&55555555&555&&5&&555&55555555555&55&&555555&555555555555&&55&55&555&555&555&555555&5555555555555555555&5555555555555555&555555555555555&5&555555555555&*8;qw:q:qq::qqqq:qq::q:qqqq::::q:qqqq::q::::qqqq::qqqqq:q::q:,;&#@####3#@#6;,:;q:qq:q:qqq:qqq:q:qq:q:qq::qqqqqq:qq:qq:q:qq::qq::q:qqq:w08&5555555555555&55555555555555555&55&5555555555&&555&555555555555555555555555&555555&5555555&555555555&5&&555555555&555555555555&555&555555555&&555&55555555555&55&555", +"5&55&55&5&55&555&55&&555&555&&5&555&5&555555555555555555&&5555555&555555&5&&&&&&55&&55&5555555&&55555&555&5&55555&&5555555555&555555&&555&5555555555&55&&55555556555&&8-:q::;;;wq::qqqqqq:qqq:::qq:qqqqq::q:::qq:qq:qqqq:qq:::q:::q>;6###$######&;,q;:qq:qqq:qqqqqqq:::qqqqqqqqq:::qqqqqqq::q:q::qqq::q:qw::qw0855555&5555555&5555555555555555&55&55555555&5555555&5555&55&55&5&555555&555&555&5&555&55&55&&&555555555555555555555555555&555&5555555555555&555555555&555555&&5555555", +"5&5&&55555555555555555555&5%5*54646%6&4&55&5555&55%*%%&%565*%5&55555&55555&555&555555555555&5&55%6%5&%55&&55&6%&55555&&5555&5555&55&5&5555555&5555555&&5&&&55555%&655*-qqq:;;q,0:::qqq:q:::qqqqq:qqqqqqq::q::q:qq0>:;q;::qq:qqqq:;w,;*###4###$#@&;,qqqqqqqq:qq:qq::q:qqqwqw:qw0::;::qq;:w;q>;:;q;q::::>;:;w;::>0*&&555&&555&5&5&555555&55&555%&%5555&&55%554&&&%5&5&5555555555555&&555&56$*5&56&55&55&555&&55555&$*&55&6555555555555555&&555&5555555&&55&555555&555555555555&5555555", +"&55&&&&55555&555&5&5555&&$&&&$46%&663%*%5555555558$&%54&%$&%&%*%5555555&5&&555555555555555555555&$55*5*4%&5%6&5555555555&5555555555555555555555555&555555&5555555555*-qwq00qw:0:qq:qq::q::q:qqq:q::qqqq::qq:q:qq>;0q>q;wqqq:qqq:;qw,q5@@@##3##@36;,qq:::qqqqqq::;;::::::w0;;:qq:q>q0q>>q;>q;::w0:w0q;0;:0;>:wq0w-*555555555555&5555&5555%%*%5%55555555&&656*53&&55&55&555&&5&&5&5&&555555*$5&6%4&5&5&555&55&55555*355&%455555555555&5555555555555&555555555&&555&5&&555555&555555555", +"55555&555&55555555555&55565&55*3&&5585&%55555&5&5$65*556&6*54&465&55555555555&555555&5&5&5555555%55%$53665%6$*3*555555555&555&5555555&55&55555555&5&555555555555%&5*-w>qq:,:w:0wq:::qq:qqqqqqq::qqqqqqqqqqqq:qq:0>w0q0,0qqq::qqq;>::q*##4####$@#&;,::qq:q:q:qqq:qq:w::qq0>w;:::qqqw>qq0qq0w0q>0q;w;;>ww:w::;qw;>:-*55%5&55555555&55555&5&6%&55465&5555554*%456645&555555&&&5555555555555%%*%&55&5555555&5555&555%%*%&55&555555555&&5&5&5&555555555555&&55555555555555555555555555555", +"5&555555555555555555&555*36%*46*&45%4*4*&&5555555*%*3%*%5356&&%%&55555555&5&5&555555&5555&55&5555*566&6$644*%5*4555555555555555555555&555555555555555&&55&&555555568qww;:0;0>;q;q:q::qq:qqq:qqqq:qq:qq::qqqq:::::q>;w:0:qqq:q:qq;w:>;&#@###$##3#&;,qqqq:::::q:qq:q;;;;;qq,-:;>0q:0>00w:q;w;wwqw;:qqq:qq;;;;>;q:q,08*5%55&55555&&5555&5555%*$6%5%5555&5555&5%5&55&555&5&5555&&&5555555555*&$55%4%55&555&555555&5565455%4%55&555&555555555555&&5555555&5555555555555&&555&5555&&5555&5", +"55&555&555555555&&5555554*%6655%&&&564%555555555%&4&&5%655*$55&655555&555555555555&5555&5&55555555%&55$*566&45&555555&55&5&5&55&5&555&555&55555&5555555555555&&55&80>>q;q:w:;0>;qqqqq:q:q:::qq::qqqqq:qqqqqq:qqqq:>0>0wwqq:q:qqq:;:,;5##$3#4$@#@&;,:qq:q:qqq::q::qqqqwwwqwqq>;;>w::0,0:q::;w0:;q>0q>q0qww>-:w;;q>:086555555555555&55555555%65%&&55&5&5555#55$6&%5&&&55555&555555&5555&5538$&%&65&5&5&55&55&55555384&%&&55555&&5555&555&5&555555&555555555&&55555555555&5555&5&555555", +"5555&5&55555555555555&5556$55%6&&%6$%56%55&555&&&&55&*$45*%55%%&5&55555555555&55&555&555555555&54&65%*%wXq5%&%$65555555555555555&5555555&55555&555555555555555555*-:>q;q;q0w0:w::q:q::qqq::qq:q::::::::q::qq::q:;w0>-w>;::::qqqqw;w>0*#@#43@3###6;,qqqqqqq:qq:q:;qq:qq;;>0w>-wwq:-::-:wqq;q0,qq:q;:qq>q00,;-ww;w:ww-*&55&5555&555&555555*%&%$6*4555555556&65*&4655&5555&5555555&555&55&&&$5&%56%5555&55555555&556$5&%5&%5&55555&555555555&55555555&555555&5&555555555555555555555555", +"&555555555555555&5&555556<<556%&<.5&6%55&&55555&%&+t%X &&+=65&&455555555555&55555&5555&555555555*7+65%*91456665555555&5555&555&5555555555555&555&5555&555&555&&5&8;wq:qq:q>0>>-:qq:qq:qq:qq:q::qq:qqqq::qqqqqq:q< wqwq*@#%@%###@36;,q:qqqqqqq::::,>>>w>>>qO+.w0qwO+q;,q>0:qqoO;wqqww0;q0>w->q;q;>qww;8*555&5555555555&5554*$&8$+755&55555$&455$*55555555555&5555&555&&5556 o5%55&555&&555&55555556 o&%55&&555555555555&5555555555555555555&5555&55&55555555&5555555&&", +"5&555&5555555555555&55&55Or4&55%rt%5&56555555555&$7.5X %5+76%555&&55555555555555&5555555555&5555%=+&%&<1*5&%%%65&555555555555555555555&5&5555555555&55555555555580>:;::q:.X:0:q:qqqqq:q::qqq::q:qqqqqq:q;:q::qq;o 88O10wqqqq:::::;:>q4#t.3#3##@@6;,:qqqq:qqq:qq:-8888-0;:9 1q>:t q;;q0:;qqO10>0;wqqw0>.X:;>q:;:w;q:0*5555555555555555554*%5$6+=5&5555555*4%&t.%55555555&55555&5555&5&555 o&555%55555555555&5&5&5 o5555%5&5555&&55555555&555555555&55&5&55555555555&555&&55555&55&55", +"55555&5555&5555&55555555&wr<&65Xe%55to555%55%%&&&&55%X 4%+=%&%*Xt&&456%65&&%4%*4%5&X%&5..&%56%to%=+6$&;ow55&%%&ot55..&6%&tX.4%65&&.q65%tt6&qow5%%&55o%55%&556%&*-,;Xot;w;+9:;:wq;owqq.o;:0::;;wqtoX;:q;:wtX>;;oto #$#58-wwqo.:;:q.oX:&@+7##$3#Xt60,qq:0w0wqq,q.t5###$%6--9rr>00Or :;;tooqq>w;:qqq;o.q:q+9;;q::o.0,0>,-..&&5&*..55%&%&455556555+=%%%to.5%&$*&4+75*365oX*56$%654*$5&55.ot55 oqXq6%6&wX,&46%6$%$*..% X&5&tX556&%55%&555555555555555&55&55&555555&5555555&55555&55555&55", +"555555555&555&5555555555%*12*4&1O6&2ree:5* X*%7+5% X6o 55+7&4.r7rO%&= 7%*545&=19=6;9er25%&1r=rr+5&w0qw>Or9r9t>; +e1>.r9r7 ##+76891e9 e1 0;Or=rew-+=::91e9 9t0*e+##+ ##+=#&=rX:19::t;:< &#+=#$3r<@Xr0w+9qqo 0wo 164####@##@4=+e1>.ro ;,tw:t o0+900=yXq1=0w+=>0qrO>or;w+ O:< 5%1240r.4*%$>r1556555+=5&;&%< 5%5&66+=548r+64+r*4=+55+75%e2$6556 e>%e+4t t3+2&5$5*$1765X X6 o-*t ,#3X 3#+=@571w;+9q::woO 5#+7$#. XXX o,+9qqo ::o 8###3###3@#37+Orq11o wq>0Xo o;+9wq91w0+9::+9-,X ooo o;+e;wo 4&rOooe+%55>9=*55&555+=55&%oO &56364+7&*. >&6> .*7+6%+=%. t*45$5 <5&=+&O9ooO 465&$*r<645 X&22oX2=*&4665&55&555&5555&5&555&55555555555&55555555555&555555555", +"555555&5555&55555&555555%6%Oe*1<%&=r=77164 o$4=+5% o5o 5$+75X ==7=.55>e15$5*4*%5=+#%* e===<*7+%*%7+%+y=77=557+&4+95%X 4%Ore9 64+=*#6o $5%+y7==754=+55&55&*. toew0 o,0:=+0+90>09+;,09r==91;qw;;+9w0:o ;q o5#X #4#X #3O=#@=+,;+=;qOree 8#O73$X =7==X,+9;:o w;< 443@#%##$@4#7+t .r.o q;Xrr9 ow+9:q=+0,+9;;+=:;o 99==Xw+9w;o 5& e777<*4&29q455&55&+75$ o q5%22$*&$6% o*%e+*4 o%o 5&+=*t t&64*5&79>555355&57+556r<44&5&7+&%67+5+=>qw9+::;22qwqw::q;>Oe;w:+=;:< ;;oy8##4@@3$#%@#7+#eee0o ;wr1>- oq+=qw9+00+=;>+=,>. .;q:w0+90:o 86e<4&6&46+r.*6556555+76ty<&X 5$%*4%+=65. w%6; .57+%%1=6t t6&3$4 X&47+5Oe&5%&%5%&55 X565 o5115&&&5&5*&5&55555555555555555&555555&55&55&55&&5555&&5555555555", +"&5&55&5555&55555&&55&5556$652r2&5&oy.5&>%* <5< +5& X6o 5%+7%4=25%5;51rq5464*5&3*=+%6&+r,*4w%Or;&< +#,yO%6q%*7+6&+=$&o 5X w5< 48+=3*4X %6%qrO65;6%7+%4*6%565Orrt>q29q;o .q+rq:;=+>;0< Xqqtw:;>;. o>;=2-8 X4@$rO#07 $#+7@#=+q,+=:o tqO *@+r##%72@#6t,+e>te qw< *$#@+X#4####7+#O <8o ,w <:. oq+9;,=+>:+=>:+r::;=2w;:t,+=0>< -5+rw#6w&< .&&%5&&&55+=4o :5< %6&%55+r5&%r+%5+r$5=16.r7%%72*%,55yo&%=+%qrO%5w&555*%22451 X6X .4%,4&&%%&55&5555555555555555555555555555555555&555&555&555&55", +"555555555555555555555555%*%6< <5*%%O =e26%1r927+&$ o$o 5&+=&5ter=r.4 7&456%&7+%6%%2r7rO*qere17+65Xye7y45=+55+755X 6%9re1re$+=&&6o &4%*ore=y4&=+5&%556%6, 1:;;t=r9rO::.reOw=+:q>qO 9e2;;:;qwOr=r9t*% X#$#< =rO 33+=@$=+ww+9w;ere1r9$,re<@t9r7rX,.rerO :0o 63## +$@#3##7+#0X0%o qq1r999rX+=q09+qw+9:0.reO>.er9rXq+=:qo 0*52r=rO%= 55&&55+75&9re1re%5%&&tr9<&.re9r.55< =91=56.re=r55 X%5=+&%ore7r%55&45.r9r< o55O =e2&6555&&5555&5&555&555555555555555555&55555555555&5&5555555", +"55555555555555&5&55555555&&&&5&5&%*%:ot%55&..&55&&&555555$65546.o&%5556%&55&5555&%5%&3*toq%5&%X.4&555%5o.645564&%5%*5%&%5ot5t.&55555555556&%X.4&555%56&555&-ww;:w;wXot:q;wtot;q:;::qwto.0qwq:qw;toX0&%#@3#$##tX03#$$###5-qw:;ww;:o.,..@@;X;###.X&;,:tot:q;:>w-5########3###3####38-:wXXwto;qqqqq::::qqqqtot0qqXo:qqq:qq;;,-5&to:&55555555&555555&%6ot4t.%&6664,Xw%&5Xo%564&to&555&%5oX65555555555&$o.&455&6$6wXt%5&6&$,Xt*$&%&%&555555&555&55555&&5555555555&5555555&5555&55&5555555", +"55555&&55555555555555555%&&4$6&3%*4*$%5&&&5%%566&5555&5&*4%5%*4*&%*%6%555&&55555%5646636*&&4&5&5&54&%6%&*4*%5%$*&4&45*%65%%*$&55&5&&555&&5&4*&&5%&5%&&5%55*-::;:0>;0>:q:q>-:qq:-:q>0:qw;>q;:qq;:ww-8%@3%$3##$#3#####@#%80>q0>w->>0:,q&###3$3#3##5;,0w;>qq:qww08%@################%600,;;;:qq;wqqqqqqq:qq;qw;:>qqq::qqqqq,-0*55%65555&555555555556&%5465&6&%$5536*$6%&%565%*6455&55$&3655&&&55&55&5&*3%*%55*%&&&%65%$&536&$&&%*5%555555555555&55&5&5555555&5555&555555555555555555555", +"55555555555555555555555&6*$6545*%&54*54&5%*&664&&5555555&55635*$36#&*%%5555&55&5&555%664%%6&%*&55%%6&3633*&3655&566555*35%&&*4%6555555555%&654%&6&&*$*#6568qwq::qq>;:w-:qq:;>:;wq;;q:w0>-:>0;>0,>-*%######4$##4######480w:,;0qw:qqw>0&#@3#@4#@##*0>ww:0>qwwqww-83#####3#3####3##@#4*0wwwq>q;>;;w:qqqq:qq>;;>q0q;q:q::::q-,0856555555555&55555555$*&4&5*5%%*65**55*355&*4&%5&&&&45$*5&65&&555&555&48%5*&%55%&&64*%4*&56*5466%55&655&555555555&5&5555555555&55555&&&555555555&55&55555", +"55555555&5&55&555&5&5&55%365%*%%6%*4&*$655$5&45555555555554664&6*65*4&5%5555555&6%%*54&&&&3584*%%5&$*56*&6%&6$55%%%%%655&&&5%663&55555555&46556%&$46%5*$5*-::;:q,;-;:;::w;:q-wq:;w;>0;,0>w:::;w:-85@@#@$#####34#####480,>;q:>q0q::;,w4#@#%##33@#5q,q:0:0:w:qw>:;85###$###########@3%6-,0q:;;;::qqq::qqqq->w;w::wqq::qqq:>:>085*%55&55&&555&&555&6%5*%4&5&%564345%&65#&%*&654564*6&%6&&5655555555*5$55$566&%&4384&%5643%566456%%&55555555555&55555&5&5555&5555&5555555555&55555555555", +"&555&&5555&5555555&&5&55666&5$&5536%%5*%55*4%*5&555&5555%&5%*5453%*5%6%&&&555555%*%5&%645655%*$66%*%5*%3545*%56%%*5&5%54%545%&5&&5555555&%&%3*&$&*5&%&64*8;>q;qq;:q:::,;0q>;>w:;;:::wwq:00:0;,q0843####43$##4@@4##$580:>q::;;w>::q0,0*##$####4@#*0,w0;>:q:qq:q:>08%3###############$%*0,,0,::;w;:q:qqq:qw0;0;>q;qq::q:qq->q>85%65555555555555&55&%4%%*%6%%%&*65%&%5*555%%$&&&$6463&%&&%555&555555&%&5*%6%56%*&55%%%6*65%46%&5%*%5555555555555555555&5555555555&55&55555555555&&55555", +"&555&5555&55555555&5&&55%%55555%5*5&*..&&4&5564&555&5&55&%*%%%5**64%*%%655555555%*%$55&65466#*65&%%*%4&*6544%6%&&&%.o%5*55*&&55%55555555%&%5855,o:5$6%368-ww;;q::0:wq;qqqq:;>-q>wq:-::0w>qq:ww;84@###$####%##%###368;>>qq;q:0:;qw0,w;&@#@$#%#@##*q>0:,0qq;;wq;:>:0-&3@@###3###3##4##@&8-q:00>->:q::qq:q:;wqw;0>;::qq:q:qqq:q-*&%5555&55555&5555&%*5&63%55*5454%&564$*5$**&555%*&566%%&*5555&5555%5%&&%45556$%&465*5%&$%&&&554%*455&&555555555555555555555555&5555555&55555555555&&5&", +"5&55555&555555&55555555&64*5&%o 555%>0;;::::>;;:w< 0-5####4$@#3#$##@@$%*-0w>:;qq;w>0>o ,:,;*$#34###3@#&0Oo>;:wqqqq:qqq:wq-*$#######3##@#33@#&-:w,>;>q;:q:qqqq:;::;q>;qqqqq:qq:q0>0q-+7555&&5&55&55&555546$4*656&%6*&55&46&%&35=+&6&%46XO%&5&$&&&555555%*555%*45556%&6&6&%&*55&4$4&&55%55555&55555&5555555555&5555&555555&&5&555&5555555555", +"5555&55&&55&55&555555&555&$555o 5%&w2.5555%5545555555555%6*$55&&&%5&%*4555555&&5&%555&65%%&&5&%6546%6545&655$6&%6. >%%5&4%565655&555&5556$*5&6<1555&%%66-:w;:wqq;>q:q;w:;q:qqqq:w;qqq:0:qqqo -5########3######t.80qw:qwqw::;qq0o ;:,:&@#$##333@#5w1O0q:;:q:;qww;w:q:08%#########333#$##5-:w0;:;w:::q::q:w;;:q;;wqqq:::qq:w::q-+=5555&&5555555555555656%%%6%5%56$55$54*&57+%4*55%<156%6&&&5555555&5%&$55%&4&56%45%&%&%564566555%&55&&5&5555&5555555&5555&5&&555&&555555555&&55&55&55&", +"&5555555&55555&55555&555%%&4otX 6%%%..655&&5to&%wX>&5&&oX,$66%%w.&&6&X&65oXq&%&5..5*4655:o:5555%6554ot3*55%6..654o &%&5%XX6%&&5%%ot$*5%&to.%46qoq5*3&&ot-,;qqwqq;>.ot;>0:.oqww0q:tot;w:q:o.o *##tX.#4###3..3##+=0:>w;::::0Xo;,0o ,0,;*###3##;X.#6;,:w0:tot:0qwqqqw>qq;8%X@#0X.3####$3#tXt;>qwtot::w-qXo.;q,.o.w::;:;.ow;:qqtot+=&&%qoq&&5%tXt555&$&54:o.&&%64&&%%5%55655=+5X.%$&%&555%ot%6%555..%*5$%555>Xo&55*%%tX>%%&5&:Xt%655&&%&*%&55&%55&5,o,4*4%&55%*5556555555&555555&5555555", +"&555&55&55&5&&55555555555*.yer= %*weer1%3oyq;;o OrerX->2reet0: Orey.qqXrer= 6$2r7r1#3+71ey1#o +;::wq+=2eret,o -,+=6@X ##< =9X*-9+;,Or9rX::=+ww+9>:91e7#< 79X43##3@1r7r8qwOr9rXw:Xrr9rw;1y=r1w0o Orre>;qO 9re=%4*4 o%*7+5554&671e=r245+763.r7rO$5+71ey1%%6363Or7re$&X r.5X 2&: e:6e+5,%4%e+$* 7;5%=rt&&>$*%e+59+;. .0+2ww=+;:+=:w=y.-*714#$####3# <@#8-. .>+20:r2w:;;Oyt>trOwo 2qt o:t oqt2=%t t%+264 <45%%&*&6t o%5724& o%$=+&*#8&47e.%. .5+756r<6Xr5&+ O%< $%%*4*:5&> o4o 14%2246 =q5Oy%%=+%6+7%o q22oo29;q <;w=+w. .>;o $##$XO #4+e#@X -;+9;>q:0,;+9:>0+90o :q+=%#X ##1rX$@*-9+:OeooO ;q9+;;+9w09+w0-2rX#@####@#r9t#$8OeooO ;X .0q:;21:0q12qoyt;q o:Orq-,+=*OeoXO %6eet%&%53&%O9*6%=r=9=1>; o,:9+qo ,0-X @40q+9;;;+9;o ;:+=&#X #4q1 9t6w=+q+r9=990:9+:>+=0>9+,,w,1 et##4#%#t7 2#4+y==9=wo :;>:;9+ww>+9qo q>w oq+=>,;+=6+r==7=6%t= 25%6655+7%5&X %& o4&=+6555%%=+*667+&+=5X =777.%+755X %4%6%6.rr= o5o %5%o %$ X*%& X57+&$+766123r.*+y====*44.r<%%%%*%45&5&5555555555&55555", +"555555&555555555&55555556o %6&o *5r<%*$65X 654 o%*=+527w$=+45 X&5&=+%552=w%7+41265, o%0:::;w:o ;;:Or022q;,;;: oq;=+wo :05X #t <3X 3#+=#&o ,0+9;q,00>w+9:,q22;o :;+9&#o ##3#0e2%q9+>Orq:,0:>=+:019;;9+:>>08>92#3#####3.rO4+9q0:+98e+%or<<7 o6wrO%5>4*%*&%72%&%w%+75%o 55X &*6r+&&+r$5=+&5+=6$+e>&%,;rO5%;*%=20w:tw;;:0o <;>=2wo Xw:t:; oq>9+q0rO8q7 3X 0#< @%+7%8o q>+r::0;>>0+r.:trOqo -:+e5-e #3w##12&:9+;trO:0tw0=1wXr9>;9+-;,t0812###3##0@&9O#wrO,-t>>=2q:t:Ort;trO:o 0ww o;X XqXr=8,rO5&0&5q55eO46455t o3*=164 <4< +&&5*$6=2,&o t4+75672%5%w&+=4*X $&*$%6 <5t o%o o64=14& +*$+r44=1*.r=66%rrO%%>rO%6w$;e25&%448$4655555555555&55&55555", +"55555555555&5555&5&55555&5< 7rO 54&2r7rO5X 5%% X56=+5< 7e1r<5 o55&=+55%< 7e2r<6<=2. X&%ore=r6%$655ter=y.6+=5%o 55o *54.reer.6%=+55+=5&>7r=r.5ore=r%*ter9rXq>;q:o =eret>;O 9e2q> owq=+::O =rO #49re1ye@+=60o q:.yeOqw;0>+rr9r2w:o :w.rerO #329er.*09+:;ore=y0:< 9e19qq=+:w07eer.@####3r=ee0##ore9r;;Xrr9r:,1r9r1;qo w;: o:;2r9e1=-&or97r5&r=re0*%64*4&$1y92=+%55%6%7er= <56+76$tee=r.3+=5$o 56$5&41r=77r.o =9req55 =eer.$*< 7e1=546Or&&55ore7r5o +5%&%55555555555&5&55555&&", +"&55555555555555555555555%*6to:$&55&6tow$555&555&4*5$56to5&ow65%5&656%555to&%X,$56%t ,5%&5X.465455%6$.X%6&55&555554&*$5&5Xo$&*%%%555&&555.Xw6%&5o.%%&*-Xoqw:;:q;o ;XX,:;:qto.q:q;::w;q:;;tX0#@#$#Xt#t.#4&-;wwqqqtotw;;>0+9wo.0qqqw0:,to-##3##.X-#&;,q:qq:oX,;wq.o::q::qq:qqwXot&3###$#3XX#@#36*oX;w;;qoo>;qw.o.0:q:qqqqq:qwqXo;w>0*55X.55&5Xo5%&%6%6%5,o.5556&..&55555555.:>o:&%5%5&5&5.X&5&555555555&555..&,X5o &..%5&% otX&6%65to$*56&&2O5%55&5X.&5&&5%55555&55555&555&5&5555555&55", +"5555&5555&555555555555&565%4*5&5$6%646&&5555&&555$&&&46&%%5$54&$%$&%6%*%%&5&54.1X<9=U&5%655&%556%%&5555&5555&4*&35*555%&56%&&55555555%5&5&5&&&5*&8;,-:q:qwq>o :w;-q>wq:q;w;:>>00>-q>0%$3##3##$####@%-qwqq;:w>:qwqw;>+90w;:>0w;qqw;6####3#33@#&;,q:qqqq,;0w;;>::qq:::q;>qq>;8%####$####3#@#50q,q;>;qq;:q;;::ww::q:q::q:q;0>;;,w5*6$6$&%&%&45%555*4&3&5%54*4*5655555555%*4&54&&6%%&%55&55555555555555&%#*&X $663*55 X4*%%*$4*$&$&$5wy:55*5%&%8#&6%%&55555&555&5555&555555&55555&", +"&5555555555&5&5555555&555%*6$6%5*%%*%$6%55&&55555*4&&%*45*%5*63*6665$64*&4&465>17=+:%*33%6&%&4*55*%**4&%55&55&556#*5&45&65&&455&555&&&%*&554&%&$*8;::;0:q:q:.+:q0wq;;0wq>0qw;qq:ww:w85@3#4###$@#@#5*-,q0q:;:;;wq;qq>oO,;;qq;wq,w>q6#@$$34#@##6;,q:q::;;>;q>0wqq:qqqq:;0,::,-*$####$#5#3###68q;:w;w;q::;qwqqq;qq:::qqqq0>::,-,:8564*&4%&%&65&5&%&5&63&&*55&5%55&55&555&56%6$54&5&5%&&&5&&55555555&5555%6&%56t+6%56*%%+t5$&%64&4&65**$.<6&4646%56&%5656555555555&555555555555555555", +"55&55555555555555&5555&5&&4$&5&&44*%5*%&&5&55555&4*$%&&6&%&$5554535&&6%%*%4&365$&445*%5*5&554&&56$%556&&&55555&5565&$5%5%&%46*$*55555555&4565%*3&$&*-:>:w>::0wq;0,;:>0wq,0>w0:w:q>0:q0-*#%@@3#$#@%###$8>q:>w;;>;:;;>:q0q:-:wqw:w0;q,-*@3@#3@3$@#&;,:qqqq:qq>w;qqq:q:qqq:>00:q::-5##$##4#$#$###8-,q;w;q:0;w;0:q;wqq:::qq::q0>0;;,;-*#&465*#*%455%55%5$5*4%$5%%5*%555555555$%5&6%6%5&5%64455555&5&55&55&55&%6%$%*%*5%%&&&6%%&46%%*&*463&4$%%*64*$&$4*%5&5%5555&5555555&555&5555&555&55", +"&5555555555555&555&555&5&6&&&$*%5*5%&5%6555555556446*%%%%55*44*&55*35&66%%*$&6%&%56&%&%56#6&5&%&&45*&&&$555&5555%$&%66&5%&4&55545555&55&56$55&56&%**-wq:q;0,q;>;:0::0>;0qw0q,0:q;qq;>,8&##$4#3###$#@%80,w:0::qwq::q;ww:qw>qqq:q;>:0,w&#@5#$##3@#&;,:::qq;:;q;;>;:qqqq:::;,::qw,-8#$#43#####3#%$-q,w:;>::;w>:;:>;q::qqqqqq:wq0ww:q-8*6&44%%&5&465%&466%5%6&6*&44*555&555556*#5*%5&6%46&&*5555&55&55&5555&554**&$&%%5655&4&%56%5&%&%%*&4*&6$%555%5*66&%%6&555555555555555555555&5555&5", +"5&555&5&5555555555555555*$5*54%&4&%*5%6&5&&555&5%**%$*56&%6%&*4%5*%&5%%&5*$6*44555%5%%6%%8%%&5554*6$%%4*555555556&6&45&&%665$56*5&555&5&4&%55%..%5*8q:w;;,qqq:0>qq:qq>>w::q:qq::;>w::;-##@3###$##@#3*-:wqqw:q,0:qwq0:q;;;q:q0;:w0q:>q54@##34$###6;,:::::;q:qq:w:q:qq::q::qq:::q>-64##3#$3####$@8wwq0wq0:>00wq;;;:::qq:qqw0;q::;q:0854%46*&%%54*4*&&%&$464&%45*%555555&556366%5&%%&5&*$%%555555555555&55555%535*%&&545*$654&5$&65%&&6#6555*%6%%&5%%3*6554555555555&&5&5&5555&5555555&", +"&55&&5&&5555&5555555&555%&&%&*5&655&%6&455555&5&55+7*54&5*&$*%*66+=&566%4655464*4%*4*$5&5%%&$&556%65%64%55&5555&4%465&57+5%5*%5%5555&55565%$*q;.+:qwwq;;Oow;;;wq;q;9+>-+t#3$@$######3*qw>q:>0oOwwq;w:;;w::;;w>q;q,0q,0*###$##$$##6;,:qq::wqqqqq;:qq::qqq::q:q:>w,q8###3$@##$#3@#6-q>q:;ww->w;;:q::q:qq:q:q>;ww::q,0-&&5*$3&&%*54&&4&&%665&%56%&6555&5555&565%4&5&*54%65&&5555555555555&55&4*36*3&456&&$*5*%5%*4555%55*555$5&%65$*5656%$5*55&5&555&55&55555&5555555555", +"&5&55555555555&&55&55555%556&$5&%5%564%&5555&5&55&+=%%6564$&55555+7&%5555&%5%&%%55&54*5%&:o&&$*5%%&55%&5555&5555&*%%6557+&55$5*%&5&55555%&6&q2.%65.=,w:qqq>;0>X9w;.X;::1O:q:>0>q:;=+08=.#@####@#3##&->>.X-:qO1:;;;qqwqqqq>:;q:w::0>>q&#@3#3##3@#6;,:::q:;:;:w;:q:qq:qqq:wq;w;;,qq-6####$#33#3#@$8;q:::;:q:qq:w:;q:qqq:qq::qq;w0::,855%&665%&%%*5%&%65%&%555%555%5555555555&%&%&%%566$4%%55555555555555555%55%5&%55555%5%%&&5&5*5&555%5555&*%%*$5%%%4&6&%555555555555&55&555&5555&5&5", +"555555&55555555&55555&55%5%tot%&55$*54&&55%,.%&%63+=3*%5ot*5%55&5+=5.o&%56%tot%%%5*%$55&&X 5&555.X>64*$6%..%%&4555&5tX&=+*&%wow65%%55&455o%65..%5&*;,wq:0XXq:0::::+9;;:;:::qXo.;;:9+;*3@###XX#3##-Xo0,q+=>0>:wqw;:oo>::qq::o.:qw0w;>q&#@####3#@#6;,:qqqq:qqqq::qqq:qqq:q:qqqqqq:>083#$3#########*->w:qwqqq:qqq:::q:q:qqq::qqq:;;w>0*55&5555555555&5&555&5555555&555&555555555555&5555555555&5555555&&&55555&555&55555555555555&55555555555&5555555555&555555555555&&555555&55&&5555&", +"555555555&555555&&&555&56*1r=r$&% o#*=+%5 +91%&5%8+=*4.y7y<**$&&4+=1ere>5&1r7y1**X %*& X6 75,7r=r<%%+=1er1*%*%66%1r=rr+$5Or7y.6%*$&5=1e7*q9er1%*o q>+92er1:>o wo y +q=+;wye= =+-6 X3tre7+3#Or7rewo +;+90>XreerX:091e9 <:0w:>,0&#@####$#@#&;,qqqqq:q:qqq::q:::q::q:qq::q:q>;8%############*-w:qqwq:qqqqqqqq:q::::::q:q:q;;w>0*5&5555555555555&555555555555555555555&555&55&555555555555&555&5&&5&555555&55555&555&55555555555555555&5555&55&555555&555555555555555555555555555", +"5555&555555555555&&5&5&&&# <%%6%5 X55=+6% 7>%&*$54+7%*r<*or5%6*4&+ <*:eO4< qwo :;+9qq09+q:t>,190w9+-5 X$+e33###-$5t o;+9::;+=q-r+w;+rq>9rX:19q:qq;,06#####3$#@#&;,qqqq:::q:q:::qqq:::qqqqqqqq::,:-*3#######33##5-:>qqqqqqqq:::q::q:q::q::q::::;:>0*555&55555&&555555&55555&55555555&5&55555555555555&5555&&55&55&55555555555555&&&5555&5555&555&555&555&555555555&5555555555555555555555&555555&555", +"555&5555&55555&&55555555%8ret&&%5 o&4=+$5 o4&54&56+7&. oXX o%4*%5+=5%%+7&21555126o $%& X%X *&%r<*%5eO*+e5%o 4&656411%45=+5OeooO %5556%7+&5%rOoXe+8o ww+e:;< :qo w:+9>::9+>0>to29:;9+83 X#< O#4$#$4.o o>+9q:q+9:X t;qt Xq91:0+9q;q:;,;*######3#@#&;,:q::qqq:qq:q:q::qq:qq:::q:::q>:084##$####3###48:w:qqq:qqqqqq:q::qq:qqqq::qqq;ww08&5555&5&55&5&5555555&555555555&55&55555&&&5555555555&5&555&555555&555&55555555555555&55555&5&555&55555&555555&55555555555555555555&5555555555555", +"5555555555555&5&5555&&555$t= 2%5$ o4%=+&4 X5&6%*4&+=4o 7===.56$&%+7&&*+=5=+&5&+=5X &&6 o6X 44& o$56=+5+755o &4&%557+*%*7+4+r777=*5*%%%7+$&5 e==7<6o w;+9q;o 0wo w0+9q;q=+;w1 9r=qq9+*# X4#OrrX#$.er9 o:+9;q:+9qo ;qq: o>9+q:+9qww;,,05######3#@#&;,qq:qqqqqqqq::qq:q:qq:qqqq:q:qq:q-5##$####3###380:w:q:qq:::q:qqqq:q:q:q::qqq:qq>;8*5&5&5&5555&555&55&55555555&&5555555&55555555555555555555555&5555&5&5555555555&55&55555555555&55&55&5&5&55555555555&5555555&55555555&555&555555&", +"55&555555&555&5555555555*55&.rO*6 o4*e+6* X644*$6%+=6t t%%%&*%5*6+=5%&11%215&&12&o &5q X%o 56$y<&5$eO*+=&5o %*%&%&=+%55=+6q+=:qo ;0o ;w+=q;q9+qOr.;+9:q9+8# X#%@%2r##r1-q oq+9ww;+9;X t:;t X0=+q;+9q;q:-,:6#@####$###&;,:q::::qq:qq:q:q::qqqqqqqqq::q;qw0*##3##3##3###*0::::qq:q:qqqqqq::q:q::qqq:qq::>;-*&%55555&5&5555555&55555555&555555555555&55&5555555&&5&5&55555&&555&5&&5555555&55&55555&55555555&5&555&5555555555555555&555555555555555&5555&555", +"&&555&555&5555&&55555555$6w55eO%6 <4< +5% o5*&&&5&+7%6726*4>66%&3+et6;y<*55&%%&=+34*+r:*4;-o >w+9:wo w,o q;+rw:q9+;+eqq29q:9+%@ X#033or#3 OO:,;5#@####$#@#&;,qq::qq:q:q::qq:::q::qq:qq:qqqq:wq83#######3###&-qwq:q:q::::q:qqq:q:qqq::qqqq:qwq-85%55&5555&5&555&5555&&55&5&5555&55&55&5555555&555&55555555555555555555555555&5&&5&5&5555555&55555555&5&5&5555&55555&555&5&5555555&5555555555555", +"555555555555&555555&5555&&r=ee;&41re1=+%5 X5$&%&5%+7%&ter=r.$&%&5+rr7r1&%*1r7r1%64err< X55er1$w7r7r<$*+=%*o 56&4&3,9r917+&6Xye=r5&55&%7+65462r7rO8o wq+9q;o q0< qq.reO;9+w.ree1 1>=+6# X#Or7 <##1r9=9rX.reOq+9;wXreerX>w9+:q+9;q=9q,;5######3#@#6;,:q:q:::qq::q:qqq:qqq:q:qq::::::,q84####$######5-;w:::qq:::q:q:q::qqq::q:q:qqqq:q-86%55555555555555&55555&5&&55555&55&5&555555&5555555&555555555555555555555555555555555&&55555&555&555&&555555555&55555555555555&5&5555555&555555", +"&55555&55&&555555555555&%&5oo5&%&4..&48%55555555555&5555.o&56465$tt5ot5&556tXt3&465ot546$65ot54&.o,5%&%&55555555&54&X.*5&46%5o.55555555&4&5*%tX>5-;w;qqq:q:qqqqq:q;totwq;w:tot>X.,085@#4##tXt###%.Xwtoqwtotq0w;:q:oo:0q>::q:qqq:q::,q6#@####3#@#6;,q:qq::qq:::qq:qqqqq:qqqqqqq::qqw;-6###########%8q,qqqqqqqqqq::q:qq::q:qqqqqq:q:q08%65555&55555555555555555555555555&55555&55&5&5555555&5555555555&55555&5555&555555555555&5555555&55&555&555555555555&5&&5&&5555555555555&5&55555", +"555&&55555555555&55&555&&%&%4&%555&55&%%555555&5555555&&5&5%&56%&%%6%66%5555%$%6&&%5$5&&&&%5$55&56$&$655555555556$*&&5$&&4*55&4&5555&555*6%%555%&0;w;:qqqqq::q:q-w;q:0>:q;;0w;qw:::8$#3@########*q0wqw::00q>0wqq;:;wqw:q:qqqqqq:::q,q&#@####3#@#6;,qq:qqqqqq:::q::q:q::::q:qqqqqq;w:-*###########48q,:::qq:qq::qq:q::qqqqqqqqqq::::0-5&&&55&5&&&55555555555&5555555&5&5555&55&555555555555&5555&55&5555&55&55&5&555&&55555555&5&55&555555555&55555&&&5555&55&555&555&5&55&5&55555555", +"555&&5555&5555555&55555555&&&5555*%&5465&5555&&555&5&&55*3*&%%%6%5&%*$%*&4&*&5&6%&6$8*46%&&48*4&63*&56%65&55555556%&%6&%55$4*%&*555555556#66$&&&50q:qqqqq:qqq:qqwqw>;:qqww;wqq0:q,w6#####3#3%#@38-wqw;;ww>>0>:;q;:0wqqw;:q:q:qq:qqq,;6#####33###&;,q:q:q:qq:::qq:q:q:::q::qqq:q::qwq0*######3####$*q,qq:q:qqqq:q:q:qqq:qq::qqqqq::q0-555&5&55555555555&555&555555&55555555555555555&5555555555&55555&&555555555555&555555&5&555&555555&55&&55555&&5555555555555555&555555555&5555555", +"55555555555&55555&5&555545&%%&5%5%%46&%$55555&555555555&%*$&&6$&6654%&545&43&546%54&44%&%5$6$4%6%*&$5%5555555555%&&4%%*5%*5*#4&4555555556%%5%5*%5;:::qqqq:q:q::q:q:-::;w;0;qw::::>0*4###3#$#@@#380;,q;0>0>0::0ww>;:00w0::qq::q:q::q,;&#@####$###6;,q::qqq:q:::qqqqqqq:q::qqq::qq:q:q08############*;,qqq:qqq:qqqq:::q::qqqqq:qq:qqq;-55555555555&555555555&55555555555555&5&5555555555555555555555&5555&5&55&&555555&&555555&555&&555&5&&555555&55555555555555555&5&55555555555&5&55", +"5555&55&&5555555555&55&&6$55&5$65&*%&&4*55555&555555&5556665%%664&%66&46%566%45%6484%6*46$84%**$%&%6&%&45555&555&%*66%6455%%**5555&55555$6%&65&55:>wq:;qq:qqqqqq;ww>;>:0:q>;0;,00,;&#####3##33##8:;>-:,;>;w,;qq:0w::w:::qqqqqqq:::q,;6#@####3#@#6;,qq:q:q:q:qqqq:qqqqq:qq:q:qq:q::::q8############&0,q::q:::::::qq:q::qqqqqqqqqqq::q055555555555555&555555&555555555&5&55555555555555555555&5555555555555555&5&5&555&555555555&5555&55&55555&55555555555555&55555555&55&555&&&&55555", +"&5&5&5555&&5555555555555%6%55%6%&$56%5*$55&5&555555555&544&&5564&45$*466*$$**555*$6$&54&64*4&5%6&44&%&&*555555&&%5%45538%5*%55$55555&5&5%5*5$&6$5>,q:w;:qqqq:qqqw:->;qqq;:;q>:0w:,0%@####$334@@48w:q>>-:qq:0;>q:>q0:00,0q:::q:q::::,;&####3#3###&;,:qq::qq:::qq:::::qqqq:qq:::q:qq:::-############50,qqq::qq:qq:qqq:::::::qq:qqq:qww-5555555&5&5&55555&&55555555555555555555555&5555555&555&555555555&55&55&5555555555555555&55&&555555&&55555&5555&&5555&555555555555555555555&5555", +"555555555555555&&5555555&%&55&%5%645&566&5&55&555&5&&55558$5&5&55*5%&6%4%*6%55%5%*&55556%6555&56566%5&$5555555556%%&&*5%*%%*%&%&&555555&*544*&%*5,,:qwqqq:::q:::0>>;w;w:w;;w0qwq;,-6####3#####3#->;q;q,q>0;>wqw0q:>;w;q:q::q:::q:q:,;6#@3###33@#&;,qqq:qqq:qqqqq::q:q::q:q:q::q:qqq:>-############%0,::::q:::::q:qq:q::q:q:qq::qq:w>055555555&55555555&55555555555&5555555555&555555555555555555555&&5555555555&555&5555555&55&5&5555555&55555&5555555555&5555&55555555&555555&5555&", +"5555555&5555555555555555555555&&&%&%%&45&&555555555555&5&555%4%5&%&6%%655%%5555&555555&%5555&5&%%&%56%&%5555&55555&%5$5%55%%545555555555$&55%%&4&,,qqw;q:q::::qqwq;q:wq;:;:::;w;q,0*@###$3######->qw;q;qwqqq0w;:qqq;:0w;:qqqq:qqqqq,;&#@###333##&;,qqq:q::qqqqqqq:qqqq::qqqqq::q:qqqw-############40,w:qqq:::qq::qq:q::qqqq:qqq:qq:w055&5555555&555555&&5555555&55&5555555555555&5&&&555&555555&555&5555555555555555555&55555555555555555555555555555555&5555555&55555555555&5555555", +"5&55555555&&5555555555555555&5555555&55555555&55&55&555555555555&55555&555555555555555555&&5&5&5555555555&&5555555&555555&555555&&555555555555555,,qq:;w:qqqq:qq:q:qq::qqqqqq:q::,0%######3#####->qqqwq:qqqqqqq:qq:qq:q:::::qqqqw;:,;&##########&;,qq::w:q:::qqq:q:qqq:qq:qq::qq;:qw,-############5-,;q:::q:qqqqq:qqq:::q::qqqq:qqw>;6555555555&555&5&5&55&55555555555555555&5&5&55555555555555555&55555&5&5&55555&55555&&55555555555555555&555&55&5555555555555555555555&55555555&5", +"5555&555555&5555&55&555&5&55555&55555555555555&5555555555555555555555555555&555555555555&5555&5555555&5555555555555555555&55555555555555&5555555&,,:qq;w:qqqqq:q::::q:qqq:::q::q:,0%#3##########->qqqwqqqq:qqqqq::qqq::q:qqq:qqq:;:,q*3#####3$##*:,q::;:::q:q:qqqqqq::qqq:q::qqqqqqq,-###########@50,;:q:qqq::qqq::qq:qqq:qq:qqqqqw>0&55555&5555&5&&5&5555555555555&5555&555555555555&55555&55555&55555555555&&&5&555555555&5555&&55555555555&55555555&5&&555555555&5&&555555555&&5&", +"5555&555555&5555555555555&555555555&555555555555555555555555555555555555&5555555&5555&5&55&555555&&&5555555&5555&&55555555555555555555555555555&5,,::qqq:q:qq:q::q:::q:q:::qqqq:w,0%####3#######->::;:q::::::qqq::qqq:qqqqqqq::qq;w,q84########$8w,q:qq:qq::::qq:q::q:qqq:qqqq:qq:q:,-###########@%-,:qq::qqq:qq::qqq:q::qq::q:::::>05%5555555555555&5555555&55555&55555555555555&5555555555&5555555555&5&555555555555&55555555555555555&55&555&5555555&55&55&5&55&55&55555555&55555", +"55&5555555555555&55555555555&5555555&5555&55&55&55555555555555555&5&555555555555&5555555&&555&555555&5555555555555555555555555555&555555555555&55,,::qq:q:qqqq:q:qq:qqq:qq::q:qq:,05############->q:;qq:qqq::::qqq::qqqqqqqq:::q::wwq-5#@#3##@#5-:>:qqqw::qqqqqqqqq:qqqq::q::q:q:qqq>-###3###3####5-,:q:q:qq:qqqq:qq:qqqqqq::qqqq:ww0&5&5&555555&555555555555&55&555555555555&55&&&55&555555555555&55555555555555555&55&555&5555&55&&55555555555555&5555555555555555555555&55&555&&5", +"5555555555555555&55555555555&5555&&555555555&5555555&55&&&&555555555&&555&5555555&55555555555555555&555555&55555&5555&&55&55555&555555&5555555&55>>>:q::::q:q:qq::q:q:::q:qqqq:q:,05############8w:q;:qq:qq:qqqq::::::::q:qqq:qqq:q::084######480:w:q::q:qqqqq::qqqq:qq:qqq::::::qqqw8############50,:::q::q::::::q:::qqqqqqqq:q:q:w-&555555555555555555555&55555&&5555555555&5&5555&5555&&555&5555&&5555&55555555&55555555555555&555555555&55555555&5&55&&555&55555555555555&555555", +"5555555555&&5&55555555&5&5555&555555&&5555&5&5&5&55555555&55&&5&5555555555&55&55555555555555555555555555555&555&5&&5&&55555555&555555555555555555w>>::q::::qqq:qq:qqq::qqqqq:qqq:,06#######3####8q:w:qqq::qqqqqqqq:qqqqq:::q:qq:::qw>w-8%$##4&8-ww::q:q;qq::qq:q:::q:q:qqqq::q:qq:q::8############&0,:qqqq:qq:qq:::q:q:::qqqq:q::q::-555&5&555555555555555&&5&55&555&555&555&&555555555555555555&555555&55&5555&&&555555555555&55555&&5555555&5555555&5&5555555555&5&555555&&5555555", +"555555555555&5&555&555&55555&55555&55555555&&&555555555&5555555555&555555555555&55&55555555&5555&5&&5555555555555&5&555&5555555555&555&5&55&55555q:>qq:;qqqq:qqq:::::q:q:qqqqqq::,q*$###3#######8q:w::qqqq:qqqq::q:qqqqqqqqqqqqq:q:::>q0-8**8-0q>wq:q:q;qqq:qq::qq:qqqq:qq:q::qqq;w:;8############*0,q::q::qqq:qq::qq:q:qqqqqqqqq:w:-55555555555555555555555555&555&5&5555555&5555555555555555555&5&5555555&55555&555555555555&55&55&55555555555&555&555555555&5555&5555555555555555", +"555555555555&555555&5&555&5&5555&5&&&555555&&5&555&555555&5555&555555555555&55&555&55555555&&&5555555&&5555555&&&555&5&555555555555555555555&555&::>q:q;::::::q::qq:q:qq:qq:q::::,;*$##3########*;qw:qq::q:q::qq::qq:qq::q:qqqq:qqqq:::wq:w;;:w>>q;:q:q:q:q:qq:qq::qq::q:qqq::::q;w:08###########3*q,;q:qqqqqq::qqqq:qq:qqq:q:qqqqq;-555&55555&555555555&5555555555555555555555&&55555&5555555555555555555555&555555555555&55&55555555555&&55555&55555555&555555555555555555&5555&55", +"555&55&&5&55&5555555555&5&&64%5%&%6%5&5555%5546%5&&&%6%66&3&5&$&55&65%*%%5&5%55&5&5%5&555556%$6%&6$%65%&%&&4&%%646645&4&6%&&55*$5555%554%&&%5&5%5->>;::;;wwq;>0;;>q;qq,0w:qq;:w;;,08%#####3###@$6-0>q;:;w0wwq;>qq>qw;:0>w0w:0q:qq;w::qw:w,:,,w:q::0>;::q>q;qq:;qqww;q:::qqq:>q0wq>q;-*###@4##3##@4*w>:w;;;,:;:q;;:>0:wq:qww:w0w;:::;8555645*$&45%*5&&5%6556%5&$&%6%5&%5&4645%&554556%*%&6%%&&&6%554&5%*%5556&%&5&5%&%6&%55555&55&5555555&5555&55555555&5&5555555&55&555555&55555&555", +"55555555&555555&555555&5&5%5566665455%55&55&*&3*45&53%*55566%%*%&5&4*545*4*%654%%4%555%54&*#6&$6%%*6$5*&5%56%6&466556365&6%5544*6&%*%&$65%6%54&*&q0;w;:w:::;:;:wqw;q:::q:0:qw;q:w,q833@4#$######*-;,w;qw;w0q0>:;;:0qqq>qw:q:::wq;,;q;;>;w>q0;0w:q;>qq;:00,:q>q::qw0:w::ww:>0w0qw;;,q8&#@#$###3###**:,;:q>:;q;q;:qq;qw0q;w:-wwq;>w0w-86$*5%&4&&**%&$5*%%54&%5566%66*4*%&%%&6%5%556%5%*4&5&5*5$*$555&56&45485$*&66%&*5644&55&55555&55555&55555&5555&&55&5&5&55555555&555&55555&5&55555", +"555555555555555&55555555%$&5&&3$&36*%&54%%5%35*5&645&*5$%635&4%6&%&&55&45$$*455*&&464*5&5%$**%&%5&45&4$5%%%*63&*54&64*%55%6%&5&46#64%*%55%4*66$4%-qwqq;qq:0,0q>0:0,qw;ww;wqw::;:;ww8%##@####3##3$80>;w>0::w;,;0:w0ww;::;;q>wq0>0:qq;,0;w0wqqw,0>:qw;0w0,,0>w0qqq;:>q;>;;:0;q0:>qw:>q-5#3#3##3####4-0;:ww0q:;;:q:;w;;:w:;;ww;:w0;w>:085*43565%5#&*5%&66&5*%%*5$5555&43&6%554&$*%5%6*$4*55*#$5&%&66$5%5*&%65%%55%455$5$65%555555&5555&&55555&555555555555&555555555&&555555555&5555555", +"5555&5&55&5555555555555548&%%%&&%&7&&55&&*4&%46635%$6555&%5&&%5%%%6%&5*%$&54564%655&$&55456%6&%5&&&56*%*%466%656%*46%56&&4*#*$*%6&%%5%&6%6%6&*8;0,:>0qw>0>q:q;>0;::0q>:0>:q:;ww006@####$#####3-w>,;;wq;:>0q,;qw:0q0qq::;;q>->qqw0wq>qww:;:0qq0wqq,w:;0wq:0>qq:w0qw0:,;,;w>:0q:>,0*3#####3#$3##*8,,,-:qqq>wq0>w0w:q0;,w0w;w0>w-,q-85$6*5%&%584$55&$56&44*5%*%%&&*&&645&5&55&4&4&%6*#5%4*6&%655%65554&%&3*5*%4*&$&5%6%&&5&5555555555555555555&5&55555&5&5555&55555555555&5555555555", +"555&5&55555&55555555555&&4:1=1<%5-qq>;wqq:;:;q>;0;qq:>,8*#@4#@%#33$##50w>>;:wwqw;:;q>0;w>q:w0q,qw:>q;q:>;:w0::;;:>:;,;;w0;;:wq0www0>:q:q:>:0;0>;;q:>;w>q*#344@##X<###6Oo;;:;>qq;09+w:>;:q;w00>w;q;w0,,;884*5&q1=2<55::;;:;:0:,::qqq:0:,0;wqq,:>;q;wq843.t3#@%####6-:w0::0qww;:w:qw0qw;0::q0:q0,;,0w;qq;w:;>q;0towq>q;q;w:qq;>0:qX.>:q0;;:;::::w0q,q-&#@#####+=###8=+w>w;q:::,=+;;otw::0qqqqq>wqwqq:8846%%e2o<+551<53*5#*4&46&35664&& o64*%58&3&%54664653%&4&*455&5%*#55 o4.7655554*4564$55555555555555555&55&555555555555555&555&5&555555555555&55&5", +"555&555555555&5555555555*X &546$5453*%:o:%%5&5%%&&%Xt&&..%5%5&44&464*,o.$*&%tot55&%to&&&%*5>X;%5%%8$&=+5% oqXw%554&w.*%6..4%*54%..5%*$&6&t .&%$%4880.o.:;>;:w.o;qtot,;0w:to.:0;w::,w8%@7+##$@;Xq@38;q,oq>>0:q:q.o:;qqq.oqq:wqw;:0>;w>w;wq.o.w0o q:;qqootqqw:0..q9+0:0,tot;q0;q0o.,-83##3#5#3O7$@%-=+>;q.oXw;-9+0>y<;0;,tot:q;;;qo.08*5%&o %%5&%6&46&%>oq*456%6&%6..$ o55%oX:5&5%5*6554&&6$*4&$*65%5*..& X*54566&..$&&55*55&&555&555555&&555555&555&5&5555555&55555555555555555555555", +"&555555555555555&55555555t <&5%6&=+5&q o>>9+3+ X@o Orre:;w2reet:; oqq9+;qq;:q1r9rqw 9qX 9er.qo OeO+ o>Oy=rX:q=1e= <-8##3###3#+=##%09+:w2r=r1q>=+:= y :qOr=rXqw91e9 <*&565t <5&&%67+45Or=r.646%&%wer9= X*. 7ert%+ 467+55+=555%%&>9re7 o%X 45:eer25&*6$555&5555&5555555&5555555555&55555555555555555555555&5&555555", +"55&55555&555555555555555&$< 1:%65=+%t t5+2&&5$&5=r.%1 <&< %%+=3*o 6&=1*$&4* <*6&5%e+5555&$=+&& e>%9+54 =w%5125wy.5+ <&o %&5&56=+656%%&*q oqq9+:w:;:: <;;:0o w;qt::qe+:o 1;wq=+0>. .w+2wq=rX:19-%#@#####3+r++++r+qwtq;< 0:=+qw o,0. .0+2;:=rXw1=8%&%%%O 1:5&&7+%t t4+2&&5&$6176%o o%w&5%e+$*5&:r1&6=+6%+7&%5&%&17&5X o&o &521%qr.%&&55&5&55&&55&&&5555&55555555&&55555555555555555555555&55555555", +"&&555555&555555555&&&555&5$X=r<55=+5O9ooO &%56&%7+55+=55X 65+7*$o 5#1rX*%%4ret%&621XX2=%5 <%*7+&&4&%&=+&5 <%67+&& o&56rOXoe+4+e&5o %5%5547+&55*%&521,;>12:o wqw o::9+0: oq>; o> owq=+8$7+#$OeXXO @&7+w>::qw;o tw0 o;22;wqw;re.qq,o qw>;w.oe+wo q,0:=+>0Oe:oO :w9+00 ow>OeooO >q91>q+=&*%4*%&X=r<%%=+6O9XoO %%6%5%rO$&% X*55toe+4%&;e7*54=+5&+7*5456%rO$*4 o$o %%rOoo9+5%45&55555555555&555555555555555555&&5&55555555555&55555555555&5", +"5555555&55555555555555&5%**5*+r:$=+6+r7=77%%&5&57+56+7*%o %&+=%5o 5*w1 9t*%t7 24&=r=97164 X%*7+%4*%657+%% X%*7+%5 o6$& e77=O$+=56X 55&&%5214564&#*7+,,q+=qoy,>0 o:0=+;> o0:> o; o:,=+-47+##+r=7774@7+:q>w0qwo w-w o>=r==91w: oqq9+;;www;.= 2;-o :qqt9r=r+:o :>:;9+0:+r=999:>=+>>+=%###$334##+7#&8;=+:wOree :;=+:w o0q+r9999qq=+0q+=64*%$5&*4+yq&7+%+y=7776%6556 o&5% o3q=r=r+6%52e>$6&=+6%+7&&$546 X%$5 X6oy8$ e777<%6%655&55555&5555&5&55&555555&555&555555555555&555555&&555555555", +"5555555&555555&5555555&546%$55 X&=+$q12qo 0;> o:,9+:w o,0. .> o0:e+057+#3>;o ;w: o022;qq0q; oq:e+:,-:qwq:Xr+,o qqq29tq=+;o ::->=+::Or,0;>0w=+w,+=5@#4@##$##+7#%0:9+0. <:o :>9+q: o:0Or:00:0:9+q,+=65&4*&$3*4yo67+5*%w*+756X %&*45%>e2w%*wo4o wqq oq;=+q; +0q+r;: <;O +w8=13#-rO33q@#=+->,w0;:o ::0 owo X>wtq, <>O +qq:;0wtw:eOqo .q>91,te+;o :>0;92:>trOqwt;w9+w,+=##<<#$###4+748w,=+,o t;O :;=100 OwwtyO>0twq9+wq+=5*%&%tt&4o t%7+$>rO5%,%&656522461 o%=1%we+5< .%56%&715.r=&3&&4&223*1 X%o 4&+r:%5w5&%6555555555&5&555&55&55555555555&5&&555&555&55555&555&5&555555", +"5&5555555555555555&555&55tre=r<&49+$5ore7r6&*4%&7+&5+=%5o &4trerO 3&2eer.4*r7req56O 7e2&5 o$*=+%4&6%5=+55 o$*=+%6 X56$%2r=rO4+=%&o %$*%%65t= =7 16*1y=r1:;o ;>; oq;9+>0 9rerX:q1re2=+q-< 7.$Xre7r##7+8q>,:wwo 0:> o:;O =e2ww1ye2=+;:qwq;y=retq:er1:< =e2rOo :;>w< =Xwore=r,091,;+=@#7=##4#$3+7$-q,9+0,ere1rew=+:>1y=qqore9r0>=+w,+=*%5%5trr7r<5&=+*&or9=r5*3%6&.rer< o&< 7e1r<7 56< =91=3*%%54.reeO o&X *452r=rO6664555555&5&5555555555555&5&&55555555555555555555&5&55555555&55", +"555&55555555555555555&55$65.o;6%53&*%*%o.6%%45&5*4$*54655%*64>X:5%*4%.o:%*45oX5%$%6qot56&%5645$*64%5%%*%64564&$6&55%&&*$tX>&55%54*%%555&55&%toow$&5*.o.w;qqq;www;qw0>q: o.ow;>:;XXww>,0&tX####X.3$3##68,:>w0>::qq:q:;qto.,q0:XX:w;;w:0,qqoowq0,;o.0>.o0:otqq,;qq:.o::wqoXw;0q,0-*@$3#@3##3###4*-,::>q0:o.:.X-qw;;,XX:>0>oX>q::;,q-6&4%&665.oq6%4%4*65$o.$6%*565&:Xt&5$$*to$5X>6&5$%*%%6to%*$*%$&*&4>ot4&$&&64&&&toq35%3*555555555555&5555555&55555555555&55&55555&555&5&55555&555&&5", +"&5&555555&555555555&5&555555$&555&55&%*45$*5%6&5%6&4*&5%5&54&5&&5&65%5&&&%6%%6%&6&55%6%5%*55&6%%55&5%&45%6556&%%46%&6%%*5&%55&%&&$655&55%65%&5%&64%*8q,;:q;::qwqw0w:;qw o::;w;qqw;0>;>q-4#$3##@3#####$80,:;>0:q;;:q::>0q;0>w:;:q;wq::q::;wq;::;w:;q;>0>;w0>q0q::;>q;w0:q;0>>w:08####3$####3##$-w:,;0q:;::0;>qw:q:qq:w;;qw;q;:wq>>8864&%&%6$4&45555%%5%&&&&555&%66%65%56%%55&54%&%*45%&%%%&65%655544&%&64*3&65&&%556*54*%555&55&55555555&55&55555555555555&55555&&&&55&&555&555555555", +"55&5555&555555555&5555555665%56%64*5$5*&6%65%%&55%64*555&$5&%55%6&54&&%&555565&5%564*&$*5$*&55$&&$*5%*465&5%5655&&%65&%5&&&4%655456%655&5555%6%&5*&%8;,q:0w:;qqqq;:w:q;+.:::qw;:;0,qq>,-*##@##3#4@3##348qw,q:qq:0>qq:ww:q;q>;0wq::q;>;;qqw;w:;:;w;w:::0>w::0w>;qq>q0wqw;0qw,>;85##3##3$#$##@3*-q>>w:;q:;:>0>:q;qqwq;>;qq0>q0qqq,,8*%4*%&%5&&%&55&4*&%&%55%%556$&565%5&5555&6%46%%65%6%6%56$6&3*555%6%*545%%555&%564%665%&%6%&&6%555&5555&5555555&555&5555555&5555&55&555555555555555", +"55&5&5&5&5555&55&5555555$&&5*38%6&&5&&35464&&%55&665$$5%5&*5%6%&$%%%*4&5%%65&$&66*%%%4&4&6465&%55*$&5%&$%4%555%55&&36%%6%%%*&&556&455*$*&5%5&6%&454&80ww>:;0,;;:q:q0>::,q:w::w0>qq0:q;ww*5#####3#3#4@#%*0>:,qw;w>;;w;q;w:;;;0w,;0,-w:;,;q:qq:-;>0w:q:::0q::,;q-,w0q,:;:w>::::0*$##33$#@3#3#33*q,w;:wwqqw0:w-,qqq;;qw;:>ww;:w:;w,-84&*&5&64&%5%&5&%4&&456&&*6%$*%%4%555%5%6*#&&4&55&$5*%6*%*%565%63*$&5&6&&6%6%5&&%6&#&%555%6#&46&5555555&55&555555&5555555&&55555555&55&555&5&55&555", +"5555555555555555&5&&5555*&%6%&5%4$&%45*&5&6%&%*5&4%*555**3&%54%6*4&6*5%%64&*46&535*&&6564*554&&55555&&5666%64*5&4&6&554&556%4&$554&553*56455%%5&55*4*0:>:;wq0>:ww-w:;q0::0w;;qwq:;:w>q,q063######3###@3$*0>>q;w;;;,00w0:qww0,q;ww;w;w::qwq;:;>w;w>q:::qwqq>::q,-q:0w;;;q0>,>;83#3#3##$333##3&;q::>;;:;qqw:w>0wq::;q:qwq0:qwqq:>;-*4464%%%65%664448455&3&&%$46&4*&&%&$*5&5%$*646%5%656365554%56%55*5&%5%&4545&&45&45&6&&6%46&6&6%55555555&5555555&&5555555555555&555555&&555555555&&5", +"&55&55&5&55555&5&5555555%%&5$546&&&5&&&5%5&3844%4&&46&%%&*%65&5$38%44456%&54*&$%&*%%&%&%5455&6%556%5&46%644655&4&$6%4*5&*%&365565&5&4*4%5%55565%554&5-q>:qqw;::0qq>;0,>0ww;w>q:;q0>0;,qw;84#$#3##3###5@34-www,;,q>0q>qw0;;q;0w;:0w>0>q:q;w;:w;0q;;qw->;q:;:0ww0,;q,0,>0q>:,;*64#$##$$@#$@#$$-;,>q,;:>;w;;;;0wqw;;>>0q;:>w>0;w:>:86*%&%666356$5%*4%&*%%*5&*%&*5%%64%&55&4&&5%5&%6*555$64&5$&84%545&$%64%%*&*554&%4*%6#%&4**$664%555555&555&&555555&5555&55&555&5&555555555555&5555555", +"555555555555&555555555555&<++++X%>;*$##$#3$@3#@3@4$ o,w:0q;;wqq0>wq:>qqw0>;qw;:;q>;:0>qq>w0w:> o:qw:wq:0ow..w0;:>,,0-+7#######3$@#@#8-,w0;;:q;wq:>o q:q:;:;q:w:;;0:;>;w,0**+=5&%5546&tt6X**5%36%6557+5%*5%555*4&5&&665445$&555,272<%5>q;:>0w1e<<2:>0w>;qqqo >:;q;;:w;wq-3$@####44##3### o:,w,:0>;qq:w;q;;::qqq;q>:q>qq:w:qqq;qwqqq o;;q;q:;>90OO;:q>>q>8&+=##33#3.t#43#58q>w:::ww;ww;:o q0>;ww0>:0,q:w0q>0>,-84+=*%5&&5&5<<6754$&*5&%4&=+554&6%*5#*%55543&&6&645&$92o<+&$1<56*35%$&%*&%&6%565 o%<1%%&%*%4&64655&55&55555555&555&55&55555555555&555555555555555555", +"555555555555555555555555%5=+55644*3&456wo>454*.Xw45*$;oo44+7$..6555:Xo56&X &5+=6%5=+*#66to.4*5%tXt%65 o%55%to5665%**5%4Xt4$*5&5%45%Xt*646$&*5to$%%&&%wot0qwq>q; o:q0:w;:XX>qwo 0;::>q0qq>q;-%#@3Xt@###$..@ X8q,XX;qqw;q.<;>0w:0>:w.o:;0q:;;o.;>qq0XX0 oqw;:Xtq;qwqw:;w,,oo,#+=####$#7+@##5*q,wqoo0;:0q>o.o >qq0o.0q;>0qXt;,0:w:,Xw+7%64&5X*4565%6&5*$to.5%7+5&6555%to5&&%*5wo;%54&&5o *%%55&55&%4,o>&%55%&&36..5 X&*%&55&Xt6%%&5555555&555555555&&5&55555555&5&555555&5&555555&55555", +"555555555&55555&5&5&555&&&7+564&%7+45 Orert5&ee=2&541 7=+5+72er155Or=re5%oy5o ++ o52r7r1351r=r5%= 562r9ew%55%$*.r7rO55+76%=1e7 <557+4&< 7er+%$Or=rXq:q0::r1q;>0:teer2qqo q:2et:=+qq+98*=1e7 <#30er97 X*,eer2:0o Orreqqq;w;;O 9er+::Xr9rO;qtere9 o;+=29Xw o:w9+>,Oye=2#+7#0r2#+ X450w>XreerX>;Xrer= qqXr=rO>q+92=X;q:>:O =re=&5=1e=5+=5%o 55:=r=eo5=+5. <561r9ew%% Orert66&45t <655&%=+5&%%64 X5o 55+=&6&7+&%%>6%< %% <54*45 o55r+&t t&+2,->0q;Xr9X:::22qtrX;o 0OrXw09+wq+9:87r.#17##1=3#X X#22wtrX:o 2wt ow-qqq. o;tr+:wrOqorqw19:wo oq+ <:;w o;;9+:. O#+=#290%#7+##%8>>,r+qq+r:we+q;+ w;rO:orq:+ <;:0:wwt o4,2=5&7rt&5+765X 4&29w65557+,e25$Oe567O&& e>%e+554*55< 2q%*57+%t t%+2%*%&4%1756o o5+=5&r<&Xr%&$&5555&5555&55&555&5555555555555&555555555555555555&55", +"&&55555555&55555&55&555545==++O4&=+&* <65=+6t 2:54&21#8%$5+e%&o %%%6.X X5o 3*+75%%7+5*&%5oO 6&ret5%*5 o&621XX2=%5*4&. oXoyo$+75&71%%+=%&7+4Oe*%5=+%O9ooO ,,;q::q.2 1w:rOoo9+:o < <0;w9+ww+=,-=13#+=#%e<##$ X3rOooe+wo t0; ow;q::Oe;,:=+qX ooo owrO:0w o,+9;q:qyo>q9+,Or5####+7+rt3@37O#%8;;,X t0;t X. .w:o :Xyooo o;+9>:;:>;,Or5&*+7&6=+4&5+=%%o 55r<&64&&=+7e*$*22oX27%5 <%*7+5%*3%6&o7r<#5=+5OeooO &$65%*r<*%5 o5+7&. oXo o4555555&55555555555555&&55&&555555555555555555555&55555", +"55555&55&555&555555555556%=+3$&667+%4 o%5=+%6Xr O&%=+64**4+=45o &6.er= o5X *&+=55&7+&35w;9+q:+9,:9+##+=$@ X##3 X# e779O>o 0,>yo>>qwq+9>;0=+wo =999X0 <:q; o;+9>w;q o;,=+0+7$##$3+r 1###3=+3$-w,wo w>q; oo :-qo 0o 9===X:+90q:;;,q+=55%+74*7+&5%+=46o 36 X53*55=e <$65=r7771%% X4*7+%*55*%%4*+r,5=+*+r=7775*$%6% o&%5 o%+=6o 7=77.*5555555555&55&55555555555555555555&&55555555&5555&&555", +"5555555555555555&&&&555&&%7+&*63%7+&% o&&7+5&65q=+qrO>:0wqo Xr+;;q9+w:19:,=+6#+73# X$4# X#r<4&6;qo ,q0 o;;;w:Or;w>e+;. .0qwq: o:;w oq+90>;; o,>e+8.y.0>0;:+9q:q:q>:+7&&5+=567+%55+=&5< 65r<&*$4&7+2r:6%11&&&%65 o&%=+*$6448%6&5 o5=+&5+=5*X $& <5t X%o &4+r&5%=165o :5< *3,%&eO5& <%6X .%5,5$*$5&=255*:5+=5%7+5%+=4&=+*:r+X7e+5>yO64,0,q:0:o;0trO;+rt;>tqo qXrOw091;Xr=:>9+8%+=#$22#@1 X3+r0$#,8o >,, owwqqqty+o9r+ww92;w:tq22q:1 o:+9q:,: <:< +$0r<##-#+73qq:r+qq+rqqrO:t= qw92w;:tq+9qqw0:wq. .$.r76$=+%*5+96>9 &%+e;*5>%=+429;5o .&6q5% X54=+5%8%&tt5%o t47+5:rO%&>%*4*%%22$%1 o%+7$&=256$q&*65&&55555555555&555555&&55555555555555555555555&55555", +"555555555&5&55&5555555555&= 767+$& o&67+%.r7y156%1 7eO5+7$&o 541r=7=r.o %&tre<4< 7.5er91re%r7re:$61r=56O 7e2&&5&%&t9r=r.4+=3*=+65+=*%7+35.22<=+%%or9=r8:,ww;9r9r10q>2r9rOwo qqO O:< 9e1=,>=+:*+7@#.rer< X@$2r7rO%o q>, q>w1re2=O##qqwwXreerX0>O 9rO w-.er9rXw+=0>:;,,881r=91=457+45&trerO $%w=r=r.47+&qeeq%O 7e2&5 o$*=+%5$%&trr=r<%&=+&5oy9=r%%6$$*.rer< o%+=5%t9r=r.%4&5555&5555555&55&5555555555555555&5&5555555&555555&55", +"&5555&55555555555555555&%6456%656%$5&*#&5%6%4,X.5*4&5tot&*3%*$%&653..&>X%46&%&>X:55to%&5ot&t.*%XX$56&$..3%&qot5&56$*$**.X*5555%4%5%&65%5&$*%%%*%r<55&5X.58w:>;qq.otw>qq;.0,-:;;.oq:;00:,q0*6###;Xt#$##3#tX0##4580q,w,,,>:::q>0r<;;wqXo0qq:to.>qqww>,,,:-..#$#@##;X.##4#5#3@#&*.0w:oo:w,:;.ot;;q:q;Xo:w>:;w;:q,08&%.X&6%4&%5655$,X,%%*%5&.X:%*%5&6&4565;ot%%&%&64&4*&4&&45.Xw$&%5&5%%4o.*&%5&63%>ot&3%&545&4&.o&%8355555555555&555555555&5555&5555555&5&55555&5555555&55", +"5555555555555&55555&5555&%&64&%5%5654&&%55%**%5&6$&$&%%&5555%*5%%6&%6$&5&55*%5%5&%&5%*45%5%6%5&55&6%&&45&6554&%&%5*56$%5&%&6%5&6&%&5%555%%&&1%*$&645*-,w>qqq;>;;qqqw0:;;::;:q,;wqqqqq:q:ww,w0*$##@###$#$####3###$3*8-q:>w>>,20>:0wqqw:>:;,,w>>>0-88$3##@3####$########%80>,,qwq;;w;wwq;0:;w;;>:qq:0:qq0q;:w;:,w0&5&55%5&55*%&555%%55&%&&4%6%&55&5%5&5&&&$&5&%*&&&64%56%55%5%55&45%%&5565%5$&5%5*$&55*4*%5556%*446$*555555555555555555555555&5555&55555555555555555555&55", +"&5555555555555555&&5555556$6%6%%55%*%5&565$66&$56&5*$65%%*4*5555%&%*&$*5&%&6%&%5%6&46%66&$&&5$66%6%65465%6&5%6&55%56$&45&5555&5555555555%655O771t*3&%5%6668:,w:q:qqqqq:qq:::qq:qqqqq::q:qq::ww:w,w0853##3##3#3##3#####3#$58--0:w>+9=2.:>:wqqw:>w:>>>,,>q;0-*5$########33###3#####58-:,>wqqq:::qqq:qq:::q:q:qqqq:;qw:;qqqw,q8*5%555555555555&55&&&55555555555555&5555555&5555&5555555&&5555555&5555555&5555555555555&5555&55&555&5555555555555555555&55555555555555555555&5555555&555", +"5555&555&5&55555555555555&%%65$*%$&465%&4*$$4%64455&5%5&546%6%$&&%5#6&&%5%55466%5%8%5&5&%66%&5&4&%&4&5%65&$55%%4%*5%63*%55555555555555&5&%5%%*$&&3&&%65%55*0>w:ww:w:ww:w:www::w:ww:w:::wq:q:wwww:>w084#####3###$####3#####$5*8-0wq;,q>;:www::ww:>>:::q0-8*5$###########33###$###$*0:>>:q:wwwwwwwwwww::ww:::w:w::wwwww:w:,>-*&5%55&555555555&&55555&5555555555555&5555&55555555555555555555555555&555555555555&&55555555555&5555555555&&&55&&55555&&&&&5555&55555555555555555555555&5", +"555555&555&555&5&&555555%&4*53*548&*6%*3&%5*$%*5663&%&5%*5555665&%6*&%45*$*%645*&54&%&455*4%6&%5&%5&4%6%55&46&&66%&*4&*55555&555&55555&5&%$6%%5&$66%55&6%4&8;,,www:w::::w::w:ww:ww:wwwwwww:ww::wq>,w0*%######3##########@###345688---w>,,,,,,,>w;0--88*&3$####################348-w,>::ww:wwwwwwwww:w:w::ww:ww::>:::>w:w,;8&55%&5555&5555555&55555555555555&55&55555&555555&5555555555555&&&55555555555&555555&55&5555555&55555&555&&&55555&55555555&55&5555555555555555&&5555555555", +"555555&55&5&5555555555554*&%&6545645545*45*$*%5%54&465%5%5$645&%55#6%&*&%*455&54%566&*&6%*%*555%56&64&4%%%%85%$5%%&4555$55&5555555555555%*63*5&%6&45*%%&55&*->,ww::w:www:::w::w::::ww::wwwwww:wwww>,>085####3####################6%***-8------888**5%4####################$###580w,>wq:>w:ww:wwwwwwwwww:::ww:w:ww:ww:::ww-65555&5555555555555555555&555&55&55555555&5&55&555555555555555&5555555555555&&5555&5&55555555&5555555&&&555555&55555555555&&555&&5555&555&55555&555555555&", +"5555&5&&&5555555555555555&ww>,>0-53#######3#########3####%#@$@4$###3#$3######3#3####3########3########5-;w>w::ww:ww:ww:www:www:::::ww::ww:ww:::>,q855655555555&55&5555&&5555555555&5555555555&555555555555555555&5&5555555555555555555555555555555&5555555555&55&555555&5555555555555&&55555&55&5555555555555", +"5555&&5555&55555555555556%= X$%$ o&6%6%6&$*5%&$&4554%5&45wo%%46&56%454%5%5&.t$455%%*5t+++r=+++%6%%84&%54%6&6$o;5&5*4$4&%55555&55555&55555%5%$&6&6&554%*%&5%5*-w>:w:ww::ww:wwww:wwww:wwwwwwww:wwwwww:>>ww-*3###3############3##3###$#4#@$##@@############3#########3########3&-;>>>wqww:q::w:wwww::w::w:www::wwwww>>ww>>>-*566555&55&&555555555&&5555&555&5555555555&555&5555555555&55&555555555555555555555555&55555&5555555&&55555555&55555555&5&&55&5&55555555&55555555&555555&55&", +"555555555555555555&5555&$&7r965* X%55to%&&%%&%5%&%&6tot&%o &*&46oX>%%6*%tt%=+&&%%*&4*54%*7+*%&%%to.%&&5>X.356 X6%%4>ow6455&5555&55555555&%65*%3%444&&55%&555&80>w:ww:w:ww:::w:w:::ww:www:w:::ww:w:ww:w>,q-*%$###########3#########@3####################$######$#########$%*-:>www:w:>:qw::::www:www:::::ww::w:ww>>:w>w086565&555&&5&5555&&55555555555555&5&555555555555&55555555&5&55555&5555&5555555&5&5555555555&55&5555555555&55555&5&5555555&55&55&55&5&&55555555&&5555&55&555&", +"&&5555555555555555&55555&5=1rO&% X6&1eee;65 o54=+&&1y=r65 7%.y7ert&o Oe<+ X&555%&%6&4=+%6%52r7y1%5< 7eo%7 56>:w,q-*55&%%655555&5555555555555555555&55555555555555&555555&55555&5&5555555555555&55&55555555&5&5555555555555555555555&55&555&5&5&5555555&5&55&555555555555555555", +"555&5&5&55555555&555555&&%7+5%5e+&X 155%7+4555&6%6%6&&=+5&%&>5&< &5=1%65%% o%5t t&+25&&56455%5555555555555555555555555555%58-::>wwqw:w:w:wwww::w::::::wwwwwww:www:www>,,q-8&$#######33############3#3####################3#######@#358-:,,>www::w::www:::www:wwwwwww:w:wwwwwww::w>>0*5555&555&&5&5555555555555555&55&55555555555555555555555555555&55555&55555&555555555&55555&5555555555&5&&555&&555&555&555&55555&5555&555&&55&&55555&&55&555&&", +"55&&55555555&55&5555555555=+*925 X*21XX1=6% o$*7+5%ret%55o 6$636to9+5X 65*4=+%&woXooX*5%&=+645&45oO &&1yo4*&5 X54OeooO &%55%&55*5&55555&5555&555555&555&&5555%*8;w,w:w>:wwwwww:w:www:wwww::::::www:www:::>,,,q-64##3######3####3############3##########3##3##3##3####%*8w>,,wwqww:ww::wwwww::::::www::w:ww::w:ww::w>wq8&5555555555&5555555555555&&55&&&55&555555&55555555555555555555555555555555&&&555555555&5555555&555555555555555&555555555&555555555555555555&5&5555555&55&555&", +"55555&555555555555&55555457+3o . o%=r===14& X%&7+56t7 25*X 565>7r7r+4o 3*5%7+*$.=7===%46*=+56%&:w>:wwwwww::w:::ww:www:w:www::wwwww::ww>,,:08*%33#####3#####3####3###############3#######3####$%*8-q,,>wq::>www::www:w::wwww:wwww:w:w:wwwwww>qw>:-6%5555555&&55555555&5555&55&555555&5&5555&5555555&55&&55555555555555555555555&5555&5&55555555555&5555&5&5555555&55555555555&5&55&555555&55&555555555555555&555", +"555&&5555&5&5555555&5555*57+552= o%125%55*5 X*&9+&4%*.rO%X 64%27;5=+5o 6$5*7+4664&%%665%57+6%$t <#o &%65>e2&* X%&w:::w:w:www::w:wwww:www:::::w::w::w:ww:qq>,>w08*%3#####3###########################3########3%680:>,:w:qwwwww:w::ww:ww::w:wwww:ww:wwww:w:wwwww>w-*5555555555555&5555555555555555&55&&&555555555555&&55555&5555&555555555&55555555&5555555555555555555&55555555&&5&555555555&5&5&5555&5&5555555555555555555555&55", +"5&5&5&55555&555&5&5&5&554&7+&6wr o%X .%5:$& <3O +%*w66eO%o t%6716>9+&o 65*4=2$4%&*%6%$&*%=+&5*X w6< %$:&4126% O6%>rO%*q56<<*%%555&5555&55&55555&5555555555555555680>>wq::w:::w::wwwwwww:w:w:::wwwww:www:qw>www>>>::0-*%3#@#####33##3###########3##############$%*80w>>>>wwww>ww:::wwwwwwww::wwwww:w:w:wwww::w::www>08655&5555555555&5555555555&5555&&5555555&5555555555555555555555555555&&55&&55&55&55&555&555&&555&55555555555555&&55&55555555&555555555&5&55555555555&&55&5555555", +"555&&5&555&&555555555555&6=+%&$+ X6&O 7e2&*1re17+%&r7re:&5er1%< 7e2yw:w::w::::w:w:www:w:ww::w:ww::w:w:w:ww:>>wq,,,w:0-86%3##@@#####################@@@###$4%&88;q>,,>:w>w:w::::ww:wwwwwww:www:w:w:w:w::w:www:ww>>q-*555555555555&555555555555555&55&&5555555&555555555&5555555555555555555&55555555&5555555&5&&5555&55555555555&555555555&555555&55555555&55&&555555555555555&55555", +"55555&55555555555&&55&55&#&5%6&5555%6:Xt%&44..4*5%&4oo3*%%*Xt65to&3X>$&46%45tX465&%5*58$%%*&*%65Xt5t.6%.Xw&%&&..4&5%X.3*46&%&&5%55555555555555555555555555&5555&56*-q>>www::wwwww::ww:w:wwww:w:w:ww::w:w:wqqww:w>,>>>,>:0-8*5333$#####################3345*8-0:>,,,>>wwww:qwwww:w::::ww::wwwww::www:::ww::www:ww>q-*55&555&55555555&5555555&5&555&555&55555555555555&5&55555555555&5&&555&555555&5&555555&&55555555&555555&5&55555&555555555555555&55&5555555555555&55555555555555&5", +"&55555555&5&555&55555555%6555$%555&55&&%56&65%6%&%5*$&*4%*%&%55&%65&%5&5%&%5%&%64&*4%5%&&&5465556%5&&$656%%*$56$&%&55&55%&56%5%&&555&5&&555&&55&555555&5%55&&5554%580>,:w:wwwwww:w:ww:w:w:w::w:www::::w:::>wwwwwqqwww,,wwq;;-88865%$3$##########$3$%5**8--0q:w,,,>:w::w:ww:>www:wwww:w:::www::ww::ww:w::wwww:w:w>08&&55555555&555555555&555555555&&&555&5&5&&55555&5&&5&55555555&555555555&5555555555555555&5555&&555&55&55&&5&555555555555&55555&&555555&555555&555&55555555&55&555", +"555555&5555&555&5555&555&555555&555555555555555555&55&&&55&&&555555555555555&555555555555&55&5555&555555&&55555555555555555555555555555555&555555555555555555&5555%580w>>w::wqw>www::ww:ww:www::wwwwwww:wwww:w::www:ww::>>,,>:;0--888**&555&5&&6*888--00>,,,>>>::::wwwwwwww::wwwwww:www::w:w::w:w:w::ww:w:w:::>>0865555&55555&5555&5555&5555&&555555555555&55&55&555555&&55555555555&55555&5&5555555&55555&55555&5555555&5555555555&&&55&55&&&&55555555&&555555&5&&&555&555555&55555", +"&55&555555&5&&55555&&555&55&&5555555&5&5555555555&5555555555555555555555555555555&5&55555&5555555555555555555&5555&55555555&55555&5&555555555555555555&5555&&5555555*-;>>ww:>:w:ww:wwww::w::w:w:www:w::ww:wwwwwww:w:w:::,,,,,,w>ww::q::;000000;;qq:qw:>,>w,>>wwqw::w::w:www:w:w::ww:w::www::wwwwww:ww::w:>>:q>wq-*%%5555555&&5555555&555&5555555&555555555555555&55555555&55555555555555555&555&55&5&55555555&5&55555555555555&5555555555&&5555555555&5&&55555555&55555555555&55&555", +"&5555&555&555555555&55&55555555&5555&5&5&5&5555555555555555555555555555&5555&55555&55555&5555555555555555555555555&555&555&5555&5555&5555&5&&5555555555&55&5555545&55*-q>www:>>q:::w:www:ww:w:wwwww:::www::wwwwww:www:wwwwww:>>>,,,,,,,,,,,,,,,,,,,,,,,,w>>:::w::www::ww::::ww:::w:wwww:wwwwwww:wwww:w:::>>qw>;-65%5&55&55555555&55&&55&5&555555&&55&5&5555555555555555&&55&5&5&5555&55555555555555&5555555&&555&5555555555&5555&&5&55555555555&55&&&&555555555&&55555&&55555555&5&5", +"5&55&&55555555&55555&55555&5555555555555&555&55&&55555555&&55&5555555555555555&55&5&5&5555555555555&55&&55555555&55555555555555&55555&5&5&5555555&&5&&55555&55555&55%58-:>>q::>:w:ww:ww:::w:w:w:ww:ww::ww:wwwwwww:w:w:w::wq:w::wwwwwwww>w::w:::w>>>www:www:ww:wwwww:::ww:::wwwww:ww:wwwwwww:ww:ww:ww:w:ww::w>>-*&&556555&55&555&555&5&555&555555555555555555555555&&5555&55&5&5555555555555555555555555&55555555555555&55&55&5555&5&55555&5555&55555&55555&555555&55555555555555&&55", +"555&555&55555555555555&555&55555&5&55555&55555&5555555&&&5555&555&5555555555555555555555&55555555555555&5&555555555&555555&555555&&555&555555555555&5&5555555&55555554&80:,>w:w>ww::w:ww::::w:w::w:wwww:ww:wwwww:www:w:w>w:ww:ww:ww::www>>>w>>:w:w::::www:ww:ww:ww:www::www:ww::w::::w::::wwwww:wwwwwww::::ww-856&&&55555&555&&55555&55555555555555&55&5&&5555&55&555555555&55&5&55&55555&555&5555555555555&55555555&5&5555555555&5555555555&555555555&&5&555&555&5&5&&&555555555&&5", +"5555&55&555&55&55555555555555555555555555555555555555555555555&555555555555&5555555555555&55555555555555&55555&55&&&5555555555555555555&55555555555555555555555&5555555&8-w,>:wwww:w::www:wwwwwww:wwwwwww:www::w:www:ww:wqww:w:w:::w:ww::q:qq::qw:wwww:w:::w:w:wwww:ww::ww:w:w:w::w::ww:w::wwwwww:www:w:qw>w0*5&555&5&5&5555&5555&5&5555555555555555&5555555&5555&55&55&55&55555555&5&5&5555&555555555&55555&5&&55555&&5&555&5555555555&5&5555&5&5555&55555555&555&55&55&&555&555&5&", +"55555&555555555555555555555555555555555&5555555555555555&5555555&555555555555&5555&5&5555555555555555&55&555555555555&&&5555555555555555555555555&555&5555&55555555555&5680w>w::w:www:ww:ww::w:wwwww:www::::w::::w:www:wwwwww>>wwwww:wwww:wwwww:ww::wwwww:w:w::wwwwwwwwww::w:::www::::::::wwwwwww:ww:ww::w:-8&56%5&55&&5555555&555555&555555&55&&&&55555&55&&&555&5555555&5555555555&55&5555&555&5&&55&55555&5&55&5555555555&5&5555555&555&&55&5&555555&555&5&555555555555&5555555&5", +"555555&5555555555&555555555&55555555555&55555555&&555555&5&&5555&5555&5555555555555555555&555555555555555555555555&&5555555555555&&&&55555555&&55555&555&5555555%565%565&&80w>::www::::w:w::ww:w::www:wwww:ww:www::www:ww:::qw:ww:www:wwww:www:::w::w::::qw:ww:w:w:www:w::::::ww:ww:wwww:www:wwww::::w:w>w086&5%5555555%5&55555555&55555555555&55&5555&555555555555555555555555555&&5&555555555555555&5555&&555&55555555&5555555555555&5555555&&5555&5&5&5555&55&&55555&55&55555555&", +"5&555&55555555&5555555555&5&5555555&55555555555555555&5555555&&5555555555555555555555&555&55555&55&555555&&5555&55555555555555555555&55555&5555&555&&&55&55&5555555555555&68-:>w:www:::>wwww:::wwwww::wwww:ww:www:w:w:::www:wwwww:ww::wwwwwwwwww::w::::ww:w:wwwwwwwwww:w:ww::::wwwwww:w:w::ww:ww:w::w>www-8&5555555555555&555555555555&5555&5&555&&555555&555555555555555&5555&&555555555&55555&555555&55555555&&555555&555&5555&&5&555&&&555555555555555555&5555555555&555555555555", +"5&5555&&5555555555555&5555&5&5555555555555&555&&5&5555555&55555&5555&55555&555555&55555555555&&55555&55&555555555555555&5555555555555555555&5&&555&555555&5&55&5555555555&5*80:,>wwwwwwww::::www:wwww::wwwww:::w:www:ww:::ww:::ww::www:w:wwwww:w::w:w:w:w:ww:w:w::w:w:w:::ww:ww::w:www:w::wwwww:w>>::>>w-86545&555&55555&&&55555555555&555555&5555555555&&5555555555&55555&555555555555&555555555555&555555555555555555555555555&&555&5555555&555&5&55&5&555&5555555555&&55&55555555", +"555&55555&&55555555&555555555555555&55&55&5555&&55555555555&5&555555&55&5555555&5&55555555555&555&55&&555555&55&55&555&55555555&5555&55555&5555&5&55555&555555&55555555555%5&80>,>wwww:w::wwww::wwwwww:ww:www:w::ww:::ww:wwwwwwwwww::::w::::w::www:w::ww:w:ww:www:ww:w:wwwwww::wwww:wwww::ww:::wwwww>>q0865%%55555&55&55&55555555555555555555&&&5&5555&5555555555555&5&5555555555&55&&5&55555555555555&5555555&5&5555&5555555&55&55555&555555555&&55555&&555555555555555555555&555&5", +"555555555&5555555555555555555555555&555555555&&&55555555555555&555555555555555555555555&555&5&555555555555555555555555&5555&55555555555555555&555&5&5555555555555&555&&555555&8-w>>>www>ww::wwww::ww:w::w::ww::wwww:ww:wwwwwww:ww:ww::wwww:::::::w:ww:www:::wwww::www:::wwwww:w:::::w:ww:w:w:w::wq:>,w-8*&5&55555555555&555555&55555555555&5&555&&555&555&55555555&5555555&5555555555&55&&555555555555&555555555&5555&55555555555555555555555&55555555&5&555&55&55&555555&5555&5&5&5", +"55555555&5555&&55&5555555&55555&5555555&5555555555555&55&555555&555555&5&55555555&5555&5&5&55555555&555&5&&&555555&555&5&&555&&5555&5555555555&&55555&55555&555555555555555&&5&8-q>,>ww>ww:w:::w:w:wwwwwwww:ww:www:w:wwww:::wwwwww:ww:wwwww:www::w:wwww:ww:wwww:www:ww::w:www:ww:ww:::::wwww:wwww>>>q085&55&&6&55555&55555555&5555555555&&555555&5555555&5555555555&555&5&55555&5555&&&5&55&555&555&555555555555555555&55&5555555555&55&&55&555555&55555555&5&55555555&5&55555&&555&", +"55&5555&5&55555555&5&55&555&555555&555555555555&5555&555&55555555555555&55&5&555555555555&55555555555555555555555555&5555555555&5555555&555&555555&5&5&5&&&5555&5&555555&5&5556**-q,,>ww:ww:wwww::ww:ww:w::w:w::wwwwwwwwwwwwww:www:wwww:www:ww:w:ww::w:w:www:w::w:w:w:::w:wwww:ww:w:www:wwwwwwww>,,;-*655&5&6&5&5&5555555&55555555555&555555&55&5555&55&555&5555&5555555&&55&55555555555555&55555555&555&555&5555555555555555&555555555&555&555555555555&555555555555555&55&55555555", +"55&55555555555&5555&5555555&5555555&5555&55555&&5555555555555555555555555555555555&&55&555&5&555&&55555555&55555555&5&555&555555555555&5555555555&5555555555555555555&55&5555&6&5*-0:>>www::www::wwww::wwwwww::wwww:wwwwwww:ww:w:ww:www:ww::w:w:ww:www::ww:www:w:::ww:::w:www:w:ww:www:www:www>>>>;8*55&55555&555555&55&55555555&55&5555555555555555&555555&55&&5555555555&555555555&555555555555555&55555&555555555&5555&55555&&5555&555555&5555&55&55&55&5&555&&55&5&5555555555555", +"555&55&55&5555555555&555&5555&5555555&5555555555&55555555&5555&5&555555555555&&5555&5555555555&555555&55555555555&&555&55&55&5555555&&&55&5555555555&555&5555555&5555555%&&5555%5&*80>,,ww::w:ww:ww:ww:::::www:www:w:::www:wwwwwww:www:www::w:ww::wwwwwwwwwww:::w:www:ww::www:w::www:w:wwwwww>>,:08*5&5%6&&55&55555555555&5555555555&555555&55&5555555555555555555&55555&5&5555&555555&555555555&555&55555&5&5&55555&&5&5&55555555555555555555555555555555&555555555&555&&5&55555555", +"5&55&55555&55&555555&555&&5%5%&55&55%%66%%&5%55&%&%6%%5%5555&55&%55%%&5%5%*%5555555555554*%%5&5%&46%6&55&55$*46&65%%%&&%55%&&%&56$&6%&&%566$6%*%$*5%&5*66&&$56665%5&5&%555&66%&%%5658-0,,w,;qq:>w:>:q>;,:>,:q>q:>:::,ww>>qwqwq:wq,qw>q:wwq,;:wq::wq;>:>>:wq>,:w>w:w:::ww:,q>q::>:w::wwwww:ww>,>:-8%56$5*5&%%&$&%*%56&$6&5%&5%65%5%&6556%55%&%&%&&$6%4*5545*%&%65%%65%&5655&#*5%5&5&564&5&&&455%5&$%65%&5%%&&%%*5&3**%6&%&%%%6&$&5&%5&&%%&555&6%&%%&5%*5%5555&55&555&55555555&5555555", +"&55&&&&55555&555&55555556%%&6%45$*&5*&5$645&5554*3*445565&55&%5%*456*545&6%46836&5555555&%5%*%%64&%64%&%%556&4$%%%&*&%6&%&*4564&*%&&%5565%%*&*4&*%4*5*$5%&&8$%%45*644%655&%%4*5&5%&65*-0w>,,>q:wq>ww,wwq,w0>:::>:>qwq>;>w:,0w,w:>w,;>>qww,;q>qqw>;:,qw;w>;:;:,qq>::q>q>:qq,qq>w;qw:wwww:qww>,>0-*%*53*545%6&&&65$6655&4&%&*4%&%%5854*$5&5&*355555*%*645%*%%635&&64565&5$%*%6$%*%55&5$&#*54&65*55%5*5&6%5665%*55$&545&64*%*&455$65&*$$63&55%%5%&%&*$5*46%555&5555&5&55555555555555555", +"555555555555&555555555555$6$5&5&*$&&35&&%6%56%&*%%&%*5%655&5%11t$*$*3%55455&&4&%555555&5366&$5&O.5&35&%556$5o.$*&63$:oXooXXooXoXq&6#O.54&&&*438woX+2<5.O65%$56&**%+6*6%5$*$*&355&%&%%*&802Ow>>,wwwtoooooowqt+w>q::ooww:w,:q::w..,qq;q:,q::;,>>O.>>:qw,q>:q,;1:>:wq:w:wwwww:>,>:086&5%5%5&5&*$*4454646%56%%5%%$&&%66%%*465%53X**%6&5%&&555555&555555&5555555&555&55", +"5&555555555555555555555&&666&3%455%6&%46>*5&4&6%&&6%3o7%555%o;.+++29+=2+++0>>w; :qw:X21>>++:qto.ww>:,1w:wqw>:;,=o>q>,0;,;>,qq q;>w,>:w::w::>,>q-*65>X*5t.X12:*5.XooXooXow%&&545&5%%%5%4*4%&6$ 44.7+o&56%:rq6&55&$*4>*5546&%*54%&5$59t45q&%5%<++o2.%9&66&>291,5&6=%56%%=+++=5r+++7*3%+o6r++r++7*5&3eX%5*3&6455&5555555&&555&&555&&555555", +"55&555&5555555555&5555555*$7 =5*%621>&&$*34*&56X7*$*4%t11t%&55%55545*45*355555555&5&&%5$1 =er5&5.7==r7=e7.*#&465&6=%*84&4*17r9=.5&&X+5.=7er==4o+%65%<+++2= ===1%55%.X.5115&6$**%56-.=tetq,,tooO2o2+oo:w:w:tew,>>t+Oo:o9=re9e9+.>:wq;9X9+oeOww;,X2+++r22=ew,:O+++29 =991:wwwwww>w>:-8*5%5Xe%4X2O.O.3%72++++++r<5&%5**%56%5*&&5*$55& %64<546&3*1 79r&*3621>66$6$$6*%.7==y77e=.&6;o+2++.<2oXXt%&o+5%1675=46577=7=%y=7=7%,o1Ot=5%7*5=4%*%r>6&4556555&55555555555&5555&5&555555", +"55&5&5555555555&5555555&4%656%5%56o=%5%&&2e.5*$*<<455o7*&5,+rX4%5*%&%%55*5&&4&*5&555&55555555Xe,*%&O1&4&45&et&3*56%&55r7=7r=77r5&465+o%55&5o+%*.oO1X.1er=y&*XooXot 4&5,4465%5%2155%384$&6=**-O+,,:qo9+29+92+rq>:to+r+O:trow:w>:w+ow:1,w>>:,q9+O:w.r,q:,0Xoooe+.>>0w>oow:>w,,,,0-*665&&<245*rqO<$**7o*%%3&% w55*%$5%%665&4451===7 =7==16$&&o9,$&5O155&%&2e.5*3*<<%55559t566#6&4t+1 r+<11+72ot+1=+4e%=%2.4*765*7*76&4=%t+=1oeooeXX=&356 %%%&*#*5555&5&5555555555555555555555", +"555&55555&55555555&55555*5%&66%5%5X=5%8356<15$6%7<5&&o7q<2e+>*5&%%65&6&564*%6%%555555&&&6366.r..53*r.56545+1O+,%6q645&=65%7*&*755t++71+o7==e+54=+2=+=&X+% 3654&<=+ 654*%*45*;=O%&56%%*5O%7%*te.ow,,<+q<+>+o,=w>t9+=1o12>Xe>qww;>+O1+eq:ww;>:r2w>:qeX:w:,.q:>=o0,;w>,,,:q08*5566&51O%649t%%*%%=o56*&%tr%45$*%56%%66465*4&%%% 5&$*445*.r..65%r.%55&&6<154*%7<55%4+1O+:*%>$6&q=1+=. X&+o&wo27o.2&7&X1&57=771&==777&8%+X&r++r++7$*%& 565$66%55&5555&55&5555555&&5555555&5", +"55&&&5555555&55555&555555&%554&5&5X=55%55%56%46<96%%%ore2o*%$5&46551==7=e&&555<+++++++++<*3or..r15O7*%%56. 2<<2<1ro%55r777r777r5$,oX2OXt=%6556%=+17+75+O4r&%%&o15o 465$5565q=21=2<5&5%.25=&$=oqet;,; wq2O>;q,+r2o22eOwww,:r:=oww:;299=re++o;,;>qo2wo :wwq>>>,,q-8*&5555%%6e.%5&1O&65%51.%&%56<2&%&<+++++++++<5%5%rq& %wr%66%Xr..e1%O=46&%%&%5*%%&&$75X+%=5+o&76%65+X%, .566%55.r7,=.:,ww;w,:trwqw >w.r>;>2O+ote>trXw>;, t>w;,eo:::>wq:w+o,w:q:wqw+o:t X;,>,,,w--6656$*54&&tr55&%.e44664%*%55*%=o465<+++++++++<5%5.e56 %52X5565t65%29r.5&%&&55$*%%.r.4*%Xr<5wO 1.4&5*0>e%&.q2:r5%6X2172:57*2o5575%r+++r%&755t7ro=%%=54=4&%5 &%655%1t5&55555555555&55555555555&55", +"&555&555555555555555&555*5%&&&%5&&o766%%4*5%*Xr<%%55*X=%655&5%4&6%*%%5*o+&4654545&55&55&%4&5$&6%57+84&55.o%.eOe5*&#*to9ooXeXXXeX;6+X+97O=&46+X&1=er715=t5=3*5#o7o1rX5%&%&.ro&4%5*4e.64et5=<2545>r*.=== ===r=99;ww++qw:yq>>OtwX2>+o2<:w++q>w09qw:wtr:>>q:>X++=O>w:>:q>>o9o2ro,>,,q-885*&%6&$56&%1+%6&6$9X&538535&5$O=5565$*%&*%4&&5%4&51O&% %*<2%%%56$&%%=+5%&%&$4*5%*Xr<4&%4.o*.eOe%%*$5.=re=r=52++&%>e<+t5o==X=%*5=*%r+++r567&X22X&r==r===&5%5 5&%6$wy5&55555&5555555555555555555&5", +"55555&555555555555555555$%&5&%5%5&X=&&$6546t1y.%&556$o756%4*5&*4%5%%5*3+O&54&*%*&5&55555*6%**4&512*455*$%5>r.57&4%*%o+e+++++++r+t521+oμ%=t&XXO1o.wr5&7654&6X+Xr,5%&*6*t5=72.46e.5o=55r2&4*2%2<6582O0:X9,w:>>wr.>,o9>:::>:+2O>ww,>,;w>12:;q,:27;>>o+ortq:-0-1e7w*554*%%*3.r>*45&%orw%5358%66r.5=5%4*&5076:,Oe;>qq,;;>,Oet>ww:: qq:1oo92tw>,;:,,2+:q0-5.26%%27O44>6X+#4%te<44557&*r+++r&%=4&&+X6*45=5*%6%5&2O53>+e>%5555555555&5555555&&&5555555", +"5&5555&&5&5&&5555&55&5555&66&$%45%.15464r1<%&5%&*35555<2=77=1<5%5%==777y=71%*5%&555&55555*&%t2r<&%5%&654%&41e+++2e&6&57&*5%65&75&X25+=OooXooX<;o+2e21rt&<+%&*64&5t+eo9*5&X2%554*&XO=1+e1.,,tr.Xr=r.wq>>;wt22O;<291tww,>w:o1r2t:;q>>q+e+1et:w1tw;,,,1<66%*6465>O&*%%&5*%>+*4$*6or+,%&%&46&5%565%%&465*X3&5% $*6%<&4*t2r<*53&&&53*r1<%55%&5*454&$1e+++2e4&5%<712te<&21w%&X+6t+eo546557*4eXoXo5675&&+o45&%7%55$&5#>9e=r2;&55&5&5&555555&&&5555&5555555&", +"5&&55&&55555&55555&5555554*4565&6&65%655&4&8$5&5$&*%%5%%%6%%55&5&%555556%&544656&5555555%%&&q+;*6%6&4%55&&6%:Xoot36%5515&%%.771%4o.$5wo++++++ot+ooq*+e71<>%**o=O-0X:>,<.:,>;:q,,q::,to>,>>:w;,:.+.>w>w,w0,>to,,w,,ww:Oo-*%&54*6<=+&5&%%55%55*65&%&5$%56544&3*:6$&*%5&55%%$&&4*%&%&%85&5%+64$4%%*&q+q&$5&&54&6%5$583&55%64&65&5>Xoot5$*te+&*Xro%&41+%4o+w,w:ww,>q,>,,q>w,,w:,w,>:,w>ww,>>:,;:,,q,,w>,ww;;886*3%*6$*%4*5&%%655$5**5%45%&5&*555%6*%&554*44*%&%%6*4%&4%5&&%&4&4&&55466%54%*&56546$565%&56&364&%55556564%4*%$*&4*%6$&$w55&6545%&5&$*5$&4%*58%4%&3*$*$%*%56&&4%6$#*5*&%5%65545&5&5&&55&5&55&555&555555&555&55", +"55555&5555555555555&5&555&5%54&55&&%553*55%55&%&%555&$6%&%&%%6*%55&6%5&&&$&&4%&55555&5555%55&6%665%5$&&5&%&54%65%*%%54*4%&465555%*%&5%*4%*5%%&%&55%%*%55%6%%%&&5546%&&455%*$6%5&&%*46&%6&%&%$65%56555%&4%*65%**5&*88-0q:,,,,,,>,w,>w,q:>:>::>;w:w,>w,,>,,,,,,>;;---8*8&65%*%#*5%&$&6%&%55&&5%5&65&555$55&&455556555&$6565%&5%&54*4555&4&%&%&6%555563&636&56$55565&%5&&%5%&&55%$*56466%5&%5%&5&%55%&5&%55&$66$56555%%&%&5&46%6&%&%&44&6$6*5&5555&54*455*%5555&5&&555555555&5&&5&55555", +"555&5555555555&&&55555&5&5%6&55%38$&55$&64&%&%5&5&%555%5555&65*4%5&4&56&%*53*5$6555555&5556645*%%4&5*53&65%%6&5%%&&%5%*%555%65%64556%5*45&$*%%6&5%*55&4&%6&$6%5*565&4655&%654*6%564&655555%*45555%%&5%&%5%*%45*%6%66*88--q0;qww>>>,,,,,,,,q>,,,,w,,,>w>w:w::-0-88&&*%5%*6$5&55%6&%5555565&4644&555&&5555555&555&5555&555&&55555&555555555&5555555555&5&5&&&555555&5555&555555555555&55&555555555555555555555&555&&55555&&5&55&5555555555555555555&5555555555&5555555&555555555555555", +"555555&555555555&&555555566$&555&45&555%$&&5&%6%%5*%5*4*%&64%6$6&555554%5%*6356%55555&55%4556*$&&&%5$&64$*%&%44*55545*%6655%646%&*%5%4566555564%6&%4565545%*5*$46&55%6555&&5%4%5&$%%%5*%&%5$5*5&&6*46&%&6%%5*5%*$&&$&556*588-88--0;::w;,>,,,,,wq:>0:-0--888*8*&64*5&6%5$4*&&%*55%545&*%45%*&%6$&55555555555&55555555555555&555555&55&55555555555&&&55&5&&555&55&55&55&5555555555&5555555&&55&&55&5&&555555555&555&5555555555555555555555&5&&&55&555555555&555555&5&5&5555&5555555555", +"55555555555555&&555&5555%35o<5%&51$565&6t5#6&5t.565%56&%&4$*&5&55%*5<.5&5*3556*5555&5&&5*55*%3*4%6%464&&5&&4*6%5%%&*53&445664*&4$55%5o%5%5&%&&$6%$&6o%5&&$6&*4*:5&%545%56%*%35&et45:553*$+o6r++r++765%5eX664546555445&5%&&64t56*%&5&:e13*5&*%4,e%5%.2+O*5$&$4%2o&84&56q.6&%45%56&%&%&55&555555555&5&5555&55555&55&55&55&55&&55555555&5555&5555&5555555555&555&5555555&55555555555555555&5555&555&55555555&5555&55555555555555555&55555&5&&5&&5555555555555555555555555555", +"5&5555&55555&55&55&&5&55&t=1X1XoX9XoX66&2.&45%o7556%66.o.&22$*565*$*e56&&<5&#&%6&55555&5564%6 %%&*X=%4%&555 55*%%8$5&54*5554*65%&4&5# %555%554*%55&4 *45<3$&%5&1 79r555521:&5*64545&.===y7=9=.660o1Ot=5&7%47&&&5r>%5&%46$55<277=err r<*365%&we1*6&%%%%4o2o<55+ot4*%*5*&X2o+96%&X765&5*o.6%%6%6&55555&55555555&55&&5555&555555&555555555555555555555&&55&55555555555555555555555555555&55&5555555555555&5555555555&5&5555&555&55555555555555555555&5555555555&&5&&5555555&555&55555", +"555555555&55555555&5&555%5<12:O++r++O5547*tooXOr11%&%&*4&11%*6354o+1 72o%11&845%55555555$&*$6 *&$6o=&56&654 %.XO+7O%&*6:6+:6%.t*&&&&& %&%6665&417==7 ====1*%6&X9q&&%O1&46%51e.6$%*<<*%6459t&&*3*%5t+71Xeooeoo=5%5$ %%*5&&%6%56eo%5%&55&55&556%555 $5&*X=5&%&+2= ==+Ooro&6%<14O+&5+O36A <:&44&&$*356%% #55%55%5.r..&4&r.4*%*46<1655$=<36&6+1O+:56w46*$+o%r++r++=%&%6 3&%%6%5%6&5*%*%2<55%%%&&&:r55et6%5*%% 1r1t5%664*5r:& 6:r5%*%or..r1&<75&&555%5*556%%%65&&%&5%rq5<+ooow&4465%%%5e.&5%&%r*$6&$4>y;&55&&5&55&555555555555555&5555555555555555555555555&55555&55&55555555555555555&5&5555555555&&&5555555&5&55555555555&555&555555555555555&5&55&555555555&55&&55555&&55555555555&5555555&&5", +"55555555555555&5555555555.72=17%.:.%=*%%76t%64X=5&%56.y7<;5t1=&5%66r:6&=o&5e.%5&%4&%5*%&&553&+55%&<1%*$55*% 55q115%555&1<*Xwo=%555&55 %>+r+;%&%5.e65 *52o5556t%&%1er.*$65%*%5*%4.r.554or<%wO 1.%5&&t=ro=55=&5=$&64 %%&5551t6%555*et&%5655&4wr<&5%*%&6&%5t95&%65&55%&6*t+=772e%*56% &5w%&551O$&%6%6$*555%555555&555&55&55555555555555&5&555555555555&5555&5555&5555&55&5&55555&55555555555555555555555555555555555&55555555555&5&&555555&5555555555555555555&55&555555&555555&55555&5", +"555555555555&55555555555&%OX+OO&=67&<4*5=O+&%*<15&55.yX%%65&5e.66%X2*5$e.5%&55tr:55 56%r.*4&%6551145*45665%6t1r.5&5%5%*;r.&7&55&%6%+o3O65=63<*55$ q*5&*1+56%644%=O5%&5&%*5%5&1e:$6&%*%%e.5<1$6$%&&4*2<5&&4&55&%&6O+&9t&54>r551e7w&5%&5455555&555&555555555555&5&55&5555555555&55&55555555555&55555&5&5&5555&55555555555&&5555&555555&5&555&5&5555&555&5555555&5&5&555&55555&5&&55555&5555555&5555555555555&&55555&5", +"&&55&55&5&&5&55&55&55555&*2X+15<2%76Oo&5=2655%56%t=1%65%6%%;o<2r+w%&5&$*5&o9&5.*&$&545+X%65&7%%655*52O$&q+e,%5&4*%&.r+t64&&44**44Oet54653.9*%O2*36&w$*41O%$*4&t%5*%5;r1=545*4;&.1%e<5*%%%65*%6&5%+r2t*4%*%&44*6%45tw4&&5%65*45%55&>XXo5%5&$6%%%*%45&*&%&4<=+&$64*%*55555&555&5555555&555555&555&555555&555555555555&5&55555&555555&555555555555555555555555555555&555555&555&555555&555555&&55&55555555&55&555555&55555&55&&55&5&&5555555555555", +"555&5&555555&&55555555&5%44:t556$556&%*554&3&&*455*5345&6%%&465&6$5&5&45&4&%%8%66$&*4*&45*&465*&$&%&%&%%38$%656%%5&*4%*%5%656**356&56$55%64664%&465$&36$&*3%&&%*%&4&$6*4&8%&%&%65&%4**%&&4&4*65556&6455%%*55654%4*65&%%5%%*4465%&$4&646%*%5*%*34$*4&%%5&%*$655%%%66%$6%&*456$5&5%%%*45*445%6%5*$564&6%555&55&&&5&55&5555555555&555555555&555555555&5555&5555&55&5555555&5555555&&5555&5555&5555&55555555555&555555555555555555555&555555&55555555&5555555&55555&55&&5555555&55&55555", +"555555&5555&555555555555*4664*%&5&5%55%5565&&%%&&5%%*65&&&5%*%%&%56$5555%5%*6%%%55*4&&%664655%%556%55&&55%556$6&5&%566$6&&$%&5$*55%64&&55*%46&5&&%565&4*&$&65%5%54*%5&5555%5%6&%%&5&%%*%4*55&&&&5%5%&&&6546%%&56&%%%64*%&&5%*5%65&*5%&%55%*%546&55&566%555544&555546%&&%%6&%5&%54&&%56546%&565%&555546645555555555&&5&55&55555555555555&5&55555555&55&5555&55&&5&55555555555&5555555555555555&55&55555555555&&5555&55555555555555555&555555&55&5&5555555&&5&5555555555555555&5555&&5", +"55555555555555555555&55555&5&5555555&555&55&555&55555&555555&5&5&&55555555555&555&&555555555555555555&5&555&555555555555&555555&55&5&55555555&&55555555&555555555555555&555555555&555555555555&5555555&5555555&5555555555555&5555&55555&55555&5555555555555555&5&55&&5555555555&55555555555&55&555555555555555555&555555555555&555555555555&555&55555555555555&&555555&55&&555555555555555555555&555&55&55555555555555&55&55555555555&5&&5&5555555&&555555555&55555&555&5&&55&555&55", +"555555555&555555555555&55&55&555555&555555555&5555&55555&5555555555555&5555&5555&&5555555555555&555555555555555&&55555555555555555555&5555555555&5555555555555&&5&55555&5&55&55&5&5555&5&555555555&&555&555555555555555555555&5&&55&5555555555&555&5&55555555&&&5555&55555555&&5&555555555&5555555555555&555&&5&&&555&55555555&&55555555555555&555&5555555&5555&555555&555555555&5555555555555555555555555&555555&55555555555555&5555&555&555&5555555555555555555&5555&555555555&5&5", +"&5555&55555&5&5555&55&55555555555555555&55&55555555&555&5&5&5555555555&&&55&55555&555555555&&5555555555555&55555555&5555&5555555555555&5555&55&55555555555&555555&555555555&555555555555&555&&555555555555555555555555555555555555555555555555555555&55&5555555&55&5555&5555&5555&&555555555&55555&5555555555&5555&555555555&&55555&5&5&55&5&555555555555&5&55&5555555555555555&555555555&&555&555555&&5555555&555555555555555&&5&5555555&555&5555555&55555555555&555555555555555555", +"5&&5555555&5555&5&5555&5&55&5&55555555&&&5&55555555555&555555&5555555&5&5&5555555&555555&5555555&5&555&5&555&5555&5&555555555555&555&555&55&555555555555555&5&5555555555&55&5&&5555555&55&5555&5555555555&&55555555555555&55555&5555555&555555555&555555555&555555555555555555555555555555&5&555555555555555&5&55555555555555555&5555555555555555555&5555555555555555&555555555&&555555&5555555&55&55&555&555555&555&5555&555555555&5555&&5&55555&&55555555555555555555&&5555&555555", +"55&55555555555555&&555&55&5555&55&555&55&5555555&5&555&555555555&555555&5555555555555&5555&5555555555555555&5555&5555&55&5&5555555&5&5555&5&555555&5555&5555555555&555&555&555555555&555555&5555&5&55555555&5555555555555&5555555&555&&55555&5555555&5555&555555555555&&5&5555555&&5&555&55555&555555555555&555&55&55555555555555555555555555555555&55555555555&555&555&55555&555555555&5555&55555&5555&5555555555555555555555&&555&55555&555555555555555555555555555&555555555&55&5", +"5555555&555555&5&555555555&5555555&&55&55&&555&&55555555555555&55&5&5&5555555&555555555555555555555555&55&5&555&&5&55&555555555&5&55&5&&55&55555555&&555555555555555&55&55555&5&5555555555555&&&555555555&5&55&55555555&55555555555555&55&555&555555&5&55555&5555555555&5555&555&&5555555555&55555&5555&5555555555&555555&555555555&5&55&555555555555555555555&555555&5&555555555555555&5555&5555555&5555555555&5555555&5555&&55555&&5&&5&&5&55&5&55555555&55&55555&55&555&55555555&", +"555555&&555555555555&5555555&5555555555&5555555&55555555555555&&5555555&5&555555555&555555555555555&&55555555&5&&55555555&555&555555555555&555555555555&&5555555&5&5555&555555555555&55555555&&555555&&5&555555555&&555&5555555&5555&555&&555&55&55&55&5&5555555555&55555&555555555555&555&555&&&&5555&555555&5555&55&5&5&555&55&5&555&5555&5555555&55&5&5555&55&&&5555&5&55555555555555555555555555555555&55555555&5555555&5&55555555555555555&5555555&55&55555&55&5555555555555555", +"555555555555555&55&5555555&&5&5&&5&5&&555&&5&&&5555555&5&5555&555&&55555555&55&555555&&55555555555&&5555&55555555555555555555555&5&5555&555555555555555555555&5555555&555&555555555&55&555555&5&555555555555555555555555&55555555&5&555555555555&5&&5&5&555555&5&5555555555&5&555&555&555&555&&55&5&55555&5&55&555555555&&55&55&55&555&5&55555555555555&5555555555555555555&5555&55555555&5&5&55555555&55555555&&5555&5555555555555555555555&&55555555&5555555555555&555&55&55&5&5&5", +"555555&5555555555555&&55&5555&55555&5&55555&5&55555&55555555&5555555555555&5&5&55&5555555555555&5555555&5&5555555555555555&555&555&5555&5&5&55555&555555&555&5&&55&5555555&5&55&55555555&55&555555&55&5555&&&&55555555555&55&&&&555555&&55555555&55&5555555555&555&555&55555555&&555&&55&55&55555555555555&5555&55&5&55555555&5555555555555&5555555&555&55555&&5555555&555555&55555555&5555&55555555&555555&&55&5555555555&555555555555555&5555555555&&55555555555&555&5555555&55&5&", +"55555555555&5555&5&55&&5&555555555&555&55555&&555555555&55&&&555&55&555555&555555555555&55555555555&&555555555555&&&55555555555&&55&55555&5&5555555555555555555&5&555555555555&555&555555555&5555&5555&55&5&5555555555555&&555555&555555555&&55555&555555555555&55555555&555&5&5&555555&5555&555555555555555555555555&5&5555555555&&5&55555&5&55555&55&5555555555555555555555&55&5555555555555555&&&55&5555&5&5&555&555555555555555&55555&5555&55555&5555555555&5555555555555555555&", +"5555555555555555&&55&&5555555&5&55555&5555555555555555&555&55&5&5&&55&&55555555&&5&55555555&555&55555555555555555555&55555&55555&&55555&555555555555&555555&55555&555&5&&55555555&555555555555555555555&5555&5555555555555555&55555555555555&55555555555555555&55555&555555555&55555555&5555&&55555&555555555555&&5&5&55&&5&&&5555&5555&55555&555555555&55&55&55555555&555&5555555555&55555&55555&555555555555555&&&555555&5&555&5&5555555&555&&55&55555&55555&5555555555&5555555555", +"55555555&&5&55&5555555555&&5555555&5555555555555555555555555555555&&555555&555555&&5&&5555555555&555555&&5&555&55555555555&&55555555555555&5555&555&5&&55555&5555555555555555555555&5555555&5&555&555555555555555&5555&5555&5555&555555&5555555&555&5&&555555&5&5&5555555&555&555555555555&5555555&55555&55555555&555555555555555555555&5&555555&5555555&555555555555&555&55&5&&55555555555555&5555555555&55555555555555&555&5555&5555555&&555555&55555555555555555555&555555&555555", +"55&5&5555&555&5&5555&&5555555&5555555&5555&555&55555555555&555555&55555555&55555555555&55555&5&5&555555&5555555555555555555555555555&&5555&555555555555&55555555555555555555555&55&&555&&&5555555555555555555&5&5555&555&55555555555555&55&5555&55&55&55555555&555&5555&555555&5555555555555555555555&5555&&&55555555&555&5555&&5555&5&5&5&5555&&55&55&555555555&5555&55&55555555555555555555&&5&55555&&555&555555&55555555555555555555&555&55555555555&555555555555&555&555&55555&&", +"&5&5&5&&5555555555555555&55&&555&&55&5&555555555&555555555&5&55&5555&55&5555&5555&55555&&5555555555555&5&5&55555&555&5555555555&55&555555555&55555555555555555555&555555&5555555555555555555&55&5555555555555555&55555555&5555555555555&&555&&55555&5555&55555555555555555555&555555555555&55&&55&555&555555555555&55&55&555&55&&5555&555555&5&&555555&55555555&555555555555555&55555&5555&&&55555&55&&555&5555555&55555&55&5&55555555555555555555555555555&555555555555555&55555555", +"&55&555555555555555&55555555555&55&5555&5555555555&5555&&555555555&&5555&55&5555555555555555555555&555&55555&55&5&55555555555&555555555555&5555555&55&555&55555555&555&55555555&5555&5555555555555555555555&5555555555555555&&55555555555555&55&555555&5555&5555555555&55&5555555555&555555555&5&5&5&5&555&5555555555&5555&55555555555&&5&5&55&5555&&5555555555&5555555555&555&5555555&555555555555&5555555555555555&555&5555555555555555555555&55&555555555555555555555&55555555555", +"&555555555555&5555555555&55555555555&&55555555555&555&5555555555&555&55555555555&5&5555555&5&&55555555&5555555555555555&55&5&55555555&55555555555&55&55555555555555555555&5555&555&&&55555555555555555555&555555555555&&55555555&555555&55555&5555&55555&5555&55555&5555555555&555555555555555555555555&55555555&55&55555555&5555555&&&555&5&5&55555555&555555&55555555&5&55555&5555&555&55555555555555555555&5555555555555&5555&5555555555555555555&55555&555555&55555555555555&555", +"555555555&55&555&5555555&555555&5555555555555555555555555555&5555555555555555&555555555&5&555555&5&555&55&555555555555&55555555555&55555555&55&55555555555&5555555555555&5555&555555555&5&5555555555&&555555555&55555&5&&&55555&555&&&55&&555555&5&5555555555&55555555&5555555555&555555555555555555&55555555555&55555&5&5555555555555555555&&&&55555555&55555555555555&5555&55&5&&55555555555555555&555555&555&5555&5555555&55555&5555&555&5555555555555555&5&5555&55555555&5&55555", +"&55&&55555555&55&55&555&&5&555&55&5555&&55555555555555&&555&55555&&&5&55555&55555555555555555555555&55555555&555&5555555555555555&55&5555555555555555555555&555555555&55555555555&5&55&55&5&5&&55555555&5555&55555&555&5&55555555&55&55555555555&&555&5555555555&5555&5&55&55555555&&5555555555555555&5&55&55&&5555&55555555555&555555&5&55555&&&555&555555&5555555&555555&55555555555&5&5&555&55555555555&55&5&5555&&555555555&555555&5&555&555555&&555&5555&5&&555&5555&5&55555555", +"555&&5555&5555555&55555555&5555555555&55&55555&555&555&55555&555555555555555555&5&&5555&5&555&5555555&5&5&555555&5555555&55555555555&&55&55555555&5555555&5555555&555&5555&5555&5555555555555&55555555555&555555555&5555&55555555555555&555&55555555&5&5555&5&55&5&555555555555555555555555&&5555555555555555555555555&55&5555555&555555&5&555555555&5&5555555555&5&55555&555555&5555&55555555555&55&55555555555555&555555&5555&55&555&&5&5555555&5555555555&55&555555555555&&55555&", +"55555555555&5555&&5&&55555&55&55555555&555555&55555&555&55&55555&55555555555&55555555555555&55555&&&55555555555&&5&5555&55&&55555&55555555&5555&55555555555&5&&55555&5555&55&&&55555&5555555&55555&&5555555555555555555&555&55&55&5555555555&5555555&&555555&55555555&555555&555555555&5555&555&55555555&55555555&555&&55555&55&5555&55555&55&5555&&55555555&555555555&5555555&555555555555555&5555555555&55&&55&5555&5555555555&&555&55&&55555&55555555555555555&5555555555555&5&55", +"5555555&55&55555555555&&555&55555555&55555555&5555&5&555555555&&555&55555555555&5555555555555555&55555555555&55555555&5555&555555555&55555555555555555555&5555555&555&&555&555555555555&555&555&555&555555555&&&555555&55555555&55555&55555&5555&5555&555&5&5555&55555555&555555555&55555555555&555&55&55&5555&&55&55555555555555555&5&555&55555555&555555&55555555555&55555555555555555555&5555555&555555&5&555&555555&5&555&55555555555555&5555555555555&555&55555555&5555&&55555&", +"5555&5555&&55&5555555555555&5555555555&&55&5&&55555555&55&5555555555&55&5&55555555555&555&5555&55555555555&555&&55&55555555&5555555555&5555555&55555&&5&555555555555555555555&&&55555555555555&5555&5&555555555&55&555555&&55&5555&555555555555555&555555555&55&&555555555555&5&55&&5&555&55555555555555&55555555555555&&5555555&5&&555555555&&5555555555555&&55555555555555&55555555&5&55&5555555&55&55555&5555555555555555&55&55555555555&5555555&55555&55555555555555555555555555", +"555555555555555&55555555&&55&5&55&55555555&555555&5&&55&55555555555555555&&5555555&55555&555555555&&55555555555555555&5&555555555&55555555555555555&55&5555&55&55555&555555555555555&555&5555555555&5555&55&55&555555&555555&5&555&555555&5555555555555555&555555&5&55&555&5555&555&5555&555555555&555&555&555&5&555555555&555&5555555555555555&55555555555555555555&55555555555555&55&555555555555&&&555555555&5555&555555555&555555555&55555&55&5555555&55&5&55555555&55555555555&", +"5555555&5555&5555555555555555&&55&55&5555&55555&555&5&&5555&5555555&5&55555555555555555&5&5&555555&&5&55555555555555555555&55555555555555555555555555555&5&&&5555555&&555&55555555555555&5555555&5555555555555555555555555555&5555555555555&5&55555555&55&55555555555555555555&5555555555&5555555&5&5&5555&5555&55555&55555&5555555555555555555&555555555&55555555&&555555555555&5555555&555555&555&55555&5555555555&55&5555555555555&555555&55555555555&5555555&5555555555&55555555", +"55555555&5&&55555555555555555555&555555555&55555&&55555555555&55&&&5&55555555555555&555555&55555&5555555&5555555&5&55555555555555&55555&5555555555555&555555555555&555&555555555555&555555555555555555555555555&55555555&55555555555555555&5555&5555555555555555&55555&55555555555555555555555&555555555&555555555555&5&5555555555&55555555555555555555&555555555555555&5555&555&5555555555555555&555&55&5&5555&55555555555555555555555555&&555&55&55555555555&&555555555&555555&5&5", +"5555&5&5555&&555555&5555&555555&55555555555555555555&5&5555555&5555&55555555555&55555&55&&&55&5&5&555&555555555555555555555555555&&55555&55555555555555555555555555&55555&5&55555555&555555555555555555555&55555&5555555&555&555555&5555555&55555&555555555&5&555555&&555&5&&55555555555&5&5555&555555&5&55555555&&55&555555&55555555555555&555555&&&5555&5&&555555&5555&&55555555555&55555&55555&5555&&55555&&&5&555555555555555555&555&&555555555555555&555555555&55&5555555555555", +"5&55&55555555&555&555&555&555555555&5&555555&5&5&5555555555555555&55555&&5555555&5555&5&55&5&5555&55&&55555&55555555555&555555555&5555555555555&5555555555&5555&555&5555&&555555&555555&555&555555&55555&&55&555&&5555555555555555555555555&55555555&555555&&&5555555&555555555555555&555555555&555555555&55555555555&55&555555&&555555555555555&555&55555555555555555555&5555555&555555&5555&5&55555555&55&55555555555555555555555&555555555555&555555555&5555555555&55&55555&55555", +"55555555&5555555&&5555555&&5&55&555&55555&5555&55555555&55555&55555&55&55&55555555555555&&555&55555&&5555555555555555555555&55555555&555555&55555&55555&5&5555&5555&555&55555&55555&5555&555555&&55&55555555&555555&55555555&5&55&&55&5555&555&555&5555555555555555&55555&5&&555&5555&55&&555&555&5555555&55&55555555555555&555555555&5&5&555555&5555&555555&5555555555555555&555555555555&5555&5&555555555555555&5555555&5&5555&5555555&55555&5&55&555555&&55555555555555&55&5555&5", +"5555&5555555&555&55555555555&55555&555&5555555555555&555&5555555555&&&&5555555555&55555555555555555&55555&&5555555555&555&55&55&555555&&55&5&&&5555&&5&&&5555&555&555&&&5&555555555555555555555555&55555&55555555&5555&&555555555&555&555&5&5&555&5&5555&55555&55555&5555555&&&5&555555&&555&555&&5&55&&5&555&5&55555&55555555&5555&5555&555555555555&55&5&5555555&5555555555&&&555555&55&&555&5555&55555&5555555&555&55555555555&55555&55&&55555555&5555&&55555555&5555555555555555", +"5555555555&&5&55555&5555&5&55&5555555&5&55&5&5&5&555555555555&5555555555555&555555555555&55555555555555555&&&5&&555&&55555555555555&5555555555555555&555&&&555&55&5555555555555555555555&555&&5555&5&5555555555555555555&5&5&555&&5&5&55555&5555555&5&5555&&55555555&555555&&5555555&5555555&55&5555555555555555&5&555&5&555555&55555555&5&5555555555555555&5&5&&5555555&&55&555555555&555555555&555555&5&55555&5555555&555555&5&555555555555555555555555555555555&5&555555&55555555", +"555&555&5555&55&555&55555555555555&5555555555555&555555&555&&&&5555555555&55555555&555&555555555&55&5555555555555&55555&5&5555555555555555555555555555&555555555&5&&&5555555555&&55&555&55&55555555555555555555&55&5555555555555555555555&555555555&555&555555555555555&55&5&555555555555555555&55&555&5555555&555555&55555555555&5&5&55555&5&555555555555555555555&5&5&55555&555555555555555555555&&&55555&55555555555555555&&55555&555555&55&5&55555555&555555555555&555555&555&5&", +"55555555555555555&5555555&5&&555555&5555555555&555&5555555&555&555&&555555555&5&55555555555&5&55555555&5555555&555555555555555555555&5555555&555&5555555&&5&555555555555555&5&&&5&55&5555&55&555555555555555&&555555&555555555555555555555555&&555555&5&555&55&55&&555555555&5&555555555&5555&&&55&&55555555555&5555555&555&555555555555&555&55555555555&&5555&5&555555555555555&55&555&555&55555555&55555555&55555555&555&5&555555555555&&55555&555555&&55555555555555&5555555555&5" +}; diff --git a/hacks/images/osx_10_3.xpm b/hacks/images/osx_10_3.xpm new file mode 100644 index 00000000..352539cd --- /dev/null +++ b/hacks/images/osx_10_3.xpm @@ -0,0 +1,279 @@ +/* XPM */ +static char *osx_10_3[] = { +/* width height ncolors chars_per_pixel */ +"474 256 16 1", +/* colors */ +" c #7D7D7D", +". c #5F5F5F", +"X c #393939", +"o c #E4E4E4", +"O c #1F1F1F", +"+ c #191919", +"@ c #151515", +"# c #A2A2A2", +"$ c #4E4E4E", +"% c #F9F9F9", +"& c #444444", +"* c #404040", +"= c #2A2A2A", +"- c #1A1A1A", +"; c #181818", +": c #C5C5C5", +/* pixels */ +"+;;;;@;+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;+;@;-++;;;;;;+;;;;@;--;;;;;@;+;;;;@;--;;;;;@;+;;;;@;--;;;;;;;+;;;;@;--;;;;;;;+;;;;@;++;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;+;;;;+++;;;;;;;;;;;@@;++;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;+", +";;;+;@;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;+;;;;;;;@;-+;;;;;;;+;;;@@;++;;;;;;;;;;;;@;+;;;;;;;;+;;;;@;++;;;;;;;+;;;;;;++;;;;;;;;;;;;@;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;++;;;;;;;;;;;;;;++;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;+", +";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;+;;;;;;;;;;;;;;++;+;;;;;;;;;;;++;;+;;;;;;+;;;;+++;+;;;;;;+;;;;+++;+;;;;;;;;;;;++;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;+++;;;;;;;;+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;+", +";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;", +";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;++;;;;+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;", +";;;;;+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;+;;-;;;;;;;;;;;++;;+;;;;;;;;;;;;;;+++;;;;;;;;;;;+;++;;;;;;;;;;;;+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;++;;;++;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;@", +";;;;++;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-;@@;;;;;;;;;+;;+;;;;;;;;;;;;;;+-+;@;;;;;;;;;+;;-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;++;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;@", +";;;;;+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;+;;+;@@;;;;;+;;;;;;+;@@;;;;;;;;;+;;+;@@;;;;;;;;;;;++;@@;+;;;+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;@;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;@", +";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;", +";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;", +";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;", +";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;", +";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;", +";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;", +";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;", +";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;", +";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;@;++;;;;;;;;;;;;;;++;@;;;@;;;;;;;;+++;;;;;;+;;;;@;++;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;", +";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;@;++;;;;;;;+;;;;;;-+;;;;;;;+;;;;;;++;;;;;;;+;;;;@;-+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;", +"+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;++;;+;;;;;;;;;;;;+;;+;;;;;;;;;;;;+;;+;;;;@;;;;;;+++;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;", +";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;", +";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;+;;;;;;;;;;;;;;;+;;;;;;;;;;;;;;;+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;", +";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;+;;;;;;;;;;;;;;;+;;;;;;;;;;;;;;;+;;;;;;;;;;;;+;;+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;", +";+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;+;;;;;;;;;;;;;;;++;;;;;;;;;;;;;;+;;;;;;;;;;;;;;;+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;", +";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;+;@;;;;;;;;;;;;++;;;;;;;;+;;;;;;;;;;;;;;;;;;;+;;+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;", +";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;+;;;++@@;;;;;;;;++;;+++;;;;;;;;;;;+;;;;;;;;;;-+;;;;;;+;;;;;;+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;", +";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;+++;;;+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;++;;+;;;;;;++;@;;;;;;;;;;;;;;;;--;;;;;;;@;;;;;+;;;;;;-;;;+;;;;;;;;;;;;;;;;;;;;;;;;;;---;;;++;;;;;;;;;-OO-;;;;;-$-;;;;;;;;;+=O;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-OO;;;;;;;;;;;;;;;;;--OO--;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;", +";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; :-;;;.#+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;=% ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;+;;;+;;;;;@;;@@;;@@;;;++;@;;;;++;;;;;;@;;+-@;+;;;;;;;;;;;;--;;;;;;;;;;;;;;;;;;;;;;;=o=;;;&#O;;;;;;;;;#o=;;;;; %=;;;;;;;;;;##O;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-: ;;;;;;;;;;;;;;;;;*%%o:&-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;", +";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;*%.-;Oo&;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;&%&;;;;;+O;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;+OO;;;;;;;;;;;;;;;-O+;;;;;;;;;;;;;;;;;;;;;@;;;;@;-;;;;;;;;;;;;;;;+;@+;@;;@@@;;+;;;@@;;;;;;;@;;+;;;@;;;O==-;;;;;;;;;;;;;;;;;;;;;;X%=;;; %O;;;;;;;;;:%O;;;;; %=;;;;;;;;;+::O;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-=O;;=:#+;;;;;;;;;;;;;;;;*% o%.+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;", +";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;+#%O+:o+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;O%X;;;;;=%O;;;;;;;;;;;;;;;;;;;;++-++;;;+-++;=o +-++++++;+-++--O O+;;;+OO;;;+--+-OOOO--O=O+O=OO===X=-@;+;O=XX=OO=XXX=--O==XX=O=X=-+O=====O--=O--==OX XO;-OOO-;--OOO-;;;;;;;;X%=;;+#%O;;+--+;;-::=;++++$%=;;;;;;;+-+##O;;--++;;++;;--;+O--O--++;;;;;;O: -+O: ++-;;;++----;;;;;$o*O*%#--OOO-+-O-;-O-----;-OO--;-OOOO-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;", +";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-:: %=;;;#ooo=;;#o-;.oO;;;;;=o#:%#-;;O:%:-;;-#o%=;;+#%%o% ;;;;O%%%:+;$ooo=;;;;;;O##o ;O:oo +;=oo% - %%%$-#%o:.;O::#:$%o%#+;;O##-;+=:=O#ooo.== :=+Xo.= o#%#O@+;O&:o%o==#o%o == : oo#$::#*-=# :::$O=#.==##X#o%%.OX:o%&O-:#o%O;;;;;;;;*%=--+.%=;-:o%%=++:%O;O#%o%%X;;;;;+X:%:o#-+&o%%#+XoO;$: -O:$&o#:%:=;;;;;.%%%&O:# %o*;;O:%% -;;;;;.o=-X%#-&%oo#-=o&;X%#-=# O&%%:&-=::#:X;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;", +";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; %%#-;;#%*-#%O;:%-;.%O;;;;;&%o*.%=;&%#+#:+;:#- %O;#%=-:%$;;;;; %.;;$%.+ %*;;;;;=%:X++#:O$%&- :=OO+=%:-+O.XO#o-Oo% --&oX-;;;-&%$-O#oO %$X#o$X#:=-&%$X#%#$=O;+-*oo.&$= % $#o.=.%%. %o .%#=X%% $:%XX% =XooX&o:$=X::X %=Oo%#=-;;;;;;;;Xooooo%%O+#%*=#%=+:o=+#%X=o%=;;;;;.%#O %#-*%#O$%.=%$+ %:OXoX$%%*.%.;;;;;=o --O:%#=#:-O#:=$%$+;;;;.oX=ooX*%#=.% Xo -.%:OX%&=o#=#:O=o% OO;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;", +";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;+:%=+;+o +;-o ;#%-;$%O;;;;;.%X;O%=;#%.O %=O%#O %X-o ;;X%$;;;;;.%=;;#:+;;#:-;;;;$%$;;=o:=$o#-#%.-+;=%#+;;--+Xo=Oo:-;;=%=;;;;;=o:-=%.=:#O-&%:* oX-&%.X o&O-;;+=.%.=OOX::*=&:o& %$=&% X&%:XX% X=$%.&% =Xo:XXo:X= % &.%&Ooo=-;;;;;;;;;Xo#. :%=-o.-+Oo +:%O=%*+-.%*;;;;+#oO+-:#-#o=;+#:X: O#%:= o=$% -=: ;;;;;O:#+;O::O+ oO=%:=.o#-;;;;$%o%o$O o=-O#:&o#=#oo**o=.%.&#%$=o:O;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;", +";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;+:%O;;Oo=;;+:#;:%O; %O;;;;;.%O;-%*;#%o%%%O.%%%%%==%$;;*% ;;;;;.%=;-:#;;;$:-;;;;$%$;;X%%%%%#+O:%o$+=%#+;+$%%%:O=%:+;;=%=;;;;;O o=.oO=% O-*oo& oX-&%.X#oX;+;;+= o*-;-*%#X-X:o$ o*O*% =*%:X*%.XO&% &%.=Xo:XXo:X=#%%%%%.O:o=;;;;;;;;;;*%XO;- %O=%=;;+:#-:oO.%=;; %X;;;;;:#O;;##-##O;;#%O#: :#oX# -$%.;Oo ;;;;;O: ;;O: ;; oOX%%%%%#-;;;;$%&=OOO##O;-&o& :.o#o##:O#%o%%o.=%:-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;", +";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;+:oO;;+o*+;+:#;#%-;$%=;;;;;.%X;-oX;#o=+++; %$;+-;O%$;;O%&;;;;;.%=;;##;;;##+;;;;$%X;;=%#+--+++-=#oX=%#;;Xo -$o=O%:+;;=o=;;;;;+X%#:#-=o#O-&o#*#oX=.%.X#oX++@;+=$%$OO=*:#*=$::$ %$X$% &$%:$$o *X.%.$% X&o:XX%oX= %.&XXOOooO;;+-;;;;;;&%=;;+ %==o*+;-:.+:oO.o=;;.%=;;;;+#:O;;#:O#oO;;#oO$:%#=#:o.;$%$;O:.;;;;;Oo ;;O: +;.oOX% -OO-+;;;;.%=;;;O :O;O o=&%#:X:o:.O o*===O=oo-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;", +";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;+:%O;;;:oO- %O;#%O=o%=;;;;;$%X;-%X;$%#+;=--::-;O-+::+-o%$;;;;;$%=;; %=;=o#;;;;;*%.;;O#%=;-O;O=- %&Oo:-+=%$-#o=O%:+;;=% -+;;;;O:%:O;O#o$& %.X %..%%.X oX;++--O&%:.$ $#% $ o $ o$&$% $$%:$$%o..o%..o:. %oXXo%$=$%:$**==o:=;;*#O;;;;;X%=;;+#%O+:oO-.%X+:%=Oo#O=o%=;;;;;#%&-&%#- %.+=% +=o%&+ %:=;$% ;Oo ;;;;;-:#-;Oo ;;.oO-:%=+O=+;;;;.o=;;;;.%.OXo#-X%% O %:=;&%#=O===%:-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;", +";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;+:%O;;;-:%o%.+;=:%o:%=;;;;;.%=;OoX;+.%o%o=;=o%o%*;=o%:o% ;;;;;-:%:+;#%%%:+;;;;;*% ;;;O:%o%#+ %o% ++.%o.Oo%ooo:&%#;;;O:%#-;;;;O&%#-;-X:%o%#XO*o%o %.=#o=--O===* %o%o$.:%o%:.$#%$&.%#$$%:$$ooo%% $&:%%:o:$X %o X.o%%%.Xoo=+-#%=;;;;;*%X;;+#%=;O:o%% -+:oO+.%%oo%X;;;;;-:%%#o:--#%%%:O;O:%X; %#-;.%.;Oo ;;;;;-.%%*O:#;; oO+=:%o%#+;;;;.o*;;;;O#%o%:=+=:o$-&%#-;O.%%%o&=o:-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;", +";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;+OO;;;;;-OOO+;;;+O-+-;;;;;;+-+;;-+;;;----;;;+---;;-+--+-+;;;;;++++;;+---;;;;;;;-O+;;;;+O--;;+-OO-;;-OO-+-OO--O---;;;;O==+;;;;-*%X-;;OX&&*=-+=*&&XX=O=*===XXX**$....&&.....&&$.&*&.$*&..$$o#..$$&*$.....&&$..&XX&&$&=OXXO;-=XO;;;;;-=-;;+-O-;;-OOO+;;-O-;+OO--O-;;;;;;--O----;+-OO-+;;OO+;+O--;-=O;+--;;;;;;+OO-+O-;;+-+;;-OOO-;;;;;O=-;;;;+O===O-;-==O;OOO;;;O===OO-==-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;", +";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;O#oO+;;-+-----+-+-OOOO==XX******&&&&$&&&&&&&&&&&&&&&&**&&$$.% $$&&**&&&**********XXX==OO---++---+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;", +";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;=#.O@@;;;@@;@;;;;+OO=XXXX********&**&&&&&*&&****&*&******&&$o $&&&******************XX==O;;;;;@;;@@;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;", +";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;O=O-@;;@;-+;;;--O==XX************&&***********************&&$$&***&********************XX=O--+@;+;;+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;", +";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;++;;;;;@;;;;;++;--;;-O===X*****************************************&&&***************************XX==O+;-+++-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;", +";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;=O+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-X-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;O=-;;;++;@@@@;@;-;;-;;;;+;;--==XX****************$.$**************&******************************************X=OO-+;@;;;++;;O=O;;;;;;;;;;;;;;;;;+++++;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-=O;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;", +";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;+#:O;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;X%%o=;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;XoX;@@--@@-;;O;@--+;;;@;-+O==XXX*****************$o *************&&&&&*&&&*************************************X=O-+++++O-;+Xo=;;;;;;;;;;;;;;;;+#oo%#O;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;X%$;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;", +";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;+:%O;;;;;;;;;;;;;+O+;;--;;;;;;;;;;;;;;;;;;;;;;;+:#--+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;&%X-;@@;@@@@;+;@;;;@;+;+O==XX********************.% &***********&&$$$&&&&****************************************X=OO-+=$=@O$%X;;;;;;;;;;;;;;;;+:o :% -;;;;;;;;;;;;;;;OO+;;;;;;;;;;;;;;-O-;;;;;;&% ;;;;;;;;;;;;;+=O;;-O=;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;", +";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;+:oO+-+;;+--;;+;;$oO;;#o-;;;;;;;;;;;;;;;;;;;;;;-:X;;;;;;;;;;;;;;;;;;;;;;;+;;;+++++++;;;;;+;;++++;+--O-+-OOO-;;&%&O;;;+O=X=O-@-=X=O--O=*&$&**$$$$&*&$&$$$&**&$$$.%#$&$$$$&*****&....$$$$$$$&****&$$$$$&*&$$$$&&$$$$&*&&$&&&**&&&&*X==O.o$X=.%&OO-;;;+;++;;;;;;;:#O-:%O;;;+++;;;++++++ o=+;;-+++;;-O--;Xo&++;;;;*% +++;;++;;;+++-##+;O: O-++--O--;+---O--;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;", +";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;+::::o#-;&oO;O#O-:%o: o%% ;;#%ooO;; ##:o&;;;;;-#%%%&;$oo%X;;$::%.;;;;- o%:O;+&o%:OOo ;;O# +X%o:O+=::::*$o%o#O+$%$O@;;O&#%o.OO*:oo.==* ooo & o%%:$&.o##o:.&&.#oo#o $ ooo#&****&.oooo.$$o:oo$****.o ooo$&$o#oo$$:o%#$&.:oo:$&#:%%$***XX:%o%*$o.#%:=;+=:%%=;;;;;+:#-+#oO;- %%#O;O#o%:-*%%%#- o%o O;.#:o##%o:=;;;;X%:#%o=;-# ;;$#-X%%% =%%%#-=:%%#=-=::#o#&-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;", +";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;+#%:= %=+#%=;=%=; %X+-:%=-;.o$O#%=; %:X#%=;;;;;Oo -+&o.O#%X; %:=+;;;;&%.-OO;=%.=:#O:#+;&%X=%.=:#-=%% =O& = %$O&o$O@+-*::.$$=X:o. %.$#%#....o% %:$.%%: %o$$:% :%#.%%...&****$o% %%.$%%#.&**** %% %o.$o% .$:% %.$:o.. &$% $ &***** %.&=$o% .o O=:#O:oO;;;;;::$#%*++ %X=:.+#%&O=O-#%$-+. O#%&; %:*-&%#O-;;;;X%%#=#:=O: ;;$oOOo#O-=:#=O=o:X.%#-X%o#$o#-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;", +";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;+:o=+-::-.%=;=oO;$oO;;#oO;;:#;;-: ;#oX;&%=;;;;;-:&;;#:+;+##;$%X;;;;;;X%#-;;+ oXO#o=Xo*+.#-.o&=#%==%#O;;OOO&% =$%$O@@;X:o.X=O$%#. o:.%o$&&& o &$#%..%#$.oo$.o:$$.% .%% $$****&.% .. %..%:.&***** % $$#%..o:.$.%: %:.o%#$&*.%:.&&*****.%.X=.o X*:#X %.X %O;;;;+#%%%$+;-::X=o:O$%#O+;+#oX;;+-+$% ; %.+;.% ;;;;;;&%#-+$% O:#;;.oO-:#+;O:#-;.%.-O.%*X%:O=:#-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;", +";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;+:oO;;:o-.o=;OoO;.o=;;#oO;-:O;;;##; o-;Xo=;;;;;-:*;+:.;;; :;$o=;;;;;;+$oo.;;#oo:o:OOo.-:.-#o:oo:X=o#-;-=#o:o =$%$O@@;O$o%:$=$%o%%%:.%#&X*$#o$*&.% .%#$$:o$.% &*$% $ :%:.&***&#% .$ % .%:$*****$ %.*$ %..%#$* o%%%%:..:o%.&& %%#$&**** %.*X.%$O=:#&:%%%%%O;;;;;::=::-;O:%%%%o=-#%%.-+#%=;+=:o%%$- %X;;&%.;;;;;;X% ;;=% O: ;;.oO-:#+;O:#-;.%X;;&%.X%#-O#:-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;", +";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;+:%O;;:#-.oO;=oO;$:O;;#:O;+:*;;;# ;.:-;=:=;;;;;-:X;+#$;;; #;X:O;;;;;;;;+$oX; #O---;+ #.#-- #=O---=:#-;=:#& o.=$o$O@;-O=*.o:*$%#...$.%:$*&$ o.*$ o..%#&$oo$.% &&$% &$. %o$***$ % $$ %..%#$*****$#o.$$ %..%#$*.%#. ..$$. oo$&$$ %:$****.%.**.%$O=o#* % $&XO;;;;+:#OXo$+Oo#=OOO++-O %X+ %X;Oo#= %.- %*;;&% ;;;;;;&%.;;*o*O:#;+ oOO: ;;=:#-;.o&+-$%.=o#-=#:-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;", +"+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;+:o&+O:X;&:=O :O;X:O;; :-;; #-;=:O;$:-;=:=;;;;;+:=;;*:O;-:X;X:-;;;;;;+-;-:*;=:*+;-+;O::$+;=:$-+OO=: -;X: &.: =$o$O;+-=&&$#o&$:o.$$ .:% $...%:..o%$.%#&$oo$$%:$.o: &...:%$***&.%: o%..o:$*****$#%#..oo..%#$*.o% .. $ .$#%$$.$.o:$**** % $&.%$=X:#X.%:$&$X-;;;+::-+#%=+:%$--O-==-$%X; %=+&%.O#%.O %*;;$%.+;;;;;X%:OO#o=O#:O.%:O-::-+O::=-*%#O=:#OX%#-O#:-O..-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;", +";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;+:oo::#+;-##: :O;+## +-##X++####=;;.#-;=#O;;;;;+#O;;;$:#:*;;X#-;;;;;;-####+;;&####-;-##O;;+&####O=# -;= :# ##X&:&O@;+X:%oo#X& %%oo#&.:%oo $#%o%%.&$%:&$oo&& %oo:% $ooo%#$&*&&$ %o%% $.%:$*****& %:%oo.$.%#$*$.ooo%#$#%o%#$.o%oo &****$:%o. %.XX::X=.o%o%&O--;-#:-;-::-O:%o%:O.oo%:O;=:%#O#%%::%*.%&;;-#%o=;;;;$%%oo%.+;$%%##o=;&o%.-X%% O.%%oo&-X%:-O::-=o#-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;", +";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;----O+;;;-OO--+;;++-;;+-+;;+---+;;++;;;+;;;;;;;;;;;;;+;+;;;;;;;;;;;;;+++;;;;;---+;;;++;;;;+-O-O--=O-;O=XXXXX=OX=-;;+OX&$$$**&....$*&$...$*$....&*&$$&&$$&*&...$.$&....$&&**&$$. ..$$$ $&*****$ % ...$*$..$**$.. .$$....$&&...$&*****&$..&&.&*X&XO;=&&$&=-;@;-=O-;;OO+;-O=OO+-OO=O+;+-=O-OX====O==-;;;O=O+;;;;-OO==O+;;-O=OOO+;-==O;O===;O==X=-;OXO+-O=+-=O;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;", +";+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;++;++-------+++;;@@;OO=X***&***********&&*&&&*************************&&**&&&$$$$$$$&*******& %.**********************************************XO;-OOOO-;;@;+-++;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;", +";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;+;;++;;;;;;;;@;+;;;;O=XX****************&***********************************&&&&&&&&&&******& :.***********************************************=O+@;--+;;;+;;-+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;", +";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;++;;@;+;;+;;@;-O=X***********************************************************************$$&***********************************************X=O;@+;;;;;;;;--;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;", +";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;++;;-+;@+O=X***********************************************************XXXXXX**********************************************************X=O;@;;;@@+;;++;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;", +";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;+-O=X*&********************************************************XX======XX*********************************************************X=O-;;;@@;@;++;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;", +";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;+;;;;;;;-O=X**********************************************************XX=OO--OO=XX*********************************************************X==O-+;;;@@;+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;", +";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;+;;-O=X***********************************************************X=O;;++@+O=X**********************************************************X==-+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;", +";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;++;-O=X***********************************************************X=O+;;;;@;+O=X**********************************************************X=O-;;;;;+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;", +";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-O=XX***********************************************************X=-+;;;;+;;-=X***********************************************************X=O-;@;;+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;", +";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;+O=XX************************************************************XO;;;;;;;;;+OX************************************************************X=O+@;;;;;;;;;;;;;;;;;;;;;;;;;+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;", +";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;O=X**************************************************************XO;;;;;;;;;+OXX************************************************************X=O+;;;;;;;;;;;;;;;;;;;;;;;;;+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;", +"+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;@;+-;;;+O=X***************************************************************XO;;;;;;;;;+OX**************************************************************X=O+;;;++;;;;;;;;;;;;;;+++;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;", +"+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;+-;;;O=X****************************************************************XO;;;;;;;;;;OX***************************************************************X=O;@;++;;;;;;;;;;;;;;+++;;;;+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;", +";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;++;;O=X&&***************************************************************XO;;;;;;;;;;OX****************************************************************X=-@;;;;;@;;++;;;;;;;;;;;;;++;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;", +";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-=X******************************************************************XO;;;;;;;;;;OX***************************************************************&*X=-;;;;;;;;;;;;;;;;;;;;;;;+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;", +";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;+-+;@;-OX*******************************************************************XO;;;;;;;;;;OX*****************************************************************X=O;@;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;", +";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;+-;;;-O=*&******************************************************************XO;;;;;;;;;;OX******************************************************************X=O;;;;;;;;;;;;;;;+;;;;;;;;;;;;;;;+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;", +";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;+O=X********************************************************************XO;;;;;;;;;;OX*******************************************************************X=O+;;;;;;;;;;;;++;;;;;;;;;;;;;;++;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;", +";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-=X********************************************************************&XO;;;;;;;;;;OX***&****************************************************************X=-@;@;+;;;;;;;++;@;;++;;;;+;;;++;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;", +";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;--+;;;;;;;;;;;;;;;;;;;;;;;;;;O+;+O+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;--+;;;;-=;;;;;;;;;;;;;;;;;;@+;;OX*&**************************************************&****************&XO;;;;;;;O=OO*&&*****************&*********&**********************&&&****&&&******XXOOO;;-;;+;@;+;+;@;-;+;;;;++;;+++;;;;;;;;;;;;;;;;;;;-=O;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;O=O;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;", +";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;$ O;;;+ =;;;;;;;;;;;;;;;;..+-:=;*o=;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;Xo=;;;O:.;;;;;;;;;;;;;;;;@;;;;O=X*&***********************************************&********************XO;;;;;;;$:O=##$&***************&$&********&*&*******************& :.&**& :.********.#X-@;+;;;+;+--;@;+;;@;;;@;+-;@;;;;;;;;;;;;;;;;;;;;X:.+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;X:X;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;", +";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;.%X-;;O%=;;;;;;;;;;;;;;;;:#+O%X;.%X;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; %X;;+##O;;;;;;;;;;;;;;;;@@@@-=XX***************************************&$.*****X*&******&*************XO;;;;;;;.%==#:$&&&&&&*******&*&$ $&**&&&&**&&&&&****************$#%#$**$:%.*******& :*-@;+@@@;+=*=+@@@@@@;;@@@@@@@;;;;;;;;;;;;;;;;;;;;*% -;;;;;;;;;;;O=O;;;;;;;;;;;;;;;;;;;;;;;;;X%*;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;", +";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;Oo#O;-$oO;;+++;;;;;;;;;;;++;=%=;$%=;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;$%X;;+---;;---O-----+;;-====OOX*&&&&&******&&***&**&&*****&&****&**&*&**$::&&X*&&*X&&&&&*&******&&&&&**X=O-++--O$%=O$.$$$$..$&&*&$$$&&$#o.$&&$$$&&&$$&$$&&*&&&&&********&:%%.*& o%.*&$$$$*&$$XOO====O-O.o.XO;O===O-O====O+;;+---;;--O----+;;;;&% -+----+;;;;-=:.O+;+---+;;--+;+--;;+----+X%X---;;;----;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;", +";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-#%=;-:#O;=#:o=;+ +;.#-;$.+Oo*;.%*;;&o: -;.:o:::=;;;;;=##o=;O:o:O;;O#:#:%*;+$o: O;X# #: =#:#=-X:::#$=.#:#: ##: & o:#$*.:#o#***&##&*&$:&&#o:#$&#o%:#.:#::X* oo#$&****&.::o#&*$###:OO:o##%==##$.: #:# $$ :oo &.o%o:$$:::#$$ :.. :.*.##:#$*******&:o% &$:o%.*.::o:$$ :$= # ::.=X:%o:X=.o:#X=$# #:#X+-X#o:=+X::::: =;;;;*% -=:::#=;;;;O#%%:$-X::: -;&#*;=# --=#:: -Xo :: O;-&::#O+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;", +";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-.%X-=%*-O:#=::O+:#-;#%O;##+O%X;$%X;.%.Xo$;-XO=:%X;;;;; %: --o#O#:++#o.$o%*;$o $o.-$%o %:##% O&#. %#* oo:..:%# $.o: o:&.%o#.***& % *$:o$#% %:$.%o $.%o#$X.o .% $***&$oo #o &$%o *O:o. %%==o%..%%o %o.$##.:%&&:% $&:% #o .#%.. %.* %:#.&*******&:#o:$$o#%.*.# #o $ % X#%o.:%$X#%#$= o .o X.%%##%.-=o#*::OO$&X#%#O;;;;&% -X#$ % -;;;O.%:*OX%:&#%.-$% ;=%#-=oo$&.-X%o %*-Xo .o#-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;", +";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;O:#O :=-.% = %X+:#-;#%O;:#-O%=; %=+#:OO::O;;;X% +;;;;; %$;; %.- %&Oo#;;#%X-::=X::O$% O*%:O=:#=OX*$::&.oo.X$:o$&$:%..:o$.%#&*****.%:&.% $%#&& %#.:%$X$%:*OX:o..::.&**$#%.&$:%$.%#=;=%$O=#o==#%..%o :%.&$$$ %&X#%$=&o: %:.#%.. %.* % $&********&o#:%. o o.*$.. ::.#% *#% * %.= %.=X#:..:o&.%#*$o O % X %.;;-=::=+;;;;&% --OO=o#-;;;;X%#-- o=-=#:O*% ;X%#O %&O;;;X% OX% O#o$X o=;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;", +";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-#%X:.O-:%%%%%=+:#+;:oO;:#-O%*;.%=-:%%o%oO;;X% +;;;;;; %=;; %o%%%XX%=;;.%==o%oo%:O$%.-*%#-=:#==.o:%#&.%:&*$::&*$%%%o%o..% ******$#o.#o$.% *&.%#.ooXO&%#=;*%%oo%o&X**$:o$*$#%$$o O;$%O;-$%==:%..o:..:%.&.#:o%*=#%*O.oo%%%o.#%.. %.* %.&*********$:# o :# %.$.#::%:. % &:%$= %.= %.O*:%oo%o&.%.=$: O %%%%% ;;=o:=-;;;;;&% -O.::%#-;;;;X%#-O:#O;-$%=&% ;X%#=::O;;;;X%*-*%#=o%o%%:X;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;", +"+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-&% oX;-#%.*&=--:#-+#%=;:#-OoX; %=-::O=OO+;Oo:+;;;;;;; %=;; %.OXO+.%=;;*%X=%#O=X=O.%$;Xo#O=:#X :. o#*.%:&*.::&&.o:. .$&.%#&*****&.%#o:&.% &X.%#.ooX+&%#=;*%o.$$$=X*&$:%$*$#%$.%.O;.%O;O$%=X:%..%:.$:%..o . %*=#%&O$% .....#%.. o.&.%.**********$o:.:o%. o $#o o#.#% &:o$= %.= %.OX::..$&=.%.=$o.O %.X$=O+O:oX-;;;;;;&% -.o$$o -;;;;*%#-O#:O;-.o=&%.-X%:O :O;;;;X%X;X% =ooX$X=O;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;", +"+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;O:%o=;+&% OO=O-::O=ooO+#:-OoX;.%X+#%X;+-;Oo#-;;;;;;;; %=;;$%#;;-+=%#;-:%*-#o=+-OO$%.;X%#OX##*#:..::$.%:&*$#:&*&#% &&.&.%#*******$o%o$X.%:.$#%.$:o&=&%#=;=#%.**&=X*&$ % $.%:$.%.O;=% O*:o=X:%..%:$$#%. %.$#%$X#%$=Xoo$&&$$:% :%.$ %.**& $****$o#.#%o$.% .:o o:. % $:%$= %.= % X=#%.&*X= %.=&: -.%#OO=O=::*O--+;;;;$% O:#=Xo#O;;;;*o#O-.%$O=o:OX% = %#-$% OOX-X%*;X%#O %$OO=O;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;", +"+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-#% O;;O.%o:%X- %o:o%=;:#-=%&;.%$;O:%:::- %%::o=;;;;; %X;;+ oo:oX+ %::%%.;O:%::#O.%.;&%#=*o#X.%o:o% .o:**.::&*&$:%oo:$ %#&******&#%:&*$ %oo% X=.%: =%#=;O*:%:o:=X**&$:%:o%.&.% O;O#%:%o%==:%$$%o$&o%.$oo:#%:X$oo#X.oo:o#& %:o:%.. %.**$o:$****$o:..##$ %.$#%::%% #% &:%$= %.O*:o#X&:%:o:X.% =&o.;O %o:oX.%%:::#O;;;;$% O.%o#o%.;;;;O#%#$O#%:oo=+=:%:o%#-O#%:o:-X%*;X% O=#%:::=;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;", +";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;+=&O;;;;OX$&$O;OXX===-;==+-=O;OX-;+O=&*=+O=XXXX-;;;;;O=-;;;-====-;+=*OO*-;+OXX*=-OX=+=$*O=&&O=$. . .$..**&..****$ .&$ .*******&$..**&$. XOO=&$=O&X-;-O*..$.==X*&&. .&&$ X-;-O$$$=$O=. &*..&&. &X&. &$.==$.$==&$..&=X . $$. $&*&..$****&..$&$$&$.$&. . .. $&. *=X$=-O&..=OX$..$=X$XO=&=;;O*$*$O=X&$$$&-;;;;O&=+O*&XX&=;;;;+O$&O-=&$$=-;-=&*XX=++OX.&=-OXO;O*=++=$&*&-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;", +";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;+;+OO+;----=*&&&&&***********************************&&X=O;--;;;;;;;;+;-OOOOOXX***&$$$&&*&XO+;;;;;;;;;O*&*********XOOO-OO+;OOO-+-OOOO-O=*&$$&&$$&&&********************&$$$&&&&&&*&&XOOO--;-OO-+-OOOO--O--+-+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;", +";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;@@;O=**************************************&***X=O-+;;;;;;;;;;;;;;+;;OX****&&&&****XO;;;;;;;;;;OX**********X=-@@@@;+;;;;;;;@;-;+O=X***&&&*&&&&********************&**********X=-+;+;;;@@-;@;;;;;@@;+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;", +";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;@@;;OX**************************************&**X=O;++;;;;;;;;;;+-;@++-=X&**********XXO;;;;;;;;;;OX***********=-;;;;+;;;;;;;;;+;;@;O=X******************************************XO-@@;+-;@;;;++;;;+;;;+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;", +";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;+;@;+;;;;@;;-=X****************************************X=O-+;;;;;;;;;;;;++;@+;OX**&**********XO;;;;;;;;;;OX***********XO;@@+;;;;;;;;;;;;;--+O=X***********&&****************************X=O;@++;@@@;;;;;;;++;;+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;", +";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-=O;;;;;;;;;;;;;;;;;OO+;;;;OO;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-;@;;;;@@;-;OX************&&$$$&**********************X==XX-;;;;;;;;;;;;;;;-OO=X**&&******&&*XO+;;;;-=O+;O*************=O;@+;;;;;;;;;;;;-=XO-O=X*********&&$$&***************************XO-+;;@;;;;;+;;;;;;;;+;;;;;;;;;;;;;;;;;;;;;;;;;O=-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;O=-;;;;;--+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;", +";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;=:=;;;;;;;;;;;;;;;;; :O;;;=oX;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;+;@;;@;;;;=X************& o%#**********************X==$:X;;;;;;;;;;;;+@@+O=X****&&****&****XO-;;;;O:#-;O*************XX=-+@;;;;;;;;;;;O##X-+O=X********&$.:.&**************************X=-;@;;;@@;;++;;;;@;;;;;;;;;;;;;;;;;;;;;;;;;;;;$#=;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;O #-;;;;;=#=;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;", +";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;*%X;;;;;;;;;;;;;;;;+#%=;;O: -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;@@@+;;+++O=X************$%:..*********************X=OX##O;;;;;;;;;;;+-@@O==*&************X*XO;;;;;=%:O;OX************&.$=-;;;;;;;;;;;;Ooo=-@-O=XX**&&&&&$.o $***************************=-@;;@@@@;;;;@@@@;+@@;;;;;;;;;;;;;;;;;;;;;;;;; o=;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;O#:-;;;;;=o=;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;", +";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;---*%=;;+---;;;;;;;;;;+#%=;;+O-;;;;;;++;;++;;;;;+++;;;;++;;;;++;+++--;;;+----;;;-==O-;-+;+-OX&&***X**&&*&&.% &***&&********&*&***&&*=OO=*=-;;;----;;;;-;O==*&*&**&*&&&&*&&$&&*O;;+--O%:O+=*&***********&:#$=O-;;+-----+;Oo:=-OO-OX&*&&$.$&$...&*&$$&&*&&&*&&&&&&&$&&&&$$&*XO;;;O===O-;-==O-@;OO---+;+---+;;+-----;;;;---.o=;;+---;;+-O--;;;;;;;----;;;;;;;;;;;;;;O#:O---;;O=O;;----;;+-+--+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;", +";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;O :##%X;-X#:#O;;;;;;=#: :o=;-.#:X+;$ $#:X= # O;O#:# -;=### =. #:=O#:# =;-&####&;+X#:#$O;-;;-*#:: &&.##::#*.o%o:.& ::: **.# ::#&*&.::: OX :#$-;-.:##O;;@;OX: ::#.&*&#::#&&.#.:##=--*:: %:OO::::.&&# ::#$& %%:#XO+;- #::=-Ooo=- $O= #$$ #o:...#.&& ::#$&.:.*$##$.# :#$.#:o#&*=-+=.###XOO$#:#*-+X##:#=-=#::$O;X# : =;+=###::=;O #:$-;=#::$;;;;;+= :# O;= .-O. -;;;;=#:$::.-;=#=;O.:: -;=#$:# O;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;", +";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;- %# o%=-&%#.: O;;;;O::. %%=;.o.#o=;#%% :o:#:%X;*#$#%X;&%%#O=:%#X-X# #%.-Xo: :% ;=::.#:*O@@-X#o #% & %o::%.$#%:.&.o: :o.*.%o::o &.oo $X o$#oXO$o#.%.O@;-=.%%o#:o$&#% o $ %:#:o&=Xo#.:%#OO## %:&&%o: %:&.%o .XXO;O%o:.%oOOoo=-o#=X::..o: :.$ % &.o# o#$.% *$::$.oo# $#%# &*XOO$:#. *O&o#.o#XX#%#$.=Xo:.#%&-$%%# %.-=::.#%:=O :. oXO :. $;;;;;=:%.#o -X%:-O#:-;;;;O#%# #%&-=%*O$%. %$-=%o##%$+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;", +";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;Oo#=O.%X-#%$X:%X;;;+.o$--:%=O:#==o +#o.-$% -=o&;--+=o.;$%#-;O::O;;-OO=: O#oXO$% -.% . % =@;O$oo %:& %#$.%#& % *$#o$&.o:&.%#$.%#&#%.X==$o:X&%:=:o*X::=@O=X.%o.&.% $%o. %o$#% $.% =#o=-=%:O-X$$:%&&o:.$o:$$o:$X**XO=o#X-*%&O:o=-o =Xoo..o: .$$ %.$:o .:%..%.*$::$.o#.&$:% $&**XOO.%#$XOO#% . %..% O-;- %$OO#o=*%#=Xo -$%.OO#o==o:X$o O#o*O-;;;;;&%.OO oX=%#-O#:-;;;;O#o=O=o:OX%&=:o**o:O=%#O=%:-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;", +";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;X%*-;X%*-:%oo%%X;;;+#o=;+#%O$%ooo%#-#%=;$%&;Oo.;-.::%.;&%.;;O: +;;-.::% =: -;*% -.%ooo% =@@=.%%o%%:& %.* % *.% *.o:**$:o& %.*.%#$o:*=;-$%:%o%:=%%oo%o=-=X&.%#&*.%:$%oo%%o$#%$&.%.X%:O;O%:OO.::o%$&% &&%:&&%:$**&*X*% -;Oo#Ooo=Oo O=:o$*#%o#.$ % $:%%o%%..%.*$::..% $*& o%:.&**=OX %o X=#%%o%%. %$;;;-#:=;-.%*&% -=:#- o=;-.o=$%%oo%#-Xo%:=-;;;;&%X;;X% =%#-O#:-;;;;O#:-;=#o-X%*=%%oo%:-=%&-=%#-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;", +"+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;X%X++X%X-:%.&&XO;;;-#%O;+#%=.% =&XO+#%=;.%$;Oo$+#:..o$;X% ;;O: +;- :. o O:#O+*%#-.% ..$XO@;= %: .* %.*.% & %#*.o:&*$:o&.o.*.%#$o:XO;O&%#&$&==%o* $&==X*&.%#&X.%#$%: ..$#%$*.% X%:O;O%:O$o# :%$&% $&%:$&o:$&***X$o#O;O%.OooOOo#O=:o&=$ #%:. %.$:% .$ %.&$::..% ***$.#oo.**XOOX$#% X#% ..$X %&+;;-#o=;- %X&% ;=: - :=;-.:=&%#*.$=+-= o:=;;;;$%X--*%.=%:-O#:-;;;;=#:-;O#:OX%X=%o*.$=-X%*;=%#-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;", +";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;Oo#O=#%X- %.OO=O;;;- %=+=o%OO::O+--+#%=;$%.;Oo*O:#-=%.+$%.;;Oo ;;O:#=Xo#O %$X#% -$%#$XXXO@+=.:o.$$$* o.* %#*.%#*&#o.& %:&.% *.%#&#%.XXX&%:=OO=O:o*=X*=XX&&.%:..#%.$oo.$$.$ %$*.% =:o=O.%:O:%..o%$$% &$%:$&%o$*&**X$%:&=.%=Ooo=Oo#=$%o&=.. oo. % $#% $$.$.% .#%:..% **&...:% **X==&*.o#X % &XX=$o#=OOO.% O=::O&% ;=: -.%$OX:o==::=OO=;=OO %.;;;;*%#OO#o==%#O.%#O;;;;O#o&OX%#-X%XO#oXOOX-=%&;=%#-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;", +";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-.%:oo%X+=:o::oX;;;;O:o:o%%=+Xoo:o.-#%=;.%X;=o*+#o:#o%=X%$;;Oo ;;- %:#o%&=:%oo% -O %::o O@-=& oo:o#* %.* % * %#&*$oo:o:$&.% *.%#&$:%::#=.%o::#OX:%#::&**&&.%%oo%#&& %o:::$#o$*$%.=X%::%%:O&%::o%:$%#&&%o$&#%: &***$oo::% OOoo=-#%::%o&X:::o $ % $.:%:::.$:oo:%:$ % **&:%:%:$***=$::oo.OX#%:::$= oo::=O#%:ooX-.% ;=o#-O:%::o:X-&oo#o ; o#o#O;;;;O %::o$-O#%:oo:-;;;;O#%o::o=+X%&-X:%#::O=%$;=%#O;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;", +";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;O*$.X&O;+O$..$O;;;;;O$$XX=O;+=$$$O+OX-;O&O;-XO;OX.X=&O-XO;;-XO;;;O&.&X.=-OX* % -;=$...XO;OX&&. # *$ &*$ $*$ $**&$ # $**& $*$ $XX&. .*+O*$.$=--=.. &&***.%:# &**&. # .&. &*& *-OX.$$&*-O. #. #$ $&& .&*&.#.****$o# .=--&&O+=$.X*$==$ $$. $&&$ ## $&$ ...&$.$**&. #$&***XX. $=++X. .XO=*..XO-=...X-;=$=;O&=++=..&X&O;OX$..=;=..$=+;;;;-O$..*O;+O. $XX-;;;;-=$$$.=-;O$O;-=$..X-O&O;O$X-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;", +";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;$#$.o:X+;+OO=O-;+OX*&&*&***********&&******&************=OO=O+;;;;;;;;;;O=*&&****$%#&*******&&&******&*=;;;;;;;;;;OX&***&*********&******$%#$X=-;;;;;;;;;;;++-O=*&&&&$&&**&&&&**&&&&***********&&*****X=OOOO--+-O==O-;;+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;", +";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;=:o%:*-;;;;@;+;@-=X***X********************************XO;+;;;;;;;;;;;;;OX*******$o &*****************XO;;;;;;;;;;OX*********************&: $XX=O+;;;;;;;;;;;;@+=X*************************************=;@;@@-+;@@@;;-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;", +";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-O&*O-;;;;;@;;;;O=************************************X=;@+;;;;;;;;;;;;OX*&******&.$******************XO;;;;;;;;;;OX**********************.$&*&X=-;;;;;;;;;;;;;;OX***X*********************************=-;;;;;+;;@@;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;", +";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;+;;;+-O=************************************=-@@;;;;;;;;;;;;-=******************************XO;;;;;;;;;;OX**********************&&**&X=O;;;;;;;;;;;;;;-=X*XX*********************************XO;@;+;+--;@;;@;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;", +";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-==-;;-OX******&$$**************************XO;;;;;;;;;;;;;;+OX******&$$&********************&&-;;-+;;;;;OX&**&*******&&*********&.$*&&X=-;;;;;;;;;;;;@@OX*&&&&*******************************X=;@;;;++++;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;", +";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;X# O@;;=X***&**$##&*************************=O-@;;;;;;;;;;;;OX*******&##&*******************$:#O;O =;;;;;OX**&#.&****&.#$*******& :$& $XO-;;;;;;;;;;;;+-=&.:.&*******************************X=-;;;;;;;++;+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;", +";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;&% O@;+=X******$::***********************.&X=-;@;;;;;;;;;;;+=********$oo&*******************#o&-;Oo&;;;;;-X**$o#&&.**&#o&*******&:%.&#:$X=;@;;;;;;;;;;OXOOX.o.&********************************=-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;", +";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;----+;;;;----;;;;--++;;;;;;;;;;;;;;;;;;;;+;;;;;+++;;+;;;;;;;;;;;;;;;;-+;;;---;;;;&%#O@-=X&******$::*************&*&*****&.:.XO-OO--;;;;;--OOO=********$:o&***&&&*****&&&&&&*&..X-;-=O;;+--=X***.&& :$&*$.&**&&***&#%.&..&*X=OO+;+-O-+;+=#&==&.$&&&$&&&***&&&&&&*****************=O;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;", +";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;$###.O+& .###O-& .## -;O O;;&X=#O+;;X&+O ##O;; ### O;;;;-$#: ;;X O;X#=;X :$;;;;&%#=O$#:#.X****$:: :: **& ::#.*& **$#.$o%: ==.## X+-&.=:#.XX*****.##:oo&*$###.&****$ ##:.& ###=;O X;X =## &*&#.&:%::& #&& ::# &&#%.& $& ###=;X### O-#%:#&.#.&& ###.&&$# #: $&****************XO;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;", +";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;.# :%=-#%%##% O#%o##o -=%X;;:#Xo -;Oo.-#:.::O;$.*#%:O;;;;$o#$ ;; o=;.%.;$%o#X;;;;&%#=&::#o#$****$:%o##% &.o:#oo$&:o&*.%.$:%:$= o# o:=O#%:#::.****&$:%#o%o&&#%#:o$****$:%: ..o:#% -O% ;$%:##%.&$% $:%##&:%$&#: %%$&#%.$%o$.o: #=+*# #%&O % X.% &.o:#oo$&#%%:o%.$&***************XO;;;;@;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;", +";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;OOO&%X- % OO#%=.%#OO#%=OoX;+::- %=; %=X%#O o&;;;O:oX-;;;;$% ++;;.o=;.%$;.% O+;;;;&% X o .:o ****$:o.&.%:&:o$*.%#&:o&*.%.&.o.=X::=O&o#= %.=.% &***$#o.&.oo&.%:. % $***$:%.&$:% .:%OO%.;.% =$%#&$%#$ %$*&:%$*$$&#%$&#%.$oo..%#$XO;OOO=o#O*%*O=.%.$:% &$o:$ %:$.% $&***************X=-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;", +";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-O ##%X- %=;- %X.%X;-.%=O%*;+#:-=%$-: + %ooo%&;;O#%&+;;;;;O#%:X+; o=;.%$;.%$+;;;;;*%#*#%:oo% ****$::&*$::$o:&*$::$::&*.% $.%.O*% -;=o:O o=O&% &***$o:&*$:%$ %ooo%#$***$:o$*$%%ooo%OO%$;.%O+X%#&$% $ %$*&:%$*$##:%.&:%.$oo.$#%: =-O.##%#O=%*-O.% $::.*&:%.#%.&.% $&&&*************X=-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;", +";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;O#: #%X- %X+- %X.%X;- %==%X;+#:O-:# o=; %#.&.O;-#%.-;;;;;;;O$:oX; :=-.%.;.%$;;;;;;$%#*#o # .****$::&*$::$o:&*$#:$::&& %.$ %$OX% -;=o#=#o=-$% $&**$oo&*$:o$ %# # .$***$:o$*.%% .$OO%.;.%O;X%#&$% $ %$*&#%$$::##%.$#%.$o:$&$ :% X o $o -=%X-O.%.$o:$*&:%$#%.* %.$$$$&************X=-;;;;;;;;++;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;", +";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;=o.O$%X-#%#O=::= % O=::OOo$-&o#-; %%#-;=o#-+---.o -;;;;;;;-O+X%.; oX=:%$;.%$;;;;;;*%#X % $$.$****$:o.& %#&#o$& %#&#o$ :% $ %.OO::OO$%.O#o=O.% $&**$#o.$ %o$.%#$$$.&***$:%$*$:o $*XOO%.;.%=;X% &.%#$ %.&&:%$ %..#%.$#%.$o:.$.$.%o&::OOo -=%&=O$% $#% &.%#$#%.*.% .. .&*************=O;;;++;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;", +";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;O::##%o= %o#:o&O %o#:o$+-#o::%#O;O:%X;;; o:#o==%%:###O;;;;*:#oo=;$%o#o%$; %.;;;;;;$%#=*:%:::.****$:%::o:$&.oo:o:$&#%::o% $.%o.O*o:#o#OO#o==.% $***&.oo:%%o&$#oo::#&***$:%$*&.:%:#oOO% ;.%O;X%#&.%#$$%:#$:%$$oo::%:$#%$$oo..o::%.X:%##%%XOoo:=$%.&.oo#oo$&#%.*.%.. % $*************=O;;;++;;;;+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;", +";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-=. X& O %.. *O- % . X-;;O. =XX+;+#:O;;;+X..#--*X .$O;;;;O. =+;O& $$.=;=.=;;;;;;=.&OO* ###$****$ # $***.## $&&& # $&$. $;-X ..=+-X$O=$ .&****& # . &*$ ###.&***$ &**&. # .--.O;= -;= .&$ .&&.##&. &*.##. #&.#&& $$### XO*. $X.=-X #=X $&*. ##$&&$#$*$ $$.#.&*************XO+;;;+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;", +";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-+-#%X;;;;- %*;;;;;;;;;;;;;;Oo +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;OO--OX&&&&*******&&******&&&****&&&&&&*X=O;;;;;;;;;;-O=X*********&&&&*****&&&&&************&*=O;;;;;;;;;O*&&&&&***&**&********&********&&&&*XOOO-;;;;;;--+-=X**&&&&&**&&****&&&&&**************XO+;;+++;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;", +";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;+.oX;;;;+.o=;;;;;;;;;;;;;;X:O;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;+OXX********************************XO;;;;;;;;;;;@+=X************************************XO;;;;;;;;;;OX**********************************X=+@;;;;;;;;;;+OX*&********************************XO+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;", +";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;OXO;;;;;==-;;;;;;;;;;;;;;-O+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-+@+=X*********************************=O;;;;;;;;;;@;O=X************************************XO;;;;;;;;;;OX**********************************X=+;+;;;;;;;;;;OX**********************************XO;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;", +";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;++;-=X********************************X=O;;;;;;;;;;+;O=*************************************XO;;;;;;;;;;OX**********************************X=O;@;;;;;;;;;;-X**********************************XO+;;;;@;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;", +";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;+;-=X********************************X=-;;;;;;;;;;+;OX*************************************XO+;;;;;;;;;OX***********************************XO-@;;;;;;;;;;-=X*********************************X=+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;", +";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;=X*******************************XX=-;;;;;;;;;;-+OX*************************************XO+;;;;;;;;;OX***********************************X=-;;;;;;;;;;;+=**********************************X=-;;;+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;", +";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;@@+=X*******************************XX=-;;;;;;;;;;--=X*************************************XO+;;;;;;;;;OX***********************************X=-+;;;;;;;;;;;=**********************************X=-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;", +";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;@@-=X*******************************XXO+;;;;;;;;;;+O=X*************************************X=-+;;;;;;;-=X***********************************X=O;;;;;;;;;;;;=***********************************=-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;", +";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-=X*******************************XXO+;;;;;;;;;;;O=**************************************X=O+;;;;;;;OX************************************X=O+;;;;;;;;;;;O***********************************=-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;", +";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-=X*******************************XXO-;;;;;;;;;;;O=***************************************X=O+;;;;+O=X************************************X=O;;;;;;;;;;;;OX*********************************X=-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;", +";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-=X********************************XO;;;;;;;;;;;;O=X**************************************XX=OO-+O=X***************************************=O+;;;;;;;;;;;OX*********************************X=-;;;+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;", +";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-=X*******************************XXO+;;;;;;;;;;;O=****************************************XXX====X****************************************=O+;+;;;;;;;;;OX*********************************X=-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;", +";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;+=X*******************************XXO+;;;;;;;;;;;-=*******************************************XXX******************************************=O-;;;;;;;;;;;OX*********************************X=-;+;;++;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;", +";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;=X*******************************XXO+;;;;;;;;;;;O=X***************************************************************************************=O-;;;;;;;;;;;OX*********************************X=---;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;", +";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;+;;=X********************************X=-;;;;;;;;;;+O=****************************************************************************************=O;;@;;;;;;;;;OX*********************************X=-++++;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;", +";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;+;;=********************************XX=-;;;;;;;;;;;O=X***************************************************************************************=O+;;;;;;;;;;;OX*********************************X=-@;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;", +";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;+-=********************************XX=-;;;;;;;;;;;O=X***************************************************************************************=O-;;;;;;;;;;;OX********************************XX=-;+;@;++;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;", +";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;+-=X*****************************&*XX=-;;;;;;;;;;+O=*&**************************************************************************************=O+;;;;;;;;;;;OX*********************************X=-O-;@+-+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;", +";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;OO-;;;-=X***************************&$$&&X=-;;;;;;;;;;+O=X***************************************************************************************=-;;;;;;;;;;;;OX*********************************X=O=XO-+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;O=-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;", +";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;OX.$*O+X$-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;=&O;X#O;;;;=X************************&&.### $X=-;;;;;;;;;;;-=X***************************************************************************************=+@;;;;;;;;;;;OX******************&..$**&. $*****X==.#*O--+;+;;;;;;;;;;;;;;;;;;;-=. *O;=.=;;;;;;;;;;;;;;;;;X#=;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;", +";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-.:o:o=-#:O;;;;;;;;;;;;;;;;;;;;;;;;;;-;O;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;.%$;.o=;@;;=X************************&#o%%oo#*=+@;;;;;;;;;;;OXX********************&&*****************************************************&$&*******X=+@@;;;OO-;;;;OX******************&#o.**$#o.&&&&*X=X#%.==XO;+;;;;;;;;;;;;;;;;;;-Xoooo&;$o&;;;;;;;;;;;;;;;;;$o*;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;", +";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;=o =*.O-==O;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;.%$; o=;--;OX&&&&*&&&&**&&&&&&******& o: . # *X=O-;;;;;;;;OOOX&&***&&&&&*********&$: &**&*&*****&*********&&&****&&******&**********&&&&*&.:$&&*&&&&XOOOOO+- O+;;-=******&&&&*********&#% **$:%.$&$$$*XX#%$X. XO-+---;;;;;;;;;;;;;;O#:XX.=;=XO;;;;;;;;;;;;;;;;O$%X;-OO;;;;-OO;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;", +";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;X% O-;;-*&O;O& =-;;;;+=X=..OO$.X+;O*-;+=O;;= $-;-= *;;+X. O;;=** X+;;;;;.%$;.o. &OO$# # &$## $&& # .&****$:o.&&&&*$&. .=++X.X .&&## &*&# ## &&&#$*& &#%o#$*&###&&& #*****. .##.&**$## $&&#$&& &****&.###.&:%##$$ ###&=X.$ $$o%#*;O&##.&& .##.&********& % $$$#%...### ** %$$oo#*OO*# XO;X$$. XO;;;;=:#=-;;;=.=;O& &O;;;;;-=. .#:X;X# *O= . .$== XOO.*-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;", +";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;O#%#=-;-:%=- o#oo=;;;;-#%o#:::::%O; %X;Oo$;Xo: #O;*%:#.;+ %#::O; %o#o:=;;;;;.%.;$%::o:&=.%o: $#o#o:$$%%o:%#&****.o#$*****$ o:#:#=O#%o#o: o:o.&$%oo:%#&$% *$%:&#%o#$$:o#o#&&%oo#&***&#%:::%$&.o::%:&&%#&&%o&****&:o#:.&:%::$.:::% X.%:: .o%:&O o:oo$&:%o:oo.********& %### o% . ::o%.$#%.$o%#&=$:::o*; %o#oo*;;;;O.%:*O;; %.O*o::o$-;;;;=#o#:%:*; :#::==## #%:=X%#OX%:O;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;", +";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;+= oo.O-:%==o#X$%.-;;;-#%#+ %#-O%X;$%=;O%*;#%$;;;; %X;;;=%#O$%.; % O.%$;;;;;.%.;$% O$%.X % && %#. % .oo..o:$***&.%#&X**&&$%#&=.% O % O*%#$.%#&.%:.$#%$$%.*$% &$%#&$ % $#%&&%o$&****& %#$.% $#%..:%&$o#&&o:&****&%:$&&& %.&&$$$.:o&.o#=-O:o=-=o:. % $:%#$#%.********& %oooo%o ... %.$#%.*#:&O*o:X&o O %#=$%.;;;;;= oo =;.%$=#:$$:#O;;;;$%#=X#o*;==O$% OOO= o$O&% O*%#O;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;", +";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;+-.oo&-:o= %::#%#O;;;-#oO;$%=;OoX;.%=;-o$;O:o#O;;=oo#O;&%o#:% ;.:=;.%$;;;;;.%.;.oX;$% X o.** %::o%# o:$.::$&*&$ %#&****&.% =+=%:O#:O;=%.=$%:&.% &&$%.$o *$%#&$%:&$:%:o:% &%:&*****&#%$*$% $%%::o%$&o#&&%:$****&#%o $&.%.**&.##%o&.%$-;Ooo=- %:::%#.:o.$ %.********& %# . :o $. :%.$#%.X#:*=$%o#:%#= %&-$% ;;;;;;O&:% O.%$*oo##o:=;;;;.%&OO&%XO=& #% ;;= o.O;$% OXo:O;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;", +";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-=%#O:o=.%# ##X-;;;+#%=;.%O;OoX;&%*;OoX;;O o:O;;O %:-.%: # =; :=; %&;;;;;.%$;.o=;.%.X.%.&$ %:###. %:..::.&&&$.%:$*&&&$ %#=+=%:O oO;=%.=&%#$.%.&&.%..o &&%:&$%#&$:o####$&%#&*****&#%&*$%#$%%####&&%#*&%:&*****&#:%:$ %$*& o:#%o&.%&+;O:o=- %#### .:o.$#% &*******&#% $$.:% .#o::%.$#o.X##&=.%:## $O %$;.% ;;;;;;;-=::=.%$*oo # $O;;;;.oX;O$%X=#o#:% ;=.%#O;;*% OXo:O;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;", +";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;O=O-=o O:o=X%.OOOO;;;;-#%=;.%=;Oo=;.%X;.%X;--;X%$;-+;#%&Oo#-+--; :=;.%.;;;;;.%.;.o=;.%.= %.&& %#.$$$.%:..::.$&&&$#%#.&$ ..%o&=$o.O#:O;=%&O&%#&.%#$.#%$.% $#%#&$%o$$#%.$&$$$%#&*****& %&*$%#$:%.&&$&&o#$ %:$*****$&$o%$.%.&$o% .oo$.%&-;-:%=-X%#.$.$.oo.$#% $..$****& % $$.:% .o: % .#%.X#o$=*:#=OOO; %.;$% ;;;;O==O=#:=.%.=::====O;;;;$%.O=#oX&%#=.%.= o#=O;;&% =.%:O;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;", +";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;=## oo=-:%=O.%: #.;;;;-#%=; %=;O%*;Oo:#:%X;*# :o=; :.::O+$%#&:$; o=;.%.;;;;;$%.;.oX;$% = %.&&.#o:#: .%:$.::.$&&&&.:%: #o#$ o# o:O=#o-;=%&O&%#&.%o#:%#$$o%#%%#&$:%#.$:%##:.$%:&****** %&*$%#&$:%# o&&o%#o%o&****&:##%:&$oo#.#%##o% .%X-;- %#&= %:#:#.oo.$#% $#%.****&#% $&$:% .:o##%:.#%.= %:X=$%: # ; %&;.%.;;;;O :.:%$O.%.O*oo.##O;;;;=:o :o:XX:o :o#.%%#. $=Xoo o%:O;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;", +";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;O*###X--$ O;O.###X;;;;+& O;=#O;- O;;X##*XO;O###=;;=###=;;-$###=;X O;X#=;;;;;= =;= O;X#&=&#.&*&.##:#.$# &$ $&&**&$. :::#.X$### X+-$.-;= =-X# &.%##:#$*& #: # &&.##.&$#::#$$# &******$#&*&#.&&.#:::&&.##.# &****&####$*& #:..## . & O;;+=.#.=*#:#:.$ #.$ #.$ #.&&**&.#.$&$ #.$.#: #$. *=* #&OO&###X;&#=;= *;;;;-X ##$O;X#X;O*#:#.O;;;;OX##.$.=O&# .. # ### =O&##. $O;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;", +";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;----+;;;;;;;---O+;;;;;;;;;;;+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-+;;;;;+-+;;;;;;---OXX****&&&&&&&&***********&&&&&&&*&&X=O+;;;;;;;;;;+=X&.%.&&&****&&*****&&&***&&&$&&&&********&&**&***&&&&&&***&*&&******&*&&***&&&***X=O=O-+;;;;;-OOOX&$$$$$$$&&&$&$$$&&**&&&$&&&&&$&&&$$&XX===O-O==O++-----;--+;---;;;;;;OOOO;;-O-;;-OOO-;;;;;;-OOO;;;;OOOOOOOOOOOOOO;-OOO;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;", +";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;@;-=X******************************&**XO@@;;;;;;;;;;;;=X.:.***************************************************************************X=+@@@;;;;;;;;;@OXX*&&&&&&&******&****&&&&***&*&&*&*X=O-+-;+;;;+;+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;", +";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;@;-=X*********************************X=-;+;;;;;;;;;;;-=$ $***********************************************************************X**X=O--@;;;;;;;;;;-=X*****&*&************&&*******&&***X=-+;;@;+;;+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;", +";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-OX*******************************&&X=O+-+;;;;;;;;;;-OX&**************************************************************************X=O-;;@;;;;;;;;;;O=X*****&&&&&**********&&*******&&&&*X=-+;;;@;+;;;+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;", +";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;+O-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-+;;;;;;;;;;;;;OO+;;;;;;;;;;;;@;O=*******************************&&&X=-+;;;;;;;;;;;--=X****************************&$$*************************&$&&***********&*XX=O;@;;;;;;;;;;;+OXX****&&$$$&******&&&&&&****&**&.$&*XO-+;;-++-;;++;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;OOO;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;", +";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;=#=;=*O;;;;;;;;;;;;OX$&$*-+=-;;;;;;;;;;;;;;;;;;;;;;+#X;;;;;;;;;;;;;*#O;;;;;;;;;;;;;-O=*&****************************&&. *=-;;;;;;OXX-;;;@OX&*************&. .&********$:.&************************&:#&*************X=O;;;;;;;;;;;;;;-=X****&&$##.&&****&$$$$$&******&$##$*=O-++;;+--;;;;;;;;;;;;;;;$ O;;;;;;;;;;;;;;;;;;;;;O .O;;;;;;;;;;;;;;;;;;;;=#.O;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;", +";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;*%X; o=;;;;;;;;;;;;.%oo%:OXo=;;;;;;;;;;;;;;;;;;;;;;Oo.;;;;;;;;;;;;;.o=;;;;;-OO;;;;@;-OX&******&$$*******************&$#o&=O;;;;;;=:#-;;;@;=X************& :%%:.********$%#&************************&%o&***********X*XO;;;;;;;;;;;;;;;OXX***&&$.oo.$&*&**$... .&****&&&$::.*=-+==O;@@;;;;;;;;;;;;;;;; o=;;;;;;;;;;;;;;;;;;;;;=:#O;;;;;;;--;O;;;;;;;;;*%#O;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;", +";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;X%X;=XO;;;;;;;;;;;; %.=OO++X-;;;;;;;;;;;;;;;;;;;;;;Oo.;;;;;;;;;;;;; o=O $-;=#&-;;-O=O=X&&&&**&$#.&**&&&**********&&&&$..&X=OOO+;;OXX-;;OOO=X**X&********$oo.. .***&&&&&$% $**&***********&&&&****&&&o:$*************XO@;;;;;;;;;;;;;O=*&&&&$...:% .$$$$&$.....$&&$&$$&.::.*=OO$#&=O;;;;+O-;;;;;;;;;O :=;;;;;;;;;;;;;;;;;;;;;=:#O;;;;;;;+;;O;;;;;;;;;*%#O;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;", +";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-X.. %X-=XO;-X X-;;;;;.%=;;;;-X+;-==$&O;;+=.$*-;;=$.X+-: O*X-;-X...=+; o=X%:.& %:$=O$ ..&X$. # $$#%: $&.# .$*****&$ #.$$..&$ .$.$=+O*&-;O ....X*&# .*****$%:$&***&.# $&$% &$ $& &*$ &&. $# .&*&$ %:&&& $*&.. &O;;;;;-&..$.O;-$ #.$$&. :o.. . .. $&. .$$. ##..::.&.$X#%#.=-@@;OX.. XO;-=$.&#o=;O&..XO;=*$.=;;;;O=.. :#O=$$$&==XO;=*=;OX...=*%#O=$X;O=..$=OO&$*$&=O;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;", +";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;+&o::o%=-#%X-Xo::oX-;;;; % OX+; %=;#%%#o:O;Xoo##O;Ooo::O-:o::% +O#o#o:=;.:=*%o#. %o#X=#o:o#*.oo::.$:%o#$.oo:% &****$ o::#..:o$.%%::%#-=o:-O %:o%:X& %:oo.&***$:%#.&*&.:::% $$% $:o.$o%$& %$&#%o:o%$&$:ooo%:&&#%:%:&&oo%#%#=;;;;-&o::%%=-*:o:o $.#%:o%o. oo::.:%.$#% $ oo:o.$::. o &#%o#XO;;O*#o#ooX-=#o::%#=O.::o:=;.%o:$;;;;=#%:o%#O&%%: &:#O;&%*OX:%::$X%#= o&;=:%#o#OX%%::o#O;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;", +";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;O::== %X- %XO::XXo#O;;;; %%o%=;.%X;#%#+ %X;#%&;;;-::O;+;-:%=-#:--=OO %&; o==: O-&% O+OXX& %$.%:.$$& % $$#o .::$****.%: %#.#:$.oo.$::O=ooO&%.*$%oX&%:. %o*****$#%% $$:%..o%$.% #o.&&:o&& %$& %:$.%#$:%.& %:$.o#$ %.&o% $:%*+;;;O::==:%==:% oo. % . oo. %:.$.:o.$ % .:% ..$$:: : X= %.X-;;@O %.O=:#=.% OX::=Xo#X.% ; %.=-;;;O o$=.%#O&%:XOX:#O;.oX=#:$=O=*o:.o$OO&%.X %&X%o$X#oO;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;", +";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;=%*-;X%X- %X=oo##o:X;;;;.%#. -;$%*;#%O;X%*;Ooo O;X%*;;;;O: ;; oO+O$$#%$; o==: -;*%#-;-X..#:$.:%#.&$ %#&.oo::oo.****.%o:o%:.::..::*X#oO=o:O oX-*%:X*%o::%:&*****&#:% .%%::oo$$%:%.**&:%&& %$& o$&&%#&%%$*&%:&:%:::%#$o:&=#%X;;;;*%X--#%XX:o::%% :%.&.:o. % $&.:o $ % o $&&&$:o%#*-= %.=;+;;=#:=;O %X oX;O :=.%o#:% ;.oX;;;;;=##=;=:#O$% O;=::O;$oX*%#O;;;Xo%o#O;= %#::% X%:==#:O;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;", +";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;&%X+;X%X- %XXoo###.O;;;;.%=;;;;.%=;#%O;&%&;;O#%:-=%X;;;;-o.;;.:-O#:#o%$; o==o -;*% -;=:%#::$X$#%o & o#&.oo#::#$**** %:::# .#:..:o*X#oO=o:= oXO*o:X&%o#:#.&******&.oo.%%#:##&$%o%.&*&:%&&#o$*#%&*&%#&o:&*&%:&:%:::#.$ooX=#%=;;;;&%X--#%&X:%:#: .o:.$.:o. % $&.:%.$ % o $&&&$:o%#&O= %.=+;+;=#:=;O %* :=;O.:X.%:###X; oX;;;;;=##=;=:#=&%#O;=##==$o**%:=;;;Xo%o#=;=#o:## XXo:O=#:O;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;", +";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;=o#OO %X- %*O::=OOO;;;;; %=;;;; %X;#%O; %X;++;X%X-o#+;++Oo$;; :-$%.O %$-.o=O:#O+&%#-; %.$ o$X$$ %:$ % &$:o.$$$&****.%#.$$$.#o..o:&*#o=Xo:=.% &.%oX*%#.$$$&***&.$&.oo.:%.$$$&$% :% &&:%$.:%&& %&*&o#&oo$&.%o& % &&$$$oo*=#%=;;;;=o:==#%$*:% ....:% ..oo. % $$.:% .:% .o: ..$$:# %#*=.%.=O++@= %$O=::= %&O=#:=X% =O==; oX;;;;;=#:XO$%#O&%#O;=##=X:o&=#:XOO=&%:.% ==$%.====*o:==#oO;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;", +";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;- % %%*- %X-.%#$ ;;;;; % $X.+&%X;#%=;$%*;X#&:o=;&%:$#O-o ;;#:-X%: :%#O.o=O o ==:o.O$%# oo $:##o#&.%o $.%o #:$****$#%# ##$::$.%o&$#o=X%:=X:%:%ooX= %# ##&***$:: #% $.oo# :&$% $:% &#%#:%%&& %&*$% & %##:%:&&#%# : &ooX=#%=;;;;O %:oo%$* oo #:..o: :%o. % $&$#%##o% .#%:#: $::$.%#X$o:.=-@@O&o:.#o&OXo:.#%:X=.%:$#.; oX;;;;;O&o: :%#O&%#O;O o :%o*O*oo. .X%#= % ==oo..#XX%:O=#:O;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;", +";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;=#:: #=-&#=;O&#:: ;;;;;X#:#::O=#O;&#-;O#O;O::#*+;+$#:#O+ =;;= +-&:#. #=X =+=#o&-X:#&O :# # $#:: $&$ :#.&.:::#$*****$#::: $##&$##&& == #=O*.# o:=-= #:#.&***& ::: &*& #:::&&:.&&#:&&#o# :&*$#&*&# && ::###&*$#:::$X =O$#O;;;;;-$#.:%.&$ :::#.$ #:###..:.$&&.#:# :.&$ ::o.$ ==.#*=.:#*-@@+OX#::.O;O&:: . =;=.#::&;X =;;;;;;O$:: $O=#$O;O=#:.$ =;O$#:#*=#.O= #=O=#::#== OO$ O;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;", +";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;+--O-+-;+-;;;;----;;;;;-+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;+------;;;;----;+---;-O=O=OO=*&*&*&&&&&*&&$&&&******&&&&&&&&*&&**&&XO+OOO=.$. % =;;O====X*****&&&****&&&&&&**&*&&&&&&&&&&***&***&&***&**&***X*&*XOO=O+;--+;;;;+X*&.o#.&&$$..$$$&$$$&&&&$&&&&&$$&&&&**&$$$&&*=O-O=OOO==O-;@;;-OOO-;;;OOOO;;;;;OOOOO;;;;;;;;;;;OOOOO;;OOO;;;OOO=;;;;;OOOOOOOO;OOOO;OOOOOO;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;", +";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;@@@@;-=X************************************X=+@;-Xoo%% XO;@@@@@-=XX**************************************************X==-@@@;;;;;;;;;;-#:o%o.$***&&&&&&***************************X=O+-;@@;@@+@;++;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;", +";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;@@;--OX*********************************&**X=O-+;O* .=O+;@;+-;;-=X***********************************************X*XX=-;;;;;;;;;;;;;;;O$ $$&************************************X=+@;;;@;;+-@;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;", +";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;@;--O=X**&*****************************&***X=O;@+O==OO;@;+;;;;-+;OXX*********************************************XX=O-;-+;;;;;;;;;;;;;;OX**&************************************X=O+;@;;;;;-+;;;;;+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;", +";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;+;;;;-=X**&********************************&*X=O;++@@+;;@;--;;;;;;+O=X*******************************************X==-+;@@;;;;;;;;;;;;;;;O=XX*************************************X=-;;@+-;;;;;+-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;", +";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-=$X=O+=X-;;;;;;;;;;;;;;;;-#O;-O+;;;;;;;;;;;;;OO;;;+-+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;++;+@@;;OX**********$ .***************&&&*X=O;@;++;;+;;;;--;;+;@;O=X***************************************X=O-;@;+;;;;;;;;;;;;;;;+O=XX*************************************X=O;@;;+-;;;;;;+;;@;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;", +";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-$:o:o=-#:=;;;;;;;;;;;;;;;;Oo=;*o=;;;;;;;;;;;;O::-;;-:.;;;;;;;;;;;;;;;;;;;;;;;-O-;;;;;;;+;;@@;;=*&*********.%%%%%%% **************&$&***X=-;@;;;@;+;;;++;;;;@;+-==X**********************************XXX=O-@@@;;;;;;;;;;;;;;;;;O=XX**************************************X=O;;;;++;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;", +";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;Oo#X$ =-XXO;;;;;;;;;;;;;;;;OoX;-X-;;;;;;;;;;;;O:% ;;Oo.;;;;;;;;;;;;;;;;;;;;;;+X =-;;;;++;@;OOOOX &&&******$..#%:..$&***********&&.:.&**&*XO+;;@;@;;;;;;;;;@;;;;+OO=XX****************************XXX==O-;;;;;;;;;;;;;;;;;;;;;O=XX***************************************X=+;;+;;;;;;;;+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;", +";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;X%.O;;;-XXO;O=X.=-;;;;;-=X=.o=;-O+;;O*=O+;;;;;O:%o=;-o.;;O=XO+;-$O;O=O+-=$$*OO#%#XOO$.&X=O=$..$ %: .&********&.%#&**&. .$&&. .$$#%# &$. $=+@;-;;;;+++;;;;;;;;;;;;O==XXX**********************XX===O-;@@;;;;;;;;;;;;;;;;;;+O=X****************************************X=O;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;", +";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;O#%.=-;-#%=-.oo%:O;;;;+=:ooo%=; %=;-:ooo=;;;;;Oo#:#+-o$;-:o:%X;$% ;=: -=:o::==:%o#O.o:oo.=.o%o %o# &*********.% &**.:oo%#$.oo::.$%%o#$.oo:o$O;+;;;;++;;;;;+;;;;;;;;;;-OO=XXXX**************XXXX==OO-+;;;;;;;;;;;;;;;;;;;;;-O=XX****************************************XO-;;;;;;;;+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;", +";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;+X#%:X--:%==o#=$%.-;;;-::=- %=;.%=;#oO-::-;;;;Oo*X%*Oo$; %=+#:-X% ;=: -$% OOO-.%$--O=O&% =.%#&=$%#&X*..$$$$*** % &**$ $.:o$.%#.$&&.% ..:o %oX-+@;;;+;@;;;;;;;;;;;;;;@@@;OO===XXXXXXXXXXXX====OOO-;@;+;;;;;;;;;;;;;;;;;;;;+O=X*****************************************X=O+++;;;;;;++;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;", +";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;+O %%X-:%= %:##o#O;;;=o$-;OoX;.%=-#o:#ooO;;;;Oo*+::*:$+::##o%=X% ;=: -=:% =-;.%.;;OXX %#=.%.OO.%#=X.::::: *** %#&**&. ::$.o%#.$*.% $.%%#:oo&=O;;;;+;@;;;;;;;;;;;;;;;+;@@+---OO=OOOOOOOOOOOO-+++;;;;;;;;;;;;;;;;;;;;;;;;;O=X*****************************************X=O;+-+;;;;;;++;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;", +";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-Xo O#o=.%::::&-;;;=%$+;=o=;.o=-oo::# -;;;;Oo$;Oo:o.+:o::#.O*o ;=o --=#%oX- %$;O o::%#=.% O-$%#==.#::::.***.%#&*&.:oo%:$&.:oo.$.% *.%o:::#&*=O+;;;;;;;;;;;;;;;;;;;;;;;;;++;@;+-----;;++;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;+O=XX*****************************************X=O;;+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;", +";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;O=O-Oo O:o=X%$O-OO;;;;O: O-$%=; %=;::-;;+;;;;;Oo.;;.%%X;#:-;;++&% O$% ;OOO$%#-$%.-X%#O*% =.% O-$%#XOX&&$$$&*** % &*&#o..::$$.$ %:$.% $.oo...$&$.*=-;;;;++;;;;;;;;;;;;;;;;;;;+;;;@@;;@;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-==XX*****************************************X=O-+;;;;+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;", +";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;=# &:oX-:%=O %#& $;;;;- % o%X;.%X;&%:=&.-;;;;Oo*;;-#%$;=%:X$ O=o: :% ;&#& %.-$%:==::X#%:X.% O;&::.X==X*******.%#&*$#% #oo..: #%#$.%:.$ o:. :$.% X=O+;;+-;;;;;;;;;;;;;;;;;;;;;;++;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;+O==X******************************************XX=O--;@;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;", +";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;O&:::&-- #=;O o:o$;;;;;O ::##=;*:O;;=#:o#+;;;;-#=;;;X:=;;O:::#O-$::# &;=:o: O;-.:#-=oo .: =:&-@O$::.O=X*&*****.: &*&$#o: :#.ooo#$&$#o#$$ ooo#&.:#*X=OO;;;+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-O=XX*******************************************X=O-+-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;", +";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;--O-+;;--+;;-----;;;;;;---;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;+;++;;+----;;+-O-+;;;;+++;+++;----+;;;O==O+O=*******&&&***&$$$$$&&$$$&&*&&$$&*&$$$&&&$&&*XX=O;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-O==X********************************************X==+;++++;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;", +";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;O=X********************************************XX==O-+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;O==X*********************************************XX=O+@;;++;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;", +";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;++;;-=XX*********************************************X==O-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;+-O=XX**********************************************X=O-;;@;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;", +";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;--;;O=**********************************************XXX==O-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;++-O=X************************************************XX=-+;;@;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;", +";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;++;-=X************************************************XX==O--;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;+-OO==X*************************************************XX=O++;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;", +";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-O=X************************************************XXXX=OO--++;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-O==XX***************************************************X=O-;;;;++;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;", +";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-O=X***************************************************XX==OO---;;;;+;;;;;;;;;;;;;;;;;;+-+;--OO==XX****************************************************X==-;;;;;++;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;", +";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-OX*******************************************************X====OOO---;;;;;;;;;;;;;;++--OOO===XX*******************************************************==O+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;", +";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-=X********************************************************XXXX====OOOO-OO----O-OOO=====XXXX********************************************************X=O+;;+++;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;", +";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;O=X**********************************************************XX*XXX=============XXXXXX************************************************************X=O;;;;;+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;", +";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;+++-=X*****************************************************************XXXXXXXXXXX*****************************************************************X=O-+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;", +";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;++;;O=X*******************************************************************************************************************************************X=O++;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;", +";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;O=X*****************************************************************************************************************************************X=O;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;", +";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;@;O=****************************************************************************************************************************************X=O-;;+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;", +";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-=X**************************************************************************************************************************************X=OO+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;", +";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;+;+;;O=X***********************************************************************************************************************************XX==-+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;", +";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;@;;;;;;O=X**********************************************************************************************************************************X==O+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;", +";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;+@;;+@;;@;O=X********************************************************************************************************************************X==O-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;", +";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;--;+;@;+-O=X*************************************************************************************************************************&&&*X=O-+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;", +";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-O-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-O+;;;;;;;;;;;;;;;;;;;OOOOO=;OOOOO+;-OXO--OOOOOO=*&&$.$&$$&********&$&********************&.$&******&$$$$$$$$$$$&***&&&****&$&***&&$&************************&$$********&*&$$&XO-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;OOO+;;;;-O-;;;;;;;;;;;;;;;;;;;;;;;+--;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;", +";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-O-;;;;- :#O;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;.#-;;;;;;;;;;= O;;;;;;&# ###.O-O&#&=X$$$$XOX.. #: $ #$&*******$:$******&......$******$%: $$$$**.###:#######.***$#.***$ :.&**& #$*&&&****&..$...$********$: $****&&$$$$.:.XO-;;;;;;;;;;;;;;;;;;;;;;;==XO;;;;O==O==OO;;;;;;;;;;;;;;;;;;;;XX+O o#-;;;-$#O;;;;;;;;;;;;;;;;;;;;;;;O O;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;", +";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-==XXXXX==O;;-XXO;;;;;;;;;;X%X;;;;=#$#=;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-#:O==O-;;+O=O#:=O=O+;;.####:o#### ==& : $ ooo% =$%%%o ..##$&&&$$$$. %...$&**$:%%o%o.******$.oo#.o **.#::%%:%%::#$***.%.***.%:#&$$.:o.. #.****$::.#:#.$***$....o: ..$&$$.... o &X=O;;;;;;;;;;;;;;;;= X;= #%.;O& # # #$-;;;;;;;;;;;;;;;;;;+ #+O#o O;;;-#:====O+;;O=O-;;;;;;;;;O==.oX===-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;", +";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-#oooooo%%X;;+#%.=+;;;OO-;;=o$;;+-=#:X+;;;;;;;;;;;;;;;;;;;;;;;;;;;;-&o:oo%% ;;+#ooo:ooo#O;;+O=== :====OO&:o%o#**&$##X.#::o##.#: .&.::::%o%o%o#$&&$. %:$******$...o %.**$ # %o#o: #.$*$$ %.$$$.## $.ooo%oo%:.****$o %# o:.***.oo:#%%%o%.$$#::#oo%ooo:=;;;;;;;;;;;;;;;;X%$;=::$#.;O#%######o:O;;;;;;;;;;;;;;-==X=##==.$O;;;-$o:ooo%#+;;X%#=-;;;-OO;;.%o%o:oo:O;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;", +";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;+-OOOO-OX%X;;+-$%#O;;- :=;;=o$--=#%#-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;+X:#-++=:&;;++- :O-+;;;;;;$%ooo%::%#O-X$.:.$*$$.##X& :: ##%o%o$$ ## o.$$$&&&$$. %.$&****&$.%$$.o#$$*$oo:%o#o%#%#&$.#oo::..o:.$*$$.: :.$****$%o#$$.%.&**$. o: .$$ o$OOO-;;;;;;;;;;;;;;;O$:X;O:.$ =;O#:XOOOOO##-;;;;;;;;;;;;;;X:ooo%%oo::X;;-=: ---=o&+;;-Ooo=;;;=:.;;--$:=O----;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;", +";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;*oX;;;;-X#=;;O::=;;=o .:o:=+;;;;;-OO=O=-;;;;-OOOOOOOO==O;+=:#=X-- :-;;;+X%::#-+OO-;;.#OO.#O=.:=O.::%:##oo::.=$%%%%%:. # o$&$$ ::oo$&&&&&&$. %:..$&**&$:.%$$ o.#$*.: o o : $$o#%# #%. o.$&&$.#o:o% .$&&&.o%.&*.o#$**& .. %####.&&$$. o:%*;;;;;;;;;;;;;;;;;;;O#:=;O:#=O-;O#:=;;;;=:.-;OOOOO==OOOOO;--OO- #-OO+-;-=:#*$OO#:O;;;;-O#&;;-*%=;;-=%:::=O==-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;", +";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;X%X;;;;;+--;O o*-;;=oo:.-+;;;;;;;.oooo%&;;;;Xoo:oooooo:X;O:#O % Xo +;;;=:% X:o#::-;;=%ooo%ooo#=O$ # $ :$XX==$%#::#:.:#.o$*&$:: #o.$&&&&$. %%:o%#.&*$#%.o$.%..% $$#oo:%oooo:.&&$.%.$.%..oo.&$.:%% %oo:.$&&.o#$&&.o#$&*$:oooo%:##.*XX&.:.$%$O;;;;;;;;;;;;;;;;;;O##=;O.o&;;;O..O;;;O$o$;;&o::oo::oo:X;;-##- #-##O;;O:#= %.&%.+;;;;;+--;-X: +;-=:%#.:o#::=;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;", +";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;X%X;;;;;;;;-$o.O;;;=oX++;;;;;;;;;++++Oo.;;;;=##########X;+--;+=:%#-;;;-::-+ oo$+;;;- #--$:--*:=O$: : $.:=-=&X$o ::##.:..o$*&.:# #% $&&&$.#%: $$.oo.*$:#.% o#$$#:$... % .....$*& o$*$o.$.%.&.%## o..%#$**.%.&**$o#$&&$. :# .$&X==X #$Xo#O;;;;;;;;;;;;;;;;;OXo$O;;=o.O;;;;;;;;-=:#O;;=##########O;;Oo + #+.o=;;+-O-+=:%#O;;;;;;;;;+=::O;;O#:XO*:%.O-+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;", +";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;*%*;;;;;;-O o:O;;;;=oX;;;;;;;;;;;;;;;X:=;;;;;;++++++++-+;;;;;;+.%=;;;;-X--#:: ;;;;;&:o..:o .:o$=&: :%:#:X=$%$$o%%o% .o$.o$*&$#o#%o $&&&$ % ...$$.% *.%..%o:$$..%.#%o%ooo%%ooo.*$:#$&.o.*$#.$#o.:#%#$$:o$**$:$**&.%.$&*$.#::%o .$*=OO=$o#:% =;;;-=X=O;;;;;;;;;O#o=;;;O#:XO;;;;;;;= %&-;;+---------+-;-.o=- #-=: -;;;;;;- oX-;;;;;;;-O*o:=+;;-*OO:o:#+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;", +";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;+O======$%X;;;-==&:%.O-;;;;X%*+;;;--+;;;;;;;+ :O;;;;;;;;;;;;;;;;;;;;;- oX;;;;;;;;#:;=#;;;;;.:%######:o -&o:#.&.o.$ :&&:#:o# .o$.o$X*&$ #:o.&**&$$..%oo $.%.* o. %:$&.%.o#$$.o# . :.$$&$.%.$$#%.*&&&$:#.:%o$$.%#$**&$&*&$:o$&*&.oo o%%:.&=O-O=& %XO;;;O#o%.O;;;;;;;O$o$O;;;O=o#=;;;;;O= o.O;;;;;;;;;;;;;;;+=: -; --&:=+;;;-O oX-;;;;;-O=X#%#O-;;;;;-.oO=#-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;", +";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-:%%oo%:o%*;;O.#oo:=-;;;;;;-##XOO* =;;;-OOOO#oXO-;;;;;;;;;;;;;;;;;O=:o=;;;;;;;;-##-O=-O+;;+*#++++--*:O;&%:o.&$:%%% *&# :: #: $ :*=X*&. % $&***&&.## #% o:$*$ %o.&$.%...$* :%%o% .$$*$:o...:#$****$#o %o...#o.&****$$.o%.&*&&.o : :%$=O-O==X#:=;;;;X:X.:=;;;;;;;=::=;;;;;O$%.;;;;OX#% =;;;;;;;;;;;;;;;;-#:O;;O=;;O:#-;;O=#o=-;;;;;;X#:%:*--;;;;;;O#:==XO=O+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;", +";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;+-OO--OO=#=;;-#: O--;;;;;;;+O:%ooo:#O;;; %oooooooO;;;;;;;;;;;;;;;;;.%#O;;;;;;;;;;Ooo::o% ;;;.#+;;-O= #O;#.X:o# ..:ooo:::..##=O==$:% $&****&&&.%%:oo:$&* :o#%...::$*&$. ##o #o%#.$$o..o%o.$****&$:%#. %%:.$***** :%o.&***&$ o::o.&. &=--O=.o:=O;;;;=:.:#=;;;;;;;O$=O;;;;;;O$X;;;;=:o&O;;;;;;;;;;;;;;;;;+OO-;;-=;;-OO-;;.%:=-;;;;;;;=o =--;;;;;;;;+=:%#::%#+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;", +";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;+-+;;+---;;;;;;;;;;;++++-++++;;;++++++++++;;;;;;;;;;;;;;;;;..-;;;;;;;;;;;;;O==O;;;;;=$;;;O %o.-;O;-O= ######$X&**&$#. %:*O;+O*#.&&***&***&$$. .$$&**$#..#%%oo &*&#oo##$$$$ oo$&.$$$ .$******&$$$&$ .$&******$#.$&******$.. $X==X=O---O..=O;;;;;OXo:=-;;;;;;;;;;;;;;;;;;;;;;;;-O=O;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;$$-+;;;;;;;;---;;;;;;;;;;;;+OOX&XO-+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;", +";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;--OO-;;;;;;;-O-OOO=OOO---O===*XO-;@-O===XXX*&***&&&********&$&&$$$$$&**&$$$$$&***$$$&******************************&&&******XXXXXX=OO-O-+;++;;;;;;;;;;;OOOO;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;", +";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;+-+;;;;--+O;;+;;;+-OO==XXX***&**&***********************************************************************XX===OO--;+;+;;+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;", +";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;++;;-;;;@@;;;;--O==XXX***************************************************************************X==OOO-+;;;;;;;++;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;", +";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-OO;;-O-;;;;;;O=-;;O-;;;;;;;;;;;;;;;;;;-+;-----;;;;;;;;;;;;;;;;;;-OO;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;--+;;;;;;;;;;;+++-;;++;;;-O;;--OO===XXX&&&***********************&$$************&$&&$..$****&$$****************X==OO-+;;;;;;;;;+-=O;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;---;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;", +";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;.X#&$ =#$;;;-O= %*;-#X;;;+& .. OX .O;+#&+X # =;;;X.-;;;;;;;;;X#XO== .O--;;-=+;;;-&=;;;;;O======-;;;;;;O:=;;;;;;;;;;;+-++++++;;-=X=-O=X*=OOO=X&.&***&*******************$#$************$#$$##%.&***$: ***************X=O-O--;O &O;;;;;;O:=O. =;;O$$O;;;;;;;;;;;;;;;;;;;;;;;;;;OX =;;;;;;+.X;;-=#.-;;;;;;&.-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;", +";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; o: o#Oo&O;;O#%%XOOO:$O-;-#ooo%=#o::%&;+#.+#o#o:#%$;;;#:O;;;;;;;+O X :#o%::.;;Xo=;;;O:.+;;;;X%%o%%:=;;;;;;Xo=;;;;;;;;+;++;;;;--+;;O&o*OOX#o*O--O=$%$*&&&&&&***&&&&&&&&&**&&.%.$&*****&&&$$.%.$ %# &**$.% ....$&&$..$*X====OO-O=XXo *X*O;;;-o&=:o#%##%&;;O:#O;;;;;;;;O=XX=XXXXX*O;;;;;O=#oX;;;;;;O:.O-O:o:=;;;;;;$%XOOO+;-X=-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;", +";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;O$#:o:. o# $OO&o&-:X:X: --#%::%= %::%*;&o:=:.+# +#.;;;# -;;;;;;;O#%## . ::* O;;.:-+-+O:#O-;;;OX&=*o.-;;;--O.:OO-O -;;;;;;;;@;;++;;;O$o$OOX o$O-OOX.o.$$...$***&$$.$$$.$&&&&$ % .$&&**&$. o # .&&&.:ooo%%%.&X$:o $X=O===O;=:o%oooo%$;;O.%#$%$=o$=:&;;=o$O;;;;;;;;.:ooo%o%%%:=;;;;O=#oXO;;;;-O*o:#=+X =-;;-===X::#o +;O:#+;;;O =-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;", +";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;O#:%%o#:##%:.X#:o%=:X:X. =-#.OO:X#$OO:&; oo*:#.::$o.;;;##;;;;;;;;+=#% X#:oo##X;;$#;=#.#oo:$;;;;;O$o&-;;;;O#oo%oo=Oo#+;;;;;;;;;+++;;+=.o$OOX o$O-=&$ % ::%#*X&...:.$. $&*&$ % .$$&&&&$:%oo%%%ooo:$&&.#o . :o.X=X. % XOO= :=;O=Xo.XX=OO;;X#oo$o# %# %&;;=:&;;;;;;;;;X.$X== o.=OO;;;O&o:XO;;;;;Xo%%::&O=OO;;;.%o%%oo#X-+;O:#-;;;O#:O;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;", +";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-=::#o o#= =-=#% *:=:*=:*O#%o%o= %%o%&;+#*+#o#oo#o.;;;# ;;;;;;;;;- o#...$. .O;;.#;&###o:O+;;;;O %.==O;;;O# o.- o-=%X+;;;;;;;;;+-;;-=$o$-OX o&OO*::%%oo# %.==*#% ::..o#$**&$ %: ..$&&&&. #o .&&.#o .. %.&=O==*.#=+;=o#O;;=#:#o$===O;--:$=::#o:#%*;;=:*;;;;;;;;;;;;;=##XO;;;;;-.%#=O;;;;;;+-$#OO.#:% ;;;-+---=#.-;;;-##+;;;-=: -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;", +";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;=o. .=:#o=:$;;O:%.:#=:&O:#O:.-X$. O-#$;+##=:X+#&+#$;;+#.+;;;;;;;-=:##%:%%o%% ;;. ;;;;-:#;;;;+O.%o:%o.=+;-+=o*+=%=-#o+;;;;;;;;;+-;;+O&o*OO*#:&OOX . : $. : *=O=.o..o. %.&XXX&.%ooo .$&**$.o. % %.&*& o..o: #%.=OO-OOOOO;= oXO;O$:% #%##o ;;Oo.&%&=o$=:&;;O:&;;;;OOO;;;;;O :XO;;;;;;=: OO;;;;;;;;;##+O##X&O;;;;-O==O#:=;;;-.#-;;;;-.:O;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;", +";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;O=X%&=&=o$oX;+&#:o%*=:*##O-:*-#oo:%&+:X+=:% : -# -:.;;;# ;;;;+ #;-#ooo%$-OO-$#;; #-O;;-:#;;;+O#%:XOO*o:-;;+&:-;=%=+=o=;;;;;;;;;;;;;+-=#=-O&: XO-O=X$o$X$o#&=--O*# $..#o.X===*.% #oo &XX$ %. % .% &XX*&*&. %%.*=--;;;;;;=$%.=;;&o#=& ooXO++O=o%.:.X:.*oX;;O:&;;;;O#.;;;;;-: O;;;;;;;-#:X-;;;;;;;;O:.;-+++;;;;;-O o%%:o -;;; #-OO-;;=o$-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;", +";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;X:%oo%%=#o:=;Oo#:$O=:% oX+-:$-#o##%$+:$=#%&+$%o%%o%$;;+ +;;;O# ;+X #:#O&#. -;;;X%#*;;O:.;;;-#:OO=O--&o=;;=##+;XoO;O&=---;;;;;;;;;;;;---;O&o =-++OO&%X=$#*=O+;-=XXX&.o.X=OOOX.% &$.o#*=X.:#. %.$.:.X====X& %#$=O++;;;;O=.%#=;;;=.=.%#%=-;;-#:%&=:%%%%o%X;;O:&;;;;=oX;;;;;-#.-;;;;;;;+-#%.O+;;;;;;&oO; ;;;;;;;=::=--=::O;;;.o==:X;;O:#-O=OO-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;", +";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;+Oo&.#=O&%$O; .$#X;-O=o.O;-:$-##.$o$+#.++#$;$O+#.+XO;;+##-;;- o&;; : o*+ .X#;+;;X%#;;;&:O;;;;-O=%%:=O.:=;-Xo=--X:-;;;;X#O;;;;;;;;;;;;;;;O=#:*O-;;;-Xo=-O===O+;+OO=X.:#*O----=.o.X=X$*==*.o.*.o.&$o X=OO=&.:#$=O-+;;O==&:%$OO;;;;;=o.O:=;;;--Oo*=.X=:&=$O;;O: O;-O :O;;;;;-#oXO;;;;;;;++&o#O-;;;;;##+=o=;;;;;;; o=-;;----;;;=: .#O;;-* -*o%#O;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;", +";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;O o%$OO:o:&O;;&:X-O=::=;;-:$-#o::%&+#$;+:$;;;;#$;;;;;; o$OO % -;; : :&X:=$#O:O;&%*;;Oo ;;;;;;O#.O#:=o#-;O :==Xo#+;;;;.% O;;;;;;;;;;;;O=$o:XO+;;;;;=% =XX #O+;+-=*.ooXO+;;;-=.%.=OO=OO=&% &X.%.XX.%XOO=&.%:$=O+;;;= #%%:XO;;;;;;;*o&O&=OO-;;Oo*;;;=o*;;;;;-#o&O=#%*-;;;;;+O:%.=O;;;;;;;+Xo#O+;;;Oo$;=o -OOO+;;*o$OOOO==;;;;-$oo +;;;--O O:$;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;", +";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-= :#%.:#=.o.O;X:X=:% O+;;-:$- #XX*O-#&+-:.;;;+: ;;;;;;-.%%%o*-;;; #$=:#+.#X#-;=:=;O%#-;;;;;;;=%#:%o*-+;X%XX%%:X-;;;;O&%.;;;;;;;;;;;;=o%:O-;;;;;;;= %%%%o:O;;;-= % =O;;;;;+O$%$=-----OX$*==.%$=-O$O;;=:% $=-;;;;;O:: =OO;;;;;;;;O oo:#%oO;O=oX;;;Oo=;;;;;--#%%%:X-;;;;;;;-O.o%X;;;;;;;;-=o#-;;; :O;;X:%%%oO;;-.%o::o%.;;;;;O .-;;;;;;;.:$:=;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;", +";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;=::=-Xo O+- :=;X##o#XO;;;;-#&;-+;;;.%:O-#%=;;;+ .;;;;;;;+O*O-+;;;;;= ##+;=o:X;;;;;;-O+;;;;;;;;+O=&O-+;;;O=--=*=-;;;;;;O. ;;;;;;;;;;;;-==-+;;;;;;;;-O=====O-;;;;O==O;;;;;;;;-X#*O-+++;-O==O=*#=-;;;;;;=#*X=-;;;;;;O=OO;;;;;;;;;;;;OO=&$=O-;=::=;;;-:=;;;;;;--OX=--;;;;;;;;;;--O-;;;;;;;;;-X=-;;;--+;;+++++++;;;+O=&$=--;;;;;;;;;;;;;;;;O#%X-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;", +";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;+OO+;-O-;;;--+;--OO--;;;;;;--;;;;;;++++;+++;;;;;;;;;;;;;;;;;;;;;;;;;O-++;;;;+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-=O-;;;;;;+--+O==O;;;;;;;-O--+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;----;;;--+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;----;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;", +";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;--+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;", +";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;", +";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;", +";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;", +";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;", +";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;", +";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;", +";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;", +";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;", +";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;", +";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;", +";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;", +";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;", +";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;", +";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;", +";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;", +";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;", +";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;", +";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;", +";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;", +";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;", +";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;", +";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;", +";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;", +";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;", +";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;", +";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;", +";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;", +";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;" +}; diff --git a/hacks/images/pacman/eyes-d.xpm b/hacks/images/pacman/eyes-d.xpm new file mode 100644 index 00000000..4771be39 --- /dev/null +++ b/hacks/images/pacman/eyes-d.xpm @@ -0,0 +1,70 @@ +/* XPM */ +static char * eyes_d_xpm[] = { +"64 64 3 1", +" c None", +"+ c #DEDEDE", +"# c #2121DE", +" ", +" ", +" ", +" ", +" ", +" ", +" ", +" ", +" ", +" ", +" ", +" ", +" ", +" ", +" ", +" ", +" ", +" ", +" +++++++++ +++++++++ ", +" +++++++++ +++++++++ ", +" +++++++++ +++++++++ ", +" +++++++++ +++++++++ ", +" +++++++++ +++++++++ ", +" ++++++++++++++++++ ++++++++++++++++++ ", +" ++++++++++++++++++ ++++++++++++++++++ ", +" ++++++++++++++++++ ++++++++++++++++++ ", +" ++++++++++++++++++ ++++++++++++++++++ ", +" ++++++++++++++++++ ++++++++++++++++++ ", +" ++++++++++++++++++ ++++++++++++++++++ ", +" ++++++++++++++++++ ++++++++++++++++++ ", +" ++++++++++++++++++ ++++++++++++++++++ ", +" ++++++++++++++++++ ++++++++++++++++++ ", +" +++++#########++++ ++++#########+++++ ", +" +++++#########++++ ++++#########+++++ ", +" +++++#########++++ ++++#########+++++ ", +" +++++#########++++ ++++#########+++++ ", +" +++++#########++++ ++++#########+++++ ", +" ######### ######### ", +" ######### ######### ", +" ######### ######### ", +" ######### ######### ", +" ", +" ", +" ", +" ", +" ", +" ", +" ", +" ", +" ", +" ", +" ", +" ", +" ", +" ", +" ", +" ", +" ", +" ", +" ", +" ", +" ", +" ", +" "}; diff --git a/hacks/images/pacman/eyes-l.xpm b/hacks/images/pacman/eyes-l.xpm new file mode 100644 index 00000000..b636a6cb --- /dev/null +++ b/hacks/images/pacman/eyes-l.xpm @@ -0,0 +1,70 @@ +/* XPM */ +static char * eyes_l_xpm[] = { +"64 64 3 1", +" c None", +"@ c #DEDEDE", +"# c #2121DE", +" ", +" ", +" ", +" ", +" ", +" ", +" ", +" ", +" ", +" ", +" ", +" ", +" ", +" ", +" @@@@@@@@@ @@@@@@@@@ ", +" @@@@@@@@@ @@@@@@@@@ ", +" @@@@@@@@@ @@@@@@@@@ ", +" @@@@@@@@@ @@@@@@@@@ ", +" @@@@@@@@@@@@@@@@@@ @@@@@@@@@@@@@@@@@@ ", +" @@@@@@@@@@@@@@@@@@ @@@@@@@@@@@@@@@@@@ ", +" @@@@@@@@@@@@@@@@@@ @@@@@@@@@@@@@@@@@@ ", +" @@@@@@@@@@@@@@@@@@ @@@@@@@@@@@@@@@@@@ ", +" @@@@@@@@@@@@@@@@@@ @@@@@@@@@@@@@@@@@@ ", +" #########@@@@@@@@@ #########@@@@@@@@@ ", +" #########@@@@@@@@@ #########@@@@@@@@@ ", +" #########@@@@@@@@@ #########@@@@@@@@@ ", +" #########@@@@@@@@@ #########@@@@@@@@@ ", +" #########@@@@@@@@@ #########@@@@@@@@@ ", +" #########@@@@@@@@@ #########@@@@@@@@@ ", +" #########@@@@@@@@@ #########@@@@@@@@@ ", +" #########@@@@@@@@@ #########@@@@@@@@@ ", +" #########@@@@@@@@@ #########@@@@@@@@@ ", +" @@@@@@@@@ @@@@@@@@@ ", +" @@@@@@@@@ @@@@@@@@@ ", +" @@@@@@@@@ @@@@@@@@@ ", +" @@@@@@@@@ @@@@@@@@@ ", +" @@@@@@@@@ @@@@@@@@@ ", +" ", +" ", +" ", +" ", +" ", +" ", +" ", +" ", +" ", +" ", +" ", +" ", +" ", +" ", +" ", +" ", +" ", +" ", +" ", +" ", +" ", +" ", +" ", +" ", +" ", +" ", +" "}; diff --git a/hacks/images/pacman/eyes-r.xpm b/hacks/images/pacman/eyes-r.xpm new file mode 100644 index 00000000..65f6e4b3 --- /dev/null +++ b/hacks/images/pacman/eyes-r.xpm @@ -0,0 +1,70 @@ +/* XPM */ +static char * eyes_r_xpm[] = { +"64 64 3 1", +" c None", +"@ c #DEDEDE", +"# c #2121DE", +" ", +" ", +" ", +" ", +" ", +" ", +" ", +" ", +" ", +" ", +" ", +" ", +" ", +" ", +" @@@@@@@@@ @@@@@@@@@ ", +" @@@@@@@@@ @@@@@@@@@ ", +" @@@@@@@@@ @@@@@@@@@ ", +" @@@@@@@@@ @@@@@@@@@ ", +" @@@@@@@@@@@@@@@@@@ @@@@@@@@@@@@@@@@@@ ", +" @@@@@@@@@@@@@@@@@@ @@@@@@@@@@@@@@@@@@ ", +" @@@@@@@@@@@@@@@@@@ @@@@@@@@@@@@@@@@@@ ", +" @@@@@@@@@@@@@@@@@@ @@@@@@@@@@@@@@@@@@ ", +" @@@@@@@@@@@@@@@@@@ @@@@@@@@@@@@@@@@@@ ", +" @@@@@@@@@######### @@@@@@@@@######### ", +" @@@@@@@@@######### @@@@@@@@@######### ", +" @@@@@@@@@######### @@@@@@@@@######### ", +" @@@@@@@@@######### @@@@@@@@@######### ", +" @@@@@@@@@######### @@@@@@@@@######### ", +" @@@@@@@@@######### @@@@@@@@@######### ", +" @@@@@@@@@######### @@@@@@@@@######### ", +" @@@@@@@@@######### @@@@@@@@@######### ", +" @@@@@@@@@######### @@@@@@@@@######### ", +" @@@@@@@@@ @@@@@@@@@ ", +" @@@@@@@@@ @@@@@@@@@ ", +" @@@@@@@@@ @@@@@@@@@ ", +" @@@@@@@@@ @@@@@@@@@ ", +" @@@@@@@@@ @@@@@@@@@ ", +" ", +" ", +" ", +" ", +" ", +" ", +" ", +" ", +" ", +" ", +" ", +" ", +" ", +" ", +" ", +" ", +" ", +" ", +" ", +" ", +" ", +" ", +" ", +" ", +" ", +" ", +" "}; diff --git a/hacks/images/pacman/eyes-u.xpm b/hacks/images/pacman/eyes-u.xpm new file mode 100644 index 00000000..8b35cd97 --- /dev/null +++ b/hacks/images/pacman/eyes-u.xpm @@ -0,0 +1,70 @@ +/* XPM */ +static char * eyes_u_xpm[] = { +"64 64 3 1", +" c None", +"@ c #DEDEDE", +"# c #2121DE", +" ", +" ", +" ", +" ", +" ", +" ######### ######### ", +" ######### ######### ", +" ######### ######### ", +" ######### ######### ", +" @@@@@#########@@@@ @@@@#########@@@@@ ", +" @@@@@#########@@@@ @@@@#########@@@@@ ", +" @@@@@#########@@@@ @@@@#########@@@@@ ", +" @@@@@#########@@@@ @@@@#########@@@@@ ", +" @@@@@#########@@@@ @@@@#########@@@@@ ", +" @@@@@@@@@@@@@@@@@@ @@@@@@@@@@@@@@@@@@ ", +" @@@@@@@@@@@@@@@@@@ @@@@@@@@@@@@@@@@@@ ", +" @@@@@@@@@@@@@@@@@@ @@@@@@@@@@@@@@@@@@ ", +" @@@@@@@@@@@@@@@@@@ @@@@@@@@@@@@@@@@@@ ", +" @@@@@@@@@@@@@@@@@@ @@@@@@@@@@@@@@@@@@ ", +" @@@@@@@@@@@@@@@@@@ @@@@@@@@@@@@@@@@@@ ", +" @@@@@@@@@@@@@@@@@@ @@@@@@@@@@@@@@@@@@ ", +" @@@@@@@@@@@@@@@@@@ @@@@@@@@@@@@@@@@@@ ", +" @@@@@@@@@@@@@@@@@@ @@@@@@@@@@@@@@@@@@ ", +" @@@@@@@@@ @@@@@@@@@ ", +" @@@@@@@@@ @@@@@@@@@ ", +" @@@@@@@@@ @@@@@@@@@ ", +" @@@@@@@@@ @@@@@@@@@ ", +" ", +" ", +" ", +" ", +" ", +" ", +" ", +" ", +" ", +" ", +" ", +" ", +" ", +" ", +" ", +" ", +" ", +" ", +" ", +" ", +" ", +" ", +" ", +" ", +" ", +" ", +" ", +" ", +" ", +" ", +" ", +" ", +" ", +" ", +" ", +" ", +" "}; diff --git a/hacks/images/pacman/ghost-d1.xpm b/hacks/images/pacman/ghost-d1.xpm new file mode 100644 index 00000000..37e7dca2 --- /dev/null +++ b/hacks/images/pacman/ghost-d1.xpm @@ -0,0 +1,72 @@ +/* XPM */ +static char * ghost_d1_xpm[] = { +"64 64 5 1", +" c None", +". c #FF0000", +"+ c #DEDEDE", +"# c #2121DE", +"@ c #000000", +" .................. ", +" .................. ", +" .................. ", +" .................. ", +" .................. ", +" .................................... ", +" .................................... ", +" .................................... ", +" .................................... ", +" .............................................. ", +" .............................................. ", +" .............................................. ", +" .............................................. ", +" .............................................. ", +" ...................................................... ", +" ...................................................... ", +" ...................................................... ", +" ...................................................... ", +" .........+++++++++..................+++++++++......... ", +" .........+++++++++..................+++++++++......... ", +" .........+++++++++..................+++++++++......... ", +" .........+++++++++..................+++++++++......... ", +" .........+++++++++..................+++++++++......... ", +" ....++++++++++++++++++..........++++++++++++++++++.... ", +" ....++++++++++++++++++..........++++++++++++++++++.... ", +" ....++++++++++++++++++..........++++++++++++++++++.... ", +" ....++++++++++++++++++..........++++++++++++++++++.... ", +".........++++++++++++++++++..........++++++++++++++++++.........", +".........++++++++++++++++++..........++++++++++++++++++.........", +".........++++++++++++++++++..........++++++++++++++++++.........", +".........++++++++++++++++++..........++++++++++++++++++.........", +".........++++++++++++++++++..........++++++++++++++++++.........", +".........+++++#########++++..........++++#########+++++.........", +".........+++++#########++++..........++++#########+++++.........", +".........+++++#########++++..........++++#########+++++.........", +".........+++++#########++++..........++++#########+++++.........", +".........+++++#########++++..........++++#########+++++.........", +"..............#########..................#########..............", +"..............#########..................#########..............", +"..............#########..................#########..............", +"..............#########..................#########..............", +"................................................................", +"................................................................", +"................................................................", +"................................................................", +"................................................................", +"................................................................", +"................................................................", +"................................................................", +"................................................................", +"................................................................", +"................................................................", +"................................................................", +"................................................................", +"................................................................", +"..................@@@@@..................@@@@@..................", +"..................@@@@@..................@@@@@..................", +"..................@@@@@..................@@@@@..................", +"..................@@@@@..................@@@@@..................", +"@@@@@.........@@@@@@@@@@@@@..........@@@@@@@@@@@@@.........@@@@@", +"@@@@@.........@@@@@@@@@@@@@..........@@@@@@@@@@@@@.........@@@@@", +"@@@@@.........@@@@@@@@@@@@@..........@@@@@@@@@@@@@.........@@@@@", +"@@@@@.........@@@@@@@@@@@@@..........@@@@@@@@@@@@@.........@@@@@", +"@@@@@.........@@@@@@@@@@@@@..........@@@@@@@@@@@@@.........@@@@@"}; diff --git a/hacks/images/pacman/ghost-d2.xpm b/hacks/images/pacman/ghost-d2.xpm new file mode 100644 index 00000000..2c8b024b --- /dev/null +++ b/hacks/images/pacman/ghost-d2.xpm @@ -0,0 +1,72 @@ +/* XPM */ +static char * ghost_d2_xpm[] = { +"64 64 5 1", +" c None", +". c #FF0000", +"+ c #DEDEDE", +"# c #2121DE", +"@ c #000000", +" .................. ", +" .................. ", +" .................. ", +" .................. ", +" .................. ", +" .................................... ", +" .................................... ", +" .................................... ", +" .................................... ", +" .............................................. ", +" .............................................. ", +" .............................................. ", +" .............................................. ", +" .............................................. ", +" ...................................................... ", +" ...................................................... ", +" ...................................................... ", +" ...................................................... ", +" .........+++++++++..................+++++++++......... ", +" .........+++++++++..................+++++++++......... ", +" .........+++++++++..................+++++++++......... ", +" .........+++++++++..................+++++++++......... ", +" .........+++++++++..................+++++++++......... ", +" ....++++++++++++++++++..........++++++++++++++++++.... ", +" ....++++++++++++++++++..........++++++++++++++++++.... ", +" ....++++++++++++++++++..........++++++++++++++++++.... ", +" ....++++++++++++++++++..........++++++++++++++++++.... ", +".........++++++++++++++++++..........++++++++++++++++++.........", +".........++++++++++++++++++..........++++++++++++++++++.........", +".........++++++++++++++++++..........++++++++++++++++++.........", +".........++++++++++++++++++..........++++++++++++++++++.........", +".........++++++++++++++++++..........++++++++++++++++++.........", +".........+++++#########++++..........++++#########+++++.........", +".........+++++#########++++..........++++#########+++++.........", +".........+++++#########++++..........++++#########+++++.........", +".........+++++#########++++..........++++#########+++++.........", +".........+++++#########++++..........++++#########+++++.........", +"..............#########..................#########..............", +"..............#########..................#########..............", +"..............#########..................#########..............", +"..............#########..................#########..............", +"................................................................", +"................................................................", +"................................................................", +"................................................................", +"................................................................", +"................................................................", +"................................................................", +"................................................................", +"................................................................", +"................................................................", +"................................................................", +"................................................................", +"................................................................", +"................................................................", +".........@@@@@.............@@@@@@@@@@.............@@@@@.........", +".........@@@@@.............@@@@@@@@@@.............@@@@@.........", +".........@@@@@.............@@@@@@@@@@.............@@@@@.........", +".........@@@@@.............@@@@@@@@@@.............@@@@@.........", +".....@@@@@@@@@@@@@.........@@@@@@@@@@.........@@@@@@@@@@@@@.....", +".....@@@@@@@@@@@@@.........@@@@@@@@@@.........@@@@@@@@@@@@@.....", +".....@@@@@@@@@@@@@.........@@@@@@@@@@.........@@@@@@@@@@@@@.....", +".....@@@@@@@@@@@@@.........@@@@@@@@@@.........@@@@@@@@@@@@@.....", +".....@@@@@@@@@@@@@.........@@@@@@@@@@.........@@@@@@@@@@@@@....."}; diff --git a/hacks/images/pacman/ghost-l1.xpm b/hacks/images/pacman/ghost-l1.xpm new file mode 100644 index 00000000..71c2b1a2 --- /dev/null +++ b/hacks/images/pacman/ghost-l1.xpm @@ -0,0 +1,72 @@ +/* XPM */ +static char * ghost_l1_xpm[] = { +"64 64 5 1", +" c None", +". c #FF0000", +"@ c #DEDEDE", +"# c #2121DE", +"+ c #000000", +" .................. ", +" .................. ", +" .................. ", +" .................. ", +" .................. ", +" .................................... ", +" .................................... ", +" .................................... ", +" .................................... ", +" .............................................. ", +" .............................................. ", +" .............................................. ", +" .............................................. ", +" .............................................. ", +" ....@@@@@@@@@...................@@@@@@@@@............. ", +" ....@@@@@@@@@...................@@@@@@@@@............. ", +" ....@@@@@@@@@...................@@@@@@@@@............. ", +" ....@@@@@@@@@...................@@@@@@@@@............. ", +" @@@@@@@@@@@@@@@@@@.........@@@@@@@@@@@@@@@@@@......... ", +" @@@@@@@@@@@@@@@@@@.........@@@@@@@@@@@@@@@@@@......... ", +" @@@@@@@@@@@@@@@@@@.........@@@@@@@@@@@@@@@@@@......... ", +" @@@@@@@@@@@@@@@@@@.........@@@@@@@@@@@@@@@@@@......... ", +" @@@@@@@@@@@@@@@@@@.........@@@@@@@@@@@@@@@@@@......... ", +" #########@@@@@@@@@.........#########@@@@@@@@@......... ", +" #########@@@@@@@@@.........#########@@@@@@@@@......... ", +" #########@@@@@@@@@.........#########@@@@@@@@@......... ", +" #########@@@@@@@@@.........#########@@@@@@@@@......... ", +".....#########@@@@@@@@@.........#########@@@@@@@@@..............", +".....#########@@@@@@@@@.........#########@@@@@@@@@..............", +".....#########@@@@@@@@@.........#########@@@@@@@@@..............", +".....#########@@@@@@@@@.........#########@@@@@@@@@..............", +".....#########@@@@@@@@@.........#########@@@@@@@@@..............", +".........@@@@@@@@@...................@@@@@@@@@..................", +".........@@@@@@@@@...................@@@@@@@@@..................", +".........@@@@@@@@@...................@@@@@@@@@..................", +".........@@@@@@@@@...................@@@@@@@@@..................", +".........@@@@@@@@@...................@@@@@@@@@..................", +"................................................................", +"................................................................", +"................................................................", +"................................................................", +"................................................................", +"................................................................", +"................................................................", +"................................................................", +"................................................................", +"................................................................", +"................................................................", +"................................................................", +"................................................................", +"................................................................", +"................................................................", +"................................................................", +"................................................................", +"................................................................", +"..................+++++..................+++++..................", +"..................+++++..................+++++..................", +"..................+++++..................+++++..................", +"..................+++++..................+++++..................", +"+++++.........+++++++++++++..........+++++++++++++.........+++++", +"+++++.........+++++++++++++..........+++++++++++++.........+++++", +"+++++.........+++++++++++++..........+++++++++++++.........+++++", +"+++++.........+++++++++++++..........+++++++++++++.........+++++", +"+++++.........+++++++++++++..........+++++++++++++.........+++++"}; diff --git a/hacks/images/pacman/ghost-l2.xpm b/hacks/images/pacman/ghost-l2.xpm new file mode 100644 index 00000000..7e008894 --- /dev/null +++ b/hacks/images/pacman/ghost-l2.xpm @@ -0,0 +1,73 @@ +/* XPM */ +static char * ghost_l2_xpm[] = { +"64 64 5 1", +" c None", +". c #FF0000", +"@ c #DEDEDE", +"# c #2121DE", +"+ c #000000", +" .................. ", +" .................. ", +" .................. ", +" .................. ", +" .................. ", +" .................................... ", +" .................................... ", +" .................................... ", +" .................................... ", +" .............................................. ", +" .............................................. ", +" .............................................. ", +" .............................................. ", +" .............................................. ", +" ....@@@@@@@@@...................@@@@@@@@@............. ", +" ....@@@@@@@@@...................@@@@@@@@@............. ", +" ....@@@@@@@@@...................@@@@@@@@@............. ", +" ....@@@@@@@@@...................@@@@@@@@@............. ", +" @@@@@@@@@@@@@@@@@@.........@@@@@@@@@@@@@@@@@@......... ", +" @@@@@@@@@@@@@@@@@@.........@@@@@@@@@@@@@@@@@@......... ", +" @@@@@@@@@@@@@@@@@@.........@@@@@@@@@@@@@@@@@@......... ", +" @@@@@@@@@@@@@@@@@@.........@@@@@@@@@@@@@@@@@@......... ", +" @@@@@@@@@@@@@@@@@@.........@@@@@@@@@@@@@@@@@@......... ", +" #########@@@@@@@@@.........#########@@@@@@@@@......... ", +" #########@@@@@@@@@.........#########@@@@@@@@@......... ", +" #########@@@@@@@@@.........#########@@@@@@@@@......... ", +" #########@@@@@@@@@.........#########@@@@@@@@@......... ", +".....#########@@@@@@@@@.........#########@@@@@@@@@..............", +".....#########@@@@@@@@@.........#########@@@@@@@@@..............", +".....#########@@@@@@@@@.........#########@@@@@@@@@..............", +".....#########@@@@@@@@@.........#########@@@@@@@@@..............", +".....#########@@@@@@@@@.........#########@@@@@@@@@..............", +".........@@@@@@@@@...................@@@@@@@@@..................", +".........@@@@@@@@@...................@@@@@@@@@..................", +".........@@@@@@@@@...................@@@@@@@@@..................", +".........@@@@@@@@@...................@@@@@@@@@..................", +".........@@@@@@@@@...................@@@@@@@@@..................", +"................................................................", +"................................................................", +"................................................................", +"................................................................", +"................................................................", +"................................................................", +"................................................................", +"................................................................", +"................................................................", +"................................................................", +"................................................................", +"................................................................", +"................................................................", +"................................................................", +"................................................................", +"................................................................", +"................................................................", +"................................................................", +".........+++++.............++++++++++.............+++++.........", +".........+++++.............++++++++++.............+++++.........", +".........+++++.............++++++++++.............+++++.........", +".........+++++.............++++++++++.............+++++.........", +".....+++++++++++++.........++++++++++.........+++++++++++++.....", +".....+++++++++++++.........++++++++++.........+++++++++++++.....", +".....+++++++++++++.........++++++++++.........+++++++++++++.....", +".....+++++++++++++.........++++++++++.........+++++++++++++.....", +".....+++++++++++++.........++++++++++.........+++++++++++++....."}; + diff --git a/hacks/images/pacman/ghost-mask.xpm b/hacks/images/pacman/ghost-mask.xpm new file mode 100644 index 00000000..86960ada --- /dev/null +++ b/hacks/images/pacman/ghost-mask.xpm @@ -0,0 +1,69 @@ +/* XPM */ +static char * ghost_mask_xpm[] = { +"64 64 2 1", +" c None", +". c #000000", +" .................. ", +" .................. ", +" .................. ", +" .................. ", +" .................. ", +" .................................... ", +" .................................... ", +" .................................... ", +" .................................... ", +" .............................................. ", +" .............................................. ", +" .............................................. ", +" .............................................. ", +" .............................................. ", +" ...................................................... ", +" ...................................................... ", +" ...................................................... ", +" ...................................................... ", +" ...................................................... ", +" ...................................................... ", +" ...................................................... ", +" ...................................................... ", +" ...................................................... ", +" ...................................................... ", +" ...................................................... ", +" ...................................................... ", +" ...................................................... ", +"................................................................", +"................................................................", +"................................................................", +"................................................................", +"................................................................", +"................................................................", +"................................................................", +"................................................................", +"................................................................", +"................................................................", +"................................................................", +"................................................................", +"................................................................", +"................................................................", +"................................................................", +"................................................................", +"................................................................", +"................................................................", +"................................................................", +"................................................................", +"................................................................", +"................................................................", +"................................................................", +"................................................................", +"................................................................", +"................................................................", +"................................................................", +"................................................................", +"................................................................", +"................................................................", +"................................................................", +"................................................................", +"................................................................", +"................................................................", +"................................................................", +"................................................................", +"................................................................"}; diff --git a/hacks/images/pacman/ghost-r1.xpm b/hacks/images/pacman/ghost-r1.xpm new file mode 100644 index 00000000..8d5fba36 --- /dev/null +++ b/hacks/images/pacman/ghost-r1.xpm @@ -0,0 +1,72 @@ +/* XPM */ +static char * ghost_r1_xpm[] = { +"64 64 5 1", +" c None", +". c #FF0000", +"@ c #DEDEDE", +"# c #2121DE", +"+ c #000000", +" .................. ", +" .................. ", +" .................. ", +" .................. ", +" .................. ", +" .................................... ", +" .................................... ", +" .................................... ", +" .................................... ", +" .............................................. ", +" .............................................. ", +" .............................................. ", +" .............................................. ", +" .............................................. ", +" .............@@@@@@@@@...................@@@@@@@@@.... ", +" .............@@@@@@@@@...................@@@@@@@@@.... ", +" .............@@@@@@@@@...................@@@@@@@@@.... ", +" .............@@@@@@@@@...................@@@@@@@@@.... ", +" .........@@@@@@@@@@@@@@@@@@.........@@@@@@@@@@@@@@@@@@ ", +" .........@@@@@@@@@@@@@@@@@@.........@@@@@@@@@@@@@@@@@@ ", +" .........@@@@@@@@@@@@@@@@@@.........@@@@@@@@@@@@@@@@@@ ", +" .........@@@@@@@@@@@@@@@@@@.........@@@@@@@@@@@@@@@@@@ ", +" .........@@@@@@@@@@@@@@@@@@.........@@@@@@@@@@@@@@@@@@ ", +" .........@@@@@@@@@#########.........@@@@@@@@@######### ", +" .........@@@@@@@@@#########.........@@@@@@@@@######### ", +" .........@@@@@@@@@#########.........@@@@@@@@@######### ", +" .........@@@@@@@@@#########.........@@@@@@@@@######### ", +"..............@@@@@@@@@#########.........@@@@@@@@@#########.....", +"..............@@@@@@@@@#########.........@@@@@@@@@#########.....", +"..............@@@@@@@@@#########.........@@@@@@@@@#########.....", +"..............@@@@@@@@@#########.........@@@@@@@@@#########.....", +"..............@@@@@@@@@#########.........@@@@@@@@@#########.....", +"..................@@@@@@@@@...................@@@@@@@@@.........", +"..................@@@@@@@@@...................@@@@@@@@@.........", +"..................@@@@@@@@@...................@@@@@@@@@.........", +"..................@@@@@@@@@...................@@@@@@@@@.........", +"..................@@@@@@@@@...................@@@@@@@@@.........", +"................................................................", +"................................................................", +"................................................................", +"................................................................", +"................................................................", +"................................................................", +"................................................................", +"................................................................", +"................................................................", +"................................................................", +"................................................................", +"................................................................", +"................................................................", +"................................................................", +"................................................................", +"................................................................", +"................................................................", +"................................................................", +"..................+++++..................+++++..................", +"..................+++++..................+++++..................", +"..................+++++..................+++++..................", +"..................+++++..................+++++..................", +"+++++.........+++++++++++++..........+++++++++++++.........+++++", +"+++++.........+++++++++++++..........+++++++++++++.........+++++", +"+++++.........+++++++++++++..........+++++++++++++.........+++++", +"+++++.........+++++++++++++..........+++++++++++++.........+++++", +"+++++.........+++++++++++++..........+++++++++++++.........+++++"}; diff --git a/hacks/images/pacman/ghost-r2.xpm b/hacks/images/pacman/ghost-r2.xpm new file mode 100644 index 00000000..4a6ab7b9 --- /dev/null +++ b/hacks/images/pacman/ghost-r2.xpm @@ -0,0 +1,72 @@ +/* XPM */ +static char * ghost_r2_xpm[] = { +"64 64 5 1", +" c None", +". c #FF0000", +"@ c #DEDEDE", +"# c #2121DE", +"+ c #000000", +" .................. ", +" .................. ", +" .................. ", +" .................. ", +" .................. ", +" .................................... ", +" .................................... ", +" .................................... ", +" .................................... ", +" .............................................. ", +" .............................................. ", +" .............................................. ", +" .............................................. ", +" .............................................. ", +" .............@@@@@@@@@...................@@@@@@@@@.... ", +" .............@@@@@@@@@...................@@@@@@@@@.... ", +" .............@@@@@@@@@...................@@@@@@@@@.... ", +" .............@@@@@@@@@...................@@@@@@@@@.... ", +" .........@@@@@@@@@@@@@@@@@@.........@@@@@@@@@@@@@@@@@@ ", +" .........@@@@@@@@@@@@@@@@@@.........@@@@@@@@@@@@@@@@@@ ", +" .........@@@@@@@@@@@@@@@@@@.........@@@@@@@@@@@@@@@@@@ ", +" .........@@@@@@@@@@@@@@@@@@.........@@@@@@@@@@@@@@@@@@ ", +" .........@@@@@@@@@@@@@@@@@@.........@@@@@@@@@@@@@@@@@@ ", +" .........@@@@@@@@@#########.........@@@@@@@@@######### ", +" .........@@@@@@@@@#########.........@@@@@@@@@######### ", +" .........@@@@@@@@@#########.........@@@@@@@@@######### ", +" .........@@@@@@@@@#########.........@@@@@@@@@######### ", +"..............@@@@@@@@@#########.........@@@@@@@@@#########.....", +"..............@@@@@@@@@#########.........@@@@@@@@@#########.....", +"..............@@@@@@@@@#########.........@@@@@@@@@#########.....", +"..............@@@@@@@@@#########.........@@@@@@@@@#########.....", +"..............@@@@@@@@@#########.........@@@@@@@@@#########.....", +"..................@@@@@@@@@...................@@@@@@@@@.........", +"..................@@@@@@@@@...................@@@@@@@@@.........", +"..................@@@@@@@@@...................@@@@@@@@@.........", +"..................@@@@@@@@@...................@@@@@@@@@.........", +"..................@@@@@@@@@...................@@@@@@@@@.........", +"................................................................", +"................................................................", +"................................................................", +"................................................................", +"................................................................", +"................................................................", +"................................................................", +"................................................................", +"................................................................", +"................................................................", +"................................................................", +"................................................................", +"................................................................", +"................................................................", +"................................................................", +"................................................................", +"................................................................", +"................................................................", +".........+++++.............++++++++++.............+++++.........", +".........+++++.............++++++++++.............+++++.........", +".........+++++.............++++++++++.............+++++.........", +".........+++++.............++++++++++.............+++++.........", +".....+++++++++++++.........++++++++++.........+++++++++++++.....", +".....+++++++++++++.........++++++++++.........+++++++++++++.....", +".....+++++++++++++.........++++++++++.........+++++++++++++.....", +".....+++++++++++++.........++++++++++.........+++++++++++++.....", +".....+++++++++++++.........++++++++++.........+++++++++++++....."}; diff --git a/hacks/images/pacman/ghost-s1.xpm b/hacks/images/pacman/ghost-s1.xpm new file mode 100644 index 00000000..4a3e394a --- /dev/null +++ b/hacks/images/pacman/ghost-s1.xpm @@ -0,0 +1,71 @@ +/* XPM */ +static char * ghost_s1_xpm[] = { +"64 64 4 1", +" c None", +". c #2121DE", +"# c #FFB897", +"@ c #000000", +" .................. ", +" .................. ", +" .................. ", +" .................. ", +" .................. ", +" .................................... ", +" .................................... ", +" .................................... ", +" .................................... ", +" .............................................. ", +" .............................................. ", +" .............................................. ", +" .............................................. ", +" .............................................. ", +" ...................................................... ", +" ...................................................... ", +" ...................................................... ", +" ...................................................... ", +" ...................................................... ", +" ...................................................... ", +" ...................................................... ", +" ...................................................... ", +" ...................................................... ", +" .............#########..........#########............. ", +" .............#########..........#########............. ", +" .............#########..........#########............. ", +" .............#########..........#########............. ", +"..................#########..........#########..................", +"..................#########..........#########..................", +"..................#########..........#########..................", +"..................#########..........#########..................", +"..................#########..........#########..................", +"................................................................", +"................................................................", +"................................................................", +"................................................................", +"................................................................", +"................................................................", +"................................................................", +"................................................................", +"................................................................", +".........#########.........##########.........#########.........", +".........#########.........##########.........#########.........", +".........#########.........##########.........#########.........", +".........#########.........##########.........#########.........", +".........#########.........##########.........#########.........", +".....####.........#########..........#########.........####.....", +".....####.........#########..........#########.........####.....", +".....####.........#########..........#########.........####.....", +".....####.........#########..........#########.........####.....", +"................................................................", +"................................................................", +"................................................................", +"................................................................", +"................................................................", +"..................@@@@@..................@@@@@..................", +"..................@@@@@..................@@@@@..................", +"..................@@@@@..................@@@@@..................", +"..................@@@@@..................@@@@@..................", +"@@@@@.........@@@@@@@@@@@@@..........@@@@@@@@@@@@@.........@@@@@", +"@@@@@.........@@@@@@@@@@@@@..........@@@@@@@@@@@@@.........@@@@@", +"@@@@@.........@@@@@@@@@@@@@..........@@@@@@@@@@@@@.........@@@@@", +"@@@@@.........@@@@@@@@@@@@@..........@@@@@@@@@@@@@.........@@@@@", +"@@@@@.........@@@@@@@@@@@@@..........@@@@@@@@@@@@@.........@@@@@"}; diff --git a/hacks/images/pacman/ghost-s2.xpm b/hacks/images/pacman/ghost-s2.xpm new file mode 100644 index 00000000..6a3b724c --- /dev/null +++ b/hacks/images/pacman/ghost-s2.xpm @@ -0,0 +1,71 @@ +/* XPM */ +static char * ghost_s2_xpm[] = { +"64 64 4 1", +" c None", +"# c #FFB897", +". c #2121DE", +"@ c #000000", +" .................. ", +" .................. ", +" .................. ", +" .................. ", +" .................. ", +" .................................... ", +" .................................... ", +" .................................... ", +" .................................... ", +" .............................................. ", +" .............................................. ", +" .............................................. ", +" .............................................. ", +" .............................................. ", +" ...................................................... ", +" ...................................................... ", +" ...................................................... ", +" ...................................................... ", +" ...................................................... ", +" ...................................................... ", +" ...................................................... ", +" ...................................................... ", +" ...................................................... ", +" .............#########..........#########............. ", +" .............#########..........#########............. ", +" .............#########..........#########............. ", +" .............#########..........#########............. ", +"..................#########..........#########..................", +"..................#########..........#########..................", +"..................#########..........#########..................", +"..................#########..........#########..................", +"..................#########..........#########..................", +"................................................................", +"................................................................", +"................................................................", +"................................................................", +"................................................................", +"................................................................", +"................................................................", +"................................................................", +"................................................................", +".........#########.........##########.........#########.........", +".........#########.........##########.........#########.........", +".........#########.........##########.........#########.........", +".........#########.........##########.........#########.........", +".........#########.........##########.........#########.........", +".....####.........#########..........#########.........####.....", +".....####.........#########..........#########.........####.....", +".....####.........#########..........#########.........####.....", +".....####.........#########..........#########.........####.....", +"................................................................", +"................................................................", +"................................................................", +"................................................................", +"................................................................", +".........@@@@@.............@@@@@@@@@@.............@@@@@.........", +".........@@@@@.............@@@@@@@@@@.............@@@@@.........", +".........@@@@@.............@@@@@@@@@@.............@@@@@.........", +".........@@@@@.............@@@@@@@@@@.............@@@@@.........", +".....@@@@@@@@@@@@@.........@@@@@@@@@@.........@@@@@@@@@@@@@.....", +".....@@@@@@@@@@@@@.........@@@@@@@@@@.........@@@@@@@@@@@@@.....", +".....@@@@@@@@@@@@@.........@@@@@@@@@@.........@@@@@@@@@@@@@.....", +".....@@@@@@@@@@@@@.........@@@@@@@@@@.........@@@@@@@@@@@@@.....", +".....@@@@@@@@@@@@@.........@@@@@@@@@@.........@@@@@@@@@@@@@....."}; diff --git a/hacks/images/pacman/ghost-sf1.xpm b/hacks/images/pacman/ghost-sf1.xpm new file mode 100644 index 00000000..3a15adb4 --- /dev/null +++ b/hacks/images/pacman/ghost-sf1.xpm @@ -0,0 +1,71 @@ +/* XPM */ +static char * ghost_sf1_xpm[] = { +"64 64 4 1", +" c None", +". c #DEDEDE", +"# c #FF0000", +"@ c #000000", +" .................. ", +" .................. ", +" .................. ", +" .................. ", +" .................. ", +" .................................... ", +" .................................... ", +" .................................... ", +" .................................... ", +" .............................................. ", +" .............................................. ", +" .............................................. ", +" .............................................. ", +" .............................................. ", +" ...................................................... ", +" ...................................................... ", +" ...................................................... ", +" ...................................................... ", +" ...................................................... ", +" ...................................................... ", +" ...................................................... ", +" ...................................................... ", +" ...................................................... ", +" .............#########..........#########............. ", +" .............#########..........#########............. ", +" .............#########..........#########............. ", +" .............#########..........#########............. ", +"..................#########..........#########..................", +"..................#########..........#########..................", +"..................#########..........#########..................", +"..................#########..........#########..................", +"..................#########..........#########..................", +"................................................................", +"................................................................", +"................................................................", +"................................................................", +"................................................................", +"................................................................", +"................................................................", +"................................................................", +"................................................................", +".........#########.........##########.........#########.........", +".........#########.........##########.........#########.........", +".........#########.........##########.........#########.........", +".........#########.........##########.........#########.........", +".........#########.........##########.........#########.........", +".....####.........#########..........#########.........####.....", +".....####.........#########..........#########.........####.....", +".....####.........#########..........#########.........####.....", +".....####.........#########..........#########.........####.....", +"................................................................", +"................................................................", +"................................................................", +"................................................................", +"................................................................", +"..................@@@@@..................@@@@@..................", +"..................@@@@@..................@@@@@..................", +"..................@@@@@..................@@@@@..................", +"..................@@@@@..................@@@@@..................", +"@@@@@.........@@@@@@@@@@@@@..........@@@@@@@@@@@@@.........@@@@@", +"@@@@@.........@@@@@@@@@@@@@..........@@@@@@@@@@@@@.........@@@@@", +"@@@@@.........@@@@@@@@@@@@@..........@@@@@@@@@@@@@.........@@@@@", +"@@@@@.........@@@@@@@@@@@@@..........@@@@@@@@@@@@@.........@@@@@", +"@@@@@.........@@@@@@@@@@@@@..........@@@@@@@@@@@@@.........@@@@@"}; diff --git a/hacks/images/pacman/ghost-sf2.xpm b/hacks/images/pacman/ghost-sf2.xpm new file mode 100644 index 00000000..d344ade7 --- /dev/null +++ b/hacks/images/pacman/ghost-sf2.xpm @@ -0,0 +1,71 @@ +/* XPM */ +static char * ghost_sf2_xpm[] = { +"64 64 4 1", +" c None", +". c #DEDEDE", +"# c #FF0000", +"@ c #000000", +" .................. ", +" .................. ", +" .................. ", +" .................. ", +" .................. ", +" .................................... ", +" .................................... ", +" .................................... ", +" .................................... ", +" .............................................. ", +" .............................................. ", +" .............................................. ", +" .............................................. ", +" .............................................. ", +" ...................................................... ", +" ...................................................... ", +" ...................................................... ", +" ...................................................... ", +" ...................................................... ", +" ...................................................... ", +" ...................................................... ", +" ...................................................... ", +" ...................................................... ", +" .............#########..........#########............. ", +" .............#########..........#########............. ", +" .............#########..........#########............. ", +" .............#########..........#########............. ", +"..................#########..........#########..................", +"..................#########..........#########..................", +"..................#########..........#########..................", +"..................#########..........#########..................", +"..................#########..........#########..................", +"................................................................", +"................................................................", +"................................................................", +"................................................................", +"................................................................", +"................................................................", +"................................................................", +"................................................................", +"................................................................", +".........#########.........##########.........#########.........", +".........#########.........##########.........#########.........", +".........#########.........##########.........#########.........", +".........#########.........##########.........#########.........", +".........#########.........##########.........#########.........", +".....####.........#########..........#########.........####.....", +".....####.........#########..........#########.........####.....", +".....####.........#########..........#########.........####.....", +".....####.........#########..........#########.........####.....", +"................................................................", +"................................................................", +"................................................................", +"................................................................", +"................................................................", +".........@@@@@.............@@@@@@@@@@.............@@@@@.........", +".........@@@@@.............@@@@@@@@@@.............@@@@@.........", +".........@@@@@.............@@@@@@@@@@.............@@@@@.........", +".........@@@@@.............@@@@@@@@@@.............@@@@@.........", +".....@@@@@@@@@@@@@.........@@@@@@@@@@.........@@@@@@@@@@@@@.....", +".....@@@@@@@@@@@@@.........@@@@@@@@@@.........@@@@@@@@@@@@@.....", +".....@@@@@@@@@@@@@.........@@@@@@@@@@.........@@@@@@@@@@@@@.....", +".....@@@@@@@@@@@@@.........@@@@@@@@@@.........@@@@@@@@@@@@@.....", +".....@@@@@@@@@@@@@.........@@@@@@@@@@.........@@@@@@@@@@@@@....."}; diff --git a/hacks/images/pacman/ghost-u1.xpm b/hacks/images/pacman/ghost-u1.xpm new file mode 100644 index 00000000..9bf458ac --- /dev/null +++ b/hacks/images/pacman/ghost-u1.xpm @@ -0,0 +1,72 @@ +/* XPM */ +static char * ghost_u1_xpm[] = { +"64 64 5 1", +" c None", +". c #FF0000", +"@ c #DEDEDE", +"# c #2121DE", +"+ c #000000", +" .................. ", +" .................. ", +" .................. ", +" .................. ", +" .................. ", +" #########..................######### ", +" #########..................######### ", +" #########..................######### ", +" #########..................######### ", +" @@@@@#########@@@@..........@@@@#########@@@@@ ", +" @@@@@#########@@@@..........@@@@#########@@@@@ ", +" @@@@@#########@@@@..........@@@@#########@@@@@ ", +" @@@@@#########@@@@..........@@@@#########@@@@@ ", +" @@@@@#########@@@@..........@@@@#########@@@@@ ", +" ....@@@@@@@@@@@@@@@@@@..........@@@@@@@@@@@@@@@@@@.... ", +" ....@@@@@@@@@@@@@@@@@@..........@@@@@@@@@@@@@@@@@@.... ", +" ....@@@@@@@@@@@@@@@@@@..........@@@@@@@@@@@@@@@@@@.... ", +" ....@@@@@@@@@@@@@@@@@@..........@@@@@@@@@@@@@@@@@@.... ", +" ....@@@@@@@@@@@@@@@@@@..........@@@@@@@@@@@@@@@@@@.... ", +" ....@@@@@@@@@@@@@@@@@@..........@@@@@@@@@@@@@@@@@@.... ", +" ....@@@@@@@@@@@@@@@@@@..........@@@@@@@@@@@@@@@@@@.... ", +" ....@@@@@@@@@@@@@@@@@@..........@@@@@@@@@@@@@@@@@@.... ", +" ....@@@@@@@@@@@@@@@@@@..........@@@@@@@@@@@@@@@@@@.... ", +" .........@@@@@@@@@..................@@@@@@@@@......... ", +" .........@@@@@@@@@..................@@@@@@@@@......... ", +" .........@@@@@@@@@..................@@@@@@@@@......... ", +" .........@@@@@@@@@..................@@@@@@@@@......... ", +"................................................................", +"................................................................", +"................................................................", +"................................................................", +"................................................................", +"................................................................", +"................................................................", +"................................................................", +"................................................................", +"................................................................", +"................................................................", +"................................................................", +"................................................................", +"................................................................", +"................................................................", +"................................................................", +"................................................................", +"................................................................", +"................................................................", +"................................................................", +"................................................................", +"................................................................", +"................................................................", +"................................................................", +"................................................................", +"................................................................", +"................................................................", +"................................................................", +"..................+++++..................+++++..................", +"..................+++++..................+++++..................", +"..................+++++..................+++++..................", +"..................+++++..................+++++..................", +"+++++.........+++++++++++++..........+++++++++++++.........+++++", +"+++++.........+++++++++++++..........+++++++++++++.........+++++", +"+++++.........+++++++++++++..........+++++++++++++.........+++++", +"+++++.........+++++++++++++..........+++++++++++++.........+++++", +"+++++.........+++++++++++++..........+++++++++++++.........+++++"}; diff --git a/hacks/images/pacman/ghost-u2.xpm b/hacks/images/pacman/ghost-u2.xpm new file mode 100644 index 00000000..74adca26 --- /dev/null +++ b/hacks/images/pacman/ghost-u2.xpm @@ -0,0 +1,72 @@ +/* XPM */ +static char * ghost_u2_xpm[] = { +"64 64 5 1", +" c None", +". c #FF0000", +"@ c #DEDEDE", +"# c #2121DE", +"+ c #000000", +" .................. ", +" .................. ", +" .................. ", +" .................. ", +" .................. ", +" #########..................######### ", +" #########..................######### ", +" #########..................######### ", +" #########..................######### ", +" @@@@@#########@@@@..........@@@@#########@@@@@ ", +" @@@@@#########@@@@..........@@@@#########@@@@@ ", +" @@@@@#########@@@@..........@@@@#########@@@@@ ", +" @@@@@#########@@@@..........@@@@#########@@@@@ ", +" @@@@@#########@@@@..........@@@@#########@@@@@ ", +" ....@@@@@@@@@@@@@@@@@@..........@@@@@@@@@@@@@@@@@@.... ", +" ....@@@@@@@@@@@@@@@@@@..........@@@@@@@@@@@@@@@@@@.... ", +" ....@@@@@@@@@@@@@@@@@@..........@@@@@@@@@@@@@@@@@@.... ", +" ....@@@@@@@@@@@@@@@@@@..........@@@@@@@@@@@@@@@@@@.... ", +" ....@@@@@@@@@@@@@@@@@@..........@@@@@@@@@@@@@@@@@@.... ", +" ....@@@@@@@@@@@@@@@@@@..........@@@@@@@@@@@@@@@@@@.... ", +" ....@@@@@@@@@@@@@@@@@@..........@@@@@@@@@@@@@@@@@@.... ", +" ....@@@@@@@@@@@@@@@@@@..........@@@@@@@@@@@@@@@@@@.... ", +" ....@@@@@@@@@@@@@@@@@@..........@@@@@@@@@@@@@@@@@@.... ", +" .........@@@@@@@@@..................@@@@@@@@@......... ", +" .........@@@@@@@@@..................@@@@@@@@@......... ", +" .........@@@@@@@@@..................@@@@@@@@@......... ", +" .........@@@@@@@@@..................@@@@@@@@@......... ", +"................................................................", +"................................................................", +"................................................................", +"................................................................", +"................................................................", +"................................................................", +"................................................................", +"................................................................", +"................................................................", +"................................................................", +"................................................................", +"................................................................", +"................................................................", +"................................................................", +"................................................................", +"................................................................", +"................................................................", +"................................................................", +"................................................................", +"................................................................", +"................................................................", +"................................................................", +"................................................................", +"................................................................", +"................................................................", +"................................................................", +"................................................................", +"................................................................", +".........+++++.............++++++++++.............+++++.........", +".........+++++.............++++++++++.............+++++.........", +".........+++++.............++++++++++.............+++++.........", +".........+++++.............++++++++++.............+++++.........", +".....+++++++++++++.........++++++++++.........+++++++++++++.....", +".....+++++++++++++.........++++++++++.........+++++++++++++.....", +".....+++++++++++++.........++++++++++.........+++++++++++++.....", +".....+++++++++++++.........++++++++++.........+++++++++++++.....", +".....+++++++++++++.........++++++++++.........+++++++++++++....."}; diff --git a/hacks/images/pacman/pacman-0.xpm b/hacks/images/pacman/pacman-0.xpm new file mode 100644 index 00000000..de0bece5 --- /dev/null +++ b/hacks/images/pacman/pacman-0.xpm @@ -0,0 +1,69 @@ +/* XPM */ +static char * pacman_0_xpm[] = { +"64 64 2 1", +" c None", +". c #FFFF00", +" ........................ ", +" ........................ ", +" ........................ ", +" ........................ ", +" ........................ ", +" ............................................ ", +" ............................................ ", +" ............................................ ", +" ............................................ ", +" ............................................ ", +" ...................................................... ", +" ...................................................... ", +" ...................................................... ", +" ...................................................... ", +" ...................................................... ", +" ...................................................... ", +" ...................................................... ", +" ...................................................... ", +" ...................................................... ", +" ...................................................... ", +"................................................................", +"................................................................", +"................................................................", +"................................................................", +"................................................................", +"................................................................", +"................................................................", +"................................................................", +"................................................................", +"................................................................", +"................................................................", +"................................................................", +"................................................................", +"................................................................", +"................................................................", +"................................................................", +"................................................................", +"................................................................", +"................................................................", +"................................................................", +"................................................................", +"................................................................", +"................................................................", +"................................................................", +" ...................................................... ", +" ...................................................... ", +" ...................................................... ", +" ...................................................... ", +" ...................................................... ", +" ...................................................... ", +" ...................................................... ", +" ...................................................... ", +" ...................................................... ", +" ...................................................... ", +" ............................................ ", +" ............................................ ", +" ............................................ ", +" ............................................ ", +" ............................................ ", +" ........................ ", +" ........................ ", +" ........................ ", +" ........................ ", +" ........................ "}; diff --git a/hacks/images/pacman/pacman-d1.xpm b/hacks/images/pacman/pacman-d1.xpm new file mode 100644 index 00000000..1063f5af --- /dev/null +++ b/hacks/images/pacman/pacman-d1.xpm @@ -0,0 +1,69 @@ +/* XPM */ +static char * pacman_d1_xpm[] = { +"64 64 2 1", +" c None", +". c #FFFF00", +" ........................ ", +" ........................ ", +" ........................ ", +" ........................ ", +" ........................ ", +" ............................................ ", +" ............................................ ", +" ............................................ ", +" ............................................ ", +" ............................................ ", +" ...................................................... ", +" ...................................................... ", +" ...................................................... ", +" ...................................................... ", +" ...................................................... ", +" ...................................................... ", +" ...................................................... ", +" ...................................................... ", +" ...................................................... ", +" ...................................................... ", +".............................. ..............................", +".............................. ..............................", +".............................. ..............................", +".............................. ..............................", +".............................. ..............................", +".............................. ..............................", +".............................. ..............................", +".............................. ..............................", +".............................. ..............................", +".............................. ..............................", +".............................. ..............................", +".............................. ..............................", +".............................. ..............................", +".............................. ..............................", +"......................... .........................", +"......................... .........................", +"......................... .........................", +"......................... .........................", +"......................... .........................", +"......................... .........................", +"......................... .........................", +"......................... .........................", +"......................... .........................", +"......................... .........................", +" .................... .................... ", +" .................... .................... ", +" .................... .................... ", +" .................... .................... ", +" .................... .................... ", +" ............... ............... ", +" ............... ............... ", +" ............... ............... ", +" ............... ............... ", +" ............... ............... ", +" .......... .......... ", +" .......... .......... ", +" .......... .......... ", +" .......... .......... ", +" .......... .......... ", +" ", +" ", +" ", +" ", +" "}; diff --git a/hacks/images/pacman/pacman-d2.xpm b/hacks/images/pacman/pacman-d2.xpm new file mode 100644 index 00000000..feba94c1 --- /dev/null +++ b/hacks/images/pacman/pacman-d2.xpm @@ -0,0 +1,69 @@ +/* XPM */ +static char * pacman_d2_xpm[] = { +"64 64 2 1", +" c None", +"+ c #FFFF00", +" ++++++++++++++++++++++++ ", +" ++++++++++++++++++++++++ ", +" ++++++++++++++++++++++++ ", +" ++++++++++++++++++++++++ ", +" ++++++++++++++++++++++++ ", +" ++++++++++++++++++++++++++++++++++++++++++++ ", +" ++++++++++++++++++++++++++++++++++++++++++++ ", +" ++++++++++++++++++++++++++++++++++++++++++++ ", +" ++++++++++++++++++++++++++++++++++++++++++++ ", +" ++++++++++++++++++++++++++++++++++++++++++++ ", +" ++++++++++++++++++++++++++++++++++++++++++++++++++++++ ", +" ++++++++++++++++++++++++++++++++++++++++++++++++++++++ ", +" ++++++++++++++++++++++++++++++++++++++++++++++++++++++ ", +" ++++++++++++++++++++++++++++++++++++++++++++++++++++++ ", +" ++++++++++++++++++++++++++++++++++++++++++++++++++++++ ", +" ++++++++++++++++++++++++++++++++++++++++++++++++++++++ ", +" ++++++++++++++++++++++++++++++++++++++++++++++++++++++ ", +" ++++++++++++++++++++++++++++++++++++++++++++++++++++++ ", +" ++++++++++++++++++++++++++++++++++++++++++++++++++++++ ", +" ++++++++++++++++++++++++++++++++++++++++++++++++++++++ ", +"++++++++++++++++++++++++++++++ ++++++++++++++++++++++++++++++", +"++++++++++++++++++++++++++++++ ++++++++++++++++++++++++++++++", +"++++++++++++++++++++++++++++++ ++++++++++++++++++++++++++++++", +"++++++++++++++++++++++++++++++ ++++++++++++++++++++++++++++++", +"++++++++++++++++++++++++++++++ ++++++++++++++++++++++++++++++", +"+++++++++++++++++++++++++ +++++++++++++++++++++++++", +"+++++++++++++++++++++++++ +++++++++++++++++++++++++", +"+++++++++++++++++++++++++ +++++++++++++++++++++++++", +"+++++++++++++++++++++++++ +++++++++++++++++++++++++", +"+++++++++++++++++++++++++ +++++++++++++++++++++++++", +"++++++++++++++++++++ ++++++++++++++++++++", +"++++++++++++++++++++ ++++++++++++++++++++", +"++++++++++++++++++++ ++++++++++++++++++++", +"++++++++++++++++++++ ++++++++++++++++++++", +"+++++++++++++++ +++++++++++++++", +"+++++++++++++++ +++++++++++++++", +"+++++++++++++++ +++++++++++++++", +"+++++++++++++++ +++++++++++++++", +"+++++++++++++++ +++++++++++++++", +"++++++++++ ++++++++++", +"++++++++++ ++++++++++", +"++++++++++ ++++++++++", +"++++++++++ ++++++++++", +"++++++++++ ++++++++++", +" ", +" ", +" ", +" ", +" ", +" ", +" ", +" ", +" ", +" ", +" ", +" ", +" ", +" ", +" ", +" ", +" ", +" ", +" ", +" "}; diff --git a/hacks/images/pacman/pacman-ds1.xpm b/hacks/images/pacman/pacman-ds1.xpm new file mode 100644 index 00000000..abdd334c --- /dev/null +++ b/hacks/images/pacman/pacman-ds1.xpm @@ -0,0 +1,69 @@ +/* XPM */ +static char * pacman_ds1_xpm[] = { +"64 64 2 1", +" c #FFFF00", +". c None ", +"................................................................", +"................................................................", +"................................................................", +"................................................................", +"................................................................", +"................................................................", +"................................................................", +"................................................................", +"................................................................", +"................................................................", +"................................................................", +"................................................................", +"................................................................", +".... ...................................... ....", +".... ...................................... ....", +".... ...................................... ....", +".... ...................................... ....", +".... .............................. ....", +".... .............................. ....", +".... .............................. ....", +".... .............................. ....", +".... ...................... ....", +".... ...................... ....", +".... ...................... ....", +".... ...................... ....", +".... ...................... ....", +".... ............ ....", +".... ............ ....", +".... ............ ....", +".... ............ ....", +".... .... ....", +".... .... ....", +".... .... ....", +".... .... ....", +"......... .........", +"......... .........", +"......... .........", +"......... .........", +"......... .........", +"......... .........", +"......... .........", +"......... .........", +"......... .........", +"............. .............", +"............. .............", +"............. .............", +"............. .............", +"..................... .....................", +"..................... .....................", +"..................... .....................", +"..................... .....................", +"................................................................", +"................................................................", +"................................................................", +"................................................................", +"................................................................", +"................................................................", +"................................................................", +"................................................................", +"................................................................", +"................................................................", +"................................................................", +"................................................................", +"................................................................"}; diff --git a/hacks/images/pacman/pacman-ds2.xpm b/hacks/images/pacman/pacman-ds2.xpm new file mode 100644 index 00000000..d9847ab7 --- /dev/null +++ b/hacks/images/pacman/pacman-ds2.xpm @@ -0,0 +1,69 @@ +/* XPM */ +static char * pacman_ds2_xpm[] = { +"64 64 2 1", +" c #FFFF00", +". c None ", +"................................................................", +"................................................................", +"................................................................", +"................................................................", +"................................................................", +"................................................................", +"................................................................", +"................................................................", +"................................................................", +"................................................................", +"................................................................", +"................................................................", +"................................................................", +"................................................................", +"................................................................", +"................................................................", +"................................................................", +"................................................................", +"................................................................", +"................................................................", +"................................................................", +"................................................................", +"................................................................", +"................................................................", +"................................................................", +"................................................................", +" ...................................... ", +" ...................................... ", +" ...................................... ", +" ...................................... ", +" ............ ", +" ............ ", +" ............ ", +" ............ ", +" ", +" ", +" ", +" ", +".... ....", +".... ....", +".... ....", +".... ....", +".... ....", +"......... .........", +"......... .........", +"......... .........", +"......... .........", +"................. .... .................", +"................. .... .................", +"................. .... .................", +"................. .... .................", +"................................................................", +"................................................................", +"................................................................", +"................................................................", +"................................................................", +"................................................................", +"................................................................", +"................................................................", +"................................................................", +"................................................................", +"................................................................", +"................................................................", +"................................................................"}; diff --git a/hacks/images/pacman/pacman-ds3.xpm b/hacks/images/pacman/pacman-ds3.xpm new file mode 100644 index 00000000..60709e77 --- /dev/null +++ b/hacks/images/pacman/pacman-ds3.xpm @@ -0,0 +1,69 @@ +/* XPM */ +static char * pacman_ds3_xpm[] = { +"64 64 2 1", +" c #FFFF00", +". c None ", +"................................................................", +"................................................................", +"................................................................", +"................................................................", +"................................................................", +"................................................................", +"................................................................", +"................................................................", +"................................................................", +"................................................................", +"................................................................", +"................................................................", +"................................................................", +"................................................................", +"................................................................", +"................................................................", +"................................................................", +"................................................................", +"................................................................", +"................................................................", +"................................................................", +"................................................................", +"................................................................", +"................................................................", +"................................................................", +"................................................................", +"................................................................", +"................................................................", +"................................................................", +"................................................................", +" .............................. ", +" .............................. ", +" .............................. ", +" .............................. ", +" ", +" ", +" ", +" ", +" ", +" ", +" ", +" ", +" ", +".... ....", +".... ....", +".... ....", +".... ....", +"............. .... .............", +"............. .... .............", +"............. .... .............", +"............. .... .............", +"................................................................", +"................................................................", +"................................................................", +"................................................................", +"................................................................", +"................................................................", +"................................................................", +"................................................................", +"................................................................", +"................................................................", +"................................................................", +"................................................................", +"................................................................"}; diff --git a/hacks/images/pacman/pacman-ds4.xpm b/hacks/images/pacman/pacman-ds4.xpm new file mode 100644 index 00000000..dc2cbdc7 --- /dev/null +++ b/hacks/images/pacman/pacman-ds4.xpm @@ -0,0 +1,69 @@ +/* XPM */ +static char * pacman_ds4_xpm[] = { +"64 64 2 1", +" c #FFFF00", +". c None", +"................................................................", +"................................................................", +"................................................................", +"................................................................", +"................................................................", +"................................................................", +"................................................................", +"................................................................", +"................................................................", +"................................................................", +"................................................................", +"................................................................", +"................................................................", +"................................................................", +"................................................................", +"................................................................", +"................................................................", +"................................................................", +"................................................................", +"................................................................", +"................................................................", +"................................................................", +"................................................................", +"................................................................", +"................................................................", +"................................................................", +"................................................................", +"................................................................", +"................................................................", +"................................................................", +"................................................................", +"................................................................", +"................................................................", +"................................................................", +"................. .................", +"................. .................", +"................. .................", +"................. .................", +" ", +" ", +" ", +" ", +" ", +" ", +" ", +" ", +" ", +".... ....", +".... ....", +".... ....", +".... ....", +"............. .... .............", +"............. .... .............", +"............. .... .............", +"............. .... .............", +"................................................................", +"................................................................", +"................................................................", +"................................................................", +"................................................................", +"................................................................", +"................................................................", +"................................................................", +"................................................................"}; diff --git a/hacks/images/pacman/pacman-ds5.xpm b/hacks/images/pacman/pacman-ds5.xpm new file mode 100644 index 00000000..87ed8f94 --- /dev/null +++ b/hacks/images/pacman/pacman-ds5.xpm @@ -0,0 +1,69 @@ +/* XPM */ +static char * pacman_ds5_xpm[] = { +"64 64 2 1", +" c #FFFF00", +". c None ", +"................................................................", +"................................................................", +"................................................................", +"................................................................", +"................................................................", +"................................................................", +"................................................................", +"................................................................", +"................................................................", +"................................................................", +"................................................................", +"................................................................", +"................................................................", +"................................................................", +"................................................................", +"................................................................", +"................................................................", +"................................................................", +"................................................................", +"................................................................", +"................................................................", +"................................................................", +"................................................................", +"................................................................", +"................................................................", +"................................................................", +"................................................................", +"................................................................", +"................................................................", +"................................................................", +"................................................................", +"................................................................", +"................................................................", +"................................................................", +".............................. ..............................", +".............................. ..............................", +".............................. ..............................", +".............................. ..............................", +".......................... ..........................", +".......................... ..........................", +".......................... ..........................", +".......................... ..........................", +".......................... ..........................", +"................. .................", +"................. .................", +"................. .................", +"................. .................", +"............. .............", +"............. .............", +"............. .............", +"............. .............", +".... ....", +".... ....", +".... ....", +".... ....", +".... .... ....", +".... .... ....", +".... .... ....", +".... .... ....", +".... .... ....", +"......... ............ .........", +"......... ............ .........", +"......... ............ .........", +"......... ............ ........."}; diff --git a/hacks/images/pacman/pacman-ds6.xpm b/hacks/images/pacman/pacman-ds6.xpm new file mode 100644 index 00000000..87636165 --- /dev/null +++ b/hacks/images/pacman/pacman-ds6.xpm @@ -0,0 +1,69 @@ +/* XPM */ +static char * pacman_ds6_xpm[] = { +"64 64 2 1", +" c #FFFF00", +". c None ", +"................................................................", +"................................................................", +"................................................................", +"................................................................", +"................................................................", +"................................................................", +"................................................................", +"................................................................", +"................................................................", +"................................................................", +"................................................................", +"................................................................", +"................................................................", +"................................................................", +"................................................................", +"................................................................", +"................................................................", +"................................................................", +"................................................................", +"................................................................", +"................................................................", +"................................................................", +"................................................................", +"................................................................", +"................................................................", +"................................................................", +"................................................................", +"................................................................", +"................................................................", +"................................................................", +"................................................................", +"................................................................", +"................................................................", +"................................................................", +".............................. ..............................", +".............................. ..............................", +".............................. ..............................", +".............................. ..............................", +".......................... ..........................", +".......................... ..........................", +".......................... ..........................", +".......................... ..........................", +".......................... ..........................", +"..................... .....................", +"..................... .....................", +"..................... .....................", +"..................... .....................", +"..................... .....................", +"..................... .....................", +"..................... .....................", +"..................... .....................", +"................. .................", +"................. .................", +"................. .................", +"................. .................", +"............. .............", +"............. .............", +"............. .............", +"............. .............", +"............. .............", +"................. .... .................", +"................. .... .................", +"................. .... .................", +"................. .... ................."}; diff --git a/hacks/images/pacman/pacman-ds7.xpm b/hacks/images/pacman/pacman-ds7.xpm new file mode 100644 index 00000000..4b895778 --- /dev/null +++ b/hacks/images/pacman/pacman-ds7.xpm @@ -0,0 +1,69 @@ +/* XPM */ +static char * pacman_ds7_xpm[] = { +"64 64 2 1", +" c #FFFF00", +". c None ", +"................................................................", +"................................................................", +"................................................................", +"................................................................", +"................................................................", +"................................................................", +"................................................................", +"................................................................", +"................................................................", +"................................................................", +"................................................................", +"................................................................", +"................................................................", +"................................................................", +"................................................................", +"................................................................", +"................................................................", +"................................................................", +"................................................................", +"................................................................", +"................................................................", +"................................................................", +"................................................................", +"................................................................", +"................................................................", +"................................................................", +"................................................................", +"................................................................", +"................................................................", +"................................................................", +"................................................................", +"................................................................", +"................................................................", +"................................................................", +".............................. ..............................", +".............................. ..............................", +".............................. ..............................", +".............................. ..............................", +".............................. ..............................", +".............................. ..............................", +".............................. ..............................", +".............................. ..............................", +".............................. ..............................", +".............................. ..............................", +".............................. ..............................", +".............................. ..............................", +".............................. ..............................", +".............................. ..............................", +".............................. ..............................", +".............................. ..............................", +".............................. ..............................", +".............................. ..............................", +".............................. ..............................", +".............................. ..............................", +".............................. ..............................", +".............................. ..............................", +".............................. ..............................", +".............................. ..............................", +".............................. ..............................", +".............................. ..............................", +"................................................................", +"................................................................", +"................................................................", +"................................................................"}; diff --git a/hacks/images/pacman/pacman-ds8.xpm b/hacks/images/pacman/pacman-ds8.xpm new file mode 100644 index 00000000..3488f98b --- /dev/null +++ b/hacks/images/pacman/pacman-ds8.xpm @@ -0,0 +1,69 @@ +/* XPM */ +static char * pacman_ds8_xpm[] = { +"64 64 2 1", +" c #FFFF00", +". c None ", +"................................................................", +"................................................................", +"................................................................", +"................................................................", +"................................................................", +"................................................................", +"................................................................", +"................................................................", +"................................................................", +"................................................................", +"................................................................", +"................................................................", +"................................................................", +"................................................................", +"................................................................", +"................................................................", +"................................................................", +"................................................................", +"................................................................", +"................................................................", +"................................................................", +"..................... ............ .....................", +"..................... ............ .....................", +"..................... ............ .....................", +"..................... ............ .....................", +"..................... ............ .....................", +"............. ......... .... ..........................", +"............. ......... .... ..........................", +"............. ......... .... ..........................", +"............. ......... .... ..........................", +"................. .......................... .............", +"................. .......................... .............", +"................. .......................... .............", +"................. .......................... .............", +"........................................... .................", +"........................................... .................", +"........................................... .................", +"........................................... .................", +"......... ...............................................", +"......... ...............................................", +"......... ...............................................", +"......... ...............................................", +"......... ...............................................", +"............................................... .........", +"............................................... .........", +"............................................... .........", +"............................................... .........", +"................. ...........................................", +"................. ...........................................", +"................. ...........................................", +"................. ...........................................", +"............. .......................... .................", +"............. .......................... .................", +"............. .......................... .................", +"............. .......................... .................", +".......................... .... ......... .............", +".......................... .... ......... .............", +".......................... .... ......... .............", +".......................... .... ......... .............", +".......................... .... ......... .............", +"..................... ............ .....................", +"..................... ............ .....................", +"..................... ............ .....................", +"..................... ............ ....................."}; diff --git a/hacks/images/pacman/pacman-l1.xpm b/hacks/images/pacman/pacman-l1.xpm new file mode 100644 index 00000000..d91a1154 --- /dev/null +++ b/hacks/images/pacman/pacman-l1.xpm @@ -0,0 +1,69 @@ +/* XPM */ +static char * pacman_l1_xpm[] = { +"64 64 2 1", +" c None", +". c #FFFF00", +" ........................ ", +" ........................ ", +" ........................ ", +" ........................ ", +" ........................ ", +" ............................................ ", +" ............................................ ", +" ............................................ ", +" ............................................ ", +" ............................................ ", +" ...................................................... ", +" ...................................................... ", +" ...................................................... ", +" ...................................................... ", +" ...................................................... ", +" ...................................................... ", +" ...................................................... ", +" ...................................................... ", +" ...................................................... ", +" ...................................................... ", +" .................................................", +" .................................................", +" .................................................", +" .................................................", +" .................................................", +" ..................................", +" ..................................", +" ..................................", +" ..................................", +" ..................................", +" ....................", +" ....................", +" ....................", +" ....................", +" ..................................", +" ..................................", +" ..................................", +" ..................................", +" ..................................", +" .................................................", +" .................................................", +" .................................................", +" .................................................", +" .................................................", +" ...................................................... ", +" ...................................................... ", +" ...................................................... ", +" ...................................................... ", +" ...................................................... ", +" ...................................................... ", +" ...................................................... ", +" ...................................................... ", +" ...................................................... ", +" ...................................................... ", +" ............................................ ", +" ............................................ ", +" ............................................ ", +" ............................................ ", +" ............................................ ", +" ........................ ", +" ........................ ", +" ........................ ", +" ........................ ", +" ........................ "}; diff --git a/hacks/images/pacman/pacman-l2.xpm b/hacks/images/pacman/pacman-l2.xpm new file mode 100644 index 00000000..67c815dc --- /dev/null +++ b/hacks/images/pacman/pacman-l2.xpm @@ -0,0 +1,69 @@ +/* XPM */ +static char * pacman_l2_xpm[] = { +"64 64 2 1", +" c None", +"+ c #FFFF00", +" ++++++++++++++++++++++++ ", +" ++++++++++++++++++++++++ ", +" ++++++++++++++++++++++++ ", +" ++++++++++++++++++++++++ ", +" ++++++++++++++++++++++++ ", +" ++++++++++++++++++++++++++++++++++ ", +" ++++++++++++++++++++++++++++++++++ ", +" ++++++++++++++++++++++++++++++++++ ", +" ++++++++++++++++++++++++++++++++++ ", +" ++++++++++++++++++++++++++++++++++ ", +" ++++++++++++++++++++++++++++++++++ ", +" ++++++++++++++++++++++++++++++++++ ", +" ++++++++++++++++++++++++++++++++++ ", +" ++++++++++++++++++++++++++++++++++ ", +" ++++++++++++++++++++++++++++++++++ ", +" +++++++++++++++++++++++++++++ ", +" +++++++++++++++++++++++++++++ ", +" +++++++++++++++++++++++++++++ ", +" +++++++++++++++++++++++++++++ ", +" +++++++++++++++++++++++++++++ ", +" ++++++++++++++++++++++++++++++", +" ++++++++++++++++++++++++++++++", +" ++++++++++++++++++++++++++++++", +" ++++++++++++++++++++++++++++++", +" ++++++++++++++++++++++++++++++", +" +++++++++++++++++++++++++", +" +++++++++++++++++++++++++", +" +++++++++++++++++++++++++", +" +++++++++++++++++++++++++", +" +++++++++++++++++++++++++", +" ++++++++++++++++++++", +" ++++++++++++++++++++", +" ++++++++++++++++++++", +" ++++++++++++++++++++", +" +++++++++++++++++++++++++", +" +++++++++++++++++++++++++", +" +++++++++++++++++++++++++", +" +++++++++++++++++++++++++", +" +++++++++++++++++++++++++", +" ++++++++++++++++++++++++++++++", +" ++++++++++++++++++++++++++++++", +" ++++++++++++++++++++++++++++++", +" ++++++++++++++++++++++++++++++", +" ++++++++++++++++++++++++++++++", +" +++++++++++++++++++++++++++++ ", +" +++++++++++++++++++++++++++++ ", +" +++++++++++++++++++++++++++++ ", +" +++++++++++++++++++++++++++++ ", +" +++++++++++++++++++++++++++++ ", +" ++++++++++++++++++++++++++++++++++ ", +" ++++++++++++++++++++++++++++++++++ ", +" ++++++++++++++++++++++++++++++++++ ", +" ++++++++++++++++++++++++++++++++++ ", +" ++++++++++++++++++++++++++++++++++ ", +" ++++++++++++++++++++++++++++++++++ ", +" ++++++++++++++++++++++++++++++++++ ", +" ++++++++++++++++++++++++++++++++++ ", +" ++++++++++++++++++++++++++++++++++ ", +" ++++++++++++++++++++++++++++++++++ ", +" ++++++++++++++++++++++++ ", +" ++++++++++++++++++++++++ ", +" ++++++++++++++++++++++++ ", +" ++++++++++++++++++++++++ ", +" ++++++++++++++++++++++++ "}; diff --git a/hacks/images/pacman/pacman-r1.xpm b/hacks/images/pacman/pacman-r1.xpm new file mode 100644 index 00000000..7b794ccb --- /dev/null +++ b/hacks/images/pacman/pacman-r1.xpm @@ -0,0 +1,69 @@ +/* XPM */ +static char * pacman_r1_xpm[] = { +"64 64 2 1", +" c None", +". c #FFFF00", +" ........................ ", +" ........................ ", +" ........................ ", +" ........................ ", +" ........................ ", +" ............................................ ", +" ............................................ ", +" ............................................ ", +" ............................................ ", +" ............................................ ", +" ...................................................... ", +" ...................................................... ", +" ...................................................... ", +" ...................................................... ", +" ...................................................... ", +" ...................................................... ", +" ...................................................... ", +" ...................................................... ", +" ...................................................... ", +" ...................................................... ", +"................................................. ", +"................................................. ", +"................................................. ", +"................................................. ", +"................................................. ", +".................................. ", +".................................. ", +".................................. ", +".................................. ", +".................................. ", +".................... ", +".................... ", +".................... ", +".................... ", +".................................. ", +".................................. ", +".................................. ", +".................................. ", +".................................. ", +"................................................. ", +"................................................. ", +"................................................. ", +"................................................. ", +"................................................. ", +" ...................................................... ", +" ...................................................... ", +" ...................................................... ", +" ...................................................... ", +" ...................................................... ", +" ...................................................... ", +" ...................................................... ", +" ...................................................... ", +" ...................................................... ", +" ...................................................... ", +" ............................................ ", +" ............................................ ", +" ............................................ ", +" ............................................ ", +" ............................................ ", +" ........................ ", +" ........................ ", +" ........................ ", +" ........................ ", +" ........................ "}; diff --git a/hacks/images/pacman/pacman-r2.xpm b/hacks/images/pacman/pacman-r2.xpm new file mode 100644 index 00000000..51c8155d --- /dev/null +++ b/hacks/images/pacman/pacman-r2.xpm @@ -0,0 +1,69 @@ +/* XPM */ +static char * pacman_r2_xpm[] = { +"64 64 2 1", +" c None", +"+ c #FFFF00", +" ++++++++++++++++++++++++ ", +" ++++++++++++++++++++++++ ", +" ++++++++++++++++++++++++ ", +" ++++++++++++++++++++++++ ", +" ++++++++++++++++++++++++ ", +" ++++++++++++++++++++++++++++++++++ ", +" ++++++++++++++++++++++++++++++++++ ", +" ++++++++++++++++++++++++++++++++++ ", +" ++++++++++++++++++++++++++++++++++ ", +" ++++++++++++++++++++++++++++++++++ ", +" ++++++++++++++++++++++++++++++++++ ", +" ++++++++++++++++++++++++++++++++++ ", +" ++++++++++++++++++++++++++++++++++ ", +" ++++++++++++++++++++++++++++++++++ ", +" ++++++++++++++++++++++++++++++++++ ", +" +++++++++++++++++++++++++++++ ", +" +++++++++++++++++++++++++++++ ", +" +++++++++++++++++++++++++++++ ", +" +++++++++++++++++++++++++++++ ", +" +++++++++++++++++++++++++++++ ", +"++++++++++++++++++++++++++++++ ", +"++++++++++++++++++++++++++++++ ", +"++++++++++++++++++++++++++++++ ", +"++++++++++++++++++++++++++++++ ", +"++++++++++++++++++++++++++++++ ", +"+++++++++++++++++++++++++ ", +"+++++++++++++++++++++++++ ", +"+++++++++++++++++++++++++ ", +"+++++++++++++++++++++++++ ", +"+++++++++++++++++++++++++ ", +"++++++++++++++++++++ ", +"++++++++++++++++++++ ", +"++++++++++++++++++++ ", +"++++++++++++++++++++ ", +"+++++++++++++++++++++++++ ", +"+++++++++++++++++++++++++ ", +"+++++++++++++++++++++++++ ", +"+++++++++++++++++++++++++ ", +"+++++++++++++++++++++++++ ", +"++++++++++++++++++++++++++++++ ", +"++++++++++++++++++++++++++++++ ", +"++++++++++++++++++++++++++++++ ", +"++++++++++++++++++++++++++++++ ", +"++++++++++++++++++++++++++++++ ", +" +++++++++++++++++++++++++++++ ", +" +++++++++++++++++++++++++++++ ", +" +++++++++++++++++++++++++++++ ", +" +++++++++++++++++++++++++++++ ", +" +++++++++++++++++++++++++++++ ", +" ++++++++++++++++++++++++++++++++++ ", +" ++++++++++++++++++++++++++++++++++ ", +" ++++++++++++++++++++++++++++++++++ ", +" ++++++++++++++++++++++++++++++++++ ", +" ++++++++++++++++++++++++++++++++++ ", +" ++++++++++++++++++++++++++++++++++ ", +" ++++++++++++++++++++++++++++++++++ ", +" ++++++++++++++++++++++++++++++++++ ", +" ++++++++++++++++++++++++++++++++++ ", +" ++++++++++++++++++++++++++++++++++ ", +" ++++++++++++++++++++++++ ", +" ++++++++++++++++++++++++ ", +" ++++++++++++++++++++++++ ", +" ++++++++++++++++++++++++ ", +" ++++++++++++++++++++++++ "}; diff --git a/hacks/images/pacman/pacman-u1.xpm b/hacks/images/pacman/pacman-u1.xpm new file mode 100644 index 00000000..a5bb69d4 --- /dev/null +++ b/hacks/images/pacman/pacman-u1.xpm @@ -0,0 +1,69 @@ +/* XPM */ +static char * pacman_u1_xpm[] = { +"64 64 2 1", +" c None", +". c #FFFF00", +" ", +" ", +" ", +" ", +" ", +" .......... .......... ", +" .......... .......... ", +" .......... .......... ", +" .......... .......... ", +" .......... .......... ", +" ............... ............... ", +" ............... ............... ", +" ............... ............... ", +" ............... ............... ", +" ............... ............... ", +" .................... .................... ", +" .................... .................... ", +" .................... .................... ", +" .................... .................... ", +" .................... .................... ", +"......................... .........................", +"......................... .........................", +"......................... .........................", +"......................... .........................", +"......................... .........................", +"......................... .........................", +"......................... .........................", +"......................... .........................", +"......................... .........................", +"......................... .........................", +".............................. ..............................", +".............................. ..............................", +".............................. ..............................", +".............................. ..............................", +".............................. ..............................", +".............................. ..............................", +".............................. ..............................", +".............................. ..............................", +".............................. ..............................", +".............................. ..............................", +".............................. ..............................", +".............................. ..............................", +".............................. ..............................", +".............................. ..............................", +" ...................................................... ", +" ...................................................... ", +" ...................................................... ", +" ...................................................... ", +" ...................................................... ", +" ...................................................... ", +" ...................................................... ", +" ...................................................... ", +" ...................................................... ", +" ...................................................... ", +" ............................................ ", +" ............................................ ", +" ............................................ ", +" ............................................ ", +" ............................................ ", +" ........................ ", +" ........................ ", +" ........................ ", +" ........................ ", +" ........................ "}; diff --git a/hacks/images/pacman/pacman-u2.xpm b/hacks/images/pacman/pacman-u2.xpm new file mode 100644 index 00000000..777e4c6e --- /dev/null +++ b/hacks/images/pacman/pacman-u2.xpm @@ -0,0 +1,69 @@ +/* XPM */ +static char * pacman_u2_xpm[] = { +"64 64 2 1", +" c None", +"+ c #FFFF00", +" ", +" ", +" ", +" ", +" ", +" ", +" ", +" ", +" ", +" ", +" ", +" ", +" ", +" ", +" ", +" ", +" ", +" ", +" ", +" ", +"++++++++++ ++++++++++", +"++++++++++ ++++++++++", +"++++++++++ ++++++++++", +"++++++++++ ++++++++++", +"++++++++++ ++++++++++", +"+++++++++++++++ +++++++++++++++", +"+++++++++++++++ +++++++++++++++", +"+++++++++++++++ +++++++++++++++", +"+++++++++++++++ +++++++++++++++", +"+++++++++++++++ +++++++++++++++", +"++++++++++++++++++++ ++++++++++++++++++++", +"++++++++++++++++++++ ++++++++++++++++++++", +"++++++++++++++++++++ ++++++++++++++++++++", +"++++++++++++++++++++ ++++++++++++++++++++", +"+++++++++++++++++++++++++ +++++++++++++++++++++++++", +"+++++++++++++++++++++++++ +++++++++++++++++++++++++", +"+++++++++++++++++++++++++ +++++++++++++++++++++++++", +"+++++++++++++++++++++++++ +++++++++++++++++++++++++", +"+++++++++++++++++++++++++ +++++++++++++++++++++++++", +"++++++++++++++++++++++++++++++ ++++++++++++++++++++++++++++++", +"++++++++++++++++++++++++++++++ ++++++++++++++++++++++++++++++", +"++++++++++++++++++++++++++++++ ++++++++++++++++++++++++++++++", +"++++++++++++++++++++++++++++++ ++++++++++++++++++++++++++++++", +"++++++++++++++++++++++++++++++ ++++++++++++++++++++++++++++++", +" ++++++++++++++++++++++++++++++++++++++++++++++++++++++ ", +" ++++++++++++++++++++++++++++++++++++++++++++++++++++++ ", +" ++++++++++++++++++++++++++++++++++++++++++++++++++++++ ", +" ++++++++++++++++++++++++++++++++++++++++++++++++++++++ ", +" ++++++++++++++++++++++++++++++++++++++++++++++++++++++ ", +" ++++++++++++++++++++++++++++++++++++++++++++++++++++++ ", +" ++++++++++++++++++++++++++++++++++++++++++++++++++++++ ", +" ++++++++++++++++++++++++++++++++++++++++++++++++++++++ ", +" ++++++++++++++++++++++++++++++++++++++++++++++++++++++ ", +" ++++++++++++++++++++++++++++++++++++++++++++++++++++++ ", +" ++++++++++++++++++++++++++++++++++++++++++++ ", +" ++++++++++++++++++++++++++++++++++++++++++++ ", +" ++++++++++++++++++++++++++++++++++++++++++++ ", +" ++++++++++++++++++++++++++++++++++++++++++++ ", +" ++++++++++++++++++++++++++++++++++++++++++++ ", +" ++++++++++++++++++++++++ ", +" ++++++++++++++++++++++++ ", +" ++++++++++++++++++++++++ ", +" ++++++++++++++++++++++++ ", +" ++++++++++++++++++++++++ "}; diff --git a/hacks/images/sball-bg.xpm b/hacks/images/sball-bg.xpm new file mode 100644 index 00000000..8f51705c --- /dev/null +++ b/hacks/images/sball-bg.xpm @@ -0,0 +1,355 @@ +/* XPM */ +static char *sball_bg[] = { +/* width height ncolors chars_per_pixel */ +"256 256 92 1", +/* colors */ +" c #1D6868", +". c #284848", +"X c #DF0305", +"o c #4B4646", +"O c #165757", +"+ c #80B4B5", +"@ c #0C7271", +"# c #092A29", +"$ c #3B595A", +"% c #4C3636", +"& c #7F393A", +"* c #7F3030", +"= c #A80406", +"- c #2F7F7F", +"; c #B80405", +": c #2F9596", +"> c #855D5D", +", c #3B7777", +"< c #A01818", +"1 c #409596", +"2 c #177271", +"3 c #1F3637", +"4 c #A67E7D", +"5 c #382828", +"6 c #56A8A8", +"7 c #350304", +"8 c #548585", +"9 c #176060", +"0 c #480506", +"q c #5D5A59", +"w c #758181", +"e c #CB5F5F", +"r c #37393A", +"t c #386969", +"y c #74999A", +"u c #B0CBCB", +"i c #3F8B8A", +"p c #CF3B3B", +"a c #980405", +"s c #055051", +"d c #790304", +"f c #874343", +"g c #86504F", +"h c #9D2827", +"j c #EE090A", +"k c #075859", +"l c #CC2727", +"z c #609696", +"x c #963637", +"c c #880305", +"v c #C71818", +"b c #290707", +"n c #6F1717", +"m c #73A5A5", +"M c #1E1313", +"N c #208988", +"B c #491919", +"V c #287272", +"C c #419F9E", +"Z c #137D7E", +"A c #0A6868", +"S c #073637", +"D c #B29D9D", +"F c #2E2222", +"G c #686868", +"H c #6E7271", +"J c #734A4B", +"K c #680305", +"L c #716060", +"P c #175050", +"I c #486969", +"U c #795454", +"Y c #547778", +"T c #064949", +"R c #285050", +"E c #074040", +"W c #482727", +"Q c #4F9697", +"! c #308A89", +"~ c #7B2121", +"^ c #1A4242", +"/ c #A53D3D", +"( c #1A2121", +") c #580405", +"_ c #09605F", +"` c #571E1E", +"' c #C70405", +"] c #81C4C4", +"[ c #207E7F", +"{ c #285C5C", +"} c #608A89", +"| c None", +/* pixels */ +"2[2[-[----i-iii!iii!i!!!!!-!!N!!N!!!!!!!!!!!!!!i!!i!i!iiiiiiiii8i888YYYHGLqUJffxxh<=acnn`B5F^^TPk 22[[N!!!!:!!:!!!!!-[[V22 99OPP^...3.r3rrrrrrrrrrrrrrR...RRR{{{{{{{t {t t ttttttttttttttI,I,IYI,YYYY}Y}wwwwyD+u]uuu]y}8It{99A A2222VV tt tttttVtVVVVV2[22[22[2", +"2V[VVV-,-i,ii,iiiiiiiii,!-!-!--[!-N[![!N-!!!!!!!!i!!!i!!i!iiiii8i8Y8YYGGGqLUJffxh<GqJoJ%J%%o%%ro%oooJqqLGHwwwyD++]]]]]]]]", +"6mm6mz6zQzQzQ}Q}Q}z}zzzyzmyym]]]u]u]u]u]D+mww8GIIt${{{OOOO___AA 2 2 Vt$$qoo&``~dddcddddKKK)))0)00000))))KKKKddcdcdcn~*~*&foJJqqqqqqqIGIqGIGYqGIqGqqLqJqJJJ&x&x~hnLLqJJJo&oJ%J%ooJJqUqHHww4y++]]]]]]]]]6", +"m66Q6QQQQQ8Qi8Qi8QQi8Q}zzzzymm6]]]u]]uu]]+DywwHGI$$$R{RPOOOk___A@ 22{V{$$$oJo``n~ddcddddKKKKK))))))))K)KKdKdddccdc~~n~&%JJJoqoqqIqqIIIIIIYIIYIItGIIYqqqLqJJJf&&x~h~<H>LLJJqJJJJJJqJqJLLHHwwyy+++]]]]]]6]66", +"6Q6QQQ181i8iQiii8ii8i8Q8QQzz6mm6]]]]]]u]u]++mw}wYqIo${RRPPPOk___AA 2 $$R$oJ%~`nddcdddddKdKKKKKKKKKKKKKdddcddccd~~*~&%JJoqqqIqI$IIIIIYIY,I,,tIIIIIIIGIqqqqJJJJ&&x*c<~acccdddKK))B0FbF(F#(S3ETsk__@22ZNN::CCCC]66]6++yyy4wHHLLUqUJoJqJqJqqLH>HwwwyDm+]]]]]6]]666", +"Q6QQ1Q1iiiiiiiiiiiiii8iQ8QzQzz6m6]]]]]]u]]u+yywwHIqIR$RRPPPsOk___A A V{{t$oo%%&`n~dddcddddKdKKKKKKKKKdddddddcdddn~~~%JJooqq$$qIIIItIt,t,V,,t,I,,,IYIIIqqqqqqJof&&***~L>LUqUJUqUq>L>HH4w4my+m+]]]]]]66666", +"6QQQ11i1iiiiii,iii,iiiiiQ8QQzz6mm6]]]]]]]u+]DyywYHIq$$$R.PPPkkk__AA 9V{$R$oo%%~nKdddddddddKdKdKKKKdKdKdddddcdc~n*`&&%JJoqoqI$IIItI,,,t,t,t,-,,It,tIIIIIIqqqJqJJJ&*h*<~cccccdddK))00BbFM((#3SE^Tkk_A2ZNNN::CC66666]6+mmywwwHHHLLULUUqUUL>H>Hwwywyy+++]]6]C]6]666", +"QC111iiii!!--!--!,:,iii8i8QQQzz66m6]]]]u]u]]++ywwHIq$$r.R^^PsOk___AA {{ $qooo%~`ndddcddddddddKdddKddddddcdcddnn~~&%J%oqq$q$qIttt,,t,t,-,-t,t-,,,t,,IIIIIqqqqJqJ&&&*~~H>L>GL>LLLHLwH4wwyD+m+]6]]]]C66666", +"CQ1111i!i!i-i-!------iiiiii8QQQzm6]6]]]]]]]u++DwwHGq$o$$..P^Pskk___A9 At{$Roo%%``ndddddcddddddddKdddddddcddddcn~`~%J%Joqoq$ItItttt,VV-VtVVV-,V-t-,t,,tIIIIIqqqqoJo&&~h~~cccccdddK))0B0bB(M((#SEETsk_A@@ZNN::CCC6C666+mmyyyw4wH4wLH>LLLH>HHHwwwDyy++6+]]6]C]6666C", +"C111!!!!!--!--------i--iiiiiQQQQ6zm6]]]]]u]]++mywwHGq$o...P^Psskk_A_ A{{{$$.oo&W*nndddddcddddddddddddddddcdddn~~~&%&ooo$$IItIttt,VtVVVV-V-V-V-VV,t,t,,ItII$qIoqJJJ%&&~*<~cccdddKKK))00FbBM((3(SEEssk_A2ZNNN::CCC66]66+6+yywywwH>wLw>H>wH4H4wwyyy+m++]6]666666C6C", +"1111!i!!-!--[--[---------iiii1QQQ6666]]]]]]]u+DywwYqIqo$...^^PPkkk_A_ {{$$oo%%``ndddcddcdddddddddddddcdddd~nn~%&oooqq$q$$$tttVtVVVVVVVV[VVVV-V-V-V,t,tIII$IqqqoJf%&~~~ccccccdddKK)000bbBM(((#3ETsk_A@@ZNN::CCC6C666+myyyDww4www>H4HHH4Lwwy4yyymm]6]6]6]6]666CC", +"1:1!!!!-N-[[-[[-V[[-----!-iiiiQQQ6m66]6]]]]]]++mywwHqq$o...P^Tssk___ _A {{$$oo%%`nnKdddddddcddddddddcdcddddnnn~`%%oJo$oqI$ttt VtVVVVVV[V2V2[V2VVV[V,V,t,tIIqIqqqJoJJ*&~*~ccccdcddKK)))07FbFM(3#SSETsk_A@@ZNN::CCC6C]C66+mzyywww4H4HH>w>wwwwwyyy+m++6]]666]CC6CCC", +":1:!!!![-[-[[[V[V[V[V[[----!iii1QQQ666]]]]]]]u+yDwHHGq$o.o3^^P^ssk___9 {{R$ror&%`nnKdddcdcddddddddcdddddddc~`*%&Jooqo$$t$ttttVVVVV2V2V2[2V2[V[V[VVVtV,,tttII$$qqoJ%J%*~hncdccddddKK))007bBM(M(#3EEss_A@@ZZ:::CCC6CC]666mmyyywwwwwww4ww4wy4wyDymm+6]]C]]666C6CCC", +"1:!!!![![[[V2V[22[V2[V[-[-!-i!i11Q6Q66]6]]]]]]++yywHHqqooR.rT^Psskk__A999{{$.oo%``nndddddddcdcdcdcddcdddddnn`*`%o%oooI$$t$t tV VV2V2V222V22V2222VV[VVVVttttIIqIoqqoJJ**~n~~ccdcdddKK)))007bFMM3##SETsk_A@ZZNN::CCCC6C66+6mmyyy4wwwwwwwwwwwyyyymmm]6]666666C6CCC:", +":!:!![N[[[2[2[22V22V2V[V[---!!ii11Q666C]]]]]]]+D+wwwHqq$oor^.^T^sskk__A {{R$oo%%``nKKdddcddddcdddcddddddnnn`~%&oJoq$$I$$ttt VtV V2V22V222222[2V222VVVVVV,tttI$q$qqoo&%&~nncdccddddKK))00B77b(M(#3SETsk_A@ZZN::CCCC666666myyyywyw4w4ww4wy4yyymy+66]66]66]6C6CC:C", +":!!N![[[[[2[22222222222[[[[--!!ii11QC6666]]]]]]++y4}HGqooRr.3^^^Tskk___99{{{$.o%%``nndKddddcdcddcdddddddKnn`*W%o%o$o$o$t$ t V 2V22 22222222222222V2V2VVV,Vttt$I$qqoJJ%&&~*wLqooorr^^^^TTskk__999{R.oo%%%`nn`KKdKdKddKdKKnKnnW`%%J%ooR$$R{t{ { A2AAAAAAAA AAAA AAA @A@ 2 2 V Vttt$t$$oqoJ%*%*nn~ddcdddddKK)))0077bMM((#SETsk_A@@ZZN::::CCCC6C6m6zy6yzymyyz6y6m6m66666C]C66CCC::::", +"!N[NZ[2Z@2@2AAA9A_A___ _A A 222[[[!!!:CC6C66]]]]++yDwwHLqJ%orrr33^ETskk__999R{o..%%W```KnKKdKdKKdKdKnnnW*`%%%oRo.o$${{{9t9 A A A A A AAAAAAAAAAAAAA A2A @ 2t t$t$q$ooo%&`~~ndddcdddddKK))00077bMM#(SSETsk_@ZZZNN::C::C6C66666z6z6yzmzmzmz6m6+66C]CC66CCC:C::!", +"NNN[[Z222@AA AAA_9__9__9A_ @ 22[[[!!!:CCC6666]]]]++ywwHLqqoo%r33^^ETssk___9O{{R.oo%%`W`nnKKKKKdKKKnn)nWnW%&r%oo.$$R{{{ tA AA AAAAA_A__A_AAA AAA A@ A2 2 t $t$$$$oJoo%*`nndddcddddKdKK))0077MMM((#SSTsk__@@ZNNN::CCCCC6C66zm6zyzzmzzm6zm666666C]C66CCCC:::N", +"NNN[ZZZ2@2A2AA__________9_AAA2222[[N!N:CCC66]C]6+++yy4HLLJoo%rr333^Tsskkk_99P{Ro.r%%W```BKnKdKKKKn)nnnW``W%%oooo$${$ {{9 9A9A A AAA_A_A_A_A_A___A_AAAA A A 2 tV{$$$$ooo&%J`~nnddddcddddKK)))00777MM((#SETsk_A@ZNNN:::::CCC6Q666z6z6mz6mzmz6666666CC6CC6CC::::N", +"NNNZ[Z2@@@ AAA______k______A A22Z[[N!!:CCC666]]]]+myywwHLqJ%orr33^EETss__k999{R.o.%%W``nnnKnKKnKnKn````%`%%oro..$$R{{{{ 9 AA_A9AA_A_______A_A__A_AAAAA2 {t$$$o$oo%%~%n~dddcddddKdKK))00777MMM##SSETk_A@@ZZNN::::CCCC6CQ6zm6zz6zz6z6m666666C6C6C6CCC:::N", +"NNNZ[ZZ22@@A_A____k9k_Ok__9_A2A22[[[N:::CCC666666+++y4wLGUoo%Wrr333ETsskk__9O{{Ro.r%%%```Bn0nnKn)n`n`n%``%%oroor$R${t{9{ 9 9A _AA_A_______________A_A_AA A A t{V{t$$$oooJ%%~nnddddddddddKKK))0077bbM((#SETsk_A@ZZNNN::C:CCCC666C6Q6mz6zm6z66666C666C6CCCC::::N", +"NNN[ZZZ@@@AA _A__kkk_kk_k____AA2@2Z[[!!:CCC66]]]]]+yyywH>qJoo%rrF3^^ETskk_k9OO{R.ro%%W`W``nnKBKnnKBn```%%%%oo..$$RR{{9{99 9A9A_A___A________________A_AAA A A A 9t{{$$$ooo%%%~`nndddcdcdddKKK)))0077bMM(##SETs__A@ZZNN:N:C:CCCCC6Qz6zCzm6z6mQ66666C6C6CC6CC:::::", +"NNNZ[ZZ2@2AAA____k_kkkkkkkk___AA@22[[N:::CC6C6666]m+mw4HHUqJ%%W3333^ETskkk_99P{RR.rr%%W````B`nn0n`n``%``%%%oroo$r{{{{{9V999A _ __A_________k_k_________A_AAA 9 { {$$$$ooo&%`%~nKdddddddddKKK))00777M(M##SSTsk_A@ZZZNN::::CCCC6C66Q6zz6z6Qz666C666C6C6CCC:C:::N", +"NNN[ZZ2@@@AAA___k_kkkkkkk_k_9_A 2@ZZ[NNN:CCC66]6]6]my4yH>GJoo%rrF33SETsskk_k9O{RRo.or%WW```n)nBn`B````%%%%ror..$R{R{{9{99 9A9A__A_______k_k_k_k_______A__AA9 9 9 {{{$R$ooor%%~`nnddddcddddKKK))00077bMM((#STTskAA@ZZZN:N:::CCCCC6Q6CmCz6z66zQ66C6C6CC6CCCC:::NN", +"NNN[ZZZ@2@AAA____kkkkkkkkkkk___AA22Z[[N:::CCC666]6++mywwHUqJ%%%r5rS3^TTskk_O9OORR.rr%%W%``)``Bn``nBn%`WW%%%ro.o.$${9{{999999A_9________k_kk_kk_kkkk_____A__AAA 9 {{{{$$R.oo&%`%nnKddddddddddKK))0077bb(M##SEEsk_A@ZZZNNN::::CCCCCC6QQQ6zQ6zC66C66C66CCCCCC:::N:", +"NNZNZZ2@@@AAA___kkkkkskkkkkk___AAA22Z[NN::CC666]]6]mmy4HH>JJo%%5rF33SETssk__k9{{RR.rr%%W``%`)```K`````%%%ror.o..RR{R{99{99AA9_______kk_k_kkkkkkk_k_k______A_9A9 99V{{{$.$ooor%`*nnKddddcddddKKKK))0077bMM((#SETsk_A@ZZNNNN::C:CCCC6Q6CmQ6Q6Q6z6C6C6CC6CCCCC:::N:", +"NNNZZZZ2@@AAAA_k_kkkkkskskkkkk__AA@2Z[ZN::CCCC66C]6+yywwHLqoJ%%%53FS^ETsskkk9OOOR.orr%%WWW```n)````W`W%W%%ro.o.o{R{{O{999999______k_k_k_kkkkkkkkkkkkk_k____A_A 9 999{R{$$Rooo%%W``nKddddddddddKK)))0777bM(##SSTsk_A@@ZZNNN::::CCCCQ16QQQ6QQ6Q6C6C6C6CC6CCC:::::N", +"NNNZNZZ@@@AAA___kkkssssskskkk___A @@2ZNNN:::C6]66]6++y4wH>>J%J%WrF333EETskk_k9O{RR..r%rWW`W``````````%W%%%rrrRoRR{R{{O999_9A_9_____k_kkkkkkkkkkkkkk_k_k_____9A_99 {{ {{R$o.ooo%`%nndKdddcdddddKK)))00777MMM##SETsk_A@@ZZNN:::::C:CC6QC6QQzQ6Q6C6C6CCCCCCCC::::N:", +"NNNNZZZ2@@@AAA___kkkkskssssskkk__AA@2ZNNN::CCCC6]6]6myywwLUq&%%%553(S3ETskkk_OOORR.rrrr%WW`W```````WWW`%r%roo.R.RR{{O{99999_9___k_k_k_kkkkkkkkkkkkkkkkk_k_____9A99999{{R$Ro.oWJ```nnKddddcdddddKK))0077bbMM##SETsk_@@ZZZNNNN:::C1CQCCQQ6Q66QQQC6CC6C6CCCCC:C:::N", +"NNNZZZZ@Z@AAA___kkkksssssssskkk___A@2Z[ZNN:CCC6666]6+mw4HH>JJ%%Wr53r3SETTskkk9OOOR..or%%WWWW`````W``%WW%%%rr.o.RR{.O{O9999_9_____k_k_kkkkkkkkkskkkkkkk_k_k____A99999{{{{R$.oro%%`n`nKdddddcdddKdKK))00777MMM##SETsk_A@ZZZNN:::::CCC1C16QQQQCQ6Q6C6CCCCCCCC::::N:", +"NNNN[ZZZ@@@AAA_k_kkkksksskssskkk__A@@2ZNN:::C6CC]66+mmywwHUJJJ%%W5FFS3EEsskk_k9ORR..rrrW%WW`B`B`W`W`W`Wr%roor..oRRR{O{O9O9_9____k_k_kkkkkkkkskkskskskkkkk_k_____A99999{{R$o.oo%%%``nKKddddcddddKKK)))077bbMM##SSTsk_A@ZZZNNNN::::1C1CQ1CQ6QQ6QQC6CCCCCCCC:C:C::N", +"NNNZNZZ@2@@AA___kkkksssssssskskk__AA@2ZZNN::CCC666]66+yw4H>qJ%%`W5rF^3^ETskkk_OOORR.rrr%WWWW`W`B`B`WWW%%%rrr.o.RRR{{OO{O99k9_k_k_k_kkkkkkskskskskskkskkkkk______9_999{O{RR$.oro%`W`nnKdddddcddddKKK))00777MM((SSETs__A@@ZZNN:N::C:CC1C6Q1QQQQQQCC6C6CCCCCC:::::N", +":NNNNZZZZ@A@AA____kskssssssssskkk__A@@ZZZN::CC6CC]66+yywwHLJJ&%%%55F#3SETsskkk9OOP...rrrrWWW%`B``%`WWWWWrr%rrr..RRRP{OO99O9_9____kk_kkkkskkssksssksskskkkkkkk____99999{{{RRo.ro%%``BnKKdddcdcddddKK)))077bbMM##SETsk_A@ZZZNNN:::::11CQ1CQ6QQQQ6QCCCCCCCC:C:C::N:", +"NNNNZZZZ@@@AAA__kkkksssssssskskkk__AA22ZNNN::CC6C66]6myw4H>UUJ*WWW5F333ETTskk_kOO{R..rr%%WWWBWW`W`WWWW%%r%rr.o..RR{RO{O9O9_kk_k_k_kkkkkkksskssskssksskskkk__k____9_9O9O{RRR.o.r%%WW`nKKdddddcddddKKK))00777MM(#SSTTk__@@ZZZNNN::::C:1CQQ1QQ6QQQ6Q6CCCCCCC:C::::N", +":NNNNNZZZ@@@AAA___kkksssTTssssskk__AA@@ZZN:::CCCC]66mmmwwHGUJ%&%%W5F3(SETTskkk9OOPR.RrrrrWWWW``BWW`WWWWW%rrrr^o.RRRO{OOOO9O9_9_k_k_kkkkkskskssssksssskskkkkk_k_k___99O9O{{$Ro.ro%%``nnKKddcdcdcdddKK))00777MMM##SETsk_@@@ZZNNNN::::C11CCQQ1QQCQQCCCCCCCCCC::::::", +"N:NNZZNZ@@@@AA___kkkssssssTsssskkk__A@@@ZZNN::C6CC666+mwy>H>JJ%%`W5F3(3SETsskkkOOOR..rrrr%WWWWB`B`WW`W%Wr%rr.r...RRRO{OO9O_O_k_k_kkkkkskksksssssssksksskskkkkkk__O_O99O{P{.R.or%r%`W`KKKdddddcdddddKK))0077bMM(#SEEsk_A@@ZZNNN:N:::C1C1QCQQQQQQQQQCCCC:C::::C::N", +":NNNNNZZZ@@@@AA___kkksssTsTssssskk__AA@ZZZN::CC6C66]6myyw4>>JJ&*%W553F3EETssk_k9OPPR..rrrrWWWWWW`W`WWWWWr%rroro..RPRRP{OO9k9k9k_k_kkkkkskskssksssssssssskskkkk_k_k__99O9{ORR.Rr.%%%```KKKddcdcdcdddKKK)0077bb(M##SETk__A@ZZZNNN::::::111Q1Q1QQQQCQCCCCCCCCC:::::", +"N:NNNZZZZ@@@A@A___kkskssTsTTsTssskk__A@2ZZNN:::CC6666+mwyHH>UJ%%`WW5F#33ETsskkkOOORR.r.rrW%WWWB`BWBWWW%Wr%rrr....RRROOOO9O9k9k_kkk_kkkkkskssssssssssssskskskkkk_k_O_O9OOO{{RRo.r%%WW``nKKddddcdcdddKK)))0077MMM##SETsk_A@@ZZNNNN:::1C1111QQQ1Q1QQQCCCCC:C:::::::", +"N:NNNZNZZZ@@@AA___kkkssssTTsTsssskk_AA@@ZZNN::CC6C6666yywwLLUJJ&`WW5FF#3ETTsskk_OOPR..r5rr5WWWWBWB`WWWWWF%rrrrr...RPRR{OOOOk9k_k_kkkkksksksssssssTssssssskskkkkk_k_k_999OOORR^o.r%WW`BnKKKdddcdcddddKKK)00777MM(#SSEsk_A@@ZZZNN:N::::1111Q1QQQQQ1QQCC:CCCCC:::::", +":NNNNNZZZZ@@@AAA_k_kssssTsTTssTsskk___A@@ZZN:::CCC]C]66yw4w>UJ*%`%W55333SETskk_kOOPR..rrr%5WWWW`W`WBWWW5%5rrrrrR..RRPPOOO9O_O_k_k_kkkkkksssksssTssssssssssskkkkkk_k9kOOOO{RRR..rrr%W```KKddddcdcdcddKK)))0777MbM##STTs__A@ZZNNNN::::1111Q1QQQQQQQQ1QQCC:C:C:::::", +"N::NNNNZZZ@@@@AA__kkkksssTsTTTssskkk__A@@ZNN:::CCCC66mmywwHLUfo&&`WF5FFSEETsskkkOOPP...rrrrWWWBWBWBWWWWWW%%rrr.r...RRR{OOOO_O_O_kkkkkksksksssssssTssTsssssksskkkkkk_k_99OP{ORR.orr%WW``)KKddddcdcddddKK))0077bMM(#SETskAA@@ZZNNNN::::11111Q18Q8Q8QQQ1CCCC:C:C:::", +":N:NNNZNZZZ@@AAA___kksksTTTTsTTssskk__A@@ZZNNN:CCC6C66myww4>LJ&%`%`WFF333ETsskk_kOOR^.^rrrW5WWWB`B`BWWW5%5rrrrr...RPRPOOOOOO_O_k_kkkkkkskssssssssssTsssssskskkkk_k_k9kOOOOORR...rr%rWW``KKKddcdccdcdddK)))0777MM(#SSTsk_A@@ZZZNNN::!:1111QiQ8QiQQ8Q1QQ1:CC:C::::", +":N:NNNNZZZZ@@@AAA__kksssssTTTTsTsskk__AA@@ZZN::CCC66Cm6yywwHUUJ&&`WW5FF(SEEssskkOOPP..r.5rrWWWBWBWBWBWWWW%5rrrr.....RPROOOOOk9kkk_kkkksksskssssssTsssTssssskskskkkkk_k_9OOOOPR.r.rr%W`)``KKddddcdcddddKK))007bbM((#SETkk_@@ZZZNN:NN:::11818QQ18QQQQ8Q1QCC:C:::::", +"::N:NNNZZZZ@@@AAA__kkksssTTTTsTssssk__AA@@ZZNN:::CC6666ywwH4JU&%~`%BF5F^3EETskk_kOOPR^.rrr5W5WWBB`WBWBWW5Wrrrrrr....PRPPOOOOkO_O_kkkkkkksksskssssTsTssssssssskskkk_kk9kO9OORRRR.rrrrWWB`KKKdddcdcccdddKKK)0077bMM##SETskAA@@ZZNNN::::i11181iQ8QQ88QQiQQ11CC::C::", +":N:NNNNNZZZZ@@@AA___kksssTsTTTTTssskk_AA@@ZZNN::CCC6666ymwHH>JJ*J``W5FF#3STTsskkkOOP^..3rrr5WWBWBWB`WBWWW5W55rrr3....RPROOOOk9kkkk_kkkkkskssssssssTsssTssssskskkkkkkkk9kOOOOPP...rrr%WW``)KKddddccdcdddKK))077bM(M#SSTsk_A@@ZZZNNN:!1:i1iC8Q88Q8iQ8iQ81Q1:C:C:::", +":::NNNNNZZZ@@@@AA___kkssssTTTTTTssskkk_A@@ZZNN:::CCC666yyww>>>f&%*W`WFFF^3ETskkk_kPPR..rrr5WWWWB`BBWBBWWWWr%rrrr.r..PPRPPOOOOk_k_kkkkkksksskssssTsssTssTsssssskskkk_k_kO_OOORRR..rrr5WW``KKKdddcdccdcddKK))0077bMM##STsk__@@ZZNNNNN::!11iQi8iQ8Q8QQ8QQQ1Q11:::::", +":::N:NNNNZZZ@@@AAA__kkkssTsTTTTTTsssk__A@@ZZZN:::C:6C66zywww>UJf%~``B5FFSSETTsskkOOPP..r3rr55WBWBW`B`BWBW5W5rrr3r3...^RP{POO_OOOkk_kkkkkksksssssssTsTsTsssssksskskkkkkk_kOOOOPP...rrr%W0``KKKddcdcccddddKK))077bM((#SETs__@@ZZZNNN::!:1i18iQQ8i8i88Q8Qi81111C:::", +"::N:NNNZNZZZ@@@@AA__kkssssTTsTTTsTskkk__A@@ZZNN:::CC6C6mywwH>UJ&&`%`WFFF#3EEss_kkkOPP..^r5rWWWBWB`BBBBBWBWW5Wrrr.r....PPPPOOOk_k9kkkkkkskkssssssTsssTsssTssssskskkkk_kOkOOOOPPRR..rrr5WWB))KKdddccdccdddKK)00077bM(#SETsk_A@@ZZNNNN:!:i1ii8888Q}8}i888QiQi111:1:", +":::N:NNNNZZZZ@@AAA___kkksTsTTTsTTssssk_AA@@ZZNN::CCCC66zyww4L>fJ&*~`BBF3(3EETsss_kOOP^.3rr555BWBBBB`B`WBWW5W5r5rr^r^.^.RPPPOOOkOkk_k_kkkksksksssssTsTsTssTsssksskskkkk_k_kOOOOPP.^.rrrWWW`KKKddddcccccddKK)))777b(M#SSTsk_A@@ZZZNN:!::!181i8Qi8}8Q8}i8Q8Q811111:", +":::N:NNNZNZZ@Z@@AAA_kksssssTTTTTTssskk__A@@ZZNNN:::6C666y}wH>Ug&*``%BWFFF^SETsk_kkOPP...rrr5WWBB`B`BBBBBBWW55rrrrr^r..^RPPOPOkOk9kkkkkkkkksksssssssssTssTsssssskskkkkkkkOkOOOPRP..r^rrrWB``)KKddcdcccdcddKK)0077bMM##STTk_A@@ZZNNNN:!!1iii8Q88QY}}8}8Q8i8Ci11:1:", +":N:::NNNNZZZZ@@@@A___k_ssssTTTTTTTsskk__A@@ZZZNN:::CCC6zzwwwH>UJ&`*``WFFFS3ETsskkkOOP^..3r555WWBBBBB`B`BBBWWW55rr3r.^..PRPPPOOOOkk_k_kkkkskksksssssTsTsTssssssskskkkkkk_k9kkOPPRP...5r5WWB)KKKdddcccccdddKK))007bb((#SETk__@@ZZZNNNN:!1i1Qi8888}8888}88Q8Q81ii1:", +":::N:NNNNNZZZZ@@AAA__kksksTsTTTTsTTsskk_AA@@ZZNN:::CCC66yyww>>UJ&&```BFFF#3ETsskkkOOPR^^rrr5WBBB`B`)B`BBBWB5W5r5rrr3...^^RPOPkOkOkkkkkkkkkskskssssssTsTssTssssssksks_kkk_kOOOOPP^..^rrr5WB`))KdddcdccccdddKK)0077MMM#SETsk_A@@ZZNNN:!:i!i8i8i88Y88}YQY8i8QiQi11!", +":::::N:NNZNZZZ@@@AA___kksssTTTTTTTsTkkk_AA@@ZZNN::CCCCQ6zwwHH>gJ&&`~`BWFF33EEsss_kkOPP.r3rrWFWBBB`BB)B`BBBBW5W55rr3rr^...PPPOPOOOkO_k_kkkkkkkssssssssssTssTsssskskskkkk_kOkkOOPPR^.^rrr5WWB`)KKdddccccccddKK))077bMM#SSTskAA@@ZZNNNN!!i1iii888}8}Y8Y}YQ}i88ii1i1", +"1!:N:N:NNNZZZZ@@@AA__kkksssTTTTTTTssskk__A@@ZZNNN:::C66Czzyw>H>f&&`*BWBFF#3SEsskkkOkO^..^r35WWBBBB)`0`)BBBBWW555rrrr^.3P^.PPPOOkkOkkkkkkkksksksksssssssssssssssskskkskkkk_kOOOPOPR...3r5WWB`)KKKddcdcccddddK))0077M(##STsk_A@@ZZNNN:N:!ii88888Y8Y8w}8Y8888Q81i11", +"::::::NNNNNZZZ@@A@AA__k_ssssTTTTTTTsssk__AA@ZZZNN::CCCC6zywww>gJ&&*```B5FF3^ETssk_kOPPP3r3%5WFBB`B)B)B)B`BBBFWW553rrr3....^POPPOOkOk_k_kkkkkkkskssssssTsTsssssksskskkkk_kkOkkkOPPP^.^rrr5WB`))KKdcdccccccdKKK)0077MM(#SETkkA@@ZZZNNN!!iiii8iY8Y8H}Y8Yw8888ii8ii1", +"i:!:N:NNNNNZZZZ@@@AA__kksssTTTTTTTTsskkk_AA@@ZZNN::::C6CQzwwH>>Uf*~```BFFF#SETskkkkOOP..^r555WBBB)B`)`)B)B`BWB5W5rr33.3.^PRPPPOkOOkOkkk_kkkkskkssksssssssssssssskskkkkkkk_kOOOOPPP...3rrr5BB`)KKdddcccccdcdKK))077bMM#SETkkAA@ZZZNNN:!!ii8iY8Y8wY8YwY8Y}888Q8i1i", +"1i:::N:NNNNNZZZ@@@AA_k_kksssTTTTTTTTsskk_AA@ZZZNNN::CCC6zzwwHH>gJ&~*n`BBF333ETsskkkkOP^^r3r5WFBBBB`)B)`)B`BBBBW5555rrr.3..P^PPPPOkO_k_kkkk_s_sksksssssssssssssssskskskkkkkk_kOkOPPP^3..555WB`)KKKddccccccdddK))0777M((SSTs__@@ZZZNNNN!!iiii88Y8Y8HYY}Y}YY888i8ii", +"i:!:N:NNNNZNZZZ@@@AA___kssssTTTTTTTssskk__A@@ZZNNN:::CCCQzyww>>gJ*&````WFF(SEEssk_kOOP^..3r55WBB)`))))B))B0`BBFW55rr33r.^^.^PPPOOkOkOkk_kkkkkkkksksssssssssssssskskkkkkk_k_kkOOPOPP...33r55BB`)KKddcdcccccddKK)0077MM##EEsk_A@@ZZNNN!:!ii8Y8Y8H}YYH}GYwY88Yi8Qii", +"ii1!::::NNNNZZZ@@@@AA__kkksTsTTTTTTTsskkkAAA@ZZZNN:::CC6Qz}wHHHgfJ~*~`BBFFF3^EssskkksOP^3rr55WBB0`0`)))`)`)BBB`FW55F%r33..^.PPPPPPkOkk_kkkkkkkkskkskssssssssssksskskskkkkkkkkkkkPPPP^3.rrr5BB`)KKdddccccccddKK))077MM(#SETk_A@@ZNZNNN!!i,i88Y}YYYHYHYH}YY}Y8888i", +"ii:!:N:NNNNZZZZZ@@AA___kksssTTTTTTTTsssk__A@@@ZZNN:::CCCQz}yw>>>f&&~```BF5#(SETs_k_kOPP..3r55BBBB))))))))0`0`BBBW5553rr3r3.P^PPPOOkOkOkk_k_kkkkkksksksssssssssssskskkkkk_k_k9kOOOPP^...3555WBB))KKdccccccccddKK)0077M(#SEss__A@ZZZNN!!!ii8Y8YYYwHHYHHYHYwY88Yii8", +"iii:!:N:NNNNNZZZ@@@@A___kksssTTTTTTTssskk__A@ZZZNNN:::C6QQ}www>>J&&*nn`BBFF3^ETsskkkOO^^^53r55BB`B)`))))))`)`0BBBW55r53r^.^..^PPPPPOkOk_kkkkkkkkkkskkskssssssssskskkskkkkkkkkOkOsOPPP^^r3rr5WB))KKdddccccccddKK))77bM((SETs__@@@ZNNNN!!i,iiY}YYGYHHHHHHYH8Y8888i", +"iiii:!:NNNNNZZZZ@@@AA__kksssTTTTTTTTTsskk_AAA@ZZNNN:::C:6QzwwH>>gf*~*``BWFF33ETskkkkOOP^.3r55WBB0))))))))))0B)BBBFW55rr53r^^^.^PPkOkOkOkk_k_kkkkkkkksksskssssksksskskkkkk_k_k_kOOOPPP...3rF5WBB)KKKddcccaccdddK))077bM##STsk_A@ZZZNNN!!!iiY8YYHHYHYHHHHHYYwY88i8", +"iiii!!:N:NNNNZZZZ@@AAA__k_ssssTTTTTTssskk__A@@ZZZNN:::CCQQz}wHH>Uf&~*~)`BFF(3EEsss_kkOP^.3rr5FBBB)`)))K)))))`)BBBBWB5553r3^r^^PPPPPPOOk_kk_k_k_kkkkkkskksskskssskskskkkkkkk_k_OkkPOPP^^^r3r55BB))KKddcccccccddK))077M(((SEskAA@@ZZZNN!!i,iY8YYHYHHHHYHYHHGY8YY88", +"8ii!:!!:NNNNZNZZ@@@@A__kkksssTTTTTTTTsskk__AA@@ZZNNN:::C1Qz}ww>>gg&&~`nBWB(F^3TTs_kkOkPP..355WB0`0))K))K)K)))0`0BBFWF5r53r3.^^.^PPPkOkOkO_kkk_kkkkkkkksksksskskskskkskkkk_kk_kk_OkPPP^...3r55WBB)KKddcccccccdddK))077M(#STTk_A@@ZZNNNN!ii,8YYYYGHGGGGGHHYHYH88Yi", +"i8iii:N:NNNNNZZZZ@@@AA__kkksssTTTTTTTssskk_AA@ZZZNNN::C1CQz}wHH>>f&**`n`BBFF#^ETssk_kOO^^.535FBB0`))))K)K)))))B)BBBFW55rr3r3.^.P^PPPPOkOkk_k_kk_k_kkkkkkksksksskskkskkkkkkkkk_kOkOOOPPP^r3rr5FB`))KKddcccacccddK)0077MM(SETs__@@ZZZNN!!!iiY8YYYHGHGHGHGGHHHYY8Y8", +"Yiiii!!!:NNNNZZZZ@@@AA__k_ssssTTTTTTTsssk__AA@@ZZZNN:::C1QQ}}wH>>ff&~*nBBB5F#3ETs_kkkOPP.33rW5BBB)))K)K)K)KK)))0`BBBBW5Fr3r3r^^^PPPPkPOkO_kk_k_kkk_kkkkskkskskskkskskkkkk_k_kkk_kOkPPP^^^r3355WB0)KKddcccccccddKK)077MM#(ETs__@@@ZNNNN-i,,8YYYHHGGGGLGGGHGHYHY8Y", +"iY8ii!!:NNNNZNZZZ@@@@A___k_sssTTTTTTTTskkk__A@@@ZNNNN::11QQzwwHL>gf&*~n``BF3F3^Tssk__kPP^.r355BBB))))K)K)KK))))))0BBBF5555r33r^^.^PPPOkOkOk_k_k_k_k_kkkkkskkskskskskkkk_kkkk_k_OkOkOPPP^^^3r55FBB)KKKddcacacccdKK))777M3#STskAA@ZZZN[!!-i,8YYGYGGGLGGHGLGYHGYYY8", +"8ii,ii!!N:NNNNZZZZ@@AAA_kksssssTTTTsTsTskk__AA@ZZZNN::::CCQ}}wH>Ugf*~*`n`BBFF3EEsskkkkOP^P3355BB0)))K)KKK)K)K))))B0BBBF5553r3.3.^P^^PPOOkO_kk_k_k_kk_kk_kkkskkkskkkkskkkk_k_k_k_kOkPOPP^..r3r55BB))KdddcccacccddK))077M((STsk_A@@ZZNNN!!i,8YYYHGGGGHLLGGGGGHHYYY", +"8Y8ii!!!:NNNNZNZZ@@@@AA___kksssTTTTTTssskk__AA@@ZZNNNN:C11QQ}}w>Hgf&&~~K`BB5F#^ETsk__OkP^.3rr5FB0`)))K)KKKKK)K))))`0BBBF555rr3r^^.PPPPsOkOkO_k_k__k_k_kkkkkkkskkkskkkkkkkk_k_k_OkkOkOPPP^^3r355BBB))KddccaccccddK))077MM#SETk_A@@ZZN[N-!,iYYGYGGGGGLLLLHLGGHHYG8", +"Y8,i,i!!!NNNNNZZZZ@@@AA__kksssTTTTTTsTsskkk_AA@@ZZZNN::::1Q8}wwH>gff~*n*B`BFF33ETskkk_kO^P.355WBB)))K)KKKKKKKK))))0)BBBB555Fr33^^^^^PPPOOkO_k_k_k__k_k_k_kkkkkkskkkkkkkkkkk_k_k_k_kOPk^P^.^3rr55BB)KKKdccccacccddK)007MM(3STs_A@@ZZZNN!-i,8IYHGGGLLL>GL>GGGGHHYY", +"8Y88iii!!:NNNNNZZZ@@@AA___kkssssTsTTTTssskk_AA@@ZZZNNN::11QQ}}wH>>gf&*~nn`BF5(3^Tskk_kkPP^r3r5F0B0))K)KKKKKK)KKK))))0BBBBF55Fr3r^r^P^PPPPkOkOk_k__k_k_k_kkkkkkkkkkkkkkkk_k_k_k_k_kOkOOPPP^^r3355BB0)KKddcccacccddK))77bF##ETsk_@@@ZN[N-!i,,YYIHGLGL>LLLLLLGGGYGY", +"YY8i,i!!!NNNNNZZZZ@@@@AA_k_sksTTTTTTTsTskkk__AA@@ZZNNN:::11Q}}wHL>gfx~*nnBBB5F^EEss_kkOk^P^3F55BB))))KKKKKKKKKK)K)))B0BBFWF55(r33^.^^PPPsOPkO_k_k___k_k_k_k_kkkkkkkkkk_kkk_k_k_k_k_OkPOPP^^^rrF5FB`))KddcccacccddKK)077MM(STsk_A@ZZZNN!-i,8YGHGGLLLLL>LLLLHGGHHY", +"YY8Y1,ii!:NNNNNZZZZ@@@A__k_ksssssTTTTTssskk__AA@ZZZNNNN::11Q8}}H>Lgff*~~n``BFF33Esskk__OO^^r3rFBB0)K)KKKKKKKKKKKK)))))B0BB55555r3r^^^^^PPPOkOkOk__k__k__k_kkk_kkkkkkkkkk_k_k_k__k9kkkOkP^P^.333rFBB))KKddccacaccdKK)077b##3Esk_A@@ZZN[N-,iYYYGLGLLLULU>L>LLLGGGY", +"YYY,8i-!!!NNNNZNZZZ@@@AA__kkkssTTTTsTTssskk__AA@@ZZZNN::::1Q8}YwH>>ff**nnnBBFFFSETsk_kkkPP^^3W5FB))))KKKKdKdKKKKKK)K))0BBBFF55F333r^^^P^PPPOkO_kk______k__k_kkkk_kkkkk_kk_k_k_k__k_OkOPPPP^^.r3W5FB0)KKddcccacccddK))07bF(SETk_A@@ZZNN[!-,YYGIGLLL>LULUULL>LGGGH", +"HYY8,i,i-!:NNNNZZZZ@@@AA___kksssTsTTsTTsskk__AA@@@ZZNNNN:111Q}}wH>>ffx~~`n``F5F3^Tssk__kOP^^r3FBBB))K)KKKKdKKdKKKKK))))0B0BBF555Fr33^^^P^PsPPkOkO_k_k___k__k_k_kkk_k_kkk_k_k____k_k_OkOsO^P.33r3FBBB))KddccacacccdK))07MM(^3TskA@@ZZZ[N-i,IYYGGG>qUU>UUUULLLLGGG", +"YYYY8,ii!!NNNNZNZZZ@@@AAA_kkksssTTTTTTssskkk_AA@@ZZZNNN:::1188}wH>Ugf&h~nn`)BFF^3Tss_k_kOPP^3r5BB00))KKKKdKdKdKKKKKK)))))BB7BF55F3r3r^^^^PPPPkOkO_k_______k_k_k_kkk_kk_kk_k_k_k___k_kOkOPPP^^r3F55BB0)KKddccaacccddK)077MMSSTs__@@ZZNN[!-,8IYLLqL>UUUUU>LUL>LLGG", +"GGYY8,i,-!!NNNNNZZZ@@@@AA__kkkssTsTsTsTssskk__AA@@ZZZNNN:::1Q8}YHH>>ff*~~n``BFF3S^Tskk_kkP^Pr35FFB)))KKKdKKdKdKdKKKKK))))00BBBFF55(r33r^P^^TPPOkOk_k__k________k__kk_k_k_k_k_____k9__kOOkP^P^^r3r5FB0))KddccccaccddK)007MM#3Esk_@@@ZZN[--iIYGIqG>q>UUUgUUUULLLGG", +"GYYYY8,!i!!NNNZNZZZZ@@AAA___kssssTTTTTsTskkk__AA@@ZZZNNN:::18Q8wwH>>ffx*~nn`BWFF3^Tkkk_k9sP^^3F5BB0))KKKKdKddKdKdKKKKK)))))0BBF5F5FF3rS.^^P^PsPOkOk_k_______k_k_k_k_k_kk_k___k__k__k_OkOPPP^P^3rF55BB))KddccaacacddKK0077((SEsk_A@ZZZ[N-,,YIHGLLUULUgUgUgUUU>qLG", +"GGGYIYi,--!NNNNNZZZ@@@@AA__k_kssssTsTTTssskk__AA@@ZZZNN:N:!11Q8}HHL>ff&h~nnn`BFF3^Ess_k_kOP^^r35FBB)))KKKKddKddddKdKKKKK))0)00BBBF55F33r3^^P^PPPkOkO__k____________k_k__k__k__k_____k_kkOkPT^^r33F5FB)))KdccccacccdKK)07MF#3^Tk_A@@ZZ[[--,,YIGLLqUUUgUgfUgUUU>LG", +"GGGYYY,ii!!!NNNZNZZZ@@@AAA__kskssTTsTsTssskkk_AAA@@ZZZNNN::118i}YH>>gf&~*nn``BB5(3^Tkk__kOOP^3r5BB0))KKKdKdKdddKddKdKKK)K))))0BbBF5FFF333^.^^PPTOOkO_k___k_____k_k__k_k_k_k_______k_O_OkPPPP^P^.3r5FBB)KKddccaacacddK)007b#(STs__@@ZZN[!-,YIGqGLUUUfUfggfUgUULq>", +"LGYGYY8,,-!-NNZNZZZZ@@@@A___k_sssssTsTTssskkk__A@@@ZZZNNN!::i18}wHHL>fx&h~nnnBW3F^^Tskk__kk^^.3(5FB0))KKdKddddddKddKdKKKKK))))00BBBF555F333^P^^PPsOkO_k___________k_k__k____k_________kOkOkP^^^33FFWF00)KKdccacaccddK))77MF#3Ts_AA@ZZZ[[-iIYIGLq>UgJgfJfUfgUUULL", +"LqGYYYYii-!!NNNZNZZZ@@@AAA__kksksTsTsTsTsskkk__AA@@ZZZNNN::!1i888wH>>ff&*gfx*~nnn`BWF33^Tskk__kO^^335FB0))KKKKddddddddddddKdKKKK))))00)BFBF55F333^^P^PsPkOkk___________k___k__________k___9kkkOTP^^^3r3FBBB))KdccccaaccddK)077((3ETk_A@ZZZ[[-iIYIqLqUUggfffgffgfgUUL", +"LLLGGYI8,-!-!N[NZZZZ@@@@AAA__kskssssTssssskkk__AA@@ZZZZNN:N::1iQ}}HL>gfx&h~nnnBBFF3^Tkk__k9kPP.r55FB0)KKKddddddcddddddddKdKKKK))))0B0FFFF3F3r3^^^^PPkOk_k________________k__________k_k_OOkPP^P3^3F55F00)KKdccacacccdK)007M(#ETk_A@@ZZ[[-tIYGLqUUJJffffffgJfgUUU", +"ULGGIYYIi,--![NNZNZZZ@@A@AA_k_kkssTsTsTsssskk___A@@@ZZZNNNN:!ii88YHHL>g/**~nn``B5F3S^ssk__kkO^^^F5FB0))KKKKddddcdccdddddddKKKKK))))0B0BFBF5F333^^P^TPOkOk_k__________________k__________kkOkPPP^^r3F5FB0)KKdcccaaaccdKK)77b3(S^s__@@ZZ[[--,IIqLUUUfgffffffffffUU", +"UqLGGGI8,ii-!NNZNZZZZ@@@AAA__kkkssssTsssTskskk__AA@@@ZZNNN:N:1i8QYwHL>gf&h~~cn`BB5F^^Tkk___OkP^^3FFB0))KKdddddddcddcddddddddKKKK))))000BbFB(5F33^^^PsPkO_k____________________________O_OkOPsP^P^^3F55BB))KddccacaccdKK)07MM(^TskAA@ZZZ[-,IIGGqUUJfffffffffgfggU", +"UULqGIYY8,---[NNZNZZ@Z@@@AA___kkksssssTsssskk___AA@@ZZZZNNN!:!1i8}HwLL>fx&h*nnn`B5F3^^skk__kOP^^3FWFB0))KKKddcdcdcccdccdddddKdKKKK))))000BFFF3F333^^^PsPkO_k____A______________________k_OkkPPP^^^r3F5F00)KKdccaaacccdK)077M#S^sk_A@@Z[[[tYIILqUUgfffffxf/ffgffU", +"UULLGGYIIi,-!![NNZZZZZ@@@AA__k_ssksssTssssskkk__AA@@@ZZZNNN:!:ii888HH>>ffx~gfx*~hnnn`BFF^^^skk__kkP^^3FBF0))KKKKddcdccccccccccdcddddddKKK))))0B07FF3F333^^TPsOkkk_____________________________kOkPT^^P3r3FFBB))Kddccaaaccdd))7773#E^k_A@Z@[2[t,IqGJUUfffffx&/xxfffff", +"fUUqLGIYIi,---N[NZZZZZ@@@AA___kksssssTssssskkk__AAA@@@ZZNNNN:!:ii88YHH>gffx*~nnnBBF53^^sk____OsP^^35FB0))KdddddcdcccdccccccdcddddddKKKK)))00BBFFFF33^^PPTOkO_k___A_A__A_________________O_kkPkPP^^^3F55F00)KKdccaaacccKK)07MM(^Ts_AA@ZZ[[,t,qGqfJfffxxxx&xx&/fff", +"fJUULqGGYY,i-![NNZNZZZ@@@@AA__k_kkssssssssskkk___AA@@ZZZZZNNN!!iiiY}HHL>f/&h~>gxx*~ffx~h~n~n`B553^^sk___kkOP^335FB0))KKdddccccaccaccacacaccccccdddddKK)))00bFB(F33^^TPsOkkk____A_A___A___A____A___9_k9kOsPP^P^3rF3FB0))KdccaaacccdK007FM3STk_A@@Z2[t,IqqUJJfxxxxxhhxhxx&/&", +"fffJUULLIYIt---[[NZZZZZ@@@AAA____skkssssssskkkkk__AA@@@ZZZNZNN:!!ii8YYHLLgffx*~>f/&h*~nnn`BF53^TPk____kOP^^r(FB0))KKdddcccacacacaaaacaaacacccccdddKKK))0BbBFF#33^PTPsOk_______A__A___A_A__A______kOkkPkP^^^rFF5FB0)Kddcaaaaacdd))77((3TskAA@@Z2VtIqqJJ&fxxhhhhxhxhxxx&", +"xfffJUqGqIYI,---[ZNZZZZZ@@AAAA___kkksksskskskkkk__AA@@@@ZZNZNNN!!!iiY8HGLUgfx~hcggfxh*~nnn`B553^^sk____kOT^^3FFF0))KKddccccacaacaaaaaaaaaaaaacacccdddK)))07BFFF^S^E^ssOk_______A__A___A_A_A_______kOkOPs^P^3335FB0))KdccaaaaccdK)77F((ETk_A@@2ZV,tqqqffxxhhhhhhhhhhhhx", +"xx*ffJUqLqG,I,V-[NZZZZZZ@@@AAA___kkkkskskssskk_k__AAA@@@ZZZNZNNN!!!i88YHHLggfx~h~gf/&h~gfxx~hg/&hhn<~nn`B5r3P^kk____OkT^^3FFM0))KKddcccaaaaaa==a======a==a=aaaacccdKK)00bBF5#3^^T^skkkk_______A_A_A___A_____k_kksOs^T^^3(3FFF))KddcaaaaacdK)07M#3^skAA@@2V tqqJJx&hhhLgffx*hcgffx~h<<~nnn`W53^^Pk9____kOTE^#FFb0)K)ddccaaa=a=====;==;=;=;=;=====aaccddKK00bBM3(S^E^sskkkk______A___A_______k_k_sPkTPE^^33FBF0))Kdca=aaacdK)07M(3Esk_AAA V$qo&x*hhv<<<<===v=<=<", +"<<Uffxxh~<~c~nnB`5r^^PO_____kOT^33FF70)KKdccaa===;=;;;;=;;;;;;;;=;=;====accdK))77FF(#3ETTsskkkk________________k_kkkPsTPT^S33FFB00KKdca=a=acdK)07F(SEs__AA {$oJ*&h<<=;;=;;;;;;=;=", +";;;;/////x", +"/x////e/e//eepeeepppppjlv;=a~n~%rr3P^ssssssssssssssssTsTsssssssskskkkkkk_____A__A_A99{{{$ooJ*~<<;;'v;<=ccK)BFF(####Mb7Ka;XXjjXjX'''v=<<;<=/eg/g/fxfx", +"x/x/g/g//e>/eeeeeeeeeeeppplv;=a<`nWrr3^^^TTTTTTTTTTTTTTTTTTTTTTTTTssssssskkkkk_k_k_k9ORRoo%&~<<;''vvv/g///&/x", +"x&/x//f//>ee/eepeeeeepepppjlv;=cnnWWrr^^EETTTTTTTTTTTTTTTTTTTTTTTsTsssskskkkkkkkk_kOOO{.oo&~*=='vvvvhvacK)0FM((M#bb)c='XjjXjjvvvh<>ge/g/f&/&&", +"xfx&/fxefe/geeeeeeeeeeeeppplvv=acnnW5r33^^EETETTTETETETEETETETTTTTTTTsssssskkkkkkkkOORR.%J%~<<;;'vvhv<>>/g/ff&x&&", +"x&x&&//g/gge>e>eeeeeeeeeeeppllv;acnn`W5333^EEEEEETEETEETEEEETETETETTTTsTsssskskskkkPPRorr&~<<=''vlllh</ffx&fx&", +"&x&xff//g/e/egeeeeeeeeeeepeppjlv=acn`W5r33^^EEEEEEEEEEEEETEEEETETETTTTTTssssssksskPPP..o%~*~=;vvjllhv4g>/gffx&x&x", +"&&x&x&f/g/g>e>ee4eeDeeeeeeeppplv==cdn`W5F33S^EEEEEEEEEEEEEEEEEEEEEETETTTTTssssskssPP..ro%`~<=;vlllllheg/g/&fx&&&", +"x~&&xxf/g/>ege>e4eeeeDeeeeeeppplv=acdnBW53333EEEEEEEEEEEEEEEEEEEETEETTTTTsTsTssssPP^.rr%*~<=;vjllplh<~dK)77MMbbb)c;XXjjjjvlhl/h/hhh*~hnhnchn>>ggfff*&*x~", +"&&&x&&ff/g/gge>e4eeDeeeeeeeeeppllv=adn`B55F3S3SESEEEEEEEESESEEEEEEEETEETTTTTsTsTPTPP.o%%`~<;;vvlplph<4>/gffx&x&&&&", +"~&*&x&ff/g/>ege>e4eeeDeDeeeeepppll=acdn`WFF3(33SSESSSSESSEEESESEEEEEETETTTTTTTTTT^^^^r%`*e>/gff&*&*~&", +"&***&x*ffgg/g>e>e4eDeeDeDeeeeeppplv4>gggfff&*&&&&", +"~&&&&&fff/gge>>e4e4eeDeDeeDeeeeppllv=cdK`BF5F^(^SSSSSSESSSSESSSESESEEEEEETETTTTT^^^rr%`~<=;vjlpplp/h>fff*f&*~&~", +"&*&*&*xfff>/gg>e>4eDeDeeDeDeeeeeppp>>gff&&&*&&*&", +"&~&&*&&fff/>ge>>e>4e4eDDeeDeDeeeeppll=acK`BB5F#F3#3SSSSSSSSSSSSSSSSESEEEEEETEE^^^3rrW~nc=;vlppppp/x4gggff&&*&&~&~", +"&&~&*&&xfg/gg>e>>e44eDeeDeDeDeeeeepplv4>>ggff&f&*&&~&", +"~&&*&*&f&ffgg/>>44>44eDDeDeDeeDeeepppl>>gfg&&&*&*`&&", +"&~*&&&&&fffgg>>e>>e4eDeDeDDeDDeeeeeppll4>>gffJ&&*&&&&~", +"&&&*&*&f&fffg>g>e>44444eDDeDeDeDeeeeppll>>gf&f&&*&~&~&", +"&`&*&*J&&ffggge>>>4>4eDDeDeDDDDeDeeeepplv>>gJfJ&J*&%&*&&", +"&&*&*&*Jf&gfgg>>>4>44444DeDDDeDeDeeeeeppl<=cdK)`7BFMF((3(#########S#S#3#3#3#rF55`ndc=vvpppeeeep/h>ggf&&&&*&*&~&", +"&~&%&*&&&fffggg>>e>4>44eDDDeDDDDeDDeeeppplhacdK)0B7F(5M#((3((#(#(###(#(^(3#FF5F``ncavvlppeeepe//*nK)0700Kc;Xjjjvl///ggggggfJgJJfJ&J&J&J&J&&J&&J&&f&ff&fxff/f//////lllvjXjjjjXXX;=acd))07bbbMMbMbMbMbMMbbb7))dc=;XXjjj'X;>ggJJf&&&*&&~&&", +"&*&*&J*&Jffggg>>>>4>44444DeDDDeDDeDeeeepppl>gggJgJJfgJffJfJfJJJJf&J&J&f&ffxffg/fg/f////pllljjjjjjjXX';=acdK)007bbbMbMMMbMbbb00)Kdc='XXjjjX'v;>UgJJ&&J*&&*&&&", +"&&&*&J*&f&gfgg>g>4>>4>w44DDeDDDDDDDeDeeeeepllgg>UgUfUgfUgJUJgJfgJff&JJf&fJ&f&fffffg//g/f///l/llvjXjjjjjjX';=ccKK)00777bbbbbbbbb70)Kdca;'XXjXjXvv<>UJf&f&&&*&&*&&", +"*&*&&&&J&fJJgg>>>>>H>44444DDDDDeDDDDDDeeeepphl/*~K))00)c='XjXjl/xgUg>>>U>UgUgUUgU>U>U>UgfJgJfJfJJfJfJfgffffgfg/g/////llljjjjjjjX'X;;acdK))00777bbbbbbb00)KKca='XXjjXXXv<<<~dK)))nheeDDDuu+DmywwHH>>UJg&J&*J&*&&&*", +"&*f&&J*&JgffgUg>>>4>4w4w444DDeDuDeDeDeDeeeeppphLL>UgUUU>UgU>Ug>UggU>UgJUfJJfJfJfgfffgfgfg/g/f///l/lljjjjjjjjjX';=acddK))00777777000))Kcc=''XjjjjXvvv<~cK)))n*/eeDuuuDumywyw>>LUUfJf&f&&*&&*&&", +"*&&&&&J&f&Jgfg>>>>>>w>4w4wD4DDDDDuDDDDDDeeeepplh<~cdK))000bBb7F7FB7FbF0B0))dcc=vlppeeeeeeeeefxnn))))Ka;XjjjvlxfgLU>LULLg>g>U>U>>Lg>>U>gUU>UJgggJfgfJfJgfgfgggfg/g////lllvjjjjjjX'X';=acdKK))00)00000)))dcc=;'XXjjjXvvvh<>UfJ&f&f&&&&&*&", +"&&&J*f&JJJfJJ>gg>>4>4H4w4y4DDDDDDDDDDDeDDeeeeppplL>>LLL>L>>>>>>>>>>U>>UgUUgJUJJUgggggggfgg/g/g///l/lljjXjjjjjj'';=aaddKK)))))0)))KKddca;'XXjjjXXjvhh<~nKK)n~/eeDuuuuD+yywwH4ULUJJfff&&&&x&*f&", +"&f*&J&f&ffggUgg>>>H>>H4w444y4DDDDDDDDDueDDeeeepphlhf&~n)))Kc='Xjjvl/fJULLLLL>LL>>L>>>H>>H>>>>>>LgU>UgUUgggJgUgJgggggg>gg/g////llljjjjjjjjXX''=aacddKKK)))K)KKddca;''jXjjjjvvl>>>>4H4L4wwyDwDDDDDDDDDDDDeDeeeeppph<<~cddKK)))))))))KKKdcc<LL>L>H>>w>4>H>H>>>>U>UU>UgUUgUgUgUgggggggg/g////llljjjjjjjjXj'';=aacdddKKdKKKddcca;;XXXjjjXjjvlhhL>JUgJf&fff&fx*f*", +"&f&fJ&fJfJJgUUg>>L>>H4Hw444y4yDDDDuDuDDDDDDDeeeeppplh<HLH>H>H>>w>4>w>H4>4>L>L>LgU>UUgUUUgUg>Ug>gggggg/g//phllvjjjjjjjXXX';=aaacddddddccaa=;;XXXjjjjjlvlhhh~nnK`nf/eDDuuuu+6mz}wHHHLUUfJf&fff&x&&f&f", +"f&f&&fJfJfUfUU>L>>H>4H>4wwwDy4mDDDDDDDuDDDDeDeeeeppphl<<HLHH4H4H4H4H4>w>G>4>L>>UUUgUUU>UU>UgU>ggg>gg/gf///pllljjjjjjjXXXX';;aaaaccccccaa==''XXjjjjXvjlhhhhhnnnn~xeDDDuuu+mmzz}wHH>LUUJfgffffxff&fxf", +"fffJfJfJgJgUgU>>L>H>LHwww4ww4y4+DDDuDuDDDDDDDDDeeeeppphhgx~`KKKd='XXXjhxJfqqqGGGLH>HHL4>w>w>H4H4>H4H4H>H>L>L>LLU>UUUgUU>U>g>g>ggg>/f////lljjXjjjjjXXX'';;==aaaaa=a==;'XXXjjjjjjlllh/hh~nn`n&/eDDuuuu+m6zw}wHLLUUUJfJf&&ff*fxfff", +"f&f&JfJfJUJUUU>L>L>H4>wwww4y4yDyDDDDDuDuDDDDDeDeeeeeppp/phhh<<<<wHH4w4w4w>w4w>4LH>H>>L>>L>LUL>ULU>Ug>g>U>ggggg/g//lllvjjjjjjjjjXXX'';;;======;;''XXjjjjjXjllh//h~~~nn*fe4Duuuu++6zz}8wHGLLUgJfffffffff&f*f", +"ff&gfJfJUfUUUL>L>>HLHH4H4wwwywyDy+DDDuDDuDuDDDeDDeeeeepplp/lff~nKnda;'XXXv/&&JqIGIGHGHHHHwH4www4w4w44w4HH4>w>HH>HL>L>L>LU>>L>L>LLg>U>>ggg/////llljXjjjjjjXX'X''';;;;;;;''XXXXjjjjjlvll//xx*n~n~x>eeDuuuu+mQzQ}YHGLLUUUfgJfff&fxfffff", +"fJfJfJgUJUUUU>>LLH>>wHHwww4ywDywyD+DDDuDuDDuDDDDeDeeeeeepppppplp/lpppppeeeeeDDeDDDDee4>>f&*nndc<'XXXvlhJJqqqIHYHHHHH4Hwww4wwy4www4w4HHH4L4LH>>H>LLL>LL>L>LU>>LULgUggggf//l/lljjjjjjjjjjXXXX'X'''''XXXXjjjjjjjvjll//hh~h~n*~fe4Duuuu]m66Q}}}HHGLUUJJffffxffffxfff", +"g&gfJfJgUUUU>LL>L>H>w>w>wwwwwwyyDmD+DuDuDuuDDuDDDeDDeeeepeepppppppppeeeeeeeDeDDDDeD444>gf~nnnd<;'XX'v*&Jq$qIGHHHHH>Hww4ww4y44y4y4www>w4H>HH>HL>HL>LL>LL>LL>LLLU>g>Uggfg/x/pllljjXjjjjjjjjXXXX'XXXXXXXXjjjjjjjvll///xxf~*`~Jgeeuuuuu+66QQ8YYHG>qUUUJfJffff/&fffff", +"fJJJfUUUUUUULL>LHLHHHHH4wwwy4yyyyymD+DDuDDuDuDuDDDDeDeeeeeeeeeeeeeeeeeeeeDDDDDDDDDeD4>/f&~nndH>H>HLH>LH>LLL>LL>L>LLULU>ggff////llljjjjjjjjjXXjXXXXXXXXjjjjjjjjjjll///xxx~*~*&fe4Duuuu]+6QQQ}}HHGq>UUJfgffffffff&fff", +"JffgJUJUUULU>LL>H>HL4HwHwwwwywwyDymmDmuDDuuDuDDuDDDDDeDDeeeeeeeepeeeeeDeDDDDDDDDDDD>4>>&*~~n~=vXXXvh&&oq$IIYGYwHwwwwwwywy4DywDwyw4w4www>HHwHHH>H>HH>HLLHLLLLG>q>LU>UUggfg/h/llljvXjjjjjjjjjjXjXXXjXjjjjjjjjlll/l///x&&***fg4euuuuu]6CQQQ8YYGGLqUUfJfffff&ffffg&f", +"JgJUUUUUUUL>GLGH>HHHHHHwww4wwwywyyDmm++DuDuDuuDuDDDDDDDeDeeeeeeeeeeeDeDDDeDDDDDDeD44>/g&~*nw>w>H>HL>GHLH>LGLLLLL>GLLLUUUggf/f//llvljjXjjjjjjjjjjjjjjjjjjjjjjjvlp//xxffx&~&&fe4Duuuu]6661188YYHGLLUUJgJffffffffffJg", +"gfUJUUUULLLLLL>GHH>HHHHHwwHywywyyyyymmD+DuDuDuuDuuuDDDDDDDDDDDeDeDDDeDDDDuDDDDDDD44>>g&&~nnw4wHHHHHGHHLHLGLGG>GHLLGLLULLL>UUgfg/h//llljjjXjjjjjjjjjjjjjjjjjjjjjlll///g/ff&&&*JgeDDuuuu]6Q118iYHYGqLJqfJgffJfffffJfgfJ", +"JUUUUULLULLLGLHLHLwHHHwwwww}wwywyyyyDm++++uDuuDuDuDDuDDDDDeDeDDDDeDDDDDDDDDuDDDD44>4gf&~*n<<w>HHH>HHGHHGHGLGGLGGLGLLULqgUUfgf////llvljjjjjjjjjjjjjjjjjjjXjvlll///f/gff*&&Jge4Duuuuu66Q11i88YGGLqUUUJfJgfffffffJfJf", +"UUUUULULLLLHLHGHHHHHHwHwHwww}w}ywyyymyy+D+DuDuuuuuDuuDDDDDDDDDDDDDDDDDDDuDuDDDDDw4H>gf**~~4euuuuu]6C11ii8YYIGLLqJUfJfJffJgfgfJfUJ", +"UUJUULqLLGGGGGHHHHHHwHwwwww}wyw}yyzymmy+m+++uDDuuuuuDuuDuDDDDDDDDDDDuDuDDDuDDDDw44>>f&&~*<4Duuuuu66C1iiiY8YHqGqUUJUJfgfJfJfJJfUJU", +"UUGUqLLLGGLGGHGHHHHwGwYwYwY}w}}wzwzyyymy+D++DuuuDuDuuDuDuDuuDuDuDuDuDuDuDuDDD4y4wL>gJ**~eDuuuu]]611:!i,iIYGqLgqJUfJJfJffJfJUgJUU", +"qULGLLqGGGGHHHHHYHwY8wYwY}w}}w}y}yzyzmmmm6++++DuuuuuuuuuuuDuuDuDuDuuDuuDuDDD+y4w4>>J&&~*hqUUfJfgxx//hlllvvjvjjjvjjljllll///fggggggfJJJf>44DDuuuu]C1!!ii,8IYILqLqUJJfJJfJJfJfJUUJU", +"ULqqLGGGGHGHYHHYH8YHwY}Yw8}w}}}}z}zzzyQmy+y++++uDuDuDuuDuuuuDuuuuuDuuDuDDuDmDw4w>>gJ&x*hhvvX'vh*%o.${tt,Y88}}}yyyyyymmymyyyyyywyw}ww}wYw8HYH8YYGYHHYGYHYHIHIGGGGGIGqGLLqUqJUJgff/h//hllllvllvljljvllll////g/ggggggfgf>>eDuuuuu]611!!!!iYYYGqLqJJUJgJfJJfJUJUJUUq", +"LqLLGGGGHYHYGYYH8H8Y8H8w8}Y}}}}}}yzzzzmz6mym+++++uuuuuuuuuDuuuDuDuuuDuDuDmDmwywH>>Jf*~hhvvv';<~~oro{Vt-,iYi}}zzyyymm+ymymyyyyywywyw8wY}YwY}HYHH8YGYYHYYLYHGHIHIIGGGqGqqGqLqJUUJff//x//lhlllllllllll//////ggg>>gUgJJUg>44DDuuuu6Q1!!!!,,iGIGqGqJLJJJUJfUJUfJUqqUU", +"GLGGGGYYGYYHYY}8Y}YwY}}Y}}}}}}}z}z}zzzzzzmmmmm++++DuDuuDuuuuDuuuuuuDuDuD+myy4w>w>>J&&&hhlv''<**%o.{{{,,,888}}zzzmymyy+ymmyyyywyw}w}w}YwwYHYY}YYYHYGYYGIYYIYYGYGGGIGIqIGqLqUqqJgJfff/xx//l/hllhlhl////x/ffggg>g>U>UU>>>4Duuuuu]6Q!!!!-,iIIIqqqLqJJJJJUJJJJqUqUUqL", +"qGGIHYGYYGYY}YHY8H8Y8}}Y}8Y8}}}}8z}zzz6z6z6mmmm+++++uuDuuuuuuuDuuDuuDu+DmDywyw4L>fJx&hhlvv';<~~%.o{{Vt-i,8Qzzzyzmmymyymymyyyy}y}}}}}}H8Y}H8YHYYYYYYIYYYGYGIGIYqYIGGILIqqqqqUJqJJJJffxxxx////h/////h/xfgggUU>LU>UUgUg>44Duuuuu+Ci!![!--,YYGIqqUqJqJqfqUJUJUqLqLGL", +"GIGYGIYYYY}YY88Y88888Y8888z8}Q8Q}8zQzQzzzz6z6m6mm++++++uuDuDuuuuuDuD++mmyyyw4wHLUJ&&&hhhv';<<`%o.R{ Vti,8i8zzzzmmymmmmymyyyzyz}}}}}Y}8Y}Y8YYYYYYYYGYGYGYYGYYYGYIGGIGIGqIqqqqqJLqJfJJfffxxxx/h//x/xf/gfgUU>U>LgLU>g>>44DDuuuu]6Q!![N--,iIIIqqqqqJqJJUJJqJqqUqLqqG", +"GYYGYYHYY8Y88Yi88i88Q8Q8888}8i}8Qziz8zQQmz6zm6mmmmm++++++uu+uDuD+u+++y+ymywywH>>Uff&hhlvv;;<~*rr.{{tV-,iQ8Qzzzz6y6mmmmymmzyz}}}}}}}Y}YYY8YYY8IYIY,YIIYIYIYIGIYGYIYGIGqIqGqIqqqqJqJJfJfffff/f/f/&/ffffgUUULLUL>>LU>L>44Duuuuu]1i--[-[--IYIGIqqqUqJqJqJqJqLJqLqGIG", +"qYYIYY,88Y8,88Yi8888i88i8Qi8Q88}Q8Q8QQQzQQzQ6z66+6mm+++++++++++++++y+myyywww>HLUfJ&*/hhv;;<~`%rr.{9VV-ii88QzQzm6mzmm6y6zyzzzzz}}}88Y8Y88Y,8I8I8IYIYIY,IYIIYIYItGIIGIIIIGIqqqqqqqJqJqJJJJfff&ffffgfJUUUULLLLLLL>>L>>H4Duuuuu]68i![[[--i,IIIqqLqJqJqqJqUqLqqqqGqGI", +"YII8Y,8,,-iii,1i8iiii8i8Q88Q8i8Qi8QQQzQQQQ6zQmz666m6mm+m+++++++++mmmyymyywywH>LUgffxhllv;=<~`%r.P{9VV,-iiQQQz6zz6mz6y6yzzzz}}}8888i88,8,IiI,,,I,I,I,IIYtIYIIIIG,IYIIIGIqIqIqqqqqqqJJqJJJJJfJfJfJJJUJqUqLqLLLLLL>L>44DDuuuuu+zi-[[[[--t,IIIGIqqqqJqJqqJqqLqGqIGIH", +"I,Yi,i,ii1,i,iiiiiiiiii8ii8i88iQ8Qi8Q88QQQQQQQQ6zm66m6m6mmmm+mmmmmmmmmzyw}ww>HUUJfxxhl<;;<~~%%..R9 V--,iQ8QzQy6m6z6zmz6zzzzz8Q8i888Y,i,Y,,I,,I,,I,I,YIIYI,IIY,IIIIIIIIIIqIIG$IqqqqqqqJJqJJqJJqJqJUJqqLqLLLLG>H>LH>w4Duuuuu]68i-[[[[[--,,IIqqqqqqqqqUqqqqqIqIGIYI", +",8,,i,i,i,iiiiiiiiiiiiiiiiiiiQi8i8Q81QQ8QQQQ6QCQC666666mm6+6m6m6m6m6yzyz}wwHHLUUffx/hl<'=Ufffxhhv;;a~~W%3..O92V--iii1QQzQCm6z6zz6zQQzQQ8Q8,i,i,,,,t,t,ttttttttttt,tIt,I,I,IIIYIIIIIIIIIII$qIqIoqqoqqqqqqUqqqqqLqGqGGGLHLH>H>wDDDuuuu]mQ,-V22[[V-t,,III$qqqoqqqqqqIqqIYIYIY,", +",-,--!-!!-!!-!!!!!i!!!i!ii1iiiiiii8i1Qi181Q1Q1QQQQQ6Q6C6z66m66z66mzzz}}w8wGLGUUJff/hlv==w4w4D+uuuuu]z8iV2[22[V[,tIII$qqIqqqqqqIqIGIIII,Ii,", +"---!-!-!-!!!!!!!!!!!!!!i:!i!i1i1ii1iiiQi11i1Q1Q1Q1CQQQQ6Q6QQ6Qz6zQzQzz}}wHHGLUJfxxxhv<;a~n`W33^PO92V--!ii11QQQQz6QQQQQQQQQiiii,--V-tVtV{V$t{${{t{{t{t{t$tttttttIttt,ItItIIIIIIIIqIIqI$I$q$qqqqqIqqIqGIGIHGHLwHHH4yDuuuuu]m},-V2222[VVV,ttIIII$q$Iq$qIqIII,IY,,-,", +"-----N-![![!!!!!!!!!!:!!!!:i!!i!iiii1ii1iiQi111Q11Q16QQQQQQ6QQQQQQzQ}}Y}YHGLLUgffx/hla= c #3A2C8C", +", c #12D6EE", +"' c #22A6D6", +") c #2A76B6", +"! c #2AEAFA", +"~ c #16CEEA", +"{ c #228BC6", +"] c #0EF2FE", +"^ c #47BEE8", +"/ c #3A2286", +"( c #2EAEDA", +"_ c #4A76C6", +": c #1EEAFE", +"< c #3B95D5", +"[ c #16DAF2", +"} c #1EFEFE", +"| c #36F8FE", +"1 c #3EBBE5", +"2 c #32A2D2", +"3 c #3A1E82", +"4 c #2EEEFA", +"5 c #36D6FE", +"6 c #2A7EBE", +"7 c #3BA8DE", +"8 c #2F60AA", +"9 c #23C2EB", +"0 c #268AC6", +"a c #419EDD", +"b c #0AFAFE", +"c c #387EC1", +"d c #56B2F2", +"e c #3A1A82", +"f c #16FEFE", +"g c #50FEFE", +"h c #32BAE6", +"i c #2ECCF3", +"j c #3E127E", +"k c #43D5F8", +"l c #4896D6", +"m c #2BFDFE", +"n c #436AB9", +"o c #4AA4E4", +"p c #4060B0", +"q c #22BEE6", +"r c #4656AE", +"s c #46F4FE", +"t c #318CCC", +"u c #2883C0", +"v c #38167E", +"w c #393E97", +"x c #404AA0", +"y c #50ABEC", +"z c #4381C6", +"jjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjj", +"..........................v/>>>/.....v.........................v", +"jjjjjjjjjjjjjjjjjjjjjjj>8u--{)%=.j..e>w%w>3.jjjjjjjjjjjjjjjjj.jj", +"..................../%-&###-{)%=...v/=%$)6)%>e...............j..", +"jvvvvvvvvvvvvvvvvv/6'#&####'{)$=.j..vew%66{6{+>3vvvvvvvvvvvvv.jj", +".jjjjjjjjjjjjjj.>8-#&######&-6%=.v....v/%+)u)uu83jjjjjjjjjjjj.v.", +"..jjj..jjj..jj.=#######&##&&-{8=...v/>>/./=uu{u6u%>...j..jj.j.jj", +"j....jj...j..v)&&&##########-{$w...e>w$8%/v=$)uuuu+3...jj..j.j..", +"jjjj..jjj...>)##########&##-)%vv...3>%8)6)$.3=)666u)%3...j.j.jjv", +"v...jj.....%-######&##&#-8=v3/%=..ve=%8)u6u$=e=8{u6{)8vj..j.j..j", +".jj..jjj..=&###&######&)vv%,@~{8.../=%+666uu68v/))uuuu%3j.j.jj.j", +"...j.....w{&#########-//)~]]],{8..v/w%)6u{u)66=3%)6u666$.j.j..j.", +"jj..jj..=-##&####&#'8>8#bbbbb@{+..v/%%6)6){{6u)%v=8{6u)u>v.jj.jj", +"..jj.../&&########'/38]bbbbb]@-8vv.=%8){u{)u6u{)>e=)u){6)=...j..", +"j..j...$###&#&##&'8%#]bbb]bbb]'+..v>%8666{6{)6uu+=386u666+w..jjj", +".jj...%-########-==,]]b]]bb]]]-).vv=$8uuu6uu{u{6{8==8)uuu68vj...", +"..j..v'&#######'>={]bbbbbbbbb]&).vv=8){{{{{{u6uu{)8v%+u6u)6/v.jj", +"j...v%&#######&)/'@bbbbbbbbbbb#6.v3%860{u0u{{{{{u{)//$){uu{$>...", +"..../+&#######uw-@bbfbffbbfbbb#{..v%)){tt8u66uu{$v.", +"..v$'####9#~#+89fff}}fffbbbbb]]'.v/+)uuutu<<<<<<<-t{)w%)u6u)u8ej", +"..v{&#####99-$#]bf}fffffbbbbbbb&vv/66uuuttt<<<<<", +"..8&####9i9'w+b}}}}}}fbfbb]bb]],..vvv3.v$c0<8tooooaa.&]@]@@::@i/=naoo7oo2z/x<<0uuuu$", +"v%{#&##99ii=%2mmmmm}}}f93=-]bbb~v&@@@@@]:]!z=xlodooooc3x8}fb]]bbbv&@@@@::!!4;i)xlyyyoar>c<6##99iiik58%;mmmm|4<%h}}}fbfbb.#@::::!!444t=j/_lolw/z<<<wo2<raa<-t0u)6=", +".v$&#q99ii55k2=7;hev/3c;|mmmm(.ph4|4|!c>>ks*lwe=/xzya&##q9iiii;k<===/e/wcz.3ni4mm2j$(m4;arjp1g4gdrjj3looo<ejv/=///r^**ssg1xj/pyyoa<_ddyoaae.jj", +"......$-qq99iiik5k;k^_/cgggggggggggggggss^n>_ldyyoa<<-tu6u8e....", +".......8&##99iki5kkk*kp/r1*gggggggggggg*r//dddyyaoaattt0u+=..vvj", +"j...v../'##9i9ii;i;ki*k^=j=d*gggggggs*n=/_yddyoooa<rzoddyyyoalaaxpzzaa<<.....j..jj.jj", +".j....j.jj.j..jj=8-qqq99iiih12c833e3/xpnt)'99999i9h(cpeee3/=r8cu0uu)=/.......j..jj.jjj", +"j....j.j..j..jjjjjjv>%-&q99q#(0n//ej3>w$)66w=e...j...jj.jj..j...", +"jjjj.j.jj.jj...j..j...e>8u-#&#t+//3v3/==w>/.......v...j..jj.jjjj", +"....j.j..j..jj...j.j....vje/=w%w>/ej.v.v.v...j.....jjj.jj..j...."}; diff --git a/hacks/images/scales.xpm b/hacks/images/scales.xpm new file mode 100644 index 00000000..3b185f0a --- /dev/null +++ b/hacks/images/scales.xpm @@ -0,0 +1,204 @@ +/* XPM */ +static char *scales[] = { +/* width height ncolors chars_per_pixel */ +"128 128 69 1", +/* colors */ +" c #B1B1B1", +". c #AFAFAF", +"X c #ADADAD", +"o c #ABABAB", +"O c #A9A9A9", +"+ c #A7A7A7", +"@ c #ECECEC", +"# c #EAEAEA", +"$ c #E8E8E8", +"% c #E6E6E6", +"& c #E4E4E4", +"* c #E2E2E2", +"= c #E0E0E0", +"- c #DEDEDE", +"; c #DCDCDC", +": c #DADADA", +"> c #D8D8D8", +", c #D6D6D6", +"< c #D4D4D4", +"1 c #D2D2D2", +"2 c #D0D0D0", +"3 c #CECECE", +"4 c #CCCCCC", +"5 c #CACACA", +"6 c #C8C8C8", +"7 c #C6C6C6", +"8 c #C4C4C4", +"9 c #C2C2C2", +"0 c #C0C0C0", +"q c #BEBEBE", +"w c #BCBCBC", +"e c #BABABA", +"r c #B8B8B8", +"t c #B6B6B6", +"y c #B4B4B4", +"u c #B2B2B2", +"i c #B0B0B0", +"p c #AEAEAE", +"a c #ACACAC", +"s c #AAAAAA", +"d c #EBEBEB", +"f c #E9E9E9", +"g c #E7E7E7", +"h c #E5E5E5", +"j c #E3E3E3", +"k c #E1E1E1", +"l c #DFDFDF", +"z c #DDDDDD", +"x c #DBDBDB", +"c c #D9D9D9", +"v c #D7D7D7", +"b c #D5D5D5", +"n c #D3D3D3", +"m c #D1D1D1", +"M c #CFCFCF", +"N c #CDCDCD", +"B c #CBCBCB", +"V c #C9C9C9", +"C c #C7C7C7", +"Z c #C5C5C5", +"A c #C3C3C3", +"S c #C1C1C1", +"D c #BFBFBF", +"F c #BDBDBD", +"G c #BBBBBB", +"H c #B9B9B9", +"J c #B7B7B7", +"K c #B5B5B5", +"L c #B3B3B3", +/* pixels */ +"VB32nbc:<6Fy uLtSN1cl&$#fzBDFD98765V76NM22m<,b5r.. LKF3lgkMFKyJewFZvg@*3euuteFqDDGLp.LtHwqDSSqeHew", +"NMmb>><4AGJyKJreAM,cx;-=*kz:>vv>cccbNB4N3M21<>x:1BBmv;xn6S987654M34M1xzx2Srtrewq0S72:l=k**kxn3B55VVVV79C2CJLJF9AA8765BNM1bbnn,c;-=kl<8HrGFq0A64BZqwF098CVB2b1CFeGqS876V8GJrGqS98CVCZ5321n", +";zl==:4DeGq0AZC6Bm>;xc,x;-=j&-2GaOXuKteA42m1<,cxcm54=&;3Z8ZCVBN21MC8754N32nbv<6euuKrwq0S7mx=kj&*cVJXpyFCMnM5VBNM21:;:3FKytHGFwHw9Z7C5432Nq.XitG0ADHtJHw098C652>zlkkx4w . tGD9SF06Mn,>cx;>VHKqVmvx-=zn8LspeCn:;-kj&=cv>c:x;:nCGyutD63", +"yuuLytJGZm:z-=k*x4qrHwDS889A64NNM1<1,-kjjl,VFJtrGFFe", +" uKrGFDS7m;=**k-4FKKJeFDSDqACV5BN2<*h=v4Sq6>j$h:40eeGqS9Ft", +"rewDS8C6BMBDGFDS876C753mm14G.p LLuJq98CV5BCG iyH0V<;xM0tKJGqSZV58GttrG0AZ52c:-*h&*l>3ADS8ZCV4M3431,>:;llc6r LKrHHF8V5432MVwKtew0ZB3BAwGFDS87V57DGGq09Z6BN48eup. uJqCNNC99876BN35Z", +"CV5BNMnbnCHu ytJJe8Mb>:x;;x>c-jkc2ZwrwAVB4M1b<3V41>-k&*vZHreFDSS85Mm1<,>MDKKJGFD9ZAetwZ421:z=k>CGHGDSAZ7Vmxzcn4ZDerHHtyyKtrw8N,x-=z2q iKwA5M35ZZCV5NM2m,zkj&*;mBV5N32<x:<332nbv:z-xMSwFDSA7V5ZHiLFVmvxl**xm", +"DZN<:lj*>V00A7CVB3Mm13C0GrrrHrLLKrGFDSZNv=%hc6r LtGq98AZ6B32mnb>c;j%%&=>m22mnbv>n47CMbcxzx,Bqy HCbl&jl,VwtGC<-h$&:5GrD7B321<1CeLyrwAB,l=b9L", +" yrFA6NN4N3M22nb>x;<8eJHwqSA77998C6543Mn>lkcVDwqS87C5VAwF8Bm,xljj;39wrKyeCnz*kcN0JyyH93xjlnZHu tqV,=kv6Hi e841,c:x-zb7qqSAZC5N3B54N32mn,>:vMC99A8765N2M8tLJFA5m>z;MGpaX. tDBv-xM9HrHGq9Vml=,VZC6542nx;bZerewD97V58HLLJewDS87C790098C65NM4AwGwDSA7VBNV0HewD98ZVN<;-v34N321b>:bVS0S", +"NM21<>:n9KLKHwDS8CCZCMbv>:;-k*-:;khggk,Ce .iJA2cz-=*=vCDDS9875N36DGwq0A7654BC88CV5NMmnb1C9987CV421n38DS8ZC5B3mbc:vbbb,vc;ll>4C6V", +"b,vcx-znAHHGqSA76BNVZVm>zk&hh=<66m:k=,7eyLKJeS4:&$$g=<6Z7CV54Mnb2C88ZCVB32nn3BBN2mnb>::<686B3M21b>,NSq8V43Mm<>:cbVweDAZC6B3m1Vwr04v=%%-m0Lur9VVAetJHGq0A5vh#glnC86432mnbc:nBVB4N3mn,cc:;xn8JJ0B1bvcxz;n6Z3:*%f$hx4wLH73", +";k%gjcVriK0CBN3m<,1ZyXuG71c,VGioX tHrHeGq098CVN<;;nCeLHZ3<,>:;;>NA73nb,>:z-:M6B&fhc6H.a wA", +"n;%hc6rXouF6M<,>:>3q p tw9AFypX.LtHrteD98CV5N211N9J XaLq54FyeCnxl**=xM0JG6b=ggz3qyi r92x**x4FyLKHS4vkh=1AJ .iyrw", +"51c<7ri.iywZ2c-k=vCHyyJeFDGL.iLJewDDwD7VBNMmn,>nZyXXp KGA3:**cBwupuq4cjg&x3DLpueCb-x3DtLKJG06nx:30rJeFD96mxznAtiiLteD90GKLLtHGFD", +"5BV0JLLtHGq8Nc*%k19eHwqSAADrtrGq09Z7ZCNmn:zzbAyiLtrGq9V1cb6GLi KeA2;k:BFy yHDC5ZFJJHwqS8C4MB9GGq98ZCBMmNStuyJew09DHKKJeFDSAZ", +"237wJreF098CN,kh;40qDS87V57SDSA87V4NN3MC88765N223VC6554M1bbbbbbNZ8C654Mm:,34M21<,>x-;nC9876VBM1<<24N3Mm1<,c", +"znZDA5M1n,>:>M0u.eC2<,>:;zz:>>c:xz--:3DJtJewqS9SS632mnbvx;:mV7CVBN3mn<3AD9Z65N3m:zlzb5VMxzl;nZJpXt9Mc-=*&&*-;lk*kl;,NDKyJGq098C66N<>cxzl**znNN32mnb>c,BFG9VN21b>cnZJtqV1:l*&jcCHH83>-*%gk2Fut05mb>;-lx276mc-*h%h", +"GLXpKDB,-j*c5GyuyrD5v*g$%k>21:=k;<4Awyurq98C653M3mv-k&%g%kvBVM:;-xmSyLG7M,c;-:3Fu J05blhgl4rXptD5nxk=<0 X HAN,zj&ln0Lt9M:j$%k", +" ..utGAM:kzM0JJHwq071-hj:MSrGZ3MV0etKyKG865432n<24M>kgfg-1AHwCn;=*jk>Cr tDB,-*k,ZrLKHFA4>=-2Fia.uJF8N1NSyi KHq72:kkb9uopKDBv;vN", +"uLtHwq9Vm,2Zwew0A87V3<<4SJ piKrHJKKJeGGD6321<,vn5qwZ1;zb6Gupuw5>*$gzNFKytHFZ2xkz30HHwDS8V21BFLiutJeF9C7qtytHwqS8B1vm8t..uteS7C0H", +"reqSAZC5NB70DS87654M2B0K.pi LyuuyrGF099ZN<>x;x,4DKLr08SGuppiLr9M;h*nAeHGFDSZBn>1C0D09ZCV4MB0tyJeFqSAC57FHeF098CV4M49rLLtHwqS9FJK", +"0S87VBN22B78765BN2nbz=lc30JyKHGrui. yJeF9V2bmC0qDSAZ6532M5Z87C654M11BqHGqS87C532NZ998C654311BqrrGFDS8CCSww", +"6V543m<,b3CVN2m1<,:x>BeytHwqS90D9Z65BN21vM8D098ZC5NN57C", +"mm1nb>:::xzk*;N0wFDS876CCVNM2mn,vnBC8SFGewqS88SGewqS8C54B9KpuDV3221b>:b5S8Bm<,>:x>3qLrABMmnb>x:,331:z-;<5C6V543mn<13M", +">c:xzl-v5H r7n;kj&hj:48A8765NMMMmb,>cx;cNqKLytG08765B6A987CVB3M5quaiw61,vc;z:3FLrA3v;l=z1AypLDB<>x;zzv49ZM>;l=*j*:MVB32mnbvccnN4", +",:ljh*:NF pLF5vkhj-,60964NMmnb,,>;z-=*kv7J uKrqZ543m1245BNM21xz-;vBDw", +"C2x&%-M0K LJGA4b,2CqyuG6mbv>xz-;c:;-*j-20rJewqA5M1b>:cb<c>2AeHGwD8M;hfhc6H yrD61cb6wttHGq83:kl<7eL yw6v&%l1ZriuF5,-*j=>BFui", +"w8Mc:MSHtJGF0AZZDrL p.J8m:lkjh*cN6V3nbM7qwqSA8CNljhhkc,x*%$h>BAA7C543mb:vNSeeF098C55C9DDS8CV5NMMV0HtJGF09ZCZFK iuyJG0V<:xzkjl>n22m1n,c::xzlx3wiaXyDVM1<,c;;>n<,>cxzl=zx;-kk:M66VBN2mM7eu KeqS8ZC5N3nx=kkkklv6H .iutHwDqD7M,x-kjk,Zt uyJq61c;-ll:mVN,zkjj*zbV973mn<,c;zx15V5B432nb>v2BB4N3M2", +"V8DFwqZ2;jh%g&;nM221nb>vbnm49t uyJHwD980Jtw7Mvz=:4FttHGF06nzjj=>4DJFB>k&lvN9HrSN,:zl=kl>464mn<,>xzlz,1<<:x:n6FHewFFD74Mmnb>xxb59DFFweyiLHwqS87V5AyapKFZN24AwGq0987Bn-*lMNb", +"A8ZC5NMn:lz,NAGF6n;k*;28qqS98874nvcx;-=-mqLiuytJKyHDA8C5B3NZtp.LJw00qqD98765N2b>,N0JuuyrwD0FryLytrwAN:**>NSJiuwBc*%ghlbCwFV,z-v2", +"65BN2n,v*&:NZA8CV4N31czlk*hh-4r uyJewwwD75B4Mmn2ZryKHGq0DFSC5BN3m1N", +"M2mn,c;x3e.Xpi yHS3cz,NVV5NMnbbvx-l=k*=bZHJrGqS98874mnnb>c:xc30HrHwDS87ZDHHwDSAZC5N4ZGyuytrGF9B<>1Zeu.iLJF7NMM", +">vc;-=*z5KX.LJHGqSCNmm222mn,cxxv122MMM49GGqSAZCVB43ncxxzllvV9987654NN2,:x:xx:>1CFwqS87654479SA8765N2n3SJKJeFDS8CVVAeL iLJeGqS6m,", +"-zlk*&jc7JyJGqS98CV55Nmbv>:z=kzM0rrHGwGtJ0765BNM1nbc-=k*j=vBC65BN2n<<c:xxvBDGw0AZC6B3M4Z96M<>;=&&:7ypiLKrHrGZN22mn,cx;:c::::v24NM21<,>v<3M1mB790qwHeA5321x-->47ZC65BNmnnBFJrwqSA76B43nv", +"8888779GHD8CV54N2>:z=k;MZS9AAS95nv>:xx>1VqreweHHGFqqDC2,>:xz--;ccx;z-l==;<4B4N3Mmnb,n5DF098CV43m1M6A", +"LytJewGre8B3M2mn,>>4HaaurFAVN59HJrGq09ZC63>zllkjh*<0L LKJte7b-kkl>MZwy..LJeF09877Bl**=-x,3ZAB1bbb,vbmB9F9C54321>:zl:5J.iyrw0AZSwwqSAZCVBN32>b135CAAN>xcx-;mwi", +"JHFDS87C63,:zll*hh;6HKJGqSA7C8SAZ654NMm:17FrrGFwGq8C5BN2n,m580DqqDZ2c;z-l=*zMqK", +"q0A87V433N3n>x-*hj>CFFD9876BNBVBNM21nb>:,CtiuteFFrtrGq0S8C5B5C80weGqSA8AZ532mnb>:,6eKKJrGFDDwt i LyKeqD9C5680Fq0S8Z6mx==l--zb6DG", +"ZCV54M1<28wF9C4mbc:;llb9uXiLJHHtHD987C5N34AHyrwDS8CV55Bm,v>xz=kc7rKJeFD98Z0ti yJew0Z78S0qqD09ZC5BNmbbn2346SwqS", +"NM2mnb>>3w.puJGDA9085N32m1b>x>m42,:z=j%kmqyLJHGqqwD754N3213CwuiJ07VBN321nvx-lkj%hx6FwqSAZC557wrHwqS97BN58S0987VB4M11N8qGeeeeJJq7", +",>>cxzlxBrp.uKrwDqqCmbbv>:z==>Cwq7M,xk&zBFreFDS8Z87N1n:>,,cx-k&*>BZ87654NM2480SA87VNmn1N665BN321bvbVr iuKreeGS5", +"l==kj&&xCrytHwqSA88Bbx;;-kjhk2eppKFAB1bM8qqS8ZC5443n>xxxv38weGwq7mv:xzl-,5A8CBM1245BN3M2mnbvn4665BN2n,cv25BM1:z-c13Mmnb>xz;b6DA4bx-=*k;20rrwqS876V54", +"Mmn,>cb4AS9AZC54M1M8GGDZ52n2ZHLLJHwD98AS74M2mnbvc>b1>==>4Z9A76BNM>kgf$*10y LJeF0DwD5nc;-=*&=,4B2bcz=*kc5r.y03ck%%lmSttF98CVB3223", +"uKHwDSDq9CV5BN2nbvmDpo.KHF0FrtrGqS8765564n,>cxxxc15AZMn2BVV5431x-=z=%%zNwia.tSNc=;M0L.yq75NM1<,bM", +"+sputrreA4m1n;ll;,N8wrHF9VN22m1b>:c1VA90FeHGqSAZC56GppKDV<;;:x;-*j-3GLyJHwDSDFS7V5BN2n,,4S9Bb:c16qHJreGq61v>>c;llvCt.pp JF98765N3VGipuJF8V7qypp KG9BM5DJytrGF0A80HyytHGDC2>-k*z3q", +"LteFqSAAC1;=*jhgg-4FewqS8766CV3m11k%*--,CHKJeFD0S61:;zllv5SDSAZCVC9qDS8765NM4787V54N2nbM8DD", +"54N32mD puKrGHJq52mnb,>x;:13mv;==>CHKtrGFFq8C5N32n<29yLHDZZSFeGqSAZCCBblj&h*vBZZCVBNMM5CC65BN2n121nnb>:x>30tur0", +"21<,>xz:NHXXiyJeeH03v:x;-=*l<9JH0CN4ZFHeF0988Z53mn<,cv4GpXiKrJtGD9876543m,-kk=x144N32mn,,1222m1<,>vNqrwZ3<:-kj*;,,cxxz=kz1Suaayw", +"MbxlkjjxVr LJGF0SS8Mcl*&gf%x6KaXurwGrGqS87654N2b>x;z-,Zt. yJeHHD75B432nb,x;:=h%-15Mv-*%$hcCJ..iyJ", +"V1-h$fh>ZerGqS8Z6V6VM>lhddkMw . KreHHqZV5BN2nn,xl*&&lm0tKrGqSS0731nnb>x;cNDJKyyr8m:l==lx16ZB<;k&&zMqKyJG0C2:lc5eyeCnz%fk3FyLtreG", +"C2;%$jcB0FD98CVB3M6FH05<;;m9JyJHwDSSD842m17erGq09ZB239yos.rS4,cmAHrewqSA", +"Nm>:b5qtJDZV543mcxz--:<2>2SuXiyrrttGD98765NMM1clkj&k:MAwF9CCZ7CV5432nbv,,>xlh$%x6etrGq098C3:;:m8D9Vm,<49wwq987V5NNVSHJreF0S8CCSHe9VN3Mm18HJHFqS8CCAA6B4321b,", +"-cVJi yJrw82x*&kvCGrGFDSA9S63mn<,>::b47Vm,1ZeLLKrGwGDB,:xxzlkkcCya.tw0qwD98Z654Mmnm6qGwqS87C5B7eiuq5mb,>x--,6Dq0AZC5N3N4mnb,>cxz", +"=v7rtrGqDSZ3:&gkn8qqSA8C55534FyyeFGJKKrGqSAA84>-=*hgg=2wpo.yJHJHS6BNMmnb>>nC0SZCV5432NAtpiHZM>zkj&k>477654N2n,,ljhh*xNDyi LuLJHw098CV5CZBn:kg#gc8KiuKrGqFq72Nqe9532mnb<30KuyrDVb=&&k:MV5NM21<,>xx*$g-M0JyKJrJrFS8765NMMCetwZmxl:BwtJeFDS8ZZB,;zzl=l:MDuuwV1,>::,BqrHGq0CMv><4AGqV1v>cxz-l:5eKJHFS87", +"DF9VN3M21b,1Ceu H7Mnb,>xx,5qGAm:cM9ereFqDqD8VBN3m<3w.a.uteFD", +"8ACM4FuiKF9SDFwqSA87CC52n:vNqLiutHwFewS87C65N2nN0tuuKH0B>*h=nCA8765NMB0tuuLyJDBbcv<24CFupiyJGqSS", +"B5N<:z-==;18HKKrGS4:&gj:NDy utrJtG098765N331v:xzllv6eKJewDS0FS64NN32n,c>NqreD9SwJKJHFD96n-k;mB5B432n<4qKyJewq0AZZ90qFGt yHwqS8CC", +"1mMMn:=jk>5qHeFDSA5vhgzNDJytHwqwGSC5B432nb,clkjh%*:>N0eeFDS88SGJtJreGerG0AZC54N", +"vnVDDC1>vNAqqS9ZCVN<;cNSHrGq0988ACN21n2M1,bMVZZC54N2cx", +"18J KJHeD754N32nz;20rrGqDS9852n<,>c18K.iyGZm-$dg;mN3M21<,,2CZ7CVBNM2M1vx-=*j", +"8GKKrGwFFA4mn<,>cb39Kir8BNN32nv>>cxz-,ZLapLH0C569FFD987CV5M,:;-lxM0tKrGF95<;zbB5M<,>cxzzvMNNM2mxzx2DKtDVn:b6r.X.uKJr0Nclk*j&=1DuiLteFS9DFS8CV54N21bxkjj*c5qGwqSAZ65C0rywV,;=*&%h->bb,v>c,3AqZm-%%=", +"qqD9ZC54NM,-j&k:MAeJJJG82:-lk*=,ZKXpyeS9Ft yJewD08N:j%$fgzBGtJeFDS8Z99VNM2mn>cx;l=x1BVC8SS87654M2N9LaaiKw7bjg&;mV5nzk=v49GrrGDZ6CC", +"BN3M21b>cb3N1n3ZqFD987C5m;%d#*nStyJew0SqHHFS98CV4M23577V579SSAZCV5N2n1mbx-l*&h%k10KLyKJqCNM21b:;;v4qJHGF0SAZ6543212ZwHGq09ZC7997V5BN2nbb4qu.uyLKq7BN32mnvcvm31cl&$#%cZyp.uytFV1,>:xv4DrrGD9ZCCSJiaoX rDA8SqDSA8CVBVA9", +"VM,xlkl>4qL.i JS6BN321b,m7qeHJrwD987654NB421nnbv:;,CKoop iLqBn,v>c;l-bAJr9Nvlkx5e uKHGw0Vbzk&*c50qD97VB46G.oa.utHeeF098CV5N2mBFK", +"JDB,l=c4FyuLyyHZ2x;>BepaXpKD7VBNMmnbbv:;;;z-=ln0upiyJJr0Ncl=kj&hzBtOsiHS6B7FJJeqS9AZB,*f#h>58ZC5N211NqLuLJeF0DF0754321b,nCKo", +" JD62mVqtKJGFFD6<;-l=k-n9LX.uLrSB2nbv>x-lz;z-ll==;NFKKHwq0SZN>l*h%%kmq.oX KeFFeew098C65Nm>*%j:M55NMmn,>>m9eewDS87CZCN120yiLtreq0qGDZ65543mbv::nVDFABmb>xzl:3SqSAZCV433Mbx;z-==:BGyy", +"q0989qFqS8ZC5N3Mn>zkj-2SHrGqSS973c-l-zz:m0KLtHwDDFwDA8765N2m50GF0S0HLuKeFq09Z89C4Mmmnb>xz:3w.opr83b;kjln9HFA6BNM1b,v:;zzzzcm8eHG", +"8765VZ8765BN2nx-kkcZ ss.KFZ3>l=,8K rS52n,cz-x3DyutHrHq8C6543mm4Z0FwGweyXX yJGFqq0V2nnbvxx<8KiuKJJJHD8C5BN21<25VN2n,xl*=cx--v6riiyttH95N32m:zll:b,:zkj&l1StytHwwFZM<,vc;-cVetJGFDSDwwDSZCV43M:;lxNH. KHF0Z6ZqeGq09Z65BNB9wGFqSA7B1x*kvZt yJGFDS8B1,", +"=*&&-m7CMv-&jcVFHGFD9AA6n;-=*&&x5qwqS9ZC788C65NM1b,vcxlj%j:BA987CV433mbc;-=j&;VrLKrGqS878DS87CVB321n2CSSA876BM1bz=&&>7GeFDS87VBVZC432mnb,>>m687VBNM1bb28taaLF98765N31:=", +"-lzn9uoX rFS9S98765BN21n,c:;zz>25554N32nbbbv>cxzl=cVHuLrGwwAN1nn<,ccnCD0Z4nv,NAD0AZ7VB323C741,cxz-->B0D7N1bvc:,VHpsXKDC4N32nbb,>", +"Z7AwLp. KHwFFD74N321<,cvMZSS9SDDZM1n<,>xzz;;;;zl=;3FiXiytreAmcx;z-lc4wLyrq87ZS9ZCV543m:>mV9", +"tty LtHFDSA984nb,vcxz-v7ypiuLytS2>x;-lk*=cnmm1:vBeiyD4>k%*5wKu", +"GFwGq98C65N2116r utHGq09Vmv,bn2B0yp.uKrHJteqSAZC544688644CSqqS87C54B8DZm:=&%h:VeLLteD8669Greq0986422VA0S8765BM>*&x4qttJ", +"9889ZV4N32n,>bN6654Mm2CFJJeF098CC790qFwGHLXpuKrGFwFS8C554M1M9y.utJJwS8C54NM2NDLyDN:&$*1SHrGqSAZZ0wGqS8765N2mNVCC65BN2nbcxvB0eewq", +"V5B542nx--bSyuKrwDDeHw098CVBNNCeuiuytJy yrw09AAA7B32mnb,3q.op LKwZBN3mn<1VH.pKDBvx,VDFDS876BB7997V5BN2n,,M554M213AwwqS8Z", +"3211nv:x;-=*l2eXXiyrGGHw9CV543mnnBGuuKrGFGHw0876V5BN1b,>:;c4G iyJHGD622AJLyJwA6V6ZA8ZC6B3m13VVN2m1B98Bm,c;-l;MF e9C55", +"<,>cc:;;zzl-vCtiutHwq0D0CN221BDHHGqS88Dq9CBNNMmb>>mVV3nv:;l=-10yt0Bn:=jkbA sprABM2", +"xz==:1M3NNN5AGttHqSA8CCCNb>>cx-lxMA0SA8CV5VBMm1<,>b22nc-kkvCDq0A7655Mc*%%=<7Dq098CV7wtGZN1bvc;z>5qF84N7765BN2mmnvc:;z:mZ096M<<378ZC65N2mcxlkjjlbCGJHF9ZZ8C5BN3M1b>>vv>bMVC65BN21MZJ ur0Bvkg%:CJiiyHD73mNSJKJeFD9Z6ZDHreq0986Mv", +"kl>5GuLKrGq0DDZ42m1nbv>>v>v147SFHr93,>:xz-zx-j%j>VFrHGqSA9ABmn40eHGS5Mm1n,v28HtrGD7m;&lMqKytHwSZ6C9FGwDS8ZC5570qD98765N2<", +"58FJtJew09ZCCCB1,,b<kkxn59wGDAAS0SAZCV4M35V3cb23M2m1nb,n3", +".i ueAVB432nbbmB7AS00S9ADtLKrGq0987B1,m6DeJJreHGSZ65B4M1CJ iLJHG93;h$hxM665B4Mnbn5S08CV54M1bvnBV31cx;xb50", +"LJrHqCMn>MDupLGA5BZGKKrGq0SZ4,zz>1NN32mn,>>29rF6M2mn,:;cM90Vncz=kklcMV3v-*&*x30t", +"HwDqSVc:;zc5HiiLrwqwHrGFDS8C6BNBZ0FD6m,>cx;xnZt.t7n>:;lk-nAKLw5>*g%l<6wJFN;gf*<8HK", +"w0AA8B>k&hjlvVGH0876543mm46V54321<,b4qrewqSA76552>;lll==vZKuyJeFFerG0987VBNM3ZKoou9n:zl==:BGiau9<;lk&&z5JXXLDmjd%,8Jpau0b$@l4FrH" +}; diff --git a/hacks/images/sea-texture.xpm b/hacks/images/sea-texture.xpm new file mode 100644 index 00000000..2f7206cc --- /dev/null +++ b/hacks/images/sea-texture.xpm @@ -0,0 +1,199 @@ +/* XPM */ +static char *sea_texture[] = { +/* width height num_colors chars_per_pixel */ +" 128 128 64 1", +/* colors */ +". c #b1b1b1", +"# c #afafaf", +"a c #adadad", +"b c #ababab", +"c c #a7a7a7", +"d c #a5a5a5", +"e c #a3a3a3", +"f c #f0f0f0", +"g c #e0e0e0", +"h c #dedede", +"i c #dadada", +"j c #d8d8d8", +"k c #d6d6d6", +"l c #d4d4d4", +"m c #d2d2d2", +"n c #d0d0d0", +"o c #cecece", +"p c #cccccc", +"q c #cacaca", +"r c #c8c8c8", +"s c #c6c6c6", +"t c #c4c4c4", +"u c #c2c2c2", +"v c #c0c0c0", +"w c #bebebe", +"x c #bcbcbc", +"y c #bababa", +"z c #b8b8b8", +"A c #b6b6b6", +"B c #b4b4b4", +"C c #b2b2b2", +"D c #b0b0b0", +"E c #aeaeae", +"F c #acacac", +"G c #aaaaaa", +"H c #a8a8a8", +"I c #a0a0a0", +"J c #9c9c9c", +"K c #929292", +"L c #e9e9e9", +"M c #e5e5e5", +"N c #e3e3e3", +"O c #dddddd", +"P c #dbdbdb", +"Q c #d9d9d9", +"R c #d7d7d7", +"S c #d5d5d5", +"T c #d3d3d3", +"U c #d1d1d1", +"V c #cfcfcf", +"W c #cdcdcd", +"X c #cbcbcb", +"Y c #c9c9c9", +"Z c #c7c7c7", +"0 c #c5c5c5", +"1 c #c3c3c3", +"2 c #c1c1c1", +"3 c #bfbfbf", +"4 c #bdbdbd", +"5 c #bbbbbb", +"6 c #b9b9b9", +"7 c #b7b7b7", +"8 c #b5b5b5", +"9 c #b3b3b3", +/* pixels */ +"PPilW0w65w2tZYpoUTlkRQQQjRRjPhNMLMMNNOTY38B7y42sWlPgPUZ4B.#abGGGbbFaE#D.A5v0qVljOhQTWZsoSONLMMNghOPQRkkkkkkjQPPPPiQQjRRkSWt5.HHH", +"PPilW0w65w2tZYpoUTlkRQQQjRRjPhNMLMMNNOTY38B7y42sWlPgPUZ4B.#abGGGbbFaE#D.A5v0qVljOhQTWZsoSONLMMNghOPQRkkkkkkjQPPPPiQQjRRkSWt5.HHH", +"PPQTp0w6y4v1srXWnmTSkjjjRkkRihgMMMNNNPmrwB97y42sWlihinsx9DEabGGGbbFaE#D.A5v0YoTRPhjmps0WlPNLMNNghPijkSSSSlSRjiPPiQQQjRRkSWt5.HHH", +"iijmp0w6yxwvutZYponTlRkSmnooUSjPhhhggPUZ499z4uZXnljPkW1yC#EaFbaED.9BB88Ay420YWmkPOkVYuvZoSPhhOPiQklmnooWpppVUlkRjjQiQQQjRVsxCGHH", +"jjRUX0w6yy5x4vu0rqpVmSlUWY00rpVTSRiPhQV05.9y2rVmTSkRUYvzDEEaaaD9A6xxxxx5wv10rpnlQPTp0452ZWTkkSllmnWqrs0t1u1sqWUTSRQPPPPPPmrwBbGG", +"RRSnX03y66z665wv1sYpVTmWZu45wu0YpnlRPRW1yDCxtokjRklmWt48EaaEE#97xvtt11u2u1t0ZqVTjQnYv685v0qWWoWopYs123456z6wusXomSQOOOhhhSXvAFbb", +"SSlVq03y67A8B76x3u0YpUnYu5B.Bz531roTjkpuzEC4rlhhiRmorv6CaFaE#.7xurWpXYrZsss0sYWUkRo0xBDB64ut0ssZsuvx67BCDaD8yv0qVlQhhggggjou7aFF", +"TTmWYt3y6A9CD98z5wusqVo04BFHb#CA52YVklqv7aC3XQNNORnY1xADbba#D9yvrVlTUVopqrZt0rpnSSXuzDbECAyxww32vx68C#aGcdca96vspTjhgNNNNPnt6Eaa", +"YYr01v4y678B9A6xv10ZYpqu59bHbE.86vZWlmr3Aa.wYkghQmq1w6B#bF#.9Ax2rWmnWqZ0t1uv2tZXVVZ3AEGECA54w3v2vxzB.EFGHdH#8y20qVlQPOhgNin0yDDD", +"xx5555y6y6zzzxvtZqYYYYsvyBabaD9AyvspmnZwAE.xsUijUXt468C#aE.B7yw2sYpY024yy55543u0YYu58EbD86w2uuu12468.#EaaF#B6w1sYpoUlkiPhjo0x9CC", +"###D9876yy54wusXVUoprs246BDED98z5vsXVWs4AE.6uXTUqt47BC.#EDB7y43210su4z9#DCBAzy4vu14z9EF.7xu000001wy8.DDD..B642sZZrrYpnljPSW04888", +"eeedbDBz5xw21rWmRQTor14yz8C.9876xv0YWXt4A#.7wspY147.#####CAy422222v58EHdcGaDBAzyx468CEa963srrrZZtvyA.DC9A7yw2trZstu2tYVTjTp0w777", +"KKKJeG.z5wu0YoTQhgjnrv6778BBA7654v0rXY1x8#D85v0uxA.bGFa#DB64vt1v34yBadIJIecbD.9B8ABCDEE8xuYpXqqYs25A..BAy4v10ZXrt2x641YVSUX03yyy", +"KKKJebBxvtrXVlQhNNPTqu5y67887765xwutst3z9aEC75347CEHHbFEDB6xvt2w57BEHeIJJedGE#DDD.D##E#AxurXYrs0uw68..9A6xw2u1s1v4y752ZWmVY14zzz", +"KKKJdD61ZXVmkQOgNMhkVZ2wx6A877zyyxw3vw6B#GbE97568DaHHbFED9z5w2wyA.aGcdIIedHbEEEaFFFaEEDA5v0stuvw5z8C#DCBAzy55x4x5y6zx2ZpnWs2y888", +"KKKJHB3qomkQOhNNLLgQTps135zA777zz66yyzB#GdcGECA8CEbHHbFE#CA6x358DbcddddddHGaEFbHccHba#CA642u3x67B9.#EED.9B888BBBA7zy4usqoqtw7CCC", +"KKKIbz0UkQOgNMLLLLNORUpZ146A7777AA88BCEGdeecGEC.#FGHHbFE#C8zyx7.bdIIedcHGFFEEbHdeedHFD9Az54wy79#aaaFFaE#D..DEFFa.Bz5wu0Ypr25B#EE", +"KKKIE4XjOgNLLLLLLLMgPkUpsvyAA7AAB9.DEFHdeIIedHaaFGHHHbFE#.BAzyBadIJJIdGE####EGceIJIdbDBA7zy68.FHdHHGbFFaaaFGcdedF.7x3u0rq03z.Fbb", +"KKJdC3WQhNMLLLLLLLNgPjlWswz99999.DEaFGcdeIIecGEEaFbbFaED.9876y8#HeIIdFDB9CD#aGHdeIdHECAA77z7CEGddcGFE#EEaFbHdIIeHD74v10rqt48EHHH", +"IIebA2pkPhNLLLLMNghPijlp159EEEEEaaFFFGHddIedGEC9.D##D.C9BAzy5x68.Eba.B7y78.#FbbbbbaD9Az7777ACEGcdGE.8ABCDEbHdIJIHD7w2tsrqtxBFddd", +"GGbCy1qmRPgMLMNghPiQjRlq27EHHHHHHGGbFbHcdddGEC77A8B9B8A7zy54w34xy676543vx7CEGa#.B8A7z6y6z7AB.EbHHaC7xx6AC#FHeIJIHDzv10ZYq1yCHeII", +"BBB6wtYVlihNLNgPjSkkRRlYw9HedddddcHGFFGHcdHaCA5xy6z77z65x4w3v22u1ttt0ss0vy9aHE9z4v3w4x5yz789DEbHGDAxu1w68DFHeIJIHD62tsZYqu6DcIII", +"44wvusrpURONMgPRTVUmSRlrx#dJIIIIedcHFFbGHHbDAy3vw4x55x43v22uu10rpVUnVVoXtxBaH#7wsqr01v45z7BCDEbHF9yuYY147CFHeIJIHD6u0ZrYquzEdJJJ", +"222uuttZpmQhNOjToqWVmSmZyEeJJJIIedHF#D#EEF#9z42uv3w443vu1t1tt0rpmkijkSmVZwAEH.y1XnWY02w5zA9.D#EaD7wsWp03zCaHeIJIH.y1srrYY27EdJJJ", +"333wwww30pmQOjTVqZqpoUV06EdIIIedcb#97z78B9B7y4vvww4x43utsss0t0YoSihOiRlUY2z.FBx0omoY0vx6AB.D.9BA6w1rWp03zCaHdIJIb9xtZrrrZv7EdJJJ", +"xxxy6z77w0pljlVqs1srXop16#dIeddHFD8y3vwx5665x4ww4x554v1ZqYrZ00qnjhNgOikmX15BD73ZnlVY035z8C#D97yw2tZqWX03zCaHdeIda8wsZrZZ03AEdIJJ", +"yy67BCD#A3somVXs1v10ZqY2zDcedHGFDA52Zrstuv3www4x55y6x20YWpqrs0XmPNLMgOjlW0w79yuqmknqtw6A9Da#ByvZqXXWoqtwzCaGHdecD7vZrrs0148EdIII", +"77A9DFHH#zvrWqsu34vutZs37DHdHbE.8x2roVWXYstuvw55y6zzx2spnVpqs0plhMfLNgiSoZ2yA40plRUqt4z8C#FEAwZVmUnVoqtwzCabHcdGC62YYrstux8EcIII", +"88B.aGdda84sXZtv45wvu0t3zCFGa#C8yvspmTUopYs13xz7777z52ZpUVWqs0WkgLfLMgiSorux63ZokQmXt47BC#F#72XSjkTUVqtw69#abHcFB51qqrstu4ADHddd", +"99C.#abbCy2YWqsuwx321ss2xzC.98zy4usXnnopqZ1w68##.B8z5v0YWpXYZsoRgLfLNhknX02xy2YnjPlWs367BC#Cy1pSjRlTUpZ2xAC#EbHa8xtXXqrZ0vy8#GGG", +"......DCz3sWnprtv4vu0rrt246z654w2tZqWWXYZt369acHFD9z53usYYrrZZVjNLfLNPmXZ1vxx1XmiOkVr2x678984sokQRSlTVYt368CDab#A4tXpXXYrt3yBDDD", +"DD#.CB8zwtqnTVq02w21sYqZ0u3w3vu10sZYqYrst2xBadIIdFCz5wv10ssZZrnQNLfLgjos12344tplPhjUq1wxyzA6vrVkQjkklUXZu468C#FD7w0pWWWpXZ13yAAA", +"EEE.Bz5wtYolkmpZuvu0ZqpqYZ00ssZrYrrrrs0123z#cIKJIHDz5xwvu1t0ZYUiNffLhSqv3ww4wsokhgiTp0v345yxuqnRiQjRkToY0vxz8.E.6vsWVoVVoXZt3xxx", +"###C7xv0YWmRQloYtutZqWVWWpXqqqXXXYrZst123w7adJKKIH.y4w3v21tsrqmiNLfLOms444wwvrnjgNPlp0v3w4xwtXUkQjRRkToXZuwyA9D9y2ZonnUUnWqZ1vvv", +"777ywu0qomkPPRmWrsrXoUTUnopXXXXXXYrZstt1u25CGIJJdD6u0sZrYqXppolPNLfNQn04w32utXmQgNiUrvyyyyyxurWmSlTmUVXr0uw579D9y2ZonnUUUWqs2444", +"33320rXVmkihhiSUpqpVTkjSTnWXXXXqqYrZs0000037DHIdEz2qWVnUmmmmUmkPhNLhkWt43v10roSPNNjotyB8A7z530qoUVoWXqZ012w579.B5urVUUUUUWYt3555", +"ZZZYpVUlRiOgNhQlnonljPOjSmopXXqqYrZss0sZZrtxA#HaAvYmkRQiPiQjkSjPOggimX14vusYpmRONNRpv8EDC9A642sqpqYrs0t12vw57B.B5urVUUmmUWru4zzz", +"VVVUmSkQPhgMMgPjlmSjPggPjlVpXXqYrrZsssZYqprux8D8wrUihgNNNNghPQiPPPPkVYu42trpnSQhNNkYx#HbED975w1srstuvvvv33w57BC8x1YnmmmmUWZ25AAA", +"kkkRjiPOhNNLLNhPRSjPgNMhikUWpXXqYYrZZrYXWVps25Ax0VjgMLLLLLMNhPiijRkUpZ2wusXnljPhNNls6becbECA6xv1tuv455x443w5z8B74tqnmTTTmWZvyBBB", +"QQQQQiiPOgNMMNhiRSjPhNNhPRTnnUUUUUnVVoVVVUWr1w6wZnjgNMLLLLNhQkSlTTmVqs23troTRQPhghUt7bdHFDBz5wut02wy7765xw34x5yx2ZXUmTTlTVYuxAAA", +"PPPiiiQQPhgNNgOQklRiOgNhPjSTSkRjQQjRRklTmmoYtv5vrnjhNNMLLMhilVVVVVVpYsu2sXUkiPPPhiouAbdHEC75wvtss2xz99A65wvvvvv1sqWUmTlSSUXtw666", +"hhOPiQjRQPhgNhPjSTkQPhghPQRkQPOgggghhOiRlToqsuwuYnRhgNMMLNPkVYYqqXXqZ011rWlQOPPPikXv8bdG#B64v1srZ258##97yw2ut0ZYqWoUmlSkRTWZ2555", +"gghOPQRSRiOhghPRlmSjiOhOPiQQOgNLLLLLLNgPRlVXZtvtqnROggNMMgjUY11t0ZZZs0t0qnRPghPQRmrwBbcb.Axv10rqr26CbbD86wu0rXoVVnnUmlkRQSVY1www", +"gggOPjSTSjPhgOikTUlRQPOPPPPPgMLffffffLNhQlVpr0u0qnkPhhgNNhSW0wwv21t0000ZpmQhNhPjlo04BbHa963u0ZqpY26.HHEBy3trpUlSTTmUmSRQPRUps222", +"iiQklUoWnljPhPjSmnTSRiPPPQQQOgNLLLLLLMgPRTVprt21sXVmkjPhgPSoZ2v22uu1t0sYVlPgMgOikUYuyC#9z4u0rqpopsvy9B6wtrpnTRiijkSTlRQPOikmWYYY", +"mmUopYZsqnSQPiRlUVmlkQiQQRkkQPhgNNggghPjlmoXZ1vvu0ZYWUkihiSnqst1u2vutsrXUkONMNhPQlWZv67y420rXponVprtv2sqVlRQPhggPijkRiPhghPjSUmm", +"YYrstuv30XURPjSmnoUTSjQjRSlTSkRQiiQQQRSlmnWqsu3www3vtYVkPQSmoXr01vw2tZqWTjhNLNghPRUps2wv1srXWonmmUnoWVTRPhgNNMMMghPQiOhgNNghPiPP", +"vv3wxy6z3ZoSQRlUVWnmlRjkSTUnnUUUmmUUUnnnVVpY02w5yz7AxuYURRSTUnprt34vtrXnSigMLMNghPkUprsZrqpWnUTSkRjQiPgNMLLLLLLLMNhPPhgNMMMNNNNN", +"zz7A89CCy1qTjkTnopVUTkRSTUVWWpXqqqqqqqXpWoprtv46A9Da95tplkSSllVqtw531rWmRPgMLLMNgOQkmVWWWVVnmTSRjPgNMLLfffffffffLMghhNNMLLLLLLLL", +"666z7A88xtqmkSTUnVmlkQijklmnWXr00ssZrYXoVUVq024z8.EbD62qmTTmUnX0vy7xuroljOgMLMNhPikTVpqpWVnUmUmmlQhNLLfffffffffLMNhPPhhNNNMMMMLL", +"44xxx5y5vsXUlllTTTkjiOhOPQRlVXs2vutsrqWnTSTWZu4zBDaG#zvYUUVWXYtvy8CzvZoSQOgNMNhPRlnWqZ0rXoUmUoWXWlPgLLfffffffLLNgOQkkjQPPOhhhhgg", +"vvvvv3vvtrpnmllSkRiPhgNghOPjUXt4x3u0rXVTkQRnY147BDFHE73rnVpY01wy8.E8wsVkiOgNNgPRTVXrt220YomTnpY0ZnRhLfffffffLLNhPRlUUmTSSkRRjjQQ", +"111ttt0srXWVUTSRQPhgNMMMNNgPTXu67x3trpnSQOPTXt479#bHaAwZopYtvxzB#FGCx0VjPOgNNhQToY0u3xxuZWTlVYt32XlhLfffffffLNOjSmVppWWooVnnUUmm", +"ZZZZrYqXpWWoVTSQPhgNMLLLLMNhSqv89z4uZWmRPghkW0479#bcF84sWq0vy8.EGcdEy0VQPOgggPSVYtv4y77w0WTlosvzysUPLffffffLMhRmnWqZZZZZZZrrYYqq", +"XXqXppWWWpXqXVmkQPhgNMMNghOjotyDF.8ywtqnkPPlWZvyACEGEAxtqs2yB#bHddeFztVQiPOhhjmXt3x67BBxuqnUXtw7ysUPLffffffLNPknWY02vvvv3v2utt00", +"VVoooooopqrssqWUSRQiPhOPRlnX1yCHdHbE.A40pllnprt357CE.7xusux8EHddeIIb7uoRQiPPiloZv5zABCC63spWr1w6xZmhLfffffLMgPknXsv5y6zz765x3v22", +"TTmmUnVoXr0u20rpnTllSkSUWYt3z.GeIIIedH.yuXWpXqrtv579Bz5vu47DHeIIIIIGA2WkRjjjRnq1x789CD.7xurY0uwy4YThLfLLLLMghiknqux89C.D#.BAyx44", +"RRkSlmUVXs1wxv1ZpooVVVWr1wz9aceJJJKKKJd#zuZrqXWY0v577y5436CGeJJJJJIHBvpSkSSSTWs3z9..#E#By3101vw53qSgLfLLMNghPQknr37#FGHHcGa.87zz", +"PPijklmVqtvy7ywuZYYYrZ03z9FceIJKKKKKKKJdEyvtYWUVq0vxy5555BadJKKKJJJc93XllTTmnYu5B#EEFFa.7532v3wx2pkgLfLMNhPiQjknsxCHdeIIIedbD9BB", +"PPiRSUVXs2x78z42srZs01v58#HdIJJKKKKKKKKea6v0XnklVq0u3wx5y9FdIJJJJJIHB3qmmnVWXtw7.FbbGbFDAy3233wx2pSgLLLgORSlSlTWty.HdeIIJIdGD8AA", +"jjRTnprtvx68Bz4uZqZs1v468.FHdIJJKKKKKKJd.4tYVSiQSnpr0u34y8#HeIIIeedE7vYnopqr0369aHHHHHbDA5212vwxvqlhLLNORUoooooY2yCbcdIIJecEB655", +"SSlnXZuw5zA9C741rXr02w5z8C#FHdIJJKKKKKIG8vrolihhikmoqsu35ACaHddcHGF9yurWXr0u3y8#GcccccH#741012w53YmPMMhjUqrrrrr036BEGceIIeG.zwvv", +"TTUpZ2x789C..741Yprtv5z789.#FHdIJJJKKJeE6tpmjhNNgPjSnq0v57B.EFaE#.9741rXrt246BDbcdddddH#7w0Zt2w5wrniNNPTX122uu12xz8.aHdeIdFBx100", +"nnoruxAD####D74tqortw6A888B9DFHdIIJJJJcC4rnkPNLLMNhPkoru5678B9B8A76xvtZY0vx79#Fcdeeeedc#73ZYsuw54sojghRo04y5xx44yzABDbceIdE7vrqq", +"ppX0369aE#D.963sXor1xA9B8A77BDaHddIIJeb83qUjhMLLLMghjnYuxy6666y5x43v10ssu47CEGHdeIeeddG.6vZqs1vxwsokhPmYvz8Az6556z7ACaHdIH.y1XWW", +"rrZu469#.987y31rpWZ2y9D98z55zB.aGHdeIdE7vqURPNLLMNghjnYux55x4w3vu1tt000t369aHddeIIedHFD85v0rstuvuroliRo0xBCBA6556z7A9#bHdbBx0WVV", +"tt1vxzB.B75w2tZqpWs3zDEC8y3vxz8.EFHHdG.62qnkPgMLNNgOjnYux54321tsZYqrZst2x8#HeeIIIIdHaCA64vtss00tsqomkmq2zD#C8z55y6z7B.EbH#73Zonn", +"vv34y7897xvtrqqpWpt48abDAxut2468CDEFGEB5uqVlihNMNghPRnYuxx3u0rYXWoVpYZ136CGeIJIIIIdbC7xwv21t0sZrYponmo04BFF#B75x5y6zA9DEFCy2YVUU", +"xx5yz7885v0qVVoooX159GH#AwsY0246ABC.#Cz41qVTjhNNghhPRnYux420YponmllnXZux8EdIJJJJJIcEA4uuu2210ZqpWWoooY26DHHaC75x5y6z7B9CD84tXUTT", +"66z6z77zwtqVlTnVWY26.Hc#A3rXr02w5yz78zxv0qomRPhghhhPRUq1431sXonmlkkUpr14A#cIJJJJIIHDz3t1122u0ZXoVoWWpZvz#cHEB6w3w4x5yz7A8yvZWmll", +"zzz666652ZpmkTVpY0w7DHH#73ZXYrs01u22v21srXoUljPPPOhhilWZuutsrqXWVUUVpqZ1wzCbddddedGDA53vvv2u0ZqpWWWWWYu5Cba9630s0t1u23w4xv0Xnlkk", +"zz76y5xwtYVSjTVqsv58#HH#7wsqqqXXXqqqqqqXXXWVUlkQiPhgPkUXs000ssZrqpppppXqsvx7CDEFHHFDBzyxw3210ZYqXpWoVX04A#.z3spopXqYrs01u0qoTkRR", +"7776543uZpmRQlorux79EHHD7w0qXWnmTTlllTUnopWoVUmSjPhghQlVXrs0tuutsZrqpWVnWYsuwy79#aEDCBA6xwu10srYqXWonWZv69A40pTSTmUnVWpqYXomSRQQ", +"AAA6x320qVliPlW0wzB.aHGD741YWnSQPPOOhPjSUWpWpWoUSihNgPjTVXrt2ww32u1ZpVTRSmnoX0vyB.DDDD.864ut0ssZrqWVUVq147y1qTiPiQjRSlmUnUTkjQii", +"zzzywu0YWUkiPTptxA9.EFaCz41roTQhgNNMMNhQlopXqqqomjhNgPQSUpr1v5x432urWmjPPQjRlWZ2y89CD##B6wtsZZZrrXWVmVqtw6x0WSOhOPPiQjklTlkjQiPP", +"www2tZqWVmlkknXtwyz78997531roligNNMMLNhQlopXqYrXVTRPQkmVpYs1v43u0rqVljOghPijSnX0vx6z8BBz4uZqXpWooVVVnpZ258zvZVkjRkSlTmUnnUlkQPPP", +"000rqWVUmmmmUWY02w4x5yy4321ZoSPNMMLLLMgiSVpXYrZrXonTUVpYZ0tu2v1ZXVTRPhNNNhPiRmoqs1vw5664usXonmTSSTUVWY147.952rVUnVooWWpXpoUSjPPP", +"ppponmlSlmnoXYZ01u2u2u2u111ZokONLLLLLMgPSVpqrZ0sZrqXqrs1u2uuuuZpURPhgNMLMghPjSmVpYstvw4usqVmSRQPPRTVXs369a#85urYYrrrZZZZrXVTRPPP", +"TTTSkjQikmoYssss0ssrrYrrs01soRhLLLLLLLNPknpqZs111111u23w4w321tqURhNMLLLLLNgPQRSTUnpYs1usXVTRQOhNgPSVYuxA#HGDA52uu22222uutZWUkPPP", +"QQQiPPOOQTWZ1tsZrqqpWoWXr0utWkOMLLLLLLgPSoqZtu3ww4xx55yyyx3u0rokONLLffffLLNhPiQjRkmVqZsqoTRPhgNLMhkos3zCbdcF.A5555555x4wvtqVSiPP", +"PPPPOOhOQSUXrYqXpWppXXYs13x40WlPggNNNhjmp0246A999BB87654v1sYpoligLLffffffLLNghhOPiSUprsXnlQOgNMLMOlXu58#HddG#9z66zz77z6yxvZWTjii", +"hhOOhOhOiRlnooVnnnWpYrt2468A4tXmkRjQiRnYux7CEGdcHGF#9z4uZqWnTSihNLffffffffLLMNNNghjTWrsXUkPgNNMLMPUZ4A.aHedHaCAAA8BBB88A741qURjj", +"gghhhhhOPQjSlllllTVXZtv579##852ZXWonUoZv6CaceIJJIIdH#AwsWUlRiPhNLLfffffffffLLLLMMNPSor0XmRONNMLLMiVt6CEGdeeHFDBBBC.DD..C96vrVSRR", +"NNggghhOPPPPiQQjjknX0v5A.aHHaC742u0ZYsw7DHeJKKKKKJJeb8vqljPhgNMLLfffffffffffffLLLMhRVr0XTQhNMMLLNjW28EbcdIecGECC.#EaaaaE#840WTSS", +"NNNNghOPPPOOOPPiQknYuxA.Fceedb#Bzy4vu37DHIJKKKKKKKKJcB2oihgNLLLLffffffffffffffffLLhRVs1qmQgMMMLLNkqw.GHdeIedHaDD#abGGGbbF95tpmll", +"MMMNghPijRSlTmnVopsvyBDFHdeecFD86x310uyCHIJKKKKKKKKJcBuVPgNMLLLffffffffffffLLMNNhPSWs3xuYVkiOhgNhmZ5DHcdeIedGECC.#abFa#DC6vYnRQQ", +"LLLMNhiRTnpYs01u23yA.FHccdddG#97531ZqZw8FeJKKKKKKKKJcBuVPgNMLLfffffffffffLMgOiRlUWruxAB63tqomSjPjW16#HcdeIecbD88B.#a#.BA6vZVkOhh", +"LLLLNOQloY1wyz7A8C#bHdeeddcHa.8ywuZXVpu6#dJKKKKKKKKJH8uVPgNMLLfffffffffLLNPkUWqZtv5ACaFD86w1ZXnlmYv7EHdeIIecaCzzAB.#.86xvZoSPNNN", +"fffLNORUquy9abGHHdeIIJJIedHFDBzxv0qVlnsx.cIKKKKKKKKJH8uVPgNLLfffffffffLLNiTp0246ACEbHddcb#C7xurWptx8aHdeIIeHEByy6A9.B6w1rolPNLLL", +"fffLNPSW05CHeIIJJJJJKKKJIdG#9AywuroTjlq3BHIJKKKKKKKJH82oigNLLffffffffLLNPTXuy8.aHdeIIJJIIdcbC6vZZv69FHdeIIeH#A445zA9741YoligLfff", +"fffLgjVswAEdIIJJJJJKKKJJeHaCA6420YWUkmr38FeJKKKKKKKIGA2WQhgNMLLffffffLNhRoswA.FceIJJJJJJIIdH#7wssv6CbcdeIIeHD7w3wx56xuZpUkPgMLLL", +"fffMPmrwz.GdIIJJJJJJJJJIdb#BzxvtZqpVUoswAEdJKKKKKKJIbA2pRPPOhgNLLfffLNhjUqu59EHeIJJJJKKJJIIdEAwsZv6CbcdeIIeG.z3222vvuZXomkihNLLL", +"fffNjW2A.FceIIJJJJJJJJIdHaCA5w1ZYqXpWqt47.GIJKKKKKJeFAvXSRRjjQONLffLMhQTp0w7.bdIJKKKKKKJJJIda8wZZv6CGddeIIebC6v1t0sZYpoUTkQOgNNN", +"fffglZ6EGcdIIIJJJJJIIIdHFDB642sqpXqqYs2xz9adJKKKKJJeaAvqTlTmmmRONLfLgilWZvyBEHeJKKKKKKKKJJJebBwZrv6CGddeIIdF9y2tZYpoVUmTSkjPOhgg", +"ffLhnuCdeeIIIIJJJJIIedHFD975vtYWoXYZ0u3x6ADcIKKKKJIdEAvYUUoWXqnjhMLMOkVZuxA.bdIJKKKKKKKKKJJIGBwZrv6CGddeIIdF9y2sqWUSSSkkkkjQiPPP", +"LLLQX4EeIIIIIIeeddcHHbaD9A6xvtrpWqrstv4y79adJKKKKJId#Aw0pXr0uvZVkhNhjUXt3y8DbdIJKKKKKKKJJIIdE7vYq26CGddeeIdF96v0qoTRRkkSSSRjQiPP", +"NNhT0zGIIIIeedHFED...C987zy4v1ZqXYZ0tvxzB#GeJKKKKJeH#B52Z0246Ax0pSPRmpru4zB#bdeJJKJJJJIeddHaBxtpX1yCGddeeedFCzw1rWTjjkSlTTSRQiPP", +"iiRpv9cJIIeedb#B6x55yy6y55x4vusrYZs0t35ADbdIJKKKKJeH#9z4u36B#FC51XmVpZtvx79EbcdIIJIIedcGFEDBy2ZoWt5CGdddeedb.AxuZWTQjklmUmlkjiPP", +"mmn0y#eJJIedH#A41Zstu2333w4wvutsss0tt369aceJJKKKJIdG#CA64zCFdIH.6uYrs12wyACEbHddeIdcHFE.9875v0Xno05CGddddedbD8yvspTQQklUonTkjiPP", +"qqr3BGIJJIecFB40omnWXr0tu23wv21tttttt3z.GeIJKKKKJIdb#.987CbeJKIcD6vvvwwxz8.abHHcccGaD9A6543usqoTnsx9Gddddddb#9zw0pTiQkTVpomSjiPP", +"tt15CHIJJedG#72qmRlUVprs1v4x4321tt00026CHeJJJKKKJeH#CBA769beJKJd#62uuuu2468.EaFGHHa#C87yxwv1Zqomnrv7DbGHHHHbE.ByuYUjjlmopWnTSRjj", +"vvwz.HeJIdHaCy1XTjSTnWqs2467yxvut0sZrt59GeIJJKKJIdaB76x43z#dIKIHBwZYYYqY02x7B.#abHa#.9Azyx4vtrpnVqtwy89.#FFFaED840WSSTUopWVnUmTT", +"55y8#GdIdHFD840WSQRlmVXsvy89Ayw2tsrqXZw8FeIJJJKJeG.64321049HIJIaztWVnUmUWr1wyA9#FGaEDCBA7654u0qoopYstvxz8.#EFFb.62qmTUnoWpWWWWWW", +"AA8CEGddcFDB6vZokijkTUWsw7DE97x2tZYpoqv7adIIJJJId#AwutZYquzaeJdDxYTkRjiiSnqt35ACEbaa#DCB87zy31rpoooWWq0v5AC#FHdF84sonVVoWpXqrrrr", +"CC.#aGHcb#97xuqnRPQRSTos48FG#8yvtrXoUWu6EdIIIIJeG9y1ZYpVnZxDdJdB2oiPhgNNORUX03yB#baaE#D.98Az420YWnmlRlWZ2y8DbcecD6uXoWooWpYZt111", +"EEaFbHHHFDBz4urWlRSlmnp1y.HdF9y2sqomSmZx.ceeIIIdEAwsqWnTSp28beb71ViPhhggOjToY14zCE#E#DDC98Az42sqoUlkQSVr2yBEHeJebB40rrYYYrstu222", +"bbGGHccdG#9753trpVoWXqsw8adeG9y1YomRPRpu7FHHccdbC6vZXVmkQUZxCG.y1WSkRRjRkTUoXs2x7B9CCCCBAzyx20qonUmmTVYux8#GdIJJdE84vv22uuuuu111", +"HHHccdddHECAy4vu0Zss0t26DHIIHC5tpUkPgOmZx.aaFFFD852ZpnSQPkp1yC74tXnnnVVoVVVoWY0vx67A8BBAz54v0YWUTmUVoqt47DbdIJKJIcE87z66yxwvut00", +"ddddddedHFD86y5xw333ww5BbdJJc.xsVSPgMNjp2ACCCCC86w1rWmROgPmq25420rXqYZs0rqponpY02wxyzAAz5w2tYWUSSTnpYtwzCbdIJKKKJIcF##D.9Aywu0ZZ", +"eeeeeeeedb#B7777777z7zAEdIJJd.xrmjhMLLOUsxz7777y420YoligNgjUY11t0sstu34x20qomVpYs1v45z7yw2tZpnljjTortw69FdIJKKKKKJIddcHHbDAxuZrr", +"eeeeeIIedb#B77AA88A77zA#cIJJdC4qTQgMLLhTYw5555542trXnkPgMgPlors0t1u3x6A8yvsXnopqZs1vw5542trqoUlRknXt368#HdIJKKKKKKJIedddHaByvsZZ", +"ddddddedHa.Ayy555x4w3vwzDGeea7vqmRPgMNinZw5xxx4v1ZXVmRPhNhQTorstuv4yz8C.Ay31rZs0001u2vvu0ZqXWooVWYt3yACEHdIJKKKKKJIeddHHb#Bz42uu", +"HHHHcdddG#9zxw3vu1tsZrZv69Fb95uqnlQPgOkWsw5x4wwusqVmSjiOhPRmoYs13x6AB.#E.Bzx3322u111tt0ZYXWppqYZ024yACDFHdIJJKKKKJIdcHba#.B76x44", +"aaFbGHcHF.8y321srqXoVUVYuxABy30qVmSRiRUqtwx4w3vtrWmkjQQPPjSUoqs24z8C#abGFE.B7z543u10ZYqpWoVoqs13x67BC#abHdeIJKKKJIecGbEDC9B8A7zz", +"DD#EabHHaC7x2trXoUmSRQjmX034vtZqWVUmlmWr1wxw322sXVSiPiQQjkTnoqsvy8DabHcdcHGFE.8zxv1sYWVnUUmVY1479CD#aFbHHcdIJJKJJIdHFED988BB9999", +"AA89.#FFDB64usYWnTSQPOPknqt2utsZYqXXXqs13x5w3u1rWURPPijRSTmnoXsv69abHcddddcHGECA5vtZXnUTTTTVr2yCEaFbGHHHHHdeIJJJIecbE#CBA89.#EEE", +"vv3x6AC.97y4v10rXWnlRiiTWsvxxx44wwwwwwxyzA75w1sqWnljjRkSlTmnVWZv6CabGHHcHHGba.8642tZqWVnUUmVr2y9#abGHHHHHGHcdeeedHGE##D..DEFGHHH", +"qqYs24zA76543vu10sqVTkRnYu5AA89CCCC.....DD96wtrponmllllllTmUnor26CFbGGGGbFE#.Bz53utsrXpoVnUVr2y9#abHccHHGFbbbGGbFaED#EEaFGHcdddd", +"SSTVqtw555x444ww3vtqoTlW0w7.#aGHdddddddHHG#A40XooVnnUUmmTTmUUnY26CFbbFFaE#.CB754210sZrYXWonor25BDabHddHGbaEDD.CCCCCCDEbHcdeeIIII", +"hhOjmX0vww44x5yyz6w0qVUYuyCFHdIJJJJJKJJIedbBxsWnVoWWWVnUmTmmmUqu6CbbFa#D.98Azy4v1000sssYXWVor258.abcddHGa#.BAzy6z788.aHdeIIJJJJJ", +"LLMhjnruvwx56zA8996vspos37DHdIJKKKKKKKKJJIHCxZVUVWXYqponmTTTTTXt59FFEDCB876yxw210ss0011sYXWpsvyBDaGcddHF#C8z54v34yzA.aHeIJJJJKKK", +"LLMhkW0wxyzAB9..#DA41YXsvyBEHeJKKKKKKKKJIda8wZVnWXr0ZqonlSSkkkVrv6998765432100ZZYrZ0t1ut0sYZ258#FGHcdHaDBzyxw3v3xy78.aHdIIIJJJJJ", +"LLMOlX2y78C.#EaaFa9630Y02469adIJKKKKKKJIdb.6vrVVpr0u0YWUSRjjQQTW036yxw210ZqpWWWppXYstuv2uu12xADGHHHHHF.Ay3vvvvvw56AB.EbHdeeIIIII", +"LLMPmrw89DaFGHHHHGDAxustuvw6CGeJKKKKKJIdGDAxuYVoqsuwuZWmRQiPPPRUX0v210rqpVmlklTUnWqZt23wwww5ADbdedcHb#85vss01234yz89.EFGHcddeeee", +"LLMPn0y.EbHdddddddF96311111wAadJJJJJJJeH#8y3tqVWrt3530pTQPPhhgPknpZYXWnmlRPOhPQkTVprtv4x5y6A.bdIIedGa96vsppYsu3x67BC.#EFbGHHcddd", +"LLMPV17aGcdeIIIIedGDAx2110Z1yDcJJJJJJIda96wusqVWZu4z4tpTiOhggNhiSUWVUTkjPhNMMNhikUWrtvxyzA8.FdIJJIdG#A4tXmUpr13x67BC.##EEaFbGHHH", +"LLMPV17aGcdeIIIIedGDAx21tsrt5.HIJJJJJIcEBy31ZXVWZu4z4tplPhhgNNhPkmonmlRQPhNMLNhPRmoYtvxyzA8.FdIJJIdbD7w0pTmWYt3x67BC.DD##EaFbGGG", +"LLMPV17aGcdeIIIIedGDAx21tsrt5.HIJJJJJIcEBy31ZXVWZu4z4tplPhhgNNhPkmonmlRQPhNMLNhPRmoYtvxyzA8.FdIJJIdbD7w0pTmWYt3x67BC.DD##EaFbGGG" +}; diff --git a/hacks/images/som.xbm b/hacks/images/som.xbm new file mode 100644 index 00000000..cd24fd01 --- /dev/null +++ b/hacks/images/som.xbm @@ -0,0 +1,1685 @@ +#define som_width 464 +#define som_height 435 +static unsigned char som_bits[] = { + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x60, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x60,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xf0,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xf0,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0xf0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0xf8,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0xf8,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0xf8,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xfc,0x01, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xfc,0x01,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xfc,0x03,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xfc,0x07,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0xfe,0x07,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0xfe,0x07,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0xfe,0x07,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff, + 0x0f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0x0f,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0xff,0x0f,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0xff,0x1f,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x80,0xff,0x3f,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x80,0xff,0x3f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x80,0xff,0x3f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xc0, + 0xff,0x3f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xe0,0xff,0x7f, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xe0,0xff,0x7f,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xe0,0xff,0x7f,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0xe0,0xff,0xff,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0xf0,0xff,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0xf0,0xff,0xff,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0xf0,0xff,0xff,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xf0,0xff, + 0xff,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xf8,0xff,0xff,0x03, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xfc,0xff,0xff,0x03,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xfc,0xff,0xff,0x03,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0xfc,0xff,0xff,0x07,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0xfc,0xff,0xff,0x07,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0xfe,0xff,0xff,0x07,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xfe, + 0xff,0xff,0x0f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xfe,0xff,0xff, + 0x0f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xff,0x0f,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0xff,0xff,0xff,0x1f,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x80,0xff,0xff,0xff,0x1f,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x80,0xff,0xff,0xff,0x1f,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x80,0xff,0xff,0xff,0x1f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xc0, + 0xff,0xff,0xff,0x3f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xc0,0xff,0xff, + 0xff,0x7f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xc0,0xff,0xff,0xff,0x7f, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xc0,0xff,0xff,0xff,0x7f,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0xe0,0xff,0xff,0xff,0xff,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0xe0,0xff,0xff,0xff,0xff,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0xf0,0xff,0xff,0xff,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0xf0,0xff,0xff,0xff,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xf0,0xff, + 0xff,0xff,0xff,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xf0,0xff,0xff,0xff, + 0xff,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xf8,0xff,0xff,0xff,0xff,0x03, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xf8,0xff,0xff,0xff,0xff,0x03,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0xf8,0xff,0xff,0xff,0xff,0x03,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0xf8,0xff,0xff,0xff,0xff,0x07,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0xfc,0xff,0xdf,0xff,0xff,0x07,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xfe, + 0xff,0xdf,0xff,0xff,0x07,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xfe,0xff,0x8f, + 0xff,0xff,0x0f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xfe,0xff,0x0f,0xff,0xff, + 0x0f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xfe,0xff,0x0f,0xff,0xff,0x0f,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x07,0xff,0xff,0x1f,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0xff,0xff,0x07,0xff,0xff,0x1f,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x80,0xff,0xff,0x07,0xfe,0xff,0x1f,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xc0, + 0xff,0xff,0x03,0xfc,0xff,0x3f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xc0,0xff,0xff, + 0x03,0xfc,0xff,0x3f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xc0,0xff,0xff,0x03,0xfc, + 0xff,0x3f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xe0,0xff,0xff,0x01,0xf8,0xff,0x7f, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0xe0,0xff,0xff,0x01,0xf8,0xff,0x7f,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0xe0,0xff,0xff,0x00,0xf0,0x03,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0xe0,0xff,0xff,0x00,0xf0,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0xe0,0xff,0x1f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xf0,0xff, + 0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xf0,0x07,0x00,0x00, + 0x80,0xff,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xf8,0xff,0xff, + 0xff,0xff,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xf8,0xff,0xff,0xff,0xff, + 0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x80,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x03, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0xc0,0xff,0xff,0xff,0x03,0x00,0x00,0xe0,0xff,0x7f,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0xfc,0xff,0xff,0x00,0x00,0x00,0x00,0x00,0xe0,0xff,0x07,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xe0,0xff, + 0x7f,0xfe,0x00,0x00,0x00,0x00,0x00,0x00,0xfc,0x7f,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xfe,0xff,0x01,0xfe, + 0x01,0x00,0x00,0x00,0x00,0x00,0xc0,0xff,0x03,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xfe,0xff,0x01,0xfe,0x01,0x00, + 0x00,0x00,0x00,0x00,0xc0,0xff,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0xf0,0xff,0x07,0x00,0xce,0x07,0x00,0x00,0x00, + 0x00,0x00,0x00,0xfe,0x1f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0xfe,0x7f,0x00,0x00,0x87,0x1f,0x00,0x00,0x00,0x00,0x00, + 0x00,0xc0,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0xe0,0xff,0x07,0x00,0x80,0x03,0x3e,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0xfe,0x07,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xfc, + 0x3f,0x00,0x00,0x80,0x03,0xf8,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xe0,0x3f, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xfc,0x3f,0x00, + 0x00,0x80,0x03,0xf8,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xe0,0x3f,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0xff,0x07,0x00,0x00,0xc0, + 0x01,0xe0,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0x01,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xf0,0xff,0x7f,0x00,0x00,0xc0,0xfb,0xff, + 0x0f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xf0,0x0f,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0xfe,0xff,0xff,0x07,0x00,0xc0,0xff,0xff,0x3f,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x80,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x80,0xff,0xc0,0xff,0x7f,0x00,0xe0,0xff,0xff,0x7f,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0xfe,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x80,0xff,0xc0,0xff,0x7f,0x00,0xe0,0xff,0xff,0x7f,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0xfe,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xc0,0x1f, + 0x00,0xf8,0xff,0x0f,0xf0,0x0f,0xc0,0xff,0x01,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0xf0,0x0f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xe0,0x0f,0x00,0x00, + 0xff,0x7f,0xf0,0x01,0x00,0xf8,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xc0, + 0x3f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xf0,0x01,0x00,0x00,0x80,0xff, + 0x7b,0x00,0x00,0xe0,0x07,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xfe,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xf8,0x00,0x00,0x00,0x00,0xfc,0x3f,0x00, + 0x00,0x80,0x1f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xf0,0x03,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0xf8,0x00,0x00,0x00,0x00,0xfc,0x3f,0x00,0x00,0x80, + 0x1f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xf0,0x03,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x3c,0x00,0x00,0x00,0x00,0xe0,0x7f,0x00,0x00,0x00,0x7e,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xe0,0x0f,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x3e,0x00,0x00,0x00,0x00,0x00,0xff,0x03,0x00,0x00,0x70,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x80,0x3f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x0f, + 0x00,0x00,0x00,0x00,0x00,0xf0,0x1f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0xfc,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xc0,0x0f,0x00,0x00, + 0x00,0x00,0x00,0x00,0xfe,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0xf0,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xc0,0x07,0x00,0x00,0x00,0x00, + 0x00,0x00,0xf8,0x07,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0xe0,0x07,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xc0,0x07,0x00,0x00,0x00,0x00,0x00,0x00, + 0xf8,0x07,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xe0,0x07, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0xe0,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0xe0,0x3f, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x0f,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0xf0,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0xff,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3f,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0xf8,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xfc,0x07,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x7c,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xf8, + 0x00,0x00,0x00,0xfe,0x03,0x00,0x00,0x00,0xf0,0x0f,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0xf8,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xf8,0x00,0x00, + 0x00,0xfe,0x03,0x00,0x00,0x00,0xf0,0x0f,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0xf8,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xfc,0x00,0x00,0xf0,0xff, + 0x1f,0x00,0x00,0x00,0x80,0x7f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0xf0,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3f,0x00,0x00,0xfc,0xff,0x7f,0x00, + 0x00,0x00,0x00,0xfe,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0xc0,0x07,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x80,0x1f,0x00,0x00,0xff,0x47,0x7f,0x00,0x00,0x00, + 0x00,0xf8,0x0f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x0f, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0xf0,0x07,0x80,0xff,0xff,0x3f,0x7c,0x00,0x00,0x00,0x00,0xc0, + 0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3e,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0xf0,0x07,0x80,0xff,0xff,0x3f,0x7c,0x00,0x00,0x00,0x00,0xc0,0xff,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3e,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xfc, + 0x03,0xc0,0xff,0xfe,0xff,0x7d,0x00,0x00,0x00,0x00,0x80,0xff,0x01,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x7c,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xc0,0xff,0x00,0x40, + 0x00,0x00,0xfe,0x7f,0x00,0x00,0x00,0x00,0x80,0xff,0x07,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0xf0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xf0,0x3f,0x00,0x00,0x80,0x03, + 0xf8,0x3f,0x00,0x00,0x00,0x00,0x80,0xe7,0x1f,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0xf0,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xfe,0x0f,0x00,0x00,0xf0,0xff,0xff,0x1f, + 0x00,0x00,0x00,0x00,0x80,0xc7,0x7f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0xe0,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0xfe,0x0f,0x00,0x00,0xf0,0xff,0xff,0x1f,0x00,0x00, + 0x00,0x00,0x80,0xc7,0x7f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0xe0,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0xc0,0xff,0x03,0x00,0x00,0xf0,0xff,0xff,0x0f,0x00,0x00,0x00,0x00, + 0xc0,0x0f,0xff,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xc0,0x07, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0xf0,0x7f,0x00,0x00,0x00,0xc0,0xff,0xff,0x01,0x00,0x00,0x00,0x00,0xc0,0x0f, + 0xfc,0x07,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x0f,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0x0f, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xc0,0x0f,0xf0,0x0f, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x1f,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0xff,0x01,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xe0,0x1f,0x80,0x3f,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x1c,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xf8,0x0f,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xf0,0x1c,0x00,0xfe,0x03,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x78,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0xf8,0x0f,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0xf0,0x1c,0x00,0xfe,0x03,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x78,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0xfe,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x70,0x1c,0x00,0xf0,0x07,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0xf0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x3f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x70,0x38,0x00,0xc0,0x1f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0xe0,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80, + 0x0f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x70, + 0x78,0x00,0x00,0x7f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xc0,0x03, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xc0,0x03,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x70,0x70,0x00, + 0x00,0xfc,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xc0,0x07,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xc0,0x03,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x70,0x70,0x00,0x00,0xfc, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xc0,0x07,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xc0,0x01,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x38,0x70,0x00,0x00,0xfe,0x03,0xfe, + 0x7f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0f,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0xe0,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x38,0xf0,0x00,0x00,0xfe,0x0f,0xff,0xff,0x01, + 0x00,0x00,0x00,0x00,0x00,0x00,0x0f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0xe0,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x18,0xe0,0x00,0x80,0x9f,0xff,0x3f,0xfe,0x03,0x00,0x00, + 0x00,0x00,0x00,0x00,0x0f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0xe0,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x1c,0xe0,0x00,0x80,0x0f,0xff,0x07,0xc0,0x0f,0x00,0x00,0x00,0x00, + 0x00,0x00,0x1e,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0xe0,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x1c,0xe0,0x00,0x80,0x0f,0xff,0x07,0xc0,0x0f,0x00,0x00,0x00,0x00,0x00,0x00, + 0x1e,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xc0,0xf1, + 0x1f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0e,0xe0, + 0x00,0xc0,0x07,0xfc,0x01,0x00,0x1f,0x00,0x00,0x00,0x00,0x00,0x00,0x3e,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xc0,0xe1,0xff,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0e,0xe0,0x01,0xe0, + 0x03,0x60,0x00,0x00,0x38,0x00,0x00,0x00,0x00,0x00,0x00,0x3c,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xc0,0xc3,0xff,0x01,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x07,0xc0,0x01,0xf0,0x01,0x00, + 0xe0,0x03,0xf0,0x00,0x00,0x00,0x00,0x00,0x00,0x38,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x07,0xf0,0x03,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x07,0xc0,0x03,0xf8,0x00,0x00,0xf8,0x1f, + 0xe0,0x00,0x00,0x00,0x00,0x00,0x00,0x38,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x80,0x07,0xf0,0x03,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x07,0xc0,0x03,0xf8,0x00,0x00,0xf8,0x1f,0xe0,0x00, + 0x00,0x00,0x00,0x00,0x00,0x38,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x80,0x0f,0xc0,0x07,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x07,0x80,0x03,0x78,0x00,0x00,0xf8,0x7f,0xe0,0x01,0x00,0x00, + 0x00,0x00,0x00,0x78,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x0f,0x80,0x0f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x80,0x03,0x80,0x03,0x3e,0x00,0x00,0x78,0x7e,0xc0,0x03,0x00,0x00,0x00,0x00, + 0x00,0x78,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x1e,0x1c,0x0f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0xf3, + 0x9f,0x03,0x1f,0x00,0x00,0x00,0xf0,0x80,0x03,0x00,0x00,0x00,0x00,0x00,0x70, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x1e,0xfe, + 0x0f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xc0,0xff,0xff,0x07, + 0x0f,0x00,0x00,0x00,0xe0,0x00,0x07,0x00,0x00,0x00,0x00,0x00,0x70,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x1e,0xfe,0x0f,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xc0,0xff,0xff,0x07,0x0f,0x00, + 0x00,0x00,0xe0,0x00,0x07,0x00,0x00,0x00,0x00,0x00,0x70,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x7c,0xfc,0x0f,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xc0,0xff,0xff,0x87,0x07,0x00,0x00,0x00, + 0xe0,0x00,0x07,0x00,0x00,0x00,0x00,0x00,0x70,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x7c,0xf8,0x0f,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0xc0,0x3f,0xf4,0xc7,0x07,0x00,0x00,0x00,0xe0,0x00, + 0x07,0x00,0x00,0x00,0x00,0x00,0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0xf0,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0xe0,0x03,0x80,0xe7,0x01,0x00,0x00,0x00,0xe0,0x00,0x07,0x00, + 0x00,0x00,0x00,0x00,0xe0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0xf0,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0xe0,0x00,0x00,0xff,0x01,0x00,0x00,0x00,0xe0,0x80,0x07,0x00,0x00,0x00, + 0x00,0x00,0xe0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0xe0,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0xff,0x00,0x00,0x00,0x00,0xf8,0x80,0x03,0x00,0x00,0x00,0x00,0x00, + 0xe0,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xe0, + 0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0xff,0x00,0x00,0x00,0x00,0xf8,0x80,0x03,0x00,0x00,0x00,0x00,0x00,0xe0,0x01, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x07,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x7e,0x00, + 0x00,0x00,0x00,0x7c,0xc0,0x01,0x00,0x00,0x00,0x00,0x00,0xe0,0x01,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x1f,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3e,0x00,0x80,0x07, + 0xe0,0x3f,0xe0,0x01,0x00,0x00,0x00,0x00,0x00,0xc0,0x01,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x1f,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x1e,0x00,0xc0,0xff,0xff,0x0f, + 0xe0,0x00,0x00,0x00,0x00,0x00,0x00,0xc0,0x01,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x1e,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x1f,0x00,0xe0,0xff,0xff,0x03,0xe0,0x00, + 0x00,0x00,0x00,0x00,0x00,0xc0,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x1e,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x1f,0x00,0xe0,0xff,0xff,0x03,0xe0,0x00,0x00,0x00, + 0x00,0x00,0x00,0xc0,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0xf0,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0x3f,0x00,0x1e,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x80,0x07,0x00,0x80,0xff,0x7f,0x00,0xf8,0x01,0x00,0x00,0x00,0x00, + 0x00,0xc0,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0xf0,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0x03,0x1e,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0xc0,0x07,0x00,0x00,0x00,0x00,0x00,0xfc,0x07,0x00,0x00,0x00,0x00,0x00,0xc0, + 0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xe0,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x07,0x1e, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xe0,0x03, + 0x00,0x00,0x00,0x00,0x00,0xfe,0x0f,0x00,0x00,0x00,0x00,0x00,0xc0,0x01,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x0f,0x0f,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xf0,0x01,0x00,0x00, + 0x00,0x00,0x80,0xcf,0x3f,0x00,0x00,0xfe,0x01,0x00,0xc0,0x01,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x0f,0x0f,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xf0,0x01,0x00,0x00,0x00,0x00, + 0x80,0xcf,0x3f,0x00,0x00,0xfe,0x01,0x00,0xc0,0x01,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x07,0x0f,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xf0,0x00,0x00,0x00,0x00,0x00,0xe0,0xe7, + 0xff,0x00,0x00,0xfe,0x0f,0x00,0xc0,0xe1,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff,0x03,0x00,0xfc,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0x03,0x0f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x7c,0x00,0x00,0x00,0x00,0xf0,0xff,0xf9,0xff,0x01, + 0x00,0xe0,0x1f,0x00,0xc0,0xe1,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff,0x03,0x00,0xf8,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0x03,0x0f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x7e,0x00,0x00,0x00,0xc0,0xff,0x7f,0xfe,0xe1,0x07,0x00,0xc0, + 0xff,0x00,0xc0,0xe1,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0x01,0x00,0xe0,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0x03,0x07,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x1e,0x00,0x00,0x00,0xfc,0xff,0x1f,0xff,0x81,0x0f,0x00,0x80,0xf1,0x03, + 0xc0,0xe1,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x7f,0x00,0x00, + 0xe0,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x03, + 0x07,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x1e, + 0x00,0x00,0x00,0xfc,0xff,0x1f,0xff,0x81,0x0f,0x00,0x80,0xf1,0x03,0xc0,0xe1, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x7f,0x00,0x00,0xc0,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x81,0x0f,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x1f,0x00,0x00, + 0x00,0xff,0x3f,0x80,0xff,0x00,0x1f,0x00,0x80,0xc1,0x07,0xc0,0xe1,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x3f,0x00,0x00,0x00,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xc1,0xff,0x3f,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x0f,0x00,0x03,0xc0,0x3f, + 0x00,0xe0,0x7f,0x00,0x7e,0x00,0x80,0x01,0x1f,0xe0,0xe1,0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0x0f,0x00,0x00,0x00,0xfc,0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xe0,0xff,0xff,0x03,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x0f,0x80,0x07,0xf0,0x07,0x00,0xf0, + 0x3f,0x00,0xf8,0x00,0x80,0x01,0x3c,0xe0,0xe1,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff,0x03,0x00,0x00,0x00,0xf8,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0xe0,0xff,0xff,0x7f,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0xc0,0x03,0x80,0xff,0xff,0x01,0x00,0xfc,0x1f,0x00, + 0xf0,0x01,0xc0,0x01,0x38,0xe0,0xe0,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff,0x00,0x00,0x00,0x00,0xc0,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0x7f,0xf0,0x00,0xf8,0xff,0x07,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0xe0,0x03,0x00,0xfe,0x1f,0x00,0x80,0xbf,0x07,0x00,0x80,0x07, + 0xc0,0x01,0xe0,0xf1,0xe0,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x1f, + 0x00,0x00,0x00,0x00,0xc0,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0x7f,0xf0,0x00,0xf8,0xff,0x07,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0xe0,0x03,0x00,0xfe,0x1f,0x00,0x80,0xbf,0x07,0x00,0x80,0x07,0xc0,0x01, + 0xe0,0xf1,0xe0,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x1f,0x00,0x00, + 0x00,0x00,0x80,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x7f, + 0xf0,0x00,0x00,0xfe,0x7f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xf0, + 0x01,0x00,0xf8,0x03,0x00,0xc0,0xcf,0x03,0x00,0x80,0x1f,0xf0,0x01,0xe0,0x71, + 0xe0,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x0f,0x00,0x00,0x00,0x00, + 0x00,0xfe,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x7f,0xf0,0x00, + 0x00,0xe0,0xff,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xf8,0x00,0x00, + 0x00,0x00,0x00,0xe0,0xe7,0x03,0x00,0x00,0x7e,0xff,0x00,0xc0,0x73,0xf0,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x03,0x00,0x00,0x00,0x00,0x00,0xfc, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x3f,0xf0,0x00,0x00,0x00, + 0xfc,0x1f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x78,0x00,0x00,0x00,0x00, + 0x00,0xf8,0xf3,0x00,0x00,0x00,0xfc,0x7f,0x00,0x00,0x7f,0xf0,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0xf0,0xff,0xff, + 0xff,0x1f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xf0,0x00,0x00,0x00,0xe0,0xff, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3c,0x00,0x00,0x00,0x00,0x00,0x7c, + 0xf8,0x00,0x00,0x00,0xf8,0xff,0xff,0xff,0x7f,0xf0,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0x7f,0x00,0x00,0x00,0x00,0x00,0x00,0xf0,0xff,0xff,0xff,0x1f, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xf0,0x00,0x00,0x00,0xe0,0xff,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x3c,0x00,0x00,0x00,0x00,0x00,0x7c,0xf8,0x00, + 0x00,0x00,0xf8,0xff,0xff,0xff,0x7f,0xf0,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0x7f,0x00,0x00,0x00,0x00,0x00,0x00,0xe0,0xff,0xff,0xff,0x3f,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x70,0x00,0x00,0x00,0x80,0xff,0x0f,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x3e,0x00,0x00,0x00,0x00,0x00,0x7f,0x7c,0x00,0x00,0x00, + 0xe0,0xff,0xff,0xff,0x7f,0xf0,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x1f, + 0x00,0x00,0x00,0x00,0x00,0x00,0x80,0xff,0xff,0xff,0xff,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x78,0x00,0x00,0x00,0x00,0xfe,0x7f,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x1e,0x00,0x00,0x00,0x00,0xc0,0x1f,0x3e,0x00,0x00,0x00,0xc0,0xff, + 0xff,0xff,0x7f,0xf0,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x0f,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xff,0xff,0x01,0x00,0x00,0x00,0x00,0x00, + 0x00,0x7c,0x00,0x00,0x00,0x00,0xf0,0xff,0x03,0x00,0x00,0x00,0x00,0x00,0x00, + 0x0f,0x00,0x00,0x00,0x00,0xe0,0x07,0x1f,0x00,0x00,0x00,0x80,0x0f,0x00,0x00, + 0x3c,0xf0,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x03,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0xfc,0xff,0xff,0xff,0x07,0x00,0x00,0x00,0x00,0x00,0x00,0x3c, + 0x00,0x00,0x00,0x00,0x00,0xfe,0x0f,0x00,0x00,0x00,0x00,0x00,0x00,0x0f,0x00, + 0x00,0x00,0x00,0xfc,0x83,0x0f,0x00,0x00,0x00,0x00,0x0f,0x00,0x00,0x38,0xf0, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x01,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0xfc,0xff,0xff,0xff,0x07,0x00,0x00,0x00,0x00,0x00,0x00,0x3c,0x00,0x00, + 0x00,0x00,0x00,0xfe,0x0f,0x00,0x00,0x00,0x00,0x00,0x00,0x0f,0x00,0x00,0x00, + 0x00,0xfc,0x83,0x0f,0x00,0x00,0x00,0x00,0x0f,0x00,0x00,0x38,0xf0,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xf0, + 0xff,0xff,0xff,0x0f,0x00,0x00,0x00,0x00,0x00,0x00,0x1e,0x00,0x00,0x00,0xf8, + 0xff,0xff,0x3f,0x00,0x00,0x00,0x00,0x00,0x80,0x07,0x00,0x00,0x00,0x00,0xff, + 0x80,0x07,0x00,0x00,0x00,0x00,0x3e,0x00,0x00,0x38,0x00,0x00,0x00,0x00,0x00, + 0xff,0xff,0xff,0x7f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xc0,0xff,0xff, + 0xff,0x7f,0x00,0x00,0x00,0x00,0x00,0x00,0x0f,0x00,0x00,0x00,0xff,0xff,0xff, + 0xff,0x03,0x00,0x00,0x00,0x00,0xe0,0x01,0x00,0x00,0x00,0xe0,0x1f,0xe0,0x03, + 0x00,0x00,0x00,0x00,0x78,0x00,0x00,0x1c,0x00,0x00,0x00,0x00,0xe0,0xff,0xff, + 0xff,0x0f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xff,0xff, + 0x00,0x00,0x00,0x00,0x00,0x80,0x0f,0x00,0x00,0x00,0xff,0x3f,0xe0,0xff,0x0f, + 0x00,0x00,0x00,0x00,0xf0,0x01,0x00,0x00,0x00,0xf8,0x07,0xf0,0x01,0x00,0x00, + 0x00,0x00,0xf0,0x01,0x00,0x1e,0x00,0x00,0x00,0x00,0xf0,0xff,0xff,0xff,0x07, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xfe,0xff,0xff,0xff,0x03,0x00, + 0x00,0x00,0x00,0x80,0x07,0x00,0x00,0x00,0xe0,0xff,0x01,0xfe,0x3f,0x00,0x00, + 0x00,0x00,0xf0,0x00,0x00,0x00,0x00,0xfe,0x01,0xf8,0x00,0x00,0x00,0x00,0x00, + 0xc0,0x03,0x00,0x0e,0x00,0x00,0x00,0x00,0xfc,0xff,0xff,0xff,0x01,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xfe,0xff,0xff,0xff,0x03,0x00,0x00,0x00, + 0x00,0x80,0x07,0x00,0x00,0x00,0xe0,0xff,0x01,0xfe,0x3f,0x00,0x00,0x00,0x00, + 0xf0,0x00,0x00,0x00,0x00,0xfe,0x01,0xf8,0x00,0x00,0x00,0x00,0x00,0xc0,0x03, + 0x00,0x0e,0x00,0x00,0x00,0x00,0xfc,0xff,0xff,0xff,0x01,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0xf8,0xff,0xff,0xff,0x07,0x00,0x00,0x00,0x00,0x80, + 0x07,0x00,0x00,0x00,0x00,0xf8,0x07,0xc0,0xff,0x01,0x00,0x00,0x00,0xf8,0x00, + 0x00,0x00,0x80,0x7f,0x00,0x78,0x00,0x00,0x00,0x00,0x00,0xc0,0x0f,0x00,0x0e, + 0x00,0x00,0x00,0x00,0xff,0xff,0xff,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0xf0,0xff,0xff,0xff,0x1f,0x00,0x00,0x00,0x00,0xc0,0xe3,0xff, + 0xff,0x00,0x00,0xc0,0x1f,0x80,0xff,0x03,0x00,0x00,0x00,0x3c,0x00,0x00,0x00, + 0xe0,0x1f,0x00,0x3e,0x00,0x00,0x00,0x00,0x00,0x00,0x0f,0x00,0x07,0x00,0x00, + 0x00,0x80,0xff,0xff,0xff,0x1f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0xc0,0xff,0xff,0xff,0x7f,0x00,0x00,0x00,0x00,0xc0,0xfb,0xff,0xff,0x0f, + 0x00,0x00,0x3e,0x80,0xf3,0x1f,0x00,0x00,0x00,0x3e,0x00,0x00,0x00,0xf8,0x07, + 0x00,0x1e,0x00,0x00,0x00,0x00,0x00,0x00,0x1e,0x00,0x07,0x00,0x00,0x00,0xe0, + 0xff,0xff,0xff,0x0f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0xff,0xff,0xff,0xff,0x00,0x00,0x00,0x00,0xc0,0xff,0xff,0xff,0xff,0x00,0x00, + 0x7c,0xc0,0x81,0xff,0x00,0x00,0x00,0x1f,0x00,0x00,0x00,0xff,0x01,0x00,0x0f, + 0x00,0x00,0x00,0x00,0x00,0x00,0x7c,0x80,0x07,0x00,0x00,0x00,0xf0,0xff,0xff, + 0xff,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xfc,0xff, + 0xff,0xff,0x03,0x00,0x00,0x00,0xc0,0x7f,0x00,0xe0,0xff,0x3f,0x00,0xf0,0xc0, + 0x01,0xfe,0x03,0x00,0x00,0x0f,0x00,0x00,0xc0,0x7f,0x00,0xc0,0x07,0x00,0x00, + 0x00,0x00,0x00,0x00,0xf0,0xc0,0x03,0x00,0x00,0x00,0xfc,0xff,0xff,0xff,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xfc,0xff,0xff,0xff, + 0x03,0x00,0x00,0x00,0xc0,0x7f,0x00,0xe0,0xff,0x3f,0x00,0xf0,0xc0,0x01,0xfe, + 0x03,0x00,0x00,0x0f,0x00,0x00,0xc0,0x7f,0x00,0xc0,0x07,0x00,0x00,0x00,0x00, + 0x00,0x00,0xf0,0xc0,0x03,0x00,0x00,0x00,0xfc,0xff,0xff,0xff,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xf8,0xff,0xff,0xff,0x07,0x00, + 0x00,0x00,0xc0,0x0f,0x00,0x00,0xfc,0xff,0x03,0xc0,0xe3,0x01,0xf0,0x07,0x00, + 0x80,0x07,0x00,0x00,0xf0,0x1f,0x00,0xc0,0x07,0x00,0x00,0x00,0x00,0x00,0x00, + 0xf0,0xc1,0x01,0x00,0x00,0x00,0xff,0xff,0xff,0x7f,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xe0,0xff,0xff,0xff,0x1f,0x00,0x00,0x00, + 0xc0,0x07,0x00,0x00,0x00,0xfc,0xff,0x00,0xf7,0x00,0x00,0x3f,0x00,0xc0,0x03, + 0x00,0x00,0xff,0x00,0x00,0xe0,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0xc0,0xe3, + 0x01,0x00,0x00,0xc0,0xff,0xff,0xff,0x0f,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x80,0xff,0xff,0xff,0xff,0x00,0x00,0x00,0xc0,0x01, + 0x00,0x00,0x00,0xc0,0xff,0x07,0x7f,0x00,0x00,0xfc,0x00,0xe0,0x03,0x00,0xe0, + 0x3f,0x00,0x00,0xf0,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0xff,0x00,0x00, + 0x00,0xf0,0xff,0xff,0xff,0x07,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0xfe,0xff,0xff,0xff,0x00,0x00,0x00,0xc0,0x01,0x00,0x00, + 0x00,0x00,0xfe,0x7f,0x7f,0x00,0x00,0xf8,0x01,0xe0,0x01,0x00,0xfc,0x07,0x00, + 0x00,0xf8,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0x00,0x00,0x00,0xfc, + 0xff,0xff,0xff,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0xfe,0xff,0xff,0xff,0x00,0x00,0x00,0xc0,0x01,0x00,0x00,0x00,0x00, + 0xfe,0x7f,0x7f,0x00,0x00,0xf8,0x01,0xe0,0x01,0x00,0xfc,0x07,0x00,0x00,0xf8, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0x00,0x00,0x00,0xfc,0xff,0xff, + 0xff,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0xfc,0xff,0xff,0xff,0x03,0x00,0x00,0xc0,0x03,0x00,0x00,0x00,0x00,0xe0,0xff, + 0x3f,0x00,0x00,0xf0,0x07,0xf0,0x00,0x00,0xff,0x03,0x00,0x00,0x7c,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x7e,0x00,0x00,0x00,0xff,0xff,0xff,0x7f,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xf0,0xff, + 0xff,0xff,0x0f,0x00,0x00,0xc0,0x03,0x00,0x00,0x00,0x00,0x00,0xfe,0x3f,0x00, + 0x00,0xc0,0x3f,0xf8,0x00,0xf8,0x3f,0x00,0x00,0x00,0x3c,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x3c,0x00,0x00,0x80,0xff,0xff,0xff,0x3f,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xc0,0xff,0xff,0xff, + 0x3f,0x00,0x00,0xc0,0x03,0x00,0x00,0x00,0x00,0x00,0xf0,0xff,0x0f,0x00,0x00, + 0x7f,0x7c,0x00,0xfe,0x07,0x00,0x00,0x00,0x1e,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x1e,0x00,0x00,0xe0,0xff,0xff,0xff,0x0f,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0xff,0xff,0xff,0x7f,0x00, + 0x00,0x80,0x07,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0x7f,0x00,0x00,0xfc,0x3e, + 0xe0,0x7f,0x00,0x00,0x00,0x00,0x1f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x1f,0x00,0x00,0xf8,0xff,0xff,0xff,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0xff,0xff,0xff,0x7f,0x00,0x00,0x80, + 0x07,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0x7f,0x00,0x00,0xfc,0x3e,0xe0,0x7f, + 0x00,0x00,0x00,0x00,0x1f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x1f,0x00, + 0x00,0xf8,0xff,0xff,0xff,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0xfe,0xff,0xff,0xff,0x01,0x00,0x80,0x0f,0x00, + 0x00,0x00,0x00,0x00,0x00,0xf0,0xff,0x1f,0x00,0xf0,0x1f,0xfe,0x0f,0x00,0x00, + 0x00,0x80,0x0f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x07,0x00,0x00,0xfc, + 0xff,0xff,0xff,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0xf8,0xff,0xff,0xff,0x03,0x00,0x00,0x0f,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0xfc,0xff,0x3f,0xc0,0xff,0xff,0x00,0x00,0x00,0x00,0xc0, + 0x07,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x03,0x00,0x00,0xff,0xff,0xff, + 0x3f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0xf0,0xff,0xff,0xff,0x0f,0x00,0x00,0x1e,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0xfe,0xff,0xff,0xff,0x1f,0x00,0x00,0x00,0x00,0xe0,0x03,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0xe0,0x03,0x00,0xc0,0xff,0xff,0xff,0x1f,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x80,0xff,0xff,0xff,0x7f,0x00,0x00,0x3c,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0xfc,0xff,0xff,0x03,0x00,0x00,0x00,0x00,0xf0,0x01,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0xf8,0x00,0x00,0xf8,0xff,0xff,0xff,0x03,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0xff, + 0xff,0xff,0x7f,0x00,0x00,0x3c,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0xfc,0xff,0xff,0x03,0x00,0x00,0x00,0x00,0xf0,0x01,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0xf8,0x00,0x00,0xf8,0xff,0xff,0xff,0x03,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xfe,0xff,0xff, + 0xff,0x00,0x00,0x78,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xf8, + 0xff,0x1f,0x00,0x00,0x00,0x00,0xf0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x7c,0x00,0x00,0xfc,0xff,0xff,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xfc,0xff,0xff,0xff,0x03, + 0x00,0xf0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xfe,0x7f, + 0x00,0x00,0x00,0x00,0x7c,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3e,0x00, + 0x00,0xff,0xff,0xff,0x7f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xf0,0xff,0xff,0xff,0x07,0x00,0xe0, + 0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x7c,0xfe,0x00,0x00, + 0x00,0x00,0x3c,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x1f,0x00,0xc0,0xff, + 0xff,0xff,0x1f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0xe0,0xff,0xff,0xff,0x1f,0x00,0xc0,0x03,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x78,0xf8,0x03,0x00,0x00,0x00, + 0x1e,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xc0,0x07,0x00,0xe0,0xff,0xff,0xff, + 0x07,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x80,0xff,0xff,0xff,0x7f,0x00,0x80,0x07,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x70,0xe0,0x0f,0x00,0x00,0x00,0x0f,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0xf0,0x03,0x00,0xf8,0xff,0xff,0xff,0x03,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x80,0xff,0xff,0xff,0x7f,0x00,0x80,0x07,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x70,0xe0,0x0f,0x00,0x00,0x00,0x0f,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0xf0,0x03,0x00,0xf8,0xff,0xff,0xff,0x03,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0xff,0xff,0xff,0xff,0x00,0x80,0x0f,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x70,0x00,0x3f,0x00,0x00,0x80,0x0f,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0xf8,0x01,0x00,0xfe,0xff,0xff,0x7f,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xfc, + 0xff,0xff,0xff,0x03,0x00,0x1f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x70,0x00,0xfe,0x00,0x00,0xc0,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x7e,0x00,0x80,0xff,0xff,0xff,0x3f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xf0,0xff,0xff, + 0xff,0x0f,0x00,0x3e,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x70, + 0x00,0xf8,0x01,0x00,0xc0,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3e,0x00, + 0xc0,0xff,0xff,0xff,0x0f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xc0,0xff,0xff,0xff,0x3f, + 0x00,0xf8,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x70,0x00,0x80, + 0x0f,0x00,0xf0,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0xc0,0x0f,0x00,0xf8,0xff, + 0xff,0xff,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xc0,0xff,0xff,0xff,0x3f,0x00,0xf8, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x70,0x00,0x80,0x0f,0x00, + 0xf0,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0xc0,0x0f,0x00,0xf8,0xff,0xff,0xff, + 0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xff,0xff,0x00,0xe0,0x01,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x70,0x00,0x00,0x3e,0x00,0xf0,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0xe0,0x07,0x00,0xfe,0xff,0xff,0xff,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0xfc,0xff,0xff,0xff,0x03,0xc0,0x03,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x70,0x00,0x00,0xfc,0x00,0x78,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0xf8,0x01,0x80,0xff,0xff,0xff,0x3f,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0xf0,0xff,0xff,0xff,0x0f,0xc0,0x07,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x78,0x00,0x00,0xe0,0x03,0x3c,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x7c,0x00,0xe0,0xff,0xff,0xff,0x0f,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0xc0,0xff,0xff,0xff,0x1f,0x00,0x0f,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x7c,0x00,0x00,0xc0,0x1f,0x1e,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x3e,0x00,0xf0,0xff,0xff,0xff,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xc0, + 0xff,0xff,0xff,0x1f,0x00,0x0f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x7c,0x00,0x00,0xc0,0x1f,0x1e,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3e,0x00, + 0xf0,0xff,0xff,0xff,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0xff,0xff, + 0xff,0x7f,0x00,0x1e,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x7c,0x00, + 0x00,0x00,0x3f,0x0f,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x0f,0x00,0xfc,0xff, + 0xff,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xfe,0xff,0xff,0xff, + 0x01,0x7c,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3c,0x00,0x00,0x00, + 0xfc,0x0f,0x00,0x00,0x00,0x00,0x00,0x00,0xe0,0x07,0x00,0xff,0xff,0xff,0x3f, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xfc,0xff,0xff,0xff,0x03,0x78, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3c,0x00,0x00,0x00,0xf8,0x07, + 0x00,0x00,0x00,0x00,0x00,0x00,0xf0,0x01,0xc0,0xff,0xff,0xff,0x1f,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xf0,0xff,0xff,0xff,0x07,0xf0,0x01,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x1c,0x00,0x00,0x00,0xfc,0x03,0x00,0x00, + 0x00,0x00,0x00,0x00,0xf8,0x00,0xf0,0xff,0xff,0xff,0x07,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0xf0,0xff,0xff,0xff,0x07,0xf0,0x01,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x1c,0x00,0x00,0x00,0xfc,0x03,0x00,0x00,0x00,0x00, + 0x00,0x00,0xf8,0x00,0xf0,0xff,0xff,0xff,0x07,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0xe0,0xff,0xff,0xff,0x1f,0xe0,0x03,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x1c,0x00,0x00,0x00,0xfc,0x01,0x00,0x00,0x00,0x00,0x00,0x00, + 0x7e,0x00,0xf8,0xff,0xff,0xff,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0xff,0xff,0xff,0xff,0x80,0x0f,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x1e,0x00,0x00,0x00,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x0f,0x00, + 0xfe,0xff,0xff,0x3f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0xfc,0xff,0xff,0xff,0x01,0x1f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0e, + 0x00,0x00,0x80,0x7f,0x00,0x00,0x00,0x00,0x00,0x00,0xc0,0x07,0x80,0xff,0xff, + 0xff,0x0f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xf8,0xff, + 0xff,0xff,0x07,0x3e,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0e,0x00,0x00, + 0xc0,0x3f,0x00,0x00,0x00,0x00,0x00,0x00,0xf0,0x01,0xe0,0xff,0xff,0xff,0x07, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xe0,0xff,0xff,0xff, + 0x0f,0x7c,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0f,0x00,0x00,0xe0,0x3f, + 0x00,0x00,0x00,0x00,0x00,0x00,0xf8,0x01,0xf8,0xff,0xff,0xff,0x01,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xe0,0xff,0xff,0xff,0x0f,0x7c, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0f,0x00,0x00,0xe0,0x3f,0x00,0x00, + 0x00,0x00,0x00,0x00,0xf8,0x01,0xf8,0xff,0xff,0xff,0x01,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xc0,0xff,0xff,0xff,0x3f,0xf0,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x0f,0x00,0x00,0xf0,0x1f,0x00,0x00,0x00,0x00, + 0x00,0x00,0x7e,0x00,0xfc,0xff,0xff,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0xfe,0xff,0xff,0x7f,0xe0,0x01,0x00,0x00,0x00, + 0x00,0x00,0x00,0x80,0x07,0x00,0x00,0xfc,0x1f,0x00,0x00,0x00,0x00,0x00,0x00, + 0x3e,0x00,0xff,0xff,0xff,0x3f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0xfc,0xff,0xff,0xff,0xe0,0x03,0x00,0x00,0x00,0x00,0x00, + 0x00,0x80,0x07,0x00,0x00,0xfc,0x0f,0x00,0x00,0x00,0x00,0x00,0x00,0x1f,0xc0, + 0xff,0xff,0xff,0x1f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0xf0,0xff,0xff,0xff,0xc1,0x07,0x00,0x00,0x00,0x00,0x00,0x00,0xc0, + 0x03,0x00,0x00,0xfe,0x07,0x00,0x00,0x00,0x00,0x00,0xc0,0x0f,0xf0,0xff,0xff, + 0xff,0x07,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0xf0,0xff,0xff,0xff,0xc1,0x07,0x00,0x00,0x00,0x00,0x00,0x00,0xc0,0x03,0x00, + 0x00,0xfe,0x07,0x00,0x00,0x00,0x00,0x00,0xc0,0x0f,0xf0,0xff,0xff,0xff,0x07, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xf0,0xff, + 0xff,0xff,0x83,0x0f,0x00,0x00,0x00,0x00,0x00,0x00,0xc0,0x01,0x00,0x00,0xff, + 0x07,0x00,0x00,0x00,0x00,0x00,0xc0,0x07,0xf8,0xff,0xff,0xff,0x03,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0xff,0xff,0xff, + 0x0f,0x1e,0x00,0x00,0x00,0x00,0x00,0x00,0xe0,0x01,0x00,0xc0,0xef,0x03,0x00, + 0x00,0x00,0x00,0x00,0xe0,0x01,0xff,0xff,0xff,0x7f,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xfe,0xff,0xff,0x0f,0x1c, + 0x00,0x00,0x00,0x00,0x00,0x00,0xf0,0x00,0x00,0xe0,0xf3,0x01,0x00,0x00,0x00, + 0x00,0x00,0xf0,0x80,0xff,0xff,0xff,0x1f,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xfc,0xff,0xff,0x1f,0x38,0x00,0x00, + 0x00,0x00,0x00,0x00,0x70,0x00,0x00,0xf0,0xf9,0x00,0x00,0x00,0x00,0x00,0x00, + 0x78,0xe0,0xff,0xff,0xff,0x07,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0xfc,0xff,0xff,0x1f,0x38,0x00,0x00,0x00,0x00, + 0x00,0x00,0x70,0x00,0x00,0xf0,0xf9,0x00,0x00,0x00,0x00,0x00,0x00,0x78,0xe0, + 0xff,0xff,0xff,0x07,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0xf0,0xff,0xff,0x7f,0xf0,0x00,0x00,0x00,0x00,0x00,0x00, + 0x78,0x00,0x00,0x78,0x7c,0x00,0x00,0x00,0x00,0x00,0x00,0x3c,0xf0,0xff,0xff, + 0xff,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x80,0xff,0xff,0xff,0xe0,0x00,0x00,0x00,0x00,0x00,0x00,0x78,0x00, + 0x00,0x7e,0x7c,0x00,0x00,0x00,0x00,0x00,0x00,0x3c,0xf8,0xff,0xff,0xff,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0xff,0xff,0xff,0xe0,0x01,0x00,0x00,0x00,0x00,0x00,0x3c,0x00,0x00,0x3e, + 0x3e,0x00,0x00,0x00,0x00,0x00,0x00,0x1f,0xfe,0xff,0xff,0x7f,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xfe, + 0xff,0xff,0xc1,0x03,0x00,0x00,0x00,0x00,0x00,0x3c,0x00,0x00,0x0f,0x1e,0x00, + 0x00,0x00,0x00,0x00,0x00,0x0f,0xfe,0xff,0xff,0x1f,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xfe,0xff,0xff, + 0xc1,0x03,0x00,0x00,0x00,0x00,0x00,0x3c,0x00,0x00,0x0f,0x1e,0x00,0x00,0x00, + 0x00,0x00,0x00,0x0f,0xfe,0xff,0xff,0x1f,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xfc,0xff,0xff,0x83,0x07, + 0x00,0x00,0x00,0x00,0x00,0x1e,0x00,0xc0,0x07,0x0f,0x00,0x00,0x00,0x00,0x00, + 0x80,0x07,0xff,0xff,0xff,0x0f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xf0,0xff,0xff,0x07,0x0f,0x00,0x00, + 0x00,0x00,0x00,0x0f,0x00,0xe0,0x83,0x0f,0x00,0x00,0x00,0x00,0x00,0x80,0xc7, + 0xff,0xff,0xff,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0xc0,0xff,0xff,0x0f,0x0f,0x00,0x00,0x00,0x00, + 0x00,0x07,0x00,0xf0,0x81,0x07,0x00,0x00,0x00,0x00,0x00,0xc0,0xc3,0xff,0xff, + 0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x1f,0x1c,0x00,0x00,0x00,0x00,0x80,0x03, + 0x00,0x7c,0xc0,0x03,0x00,0x00,0x00,0x00,0x00,0xe0,0xe1,0xff,0xff,0x7f,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0xfe,0xff,0x3f,0x3c,0x00,0x00,0x00,0x00,0xc0,0x03,0x00,0x3f, + 0xe0,0x01,0x00,0x00,0x00,0x00,0x00,0xe0,0xe0,0xff,0xff,0x1f,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0xfe,0xff,0x3f,0x3c,0x00,0x00,0x00,0x00,0xc0,0x03,0x00,0x3f,0xe0,0x01, + 0x00,0x00,0x00,0x00,0x00,0xe0,0xe0,0xff,0xff,0x1f,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xf8, + 0xff,0x3f,0x3c,0x00,0x00,0x00,0x00,0xe0,0x01,0x80,0x1f,0xe0,0x01,0x00,0x00, + 0x00,0x00,0x00,0xf0,0xe0,0xff,0xff,0x07,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xf8,0xff,0x3f, + 0x38,0x00,0x00,0x00,0x00,0xe0,0x00,0xe0,0x07,0xf0,0x00,0x00,0x00,0x00,0x00, + 0x00,0x78,0xf8,0xff,0xff,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xf8,0xff,0x3f,0x38,0x00, + 0x00,0x00,0x00,0xf0,0x00,0xf0,0x03,0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x78, + 0xf8,0xff,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xf8,0xff,0x3f,0x38,0x00,0x00,0x00, + 0x00,0x70,0x00,0xfe,0x00,0x38,0x00,0x00,0x00,0x00,0x00,0x00,0x3c,0xfc,0xff, + 0x3f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0xf8,0xff,0x3f,0x38,0x00,0x00,0x00,0x00,0x70, + 0x00,0xfe,0x00,0x38,0x00,0x00,0x00,0x00,0x00,0x00,0x3c,0xfc,0xff,0x3f,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0xf8,0xff,0x3f,0x38,0x00,0x00,0x00,0x00,0x38,0x80,0x3f, + 0x00,0x3c,0x00,0x00,0x00,0x00,0x00,0x00,0x1c,0xfc,0xff,0x3f,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0xfc,0xff,0x3f,0x38,0x00,0x00,0x00,0x00,0x1c,0xc0,0x0f,0x00,0x1c, + 0x00,0x00,0x00,0x00,0x00,0x00,0x1e,0xfc,0xff,0x3f,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0xfc,0xff,0x1f,0x38,0x00,0x00,0x00,0x00,0x1e,0xf0,0x03,0x00,0x1e,0x00,0x00, + 0x00,0x00,0x00,0x00,0x1e,0xfc,0xff,0x3f,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xfe,0xff, + 0x1f,0x38,0x00,0x00,0x00,0x00,0x0f,0x7f,0x00,0x00,0x0f,0x00,0x00,0x00,0x00, + 0x00,0x00,0x0f,0xfc,0xff,0x3f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xfe,0xff,0x1f,0x38, + 0x00,0x00,0x00,0x00,0x0f,0x7f,0x00,0x00,0x0f,0x00,0x00,0x00,0x00,0x00,0x00, + 0x0f,0xfc,0xff,0x3f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xfe,0xff,0x1f,0x38,0x00,0x00, + 0x00,0x00,0xe7,0x3f,0x00,0x00,0x07,0x00,0x00,0x00,0x00,0x00,0x00,0x0f,0xfc, + 0xff,0x7f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x0f,0x38,0x00,0x00,0x00,0x80, + 0xfb,0x0f,0x00,0x80,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x07,0xfc,0xff,0x7f, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x07,0x38,0x00,0x00,0x00,0xc0,0xff,0x01, + 0x00,0xc0,0x03,0x00,0x00,0x00,0x00,0x00,0x80,0x07,0xf8,0xff,0xff,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0xff,0xff,0x07,0x38,0x00,0x00,0x00,0xe0,0x3f,0x00,0x00,0xc0, + 0x01,0x00,0x00,0x00,0x00,0x00,0xc0,0x03,0xf8,0xff,0xff,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0xff,0xff,0x07,0x38,0x00,0x00,0x00,0xe0,0x3f,0x00,0x00,0xc0,0x01,0x00, + 0x00,0x00,0x00,0x00,0xc0,0x03,0xf8,0xff,0xff,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0xff, + 0xff,0x07,0x38,0x00,0x00,0x00,0xe0,0x0f,0x00,0x00,0xe0,0x00,0x00,0x00,0x00, + 0x00,0x00,0xc0,0x03,0xf8,0xff,0xff,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0xff,0xff,0x03, + 0x38,0x00,0x00,0x00,0xf0,0x03,0x00,0x00,0xf0,0x00,0x00,0x00,0x00,0x00,0x00, + 0xe0,0x01,0xf8,0xff,0xff,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xc0,0xff,0xff,0x03,0x38,0x00, + 0x00,0x00,0x70,0x00,0x00,0x00,0x70,0x00,0x00,0x00,0x00,0x00,0x00,0xe0,0x01, + 0xf0,0xff,0xff,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xc0,0xff,0xff,0x01,0x38,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x78,0x00,0x00,0x00,0x00,0x00,0x00,0xe0,0x00,0xf0,0xff, + 0xff,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0xe0,0xff,0xff,0x00,0x38,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x38,0x00,0x00,0x00,0x00,0x00,0x00,0xf0,0x00,0xf0,0xff,0xff,0x03, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0xe0,0xff,0xff,0x00,0x38,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x38,0x00,0x00,0x00,0x00,0x00,0x00,0xf0,0x00,0xf0,0xff,0xff,0x03,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0xe0,0xff,0xff,0x00,0x38,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3c,0x00, + 0x00,0x00,0x00,0x00,0x00,0xf0,0x00,0xe0,0xff,0xff,0x07,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xe0, + 0xff,0xff,0x00,0x38,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x1e,0x00,0x00,0x00, + 0x00,0x00,0x00,0x78,0x00,0xe0,0xff,0xff,0x07,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xf0,0xff,0x7f, + 0x00,0x18,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x1e,0x00,0x00,0x00,0x00,0x00, + 0x00,0x78,0x00,0xc0,0xff,0xff,0x0f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xf0,0xff,0x7f,0x00,0x18, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0f,0x00,0x00,0x00,0x00,0x00,0x00,0x3c, + 0x00,0xc0,0xff,0xff,0x0f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xf0,0xff,0x7f,0x00,0x18,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x0f,0x00,0x00,0x00,0x00,0x00,0x00,0x3c,0x00,0xc0, + 0xff,0xff,0x0f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0xf8,0xff,0x7f,0x00,0x1c,0x00,0x00,0x00,0x00, + 0x00,0x00,0x80,0x07,0x00,0x00,0x00,0x00,0x00,0x00,0x3c,0x00,0x80,0xff,0xff, + 0x0f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0xf8,0xff,0x3f,0x00,0x1c,0x00,0x00,0x00,0x00,0x00,0x00, + 0x80,0x07,0x00,0x00,0x00,0x00,0x00,0x00,0x1e,0x00,0x80,0xff,0xff,0x1f,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0xfc,0xff,0x1f,0x00,0x1c,0x00,0x00,0x00,0x00,0x00,0x00,0xc0,0x03, + 0x00,0x00,0x00,0x00,0x00,0x00,0x1e,0x00,0x80,0xff,0xff,0x1f,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0xfc,0xff,0x1f,0x00,0x1c,0x00,0x00,0x00,0x00,0x00,0x00,0xc0,0x03,0x00,0x00, + 0x00,0x00,0x00,0x00,0x1f,0x00,0x00,0xff,0xff,0x1f,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xfc,0xff, + 0x1f,0x00,0x1c,0x00,0x00,0x00,0x00,0x00,0x00,0xc0,0x03,0x00,0x00,0x00,0x00, + 0x00,0x00,0x1f,0x00,0x00,0xff,0xff,0x1f,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xfe,0xff,0x0f,0x00, + 0x1c,0x00,0x00,0x00,0x00,0x00,0x00,0xe0,0x01,0x00,0x00,0x00,0x00,0x00,0x00, + 0x0f,0x00,0x00,0xff,0xff,0x3f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xfe,0xff,0x0f,0x00,0x1c,0x00, + 0x00,0x00,0x00,0x00,0x00,0xe0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0f,0x00, + 0x00,0xff,0xff,0x3f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xfe,0xff,0x07,0x00,0x1c,0x00,0x00,0x00, + 0x00,0x00,0x00,0xf0,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x07,0x00,0x00,0xfe, + 0xff,0x3f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x07,0x00,0x1e,0x00,0x00,0x00,0x00,0x00, + 0x00,0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x07,0x00,0x00,0xfe,0xff,0x7f, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0xff,0xff,0x07,0x00,0x1e,0x00,0x00,0x00,0x00,0x00,0x00,0x70, + 0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x07,0x00,0x00,0xfe,0xff,0x7f,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0xff,0xff,0x07,0x00,0x1e,0x00,0x00,0x00,0x00,0x00,0x00,0x78,0x00,0x00, + 0x00,0x00,0x00,0x00,0x80,0x07,0x00,0x00,0xfc,0xff,0x7f,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0xff, + 0xff,0x03,0x00,0x1e,0x00,0x00,0x00,0x00,0x00,0x00,0x38,0x00,0x00,0x00,0x00, + 0x00,0x00,0x80,0x03,0x00,0x00,0xfc,0xff,0xff,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0xff,0xff,0x03, + 0x00,0x1e,0x00,0x00,0x00,0x00,0x00,0x00,0x3c,0x00,0x00,0x00,0x00,0x00,0x00, + 0xc0,0x03,0x00,0x00,0xfc,0xff,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xc0,0xff,0xff,0x03,0x00,0x1e, + 0x00,0x00,0x00,0x00,0x00,0x00,0x1e,0x00,0x00,0x00,0x00,0x00,0x00,0xc0,0x03, + 0x00,0x00,0xf8,0xff,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xc0,0xff,0xff,0x03,0x00,0x1e,0x00,0x00, + 0x00,0x00,0x00,0x00,0x1e,0x00,0x00,0x00,0x00,0x00,0x00,0xc0,0x03,0x00,0x00, + 0xf8,0xff,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0xc0,0xff,0xff,0x01,0x00,0x1e,0x00,0x00,0x00,0x00, + 0x00,0x00,0x1e,0x00,0x00,0x00,0x00,0x00,0x00,0xc0,0x03,0x00,0x00,0xf8,0xff, + 0xff,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0xe0,0xff,0xff,0x01,0x00,0x1c,0x00,0x00,0x00,0x00,0x00,0x00, + 0x0f,0x00,0x00,0x00,0x00,0x00,0x00,0xc0,0x01,0x00,0x00,0xf0,0xff,0xff,0x01, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0xe0,0xff,0xff,0x00,0x00,0x1c,0x00,0x00,0x00,0x00,0x00,0x80,0x07,0x00, + 0x00,0x00,0x00,0x00,0x00,0xc0,0x01,0x00,0x00,0xf0,0xff,0xff,0x01,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xe0, + 0xff,0xff,0x00,0x00,0x3c,0x00,0x00,0x00,0x00,0x00,0x80,0x07,0x00,0x00,0x00, + 0x00,0x00,0x00,0xc0,0x01,0x00,0x00,0xf0,0xff,0xff,0x03,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xf0,0xff,0x7f, + 0x00,0x00,0x3c,0x00,0x00,0x00,0x00,0x00,0x80,0x03,0x00,0x00,0x00,0x00,0x00, + 0x00,0xc0,0x01,0x00,0x00,0xe0,0xff,0xff,0x03,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xf0,0xff,0x7f,0x00,0x00, + 0x3c,0x00,0x00,0x00,0x00,0x00,0x80,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0xc0, + 0x01,0x00,0x00,0xe0,0xff,0xff,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xf0,0xff,0x7f,0x00,0x00,0x38,0x00, + 0x00,0x00,0x00,0x00,0xc0,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0xc0,0x01,0x00, + 0x00,0xe0,0xff,0xff,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0xf8,0xff,0x3f,0x00,0x00,0x38,0x00,0x00,0x00, + 0x00,0x00,0xc0,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0xc0,0x01,0x00,0x00,0xe0, + 0xff,0xff,0x07,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0xf8,0xff,0x3f,0x00,0x00,0x38,0x00,0x00,0x00,0x00,0x00, + 0xe0,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0xc0,0x01,0x00,0x00,0xc0,0xff,0xff, + 0x07,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0xfc,0xff,0x1f,0x00,0x00,0x38,0x00,0x00,0x00,0x00,0x00,0xe0,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0xc0,0x01,0x00,0x00,0xc0,0xff,0xff,0x07,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0xfc,0xff,0x1f,0x00,0x00,0x38,0x00,0x00,0x00,0x00,0x00,0xe0,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0xc0,0x01,0x00,0x00,0xc0,0xff,0xff,0x07,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xfc,0xff, + 0x1f,0x00,0x00,0x38,0x00,0x00,0x00,0x00,0x00,0xf0,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0xc0,0x01,0x00,0x00,0x80,0xff,0xff,0x0f,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xfc,0xff,0x1f,0x00, + 0x00,0x38,0x00,0x00,0x00,0x00,0x00,0x78,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0xc0,0x03,0x00,0x00,0x80,0xff,0xff,0x0f,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xfe,0xff,0x0f,0x00,0x00,0x38, + 0x00,0x00,0x00,0x00,0x00,0x78,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xc0,0x03, + 0x00,0x00,0x00,0xff,0xff,0x1f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xfe,0xff,0x0f,0x00,0x00,0x3c,0x00,0x00, + 0x00,0x00,0x00,0x3c,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x07,0x00,0x00, + 0x00,0xff,0xff,0x1f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0xfe,0xff,0x0f,0x00,0x00,0x3c,0x00,0x00,0x00,0x00, + 0x00,0x3c,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x07,0x00,0x00,0x00,0xff, + 0xff,0x1f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0xff,0x07,0x00,0x00,0xfc,0x3f,0x00,0x00,0x00,0x00,0x00,0x3e, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x07,0x00,0x00,0x00,0xfe,0xff,0x1f, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x0f,0x00,0xe0,0xff,0xff,0x3f,0x00,0x00,0x00,0x00,0x00,0x1e,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x0f,0x00,0x00,0x00,0xfe,0xff,0x3f,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0xfc,0xff,0xff,0xff,0x3f,0x00,0x00,0x00,0x00,0x00,0x0f,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x0f,0x00,0x00,0x00,0xfe,0xff,0x3f,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xe0,0xff,0xff, + 0xff,0x0f,0x3c,0x00,0x00,0x00,0x00,0x00,0x0f,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x0e,0x00,0x00,0x00,0xfc,0xff,0x3f,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xe0,0xff,0xff,0xff,0x0f, + 0x3c,0x00,0x00,0x00,0x00,0x00,0x0f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x0e,0x00,0x00,0x00,0xfc,0xff,0x3f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xfc,0xff,0xff,0x01,0x00,0x38,0x00, + 0x00,0x00,0x00,0x80,0x07,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x1e,0x00, + 0x00,0x00,0xfc,0xff,0x7f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0xf0,0xff,0xff,0x00,0x00,0x00,0x38,0x00,0x00,0x00, + 0x00,0x80,0x07,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3c,0x00,0x00,0x00, + 0xfc,0xff,0x7f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0xff,0xff,0x03,0x00,0x00,0x00,0x38,0x00,0x00,0x00,0x00,0xc0, + 0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x78,0x00,0x00,0x00,0xf8,0xff, + 0x7f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0xfc,0xff,0x1f,0x00,0x00,0x00,0x00,0x78,0x00,0x00,0x00,0x00,0xc0,0x01,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x70,0x00,0x00,0x00,0xf8,0xff,0xff,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xc0,0xff,0xff, + 0x01,0x00,0x00,0x00,0x00,0x70,0x00,0x00,0x00,0x00,0xe0,0x01,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0xf0,0x01,0x00,0x00,0xf0,0xff,0xff,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xc0,0xff,0xff,0x01,0x00, + 0x00,0x00,0x00,0x70,0x00,0x00,0x00,0x00,0xe0,0x01,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0xf0,0x01,0x00,0x00,0xf0,0xff,0xff,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x07,0x00,0xfe,0x00,0x00, + 0x00,0x70,0x00,0x00,0x00,0x00,0xe0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0xe0,0x03,0x00,0x00,0xf0,0xff,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0xf0,0xff,0x1f,0x00,0xf8,0xff,0x00,0x00,0x00,0x70, + 0x00,0x00,0x00,0x00,0xf0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xc0, + 0x03,0x00,0x00,0xf0,0xff,0xff,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0xfe,0x7f,0x00,0xe0,0xff,0x7f,0x00,0x00,0x00,0x70,0x00,0x00, + 0x00,0x00,0xf8,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x0f,0x00, + 0x00,0xf0,0xff,0xff,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0xe0,0xff,0x03,0x00,0xf0,0xff,0x3f,0x00,0x00,0x00,0x70,0x00,0x00,0x00,0x00, + 0x78,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x1f,0x00,0x00,0xe0, + 0xff,0xff,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xe0,0xff, + 0x03,0x00,0xf0,0xff,0x3f,0x00,0x00,0x00,0x70,0x00,0x00,0x00,0x00,0x78,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x1f,0x00,0x00,0xe0,0xff,0xff, + 0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xfc,0x7f,0x00,0x00, + 0xf8,0xff,0x3f,0x00,0x00,0x00,0x70,0x00,0x00,0x00,0x00,0x78,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x7c,0x00,0x00,0xe0,0xff,0xff,0x03,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0xff,0x07,0x00,0x00,0xf8,0xff, + 0x1f,0x00,0x00,0x00,0xe0,0x00,0x00,0x00,0x00,0x3c,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0xf8,0x01,0x00,0xe0,0xff,0xff,0x03,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0xc0,0xff,0x00,0x00,0x00,0xfc,0xff,0x1f,0x00, + 0x00,0x00,0xe0,0x00,0x00,0x00,0x00,0x3c,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0xe0,0x07,0x00,0xc0,0xff,0xff,0x03,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0xc0,0x1f,0x00,0x00,0x00,0xfe,0xff,0x1f,0x00,0x00,0x00, + 0xe0,0x00,0x00,0x00,0x00,0x3c,0x00,0x00,0x60,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0xc0,0x3f,0x00,0xc0,0xff,0xff,0x07,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0xc0,0x1f,0x00,0x00,0x00,0xfe,0xff,0x1f,0x00,0x00,0x00,0xe0,0x00, + 0x00,0x00,0x00,0x3c,0x00,0x00,0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xc0, + 0x3f,0x00,0xc0,0xff,0xff,0x07,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x80,0x03,0x00,0x00,0x00,0xfe,0xff,0x0f,0x00,0x00,0x00,0xe0,0x00,0x00,0x00, + 0x00,0x3e,0x00,0x00,0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0x01, + 0x80,0xff,0xff,0x07,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0xfe,0xff,0x0f,0x00,0x00,0x00,0xe0,0x00,0x00,0x00,0x00,0x3f, + 0x00,0x00,0x38,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xf8,0x3f,0x80,0xff, + 0xff,0x0f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0xff,0xff,0x07,0x00,0x00,0x00,0xc0,0x01,0x00,0x00,0x00,0xff,0x00,0x00, + 0x38,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xc0,0xff,0x00,0xfc,0xff,0x0f, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff, + 0xff,0x07,0x00,0x00,0x00,0xc0,0x01,0x00,0x00,0x00,0xf7,0x03,0x00,0x3c,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0x0f,0xc0,0xff,0x0f,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x07, + 0x00,0x00,0x00,0xc0,0x01,0x00,0x00,0x00,0xf7,0x03,0x00,0x3c,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0xff,0x0f,0xc0,0xff,0x0f,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0xff,0xff,0x03,0x00,0x00, + 0x00,0xc0,0x01,0x00,0x00,0x80,0xe3,0x0f,0x00,0x3f,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0xf0,0x7f,0x00,0xf8,0x1f,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0xff,0xff,0x03,0x00,0x00,0x00,0xc0, + 0x01,0x00,0x00,0x80,0xe3,0xff,0xff,0x3f,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x80,0xff,0x03,0x80,0x0f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x80,0xff,0xff,0x03,0x00,0x00,0x00,0xc0,0x01,0x00, + 0x00,0x80,0xc3,0xff,0xff,0x3f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0xfe,0x1f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0xc0,0xff,0xff,0x01,0x00,0x00,0x00,0xc0,0x01,0x00,0x00,0xc0, + 0x01,0xff,0xff,0x3f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xe0, + 0xff,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0xc0,0xff,0xff,0x00,0x00,0x00,0x00,0xc0,0x01,0x00,0x00,0xc0,0x01,0xfe, + 0x7f,0x38,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xfe,0x1f, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xc0, + 0xff,0xff,0x00,0x00,0x00,0x00,0xc0,0x01,0x00,0x00,0xc0,0x01,0xfe,0x7f,0x38, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xfe,0x1f,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xe0,0xff,0xff, + 0x00,0x00,0x00,0x00,0xc1,0x01,0x00,0x00,0xe0,0x00,0x3e,0x00,0x38,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xf0,0xff,0x01,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xe0,0xff,0xff,0x00,0x00, + 0x00,0x80,0xc3,0x01,0x00,0x00,0xe0,0x00,0x7c,0x00,0x3c,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0x7f,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xf0,0xff,0x7f,0x00,0x00,0x00,0xf0, + 0xc3,0x01,0x00,0x00,0xf0,0x00,0xf0,0x00,0x3c,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x80,0xff,0xff,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0xf8,0xff,0x7f,0x00,0x00,0x00,0xf8,0xc3,0x01, + 0x00,0x00,0xf0,0x00,0xe0,0x01,0x3c,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0xe0,0xff,0xff,0x03,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0xf8,0xff,0x7f,0x00,0x00,0x00,0xf8,0xc3,0x01,0x00,0x00, + 0xf0,0x00,0xe0,0x01,0x3c,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0xe0,0xff,0xff,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0xf8,0xff,0x7f,0x00,0x00,0x00,0xff,0xc3,0x03,0x00,0x00,0x70,0x00, + 0xc0,0x03,0x3c,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x80,0xff,0xff,0xff,0x07,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0xf8,0xff,0x3f,0x00,0x00,0x80,0xff,0xc3,0x03,0x00,0x00,0x70,0x00,0xc0,0x03, + 0x3c,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xf0,0x01,0x00, + 0xf0,0xff,0xff,0x0f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xf8,0xff, + 0x1f,0x00,0x00,0xe0,0xff,0xc3,0x03,0x00,0x00,0x78,0x00,0x80,0x07,0x3c,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xf0,0x7f,0x00,0x00,0x00, + 0xfc,0x0f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xfc,0xff,0x1f,0x00, + 0x00,0xf8,0xff,0xc3,0x03,0x00,0x00,0x78,0x00,0x00,0x0f,0x3c,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xe0,0xff,0x0f,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xfc,0xff,0x1f,0x00,0x00,0xf8, + 0xff,0xc3,0x03,0x00,0x00,0x78,0x00,0x00,0x0f,0x3c,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0xe0,0xff,0x0f,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xfc,0xff,0x0f,0x00,0x00,0xfe,0xff,0x83, + 0x03,0x00,0x00,0x3c,0x00,0x00,0x1e,0x1c,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0xfc,0xff,0x01,0xe0,0xff,0xff,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0xfe,0xff,0x0f,0x00,0x80,0xff,0xff,0x87,0x03,0x00, + 0x00,0x3c,0x00,0x00,0x3c,0x1c,0x00,0x00,0x00,0x00,0x00,0x00,0xf8,0xff,0xff, + 0xff,0xff,0xe1,0xff,0xff,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0xfe,0xff,0x0f,0x00,0xc0,0xff,0xff,0x87,0x03,0x00,0x00,0x3c, + 0x00,0x00,0x78,0x1c,0x00,0x00,0x00,0x00,0x00,0xfe,0xff,0xff,0xff,0xff,0xff, + 0xe1,0xff,0xff,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0xff,0xff,0x07,0x00,0xf8,0xff,0xff,0xc7,0x03,0x00,0x00,0x1c,0x00,0x00, + 0xe0,0x1c,0x00,0x00,0x00,0x80,0xff,0xff,0xff,0x01,0x00,0x00,0x00,0xc0,0xff, + 0xff,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff, + 0xff,0x07,0x00,0xf8,0xff,0xff,0xc7,0x03,0x00,0x00,0x1c,0x00,0x00,0xe0,0x1c, + 0x00,0x00,0x00,0x80,0xff,0xff,0xff,0x01,0x00,0x00,0x00,0xc0,0xff,0xff,0x03, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x03, + 0x00,0xfe,0xff,0xff,0xc7,0x03,0x00,0x00,0x1c,0x00,0x00,0xe0,0x1f,0x00,0x00, + 0x00,0xf0,0xff,0xff,0x00,0x00,0x00,0x00,0x00,0x80,0xff,0xff,0x07,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0xff,0xff,0x03,0x00,0xff, + 0xff,0xff,0xc7,0x03,0x00,0x00,0x1c,0x00,0x00,0x80,0x1f,0x00,0x00,0x00,0xff, + 0xff,0x03,0x00,0x00,0x00,0xfc,0x03,0x80,0xff,0xff,0x07,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0xff,0xff,0x03,0xc0,0xff,0xff,0xff, + 0xc7,0x03,0x00,0x00,0x1e,0x00,0x00,0x00,0x1f,0x00,0x00,0xf8,0xff,0x0f,0x00, + 0x80,0xff,0xff,0xff,0x1f,0x00,0xff,0xff,0x07,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x80,0xff,0xff,0x01,0xf0,0xff,0xff,0xff,0xc3,0x03, + 0x00,0x00,0xfe,0xff,0x00,0x00,0x1f,0x00,0xe0,0xff,0x3f,0x00,0x00,0x80,0xff, + 0xff,0xff,0x3f,0x00,0xff,0xff,0x07,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0xc0,0xff,0xff,0x01,0xfc,0xff,0xff,0xff,0xc1,0x03,0x00,0x00, + 0xfe,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x01,0x00,0x00,0x80,0xff,0xff,0xff, + 0x7f,0x00,0xff,0xff,0x0f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0xc0,0xff,0xff,0x01,0xfc,0xff,0xff,0xff,0xc1,0x03,0x00,0x00,0xfe,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0x01,0x00,0x00,0x80,0xff,0xff,0xff,0x7f,0x00, + 0xff,0xff,0x0f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xe0, + 0xff,0xff,0x01,0xff,0xff,0xff,0xff,0x80,0x03,0x00,0x00,0xfe,0xff,0xff,0xff, + 0xff,0xff,0xff,0x07,0x00,0x00,0x00,0x00,0xfe,0xff,0xff,0xff,0x01,0xfe,0xff, + 0x1f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xe0,0xff,0xff, + 0x80,0xff,0xff,0xff,0x3f,0x00,0x00,0x00,0x00,0x7c,0x00,0x00,0xf5,0xff,0xff, + 0x3f,0x00,0x00,0x00,0x00,0x00,0xfc,0xff,0xff,0xff,0x07,0xfe,0xff,0x1f,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xe0,0xff,0x7f,0xf0,0xff, + 0xff,0xff,0x0f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0xf0,0xff,0xff,0xff,0x1f,0xfe,0xff,0x1f,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xf0,0xff,0x7f,0xf8,0xff,0xff,0xff, + 0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0xc0,0xff,0xff,0xff,0x3f,0xfe,0xff,0x3f,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0xf0,0xff,0x7f,0xf8,0xff,0xff,0xff,0x03,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0xc0,0xff,0xff,0xff,0x3f,0xfe,0xff,0x3f,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0xf0,0xff,0xff,0xff,0xff,0xff,0x7f,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff, + 0xff,0xff,0xff,0xfc,0xff,0x3f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0xf8,0xff,0xff,0xff,0xff,0xff,0x3f,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xfc,0xff,0xff, + 0xff,0xff,0xff,0x3f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0xf8,0xff,0xff,0xff,0xff,0xff,0x0f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xf0,0xff,0xff,0xff,0xff, + 0xff,0x3f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xfc,0xff, + 0xff,0xff,0xff,0xff,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xe0,0xff,0xff,0xff,0xff,0xff,0x7f, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xfc,0xff,0xff,0xff, + 0xff,0xff,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0xe0,0xff,0xff,0xff,0xff,0xff,0x7f,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xfc,0xff,0xff,0xff,0xff,0xff, + 0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x80,0xff,0xff,0xff,0xff,0xff,0x7f,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xfc,0xff,0xff,0xff,0xff,0x7f,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0xfe,0xff,0xff,0xff,0xff,0xff,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0xfe,0xff,0xff,0xff,0xff,0x3f,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0xfc,0xff,0xff,0xff,0xff,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0xfe,0xff,0xff,0xff,0xff,0x07,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xf0, + 0xff,0xff,0xff,0xff,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0xfe,0xff,0xff,0xff,0xff,0x07,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xf0,0xff,0xff, + 0xff,0xff,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xfe, + 0xff,0xff,0xff,0xff,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xe0,0xff,0xff,0xff,0xff, + 0xff,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xff, + 0xff,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0xff,0xff,0xff,0xff,0xff,0x01, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0xff,0xff,0xff,0xff,0x3f, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xfe,0xff,0xff,0xff,0xff,0x01,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0xff,0xff,0xff,0xff,0x1f,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0xf8,0xff,0xff,0xff,0xff,0x03,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0xc0,0xff,0xff,0xff,0xff,0x07,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0xf0,0xff,0xff,0xff,0xff,0x03,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0xc0,0xff,0xff,0xff,0xff,0x07,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0xf0,0xff,0xff,0xff,0xff,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0xc0,0xff,0xff,0xff,0xff,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xc0, + 0xff,0xff,0xff,0xff,0x07,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xc0, + 0xff,0xff,0xff,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0xff,0xff, + 0xff,0xff,0x07,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xe0,0xff,0xff, + 0xff,0x1f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xff,0xff, + 0x07,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xe0,0xff,0xff,0xff,0x0f, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xfc,0xff,0xff,0xff,0x0f,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xe0,0xff,0xff,0xff,0x0f,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xfc,0xff,0xff,0xff,0x0f,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0xf0,0xff,0xff,0xff,0x03,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0xf8,0xff,0xff,0xff,0x0f,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0xf0,0xff,0xff,0xff,0x01,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0xe0,0xff,0xff,0xff,0x0f,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0xf8,0xff,0xff,0x7f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0xc0,0xff,0xff,0xff,0x0f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0xf8,0xff,0xff,0x3f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0xff,0xff,0xff,0x1f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xf8,0xff, + 0xff,0x3f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff, + 0xff,0x1f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xf8,0xff,0xff,0x07, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xfc,0xff,0xff,0x3f, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xfc,0xff,0xff,0x03,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xf8,0xff,0xff,0x3f,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xfe,0xff,0xff,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xe0,0xff,0xff,0x3f,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0xfe,0xff,0x3f,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x80,0xff,0xff,0x3f,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0xfe,0xff,0x3f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x80,0xff,0xff,0x3f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0xfe,0xff,0x0f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0xfe,0xff,0x7f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff, + 0xff,0x07,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0xfc,0xff,0x7f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xf0,0xff, + 0x7f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0xff,0x3f,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xc0,0xff,0x7f,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0xff,0x1f,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0xff,0xff,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x80,0xff,0x1f,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0xff,0xff,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0xc0,0xff,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0xfe,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0xc0,0xff,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0xfc,0xff,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xc0, + 0x7f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0xf0,0xff,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xe0,0x1f,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0xc0,0xff,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xe0,0x1f,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xc0,0xff, + 0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xe0,0x0f,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0xff,0x01,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0xf0,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xfe,0x03,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x78,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xf8,0x03,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x18,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0xf0,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x18,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0xf0,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0xc0,0x07,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x07,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}; diff --git a/hacks/images/timetunnel0.xpm b/hacks/images/timetunnel0.xpm new file mode 100644 index 00000000..65a6e8b0 --- /dev/null +++ b/hacks/images/timetunnel0.xpm @@ -0,0 +1,343 @@ +/* XPM */ +static char * timetunnel0_xpm[] = { +"256 256 84 1", +" c #5D699C", +". c #5A6EC7", +"+ c #596FD1", +"@ c #576FD7", +"# c #566FDE", +"$ c #6172B3", +"% c #5670E6", +"& c #6477BF", +"* c #6076D2", +"= c #6377C6", +"- c #6277CC", +"; c #5876F6", +"> c #607AE7", +", c #5D7AF0", +"' c #627BDE", +") c #6982D1", +"! c #6582DE", +"~ c #6882D8", +"{ c #6D7FDC", +"] c #6284FD", +"^ c #7088D1", +"/ c #6886F6", +"( c #738ACC", +"_ c #7185EF", +": c #6C89EC", +"< c #698AF4", +"[ c #648DFD", +"} c #6C8EE7", +"| c #748BE7", +"1 c #738FDE", +"2 c #6D94FF", +"3 c #6B9BFD", +"4 c #7796FA", +"5 c #709DF5", +"6 c #7A9EDD", +"7 c #7C9BEB", +"8 c #8A99D1", +"9 c #73A1E8", +"0 c #8198F6", +"a c #8895F3", +"b c #819CE6", +"c c #7D9DF7", +"d c #89A0E3", +"e c #78A6FE", +"f c #76ACFD", +"g c #83AAE9", +"h c #72B3FF", +"i c #89ABFC", +"j c #80B6FD", +"k c #92AEF9", +"l c #7DBFFE", +"m c #8DBCEE", +"n c #9BB7EC", +"o c #8DBCFA", +"p c #9FB4F8", +"q c #97B8F9", +"r c #7AC7FF", +"s c #AEB7EF", +"t c #80D5FF", +"u c #8DD1FD", +"v c #99CCFD", +"w c #89DDFF", +"x c #B1CAFB", +"y c #A8D3FB", +"z c #82E6FF", +"A c #9AE1FE", +"B c #CCCCFA", +"C c #B3D9FC", +"D c #87F4FF", +"E c #93EFFF", +"F c #A8EAFE", +"G c #B6E6FD", +"H c #C5E0FC", +"I c #99FDFF", +"J c #AEFCFF", +"K c #BDF7FF", +"L c #E7E9FA", +"M c #E4F0FD", +"N c #D9F6FF", +"O c #C9FFFE", +"P c #D7FDF8", +"Q c #D5FFFF", +"R c #ECFFFE", +"S c #FCFFFD", +";%%;,,,;,,,#,,,,,,/>++#@@#+.+++@+@@+@#++..++.+@+++':|1gAAFAv9e}32<::||01|44cc111e777iikc77ibGSSRRRRRRQOJIIIIIDIEEwwttwwzztj& ^$ iJEIDDIIIJIIOOIOROJEEJKKOQQMSBqqddb(bb^b1^^^&=~~:!<'{!!!!~|{::<::|{:{'{'''''*'''*''+'*++.'++++@+++@@#@@@@#>@####%%%%,#@###", +"%##%%%,,,>#>###,//#@+@@@@@@++@++.+#@+@+#+++++++....*}55jAAttvAvomf71}:~~|~!~~)1~))1117c|}c1dHSSSSROOJJJEIDDEztrllhjjrrjjju2= $)= GulEEwwEIIIIIJOJJORQJJFKKQNSSBndd(((((((^^&&====~~!{{:<'{!:::::':!{:{:{:''''''''{'''*'@@+++.+*++++@@@#%#>>>##%###%#%#%####", +"%#%%%%%,##%#,,,/,,#@@++###@++++.+@++@.+@+..+.+++++..*!5ehturrhjlvvvvvvmmoobbb7^^^(((d8d88CHLLSSSNKKFFEEEEDDDztwtrljheeeffj/- $)&$ AjflEttwzIIIIIJJOJIORRQKKGHLSssd(((^^((^(^&&&&)====~-'*''{<'{<<{!'''~'''<:{'*''''''>''''''>>@@+@@+#@#,;%%#,,%%%%%%%###%#%%", +"%%%%,%%,%%,,]/,###,##++#@@@+++.+@@++.++++++.....++***-!}5erwljfhfffjhjjjjooommmomyCHNNRRRLLLSSSSSNKFFFFEEEEEwrllhrhhhffjef[-$$$)^$$ j32eEEEzwIEEIIIIIJOQJOPRRMMLSBs8(((^^(&$&$&&&&&=&&===--**_'_'_/_<_'''////__'''_'*'''''''''''>>>@@@####;%;%,>%%%;%%##%%#%%;", +"%%#%#%%%%,,/#%%#####%@@+@@@@@+.++++++..+.......*.***-!}!:43jrleffe553c5e5b7igovvGKKQQQKCvmnCLSSSSSNFAutAwtwturjjhlfefeee33[-$$&=)$$$ $4342lzEEEIEwtwEIIIIJOQPQRRSSSB88(((^)&$&&&&&&&&=&&&====--*{'{'>>/_'_><'''<<<<<<<<<<<<<[<<_>#,###,%%,>,%%###%@##%##%%", +"%#%,,##,,>###%%#######@@#@###@++.+@..++...+......**--!!!:::>,>>>>''>''<:::__//////]]/242[//]>>,>,>,,###@####%##%;;", +"#,,,/>>##@#####%%########@@##@+@+++.+.........-*****!!!!:_/<<2hh55efefjfeiiivvvvoii7pbbbdgnySSSSSSSSRKAuuuuurlhhfe55e3333[[-$$==1(($$$_{!!:fztzwhhoruAEIJIJJFGGNSSSLd88(((^^&&)&&&&&&&=&&=&====-==--****+@>>@>>_>>___'<<<>__2,,,,,>,,],###,%##%,##%%", +",,/>@#%%###%%%%###%###@#%@#@#@+##++.+++.+....+***'''|!!!>,>>>>/>>/////_'_'__/__/<2/>],,,],,,;>%,%,%,,,#,%,", +",##%####%@#%#####%%#@##%%@@#@@@@@@@++@+.+..+***''*'!~!!|::<42cc3hrrtturje3:|~||~}177^^^^((8xCxMNNKKQROJJFrglo99f55}34322>>,>//>/>'_>_'>_/'<_<__/<32/>,,>,,],,,,,%,#%,##,]", +"%%%##%%@%#####@@###@@@###+@@#+@++#@.@++>+++****''*!|7eeie43ceie33fffee2<2<:|~~~~~|77)1^^(((sdnHHCGKJORJIJErlj9iee5}344<<<<[)&&===&&$$$!---===1oh5efjjvEzAAAJJKGNSSSB8(((^^^^^^)^&==----=----=--=-=-*-***+.++@'*'_>]]]/////////,,,]]],],;%,,,],,#", +"#####%%%%%%%####@##@#####@+@@@.+@>.*++'*+''*'*!!|cfjfi333233[/]_'':[22232<<4|~|||1c)~1^^((dd66xnvyAJIOOJIIIurjb55534:<<<<_/!&&=-=&&$$$-==---==1e551b9rtuuuwAAAKRSSSBs((((^^^^(^(&&&=----=---==&=--*--**''''>_'_<__>>///////_<]],#%%%", +"%#%;;;;;%%%%#@##@++##@@@@@@##+++@+**''''''{!}9ei33e5222/[//]/'=-&==!<<<2222:34|}17|~)1^(sxsddgxnoouAEIQOIIIIwof555332<:::_/~&$&~==$$$$=-====&&&~33177luuuvmuvyCNSSSB8d8((^^^^^^&&)&=======**--*-*--****''*'_''///'_/////,//2>]///[<22[/]]]]]//];%%%%%%", +";;%%%%%%%@#%%###@@##%%@@+@@@+++++**'''':}5e5e3::<[2<[[[//_>>*-==&===!<_<242444}c7c~)~^b(dxnddxLCymvvvFJQQOIEEu9b75344<'{__/!$&=)~=&$$$&-==&=&=&&~}1}5jommmvvmmvNSSSLss((((^^^)^^&&)=&==-*''___'**'!'*''_'''>_///_'__////[2[////]>>>],,,,,//<[[/[3[[]]];;];;;;;;;", +";%%#%%%#%%#%###@@#@@###@@++++++''{'':4ce3342<<<'<__/[[2ce2///>>#,>>>,,,,,,//2[22]//]]];;;;;;;;;;", +";;%%%%%##%%##%#@#%@@@@##@@@@+@@':|||44:4::<'_>>>>>>>>,,,,,,/3e2]];;;;]/]];;;;;;", +";;;;%%;%%%%%########@@@@@@@+'''{044|::!:<<'>////[<<::!!-~-{--===&&&&&&==!:::4eij3::!~)))^^^(xxvyAuvrmlrlrEJOKwtAj771||:::_2{===-~)))^&$$-=&&$&$&&&$&^99966gggovvnxLLLSB8((^(^^&^&^&~!:{'{!~!~-!~{'''_''''{'''<<<<<222522[[/''_>>>>>>>>>,>,,,][//]//;;;;;;]/];;;;", +";;;;;;;;;%;%#%########@@@@>>'':244:::<<<<'::::'!!-=--===&&&&&$&&&&&)::4eqc2<:!!~~)))^ds86ovwEEulllruDIJKwwAmjiccccc42{===--=&&&$$$=-&&&&$$$&$$^969bbbbggmngnLBBLLL8(((^^^^&^)~~{!!!!~'{!{{!{{_<'!'::'<<<<<<242<<<<>/_'_>>>,>>>/>,;,///;];;;;;;]]]]]", +"]]]];;;;;;;;%%%%#@@###@@>>_/__<<<:<<<<<_!!!:!!{'~=--!====&=&=&&&&&&&)|0qc2<<::!!|!))^dd((66guAEEwrruEIIJAtwu77c7eieci~)&)--==&&&&&===&&$$$$$$$(b996bbb6goqqdBBBBBLBs8(^^^^^&)~~~!!~!~{{'{!!!{''':<<<<<<<<<<__<_<<_<<<_<___///_//_>'>,#,,>]]]//]]]];;;;;;;;", +";;;;;]]];;;;;;;;%#%#%@+___/_]]>_'*!!:|!!!!~~~{!~==&===&&&&&&&&&(de::3<:::|!~~}7bb^(bbb9jrtuuutAIIIOurwf}}55335511c|||~))&&&$&)=&)1^^^^^$(b666bbbbgo8gdssssBBBBsd(^^)))~)~~!~~)~!!!~!~!:{!::<<<:<<<<::<<:_<<::':'______/__///_,,,,,%,,;;]]]]]]];];;;;", +"]];;;;;;;]//]]];;;;%;@____''_/<<<>''!!!:}}}::|~-!:~~)&&====&==&&&&(8():<<2<<:!}|}171b^^^^11b9jruljlzzDJFrtr7333533:}}11cicc1^^&$$&&&^^($(((((og66bbbbgonq8sssssssssspbb^))))~~~~~)~~!!!!~|4:::!'<<@>,,>,/>>,],]];;;;;;;;;;;", +";;]]/]]];;;;]]////]]/3///_<<<<<<<<[///>'>+*''!!:}:::|!!!||~~=)=====&=&&&&(d(&&&!<<2[+.@@@#,/,,///]]]]];;;;;;;", +";;;;;];]/][/];]]]][3e33222[[/<>>'*'*<44::!!!!:!~!~~))~)===&&&$(d8$$)&&$~<<222!|771771111177775hjllrutrJe35fljllj5~~==~~}~~)))^^^111^^&&^$$$$(og6666dgoqqqxssspsBBpppdkbb711)))~~~~||||||}c:2:4<<<:::{{:{::::<:::::{{{'::_''>@@@+@++@@@@>@>/<332[/]];;;;", +";;;;;;;;;;;]//[[/[422223eff33232//[_/__''*>''<2:<:!~!|:{!~~~~~)))==&&^(n8$&&=&&&==:<<20acc111111111177555hhjjruAr552[<<<''!!!~~}}}!~~))^&&^^11^(&^($&$66g66666ggddxsppppssssdkbbbb7b1111||~bb7c4|c044::::4:::{{~!:{:'::{*:':{::{'**+++@+++++@+@@@##>@>,;,//2[//]", +";;;;;;;;;;];;]]/[2e333333333eeee3324[//<'>@'<<<<<'!:!:{:!|!~~~~)~|11bkd(&&&&=&&&&&=!:4c4011111111111}1715efhlruEwf322*--~~!|}}1~~))&&&$(^^^^^^(($$(6gg66(6g6dsBspppppssssdpdb7717cccc7oyxCi0|}||:<||:_:<::{!!!|:{::{!:{::{'-**'+'++++.@++@+@@@##%#%%;;;;;;;;", +";%;;%;;;;;;]]]//2222233fhlhlfe33eehlfe532<>_/<<_'''::<'<:||!!|~~~)1171==&&===&&=&&&&7c04401111171111}}5115efhjrAte332[//***--!!!}}~~)))=)&&$$^)^^^((($(66gg666g6bnxppddppdpdpddpkiiecc7e77oi7bpcc||{|:||!:<{:::|{:{~{{::{::{*''**'*''.++++++@++@@@@#@###%;;;;;;;", +";;;;;%%%;;;;//[222[23e3ehhfflhheeeeehfhhjl53<<_'''{'{<<<:::!~||~))17)==--====&&&&$$11^14244}71111}51}}}5}55ffhrEuee32<<'*****!!!:!!~~}~))&&&$$)))^&$^^(666gggjggbnppppdddpdpdkpkkqkii7cc77j77cp7c||!|:{{{::::{::!|{!!:{|!!**'****''''.+++@+++.+@@+@#####%%;%;%%;", +";;;;;;;;;%,]]//<33333eef33eeeefefejjfjheejtuhh3::'!!'<:24:::!|||)11)---=-=-==&=&&&11^^^1c5e577751}}}}55}}}5ehhlEhfee32/'*+'**'!!!!~~~~====)=&&^&)&)&&&((oogjoogoggspppddddppppkkkppki7cc7ij7c1pkic1||:!|!::::{::::!!!::!*-*'{*-**'>'>++++++++++@@+@@#@#%%#%%;;%;", +";;;;;;;;;]],/23flffeeee3223333e3e3ee5fjljjrumhhjje554|::::{!|||cc~---=----!~==))11ki77777efjfeeee55}555}}}3flhrIe333e3<''.''*!!!!!~~!-===&&=)&^^&=)))=))brvvoggoggnnpppddddpppiikpkkkkieiiji77kiiccc||||!{:::|{::!{!{!**-!'!*{{{**'''@+++++@+.+@@@@##%%%###%%%%;", +";;%;;;;;/33efjhhfee33ee33322[[2233e3335efhrrmvjfffljjfe}|4:!:|0||!!---=---!!|}75c7eb7171117fffee7555eee533fljhzw33223[[<''***!!::!!~!~=~~====^^)1)~~154}~9momvmmmgnndddddddppp77kkkbkkk7i7k77dpkiccac0:|~||:|:{{{|~!'*''--!*'{'{{:::'@+++@@@+@+@@@@@###%%@#%%%;;", +";%#,;,:jjrrhrllje333e3333322[2[[23e5333cefeeefvujheffjomjee10c~~!{------!-!}33ccc17b5bbb7bberttrof55fe533hlllrEr3333[[//>''**!!!!!!!!~!!|}}}15ehjjlhe}~~^^9mvvmmmmnnqdddddkkppbiikbiikkpkbkbiqqjkii77|||||44:|||!!!!<:'-*!*-{'{***|:+@@+@@+@++@@@@@@###%###%#%;%", +";%,,}hrhfefhfhlhff33333[[22222[[22332[223jfeceeooojihifffomvj7}!!{!-!---!24c5cc3355ff99999hjjtEurlrrlfeehflllrJeehh3322/'''-.-'232", +"th322[22233e2[//2//]//[[22////[//<<<<[3eie22cecijecciic0ccc4|||||}eifjjoAroh555551}~19h55155ejjjjurrrruEDzzDJwhhfhhfhlhjfe5235fff5332:::!!!!-!~=~~~=))))))=))=&^gAGuyuoyvvvvvvxxqkkdddddddgoqdddgkkb^77111c}|0a||ac|))~-!:{----*---*---**.++++@@+@+@@##@@@#<323f", +"f3322[2/[2[2///////]][//[[[////<[2<<<<222ec4443ciooic33ceccc|}||ceeeeefolruvllf5}~~~~5ff5fefjhltwurruwEEzutDArlrrrlhhhlflfeee3333e33}}:!!!!!!!!!!}~~~=)))))=)&&&^GRNAAvvvCxvvyyxxpdddddgdggogddbbbdbb7717c11cc|||a1|1|a~~-----*'--****-'...+@@+.@@@+@###%>3223hu", +"3[////[/222///[/,//]]]///[/////<<2<<<<22<234:444ciiie44c0c0cc00ciieeefjffhojmuwj1:!!}}jheehjhrAwtuutrtEEwzwwrhffhhllllfefhhff3333333333:!:!!!!!~!~)~)))~))))))~))nGQRJEAmmyxxCCyvvqgdddddggogbbbdbbbb77777c7c11ccc1)|aaa~-==--*-*-*****''....@@@+@@#+@@#<323frll", +"/]/]]]/[[2/]]///]]]]]/],//[[////<<<<<3322434400cc0:4cicc40cc00ciiifefjhjjhffjofiff1}:3jlhlrrtAwtwwuruzwzEwuAhfe3353fhllllhhfhff33223::}2:}}::!}~!~)~))))))^~~~~~)oCyFQKEAvmHCyyGyvnggbkd6dgojkbbbbbbbb77777711cc71|||||a|{{-=--=--*--*******+@@@+@+@++@}233htle[", +"]];]]///[[;]/]]],]]/,>],/],/////2<[<43332224ccc}::24|0eicccciiiiiiifolroffehfcc5eifj55flurwEwuwwurrrzzzwrrAtjeefe3e3efhlrllhhhefe332<:335535}}}}}~}}~~~}~~}}~}}}}oGxowKQFAAvGCyyCGvnqbddgdqo9bg6dbdbbbb7b7b111ci1||||~)||~~~===-*=------'*+>@@>++++.+#533hrlf32[", +"2[[[/////]];]]]]]]/,,,/]/>,/////<:'>>++@+@/lfhwzrhee33", +"//233333[[/]]]]]/],]>,]>//]/>////:<234::44eof44!!{|:|00acikkiceiifvvoohf5hh444343fifotEJIIEDtrrrttDIElrlltujfhfeeffjlrfeffhfflllhjlhhffee3533}3}333}333}3}::::}1^6xndddguKOJEFQGGFGGymgggooogggg6gdddb777b1117o71)1~~~)~~~~|||~~=-------!'*'*_>+,,/3rhrwrhff3[22", +"//[22[22/2[[[[//]//,,,/>,>>////>/_<4444444ie344|{:||||0cccckojiiiovurojhjf34:333ei5hrEJJOJEturtttDEurljfjAhffeehhhhhllhhlhfflrrrrrrrljrhheeee3535353333}::}}}1^^^(xndgdd8gFOKEFQKKKKGCmoomogqggggd68dbbb^b777gd111))~)~~||~||||1)~---!---{**'>.@/2errrrhf3e322[]", +";]][//[[/];]]]///[[[[//////'_>>///<34::|434434|||||00||acciijovovuAFvjjlh33335eefhrwIIIJJJJEwtutDAlejlhhturtwwwzwwzwzDrrrrrwzzzzzzwtrrrhljfffeeeee3ee533c}1111^^((xndg66d66uKOJFOOKKKFyxmvooggggggggdddb^bbbbg^^1^11c11}1|11||c7||1~==-!!:':<>>[[errrhfee33[//];", +"]]]]]/]][[]];],]],]//////////>>//<34224334444344||0|||10cciffjouFEFAAuAve3eeeeehrwIIIIIIIIJJEwwArhloAEEDOIDDDIIDDDzDDIDDDDDIIIIIDDzwwruurlrljhjhfeefe5555b7^^^^^^dxnd6666666mFOJKOOKOKKCCCngogggg86ggddbbbbbgb11711111111}}11}17c1c1|~~~!:<_/<[/3wwlfffee[/]]]/;", +"]]/]/]]]]],]]]]]],,,],/]]////////222:c34:<44444400|||||ccejvvvvAEJJEFFAvvjjhfhltDIJJJJJJIIJEJEtruFJOJJJQOOJJIIIJJIJIJOJJJJJIIIIIDDzzztutttrurlllhhef55517999^^^^(6xndddd666666uFOOROOQOKFGvnogogonggggdbdbbgg^)^1111111)1111111111cc111}!:/4j3[2tzrlhffe3/]]]];]", +"]]]//]];;;]]]/]]]],/]]],,>>>///[[e33344::::4404c||||||0ioGGCyuFOQOEJJJJKKKFEEEJOQOOOORJJIEzEFEJKJIIIIIIOIIJOOQRSRRRQNQNMNNGKKOOQOOOJJJIIIIIDEAzwtrhhh999999^^^(((6npddd66dd6d66gyKQRQOOQQKGCvmnggooggg6dbddvb^^11111111111111111}1177cc1c7ehl35wztlfee3e[]]]]];]", +"]]//]]];;;,,]]]]]],]]]]/]>,>>///[335e2<<<<444cccc||00ciCGAvuurEJEwttAAFFJEJOOOOOOJJJJOIIEEEEJORJIIIIIIOOOOOQOKJEAzurrtlefe3eflrtrwwzDIDzwwtttwtutwtuwtrml69((^(66oyngg6gd(ddd6666mGQRROOROKKGymmmmmgg66bd6mgbbbb1^111111111111111111c77eovoujfwIIDzulle3/]]/]]]/", +"]//]]];;;]],//,//],,],/]]]/,>///2232222244424333c400cjFFvvuuAAIwAtuuvlAFJOQQRRQOJIIIIIIIIEEIIOJJEEIEDIQIIJEwturrllhlltte332333hhffffhjlruurrrhh9h99jjllgjjgj9gg66oynggg6d6666d66666mNRRQRRQKKKGvnmgg6gggggC6bb77^bb7711^1111111111177cjvyvFtuFwhflrtzrf3/]]]]]//", +"/[///,,;;],],,]]/]],]]///,,,///23322222<<<4223ieecccjEAvvAyuFEEEwuurjlwJOORSRRRQOJJIIIJJEEDIIEJJEIDIIOJzztrllfffflluuzDre33e5lrrllffeeehe5eehlhhh999999b999996696vGymmm66666d8666666nyMRQQRROKKGymgggooggymbbbbb7bbbb77b7)11)1111177iovvuAJEJEle2[2fuwuf/]]]]]//", +"[/]/];,]],>/>]],>,]]]///>/]>/[/e332<4222<<<[23hooi4fJwvuFAFAEEDElrrrrwIJQRQQOQQQQOOJOKEzEEIIJIJKOOJJIJttrjjhefhfjlruzEDIttwzwEzwrljfefe323335}115f9997711999999((6Cxmggoogg66666ddd6gqmGRRQQRRKOKymogggomGndbdbb7bbbb7^771111111^b9ovooeiAJIJwlh3<[[,,,>],]/,//>/////3e242<<22<<<2233eruhjJEtAJFAKFEJAllrtAJJQRJOJJJJOOOQRRJJJEIEIIIEEJROEEJwurjfefhflrrrwEDJOOOOOOQJDrlffe3333::}}}~}}~11151117^^^^^^^^6nnqg6g66b6gg6gg66666gxmGQQRRROJKCvmmvmCCgqggkbbb^bbbb1b^1779gjgfecc4cefjAJAuofi53,],>>,,/]>/////23i3[<<222[2<2233eeefrEIIJJIEFKFJFjlrAKJQRJIIIJJJIJJRROJOQJJEJIIIIJJOJEIEuullhhhjtIurzJJOJIDIIIIOQzrle5f23::::!!}}|~}~)~))^~^^^^^^^^^byqd66gg666666g6ggg66nnnnCGQQQOOOJFCvyyNxqggggdbbbdbkbbggoooq9i70|:4444ijFErooiiec52<[rwhe2[[[/", +"/[]]]]]],,,]>,,>>,,>>/////223e3<[[<2223222323333etIDIIIIIEKKJvuAJJQQJIIIIIIIIIOQFEJOOROOOJJJJJJEKOIJwuurrrrttzwEKJEIIDDDDDIJQthhf325c334|:}:}}}}~}~~=))=&&&&^1^^^gngb66666ggggg666g6ggmoxxnxyGQRRROJKKGGMynnoooymqgggomomomoogia000cicccioAFmojfjjcic[22utfe[//2", +"2[//_/]]]>/>>/>>>>>]>_/<2242e32<2<2222333243542elEEzEIIEJJJOKKKJQQJIIIDIDIIIJKEEAFFJOROOQQQOJEEEOQJJwzuttwEzEJJJIDDIDDEEJOQArffh523:c3}:44}:|}|}~)~=====)&)&&&&&^6ngbbbd6d66666gggggggonnCHCHGCKRRRROOKQRGCyyyxCHCGGCvnxnddb77ccccc0c00ijAvuAvooqvvqqqieiAtmf343", +"iccccc4424422<<<::<_|a44442352:2422233efe33e322fzEzAAIIIIIORRRRQJIIIIIEEIIJKAutwFEEJOQOQRRQQOKEKRRJDEzzIIIJOJDDDEDDIEEJEFwrffe3e333:}c3}||}|}!!!~)))==~==&&&&&&&^^kd^((dd(dd((68666666gggnxnnnyyCGQRSRQRSNQQNNQRRRNMMMLLLLCxxssssppppppxyAvvGGyyxqxCxxxoqvKAvoji", +"jiiiccc0c4c0cc4000iiiiiiiijjiceccciiiiiojfffeefuIzDtwEJJJQQRSROJIIIIIIIJOKurlrutwJJIJJJOOQQOQQQRSRJIIDDIOJJIDIEDDDDEwrurlllfe35e222:43c4|}}|!:!~}~~~)===)&&&&)))^^dd^((((((((66666666d666dnssdnnnmCGRRSSSSSSSSSSSSSSSMRSSMnppppqpppppppxCGvoyyyyyyxxxCxqxvyFFAyo", +"iii44444222444ac0a0a0ciicckc0ccciiiiqqooovyvyyAKJKJKJJKRSSSSSRQJJIIJJJJFAvmomvuwwEEIIJJFEJJOQRSSSRJIIJOOIIIIIDEzDzwwrrrlhhfe3333<:::::::}}::|!!!~~}~~~==))&&^&))^bdd(((((((((666((((((((666nnnnnnvvvAKRSSSSSRSRRSSSSRMRRRMCvoqkkki7cccikoooqqqoqqxxppqxCHCxGGyyo", +"kkkiccc00000c44442444444ce44:440cciiiiiijooovFOQOOJJORRSSSSSSSSOOOOOQKAAAvvyvyttAJJJJIEEIEEJQSSSSRRQROIIIEzzzDDzzttrlrrlfe332[2<'<:2:!::}}::|!!!~}!~)~~~~)=^))&)^bdg(^^((((((((((((((bd6666gnxvvvvvvvyCNRSSSRRMSMMMMRRRRRSGyvxvvoqjjieeijfiiiiiiiikkpkoxyxxyNGAy", +"occccc00iciic0044404444cc3442:4cc43cc4ciiiijjvKQOJQRSSRRRSSSSSSRRQRQKGGGGKNNKKKQQROOJJJJJIKRRRSSSSSSRQJIEDEEzEzzwrrlhfhhf33223[///':::!::}||:!!!!|!!~)~=&==&&)&)^bdg(((((((((((((((^(9999jjjovxvmmnxnnnxCCNSSSSRNGCGHNRRRRMyvvmnvvyvoojjfiii5eeiic00ccqxqqxCCNKG", +"Gxicc40cc4404440404ccccic34000ci00ccccciccijoAJJRRRSSRRRSSSSSSSSROKKOOOOQQQQQQQRRQQRQQQQRRSSRRSSSQRRRRRQJEzwzwwturhfffefee32[3///<::4::22::::}!!!:!~~~)&))^111^^^^d(b((((((((((((((99jf999966gnnn888psnssBLSSSSSRQKFGvNRRRQCvooooqnvCCuvjiie77iii0cceiiiiiiipCGG", +"CGoccckii000c424244c444cc0c0ciiqkkpkpqqxxxyGKRSSSSSSSRRRRSSSSSSSSRRRQRRQRRRSSSSSSSSSSSSSSSSSSSSSRJJORROQRQKFAwtwrlfeee5333e332[[2<<[:3}}}}:!}|!!!~))~~~)^^&&&))^&^b(^(((^(((^^^9999e9969b^^(((888d888pssBSLLLHGNRRRRQNQQRRQGmoooqqvvoCAAmifee7eiiceeeiiiiiiickyG", +"GGyqicc04cicicc44444c40cikpppxxxxxCHCyxxqxCNSSSSSRRRRRRRRRSSSSSSSSRQQOOORRRRQQRRRSRSSSSSSSSSSSSSQOOJOQKOOQQQKAtwuhffe33233e332[[[<22/<:!}!:!}}}}1}5}1~)&=)&=)))^^(bbb9b6^(99b77b9^^71^(($$$$$$(8d8dd88dsLLLLHxpqvFKQRRQRSSRSNGxoijjvvmFKuoee7eiceicikqckiicic0iC", +"yCKyoqc0424c4ccciickqxxxxxxppkkkppppqppxHNRSSSSSRRRRRRRRRQQSSSSSSSSSRQQOOOOOOOOOORSSSSSSSSSSSSSSROKFwuuvyGKKQQKFuffee3ee3ff2222[['!!!}5f91)$=&$$$$$$$$$$$$$$$$$$&&&&$$$$$$$$$$$&^k7bbbBsBBsxyvo7c11|17ikxHgmyAFFKKFKKQKGCqqqqqjvHn02<22[2224", +"2ccvKRRRNHGCCCxxqiiiiBMHyGNRSSSSSSRQOJFEJOQJIIJEFJJJJQOQRRRRSRRRRSSSSSSSSSSSSSSSSSSRSRRSSSSSSNRyfiefffffhjojjolifhhfe5eovGQRNGAmjhf333:[<<<:1oc<''>>//2551~&=$$$=$$$$$$$&$$$$$$$$$$&&&$$$$$$$$$$&&))&^kkb7dBBBsspyvo771117kbnNd7iomwJJJQRNKKCkkkjoHH7>-&&&&=$&&&$$$$$$$$$$$$$$$$&$$$$$$$$&$$$=)==)^pdbbsBspskkyvq77771i7kNp77c7jtFJOROOJCojovNvc2<<__<<<2[//", +"e3322floGNRRHCHMSMHHKNRSSSSSRJJFKKAvlolwORJJIJJJIJQRRSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSRRQNRSNNRGHGe35e5533e55fhmlvflvlofie52<2>,_-=$=$&&$$$$$$$$$$$ $$$$$&&&$$$$&&$&&=&===-=^pbbdLspsp7kCvk71^17bbyC7i7ceooAKOOJJKAAGK94:4c4:_//[[/24", +"ee3323jljvvoxHMSMMRSSSSSSSROOOGGGyoojjvJRROOJJOQRRSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSRRRRRNNyojv533333efe35ehjljfficccc4<<:<::!:ciCMMCq}:::!!!!!-{!{***-*++*+>>*-&$$$&$$$$$$$$$$$$$$$&&&&&&&&$&=====&===&(pddsLssxk7jyvkxd1^i7gH7kioojjmruNOJJKKyjic444444_/_///2", +"c433c43jhfejjiiyMSSSSSSSSRSRNKQNyxvxvCKRSSOOQRRSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSNQGCvffov55efeeeff5ee33323c_<<<44_4_2::||::|cxHMHqc|!:|!!!!{:--***'***+>>>@.&&$$&$$$$$$$$$$&$$&&&&&&&&&&====&&===&&^pddLBssp77jyvCGb1i77Gkkiijfmuj7jvHxm97ccicc044c42_///4", +"2e3444ciffhevoHRSRSRRSSSSSSSSSSMHHHHNORSSSRQRSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSMNCyAujiffjove5ef533<<2[[<][[<>____<44::::::::::{{|pxMHxb|~|!|!!!---*********+>,+-=$& $$$$$$$$$&$$&==&&&&)=&=&&&=&&==&&&bpdsLspxk7ioCKQm177iCgi7jooug777fj!|0440444ci000044223", +"e2222243fjuGRSRQQQQOJFGHMMSSSSSSSSSSRSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSQNCqfhjuffffjfij2<2<<<<[/<<[[/[[>@*>@>>/<__/_:_:4:__|:{|7nHMCq7~~~!!!~-!*'**-*{**'++>@*=$$$$$$$$&&&$&&=&&&=&&&&&&&&=&&&&&&&&1kpLBsspii7vGNKg77kyoiijvto}}75j5~{{:444::440icciqooe", +"i33e323jyMSRQOOQOJJAwvjjjppxLMSSMLRRSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSRKGvrjffhuhe5c3340c<<_/>__//<<<22<_*''*@@@>/_>>_____4_a____|~|pxMMxd1~~!~!!-!***---***'**+>*-&$$$$$&$&$&&=&===&=&&&&&&&&&&&&&&=&bksBBspkk7bCGQGbijmyiilwu7}11bj1'*{{'_:::<<4eiijjoyv", +"voiffvMSRQOOQRROEEAwlic44cjoqqxMMSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSRRSSSRNGAlolfe3je<<<<<::|:{<__'''>>//,//>@'*>+@>'+>>@+++_*_____4aaa__||bsHMHqb~!!~~~!!*----*****+++>'-=$$$$$&&&&&=====&&&&&&=&&=&&&&&&)&bdBBBsbi779AQQvjojHjjwwe7111f9:''''/>>'_4<<24ciivyy", +"vvyHMSROJJQRQJIIDFufc4|4443iovvoxyHRSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSRQOQQNGvljjfii423f[_<<<::|0|:{'!'''>/////@+++++.+>@@'>#@++@+'>'''_{_|_aa_|{1pCMMyd~!!-----!-------'-*+''''=$$$&&&&===&==&&&&&$&&&&&&$&&&=&^bsBLBpk777vKQKojgGjuE971}579e''___/_>_'>>_2223ifvv", +"NMSRQOJORROIIIIEIAicc0004cecijvyCCGRSSSSSSSSSSSSSSSSSSRRRRRSSSSSSRRQKFArof35333442////++..@*@++@@+@>>@++@@'>++@+''____aa_aaabnHMHq1~!~=---~---=---.'**'>>*-=&&&=====&&$&&&&&&$&&&&$&&&=&&^bBBLxkk779AQRGjoGjFo}57}}555{*_///>_>_'>'__4i5efj", +"SQOJORRROJDIIAwuuueic004ciiiiijvFKRSSSSSSSSSSSSSSSSSROOJJJJJIJJOJFAvjjjee3222222>/'*.+*@@++@@@@@+@@>>>@+@@@+++.*''{__{{|aaa7dxMNnb1}~)===-!~!{---**-**'__*===&&=&&$&&&&&&&&&&&&&&&&=&)&^dBLLpik7ivQRQvgFmm1}77}}5e}'''>>'_>>>'>>>/23eyHM", +"OJORRQOIDIEurtlhejfcccciiiiiiifjmKSSSSSSSSSSSSSSSSRRQOOJOJIIIIIEwrheeie332@@@@@@@@+++++.+...**+*{{{||aaabsHNyk1~)))=---!||1---*'**_/>'*==&=&&&&&&&&&&&&&=&&==&)~~^bnBMBkki7oKSRGoKr7|}e55555~*+>>*'_/>>>>//3fyMSRR", +"SSSSSOIEErjojovjeeoeiiijjifiifijAQSSSSSSSSSSSRRRQJJJOOOOJIEJEwtrre323e24[///_//_/i<<':{:{!!~--~!*''!''<''.*....+.+@@@++'>@@@>@@>@++@+.+@++..++**{'{|||aa7pxNHob})=~=-~-~~|~----*'///<:*===&&&&$&&&&=&&&=&&)))~)))bxLSsiqiiyRSMvFf5|c7fe55e!'>''_>_/<[33fyMSSSRRR", +"RQOOOSJtliec4covofjofiifjjjiqjouQSSSSSSSSSSSSROJIIIIIJIJJJAtvjjfe32/2322[/__////c<_'{!!!{{!!={!--'!!''<'*.-..++.++++++@@@@@@@@@>>>@.++.@++.+....**-~{{|{)a7knHNyk1~~~~!!-))~---*''':<_''_'<<25oHSSRROOORR", +"KIDIORAlj3e44c5oojovyojjiiijjoAKSSSSSRRRSRRROJJIIIIIIAwtwvooojef54/[<2[[///___/5c{'{:{!~!-{!-!!--{-'''**..*+..@+@@@@@+++@#++#@#@>@>+++++..++++.....***--{|||7kpxMCq7}~~~~~))-!!!*{!:'__/>_--&&&===&&&&=&)&&))~~)))1sBSspxqoGRRNye7}}7ff5e:>>'_<<25jHRSROOJOJOQRO", +"zEIIIGeiiiicccefmvmmuyoqqfjjvAKSSSSRQOJJKQRQOJJIIIIIwurlfeeiiiif42//____<3:@+..++..+.........**-{{{aa7dxHHxg1}~~~~~!~!:!!{'{''_''_{-=&&=&&&&====)=)~~~)~~bBLMpyvoyRSSv7i}cefh5h<''<<3fyMRRQOJOOJJOQOKE", +"IIDEw32<<44eecccoAuvmvvovvvvAFQSSSROJJEFFJORQKJEEzttulfe52<3cecc42//<@+.++.++.+........-.---{{|1bksCHHmb71}}~~|:!!!!{{'''''__'*=&&=&=======~)~~~~~)xBSxxCvyRSSm7e}ifjhjh<<:5qHNRQOJOJJJJOQOEzwD", +"zrffe/:<[<2<4cefoAtrjrAAuvAFJQSSROOOJFAFFJJJKQQKAuullhe32<2444c42___<<__<<''_3}{~!-*!------~!~!!!'!!--**'**++++@++++++++#@++@@+@#@##@@@@++..++.+..........=-.-=-{{|1bsxHHyok71}}}}~~!!!'!!'{'____*==&&===)))~~~)~~~-^HLMqCvyNSSC7f5efljl5}qHNQOQOJJJIIORQJEEwDDI", +"3e33[/<<<[<<[<3ejoAAmovwuAEJOSSROJJJJJJFJJJAAFNRQAvjjf2#@+.....+..+.......-.*=----~|1bsBHNGvoi771}}}~!!!{!-!'<___/*-&&===~~|~)=~)~~-nxSCyCoCSRMefeejurAyMQJOQOJIIIJOROJwrjruzzr", +"222[<<<<<<[/[2ee5eoAAruAFEEJRSRQQOKKFJJJOOJFAuvCRRKof3<__<422<22<<<<:<<:|:_<3:{!!!:{**------~-~~!!!!!!!*'*'***+@'+++@@@@++@@+@@##@@+@@@#>>>@...+.++++...-....---==-==~)17pBMNGGv9757}}|!!!!!!!'**''_<'-==)))|!~=~~-!!)HLMCxqxSSM7oouEFNQOJQQJIIIJOQQJEtlhhrutth3", +"2[2<<<<[<[[<3332323ltrlvEIJQSROJJJKOKJJJOKFKGyvGGGMMC4<:<<:<<<<2<<<:::<:{!<3<:!!!!-{{*-===--=~)~115}}}5:'.'*+@@.+.++@@@@@@#@#@@#@@@+++@+#@@>++...+@...+...-.-..==-*----=)17dBHMGGvmf7c13}~!!:!!{{**'''/<~~))~!!~~~-~~~dBSxxqvRSMfFFNRRQOQOIIIIOQOJIErh5hhlffhre2", +"[32/<'<[//23ee333333rhfjtIOSROJJJJJFKOQQOKGGNKQKyyyRRxa||:<<<<_<<<:<<<<<:_3<'{{{-{:!-----~==~}77}}~!15!:'**+.++.+@@@@@@@+@+@+@+@#@#@@@@@@@@#>@....++.......-.--===---.--===~17sLMCvvuo917~}}}:!!''{-'''<_<~~--~~!{{{!~~HLBxxoMSRGSRRRRRJIIIJQKIIDzlfefef32233233", +"/2[><'@+@.+.+.........------*------=--=~akBMCoomvje71}}::<:!{{''{'/<'++.+@@@@++@@@######@#@@+@##+@@@@++#@+@@+..++.......*-----.----=-=.--=-==)|sLLCofjjhhhe5}}|:::<<@@@@++......*....--.**....--!!~!|}~-----)dBMMyoi755555efeifjjvAKJJQRNKOGMSRSSSSQREul97}}}~=-!'!!-{{<'<<<[[[/23", +"[////[f33e353333eeerOQQIwuDtrrDDtrutEzljhjmhfhfee553}4332444c3:<:::4c4<:{|c|||~!|}!!~~~!|}}|---***-''+.++++++++.+@@@@++@@@##%##%#%#@@#####@@@@@+@@##@@@@+**+*.****...**....**!!!-*!~!-----=-)(nMMCofjfeeeifjlAFKKFwEFFKJumHSSSSSSSKm91}}~~---!!!!--!!'<<@@@>+..+.******..*-..-*!!-!-*--!--**-----~bnLRGyoiifjrFJFFtAAFFJJwtwwySSSSSSRm1~~-==---'{!-----''''''<2[2eh", +"2[2[[2fehf32[[2eefrIRQItlhhAJuwAJJEAEEGyxnqvNGoojjfiec3c444<::4343i4440}||}}|||!!!{!!!}!!!-!*-**-.*.*..+.+@+..@@###@@@#@@###@####%###@@@@#@#+@#@+@+#@@+@+@+.+++'**++*+.-*'''!!-*-***!***''{{!~!~~^nMRNGyGKFArmmAFEJEwutEzEJMSSSSSC~~====---'------'''''{'<<22335", +"233333je332[[23eflEJSOItlouvFJEJEEEwwEJOvyoqvFAvfieiee5c444::::4ce4:2:}}}|:|~!!:!!~!!!!!''!-_'''+**++++@##@>%%;;;;;;;;];,,,,%%#%%%@@##@###@@@@+@@@@@@@++++>_+.*'**'''>>_/<<<'<'''''*'**-**{{{~!~~-~^xMSRQAutuAEFKJAuwAEEIIOSSSSSS)-===-==*'*=---**'''<':<<223333", +"3e3422fje2ceiiijvJORROJwuAvolKJEFEEAtwIRyvofjoAumjiffecc2232::4e54c44:}|}4!!:}!!}}:!:''''*-'>****++++++++#>,;%;;;;%%;;%;;,],;;;;;;;;;;,,;,,#+@+.@@@+@++.++++''@'_<<<<:<<<<2<<<<'/__<<<___'_:<:::!|7orvCMSRKNKJJJJwrrttAwAJRRSSSSH===-----------'*'>'<<42<<225333", +"yxppccoyyovoqjjjFJQROJIEtmlrAuGJAzEzAwEOOAmhjfgtulrojhfe534:ceoe44c44}4::::::||}3}:!*****--***-**..+*+@#,;%;;;%##%%%%%%%;%;;;;;;;;%;;;,%,;;],,,>>>,@@#++++@+''.+..-**-!'!!'!'!!!<<<::{<<<:<444cejuurommuNSSSSROJJFEAAFFJJQNGMSSSd-----------******'<:cca|0cijovC", +"qki77cqjovofoovAJJSOJIIErlurhhlFEztAEEJJJOwjjjf9ttrtwwrojefoule33cc33:::::!::!}}!:!-'*-*-*-**.*...++@>,;;;%#%##%#@#%###%%##%%%%%%%#;%%%%%;;%%,,,,,],,,,>>>@>@'''++++++.******-***********-*!!:5jj9b5eijmuFQSSRQQQKEAEJJJQGyxMSSSi:'**--!---'--*'*-!7xCHBLSMMHHHC", +"oiij7ivojottvruJJQQJIIIEutujefjjAJzzDIQJOOOAumjjjutwEAuvvvvjec5544}!!|:!!|!::}!!!-'!-****-.**+*+*.+>>>,%###@############%%#%%%%;%%#%%##%@#%%%#%@##,,%,,,,,@+*.+**''''****..**'--.*-!}}}}~~11119orwuyMSRRSSQKJJQNyyvxMSSM3332<<''*--***-~}bovoojjoGGCvvyy", +"ooojffrjhjluwwEJOROIIIIIIzrljrlhltJIIONKFKJKug99b9bjomoji71|}}}~~~~!!!!!|}}}!~!~!'*!********..*..+@>>>@##,,###@#@###%##@#%%%##%%%%%%#%%##%%%%%%%%%%%%,,,,>>>>>///''@>*''+''**+*''*---'<:|!~~~~^1bjojj9996yRRRSRQRRyvoHHMRSSM33333<'<<<<':}7jfjojfhjjoojyyvvv", +"olfbe9ljlllruIOORRJIIIJJDzwttrujhhjvAvrrrAAKKmbbb^^b^^^^^~)~)}|~~~!!~!~}}}!!!!!!**'!-**-.*...++*+>>>@@@#@,####@####@#######%%#%%%#%%%%%@##%%###%%#%%,,#,>>>>>>>>>/]//////<:/>+'*+''+'!!!:::!!!~~~~19holf5559fbmHRRQNHHGxqoxCxSSMnoe3332:}}7ijojluttullrrjejoCvmu", +"wwrllltrruuruEOOROJIIIIJztutulje5b5bbb966oovKNn(bd(bb^^^^)~~})~~)~~!~}~~}!:~!!!-*!*-***..*.*'+*>>@@@@@@@+@@#@#@@@+@###@#@######%;%%%%%#%%%%%%%%%%#%,%>@#,>>>>>>@#>>>,>,,>>>],>@'''--:::!!!!!!!~~~59fhh577eee579jCSSGmvvGHyCxxMSMCGAytwAAFEEEzwEEEEzwzzAwtllfvwAE", +"wujj9jjejjffjEJOOIIJIIIOvjhfe557717bb66(dggqnCMn(8dd(^^^^11)~~~-=~~}~~~~~!!-!!-!--**+'**.*.-'@>>>+*@@@+++@+@##@@@#@@###@####%%%%%%#%#%%%#%#@#%%##%#%,#>,>,,>>,>>,#>>#,,;,>>],@*''*!:!,#>>>@@@>,>@,>,]]>>,,'''''!:!!!~!!~=}}7ifff77}55eefjvvvoijqCSNGGAGRSRSSSROJJEEEIIDEzzEEzwuturjrrrllhflut", +"1~)&&^<<2455tEJQIArrrlrrutulojoruuuvrmmmmnCCLLLBd(^^1b71^^1)^~=)~1~~-~~~---------=---**..'-'*+++@+@+@@@@+@@@##@@@@%%###%##%%%###%%%#%#%%#%;%#%%##%#>,,,,,###>####,@>,,>;],]>>*'!''!!-!-!!!!~}55eee7}}5c}}5hoCv7ijojjnMRRKFFGRSSQQOJJEEztututrjfhhfh95555555}~bfh", +"!&$$$&<':<<3zEJJEujjhjjhhhjuwumgggmmogggggpsss8d((bbb111711~^11~~))~=--~~-=---!----*+-.-'-**..+@@@+@@*+@@@@@@#@+@#####%%%##%##@#%%;%;%%%%;%%%#%#@,,>##>;#>>>#,,###>>,]]]]/>>'''''!!!!!!-!~!}c3e5571}3c}3eioo7bikiiiekjHRRKAvCNSROJJJEFzwtwwEtrhhfhe}4<::'''*=&c3", +"$$$ &<':2####,###@##>@>>,,///'*{-'*-*'*!!!!-~}}c35}}:}533ceii5}|1iki7cejeioNRQFFFRNKJEtrurltwtrrrjhje2:<<::<* $(", +"$ &<<<23tDIQIzrjjffhhfh99googgggmnnxxnxnnggggoo9bb117^111~~))==~--------****!'--**-'*..**--...+@@@@++++@+++@###@@+##@%#%##%%;%###%##%%%%%%%,,%%%%,,%#%#@#,,,,@>,,,2h<>*'****---*'!!::|}:3}5}}}2244ce3}4cie5cccikivjiiekvKOKNSNAAEJJDtrrlrhhe32:'{!--=---& $(", +"$$$ &[/<2hzIIQIwrljhhjhffffgoooooggggqxxBBddgggoggbbbbb1^^^)~~=--!~-==-----.---*!!*****-**......++++@@@++@+@#@+###@+@####%###%;%%%%###%%%;;%%;###%##,,#,,##,##,,,,,25''@'''-'--'''<{:<<442334}444c4c4333c777cccc4cqvoiiiikyCAQSSNJJAEIzwwurf35322<'!-=-==-= (", +"$$ &2[23jDIIRDwrllhjhjjjjjoooooggoooqnBxnnxyvgg6dbbbbb11^))~~~-{----=-!----!!!*{!-*-****+.+...+++++++@++@@@@#@#@##@####%%##%%%;%;;%%%%%%%,,#;,%>#,########%%,,,,/2}>@'>''*****''<<<22433eeec3343fc3<:!|))1)))))}}7poiiiikxvFNSSSOJEAAAAtrljhf3322{!!!!-*'- $", +"$$ $4325lIIIRIztrrljjhljojjhjjogooovxCxoqovGmoj9bbbbb^^7^))))==--------=-!!!---'-{-*-*.***+..+...@+@++@@@@++#@@+#######%%#%#%%%%%%#%%;;%%,,%;%,,%;,>#%%;;,;,,>/[2++@+.**++.-***-!!:|:<<<* $", +"$ $:e23rIIIQIEturrlllloggjjmojjooqoxCggggjoqii9b1111^^11)))))==--**--~|~~!{**{***'*-**.*.+....+.++++++@@#++#@++@####%##%###%%%%%#%#,;;%%;%,%####%,##%#,%,>,,/2:@++++.++++*-''--!!<:::!-!~}7|~!---))))))))))))~~}}1bxppnxokgMSSRQOJJJEzEzwzulhfe522<* $", +"( >/2'@+@#@@++@@>'!-'':!!!!~}}1~~--=-===&&&))&)))))~~~)}~}cqxxyxqqqCMSSROJEEEDEEztwturjhee2<,* ", +"( 'eljuIIIOOIEztruuuurmmmogomonnxHx9jj996ljgjf7c111111)}~)~)-===)|---****-...*--..-.''***.+.++++@,@@@+#@@#@>####%#%###%%%%%%%#%%##%%######,%##@#@>####>,><:'+@@+@+#++@>_''''{'*-~c7~=--==&===&==&&&)==))))))))))11bxyxxdgdBMMSSRROJEEzDEEwuuurljf32[<[[! ", +"$ ~etEDIIIORJDzEtuuttuuvmoommxyyHHki77ijoug9ieb1111711~))=)=-~-~~=-***--**..-.*.+....-.'*..++++++@#@@+@++#@@@@@######%%%;%%%;%%%##%##%#######@####,%#>>/['@@@@+@@++++@>>/_''{*~71~----=-==&=&====)=&&&)))~))^))1c77dxMxpqnLLHQRQQQROJDDztwrrrrtuuhh3233! ", +"$ ~elwzDIIJOOIIDEwwwwwAuvmmmmmxnxpb7e7efeibbie777111|c}~~~~)-~!~~-=-----**'***.**.*....-'*-*++++.+@@@++++@@>@@@#@@#%%%%%;#%#;%%%%#%##%###@#######,,,>><<@@+++@@@@+++@@++_'''*{k|--{---=--====&)))&))~~))~~~~)~)1c17kqNHxqnMMGKOQOOJJOOOJEwtrrlhlrulh332{ ", +"$ *hjwDIIIIJQOIIDzzwwwwAAAAGKNMLHdbbbbbee71771771111|}1|~~~~~~~)~~~-***--.*.**.*.-.......+*'@++++@+@@+++@+@#@@#@##%###%%%%%%;###%%%,#%####@#####>,>>>::++@+@+++@#+@+#@++_'{{-{p~{{---==^^(^^11777bb999bc<::||~|1117kpGKynnLMHGFKJJJIIIIIDEIFwtuljhurh22| ", +"$ =hutDIIIIJJROIIJEEEFAAAFKQQRSSxgd66bb17cc5}c1c}1}~}}~~c}|||!|~~~{-{---****'*.........*++.....@+@@#@@+@+@@@@+@@@#%###%#@%#%%#%%%%%,#%#@,#>,%@>,>>'>>><<+@@++@+@@@+++.+..+.+..*''{{bxxk|~~~~}1cciiiic5c77c433<42444000cii7mGHxMNHyAKEJEIDIEDDEEttutttzDDJFt} ", +" 'uJIIIJJJOOQJORJIIIEJJKKKNNRSHqoggb(bbbb^)1|||{:::|~~~}~}|:::::::'*{{{'{'*''''*+.*+++++....+.+@@+.@#@++++@>@@######%%#%#%%%%##%##%%%,,,>#>@%>>'*'''*''+'*++.+++++@+++@##@@@@#>@#%##%%#%######%%%%;,,;;,%,,,,#;,>,@@@@@#@++@+@+#@+@@@++.++++@@.+'::1oFyAuoi5}422<::|0c|44cccccce7iiikkieijCSSSNQNQQQOJJIIIIIIEEzzwAzzEEwr! $", +"$ $GuuIEwEDIIIIIOOIOQRKJJFKKQMSSnpdd(^(((((^^&&===-~~:'!::'!!::::::{!{:':{'''*''''''''+*+>@**.*+*+++++@@##@##>@#%##%##,#%####%%#%%%,,,,,##,#>,/>@+@@@@@@.+@++.+#@@@+@++++++++.+.*|55jAEAAuvvjje}|::!~||||~)}1}111177a|cc7xSSSSRQQOJKJIIIDEztrljlhrrrrruf! $", +"$$ 8AleAwttwEIIIIIJOOIJQRQOKKGMMLss8(((^(((^(^&&&====~~{-'*''!<'{<':!!''~:{'{{{''_''''''''+'''@++++>+@@@#%;,,#,,%%###%%%@%%##%%#%%%%%,##%,>,,//,,@@++###@++++.+@@++++@@..+.++.+...*}57hwtrrolmuvvvmoogg6b1)}~))^^)^^1((8nxHSSSNQKKFEEEIEDEEtwtrllhfeefhj3' $&", +"$$ 8j33lJzzwAIEIIIJIJOOOJORRNNMLSB8((((^^(&&&$&&&&&&&====*-*'_<_'_<<<<'''///___**'''***'''''+''>>>>@@@##,#;%;%,>%;%%%%##%,#%%%%#%%%%%%#%%,,/,##%,%#@+#@@@+++.+@@++..+++++.....++****!}5frwrjffjfjoooovomomvmmomvyyHMMSSMLMSSSSSNKGEFFEzDDEEurrjrhjhffhef3'$$$&", +"^$$ &3342FEEIEEEwzEIIIIJOQRQKRSSSSB8(((^)&&$&&&&&&&&=&&&===---'{''_>>//'__'''_<<<<>>>##,###,%%,>,%%#%##@##%@%%%;%#%#,%%%,>],#%#####,@@@@+@+@+..+@++++.++......*.***-!!~|35julfhfee5}55ee9bibqooyGKQNQOKyxnxLSSSSRNFAttAzwwttrljjlfehfeeee['$$&=", +"1&$$ &_:24eAwwEEzAurwIIIIIJJKQRSSSSB8((($^&&&&&$&&&&&&=&&===-==---*+'''>>>,>/_>'''''{!::>>,#,#,,,##########%;;%#%%,,#,,],##%%#######@@@#%#@@++.+@+.+............**-!~!::::eree5e533c57c17iqnvvAAAFKyogoooyLSSSSSSNGuwwAwAtrljhhjfeeeffe3/'$$&=", +"1(&$$&_{!:4uwuztjjruAEEIJIJFFFKNSSSB88(((^^&&&)&&&&&&&=&=======-=---***'@>>>>>>_>>__2//>,],,,>,,],###%%%#%%#%%%%,,,,>/>>@######%#@#@@#@#@@##@@++++.+.........-*****{!!~:>>>>_>>>///____<_'<____<2@#%####%%%%######@#%@#@#@+##++.+++....-..*'****!!!!:_/>/_:jjjfjfjfjjoovvqkccc7bpdbbbd6nLMMSNQSSRRQuuururjjff55353332[[{$$&=", +"))$$$$!!--=-9twlhf9jorAEJJJKQNSSSSSB8((((^^^(^&==========-=-===-==.****.*+.*+@>,,,>//>/>'>/'''__<____/_<3<,,,,,,]],,,,%;,##,#,,],>#%####%###%@%#%#%%@###%#@##@+@@@@++++.++.+*******'!!!|<<<444c3fvjvuruvjfc0|||}117bb1^1((8nHxLRNKKRROOKFrlll999e5cc34322[[:&$$=", +"=)&$$$!---===9lfeefjjuzEEEFKKGGNSSSB8(((^^^^(^))&==--=-=-----=-=-=-*****'.++>''>>>]]]/////////,>,,],,],,;%,,,,>,#%%%##%%###########@#@@###@@##@@@+##.@++++++****''*{|}cc7c443eei3ehjlhf322<<||)|~~|77)1)^(((snnCMGGKJQRJIJErgo99fe5}}4322<<<|&&&=", +"=&&$$$~=----==9e55b99rtuuuAFAGQMSSSB8(((^^^^^^^^&&=-----=---=-==-----**''++'>'{'__,]///////_<+.+++'+*'*'**!:|7iffeee23322//<':[23242<<4|~||||71)1^^(((d66nxxyFJJOOJIIIur99555c44<<<<''//_'_/]///]//<///[//[[2[//,,]]]//],;%%%%%%##;;%;;%%%%####@@@@#@#@@@@@#@+++@+.++'''''!|15eccei33222[///>*-==-!,>/>,,,///<[[[22//]]]];;;;;;%;;;;;;;%%%%###%###@+@%%%@@+@@#@+++@+*'''':|}c7e7}}2<22<[>>-==&===!<<<24<444|17c})~)b(dsnddnHxmommvFJQQJIIEu9be5c442<::__'**--{'__>__'___>_'___/[/2232[//>>>,>>,,,,,,,/<2[['//2222ejc///>>>>>>>>>,,,,,,]2ce[];;;]]]];];;;];;;;%%%%%##%%###%@@##@@@###@@+@++'::{|44432::<@>_>>>>,,>,,]/[<[]/];;;;;][];;;;;;;;;%%;%%##%%#####%#@#@@@@@++>>{|044|:!:'<<'/////<<<:'{-{!{**-==&&==&&==!<<<4ceje:||~)^)^^^(nCvCAvvvmrrmmEJOQzwto71c||::://_=~&{", +"-=&&$$$&==&&&&$$$$$&1999bb96gmvnnxLBLLLn((((^^^&^^)~|:!!!~~{!~{!'''_<''':{'<<<<_<232<<<<___>>/>>,>>>/>,]][//;];;;;;;/]]];;;;;;;;;;%%%##@%##@##@@@#@>>'':<44:::<:<<'//]]/<::::!!{-=---==&&&=&&&&&&&~:::5ji4<:!!~)))&^(pdgovwFwulllrrDJJKwtAoq77c00042:====", +"===&&&&&=-&&$$$$$$$$^996bbbdggoggsBBBBLLB8(^^^^&&&))~!|!~~-{{!{{!:{_''{:<<<<<<<<<_[<<<<<<<<_<___//__//>>>>]>,%,]]]/]]]];;;;;;;;]]]];;;;;;;;;%%%##@@####@+>____<<4:<:<<<>'!~::!!'-==-{====&=&&$&&&&$&)|4ii4<<<:!~|~))^dd((66muEEAurrrzIIJFtAAb7cc7eecc|=&=~", +"~~=&&&&&&==&)^(^$$&$(9966bbbdgogddssBBBBBxpd(^)^))~)~~!~)~~!!!!~!!!{'<<<_<:<<<<::_<<__<<:'{___'__//_/>_/_>,,,,%,,,]]];]]]];;;;;;;;;]]]]];;;;;;;%%#####@>___/<<<<<:<<<_'!!|:!!!!~~~{!~~====&=&&&&&&&(^bq::3<<:!|!~~~1bb^(bbb9outwwttwIIIKwuwh7}c55c5ec1c|~", +"c111^&&$$&)&)((&^^(((g666bbbbqnngssssssBsBspkb^^)~~)~~~~~=~~~!!!!|4:::!{__24c7<<<2<:'{::'_'''<<'''____>>>,,,],,>,;;]]];;;;;;;;;;;;;;;;;;]]]]];];;%;%;@____<'>>''!!!}}}::|!~~!!!)=&&===&&&=&&&(8d):<<<<<:|}!~177b^^^^71b9lruljlEDIIGutr53535333~~11c", +"c1777b1^&&)=)&(&$&$$(mvmggbbbqoqpnsssssssssspkb11)))))~~~~~~|!||}||!:::c333ci00:::<::':{:'{{:_'*{'___+>++@@@,,/,///,]]]];;;;;;;;;];]]];;;;];/]//]]]]]2<_/_<<<<<<<<[////>>>*''!!:}:::!|!!!:~~))=====&=&&&&(d8$))!<<2<>@@+.@+@@@>>>>//[32[/]];;;;;;;;;]]]]]]]]];]]]//3c332[[[<<<<>>'>*'*':}:::!!|:!~{~~))~===&=&&&$(8($&&$$~<<222!|771771111177775jlrlrutuEo5fjuljjhf}~~)~~", +"~}~)~))&&^^111^(^^$$&(gg66666gggpsxsppppsssdkkbdbb7^1))}:|~}10}||c00::::<4::::||{:{:::{{{:''{::{'+'+++@+.@++@@@@#>@@@>>]//[3]//;;;;;;;;;];]]//[///[223233fe3222[//[@''<<<''::!:!:!|!~~~~))|1117kd$$&&==&&&&=!:**!~~~}", +"}}}})=)=&&&$&))^^^(($$(6ggg666g6bxxppddppdsspddpkciccc7e7eoi7gkcc||!|:||{<<{:::|{:{!{:::{:::{''**'*+++++.++@@+++#@##@###;;;;;;;;;%;;%;;;;;;]]]]/[322233effhhfe3efffjf332<'>'_<:_'''':<{<:!|!!|~~~)1^77^&&&===&&=&&&&)c044|1111171111}}51155hhlutFf333[//'*----!!", +"!!~~~~~)&=&&$&))^^((^^(666gg69ogbxpppppddppdpdkkpqii7ecc7bi77cp7c||||::{'::::{:{!|{!!:!|||***''****''.+.+@+++.+@@@@###@#%%%;;%;;;;;;;%%;;;;;]/[/[3[[233ellhfllhe3e3fhjhjff3[<<<''''{!:<<::|!!||~~)171&=--&===&&&&$$(b^14440|c111115}}}}5155efhlwFfe32<@.++@@++++@@@@###%%#@%%%%%;;;;%%%%;][[23hfllff33ee333[2223333e3333fhjuumrhf9hljfe7}|4:|||0c}-!---=----!~|77c7ii7711115fffee55555fe5c:5hlhrEf32232[<'''**!!!", +"!!!!!~~~}!~~115f9jghe}}})1omvmvmmmnngdddddkpppb7kkbiikkkbkkbbopki777c|||||4::~|!~!~!<'{-!{--{'{{{{a''@@+@@+@+@@+@@@#%######%#%;;;;%%;;,3hrrlrljhe3333e333322[[2223e52333eiiffjuujfefhooof75}|0c~!!------!--|43cccc7b51bb17bejtulh555eeec3ellllzA33332[/<_''**!!!", +"'-!!!!!:}:}55e5he1111))^&&(grmmmvynnngqppdppppbikikikkkdddkbbxqdbbb777ac0||::|~~{{{@++@@@++@++@@####@###%;%%%%%%%,>}rrffhhhhllff333332[2232[[[[23332422ffeceeovojffiifjooof7|!!!!-----!::3cccc3c7fiibbbb9jjuzurllljfe5fhllllzlefh32[[<_''-**'<", +"'332flrh32/]];]],/[/2]]/]]],,]],,],////////[<2<<33322244ccc|:<440eicacciciieiifjoloffifjec57iff53erlruzzttwwrrrtzzztuuAlffee333efhjrllffhff", +"fee2233333535c3}}~}}}}}}}}|}!}}}}vyogguQQJEAAGCCGGynggggggoo9bggbbbbbb77bb^1117b|}1|~~)~~|~{~~=----------'+>'>@@@@+@'fffrwlh3333[///////[]];]]]]]]]],,],/>,>////<2<[2343434ei7}||:|4400cpkic7kjiicefoouyvmfje4435efjoohtEzDztwwuurruzEwrruErhfeffeeffhffhlhllrff", +"fhhffffe53533}3}}}}}}33}}}::::}11nxgd86mFQJEEGNGGFGCmngggmoogkggggdddb177bb117qb1))~~~)~~~|||~~~=------*''*''/@+#>>3llrwtlfe3222[[233333[//]]]]/]],]>,/]////>///<:<<34:4433fjc4!|{::|00ackqkiceiiijvoojh5ej544333eihjvAJIIEDzuurtuzIEtlrlrAlfhfeeffhllheeehfflll", +"rrrllhlff5ee53355333333}:::}}1^^^dxqdddd6uKOJFGQGFKGCynoqmogqggggdddbbb7^b777qb11)))~)|~||)||||)~~=--!---'*-'>.@/[errrulfee322[///223233[22[[///]/],,,/>/>>////>/_<234:444ei544|{:{|||0acccjojiiijvvvojffj54:433eieelAJJJJDwuruttzIEtllhhArhffffhhhhllhhlhffhlll", +"wtturllhlhef55e5ee5e5333}}}1^^(^$dxn6g6dd6mFOJEFOKKOFGvmmmoggdgggg66ddbb^bb7bg^^1^1111)}}||}||c1||~--=-!!:-<<@><[3rruhhf3e3[//];;]]/[/[[/]]]////[[[////>]//__/>////32:::43343<4||||00||acceijovoovvAujhjle4343eeffhrEIIJJJJzttutzEufflhflwhlrrrututttzrlllrrtwzz", +"DDztwurrrlljhhjhf55ffe55551^1^^^^gxqg666g866uKOJKOOKOKGyCvgogg6gggggdddbbb7bgb1b71^11c111}111}17c1c}~~~~!<<_/>>///222<4334444344||||||1acciiffovAAFAAvvvf335eeefjrzIIIIIIIJJEwtEwlhfrzwzKIDDDIIDDzDDDIDzEDDDDDII", +"Dzwtwrrrrrhrlhhhffef55511999^^^^(gxgddd666666mFKOQQOOQOFGymgogogng6gg6dbdbbgg^^11111111111)111111cc11}~~!:_2i2<[wzrlhhee2/]]/;]]]]]]]]]]]]]]]]]]/,,,],/]////[/>//[2223334<4:44440|0||||00cijjoouAEJEFAFvofhfifhlzIJJJJJJIIIJJEArltFKQOOOROJIIIIIIIIIIIIIIIIIIIII", +"OOOJJJJJIDDDwtwtrrhff999999^^((^(gnddd(66d66666mFORQOOOQKFGvmmngogogggddbdgv^^1111^111111111111a}1777c11}}cjl33wwtlfef3e[]]/]];]]]]]/]]];;;,]]]]]],]/]],,>>>]/[/[3334:4::::440400||||||7ivCKHCKOQQJJJJJFKFAAwwFJOOJJQQJJIIEwEEAFJIIIIIIOIIIOOQRSSRRSSSSSRRQOOOOQ", +"AIDDIDDDwEwAFEzAzwuuurlgg69(^^(66mxq6666dd66d6666uKRRQOQROKGCmnmmmgg66bbb6ggbb^1111111111111}1)11111c7c7oojrhfwIIzwlhh32/]]]];]/]]][]]];;;,]]/]]]],]]]]//,>>>////3eee4<:<<442cccc|||00coGGuvrrwJJFtwAFFFKJKJJOOQOJJJJOJIDEEEEJROIIIIIIJOJOJQRQOKFEAwttthlhehhttA", +"3effrutwttlrrjh9h9jllrrmojj9g966gmyggg66(d66666666gGRRQQRROKKGymmogg6g66ggydbb77^b111^1^111111111177ccjvvvFtrAAlrwtwtle2]]]/]]/]]]//]]];,]],]/,/],],],]]/,/,>///<223222224422333c400c7vKuvvAAwEzAwutrvuFJJOQRRROJJJIIJIIIJEIIOOJIEIDIIOJJJJEzwttrllhltue333333hh", +"hlfeeefh5hfhllh9h999999999996669gvGvmmg66666dd666666yNRRQRRQKKKymngggogggymbbbbbbb^b7777111111111117iovyyAJEJAh32[5lwrr3/]]]]/////[]]];;;]]],,,,//,,,,///]>,>//[3232222<<24223eeeccceyFuvuAuAEEzwtrrlouFJORRSRRQOJIIIJIJEEEIIJJJJEIEIJOEEwullhfhfjhrrwEr33333fll", +"ljhfefe33333515b9f9995777999999(6gCmmmoog66668668dddqnCNRRQRRQKOGmgggggomG6bbbbb7bbbb1b77111^111bbiovoofjFJJJwje2/[[ewth2/]]]///////];,]],>]>]]],]]]]]//>/]/>//333222222<<<2[3fjji35AEurwAFAFEIEurtuluEJORRRRQQQQOOJJOEEEEIIJIJJOJJJIJztullhhfhfhjrrtEDIrlrurwzw", +"lffe5333::}}}}}}1117b5111b^^^^^^(6xngg6g669gg66666d66gnyCNRQRRRKKGvmmmxmCyggggbbbbbbbb11b1177b69qfi7e4eefrEJAroje32[]3ttf2////]][/]/]]]]],]]>]],>],]////>>////2e442<<22<:<<[23eluhitJttFEAFAFJEulrutFJJQQOOJJOOQOORROJEEEEIIIDEJQOJEEEuulhffhfhlrrtzEIJJOOOOOJIt", +"heee34::::!!}}}}}))~~)1^1^^^^(^^(6ygdgggg666666ggggg66nnnxGQQQQOOJKCvmyyMnqggqgbbbdbbb7bbdgggjji7c|:4433flKFrvoiie33[[5zrf3[/[/]/[[]],],,],,>>],>>,,//>//>//[2ee2<<222<2<22333eejlwJIEKJJFKFJJvoluFJOQOJIIJJJJJJORQOOQJJJEIIIIJJQJEEJtujlhfhhrEwruEJOOIIIIIIJRDr", +"e33e334:|:}:}}}}}~)~=~)=^^^^^1(^(gndb6666ggg66666666ggmnxnnyGNRRRQJKKGCGMmoqqonxodgddqoomovomgic0000ic0cevEFojjfjicc4[[eAlf3[/[2[//]],]],,,]>,,>>,,,>>/////22ee<2[<<223222322e333lEDIIIIIEFKJAmtFJOROJIIIIIIIIJQKJJOOROOJJIIIJJEKOJIFuurlrrrutzwEKKIIIDDIIIIOKll", +"323}}3}:43}:}}|}~)~)====&))&&&^^bgng6d(b6d6666gggnggqgonxHHCHGGQRRROOKKRMCyxxmnyyyCCyvmmqggbb7acacccc0cjjAvFuvooovoqqicclArj3222[[]]>,,]],>>>>>>>,,,>_//<2243e3<2<22223332423323fADAEIIEIJJOKFKJOROIIIIIDIIIIOKEAFFJOROOQOOOJEEEKQJJzwuurrwzzIJJIDDDIDDzDJOKwhff", +"333:cc3}:|}|~|~!~)))=~===&=&&$&&^^dd^bb(6d6d6d66666666gggnxnnCyCGNRRRRQRSNNQNNNQQNNMMLHBHxxxsppppkkkkkpvyAvyGyvoqqyxqqoqiyFuoiice4444022222_2________:<42442e22<442232eee53ee225uDwzwIJIIIJORRRROJIIIIEEIIJJFtAwFEFJORORQRRQOKEFQRJEEztEDDIJOJDDDEDIJIJJKFtlff35", +"22::43c4}|c|!:!~}~~~)====&&&&)))^(d(^((^((((((66666666668gns88nnnyFNRSRSSSRRRSSSSSSSSSSSSMnnxpxxxspppppxGCovCCHCyxxxHCxqxvGFFFvookkkiiccc0c0cc0400cikiiiiiijiccc4ccceeeffeee3cehEEDwwEJJIOQRSSQJIIIIIIIIJOGtlrutAEJJJJJOOQQOQQOQRROIDDEIIJOIDDEIIIDDzuttrllfe35f", +"::4::4}:}}:!!!!!!~}~~~=))&&&)))&^bd(((((((((6666(((((b((66gnnnnnnmvuFQSSSSSSSSSRSSSSMMRRRMxqkkeiiiccccjovoooooooxyxqqxCCCxxGyuvoicc424044222444000c00ciki0jicccciiiiqooovvCvvovFJFJFFEJQSRRSSRQJJIIIIIJJFtvomvuwwEEIIJJEEJJQQQRSSSJIIIIOOIIIIDDzDzzDrrrlhhff3233", +"<<::::::}}||}!!~~}!==~)~~)&^^^)&^bdd((((((((((((((((6bd(666gxxmvmvyyvAGRSSSRRRMSMMRMSSSRRSCvyvvmqkkkicifjfiiiijikkkkpkxxCxyHKGAvqpkiccc40444044aa44444c3cce44440ciciikiqjooovFKQOOJJJQRRSSSSSSSOOOOOOOFwyvvvvvutAEJIJJEEEJEJORSSSSROOQJIIDzEEDEzzttrrrrrffe3322[", +"/'<:::!:}}!!|!:!!}!~~~~===&&&^&^^dgo(((((((((((((((^(999699gvxyvvmmvmmnCHNRSSSSRNHCHGNRRRRHyvvvvvyvoojfjiiji5eiik400cioxqxxyHNGGoiiiic0cciiii044444440444c44<:44c4ccccciiifjjoKROJOQSRSRRSSSSSSRRQOQKGGGGGGGGKFGKOOJJJEEIIJQRRSSSRSSSOJIIDEzzDDzzuurjhlhe332222/", +"/'<2::!2:}:}|}!!}!!~~~~&)))^1)^^1bddb(((((((((((((^99j999996gqnnn6d8qnnxnxHSSSSRQKFGCCNRRRNvvoqqoovvyymmjiee7eiie00cciikiikpxNGKGvic044000400000400000cci34044ccc04cc4eiicijovJJQRRSSRQRSSSSSSSSRROKOOOQQQQQOQQRRQQRRROQRQRSRRSSSRRRRRRQJJEzzzwwurlfffefef32[3[]", +"2<<[23:}4}}|}}~!!!))~~)^1^))))&&^^b(^((^((((^^^99b9999999b^(((8888888psxBMLLMLNRRRQQKGQRQRQyoooooovovAAujiieceiiiceciiiiiiicioCGGGoicckii0440424244c04ccccc0ccciiikiikkqqpoyCQRRSSSSSRRRRSSSSSSSSRQQQQRQRRRRSSSSSSRSRRRRSSSSSSSSSJJORRQRRQKAAwtwtrffeeee33e323[[", +"[<2['::}}::!}}}~1}5111))=&&))))^^(bbbbb(^(9977b9991b1^((($$$$$(8d8d88ddsLLLLHxqvGKORRRQRSSRMHyoqijoxvvFFvfee7ei7eieikkikicii00oGGGyqi0cc0iiiic0444444444cckkkpxxxxCHCyyxxxyGRSSSSRRRRRRRRRSSSSSSSSRROOOOQRRRRRRRSSSSSSSSSSSSSSSSRJOOOQOOOQQQKAtwtrhfe53233e332[[", +"2<,]<:}551^&$$$)$$$$$$$&$$$$$$$$$$&&&$$$$$$$$$$&&&)&bkbbbsBBBspxyvkc1111ikkyH77ovuFJJOOQNKKxqkijjCGe>>>>*=&&=$&&$$$$$$$$$$$$$$$$$&&$$$$$&&$&&=====-&dpbbsBspsp7oAm77111kbdGo7ec7iovFOQOJJGvvGKq4243<:__>+>>'-=&$$$&$$$ $$$$$$$$$$&&&&&&$&&$&=====&===$dpbdBBpss77mCobnb117byy7iiqoojvwGQJIEKQCo704444:_//_///2ee3323jjouyyHHHMMMRRRSSSSSSQOOFGGGvojfoEOROJJJJOOQRSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSRRNRSNNNvove53355efe33ehjrojjjiiec42<<_<{{}i", +"|bpHMHx7|:':!!!-!{:-****'*++>>>>.=$&$$$$$$$$$$$$$&$$&&&&$&&&&=====&&===&&bkdsLssxp77oymNn11i7dH7kkkojmu9bvGGGug7ceicc444c2__][/ee433c33jjhijjipyMSSSSSSSSRSRQQKQHvovvvFORSOOOQRRSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSRQNGyoijve55e35effeef5e33352<:<44__22:::|:", +":{{|kxHMCk|!!!!:!!!---*'*****''+>>.&$$$ $$$$$$$$$&$$===&&&&)=&=&&&&&&==&&&kkdBBssq77kvCQKd1k7kGi77jjjwj77ej9}}c04040ccc400022/<32333444ifffejfxNSSSSSSSSSSSSSSRMHCCyGKQSSSQORSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSRMHyFvjifjovfeehe3332222[/<2[/__<_<44:::2::::", +"_::{{~7pCNHqc~|~~!!!--**********'@>>+=$$$$$$$$$&&&$&&==&&=&&=&&&&&=&&==&&&^kksBBpskii9CGQGb779Cbiilrto155ej7!{|4444::4ccic0iqif3c22222c3ihlvGMSRQORQJKNMSSSSSSSSSMRMRRSSSSSRSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSRNNyojhAfifjjjjo52242<<[//<[<<[[/@'>>>/_2____:__4", +"4_a__{_{|kxMNxb1~!!!~!!-***----****++@@*&$$$$$$&$&$&=&&===&=&&&$&&&=&&&&&&&^bkBBBpkk77oGNOvbioymiirwv5}11fj~'*{{'<4::<<3iiijkvyoi3433223jHRSRQOOOOJEztmooqxHSSSSMLMSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSNNGvjifhruffec5cce:>>_//<[<[2[<@@'*@>@>>/>>_::__", +"___:a_a__:{7pHNHn1)|!~=~!-*--*-******+*@>*&&$$$&$&&&&&=====&&&&&&&&&=&&&=&&&^bsBLspki77vFQK9joqx9jAt55111he:''''>>':<44243effyyyvoii5iyMSRQOOQRQJEEtuji44ckokqCMSSSRSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSNAmorof5fl2<<<<::44:<_/>''>>//,///>'*>@+>>*>>+@@+_'_", +">____{{|a_aa|~dxMNHd)~!!-~-!!-------*'.*''>*-&$$$&&&&======&&&&&&&$&=&&&&&&=&1dBBLsdi77byOQCojoyjuF97}}7597''___//>_>___<223fovvvvovHSSROIORRQJIEEtre4|0443ioovoxHHSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSROQRRNGrrmjff342h2_<<<::|0|:<_''''>>////>+@+*+++@@@@>#@++++>", +">*+@''____|aaaa|7sHNHn7~~~==---~------**'**'>'=&&&&&=====&&$&&&&&&&&&&&&&&&=&)1dBLBsik77oFQQujmCjFj157}55e5**_//_>>>>>''<4ce5efvyHSSRQJJORROIIIJIJjcc0004ccciovyyCCNSSSSSSSSSSSSSSSSSSSRRRRSSSSSSSRRQKFCvjee5e3332>>@+@+'", +"@+@+++*'''___{aaaaadxMMyb1~~~~==--~--!--****'''_*-&==&&=&&$&&&&$&&&&&&&&&&&=&=&bnBMBbki7iFQRKjoFmm1}55}}55}''>,___>>>'>_>/4efmCMSRQOJORRRJIDIEEtwwfcicc4ceeiiejvGFQSSSSSSSSSSSSSSSSSSROOJJJOOOOOQKGCmoofi33222442<4e/<{{::{{~||!!**''>>>>>'+...@@+++@@@@@@@@@>@.", +"+@++++.+..*''{_{||aaabsHMCq7~~~==---!!||)---*'*'_>>*-====&&&&&&&&&&&&&&&&==&)~)^bxLMsikiivQSRvoFo7}5e75}55!*'>>*'_>>>_>//3eoMSSROJJORRQOJIEAtwujijjccccciiiiiifjvFSSSSSSSSSSSSSSSSSRQOOJJJJJIIIIztlfeff3322'.'-++++++++@@@@@@@@@@@", +"@++@+.@+....++*'{_{|aaa7pxHGnb1~)=-=~~-~||=-*--*_///<{====&&&&$&&&&&&&=&&))))~))1pBMLpkkijGSSGvFic|cfe5557-'>''>>_//<225oMMSSRQRRRSSSQIIEwvvvovjeeoieiijiiiiiiijvKSSSSSSSSSSSSSRROJOOQOOJJIEIEAtuje43e332////_/@@@@@@@", +">@+++.+@.+.+....**{{{||||7bpHMCq1)~~~~~~-)~~!--*>'<:2__'-=&&&&&&&=&=&&&==&&))~)))bxBSBkqiiyRRSCyic}}ejf5e5'>_'_/'<<<3jyMSRRQQQRRSRRQQROzuhii3covoijjfiifjjiijjjvGRSSSSSSSSSSSRQOJIJIIJJJJJEAwlohfe3/2322@>+++.@..+++.....-**--{~||77pxHHni1~~~~=~))-!!**'::'_//_'-=&&&=&=&&&&=&)&&))~))))kBLLpqqjoQRSNv77}}efe5e!_>>_'<23fyMSSQOOOOOQRQOJDIJRKro3e340cmojovyojjiiijjovFRSSSSRRSSRRSROOIIIIIIEAAAAvvojiie3>+...+++.+....-..**-*{{{~akppHNyg7})~))~~!-{!!!!'''__'''-=&=&==&&&===&=)~~~))~1sBMCqxvoGRSRo77}ceff5f'''<<25mHRSROJJOJJOQQOEzzDIJOlfjiiccceioooovCoqjiijoyFQSSSSRQOJKQRQOOJIIIIIEuurleiijiij32//<<<>@..++.++...........---{||a1ppxMHn971~~~~~::!{!{*'''''___*==&&&====)===~~~~)~~^BBMxyyvGSSMj77cefjfhe<<::fCSRROJOJJJIOQQJAtEIIIIIl2<24ciecccfAwvmvvoovvvvwKSSSRQJKJEEJQRRJIIDEzwtrjee32cecci42*+>@++++@+@@+++@@++", +"#@@@@+@+.+.+++.+.....+.-..=.-=={||1bpsHNCok77}}~||!!!!{'!{{'__/_*-&=&&=&))=)~~~~~|~)sBMCoyxyRSSo7i5ejlhr::5yNQOQOJJOIIJQQOJDzDIIIzlfh[22[<2<4ccijAtromtAyvyFKORSRROOJFAFAEJJKRQJAtulrjfe22<443c32<<_<<<_<<_'_#++..+.++.........-...=---{|a7pBHNGyqi7c1}~}!!!!!!!!'<____'-=&&===~~~~)=~)~~)BBMxHyoNSSyeieeorrumHROOQOJJIIIJQQJEtlrrzzuff333/{:<[[2<<4ijowtvovwutFEORSSOJJJJJFKEJJFFFNROAvljh52//<422244_/_<<<<<<{'_e<{!~--{------!!--!!'!!--*'**'*@++'@@++++@+@@@@@+@#", +"#@+++@#@>#@+.+.+.+++....--..-.-=====~~17pBHMNGvjbc71}||!!{!!!{'*'___'-=&=)~~|~==~)~!!dHLHCvqHSSCcjjrwFQROJOOOIIIIJOQOJzrhlltwzhe3222/<<<<<[/[2eeeeoAwmrAAzEEOSSRQOJJEJJJJOJFAAvCRRGvhi2_/<:42<<2<<<<:<<:::<<3:{!!!!{*-----~-~~~)!-!!!-!-*'+*++@@>++@@@@+@+@@++##", +"@@@+++@@>@>@.+...+@.......--...==------=117sHMNGCofb1c}}|~!!!!{{{**'__'{~~)~~{!~~~~~~~xBMxxqCSSCjAFQRRQJOQJIIIJOOOJDthehhllllr332[22<<[<[<2/2332333jwurvAIJKSRQOOKOKKKJJOOKKGyvyFNMGyc<<:<:<<<<2<<<<::<::!<24:{!!!!!!{-===-!--~~~1}}}}3:'.*'+@'++.+@@@@@@+#@#@@#", +"#@@+++@@@@@>>+...+++.......----==-------==~|7pHMHCvuof771}}:|:!!'{{{''_<@++...+.........-------------=-=~1kBLHvmmmof7}1}}:::{!!'''{{<_{~~~~!{::::|xLLCGySSRRSRRSSOQRRQJJIIAl55ee322[<[2[[33/[2/<'<'</'<<23ff533[2233fftIIROIDwrrwutwzzEuuujhjfifiiibkvCiccc0||444::::<4:e:<:::{{!!!||!:~||~~||!|:!!!!!**'''++.++@@+@+@#@#%######", +"@@@@@@@#@@+++@+++@@+.++......---=----------=--=--===-^dBMHxjibhjffe534::<::#@#@>+++@.+.....-*.*..--***-...=.!!!!}}---=-~^xLMCofi775e537eeijjjouEJJQRRNQNSSRSSSRQREtlj153}~=-!'!!-!'<'<'<<[[[3332////2f32ee32333fjfAJJOIIDtutzzttuwzwtlAwjee3ee335:2432:40c42:<<<::<23<::{!!!!!|~~~|}~::!}1-!{-!--*'+++*@++++++++#@@@#@@#%##@@#", +"#,@@@###%#@@@@@@@@@@#@@@+.+...***-.-*.*..*..*!!!!*!!------=)^nLRHofffeeeiffjjuAKOEFJKFFJwmMSSSSSSRKmg1}}!----!:!!--!'''***+.*-****.**-.-**!!!!-*-!*---!-----)nLRNyvfeeiflwFKFAwwFAJJAwuvHSSSSSSNm1}!-==---!!!----!'''<_'<[[2eh[////[h3eeee33[[eeerKROEultDttzDwwwEIErf3ioujhhf55771c3544444c444<233<44||||!~}~|!-!!!~|!:!:----.-.''*...++++++.+##@@+@@#@#@@@##", +"####@@@@@#@#+@@#@@@#>@@@@@*.+.+'*++++*.-*'*!!!**.**--***{{{{{~!~)8LRNGvvyFKAurvuFEJJAuuAzEFSSSSSSm~~-===---'!-----''''<''<2[23e3[[[[[/h3hfe3[[[3eelEORJwrjfwJwtzEJEEEIKvqpkoHGjjjjjfic55}44<4:4432e34:4}|||}|}}|!!!!!!|!-!!!****-.+.**.+.+@@..++@@@@@@@#@@##@###", +"#%@##@@##@#@@@@@++@#@@+++@>'+.*'**+''>>'_<<'''''*'*''***'*!{{-!~~~~8LRRROAtuvuFFKJAutwEEIIOSSSSSM1=-==-=-'**=-----''!<':<<22233322333[jfee2/[[4eifwIRQIwrjluFEEEJJEwwEJQHCxovFAvfiiie5534444:::44e5:24|}}|||~!::!!!!!!!!''!!''''*.*++*+@@#@@##%;;;;;;;,;%##%%##%", +";;;,;;,%,#%@+@+++@@+@++++++''>+':<<<<<<<<<<<_'''{::{|~|79myMSRNFGKJJJJtrutwwwEJRRSSSSx===-----*----***'''<:22<222533335532'''*''++@+++##,;;;;;;%;;;;;;]/];;;;", +";;%;;,,;,;,,,,%@#@#@@@+.++@+'@...**-!!:'!{:::{{'<<<:<{<<<<<:443cfruvlooGRSRSRQOJJAAwAAFEJRRNSSSM(-----------*'*'*''<:34::24efjoooqkkc0oyyqooqqjjuJOROJIEwvmoAwFEEAEzEtEOQAvfjfgwullojff5334::3ff34c43::::::::|||}3:!{**-**-*'*-**...+++@#;,;;;%%%%%%%%;%%;;;;;;;", +"%%%;%%%%;;;%,,]],/],,,>@@@@@'''+++++*+**.****-****-*{*'*'*!|||emoofffjmvuKRSSRQOOJzAEJJJQKyxSSSMc'*----!---'-**'**'cnxHBLLMMGGGHxqki7aioovjfjoolJJRRJJIIulrrljlGEwwzEwEOJOwojjf9uuruwtljf55imrj33354c}::::!::!|}}::!''**.*-**.**.*.+@@#,;;%#,#%%###%%##%%#%%%%%%", +"%##%%#%%##%%%###>,,,,,],]/'>>++**.'.''*'.***.*'**-..**!}}}}1}1111fluAAMSRRRSNKJJJQNCyxxSSSH233<'''*---*****~boyxokkvKNyvvyvvkii77oofouurrrEJOROIIIIrrwjffjlwJzwEDJOJOOtrmjjjutwAFwvvvvrje5544c|||::!|!:}4!~!!!{-*-*..--***+*..@>>,,%##@###%##@####%%%#%%%%;", +"%%%%%%%##%%%%%%%%%%%#>,>,>>>>>////>_''*+'+>*+''**+*''*-**'<:}!~~~^11bfojlg96nMRRSSRQQNHvvGHMSSSC23332<'<<{'''!1iijoiffjomovCvvvvoooofivmjomtAuwJJROJIIIIDzrjfjjhjtJIIJROKQJOAoj9999mvulofe9}c}}}~!~~!|!~!}}}|!!!!'*!!**-*'.*..+...+>>#@#####@#@%@@%#%#@##%%%##%%", +"%#%%%%%@##%%%###%%;,;#>,>>>>>>>>>/]//[///:<'*'**+*'+'-'!:::!!-~~~159jmlfb1b999ySRRORMNCoooyHHSSHie3333<:::}7fjjovuurojolfejvGvvuoofb57lhhjhjrDIJQROIIIIOIEwttutljhltKCuuuAFJKmbbb^^^^^b^^~)~~}||~~!|~!!|}}}!!!!!!{'-!-'-..**.++..>,>@@@##,,%#@@#@##@######%%%#%%", +";%%%%##%%#%%%#%%%#%%%>@#,>>>>>>>#>#>,,,,>/,]/@@*''*'::!:!!!~!~~~~19fjh977eee759mMSRymvHNyxyxxSSMNGyvvuuuuAAAwtAEEzAwwAttujffvutAtwuoofwururuuzQORQJIIIIJDttwwulfeb59eb99gvoyKQndbb(^bb^^^)~)}~~~)~~!~~~~}!|!-!--*{*-***.-*-**++>>>>@>@@@+@@#@###@@@@####@#%####%", +";%#%%%%%%%##%%,,#%%,,>>,>>>>>,##,#,>>,,;>>>],@***'!:::!~~!!}}~)15fhfe555ife55fhmGxSRGvovGMHCHRSMvvuuFJIIEIDEEDIDwtwtDDEwtuwlAJIDEwllofuhjljhlAJIRJIJIIIJAlhfe557577bb6(6d6ooxHMnd8dp(^)^^11~~)~~=~~~~~~~~!!~!!*---**'+**.**-*@>>>@*@@@@++@+@@#@@@@@###@###@###%%", +"%%%#%%%%%%##,%##%######,,>>>#@>>,#>>,,;]]>>;>''''!!!!!~~!!~~}~7eff971}55eefjovyo7knMRNyyyKRMNSSRQOJJEEDIDEzzEIEzztwwtlurrrujltwwrlb^^^3<333ehEIOOIIIJJJJulhffe999b7b96666d6gqxLLddbd^^(^71)))~~~)=~}}~~~-=~!*--!--***'******>>@@@@+++@+@+@++##@@#@#@######@###%%", +"%%%#%#%##;%%#;%##%#,,,,>#####>#@#,>>,>,],,]>'''''!!!!!~!!!!~15eeef71}555}efoCokijojoHSROJKQMSSSRQOJEEEzwttwtrljlhhlhe5fheff57foh71~)&&3<235erEDQIEwtrrruuwulljlmvummmgmgg6nnBBLLdd(^^b711^^})))~~11~~~~~=------------***.*'*'*+@++++@>+@+@@@#@@@@##%#######%%%##", +"%%;%%%%#%;%%%%,##,,>#,,,#>>>##,##,>>,]];]/>>'''''!'!!!!!!~~}cc55771}3c3}efjoqiikiiiijxMRKFuvGRSQOJJJEEzttutwrjffeh5}::::'''-&)c4|=$$$$2'::<2uEJQItljjjjlhllrtrmgmmmmmoomooxxBBs8((bbb71^1^11^1^~~)~~---==~=--------.*-.-*--***++@@@+@@+@+@@@@#@+@#####%%%##%##@#", +"%#%%%%%%%;%,%%;%#,,#>>####,#,#@##>>>>,]///'-'-''--'{!!!!-!}}335}}}}c3}ceiiec17kki7cijiqCRRKyFGSQOJEwuturwzwtrrjjlf:2<####,,,,>###,,,,23/'***''''-*{!!!|}3}5c55}}:55ceicc}}cc1cii7c7jeeivQQQKuRNAEEtrrrtrhhjjhje}:- $($$ $2'<22fEIOIEwrlhffhf999jggmmvuymggg6ggnnpd66j9bbb1^111}}1))~~)--------{--!!**-***'*''****++.++@++++++@+@@@@+@@@@@##%%@#%#@#", +"%##%%%#%,;%%%%,%%%%%,,%#,@@#,,,#@>,,,3h<'*'*'*--*--'!!::}}}}c5}}}22c4ce4::c55ccccikioiiiioGQKGRSGyAEEEEurljlhh52>,,2e'>'''*-*-*!{''!:<:::43}:}:<444c4333eeeeeecc0kqvoiiiioGGFRSRFJEEIEwwtulf5e32:{!!-=-==-& $($$$ $2/<,#,,#####%,#,,,/35@>>>''****-''<<<<2233eeee353ife3<:||1)})))~}|1ivoiiiijxAKRSSROEEAEEwullhfe322,/2'@@++*'+***-*'':::|:222>= $$$ $:323hEIIRIztrrlljhjjjjjhjjogooooxxCqqoxGyoo99bbbbb^11))))~=--*-=-----*!!---''{-*.*.***+..+...@+@++@@@+@+@#@@###%##%%%#%#%%", +"%%%%%%,;%%%;%%%#%#,%,#%%%;;,,,]/22@+++++++++-*'''-!!<:<= $$ |e23hEIIQIEturrljjlogjjjlojjooqoxCnooojookibb1^b1^^^1))))))=---*---~~~!!!*{***''=****-*+...+.++++++@+#@+@@++@#####%#%#@%%%", +"%####%##,%%#%######@#@###,,,@,/2'@+@##@++++''!*!!!:!!!!}~11}~-======))))&))))))~~)1|}7xxxxxqjqMSSSQOJEEEDEzzwwurjhf33<<<<_>= $( !ee5rDIIQJIEtrurtrrlmmojjojoovonCxgoog99bbb9k7c11^1^1^))))==)----~~!!*******-***'**.***......++@++++@##@###@@#%%;%%%%%##%%", +"##%##%#,######,%###@#,####,>><:'+@@+@@#++>__''*'''*~~}71~-=-=====&=&&&))&)))))~)~)))17dxCxndgqHMSSSROJEEDEDEwwrtrrjhe32[<[/= $( !3hhrEIIJQIIzuurtuurrmmoggmoooxCHp9j969gf9jjb7111111)~~)))=====~!---*-*-.*.*-*..****'**++.@+++@#@+@+@@##@>####%%%#%#%%%%#%", +";%%%#%###%#,###%#@#@##,%#>,/<<++@+@@@+@+@>>>//''{*~c7|----=-=====&=&=&=&&))))))^)))1c7bqCHndgnLLNRRQRQOJEEEztwurrutulfe2233~ $ =3rzzIIIJRJIzzwuuutuummooomvxxHMqiibb9juojiib7111111))))))-~--~~---*-***..----...-.-***..+++++@@#@@+@@+@@@@@@@##%###%%%%%%", +";%%%#%%##%########>>#%#>#>/<'#+++@@@@.+++@+>_'*'{{k)-----==-=====&==)&=))))))~~))))1c1ikyNyqqxSMGKQQOOJOOJJEzwrlrllrurjf232- $$ &5lwwDIIIOQIDDEtwtwtwummmmmmxnxxbbe7e9fj9bbe77711c}11~~~~~=~~~~~---*--**'.**.****.....**..++@+.+@#@++++@@#@@@##@#%%#%%;%%#", +";#%%%%%,,%#,########>%>>>2:++@+@+++@@+@+#@++_'**-a7{{{---===&&)))^11}1117b1|:|!~|~1111bkqKKxoxMMHGKKJJIIIIIIIEEwtrlhhrrl322- $$ =5jtDDIIIJOOIIDzzwwwAwAACGGGMLLpbbb5bie771777711}1|1c|~~~~~~~~~~----{--.*.**.**..-...-.+*'>++++++@@+++@+@@@@@@#@%###%%%#%%", +"%@%%%%;,#,#@,#>,##>,>,>>>[<@#+++@+@@+++++...+.+..'*{{~sxpc||~|}1777ijiiee575c3344424440aa7ikbCNCCMGyyGKJJEIDIDDEEzturrttEEJJtt) $ =}wwwIIIJIQJRQJJOOIJJJAFFKGMSSn666ddb^7111|||c||}~)}~|}111|||~!~!{-!!-*{*-'***.**-.+....+.++..++++##+@@+@+@@@@@@#@##%#@###", +",%##%##;#,%,###>##>> c #544F4E", +", c #5A5553", +"' c #5F5353", +") c #605B59", +"! c #655A59", +"~ c #666160", +"{ c #6A5F60", +"] c #6B635D", +"^ c #6F615D", +"/ c #6B6665", +"( c #706465", +"_ c #756A6A", +": c #736C65", +"< c #716C6B", +"[ c #786A66", +"} c #7B716B", +"| c #777271", +"1 c #7C7071", +"2 c #807771", +"3 c #7D7877", +"4 c #827677", +"5 c #827D7C", +"6 c #867D77", +"7 c #877C7C", +"8 c #8B837C", +"9 c #898482", +"0 c #8E8282", +"a c #90827D", +"b c #938983", +"c c #8F8A89", +"d c #948889", +"e c #978F89", +"f c #95908F", +"g c #9A8E8F", +"h c #9E908B", +"i c #9B9694", +"j c #9D968F", +"k c #A09495", +"l c #9F9A99", +"m c #A69A9A", +"n c #A49C95", +"o c #A39E9D", +"p c #A8A3A1", +"q c #ADA1A1", +"r c #ABA39C", +"s c #AFA7A1", +"t c #AEA9A8", +"u c #B4A7A8", +"v c #B9AAA5", +"w c #B4AFAD", +"x c #BAADAE", +"y c #B9B4B2", +"z c #C0B3B3", +"A c #BDB7B6", +"B c #C1BCBA", +"C c #C6BABA", +"D c #C4BCB5", +"E c #C6C0BF", +"F c #C9C1BA", +"G c #CCBFC0", +"H c #C9C4C2", +"I c #CDC7C6", +"J c #D2C5C6", +"K c #D2CCCB", +"L c #D7CBCB", +"M c #D6D0CF", +"N c #DAD4D3", +"O c #E0DAD9", +"P c #E6E0DF", +"Q c #ECE7E5", +"R c #F3EEEC", +"S c #F9F4F3", +"li93::|9ic|{>-%%%$+. .@%-*%*,),,>-%*>~3gquqmmikuupc3|3cg95coAIMMIKKKIEABEIIIKKKHEBEHIKMIEHEIMNMNNKKIHEEEHIKIEEEKKKIKNOOPQQPQQQRRQOOOOLLLKFFEzzxvvvssssmmmmmmmssssssssssvvvvvvzzzCFFILLLLOOOOPPPQPOOLLFFzvstqqllkgggddgdehquuuwyAAxzyyzAwwplf777225foolifffifcci", +"fi953}<3fl9<,>%#$#+. .#**%%-)),,>%$*,_0kqqqmkkqupi1(/|0c59itEKMKIIIHHEEIIIIHIIHBwwAAEIHEEEKNNNOOONMKHEBEIKIGEAAHEGHFKMMOOOPPQRRQOOOOLLKFIHBzzvvvvsrrrmmmmmmmrrrrrrrrrrrvvvvvzzzCDFHLLLMNNOOPPQQPONLLFDzvspmmjjkkggddddhehqquuyAyuxzwxywwpoi9576329ioliffffc99c", +"b0c955|<5ff3~>*###@+....@%*%%%>,,,,-%%-)_cmquqmkkuuo9<)~|9550iwEKKIIIHHEEIIKIHEEEBwwAwABEBBEIKKMOOOOONKHEEHKMIBBAEEEGEFKMNOOPPPRRQPOONMLKKIHzzvvvvsssrrmmmmmmmmrrrrrrrrrrvvvvvzzzCDFHLLLNNNOPPPQQPONLHFCzvrrmmjjkkkggddddeejquuuAyuuxwwyAwwpof950059iooifcifd098", +"799dc9|(/|99<,-%#@@#@+++@$**%%*>>,,,-%*>~3gmqumkkmuul3/!/35379iwEIIHEEEBBEHIHEEBBBAAAAyAAAAAABEHMNOOOONKIHIKNNKEHEIIIHKMNNOOOPPQRPPOONMMKKHEzzvvvsssssrmmmmmmmmmrrrrrrrrrrvvvvxxzDDFHLLMNNOOPPQQQPONLHFCzvrmmmedggkkkggddeeemquxxAxqutwwywwpolf00cdcciiiccffc988", +"99ccc9|(!)|95/>*$@#$$##@#$*-*%%*->>,,>->)/0kmqqkgluuuf1!)_7||39lAHHEEAwwtyABEBAyAAAABBywyyAywAABEKNNNNMKIIIIMONMKKIKKIIMMNNOOOPPQPPOOMNNKLFEzzvvvsssssrmmmmmmmmmhrrrrrrrrrvvvvxxzDDFHLLMNNOPPPQQQPONLHFzzvrmmeeddggffkggddeemmuxyxwqqxtwwywwpoif99cd999cccfff995", +"9955553_),~393)-%##%*--%%%->>-%%*->>)~)>,~|fmqumkkquxm7{)(3|<13ctBEEByppttwyyytolpwyAAwtppwwwyAAAEKKKKKHEEEEHKMKHHHIIEEHIKKMMNOPPPPOONNNMFFCzzvvssssssmmmmmhhmmmmmrrrrrrrrrvvvxxzDDFHLLNNOOPPQQQPPONLHFzzvrmmeeddddbhhkgggeeemqtAyutqqpwxzwwpoif9500d079cffiicc9", +"92||333|/),~39|,-%%*>,>-**>)),-%%*->)/~,,)/7imuqkmmuxug<){|3<_19mAEEEypoptwtttpidfltyAwpoioppttwwAHIHHHBAAAyBEHEzyAAEBCCEEFIKLNOPPPPONNMKIFCzxvvssssmmmmmmmmmmmmmmmmrrrrrrrvvvxxzDFHLLMNNOPPPQQQPPONLHDzzvrmmeeddddbbbgkkgjeemmuzAuqmqupwxwwwpif9569d0779fillif9", +"2|:::|||<~,,~35<,-->,>>-*%-,~~,-%%*->)~,>,~),->)~3gquqmqqtuqc_~{|4<~/5lAEEByoilpppppoicclwAwtollloomrqqwBBABAwswwyAEEBxuwwyAzzzEFFLLOOOOPOONMKFFzzyvtussmmmmmmmmmmhmhmmmmmmmrrrrvvvxxzDFHLLNNOOPPQQQQPPNNLHDzzvrmmmeeddd888dggkkjjjmquzzuqsmqptuwywtlfaaa507479lttoi9", +"221<**,)(9kuqmmqpuuo7/(<|1{{<5pBEBAtiiotpopppi9ftAAytoolooqqmqtyyyAAtpsttwABAyuqtxzzzzCEHILMOOOOOONMKHECzAyttsmmmmmmmmmmmkkkkkkhmmmmrrrrvvxxzDFHLLNOOPPQQQQQPONMLHDzzvrrmmeedddd88dddgknjjjquxxxuqmmqptuwwwpic8a634439iptof9", +"59553<(//<<<~))/|33<)*#+....+*~//,-%*->,-*>)~|fqumopuuuuk3_/<|/){_fyBCBypfgoolopqoifowBAwppqppttppwAywwyupoooqtAAwxuqtwxwzADFFILONNOOONMLIGCzzztusmmmmmmmmmhmkkkkkkkkhmmrrrruvxvzDFHLLNOOPPQQQQQPONMLHDzzvrrmmeeddddddddddgjjjjquxuuuqmmquutxwwtpica666859cilof9", +"9cff93|(~~/--,)(9kqqomquuuqc|((__~)<5oABCAwmcfigkooppllpyEAwwttuuwwyAywtwytlinllpxywxuqtxzwwzCBFFLLLNNOONMKFGCCzAttsmmmmmmhmmkeebbbkkkkkkmmrrrvvxxzDFHLMNOPPQQQQQQPONMLHDzzvrrmmeeeddddddddddjjjlouxuquuqmmqotuxwwtpfa6aa9cc99ciic", +"ffiic731/))~~/~/<|59<-$@. ...#>~<~,**->,,->,~|gmqmmquuuuk5<~/_({(5fpABAAtg9ccglmptpoouAABByyyyAEEAAwtwAwojjiiouwwsuqrtwxwxzABFILLNNOONMKIGCCAztutmmmmmmhmmeebbbbbbkkkkhmrrrvvxxzDFEJKMNPPPQQQQPPONMLHFCzvrrmmmeeddddddddddeejnopxuqquuqmmqptuxwttofc9ccc9575cff", +"filic541<~),,)~<<<39|,%#@.. .+%,~/~--*>,,>>>!/9kqqmmtuuuqc|/~///(49iwAAAypc90dioppwpolpwEEEEEBEHEBAytwAyplliinuwxtpqqttyxxzzAFFILLNNNNMLFGCCzztttmmmmmeeeeeebbbbbbbkkkkkrrrvvvxzDEJJMMNPPPPQQQPPONMLHFzzvvrrmmeeeddddddddeeeejoptuqqqqqqmquutuwwttplie98655379c", +"cilic5||>)~~<3|~-%$#@...+#-)~),---,,,>,)~|gmqolquuuuk7_((///<7ftyAyyti059floqppogioyEHIHEEHEBAyttwypooihjpttwpqqqtuzxyzDzFFILMNNMKFIHCCAzuttmmmmeeeeeeebbbbbbbbkkkkkrrvvxxDDEJJMMNPPPPPPQPPONMLHFDzvvrrmmmeeeedddddeeeeejnptxuqmqqqqmquttutwwwtlf866444426", +"3clic54<<<~'-**--,~||~,>--*$+++#*,)),,;-,,))))~{5kpmllquuuq0|<(((~/3gpyAywwpf70fiiiioplcfpyEIIEHHEBAwolptpookfeotttsommqtxxyxAzzFHKMLLMKKHHCzzAtttmmmmeeeeeeebbbbbbbbbhkkkrrvvxxDDEJJMNOOOPPPPPPPONMLHFDxvvrrrmmmeeeeeeeeeeeeeejotpuqqqqqqmmqutwwyBBypc662|11[}}", +"<3fif93|*%%%-~||/))),>*%#+@%>)),>,>,,)//~~~,,>,)/<-%%%>))>>,>,)~/%##$-))~//~/<|*-)~,>>>,)~{/<(~(7kmmfgmquuqi9995<{)|fpyAyppqpppof059cittrififiopttpiiptpllljifisttqomljmmrnqmssvCCHILLIIHEzzyytsmmmmjeeeedbdddddddbbbkkkrrvvxxADEJMMNNOOOOOOPOPNMNLLHFDzxxvvvrrrmmmmmmmmmmmmmmquqmmmqqqquuquxABywurpppic6|1(][", +"/~~(~~<5953<~),-$##%-->)~~<39c93/)>,),>->,~/<<||(~|gmmgckpquuog9997<~/5ityywpoppolic76acottpf9889fiiilouwtooleiiiottppjjhnmqrnmmstzCCIIKIIHGzzyxuvmmmmjeeeddddddadadbbbkkhrrvvxxADJJMMNNNOOOOOOOONMMMLLHFDAxxvvvrrrrmmmmmmmmmmmmquqmmmmqqloppppttttsqolpli86|_^[", +"{~~{{))<|55|/~),*$#%*%%*>)<3cff93<~)),>-->~/|353<~*%%*$##%>~|355955|>)/|3|/~)>**-%@+#*,///<39fc9|,~<|<~~),>>-$@@%>,,)/|9fiif93/>$$-/9ili5||0gmmg7dkquumg517c7;--->,~///~~)),%#@$*--,~<359cili9/-%%,|ioli515gmqk75gmquqmd1|5c3/{/3iwAytlgf9566862259dflptwwwwywtpicbc999fnppooihdehehebdjnuxzBGGEEFFzzvvvssmmmmheeeeeddddddbbbkkmrpvxxDDEJIMMMMMMMNNNOOOONNMMMJJJLHFFFDDAzxxxxvvvvvrrqswyqmmmmmqnoolnppkggmquqqific953}", +"3|1/{';-*--**;>)/////~>%#%***,~|||||3cooc/-*-~9lpoi59giqmg40mmppqi3<|00|{~19pyAytif9566762223099dimopppppolfcc988biooolihhhbgbabbgnrxzBCGGCBBzzvvvsrmmmmeeeeeeedddddbbbkmmrvvxxDDFIIIIMMMMMMNNNOONNNNMMMKJJLLFHFFDDDzzxxxxvvvvstwywmmmmquonjjjnmmkgkmqunjefd967}", +"253|_{';**-*&%*-,~<<||~>%*-->)/<33|)3lppof9fkqpi77fmqpumc|<5d3_/<5itAAypid76266|}1|1|4509d9cdgklkiif9669flomligbhbbhb8bbkrszzzCCBBBBzvvvvrrmmkheeeeeeddddbbbemmrrvvxxDDIJJJJIIMMMMMMNNONNNNNMMMMJJLLLHHFFFDDDzxxxxvvvyyywummqquujeehjmmmkkkqppoieb963|", +"}55531/)>--*=%&%*-~<35|~>>,,)~/|5995|/|9fc|~))|iptpidflqqmd7dkouuum9|7dc3<~|dowAAwoi9311||1__(__37777750ciillf9268cjlollihcabaa86ejmqxzzzCCBBDzvxvvrrrkkhheeeeeeddbbbbkmmqrvvvzDEJIJJJJJIMMMMMMNNNNNNNNNMMMMKLLLLKHHFFFDDzzxxxvyBAwtsqquuqheeedgmmmkkipppmiida31", +"2359993<~,>-=***%*>)|99|~)~/<<|59fff9|<|59|~))-=*&%%%%>)|c9|<|335cfc9cfic5|373~,>~3pwwtpllqqpmicgkquuuof0cif9=%$####%%,|95559cfllifffilf9355<,--)9ptwtppuutpmgilqquuulddiif5<_|0qwAytplf91^]^^^[::(]]!{!{{(159a2}26abfgiiigbaaa2226hhlruxzxzzADBDwuuvvrrrkkkhhhheeeeeehhhrrvvxxDDFJJJJJJJHJJIMMMMMMNNNOOOOOOONNNNNNNNMLLLLHHFFDCzCEEAAAuqmeeeeddddgklonoppppomif0", +"d56359cfc9|<~,=%$####%>/||9flpttpoollllf5593/>*-~9opttuuxxwumikmmqqpplfioic3<<4ipyyytog92[{!!^^]::^]!!!{{(|462}}228cffiiifc9aa2}}68hnouxxyzzCADDAuuvvsrrrkkhhhhheeeekmmmrrvvvzDDEJJJJJHJJHJJIMMMMMMNOOOOOOOOOOOONNONNNNLLLLHFFFCCHIHEAqmmeeedddddgklooompppomiii", +"pigfccfiifcc5|/)>*%%%$*,))/5lwyywttttpoid955|~>-,<9iotutxzywtmmmmmqqpploqof951|9lwyywoi93[^^!!!^](^]]^{{(_1||2}2268bffkgigc0082}}6ablnrtxzyzCABADxuuvvvrrrkkhhhhhmmmkmmrrrvxxDDEJHDEDEEHJJHJJMMMMMMNNOOOOOPOOOOOPPOOOONNNLLLHFFECIIIAwmmmeeeddddggkinonmptwwttpt", +"tpllc99cccffc03<~))>>->,),,/9oyAAyyAywtpli953<)>,/39copqtxxzxuomqqmmqqopqplg9547fpwAytlc6}:^^!!!]]^]^(____||<}22270dfiiiifc9071}}28bhnqsxzxzzCADDyxuuvsrrrrkkhhhhmmmmmmrquvxxDDEEEEEEEEEJJJHJIMMMMMNOOOOOPPPPPPPOPPPPOOONNLKHFFFCJIHztmmmeeeddgggggeiopptABAAywt", +"tolic57555555953,~~<3copttofflpABEEAywpi933999fpwuuyAAyuppqppqppuwyywoigfdflwEEEAwoic93<<:[::::<__11|23559ccfilifdc954_(_128bhgmrqsuxzzCGADAvxuuvvvvsvrvvvqqssvvwxxADDEDDDDDDDDDDDEJJJJKKLMMOOOPPPPQQQQQQQQQPPPPOONNLLIFFBzxvrrmmmjjggkmpppqnoooooptyyto", +"ifgd52_~!!,,>;>--->,)),,,))~<5fqttogccfltAEEBAypic99fiiptwuwzAzxpqpuqqppppwywpiffifgpAHHEAwoif954}|}<<<|1_|__}|3659cfgiiffc951_({}47bhhjnruuwxACCAzADvwuvvvvvvvrvvvqsvvvvxzDDDDBDDDDDDDDDEDEJJJIKKMMOOOPPPPPQQQQQQPPPPPPPOONLLIFFFzzvvpmmqjjgkmpqpqmlnlollilpwwp", +"lfdd961(!!';;=*&%&%*->>,,)~)~|clppofc99cfpwABBAytlfcfllltwwxzCzyuqpputpppptyywojfifcitBHHEAplfc953}:<<__<_<<}123559cfiiifgc95}_{{_47ahhjmnrpsxwACCzAAyvwuvuuvvvvvvvvvvvvvxzDDDDDDDDDDDDDDDEDJJJIKKMMOOOPPPPOOOOPPPPPPPPPPOONNLKIFFAzvvsuqqjjoqppqmmmmiiiiifhipwt", +"oifdd94_{!'>;-*&$$$$$$%*-,~~/|ciopi953359fptwAAyytoilpolpwyyCGCzwtputppppoqwyywmmlifflwEHHBypiffc93|}:<_||||2355599cfiifgff92:^{{(120hhhjnrrstxvAzCAADyvvtvuxxvvvuuvvvvvvzDDEDADDDDDDDDDDDEEJJJJKKMMNOOOOOOOOOOOOOOOPPPPPPOONKLHFECzvvstqqqppqqqmmmmkeeehhebhltt", +"tlgdd56_~!'';=**&$$$#####%>)/|clpoi5|<<<|9iptwwwtollottttyAABEHEAwtttupmqpptyAytoiiffipAEHHEAtoiikf953|1||4355555cccffiigfd52[^!![1700hejnnrrstvzAACAzADvywzxxxxvvuvvvxxzzBDEDDDDDzzDDDDDDDEEJJJKKMMNOOOONONNNNNNOOOPPPPPOOONNKLHFEzzytuqquttqqmmmkkggbbbfebbfot", +"poid055_/!'';;*%&%$$##@@@@%->/5lppi9|/~)~<5ipwwwti9cipwwwyABEHIIGAywwwuopxwwyAAyumifilotBEHHEEypppolf905755599090cccfifffc96}[^!!(1400behjnrrstvyyzAAzAADADDAzxxxxwxxxxxADDEDDDzzzxzzyDDDDDDEJJJKKKMNONMMMNNMMMMMNNNOOOOOOOONNLLHFECzzvtwuxtpmmmmkggggdbbbhbbafo", +"polfd071_{'';;%&%&$####@+@#$%>|gifc93<),,)/3itzAtg3|5foppotyBJKKHEEAAzywACEEEBBBAtooppttyBEHHHEBAAwtppoliiffcc95559cd990962}[^!!^_1700eejjjrrssswyDzACCCAAADAAzyvxvxzADBFDDDzzxxxxxxxzDDDDDEJJJIMKMMMMMMLJJJJJJJIJKMMNOOOOOONOMLHFFBzAyAxxuookgggddeddddbbeehae", +"flligd541({!';;%&$$####@@@@#$$*!59953|<~~~~~<5itxxtf430floiitxAEJEEBAAAAtwAEEEBBBAytpoopptABEEEEEBAwtpoolifffc9955550d050762}[^!!]_1700deejjnrrssvwyAAACGGACBDADAzzzzADBFDDDzzxxxxxxxxxyDDDDEIJJIKMMLMMKJJJJJJEEJIJJLLLNNLLNOOOMLKFFCCBEAAuunjjgddddeedddddbhhbb", +"biiiid061/{!''-=%&%$$####@@@#$%'|95;%&$$&$$$##@##$%;_57_!>-=-,)~/<3ftxBAuifiomigipwABGBzwtttmfimwyywtppoic5590cipwwwwywttoiifdc957590cfiifc9d95|[[]!!^^176adeejjnnrqsxwvyADACGGGGEEDDDDDDBDDDBzzzzvxxxxxxxxwDDDDEEIJJMKMIJJJEEDDDDDDDDFFFHLKLNNNNNNNKMIIIEGCyyqqmjheeeeeeeeeedddgkhe", +"eciiid999|>,,)/3iwACAwptttpoiluyBECywtppmg0dipuupmomkc953459iutttttttpoliigc9009cffffcccc9531[^!!^^1470abeehhnhqqsxDvAAAzCGGHJEEBDDDDBDADzxxzzzxxxxxxxxxzDDDEEJIJMIJIIEEDDDDzzxyzAzDDEFHKKNNNNNNMMMKIIGCAxummmeeeeeeemmeeeedggkk", +"kehffd99971({!'';&%&$$$%$###$&&&,|77(;*-,,;--;;)|fwABAwwyAywpmpxAEEAxwtpok05cimliiiiigc05337doutpptttttpppoifcccccc99599905531:]]]_177a0behhhhhmqsxDvyADzGGHHJHEEBDDDDDAAxxxxzvvvvuxxxxxzDDDEEJJIJJIJEEDDDzxxxvxxxvxzDFHHLLMNNNNOMMKKICCAtummmmeeeeemmmmmeeejgkk", +"mhccffd5903_({!,;***$%&&$$$#$%**>/77<,;,{,*%%%%*>|iwAAtptyAAywtwCGJCzzwtpog59fkkkgikgfffc959cipttppppttpppplifd9995537535433||1}:}|45799aeehhhhmqvuyDyAACBHJHGGGEEEDDADzzxxxxvvvvvuvxxxxzDDDEFJJJJJJEDDDzxvxvsvvsvvvvzCDFHLLMNNOOLMMLIECyyusmmmmeeemmmmmmmhjhjnm", +"mlfdgfd06873<{!',;**&%%&&$$$%%---)104),~_!*$$&$$*,|owAwlltyCBAwyACJJEzAwwtoc0dkmqmiiiffkifcccfmptwtpolooppolifcc955333|||1<__<<}}35509dbeehhhhhmqvuyDDyDCEHGHGGEEEBDDAzxxxxxvvvvvvvuxxxxzDDDDEJJJJFEDDDzvxvvvvvvvsvvxzzzDFHLKMOOONNNKIEzvvspmmmmmmmmmmmmmmqqqnno", +"policfd02505|_{'';--*=%%&&&%%=;;-,<75()~<_'=%$$$%*{5pwxofityAAyzAAGHEAAAwtui75gquumkkfccffgcd0diopppliiilooliiffc95531_<>{45<~~(||~>=&**%>{9pxtifowyyyyyABEEAyzwtum0|5gquqggd73570d0579fiilllilloolliifc995|1|>!|7|/~~_33(),>-%=;/cuuiffotxwxxzBGGzwxwttti415iomdd051<14507770ddgfiilolollliiic953||<_{~)!'';'{:|0dcfjnlolnnqqvuxyDABDABBBDDAADAxwvuuvvuuvvvvvvvvvxxxxzDBDEEEFDDDxxvvvrrrkkhhmmmmrsswvzxDFIMMOOONKFFCzvvrrsmmmqqqxwyCAABAxuuu", +"xupoffiikccgc541_)'-;--;>=%%*=;'>>,/44_~!{390|<{>;=*,|lpofciuwutwzABGBxttuutp9<<39c90901_(_|3777590099cfilllooooolif953|<(~~)';;;'^[400eejllqmruquuxyzBAAABDADDAADwuuvvvvvuuvvvvvvvvvuxxxzDDBDEDDDDzxxvvrrrmmkkhhmmmmmptvvzzFFIMNOOMMIFDzzvvspstqqqwwwwABEEBAAxx", +"wtpooiiiliiiif997,,,>*%%&=;>>'{451~~/7mpi9|)>**>(9opkdfpwtutwyAEGAuppptuo5,!|7|/~|dqtpoc|!;->{3kppfciutttxwzAEBypooptug4{~_47007|_({(_1359000077670cfiiffffffffcc93|/),';!{_}70bbejnnnmqvxxzCCCBBBBADyywtuuuuvvvuvvrvvvssvvvvvxxxxDDDBDDDzxxvsvrrmmkeeeeeeeeemmmpsxwzAHKKNMMLIFFCzzvvuuwwwwwwuACHHIHEAAA", +"qlkllicfkmiiiigccc95|!<9ouodfotwwxxwyCEAwpommpqf|~/<3555|_{{!{<|35999d97243230995595555599995|/~){{<}20beejnjjmqvuuzCCCDBBDAyxtvuuuvvrvvurrrrvvqsvvvvvuxxzzDDBDDyxxxvvrrmmkeeeebdddeeemmmptyyzEIFKMKKHFFEzzzyzwutttwxABEIIHEECyw", +"qqomloiffilkifgc9553|-*&&%%*-'~|3<~<3dlf09d9|~!!~|dpukciptwxxwwzCCywpmioppc|<_|1353_]~)){_|359cdd06||2122|3||||<||||459553|||||60dejnnnmmmquuxzzzCDDAzxuvuuvrvvvvnnrqrrrvvssvvvvvxxxyDDDDzxxxvvrrhhmkeebbbbddddeeemmttyAEEHIIKLLHHFAzzzAyststwCEHJIJGCAzAw", +"wqomolifffkifdfd0743|;=%%*->!/4|~/<507||499|{!)(3mtpfdltwwxuwxzCAwtpiiopm91____471(~]))~/<159dgd967321|||<<<_((/(((<<|3359999d9dfhjnnnqqquwwzzAAADzxuuuurvqqqqnnnnmrrrvvvsqvvvvxxxzzDDzxxxvuvrrhhheedbbbbbddddeeemmstzCEEFFLLLHFFCzCzAvvwvzCEHHHGECzzzzA", +"wqomlilfc9dggddfd0333|-;'')<|/~/|4|7d03354<{~_5muukdiqutuutxyzwtpollqupf3,~|5cflopppprrrqvuuxwxxxxuuvuvssssnnnnnnnnnmrrrvvvqvvvvvxxxzzxxxxvvqqrkhheeddd88888888ddeeqquyyAyzzFFHJHFEEzzxyvzBEHECCzCFFBzzzz", +"Awqnkhb9aa3589575093|||||||||<<~~)',))/||~~|449mqf5573_/_4gtwpgflpututuxyxupomlqppoc|<<|75|/)'>>''''~_|0900765342||||<_/~~)),>;=->)<|5clopttttppqvxuxwxuuvvvvqvqrornnnnnnnnnrrrvvvqqvvvsxxvvxxxxvvvqqmkkeeddd8886666888ddhjquuywywxDFEEFHFEzzzvABEHEBCCzCFFFBzzC", +"Axqqkhab9644307||774_//<_|||3||///({{{/|4>'>'!{_3a9006332}<<<_<<<>-==>'~_25dioptwwvwuutuuuuuvvqqqrrnnjlnnnnkkhhknrrrvvvqvvvsxxxvvxxssvrrqmmkeedd888666666688dgjnuusstwxxDDEHHFDCzzzGEHHGCCzCHFFFFCCC", +"zzwqjkhb88634704|4751~~~~~/<|33||<>')/:77657633|}__<(<<<-*=>,](<|7cfiostywyxxwxxussqqqqnjnjjjjghhkkkkkkrqrqvvqvvvvsxxvvxxvsvrrmmmeeddd886666666668bggopwuqurvxzDEFEFDEAzCGHHHGCCBCFFFIFFBC", +"CAwsnkie999535873|703_)),)))/_1333-->,)/<|35bginpswwyzxxztvuvqqjjjjjjhhghhhkkhmmmrrrrqvvvvvsxxxvvvvvrrrmmmeedd8886666666666bbgmppummpvvxzACFDDDCCCGHGGCCzCFFFKFFHEE", +"GEAwxtqijfd0539d73799|~),,,,),{_|53,'!{_|22322|4|__//{),,>>>>>--'']/<|25dcfinnpttwxxzzxusvnnnjjjhhghgghkhhhmnrrqrrrvvvvvvuuxvvvvrrrmmmeedd886666666666a8bhmqpommhrvvzzzzzDFHHHGGCCzzCEFFFKKIFII", +"NMMKIBzytpolgccfd97905<~,'>,,>'')<||<<<|0iic00dfiikmtpi9900imuxwpfcgkmptqqqqupoi539iqppoikmmk9_{',',,',{:|42732|1<_(]{~),>-;*=&%*>'~_<|279cfijjoppqsxxzzwwsnnjjghgghhgghkkmnnnutpsurvvvvuvvuvvvvrrrmmmeeedd886666666666688ilomnjmmppvzzzzzAFIIIECzzzBEIIIFKMMMMN", +"POPPONIIHEAwtoillidcc93/~',>,,;;>>)/||<<3clkfgiif95cimoicddioptwtmfcfmppqooqqqold3|9fmppppmqmg9;;=&&$$*;)(<3359ffginnoporvuxwtupppohgghgghghhhkhjknrputttutttvvvvvvvrrrrmmmeeddd886666666666688ellmgjemmstwwvxzzBIIIHBACBEIIILMNOOOOO", +"PPQQOMIIIIEBAtooppliifd3<{'>,,,;--->)<1||5fliilol9459gmolmklmquxwulggippuqomqqoom91|0imqpppupof7|~~!)!]{][:}652641_(]]'>,>;==%$##%=,)]<35cfffilnoonmnrsrrspppmmkkggggggghghkhkrrqtuutwwvvvvvvvvrrrmmmmeedd88666666666666aafiifhgehmmtwvvvzzCHIIHECEEIIFMNOOPPPPP", +"QPOOKEAzAAwttpiiloolilof5<~',,)''-*--)/|359fiiotpi9339fmppppommtwxtidfkoqqqmmmmomm0|40gmquttupi97|//~!!]]]:}473a71|:]]''>--=%%$##%=;,]/|29cijlloonnqqqqnqnnojmmmmmkkgggkkjkjkhrrrusuwywvvvuvvvqrrrmmmmeedd886666666}}}}68bfihebddejmmsvvvyzCGHHFFFFFFKMNOOPQQQQQ", +"POMKEzAwuppligf9cfiiilptl9|/),)))'-**>)/|55cfiotwpf5459iptutqplqxwwqgdgmqqpmmmmlmmk5159imptuupmg77|<(({{{[_[}26672}:({]'>-*=%$$##%=->!~_170dijlororoqrrnmjjjgkkmmommmmmlmnmmmkrqrrptwyywxvuvvurrrrmmmeeedd886666666}}}}28biih8b8dgjmmrprvAACGCHFFFFFKMNNOOQQQQQP", +"NNMIHEAwtpoifiid9cgiilptpi9|(~~~/{,;;->)/|5cfikpxwofc09cmtttqqolqwwui9dfopppmmmkkmmc||5cgoqputqic5311<_((_:[1a5a731<]{{''>-*&$#@#%=;,!~::479hfioprrrpqqnnjhhhggkkmmqpppoomqqmrrrrrpvxwwvvwvvvrrrrkmmmeeeddb8666666}}}22268iiba68bggjmmrptzCCCzAFFIIKNNNNOPQQQQPO", +"NNNKIHBAxwtoooooliiopoppplc5||//<>-*&#@@$=;>!]_<435dbgilnnrprrnjjihhggggklmpppqpqpprrpqrrsuvwtvvvvvrrrrqmmmmeeeddbb666666}}}2226bccc8666bggemmstwyBAzzEFKMNNNOOOPPPPPOO", +"OOONNMMKIHEEAywwwttttwtppof053|||33|{'')~/_3cillotutpommmuwtqptpqtxxumd9ckmpqqmligki91|7ddgkoppoi97733377742}2677a311_{!'>--*%$#$%==>'{/:4750cbginnnmnnniijggggggkkkklmqqutttrqprruvwutvvvvvrrrqmmmnmeeeddbbb666662}}226acc9666668egehmnwwyzyyzBFMMNNOOOOPPOOPPP", +"QQPPOONMMKMKIHHEEAwtwyxtppl0533|3553|////(<<3flloptwwtpquwzxppuuttxwxqf90dkpqqmmkgggd7<|0dgglmolic077|335066aa65723|1<({)'>-*%$#$%=>>'~~_4790bbgginnihnnjihhggggggggggkmmptttprprpsvvsvvvuvrrrrrmmmmmeeeddbbb6666622}22aacc862}6a8hbdemqquwwvyzCIMMMNOPOPOOPQQQQ", +"QQQPOONMKIKKIIIIIIEAABAywwtl53||3|33|<<<||,')]_1359dddfhjjkhjhhjgggkgggggggggkmqqtttttprxuvvvvvvrrqrrmmmmmeedddb888a6222}2}}}26cc662}2688bdgjquuwtsyCGIKMNOOOOOOPPQRQQ", +"QQQQPOONKIIIIIIIKIIIHHHEAAAyo9333<;;=%&&&->''{/_1457bhbggijikhjejdfgkgggggkkkgkkmpprtstswvvvuvvvrrrrqqmmmmeeggbb888222}}}[[[[}26bc62}[22866bgjnuuqstzBJHKNOOONOPPPQQQQQ", +"PQQQQOONMKIIIHKMKKKKKKKIHEEEAtig9|/{~<|353>==&&&*--']~(_1375abcfikjhhejefddgggggkkmkkkkkrrnrrrwwwvwxvvvrrrrrrkkkmeeddb88aa2}}}}}}_____16b96}}}}22666bkoouqmsyEEHKNOOOOPPPPQQQQQ", +"PPQQPOONKIHEEEHIKMKMMKKMKIIIIEypi5-*&$%*-;,)](<1357acdgfinhjhjgfddddggggkkkkkkkmooopstxwxyywxrrrrqqmkkkeeddb888222}}___(((((([79562[[}2226aekmooqquABEIKOOOOPPPPPPQQQQ", +"PPPPPONKIIEBAAAAEIIIIIKKMKKKKIEApg5|/~{_|7974|<19gltyAyplltEEEHHHGEzyxywqc3379mqqqmmg05731147dcgfcc03790d05a7888ab07241_{~,;;*%$$%->,)(/1|350ddcgfinjjnnfgddddddddggkkkkoonnnssvvwvyywtttpprmmmmeedbb88a2222__(({^^^!^^(|774_[[}}2}28bimonqquAAEIMNNOPPPPOPQQQQQ", +"QPPPOOMMIEAzwtppwwwtyEHIKKKKKMKHBpic3({!(<7907770diowBBwoipyHIIHHHHEzzyxum0445cmqqqmkd033113500diiic5750d998008a8aa722*&&&&->,{(_11550cbbgfgjhnnqiigddddd0ddggkkooonovsvvuvvvttutttsmmmmmeeddb6622}}___^^^^^^^^^[}32|(_[}}}}26bflmniuwxAEKKMNOPPOOPQQQQQQ", +"PPPONMKIHEAwwttpplikipwEHIKKKMMKIEwoc|(!!{_7999ccfiipAAypootBIIHHHHECAyzwug7345gqqqqmk0744|43570diif97570dcdcdc8bac0522_({!'>-*%%=-'']{_|450acbggghjhjlmllgggddd0dddggmonmnrvsssttvsussttqmmmmmghggb882}}}_((^^^''''''!]12}:{{_:}}}26bfimklpxwBIKKKOOOOOPQQQQQQP", +"PPPOOMIIEBEyywwtpogc9flpwEIIIKKMMIEwl93/{)~<59cfilllowAwpoopwEIIIJHGEBAAAxqd3439mqqpqmg74414409779cfcc090dhcfegbb0a857}}({{'';*%%=;'!{{_<159abcggiijhhfiiilggdddddddgiljnlqvrsstusrsspummqmqqmmjegbb886}}_(^^]!!''','''{<||]^!(::_[269eeikmpwxBIKKMNNNOPQQQQPQPP", +"PPPOONKIIHEAzywppolf09ccflyEIIKKKKHApi93<{{/<39ciopptyAAtollpwEHIHHEEAAAzAum0775cmqqqqld741347007359dgddddd9figgbbb8a53}:({!';;===;'!{{_<1789cfggggjhhggfiigggddddddikiljnrqrsvvrrrusmmmmmmmqqmjggb88622_(^^{'','''''''{_|_{]^^(:__26c9fimqtpzEIHKMMMNOPQQQPPPPP", +"QPPPONMHHEAyxwttpllfd99999iwBHIKKIIEwplf92:::269ciptwAABypiiopwEHHHHECAAzAzumc075iqqqqpkc743479093379fffidbdhejkjhhbaa7|[[{]'';;;;''!{(_12a8a9ggiijjhgggfggigggdddgiilkinmmqvvsrrqrmmmmmmmmmmmjjggb88621_^^{!''';>;;>;'!<_/]'^^((__<69cfciqptBHIIKKIMNOPQPPPPPPP", +"QPPONKFCCAuwttppollicdccdcfmtyEHIIIEAtpoic5}:}268clpwyABAukfiopwEEHJJECzAzAzukd57dmqqqqqm0333570d07359fgighgbejkkjehbaa74[[(!';;;;'!{(__22669dgggfjhhgggggffddddggkkmlnmnmmrrrnrqrmmmmmmmmmmmmjjgea8622_(^^!'';;--;;--,)<<('''^]({(1688chnqqwBHEIKIIMOPPPPPPPPPQ", +"QPPOMLFBzwqqnmlloiiffcccfiilptwAEIIIEAywtpi9714370fltwyABymfflptyBEEHHEAzAAAxpfd00goqqqqqk055670dd95770gflkggeejkmjjhbaa74[[^'';;''{([[}2260cdfggjjhjgggffgfgfhhhiilloqnnnrrvnnokkmmmqmqmmmmmmjkkebba21_^]!!'''--===*;>)/,]<~';'){{!{[3389cnnqAEHHIHHMNONNOPPPPPQQ", +"QPOOOLIFzvsmedgbab989cfiifiilptwwAEKMKIEBAAwoi9550dfimwAEEyqiiotwAAAEHIHEAyAAwtlcddgmppquumkcd999dggd00dggomnmjjjkmmjjjb864<_^^!!^^^:<13779cdgiheeehhggggffdhheijjjnrrqrvrrrnnhhkkmejnrprppqppqqmkidaa4[:{''';;--=&&&=;,/<~>;''!^^^_|388fllpAEEIEEIMOONMOPPPPPQQ", +"QPPOOLHEzvsmmedb886868cfffiiilptwyAHKMMKHEAwtplfbbcffiqwBHEytppptyAAAEHHHBAAzzwuifgilqqquuupigd9dddgggddhhomqpnknkmmmljeb8621(({{((_|17790cfhhghheeheeehjjeheeheihjnonmrqppnnhkkkejjorpspppppppqoikfb05}_/!,>;--==%%%%;'{<{>;''!!^^:<158cfltBEHIGEKNNMMMNOPPPQPQ", +"QPPONLHFzvssmed8a662a689bccfiilptyABIKMNMIBywwtpibdfiiipyEKEAwpppwAAzAEHHGBAAAzwuiiilopuuuuupkcddcdgggggjkmmmqnnnnmmmmnjea662__((__14479acefffhhfeehhhehhheehhehjjnnnmmqrrorkhkhhhjnqqqqppprpppmokjgcd06|<~!,--=%%%%$%*>{/);-;,''^^[:159cfltBEEHBHMNMIKMNNOPQPPQ", +"QPPPNLLFzzvsmeeda666268b988fiiilpwyAEKMMMKHByyywplfffiiowAEIHBwpopyAAyAEEHGAAAACytolmmpuxtxxtuidddgggggjjloomnqnnnmmmmmjefa622}[[}2266a8cbffffhhhehhghehehehhhhjhjnnnmmnqnnhmmmjjknmqqmmmmpprppmmijcc0763|<~,>=*%%%&&%*>)()-->'''!^[[:40cciwBEEECINNKHIKNNOOPPPQ", +"QPPPNMLHCzvsmmedbb66886a9668fppptwyAEIMMNNMIEAAytplifiilowAEHHBwttyAAyyAEEHBAAACBzwqlmqxxxwxxxpkgggiggkkgilljmmloommmnmmjhbba6}[[}22a6abcfffffhhheehhghhhehhehjjjhmnqnnnjnkhkjjkmmooollllmmnnlnmifea90221||<~'>*%&&&&&&-)~'-=-''''{:::40c9iyEEByBIMMHGIKMMOOPPPQ", +"RQPPOMLFFzvsmmeddb6668abbbadiptwwyAABHKMMNNMIEAwtpoiiiijiptyEHHEAyAAAyyyAEHECAyABBAyuqquxzyxxzxumkkkijkkkjjjkkmjnommmmmmmhbbba2}}226a89bhffhffheeeehhhheeehhhjjjjnnrrmmmlnhheegklpolijhhjjkkknnkhhh8a3}1___(/{,>*&&&&&&-)~'-=;''''{_:1250clABEAwEKKKEGIKKLOOPPQQ", +"RQQPONLIFzvssmeedbb6666a88bciopwyAAABEKNNNNNNKBytpillllifipwAEEEEEBAAywwyAEHHAAzABCAxpmpxAAzAzzxxqmmkjjkkkjjjhmmnnpmmnmmmmhha886688bbhfjieffhffeeehhhhheeehehjjjjhmmmnrlnhhbhdbiiolliieeehhkkkjkeb666|[_(({{~{~,>-&$$&&;)~!=*-'''){(_}250coyAAzyHKIIEGFFKMOOPPQQ", +"RQQPONLIEzvssmmhddbbb666889jloopwyyAABIMNNNNONKEypoiopoiffipwyABEHEEAwtwwABGIHAAAzCCzwuquyzACzAzzxuqnmmllljnhhkmhnrmmmmmmmkkeb86688bbbejiffefhheeejhhhhhhhheehhjjmmqmrnnghhbdbbhiiffc9ahbbbeegggeb6661[{{!)!)!)),'-%$$&;)~);*=-;''{/(}437cpyAAwAIIIIEGGIILNOOPQR", +"RQQPONLHFzvvsmmeeddb88bbbbhimmmmqttyAABHMNNNOONKEypplptoiffotwAAAABBAwttwABEIIGBAAAzzzxtwwyACAzzzAyuqpqoonkjkkhmjnnmmmmmmmkkggb88bbehhfhifhehfehehhfhhhhhehhhhhhhmqqmmnnhhba88bebcbd8aaa8bbbeghgebb62_[{!'''>,,,',>-*&%-'~);*=>''')//_227cpwywwBKIEHEGGFILNOOPQR", +"RQQPONKIFzzvummhjgdddbbbbhgkmmkjnpptwyyyEMNNNOONMEytppttpigjowyyyyAAywtptyBEEIIHEBBAAAzAyyAABAAAzzzzxtppppmmnmmqqnnnmmmmmmkkjggddgggechfjihfhgeehehhhhhheehhjhhmmrqmnjjhhba888bc9098aa66aa8bbhkgebb62_^{!',>;--->>,,-**;'~);-;;'''!((<227ftwtttBKHEEEGEIILNOOPQR", +"RQQPOOLIFBCAwwqqjjgggdddddgknnijjqptwwwuwBKMNNOONKHBwwwwwoifotwwwwwwwttttwABEEIKIEEBAAAAAzBBBCCzzzAAAytppmqqqqqqqnnnmmmmmmkkjjjedgggejeehihfhhheeehehhhhhhhjhhmmnmqnnjhgba8aa8aa8aa4316666a8cbekhba62[^{!'';;**==;>>>>->,~)>-;>'''!~/<126fpwttwEIEEEEGHIIMNOOPQR", +"RQQPOOMKKHCByyuuornkkgggddfjnjmmmqpttwwwuxAHKMNNONMIEBABAwolmptAAAwttpttttyAEEHKKIHEBBBAAACCEGGEECAAAAwttpqpqqononnnonmmmkkkjjjeehggejeejhhhfeheeeghhhhehhhhhhmmmmmnjjgb0a68a8a86531_111266aabbheba62}^{!'>;-=%%&%*->>,'~/~'-->'''!{(<<26ittppwEHEEHEGGFILNOOPQR", +"RQQQPONMKECAwyuuuppprmmnjjhjqqnmmqupwwwywtuABIKMNONMKIHEBAtolnpyAAwwtppttptyBBEHKKIHEEEBAAABEEHIIEECBAywuuptuprprnnnrmmmmkknjjjeehggejhehihhfefhehhhhhhhhhhhhjmmmmmnjhgb086266873}[[:[__112aa8bhebb861^^!'>;-=*&&&%%=>,)/,''!{((|39ittptwHHEEHECEFIMNOOPQR", +"RRQQPONKFCzzwwuuqnnnnnooonqqqqmmmmqppttwAwutyAEIMNNNMKKIEBAtoopyABAwtpooppptyABEHIIIEEEBAAAAEHIIKIHEEAAAxutuptttpprnrnmmmkknjjjedggghhbhehieffehehehhhhhhhhhjhkhhnnljhba8662aa53}:[]^^^^__12aa8bbhbaa1_^{!';-=*%&&$$%=;)(||)>;>'''!{(/|39iptppAIEAyBEGIFILNOOPQR", +"RRQQPOLIFCzyzwyqqqjjjjnnouuquqtmmmqloppwxAyttwABHMNNMIHHEEByppptAAAywtpooppptwAEEHIIGEBAyAABEHIKKIIHEBEBywwttttttuqmmmmmmmknjjgddgbebbbhhehheheechhhhhhhhhhhkhkhhjnjhhba6622634}[:^]^^^^^(_12288bhba64_[{!'>-=*%&&&$$%*'~|3(,>>'''!{{(<39lppppAIEwxAEGIIILOOOPQR", +"RRQQOOLIFFzyAyyqqmmmmmmmqquuyywqmmqnlotwwyywttwABIKMMIBABEEBwpoptyABAytpnoppptwBHHIIIEBAyyAEEHIKIIIIIEEAAAAwtttutuqqpqqmmmkkgggd8b88bbbhaabbbbcbbhhhdhhhhhhhhhhjjhjjhba8662244}[[{!]!]{^^^(_1228bbbaa41[{!';-=*%&$&##$&=,<3<~,,'''){((<49lppopAHAwxAEGIIILOOOPQR", +"RRQPOOLLFFzzzwwqrnmmmmmmmmqtwyyuqqqqnpwyxyAyvtwABBEIKKHAAAAEAwpoppyABAytppoppptAEIIIKIHCAyyBEIIIKIIIIHHEECAywttutuqquupqqmmkkbb8668aa888aaa8bbbbbdddddddddddgghkjkjggb8662224}[[]]!!!!!!{^^(_122abba64|[{!'>-=%%$&&###&&>~|_/))!''!~((<39lpploAEAtxABGIIIMOOOPQR", +"RQQPONLLFFEGCCAyqqqrqqqmmmpuuwyuuupupwyAAAAAAwwwABBEKKKEywwyBytpootyBEAytpqppptwAHKKKKIHEByABHHHIHIIKIIHHEBAxwttuqpopoppnoljhe8666a6aaaaaa880999dc9000aa0dddggggghhh8a862}221[[({,,',,'!!{]^__222ab8631:{!'>-=%%$&&###$%*)/~/~{/(~'){(_|5coppooAAwtxyCCEIKMNOPQRR", +"QQPPOOONMMKIEEAAAAzywuwttpqwvwttquwyABywyyyAABAwwyEEEIKKIytptttppoopxAAAAtpmpptwAABHKMNNMKIEBABEBGHHHIHIHEEEEBAyvwpponijjiffefb66222264434244226aaaaaaaaaaaaaaabddda066}}2}:::(]'''>;''','!^^(_}22aa6|1:{!',>-*%%$&###$&&>){)'~(/{~~(_|5coppooAywtxyCCCIKMNOPQRR", +"QQQQQOPOMMLHHEEAAABBAAyywtxwvxptmqtyBEAwuttwAEEBwwBEHHIKKHytppopppopuwAAAytpoptwyyABHKMOONMKIEBBEEHHEEEEEEBBEEEBAywtppllijgeb8886626|14111}}}}222644477770aaaaab800a722}2}_[_<]!'>>>;;>''''!^^(_}26a24_[{!',>=*%&&$####$&-){)',{/((((/|5copplpwwptxuyABFKMOOPQQQ", +"QQQQPPPONNMKKIIIEEEEBAAyyAAywwqttmqwAEEypolptwEEBAAEHHIKKKHAtppopporpuwzAAypprtwwwyAEHKMNOONMIHEEEHEBBAABAAABBEEEBAwwtpniec8662226434||::[}}}1|11111444377770008aa67a2}[}[[[:({'';;;;;;;;','^^^[}}2221:[{]!'--*%&&$$###$&=,)'->){{(___|3coppopttpsxuyABFIMOPQQQQ", +"QQQPPPPOPOOOOOONMKKIHEBEBBACywpttmmuzEEyplfilpwBHEBBEIIKMMMIBwtptrpopqtwABzwsqppwwwyAEHKNOOONMMKHEEEBAzAAyyAAAABEEBBAtpoljca662}2|3||}}}}____<|:_1111}42277700067a622}}[_[:_:(!''-;;=-;;;;''!]^(_}2221_[{{''-=*%&&$$$##$&=>),>>''!(_11|39oppoptpoqxuyzzFIMOPQQQQ", +"RRQQQPQPQQQQQQPPPOOONNKIEEBCAAytttqqwBBAtofcffowEHHEEHKKMNNMKEywttppputwAEEAyuqutwtwyEEIMNOOONNNKHEEEEAAAyyxywyyAEEEAywtolfc862<_((:[}21<:<((_______11144777776777a2}}[[[^[([{!,---===-;;;;''^^^[}2}21^[{!''-=*&%&$$$$#$$%>),>;>''!_34350ltppoppoqxuyzzFIMNPQRRR", +"RRRQQQQQQQQQQPPPOOOPPOOMKIECCAAwwwwtwAAAwpjiccfltBHHBEIKMMNNNKEAwwtptuwwCEEBAwtuutwtwAEKMNOOOONMKKIHHHEEBAAwxwttwAAAAAywtpoib531_(^^[_<|<<___(((__::[1}1227777767342}[[[^][(({'>;;===**=;;;''^^^__}}}_^{!!,;>;*%&$$$$$$#&%-,)>;>'''{1459dotpppppppxuyAzFKNOQQRRR", +"RRRRRRRRRQQPONMMKMMNNNNOONKHEAABAAAyyBAAwtpoifffltAEEAEIKMNNNMIBywtptwwwABEHHEzwvwyywyEKMNOOOONMMKKKIIHEHEEAAwtttwtwwwyyywtpic53::^(]{{/___<<__///____<1}}244734733}}[[(^^((^{'>-=====*=;;;;''^^][}}}[^{!'';;**&%$$$$$$#&%-,),;;'''!_|59iptpppttpuxuyAzFKNOQQRRR", +"RRRRRSSRQQONMIGGGEHIIIKMNONMIEEEBBBAAEBAwtptpliffltAEBBEKMNNNMKEAwwtstwwyACEHHEAyAABBBBIKMMNNOONNMMMMKIIIIIHEBAwwtppppttwywtpic5|}_/(~{{{{(/<<<<((((__<:1}}24421144}1[^(^^]{]!,;===%=====;;;''^^{_}}}_^!!''>;**%%$$$####&&*,{);>,''!(_|9ipwtpptttttuyAzFKOOQQQQR", +"RRRRSRRQQPNKIHBCCCCGGGHIKNOOMKHEEEEEBEEAtppttpoifiipAEEBEKNNNNKHAwywwwttxAEHIKHEEBEEEHEIMNNNNNOONNNNNNKKKKKMKKHEBytpooooptttpoif95|<_((~~)~~((_<<<(/<_<<<:111|}1}12|:[[{^^{({!';==*%%==*=;;;;'!^{[}}__^!''>-=**&%$$######&=>~)>>'''!{<|5ipywppttswtuyAzHFOOQQPQQ", +"RRSSRRQPPONMKFFBCCCCCCGGIKNNNNMKIIIIHHHEAtptwwwplifipAEBBEKNNNMIBwyyyzutuyABEIIHHHEEEHIIMNONNNNOONONNONNNMNNONNMKIBytollilopppoolf933|__~~~~~~/))>>''''~/<3coyytptttwwuwzzFKOOPPPPQ", +"QRSRRQQPOOOMMKKHEGGGGGGEHKKMMNOONNMKKIIIEwpwAEEAwoiiltBEEEIKMNNKEAAwAAwtuyyEEHHIHHEEEHHIMNOOONNNNNNNNNOOOOOOOONONNMHBwpiffiiloppplif953|<<<'!^{[[[^^!',;-=%&&$$$######&&-)),;;''')(<|9lwAwtwwwywxyAzFLOOPPPPQ", +"QRRRQQPOOOOONNMMKIKIIIHHIILKKMOPPPOMKIIIIBwyBHEBAwpllpyEHHHIKMNMKEAyyyxtwyABEEEHHEEEHEHIMNOONNNNMMMMMMNNOQQPONMMNONKIBwoic9cffiiiillifc53||'!!^[[^^{''>;-*%&&$$########&*,));>'''!(/19ftyywAywywxyACIKMOPOOOP", +"QRRQQPOOOOOOOOOOOOONNMKKIKIIKKNOPQPOMIEIMIBBEEBBEBAtppyEIKIIKMNNNKEAAAyyzAABEBEEEEEEEHIKKMNNNNNNMMMMMKMKNOPQPNMKKMMKKHBtlf63333359ciiiic953|/~)))))~{/<<<<<_<__](:::]]!!!!(_:{';**%%%%%&%==;;>'!!^{^^^''>;-=*%&$$#########&&>))'>'''!((|6cpwwwBAAAwxyACFKMONNNOP", +"RRRQPPOOPPPQQQQQQQQPPOONMKKKKMMMNPPPOKIIMMHEEEEIKIHBwtyEIMMKIKNOONMEBAyyAAyACCCBEEEEGEHIKMMNNMMMNNNNMKKKIMNOOONMKIIKKIEAtlc6}/~~(<|59fffc953<~))!!!!!!{((<|<<(_(:::(]^!'!'{(:~'--**%%%%&&%=;;>'!!^^^^^'';;-=%&%$########$#$&-)~'>,''!(_}29ottwABBByxyCGFKNONNOPQ", +"RRQQPOOOPQQRRQQQQQQQQPOOONNMMMMKKNOPOMIHIIHEEEHIKIIIEBBBHMMMIIMOPPONHBAyABABACzzEEEEEHEHKMMMMNMNOOOONNKKIKKMNNNONMKKIHEBAwof9<~)')~/|599c9953!!{^{^^'';=*=%&&$#########$&&*)),;'',!//}29ltttyBHHAxyCGKKNONMOPQ", +"QQQOOOPQQQRRRQQQQQQQQQPPOPOOONNMKKMNNOMHEHHEEEEHEBEHIIIEHKNNMIKNOQQPNHBABEEHEEBCBEEEEHHIKMMNNNNNPPPPOOMMKIKIIIKNNNNMIEAAABAti9<{',,))/|3599995|!!{^!!!';-=*%%&$$#########$&&*,))>''')~_}29lttpwBIIByACHKLNNNOOPQ", +"QQONNNOQQRRQQQQQQQQQQQQQPPPPPOONMKIIKMMKHEHHEHHEAwwAHKMKKKNOOMKMOPPPONIEHHIIKIIHEEEEHIIKMNOOOOPPPPPPPOONNMMKEEEIIIMMKIBwwABByo9|/~))!)~(<|59cc953|;;*&%$&$##########$$%*>))'>''){_}29ltwtwAEHBAAEGKKNNNOOOP", +"PPNKKMOPQQQQQQQQPPPQQQPQQQQQPPOONKHEHHIMKIHEEHIHBwwAEKNNOOOOONKKMOPPPPOKKIKMNMKKIIHEHHIKMOOPPPPPPPPPPPPOOONMIEBAAAEEIKIAtptAAwpf5|/~~~!)~/|59ccc93|''!!!!!!';;=*&%$$#####@##@@@$$&%>)~'>'')![:}5iwwtwyEEBABEJKLMNNNNNO", +"ONKKKNOPQQQQQQQQPPOOOOOOOPQQPPOONKHBBABIKKIHHHIIIEBBEKMNOOOOONMIINOPQQQPOKKNNONNMKKIIIIKNOOOOOOOONONOPPPOONMKHBywtwAAEEAwppptwywl9|/~~!)))~<39ccc953|'']]!!!!';;=*&$$##@####@#@##@#&&-,~)'''!{::}0itywwwBBAzAEIKKKNNMKLN", +"OMHCHMOPPOPQQQPQQOOOOOOOOOPPPPOONKIBAyBEHKMKIHIMMKIEHIKMOONNNMKIEINOPQQQQOOOPPPPOOONMMMNNNNONNONNNNNNOOPOONNMKHBywtttwwyyywtpptwwo9|/~)),,,)~<39ccc995|->,~<|59ccc53|-**%%%%&%%=;;;'!!]^!'';-*&%$$#@###@@@@@@@@#$&%>~{)'''!]::4dpwwwwBEAzAEHKIIKKHEIM", +"NKHEHMNPOOPQQPOONOOOMMMNNOOOOOONNNMKHHEHIIKMNMMKKIEwpptAEIKMKKKKKEBHKNOOOOPPPQQQRRRQQPOONNNNNMNNNNNNNMMMMMNNMMMKHEBwtolootwBEApfciolc3<~),,-;=-,)/|5999953|<<<<(]~]]/_/^''''!)'>---***&%%===;;''!!!',;;-*=*&%$###@@+@@@@#@#$$%;)~~'''!^[:39ltwwwBHBAyBGIHIKIEEIM", +"MIEIKNOOOOPQPONMMNOONNNNNOOOOOOOONNNKKIIKMMMNNMIEAwpliotwAHKKKKKMKEEIMOOOOOPPPPQQQRRQQPPOONNONNNNNNMNNMKMMMKMKKKIHEBAwpooptAHIEtiilifc9|~)',-==;-,)<3599953|<<<_/~]{]//]!)!!)]'-*********=*;;;,',!'';;;=*&%&$$####@@@@#####$$%='~~!'']^^|39ipwwwBHEAACGGGHKIEEEK", +"MKIHINOOOOPPONMMMMNNNNNNNOOOPPOOOOOOONMMMMMMMMMIEytpliklopwEIIIIKKKKKNOOPOOOOOOPPPPQQQQQQPPPOONONNNNNONMKKKKIKIKIIIHEEAAwptyEKMKHApf9cc9|(~)>-**=*>,~<3599971|<<)/{!!!^]|39ipwywAHHBACCCAEKIBAEI", +"KKEHIKNNMMNNMKMMMMKMMMNNNOOOPPOOOOOOONNNMMKKIIKKIEwpoikiilpwEIIHIIIIKMNOPPOOOOOOOOOOOOOOPPPPPPPOOOOONOONMKKIIEHHIIIIIIIIEBABEHKOPOEl539c93;==**->)~|359953||<]]]](/!!'!)~~)'-*%%%%&*=;;;;'!]!'';;=*%$$###@@@@+@@@##$$$%%&**;~--****->)/|559553|//]](/{!'',)~),-**%%&%&%*=;''!]]'',;-*%&###@+++++++++@###%&%**;)<<_/([:|79fowAyAEHEBBBAwAEHzAEK", +"OMEABHNNIHEGGHEHKKKKMKKMNNOOOOPONNNNOOONMMKIEBEIKMKEwpttppootAEHIIIHHHIKKKMMKMMNNONNMMNNNNOOOPQQQQQQPQPPOONNMKKHEEBEEEHHHHHEEAAAEKONEpf5|3599|~,>-****->,~<359905|<]{(/]!'''))!'-**%%&&%===-;',!'''';-=*&$#@@++++++++++@##$$%%*;,(<_//::179flwBAAEIHEAAyyAEBAAGM", +"NKAwAEKKHAzCBGCCEIKMKMKMMNNOOOOONNNNNNNNMKIHEBBEIKMKEywwwwtppwAIIIIHEEEEEEEHEEEIKMMMNNONOOOPPPPPPQQQQQQQQQQPONMIIEEBBEEBEAAAAywyyBKNNHwi5||5cc5<),>----->,)<|599933<(//]{''')!)'>*%%&&**==;;>'''''>;;-=&%$$#@@@++++++++@@@##$%%=-)<_(~:[_|5cipwAABHIBBAyyxzzyzAI", +"KIAwwAIIEAzABCzzCHIKMNNMMNOOOOOONNNNMMMNMKIHHEEBEIKMKBywwywtttwEIKIHBAAAAAAAAABBEIKKMNNOOOOPPPPQPQQQQQQQRRRRQPONKKIHEEEBBAABAywyABEHKMHwi5<|3cfc3/),>>>>>>,~<|599993<',)),>-=*&&%%==;;;','';;;=*%&$#$#@@#@@@++@+@#@@##$%%=-,/_({]^_|38cltyyzEIBxuuuuyzrrwE", +"IIBwwAEIAAyBBCCCGHIKNOOOOOOOOOOOONONMKKMMKKIIHHHHIKMMKEAwtwwtpwAHKKIEAwyyAyAABBBBEEIKNNOOOPPQQQQQQQRQQRRRRSSSRQPOOOMMKKKKKIIKIEEIKIEEKNKAo9|<|9ff5<~,,>>>>,)~/|599953||<],'>>,),,>--***%*==;-''';;;;=%$$###@+@@+++@@@###$#&&%%==-,{_>>>,,)(|3599555|:),';',,,>>>;>---;;>;'''>;;=%&$$##@@++++++@@@@###$%==-->>)/11_::_1379fpyyAzEBtpruuttqmuA", +"EEByAEHIAyxAAAHEEGGHKMNOPQPPOOOPPPPONMKHHIIKKKMMMKKKMMMIypoopoolotBEHHEAwtwwAAABBBEBEIKMNOOPPQPPPQQRRRRRRSSSSSRRRRRRQQQQQQQQQRRQQQOHAEOPPOKAti99fopi9|/~)),,!!~<|3555953|~,,>,,,>--->>>,;>>>'','>-==%&$$##@@++++@@@+++@###$&&*;>')(|33}::|35cfoyyAAAAtpprpttqqpy", +"ABAwyEIIAxuyABEBEEHIKKMNPQQQQPPPPPPOOONIIEEIIKKMKKKIIKKKEtllloliiotABEEBwtptwyyAABEHHHIIKMNOOOPPPQQRRRRRRSSSSSSSRRRRRRRRQRRRRRRQQPOIBEIOPPOKBwl9cflppi9|,,,>****->,,,,,'!!,;;;=%$$#@#@++++@##@+@++@##$&%*;-;,{<|72[[||59clwAAzAzwqqmpqtpnpw", +"yBAwwBKKEwxwzEEEEIIIHKMNOOPQQQQQQPPPPONKHAyABHIIIIIIHHIKIApolooolopwABEBAtpptwwwwyEKKIIKKMNNOOOOPQQQQQRRRSSSSSSSSRRRRRRRRRSSSSSRQQQOMHHIOQQOHAti999iptoc5|<<<<||||33599995|/)))),>****->,,,){]]!'>;=&$$##@+++++@#@@+++@###%*->',,)/_3952}|159cityAAAywrqqqutpoot", +"yBEAyAIMIBwAzAyEEEEECEIKMOPPPQQQQPPOOONKEAwtwyAEHIKKIHHIKIAtoopoooptyBEBAywttttttwAHIKKMMNNNNNNOOOPQQQQQRRRSSSSSSSSRSSRRSSSSSSSSRRRQQPNNOQQQMBwti955fotof5|<<<<||<|||355c95|>-;;;'',))]]{),;-*%$###@++++++++++++##$%-,~)){/|35fc94335bcipyAAAytppppwwtrot", +"yABAwyBIIByAAyzAEAyAABEIKNNOOPQQQPPPOOMKEBytttwyBIIKKIIIIIHAtpooooopwBEEBAwtttppopwyBEIKMNNNNMMMMNOOOOPPQQQRRSSSSSSSSSSSSSSSSSSSSRRQQQQQQQRQOHAAwof99fptpi93<<<<|<<<<1||555||<>>>'')!{{]))),>>-=$##@++++......+++@$&=>!)~/<|35ff953799fiowABBAwtpppwytppt", +"tyBAwwAEEAAywyAzyywAACzEFKMOOPQQQQPPPPNMHBAwwwwwwBHIKKIIIIHEAtpooollpwAEEByttpolloptyABEIKMMMMMMMMNNNNNNOPPQQQQQRRRRRRRSSSSSSSSSSRQPOQQQQQQONEwAEyof99fpwwof53||11<,>'',){]])'',,'>-*=*%###@++....++++#$&*->,)/(_|5cc52459fiopyAAywtppptwwppp", +"twBAwwABEBzyyyBAwuyyzyzAEKMMOPQQQQQQPPNKIBBAwtppptAEHIKIHHHEBypoopoilptABBAwpolffilptwyAABHIIKKKKMMMNMMMMNOOPPPPQPPPPPQRRRSRRRRRRQPOKMNPQPOIyoipBBti933cowwpf95|33||<(/~/<|||<<<;',,)!{]),',>--;*=**%%%$##@@+++@@+#$$$&*;;,'!/|7952|70filpwBBAAwpoptwwtop", +"ptyAwtyABBAxzBEAzxwywyzzFKMNOPQQQQPPPOMIHAAywpoiilptBHIHHEEEBAtppttoiiopwAAytpliffilptwyyABEHIIIIMNNMNNMMNNOOOOOPOOOOOOPPQQQQQQQPPPOMKKMNNKAoc9iyHyi5<<|5fpplc53333|<(~))~/<<<<|||/),',''''',){)''>--*=%%%%$%%%%$$########$$%&*=;;''!{122}:457filtABBBAtolowwoop", +"opwAwttyBEBAzAEAwxxuwwzBEKMNOOPPQQPPPOMIHAAwupokiilptAEHHEEEEBAwtwwtoiiloptwwtplifdgioptwyBEEHHIIMMNNNNOOOOOOOOOOOOOONNNNOOOPPQQQQPONMMMNNMIAoioAIAi9|/~/|9ili933||<<~)>;'))~~/<|||/)),,,'',,,,'',>-*&%%$####$$$$$$$$%$$%%&***---;'!!!{13}[_1|85cipwAywpiijopoll", +"iopwwtptyABwtwzywtwuqwAAEKKNMOOPPPPPPONMIEAyutpolllootAHHHHHHEEBAAAytpliiilptttplifdfilotwABEEEHIKMMNOPPQPPOOOOOOOOONONMMMMKNOPQRQQPOMKMNNNNNHAwAAti93/~~~<9iiic53|>,)~/<;*&$$$##@@@@@@@@#$$$$*=*->->,''!!{){<43:^_1|439iptppifccgiifi", +"filpwpootyAtppwxptpuqwxABEIKMOOPPQPPPOOMKICAywtqpppppptBIKIIIIIIHEBAwtpoiiilptwtpolifiilmpwABEEHIKKKMNPQQQQPPPPPOONMMMMMMMNMKKMOPQQQOMIKMKIKNNHApof993**%**=->)////)),>;;;;>>';;>-*&%$##@+@@@++++@@@##$%*->>,)~{//~(/<|52:<<__|29looli9589cfcc", +"cfiottllpwAtlltpqqpoqqwAyzEIKMNOOPPPOONMKKEBywttqpppoppwEIIHEHIIIIEAwwwtplilotwAAywwtppoopwyBEHHIHKKKMOQQQQPQQQQQPONMMMKMNNNNKIKMNOPPONMMHBBEHEypf953|||/~))/5iolc5|/~)>**%%*&*->)///~),>>-;;;>>;;--*&&$###@+++++++++++##$$%*->,'{{////||5832}:}269ioolic977cc99", +"fiiowwpoopAwpopplmmlqqwuxzBFKKMNOPOOOONKKKHEyttpppooolotwBEEBBEEHHEBwtttpoiilowAEEEEAAyyyyABEHIIKKIIKKNPRQQPPQRRRRQQONMKKMMNNMMMMMMNOOOOOKEAyyAwtof5|<<|3<),~<9lpi9|-*%%*&%*-,~//~~),,>>;;;>;;*=%%&$##@+++++++++++@###$&&*-;''''!!~~_|593321359fptpoic90dcfc", +"illpwAwpotwywtpolikinuuwxzAEIKNNOOOOOONKKIEBytuoolololooptwBBAABBBAAwpllllifcflpwyAAAAABBABEEIIKMMMMKMNPQRQQPQQRSSSSRQPONNMMNMMMNNMKKKNOOONKEAwtttpi93|353/))/3cilf5|<~,-=*%%&%&*-,~///~)),,>;;;;;-*%%%$##@@+++++.++++@@##$&*=-;'';''''')/|3|<<<<|39ipppoic9cfif", +"iilpyEBwttyEEywpiikgjquwtxzFIKMNOOONONMKHEBAytplkilllollloptyAywwwywwtoifiif999cilptttttwwwAABEIIKKMKKNOQQRQQQQRSSSSSSSRQPPONKKKMMMIIEEHINOPPNHyttwwpi9995|///|39ilf5|/)-*%%*%$$$%-,~~~)~)),,>>;;;-*%%%%$#@@@++++...++@###$&%=*;;;;;;;''''/<<~~!){/|5ioolifc9cff", +"cciltAEAwtwEIHAyoiigjiqqtwzDEKKMMONNNNKIEBAxwtqplkllllliililpwwwtptttpplififc55599floooppppwyyAABEEEIIIMNOQQQQQQSSSSSSSSSSRQQONMKKIHHHBBABIMOPOIBAABAwoc53|<<<<|39ilc3<~,*%%%%$###%*,,)))))),'>--;-*=%&%%$$#@@+++++++@@###&%%*;;;;;;;;;;;')/({''''!{_5fifc95599c", +"59cciwBBwptAIIEAtligdemmtwzAEIIMMMNNNNKIEAyuuppqollifeffiiiiiptwtppppppoliffc955555cilloppptwwyAyyAAAEEHIKMOPPPPQSSSSSSSSSSSRRQPOMKHHIEEBABEIMMMMIHHEBwoc5|<<<<|35fiic|/)>%$%*%####&=>>>,)))),,>>--*=%&%$$$##@+++..+@@####&%&*;;;;;;;;;;;;'!~{';;;''{<0cc953|359", +"95359lyBypptBIEAtiebdemmquxAEHIMMMMMMMKIEAAuqomqpomiicccfffgilpttppopppooifffc9553359filooppptvwywyyyABEHHIMOPPPPQRRRSSSSSSSSSRRQPNKIIHIIEEEEEEHIKMMKIEyoc53|||5559fol9|/)-%%%%$#@@#%*-->,,))),,>>>-*%&$#####@+++..+++##@#&%&*;*;;;;;;;;;;;')),---->,~|9995||||5", +"95259fpAypopyEBypicedeempvuAEHIKMMKMKMKIECAwuqmmoppoifccccffiilpttppoooooiifffc9533599fillopptwwwwwwxwyAAEEHKNOOOPQQQQQQQPPPPQQRRQPNIHEHHEEEEBAyAEIMNMMKApic5339c95cotl9|/,-%%*%#@@##%***-,)))),,>>-*%$########+++++++@#@$&%*******;=;;;;;;->),;===->,~39995||<3", +"35359flwytolpwwppifeggjmpqvxDHIIKKKKKKKIECAysrnjoppuplfccccfilllppppooollliifffc9555559cilopttwwwwwwwxwwyyCEIIMNOOPQQQQPONMMMNNOPPPOMIIEBAwAAywwttyEKMNNNIAtlc9cfc9cltti5<)>*%%*%#@@#$%%%*-,))),,,;=*%%$###@###@+@+@+@###$%&***=*&%&**==;=*==',>-*%*=>)<5c905||3", +"5559ccfowwoifooppofffgjmmrsuDFHIIIKKKIIICCAvurnkmnpppolfcccfloolloppplllliiifffcc9557550cfipptttwwwwwyywwyABBHIMNNPPQQQPOMKKKKKKNNNONNMKHAwwttttpoopwBIMNNNMHAtppoolotwo9|~,-***%$#@@#%%%%*>,,,,,,>=*%%$$###@##@@@@@@##@#$%&***%%%%%%&*=**&%%-,,>****->{3cc99953", +"5555599fopofdilptpihhgjmmruuDDEEIIIIIIIHCByvqqmnmolilllifccfioooooooooliiiffffcc9955333599fiopppptttwwyyyyyAAEEIKMOPPPPPONMKKIHEHEHIMNOONKEAytpoliiffipBKMOOOOMIHEAywAytf5/)>>**%%##@#$%$$%*->,,,,>-*%&%$$$#@@@#@@@@+###$&%&****%%%%%%**%&%%&&;'>==&&->,<9ffffc5", +"333||425fomgc9ipwtibegemmrtuxDBFEIIHHHIHEAyvuqqnmoifgiiifffffioppolooooliifffcc95595533335afilooooppppwwxwyAAAEHIKNOPPPPONNMKKHEBAAABHMOOONKIEwoifcc99cltBINOOONMKIHBBAyo9|~),-*%%$###$%$$$%*->,,,,>-*&%%$$#@@@@##@@####&&%%******%%%**&%%%&&=*>,,-;;->)<5iiiif9", +"1<<|_<139ipld0fowwocfgjmmrsuuxDBEEEHHHIHHBDvtqropomfddgfifcccfiopololloliifcc9955555553337adfjilllllppptwwwwzzBBEIINOOOOOONMKIIIBAwwwyAIMNOOOMHwof999599flpwEKNMKIHHBBAyti5|/~)>-*%%$$%%%%$%*->,)),,>=*%%$#@@@@########$&%%****%******&%%&==***>)~),>,'!/|ciffc5", +"_(<<<<122cloidcitypffhhmmrvvsuxDBEEEHHHIIEDyuusppmlfc0cdfffc99cioooolllliifc99553355557735a0behiikilooooputwAyAAEEJMNNNOOONMKIKICytqpptABHIKMMKEwof953599ccfowBEEAwwwwwwti953-*%%%%**%%%*=->))),>-;*%$$####$##$$$$$$&%&****===*===**=;--**->)//)>>>,)/|9c995", +"<((<-%%%%***%%%=->,))),,>-*%&$$$%%%$$&&&$%%*=*--*=--=-;-*=;--*=**=-,)'-*-->,~|9995", +"|_(__<(_}39loifciopifkljmmponrruuABBBBEHHHEBywxttpoofb99cffifc9059cffffififfc955333599990999ddcchgeiijonlrqptxxzECCHIMNNNNNOMKIHAuqjjkhinloooptyBBypf5||35559clpwwplifc99|<|3|/~~)>-*%****%%$&*=>>,,,,>>-*%%%%%%%$$&&&%%&*****=*==*=**&&*%%&&%%&%=>';%%**>)/3999", +"5|_(<*%%*-*=&%%%**->>>>---=&$$$$$$$#$$$$%&%&*%%&&&&&&%$$$$$#$&$###$*;;*&%%=;,<599", +"93<_<<-*%*---*&%%%**---;-***&$#######$###$$$%%%%$$$&&$$#@####$####@@#%=*%$#$&>)<55", +"953:_<|<}}}5fooic9c9bcijmolqmmppuwxAABABEEEEAyywwwttpoieccdcc999997333599ffffffcc99535599ccc88a99cdhfilonorqpxxAACEHIKMMMNMMNNMMKEAuqjjg8664}||59fiopyBBytl93||39iwBBtlf953|3|/),,,>-*%%=>,>-*******--**=%%$############&%&%%%$$$$#$###@#######@@@@#%=&$#$&=>)|5", +"5954||3|22239ipoicc9acfiooolqpqttwwyAABABEEEAyywwttpplkicccfc99999553|3559ccffiiiffc99cccjiiffcccdchiklooorqtxwyyBCEKKNNMMNMMNNMKIEAuqjg8a24:<<<|359ipyBEEAti93339ipwtplic533|>-**%*-,,>=*-*==**=***=%$$##########$$%&%&%$$$$###@@#####@@@+++@@$&=%$$&&->~|", +"35553|3352226fotoifccciioooolpmmttwyAABEEEEEAyxtttqoooiiifcfc995999955559cffiloooooliiiiilloliiifiilloopppttwyxAABCHIKNNNNMNMMMNMKKEwuigaa21:_(///<|9ipwAEIHAof5535ciptpoic533|>--*%&=>,,---*=***=*****%$##@@######$$%%%%%&$$####@@@####@+++..+@#$==&$$&*-'<", +"|599955555559cittoieciilioomlnmopttwyABEEEEBAwtprrppoookggf9c999999cccfcciiiilppppppoollliiiiiiiiillooopttwyyAAEEEHIFMNNONMMNMMNMMMIExuke861[_(~////|9fowAEIHAtf95559ipttpif953||~)>-*****-,,,-*=&%%%=***--*%$$#@@#######$&=&%%$$###@@@#####@@++..+@@#%;*%%&*-'~", +"<59ff99999599cfowtlfffiiilooonlomttpxwAAEBBBAytpqqpqplllgccdfcccffiiioliiiiilillloooolllliicddccfgiillloppswyAAEEIIKMNOOPPONNNMMNKMMIEymib64_[]{//(/||5iptyBEHBtic999cipttpiffc95|/)>**%%%*-,,>**%%%$&%**---**%$#######$#$&**=%&$###@@@@@##@@@@++++++#$=;-*==-')", +"/39fifcc999599cipwplfifffilooolimmoouutwyADAAAywtrrmmmiiiggdgiiilpptpppliiiiiiifiilllllooolic9099cfigiiknopuwzzBEHIKMNOOPPPPOONNMKKMMKEwoia61[]/<||||||9fiopyBEBwoicccflppoiffffc95<)--***=-,),-*%%$$&%%**----*%$###$####$&%%**%$$#@@@@#@#####@+++++@#$*;,>>;>,)", +"~|5fiifc9999559fottpliiffcilllkikkglnrpuuyAAAAywwpqrnliiiilikllmopwAywtplliifififiilllloooolic0899dffiijnlrutxxAEEGKMMNOPPPPPOOOONKMMKIBwof94}<_|33|>>>>>,~~>-=%%&$$%%*->->--*%$$&%$$$$$%****%&&####@###$$###@@@@@$$=>)))>,,)", +")<3ciiiifccc999ciottoifc988fffgdhgggmlrquwAAABAwturpqomoploollllopwyyttptplliiffffffiiillliiifd99999fiijnloqtxwABEGILMNNOPPPPPOPOONMMMKIEtic62<_|33>>,,>,)~)>-*%&%%%%-->>>>>-;**&**&&%%*;**=*&&%%$&$$$%%%%$######$%%=,~{),,,", +"~/|0ioooiiffc95559iolfc986a9cfegfbggijmmquyAAAAwuqquuttttpoooiiiilopttttttpplic99999ccfiiifcfccdc800cffilloqtxxACBCIKKNOOPPPOPOOONMKKKMMKEtl92__<|3->,,,,,)~,-**&%%%%*->->>>>>------=*=--*****&%%&&$%$%**%%$#####$%&&-)//),)", +"/<|5cioolic995|||19fic999626bcfgdbgggiinmqwyAyyytpquttwttuppllifffiloopttwttplf955599ccffffc9c9cc990dccfjjmqsuuyCEEHFMMOOPPQPOPOONMKJHHIKIEyoc3|/_|<-&&%%$$%**;->>>>>-----------***==%%&&$$$%***%%$$$$$%*=*-,/-==%%%&&&*-->>>>>--->>>>>>-;--=*%%&$%$$%*---=%%%%%*--->,)<<>,~~,>==*%%%%*-->>,,,,,>>>;,,>>>>>---***%*%%*-->--**&%%**=**->,~/~", +")'''')/|9993|<<<((/(<7c9056266dcfghgkkooqrqtwyABBAAywtpommlkiiiiffcc99ccfiiiiopwyytlfccfccc99ccccccfiiiiloqppxAEEGFFIMMNOOPPPPOONMKKHEAywwwyAywoc53353|<|553|3359fflliiltBHHEyo933333||=&%%%%%%*-->>,,,,,,,>>>>>>>---**=*%%%$$%**%%%%####$&&%%&-,)~", +"!!''>,){|553|<<<_({~(|9c90566689ffgfkknlqrqtyBEEBBAywwpolkkfggccfcfccc9cffffffipwAAwpiffc9999c9cccfgifilloqpxwBHHHIFILNNOPPPQPOOOLIFCBAxtpptwAAtl9533533599533359fiiliiopyAEEBApc99993||,,>&$######$%**-->-----;--*=-***&%%%&$$#####$$#$###@##$$$&&*;>!", +"!!';-;''~|553|<<__{{{(|9cc0866889fgikklinnqtABEEEEAAywtrllidd90999cfiiifffcc9cffiotwwtoif9999c9ccccfiiilinmpuwAEIIKKMMONOPPPQPPOOLIFAAyurmmoptAytof5||||59fccc99cciiloopptABAABApifff53||<~),>**-,,>*$$#@@####%%**=------=*%**%%%&$##$###@@@#######@@#####&%%&*>", +"'!!>;;;-,~|553|<__({]{_49cc066aa0fkifkglnrptyABEEBBBAAwpolif9999099ccffffffc99c9ccfiotttoi999c9dccffiiilnnmruuAEHIMMNMOOOPPQQPPOOLLFBvwqrmieiiptwwplc5|||39fiopppiiiloopppwBAAABAplii9533|/))>--;>>>-&#@#@@@@@#$%**-----;=&%%&%%%$######@++++@@##@@++@@#@#$$&%%-", +";'!,';--;,~|5531<_>-->>-&#@@+++++@#$$%*----*=&%$$&$##@@@@@@@.+++++@@@@+@@##@##$&%==", +";;'),'-=->,~|553|<|<_(~][20cc969afgkimioptuuwwwyzAAAAAwwtpoifffc995573559cfiiifc955599flppoliccccgfiiiooopqppuyyBGFKNNOOPPPQQQPOOOLIFzvtqkeb96259iopoic99599ftINIAwwtpoollowBEHEEAtlf955993>-*$#@@@++++@##$%******&&$$$####@+++++....+++@@@++@##@##$&%==", +";;;,',>--=;,(|5353|1<_]/_}29cc98ccfiommpptuuwwwxwyxwxwwwttpolifcc9533333559ciilic953599cfloollicccfiiiiolpqqpuuyACHKNNOOPPQQQQPPOOMKFzzwqkij96}||5ciif93359cipEKEtooppttpoopwAEEEBwpif99cf93|<>--&$#@@@++++@##%%*****=&$$#$$##@@++++++.+.++@@@@#@##@$#$%%=;", +";;;;,,,>===;,(|35533|1_/(:}5cffccbfipppupsuuwwwywwwwtpptttppolifc99533333559cfilli955559cfiilooliiiiiiillloqrwuyCCEKMNOPQPQQQQPPOONMKCByumjjc9}<_|39cc9|<<39flAIBpc9cipwwtppttwyAAytoifffi93|<--*&##@@+++++@#$$%**%%%*&$$$$##@@++++.+++++++@@@#####$$&%==;", +";;;=>>,,-==*-,~|35577|1,';***-,~|555733||}:15ciilfffltutppqptvwwttttttpppoomoliiiifc955333355559fillif9909ccflottpoolnlmlloqqpuyyACFKMNOPQRQQQQPPOOOKHBAupojeb52<(/<<399|<~/|9iwEAl9599cilptwwtliiottpifc95||,'-***-,/|55557552}|38dfllikipqqppqpttttttttttppppollliiiiiffc953333353359filiic9009cflpttpppppppoooppxuyBCFLNNOOQQRQQQPQOONMICwurmjeb564|(]{<355|/~~3fpABtfcffiiilopwwtiffiptoic93-****$#@++++++#$$%%%%%%&&%$$##@@@@++++++++++++#####&%$%==;;", +";;===**->>>-***-,/|59599c96|458ciloooqmpoqqpsttttttttttpppooliiiffiiifcc955333333559fiilic909cloptwtwwwwtpppptwwABGHKMNOPQQQRQQQPOONMICzqlkfa85434_~{~<355|~~/5iwAwicfltwpolipwwtlffiptpof5|/~/~,,)~)>*&**%##@+++.+@#$$%%%%%%&&%$##@@@@+++++++++++@@@#$$&%&&=;;;", +";;;===**=->>-***-,~|5599cfc556a8flpttpmooqqpppputttttttpppooomiffccfffiic995553335599cflolifcdiotwABEEEAwwtwwwAABEHIMMOPPQQQRRRQQOONMICAwqkbb67}<1|>--*-;,/|599cfid9a66cipwwwppopqqprpuuttttpttpppoollifcccccffiiffc955755999cfloppollotyBHIKIEAywwyAEBHIIIMNOPPQQQRRRQQPOONLEztqjhb64[_/(/>>-*;;,(|599cfifc66bfopwwtttuqmopppoppttptttppoooliiifcccfffiillfc99999cccfilppttpppwAEIIIHEAyyyAAEHHIKNNOOQQRRRRRRQQPOOMIBxqjhb62_[{{{~//~~/|53|<<|5cooiipyEIKIHAywywwtpllpttof3/~)),>,))>*%%*%#@++..+@#$$$$%***&**%$#@###@++.+++++@@@###&*=-;;;;;", +";;;;;-=**&==->>>;;>>)/|55ccggf99ccimpwwywtpmmmponoppptpttpppoooiiiifffiiiiloolifcdf9ccffiiilpttttwwABEEEEEBAAyAEHHIKNNOOQQRRRRSSRQQPONMJAulkb861[({'!)~~~~<|33|<||5fiiilwBHHBAAAAAywwtplllopoc|/~/~,,'~)>*%%%&@++..++#$$#$%%*=&***%#@@##@@@+++++@@@####&%=-;';';", +";;;;;-=***===->,';-;''(|59ccgffcfehklptywtppopmmnnoooppttpppppolliiiiiiilllooooliiiffcdcff9bfltwyyyyyAABBEEEECAEBHKKMNOOQQRRRRSSRRQPOONKHzrmf861[({!,,,)))~<3553|||5cfiltAAwppttyBAywwwplilptpf3|',';-''!{|99cfefilifgjmqttwtppoomlnoopopppttppppoooooliiiiiiopppooolifc999d99ciotwAAywyAAAEEIIHEGBEIIIMNOPPQRRRSSSRQQOOOMKHAulia7}_({),,,,))~<3995|||39fopwyplillpwBAyyyypliowwtic53|//~/~,-&%&%#@++@@@####$%**=****%#@@##@@@+++@@@@##@#$%*;;''!!", +"!'';;;=;;***===;',,',''{_26cifiopplkiimoppppololkinoopoppppttpppppoliifffffoptpopmlic97759a99cfiotyyyywwyABBEEHHEEHEHKMNOPPQQRRSSRRQQONMKIBysric0a|_~)',',,,)<3995|||3clptwtoiffiptwAyyAytllpwywpi953|*%&%%#@@@@@@##$$%*-*****&&####@@@@++@@@###@$%%*=;''^^", +"^!'';;;;;****--;>,,!'''!{:29fiipptpojiiimmopooiiikiolooppppptttttpoliififfiottplifcc99079909099dioptwttttyAABEEIHHHEGKKNNOPQQRRRRRQQPONMKIEywpolfc93|(~))',),~<3999|||5fllopplc99foptwwyAytpopwwwtof99|<<<)-%$$%$#@@@++@##$$%*=-***=&$@##@@@@@@@@@####$%&*=;;'^^", +"^^!,';;;;;;**----;,!{!!)^]16bflppwwplkifhfllmlliiggilloppppttwwwtpoiiiiiiilpwtlfc055999c05508888cfilpppptwAABEEIIKIIHKMMNOPQQQRRRRQPPOMLIIEAwtolffc953|<~))))){<59c93<|9fffillc559fioptwyAywwwwwwwwpic53||/,*%$$%$#@@++@##$$%==--=*=*$####@@@@@@@@####$%&*=;;'!]", +"!^^!''';;;;;*----;>'{]{{^]_16cipptwtpokddccfililfffgfilmopttwwwttpoliiiiloottoic933375599009d909ccfflopttwyABEHHIKKMKKMMNOOPQQRRRRQQONMFGEEAwppigcdc9953!!", +"{!]^!'''';;;;;;;;;;'!~]:^(:228ioopptpplgcd09ciiiiffddfilmptwwwtttpolliilppptpic9553|433599ccccccccfcilptwyyAEHKIKKNNNMMNOOPPQRRRRRQQPONLEBAxtplfifcc99554|<%&%%%$@++@##$%%&*---*&=%$###@@@@@@@@@####$%&*=;;!!", +"{!!^{{!!''';;;;;;;'',!{[::_}26biopppppolgd00a9fffiffddfilpttwwtttpooolopttttoic9554|}1|35dfcfffeffgilopwAEEEIMNOOOOPOOPOOPQQRQRRRRRQPONMHCAxtnied9999555543||||<--&&%%###@@@@@@@+@@####$%*=;;'!", +"!{{!^^{!)''''';;'''''']^:11}26bbeiloooooifd0786ddgfffddiiopppptttppppopttttpofc95511<|13559cfilliloptwyBEKMNOPQQQQQRQQQQQQQQRRRSSRRQQPNMKECxsqib8967575555533333|<<|59fc53599ciof5|||5cfiffioyEEEEBywtpoli9**%$$$#@@#$$&&**----=&%%$##@@@@++++@@@###$%&%=;;!", +"!!{{{]^^!!!''''''''''!^^_162668abcfilllliic9776500dfifgillliopptttttpptppttplfc953|||3543559ilptttttwAAEIKNOPQQQQQQRRRRRRRQRRRRSSSRRQQOONIHBytpkb85633755555337553|<|3cc9559ccili93<|5cfili99itAEHIBAwtplic5|~,--%%$$$###$$&&**-;--=&%%&##@@@+++++++@@###$%&==;;", +"'!!{{(^^^{!{{!)'''''^^^(_}2aaab888bffiiiiiic9725500cfiiiiifiiloppttwwwtppppoic9555333555559fiottwttwyBEHIKKNOPPPPOPPPPQQQQQQQRRRSSRRRQPONKIEAywplf9a4773334333335553||599559cfiiic3<<3ciilic59fowBEEAywtoic95<~,;*%$%%%%$$&$%%*----==%%%$#@@+++++++++@@#@#$%%=;;", +";!!{{{({^^^^({{!!'!^^^^(_}}26cba8aa99cfjffffc9732357ciiiiifffiilpptwywtpptplf995555595999ffiiloptwwyAEHHEEEEIKMMMKMNOOPPQQQQQQRRSSRRQQQOONKHBAAwtoi995573||||33||3555359c95559fiif9|<3ciloif9559fpyBBAwtplc95|/~,>*%%***%&&$%%*=----=%%%$##++++++.++++@@#@#%&%=;", +";;!!{{((({^^^[[[^^^{^{(_}}}28bb98aa868accffccc9743570ciifffffiiloppwwttttwpic953559999cfiiiffioptABBBBAywyyyAEHKKMKNOPPPQQRQQQRRSSRRQQQPONKKEAywytqlf9053<<_<<||||335359cc95359fiif9339ciolic54|39ltAAyytpi95|*%*->>*&%%***-->>==%%&#@++++....++++@##@#$&%=", +"=;;!{{((_(((^^^^^[^_[(__}}2268ca698a6a6689cccfc976357ccccfffffiilptttpptwwpic95359cffiiifccciotwAAAywwwwtwyABEIMNOOPPQQQRRSSSRSSSSSSRRQQPOMMIBwwtttplc997|<<(//<<|||33359ffc5339ilif9559ciiif951<|9ityyywtpi93**->>-*%%%***;>>;=%$$#++++.+.....+++@##@#$%=", +"=;;'!{{(____(((__1111122}}}66866a6aa2}}}65999cc9d959999999cfffiilptpooptwwpic9559cfilifc99flpwyAywtppwyAAABEHIMNOPQQQQQQRSSSSSSSSSSSSSSRQPONKHAwpppoifd0554|_/(/~/<||33359fic535cilifc959cccfc9|<<|5fptywtplf93--;>>-****=*->>;=%#$#@++..+++....+++@#@@#$%", +"%=;'!!{___}}__[___1122222266a22226662}[:[2355999cc99d95559ccffiioppollpttplifc9ccfiiic999ipwAytppppttyEHIIHEEEIKMOOPQQPQQRSSSSSSSSSSSSSSRQPONKHBwtpoifc9577553<<{//<||33|39iif959fiiffc99959cc93<;-;>>>-;;***->>;%$#@@@...++++....++++@@#$&", +"&%=;'!{___}}}}}}}}}2226a686a222222662}}:[:}225799cccd9955799cfilopplilpppliifffiillc535clwAAypllotwyyBEIIHEAAyBEKMNOPPPPQRRSSSSSSSSSSSSSRQQQPONKHEAyplifd5559553|>>--;-->>>>*=*;>>;%$#@@+............+.++@@#$", +"$&%=;'!(__}}}}2}}}}}}2268aa86622}22222}[:[[}}32399dff99555599cflppolilopliffffiopof5|3fpABBytooptyAAyAAyAABAAAEIMNOOPPPPPQQRSSSSSSSSRRRRRQQQQQQPPNKKEAwtlf95555953||<-->>>->,,>**->>;*$#@@@+..............+@@@#", +"#$&=;>'!(}}}}2222222226866626662222}1}}}1::}}[}|300c9999955999fipolliiooiffffiiooi935cpAEAywtttwwyyytppptAEHIIMMNNNNNOPPPPQQRRSSSSSSRRQQQQQQQQQQQQPOOMIEypic53|33|33||<|3|||39ilfc9cfiiffc553553|<<->>>>>>),,--->>-*&#@@+++..............+@+@", +"@#$%=;'!^:}}22886666666666626662222}}}}:_:::__::|3795999c9999cfloliiilooiffifillf999coAEBwtwwwwwwwtoiiopAEKMNNNMKIIIKKNOOPPQQQRRRRRRRQQPPPPPPQQQQQQQPOOMIEwpic53|<<|33335955|39fifccfiliic93|333|<,,'>,,),,--;>-*%#@@+++...............++@", +"@@#$%=;']{_}}2866666666666}222222222}}::::<:}[::}|3335799999cciiiiifiioliiiiiiic559coAHEAttwwwttpliffotAHKMNNMMIHBEEEHKMNOPPPQQRRQQQQQPOONNNMNNOPPPPOOOOOMIEAwpi9|/<||3335993335cfccfiooli953|<|--;-=%#@+++.................++", +"+@#$&*=;'^]_}}866666666666}}22222221}1[_::_:}}:_||11|439999cffiliiiffilliiilllf559ciwEHBwwwtttplfcciowBHIKKIHEHEBABAAEEIMNOPPQQQQQQQQQPNNMKKIHIKMMMKMKMOONNMKKIApc3<<<|||35555335cfccflopoic9|//~~~)))~//<39iif9335995|/~~{)){!)),>---*%$@++++.......... .. ...+", +"++@#$&*;;'](_}266666666666}}222}22}}[:[::[[/}||:|}1<<||55999filliifffilifiloplc59fltAEAwtwtpptlc79itAHKHHEByyABABABAABEIKMOPPQQQQQQPPPONNMKIIHHHHIEBBABIMMMMNNNMEti93;--%$#++++...... . . . ..+", +"++@@#%*;;'!^(_}26666666666}}222}22}[::::]]]:<<||334_|||33559filliifcfiiifioppicciopAAyttptpttof50fpBIMKEEAwptwyyAACBABBHIKNOPQQQQPPOOOMMMKKIIHHEEHEAAwtwABBEIMNNMHyoc5|////<<||||59cfffloppoi93/!,,)),,)<<<<|59c953||5cc93|<-*$#++++...... . . ...", +".+@@@$%*;;'^^(}}2666666662}}222}}2}[::^^]]]::::}363||||1|355cilliifffiiiilopiccipwAEytppppptpi99itBHKMKHAwpoppwwyAEEBEBEHHKNOPPQOOOONKKIIHEEBBCBAEBAAwttppptwBHKKIEwpi93|///<<|3359ffffiloppoi9|/))))),,)/(//<35995335cffc95|,)~~~/<|595559fiifc93-',))))~<359999fllif93*%@@++... ", +" ..+@##&%=;''!^(_[}66666666226222a642}}}<<::_::}|1_<:|1|3557cfiiffffioopptplffoAHIHypollppi95fpEHBywtpolproppwywttuzEHIECCFFKNOOOONMHIIEBxxppmlhjffffgfloomlliffiotwAABAAwtpf53||350ciopifcfiiiic5|---,,),,)/|59555fioif93>-;->,,,,)~|55559fillf95_/!)),>>-$#++... ..", +" ....+#@#%=*;''^^_}}}6a6a99899889b99652|}1:_:]:<<_(//<_|||359fffcc99flopppliltEMMKApifipti95iwHIAtpopptwwwwAzwpnnquAEAEEJHIFKNNOMMMIHEEEAAAtqqlgeba87976809cgiifffiffilpwBEBAtplic95439cfc99cfioolc5|>>---,,,,)/|3559cfiolic5<{~),>--*$@+.... ", +" ...+@##&%=;;''^(_[26a688aa99cccfg99522|||<:<:||<__/__|<||59cfc9999floppoiioAKNMEwlfclto939oAIEwpppwBBBAABAwppnquwEBAABGKKKKLNMKIHHHHBBAAwtpooiica8774263779ccccfcffccfltAABAwtof9533|599ccciiopoi95|>>>>',)),)/|399cfioooic5|<~,>--*%$@+++... ", +" ..++@##$&%*;;'^^{[}}6689aaabbcfif9956333|||||4|||<|_<|<||79ccc9959flopoiilpEMNIApiffpti53fpAHEwppwEIIEBAytuprrtxAEACzCCKMMNMMKKICEHHBByAwwqroolfda573}24347759999cc989ciowyAAwplf957||359ciiloooic93||/),>>,>>>>,)))/<59cilooolic93<),>-**%$@++.. ", +" ..+@+@##$%=*;',^{_[26688a98999cif995532533}||||<|<1__|||359ccc9959flopoiiowHMIBtliflwwf90ltwBEAttAEEEAywtpqtttwyABAAAzBFLMNNKFFECBEEEAyywtupoooigca74}}1|14335355999999dgltwyAwpoif973359cffilooic9533<~!,>,,>-->,))~/|9cflllliiif9|/'>-*%%%#@+.. ", +" ...++#@##&%*;;,!](}}2aaa66809a9fic9966333}:1<|1:<___||||3599999559flopliotBIIBwoffipAtf9foptABAywwywttttptpttwuuAAEBCCGHKMOOMKIBCCCBEAAwwuupppplifc77}}211114|33369909999ciptyAywtoof95599999filif9533|-->)///<39ciiiiifffc5<),>*%$$##@+.. ", +" ...++##$$&=-;'!^[_[266622aa86dcec9965334|1_<|}:<___|<||3399995559flopllpAEIEypifflwApcclooptyywtpojnoptttpspuuxyAEEGEIKMOOOONKCCBEBEBEAywwwtppoiie97322|1||1|||||7589999cfiotyAAAwtpic55555359ffc53||||<<~~),>>->)/<||359fiiffcccc9|<~,>%$#$###+... ", +" ..+@@$%%=-;','^^(_}6662269989bb900077574|||||<|1__|<||1399995559fopplowBIIEwofcfowwlcflolloopligceiopptqttwxuAAEHIJIKMMOOOOOMIJEEEHEIHEAAAwwtpollc9722|1|11<||_<|2695099cfiopyABAytof953333|39c953||||||>--,~/|35999cfcc9955553<~,-*%$#$$$#@@.. ", +" ..+@#$&&**=;-;>'!{[[26622a8888dd0076777734333341|<||<|14599995555flooiowEIIEwl99fpwti9fiiiififcc9cellopqqpzyzBBEEEHHKMMNOONOONMKKKKIKMMKIEEBAwtppplic96733|11<|_<<|||23350ccilpwyAAwpic53|33|||5553|<<<|||->,)~<399999c99953||555|/,>*%$$$%%$@+. ", +" ..++@@###$&%=*-;;,!!([[226aa88d00d077424633333574||||||||4599955339flolipyEHHBti99fpwoc5cff999ccdccffijoomptAAABBEBCCILLMNOONNOOOOONMKKMMNMIEBAypppppolie0955|1|||||<<:<<|379dggilpwAAwpi933353|<|33||>>,)~<|59c99c99553||3595|/,>-%$####@+. ", +"....+++@@+##$%*=*;'!!([[286660dd000a666224233355531|3||3||3999975359flolipAEEBAoc59fpwoc59c03439cddchfiloqqpxwyBAEEGCEFFKNNNONOONOONKIHHIIMNKHAAypolloollfe9090334|||<<_<::|25ciiifiptyAytlc55995|<|||<<~~~<|33|/),>>,)/<|3599c995553|||555|/)-%$#@@@@+.. ..", +".......+++@##$&*-;>'!([[286000ddbbca6622}}}43435311|||3|||3999995359flolltABAyti959itwl939c931409999cfiioqrpwwBEHEEHIKKMNOOOPOOONNNMHEAAABHKMKEBAwpoiliiifc999099953||<|<<|<}39fifffiptyAAyof9ccc9|>,,{<|||-*%$$##@+. ", +" ...+++@##$%&*;'^{[[260088bbggkkgd07744411355||<|||_<|3599995335flolpBEytoi955coAwf3|3|||<||279fiigikopxAEHIIHIKMMOOPPPONKIHCGEIIKIHHEEHIKMOOOONIBywttolfc909999cccc963||2|433||||359ipwABAwpoi9|{]~)'>,>>,~/|3||*%$#++++.. ", +" ....++@##$&&*;']{([28088bbkggkkgd07a46662553|||||<<_|3599995333clolwEEwpif535coAtc||31_<13769fffffjmpwAEBEBBEHIKNOOPPOONIFECGEHEIHIHEEEIIMOPPPPOMHEAwwtpliilifcccffcc86532||4|<_<<||3dotABBAtoic|~!)),,,,>,)/|33||%$#@+..... ", +". ....++@##$&%*;;!{^[280b8ggkgggklifd98676265334||||_<|3599995333clllyIEwlfc5|3coyt9||3|--'/|3331|<||39c97|555553|<<~,>->)<||~>%$#@+.....", +"........+++@##$&%==;!!([28abghggggmlligfd866533952||||1_||3599995333ciloyIEwlc9||3coyp93334-=;,/|35533559cgf953333||-%*,~||/,*$#++....", +".++.....+++@##$&%==;!!([280hhggglljmliffd9668a6952||||1|||35999953339ioowEEwic9||5cpyp93334|<<|769fillpxwwutwvxzDFIMNPPPPPOOONOONKIIHIMNOOOOONNNOPQQQQQQPPPPPNIHEBywtpollf99999553|1|_/_<|3|359ipwywtpic|/~~),>;-=-)<39c9c99cfffc72|<<;*%%-)/|<)-%#@+...", +"..+++...+++@###&%*=;'!(:2a0ghhgllllmliffcd95607055|4|1||||3599c953339ioowBBtic9||5cpwo931|4555099filopttuqsrvxzDHILNPPPOOOONONOOKIIIKMNNOPPPONMKKMNOOOOPOPPQPPPOMKEBAtpoolif97565533|<<<<<|353|5citwwtpl93>>>,/|59ccccc9c99931>-%%*>~<|/,*%#@+.", +"+..++++++++@###&%*=;!!([280gghilllplmifdcd997868554|1|||||3599c953|39ioptAApfc5|39ftwo93||49filliiiottuommrtvxCFILMOPOOONOONOOONKKKNNNONOOOONMIEEEEEHHHIKMMOOPPPPONMIEwpppoic85555753|1<<<|5333|49iptwwtlc5|<~,,,>>>)~|359cc9999053|<_())!~~~),>>-*%%*,/||~>*$@+", +"@+..+@##@+@####&%*;;!!(:2abkgjjjopqlmkfcd90870600541||||||35999953339ioopywoc95||5fpwoc53|4cioppoioptpmhmqrvxBEFKKNOOOONNOONONNMKMOPPOOOOONMKEAywwwwAAAABBEEHIKNONNOONIEywtoic9975355573|||33|33435cotwwtof9|/,>>>>->)~<359dcc999572_(/),',,!)),,>>-%$%-~<|<)-%#", +"##@+@@#########&&*;;!!([28bknjjnrrrmlifcb90990850541||3|3|35999953|39foopwwi953||5fpwofc535copppoopwpmjmmrswzEHILKNOOOOOOOOOONMMNOPQPPPPONIHEAwwpppttAAAAAAABABEIIIKNNNMKEAtpiiif955559053|||||333339lpttoif5<)>>>>>-')/||7ccfcc99721<(~]!'>,')),,,>-%$$%>/||/>%", +"-%$##@@@##$$$#$&&*;'!{[[26bknmjmrrrmllggc9009d09055533333|35999953335flopwti953<|5ftypic9|3clppootwpnkjmrpxzBHHLKNOOOOOOOOOOOMMNOPQPPPQPNKHBAAAwpooptyEHEEEEBBBBEHEEEHIKMMKEAtoolf995590953|||1437|||9ilpoli93/,>>>>;;,):<359iifcc964|,',)),,>-*%$%-~|3|)", +"~,*%$##@@#$%%$&%&;;'!{[[2abknlrmqrqmllkgc9089dddd055553333359ccc53335floptti553<<3ftytif9330lpplpwtlhghmrwyzFEILMNOOOOOOPOOOOMMOPQPPPQPOMIEAAABAwptttyEIKKKIIHHHIKKEBAAEHIKKIEytplf953335555||11273||35ciooif5|/)'>>';'']_|30fiigc95241<~!)',>;'',),,>--%$$*,/||", +"|<~>*%%$$#$&%%=*=;;'!{[}20bkorqrqrrrlmifgc988cgfcd59555553559fff95559floptwl553/<3ftAwoif530lppotwpfggmmszzBFEIKNOOOOOOPPOOOONOPQQPPQQPOKHEABBEBAywwywAEKMMNMMKMNOONKEAAAyABHIEBwpic953||35553345993||35ciiif95|/)>;',,!]/|26bcfiff9631|;>,,,,,,>>=%$%-)/", +"/||<~>-*%&&$%%*->;''!{[}60bkosrquusromliifc9cdggigc999955599ciiic9559foptwyo993/<3ftAytpi95cmoopwpihgemmtAzDEIIMNOPOOPPPPPPOOOOQQPPQQPNMIEEBBAEEEAywyyAEKNOPPPOOOPQQPNIBytpppwBEBytlf953|1|35555dfg9933359fifc95|/),,))]!(}269ccecfc9534|_(~!,>>>;>'>,,,,,>-**-,", +">)<||/)>-=&%%=*;;''!^_[}a0bhutsuussuooolifd9dddfkigc99999599fiilic999fptwABpcc5||5iwAAAwofciooowtlhhgemqwzzBCHIMNPPPPPPPQPPOOOPQQPPQPNKHEABBAACEEAyyAAEKOPPPPPPOOOPQQQPMEypliiowABAtoic931||359ccfiic953339cfc953|/!))~]{([}0accbcc999053|<<~!',>>>--;''!),,>-**", +";>)/|||(!'>-*=-;>'){]<}a6dkovtuuuusuroolifcccccdgiicc9995999filiic999fptwBEtic5||5iyBBBBwliopptwplehgjmqwyzDCHILOPPPPPPPQPPOOPQQPOOPOKHBEAzzwyAAyyABEHKNOOPPOONMMMNOQQQPNKBtlffiotyAwplf931||359dfiif9993||5ccc93||>;;;-',,),,;;", +"'',,~<1|>>,'!]_126adknvtxuuusqqqoiifgc900ddiifc9955559cfiif9959clptAEtic5||5iwByAByoopptwwolfegjqwwyzBEJIMOPPPPPPPQPPOPPQQPOONKHBBzwxptwxwwAEHKMNMMMMKIIHHIIIMNPPPPONKApiccfltyywoic73|359cgiliic953|35ccc5|||||:<_}}}6bbebc8a5269977||-=*;->,)))'", +"~~),,)/<|||(!)),'!!^_228bbknruuuuuuqpqpokgga90009iifc95555559cfff95359iptyBti95|<3ftytpppopppwwpolhhknuywzzDEJKMOPPPPPQPPPPOPQQPONMIHBBywuurpttutyEKNOMIIKIHEBBEEEEHMOPPPPOONIyoiccfltwwtlf055559dillifcc93|55ccc53333|1|21668bheca97424375541<<({),>>-==%*->,)!", +"~~~~))~/<|3|;=*=%&&=;", +"->)~{(<|55||<|34||}|4268dbhnvuuttuqqqnlnkhdda0999ccc9995353359ccc93335citBHyi93/~<9iooooofcilifggeeknrtwwyyEEINOPOOPPPPPPPOPPQPOMKHEHEAxprnnmpmkiopAKNMMNMHAABHHHHEBABEKOPONOOOOOONHwoifiotwtoicc990ciid3|355335cffc909c99dchgggghb8877}2__<|35554|<((),--==&&&%", +"*=>,)~/<|7|<<|14376786bbhhknquvtvvqqqqmmmkgd09b9cccc8995353359ccc953359itEHAi95/~<5floooicflifddfchkruqtwxzDEINOOOOOPPPOOPOPQQOOMIEHHHApprnkmqmhkjltEKKKKIByyAEHIHEAyyyBHKKIIMNOOOONMEtlffipttpifc9599fc9|<355559cfcfc9cccffkllkkeeb985321_<__|7555||_~)'>;==&&%", +"*=>;','{/<<(_<|436509cffgjmnrvvtvwwtuqmmmkfdccbccccc9599553359ccc953359itEHAoc5<~/3fiopliiloicabbbhknqqptxzDILNNOOOOPPOOPOPPQPOONIIKKHtppnkkmqmkkjiotBHKKHBAyyAEHIEBAwwwAEEEBEHKMNNNONHwoicflppoifc955cfc3<<|3595cfiiiiffcfimppnmmffb953}}1_<(__|333|_,,,,)~(/__|36709cfgiknnstssuwvvvttqmmmiifcbbcccc9999995599cffc9555citEHEpf5>''',,'!{((<|589cfcfiloqttxtutvvwvwwuppoliifbcbccc9999cd999cfiiic999fltEKIwi9|<<5fipwABAtlcb88bcimlmprsuDDJIMMONNOOONONOOPQOOPNMMOMEvqqmkkkmmmmhefhiopyAAyyyAAEHIIEAwtwyAytpptwABEINNMIAof09cilliffc9cfc92||359ccilllliiiiloopppqiif9953}}<__/({(/(<_1<;>''{<<11<", +"1|44322}[[[[:_12|226bekopuwyyyyABBAyvwywtttrliffccccc8990999999fiifc99cioBMMEp9;;->;'{_<|", +"|35599652}[1142a6268abhiottwzyyyAABAyyAywwwpolifeccfcc990509999cffc9559ciyKMIwc|>,~<", +"~|49cccdd0755766aa8abhhjmpuxxxxwyAAAAABBAAywpoiifffffcc90999999ccfc93335ftHMIwc3|<|9959fgb968bbcioomkoruyDGGIKMNNNNNMMKKIIKNOKCEMOONHtoioonilnoptuuptttpollpttpoffccfiolfcccfiotwtpooic99cffmtyAwtpoppwAytpooifcccc9cfjioptwtuuuqqqnnmmjiliifc0|[:!'';;------->,", +"'!_49ciifdefc898abbbbgehmptxwxxxxyAAAABEEBBAwpolieffiffcc909999cffc95335coBKIyf|>;;>>,,)~~/<<<<;>;;->->>,,)~/<|||||<<<11375cfiiowABHIKKMKIHHKKIHHECGEHGEHIIKIKIIIFIKKMMKKMLKKMOOOOOOMKKIIJKMMMKKMKNNNNNNO", +"ONNNMIJEDzxvvnnnhggbbbaa7744411111112}411423599cc52200adiptwywzAzzzAEEBAABCBECCCGMMMMJCzCEEHEBFGIIMNNOOOONMKIEAzwwwttstttxwwwwttmhgghbiec8833|_[^{)!',>>;>>>>>>>,!!~/<|||33111|3779cioopwAEIKMMIHHIIIHHHEGEGGGGHHIKKKIIIFIIIKKKIKLLKKMNNNNNNMKKIJIKLMLLLLLLLMMNO", +"LMNNLIEEDxxvvnnkhgbbb0a7774441}[[[}111}11134459cc5220dadjpwwzwywzzAAzEBBAAEEECCCHMNNMIGBBEEEEDFGIJMMNNOOONMKFFzxzvwvssssuwwwwtummegbcfb906|1_(^^^!!',;>;;>->->>>,'!~~/_||3373||376acglpttzEIKMKIIHHHGEEHHHGGCCHHIIKKMKIFFHFIFKKKIIKKKKMNNNNNMMKKIJJKMMLKLLLLLLLL", +"LLLLLJEEDvuvrnkggaaba0aa222}}}}[[:}}[1_:1112239995345badiowwyzwwwzAAzBBEEEEHGGCGIMNNMKHCCGBEDDFEIJMMNNOOONMIFDzxzxwxsssstxwwussmedgebe8622_(((]]{'''>;>;-*-=---->>,))~/__1137337aa9dilptwzAHKKKKIHEEGEGHIHEECCHHIKIKMMKIHHHFFFKIHIIIIIKMMKKMKKIHHEEHIIIIHHHHLLLL", +"ILLLLHDDzvvvrnghbab00a6a6}}[[[[[[::[[_1_:11211|441247adhhmtwyzwwwvzzAzBBEEEHHGEIIMNNMKIFCCEEEDEEIIKMMMNOOOMLHFDzzwwxssstwwwtsummegecba62}__({^^^'''>;--=**======->',)){(__<|4508600chkptyACEKKKKIECCEECHIIHEEEHHKKIKLMMKFHFFFFFHHHFFIIIKMKKLKKIFFFDFFHFHHFEFHHHI", +"FFHHHHDDwvvvrkghba0066622}}[[[::[::[:[[__[11|1|111135a0henpwyxwwxwwzzzBBEEHJHHIFKMNONMIHFHEEDDDEEIIMMMNNOOMKHFDzxzvvvsstwwwtmmmeggccaa2}_({{!!^^'';-=*=***&=====->>,,!){_<_|4609ddhbflowyAzEHIKKIECCCBzBHIHEEGHHIKKKKMMKFFFFFFHHFFFHHHHIKKIKKKHEEDBBBFFFFDDDFFFF", +"FDFFEFDDxvvrnkgbb00662222}}[[]]^]^^][[::__[1111111112a0hhjrwywxuwwwwzzBBEEGJIKFFKMOONNKHEHFEFBFEEIIMKKNNOOMKHEDDxzxvvsstwwwsmmmeghfb62}[(^{!!!^!';;-=*&%%&&&=====->',!){(<1}2269cfhehjruABAEBHIKIECzAzzAEHHHHIIIIKKIKMMKFFHEEEBEFEEEEEEEIIIIIIIFBCAAzzAACCCzDDDF", +"CCDDDDDzxvvrnkgbb00a22222:[[[]^]^^]^^^:^[__:|111111124abhjqwyyxuuxwwyyzBEEJIKKKFKNOOONKIHHHFEFFEHJKKKIKMMMKKJHFDzzzvvwtwwwttmmegkbb62}[(({{!!!!'';;-**&%%%&&&====->','){(_}}2770bhfinjnqyCBBEEHIIHCAzyAzBEEHIKKIIKKIKIKKIIHECCCCCBBFEEEEHIIEHHEBzzzxxzzzzzzzzzzz", +"zzxxxzzxxvvrhkgb006a2222[[:[:]]]^]]]^^^]^:_[:1111114277bhjnuwwxuuuwwwzzBBEJIKMKKMNOOONKIHEFHEFFEHKKKKIKMMMMKIEDDzzzvvvtwwwummmjkicb2}[(({{!!!!!'';-=*&&%%&&&&====->','){(_}}7559bchlmrqszCECAAEHIIEAAzAAzAEHIKKKKKKHJIKKIHCCCCCCCzAzBEEEBEECCECCzzzzxxwzyyvzzzzz", +"vvvxxvxxxvrrhkbb00a2222}}:::]]^^^!^]]^{]]^:_[111[[124770hhnptwvuuuutwzzBBEGIKMMMMNOPONMIHFFHFEEEHKKKKKLMMMMKIJEFDzzzvwywwusmmjgkeb6}[[({{!!!!!'';;==*&%%&%&%%%===--;,'){(_}270aabhjnpqtxzEECAzzEHHEEAAAzzzAGIKKKKKIJJHIIHGCCGGCCCzzzzCCCCCGCCCCCAzyxwvwwyvwvvvvv", +"vvxvvvvvvvrrhhbba66222}}[[[:]]{!!!!!^]^{^]]__:_[_:}}47a0hhnpuwwtuuuwwzyzBEEJKMNMMOOOOOMKHFHFEFDHHKKKHHHKKKIHHEFEFBzzvxzwwtsmejkjb82}[(({!!!!!''';;==*&%%&$%$%%===*-;,'){(_}27aaabjhnqqtxAEEBBxzCEEHEBAzAyAzEIKKIIKIJGEHHEGCGEEEBAzzzzCCCCCCGCACBCzyzwwwvsttsssvv", +"srrrrrvvvvrrhkb0a6222}[}[[[:{{{!!!''!!^^^^]]_[[[[:}}26aahhhnttwtpuuuttzzBEEJLMLMNOOPOOOKIIHEEFEHHKHIHHHIKIFEFEFDFFzzzvAAttmmhkjcb2}[[({!!!!!''';;;==%&%%$&&$$%&==*-;,'!{(<}478bbhjjmmqxxABBBBCzzBEEEEEAzyyzEHIIIIKIIHEFECCCEEEEEAAzzxzBGCzCBBzCBCAAutusstuusssss", +"srrrrrrrrrrkhbb0a6222[::[:(^]{!!!''''!!^^{^^:_}[:}}}466ahhjiputspuuuttxzBAEGKMMMOOOPPOONIIIFEFEHHHFHHFFFFIFDBDDCAzzzvvAwtmmejkhc82:[({!!!!!'''';;;=%%&%$$$$$$%&==*-;,'!{(_}45abhhjmmruxzAEBBBCCzBEHIIHBzyAAEEHIIIKIIHEECCCCBEEEEBBzxwwzBBABBBCAAyywtttsspmmmmmmm", +"mmmmmmmkkkkkhbb08622[[[[:((^{{!!''',''!!^^^^[_1__}}4a666hheipputrrruutxzBAEGIMMNOOPPPPONMIIHHHEHIHFFHEEHIIHEBAACCzvvvtwtmmjjkic92}[[({!!!!''>'';;==%&&$$$$&$&%%&=*-;,'){(_}47abhjmmruuyzAEEBCCAAAEHIIIEBAAACEEHIKKIIHFEAzzzCBBEEEBBzwwyBEBCBBByyyywwtqmmmmmmmmmm", +"mmmmmmmkkkhkkbb08222}[[:::(^{!!!''','''!^^^^^:111}}47666bghhlptpppquuttxxAEGIMMNOOPPPPONMLIHHGHHHHFHEEFHIIEAzzCCBzvvtwwqmjjgkjb82[[({!!!!'''''';==&%&&$$$$&$$$%&=*-;,'){(_}47abhjmruuwxzABEBCAAADBEHIIHEBAABCGEEIKKKHFEzzzzzAyAAABBBywzAEBBBAAyyyywqqqmmmmmmmmmm", +"eeeeeeeeebbbbba08222[[[[__^]^^!!''',,','!^]]^]11}}}47a68bhghjppqpnppustxxAEGHKMLNOPPPPPNMKLLHHHIHIHHFEEHHECzzzCBAzvsuwqmmhggeca2}[[({!!!!;''''';=*&%&&$$#$&$$$&%&*-;>',{(_}47abhjmuuwwzzCABBAAAAADEHIHHEEBzBECEEHIIKHEECzzzywyyAAyBBzzyAEEAAAAyyyuuqqqqmmejjjeee", +"eeeeeeeeebbbbb006222[[[[__({^^!!';;;'>,''!^]^^:1}}}78aa68bhgjnpppopqqqtxxAEGGKMLMOOPPPPOMKLLLLLLIIHFEDEEECCzzzzAAtstqqqmeeghcba2[[({!!!!';>'';;;==&%&&$$$$$&&&%%&*-;>',{{([4aahhmnuuxzzACzBBAAAAAABHHEEEEBAACECGGJIIHEGzAAzwwwyAAwyywytwAAAAAAAuuuuuqqjjjjjjjgdd", +"dddddddddddaaa00822}}[[[_({^^^^',';;;''''!^^^]_}}}3666a6a88hhoppqoopqqtxxAAGGKMNNOOPPPPOOMKLLKLKIIHFEDAACCCyAzzywusmqqmjhggfba2}[[({!!!';;;;;;;;=*&%&&$$$#$$&%&&&*-;>'!{{_[4aahemnuxzzzAzAAAAAADAABEEEEEEEBACCEGGGHHHHBCAzAuwwyyAyywwuutwAAAAAxuuuuunnljjggggddd", +"8888888888888888822}}[[(_((^]]!,'';;;;',,!!^^([}}2a66666aa8ahlpppnnpqqppxAACHIMMNOOPPPPOONMKLLKKIIHFFCAzCCCAzAzywumqqjjjggebb82[[((!!!!';;;;;;;;=*&%&&$$##$$$%&&%*;;>'!{]_:78ahjmnuxzCzzzCAzyzAAABBDEEEEEEBBBBGGGGGGEEBCAzwuxwyAAAAywwtttyAAAwxwuuuoonnkgggdbbb8", +"8888888866666666622}[[[[[(^^^{!''>;;;;;,,'!^^^[[}26a6666aa8abhopqnnppqssxxAEGIMMNOPPPPPPOONMLLKKIIHEFCzzBBCAAyAysmmqnjjghecb82}[[({!!!';;;;;;;;;=*&%$&$#$#$$$&&%%*;>>,!{([[788hjmnuxzCCzzBAAyyAABEBDBEFBEEEBCCGGGGGCABzzAAwxwwyAAAAyywuutwyAxwxxuuonllkkggbbbbb8", +"6666666666666666662}[[:[({]^^!!',>;;;>''!!!{^^[:}46aa226aaaabhoppoorrqssxxACGHKMNOOPPQPPOONMMMKKIIFEFBzzCBBAyyAuqmmjnjggbebc82[[[({!!!';>;;;;;;;=&&%$&$####$$&$%**=>''!{([1468hjmvqwzzzzzCzAyyyABEBAABEEEEEEEHGGGGGBADxzAAyywywAAAAAyywtttwuwxwxuroolkkkebba6666", +"66666a666666622}}}}}[[[[((]^^!{!'',''''']{{^[[[}25a66a6668abbeottppprqupxwACCGKMNNOPPQPPOONNMMKKKIFEEAzzABCyyywtqmjnngdbebcb22[[((!!!!;;>;;;;;;;=%&%%&#$####$%%%*=;-',!{([1488ejnvwwAzzzzCCAyyyyAEEAABEEEEEJGJHJGGGADDxxyAAyywyyBBBAAywwttqutxxwupnokkkeeb888666", +"66666a22222222222}}2}}}__:^^{]]!!''',,''!]^^^^[}44a6666666a0cemtwtpppuuuxwAGCGKLNNOPPQQPPOOOMMMKLIFFFAzzABByyytuqjjnggabbhca2}[[({!!!!;;>;;;;;;;=%&%%$&$$#$$$%%*=;-;,'!{_[168bbknvwAAAzzzABAyyyAADBBAAEHHEHJGGJIIHEAAxxxxzyyywyAABBBAyywttquuxxxppomkkhfa8888666", +"}}}}22}2}}}}}}}}}}}}}}}__(]^{~{]'''''','']^^^^[[}2222222266abckpttqpruuuxxABEHKMNNOPPQQPPOOONLNLLIIFFBAzBEAywquuqjjkggb8ceb22[[[({!!!';;;;;;;;;==%&%%$$$$%$$%%%%==-;,'!{[[266bjhnqwAAAzzzAAAyyyADAADAABHIHHHGGIIKIEBxxuusptwywAAAAEEBAyywqquuxwxpppmkfheb888822}", +"}}}2}}}}}}}}}}}}}}}}}}}_:]]]{{!!!'''',',!{]^^[[1122222622260abkotprrrqqtxxAAGJKMMNOPPQQPPOOONNLLLIKHECAABEAwtquujjkkgbb8cf62}[[(({!!!';;;;;;;;;==%&&%%&&$%%%%%&==-;'''{{[_468bjhnvwAAAzzzyAAAyyAAyyABBBHIIJIHJIIKKHByxurspstuuyAAAEEEBAAuuquuuxpprmmmjfbbaa8222}", +"[[}}}[[}}}}}}[___[[[_}}::]^]({{{!'',,!!]]]:[_122aaa66aaaaaabfhlpttpppquuxxAzBGIMMNOPPQQQPPPOONLMLMKHEEzCBEAwqqunjjkkbbabfb62[[[(({!!!';;;;;;;;;==%&&%%&&&&%&&&&&**;>'!{{[1468benqvwAAAAwwzzCAyAAxuuAABCEJIIIIIHHIIIBzxxsspquqquAAAAEEEBAxuuuuuxpppmmijbccb8222}[", +"[[[[[}}}}__[_:_:([(__[[___[:_//(({!!]{{((<1|1356988999a9cccfjiotyywttxuuzzAAEGHKMNOOPQQQQPPPPONNLMKFEHAAEEAwqqunikkkbb8bf62}[[[(({!!!';;;;;;;;;==%&&%%%&&&%&&&***;-',!{[[166bbknqsyAAAwwyAAAzAAwwuutACEEJKKIIJJHIIKEEAxwwuutquuyAAyABEEAyxuuuuxpspmmjjbbbb62}}}[", +"[[[[[}}____(([((((((:_1:|1:}1____({{{{(((_1|}34688a8abda9ecchmptAAyyyAAACAEEHJIMMLNOPQQQQQPPOOOOMMMKIHBBEEAwqqunjjkeb88bc62}[[[(({!!!';;;;;;;;;==%%&&%*%%%&%%%**=;;''!{^_166bhknqsyyAwwwxAACAAzxutuuxBEEIKKIIKIKIKHHEAAywtttuuxyAAwwABEAyxxuuupppqomiicbb6a2}[[[", +"[[[[[____((((^^^^:[:[[[1|}[[_<<__({{{{{((_<11|366a68899a8bbdflouwAAyyAAACCCEIIKNNOOPQQQQQQPPOOONONMKIHCCEEAxqqunjkkbb8acc62[[[[(({!!!';;;;;;;;;===%%&=%%%%%%%%==;;;''!{^_166aekvqwyyAwwwxzCBCBzxxuxxxAEHHKKKKMMMKIEEEAAwxtuuquuyAzxwyAyAyyxpprpppqqmjfbcba62}[[[", +"[[[(___]]((^^^^[[[:[[[:[[1:[_<___{{!!{{(((_}_|266a6668668aa9filotyAyzzAACCCHIIKNOOOPQQQQQQPPOOONOMMKIIEEEHAyuuunjjkb88bb822[[[[(({!!!!;;;;;;;;;===&%*&&&&%%&&=*-=;;''!^^126bagjrtvyywwwxxzCEEAzxuuuxxCCHHKMMMMNNKIEBDyyxxuupqquwyAwtwuwyztprppprrqqlifbb6622}}[[", +"((((__(](^^^^^^[(((((:[[:[:[}__<,'^^_122bbgjmstvvywwwxxzAEzxxxuxxzzzEIKMNOOMMKIECvvqqqronppoqtxywuqlnmptpoiiijjllliecba222}}((", +"((((({^^^^^!{{{{{{{{]{{]{(([:_((:<]]!!!!]^{]:[^[:[:_2}2}266a8ahimpwxustwzxAAEEGIMMMOPQQQQQQQPPPPPPPOOMMMKIEyyxxppmmjbbhba2}[[[[[(({!!!!';;;;;;;;;===;=-=====;;;;'''^^(_2268hgjmvvvvywwwwyzABzxxxxxzzzBIIIMMNNMMKIGzvtqqqmnnnonquwyxuqnkklppoifiifiiifecb622}}_((", +"(({(({^^^^{{{!!]!]]{^{{{{{(](_((__]]!!!!^^]^(^^_[[1[[}}2226668gelqwttupwxxAACBGGKMMNOPQQQQQQQPPPPPPPONNNNKHAAxwpomkiififa22}[[[[(({{!!!!;;;;;;;;;==*=;====;;;;;;,'^^^(_2288bgmmsvvvvwwxwyzzAxxxxxzzzCEHIIKKMMMKIEGCvsqqmnnnnnhmquwwuonkjiiooliiijiiiief86222}_((", +"({{({^^^^{!{!!!!!!!!{{{{]{](]((](<(!!]!]^^^]]^^[[[[[[122226668bgkqtwsrtuuuyyBCGGILKMOPQQQQQQPPOOPPPPOOOOONKIEAyxokkhjhifb622}[[[[(({!!!!';;;;;;;;;;;;;;;;;;;;;','!^^(_}228bgjmvvvvvvywwwyzAAAxxxxzzCEEHHHIIKMMKKEEAwuqqmnjnnnjhmqtuunkkjfiloiffffccbife8622}}_((", +"{{{({^^^^!!!!!!!!!!!{!!!{{{]]//(/_(]]!]!{^^]^[[[[[_[[222222888hghmwwsruuuuyxzACCHFIMNPPQQQQQPPOOOPPPOOOOONNMIIBAtpkkeffbb8622}}[[[(({!!!!';;;;;;;;;;;;;;;;;;;''!!!^(_}}2aabgjmvvvvvvywwwyzzAzxxxzzCEGHHHEIIIKMKIEEAvuqmmmjjjnhjjmuuonkheheiiifcfccc9bb98622}__((", +"{{{({^^^{!!!!!!!!!!!{{!]!{^]{]:<:::]{]^]^^]]]][^[[[}2}2222668adghottsuuuuzyxzzACHIFKNOPQQQQQPPOOPPPPPOOOOOMMKIECwtqmiifbaa866a22}[(({{!!!';;;;;;;;;;;;;;;;;;>!!!!!{__}}28bdjmmvvvvvvyzwwwyAAzAxzzzCEEHHEHIIIJKKHEBAvuqmnmjjjjjjhmqunkkhbb8bfffbccc999988a62}__({", +"{{{({^^^{!!!!!!'!!!'!!{]]!{^]]:::::(]]]]^^]^]^[^[}}}}}2}2666a0dhjotxxuuuuwxxAzzCEIFILNPQQPQPPPPOOPPPPOOOOOMKKIHBBywtponc888826a22}[(({!!!!';;;;;;;;;;;;;;;'!!!!!{{([[}2a8bdhmsvzzvvvvzzwwzAAzAzzABEEHHEEHHIIHHIHGEDvuqmnnjjjjjhhmquokfbbb888ffc9cc998866662}__({", +"{{{(^^^^{!!!!!''!'''!!!!]]{{{(:_:::({]^]^^^]:[[[[}}}}}}266aaaaeejnuwxuuuwwwwzzACGIIKMNOPPPPPPPOOOOPPOOOOONMMKHHCAwwxwwplhba8a226222}_({!!!!';;;;;;;;;;;;;;'!!!!{{^([[26aabhmmsvzzzvvvzzzwzAAAAABEEHHEEEEHHHIHEIHHEDwuqmnnjjjjjhhmqomkjcb8a68bc99995555866222__({", +"{{{({^^^{]!!!!'!]'!'!!!!{]]{{(:_:_<_]]]^{^^^[[[[[}}}}}226aaabbehmquywuuwwwwwzzzCGFHFKNOPPPPOPPPOOOOOOOOOOOOMKIEEAytwwxtpoheb888222222_{!!!!';;;;;;;;;;;;;;',!^^(([[[}266ademvvxzzzzvvzzzABzAACBEHHHEEEEHGHHIHEHEEBDwuqmnhjjjjjhkkmomjeh888a85095555335544222__({", +"{{{({^^^{!!!!!'!'')!!]{!{{]{{(_<<<1_(]]^{^^^::_[[[}}2227aaa8bbhkmquxxvwwvwwzAzACGHHFKNOPPPPOOOPOPOOOOOPOOOOMKIEEzxxtwwtppplifba8222}2<(]^!!';;;;;;;;;;;;';'!,^(([[[[}668bhhhvuxzzzzzvvzzzCCzzBEHHHEEEEHHHHGHECBCEBAyuqnnnjjjjjhkkmomifea6aa475534224443||||2__({", +"{{{({^^^{!!]!!!!'!!!]{{{{{{]](__|_1__]^]^^]::::[[[}2227778888hhkmquyAxwwwwxzzzACGHFFKNOOOOPOOOOPPOOOOOOOOOONIHHBBwxxwwuqqppolihha22}__(^^^^';;;;-;;;;;;;'''!,{([[[[}668abekrvuzDzzzzzzzzAABBABEHHEEEEHHHHHHHEEzBEBDyturnnjjjjhkkmnnmkjjc8a744432}22}}}}|1<_<<_((", +"({{({^^^{!{]^!]!')!]!!]~{({((:[<}|11_]]]^^^:::_[[22277777888bgkkmpuyyyxxwDAzyACCGHHFKMOOOOOOOOOOPPOOOOOPOOOMIHEEAAxxttpqqqnopllih8a2__(^^]^!'';>;;;;;;>;'''!!{([[}}6668abkkqvxDDDzzzzzzzACBCCEHHIEEHHHHHJEHBEEzCGBDAxurmmjjjjkkkmmnmkhheba541}22}}22}}}::^(_((((", +"{{{({^^^{{]!^!]!!]]!]!{]{/(((_1|}}111:::_([_::}222277777a888bghkqptyAywzyDAAyyCCGHFFFKMOOOONONOOOPOOOOOPOPONKGCByyuxyyppmmmmooplmfc61_{!^]^!!!!''>;;;;;;;;'!!{([[[2228abkhrvvxAADDzzzzzzzACABEEEHHHHHHHIHGHBCAAzAAAAxuqrnjjjmkkknmlmlfcfec74[}2221111_}:::]^]{{{", +"!!{{(^^^^{{!!!!]!!]{{!{{(/(_<_143|||1<::__[[}22222777770a888bghmmrtzCBAzAAAAAzzCGHFFFKMNOOONNNNOOOOOOOPPPPPNKHCzzwwuxxupormmmmoolifc9|_^]!!^{~{{'';;;--;;;'!!{(:[222600bkknvuDBBBDDDzzzzzAzABEEEEGEEHHHIHGEBEACCAAAAxxsqmjmnkkkmmmlmlifiic04}}}1_<<<<;-;;'''!{[[2260bagnnvuDDBECDBCzzyADzAAEEBAAAEEHHHHHEEECBBAADAyxxuummnmkkkkkmjmmifiic92}}_<|',''!{[[2260bhgmvutyCGEBDBzzzyDxyABBBAzAAAEEHHIHHHCBCAAADAAzzxupmnmmhkkkmjklifffd922}_<<<(((/{{{)),''>;", +";;'''{^^^:{({{{{{{{{({]((__:__|114414}_____111226666aaaa9behjilqqqtyEECCCzCAzzzCEHEFFIKNNNNMMKLMOOOOOOPQQQQONKHFAzzyywprssmqqlife9aa7445cd95}<]^]!'''''';',''!{[:22a0ahnnvvvDBGBBDBzzwyzyDBEzxxAzAABHIIHHIHGCEABAAAAAAAzturmnhhkkkjkiidccd5221_<<__((({{{!'',;;;", +";;;'''{^:[{]{{{{{{{{{{{^(__::<|11442|}[[[_[}}222aaaa0898abbbejlquuwyBEEEEEEEBBBEEHEEFIKNNNNMIKLKNOOOOOPQQQPONMIFDAzzzvvvrrsmhgfbe8a85375955743}:^]!''''''',''!]^[22608gnjvuvDAGBBDzzzwvwyABAzxxxzAABHIHHHHHEEBAAAAABAAAAwuqmnmhkkhkkiicccd963|<<<<_(~~~)),''';;;", +"=;;;'']{:[(({]^]{{~{{{(((_::<1|4443332}[[}}1222000aa9c9aaaabejoquuuyBEECHFIHHEGEEHEEEHKMNNNMKLKLMOOOOOPQQQPPNMIHFDAzzzvvvvrmegbabaa777753}}}3437}_]!'''''!!!'!{^[2260agljqqwDADBBDzzzwywzAzzxxxxxABBEEEEBHHHBAAzyyAAAAAzwtqrqnmhhhkkiifcccc654|____~{~~))''>;;;=", +"==;;'''{([[((]((]]{/(((((__<:11|4353552}}}42770ddabbdccccdhgiopptxwABEGEIHIFIFFFEHECEHIMNNNMKIKLMOOOOOPQQQPPOMKHHEEEAzxxvvrmedaa222|7572[<[:|1|742|[!)'''!]!!{]][22678gjjqqwDDDDDDxzwxvxzAzxuuuxxzBEEEEBEHHBAAwxyyyAAAAwttqrqqljkhkkkiiecdc954|___//{~)),>>>;-==", +"%==;;''!](:((](((]]/(((((_<_<1|435575955775700ddihhggfffikimopptwwxABHEEHIKKKIFFEIEECEIMNNNMFILMMNPOOOPQQQQPONKLHHHEFzzxxxrmed862}}1774[[:[::[|4443|:{!''!!]^{([[}}6a8gjjqquDAADDDxzwwuwzwxuuuuxxxBEEEEEHHBAyyxxzyyyzAzwwtpqpooljjjkkiifcdc993|<__//)))),>>--*%%", +"%%*;;;,!{{(_((:(((:(/<:__<_1|4377590990775000ddijifikfiiimmmmpqppwwABHHHHIKKKIIIHIHECEIKNNNMIIIMMOOOOOPQQQQPOOMLKHIFHDDzxvrmed862}}131_^]:^::_14|1233}({'!!!](__:}2778gjjrquDAADDDxxwwwwzxusuuuxxzzBBBEHHByyxxxxxywwyyAwwupuqnoomkkkmiieffc995|<__//~))),>;--*%%", +"&&**-;'!]]([(__:_::/_<<<<|11|4355599900557909ciiiigggkfiikkkkmnnrtxxBHHHIKKLLKIIKKIEEEIKMNNKIFILMOOOOPPQQQPPPOOMKLKIHFDzxvrmed862}}1|_{^^]^_<_1111:}334<^]!!!{(:}22778dikmquwADDADxxwwwyyuuqvvuxzzzBzEEEAAwuuuuxxwwuxxxwwtrqooopmmmmmllffffc97||;-=%&&", +"$&&=--'']{]_______<<<<||||3||47579999990099ccgiiiijgggcfghhgggijjquuyBEEEIKMKKKKKKIHEHIKNNNMIHIIMOOOOOPQQPPPPOONMLLMLHDzxvrmed862}2__{{{{{((__111<_[}323|:]!!{{[}62088djjmqtwAADAxxxxzwyuuqvvvuxzzzzBEEAywuuuuuupstpuxxtwuqqlnnmmmmmmoliffc9673|_//~~),,,>-**%$$", +"$$%==-''!{((1<_<1<<|<||||||33347799ccffdccccfgjkkggddggcdbbdhheehmqqwAEECGIKFFLKKKKIHIKMNNNMKFIILOOOOPQQQPPPPOONNNMMLHDzxvrmed86222_({{!!{((_11311_[<:}2|11:({/:[220agdjmmqtvAADDyvxxywyuqqvvuuxxxzBEEAywutuxuspppsqutxuwtrnmlkmomliloonifc9663|1>>-**%$$", +"#$%%==>''{(_1<|<|111||||||33357709cccffcc99cghhhhjghddgdbbhbdgeehmmqwABBCBHIKIFIIKKIHIKMNNONKFFIMNOOPPQQQQQPPOOONLNMLHDzxvrmed8622}[(({{{{{{__2221__](:<11|||1_::220bghjmmquvyADDyuxwzyyvqqqqrruxxzGEAywxuxxtpprrppquuxtwtqqnjkjjillnilolif9a63||>>-*&&##", +"##$%*=>>'!{(__1_111||11||33355900ddccfgc99ddhehhhhhhddddbbbabheeemmmtyCBCCHIFIFIIKIHEHKMNNOOMKFKKOOOPPPQQQQPOOOOOONMLHFzxvrmed8a22}[(({{{{((([}}2|__^](::<||752}}2609gglmnqtvyADDxvxwAyxqqqqsrquxzBEBAyxxuuxtutsssppstxtwtummkhkehijiilolij9aa3|1>>==&&##", +"##$&**;>,!{(_|||||1||1|33335599990dccfffddhhhghhhhhghdddabbbhheeehmmqyABBCEHFKIIIKIEEHKMNNOONKKKMOOOPPQQQPPPOOPPOONMKHFzxvrmed88a}[[(((((({{[[[}}_1<<]^]^[_1459556678gglqqqtvyADyAvxxAwwqqqqvrruxzBEAywxwxxttwwyvvwwtxywyutpmmkheehhiiloilic9673|_<~~),>>;==&&##", +"@@$&&*-;'){{(_|11|||11133555569990cccghfebhhhghkkhjfgdgggbbehhhjjhmqqyABCCEFIIFIIKKIHIKMNNOONMKMNOPOPQQQPPPPOOPPPONNKHFzxvrmedb8a2[[[(((((([:[[}[}<__]^^]^]_|3999990adgjqqquwAADDDwxwzwwmmqqunruzACyyywxwxwyAEEEEBAAAAAAAwwsomkhhbbbejliiiif9673|_;===%$@@", +"@@#&%=*>>'!)(__1<1||43347555599999ddghfifghggklnjmmmiigghhfhghggjjqquyAEBCCHFKKIFKKIHIKNNOOONNMMNPPOPQQQQPQPOOPPPONNLLFDxvrmmhb88}[[[[((([[[::1}}}_|__]/](^<<1599cfdbggkqpqwyAAADDxxyAwtsmqqquoxzzywwxwyAABEHKMKIIHEEBAAAAAwpmmjjbbbfiiiiiifc953||-==%%$#@", +"@@#$%%=;;,,!~(__|_|||33555550999cccdggiiijkjlooommmollkkkffghghkjjnquAAEBCEFIKKKKKKHHIKMNOOONNMNNOPOPQQQQQQPPOPPPPONLLFDxvrmmjga6}[[[[[[[[::}22}}}}_<_<_:/(__137ccfgfigimmqvyACADDzzzAztsmqqqquxAAvtwwABEEHIKMMIEEBAAywwyABytqnjjgbhhhgiiiifd99531;==%%$@@", +"@@##$%%*;;,!{/_<<||1|145559709cccffiillllllopprpppppoommiiikkkkkknmuuAAEECEFIKKKKFKFHHKMNNOONNNNNOOOPQQQQQQPPPPPPPONLLHDxvrrmhgba6}[[[[[::[}22662}}(//<_<__<_}|580fiimomrqqwyAEADDAzAywusmqqqvxzAwtwxyBEHIKKKKEBAwwwxwtwyyAywqmoijijhfhfiijif8853|<<~)),;=%%%#@@", +"@@##$&&**-')){/<_<<|||3755999dcfffiilooooooooppppqppppopllommmpmmpptwABEEGCIFKKKKLKIHIKMNNOONNMNNOOOOPQQQQQQPPPPPOONMLHFzxvrmjgb66}}[[[[[}}2288864}}({{(1||1_}|298fgiopprqqvvACADDDzzvvsssqqquxzzttwyAEIIMKIHBAywtttxwwwyyAywtpmlmihehcfiiiff9973||'!~/_<<|||3355999ccdgfgiillllollnoorrpmoqoommoloompqpqttyyEHIHGHKKKKKLKKFFIKMNMNONNMNNOOOOPQQQQPPPPPOOOOONLHFzxvsmhdd666}}[[}}266ccff996}(({/<||1_|2269dfmotttutvyACEBBBBzxvvstqqqtwzxtwyAEHIKKIEBAyAAyyyyAyAAAAywtpmlnlgfhfeeifgfc8953|,!~/<<<<||3335599ccggfiijllnnlloooopppqqpoomomlmmmopqqttyAEIKKIIMMMMMKKLKIKKMMMMNMMMNOOOOPPQQQQPPPPOOOPPOOKLFBxvsmmed8666}222a6bbfeifif92[((/_|<_}}2269dfmmpwwwwwyABEBDEEzxvvtutqqxwxxwyABHIIHHHEEEEEHEEEEEBBABAAytpoliiiighceffgcc8953|;%%$#@+", +"+@@##$%%*;>,){//<<||||355599ccggfiijllonpppppttwwtxwttpttpppppputtwAAEIKKKKNOOONNMMKKKLNNNNNNMMNOOOOPPPQQQPPPOOOOPPPOMLIDzvssmed86666226bbbccjjefc6|[(((((/(::2669dckkptwwAAAACEGEHEAxxxwstuuxxxxwAEEIIHEHIKIKIIIHIIHIEEBEBAAwppojhfiffcddddc88653|;*%$#@+", +"+@@#@#$%*->,,)//<<<||||35599ccfiiillooppttwwwwyyyyAAyywwywwwtxzzyyABCHIMKKMNOOOOOOOMMMMNNNNNNMMNOOOOPPPQQPPPPOOOOPPPOOMIFBzytmmed86688abcbccehgif86}}[(({{{^:[}659dekoouuwABEBEEEEHEEzxvvwswyDuxzBBEHIHHIKMMMKKIIEHIHIIIHHEBBAwponijijfcccccc98655||<~),>;*%$#@+", +"++@@@#$$*--,,)~//<<||||35599ccfiiloppttwwywwwwyyywyyywwtwwtttwAAAAEEEIKMMMNNOOPPOOOOOOOOONNNNMNNOOOOPPPPPPPPPOOOPPPOOONNIHzztmmeddba88bbcciikggfc82}[:[{{^]^^::27dffkooptwABEHHGHIEEBAxzvvwwzyuxABBHHHHIKMKKKMKIIHHIHIIKIHHEEBAtpnjffefffcd9c996533|,)~///<|||335599cfiilopppttwwwwwwwwywwwwywwuppppptwwyzABEHMNNMOOOPPPPPPPOPPPPPOOONNOPPPPPPPPPPPOPOOOPPPOOOONMIEAzsmmeggbehchfilokkkf962}::::::[][:}2a0ckkmrpuwAAEJIIIKIEBCAzzyyAzyAzCEIHHIIKKKIIKMKIIEEHHIIKIHHEEBBypljfbeffcc9cc95333||,)~//<<||3355599cffillppptwwwwywwwyyyywyywwwutttttwwwyyABEIMMMNOOPPQPQQQPPQQQQPPOOOPPPOPOOOPPPPOOOOOPPPOOOONMMKGAwtqjjkkkhfhgkmmonkg6a6[::[:[[[:::2}60agkoupuwyABHIKMKIHBDDzzzACAyACEHIKHIIIIIHIIIIHHEBBAEEEEEHEEEBytoifbhcfdcccc9533|||;%$#@+", +"+++@@##$%*-->)~/<<<|||355599ccffiiloptwwwwywwwyyAAAyyywwywyyAAAAACEHHKMNNNNOOOOOOOPPPPQQQQQQQQQQQQQPOOOPPPPOOOOOOOPOOOOOOMMKGEAAxuronljeejjjqmhd8666}:[:[::[[22608ggjppuwyAAEEEKMNMIIEBDEBEEBEEHIIKKKIIKKHEEBBBBBAzyywtwwwAEBBBAwpoijedd99cc9953|||<<<~),>;%%#@+", +"+++@@@#$%*->,,~/<<<||||335599ccfiiloppwwwwyAyyyyyyywwwwwwwtwwxyyAEEEKKNOOOOOOPOOOOOOOOPQQQQQQQQRQQQQPOOOPPPOOOOOOOOOOOOOOONKHHHEEywuoljeemmqmmed8aaa}}[[:[:[422a08ggioqqwyAAEEHKMMMKKIEEEEEGGHIIKMKKKKMKIEBAAAAAAAAAywttpuwAABAAwtolifdda8c995531|<<<<~~,>;=%#@+", +"+.+@+@#$%%->,)~//<<<|||3355999cfiilopptwwyyywwwyvwwuutttpstquuuxAAAEHIMOOOOPPPPPPOPPOOOPQQQQQQQQQQQQQPPOPPPOOOOOOOOOONOOONMMMJIIHHAyuqqmmqqqpmhdd8662}:[:[:2226788glinqqwAAEEEIKMMMMKKKHHHFHHFKKKMKIKMKIEBAABzAAABAAAwxupqtwyAAAwtpoljgd890999541<<<;=%$@+", +"+.+@+@#$%*->,))~//<<<||335599ccfiillopptwwwwwwwywwwvxxwwwwwwwwyAAACEGHKNOOOOOPPPPQPPPPPPQPPPOPPQQQQQQQQPPPPPOOOOOOONNNNOONNMNNMKKHHEwuuqqqwtpkked82222[:[:22}267agglrrqtwyAEEHKKMMMMMMKKKIIIHKMNNMKMMKIHGEABBAAyyDyyyyuupttwwyyAywtpoifd09999953|1>=%$@+", +"+.++@##$%*-->))~//<<|||355599ccffiilllpptwwyyyyAAABBAABBEBABBBBEEHGIIKMOOOOOOPOOPPPQQQQQQQPOOOOPQQQQQQQQQQQPOOOOOOOONNNOOOMNNNNNMKEEEBAyyywtpkmeda82222222222607aggkqrqvvAACEIKKMMMMMMMMMMKKKMNNNNMMMKEEEECAywwstsstzwuuutwwwwwyywtpplic98999953|<=&$#+", +"+.++@##$%*-->,)~~//<<<||35599cccgffiloptwwAABBBEEEEEEEEEHHHHGHHKKKMMNOOOPPPOPPPOPPPPPQQQQQQQPOOPQQPPQQQQQQQQPOOOOOOOONNOOOOMMMNNMKIEEEBBABzypmkb0082266689889909ggkjmquvvABBEIKMMMNMMMMNMMMMMMNNNNONKIHIBBzzzxssrrruuuuuputwwwwwywwtolifcb955553|=&$#+", +"+.++@##%%*-->,,~~/<<<|||335599ccfiiloppwyABBBBBEEEEHHHHHHEEHHHIKKMMNOOOPQQPQQQQPPPPPPPQQQQQQQPPQQQPPPPPQQQQQQPPPPPPOOOOOOOONMMMMKKKHHEHIIEAAtmme0088688cccfjiigfkglmnqtvwyBBIIKMMNNNNMNMNNONOONNNOONMIHEEAzxxuuuuuuqusuuttuwtwtwwwwtooiib9955553|<-&&#+", +"++++@##%%*-->,,~~//<<|||333599ccfilopttwwyAABBEEEEEEEEIHEEEEEEHHIIKMNOOPQQQQQQQQQQQQPPQQQQQQQQQQQQPPPPPPQQQQQPQPQPPPOOOOOOOOMNMLKIJIKIIIIIHBwtmefd9ccffccfiilklqmporqqwvyCAEHIMMNNNNNNMNNOOOOOONOONNKKJEBzAxuuuuuvvqqqqtuspttttwwywwpoliec957533|<-&&#+", +"+++@@##%%*-->,,~///<<<||335599cfilloppptwwyyAABBBBEBBEEEEAACCBCCEIKMNNOOPQPQPQQPPPQQQQQQQQQQQPQQQQQPPPPPPPOOPPPQQQQPPPPOOOOOONMKFIIIKMKIIIHECwmmigkilifccffkkllpptupqtvvyCBHHIMMNNNOONONNOOPPPPOPOMMMIHHGAzAxuvuuuvqqqsttqutttwwwyywppliec95733||-*&#+", +"+++@@##%%*->>,))~//<<<||335599cfiloooppptwwwAAAAAAAAAADBBBAAAAEEHIKMMNNOPPPPPPPPPPPQPPQQQQQQPPQQQQQQQQQQQPOOOOOPQQQQPPPPPOOOOOMMKIIILMNNMKEEEAupnomoijfeccgggjomttxxuvyAyCBBHIKMMNNOOOOOOOOPPPPPPONMKIJGECzyxywvuvuqqvsuupuwwwwwwyywtplif9997731<<({~!),,>>-*&$@", +"+++@@##%%*->>,)~~///<<||355599cfiloooppptwwwyAABBBBBBAAABEDBDEEHHIKMNNOOPPPPPPPPOOPPPPPQQQQQPPQQQQQQQQQQQPOONNOOPQQQQQPPPPPPPOOMMLIKKMNNNKHCBAxxttqoifbc9dddeekmpuwwyAAyAACBIIKMMMNOOPOOOOPPPPQQPONMKIJJECBzxwwwwwtttvstqstuwwwwwyywwtoifc9973||--**$@", +"+++@@#$%%*->,,)~~~/<<|||355559cfiioooopptwyAAEEEBEEBEEEBEEEEEHFIKKMMMOOOPPPPOPPOOOOOOOPQQQQQPPPQQQQQQQQQQQPOONNOPPQQQQQQQQPPPPOOLMMMKKMMMKIGCAyBywpokgddd00bbggoostxAAADyABEEIIKMMNNOPPPOPPPPPQQPONMKKIGGGCzzzvvwttttsvsuvttttwywyyywtplicc053|||>-=**$@", +"+++@@#$%%*->,,))~~/<<<|||35559cfiilooopptwyAABEEEEEEEEEEHEHHHIIKMMMNOOOPQQPPOPPOOOOOOOPPQQPPPPPQQQQQQQQQQQQPPOOOPQQQQQQQQQQPPPPOONMMMMMMKKHEEABABywmkgdd00bbgggmlpuwAAAADAAEHIIIKMNOOOPPPPQQPQPQPPONKKIIGGCCCzDytuutssvtvusuutvwwwwywttoicc973||<>--;=*$@", +"++@@##$%*-->,,))~//<<<<||35559ccfiillmopptwwyBBEEEEHIEHHHIIIIKKKMMNNNOOQQQPPPOPPOOOOOOOPPPPPPOPPQQQQQQQQQQQQPPPOPQQQQQQQQQRQQQQPPOOONLMLIIEEEEEAzwtpmgdd0bbbggllqruwAAAAAAAEHHIIIMMNOOOPPPQQQQQPPPOOMKLKIHGCCAAAxvvvvvvtwuusuttvvwwwwttplic973||--**=*%@", +"@#@@##$%*-->,,)~~//<<<<||355559cffiikllopppwwAABBBEHHHIHEGJHJJIIMMNNOOPQQQPPPOOOOOOOOOOPPPPPOOOPQQPPPPQQQQQQPPQQQQQQQQQQQQQQQQQQPPOOOOOMIFECEEHAytpppligecbgggnmrqquwwADDAABHHHIKKMNOOOPPQQQQQPPPPOOONKKKIIGCBAAzvvvvvvtwxxvutwwwwwwwwtpoifc95||<-;**%&%#", +"@##@#$$%*-->,,)~~///<<<||335559cffiiiillooptwyAzAAzEEHHHIIJIIIMMMLNOOPPPQQPPOOOOOOOOOOOPPPPOOOOOPPOPPPQQQQPPPPPQQQQQQQQQQQQQQQQQQQPPPOOLIFBCEEEAywppppoljekggnlrvqttttxDABDEEHGIIKMNNOOPPQQQQQQPPPPOOONKKKIIHGGCCzzzzxwvxxxuuwwwyytwwwtpoifc95|1<--=*%&$#", +"@##@#$$%**->,,)~~///<<<||3355599fffiiillopptwwyAAzABEHHIJIIIKKMMOOOPPPPQQQPPOOOOOOLNNOOPPPPPOOOOPPOOOPPQQPPPPPPPQQQRRRRRRQQQQQRRQQQQPPOMIHECBEAwwwpooppolmmkknnquutuutuwDDEEEHEHIKKNNOPPPQQQQQQPPPOOPOONNMKKKKHGCCCCzzzxxxxxvwvyyywtttwtoifc9531--;=%%$$#", +"@####$$%*-->,,)~~///<<|||3355599ffiffiiloppptwyyAAzBHHHIIKIKMMNOOOPPPPPPQQPOOOOOONMNNNOOPPOOOOOPPPNNOOPPPPPOPPPPQQQRRRRRRRRRRRRRRQQQQPOMKIHCCAwwuuuoooppuqmmqmrruttqqqutwDBEEBGEIIKNNOOPPQQQQQQQPPPPOPOOOOMMFIIHGCzzzAAzzxxxvwyyAAywwtttolfc9531>-*=%&$$#", +"@@#$#$%%*->>,))~~///<<<|||355599ffifgiiloooppwwyAAABEHHIIKKMMNNOOOOPPPPPQQPOOONNONMMMMNOOOOOOOOPPPNNNNOPPPOOOOPPPQQQRRRRRRRRRRSRRRRQQPONMKKCzytuqqtuoooutuqtqqvvutuuuqqquwBEEBGEEIIKNOOPPQQQQQQQQQPPOOPPOOOMKIIHFECzzzAAAzzyyyyAAAywwtttplfc953|>-*%&&$##", +"#@#$#$%%*->>,))~////<<<||335599cfffgfiiloloopwwyAAABEGEIIKMNNOOOOOPPPPPPQQPOOONNNNMMMMNOOOOONNOOPPONNNNOOOONOOOPPPQQQRRRRRRRRRSSRRRQQPPOOMKEAxutmqqutuuquuuwtxuuuuqquqqquwAEEBAECHIKMNOOPPQQQQQQQQQQPPPPPOOMLIFFHEEzAzzzABAAzAAABBAyywttpoic953|--*%%&#@#", +"#@#$$$%%*->>,,)~////<<|||335999cffifiiililopptyyAABEEEHIIKMNNOOOPPPPPPPPPQPOOONOONMMMLNNOONONNNOOONNNNNNNNNNNNNOPPQQQQRRRSSRRRSSSRRQQPPOONNHCyputmqquuutupwywyxxwuuqqqquuuyEEEBAEEIKKNOOPPPQQQQQQQQQQQPPOPNNMMKIHHEEDDDDABBBBABEEEBAywwtpoic9531-**%%&#@@", +"###$%$%**->>,,)~//<<<<||3335599cfffffiililooptyyAABEHHHIKMMNOOOOPPPOOOOPPQPOOONNONNNNMMNOONMMMNOOOMMNMMMNNNMKMMNOPPQQQQRRRSSSSSSSSRQQPPOOONKEAyttmmqquuuupwwAAyxwuuuuqqquuyAEEBBGEHIMNOOOPPPPQQQQQQQQQPOPOOONNMKIIIHEDAAABBEEEEEEEEBAAwwpoic953|-**%%$#@@", +"###&%$%**->>,,)~//<<<|||3335599ccfcffiiiilopppwyyAAEEEHIKMNNOOOOOOOOOOOPPPPOOONNONNNLMMNONNMMKNOOOMMMKKKKMMMMKKMNOOPQQQRRRRSSSSSSSSQQPPOPONKJEAttmmqmqquuwwwAAAzyxuuuqqqquxyDDEEBEHHKNNOOOPPPPPPQQQQQQQPPPPPPONMKKIHHEDAABBEEEEEBEEBBAwwtplf953|-*%%%$##@", +"#$$&%%%**->>,))~~/<<||||||3359cccfcffiiiloopptwAAAAEEEEIIKMNNOOOOOOOOOOOOPPOOONNOMMMMKKMNNMMKKKNOOMMMKIHHKKMKKKKMNNOOPQQRRRRSSSSSSSQQPPOOOMKIHEwutqqqmqqwwwwyAAAAyxxuuqquuwyyABEEEHIKNNNOOOOOPPPQQQQQQQQQPPPPOONMKKIHHBBACBDEIHBBABEBAywtpoic95|<-*%%%$##@", +"@#$&%%%*-->,,)~~//<<||33333559cfffffiillloopttwyAAAEHEEEIIKMNOOOOPOONNOOOOPOOONNMMMLMIKMNNKKKKKMNMMMMKIEEJHIKKIKKNNNOOPQQRRRSSSSSSSRQQPOONMIIHHAwwwqqqqttwwAyzAABAxxxuuuuuwwwyABEEEIKMNNNNOOOOPPQQQQQQQQQQPPPPOONMMIIHEEBCCBEIHBAAAABBywwppif953|-**%$$##@", +"@#$&&*%*->>,))~~//<|||3333559cffiffiiilllopptwxAABBCEHHHHIKKKMMNOOOOOOOOOPPOOONNMMMMKIKKMMKKKIFMNMKKKKIHEECGHHIIKMNNOOOPPQRRSSSSSSSRRQQOOMKKHHEEywwwyywtttwAAzzABAzxxuuuuuxwwyyAEEHIMNMMNNNOONOOPPQPQQQQQQQQQQQPOOMKIHHEGBAEEHEBAAAABAAywtplfc53|>,))~~/<<|||3335599cffffffiiiillooptwyABBEEHHIIIIKKMMNNNNNNNNOOPPPONNNMLLMKIIKMMKKIFKMNMKKMKFHEECCCEGHIKMNNOOOPPQRRRSSSSSSRRQQPMKFEGCByywwwywtppzAAzzDEBAzxxuuuxxwwwyABEHIKNMMMNNNNNOOPQQQQQQQRRRRRQQQPPONMIHEEEEEEEEEAAyyAAyyywpoic95||//~),--*%$$##@", +"@@$%%*--->>,,)~~/<<||333355599ccfccfgfiiiiloopptwAABEGHIIKKKKMMNMNNNNNNOOOPOOONNMKLMKKIKMMKKIIIMMKIKMKFEEEzzzzCGGIKMNNOOPPQPQRRSSSSSRRRQPOMMIGAzAyyywwwtuxwxzAAEDAAAzyxxxxywtuwDBEHIKMMMMMNNLNOOPQQQQQQRRRRRQQQQPPPONKIIIHHEEEGBBAyywwywwwtpif993|-*%%$##+", +"@@#%&---->,,,)~~/<<||3|3335559ccc9ccffifiiiloopptwyABCEHHIKKMMMNNNNNONOOOPPPOOOONLMMKKKKMMKIIHFKMKIKKKFFFEzzzzzzEEHHKNNOOPPPPQQRRSRSRRRQQPONMICAAzyAywwtxtttzABEEEAAAAxxxzyxuttxBEIKKKKMMMMMNNOPQQQQQQRRRRRQQPPOOOOPONKIHIIIHHEEAAyytwwttttplfc953|**%$##+", +"@#$&==--->,)))~~//<<||33333559ccccccdfffiiiilnrptwyyAEEHHHIKMMNNOOOOOOOOOOPPOOONNNMMKKKMMMKIHHFKMKIFKKIFHEzzzzzzCCCGGINNOOPPPPQQRRRRRRRRQPPONKHBzAzyAyzywttxxAEEEEEAAAAyzAyxutuxAEIMMKKKMMKKKNPPPPQQQRRRQQQQPPONNONOONMKIIKIIHEEBBAwttwttppplfc953|<--%$#@", +"#$&&*-->>>,))~~~~//<<||3333599ccfdcffcfffiinnrpttwyAABEHHHHIIIKMMNNNNNNOOOOOOOOOOOOOMKKMNNKIIHIKKFFHIIIIHEBzzvxxzCCCCGHKNOOOPPPQQQQRRRRQQQPONMIEAzAzBBBzywxxuzBEHDEDAAzAAAAxuuxyABIMMKKKMKKKKMOOOOPQRRQQQQPPPPOONNNMNNNMKKKKKIHEEEBywtttpppolfc953|>-%%#", +"$&**;>,,,,))))~~~//<<||335559ccfccfffffiilnlnpptwyyAABEEHHEEHHIIKKKMMMNNNNOONNNNOOOOONMNOOMIIEEHIIEEIIIHIIBzzzxwxyzzCCCEKMNOPQPPPPQQQRQQQQQPONKHEAzAABEBAzxxwDAEEHEDAAAAEBAxxuxxzEIMMMKKKKLKMMOOOPQQRQQPPPPPPPPOONMMKMNNMKIIKIIHHHBAytwtppoolic953|>-*%%$", +"##%=;>,)))))~~~~//<<|||355999cccccffffeiiiloppttwwwAAAABEEHGEGGJIIJIKKMNNNONMMKKMMNOOOOOOONKIEEHIHBEHIIHIICzzzwwvvvvyzzCCIKMOPQPPOPPQQQQQQPPPONKHEAAyAABBCAxwyAAEDEAAyzAEECzxxxzAEIMMMMKKIKKMNNOOPQQQQPPPPPQPQQPONMMKMNNNMIIIIEHEHEBAwwttpoolif953|>-*%%$#", +"+@#%*-,,))))~~///<<||33559cccffccffcfeiiilloopppptwwwAABBEEEHJHHIIJIIKKMNNOOMKIIKKMNOOOOOONMKIIIKIGCGIIEIIEzzzxvvvvvvxyzCCELNOPPPOPPOOOPPPPPPPONMKHAzxzzBBCzzyADEDDBAyAzBEEAzxxzAEKMMMMKIIIKMNNOOQQQQPOOPQQQQQQPPONMKKNNNNKIIIEHEEBAyywtwppoolic933|<~))>--*%$#+", +"+@#$%=->,,,,))~//<||335599ccfffcfffffiiiillllmmooqssvyADBEHIIHIIILIIKLKLMNNNNMKFIIIKMNOOPONKKIKKMKHGGHEEHIECzzvvwvvwwvxyAzCHMNOOPOOONNMNOOOPPPPOONMHAxxyzAACAzADDDEBAzAABCCBAzzzAEKMMNNKIIKKKMMOPQQPPPPPQQRRRRQQPPONMMMMNMMKIHHHHBAAywtttpooolif955||/~),>-*%#@+", +"++#$%%;>>>,,,))~/<<||335559cccccffffiiiijliiiiillmqtwwDABEHIKKKIIMKKKKKKMMNNMMKKKIIKMMNOPPNKIIIKMIHEGHECEHECzzxxwvvwvvwzyyzCIMMNOOOOOMKIKNOOOOPPONNKBwxwxzABCzAABBAAAzAACEBBBAAzBHKMMNNMIIKKMMOOPQPOOPQQRRRRRRRQQPPOOMKKKMMKIHHHEBAAAywtpoolllifc9953|/~),>-%#@+", +"++@#%&=;>'>,)))~/<<<||33555999ccfffiiiffffgfggkkmmqptwyDBEHIIIIIIIIIKKKKIKMNMMKKKLKKKMMNPPOMKHEIIIEEGJHHHHICCzwwvvrrrppwyzzCGHKKNNOONKIHIKMOOOOOOONMIBwxwwyACCCBBEAyzAzAEEAABBBBEIKKMNMMKIFKMNOPPPONOPQRRQRRRRRQQQQPONKIIKMKKIHIEEBBByywtpoiiiffc9553|'',){~~//<|||33355999ccfffffccfccccggkkmoqqutwyABBEEHHIHHHIIIKKKKMMKKKKKKKMMMMNOPONMIHIIHBCBEIJIIIECzxwvqrrrrrssxzzGGEIMNONKIHJEHIMONNOONNMKEAAxxwzACBCBBAzzAzBEEBAABEHIKMMMMMMKKKKMNOOOOMNOPQQQQQQQQQQQQQPPOMKIKMMKIIIHEBAAAyttpoiiifc9953|<-%#+", +"@#$%%*->''){~{///<<||||3555999cfcccccccccccgggimmpquutuwyABBEHHIIIIIIKMKMMMMMKKIHIKKMMMNOPPOOMKKIHDzABEEIIIHGCyvvqrrrrrsssvzBCCEKMMMIIHEEEHKKNNNNNNNKHEAzwxwyCBCBBAAyABBEECAAAEIKNMMMMKIMMMMNNNOOMMNOPQQQQQQQPQPPQQPPONMKKMMMKKKIEBAAywttpoiiifc995|<*%$@+", +"+@#$%*>>)!~{/(/(<<|||3355599ccfccccc9cccccgggkkmmqqqqutuwyBEEHIKKKKKKMMMNNNNNMKKIIIKMMMNOPPOOONNKIDzzzACEIHHHEAAussrrrrssstzBAzCEHIIIIHEEHHEHKNNNNNNKIEEAAwwwyACBCBBzCCGEBzACAEINONNNMIIKMNNNNOONKMOOPPQQQPPPPPPPPPPPOONMMNNNMMKIEAyywwtppoiiffc9953|<~),>*%$#+.", +".+##$&*>,){~//<__|||335559ccfccccccccfcccfggilmoomqquuxwyAEHIKKMMMMMMMMMNNNONNMMMKKMNNNOOPPOOOOOOMEBAzAzBHEEGEEBwtsummmmssswCAvzCHHGCEHHHHEEEEIMNNNNMKIEBBzwwwyABCBBBCEHHBzzCEEIMOONNMIHKMNNNOOOMMNOOPQQPPPOPOOPPPPPPOOONMNNNNMKIEAywwwtppoliffc953||/~),-*%$#+.", +"+@#$%&*>>,!)]~(((<|2335999ccfffffffffffffkilooooppptwxzACEEHIKMMMNNNNNNMMNNONNNNNMMNNOOOPPPPOOOOONIEABAABGEEEEEBwwummqqmmmtwwzvzCEECCBEEBBBEEEEHKNNNNMKIEBBAwwwyAACBEEHIIEAAAEHINOOOOMIFIMNNNOOONNOPPPPPOOOOOPOOPPPPPPOONNNNNMMKIHBywwwttpoliifc953|-*%$#@+", +"+#%%=*=>>,!~{](/__<|335999cccfccffffffffiiloloppptwzAABEEEEEHIKKMNNNNNMMMMNNNNNMNMMMNNNOPQQPPPPOOOMHEBEEEHGCCEBzxxwuuuqqmmqwwtwvABBAzCABBAABBBBBEINNNNMKIHEEAwxwxzzzBEHIKHBBBEKMNOOOOMIIIMNNNOPOOOOOOPOONNOOOPOOPPPPOPOOOONMMMMKIHEAywwwwtpliffc933|-*%$#@+", +"+@$%**->,'!!~]/<__135999ccccccccfccfccdfiilllopptwyAAAABEEEEHIKMMNNNNMMMKMMMMMKKKKMMNNNOPPQPPPPOOONKIHHHHHGCCBAwttquuuuqmmqquspvAAAzwwyABAAAABBBBEIMNNNMMKIEEAxwwwzzyBGHIHEEAEIMNOOOONKIKMNNOOPOOOONNNNNNNNNOPPPPPPPOOOOOONNMKMKIEEAywwwwwtplic9553|-*%$@+.", +".+@$&%=->,,']/<<<1|5cfffccccffffffffcdfiililoptwwyyAAAAAEEEHHIKMMNMMMMKIIKIIIIIHHHIKMMMNOPPPPPPPPOONMKHIIKIECBBwtuqquuuuqqqqqssuwwusuwyAABAAAAAAAAEIMNNNMMMKIEAzxwzzyyAEHEEEAzEKNOOOONMKKMMNOPONNOOMKKKMMMMNNOPPPPPOOOPOOONNMKKKIEEAywwtwwtpoifc993|*$#+. ", +" .+#$%&->,')]]_1||79filiffffiiiiiiiiiiilllopttwwwyyyyyAEEEEEEEIKKMMKKKKIIHHHHHEEEEEHIKKKNOPOOPPOPPOONNKKKMKIHEEwtumqquuuuuuuqtswwwssstwyABBAAAAAABBEIMNNNNNMKIEAAyzAyyAEEEEECABHMNOOONMMMMMNOPONNONKIKKIKMMONOPPPPPOOOPOOONNMKMKIHEBAwtpttpoliffcc93|,')]_<1359dfifcfiilllliiiiiilloopwwwwwwwwyyAABBAAAABEIIKKKKKIIIHEHHGEBBACBEHEEIMNMNOOOOOOOOONNMNMKIHEAwtmqquuuutxxqmtwwwtssttwyAAAAAAAABBBEIMNNNNMMKHByzyAAAAEEEBBAACHKMNNNMMMNMMNOPOMNNMKIIKFKMNOOOPPPPOOOOOOOOONNMMMIHEBAwtpppplifcc99953|,')]_<|359900009dfiiiiiiiiiilooptwwwwwwwwwwyywwxxxzzAEEIKKKKIIIIHIIHEBAAzzCABEHKMKIKNNOOOOOOOOOONMKIIByuquuuomnpzyuqquuqmmmmstwyyyyABAAAAABEIMNNNMMKKHEywwwyyAABBBBBBHKMNNMKKNNMMOOOONNMKIKKKKMNOPPPPPPPPOOOOOOOONNNMMMIEAAwtpppplfc99553333|*$@.", +"@@#$%&**-''')~(<}357527755799ccffffilloppttttwwttppttwtttutxxxABEEIIKIIIIIIKKIEEBAAAyAABHKMIHIIKMNNNOOOOPPONMKKEEzyyAtrnnrtzxuuuuqmmmmmmswwtwwAAAAAABEHKMNNNMKKKIEAwwyABAyyABEHIKMMMKKKMONNOOOONNMIJIKMMMNOPQQQPPQPPPONOOOOONNMMKIEAywtpppolif955||<<<*%#", +"#$%*;>>,,))!~](<|35772447777709cccfiiopptptttttptppppuwwwwwxwyyAEEEHHHIIHHIKKKHEEEEAABBBHMNMIIIIKMMMNOOOPPPPOMMIHEEGEytnlopxxuuxuqmmmmmmmsttuuwAAAAABEHHIKNNMMKKKIEAAABEBAyAEHIKMMKKKKKMNOOPOOOONKIIKMMNNNOPQQQQQPQPPOONNOOONNMMKIHAAwwpppplifc95||<-*%$#", +"+#%*>,,~~~~///<|2552243277777090ccgiloppopttttppppppptwyywwwwxxADBFFHHIIIHHIKKIEEEEABEEEHMONMKKIIKKKKNNNOPPPPOOMKEEHHEwprptxuuxzxqmmmmmmmssssstyAAABBEHHHIMNNMKIHHHEBABEEAAAEIKNMMMKKKMMMOPPOOOONKIIKMMNNNNOPQRQQQQPPOOMMNNONNNMKKIEAwwttppoifc953|-*%$#@+", +".+@$=-,)~//<<11555575a7657509099cgfiooolopppppoloppptttwxttuuuuyAEEEEEHHHEEHIIIHEEEBEEEEHIMNMMKKKKIIIKKKNOPPPOOONIHEEEAtpptpuuxyxuqmmmmmmsssssswyABBABEHIIKNNNMKHEEEAwwAAywwAEMNONMKIKMNMNPQPOOPOKIIKMMMNMNOOPQQQQPPPONMKKMMONNNMMIHBywwttpolic953|-%$#+. ", +" .@#$*->,!~]<149999909a888999ddcffilollloppooooopptttppprqpuuuuwDEFEEEEEEEGHIKIIIHHEHIIIIIMMMMMKKMKIIKKIKNPPPOOOOMKHEEBwtttpppptsuuqqmmmmpspssutwABEBAAEHIKMNNNMIEACAwwwwwwwyBINOONKIKMNNNOPPOOONMIIIIIKMMNNNOPQQQPPPONMMKKMNNNNMMKIEAywttpplic953|*%$#+. ", +" .@#$%-->,)~/<|56596999cdccffggiilooliloppooloptttutpollqrqruquwAEBBDBDDABEIKMMKKKKIKKMMKMNNNMNNMMMKKKKMKMNOOOOOONNMIHAwwwwtpppppnuuqqmmmrssusttyABEEBAABHIKMNNNMHEEEBywwtttwAEMOOOKIIKMNOOPPPPONMKKIIHIMMNNOOPQQQPPOONMKKIKMNNNNMMKHEAwttppoif953|-%$#+. ", +" +@#$%-;;'!](_||322565599gfffiiloppolllppplooptwwtpollllprprqquwABAAADDAABEIMNNNMMMKKMMNMNOONNNNNNNMKMMNNMOONMNNONOONMEwtwwwtpppnjnquuqmmsssupuwBCEEHHHAABHIKNNNMKIHHHEAwtuttwBINNMIIIIMNOOOPPPOMMMMIHGHIMNOOOPPPPPPOONMKIIIKMNNNMMKIEBywppooifc53|-%$#+. ", +".+@#$*=;>,!](_<}}|346769099cfiiooppoilpttppoptwwtpplllooprrmqquyBADyDxxyAAEIMNNNNMMMKKMMKMNOONNNNNNMMMOOOOPPOMIIIMNONNKAwwwwupppnjhqqquqqssspuwACBBBEEHEAAEHKKNMMMKIIIIEypopptyEKKIEEHIINOOOOOPONMMMIGEEHKMOOOOOPPPPOONKKKIHIKNNNNMKKHEAwtpollic953<*%$#+. ", +".+@#%=-;',](_<|:|||776599989fiilooliiotwtttptwwttpooooollqrqquuABADxtuxxzAEIMNNNNMKKKMMMIIMNNNNNNNNMNNNOOPPQPOKIEHKNNNMIEBwutwtqnhjjmqquwttpsvwzABAwwyABAABEIKMMMMKIHEHEBwtptwAEEEHEEEHIMNOONNPPNMMKIGCCEFKMNNOOOPPOONNMKKIIHKMNNMMKKIEAwtpollif993|-%$#@..", +".+@#&=;>,)](_<1:}|4114700099filoolffiotttppttttppoopooolnqqvvuxABDxuuuxxxzGKMNNMNNMMKMMMHHKMKIIKKKMMKNNOOPQQQPNKGEEIKMMKKIBxuwxupjhemmqqwwwuvxwtwywtutxAAAABHKMKMMKKHEAABywptwAEHEEHHIIIKNOONNOONMKIHGCCBHIKKMNOOOOOOONMKKKIIIMNNNMMKKEAywpollifc953-%$#+.", +".+#&%;;,]((<<:<||1114770770fioollffgkpppqppooigllooolikilrprruxEBwuxvstwwxzEKNNMKMMMNKIIEHKMKIHEHHHHEHKMNOPQQQPOKHHEEBAAHKMKGCAxuppnqqmmtwwwxtsmquuqmmmmwyyyAEIKKKMMMIEBxqoputyBBAABEKMMNOPONOPOONKIEEEBCGHHIIKMNNNOOOMMMKKKKKKMNNMMMKKEAywpoliifc953,]((_::<|_114470770dflooiifcgmppppqpoiigglmolikjiimmnruwAAxussvvupptyHMNNMKKKKIIHHEIMMKIIIIHEABIKMOOPQPPONKEEEAtuwEIKKKHAutttxuquttxwqqqmquqqmmmmmwywwyEIMKMMMKIHAqmmuuAAAwxwAEIKNPPPOOPPONMIEGGECBHFFIIMNNNNNNMMKMKMMKKKNNNMMMKIEAytpliiifc93|/~),>*$#+.", +"+@#&=->){((___<|__14770070cilpliggdflpppppplggggkoolikikjnmmqqwAAxsstunqqpptyEKNMMKIIIHEEEIMNMKIIIIEAAEIMOPPPPOOOMIHEAumotAEKMMHAwwyAAxwwuqqquuqlnnjmhmmmqwwwwyAIMMMMMKKEumlptABywttyAAHMOPPOOPPONKIJECCCEHIIIKKKKMMMMMMMMKKKMKKMONNMMKIHBywpoiiffc953|/),>*%#@.", +"+#&&->'!{(((___|__1477770dgimoliiddglloppoigggggkkolikjkkmmnqqtwyzutvoonoppttyEIIKKKIIEEEBEKNMKKKKKIEABIMOPPPOOONMKKKHwolootAIMMHBAABAzAyqqqqnorooonjemmmqqwwwwuAIMMMMNMKApopwBEAwtttyyBINPOOOPPOMIIHGECCEGIIIKIKKKMMKMMMMKKKKKMMNONNMMKHEAytpoiffc953|<~),-%$@+", +"+#&*->!{{(((__<_[_1}23246dklopmliddfiilllifc9agkkiollillknqpuuuwxxwunnoookkmqwABBAEHHIHIHHEIMMMKKIIIHEEIKOOPOOONNMKMMKEwpojipyIKKHEBCAyxuuunnlmmmmmkifjjqqpwywwquCIMKMNNMHytpwBIHAtttwyAEMOONNNONKHHHJGBBGEIIKIIIIIIIIMNNMMKKKMMMNOONMMKIHBAwpoiifc955|*$#+", +"+#%*>'!{{((::___[_1}34226bkmppoliddciiigifc9a8akmkkollllmprsuuuuxwzxrnnkkkkmmqtwywwyyEHHIIHKMMMMKIHHEEEIKMOOOOONMMMKMMKAwpiiipyGIIIHEAzxxrookkmmqqqmkgjjjqquAyywqwBIKMNONMHAwtBKMHytuwyyEINNKKMMMIJEEEGBCEHHHIIIIIIIIIKMNNNMMMNNNNOONNMMIHEAytplifc995|*&#+", +"@#%-''{{({](<:<__:<}3222adjouuqligd9fiddddd9aaakmkglolmomrqpuuuuuuyttqkkmmmmmmtwuqtutuAAEEEKMNMMKIHIHEEEIKKNOOONNMMMMMKIEApfhlpxzEIMICztppmkkfjiloppmkkjjquwAAAyuuyEHMNOONMIBAEMNKBttttwyHKKIKMMKJHEBEEECCEHHHHIIHHIIIKMNNNMNMOOOOOOONNMKIEBywpoifc9953|/~)>-%#+", +"@$=;,){(~/]<:<:___:}422269iotwtmig9acgddgdd0788cmkgloooomqqqqsuvuswtwtmmmmkjmmuwuqmmppuwwyABIMMMMKIIHEEEIEIMNONNMMMNMMMKIIAoooopuyEMMJAwqqmjeecbcfopomkgjnwwwAAAuutABHMNOONKIHIMNNHwppptwEIIEHMMIHHEBCBCEEEEHEHIIHHHIIIKMNMMMNOOPOPOOONNKIEEAwtolicc953|<~),;*$@", +"#&=>,!~(](/(:<::__<}211179iotxwpmg9a0ggggfd07a8cmkggoooooqrmqquurrtpwtuqmmmmhjuwwuqmmmutuwwxCIKKKKIIEEEEEEIIMKKKIKKMNNMKKKIAttpmmpwHIKHzuomiec9abbfiolkggluuuwyAAtuuyAHMOONMKKKKMMHypqptwEIEEEMNIEBEEAABEGEBEHHIHHHHIIIIIKMMMNNOPPPPOOONMIHEBywpolfc955|))~(]//<;&#", +"%*;,){/]/*%", +"*;,)~((/::<<<<<_::11211147dipwAAztlgdddccca0008aemkklooputxussuuuuorpkmmqoppptwyAyttpuuuxxxxCEEEBBAABBBAAwAEHEywwwyAEKMMMMMMMNMIBwqmoptAEEyolifca668ciilmmonqqwyAAyxuoptzIKMMMMNONMKBwqotAIEEEHEEEBABBBADEIHEEIIIIIKKKKIIIKKMMKKMNOOOOPONKHEBBAwtpoifc9953|<~)>*", +"-,)~/_|<||||1__<}|2|4411470gmtyCBypkgbdfgfdd008bbmmkkonpptywwttusuvookkmmlnoopptwwprolluutuuzEHEEEAzAwtwwwwBHEypppptwBHIIMKKMNNNKGzpooptAEBwpiif9a6aceiinqpnuuxAAAByxtopxEIKMMMNOONMIAwqtyHHEBEEEEEBABEEEHIIHEHKKIIKKMKKIIKKKMKKKMNNOOOOOMIEEAywwtoigc9953|)~/(_||||1||__}|14434}470dkpyzEAzulfhffffgdddabmmmkkorppwyyxwuustprmmmmiikillmptplnjinqqqquAEEBEAwwwptttwAIHAtlilptwyAEIKKMNOONKEwpoolpyEEyplifd866fiioqqpxzAEEEByxwppuAEIMNNNOOONKHAttyHHHBEEEEEByAAEHHIKIHHIIIIKKKKKFIIKKMKKKKKMNOOPONKIEAyywtplid995||/~)>-", +"*-,)~/_<|}|||<__:<|2442}}470dlpwABAAtoifcffggdhbbkmmmkgoopuxyzywwuuppummmeefefgkopmkijhijijquyBAAywttuuuppowHIAwpliloppptBEIIMNONMIBwpiiiowEEAtliff98biilotwwAEIKIHEAywptyBEKNNNOOOOMKEywAIKIEHEEEEAAyAEEIIKKKIIIIIIFFKIIHIIIKMMKKKKMNOOPOMKEEyywtpoifc0531,!~/<_|}|___<_<:_<1422}}2770cilpuxwwwtplifggikmmmmomkoloouuwAABAAAwtmkkkbbbcdgmtplggddeijjnpwwvttqmoollllltABAwpoiillfflttyBIKMMKIEAtoffipyEEypliiifiiilpwBIKKKKKKIECwwAEEHKNOOOONNNNKEHKMKEIIHEEBAyyAAEHIIKMIHEEEHIIFFHHHIIKMMKKIKMNOOOONKIHByytpolic054|(~';", +"=;,)~/_<|}|<1<<__((<14222227770bhkmoptttupolkgjimmqqqqmkllmmppwAABBBwupkkkbbbbdglpumgddddgkknpxzwwwqlolnlifipyAAAwpolllifioopyBHIKKIEAwpicccmwBBxpllliillootBIMMKKKKHHEAyABEEHKOPPONNNNNIIKMMHEHHEEBAywwyAEIIIKKHFEFFEIIFHIIKKMNNMKIKMNNOOOOMKIHBAwtpolid571_/';", +"=;,~/<<||||11<|__::_1}222227777abdgekloptttpqmlimmqpqqqknnnorppwyAABwtpkkkkbbb0glppmgdddggmmmuwAAywtolnllecclwAAAywpoopoiiiiltyABHHHEEAtof57dipyypoiiillllotzHMNKKKKKKEEABBBEEINPPPONONNMIKMKEBEEBBAwwtttwAHIIKKHBBEEEFIIIIIMMOONMMKIKMNOOOONMKHHBAytpoifc96}_!;", +";'!~/<<|||21|1|__:___}}22227777880888bfioopputpoqmmmpqqmomnnrppuwyAzAtpmkgkhcb0dkoqmgdddgkmmmqtAAyywooooif98fotyywwtpopplifciowwtwBEEEByti0730gmutpiiiillilotCKMKIIIKIIEEBBAABEKOPPONMNNMIKKEEDAABAywttpptyEIIIKHEABAFGHIIIKKNOONNNMKKKMNOOOONMIHBAAytpoif952_!-", +";')~/<|1||3114|<1:[_[1}12267000a0aaa66aadfloqutttppommmmprnoopqpwxwyywtpkkkfehddkmqmggggkkkkkmqtwwwpolollic89ilotwwwtqptpoiccippoptyBEBAxqf5347dltwoiiiiliifowEKKHEAEEHHEEAyyAAHMOPONKKIIIIIEBAAyABAwtuuqutAIIIKIHBAzACFHIIKKNNOOOOONKKMOOPOOONMIHBAywtpoif97:);", +";'~/<1|1453442|11::___:[}227000bdaaaaaa6a8cfkmutwxtuqmmmqprnnopptwxxzzwtmmmmheedgmpmkbcfffbbbeipttopllillif99fcipyywtpopmpof9flpoilpwABAAuld3||7dlutoiiiififioyEIJAwwABEHEBywwwAINOPNIEHHHIIEAyAyABAwqprpptyEIIIIHECzAABEGHIKMNNOOOOOONNOPPPPOONKIHBAywttlif5}{'", +"'!~<<|347555333311:___1:[}47770008a6aaa66a0adglowwyxuupmpppronpppwxxwywwtmmqjjedgmoojeeehbbbbhfoooooljfiiifccddcowywpilommplccilliilptAAAyuid7|47dmwtoiifffbilwAEEAtppxAEEEAwpwAHKOOOMHCBEIIIBAwwAEEwqmprptwEHHHJHHBzzzzABEEIKNOOOOOPPPONOOOOOONMKIEEAywtpol92[,", +"!~(||355055957|211}}__1}[}447787066aaaa8668a0degmuwwxwwuttppqrqppwwwxxywwqqpllidgkmpjffhfb9bhbfiopooofccffcb50ccitAypiglllppiffiiifilptyAAytmf0770itzwpliiifcipwBEypolqtwBHEwppyEKNOONKBABHIIEyywxAEwumpqqtwAEHHEHHECzzzzzCCGKNOONNOPPQPONOOOOOONMKIEEAywtpof7}!", +"~/1435990999577314}}1111}44247a76222666a6868ddbkkmquuwwwywttpprrqxxxzxwtwpqqqonggkmqljfeea8bbb8elponifccccc770dcfpywoffiiklpoliififiioqtyAAzwpmd77dmwAwmgiiiffotAAwtoiilpyEIBtotAIMOONMHyABEHHAtwwyBytqppruwAEHHHHHHECzzzzzCCGKNONNNNOOOONONOOOONNMKHEBAAwtpi93:", +"~<|7599cddcc099544}22114244477776}22226a66a8ddekkkkmmquwAzywwupqqwwxzyxttwuutlliggmqoiiheb8ba88clpoolibcccc5750dfltwofdfifimpppliffiiimptwAAAyulc0dkuAAwoimoilotwwtplifcipAEIAtpyHKNOONKBwyzEEBxwwwAxwutrpptyEHIIHHHHECCACzCCBHMNNNMKKKMNOONOOONONNMKIEBAywplc|:", +"]<|5559ccdfcc9a90772244444477776622222226268ddekkkkkkmmqwAAAywttpwwxzzzytwquuojigkmooljieb8a888ciopoli999cc95|399fowpf9cfdglotwticcfffgouwABEEBwpifipwAAwpppqppwyytpplffeioyHIAttBIMNONNIywAAEAzxtuwwwuwsrpuwBEIIHEEEEGBCCCAABEIMNNMIIHHIKNNNOOONNNMKKHEBywpid3]", +":|35099dfdgbc0d9975224477777787a2222[}22622a00bkkkkkkkmmtwyAAAywtwwvxzzzwuwqtuljkkmmoliifb678889fopliic88c097||59clwwofcfccilqwwofcfiiiotAAEEHHEApliipwAAyttttpwAytpppliccipAIIytyHMNOONMEwyAEBAwwwzwxuytprptyBEHIEEEEEEBAAzAABHKMNKHHHEEGIMNNONNMNMMKKIEBypli5:", +"}6599ccfffgfc0dd9706657777777776222}1}16666800bkkkkkkkmmpputAAAAyAwwxzzyytuquuoojkmmooiihc666888elpllic9999951|45clwywpif99cgipwwlfiopootyAABEHHEwpiiiowAAytututyytolopoiiiltHKHzwEKNOOONKAwAEEAyyAzwtuwwtrrpwABEEEEEEHEBAzAzABEEMOMIEEEBGGKMNONNMKKKKIHHEAwpic4", +"|609cgiiiliiecdd0000675777708066266}2226a66800bkkkkkkkmmqpuqwwAAABAzzxywyttqquppoklmqoljheaa68aabjplllic99055|||5fotyAwoi9599glwBypopppoptwyyAEEEAtmifglwAAtpqptwAwlcfiooifflwIIEABKNOOOONIAABEEwyyAwuuwywpppswzAEEEBEEHEAzyzzAAEKNNKEFEBCCIKMNNNMMKKKHHEEAtoib5", +"_}599fgiklliifgd9c006665500cb0aa6a4242228aa8dehkkkkkkkkprqrsstwyACBAAzzvxxttquxppmmoppojifb666aabfolloic99575|1|5iptyAtoic509clwEEypoppplotwwyAEEAwplf99itzypompwAwofcfqoliffoAIIEAHNOOOPOMHABHHBvxwuuutxwtppptwwAEEEBEHECyyvwwzBHMMMIEECCCHIKMMNNMMKIIIHBAwpi81", +"_|290cggiiiiifdcdc90d0899bcfdgc9807a666a8a8bghemkkkkkkkrrrqpuuutwBEEEEAzvxtwquxttpmppppniee866a88elllllf997553115iptwAtliiccfilpAEAwpoppootwAAABEBAyulf99iwzwpllpyAtf9ioolkdfipAEByBKOOPPPOMHBHKHytwtuquttwtqqtwwyAEEBBEHEAytwwyAEIIKIEECCGIIKMMMMMMMMIIHEAwpj82", +"}478dcggfiiiifdchd00d09cdfffggeff9b99999fccfhjmmmmmmkkkprrrpruptyAAGEHEzxwttquutttqqttpojfeb668a8ciillif885553335fpwABApoooliigipyAAtooppopyEEEEBEBAwpf979iuxulgipyti9ciolffcdipABAwENOOPPONMIHKKBwppuqqutuqmmpswwyBBEBEEHEwxwwwyzABHHEEEEHKMNNMMMMMKKKIEEAwpj9}", +"[458ccfgiiiliifhfffdggcfffiigffffcc9dcccffhimnqqmmmmmmprqrrrrrqqwvzCGIIECzwttquupttttxwplfehb6a88bfllliic885557339lwABEAwwtoic9fotwwwpoppptAHIEBAAAzwpg5413guuogditwlc9cillfc0cipyAyAINOOPOONKIKKIAtppopttupqmmqqwyABDBBEHEzxxwyuxzAAEEEHHIKNOONMMMMKKIIHHBwpj8}", +"[659cffiiilllikiiiigkkfffiiigc9cc8956aa9bfgimouuqqqqmmpprpprrrrrxxzzBIKHGAzttqqupptuwwwtnifhbb6a8aclloiic9959994}6ftwAEIHAticccfloppxwtpptwyEHEyxwwwwpk0|<_4gqpicfpwticcktttld9dltAAAEKNOOOONMKIKIEwttppppptqmmmquuyABABEEEByxxzuxyzzAABHHIIMNONNNNNMKKKHHBwulb}", +"}6addfgiillolllmlilikikffffdd96622|2327689ahknqquuuuqttutrrrrprtvwxzAEIHHEAttuqquppuxAzypjfhbbb888bioollfc909954[3cpwAHKHyof9cccfilotAAtpwwwAEEAwwpppqmd4_/<9kqofcmyApifoAAAwof9iqwBAAHMOOOONMKIHKHAwuttttttpolmquuuwABAABEEAywsuxxyxwAAFEGHKMNNNOONNMKKKIEAtqc6", +"669ddfiilmmpooollilffffg9bc0d056}}:}[}2}a68dhhmnmqpswwwwtttuprrvvxxAEDEEGGEBwtmqqopstABCyoifbbbb88bfllollfcfd95333cpAEIHBtlfccc9ciiopyAAwtttwBEEAwpoomif5|<_49mqkfiwytiipAAAAtlfcfpwBABKNOOONMKIHIIBwwwtutwwwtooouttuxBBABEEEAuuuuxzxuyyyCBGKKMNNOOONNMKIIEAtqh6", +"6abfiikllmpqppomlmiigffgf9906622}}[[::[}66addbkmmmmtttxvwwwttuwvvxxzBFEEBCEEAwqmqqnotyEIEwmhbbbb888cipopoiff995756cpEHEytpliif959clpptAEAwttyEEEAwpmkmmg93<<<|9mmgfmwwoiotwttwplccfqyAyBKNOOONKHHHIHAwtpttwyywttppttuxAEEEEEEExxxxxzzxywwAzCEIKMNNNNNNMKIIHEzrk8", +"6bhilllomppppppmllilgggig997a222}}}_[[:[22adbbkkkkrrquttwwwwvyxvxxyDBEFEBzCEAAwqqqooptBIICtlgbbaba8biooptofcb90799ftEEypopplifc55cloptyEHyttyBEywpoomlmld7|_((|dolcfqupllliilptpicfipyyyEMOOONKIEEHIEwtppptwwwwwwyywwyzEEEEEHBAzxxxzzyxywAAzCHIMMNMNNMMKKIHEzxk8", +"8bjilooopppppppmloiifgkkica76222}}2}}[[[2280bkkkrrqrrrrpttwwzzzyzxzDDEFEEzzAEBAuqqqoppxEKHymkggbdb88fltttof990900flwBAtiiopoifc569iotwwEIEwtwyAtpooomopplc51_(/3goicippliiiflpttpfciowAyAIMOOOMIBABIIBwoilpttttyAEEBAACEIHHEHBBAxwyzzAyAyAzzCFIKMMKMMMMMMMIHBxnd", +"dhinommppqppprrmloiigggkkf00a222}}22}}[22280bkkppprrrrvqrqvxzAACzAEEFEEFDzzzAAByuqqnprtAHIBtmgggbbb8cltwtpiccc90cipwywpfcippifc959fopwwAHKBwtwwplmllmoptpod7|>>->!<1<(_||||/~/4cilkggiddfoxAtpic7||3fpAEIKMMKMKIAwyHKMNMMKIBAywoilpwwwtpotAHKKNNKHBABBAxwuwACEIKKMMKKKMNNNOOPPO", +"OOLNNNNNLKIIEDDzxxwtwwwuuqqqqnigggggggeemmrrvvvwxxzzDFFFIIMMMNOOOPPPONLHFDzvvprmmmqquuqmmmqwyAIIKKIBypof997735illooliiiloptpptttppwwof5|(~~),>>-=='!<_{)///~~,,{3gklkgiigfotyytpi95335fpwBIKIIKKIBwyEKMNMMKKIIHEyplloptwywyBKNNNNNKIEEEEzuwwzCGGKKKKIIIMLMNOOPPP", +"POOOOOOMMJIJEEDzzwywwwwqqqmmmjhjhggggiijmmtsvvvvzzzDDFFHHLLMMOOOOQQQOOLIFCzvpsmmmmmjnuuqmmmtwAHHIHEEztpic99542cllopoiiiiilpppppollptof3<())))'>;=&*>~<~,)~~)),>,~5ilkiliiiopuyywpf95599kowEIIHHIIEwwAIKMNNMKIKMMIAtolllpwAyEKNNMNNMKKIKIEzAwwCBEHIKKKIILLLMNOPPP", +"POOOOOONKLLHFFDzzyAwwttmmmmmmmeeedgghjjmmsswxyzzzzzEFHFIIKMMOOOOQQQPONLIEzzvppmmmmejjnruqmmtuyBHIEHEBwpofc95439iopttpolliiopolliffilli5|~),,'-*==%%;~11(~//~)~),);**=-,)),)~<<~~/<<<|<))<5fluqqoommuxAyticcf9335itEKIIKKIAttyHIHHHHHIKMNOOMBwoliowBHKOOOOMIHIIMNMKIHIIHHIKKKKMMMNOOPQR", +"RQPPOONLLLIFFFECCyvtsrrmmmmmmrmmmmmmmmmpssvvvvvzzAEFFIILLLMOOOPPPPQOOLKFECAwwqqjjjjjjjjnpxuqqwyBHEEEEEEAtpic0975cipwwwtplililllllif99flf3~,>***-,),-*-)~~),)~~~~)>)<3clqqmmikmtyytlfffc5|39lAIIIIKKIAtwEIIHEEEEHKMOONMEwpoptABEMNOOOKHIHIMMIIHKMMKKMMMMNNNNOPPQR", +"RQQOOONLLIFFFGCzyxvsrrrmmmmmmmrmmmmmmmmrrvvvwvzzzzFFFIKKKLOOOOPPQPPOOLIFCAzwuqqjjjggggjjnuuuqwyAEBCBBEEAytof009669ipttplifiioloolid3}5fi9/)>*&*-->*#@#*>,>-->,',,>>)/|dlqqmkggmtxuiccffc559itEIIIIKKHytyEIIHHHHEHKMNNMIEywwyBEEIKMNMKIHIIKMKIHHMMMMOOOOPPPPPQQQR", +"RQPOOOMLLIFHFECzvvvssssmmmmmmmssmmmmmsssvvvvvxzzzCFFIILLLMOOOPPPQPPOMMFFzyzxuuljjggggggjjjuuuqwABEAAyABAwtpi0097269lppoifffiliilii93:<5ff|~,-=***%#+.+@%--*%-),,,---,{|foqqmkgkqtul959fif99fpEKKKKKKKEwwBEIIIKKIHHIKKMMKEBEBEIKIMKKKKIHEIIKKIHHKMMMNOOPQQQQQQQRR", +"RQOOOOLLLKFFEzzxvvvssssmmmmmmmssssssssssvvvvvvzzzCFFILLLLOOOOPPPQPOOLLFFzvstqqllkgggddgdehquuuwyAAxzyyzAwwplf777225foolifffifccili93::|9ic|{>-%%%$+. .@%-*%*,),,>-%*>~3gquqmmikuupc3|3cg95coAIMMIKKKIEABEIIIKKKHEBEHIKMIEHEIMNMNNKKIHEEEHIKIEEEKKKIKNOOPQQPQQQR", +"RQOOOOLLKFIHBzzvvvvsrrrmmmmmmmrrrrrrrrrrrvvvvvzzzCDFHLLLMNNOOPPQQPONLLFDzvspmmjjkkggddddhehqquuyAyuxzwxywwpoi9576329ioliffffc99cfi953}<3fl9<,>%#$#+. .#**%%-)),,>%$*,_0kqqqmkkqupi1(/|0c59itEKMKIIIHHEEIIIIHIIHBwwAAEIHEEEKNNNOOONMKHEBEIKIGEAAHEGHFKMMOOOPPQR", +"RQPOONMLKKIHzzvvvvsssrrmmmmmmmmrrrrrrrrrrvvvvvzzzCDFHLLLNNNOPPPQQPONLHFCzvrrmmjjkkkggddddeejquuuAyuuxwwyAwwpof950059iooifcifd098b0c955|<5ff3~>*###@+....@%*%%%>,,,,-%%-)_cmquqmkkuuo9<)~|9550iwEKKIIIHHEEIIKIHEEEBwwAwABEBBEIKKMOOOOONKHEEHKMIBBAEEEGEFKMNOOPPPR", +"RPPOONMMKKHEzzvvvsssssrmmmmmmmmmrrrrrrrrrrvvvvxxzDDFHLLMNNOOPPQQQPONLHFCzvrmmmedggkkkggddeeemquxxAxqutwwywwpolf00cdcciiiccffc988799dc9|(/|99<,-%#@@#@+++@$**%%*>>,,,-%*>~3gmqumkkmuul3/!/35379iwEIIHEEEBBEHIHEEBBBAAAAyAAAAAABEHMNOOOONKIHIKNNKEHEIIIHKMNNOOOPPQ", +"QPPOOMNNKLFEzzvvvsssssrmmmmmmmmmhrrrrrrrrrvvvvxxzDDFHLLMNNOPPPQQQPONLHFzzvrmmeeddggffkggddeemmuxyxwqqxtwwywwpoif99cd999cccfff99599ccc9|(!)|95/>*$@#$$##@#$*-*%%*->>,,>->)/0kmqqkgluuuf1!)_7||39lAHHEEAwwtyABEBAyAAAABBywyyAywAABEKNNNNMKIIIIMONMKKIKKIIMMNNOOOPP", +"PPPOONNNMFFCzzvvssssssmmmmmhhmmmmmrrrrrrrrrvvvxxzDDFHLLNNOOPPQQQPPONLHFzzvrmmeeddddbhhkgggeeemqtAyutqqpwxzwwpoif9500d079cffiicc99955553_),~393)-%##%*--%%%->>-%%*->>)~)>,~|fmqumkkquxm7{)(3|<13ctBEEByppttwyyytolpwyAAwtppwwwyAAAEKKKKKHEEEEHKMKHHHIIEEHIKKMMNOP", +"PPPPONNMKIFCzxvvssssmmmmmmmmmmmmmmmmrrrrrrrvvvxxzDFHLLMNNOPPPQQQPPONLHDzzvrmmeeddddbbbgkkgjeemmuzAuqmqupwxwwwpif9569d0779fillif992||333|/),~39|,-%%*>,>-**>)),-%%*->)/~,,)/7imuqkmmuxug<){|3<_19mAEEEypoptwtttpidfltyAwpoioppttwwAHIHHHBAAAyBEHEzyAAEBCCEEFIKLNO", +"PPPPPONMKHHzzvvxsssmmmmmmmmmmmmmmmmmmmrrrrqvvvxxzDFHLLNNOOPPQQQQPPONLHDzzvrmmeedddd88bbgkkgjeemqwzxqtmquttwwwwofc645d07|5coppof92|:::|||<~,,~35<,-->,>>-*%-,~~,-%%*->)~,>,~),->)~3gquqmqqtuqc_~{|4<~/5lAEEByoilpppppoicclwAwtollloomrqqwBBABAwswwyAEEBxuwwyAzzzEFFLLO", +"OOOOOONMKHECzAyttsmmmmmmmmmmmkkkkkkhmmmmrrrrvvxxzDFHLLNOOPPQQQQQPONMLHDzzvrrmmeedddd88dddgknjjjquxxxuqmmqptuwwwpic8a634439iptof9221<**,)(9kuqmmqpuuo7/(<|1{{<5pBEBAtiiotpopppi9ftAAytoolooqqmqtyyyAAtpsttwABAyuqtxzzzzCEHILM", +"ONNOOONMLIGCzzztusmmmmmmmmmhmkkkkkkkkhmmrrrruvxvzDFHLLNOOPPQQQQQPONMLHDzzvrrmmeeddddddddddgjjjjquxuuuqmmquutxwwtpica666859cilof959553<(//<<<~))/|33<)*#+....+*~//,-%*->,-*>)~|fqumopuuuuk3_/<|/){_fyBCBypfgoolopqoifowBAwppqppttppwAywwyupoooqtAAwxuqtwxwzADFFIL", +"LLNNOONMKFGCCzAttsmmmmmmhmmkeebbbkkkkkkmmrrrvvxxzDFHLMNOPPQQQQQQPONMLHDzzvrrmmeeeddddddddddjjjlouxuquuqmmqotuxwwtpfa6aa9cc99ciic9cff93|(~~/--,)(9kqqomquuuqc|((__~)<5oABCAwmcfigkooppllpyEAwwttuuwwyAywtwytlinllpxywxuqtxzwwzCBFFL", +"LLNNOONMKIGCCAztutmmmmmmhmmeebbbbbbkkkkhmrrrvvxxzDFEJKMNPPPQQQQPPONMLHFCzvrrmmmeeddddddddddeejnopxuqquuqmmqptuxwttofc9ccc9575cffffiic731/))~~/~/<|59<-$@. ...#>~<~,**->,,->,~|gmqmmquuuuk5<~/_({(5fpABAAtg9ccglmptpoouAABByyyyAEEAAwtwAwojjiiouwwsuqrtwxwxzABFI", +"ILLNNNNMLFGCCzztttmmmmmeeeeeebbbbbbbkkkkkrrrvvvxzDEJJMMNPPPPQQQPPONMLHFzzvvrrmmeeeddddddddeeeejoptuqqqqqqmquutuwwttplie98655379cfilic541<~),,)~<<<39|,%#@.. .+%,~/~--*>,,>>>!/9kqqmmtuuuqc|/~///(49iwAAAypc90dioppwpolpwEEEEEBEHEBAytwAyplliinuwxtpqqttyxxzzAFF", +"FILMNNMKFIHCCAzuttmmmmeeeeeeebbbbbbbbkkkkkrrvvxxDDEJJMMNPPPPPPQPPONMLHFDzvvrrmmmeeeedddddeeeeejnptxuqmqqqqmquttutwwwtlf866444426cilic5||>)~~<3|~-%$#@...+#-)~),---,,,>,)~|gmqolquuuuk7_((///<7ftyAyyti059floqppogioyEHIHEEHEBAyttwypooihjpttwpqqqtuzxyzDzF", +"FHKMLLMKKHHCzzAtttmmmmeeeeeeebbbbbbbbbhkkkrrvvxxDDEJJMNOOOPPPPPPPONMLHFDxvvrrrmmmeeeeeeeeeeeeeejotpuqqqqqqmmqutwwyBBypc662|11[}}3clic54<<<~'-**--,~||~,>--*$+++#*,)),,;-,,))))~{5kpmllquuuq0|<(((~/3gpyAywwpf70fiiiioplcfpyEIIEHHEBAwolptpookfeotttsommqtxxyxAzz", +"zFIKMLLKKIHCzzvtttqmmmheeeeeebbbbbbbbbkkkkrrvvxxDDEJJMNOOOOPPPPPPONMLHFDzxvvrrmmmmmeeeeeeeeeeeejoppouqqqqqqmquxwxABAypf96221__[:<3fif93|*%%%-~||/))),>*%#+@%>)),>,>,,)//~~~,,>,)/<-%%%>))>>,>,)~/%##$-))~//~/<|*-)~,>>>,)~{/<(~(7kmmfgmquuqi9995<{)|fpyAyppqpppof059cittrififiopttpiiptpllljifisttqomljmmrnqms", +"stzCCIIKIIHGzzyxuvmmmmjeeeddddddadadbbbkkhrrvvxxADJJMMNNNOOOOOOOONMMMLLHFDAxxvvvrrrrmmmmmmmmmmmmquqmmmmqqloppppttttsqolpli86|_^[/~~(~~<5953<~),-$##%-->)~~<39c93/)>,),>->,~/<<||(~|gmmgckpquuog9997<~/5ityywpoppolic76acottpf9889fiiilouwtooleiiiottppjjhnmqrnmm", +"mtwCCGJIHFIFAzyvussmmmhjhedddddddadabbbkkkrrwvvzDEIIMNNNNNOOOOOOONNMKLLHFFDzxxvvvvrrrrrrmmmmmmmmquqmmmmjjlopttpnopttqmlloic84<^]{~~{{))<|55|/~),*$#%*%%*>)<3cff93<~)),>-->~/|353<~*%%*$##%>~|355955|>)/|3|/~)>**-%@+#*,///<39fc9|,~<|<~~),>>-$@@%>,,)/|9fiif93/>$$-/9ili5||0gmmg7dkquumg517c7;--->,~///~~)),%#@$*--,~<359cili9/-%%,|ioli515gmqk75gmquqmd1|5c3/{/3iwAytlgf9566862259dflptwwwwywtpicbc999fnppooihdeheheb", +"bgnrxzBCGGCBBzzvvvsrmmmmeeeeeeedddddbbbkmmrvvxxDDFIIIIMMMMMMNNNOONNNNMMMKJJLLFHFFDDDzzxxxxvvvvstwywmmmmquonjjjnmmkgkmqunjefd967}3|1/{';-*--**;>)/////~>%#%***,~|||||3cooc/-*-~9lpoi59giqmg40mmppqi3<|00|{~19pyAytif9566762223099dimopppppolfcc988biooolihhhbgbab", +"bbkrszzzCCBBBBzvvvvrrmmkheeeeeeddddbbbemmrrvvxxDDIJJJJIIMMMMMMNNONNNNNMMMMJJLLLHHFFFDDDzxxxxvvvyyywummqquujeehjmmmkkkqppoieb963|253|_{';**-*&%*-,~<<||~>%*-->)/<33|)3lppof9fkqpi77fmqpumc|<5d3_/<5itAAypid76266|}1|1|4509d9cdgklkiif9669flomligbhbbhb8", +"6ejmqxzzzCCBBDzvxvvrrrkkhheeeeeeddbbbbkmmqrvvvzDEJIJJJJJIMMMMMMNNNNNNNNNMMMMKLLLLKHHFFFDDzzxxxvyBAwtsqquuqheeedgmmmkkipppmiida31}55531/)>--*=%&%*-~<35|~>>,,)~/|5995|/|9fc|~))|iptpidflqqmd7dkouuum9|7dc3<~|dowAAwoi9311||1__(__37777750ciillf9268cjlollihcabaa8", +"8bjnquwzzzCADBDzxvvvrrkkkhheeeeeeeebbemmmprvsxDDEJJJJJHJJIIMMMMMNNNNNNNNNNMMMMMLLLLLHHHFFDDzzxzyBEAtuwuuqjheeeddgmmmjjmpplllifc32359993<~,>-=***%*>)|99|~)~/<<|59fff9|<|59|~))-=*&%%%%>)|c9|<|335cfc9cfic5|373~,>~3pwwtpllqqpmicgkquuuof0cif9=%$####%%,|95559cfllifffilf9355<,--)9ptwtppuutpmgilqquuulddiif5<_|0qwAytplf91^]^^^[::(]]!{!{{(159a2}26abfgiiigbaaa22", +"}68hnouxxyzzCADDAuuvvsrrrkkhhhhheeeekmmmrrvvvzDDEJJJJJHJJHJJIMMMMMMNOOOOOOOOOOOONNONNNNLLLLHFFFCCHIHEAqmmeeedddddgklooompppomiiid56359cfc9|<~,=%$####%>/||9flpttpoollllf5593/>*-~9opttuuxxwumikmmqqpplfioic3<<4ipyyytog92[{!!^^]::^]!!!{{(|462}}228cffiiifc9aa2}", +"}6ablnrtxzyzCABADxuuvvvrrrkkhhhhhmmmkmmrrrvxxDDEJHDEDEEHJJHJJMMMMMMNNOOOOOPOOOOOPPOOOONNNLLLHFFECIIIAwmmmeeeddddggkinonmptwwttptpigfccfiifcc5|/)>*%%%$*,))/5lwyywttttpoid955|~>-,<9iotutxzywtmmmmmqqpploqof951|9lwyywoi93[^^!!!^](^]]^{{(_1||2}2268bffkgigc0082}", +"}28bhnqsxzxzzCADDyxuuvsrrrrkkhhhhmmmmmmrquvxxDDEEEEEEEEEJJJHJIMMMMMNOOOOOPPPPPPPOPPPPOOONNLKHFFFCJIHztmmmeeeddgggggeiopptABAAywttpllc99cccffc03<~))>>->,),,/9oyAAyyAywtpli953<)>,/39copqtxxzxuomqqmmqqopqplg9547fpwAytlc6}:^^!!!]]^]^(____||<}22270dfiiiifc9071}", +"}2aahjpqpwxzzCABAyyxvuvvrrrrrrhhmmmmmmrprvuxxDDEEEEEEEEEEJJJHJKMMMMNOOOOPPPQQQQQQPPPPPOONNMLKHFFEGEBtsmmmeeedgggggghlpttwAEEAwpptolic57555555953,~~<3copttofflpABEEAywpi933999fpwuuyAAyuppqppqppuwyywoigfdflwEEEAwoic93<<:[::::<__11|23559ccfilifdc954_(", +"{}47bhhjnruuwxACCAzADvwuvvvvvvvrvvvqsvvvvxzDDDDBDDDDDDDDDEDEJJJIKKMMOOOPPPPPQQQQQQPPPPPPPOONLLIFFFzzvvpmmqjjgkmpqpqmlnlollilpwwpifgd52_~!!,,>;>--->,)),,,))~<5fqttogccfltAEEBAypic99fiiptwuwzAzxpqpuqqppppwywpiffifgpAHHEAwoif954}|}<<<|1_|__}|3659cfgiiffc951_(", +"{_47ahhjmnrpsxwACCzAAyvwuvuuvvvvvvvvvvvvvxzDDDDDDDDDDDDDDDEDJJJIKKMMOOOPPPPOOOOPPPPPPPPPPOONNLKIFFAzvvsuqqjjoqppqmmmmiiiiifhipwtlfdd961(!!';;=*&%&%*->>,,)~)~|clppofc99cfpwABBAytlfcfllltwwxzCzyuqpputpppptyywojfifcitBHHEAplfc953}:<<__<_<<}123559cfiiifgc95}_{", +"{(120hhhjnrrstxvAzCAADyvvtvuxxvvvuuvvvvvvzDDEDADDDDDDDDDDDEEJJJJKKMMNOOOOOOOOOOOOOOOPPPPPPOONKLHFECzvvstqqqppqqqmmmmkeeehhebhlttoifdd94_{!'>;-*&$$$$$$%*-,~~/|ciopi953359fptwAAyytoilpolpwyyCGCzwtputppppoqwyywmmlifflwEHHBypiffc93|}:<_||||2355599cfiifgff92:^{", +"![1700hejnnrrstvzAACAzADvywzxxxxvvuvvvxxzzBDEDDDDDzzDDDDDDDEEJJJKKMMNOOOONONNNNNNOOOPPPPPOOONNKLHFEzzytuqquttqqmmmkkggbbbfebbfottlgdd56_~!'';=**&$$$#####%>)/|clpoi5|<<<|9iptwwwtollottttyAABEHEAwtttupmqpptyAytoiiffipAEHHEAtoiikf953|1||4355555cccffiigfd52[^!", +"!(1400behjnrrstvyyzAAzAADADDAzxxxxwxxxxxADDEDDDzzzxzzyDDDDDDEJJJKKKMNONMMMNNMMMMMNNNOOOOOOOONNLLHFECzzvtwuxtpmmmmkggggdbbbhbbafopoid055_/!'';;*%&%$$##@@@@%->/5lppi9|/~)~<5ipwwwti9cipwwwyABEHIIGAywwwuopxwwyAAyumifilotBEHHEEypppolf905755599090cccfifffc96}[^!", +"!^_270deejnnrrssvyyAzAAAADADAAzxxxxxxxzzBDFDDDzzzxwxxzyDDDDEEJJJIKKMMMMMLMMMMMMMMMMMNNOOOOOOONMLLHFFzyywyxxppomkkgggddddbbehbabipolfd071_{'';;%&%&$####@+@#$%>|gifc93<),,)/3itzAtg3|5foppotyBJKKHEEAAzywACEEEBBBAtooppttyBEHHHEBAAwtppoliiffcc95559cd990962}[^!", +"!]_1700deejjnrrssvwyAAACGGACBDADAzzzzADBFDDDzzxxxxxxxxxyDDDDEIJJIKMMLMMKJJJJJJEEJIJJLLLNNLLNOOOMLKFFCCBEAAuunjjgddddeedddddbhhbbflligd541({!';;%&$$####@@@@#$$*!59953|<~~~~~<5itxxtf430floiitxAEJEEBAAAAtwAEEEBBBAytpoopptABEEEEEBAwtpoolifffc9955550d050762}[^!", +"!]_17709eejjnnrqsvwvDAAzCGGGGBBDDADDDADFBDDzzzxxxxxxxxxzDDDDEIJJJKLMMKIJJJEEEDDDDEEHILLMNNLNNNNNLLIHFCEEAyuqqjjedddeeeeeddddgfehbiiiid061/{!''-=%&%$$####@@@#$%'|95;%&$$&$$$##@##$%;_57_!>-=-,)~/<3ftxBAuifiomigipwABGBzwtttmfimwyywtppoic5590cipwwwwywttoiifdc957590cfiifc9d95|[[]!", +"!^^1470abeehhnhqqsxDvAAAzCGGHJEEBDDDDBDADzxxzzzxxxxxxxxxzDDDEEJIJMIJIIEEDDDDzzxyzAzDDEFHKKNNNNNNMMMKIIGCAxummmeeeeeeemmeeeedggkkeciiid999|>,,)/3iwACAwptttpoiluyBECywtppmg0dipuupmomkc953459iutttttttpoliigc9009cffffcccc9531[^!", +"]]_177a0behhhhhmqsxDvyADzGGHHJHEEBDDDDDAAxxxxzvvvvuxxxxxzDDDEEJJIJJIJEEDDDzxxxvxxxvxzDFHHLLMNNNNOMMKKICCAtummmmeeeeemmmmmeeejgkkkehffd99971({!'';&%&$$$%$###$&&&,|77(;*-,,;--;;)|fwABAwwyAywpmpxAEEAxwtpok05cimliiiiigc05337doutpptttttpppoifcccccc99599905531:]", +":}|45799aeehhhhmqvuyDyAACBHJHGGGEEEDDADzzxxxxvvvvvuvxxxxzDDDEFJJJJJJEDDDzxvxvsvvsvvvvzCDFHLLMNNOOLMMLIECyyusmmmmeeemmmmmmmhjhjnmmhccffd5903_({!,;***$%&&$$$#$%**>/77<,;,{,*%%%%*>|iwAAtptyAAywtwCGJCzzwtpog59fkkkgikgfffc959cipttppppttpppplifd9995537535433||1}", +"}35509dbeehhhhhmqvuyDDyDCEHGHGGEEEBDDAzxxxxxvvvvvvvuxxxxzDDDDEJJJJFEDDDzvxvvvvvvvsvvxzzzDFHLKMOOONNNKIEzvvspmmmmmmmmmmmmmmqqqnnomlfdgfd06873<{!',;**&%%&&$$$%%---)104),~_!*$$&$$*,|owAwlltyCBAwyACJJEzAwwtoc0dkmqmiiiffkifcccfmptwtpolooppolifcc955333|||1<__<<}", +":}79ccffjjhhhhhmqvuxyDDBEEEGGBEEEAADDzxxxxxvvvvvvvvvuxxxxDDDDEIJJEEDDDxxxvvvrrrrrrrrvwwzzDFHKKNOOONNMIFzzvrrrmmmmmmmmmtwwqqssuuppolicfd02505|_{'';--*=%%&&&%%=;;-,<75()~<_'=%$$$%*{5pwxofityAAyzAAGHEAAAwtui75gquumkkfccffgcd0diopppliiilooliiffc95531_<>{45<~~(||~>=&**%>{9pxtifowyyyyyABEEAyzwtum0|5gquqggd73570d0579fiilllilloolliifc995|1|>!|7|/~~_33(),>-%=;/cuuiffotxwxxzBGGzwxwttti415iomdd051<14507770ddgfiilolollliiic953||<_{~)!'';", +";'^[400eejllqmruquuxyzBAAABDADDAADwuuvvvvvuuvvvvvvvvvuxxxzDDBDEDDDDzxxvvrrrmmkkhhmmmmmptvvzzFFIMNOOMMIFDzzvvspstqqqwwwwABEEBAAxxxupoffiikccgc541_)'-;--;>=%%*=;'>>,/44_~!{390|<{>;=*,|lpofciuwutwzABGBxttuutp9<<39c90901_(_|3777590099cfilllooooolif953|<(~~)';;", +";'{[}0bbehjjnnquuuxxzzBDADDDAyDDxuvuuuvsvvvuuvvvvvvvvvxxxxADBDDDDDzxxsvrrrmmkkeeeeemmmmspwvzzFIKNNOMMIFFzzvvwstwwwwwuuyABEHBBAAxwtpooiiiliiiif997,,,>*%%&=;>>'{451~~/7mpi9|)>**>(9opkdfpwtutwyAEGAuppptuo5,!|7|/~|dqtpoc|!;->{3kppfciutttxwzAEBypooptug4{~_47007|_({(_1359000077670cfiiffffffffcc93|/),'", +"){{<}20beejnjjmqvuuzCCCDBBDAyxtvuuuvvrvvurrrrvvqsvvvvvuxxzzDDBDDyxxxvvrrmmkeeeebdddeeemmmptyyzEIFKMKKHFFEzzzyzwutttwxABEIIHEECywqlkllicfkmiiiigccc95|!<9ouodfotwwxxwyCEAwpommpqf|~/<3555|_{{!{<|35999d97243230995595555599995|/~", +"|||||60dejnnnmmmquuxzzzCDDAzxuvuuvrvvvvnnrqrrrvvssvvvvvxxxyDDDDzxxxvvrrhhmkeebbbbddddeeemmttyAEEHIIKLLHHFAzzzAyststwCEHJIJGCAzAwqqomloiffilkifgc9553|-*&&%%*-'~|3<~<3dlf09d9|~!!~|dpukciptwxxwwzCCywpmioppc|<_|1353_]~)){_|359cdd06||2122|3||||<||||459553", +"59999d9dfhjnnnqqquwwzzAAADzxuuuurvqqqqnnnnmrrrvvvsqvvvvxxxzzDDzxxxvuvrrhhheedbbbbbddddeeemmstzCEEFFLLLHFFCzCzAvvwvzCEHHHGECzzzzAwqomolifffkifdfd0743|;=%%*->!/4|~/<507||499|{!)(3mtpfdltwwxuwxzCAwtpiiopm91____471(~]))~/<159dgd967321|||<<<_((/(((<<|33", +"<39fiiiilljnnrqruuxxzxywyxxvvuuvsvrvnnnnnnnrrrrvvqqvvvvxxxxyDzxxxvvurrkhheeddbb88888dddeeemqxyBCCBDHHHHFFFCCzyxxyzBEHEGCEFBzzzvAwqomlilfc9dggddfd0333|-;'')<|/~/|4|7d03354<{~_5muukdiqutuutxyzwtpollqupf3", +"->)<|5clopttttppqvxuxwxuuvvvvqvqrornnnnnnnnnrrrvvvqqvvvsxxvvxxxxvvvqqmkkeeddd8886666888ddhjquuywywxDFEEFHFEzzzvABEHEBCCzCFFFBzzCAwqnkhb9aa3589575093|||||||||<<~~)',))/||~~|449mqf5573_/_4gtwpgflpututuxyxupomlqppoc|<<|75|/)'>>''''~_|0900765342||||<_/~~)),>;=", +"=>'~_25dioptwwvwuutuuuuuvvqqqrrnnjlnnnnkkhhknrrrvvvqvvvsxxxvvxxssvrrqmmkeedd888666666688dgjnuusstwxxDDEHHFDCzzzGEHHGCCzCHFFFFCCCAxqqkhab9644307||774_//<_|||3||///({{{/|4>'>'!{_3a9006332}<<<_<<<>-=", +"=>,](<|7cfiostywyxxwxxussqqqqnjnjjjjghhkkkkkkrqrqvvqvvvvsxxvvxxvsvrrmmmeeddd886666666668bggopwuqurvxzDEFEFDEAzCGHHHGCCBCFFFIFFBCzzwqjkhb88634704|4751~~~~~/<|33||<>')/:77657633|}__<(<<<-*", +"->,)/<|35bginpswwyzxxztvuvqqjjjjjjhhghhhkkhmmmrrrrqvvvvvsxxxvvvvvrrrmmmeedd8886666666666bbgmppummpvvxzACFDDDCCCGHGGCCzCFFFKFFHEECAwsnkie999535873|703_)),)))/_1333-", +"-'']/<|25dcfinnpttwxxzzxusvnnnjjjhhghgghkhhhmnrrqrrrvvvvvvuuxvvvvrrrmmmeedd886666666666a8bhmqpommhrvvzzzzzDFHHHGGCCzzCEFFFKKIFIIGEAwxtqijfd0539d73799|~),,,,),{_|53,'!{_|22322|4|__//{),,>>>>>-", +"*>'~_<|279cfijjoppqsxxzzwwsnnjjghgghhgghkkmnnnutpsurvvvvuvvuvvvvrrrmmmeeedd886666666666688ilomnjmmppvzzzzzAFIIIECzzzBEIIIFKMMMMNNMMKIBzytpolgccfd97905<~,'>,,>'')<||<<<|0iic00dfiikmtpi9900imuxwpfcgkmptqqqqupoi539iqppoikmmk9_{',',,',{:|42732|1<_(]{~),>-;*=&%", +"$*;)(<3359ffginnoporvuxwtupppohgghgghghhhkhjknrputttutttvvvvvvvrrrrmmmeeddd886666666666688ellmgjemmstwwvxzzBIIIHBACBEIIILMNOOOOOPOPPONIIHEAwtoillidcc93/~',>,,;;>>)/||<<3clkfgiif95cimoicddioptwtmfcfmppqooqqqold3|9fmppppmqmg9;;=&&$", +"#%=,)]<35cfffilnoonmnrsrrspppmmkkggggggghghkhkrrqtuutwwvvvvvvvvrrrmmmmeedd88666666666666aafiifhgehmmtwvvvzzCHIIHECEEIIFMNOOPPPPPPPQQOMIIIIEBAtooppliifd3<{'>,,,;--->)<1||5fliilol9459gmolmklmquxwulggippuqomqqoom91|0imqpppupof7|~~!)!]{][:}652641_(]]'>,>;==%$#", +"#%=;,]/|29cijlloonnqqqqnqnnojmmmmmkkgggkkjkjkhrrrusuwywvvvuvvvqrrrmmmmeedd886666666}}}}68bfihebddejmmsvvvyzCGHHFFFFFFKMNOOPQQQQQQPOOKEAzAAwttpiiloolilof5<~',,)''-*--)/|359fiiotpi9339fmppppommtwxtidfkoqqqmmmmomm0|40gmquttupi97|//~!!]]]:}473a71|:]]''>--=%%$#", +"#%=->!~_170dijlororoqrrnmjjjgkkmmommmmmlmnmmmkrqrrptwyywxvuvvurrrrmmmeeedd886666666}}}}28biih8b8dgjmmrprvAACGCHFFFFFKMNNOOQQQQQPPOMKEzAwuppligf9cfiiilptl9|/),)))'-**>)/|55cfiotwpf5459iptutqplqxwwqgdgmqqpmmmmlmmk5159imptuupmg77|<(({{{[_[}26672}:({]'>-*=%$$#", +"#%=;,!~::479hfioprrrpqqnnjhhhggkkmmqpppoomqqmrrrrrpvxwwvvwvvvrrrrkmmmeeeddb8666666}}}22268iiba68bggjmmrptzCCCzAFFIIKNNNNOPQQQQPONNMIHEAwtpoifiid9cgiilptpi9|(~~~/{,;;->)/|5cfikpxwofc09cmtttqqolqwwui9dfopppmmmkkmmc||5cgoqputqic5311<_((_:[1a5a731<]{{''>-*&$#@", +"@$=;>!]_<435dbgilnnrprrnjjihhggggklmpppqpqpprrpqrrsuvwtvvvvvrrrrqmmmmeeeddbb666666}}}2226bccc8666bggemmstwyBAzzEFKMNNNOOOPPPPPOONNNKIHBAxwtoooooliiopoppplc5||//<>-*&#@", +"$%==>'{/:4750cbginnnmnnniijggggggkkkklmqqutttrqprruvwutvvvvvrrrqmmmnmeeeddbbb666662}}226acc9666668egehmnwwyzyyzBFMMNNOOOOPPOOPPPOOONNMMKIHEEAywwwttttwtppof053|||33|{'')~/_3cillotutpommmuwtqptpqtxxumd9ckmpqqmligki91|7ddgkoppoi97733377742}2677a311_{!'>--*%$#", +"$%=>>'~~_4790bbgginnihnnjihhggggggggggkmmptttprprpsvvsvvvuvrrrrrmmmmmeeeddbbb6666622}22aacc862}6a8hbdemqquwwvyzCIMMMNOPOPOOPQQQQQQPPOONMMKMKIHHEEAwtwyxtppl0533|3553|////(<<3flloptwwtpquwzxppuuttxwxqf90dkpqqmmkgggd7<|0dgglmolic077|335066aa65723|1<({)'>-*%$#", +"$==>,')]_1359dddfhjjkhjhhjgggkgggggggggkmqqtttttprxuvvvvvvrrqrrmmmmmeedddb888a6222}2}}}26cc662}2688bdgjquuwtsyCGIKMNOOOOOOPPQRQQQQQPOONMKIKKIIIIIIEAABAywwtl53||3|33|<<<||''{/_1457bhbggijikhjejdfgkgggggkkkgkkmpprtstswvvvuvvvrrrrqqmmmmeeggbb888222}}}[[[[}26bc62}[22866bgjnuuqstzBJHKNOOONOPPPQQQQQQQQQPOONKIIIIIIIKIIIHHHEAAAyo9333<;;=%&", +"&*--']~(_1375abcfikjhhejefddgggggkkmkkkkkrrnrrrwwwvwxvvvrrrrrrkkkmeeddb88aa2}}}}}}_____16b96}}}}22666bkoouqmsyEEHKNOOOOPPPPQQQQQPQQQQOONMKIIIHKMKKKKKKKIHEEEAtig9|/{~<|353>==&&", +"%*-;,)](<1357acdgfinhjhjgfddddggggkkkkkkkmooopstxwxyywxrrrrqqmkkkeeddb888222}}___(((((([79562[[}2226aekmooqquABEIKOOOOPPPPPPQQQQPPQQPOONKIHEEEHIKMKMMKKMKIIIIEypi5-*&$", +"$%->,)(/1|350ddcgfinjjnnfgddddddddggkkkkoonnnssvvwvyywtttpprmmmmeedbb88a2222__(({^^^!^^(|774_[[}}2}28bimonqquAAEIMNNOPPPPOPQQQQQPPPPPONKIIEBAAAAEIIIIIKKMKKKKIEApg5|/~{_|7974|<19gltyAyplltEEEHHHGEzyxywqc3379mqqqmmg05731147dcgfcc03790d05a7888ab07241_{~,;;*%$", +"&&->,{(_11550cbbgfgjhnnqiigddddd0ddggkkooonovsvvuvvvttutttsmmmmmeeddb6622}}___^^^^^^^^^[}32|(_[}}}}26bflmniuwxAEKKMNOPPOOPQQQQQQQPPPOOMMIEAzwtppwwwtyEHIKKKKKMKHBpic3({!(<7907770diowBBwoipyHIIHHHHEzzyxum0445cmqqqmkd033113500diiic5750d998008a8aa722*&&", +"%=-'']{_|450acbggghjhjlmllgggddd0dddggmonmnrvsssttvsussttqmmmmmghggb882}}}_((^^^''''''!]12}:{{_:}}}26bfimklpxwBIKKKOOOOOPQQQQQQPPPPONMKIHEAwwttpplikipwEHIKKKMMKIEwoc|(!!{_7999ccfiipAAypootBIIHHHHECAyzwug7345gqqqqmk0744|43570diif97570dcdcdc8bac0522_({!'>-*%", +"%=;'!{{_<159abcggiijhhfiiilggdddddddgiljnlqvrsstusrsspummqmqqmmjegbb886}}_(^^]!!''','''{<||]^!(::_[269eeikmpwxBIKKMNNNOPQQQQPQPPPPPOOMIIEBEyywwtpogc9flpwEIIIKKMMIEwl93/{)~<59cfilllowAwpoopwEIIIJHGEBAAAxqd3439mqqpqmg74414409779cfcc090dhcfegbb0a857}}({{'';*%", +"==;'!{{_<1789cfggggjhhggfiigggddddddikiljnrqrsvvrrrusmmmmmmmqqmjggb88622_(^^{'','''''''{_|_{]^^(:__26c9fimqtpzEIHKMMMNOPQQQPPPPPPPPOONKIIHEAzywppolf09ccflyEIIKKKKHApi93<{{/<39ciopptyAAtollpwEHIHHEEAAAzAum0775cmqqqqld741347007359dgddddd9figgbbb8a53}:({!';;=", +";;''!{(_12a8a9ggiijjhgggfggigggdddgiilkinmmqvvsrrqrmmmmmmmmmmmjjggb88621_^^{!''';>;;>;'!<_/]'^^((__<69cfciqptBHIIKKIMNOPQPPPPPPPQPPPONMHHEAyxwttpllfd99999iwBHIKKIIEwplf92:::269ciptwAABypiiopwEHHHHECAAzAzumc075iqqqqpkc743479093379fffidbdhejkjhhbaa7|[[{]'';;", +";;'!{(__22669dgggfjhhgggggffddddggkkmlnmnmmrrrnrqrmmmmmmmmmmmmjjgea8622_(^^!'';;--;;--,)<<('''^]({(1688chnqqwBHEIKIIMOPPPPPPPPPQQPPONKFCCAuwttppollicdccdcfmtyEHIIIEAtpoic5}:}268clpwyABAukfiopwEEHJJECzAzAzukd57dmqqqqqm0333570d07359fgighgbejkkjehbaa74[[(!';;", +";''{([[}2260cdfggjjhjgggffgfgfhhhiilloqnnnrrvnnokkmmmqmqmmmmmmjkkebba21_^]!!'''--===*;>)/,]<~';'){{!{[3389cnnqAEHHIHHMNONNOPPPPPQQQOOONLFCzvsmjghbffccfffffilloptwyHIKIHBAyytof05770dfluyABApkgiptwyAEHIHCAzzAzwoddddkoqqqumgd90070dc0570dcimmkjjjjkmnjha884}[^^^!", +"!^^^:<13779cdgiheeehhggggffdhheijjjnrrqrvrrrnnhhkkmejnrprppqppqqmkidaa4[:{''';;--=&&&=;,/<~>;''!^^^_|388fllpAEEIEEIMOONMOPPPPPQQQPOOOLIFzvsmedgbab989cfiifiilptwwAEKMKIEBAAwoi9550dfimwAEEyqiiotwAAAEHIHEAyAAwtlcddgmppquumkcd999dggd00dggomnmjjjkmmjjjb864<_^^!", +"{((_|17790cfhhghheeheeehjjeheeheihjnonmrqppnnhkkkejjorpspppppppqoikfb05}_/!,>;--==%%%%;'{<{>;''!!^^:<158cfltBEHIGEKNNMMMNOPPPQPQQPPOOLHEzvsmmedb886868cfffiiilptwyAHKMMKHEAwtplfbbcffiqwBHEytppptyAAAEHHHBAAzzwuifgilqqquuupigd9dddgggddhhomqpnknkmmmljeb8621(({", +"(__14479acefffhhfeehhhehhheehhehjjnnnmmqrrorkhkhhhjnqqqqppprpppmokjgcd06|<~!,--=%%%%$%*>{/);-;,''^^[:159cfltBEEHBHMNMIKMNNOPQPPQQPPONLHFzvssmed8a662a689bccfiilptyABIKMNMIBywwtpibdfiiipyEKEAwpppwAAzAEHHGBAAAzwuiiilopuuuuupkcddcdgggggjkmmmqnnnnmmmmnjea662__(", +"[}2266a8cbffffhhhehhghehehehhhhjhjnnnmmnqnnhmmmjjknmqqmmmmpprppmmijcc0763|<~,>=*%%%&&%*>)()-->'''!^[[:40cciwBEEECINNKHIKNNOOPPPQQPPPNLLFzzvsmeeda666268b988fiiilpwyAEKMMMKHByyywplfffiiowAEIHBwpopyAAyAEEHGAAAACytolmmpuxtxxtuidddgggggjjloomnqnnnmmmmmjefa622}[", +"[}22a6abcfffffhhheehhghhhehhehjjjhmnqnnnjnkhkjjkmmooollllmmnnlnmifea90221||<~'>*%&&&&&&-)~'-=-''''{:::40c9iyEEByBIMMHGIKMMOOPPPQQPPPNMLHCzvsmmedbb66886a9668fppptwyAEIMMNNMIEAAytplifiilowAEHHBwttyAAyyAEEHBAAACBzwqlmqxxxwxxxpkgggiggkkgilljmmloommmnmmjhbba6}[", +"}226a89bhffhffheeeehhhheeehhhjjjjnnrrmmmlnhheegklpolijhhjjkkknnkhhh8a3}1___(/{,>*&&&&&&-)~'-=;''''{_:1250clABEAwEKKKEGIKKLOOPPQQRQPPOMLFFzvsmmeddb6668abbbadiptwwyAABHKMMNNMIEAwtpoiiiijiptyEHHEAyAAAyyyAEHECAyABBAyuqquxzyxxzxumkkkijkkkjjjkkmjnommmmmmmhbbba2}", +"688bbhfjieffhffeeehhhhheeehehjjjjhmmmnrlnhhbhdbiiolliieeehhkkkjkeb666|[_(({{~{~,>-&$$&&;)~!=*-'''){(_}250coyAAzyHKIIEGFFKMOOPPQQRQQPONLIFzvssmeedbb6666a88bciopwyAAABEKNNNNNNKBytpillllifipwAEEEEEBAAywwyAEHHAAzABCAxpmpxAAzAzzxxqmmkjjkkkjjjhmmnnpmmnmmmmhha886", +"688bbbejiffefhheeejhhhhhhhheehhjjmmqmrnnghhbdbbhiiffc9ahbbbeegggeb6661[{{!)!)!)),'-%$$&;)~);*=-;''{/(}437cpyAAwAIIIIEGGIILNOOPQRRQQPONLIEzvssmmhddbbb666889jloopwyyAABIMNNNNONKEypoiopoiffipwyABEHEEAwtwwABGIHAAAzCCzwuquyzACzAzzxuqnmmllljnhhkmhnrmmmmmmmkkeb86", +"8bbehhfhifhehfehehhfhhhhhehhhhhhhmqqmmnnhhba88bebcbd8aaa8bbbeghgebb62_[{!'''>,,,',>-*&%-'~);*=>''')//_227cpwywwBKIEHEGGFILNOOPQRRQQPONLHFzvvsmmeeddb88bbbbhimmmmqttyAABHMNNNOONKEypplptoiffotwAAAABBAwttwABEIIGBAAAzzzxtwwyACAzzzAyuqpqoonkjkkhmjnnmmmmmmmkkggb8", +"dgggechfjihfhgeehehhhhhheehhjhhmmrqmnjjhhba888bc9098aa66aa8bbhkgebb62_^{!',>;--->>,,-**;'~);-;;'''!((<227ftwtttBKHEEEGEIILNOOPQRRQQPONKIFzzvummhjgdddbbbbhgkmmkjnpptwyyyEMNNNOONMEytppttpigjowyyyyAAywtptyBEEIIHEBBAAAzAyyAABAAAzzzzxtppppmmnmmqqnnnmmmmmmkkjggd", +"dgggejeehihfhhheeehehhhhhhhjhhmmnmqnnjhgba8aa8aa8aa4316666a8cbekhba62[^{!'';;**==;>>>>->,~)>-;>'''!~/<126fpwttwEIEEEEGHIIMNOOPQRRQQPOOLIFBCAwwqqjjgggdddddgknnijjqptwwwuwBKMNNOONKHBwwwwwoifotwwwwwwwttttwABEEIKIEEBAAAAAzBBBCCzzzAAAytppmqqqqqqqnnnmmmmmmkkjjje", +"ehggejeejhhhfeheeeghhhhehhhhhhmmmmmnjjgb0a68a8a86531_111266aabbheba62}^{!'>;-=%%&%*->>,'~/~'-->'''!{(<<26ittppwEHEEHEGGFILNOOPQRRQQPOOMKKHCByyuuornkkgggddfjnjmmmqpttwwwuxAHKMNNONMIEBABAwolmptAAAwttpttttyAEEHKKIHEBBBAAACCEGGEECAAAAwttpqpqqononnnonmmmkkkjjje", +"ehggejhehihhfefhehhhhhhhhhhhhjmmmmmnjhgb086266873}[[:[__112aa8bhebb861^^!'>;-=*&&&%%=>,)/,''!{((|39ittptwHHEEHECEFIMNOOPQRRQQQPONMKECAwyuuuppprmmnjjhjqqnmmqupwwwywtuABIKMNONMKIHEBAtolnpyAAwwtppttptyBBEHKKIHEEEBAAABEEHIIEECBAywuuptuprprnnnrmmmmkknjjje", +"dggghhbhehieffehehehhhhhhhhhjhkhhnnljhba8662aa53}:[]^^^^__12aa8bbhbaa1_^{!';-=*%&&$$%=;)(||)>;>'''!{(/|39iptppAIEAyBEGIFILNOOPQRRRQQPONKFCzzwwuuqnnnnnooonqqqqmmmmqppttwAwutyAEIMNNNMKKIEBAtoopyABAwtpooppptyABEHIIIEEEBAAAAEHIIKIHEEAAAxutuptttpprnrnmmmkknjjje", +"dgbebbbhhehheheechhhhhhhhhhhkhkhhjnjhhba6622634}[:^]^^^^^(_12288bhba64_[{!'>-=*%&&&$$%*'~|3(,>>'''!{{(<39lppppAIEwxAEGIIILOOOPQRRRQQPOLIFCzyzwyqqqjjjjnnouuquqtmmmqloppwxAyttwABHMNNMIHHEEByppptAAAywtpooppptwAEEHIIGEBAyAABEHIKKIIHEBEBywwttttttuqmmmmmmmknjjgd", +"8b88bbbhaabbbbcbbhhhdhhhhhhhhhhjjhjjhba8662244}[[{!]!]{^^^(_1228bbbaa41[{!';-=*%&$&##$&=,<3<~,,'''){((<49lppopAHAwxAEGIIILOOOPQRRRQQOOLIFFzyAyyqqmmmmmmmqquuyywqmmqnlotwwyywttwABIKMMIBABEEBwpoptyABAytpnoppptwBHHIIIEBAyyAEEHIKIIIIIEEAAAAwtttutuqqpqqmmmkkgggd", +"668aa888aaa8bbbbbdddddddddddgghkjkjggb8662224}[[]]!!!!!!{^^(_122abba64|[{!'>-=%%$&&###&&>~|_/))!''!~((<39lpploAEAtxABGIIIMOOOPQRRRQPOOLLFFzzzwwqrnmmmmmmmmqtwyyuqqqqnpwyxyAyvtwABBEIKKHAAAAEAwpoppyABAytppoppptAEIIIKIHCAyyBEIIIKIIIIHHEECAywttutuqquupqqmmkkbb8", +"66a6aaaaaa880999dc9000aa0dddggggghhh8a862}221[[({,,',,'!!{]^__222ab8631:{!'>-=%%$&&###$%*)/~/~{/(~'){(_|5coppooAAwtxyCCEIKMNOPQRRQQPPOOLMKKIIEEBBAuxxupqmtpppwuwwuttwywyyAAAAAAywwAEEHKKIAwtwyywpomotABEAwppppttwyEIKMMMMIHEAABEEEEHIKKKIIHEBAzwtttppqljjjiiihba8", +"6222264434244226aaaaaaaaaaaaaaabddda066}}2}:::(]'''>;''','!^^(_}22aa6|1:{!',>-*%%$&###$&&>){)'~(/{~~(_|5coppooAywtxyCCCIKMNOPQRRQQPPOOONMMKIEEAAAAzywuwttpqwvwttquwyABywyyyAABAwwyEEEIKKIytptttppoopxAAAAtpmpptwAABHKMNNMKIEBABEBGHHHIHIHEEEEBAyvwpponijjiffefb6", +"6626|14111}}}}222644477770aaaaab800a722}2}_[_<]!'>>>;;>''''!^^(_}26a24_[{!',>=*%&&$####$&-){)',{/((((/|5copplpwwptxuyABFKMOOPQQQQQQQQOPOMMLHHEEAAABBAAyywtxwvxptmqtyBEAwuttwAEEBwwBEHHIKKHytppopppopuwAAAytpoptwyyABHKMOONMKIEBBEEHHEEEEEEBBEEEBAywtppllijgeb888", +"26434||::[}}}1|11111444377770008aa67a2}[}[[[:({'';;;;;;;;','^^^[}}2221:[{]!'--*%&&$$###$&=,)'->){{(___|3coppopttpsxuyABFIMOPQQQQQQQQPPPONNMKKIIIEEEEBAAyyAAywwqttmqwAEEypolptwEEBAAEHHIKKKHAtppopporpuwzAAypprtwwwyAEHKMNOONMIHEEEHEBBAABAAABBEEEBAwwtpniec86622", +"2|3||}}}}____<|:_1111}42277700067a622}}[_[:_:(!''-;;=-;;;;''!]^(_}2221_[{{''-=*%&&$$$##$&=>),>>''!(_11|39oppoptpoqxuyzzFIMOPQQQQQQQPPPPOPOOOOOONMKKIHEBEBBACywpttmmuzEEyplfilpwBHEBBEIIKMMMIBwtptrpopqtwABzwsqppwwwyAEHKNOOONMMKHEEEBAzAAyyAAAABEEBBAtpoljca662}", +"_((:[}21<:<((_______11144777776777a2}}[[[^[([{!,---===-;;;;''^^^[}2}21^[{!''-=*&%&$$$$#$$%>),>;>''!_34350ltppoppoqxuyzzFIMNPQRRRRRQQQPQPQQQQQQPPPOOONNKIEEBCAAytttqqwBBAtofcffowEHHEEHKKMNNMKEywttppputwAEEAyuqutwtwyEEIMNOOONNNKHEEEEAAAyyxywyyAEEEAywtolfc862<", +"_(^^[_<|<<___(((__::[1}1227777767342}[[[^][(({'>;;===**=;;;''^^^__}}}_^{!!,;>;*%&$$$$$$#&%-,)>;>'''{1459dotpppppppxuyAzFKNOQQRRRRRRQQQQQQQQQQPPPOOOPPOOMKIECCAAwwwwtwAAAwpjiccfltBHHBEIKMMNNNKEAwwtptuwwCEEBAwtuutwtwAEKMNOOOONMKKIHHHEEBAAwxwttwAAAAAywtpoib531", +"::^(]{{/___<<__///____<1}}244734733}}[[(^^((^{'>-=====*=;;;;''^^][}}}[^{!'';;**&%$$$$$$#&%-,),;;'''!_|59iptpppttpuxuyAzFKNOQQRRRRRRRRRRRRQQPONMMKMMNNNNOONKHEAABAAAyyBAAwtpoifffltAEEAEIKMNNNMIBywtptwwwABEHHEzwvwyywyEKMNOOOONMMKKKIIHEHEEAAwtttwtwwwyyywtpic53", +"|}_/(~{{{{(/<<<<((((__<:1}}24421144}1[^(^^]{]!,;===%=====;;;''^^{_}}}_^!!''>;**%%$$$####&&*,{);>,''!(_|9ipwtpptttttuyAzFKOOQQQQRRRRRRSSRQQONMIGGGEHIIIKMNONMIEEEBBBAAEBAwtptpliffltAEBBEKMNNNMKEAwwtstwwyACEHHEAyAABBBBIKMMNNOONNMMMMKIIIIIHEBAwwtppppttwywtpic5", +"95|<_((~~)~~((_<<<(/<_<<<:111|}1}12|:[[{^^{({!';==*%%==*=;;;;'!^{[}}__^!''>-=**&%$$######&=>~)>>'''!{<|5ipywppttswtuyAzHFOOQQPQQRRRRSRRQQPNKIHBCCCCGGGHIKNOOMKHEEEEEBEEAtppttpoifiipAEEBEKNNNNKHAwywwwttxAEHIKHEEBEEEHEIMNNNNNOONNNNNNKKKKKMKKHEBytpooooptttpoif", +"lf933|__~~~~~~/))>>''''~/<3coyytptttwwuwzzFKOOPPPPQRRSSRRQPPONMKFFBCCCCCCGGIKNNNNMKIIIIHHHEAtptwwwplifipAEBBEKNNNMIBwyyyzutuyABEIIHHHEEEHIIMNONNNNOONONNONNNMNNONNMKIBytollilopppoo", +"plif953|<<<'!^{[[[^^!',;-=%&&$$$######&&-)),;;''')(<|9lwAwtwwwywxyAzFLOOPPPPQQRSRRQQPOOOMMKKHEGGGGGGEHKKMMNOONNMKKIIIEwpwAEEAwoiiltBEEEIKMNNKEAAwAAwtuyyEEHHIHHEEEHHIMNOOONNNNNNNNNOOOOOOOONONNMHBwpiffiilopp", +"iillifc53||'!!^[[^^{''>;-*%&&$$########&*,));>'''!(/19ftyywAywywxyACIKMOPOOOPQRRRQQPOOOOONNMMKIKIIIHHIILKKMOPPPOMKIIIIBwyBHEBAwpllpyEHHHIKMNMKEAyyyxtwyABEEEHHEEEHEHIMNOONNNNMMMMMMNNOQQPONMMNONKIBwoic9cffii", +"59ciiiic953|/~)))))~{/<<<<<_<__](:::]]!!!!(_:{';**%%%%%&%==;;>'!!^{^^^''>;-=*%&$$#########&&>))'>'''!((|6cpwwwBAAAwxyACFKMONNNOPQRRQQPOOOOOOOOOOOOONNMKKIKIIKKNOPQPOMIEIMIBBEEBBEBAtppyEIKIIKMNNNKEAAAyyzAABEBEEEEEEEHIKKMNNNNNNMMMMMKMKNOPQPNMKKMMKKHBtlf633333", +"(<|59fffc953<~))!!!!!!{((<|<<(_(:::(]^!'!'{(:~'--**%%%%&&%=;;>'!!^^^^^'';;-=%&%$########$#$&-)~'>,''!(_}29ottwABBByxyCGFKNONNOPQRRRQPPOOPPPQQQQQQQQPPOONMKKKKMMMNPPPOKIIMMHEEEEIKIHBwtyEIMMKIKNOONMEBAyyAAyACCCBEEEEGEHIKMMNNMMMNNNNMKKKIMNOOONMKIIKKIEAtlc6}/~~", +"')~/|599c9953!!{^{^^'';=*=%&&$#########$&&*)),;'',!//}29ltttyBHHAxyCGKKNONMOPQRRQQPOOOPQQRRQQQQQQQQPOOONNMMMMKKNOPOMIHIIHEEEHIKIIIEBBBHMMMIIMOPPONHBAyABABACzzEEEEEHEHKMMMMNMNOOOONNKKIKKMNNNONMKKIHEBAwof9<~)", +"',,))/|3599995|!!{^!!!';-=*%%&$$#########$&&*,))>''')~_}29lttpwBIIByACHKLNNNOOPQQQQOOOPQQQRRRQQQQQQQQQPPOPOOONNMKKMNNOMHEHHEEEEHEBEHIIIEHKNNMIKNOQQPNHBABEEHEEBCBEEEEHHIKMMNNNNNPPPPOOMMKIKIIIKNNNNMIEAAABAti9<{", +"/~))!)~(<|59cc953|;;*&%$&$##########$$%*>))'>''){_}29ltwtwAEHBAAEGKKNNNOOOPQQONNNOQQRRQQQQQQQQQQQQQPPPPPOONMKIIKMMKHEHHEHHEAwwAHKMKKKNOOMKMOPPPONIEHHIIKIIHEEEEHIIKMNOOOOPPPPPPPOONNMMKEEEIIIMMKIBwwABByo9|", +"5|/~~~!)~/|59ccc93|''!!!!!!';;=*&%$$#####@##@@@$$&%>)~'>'')![:}5iwwtwyEEBABEJKLMNNNNNOPPNKKMOPQQQQQQQQPPPQQQPQQQQQPPOONKHEHHIMKIHEEHIHBwwAEKNNOOOOONKKMOPPPPOKKIKMNMKKIIHEHHIKMOOPPPPPPPPPPPPOOONMIEBAAAEEIKIAtptAAwpf", +"l9|/~~!)))~<39ccc953|'']]!!!!';;=*&$$##@####@#@##@#&&-,~)'''!{::}0itywwwBBAzAEIKKKNNMKLNONKKKNOPQQQQQQQQPPOOOOOOOPQQPPOONKHBBABIKKIHHHIIIEBBEKMNOOOOONMIINOPQQQPOKKNNONNMKKIIIIKNOOOOOOOONONOPPPOONMKHBywtwAAEEAwppptwyw", +"wo9|/~)),,,)~<39ccc995|->,~<|59ccc53|-**%%%%&%%=;;;'!!]^!'';-*&%$$#@###@@@@@@@@#$&%>~{)'''!]::4dpwwwwBEAzAEHKIIKKHEIMNKECGINPOOPQQPPPPPNNMMNNOOOOOOOONMKEBBBEEIKMMKKMNMKBAAEIMNMMKKKIEEHMNOOPPPPPQQQQQQPPOONNNNNNNNNNNNNNMMNNNNNNNNKIEAwttppptyAAwpll", +"ciolc3<~),,-;=-,)/|5999953|<<<<(]~]]/_/^''''!)'>---***&%%===;;''!!!',;;-*=*&%$###@@+@@@@#@#$$%;)~~'''!^[:39ltwwwBHBAyBGIHIKIEEIMNKHEHMNPOOPQQPOONOOOMMMNNOOOOOONNNMKHHEHIIKMNMMKKIEwpptAEIKMKKKKKEBHKNOOOOPPPQQQRRRQQPOONNNNNMNNNNNNNMMMMMNNMMMKHEBwtolootwBEApf", +"iilifc9|~)',-==;-,)<3599953|<<<_/~]{]//]!)!!)]'-*********=*;;;,',!'';;;=*&%&$$####@@@@#####$$%='~~!'']^^|39ipwwwBHEAACGGGHKIEEEKMIEIKNOOOOPQPONMMNOONNNNNOOOOOOOONNNKKIIKMMMNNMIEAwpliotwAHKKKKKMKEEIMOOOOOPPPPQQQRRQQPPOONNONNNNNNMNNMKMMMKMKKKIHEBAwpooptAHIEt", +"HApf9cc9|(~)>-**=*>,~<3599971|<<)/{!!!^]|39ipwywAHHBACCCAEKIBAEIMKIHINOOOOPPONMMMMNNNNNNNOOOPPOOOOOOONMMMMMMMMMIEytpliklopwEIIIIKKKKKNOOPOOOOOOPPPPQQQQQQPPPOONONNNNNONMKKKKIKIKIIIHEEAAwptyEKMK", +"POEl539c93;==**->)~|359953||<]]]](/!!'!)~~)'-*%%%%&*=;;;;'!]!'';;=*%$$###@@@@+@@@##$$$%%&**;~--****->)/|559553|//]](/{!'',)~),-**%%&%&%*=;''!]]'',;-*%&###@+++++++++@###%&%**;)<<_/([:|79fowAyAEHEBBBAwAEHzAEKNKEABKMNMIKIIIKMKMMMMMMNNNNOPPPONNNNONONMMKKEEIKMKHwploollopwEHHHHHHIKMNOOONNNNOOONNNNNNOOOOPPQQQPPPOPOOONMKIHEHEEEHHIIIIIHHEEBI", +"EKONEpf5|3599|~,>-****->,~<359905|<]{(/]!'''))!'-**%%&&%===-;',!'''';-=*&$#@@++++++++++@##$$%%*;,(<_//::179flwBAAEIHEAAyyAEBAAGMOMEABHNNIHEGGHEHKKKKMKKMNNOOOOPONNNNOOONMMKIEBEIKMKEwpttppootAEHIIIHHHIKKKMMKMMNNONNMMNNNNOOOPQQQQQQPQPPOONNMKKHEEBEEEHHHHHEEAAA", +"yBKNNHwi5||5cc5<),>----->,)<|599933<(//]{''')!)'>*%%&&**==;;>'''''>;;-=&%$$#@@@++++++++@@@##$%%=-)<_(~:[_|5cipwAABHIBBAyyxzzyzAINKAwAEKKHAzCBGCCEIKMKMKMMNNOOOOONNNNNNNNMKIHEBBEIKMKEywwwwtppwAIIIIHEEEEEEEHEEEIKMMMNNONOOOPPPPPPQQQQQQQQQQPONMIIEEBBEEBEAAAAywy", +"ABEHKMHwi5<|3cfc3/),>>>>>>,~<|599993<',)),>-=*&&%%==;;;','';;;=*%&$#$#@@#@@@++@+@#@@##$%%=-,/_({]^_|38cltyyzEIBxuuuuyzrrwEKIAwwAIIEAzABCzzCHIKMNNMMNOOOOOONNNNMMMNMKIHHEEBEIKMKBywwywtttwEIKIHBAAAAAAAAABBEIKKMNNOOOOPPPPQPQQQQQQQRRRRQPONKKIHEEEBBAABAywy", +"IKIEEKNKAo9|<|9ff5<~,,>>>>,)~/|599953||<],'>>,),,>--***%*==;-''';;;;=%$$###@+@@+++@@@###$#&&%%==-,{_>>>,,)(|3599555|:),';',,,>>>;>---;;>;'''>;;=%&$$##@@++++++@@@@###$%==-->>)/11_::_1379fpyyAzEBtpruuttqmuAEHByyAHHBAAAyCEEGHIKMNOPPPOOOOOOOOOOMKIIIKKKKIIKKKKMNNKEwppttoptyEIIIEAywyyAABBEBBBEHKMNOOPQQQQQQQQRRRRRRRSSSSRQQQQQOOOOPOOPQPPO", +"QQOHAEOPPOKAti99fopi9|/~)),,!!~<|3555953|~,,>,,,>--->>>,;>>>'','>-==%&$$##@@++++@@@+++@###$&&*;>')(|33}::|35cfoyyAAAAtpprpttqqpyEEByAEHIAyxAAAHEEGGHKMNOPQPPOOOPPPPONMKHHIIKKKMMMKKKMMMIypoopoolotBEHHEAwtwwAAABBBEBEIKMNOOPPQPPPQQRRRRRRSSSSSRRRRRRQQQQQQQQQRRQ", +"QPOIBEIOPPOKBwl9cflppi9|,,,>****->,,,,,'!!,;;;=%$$#@#@++++@##@+@++@##$&%*;-;,{<|72[[||59clwAAzAzwqqmpqtpnpwABAwyEIIAxuyABEBEEHIKKMNPQQQQPPPPPPOOONIIEEIIKKMKKKIIKKKEtllloliiotABEEBwtptwyyAABEHHHIIKMNOOOPPPQQRRRRRRSSSSSSSRRRRRRRRQRRRRRRQ", +"QQQOMHHIOQQOHAti999iptoc5|<<<<||||33599995|/)))),>****->,,,){]]!'>;=&$$##@+++++@#@@+++@###%*->',,)/_3952}|159cityAAAywrqqqutpootyBAwwBKKEwxwzEEEEIIIHKMNOOPQQQQQQPPPPONKHAyABHIIIIIIHHIKIApolooolopwABEBAtpptwwwwyEKKIIKKMNNOOOOPQQQQQRRRSSSSSSSSRRRRRRRRRSSSSSR", +"RRRQQPNNOQQQMBwti955fotof5|<<<<||<|||355c95|>-;;;'',))]]{),;-*%$###@++++++++++++##$%-,~)){/|35fc94335bcipyAAAytppppwwtrotyBEAyAIMIBwAzAyEEEEECEIKMOPPPQQQQPPOOONKEAwtwyAEHIKKIHHIKIAtoopoooptyBEBAywttttttwAHIKKMMNNNNNNOOOPQQQQQRRRSSSSSSSSRSSRRSSSSSSSS", +"SRRQQQQQQQRQOHAAwof99fptpi93<<<<|<<<<1||555||<>>>'')!{{]))),>>-=$##@++++......+++@$&=>!)~/<|35ff953799fiowABBAwtpppwytpptyABAwyBIIByAAyzAEAyAABEIKNNOOPQQQPPPOOMKEBytttwyBIIKKIIIIIHAtpooooopwBEEBAwtttppopwyBEIKMNNNNMMMMNOOOOPPQQQRRSSSSSSSSSSSSSSSSSSS", +"SRQPOQQQQQQONEwAEyof99fpwwof53||11<,>'',){]])'',,'>-*=*%###@++....++++#$&*->,)/(_|5cc52459fiopyAAywtppptwwppptyBAwwAEEAAywyAzyywAACzEFKMOOPQQQQPPPPNMHBAwwwwwwBHIKKIIIIHEAtpooollpwAEEByttpolloptyABEIKMMMMMMMMNNNNNNOPPQQQQQRRRRRRRSSSSSSSSS", +"RQPOKMNPQPOIyoipBBti933cowwpf95|33||<(/~/<|||<<<;',,)!{]),',>--;*=**%%%$##@@+++@@+#$$$&*;;,'!/|7952|70filpwBBAAwpoptwwtoptwBAwwABEBzyyyBAwuyyzyzAEKMMOPQQQQQQPPNKIBBAwtppptAEHIKIHHHEBypoopoilptABBAwpolffilptwyAABHIIKKKKMMMNMMMMNOOPPPPQPPPPPQRRRSRRRRR", +"PPPOMKKMNNKAoc9iyHyi5<<|5fpplc53333|<(~))~/<<<<|||/),',''''',){)''>--*=%%%%$%%%%$$########$$%&*=;;''!{122}:457filtABBBAtolowwoopptyAwtyABBAxzBEAzxwywyzzFKMNOPQQQQPPPOMIHAAywpoiilptBHIHHEEEBAtppttoiiopwAAytpliffilptwyyABEHIIIIMNNMNNMMNNOOOOOPOOOOOOPPQQQQQQQ", +"QQPONMMMNNMIAoioAIAi9|/~/|9ili933||<<~)>;'))~~/<|||/)),,,'',,,,'',>-*&%%$####$$$$$$$$%$$%%&***---;'!!!{13}[_1|85cipwAywpiijopollopwAwttyBEBAzAEAwxxuwwzBEKMNOOPPQQPPPOMIHAAwupokiilptAEHHEEEEBAwtwwtoiiloptwwtplifdgioptwyBEEHHIIMMNNNNOOOOOOOOOOOOOONNNNOOOPPQQ", +"RQQPOMKMNNNNNHAwAAti93/~~~<9iiic53|>,)~/<;*&$$$##@@@@@@@@#$$$$*=*->->,''!!{){<43:^_1|439iptppifccgiifiiopwwtptyABwtwzywtwuqwAAEKKNMOOPPPPPPONMIEAyutpolllootAHHHHHHEEBAAAytpliiilptttplifdfilotwABEEEHIKMMNOPPQPPOOOOOOOOONONMMMMKNOPQ", +"PQQQOMIKMKIKNNHApof993**%**=->)////)),>;;;;>>';;>-*&%$##@+@@@++++@@@##$%*->>,)~{//~(/<|52:<<__|29looli9589cfccfilpwpootyAtppwxptpuqwxABEIKMOOPPQPPPOOMKICAywtqpppppptBIKIIIIIIHEBAwtpoiiilptwtpolifiilmpwABEEHIKKKMNPQQQQPPPPPOONMMMMMMMNMKKMO", +"MNOPPONMMHBBEHEypf953|||/~))/5iolc5|/~)>**%%*&*->)///~),>>-;;;>>;;--*&&$###@+++++++++++##$$%*->,'{{////||5832}:}269ioolic977cc99cfiottllpwAtlltpqqpoqqwAyzEIKMNOOPPPOONMKKEBywttqpppoppwEIIHEHIIIIEAwwwtplilotwAAywwtppoopwyBEHHIHKKKMOQQQQPQQQQQPONMMMKMNNNNKIK", +"MMMNOOOOOKEAyyAwtof5|<<|3<),~<9lpi9|-*%%*&%*-,~//~~),,>>;;;>;;*=%%&$##@+++++++++++@###$&&*-;''''!!~~_|593321359fptpoic90dcfcfiiowwpoopAwpopplmmlqqwuxzBFKKMNOPOOOONKKKHEyttpppooolotwBEEBBEEHHEBwtttpoiilowAEEEEAAyyyyABEHIIKKIIKKNPRQQPPQRRRRQQONMKKMMNNMMM", +"NNMKKKNOOONKEAwtttpi93|353/))/3cilf5|<~,-=*%%&%&*-,~///~)),,>;;;;;-*%%%$##@@+++++.++++@@##$&*=-;'';''''')/|3|<<<<|39ipppoic9cfifillpwAwpotwywtpolikinuuwxzAEIKNNOOOOOONKKIEBytuoolololooptwBBAABBBAAwpllllifcflpwyAAAAABBABEEIIKMMMMKMNPQRQQPQQRSSSSRQPONNMMNMMM", +"MMMIIEEHINOPPNHyttwwpi9995|///|39ilf5|/)-*%%*%$$$%-,~~~)~)),,>>;;;-*%%%%$#@@@++++...++@###$&%=*;;;;;;;''''/<<~~!){/|5ioolifc9cffiilpyEBwttyEEywpiikgjquwtxzFIKMNOOONONMKHEBAytplkilllollloptyAywwwywwtoifiif999cilptttttwwwAABEIIKKMKKNOQQRQQQQRSSSSSSSRQPPONKKK", +"KKIHHHBBABIMOPOIBAABAwoc53|<<<<|39ilc3<~,*%%%%$###%*,,)))))),'>--;-*=%&%%$$#@@+++++++@@###&%%*;;;;;;;;;;;')/({''''!{_5fifc95599ccciltAEAwtwEIHAyoiigjiqqtwzDEKKMMONNNNKIEBAxwtqplkllllliililpwwwtptttpplififc55599floooppppwyyAABEEEIIIMNOQQQQQQSSSSSSSSSSRQQONM", +"OMKHHIEEBABEIMMMMIHHEBwoc5|<<<<|35fiic|/)>%$%*%####&=>>>,)))),,>>--*=%&%$$$##@+++..+@@####&%&*;;;;;;;;;;;;'!~{';;;''{<0cc953|35959cciwBBwptAIIEAtligdemmtwzAEIIMMMNNNNKIEAyuuppqollifeffiiiiiptwtppppppoliffc955555cilloppptwwyAyyAAAEEHIKMOPPPPQSSSSSSSSSSSRRQP", +"QPNKIIHIIEEEEEEHIKMMKIEyoc53|||5559fol9|/)-%%%%$#@@#%*-->,,))),,>>>-*%&$#####@+++..+++##@#&%&*;*;;;;;;;;;;;')),---->,~|9995||||595359lyBypptBIEAtiebdemmquxAEHIMMMMMMMKIEAAuqomqpomiicccfffgilpttppopppooifffc9553359filooppptvwywyyyABEHHIMOPPPPQRRRSSSSSSSSSRR", +"RQPNIHEHHEEEEBAyAEIMNMMKApic5339c95cotl9|/,-%%*%#@@##%***-,)))),,>>-*%$########+++++++@#@$&%*******;=;;;;;;->),;===->,~39995||<395259fpAypopyEBypicedeempvuAEHIKMMKMKMKIECAwuqmmoppoifccccffiilpttppoooooiifffc9533599fillopptwwwwwwxwyAAEEHKNOOOPQQQQQQQPPPPQQR", +"PPPOMIIEBAwAAywwttyEKMNNNIAtlc9cfc9cltti5<)>*%%*%#@@#$%%%*-,))),,,;=*%%$###@###@+@+@+@###$%&***=*&%&**==;=*==',>-*%*=>)<5c905||335359flwytolpwwppifeggjmpqvxDHIIKKKKKKKIECAysrnjoppuplfccccfilllppppooollliifffc9555559cilopttwwwwwwwxwwyyCEIIMNOOPQQQQPONMMMNNO", +"NNNONNMKHAwwttttpoopwBIMNNNMHAtppoolotwo9|~,-***%$#@@#%%%%*>,,,,,,>=*%%$$###@##@@@@@@##@#$%&***%%%%%%&*=**&%%-,,>****->{3cc999535559ccfowwoifooppofffgjmmrsuDFHIIIKKKIIICCAvurnkmnpppolfcccfloolloppplllliiifffcc9557550cfipptttwwwwwyywwyABBHIMNNPPQQQPOMKKKKKK", +"HEHIMNOONKEAytpoliiffipBKMOOOOMIHEAywAytf5/)>>**%%##@#$%$$%*->,,,,>-*%&%$$$#@@@#@@@@+###$&%&****%%%%%%**%&%%&&;'>==&&->,<9ffffc55555599fopofdilptpihhgjmmruuDDEEIIIIIIIHCByvqqmnmolilllifccfioooooooooliiiffffcc9955333599fiopppptttwwyyyyyAAEEIKMOPPPPPONMKKIHE", +"BAAABHMOOONKIEwoifcc99cltBINOOONMKIHBBAyo9|~),-*%%$###$%$$$%*->,,,,>-*&%%$$#@@@@##@@####&&%%******%%%**&%%%&&=*>,,-;;->)<5iiiif9333||425fomgc9ipwtibegemmrtuxDBFEIIHHHIHEAyvuqqnmoifgiiifffffioppolooooliifffcc95595533335afilooooppppwwxwyAAAEHIKNOPPPPONNMKKHE", +"BAwwwyAIMNOOOMHwof999599flpwEKNMKIHHBBAyti5|/~)>-*%%$$%%%%$%*->,)),,>=*%%$#@@@@########$&%%****%******&%%&==***>)~),>,'!/|ciffc51<<|_<139ipld0fowwocfgjmmrsuuxDBEEEHHHIHHBDvtqropomfddgfifcccfiopololloliifcc9955555553337adfjilllllppptwwwwzzBBEIINOOOOOONMKIII", +"CytqpptABHIKMMKEwof953599ccfowBEEAwwwwwwti953-*%%%%**%%%*=->))),>-;*%$$####$##$$$$$$&%&****===*===**=;--**->)//)>>>,)/|9c995_(<<<<122cloidcitypffhhmmrvvsuxDBEEEHHHIIEDyuusppmlfc0cdfffc99cioooolllliifc99553355557735a0behiikilooooputwAyAAEEJMNNNOOONMKIKI", +"BuuomorpwwwyABEEBypf5||39999cipwytpoooooi9355|<~)>-%%%%***%%%=->,))),,>-*%&$$$%%%$$&&&$%%*=*--*=--=-;-*=;--*=**=-,)'-*-->,~|9995<((<-*%****%%$&*=>>,,,,>>-*%%%%%%%$$&&&%%&*****=*==*=**&&*%%&&%%&%=>';%%**>)/3999|_(__<(_}39loifciopifkljmmponrruuABBBBEHHHEBywxttpoofb99cffifc9059cffffififfc955333599990999ddcchgeiijonlrqptxxzECCHIMNNNNNOMKIH", +"ByqmjggeebbcccipwyAytof5553335clpwwtof95|*%%*-*=&%%%**->>>>---=&$$$$$$$#$$$$%&%&*%%&&&&&&%$$$$$#$&$###$*;;*&%%=;,<5995|_(<-*%*---*&%%%**---;-***&$#######$###$$$%%%%$$$&&$$#@####$####@@#%=*%$#$&>)<5593<_<<-*%%=>,>-*******--**=%%$############&%&%%%$$$$#$###@#######@@@@#%=&$#$&=>)|5953:_<|<}}}5fooic9c9bcijmolqmmppuwxAABABEEEEAyywwwttpoieccdcc999997333599ffffffcc99535599ccc88a99cdhfilonorqpxxAACEHIKMMMNMMNNMM", +"KIEAuqjg8a24:<<<|359ipyBEEAti93339ipwtplic533|>-**%*-,,>=*-*==**=***=%$$##########$$%&%&%$$$$###@@#####@@@+++@@$&=%$$&&->~|5954||3|22239ipoicc9acfiooolqpqttwwyAABABEEEAyywwttpplkicccfc99999553|3559ccffiiiffc99cccjiiffcccdchiklooorqtxwyyBCEKKNNMMNMMNNM", +"MKKEwuigaa21:_(///<|9ipwAEIHAof5535ciptpoic533|>--*%&=>,,---*=***=*****%$##@@######$$%%%%%&$$####@@@####@+++..+@#$==&$$&*-'<35553|3352226fotoifccciioooolpmmttwyAABEEEEEAyxtttqoooiiifcfc995999955559cffiloooooliiiiilloliiifiilloopppttwyxAABCHIKNNNNMNMMMN", +"MMMIExuke861[_(~////|9fowAEIHAtf95559ipttpif953||~)>-*****-,,,-*=&%%%=***--*%$$#@@#######$&=&%%$$###@@@#####@@++..+@@#%;*%%&*-'~|599955555559cittoieciilioomlnmopttwyABEEEEBAwtprrppoookggf9c999999cccfcciiiilppppppoollliiiiiiiiillooopttwyyAAEEEHIFMNNONMMNMMN", +"NKMMIEymib64_[]{//(/||5iptyBEHBtic999cipttpiffc95|/)>**%%%*-,,>**%%%$&%**---**%$#######$#$&**=%&$###@@@@@##@@@@++++++#$=;-*==-')<59ff99999599cfowtlfffiiilooonlomttpxwAAEBBBAytpqqpqplllgccdfcccffiiioliiiiilillloooolllliicddccfgiillloppswyAAEEIIKMNOOPPONNNMM", +"MKKMMKEwoia61[]/<||||||9fiopyBEBwoicccflppoiffffc95<)--***=-,),-*%%$$&%%**----*%$###$####$&%%**%$$#@@@@#@#####@+++++@#$*;,>>;>,)/39fifcc999599cipwplfifffilooolimmoouutwyADAAAywtrrmmmiiiggdgiiilpptpppliiiiiiifiilllllooolic9099cfigiiknopuwzzBEHIKMNOOPPPPOONN", +"ONKMMKIBwof94}<_|33|>>>>>,~~>-=%%&$$%%*->->--*%$$&%$$$$$%****%&&####@###$$###@@@@@$$=>)))>,,)~|5fiifc9999559fottpliiffcilllkikkglnrpuuyAAAAywwpqrnliiiilikllmopwAywtplliifififiilllloooolic0899dffiijnlrutxxAEEGKMMNOPPPPPOOO", +"OONMMMKIEtic62<_|33>>,,>,)~)>-*%&%%%%-->>>>>-;**&**&&%%*;**=*&&%%$&$$$%%%%$######$%%=,~{),,,)<3ciiiifccc999ciottoifc988fffgdhgggmlrquwAAABAwturpqomoploollllopwyyttptplliiffffffiiillliiifd99999fiijnloqtxwABEGILMNNOPPPPPOP", +"ONMKKKMMKEtl92__<|3->,,,,,)~,-**&%%%%*->->>>>>------=*=--*****&%%&&$%$%**%%$#####$%&&-)//),)~/|0ioooiiffc95559iolfc986a9cfegfbggijmmquyAAAAwuqquuttttpoooiiiilopttttttpplic99999ccfiiifcfccdc800cffilloqtxxACBCIKKNOOPPPOPOO", +"ONMKJHHIKIEyoc3|/_|<-&&%%$$%**;->>>>>-----------***==%%&&$$$%***%%$$$$$%*=*-,/-==%%%&&&*-->>>>>--->>>>>>-;--=*%%&$%$$%*---=%%%%%*--->,)<<>,~~,>==*%%%%*-->>,,,,,>>>;,,>>>>>---***%*%%*-->--**&%%**=**->,~/~)!!{{/|9c953||1____|7cc977626bcfgdfkkkmrrqqtwyyAAAywtuqpmmloooliifcccfffilopptttplfcccfffcccccc9ccddgfeiliqqpuyyBBGHILMOOOPQQPPO", +"NMKKHEAywwwyAywoc53353|<|553|3359fflliiltBHHEyo933333||=&%%%%%%*-->>,,,,,,,>>>>>>>---**=*%%%$$%**%%%%####$&&%%&-,)~)'''')/|9993|<<<((/(<7c9056266dcfghgkkooqrqtwyABBAAywtpommlkiiiiffcc99ccfiiiiopwyytlfccfccc99ccccccfiiiiloqppxAEEGFFIMMNOOPPPPOO", +"OLIFCBAxtpptwAAtl9533533599533359fiiliiopyAEEBApc99993||,,>&$######$%**-->-----;--*=-***&%%%&$$#####$$#$###@##$$$&&*;>!!!''>,){|553|<<<_({~(|9c90566689ffgfkknlqrqtyBEEBBAywwpolkkfggccfcfccc9cffffffipwAAwpiffc9999c9cccfgifilloqpxwBHHHIFILNNOPPPQPOO", +"OLIFAAyurmmoptAytof5||||59fccc99cciiloopptABAABApifff53||<~),>**-,,>*$$#@@####%%**=------=*%**%%%&$##$###@@@#######@@#####&%%&*>!!';-;''~|553|<<__{{{(|9cc0866889fgikklinnqtABEEEEAAywtrllidd90999cfiiifffcc9cffiotwwtoif9999c9ccccfiiilinmpuwAEIIKKMMONOPPPQPPO", +"OLLFBvwqrmieiiptwwplc5|||39fiopppiiiloopppwBAAABAplii9533|/))>--;>>>-&#@#@@@@@#$%**-----;=&%%&%%%$######@++++@@##@@++@@#@#$$&%%-'!!>;;;-,~|553|<__({]{_49cc066aa0fkifkglnrptyABEEBBBAAwpolif9999099ccffffffc99c9ccfiotttoi999c9dccffiiilnnmruuAEHIMMNMOOOPPQQPPO", +"OMLFFzvqnmebb9ciotttoi953359itHMHwtpollollpAEBBEBwoif95595<~))>>-->>-&#@@+++++@#$$%*----*=&%$$&$##@@@@@@@.+++++@@@@+@@##@##$&%==;'!,';--;,~|5531<_>-*$#@@@++++@##$%******&&$$$####@+++++....+++@@@++@##@##$&%==;;'),'-=->,~|553|<|<_(~][20cc969afgkimioptuuwwwyzAAAAAwwtpoifffc995573559cfiiifc955599flppoliccccgfiiiooopqppuyyBGFKNNOOPPPQQQPO", +"OOMKFzzwqkij96}||5ciif93359cipEKEtooppttpoopwAEEEBwpif99cf93|<>--&$#@@@++++@##%%*****=&$$#$$##@@++++++.+.++@@@@#@##@$#$%%=;;;;,',>--=;,(|5353|1<_]/_}29cc98ccfiommpptuuwwwxwyxwxwwwttpolifcc9533333559ciilic953599cfloollicccfiiiiolpqqpuuyACHKNNOOPPQQQQPP", +"OONMKCByumjjc9}<_|39cc9|<<39flAIBpc9cipwwtppttwyAAytoifffi93|<--*&##@@+++++@#$$%**%%%*&$$$$##@@++++.+++++++@@@#####$$&%==;;;;;,,,>===;,(|35533|1_/(:}5cffccbfipppupsuuwwwywwwwtpptttppolifc99533333559cfilli955559cfiilooliiiiiiillloqrwuyCCEKMNOPQPQQQQPP", +"OOOOKHByxrljc921_/_|5993>,,-==*-,~|35577|1,';***-,~|555733||}:15ciilfffltutppqptvwwttttttpppoomoliiiifc955333355559fillif9909ccflottpoolnlmlloqqpuyyACFKMNOPQRQQQQP", +"QOONMICwurmjeb564|(]{<355|/~~3fpABtfcffiiilopwwtiffiptoic93-****$#@++++++#$$%%%%%%&&%$$##@@@@++++++++++++#####&%$%==;;;;===*->,'-***-,/|55557552}|38dfllikipqqppqpttttttttttppppollliiiiiffc953333353359filiic9009cflpttpppppppoooppxuyBCFLNNOOQQRQQQP", +"POONMICzqlkfa85434_~{~<355|~~/5iwAwicfltwpolipwwtlffiptpof5|/~/~,,)~)>*&**%##@+++.+@#$$%%%%%%&&%$##@@@@+++++++++++@@@#$$&%&&=;;;;;===**->>>-***-,/|59599c96|458ciloooqmpoqqpsttttttttttpppooliiiffiiifcc955333333559fiilic909cloptwtwwwwtpppptwwABGHKMNOPQQQRQQQ", +"QOONMICAwqkbb67}<1|>-***-,~|5599cfc556a8flpttpmooqqpppputttttttpppooomiffccfffiic995553335599cflolifcdiotwABEEEAwwtwwwAABEHIMMOPPQQQRRRQ", +"QPOONLEztqjhb64[_/(/>--*-;,/|599cfid9a66cipwwwppopqqprpuuttttpttpppoollifcccccffiiffc955755999cfloppollotyBHIKIEAywwyAEBHIIIMNOPPQQQRRRQ", +"QQPOOMIBxqjhb62_[{{{~//~~/|53|<<|5cooiipyEIKIHAywywwtpllpttof3/~)),>,))>*%%*%#@++..+@#$$$$%***&**%$#@###@++.+++++@@@###&*=-;;;;;;;;;==***==->>>-*;;,(|599cfifc66bfopwwtttuqmopppoppttptttppoooliiifcccfffiillfc99999cccfilppttpppwAEIIIHEAyyyAAEHHIKNNOOQQRRRRRR", +"RQQPONMJAulkb861[({'!)~~~~<|33|<||5fiiilwBHHBAAAAAywwtplllopoc|/~/~,,'~)>*%%%&@++..++#$$#$%%*=&***%#@@##@@@+++++@@@####&%=-;';';;;;;;-=**&==->>>;;>>)/|55ccggf99ccimpwwywtpmmmponoppptpttpppoooiiiifffiiiiloolifcdf9ccffiiilpttttwwABEEEEEBAAyAEHHIKNNOOQQRRRRSS", +"RRQPOONKHzrmf861[({!,,,)))~<3553|||5cfiltAAwppttyBAywwwplilptpf3|,';-;''(|59ccgffcfehklptywtppopmmnnoooppttpppppolliiiiiiilllooooliiiffcdcff9bfltwyyyyyAABBEEEECAEBHKKMNOOQQRRRRSS", +"SRQQOOOMKHAulia7}_({),,,,))~<3995|||39fopwyplillpwBAyyyypliowwtic53|//~/~,-&%&%#@++@@@####$%**=****%#@@##@@@+++@@@@##@#$%*;;''!!';;;;;=;***===>',';-''!{|99cfefilifgjmqttwtppoomlnoopopppttppppoooooliiiiiiopppooolifc999d99ciotwAAywyAAAEEIIHEGBEIIIMNOPPQRRRSS", +"SRRQQONMKIBysric0a|_~)',',,,)<3995|||3clptwtoiffiptwAyyAytllpwywpi953|*%&%%#@@@@@@##$$%*-*****&&####@@@@++@@@###@$%%*=;''^^!'';;;=;;***===;',,',''{_26cifiopplkiimoppppololkinoopoppppttpppppoliifffffoptpopmlic97759a99cfiotyyyywwyABBEEHHEEHEHKMNOPPQQRRS", +"RRQQPONMKIEywpolfc93|(~))',),~<3999|||5fllopplc99foptwwyAytpopwwwtof99|<<<)-%$$%$#@@@++@##$$%*=-***=&$@##@@@@@@@@@####$%&*=;;'^^^!'';;;;;****--;>,,!'''!{:29fiipptpojiiimmopooiiikiolooppppptttttpoliififfiottplifcc99079909099dioptwttttyAABEEIHHHEGKKNNOPQQRRR", +"RRQPPOMLIIEAwtolffc953|<~))))){<59c93<|9fffillc559fioptwyAywwwwwwwwpic53||/,*%$$%$#@@++@##$$%==--=*=*$####@@@@@@@@####$%&*=;;'!]^^!,';;;;;;**----;,!{!!)^]16bflppwwplkifhfllmlliiggilloppppttwwwtpoiiiiiiilpwtlfc055999c05508888cfilpppptwAABEEIIKIIHKMMNOPQQQRR", +"RRQQONMFGEEAwppigcdc9953!!!^^!''';;;;;*----;>'{]{{^]_16cipptwtpokddccfililfffgfilmopttwwwttpoliiiiloottoic933375599009d909ccfflopttwyABEHHIKKMKKMMNOOPQQRR", +"RRQQPONLEBAxtplfifcc99554|<%&%%%$@++@##$%%&*---*&=%$###@@@@@@@@@####$%&*=;;!!{!]^!'''';;;;;;;;;;'!~]:^(:228ioopptpplgcd09ciiiiffddfilmptwwwtttpolliilppptpic9553|433599ccccccccfcilptwyyAEHKIKKNNNMMNOOPPQRRR", +"RRRQPONMHCAxtnied9999555543||||<--&&%%###@@@@@@@+@@####$%*=;;'!{!!^{{!!''';;;;;;;'',!{[::_}26biopppppolgd00a9fffiffddfilpttwwtttpooolopttttoic9554|}1|35dfcfffeffgilopwAEEEIMNOOOOPOOPOOPQQRQRR", +"SRRQQPNMKECxsqib8967575555533333|<<|59fc53599ciof5|||5cfiffioyEEEEBywtpoli9**%$$$#@@#$$&&**----=&%%$##@@@@++++@@@###$%&%=;;!!{{!^^{!)''''';;'''''']^:11}26bbeiloooooifd0786ddgfffddiiopppptttppppopttttpofc95511<|13559cfilliloptwyBEKMNOPQQQQQRQQQQQQQQRRRS", +"SSRRQQOONIHBytpkb85633755555337553|<|3cc9559ccili93<|5cfili99itAEHIBAwtplic5|~,--%%$$$###$$&&**-;--=&%%&##@@@+++++++@@###$%&==;;!!{{{]^^!!!''''''''''!^^_162668abcfilllliic9776500dfifgillliopptttttpptppttplfc953|||3543559ilptttttwAAEIKNOPQQQQQQRRRRRRRQRRRRS", +"SSRRRQPONKIEAywplf9a4773334333335553||599559cfiiic3<<3ciilic59fowBEEAywtoic95<~,;*%$%%%%$$&$%%*----==%%%$#@@+++++++++@@#@#$%%=;;'!!{{(^^^{!{{!)'''''^^^(_}2aaab888bffiiiiiic9725500cfiiiiifiiloppttwwwtppppoic9555333555559fiottwttwyBEHIKKNOPPPPOPPPPQQQQQQQRRR", +"SSRRQQQOONKHBAAwtoi995573||||33||3555359c95559fiif9|<3ciloif9559fpyBBAwtplc95|/~,>*%%***%&&$%%*=----=%%%$##++++++.++++@@#@#%&%=;;!!{{{({^^^^({{!!'!^^^^(_}}26cba8aa99cfjffffc9732357ciiiiifffiilpptwywtpptplf995555595999ffiiloptwwyAEHHEEEEIKMMMKMNOOPPQQQQQQRR", +"SSRRQQQPONKKEAywytqlf9053<<_<<||||335359cc95359fiif9339ciolic54|39ltAAyytpi95|*%*->>*&%%***-->>==%%&#@++++....++++@##@#$&%=;;!!{{((({^^^[[[^^^{^{(_}}}28bb98aa868accffccc9743570ciifffffiiloppwwttttwpic953559999cfiiiffioptABBBBAywyyyAEHKKMKNOPPPQQRQQQRR", +"SSSSRRQQPOMMIBwwtttplc997|<<(//<<|||33359ffc5339ilif9559ciiif951<|9ityyywtpi93**->>-*%%%***;>>;=%$$#++++.+.....+++@##@#$%==;;!{{((_(((^^^^^[^_[(__}}2268ca698a6a6689cccfc976357ccccfffffiilptttpptwwpic95359cffiiifccciotwAAAywwwwtwyABEIMNOOPPQQQRRSSSRSS", +"SSSSSSSRQPONKHAwpppoifd0554|_/(/~/<||33359fic535cilifc959cccfc9|<<|5fptywtplf93--;>>-****=*->>;=%#$#@++..+++....+++@#@@#$%=;;'!{{(____(((__1111122}}}66866a6aa2}}}65999cc9d959999999cfffiilptpooptwwpic9559cfilifc99flpwyAywtppwyAAABEHIMNOPQQQQQQRSSSSSSS", +"SSSSSSSSRQPONKHBwtpoifc9577553<<{//<||33|39iif959fiiffc99959cc93<;-;>>>-;;***->>;%$#@@@...++++....++++@@#$&%=;'!!{___}}__[___1122222266a22226662}[:[2355999cc99d95559ccffiioppollpttplifc9ccfiiic999ipwAytppppttyEHIIHEEEIKMOOPQQPQQRSSSSSS", +"SSSSSSSSRQQQPONKHEAyplifd5559553|>>--;-->>>>*=*;>>;%$#@@+............+.++@@#$&%=;'!{___}}}}}}}}}2226a686a222222662}}:[:}225799cccd9955799cfilopplilpppliifffiillc535clwAAypllotwyyBEIIHEAAyBEKMNOPPPPQRRSSSSS", +"SSSSRRRRRQQQQQQPPNKKEAwtlf95555953||<-->>>->,,>**->>;*$#@@@+..............+@@@#$&%=;'!(__}}}}2}}}}}}2268aa86622}22222}[:[[}}32399dff99555599cflppolilopliffffiopof5|3fpABBytooptyAAyAAyAABAAAEIMNOOPPPPPQQRSSSS", +"SSSSRRQQQQQQQQQQQQPOOMIEypic53|33|33||<|3|||39ilfc9cfiiffc553553|<<->>>>>>),,--->>-*&#@@+++..............+@+@#$&=;>'!(}}}}2222222226866626662222}1}}}1::}}[}|300c9999955999fipolliiooiffffiiooi935cpAEAywtttwwyyytppptAEHIIMMNNNNNOPPPPQQRRSS", +"RRRRRQQPPPPPPQQQQQQQPOOMIEwpic53|<<|33335955|39fifccfiliic93|333|<,,'>,,),,--;>-*%#@@+++...............++@@#$%=;'!^:}}22886666666666626662222}}}}:_:::__::|3795999c9999cfloliiilooiffifillf999coAEBwtwwwwwwwtoiiopAEKMNNNMKIIIKKNOOPPQQQRR", +"RQQQQQPOONNNMNNOPPPPOOOOOMIEAwpi9|/<||3335993335cfccfiooli953|<|--;-=%#@+++.................++@@#$%=;']{_}}2866666666666}222222222}}::::<:}[::}|3335799999cciiiiifiioliiiiiiic559coAHEAttwwwttpliffotAHKMNNMMIHBEEEHKMNOPPPQQR", +"QQQQQQPNNMKKIHIKMMMKMKMOONNMKKIApc3<<<|||35555335cfccflopoic9|//~~~)))~//<39iif9335995|/~~{)){!)),>---*%$@++++.......... .. ...++@#$&*=;'^]_}}866666666666}}22222221}1[_::_:}}:_||11|439999cffiliiiffilliiilllf559ciwEHBwwwtttplfcciowBHIKKIHEHEBABAAEEIMNOPPQQQ", +"QQQPPPONNMKIIHHHHIEBBABIMMMMNNNMEti93;--%$#++++...... . . . ..+++@#$&*;;'](_}266666666666}}222}22}}[:[::[[/}||:|}1<<||55999filliifffilifiloplc59fltAEAwtwtpptlc79itAHKHHEByyABABABAABEIKMOPPQQQ", +"QPPOOOMMMKKIIHHEEHEAAwtwABBEIMNNMHyoc5|////<<||||59cfffloppoi93/!,,)),,)<<<<|59c953||5cc93|<-*$#++++...... . . ...++@@#%*;;'!^(_}26666666666}}222}22}[::::]]]:<<||334_|||33559filliifcfiiifioppicciopAAyttptpttof50fpBIMKEEAwptwyyAACBABBHIKNOPQQQ", +"OOOONKKIIHEEBBCBAEBAAwttppptwBHKKIEwpi93|///<<|3359ffffiloppoi9|/))))),,)/(//<35995335cffc95|,)~~~/<|595559fiifc93-',))))~<359999fllif93*%@@++... ..++#@&%&=;',^{_}}26666a62}}222222}[[::^:::[<:::||1|}33|35359fiiifffioooppplfcitBHIBtpollpoid9kwEEEEEAwppoooptwwwwyABHEECCFIKNOP", +"OONMHIIEBxxppmlhjffffgfloomlliffiotwAABAAwtpf53||350ciopifcfiiiic5|---,,),,)/|59555fioif93>-;->,,,,)~|55559fillf95_/!)),>>-$#++... ......+###&%*;''^](_}26666666889886067222}}::::]]:}<(/:_<||3559fffccccioopptpiioyIKKEtoliotpf59lAIBytploloprpwyytpnquzEEHHEEFIKNOO", +"MMMIHEEEAAAtqqlgeba87976809cgiifffiffilpwBEBAtplic95439cfc99cfioolc5|>>---,,,,)/|3559cfiolic5<{~),>--*$@+.... ....+#@#%=*;''^^_}}}6a6a99899889b99652|}1:_:]:<<_(//<_|||359fffcc99flopppliltEMMKApifipti95iwHIAtpopptwwwwAzwpnnquAEAEEJHIFKNNO", +"KIHHHHBBAAwtpooiica8774263779ccccfcffccfltAABAwtof9533|599ccciiopoi95|>>>>',)),)/|399cfioooic5|<~,>--*%$@+++... ...+@##&%=;;''^(_[26a688aa99cccfg99522|||<:<:||<__/__|<||59cfc9999floppoiioAKNMEwlfclto939oAIEwpppwBBBAABAwppnquwEBAABGKKKKLNM", +"KICEHHBByAwwqroolfda573}24347759999cc989ciowyAAwplf957||359ciiloooic93||/),>>,>>>>,)))/<59cilooolic93<),>-**%$@++.. ..++@##$&%*;;'^^{[}}6689aaabbcfif9956333|||||4|||<|_<|<||79ccc9959flopoiilpEMNIApiffpti53fpAHEwppwEIIEBAytuprrtxAEACzCCKMMNMMK", +"FECBEEEAyywtupoooigca74}}1|14335355999999dgltwyAwpoif973359cffilooic9533<~!,>,,>-->,))~/|9cflllliiif9|/'>-*%%%#@+.. ..+@+@##$%=*;',^{_[26688a98999cif995532533}||||<|<1__|||359ccc9959flopoiiowHMIBtliflwwf90ltwBEAttAEEEAywtpqtttwyABAAAzBFLMNNKF", +"IBCCCBEAAwwuupppplifc77}}211114|33369909999ciptyAywtoof95599999filif9533|-->)///<39ciiiiifffc5<),>*%$$##@+.. ...++#@##&%*;;,!](}}2aaa66809a9fic9966333}:1<|1:<___||||3599999559flopliotBIIBwoffipAtf9foptABAywwywttttptpttwuuAAEBCCGHKMOOMK", +"KCCBEBEBEAywwwtppoiie97322|1||1|||||7589999cfiotyAAAwtpic55555359ffc53||||<<~~),>>->)/<||359fiiffcccc9|<~,>%$#$###+... ...++##$$&=-;'!^[_[266622aa86dcec9965334|1_<|}:<___|<||3399995559flopllpAEIEypifflwApcclooptyywtpojnoptttpspuuxyAEEGEIKMOOOON", +"MIJEEEHEIHEAAAwwtpollc9722|1|11<||_<|2695099cfiopyABAytof953333|39c953||||||>--,~/|35999cfcc9955553<~,-*%$#$$$#@@.. ..+@@$%%=-;','^^(_}6662269989bb900077574|||||<|1__|<||1399995559fopplowBIIEwofcfowwlcflolloopligceiopptqttwxuAAEHIJIKMMOOOOO", +"NMKKKKIKMMKIEEBAwtppplic96733|11<|_<<|||23350ccilpwyAAwpic53|33|||5553|<<<|||->,)~<399999c99953||555|/,>*%$$$%%$@+. ..+@#$&&**=;-;>'!{[[26622a8888dd0076777734333341|<||<|14599995555flooiowEIIEwl99fpwti9fiiiififcc9cellopqqpzyzBBEEEHHKMMNOONOO", +"OOOONMKKMMNMIEBAypppppolie0955|1|||||<<:<<|379dggilpwAAwpi933353|<|33||>>,)~<|59c99c99553||3595|/,>-%$####@+. ..++@@###$&%=*-;;,!!([[226aa88d00d077424633333574||||||||4599955339flolipyEHHBti99fpwoc5cff999ccdccffijoomptAAABBEBCCILLMNOONNO", +"NOONKIHHIIMNKHAAypolloollfe9090334|||<<_<::|25ciiifiptyAytlc55995|<|||<<~~~<|33|/),>>,)/<|3599c995553|||555|/)-%$#@@@@+.. ......+++@@+##$%*=*;'!!([[286660dd000a666224233355531|3||3||3999975359flolipAEEBAoc59fpwoc59c03439cddchfiloqqpxwyBAEEGCEFFKNNNONOO", +"NNNMHEAAABHKMKEBAwpoiliiifc999099953||<|<<|<}39fifffiptyAAyof9ccc9|'!([[286000ddbbca6622}}}43435311|||3|||3999995359flolltABAyti959itwl939c931409999cfiioqrpwwBEHEEHIKKMNOOOPOOO", +"MMMMIHAyzyAEKMMKIEAtooilifc955709995533|||<|||59cc99cfipwAAAtlfcff5<~~//~),,)/|33|/~),,)/<||13675334||<<(//<|3<)-*%$$$$$$#@+.. ....++@@##&%-;;'!{[[28a0a0dccceba60a6744444331||||||||3999995555flplltAAwtof539lwwi937905337675dfiimmopuxyEEIIKKMNNOOOPPPPON", +"IIIKKKEEBABEHMNNNMKEytppoiic9577790c99953|}}||35553755cfotyAAwoiiic|/~~{~,>>,,{<|||-*%$$##@+. ...++@@##&%&;;'!{[[26000abbchkgd00a64441114||||<||<||3599955335flployAytplc559oywi533553|1|246cilkjmmouxBEIIKKNNNNOOPPPPNMK", +"CGEIIKIHHEEHIKMOOOONIBywttolfc909999cccc963||2|433||||359ipwABAwpoi9|{]~)'>,>>,~/|3||*%$#++++.. ...+++@##$%&*;'^{[[260088bbggkkgd07744411355||<|||_<|3599995335flolpBEytoi955coAwf3|3|||<||279fiigikopxAEHIIHIKMMOOPPPONKIH", +"CGEHEIHIHEEEIIMOPPPPOMHEAwwtpliilifcccffcc86532||4|<_<<||3dotABBAtoic|~!)),,,,>,)/|33||%$#@+..... ....++@##$&&*;']{([28088bbkggkkgd07a46662553|||||<<_|3599995333clolwEEwpif535coAtc||31_<13769fffffjmpwAEBEBBEHIKNOOPPOONIFE", +"HIIIEEEHHEEEIKNOQQQQQPONKEBAwtppttplifgffc999a5||||1_/(/<<|9ftAEBytoi9|/~))),,>--'/|3331|<||39c97|555553|<<~,>->)<||~>%$#@+...... ....++@##$&%*;;!{^[280b8ggkgggklifd98676265334||||_<|3599995333clllyIEwlfc5|3coyt9||3|-=;,/|35533559cgf953333||-%*,~||/,*$#++............+++@##$&%==;!!([28abghggggmlligfd866533952||||1_||3599995333ciloyIEwlc9||3coyp93334;-=-)<39c9c99cfffc72|<<;*%%-)/|<)-%#@+....++.....+++@##$&%==;!!([280hhggglljmliffd9668a6952||||1|||35999953339ioowEEwic9||5cpyp93334|<<|769fillpxwwutwvxzDFIMNPPPPPOOONOO", +"KIIIKMNNOPPPONMKKMNOOOOPOPPQPPPOMKEBAtpoolif97565533|<<<<<|353|5citwwtpl93>>>,/|59ccccc9c99931>-%%*>~<|/,*%#@+...+++...+++@###&%*=;'!(:2a0ghhgllllmliffcd95607055|4|1||||3599c953339ioowBBtic9||5cpwo931|4555099filopttuqsrvxzDHILNPPPOOOONONOO", +"KKKNNNONOOOONMIEEEEEHHHIKMMOOPPPPONMIEwpppoic85555753|1<<<|5333|49iptwwtlc5|<~,,,>>>)~|359cc9999053|<_())!~~~),>>-*%%*,/||~>*$@++..++++++++@###&%*=;!!([280gghilllplmifdcd997868554|1|||||3599c953|39ioptAApfc5|39ftwo93||49filliiiottuommrtvxCFILMOPOOONOONOOON", +"KMOPPOOOOONMKEAywwwwAAAABBEEHIKNONNOONIEywtoic9975355573|||33|33435cotwwtof9|/,>>>>->)~<359dcc999572_(/),',,!)),,>>-%$%-~<|<)-%#@+..+@##@+@####&%*;;!!(:2abkgjjjopqlmkfcd90870600541||||||35999953339ioopywoc95||5fpwoc53|4cioppoioptpmhmqrvxBEFKKNOOOONNOONONNM", +"NOPQPPPPONIHEAwwpppttAAAAAAABABEIIIKNNNMKEAtpiiif955559053|||||333339lpttoif5<)>>>>>-')/||7ccfcc99721<(~]!'>,')),,,>-%$$%>/||/>%##@+@@#########&&*;;!!([28bknjjnrrrmlifcb90990850541||3|3|35999953|39foopwwi953||5fpwofc535copppoopwpmjmmrswzEHILKNOOOOOOOOOONMM", +"OPQPPPQPNKHBAAAwpooptyEHEEEEBBBBEHEEEHIKMMKEAtoolf995590953|||1437|||9ilpoli93/,>>>>;;,):<359iifcc964|,',)),,>-*%$%-~|3|)-%$##@@@##$$$#$&&*;'!{[[26bknmjmrrrmllggc9009d09055533333|35999953335flopwti953<|5ftypic9|3clppootwpnkjmrpxzBHHLKNOOOOOOOOOOOMMN", +"PQPPPQPOMIEAAABAwptttyEIKKKIIHHHIKKEBAAEHIKKIEytplf953335555||11273||35ciooif5|/)'>>';'']_|30fiigc95241<~!)',>;'',),,>--%$$*,/||~,*%$##@@#$%%$&%&;;'!{[[2abknlrmqrqmllkgc9089dddd055553333359ccc53335floptti553<<3ftytif9330lpplpwtlhghmrwyzFEILMNOOOOOOPOOOOMMO", +"QQPPQQPOKHEABBEBAywwywAEKMMNMMKMNOONKEAAAyABHIEBwpic953||35553345993||35ciiif95|/)>;',,!]/|26bcfiff9631|;>,,,,,,>>=%$%-)/|<~>*%%$$#$&%%=*=;;'!{[}20bkorqrqrrrlmifgc988cgfcd59555553559fff95559floptwl553/<3ftAwoif530lppotwpfggmmszzBFEIKNOOOOOOPPOOOONOP", +"QPPQQPNMIEEBBAEEEAywyyAEKNOPPPOOOPQQPNIBytpppwBEBytlf953|1|35555dfg9933359fifc95|/),,))]!(}269ccecfc9534|_(~!,>>>;>'>,,,,,>-**-,/||<~>-*%&&$%%*->;''!{[}60bkosrquusromliifc9cdggigc999955599ciiic9559foptwyo993/<3ftAytpi95cmoopwpihgemmtAzDEIIMNOPOOPPPPPPOOOOQ", +"QPPQPNKHEABBAACEEAyyAAEKOPPPPPPOOOPQQQPMEypliiowABAtoic931||359ccfiic953339cfc953|/!))~]{([}0accbcc999053|<<~!',>>>--;''!),,>-**>)<||/)>-=&%%=*;;''!^_[}a0bhutsuussuooolifd9dddfkigc99999599fiilic999fptwABpcc5||5iwAAAwofciooowtlhhgemqwzzBCHIMNPPPPPPPQPPOOOPQ", +"POOPOKHBEAzzwyAAyyABEHKNOOPPOONMMMNOQQQPNKBtlffiotyAwplf931||359dfiif9993||5ccc93||>;;;-',,),,;;;>)/|||(!'>-*=-;>'){]<}a6dkovtuuuusuroolifcccccdgiicc9995999filiic999fptwBEtic5||5iyBBBBwliopptwplehgjmqwyzDCHILOPPPPPPPQPPOOPQQ", +"POONKHBBzwxptwxwwAEHKMNMMMMKIIHHIIIMNPPPPONKApiccfltyywoic73|359cgiliic953|35ccc5|||||:<_}}}6bbebc8a5269977||-=*;->,)))''',,~<1|>>,'!]_126adknvtxuuusqqqoiifgc900ddiifc9955559cfiif9959clptAEtic5||5iwByAByoopptwwolfegjqwwyzBEJIMOPPPPPPPQPPOPPQQ", +"ONMIHBBywuurpttutyEKNOMIIKIHEBBEEEEHMOPPPPOONIyoiccfltwwtlf055559dillifcc93|55ccc53333|1|21668bheca97424375541<<({),>>-==%*->,)!~~),,)/<|||(!)),'!!^_228bbknruuuuuuqpqpokgga90009iifc95555559cfff95359iptyBti95|<3ftytpppopppwwpolhhknuywzzDEJKMOPPPPPQPPPPOPQQP", +"OMIHBEEzxuonpuupotAKOOMIKMIEBBBEEBABIOPQQPPOOOMEwpiccfowwwoic99559gioif99953|59cc9533537222a6dbbhba874111355553|<;=*=%&&=;,{{(((__1||||||<__[[}2268ekoruuuuqqqomolkfd900099cccc955353359ccc53335cltAEwi93/~<9lpplillfiopoiiifjmpwwzyADEIMOOOOPPPPPPOPOQQQP", +"MKHEHEAxprnnmpmkiopAKNMMNMHAABHHHHEBABEKOPONOOOOOONHwoifiotwtoicc990ciid3|355335cffc909c99dchgggghb8877}2__<|35554|<((),--==&&&%->)~{(<|55||<|34||}|4268dbhnvuuttuqqqnlnkhdda0999ccc9995353359ccc93335citBHyi93/~<9iooooofcilifggeeknrtwwyyEEINOPOOPPPPPPPOPPQPO", +"MIEHHHApprnkmqmhkjltEKKKKIByyAEHIHEAyyyBHKKIIMNOOOONMEtlffipttpifc9599fc9|<355559cfcfc9cccffkllkkeeb985321_<__|7555||_~)'>;==&&%*=>,)~/<|7|<<|14376786bbhhknquvtvvqqqqmmmkgd09b9cccc8995353359ccc953359itEHAi95/~<5floooicflifddfchkruqtwxzDEINOOOOOPPPOOPOPQQOO", +"NIIKKHtppnkkmqmkkjiotBHKKHBAyyAEHIEBAwwwAEEEBEHKMNNNONHwoicflppoifc955cfc3<<|3595cfiiiiffcfimppnmmffb953}}1_<(__|333|_;','{/<<(_<|436509cffgjmnrvvtvwwtuqmmmkfdccbccccc9599553359ccc953359itEHAoc5<~/3fiopliiloicabbbhknqqptxzDILNNOOOOPPOOPOPPQPOO", +"NKMNNEtpqlkkkmqmkeihlpwEIIHEBBBEHIIEBAwwyBEAywyBHIKMNONIApf9dioplifc90cgf92_:|5999fillliiiiimopppmljfc954}}1,,,,)~(/__|36709cfgiknnstssuwvvvttqmmmiifcbbcccc9999995599cffc9555citEHEpf5>''',,'!{((<|589cfcfiloqttxtutvvwvwwuppoliifbcbccc9999cd999cfiiic999fltEKIwi9|<<5fipwABAtlcb88bcimlmprsuDDJIMMONNOOONONOOPQOOP", +"OMMNMEwtpmnkejmpmmhbheiioppolooopwBEBAwttttwtollooptwEIKKIypg009flollifcfic953|35ccfilloolommnqopppoiibb953}[:((({))))~_||<;>''{<<11<<(/_/_((/{([[[:13669fhloptwyyyyAAAywsvwtttpolieeccbbc999dcdcccfiloic999ioEMIAl5<~~|95559dc89898ccnoonmrsuDDHHKMMNNNONMNMKKNNNKIN", +"PPNKEwpttpnnllloutwplhjijejif98cfilpttpoliiipwwtoiiffffioptwAytofcfltwwwqolif9956269cfoppttppuuqrqopmollifc9741[:])''>;;->;'{_<|1|44322}[[[[:_12|226bekopuwyyyyABBAyvwywtttrliffccccc8990999999fiifc99cioBMMEp9>,~<|35599652}[1142a6268abhiottwzyyyAABAyyAywwwpolifeccfcc990509999cffc9559ciyKMIwc|,~|49cccdd0755766aa8abhhjmpuxxxxwyAAAAABBAAywpoiifffffcc90999999ccfc93335ftHMIwc3|<|9959fgb968bbcioomkoruyDGGIKMNNNNNMMKKIIKNOKCE", +"INONHpjkloliinonmmmqrtwwwttwyytlc9909cfif9999ciptttppoic9999flpwyAAwtppwwyuopoifciifccfloptwzxyuuqqnonkjjiliifc5}:(!'';;*-=-==--'!_49ciifdefc898abbbbgehmptxwxxxxyAAAABEEBBAwpolieffiffcc909999cffc95335coBKIyf|>;;>>,,)~~/<<<<;>;;->->>,,)~/<|||||<<<11375cfiiowABHIKKMKIHHKKIHHECGEHGEHIIKIKIIIFIKKMMKKMLKKMOOOOOOMKKIIJKMMMKKMKNNNNNNOOOONLIJEDDwvsvnnhkkggb88aaa222222222274132259999953700adoswywxzzzAAAEBAAAACBABCCHKMMKHCzCGIIHEFGJIMMOOOOONMIHEzzwwytsuuttwwwwwwt", +"mhgghbiec8833|_[^{)!',>>;>>>>>>>,!!~/<|||33111|3779cioopwAEIKMMIHHIIIHHHEGEGGGGHHIKKKIIIFIIIKKKIKLLKKMNNNNNNMKKIJIKLMLLLLLLLMMNOONNNMIJEDzxvvnnnhggbbbaa7744411111112}411423599cc52200adiptwywzAzzzAEEBAABCBECCCGMMMMJCzCEEHEBFGIIMNNOOOONMKIEAzwwwttstttxwwwwtt", +"megbcfb906|1_(^^^!!',;>;;>->->>>,'!~~/_||3373||376acglpttzEIKMKIIHHHGEEHHHGGCCHHIIKKMKIFFHFIFKKKIIKKKKMNNNNNMMKKIJJKMMLKLLLLLLLLLMNNLIEEDxxvvnnkhgbbb0a7774441}[[[}111}11134459cc5220dadjpwwzwywzzAAzEBBAAEEECCCHMNNMIGBBEEEEDFGIJMMNNOOONMKFFzxzvwvssssuwwwwtum", +"edgebe8622_(((]]{'''>;>;-*-=---->>,))~/__1137337aa9dilptwzAHKKKKIHEEGEGHIHEECCHHIKIKMMKIHHHFFFKIHIIIIIKMMKKMKKIHHEEHIIIIHHHHLLLLLLLLLJEEDvuvrnkggaaba0aa222}}}}[[:}}[1_:1112239995345badiowwyzwwwzAAzBBEEEEHGGCGIMNNMKHCCGBEDDFEIJMMNNOOONMIFDzxzxwxsssstxwwussm", +"egecba62}__({^^^'''>;--=**======->',)){(__<|4508600chkptyACEKKKKIECCEECHIIHEEEHHKKIKLMMKFHFFFFFHHHFFIIIKMKKLKKIFFFDFFHFHHFEFHHHIILLLLHDDzvvvrnghbab00a6a6}}[[[[[[::[[_1_:11211|441247adhhmtwyzwwwvzzAzBBEEEHHGEIIMNNMKIFCCEEEDEEIIKMMMNOOOMLHFDzzwwxssstwwwtsumm", +"ggccaa2}_({{!!^^'';-=*=***&=====->>,,!){_<_|4609ddhbflowyAzEHIKKIECCCBzBHIHEEGHHIKKKKMMKFFFFFFHHFFFHHHHIKKIKKKHEEDBBBFFFFDDDFFFFFFHHHHDDwvvvrkghba0066622}}[[[::[::[:[[__[11|1|111135a0henpwyxwwxwwzzzBBEEHJHHIFKMNONMIHFHEEDDDEEIIMMMNNOOMKHFDzxzvvvsstwwwtmmme", +"ghfb62}[(^{!!!^!';;-=*&%%&&&=====->',!){(<1}2269cfhehjruABAEBHIKIECzAzzAEHHHHIIIIKKIKMMKFFHEEEBEFEEEEEEEIIIIIIIFBCAAzzAACCCzDDDFFDFFEFDDxvvrnkgbb00662222}}[[]]^]^^][[::__[1111111112a0hhjrwywxuwwwwzzBBEEGJIKFFKMOONNKHEHFEFBFEEIIMKKNNOOMKHEDDxzxvvsstwwwsmmme", +"kbb62}[(({{!!!!'';;-**&%%%&&&====->','){(_}}2770bhfinjnqyCBBEEHIIHCAzyAzBEEHIKKIIKKIKIKKIIHECCCCCBBFEEEEHIIEHHEBzzzxxzzzzzzzzzzzCCDDDDDzxvvrnkgbb00a22222:[[[]^]^^]^^^:^[__:|111111124abhjqwyyxuuxwwyyzBEEJIKKKFKNOOONKIHHHFEFFEHJKKKIKMMMKKJHFDzzzvvwtwwwttmmeg", +"icb2}[(({{!!!!!'';-=*&&%%&&&&====->','){(_}}7559bchlmrqszCECAAEHIIEAAzAAzAEHIKKKKKKHJIKKIHCCCCCCCzAzBEEEBEECCECCzzzzxxwzyyvzzzzzzzxxxzzxxvvrhkgb006a2222[[:[:]]]^]]]^^^]^:_[:1111114277bhjnuwwxuuuwwwzzBBEJIKMKKMNOOONKIHEFHEFFEHKKKKIKMMMMKIEDDzzzvvvtwwwummmjk", +"eb6}[[({{!!!!!'';;==*&%%&%&%%%===--;,'){(_}270aabhjnpqtxzEECAzzEHHEEAAAzzzAGIKKKKKIJJHIIHGCCGGCCCzzzzCCCCCGCCCCCAzyxwvwwyvwvvvvvvvvxxvxxxvrrhkbb00a2222}}:::]]^^^!^]]^{]]^:_[111[[124770hhnptwvuuuutwzzBBEGIKMMMMNOPONMIHFFHFEEEHKKKKKLMMMMKIJEFDzzzvwywwusmmjgk", +"b82}[(({!!!!!''';;==*&%%&$%$%%===*-;,'){(_}27aaabjhnqqtxAEEBBxzCEEHEBAzAyAzEIKKIIKIJGEHHEGCGEEEBAzzzzCCCCCCGCACBCzyzwwwvsttsssvvvvxvvvvvvvrrhhbba66222}}[[[:]]{!!!!!^]^{^]]__:_[_:}}47a0hhnpuwwtuuuwwzyzBEEJKMNMMOOOOOMKHFHFEFDHHKKKHHHKKKIHHEFEFBzzvxzwwtsmejkj", +"b2}[[({!!!!!''';;;==%&%%$&&$$%&==*-;,'!{(<}478bbhjjmmqxxABBBBCzzBEEEEEAzyyzEHIIIIKIIHEFECCCEEEEEAAzzxzBGCzCBBzCBCAAutusstuussssssrrrrrvvvvrrhkb0a6222}[}[[[:{{{!!!''!!^^^^]]_[[[[:}}26aahhhnttwtpuuuttzzBEEJLMLMNOOPOOOKIIHEEFEHHKHIHHHIKIFEFEFDFFzzzvAAttmmhkjc", +"82:[({!!!!!'''';;;=%%&%$$$$$$%&==*-;,'!{(_}45abhhjmmruxzAEBBBCCzBEHIIHBzyAAEEHIIIKIIHEECCCCBEEEEBBzxwwzBBABBBCAAyywtttsspmmmmmmmsrrrrrrrrrrkhbb0a6222[::[:(^]{!!!''''!!^^{^^:_}[:}}}466ahhjiputspuuuttxzBAEGKMMMOOOPPOONIIIFEFEHHHFHHFFFFIFDBDDCAzzzvvAwtmmejkhc", +"2}[[({!!!!''>'';;==%&&$$$$&$&%%&=*-;,'){(_}47abhjmmruuyzAEEBCCAAAEHIIIEBAAACEEHIKKIIHFEAzzzCBBEEEBBzwwyBEBCBBByyyywwtqmmmmmmmmmmmmmmmmmkkkkkhbb08622[[[[:((^{{!!''',''!!^^^^[_1__}}4a666hheipputrrruutxzBAEGIMMNOOPPPPONMIIHHHEHIHFFHEEHIIHEBAACCzvvvtwtmmjjkic9", +"2[[({!!!!'''''';==&%&&$$$$&$$$%&=*-;,'){(_}47abhjmruuwxzABEBCAAADBEHIIHEBAABCGEEIKKKHFEzzzzzAyAAABBBywzAEBBBAAyyyywqqqmmmmmmmmmmmmmmmmmkkkhkkbb08222}[[:::(^{!!!''','''!^^^^^:111}}47666bghhlptpppquuttxxAEGIMMNOOPPPPONMLIHHGHHHHFHEEFHIIEAzzCCBzvvtwwqmjjgkjb8", +"}[[({!!!!;''''';=*&%&&$$#$&$$$&%&*-;>',{(_}47abhjmuuwwzzCABBAAAAADEHIHHEEBzBECEEHIIKHEECzzzywyyAAyBBzzyAEEAAAAyyyuuqqqqmmejjjeeeeeeeeeeeebbbbba08222[[[[__^]^^!!''',,','!^]]^]11}}}47a68bhghjppqpnppustxxAEGHKMLNOPPPPPNMKLLHHHIHIHHFEEHHECzzzCBAzvsuwqmmhggeca2", +"[[({!!!!';>'';;;==&%&&$$$$$&&&%%&*-;>',{{([4aahhmnuuxzzACzBBAAAAAABHHEEEEBAACECGGJIIHEGzAAzwwwyAAwyywytwAAAAAAAuuuuuqqjjjjjjjgddeeeeeeeeebbbbb006222[[[[__({^^!!';;;'>,''!^]^^:1}}}78aa68bhgjnpppopqqqtxxAEGGKMLMOOPPPPOMKLLLLLLIIHFEDEEECCzzzzAAtstqqqmeeghcba2", +"[[({!!!';;;;;;;;=*&%&&$$$#$$&%&&&*-;>'!{{_[4aahemnuxzzzAzAAAAAADAABEEEEEEEBACCEGGGHHHHBCAzAuwwyyAyywwuutwAAAAAxuuuuunnljjggggddddddddddddddaaa00822}}[[[_({^^^^',';;;''''!^^^]_}}}3666a6a88hhoppqoopqqtxxAAGGKMNNOOPPPPOOMKLLKLKIIHFEDAACCCyAzzywusmqqmjhggfba2}", +"[((!!!!';;;;;;;;=*&%&&$$##$$$%&&%*;;>'!{]_:78ahjmnuxzCzzzCAzyzAAABBDEEEEEEBBBBGGGGGGEEBCAzwuxwyAAAAywwtttyAAAwxwuuuoonnkgggdbbb88888888888888888822}}[[(_((^]]!,'';;;;',,!!^^([}}2a66666aa8ahlpppnnpqqppxAACHIMMNOOPPPPOONMKLLKKIIHFFCAzCCCAzAzywumqqjjjggebb82[", +"[({!!!';;;;;;;;;=*&%$&$#$#$$$&&%%*;>>,!{([[788hjmnuxzCCzzBAAyyAABEBDBEFBEEEBCCGGGGGCABzzAAwxwwyAAAAyywuutwyAxwxxuuonllkkggbbbbb88888888866666666622}[[[[[(^^^{!''>;;;;;,,'!^^^[[}26a6666aa8abhopqnnppqssxxAEGIMMNOPPPPPPOONMLLKKIIHEFCzzBBCAAyAysmmqnjjghecb82}[", +"[({!!!';>;;;;;;;=&&%$&$####$$&$%**=>''!{([1468hjmvqwzzzzzCzAyyyABEBAABEEEEEEEHGGGGGBADxzAAyywywAAAAAyywtttwuwxwxuroolkkkebba66666666666666666666662}[[:[({]^^!!',>;;;>''!!!{^^[:}46aa226aaaabhoppoorrqssxxACGHKMNOOPPQPPOONMMMKKIIFEFBzzCBBAyyAuqmmjnjggbebc82[[", +"((!!!!;;>;;;;;;;=%&%%&#$####$%%%*=;-',!{([1488ejnvwwAzzzzCCAyyyyAEEAABEEEEEJGJHJGGGADDxxyAAyywyyBBBAAywwttqutxxwupnokkkeeb88866666666a666666622}}}}}[[[[((]^^!{!'',''''']{{^[[[}25a66a6668abbeottppprqupxwACCGKMNNOPPQPPOONNMMKKKIFEEAzzABCyyywtqmjnngdbebcb22[[", +"({!!!!;;>;;;;;;;=%&%%$&$$#$$$%%*=;-;,'!{_[168bbknvwAAAzzzABAyyyAADBBAAEHHEHJGGJIIHEAAxxxxzyyywyAABBBAyywttquuxxxppomkkhfa888866666666a22222222222}}2}}}__:^^{]]!!''',,''!]^^^^[}44a6666666a0cemtwtpppuuuxwAGCGKLNNOPPQQPPOOOMMMKLIFFFAzzABByyytuqjjnggabbhca2}[[", +"({!!!';;;;;;;;;==%&%%$$$$%$$%%%%==-;,'!{[[266bjhnqwAAAzzzAAAyyyADAADAABHIHHHGGIIKIEBxxuusptwywAAAAEEBAyywqquuxwxpppmkfheb888822}}}}}22}2}}}}}}}}}}}}}}}__(]^{~{]'''''','']^^^^[[}2222222266abckpttqpruuuxxABEHKMNNOPPQQPPOOONLNLLIIFFBAzBEAywquuqjjkggb8ceb22[[[", +"({!!!';;;;;;;;;==%&&%%&&$%%%%%&==-;'''{{[_468bjhnvwAAAzzzyAAAyyAAyyABBBHIIJIHJIIKKHByxurspstuuyAAAEEEBAAuuquuuxpprmmmjfbbaa8222}}}}2}}}}}}}}}}}}}}}}}}}_:]]]{{!!!'''',',!{]^^[[1122222622260abkotprrrqqtxxAAGJKMMNOPPQQPPOOONNLLLIKHECAABEAwtquujjkkgbb8cf62}[[(", +"({!!!';;;;;;;;;==%&&%%&&&&%&&&&&**;>'!{{[1468benqvwAAAAwwzzCAyAAxuuAABCEJIIIIIHHIIIBzxxsspquqquAAAAEEEBAxuuuuuxpppmmijbccb8222}[[[}}}[[}}}}}}[___[[[_}}::]^]({{{!'',,!!]]]:[_122aaa66aaaaaabfhlpttpppquuxxAzBGIMMNOPPQQQPPPOONLMLMKHEEzCBEAwqqunjjkkbbabfb62[[[(", +"({!!!';;;;;;;;;==%&&%%%&&&%&&&***;-',!{[[166bbknqsyAAAwwyAAAzAAwwuutACEEJKKIIJJHIIKEEAxwwuutquuyAAyABEEAyxuuuuxpspmmjjbbbb62}}}[[[[[[}}}}__[_:_:([(__[[___[:_//(({!!]{{((<1|1356988999a9cccfjiotyywttxuuzzAAEGHKMNOOPQQQQPPPPONNLMKFEHAAEEAwqqunikkkbb8bf62}[[[(", +"({!!!';;;;;;;;;==%%&&%*%%%&%%%**=;;''!{^_166bhknqsyyAwwwxAACAAzxutuuxBEEIKKIIKIKIKHHEAAywtttuuxyAAwwABEAyxxuuupppqomiicbb6a2}[[[[[[[[}}____(([((((((:_1:|1:}1____({{{{(((_1|}34688a8abda9ecchmptAAyyyAAACAEEHJIMMLNOPQQQQQPPOOOOMMMKIHBBEEAwqqunjjkeb88bc62}[[[(", +"({!!!';;;;;;;;;===%%&=%%%%%%%%==;;;''!{^_166aekvqwyyAwwwxzCBCBzxxuxxxAEHHKKKKMMMKIEEEAAwxtuuquuyAzxwyAyAyyxpprpppqqmjfbcba62}[[[[[[[[____((((^^^^:[:[[[1|}[[_<<__({{{{{((_<11|366a68899a8bbdflouwAAyyAAACCCEIIKNNOOPQQQQQQPPOOONONMKIHCCEEAxqqunjkkbb8acc62[[[[(", +"({!!!!;;;;;;;;;===&%*&&&&%%&&=*-=;;''!^^126bagjrtvyywwwxxzCEEAzxuuuxxCCHHKMMMMNNKIEBDyyxxuupqquwyAwtwuwyztprppprrqqlifbb6622}}[[[[[(___]]((^^^^[[[:[[[:[[1:[_<___{{!!{{(((_}_|266a6668668aa9filotyAyzzAACCCHIIKNOOOPQQQQQQPPOOONOMMKIIEEEHAyuuunjjkb88bb822[[[[(", +"({!!!!';;;;;;;;;===%***&&&&&=***;;''!{^_126bhgjqtvyywwwxxzBEBAxxuuuxxzEHIMNONMMMKHBByxxuxtspqrquwyxtuuttwtqmmmommmmljfbb662}}}[(((((__(](^^^^^^[(((((:[[:[:[}__<,'^^_122bbgjmstvvywwwxxzAEzxxxuxxzzzEIKMNOOMMKIECvvqqqronppoqtxywuqlnmptpoiiijjllliecba222}}(((((_(((^^^^^{{{{{{{((((((_:[:<<<<_]{!]]]^]]][[[[}}}2}222268a8bhipwwxuwwwzzBBEGJKMMOOPQRRQQQQPPPPPOONMKIIIHBwzwzppmkeabcc62}[[[[[", +"(({!!!!';;;;;;;;;===;=-=====;;;;'''^^(_2268hgjmvvvvywwwwyzABzxxxxxzzzBIIIMMNNMMKIGzvtqqqmnnnonquwyxuqnkklppoifiifiiifecb622}}_((((((({^^^^^!{{{{{{{{]{{]{(([:_((:<]]!!!!]^{]:[^[:[:_2}2}266a8ahimpwxustwzxAAEEGIMMMOPQQQQQQQPPPPPPPOOMMMKIEyyxxppmmjbbhba2}[[[[[", +"(({{!!!!;;;;;;;;;==*=;====;;;;;;,'^^^(_2288bgmmsvvvvwwxwyzzAxxxxxzzzCEHIIKKMMMKIEGCvsqqmnnnnnhmquwwuonkjiiooliiijiiiief86222}_(((({(({^^^^{{{!!]!]]{^{{{{{(](_((__]]!!!!^^]^(^^_[[1[[}}2226668gelqwttupwxxAACBGGKMMNOPQQQQQQQPPPPPPPONNNNKHAAxwpomkiififa22}[[[[", +"[(({!!!!';;;;;;;;;;;;;;;;;;;;;','!^^(_}228bgjmvvvvvvywwwyzAAAxxxxzzCEEHHHIIKMMKKEEAwuqqmnjnnnjhmqtuunkkjfiloiffffccbife8622}}_((({{({^^^^{!{!!!!!!!!{{{{]{](]((](<(!!]!]^^^]]^^[[[[[[122226668bgkqtwsrtuuuyyBCGGILKMOPQQQQQQPPOOPPPPOOOOONKIEAyxokkhjhifb622}[[[", +"[[(({!!!!';;;;;;;;;;;;;;;;;;;''!!!^(_}}2aabgjmvvvvvvywwwyzzAzxxxzzCEGHHHEIIIKMKIEEAvuqmmmjjjnhjjmuuonkheheiiifcfccc9bb98622}__(({{{({^^^^!!!!!!!!!!!{!!!{{{]]//(/_(]]!]!{^^]^[[[[[_[[222222888hghmwwsruuuuyxzACCHFIMNPPQQQQQPPOOOPPPOOOOONNMIIBAtpkkeffbb8622}}[", +"}[(({{!!!';;;;;;;;;;;;;;;;;;>!!!!!{__}}28bdjmmvvvvvvyzwwwyAAzAxzzzCEEHHEHIIIJKKHEBAvuqmnmjjjjjjhmqunkkhbb8bfffbccc999988a62}__({{{{({^^^{!!!!!!!!!!!{{!]!{^]{]:<:::]{]^]^^]]]][^[[[}2}2222668adghottsuuuuzyxzzACHIFKNOPQQQQQPPOOPPPPPOOOOOMMKIECwtqmiifbaa866a22", +"2}[(({!!!!';;;;;;;;;;;;;;;'!!!!!{{([[}2a8bdhmsvzzvvvvzzwwzAAzAzzABEEHHEEHHIIHHIHGEDvuqmnnjjjjjhhmquokfbbb888ffc9cc998866662}__({{{{({^^^{!!!!!!'!!!'!!{]]!{^]]:::::(]]]]^^]^]^[^[}}}}}2}2666a0dhjotxxuuuuwxxAzzCEIFILNPQQPQPPPPOOPPPPOOOOOMKKIHBBywtponc888826a2", +"222}_({!!!!';;;;;;;;;;;;;;'!!!!{{^([[26aabhmmsvzzzvvvzzzwzAAAAABEEHHEEEEHHHIHEIHHEDwuqmnnjjjjjhhmqomkjcb8a68bc99995555866222__({{{{(^^^^{!!!!!''!'''!!!!]]{{{(:_:::({]^]^^^]:[[[[}}}}}}266aaaaeejnuwxuuuwwwwzzACGIIKMNOPPPPPPPOOOOPPOOOOONMMKHHCAwwxwwplhba8a226", +"22222_{!!!!';;;;;;;;;;;;;;',!^^(([[[}266ademvvxzzzzvvzzzABzAACBEHHHEEEEHGHHIHEHEEBDwuqmnhjjjjjhkkmomjeh888a85095555335544222__({{{{({^^^{]!!!!'!]'!'!!!!{]]{{(:_:_<_]]]^{^^^[[[[[}}}}}226aaabbehmquywuuwwwwwzzzCGFHFKNOPPPPOPPPOOOOOOOOOOOOMKIEEAytwwxtpoheb8882", +"222}2<(]^!!';;;;;;;;;;;;';'!,^(([[[[}668bhhhvuxzzzzzvvzzzCCzzBEHHHEEEEHHHHGHECBCEBAyuqnnnjjjjjhkkmomifea6aa475534224443||||2__({{{{({^^^{!!!!!'!'')!!]{!{{]{{(_<<<1_(]]^{^^^::_[[[}}2227aaa8bbhkmquxxvwwvwwzAzACGHHFKNOPPPPOOOPOPOOOOOPOOOOMKIEEzxxtwwtppplifba8", +"a22}__(^^^^';;;;-;;;;;;;'''!,{([[[[}668abekrvuzDzzzzzzzzAABBABEHHEEEEHHHHHHHEEzBEBDyturnnjjjjhkkmnnmkjjc8a744432}22}}}}|1<_<<_(({{{({^^^{!!]!!!!'!!!]{{{{{{]](__|_1__]^]^^]::::[[[}2227778888hhkmquyAxwwwwxzzzACGHFFKNOOOOPOOOOPPOOOOOOOOOONIHHBBwxxwwuqqppolihh", +"h8a2__(^^]^!'';>;;;;;;>;'''!!{([[}}6668abkkqvxDDDzzzzzzzACBCCEHHIEEHHHHHJEHBEEzCGBDAxurmmjjjjkkkmmnmkhheba541}22}}22}}}::^(_((((({{({^^^{!{]^!]!')!]!!]~{({((:[<}|11_]]]^^^:::_[[22277777888bgkkmpuyyyxxwDAzyACCGHHFKMOOOOOOOOOOPPOOOOOPOOOMIHEEAAxxttpqqqnoplli", +"mfc61_{!^]^!!!!''>;;;;;;;;'!!{([[[2228abkhrvvxAADDzzzzzzzACABEEEHHHHHHHIHGHBCAAzAAAAxuqrnjjjmkkknmlmlfcfec74[}2221111_}:::]^]{{{{{{({^^^{{]!^!]!!]]!]!{]{/(((_1|}}111:::_([_::}222277777a888bghkqptyAywzyDAAyyCCGHFFFKMOOOONONOOOPOOOOOPOPONKGCByyuxyyppmmmmoopl", +"lifc9|_^]!!^{~{{'';;;--;;;'!!{(:[222600bkknvuDBBBDDDzzzzzAzABEEEEGEEHHHIHGEBEACCAAAAxxsqmjmnkkkmmmlmlifiic04}}}1_<<<<;-;;'''!{[[2260bagnnvuDDBECDBCzzyADzAAEEBAAAEEHHHHHEEECBBAADAyxxuummnmkkkkkmjmmifiic92}}_<|',''!{[[2260bhgmvutyCGEBDBzzzyDxyABBBAzAAAEEHHIHHHCBCAAADAAzzxupmnmmhkkkmjklifffd922}_<<<(((/{{{)),''>;;''!^^^^]({{{{{{{{~{{{]](____}11|4|221____1114446aaaa0adbeffehmmmqtwEECCAzzzzzzCEHIFFIMNNNNNMKLNOOOOOOPQQQQOMKFBzzwytusmmmqqurmf", +"e9aa7445cd95}<]^]!'''''';',''!{[:22a0ahnnvvvDBGBBDBzzwyzyDBEzxxAzAABHIIHHIHGCEABAAAAAAAzturmnhhkkkjkiidccd5221_<<__((({{{!'',;;;;;'''{^^^:{({{{{{{{{({]((__:__|114414}_____111226666aaaa9behjilqqqtyEECCCzCAzzzCEHEFFIKNNNNMMKLMOOOOOOPQQQQONKHFAzzyywprssmqqlif", +"e8a85375955743}:^]!''''''',''!]^[22608gnjvuvDAGBBDzzzwvwyABAzxxxzAABHIHHHHHEEBAAAAABAAAAwuqmnmhkkhkkiicccd963|<<<<_(~~~)),''';;;;;;'''{^:[{]{{{{{{{{{{{^(__::<|11442|}[[[_[}}222aaaa0898abbbejlquuwyBEEEEEEEBBBEEHEEFIKNNNNMIKLKNOOOOOPQQQPONMIFDAzzzvvvrrsmhgfb", +"baa777753}}}3437}_]!'''''!!!'!{^[2260agljqqwDADBBDzzzwywzAzzxxxxxABBEEEEBHHHBAAzyyAAAAAzwtqrqnmhhhkkiifcccc654|____~{~~))''>;;;==;;;'']{:[(({]^]{{~{{{(((_::<1|4443332}[[}}1222000aa9c9aaaabejoquuuyBEECHFIHHEGEEHEEEHKMNNNMKLKLMOOOOOPQQQPPNMIHFDAzzzvvvvrmegba", +"222|7572[<[:|1|742|[!)'''!]!!{]][22678gjjqqwDDDDDDxzwxvxzAzxuuuxxzBEEEEBEHHBAAwxyyyAAAAwttqrqqljkhkkkiiecdc954|___//{~)),>>>;-====;;'''{([[((]((]]{/(((((__<:11|4353552}}}42770ddabbdccccdhgiopptxwABEGEIHIFIFFFEHECEHIMNNNMKIKLMOOOOOPQQQPPOMKHHEEEAzxxvvrmedaa", +"2}}1774[[:[::[|4443|:{!''!!]^{([[}}6a8gjjqquDAADDDxzwwuwzwxuuuuxxxBEEEEEHHBAyyxxzyyyzAzwwtpqpooljjjkkiifcdc993|<__//)))),>>--*%%%==;;''!](:((](((]]/(((((_<_<1|435575955775700ddihhggfffikimopptwwxABHEEHIKKKIFFEIEECEIMNNNMFILMMNPOOOPQQQQPONKLHHHEFzzxxxrmed86", +"2}}131_^]:^::_14|1233}({'!!!](__:}2778gjjrquDAADDDxxwwwwzxusuuuxxzzBBBEHHByyxxxxxywwyyAwwupuqnoomkkkmiieffc995|<__//~))),>;--*%%%%*;;;,!{{(_((:(((:(/<:__<_1|4377590990775000ddijifikfiiimmmmpqppwwABHHHHIKKKIIIHIHECEIKNNNMIIIMMOOOOOPQQQQPOOMLKHIFHDDzxvrmed86", +"2}}1|_{^^]^_<_1111:}334<^]!!!{(:}22778dikmquwADDADxxwwwyyuuqvvuxzzzBzEEEAAwuuuuxxwwuxxxwwtrqooopmmmmmllffffc97||;-=%&&&&**-;'!]]([(__:_::/_<<<<|11|4355599900557909ciiiigggkfiikkkkmnnrtxxBHHHIKKLLKIIKKIEEEIKMNNKIFILMOOOOPPQQQPPPOOMKLKIHFDzxvrmed86", +"2}2__{{{{{((__111<_[}323|:]!!{{[}62088djjmqtwAADAxxxxzwyuuqvvvuxzzzzBEEAywuuuuuupstpuxxtwuqqlnnmmmmmmoliffc9673|_//~~),,,>-**%$$$&&=--'']{]_______<<<<||||3||47579999990099ccgiiiijgggcfghhgggijjquuyBEEEIKMKKKKKKIHEHIKNNNMIHIIMOOOOOPQQPPPPOONMLLMLHDzxvrmed86", +"222_({{!!{((_11311_[<:}2|11:({/:[220agdjmmqtvAADDyvxxywyuqqvvuuxxxzBEEAywutuxuspppsqutxuwtrnmlkmomliloonifc9663|1>>-**%$$$$%==-''!{((1<_<1<<|<||||||33347799ccffdccccfgjkkggddggcdbbdhheehmqqwAEECGIKFFLKKKKIHIKMNNNMKFIILOOOOPQQQPPPPOONNNMMLHDzxvrmed86", +"22}[(({{{{{{__2221__](:<11|||1_::220bghjmmquvyADDyuxwzyyvqqqqrruxxzGEAywxuxxtpprrppquuxtwtqqnjkjjillnilolif9a63||>>-*&&###$%%==>''{(_1<|<|111||||||33357709cccffcc99cghhhhjghddgdbbhbdgeehmmqwABBCBHIKIFIIKKIHIKMNNONKFFIMNOOPPQQQQQPPOOONLNMLHDzxvrmed86", +"22}[(({{{{((([}}2|__^](::<||752}}2609gglmnqtvyADDxvxwAyxqqqqsrquxzBEBAyxxuuxtutsssppstxtwtummkhkehijiilolij9aa3|1>>==&&####$%*=>>'!{(__1_111||11||33355900ddccfgc99ddhehhhhhhddddbbbabheeemmmtyCBCCHIFIFIIKIHEHKMNNOOMKFKKOOOPPPQQQQPOOOOOONMLHFzxvrmed8a", +"a}[[(((((({{[[[}}_1<<]^]^[_1459556678gglqqqtvyADyAvxxAwwqqqqvrruxzBEAywxwxxttwwyvvwwtxywyutpmmkheehhiiloilic9673|_<~~),>>;==&&####$&**;>,!{(_|||||1||1|33335599990dccfffddhhhghhhhhghdddabbbhheeehmmqyABBCEHFKIIIKIEEHKMNNOONKKKMOOOPPQQQPPPOOPPOONMKHFzxvrmed88", +"a2[[[(((((([:[[}[}<__]^^]^]_|3999990adgjqqquwAADDDwxwzwwmmqqunruzACyyywxwxwyAEEEEBAAAAAAAwwsomkhhbbbejliiiif9673|_;===%$@@@@$&&*-;'){{(_|11|||11133555569990cccghfebhhhghkkhjfgdgggbbehhhjjhmqqyABCCEFIIFIIKKIHIKMNNOONMKMNOPOPQQQPPPPOOPPPONNKHFzxvrmedb8", +"8}[[[[((([[[::1}}}_|__]/](^<<1599cfdbggkqpqwyAAADDxxyAwtsmqqquoxzzywwxwyAABEHKMKIIHEEBAAAAAwpmmjjbbbfiiiiiifc953||-==%%$#@@@#&%=*>>'!)(__1<1||43347555599999ddghfifghggklnjmmmiigghhfhghggjjqquyAEBCCHFKKIFKKIHIKNNOOONNMMNPPOPQQQQPQPOOPPPONNLLFDxvrmmhb8", +"6}[[[[[[[[::}22}}}}_<_<_:/(__137ccfgfigimmqvyACADDzzzAztsmqqqquxAAvtwwABEEHIKMMIEEBAAywwyABytqnjjgbhhhgiiiifd99531;==%%$@@@@#$%%=;;,,!~(__|_|||33555550999cccdggiiijkjlooommmollkkkffghghkjjnquAAEBCEFIKKKKKKHHIKMNOOONNMNNOPOPQQQQQQPPOPPPPONLLFDxvrmmjga", +"a6}[[[[[::[}22662}}(//<_<__<_}|580fiimomrqqwyAEADDAzAywusmqqqvxzAwtwxyBEHIKKKKEBAwwwxwtwyyAywqmoijijhfhfiijif8853|<<~)),;=%%%#@@@@##$%%*;;,!{/_<<||1|145559709cccffiillllllopprpppppoommiiikkkkkknmuuAAEECEFIKKKKFKFHHKMNNOONNNNNOOOPQQQQQQPPPPPPPONLLHDxvrrmhgb", +"66}}[[[[[}}2288864}}({{(1||1_}|298fgiopprqqvvACADDDzzvvsssqqquxzzttwyAEIIMKIHBAywtttxwwwyyAywtpmlmihehcfiiiff9973||'!~/_<<|||3355999ccdgfgiillllollnoorrpmoqoommoloompqpqttyyEHIHGHKKKKKLKKFFIKMNMNONNMNNOOOOPQQQQPPPPPOOOOONLHFzxvsmhdd", +"8666}222a6bbfeifif92[((/_|<_}}2269dfmmpwwwwwyABEBDEEzxvvtutqqxwxxwyABHIIHHHEEEEEHEEEEEBBABAAytpoliiiighceffgcc8953|;%%$#@++@###$&==;>,!~/<<<<||3335599ccggfiijllnnlloooopppqqpoomomlmmmopqqttyAEIKKIIMMMMMKKLKIKKMMMMNMMMNOOOOPPQQQQPPPPOOOPPOOKLFBxvsmmed", +"86666226bbbccjjefc6|[(((((/(::2669dckkptwwAAAACEGEHEAxxxwstuuxxxxwAEEIIHEHIKIKIIIHIIHIEEBEBAAwppojhfiffcddddc88653|;*%$#@++@@##$%%*;>,){//<<||||355599ccggfiijllonpppppttwwtxwttpttpppppputtwAAEIKKKKNOOONNMMKKKLNNNNNNMMNOOOOPPPQQQPPPOOOOPPPOMLIDzvssmed", +"d86688abcbccehgif86}}[(({{{^:[}659dekoouuwABEBEEEEHEEzxvvwswyDuxzBBEHIHHIKMMMKKIIEHIHIIIHHEBBAwponijijfcccccc98655||<~),>;*%$#@++@@#@#$%*->,,)//<<<||||35599ccfiiillooppttwwwwyyyyAAyywwywwwtxzzyyABCHIMKKMNOOOOOOOMMMMNNNNNNMMNOOOOPPPQQPPPPOOOOPPPOOMIFBzytmme", +"ddba88bbcciikggfc82}[:[{{^]^^::27dffkooptwABEHHGHIEEBAxzvvwwzyuxABBHHHHIKMKKKMKIIHHIHIIKIHHEEBAtpnjffefffcd9c996533|,)~///<|||335599cfiilopppttwwwwwwwwywwwwywwuppppptwwyzABEHMNNMOOOPPPPPPPOPPPPPOOONNOPPPPPPPPPPPOPOOOPPPOOOONMIEAzsmm", +"jjkkkhfhgkmmonkg6a6[::[:[[[:::2}60agkoupuwyABHIKMKIHBDDzzzACAyACEHIKHIIIIIHIIIIHHEBBAEEEEEHEEEBytoifbhcfdcccc9533|||,)~//<<||3355599cffillppptwwwwywwwyyyywyywwwutttttwwwyyABEIMMMNOOPPQPQQQPPQQQQPPOOOPPPOPOOOPPPPOOOOOPPPOOOONMMKGAwtq", +"qnokkkggggillqjg862[}[[:::[[[222788glouuuyAAEGGKNNKIEBBDzzBBAABEEIIKIIIKKIHHEHHEEAAyyAyyAAEEBEBAwpljeedcc9ccc953||||<<~),>;%$#@++++@@#$%%*--,)~/(<||||355999ccfiilopptttwwwwwwyyyyyAAAyywwwyyyAAAAzEEIKMMMNNOOPPOPQQQPQQQQQQQPPPQPPPOOOPPPPOOOOOOPPOOOOONMKGEBwq", +"xuronljeejjjqmhd8666}:[:[::[[22608ggjppuwyAAEEEKMNMIIEBDEBEEBEEHIIKKKIIKKHEEBBBBBAzyywtwwwAEBBBAwpoijedd99cc9953|||<<<~),>;%%#@++++@@##$%*-->)~/<<<|||355599ccffiiloptwwwwywwwyyAAAyyywwywyyAAAAACEHHKMNNNNOOOOOOOPPPPQQQQQQQQQQQQQPOOOPPPPOOOOOOOPOOOOOOMMKGEAA", +"Eywuoljeemmqmmed8aaa}}[[:[:[422a08ggioqqwyAAEEHKMMMKKIEEEEEGGHIIKMKKKKMKIEBAAAAAAAAAywttpuwAABAAwtolifdda8c995531|<<<<~~,>;=%#@++++@@@#$%*->,,~/<<<||||335599ccfiiloppwwwwyAyyyyyyywwwwwwwtwwxyyAEEEKKNOOOOOOPOOOOOOOOPQQQQQQQQRQQQQPOOOPPPOOOOOOOOOOOOOOONKHHHE", +"HHAyuqqmmqqqpmhdd8662}:[:[:2226788glinqqwAAEEEIKMMMMKKKHHHFHHFKKKMKIKMKIEBAABzAAABAAAwxupqtwyAAAwtpoljgd890999541<<<;=%$@++.+@+@#$%%->,)~//<<<|||3355999cfiilopptwwyyywwwyvwwuutttpstquuuxAAAEHIMOOOOPPPPPPOPPOOOPQQQQQQQQQQQQQPPOPPPOOOOOOOOOONOOONMMMJII", +"KHHEwuuqqqwtpkked82222[:[:22}267agglrrqtwyAEEHKKMMMMMMKKKIIIHKMNNMKMMKIHGEABBAAyyDyyyyuupttwwyyAywtpoifd09999953|1>=%$@++.+@+@#$%*->,))~//<<<||335599ccfiillopptwwwwwwwywwwvxxwwwwwwwwyAAACEGHKNOOOOOPPPPQPPPPPPQPPPOPPQQQQQQQQPPPPPOOOOOOONNNNOONNMNNMK", +"MKEEEBAyyywtpkmeda82222222222607aggkqrqvvAACEIKKMMMMMMMMMMKKKMNNNNMMMKEEEECAywwstsstzwuuutwwwwwyywtpplic98999953|<=&$#++.++@##$%*-->))~//<<|||355599ccffiilllpptwwyyyyAAABBAABBEBABBBBEEHGIIKMOOOOOOPOOPPPQQQQQQQPOOOOPQQQQQQQQQQQPOOOOOOOONNNOOOMNNNNN", +"MKIEEEBBABzypmkb0082266689889909ggkjmquvvABBEIKMMMNMMMMNMMMMMMNNNNONKIHIBBzzzxssrrruuuuuputwwwwwywwtolifcb955553|=&$#++.++@##$%*-->,)~~//<<<||35599cccgffiloptwwAABBBEEEEEEEEEHHHHGHHKKKMMNOOOPPPOPPPOPPPPPQQQQQQQPOOPQQPPQQQQQQQQPOOOOOOOONNOOOOMMMNN", +"KKKHHEHIIEAAtmme0088688cccfjiigfkglmnqtvwyBBIIKMMNNNNMNMNNONOONNNOONMIHEEAzxxuuuuuuqusuuttuwtwtwwwwtooiib9955553|<-&&#++.++@##%%*-->,,~~/<<<|||335599ccfiiloppwyABBBBBEEEEHHHHHHEEHHHIKKMMNOOOPQQPQQQQPPPPPPPQQQQQQQPPQQQPPPPPQQQQQQPPPPPPOOOOOOOONMMMM", +"KIJIKIIIIIHBwtmefd9ccffccfiilklqmporqqwvyCAEHIMMNNNNNNMNNOOOOOONOONNKKJEBzAxuuuuuvvqqqqtuspttttwwywwpoliec957533|<-&&#+++++@##%%*-->,,~~//<<|||333599ccfilopttwwyAABBEEEEEEEEIHEEEEEEHHIIKMNOOPQQQQQQQQQQQQPPQQQQQQQQQQQQPPPPPPQQQQQPQPQPPPOOOOOOOOMNML", +"FIIIKMKIIIHECwmmigkilifccffkkllpptupqtvvyCBHHIMMNNNOONONNOOPPPPOPOMMMIHHGAzAxuvuuuvqqqsttqutttwwwyywppliec95733||-*&#++++@@##%%*-->,,~///<<<||335599cfilloppptwwyyAABBBBEBBEEEEAACCBCCEIKMNNOOPQPQPQQPPPQQQQQQQQQQQPQQQQQPPPPPPPOOPPPQQQQPPPPOOOOOONMK", +"KIIILMNNMKEEEAupnomoijfeccgggjomttxxuvyAyCBBHIKMMNNOOOOOOOOPPPPPPONMKIJGECzyxywvuvuqqvsuupuwwwwwwyywtplif9997731<<({~!),,>>-*&$@+++@@##%%*->>,))~//<<<||335599cfiloooppptwwwAAAAAAAAAADBBBAAAAEEHIKMMNNOPPPPPPPPPPPQPPQQQQQQPPQQQQQQQQQQQPOOOOOPQQQQPPPPPOOOOOMM", +"MLIKKMNNNKHCBAxxttqoifbc9dddeekmpuwwyAAyAACBIIKMMMNOOPOOOOPPPPQQPONMKIJJECBzxwwwwwtttvstqstuwwwwwyywwtoifc9973||--**$@+++@@##%%*->>,)~~///<<||355599cfiloooppptwwwyAABBBBBBAAABEDBDEEHHIKMNNOOPPPPPPPPOOPPPPPQQQQQPPQQQQQQQQQQQPOONNOOPQQQQQPPPPPPPOOM", +"LMMMKKMMMKIGCAyBywpokgddd00bbggoostxAAADyABEEIIKMMNNOPPPOPPPPPQQPONMKKIGGGCzzzvvwttttsvsuvttttwywyyywtplicc053|||>-=**$@+++@@#$%%*->,,)~~~/<<|||355559cfiioooopptwyAAEEEBEEBEEEBEEEEEHFIKKMMMOOOPPPPOPPOOOOOOOPQQQQQPPPQQQQQQQQQQQPOONNOPPQQQQQQQQPPPPOO", +"ONMMMMMMKKHEEABABywmkgdd00bbgggmlpuwAAAADAAEHIIIKMNOOOPPPPQQPQPQPPONKKIIGGCCCzDytuutssvtvusuutvwwwwywttoicc973||<>--;=*$@+++@@#$%%*->,,))~~/<<<|||35559cfiilooopptwyAABEEEEEEEEEEHEHHHIIKMMMNOOOPQQPPOPPOOOOOOOPPQQPPPPPQQQQQQQQQQQQPPOOOPQQQQQQQQQQPPPPO", +"POOONLMLIIEEEEEAzwtpmgdd0bbbggllqruwAAAAAAAEHHIIIMMNOOOPPPQQQQQPPPOOMKLKIHGCCAAAxvvvvvvtwuusuttvvwwwwttplic973||--**=*%@++@@##$%*-->,,))~//<<<<||35559ccfiillmopptwwyBBEEEEHIEHHHIIIIKKKMMNNNOOQQQPPPOPPOOOOOOOPPPPPPOPPQQQQQQQQQQQQPPPOPQQQQQQQQQRQQQQP", +"PPOOOOOMIFECEEHAytpppligecbgggnmrqquwwADDAABHHHIKKMNOOOPPQQQQQPPPPOOONKKKIIGCBAAzvvvvvvtwxxvutwwwwwwwwtpoifc95||<-;**%&%#@#@@##$%*-->,,)~~//<<<<||355559cffiikllopppwwAABBBEHHHIHEGJHJJIIMMNNOOPQQQPPPOOOOOOOOOOPPPPPOOOPQQPPPPQQQQQQPPQQQQQQQQQQQQQQQQQQ", +"QQPPPOOLIFBCEEEAywppppoljekggnlrvqttttxDABDEEHGIIKMNNOOPPQQQQQQPPPPOOONKKKIIHGGCCzzzzxwvxxxuuwwwyytwwwtpoifc95|1<--=*%&$#@##@#$$%*-->,,)~~///<<<||335559cffiiiillooptwyAzAAzEEHHHIIJIIIMMMLNOOPPPQQPPOOOOOOOOOOOPPPPOOOOOPPOPPPQQQQPPPPPQQQQQQQQQQQQQQQQQ", +"QQQQPPOMIHECBEAwwwpooppolmmkknnquutuutuwDDEEEHEHIKKNNOPPPQQQQQQPPPOOPOONNMKKKKHGCCCCzzzxxxxxvwvyyywtttwtoifc9531--;=%%$$#@##@#$$%**->,,)~~///<<<||3355599fffiiillopptwwyAAzABEHHIJIIIKKMMOOOPPPPQQQPPOOOOOOLNNOOPPPPPOOOOPPOOOPPQQPPPPPPPQQQRRRRRRQQQQQRR", +"RQQQQPOMKIHCCAwwuuuoooppuqmmqmrruttqqqutwDBEEBGEIIKNNOOPPQQQQQQQPPPPOPOOOOMMFIIHGCzzzAAzzxxxvwyyAAywwtttolfc9531>-*=%&$$#@####$$%*-->,,)~~///<<|||3355599ffiffiiloppptwyyAAzBHHHIIKIKMMNOOOPPPPPPQQPOOOOOONMNNNOOPPOOOOOPPPNNOOPPPPPOPPPPQQQRRRRRRRRRRRRR", +"RRRQQPONMKKCzytuqqtuoooutuqtqqvvutuuuqqquwBEEBGEEIIKNOOPPQQQQQQQQQPPOOPPOOOMKIIHFECzzzAAAzzyyyyAAAywwtttplfc953|>-*%&&$##@@#$#$%%*->>,))~~///<<<|||355599ffifgiiloooppwwyAAABEHHIIKKMMNNOOOOPPPPPQQPOOONNONMMMMNOOOOOOOOPPPNNNNOPPPOOOOPPPQQQRRRRRRRRRRSR", +"RRRQQPPOOMKEAxutmqqutuuquuuwtxuuuuqquqqquwAEEBAECHIKMNOOPPQQQQQQQQQQPPPPPOOMLIFFHEEzAzzzABAAzAAABBAyywttpoic953|--*%%&#@##@#$#$%%*->>,))~////<<<||335599cfffgfiiloloopwwyAAABEGEIIKMNNOOOOOPPPPPPQQPOOONNNNMMMMNOOOOONNOOPPONNNNOOOONOOOPPPQQQRRRRRRRRRSS", +"SRRQQPPOONNHCyputmqquuutupwywyxxwuuqqqquuuyEEEBAEEIKKNOOPPPQQQQQQQQQQQPPOPNNMMKIHHEEDDDDABBBBABEEEBAywwtpoic9531-**%%&#@@#@#$$$%%*->>,,)~////<<|||335999cffifiiililopptyyAABEEEHIIKMNNOOOPPPPPPPPPQPOOONOONMMMLNNOONONNNOOONNNNNNNNNNNNNOPPQQQQRRRSSRRRSS", +"SSRQQPPOOONKEAyttmmqquuuupwwAAyxwuuuuqqquuyAEEBBGEHIMNOOOPPPPQQQQQQQQQPOPOOONNMKIIIHEDAAABBEEEEEEEEBAAwwpoic953|-**%%$#@@###$%$%**->>,,)~//<<<<||3335599cfffffiililooptyyAABEHHHIKMMNOOOOPPPOOOOPPQPOOONNONNNNMMNOONMMMNOOOMMNMMMNNNMKMMNOPPQQQQRRRSSSSSS", +"SSSQQPPOPONKJEAttmmqmqquuwwwAAAzyxuuuqqqquxyDDEEBEHHKNNOOOPPPPPPQQQQQQQPPPPPPONMKKIHHEDAABBEEEEEBEEBBAwwtplf953|-*%%%$##@###&%$%**->>,,)~//<<<|||3335599ccfcffiiiilopppwyyAAEEEHIKMNNOOOOOOOOOOOPPPPOOONNONNNLMMNONNMMKNOOOMMMKKKKMMMMKKMNOOPQQQRRRRSSSSS", +"SSSQQPPOOOMKIHEwutqqqmqqwwwwyAAAAyxxuuqquuwyyABEEEHIKNNNOOOOOPPPQQQQQQQQQPPPPOONMKKIHHBBACBDEIHBBABEBAywtpoic95|<-*%%%$##@#$$&%%%**->>,))~~/<<||||||3359cccfcffiiiloopptwAAAAEEEEIIKMNNOOOOOOOOOOOOPPOOONNOMMMMKKMNNMMKKKNOOMMMKIHHKKMKKKKMNNOOPQQRRRRSSSS", +"SSSRQQPOONMIIHHAwwwqqqqttwwAyzAABAxxxuuuuuwwwyABEEEIKMNNNNOOOOPPQQQQQQQQQQPPPPOONMMIIHEEBCCBEIHBAAAABBywwppif953|-**%$$##@@#$&%%%*-->,,)~~//<<||33333559cfffffiillloopttwyAAAEHEEEIIKMNOOOOPOONNOOOOPOOONNMMMLMIKMNNKKKKKMNMMMMKIEEJHIKKIKKNNNOOPQQRRRSSSS", +"SSSRRQQOOMKKHHEEywwwyywtttwAAzzABAzxxuuuuuxwwyyAEEHIMNMMNNNOONOOPPQPQQQQQQQQQQQPOOMKIHHEGBAEEHEBAAAABAAywtplfc53|>,))~~//<|||3333559cffiffiiilllopptwxAABBCEHHHHIKKKMMNOOOOOOOOOPPOOONNMMMMKIKKMMKKKIFMNMKKKKIHEECGHHIIKMNNOOOPPQRRSSSS", +"SSSSRRQQPMKFEGCByywwwywtppzAAzzDEBAzxxuuuxxwwwyABEHIKNMMMNNNNNOOPQQQQQQQRRRRRQQQPPONMIHEEEEEEEEEAAyyAAyyywpoic95||//~),--*%$$##@@@$&&**-->>,))~~/<<|||3335599cffffffiiiillooptwyABBEEHHIIIIKKMMNNNNNNNNOOPPPONNNMLLMKIIKMMKKIFKMNMKKMKFHEECCCEGHIKMNNOOOPPQRRRSS", +"SSSSRRRQPOMMIGAzAyyywwwtuxwxzAAEDAAAzyxxxxywtuwDBEHIKMMMMMNNLNOOPQQQQQQRRRRRQQQQPPPONKIIIHHEEEGBBAyywwywwwtpif993|-*%%$##+@@$%%*--->>,,)~~/<<||333355599ccfccfgfiiiiloopptwAABEGHIIKKKKMMNMNNNNNNOOOPOOONNMKLMKKIKMMKKIIIMMKIKMKFEEEzzzzCGGIKMNNOOPPQPQRRS", +"RSRSRRRQQPONMICAAzyAywwtxtttzABEEEAAAAxxxzyxuttxBEIKKKKMMMMMNNOPQQQQQQRRRRRQQPPOOOOPONKIHIIIHHEEAAyytwwttttplfc953|**%$##+@@#%&---->,,,)~~/<<||3|3335559ccc9ccffifiiiloopptwyABCEHHIKKMMMNNNNNONOOOPPPOOOONLMMKKKKMMKIIHFKMKIKKKFFFEzzzzzzEEHHKNNOOPPPPQQR", +"RRRRRRRRQPPONKHBzAzyAyzywttxxAEEEEEAAAAyzAyxutuxAEIMMKKKMMKKKNPPPPQQQRRRQQQQPPONNONOONMKIIKIIHEEBBAwttwttppplfc953|<--%$#@@#$&==--->,)))~~//<<||33333559ccccccdfffiiiilnrptwyyAEEHHHIKMMNNOOOOOOOOOOPPOOONNNMMKKKMMMKIHHFKMKIFKKIFHEzzzzzzCCCGGINNOOPPPPQQ", +"QQQRRRRQQQPONMIEAzAzBBBzywxxuzBEHDEDAAzAAAAxuuxyABIMMKKKMKKKKMOOOOPQRRQQQQPPPPOONNNMNNNMKKKKKIHEEEBywtttpppolfc953|>-%%##$&&*-->>>,))~~~~//<<||3333599ccfdcffcfffiinnrpttwyAABEHHHHIIIKMMNNNNNNOOOOOOOOOOOOOMKKMNNKIIHIKKFFHIIIIHEBzzvxxzCCCCGHKNOOOPPPQ", +"PPQQQRQQQQQPONKHEAzAABEBAzxxwDAEEHEDAAAAEBAxxuxxzEIMMMKKKKLKMMOOOPQQRQQPPPPPPPPOONMMKMNNMKIIKIIHHHBAytwtppoolic953|>-*%%$$&**;>,,,,))))~~~//<<||335559ccfccfffffiilnlnpptwyyAABEEHHEEHHIIKKKMMMNNNNOONNNNOOOOONMNOOMIIEEHIIEEIIIHIIBzzzxwxyzzCCCEKMNOPQPP", +"POPPQQQQQQPPPONKHEAAyAABBCAxwyAAEDEAAyzAEECzxxxzAEIMMMMKKIKKMNNOOPQQQQPPPPPQPQQPONMMKMNNNMIIIIEHEHEBAwwttpoolif953|>-*%%$###%=;>,)))))~~~~//<<|||355999cccccffffeiiiloppttwwwAAAABEEHGEGGJIIJIKKMNNNONMMKKMMNOOOOOOONKIEEHIHBEHIIHIICzzzwwvvvvyzzCCIKMOPQP", +"POPPOOOPPPPPPPONMKHAzxzzBBCzzyADEDDBAyAzBEEAzxxzAEKMMMMKIIIKMNNOOQQQQPOOPQQQQQQPPONMKKNNNNKIIIEHEEBAyywtwppoolic933|<~))>--*%$#++@#%*-,,))))~~///<<||33559cccffccffcfeiiilloopppptwwwAABBEEEHJHHIIJIIKKMNNOOMKIIKKMNOOOOOONMKIIIKIGCGIIEIIEzzzxvvvvvvxyzCCELNOPP", +"POOONNMNOOOPPPPOONMHAxxyzAACAzADDDEBAzAABCCBAzzzAEKMMNNKIIKKKMMOPQQPPPPPQQRRRRQQPPONMMMMNMMKIHHHHBAAywtttpooolif955||/~),>-*%#@++@#$%=->,,,,))~//<||335599ccfffcfffffiiiillllmmooqssvyADBEHIIHIIILIIKLKLMNNNNMKFIIIKMNOOPONKKIKKMKHGGHEEHIECzzvvwvvwwvxyAzCHMNOO", +"OOOOOMKIKNOOOOPPONNKBwxwxzABCzAABBAAAzAACEBBBAAzBHKMMNNMIIKKMMOOPQPOOPQQRRRRRRRQQPPOOMKKKMMKIHHHEBAAAywtpoolllifc9953|/~),>-%#@+++#$%%;>>>,,,))~/<<||335559cccccffffiiiijliiiiillmqtwwDABEHIKKKIIMKKKKKKMMNNMMKKKIIKMMNOPPNKIIIKMIHEGHECEHECzzxxwvvwvvwzyyzCIMMN", +"NNOONKIHIKMOOOOOOONMIBwxwwyACCCBBEAyzAzAEEAABBBBEIKKMNMMKIFKMNOPPPONOPQRRQRRRRRQQQQPONKIIKMKKIHIEEBBByywtpoiiiffc9553|'>,)))~/<<<||33555999ccfffiiiffffgfggkkmmqptwyDBEHIIIIIIIIIKKKKIKMNMMKKKLKKKMMNPPOMKHEIIIEEGJHHHHICCzwwvvrrrppwyzzCGHKK", +"MNONKIHJEHIMONNOONNMKEAAxxwzACBCBBAzzAzBEEBAABEHIKMMMMMMKKKKMNOOOOMNOPQQQQQQQQQQQQQPPOMKIKMMKIIIHEBAAAyttpoiiifc9953|<-%#++@#$%**;>'',){~~//<|||33355999ccfffffccfccccggkkmoqqutwyABBEEHHIHHHIIIKKKKMMKKKKKKKMMMMNOPONMIHIIHBCBEIJIIIECzxwvqrrrrrssxzzGGEI", +"KMMMIIHEEEHKKNNNNNNNKHEAzwxwyCBCBBAAyABBEECAAAEIKNMMMMKIMMMMNNNOOMMNOPQQQQQQQPQPPQQPPONMKKMMMKKKIEBAAywttpoiiifc995|<*%$@+@#$%%*->''){~{///<<||||3555999cfcccccccccccgggimmpquutuwyABBEHHIIIIIIKMKMMMMMKKIHIKKMMMNOPPOOMKKIHDzABEEIIIHGCyvvqrrrrrsssvzBCCE", +"EHIIIIHEEHHEHKNNNNNNKIEEAAwwwyACBCBBzCCGEBzACAEINONNNMIIKMNNNNOONKMOOPPQQQPPPPPPPPPPPOONMMNNNMMKIEAyywwtppoiiffc9953|<~),>*%$#+.+@#$%*>>)!~{/(/(<<|||3355599ccfccccc9cccccgggkkmmqqqqutuwyBEEHIKKKKKKMMMNNNNNMKKIIIKMMMNOPPOOONNKIDzzzACEIHHHEAAussrrrrssstzBAzC", +"CHHGCEHHHHEEEEIMNNNNMKIEBBzwwwyABCBBBCEHHBzzCEEIMOONNMIHKMNNNOOOMMNOOPQQPPPOPOOPPPPPPOOONMNNNNMKIEAywwwtppoliffc953||/~),-*%$#+..+##$&*>,){~//<__|||335559ccfccccccccfcccfggilmoomqquuxwyAEHIKKMMMMMMMMMNNNONNMMMKKMNNNOOPPOOOOOOMEBAzAzBHEEGEEBwtsummmmssswCAvz", +"CEECCBEEBBBEEEEHKNNNNMKIEBBAwwwyAACBEEHIIEAAAEHINOOOOMIFIMNNNOOONNOPPPPPOOOOOPOOPPPPPPOONNNNNMMKIHBywwwttpoliifc953|-*%$#@++@#$%&*>>,!)]~(((<|2335999ccfffffffffffffkilooooppptwxzACEEHIKMMMNNNNNNMMNNONNNNNMMNNOOOPPPPOOOOONIEABAABGEEEEEBwwummqqmmmtwwzvz", +"ABBAzCABBAABBBBBEINNNNMKIHEEAwxwxzzzBEHIKHBBBEKMNOOOOMIIIMNNNOPOOOOOOPOONNOOOPOOPPPPOPOOOONMMMMKIHEAywwwwtpliffc933|-*%$#@++#%%=*=>>,!~{](/__<|335999cccfccffffffffiiloloppptwzAABEEEEEHIKKMNNNNNMMMMNNNNNMNMMMNNNOPQQPPPPOOOMHEBEEEHGCCEBzxxwuuuqqmmqwwtwv", +"AAAzwwyABAAAABBBBEIMNNNMMKIEEAxwwwzzyBGHIHEEAEIMNOOOONKIKMNNOOPOOOONNNNNNNNNOPPPPPPPOOOOOONNMKMKIEEAywwwwwtplic9553|-*%$@+.+@$%**->,'!!~]/<__135999ccccccccfccfccdfiilllopptwyAAAABEEEEHIKMMNNNNMMMKMMMMMKKKKMMNNNOPPQPPPPOOONKIHHHHHGCCBAwttquuuuqmmqquspv", +"wwusuwyAABAAAAAAAAEIMNNNMMMKIEAzxwzzyyAEHEEEAzEKNOOOONMKKMMNOPONNOOMKKKMMMMNNOPPPPPOOOPOOONNMKKKIEEAywwtwwtpoifc993|*$#+. .+@$&%=->,,']/<<<1|5cfffccccffffffffcdfiililoptwwyyAAAAAEEEHHIKMMNMMMMKIIKIIIIIHHHIKMMMNOPPPPPPPPOONMKHIIKIECBBwtuqquuuuqqqqqssu", +"wwssstwyABBAAAAAABBEIMNNNNNMKIEAAyzAyyAEEEEECABHMNOOONMMMMMNOPONNONKIKKIKMMONOPPPPPOOOPOOONNMKMKIHEBAwtpttpoliffcc93|,')]]_1||79filiffffiiiiiiiiiiilllopttwwwyyyyyAEEEEEEEIKKMMKKKKIIHHHHHEEEEEHIKKKNOPOOPPOPPOONNKKKMKIHEEwtumqquuuuuuuqtsw", +"wwtssttwyAAAAAAAABBBEIMNNNNMMKHByzyAAAAEEEBBAACHKMNNNMMMNMMNOPOMNNMKIIKFKMNOOOPPPPOOOOOOOOONNMMMIHEBAwtpppplifcc99953|,')]_<1359dfifcfiilllliiiiiilloopwwwwwwwwyyAABBAAAABEIIKKKKKIIIHEHHGEBBACBEHEEIMNMNOOOOOOOOONNMNMKIHEAwtmqquuuutxxqmtw", +"uqmmmmstwyyyyABAAAAABEIMNNNMMKKHEywwwyyAABBBBBBHKMNNMKKNNMMOOOONNMKIKKKKMNOPPPPPPPPOOOOOOOONNNMMMIEAAwtpppplfc99553333|*$@...+#$&%*;>,')]_<|359900009dfiiiiiiiiiilooptwwwwwwwwwwyywwxxxzzAEEIKKKKIIIIHIIHEBAAzzCABEHKMKIKNNOOOOOOOOOONMKIIByuquuuomnpzyuqqu", +"uqmmmmmmswwtwwAAAAAABEHKMNNNMKKKIEAwwyABAyyABEHIKMMMKKKMONNOOOONNMIJIKMMMNOPQQQPPQPPPONOOOOONNMMKIEAywtpppolif955||<<<*%#@@#$%&**-''')~(<}357527755799ccffffilloppttttwwttppttwtttutxxxABEEIIKIIIIIIKKIEEBAAAyAABHKMIHIIKMNNNOOOOPPONMKKEEzyyAtrnnrtzxuuu", +"uqmmmmmmmsttuuwAAAAABEHHIKNNMMKKKIEAAABEBAyAEHIKMMKKKKKMNOOPOOOONKIIKMMNNNOPQQQQQPQPPOONNOOONNMMKIHAAwwpppplifc95||<-*%$##$%*;>>,,))!~](<|35772447777709cccfiiopptptttttptppppuwwwwwxwyyAEEEHHHIIHHIKKKHEEEEAABBBHMNMIIIIKMMMNOOOPPPPOMMIHEEGEytnlopxxuux", +"xqmmmmmmmssssstyAAABBEHHHIMNNMKIHHHEBABEEAAAEIKNMMMKKKMMMOPPOOOONKIIKMMNNNNOPQRQQQQPPOOMMNNONNNMKKIEAwwttppoifc953|-*%$#@++#%*>,,~~~~///<|2552243277777090ccgiloppopttttppppppptwyywwwwxxADBFFHHIIIHHIKKIEEEEABEEEHMONMKKIIKKKKNNNOPPPPOOMKEEHHEwprptxuuxz", +"xuqmmmmmmsssssswyABBABEHIIKNNNMKHEEEAwwAAywwAEMNONMKIKMNMNPQPOOPOKIIKMMMNMNOOPQQQQPPPONMKKMMONNNMMIHBywwttpolic953|-%$#+. .+@$=-,)~//<<11555575a7657509099cgfiooolopppppoloppptttwxttuuuuyAEEEEEHHHEEHIIIHEEEBEEEEHIMNMMKKKKIIIKKKNOPPPOOONIHEEEAtpptpuuxy", +"suuqqmmmmpspssutwABEBAAEHIKMNNNMIEACAwwwwwwwyBINOONKIKMNNNOPPOOONMIIIIIKMMNNNOPQQQPPPONMMKKMNNNNMMKIEAywttpplic953|*%$#+. .@#$*->,!~]<149999909a888999ddcffilollloppooooopptttppprqpuuuuwDEFEEEEEEEGHIKIIIHHEHIIIIIMMMMMKKMKIIKKIKNPPPOOOOMKHEEBwtttppppt", +"pnuuqqmmmrssusttyABEEBAABHIKMNNNMHEEEBywwtttwAEMOOOKIIKMNOOPPPPONMKKIIHIMMNNOOPQQQPPOONMKKIKMNNNNMMKHEAwttppoif953|-%$#+. .@#$%-->,)~/<|56596999cdccffggiilooliloppooloptttutpollqrqruquwAEBBDBDDABEIKMMKKKKIKKMMKMNNNMNNMMMKKKKMKMNOOOOOONNMIHAwwwwtpppp", +"njnquuqmmsssupuwBCEEHHHAABHIKNNNMKIHHHEAwtuttwBINNMIIIIMNOOOPPPOMMMMIHGHIMNOOOPPPPPPOONMKIIIKMNNNMMKIEBywppooifc53|-%$#+. +@#$%-;;'!](_||322565599gfffiiloppolllppplooptwwtpollllprprqquwABAAADDAABEIMNNNMMMKKMMNMNOONNNNNNNMKMMNNMOONMNNONOONMEwtwwwtppp", +"njhqqquqqssspuwACBBBEEHEAAEHKKNMMMKIIIIEypopptyEKKIEEHIINOOOOOPONMMMIGEEHKMOOOOOPPPPOONKKKIHIKNNNNMKKHEAwtpollic953<*%$#+. .+@#$*=;>,!](_<}}|346769099cfiiooppoilpttppoptwwtpplllooprrmqquyBADyDxxyAAEIMNNNNMMMKKMMKMNOONNNNNNMMMOOOOPPOMIIIMNONNKAwwwwuppp", +"nhjjmqquwttpsvwzABAwwyABAABEIKMMMMKIHEHEBwtptwAEEEHEEEHIMNOONNPPNMMKIGCCEFKMNNOOOPPOONNMKKIIHKMNNMMKKIEAwtpollif993|-%$#@...+@#%=-;',](_<|:|||776599989fiilooliiotwtttptwwttpooooollqrqquuABADxtuxxzAEIMNNNNMKKKMMMIIMNNNNNNNNMNNNOOPPQPOKIEHKNNNMIEBwutwtq", +"pjhemmqqwwwuvxwtwywtutxAAAABHKMKMMKKHEAABywptwAEHEEHHIIIKNOONNOONMKIHGCCBHIKKMNOOOOOOONMKKKIIIMNNNMMKKEAywpollifc953,)](_<1:}|4114700099filoolffiotttppttttppoopooolnqqvvuxABDxuuuxxxzGKMNNMNNMMKMMMHHKMKIIKKKMMKNNOOPQQQPNKGEEIKMMKKIBxuwxu", +"qnjhmmmqwwwwypsuwywtpqtwyAAAEIKKKMMMKEAAAtpptwAEEEEEIKMKMNOONNOONMKHEECCBGHIIKNNOOOOOONMMKKKIIKMNNMMMKHEAwtplliifc93|-%$#+..+@$&--')]((<<_1}|114770799cfilolfffiopttpppopoooopoolmllrvrruxEBzuxuutwwxBIMNMMMNNNMMMKEHKKKHEEHHIIIMNNOOPQQQOMHEEHHHIIKMKBywxx", +"uppnqqmmtwwwxtsmquuqmmmmwyyyAEIKKKMMMIEBxqoputyBBAABEKMMNOPONOPOONKIEEEBCGHHIIKMNNNOOOMMMKKKKKKMNNMMMKKEAywpoliifc953*$#+..@#&=;>,]((_::<|_114470770dflooiifcgmppppqpoiigglmolikjiimmnruwAAxussvvupptyHMNNMKKKKIIHHEIMMKIIIIHEABIKMOOPQPPONKEEEAtuwEIKKKHA", +"AwwyAAxwwuqqquuqlnnjmhmmmqwwwwyAIMMMMMKKEumlptABywttyAAHMOPPOOPPONKIJECCCEHIIIKKKKMMMMMMMMKKKMKKMONNMMKIHBywpoiiffc953|/),>*%#@.+@#&=->){((___<|__14770070cilpliggdflpppppplggggkoolikikjnmmqqwAAxsstunqqpptyEKNMMKIIIHEEEIMNMKIIIIEAAEIMOPPPPOOOMIHEAumotAEKMMH", +"HBAABAzAyqqqqnorooonjemmmqqwwwwuAIMMMMNMKApopwBEAwtttyyBINPOOOPPOMIIHGECCEGIIIKIKKKMMKMMMMKKKKKMMNONNMMKHEAytpoiffc953|<~),-%$@++#&&->'!{(((___|__1477770dgimoliiddglloppoigggggkkolikjkkmmnqqtwyzutvoonoppttyEIIKKKIIEEEBEKNMKKKKKIEABIMOPPPOOONMKKKHwolootAIMM", +"KHEBCAyxuuunnlmmmmmkifjjqqpwywwquCIMKMNNMHytpwBIHAtttwyAEMOONNNONKHHHJGBBGEIIKIIIIIIIIMNNMMKKKMMMNOONMMKIHBAwpoiifc955|*$#++#&*->!{{(((__<_[_1}23246dklopmliddfiilllifc9agkkiollillknqpuuuwxxwunnoookkmqwABBAEHHIHIHHEIMMMKKIIIHEEIKOOPOOONNMKMMKEwpojipyIK", +"IIIHEAzxxrookkmmqqqmkgjjjqquAyywqwBIKMNONMHAwtBKMHytuwyyEINNKKMMMIJEEEGBCEHHHIIIIIIIIIKMNNNMMMNNNNOONNMMIHEAytplifc995|*&#++#%*>'!{{((::___[_1}34226bkmppoliddciiigifc9a8akmkkollllmprsuuuuxwzxrnnkkkkmmqtwywwyyEHHIIHKMMMMKIHHEEEIKMOOOOONMMMKMMKAwpiiipyG", +"zEIMICztppmkkfjiloppmkkjjquwAAAyuuyEHMNOONMIBAEMNKBttttwyHKKIKMMKJHEBEEECCEHHHHIIHHIIIKMNNNMNMOOOOOOONNMKIEBywpoifc9953|/~)>-%#+@#%-''{{({](<:<__:<}3222adjouuqligd9fiddddd9aaakmkglolmomrqpuuuuuuyttqkkmmmmmmtwuqtutuAAEEEKMNMMKIHIHEEEIKKNOOONNMMMMMKIEApfhlpx", +"uyEMMJAwqqmjeecbcfopomkgjnwwwAAAuutABHMNOONKIHIMNNHwppptwEIIEHMMIHHEBCBCEEEEHEHIIHHHIIIKMNMMMNOOPOPOOONNKIEEAwtolicc953|<~),;*$@@$=;,){(~/]<:<:___:}422269iotwtmig9acgddgdd0788cmkgloooomqqqqsuvuswtwtmmmmkjmmuwuqmmppuwwyABIMMMMKIIHEEEIEIMNONNMMMNMMMKIIAoooop", +"mpwHIKHzuomiec9abbfiolkggluuuwyAAtuuyAHMOONMKKKKMMHypqptwEIEEEMNIEBEEAABEGEBEHHIHHHHIIIIIKMMMNNOPPPPOOONMIHEBywpolfc955|,!~(](/(:<::__<}211179iotxwpmg9a0ggggfd07a8cmkggoooooqrmqquurrtpwtuqmmmmhjuwwuqmmmutuwwxCIKKKKIIEEEEEEIIMKKKIKKMNNMKKKIAttpm", +"mmpwBHIEApmkifba88beinikglnqquwyAwuuutyEMNNNKKKMMMIBtomqtEIEEEMMIEABEBzAEHEBBHHIIHHIIFIHHIKMMMNOPPPPPOOOMKHEEBytpolfc953|<~)>;&##%->))~(]//<*%%*;,){/]/**;,)~((/::<<<<<_::11211147dipwAAztlgdddccca0008aemkklooputxussuuuuorpkmmqoppptwyAyttpuuuxxxxCEEEBBAABBBAAwAEHEywwwyAEKMMMMMMMNMI", +"KGzpooptAEBwpiif9a6aceiinqpnuuxAAAByxtopxEIKMMMNOONMIAwqtyHHEBEEEEEBABEEEHIIHEHKKIIKKMKKIIKKKMKKKMNNOOOOOMIEEAywwtoigc9953|-;>)~/(_||||1||__}|14434}470dkpyzEAzulfhffffgdddabmmmkkorppwyyxwuustprmmmmiikillmptplnjinqqqquAEEBEAwwwptttwAIHAtlilptwyAEIKKMNOO", +"NMIBwpiiiowEEAtliff98biilotwwAEIKIHEAywptyBEKNNNOOOOMKEywAIKIEHEEEEAAyAEEIIKKKIIIIIIFFKIIHIIIKMMKKKKMNOOPOMKEEyywtpoifc0531,!~/<_|}|___<_<:_<1422}}2770cilpuxwwwtplifggikmmmmomkoloouuwAABAAAwtmkkkbbbcdgmtplggddeijjnpwwvttqmoollllltABAwpoiillfflttyBIK", +"IKKIEAwpicccmwBBxpllliillootBIMMKKKKHHEAyABEEHKOPPONNNNNIIKMMHEHHEEBAywwyAEIIIKKHFEFFEIIFHIIKKMNNMKIKMNNOOOOMKIHBAwtpolid571_/';=;,)~/_<|}|<1<<__((<14222227770bhkmoptttupolkgjimmqqqqmkllmmppwAABBBwupkkkbbbbdglpumgddddgkknpxzwwwqlolnlifipyAAAwpolllifioopyBH", +"BHHHEEAtof57dipyypoiiillllotzHMNKKKKKKEEABBBEEINPPPONONNMIKMKEBEEBBAwwtttwAHIIKKHBBEEEFIIIIIMMOONMMKIKMNOOOONMKHHBAytpoifc96}_!;=;,~/<<||||11<|__::_1}222227777abdgekloptttpqmlimmqpqqqknnnorppwyAABwtpkkkkbbb0glppmgdddggmmmuwAAywtolnllecclwAAAywpoopoiiiiltyA", +"twBEEEByti0730gmutpiiiillilotCKMKIIIKIIEEBBAABEKOPPONMNNMIKKEEDAABAywttpptyEIIIKHEABAFGHIIIKKNOONNNMKKKMNOOOONMIHBAAytpoif952_!-;'!~/<<|||21|1|__:___}}22227777880888bfioopputpoqmmmpqqmomnnrppuwyAzAtpmkgkhcb0dkoqmgdddgkmmmqtAAyywooooif98fotyywwtpopplifcioww", +"optyBEBAxqf5347dltwoiiiiliifowEKKHEAEEHHEEAyyAAHMOPONKKIIIIIEBAAyABAwtuuqutAIIIKIHBAzACFHIIKKNNOOOOONKKMOOPOOONMIHBAywtpoif97:);;')~/<|1||3114|<1:[_[1}12267000a0aaa66aadfloqutttppommmmprnoopqpwxwyywtpkkkfehddkmqmggggkkkkkmqtwwwpolollic89ilotwwwtqptpoiccipp", +"oilpwABAAuld3||7dlutoiiiififioyEIJAwwABEHEBywwwAINOPNIEHHHIIEAyAyABAwqprpptyEIIIIHECzAABEGHIKMNNOOOOOONNOPPPPOONKIHBAywttlif5}{';'~/<1|1453442|11::___:[}227000bdaaaaaa6a8cfkmutwxtuqmmmqprnnopptwxxzzwtmmmmheedgmpmkbcfffbbbeipttopllillif99fcipyywtpopmpof9flp", +"liilptAAAyuid7|47dmwtoiifffbilwAEEAtppxAEEEAwpwAHKOOOMHCBEIIIBAwwAEEwqmprptwEHHHJHHBzzzzABEEIKNOOOOOPPPONOOOOOONMKIEEAywtpol92[,'!~<<|347555333311:___1:[}47770008a6aaa66a0adglowwyxuupmpppronpppwxxwywwtmmqjjedgmoojeeehbbbbhfoooooljfiiifccddcowywpilommplccil", +"iifilptyAAytmf0770itzwpliiifcipwBEypolqtwBHEwppyEKNOONKBABHIIEyywxAEwumpqqtwAEHHEHHECzzzzzCCGKNOONNOPPQPONOOOOOONMKIEEAywtpof7}!!~(||355055957|211}}__1}[}447787066aaaa8668a0degmuwwxwwuttppqrqppwwwxxywwqqpllidgkmpjffhfb9bhbfiopooofccffcb50ccitAypiglllppiffi", +"fifiioqtyAAzwpmd77dmwAwmgiiiffotAAwtoiilpyEIBtotAIMOONMHyABEHHAtwwyBytqppruwAEHHHHHHECzzzzzCCGKNONNNNOOOONONOOOONNMKHEBAAwtpi93:~/1435990999577314}}1111}44247a76222666a6868ddbkkmquuwwwywttpprrqxxxzxwtwpqqqonggkmqljfeea8bbb8elponifccccc770dcfpywoffiiklpolii", +"iffiiimptwAAAyulc0dkuAAwoimoilotwwtplifcipAEIAtpyHKNOONKBwyzEEBxwwwAxwutrpptyEHIIHHHHECCACzCCBHMNNNMKKKMNOONOOONONNMKIEBAywplc|:~<|7599cddcc099544}22114244477776}22226a66a8ddekkkkmmquwAzywwupqqwwxzyxttwuutlliggmqoiiheb8ba88clpoolibcccc5750dfltwofdfifimpppl", +"iccfffgouwABEEBwpifipwAAwpppqppwyytpplffeioyHIAttBIMNONNIywAAEAzxtuwwwuwsrpuwBEIIHEEEEGBCCCAABEIMNNMIIHHIKNNNOOONNNMKKHEBywpid3]]<|5559ccdfcc9a90772244444477776622222226268ddekkkkkkmmqwAAAywttpwwxzzzytwquuojigkmooljieb8a888ciopoli999cc95|399fowpf9cfdglotwt", +"ofcfiiiotAAEEHHEApliipwAAyttttpwAytpppliccipAIIytyHMNOONMEwyAEBAwwwzwxuytprptyBEHIEEEEEEBAAzAABHKMNKHHHEEGIMNNONNMNMMKKIEBypli5::|35099dfdgbc0d9975224477777787a2222[}22622a00bkkkkkkkmmtwyAAAywtwwvxzzzwuwqtuljkkmmoliifb678889fopliic88c097||59clwwofcfccilqww", +"wlfiopootyAABEHHEwpiiiowAAytututyytolopoiiiltHKHzwEKNOOONKAwAEEAyyAzwtuwwtrrpwABEEEEEEHEBAzAzABEEMOMIEEEBGGKMNONNMKKKKIHHEAwpic4}6599ccfffgfc0dd9706657777777776222}1}16666800bkkkkkkkmmpputAAAAyAwwxzzyytuquuoojkmmooiihc666888elpllic9999951|45clwywpif99cgipw", +"BypopppoptwyyAEEEAtmifglwAAtpqptwAwlcfiooifflwIIEABKNOOOONIAABEEwyyAwuuwywpppswzAEEEBEEHEAzyzzAAEKNNKEFEBCCIKMNNNMMKKKHHEEAtoib5|609cgiiiliiecdd0000675777708066266}2226a66800bkkkkkkkmmqpuqwwAAABAzzxywyttqquppoklmqoljheaa68aabjplllic99055|||5fotyAwoi9599glw", +"EEypoppplotwwyAEEAwplf99itzypompwAwofcfqoliffoAIIEAHNOOOPOMHABHHBvxwuuutxwtppptwwAEEEBEHECyyvwwzBHMMMIEECCCHIKMMNNMMKIIIHBAwpi81_}599fgiklliifgd9c006665500cb0aa6a4242228aa8dehkkkkkkkkprqrsstwyACBAAzzvxxttquxppmmoppojifb666aabfolloic99575|1|5iptyAtoic509clw", +"AEAwpoppootwAAABEBAyulf99iwzwpllpyAtf9ioolkdfipAEByBKOOPPPOMHBHKHytwtuquttwtqqtwwyAEEBBEHEAytwwyAEIIKIEECCGIIKMMMMMMMMIIHEAwpj82_|290cggiiiiifdcdc90d0899bcfdgc9807a666a8a8bghemkkkkkkkrrrqpuuutwBEEEEAzvxtwquxttpmppppniee866a88elllllf997553115iptwAtliiccfilp", +"pyAAtooppopyEEEEBEBAwpf979iuxulgipyti9ciolffcdipABAwENOOPPONMIHKKBwppuqqutuqmmpswwyBBEBEEHEwxwwwyzABHHEEEEHKMNNMMMMMKKKIEEAwpj9}}478dcggfiiiifdchd00d09cdfffggeff9b99999fccfhjmmmmmmkkkprrrpruptyAAGEHEzxwttquutttqqttpojfeb668a8ciillif885553335fpwABApoooliigi", +"otwwwpoppptAHIEBAAAzwpg5413guuogditwlc9cillfc0cipyAyAINOOPOONKIKKIAtppopttupqmmqqwyABDBBEHEzxxwyuxzAAEEEHHIKNOONMMMMKKIIHHBwpj8}[458ccfgiiiliifhfffdggcfffiigffffcc9dcccffhimnqqmmmmmmprqrrrrrqqwvzCGIIECzwttquupttttxwplfehb6a88bfllliic885557339lwABEAwwtoic9f", +"loppxwtpptwyEHEyxwwwwpk0|<_4gqpicfpwticcktttld9dltAAAEKNOOOONMKIKIEwttppppptqmmmquuyABABEEEByxxzuxyzzAABHHIIMNONNNNNMKKKHHBwulb}[659cffiiilllikiiiigkkfffiiigc9cc8956aa9bfgimouuqqqqmmpprpprrrrrxxzzBIKHGAzttqqupptuwwwtnifhbb6a8aclloiic9959994}6ftwAEIHAticccf", +"filotAAtpwwwAEEAwwpppqmd4_/<9kqofcmyApifoAAAwof9iqwBAAHMOOOONMKIHKHAwuttttttpolmquuuwABAABEEAywsuxxyxwAAFEGHKMNNNOONNMKKKIEAtqc6}6addfgiillolllmlilikikffffdd96622|2327689ahknqquuuuqttutrrrrprtvwxzAEIHHEAttuqquppuxAzypjfhbbb888bioollfc909954[3cpwAHKHyof9ccc", +"ciiopyAAwtttwBEEAwpoomif5|<_49mqkfiwytiipAAAAtlfcfpwBABKNOOONMKIHIIBwwwtutwwwtooouttuxBBABEEEAuuuuxzxuyyyCBGKKMNNOOONNMKIIEAtqh6669ddfiilmmpooollilffffg9bc0d056}}:}[}2}a68dhhmnmqpswwwwtttuprrvvxxAEDEEGGEBwtmqqopstABCyoifbbbb88bfllollfcfd95333cpAEIHBtlfccc9", +"9clpptAEAwttyEEEAwpmkmmg93<<<|9mmgfmwwoiotwttwplccfqyAyBKNOOONKHHHIHAwtpttwyywttppttuxAEEEEEEExxxxxzzxywwAzCEIKMNNNNNNMKIIHEzrk86abfiikllmpqppomlmiigffgf9906622}}[[::[}66addbkmmmmtttxvwwwttuwvvxxzBFEEBCEEAwqmqqnotyEIEwmhbbbb888cipopoiff995756cpEHEytpliif95", +"5cloptyEHyttyBEywpoomlmld7|_((|dolcfqupllliilptpicfipyyyEMOOONKIEEHIEwtppptwwwwwwyywwyzEEEEEHBAzxxxzzyxywAAzCHIMMNMNNMMKKIHEzxk86bhilllomppppppmllilgggig997a222}}}_[[:[22adbbkkkkrrquttwwwwvyxvxxyDBEFEBzCEAAwqqqooptBIICtlgbbaba8biooptofcb90799ftEEypopplifc5", +"69iotwwEIEwtwyAtpooomopplc51_(/3goicippliiiflpttpfciowAyAIMOOOMIBABIIBwoilpttttyAEEBAACEIHHEHBBAxwyzzAyAyAzzCFIKMMKMMMMMMMIHBxnd8bjilooopppppppmloiifgkkica76222}}2}}[[[2280bkkkrrqrrrrpttwwzzzyzxzDDEFEEzzAEBAuqqqoppxEKHymkggbdb88fltttof990900flwBAtiiopoifc5", +"59fopwwAHKBwtwwplmllmoptpod7|>>->!<1<(_||||/~/4cilkggiddfoxAtpic7||3fpAEIKMMKMKIAwyHKMNMMKIBAywoilpwwwtpotAHKKNNKHBABBAxwuwACEIKKMMKKKMNNNOOPPOONNMNMNNMMJIEDDzxvvtuwwuuuuunokkhebbbddehmmqwwvwzzzzEFFFFKKMMMOOOOPPONLKHDzxvrrsmqquqqmmmqwyABEIMMICyplc99575floppppoootwytppttt", +"ppwwof5|(~~),>>-=='!<_{)///~~,,{3gklkgiigfotyytpi95335fpwBIKIIKKIBwyEKMNMMKKIIHEyplloptwywyBKNNNNNKIEEEEzuwwzCGGKKKKIIIMLMNOOPPPOOLNNNNNLKIIEDDzxxwtwwwuuqqqqnigggggggeemmrrvvvwxxzzDFFFIIMMMNOOOPPPONLHFDzvvprmmmqquuqmmmqwyAIIKKIBypof997735illooliiiloptppttt", +"llptof3<())))'>;=&*>~<~,)~~)),>,~5ilkiliiiopuyywpf95599kowEIIHHIIEwwAIKMNNMKIKMMIAtolllpwAyEKNNMNNMKKIKIEzAwwCBEHIKKKIILLLMNOPPPPOOOOOOMMJIJEEDzzwywwwwqqqmmmjhjhggggiijmmtsvvvvzzzDDFFHHLLMMOOOOQQQOOLIFCzvpsmmmmmjnuuqmmmtwAHHIHEEztpic99542cllopoiiiiilpppppo", +"ffilli5|~),,'-*==%%;~11(~//~)~),);**=-,)),)~<<~~/<<<|<))<5fluqqoommuxAyticcf9335itEKIIKKIAttyHIHHHHHIKMNOOMBwoliowBHKOOOOMIHIIMNMKIHIIHHIKKKKMMMNOOPQRQPPPOONNLLHFFFCzzAzssssmmmmmmmmmeeeeemmmssvvvwxzzzFFFIIMMMMOOOOPQQQPOMKKECAtummmjjjjhjjouuqquwAEIEBABBywplf00725fotwywtollliliff", +"lif99flf3~,>***-,),-*-)~~),)~~~~)>)<3clqqmmikmtyytlfffc5|39lAIIIIKKIAtwEIIHEEEEHKMOONMEwpoptABEMNOOOKHIHIMMIIHKMMKKMMMMNNNNOPPQRRQPPOONLLLIFFFECCyvtsrrmmmmmmrmmmmmmmmmpssvvvvvzzAEFFIILLLMOOOPPPPQOOLKFECAwwqqjjjjjjjjnpxuqqwyBHEEEEEEAtpic0975cipwwwtplilillll", +"lid3}5fi9/)>*&*-->*#@#*>,>-->,',,>>)/|dlqqmkggmtxuiccffc559itEIIIIKKHytyEIIHHHHEHKMNNMIEywwyBEEIKMNMKIHIIKMKIHHMMMMOOOOPPPPPQQQRRQQOOONLLIFFFGCzyxvsrrrmmmmmmmrmmmmmmmmrrvvvwvzzzzFFFIKKKLOOOOPPQPPOOLIFCAzwuqqjjjggggjjnuuuqwyAEBCBBEEAytof009669ipttplifiioloo", +"ii93:<5ff|~,-=***%#+.+@%--*%-),,,---,{|foqqmkgkqtul959fif99fpEKKKKKKKEwwBEIIIKKIHHIKKMMKEBEBEIKIMKKKKIHEIIKKIHHKMMMNOOPQQQQQQQRRRQPOOOMLLIFHFECzvvvssssmmmmmmmssmmmmmsssvvvvvxzzzCFFIILLLMOOOPPPQPPOMMFFzyzxuuljjggggggjjjuuuqwABEAAyABAwtpi0097269lppoifffiliil"}; diff --git a/hacks/images/timetunnel2.xpm b/hacks/images/timetunnel2.xpm new file mode 100644 index 00000000..f87144ef --- /dev/null +++ b/hacks/images/timetunnel2.xpm @@ -0,0 +1,599 @@ +/* XPM */ +static char * timetunnel2_xpm[] = { +"256 512 84 1", +" c #100A08", +". c #120C13", +"+ c #171021", +"@ c #18112D", +"# c #1C150F", +"$ c #18103A", +"% c #1A1049", +"& c #1B105D", +"* c #1B1076", +"= c #241492", +"- c #21149D", +"; c #2012AC", +"> c #2112C7", +", c #332A1C", +"' c #382A2F", +") c #36245C", +"! c #39274A", +"~ c #331F8A", +"{ c #372375", +"] c #2714F8", +"^ c #2B15EE", +"/ c #2E17E3", +"( c #4021D9", +"_ c #441DFC", +": c #4B2AC6", +"< c #5031B4", +"[ c #5728F7", +"} c #6822FD", +"| c #5A4382", +"1 c #5B3CAE", +"2 c #5E439A", +"3 c #5E34ED", +"4 c #60514F", +"5 c #655D38", +"6 c #7A2FFA", +"7 c #665471", +"8 c #9027FE", +"9 c #7540F9", +"0 c #8D38FB", +"a c #7748EC", +"b c #6E4FE4", +"c c #784ED8", +"d c #9447F8", +"e c #AB3BFD", +"f c #A340FC", +"g c #9559FA", +"h c #B052FC", +"i c #9A64E7", +"j c #9267F5", +"k c #8D72CE", +"l c #8E6EE3", +"m c #BF5AFC", +"n c #AC64FB", +"o c #907EBF", +"p c #9386A0", +"q c #999C57", +"r c #D066FD", +"s c #B978FB", +"t c #AD83F7", +"u c #CD72FC", +"v c #A19F91", +"w c #CF84FB", +"x c #B197F3", +"y c #C793F9", +"z c #B2A8C4", +"A c #B2A8E4", +"B c #DE8FFC", +"C c #CAACF7", +"D c #DAA7FB", +"E c #D1BEF8", +"F c #CDC7EB", +"G c #DFBCFB", +"H c #CED1C5", +"I c #CECEDA", +"J c #E5CBFA", +"K c #DBE2A4", +"L c #E6D7FB", +"M c #E4DEF9", +"N c #E6E9DF", +"O c #EAE7F6", +"P c #EDF1D0", +"Q c #F2F0FC", +"R c #F9F8FC", +"S c #F9FAF6", +"_[[0nDJMOOOMMMMMOOQQQQQQOMJCysngggitCJLMMLLGDwumhff0000fhsyCCCtc~%$$$&=:agc). ..+$%&**=-;>>/////>;=****=-;;>:blAFOOOOMMMOQRRRRRSSSSSSSSSRRRQMFCtjad9ddnniic2!'# ..++@$%&&&&%$$$%&=>///^^^", +"__}0gBGLLMMMLLMMOQQQQQQOMLGysngdggixELMMMLJGywmhdf006660hsyCCDtccclxFORRRRRQQQQQQQQRRRRRRRRRRRRRRRRQOMLLLLLLJJDBumf93(={%%&~:3dhg~+ ..+@%&*=-;>>//^^^^^/>;-==--;;;::lAFOQQOOMMMOQRRRRRSSSSSSSSSRRRQOLCtjg999dgggb1)+.# ...+$&&**=**&%%$%&=;///^^^", +"__[6dsyGJJJLLLMOOQQQQQOOLEDtngd9dgsxELMMMLJDyshd006}}}60hsyCCCxlllxFORRRRRRRQQQQQQRRRRRRRRRRRRRRRRRQOLLJJJJGGDBurhf63(-~{*~:(dhmd:).. ...+$&*->>//^^^]]]]^^//>;;;;;>(blAMOQQQQOOMOQQRRRRRSSSSSSSSSRRRROMEyjg999999:<)+.# ...@%*=;;>;;-*&&%&*=;>//^^^", +"]__[0hsyDDGJJLMOOQQQQOMLGysnd9399gtCLMOOMLGDwnh006}}}}}0hsDGECCkkxEORRSSSRRRRRQRRRRRRRRRRRRRRRRRRRQQOLLJGGGDDBurhf063(:=~=:(0dmmh3~@+............+@&=;>//^^]]]]]__]^^//>>>>((bkFOQRRRQQOOOOQRRRRRRRSSSSSSSSRRRROMEyja93333(<)@+. ..@%*;>////>>-=*&**=;>>////", +"^]_}6dhuwyDGJLMOOOOOMLJCysg96[[39jyELOOOMLGysgd06}}___[6dsDEJEACCAMORSSSSRRRRRRRRRRRRRRRRRRRRRRRRRQQOLJGGDDBBurmef063(::::33dmrmh0:&@+++..++.+++@$&=;//^^]]_______^^^///(((alxFORRRRRQQQOOQQRRRRRRRRSSSSSSSRRRQOLCtj933((>=%@.. ..+%*;/^^^^^/>>-=**=--;;;>>>", +"^^^^[6dhmuBDGJLLMMLLJCysg93[[[[3aixFOOOOMLGysh06}}____}6gtCELFEEEFORSSSSSSRRRRRRRRRRRRRRRRRRRRRRRRQQOLJGDDBwurmef00633:::33dhrrrh0(=&%$@@@@@@@@$%*->/^^^_______[[[[[33333ackFMQRRRRRRRQQQQQRRRRRRRRRRSSSSSRRRRQMExja3(/>-*%+.. ..+$*;/^]]]]]^/>;-=========--", +"//^^[}60dmuBDGGJJGGDysg96[[[[/(3btEMOQQOMLCynd06}_____[6gtGJMLFFFMORSSSSSSRRRRRRRRRQRRRRRRRRRRRRRRRQOLJGDBwurmeef00033::3adhmuurm03>-**&&&******-;//^^_____}[[669999aaaaclAFORRSRRRRRQQQQQRRRRRRRRRRRRRSSRRRRROLCla3((;=&$+.. ..+$*;/^]]]]]]^/>;-==***&&&&&&", +";>/^^[}60dmuwyyyywsng96[[^^^//(3iCLOQQQOMLCtnd6[[_____[6gtGLMMFFMORRSSSSSSRRRRRRRRQQRRRRRRRRRRRRRRRQOLJGDBurmhee000093aaaddmruuume6/>>;;;;;;>>>>//^^^[[[}66660dgnjtjiiltCFORRSSSRRRRRQQQQRRRRRRRRRRRRRRRRRRRRQMEtb3((-*%@+.. ..+$*;/^]]]]]]]^/>;-=**&&%$$$$%", +"-;//^^_}}0dhmnnngd06[[[^^^^^//3bxJOQQQQOMJCtnd6[_____^[6gtELMMMMMQRSSSSSSSRRRRRRQQQQQRRRRRRRRRRRRRRQOLJGBwummeee00099aaaddhruwuume6[/////////////[[[[660000ddnsyDCCCxCAFMORSSSSSRRRRQQQQRRRRRRRRRRRRRRRRRRRRQOFxj93(;=&$+... ..+$*;/^]]]]]]]]^/>;=**&&$@@++@@", +"*->/^^^__}6600066[[[^^___^^^/3atEMOQQQQOMJCwn06[_____^[3gyELMMMMOQRRSSSSSRRRRRRQQQQQQRRRRRRSSRRRRRRQOMJGBwrmeee00009daaddhmruuwume6[////////[33399aggnnnnnnswyGJLMLLFFMORRSSSSSRRRRRQQQRRRRRRRRRRRRRRRRRRRRRQMCta3((;~&@+.. .+@&;/^]]]]]]]]]^/>-=**&%$@++++@", +"*->/^^]_____[[[_^________^^[39iCLOQRRQQOLJDwg06[[_^^^^[9nyEMMMMOQRRRSSSSRRRRRRQQQOQQQRRRRRSSSRRRRRRQOMJDBurmfe000099dddddhmruwurme6[[////[33ajitxxCCCCCCDDDCGJLMOOOOOORRSSSSSSSRRRRQQQQRRRRRRRRRRRRRRRRRRRRQMExj33((;=&$+.. ..@&->^]]]]]]]]]]^/>-=**&%$@++++@", +"*-;>/^^]]_______]]]]]___^[[[9jxJOQRRQQQOLGysh06[^^^^^^[9sCLMMOOOQRRRSSSRRRRRRQQOOOOQQRRRRSSSSSRRRRRQOMJDBumhee000099aadddhmruuurme6[[//(3ajtxEFMMMMOMMMMLLLLLMOQQRRRRRSSSSSSSSSRRRQQQQRRRRRRRRRRRRRRRRRRRRROLCla3[//>-*$@+......+%*>/^]]]]]]]]]]^/>;-=**&%$@@@@@", +"*->>/^^]]]]]]]]]]]]]___[[[39jyEMOQQQQQOMJDwnd0[[^^^^^^[gtEMOOOOQRRRSSRSRRRRRRQOMLLMOQRRRRSRRSSRRRRRQOLJDyumhff000099aaddhmruuuurhe6[[(3abtCFMQQQQRRRRRQQQOOOOQQQRRRRSSSSSSSSSSRRRRQQQQRRRRRRRRRRRRRRRRRRRRQMEtj93[//(;~%@+.....+$*;/^]]]]]]]]]]]^/>>;;-=*&%$@@@$", +"=;>//^]]]]]]]]]]]]]]__[[39ajtALOQQQQQOMJGBsh06}^^^^^^[3nCLMOQQQQRRRSRSSSRRRRQQMLJLLOQRRRRRRRSRRRRRQQOLJDyumhf000009daaddhmruuurme06333bckEMORRRRRRRRRRRRRQQQQQQRRRRSSSSSSSSSSSRRRQQQQQRRRRRRRRRRRRRRRRRRQQMExia96[[//>-&$@+...+@&->/^]_]]]]]]__]^^//>>>;-*&$$$$$", +";>>/^^]]]]]]]]]]]]]__[[39ajtCJMOQQQQOMLGDwnf6[_^^^^^^[9sEMOQQQQQRRRSRSSSRRRRQOLJGGLOQRRRRRRRSRRRRRQQOLJDBumff0000099adddhmrrurrhe033:<1kAIRSSSSSSSSRRRRRRRQQQQQQRRSSSSSSSSSSSRRRRQQQQQRRRRRRRRRRRRRRRRRQQMExsg936[[[/>;*%@+++@@&=>/^]]_]]]]]___]^^^^///>;=&%$$%%", +">>/^^]]]]]]]]]]]]]]__[39gjtxEMOQQQQOMLGDwrf0}__^^^^^^[gtJMQQQQQQRRRSRSSSRRRRQOLGDCJMQRRRRRRRSRRRRRQOMLJDBsmff000099999ddhmrrrrme003:<1koINNSSSSSSSSSSSRRRRQOOMOQQRRSSSSSSSSSRRRRQQOOQQRRRRRRRRRRRRRRRRQOMExtgd966[[[/(;*%@@@@$&~;//^]]]]]]______]^^^^^^/>-*&%&&*", +"/^^]]]]]]]]]]]]]]]__[39gitxELMOQQOOLJGDwrh06}__^^^^^^[gyLOQQQQQQRRRSRSSRRRRRQMJDyDGMQRRRRRRRSRRRRRQOMLEDBsmhff00099999ddhmmrmme003:<2||pINNSSSSSSSSSSRRRRQOMLJLMOQRRSSSSSSSRRRRQOOMOOQRRRRRRRRRRRRRRQQOLExiga93666[[/(;*%@@@$&~;(/^]_]]]]]______]]]]]^^/>-*&&*=-", +"^^]]]]]]]]]]]]]]]__[[9gitxEFMOQQOOLLGDwuhf6}__]]^^]]^[gDLOQQQQQQRRRSRRSRRRRRQMGyByGLQRRRRRRRSRRRRRQOMLGDBsnhdf000099900dhhmmme063:<{||7pHNNSSSSSSSSSRRRRQQMJGCCGLMQRRSSSSSRRRQQOMLLMOQRRRRRRRRRRRRRRQOLExiga9900666[/(;*%@@$%*;>/^^_]]]]]________]]]]]^/>-***-;>", +"]]]]]]]]]]^^]]]]]_^[9gjtxEFMOQQQOMLJDBumf0}___]]]]]__6gDLOQQQQQRRRRSRRSRRRRROLCywyCLQRRRRRRRRRRRRQQOLJGDBsnhdf000009900fhhhhe06[(:~{)!7pvNNSSSSSSSSRRRRRQMJCtsstDEMQRRRRRRRRQOMLJJJLOQQRRRRRRRRRRRRQOMExigd9999d006[/(-&%$$%&=>/^^]__]]]]_____^__]]]]]^/>-==->>/", +"]]]]]]]]]^^^]]]]__[9gjtxEFMOQQQQOMJGyumd06}__]]]]]]__[dyJOQQQQQRRRRSRSSRRRRROLDwswDLORRRRRRRRRRRRQOOLJGDysnhdd000066660fffff06[[(-{)!!7pzHNSSSSSSSSRRRQOMEDwnggmsyGLOQRRRRRQOLJGDDGJMQQRRRRRRRRRRRRQMJCtja999ddddd6[/>-&%$%&*;>/^]]]]]]]______^^^^^^^^/>;--;>>/^", +"]]]]]]]]^^^^]]]__[9gtxCELMQQRRQQOMJDBuh06[[__]^^]]]__[dwEMQQQRRRRRSRRSSRRRRROJDwswDLORRRRRRRRRRRRQOMLJGDwumhdd0006666600fff06}[/>=))!!77zIRSSSSSSRRRRQOLEDsnhdddhnwDJMQQQQQMLGDBBBDJMQQRRRRRRRRRRQQMJCtjg999dhgmhd06/>-&%%%*->/^^]]]]]]]____[[^^^^^^^//>;;;>>/^]", +"]]]]]]]^^/^^^]]_[3gtxEFMMQRRRRRQOLGDsnd06[__]]^^^]]]_[9sGMQQRRRRRRRRSSSSSRRROJysnsDLOQRRRRRRRRRRRQOMLJGDwumhf00066[[[6000006}_^/;*%!!!77zIRSSSSSRRRQQOLGyshdd0000fhsyGLMOMLJDyuuuBDJOQRRRRRRRRRRQQMLGysgd99dhnnnnh06/(;*&&*=;>/^^]]]]]]]____}[^//////>>>;;>>/^]]", +"____]]^^///^^^^[3gtCFMMOQRRRRRRQOLCtnd06[___]^^^^^]]_[9sGMQQRRRRRRRSSSSSSRRROJysssDLOQRRRRRRRRRRQQOMLJGDwumff0066[[[}}60006}__^/-&%$!!|ozIRSSSRRRRQOMJCyshd00000000dnwCJJJGDwumruwDLOQRRRRRRRRQQOMJCysga999dhnnnmd0[/(;=**=->/^^]]]]]]]_____[[//>>>>>>;;;>>/^^]]", +"____]^^////^^^^[atELMOOQRRRRRRRQMEynd66[___]^^///^]]_[9sEMQRRRRRRRSSSSSSSRRROLCwwwDLOQRRRRRRRRRRQOOMLLEDBumff066[[[}}}}66}}__]^>=&$@!)|ozORRRRRRQQOLEDwnhd0000086660dmsyDDywummmuBGLOQRRRRRRRQQOMECtjgd9000ddhggd9[[/(>-=-->>/^^]]]]]]]_____^//>;;;;;---;>>/^^]]", +"__[^^^//>>//^^[9lCLMOQQRRRRRRRQOLCsd0[}___]^^/>>>/^^^[9tEOQRRRRRRSSSSSSSSSRROLGyByGMQRRRRRRRRRRRQOOMMLJCysmf006}}}_}}}}}}}___]^>*%$@!)|oIORRRRRQQMLEDsndd00000886}660dmswwsrmhhmuyJMQRRRRRRRQQMLEDsng996666000096[[//>>;;;>>//^]]]]]]]]_____^/>;-----==-;;>//^^^", +"[[[[//(>>>//^[3jxFMOQQRRRRRRRQQLGtg0[}____]^>;;;>>/^^[gyLORRRRSRSSSSSSSSSRRRQMECDDJMQRRRRRRRRRRQQOOOMLJCysnf006}}____}}}}___]^/;*%@@!|ozIQRRRRQOMJCysgd000008888}}}}60hnusumhhhmwDJOQRRRRRRRQOLEDsn9966[[[[[[[[[[////>>>>>>>/^^]]]]]]]______^/>;;--=====-;>>//^^", +"[[[[/(>;;;>//3atEMOQQRRRRRRRRQMJyn96}____]^/;=*=->/^^3jCMQRRRRSRSSSSSSSSSRRRQMJGGGLOQRRRRRRRRRRRQOOOMLJGywnf06}}______}_____]^/-&$@@!|pzORRRRQOMJCtjgd0000088886}}}}60hnsuurmmmuBGMQRRRRRRRRQMLCtja9[[[[[[[[[^^^///>>>>>>>>/^^]]]]]________^^/>>;;--=***=--;>>//", +"////(>-=~-;((3jxFMQQRRRRRRRRQOLCsd6[____]^/;=&&*=;//[atJORRRRSSSSSSSSSSSSRRRQOLJJJLOQRRRRRRRRRRQQOOOOMLGDwnd06}}___________]]^>-&$@@!|pIORRRQOMJCtng906600088886}}}60dnswBwwuuuyDJOQRRRRRRRQOLEyia93[[[[^^^_^^//>;;;;;>>>//^^]]]___________^^//>>>;-=******==;;>", +"(((>;=*&&*->(atEMOQQRRRRRRRQQMGtg3[^__]]^/>=&%%&*;>/3jCMQRRRRSSSSSSSSSSSSRRRQOLLJLMOQRRRRRRRRRRQQQQQOMLJDwnd06}___________]]]/>=&$@!!7zIQRRRQOLCtja9666600088886}}66dmwDCGGDDDDGJMQRRRRRRRROMExlb93([//^^^^^^//;-==-;;>>//^^]]]_____}}}}____^^///>>;=**&&&&&&**=", +"----~&%$%&=:3jxFMOQQRRRRRRQQMEyn3[/^^^^^/;=&%$%&*;>(ayJORRRRRSSSSSSSSSSSSRRRQOMLLLMQQRRRRRRRRRRQQQQQQOMJDwnd0}[___________]]^/;*%@@!!pzIQRRROMEyia96666600888886666dhsCJLLLLLJLLMOQRRRRRRRQIFxlc:((((////^^//>>-=*=-;>>//^^]]____}}66686}}__^^^^^/>>-**&&&%%%%%&", +"&&&&%$@@@%*>>>>>>-*&$$$%&=;(3jCMQRRRRRSSSSSSSSSSSSRRRQOMMMMOQQRRRRRRRRRRRQQQQQOMJDwnd6[[__________]]]^/;*%$@!7pINRRROOFCtg93[666000888886660hsCLOOQQQOOOOQQRRRRRSSNIzok11<==--;>(////>>;-==-;>>/^^]]]___}60feeee06}}__^^^^^/>;=*&&%$$@@@@", +"@@@@+++++$&1cxFOOQQRRRRRRQMJxi<~{&&&****&%$@@$%*->(atEOQRRRRRSSSSSSSSSSSSRRRQQOMMOOQRRRRRRRRRRRRQQQQQOMJDwnd6[___________]]^^>-&%$!!7zHNNNQOMExia96[6600088888060fhsDLOQRRRRRQQQRRRRRRSNNHp77))))%&&{~-;>(((>>;;;;>>//^^]]]___}0fhmmmmhe06}}_^^^^^/>;-**&%$@++++", +"........+@)2kAMOQQQRRRRRQMExl1)$@@@@@$$$@@@@@%&=;((ayJORRRRRRSSSSSSSSSSSSRRRQQOOOOQQRRRRRRRRSRRRRQQQQOMJCwg96[[^________]]]^/>=&%$!7pHNNNNQOFAtja3666000eee88800dhuyJOQRRRRRRRRRRRRRSSNHvv4''!@@@@@$){~-:>((>>>>///^^^]]]____}0fmuuwwwumh06[[^^^^^/>>;=*&%@+++..", +".........+!|AFOQQQQRRRQQMFxl2)@+....+++++++@$&*;>/3gyLOQRRRRRSSSSSSSSSSSSRRRRQQOOQQQRRRRRRSSSRRRRRQQQOMJDsg9[[[^_______]]]^^/;=&$$!7vHNNNNNOFAtja366600eeeee800fhnyGMQRRRSRRRRRRRRRRSNHv54'''++++++@!)~<<:(((////^^^]]]_____}0dmuwBDDDBwnh0[[[^^^//>>;=*&%@++...", +" ..''pzIQRRRRRRQQMFxk2)@+........++++@%*->//3gyLOQRRRRRRSSSSSSSSSSSRRRRQQQQQQRRRRRRRSRSSRQQRQQQOMJDsg9[[[^^^^^^^_]]]^/>;*&$!!pHNNNNNNOFAtca936000feeeeeefhnyGMQRSSSSSSSRRRRRSSNHv5,,##....++@!){21cba3(//^^^]_______}}0fmuwBDGGGGDwnd6[//////>>;=*&$@+....", +" #'4vHNNRRRRRQQMJxl2)!+.. ....++@$&=>/^[6gyJOQQRRRRRSSSSSSSSSSSRRRRQQQQQQRRRRRRRRSSRRQQOQQQOMJCsg9[[[^^^^^^^^]]^^/>-&%$!7vHNNNNNNIFAtca9900000ee0e0edmwDLORSSSSSSSSSSSSSSNHv5,,##....++@!)|2kkliga3[[^^_______}}}00hmuBDGJLLLJCtga33(///>>;;=*&$@+... ", +" #,5KHNSSRRRQQMJxl1{)+.. ...++@%*;>/^^6gyGMOQRRRRRSSSSSSSSSSSRRRRQQQQQQRRRRRRRSSSRQOOOQQQOMJDsg9[[^^^^^^^^^^^^^>;*&%$!7vHNNNNNNIFClca990000000000fhnDJORSSSSSSSSSSSSSSNHv5,,##...+++@))22kxxytia9[[[[_____}}}600fhmuyDJLMOMLExib33(((>>;;-*&%@+.... ", +" #,5qPNNSSRRRQOFClc1{$+.. ...++$&=>/^^[6hsCLOQQRRRRSSSSSSSSSSSRRRRRQQQQQRRRRRRRRRRQOIIOOQQOMExia3[[^^^^^^^^^^^^/>-*%$!!4HPPNPNPNIzxlba366600000000fmwGMQRSSSSSSSSSSSSSNHv5,,##..++@@$%{11lyDxytng96[[}}}}}}}66000ffmsyGLMOOOMLCtiaa3((>;;-=*&$@+... ", +" #,5KHNSSRRRQOMAlb:~%@+.. ..++$&->/^^[6dsDJLOQRRRRSSSSSSSSSSSRRRRRQQQQQRRRRRRRRRRNIIIOOOOOMExja3[^^^^^^^^^^^^//;=&$$!7vHPPPPPPHIzklb9366666666660dsxJORSSSSSSSSSSSSSNHv44'#...+@@$%{~</^^[6dnyCJMOQRRSSSSSSSSSSSSRRRRRRQQQQRRRRRRRRRRIIIIIOOOMFAtb93[^^^^^^^^^^^^/>;*%$@!4vKPPPPPPHIAkia93[[[}}66666dgtGMQRSSSSSSSSSSSSRIvp4'#...+@@%&*=-:acittwssnhdd000666686886800fhwCLMQQQQOMExtiga::;-=*&$@++... ", +" ##4vHNRRRQQOMFxja-{$+... ..++$&->/^^[6dgsyGLMQRRSSSSSSSSSSSSRRRRRRQQQQRRRRRRRRROFzzzIIIIMFxla3[^^^^^^^^//^//>>-&%$@!4vPPPPPPPHzAkca36[[[}}}}}60dnxFORSSSSSSSSSSSSNIzp4''...+@@%&*-;:(3agnissnnmhhdff00068886}6600hwGLOQQQQOMExtljba:;=*&%@++.... ", +" .'7pFOOQQQOMLCla:~%@.. ..+@%*->/^^[60hnsyGLORRRSSSSSSSSSSSRRRRRRQQQQRRRRRRRROIzppzIIIIIAxia3/^^^^^////////>;*&%$!!4vPPPPPPHHzolca3[[[[}}}}}69gtCMORSSSSSSSSSSSNHIp4''...+@$%&*=;;>((3agnnususurmhffe0066}}}}}6dnyJMQQQQOMLExytica:-~&%@@+...... ", +" ..+!2kAFOOOOMLExb:-&@+.. ..+@%*;>/^^[60dgnyCJORRSSSSSSSSSSSSRRRRRRQQQQRRRRRRRQOFAoppvHHIIAkca(/^^^/////////>>-*%$@!7vHPPNNPPHIzxlcd3[[[____}[6diyJMQRSSSSSSSSSNNHHp4''...+@$%&=-;;>>((33dhnwByyywwumhf006}}}}}}0gwGLOQQQQOMJGCCxtib:=*%$@+........ ", +" ..+${/^^[69dhnsDJOQRSSSSSSSSSSSSRRRRRRQQQQRRRRRRQOMAooopvHHIzAkc3(/^^////((////>;=&%$$!4vHNNNNNNNIAxlg93[[[____[[9gtEMORRRSSSSSNNNNHvp4'''+++@$&*=;;>>>>((30dmwDDGGGDDwumhf06}}}}}6dsDJMQQQQOMMJEECCxlc<~{$@++.........", +" ...+@&-:bxCJLLLExia3-&@.. ..+$&=>//^/[660dhsyJORRSSSSSSSSSSSSRRRRRRRQQQRRRRRRQMJxkkopvIHIzAkc3(/^///(((((//>>-*&%$!7pHNNNNNNNIIAxlga3[[[___[[6aiCJMORRRRRNNNNNHHvp7'!'++@$%&=;>>>>>((((3dnwDGJLLLJGDwuhf06}}}[69nyJMOQQQQOMMLLLLECxl1~)$@+..........", +"...+@&=>(alxEJEExta3(=%@.. ..+$&->///[[669dhsDJORRSSSSSSSSSSSSRRRRRRRRRRRRRRRQOMExkkozzHIIFAkca(///(/(((((>>>;-*&%$!7vHNNSSNNOIFExtja9[[[__[[[9jxEMOOQRRQNOIIHHvp77!!!@@$%&~->>////////39hsDGLMOOMLJDysmd06[}}[6gtEMQQQQQQOMMMMMMLJCl1{)!@+..........", +"..+@%*;/(9ixCEExtg3(:*$+.. ..+$*->///[339ddgsDLORSSSSSSSSSSSSSRRRRRRRRRRRRRRRQOMCklkozIIIIFAkca3///(((::(>>>>;=&%$$!pHNNSSRRQOMFECysgd6[[[[[[9jtCFMOOOOOIIFzzzpp7|)))))%&~-;>////////[3dnwDJLMOOOOLJGysgd6[[[[[9sCMOQRRRQQOOOOOOOOMAk2{)!@++.........", +".+@%*;>/[9ixCECyja3(-&@+. .+@%*;>///[39dddnwCMQRSSSSSSSSSSSSSRRRRRRRRRRRRRRRQOFAxkkozIIIIFAkca3//(((:::>>>>;-*&%$!7pHNNRRROOMMFECytjgd6[[[[9gtxEFMMMMIFFAAooo|22{{{{~~~=;>(///[[[[[39gsyGJLOOOOOMLJCysh0[[[[[9gxLOQRRRRRQQQQQQQQOMFo2{)$@+++........", +"+@%*;>//[atCEECtj3(;~%@.. ..+$&=>///[39ddddnyGMQRSSSSSSSSSSSSSRRRRRRRRRRRRRRRQMFCxkkAzIIIIFAtb33//(((::::>>;-*&%$@@7vHNRRROOMMLJJECDtsg99669ajxCEFMFFFAAokkkl11<<<----:::((([[[[[[39gsyCJLMOOOOOMLJCysg96[[[[[9tEMQRRRRRRRRRRRRRRQOFo2{)$$@++........", +"$%*;//^[6gtCEECta3(-&@+.. ..+$*;>///39ddddgsyEORRSSSSSSSSSSSSSRRRRRRRRRRRRRRQQMJCkkoAzIIIFFxlb33//(((::::;;;=*%$@@+4vHNNQOOMLLJJJJECDtng9999gtxCEEFEACxkkllicc::((((((::a33333[639gsyCJLMOOOOOMLLECysg9[[[^^[[atFOQRRRRRRRRRRRRRRROFk2{{)$@++........", +"&~;(/^^[9nxEEExla(;*%@.. ..@%=>///[6ddggdgsyGMQRSSSSSSSSSSSSSRRRRRRRRRRRRRRQOMExkkoAFIIMFAxja33[/((:::;;;;-*&%@@++'vHHOOMLJJEJJJJEGCysgd999gjxCCCCCxxklllicba333(333aaaaa993339gntCJLMOOOOOMLLGCysnd6[[^^^^^3gxLOQRRRRRRRRRRRRRRQOAk1~{%$@++........", +"=;(/[[[[9jyCECxja:=&@+.. .+@&->//[39dddddgsyJMQRSSSSSSSSSSSSSSRRRRRRRRRRRRRQOLCxlkoAFIMFFCtb33[//(((:;;;;-=*&$@++''4vIILLJGCCGEEJEGDysg9999ajttxxxxxtktttliga933339abbjbba9999gntCJMOOOOOMLJGDtsgd9[[[^^^^^^3jxLOQRRRRRRRRRRRRRROMAl1~{)$@+........+", +":(([[[[6djtyxtia(;*%@... .+$*;(/330ddddddgsyJMQRSSSSSSSSSSSSSSRRRRRRRRRRRRQOMExlllkAFFFFAxia3[///(((:;;;;-*&%$@+++'4pzJJGDDyDDCGGGDywnd96[39ajitttxxxCCCxytjga999abjjiijbaa9dgnsDGLMOOOOMLECysgd96[[^__]]^^^3jxLOQRRRRRRRRRRRRRQOFxl<~{$@+........+@", +"(([[[[[69gjssja3>=&@+.. ..+%~:(330dddddddgsDJOQRSSSSSSSSSSSSSSSRRRRRRRRRRQQMJCtjclkCEFFECtb33[^^///(>;;;;-*&%$@+++'7pAADywwwwyDDDDDBshd6[[[39abiltxCAEEECCytjgaagjjillijbaaaggnwDELMOOOMLGDwnh06[[[____]]]^[[gyJOQQRRRRRRRRRRRQOFAlc<{)@+... ..+@$", +"(([[[[[[69dga93(-*$+.. .+@)<:339ddd9399dgtCLORRSSSSSSSSSSSSNNNRRRRRRRQQQQOLExibbilxAEECxia3[^^^^//(>;;;;-*&%$@+++'77oyysiinswwyyDywnh06[[[[39ajitxEEFFJECxtijjjjltllljjbbjgjnsyDGJLLLLECyshd06[[[_____]]__[6gyEMOQQQQQQRRRRRRQMEkc<~{$@+.. ..@%{", +"[[[[[[[[[[66[[(;~%@+.. .+!{<:aaddda3339dnyGMQRRSSSSSSSSSSNNHHIINRRQQQQQOOMExlbabblxCCCxtj93[^^^^//(>>>;;-=&%$@+++'!|2linggdgnswBywsnd0[[[[[[39gitxEEFFJECyttiillttllliiilltstwyyDGGGGDysnh0066[[[_________[6hwGLOOQQQQQRRRRQQMExib<~%@+.. ..+$*-", +"[^^^^^[__[[[[/>=&@+... .+@)21ccgdaa33339gsDJOQRRSSSSSSSSSNHHzppzIOOQQOOOMLECtjaaabltxCxtig9[[^^^^^//>>>>;-=&%$@++++!)21caa39dhnswwwsnd0[[[[[[[9ajtxCEEEECxyttiitttlllllltxxxyyyyyyyyywsnhd066[[[[__________}6hsDJMOQQQQRRRQQQOLClb:<~%@+.. ..+@&->", +"^^^^^_____^^//;&$+... ..+!22lligaa:::(39gtCLORRSSSSSSSSSNHvp777pzIOOOOMMLECtja99agitxxytna3[[^^^^^///>>>;-=&%$+++.+@){1<::(33dhnuwwsnh96[[[[[[69gjttxxxxtttiiiiiliiilltxCAECCDyywsssnhdd0666[[[[[__________}0hsDELOOQQQRRQQQOLEyib:-*%@+... ..+@&=>/", +"^^^________^/>*%@... ..+$)2kkktic::::(3aiyEMQRRSSSSSSSSNHzp7777ozIOOOMMLECtjg999ajityytig9[[[^^^^^////>>;-=&%$+++.+@!{~<:::((3dhswywsgd6[[[[[[[39gjjjiiijjjjjjjjjjjilxCEFFFJECyysnnhd0066}[}[[[[[[________}0fmwDGLOQQQRRRQQOMJCtb::-*%@+.....+@%=>//", +"__________]^/-&@+.. ..+@)2koACxtic<<::abtCLORRRSSSSSSSRIzp7!!!|ozFOOMMLECysg9999ajittttig9[[[^^^^^^///>>>-=&%$++..++!{~==--;:(9giwywsnd0[[[[[[[669dggggaaaaaggggjjjlxCEFMMMLJCywshd0066}}}}[[[[[[[______}}0dmuyDJLOQQRRRRQQOMJxib::-~&$@+...+@%=>//[", +"_^________^/>*%@.... ..@%~1kAFFAxlc<<::aixEMQRRSSSSSSSNIzp|!!!!)|AFMMMLECtjg99399ajitttsnd6[[[^^_^^^////>>;=&%@++..++@%{*~===-::anwwwsnd96[[[[[[6699999999999aaaabjitCEMOOOMLJCysnd066}}}___[[[[[[[____}}60hnwyDGJMOQRRRRRRQOMExlc::-~&$@++++!{=:(/[[", +"[[[}}}____^/;*$+... ..+${>;=&%@++...+@$%&&&**~=:aisttsng906[[[[[6669999999999999aajtCEMOOOOOLECysg966[}____}[[[[[[[}}}}}60huBDCGJLMOQRRRRRRQOMGxlc:<=*&%@@+!){1:3366[", +"6666[}}}__^/-&@+... ..+@%~>;=&%@++...++@$%%%%&&~<:ciwtsngd96666666999993366663339aglxEFMOOOOMLCysnd06[______}[[666[[}}}}60hsyDGJJLLMQQRRRRRRQOLEkl<<=~{%$$!!)21cgddd00", +"000066}}__/>=%@... ..+$&=cxFOOOIAk1>;=*%@+.....+@@$%%%%%{~*$+... ..+$&>;=*%$+.....++@$$$%%%&{1clttsingdddddddddd99936[[[[399ajtxCJMMOOMFExtng9[[[______[[6666666}}60fnwDGJJJJLLMOQRRRRRRQMFCl1<~~{&)))|ooCCDysnhdd", +"dfff06}}_^/;&@+.. ...+${>;-*&$+.....++@$%%%%%%{11kxyttinggggghhgddd993[[[[699gjstyCELMMLJCxsgd0[[[______[[669000666660dnBDGJJJJLLOQQRRRRRQOMAkl1~~{{{{{2oAEJJCywnhdd", +"fff006}__^/-&@... ...+${1kFOQQNIAlb:39aiyEMQRRRRRRRIzo|)!@+++@!)|oAAxtj93[[[[3339aaaa93[[[________]]^^^//>>-*&$++....++$%&&&%%%{2kkxxytsssssnnnnngad93[[[[69agjttyDCCEEEGDyig96[[_______[[660ddd000000fhsyGJJJLLLMOQRRRRRRQOFok11~~~*~~1kAFMLLGysnhfd", +"ff006}}__^>=%@.. ...@${1oINRQIFola333ajyEMQRRRRRRIFpo|)!@+++@!)|oAAAtj93[[[[339aaaa99[[[[_________]^^^///>;-*%@+....+@%&***&&%{2koCCxxttttssssinga933[[[[9ajjttyyyyyDDytsgd96[[[______[[[69dddddd000ffnwDGJLLLMOQQRRRRRRRQIAk2~~~~~=<1kAFOOMLEDsnhdf", +"ff00}}__^/>*$+.. ..+@%{2AINNNIFkca3339jtGMOQRRRROIAo|))@@@+@@!|oAFFAtj93([[339aaaa993[[[[_________^^^^^^//>;=&$+++++@%*=--=*&&)|2oAACCyytttwtsngga33[[[[39gstyyyyywwssngd96[[[^_______[[69ddgnhhfdfdhnsyGJLLMOOQQRRRRRSSSNIo|{{~~==-;*&$@++@%*-;;;-*&&){2oAEECDyyywtsngaa33(/[[[9gjtyyyyyssnggd93[[^^_______^[[69ddgnnnhhhhmnsyDJLMMOQQRRRRRSSSSNHp7|){{~-::cxFMQQQOLEDwshhh", +"ff0}}__^/>*%+.. ..+${1kzIOOIFxia3[[[6gsCLMQQOOIAo||))$@@@@@!)|zIIFFxia3((33aabbba996[[[[___[[[^^^^^^^^]]^^/>;*%$$$%*->>>>;=&&%{2oAEEECDyttsnga33(((//[[9gstyyyysnghd06[[[^^________[[[99gnnnsnnnnuwBDCJLMOOQQRRRRRRSSSSNHp7)){~=::cxFOQQQQOLJCysunm", +"hf0}__^^/;&$+... .+@%~1kzIIIFAkb33[[[6dsyJMOOOIzo|))!@@@@@@@!)7zIIMExia3(33aajjjgad966[[}}}[[[[[^^^^^]]]]]]^/>-*&&&*;>///>>=*&%{2kAFFECDytigaa3((>>(//[39gsyyyysnhd06[[[^^^]]]]]___[[[69ggnnssssswyDGEJLMOQQRRRRRSSSSSSNNv7!)){~=%@+.. ..+$&~1kAFIFAxla3[[[[6dnyELMMFzp|!!@@@+@+@@@!|pzIIIFxlb:33abjjjjgad000666}}}[[[[^^^^^____]]^^/>-==-;>/^^^/>-*&%{2kAFFJECysga33((>>>>(((3djstytsngd06[[/^^^^]]]]]___[[69dgnsssswwyDCELLMOOQQRRRRRSSSSSSSNHv7!){~<;*%@... ..+@%*=;;>//^^^^/>=&%%)2kAFFJECtia3((>>;;;;>((3ajsttssgdd6[[/^^^^^]]]]]]__[[69gnjsttyyyDGJLMOOOQQQRRRRRSSSSSSSNHp7|{~<=&$+.... ...+$&=-:lkAAAxklja9000dhsyGJFzp7!'++++++++@@$)|pFIIFAxlcbbbittttsnghhffeeeeeee066[[[[_______]^^/>>>//^^^^//;=&%$){2oEFJCxiba::>;;;;;;;>(3ajsttsngd96[[//^^^^^^]]]]_^[[99gjstyDDCCGELLMOOOQQQRRRRSSSSSSSNNHp|211ckAMORRRRRRRQOMLJEGCDy", +"d0[[//>;*&@+.... ...+$&*;>:blkxxxxttigdddhnwDGEFzp7''.+...+++@@)||AFIFFAklcccitxxxytsnmhhhheeeehff06[[[[}}}}____]^//////^^^//>-*%$$!)|oAEACtcb::;;;;;;---;::acittingd33[/////^^^^^]]]^^[[9gjttDCGGGEJJLLMMOOOQQRRRRRSSSSSSNNIpk11lkAMORRRRRRRQQOMLLJGCDB", +"0[[//>>-*%@+... ...+$&*;>((:clkxxCCCytnmmnsyDGEzp74''....+++@@$)2oAFFFExklccitxCCCxytsnmmmmhhmmmmmff06[}}}}}____]^//////////>-*%$@@+!!|oAokl<<===--;;;--==-:bcitlingd33/////////^^^^^^^[39jtyCEJLLLLLLLLLLLLMMOQRRRRSSSSSSNNzokllkAFORRRRRRRRQOMLLJEGDBw", +"[[//>>-*&$++... ...+$&=;>///(ablxAEJJGDywsswDCGEzp4''.....++@@$){2oAFFFAxllcilxCCCCDywsurmmmmmmrrrrmhff0066}}}___^^//(3333((>-*%$++++''77oo22{{{**=-----====<>-*&%@+.... ...+@&*;>////(3alxEMMMLJCDyyDDGGzzp4''#....++@$){2koAFFEAxliiltxCEECDywuurrrrrrrruuurrmhhfe00}}___^^/39ajga3:={)@++.##''4477|)))%%&*=---=***~~>>>>>>>>>////[9jtCFMOQQQQOMLJCDyyxCEMOQRRRRRSSSSQIAokxAFORRRRRRRRRQOMLJJEGDysn", +"[/(>-**&$++... ..+@%*;>/^^^//3alAMOOOOLJGDDDGGEzp44''#...++@@$)22kAAFEACtliilxCCEECDywwuurrrrrruuwuuwuumhffe0}}__^[[9gtytlc<{)!+.###,,,,447!!@@@$%&*===*****~~1cilicba:(>>>>>>;;;;;;>>/(3atCFMQQRRRQQOLEDttttCEMOQRRRRSSSSROFAoxAFORRRRRRRRRQQOLLJEGDywnh", +"//>-=*&%@++... ...+$&->//^^^^/3atEMQQQQOLJGGGGJJzp44''#...++@$){2koAEEEAxliiltxCEEECDyBwuurrrrrruwwBBBBwwurhf06}}_[[9gtxDxtl2)!''###,,,,,44'''++@@$%&******&&*~<1ccccb:::;;;;;;-==**=-;>(3ixJMQRRRRRRQOLEDtttxELOQRRRRRSSRRROFAAAFOQRRSRRRRRRQQMLJEGCDysh9", +"/>;=*&&%@+.... ..+@%*;>/^^^^^/3bxLOQRQQOMLJGGJJJzp4'''#..+++!))22koAAAAxtliiltxCEEEGDyywuurrrrruuwBBDDDDDBwrmf06}}[6dntDCxk2|!'''##,,,,5544'''+++@$%&&***&&&&{{~<;=*&&%@+.... ..+@&=>//^^^^/[9iCMQRRRQQOLJJGJJFzp4,''#..++!!)||oooCACxtijjjlxCEEJEGCDywuuurrruuwBBDDGJJGGDBumd06669ditxxtk2|!'''',',,555544''+++@@$%&&&&&&&&&{~<<<<<<==~*****&&&%%%&*=:blCMORRRRRRRRRQMECxCEMOQRRRSSSRRRRQOMFFMOQRRSSRRRRRRQQOLJGCDysnd0[", +"/>-**&%$@+.... ..+$&->//^^///3atFORRRRQQOLJJJJJFzp44,,''''!!77ooooCCCxtljbjitxCEJJJEGDDBBuuuuuuuwBBDGJLLLJGDyumd0009gnstll2|)!!+''''445vvv477!++@@@$%%&&%%%%%%&*~=<--=~*&%%%%%%%$$$$%*-:cxEMQRRRRRRRRQOMJEEFMOQRRSSSSSRRRQOMMMMOQRRSSSSRRRRRQQMLECDysnd9[[", +">>-**&%$@+... ..+$*->//////(3jCMQRRRRRQOMLJJJFFzv44,,,''477ppzzAAACxxtijbjlyCELLLLJGGDDBwuuuuuwBBDGJLMOOMLJDBuhdd9ddgnic12))!!!!!)77ppvvzpp7!!!@@$$$%%%%%$%%%%&*~==~*&%$$@@@$$$$@$%&~:biCJOQQRRRRRRQOMLJJLMOQRSSSSSSSSRRQOMMOOQRRRSSSSSRRRRQOMLGCywsg96[[", +">;=*&&%$@+... ..+%*;>////>((btFORRRRRRQOMLLJLLIIvv555555vvHHIIIFFAAxtljjjitCELLLMLLJGDDBwuuuuuwBBDGLMOQQOMLGDwsghdddaab12)))))){22|ozzIIIzpo|))$$$$$$$$$$$$$$%%&*~**&%$@@+++@@@@@$%*-:aiCJMOQQRRRQQOMMLLLMOQRSSSSSSSSRRRQOOOQRRRRSSSSSRRRRRQOMLGCysnd9[[^", +";=*&&%%$++... ..+@&=;>//(>>::iAIRRSSRRRQOMLLLLMIIHvqqqqqKPPNNNNNIFEAxtljjitxELLMMMMMLJGDDBwuuuuwBBDJLOQQQQOMLGDwngddda:<2)))){21///>;;<1kFQSSSSSRRROMLLLMOOHHKKKKKPPPNNSSSROMJAxtljjiyCJLMOOOOMMLJDDBBwuuuwBBDJLOQQRQQOMJGywngaaa<2{)!||21cclxAFMOOOOMFAk2{)$$@@@++++++++@@$%%%$@@+++.+++++@@%&->3ajtDGLLMOOMMLLLLMOQQRRSSSSSSSSSRRQQQQRRRRRRRSSRRRRRRRQOOLLGDtnd[[^/", +"%%$$$$$@+... ..+@&=>>//(>;-12oINSSSSSSRROMLLMMONNNPPPPPPNSSSSSSSRMFExtljitxGLMOOOOOOMLJGDDBwuuuwBBGJMQQRRRQQOLJGDtigbc12|777okktxxEFMOOQOOOIzo2{)$@@++++++..++++@@@@@+++....++++@@%*-(3djsyCGJLLLLLLLLMOQRRRSSSSSSSSSRRRQQQRRRRRRRSSRRRRRRRRQQOMLEDtg9[///", +"@@@@@@@@+... ..+@%*;>//((:;=12zISSSSSSSRROMMLMOQRNNNNNNNSSSSSSSSSROFCxtiistCELMOOQQQOMLJGDBwwuuuwBBGJMQRRRRRRQOMLECyti1277ppzzAACCELMOQQQQQOOIAo|!@@++..........+++++++......++++@@%*;(3ajsyDCGEJJJJLLMOQRRRSSSSSSSSSSRRRQQRRRRRRRRRRRRRRRRRQQQOMLGysa3[//;", +"+++++@@++... ..+@%*;>///((:;<1kzNSSSSSSSRROMLLMORRSSSSSSSSSSSSSSSSROFCttiisyCJLMOQQQQOOLJGDBwuuuuuBBGJMQRRRRRRRQOOMJGCxopvvHHIIFFJFLMOQQQRRRROIzp|!+++........................++++@$&=>(3antyDCGEEJJLLMOQRRRSSSSSSSSSSRRRQQQRRRRRRRRRRRRRRRRRQQOOLJCtg9[//>=", +"++++++++... ..+@%*;>////((>:<3djsyDCCGEJJLLMOQRRRSSSSSSSSSSSRRQQQRRRRRRRRRRRRRRRRRQQOOMJCtn9[[/>;*", +"....+++.... ..+@%*;>//////(>::=&", +"........... ..+@%*;//^^/[[/((>(:lFORSSSSSSRQOMLLMRSSSSSSSSSSSSSSSRRRQMCtsinssyDJLMOQQQOMLGDywurrrruuBBDJMQRRRRRRRRRRRRQONNNNSSSRRQOMMOOQQQQRRRRRRNIp7''+............ ...++@$%&=:3gsyCGGEJLLLMOOQRRRSSSSSSSSSSSRRQQQQRRRRRRRRRRRRRRRRQOMMLECynd6[^^>-&%", +".......... ..+@%*;//^^^[[[//(((3iEORSSSSSSRQOMLMORSSSSSSSSSSSSSSSRRROLCtsnnswyDJLMOQQOOMJGDBwurrrruuBBDJMQRRRRRRRRRRRRRNNNSSSSSRRQOMMOOQQQQQRRRRRNIz4''++.++......... ...+@$%*-:bixCGEJLLLMOOQQRRRRSSSSSSSSSSRRQQQQRRRRRRRRRRRRRRRQQOMMLJCysg9[^^/;*%@", +".......... ....@%*;/^^^__[[[/((((3bCMRSSSSSSROOMLMORSSSSSSSSSSSSSRRRRROLCytssswyDGLMOOOOOLJCywwurrruuuBBDJMQRRRRRRRRRRRRNSNSSSSSSRRQMMMOOQQQQQQRRRRRIzp7!+++@@++++..... ...+@@%*=&@+", +"..............+$&->/^^__}}[[/(((/3bxMQRSSSSRROMLLMORSSSSSSSSSSSSSRRRRROLGCytwwByDJLMOOOOMLGDywwurrruuuBBDJMQRRRRRRRRRRRRSSSSSSSSRRQOMMMMOOQQQQQRRRRROIp7!!@@@$$$@@++.... ...+@%{=&@+.", +".............+@&=>/^^__}}[[(((>(/(axLQRRSSSRROMLMMORSSSSSSSSSSSSSRRRRROMLGCDyyyDGJLMOOOOMJGDywwuuruuuwBBDJMQRRRRRRRRRRRRSSSSSSSSRRQMMLLLMMOOOQQQRRRROFo|!$$$%%%%%$@+.... ...+@){1ctDCEJLMMOQQRRRRRRSSSSSSSSSSSSRRRRRRRRRRRRRRRRRRRRRRQQOOLJDwn9[/>-&$+..", +" ...........+@%*;/^^__}}6663((>//(9tEORRSSRROMLLMMORSSSSSSSSSSSSRRRRRRQOMLLEGCDGJLMOOQOOMLGDywwuuuuuwBBDGJMQRRRRRRRRRRRSSSSSSSSRRROMJEEJLLMMMOQQQRRQOzo|)$$%%&&&%$@++... ..+@${1clxCGJLMOQQRRRRRRRSSSSSSSSSNSRRRRRRRRRRRRRRRRRRRRRRRRQQOMLGyn93(-&$+...", +" .........+@$*->/^^_}}60003(((//[9lEMQRRRRQOMJJLMQRRSSSSSSSSSSSRRRRRRQQOOMLLJJJLMOOQQOOMLGDywwuuuuuwBBDGJMQQRRRRRQQQRRSSSSSSSRRRQOLEGGGEJLLLMOQQQQOFA2{)$$%%&&&%$@+.... ...+${/^^_}}60fd03(((//[3jxMOQRRQOMFEGJMORSSSSSSSSSSSSRRRRRRRRQQQOMMLMMOOQQQQOMLGDywuuuuuwBBBDGLMQQRRRRQQQQRRSSSSSSSRRRQMLEGCCGGGJLMOQQQQOFo2{)$$$%%%$$@++.... ...+$&<:bixCJMOQRRRRRRRSSSSSSSSSNNNNRRSSSSSRSRRRRRRRRRRRRRRRQQQMLCwg3(-&@+.. ", +" .......++$&=>/^^__}}0ddd03((////3atEMOOOOMFGCCGLORRSSSSSSSSSSRRRRRRRRRRRQQQOOOOQQQQQQOMLGDywuuruuwBBDDGLMQQRRRQQQQQRRSSSSSSSRRRQMLEGDDDDCGJLOQQQQMEk2)$$@$$$$@+++...... ...+$&-(ajtCJMOQRRRRRRRSSSSSSSSNNNNNNSSSSSRSSRRRRRRRRRRRRRRQQQOLJDsa3>~%@.. ", +" ......++$&=>/^^]__}60ffd03(///^^[3iCFMOMMJCDyDGLORRSSSSSSSSSSRRRRRRRRRRRRRQQQQQQRRRQQOMJCywurrruuBBBDGJLMQQQQQQOOOQRRRSSSSSSRRRQMLEGDDDDDCELOQQQOMAk2)$@@@@@+++........ ....@$&-(3gtCLMQQRRRRRRRSSSSSSSNNNNINNSSSSSSSSRRRRRRRRRRRRRQQQOMJCwg9(;*$+.. ", +" ....+++@%*;/^^]___}60ef03((//^^^/3axAFMFFAxywyDJORRSSSSSSSSSRRRRRRRRRRRRRRRRQQRRRRRRQOMGDwurrrruwBBDGGJLOOQQQOOMMOQRRSSSSSSRRRQOMLEGDyyyyDGLOOQQOFCl{)$@@++++.......... ...+@$*;(3bxEMOQRRRRRRRRSSSSSSNNNHHINSSSSSSSSSRRRRRRRRRRRRQQQOMJGynd3(-&@.. ", +" ....++@%*->/^]]__}}60e003(//^^^^^[9lxEEEAxtsswDJOQRRSSSSSSSRRRRRRRRRRRRRRRRRRRRRRRRRQOLGysrmmmruwBDDGJLLMOOOOMLLLMOQRRSSSSRRRRQMLJGDyywwwyGLMOQOMFx1{)$@+++............. ...+@%*;(3jxFMQQRRRRRRRRRSSSNNNNHHINNSSSSSSRSSRRRRRRRRRRRRQQOMLGysg93:*$+. ", +" ...+@$&->/^]]]__}}800063///^^^^^[3btCAAxysissDJOQRRSRRSSSRRRRRRRRRRRRRRRRRRRRRRRRRRQOLCwummmrrwBDDGJJLLMOOMLLJJJLOQRRRRSRRRRQOMJGCDywuuwyGLMOQOMAk1{)@@++............... .....+@%*;(bxFMOQRRRRRRRRRRSSSNNHHHIINNSSSSSSRSSRRRRRRRRRRRRQQOLJDwnd3(=%@.. ", +" ..++@%*;/^]]]___}}66666[//^^^^^^^3alxxxxtinnsDJORRRSRRRRRRRRRRRRRRRRRRRRRRRRRRRSSRRROJDwnmmmruBDDGJJLLLMMMLJGGGGJMQRRRRRRRRQOMJGCDywuuusyGLMOOMFAl1{%@++........................++@%~:alEMQQRRRRRRRRRRRRRNNHHzzIHNNSSSSSSRSSRRRRRRRRRRRRQQOLGysg9(-{@+. ", +" ..++$&->/^]]]____}}}6[[[//^^^]]^^39jtxxtijnnwDLORRRRRRRRRRRRRRRRRRRRRRRRRRRRRRSSSSRRMJDwrmmmrwBGGJLLLLMMMLJGCCDGJMORRRRRRRQOMJCDyywwurrsyGLMOOMExl<{%@+.......................+++@$&=:lAMQRRRRRRRRRRRRRROIzzpppzHNNSSSSSSSSRRRRRRRRRRRRRQOMJDtna3:~$+. ", +" ..+@%*;>^]]]]]___}}}}[[[/^^^]]]^^[3bltttinnsyGLQRRRRRRRRRRRRRRRRRRRRRRRRRRRRRSSSSSSQMJDwnmmruBDGJLLMMMLLJJGDDDDCELOQRRRRRQQMJCyyywwuumrsyGLMOMLAkc<~%@+... .....+++....+++++@@$&*:jAMQRRRRRRRRRRQOFAk12{))!7vHNNSSSSSSSSSSSSSRRRRRRRRQOJCtg93:~)+. ", +" ..+@%*;>^]]]]______^^^^^]]]]]]]]_^[[9gnistDGJMQRRRRRRRRRRRRRRRRRRRRRRRRRRRRRSSSSSNNOLGywuwwBDJLMOOOMLJGDBwwyDGJJLLMMOOOMLGysnnruwBwwwuwyGJLLLExj3(>-&@+... .....+@$%&*=-;>>>>>>>>(alAMOQRRRRRRRQQOLAkl1{)))|pvHNNSSSSSSSSSSSSRRRRRRRRQOMEDsa9(-{@+. ", +" ...+$&->/^]]_____}[^^^^]]]]]]]]]__[[9dgntyCELOQRRRRRRRRRRRRRRRRRRRRRRRRRRRRRSSSNSNROLGywwwBDGLMOOOMLJGDwsstDGJLLLLLMMMMLEDtnnnuwBBBBwwBDGJLLExia3/(;&$+.........++$%&*-;>>////>>>/(atEMOQQRRRQQQOMLExl<1{{))7pHPNSSSSSSSSSSSRRRRRRRRRRQOLGyia3:~)+. ", +" ..+$&->/^]]___[[[[^^^^]]]]]]]]]__[[69gntDCJLOQRRRRRRRRRRRRRRRRRRRRRRRRRQQQRRSNNNSQMLGDBBBBGJLMOOMMJGDwunsyCJLMMMMLLLLLECtsnnswBDDDBBBBDGJJECtb3///;*$+.........+@%&*-;>//////////(atCLMOOQQOOOMLJExlc<<~{{|7vHNNSSSSSSSSSRRRRRRRRRRRRQMJCtga3<{@+# ", +" ..+@&=>/^^]_[[[[[[[^^^]]]]]]]]]___[60dntDGJMOQQRRRRRRRRRRRRRRRRRRRRRRRQOOMOORNNNQOMJGDyBBDGJLMMMMJGDwumnsyELMOOMMLLLJECyssnswBDDDDDBByDGGGCtj93^//;*$+........++$&*=;>>//////>>>/(aixELMMMMMMLJECxlca:<~{{|pHNNNSSSSSSSSSRRRRRRRRRRRQOLGysga:~!+. ", +" ..+@&=>/^^^^[6666[[^^^^]]]]]]]]____}0dntCELMOQQRRRRRRRRRRRRRRRRRRRRRRQOMLFFMOOQQOMLECDBBDDGLLMMMLJDwughgsCJMOQOOMLJEGDysnnnuwyDGGDDByDDCCDtj93^^//;*$+........+@%&*-;>>/////>>>>//3btxCEEEEEECCxtlba::<~~2ozHNNSSSSSSSSSSSRRRRRRRRRRQMJCwna:<)@+# # ", +" ..+$&->/^^^[[6666[[^^^^]]]]]]]]____[0dntCELMOQQQRRRRRRRRRRRRRRRRRRRRQOMJGCCEFMOOMLJGDDBBDGJLLMMLJDysngggtCLOQQQOMLECytsnghnsBDGGJGDDDDDDDyja3[^^^/;*%+.......++$&**-;>>>>>>>>;;>>((9jityxxxxxxttiba3(:<<12pIHNNSSSSSSSSSSSSRRRRRRRRQQLGDsna<{!+. ", +" ..+%=>/^^^[[6666[[[^^^]]]]]]]]]]___[6dntCELMOQQQRRRRRRRRRRRRRRRRRRRRQMJCytyxCEFFJEGDDBBBDGJLLLLJGDwngdgiyEMOQQQOMJCysngddhnuBGJJJJGDDDDyysg9[^^^^/>*%+.......+@%&*==-;>>>>;;---;;>((3aggjiiiiiibaa3((:<<2ozHNNNSSSSSSSSSSSSSRRRRRRRQOLGysb:~)+.# ## ", +" .+$*;>^^^^[[666[[[^^^^]]]]]]]]]]___}60ntDGJLOOQQQRRRRRRRRRRRRRRRRRRQOLCysiistDCCCCDyBBBBDGGJLLJJDBshddgixJMQQQQOLEDtngdddhuBGJLLLLJGDDywsg9[[^^^^/>=&@+.....++$%&**=---;;--=***==;>((333aaabccba:(((>:<12oINNNSSSSSSSSSSSSSSSRRRRRRQOLCyic1{!+## # ", +" ..@&->/^^__}[[[[[[^^^^]]]]]]_]]]_____69gsyCJLMOQQQQRRRRRRRRRRRRRRRRQOMGDwngggiswyyywwwwwBDDGJJJGDyundaaaiCFOQQQQOLEDsndddhuBDJMOOOMLJDDBsgd6[^_]]^/>-&$+.....+@%&***======***&&&&**=;>>((::::::::((((>::1ozINNNSSSSSSSSSSSSSSSRRRRRRQOLCyic2)+.#### ", +" ..+%*>/^]]__}}}[[[^^^]]]]]]]]]_]______[0dntDGJLMOQQQQRRRRRRRRRRRRRRRQOLCysndddgnnsssuuuuuBBDGGGGDywnd93abiCFOOQQOOLGDsnghhrwDJMOQQQOMJGysnd6[[__]]^^/;*$++...+@$&**======***&&%$$$%%&*=----=<<<::((((((:blAINNNSSSSSSSSSSSSSSSSSRRRRRQOLGyl1)!'#### ", +" ..+$*;/^^]____}}[[^^^^]]]]]]]___]_____}[9dnsyCGJLMOQQQRRRRRRRRRRRRRRQOMEDsnddddddhgmnrrruuwBDDDGDBwmd93::bixFOOQQOMLEDwsnnswDJMQQQQQQMLGysg9[[^__]]]^/>=&@++++@$&*=---===***&%$$@@@@@$%&&***~~=<::((((((:ckAIQNSSSSSSRRSRSSSSSSSSRRRRRQOJCk2|!'##### ", +"..+$&;>^^]________^^^^]]]]____________[[69dgswyCEJLMOOQQRRRRRRRRRRRRRQOLCyuhd00660ddhhmmrruwBBDDDBwrd03::::ixJMOOQOOLJGDBwwBDJMOQRRRQQOLGynd6[[^___]]^^>-&%@@@@$&*=;;;;--=**&%$@+++++++@@$%%&{*~=-:((((33alxFORRSSSRRRRRRRSSSSSSSSRRRRRQMJCk|!'#### ", +"++$&->^^]]_____________]_____________[[69ddgnsyDDGJLMOOQQRRRRRRRRRRRQQLEDsmdd0666600ffhmmruuwBBBBwrh03(:-<>>;;;-**&$@++......++@$%%&{~~<::(333aixEMOQRRRRRRRRRRRRSSSSSSSSRRRQOMAk2!'### # ", +"@%*;>^^]]___________________________[[6dggnnsswyyDGGJLOOQRRRRRRRRRRRQOLDBrhd0666[660ffhmmrruuuwwumh03(:-===*&%&&*-;>>>>>;;-*&$@+..........+@$)){{~<<:aaagitCJMOQRRRRRQRRRRRRSSSSSSRRRRRQMJxk|!'## ", +"&=;/^^]]___________________________[[9gnsssssswwByDDGJMOQQRRRRRRRRRQOLGysmhe066[[[60ffhmmmmrrrmmhf03(>;===-*&&&*-;>>>>>>;;=&%@+..... ..++@$)){211cccityCJMOQQRQQQQQQRRRRRRSSSSRRRRRQOFCl2!'## ..", +"->//^^________^____________________[9gsyDDDyywwwwwBDDJLMOQQRRRRRRRRQOLDBuhfe06}}}[60fhhhmmmhhhff033((;-===;****=;>>>>>>>;=*%@+.... ..+@!!))|2kkkkxDGFMOOQQQQQQQQQQRRRRRRRRRRRRRQOLEt1|!'# .+@", +"(((/^^[[}}[^^^^___________________[6gsCEJEGCDywwsuwBDGJLMOQQRRRRRRQOLGDwrhee066}[[60dhhhhfff0063(((>>;===-:cyGLMMOOOOQQQQQQQQRRRRRRRRROLGytsjjnnng96[[//>;**&*=;>>>>>>;=*&$+.... .+++!!!!||ooCAEFMMOQQQQQQQQQQQRRRRRRRRRRRRRQOMExl1)@. .+@)", +"ba93[[[6[[[[[^^^__________________[dsCJLMMLJGDywsswwBDGJLMMOQQRRQQOMLDBumhee066}}660dhhhdd0633(((>>;-=~==-:ixGJMMMOOQQQQRQRRRRRRRRRRRRQMJCyyyyyttng96[//>-*&&*=-;>>>;-=*&$++... ..++!!!77ppzzFMOOOQQRQQQQQQQQQRRRRRRSRRRRRQOMLCtc1)+. .+@)~", +"xtingdddd066[[^^_________________[0gyEMOOOMLJGDBwsswBDDGGEJLMOQQQOOLJDwumhee866}6600dddd0663((>>;;-=***=-:bixELLMMOOQQRRRRRRRRRRRRRRRRQMLECCCCCDysgd6[//;=*&&&*=;;;;-*&%$@+... ...+@@!!77pzzFIOOOQQQQRQQQQQQQRRRRRRSRRRRRQOOLExi:~)+. ..@)21", +"JECyttsnngd96[[^________________}[9sCLOQQQOMLEDywsuswwBBByDCJMMOOOMLGywrmhee066666099d9033((>>;;-==****=;:btCELLMMOOQRRRRRRRRRRRRRRRRRQOLJEGGEGCysg9[[/>;*&%%%&*=--=*&%$@+.... ..+@@!!!77pzFIOOOOQQQQQQQQQQQRRRRRRSSRRRRQQOMJCtb:~$+. .+!|2o", +"OMLLECDytsgd3[[[________________[6dtEMOQQQQOLJCywsuuuuunnnntxELMMLLEDywrmhee006666699333(((>;;-==*****=;:3gtCELLLMOOQRRRRRRRRRRRRSSRRQOMLJJEGGCDtn9[[//>=&%$$$%&***&&%$@++.... ..+@@$))||opzFIOOOQQQQQQQOOOQQRRRRRRSRRRRRQOMLExja<&@+. ..+)|oF", +"RQQOOLJGDtna96[[_______________[[6gtEMOQQQOOLJCywsrnmhhd999ajtCELLJGDywrmmee80666[66333/(>>;-===***==-;>(3iyCJJLLMMQQRRRRRRRRRRSRSRRROMLJGGGCDysn9[[^/>-*%@@+@$$%&&%$$@++.... ....+@%&*~22kAEFMOOOOQQQOOOOOOQQRRRRRSRSRRRQQOMFCtb:~$+.. .+!|oFI", +"RRRRQOMJGxig93[[[}__________^^[[[6dsCJMOOOOMLGDwsnmhhd06[[[39jtCEEGCDywummhee0066[[[[//(>>;-======-;;>>(3asyGJLLLLMQQRRRRRRRRRSSSSSROMJECDDyttjg9[[^//;*%@+++++@@$$$@@+++.... .....+@%*=-:>;-=====-;>>(//[3gtCEJLLLLOQQRRRRRSRRSSSSRROFEDytsnngg9[[^^^/>=&@++....+++++++++..... .. .....++$&=;>(actCEJLLMMMOMMMLLLMOQRRRRRSRRRRRQOMMFClc<{@+.. .+!7INSS", +"SSSSSSQOFCtja9066}}}}}_[/////((>>((:bilkxxxytigdd0066[[/^^^^/3ajtyDDDyBwurmhhd006[[////>;;-===-;;>////[6dsDGJLLLLLOQRRRRRRSRSSSSSQIExljggdd96[[[^^^^>-&$++.......+++++++...... ......+@%*;>((ajtCCEJLLLLLLLJJJLMOQRRRRRRRRRRQOMMFAtc<~$+.. ..+!7zNSSS", +"SSSSSRROFAxigd9066}}}[[//(>;;;------<<<<1cccaa33333[[[/^^^^^^[9gttyyyyBywwummhd06[[////>;;----;>>//[[[3dnyCJLLLLLMOQRRRRRSRSSSSSQFAlba336[[[[[__]^^>-&$++.........++++@++.............+@%*;(/39jtDCGGEJJJEGGCCELMOQRRRRRRRRRQOMFECxib<{$+.. .+!7pHSSSS", +"SSSSRROOFAxtjgdd066}[[/(>;=********~~~~~~~<<::(((///////^^^^^/3ajsyyyDDDyywurnd96[[////>>;;;;;>(/([39dgntCELLLLLMOQQRRRRRRSSSSRQIClb3([[[[[^__]]^^>;*$++..........++@!!!@++...........+@%=;//3aitDCCCCCDCDDyyyCJMQRRRRRRRRRQOMJExtjb:=&$+.. ..+@!pINSSSS", +"SSRRRQOMMJECysnhd06[[/>;=*&%%%&&&&&****{{**~=-;>>((//////^^^^^[9gstyyDDDDDyBsng93[[////>>>>>>>((33agjstDCELLLLLMMOQRRRRRRSSSSSOIxla((/^^^____]]^^>;*$@+.........++@!)))))!@++.........+@%*;(/3aiyDDDDyyBwwtstyCLOQRRRRRRRRQMLECxtjb::=&@+.... ...+!|oINSSSSS", +"RRRQQOOOMMLJECyshd93(>-*&%%$%%%&&&&*&*&&&&&**==-;>>>>////^^^^^[9gjtyDDCGGGDywsg96[///////(>>(((39gitxCGELLLLLMMMOQRRRRRRSSSSSOFCla((/^^^]]]]]]^^>;*%@+.........+@$){22222{)$@++.......+@%*;>/3gsyDDDywwunnnisyELOQRRRRRRRQMFECxtjba(:=&$@+.........+@!|ozNSSSSSS", +"RQQOOOOQQQOOMLGysh93:-*&%$$$%%&&&********&*****=-;>>>///^^^^^^[3gjtyDCGGEGGDysg9[[///////////[39gtCEJLLMMMMMMMMOQRRRRRSSSSSSQMAla3(/^^^]]]]]]^^/;*%@+........+@$&~1<1lcc<<~{%@+........@%*;>(3gsyDDywsnmhhgntxEMQRRRRRRRQOLECxtiba3(:=&$@++.....++@$)2kzIRSSSSSS", +"OOOOOQQRRRQQOMLCyia:;~*&%%%%%&&**=====********==-;>>>//^^^]]]^[3antyDCGEEGGDysd9[[[[[[[[///[[69gtCJMOOOQOOOOMOOQRRRRRSSSSSSRIAkb3(/^^^^]]]]]^^/>=&$+.......+@$%*=::bbbcb::-~&$@+.......@%*->(3gsyyyBsnhdddgiyELOQRRRRRRRQMJCxtljba3(:-*%$@+++++@@%&~1kAIRSSSSSRR", +"MMMOQQRRRRRRQOMExia:-~*&&&&&&**=--;;;;;---====--;;>>/^^^]]]]]_^[9nsyDGGEEEGDwnd6[[[[[[[[[[[669gsDEMOQQRQQQQOOOQQRRRRSSSSSNNIzkc33/^^^^^]]]]]^/>-*%@+......+@$&~->((33aa3(:-=*%@+.......+$&=;(3gsyywsnhd09djtCJMOQRRRRRRROMExtiija33(>-~&%%$$$$%&*=-:lAIRRSSSRRRQ", +"FLMOQQRRRRRRQQMExib:-=**&***==-;;>>>>>>>>>>;;;;>>>//^^]]]]]]]_^[9nsyCGGEEGCysg9[[[[[[6660600dgsyELOQRRRRRQQQQQQRRRRSSSSSPPHzo1:((//^^^^^]]^^^/>-*%@+......+$&=;>(((333((>;-=&%@+.......+$&*->3aitssnhd069diyELOQRRRRRRRQOLExtija93((>;-=*&&&**=-;>(cxFORRRRRRQQO", +"EFMOQRRRRRRRQOFCtc::-=~****=--;>>>>///////////////^^]]]]]]]]]__[9gsyCGGEGCytnd6[[[[60dfdhhdhmsyGLOQRRRRRRRQQQQRRRRRSSSNPKKv7|1:((/////^^^^^^//>-*%@+.....+@%~;>(/////((;-=~*&%@+.......+@%*-:(aninnd06669gtCJMOQRRRRRRRQOLCytjga33(/(>>;;--;;>>//3bxFOQRRRRQQOMF", +"CELOQQRRRRROMFAklc:-=~*****=-;>>>///^^^^^^^^^^^^^^]]]]]]]]]]]]^[9gsyCCGGCDtsd96[[[60dhmrrmmruwDJOQRRRRRRRRQQQQRRRRSSSNPKq54'!{=;>(//////[[[[(/(;=&%@+...+@%*->((/[///(;-**&&%$@+.......+@%*=;:agggd06[[39gtCLMOQRRRRRRQOMEDtiga33(/////>>>>/////3bxEMOQRRQQOMFEC", +"xEFMOQQOOOIFAolc<<<~~*&&&**=-;>>//^^^]]]]]]]]]]]]]]]]]]]]]]]]]^[3gsyDCCCDtsgd06[660dmuwwwuwwBDGLOQRRRRRRRQQQQRRRRSSNPKqq5,,'@){=;>(((33aabbbaa3::~&$@+++@$&=:(333[[/(>-*&%%%$$@++......+@%*=;(aagdd3[[[39gtCLMOQQRRRRRQOLCyiga33[////////^^^^^[3btEFOQQQQOMFAxtl", +"tCEFMMMIFAokk211~~~{&%%%%&**-;>/^^^^___]]]]]]_________]]]]]]]]^^[ajtyDyytsgd906600dnuwBBBBwByDJMQRRRRRRRRQQQQQRRRSNNHq5,,##.+@%*-::abblxCCACxtib:<{%$@@@%*=:33aad333(:=&%$$$$$@@++.....+@%*=;:3ada33(/(39jtCJMMOQQRRQQOLGysga93[///^^^^^^^]^^[3btCFMOOOOMFAxijba", +"ltxCAAAoo||22{{{{{&%%$$$%&*=;>//^^______]]]]]__[[[[[^^_]]]]]^^^^[9gjtttsngd99000dhnuBDDDDBBBDGLOQRRRRRRQQQOOQQQRRNHv5,,### ..@${~//^_______]]]]]__[39999[[^_]]^^^^^^[3dgnnggd990090dhnsBDDDDDDBDDJMOQRRRRRQQOOMMOOQOOIv4,### ..+${1clxEMOQQRRQOMEyi1{))%{=::aityxxttja::={%%%%&&&&%$@++++@%&*=-:::a:3((((39gsyDGJLMOOOOLEDsg9[[^^^^^^^]]]]]_^[3gtCELMMFFECxja99339", +"9aaab<1{{))))))))))%%%%&*=;>//^_________]]]__[9ajjjg93[^^^^^^^^^/[39dd99666609dhnswBDGGGDDDDGJMOQQRRRQOMLLLLMMMMzp4'## ..+${1lkAMOQRRRRRROJx22{)&*=:agtxCCECCxtja:=~&&&&*****&%$@@@$%&*~=<<:::((((33dgityDGJLLLLLGDsg9[[^^^^^^^]]]]]_^[9gtCEJFFFECxtja9936[6", +"333(::=~~{{{{{{{{{{{{*~=;>(//____}______]]__[6ajttttj9[[^^^^^^^^/[[6366[[[[660dgnsBDDGGGDDDDGLMQQQQQQOMLEGCCCECoo7'## ..+${>;;---<<<::<:-:::((/[[}}}}}}_____]_]__[9nsyyytja3[^^^^^^^^/[[[[[[[[[[60dhnuwBBDGGGDDDCGLMOQQQQOLECyttttll2)!'. ..@%~:ctEMQRRSSSRRIzo2{{{~::gtCELMMMLLECtb::;--;;;>>>>>>;-=~~~~~~~~1<<::((333dggnnswyDDDysnd6[[___]]]]]]]___[[3aitCAACxtljbaa99999936", +"[[///////((333aa93333333[[}}}}}}}}_____]]__[[djtyyysnd6[^^^^^^^^^[[[[[[[[[[60dhnuuwBDDDDDDDGJLMOQQOMLGDsjgaac1{)++.. ...@%~:aiAMQRRRRRRIzo22{{~::btCJLMMMMMLECtb:::>>>>>////^//>>;;--=~~~11<::33339dghggnsswwsng96[____]]]]_____[[[3ajtxxCxklcbaa9dddddd996", +"[[^^^^^[[[69dddhddd00066666}}}}}}}____]]]__[6dnswwsnh9[[^^^^^^^^[[[[[[[[[[[60dhmuuwBBBDDDDDGJLMOOOMLGyja93(:~{!@+.. ..+@&=>3bxFOQRRRROIAk2~~<::btCJMMOOMMMMEClc:(>>>////^^^^^^///>>;-=~~11<::33399dddhhgnnsnng96[[^___]]___^[[[[69agittkkllcbaaaddhhhhhd06", +"[[[[_[}[660dhmmmmhhfee0008888}}}}____]]]]__[6dgnnngd06[__]^^^^^^[[[[[[[[[[60dhmrruuuwwBByyDGJLMMMMLGyja3((-*%$++.. ..+@&->(atEMOQQOOFAk1<<::abtCJMOOOOOMMLExlb:(((////^^^]]]^^^///>:-<111cba3999ddddhhhnnngg96[[________[[[699dgggjiiliccc:aadddhmmnmhd06", +"[____[}60dhmmuuurmhfeee8888888}}____]]]]]__[60dhhdd06[___]]]^^^[[66[[[[[[[60dhmrrrruuuuuwwyCELLMLJGysa3((-*%@+.... ..+$*;((3jxJMMMMExlc::((3aiCJMOOOOOOMMFExia:(((///^^^^]]]__^^//((:<<//3aixEEAxtca3((33diyEMOQQQOOOMMJCtb:(((////^^^]]]]___^^//((:-&$@+... ...+@%*;///^[[[999933[/[[[6dsDLOQQRQQQOMLJCtja3((/////^^^]]]_____^^[(((:abnitwyyDCGEJJJJGDysnhdf006600dmsyCGEECylcc:::::300fhmrrrrmhe06}}_", +"___}}60fhmuuwuurmfee00086}}}}}___]]]]]]]____}}}}}}_____]]]]_^[0dhmmhdd0ddhnwBBwwrmhe0000dntCGJJEDtj93[/>-&$@+..... .....+@&=>///[^^[[[[[[[^^^[[6dnyJMQQRRRQQOMLExlba3((////^^^^]]]]]]__^^[/(33agisyyDGEJLLMMMMLGDwsnhhfffefhmsyCGEECxlcb:::(3300femmrrmmhe06}}__", +"____}60fhmuuuurmhf000666}}}}}____]]]]]]]____}}}}}______]]]__[60hmmmmhdddhuwyDyBumhe06660dntCEJEGytg93[//;*&@++........+@$*->//[[[[^^^[[[_^^___}0hBGMQQRRRRQQOMLExib33(////^^^^]]]]]]]__^^[/(3aansyDCGJLLMOOOOOMJCywurrmmhhhhnsyDCCCxlca::(33660eemmmrmmhe06}____", +"____}}0dhmuuuurhd00666}}}}}}____]]]]]]]]___}}}}}_______]___[[6dhmmmmhhhmuwyDDDBumf06}}60dsyGEJECytg93[//>;*%$@+++++++@@%*;>/[[[[[[[^^^_______}6duDLOQRRRRRQQOMJCtja3(////^^^^]]]_]]]]___^//(3agsyDCGJLLMOOQQQOMLGDBwwwurrmmmnswyyytiba33336660eemmrrrmme06}}____", +"____}}0fhmuuuumhf0066}}}}}}____]]]]]]]]____}}}}____________[}0fhmmmmmmnuwDCGGDBrh06}}[69gtCEJJECytg93[[//>;*&%$@@@@@@$&*;>//[666[[[/^^______}6fmBJOQRRRRRRQOMLGxia3((///^^^^^_____]]]___^^/(3aitDGJJJLLMOOQQQOMLGDDyyBwwuurmniiiicba:33336660eemmrrrrmhf06}____]", +"____}}00hhnrrnhd006}}}}}}}_____]]]]]]]_____}}}}__________[[[60fhmmmmmnsyDGJJGDwnd6}}_[69jyCEJJECytja9[[^^/>;=&&%$@@$$&*;>//[[6663////^___}}}60hwGLQRRRRRRRQOLECtg93(///^^^^^_____]]]]]]]^^/(3atDGJJLLLLMOOQQQOMLGGCDDDDBwunnggaaa::(((3[[660eemruuwuumhf06}____]", +"___}}60dhhnnnhd0066}}}}}}}____]]]]]]]]____}}}}}_______^[[[[600fhmmmmrswDELLLJDwh06}_[[6atxEEJEECytjg9[[^^//>-*&%%$$$%*=>///[6633(((/[[}}}}60fmuDLOQRRRRRRQOLECtg93(///^^^^^______]]]]]]]^^/(3btCJLLLLLLMOOQQQOMJJGGGGGDDBwngaa::::((([[[660efmrwBBBBwrh06[[____]", +"___}}60dhhnnhhd0666}}}}}}}____]]]]]]]____}}}}}}}____[[[[[6600fhhmmruswDELMMLJCsh0[[^[[3gtCEEEEGCxttga9[[^//>;*&%$$$%&*;>/^/[333((((//[[600dhuwDJOQRRRRRRQOMJDtg93(/////^^^]______]]]]]]]^^//3cxGJLLLLLLLMOOOOMLJJGGJJGGDysic:::::((([[[660ehmuwBDDDywnh06[[____]", +"___}[60ddhhhhd0066}}}}}}}_____]]]]]]____}}}}}}}}}_}[[[6999ddhhhmruuwBDELMOOMLGwg0[[^[[9jtCEEEEECCxtjg9[[///;=*%$$$$%&=>//^[[[3((>>(([66dhnwyDJLOQRRRRRRRQOLCtn93(//////^^^]_____]]]]]]]]^///3bxGJLLLLLLLMOOOOMJJGGGJJGGDBic<<:::((([[[60efhruBDGGGDysnd6[[[_____", +"___}}60ddhhhdd0666}}}}}}}____]]]]]]____}}}}}}}}}}}6699ggnnnsssswwwyyDELOOQQOMEyn9[[[[39jtxCCCCCCCxtsg93[(/>-*%$@@@$&*->/^^^[///(>>(/[6dnwDGLMOQQRRRRRRRRQMJDjd3[///////^^^]]____]]]]]]]^^//((bxGJLLLLLLLMMOMMLJGCCGGGGDysic<:::((/[[660fhmuwDDGJJGDysg9[[[______", +"___}}00ddhhdd006666}}}}}}____]]]]]____}}}}}}}}}}6609gnstyyDDDCDDDCGEJLOQQQQQOLDsd3[[[3ajtxxCCCCCCxyig93((>-*%$@@@$%&=>/^^^^^^///////6dnyGLOQQRRRRRRRRRRRQMEyg93(/((/////^^]_____]]]]]]]^^//((cxELLLLLLLMMOOMLJGDDDDDDDytic<::>(//[[60fhmuwBDGJJJJGysg9[[[______]", +"__}}600dhhhdd00066666}}}}____]]]]____}}}}}}}}}}609dnstDCEJJLLLLLLLLMMOQQRRRQOMGtg93339ajittxxxCCCxtib33(;=*%$@@@@$&=;>/^^^^^^^/////[0myJMQRRRRRRRRRRRRRRQLGtg3(/(>>////^^^]_____]]]]]]^^//>>:lxJLMMMMMMMOOOMJGDwssswtttic<::((/[[[6dhmuwBDGJJLLJGDwn9[[[______]_", +"__}}60ffhhfdf00006666}}}_____]]]]____}}}}}}}}6600dnsyCELMMOOOOOOOOOOQQRRRRRRQMJyia93399gjjiltxxCxysja::-~&%$@@@@$&*;>/^^^^^^^^^^^^[6hwJMQRRRRRRRRRRRRRRQQMCta3(((>(////^^]_______]]]]]^^/>>>:lCLMOOMOOOOOOOLGDtingniiiicc::((/[[60dhuwBDGGJJLLJGCynd6[[_____]]__", +"_}}60fdhhhfff00000088}}}_____]]]____}}}}}}}66600dnsyCJMMOQQQRQQQQQQQQRRRRRRRQMJxia999999aaajityyytib:<~{%%@@@@@$&*;>/^^^^^^^^^^^^^[dsGMQRRRRRRRRRRRRRRRQOLCta3((((///^^^__________]]]]^//>;:bkEMOOOOOOQQQOMJCticaaacciccb:3([[[60hnwyDGJJLLLLJGDysd6[[______]___", +"}}}60ffhhhfffe0000086}}______]]______}}}}}6000dhnsyCJMOQQRRRRRRRRRRRRRRRRRRRQMExja933333339ajistiib<<~{%$@@@@@$&*;>/^^^^^^^^^]]]_[9nCMQRRRRRRRRRRRRRRRRQOLCtb93((((//^^____________]]]^/>;;-ckFMOOOQQQQQQOMExl1<:::ccccba336[60dhsyCJJLLLLLLJGDysg9[[___________", +"}}60efhhhhffee008086}}_____]]]_______}}}6600dhnstyCJMOQQRRRRRRRRRRRRRRRRRRRQOLCta93333[[3333abjjbb<1{)$@@@@@@$&*->/^^^^^^^^^^]]]^[gCLQRRRRRRRSSSSRRRRRRQMExtga99333[[[[____}}______]]^^/>;-<1kFMOOOQQQQQOOFAk21<<::acccgad9099hnwDGLMOOOMMLJGDBwnd0[[___________", +"}800ehhhhhfeee0806}}}}__^^^]]]]______}}600dhnssyDEJMOQQRRRRRRRRRRRRRRRRRRRROMEtb933(///////3333a:<~{!@@+++@@$&*->/^^^^^^//^^^]]^[atLQRRRRRRSSSSSSRRRRRQOLExtjbggggad966[}}}}}}_____]]^^/;-==1kEMMOOOOQQOOMzo211<:::aagggggddhnsyCJMOOQQOOMLJGDwuhd6[[___________", +"880ehhhhhefee0066}}}[^^^^^^^^^]]____}[60dhgnsyDGJLMOQQRRRRRRRRRRRRRRRRRRRQOMEtj93((/(//////((((:<~)!@++++@@$%*->//^^^^/////^^]^^3sEORRRSRRSSSSSRRRSRRRQMJCytiiitstsjndd0066}}}______]^//;-==////^^^^^[[[60dgnstyCELMOQQRRRRRSRSRRRRRRQQQQQOOMFCtba3((((>>(//////(:={)@++..++@$%*->>/^^^//>>>//^^]^[axMQRRSRRSSSSRRRRSRRRQOLExttittyyDDytsnhdd006}_____]]^//>-==>>;;>>///^^^[[[9dgnstyDCELMOQRRRSSSSSSSRRRRRRQQOMMLJCxlba::::::;>>(////(>-*%@++..++@$%*->>//^///>>>>>/^^]^[jEORRRSRSSSRRRRRRRRRQOMExttistyDCCCCCyyssnhd06}____]^^//>;-<>>;;-;;;>///^^[[[9gnsyDCCGJLMOQRRSSSSSSSSSSRRRRQQOMLGCylccc:<<<<<-;;>/////>;~&$++...+@@%*->>//^//>>;--;>/^^]^3tLQRRSRRRRRRRRRRRRRQOMExtjnnistyDCGGGCDyywshd6[___^^^///>;-<>>;;----;;>(///^^[[9gstDCGGJLMOQRRSSSSSSSSSSSSRRRRQOMLGDtic<1111111<-->>/////>-*%@++..+@@%*->>/^^//>>-===;>/^]][9yMQRRRRRRRRRRRRRRRQOLEDsnggdgnswyDGGGGGGCDysg06[^^^^^///(>:::cityyDDyytic1<=-;>(/36660dhnsyDGLMOQQRRRRRQQOLGywsnggd9966666}}}}}}", +"}}}}}[[////(>>;;;-----;>>/////[[[6dntyCGJLLMOQRSSSSSSSSSSSSSSRRRRQOMJCyic<1222|221<<:>//////>-*%@++++@$%*->>/^^^//>-***=;>^]]_[axMQRRRRRRRRRRRRRRQOMJDtndd0ddhnuwyDCGGGGGCDynd6[^^^^/////(((abittyyyttic<<~=-;>(/[[6600dhnwyGJLMOQRRRRRQOMEDwnnggdd99666666}}}}}", +"___[[///>>>>;;;-----;>>/////^/[[[6dnsyCEJLMOQRSSSSSSSSSSSSSSSRRRRQOMJDtic122|oook1<:(///////>-*&$@@@@$%*=>>/^^^//>;=***=;/^]]_[gxMQRRRRRRRRRRRRRQQOLGyshd0000ddmmuwyDGGGJECysg9[[^^^/////((3agistwwssic<<~~=->(//[[}}660dhswDGJLOQQRRRQQMLCtngdddd999666666}}}__", +"^^^//(>>;;;;;;----;;>///^^^^^^[[[0dgsyDGLMOQRSSSNNNSSSSSSSSSSRRRRQOMJDti112|ooooklb((/^^^^//>;-*&%$$%&*->>/^^^^//>-****=>/^]__[gxLOQRRRRRRRRRRRQQOMJCwnd0000000fhmrwBDGGJJGDtnd6[[[[[[[[[339agissssincc<~~~=;>(/[[}}}}660dgswyGJMOQRRQQOLCtnd9909999966666[}____", +"^//>>;------;;;;;>>>//^^^^^^^^[[[60hntyCLMORSSNNNNNSSSSSSSSSRRRRRQOLExli1122kokklca3/^^^^^^//>;-=*&&*=->//^^^^//>;-***=;>/]]__[gyLMOQQRRRRRRRRRQQOLEDtnh00000000fhmuwBDGJJGDynd9[[[[[[66639agiisssinga:<~**=;>//[}}}}}}660dnstDGLMQQQQOLCtg96[[[66366[[[[[[____]", +">>;;-=***=-;;>>>>///^^^]]]__^_}}}60dgsyGLOQSSNNNNNNSSSSSSSSRRRRRRQOLCxlcc<1lllllba3[^^^_^^^^///>;;---;>//^^^^^//>;-==-;>/^]]__6gyELOOQQQQQQQRRQQQOLECtsgdd000000ffhmuwDGGJGDysg99660999ddagjisttsinga:<~{{*-;(/[[}}}}}}}60dhnsyCJMOOOOLCtg9[[[[[[[[[[[[[[[^_^^^^", +"-==******=;;>>///^^^^]]]_____}}}}60dgsyEMOSNNNNNNNSSSSSSSRRRRRRRQOLExlibbbbbccbb93[[^___]^^^^^////>>>//^^^^[[[//>;;;;>>/^]]___6dtGLLMMMMOOQQQRQQQOLECysngddddddddfhmuwDDGGGDysngdgggnnnnniistyytsngaa:~{&{~->//}}}}}}}}}00dhnwyCELMMMFAtb3((////[[[[[[[[/^^^^//>", +"**&&&&**=;>///^^^^^]]_____}[[}}6600hsyCLOQSNNNNNNSSSSSSSRRRRRRQOMLECticbaaaaaa933[[[^____]]^^^^^^^///^^^[[[[[[/(>>>>>//^]]]___6dsDGJJJJLLOOQQQQQQOLJGDtsnngnnnnnnnmuuwyDGGGDyssnnsswttttttyxCCCxtiga:<{%%&~;(/[}}}}}}}}60fhnswyCELLMFAxl::>>>>>(((((((/////>>>;;", +"&&&&&**->>//^^^^]]]___^[[[6600000dhnyCLMORSNNNNNSSSSSRRRRRRRQOOLJGxxtijgaa99933[[[[[____________]]^^^^[[60dd063(((>//^^]]]____6dnyDGGGGJLMOQQQQQOMLJGCytsssstyyywwwwwyDDGGCDyywwyyDDCDCDDCCEEEECxtcb<{)%%&~;(/}}}}}}}}800fmuBDCEJLLLFAk1<--------;:::::::;;;--=*", +"****=-;>//^^_________[[[09dhhhhhhnsyGLMORSSSSNSSSSSRRRRQQQOOMLECDxytttsigga993[[[[[_________________[[0dgusnnd3((///^^]]]_____60nuBDDDDGJLOOQQQOOMLJGCytstyDGGGGCDyyyyDDGGCDDyyDDGEEEEGGGGELLMLJCxic~))$%&=>/[}}}}}88880ehuBDGJLMMMMFAk11=========<<<<--======~*", +"--;;>(//^^__________[[9answtwwwwwyDGLMOQRRSSSSSSSRRQQQOOMLLECDytttyxDDxytijgd93[[[[[_______________[60hsByDysnd3(//^^]]_______}0huwBBBDDGLMOOOOMLLJEGCyttyCELLLLJEGDDDDDCCDDDDDCGJLLLJEGGEJLMMMMJCk1{)!$%{->/[}}}8888880fmwDGLLMOOOOMAok1<======<<<<<<111<<=----", +"((////^__}}_______[[[9ntDCGEEEGGGJLLOOQQRRRRSRRRRQOMMLJGCDytsiiisyDGEEGCCytjga996[[[[___[[[[[[}}_}}6dmwDGJGCysg33/^^]_________}0hmuwBBDDGJLLMLLLJEGCDyttyCELMOOMLLJGCDDDCDDDDDGGJLLLLJEGGGJMMOOOLAk2|!!!%*;(/[}}6688880efuyGLMOQQQQOOFAkc<<::::::>>", +"[[[[}}}}}}}______[[6ajxGLLMOOOMMMOOOQQQQQQRRQQQOMMFECxtsnnggagjiyCELLMLLECytsngd99[[[[[[[[66666}}}6dmwDJLLLECtg93[^^__________}0dmuuwBBDDGJJJGGCCDDyysssyCJMOOOOMLJGCDDCDGGGGGGJLLLLLJGCCCELMOOOMFo|!!!!)~;([[}}68888800hsDJMOQQRRRROOFCtca3333aacitkxCCxkiba333", +"[}}}}}}}}}}}____[[3ajxEMOQQQQQQQQQQQQQQQQQQQOMMLECxtiga993399gixGFMOOOOMLJGCytjng9966[6660dddd0000fhuDJLMMLJCtg93[^^__________}6fhrruwBBDDDDDDBBwwwssnnstCLMOOOOMLEGCDDCGGGGGGJJLLLLJGDyyDCLMOQOOFA77!!!&=>([[}688866660hwCLOQQRRRRRROMJCwngdddgitxCEFFFECxigd66", +"6}}}}}}}}}}}}__[[3aixEMOQRRRRRRRRRRRRQQQQOOMLLGCytjg93[[[[[3aixEMOQQQQOOMLJECytsjgd9999ddgnnnmhdfdhuyGLOOOMJDla3[^^____________60hmruuwBBBBBwwuuumnnhhhnwCJMOOMMLEGCDDDCGGGGGJJJLLLJGDywttCEMOOOOIzp7!!){<((66600086}}60hyGLOQRRRRRRRROMJDysnnnswyGJLMMMLECtnd00", +"666}}}}}}}}}}}}66ajtAFOQRRRRRRRRRRRRRQQQOOMLJCytjg93[[[//[3aiCFOQRRRRQQOOMLJECytsjggdggnswByBwummmuBGLMOOOLExia3[^^____________}0fhrruwwBBBwuummhhhhddhnsyGLLLLJECyyyyDDGGGGGJJJJJJGDyssnsyEMOOOOIzp77!)~:(360000006}66dnyJMQQRRRRRRRRQOLGDBwsswyDGLLMMLLGDsgd00", +"666}}}}}}}}}}}60dgtxEMORSSSRRRRRRRRRRQQQOMLJGysnd9[[////((alCMORRRRRRRQQOMMLJECysjnggnswyDCGDDBwwwBDJMOQQOLGtg33^^_________]]__[6fhmruwByyBBurmhfff000ddnsyCGGCxytssswyDGGGGGGGJJJJDywnggntCFOOOOIIpp7|21:addhhhhf00660hwCLOQQRRRRRRRRQOLJDBwwuwBDCJLLLJGDwnd006", +"8888}}}}}}}}6600gjxCFINNSSSSRRRRRRRRRQQOOMLGDynd93(/(>>::blAIRSSSSRRRRQOOMMFJECytsnnnstDCEJJJJGDDDGJMOQQQOLCta3[^^______]]]]]^^[6fhmuByDGGDDwumhd0006600dgnstssnnggnswyDGGGGGGGGGGDDwngddgtCJMOOOIIvpp721innssuurmhd00hsDJOQQRRRRRRRRRQOLJDBwuuuuwyDGEEGDwnh0000", +"66888888888800dhntxEFINNNSSSSRRRRRRRQQQOOMLGDsgd3((:--=<>>>(3dsDJMOQQQOMLGysh06[[^^^^______[[[69dnsBDDDBBwuuuuumh06[[[3alCFFIIzzzzzFFLMOOOQQQOMLJEELMOQRRRRRRRRRRQQOLGDwuhffffhnwyDDDywsnddf0", +"66686000effhmuwyDCJLMOOOOOMLLLLLMMOOOOMMLJCyib::<~{{||pzHNNSSSSSSSRRROMFAzAFEECxtsnswyCJLLMMMMMMMOQQRRRRRQOEtb3(//^^^^^//>;==;(aiDJMQQRRQQOLGysh06[[^^^^_______[[60dnswyBBwurmmhhd006[[^/(3btCAzzzzAAzFMOORRRRRRRQOMMMMOQRRRRRRRRRRRQOMJDBumhfffdhsyCGGGCDtsnhdd", +"[[[[[6660fhmuwyCGJLMMOOOMFJGCCCGJJLLLLLLECxiba:<~~{||pzHNSSSSSSSSSRRQOFAAAAAEECCtssstyGEJLLLMMMMMOQQRRRRRRQMCia3(//////>;=*&*=:cxJOQRRRRRQOLGysh06[^^^^^_^[[[[[[600hnuuwwwumhff0066}___^//(aikooooooAEFOQRRRRRRRRRQQOOQQQRRRRRRRRRQQQOMJDBumhffdhnyCEJJJGCysngd0", +"////((336ddmsyCGJLMMMOMMFECxywwyyDCGGGGCxtja::<<~22ozINNSSSSSSSSSRRRQMFAooAFFFECytssyDCGJJJJLLLLLOQQRRRRRRQOFxc::((>>>;-*&%%&~;;=&%$@@%{1CMQRRRRRRQOLGysh06[[[[/[39gjjjjnnnnnmmrrmmhff06}}_____]]^/>>:<11222kkxEMORRRSRSSRRRRRQQQRRRRRRQQQQQQQQOLJDwumhddhnsDGJJEECxlca:::", +"**&***~=<:ciDELMOOOOMMLJCywsnhdddgggggga33(:--<11kAINSSSSSSSSSSSRRRQOEoooozFMMMJCyttyyDDDDDDDDDGJLOQRRRRRRRROFAk1<:--~&%$@@@${kEOQRRRRRQOMGysg96[[[//[3btxCEECDywwuurrmmhee0}}_____]]]]^/>;--<1111llxAMORRRSSSSRRRRRRRRRRRRRQQQQQQQQQOLJDwumhfddgsyDCCDxlcc<<-=~", +"%%%%%&{~<;--=<1kAIORSSSSSSSSSSSRRRQMAooopzIOOMLECyyyyyyBBwwwwBBDJMQRRRRRRRRROFok1<==*&$@++@!|kEMOQRRRQOLCtng96[[[//(3bxELMMMLJGDywuummhe00}}____]]]]]]^/>;--=<111clkAFOQRRSRSSRRRRRRRRRRRRRQQQQQQQQOOLGDwnhdddddgistiicb<<~~*&&", +"%%&&&*~~<1kALOOQQQOMLLGDBumhd0333((((((>;--==<1kAIORSSSSSSSSSRRSRRROFoo7pzIIOOOMJCyytyBBwwuuruuwBGLORRRRRRRRROMAk1<~*&%@@++@!{kCFMOOOOFExig96[[[///(3btFMQQQQOMLGDBwurhee0}}_____]]]]]^//>;;--<<<>;-===<1kAIORRSSSSSSSSSRRSSRROzp77pvINRQOMLEyttssuurmmmmrrwDJOQRRRRRRRROLCk11{&%$@+++@${1kxGEEACklba3(//^^///(3lEMQRRRRQOLJDBwrmhe0}}_____]]]]]]^//>;;::<<::bclxEMQRRRRRRRRRRQQQQQRRQQQQOOOOOOMLGysgd063[((3333((>>;---==*", +">>>>((3alCLOQQQQQOMLJCysnhd66[///(((>;-=~~~11kAIORRRSSSSSSRSSRSSSSRIzpppvHNNRQQMLCyssnnnmhheeehmrBGMQRRRRRRRQMJCk1{)!@+++.++${1cittlicb::((////////(axFQRRRRRQOLJDBurme06}_____]]]]]]^^/>>::::::::bbjtAFOQRRRRRRRRQQQQQQQQQQOOMMMMLLJCysh96[[//(((((/////>>>>>>>", +"^^^^/[9iCLOQQQQQOMLEDBsmd06[[///((((:-=~~~1koFOQRRRSSSSSSSSSSSSSSSSIzppvHHNRRQOMFCtjgdddffeeeeeehuDLOQRRRRRQOLGk22)@++....++${~>(////////(axMQRRRRRQOLGDwumhe0}}_____]]]]]]^//>:::bbbb:::bblxEMOQRRRRRQQQOOQQQQQOOMLLJGGCCxtia93[///(((///////////^^^^", +"]__^[9nyJMOQQQQOMLGDwnh006[[[//((((::<1122oAIORRSSSSSSSSSSSSSSSSSSSNHvvvHNSRRQOMExjg990000088880fmyJOQRRRRQOLCy12)@+.......+${~>>(//^^^^^^/[gxMQRRRRRQOLGBwrmee6}_____]]]]]]^^/>::ccllccb:::bclCFOQQRRRQQQOOOOOOOOMLJGCyttsijga3[/////((///^^^^^^^^^__]]", +"___[6gtGLOQQQOOLJCysg006[[[[[/((3abc112oozIIRSSSSSSSSSSSSSSSSSSSSSNNHHHHNNSRRQOLCtg96[[[}}}}}}660hBGMOQQQOMJDtc1)@+.......+@${1ccba3((((//^^^^^^^^^[gyMQRRRRRQMJDBurme86}______]]]]]^/(>:clkkklc<<:::bixEMOQQRQQQOMMMMMMMLJGDtiggdd9933//////>>///^^____________", +"__[[9sCJMOOOOMLGysgd06[[[[^^[[3abclkoAzIIINSSSSSSSSSSSSSSSSSSSSSSSNNHHHNNSSRRQMEyj93[[[______}}}6dsCLMOOMJCtib<~)@+......++@)22lliba3(///^^^]]]]__[6gyLOQRRRQOLJDwumhe06}______]]]]]^/>::1kzIIIzo22{{~=<:clALOOOOMLGxtttsssng96[[[[_^^_^^^^^^^///^^______________]", +"_[6gtCELLLEDwnd6[_____^^^[[33blxFMORSSSSSSSSSSSSSSSSSSSSSSSSSSSSRRONNNSSSSRRQMEta3[^^^^^^^^]]]___[0gsssiga::;;;;-=*&%$$$%&~1oFMMMECta93[[[[[[[___}}6fnyGLMOMLJDBwurmee06}}______]]^//:<2ozIIIzoo|)){~<:bjxEMMMMLEytjngggd90[[[___________]^^^^^^^_____________]]", +"_[9jyCEJJGDwnd6[^^^^^^^^^[33ajxAMORSSSSSSSSSSSSSSSSSSSSSSSSSSSSRROOOQSSSSRRRQMCl9[^^^//////^^^]]_[[9daaa::;;;>>>>>;-**&&&~1kAMOOMFCtb93[[[[[[[}}}}}6fhuDJJLJGDBBurmmhe06}}______]^^/>:1ozIIHHIp7|)){~-::blxEFLECxtja999066[[[_____________]^^^^^]___________]]]]", +"[9gtCEEEGCynd0[^^^^^^^^^[339blCFORSSSSSSSSSSSSSSSSSSSSSSSSSSSSSROOOORRSSRRRQOFxj3[^^//>>>>>//^^^^^/[3(::---;>>/////>;=**~=1kFOOOMFCla3[[[[[[[[[}}}}60hrBDGGGDBwurrmhe006}}}}____^^/>:<2oIHNNHHv77!){~-((3aixCCCtjg99666[[[}}}}}}__________]^^^^]]__________]]]]]", +"6atxEJJJCDsg96[/////////[33ajxEORRSSSSSSSSSSSSSSSSSSSSSSSSSSSSRQOOMOQRRRRRRQMEta[[^^/>;;--;>>//////>;;-==~=;>/^^^^//>-=*~~1oFOOOMExja3[[[[[[6666}}600fmuBDDBBwurrmhee0066}}}}___^//>:1kzINNNNHv47!){=;(((3ajlttja96[[[[[}}}}}}}6}[}_______^^^^^^]_________]]]]]]", +"gtxEJLJECyia3(((>>>>(//((3abtAMQRSSSSSSSSSSSSSSSSSSSSSSSSSSSSRRQOOOOQRRRRRQMJxj9[^^//>;=**=-;>>>>>;-=*****-;>/^]]]^/>-***~2AFIMMExla3[[[[[66666666600emruwwuurrmmeee0066666}}__^^/(>:lAINNNNNHvv7!{~->//^[39aga99[[[}_[_[_}[6660666[[____^^^^^^^]]]_______]]]]__", +"txELLLLExtja::-====-;>((3ablCFORRSSSSSSSSSSSSSSSSSSSSSSSSSSSSRRQOOOOQQRRQQOLxj9[[_^^/>-=***=-;>>;-**&&&**=;>/^]]]]^/>-*&{{2ozFFExla3[[[[[399900666000ehmruurrmmheee006666666}}_^^//(bkFNNSNNNPHv7){=>//^^[[[366[[[[_____[[[660ddd906[[[^^^^^^^^^^]]_______]]]__[", +"xEJLMLJCxic<<~{{&{{~=<::bckAFORRSSSSSSSSSSSSSSSSSSSSSSSSSSSSRRRQQOOOOQQQOMLCsa6[__^^/>;=***-;;;;-**&&&&*=->/^]]]]]^/>=*&&{|oAAAxla3[/^[[[9dddd000000eehmrrrrmmheee0066666666}}_^^//3cCMRSSSNNPHv7){->/^^^^[[[[[[[_______[[69ddnnngd0[[[[//////^^^^]___________[[", +"EFLMLJCxlc11{)!!!!)){~11koAIORSSSSSSSSSSSSSSSSSSSSSSSSSSSSSRRRRQQOOOOOOOMJCtg9[[___]^/>;---;;;;-=*&&&&**-;>/^]]]]]^/>=&%%)||ookcb((///[[9dgggdd0000eeemrrurrmmeee8088666686}}___^/(alFORSSSNNPHv7)~;(/^^____[__________[[[69gnsssng96[[////////^^^^^^^^______[39", +"EEFJECkl12{)!!!+'+!!!||ozIINSSSSSSSSSSSSSSSSSSSSSSSSSSSSSRRRRRRQQQOMMLLLEDsg9[____]]]^//>>>>>>;-**&&&**-;>/^]]]]]]^/;*&%$))||21<::>>///39dggghd0000eehruuuuurheee0006666866}}___^/3bxFORSSSSNPKv7|~:(/^^______________[[[39gjsttssga3[(/////////^^^^^[[[____[[9g", +"CCCxxkl22{)!!++''''''4pvHPPNNSSSSSSSSSSSSSSSSSSSSSSSSRRRRRRRRRRQQQOLLEGCyjg6[____]]_]^^/////(>;-*&&&**-;>/^]]]]]]]^>-*%$$@!)){{{*~=;>(/3dhhhhdf000eeemuwBBBwrmfee8000666066}}__^^[9lAORSSSSSNPKv72<((/[[____________[[[[39ajjstttsga33(((>>>(////^^^[[[[[___[[9g", +"tllic11{{)!!!+''''',45qKKPPPNSSSSSSSSSSSSSSSSSSSSSSRRRRRRRRRRRRRQOMLGDysn96[[___]]]__^^[[3993(:=*&&**-;>//^]]]]]]^/>=&$@@@@$)))%%%&~;>(6dhhhdfe000eemrwBDDDBumhffee80800006}}__^[3bxFORSSSSSNPHvo2<33[[[[[_^_______^[[[399gjtttttiga33((>>>>>(////^[333[[[__[[39", +"aaa:<~{{%)$!@+++'',5qqKKKPPPNSSSSSSSSSSSSSSSSSSSSSRRRRRRRRRRRRRRQOLEDwnd9[[___]]]____[[9gistib:=*&&*=;>>/^]]]__]]^/-&$@+++@@@@@@@$%&=>(0fffffe0088eemuBDGGDywuhhfeeee800806}}_[[3alAORRSSSSSNNHzolba36[[[[[^^^___^^[[[339aajjtttija93((>:>>>>>(///[33993[[^^^[[3", +"(((;=~{&%%$$@++'',5qqKKKKPPPSSSSSSSSSSSSSSSSSSSSSRRRRQQQRRRRRRRRQOLGynd9[[___]]]____[9gsxGEEClc<~**=-;>/^^]]___]^/>*%@+++++++++++@$&=(30fffee8008eemrBDGJJGDwrhffeeeee80806}}[[39jxFORSSSSSSSNHzolca9996[[[^^^^^^^^[[3333aabjjijjba3(::::;;>>>>(/(3aaaa3[[^^^^^[", +"/>>-=*&&&%%$@++',5qqKKKKPPPPSSSSSSSSSSSSSSSSSSSSRRRRQQQQRRRRRRRRQOJCsg9[[[___]_____69nyELMMLJxl1~~=-;>//^^]___]]^>=&@++.....+++++@$&;(600eee80888eemuBGJJJGDwnhdfeeee88008}}}[[3bxFORSSSSSSSSNIFAkiggd996[[^^//^^^^^//(3333aaaabaa:::---;;::>>>>((abjjja3[^^^^^/", +">>;-=**&&%%$@@',5qqKKKKPPPPSSSSSSSSSSSSSSSSSSSSRRRRQOOOQRRRRRRRRQMJDsd9[[^_______}6dsDJMOOOOLCk11=-;>//^^]____]^/;&$++.........++@%~:(6608e88888eehrwDGJJJCyshdf0000008086}}}[3alAORRSSSSSSSSROFAxljgg996[[///////^////(((33333:::<=~~~==-;;;;:::aclxtlb93//////", +">>;-=**&&%%$!!45qqKKKKPPPPSSSSSSSSSSSSSSSSSSSSRRRRQOOOQQRRRRRRRRQMEysg9[[[______[6dsDJMOQQQOLGlc<-;>(/^^^_____]^>=%@+..........++$&-([668888888eeemuBDGJJGDwnd00000000686}}}[[3jxFQRSSSSRSRRRROFAxtjgd96[[[//>>>//////((((((((:;=~{&&{{~~<<<<-::;-=~*&&%)!!45qKKKKPPPPPSSSSSSSSSSSSSSSSSSSSRRRRQOOOOQRRRRRRRRRQMJDwnd0[[[[_[[60gwCJMOQQQOMJxib::>(//^^______^/;&$+...........+@%=>/[68888888eeehmuBDGJGDysh0066}}}}}}}}}}}[6atEORSSSSSSRRRRROLCyigd96[[[//>---;>>>>>>;;;;;;;-~&%$$$$){~11<<<11koAFFFAxia3((((/", +"((>;-=~{{))74vKKKKKPPPPSSSSSSSSSSSSSSSSSSSSSRRRRQOMMOQRRRRRRRRRRQMLGywnh906660dgsyGLMOOQQOMLCtga(((///^^_____^^>=%@+..........+@%*;/[}6888888eeeehruBDGGDysh066}}}}}}}}}}__[[3jCMQRRSSSRRRRRRROFCtja96[[[^/>-*&**-;;;;-======*&%$@@++@!)|222222oAIIOOOFAtib:((((", +"//(>;=~{{|7vvKKKKPPPPPSSSSSSSSSSSSSSSSSSSSSSRRRQMLLMOQRRRRRRRRRRQOMLECywsnggnswDGLMOOQQOOMLGynd3((///[^______^/;&$+.........++@$&;(/}}88888eeeeehmrwBDDDysnd06}}}}}}}}}}___[[atFORRSRSRRRRRRROMExia96[[[^^/>*&%%&&*===**&&&&&%%@@+++++!77ooooopzHNNRROOFClcb:333", +"[//(:-~2|pvHKKKKPPPPPSSSSSSSSSSSSSSSSSSSSRRRRQQMLLLOQRRRRRRRRRRRQQOMLLJGCDyyDGJLMOOQQQOOMLGynd6[/////[[_}___^/>*%@+....++++++@$&=>/[}68888eeeeeemmuwyDDysnd06}}}____}}_____[3jCMQRRRSRRRRRRRQOJCtg93[[[__^/-&%$$$%&&&&&%%$$$$$@+++..+''7pppppzHHNNSSRROFAklca333", +"[[((:<2|pvKKKPPPPPPPSSSSSSSSSSSSSSSSSSSSSRRRRQOLJJLOQRRRRSSRRRRRRQQQQOOMLLLLLMOQQQQQQOOLJCBnd6[//////[}}____^/-&@+...++@@@@$$%&=;/[[60888eeeeehhmruwyyBsnh06[}_____}}}}___[[9tEORRRRRRRRRRQQOLExia3[[[__^^>=&$@@@$%%%%$@@@@@@+++....''4vvzzzvHHNNSSSSROMExlcaa36", +"[[((:1opvKKKKPPPPPSSSSSSSSSSSSSSSSSSSSSSRRRRQOLJJJMORRRRRSSRRRRRRRRRQQQQQQQQQQQRRRQQQOLJDwnd6[^^//////[}___^/>*%@+.+++!))%%%&&~;(/660eeeeeehhmmmmruwwwsnh066}_____}}}}}}__[3gxMQRRRRRRRRQQQOMJDib3[[[[^_^/>*%$@@@@$$$$@+++++++......'44vvIIHHHPNSSSSSRQMFxlca996", +"[[(3ckpHKKKKPPPPPSSSSSSSSSSSSSSSSSSSSSSRRRRRQOLJGJMQRRRRRSSRRRRRRRRRRRRRRRRRRRRRRRQQOLJDwnd0[[^//>>>///___^^>=&@+++''!||{~***~->(6dhhhfeefhmmmmmmussssnhd06}}____}}}66}}}[[9tEMQRRRRRRRQOOMMJCtja3[[^^_^^/>*%$@@@@@$@@++...........''4vvIIIHHNNNSSSSSROMAxiaa6[[", +"^[3bkzHPKKKPPPPPSSSSSSSSSSSSSSSSSSSSSSSRRRRRQMLGGJLORRRSSSRRRRRRRRRRRRRRRRRRRRRRRRQQMJDBuh0}_^^/>;;;;(//^^^/;*$@++''47po21~~~=:(dgussurmmmmmrrrmnnnsnngd06}}____}}}60006669jxLQRRRRRRRQOOMLJGDsb3(/^^^_^^/;*&$@@@@@@+++...........+'7pzIIIIIHNNSSSSSRROFCtca3[[[", +"^3alAIHPPPPPPPPSSSSSSSSSSSSSSSSSSSSSSSSRRRRQOMJGCGLMQRRSSSSSSRRRRRRRRRRRRRRRRRRRRQQOLGBuhf6}_^^>;****->>//>;*%@@+''4vpzok1<==-:anyDCDDywuuuruurnnnnghd066}}}___}}}60df0069gtEOQRRRRRRQOMLLJJCxia3(/^^^^^^/>~&$@@@@+++............+'77pzIIIIIHNNSSSSRRQMExia3[[[_", +"^3bxFNPPPPPPPSSSSSSSSSSSSSSSSSSSSSSSSSRRRRRQOLJCDDEMORRSSSSSRRRRRRRRRRRRRRRRRRRRQQOLGDwrh0}}_^/;*&%$%&**==*&%@@++'4vvIIAkl<<<::ctGLLLJDywuuuurnhhddd0066}}____}}}600dddd0djCMQRRRRRRQQMLLLJECyia3(/^^^^^//>=&$@@++++.... ....''77ozFFFFIIINSSSSRRQOLClg9[[^__", +"^3lFINNNPPNSSSSSSSSSSSSSSSSSSSSSSSSSSRRRRRRQOLGDyyxGFORSSSSSSSRRRSRRRRRRRRRRRRRQQOMJDBumf0}_^/>=&$@++@@$%%$@@@+@@7pzIIIAkl1<<:biDJMMLLGDwsunnhhdd0066[}}______}}}600dddddnyJOQRRRRRRQOMLLJJGCtib((//^^^[[(:=&$@@+++.... ###''77zzFMMFFIINNSSSSRRQMEyja3[^^__", +"[axMRSSSNSSSSSSSSSSSSSSSSSSSSSSSSSSSSRRRRRRQOLGysiitCFIRSSSSSRRRRSSSRSSSRRRRRRQQOLJGDwume0}[//;*%@+....+++++++@@)|ozIIFAkc<::::ixJMMLLGysnnhdd00666[}}________}}}}6000ddntEMQRRRRRRQOMLLJJJGCtc<:>(///[33a:<{$@+++.... ###'44pzFMMMMMFIIRSSSSRRROLCtg33/^^__", +"3jAORSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSRRRRRQOLCyigbclkAFIQSSSRSRSSSSSSSSRRRRRQOMLJGDBwumf0}[/>-&@+...........+@${2oAFFAkcb:::(3btCJLJGDtngd00666}}______________}}}6600hsCLORRRRRRRQMLLJJJGCxic<-;>//33bjll2|)!++.... ##,,5vvIIIOOMMMMOORSSSRRRQOLCtb33[[^__", +"axMQRSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSRRRRRQOLCwna:<122opzIIQRRSSSSSSSSSRRRQQMLGDDDBBBurhf6[(>=%@+... ....+@%~>((3jtCCCysnd9666[}}__________________}}}60gtEMQRRRRRRQOMLJEEGCDtic<=->/(3btCAAAo7!''.# ##,,55vHHNOOOOOOMOORRSSSSRRQOLCtja33[[[[", +"tEORSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSRRRRQOJDsb::=~{{)||opzIORSSSSSSSRRRQOLGDyyBBBBBwumd63(:~%@+... ....@%=:bbbba:(>>>///[9gsssjnd9666}}}}___________________}}6dsCMQRRRRRRQOMLJGGGCDysc<<=->(3atAMMOIzp7'''#######,55qKPNNRRQOOOOOOORRSSSRRRQOMExlcba3399", +"EMQRSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSRRRQMJyia::=*&%))))||ozIQSSSSSSRRQMJCtsuuwBBBBBund03(:=&$+... ...+%=:(((((>>>>//^^[[9gnnngdd9666}}}}__________________}}6dtJOQRRRRRQQOLJGGCDDyysg:<-;>(3jCLOQQOIIp44'#####,,5qqKPNNSRRQQOOOOOQRRRRRRRRQOLExkklcbjit", +"MORRSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSRQOJCsb:(;=*&%%$$)){2koFIRSSSRRQMFxsnhhnuwBBBBsnhd93:-~%$+... ...+$*;>>>>;;>>//^^^[[9dgnnnnngd00066}}}}__}}}}}}}}}_}}}}60nCLQRRRRRQQOLJGGCDDDywsg::;:((atEMQQRROIzp74'',,,5qqKKPPSSSRRQQOMMOQQRRRRRRRQOMFAoookkkxCE", +"OQRRSSSSSSSSSSNNNNNNSSSSSSSSSSSSSSNNNNNNNOMJxib3((>-=*&%%%%{~<1loFIRRRRQOMExjgddhhuwwBwsngdda3:<~%$+.. ...+@&=;;;--;;>/^^_^[60hnswyyyysnhff0066}}}66006}}}}}}}}}0dwEMQRRRRQQOMLGGDDDDDyytna::>(3atJOQRRQQOMzpp7445qqKKKPNSSSSRRQOMMMOQQRRRRRRRQOLEAoo7oooAFM", +"QQRSSSNNPPPPPKKKKKKPPNNNNNHHIIIIHHHPKKKHIAxlba3(((>;-=~***~=-::ixFIRRRRRQMLCtjgddhgnsssssngggga:<~%@+.. ..+@%&*====-;>^^]_[[0hnsBDGJJGGDwumhee00fffffee0066}}}60dnDLOQRRRQQOMJGDDDyyyDDyyib:(((3bxJMQQQQQOMFFAzpvvKKPPNSSSSSSRRQOMMMOQQRRRRRQQMLGxko777ooEMO", +"QQRNPPKKKKKqqqqqqqqvvvpppooo||||||7744447|1<(((//>>>>;;;;::::actAMORSSRRRQOMExjgdddgnnsssssssiig:~)@+. ....+$%&&&&*=;/^^^[[6dgnwDGJMMMLJDBwrmmmmmuuuurmhff000000hsCLOQQQQQOLJGDByBBBBDDDDtia:((3axEMOQQQOOMMMLLIINNNSSSSSSSSSRRQOMMMOQQRRRRQQMJCtl2|!!77oAMO", +"QONKqqqqqq5555,,,,''!!)){){{{{{{{))!!'+'!){=;>>>>>((((3333adnsDJMRRSSSSSRRRQMJxjgd9ddgnnsswyyytic~)@.. .....+@$$%%%&=;/^^^[[9dhnwDJLOOOOLJDBwwuwwBDDDDBwumhff00fhnyELOQQQOMLJDBwwuuuwBDDGGDic:((3bxEMOOOOOOOOOOOORRSSSSSSSSSSSRRQOMMMOQQRRRQQOLCyic1)!!!)2xFO", +"QIvq555,,,,,######.+@$%%&&&&&&&&&&%$$@+@@$&*-;>>>((:abjinnnwyGLORRSSSSSSSRRRQMJxtga9ddgnssyyDxti1{!+. ....++@$$$$%&*;/^^^[[09dgsDJMOQQOMLJGDDDDGJJLJJGDyumhfddhnsDJMOOOOMLGDwurmmmmuwBCGGCtc::(3jxJMOOOOOOOOOQQQRRRSSSSSSSSRRRRROMMMOQQQQQQOLGynd:~)!@@)2lEO", +"Oz5,,,######## .+@$%&&&&***====*&%$@@$%&*-;>>>(ajtxCCyDDGJMQRRRSSSSSSSSSRRQMExjga9ddgnstyyyl12!+. ...+++@$$$$$$%*;>/^^[[[60dnBGLOQQOOLJJJJJJLMOOMMJGDwunhhhgsyCJMOOMLJGywumhhffhmsyCGECkc:::blAMOOQOOOOOOQQQQRRRRSSSSSSSRRRRQOMMMMOQQQQOLJDsh3:~)$@@)~cDM", +"Jo'###### ..+@%&&**==-;>>>>;-*&&%&&*=-;;>:bkAFLLLJGJLOQRRRRSSSSSSSSRSRRQMEyjgaddggnsssi1|!+. ..++@$$%%%%$$$%*->/^^^[[[[0dsDLMOOOMMLLLLMOOOOOOMLGDwsnhhgntDELMMMLJGywumhfe00ffnwDGGCkc<:biCFOQQQQOOOOQQQQRRRRRRRSSSSSRRRRQOMLLMMOOOMLJDwmd3:~%$$$&~btJ", +"y1!# ..+@$&*=-;>>>//^^//>;-=**==-;;>:lxFMOOOMLLMOQRRRRRRSSSSSSSSRRRQMFCtjg99dagggc1|!'# ...+@%&&***&&%%%%*->//^^^^[[[0nyGLMMMLLLLMOOOQQQQOMLGysnhddgiyCLMMMLLGDwumff00000fhsyCCCtccccxFORRRRRQQOQQQQQRRRRRRRSSSRRRRRRQOMLLLLLLLJGDwrh03(={%%&~:anD", +"n:)+. ...+$&*-;>>//^^]]]]^^/>>;;;;;>(blAMOQQQQOMMOOQRRRRRRSSSSSSSSRRRQOMEyig999999a<)@.# ...+$&=-;;;;-*&&%&*=;>//^^^__[6dsDGJLJLLLMOOQQQQQOMLGDsngd9dgsxELMMMLJDysmdf066}}60hsDCCCxlllxFORRRRRRRQQQQQQRRRRRRRRRRRRRRRRRQOLLJJJJJGDBwrhf63(-~{*~:3drB", +"m3~$+............+@&=;>//^^^]]]]__]^^//>>>>>(bkFOQRRRQQOOOOQRRRRRRRSSSSSSSSRRRQOMEyja93333(<)@+ ..@%*;>////>>-=*&**=;>>//^^^__[0hsyDDGJJLMOOQQQQOMLGysgd9399gtCLMOOMLEDwnhd06}}}}}0hsDGEECkkxEORRSSSRRRRRQRRRRRRRRRRRRRRRRRRRQQOLLJGGGDDBurhf063(:=~=:(0huw", +"h0:&@+++..++.+++@$&=;//^^]]_______^^^///(((alxFORRRRRQQQOOQQRRRRRRRRSSSSSSSRRRQOLCtj933((>=%@.. ..+%*;/^^^^^/>>-=**=--;;>>//^^^}6dhuwyDGJLMOOOOOMLJCysg96[[39jyELOOOMLGysgd06}}___[6dsDEJEACCAMORSSSSRRRRRRRRRRRRRRRRRRRRRRRRRQQOLJGGDDBBurmff063(::::33dmuB", +"h0(=&%$@@@@@@@@$%*->/^^^_______[[[[[33333ackFMQRRRRRRRQQQQQRRRRRRRRRRSSSSSRRRRQMExja3(/>-*%+.. ..+$*;/^]]]]]^/>;-=========;>/^^^[6dhmuBDGJLLMMLLJCysg93[[[[3aixFOOOOMLGysh06}}____}6gtCELFEEEFORSSSSSSRRRRRRRRRRRRRRRRRRRRRRRRQQOLJGDDBwurmef00633:::33dhruB", +"h0(>-**&&&******-;//^^_____}[[669999aaaaclAFORRSRRRRRQQQQQRRRRRRRRRRRRRSSRRRRROLCla3((;=&$+.. ..+$*;/^]]]]]]^/>;-==***&&&&*=>/^^[}60dmuBDGGJJGGDysg96[[[[/(3btEMOQQOMLCynd06}_____[6gtGJMLFFFMORSSSSSSRRRRRRRRRQRRRRRRRRRRRRRRRQOLJGDBwurmeef00033::3adhmuwB", +"he6/>>;;;;;;>>>>//^^^[[[}66660dgnjtjiiltCFORRSSSRRRRRQQQQRRRRRRRRRRRRRRRRRRRRQMEtb3((-*%@+.. ..+$*;/^]]]]]]]^/>;-=**&&%$$$%&=>/^^[}60dmuwyyyywsng96[[^^^//(3iCLOQQQOMLCtnd6[[_____[6gtGLMMFFMORRSSSSSSRRRRRRRRQQRRRRRRRRRRRRRRRQOLJGDBurmhee000093aaaddmruBB", +"he6[/////////////[[[[660000ddnsyDCCCxCAFMORSSSSSRRRRQQQQRRRRRRRRRRRRRRRRRRRRQOFxj93(;=&$+... ..+$*;/^]]]]]]]]^/>;=**&&$@@+@@%*;>/^^_}}0dhmnnngd06[[[^^^^^//3bxJOQQQQOMJCtnd6[_____^[6gtELMMMMMQRSSSSSSSRRRRRRQQQQQRRRRRRRRRRRRRRQOLJGBwummeee00099aaaddhruwBB", +"he6[////////[33399aggnnnnnnswyGJLMLLFFMORRSSSSSRRRRRQQQRRRRRRRRRRRRRRRRRRRRRQMCta3((;~&@+.. .+@&;/^]]]]]]]]]^/>-=**&%$@+++@$&=>/^^^__}6600066[[[^^___^^^/3atEMOQQQQOMJCwn06[_____^[3gyELMMMMOQRRSSSSSRRRRRRQQQQQQRRRRRRSSRRRRRRQOMJGBwrmeee00009daaddhmruwBB", +"ee6[[////[33ajitxxCCCCCCDDDCGJLMOOOOOORRSSSSSSSRRRRQQQQRRRRRRRRRRRRRRRRRRRRQMExj33((;=&$+.. ..@&->^]]]]]]]]]]^/>-=**&%$@+++@$&=;/^^]_____[[[_^________^^[39iCLOQRRQQOLJDwg06[[_^^^^[9nyEMMMMOQRRRSSSSRRRRRRQQQOQQQRRRRRSSSRRRRRRQOMJDBurmfe000099dddddhmruwBw", +"ee6[[//(3ajtxEFMMMMOMMMMLLLLLMOQQRRRRRSSSSSSSSSRRRQQQQRRRRRRRRRRRRRRRRRRRRROLCla3[//>-*$@+......+%*>/^]]]]]]]]]]^/>;-=**&%$@@@@$&=;>/^^]]_______]]]]]___^[[[9jxJOQRRQQQOLGysh06[^^^^^^[9sCLMMOOOQRRRSSSRRRRRRQQOOOOQQRRRRSSSSSRRRRRQOMJDBumhee000099aadddhmruwwu", +"e06[[(3abtCFMQQQQRRRRRQQQOOOOQQQRRRRSSSSSSSSSSRRRRQQQQRRRRRRRRRRRRRRRRRRRRQMEtj93[//(;~%@+.....+$*;/^]]]]]]]]]]]^/>>;;-=*&%$@@$%&=;>/^^]]]]]]]]]]]]]___[[[39jyEMOQQQQQOMJDwnd0[[^^^^^^[gtEMOOOOQRRRSSRSRRRRRRQOMLLMOQRRRRSRRSSRRRRRQOLJDyumhff000099aaddhmruuwuu", +"e66333bckEMORRRRRRRRRRRRRQQQQQQRRRRSSSSSSSSSSSRRRQQQQQRRRRRRRRRRRRRRRRRRQQMExia96[[//>-&$@+...+@&->/^]_]]]]]]__]^^//>>>;-*&$$$$&*->//^]]]]]]]]]]]]]]__[[39ajtALOQQQQQOMJGBsh06}^^^^^^[3nCLMOQQQQRRRSRSSSRRRRQQMLJLLOQRRRRRRRSRRRRRQQOLJDyumhf000009daaddhmruuuur", +"0633:<1kAIRSSSSSSSSRRRRRRRQQQQQQRRSSSSSSSSSSSRRRRQQQQQRRRRRRRRRRRRRRRRRQQMExsg936[[[/>;*%@+++@@&=>/^]]_]]]]]___]^^^^///>;=&%%%%&=;>/^^]]]]]]]]]]]]]__[[39ajtCJMOQQQQOMLGDwnf6[_^^^^^^[9sEMOQQQQQRRRSRSSSRRRRQOLJGGLOQRRRRRRRSRRRRRQQOLJDBumff0000099adddhmrruurr", +"63(:<1koINNSSSSSSSSSSSRRRRQOOMOQQRRSSSSSSSSSRRRRQQOOQQRRRRRRRRRRRRRRRRQOMExtgd966[[[/(;*%@@@@$&~;//^]]]]]]______]^^^^^^/>-*&%&*=;>/^^]]]]]]]]]]]]]]__[39gjtxEMOQQQQOMLGDwrf0}__^^^^^^[gtJMQQQQQQRRRSRSSSRRRRQOLGDCJMQRRRRRRRSRRRRRQOMLJDBsmff000099999ddhmrrrrmm", +"3(:<2||pINNSSSSSSSSSSRRRRQOMLJLMOQRRSSSSSSSRRRRQOOMOOQRRRRRRRRRRRRRRQQOLExiga93666[[/(;*%@@@$&~;(/^]_]]]]]______]]]]]^^/>-*&&*=;>/^^]]]]]]]]]]]]]]__[39gitxELMOQQOOLJGDwrh06}__^^^^^^[gyLOQQQQQQRRRSRSSRRRRRQMJDyDGMQRRRRRRRSRRRRRQOMLEDBsmhff00099999ddhmmrmmee", +"(:<{||7pHNNSSSSSSSSSRRRRQQMJGCCGLMQRRSSSSSRRRQQOMLLMOQRRRRRRRRRRRRRRQOLExiga9900666[/(;*%@@$%*;>/^^_]]]]]________]]]]]^/>-***->>/^]]]]]]]]]]]]]]]__[[9gitxEFMOQQOOLLGDwuhf6}__]]^^]]^[gDLOQQQQQQRRRSRRSRRRRRQMGyByGLQRRRRRRRSRRRRRQOMLGDBsnhdf000099900dhhmmmee0", +":-~{)!7pvNNSSSSSSSSRRRRRQMJCtsstDEMQRRRRRRRRQOMLJJJLOQQRRRRRRRRRRRRQOMExigd9999d006[/(-&%$$%&=>/^^]__]]]]_____^__]]]]]^/>-==->/^^]]]]]]]]]^^]]]]]_^[9gjtxEFMOQQQOMLJDBumf0}___]]]]]__6gDLOQQQQQRRRRSRRSRRRRROLCywyCLQRRRRRRRRRRRRQQOLJGDBsnhdf000009900fhhhhee6}", +"-~{)!!7pzHNSSSSSSSSRRRQOMEDwnggmsyGLOQRRRRRQOLJGDDGJMQQRRRRRRRRRRRRQMJCtja999ddddd6[/>-&%$%&*;>/^]]]]]]]______^^^^^^^^/>;--;>/^^]]]]]]]]]^^^]]]]__[9gjtxEFMOQQQQOMJGyumd06}__]]]]]]__[dyJOQQQQQRRRRSRSSRRRRROLDwswDLORRRRRRRRRRRRQOOLJGDysnhdd000066660fffff06}}", +"=*%)!!77zIRSSSSSSRRRRQOLEDsnhdddhnwDJMQQQQQMLGDBBBDJMQQRRRRRRRRRRQQMJCtjg999dhgmhd06/>-&%%%*->/^^]]]]]]]____[[^^^^^^^//>;;;>>^^]]]]]]]]]^^^^]]]__[9gtxCELMQQRRQQOMJDBuh06[[__]^^]]]__[dwEMQQQRRRRRSRRSSRRRRROJDwswDLORRRRRRRRRRRRQOMLJGDwumhdd0006666600fff06}}^", +"*&%!!!77zIRSSSSSRRRQQOLGyshdd0000fhsyGLMOMLJDyuuuBDJOQRRRRRRRRRRQQMLGysgd99dhnnnnh06/(;*&&*=;>/^^]]]]]]]____}[^//////>>>;;>>/^]]]]]]]]]^^/^^^]]_[3gtxEFMMQRRRRRQOLGDsnd06[__]]^^^]]]_[9sGMQQRRRRRRRRSSSSSRRROJysnsDLOQRRRRRRRRRRRQOMLJGDwumhf00066[[[6000006}__^", +"&%$$!!|ozIRSSSRRRRQOMJCyshd00000000dnwCJJJGDwumruwDLOQRRRRRRRRQQOMJCysga999dhnnnmd0[/(;=**=->/^^]]]]]]]_____[[//>>>>>>;;;>>/^^]]]___]]^^///^^^^[3gtCFMMOQRRRRRRQOLCtnd06[___]^^^^^]]_[9sGMQQRRRRRRRSSSSSSRRROJysssDLOQRRRRRRRRRRQQOMLJGDwumff0066[[[}}60006}__]^", +"%$$@!)|ozORRRRRRQQOLEDwnhd0000086660dmsyDDywummmuBGLOQRRRRRRRQQOMECtjgd9000ddhggd9[[/(>-=-->>/^^]]]]]]]_____^//>;;;;;---;>>/^^]]____]^^////^^^^[atELMOOQRRRRRRRQMEynd66[___]^^///^]]_[9sEMQRRRRRRRSSSSSSSRRROLCwwwDLOQRRRRRRRRRRQOOMLLEDBumff066[[[}}}}66}}__]^^", +"%$@@!)|oIORRRRRQQMLEDsndd00000886}660dmswwsrmhhmuyJMQRRRRRRRQQMLEDsng996666000096[[//>>;;;>>//^]]]]]]]]_____^/>;-----==-;;>//^^^^^^^^^//>>//^^[9lCLMOQQRRRRRRRQOLCsd0[}___]^^/>>>/^^^[9tEOQRRRRRRSSSSSSSSSRROLGyByGMQRRRRRRRRRRRQOOMMLJCysmf006}}}_}}}}}}}___]^/", +"$@@@!|ozIQRRRRQOMJCysgd000008888}}}}60hnusumhhhmwDJOQRRRRRRRQOLEDsn9966[[[[[[[[[[////>>>>>>>/^^]]]]]]]______^/>;;--=====-;>>//^^^[[^//(>>>//^[3jxFMOQQRRRRRRRQQLGtg0[}____]^>;;;>>/^^[gyLORRRRSRSSSSSSSSSRRRQMECDDJMQRRRRRRRRRRQQOOOMLJCysnf006}}____}}}}___]]^/", +"@@@@!|pzORRRRQOMJCtjgd0000088886}}}}60hnsuurmmmuBGMQRRRRRRRRQMLCtja9[[[[[[[[[^^^///>>>>>>>>/^^]]]]]________^^/>>;;--=***=--;>>///[[[/(>;;;>//3atEMOQQRRRRRRRRQMJyn96}____]^/;=*=->/^^3jCMQRRRRSRSSSSSSSSSRRRQMJGGGLOQRRRRRRRRRRRQOOOMLJGywnf06}}______}_____]^/>", +"@@@@!|pIORRRQOMJCtng906600088886}}}60dnswBwwuuuyDJOQRRRRRRRQOLEyia93[[[[^^^_^^//>;;;;;>>>//^^]]]___________^^//>>>;-=******=-;>(////(>-=~-;((3jxFMQQRRRRRRRRQOLCsd6[____]^/;=&&*=;//[atJORRRRSSSSSSSSSSSSRRRQOLJJJLOQRRRRRRRRRRQQOOOOMLGDwnd06}}___________]]^/>", +"@@@@!7zIQRRRQOLCtja9666600088886}}66dmwDCGGDDDDGJMQRRRRRRRROMExlb93([//^^^^^^//;-==-;;>>//^^]]]_____}}}}____^^///>>;=**&&&&&&*=;>((>;=*&&*->(atEMOQQRRRRRRRQQMGtg3[^__]]^/>=&%%&*;>/3jCMQRRRRSSSSSSSSSSSSRRRQOLLJLMOQRRRRRRRRRRQQQQQOMLJDwnd06}___________]]]^>;", +"@@@!!pzIQRRROMEyia96666600888886666dhsCJLLLLLJLLMOQRRRRRRRQIFxlc:((((////^^//>>-=*=-;>>//^^]]____}}66686}}__^^^^^/>>-**&&&%%%%&*=--=*&%$%&=:3jxFMOQQRRRRRRQQMEyn3[/^^^^^/;=&%$%&*;>(ayJORRRRRSSSSSSSSSSSSRRRQOMLLLMQQRRRRRRRRRRQQQQQQOMJDwnd0}[___________]]^/>;", +"@@@!7pINRRROOFCtg93[666000888886660hsCLOOQQQOOOOQQRRRRRSSNIzok11<==--;>(////>>;-==-;>>/^^]]]___}60feeee06}}__^^^^^/>;=*&&%$$@@@$%&&&%$@@@%*>>>>>>-*&$$$%&=;(3jCMQRRRRRSSSSSSSSSSSSRRRQOMMMMOQQRRRRRRRRRRRQQQQQOMJDwnd6[[__________]]]^/>=", +"@@@!7zHNNNQOMExia96[6600088888060fhsDLOQRRRRRQQQRRRRRRSNNHp77))))%&&{~-;>(((>>;;;;>>//^^]]]___}0fhmmmmhe06}}_^^^^^/>;-**&%$@+++++@@@+++++$&1cxFOOQQRRRRRRQMJxi<~{&&&****&%$@@$%*->(atEOQRRRRRSSSSSSSSSSSSRRRQQOMMOOQRRRRRRRRRRRRQQQQQOMJDwnd6[___________]]]^>;=", +"@@!7pHNNNNQOFAtja3666000eee88800dhuyJOQRRRRRRRRRRRRRSSNHvv4''!@@@@@$){~-:>((>>>>///^^^]]]____}0fmuuwwwumh06[[^^^^^/>>;=*&%@+++..........+@)2kAMOQQQRRRRRQMExl1)$@@@@@$$$@@@@@%&=;((ayJORRRRRRSSSSSSSSSSSSRRRQQOOOOQQRRRRRRRRSRRRRQQQQOMJCwg96[[^________]]]^/>-*", +"@@!7vHNNNNNOFAtja366600eeeee800fhnyGMQRRRSRRRRRRRRRRSNHv54'''++++++@!)~<<:(((////^^^]]]_____}0dmuwBDDDBwnh0[[[^^^//>>;=*&%@++............+!|AFOQQQQRRRQQMFxl2)@+....+++++++@$&*;>/3gyLOQRRRRRSSSSSSSSSSSSRRRRQQOOQQQRRRRRRSSSRRRRRQQQOMJDsg9[[[^_______]]]^^/>=&", +"@!7pHNNNNNNOFAtca936000feeeeeefhnyGMQRSSSSSSSRRRRRSSNHv5,,##....++@!){21cba3(//^^^]_______}}0fmuwBDGGGGDwnd6[//////>>;=*&$@+.... ..''pzIQRRRRRRQQMFxk2)@+........++++@%*->//3gyLOQRRRRRRSSSSSSSSSSSRRRRQQQQQQRRRRRRRSRSSRQQRQQQOMJDsg9[[[^^^^^^^_]]]^/>;*&", +"@!7vHNNNNNNIFAtca9900000ee0e0edmwDLORSSSSSSSSSSSSSSNHv5,,##....++@!)|2kkliga3[[^^_______}}}00hmuBDGJLLLJCtga33(///>>;;=*&$@+... #'4vHNNRRRRRQQMJxl2)!+.. ....++@$&=>/^[6gyJOQQRRRRRSSSSSSSSSSSRRRRQQQQQQRRRRRRRRSSRRQQOQQQOMJCsg9[[[^^^^^^^^]]^^/>-&%", +"@!7vHNNNNNNIFClca990000000000fhnDJORSSSSSSSSSSSSSSNHv5,,##...+++@))22kxxytia9[[[[_____}}}600fhmuyDJLMOMLExib33(((>>;;-*&%@+... #,5KHNSSRRRQQMJxl1{)+.. ...++@%*;>/^^6gyGMOQRRRRRSSSSSSSSSSSRRRRQQQQQQRRRRRRRSSSRQOOOQQQOMJDsg9[[^^^^^^^^^^^^^>;*&$", +"!74HPPNPNPNIzxlba366600000000fmwGMQRSSSSSSSSSSSSSNHv5,,##..++@@$%{11lyDxytng96[[}}}}}}}66000ffmsyGLMOOOMLCtiaa3((>;;-=*&$@+... #,5qPNNSSRRRQOFClc1{$+.. ...++$&=>/^^[6hsCLOQQRRRRSSSSSSSSSSSRRRRRQQQQQRRRRRRRRRRQOIIOOQQOMExia3[[^^^^^^^^^^^^/>-*%$", +"!4vHPPPPPPHIzklb9366666666660dsxJORSSSSSSSSSSSSSNHv44'#...+@@$%{~</^^[6dsDJLOQRRRRSSSSSSSSSSSRRRRRQQQQQRRRRRRRRRRNIIIOOOOOMExja3[^^^^^^^^^^^^//;=&$@", +"'4vKPPPPPPHIAkia93[[[}}66666dgtGMQRSSSSSSSSSSSSRIvp4'#...+@@%&*=-:acittwssnhdd000666686886800fhwCLMQQQQOMExtiga::;-=*&$@++... #,,vHNNSRRRQOMExb:=&$+.. ..++$&->/^^[6dnyCJMOQRRSSSSSSSSSSSSRRRRRRQQQQRRRRRRRRRRIIIIIOOOMFAtb93[^^^^^^^^^^^^/>;*&$@", +"44vPPPPPPPHzAkca36[[[}}}}}60dnxFORSSSSSSSSSSSSNIzp4''...+@@%&*-;:(3agnissnnmhhdff00068886}6600hwGLOQQQQOMExtljba:;=*&%@++.... ##4vHNRRRQQOMFxja-{$+... ..++$&->/^^[6dgsyGLMQRRSSSSSSSSSSSSRRRRRRQQQQRRRRRRRRROFzzzIIIIMFxla3[^^^^^^^^//^//>>-&%@@", +"4vHPPPPPPHHzolca3[[[[}}}}}69gtCMORSSSSSSSSSSSNHIp4''...+@$%&*=;;>((3agnnususurmhffe0066}}}}}6dnyJMQQQQOMLExytica:-~&%@@+...... .'7pFOOQQQOMLCla:~%@.. ..+@%*->/^^[60hnsyGLORRRSSSSSSSSSSSRRRRRRQQQQRRRRRRRROIzppzIIIIIAxia3/^^^^^////////>;*&$@@", +"vvPPPNNPPHIzxlcd3[[[____}[6diyJMQRSSSSSSSSSNNHHp4''...+@$%&=-;;>>((33dhnwByyywwumhf006}}}}}}0gwGLOQQQQOMJGCCxtib:=*%$@+....... ..+!2kAFOOOOMLExb:-&@+.. ..+@%*;>/^^[60dgnyCJORRSSSSSSSSSSSSRRRRRRQQQQRRRRRRRQOFAoppvHHIIAkca(/^^^/////////>>-*%$@@", +"vHHNNNNNNNIAxlg93[[[____[[9gtEMORRRSSSSSNNNNHvp4'''+++@$&*=;;>>>>((30dmwDDGGGDDwumhf06}}}}}6dsDJMQQQQOMMJEECCxlc<~{$@++......... ..+${/^^[69dhnsDJOQRSSSSSSSSSSSSRRRRRRQQQQRRRRRRQOMAooopvHHIzAkc3(/^^////((////>;=&%$@@", +"HHNNNNNNNIIAxlga3[[[___[[6aiCJMORRRRRNNNNNHHvp7'!'++@$%&=;>>>>>((((3dnwDGJLLLJGDwuhf06}}}[69nyJMOQQQQOMMLLLLECxl1~)$@+..............+@&-:bxCJLLLExia3-&@.. ..+$&=>//^/[660dhsyJORRSSSSSSSSSSSSRRRRRRRQQQRRRRRRQMJxkkopvIHIzAkc3(/^///(((((//>>-*&%$@!", +"HNNNSSNNOIFExtja9[[[__[[[9jxEMOOQRRQNOIIHHvp77!!!@@$%&~->>////////39hsDGLMOOMLJDysmd06[}}[6gtEMQQQQQQOMMMMMMLJCl1{)!@+.............+@&=>(alxEJEExta3(=%@.. ..+$&->///[[669dhsDJORRSSSSSSSSSSSSRRRRRRRRRRRRRRRQOMExkkozzHIIFAkca(///(/(((((>>>;-*&%$!!", +"NNNSSRRQOMFECysgd6[[[[[[9jtCFMOOOOOIIFzzzpp7|)))))%&~-;>////////[3dnwDJLMOOOOLJGysgd6[[[[[9sCMOQRRRQQOOOOOOOOMAk2{)!@++...........+@%*;/(9ixCEExtg3(:*$+.. ..+$*->///[339ddgsDLORSSSSSSSSSSSSSRRRRRRRRRRRRRRRQOMCklkozIIIIFAkca3///(((::(>>>>;=&%$$!7", +"NNSRRROOMMFECytjgd6[[[[9gtxEFMMMMIFFAAooo|22{{{{~~~=;>(///[[[[[39gsyGJLOOOOOMLJCysh0[[[[[9gxLOQRRRRRQQQQQQQQOMFo2{)$@+++.........+@%*;>/[9ixCECyja3(-&@+. .+@%*;>///[39dddnwCMQRSSSSSSSSSSSSSRRRRRRRRRRRRRRRQOFAxkkozIIIIFAkca3//(((:::>>>>;-*&%$!!4", +"NNRRROOMMLJJECDtsg99669ajxCEFMFFFAAokkkl11<<<----:::((([[[[[[39gsyCJLMOOOOOMLJCysg96[[[[[9tEMQRRRRRRRRRRRRRRQOFo2{)$$@++........+@%*;>//[atCEECtj3(;~%@.. ..+$&=>///[39ddddnyGMQRSSSSSSSSSSSSSRRRRRRRRRRRRRRRQMFCxkkAzIIIIFAtb33//(((::::>>;-*&%$@@'4", +"NNNQOOMLLJJJJECDtng9999gtxCEEFEACxkkllicc::((((((::a33333[639gsyCJLMOOOOOMLLECysg9[[[^^[[atFOQRRRRRRRRRRRRRRROFk2{{)$@++.......+@%*;//^[6gtCEECta3(-&@+.. ..+$*;>///39ddddgsyEORRSSSSSSSSSSSSSRRRRRRRRRRRRRRQQMJCkkoAzIIIFFxlb33//(((::::;;;=*%$@@+'4", +"NNOOMLJJEJJJJEGCysgd999gjxCCCCCxxklllicba333(333aaaaa993339gntCJLMOOOOOMLLGCysnd6[[^^^^^3gxLOQRRRRRRRRRRRRRRQOAk1~{%$@++.......+$*;(/^^[9nxEEExla(;*%@.. ..@%=>///[6ddggdgsyGMQRSSSSSSSSSSSSSRRRRRRRRRRRRRRQOMExkkoAFIIMFAxja33[/((:::;;;;-*&%@@+''4", +"HIMLLJGCCGEEJEGDysg9999ajttxxxxxtktttliga933339abbjbba9999gntCJMOOOOOMLJGDtsgd9[[[^^^^^^3jxLOQRRRRRRRRRRRRRROMAl1~{)$@+.......+@&-(/[[[[9jyCECxja:=&@+.. .+@&->//[39dddddgsyJMQRSSSSSSSSSSSSSSRRRRRRRRRRRRRQOLCxlkoAFIMFFCtb33[//(((:;;;;-=*&$@+++'4", +"IIFJGDDyDDCGGGDywnd96[39ajitttxxxCCCxytjga999abjjiijbaa9dgnsDGLMOOOOMLECysgd96[[^__]]^^^3jxLOQRRRRRRRRRRRRRQOFxl<~{$@+........+%~:([[[[6djtyxtia(;*%@... .+$*;(/330ddddddgsyJMQRSSSSSSSSSSSSSSRRRRRRRRRRRRQOMExlllkAFFFFAxia3[///(((:;;;;-*&%$@+++'4", +"zzGCywwwwyDDDDDBshd6[[[39abiltxCAEEECCytjgaagjjillijbaaaggnwDELMOOOMLGDwnh06[[[____]]]^[[gyJOQQRRRRRRRRRRRQOFAlc<{)@+... ..+${;([[[[[69gjssja3>=&@+.. ..+%~:(330dddddddgsDJOQRSSSSSSSSSSSSSSSRRRRRRRRRRQQMJCtjclkCEFFECtb33[^^///(>;;;;-*&%$@+++''", +"ooytsiinswwyyDywnh06[[[[39ajitxEEFFJECxtijjjjltllljjbbjgjnsyDGJLLLLECyshd06[[[_____]]__[6gyEMOQQQQQQRRRRRRQMEkc<~{$@+.. ..@%=(([[[[[[69dga93(-*$+.. .+@)<:339ddd9399dgtCLORRSSSSSSSSSSSSNNNRRRRRRRQQQQOLExibbilxAEECxia3[^^^^//(>;;;;-*&%$@+++''", +"oklinggdgnswBywsnd0[[[[[[39gitxEEFFJECyttiillttllliiilltstwyyDGGGGDysnh0066[[[_________[6hwGLOOQQQQQRRRRQQMExib<~%@+.. ..+$~>//[[[[[[[[66[[(;~%@+.. .+!{<:aaddda3339dnyGMQRRSSSSSSSSSSNNHHIINRRQQQQQOOMExlbabblxCCCxtj93[^^^^//(>>>;;-=&%$@++++'", +"|2ccaa39dhnswwwsnd0[[[[[[[9ajtxCEEEECxyttiitttlllllltxxxyyyyyyyyywsnhd066[[[[__________}6hsDJMOQQQQRRRQQQOLClb:<~%@+.. ..+$&;(//^^^^[__[[[[/>=&@+... .+@)21ccgdaa33339gsDJOQRRSSSSSSSSSNHHzppzIOOQQOOOMLECtjaaabltxCxtig9[[^^^^^//>>>>;-=&%$@++.+'", +"22<:::(33dhnuwwsnh96[[[[[[69gjttxxxxtttiiiiiliiilltxCAECCDyywsssnhdd0666[[[[[__________}0hsDELOOQQQRRQQQOLEyib:-*%@+... ..+@&->/^^^^^_____^^//;&$+... ..+!22lligaa:::(39gtCLORRSSSSSSSSSNHvp777pzIOOOOMMLECtja99agitxxytna3[[^^^^^///>>>;-=&%$++..++", +"){~<:::((3dhswywsgd6[[[[[[[39gjjjiiijjjjjjjjjjjilxCEFFFJECyysnnhd0066}[}[[[[[[________}0fmwDGLOQQQRRRQQOMJCtb::-*%@+.....+@%=>/^^^^________^/>*%@... ..+$)2kkktic::::(3aiyEMQRRSSSSSSSSNHzp7777ozIOOOMMLECtjg999ajityytig9[[[^^^^^////>>;-=&%$++...+", +"){~~=--;:(9giwywsnd0[[[[[[[669dggggaaaaaggggjjjlxCEFMMMLJCywshd0066}}}}[[[[[[[______}}0dmuyDJLOQQRRRRQQOMJxib::-~&$@+...+@%=>//^^^________]^/-&@+.. ..+@)2koACxtic<<::abtCLORRRSSSSSSSRIzp7!!!|ozFOOMMLECysg9999ajittttig9[[[^^^^^^///>>>-=&%$++....", +"%%{*~===-::anwwwsnd96[[[[[[6699999999999aaaabjitCEMOOOMLJCysnd066}}}___[[[[[[[____}}60hnwyDGJMOQRRRRRRQOMExlc::-~&$@++++!{=:(/[[[^________^/>*%@.... ..@%~1kAFFAxlc<<::aixEMQRRSSSSSSSNIzp|!!!!)|AFMMMLECtjg99399ajitttsnd6[[[^^_^^^////>>;=&%@++....", +"$%%&&&**~=:aisttsng906[[[[[6669999999999999aajtCEMOOOOOLECysg966[}____}[[[[[[[}}}}}60huBDCGJLMOQRRRRRRQOMGxlc:<=*&%@@+!){1:336[[[[[}}}____^/;*$+... ..+${>;=&%@++....", +"@@$%%%%&&~<:ciwtsngd96666666999993366663339aglxEFMOOOOMLCysnd06[______}[[666[[}}}}60hsyDGJJLLMQQRRRRRRQOLEkl<<=~{%$$!!)21cgdd0066666[}}}__^/-&@+... ..+@%~>;=&%@++....", +"@@@$%%%%%{~=%@... ..+$&=cxFOOOIAk1>;=*%@+.....", +"+@@$$$%%%&{1clttsingdddddddddd99936[[[[399ajtxCJMMOOMFExtng9[[[______[[6666666}}60fnwDGJJJJLLMOQRRRRRRQMFCl1<~~{&)))|ooCCDysnhddd000066}_^/>*$+... ..+$&>;=*%$+.....", +"++@$%%%%%%{11kxyttinggggghhgddd993[[[[699gjstyCELMMLJCxsgd0[[[______[[669000666660dnBDGJJJJLLOQQRRRRRQOMAkl1~~{{{{{2oAEJJCywnhdfdfff06}}_^/;&@+.. ...+${>;-*&$+.....", +"+@$%&&&%%%{2kkxxytsssssnnnnngad93[[[[69agjttyDCCEEEGDyig96[[_______[[660ddd000000fhsyGJJJLLLMOQRRRRRRQOFok11~~~*~~1kAFMLLGysnhdffff006}__^/-&@... ...+${1kFOQQNIAlb:39aiyEMQRRRRRRRIzo|)!@+++@!)|oAAxtj93[[[[3339aaaa93[[[________]]^^^//>>-*&$++....", +"@$%&***&&%{2koCCxxttttssssinga933[[[[9ajjttyyyyyDDytsgd96[[[______[[[69dddddd000ffnwDGJLLLMOQQRRRRRRRQIAk2~~~~~=<1kAFOOMLEDsnhdfff006}}__^>=%@.. ...@${1oINRQIFola333ajyEMQRRRRRRIFpo|)!@+++@!)|oAAAtj93[[[[339aaaa99[[[[_________]^^^///>;-*%@+....", +"$%*=--=*&&)|2oAACCyytttwtsngga33[[[[39gstyyyyywwssngd96[[[^_______[[69ddgnhhfdfdhnsyGJLLMOOQQRRRRRSSSNIo|{{~~==-*$+.. ..+@%{2AINNNIFkca3339jtGMOQRRRROIAo|))@@@+@@!|oAFFAtj93([[339aaaa993[[[[_________^^^^^^//>;=&$++...", +"&*-;;;-*&&){2oAEECDyyywtsngaa33(/[[[9gjtyyyyyssnggd93[[^^_______^[[69ddgnnnhhhhmnsyDJLMMOQQRRRRRSSSSNHp7|){{~-::cxFMQQQOLEDwshhfff06}___^/;&@+.. ..+@%~kAINNOIAlb3[[[9gtCLOQQRQOIAo||)!@@@@@@!|ozFFAxj93((339aaaaaa93[[[[_____^^^^^^^^^^^^/>;*&$++++", +"=;>>>>;=&&%{2oAEEECDyttsnga33(((//[[9gstyyyysnghd06[[[^^________[[[99gnnnsnnnnuwBDCJLMOOQQRRRRRRSSSSNHp7)){~=::cxFOQQQQOLJCyssnhff06}__^/>*%+.. ..+${1kzIOOIFxia3[[[6gsCLMQQOOIAo||))$@@@@@!)|zIIFFxia3((33aabbba996[[[[___[[[^^^^^^^^]]^^/>;*%$@@$", +">>///>>=*&%{2kAFFECDytigaa3((>>(//[39gsyyyysnhd06[[[^^^]]]]]___[[[69ggnnssssswyDGEJLMOQQRRRRRSSSSSSNNv7!)){~-*&&&&", +"//^^^/>-*&%{2kAFFJECysga33((>>>>(((3djstytsngd06[[/^^^^]]]]]___[[69dgnsssswwyDCELLMOOQQRRRRRSSSSSSSNHv7!){~<=%@+.. ..+$&~1kAFIFAxla3[[[[6dnyELMMFzp|!!@@@+@+@@@!|pzIIIFxlb:33abjjjjgad000666}}}[[[[^^^^^____]]^^/>-===-", +"^^^^^/>=&%%)2kAFFJECtia3((>>;;;;>((3ajsttssgdd6[[/^^^^^]]]]]]__[[69gnjsttyyyDGJLMOOOQQQRRRRRSSSSSSSNHp7|{~<;*%@... ..+@%*=;;>>", +"^^^^//;=&%$){2oEFJCxiba::>;;;;;;;>(3ajsttsngd96[[//^^^^^^]]]]_^[[99gjstyDDCCGELLMOOOQQQRRRRSSSSSSSNNHp|211ckAMORRRRRRRQOMLJEGDywmf6[^//>=&$+.... ...+$&=-:lkAAAxklja9000dhsyGJFzp7!'++++++++@@$)|pFIIFAxlcbbbittttsnghhffeeeeeee066[[[[_______]^^/>>>//", +"^^^//>-*%$$!)|oAEACtcb::;;;;;;---;::acittingd33[/////^^^^^]]]^^[[9gjttDCGGGEJJLLMMOOOQQRRRRRSSSSSSNNIpk11lkAMORRRRRRRQQOMLLJGDysh0[[//>;*&@+.... ...+$&*;>:blkxxxxttigdddhnwDGEFzp7''.+...+++@@)||AFIFFAklcccitxxxytsnmhhhheeeehff06[[[[}}}}____]^//////", +"^///>-*%$@@+!!|oAokl<<===--;;;--==-:bcitlingd33/////////^^^^^^^[39jtyCEJLLLLLLLLLLLLMMOQRRRRSSSSSSNNzokllkAFORRRRRRRRQOMLLJEGDBrd6[//>>-*%@+... ...+$&*;>((:clkxxCCCytnmmnsyDGEzp74''....+++@@$)2oAFFFExklccitxCCCxytsnmmmmhhmmmmmff06[}}}}}____]^/////[", +"(((>-*%$++++''77oo22{{{**=-----====<-*&$++... ...+$&=;>///(ablxAEJJGDywsswDCGEzp4''.....++@@$){2oAFFFAxllcilxCCCCDywsurmmmmmmrrrrmhff0066}}}___^^//(339", +"a3:={)@++.##''4477|)))%%&*=---=***~~>>>>>>>>>////[9jtCFMOQQQQOMLJCDyyxCEMOQRRRRRSSSSQIAokxAFORRRRRRRRRQOMLJJEGDBnd6[//>-*&%@+.... ...+@&*;>////(3alxEMMMLJCDyyDDGGzzp4''#....++@$){2koAFFEAxliiltxCEECDywuurrrrrrrruuurrmhhfe00}}___^^/39gii", +"ic<{)!+.###,,,,447!!@@@$%&*===*****~~1cilicba:(>>>>>>;;;;;;>>/(3atCFMQQRRRQQOLEDttttCEMOQRRRRSSSSROFAoxAFORRRRRRRRRQQOLLJEGDysg9[//>-**&$++... ..+@%*;>/^^^//3alAMOOOOLJGDDDGGEzp44''#...++@@$)22kAAFEACtliilxCCEECDywwuurrrrrruuwuuwuumhffe0}}__^[[9jtxC", +"l12)!''###,,,,,44'''++@@$%&******&&*~<1ccccb:::;;;;;;-==**=-;>(3ixJMQRRRRRRQOLEDtttxELOQRRRRRSSRRROFAAAFOQRRSRRRRRRQQMLJEGCDynd6[/>-=*&%@++... ...+$&->//^^^^/3atEMQQQQOLJGGGGJJzp44''#...++@$){2koAEEEAxliiltxCEEECDyBwuurrrrrruwwBBBBwwurhf06}}_[[9gsxCG", +"k2|!'''##,,,,5544'''+++@$%&&***&&&&{{~</^^^^^/3bxLOQRQQOMLJGGJJJzp4'''#..+++!))22koAAAAxtliiltxCEEEGDyywuurrrrruuwBBDDDDDBwrmf06}}[6dntCGG", +"22)!'''',',,555544''+++@@$%&&&&&&&&&{~<<<<<<==~*****&&&%%%&*=:blCMORRRRRRRRRQMECxCEMOQRRRSSSRRRRQOMFFMOQRRSSRRRRRRQQOLJGCDysnd6[/(;=*&&%@+.... ..+@&=>//^^^^/[9iCMQRRRQQOLJJGJJFzp4,''#..++!!)||oooCACxtijjjlxCEEJEGCDywuuurrruuwBBDDGJJGGDBumd06669ditxDx", +"2))!!+''''445vvv477!++@@@$%%&&%%%%%%&*~=<--=~*&%%%%%%%$$$$%*-:cxEMQRRRRRRRRQOMJEEFMOQRRSSSSSRRRQOMMMMOQRRSSSSRRRRRQQMLECDysnd9[[/>;=*&%$@+.... ..+$&->//^^///3atFORRRRQQOLJJJJJFzp44,,''''!!77ooooCCCxtljbjitxCEJJJEGDDBBuuuuuuuwBBDGJLLLJGDyumd0009gnsttt", +"))!!!!!!)77ppvvzpp7!!!@@$$$%%%%%$%%%%&*~==~*&%$$@@@$$$$@$%&~:biCJOQQRRRRRRQOMLJJLMOQRSSSSSSSSRRQOMMOOQRRRSSSSSRRRRQOMLGCywsg96[^/>-**&%$@+... ..+$*->//////(3jCMQRRRRRQOMLJJJFFzv44,,,''477ppzzAAACxxtijbjlyCELLLLJGGDDBwuuuuuwBBDGJLMOOMLJDBuhdd9ddgnii1", +")!!))){22|ozzIIIzpo|))$$$$$$$$$$$$$$%%&*~**&%$@@+++@@@@@$%*-:aiCJMOQQRRRQQOMMLLLMOQRSSSSSSSSRRRQOOOQRRRRSSSSSRRRRRQOMLGCysnd9[[^/>-*&&%$@+... ..+%*;>////>((btFORRRRRRQOMLLJLLIIvv555555vvHHIIIFFAAxtljjjitCELLLMLLJGDDBwuuuuuwBBDGLMOQQOMLGDwsghdddaab<1", +"!)){21;*&&%%$++... ..+@&=;>//(>>::iAIRRSSRRRQOMLLLLMIIHvqqqqqKPPNNNNNIFEAxtljjitxELLMMMMMLJGDDBwuuuuwBBDJLOQQQQOMLGDwngddda:<~{", +"7||21cclxAFMOOOOMFAk2{)$$@@@++++++++@@$%%%$@@+++.+++++@@%&->3ajtDGLLMOOMMLLLLMOQQRRSSSSSSSSSRRQQQQRRRRRRRSSRRRRRRRQOOLLGDtnd[[//;*&%%%$@+... ..+%*;>///>;;<1kFQSSSSSRRROMLLLMOOHHKKKKKPPPNNSSSROMJAxtljjiyCJLMOOOOMMLJDDBBwuuuwBBDJLOQQRQQOMJGywngaa:<~{)", +"ppokktxxEFMOOQOOOIzo2{)$@@++++++..++++@@@@@+++....++++@@%*-(3djsyCGJLLLLLLLLMOQRRRSSSSSSSSSRRRQQQRRRRRRRSSRRRRRRRRQQOMLEDtg9[//>*&%$$$$@+... ..+@&=>>//(>;-12oINSSSSSSRROMLLMMONNNPPPPPPNSSSSSSSRMFExtljitxGLMOOOOOOMLJGDDBwuuuwBBGJMQQRRRQQOLJGDtigbc1||7", +"vzzAACCELMOQQQQQOOIAo|!@@++..........+++++++......++++@@%*;(3ajsyDCGEJJJJLLMOQRRRSSSSSSSSSSRRRQQRRRRRRRRRRRRRRRRRQQQOMLGysa3[/>=&$@@@@@@+... ..+@%*;>//((:;=12zISSSSSSSRROMMLMOQRNNNNNNNSSSSSSSSSROFCxtiistCELMOOQQQOMLJGDBwwuuuwBBGJMQRRRRRRQOMLECyti12|74", +"NIIMFJFLMOQQQRRRROIzp|!+++........................++++@$&=>(3antyDCGEEJJLLMOQRRRSSSSSSSSSSRRRQQQRRRRRRRRRRRRRRRRRQQOOLJCtg9[//;*$@+++@@++... ..+@%*;>///((:;<1kzNSSSSSSSRROMLLMORRSSSSSSSSSSSSSSSSROFCttiisyCJLMOQQQQOOLJGDBwuuuuuBBGJMQRRRRRRRQOOMJGCxoppvv", +"NROOMMMMOQQQRRRRRROIp7!++.........................+++@@%&->3djsyDCCGEJJLLMOQRRRSSSSSSSSSSSRRQQQRRRRRRRRRRRRRRRRRQQOOMJCtn9[[/>=&@+++++++... ..+@%*;>////((>:<//////(>::-&@+.......... ..+@%*;//^^/[[/((>(:lFORSSSSSSRQOMLLMRSSSSSSSSSSSSSSSRRRQMCtsinssyDJLMOQQQOMLGDywurrrruuBBDJMQRRRRRRRRRRRRQONNNNSS", +"RRRQOMMOOQQQQQRRRRRNIz4''++.++......... ...+@$%*-:bixCGEJLLLMOOQQRRRRSSSSSSSSSSRRQQQQRRRRRRRRRRRRRRRQQOMMLJCysg9[^^/;*$@+......... ..+@%*;//^^^[[[//(((3iEORSSSSSSRQOMLMORSSSSSSSSSSSSSSSRRROLCtsnnswyDJLMOQQOOMJGDBwurrrruuBBDJMQRRRRRRRRRRRRRNNNSSSS", +"RRRQMMMOOQQQQQQRRRRRIzp7!+++@@++++..... ...+@@%*=%@+.......... ....@%*;/^^^__[[[/((((3bCMRSSSSSSROOMLMORSSSSSSSSSSSSSRRRRROLCytssswyDGLMOOOOOLJCywwurrruuuBBDJMQRRRRRRRRRRRRNSNSSSSS", +"RRQOMMMMOOQQQQQRRRRROIp7!!@@@$$$@@++.... ...+@%{=&@+...............+$&->/^^__}}[[/(((/3bxMQRSSSSRROMLLMORSSSSSSSSSSSSSRRRRROLGCytwwByDJLMOOOOMLGDywwurrruuuBBDJMQRRRRRRRRRRRRSSSSSSSS", +"RRQMMLLLMMOOOQQQRRRROFo|!$$$%%%%%$@+.... ...+@){1ctDCEJLMMOQQRRRRRRSSSSSSSSSSSSRRRRRRRRRRRRRRRRRRRRRRQQOOLJDwn9[/>-&$+...............+@&=>/^^__}}[[(((>(/(axLQRRSSSRROMLMMORSSSSSSSSSSSSSRRRRROMLGCDyyyDGJLMOOOOMJGDywwuuruuuwBBDJMQRRRRRRRRRRRRSSSSSSSS", +"RQOMJEEJLLMMMOQQQRRQOzo|)$$%%&&&%$@++... ..+@${1clxCGJLMOQQRRRRRRRSSSSSSSSSNSRRRRRRRRRRRRRRRRRRRRRRRRQQOMLGyn93(-&$+...............+@%*;/^^__}}6663((>//(9tEORRSSRROMLLMMORSSSSSSSSSSSSRRRRRRQOMLLEGCDGJLMOOQOOMLGDywwuuuuuwBBDGJMQRRRRRRRRRRRSSSSSSSSS", +"QQMLEGGGEJLLLMOQQQQOFA2{)$$%%&&&%$@+.... ...+${/^^_}}60003(((//[9lEMQRRRRQOMJJLMQRRSSSSSSSSSSSRRRRRRQQOOMLLJJJLMOOQQOOMLGDywwuuuuuwBBDGJMQQRRRRRQQQRRSSSSSSSSS", +"QQMLEGCCGGGJLMOQQQQOFo2{)$$$%%%$$@++.... ...+$&<:bixCJMOQRRRRRRRSSSSSSSSSNNNNRRSSSSSRSRRRRRRRRRRRRRRRQQQMLCwg3(-&@+.. ........+@$&->/^^_}}60fd03(((//[3jxMOQRRQOMFEGJMORSSSSSSSSSSSSRRRRRRRRQQQOMMLMMOOQQQQOMLGDywuuuuuwBBBDGLMQQRRRRQQQQRRSSSSSSSSS", +"QQMLEGDDDDCGJLOQQQQMEk2)$$@$$$$@+++...... ...+$&-(ajtCJMOQRRRRRRRSSSSSSSSNNNNNNSSSSSRSSRRRRRRRRRRRRRRQQQOLJDsa3>~%@.. ........++$&=>/^^__}}0ddd03((////3atEMOOOOMFGCCGLORRSSSSSSSSSSRRRRRRRRRRRQQQOOOOQQQQQQOMLGDywuuruuwBBDDGLMQQRRRQQQQQRRSSSSSSSSR", +"QOMLEGDDDDDCELOQQQOMAk2)$@@@@@+++........ ....@$&-(3gtCLMQQRRRRRRRSSSSSSSNNNNINNSSSSSSSSRRRRRRRRRRRRRQQQOMJCwg9(;*$+.. ......++$&=>/^^]__}60ffd03(///^^[3iCFMOMMJCDyDGLORRSSSSSSSSSSRRRRRRRRRRRRRQQQQQQRRRQQOMJCywurrruuBBBDGJLMQQQQQQOOOQRRRSSSSSSRR", +"OMMJEGDyyyyDGLOOQQOFCl{)$@@++++.......... ...+@$*;(3bxEMOQRRRRRRRRSSSSSSNNNHHINSSSSSSSSSRRRRRRRRRRRRQQQOMJGynd3(-&@.. ....+++@%*;/^^]___}60ef03((//^^^/3axAFMFFAxywyDJORRSSSSSSSSSRRRRRRRRRRRRRRRRQQRRRRRRQOMGDwurrrruwBBDGGJLOOQQQOOMMOQRRSSSSSSRRR", +"MMLEGDyywwwyGLMOQOMFx1{)$@+++............. ...+@%*;(3jxFMQQRRRRRRRRRSSSNNNNHHINNSSSSSSRSSRRRRRRRRRRRRQQOMLGysg93:*$+. ....++@%*->/^]]__}}60e003(//^^^^^[9lxEEEAxtsswDJOQRRSSSSSSSRRRRRRRRRRRRRRRRRRRRRRRRRQOLGysrmmmruwBDDGJLLMOOOOMLLLMOQRRSSSSRRRR", +"MLEGCDywuuwyGLMOQOMAk1{)@@++............... .....+@%*;(bxFMOQRRRRRRRRRRSSSNNHHHIINNSSSSSSRSSRRRRRRRRRRRRQQOLJDwnd3(=%@.. ...+@$&->/^]]]__}}800063///^^^^^[3btCAAxysissDJOQRRSRRSSSRRRRRRRRRRRRRRRRRRRRRRRRRRQOLCwummmrrwBDDGJJLLMOOMLLJJJLOQRRRRSRRRRQ", +"EGCCDywuuusyGLMOOMFAl1{%@++........................++@%~:alEMQQRRRRRRRRRRRRRNNHHzzIHNNSSSSSSRSSRRRRRRRRRRRRQQOLGysg9(-{@+. ..++@%*;/^]]]___}}66666[//^^^^^^^3alxxxxtinnsDJORRRSRRRRRRRRRRRRRRRRRRRRRRRRRRRSSRRROJDwnmmmruBDDGJJLLLMMMLJGGGGJMQRRRRRRRRQQ", +"CDyyywwurrsyGLMOOMExl<{%@+.......................+++@$&=:lAMQRRRRRRRRRRRRRROIzzpppzHNNSSSSSSSSRRRRRRRRRRRRRQOMJDtna3:~$+. ..++$&->/^]]]____}}}6[[[//^^^]]^^39jtxxtijnnwDLORRRRRRRRRRRRRRRRRRRRRRRRRRRRRRSSSSRRMJDwrmmmrwBGGJLLLLMMMLJGCCDGJMORRRRRRRQQM", +"ttwwwwuumrsyGLMOMLAkc<~%@+... .....+++....+++++@@$&*^]]]]]___}}}}[[[/^^^]]]^^[3bltttinnsyGLQRRRRRRRRRRRRRRRRRRRRRRRRRRRRRSSSSSSQMJDwnmmruBDGJLLMMMLLJJGDDDDCELOQRRRRRQQML", +"ssswwwuuruwDELMMMFClb:~%@+... ....++++++++@@$$$%%&*-:lFORRRRRRRRRRRRQOMAok|||7pIHNNSSSSSSSSSSSSRRRRRRRRQOMJDtga3:{$+. ..+@%*;/^]]]]]____}}}[[/^^^^]]]]^[3ajltiiiswDJMQRRRRRRRRRRRRRRRRRRRRRRRRRRRRSSSSSSSQMGywumruwDGJLMMMMMLJJGDDDDDCELOQQRRRQQMJC", +"nnsuwwuuuswDJLMMMExj::=%@+.. ...+++@@@$$%%&&****~-:bxFORRRRRRRRRRRQOFAk22))|7pHNNSSSSSSSSSSSSSRRRRRRRRQOLGyia3:=&@+. ..+@%*;/^]]]]]______^^^^^^]]]]]]^^[9gjiiiswyGLOQRRRRRRRRRRRRRRRRRRRRRRRRRRRRSSSSSSSQLGywuruwBDJLMOOOMLLJGDyyDDDGELMOQQQQQMJCt", +"nnsuwwwuuwyCJLMMJClb3:-&@+... ....++@$$%&&*=------;>:jAMQRRRRRRRRRRQOFAk12{))!7vHNNSSSSSSSSSSSSSRRRRRRRRQOJCtg93:~)+. ..+@%*;/^]]]]]______^^^^^]]]]]]]_^[3ajiistyDJLORRRRRRRRRRRRRRRRRRRRRRRRRRRRRSSSSSSSOLGywuuuBDGLMOOOMMLJGDyyyDCGEJLMOQQQQMJCtn", +"nruwBwwwuwyGJLLLExj3(>-&@+... .....+@$%&*=-;>>>>>>>>(alAMOQRRRRRRRQQOLAkl1{)))|pvHNNSSSSSSSSSSSSRRRRRRRRQOMEDsa9(-{@+. ..+@%*;>^]]]]______^^^^^]]]]]]]]_^[[9gnistDGJMQRRRRRRRRRRRRRRRRRRRRRRRRRRRRRSSSSSNNOLGywuwwBDJLMOOOMLJGDBwwyDGJJLLMMOOOMLGysn", +"ruwBBBBwwBDGJLLExia3/(;&$+.........++$%&*-;>>////>>>/(atEMOQQRRRQQQOMLExl<1{{))7pHPNSSSSSSSSSSSRRRRRRRRRRQOLGyia3:~)+. ...+$&->/^]]_____}[^^^^]]]]]]]]]__[[9dgntyCELOQRRRRRRRRRRRRRRRRRRRRRRRRRRRRRSSSNSNROLGywwwBDGLMOOOMLJGDwsstDGJLLLLLMMMMLEDsng", +"uwBDDDBBBBDGJJECtb3///;*$+.........+@%&*-;>//////////(atCLMOOQQOOOMLJExlc<<~{{|7vHNNSSSSSSSSSRRRRRRRRRRRRQMJCtga3<{@+# ..+$&->/^]]___[[[[^^^^]]]]]]]]]__[[69gntDCJLOQRRRRRRRRRRRRRRRRRRRRRRRRRQQQRRSNNNSQMLGDBBBBGJLMOOMMJGDwunsyCJLMMMMLLLLLECtsng", +"wBDDDDDBByDGGGCtj93^//;*$+........++$&*=;>>//////>>>/(aixELMMMMMMLJECxlca:<~{{|pHNNNSSSSSSSSSRRRRRRRRRRRQOLGysga:~!+. ..+@&=>/^^]_[[[[[[[^^^]]]]]]]]]___[60dntDGJMOQQRRRRRRRRRRRRRRRRRRRRRRRQOOMOORNNNQOMJGDyBBDGJLMMMMJGDwumnsyELMOOMMLLLJECysnnn", +"BDDGGDDByDDCCDtj93^^//;*$+........+@%&*-;>>/////>>>>//3btxCEEEEEECCxtlba::<~~2ozHNNSSSSSSSSSSSRRRRRRRRRRQMJCwna:<)@+# # ..+@&=>/^^^^[6666[[^^^^]]]]]]]]____}0dntCELMOQQRRRRRRRRRRRRRRRRRRRRRRQOMLFFMOOQQOMLECDBBDDGLLMMMLJDwughgsCJMOQOOMLJEGDysnnnh", +"DDGGJGDDDDDDDyja3[^^^/;*%+.......++$&**-;>>>>>>>>;;>>((9jityxxxxxxttiba3(:<<12pIHNNSSSSSSSSSSSSRRRRRRRRQQLGDsna<{!+. ..+$&->/^^^[[6666[[^^^^]]]]]]]]____[0dntCELMOQQQRRRRRRRRRRRRRRRRRRRRQOMJGCCEFMOOMLJGDDBBDGJLLMMLJDysngggtCLOQQQOMLECytsngghm", +"DGJJJJGDDDDyysg9[^^^^/>*%+.......+@%&*==-;>>>>;;---;;>((3aggjiiiiiibaa3((:<<2ozHNNNSSSSSSSSSSSSSRRRRRRRQOLGysb:~)+.# ## ..+%=>/^^^[[6666[[[^^^]]]]]]]]]]___[6dntCELMOQQQRRRRRRRRRRRRRRRRRRRRQMJCytyxCEFFJEGDDBBBDGJLLLLJGDwngdgiyEMOQQQOMJCysngddhhm", +"JJLLLLJGDDywsg9[[^^^^/>=&@+.....++$%&**=---;;--=***==;>((333aaabccba:(((>:<12oINNNSSSSSSSSSSSSSSSRRRRRRQOLCyic1{!+## # .+$*;>^^^^[[666[[[^^^^]]]]]]]]]]___}60ntDGJLOOQQQRRRRRRRRRRRRRRRRRRQOLCysiistDCCCCDyBBBBDGGJLLJJDBshddgixJMQQQQOLEDtngdddhmu", +"MMOOOMLJDDBsgd6[^_]]^/>-&$+.....+@%&***======***&&&&**=;>>((::::::::((((>::1ozINNNSSSSSSSSSSSSSSSRRRRRRQOLCyic2)+.#### ..@&->/^^__}[[[[[[^^^^]]]]]]_]]]_____69gsyCJLMOQQQQRRRRRRRRRRRRRRRRQOMGDwngggiswyyywwwwwBDDGJJJGDyundaaaiCFOQQQQOLEDsndddhrwB", +"OQQQQOMJGysnd6[[__]]^^/;*$++...+@$&**======***&&%$$$%%&*=----=<<<::((((((:blAINNNSSSSSSSSSSSSSSSSSRRRRRQOLGyl1)!'#### ..+%*>/^]]__}}}[[[^^^]]]]]]]]]_]______[0dntDGJLMOQQQQRRRRRRRRRRRRRRRQOLCysndddgnnsssuuuuuBBDGGGGDywnd93abiCFOOQQOOLGDsnghhrwDG", +"QQQQQQMLGysg9[[^__]]]^/>=&@++++@$&*=---===***&%$$@@@@@$%&&***~~=<::((((((:ckAIQNSSSSSSRRSRSSSSSSSSRRRRRQOJCk2|!'##### .+$*;/^^]____}}[[^^^^]]]]]]]___]_____}[9dnsyCGJLMOQQQRRRRRRRRRRRRRRQOMEDsnddddddhgmnrrruuwBDDDGDBwmd93::bixFOOQQOMLEDwsnnswDGL", +"RRRRQQOLGynd6[[^___]]^^>-&%@@@@$&*=;;;;--=**&%$@+++++++@@$%%&{*~=-:((((33alxFORRSSSRRRRRRRSSSSSSSSRRRRRQMJCk|!'#### ..+$&;>^^]________^^^^]]]]____________[[69dgswyCEJLMOOQQRRRRRRRRRRRRRQOLCyuhd00660ddhhmmrruwBBDDDBwrd03::::ixJMOOQOOLJGDBwwBDJLO", +"RRRRRQOLCyn96[[[^___]^^/;*&$$$%&*-;>>>;;;-**&$@++......++@$%%&{~~<::(333aixEMOQRRRRRRRRRRRRSSSSSSSSRRRQOMAk2!'### # .+$&->^^]]_____________]_____________[[69ddgnsyDDGJLMOOQQRRRRRRRRRRRQQLEDsmdd0666600ffhmmruuwBBBBwrh03(:-<=*&%&&*-;>>>>>;;-*&$@+..........+@$)){{~<<:aaagitCJMOQRRRRRQRRRRRRSSSSSSRRRRRQMJxk|!'## .+$*;>^^]]___________________________[[6dggnnsswyyDGGJLOOQRRRRRRRRRRRQOLDBrhd0666[660ffhmmrruuuwwumh03(:-==-*&&&*-;>>>>>>;;=&%@+..... ..++@$)){211cccityCJMOQQRQQQQQQRRRRRRSSSSRRRRRQOFCl2!'## .+$*;/^^]]___________________________[[9gnsssssswwByDDGJMOQQRRRRRRRRRQOLGysmhe066[[[60ffhmmmmrrrmmhf03(>;===;****=;>>>>>>>;=*%@+.... ..+@!!))|2kkkkxDGFMOOQQQQQQQQQQRRRRRRRRRRRRRQOLEt1|!'# .+$*;(/^^________^____________________[9gsyDDDyywwwwwBDDJLMOQQRRRRRRRRQOLDBuhfe06}}}[60fhhhmmmhhhff033((;-===;**&*=;>>>>>>;=*&$+.... .+++!!!!||ooCAEFMMOQQQQQQQQQQQRRRRRRRRRRRRRQOMExl1)@. .+${:((/^^[[}}[^^^^___________________[6gsCEJEGCDywwsuwBDGJLMOQQRRRRRRQOLGDwrhee066}[[60dhhhhfff0063(((>>;===-:cyGLMMOOOOQQQQQQQQRRR", +"RRRRRRQMJCyyyyyttng96[//>-*&&*=-;>>>;-=*&$++... ..++!!!77ppzzFMOOOQQRQQQQQQQQQRRRRRRSRRRRRQOMLCtc1)+. .+!{>;-=~==-:ixGJMMMOOQQQQRQRRRRRR", +"RRRRRRQMLECCCCCDysgd6[//;=*&&&*=;;;;-*&%$@+... ...+@@!!77pzzFIOOOQQQQRQQQQQQQRRRRRRSRRRRRQOOLExi:~)+. ..@)1lllijgdddd066[[^^_________________[0gyEMOOOMLJGDBwsswBDDGGEJLMOQQQOOLJDwumhee866}6600dddd0663((>>;;-=***=-:bixELLMMOOQQRRRRRRRRRR", +"RRRRRRQOLJEGGEGCysg9[[/>;*&%%%&*=--=*&%$@+.... ..+@@!!!77pzFIOOOOQQQQQQQQQQQRRRRRRSSRRRRQQOMJCtb:~$+. .+!2kxCCCyttsnngd96[[^________________}[9sCLOQQQOMLEDywsuswwBBByDCJMMOOOMLGywrmhee066666099d9033((>>;;-==****=;:btCELLMMOOQRRRRRRRRRRR", +"SSSRRQOMLJJEGGCDtn9[[//>=&%$$$%&***&&%$@++.... ..+@@$))||opzFIOOOQQQQQQQOOOQQRRRRRRSRRRRRQOMLExja<&@+. ..+!2oFMMLLECDytsgd3[[[________________[6dtEMOQQQQOLJCywsuuuuunnnntxELMMLLEDywrmhee006666699333(((>;;-==*****=;:3gtCELLLMOOQRRRRRRRRRRR", +"SSSRROMLJGGGCDysn9[[^/>-*%@@+@$$%&&%$$@++.... ....+@%&*~22kAEFMOOOOQQQOOOOOOQQRRRRRSRSRRRQQOMFCtb:~$+.. .+!|oFOOQOOMLJGDtna96[[_______________[[6gtEMOQQQOOLJCywsrnmhhd999ajtCELLJGDywrmmee80666[66333/(>>;-===***==-;>(3iyCJJLLMMQQRRRRRRRRRRR", +"SSRROMJECDDyttjg9[[^//;*%@+++++@@$$$@@+++.... .....+@%*=-:>;-======-;;>>(3asyGJLLLLMQQRRRRRRRRRSS", +"SRQOFEDytsnngg9[[^^^/>=&@++....+++++++++..... .. .....++$&=;>(actCEJLLMMMOMMMLLLMOQRRRRRSRRRRRQOMMFClc<{@+.. .+!7INSSSSSRRROMFxtgd96[}}}______[///////33glxEFLLLJGywsghdd06[[[^^/[9jtCCCDDywurmhff0066[[[///>>;-=====-;>>(//[3gtCEJLLLLOQQRRRRRSRRSSS", +"ROIExljggdd96[[[^^^^>-&$++.......+++++++...... ......+@%*;>((ajtCCEJLLLLLLLJJJLMOQRRRRRRRRRRQOMMFAtc<~$+.. ..+!7zNSSSSSSSSSQOFCtja9066}}}}}_[/////((>>((:bilkxxxytigdd0066[[/^^^^/3ajtyDDDyBwurmhhd006[[////>;;-===-;;>////[6dsDGJLLLLLOQRRRRRRSRSSSS", +"IFClba336[[[[[__]^^>-&$++.........++++@++.............+@%*;(/39jtDCGGEJJJEGGCCELMOQRRRRRRRRRQOMFECxib<{$+.. .+!7pHSSSSSSSSSRROFAxigd9066}}}[[//(>;;;------<<<<1cccaa33333[[[/^^^^^^[9gttyyyyBywwummhd06[[////>;;----;>>//[[[3dnyCJLLLLLMOQRRRRRSRSSSSS", +"Akla3([[[[[^__]]^^>;*$++..........++@!!!@++...........+@%=;//3aitDCCCCCDCDDyyyCJMQRRRRRRRRRQOMJExtjb:=&$+.. ..+@!pINSSSSSSSSRROOFAxtjgdd066}[[/(>;=********~~~~~~~<<::(((///////^^^^^/3ajsyyyDDDyywurnd96[[////>>;;;;;>(/([39dgntCELLLLLMOQQRRRRRRSSSSSR", +"lca((/^^^____]]^^>;*$@+.........++@!)))))!@++.........+@%*;(/3aiyDDDDyyBwwtstyCLOQRRRRRRRRQMLECxtjb::=&@+.... ...+!|oINSSSSSSSRRRQOMMJECysnhd06[[/>;=*&%%%&&&&&****{{**~=-;>>((//////^^^^^[9gstyyDDDDDyBsng93[[////>>>>>>>((33agjstDCELLLLLMMOQRRRRRRSSSSRQO", +"a3(//^^^]]]]]]^^>;*%@+.........+@$){22222{)$@++.......+@%*;>/3gsyDDDywwunnnisyELOQRRRRRRRQMFECxtjba(:=&$@+.........+@!|ozNSSSSSSRRRQQOOOMMLJECyshd93(>-*&%%$%%%&&&&*&*&&&&&**==-;>>>>////^^^^^[9gjtyDDCGGGDywsg96[///////(>>(((39gitxCGELLLLLMMMOQRRRRRRSSSSSOMF", +"3((/^^^]]]]]]^^/;*%@+........+@$&~1<1lcc<<~{%@+........@%*;>(3gsyDDywsnmhhgntxEMQRRRRRRRQOLECxtiba3(:=&$@++.....++@$)2kzIRSSSSRRRRQOOOOQQQOOMLGysh93:-*&%$$$%%&&&********&*****=-;>>>///^^^^^^[3gjtyDCGGEGGDysg9[[///////////[39gtCEJLLMMMMMMMMOQRRRRRSSSSSSQMAx", +"(//^^^^]]]]]^^/>=&$+.......+@$%*=::bbbcb::-~&$@+.......@%*->(3gsyyyBsnhdddgiyELOQRRRRRRRQMJCxtljba3(:-*%$@+++++@@%&~1kAIRSSSSSRRQQOOOQQRRRQQOMLCyia:;~*&%%%%%&&**=====********==-;>>>//^^^]]]^[3antyDCGEEGGDysd9[[[[[[[[///[[69gtCJMOOOQOOOOMOOQRRRRRSSSSSSRIAki", +"//^^^^^]]]]]^/>-*%@+......+@$&~->((33aa3(:-=*%@+.......+$&=;(3gsyywsnhd09djtCJMOQRRRRRRROMExtiija33(>-~&%%$$$$%&*=-:lAIRRSSSRRRQOMMOQQRRRRRRQOMExia:-~*&&&&&&**=--;;;;;---====--;;>>/^^^]]]]]_^[9nsyDGGEEEGDwnd6[[[[[[[[[[[669gsDEMOQQRQQQQOOOQQRRRRSSSSSNNIzkca", +"///^^^^^]]^^^/>-*%@+......+$&=;>(((333((>;-=&%@+.......+$&*->3aitssnhd069diyELOQRRRRRRRQOLExtija93((>;-=*&&&**=-;>(cxFORRRRRRQOOMMMOQQRRRRRRQQMExib:-=**&***==-;;>>>>>>>>>>;;;;>>>//^^]]]]]]]_^[9nsyCGGEEGCysg9[[[[[[6660600dgsyELOQRRRRRQQQQQQRRRRSSSSSPPHzo1b3", +"//////^^^^^^//>-*%@+.....+@%~;>(/////((;-=~*&%@+.......+@%*-:(aninnd06669gtCJMOQRRRRRRRQOLCytjga33(/(>>;;--;;>>//3bxFOQRRRRQQOMFFFMOQRRRRRRRQOFCtc::-=~****=--;>>>>///////////////^^]]]]]]]]]__[9gsyCGGEGCytnd6[[[[60dfdhhdhmsyGLOQRRRRRRRQQQQRRRRRSSSNPKKv7|1::", +"(///////[[[[(/(;=&%@+...+@%*->((/[///(;-**&&%$@+.......+@%*=;:agggd06[[39gtCLMOQRRRRRRQOMEDtiga33(/////>>>>/////3bxEMOQRRQQOMFECEFLOQQRRRRROMFAklc:-=~*****=-;>>>///^^^^^^^^^^^^^^]]]]]]]]]]]]^[9gsyCCGGCDtsd96[[[60dhmrrmmruwDJOQRRRRRRRRQQQQRRRRSSSNPKq54'!{~-", +">((((33aabbbaa3::~&$@+++@$&=:(333[[/(>-*&%%%$$@++......+@%*=;(aagdd3[[[39gtCLMOQQRRRRRQOLCyiga33[////////^^^^^[3btEFOQQQQOMFAxttxCFMOQQOOOIFAolc<<<~~*&&&**=-;>>//^^^]]]]]]]]]]]]]]]]]]]]]]]]]^[3gsyDCCCDtsgd06[660dmuwwwuwwBDGLOQRRRRRRRQQQQRRRRSSNPKqq5,,'+$&~", +":::abblxCCACxtib:<{%$@@@%*=:33aad333(:=&%$$$$$@@++.....+@%*=;:3ada33(/(39jtCJMMOQQRRQQOLGysga93[///^^^^^^^]^^[3btCFMOOOOMFAxijjjtxEFMMMIFAokk211~~~{&%%%%&**-;>/^^^^___]]]]]]_________]]]]]]]]^^[ajtyDyytsgd906600dnuwBBBBwByDJMQRRRRRRRRQQQQQRRRSNNHq5,,##.+@%&", +"//^^______]]]]]__[[[[[^^_]]]]]^^^^[9gjtttsngd99000dhnuBDDDDBBBDGLOQRRRRRRQQQOOQQQRRNHv5,,### ..+$%", +"//^_______]]]]]__[39999[[^_]]^^^^^^[3dgnnggd990090dhnsBDDDDDDBDDJMOQRRRRRQQOOMMOOQOOIv4,### ..+$%", +"clxEMOQRRRRRROJx22{)&*=:agtxCCECCxtja:=~&&&&*****&%$@@@$%&*~=<<:::((((33dgityDGJLLLLLGDsg9[[^^^^^^^]]]]]_^[9gtCEJFFFECxtja9936639aaab<1{{))))))))))%%%%&*=;>//^_________]]]__[9ajjjg93[^^^^^^^^^/[39dd99666609dhnswBDGGGDDDDGJMOQQRRRQOMLLLLMMMMzp4'## ..+$%", +"clxEMQRRRSSRROzo||){{=:agtCEJLLJECxlb::==~~=--;;;-=*&&%&&*~~~<<<:::(((33dgnstyyCGEEGCynd6[[^^^^]]]]]]]__^[3gtxEEEEACxtjga9996663333(::=~~{{{{{{{{{{{{*~=;>(//____}______]]__[6ajttttj9[[^^^^^^^^/[[6366[[[[660dgnsBDDGGGDDDDGLMQQQQQQOMLEGCCCECoo7'## ..+$%", +"ackEMQRRSSSRRIzo2{{{~::gtCELMMMLLECtb::;--;;;>>>>>>;-=~~~~~~~~1<<::((333dggnnswyDDDysnd6[[___]]]]]]]___[[3aitCAACxtljbaa9999996[[[(/(>>;;---<<<::<:-:::((/[[}}}}}}_____]_]__[9nsyyytja3[^^^^^^^^/[[[[[[[[[[60dhnuwBBDGGGDDDCGLMOQQQQOLECyttttll2)!'. ..@$&", +"3alAMQRRRRRRIzo22{{~::btCJLMMMMMLECtb:::>>>>>////^//>>;;--=~~~11<::33339dghggnsswwsng96[____]]]]_____[[[3ajtxxCxklcbaa9dddddd006[[///////((333aa93333333[[}}}}}}}}_____]]__[[djtyyysnd6[^^^^^^^^^[[[[[[[[[[60dhnuuwBDDDDDDDGJLMOQQOMLGDsjgaac1{)++.. ...@%&", +"(3jxFOQRRRROIAk2~~<::btCJMMOOMMMMEClc:(>>>////^^^^^^///>>;-=~~11<::33399dddhhgnnsnng96[[^___]]___^[[[[69agittkkllcbaaaddhhhhhd06[[^^^^^[[[69dddhddd00066666}}}}}}}____]]]__[6dnswwsnh9[[^^^^^^^^[[[[[[[[[[[60dhmuuwBBBDDDDDGJLMOOOMLGyja93(:~{!@+.. ..+@%*", +"/3atEMOQQOOFAk1<<::abtCJMOOOOOMMLExlb:(((////^^^]]]^^^///>:-<111cba3999ddddhhhnnngg96[[________[[[699dgggjiiliccc:aadddhmmnmhd0[[[[[_[}[660dhmmmmhhfee0008888}}}}____]]]]__[6dgnnngd06[__]^^^^^^[[[[[[[[[[60dhmrruuuwwBByyDGJLMMMMLGyja3((-*%$++.. ..+@&=", +"/(3jxJMMMMExlc::((3aiCJMOOOOOOMMFExia:(((///^^^^]]]__^^//((:<<", +"^^[[[999933[/[[[6dsDLOQQRQQQOMLJCtja3((/////^^^]]]_____^^[(((:abnitwyyDCGEJJJJGDysnhdf006600dmsyCGEECylcc:::::300fhmrrrrmhe06}}___}}}60fhmuuwwurmhfee088888}}}____]]]]]]____}}}}}}}____]]]]]^[60dhhdd0000dhrswwurmheee0ddntDGJJECyja3[/>-&$@+... ...+@%*;(/", +"^^^[[[[[[[^^^[[6dnyJMQQRRRQQOMLExlba3((////^^^^]]]]]]__^^[/(33agisyyDGEJLLMMMMLGDwsnhhfffefhmsyCGEECxlcb:::(3300femmrrmmhe06}}_____}}60fhmuuwuurmfee00086}}}}}___]]]]]]]____}}}}}}_____]]]]_^[0dhmmhdd0ddhnwBBwwrmhe0000dntCGJJEDtj93[/>-&$@+..... .....+@&=>//[", +"[^^^^[[[_^^___}0hBGMQQRRRRQQOMLExib33(////^^^^]]]]]]]__^^[/(3aansyDCGJLLMOOOOOMJCywurrmmhhhhnsyDCCCxlca::(33660eemmmrmmhe06}_______}}60fhmuuuurmhf000666}}}}}____]]]]]]]____}}}}}______]]]__[60hmmmmhdddhuwyDyBumhe06660dntCEJEGytg93[//;*&@++........+@$*->/[[[", +"[[[^^^_______}6duDLOQRRRRRQQOMJCtja3(////^^^^]]]_]]]]___^//(3agsyDCGJLLMOOQQQOMLGDBwwwurrmmmnswyyytiba33336660eemmrrrmme06}}________}}0dhmuuuurhd00666}}}}}}____]]]]]]]]___}}}}}_______]___[[6dhmmmmhhhmuwyDDDBumf06}}60dsyGEJECytg93[//>;*%$@+++++++@@%*;(/[[66", +"[[[/^^______}6fmBJOQRRRRRRQOMLGxia3((///^^^^^_____]]]___^^/(3aitDGJJJLLMOOQQQOMLGDDyyBwwuurmniiiicba:33336660eemmrrrrmhf06}_________}}0fhmuuuumhf0066}}}}}}____]]]]]]]]____}}}}____________[}0fhmmmmmmnuwDCGGDBrh06}}[69gtCEJJECytg93[[//>;*&%$@@@@@@$&*;>/[[666", +"(////^___}}}60hwGLQRRRRRRRQOLECtg93(///^^^^^_____]]]]]]]^^/(3atDGJJLLLLMOOQQQOMLGGCDDDDBwunnggaaa::(((3[[660eemruuwuumhf06}_________}}00hhnrrnhd006}}}}}}}_____]]]]]]]_____}}}}__________[[[60fhmmmmmnsyDGJJGDwnd6}}_[69jyCEJJECytja9[[^^/>;=&&%$@@$$&*;>//[6666", +"(((/[[}}}}60fmuDLOQRRRRRRQOLECtg93(///^^^^^______]]]]]]]^^/(3btCJLLLLLLMOOQQQOMJJGGGGGDDBwngaa::::((([[[660efmrwBBBBwrh06[[________}}60dhhnnnhd0066}}}}}}}____]]]]]]]]____}}}}}_______^[[[[600fhmmmmrswDELLLJDwh06}_[[6atxEEJEECytjg9[[^^//>-*&%%$$$%*=>///[6663", +":>((/[[600dhuwDJOQRRRRRRQOMJDtg93(/////^^^]______]]]]]]]^^//3cxGJLLLLLLLMOOOOMLJJGGJJGGDysic:::::((([[[660ehmuwBDDDywnh06[[________}}60dhhnnhhd0666}}}}}}}____]]]]]]]____}}}}}}}____[[[[[6600fhhmmruswDELMMLJCsh0[[^[[3gtCEEEEGCxttga9[[^//>;*&%$$$%&*;>/^/[[333", +";;>([66dhnwyDJLOQRRRRRRRQOLCtn93(//////^^^]_____]]]]]]]]^///3bxGJLLLLLLLMOOOOMJJGGGJJGGDBic<<:::((([[[60efhruBDGGGDysnd6[[[________}[60ddhhhhd0066}}}}}}}_____]]]]]]____}}}}}}}}}_}[[[6999ddhhhmruuwBDELMOOMLGwg0[[^[[9jtCEEEEECCxtjg9[[///;=*%$$$$%&=>//^[[[[((", +";>(/[6dnwDGLMOQQRRRRRRRRQMJDjd3[///////^^^]]____]]]]]]]^^//((bxGJLLLLLLLMMOMMLJGCCGGGGDysic<:::((/[[660fhmuwDDGJJGDysg9[[[_________}}60ddhhhdd0666}}}}}}}____]]]]]]____}}}}}}}}}}}6699ggnnnsssswwwyyDELOOQQOMEyn9[[[[39jtxCCCCCCCxtsg93[(/>-*%$@@@$&*->/^^^[///(", +">///6dnyGLOQQRRRRRRRRRRRQMEyg93(/((/////^^]_____]]]]]]]^^//((cxELLLLLLLMMOOMLJGDDDDDDDytic<::>(//[[60fhmuwBDGJJJJGysg9[[[__________}}00ddhhdd006666}}}}}}____]]]]]____}}}}}}}}}}6609gnstyyDDDCDDDCGEJLOQQQQQOLDsd3[[[3ajtxxCCCCCCxyig93((>-*%$@@@$%&=>/^^^^^^///", +"///[0myJMQRRRRRRRRRRRRRRQLGtg3(/(>>////^^^]_____]]]]]]^^//>>:lxJLMMMMMMMOOOMJGDwssswtttic<::((/[[[6dhmuwBDGJJLLJGDwn9[[[__________}}600dhhhdd00066666}}}}____]]]]____}}}}}}}}}}609dnstDCEJJLLLLLLLLMMOQQRRRQOMGtg93339ajittxxxCCCxtib33(;=*%$@@@@$&=;>/^^^^^^^//", +"^^[6hwJMQRRRRRRRRRRRRRRQQMCta3(((>(////^^]_______]]]]]^^/>>>:lCLMOOMOOOOOOOLGDtingniiiicc::((/[[60dhuwBDGGJJLLJGCynd6[[___________}}60ffhhfdf00006666}}}_____]]]]____}}}}}}}}6600dnsyCELMMOOOOOOOOOOQQRRRRRRQMJyia93399gjjiltxxCxysja::-~&%$@@@@$&*;>/^^^^^^^^^^", +"^^[dsGMQRRRRRRRRRRRRRRRQOLCta3((((///^^^__________]]]]^//>;:bkEMOOOOOOQQQOMJCticaaacciccb:3([[[60hnwyDGJJLLLLJGDysd6[[______]____}}60fdhhhfff00000088}}}_____]]]____}}}}}}}66600dnsyCJMMOQQQRQQQQQQQQRRRRRRRQMJxia999999aaajityyytib:<~{%%@@@@@$&*;>/^^^^^^^^^^^", +"_[6nCMQRRRRRRRRRRRRRRRRQOLCtb93((((//^^____________]]]^/>;;-ckFMOOOQQQQQQOMExl1<:::ccccba336[60dhsyCJJLLLLLLJGDysg9[[____________}}60ffhhhfffe0000086}}______]]______}}}}}6000dhnsyCJMOQQRRRRRRRRRRRRRRRRRRRQMExja933333339ajistiib<<~{%$@@@@@$&*;>/^^^^^^^^^]]]", +"[[gCLQRRRRRRRSSSSRRRRRRQMExtga99333[[[[____}}______]]^^/>;-<1kFMOOOQQQQQOOFAk21<<::acccgad9099hnwDGLMOOOMMLJGDBwnd0[[___________}}60efhhhhffee008086}}_____]]]_______}}}6600dhnstyCJMOQQRRRRRRRRRRRRRRRRRRRQOLCta93333[[3333abjjbb<1{)$@@@@@@$&*->/^^^^^^^^^^]]]", +"[gyLQRRRRRRSSSSSSRRRRRQOLExtjbggggad966[}}}}}}_____]]^^/;-==1kEMMOOOOQQOOMzo211<:::aagggggddhnsyCJMOOQQOOMLJGDwuhd6[[__________}}}00ehhhhhfeee0806}}}}__^^^]]]]______}}600dhnssyDEJMOQQRRRRRRRRRRRRRRRRRRRROMEtb933(///////3333a:<~{!@@+++@@$&*->/^^^^^^//^^^]]]", +"atEORRRSRRSSSSSRRRSRRRQMJCytiiitstsjndd0066}}}______]^//;-==//^^^^/////^^]]]", +"jCMQRRSRRSSSSRRRRSRRRQOLExttittyyDDytsnhdd006}_____]]^//>-==////^^^^^[[[60dgnstyCELMOQQRRRRRSRSRRRRRRQQQQQOOMFCtba3((((>>(//////(:={)@++..++@$%*->>/^^^//>>>//^^]]]", +"xJORRRSRSSSRRRRRRRRRQOMExttistyDCCCCCyyssnhd06}____]^^//>;-<>>;;>>///^^^[[[9dgnstyDCELMOQRRRSSSSSSSRRRRRRQQOMMLJCxlba::::::;>>(////(>-*%@++..++@$%*->>//^///>>>>>/^]]]^", +"CMQRRSRRRRRRRRRRRRRQOMExtjnnistyDCGGGCDyywshd6[___^^^///>;-<>>;;-;;;>///^^[[[9gnsyDCCGJLMOQRRSSSSSSSSSSRRRRQQOMLGCylccc:<<<<<-;;>/////>;~&$++...+@@%*->>//^//>>;--;>/^^]__", +"EMQRRRRRRRRRRRRRRRQOLEDsnggdgnswyDGGGGGGCDysg06[^^^^^///(>:::cityyDDyytic1<=-;>(/36660dhnsyDGLMOQQRRRRRQQOLGywsnggd9966666}}}}}}8800066[[[////>>>;;----;;>(///^^[[9gstDCGGJLMOQRRSSSSSSSSSSSSRRRRQOMLGDtic<1111111<-->>/////>-*%@++..+@@%*->>/^^//>>-===;>/^]]_[", +"JMQRRRRRRRRRRRRRRQOMJDtndd0ddhnuwyDCGGGGGCDynd6[^^^^/////(((abittyyyttic<<~=-;>(/[[6600dhnwyGJLMOQRRRRRQOMEDwnnggdd99666666}}}}}}}}}}[[////(>>;;;-----;>>/////[[[6dntyCGJLLMOQRSSSSSSSSSSSSSSRRRRQOMJCyic<1222|221<<:>//////>-*%@++++@$%*->>/^^^//>-***=;>^]]__[", +"JMQRRRRRRRRRRRRRQQOLGyshd0000ddmmuwyDGGGJECysg9[[^^^/////((3agistwwssic<<~~=->(//[[}}660dhswDGJLOQQRRRQQMLCtngdddd999666666}}}_____[[///>>>>;;;-----;>>/////^/[[[6dnsyCEJLMOQRSSSSSSSSSSSSSSSRRRRQOMJDtic122|oook1<:(///////>-*&$@@@@$%*=>>/^^^//>;=***=;/^]]_^[", +"JMOQRRRRRRRRRRRQQOMJCwnd0000000fhmrwBDGGJJGDtnd6[[[[[[[[[339agissssincc<~~~=;>(/[[}}}}660dgswyGJMOQRRQQOLCtnd9909999966666[}_____^^//(>>;;;;;;----;;>///^^^^^^[[[0dgsyDGLMOQRSSSNNNSSSSSSSSSSRRRRQOMJDti112|ooooklb((/^^^^//>;-*&%$$%&*->>/^^^^//>-****=>/^]]_[[", +"ELOQQQRRRRRRRRRQQOLEDtnh00000000fhmuwBDGJJGDynd9[[[[[[66639agiisssinga:<~**=;>//[}}}}}}660dnstDGLMQQQQOLCtg96[[[66366[[[[[[___]^^//>>;------;;;;;>>>//^^^^^^^^[[[60hntyCLMORSSNNNNNSSSSSSSSSRRRRRQOLExli1122kokklca3/^^^^^^//>;-=*&&*=->//^^^^//>;-***=;>/]]__[[", +"ELMOOQQQQQQQRRQQQOLECtsgdd000000ffhmuwDGGJGDysg99660999ddagjisttsinga:<~{{*-;(/[[}}}}}}}60dhnsyCJMOOOOLCtg9[[[[[[[[[[[[[[[^_^^^^/>;;-=***=-;;>>>>///^^^]]]__^_}}}60dgsyGLOQSSNNNNNNSSSSSSSSRRRRRRQOLCxlcc<1lllllba3[^^^_^^^^///>;;---;>//^^^^^//>;-==-;>/^]]__[6", +"CELLMMMMOOQQQRQQQOLECysngddddddddfhmuwDDGGGDysngdgggnnnnniistyytsngaa:~{&{~->//}}}}}}}}}00dhnwyCELMMMFAtb3((////[[[[[[[[/^^^///>;-=******=;;>>///^^^^]]]_____}}}}60dgsyEMOSNNNNNNNSSSSSSSRRRRRRRQOLExlibbbbbccbb93[[^___]^^^^^////>>>//^^^^[[[//>;;;;>>/^]]___[6", +"DGJJJJJLLOOQQQQQQOLJGDtsnngnnnnnnnmuuwyDGGGDyssnnsswttttttyxCCCxtiga:<{%%&~;(/[}}}}}}}}60fhnswyCELLMFAxl::>>>>>(((((((/////>>>;-=*&&&&**=;>///^^^^^]]_____}[[}}6600hsyCLOQSNNNNNNSSSSSSSRRRRRRQOMLECticbaaaaaa933[[[^____]]^^^^^^^///^^^[[[[[[/(>>>>>//^]]]___}6", +"yDDGGGGJLMOQQQQQOMLJGCytsssstyyywwwwwyDDGGCDyywwyyDDCDCDDCCEEEECxtcb<{)%%&~;(/}}}}}}}}800fmuBDCEJLLLFAk1<--------;:::::::;;;-==**&&&&**->>//^^^^]]]___^[[[6600000dhnyCLMORSNNNNNSSSSSRRRRRRRQOOLJGxxtijgaa99933[[[[[____________]]^^^^[[60dd063(((>//^^]]]____}6", +"wByDDDDGJLOOQQQOOMLJGCytstyDGGGGCDyyyyDDGGCDDyyDDGEEEEGGGGELLMLJCxic~))$%&=>/[}}}}}88880ehuBDGJLMMMMFAk11=========<<<<--======******=-;>//^^_________[[[09dhhhhhhnsyGLMORSSSSNSSSSSRRRRQQQOOMLECDxytttsigga993[[[[[_________________[[0dgusnnd3((///^^]]]_____}6", +"uwwBBBDDGLMOOOOMLLJEGCyttyCELLLLJEGDDDDDCCDDDDDCGJLLLJEGGEJLMMMMJCk1{)!$%{->/[}}}8888880fmwDGLLMOOOOMAok1<======<<<<<<111<<=------;;>(//^^__________[[9answtwwwwwyDGLMOQRRSSSSSSSRRQQQOOMLLECDytttyxDDxytijgd93[[[[[_______________[60hsByDysnd3(//^^]]_______}6", +"muwwBBDDGJLLMLLLJEGCDyttyCELMOOMLLJGCDDDCDDDDDGGJLLLLJEGGGJMMOOOLAk2|!!!%*;(/[}}6688880efuyGLMOQQQQOOFAkc<<::::::>>((////^__}}_______[[[9ntDCGEEEGGGJLLOOQQRRRRSRRRRQOMMLJGCDytsiiisyDGEEGCCytjga996[[[[___[[[[[[}}_}}6dmwDGJGCysg33/^^]_________}}", +"mruuwBBDDGJJJGGCCDDyysssyCJMOOOOMLJGCDDCDGGGGGGJLLLLLJGCCCELMOOOMFo|!!!!)~;([[}}68888800hsDJMOQQRRRROOFCtca3333aacitkxCCxkiba33[[[[[}}}}}}}______[[6ajxGLLMOOOMMMOOOQQQQQQRRQQQOMMFECxtsnnggagjiyCELLMLLECytsngd99[[[[[[[[66666}}}6dmwDJLLLECtg93[^^__________}}", +"hmruuwBBDDDDDDBBwwwssnnstCLMOOOOMLEGCDDCGGGGGGJJLLLLJGDyyDCLMOQOOFA77!!!&=>([[}688866660hwCLOQQRRRRRROMJCwngdddgitxCEFFFECxig966[[}}}}}}}}}}____[[3ajxEMOQQQQQQQQQQQQQQQQQQQOMMLECxtiga993399gixGFMOOOOMLJGCytjng9966[6660dddd0000fhuDJLMMLJCtg93[^^___________}", +"fhrruuwBBBBBwwuuumnnhhhnwCJMOOMMLEGCDDDCGGGGGJJJLLLJGDywttCEMOOOOIzp7!!){<((66600086}}60hyGLOQRRRRRRRROMJDysnnnswyGJLMMMLECtnd0066}}}}}}}}}}}__[[3aixEMOQRRRRRRRRRRRRQQQQOOMLLGCytjg93[[[[[3aixEMOQQQQOOMLJECytsjgd9999ddgnnnmhdfdhuyGLOOOMJDla3[^^____________}", +"fhmrruwwBBBwuummhhhhddhnsyGLLLLJECyyyyDDGGGGGJJJJJJGDyssnsyEMOOOOIzp77!)~:(360000006}66dnyJMQQRRRRRRRRQOLGDBwsswyDGLLMMLLGDsgd06666}}}}}}}}}}}}66ajtAFOQRRRRRRRRRRRRRQQQOOMLJCytjg93[[[//[3aiCFOQRRRRQQOOMLJECytsjggdggnswByBwummmuBGLMOOOLExia3[^^_____________", +"fdhmruwByyBBurmhfff000ddnsyCGGCxytssswyDGGGGGGGJJJJDywnggntCFOOOOIIpp7|21:addhhhhf00660hwCLOQQRRRRRRRRQOLJDBwwuwBDCJLLLJGDwnd006666}}}}}}}}}}}60dgtxEMORSSSRRRRRRRRRRQQQOMLJGysnd9[[////((alCMORRRRRRRQQOMMLJECysjnggnswyDCGDDBwwwBDJMOQQOLGtg33^^_________]]___", +"0fhruByDGGDDwumhd0006600dgnstssnnggnswyDGGGGGGGGGGDDwngddgtCJMOOOIIvpp721innssuurmhd00hsDJOQQRRRRRRRRRQOLJDBwuuuuwyDGEEGDwnh00066888}}}}}}}}6600gjxCFINNSSSSRRRRRRRRRQQOOMLGDynd93(/(>>::blAIRSSSSRRRRQOOMMFJECytsnnnstDCEJJJJGDDDGJMOQQQOLCta3[^^______]]]]]^^^", +"fhmuyDGJLLJGDwnhd066[[[[6699999999dgnsyDGGGDDDDDDDywuhd99aixEMOOIIIzppookyyDDDDDyysnnnsyEMQQRRRRRRRRRRQOLGDwurmmmuwyDDDDysnd000066888888888800dhntxEFINNNSSSSRRRRRRRQQQOOMLGDsgd3((:--=<>;>>(", +"yCJMQQRRQQOLGysh06[[^^^^_______[[60dnswyBBwurmmhhd006[[^/(3btCAzzzzAAzFMOORRRRRRRQOMMMMOQRRRRRRRRRRRQOMJDBumhfffdhsyCGGGCDtsnhd006686000effhmuwyDCJLMOOOOOMLLLLLMMOOOOMMLJCyib::<~{{||pzHNNSSSSSSSRRROMFAzAFEECxtsnswyCJLLMMMMMMMOQQRRRRRQOEtb3(//^^^^^//>;==-:(", +"GLOQRRRRRQOLGysh06[^^^^^_^[[[[[[600hnuuwwwumhff0066}___^//(aikooooooAEFOQRRRRRRRRRQQOOQQQRRRRRRRRRQQQOMJDBumhffdhnyCEJJJGCysndd066[[[6660fhmuwyCGJLMMOOOMFJGCCCGJJLLLLLLECxiba:<~~{||pzHNSSSSSSSSSRRQOFAAAAAEECCtssstyGEJLLLMMMMMOQQRRRRRRQMCia3(//////>;=*&*=::", +"MOQRRRRRRQMJDwnd0[[^^^^^[[3999990dhhmuuuurmhf006}}____]^//(:<1lkookkAFFORRRRSRRRRRRQQQQQRRRRRRRQRRQQQOLGDwumhdffmsyGJLLJECysgd333(//((336ddmsyCGJLMMMOMMFECxywwyyDCGGGGCxtja::<<~22ozINNSSSSSSSSSRRRQMFAooAFFFECytssyDCGJJJJLLLLLOQQRRRRRRQOFxc::((>>>;-*&%%%~>:<11222kkxEMORRRSRSSRRRRRQQQRRRRRRQQQQQQQQOLJDwumhddhnsDGJJEECxlca::::;;;;::((3aiwDELLMMOMMLLEDywsnnnstwyyyttjaa3::<<12ozIONSSSSSSSSSSSRROFAoooAFFFJExtttyDDGGGGGGGGJLMOQRRRRRRRQMAk1<::>;;=&%$@@${1k", +"QRRRRRRQOMGysg96[[[//[3btxCEECDywwuurrmmhee0}}_____]]]]^/>;--<1111llxAMORRRSSSSRRRRRRRRRRRRRQQQQQQQQQOLJDwumhfddgsyDCCDxlcc<<==~******~=<:ciDELMOOOOMMLJCywsnhdddgggggga33(:--<11kAINSSSSSSSSSSSRRRQOEoooozFMMMJCyttyyDDDDDDDDDGJLOQRRRRRRRROFAk1<:--~&%$@@@${2o", +"OQQRRRQOLCtng96[[[//(3bxELMMMLJGDywuummhe00}}____]]]]]]^/>;--=<111clkAFOQRRSRSSRRRRRRRRRRRRRQQQQQQQQOOLGDwnhdddddgistiicb<<~~*&&&%%%%&{~<;--=<1kAIORSSSSSSSSSSSRRRQMAooopzIOOMLECyyyyyyBBwwwwBBDJMQRRRRRRRRROFok1<==*&$@++@!{2o", +"MOOOOOFExig96[[[///(3btFMQQQQOMLGDBwurhee0}}_____]]]]]^//>;;--<<<;--==<1kAIORSSSSSSSSSRRSRRROFoo7pzIIOOOMJCyytyBBwwuuruuwBGLORRRRRRRRROMAk1<~*&%@@++@!{2k", +"JEEEACklba3(//^^///(3lEMQRRRRQOLJDBwrmhe0}}_____]]]]]]^//>;;::<<::bclxEMQRRRRRRRRRRQQQQQRRQQQQOOOOOOMLGysgd063[((3333((>>;---==****==-;:clCLOQQQQQOMLJCysnhd633((/(((>>;-===<1kAIORRSSSSSSSSSRRSSRROzp77pvINRQOMLEyttssuurmmmmrrwDJOQRRRRRRRROLCk11{&%$@+++@${1l", +"tttlicb::((////////(axFQRRRRRQOLJDBurme06}_____]]]]]]^^/>>::::::::bbjtAFOQRRRRRRRRQQQQQQQQQQOOMMMMLLJCysh96[[//(((((/////>>>>>>>>>>>((3alCLOQQQQQOMLJCysnhd66[///(((>;-=~~~11kAIORRRSSSSSSRSSRSSSSRIzpppvHNNRQQMLCyssnnnmhheeehmrBGMQRRRRRRRQMJCk1{)!@+++.++${1c", +"icga::::>>(////////(axMQRRRRRQOLGDwumhe0}}_____]]]]]]^//>:::bbbb:::bblxEMOQRRRRRQQQOOQQQQQOOMLLJGGCCxtia93[///(((///////////^^^^^^^^/[9iCLOQQQQQOMLEDBsmd06[[///((((:-=~~~1koFOQRRRSSSSSSSSSSSSSSSSIzppvHHNRRQOMFCtjgdddffeeeeeehuDLOQRRRRRQOLGk22)@++....++$)~<", +"caa:((>>>(//^^^^^^/[gxMQRRRRRQOLGBwrmee6}_____]]]]]]^^/>::ccllccb:::bclCFOQQRRRQQQOOOOOOOOMLJGCyttsijga3[/////((///^^^^^^^^^__]]]__^[9nyJMOQQQQOMLGDwnh006[[[//((((::<1122oAIORRSSSSSSSSSSSSSSSSSSSNHvvvHNSRRQOMExjg990000088880fmyJOQRRRRQOLCy12)@+.......+$)~<", +"ica3((((//^^^^^^^^^[gyMQRRRRRQMJDBurme86}______]]]]]^/(>:clkkklc<<:::bixEMOQQRQQQOMMMMMMMLJGDtiggdd9933//////>>///^^_______________[6gtGLOQQQOOLJCysg006[[[[[/((3abc112oozIIRSSSSSSSSSSSSSSSSSSSSSNNHHHHNNSRRQOLCtg96[[[}}}}}}660hBGMOQQQOMJDtc1)@+.......++${11", +"tiga3(///^^^]]]]__[6gyLOQRRRQOLJDwumhe06}______]]]]]^/>::1kzIIIzo22{{~=<:clALOOOOMLGxtttsssng96[[[[_^^_^^^^^^^///^^_________________[9jyELMMLJGysd0[[____^^^[[33blxAFIQNSSSSSSSSSSSSSSSSSSSSSSSSSSSSQNNNNSSSRRQOFxj9[[^^^^^_______}0hsyCCDtna::;-=*&$@@++@@$){2oFM", +"MExta93[[[[[[[___}}6fnyGLMOMLJDBwurmee06}}______]]^//:<2ozIIIzoo|)){~<:bjxEMMMMLEytjngggd90[[[___________]^^^^^^^_____________]__[6gtCELLLEDwnd6[_____^^^[[33blxFMORSSSSSSSSSSSSSSSSSSSSSSSSSSSSRRONNNSSSSRRQMEta3[^^^^^^^^]]]___[0gsssiga::;;;;-=*&%$$$%&~2oFIO", +"MFCtb93[[[[[[[}}}}}6fhuDJJLJGDBBurmmhe06}}______]^^/>:1ozIIHHIp7|)){~-::blxEFLECxtja999066[[[_____________]^^^^^]___________]]]__[9jyCEJJGDwnd6[^^^^^^^^^[33ajxAMORSSSSSSSSSSSSSSSSSSSSSSSSSSSSRROOOQSSSSRRRQMCl9[^^^//////^^^]]_[[9daaa::;;;>>>>>;-**&&&~1kAIOQ", +"MECla3[[[[[[[[[}}}}60hrBDGGGDBwurrmhe006}}}}____^^/>:<2oIHNNHHv77!){~-((3aixCCCtjg99666[[[}}}}}}__________]^^^^]]__________]]]]_[3gtCEEEGCynd0[^^^^^^^^^[339blCFORSSSSSSSSSSSSSSSSSSSSSSSSSSSSSROOOORRSSRRRQOFxj3[^^//>>>>>//^^^^^/[3(::---;>>/////>;=**~=1kFOOQ", +"FEtja3[[[[[[6666}}600fmuBDDBBwurrmhee0066}}}}___^//>:1kzINNNNHv47!){=;(((3ajlttja96[[[[[}}}}}}}6}[}_______^^^^^^]_________]]]]__[9jxEJJJCDsg96[/////////[33ajxEORRSSSSSSSSSSSSSSSSSSSSSSSSSSSSRQOOMOQRRRRRRQMEta[[^^/>;;--;>>//////>;;-==~=;>/^^^^//>-=*~~1oFOOO", +"Axja3[[[[[66666666600emruwwuurrmmeee0066666}}__^^/(>:lAINNNNNHvv7!{~->//^[39aga99[[[}_[_[_}[6660666[[____^^^^^^^]]]_______]]]__[9jyEJLJECyia3(((>>>>(//((3abtAMQRSSSSSSSSSSSSSSSSSSSSSSSSSSSSRRQOOOOQRRRRRQMJxj9[^^//>;=**=-;>>>>>;-=*****-;>/^]]]^/>-***~2AFIOO", +"tja3[[[[[399900666000ehmruurrmmheee006666666}}_^^//(bkFNNSNNNPHv7){=>//^^[[[366[[[[_____[[[660ddd906[[[^^^^^^^^^^]]_______]]__[3gtEJLLLExtja::-====-;>((3ablCFORRSSSSSSSSSSSSSSSSSSSSSSSSSSSSRRQOOOOQQRRQQOLxj9[[_^^/>-=***=-;>>;-**&&&**=;>/^]]]]^/>-*&{{2ozFFF", +"ba3[/^[[[9dddd000000eehmrrrrmmheee0066666666}}_^^//3cCMRSSSNNPHv7){->/^^^^[[[[[[[_______[[69ddnnngd0[[[[//////^^^^]___________[atCFLMLJCxic<<~{{&{{~=<::bckAFORRSSSSSSSSSSSSSSSSSSSSSSSSSSSSRRRQQOOOOQQQOMLCsa6[__^^/>;=***-;;;;-**&&&&*=->/^]]]]]^/>=*&&{|oAAAA", +":(////[[9dgggdd0000eeemrrurrmmeee8088666686}}___^/(alFORSSSNNPHv7)~;(/^^____[__________[[[69gnsssng96[[////////^^^^^^^^______[9jxEFLLJCxlc11{)!!!!)){~11koAIORSSSSSSSSSSSSSSSSSSSSSSSSSSSSSRRRRQQOOOOOOOMJCtg9[[___]^/>;---;;;;-=*&&&&**-;>/^]]]]]^/>=&%%)||ookk", +";;>>///39dggghd0000eehruuuuurheee0006666866}}___^/3bxFORSSSSNPKv7|~:(/^^______________[[[39gjsttssga3[(/////////^^^^^[[[____[[alxEEFECkl12{)!!!+'+!!!||ozIINSSSSSSSSSSSSSSSSSSSSSSSSSSSSSRRRRRRQQQOMMLLLEDsg9[____]]]^//>>>>>>;-**&&&**-;>/^]]]]]]^/;*&%$))||221", +"*~=;>(/3dhhhhdf000eeemuwBBBwrmfee8000666066}}__^^[9lAORSSSSSNPKv72<((/[[____________[[[[39ajjstttsga33(((>>>(////^^^[[[[[___[[ajtxCxxkl22{)!!++''''''4pvHPPNNSSSSSSSSSSSSSSSSSSSSSSSSRRRRRRRRRRQQQOLLEGCyjg6[____]]_]^^/////(>;-*&&&**-;>/^]]]]]]]^>-*%$$@!)){{{", +"$%&~;>(6dhhhdfe000eemrwBDDDBumhffee80800006}}__^[3bxFORSSSSSNPHvo2<33[[[[[_^_______^[[[399gjtttttiga33((>>>>>(////^[333[[[__[[9ajiiic11{{)!!!+''''',45qKKPPPNSSSSSSSSSSSSSSSSSSSSSSRRRRRRRRRRRRRQOMLGDysn96[[___]]]__^^[[3993(:=*&&**-;>//^]]]]]]^/>=&$@@@@$))$$", +"@@%&=>(0fffffe0088eemuBDGGDywuhhfeeee800806}}_[[3alAORRSSSSSNNHzolba36[[[[[^^^___^^[[[339aajjtttija93((>:>>>>>(///[33993[[^^^[[33a3:<~{{%)$!@+++'',5qqKKKPPPNSSSSSSSSSSSSSSSSSSSSSRRRRRRRRRRRRRRQOLEDwnd9[[___]]]____[[9gistib:=*&&*=;>>/^]]]__]]^/-&$@+++@@@@@@", +"+@$&=(30fffee8008eemrBDGJJGDwrhffeeeee80806}}[[39jxFORSSSSSSSNHzolca9996[[[^^^^^^^^[[3333aabjjijjba3(::::;;>>>>(/(3aaaa3[[^^^^//(((;-~{&%%$$@++'',5qqKKKKPPPSSSSSSSSSSSSSSSSSSSSSRRRRQQQRRRRRRRRQOLGynd9[[___]]]____[9gsxGEEClc<~**=-;>/^^]]___]^/>*%@++++++++++", +"+@$&;(600eee80888eemuBGJJJGDwnhdfeeee88008}}}[[3bxFORSSSSSSSSNIFAkiggd996[[^^//^^^^^//(3333aaaabaa:::---;;::>>>>((abjjja3[^^^^^//>>-=*&&&%%$@++',5qqKKKKPPPPSSSSSSSSSSSSSSSSSSSSRRRRQQQQRRRRRRRRQOJCsg9[[[___]_____69nyELMMLJxl1~~=-;>//^^]___]]^>=&@++.....++..", +"+@%~:(6608e88888eehrwDGJJJCyshdf0000008086}}}[3alAORRSSSSSSSSROFAxljgg996[[///////^////(((33333:::<=~~~==-;;;;:::aclxtlb93//////(>;-=**&&%%$@@',5qqKKKKPPPPSSSSSSSSSSSSSSSSSSSSRRRRQOOOQRRRRRRRRQMJDsd9[[^_______}6dsDJMOOOOLCk11=-;>//^^]____]^/;&$++..........", +"@$&;([668888888eeemuBDGJJGDwnd00000000686}}}[[3jxFQRSSSSRSRRRROFAxtjgd96[[[//>>>//////((((((((:;=~{&&{{~~<<<<-::>;-=**&&%%$!!45qqKKKKPPPPSSSSSSSSSSSSSSSSSSSSRRRRQOOOQQRRRRRRRRQMEysg9[[[______[6dsDJMOQQQOLGlc<-;>(/^^^_____]^>=%@+...........", +"$&=>/[68888888eeehmuBDGJGDysh0066}}}}}}}}}}}[6atEORSSSSSSRRRRROLCyigd96[[[//>---;>>>>>>;;;;;;;-~&%$$$$){~11<<<11koAFFFAxia3(((((>>;-=~*&&%)!!45qKKKKPPPPPSSSSSSSSSSSSSSSSSSSSRRRRQOOOOQRRRRRRRRRQMJDwnd0[[[[_[[60gwCJMOQQQOMJxib::>(//^^______^/;&$+............", +"&*;/[}6888888eeeehruBDGGDysh066}}}}}}}}}}__[[3jCMQRRSSSRRRRRRROFCtja96[[[^/>-*&**-;;;;-======*&%$@@++@!)|222222oAIIOOOFAtib:((((((>;-=~{{))74vKKKKKPPPPSSSSSSSSSSSSSSSSSSSSSRRRRQOMMOQRRRRRRRRRRQMLGywnh906660dgsyGLMOOQQOMLCtga(((///^^_____^^>=%@+..........++", +"=;(/}}88888eeeeehmrwBDDDysnd06}}}}}}}}}}___[[atFORRSRSRRRRRRROMExia96[[[^^/>*&%%&&*===**&&&&&%%@@+++++!77ooooopzHNNRROOFClcb:33((((>;=~{{|7vvKKKKPPPPPSSSSSSSSSSSSSSSSSSSSSSRRRQMLLMOQRRRRRRRRRRQOMLECywsnggnswDGLMOOQQOOMLGynd3((///[^______^/;&$+.........+++@", +";(/[}68888eeeeeemmuwyDDysnd06}}}____}}_____[3jCMQRRRSRRRRRRRQOJCtg93[[[__^/-&%$$$%&&&&&%%$$$$$@+++..+''7pppppzHHNNSSRROFAklca333[//(:-~2|pvHKKKKPPPPPSSSSSSSSSSSSSSSSSSSSRRRRQQMLLLOQRRRRRRRRRRRQQOMLLJGCDyyDGJLMOOQQQOOMLGynd6[/////[[_}___^/>*%@+....++++++@@$", +"(/[[60888eeeeehhmruwyyBsnh06[}_____}}}}___[[9tEORRRRRRRRRRQQOLExia3[[[__^^>=&$@@@$%%%%$@@@@@@+++....''4vvzzzvHHNNSSSSROMExlcaa36[[((:<2|pvKKKPPPPPPPSSSSSSSSSSSSSSSSSSSSSRRRRQOLJJLOQRRRRSSRRRRRRQQQQOOMLLLLLMOQQQQQQOOLJCBnd6[//////[}}____^/-&@+...++@@@@$$$%&", +"/[660eeeeeehhmmmmruwwwsnh066}_____}}}}}}__[3gxMQRRRRRRRRQQQOMJDib3[[[[^_^/>*%$@@@@$$$$@+++++++......'44vvIIHHHPNSSSSSRQMFxlca96[[[((:1opvKKKKPPPPPSSSSSSSSSSSSSSSSSSSSSSRRRRQOLJJJMORRRRRSSRRRRRRRRRQQQQQQQQQQQRRRQQQOLJDwnd6[^^//////[}___^/>*%@+.+++!))%%%&&*=", +"30dhhhfeefhmmmmmmussssnhd06}}____}}}66}}}[[9tEMQRRRRRRRQOOMMJCtja3[[^^_^^/>*%$@@@@@$@@++...........''4vvIIIHHNNNSSSSSROMAxia93[[[[(3ckpHKKKKPPPPPSSSSSSSSSSSSSSSSSSSSSSRRRRRQOLJGJMQRRRRRSSRRRRRRRRRRRRRRRRRRRRRRRQQOLJDwnd0[[^//>>>///___^^>=&@+++''!||{~***~=;", +"gnsssurmmmmmrrrmnnnsnngd06}}____}}}60006669jxLQRRRRRRRQOOMLJGDsb3(/^^^_^^/;*&$@@@@@@+++...........+'7pzIIIIIHNNSSSSSRROFCtca3[[[[[3bkzHPKKKPPPPPSSSSSSSSSSSSSSSSSSSSSSSRRRRRQMLGGJLORRRSSSRRRRRRRRRRRRRRRRRRRRRRRRQQMJDBuh0}_^^/>;;;;(//^^^/;*$@++''47po21~~~=-:", +"wyCCDDywuuuruurnnnnghd066}}}___}}}60df0069gtEOQRRRRRRQOMLLJJCxia3(/^^^^^^/>~&$@@@@+++............+'77pzIIIIIHNNSSSSRRQMExia3[[[[[[alAIHPPPPPPPPSSSSSSSSSSSSSSSSSSSSSSSSRRRRQOMJGCGLMQRRSSSSSSRRRRRRRRRRRRRRRRRRRRQQOLGBuhf6}_^^>;****->>//>;*%@@+''4vpzok1<==-::", +"CJLLLJDywuuuurnhhddd0066}}____}}}600dddd0djCMQRRRRRRQQMLLLJECyia3(/^^^^^//>=&$@@++++.... ....''77ozFFFFIIINSSSSRRQOLClg9[[^^^[3bxFNPPPPPPPSSSSSSSSSSSSSSSSSSSSSSSSSRRRRRQOLJCDDEMORRSSSSSRRRRRRRRRRRRRRRRRRRRQQOLGDwrh0}}_^/;*&%$%&**==*&%@@++'4vvIIAkl<<<<::", +"JLMMMLGDwsunnhhdd0066[}}______}}}600dddddnyJOQRRRRRRQOMLLJJGCtib((//^^^[[(:=&$@@+++.... ###''77zzFMMFFIINNSSSSRRQMEyja3[^^_^[9lFINNNPPNSSSSSSSSSSSSSSSSSSSSSSSSSSRRRRRRQOLGDyyxGFORSSSSSSSRRRSRRRRRRRRRRRRRQQOMJDBumf0}_^/>=&$@++@@$%%$@@@+@@7pzIIIAkl1<<:::", +"JLMMLLGysnnhdd00666[}}________}}}}6000ddntEMQRRRRRRQOMLLJJJGCtc<:>(///[33a:<{$@+++.... ###'44pzFMMMMMFIIRSSSSRRROLCtg33/^^_^[axMRSSSNSSSSSSSSSSSSSSSSSSSSSSSSSSSSRRRRRRQOLGysiitCFIRSSSSSRRRRSSSRSSSRRRRRRQQOLJGDwume0}[//;*%@+....+++++++@@)|ozIIFAkc<<-:::", +"CELLJGDtngd00666}}______________}}}6600hsCLORRRRRRRQMLLJJJGCxic<-;>//33bjll2|)!++.... ##,,5vvIIIOOMMMMOORSSSRRRQOLCtb33[[^^[3jAORSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSRRRRRQOLCyigbclkAFIQSSSRSRSSSSSSSSRRRRRQOMLJGDBwumf0}[/>-&@+...........+@${2oAFFAkcb:::>(3", +"txCCCysnd9666[}}__________________}}}60gtEMQRRRRRRQOMLJEEGCDtic<=->/(3btCAAAo7!''.# ##,,55vHHNOOOOOOMOORRSSSSRRQOLCtja33[[[3axMQRSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSRRRRRQOLCwna:<122opzIIQRRSSSSSSSSSRRRQQMLGDDDBBBurhf6[(>=%@+... ....+@%~>(/(", +"gjsssjnd9666}}}}___________________}}6dsCMQRRRRRRQOMLJGGGCDysc<<=->(3atAMMOIzp7'''#######,55qKPNNRRQOOOOOOORRSSSRRRQOMExlcba339jtEORSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSRRRRQOJDsb::=~{{)||opzIORSSSSSSSRRRQOLGDyyBBBBBwumd63(:~%@+... ....@%=:bbbba:(>>>////", +"9ggnnngdd9666}}}}__________________}}6dtJOQRRRRRQQOLJGGCDDyysg:<-;>(3jCLOQQOIIp44'#####,,5qqKPNNSRRQQOOOOOQRRRRRRRRQOLExkklcbjtxEMQRSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSRRRQMJyia::=*&%))))||ozIQSSSSSSRRQMJCtsuuwBBBBBund03(:=&$+... ...+%=:(((((>>>>//^^^", +"9dhgnnnnngd00066}}}}__}}}}}}}}}_}}}}60nCLQRRRRRQQOLJGGCDDDywsg::;:((atEMQQRROIzp74'',,,5qqKKPPSSSRRQQOMMOQQRRRRRRRQOMFAoookkkxCFMQRRSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSRQOJCsb:(;=*&%%$$)){2koFIRSSSRRQMFxsnhhnuwBBBBsnhd93:-~%$+... ...+$*;>>>>;;>>//^^^^", +"0dhnswyyyysnhff0066}}}66006}}}}}}}}}0dwEMQRRRRQQOMLGGDDDDDyytna::>(3atJOQRRQQOMzpp7445qqKKKPNSSSSRRQOMMMOQQRRRRRRRQOLEAoo7oooAFMOQRRSSSSSSSSSSNNNNNNSSSSSSSSSSSSSSNNNNNNNOMJxib3((>-=*&%%%%{~~1loFIRRRRQOMExjgddhhuwwBwsngdda3:<~%$+.. ...+@&=;;;--;;>/^^__[", +"hhnsBDGJJGGDwumhee00fffffee00686}660dnyLOQRRRQQOMJGDDDyyyDDyyib:(((3bxJMQQQQQOMFFAzpvvKKPPNSSSSSSRRQOMMMOQQRRRRRQQMLGxko777ooEMOQRRSSSNNPPPPPKKKKKKPPNNNNNHHIIIIHHHPKKKHIAxlba3(((>;-=~***~=-::ixFIQRRRRQMLCtjgddhgnsssssngggga:<~%@+.. ..+@%&*====-;>^^]_[[", +"gnuwDGLMMMLJDBurmhhmmuuuurmhfe000000hsCLOQQQQQOLJGDByBByBDDCDtia:((3bxEMOQQQOOMMLLLMINNNSSSSSSSSSRRQOMMMOQQRRRRQQMJCyl2|!!77oALOQRRNNPKKKKKqqqqqqqqvvvppppo||||||77444447|1<(((/(>>>>;;;;::::actAMQRSSRRRQOMEyjgddddnnssssssssig:<)@+. ...+@%&&&&*=;/^^_[[[", +"gnswDJMOOOOLJDBwuuuwBDDDDBwumhff00fhnyELOQQQOMLJDBwwuuuwBDCGGDlc:((3btEMOOOOOOOOOOOORRSSSSSSSSSSSRRQOMMMOQQRRRRQOLCyic1)!!!)|oFOOQNKqqqqqq5555,,,,,'!!)))))){{{{))!!'''+@){=;>>>>>>((((3333dgsyEMQRSSSSSRRRQMExjgd9ddgnnsstyyytic1)@.. ....+@$$%%%&=>/^^^[[9", +"hhnsDJMOQQOMLJDDBBDDGJJJJGDBumhhfdhnsDJMOOOOMLGDBwurrrruwDGEECkc::(3btEMMOOOMMOOOQQQRRRSSSSSSSSSRRRRQOMMOQQRRRQQMJysa:~)@@@!|kEOOHqq555,,,,,######.++@$%%%%%%%%&%%$@+++++@%*=;>>>>((3abgggnnyCJOQRSSSSSSSSRRQMEtja999dgnswyDCDxsc2!+. ....++@$$$%&*;/^^^[69", +"ddgsDJMQQQQOMJGDDDGJLMMMMJGDBsmhhhhnwCJMOOOMLGDBurmmhhmmuyGJJGkc<:::bxELMMMMMMOOQQQQRRRRSSSSSSSSRRRRQOMMOQQRRQQOLGwn9:{$@++@)2AINKq5,,######### ..+@$$$%%%%%&&&%%$@+++@@%*=-;>>>(:bitttwwyGLOQRRSSSSSSSSRRROLxtg999ddnswDCGCDt1)!. ....++@@@$$&*;/^^[[69"}; diff --git a/hacks/images/toast.xpm b/hacks/images/toast.xpm new file mode 100644 index 00000000..39e51136 --- /dev/null +++ b/hacks/images/toast.xpm @@ -0,0 +1,222 @@ +/* XPM */ +static char * toast_xpm[] = { +"128 128 91 1", +" c None", +". c #744933", +"+ c #A87B45", +"@ c #AF8856", +"# c #C9AB78", +"$ c #DCCB86", +"% c #EADA98", +"& c #90673B", +"* c #F5EAB1", +"= c #D4B777", +"- c #AC7443", +"; c #C8A463", +"> c #EDDE9C", +", c #E4D38F", +"' c #9F6A3D", +") c #D8BE80", +"! c #C09C6A", +"~ c #B27B46", +"{ c #EEE2A1", +"] c #825538", +"^ c #A37649", +"/ c #A26F40", +"( c #EBD493", +"_ c #BC9668", +": c #E7C58D", +"< c #8B5E33", +"[ c #997246", +"} c #D9C383", +"| c #F3E5B3", +"1 c #E4CC87", +"2 c #BF8155", +"3 c #9E6F4B", +"4 c #916745", +"5 c #BB8A5B", +"6 c #F3E3A1", +"7 c #8B5D3F", +"8 c #F2DAA6", +"9 c #BA7F54", +"0 c #FEF6C6", +"a c #E4CA93", +"b c #AB7250", +"c c #DFC488", +"d c #E5D299", +"e c #B17B53", +"f c #E6DAA1", +"g c #FBEFC1", +"h c #EADEA6", +"i c #EECD98", +"j c #976243", +"k c #EBD29E", +"l c #986E48", +"m c #F0DEA7", +"n c #E4CE96", +"o c #DFB980", +"p c #A46E4B", +"q c #D1AF6F", +"r c #B08256", +"s c #F3E2AB", +"t c #97663C", +"u c #FEEEB8", +"v c #8F6240", +"w c #BA9263", +"x c #986645", +"y c #ECDAA3", +"z c #F3E6AB", +"A c #ECD6A0", +"B c #E5D69C", +"C c #D7B982", +"D c #EEE3AA", +"E c #A77D56", +"F c #F8EDBA", +"G c #A5724C", +"H c #CFAA7A", +"I c #EACE9A", +"J c #9F6A47", +"K c #E0C590", +"L c #B2926B", +"M c #AE7650", +"N c #E2BE85", +"O c #DAC48D", +"P c #FAECB3", +"Q c #FAE6B5", +"R c #986B3B", +"S c #B67D54", +"T c #DECB91", +"U c #925E42", +"V c #C7A473", +"W c #D3B17C", +"X c #DBBE89", +"Y c #996A46", +"Z c #AE8A62", +"5SeMbGpppppppppbGGGGpppppp3JJYxx44&v&vvvvvvv&v&44vj&tRRRx''3''J''''''/ppppGGpGGGMGMM~M~e~~SSS2r92S2299292225555522222S9SSSSMeSe2", +"2SMMbp333JJJJJppppppp/pppJxJxxxxvvvvvv<<<<ykKKX:oWWXcHc=c))=)}=q;c;=qH##q##;!;!_w55@~+-+-+~--~~-~9MSMS9SSSS2SSMeS", +"S~bbbbjpJxJxJxJYYY3'Yl33/^Er@Z!L!!w!VWWCnBKkIkkIAnaacn}mAnm8qcCInaK)=IKKan)d}O}K)Kcn1}=1)a)=Cq=#V!_5@++--++--~---M9SS9SSSSSS9SS9", +"SSSMbbpJxJxJxxtxx'JY3J3/^+@_!V!#VWCq#XkXaakkBInsymmmmmIysk(dc8ck=IIa:8:a}nCnAnATTkydInAdTyAaKKKKCW;;w_~+-/-+/--~MMMSMS2MSMMSMSe9", +"9~M9bpppJpJJtxxt'Y3J3J3E+5_!V=WCCW#XWqCKKCakyTaknyByknamk}8AAnk8=A8Kaaacynk}}}CaOAknAm8A|dTOAdAaKaXXW;_wr---/----MMbSSSMSSSMSMSS", +"229M-bbpG3YJjx'xx'Jl33^r5!#WWWa:aXNWXiXIkCAKTOymAmQmTnTQT8K8n:sCAkKaacoAQOnkTnOnTddBddPm*{hzsdA|mIIkC);;5++-/^---bMMMS2MMMSMSMMS", +"29M~MbpJJpYtRjjttYYJG^E@!W=CWCICcaCcX:C8OIk8O8kQdmOAdymndmkOIC:Wmim:AO8Kc)=anAAycyddBdDdfs%fd|BmmnOAIc=;!5++^/^^----SbMSSMM9bSMS", +"22S2Mbp'pY'R4txx&4JY/~5!qWHKK:IXakAK8kKiXAK|CDOmTDdsmT|nmaKIyKci:k8dIIKykTK)d=BkAkAmnfBDfshshhsmTfmya1c);wr/^/-//--MMMMSSMMMMMMM", +"2S9S-bb'JYxt&vjjRRlGEZ5HqCNCK:IXcaa)aC)anAkOkBQnknhATFkkmKaaaKIKoKXOAAKXXdTIk=ndOaaBdhydfDsBDmhf*snByIacX;w~+/+///^-eMMbbMMbMM~M", +"2S99MbpJ'JY&v4vv4t[r@_qCXCX:KciIAAannnAskdsAmXOOfABOmnB=k=OIOq8q8Kk=IOn8aXKTBOsdydmAyh|BDfhODBhhB,|BA%s1Xq_w++^^/GG-pbbMMbbMbMMM", +"222S-bbJxxv4vvvjxpE@__HCiXI:KCicc)nAsdcO=IIT8sFI|An;TOCdyTOanaCiCCXTKdTKXCannTXnOAdyaBsAfh*DDBfffDhDhBhBc}#!@++^//^+bbbbMbbMbMMM", +"2229b-p/xx4v4vvvl^@5!=o:KKoKic8oaqIc:k:annamBOmOOOnIhXnAOaOkKXIOcKXKnkn8OITKaOh}kd8kTynT|ddmQdmdfnBhdhymn==q!w~+^^^MpbbbMbbMbbMM", +"2999Mb''tjvvv7vj3^Z!H;WNNIiINIn=AckaInkkkd8KykAdAO=aOXfnkXCQKCCXI#XkaTOknX)OIOk)A)daCAAafyDhABmdDmfhy*DdT}c}q_@~^bpbppbbbMMbbbbM", +"29M9Mb'jj4v7777UYE@;;oo:Cqaaa)ii8NiNi::iKAAkafC8|XnOfIO=nOTanCHK;inXKaAdkTAATOd=sd8dsKknA=TkyABmdBDm|BBh1}1=X!wS+GGppbpbbbbbbbMb", +"S9SMMb/xj4vvv7vvxEr!;HoNK:cIa(8(i8kaiW:iackCIIOWBCkWaCCXnCKX8c:qKkCTnmmTAXkOAkyyCaAnAKknmABdB8TkdysBsBdOnna}cHV@e/G-pbbbbbbMbbGM", +"99SeMp''4vv7v774vEwVHHo:Niak(1()}((=8cooiIckaK8CIkIOAndVX#K:cCaXaWnddhXC8AOOdnO8mdKAkKaaaTnn8nhOTmBfAmdnKdacKC__@^GppbMbbbbbbbbp", +"9SSMbpxx4777<7>(}86%6d}BT|Tyn}zz6O>Ana:c!wrE3xYxYJxJpJJppb", +"9eSMbb3pYJJxJYJJJJpb22;;qNNIdcdOIkydCaaAACOCmmBD0nd,,{{BBmOhDFO|d|||dTDTBDDfFBFh*hQ8%6}PA%n1a8mQd$A6BBm6d,NCoWLE^Y4jjYxxJJJJppbb", +"9eeMGb3plJ3xJY33/3pp~5;qNqo1>cBc%Kn}yAdInK=|mhyD|g%h66,6OmnBQhD|||TdBDhfgTDfBDgDh*z6%%((((($,1)mmAy}>$Oy>d)c;!r3lxY4UjxxJjJJpbbb", +"eMebb^p3plJ3J3J3R3GGS2;oNokakdkBcannnTI8|d|dBBh*yP$>,,>{%nQdQdfhh|T*DsD}FDDFm|zhgP{(6%6zm(%PksdsnfdODz6mm8:o_w3Y47vUjvjjjJpjJpJp", +"Se+MGppJJJxpxJJp/Gp^@5H;qNK}A$}nAkynk}TAm=nf||dD*Fz{P>%(%{hzf>DzBmB*z,>{>>BDmymffBzz6P%m)}c8}AdammB,gFm(m(=W!@^j4vv7vv4jxJJJpppp", +"SeMG^bpppJJJJJppGGGe2wWHI}BATmmOnmaKdK8kDddmyh$D,z*{*>(%$B%>zzm>BB,6${{>$*szs|*s,zh6z(1}(86(=,(m11>F*0(1)A:WVEJUUv777v74xjJxJJpp", +"eeeb^bppppJJJJ3J/G^r@!;;iaKdykkdnaKTdTTann|n)*F{,f{%{%>%%zP6,>%,$>%>>}%>6z>*zs|sdF|g*zz>z>m%8%6(,u=*$,6(,m=q_rxj77777vUvxxYxJppb", +"eee+MbpppJ'JJJ'p'^~@wWWXcCdKdfkkKdkkIIIyBh|zfBDz|hP>P%%*66>1%>}nm%%,%%B%*hz|*D|hFz**Fz(mz}1(%11yQ|*Dz$d,AnkWVE37777777vv4jxxJJpJ", +"9eMM^GpbpJJJpppp--~@!oWKiCTakdCOIOOOnTAkdsyh{FhFuB%$>*s>,1{%6%,y{O1)%z,{z>z|P*D**BF*DFBPmP16s%s1}ssmd1AAcIKCVEpjU7777777vjYxJJpb", +"eeM^MppJJpppJJp//+5wHoooKIIBdd8dKTAITaKddB**h{u*zz*B*,>>z6Q1I>y>$%%,Q6>>*hFz**|*FfDhF*{QAPAQmQ)B1m86ym1AOnKXVZEl4v7U7]77vUxxJJpp", +"eeeM^ppppJxJpJpp^+@_WWCCKkyXddnOAKKQCdaOOzBz{{{*}m{B*$DPzz6*(66h**(,16>f*hzFzFzhF**FDzh6AuTsmfdyA1a61$m}skOCV_E[4v<7<777vjxxJJpG", +"9eMM+bppJJJJJp3'-rw;#WKaaKKdOkTdkTBOOTnT,>z,*{zPP066***z{6{${zz6z>(6>*6***zzg*DD,fh*F>Ps>PF$>sBym(61(m8)Aa8CCWLZEl777777UUxxxJpb", +"eeMbbppp3'JJYJG^-2!;WiCakIn8kKaka:Kak)kdyT6{{*,66*{>%{z{*>z{6*{P*{,6P6{>z{***h*zFfDFf{ynP>sz$zyQy1%8%81y1QkkOC!!rEJ777]&7vjjJpJp", +"SMMMGbpp'JYYJ3[^-5_HCWICanIaCCIN8KKnOITA$>666>P6666>>*h*F*{{{*>{z%*6>{>B{$*,*f*D*{z{FBP%{,sy>s%,(P%Q81n1n(ysOOWHw@E[&<<77jjxJJpb", +"MMMbppJJYJJlpG+E@VVCXCXAakaa:aIXKakKOykd,,%*61(666>$hzz>hz>*{>Dz{6,{>%>{z*{{F{,$*{}>>BPKh6P%ss*,m16%{z%dAm6$n8CVVwrE[&$,>6%6z>h{*{B$**h{z*$6z%%hs{*{{D*>f,{>F%zs,zQ>,sAszy%>(B,>z$1y,|mT)C!HLE[&v7UvjxJJGG", +"eMbbJp3xx'xYY+@_!WoCOKkaIkTXKK8WKaaXnAA8AP88*1,$6>%>6{F***F*,{zszns>%>A*{z{>z{,{*6,(>Q%%s$%BsPzudP(%B6z,%>(>myIkNW!Z^<<7vvjx'JGb", +"SMbbppJ'xxJJGEw!VCCXITIOOOXaXN:kkXk}ncdk>1,6>%((P6%>*Fzf{f{{*{{{m%QAmm6%$f*{s,z$z6*$,,msm,,sPmA,*sz>},%%(1%%(1=C=C_Z[&v7Ujxxx'b^", +"SMbbpppJxJYY^r_VCXCXa}AnaAkICK::aakIanycz61%6>>66**>6>*fz{{f%fD{,>>6n>,%*>,z}>>f%$>,6%=(6>fAn{%uhz>%1((1:(%,(=8:WV!@[v<(*$(>>>{{z{>*>*z{z>%%>((n,(66(6(>P>P{>6>6>,%A>y$zfsdyDFzQ161:,(1((ioWHH!Z^v<7vvjYJpGM", +"MMMbppJxYxxlEZVCXakXdkkyakKkakaand8TkK888(1%%>%(>%>%%z{zzz{zz>%({z%%*6%*%%81$>f$,%>1%>,(%66B${*s{z6((6(6(118i:ioXWVr[vUUvvjxJpGM", +"SMbppJJJJxYxE5!W=aAkkTndyTnOkAoIckka(aaAA>18>>6,%*{>%6>zzz6>>%66z>z%6,%68186(>>{,6%,>>A,(6>>P6%{%s6Q(i((%(c()cAHNHH@GvUUv44xJJpM", +"MMbpJpJxYxJYELVXKTKnBd8kkkdTaak:Kaaaac,m8z1m>(66>6%*zz*Pzz{{6*P6{>P666((>,>6%s%,%*6>}>P{(,m%6{Bzz(m1(((661>{%mcC1q_5^4v7U4YxJpbM", +"9~bbpJJJYYxJELVWTITkdnfdsmAnanKKa:cyAzAys{>(,66,%{,*z{{>z*,{6>{6>*66%>6{6>6z6P6}%(%(,(,,(I61,%6P>66>>%6((,*$,==k:WW_E4U7vv4xJpGM", +"SMbbJpJxxYjJ+@VWdnOTTkdBdnyykykKaa))dBzdzh,z*%*zzzP**{z>,*P*u{zz{z>666666>6%>,}%>>((%,%8%%1m($%>8(,>>6%u%P*6,$,naWVwE47]vj4xJJbM", +"SbbbpJJJJYj3^w#XayBndyhhBnAnda%cnay%Ads{fh*D,**z*{$>*{z>z{*{>z*zFz*{**>%z>*>6{*>c(6%(%1>c8%,,(%>>(66>Pz%>P,$,%dkoNHLZ[U]v4YxxpbM", +"SMbbJJJxJYj3EL!XndnfmydmfAAsO8}8c)A}andB{fD*,Dfz*z{F*{{F***z*0D0{Df%{PzPPzP>>>(6P>6}>c6$(>i(%%1>%%*P0>{%{%,0BBOAcWVVE[v7Uv4YJJbM", +"SMbbpJJJxxjJEwVXTddyhfDhyddm,amkByd$dnydhBD,*,{00*{D,D$F0gDhFF{*gg*0D*6{zg$$s>61P>6%>$%6%(1>(1>,{z6{z,zzf{*BmOT#:oH!E4U7v4YxJpGM", +"M~bbbJJJYYxGr_VWa}yymyymyyAmy$,B$fs,}By,d$d$*F$fzzf*zDfD*{*F0{DF*0DhDgD|Fz{BD{d>%(,>6a(K111((%u*F*0F0{{{$0z}ycc:CHV!Z377UUjxJpGM", +"~~-bpJJJJxj3@!WaIdm%f%sd8AAyB,B6z>{,sdAdThfThhzhh${*,fBfDB*hFh**fgf|DPDf*fDPBz}11(dAOmKmyyA}1%%%*Fz**fF${)*,TkKCaWoLrxj]vvvt'p^M", +"S--'pp'xJJxpr!q)I(%%%zs>A>(%Qz6{6zzf%,%mydBdyhBzF,hTf{Bhhh*DDDDBDhF|DTh*fB|yyBuyyd**F*BTdAnsc,z*,{{Fzz{$0DdyakONXWHLrYx7jjxY'/GM", +"~~-'p''JYYx3Z_qc(%>*>%%(%(>%6>%%{,*zzmnnhmhdhAdy$hBB}msDf$DDffDDf*hfDm|yDAsmmIn}sds*hdmyy,acA$,h{FB{f*zhB|fnaaHIHHH!r37U4vtR3pGM", +"S-~-bb'YYjx3r!W)a6%{>>{s6z(,6{>6z,zs|%DmdTOByBd|ATmdfnnf|DfDDD*ffhfDhhByOdydmak)yfhhhhm$KdaA6$gf{{{ff*FDzAdOK=KKKHHLEJU]jjxY//GG", +"2-~/pJJ'3xx3ZVqc1,{6z{zz%%>>>{6D{{zDz,shBBhKfydyBnTnymdfDfhDDhh*DDffhAOB}nTnaddABA$yBDnn$Bnky%fffh{,F{DB$TPnTIXWKWHLrYUUU4Y'3/Gb", +"S~-b'bJJlxx3Z!#Oay>>{h{s>%{6{{z{*FFzz|smydddnfhdAdBDmAmTDdhfDDDfh||hDsshD}fhnAyAmnyTd,BnOdA)A$,*$BDDfBDfQnKnOkICXHVLEYUvUjxJ3/G-", +"9-~/-p/J[YJGZ!WKA>{{*zs6>6{%{%0{{{hhhhdmyhTdnfdyddnyndnf$h*hDDDhDhDmBfyAfdBAyAAsdmTByandAsyA11%fdPs}hTh*aAaanXCKKXVVElxvv4YY'GM+", +"~~~M-p'pJYJpr!WanA{h{{zh{*{*6*z{*DFzzD|hd{hDBBfDdymmABByDdDf**DffBhQhBfsTTTnnmydyyddBQKyndOf,TKsAOBABynBdPdcKnOaXKWVZ[vvUvR'/-MM", +"9~~--p/p3JJGr_W:d${{{{zz{>{*z%{gzfFzz|BB,dmBhBBmy|ddyDB|ffffhfDhQ|BDdsBByAdsyddsfBBnBOm)$n%nmm,nOBmnOdAOkamACCaXKCVVLEljjttt/^+-", +"9-~--/'3333^Z_WNaA{*z{FP{%f{*{{{zzhzF|dfD||hDyhfssdynnBhhDBffBDBhmsdTfdyAnBATksadB)nkaKannk$ddy$yddAynO}BkT)daaXCWWVZ[l4jt'tpb+M", +"~~~--pJp3Ypbr_qCa}>>{{*z{>{{*f,*f*{z*zBhDDDhBDD|BshhhTBfhfDffBDhyhdy*AfBdnAAPyydOAnyAdnKm}ynyTKA8AdnA=OOICkKTXCkWC#V_ElU*z{%{{{{$*z{*zDhBfDDfDDdhfDh|BdhDhBBdDsDfQyAyBydBnynyBmnnnddAnakaKkncymkyaAnKd)TAaOTAaKXIKaOCV!LE4zg>{zhhBB|d*Dh|DBh|yBhmmyyBddBnnmQndnnAATkOnAdkTTadcAankkcak$akmInanXCnOK8KaXC:K#XVL^v7>{f,{{*{%{*{{zzfDhDBf|mmdhDfDfDyhyfAmmmBBmsKsyBTAAdBTdddnnAkcnaIIIAIn8cnncaan)aA8OXKCXI:X#KXVZlY<%6*{6>{%6{z{{{{{{{h{DDh|fh|fyQBfmfnBBfyymysd8yOAyydymAmTdaTK)AIIacc,cdOaak)}k):=IAaaKanCICKoKCWLZl77%%6>{>>>{*>zsmsBh|D||BhDhQhyBBByyBydddsyBnAndBTByBAnOkIk)$kaAydT1Odc(XNcOK=kXOmOcKKiKKWWW!E4vv%,1{{,>,{%%{>**66{z**fDD|Dy||DhhhAAQhhdBmdymyAyBddAdnmOOskAcI):nd}k}n}%Ak}kk=:iaaaKakdaIa:KCC##LZv]77v4R'/Me", +"9~M--bGp/'J+r_H=N1(1(1%%>>>,z%%{{>>{{h|DDmD|d*h|hDgffshBBmQydAAnsByasyTABmydd}$kcCnaAndTn$}ann8n:IIK8Oka$AndOIIXOC#LE77]<>z,6{6z{6{*zf*zhhfyfDhh*|*B|fhdyfyBmyyddAAAmyAnyndddAycAkIIcck=8nAAAKad)nKWaOIIdKkdnkdOKXC##LE7]7]6>*${%6{{{z**zzh*|fD|DDfD||D|*Df|||mhhdysAyAymdndAyByyAndcakcac}nydTdycknaankIAdBA$sI8aaCKCC#L[4]]<6z{*f*{>>>{**zD{|DfyhmhhyfDDhfDf|hDfdyyAAdmddnnBynBdnT%ynnd1a1cK$kAmBAd8IK8KIykkK8nB$yAKOkOX##LE4].7]&t'p-M", +"2~--b-/ppx'[^5;o%=>>%*6{,%f{z{z*{zDhf*D|g|Dy|D||DDDD|DdmfDmyDyAymadA8sdAO,nTnayn:cc%nk>Onaf)kKnOATXd8ndm8dAAnKdCXOVLE4]]]6%*f*z{{z{>zf{D{DhhDf*dh|BfDDBhhDDDdf|BQBAyBsydATByAnyAdnnn}nnkAaAyyyfdA}IadaT8nmd8sddAdKIKXXWLZ4]]<]jt'b-~", +"99---p''''tY[+wH:11${{{>{fz{{{%fzD**DDDf|D|DDgfDDhhhBfhmhD|mhdydyBfyDdyfmhn%1A)Tkk8daKsnTyABynAAATAAmnAnBnskanIKOC#!Z4<]<{,%%{{,{{%{z{zD***FD*hDDDfhhD|hD|fh|hDDyhdhmddBmndmyTAdOnB%BnaddOkyA{TAdnAn}dABdmmddBndAyyKTK##!Z47]]%%{{D{DFDDD*FhD|hD|DDyDDD|DdmffDsmmByBsmBfyymfBBsnky,md$AAAh,%TABTdByyBnhdydnB8KAXOOWWVZ[<]<6%>{%*{**FD0fDhDhDDdDd*|ByDhhhDhyyByBysOfsAdBBAdAdnTdynKyAdTnndDdydBByyfByBdymydDKnOXkX)VZ47]]{>66%%%{B{*{hF*DDDDDfD|DhfhhBD||m|hhyyhyAmDyBAmydnhnhDdThmyy%BBBynBydhBfyBfmydBB|mdadKkTn=)O#VZ[v]]>{>,%*%z{h{*{**hFh*D*DDhhfBBhfD|hhBhfshhs8BBmhyffTmmyhBfDyndABAnfndnmnBfhmyKAIkAATTdnOKmOOOC#LZl7]7>>%{{{f*F{*D{DF**DfhDD|hhhDffhhhy|D|Bmmd|mB|BddBA|Bfd|smDTmysfmmdydymmDhfnmnmmdAcyndnIakO#OV#L[v]]7jJJb-M", +"29~---''/&t&[Z!qCc11(,>6>>{z>**{DDF*****DDfhDDBTBdmhd|fDn|yhy|hd|d|mmdfABDyhDhBgBDD|DBBOyQdDynydAAnn8kAkBmnsnkOTKOO!L[<<7Ujxpb-e", +"2~9~-//'RR4R^@_qN:(((866*{{**F{*D*{DDDD*D*Df|hhffdnBhDh|hmBAfBf|DhhhyBnyDBBDBDDhhfD*Dyhmh|fmyyysmmA8mdkdyTkkaAkaOX#VL[&]7Uj''-MS", +"229---/''x&&^Z!q=:a1(1%>6zz*{***{**D*DFfDD*hhfBfmDD|DDfhddfm|fhDDm|dhByBsyhDhDDDDDDD{f|ymy*hDmyBymmmsAAnnsdnAKkKXOC#L[4]7UjxJb-e", +"222~---G'xtR^_VqoN:ii(>>*,*{****D{FD*D,Ffhh|BDnBBndDBDfDyBhDhfhhh|DDBsmsf|B*fDDg|FDDDhfsDmyDmm||sAsAmnQkyndAAnkanCW_Z[4<7UxJJpbM", +"22~~S-/'ptj&+Z!;o:Ni((i%{{*F**{***hD*hF*h*hDf|dhmhBfmhnDByfhDh|f|Dh|hhffhhBh*DDFDF*gDhBmhysff|myzymAsAPdmBmynAKnOO#VEl7]]7UxJGbe", +"299MeM-G'jxY^w;oq::((1(,{****{*{**D**D*Dh*Fffhmhyk8BBDDBhhyfDDD*Fh|*DhDmhD*FhF*DDDD*g*DDy||hDzD*m>z>m1AaynAAkTdXXC#!Zlv]]7Ujx3GM", +"299~M-//'xx3EwVqoNN(1((>6{**0******DF***DDDhBmmAmnm8By|8BhD|DhDDD*|DDDhDhf|D*D*DFFfDg*DD||zD*zs*smDsm%hymy8T8nAXO#VZ[vv]]7]UU''b", +"992~M-bGJxJ3EwHooNN1i(>>{{{**F**0D**h**D*D|z|shhnmAm8Tnhfffhf*FDDBD|hmf|fDDF**FDDF***h|f*z{By{fDzmsy{syykT|IaAOOW#LE[<]]]]77jx'G", +"29MS~MbpJJxJEwVHoo:(11%66{*****{*D*Fh*DDFD*DhsAsTmyBfBDffD|DDDDDDDf*D|**|DhFDFDDDFD*DDDF*zzzFz{zzD*B>s|ymAOKKIC##LL[&v]]]].]7Ujb", +"22SeebMp3xJJEw!q=N:1((%%{{{***F*FD*DfFDF*DzzmB8|I8AB8hBhDfhDhfFDDD|*DgDD*DfD|DFDDD|*F|*zF*FzFz{*Fz*P>sssmmAIIOX!LE[&v]].].]]]Ujp", +"99MSMbMppYYJG@Z;;)N1(%%>6{{{{F*{D*FDDDDDzhfffhTyTfABTydBhTBDhfBh*BhhDfDD|g|hDhD|hDFDDDB|D**Dz|**zDmBm%TydyAIIXWVZ[&<].......]UU3", +"9SSb~bMGGpxx[^@_;==N1%(>>f{{{{*DDD*DDhD{{B>%AyyhAkdAm|nffdddfDDffh*h**DfDDhhhhDffffhD*D*D{*D***zDzsQzsAy88IaX##Z[&&<]]......]7Ux", +"S9MM~b-G'''x'[E@w;=}1($,$h{ffff{fDh{DhfhdyyTAfnBddTyddnAdTBfBfBdhffhDh*fdfhDhDfhf|fBhfDhDD{zhDfmy,%s(11nTBKIIW!Zlv77]........]vx", +"S2SeeMGb/pJ'jtR+@w;qq})$$$$,{,hffffhBBfdTnknATdnThAnOkTnOTOdTfBffBDhdBfffhfhBBfdBBdBBBBfBhdfdBd%A$naKdndnIaOX!L^lvv7]]......]]Ux", +"2SSMSM-M--'pxY4[EZ_;;W==}}}}$)$$$d,TnOTOKOXKXOOTXnTXCTXOCOCOXOOOOTOOOOOOOOOOOOWCOOOOCOOXKnCnTKX}CCC=cXXOXCC##VEElvv77].......]vx", +"99S9reM-//pJY44l[^E@L_L_LV!##==))=CCCCW##V####VC#CWXC##VVLVVVLVVV#######!#LV!VV#VVV#####=##W##V!!_V!V_V!V!!LLZEYYvv7<]]....]]7&Y", +"2299Me~MbbpJJJxjl[[^E@@@@@ZZLLLL!!!!!!LL_ZLLLLLLLLL!LLLLZEE[EZZZZZZZZLZZZELEZZZZZLEZZZZZLLLLLZZ@@EEEZZZZEZEEEE[lYY4vv<]]]].]]7tp", +"22252~e~MbppJJxYYYl[^[[[&[[[[[[E[ZEEZEEZEll4lll[EElZEEE[ll[4ll[[E[Z[l4[4E44[[4[4[l444l[l[^E^[[llllllll[[lYll4xRtJxxvv<<]<]77UUYG", +"52222SeeMMbpppJJJllllR[R&R[[[[[[[[&[&&vv44l444444[4[[[[l4v4444l4l4l[[[[llll4l[[4l444444v&&l&&&<<&<&&4444vv4Y&&YYRxYY4&& c #928D42", +", c #A29D55", +"< c #F2F2E9", +"1 c #AAA26A", +"2 c #958627", +"3 c #B7A64F", +"4 c #313C1E", +"5 c #7B8260", +"6 c #E1E2D8", +"7 c #989858", +"8 c #A69948", +"9 c #677635", +"0 c #787328", +"q c #D8D8CF", +"w c #A9A458", +"e c #67684C", +"r c #49662B", +"t c #B8B577", +"y c #E6E8E3", +"u c #697651", +"i c #D0CE9F", +"p c #D3BF6D", +"a c #C8B976", +"s c #121416", +"d c #888837", +"f c #BDB061", +"g c #464921", +"h c #ECEBE5", +"j c #9E9974", +"k c #4B5929", +"l c #BBC28D", +"z c #85884E", +"x c #CFCDC5", +"c c #0C1216", +"v c #4E4E39", +"b c #83832E", +"n c #9C922C", +"m c #585832", +"M c #A9AD88", +"N c #C4BA9F", +"B c #C4C395", +"V c #ACB37A", +"C c #B8B893", +"Z c #C3A955", +"A c #666A35", +"S c #7A8438", +"D c #8A9476", +"F c #161A18", +"G c #586827", +"H c #90955E", +"J c #9A9E75", +"K c #C9C8AD", +"L c #3C3F29", +"P c #B9C0B4", +"I c #767947", +"U c #61692F", +"Y c #7A7041", +"T c #2F2C29", +"R c #98A386", +"E c #DDD6A2", +"W c #B4AA87", +"Q c #0A0C15", +"! c #A59639", +"~ c #8B9247", +"^ c #A7A67D", +"/ c #3B482A", +"( c #1A261A", +") c #989339", +"_ c #B6A867", +"` c #60614E", +"' c #26291F", +"] c #767A35", +"[ c #3A5525", +"{ c #7B795B", +"} c #6C762B", +/* pixels */ +" h qMt-1X,zIIDRVIHH@J#ftV1fta+iifC < K6~z9>zCHH9H59U5rzw,)]--7%f]oJ,f{zYHfttp+Coh< ", +" +_,7VK%1Ct31-w1^wf,,X-9SSwH=I%Juz-w#3Y,w99-!16^jC<]qD*7f+a+++Chxy ", +" 61SH`R<@H1^wZ_838,H311w]Swv=PH5M~_w->]N&U^A>,3p7718-wwwJf1VV+1K%q ", +" tWZ8#zuz1t>]w7-I97w#f,JJwIwSKIt,S~SUI7d73w#~~S;S-ww,H~7+JVaVx6xh ", +" hK^+_HK_tV,X8_1YH]~-3-J,X~zI3DzI;9A;Ad>-X3d-fd;S~Iz>Ia1H@^CV6 %x ", +" 6 PR3f#pa##pfzwf8-~-]~~~,Hz-SH;5rrU9A99>dz]>8H7fwfpf-#+CMllMq R ", +" qxK8p#appwX*-X-W1IIr%Iz-Hdw~zIz5KAA K^x)~--]wdd>3-X,X,w7Rq< D% ", +" 6d]r/Hj*S9->}IrIo q%N,>SS;)X~~Xw]]-~9~>wz`P%Pu% ", +" hPffat81>,*I~DzIIYv@H8-->-Sd9$$]]M*wS;dIrbI}dSd]d)~KD>~HHD%{vv ", +" Pe%NH>IKx8]U9u6]II9]d>3X>SA;;/k[`r9;;;9d;]99[r0^j DS99MR`Dv{ ", +" +oNCD@uRKP1*K^599zdd&dI9U>-/>9`]k[[/rIIb;AGrdUASrAq^eK M-]IGI%RD= PD ", +" qN+f3fI*Cq@xP%6P%<5Av{7&CqI4II'I]SS;;rU@`;8eW,*UI1-)1oYN <6%AdA]IH%`DxDP ", +" C3ppppHjJYRJ%PPP`%%L4sFT%RI]rA5=);r;[;S-3]>)73WN1_bzz^ q 6&RI-t787+++a_%x ", +" Kt< %zp^33##1##f3XX1a5tvgFF`vL5,A};/38ddk`d)-!*g*m*>w]S8-1q9*o6Dj*1WKot*fa_#fx ", +" MCq << DCt##pp3w>)83zP1m{TF_t{*>Yk/$S9d]9[`r[dYm]f3#p#bS)]S9kzNh6R1fj>,qDh@Ivy ", +" DMK PKajZ,aZp3#)fZp3#p&]8]A1)w-1RLDm]]r;;r99XSr;df#f8))-&}5I^Ho hzHHdIz6y P@D ", +" RKP,o< %eWx^8,f##fX)X#pX-fz--]3-}{Grg9veg$[r`rr9[r]!nb}r9)SdH@9S9r% yKqID ", +" 6 5KHMiCN+N%1pf_tZ#_3_3ZX-3#wddzd])w~5;79k99VA]rr;;d/k;;}};rbdG%5u[J~0Aq P 6 ", +" %hHH76C,~a)9w>~*__f*f-Z3!#3,~)HMMI8]zqyKY[vDr9->b]rg;G9]r[r}}-]IK %%2)S* h%q ", +" xP@rrN%yU[rrr;;9-Xh6]Z8>33,8-8)w#!-XtN1D(/Tgze/$k==[9>S>SI;[;r[[^MUIxH- h ^H*xh ", +" K% yR %;[9]rrIdI* 6^17H tMd9S,a>3&~ISUYv'FgA~`$`($k/;S99}5UPR%@[IK6%M1qKoHIq ", +" D% D@HoRzI76x h x8XS-,wS})8)]S)m.=eU`Ue4=/k;%``;I yy DRHr0GtJxq%w__aE% yfZ8)->))dz,`;999Gd0*A4/b8Ikuq Dx PPPHm]}Jk]Kx ", +" hI%vNW]~-Sm>U;]~I}U}L=}.0b//% `Igr/k%% ", +" 5;*xPKP)!U)X83ZX)XzxHd8I!)}]g;9>Xm$U&{`b'./U[R% 6%U;7 ", +" hRiahq,J&gz03XdI&)3w0}!]3)}ddz)wU(.z4v3kXI*H6 qB8d)3)*m-)d8bbb)b4/csFXm>m&>zH q x ", +" q!K CPi+_3ap*YjwI0)dmGI>]mH;}bGYm(=(..1bA]~m%<@y < ", +" KPK%z_p#p+3XtDH}!&z7z9]ddw.'zz4G{cFvv(U;.gbU`$k]b0)i ", +" D)~d*>!S3-Kxo%t1mvY'>mUm'ee'cQcsvscvvg4=4GHy`G]gn;Ki h ", +" M%Kb@H%`TmZj)f__*`Fs'F*g0'4;AsTcFcQFs4Gmk]q%e C]}0;S;r;JMAz^qI%< ", +" yP$F`Dh WC%W3Z#3AY'ssYL'vTL`s'5scFcc4G[;M`u19;kr[;`}SG;b99d~zK9]x ", +" iKH)4=)X8Y{gY3)-;*YdmsL.{A'T8!I4s'$U(%KH@gvjK%5K%k`vr}S}d!d-+-;;zh ", +" qd88Ifu4!>gs`vI!90db8b4^Fumm]Z3#3'!((]VYg[G)ah<>J9.y`D%z7z-&*zHq@P9h ", +" qIbS-3w3&TL>YZ*`emI)!!!b-#ZnZm{0Xg!sgs'U8UU]9XZ*sLccF'{8CH8#Z)_)!8!0Hz9NmmN)0>mw%h J9>Kh ", +" qhK Pu9]9AIK{[[zZp]zS8>>##3-33bUU-d)0{;!*m'LTj3b)bn!20{)f87>]IXw_@MI7kH1zd@K}k{IKh ", +" ^~~9r[/kjYUkre//r]ddz))83XZXZ-d9->SS]V-}8Z0m{sm>>&&I0wz&dYmge>_d,de45m`'eM1j94r%h ", +" ~I;rr;9z[/k]k[md73,d}}IX)&n3nd!SU)]b8-rb!>S{45L0vgXn!!aw0X0!e.0w>;rGUR'/GIm]ArSM ", +" qKh '$$=Jvvm(L4=g'4Y@>)9]])3#Z)z,9;;U;]m]}k$9G;m=4=~`QggInZZ2)!Z!gA]&00=GkG[4I7bIU/r9D ", +" _pa30(FcvFcYv]ZbG==IHt,KMU7~83X!b8;Idmkm4//$$[[9;4F0)mTQQ.0)2!!X_Xn0&db)&0;[k;]h {9PPP ", +" LmZ>>'>8emvww!04AI1>IUMdbt]d>S]!)Y3X_'FT*0mg('[GkGvXX#)Z04F'2)Y..bzH0m.'F=G$(=/H y ", +" x/&II3TT>*pZ8b0r0b>0d!&Y)d]d]MI)003!)p#&g/v'{Qc(===.=mu&2'(F.mv,0)>IGYe)UzGgQFkz]} ", +" Kw#3&3Z#pw]#))gkGU&G&&&!8!nd7z7^GUvFvgY^#Deg'=4(gcsFc(4Fs:Qcs((mv'mb.d;b}YSG/cckS>C ", +" R/o^t&#Z!Ge33SGrk[kG.{'4Um4s`K^yDDvFs5TF4QT((=GkF('`v$k.4:::v((4/sF/r[;Ib)X}bS09;dd)q ", +" DF`5Y!!2mmb&rrkk0_44F4=:Lv ` %x yuFsGmd/0gQFc(=./QQQF[mg.4vYQQT`@9AU.$}r;r};]kG[9IrSSM ", +" `ccs'mFmbSUk}0&}I``vQ:vqx `%@ xsQ:4=kgL:QQQ4('s(cg202G.dbG4v%5KhyRRUHU$$kUkePP=/kk[[@ ", +" DFsQe`w3Ukm[v'gvWhKoxL<g20G.UUM {Hq PohK%(4]>4PP yGb9=F` ", +" hPPvg,>YA'4/>(FPhxKK-Nhh vD:v `vsTT::::::Tss`c(FF'emv]Lcgg(q 6 yH1%RCh5y Rr%x^H ", +" i,wd_ZsQQ'QcQTRoP h<<< 6vQ:Tvxqs`4mFvQQT:::QF4(vLTvPRL'4'sL4^ Kxy yh ", +" Rx1Xt*DvDILvY`KNP 6RF:QTsvTQF:'LQ:T:::QccmmmD%j{v'DK`44.zaK ", +" hP6N%Z#papafa_tNh %xqvT@`::TQ:Qssgk(`JyQ:QQQQc4T%RYm< oAm0G0G ", +" q 6jXN_a1>*WP yxsPRv::v:::L0m40v4`B5QQccQTR`sQvu@.HM=Pq4G0K ", +" 6PPqx^K< %%`vR@T:::::Q'Fv9(/L0gv:QQQ::::::R yqP% ", +" 6hh6 hR4{#XZ{`gdU&zww]I{{.'T:QcQQ:Q:Q'>% q4 K u/^y ", +" PQUn))ppZ333w>>J-b`]mA-mcQQ:`vT.*N oiR5Uh9zM ", +" K1Z#&&)`2XZ3Gbbz;bb}zI0k;&UF(Qssv:% y RzMB0UUgIC ", +" Xp#XX)GtvYGGk/[}db0;GG]0G.'4[k$'Q:T a0G.G&=/4Gb3>Cq ", +" 6t8f5A>TQ'm.kU4.))0;SrG([r[]'T($vLT` %;0;;U>D`{9}}}bKh +< ", +" qqxyD`$I~-;[/kG}bbrk.gG;rG[k[=4csT` h @vvu`$;>dm`(v=G2tz!@y ", +" `[$kG[G$$gkGG;r[0Sk[$/v[IkA=4RD _e` ", +" 6C*oPqP0Tvm44}v/(4'G./G;GGGr$F=k(QFm4dYmUgF% x% @5U/9rb/P ", +" yz7,Kh0mFTQTmU7c::sgg-mD44.9G(===(FH>vmm@)~X~H %kD};rS1K ", +" >*+)dmY!ZZ3)0bgF=.=bd{qqx D=}g/==480^AsD DKuy x hx[H ", +" CK]tv8t3###))G==F4G0b7>MRIUgKRzmcc'9U8fLN yx ", +" tBCi^#I]!)X!$.Um3-'4gMhC-MK%GKgQc(g$/>Zt,+ ", +" hCI h5^{&,0z&m}372g]30!h `x'Qcs94s/H/,-% ", +" +Wy ", +" PHH)K qxD9bbXX>%0YXG>b) c #424242", +", c #454545", +"< c #494949", +"1 c #4e4e4e", +"2 c #525252", +"3 c #565656", +"4 c #595959", +"5 c #5d5d5d", +"6 c #616161", +"7 c #666666", +"8 c #6a6a6a", +"9 c #6e6e6e", +"0 c #727272", +"q c #6e6e6e", +"w c #707070", +"e c #7d7d7d", +"r c #818181", +"t c #858585", +"y c #898989", +"u c #8e8e8e", +"i c #929292", +"p c #959595", +"a c #9a9a9a", +"s c #9e9e9e", +"d c #a1a1a1", +"f c #a5a5a5", +"g c #a9a9a9", +"h c #aeaeae", +"j c #b1b1b1", +"k c #b5b5b5", +"l c #bababa", +"z c #bebebe", +"x c #c1c1c1", +"c c #c5c5c5", +"v c #cacaca", +"b c #cdcdcd", +"n c #d1d1d1", +"m c #d5d5d5", +"M c #d9d9d9", +"N c #dedede", +"B c #e1e1e1", +"V c #e5e5e5", +"C c #e9e9e9", +"Z c #ededed", +"A c #f1f1f1", +"S c #f6f6f6", +"D c #fafafa", +"F c #fdfdfd", +/* pixels */ +"FFFFDDSAAZVNMnzg,ihzvvvbbvcxxkgp;eahllzzzzlkjhau-qpfhjkklkkjhdpw-tagjkkllllkjgau-wpgjklzzzzlljfi;rdjzxcvbbvvvxlf,pkvMNBCZASSDDFF", +"FFFDFDSSZZVBMbxg,ihzcvvbbvvxzkgp;eahkkllzllkjgay-qifhhjkkjhgdae-epfhklzzzzlkkhdu-wagkklzxxzzljfi;rdjzxcvbbbvvxlf>pkbmMVCZASDDDFF", +"FFFFDDSAACVNMnzg,ihzvcvbvvcxzkfi;eahkkllzllkjgat-0udgghhhhgape-rafhklzxxzxzlkhdu-wahkllzxxzzlkfi;rdkxxvvbbbvvclf,pkbMNVCZASDDDFF", +"FFFDDDSAACVNMbxg>uhzccvvvvcxzjfi;wagkkllllkjhfar=9yaffgggfaiw-eafjlzxxccxxxzljfu;wahklzxxxxzljgp;rdkzxcbbbbbvxkf,pkvmNVCZASDDDFF", +"FFFDDDSAZCVNMbzf>ihzccvvvvczljfu;wpgjjkllkkjhdpr=9tadfffdauw=epfhkzxccccvcxzlkfi;eahllzxxxxzlkgp:rdkxxcbbbbvvxlf,pkbMNVCZASSDDFF", +"FFDDDSSAZCVNmbzf>ugzcccvvcxzljdu;wpfjjkkkkjhgdpe*8tpaadapuq-wpdhklxccvvvvcczljfi;eajllxxxcxzlkfp:rdkxxvvbbbvvxlf,pkvmMVCZASSDDDF", +"FDDDDSAAZCBNmbzf>uglxcccccxzlhdu-qpfhjjkkjhggaiw*7riappiyq=wpdhkzxccvvbbvvcxzkfi;rahllxxccxzzkgp;rdkxxvvbbbvvxlf,pkvMNBCZASSDDDF", +"DDDDDSAZZCBMmblf>uglxxcccxxlkhdy-qidhhjjjjhgfauq*5wyiuyr9*qidhkzxcvvbbbbbvcxzkgp;rajllxxcxxxlkfp;tdkzxvvbbbvvxkf>pkvmMBCZAASSDDD", +"FDDDSSAZCCBMmvld>uflxxcccxzlkhay-qudghhjjhgfday0&5qryte8*0uagjlxcvvbbnnnbvcxxkgp;rajlzxxccxzzkgp:rdkzxvbbbbvvxkf,pkvmMBCCZASSDDD", +"DDDSSSAZCVBMnvld>ufkxzxxcxzljgay=0uagghhhhgfapt9&30eeq7&8yafjkzccvbnnnnnbbvczlgp:rdjlzxcccxxlkgp;rdkzxcvbbbvvxkf>ikvmMBVZZASSSSD", +"DSSSSAZZCVNMnvld:yfkzzxxxzlkjgat-0uaffgggffaair8%17095&8tpfhkzxvvbnnnnnnnbvcxlgp:rajlzzxcxxzzkgp:rdkzxcvvbvvvxkd>ijvmMBVCZASSSSD", +"SSSSSAZZVVNmnckd:tfjlzzzzzlkhgat=9yadfffffaapyw6$<563%6riahjlzcvbbnnmmmnnbvczlgp:rajllxxccxzljfp;rdjzzcvvvvvcxkd,ijvnmNVCZASASSS", +"SSSAAAZCVBNmbcka:tdjllzzzlljhfpr=8tpdddfddaaitq5#:1<$4wuafjkzxcvbnnmmmmnnbvcxlgp;rajlzxxxcxzljgp:rdjzxcvvvvvczkd>ijcnmNVCZZAASSS", +"ASSAAACCVBMnbxja:tdjllllllkjgdpe*8tpaaddaaaiye93@-;@29tpdgjlxcvbnnmmmmnnnbvcxkgp;rdjllxxxxxzljfi;rdkzzccvvvcczjd>ihcnmNVVCZAASSA", +"AAAAZZCVBNMnvxja:rajkklllkjhgdiw*7riaaaaapiytw7<+$+<8wuafjkzxcvbnnmmmmmmnnvcxlgp:rahllxxxxxzljfi;eajlzxcvvvcxzjd>uhcnmMBVCZZAAAA", +"AAAZZCVVBNmbvzhp;rahjjkkkjjgfauq*6eupppppiute94:oX;5qtpdgjlxccbnnnmmmmmnnnvczlgp;rahllzxxxzlljdi;eajlzxccccxxzja:uhxbnMBVCCZZAAA", +"ZAZZCCVBNMmbczhp;eagjjjjkjhgdayq*5wyiiiiiute07<& #18euafhjlxcvbbnmmmmmmmnbvcxkgi;eahklzzxzzlkjdi;eahllzccccxzlja:yhxbnMNBVCCZZZZ", +"ZZZCCCBBNMnvclgi;wpfhhjjjhgfdpy0&4qtyuuuuteq84-oX*30ruaghklxcvbnnmmmmmmnnbvxzkgi;eahlllzzzzlkhdu;eahklzxcccxzlha>ygzvnmNBVVCZZZZ", +"ZCCCVVBNMmbvxkfi-wifghhhhgfdair9%30rttttreq84:O%O-5qyiagjklxcvbnnmmmmmnnnbvxzkfi;eahkklzzzzkkhdu-wahklzxxxxzzkha:ygzvbmMNBVVCCCZ", +"CVVVBBNMmnbczkfu-0idgggggfdapue8%28wrrrew074:+=-O:6eypdgjkzxcvbnnnnmmmnnbbcxzkfi;wagjklllzlkjhau-qpgjklzxxzzlkgp:tflcvnmNNBVVVVC", +"VVVBBNMmmnvxljdy-0uaffgffdaapye7$17qwewq084>+-,>@>7eupdgjkzxcvbbnnnmnmnnbvcxzjfu;wagjjllllkkjgay-qpfjklzzzzlljfi;rflcvbmMNNBVVVV", +"BBBBNNMmnbczlhat=9yaddddddaputq5$<60qq0974>+;11<@,7eupdgjkzxcvvbnnnnnnnbbvczljdu-qpfjjkklkkjhgat-0ifjjklzlllkjfi;rdkxcbnmMNNBBBB", +"NNNMMMmnbvxlkgar=8tpaaaaaapuyr04#,5798763:@:233<@,8ruadgjklxccvvbbnbnbbvvcxlkhdy-qidhhjkkkjhhfpr-0udghkkllkkjhdu;eajzxvbnmMNNNNB", +"MMMMmnbbcxzkhfpe*7eupaaaapuytw82@:266541;+:24541#,8rupdghklzxccvbbbbbbvvcczlkhay-0udggjjjjhhgdpr=9uaggjjkkkjjgay;wahlzcvnnmmMMMM", +"mmmnnbbvcxljgdiw*6wyiiiiiiyteq71+-1342<-+;146642#,8rupaghklzzxcvvvbvvvvccxzkjgat=0yafghhhhhgfaie*8yaffhhjjjhgfat-qpgklxcvbnmmmmm", +"mnnbbvcxzljhfay0&5qtuuuuuyteq95,+=><<,=O-<356652#<8eyiafghklzxxcccvvvccxxzljhfpr=8yadfgggggfdauw*7tpdfgghhhgfdpr-0pfjkzxcvbbnnnn", +"bbvvcxxzlkhfapr9&39ertttrreq972:O&-:;&O=,2466641@,7wyiafghjklzzxxxxxxxxzzlkhgdie*8tpadffgfdaaiy0*6riaadfgfffdaie=9uahjkzxccvvvbb", +"cxxxzzlkjhfaaue7$18qeeeewq0874<=o#&*$o&:1356664<@>6wtupadfhhkkllzzzzzzllkjhgdayq*6euaaaaddaapur9&4wypaaddddaapyq*7tafgjklzzxxccc", +"xxxzlkkjhfaaitq5$,690qqq008641:&X+#@X$-,1355653<@:5qryiadfghjkkkllzzllkkjhgfapt0&5wyipaaaaapuye8%30tiipaaaaapur0&6epafhjjllzxxxx", +"kkjjhhgddaputw83@:36788876531>=$.Xo.@&;,1244442>+;38weyipadffghhhhjjjhhggfdapue8%29ryyuiiiuyte05$18wtyuuiiiuytw7%3qypadfghjjjkkk", +"daaaappiutew084>+*,2333321<>;*$O o#%-:,,<1<<>-O*<579wetyuipaaaaaaaaaaapiutrw93#,59qweeeewwq961@:480qweereww083#,7qrtuipaaaddad", +"rreewqq997642<:%X+&--;---=&%#+o. .X+@$&*=---=*$X@=>1356890qqwwerrrrreeww008751;O&>24456665432,=o%:<3455665543<;O*,46790qweerrrr", +";;;-;--=**&%$#@o XO++++++OooX. .XooO++++@+Oo.X+#$%&**==--;;;;;;;;;;;--=**&$@.O#$%&&&&&&%%$#+.o@$%&&&*&&&%%$+.O#%&*=----;;;;;", +"iiiuuutrew0864<-o$-:>>>>:;=&#+X O#&=;:,,<<<,:=o%>3680wertyuiiippppiiiuuytew961@;36890q0009863,+=1578900009974<@;480wrtyyuiiiii", +"ffddaaapuyteq84>+*>132211,:=%O.. o$=:,134555643,+;49qetippaddfggggggggffdaaiutq6$18wrrtyyttreq83#,60werttyttew95$19eyupaadffffgf", +"kjjhggfdaaiyrq71@-1455442<:=#.O+.@*>146899000862#,7wtupadggjjjkklllllkkjhhgdait9%4qtuipappiuurq6%29eyyippppiuye8%4wypadfghjjjkkk", +"llkkkjhffapite83@:2566543<;%X#%$X$:14780qwwwwq85$19tiadfhjkllzzxxxxxxxzllkjgfauq*6eiaaaadaaapue8%4qyipaaaaaapit0&6rpafghjkllzlzz", +"xzzllkjhgfaiyr93#:3676541,*o%=-&o%,4780werrrre06%3qyaafhjklzxxcccvvvvccxzlkjgdie*7tpaddffdfaait0&5eupaadddfdapyq*7tadghjkllzzxxz", +"ccxxzlkjhgaair04#>367652<-O*:,>-O=169qertyyyttw8%5eiafhklzxcvvvbnbbbbbvvcxzkjgar=9yadfgggggfaauq*7rpadfgfggfdaue*8yaghklzzxccccc", +"vccxxzljjgdaitq4#>466531-O-,221>+;39qetyuiuiiyr0&6rafhjlxccvbnnmmmnmnnnbvcxzkhay-0udgghhhhhgfaie*7tadfgghhhgfair=0udhjlzxcccvvvv", +"vvvcxzlkjhfaptq5#>35642;O;14543<@:50eryiippaputq*8yagjkzccbbnmmMMMMmMmmnnbcxzjdu-qifhhjjjjjhfdpe=9yafghhjjhhgdpt=0ifjklxccvvbbbb", +"bvvccxzljhfaiyq4#>2442:+:2567751@,7qttipaaaaapyw*8udhkzcvbnmmMMMMNNNMMmmnbvxzkfu;wpgjjkkkkjjhdar=9uagghjjkjhhfat-qigkkzccvbbbbbb", +"bbbvcxzlkhfaiyq4#:131:@>36890973#<8eyupaaaddaaue=9ifjlzcvnmMMNNBBNBBNNNMMmbcxlgi;eagjkllllkjhfat=0idhhjkkkkjjgay-qpgklxcvbbnnnnn", +"nnbvvczlkhfait04@;<<;+>489qqw095$20ruiaddffffapr=0pgkzcvbmMNNBBBVVVBBBNNMmnvclhp;rahkllzzzlkjgay-qifhjkllllkjhay;wahlzxcvbbnnnnn", +"nnbbcczlkhfait03@-:;+:480wweew06$30tiaaffggffdat-qahlzvbnMNNBBVVCVCVVVBBNMnbczja:rajllzzxzzkkhay-qpfjjkllllkjhdu-wahlzcvbbnnmnmn", +"nnbvvczljhfair91+&*+:38qerrttrq7%4wyaadfgghggfay-wahzxvnmMNBVVCCCCCCCVVBNMmnvxja:tdkzzzxxxzlkhdu-wpgjkklzzzkkhdu;eahlzcvbnnmmmmn", +"mnbbvxzljhdaue7yfkzxxcccxzljfu;eahklzzzzzlljfi;rakzxvbnnmmmmmm", +"mnbvcxzkjfair03* #,60etuippiiut0&6rpdfhjkkkkjhdi;rdlcvnMNBVCCZZZAAAZZZCCVBNmbckd>yfkxxccvcxzljfi;eahklzzxxzlljfi;rakzxvbbnmmmmmm", +"nnbvcxlkhfayw7:OX*39eruiaaaapitq*7tafghjkkkkkhfi;tflcbmMBVVZZZAAAAAAAZZCVBNmnvld>uglxxccvccxlkgi;rahllzxxxxzljfp:rdkxxvbnnnmmmmn", +"nbbcxzkjgair91@*+;5qtyipaaaaapyw*8taggjkllllkjfp:tfzvbmNBVCZZAAAAAASAAZCCVBMnvld>uglcccvvvcxzkgi;eajllzxxxxzljgi;rdkxxvbnnmmmmmm", +"nbvcxlkhdatq3#>,@,7eyuaadddddauw=9uaghklllzllkga:ygzvnMNBVZZAASSSSSSSAAZCVBMmvlf>uglccvvvvcxzkgp:rahllxxxcxzlkfi;rdjzxcbnnmmmmmn", +"nbcxxljgaie5$142#19rupaddffffaie=9udhjklzzzzlkha:ygxbnMBVCZZAASSSSSSSAAZZVBMmvzf>uhzcvvvvvcxxkhp;rajllxxccxzlkfi:rdkzxcbnnnmmmnn", +"bvcxzkhdpt7%4774$20yiaaffggffapr=0idhjkzxzzzzkha>yhxbnNBVCZZASSSSDSSSSAZZCBMmbzf>uhzccvbbvvxzlgp;rdjlzxxcxxzlkgp:rdkxxvbnnnmnnnn", +"vcxzkhday8&60q06%4wuaafgghgggdpr=0ifjjlzxxxxzlja>uhxnmNBVZZASSSDDDDSSSAAZCBNMbzf>ihzvvvbbvvxxkgp:rdjlzxcccxzlkfp;rdkzxcbbnnnnnnb", +"cczljgay9*7wrrw8%5eiadgghhhhgdat-qpgjkzxxccxxlja:uhcnmNVCZAASSDDDDDSSSAAZCVNMbzg,ihzcvbbbvvcxlgp;tajlzxxccxzlkgp;rdjzxcbbbnnnbbv", +"cxzkgdu0*8eyyyr0&6rpdfghhjjhhfat-qpgklzxcccxxzjd>ujcnMNVCZASSSDDDFDDDSSAZCVNMnxg,ihzvvvbbvvcxlga:rdjzzxxcxxzlkfp:rdjzxcvbbbnbbvv", +"xzkhdpw=0ruiiutq*7tpdghjjjjjhgay-qphklzxccccxzja>ujcnMNVCZASSDDDDDDDDSSAZZVNMbzg,ihxvvbbbvvcxlhp:rdjlzxxccxzljfi;rajzzcvvbbbbbvc", +"zkhdpw-qupaaapyw*8yafghkkkkjjgay-wahkzxcccccczkd>ijvmMBVZZASSDDFFFDDDSSAAZVNMnzg,ihxvvbbbbvxxlgp:rdjlzxxcxxzlkfi;rajlzccvvvvvccz", +"khfiw=wiaaaddaue=9uaghjklkkkjhdu;wahkzxcvvvvczkd>ijvmMBCZASSDDDFFFDDDDSAZZVBMnxg,ihxvcbbbbvcxlhp;rajlzxxxxzzljfi;eahllxccvvccczz", +"hfpe-wiadffffapr=9udghjklllkjhdu;wajzzxvvvvccxkf>ikvmMBCZZSSDDDFFFFFDDSSAZVBMnxg,ijxvvbbbbvcxlgp:rdjlzzxxxxzljdi;eahllxxccccxxzk", +"fae-wiafghhggdpr=0idhjkllllkkhdu;eajlzxcvvvvcxkd>pkvmMBCZASSDDFFFFDFDDSAAZVBMnxg,ijxvvbbbbvcxkgp;rajllzxxxzlkjdi;wahklzxxxxxxzkh", +"pr;epdghjjjhhfat=qifhjkllzlkkhfu;eajzzcvvvvvvxkf,pkvmMBCZASSDDFFFFFFDDSSAZVBMnxg,ihxcvvbbbvxxlgp:rajllzxxxzlkjdu-wpgkklzxxzzlkhf", +"q-radhjkkkkjjgay-qifjklzzzzlkjfi;rdjzzcvbbbvvxkf,pkvMNVCZASSDDFFFFFFDDSAZZVNMnxg,ihzvvvbbvvxxkgp;eahklzzzzllkhau-wpgjjlllzlkkhfa", +"-epfhjkllllkjgay-qpgjklzzzzlljfi;rdjzxcvbbbvvckf,pkvmMVCZASSDFFFFFFFDDSSAZVBMnxg,ihzvvbbbvcxzkgi;eahklzzzzlkkhdy-qpfhjkllkkjhfpe", +"tafhkkzzzzlkkhdu;wpgkklzxzzzljfi;rdjzxcvbbbvvxlf,pkvMNVCZASDDDFFFFFDDDSAZCVNMnxg>ihzccvbbvvxzkgp;eahklllzllkjgay-qidhhjkkjhgdae;", +"afhlzzxxxxzlkhdu;wahklzzxxxzljfp;rdkzxvvbbbvvxkf,pkbMNVCZASSDDFFFFFDDDSAACVBMbzg,ihzvvvvvvcxzjfi;eahkkllzllkjfat-0idgghjhhfdpe-r", +"gjkzxxcccxzzljfi;wahklzxxxxzljfp:rdkxxcvbbbvvxlf,pkvMMVCZASDDDFFFFFDDDSAACVNMbzg>uhzccvvvvcxzkfi;eagjjllllkjhfar=9uaffgggfaiw-ea", +"jkzxccccccxzljfi;eahllzxxxxzlkgp;rdkzxvvbbbvvxlf,pkvMNVCZASSDDFFFFFDDDSAZCBNMbzg>ihzccvvvcczlkfu;wagjkkllkkjhfpr=8yaddffdauw-epf", +"klxccvvvvccxzjfi;eahklzxcxxzlkfp;rdkxxvvbbbvvxlf,pkvmNBCZASSDDDFFFDDDSSAZCVNmbzf>igzcccvvcxzljdu-wpfjjkkkkjhgdie*8tpaaaapuq-wpdh", +"zzcvvvbbbvcxzkfi;eajllxxccxxlkgp;tdkxxvvbbbvvxlf,pkvMMBCZASSSDDDFDDDDSSAZCVNmbzf>uglccccvcxzlhdu-qpfhhjkkjhhfaiw*7eiappiy0=wpdhk", +"xcvvbbbbbvcxzkgp;rajlzxxcxxxzkfi;tdkzxvbbbbvvxkf,pkvmMBCZAASDDDDDFDDSSAZZCBMmvlf>uglxxcccxxzkhdy-qidhhjjjjhgfauq*6wyiuyr9*qpdgkz", +"ccvbbnnbbvvxxkgp:rdjlzxxcxxzzkgp:rdkzxvvbbvvvxlf>pkvmMBCZAASSDDDDDDDSSAZCCBMmvld>yflxxcccxzlkhay-qidghhhjhgfday0&5qryrw8*0uahjlx", +"vvbnnnnnnbvxzlgp;rajlzxxccxxzkgp:rdkzxcvbbbvvxkf>ijvmMBVCZASSSDDDDSDSSAZCVBMnvld>yflzzxxxxzlkhay-0uagghhhgfdait9%40eeq7*9yafjlzx", +"vbbnnnnnnbvcxkgp;rajllxxcxxzlkgp;rdkzxcvbbvvcxkd>ijvmMBVCZASSSSSDSSSSAAZCVNMncld>yfkzzxxxzlkjgat=0uaffggggfaair8%27095&8tpfhklxv", +"bbnmmmmnnbvcxlgp;rdjlzxcccxzlkfp;rdkzxcvvvvvcxkd,ijvnmNVCZZSSSSSSSSSAAZCCVNmnvka>tfjzlzzzzlkjfar=9yadfffffdapyw6$,463%6riagkzzcv", +"bnnmmmmnnbvczlgp:rajlzxxxcxzljfi:rdkzxcvvvvcczkd>ijcnmNVCCZAASSSSSSAAAZCVBNmbcka:tdjllzzzlkjhfpr=8tpdddfddapitq5#:1<$4wuafjkzxcb", +"nnnmmmmnnbvcxlgp:rajllzxcxxzlkfi;rajzzccvvvcczjd>ijcnmNVCCZAAAASSSAAAACCVBMnbxka:tdjllllllkjhdpe=8tiaadddapiyr93@-;#29tpdgjlzcvb", +"nnmmmmmmnnvcxlgp:rajlzzxxxxzljfi;rajlzxcvvvcxzjd>ujcnmMBVCZZAAASSAAAZZCVBNMnvxja:rahkklllkjhgaiw*7riaaaaapiutw7yhxbnMNBVCCZZZZZAZZZCVBNMmbczhp;eagjjkjkjhfdayq*5wyuiiiiute071% #18euafhjlxcvvn", +"mnmmmmmnnbvczkgi;eahklzzzzzlkhdu;wahklzxcccxzlha:ygzvnmNBVVCZZZZZZZCCVBBNMnvclgi;wpfhhjjjhgfdpt0&4qtuuuuyteq73-oX*30ruafhklxcvbn", +"nnmmmmmnbbvczkfi;eahkklzzzlkkhdu-wagklzxxxxzzkha:yfzvbmMNBVVCCCZCCCCVVBNMmbvxkfi;widhghhhggdair9%40ettytreq84:O%O-5qyiagjkzxcvbb", +"nnmmmmnnbbcxzkfi;wagkklllzlkkgdu-wpgjklzxxzzlkgp:tflcvnMNNBVVVVCCVVVVBNMmnbczkfu-0udfggggfdaaue8%29wrrrewq84:+=;O:6eupdgjklxcvbb", +"nnmmnmnbbvczljdu-wpgjjllllljjgay-qpgjklzzzzlljfi;rflcvnmMNNBBVVVVVVBBNNmnnvxzjdy-0uaffffffaapyw7$17qewwq084>+;,>@>7eupdgjkzxcvbb", +"nnnnnnnbvvczljdu-qpfjjkklkkjhgat-qifhjklllllkhfi;rdkxcbnmMNBBBBBBBBBNMMmnbczlhat=9yaddddddaputq5$<69qq0974>+:<1,@,8eupdgjkzxcvbb", +"bbnbnbbvvcxzlhdy-qidhhjkkjjhgfpr=0udghjllklkjhdu;eajzxvbnmMMNNNBNNNMMmmnbcxlkgar=8tpaaaaaapuyr94#>5798763:+:233<@<8euadgjkzxccvb", +"bbbbbbvvcczlkhat-0idgghjjjhhgdpr=9yaghjjkkkjhgay-wahlzcvbnmMMMMMMMMMmnnvvczkhfpe*7riaaaappuytw82@:356541:+;24541#,8rupdghklzxccv", +"vvvvbvvccxzkjgat=0yafghhhhhgfaie=8yafghhjjjhgfat-qpgklxcbbnnmmmmmmmmnbbvcxljhdiw&6eyiiiiiuyte071@-1342<-O-146652#,8rupaghjlzzxcv", +"vcvvvccxxzljhfpr=9yadfggggffdauw*7tpddghhhhggdpr=0ifjkzxcvbnnnnnmnnbbvcczlkgfayq&5qtuuuuyyteq95,+=>1<,=O-<356651#,8eupafhjklzxxc", +"xxxxxxxzllkhgdie*7tpaddfffddapy0&6eiaaffffffdaie*9udhjkzxccvvbbbbvvvccxllkhfapt9%30etrtttrwq973:O%-:;&O=,2466651@,7eyiadfhjklzzx", +"zzzzzzllkjhgfayq*6euaaadddaapur9&5wypaaadddaapyq*7tafgjklzzxcxxccxxxzllkjhfapye7$18qeeewwq0964<-o#&*$o&:13566641@>6qtypadghhjkll", +"lllllllkjhgfapy0&4wyippaaaapiyw8%30tuipaaaaapir0&6rpadgjkklzzxxxxzxzlkkjhfaaitq5$,690qqqq98641:&X+#@X$-,2346653<@:5qryiadfghjkkl", +"jjhjjjhggfdapue8%29ryyuiiiuyte05$18wttuuiiiuytw7%4qypadfghhjkkkkkjjjhhgddaputw83@:36888886531>=#.oo.@&;,1334432>+;39wryipadffghh", +"aaaaaaaapiutrw93#,59qweeeeww0961@:480qweereew073#,7qrtuipaaaaddddadaappiytrw084>+*,2333321<>;=$O o#&-:,,<<1<>-O*<579wetyuippaa", +"rrrreeewwq98751;O*>24456655432,-o%:<3455665543<;O*,4689qqweeerrrreeewwq997642<;%X@&---;--=&$#+o. .XO@$&*=---=*$.@=>1356890qqwee", +"::;;;;;;--=**&$@.O#$%&&&&&&&%$@+.o@$%&&&&&&&%%#@.O#%&*=---;;;;;;;;;;--==**&%$#@o .O++++++OooX. .XXoO++++@+Oo X+#$%&**==--;;;", +"pppppiiuuytew061@;369900q099863>+=1578900009974<@;48qwetyuuuiipiiiiuuytrew0864<-o$-:,>>>:;=&#+. O#&=;>,<<<<,:=o&>3680qertyuuii", +"ggggggfddaaiutq6$18wrrtyyttreq83#,60wertyttrrw95$18eyupaaddfffgffffdaaapiyreq84>+*,132211,:=%O.. o$=:,134555642,+;48weyuipaddfff", +"lllllkkjhhgdait9&4qtuipappiiurw6$29eyuiipppiute8%4qupadfghjjjkkkjjjhhgfdaaiyrq71@-1455542<:=#.O+.+=>246789009962#,7wtupadghjjkkk", +"xxcxxxzzlkjgfauw&6euaaaadaaapye9%4qyipaaaaaaait0&6rpadgjjklllllzlllkkjhffaaiye83@:2566543<;%X#%$X$:14690qwwwwq85$10tipdfhjjlzzzx", +"vcvvcccxzlkjgdie*7tpaadfffdaait0&5euaaaddfdaapyq*7tafghjklzzzzxxzzzlkkjhgdaiyr93#:3676542>*o%=-&o%,4780werrrre06%3qyaafhjklzxxcc", +"bbbbbbvvcxzkjfar=9yaffgghgfdaayq*7riadffggffdaue*9yafhklzzxccccccxxzzlkjhgaaur04#>367652<-O*:,>-O=169qertyyyyrw8%5eiafhklzxcvvbb", +"mmmmnnbbbcxzkhay-qudghhhjhhgfaie*8tadfgghhggfdpr=0udhjlzxccvvvvvvvcxxzlkjgdaitq5#>366531-O-<221>+;48qetyuuiiiyr0&6rafhjlxcvvbnnm", +"MMMmMmmnnbcxljdu-qifhhjjkjjhfdpe*9yafghhjjhhgdat=0ifjklxcvvvbbbbvvvcxxlkjhfaptq4#>36641;+;14553,@:50eryippppputq*8yagjlxxvbbnmmM", +"NNNNNMmmnbvczkfu;wpgjjkklkjhgfar=9uagghjjkjhhfat-qpfjkzxcvvbbbnbbbvccxzljhfaiyq4#:2442:+:2567751@,7wryipaaaaapyw*8udhjzxvvnmmMMM", +"NBNBNNMMmnbcxlgi;eahjkklllkjhgat=0idhhjkkkjjhgay-qpgklxcvbbnnnnnbbbvcxzlkhfaptq4#:132:+>36899973#<8eyupaaddaaaue=9ufjlxcvbmmMNNB", +"VVVBBBBNMmnbclhp;rahkllzzzlkjgay-qifhjkllllkjgdy;wahlzxcvbbnnnnnnnbvvxzlkhfaitq4@;<<;+>479qww085$19rupadfffffapr=qpgkzcvnmMNNBBB", +"VVVVVVBNNMmbczja:rajllzzzzzkkhay-qpfjjklzllkjhdu-wahlzcvbbnnmmmnnnbvvczlkhfait93@=:-+>480weeew06%30yiaaffggffdat-qahlzvbmmNNBBVV", +"CCCCCVVBNMmbvxja:tdklzzxxxzlkhdu-wagjjllzzlkkhdu;eajlxcvbnnmnmmnnnbbcczlkhfaur92@**+:380errttrq7%3qupadfgghggfay-wahzxvnmMNBVVVC", +"ZZZZCCVVBNMnbxka:tfkzzxcxxzlkjdu-wagkklzzzzlkhdi;eajzxcbnnmmmmmnmnbbvczlkgdpue7yfkxxxcccxzljfu;wahklzzxzzlljfi;edjzxcbbnmmmmmmmnbvcxzkjgdiyq6:oX=37qrtuuiiuyr9&5epafghjjjjjgdi;rdkxcnmMNVVCCZZ", +"AAAZZZCCVBNmbcld>yflxxccccxzljfi;eahklzzxxzzljfi;rdjzxvbnnmmmmmmnnbvvxzkjfair93* #,60etuiippiut0&7rpdfhjkkkkjhdi;rdlcvnMNBVCCZZZ", +"AAAAAZZCVBNmncld>yglxxcvvvxxzkfi;eajllzxxxxlljfp;rdkxxcbnnnmmmmnnnbvcxljhfayw7>oX*39eruipaaaaptq*7tafghjkkkkkjfi;rflcbmMNVCCZZAA", +"SAASAAZZCVBMnvld>uglxccvvccxzkgi;eahllzxxxxzljfp;rdjzxcbnnmmmmmmnnbcczkjgair91@*+:5qryiaaaaaapyw*8yafgjklllkkjfp:tfzvbmNBVCZZZAS", +"SSSSAAAZCVBMmvlf>ugzccvvvvcxzkgp:rdjllxxcxxzzjgi;rdkxxvbnnmmmmmnnbvcxlkgdayq3#>,@,7eyipaddddaauw*9udghkklzzzljgp:ygzvnMNBVZZAASS", +"SSSSAAAZCCBMmbzf>ugzccvvbvvxzlgp;rajllxxcxxzzkgi:rdkzxvbnnnmmmnnbbcczljgaie5$142#19ripadfffddaie=9udhhklzzzzlkga:ygxbnMBVCZAASSS", +"SDSSSSAZZVBNmbzf>ihzcvvbbvcxxkgp;rdjlzxccxxzlkfi;rdkxxvbnnnmnnnnbvcxzkhdpt7%3774$20yiaaffggffdir=0idhjlzzzzzzkha>yhxbmNBVCZAASSS", +"DDSSSSAAZCBNmbzf,uhzvcvbbvcczlgp:rajlzxxccxzlkfp;rdkzxcbbnnnnnbbvcxlkhfay8&60q06%3wuaafgghgggdpt-0ifjklzxxxxxlha>uhxnmNBVCZAASSD", +"DDDDDSAAZCVNMbzg,ihzvvbbbvvcxlhp:rdjlzxcccxzlkgp;rdjzxcbbbnnnnbvvczljgay9*7wrrw9&5eiadfghhhhgdat-qpfjkzxxccxxljd:uhcnmNBCZAASSDD", +"DDDDDSSAZCVNMbxg,ihzvvvbbbvcxlgp:rajzzxxccxzzkfi;rdjzxcvbbbbnbvvcxlkhai0*8rtuyr0&6rpafghjjjhhfat-qpgklzxcccxxzja>ujcnmBVCZASSSDD", +"DDDDDSSAACVBMbxg,ihxvvbbbbvcxlgp:rdjlzxccxxzljfi;rajzxxvvvbbbvccxzkhdpw=0tuiiut0&7taffhjjkjjhgay-wpgklzcccccxzjd>ijvmMNVCZASSDDD", +"FFDDDSSAZZVNMnzg,ihxvvbbbbvcxlhp:rajlzzxcxxzljfi;rajlzxvvvvvvccxzkhdpw=qypaaapyw*8yafghkkkkjjgdu-wahklxccvvcczjd>ijcmMBVZZASDDDD", +"FFFDDDSAAZVNMnxg,ihzvcbbbbvcxlgp:rdjlzxxcxzzljfi;eajlzxccvvvccxzkhdpw-wiaaaddaue*9uaghjklkkkjgau-wahlzxccvvcczkd>ijvmMBCZASSDDDF", +"FFFDDDSAAZVBMnxg,ijxvvbbbvvcxkgp:rajlzxxxxxzljfi;eahklxxccccxxzkjfpe=wiadffffapr=9udghkklllkjhdu;eajlzxvvvvccxkf>ikvmMBCZZSSDDDF", +"FFFFDDSAZZVBMnxg,ijxcvvbbvvcxlhp;rdjllzxxxzlkjdu;wahklzxxxxxxzkhfar-eiafghhgfdpr=0idhjkllllkkhdu;rajlzxcvvvvcxkd>pjvmMVCZASSDDDF", +"FFFFDDSSAZVBMnxg,ihxvvvbbbvcxlgp:rahllzxxxzlkjdu-wagkklzxxzzlkhfar-epdghjjjhhfat-qifjjklllllkhdi;rajzzcvvvvvvxkf>pkvmNBCZAASDDFF", +"FFFFDDSAAZVBMnxg,ihzvvbbbvvxzkgp;rahklzzxzllkhau-qpgjjlllllkkhfpe-radhjkkkkjhgay-qpfjkkzzzzlkjfi;rajzxcvvbbvvxkf,pkvmNVCZASDDFFF" +}; diff --git a/hacks/images/tunnel1.xpm b/hacks/images/tunnel1.xpm new file mode 100644 index 00000000..ba1e71f7 --- /dev/null +++ b/hacks/images/tunnel1.xpm @@ -0,0 +1,134 @@ +/* XPM */ +static char *texture1[] = { +/* columns rows colors chars-per-pixel */ +"64 64 64 1", +" c #1b0b06", +". c #2a160c", +"X c #2b1c15", +"o c #34180e", +"O c #361d16", +"+ c #280d07", +"@ c #382718", +"# c #2b2416", +"$ c #392925", +"% c #3b3426", +"& c #4a2918", +"* c #472c24", +"= c #483728", +"- c #573729", +"; c #573c36", +": c #493a35", +"> c #643e1c", +", c #4a1b15", +"< c #584738", +"1 c #4e4431", +"2 c #674d38", +"3 c #605c28", +"4 c #595248", +"5 c #5f4a46", +"6 c #655448", +"7 c #675c52", +"8 c #6e4f46", +"9 c #6a6457", +"0 c #766b55", +"q c #797065", +"w c #3c4e24", +"e c #867a6e", +"r c #907155", +"t c #958a76", +"y c #8e8a75", +"u c #b5a27e", +"i c #a59a71", +"p c #9b9787", +"a c #978c81", +"s c #9ca68e", +"d c #a69b88", +"f c #b49c8d", +"g c #a9a286", +"h c #aca693", +"j c #b5ac98", +"k c #bbb499", +"l c #b9ae8d", +"z c #b9b5a7", +"x c #acadac", +"c c #c4ba9a", +"v c #c8b18d", +"b c #c5bba7", +"n c #c3bcb6", +"m c #cac3ab", +"M c #cac8b8", +"N c #d4c5ad", +"B c #d7ccb4", +"V c #d8d3ba", +"C c #e8d8b9", +"Z c #e4da9c", +"A c #d6d5cb", +"S c #e8dcc8", +"D c #f0e9d2", +"F c #f4f4e9", +/* pixels */ +".:&=<5<:::<=<0evnBDSSSVbdaivnbCFj=*47$=:78ti0eetqAbBgbhMNBvldhkh", +"*$@@$oOO@O#:%**:eMzbbMBbfhdhfbBAh=@15:#X%287=-&*r80sDDMcBCmbbkbbkVm", +"5O* X$.$%1<:$..4xzkkkxVVBttdhhhe<;&&&;02<2&&-8esFFSBlmcmzkjmszk", +"*.$@@=##@X@:%#O@9jghbbskBjdadkhhp2*o=@><-<488:5ehFFSBkBmzmbzbszp", +"=@*O.@$=O@#oo&X$9zmkBmkmVMmgpxjxq1. X&;2<<<@2=2raFFFBulBcbcckhhg", +":#XX@#@@o.@X#$$$7kzhcMbmMzziaspp9@$%=X*:1=,*52&8aFFFFCSSCvuccxhh", +"X#X##X#@@&=:+#%@7mBdgbASzAppqeep4%:@=$*---&&<--6eFAFDSDCDCbckAhh", +" .#@@$@%==:60@XX1gkkhmAAnzsaeeasq#@@#$OO=@$=;=@qjAADDCCCDNbjxhxp", +"149900tyfeyuht976@=97eetqaqq9q9999qe0ihkhyghjpilaq7:6evbbfvdtteq", +"*=15<2@@#=@X=4szzMmlVhSCclkNAe=$*228*62&.@#.@", +"1fNNNABvbkcbFCDDi<262:-7;*:$=#=<=7-*4;%", +"3hfjlubBABSMAbuv9X*=15*,<**@@*O19nbzzMSmbjzAbdpd4$@#. ,@-2-2=:->", +"1pdhjhtkbBSNbdph7..@o:5:%::<+.@*4ABAMCzndhxzldhgqX.o,,&2-;*&-&-<", +"1yadgjmBNcvbjpdh7XOO*::%@@,@O.OO0MBVVVBbjznzfhdd9.X#O*<2-,;-2226", +"wyyydhbBANbjsfph7..XO=-1:$OX.+..9MmbVCBkhbhmhjdd5 .o.118-<,*0338", +"wipddjfbBNAzhdpd4X O$*$;4%X++.OX5mBSmSmblimbjhdiq@o@&*22>2,>2>2-", +"&tkdtdjzbMzhsihp7# .O#@:$XX@O.+X6bbBmAzztcjjhhhjy*2<**->*&o-2212", +"%pdtptpzhbhhhxhpq.@X..@%$ X +X.4xghzjbbphtlzjndy@o-=ooo,=*<<2--", +":ggdatddzbjfpaye7 X +$X... .$X4jhhhbpapphdbjzAd=o,Xo o&,&<8<<", +"1hhzjfnvvzaysdye1. $..$ #. X XX;dpbNbhddgtkjghxq=Xoo&#.o+,@13<-", +"%jhlnbMnnhpaddey4 .X #$+ .+X# c #495956", +", c #5b635a", +"< c #586965", +"1 c #675a45", +"2 c #67604b", +"3 c #686857", +"4 c #75654e", +"5 c #776b55", +"6 c #7c7059", +"7 c #797666", +"8 c #6d736b", +"9 c #445e64", +"0 c #74807c", +"q c #7c8882", +"w c #84745d", +"e c #8c765e", +"r c #846a54", +"t c #8a7c65", +"y c #947d65", +"u c #847e74", +"i c #8b826b", +"p c #898675", +"a c #98856b", +"s c #948974", +"d c #9b8c76", +"f c #9c927b", +"g c #a58d75", +"h c #a8957a", +"j c #b4997c", +"k c #a4866b", +"l c #9a9686", +"z c #90948a", +"x c #9ca09c", +"c c #a99984", +"v c #b49e83", +"b c #bc9e83", +"n c #aca08c", +"m c #aaa397", +"M c #b4a38c", +"N c #bca68b", +"B c #bca284", +"V c #baa995", +"C c #bcb29b", +"Z c #b8b3a6", +"A c #c5aa8b", +"S c #c3ad95", +"D c #c9b498", +"F c #d4b99a", +"G c #c8b8a4", +"H c #d4bea4", +"J c #c4bfb0", +"K c #d9c4a9", +"L c #d7c8b4", +"P c #e6cdb0", +"I c #f3e8d1", +"U c #e1d4c3", +/* pixels */ +"XXOOXXXXoXX#XO@#XO#OOO$#O$##$$OOO@:0ip8O$$OOOO$OOOOOOOOX+.+++++O.+XXX+XXX.XXXXXXO+++OX.XXXXX.OXXXX,8-XXXXXXXX.XXX...X.XX.Xoo@X.X", +"OOO#$==>>::,:,<,,,:,,:,:,<8<<8,,:80s00p3:::>==#--$;:-$->$$$$@@$O#$#O#$O@OOOOOO##@+O+OO@OOX.#XXXXO>888;@@O+@XOX+O@#@X@@@@=@#====#", +"XOO$:=@>->-:=;=,::::<8838738838u63706:3,;3,,3,<8338<368833838833,3<3873<8833888<<88<3<883,<<,>,,88783383,,,,,,,,,,,:>:>>>-;>->#O", +"OX@8mJz7:,<:,<833888z7878<877uz8,3%200l0p03070888833<,,<08,23,-83,,,,,,>,$,,:3:,,,,,,:---:::-,33,,33:--:,;:,,,,,3,83383888838<>X", +"<3slcmllllmxmmmmGmVSmVGJCCCSJCx;--,0JFLLKKDDPVDCKKLLKDKGDCCnVCCKfnCZGGCmGCZVJZxmCZlllzlmmzxlzx0:=-,8pxlzl0nlllzxxzpzulzzzcxusuu8", +":,sccllulvcSccGHHSSHSHbGM3-37:;%-;:8fDDSDDFFZHHKKCMKGPKKPKCLLUKFLLHLKLnKKSLScHGSDCGVmLCNVscSs&=+++OlV5lhVnCMGVVVmGGVVcVmmMnSGcuu", +"qslluyscCcvcVSVDcMgclcMASt;3-%8=#%#7Vc4nfMghhndMlhMst6lsn0isis207;fNcawdVCMChsasVSCDnfidMKMhfs@@+@+laKSnDcDhjNccdvallheySMMyccuw", +"ulVulzcyytacttdauycuySVcggGatcdX$-#zKMFslnMediahfhc6clfaf36nipff3iddinnaisitMsf7iwuiMs8dGcdu62@X@@@fNadjdcydhdttlslcvhchyyyyuwuu", +"uwu5zsdhVglswccccMadcdf6tt7DsclX@#$zKhhhagjjjchnNhhViaasfMMnhdhiMdchaNdhh6cMdvhhNsicaicChSdSin-XX@XchggggsnanacccNchslffdlcgluz7", +"wullnycctuhccSdscscehfhjds7ttp6X+@@mSAdjDAhbABcienddDdhDniiaNwgjfiaawdhhlcsaDggcchMapfDVFcssa6XXOXOmVjchMggdccNhcyvcccvcvuglynly", +"cyctsdcsfgyygircwiiinHhMSadn2ipX@$$LNjhhgjDbjheMNDSaaaDwaNjheVaf4gh6hhi1iwhaBhhh6addiwihntiiNt.XXO%nhjjghjhjhfVhMtahfsahcngdgsgs", +"VugyftftgVclhhsccGhnM5nhawr3o58XO@#LadAASAAgghMShNnhjNhgDdhaMiaFAhMFSBSSDaBSjhgAhnjMwiiapliyttX.++:ZBBNvhgcgvMcvccvscccdcglgydly", +"ulttslscMctsudldafyacnihwsM3Vi:O@$@ZhHjjagADgBkjjgjghBaiaahgnhhjveid6adahghkjjkjgaygjc7d7icDS;o.+O8GSjgjaccdchdhhddckihddcfhlugd", +"lylgddtd5tcasdyCditah1MMdnncd&-X@@#ZMDBAMAgkjBAAaDajjaihCgajCADg5iAihhaNhBBhBagjwgaMDscMMnchg;XXX@3GSjhjaggcghtvyhgscccsSylctnsc", +"gnluwgcdfhcmvMvhtclhMjhid&s7c>-X+@@ZLAhghjjgDgjeMaNMMDgh6haMjj5;6ahidjNjrjNAjhyhSgt5a4sVGscat2X.+O,DMgjNghvvgchhshhvvidtacgsdtyd", +"dt6tactfVtdhssdasfansicincfth1;oX@=DDjhDagAjyhjVajjjBahaNhn62hsMDji5hh6iNjgkjkDrghVKNcsNw7ihd3X.+#,nhgdhcdddadpiahghvdhccfcffhvd", +"2sdflhss6dcwtdtsdcMhanwc6iahDn2X@@@GGycggcNgbjjhgvFjaeMAhhaA4udgiadNMgMggyjghBaAjk6*2csstdmcd8Xoo@>SMbggedihMassgcgktcdndaisseud", +"sfcsdiwsncdaasgtcddMlhMMamthh2=XO@@GFbgygbbbgbjkvMaakahgB4dtSMrhVehgcs6HDaihhajhjkaKjaGMKstp53XXX@=GNgygMcjhtghdcf65cdaahhcciufw", +"tdcaiMfwtdsaVatdifdjahCaM6nsdf@O@#XJGcygMgyvahjSSgdhNBNd&aMttrvkiFFcwwV4;1VNkBrgjhNiaM66tut3t%.XX@XVbycjavgNcccdtsfffsddacapadhM", +"diahdhijnatcians6Mi3indadfhiht3O@#@GAyHygdMttbggaavjagggfVdcSMhthi6hPh4npiSahhasa5aha63ivNlvt;X.XOXmgchhvchghagvcthcgdddchhftsg5", +"cisahhldhdidVMhCDnifmfahnMMdhv&XX=%GbFyybaykHvgjgFagnddgDgig65igacVa44Mw5Vy5n76666adaffAHctgg;XXXOXmAhyyehcvaca6bcdidcdstshdniiM", +"6schiwdwntnMwahtawai5anhiiadhj-OX##mFgvbjyADbAgvhhahaaAjg45gChyiahawhhejaAMjh;i5fwsaffwhc1ccl:XX@@Xcgagvchbadywc6yhsth8ldgsaaica", +"wsaddeiafahwaMdiadaMChjCwhnCMh%OXO#GAbcjhSgShvhv6kNhahjtaaANhaNNt5gVkhacaihheNhMsiagNMNMVMstc-XX.#XmgyhchcycctNaMic5cs5cdcydfhid", +"DsisidfceawdcMwadFjn66niShVwth&OX@@HFbccykvgbhvwShaawwi6thwtiMwgNggyjiaacaaaa5hjDjNhawhahh1swXXXX@oMchhhhchvhcwcthdcvtccchnassii", +"ttc5ccauiicjdisict3;sccafnacngtX@@=UHSbcjVbjekyhaat4jFjavgVhNtaceaBawcVgvdMghjahhaghafScVMsfs=XXXOXcMryVaaMyMegcivaicahgistddwss", +"Mt56ligyvhcaaMdatf1lthgch6NdMg5@OX>HbbvyhAjkkDnhaiNDhjhhh6duytdtai4ahadecadwSNcfwdwsy525gtist3.XXXXGcvgcwDMMeMgtftihgtcldfhvdgha", +"tifMtthvsccwcwdvNccsndudycSgajw#@#=HPKyvdajaBaghejasghgakDdthsMtdMidgaaDdnNh3;1wwf6CDnnhh83ty:O XXomgygcBaahtadcdhcdfcdcdcsdyffs", +"6cttn5ctst5ttscdbvhMhcvcccvddNf+@#=JHgSbajgghhBaeAciaBMSttdhatitaihDwa5t1dtntchvhsVi4wMMcvdcf8X.OX@VSgygtdcdcaieasdhssyccchdzydf", +"cifsssfzststcdBNtdffhs6tVgvadA2@X=@GjghgCnhdaakcBjagh5ctMdtdgMNnhhg6ccDhSc4avv6iaVjsfniMscdvgfXXX@ocgyjjhacidlcdhdtcggchhiycscgl", +"tctfifd4afacnNgdDhutcfcpgNdScN2XX#-JSFDdfgagacMaecDggNggecsghaytah6sBSitgwcvhg6cag40i6ai1;uft%XXXOXNDewjyvMSvctstsgtcscgdlcsdhsf", +"mtcsfauhnMcfc6Sau57mthcdcMDaVjc-X#=GHbaacDggwaghDtehcccgetydgwVg7htMedicjNSgcacsfsMcNhhfcGcts5X XOXSbAvghgtdtssdhdclachccahisacl", +"slccfddsatdftdrdlwVcf6ucHcartbdXo@%SjbNVghhcVGehaaVdtiasynMMctsctghcA6Miy5edtMct*wwf0wMhwvcvc&XXXXXnbASyyacdsiwuchyilhayfdccfacg", +"t7fwthasCsiddcft7cw4uwdhpwVlVF5o+@@CSgScgvcjStVhNcjcvMGvVghcafhafSdccMrlcccvCdwhVMgydcgtgc6hc5X.XOolFbycccgydycsttncdtfclcdpfdia", +"clcsVdlcidtptissmcwZsncsdiadteh+@@@cASjgcfvjVeaDacNchcytVcMd5tcncatcshgytdhtcyahctlgaMdac4ss6-.XXOXZbbyegMMguchsvlsycccfstsdciic", +"6gdcdtwttsMhsccffhfiuscMsmmcnjs++@@mgkghhcuVhScMDcfdMtVncastVVjifsccassVcVMchhDgcgcclyysvcScc;..XO@GSyyMyyccccdcs6lgfauscccfcscn", +"ccdsgsdmccsualddhMidncMhflKsdhioXX@nFAjjsdchcsSc73hVvfaChMcmaiMacdstccgauwt1fwdceec6cydcyNyt3-.XXX@VbGuSjgyuvssdccccfstsctltscss", +"snssscgutddtlMcndHhldfnsfi4Mhido.X+fDbjadjVds6&t6ifcddjadcsctvaNcyptw6MawvdVMhtgSccSvvSbNvjc73X.XXXVguMyAbccueccudfdffsclcchsdfd", +"nyyssdlvcccSccdti6fhhAisljVaaD&+.@OfubAje5wdanKVLD6ijnCniGgAFNSANhvSDHjVhHvcMMVDbvNySutd5Mct5;.XXOXmbbevcctGcNycvccccfNcscsdtdsa", +"nlldtutw6wi61afVNi3taictfeeVa5+.XXOps6g5thc6dcyyjdsdhhMNcchvtitwadNidyahNAaaaMaht5t7MvdgVMaal>XXXoXmvygVagcMbcbcidhfpdddfshhfccd", +"8553533323;333;2;&&-&-&;-%;;+o++O#X83o@%%%%@o%2ldafii522&3556tyHtisc6p7s4uii6piw7ydF64s&%;ac;@XXXoXmcVgycllgygldfspttutiuiii0667", +";=%-@@+@X@====%@#@#@@#%#->=%-=XX@#O38+@@@@+#@@+o++++@+@@##@%%+@@+@+%%%@@@@@@@+@@o=X%%:@%#@XoXXX.XXoz42&112=;%@%%&252;;-;-;-%-;;;", +"XXoXooXO@@+X++XX%@###%@#;-#-=XXX@OO8;73%%@%@@=@%+++@@@#@#--@$@#@@X@%#@#%#=#==@@@=X@@XX#%X=@X%#X.XXoz,+X@+oXX+ooo8XXoXXoX..ooXo+X", +"XoX.XXX+oXXXXXXXX+XoX@+oXoXoXXXX#@#@.@o@++@o++o++++++++@@@@@@@+@+%XX++@@@@@+@@+@XX==%XXXXX@OXXoXXOo=%=XoXOXoXX@XoooXXXXXXX+XoXXX", +"..o.oo....o.o.oo...Xooooo.ooooXXOOXooo.Xoooo+oXXo...oooo++Xooo.oXXooooooXXXOoo..oXoXooXXX...o.o.OOo. . . ...o . oo . ... .o", +"o X.........o..o.X.X.XXXXXoX.XXX@X@XXXX.XXXXX..oX.X.OOX+Xo+.......oX.o..XX...XX.X.X o.o.. . ..XXOOX. o .o . o ... . ..", +".....X..XX.+.XXOXXOXXXXOOOOOX#O$$$##$++OX@OO@OXOOOOOXX++OO+OXXOXOXX+XXO.O.X.XoX....XoX..X.X.X.XX.X.o . . o o . ..o.", +"XXX+>>>>>$>9,9,88<,,<<8888888z89X#>8ZUZ0<,-->>>>#--#$$$$$>=$-$$@$@$$@$@#$OOO@$$#OXOOXOXXOXOXOOOXOO$O>,=XoX#o..X..X..OOXO@X##$$#.", +"+X+8038ppppsmmmpmmmlCmVGVKSGSccHfmKSciMKLGcJZmVZZZKZZZZLLZCZZUZGZJmZZZGZZZZZZmxxxmmxxzxzxxzxxq#O#9>xUUUGZxzzzu0u088878888777u7#.", +"XX,Z3sVVMJGgSDPDHLbcGSHDHDDSDPShHDSdcGNSjSDcybyFSbSMytydsgjkhhctw7wMMayyMrgrsyNbFvFPPDhcMVSyyvu=uGcLecclrcbbMDSvSVcmVDMMVGGGMfXX", +"XO8spvNJGvhVHSVcvcVHyLVHDHAKgheShtvyVNDHULFPHSKFAPSMDHLHHDKHckVVPKFPbDLLGLHLiuDcSAaSgHHGPSGHclyGHwccHHHSHHPGHcc7tnc4Vigacygggu%X", +"OX7tgHcdptmlsslncccMyccDcVHaDvmcNztSncVyscPyvKDDbyMycycagvcvaGPBwFMccvc2u1yNgNHDHGvjPbaCyudvGHwwmmSGcgdsltVSHHMhwlyLtVVcdsscv4oo", +"XXzcFyczyhyastdVnycuSbgl4f7amAsScvVceVMsVtdhccgygMVSSdgMSu5djvwNhcs5vCVwGcMwtMaGhHvhjhMnclcMmlMGgJVlwcrllecccbMVSNGcdhMfwcVNs2X.", +"O@VgFgtltDCcVdVitdnnclgcVnSnDGSMMVylmvcwVcsDSgMMhSjcbcvvaVcVNvckcgbSGvghbvcgstcvcvMSNSADNSymyccMGVcyycgAgGVcclsscvcdMvatcgdvt=XX", +"O=GcSccctftttcfVmStylgcliMcwMtaccyyyySccacKcvMhMShddgcbAjtcg6chDcVghdtNgVAvgctSNMavecvAvSScSVcrvrgymgJgccyydcsygcchcddMcs2cgy;XX", +"X-SyvccucdtilccansmccMvMKchdaVchlyGlbvgvhdhuyhMVjdkSDyySccahSyctdgdgVNjNahy5lbDSNraSyASAVNScgVVcgdywGycdytmVyVVngccccf55tDvNw&XX", +"@>Zbvy5yn6pcMsMcacdfcSscwMVDGhhsMccncDSgaNccNHNiasbcDDHcNydMcMhvVGShgyvASGassVAgMhGahHDhySuGMVcgcynVdwygcGSychscdaycuwasVyau2X#X", +"O=cgbydsctmffcddcdfdC4MMMhc4thcNctyyvNaGMiSAhh6cVhftygySBhhcydbhADMNgfSadyNaMgDDec54Mhh1c5uvlruclcaydcSvgSgbjsccHdaChSMctitu3@XX", +"@#lSGvcldsycn6scslMcpChnaMcfccadccgHhMcaMchhtccyaatvDVVh5MGDjvBvA4sDrMhyjgvNVgvrtgch4ec3ucHvchgcswdtVcyCghySaMfvcshaVt6ws6lc6;XX", +"@XsvgdtuivlacsMdMds6hwStwdMhMdMFVcGcCdtfaSvGhSScNcNvgyDyNBkvSjhha7lgcDjhbehSyAthSbSFPFDhUcgSSSSSgaHacscsdNvgdtyccwtf35lcvsftt@X.", +"OXzgbhscdlMMaCitstMgcdhMnMMVwaadcc5cccgGSNhhVtchvGHNhjvAgaGBeAgaHtuytgvStSGyhKckhgDhNjwagrcScgMMvcgNyGySvaahhcceahncccdtstcf5=.X", +"#XpvcrflissdfcincchsMdCVahhaDCMVVvSdydjDSSiSNGjDhaytnSSe4SddSSvcNitdatchkFbghaaLSSjVhhcVStSctVcdctMgdahtahgVg7dMVhattyvcMsccu+X.", +".@zcv6dfdccVMvMVacSVcNcatsadjehhvcwVdaNbijKCkhSAjShyMhhcvAvayaMvNNcHMMjcdycGjASaSHva4jSNadHyMVwyh6scdh4yMdy4yhdsjcSacdtptff65@XX", +"@XuccthcsccsdswccVgiMhaSKLLSiaCdHgKyNujcjggdtDcaFhMVSdighAbSHSyAhhGScSjSaHcjvNHNMdvcSFNvSMyaghwVszVvaMSvjhSjSdcdVatthdgcmssst%XX", +"XXlthhVsfiaccsCaiaMcnfMwngjnMVhhgvlsMMftvGtSwhdNyVjjaGGDSDcMSSADvvbtgaSSNSDAAv5jaagycMgvbGHHNKHgvtVNcdddaiwacivcNchvVcMNttsct@XX", +"O+z6gcwztsVMaacsMfhMetsjPBghCNSGa6VtctmcFdhSNSchAgvNtNhADvg5jhvDtHVNcNgkyg5ucgSjSPSHGtDSgVMdGcyyacywycygNgbyycahgtfdtypsfc5h6%X.", +"XO76VcdtmftdMMDVMahMasVaBFA66hihMGcGcccjMSMgBggcdSSNSvahAADPFcvyAFScVacbghcbHcvShgNyhbGyyMSctycgggkbVyjctyhjhhjMcLwtcMaMhasi6%XX", +"O+pyBtcMi6nnyHvDdaScVMSaAa23iSFDgacttdSLtVhSgvFSvjahvahvyevFNvADvNASaaGcuSvFawDabvcNVyyHGcggAycttccDtdhattthiytcattvMdch6usc3%XX", +"X+pvShta6tcinchtwsnsgNaNh62idnaScyfdhchwDhaNVvhjgNA6GcbaGbAjwhgjvvdhGaagDSFNNcaycbbgMDGyhyHNdgyvSgygatvvcvNNdtytvhc7gidtctdv5-.X", +"X+zKy5ssinchii6t7dsdGhSdaGCgDMhncsVwgNDDgaaStcSDhSSyavNhagjyvwftdgVdyHMySAyhtVgcbgtdhlgbgcb4bSSvg4vStVt1iiSgggVidttcySdvnddu5%X.", +"+XibncMgsavtcvn5picSMgjMVehjM6cDcMyvKLHMhdScatcrda4bShdeFeAbggDgNSSdydySStvgywjgFvaywt4gegbDcc4gVjagGycwcakNMaMdcatcachdddsf3%X.", +"XOpgsctpmcdMhcs7sfLSDMSjhhALhdHhyvcSMrg5tiDBvhdcvhgkFSSPhvjgAbDjPyddbMyaebjaDKguggvSHDMjSMclycuvaAVysckcdahatgidVhDMhMguagdc2+.X", +"XO7af5scycgcMcthdcKDwMNhVKSwSKhNGawwNSMLKKSNMDvhcGaKgkaawbFbgbAagccjHcuSddArDebvSgljcAbMSKgDvybyatwacajhgc4d76aMggctsaMcSsMc3X.X", +"#Xugccc6MMddhssGVLDwifhMhniNhhhDyNNDvvAbddyyAaNhvvSttSSSAKajFMhASycgy5bHcSbysMHMcjaSckFbrNvhNDjnNjDadVvVNvDi5wnaccdfcifcdaa7;+X.", +"XXughdtddhcflcdDNVtjVKgcjjhMDfjhCyaGgVDNMaShHvS4gcglMSFShjAMjDgBgjvgFgbeybjGSrgydHbavStgSgNNccNvycyavNg6MySbhDg5ccicMMdccsnw;O..", +"XXzHatd6VcccaaKDBidMiSVhMCDhhCShcc6tcMacScFFvvvDvNgaKHjgahnhKaehbHbcchScvSHabLAGSgMMSjSgNPcMMSVhyNcvhvdvhjvhhgvVafhadaNVtadu8@..", +"XOubgdtfsdffhGtttdjnhCcSjnhgjgFwcaHLKSgvyNh2aGcgdyFHAkMhBNhAjcVjbycbSFAKNSkyreggSeyHGrbSScaedthnGMgNDhbgvNcMcvctsvcGVcMhddiu2=XX", +".OpSatwSinchScaiVNMGhcNnjDjMnKAhGSSNgSAvLKSnygtSHSyt4vcFMMeiSajNFSjSgAArkHvHGFGvbVScjKFDgcStGLVKdtSGchDcVFcvS5cscfdtfccalca7,O.o", +"XXihw6MisD6hiVcMVcMjKVDdAaNDnjDFbcDNSSjHgldyDSNggggDSbdkFKHFkFAjygFgHSygAycSvAyvggggbccyhGHcasi4tGv62tMttyantsVssccvatscfwci@+..", +"XO0AdacjnaancdfVchVSNMKNMVhidhNaSSvavgGadchVASVvjMbSHkgciawFDjahyHSvdHVFSMvNggdgvccHyVccVNjtVMmhDAstclSvyccgccaccfS6ddfa7cs;-X..", +"XXpNsnDVMcMMMNcShGdGhcBNHDVGPLhKgGdcsGggvgcgSatAKNgMybLdgCnaABhkjkyaMtvDgyFDPHDHgbjPPchDVFvVMa6MKa6PhdVgglVSvcdctcShnDhcMas63X..", +"X#pN1rttsyffstcaVSFhDSnKVhn66iwhScyJChSSPDnDKHADgjPSjSjcDgFKDjKDAbDKMgDPKSNhjihiDFNhaKjhVhgaGLiSafhhFiichiMtdVtmaahcccahwc7t,=o.", +"XOpVultt7u723;1722;;;232266;,;06343542d6a6pt45iwaDfhsasNKVhiMBaiSDjtwtcafdwhei0lBhajniiMjnFShHKKnpDNhCKCaDDMNhNvcMS6kii572;%-%..", +"XXzs7uut7333883>3::,,,:;;--;>,::--8:;-=%-=---=;=--&-&%%&;&&%%&%%-;&&@@=-%;2;%&-%&;&&%-%-;&&&22;&&%2%&&;&%;%&;3;;i127;3533#@+O-.X", +".X85,257,33,,,,3-;;-;-#%-##--@--$==--#,=%-=#----#=-@==#=@=@#$%@%-#=--=@@-#@@#%z-@#$$#-@%@####+XO+@@@@O@@@#@#@@@@+@@o@++X++O+XX..", +"XX8=#===%%%+%%@@@@%@%X@%@@++@@+@@@%@@%@+@@@@+@@%@@+++%@@@@+@+@++@+%+@%@@+@%@@+-.@@@@#@+@+%@%@@++@@@@@++@X@+@OXX%+X+X@++OXXXXX@..", +"OX,@@@XX+O+XXX++X@++@%XX+o+o++++@#++++XX+++++++o+ooXoXoXo+++o+o+ooXo.o@o+++X+++++++.+++++X+X+o+XO+++Oo+ooXo+oXoXoXXXoXoXXXXXoXXX", +"OO$@@XXoXX.OXOOXXOXOXOX@+O@++@OO@@@@@@++@@@@@+@+XO+O+XXX@@+OO++O++OX+.+.OXX++.X..+.+..ooXXX.XXXX..X.......o.oooo.ooo.oXoXX..X.XO", +"$#>0z,@@O#O##@#@O##@##$$#$#$O#@#@@#$@####$#$$$#$$@O@##OX#@$$@O@O@OOO@@OXOOOO@OOOO+O+OOoOXXXOXXXXO.+.......XoXXXX+XXXXXXXX.XXXOXO", +"$87zizp0z7708zzzxzxzzzzzzzxlzxz>++#-zxZl0zz7<8883<3>:>>-9>>:>>-$$$-$$$>9>99>$O$$$$$$#$$O$$$O##OO@OOOOOOOXXX#@###$>=>::-,:::3,8=#", +"z7ZLf5307:833772ttsMu7assfVmcms#+X#,UmZPIIIIIIIIIIIIIIIIIIIPIUUPULULKKLZLLLJJKZmn8pp3,808q0q8<$X+@$$$$O$$>>:>->:>,,,><:9<<<<<>8q", +";sSGLGDDDSvGHHGGDVDBHSKSc22t5;;#O+X:7cyPFFPAFHPHbPDKDNvABDFPFFFPKPHLKPFNAFNDjAAFDBFCGcfjVMtVVcX@@$3ZxcpmmzfucmVZGCCclzcmzl7uzz58", +"4cddyiBNScjAAAAvDFNFHFAjSHNs;3c@@X#3l=vPPKaFANhBAbgAhygBhgBhAgjjhhaa*hgw6i206aiaSh6wtAFAvrMhc8..O+pi3lsia6KPDFSABbbFbSMhgdtudcyl", +"HCtDgNaadaFSggVDjBAgjhNvAcyHHZ2o.#-8d&sDFhshNvNSjbbgajjbjAjAjgkAbkhgjggArBkihhagvgagSgAjwhFa5;.X@#fnw6iKdvFhAavahdaghags7tdzccMG", +"ctcdhMghcSardcg4hatdc6wctsGFgDcX@#XZHSHSgcvbhghgbjBbAjABjAjNgbAjjjjkhjAjjkjkAjhkagjbggjPFBjiH;XXO@fsjnHDDSByaveh25wvta16;:46Vaht", +"disvdi6wVhhNf6ptMhSshnlcSggjhV5-##:PUHPjcvtgvcchvjgNjjhjaahaykkgjkgAjFjjjAjAAkhNhgkAAgADjFkja;.OO@ldjFHhyrtyh4wtccaahdgu-3cSyats", +"cshafdahahNa6vhchatSSsjhaccvvct=##:PbKjhAevDvSgMNhAvkNjngjjahjgAkjjjjjjkjaahkjjjkhjgkejkehhD*,XX@@nbBiwachagchfSjAgkaaNp5Svajttc", +"tt6tacthFhw4itvB0BAihDaBhBABaf2$@@;UKajAADMNajjBMMjNNdvvMjvhvhSSNDgajgjjjdFjjhjhjjhjjjhjAaja*0XO@-Gnyadajhajaa0ahkaaijaahAiaaahi", +"ca7MhejSah606hhABBhf0aFhfMhhAN3-+$$PFPjjaM*fVDDAvjjNvSavjBhjNAvAjjgFFjjBjjkAAjaaajhjjkkDajhAf*X+O%GgghaBi0aaiihhiaajaehaBhajhjha", +"d6aidisai6ahhBhf2iDDFDhA5ahivi0;##3UiaFAjMGCNghnBDDAvbMvAahBFAShBhhMhNhjAjjjjjjhhjAAijhaBAhj0%XX$@CgahMwiijhjajahaaa0kjhjhAhhiah", +"ihhj6chajh0hhaAADBiDhiFf0aBADff*O@;PPPFAKjjhAAVDijSDgFSvjADvggjSDjjhjiDFjjhhaNhFNajhjjAkaiji4%O+O+Jgbi5sijiahgggjhaahhjahi0h4fa6", +"iajhfaDjBhDDhhBh0ahvhFCBBhh0BC*$+=3Pj5hhdhBjfNjBDbjDbHAgNjjvjkBaiaAKNDjgjNjDjjhdaDNNjhADAAh*&-X+@;ChAgbkDihh0hjkaahhhhahaiBBhh0a", +"aMaiMMNaDBh6hAhvaBhi6hhaBFBhAh;%=$,LjjPjjjAANNBBbkSvgAhAhMAgADSddhaahajNAhjhjhFFFNNhjahhjkh-@-XXO-LjDjahjhh2ihhhr0ahihahihah6aij", +"AghjjagNBhhfNvaDBAFvDAhBAAiAaB0%@@&KhjDFDDjACAjjSFDAgDgSjjAhykawLMFhDNAMjhNNdjjFjjjjajDAakh;@@+XO+HhaekiaAja4i0rjjAhhijjNihahfa6", +"jahiighh6ivhhihhDABDFaBFhfKAA0*@@$-PFFjjgghDhASjjejAvAvjNMBggSSca5SghkjhNjhDjhjahhaDihakDh0:20XO@@GhBjDaaaahAkhhkjhiajihaiaaafjj", +"nd5ijfjDjNfsABaahhfhAFAAjK6hh;0O+@-UKjPKNajjCjNNgNvbjvhFhgjgFANDDBKDHDjDjjMhhCjjjjhkjjDAak0;i%XO@@VagjkhgaaihDjaBa40Bii6050haka5", +"jiNNjhhjhh00ejhABfjhhi6Ajhaf366@@@-PkPDjjFPjCNjfSDFyAADjjAkDVjgvSAAAgSBFhNjjjjjjjjhAjhaaaBja0;.+@#mBAaajjnkajjahhwahafhBahBjajBB", +"hNhhhiaa040jAjAAhA6hAFDhBDhN;fN:O@2IKPjhjFjFCjjMShgFFFFDjgFNHVDSywDtDAkgNjjDfjajDjFhjkjhjajaF0o+O@MDhae5iNgjiakjtavhhvawBhhaBh6h", +"Cahijhhh4haha0DABaBDFAaaiaA60JfO@@,PjAAKDhahhCKjSvhvjFAgFgFhVyhtSMFahjhFhjhhiajDajhjjaFAAAaBh&+++@CgadshgahdaifaiaffAwhhBaaii5fa", +"ihdajjhNajjjFAhDaAfAhhDi0iD50i*@O$0PPIFAjhDNKAFCMaASBjgagjDMahjSADvNhjggjfhjjjhkAjjkakjAjhBh6%XX#+MDVhaSkkkkMNjjht0haaaBkihavhBB", +"aaikDjahBAAi0hhBhhhAvihKFFKBwh5X@@6PPjDjjAgCjhNjgShaAghMKvgyhjAhyhhahKDMjjjjFjAFjjajAFhaBjBBj&XXO@VBw5jajgigiakihhB6jahfwhhhaaai", +"NghahiahBA6ihahAhhBfvihahAAAPPfO@@jPAAijjdjhsFhCBkVgMshNjtDvNhdMbLggFvcvhkAjaAjajiAjjhDhjjhi4+.X@+CgyShhagNhajMahhaai0wwih00haaf", +"fadhjjhNaiBBAFBaAAihDAFDjAiBBh%-+%NFjPKKjjCDDjNiwfcDDNsNaNMvMgDchajASvghjCjjjhhjhDhkhjjajhaFa%+X@+mhfi44hgaagj0rBhBtavaaahfAiava", +"Df6hhhajBaiah6ihaiBBBhahBhFhAFi7XOvPFjFBhfhBAfNNCGDhhaMCDKaMgDFCMvcAhhMcgjjjgjjgi6ahFjkhhhBji@.+OOCaaBhDthhhtifhhataa6iahafafaif", +"AaBBaahBhDBAi5iAhhvBhiFBhhFhKhv3++fKBAjFjBDAjDhihADMCjDfhfsGHahacjhvvNVNBANBghghhAjjjaBAhBjh6%XXOOCahaihi6fhhBt66aaaChhaahiBaDhh", +"hBafBhBah6aBBDAahi6fBBhD6vBhhAiO+%0PFFFjDjh0MhhDAHfhhDjpNjMhaCDHSbchhdaakwhaiijBAkABkBjhhBkB**XX@@CvaaAahhhhh6hv0hBfhaaffhiifiBB", +"ihah6ihh6Dfh6hfiAAKKhhaFDhhBFh6-+@;PFFBjahAKhDNhCNfajfjDFNfDjafhVgNSgjASDcggNNjBhaBhahhABhBB0+XX@OAhAh6iaftBfi6hva366ta6A6iihii6", +"ii6ihfihifhfhDBi6hBfBDFhifANhBf*+%2FKjjBBaKDjjhFHMMFMMCjjMJhjKCjeccjNghBhFhBhaedAvaiBhahajAja+XOO+DiahBahaA66Bhf6afafhah6ih6iiih", +"AafhihDfBCaifiiDDAKhDAihhvDCAh*O+X0KKKFDABAhBDNfMhNDjNjhhfhHjfhhvNDASjBHShhBkAhaahjjhBBBAhBa5++.OOCahAaih6a0h6iavaNAhi0faBfaBBfa", +"AiBhFAfBhaiBfCDh6CfCBhDFKi6CBi2;X@%KjDDjABDDNCAjjhKjNDjNCAfFaDhjNaahgSBijhBhNABKFBBAAiahhjjBv%.XOOn5hht64hhBthiBhiaaiaffiaiiiiih", +"6aiffiBBfBfDABiaiBiB0DKDhDNNh*;O+$-APPjNBBFjNFNNNhNDADjNCjjNCjCfhDDSShhjhMBASNhaaBBAhhjjBhjj0++XOOCfBj6vhBBaihhh6fatfiaBBiiiihha", +"fiihihf46hhhfChCChKFDhaBfBKADhf%+@@HFKaNADDANFjACFFHahDDCDjhjhjAjFdjDhjjNDjhaaDhBhAhaaBajBAh2+O+O+Cs0a0ahahwvahifhBAhhvi6ii6fiaf", +"fifiahaBBBvNBANNABBBBDhDFKDAfaf-@%%AFjjFAAjCDDjADjAjjKDjjjFAADCFjjjDhFhjDhjdjFNaFhhAAhABAAh06%+@@+CiAjjhDahhhhavhhai6i6hBvFAhfai", +"6iifCBBAhhhNBhChfCBABAhvAfaAh*3;%-;hDjBAjNjADDjaajjCDjAAFAjFhjjjDjhjMhjNhjkhAhhjaajhBBBaBBjhw;$$%%nfhBaai0aihhaa66i0fiiii66ii6fa", +";36i66i60h6373if6iiiiiifBhf326i--&-0h3sjDDFKNNhjCNjCAHjDjhDkhAjFjDAahjjNADDNFjhjhBABBBBhAAhh5%@---n66tahahhhiiiiiiifaihifi6336ii", +"-*-*73332;3333*;3-;2*-;*-***33-;---03;&*204040242*2i00aihhjjjDjajNDNFNFAjaiiihMFjjBDBAFAAAjB0*2;;2l34s0hh0taf0iifhfi266i6632333;", +"-%@%---*-*%%--%%%%%O+%@+++O+OO@O@OO;&+++++++++%+@%@%@+o+++@@@%%%&&%-&&&%%%+@%&*2562**%;**%%%%%@@@+0;***2***3*;***;;*%*-+%%%*-O%-", +".OX+-OOO++++OO+%+@@@%++@@O+O++O-@$O$@@+@++++O+O++-%++%+++O++@@+@@+++@++++++++O+O++.O+O.+X.OX.+OOOO;+XX+..O+.O+XXXXOOXXX+OX+O@%OO", +"O.O+OOOO.X+OOOOO+OOOO+@@++O+++OO+OO;;-+++.ooX++++++++++o++O++O.+++++++++@@+O++O+O+X+OO++.+.X.XXOOOO+X+OXXXOOXXX.OXXXX.XXOO+@O+OX" +}; diff --git a/hacks/images/tunnel3.xpm b/hacks/images/tunnel3.xpm new file mode 100644 index 00000000..b438f701 --- /dev/null +++ b/hacks/images/tunnel3.xpm @@ -0,0 +1,150 @@ +/* XPM */ +static char *texture3[] = { +/* columns rows colors chars-per-pixel */ +"128 128 16 1", +" c #8C7D6A", +". c #8F806D", +"X c #91826E", +"o c #9A8B77", +"O c #9F907C", +"+ c #A1927E", +"@ c #9F9280", +"# c #A89A87", +"$ c #AEA18E", +"% c #AFA291", +"& c #B0A28F", +"* c #B6AA98", +"= c #BCB09F", +"- c #BCAFA0", +"; c #BDB1A1", +": c #C0B4A4", +/* pixels */ +"&$$$####+$$$$$##$#$$#$$#++###%**%**;--=*%%%$**-*---=*=****;==&#$##&#$$##@###+#+++######&######&&#&###@#&$$&$#$$#$$#$$+@O$#$*****", +"$$$$$###+$$$$$$##$#$$$$##$###=::;-;;;;;;-%#$%***************=&##$##&&&####$##+##+#####&&#####&&&#&$##@#&&&&$$+$##$$$$@$$@$%==:==", +"%$$#$#%#+$$%%$$$$$#$$#$$$$$##*==---*-----$#%#%&&&&&*****=**==&$$$#&##$&#$%$######&###&&&&&&##&&&$$#&&@##*&&&$$$$$$##$$#$%#$====*", +"&&%#$$$+#%%***$&$$#$$+$*$$$$#===***------$#####&#$#&#&*****-*&$&&&&##&&&#%#######&###&*&&&&#@&&&##&&#@$&&**&$&$$$$@$%%$$$$$=*=**", +"$#####$+o#######$++$$$&&%$#$$*==--=*=---*###@+#&&#####&&&**-*&+#+##$#&&&$$$#+####&##&&&&&&#######@#&#O@##$+###++@$$#$$$#$#*;;;==", +"%##&%**$ooO+##XoO+++$++$$$##$=::;---:===*######&#####%###&&&&+++O######$###$#+##&&&&*&+######&&#&&***@ O+##OX+++###$$$$$#%%;;;==", +"***=====%**==*@####$++$$$##$%=::-*-:=--**$$##########&%#&#++#++#+##+##$$$#$#####&&&##+ +@ #@&***:-=-:****==&####$+@+#$$##$*;;-**", +"***====;======###++$$$$+#$##%=;==--:*-==*%$#########%%&#+#&&#########$#$##########+++#+ @#&@#**--*--=:*-;==&###+O$$$$+$$##*;;--;", +"*===-******-*=$#$++$####$$##$====:---*=**&&#+&&+#####&#+#$&###&#+&++###$%##$######+### +O####-*----&****:--*##++######%$##%:=;;=", +"***=--*****-=*$#&+$+###$$$$$$*:=:::**-***&##&++##$$#&&###$##+&&#++&$##$$$$#$#$########+OO@#@#-***--******--%$$$##+####$#$%*;;::;", +"*%*=*****=--*=$@$+++#####$$$$=:::==--***=&&&+++&#$+#&&+++&#+++##++++$+#&$$#############O+@#@@*&*:****-*=-***####+#+$##%%#$%::;;;", +"*****%**==-**=@oOOooOoOoOOo++=:=----==***&#&&++++++##$+++++++++o++OOoOoOOO@O@@###&####&&###o@****-%%&==--*-$OooooOOOOOOO@@%::==;", +"=**==%%*=***=*%%$$++%%%$$$$@#*:=-:--==-**&#&*&#&&&&&##$$#+#####&&$$&%##%&##$&*&&##&&&#&&&&&o@:***:*%*******%%$%#+$%$%#$%#@%;:==;", +"**===*%**=*****-==::;;===:*#$*=:-=::;--**#+#+##*=:==****=;***=-:====::;:;&&****&++++##&&&#& @-**==**&-:**-**==;===::;;:;#%%-;;;;", +"*%==*%****;;=*====::=*=;::*$**===:::-*-**+o+++#&*=*&&***====**========;=;*&*=*=*ooO##@#&&#@ @*&*=*%%*-**:-=*========;;;=%***;;=;", +"*****&*===;;;==*=:::===:==*%**:=-;:::-***@O+++#*&****=*==;;===-=====*=;==*&****&+o+#@#&*&&o @-********---:-=*==;:==*-;==%**-;;;;", +"%********===**=====*%=*===*%**;:--;;;;=%%#O#+##*%*******--=**-*-==***----*%**%**#+####&=*&+X#*&&*******===*======**=====%**=;:;=", +":**==*==*=*=*%*****=*===:;****;:====-==%%#OO#++==*-=*--=-**&*=***==*-*-;-****=**$$%$#&#*-*#o$:-*==*====***%*****=*=*=;;=***=:;-=", +"=;*=**=====**=*==*======:=****:=*=====*####O+##***-**=;-=**==*-*====--;;*****-==***=*-%**&##&::-==**=====**=*=*=========*=*;:;*=", +"%=*=*#%**==*==**========-*%%%$%**&*%$&%%##$####$#*-%$%*-*=*==**-=====-;-*%%$%%*=**%%%%%##&&*&%*-==$$%==***=**==========%#%#%%%%*", +"*=**%$##%*=**=**=****=*=**#$%*%*=*%%%$$$##%&##$&%**####%*-*--&*-***=*=***#%**%*=*%*%%%%#&&&&%&****$##$%==*==********===%#%*%****", +"==%*$##O#*=**=**=*****===*%%****==%%%%%$#%&&&####**###@$*-**-**-****==*=%#%****=*%%%%%%#####%-:**%$##@%*=*=**=*=%****=*%%*****=*", +"=***%$$#%%%*******%**=****%*****-=***%*$#%%&#####$*####&&********%***;=********;;*%**%&####@%:-**%$##$*%*******%***===********==", +"==*%%$@@%====*******=*=*********-****%%%##%&%#####*&###*----*******;*****%*****=****&%%#@##@$::**%$$@#**==********=**********==*", +"==****%#%====*==========*==**===-**%*%%*%#%%$#####***$#*::-**---;=======*=*=====**%*%*%#####$--***=%%#=;=*****=======*=***====-*", +"=%%%%**%$%$%$#%%***=*=********=*-*%***%*%%*%%$$###&***$$&&##$&&**=*************=*%***%*%%###$:*$%%***$%$$$$$%**=**=********=***%", +"=*%%%%*%$$$$##%$$$%%***********=*%%**%*%%%***%%###%%%*$##&##$&&&%%*%*******=*==*%$****%%%%##$**%%$%%%%%$$##$%%%%*%*%***=****--*%", +"****%**$$$$###$#$$$$$$$$%=*==*==*%$%-%***%&**&%###%%**#%&&&##$##%$%$$%%***=*=-**%#**%***%##@$--**%%*%#%$$#####$$$$$%%****===-*%%", +"=*%*%**%$*$##$##+#$$##$$$$%***=*%*%******%**%%%$##****$%&&####@#$$$##$$$*%**==*$*******%%%$@&--%$***%#%%####@###$#$#%%%%%*=**%%*", +"*%@%%#%%$%$##+#++$$####$$$#$****%**%***%%#%%*#####$##%#$&&#@#+###$######$$%****%*%%*%**$#$###-&##$#$%$%%$####@#$#######$%%******", +"%$@##%%%%%%%#####$######$##$##$#$%%****%%$$%########%%$$&*######$$####$$#$$@##%$****%%%##$$##&%#+##%$$%*%######$#####%##%###%%%%", +"#$@@@o@#$**$%###+#$#@##$%$#####@#*;;;==*-=-**#@##@o@o#$%*&&&###@$##+@$$$$@@$@##%*----**-***%@@&#OOOo#$%*%$$##########%%%#@##@@%;", +"o@@OooO$$%**%$$@##++##$&&&++#&&##*====-=*-=*=#Xo#@ooo@$%*%*%$###$+#+##$&#+##%##&*=-=====**-*+o++Oooo##***%%###+#@###$$$++$$&##&=", +".ooXo+$$$***%$@$#####$#&&++&&&#+#*====**-*=**#oXooX@##$$***&#####+$#$#&&###$####**=-*=*==-=&+ooOXoO#$$$**%%$########$$$O+$$#+#&*", +"OOo.o+O$***&$$$$$+$$###&&#+#$+#+#&==*==*==;=*#OOoX o+#$*%*&$&$##+&&###&&#+####+$*==-=*=*===*+++O.X+O#%***%$$##@#$$##$$$O+$$$+#$*", +"@@@oooo@%*&$O$$++++#+#$&$#++###+#*=*==*==*=**#O@O#oooo#***#####++##+#&&##++#####**=*===**-**++++OoOoO$%*%##$##+#$#+$$$$$+$++#+&*", +"#@OOOOoO$$$$O$$$O#$+#+#++#+#OO#++&*====*=**=*#O#++O#oo#%%%#+#$$O$##++#++++#OO#O#**--==*=**-&##++OOOOo+%%%#@$##O#++++$O+@++O+++&*", +"##@OOOoO$$$*$&$$&$$$+oXoooX XXo&*=*===*==**#$$##OO#O#$$%&$%&&&&&&+XooOoX XXo+&---=;=*===&+&&+OOOOO$$%%%$%%%%$&$ooooOo XoX#&", +"$$$#+O+$$$$&$$$$$$+$$$+#&#OXo#OOo#====**=*==*##$%##OO#&&$%*$%$$%#$&&+##$#oXO+OoO**===**====&+&&&#++++$$$*%#$$$$#$$$@@$$+oo+++o+*", +"%*%%$$$$$$$$$$$$+$$$$$%%&####&&#+&=*=**=*===&@$&%&#####&$%&$%%##$+#&*&&&####%&##%*==**=*-*=&+*&&$$$##$%$%%$$$#$#@$$&*%$+##&&&##*", +"$%%$$%$$$$&&&$$$%&##$$**%$$##&&$$***===*=*=*%O%%*&%%&##%*%&%$$$%&##$%**%&##$&&$#**=*=**===*&+&&&$$$$#$%%%%$$%$%$##%%*&%$##&&&#&=", +"$$$$$$@$$$$&**&%%%$#%%%**$$#&&#%+%*********=%O#$#####$%&&%%**%%%&##&*%**%$$&$$%#***=*--**=*&+#&&$##$#%%%%%**%%%%##*****%##&%%##*", +"@@@$O@@$$&&&$***&$#@$*****%$&&#&$&*********%%+#########%*%%%%**$####*****##%$$$$%=*******&&&++++$@O#@%%%%%%%**%#@#&*****#&&#$&$*", +"%**-***-====*%%=**%%*****%&%%&$*$$$##O##$#$$$$%*%*****====**#*=**&$*****&&&%%%&####+#######+#***=***-;;-=**%****%%*****%&&&&&&##", +"$*;;;-;;;;;;-*$*****=**%%%*$##&*#OOOoXoXoooOO###*;:;-:::==;=*&**=*-***&&&%##$&&#@oooXXXoo Oo+#&::;;;;;;;=;=%%****-***%%%%$#$*&#+", +"$$-=---**----*$%%$***%*%#&%###%&$OO@+###++OooOOo#=-=*-**===;&%*$%***$*%#&*%##&&##o#O####+####+&-===*=*-====$%%%%**%%*$%%$###&%##", +"$%==****--;-;*%*%$$%%***$$#$#+#&###O$O#+%$@ooOO##*-****=;;:;%&*%#%%%***%######$##O##+O##&#&++#&*==****=;=:=$**%%%%***%%#####$#+#", +"$*------;;---%%*%*$#%%%%$$###$&&@O#O+++$+O@OOO+##-;---=;;;;*%&*%*##%%&*%##@#%&##+#O+####+#+++#&*======:;==*$*%%*$#%%%*%#@##$&#O#", +"$&:::;==;==**&&*&&$$&&%*&&$##&&##O#+########O+###*::==::-=**$%*%%&&*&%*&$##$%%############+###&=:;;;;;;--**$*&%%%%%%&*&###$&$#+#", +"$*::;;*;=-;==*#&%$$&%*****$&&**&$#+#########+OO##;:==*:*-;-=$#%%#%%*%*=*%%%**%%#++#######&#&##&;:;;*;;*--**##%%%%*&**=*#&*&*&$#+", +"#*====;;=-;;=*&*-:*::::-==&$&&&&%#+#+$########+#&===---=--==%**--=::;-=;-%#$%%%###+#+########+&:;;*;;;=-;-*$*==;=:;;--:*$$$&&%##", +"+*==;;;;*-=**&-:::::----==&oo+ooO###$++#+#+#####*==::--*=****;;;::;-;;-;=#oo@@o#+####++##+#####-;;;;--*;=***:;;;;==;--;-OXo+oo#+", +"#%;;;:;;*-*****-:::::::-::&Xoo+++#++++########@#*;;:::-*****%-;;-:--;::::# o@+##+@+##++#####&+#*;;::;-*****%=;;-:=;;;::=+Xo+#+#+", +"#=;;;;;;*-**-**---**-:::::&oo++##+#++##+O##+#$##*::;---==*****;--*-::::;:#oO@@###+#+++######&+&-;;;;-==***=*=;-=-=::::;=+oo+####", +"#$;;;=;=-*--***:--*:=::::=*+++###+#####+###O@$##*;:----=*--**-;;-=*:;:;;-&@++#@#######+#+# &&##*;;;;-==--***-;;---=;;;;;#+O+##+#", +"#$;;==;=;-*****-:-===:--==*++++##+++#+#+@###$$##*::-==----**%*--:---=;;;:&@++@#@o++##+####&&###*;;;;=----**%*;----;;;;;;&+OOO#Oo", +"O#=;;;:::=****&**--*-;;;--*@+++++o O#+###$$&%$##*---;;::;-*-***-----:----$@#++@+X ooOo++#$$&#O+*;:;;===*=****=*---;;:---#++#+#o ", +"#######+#&&&*&**---:--;---*#$$#####@$&$&&&&$%*$$*---;;:;-*****--------*--&#####&##+@#@+##$$&&###@$##$$$$$&*%**---;-:--*-&#######", +"OoooXooooo+++&&----**---==*&$#$$&###&&%*&#%$####%--:;:;;;***%*-----*-----*&$&##&&##+@#+#####&#oooooXooXo@+#%==---=*--*-**&$#$&&#", +"@@#@####Ooo+++&--:-***--=**&$$$%&&###%&&&$$$#%##%;::;;;;;-*%%*---***---**&$$&&#&#####+++++##&#+#@##$#+ooOOO#*---***----*&$$$$&&#", +"+##++###+ o+#+&;-:--*-*-***$#%$##&#$#&&&&&#%&&%#*;;=-=;--*%#*-;-;;---*--=*#$&&$$&&###+##++##&#+#+++&$+OoO++#-;;;----**-*&#$%$$$#", +"+O+####+#+O##+&:-:--*-:-==-#$*%$$$##$&%&&****&##&;=-*-*-*-%@%-;;;;-*--**=*$&&&#$###++++oX+#&*&++##+++++OO###-;-;;**-----&%&&$#$$", +"#########+++#+&&****%*%%%%&%%%%#$####**&&%&*&####%*%**%%%*%##%%%%%%%%*&%#%%&$$$###++++oooo+#&&++$+####++O+##%****%*%&***%%&$$$##", +"#########++++#&---**-****%#%%&%$$$#$***=-******%%%$%%%#%%%$%%%%%$####@####&&&$$$&###+++++OOo#*###$##$#+#OO##*=;;*-****%##&&$$$$#", +"++$++$$$+$#++#%==;=**=*=**O$$$$$$$$$&%****%*%$$%%$%%*%#**&**=*=*******%#&&%%$$$$$$$#O@O++O++&&+&+&#####+#+#%*;;;=-*=*=*##%$$$$$$", +"$$+$++++#+###$*=======*==*+$$$$$$$$$&$$$**%**$$$$$@#$#%==**===*=***=******$$$$#$$$OOOOOOooO++&&+++#++#+&###&====-*=*=*=$#%$$#$#$", +"+++++$$+###$+$*===*==**==*$$$+$#O$$$**&$$#*%*%$$@@##$#$=***=*==**********%$##%##$#O@#OOO+o++&&++##++++&####%*===*-*===*$@$#$$###", +"$+$++++#$+$$+$*====*====**+##$+$$@@$*&&%#$%%*&#$@$#%%#$=****==***********$######@$OOOOOO+O+#&*+++++&#&#+$##*=-*=-**====$########", +"+$$++$+#+O#$#$%=*====*==**##$+$#@$+$&&$$%%*%*%%$$$%%##%**%*******&&&%%$%*#########OoOooOooo+&$++##+++#++%#$%**==-=*==**%#+######", +"++++++$+$$$#+#%*===**=**=*#+$+++O++OOOO####$#%%%$$$#%%%*$$%******%%%%#######@@oO#OOoOO@@++O+&$+++#+#&##&%@@***==-*;*==*$+###@@@@", +"Xo+$#$$$%$$$#$**===**=*=**#+++OoO#$+####$##$$$***=*==**%%%$$%&&*%$$%#$#####+@o.o$*-***;;=:*$&+o+##+$&&&&$#%$***==*=**=*$#+@@oo@#", +"+$$$$*$&&$%$$$%**==*=*===*#+$+oXo&**%**=*=*&*=;;;;;;;*%%#%###%&$$$########+##o o=;;;;;;;;;=**&+&&&*&&&&&$#%%*===*=*====####@XX#=", +"$$$$&&$$$$####**=*=*==*==*++$OXXo*=;;=;:-;;;*%--===*=;###+##$$$$$$#$$###$##++o o*==*=**----*%*#%&$&&#&%####%*=*=*==**=*$O#OO.X#;", +"$+$$&*$$$$$$$@%**=*=*****&+++oXXo*======---;-$*=**&&**+O$+####$$$#$###+###+##XXo%==****;;-;-$%##&&*&$%$#&&##**=**=***=*#+OOo.X$=", +"$$$$%&&&$$$$$#$*-*****=**$++$++OO*==****--;;-$%*&&%$%%##$O#$###$###$$##$$#####++*-;-;*-;;-=*$$#$&&&&%&%%%$##%***=***=**####OOo$=", +"$+$%%%**%**$#@$$####%#$$$$$$$+$O+*==*===;;;;=#$$&&%$$###$+++#####$$#$#$####$+++#-;;;--;;--=*###%&&&*%**%%$##$#####$#$#%##$##$O$=", +"+$$***%$%**$$#######@@##+$+$+&++@-;;;==---=**#&&$$#$###$$O$$######$###$##&#&$#+&;;;--;;=-=-*$#@$***%%*%*%%##%###$#@####+$$+$O+$=", +"$&*=*==****$%%$$$%*%%$%%$$$$+&+$$;:;;=-;==-**$$&$$$#%$#$$$++####&&#&$####&#++#+&;;--=;;*--=*##%**********%%%%&%*%$#$*%#$$$++$O&:", +"$$&&****$*$$%*$##$*$$#$%&$+$&+++#=;-=---====*#$#$++$$$+O+OOO@@@#######+######++&;;;;---*=**%#$%%%%******#%%%##$%%$#$&&#$$@@$++&:", +"$$&$$&&*$**$$$$#@$$####$$$$$&&$+#*;-----*=***#&&+$&&**#XO@@#@ooOO#####$#&#&&##+&;;;;;;=***=*#$$**#%**%%**%#%###$$####$##$$$O$$*;", +"$$*&&$#%%%&&$#@#+$$$O###$#$#$+$+#=;;;;;;==***#***=;;*;=%**=;*@#####+##&$#%#$####==:==:******#%#%*%%#%%%**%###@$%$$+$$$$$$$$+$+*=", +"O%&*%%%%*%**$#@$$&$#+$#$#$$#$+$+#*:=;;;;=****%*****;;;;=*=;;*##$+######$###%#$#$=::=-------%#%#***%#%*%%%%#@##%%#+$+$+$+$++$$+*=", +"@$%$%%%%%*%%%%$$$$$$$+$#$$$$+$$+#=::=;;;*==**%**===;**=***==*#$##+#####$%######$*::=-----***$%@%%%%%%%%**%%$%%%##$+$$$$$$##$$$$=", +"%%%*%*%%%****%$##$#$$####$$#$$$$#*:;;;;;-=***%***;*****%*==**#$$#######$#%#%#$#$=:==-:::--**$*%%%%%*%%%****%#$#$$#+$+$$$$+$$$$&=", +"***==*=*====*=####@@##$#$$#$$$$O#%;;=;:::==*=%%***=****====**##########$$$#####$=;=-:::--***#***--***=*==***@##@+#$$+$$$&+$$+$$=", +"*%*=*%%*===**=#ooooo@OO@oOOOOOO##*;;;;;;;*=**#%*****%%*===*=*@oooXo+OOo+OO++O+##*;;;:-:-***%#*&*-**%**===*=%@o@ooOOOOoOOOOo+++$*", +"=***=%%**=****$$$$##%%%#$&$#$$&%$%;;=;;;;=***#***===***=*****$$$##$&$$$$$#$#$&%%*::;-:----*%#-*=-**%*==**=*%%%%#+$&$$$$$+&$&&&$*", +"**===***=***=**=;;==;;;-*;*$*&**%*;:;;;;;=-*%#*-**=**%*==*=***====*:=:=::%&**=*%-::*-----*###-**=-**%*=**=***;;-===:====$*****&*", +"=%==*%***=====*==-;;;--=;;*$*=*;**=:======*%%#**%==*%**==;==*-*=::----;;;%%***-**:=---*-**###***=**%**==:=**=*=;;--=;;;-$&*=*=**", +"*%******=*=====*;;;;==--;-***=%**=::=*====-#@@%********====---*:::-*--;;;*%**%%$###&%$#$$####**%**%***==;:====;;;-*=;;;-&******=", +"%%*******===**==---****-;--%*%*%*%%%%%*$%%*%#@%*%*******=-=%==*-*=****---*%%$#####$#########O#*&*******-=**=**==-***-;;-&*&***&%", +";=*;=**==*==%%=******---;;*******$#$%%$#%*%#@$%*=*==**=--*=%******=*--;:-=%#%$##$$#**%$$##@##*:*==*==*--**%**=*--*=*-;;-*=*****#", +";;==**====*==*===--=--*-;-*****=;***=*****%$#$%=;-=**--===***===:------;=*%##OO###%%%##$####+&:*=;**=;;=***=---*-;-=-;;-*=*=*==*", +"%=*=*#%*===*==*%*--=----;-$%%%%*==%*%*%%$$$%%*%=****$%*=*-*==**=-*------*##O#@######%#$#%####$=***%%%==*=*;=**----=-;--%#%#%**=*", +"*=**%$$#$%=**=***--***---*$#%*%*==%*%%$$###%%%*=**%$$$$$*-*==**-=****--**#%##@######%####&###&=***%##$%==*=-**-*****--*%#*%*&*=*", +"=***$$#@#*=*==**-******==%$$*****=%%%%%$$#$$%%%==*%$$@@$***==********--*&#%###@######%%###$##&:**%#$@@%*=**********--**$$*****=*", +"=***%#$#%*%*******%***==***%=***--*%**&%#####&*-***####%&*******%***--***%%#########$$######$%****###$*%*******%***==*******=---", +"==*%%%#@%===********=******%****--***$%%#####%*-***%&##**--********==******#########$$$$$$#$#*;**%%$@#**==*********=****%*****-*", +"==*%**%#%===***===*==;=;=*===*--;**%*%%*######*-*****$#*:--***-*-=--===*=**####@#######$####O&==***%#$;;==*%======;==*==**==---*", +"**$%%**%$$$$$$$&&*=**=*******=-*-*%****%%#####***%#***$%&&#$$$&**=*=**=*****&$%%##%%%$%$##O#$*=%%%**%$%%%##$$%***=*==****=**=-*%", +"=*%%%%*%$$$$#$&%&&$&*****=*****=*%%%*%***%%#$$****&%%*%$&$##$&&&&*&**********===%%*****%&$$#$*=%%%%%*$#%$@$$%%$$%************=*$", +"=***%**$$&$#####$$$$$%$$****====*%$%**%***###%****%&*%##&&###$##%$$$%*%*=**===*%#%%*%**%&$$O$=***%**%$%%$##$$#$$$$%%%****==*-*%$", +"=%%%%%*$$%$###@###$$$$#$$%%*****%*%***%*&%%%$%**%%***=%%*########$####$&*%**=**&%**-*%*%$$$O$=*&%*%=%$%%$####O#$$$###%%%***=;%%*", +"*%#$%#$$$%%###$O@$$####$$$$$****%*******#####$%%$#%##%##&&#@##+##$##$##$##&**=*&**%****#@$$#$=&$#%#$$$%*####O#$######$#$$$***%**", +"%#@##$%$#%*$#####$$#O$+$##$$++$$#*%**%$%######$&####&&#&*&$#####&$###########$#%%***&&%##$$#O&$+@#$%&#&&&$+####%##+##$####$+$$&*", +"#$OO@o+$%*%%$###$####+$$%$$++$++#*=;;;==--=*&+++#+OO@@$&*&&#$##@###+##$%$#######--:;-=--*=*$OO%+@+Oo#$***$$##########$$$##O$++&=", +"o#@OoX@#$****$$++#+#+#$+%$OO+$&$#*--;==*=**=*#OO@@ooo#$&*&*&########$##&#+O$$##$*-----*==*=*OXO#Oooo$#&**&$######O##$$&$O@$%+$$=", +"XooXo##$%**%&$$#+###$#$$%$O$$$$+$%==;=*=-*==*+ooooXo@$&&***&$########$%&#+$$####*---**=**==&OooOXXO#$&%***$$#+###$##$$&+#$$#$+$=", +"OoXXo@+$****$$$#$#$$$$+$*+++$$++#%==-=*==*;-*++ooo @@+&***&&&$#@######%%+O#$$O++*----*-====*+++o.XO@@****$$$#@+#$####%#+O$$$+$$*", +"@@OooOo#&%*%##$+OO$@+$$&$$+++$++$*=***=**--**$++@OoOOO#&*&#####@######&#$O##@$+$*-*--**===**++++@oooO$&&%#####O###+#$$##O$++++&=", +"#+OOOOo+$%$#+##$OO+$+++++++++O++@%*---*====**+++#@O+Oo#$&$#@#&#@###+###+#OOOO#@$%*==*===**=&+$++OO@Oo$$$$#O$$#O##++#+#++O+OO$+$*", +"$##OOOO+$#$%$%%%*$$$+oooO+X..XoXo$**--==**=-*#$##@O@OO###*&$%&%&&&&OXXoOo....X.O%**-==**=*=&#&$+@O@OO$$$&&$*$&&$&$ooooOo...XXX+&", +"&&&++++#%$%&$$$$$###%$@$$@OXOOOOO&====*=*===*+&$&$+++#$$$&%$$$$$##&&#@###ooo##oo&===***====&#&&&##O+#&%$%&#%&&%##&$+#### o@#Oo@*", +"&*&&#$##%%&*$$$$$$##$%%*%$@@$$$$+&*==*=*=*=**#$&&&&#$+$$&*%&$$#$###&%%*%#####%##**===*==*=*&+**&&####$$&*&&&&####$$*%&*####%%##*", +"$&&&$&$#$%&&$$$$$%##$$%*&$$$$$$$#&*=*=*=*=*=&+&**&$&&#$&&%%&$$$%%##$***%###%&&##**==*;***==#+&&*%&*$##%&&&&$#%%%##$***%###$%%#$*", +"$$#&#$$#%%$&&%%%&%$@$****%$#$$$$#&*==**=****&+#&&#$#&#$&&$&%*%%%$##&%****##%%$&#***==**=***&+#&&$####$&%$*%*&**##$&&***&#$%#$#$*", +"++$$+#+$$&$$$%**&$#O$*****$$$$$$&&*=***-=*=*&+#++$++#+#$*$$&*%*$###%*%***##&$#&$&**=*==;***&+#++##+###*&&%%%*&##+#&*****#$&$$%%*", +"&&******====*%%-**%%*****$$$$$%&&+#+++#+#$++++$&&*=***====**%*=**%%%*=**&%%%&&*#&#++++#&###+#*&*=*&&*-====%%**-*%%****%%$$%&%%##", +"$*::;=======-*%****=***%$$*$$$%*&++OooooooX+++++*=::;;;;;;==*%****==**%%&&$#$&*#++Oo o ooo++&*=::;;--:-:-=%***=*=***%%%%##&*&#+", +"#*==========-*%%%%***$*$$%&$@#$%&++++++#+$+++&++*=====*=====%$$$%**%%*%#*%###%%#+++#++#+++++#+#=--==-*----=*&%%&**&*%%%*%$##&$#+", +"#&==****=--;;*%**$$$*&**%$$$@@$$#+++#++#$$##%%##*==****--;;=$%*$#%%*%=*%####@$$#++#++##&##$+##$*=*****-;::-%%*#$%%%**%%%####$##+", +"$*======-----*%*%&$#$%$*%$@@#$$$###+#@++O@#$%$$#*=-*--*---;=$****#$%%%%$$#@#$&$O+#+##++##+#O##%*:-----;;--*$%**&#%%%&*%####$&###", +"$&;::-=-;---*$$*%%$%%%&*%%$$$&&$#+######$@#$$$$$*:::-*::-=-*#%*%%%$%%**%$$#$$$$O#+#+##########*=:::--;;;-**%*%%$%%%%**%###&&$#+#", +"$*::=-*=-*==**@%%%$%***==%$%&*&$#++#####$$$$$$*$*:::--;--;**$#$%#%*%**=*$$$%*$$$#+#########$#O%=::-*-;-;-**##%&%%**%***%&&*&&##+", +"#*;;--;;==;==%%==;;;:;====&&$&&&&##+##+#$#$$$%%%;;;;-;;----*%*---;;;;;;==&$$$$&&@###+#########$;;--;;;----*%**---:;-==-*$&&&&&##", +"#*;;=;=-*-=***=;;;;;====:=&XoO+O++#######$$$#%%%-;;;---=-****;;;;;;;;;;;=+XoOOo#+######+#######=;;;;--*-*-**:::;:;;;:--*OXO+OO#+", +"#%;;;:;;*=*%***;;;;;:==:::&Xo+O++##++++#+#####%#*;;::;-*-**-%-;;;;;;;=;;=$XoOO+++++++#+##+###@#=;;;;;-**&***-:-;;;;;-;:=OXo++++#", +"#&:;;;=;=*=*=**-;--==:::=:&ooO+###+++##+#####$##*;;;;;-*******;;-;;;:;;==$ooO+$$##+#++#+###$##$-;;;;;--**=***----;:::::=#Xo+###+" +}; diff --git a/hacks/images/tunnel4.xpm b/hacks/images/tunnel4.xpm new file mode 100644 index 00000000..66b135c2 --- /dev/null +++ b/hacks/images/tunnel4.xpm @@ -0,0 +1,134 @@ +/* XPM */ +static char *texture4[] = { +/* columns rows colors chars-per-pixel */ +"64 64 64 1", +" c #201C02", +". c #2C2703", +"X c #332B06", +"o c #352C17", +"O c #393311", +"+ c #3D3626", +"@ c #1D1B00", +"# c #453917", +"$ c #443C0A", +"% c #453B24", +"& c #4F4516", +"* c #4D4328", +"= c #574927", +"- c #585033", +"; c #645630", +": c #72623A", +"> c #57544F", +", c #645B53", +"< c #6A645D", +"1 c #70684F", +"2 c #6B6867", +"3 c #746C68", +"4 c #7A736D", +"5 c #7A7876", +"6 c #6F6F70", +"7 c #7F7F80", +"8 c #7F807E", +"9 c #7F8081", +"0 c #857A6A", +"q c #847C78", +"w c #82775A", +"e c #817F80", +"r c #89827C", +"t c #93867B", +"y c #958E72", +"u c #A1927D", +"i c #92805F", +"p c #8B8886", +"a c #948D88", +"s c #98928D", +"d c #9A9796", +"f c #908F90", +"g c #9F9EA0", +"h c #A3958C", +"j c #A39C98", +"k c #AD968D", +"l c #A19FA0", +"z c #A7A29D", +"x c #B3A59C", +"c c #A4A085", +"v c #AAA7A5", +"b c #B3ACA8", +"n c #B7B2AD", +"m c #B9B7B4", +"M c #B0B0B1", +"N c #C3BCB7", +"B c #C3B5AC", +"V c #C1A799", +"C c #C6C1BD", +"Z c #C9C7C5", +"A c #D2CBC7", +"S c #D7D5D2", +"D c #E2E0DF", +"F c #E2DBD8", +/* pixels */ +"M6a5ClMCg9<*=B4bfdzBm0>adbtxzsl5krtd4sr4hv8AznbqkjNhZdqjzvge4fZf", +"6bvCg,855mf*&Cbarldr3sCNmjvvz6sndjt4jkbzflvszrhxtpshfdMpbbpMlNpv", +"mav4>gCZDz4*-cyrxa4mavd5rrja6fbvCadxCmtr8sal0hztbajqfvMfd7gpggvd", +"vbddMS9d96s*-jzzzCnbssddajppvvzvdraavpppvaNdxmdNqdjjvvpvvdgvmvpf", +"pddjpp9vpd,-&rbadjfbaBbjhxprppp83jpavvvZfMpfdzsrebm7fasldtvmppvm", +"vMjvfdga7gS1&bjhxaarsjjs3azNavmmvCnndpmrglgvvdsrzd45jbMjMvMfpdMm", +"dfdplrvfdv3.&nsstBxtsta3zk6alsssr2mjfdddldMdjpqxzvvvdpplfpglvvvp", +"gvp6mMvdpfC+*absa0qh2tqbnkCzrbxzsdvdzzazdffvrjjsseadfljevnMpdv6f", +"mvMZvvvaffp+#xxqrNNBFhmMq4apBvt2vvfpddfafCjpshCz4rvaajCjv6szz<5m", +"dfffvd8dsfbo#anvAab45hdqjSANpjbSddmAbmplMdzzmvapNCdjnzpr5hdmaMSv", +"ddMsjdCdfds+-aldps5jNzdNC,qerqv6pmM45gdva6dszjnAgvjZjsejfj", +"hakbnv1aaspo*6cnajBznffsnvvgpMvfldc5vvbbpfa6mddrpAbjdd8sC5tshpdZ", +"pNajjkvdvm2O=dg8Cnjzfvbs5dddvffszfvmmp6rjMd6f5dvdse>o;1-8,1411-8;o--+-pu18:-;111;-<1-ky10tiyy4iu8xitqic,s", +"o O%.X$#@@.&&XX.X$.&.$XO&&OO$XX#$X&$&&O&$$&&$X&#OXOOXXX.X$X.OXX&", +"y0hhyyuyyuu&&>yy11y&yy11101==000&i-1:*1=;*w11:wi1ywtxdzyt5*;vfdfg9smzzsjqxhexj2v88vCg>6fvsrdzjvdarbzmvrjdzpvZap", +"MdvvpMgr6naO=Cdzdplz2dvCemjaxseNzcMfsamgdCpnjdma4sbNazbdgM9ZmNml", +"g8NrfvvMmfd+=spddMMNl8azlqqpzzhvvdxsdM>>mdvdrvsjbnqqbfpfbp3NvNn>jaqqjuzjl5", +"mmCvdvb2snaO;jrajmbhxzjqebseqCjMevxvjfenxkualBbZbjbBrvdAjNbajjbb", +"dglpsnrxvf5O&0pjvqpjjbpVnxjeNvdeMgfseqqjq3VNamgdqvCeCsaBq3afsgpqqNZCxsspbvdfvl", +"gdvdscCszz5*&xd5jdpbpqtavSNvvMlefmvvexeqBeejvlMvdbBpq2akebsddqfg", +"fqdzbadhxp5O=0asddjpq5j0jvpgvjvvvfrejpsNhpZxbvd4qsaMeCm0pknqpvln", +"fmdvfadbtjr-&vjsrdmppmdCnqpZdfdasjMnjjvk3NalepjzAhspCvjbjj4NAMvb", +"Mdrvsamdzbl%;sqjBmq0z0vqfvNdpfevjppfss5dAaapfnbdefNm3qeqnddddjjs", +"pfbvjnvpjsq*&rjnvbhmjtjvnjfpq5zqbmMkkvMpabedvjqzlmbe4jabkbMvdgjn", +"bNjxad65M5q>=jd>atsqjChhtzff5lhjjhdaBdfbaqhf5lMdsvd6d6vbe5ajMdev", +"a5x5zMgSsjN*$0sSaaAjz6pmnjavM,3bjkqBj0ssdCZsmv7ll55Mjjh3jmemfjja", +"dAv5p>vd5v c #544B4B", +", c #564D53", +"< c #58514D", +"1 c #5B5557", +"2 c #4F5053", +"3 c #5C5A63", +"4 c #5E615D", +"5 c #5F6469", +"6 c #635A5B", +"7 c #61534C", +"8 c #665D63", +"9 c #715D68", +"0 c #69625D", +"q c #70635E", +"w c #6B6567", +"e c #6E6A72", +"r c #6E7073", +"t c #74696A", +"y c #756C74", +"u c #79726E", +"i c #7A7477", +"p c #6E706E", +"a c #7D7982", +"s c #7E8183", +"d c #816E77", +"f c #82756C", +"g c #84797A", +"h c #907F73", +"j c #857C84", +"k c #947F8A", +"l c #8A827D", +"z c #94877B", +"x c #8A8488", +"c c #8C8892", +"v c #948989", +"b c #958C94", +"n c #9B938B", +"m c #9B9497", +"M c #8E908D", +"N c #9D99A1", +"B c #A3948B", +"V c #A49898", +"C c #A59397", +"Z c #A49AA4", +"A c #ABA099", +"S c #A9A3A9", +"D c #ABA8B2", +"F c #B5ABB0", +/* pixels */ +"o4iiy38j9yt6dd6tkNZkZZk93*j,;1ewyccwecccaw:t98e88e8,3a,9939e#+&*", +";2raaa,3*9ddd9qjkZZZDkka9:39eiaiacci%2jcj98yyiaeeya8339999ey**;*", +";:1ayad7dgdt66dvNZZZZDk999jadgxxjcbcg,:aj1,dyiiaaaaa33:a3339:*:;", +"*,*;yjkjd96,,9jxbkbZZkkjt*k9wikcmmNbbj91d7@iiair9aaaaaaa53*9:*,%", +"%:&*9gt>,9969yjvcbCZbcbdj,kjggcbmZZCbkt9tto;iiitaaaaaaaaa8,8,***", +"%*O:89,>,yjytdkbbbbCvkkdk*ivkbCCZNCmct7t666+2irr5aaajjcaaa93,#**", +"#*o*8w9,9gjagxcvbmCbvkjik7dxvbmNZZZmx99gy369#>traaaakkkkjae8,+**", +"%*.*9ee69jkjjcvvvcbvxjigd99kxCmCZZZmc<9giw96w@,t9a3aajakaae9,o*%", +"**X1yy7>6gvjxcvxxkcvvhgu<68icbbcbZmbc<9glji88tO:eyyeaajsaaa93o**", +"&&o6ykh7=;1,1wiaddjkhkg7666>6jvvvckkjkt9dq,uvcgigl=tMmbcxe69<.;:*+$oo +o+9*+&", +"**&,dvgu6tt66wtdf6;&&&66j67fgd<0gjhxl;wmmmbMgt7w7>7<01<;%+%*6,+*", +"*,**i8886yyttygdgtittq1199qtfhhq1wgjx<6cmbmbxx66f8ugj1w113,893+*", +"&&*o8:39yglgghggguuyfut9wt97666tutwug61xcbmbccaet1ycj80w399y99+o", +"....*,tggvvxxxvxgljgutd87gufuuqqulgtg6,xscbbcvjg8;imce192:*,76*o", +"&,69&6dvxnCnvvvvxxxjjii>tgihlutwttugg6*76696*", +"+&,:@6dnmVmCmbbbxxxxxlw>glMnvluttwtflw=uuivbkcjey1,8ww66686<>*#O", +"+;1;O6jbmmmmCbvvvxlxlg,gxcji86,>;ww6>6;*&;,:1>*", +"7tlw@8bZVVmbmbvgfigxlgq7uxnbmbittpttft8&gxcy96;7<6tt1=;O#*,1w911", +"wyyw*0xZZbvggq6#&>&>6fp=2116ugguuitwlli&iMawp<<68tpt8<;O$;1we9w8", +"yew,#1ei3*&&--qq&utwtfuttfgw,>,660pulxx>wx8uw068euew83>+#:5eeeey", +"ie8>,*><769ufhvz&fbgt0wt99tdgtyut7<><0u9@wwu6w1qyyyw1::&@>88eeaa", +"ye9*gdfghguytigv<6mgutut69yijgthzguqwwtg6tgu<0VliigiuxxlMvxxxgt686,66th977nxxjxxgxccmmMbvi8,,;&+>ff;8iijjjw8xbVZbxb6gmMglirxmmmmmvxw;,8,*&6dy;67qgiiteww>;;1##<,;:", +"6w83bmCvjavVASmMcu0mmxggxbmMZmbgt<1<,,>7ww67q7quuuuiyw:;;2,=>w66", +"bmVbvcbZSSmmvj>vVnxvMbmmmbkt<60<111,68,w60quuiliuw<:;>,,69w<", +"+o*&jmbbmmVDFSSmbk>gnbmbxbmmCcg6<10<,t6116:tqq6ppsaiw<>,>1@&;yvxbVNZDFSmbbbt,bbbMxccbjdt;<761;6;4r38:+", +"2:&:yacjmNZSDVxxxji:vmMbcxbj;t,><166tep661<<><2->1<<>&****ware;#", +",;+:jiccbSVZZbggddv66vxxcay*6l;#>>60pyyw101rt0<&&&&>;**#:,eaae:%", +">;::aucZmZmbbbgggnnv-tlgiw#7hzu#;<<4www10<1wwtutq>&&;<;;6eaaaa;$", +",;3#uimNbNvbcxxvfvvvf1gii%>dggx1#<1<1e1:1;wt8,6wuutqw6&wisxaaa:%", +";+32ibmbixdtivVv6Czvv66u6@1wgxgl-=<<1w1,1=0rp1,68ty6i23iaccser%%", +";#e;weyt888dlfhg,ncgjj>t;@3rlsllg#<<6113<;10gxlMxx1&<1121<0pxxjaity:11:upscccsa%:", +">;yiaduyuuq0dz7gxfkvvzvtfu6gMMNMjj2&<<1:6uxxxxiarw;6;1iagxxcci#:", +"1;8<66680w41gv,vhBvffgzhvl1uxMANcjv&;11;wgxxxsxjtwo+;#;8eiaiww*1", +"w1;*>wwwtaglg;ukCCnlfggvng;wiMSNNxjt<11>ygxcxcxxii0=601>;<<;;=2w", +"52,pwtiixbmbpgxvxxxgiuu06weewwqwp22w", +"=16618xcbNZwuvfzBnVvggt6zl=0lMSSZcxigt1;wgixMxxgi<12;618ewww,71=", +"160wjivcNmb7guvvBvnguiigxz;1gMNSDNcipuw;wi1uxxui6<44133wttpu,**6", +"=118jgbjmmi6yuVnbnvillxmzl14xMNDDZcjayt=8i6qlluu>0wpe513wpiu8;#&", +"<61eNicxmVuttzBvvnVhxvmnzz4", +"<12emtcmCB6u6BVgMVBnzzzffu01xwcNmx7gwAABVBBBvnzzhzt>ixmSDSNmxiewww1##;;pacsaeww2eeiar311", +"40<;xycNmtwdqAABAABnzzzzhlf@5ajccxirra2wtiut0w1", +"4expij>,>gB9BCBkzAAABnnVVvi,O;raxcxcsaaj18tutpw53", +"3pcyyxi669kdBzBzznAAAVVBVniwtdfBBBBzzMVNASVmnlgt>plxxbxje9t97@>wscaccccaiiw6tyryye5", +"55acnBnBnzzVAAZVbgggw>wxcMxt60ut#;4acsacbcxxaje8eutpp55", +"00pw&8jjugvx&-fzBBBzznAZVMffq6u&1xaetijgw#1racaaxjjcbaxybmiwixVmcx8$.,raaeaayjgijj1044:$23", +"5311:jcd,,vCCCBiakj818,;66;;;$#33", +"2323ead>tvkjyyj6imNZZNx16w6<*gnnijmca2;ij9,9:%%%+$*%+*3181;#o#::", +"$2raae,9vt9yy6#,vCCZCCbtw*6gkxjcccbi*,accy,yaae93:,,,;;::1we%#;$", +" 3sia89dud91du>6vbbbZmv98,mvge9yxcceejccc9,y88ee8e83:;,89ett@#%%" +}; diff --git a/hacks/images/tunnelstar.xpm b/hacks/images/tunnelstar.xpm new file mode 100644 index 00000000..e87d4527 --- /dev/null +++ b/hacks/images/tunnelstar.xpm @@ -0,0 +1,323 @@ +/* XPM */ +static char * tunnelstar_xpm[] = { +"256 256 64 1", +" c #020202", +". c #040404", +"+ c #070707", +"@ c #0B0B0B", +"# c #0E0E0E", +"$ c #121212", +"% c #161616", +"& c #1A1A1A", +"* c #1D1D1D", +"= c #202020", +"- c #252525", +"; c #282828", +"> c #2C2C2C", +", c #2F2F2F", +"' c #333333", +") c #363636", +"! c #3A3A3A", +"~ c #3C3C3C", +"{ c #3E3E3E", +"] c #414141", +"^ c #454545", +"/ c #494949", +"( c #4C4C4C", +"_ c #505050", +": c #535353", +"< c #575757", +"[ c #5A5A5A", +"} c #5F5F5F", +"| c #626262", +"1 c #666666", +"2 c #696969", +"3 c #6D6D6D", +"4 c #707070", +"5 c #747474", +"6 c #767676", +"7 c #797979", +"8 c #7B7B7B", +"9 c #7F7F7F", +"0 c #838383", +"a c #878787", +"b c #8A8A8A", +"c c #8E8E8E", +"d c #929292", +"e c #969696", +"f c #999999", +"g c #9D9D9D", +"h c #A0A0A0", +"i c #A4A4A4", +"j c #ACACAC", +"k c #AFAFAF", +"l c #B3B3B3", +"m c #B6B6B6", +"n c #BABABA", +"o c #BEBEBE", +"p c #C2C2C2", +"q c #C5C5C5", +"r c #C8C8C8", +"s c #CCCCCC", +"t c #CFCFCF", +"u c #D1D1D1", +"v c #D6D6D6", +"w c #E2E2E2", +"x c #E6E6E6", +"y c #EAEAEA", +"wqljjjkkkllkkkjjjjjjjjkllmmmmmllkkkjkkklllllllkkkklmnnnnmlkkkkkklmmmlkkkkklmnonmmlkkklmmmlkjjjjjkkkkkjjjjjjjjjjjjjjkkkkkkkkklmnmmlkkjkkklllkkklmnonmllklmopponmlkkklllllkkklmnnonnmmlklmmnnnnmmlllmnoooonmllllmoqstsrqponmmmoqsuutsrponmmmmmnoqrrrqpponnmmlmnpvy", +"qc1<<[}}|11||}[[<<<<[[}|234443221|}}}}||122221||}}|2577531|}[[}|23332||}}}14687531|}}13442|[[[[[}}}}}[[<<[[[[[[[[[[}}|||}}}|245431|}[}||111|||24787421|248009642|||22221|||1357875421|13577654211247909753221250cfgfdb0864459cfiihec0864323580cddcba087542236bjv", +"l1,*&*=-;>,>>;-==****=-;,)~~~!)),>;---;>,'''',,>;;>'{^/^{)>;---;,)!!',>;-;,!^((^~'>;;,!]{)>-=*==-;;--==**==--======-;;;;;;;>){]{),;---;,,,,>>,)]((/{),,']_[<_^!'>>,'))',>;>,!^((/^~),>'!^//^]!),,)](:<_/]!'''~(}47752}:(^{]/[380073}:(]~!!{/:}1221}[:(^{!)!]_2es", +"j<*+.+@#$%&&&%$#@@+++@#$&=;>>;;-=*%$##$%&=====*&%%%*;')),;*%$##$&-;;-*&%$$&-,!!)>-&%$&->,-&$@@@##$$$##@+++@###@@@@#$$%%%%$$&->,,-*%$#$%&***&&&-'~~)>=&&-']/^~';*%%*=-=*&%%&=>)~~),;=&&=>)!)'>;=*=;']^^~'>-==-'^[232|:/{),,)^[26741;;>'](<[[<:(^~),;;;,~(2es", +"j:&. .+@#$%%%$#@++...+@$%=-;;;-=*%$####$&****&&%$$%*;')';=%##@#$*=--*%$##$*;'!)>-&$#$*;>-&#++++@#$##@+..++@@@++++@#$$$$$##%=;,>-&$#@#$%&&&%%%-,!!';*%&-']^])>=%$%&==*&%$$%=,)!)';=&%&-,))'>;=*&=;)]]{)>-=*=;!_|22|<(]),>,~_|4641--;,~/:[[<_/]!'>;-->!/[5gt", +"j:&. .+@#$%%%$#@++...+@$%=-;;--=&%$#@#$%&****&%$$$%=>'),-&$#@#$%=--=&%###%-,)),;*%$$&-;;*$@+++@#$##@+...+@@@+++++##$$$$##%=;,>-&$#@#$%&&&%%&-'!!,-*%&-)]^{);=%$%*==&%$$$&-,!!),-*%%*;')),;-*&*-,~]]!,-=**-'^[221[(]),>,!(}4652[(])>;--,!^_<[<_/]~'>;-->!/[29iu", +"j<&. .+@#$%%%$#@++..++@$&=-;;-=*&%##@#$%&****&%$$$&-,)'>=%$#@#$*=-=*%$##$*>))'>=%$#%=;;=%@+++@##$#@++..++@@+++++@#$$$$##%=;,>-&$#@#$%&&&%%&-'!),-&%&;!^^~'-*%$%*=*&%$$%*;)!!'>-&%&=>))'>;=*&=>)]]~';-**=>{:|21}:^~'>>)^[3652}_]),;-->)^_<[<_/]~),;-->!/[250iu", +"j<&. .+@#$%%%$#@+...++#$&=;;;-=*%$##@#$%****&&%$$%=;'),-*$#@#$%=--=&%##$&-')),-&$#$*-;-&#++++@###@++..++@@+++++@#$$$$##%*;,>-&$#@#%&&&&%%&;'!)>=&%*>~^^!,-&$%&*=*&%$$%=,)!),;=&%*;,)),;-*&*-'~]{),-=*=;)(}22|>']:2563|:^!,;-->)]_<[<:(^~),;-->!/[2469ht", +"j<*+ .+@#$%%%$#@+...++#%*-;;;-=*%$#@##%&****&%$$$&-,''>=%$#@#$&=-=*%$##$=>)),;*%$$&-;;*$@+++@#$##@+..++@@+++++@#$$$$##$*;,>-&$#@#%&&&%%%*;)!)>=&%=,{^])>=%$%&=*&%$$$&-'!!'>-*%&=>')'>;=*&=>)]]!';=**-,^[121[(]),>,~_|464|:^!';--;'](:[<:(^~),;-->)/[24557fs", +"j[=+ .+@#$%%%$#++...++#%*-;;--=&%$#@#$%&****&%$$%*;'),;*%#@@#%=--=&$##$&;')'>=&$#%=;;=%@+++@#$##@+..++@@+++++@#$$$$##$*;,>-&$#@#%&&&%%%*>)!';=&&-']^]);=%%%*=*&%$$%=>)!)';=&%*-,)),;-*&*-'~]{)>-=*=>~:|21}_^!,>>)/}4641--;'{(:<<:(^{),;-->)/[245434dr", +"j[=@. .+@#$%%$$#++...+@#%=-;;-=*&%##@#$%&***&%%$$%=>''>-&$#@#$&=-=*%$##%=,)),-*$#$*-;-%#+++@####@++..+@@+++++@#$$$$##$*;,>-&$###%&&&%%%=>)!';*%&-)]^{';*%%&*=*&%$$%-,)!),-*%%=>')'>;=*&=>!]]!,;=**-)/}22|>'^[2552[(])>--;,{/:[<:(^{),;-->)/[24542|2bq", +"k}-#+. .+@$$%%$#@++...+@$%=-;;-=*&$####$&****&%$$$&-,)';*%####%=--=&$##$*;))';=%$$&-;-*$++++@###@++..+@@@++++@#$$$$##$*;,>-&$###%&&&%%%=,)),-*%&;!^^~,-&%%&*=*&%$%*;'!!'>-&%&-,)),;-*&*;'{]{'>-**=,]<121[(]),>']:1553}_]),;-;,~/:[<:(^{),;-->!/[24542}<}0p", +"k}-#@+. .+@$%%%$#@++...+@$&=-;;-=*%$###$%&****&%$$%=;'',-&$#@#$&=-=*%$##%-,))>-&$#%=;;=$@+++@#$##@+..+@@@++++@#$$$$##$*;,>=&$##$%&&&%%%=,!),-&%*>~^]!>=%$%*==*%$$%=>)!),;=&%=;')'>;=**=,!]]!,-=*=;!_|21}_^!,>,!_|454|:^!,;--,!^:<<:(^{),;-->)/[24542}:(<9o", +"j[-#@++. .+#$%%%$#@++..++#$&=-;--=&%$#@#$%&***&%$$$&-,'';=%####%=--=&$##$*>)),;*%$$*-;-%#+++@#$##@++.++@@++++@#$$$$##$*;>>=&$##$%&&&%%&-,!)>=&%=,{^]);=%%%*=*&%$$&-,)!'>-*%&-,)),;-*&*;){]~';-**-'/[12|:/~'>,)/}3541!^_<[:_^]),;-->)/[24541}:/^(7n", +"j[=#@@@+. .+#$%%%$#@++..++#%*-;;--=&%##@#$%&***&%$$$*;,',-*$#@#$&=-=*%$#$&-')'>=%$$&-;-*$+++@####@++.++@@+++++##$$$$#$*;,>=&$##$%&&&%%&-'!)>=&&-']^{';*%%&*=*&%$%*;'!)';=&%*;')',;=**-,!]]),-=*=>]:12|[(]),>'^[2552[({'>-->)^_<[:_/]!,;-->)/[24541}:/]~^5m", +"j[=#@@@@++. .+#$$%%$#@++..+@#%*-;;-=*&$####$&***&&%$$%=>''>=%$###%=--=%$##%=,)),-&$$%=;;=$@+++####@++.++@@+++++@#$$$$#$*;,>=&$##$%&&&%%&;')';=&&-)]^~,-&$%&==*%%$%=>)!),-*&&=>'),;-*&=;){]~';=*=;)(}21}_^!,>,{:1552}(])>;->)](<[<_/]!,;-->)/[24541}:/])'{3m", +"j<*@@@@@@++. .+@$$%%$#@++..+@#%=-;;-=*%$#@#$%&***&%$$$&-,',;*$###$*=-=*%$#$&;')';=%$$*-;=%#+++@#$##@+.++@@+++++@#$$$$#$*;>>=&$##$%&&&%%*;')';*&&;!^]!>=%$%*=*&%%%&-,))'>-&%*;,)',;=&*-,~]{)>-=*-,^[12|:/~'>,!(|453}_]),;-;'](<[<_/]!'>-->)/[24431[:/{),>!3m", +"j<*+++@@@@++. .+#$$%%$#@++.++@$&=-;--=&%$#@#$%&***&%$$%=;'',-&$###%=--*%$##%=,)'>=&$$%-;-&#+++@#$$#@++++@@@++++@#$$$$#$*;>>=&$##$%&&&%%*;)),-*&*>!^]);*%%&*=*&%$%*;'!),;=&&=>'),>-*&=;){]!,;=*=>{:|2|<({),,)/}354|:^!,;-;'{(:<<_/]!'>-->)/[24431[:/{),;;~4m", +"j<*+.++@@@@++. .+#$%%$$#@+++++#$&=-;--=&%####$%&**&&%$$&-,'';*%###$&=-=&%$#$*;'),-*$$%=;;=$@++@#$$#@++++@@@++++@#$$$$#$*;,>=%$##$%&&&%%=>)),-&&=,{^{';*%%&==*%%$%=,)!)>-*%*-,)',;=**-,~]{)>-==-)(}11[_]),>']<2541-->)/[24431[_^{),;;,^7o", +"j[*+..++@@@@++. .+#$%%$$#@+++++#$*=-;-=*&$####%&***&%$$%*;'',-&$##$%=--*%$##%-,)';=%$$*-;=%#++@#$$#@++++@@@++++@#$$$$#$&;>>=%$##$&&&&%%=>)),=&&-']]~,-&%%*==&%%%&-'!)';=&&=>')'>-*&=;)]]!,-=*=,]<|1}:^!'>,{:1442[({'>-;,!/:<<_/]!'>-->)/[2443|[_^~'>;;>!:aq", +"j[=@...++@@@@++. ++#$$%$##@+++++#%*-;;-=*%$###$%&***&%$$%=>''>=%###$*--=&%$#$=>)),-&$$&-;-&#+++@#$##@+++@@@++++@#$$$$#$&;>;=%$##%&*&%%%=,))>=&&-)]]!>=%%%*=*&%$%*;)!),-*&*-,)',;=**-,~]~';=*=;!_}1|,!(|442}(])>-->!^:<<:(]!'>-->)/[2443|[_^~'>;;,!/1ds", +"k}=@+...+++@@@++. ++#$$%$##@++++@#%*-;--=&%$###$%&***&%$$&-,',-&$##$%=--*%$#$&;'),;*%$%=;;*$@++@#$$#@++++@@@+++@#$$$$#$&->>=%###%&*&%%&-,)';=&*;!]]);*%%&*=*&%$%=,))'>-&&=;')'>-*&=>)]]),-==-'/[1|[(]),>)^[353|_])>;->)^_<<:(^~'>;->)/[2442|<(^!'>;;,!(}6ht", +"k}-#++...+++@@@++. ++#$$%$#@+++++@$%=-;--=&%####%&***&%$$%*;''>=%$##$*--=&$##%=,)'>=%$$*-;=%#++@#$$#@++++@@@+++@#$$$$#$&->>=%$##%&*&%%&-,)';*&*>!]{';*%%&==*%%%&-')),;=&&-,)',;=**-'~]~';=*=>{:||}_^!,>']<244|:^!,;->)^_<<:(^~'>;->)^[1442|<(^!'>;;,{(}39iu", +"k|;$@++...+++@@@++. ++#$$%$#@+++++@$&=---=*%$###$%&***&%$$&-,',;*$##$%=--*%$#$&;'),-&$$&-;-&#@+@#$$##@+++@@@+++@#$$$$#$&->>=%$#$%&*&%%&-,),;*&=,~]~,-&%%*=*&%$%*>)!)>-*&=;')'>-**=>!]{)>-==;)(}|}:/~'>,~_1441;->)^[1442|<(]!,>;;'{_}360it", +"k|;%#@@+...+++@@@++. +@#$$$$#@+++++@$&=---=*%$###$%&***&%$%*;,'>-%$##$*--=&$##%-,)';=%$%=;;*$@++#$$$#@+++@#@+++@#$$$$#$&->>=%$#$%**&%%&;'),-*&='{]!>=%%&*=*&%%&-,))';=&&-,'',;=**-'{]!,-=*-,^<||<(]),,!(}342[({';;;'](<[:(^~'>;->)^[1342}<(]),;;>']:|3568gs", +"l1>%$##@++...++@@@+++. ++#$$$$#@+++++#$&=---=&%$###$&***&%$$%=>',;*%##$%=--*%$#$*>'),-&$%*;;=%#++@#$$#@+++@#@++++#$$$$$$&->;=%##$%**&%%*;''>-&&-)]]);*%%&==*%%%*;'!),-*&*;')'>-**=>!]{)>-*=>~_}|[_]),>)^[243}_])>;;,{(<[<_^{)>;->)^<1332}:/]),;;>)^:|45435dr", +"l1,&%$##@++...++@@@@++. ++#$$$$#@+++++#%*=--=*&$###$%&***&%$$&-,',-&$##$*--=&$#$%-,),;*%$&-;-&#@+@#$$##+++@#@@+++#$$$$$$&->;=%##$&**&%%*;''>=&*;)]{';*%%*==&%$%=>))'>=&&=>'),;=**;'{]!,-==-)/[|}:^!,>']<243|:])>;;,~/:[<_^{)>;-;)^<1332}:/]),;;>)^<14542|1bp", +"l2'*%%$##@++...++@@@@++. .+@#$$$$#@++++@#%*=--=*%$###$%&***&%$%*;,';=%##$%=--=%$#%=>''>=%$%=;;*$@@@#$$$#@++@##@+++#$$$$$$&->;=%##$&**&%%=>'';=&*;!]~,-&%%*=*&%%&-,)),;=&*;,)'>-=*=,!]~';===,]:}};-;)^<1331}:/{),;;,!/[24541[:[0o", +"l2'=&%%$$#@++...++@@@@++. .+@#$$$$#@++++@#%*---=*%$###$%&**&%$$%-,',-&$##$*--=&$$$&;'',-&%%*;;=%#@@#$$$#@++@##@+++#$$$$$$&->;=%##%&=*&%%=>',;=&=,~]!>=%%&==*%%%*;'))>-*&=>'),;=**;){]!,-==;!([}[(]),,)(}342[/!,;;,!/:[<_/]),;-;)^<1331}:/{)>;;,~(}24531[_/_7n", +"l1,=*&&%$$#@@++..++@@@@++.. .+@#$$$##@++++@$&=--==&%####$&***&%$%*;,'>=%##$%=--=%$$%=,'';=%$&-;-&$@@#$%$$#++@##@@++@#$$$$$&->;=%##%*=*&%%=>',-*&=,{]);*%%*==*%%%=>))';=&*-,)'>-=*-,~]~';==-'^<}[_^!,>'^[242[({'>;>!^:<<:/]),;-;)^<|221[_^~'>;;'{_}3553|<(]~^5n", +"k|,*&*&&%%$##@++.+++@@@@++.. .++#$$$##@++++#$&=--=*%$###$%&**&%%$%=>',;*$##%*-;-&$$$*;''>-&%%=;;*$#@#$$%$#@+@###@++@#$$$$$&->;=%##%*=*&%%=>',-*&-)]{'-&%%*=*&%$&-,)),-*&=>'),;=*=;)]])>-==>~_[[:/~'>,]:243}_]'>;>)^:[[:/]),;-;)^<|22|[_^~'>;;']:|3542}:/])'{4m", +"k};&%&*&&%%$##@++.+++@@@@+++.. .++##$$#@@++++#$&=-==*%$#@#$%&**&%$$&-,'>=%##$&=;-=%$$%-,',;*%%*;;=%#@@#$%$#@+@###@++@#$$$$$&->;=%#$%===&%&=>,>=&*;)]~,-&%&==*&%%*;')'>=**-,)'>-=*-,~]~';==-)/<[<({',,!_|43|:])>;>)]_[[:(]),;-;'^<|22|[_^!'>;>)^:|3442}:^{),>!2m", +"k}-$$%&&&&%%$##@++.+++@@@@@++... .++##$$#@@+++@#%&===*&%$#@#$%&**&%$%*;',;*$##%*-;-&$$$*>''>=%%&-;-&$@@#$%%$#@@###@++@#$%$$$%->;=%#$%===&%&-,,;=&*>!]!>=%%&==*%%%=,)),;=*=;'),;=*=;)]{)>-==,]:[<(]),,)/}341<^!,;>']_<[:(]),;-;'^:|22|<(]!,>;>)^<14431[_^!'>;;)3m", +"j[-$#$%&&*&&%$$#@+++.++@@@@@+++.. .++##$##@++++@#%*===*&$#@@#$%&*&&%%&-,',-%$#$&-;;=%$$&-,',-&%%=;;*$#@#$%%$#@@####@+@#$%$$$%->;=%#$&=-=&%&-,,;=&=,~{);*%%*==&%%&-'))>-**-,)'>-=*-'{]!,-==;!(<[_^!,>'^[242[/!,;;'](<[<(]!,;-;'^:|22|<(]!,>;,!/[2443|[(]!,>--;{5n", +"k}-#@#$%%&&&&%$$#@++++++@@@@@+++....++@####@++++@#%*===*%$#@#$%&**&%%%*;,';=%##%=;;-*%$%=>',;*%%*;;=%#@#$%%$#@@####@+@#$%$$$%->;=%$$&=-=&%*-,,;*&=,{{'-&%%*=*&%%*;))';=*=;'),;=*=>!]{);==-'^:<:/~',,{:142}({'>;,{(<[<(^!,;-;']:|21}<(]),;;,~([2442|',-&$#$&-;;=%$$&;,'>=&%&-;-&$##$%%%$#@##$#@+@#$%$$$%=;;=%$$*--=&%*;,>-**-'{~,=%%&==*%%%=,)),-**-,)'>-=*-'{]!,-==>~(<:({),,!_|33|_])>;,~(<[<_^!,;-;']:|11}:/]),;;,{(}2442}:/~)>;-->)^}cr", +"k|;$#@@##$%&&&&%%$##@+++++@@#@@@+++...++@####@++++#$&*==*%$#@@#$%&&&%%$&-,'>=%##%=;;-&$$%=>',-*%&=;;=%###%%%$#@##$#@+@#$%$$$%=>;=%$$*--=&%*;,>-**;){!>=%%*==*%%&;')'>=*=;')';=*=>!]{';==-)^::(]),,)/}33|:^)>;,!/<[<_^!,;-;']:}1|}:/{),;>']_|3431[_^!'>---,!^<4fs", +"k|>%##@@@#$%&&&&%%$##@+++++@@##@@+++...++@####@+++@#$&*==&%$#@##$%&&&%%%*;,,;&$#$&-;;=%$$*;,,;=&%=;;-%###$%%%#@##$#@@@#$%$$$%=;;=%$%=--=&%*;>;=&*>!{);*%%*==&%%=>)),;=*-,)',-=*-'{])>-=-,]_:_^!,>'][231<^!,;,!/:[<_^!,;-;']:}1|[:/{'>;>']:|343|[(]!,;--;,{([28ht", +"l1,&$$#@@@#$%%&&&%%$##@+++++@@##@@+++...++@###@@+++@#$&*=*&%$#@#$%&&*&%%%=>'>=%##%=;;-*%$%-,'>-&%*->-*$##$%&%$###$$#@@#$%%$$%=;;*%$%=;-=&%=;>;=&=,!~'-&%&==*&%&-,))>-*=;')';=*=,!]~';==;!/:_/~'>,{:132[/~,>>)^:[[_^!,;-;,]:}||[_^~'>;>)^<1342|)]:}248gt", +"l1,*%$$##@@##$%&&&%%$$#@++++++@##@@@++...++@###@@+++@#%&*=*&$#@@#$%&&&%%%&;,,;*$#$&->;=%$%*;,,;*%&-;;=%##$%&%$###$$#@@#$%%$$%=;;*%$%=;-=%%=;>-**=,~!,=%%&==*%%*;')';=*->)),-==;)]])>==-,](_/]),,!(|32}({'>>)^:[[:/~';-;,]:}||[_^!'>;>)^<1442}:/~'>;-;,!/<|3446er", +"l2'=&%%$##@@##$%&&&&%$$#@++++++@###@@+++..++@@##@@@++@#%&**&%$#@@#$%&*&%%%=>,,-%$#%=;>-*%$&-,,>=&&=;;-&$#$%&&%###$$#@@#$%%$$%=;;*%$%-;-*%%=;>-**-'{!>*%%*==&%%=>)),-==;,)'>=*-,~]~,-==>!/_(]),>)/}23|:])>>)]_[[:/~';-;,]_}|}<(^!'>;,!/[2431[_^!'>--;,{([134212cq", +"l2'=*&%%$$#@@@#$%%&&&%%$##@+++++@###@@+++..++@@##@@@+@@$%&**&%$#@@#$%&&&%%&-,,;*$#$&->;=%$%=>,,-*%*->-*$#$%&&%$##$$#@@#$%%$$%=;;*$$&-;-*%&=;;-**;)~);&%&===&%&-,)'>=*=>'),-==;)]]);==;)^((^!,>']<23|:^),>']_[[:/{';-;,]_[|}<(]!,>>,~(}233|[(]),;-->)]:}2332}<}0p", +"l2'=**&&%%$##@@##$%&&&%%$##@+++++@####@@++..++@@@@@@@+@#$%&**&$#@@#$%&&&%%%*;,,-&$#%=;>-*%$&;,,;=&&->;=%##%&*%$##$$$#@@$%%$$%=;;*$$&-;-*%&=;;=*=>!~'-&%&==*&%*;'),;==;,)'>-=-,~]!,-=-,{/(^~'>,~:131'{_[[:/{';-;,]_[|}<(]),;>'{_}232|,>=%#$*;>;=%$%=>,>-*&=;>-&$#$&*&%##$%$#@@$%%$$%=;;*$$&->-*%&-;;=*=,!!,=%%*==*%%=>))>-==>'),;==;)]{);==;)^(/{),,!(|32[(~,>,{(<[<({';-;,{_[}}:(]),;>']:|232}:^~'>;-;'{([1332}<(^{/6n", +"k|,******&&%$$##@##$%%&&%%$$#@+++++@#####@++..++@@@@@@@@@#$&**&%$#@@#$%&&&%%*;,,-&$$%=>>-*%%*;,,;=&*;>;*$#$&**%$#$%$#@@$%%$$%=;;*$$*;>-*%&-;-=*=,!!>*%%=-=&%&-,)';==-,)'>-=-'{]!,-=-,]//]),>)^[22}({'>,~(<[<(]'>-;,{_[}[:/{)>;>)^:|231[_^!,;-->)]:}2321[:/]))]4m", +"k};&&&****&&%%$##@@#$$%&&&%$$#@+++++@#####@+++..++@@@@@@@@#$&*&&$#@@@#%&&&%%%=>,>=%$$*;>;=%$&->,>=&*->;=%$$%**%$#$%%#@@$%%%$%=;;*$$*;>-*%*-;-**-'~);&%&=-=&%*;'),-==>'),;==>!]{';==>!^/]!,>']<12|:]),,!/<[<(])>-;,{([}[:/{'>;>)^<132|[(]),;-;,!/<|232|<(^~),>~3m", +"k}-$$%&&****&%%$$##@##$%%&&%%$#@@++++@#####@@++..++@@@@@@@@#%&&&%$#@@#$%&&&%%&-,,;*$$%=>>-*%%=;,,-*&=;>-&$$%**&$$$%%$@@#%%%$%=;-*$$=;>-&%*-;-**;)!'-&%*=-*&&=,)'>==-,)'>-=-'{])>-=-']^^~'>,~_|21<^),,!/<[[_])>--,{(<[[_^~'>;>)/[132|;-;'{([1321}:/]!'>;;~4m", +"j[=##$%%&****&&%%$##@##$%%&&%%$##@++++@#####@@++..++@@@@@@@##%&&&%$#@@#$%&&&%%*;,>-%$$*;,;=%%&-,,;=&=;>;*$$%***%$$%%$#@#%%%$%=;;*$%=>>-&%*--=*=>)!,=%%*-=*%&-'),;==;'),;==>!]~'-=->!^^{),>)(}21[/!,,)^:[[_])>--,~(<[<_^!'>;,!([122}:^~'>;;>)^:}222|[_^~),;;;,^7o", +"j[=#@##$%&*****&&%$$#@@#$$%%&%%$##@++++@######@++..++@@@@@@@#$%&&%%##@@#$%&&%%&=>,;*$$%=>>-*%%=>,>-**->;=%$$&=*%$$%%$###%%%$%=;-*$%=>>-&%*--=*=>!)>*%&=-=&%*>))>-=-,)'>-=-'{]);==;)]^]),>'^[22}(~',)^:[[_^)>--,~(<[<(^!,>>,~(}221[_^!,;-;,!/<|221}:/]!'>;;;,~:aq", +"j[=@+@@#$%%&*****&%$$##@##$%%&%%$##@++++@######@++..++@@@@@@@#$%&&%$#@@@#%%&&%%*;,,-&$$*;,;=%%*;,,;=*=;>-&$$&==&$$%%$###%%%$%=;-*$%-,,-&%*--=*=,!);&%&=-*&&=,)';==;'),;==>!]~,-=-,~]]!,>,]:12}_{',)]:[[:^)>-;,~(<[:(]!,>>']_}22|[(]),;-;'{([122|[_^~),;;;>)]_2es", +"j[=@+++@##$%&*****&%%$##@##$%%%%%$$#@++++@##$$##@++.+++@@@@@@@#$%&&%$#@@#$%&&&%%=>,>=%$%->>-&%%=>,>=*=;>;=%$%==*%$%%%###$%%$%=;-&$%-,,-&%*--**-'!'-&%*-=*%&-'),-=-,)'>-=;)]]);==>)]]~'>,!_|2|:]),']_[[:^)>--,~(<[:(]),>>']:|22|:/{'>;;>)^:}121}:(]!'>;;;,~/<|7ht", +"j[=@++++@@#$%%&****&&%$$####$$%%%%$$#@++++@##$$##@@+++++@@@@@@##$%&%%$#@@#$%&&%%&-,,-&$$*;,;=%%*;,>-**->>=%$%*=*%$%&%$##$%%%%=;-&$%-,,-&%=-=**;)!,=%&=-=&&=>''>-=;'),;=-,~]!,-=-'~]~),>)/}21<^),'{([[:^!,;-,~(:<:/]),;>)^<|21}:^!';;;,!/<|21|[_^{),;;;,)]_}249ht", +"j[=@++++++@##$%&*****&%%$#####$%%%%$$#@++++@##$$$##@++.++@@@@@@##$%&%$#@@@#$&&&%%*;,>=%$%->>-&%&->,;=*->>-&%%*==&$%&%$##$%%%%*;-&$%;',=&&=-=*=;))>*%&=-=&&-,),;=->)'>-=;)]{';=->!]{),>'^[11[/!,'~(<[:/!,;-,~/:<:/{)>;>)/<|21[_]),;;;'{([|11}<(]!'>;;>'{(<|3448fs", +"j[=@+++++++@@#$%%&****&&%$#####$%%%%%$#@@+++@##$$$##@+++++@@@@@@#$%%&%$#@@#$%&&&%&=>,;*$$*;,;=%%=;,>-*=;,;=%%&==&%%&&$##$%%%%*--&$&;',=&&===*=>));&%*--*&*;''>-=;,),;=-,~]!>-=;'~{!,>,{:|1}(~''!/<[:/!,;-,!/:<_/~'>;,!/[12|<(])>;;>)]_}11|[_^{),>;;,!^:}244324dr", +"j[*@+++++++++@##$%&****&&%$$##@#$$%%%%$##@+++@@#$$$##@+++++@@@####$%%%%$#@@#$%&&%%*-,>=%$%->>-&%&->,;==;,>=&%&==*%%%&$##$%%%%*--&$&;',=&&===*=,)'-&%=-=*&=>'';-->''>-=;)]{'-=-,!{!'>,!(}1}_{''!/:[!/::_^~'>;,~([11|;;,!^:}1|}<(]!'>;;>']([13432}[|ap", +"j<*++++++++++++@#$%%&****&%%$##@##$%%%%$##@+++@##$$$$#@+++++@@#####$%%%%$#@@#$%&&%%=;,;*$$*;,;=%%=>,;==->,-*%&==*%%%&%##$%%%%*--&$&;'>=%&==**-,),=%&=-=&&-,',-=;,),;=-,{])>==;)~!),>)/[1|:])')^:[<(~,;;>!/::(^!,>;,{(}11}:^!,;;;,{([|||[_^{),>;>,!^:|2432|[_(:8o", +"j<*+..++++++++++@##$%&****&&%$$####$$%%%$##@+++@##$$$$#@+++++@@#####$%%%$#@@#$%&&&%&->>-&$%->>-&%*;,>-==;,;=%&=-=&%%&%$#$%%%%*--&%&;'>=%&==**;')>*%*--*&*;'';-->''>-=;)]~,-=-,!~),>']<1|<^)')^:[<({,;;>!/_:(^!,>>']_}1|[_]),;;>']_[||}<(]!'>;;>)]_[13431}:(]~/5n", +"j<*+....++++++++++@#$$%&****&%%$#####$%%%$$#@+++@##$$$$#@+++++@@#####$%%%$#@@#$%&&%%*;,;*%$*;,;=%&=>,;==;,>-&%*-=&%%&%$#$%&%%*--&%*;'>*%*==*=;'';&%*--*&=>',;-;,),;=-,{{);=->)!),>,~:|1[/!')]_[<({';;>!^__(]),>>)]:}1|<({'>;;>)^:[}}[_^{),>;>'~/<|2331}<(^~',~3m", +"j[*+.....++++++++++@@#$%&*****&%$##@##$%%%$$#@+++@@#$$$$#@+++++@#####$$%%%$#@@#$&&&%&=>>-&$%->>-&%*;,>-=->,-*%*=-*%%&&$#$%&%%*--&%*>';*%&==*=>),-&&=-=&&-,'>--;'',-->!]!,-=;'!!'>>)(}|[(~')]_[[_]';;>!^__/]),;>)^<||}:/~';;;,~/:}}[:(]!'>;;,)^:}2332|[_^{),;;)2l", +"j[=@+......+++++++++@@#$$%&****&%%$####$$%%$$#@++++@#$$$$##++++@@#####$%%%$##@@#%&&&%*->>=%$*;,;=%&->>-=->,;=&*=-=&%&&$#$%&%%*--&%*>,;*%&==*=,),=&&--=&*;',;--,)';--'{{';=-,)!),>'^[|}_{)'{([[_]';;>!^(_/]),;>)/<||[_^!,;;;'](<}}<_^{),>;>'{([1332|[:/]),;-=-)2m", +"j[=@+++.....++++++++++@@#$%&*****&%$#####$$%$$##@+++@#$$$$##++++@@#####$%%%$#@@#$%&&&&=;,;&%%->>-&%=;>;==;,>-&&=-=&%&&%#$%&%%*--&%*>,;&%*=**-,'>*%*--*&=>',--;'',-->!{!>--;'!),>,]:|}:]))~(<[_]';;>!^((/{)>;,!/[||[(])>;;>)]_<[[:(]!'>;>,!^:|2331}<(]!'>-===;{5n", +"j[=@+++++....+++++++++++@#$%%&****&%%$####$$$$$##@+++@#$$%$$#@+++@@#####$%%%$#@@#$&&&&*->>=%%*;>;*%*->>-=-,,-*&=--*%&&%$$%&%%*--&%=>,-&%*=**-,';&&=-=**-,,;--,'';-;'{~'-=-,))'>,~_}}:^)'!/<[:^)>;>!^((^{'>;,~([|}<({'>;;,!^_<[<_^{),>;>)]([1332|<_^~'>;-==->)(9o", +"k[=#++++++....+++++++++++@@#$%&*****&%$#####$$$$##@+++@#$$%$$#@+++@######$%%%$#@@#%&*&&=;,;*%%=>>-&&=;>;=->,;=&*--*%&&%$#%&%%*--&%=>,-&%*=*=;',-&&=-=&*;,,;-;'',-->!{)>-->))',>)/[};>)^((^~'>>,{([|}:^!,;;;,~/:<<:/]!'>;>,~/<|232|[_/{),;-==-;,!^[ap", +"k}-#@@++++++++++++++++++++@@#$$%&****&%$$####$$$$$#@+++@#$%%$$#@+++@#####$$%%%$#@#$%&&&&=>>-&%*;>;*&*;>;--;,>=&*--=&&*&$$%&&%&--&%=,,-&&*=*=>',=&*--**=>,>-->'';-;'{!,-=;')),>'^<}[(~))^:<:^)>;>)^((^!'>>']_[}[_^),;;>'](:<:(^~),;;,)]_}1321}:/]),;-==-;,)]^_|bq", +"k}-#@@@@++++++++++++++++++++@@#$%&*****&%$####$$$$$#@+++@#$%%$$#@++@######$%%%$##@#$&*&&*->;=%%=;;=&&->>-=;,,-**--=&&*&$$%&&%&--*&=,,-&&*=*=>'>=&=--**-,,;-;,',-->!~);=-,)),>,{:}[({))]_<:^)>;>)^((^!,>>']:}}<(])>;;,)](::_/]!'>;>'~(<|222}<(]!'>-==-;,)]^(_:|bq", +"k};$##@@@@+++++++++++++++++++@@##$%&****&%$#####$$$$#@@++@#$%%%$#@++@##$$#$$%%%$#@#$%&*&&=;>-&%*->-*&=;>;-->,;=*=--*&&&$$%&&%&--*&-,,=&&*=*-,';*&=-=*=;,>-->'';-;)~!,-->')'>,!([}:]))]_<:/!>;>)]//]!,>>)^:}};-=-;,){^(____[0p", +"k};$####@@@@+++++++++++++++++++@@#$%&*****&%$####$$$$##@++@#$%%%$#@+@@##$$$$$%%%$###$%**&*->>=%%=;;=&*->>--;,>=*=--*&&&%$%&&%&=-*&-,>=&&**=-,,-**--=*=>,;-;,',--,!~';-;,)',>)^<[:^!)](<:/!,;>)]//]),>,)^:}[:^!,;;>'{/__(/])'>;>'{([|22|[:/{),;-=-;,){^(___(//:9o", +"k};$$#####@@@++++++++++++++@@@+++@##$%&*=**&%$####$$$$##@++@#$%%%$#@@@@#$$$$$$%%%$###%&**&=;>;*%*-;-*&=;>;-;,,-*=--*&&&%$$&&%&=-*&-,>=%&**=;',=&=--**-,,;->'';-;)~)>--,)),>']:[)]//]),>,!/<[[_])>;;>)]/((/]!',>>,!^:}121}:(]),;-=-->'~^((__(/^]{(7n", +"k};$$$######@@@@+++++++++++++@@@++@@#$%&**=**%$#####$$$##@++@#$%%%$#@@@##$$$$$%%&%$##$%****->>=&%=;;=&*->;-->,;==--=&&&%$$%&%&=-*&-,>=%&**=>'>=&=-=*=;,>--,',;-,!!,;-;')',,~_[)]/^]),>,~(<[<({'>;;,)]/((^{),>;>)]([|21}<(]!'>-=-->'~^/(__(/^]!))]4m", +"k}-$##########@@@@+++++++++++@@@@@@@@##$%&*=**&%$####$$$$#@@+@#$%%%$#@@@#$$$$$$%&&%$##$&***=->;*%&-;-&&=;>-->,>-*--=*&*%$$%&%&=-*&-,>*%&**->';**--=*->,;-;,'>-;)!);-;,)',,)/<<({)!^::(~,;>)]/^{),>,{(<[:/!,;;;,!^/(/]!'>;>,~/<|11|[_^~'>---->'!]/(__(/^]!)'>>!3m", +"j[-#############@@@@+++++++++@@@@@@@@@@#$%&**=*&%$####$$$$#@@+@#$%%%$##@##$$$$$%%&&%###%&***=;>-&%=--*&=;>;-;,,-==--*&&%$$%&%&=-**-,;*&***-,,-*=--=*->>-;>',;;,!!,-->'',,'^:<_])!^_:({,>>)]^^{',>'](<<_^),;;>'~^//^{),>;,)]_}11|}:/{),;---;,!]/(_((/^]!),>;-;)3m", +"k[-#@@############@@@@++++++++@@@@@@@@@@##$%&*==*&%$####$$$##@+@#$%%%$$###$$%%$$%&&&$##$%****->;=%&-;=&*->;-;,,;==--*&&&$$%&&&=-**->;*&*==-,,-*=--*=;>;-;,,>->)!';-;')',,{_<_^!!](:({'>,)]^^~'>>)]_<<(])>;;>){^^^]!'>;>'~(<|11}<(]),;---;,)]^((((/^{!),>;---;~4m", +"k}-#@@@@####$$$#####@@@@+++++++@@@@@@@@@@@#$%&*==*&%$####$$$##@@@#$$%%%$###$%%%$$%&&%$##$&***=;>-&%*--*&=;>;->,>-=--=&&&%$%&&&=-**->-*&**=;,>=*=-=*->>;->,,;;,!)>-;,)',,!(::^!!](:(]'>,)]^^~'>,)^_<:/~';;;,)]^^]~),>>,)^:}11|<(]!,;---;,){^/(((/]{!),>;----;,^7n", +"k|;$##@@@@####$$$$####@@@@+++++@@@@@##@@@@@##$%**==*&$####$$$##@@@#$%%%%$###$%%%%%%&&%$#$%*=**-;;=&&=-=&*->;->,,-=--=&&&%$%&&&=-**-;-&&*==>,;==--==->;-;,,>;>)!';->'),,)^::/~!](:(]'>,)]^]!'>,)^_:_^!,;;;,!]^]{)'>;>'{([|1|[_^~'>---;>)~^/((/^]{!',>;---;;,){:0p", +"l1,&$$##@@@@####$$$$#####@@@+++++@@@####@@@@@#$%&*==*&%$####$$##@@@#$$%%%$##$%%%%%%%&&%$$$&*=*=;>-*&*-=*&=;;;;,,;=--=*&&%$%&&*=-**-;=&&*=->,;==--==;>;->,,;;,))>-;')',']_:({!{/_(])>,)]^]!,>,!^_:(])>;;>'!]]]!',>>,!^:}||[:/{)>;--->'~]/((/^]~!',>;---;>,){]/[ap", +"m2)=&%$$##@@@@###$$$$$$####@@@+++@@@@######@@@##$%**=**%$####$$$##@@#$%%%%$##$%&&%%%&**%$$%*===-;;=&&=-*&*;;;;,'>--;-*&&%$%&&*=-**-;=&&*=->>-=--==-;;-;>,>;>)),;;,)',,~(:(]!~/__]),,)]^]!,>,!/::({'>;;,)~]]~),>;>)]_[||}<(]),;--->'!]^///^]~)',;;---;>'!{^/(_}ap", +"m4~;=*&%%$###@@@###$$$$$$$###@@@@@@@@@#######@@@#$%&*==*&%$###$$$##@@@#$%%%$$$$%&&%%%&*&%$$%*===-;;*&*==&&-;;;>,,----=&&%%%&&*=-**--=%&*=->>-=--==->;-;,,;;,)'>;>'),,)^_(]!!^_(^),,)]^]),>,~/__/~,;;;,)~]{!',>>,!/<}|}<(]),;---;,){^///^]~)',;;---;,'!]^/(((([0p", +"n6^,>;-=*&%$$##@@@###$$$$$$$###@@@@@@@@########@@##%&*===*%$###$$$##@@##$%%%$$$%&*&&%&**&%$%&====;;-&&==*&=;;;;,,;---=&&%%%&**=-**--*&&*=;,;==--==;;-->,>;>)),;;,)',)]((^!!]((^),,)]^]),>'~/_(^),;;>'!~{~),>>,)]_[||[_^!,;---;,)~]^/^]{!)'>;---;>,)~]^/(((/^^:9o", +"n7/)',>;-=*&%$$##@@###$$$$$$$$$##@@@@@@@#########@##$%&*==*&$$###$$$#@@##$%%%$$$%&**&%&**&%$%*===-;;=&*=*&*-;;;,'>---=&&&%%&&*=-**--*&*==;,;=---=-;;-;,>;;,),;;,)','{/(^~!]/(^),,)]]{),,'{/(/])>;;>'!~~!',>>'~/<}|[:/~'>---;>'!]^^^]{!),>;---;>'){]/(((/^^]{~(7n", +"n6^))'',,;--=&%%$#######$$$%%%$$$##@@@@@@####$$###@@##$&*==*&%$###$$$##@@#$%%%$$$&***&&&**&%%&====;;-*&*=&&=;;;>',;-;-*&%%%&&*=-**=-*&*=-;>-=--==-;;;>,>;>''>;>'),,!^(^~!{/(^!,,)]]{),,)]/(^~,;;;,)!~!),>>,)^_[}}<(])>;--->'!]]^^]~!',>;---;>'!{^/(((/^]]~!))]5m", +"m4{,,'')'',>;-=*&%$$######$$%%%%%$$###@@@@@###$$$$#####$%&*==*%$###$$$##@##$%%%%$%&*=*&&*=*&%%*===-;;=&&**&*-;;;,,;-;-*&&%%&&*==**==*&*=->>-=--==;;-;>>;;,',;>')',)](/{!{^(^!,,)]]{),,)]//]!,;;>,)!!)',>>'{(<}}<(]),;---;,){]]]{~)',;;--;;,)!]^/((//^]{!)',>>~4m", +"l2)-;;,,'''',>;-=*&%$$#####$$%%%%%%$$$##@@@@###$$$$$####$%&*==*&%$##$$$#####$%%%%$%&==*&&*=*&%&=-==-;-*&**&&=;;;,'>;;-=&&%%&&*=-**==&&*=->>--;-=-;;-;>>;>''>;,)),'{//]!~^(^!',)]]{),,)]//])>;;>'!!!),>>,!^:[}[_^!,;-=-;,)!{]]{!)'>;;--;>,)~]^/(//^]]~)),,>;;;~4m", +"l1,**=-;>,,''',,>;-=&%%$#####$$%%&&&%%$$##@@@###$$$$$$####$%*===&%$##$$$$####$%%%%%%*===**==*&%&=---;;=&&*&&=;;;>',;;-=&&%%&**==**==&&*=;>;--;-=-;-;>>;;,',;>')''!^/]!~^/^~'')]]~',,)]^^~'>;;,)!!)'>>>)](<[[:/~';-=-;>'!~{{~!),>;---;>,){]^/(//^]{!)',>;;;;;,^6n", +"l1,*&&**=-;>,'''',>;-=*&%$$####$%%&&&&&%%$###@###$$$$$$$###$%&*==*%$$#$$$$####$%%%%%&*===**==*&&*----;;=&&&&*-;;>,,;;;=&&%%&&*===*==&&==;>;---==-;-;>>;>',>>')'')]^]!!]/^~''!]]~',,)]^]!,;;>,)!!),>>,!^:[[:({'>-=-->')!~~!)',>;---;>'!{^////^]{~)',>>;;;;>,){:0p", +"l2'=&&&&&*==-;,,''',,;-=*&%$$###$$%%&***&%%$###@###$$$$$$####$%*==*&%$#$$$$####$%%%%%&=--=*===*&&=---;;-*&&&&=;;;,'>;;-*&%%&**==**=*&&=-;>;-;-=-;-->>;;,',>,))'){^]~!]^^~''!]]~','!]]{)>;;>')!)',>,)](<[<(])>--=-;,)!!!!)',;;---;,'!]^///^^]~!)',>;;;;>,)!]/_|cq", +"m3!-=**&&&&&*=-;>,,'',,>;-=&%%$$##$$%&**=*&%%$######$$$%$$$###$%&*==*%$$$$$$$###$%%%%%&=--=====*&*----;;=&&&&*-;;,',;;-*&%%&**===*=*&*=->>--;-=---;>>;>,,>,')''~]]~!{^^{)'!]]!','!]]~'>;;,'))',>>'~/:<<_^!,;-=-;,')!!)',>;----;,)!]^^//^]{~)',>>;;;>,'!]^(:<[2dr", +"m4~;--==**&&&&*==-;>,,,,,>;-=*&%$$#$$$%&*===*&%$######$$%%%$$##$$%*==*&%$$$$$$###$%%%%%*=--===-=**=---;;-*&&%&=;;>',>;-=&%%%**===**&&*=->;---==---;>;;,,>>')''!]]{!{^^{)'!]]!','!]]!,;;>,)))',>,)](:<_/~';-=-;>'))))',>;---->,)~]^^^^^]~!)',>;;;>,'!{^(_:<[[[1bq", +"n5],;;;--==**&&&&*==-;>,,,,>;-=*&%$$$$$%%&*===*&%$$####$$%%%$$$##$%&*=*&%$$$$$$$##$%%%%&*-;-===-=**=---;;=&%%%*-;>,'>;;=&%%%**===**&&*=;>;-;-=---;>;;>,,>,))'){]{!~]^{))!]]!','!{~),;;>'))),>,'{/:::/{'>-=-->,'))',>;;---;>,)~]^^^^]{!)',>;;;;,'){^(_:<[<<:__[0o", +"n5],>>>;;;--==**&&&&*=-;;>,,,>;--=&%%$$$$%&*==-==&%$$####$$%%%%$$$$%&*==*%$$$$$$$##$%%&%&=-;-==--=*=---;;-*%%%&=;;,',;;=&%%%**===**&&*=;>;-;-=---;>;;,,>,')')!]{!!]^{))!]{!','!~!'>;;,'))',>,!](::(])>----;,'''',>;----;>'){]^^^]]~)',>>;;;>,)~]/_:<<<<:_(^]](7n", +"m4{,>>>>>>;;;--==**&&&**=-;>>,,>>;-=*%%$$$$%&*=---=*&%$###$$$%%%$$$$$%&*=*&%$$$%$$$$$%&&&&=-;;----===-;;;;=&%%%=-;>',>;-*&%%&*=-=**&&*-;;;;;-=---;;;>,,,'))'!{{!!{]{!)!]{)','!!),;;>,))),,,'{/_:(^!,;-=-;>,'',,;;----;>'!{]^^^]{!)',>;;;>,)!]/(:<<<<:_(^]~!)']4m", +"l2);;;>>>>>>>;;;--==**&&&**=-;>>>>;;-=*&%$$$$%&*=---=*&%$###$$%%%%$$$$%&*==&%$$$%%$$$$%%&&*=;;;----==-;;;;-=%%%&-;>,',;-*&%%&*=-=*&&&=-;;;;-=---;;;;,,>,))')~{!!{]{!)~]{),,'!!'>;;,'))',,'!^(__^~';-=-;>,,,,>;--==-;,'!{]^^]{!)',>;;;>,'!]^(_:<<::_/^]~)',>;>!3m", +"k|,**=--;;>>>>>>;;;--==**&&&*==-;;>>;;-=*&%%$$%%&==---=*&%$###$$%%%%$$$%%*==*&%$$%%$$$$%%&&*-;>;----==-;;;;-&%%%=;;,',;-=&%%&*=-=*&&*=-;;;;-=---;;;>,,,')))!{~!{]]!)~]{),,'))'>;>,)))',,){/__/{'>-=--;,,,>>;--=--;,)!{]]]]~!),,>;;;>'){^/_::<::(/^]~)',>;;--;!3m", +"k};%$%&*==-;;>>>>>>>;;--==*&&&&*==-;;;;;--=*&%$$%%&=--;-=*&%$##$$$%%%%$$$%&==*&%$$%%%$$$%%&&*-;>;----=-;;;;;=%%%*-;,',>;=&%%&*=-=&&&*=->;;;-=--;;;>,,,')))!~~!{]]!!~]{),,')),;;>'))',,'!^((/])>----;>,,>;;-==-->,)!{]]]{!)',>;;;>,)~]/(::::_(/^]!)',>;;----->{5n", +"k};$##$$%%&*=--;>>>>>>;;;--==*&&&&*==-;;;;--=*&%%$%%&=--;--*&%$##$$%%%%%$$%&*==*%%%%%%$$$%%&&=->>;;-----;;;;-&%$%=;>,',;=&%%&*=-=&%&*=;;;;-==--;;;>,,'))))!!!~]]~!~{~),,')'>;;,'))',,)]/(/]!,;---;>>>>;--==-;>,)~{]]{~)',>;;;>,'!]^(_:::_(/^{!)',>;;----;>,'!(8o", +"k|>%$$####$$%&*==-;>>>>>>>;;--=**&&&&*==--;;--=*&%%%%%&=-;;;-=&%$$$$$%%%%$$%%*==*&%%%%%%$$%&&*=;>,;;;---;;;;;=%%%*->,',;-*&%&*=-=&%%*-;;;;-==--;;>,,,))))!!!!]]~!~{~),,'',>;>,)))','!^//^~';---;;>>;;-===-;>')~{{{~!),,>;;;>'){^/(_:__(^]{!),>;;----;;>,)!{^(}bq", +"l2'*&%%$$###$$$%%&==-;;>>,,>>;;-==*&&&&&*==-----=*&%%%%%&=-;;;-=&%$$$$%%%%%%%%&*==&%%%%%%$$%&&*=;,,;;;;--;;;;-*%$&=;,',>-=&%&*=-=&%%*-;;;;-=--;;;>,,'))))!!!{{~!~{~),,',,;;>'))',')]^/^{)>---;;>>;;-===-;>')~{{~!)',>;;;>,)~]/(___(/^]~)',>;;---;;>,')~]^(_:[2cr", +"m4~;==*&%%$$$$$$$$%%&*=-;>>,,,>>;;-==*&&&&&*==----=**&%%%%&=-;;;-=&%$$$$%%%%%%%&*==*&%%%%%%%%%&*=;,,>;;;;;;;;;=%$%*->,,,;=&%%*=-=&%%*-;;;--=--;;;>,'))))!!!~{~!~{!',,,,>;>,)))'')~]^^]),;---;;;;--===-;,')!~~!)',>;;;>,'!]^/((((/^]~)',>;;---;;,')!]^(_::<<[[2cr", +"n6^'>;;-==*&%%$$$$$$$$%&*=-;>>,,,,>;;-==*&&&&&*===--==*&%%%%&=-;;;-=&%$$$$%%%%%%%*==*&%%%%%%%%%&*=;,,>>;;;;;>;-*%$&-;,',;=&%%*--=&%%*-;>;-==-;;;>,,)))))!!!~~!~~!',,,,>;>,)))''!{^^]!,;---;;;;--===-;,)!!~!!)',>;;;>')~]/(((/^]{!)',>;;--;;>,)!{^/(_:<<[[<<:<|bq", +"n7(!)',,>;;-==*&%%$$$$$$%%&*=-;>>,,,,>>;-==*&&&&&*======*&&%%%&=--;--*&%$$$$%%%%%%&*==*&%%%%%%%%&*-;,,>>;;;;>;;=%$%=;,',;=&%&=--=&%&=-;;;-=--;;>>,'))))!!~~~!~~!',,,>>>,'))'')~]^]!'>;--;;;;-====->,)!!!!)',>;;;>,)!]^/((/^]~!',>;;;-;;>,')~]^(_:<<<<<<::_((([0o", +"n7/!)))))',,>;;-==*&%%%$$$$%%&*=-;>,,,,,,>;-==*&&&&&**====**&%%%&=--;--*&%$$$$%%%%%&*==*&%%%%%%%%&*->,,>;;;;>>;-*%%&->,,>-*&&=--=&%&=-;;;---;;;>,')))))!~~~!~~!',>>>;>,)))')!{]]~)>;-;;;;;--==-;>,))!!)',>;;;>,'!{]^//^^]~)',>;;--;;>,)!]^/(::<<<<<::_((/^]]{(7n", +"m4],,''))))))',,>;;-==*&&%%$$$%%&*=-;>,,,,,,>;-==*&&&&&**===**&&%&&*=---=*&%$$$$%%%%%&*==*&%%%%%%%&*->,,>;;;;>>;=&$%=;,',;=&*=--=&&*-;;;-==-;;>>,'))))!~{~~~~)',>>;;>')))))!]]{),;;;;;;;-===-;>,))!)),,>;;;>,)~]^^^^]{!)',>;---;>,')~]/(_::<<<:::_((/^]{~!)')^5n", +"l2'---;>,,'))))))'',>;;-==*&&%%%%%%&*=-;>,,'',,>;-=*&&%%&&**==**&&&&&*=---=*%$$$$$%%%%&*==*&&&&%%%%&=->,,>>;;>>;-*%%*-,',;=&&==-=&&*-;>;-=--;;>,')))))!~~~~!)',>>;>,'))))!~]{!'>;;;;;;-===-;,'))))',>;;;>,)!{]^^^]~!),>;;--;;>,)!]^/(:::<<::__(/^]]{!))',,>>,]4m", +"k|>&&&*==-;;>,'')))))'',,>;--=**&%%%%&&*=-;>,'''',>;-=*&&%&&&**=***&&&&*==--=*%$$$$$%%%&*===*&&%%%%&&=->,,>>;;>>;-&%%=>,,;=&&*===&&*-;>;----;>,')))))!~~~~!),,>>;>,)))))!{{!'>;;;;;;--=--;,')))',>;;;;,')~]]]]{!)',>;---;>,')~]/(_::::::_((/^]{~!)'',,,,,,,')/7o", +"k|>%%%%%%&**=--;>,,'))))))',,>;;-==*&&&&&&*=-;>,'''',>;-=*&&&&&******&&&&*==-==&%$$$$$%%%&*==*&&&%%%&*=->,,,>>>>>;*%%*;,,>-&&&==*&&*-;;--=-;;>,')))))!~~!!),>;;>,'))))!~~!),>;;;;;--=-;>,'))',,>;;;>,)!{]]]{!)',>;;-;;>,)!]^/(_::::__(/^^]{!))',,,,,,,')!~]^(}bq", +"l1,*&%%%%%%%%%&*==-;>>,''))))))',,>;--=**&&&*==-;>,'''',>;-=*&&&&&******&&&*====*&%$$$$$%%&*==**&&&&&&*=->,,,>>>>;-&%&->,,;*&&*=*&&=-;;----;>,')))))!~~!!',>;;>,'))))!~!),>;;;;;----;>,'''',>;;;>,')!{{{~)),>;;-;;>,'){]/(__::__((/^]]~!))',,,,,,')!~]^/(:<[|4es", +"m3!-==**&&%%%%%%%%&&*=--;>,'')))))))',>;;-==****==-;>,'''',,;-=*&&&&&******&***===*&%$$$$$%%&*==*&&&&&&*=;>,,,>>>>;=%%=;,,;=%%*=*%&=;;;----;>,'))))!!~!!',;;;>,))))!!!)'>>;;;;----;>,''',>;;;>,')!~~~!)',>;;;;;>,)!]^/(_____(/^^]{!))'',,,,,')!~]^/(:<[}|12237fs", +"n5],>;;--==**&&%%%%%%%%&*==-;>,'')!!!!))'',>;--======-;>,'''',,;-=**&&&**********==**&%$$$$%%&*==**&&&&&*=;,,,,>>>;-*%&->,;=&%*=&%&-;>;---;>,'))))!!~!)',;;>,'))))!!)',>>;;;----;>,',,>>;;;>,')!!!)),,>;;;;>,')~]^(((_(((/^]]~!))',,,,,')!~]^/_:<[}|1122222114er", +"o8(~))',,>>;;--==**&&%%%%%%&*==-;>,'))!!!!!))',>;;-====--;>,'''',,;-=**&&***********=*&%%$$$$%%&*==*&&&&&*=;>,,,>>>;=&%=;,>=&&*=&%&-;;----;>,)))))!!!)'>;;>,)))))!)',>>;;;---;;>,,,,>;;;>,'))!))',>>;;;;>')!]^/(((((/^^]{~!))'''''')!{]^(_:<[}|1111111||}}[<<|bq", +"o9:]{{~~!!))',,>;;--==**&&%%%%&&&*=-;>,'))!!~~!!)',,>;------;>,,''',,;-==***************&%%$$$%%&**=**&&&&*=;,,,,>>>-*%*;,>;**==&%*=;;---;>,'))))!!!)'>;;>,))))))),,>;;;---;>>,,,>;;;>>,'))))',>;;;;>,')~]^//((//^]]~!))'''''))!{]^(_:<[}||1111|||}[[<:__(/^^:9o", +"n7(~~~{{{{~~~!!)))',,>;;-==**&&&%&&&&*=-;;,'))!~~~!!))',>;-----;>,,''',,;-==*****==*******&%$$$$%%&*=***&&&*=;,,,,>>;=&&->,;=*==&&=--;--;;,'')))!!!),>;>,'))))))',>>;;;--;>>,>>;;;;>,,'))'',>>;;>,')!{]^////^^]{~!))'''))!~]]/(_:[[}||||||||}[[<:_(//^]]{!!))^6n", +"m4{,,,')))!!~~~~~~!!!))',,>;;--==*&&&&&&&*==-;>,')!~~~!!))',>;;---;;>,,'',>;-==***=====****&&%$$$$%&*****&&&*=;,',,>>-*&=;,;===*%&=;;---;>,)))!!~!),>;>,')))))',>>;;;-;;;>>>>;;;>>,'''',,>>>>,,)!~]^^^^^^]]~!!))))))!~]^/(:<[[}||||||}}[<::_(/^^]{~!))''',,,,]4m", +"l1'====-;;>,,''))!!!~~!!!!))',,>;;--=**&&&&&&**=-;>,'))!~!!!)),,>;;--;;>,,,,,>;--=========***&%%$$$$%&****&&&*=;,'',,;-**->;===&%%->;--;;,'))!~~!),>>>,)))))',,>;;;;;;;>>>;;;;>,,,,,,,>>>>,')!{]^^^^]]{~!)))))!!{]^/(:<[[}}||}}}[[<:_((/^]]~!!))'',,,,,,,,,,'^6n", +"k|>%%%%%&&**==--;>>,''))))!!!))))',,>;;--=***&&&&**==-;>,'))!!!))',>;;;-;;>>,,,,>;--========**&&%%$$$%%&****&&*=>,'',>;=*=;>;-*%$%=;;;-;>,'))!!)',>>,'))))',,>>;;;;;;>;;;;;>>,,,,,>>>,,')!~]]]]]]{~!!))))!!{]^/(:<[[}}}}}[[<::_(/^]]{!!))'',,,,,,,,'''))!~]]/[ap", +"k|>%$$$$$$$%%%%&&**==--;;>,,''')))))'',,,>;;--==**&&&**==-;;,,'')))'',>;;;;-;;>>,,>>;---======**&&%$$$$%&*****&*=;,,,>;-**;,>=&$#$&=--;;,''))!)'>>>,')))',,>>;;;;;;;;;;;;>>,,,,,,,,'))!{]]]]{{~!)))!!!{]^/(_:<[}}[[[[<:_(/^]]~!!))'',,,,,,'''')!!{]^^/(_:<[}|5fs", +"l1,*&%%%%%%%$$$$$%%%%%%&&*===--;;>,,,,'''',,,>>;;-==****&&**==-;>>,,'',,,>;;---;;;>>>>>;;--======*&&%$$$%%&***&&*-;>,>>;=*->;*$##$&=--;>'''))),>;>,'))'',>>;;;;;;;;;;;>>>,,,,,,'')!~{{{{{~!)))!!!~]^/(_:<<[[<<<:_(/^]]~!!))'',,,,,'''))!~{]^//(_:<[}|122344560iu", +"m3!;-===****&&&%%%%%%$$$%%%%%%%&**===--;;;>>>,,,>>>;;;--==******===-;;;>>>>;;;;-----;;>>>;;;---====*&%%$$$%&*****=-;>,,>-==--*$#$&=---;,'))))',>>,')'',,>;;;;;;;;;;;>>>,,,,,'))!!~~~~!!))))!~]^^/(_::::::__(/^]{!!)'',,,,,,'''))~{]^//(_:[}||12234455666666670iu", +"n5^',>>>;;;----===***&&&%%%%%%%%%%%%%%%&&**==---;;;;>>;;;;---===****====-----;----------;;;;;;-----==*&%%$$%%&****==;>,>;==--=%$%=-;-->'))))',,,,''',,>>;;;;;;;;;;>>>,,,''))!!!!!))))))!~]]^/(___((((/^]{~!))',,,,,,''))!~]]^/(_:[}}|1123445555555555444332225fs", +"o8(~)))))''',,,,>>;;;;---===***&&&%%%%%%%%%%%%%&&*===----;;;;;;-----======================---;;;;----==**&%%%%%&***==;>,>-=-;-*%&=---;,)!)),,,''''',,>;;;;;;;;;>>,,,'''))))))))))))!~{]]^////^^^]{~!))',,,,,'''))!{]^/(_:<[}}|122344444444444332211||}}}[[<:<|bq", +"o8(~!!!!!!!!!))))))))'',,,,>>;;;;--===***&&%%%%%%%%%%%%&**====---;;;-------=========*********==--;;;----==*&%%%%&&***=-;>;----*&&=--;,)!!)',,,''',>>;;;;;;;;;>,,,'''))))))''''))!!~]]]]]]]]~!)))'',''''')!~]]^/(_:<[[}||122222222222211|||}}[[<<::__((//^^^]^:9o", +"n5^)''''')))))))!!!!!!!!!)))))))))'',,,>>;;--===***&&%%%%%%%&&&**====--;;;;------====***&&&&&&&&*==-------==*&%%%%&***=----=--=**=-;>'!!)',,,'',,>;;;;;;;;>>,,,'''''''',,'')))!!!!~~~!)))))'''''))!{]^//((_:<[}}}||||||||||}}}[[[<<:::_(((//^^]]]{~~!!!))))')^6n", +"m3!;--;;;;;>>>,,,,''''))))))!!!~~~~~~~!!!!!)))'',,>>;;--====**&&&&&***==-----;;;;;;;;---==**&&&%%%&***=-----==**&%&&&*****=---===-;>>,)',,'',,,>;;;;;;;>,,,,'',,,,,,,,,'''))))))))))))))))!{]]^^^/(_:<<<<<<<[[[[[<<:::__(((//^^^]]]]{{~~!!!)))''''',,,,,,,,,'^5n", +"l2'=****======------;;;;;>>,,,'')))))!!!~~{{]]{{{~~!!!))))'',>>;---===========--;;;;;;;;;;---==*&&&%%%&***======**&&&**&%&=----==->,,,,,>,'',>;;;;;;>>>,,,,,,,>>>>,,,,''''''))))))!~~{]]]^/((___________((///^^^]]]]{{~~!!!)))))''''')'''''''''''')))))!!!!~]_9o", +"l2'=************===========----;;;;>>,,,,'')))!!!!~~~{{]]]]{~!!)))'''',,>;;---------;;;;;>>>>;;----=*&&&&&***======****&%&=--===*->',,,,>,,,>>;;>>>>>,>>>>;;>,,,,,,,''''))))!!!~{]]^^^^^^^^//^^^]]]]{{{~~!!)))))))))))))))))))))))!!~~{{]]]]^^^^^///(((__:::<1cr", +"m3!;----------==================---------;;;;;>>,,,,'')))!!!!)))!!!!!~~!))'',,,,>>>>;;;;;;;;;;;>>,>;--====*&&&**======*&&&*====**->',,,,>>>>>>>;>>>>>>>>>>;>>,'''''')))!!~~~{{{{]]]]]]{~~~!!!!!))))))))))))!!!!!!~~{]]]]^^^^///(((__::<<<[[[}}}}|||||111222237gt", +"n6^',,,,,,,,,>>>>>>>>>>;;;;;;;;;;;;;;;;;;;;;;;;;;;;>>>>>,,,,,,,,,,'')))))))'''',,,,,,,,>>>>>;;>>,,,>;;;;>;-=====-==**=***&&&**=*=->,>;;;>>>;>,,>;;>>>>,,,,>,,'))!))))!!!!!!!!!!!!!!!!!!!!!!!!!!~~{]]]^^///((((___:::<<[[[[}}}}}|||1112222333334444444444444459ht", +"o9:]{{{{{~~~~~~!!!!!!!!!!!)))))))))))))'''''''''''''''',,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,>>>>>>>>,>>;;--;;>>;;;;;>;-=&*====&&&&*==-;'',;--;>;;>')',>>>,,''',,,,'))))))))))))))!!!~~{{{]]]]]]^^^//(((_:::<<[[}}}}}}}||||||||||11111111122222222222222222111111125fs", +"pa}_((((((/////////////^^^^^^^^^^^^^^^]]]]]]]]]]]]]{{{{{~~~~!!!!!!)))))))'''',,,,,,,,,,>>>>>>>>>;;;----;;;;>>>,,>-=**-;;-=*====-;,')'>;-;>>>'!~!)',,,,'',,>>,,,''''))))))!!!~{]]]]]^^^^^^////((((____::::<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<::::::::::|bq", +"qb|:_____((((((((((((((((((((///////////^^^^^^^^^^^^^]]]]]]]]]{{{{~~~!!!!)))))'''',,,,,,,>>>>>;;;;;----;;;>>>>>;;-==-;>>>;;;;--;>,')),>;>,,)~]]{!)'',,,,,>>>>>>,,,,,'''')))))!!!!!!!!!!!~~~~~~~~~~{{{{{{{{]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]:9o", +"p0<^^^^^]]]]]]]]]]]]]]]]]]]]]{{{{{{{{~~~~~~!!!!!!!!!))))))))))))))))))''''''''',,,,,,,,,,,,,,>>>>>;;;;>>,,'',,>;---;,''',,;;;;;>,,,'',,,,'){^^]!'',,',,,,>>>>>>,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,''''''''''''''''''''''''')^6n", +"n6^),,,,,,,,,,,,,,,,,,,,,,,,,,,,,,>>>>>>>>>>>>>>>>>>;;;;>>>>>>>>>,,,,,,,,,,,,,,,''''''''''))))'''',,,,'))!!!!)'>--;>')'',;;;;;>>>>>,,,,,,,){/^~'>>,')))',,,>,,,''''''''''',,,,,,,,,,,,,,,,,,,,,>>>>>>>>>>>>>>>>>>>,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,>,]4m", +"m3!;------------------------------------;;;;;;;;;;;;;;>>>>>,,,,,'''''')))))))!!!!!!!!!!!!!!!!!!!!!))'')!~!!))!),;-->,,,>;----;>;;;;>>;;;>>,)]{'>>,))!!!)',,,'')))))'''''',,,,,,,,,,,'''''''))))))))))))))))))!!!!!~~~~~{{{{{{{{{]]]]]]]]]]]]]{{{{~~~~!!!!!))!/7n", +"m2)-=========-------------;;;;;;;;>>>>>>,,,,,''''')))))))!!!!~~{{{~~~~~~~~~~~~~!!!!!!!!!!!!!!~~{{~!)'')))',>>,,>;--;>;;;---;;;>;--;;;----;;,)'>>,)!!)!!!)',')!!)))'''',,,,,,,,,,>>>>,,,,,,,'''''))))))!!!~~{{]]]^^///(((((_____::::::<<<<<<<<<<<<::::::____(_}ap", +"m3!;;;;;;;;;;>>>>>>,,,,,,,,'''))))))!!!!~~~{{{]]]]]]]]]]]]]]]]]]]{~!!))))))))))))))))!!!!~!!!!!!!!)'>>>>>;;-;;;;;;-;;;-----;-;>>;;;;;------;>;;>,'''))!!!)))!~!))))))))''''',,,,>>>>>;;;;;;;;;;>>>,,,,,'''))!!~~{]]^^///((___::<<<[[[}}}|||1111111111111||||14er", +"n5^'''''''))))))!!!!~~~~{{{]]]]]]^^^^^^^^^^^^^^^^^]]]{{~!!))))))))'',,,,''')))))!!~~~~~~~~!))',,,>;;-=---;;;;>>;;;-----;--;;-------;;;;;-==----;>>>,,,'))))!~~!!)))!))))))))))))'',,,,,,>>;;------------;;;;>>,,,'''))!!~{{]]^^//((__::<<[[}}}|||||11111122237gs", +"o8_]{{{]]]]]]]^^^^^^^^^/////////^^^^^^]]]]{{~!!!)))''',,,,>>>>,,,,,''''))!~{{{{{{{{~!!))',,>;;--=====--;;>,>>>;---===-;>>;;;--==**=-;>,,;=====---;;;>>>,,,')!!!!!~{{~~!!!))))))))))))))))'',,,,>>>;;;---------------;;;;>>,,,,'')))!~~{]]^^^//(((__:::<<[[[[}3dr", +"p0[(/////((((((////////^^^^]]]]{~~!!))''',,,,>>;;;;;;;>>>>>,,''))!~~{]]]]]]]]{!!))',,>;;--========-;;>,,>>>;;--=====-->,>;--;-=*&&=--;,,;-==**==---;;;;;>>>,''')!!!~{{]]]{{~~!!))))')))))))))))))))''',,,,,>>;;;;----------------;;;;>>>,,,''')))!!~~{]]]^^^([ap", +"pa}_((((////^^^^]]]{{~!!))''',,,,>>;;;;--;;;;;;;;>>,,''))!!~{]]^^^^^^^]{~!))',>>;;---====**===-;;>,,,,>>;;;--==**==-;;,>;==-;;-*&*=---;;;--==****=--;;;;;;;>>>,''''))!~{]]]^^^]]]{~!)))))'))))))!!!!!!!!!~!!!))))''',,,>>>;;;------------------;;;;;>>>,,,'')/7n", +"p0<^]]]{{~!!)))'',,,>>>;;;------------;;;>>,,''))!~{]]^^^^^^^^^^]{~!!)',>>;;---=====****==--;>,,,,,,>;;;;---=***=--;>>>;=*=->>-==*=--===-----=**&**=-------;;;;>>,,''')))!~{]]^^///^^^]]~!))))'''))))!!!~{{{]]]]]]]]]]{{~~!!)))'',,,>>;;------=========-----;!3m", +"n7/)',,,>>>;;;;--------------;;;;>>,,''))!~{]]^^////////^^]{~!)),,>;;;-----======**===--;>>,,,,,,>>;;-----=****=--;>>>;-=*=->;---==--==*==-----=*&&**==---;-----;;;>,,'''')))!!{]^^//((((/^^^]!))))''''')))!!~{]]]^^^^^///////^^^^^]]{~!))'',,>>;;-----=====-)2l", +"m4!;-----------------;;;>>,,,'))!!~{]]^^/((((((((/^^]{~!)',>>;;;--------===========-;;>,,,,,,,>;;;---;;-=*&&*=---;>>>>-=**=-;;;;;-=---=***=--;-==*&&&&*==-;;;------;;>>,,''')))))!!~]^//((_::_(//^]{!)))'''''')))!!~{]]^^//((((___:::__(((///^]]{!!))',,,>;;;!3m", +"m2)-====-----;;;>>,,''))!!{]]^^//(((_____((//^]]~!)',>>;;;------------========--;;>,,,,,,,>>>;;----;;-=*&&*=-----;>,>;==*=-;;;>>>-=-;;-=***=----==*&&&&&*==-----------;;;>,,''))))))))!~{]^((_::<<:_((/^]{!))''',,''')))!~{]]^^/((__:::::<<<<<:::__((//^]]{!~/7n", +"m3!;;;;;>>,,''))!~{]]^^//((_________((/^]]~!)',>;;;;----------------======--;;>,,,,,,,>>>;;;;---;;;-=*&%&*=-----;>,>;=**=->,,,,,>-==;;-==**=-------=*&&&&&*==-------------;;;>,'')))))))))!!{]^/(_::<[[<::_(/^]~!)''',,,,,''))!!~{]^^//((_::<<<<[[[[[[[<<::_:}ap", +"n5^)''))!!{]]^^//((__::::::::_((/^]{!))',>;;;;-----;;;;;;;;;;;---=====---;>,,,,,,,>>>;;;;;;--;;;;-=*&%%&=-----;;>,,;-***=;>,,,',;=&&-;;-=**=--------=*&&&&&&*==--------------;;;>,''))))))))'))!~{]^(_:<[[[[[<::_(/^]~))'',,,,,,,''))!!~]]^^/((__::<<[[[[[[[}3dr", +"o9_]]^^//((__::::::<:::_((/^]{!))',>;;;;----;;;;;>>>>>>>;;;---====--;;>,,,,,,,>>;;;;;;;;;;;;;;;;=*&%%&*=-----;;>,,>;=**=-;>;;>,,;*%&-;;;-=**=---------=*&&&&&&**==---------------;;>,,')!!!!!))'''))!~]^/(:<[[}}}}[[<:_/^]{!)'',,,,>,,,,''))!!~{]]^//((_:::<[2dr", +"pa}:_:::<<<<<<<::_((/^]{!))',>;;;;----;;;>>>,,,,,,,>>>;;---===--;;>>,,,,,,>>;;;;;;>>;;;;;;;>;;-*%%$%&=------;>>,,,;-*&*=;>,;-->,;*%%=;;;-==**=---------=*&&%%&&&**==-----==----------;;>,')!~~~!!))''''))!{]^(_:[[}}|||}[[<:(/^]{!)',,,,>>>,,,,'')))!~{]]^^/(}aq", +"rc2[<<<<::__(//^]~!)',,>;;;;;--;;;;>>,,,''''''',,>>;;---==---;>>,,''',,>;----;;>>>>;;;;;>>>;-*%%$%&*-;;----;>,,,,;-*&*=-;>,>;->>;*%%*->;;-=***=---------==*&&%%&&&&**==----====--;;------;>,')!~{{~!!))''''')!~]^/(:<[}}|||||}[[<_(/^]~!)',,,>>>>>>,,,'')))!{_9o", +"rc1<__(/^]]~!)',,>;;;-----;;;>>,,''))))))))'',>>;;------;;>>,,''',,>;;-----;>>,,>;;;;>>,>;-*&%$$%*=-;-----;>,,,>;-*&&*=;>,,>;-;>;=&%&->>;--=*&*=----------=*&&%%%&&&&**==----====--;;;------;;,')!~{]]{~!))',,,'')!{]^(_:[}}||111||}[[:_(^]{!)',,,>>>;>>>>>,'^6n", +"p0<^{~))',>>;;;-----;;;>>,,')))!!!!!!!)))',>;;-------;>>,'''''',>;--===-;>,,,,>>;;;>,,>;-*%%$$%&=-;;--=--;>,,,>;-=&&&*-;>,>;;;;>;=*&&->>;;-==*&*=----------=*&&&%%%&&&&**==---======--;;;;------;>,)!~{]]]{~!))',,,,'))~]^/(:<[}||11111||}[<:_/^]{!)',,>>>;;>{4m", +"n6^'>;;-------;;;>>,,''))!!~~{{{{~!!)',,>;;-----;;>>,'')))'',>;-====-;>,''',>>;;;>,,>;-*%%$$$%*-;;--==--;>,,,>;-=*&&*=->,,>;;;;>;==&&=;>>;--=*&&*=----------==*&&&%%%&&&&&**==--==***==-;;;;;--===-;;,')!{]]]]]~!)',,,,,,')!{]^(_:<[}|1122221||}[<:(/^]~!)',,]4m", +"m3!;-----;;;>,,''))!!~{{]]]]]{{!!)',>;;------;>>,'))))))',>;-=**==-;,'))',>>;;>,,,>;-*&%$$$%&=-;--===--;>,,,,>;=*&&&*-;>,,>;-;>>;-=&%*->>;;-==*&&=------------=**&&%%%%&&&&&**==--==****=--;;;;;--===--;>')!{]]^^]]~!)',,>,,,,')~]^/(:<[}||12222221|}}[:_(^]](8n", +"m3!;;;>>,,''))!~{]]]^^^]]]]~!)',>;;------;>>,'))!!!))',>;-=***=-;,')))',>;;;>,,,>;-*&%$$$$%*--;--====-;>,,,,>;-*&&&*=-;>,,>;-;>>;-=%%&->,>;--=*&&&=------------=**&&&%%%%&&*&&&**=====**&**=-;;;>;;--====-;>,)!{]^^^^]]~!)',,>>>,,')!{]^(_:<[}|1222233221|}[[|bq", +"m4]',''))!~{]]]^^^^^^]]{!)',>;;------;;>,'))!!!!!)',>;-=***=-;,')!!)',>;;>>,,,>;=*&%$$$$%&=-;--=====-;>,,,,>;-=&&&&*=;>>,>;--;>,;-=&%&=>,>;;-==*&&*=-------------=*&&&&%%%%&**&&&&*=====*&&&**=-;;>>;;--====--;,')~]^^/^^^]~!)',>>>>>,,))~]^/(_:[[}|1223333336fs", +"n7(~!~{]]]^^^^^^^^]{~)',>;;------;;>,'))!~{{~!!),>;-=***=-;,')!~!)',>;;>,,',>;=*&%$$$$$%*-;;-=====-;>,,,,,>;-=*&&&*=-;>>>>;--;>,;-=&%%=;,,;;--==*&&*=-------------=*&&&&%%%%%&**&&&&**====*&&&&*=--;>>>>;--====--;>')!]]^///^^]~!)',>>>>>,,')!{]^/(:<[}||22348gt", +"o9:^^^^^//^^^^]{!)),>;;------;;>,'))!~{]]{~!),>;-=***=-;>')~{~!)',>;;>,'',>;=*%%$$$$$%&=-;-======-;>,,,,,>;-=*&&&&*=;>>,,>;-;>,,>--*%%*-,,>;;--=**&&*--------------=**&*&&%%%%&&***&&&&*====*&&%&&*=-;>>>>>;--=====-;>,)!{]^////^^]~!),,>;;;>>,'))~{]^(_:<[}|5fs", +"p0[(///^^]]{!)',>;;--=----;>,'))!{]]]]]{!)'>;-=***=-;>')~]]{!),>;;>>,'',>;=*%%$$$$$$%*----======-;>,,,,,>;-=*&&&&&=-;>>,,>;;;>,,>;-=&%&->,,;;--==*&&&=---------------=*&***&%%%%&&***&&&&*====*&&%%&&*=-;>>>>>;--=====-;>,'!~]^/(((//^]~)',,>;;;;>,,')!~]^/(:|cr", +"p0[/^]]~!)',>;;--===--;>,,')!{]]^^^]]~)',;-=***==;>')~]]]{!',>;;>,,'',>;=*&%%$$$$$%&=-;-=**====-;,,,,,,>;;=*&&&&&*=->>>>>>;;;>>,>;-=&%&=;,,>;---==*&&&=-------=-------=*&&***&%$%%&****&%%&&*===**&%%%&&=--;>,,,>;--==*===-;,')~]^/(((((/^]~)',,>;;;;;>,'))!]:0p", +"o9:]!)',>;--====--;;>,')!~]]^^^^^]{!',;-=***=-;>')~]]]]~),>;;;>,''',>;=*%%%%$$$$$%*---==***===->,,,,,,>;;-=*&&&&&*-;>>>>>;--;>>,>;-=&%%=;,,>;-;--==*&%&=-------=-------=*&&***&%%$%%&****&&%&&*====*&%%%%&*=-;>,,,,>;--==*===-;>,)!{^^/(((((/^]~)',>;;;;;;>,'^7n", +"n6^,>;--====--;;>,')!~]]^////^]{!',;-==*==-;>,)~]^^]]!',;;;;>,''',>-=*&%%%$$$$$%&=---=******=->,,,,,>;;;-=*&%%&&*=-;>>>,>;--;;>>>;-=&%%*;,,,;;;;-==*&%%*=;;-----=--------=*&&***&%%$%%&*==*&%%%&**===*&%%%%%&*=-;>,,,,>;--==**==-;>,'!{]^/((((((/^]~)',>;;;;;~4m", +"m3!-=====--;>,'))~{]^//(//^^{!),;-=====-;>')~]^^^]~),>;;;;,,''',>-=*%%%%%$$$$$%*=--=*******=->,,,,,>;;;-=*&&%&&&*=;>>>>,>;--;;;>>;-=&%%*->,,>;-;;-==*&%&*-;;-----=---=----=*&&**=*&%$$$%*===*&%%%&&*===*&&%%$%%&*=-;>,,,,>;--==**==--;,')~]^/((___((/^]!)',>>~4m", +"l2)-=--;>,,')!{]^^/(((//^]!),;-=====-;>,)~]^^^^]!',;;;;>,'')',>-=*&%%%%%$$$$%&=--==*&*****=->>>,,,>;;;-=*&&%&&&*=-;>>>>>>;--;;;>>;-=*&%*-;,',;;;;-===*&%&=-;-----===--==----=&&&*==*%%$$%%*===*&%%%&&*====*&%%$$%%&==-;>,,,,>;--==***=--;>,)!{]^/(____((/^{!!^5n", +"m3!>;>,')!~]]^/(((((/^]!),;-=====-;>,)~]^///^{),>;--;>,'))',>-=&&%%%%%$$$$$%*=--=*&&*****=;>>>>,,>;-;-=**&%%%%&*=;>>>>>>;--;;;;>>-===&%&=;,',>;-;;-==*&%%&=-;---;-===---==---=*&&*===&%$$$%&*===*&%%%%&*====*&%%$$$%&*=-;>,,,,,>;--=****==-;>,')~]^/(_____((/<9o", +"n5^)))!{]^/((((((/^]!',;-=====-;>,)~]^/(/^]!',;--;;>,'))',>-=&&%%%%%%$$$$%&==-=*&&&***&*=;>>>>,,>;-;--=*&%%%%&&=-;>;;>>>;--;;;;>>;-==*&&=;,',>;-;;-===*&%%&=-;---;-===---==---=*&&&*==*&%$$$%&*===*&%%%%&*====*&%%$$$$%&*=-;>,''',>;-==****==-;>,')!{]^((__::|bq", +"o8(]]^^/((((((/]{!',;-=====-;>,)!]^/((/^{),>;--;;>,'))',>-=&&%%%%%%$$$$$%*===*&&&&***&*=;>>>>,,>;----=**&%%%%&*=->>;>>>>;--;;;;>>;--=*&&=->,',;;-;;-===&&%%&=-;---;-===---==----*&%&*===*&$$#$%&==-=*&%%%%&*====**&%$$$$%%&*=-;,,''',>;-==*****=--;>,)!{]^/(:|bq", +"o0[((((__((/]{!'>;-=====-;>,)!]^/(((/]!',;---;>,')))',;-=&&%&&&&%%$$$$%&====*&%&&**&&*-;,>>>,,,;----=**&%%%%%&*=;>;;>>,>;--;>;;>>;---*&&*-;,',>;-;;;===*&&%&*=;;---;;-==---===---=&%%&*===*%$##$%*=--=*&&%%%&*=====*&%%$$$$%%*=-;>,,''',>;-==*****==-;>,')!{^<0p", +"qb}:__(/^]~)'>;-=====-;>,)!]^/(((/^{),>----;>,')))',;-=&&%&&&&&%$$#$$%*===*&%%&**&&&*->,>;>,,,;----=**&%%&%%%*=->>;;;>,>;--;>;>>>;---*&&*-;,''>;--;;-===*&%%&*-;;--;;;-==---===---=*&%&*=--=&%$##$%*=--==*&%%%&*=====*&%%$$$$$%&*=-;>,'''',>;-==*****==-;;,')(8o", +"qb}_/^]~),>;-=====-;>,)!{^/(_((/]!',;----;>,')))',;-=&&%&&&&&%%$$$$%&*===&%%%&**&&&*->,>;;,,,;----=***&%%%%%&*=;>;;;;>,;---;>;>,>;---*&&*=;>'',;;-;;;====&&%%&*-;;--;>;-==---=*==---*&%%&*=-=*&$###$&*=--==*&%%%&*======*&%$$$$$$%&*=-;>,'''',>;-==**&&**=-->]5n", +"p0<]~),>;-=====-;>,'!{^/(__((^{),>-----;>,')))',;-=&&&&&**&&%$$#$%%*===*&%%%&**&%&*->,>;;,',;----=***&%%%%%%&*->>;;;;>,;---;>;>,>;;--=***=;>,',>;;-;>-===*&%%%&=;>;--;>;-===--=**=---=&%%%*=--=*%$##$%&=----=*&%%%&*===-==*&%$$$$$$%%&*=-;,,'''',>;-==*&&&**-)3m", +"n7^';-======-;>,'!{]/(___(/]!'>;-==-;>,'))))',;-=&&&&&***&%$$#$$%&*==*&%%%&&*&&%&*;>,>;;,',;-=--=****&%%%%%&*=;>;;;;;,>;--;;;;>,>>;--=***=->,'',;;-;>;-===*&%&%&=;>;--;>;-===--=**==--=*%%%&*=--=&%$##$%*=-;--=*&%%&&*===-==*&%%$$$$$$%%*=-;>,''''',>;-==*&&*,1l", +"m3!-==*==--;,')~]^(____(^{),;-==--;>,'))))',;-=&&&&*****&%$##$%%*==*&%%%%&&*&%%&=;,,>;;,',;==--=**=*&%%&%%%&*-;>;-;;>,>;--;;;;>,>>;--=***=->,'',>;;-;>;====&&&&&&=;>;--;>>-===---=**=---=&%%%*=---*&$###$%*--;;-=*&%%&&*==---==*&%$$$#$$$%&*=-;>,'')'',>;-===,1l", +"l2'===--;,')~]^(__:_(/]!'>;-===-;>,'))))',;-=&&&&**==*&%$$#$$%&*==*&%%%%&*&&%%%=;,,>;;,',;===-=****&%%&%%%%&=->;--;;>,>;--;>;;,,,>;--=**==-;>,)'>;;-;>>-====&%&&%&=;;---;,>-=*=---=**=---=&%%%&*---=*%$###$&=-;;;-=*&%%&&*==---==*&%%$$##$$%%&*=-;,,')))',>;;)2l", +"l2)--;>,)!]^/(_::_(^{),;-===--;>,')!!)',;-=&&&**====*&%$##$%%**=*&%%%%%&&&%%%&=;,,;-;,',;===-=***=*%%%%%$%&*=;>;--;;,,;;--;>;;,,,>;--=====-;>,'',>;;-;,;====*&%&&%*-;;--->,>-=*=---=&&*=--=*%$$%*=---=&%####$&=-;;;-=*&%%&&*==----=*&&%$$###$$%%&=-;>,'')))'']4m", +"m4{,,)!{^/(_:::(/]!'>;-===-;;,'))!!)',;-=*&&**====*&%$$##$%&*=**%%$%%&&&&%%%&=;,,;-;>'';=*===***=*&%%%%$$%&*->>----;,,;;;-;>;;,,,,>---====-;>,'),>;;-;,,-====&%&&&%*->;--->,>-=*=---=&&*=---=&%$%&*=---*%$####%*=;;;;-=*&%%&&*==----==*&%$$###$$$%&*=-;>,'))!/7n", +"n6/~{]/(_:::_(^{),;-====-;>,'))!!)',;-=*&&*======*&%$##$%&****&%$$%%&&&&%$%&->,,;-;>'';=**===**==&%%%%%$%%&=;>;---->,,;;;-;>;;,,,,>---===-=;>,,)'>;;;->,>=*=-*&%&&%&*->;--->,>-=*=---=*&&*=--=*%$$%&=---=*%$###$%*-;>>;-=*&%%&**==-----=*&%$$####$$$%&*=-;>,)/7n", +"o9:/(_::::_/]!'>;-===--;>,'))!!)',;-=*&&*==---==&%$##$$%&*=**&%$$%%&&&%%$%&->,,;-->''>=**===&*==*%%%%%$$%&*->>----->,>;;--;>;;,',,>---==---;>,,)),;;;-;,,;====*%%&&%&=;>;--;,,,-=**---=*&&*=--=*&$$%%*=---=&$####$&=-;>>;-=*&&&&**==-----=*&%%$$####$$%%&==->]5n", +"pa|::::_(^{),;-====--;>,')!!!)',;-=*&**==----=*%$$#$$%&**=*&%$$$%%&&&%$$%*-,,,;-->''>=**===&&*==&%%%%$$$%&=;>;----;,,;;;;->>;;,',,,;--==---->,,'),;;;-->,>-*=-=&%&&&%&=;>;--;,',;=**=---*%%&=---=&%$$%&=---=*%$#@##$&=;>>>;-=*&%&&**=------==*&%$$#####$$%&*-)3m", +"qc1<:_/]!'>;=====-;>,'))!!!)'>;-=*&**==----=*&%$##$%%**==*&%$$%%&&&%%$$%*-,,,;-->''>=&&*==*&*==&%%%%%$$%%&->>-=---;,,;;;-->>;;,',',;--==-;-->,,,)'>;>;-;,,;=*=-*%%&*&%&=;>;--;,',;=&*=-;-*%%&*=--=*%$$$%*=---=&%##@#$%*=;>,>;-=*&%&&*==------==*&%$$#####$$%&,1l", +"qb|_^{),;-=====-;>,'))!!!)'>;-=****=------=*%$##$$%&*==*&%$$$%%&&&%$$$%*;,,>-=->''>-&&*==*&*==*%%%%%$$$%&*;>;-=--->,,;;;-->>;;,','';--==-;--;,,,)),;;>-->',-*=-=*%%&*&%&->>;--;,',;=&*=-;-*&%%&=--=*&$$$%&*----*&$#@@#$%*-;,,>;-=*&&&&*==-------=*&&%$$#####%;|k", +"p0:~'>;-====--;>,')!!!!)'>;-=****=--;;;-=*&$$##$%&*===*&%$$$%%&&&%$$$%*;,,>-=->,'>-&%&==*&&=-=&%%%%$$$$%&=>>;==--->,>;;;-->>-;'',''>--=*=;;-;,,,'),;;>;-;,';=*=-=&%&**&%*->>;--;,',;=&&=---=&%%&*=--=&%$$$%*=---=*%$#@@#$&=->,,,;-=*&%&&*==-------==*&%$$###$-}k", +"n6]>-=====-;;,,')!!!!)'>;-=***==--;;;;-=&%$##$$%&*==*&%$$$$%&&&%%$$$%=;,,;-=-;,'>-&%&*=*&&*-=&%$%&%$#$%%*->>-=--=;,,>;;;-->>-;'',''>--===;;-;,,,,)'>;>>-->',-**--*%%&**%%*->>;--;,',;=&&=-;-=&%%%*=--=*%$$$%&*----=&$#@@@#$&=;>,,,;-=*&%&&*==-------==*&%%$$$-}k", +"m3)-====-;>,,')!!!!)'>;-=***==-;;;;;-=*%$###$%&*===*&%$$$%%&&&%%$#$%=;,,;-=-;,'>-&%&*=*&%*=-*%$%%%$##$%&=;>;==-==;,,;;;;-->>-;'',))>---==;>;;,',,)),;;>;-;,'>=*=--*%%&*&%%*;>>;-->')';=&&*-;-=&%%%&==-=*%$$$$%*=---=*%$#@@##%*-;,,,,>-=*&%&&*==--------=*&&%%;}k", +"l2'==--;>,'))!!!!)'>;==***==-;;;>;;-=&%$##$$%*====*%%$$$%%&&&%$$#$%=>,,;===;,'>-&%%***&%*=-=&$$%%%##$$%&->>-==-=->',;;>;-->;->'',)),---==;,;->',,')';;>>-->'';**=-=&%%**&%%*;,>;-->')';=&&*-;;-*%$%%*===*&%$#$%&*=---=&%##@@#$%*->,'',;-=*&%&&*==--------==**,|k", +"l2);;;>,'))!!!!),>;==***==-;;>>>;-=*%$###$%&*====&%$$$$%&&&&%$##$&=>,,;=*=;,',-&%%&**&%&=--*%$%%%$##$%%=;,;=====-,'>;;>;-;>;->)',)),---==;,>;;'','))>;>,;--,),=**--*%%&**&%%=;,>--->')';=&&*=-;-*%$$%&====&%$##$%&=---=*%$#@@@#$%=->,'',;-=*&%&&**==-------=-'2l", +"m4~,>,'))!!!!),>;==***==-;;>>>>;-*&$###$%&*=--=*&%$$$%%&&&%%$##$&->,,;=*=;,',-&%%&**&%&=--*%$$%%$###$%&->>-*====;,'>;>>--;,;->)),)),---==;,>;;,',,)),;;>>-->'';*&=--&%%&=*%%&=>,>-=->')';=&&*=-;-*%$$%&*===*%$$#$$%*=---=&%$#@@@#$&=;,''',;-=*&%&&**==------;)2m", +"n5])')!!!!)),>-=****==-;;>>>>;-=&%$###$%&==--=*%$$$$%%&&&%%$##$&-,,,-**=;,',-&$$%**&%%*--=&$$%%%$##$$%*;,;=*====;',;;>>--;,>;,)),)),---==-,,;;,),,')';;>,;--,),-&*--=%%%*=*%%&->,>-=->))'>=&%&=-;-=%$$$%*===*&%$##$%&==--=*&$#@@@##%&=;,')',;-=&&%%&**==----;!3m", +"n7/!!!~!!),>-=****==-;>>,,>>;=*%$###$%&*=--=*&%$$$$%&&&&%$$##$*-,',-**=;,',-&$$%&*&%%&-;-*$$%%%$###$%&=>,-=*==*=>',;;>>-->,>;,)),)!,---=*-,'>;,)','))>-;,>--;))>=&=--*%$%*=&%%&->,;-=->)))>=&%&=-;-=&$$$%&*===&%$##$$%*=---=&%$#@@@#$%*->,')',>-=&&%%&**==--;!3m", +"o8({~!)),>-=****==-;>>,,,>;-*&$###$$%*=---=*%$$#$$%&&&&%$###%*;,,>-*&=;,',-&$$%&*&%%&=--=%$$%%%#@#$$%*;,>=*===*-,'>;;,;==>,;-,!),)!,-=-=*-,),;>'),,)),;;>,;=-,)'-&&=--&%%&==&%%&->,;-=-,)!)>=&%&=-;-=&$$$$%*===*%$###$%&*=--=*&$##@@@#$%*->,))',;-=&&%%&**==-!3m", +"o9_{!),>-=****==-;;>,,,>;-=&%$###$%&=----=&%$##$%%&&&&%$###%*;,,>-*&=;,',;*$$$&*&%%%=-;=%$$%%%$#@#$$%=>,;=*==*=;,'>;>,;=->,;-,!),)!'-=-=*=,),;;'),,')';->,>-->))>=&*--=%$%*==&$%*;,,;-=;,)!)>=&%&*-;;=&%$$$%&*==*&$$##$$%&==--=*%$#@@@@#$&=->'))',;-=&&%%&&*-)2m", +"o8(),;-=**&*==-;>>,,,,>;=*%$###$%&*=-;--=&$$#$$%%&&&%%$###%=;,,>=*&=;,',;*$$$%&&%$%*-;-&$$$%%$#@##$%&-,>-**==*=;',;;>,;=->,;-,!),)!'-=--==>)';;,)',,))>-;,,;--,)'-&&=--*%$%*=*%$%*;,>;==;,)!)>=&%%*=-;-*%$#$%&**=*&%$###$%&*=--==&%##@@@@#$&=;,'))',;-=&%%%&*'2l", +"n6]>-=**&*==-;>>,,,,>;-*%$####$%*=-;;-=*%$##$$%&&&&%$$##$%=;,,;=&&*-,',;*$$$%&&%$%&-;-*%$$%%%$@@#$$%=;,;=**=**=>',;;,,;=->>--'!),)!);---==;))>;,)),,)),;->,>-->)),=&&=-=&$$&==*%$%=;,>;==;,)!)>=&%%*=-;-*%$#$$%&***&%$####$%&*=--=*%$#@@@@##%*=;,'))',;-=&%%&,1l", +"m3!-**&*==-;>>,,,,,;-=&%$###$%&*-;;;-=&%$##$%%&*&&%$###$%=;,,;=&&*-,',;*$#$%&&&%%&=;;=%$$$%%$#@@#$$&-,,-**==**-,'>-;,,-=->>--'~),)~);---==;)!,;>)),>'!);-;,,;=-,));&%*--=%$%&==&%$%=;,>-==;,)!),=&%%&=---=%$##$%&&**&%$####$%%*==-==&%$#@@@@#$%*->,)))',;-=&*,|k", +"l2'=&*==-;;>,,,,,>;=*%$####$%*=-;;;-*%$###$%%&**&%$###$%=;,,;=&&*-,'';*%##$&&&%$%=-;-&$#$%%%#@@##$%*;,>=**==**;'';-;,>-=-,>--'~),)~)>---=*-'!';>)!'>,)),-;,'>-=;)!,=&&=--*%$%*-=&$$&->,>-==;,)!),=&%%&=---=&$##$$%&**&%%$####$%&*====*&$#@@@@@#$%*->')))',;-=,1l", +"l1,=*=-;;>,,,,,>;-*%$####$%&=-;;;;=*%$##$$%&&**&%$###$&=;,>-*&&*-,''>=%##$%&&%$%*-;;*%#$%%%$@@@#$$&->,;*&*=*&=>',;->,>==;,>--'~),)~!>---=*-'!)>;'!),,)!';->',;=-,!);*%*-;-&$$%=-=%$$&->,>-==;,)!),=&%%&*---=&$###$%&&**&%$####$%%*=====&%$#@@@@@#$&=->')))',>!2l", +"l2'--;;>,,,,,,;-=&$####$$&*=;;>;-=&$###$$%&**&%%$#@#$&=>,>-*%%*->''>=%##$%&&%$$&-;;=%##$%%$#@@##$%*;,>-&*==*&-,',-->,;==;,>--){),){~,---=*-,!)>;,!),>'!)>-;,'>-=;)!'-&&=--=%$$&=-*%$$&->,;-==;,)!),=&$%%*---=&$###$$%&&&&%$#####$%&*====*&%$#@@@@##%&=;,'))))^5m", +"m3!;;>,,,',,>;=*%$####$%&=-;>>;-*%$###$%&&**&%$##@#$&->,>-*%%*->''>=%##$%&&%$$%=;;-&$#$%%%#@+@#$$%=>,;=&*==**-,'>-;,,;*=;,>-;){),){~,---=*=,!!,;>)!'>,)!,-->',;=-,!)>*%&=;-*%$%*--*%$%*;>,;-==;,)!),=&$$%*=--=*%####$%&&&&%$#####$$%&*====*%$#@@@@@#$%*=;,')!(7n", +"m4{,,,,'',>;-*%$####$%&*-;>>>;=&$####$%&***&%$##@#$&->,>-&%%*->''>=%###%&&%$$%*-;-*$##$%%$#++@#$$*;,,-*&==*&*;'';-;,,;*=>,;=-){),)]{,---=*=>!~';>)!'>,)!';-;,'>-=;)!'-&%*-;=&$$%=-=&$$%*;,>;===;,)!),-&$$%*=--=*%$###$$%&&&%$$##@##$%&*====*&%$#@@+@@#$%*-;,)(8o", +"n5]','',,;-=&$#####$%*=-;>>;-*%$####$%&***&%$#@@#$&->>;=&%%*->''>=%###$%&%$$%*-;;=%##$%%$#@+@#$$%=>,>=&&==*&=>',;-;,,-*=>,;=;){),)]]'----*=;!{);;'!),>'!)>--,)';=-,!!>*%&=--=%$$&=-=&$$%=;,>;===;,)!),-&$$%&=---*%$###$$%%&&%%$##@@#$$%&*====*&%##@++@@#$%*->^6n", +"n5^)',,>;=&%$####$%&=-;>,>;=&%####$$%**=*&%$#@@#$*-;>;=&%%*->,'>=%###$%&%$$$&=;;-&$##$%%$@++@#$$&-,,;*&*==*&-,',-->,,-*=>,;=;){),)]]'----**;){)>;,!!,>,!!,--;''>-=;)~)-&%*-;-*%$$*--=%$$%=;,>-===;,)!),-&$$%&=---*%$#@##$$%%%%%$##@@##$%&*=====*%$#@@++@##$&=!4m", +"n6^),>;=*%$####$$%*=;>,,>-=&$####$%&*==*&$##@@#%*-;>;=&%%*->,'>=%###$%&%$$$%=;;-*$##$%%$#++@#$$%=;,>-&&==*&*-,'>-->,>=&=>,-=;)~),']]'-=--**-'{!,;,)~'>>)!);-;,)';=-,!!,=%%*-;-&$$%*--*%$$&=>,>-===;,)!),-&$$%&*=--=&$####$$%%%%%$##@@@#$$%&*====*&%$#@+++@##%,1l", +"n6^,;-*%$#####$%&=-;>,>;-*%$###$$%&*==*%$#@@@#%*-;;-*%%%*->,'>-%###$%&&%$$%*-;;=%##$$%$#@++@#$$&-,,;*&*==*&*;'';--,';*&->,-=;)~)>'{]'-=--=*-'{{';>)~)>>'!!,-->))>-=;)~);&%&=;-=%$$%=--*$#$&->,>-=*=;,)!),-&$$$%*=--=&$##@##$$%%%%$$#@@@##$%%&*====*&$##@++@@$;|k", +"n5{;=&%#####$%%*=;>,,>;=&$####$$%*==*&%$#@@@#%*-;;-*%$%*->,'>-&#@##%%&%$$$&-;;-%###$%%$@++@##$%*;,,-&&*==*&=>',;=;,,;**->>-=;)~'>'{]'-=--=*=,{]);;'~!,;,!!';=;')';=-,!!,=%%*-;-*$$$&-;=&$#$&->,;-**=;,)!),-&$$$%*=--=&%#@@@##$%%%%$$#@@@@#$$%&*=====&%$#@@++#-}k", +"m3)=%$#####$%&=->,,,;-*%$####$%&*==*&%$#@@@#%*-;;-*%$%&=;,,>-&$###$%&%$$$&=;>-*$##$%%$#+++@#$$&->,>=&&=-=&&-,',-=;,,-**-,>=*;)~'>'{])-=--=*=>~])>;,!~';>)!)>--,))>==;)~);&%%=-;=&$$%*--=%$#$*->>;=**=;,)!),-&$$$%&==-=&%#@@@##$$%%%$$##@@@##$%%&*====*&%$#@+@=[j", +"l1>%##@##$%&*-;>,,>;=&$##@##$%&====&$#@@@@#%*-;;=&%$%&=;,,>-&$#@#$%&%$#$%=;>;=$###$%$#@++@##$$*;,,;*&*=-*&*;,'>-=;,,-&*;,;=*;)~'>,{])-=---*=;!]!>;,!~)>;'!!,-->))'-=-,!!,=%$&=;-=%$$%=--=%##%*->>;=**=;,)!),-&$$$%&*===*%$#@@###$$%%%$##@@@@#$$%&*=====*%$###=[j", +"k};$###$$%*=->,,,>-=%$####$$%*===*&$#@@@@#%*-;-=&%$%&=;,,>-&$@@#$%&%$#$%*-;;=%#@#$$%$#+++@#$$%=>',-&&=-=*&*;'';=->,,=&*;,;=*;)!'>,~]);=-;-**;)]{,;>){)>;,!!';=-,))>==;'!);&$%*-;-*$$$&=;-*$#$%=;>>;=**=;,))),-&$$$%&*===*%$#@@@##$$%%%$$#@@@@##$%%&*====*&%$$-[j", +"k}-###$%&=-;>,,,;=&%##@##$%&*===*%$#@@@@$%*-;-=&$$%&=;,,>-&$@@#$%&%$##$&-;>-&$@##$%$#@++@##$$&-,';=&&=-=&&=>',-=->,>=&*;,;**;)!'>,~]!;=-;-**-)]]';;'~!,;>)!)>=->)!,-=-,)!'-%$%=;;=&$#$*-;-&$#$%=;>>-=**=;,)))>-&$$$%&*===*%$#@@@###$$%%$$##@@@@#$$%&**====*&%;}k", +"k}-$$$%*=;>,,,>-=%$#@@##$%&====*%$#@+@@$%*---*%$$%&=;,,>-&$@@#$%%%$##$&=;;;*$#@#$$$#@+++##$$%=>',-&&*--=&&-,',-=-,,;*&=;,;**;)!,;,~]!;=-;-=*-']]);;,!~';;'!!,-=;'!)>==;'!)>*$%&-;;=%$$%=;;=&$#$&=;>>-*&*=;,)))>-&$$$$%*===*%$#@@@@##$$$$$$##@@@@##$%%&*======,|k", +"k};%%&=-;,,,,;-*%$#@@##$%*=--=&%#@@+@#$%*--=*%$$%&=;>,>-&$@@##%%%%$#$%*-;;=%#@##$$$#+++@#$$$&-,'>=&&=--*&*;,'>==;,,;*&=>,-**;)!,;,~]!>=---=*=,{^!>->!{)>;,)!';=-,)!,-=-,)!'-%$%*-;-*$$$&=;;=%$#$&-;>;-*&*=;,')'>-&$$$$%&*==*&$#@@@@###$$$$$##@@@@@#$$%&&*===-)2l", +"k|>**=;>,,,>-=&$##@##$%&*=-==&$#@@+@#$%*=-=*%$$%&=;>,>-*$#@@#$%&%$##%*-;;-&#@@#$$$#@+++##$$%=;'';*&*---*&=;'';==;,,-&&=>,-**;)!,;,!]~>==--=*=>~^~,->){!,;>)~!,-=;)!)>==;'!)>*$$&=;;=&$#$&-;-*%##$*->>;=*&*=;,')'>-&$#$$%&*==*&%#@@@@@##$$$$$$##@@@@##$%%&*==-)3m", +"l1'--;,,,,;-*%$#@@##$%&=--=*%$#@++@#$%*===&%$$%&=;>,>-*$#@@#$%&%$##$&=;;-*$@@##$$#@+++@#$$$&-,',-&&=-;=&&=>',-*=;,,-&&=>>-&*;)!,;>!]~>==-;=*=;!^]';;'~~,;;'!!'-=-,!!,-=->)!'-%$%*-;-=%$$%*-;-&$##%*->>;=&&*=;,')'>=&$##$%&*==*&%#@@+@@###$$$$$##@@@@@#$$%&&*-)3m", +"l2!>>,',>;=&$##@@##$%*=--=*%$#@++@#$%*==*&%$$%&=->,>-*$#@@#$%%%$##$%=-;;=%#@@#$$$#++++##$$%*;,'>=&&=;-=&&-,',-*->,>=&&->>=&*;)!,;>!]{,==-;-**;)]]);;,!{);;,)~);=->)~);==;'!!>*$$%=;;-*$$$%=;;=&$#$%*->>-=&&*=;,')'>=&$##$%&**=*&%$@@++@@###$$$$##@@@@@##$%%&='2m", +"m4]',,,;-*%$#@@##$%&*=--=*%#@+++@#$%*==*%$$$%&=->,>-*$#@@#$%%%$###%*-;;=%#@@##$$#@+.+@#$$$%=>',-*&*-;-*&*-,';=*->,;=&&->;=&*;)),;>!]{,==-;-**-']^);->!{)>->)~!,-=;'~!,-=->)!'-&$$&=;;=&$#$&=;;=%$#$%=->;-*&&*=;>'',>=&$##$%%&*=*&%$#@++@@###$$$$$##@@@@##$$%*,2l", +"n5^',>;=&$##@@##$%&=---=&%#@+++@#$%*==*%$$$%&=->,>-*$#@@#$%%%$###%*-;;-&$@@@#$$#@+..+##$$$*;,',=&&=;;-&&=;,,;=*->,;*%*->;=&*>)),->)]],==-;-=*=,]^~>-;){!,-;,!~';=-,!~);==;'!!,=%$%*-;-*%$$%*-;;=%##$%=;>;-*&%*=;>,',>=&$##$$%&***&%$#@+++@@###$$$$##@@@@@##$%>1l", +"n6^'>-*%$#@@@##$%*=---=&$#@+++@#$%*=*&%$$$%&=->,>;*%#@@#$%%%%$##$&=;;-*$@@@##$##++.+@#$$$%=>'';*%&-;;=&&=>',-**-,,-&%*->;*&*>))>-;)]],==-;-=*=,{^{,-;'~~';-,)~)>==;)~!,-=->)!);&$$%=;;-&$$$%=;;-*$##$&=;>;-*%%&=->,',;=&$##$$%&***&%$#@+++@@###$$$$###@@@@@#$;|k", +"n5]>=&$##@@##$%&*=--=*%$#@+++@#$%***&%$$$%&=->,>;*%#@@##$%%%$##$%*-;;=%#@@@#$$#@+..+#$$$$&-,),-&%*->;=&&->'>=*=;,,-&%*->-*%*>))>-;)]]'==-;;=*=>~^]';-,!{);->)~!,-=-,!{);==;'!),=%$$&-;;=%$#$&=;;-&$##$&=;>;=&%%&=->,',;=&$##$$%&&**&%$#@+++@@@###$$$$##@@@@@$-}k", +"m4!=%$#@@@##$%&=---=*%$@@+++@#$%&**&%$#$%&=-;>>;*%#@@##$%%%$###%*-;;-&#@+@##$#@++.+@#$$$%=;''>=%&=;>-*%*-,,;=*=;,>=%%*;>-*%*>))>-;)]]'-*-;;-*=;!^^);->){!>-;,!~);=->){!,-=->)!);&$$%*-;-*%$$%*-;;=%$##$&-;;;=&%%&=->,,,;=&$##$$%%&**&%$#@++++@@###$$$$##@@@@#-}k", +"l2,%##@@##$$%*=---=&%#@++++@#$%&*&%$##$%&=-;>>-*%#@@@#$%&%$###$&=-;-*$@+@#####++..+#$$$$&-,)';*%*->>-&%*;,,;*&=;,>=%%=;;-&%=>))>-;)]]'-*=;;-**;)^^!>-;){~,-->)~!,-=;'~{);==;,)),=%$$&=;;-&$$$%*-;;=%###%*-;;-=&%%&=-;,,,;=&$##$$%%&***&%#@@+++@@###$$$$$##@@#=[j", +"k|;$@@@##$%&*----=&$#@++++@#$%&&&%$##$%&=-;>>;=%#@@@#$%%%$###$&=-;-=%#++@####@+..+@#$$$%*;'),=&&=;>;=&&=>,,-*&=>,;*%%=;;=&%=>))>-;)]^)-*=;;-**-']^{,-;'~{';-;'~~'-=-,!{!,-=->'!);&$$%*-;;=%$#$&=;;-*$##$%*-;;-*%%%&=-;,,,;=&$###$%%&**&&%$#@+++@@@###$$$$##@#=[j", +"k}-#@@##$%*=----*%$#@++++@#$%&&&%$##$%&*-;>>-=%#@@@#$%&%%###$%*-;;=%#++@@###@+...+#$$#$&->)';*%&->,;*%&->,>=&*->,;*%&=;;=%%=>));-;']^)-*=;;-=*=,{^],--,!{);-;,!~);==;){{);==;,)),=%$$%=;;-*%$$$&-;;-&$##$%*-;;-*%%%&=-;>,>;=&$###$%%&&**&%$#@++++@@###$$$$###-[j", +"k[-#@#$$%*=-;-=*%#@+++++@#$%&&%%$##$%&*-;>>-=%#@@@#$%%&%$###%&=;;-&$@++@###@++..+@#$$$%*;')'-&%*-,,-*%*-,,;=&*->,-&%&=;;=%%=>)';=-']^)-*=;;;=&=>~^]'-->){!,-->)~!,-=-,!]~,-=->')';*$#$&=;;-&$#$%*-;;=&$##$%=-;;=*%$%&*-;>,>;=&$###$$%&&*&&%$#@++++@@###$$$$$$-}k", +"j[-$#$%&*----=&%#@+++++@#$%%%%$$##$%&*-;;;-=%#@@@#$%%&%$#@#$&=-;-*$@++@@###@+...@#$$#$%=>')>=%&=;,>-&%*;,,;*&*;>>-&%&-;-*%%=>)';=-']^!;*=-;;=*=>!^^);-;){~'-=;'~~';=->)]]);==;,)),-%$$%*-;;=%$$$%=;>;=%###$&=-;;=&%$%&*-;>>>;=&$###$$%%&&&&%$#@++++@@@###$$$$;}k", +"k}-$$%&=----=&$#@+++++@#$%%%%$###$%&*=;;;-=%#@@@#$%%&%$#@#$%*-;-=%#+++@###@+...+@$$$$$&-,)';*%&->,>=%%=;,,-&&=;>>=%%*-;-*%%=>)';=-,{^!;*=-;;-**;)^^!>-;'~{);=-,!~)>==;'~]~,-=->')';*$#$%=;;-*%$$$&=;;-*%###$&=-;-=&%$%&*=;;>>-=&$###$$%%&&&&%$#@@++++@@###$$%;}k", +"k};%%*=-;--*%$#@+++++@#$%%%%$###$%&*=;;;-=%#@@@#$$%%%$#@@#%*=--=&#@++@@##@++..+@#$$#$%=>'),-&%=;,,;*%&=>,>=&&=;>;=%%*-;-*%%=>)';=-,{^!;*=-;;-**-']^{,--,!]!>=->)~!,-=-,!]]);==;,)),-%$#$&-;;-&$$$%*-;;-&$##$%&=-;-*%$$%&*=-;>;-=&$###$$%%&&&&%$#@@++++@@###$%;|k", +"k|>*=--;-=*%$@++++++@#$%%%$$###$%&*=;;;-=%#@@@#$$%%%$#@@#$&=---*$@+++@##@@+. .+#$$$#$&-,))>*%&=>',-&%*-,,;=%&=;>;*%%*-;-&%%=,)';=-,~^!;=*-;;-**-,]/],-->){~,-=;'~~);==;){]!,==->')';*$#$%=-;;=%$$$%=-;;=&$##$%*=;;-*%$$$&*=-;>;-=&$###$$%%&&&&%$$#@++++@@###$;|k", +"l1'---;-=&%#@+++++@@#$%%%$$###$%&*=-;;-=%$@@@##$%%%%#@@#$&=---*%#+++@@##@+. +@#$$#$%=;')'-&%*-,',=%%*;,,;*%&-;>-&%%*-;=&$%=,)';=-,~]~>=*-;>-=*=,{^^)--;){{'-=-,!~!>-=;,~]]);==;,)),-%$#$&=;;-*%$$$&=;;;=%###$%*=--=*%$$$%*=-;;;-=%$###$$$%%&&&%%$#@++++@@@#$;}k", +"l2);;;-=&$#@+++++@@#$$%%$$###$%&*=-;;-=%$@@@##$%%%%$#@#$%*---=%#+++@@##@++. .+#$$$#$&-,)),=%&=;''>*%%=;,>-&%*->>-&%&=--=%$%=,),-==>~]~>=*-;>;=*=>!^^!;=;'~{);=->)~~'-=->)]]!>==->')';*$#$%*-;;=&$$$%*-;>-*%###$%*---=&%$$$%*=-;;;-*%$####$$%%&&&&%$#@+++++@@$-}k", +"m3~>;-*%$#@+++++@@#$$%$$####$%&*=-;;-=%$@@@##$%%%%$#@@#%&=--=&$@+++@@@@++. .+@#$$$$%*;'));*%&->'';&%&=>,>=%%*->;=&%&=--=%$%=,),-==>!]~>=*=;>;=*=;!^/~>--,!{!>==;'!~)>==;'{^]';==;,'),-&$#$%=;;;=%$$$%*->;-*$###$%*---=&$$$$%*=-;;;-*%$####$$%%&&&&%$#@@++++@#-}k", +"m4~;=*%$#++++++@##$$%$$####$$%*=-;;-=%#@+@@#$%%%%$#@@#$&=---*$@+++@@@@@+. .+#$$$#$%=>)),-&%*;,),-%%&->,;*%%*->;=%%&=--*%$%=,),-*=>!]~>=*=;>;=**;)^/{,-->){~,-=-,!~!,-=-,!]^!>==->,)'>=%##$&=;;-*%$$$&=;>;=&$###$%*---=&$##$%*=-;;--*%$####$$%%&&&&%$#@@++++#=[k", +"m4!-&%#@++++++@##$$$$$####$$%*=-;;-=%$@@@@#$%%&%$#@@#$%*---=%#++++@@@@++. .+@#$$##$*-,))>=%&=>')>=%%*-,,;*%&=;>;*%%&=--*%$%-,',-*=>!]{,=&=;>>-**-']/]'-=;'~{);==>)~~';==>)]^]'-==;,'',-&$##%*-;;=&$$$%*-;>;=%$###$&=---*%$##$%&=--;-=*%$####$$%%&&&&%$$#@+++@=[j", +"m2'*$#@++++++@##$$$$$####$$%*=--;-=%$@@@@#$%%&%$#@@@$%*=--=&$@++++@@@++. .+#$$$#$%=>)!';&%&-,));*%%=;,>-&%&=;>-*%%*=--*%$&-,',-*=;!]{,=&=;>>-**-,{/^);=;'~{);==;'!{)>==;,~^^!>==->,''>=%##$%=;;;=%$$$%*-;>;*%####$&=---*%$##$%&=--;-=*%$####$$%%%&&&%%$#@++@=[j", +"l1>%#@++++++@##$$$$#####$$%&=--;-=&$@@@@#$$%&%%$@@@#%&=---*$@++++@@@++.. .+@$$$##$&-,)),=&%*;')'-&%&=>,>=%%&=;;-&%%*=-=&$$&-,',-*=;)]],=&=->>;=*=,~//!;=-,!{~,==-,)~!,-=->)]^]'-==;,'',-&$##$&-;;-*%$$$&=;>;-*$####%&=--=*%$##$%&==---=*%$####$$%%%&&&&%$#@+@=[j", +"k|;#@++++++@##$$$$#####$%%*=----=&$#@@@#$$%&%%$#@@#$&*=--*%#+++++@@++.. .+#$$$#$%=;'!);*%&=>)),=%%&->,;*%%&-;;-&%%*=-=&$$&-,',-*=;)]]'=&*->>;=*=>!^/{>-->){{'-*=>)~~);==;'{^]!>==-;,''>=%##$%*-;;=&$$$%*=;>;-&$###$%&=--=&%###$%&*=---=*%$####$$%%%&&&&%$#@#=[j", +"k}=@++++++@##$$$$##@##$%%*=----=&$#@@@#$$%%&%$#@@#$%*=--=%#+++++@@+++. .+@$$$##$&-,)!'-&%*-,))>*%%*-,,;*%%*-;;=%%%*=-=%$$&-,',-**;)]]'-**->>;=&*;)^/],-=;'~{);==;'!{!>==-,!]^{'-==;>'',-&$##$&=;;-=%$$$%*-;>;=%$###$%*=--=&$###$%&*=---=*%$####$$$%%&&&&%$#$=[j", +"j[=@+++++@##$$$$##@##$%%*=----=&$#@@@#$$%%&%$#@@#$%&=--=&$@+++++@+++. +@#$$$#$%*;'!)>=%%=;)!);&%%=;,>-&%%*-;;=%$%*--*%$$&-,',-**;)]])-**->>;=**-']/]'-=;,!]!>=*-,)~~'-==;)]^^!;==-;,''>=%###%*-;;-&$$$$&=->>;=%$###$%*=--=&$###$%&*=---=*%$####$$$%%&&&&%%%-}j", +"j[=@++++@##$$$$##@##$%%*==---=&$#@@@##$%%&%$#@@@#%&==-=*$@+++++++++.. .+#$$$##$&=>)!';&%&=,)!,-%%&=;,>=%%&=-;-*%$&=-=*%$$&-,'>=&*;)]])-**-;>>-**-,]/^);=-,!{~,-*=>)~{);==-,!^^{,-==;>,',;*$##$%=;;;=%$#$%&=;>>-*%####$%*=--*%$###$%&*==--=*%$#####$$%%&&&&%&;}k", +"j[=@++@@##$$$###@##$%%&==---=&$#@@@##$%%&%%#@@@#$&*=--=%#++++++++++. .@#$$$##%*;,!!,=%%*-'!!>=%%&->,;*%%&=;;-&%%&=-=*%$$&-,'>=&*;)]^)-**=;,>-**-,{//!;=->){{)-*=;'!{!,-==>)]^]);==-;,''>=%###$&-;;-*%$#$%*-;>;-&$####$&*=-=*%$###$%&*==-==*%$#####$$%%&&&&*>|k", +"j[=@+@@#$$$$###@##$%%&==---=&$#@+@##$%%&%%$#@@#$%*=--=&$@+.+++++++. .+#$$$$#$%=>)!);*%%=>)~);&$%*->,;*%%&=;;-&$%&=-=*%$$&-,'>=&*-']^!;**=;,>-**=>!//{>==;'~]);=*-,){~';==;'~^^{,-==;>,',;*$##$%*-;;-&$$$$&=-;>;=&$###$%&=--=*%$###$%&*==-==*%$#####$$%%&&&*,1k", +"j[=@@##$$$$##@@##$%%&*=---=&$#@+@##$%%%%%$#@@#$%&==-=*$@+.+++++++. .@#$$$##$*-,!!'-&%&-,!~'-%$%=;,>-&$%&-;;=&$%*=-=&$$$&-,'>=&*-']^!;*&=;>>;*&=;)^(],-=;,!]~,=*=>)~{)>==-,!]^]);==-;,''>-%###$&=;;;=%$#$%&=;>>;=%$###$%&=--=*%####$%&*==-==*%$#####$$%%%&*,1l", +"j[=###$$$$##@@##$%%&*=---=&$#@+@##$$%%%%$#@@@#%&*=--*%#+..+++++++. .+@$$$##$%=;'!)>=%%*;'!!,=%$&=;,>=%$%*-;;=%$%*===&$$$*-,'>=&*-']^!;*&=;>,;=&*;)^(^'-=-,!]{'-*=;'!{!,-==;){^^{,-*=;>,',;*$###%*-;;-*%$#$%*=;>>-*%####$%&=--=&%#@@#$%&*=====*%$#####$$%%%*,1l", +"j[-$#$$$$##@@##$%%&*=---=&$#@+@@#$$%%&%$#@+@#$%*=--=%#++.+++++++. .@#$$$##$&-,)!';&%&=>)~);*%%&->,;*%$%*-;;=%$%*=-=&$$$*;,'>=&*-']^!;*&=;>,;=&*-']/^);=->){]);**-,){{);==-,!^/]);==-;,',>-&$##$%=-;;-&$$$$%*-;>;-&$####$%&=--=&$#@@#$%&*=====*%$#####$$%%&,1l", +"k}-$$$$$##@@##$%%&*=---=&%#@+@@#$$%%&%$#@+@#$%*=--=&$@+.+++++++. .+#$$$##$%*;'!!,=%%&-,!~)-&$%*-,,;*%$%=-;-*%$%*=-=&$$%*;,'>=&*-']^~;*&=->,;=**-,{//~>==;'~]!>=*=>)~{!,=*->)]^^~,-*=;>,',;=%###$&=;>;=%$#$%&=-;>;=&$####$%*=--=&$#@@#$%&*=====*%$#####$$$&,1l", +"k};%$$$##@@##$%%&*=---=&%#@+@@#$$%%&%%$#@@#$%&=--=*%#+..+++++++. +@#$$$##$&=>)!);*%%*;'~~,=%$%=;,,-&$$&=;;-&%$&====%$$%*;,'>=&*-,{^~>*&*->,>-**=,~/(],==;,!]~,-*=;'!{~'-==;'~^/]);==-;,''>-&$##$%*-;;-*%$#$%&=;>>;=%$####$%*=-=*%$#@##$%&*=====*%$#####$$%>|k", +"k|;%$$##@@##$%%&*=---=*%#@++@##$%%&&%$#@@@#%&*=--=%#++.+++++++. .+#$$$###%*;,!!'-&%&=>){!>*$$&=>,>=%$%&=;;-&$$&===*%$#%*;,'>=&&-,{^~>*&*->,>-*&=>!^(]'-=-,){{);**-,){{);=*-,)]/^~,=*=;>,',;=%###$%=;;;=&$#$$%*-;>>-*%##@#$$&*=-=*%$#@##$%&*=====*%$#####$%>|k", +"k|;%$##@@##$%%&*=---=*%#@++@##$%%&%%$#@@@#$%*=--=&$@+.+++++++.. +@#$$$##$&=>)~!>=%%*-,!{);&$%&->,;=%$%*-;;=%$%&===*%$#%*;,'>=&&-,{^{,*&*-;,>-*&=;)^(^)-=->){]!>=*=>)~{!,-*=;'{^/]';==-;,,',-&$###%&-;>;=%$#$%&=-;>;-*$####$%&*=-=*%$#@##$%&*=====&%$#####$;|k", +"k|;%##@@##$%%&*=---=*%#@++@##$%%&&%$#@+@#$%&==-=*$#+..+++++++. .+#$$$###%*-,!~);*%%=;)~~'=%$%*-,,;*$$%*-;;=%$%&===*%##%*;,'>=&&-,{^{,=&*-;,,;=&*;'](/!;==;'~]~,=*=;'!{~';==-,!^/^!>=*=;>,',;=%###$%*-;;-*%$#$%&=-;>;=&$####$%&==-=*%##@##$%&*=====&%$####$;}k", +"k};$#@@##$%%&*=---=*%#@++@##$$%%&%$#@+@#$%&*=--*%#+..+++++++.. +@#$$$##$%=;)~!,-%%&=,!{!>*$$%=;,,-&$$%=-;;=%$%*===&$##%*;,'>=&&-,~^],=&&=;,,;=&*-'](/~>==;,!]{'-**-,){{)>=*=>)]^/]'-*=-;,,,,-*$###$&=;>;-&$#$$%*=;>>;=%$####$%&=--=*%#@@##$%&**====*%$###$-}k", +"k}-#@@##$%%&*=---=*%$@++@##$$%%&%%$@@@@#%&*=--=&$@+..++++++.. .+#$$$###$&-,)~)>*%%*-'~{);&$$&=>,>=%$$&=-;-*%$%*===&$##%=;,'>=&&-,~^],=&&=;,,;=&*-,~/(],==-,){]);*&=>)~{~,-*=;'~^/^!>=*=->,',>=%###$%*-;>;=%$#$$%*-;>>-=%$####$%&=--=&%#@@##$%&**====*%$##$-}k", +"k}-#@##$%%&*=---=*%$@+++@#$$%%&%%$#@+@#$%*=--=*$@+..+++++++. +@#$$$##$%=;'!~'-&%%=;){{'-%$%*->,;=%$%&=;;-*$$%*===&$##%=;,'>=&&=,~^]'=&&=;>,;=&&=>!/(^'-=->){]!>=&=;,!{{);=*->)]//]'-*=-;,,,,;*$###$%=;>;-*%$#$%&=-;>;-*%##@##$%*=--=&$#@@##$%&**====*%$#$-}k", +"k}-###$%%&*=---=*%$@+++@#$$%%&&%$#@+@#$%&=--=*%#+..+++++++.. .+#$$$$##$&->)~!,=%%&-,!{!,=%$%*;,,;*%$%*-;;-&$$%*===&$#$%=;''>=&&=,~^]'-&&=;>,>-*&=>)^(^);==;'~]~,-&*-,){{!>=*=;'~^/^!>=*=->,',>-&$###$&=;>;=&$#$$%*=;>>;-&$####$$%*=--=&$#@@##$%&**====*%$$-}k", +"j[-$#$%%&*=---=*%$@+++@##$%%&&%$#@+@#$%&*=--=&$@+..+++++++. +@#$$$##$%*;'!~);*%%*-'~{);&$$&=;,,-&$$%*-;;=&$$&*===&$#$%=;,';=&&=>!^])-&&=->,>-*&=;)](/!;==;,!]{);*&=>'~]~'-**-,!]//{,-*=-;,,',;*%###$%*-;>;=%$#$$%*-;>>;=&$####$%&*=--=&$#@@##$%&**====*%%;}k", +"k}-$$%%&*=---=*%$#+++@##$%%&&%$#@++@#$&*=--=&$@+..+++++++.. .+#$$$$##$&=>)~!,=%%%=;){{'-%$%&->,>-&$$%=-;;=%$$&===*%$#$%=>'';=&&=>!^^)-&&*->,,-*&*;'](({>==-,){]!>=&=;,!{{);=*=>){^/^);=*=->,',>-&$###$&=;>;-*%$#$%&=-;>>-=%$#@##$%&*=-=*%$#@@##$%&**====**>|k", +"k};%%%&*=----*&$#+++@##$$%%&%%$@@+@#$%*=--=*%#+..++++++++. +@#$$$##$%*-,!~)>*%%&-,!]~,=%$%*->,>=%$$&=-;;=%$%&===*%$#$%=>'';=&&=>!^^)-&&*->,,;=&*-,{/(],=*->)~]~,=&*-,){]!,-*=;,!^//{,-**-;,,',;=%####%*-;>;=&$##$%&=-;>;-*%##@##$%&=--=*%$#@@##$%&**=====,|k", +"k|;&&&*=----=&$#@++@##$$%%&%%$#@+@#$%&==--=%$@+..+++++++. .+#$$$###$&=>)~~'-&%%*;'~]);&$$%=;,,;*%$%&=;;-*%$%&===*%$#$&=>'';=&&=>!^^!;&%*->,,;=&*-,~/(^)-==;'~]{'-&&=>'~]~';**->)]//^);=*=->,',>-&$###$%=->>;=%$#$$%*=;>>;-&$#@@##$%&=--=*%$#@@#$$%&**===-'1l", +"k|>***=----=&$#@++@##$$%%&&%$#@+@#$%&*=--=&$@+..+++++++.. +@#$$$###%*-,!~!,=%%&=>){{)-%$$&=;,,;&$$%*=;;-*%$%*===*%$#$&=>'';=&&=>!^^!;&%*-;,,;=&&=>!^(/);==;,!]]);*&=;,!{{)>=*=;'~^//~,=**-;,,',;=%####$&=;>;-*%$#$%&*-;>>;=&$#@###$%*=--=*%$#@@#$$%&**==-)2l", +"l1'-=-;;;;-*%$#@@##$%%&&**&%$#@##$%*=-;;-=&$@+++@@@@@@++++..++@$%%%$$$%*->){{)>=%&=;'~]{'-&%%*-,',;*%%&=;>>;*%%&=---=&$$%*-,)'>=**-,~//{>*&=->'',-**->!^_({,-=;,!]^{,-*=;,!]]{';==;,!^((^!>==-;,')',;=%$#$%&=;>,>-*%$$%&*=;>,,;-&%$##$$%*=-;;-=&$###$%%&*==-;!3m", +"n5^)))!!!)'>;-===--;;>,,,,>;-===-;,'))!!),;=****======**&&&&&*-;>>;;-;>,)]/_(^!,>>'~^_:(]'>;>'!]^]),;;,'!{{),;;,')))'>;-;,)]^^{),,){(<[_{,,,)~]^])',)~/:}}:])')]/_:_^),')]/_:_/~'')]/_[[<(])''!{]^^^{)>;---;,)~]]!'>;-;;>,)~]]{!'>;----;>,')!!),>--=--;>,,')!(7n", +"sf632333321|}[[[[}}}||111||}[[[}}|1223332|}[<<<[[[[[[[<<<<<<<[}}||}}}}|23589852|||24799741|||245542|||1234421||122221|}}|13465421124800841|1245543112469aa95222468996311246899742124680a095312345565431}}[}}|2344421}}}||123454421}}[}}}||123332|}}[[}}||11237gt", +"xsnmmmmmmlkkjjjjjkkkkklllkkkjjjkkklllmmmlkjjjjjjjjjjjjjjjjjjjjjkkkkkkkklmnoonmlkkllmnoonmlkkklmnnmlkkkllmmmlkkkkllmllkkkklmmnnmlkllmoppomlkllmnnmmlllmnopponmlmmnooonmlllmnooonmlllmnoopponmlllmmnnnnmlkkjkkklmmmmmlkkkkkklmmnnmllkkjjkkkkllmmmlkkjjjjkkkkllmnsx"}; diff --git a/hacks/images/wood.xpm b/hacks/images/wood.xpm new file mode 100644 index 00000000..0bc9b869 --- /dev/null +++ b/hacks/images/wood.xpm @@ -0,0 +1,70 @@ +/* XPM */ +static char *wood_texture[] = { +/* columns rows colors chars-per-pixel */ +"128 32 32 1 ", +" c #6C2A14", +". c #7C3A24", +"X c #945644", +"o c #9C5A44", +"O c #A45E4C", +"+ c #A46254", +"@ c #A4624C", +"# c #9C5E4C", +"$ c #AC6A54", +"% c #AC6654", +"& c #B46E5C", +"* c #B4725C", +"= c #BC7664", +"- c #CC8674", +"; c #AC6E5C", +": c #AC725C", +"> c #C47E64", +", c #A46A54", +"< c #9C624C", +"1 c #94523C", +"2 c #8C4E3C", +"3 c #AC665C", +"4 c #844A3C", +"5 c #7C3E2C", +"6 c #000000", +"7 c #000000", +"8 c #000000", +"9 c #000000", +"0 c #000000", +"q c #000000", +"w c #000000", +"e c #000000", +/* pixels */ +" . . . .... . . . . ........ 5 ", +" 2X#XooXooooooO++@oO#@@#@@+$$@Oo@$@OO@@@%$$$$@@@O@@@O%$%@@%>>->>=&========***;$;%$;&;%%$$$$$$%+@$;$:*&;;$+**=**$$&**;;*=>>>--, ", +" 4=>-=>>=>>=>>>>->>>>>>>>>>--->>>>->=>>>>>--->>>>>>->>>>->----------------->-------------->>>>===>>>==>>>>>---->==>>>>>-------< ", +" +#+X##O3OoO+O@@%$$$+O<+@++@@%$$$$@@@@@@$&$@@$*@@$&*&$*=*=*>=;%$&@;$$%%%$@@$;**==>=>=*=***&*&$;;==$&*;***;***&;**$&*=***&&==>, ", +" X###O#OooOo11@oo#@@@XoooO#oo%*=$$@O@%$%$&$@@$*$$$&&%O$***&&$@;=*&=$O@%++$$$$$;=*&***===**;;=*$$**;$;*=*;&,$$;;;$&&***==&&===2 ", +" .###X#Xoo#oo121Xo#@+@oo#o#O%@%$&$@%OO%&&%$%@@%&$$$*&%o$*&&%+OoO&%+&+O@+@+%,;;;&==*:&&=***&;&=*;$;;+%;***&$;&**=****=====>=>*=< ", +" .X2X2oXoO#oX12ooo#O#XXo#oo#%%$&*&%$@@$$&$&&@%$*&&&*&$O$=*$&$%O@&%%&%@O@@%+$$;**===;$,*&$;&;**;$$;$O@;*;;$+;&;*******=*=*&&&;:4 ", +" #XXX##+Ooooo#O#@@@#oXooXooO@&=*=*$%@$$@*>=$%&=*&***$O&==*=&&@$=$&*&$@%@@%$;**=>=*$+%;$;$$;&&;;&;&@#$*$+$@%,$;;&;$$$&$$$&$===# ", +" 5<++#+@#O#oooO##@+$$%XooX1oo@&*>>=&$$$&@=>=$$*=***==&%$>==&$@O$&$&*&&$$$%+;*=====;,%$&;$$%$$;;$&:&$o;*%+&@+%+$$$$%$$$,$%%%*==X ", +" .XXX21211ooooX%%+$$+@@#@OO#&**$*=*=*&*=*=*===*&=**=>*&*>>*=*&%&=$&$&*&&*=;*====**&***&$$+%,$:&;&$;&+;**&$$*&&;;;&;&*****=*>=>, ", +" .#o#X+##11XOO%@$&*=&;O@+@+%==>=**>=*===&>=>>>=*=*=>>>*=>=>>*&@&*%>*=*&=*=*==>=*=&*==:;;%+%$;&*;$$$$$&**=&&*:;$$$$&;*****=&===X ", +" 4oo#@#OoooXo#@&%$*=*;@ooO%$*>>=&=>>>>>>*=>===*==>=>>>>=>>->====*==**%$=========*$;*;$&**&++%;$$&;&;%;***;;**&&;;;&&**=**%%&+;X ", +" 52o#OXoO#o1XoO@#%&==*+O#oOO@&>>>>>=>>>==>-->>>>>=>>>>=>===>>=***=>==&*==****=*;O+*=$@@+%%@%$&&&&&&&$;*=***=*=*===&;**===$%=+;4 ", +" 5o@+@o#111111XXXo@%$$%@#1241%*>>>->>>>>=->>>=>>>==>>=>=>===>>>*=====&*=======*&@+==$+&&&&$&;&*&*;&&%$;&;;;*******&***====&=3=4 ", +" 4oXooo+o##@+@%%$&&&****&+Oo%&=>>====**==>>=*==>>=>>>=&*=*&$*>>>*>===&*=*=====*$#O@%@$==**&&&&;&;&;;%$;$$$$%+$$$$;&;&;***===&=4 ", +" 54221Oo@+$$;$&*&&*&*&**&*=&***&&&**&&$&**&&&==&&&&*$@%&&;$&*=%$*===&&=*****$+#2Xo#<%;$$%$$$$%$%$$$$;&&;$;+%,$;$$;;+%+$$&&&3=4 ", +" X$$$&+$$+$$;$;$$$&&&&=*&&;&==>>-==*=>==&>>==>>>>>>-->=*$&***>&***&&&@%&$$%$$;$@===*;$$;&$%%%%+%%;$&@@@@##@+@%+%@#%3+%,@%@%%+,5 ", +" X@#@+%$+@+$;&$&$&&*&;%+$&&$&%@$$%@@%$$@oO@OOoO@@@%$$%$@11oOO@%%%%%@@oO@@O#O@+@+o#o#oooo@OO@%@%%$$&*;&;&$$;$;***$$3$;;;$$&&&%;5 ", +" 1o@@@o1XX1XoXoo+@#O@@oO@Oo#@%%@@&=*===*&$======%$&*==*==*%@$@@%%@@%%OO%@@o#@#o##@@#oXoooo1Xooo11o#o1oXXoo#ooo#ooXooo#@+$%O%%34 ", +" 522222211Xooo#XoooooO#o%+OO&&*&&*=**=**&*=***==*&***$$&===$$%%$$%%%$O@%@%#+%@@@O@+@@@O#O#oooOooo#@#oXoo##o##O****&;&+&&*&*&****==***=*&&&**&&&***&&&&$$&&&$&*%%&&*$$$$;$&$@@&$%+$;$%+@@+@oo+%%+@+%%@@%$$O#@@@+@#@%+@+@+++%++@@%OOO:X5", +"5XO@@@+@$;$;&**+$;&&$%*=*%&=%$$&&&%&&&&**$%@%$&*%$$$$%%%%%&&%$$%%$&&%oO$*%@+$+@+@++@+@OO@+@@%@@O@%%o+@@@@+%+@+@@@+%+%+@@@%@%O<45", +"5@+++%$+++%$$;&;&***&+*==*&=*===*=$&;&$$&$%%$&**$$&*&$$$&*&$%$$@%$$&$oo$&+@+$+@@$$@O@+@+%@@O@+OOO+@oO#@@+%@%@+@@+@+%+@<@O@%%O,45", +"5+@oo@+@$$$;$;$&&&*&$@&*==*&*==&&=$*&&$$$$&&**&&$&&=**==**&&$$$%@$@&$Oo%$;@+%@++++oX%$%%%@O#O%@#O@+oX#O++++$+%@+@+OO++@O#@++#355", +".,$%++@+$;$;$;*&;&==***=***&=====*&=*&$&*&$$*==**===**==***$$$@@$*$%%@@@@++@@@@+@===;&:$$$**&$$@%@+%@+@++@@OoO@@%+@@#@@@@#@++Oo+$;%@,+@+<@@++OOO++O#####. ", +".;;;$;,$$$;$$$&$$&**=*&&&$&$&&&&&$&**;$$;$%$*****===**&;$;$&&&:&:&:$$,$+$@+@+@+@@##o##+@@##o#@@#@@@#oo@@#oO=>======>>>=**=>>=**=====>>=>->=***========>=*$$+%@+%#@+@@@<@#O#oO@+@#o#oO#O<@+oO@++@@@#o###o#%+@+++%++,++5.", +" oooXooXo#oXoo#XoOo#O##oo#oooo#o#oOO#ooooooo#o#ooOo#o#ooOoOo#####X+@#O#O#O@@O@##@@@@@@#o##O<@###O@@#oo#oooo#oo#oooXo#oooo#++#X. ", +" 22222221112221222222212121242221122112222221222221111Xo1X1XXXXoX1X1212121222211121221221211111221121X112112222212XXXXXXXX1224. ", +" . . . .......5..5.55555555555..555.555555.555555..555.5..5.................... 5 " +}; diff --git a/hacks/imsmap.c b/hacks/imsmap.c new file mode 100644 index 00000000..aeee0308 --- /dev/null +++ b/hacks/imsmap.c @@ -0,0 +1,416 @@ +/* imsmap, Copyright (c) 1992-2008 Juergen Nickelsen and Jamie Zawinski. + * Derived from code by Markus Schirmer, TU Berlin. + * + * 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. + * + * Revision History: + * 24-aug-92: jwz: hacked. + * 17-May-97: jwz: hacked more. + */ + +#include +#include + +#include "screenhack.h" + +#define NSTEPS 7 +#define COUNT (1 << NSTEPS) +#define CELL(c, r) st->cell[((unsigned int)(c)) + ((unsigned int) (r)) * st->xmax] + +#if defined(sun) && !__STDC__ /* sun cc doesn't know "signed char" */ +#define signed /**/ +#endif + +struct state { + Display *dpy; + Window window; + Colormap cmap; + int ncolors; + XColor *colors; + Bool extra_krinkly_p; + + int delay, delay2; + signed char *cell; + int xmax, ymax; + int iteration, iterations; + + int cx, xstep, ystep, xnextStep, ynextStep; + + unsigned int last_pixel, last_valid; + int flip_x; + int flip_xy; + + GC gc, gc2; + XWindowAttributes xgwa; + + struct timeval then; +}; + + +#define HEIGHT_TO_PIXEL(height) \ + ((height) < 0 \ + ? (st->extra_krinkly_p \ + ? st->ncolors - 1 - ((-(height)) % st->ncolors) \ + : 0) \ + : ((height) >= st->ncolors \ + ? (st->extra_krinkly_p \ + ? (height) % st->ncolors \ + : st->ncolors-1) \ + : (height))) + + +static unsigned int +set (struct state *st, + unsigned int l, + unsigned int c, + unsigned int size, + int height) +{ + int rang = 1 << (NSTEPS - size); + height = height + (random () % rang) - rang / 2; + height = HEIGHT_TO_PIXEL(height); + CELL (l, c) = height; + return st->colors[height].pixel; +} + + +static void +floyd_steinberg (struct state *st) +{ + int x, y, err; + + /* Instead of repeatedly calling XPutPixel(), we make an Image and then + send its bits over all at once. This consumes much less network + bandwidth. The image we create is Wx1 intead of WxH, so that we + don't use enormous amounts of memory. + */ + XImage *image = + XCreateImage (st->dpy, st->xgwa.visual, + 1, XYBitmap, 0, /* depth, format, offset */ + (char *) calloc ((st->xmax + 8) / 8, 1), /* data */ + st->xmax, 1, 8, 0); /* w, h, pad, bpl */ + + XSetForeground (st->dpy, st->gc, st->colors[0].pixel); + XSetBackground (st->dpy, st->gc, st->colors[1].pixel); + + for (y = 0; y < st->ymax - 1; y++) + { + for (x = 0; x < st->xmax - 1; x++) + { + if (CELL(x, y) < 0) + { + err = CELL (x, y); + XPutPixel (image, x, 0, 1); + } + else + { + err = CELL (x, y) - 1; + XPutPixel (image, x, 0, 0); + } + /* distribute error */ + CELL (x, y+1) += (int) (((float) err) * 3.0/8.0); + CELL (x+1, y) += (int) (((float) err) * 3.0/8.0); + CELL (x+1, y+1) += (int) (((float) err) * 1.0/4.0); + } + XPutImage (st->dpy, st->window, st->gc, image, 0, 0, 0, y, st->xmax, 1); + } + XDestroyImage (image); +} + + +static void +draw (struct state *st, + int x, int y, unsigned long pixel, int grid_size) +{ + if (st->flip_x) + x = st->xmax - x; + + if (st->flip_xy) + { + int swap = x; + x = y; + y = swap; + } + + if (! (st->last_valid && pixel == st->last_pixel)) + XSetForeground (st->dpy, st->gc, pixel); + st->last_valid = 1, st->last_pixel = pixel; + if (grid_size == 1) + XDrawPoint (st->dpy, st->window, st->gc, x, y); + else + XFillRectangle (st->dpy, st->window, st->gc, x, y, grid_size, grid_size); +} + + +static void +init_map (struct state *st) +{ + XGCValues gcv; + + XGetWindowAttributes (st->dpy, st->window, &st->xgwa); + st->cmap = st->xgwa.colormap; + + st->flip_x = (random() % 2); + st->flip_xy = (random() % 2); + + if (mono_p) + st->flip_xy = 0; + else if (st->colors) + free_colors (st->dpy, st->cmap, st->colors, st->ncolors); + st->colors = 0; + + st->ncolors = get_integer_resource (st->dpy, "ncolors", "Integer"); + st->delay = get_integer_resource (st->dpy, "delay", "Integer"); + st->delay2 = get_integer_resource (st->dpy, "delay2", "Integer"); + st->iterations = get_integer_resource (st->dpy, "iterations", "Integer"); + if (st->iterations < 0) st->iterations = 0; + else if (st->iterations > 7) st->iterations = 7; + + if (st->ncolors <= 2) st->ncolors = 0; + if (st->ncolors == 0) mono_p = True; + if (st->ncolors > 255) st->ncolors = 255; /* too many look bad */ + + if (!st->gc) st->gc = XCreateGC (st->dpy, st->window, 0, &gcv); + if (!st->gc2) st->gc2 = XCreateGC (st->dpy, st->window, 0, &gcv); + + if (mono_p) + st->extra_krinkly_p = !(random() % 15); + else + st->extra_krinkly_p = !(random() % 5); + + if (!mono_p) + { + st->colors = (XColor *) malloc (st->ncolors * sizeof(*st->colors)); + + make_smooth_colormap (st->dpy, st->xgwa.visual, st->cmap, + st->colors, &st->ncolors, + True, 0, False); + if (st->ncolors <= 2) + mono_p = 1; + } + + if (mono_p) + { + int i; + unsigned long fg_pixel = + get_pixel_resource (st->dpy, st->xgwa.colormap, + "foreground", "Foreground"); + unsigned long bg_pixel = + get_pixel_resource (st->dpy, st->xgwa.colormap, + "background", "Background"); + if (!st->colors) + { + st->ncolors = 50; + st->colors = (XColor *) calloc (st->ncolors, sizeof(*st->colors)); + } + st->colors[0].pixel = fg_pixel; + for (i = 1; i < st->ncolors; i++) + st->colors[i].pixel = bg_pixel; + } + + XSetForeground (st->dpy, st->gc, st->colors[1].pixel); + XFillRectangle (st->dpy, st->window, st->gc, 0, 0, + st->xgwa.width, st->xgwa.height); + + if (st->flip_xy) + { + st->xmax = st->xgwa.height; + st->ymax = st->xgwa.width; + } + else + { + st->xmax = st->xgwa.width; + st->ymax = st->xgwa.height; + } + + if (st->cell) free (st->cell); + st->cell = (signed char *) calloc (st->xmax * st->ymax, 1); + + CELL (0, 0) = 0; + st->xstep = COUNT; + st->ystep = COUNT; + + st->iteration = 0; + st->cx = 0; +} + + +static void * +imsmap_init (Display *dpy, Window window) +{ + struct state *st = (struct state *) calloc (1, sizeof(*st)); + st->dpy = dpy; + st->window = window; + init_map (st); + return st; +} + + +static unsigned long +imsmap_draw (Display *dpy, Window window, void *closure) +{ + struct state *st = (struct state *) closure; + int this_delay = st->delay2; + int i; + + /* do this many lines at a time without pausing */ + int col_chunk = st->iteration * 2 + 1; + + if (st->iteration > st->iterations) + init_map (st); + + if (st->cx == 0) + { + st->xnextStep = st->xstep / 2; + st->ynextStep = st->ystep / 2; + } + + for (i = 0; i < col_chunk; i++) + { + int x1, x2, y1, y2; + int y; + int x = st->cx; + + x1 = x + st->xnextStep; + if (x1 < 0) + x1 = st->xmax-1; + else if (x1 >= st->xmax) + x1 = 0; + + x2 = x + st->xstep; + if (x2 < 0) + x2 = st->xmax-1; + else if (x2 >= st->xmax) + x2 = 0; + + for (y = 0; y < st->ymax; y += st->ystep) + { + unsigned int pixel, qpixels [4]; + + y1 = y + st->ynextStep; + if (y1 < 0) + y1 = st->ymax-1; + else if (y1 >= st->ymax) + y1 = 0; + + y2 = y + st->ystep; + if (y2 < 0) + y2 = st->ymax-1; + else if (y2 >= st->ymax) + y2 = 0; + + qpixels [0] = st->colors [HEIGHT_TO_PIXEL (CELL (x, y))].pixel; + qpixels [1] = st->colors [HEIGHT_TO_PIXEL (CELL (x, y2))].pixel; + qpixels [2] = st->colors [HEIGHT_TO_PIXEL (CELL (x2, y))].pixel; + qpixels [3] = st->colors [HEIGHT_TO_PIXEL (CELL (x2, y2))].pixel; + + pixel = set (st, x, y1, st->iteration, + ((int) CELL (x, y) + (int) CELL (x, y2) + 1) / 2); + + if (! mono_p && + (pixel != qpixels[0] || pixel != qpixels[1] || + pixel != qpixels[2] || pixel != qpixels[3])) + draw (st, x, y1, pixel, st->ynextStep); + + pixel = set (st, x1, y, st->iteration, + ((int) CELL (x, y) + (int) CELL (x2, y) + 1) / 2); + if (! mono_p && + (pixel != qpixels[0] || pixel != qpixels[1] || + pixel != qpixels[2] || pixel != qpixels[3])) + draw (st, x1, y, pixel, st->ynextStep); + + pixel = set (st, x1, y1, st->iteration, + ((int) CELL (x, y) + (int) CELL (x, y2) + + (int) CELL (x2, y) + (int) CELL (x2, y2) + 2) + / 4); + if (! mono_p && + (pixel != qpixels[0] || pixel != qpixels[1] || + pixel != qpixels[2] || pixel != qpixels[3])) + draw (st, x1, y1, pixel, st->ynextStep); + } + + st->cx += st->xstep; + if (st->cx >= st->xmax) + break; + } + + if (st->cx >= st->xmax) + { + st->cx = 0; + st->xstep = st->xnextStep; + st->ystep = st->ynextStep; + + st->iteration++; + + if (st->iteration > st->iterations) + this_delay = st->delay * 1000000; + + if (mono_p) + floyd_steinberg (st); /* in mono, do all drawing at the end */ + } + + return this_delay; +} + + +static void +imsmap_reshape (Display *dpy, Window window, void *closure, + unsigned int w, unsigned int h) +{ + struct state *st = (struct state *) closure; + init_map (st); +} + + +static Bool +imsmap_event (Display *dpy, Window window, void *closure, XEvent *event) +{ + struct state *st = (struct state *) closure; + if (event->xany.type == ButtonPress) + { + init_map (st); + return True; + } + + return False; +} + + +static void +imsmap_free (Display *dpy, Window window, void *closure) +{ + struct state *st = (struct state *) closure; + if (st->colors) free (st->colors); + if (st->cell) free (st->cell); + free (st); +} + + +static const char *imsmap_defaults [] = { + ".background: #000066", + ".foreground: #FF00FF", + "*fpsSolid: true", + "*mode: random", + "*ncolors: 50", + "*iterations: 7", + "*delay: 5", + "*delay2: 20000", + 0 +}; + +static XrmOptionDescRec imsmap_options [] = { + { "-ncolors", ".ncolors", XrmoptionSepArg, 0 }, + { "-delay", ".delay", XrmoptionSepArg, 0 }, + { "-delay2", ".delay2", XrmoptionSepArg, 0 }, + { "-mode", ".mode", XrmoptionSepArg, 0 }, + { "-iterations", ".iterations", XrmoptionSepArg, 0 }, + { 0, 0, 0, 0 } +}; + +XSCREENSAVER_MODULE ("IMSMap", imsmap) diff --git a/hacks/imsmap.man b/hacks/imsmap.man new file mode 100644 index 00000000..b4bc092c --- /dev/null +++ b/hacks/imsmap.man @@ -0,0 +1,64 @@ +.TH XScreenSaver 1 "17-May-97" "X Version 11" +.SH NAME +imsmap - generate fractal maps +.SH SYNOPSIS +.B imsmap +[\-display \fIhost:display.screen\fP] [\-foreground \fIcolor\fP] [\-background \fIcolor\fP] [\-window] [\-root] [\-mono] [\-install] [\-visual \fIvisual\fP] [\-ncolors \fIint\fP] [\-delay \fIseconds\fP] [\-delay2 \fImicroseconds\fP] [\-iterations \fIint\fP] [\-mode h|s|v|random] +[\-fps] +.SH DESCRIPTION +The \fIimsmap\fP program generates map or cloud-like patterns. It looks +quite different in monochrome and color. +.SH OPTIONS +.I imsmap +accepts the following options: +.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 \-mono +If on a color display, pretend we're on a monochrome display. +.TP 8 +.B \-install +Install a private colormap for the window. +.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 \-ncolors \fIinteger\fP +How many colors to use. Default 50. +.TP 8 +.B \-delay \fIinteger\fP +How long to delay between images. Default 10 seconds. +.TP 8 +.B \-delay2 \fIinteger\fP +How long to delay between bitmaps. Default 200000 (0.2 seconds). +.TP 8 +.B \-iterations \fIinteger\fP +A measure of the resolution of the resultant image, from 0 to 7. Default 7. +.TP 8 +.B \-mode [ hue | saturation | value | random ] +The axis upon which colors should be interpolated between the foreground +and background color. Default random. +.TP 8 +.B \-fps +Display the current frame rate and CPU load. +.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 AUTHOR +Juergen Nickelsen , 23-aug-92. + +Hacked on by Jamie Zawinski , 24-aug-92, 17-May-97. diff --git a/hacks/interaggregate.c b/hacks/interaggregate.c new file mode 100644 index 00000000..6e48f3f2 --- /dev/null +++ b/hacks/interaggregate.c @@ -0,0 +1,971 @@ +/* + * InterAggregate (dagraz@gmail.com) + * Based on code from complexification.net Intersection Aggregate + * http://www.complexification.net/gallery/machines/interAggregate/index.php + * + * Intersection Aggregate code: + * j.tarbell May, 2004 + * Albuquerque, New Mexico + * complexification.net + * + * Also based on substrate, a port of j.tarbell's Substrate Art done + * by dragorn@kismetwireless.net + * + * + * Interesting command line options, all of which serve to + * concentrate the painting in some way: + * + * -percent-orbits 100 -base-orbits 50 -base-on-center -growth-delay 0 + * + * Paint should be concentrated in the center of the canvas, orbiting + * about it. -percent-orbits 100 implies -base-on-center, so that's + * not really needed. + * + * + * -percent-orbits 99 -base-orbits 50 -growth-delay 0 + * + * Like the above example, but the 'center' will rove about the screen. + * + * -percent-orbits 98 -base-orbits 50 -growth-delay 0 + * + * Like the above example, but there will be two roving centers. + * + * + * TODO: + * -fix alpha blending / byte ordering + * + * CHANGES + * + * + * Directly based the hacks of: + * + * xscreensaver, Copyright (c) 1997, 1998, 2002 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. + */ + +#include +#include "screenhack.h" + + +/* this program goes faster if some functions are inline. The following is + * borrowed from ifs.c */ +#if !defined( __GNUC__ ) && !defined(__cplusplus) && !defined(c_plusplus) +#undef inline +#define inline /* */ +#endif + +#ifndef MIN +#define MIN(x,y) ((x < y) ? x : y) +#endif + +#ifndef MAX +#define MAX(x,y) ((x < y) ? y : x) +#endif + +static const char *interaggregate_defaults[] = +{ + ".background: white", + ".foreground: black", + "*fpsSolid: true", + "*maxCycles: 100000", +#ifdef TIME_ME + "*growthDelay: 0", +#else + "*growthDelay: 18000", +#endif + "*numCircles: 100", + "*percentOrbits: 0", + "*baseOrbits: 75", + "*baseOnCenter: False", + "*drawCenters: False", + 0 +}; + +static XrmOptionDescRec interaggregate_options[] = +{ + {"-background", ".background", XrmoptionSepArg, 0}, + {"-foreground", ".foreground", XrmoptionSepArg, 0}, + {"-max-cycles", ".maxCycles", XrmoptionSepArg, 0}, + {"-growth-delay", ".growthDelay", XrmoptionSepArg, 0}, + {"-num-circles", ".numCircles", XrmoptionSepArg, 0}, + {"-percent-orbits", ".percentOrbits", XrmoptionSepArg, 0}, + {"-base-orbits", ".baseOrbits", XrmoptionSepArg, 0}, + {"-base-on-center", ".baseOnCenter", XrmoptionNoArg, "true"}, + {"-draw-centers", ".drawCenters", XrmoptionNoArg, "true"}, + {0, 0, 0, 0} +}; + +/* Raw colormap extracted from pollockEFF.gif */ +#if 0 +char *rgb_colormap[] = +{ + "#FFFFFF", /* white */ + "#000000", /* black */ + "#000000", /* more black */ + /* "#736451", */ + "#4e3e2e", /* olive */ + /* "#666666", */ + "#694d35", /* camel */ + "#b9a88c", /* tan */ + 0 +}; +#endif + +static const char *rgb_colormap[] = +{ + "#FFFFFF", /* white */ + "#000000", /* more black */ + "#000000", /* more black */ + "#4e3e2e", /* olive */ + "#694d35", /* camel */ + "#b0a085", /* tan */ + "#e6d3ae", + 0 +}; + +/* black white brown olive grey camel */ + +typedef enum { LINEAR, ORBIT } PathType; + +typedef struct +{ + + unsigned long color; + double gain; + double p; + +} SandPainter; + +typedef struct _circle +{ + double radius; + + double x; + double y; + + PathType path_type; + + /* for a linear path */ + double dx; + double dy; + + /* for orbital path */ + double theta; + double r; + double dtheta; + + struct _circle* center; + + int num_painters; + SandPainter* painters; + +} Circle; + + +struct field +{ + int height; + int width; + + int num_circles; + Circle* circles; + + int percent_orbits; + int base_orbits; + Bool base_on_center; + + /* used for orbits circling the center of the screen */ + Circle center_of_universe; + + /* Raw map of pixels we need to keep for alpha blending */ + unsigned long int *off_img; + + /* color parms */ + int numcolors; + unsigned long *parsedcolors; + unsigned long fgcolor; + unsigned long bgcolor; + int visdepth; + + unsigned int cycles; + + double max_gain; + + /* for debugging */ + Bool draw_centers; + + /* for profiling whatnot */ + int possible_intersections; + int intersection_count; +}; + + +static struct field * +init_field(void) +{ + struct field *f = (struct field*) malloc(sizeof(struct field)); + if ( f == NULL ) + { + fprintf(stderr, "%s: Failed to allocate field!\n", progname); + exit(1); + } + + f->height = 0; + f->width = 0; + f->num_circles = 0; + f->circles = NULL; + f->percent_orbits = 0; + f->base_orbits = 0; + f->base_on_center = False; + f->off_img = NULL; + f->numcolors = 0; + f->parsedcolors = NULL; + f->fgcolor = 0; + f->bgcolor = 0; + f->visdepth = 0; + + f->cycles = 0; + + f->max_gain = 0.22; + + f->draw_centers = False; + + f->possible_intersections = 0; + f->intersection_count = 0; + + return f; +} + +/* Quick references to pixels in the offscreen map and in the crack grid */ +#define ref_pixel(f, x, y) ((f)->off_img[(y) * (f)->width + (x)]) + +#define in_bounds(f, x, y) ((x >= 0) && (x < f->width) && (y >= 0) && (y < f->height)) + +/* Consider rewriting with XQueryColor, or ImageByteOrder */ + +static inline void point2rgb(int depth, unsigned long c, int *r, int *g, int *b) +{ + switch(depth) + { + case 32: + case 24: +#ifdef HAVE_COCOA + /* This program idiotically does not go through a color map, so + we have to hardcode in knowledge of how jwxyz.a packs pixels! + Fix it to go through st->colors[st->ncolors] instead! + */ + *r = (c & 0x00ff0000) >> 16; + *g = (c & 0x0000ffff) >> 8; + *b = (c & 0x000000ff); +#else + *b = c & 0xff; + *g = (c & 0xff00) >> 8; + *r = (c & 0xff0000) >> 16; +#endif + break; + case 16: + *b = (c & 0x1f) << 3; + *g = ((c >> 5) & 0x3f) << 2; + *r = ((c >> 11) & 0x1f) << 3; + break; + case 15: + *b = (c & 0x1f) << 3; + *g = ((c >> 5) & 0x1f) << 3; + *r = ((c >> 10) & 0x1f) << 3; + break; + } +} + +static inline unsigned long rgb2point(int depth, int r, int g, int b) +{ + unsigned long ret = 0; + + switch(depth) + { + case 32: + case 24: +#ifdef HAVE_COCOA + /* This program idiotically does not go through a color map, so + we have to hardcode in knowledge of how jwxyz.a packs pixels! + Fix it to go through st->colors[st->ncolors] instead! + */ + ret = 0xFF000000 | (r << 16) | (g << 8) | b; +#else + ret |= (r << 16) | (g << 8) | b; +#endif + break; + case 16: + ret = ((r>>3) << 11) | ((g>>2)<<5) | (b>>3); + break; + case 15: + ret = ((r>>3) << 10) | ((g>>3)<<5) | (b>>3); + break; + } + + return ret; +} + +/* alpha blended point drawing -- this is Not Right and will likely fail on + * non-intel platforms as it is now, needs fixing */ +static inline unsigned long trans_point(int x1, int y1, unsigned long myc, double a, + struct field *f) +{ + if (a >= 1.0) + { + ref_pixel(f, x1, y1) = myc; + return myc; + } + else + { + int or=0, og=0, ob=0; + int r=0, g=0, b=0; + int nr, ng, nb; + unsigned long c; + + c = ref_pixel(f, x1, y1); + + point2rgb(f->visdepth, c, &or, &og, &ob); + point2rgb(f->visdepth, myc, &r, &g, &b); + + nr = or + (r - or) * a; + ng = og + (g - og) * a; + nb = ob + (b - ob) * a; + + c = rgb2point(f->visdepth, nr, ng, nb); + + ref_pixel(f, x1, y1) = c; + + return c; + } +} + +static inline void drawPoint(int x, int y, unsigned long color, double intensity, + Display *dpy, Window window, GC fgc, struct field *f) + +{ + unsigned long c; + + while ( x >= f->width ) x -= f->width; + while ( x < 0 ) x += f->width; + + while ( y >= f->height ) y -= f->height; + while ( y < 0 ) y += f->height; + + /* if ( in_bounds(f, x, y) ) ... */ + + c = trans_point(x, y, color, intensity, f); + + XSetForeground(dpy, fgc, c); + XDrawPoint(dpy, window, fgc, x, y); +} + +static inline void paint(SandPainter* painter, double ax, double ay, double bx, double by, + Display *dpy, Window window, GC fgc, + struct field *f) +{ + /* the sand painter */ + + double inc, sandp; + int i; + + /* XXX try adding tpoint here, like orig */ + + /* jitter the painter's values */ + painter->gain += frand(0.05) - 0.025; + + if ( painter->gain > f->max_gain ) + painter->gain = -f->max_gain; + else if ( painter->gain < -f->max_gain ) + painter->gain = f->max_gain; + + painter->p += frand(0.1) - 0.05; + + if ( 0 < painter->p ) + painter->p = 0; + else if ( painter->p > 1.0 ) + painter->p = 1.0; + + /* replace 0.1 with 1 / f->grains */ + inc = painter->gain * 0.1; + sandp = 0; + + for(i = 0; i <= 10; ++i) + { + int drawx, drawy; + double sp, sm; + double intensity = 0.1 - 0.009 * i; + + sp = sin(painter->p + sandp); + drawx = ax + (bx - ax) * sp; + drawy = ay + (by - ay) * sp; + + drawPoint(drawx, drawy, painter->color, + intensity, + dpy, window, fgc, f); + + sm = sin(painter->p - sandp); + drawx = ax + (bx - ax) * sm; + drawy = ay + (by - ay) * sm; + + drawPoint(drawx, drawy, painter->color, + intensity, + dpy, window, fgc, f); + + sandp += inc; + } +} + +static void build_colors(struct field *f, Display *dpy, XWindowAttributes *xgwa) +{ + + XColor tmpcolor; + int i; + /* Count the colors in our map and assign them in a horrifically inefficient + * manner but it only happens once */ + + for( f->numcolors = 0; + rgb_colormap[f->numcolors] != NULL; + ++f->numcolors ) + { + ; + } + + f->parsedcolors = (unsigned long *) calloc(f->numcolors, + sizeof(unsigned long)); + if ( f->parsedcolors == NULL ) + { + fprintf(stderr, "%s: Failed to allocate parsedcolors\n", + progname); + exit(1); + } + + for(i = 0; i < f->numcolors; ++i) + { + if (!XParseColor(dpy, xgwa->colormap, + rgb_colormap[i], &tmpcolor)) + { + fprintf(stderr, "%s: couldn't parse color %s\n", progname, + rgb_colormap[i]); + exit(1); + } + + if (!XAllocColor(dpy, xgwa->colormap, &tmpcolor)) + { + fprintf(stderr, "%s: couldn't allocate color %s\n", progname, + rgb_colormap[i]); + exit(1); + } + + f->parsedcolors[i] = tmpcolor.pixel; + + } +} + +/* used when the window is resized */ +static void build_img(struct field *f) +{ + if (f->off_img) { + free(f->off_img); + f->off_img = NULL; + } + + f->off_img = (unsigned long *) calloc(f->width * f->height, + sizeof(unsigned long)); + + + if ( f->off_img == NULL ) + { + fprintf(stderr, "%s: Failed to allocate off_img\n", + progname); + exit(1); + } + + memset(f->off_img, f->bgcolor, + sizeof(unsigned long) * f->width * f->height); +} + +static void free_circles(struct field *f) +{ + int i; + + if ( f->circles != NULL ) + { + for(i = 0; i < f->num_circles; ++i) + { + free (f->circles[i].painters); + } + + free (f->circles); + f->circles = NULL; + } +} + +static void build_field(Display *dpy, Window window, XWindowAttributes xgwa, GC fgc, + struct field *f) +{ + int i; + int num_orbits; + int base_orbits; + int orbit_start; + build_img(f); + + f->center_of_universe.x = f->width / 2.0; + f->center_of_universe.y = f->height / 2.0; + f->center_of_universe.r = MAX(f->width, f->height) / 2.0; + + num_orbits = (f->percent_orbits * f->num_circles) / 100; + orbit_start = f->num_circles - num_orbits; + base_orbits = orbit_start + (num_orbits * f->base_orbits) / 100; + + free_circles(f); + + f->circles = (Circle*) calloc(f->num_circles, sizeof(Circle)); + if ( f->circles == NULL ) + { + fprintf(stderr, "%s: Failed to allocate off_img\n", + progname); + exit(1); + } + + for(i = 0; i < f->num_circles; ++i) + { + int j; + Circle *circle = f->circles + i; + + /* make this a pref */ + + if ( i >= orbit_start ) + circle->path_type = ORBIT; + else + circle->path_type = LINEAR; + + + if ( circle->path_type == LINEAR ) + { + circle->x = frand(f->width); + circle->y = frand(f->height); + + circle->dx = frand(0.5) - 0.25; + circle->dy = frand(0.5) - 0.25; + /* circle->dy = 0; */ + /* circle->r = f->height * (0.05 + frand(0.1)); */ + circle->radius = 5 + frand(55); + + /* in case we want orbits based on lines */ + circle->r = MIN(f->width, f->height) / 2.0; + circle->center = NULL; + } + else /* == ORBIT */ + { + if (i < base_orbits ) + { + if ( f->base_on_center ) + circle->center = &f->center_of_universe; + else + { + circle->center = f->circles + + ((int)frand(orbit_start - 0.1)); + } + + circle->r = 1 + frand(MIN(f->width, f->height) / 2.0); + + /* circle->radius = 5 + frand(55); */ + } + else + { + /* give a preference for the earlier circles */ + + double p = frand(0.9); + + circle->center = f->circles + (int) (p*i); + + circle->r = 1 + 0.5 * circle->center->r + 0.5 * frand(circle->center->r); + /* circle->r = 1 + frand(circle->center->r / 2); */ + + + /* circle->radius = MAX(5, frand(circle->r)); */ + /* circle->radius = 5 + frand(55); */ + } + + circle->radius = 5 + frand(MIN(55, circle->r)); + circle->dtheta = (frand(0.5) - 0.25) / circle->r; + circle->theta = frand(2 * M_PI); + + circle->x = circle->r * cos(circle->theta) + circle->center->x; + circle->y = circle->r * sin(circle->theta) + circle->center->y; + + } + + /* make this a command line option */ + circle->num_painters = 3; + circle->painters = (SandPainter*) calloc(circle->num_painters, + sizeof(SandPainter)); + if ( circle->painters == NULL ) + { + fprintf(stderr, "%s: failed to allocate painters", progname); + exit(1); + } + + for(j = 0; j < circle->num_painters; ++j) + { + SandPainter *painter = circle->painters + j; + + painter->gain = frand(0.09) + 0.01; + painter->p = frand(1.0); + painter->color = + f->parsedcolors[(int)(frand(0.999) * f->numcolors)]; + } + } +} + +static void moveCircles(struct field *f) +{ + int i; + + for(i = 0; i < f->num_circles; ++i) + { + Circle *circle = f->circles + i; + + if ( circle->path_type == LINEAR ) + { + circle->x += circle->dx; + circle->y += circle->dy; + +#if 0 + if ( circle->x < -circle->radius ) + circle->x = f->width + circle->radius; + else if ( circle->x >= f->width + circle->radius ) + circle->x = -circle->radius; + + if ( circle->y < -circle->radius ) + circle->y = f->height + circle->radius; + else if ( circle->y >= f->height + circle->radius ) + circle->y = -circle->radius; +#else + if ( circle->x < 0 ) circle->x += f->width; + else if ( circle->x >= f->width ) circle->x -= f->width; + + if ( circle->y < 0 ) circle->y += f->height; + else if ( circle->y >= f->height ) circle->y -= f->height; +#endif + } + else /* (circle->path_type == ORBIT) */ + { + circle->theta += circle->dtheta; + + if ( circle->theta < 0 ) circle->theta += 2 * M_PI; + else if ( circle->theta > 2 * M_PI ) circle->theta -= 2 * M_PI; + + circle->x = circle->r * cos(circle->theta) + circle->center->x; + circle->y = circle->r * sin(circle->theta) + circle->center->y; + +#if 0 + if ( circle->x < -circle->radius ) + circle->x += f->width + 2 * circle->radius; + else if ( circle->x >= f->width + circle->radius ) + circle->x -= f->width + 2 * circle->radius; + + if ( circle->y < -circle->radius ) + circle->y += f->height + 2 * circle->radius; + else if ( circle->y >= f->height + circle->radius ) + circle->y -= f->height + 2 * circle->radius; +#else + if ( circle->x < 0 ) circle->x += f->width; + else if ( circle->x >= f->width ) circle->x -= f->width; + + if ( circle->y < 0 ) circle->y += f->height; + else if ( circle->y >= f->height ) circle->y -= f->height; +#endif + } + } +} + +static void drawIntersections(Display *dpy, Window window, GC fgc, struct field *f) +{ + int i,j; + + /* One might be tempted to think 'hey, this is a crude algorithm + * that is going to check each of the n (n-1) / 2 possible + * intersections! Why not try bsp trees, quad trees, etc, etc, + * etc' + * + * In practice the time spent drawing the intersection of two + * circles dwarfs the time takes to check for intersection. + * Profiling on a 640x480 screen with 100 circles shows possible + * speed gains to be only a couple of percent. + * + * But hey, if you're bored, go have fun. Let me know how it + * turns out. + */ + + + for(i = 0; i < f->num_circles; ++i) + { + Circle *c1 = f->circles + i; + + if ( !f->draw_centers ) + { + /* the default branch */ + + for(j = i + 1; j < f->num_circles; ++j) + { + double d, dsqr, dx, dy; + Circle *c2 = f->circles + j; + +#ifdef TIME_ME + ++f->possible_intersections; +#endif + dx = c2->x - c1->x; + dy = c2->y - c1->y; + + dsqr = dx * dx + dy * dy; + d = sqrt(dsqr); + + if ( (fabs(dx) < (c1->radius + c2->radius)) && + (fabs(dy) < (c1->radius + c2->radius)) && + ( d < (c1->radius + c2->radius) ) && + ( d > fabs(c1->radius - c2->radius) ) ) + { + double d1, d2, r1sqr; + double bx, by; + double midpx, midpy; + double int1x, int1y; + double int2x, int2y; + int s; + + /* woo-hoo. the circles are neither outside nor + * inside each other. they intersect. + * + * Now, compute the coordinates of the points of + * intersection + */ + +#ifdef TIME_ME + ++f->intersection_count; +#endif + + /* unit vector in direction of c1 to c2 */ + bx = dx / d; + by = dy / d; + + r1sqr = c1->radius * c1->radius; + + /* distance from c1's center midpoint of intersection + * points */ + + d1 = 0.5 * (r1sqr - c2->radius * c2->radius + dsqr) / d; + + midpx = c1->x + d1 * bx; + midpy = c1->y + d1 * by; + + /* distance from midpoint to points of intersection */ + + d2 = sqrt(r1sqr - d1 * d1); + + int1x = midpx + d2 * by; + int1y = midpy - d2 * bx; + + int2x = midpx - d2 * by; + int2y = midpy + d2 * bx; + + for(s = 0; s < c1->num_painters; ++s) + { + paint(c1->painters + s, int1x, int1y, int2x, int2y, + dpy, window, fgc, f); + } + } + } + } + else /* f->draw_centers */ + { + XDrawPoint(dpy, window, fgc, c1->x, c1->y); + } + } +} + +struct state { + Display *dpy; + Window window; + + unsigned int max_cycles; + int growth_delay; + GC fgc; + XGCValues gcv; + XWindowAttributes xgwa; + + struct field *f; +}; + + +static void * +interaggregate_init (Display *dpy, Window window) +{ + struct state *st = (struct state *) calloc (1, sizeof(*st)); + +#ifdef TIME_ME + int frames; + struct timeval tm1, tm2; + double tdiff; +#endif + + st->dpy = dpy; + st->window = window; + st->f = init_field(); + st->growth_delay = (get_integer_resource(st->dpy, "growthDelay", "Integer")); + st->max_cycles = (get_integer_resource(st->dpy, "maxCycles", "Integer")); + st->f->num_circles = (get_integer_resource(st->dpy, "numCircles", "Integer")); + st->f->percent_orbits = (get_integer_resource(st->dpy, "percentOrbits", "Integer")); + st->f->base_orbits = (get_integer_resource(st->dpy, "baseOrbits", "Integer")); + st->f->base_on_center = (get_boolean_resource(st->dpy, "baseOnCenter", "Boolean")); + st->f->draw_centers = (get_boolean_resource(st->dpy, "drawCenters", "Boolean")); + + if (st->f->num_circles <= 1) + { + fprintf(stderr, "%s: Minimum number of circles is 2\n", + progname); + exit (1); + } + + if ( (st->f->percent_orbits < 0) || (st->f->percent_orbits > 100) ) + { + fprintf(stderr, "%s: percent-oribts must be between 0 and 100\n", + progname); + exit (1); + } + + if ( (st->f->base_orbits < 0) || (st->f->base_orbits > 100) ) + { + fprintf(stderr, "%s: base-oribts must be between 0 and 100\n", + progname); + exit (1); + } + + if ( st->f->percent_orbits == 100 ) + st->f->base_on_center = True; + + XGetWindowAttributes(st->dpy, st->window, &st->xgwa); + + build_colors(st->f, st->dpy, &st->xgwa); + + st->gcv.foreground = get_pixel_resource(st->dpy, st->xgwa.colormap, + "foreground", "Foreground"); + st->gcv.background = get_pixel_resource(st->dpy, st->xgwa.colormap, + "background", "Background"); + + st->fgc = XCreateGC(st->dpy, st->window, GCForeground, &st->gcv); + + st->f->height = st->xgwa.height; + st->f->width = st->xgwa.width; + st->f->visdepth = st->xgwa.depth; + st->f->fgcolor = st->gcv.foreground; + st->f->bgcolor = st->gcv.background; + + /* Initialize stuff */ + build_field(st->dpy, st->window, st->xgwa, st->fgc, st->f); + +#ifdef TIME_ME + gettimeofday(&tm1, NULL); + frames = 0; +#endif + + return st; +} + + +static unsigned long +interaggregate_draw (Display *dpy, Window window, void *closure) +{ + struct state *st = (struct state *) closure; + + if ((st->f->cycles % 10) == 0) + { + /* Restart if the window size changes */ + XGetWindowAttributes(st->dpy, st->window, &st->xgwa); + + if (st->f->height != st->xgwa.height || st->f->width != st->xgwa.width) + { + st->f->height = st->xgwa.height; + st->f->width = st->xgwa.width; + st->f->visdepth = st->xgwa.depth; + + build_field(st->dpy, st->window, st->xgwa, st->fgc, st->f); + XSetForeground(st->dpy, st->fgc, st->gcv.background); + XFillRectangle(st->dpy, st->window, st->fgc, 0, 0, st->xgwa.width, st->xgwa.height); + XSetForeground(st->dpy, st->fgc, st->gcv.foreground); + } + } + + moveCircles(st->f); + drawIntersections(st->dpy, st->window, st->fgc, st->f); + + st->f->cycles++; + + + if (st->f->cycles >= st->max_cycles && st->max_cycles != 0) + { + build_field(st->dpy, st->window, st->xgwa, st->fgc, st->f); + XSetForeground(st->dpy, st->fgc, st->gcv.background); + XFillRectangle(st->dpy, st->window, st->fgc, 0, 0, st->xgwa.width, st->xgwa.height); + XSetForeground(st->dpy, st->fgc, st->gcv.foreground); + } + +#ifdef TIME_ME + frames++; + gettimeofday(&tm2, NULL); + + tdiff = (tm2.tv_sec - tm1.tv_sec) + + (tm2.tv_usec - tm1.tv_usec) * 0.00001; + + if ( tdiff > 1 ) + { + fprintf(stderr, "fps: %d %f %f\n", + frames, tdiff, frames / tdiff ); + + fprintf(stderr, "intersections: %d %d %f\n", + f->intersection_count, f->possible_intersections, + ((double)f->intersection_count) / + f->possible_intersections); + + fprintf(stderr, "fpi: %f\n", + ((double)frames) / f->intersection_count ); + + frames = 0; + tm1.tv_sec = tm2.tv_sec; + tm1.tv_usec = tm2.tv_usec; + + f->intersection_count = f->possible_intersections = 0; + } +#endif + + return st->growth_delay; +} + + +static void +interaggregate_reshape (Display *dpy, Window window, void *closure, + unsigned int w, unsigned int h) +{ +} + +static Bool +interaggregate_event (Display *dpy, Window window, void *closure, XEvent *event) +{ + return False; +} + +static void +interaggregate_free (Display *dpy, Window window, void *closure) +{ + struct state *st = (struct state *) closure; + free (st); +} + + +XSCREENSAVER_MODULE ("Interaggregate", interaggregate) diff --git a/hacks/interaggregate.man b/hacks/interaggregate.man new file mode 100644 index 00000000..3d1eee3e --- /dev/null +++ b/hacks/interaggregate.man @@ -0,0 +1,72 @@ +.TH Interaggregate 1 "08-Oct-04" "X Version 11" +.SH NAME +interaggregate - Visualize the momentary and aggregate intersections +between slowly moving circles. +.SH SYNOPSIS +.B interaggregate +[\-display \fIhost:display.screen\fP] +[\-foreground \fIcolor\fP] +[\-background \fIcolor\fP] +[\-num\-circles \fIdisc count\fP] +[\-growth\-delay \fIdelayms\fP] +[\-max\-cycles \fImaxr\fP] +[\-percent\-orbits \fIpercent\fP] +[\-base\-orbits \fIpercent\fP] +[\-base\-on\-center] +[\-draw\-centers] +[\-fps] +.SH DESCRIPTION +The Intersection Aggregate is a fun visualization defining the relationships +between objects with Casey Reas, William Ngan, and Robert Hodgin. Commissioned +for display at the Whitney Museum of American Art. + +A surface filled with 100 medium to small sized circles. Each circle has a +different size and direction, but moves at the same slow rate. Display: + + A. The instantaneous intersections of the circles. + B. The aggregate intersections of the circles. + +Ported to XScreensaver from the art project "InterAggregate" at +http://www.complexification.net by J.Tarbell +.SH OPTIONS +.I interaggregate +accepts the following options: +.TP 8 +.B \-num\-circles \fIdisc count\fP (Default: \fI100\fP) +Number of slowly moving and growing discs to use. The more discs, +the more CPU power. +.TP 8 +.B \-growth\-delay \fIdelayms\fP (Default: \fI18000\fP) +Delay in ms between drawing cycles. More delay, slower (but smoother +and less CPU intensive.) +art. +.TP 8 +.B \-fps +Display the current frame rate and CPU load. +.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. +.TP 8 +.SH BUGS +.PP +.TP 8 +Setting the background to anything besides black confuses the intensity +algorithm and will look terrible. +.SH SEE ALSO +.BR X (1), +.BR xscreensaver (1) +.SH COPYRIGHT +Copyright \(co 2003 by J. Tarbell +(complex@complexification.net, http://www.complexification.net). + +Ported to XScreensaver 2005 by David Agraz. +.SH AUTHOR +J. Tarbell , Jun-03 + +David Agraz , Apr-05. diff --git a/hacks/interference.c b/hacks/interference.c new file mode 100644 index 00000000..60607981 --- /dev/null +++ b/hacks/interference.c @@ -0,0 +1,476 @@ +/* interference.c --- colored fields via decaying sinusoidal waves. + * An entry for the RHAD Labs Screensaver Contest. + * + * Author: Hannu Mallat + * + * Copyright (C) 1998 Hannu Mallat. + * + * 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. + * + * decaying sinusoidal waves, which extend spherically from their + * respective origins, move around the plane. a sort of interference + * between them is calculated and the resulting twodimensional wave + * height map is plotted in a grid, using softly changing colours. + * + * not physically (or in any sense) accurate, but fun to look at for + * a while. you may tune the speed/resolution/interestingness tradeoff + * with X resources, see below. + * + * Created : Wed Apr 22 09:30:30 1998, hmallat + * Last modified: Wed Apr 22 09:30:30 1998, hmallat + * Last modified: Sun Aug 31 23:40:14 2003, + * david slimp + * added -hue option to specify base color hue + * + * TODO: + * + * This really needs to be sped up. + * + * I've tried making it use XPutPixel/XPutImage instead of XFillRectangle, + * but that doesn't seem to help (it's the same speed at gridsize=1, and + * it actually makes it slower at larger sizes.) + * + * I played around with shared memory, but clearly I still don't know how + * to use the XSHM extension properly, because it doesn't work yet. + * + * Hannu had put in code to use the double-buffering extension, but that + * code didn't work for me on Irix. I don't think it would help anyway, + * since it's not the swapping of frames that is the bottleneck (or a source + * of visible flicker.) + * + * -- jwz, 4-Jun-98 + */ + +#include + +#include "screenhack.h" + +/* I thought it would be faster this way, but it turns out not to be... -jwz */ +#undef USE_XIMAGE + +#ifndef USE_XIMAGE +# undef HAVE_XSHM_EXTENSION /* only applicable when using XImages */ +#endif /* USE_XIMAGE */ + + +#ifdef HAVE_DOUBLE_BUFFER_EXTENSION +# include "xdbe.h" +#endif /* HAVE_DOUBLE_BUFFER_EXTENSION */ + +#ifdef HAVE_XSHM_EXTENSION +# include "xshm.h" +#endif /* HAVE_XSHM_EXTENSION */ + +static const char *interference_defaults [] = { + ".background: black", + ".foreground: white", + "*count: 3", /* number of waves */ + "*gridsize: 4", /* pixel size, smaller values for better resolution */ + "*ncolors: 128", /* number of colours used */ + "*hue: 0", /* hue to use for base color (0-360) */ + "*speed: 30", /* speed of wave origins moving around */ + "*delay: 30000", /* or something */ + "*color-shift: 60", /* h in hsv space, smaller values for smaller + * color gradients */ + "*radius: 800", /* wave extent */ + "*gray: false", /* color or grayscale */ + "*mono: false", /* monochrome, not very much fun */ + + "*doubleBuffer: True", +#ifdef HAVE_DOUBLE_BUFFER_EXTENSION + "*useDBE: True", /* use double buffering extension */ +#endif /* HAVE_DOUBLE_BUFFER_EXTENSION */ + +#ifdef HAVE_XSHM_EXTENSION + "*useSHM: True", /* use shared memory extension */ +#endif /* HAVE_XSHM_EXTENSION */ + 0 +}; + +static XrmOptionDescRec interference_options [] = { + { "-count", ".count", XrmoptionSepArg, 0 }, + { "-ncolors", ".ncolors", XrmoptionSepArg, 0 }, + { "-gridsize", ".gridsize", XrmoptionSepArg, 0 }, + { "-hue", ".hue", XrmoptionSepArg, 0 }, + { "-speed", ".speed", XrmoptionSepArg, 0 }, + { "-delay", ".delay", XrmoptionSepArg, 0 }, + { "-color-shift", ".color-shift", XrmoptionSepArg, 0 }, + { "-radius", ".radius", XrmoptionSepArg, 0 }, + { "-gray", ".gray", XrmoptionNoArg, "True" }, + { "-mono", ".mono", XrmoptionNoArg, "True" }, + { "-db", ".doubleBuffer", XrmoptionNoArg, "True" }, + { "-no-db", ".doubleBuffer", XrmoptionNoArg, "False" }, +#ifdef HAVE_XSHM_EXTENSION + { "-shm", ".useSHM", XrmoptionNoArg, "True" }, + { "-no-shm", ".useSHM", XrmoptionNoArg, "False" }, +#endif /* HAVE_XSHM_EXTENSION */ + { 0, 0, 0, 0 } +}; + +struct inter_source { + int x; + int y; + double x_theta; + double y_theta; +}; + +struct inter_context { + /* + * Display-related entries + */ + Display* dpy; + Window win; + +#ifdef HAVE_DOUBLE_BUFFER_EXTENSION + XdbeBackBuffer back_buf; +#endif /* HAVE_DOUBLE_BUFFER_EXTENSION */ + Pixmap pix_buf; + + GC copy_gc; +#ifdef USE_XIMAGE + XImage *ximage; +#endif /* USE_XIMAGE */ + +#ifdef HAVE_XSHM_EXTENSION + Bool use_shm; + XShmSegmentInfo shm_info; +#endif /* HAVE_XSHM_EXTENSION */ + + /* + * Resources + */ + int count; + int grid_size; + int colors; + float hue; + int speed; + int delay; + int shift; + int radius; + + /* + * Drawing-related entries + */ + int w; + int h; + Colormap cmap; + XColor* pal; + GC* gcs; + + /* + * lookup tables + */ + int* wave_height; + + /* + * Interference sources + */ + struct inter_source* source; +}; + +#ifdef HAVE_DOUBLE_BUFFER_EXTENSION +# define TARGET(c) ((c)->back_buf ? (c)->back_buf : \ + (c)->pix_buf ? (c)->pix_buf : (c)->win) +#else /* HAVE_DOUBLE_BUFFER_EXTENSION */ +# define TARGET(c) ((c)->pix_buf ? (c)->pix_buf : (c)->win) +#endif /* !HAVE_DOUBLE_BUFFER_EXTENSION */ + +static void inter_init(Display* dpy, Window win, struct inter_context* c) +{ + XWindowAttributes xgwa; + double H[3], S[3], V[3]; + int i; + int mono; + int gray; + XGCValues val; + unsigned long valmask = 0; + Bool dbuf = get_boolean_resource (dpy, "doubleBuffer", "Boolean"); + +# ifdef HAVE_COCOA /* Don't second-guess Quartz's double-buffering */ + dbuf = False; +# endif + + memset (c, 0, sizeof(*c)); + + c->dpy = dpy; + c->win = win; + + c->delay = get_integer_resource(dpy, "delay", "Integer"); + + + XGetWindowAttributes(c->dpy, c->win, &xgwa); + c->w = xgwa.width; + c->h = xgwa.height; + c->cmap = xgwa.colormap; + +#ifdef HAVE_XSHM_EXTENSION + c->use_shm = get_boolean_resource(dpy, "useSHM", "Boolean"); +#endif /* HAVE_XSHM_EXTENSION */ + + if (dbuf) + { +#ifdef HAVE_DOUBLE_BUFFER_EXTENSION + c->back_buf = xdbe_get_backbuffer (c->dpy, c->win, XdbeUndefined); +#endif /* HAVE_DOUBLE_BUFFER_EXTENSION */ + +#ifdef HAVE_DOUBLE_BUFFER_EXTENSION + if (!c->back_buf) +#endif /* HAVE_DOUBLE_BUFFER_EXTENSION */ + c->pix_buf = XCreatePixmap (dpy, win, xgwa.width, xgwa.height, + xgwa.depth); + } + + val.function = GXcopy; + c->copy_gc = XCreateGC(c->dpy, TARGET(c), GCFunction, &val); + + c->count = get_integer_resource(dpy, "count", "Integer"); + if(c->count < 1) + c->count = 1; + c->grid_size = get_integer_resource(dpy, "gridsize", "Integer"); + if(c->grid_size < 1) + c->grid_size = 1; + mono = get_boolean_resource(dpy, "mono", "Boolean"); + if(!mono) { + c->colors = get_integer_resource(dpy, "ncolors", "Integer"); + if(c->colors < 2) + c->colors = 2; + } + c->hue = get_integer_resource(dpy, "hue", "Float"); + while (c->hue < 0 || c->hue >= 360) + c->hue = frand(360.0); + c->speed = get_integer_resource(dpy, "speed", "Integer"); + c->shift = get_float_resource(dpy, "color-shift", "Float"); + while(c->shift >= 360.0) + c->shift -= 360.0; + while(c->shift <= -360.0) + c->shift += 360.0; + c->radius = get_integer_resource(dpy, "radius", "Integer");; + if(c->radius < 1) + c->radius = 1; + +#ifdef USE_XIMAGE + + c->ximage = 0; + +# ifdef HAVE_XSHM_EXTENSION + if (c->use_shm) + { + c->ximage = create_xshm_image(dpy, xgwa.visual, xgwa.depth, + ZPixmap, 0, &c->shm_info, + xgwa.width, c->grid_size); + if (!c->ximage) + c->use_shm = False; + } +# endif /* HAVE_XSHM_EXTENSION */ + + if (!c->ximage) + { + c->ximage = + XCreateImage (dpy, xgwa.visual, + xgwa.depth, ZPixmap, 0, 0, /* depth, fmt, offset, data */ + xgwa.width, c->grid_size, /* width, height */ + 8, 0); /* pad, bpl */ + c->ximage->data = (unsigned char *) + calloc(c->ximage->height, c->ximage->bytes_per_line); + } +#endif /* USE_XIMAGE */ + + if(!mono) { + c->pal = calloc(c->colors, sizeof(XColor)); + + gray = get_boolean_resource(dpy, "gray", "Boolean"); + if(!gray) { + H[0] = c->hue; + H[1] = H[0] + c->shift < 360.0 ? H[0]+c->shift : H[0] + c->shift-360.0; + H[2] = H[1] + c->shift < 360.0 ? H[1]+c->shift : H[1] + c->shift-360.0; + S[0] = S[1] = S[2] = 1.0; + V[0] = V[1] = V[2] = 1.0; + } else { + H[0] = H[1] = H[2] = 0.0; + S[0] = S[1] = S[2] = 0.0; + V[0] = 1.0; V[1] = 0.5; V[2] = 0.0; + } + + make_color_loop(c->dpy, c->cmap, + H[0], S[0], V[0], + H[1], S[1], V[1], + H[2], S[2], V[2], + c->pal, &(c->colors), + True, False); + if(c->colors < 2) { /* color allocation failure */ + mono = 1; + free(c->pal); + } + } + + if(mono) { /* DON'T else this with the previous if! */ + c->colors = 2; + c->pal = calloc(2, sizeof(XColor)); + c->pal[0].pixel = BlackPixel(c->dpy, DefaultScreen(c->dpy)); + c->pal[1].pixel = WhitePixel(c->dpy, DefaultScreen(c->dpy)); + } + + valmask = GCForeground; + c->gcs = calloc(c->colors, sizeof(GC)); + for(i = 0; i < c->colors; i++) { + val.foreground = c->pal[i].pixel; + c->gcs[i] = XCreateGC(c->dpy, TARGET(c), valmask, &val); + } + + c->wave_height = calloc(c->radius, sizeof(int)); + for(i = 0; i < c->radius; i++) { + float max = + ((float)c->colors) * + ((float)c->radius - (float)i) / + ((float)c->radius); + c->wave_height[i] = + (int) + ((max + max*cos((double)i/50.0)) / 2.0); + } + + c->source = calloc(c->count, sizeof(struct inter_source)); + for(i = 0; i < c->count; i++) { + c->source[i].x_theta = frand(2.0)*3.14159; + c->source[i].y_theta = frand(2.0)*3.14159; + } + +} + +#define source_x(c, i) \ + (c->w/2 + ((int)(cos(c->source[i].x_theta)*((float)c->w/2.0)))) +#define source_y(c, i) \ + (c->h/2 + ((int)(cos(c->source[i].y_theta)*((float)c->h/2.0)))) + +/* + * this is rather suboptimal. the sqrt() doesn't seem to be a big + * performance hit, but all those separate XFillRectangle()'s are. + * hell, it's just a quick hack anyway -- if someone wishes to tune + * it, go ahead! + */ + +static void do_inter(struct inter_context* c) +{ + int i, j, k; + int result; + int dist; + int g; + + int dx, dy; + + for(i = 0; i < c->count; i++) { + c->source[i].x_theta += (c->speed/1000.0); + if(c->source[i].x_theta > 2.0*3.14159) + c->source[i].x_theta -= 2.0*3.14159; + c->source[i].y_theta += (c->speed/1000.0); + if(c->source[i].y_theta > 2.0*3.14159) + c->source[i].y_theta -= 2.0*3.14159; + c->source[i].x = source_x(c, i); + c->source[i].y = source_y(c, i); + } + + g = c->grid_size; + + for(j = 0; j < c->h/g; j++) { + for(i = 0; i < c->w/g; i++) { + result = 0; + for(k = 0; k < c->count; k++) { + dx = i*g + g/2 - c->source[k].x; + dy = j*g + g/2 - c->source[k].y; + dist = sqrt(dx*dx + dy*dy); /* what's the performance penalty here? */ + result += (dist >= c->radius ? 0 : c->wave_height[dist]); + } + result %= c->colors; + +#ifdef USE_XIMAGE + /* Fill in these `gridsize' horizontal bits in the scanline */ + for(k = 0; k < g; k++) + XPutPixel(c->ximage, (g*i)+k, 0, c->pal[result].pixel); + +#else /* !USE_XIMAGE */ + XFillRectangle(c->dpy, TARGET(c), c->gcs[result], g*i, g*j, g, g); +#endif /* !USE_XIMAGE */ + } + +#ifdef USE_XIMAGE + + /* Only the first scanline of the image has been filled in; clone that + scanline to the rest of the `gridsize' lines in the ximage */ + for(k = 0; k < (g-1); k++) + memcpy(c->ximage->data + (c->ximage->bytes_per_line * (k + 1)), + c->ximage->data + (c->ximage->bytes_per_line * k), + c->ximage->bytes_per_line); + + /* Move the bits for this horizontal stripe to the server. */ +# ifdef HAVE_XSHM_EXTENSION + if (c->use_shm) + XShmPutImage(c->dpy, TARGET(c), c->copy_gc, c->ximage, + 0, 0, 0, g*j, c->ximage->width, c->ximage->height, + False); + else +# endif /* HAVE_XSHM_EXTENSION */ + XPutImage(c->dpy, TARGET(c), c->copy_gc, c->ximage, + 0, 0, 0, g*j, c->ximage->width, c->ximage->height); + +#endif /* USE_XIMAGE */ + } + +#ifdef HAVE_DOUBLE_BUFFER_EXTENSION + if (c->back_buf) + { + XdbeSwapInfo info[1]; + info[0].swap_window = c->win; + info[0].swap_action = XdbeUndefined; + XdbeSwapBuffers(c->dpy, info, 1); + } + else +#endif /* HAVE_DOUBLE_BUFFER_EXTENSION */ + if (c->pix_buf) + { + XCopyArea (c->dpy, c->pix_buf, c->win, c->copy_gc, + 0, 0, c->w, c->h, 0, 0); + } +} + +static void * +interference_init (Display *dpy, Window win) +{ + struct inter_context *c = (struct inter_context *) calloc (1, sizeof(*c)); + inter_init(dpy, win, c); + return c; +} + +static unsigned long +interference_draw (Display *dpy, Window win, void *closure) +{ + struct inter_context *c = (struct inter_context *) closure; + do_inter(c); + return c->delay; +} + +static void +interference_reshape (Display *dpy, Window window, void *closure, + unsigned int w, unsigned int h) +{ + struct inter_context *c = (struct inter_context *) closure; + c->w = w; + c->h = h; +} + +static Bool +interference_event (Display *dpy, Window window, void *closure, XEvent *event) +{ + return False; +} + +static void +interference_free (Display *dpy, Window window, void *closure) +{ +} + +XSCREENSAVER_MODULE ("Interference", interference) diff --git a/hacks/interference.man b/hacks/interference.man new file mode 100644 index 00000000..f95fb2c3 --- /dev/null +++ b/hacks/interference.man @@ -0,0 +1,86 @@ +.TH XScreenSaver 1 "" "X Version 11" +.SH NAME +interference - decaying sinusoidal waves +.SH SYNOPSIS +.B interference +[\-display \fIhost:display.screen\fP] +[\-visual \fIvisual\fP] +[\-window] +[\-root] +[\-count \fInumber\fP] +[\-gridsize \fInumber\fP] +[\-delay \fInumber\fP] +[\-speed \fInumber\fP] +[\-radius \fInumber\fP] +[\-ncolors \fInumber\fP] +[\-color-shift \fInumber\fP] +[\-hue \fInumber\fP] +[\-no-db] +[\-fps] +.SH DESCRIPTION +Another color-field hack, this one works by computing decaying sinusoidal +waves, and allowing them to interfere with each other as their origins +move. +.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 \-count \fInumber\fP +Number of Waves. 0 - 20. Default: 3. +.TP 8 +.B \-gridsize \fInumber\fP +Magnification. 1 - 20. Default: 4. +.TP 8 +.B \-delay \fInumber\fP +Per-frame delay, in microseconds. Default: 30000 (0.03 seconds.). +.TP 8 +.B \-speed \fInumber\fP +Wave Speed. 1 - 100. Default: 30. +.TP 8 +.B \-radius \fInumber\fP +Wave Size. 50 - 1500. Default: 800. +.TP 8 +.B \-ncolors \fInumber\fP +Number of Colors. Default: 128. +.TP 8 +.B \-color-shift \fInumber\fP +Color Contrast. 0 - 100. Default: 60. +.TP 8 +.B \-hue \fInumber\fP +Hue of the base color (0-360, as in HSV space.) Default 0, meaning random. +.TP 8 +.B \-db | \-no-db +Whether to double buffer. +.TP 8 +.B \-fps +Display the current frame rate and CPU load. +.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 2002 by Hannu Mallat. 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 +Hannu Mallat. diff --git a/hacks/intermomentary.c b/hacks/intermomentary.c new file mode 100644 index 00000000..ba5268ab --- /dev/null +++ b/hacks/intermomentary.c @@ -0,0 +1,572 @@ +/* + * InterMomentary (dragorn@kismetwireless.net) + * Directly ported code from complexification.net InterMomentary art + * http://www.complexification.net/gallery/machines/interMomentary/applet_l/interMomentary_l.pde + * + * Intersecting Circles, Instantaneous + * J. Tarbell + complexification.net + * Albuquerque, New Mexico + * May, 2004 + * + * a REAS collaboration for the + groupc.net + * Whitney Museum of American Art ARTPORT + artport.whitney.org + * Robert Hodgin + flight404.com + * William Ngan + metaphorical.net + * + * + * 1.0 Oct 10 2004 dragorn Completed first port + * + * + * Based, of course, on other hacks in: + * + * xscreensaver, Copyright (c) 1997, 1998, 2002 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. + */ + +#include +#include "screenhack.h" +#include "hsv.h" + +/* this program goes faster if some functions are inline. The following is + * borrowed from ifs.c */ +#if !defined( __GNUC__ ) && !defined(__cplusplus) && !defined(c_plusplus) +#undef inline +#define inline /* */ +#endif + +/* Pixel rider */ +typedef struct { + float t; + float vt; + float mycharge; +} PxRider; + +/* disc of light */ +typedef struct { + /* index identifier */ + int id; + /* position */ + float x, y; + /* radius */ + float r, dr; + /* velocity */ + float vx, vy; + + /* pixel riders */ + int numr; + PxRider *pxRiders; +} Disc; + +struct field { + unsigned int height; + unsigned int width; + + int initial_discs; + Disc *discs; + + unsigned int num; + + unsigned int maxrider; + unsigned int maxradius; + + /* color parms */ + unsigned long fgcolor; + unsigned long bgcolor; + int visdepth; + + unsigned int cycles; + + /* Offscreen image we draw to */ + Pixmap off_map; + unsigned char *off_alpha; +}; + + +struct state { + Display *dpy; + Window window; + + struct field *f; + GC fgc, copygc; + XWindowAttributes xgwa; + int draw_delay; + + XColor *colors; + int ncolors; +}; + + +static void *xrealloc(void *p, size_t size) +{ + void *ret; + if ((ret = realloc(p, size)) == NULL) { + fprintf(stderr, "%s: out of memory\n", progname); + exit(1); + } + return ret; +} + +static struct field *init_field(void) +{ + struct field *f = xrealloc(NULL, sizeof(struct field)); + f->height = 0; + f->width = 0; + f->initial_discs = 0; + f->discs = NULL; + f->num = 0; + f->maxrider = 0; + f->maxradius = 0; + f->cycles = 0; + f->fgcolor = 0; + f->bgcolor = 0; + f->off_alpha = NULL; + f->visdepth = 0; + return f; +} + +/* Quick-ref to pixels in the alpha map */ +#define ref_pixel(f, x, y) ((f)->off_alpha[(y) * (f)->width + (x)]) + +static inline void make_disc(struct field *f, float x, float y, float vx, float vy, float r) +{ + /* Synthesis of Disc::Disc and PxRider::PxRider */ + Disc *nd; + int ix; + + /* allocate a new disc */ + f->discs = (Disc *) xrealloc(f->discs, sizeof(Disc) * (f->num + 1)); + + nd = &(f->discs[f->num]); + + nd->id = f->num++; + nd->x = x; + nd->y = y; + nd->vx = vx; + nd->vy = vy; + nd->dr = r; + nd->r = frand(r) / 3; + + nd->numr = (frand(r) / 2.62); + if (nd->numr > f->maxrider) + nd->numr = f->maxrider; + + nd->pxRiders = NULL; + nd->pxRiders = (PxRider *) xrealloc(nd->pxRiders, sizeof(PxRider) * (f->maxrider)); + for (ix = 0; ix < f->maxrider; ix++) { + nd->pxRiders[ix].vt = 0.0; + nd->pxRiders[ix].t = frand(M_PI * 2); + nd->pxRiders[ix].mycharge = 0; + } +} + + +/* alpha blended point drawing */ +static inline unsigned long +trans_point(struct state *st, + int x1, int y1, unsigned char myc, float a, struct field *f) +{ + if ((x1 >= 0) && (x1 < f->width) && (y1 >= 0) && (y1 < f->height)) { + if (a >= 1.0) { + ref_pixel(f, x1, y1) = myc; + } else { + unsigned long c = ref_pixel(f, x1, y1); + c = c + (myc - c) * a; + ref_pixel(f, x1, y1) = c; + return c; + } + } + + return 0; +} + +static inline unsigned long +get_pixel (struct state *st, unsigned char v) +{ + return st->colors [v * (st->ncolors-1) / 255].pixel; +} + + +static inline void move_disc(struct field *f, int dnum) +{ + Disc *d = &(f->discs[dnum]); + + /* add velocity to position */ + d->x += d->vx; + d->y += d->vy; + + /* bound check */ + if (d->x + d->r < 0) + d->x += f->width + d->r + d->r; + if (d->x - d->r > f->width) + d->x -= f->width + d->r + d->r; + if (d->y + d->r < 0) + d->y += f->height + d->r + d->r; + if (d->y - d->r > f->height) + d->y -= f->height + d->r + d->r; + + /* increase to destination radius */ + if (d->r < d->dr) + d->r += 0.1; +} + +static inline void +draw_glowpoint(struct state *st, Drawable drawable, + GC fgc, struct field *f, float px, float py) +{ + int i, j; + float a; + unsigned long c; + + for (i = -2; i < 3; i++) { + for (j = -2; j < 3; j++) { + a = 0.8 - i * i * 0.1 - j * j * 0.1; + + c = trans_point(st, px+i, py+j, 255, a, f); + XSetForeground(st->dpy, fgc, get_pixel (st, c)); + XDrawPoint(st->dpy, drawable, fgc, px + i, py + j); + XSetForeground(st->dpy, fgc, f->fgcolor); + } + } +} + +static inline void +moverender_rider(struct state *st, Drawable drawable, + GC fgc, struct field *f, PxRider *rid, + float x, float y, float r) +{ + float px, py; + unsigned long int c; + double cv; + + /* add velocity to theta */ + rid->t = fmod((rid->t + rid->vt + M_PI), (2 * M_PI)) - M_PI; + + rid->vt += frand(0.002) - 0.001; + + /* apply friction brakes */ + if (abs(rid->vt) > 0.02) + rid->vt *= 0.9; + + /* draw */ + px = x + r * cos(rid->t); + py = y + r * sin(rid->t); + + if ((px < 0) || (px >= f->width) || (py < 0) || (py >= f->height)) + return; + + /* max brightness seems to be 0.003845 */ + + c = ref_pixel(f, (int) px, (int) py); + cv = c / 255.0; + + /* guestimated - 40 is 18% of 255, so scale this to 0.0 to 0.003845 */ + if (cv > 0.0006921) { + draw_glowpoint(st, drawable, fgc, f, px, py); + + rid->mycharge = 0.003845; + } else { + rid->mycharge *= 0.98; + + c = 255 * rid->mycharge; + + trans_point(st, px, py, c, 0.5, f); + + XSetForeground(st->dpy, fgc, get_pixel(st, c)); + XDrawPoint(st->dpy, drawable, fgc, px, py); + XSetForeground(st->dpy, fgc, f->fgcolor); + } +} + +static inline void +render_disc(struct state *st, Drawable drawable, GC fgc, struct field *f, int dnum) +{ + Disc *di = &(f->discs[dnum]); + int n, m; + float dx, dy, d; + float a, p2x, p2y, h, p3ax, p3ay, p3bx, p3by; + unsigned long c; + + /* Find intersecting points with all ascending discs */ + for (n = di->id + 1; n < f->num; n++) { + dx = f->discs[n].x - di->x; + dy = f->discs[n].y - di->y; + d = sqrt(dx * dx + dy * dy); + + /* intersection test */ + if (d < (f->discs[n].r + di->r)) { + /* complete containment test */ + if (d > abs(f->discs[n].r - di->r)) { + /* find solutions */ + a = (di->r * di->r - f->discs[n].r * f->discs[n].r + d * d) / (2 * d); + p2x = di->x + a * (f->discs[n].x - di->x) / d; + p2y = di->y + a * (f->discs[n].y - di->y) / d; + + h = sqrt(di->r * di->r - a * a); + + p3ax = p2x + h * (f->discs[n].y - di->y) / d; + p3ay = p2y - h * (f->discs[n].x - di->x) / d; + + p3bx = p2x - h * (f->discs[n].y - di->y) / d; + p3by = p2y + h * (f->discs[n].x - di->x) / d; + + /* bounds check */ + if ((p3ax < 0) || (p3ax >= f->width) || (p3ay < 0) || (p3ay >= f->height) || + (p3bx < 0) || (p3bx >= f->width) || (p3by < 0) || (p3by >= f->height)) + continue; + + /* p3a and p3b might be identical, ignore this case for now */ + /* XPutPixel(f->off_map, p3ax, p3ay, f->fgcolor); */ + c = trans_point(st, p3ax, p3ay, 255, 0.75, f); + XSetForeground(st->dpy, fgc, get_pixel (st, c)); + XDrawPoint(st->dpy, drawable, fgc, p3ax, p3ay); + + /* XPutPixel(f->off_map, p3bx, p3by, f->fgcolor); */ + c = trans_point(st, p3bx, p3by, 255, 0.75, f); + XSetForeground(st->dpy, fgc, get_pixel (st, c)); + XDrawPoint(st->dpy, drawable, fgc, p3bx, p3by); + XSetForeground(st->dpy, fgc, f->fgcolor); + } + } + + } + + /* Render all the pixel riders */ + for (m = 0; m < di->numr; m++) { + moverender_rider(st, drawable, fgc, f, &(di->pxRiders[m]), + di->x, di->y, di->r); + } +} + +static void build_img(Display *dpy, Window window, struct field *f) +{ + if (f->off_alpha) { + free(f->off_alpha); + f->off_alpha = NULL; + + /* Assume theres also an off pixmap */ + if (f->off_map != window) + XFreePixmap(dpy, f->off_map); + } + + f->off_alpha = (unsigned char *) + xrealloc(f->off_alpha, sizeof(unsigned char) * f->width * f->height); + + memset(f->off_alpha, 0, sizeof(unsigned char) * f->width * f->height); + +# ifdef HAVE_COCOA /* Don't second-guess Quartz's double-buffering */ + f->off_map = window; +# else + f->off_map = XCreatePixmap(dpy, window, f->width, f->height, f->visdepth); +# endif + +} + +static inline void blank_img(Display *dpy, Window window, XWindowAttributes xgwa, GC fgc, struct field *f) +{ + memset(f->off_alpha, 0, sizeof(unsigned char) * f->width * f->height); + + XSetForeground(dpy, fgc, f->bgcolor); + XFillRectangle(dpy, window, fgc, 0, 0, xgwa.width, xgwa.height); + XSetForeground(dpy, fgc, f->fgcolor); +} + + +static void * +intermomentary_init (Display *dpy, Window window) +{ + struct state *st = (struct state *) calloc (1, sizeof(*st)); + +#ifdef TIME_ME + time_t start_time = time(NULL); +#endif + + int tempx; + XGCValues gcv; + + st->dpy = dpy; + st->window = window; + + XGetWindowAttributes(dpy, window, &st->xgwa); + + st->ncolors = get_integer_resource (st->dpy, "colors", "Colors"); + st->ncolors++; + st->colors = (XColor *) malloc(sizeof(*st->colors) * (st->ncolors+1)); + + gcv.foreground = get_pixel_resource(dpy, st->xgwa.colormap, + "foreground", "Foreground"); + gcv.background = get_pixel_resource(dpy, st->xgwa.colormap, + "background", "Background"); + + { + XColor fgc, bgc; + int fgh, bgh; + double fgs, fgv, bgs, bgv; + fgc.pixel = gcv.foreground; + bgc.pixel = gcv.background; + XQueryColor (st->dpy, st->xgwa.colormap, &fgc); + XQueryColor (st->dpy, st->xgwa.colormap, &bgc); + rgb_to_hsv (fgc.red, fgc.green, fgc.blue, &fgh, &fgs, &fgv); + rgb_to_hsv (bgc.red, bgc.green, bgc.blue, &bgh, &bgs, &bgv); +#if 0 + bgh = fgh; + bgs = fgs; + bgv = fgv / 10.0; +#endif + make_color_ramp (st->dpy, st->xgwa.colormap, + bgh, bgs, bgv, + fgh, fgs, fgv, + st->colors, &st->ncolors, + False, /* closed */ + True, False); + } + + st->f = init_field(); + + st->f->height = st->xgwa.height; + st->f->width = st->xgwa.width; + st->f->visdepth = st->xgwa.depth; + + st->draw_delay = (get_integer_resource(dpy, "drawDelay", "Integer")); + st->f->maxrider = (get_integer_resource(dpy, "maxRiders", "Integer")); + st->f->maxradius = (get_integer_resource(dpy, "maxRadius", "Integer")); + st->f->initial_discs = (get_integer_resource(dpy, "numDiscs", "Integer")); + + if (st->f->initial_discs <= 10) { + fprintf(stderr, "%s: Initial discs must be greater than 10\n", progname); + exit (1); + } + + if (st->f->maxradius <= 30) { + fprintf(stderr, "%s: Max radius must be greater than 30\n", progname); + exit (1); + } + + if (st->f->maxrider <= 10) { + fprintf(stderr, "%s: Max riders must be greater than 10\n", progname); + exit (1); + } + + st->fgc = XCreateGC(dpy, window, GCForeground, &gcv); + st->copygc = XCreateGC(dpy, window, GCForeground, &gcv); + + st->f->fgcolor = gcv.foreground; + st->f->bgcolor = gcv.background; + + /* Initialize stuff */ + build_img(dpy, window, st->f); + + for (tempx = 0; tempx < st->f->initial_discs; tempx++) { + float fx, fy, x, y, r; + int bt; + + /* Arrange in anti-collapsing circle */ + fx = 0.4 * st->f->width * cos((2 * M_PI) * tempx / st->f->initial_discs); + fy = 0.4 * st->f->height * sin((2 * M_PI) * tempx / st->f->initial_discs); + x = frand(st->f->width / 2) + fx; + y = frand(st->f->height / 2) + fy; + r = 5 + frand(st->f->maxradius); + bt = 1; + + if ((random() % 100) < 50) + bt = -1; + + make_disc(st->f, x, y, bt * fx / 1000.0, bt * fy / 1000.0, r); + + } + + return st; +} + +static unsigned long +intermomentary_draw (Display *dpy, Window window, void *closure) +{ + struct state *st = (struct state *) closure; + int tempx; + + if ((st->f->cycles % 10) == 0) { + /* Restart if the window size changes */ + XGetWindowAttributes(dpy, window, &st->xgwa); + + if (st->f->height != st->xgwa.height || st->f->width != st->xgwa.width) { + st->f->height = st->xgwa.height; + st->f->width = st->xgwa.width; + st->f->visdepth = st->xgwa.depth; + + build_img(dpy, window, st->f); + } + } + + blank_img(dpy, st->f->off_map, st->xgwa, st->fgc, st->f); + for (tempx = 0; tempx < st->f->num; tempx++) { + move_disc(st->f, tempx); + render_disc(st, st->f->off_map, st->fgc, st->f, tempx); + } + +#if 0 + XSetFillStyle(dpy, st->copygc, FillTiled); + XSetTile(dpy, st->copygc, st->f->off_map); + XFillRectangle(dpy, window, st->copygc, 0, 0, st->f->width, st->f->height); +#else + if (st->f->off_map != window) + XCopyArea (dpy, st->f->off_map, window, st->copygc, 0, 0, + st->f->width, st->f->height, 0, 0); + +#endif + + st->f->cycles++; + + return st->draw_delay; +} + + +static void +intermomentary_reshape (Display *dpy, Window window, void *closure, + unsigned int w, unsigned int h) +{ +} + +static Bool +intermomentary_event (Display *dpy, Window window, void *closure, XEvent *event) +{ + return False; +} + +static void +intermomentary_free (Display *dpy, Window window, void *closure) +{ + struct state *st = (struct state *) closure; + free (st); +} + + +static const char *intermomentary_defaults[] = { + ".background: black", + ".foreground: yellow", + "*drawDelay: 30000", + "*numDiscs: 85", + "*maxRiders: 40", + "*maxRadius: 100", + "*colors: 256", + 0 +}; + +static XrmOptionDescRec intermomentary_options[] = { + {"-background", ".background", XrmoptionSepArg, 0}, + {"-foreground", ".foreground", XrmoptionSepArg, 0}, + {"-draw-delay", ".drawDelay", XrmoptionSepArg, 0}, + {"-num-discs", ".numDiscs", XrmoptionSepArg, 0}, + {"-max-riders", ".maxRiders", XrmoptionSepArg, 0}, + {"-max-radius", ".maxRadius", XrmoptionSepArg, 0}, + { "-colors", ".colors", XrmoptionSepArg, 0 }, + {0, 0, 0, 0} +}; + + +XSCREENSAVER_MODULE ("Intermomentary", intermomentary) diff --git a/hacks/intermomentary.man b/hacks/intermomentary.man new file mode 100644 index 00000000..5947c596 --- /dev/null +++ b/hacks/intermomentary.man @@ -0,0 +1,82 @@ +.TH Intermomentary 1 "08-Oct-04" "X Version 11" +.SH NAME +intermomentary - Visualize the momentary and aggregate intersections +between slowly moving circles. +.SH SYNOPSIS +.B intermomentary +[\-display \fIhost:display.screen\fP] +[\-foreground \fIcolor\fP] +[\-background \fIcolor\fP] +[\-num\-discs \fIdisc count\fP] +[\-draw\-delay \fIdelayms\fP] +[\-max\-riders \fImaxr\fP] +[\-max\-radius \fImaxradius\fP] +[\-fps] +.SH DESCRIPTION +The Intersection Momentary is a fun visualization defining the relationships +between objects with Casey Reas, William Ngan, and Robert Hodgin. Commissioned +for display at the Whitney Museum of American Art. + +A surface filled with 100 medium to small sized circles. Each circle has a +different size and direction, but moves at the same slow rate. Display: + + A. The instantaneous intersections of the circles. + B. The aggregate intersections of the circles. + +The circles begin with a radius of 1 pixel and slowly increase to some +arbitrary size. Circles are drawn with small moving points along the +perimeter. The intersections are rendered as glowing orbs. Glowing +orbs are rendered only when a perimeter point moves past the +intersection point. + +Ported to XScreensaver from the art project "InterMomentary" at +http://www.complexification.net by J.Tarbell +.SH OPTIONS +.I intermomentary +accepts the following options: +.TP 8 +.B \-num\-discs \fIdisc count\fP (Default: \fI85\fP) +Number of slowly moving and growing discs to use. The more discs, +the more CPU power. +.TP 8 +.B \-draw\-delay \fIdelayms\fP (Default: \fI30000\fP) +Delay in ms between drawing cycles. More delay, slower (but smoother +and less CPU intensive.) +art. +.TP 8 +.B \-max\-riders \fImaxrider\fP (Default: \fI40\fP) +Maximum number of 'riders', single dots moving around the edge of the discs. +.TP 8 +.B \-max\-radius \fImaxradius\fP (Default: \fI100\fP) +Maximum possible radius of a disc. +.TP 8 +.TP 8 +.B \-fps +Display the current frame rate and CPU load. +.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. +.TP 8 +.SH BUGS +.PP +.TP 8 +Setting the background to anything besides black confuses the intensity +algorithm and will look terrible. +.SH SEE ALSO +.BR X (1), +.BR xscreensaver (1) +.SH COPYRIGHT +Copyright \(co 2003 by J. Tarbell +(complex@complexification.net, http://www.complexification.net). + +Ported to XScreensaver 2004 by Mike Kershaw (dragorn@kismetwireless.net) +.SH AUTHOR +J. Tarbell , Jun-03 + +Mike Kershaw , Oct-04 diff --git a/hacks/juggle.c b/hacks/juggle.c new file mode 100644 index 00000000..f0b555e6 --- /dev/null +++ b/hacks/juggle.c @@ -0,0 +1,2823 @@ +/* -*- Mode: C; tab-width: 4 -*- */ +/* juggle */ + +#if !defined( lint ) && !defined( SABER ) +static const char sccsid[] = "@(#)juggle.c 5.10 2003/09/02 xlockmore"; + +#endif + +/*- + * Copyright (c) 1996 by Tim Auckland + * + * Permission to use, copy, modify, and distribute this software and its + * documentation for any purpose and without fee is hereby granted, + * provided that the above copyright notice appear in all copies and that + * both that copyright notice and this permission notice appear in + * supporting documentation. + * + * This file is provided AS IS with no warranties of any kind. The author + * shall have no liability with respect to the infringement of copyrights, + * trade secrets or any patents by this file or any part thereof. In no + * event will the author be liable for any lost revenue or profits or + * other special, indirect and consequential damages. + * + * Revision History + * 13-Dec-2004: [TDA] Use -cycles and -count in a rational manner. + * Add -rings, -bballs. Add -describe. Finally made + * live pattern updates possible. Add refill_juggle(), + * change_juggle() and reshape_juggle(). Make + * init_juggle() non-destructive. Reorder erase/draw + * operations. Update xscreensaver xml and manpage. + * 15-Nov-2004: [TDA] Fix all memory leaks. + * 12-Nov-2004: [TDA] Add -torches and another new trail + * implementation, so that different objects can have + * different length trails. + * 11-Nov-2004: [TDA] Clap when all the balls are in the air. + * 10-Nov-2004: [TDA] Display pattern name converted to hight + * notation. + * 31-Oct-2004: [TDA] Add -clubs and new trail implementation. + * 02-Sep-2003: Non-real time to see what is happening without a + * strobe effect for slow machines. + * 01-Nov-2000: Allocation checks + * 1996: Written + */ + +/*- + * TODO + * Implement the anonymously promised -uni option. + */ + + +/* + * Notes on Adam Chalcraft Juggling Notation (used by permission) + * a-> Adam's notation s-> Site swap (Cambridge) notation + * + * To define a map from a-notation to s-notation ("site-swap"), both + * of which look like doubly infinite sequences of natural numbers. In + * s-notation, there is a restriction on what is allowed, namely for + * the sequence s_n, the associated function f(n)=n+s_n must be a + * bijection. In a-notation, there is no restriction. + * + * To go from a-notation to s-notation, you start by mapping each a_n + * to a permutation of N, the natural numbers. + * + * 0 -> the identity + * 1 -> (10) [i.e. f(1)=0, f(0)=1] + * 2 -> (210) [i.e. f(2)=1, f(1)=0, f(0)=2] + * 3 -> (3210) [i.e. f(3)=2, f(2)=1, f(1)=0, f(0)=3] + * etc. + * + * Then for each n, you look at how long 0 takes to get back to 0 + * again and you call this t_n. If a_n=0, for example, then since the + * identity leaves 0 alone, it gets back to 0 in 1 step, so t_n=1. If + * a_n=1, then f(0)=1. Now any further a_n=0 leave 1 alone, but the + * next a_n>0 sends 1 back to 0. Hence t_n is 2 + the number of 0's + * following the 1. Finally, set s_n = t_n - 1. + * + * To give some examples, it helps to have a notation for cyclic + * sequences. By (123), for example, I mean ...123123123123... . Now + * under the a-notation -> s-notation mapping we have some familiar + * examples: + * + * (0)->(0), (1)->(1), (2)->(2) etc. + * (21)->(31), (31)->(51), (41)->(71) etc. + * (10)->(20), (20)->(40), (30)->(60) etc. + * (331)->(441), (312)->(612), (303)->(504), (321)->(531) + * (43)->(53), (434)->(534), (433)->(633) + * (552)->(672) + * + * In general, the number of balls is the *average* of the s-notation, + * and the *maximum* of the a-notation. Another theorem is that the + * minimum values in the a-notation and the s-notation and equal, and + * preserved in the same positions. + * + * The usefulness of a-notation is the fact that there are no + * restrictions on what is allowed. This makes random juggle + * generation much easier. It also makes enumeration very + * easy. Another handy feature is computing changes. Suppose you can + * do (5) and want a neat change up to (771) in s-notation [Mike Day + * actually needed this example!]. Write them both in a-notation, + * which gives (5) and (551). Now concatenate them (in general, there + * may be more than one way to do this, but not in this example), to + * get + * + * ...55555555551551551551551... + * + * Now convert back to s-notation, to get + * + * ...55555566771771771771771... + * + * So the answer is to do two 6 throws and then go straight into + * (771). Coming back down of course, + * + * ...5515515515515515555555555... + * + * converts to + * + * ...7717717717716615555555555... + * + * so the answer is to do a single 661 and then drop straight down to + * (5). + * + * [The number of balls in the generated pattern occasionally changes. + * In order to decrease the number of balls I had to introduce a new + * symbol into the Adam notation, [*] which means 'lose the current + * ball'.] + */ + +/* This code uses so many linked lists it's worth having a built-in + * leak-checker */ +#undef MEMTEST + +#ifdef STANDALONE +# define MODE_juggle +# define DEFAULTS "*delay: 10000 \n" \ + "*count: 200 \n" \ + "*cycles: 1000 \n" \ + "*ncolors: 32 \n" \ + "*font: -*-helvetica-bold-r-normal-*-180-*\n" \ + "*fpsSolid: true\n" \ + +# define refresh_juggle 0 +# define juggle_handle_event 0 +# undef SMOOTH_COLORS +# include "xlockmore.h" /* in xscreensaver distribution */ +#else /* STANDALONE */ +# include "xlock.h" /* in xlockmore distribution */ +#endif /* STANDALONE */ + +#ifdef MODE_juggle + +#if 0 +#define XClearWindow(d, w) \ +{ \ + XSetForeground(d, MI_GC(mi), MI_PIXEL(mi, 3)); \ + XFillRectangle(d, w, MI_GC(mi), \ + 0, 0, (unsigned int) MI_WIDTH(mi), (unsigned int) MI_HEIGHT(mi)); \ +} +#endif + +#define DEF_PATTERN "random" /* All patterns */ +#define DEF_TAIL "1" /* No trace */ +#ifdef UNI +/* Maybe a ROLA BOLA would be at a better angle for viewing */ +#define DEF_UNI "False" /* No unicycle */ /* Not implemented yet */ +#endif +#define DEF_REAL "True" +#define DEF_DESCRIBE "True" + +#define DEF_BALLS "True" /* Use Balls */ +#define DEF_CLUBS "True" /* Use Clubs */ +#define DEF_TORCHES "True" /* Use Torches */ +#define DEF_KNIVES "True" /* Use Knives */ +#define DEF_RINGS "True" /* Use Rings */ +#define DEF_BBALLS "True" /* Use Bowling Balls */ + +#ifndef XtNumber +#define XtNumber(arr) ((unsigned int) (sizeof(arr) / sizeof(arr[0]))) +#endif + +static char *pattern; +static int tail; +#ifdef UNI +static Bool uni; +#endif +static Bool real; +static Bool describe; +static Bool balls; +static Bool clubs; +static Bool torches; +static Bool knives; +static Bool rings; +static Bool bballs; +static char *only; + +static XrmOptionDescRec opts[] = +{ + {"-pattern", ".juggle.pattern", XrmoptionSepArg, NULL }, + {"-tail", ".juggle.tail", XrmoptionSepArg, NULL }, +#ifdef UNI + {"-uni", ".juggle.uni", XrmoptionNoArg, "on" }, + {"+uni", ".juggle.uni", XrmoptionNoArg, "off" }, +#endif + {"-real", ".juggle.real", XrmoptionNoArg, "on" }, + {"+real", ".juggle.real", XrmoptionNoArg, "off" }, + {"-describe", ".juggle.describe", XrmoptionNoArg, "on" }, + {"+describe", ".juggle.describe", XrmoptionNoArg, "off" }, + {"-balls", ".juggle.balls", XrmoptionNoArg, "on" }, + {"+balls", ".juggle.balls", XrmoptionNoArg, "off" }, + {"-clubs", ".juggle.clubs", XrmoptionNoArg, "on" }, + {"+clubs", ".juggle.clubs", XrmoptionNoArg, "off" }, + {"-torches", ".juggle.torches", XrmoptionNoArg, "on" }, + {"+torches", ".juggle.torches", XrmoptionNoArg, "off" }, + {"-knives", ".juggle.knives", XrmoptionNoArg, "on" }, + {"+knives", ".juggle.knives", XrmoptionNoArg, "off" }, + {"-rings", ".juggle.rings", XrmoptionNoArg, "on" }, + {"+rings", ".juggle.rings", XrmoptionNoArg, "off" }, + {"-bballs", ".juggle.bballs", XrmoptionNoArg, "on" }, + {"+bballs", ".juggle.bballs", XrmoptionNoArg, "off" }, + {"-only", ".juggle.only", XrmoptionSepArg, NULL }, +}; +static argtype vars[] = +{ + { &pattern, "pattern", "Pattern", DEF_PATTERN, t_String }, + { &tail, "tail", "Tail", DEF_TAIL, t_Int }, +#ifdef UNI + { &uni, "uni", "Uni", DEF_UNI, t_Bool }, +#endif + { &real, "real", "Real", DEF_REAL, t_Bool }, + { &describe, "describe", "Describe", DEF_DESCRIBE, t_Bool }, + { &balls, "balls", "Clubs", DEF_BALLS, t_Bool }, + { &clubs, "clubs", "Clubs", DEF_CLUBS, t_Bool }, + { &torches, "torches", "Torches", DEF_TORCHES, t_Bool }, + { &knives, "knives", "Knives", DEF_KNIVES, t_Bool }, + { &rings, "rings", "Rings", DEF_RINGS, t_Bool }, + { &bballs, "bballs", "BBalls", DEF_BBALLS, t_Bool }, + { &only, "only", "BBalls", " ", t_String }, +}; +static OptionStruct desc[] = +{ + { "-pattern string", "Cambridge Juggling Pattern" }, + { "-tail num", "Trace Juggling Patterns" }, +#ifdef UNI + { "-/+uni", "Unicycle" }, +#endif + { "-/+real", "Real-time" }, + { "-/+describe", "turn on/off pattern descriptions." }, + { "-/+balls", "turn on/off Balls." }, + { "-/+clubs", "turn on/off Clubs." }, + { "-/+torches", "turn on/off Flaming Torches." }, + { "-/+knives", "turn on/off Knives." }, + { "-/+rings", "turn on/off Rings." }, + { "-/+bballs", "turn on/off Bowling Balls." }, + { "-only", "Turn off all objects but the named one." }, +}; + +ENTRYPOINT ModeSpecOpt juggle_opts = + { XtNumber(opts), opts, XtNumber(vars), vars, desc }; + +#ifdef USE_MODULES +ModStruct juggle_description = { + "juggle", "init_juggle", "draw_juggle", "release_juggle", + "draw_juggle", "change_juggle", (char *) NULL, &juggle_opts, + 10000, 200, 1000, 1, 64, 1.0, "", + "Shows a Juggler, juggling", 0, NULL +}; + +#endif + +#ifdef USE_XVMSUTILS +# include +#endif + +/* Note: All "lengths" are scaled by sp->scale = MI_HEIGHT/480. All + "thicknesses" are scaled by sqrt(sp->scale) so that they are + proportionally thicker for smaller windows. Objects spinning out + of the plane (such as clubs) fake perspective by compressing their + horizontal coordinates by PERSPEC */ + +/* Figure */ +#define ARMLENGTH 50 +#define ARMWIDTH ((int) (8.0 * sqrt(sp->scale))) +#define POSE 10 +#define BALLRADIUS ARMWIDTH + +#define PERSPEC 0.4 + +/* macros */ +#define GRAVITY(h, t) 4*(double)(h)/((t)*(t)) + +/* Timing based on count. Units are milliseconds. Juggles per second + is: 2000 / THROW_CATCH_INTERVAL + CATCH_THROW_INTERVAL */ + +#define THROW_CATCH_INTERVAL (sp->count) +#define THROW_NULL_INTERVAL (sp->count * 0.5) +#define CATCH_THROW_INTERVAL (sp->count * 0.2) + +/******************************************************************** + * Trace Definitions * + * * + * These record rendering data so that a drawn object can be erased * + * later. Each object has its own Trace list. * + * * + ********************************************************************/ + +typedef struct {double x, y; } DXPoint; +typedef struct trace *TracePtr; +typedef struct trace { + TracePtr next, prev; + double x, y; + double angle; + int divisions; + DXPoint dlast; +#ifdef MEMTEST + char pad[1024]; +#endif +} Trace; + +/******************************************************************* + * Object Definitions * + * * + * These describe the various types of Object that can be juggled * + * * + *******************************************************************/ +typedef void (DrawProc)(ModeInfo*, unsigned long, Trace *); + +static DrawProc show_ball, show_europeanclub, show_torch, show_knife; +static DrawProc show_ring, show_bball; + +typedef enum {BALL, CLUB, TORCH, KNIFE, RING, BBALLS, + NUM_OBJECT_TYPES} ObjType; +#define OBJMIXPROB 20 /* inverse of the chances of using an odd + object in the pattern */ + +static const struct { + DrawProc *draw; /* Object Rendering function */ + int handle; /* Length of object's handle */ + int mintrail; /* Minimum trail length */ + double cor; /* Coefficient of Restitution. perfect bounce = 1 */ + double weight; /* Heavier objects don't get thrown as high */ +} ObjectDefs[] = { + { /* Ball */ + show_ball, + 0, + 1, + 0.9, + 1.0, + }, + { /* Club */ + show_europeanclub, + 15, + 1, + 0.55, /* Clubs don't bounce too well */ + 1.0, + }, + { /* Torch */ + show_torch, + 15, + 20, /* Torches need flames */ + 0, /* Torches don't bounce -- fire risk! */ + 1.0, + }, + { /* Knife */ + show_knife, + 15, + 1, + 0, /* Knives don't bounce */ + 1.0, + }, + { /* Ring */ + show_ring, + 15, + 1, + 0.8, + 1.0, + }, + { /* Bowling Ball */ + show_bball, + 0, + 1, + 0.2, + 5.0, + }, +}; + +/************************** + * Trajectory definitions * + **************************/ + +typedef enum {HEIGHT, ADAM} Notation; +typedef enum {Empty, Full, Ball} Throwable; +typedef enum {LEFT, RIGHT} Hand; +typedef enum {THROW, CATCH} Action; +typedef enum {HAND, ELBOW, SHOULDER} Joint; +typedef enum {ATCH, THRATCH, ACTION, LINKEDACTION, + PTHRATCH, BPREDICTOR, PREDICTOR} TrajectoryStatus; +typedef struct {double a, b, c, d; } Spline; +typedef DXPoint Arm[3]; + +/* A Wander contains a Spline and a time interval. A list of Wanders + * describes the performer's position as he moves around the screen. */ +typedef struct wander *WanderPtr; +typedef struct wander { + WanderPtr next, prev; + double x; + unsigned long finish; + Spline s; +#ifdef MEMTEST + char pad[1024]; +#endif +} Wander; + +/* Object is an arbitrary object being juggled. Each Trajectory + * references an Object ("count" tracks this), and each Object is also + * linked into a global Objects list. Objects may include a Trace + * list for tracking erasures. */ +typedef struct object *ObjectPtr; +typedef struct object { + ObjectPtr next, prev; + + ObjType type; + int color; + int count; /* reference count */ + Bool active; /* Object is in use */ + + Trace *trace; + int tracelen; + int tail; +#ifdef MEMTEST + char pad[1024]; +#endif +} Object; + +/* Trajectory is a segment of juggling action. A list of Trajectories + * defines the juggling performance. The Trajectory list goes through + * multiple processing steps to convert it from basic juggling + * notation into rendering data. */ + +typedef struct trajectory *TrajectoryPtr; +typedef struct trajectory { + TrajectoryPtr prev, next; /* for building list */ + TrajectoryStatus status; + + /* Throw */ + char posn; + int height; + int adam; + char *pattern; + char *name; + + /* Action */ + Hand hand; + Action action; + + /* LinkedAction */ + int color; + Object *object; + int divisions; + double angle, spin; + TrajectoryPtr balllink; + TrajectoryPtr handlink; + + /* PThratch */ + double cx; /* Moving juggler */ + double x, y; /* current position */ + double dx, dy; /* initial velocity */ + + /* Predictor */ + Throwable type; + unsigned long start, finish; + Spline xp, yp; + +#ifdef MEMTEST + char pad[1024]; +#endif +} Trajectory; + + +/******************* + * Pattern Library * + *******************/ + +typedef struct { + const char * pattern; + const char * name; +} patternstruct; + +/* List of popular patterns, in any order */ +/* Patterns should be given in Adam notation so the generator can + concatenate them safely. Null descriptions are ok. Height + notation will be displayed automatically. */ +/* Can't const this because it is qsorted. This *should* be reentrant, + I think... */ +static /*const*/ patternstruct portfolio[] = { + {"[+2 1]", /* +3 1 */ "Typical 2 ball juggler"}, + {"[2 0]", /* 4 0 */ "2 in 1 hand"}, + {"[2 0 1]", /* 5 0 1 */}, + {"[+2 0 +2 0 0]" /* +5 0 +5 0 0 */}, + {"[+2 0 1 2 2]", /* +4 0 1 2 3 */}, + {"[2 0 1 1]", /* 6 0 1 1 */}, + + {"[3]", /* 3 */ "3 cascade"}, + {"[+3]", /* +3 */ "reverse 3 cascade"}, + {"[=3]", /* =3 */ "cascade 3 under arm"}, + {"[&3]", /* &3 */ "cascade 3 catching under arm"}, + {"[_3]", /* _3 */ "bouncing 3 cascade"}, + {"[+3 x3 =3]", /* +3 x3 =3 */ "Mill's mess"}, + {"[3 2 1]", /* 5 3 1" */}, + {"[3 3 1]", /* 4 4 1" */}, + {"[3 1 2]", /* 6 1 2 */ "See-saw"}, + {"[=3 3 1 2]", /* =4 5 1 2 */}, + {"[=3 2 2 3 1 2]", /* =6 2 2 5 1 2 */ "=4 5 1 2 stretched"}, + {"[+3 3 1 3]", /* +4 4 1 3 */ "anemic shower box"}, + {"[3 3 1]", /* 4 4 1 */}, + {"[+3 2 3]", /* +4 2 3 */}, + {"[+3 1]", /* +5 1 */ "3 shower"}, + {"[_3 1]", /* _5 1 */ "bouncing 3 shower"}, + {"[3 0 3 0 3]", /* 5 0 5 0 5 */ "shake 3 out of 5"}, + {"[3 3 3 0 0]", /* 5 5 5 0 0 */ "flash 3 out of 5"}, + {"[3 3 0]", /* 4 5 0 */ "complete waste of a 5 ball juggler"}, + {"[3 3 3 0 0 0 0]", /* 7 7 7 0 0 0 0 */ "3 flash"}, + {"[+3 0 +3 0 +3 0 0]", /* +7 0 +7 0 +7 0 0 */}, + {"[3 2 2 0 3 2 0 2 3 0 2 2 0]", /* 7 3 3 0 7 3 0 3 7 0 3 3 0 */}, + {"[3 0 2 0]", /* 8 0 4 0 */}, + {"[_3 2 1]", /* _5 3 1 */}, + {"[_3 0 1]", /* _8 0 1 */}, + {"[1 _3 1 _3 0 1 _3 0]", /* 1 _7 1 _7 0 1 _7 0 */}, + {"[_3 2 1 _3 1 2 1]", /* _6 3 1 _6 1 3 1 */}, + + {"[4]", /* 4 */ "4 cascade"}, + {"[+4 3]", /* +5 3 */ "4 ball half shower"}, + {"[4 4 2]", /* 5 5 2 */}, + {"[+4 4 4 +4]", /* +4 4 4 +4 */ "4 columns"}, + {"[+4 3 +4]", /* +5 3 +4 */}, + {"[4 3 4 4]", /* 5 3 4 4 */}, + {"[4 3 3 4]", /* 6 3 3 4 */}, + {"[4 3 2 4", /* 6 4 2 4 */}, + {"[+4 1]", /* +7 1 */ "4 shower"}, + {"[4 4 4 4 0]", /* 5 5 5 5 0 */ "learning 5"}, + {"[+4 x4 =4]", /* +4 x4 =4 */ "Mill's mess for 4"}, + {"[+4 2 1 3]", /* +9 3 1 3 */}, + {"[4 4 1 4 1 4]", /* 6 6 1 5 1 5, by Allen Knutson */}, + {"[_4 _4 _4 1 _4 1]", /* _5 _6 _6 1 _5 1 */}, + {"[_4 3 3]", /* _6 3 3 */}, + {"[_4 3 1]", /* _7 4 1 */}, + {"[_4 2 1]", /* _8 3 1 */}, + {"[_4 3 3 3 0]", /* _8 4 4 4 0 */}, + {"[_4 1 3 1]", /* _9 1 5 1 */}, + {"[_4 1 3 1 2]", /* _10 1 6 1 2 */}, + + {"[5]", /* 5 */ "5 cascade"}, + {"[_5 _5 _5 _5 _5 5 5 5 5 5]", /* _5 _5 _5 _5 _5 5 5 5 5 5 */}, + {"[+5 x5 =5]", /* +5 x5 =5 */ "Mill's mess for 5"}, + {"[5 4 4]", /* 7 4 4 */}, + {"[_5 4 4]", /* _7 4 4 */}, + {"[1 2 3 4 5 5 5 5 5]", /* 1 2 3 4 5 6 7 8 9 */ "5 ramp"}, + {"[5 4 5 3 1]", /* 8 5 7 4 1, by Allen Knutson */}, + {"[_5 4 1 +4]", /* _9 5 1 5 */}, + {"[_5 4 +4 +4]", /* _8 4 +4 +4 */}, + {"[_5 4 4 4 1]", /* _9 5 5 5 1 */}, + {"[_5 4 4 5 1]",}, + {"[_5 4 4 +4 4 0]", /*_10 5 5 +5 5 0 */}, + + {"[6]", /* 6 */ "6 cascade"}, + {"[+6 5]", /* +7 5 */}, + {"[6 4]", /* 8 4 */}, + {"[+6 3]", /* +9 3 */}, + {"[6 5 4 4]", /* 9 7 4 4 */}, + {"[+6 5 5 5]", /* +9 5 5 5 */}, + {"[6 0 6]", /* 9 0 9 */}, + {"[_6 0 _6]", /* _9 0 _9 */}, + + {"[_7]", /* _7 */ "bouncing 7 cascade"}, + {"[7]", /* 7 */ "7 cascade"}, + {"[7 6 6 6 6]", /* 11 6 6 6 6 */ "Gatto's High Throw"}, + +}; + + + +typedef struct { int start; int number; } PatternIndex; + +struct patternindex { + int minballs; + int maxballs; + PatternIndex index[XtNumber(portfolio)]; +}; + + +/* Jugglestruct: per-screen global data. The master Wander, Object + * and Trajectory lists are anchored here. */ +typedef struct { + double scale; + Wander *wander; + double cx; + double Gr; + Trajectory *head; + Arm arm[2][2]; + char *pattern; + int count; + int num_balls; + time_t begintime; /* should make 'time' usable for at least 48 days + on a 32-bit machine */ + unsigned long time; /* millisecond timer*/ + ObjType objtypes; + Object *objects; + struct patternindex patternindex; + XFontStruct *mode_font; +} jugglestruct; + +static jugglestruct *juggles = (jugglestruct *) NULL; + +/******************* + * list management * + *******************/ + +#define DUP_OBJECT(n, t) { \ + (n)->object = (t)->object; \ + if((n)->object != NULL) (n)->object->count++; \ +} + +/* t must point to an existing element. t must not be an + expression ending ->next or ->prev */ +#define REMOVE(t) { \ + (t)->next->prev = (t)->prev; \ + (t)->prev->next = (t)->next; \ + free(t); \ +} + +/* t receives element to be created and added to the list. ot must + point to an existing element or be identical to t to start a new + list. Applicable to Trajectories, Objects and Traces. */ +#define ADD_ELEMENT(type, t, ot) \ + if (((t) = (type*)calloc(1,sizeof(type))) != NULL) { \ + (t)->next = (ot)->next; \ + (t)->prev = (ot); \ + (ot)->next = (t); \ + (t)->next->prev = (t); \ + } + +static void +object_destroy(Object* o) +{ + if(o->trace != NULL) { + while(o->trace->next != o->trace) { + Trace *s = o->trace->next; + REMOVE(s); /* Don't eliminate 's' */ + } + free(o->trace); + } + REMOVE(o); +} + +static void +trajectory_destroy(Trajectory *t) { + if(t->name != NULL) free(t->name); + if(t->pattern != NULL) free(t->pattern); + /* Reduce object link count and call destructor if necessary */ + if(t->object != NULL && --t->object->count < 1 && t->object->tracelen == 0) { + object_destroy(t->object); + } + REMOVE(t); /* Unlink and free */ +} + +static void +free_juggle(jugglestruct *sp) { + if (sp->head != NULL) { + while (sp->head->next != sp->head) { + trajectory_destroy(sp->head->next); + } + free(sp->head); + sp->head = (Trajectory *) NULL; + } + if(sp->objects != NULL) { + while (sp->objects->next != sp->objects) { + object_destroy(sp->objects->next); + } + free(sp->objects); + sp->objects = (Object*)NULL; + } + if(sp->wander != NULL) { + while (sp->wander->next != sp->wander) { + Wander *w = sp->wander->next; + REMOVE(w); + } + free(sp->wander); + sp->wander = (Wander*)NULL; + } + if(sp->pattern != NULL) { + free(sp->pattern); + sp->pattern = NULL; + } + if (sp->mode_font!=None) { + XFreeFontInfo(NULL,sp->mode_font,1); + sp->mode_font = None; + } +} + +static Bool +add_throw(jugglestruct *sp, char type, int h, Notation n, const char* name) +{ + Trajectory *t; + + ADD_ELEMENT(Trajectory, t, sp->head->prev); + if(t == NULL){ /* Out of Memory */ + free_juggle(sp); + return False; + } + t->object = NULL; + if(name != NULL) + t->name = strdup(name); + t->posn = type; + if (n == ADAM) { + t->adam = h; + t->height = 0; + t->status = ATCH; + } else { + t->height = h; + t->status = THRATCH; + } + return True; +} + +/* add a Thratch to the performance */ +static Bool +program(ModeInfo *mi, const char *patn, const char *name, int cycles) +{ + jugglestruct *sp = &juggles[MI_SCREEN(mi)]; + const char *p; + int w, h, i, seen; + Notation notation; + char type; + + if (MI_IS_VERBOSE(mi)) { + (void) fprintf(stderr, "juggle[%d]: Programmed: %s x %d\n", + MI_SCREEN(mi), (name == NULL) ? patn : name, cycles); + } + + for(w=i=0; i < cycles; i++, w++) { /* repeat until at least "cycles" throws + have been programmed */ + /* title is the pattern name to be supplied to the first throw of + a sequence. If no name if given, use an empty title so that + the sequences are still delimited. */ + const char *title = (name != NULL)? name : ""; + type=' '; + h = 0; + seen = 0; + notation = HEIGHT; + for(p=patn; *p; p++) { + if (*p >= '0' && *p <='9') { + seen = 1; + h = 10*h + (*p - '0'); + } else { + Notation nn = notation; + switch (*p) { + case '[': /* begin Adam notation */ + notation = ADAM; + break; + case '-': /* Inside throw */ + type = ' '; + break; + case '+': /* Outside throw */ + case '=': /* Cross throw */ + case '&': /* Cross catch */ + case 'x': /* Cross throw and catch */ + case '_': /* Bounce */ + case 'k': /* Kickup */ + type = *p; + break; + case '*': /* Lose ball */ + seen = 1; + h = -1; + /* fall through */ + case ']': /* end Adam notation */ + nn = HEIGHT; + /* fall through */ + case ' ': + if (seen) { + i++; + if (!add_throw(sp, type, h, notation, title)) + return False; + title = NULL; + type=' '; + h = 0; + seen = 0; + } + notation = nn; + break; + default: + if(w == 0) { /* Only warn on first pass */ + (void) fprintf(stderr, + "juggle[%d]: Unexpected pattern instruction: '%c'\n", + MI_SCREEN(mi), *p); + } + break; + } + } + } + if (seen) { /* end of sequence */ + if (!add_throw(sp, type, h, notation, title)) + return False; + title = NULL; + } + } + return True; +} + +/* + ~~~~\~~~~~\~~~ + \\~\\~\~\\\~~~ + \\~\\\\~\\\~\~ + \\\\\\\\\\\~\\ + +[ 3 3 1 3 4 2 3 1 3 3 4 0 2 1 ] + +4 4 1 3 12 2 4 1 4 4 13 0 3 1 + +*/ +#define BOUNCEOVER 10 +#define KICKMIN 7 +#define THROWMAX 20 + +/* Convert Adam notation into heights */ +static void +adam(jugglestruct *sp) +{ + Trajectory *t, *p; + for(t = sp->head->next; t != sp->head; t = t->next) { + if (t->status == ATCH) { + int a = t->adam; + t->height = 0; + for(p = t->next; a > 0; p = p->next) { + if(p == sp->head) { + t->height = -9; /* Indicate end of processing for name() */ + return; + } + if (p->status != ATCH || p->adam < 0 || p->adam>= a) { + a--; + } + t->height++; + } + if(t->height > BOUNCEOVER && t->posn == ' '){ + t->posn = '_'; /* high defaults can be bounced */ + } else if(t->height < 3 && t->posn == '_') { + t->posn = ' '; /* Can't bounce short throws. */ + } + if(t->height < KICKMIN && t->posn == 'k'){ + t->posn = ' '; /* Can't kick short throws */ + } + if(t->height > THROWMAX){ + t->posn = 'k'; /* Use kicks for ridiculously high throws */ + } + t->status = THRATCH; + } + } +} + +/* Discover converted heights and update the sequence title */ +static void +name(jugglestruct *sp) +{ + Trajectory *t, *p; + char buffer[BUFSIZ]; + char *b; + for(t = sp->head->next; t != sp->head; t = t->next) { + if (t->status == THRATCH && t->name != NULL) { + b = buffer; + for(p = t; p == t || p->name == NULL; p = p->next) { + if(p == sp->head || p->height < 0) { /* end of reliable data */ + return; + } + if(p->posn == ' ') { + b += sprintf(b, " %d", p->height); + } else { + b += sprintf(b, " %c%d", p->posn, p->height); + } + if(b - buffer > 500) break; /* otherwise this could eventually + overflow. It'll be too big to + display anyway. */ + } + if(*t->name != 0) { + (void) sprintf(b, ", %s", t->name); + } + free(t->name); /* Don't need name any more, it's been converted + to pattern */ + t->name = NULL; + if(t->pattern != NULL) free(t->pattern); + t->pattern = strdup(buffer); + } + } +} + +/* Split Thratch notation into explicit throws and catches. + Usually Catch follows Throw in same hand, but take care of special + cases. */ + +/* ..n1.. -> .. LTn RT1 LC RC .. */ +/* ..nm.. -> .. LTn LC RTm RC .. */ + +static Bool +part(jugglestruct *sp) +{ + Trajectory *t, *nt, *p; + Hand hand = (LRAND() & 1) ? RIGHT : LEFT; + + for (t = sp->head->next; t != sp->head; t = t->next) { + if (t->status > THRATCH) { + hand = t->hand; + } else if (t->status == THRATCH) { + char posn = '='; + + /* plausibility check */ + if (t->height <= 2 && t->posn == '_') { + t->posn = ' '; /* no short bounces */ + } + if (t->height <= 1 && (t->posn == '=' || t->posn == '&')) { + t->posn = ' '; /* 1's need close catches */ + } + + switch (t->posn) { + /* throw catch */ + case ' ': posn = '-'; t->posn = '+'; break; + case '+': posn = '+'; t->posn = '-'; break; + case '=': posn = '='; t->posn = '+'; break; + case '&': posn = '+'; t->posn = '='; break; + case 'x': posn = '='; t->posn = '='; break; + case '_': posn = '_'; t->posn = '-'; break; + case 'k': posn = 'k'; t->posn = 'k'; break; + default: + (void) fprintf(stderr, "juggle: unexpected posn %c\n", t->posn); + break; + } + hand = (Hand) ((hand + 1) % 2); + t->status = ACTION; + t->hand = hand; + p = t->prev; + + if (t->height == 1 && p != sp->head) { + p = p->prev; /* '1's are thrown earlier than usual */ + } + + + + t->action = CATCH; + ADD_ELEMENT(Trajectory, nt, p); + if(nt == NULL){ + free_juggle(sp); + return False; + } + nt->object = NULL; + nt->status = ACTION; + nt->action = THROW; + nt->height = t->height; + nt->hand = hand; + nt->posn = posn; + + } + } + return True; +} + +static ObjType +choose_object(void) { + ObjType o; + for (;;) { + o = (ObjType)NRAND((ObjType)NUM_OBJECT_TYPES); + if(balls && o == BALL) break; + if(clubs && o == CLUB) break; + if(torches && o == TORCH) break; + if(knives && o == KNIFE) break; + if(rings && o == RING) break; + if(bballs && o == BBALLS) break; + } + return o; +} + +/* Connnect up throws and catches to figure out which ball goes where. + Do the same with the juggler's hands. */ + +static void +lob(ModeInfo *mi) +{ + jugglestruct *sp = &juggles[MI_SCREEN(mi)]; + Trajectory *t, *p; + int h; + for (t = sp->head->next; t != sp->head; t = t->next) { + if (t->status == ACTION) { + if (t->action == THROW) { + if (t->type == Empty) { + /* Create new Object */ + ADD_ELEMENT(Object, t->object, sp->objects); + t->object->count = 1; + t->object->tracelen = 0; + t->object->active = False; + /* Initialise object's circular trace list */ + ADD_ELEMENT(Trace, t->object->trace, t->object->trace); + + if (MI_NPIXELS(mi) > 2) { + t->object->color = 1 + NRAND(MI_NPIXELS(mi) - 2); + } else { +#ifdef STANDALONE + t->object->color = 1; +#else + t->object->color = 0; +#endif + } + + /* Small chance of picking a random object instead of the + current theme. */ + if(NRAND(OBJMIXPROB) == 0) { + t->object->type = choose_object(); + } else { + t->object->type = sp->objtypes; + } + + /* Check to see if we need trails for this object */ + if(tail < ObjectDefs[t->object->type].mintrail) { + t->object->tail = ObjectDefs[t->object->type].mintrail; + } else { + t->object->tail = tail; + } + } + + /* Balls can change divisions at each throw */ + t->divisions = 2 * (NRAND(2) + 1); + + /* search forward for next catch in this hand */ + for (p = t->next; t->handlink == NULL; p = p->next) { + if(p->status < ACTION || p == sp->head) return; + if (p->action == CATCH) { + if (t->handlink == NULL && p->hand == t->hand) { + t->handlink = p; + } + } + } + + if (t->height > 0) { + h = t->height - 1; + + /* search forward for next ball catch */ + for (p = t->next; t->balllink == NULL; p = p->next) { + if(p->status < ACTION || p == sp->head) { + t->handlink = NULL; + return; + } + if (p->action == CATCH) { + if (t->balllink == NULL && --h < 1) { /* caught */ + t->balllink = p; /* complete trajectory */ +# if 0 + if (p->type == Full) { + (void) fprintf(stderr, "juggle[%d]: Dropped %d\n", + MI_SCREEN(mi), t->object->color); + } +#endif + p->type = Full; + DUP_OBJECT(p, t); /* accept catch */ + p->angle = t->angle; + p->divisions = t->divisions; + } + } + } + } + t->type = Empty; /* thrown */ + } else if (t->action == CATCH) { + /* search forward for next throw from this hand */ + for (p = t->next; t->handlink == NULL; p = p->next) { + if(p->status < ACTION || p == sp->head) return; + if (p->action == THROW && p->hand == t->hand) { + p->type = t->type; /* pass ball */ + DUP_OBJECT(p, t); /* pass object */ + p->divisions = t->divisions; + t->handlink = p; + } + } + } + t->status = LINKEDACTION; + } + } +} + +/* Clap when both hands are empty */ +static void +clap(jugglestruct *sp) +{ + Trajectory *t, *p; + for (t = sp->head->next; t != sp->head; t = t->next) { + if (t->status == LINKEDACTION && + t->action == CATCH && + t->type == Empty && + t->handlink != NULL && + t->handlink->height == 0) { /* Completely idle hand */ + + for (p = t->next; p != sp->head; p = p->next) { + if (p->status == LINKEDACTION && + p->action == CATCH && + p->hand != t->hand) { /* Next catch other hand */ + if(p->type == Empty && + p->handlink != NULL && + p->handlink->height == 0) { /* Also completely idle */ + + t->handlink->posn = '^'; /* Move first hand's empty throw */ + p->posn = '^'; /* to meet second hand's empty + catch */ + + } + break; /* Only need first catch */ + } + } + } + } +} + +#define CUBIC(s, t) ((((s).a * (t) + (s).b) * (t) + (s).c) * (t) + (s).d) + +/* Compute single spline from x0 with velocity dx0 at time t0 to x1 + with velocity dx1 at time t1 */ +static Spline +makeSpline(double x0, double dx0, int t0, double x1, double dx1, int t1) +{ + Spline s; + double a, b, c, d; + double x10; + double t10; + + x10 = x1 - x0; + t10 = t1 - t0; + a = ((dx0 + dx1)*t10 - 2*x10) / (t10*t10*t10); + b = (3*x10 - (2*dx0 + dx1)*t10) / (t10*t10); + c = dx0; + d = x0; + s.a = a; + s.b = -3*a*t0 + b; + s.c = (3*a*t0 - 2*b)*t0 + c; + s.d = ((-a*t0 + b)*t0 - c)*t0 +d; + return s; +} + +/* Compute a pair of splines. s1 goes from x0 vith velocity dx0 at + time t0 to x1 at time t1. s2 goes from x1 at time t1 to x2 with + velocity dx2 at time t2. The arrival and departure velocities at + x1, t1 must be the same. */ +static double +makeSplinePair(Spline *s1, Spline *s2, + double x0, double dx0, int t0, + double x1, int t1, + double x2, double dx2, int t2) +{ + double x10, x21, t21, t10, t20, dx1; + x10 = x1 - x0; + x21 = x2 - x1; + t21 = t2 - t1; + t10 = t1 - t0; + t20 = t2 - t0; + dx1 = (3*x10*t21*t21 + 3*x21*t10*t10 + 3*dx0*t10*t21*t21 + - dx2*t10*t10*t21 - 4*dx0*t10*t21*t21) / + (2*t10*t21*t20); + *s1 = makeSpline(x0, dx0, t0, x1, dx1, t1); + *s2 = makeSpline(x1, dx1, t1, x2, dx2, t2); + return dx1; +} + +/* Compute a Ballistic path in a pair of degenerate splines. sx goes + from x at time t at constant velocity dx. sy goes from y at time t + with velocity dy and constant acceleration g. */ +static void +makeParabola(Trajectory *n, + double x, double dx, double y, double dy, double g) +{ + double t = (double)n->start; + n->xp.a = 0; + n->xp.b = 0; + n->xp.c = dx; + n->xp.d = -dx*t + x; + n->yp.a = 0; + n->yp.b = g/2; + n->yp.c = -g*t + dy; + n->yp.d = g/2*t*t - dy*t + y; +} + + + +/* Make juggler wander around the screen */ +static double wander(jugglestruct *sp, unsigned long time) +{ + Wander *w = NULL; + for (w = sp->wander->next; w != sp->wander; w = w->next) { + if (w->finish < sp->time) { /* expired */ + Wander *ww = w; + w = w->prev; + REMOVE(ww); + } else if(w->finish > time) { + break; + } + } + if(w == sp->wander) { /* Need a new one */ + ADD_ELEMENT(Wander, w, sp->wander->prev); + if(w == NULL) { /* Memory problem */ + return 0.0; + } + w->finish = time + 3*THROW_CATCH_INTERVAL + NRAND(10*THROW_CATCH_INTERVAL); + if(time == 0) { + w->x = 0; + } else { + w->x = w->prev->x * 0.9 + NRAND(40) - 20; + } + w->s = makeSpline(w->prev->x, 0.0, w->prev->finish, w->x, 0.0, w->finish); + } + return CUBIC(w->s, time); +} + +#define SX 25 /* Shoulder Width */ + +/* Convert hand position symbols into actual time/space coordinates */ +static void +positions(jugglestruct *sp) +{ + Trajectory *t; + unsigned long now = sp->time; /* Make sure we're not lost in the past */ + for (t = sp->head->next; t != sp->head; t = t->next) { + if (t->status >= PTHRATCH) { + now = t->start; + } else if (t->status == ACTION || t->status == LINKEDACTION) { + /* Allow ACTIONs to be annotated, but we won't mark them ready + for the next stage */ + + double xo = 0, yo; + double sx = SX; + double pose = SX/2; + + /* time */ + if (t->action == CATCH) { /* Throw-to-catch */ + if (t->type == Empty) { + now += (int) THROW_NULL_INTERVAL; /* failed catch is short */ + } else { /* successful catch */ + now += (int)(THROW_CATCH_INTERVAL); + } + } else { /* Catch-to-throw */ + if(t->object != NULL) { + now += (int) (CATCH_THROW_INTERVAL * + ObjectDefs[t->object->type].weight); + } else { + now += (int) (CATCH_THROW_INTERVAL); + } + } + + if(t->start == 0) + t->start = now; + else /* Concatenated performances may need clock resync */ + now = t->start; + + t->cx = wander(sp, t->start); + + /* space */ + yo = 90; + + /* Add room for the handle */ + if(t->action == CATCH && t->object != NULL) + yo -= ObjectDefs[t->object->type].handle; + + switch (t->posn) { + case '-': xo = sx - pose; break; + case '_': + case 'k': + case '+': xo = sx + pose; break; + case '~': + case '=': xo = - sx - pose; yo += pose; break; + case '^': xo = 0; yo += pose*2; break; /* clap */ + default: + (void) fprintf(stderr, "juggle: unexpected posn %c\n", t->posn); + break; + } + + t->angle = (((t->hand == LEFT) ^ + (t->posn == '+' || t->posn == '_' || t->posn == 'k' ))? + -1 : 1) * M_PI/2; + + t->x = t->cx + ((t->hand == LEFT) ? xo : -xo); + t->y = yo; + + /* Only mark complete if it was already linked */ + if(t->status == LINKEDACTION) { + t->status = PTHRATCH; + } + } + } +} + + +/* Private physics functions */ + +/* Compute the spin-rate for a trajectory. Different types of throw + (eg, regular thows, bounces, kicks, etc) have different spin + requirements. + + type = type of object + h = trajectory of throwing hand (throws), or next throwing hand (catches) + old = earlier spin to consider + dt = time span of this trajectory + height = height of ball throw or 0 if based on old spin + turns = full club turns required during this operation + togo = partial club turns required to match hands +*/ +static double +spinrate(ObjType type, Trajectory *h, double old, double dt, + int height, int turns, double togo) +{ + const int dir = (h->hand == LEFT) ^ (h->posn == '+')? -1 : 1; + + if(ObjectDefs[type].handle != 0) { /* Clubs */ + return (dir * turns * 2 * M_PI + togo) / dt; + } else if(height == 0) { /* Balls already spinning */ + return old/2; + } else { /* Balls */ + return dir * NRAND(height*10)/20/ObjectDefs[type].weight * 2 * M_PI / dt; + } +} + + +/* compute the angle at the end of a spinning trajectory */ +static double +end_spin(Trajectory *t) +{ + return t->angle + t->spin * (t->finish - t->start); +} + +/* Sets the initial angle of the catch following hand movement t to + the final angle of the throw n. Also sets the angle of the + subsequent throw to the same angle plus half a turn. */ +static void +match_spins_on_catch(Trajectory *t, Trajectory *n) +{ + if(ObjectDefs[t->balllink->object->type].handle == 0) { + t->balllink->angle = end_spin(n); + if(t->balllink->handlink != NULL) { + t->balllink->handlink->angle = t->balllink->angle + M_PI; + } + } +} + +static double +find_bounce(jugglestruct *sp, + double yo, double yf, double yc, double tc, double cor) +{ + double tb, i, dy = 0; + const double e = 1; /* permissible error in yc */ + + /* + tb = time to bounce + yt = height at catch time after one bounce + one or three roots according to timing + find one by interval bisection + */ + tb = tc; + for(i = tc / 2; i > 0.0001; i/=2){ + double dt, yt; + if(tb == 0){ + (void) fprintf(stderr, "juggle: bounce div by zero!\n"); + break; + } + dy = (yf - yo)/tb + sp->Gr/2*tb; + dt = tc - tb; + yt = -cor*dy*dt + sp->Gr/2*dt*dt + yf; + if(yt < yc + e){ + tb-=i; + }else if(yt > yc - e){ + tb+=i; + }else{ + break; + } + } + if(dy*THROW_CATCH_INTERVAL < -200) { /* bounce too hard */ + tb = -1; + } + return tb; +} + +static Trajectory* +new_predictor(const Trajectory *t, int start, int finish, double angle) +{ + Trajectory *n; + ADD_ELEMENT(Trajectory, n, t->prev); + if(n == NULL){ + return NULL; + } + DUP_OBJECT(n, t); + n->divisions = t->divisions; + n->type = Ball; + n->status = PREDICTOR; + + n->start = start; + n->finish = finish; + n->angle = angle; + return n; +} + +/* Turn abstract timings into physically appropriate object trajectories. */ +static Bool +projectile(jugglestruct *sp) +{ + Trajectory *t; + const int yf = 0; /* Floor height */ + + for (t = sp->head->next; t != sp->head; t = t->next) { + if (t->status != PTHRATCH || t->action != THROW) { + continue; + } else if (t->balllink == NULL) { /* Zero Throw */ + t->status = BPREDICTOR; + } else if (t->balllink->handlink == NULL) { /* Incomplete */ + return True; + } else if(t->balllink == t->handlink) { + /* '2' height - hold on to ball. Don't need to consider + flourishes, 'hands' will do that automatically anyway */ + + t->type = Full; + /* Zero spin to avoid wrist injuries */ + t->spin = 0; + match_spins_on_catch(t, t); + t->dx = t->dy = 0; + t->status = BPREDICTOR; + continue; + } else { + if (t->posn == '_') { /* Bounce once */ + + const int tb = t->start + + find_bounce(sp, t->y, (double) yf, t->balllink->y, + (double) (t->balllink->start - t->start), + ObjectDefs[t->object->type].cor); + + if(tb < t->start) { /* bounce too hard */ + t->posn = '+'; /* Use regular throw */ + } else { + Trajectory *n; /* First (throw) trajectory. */ + double dt; /* Time span of a trajectory */ + double dy; /* Distance span of a follow-on trajectory. + First trajectory uses t->dy */ + /* dx is constant across both trajectories */ + t->dx = (t->balllink->x - t->x) / (t->balllink->start - t->start); + + { /* ball follows parabola down */ + n = new_predictor(t, t->start, tb, t->angle); + if(n == NULL) return False; + dt = n->finish - n->start; + /* Ball rate 4, no flight or matching club turns */ + n->spin = spinrate(t->object->type, t, 0.0, dt, 4, 0, 0.0); + t->dy = (yf - t->y)/dt - sp->Gr/2*dt; + makeParabola(n, t->x, t->dx, t->y, t->dy, sp->Gr); + } + + { /* ball follows parabola up */ + Trajectory *m = new_predictor(t, n->finish, t->balllink->start, + end_spin(n)); + if(m == NULL) return False; + dt = m->finish - m->start; + /* Use previous ball rate, no flight club turns */ + m->spin = spinrate(t->object->type, t, n->spin, dt, 0, 0, + t->balllink->angle - m->angle); + match_spins_on_catch(t, m); + dy = (t->balllink->y - yf)/dt - sp->Gr/2 * dt; + makeParabola(m, t->balllink->x - t->dx * dt, + t->dx, (double) yf, dy, sp->Gr); + } + + t->status = BPREDICTOR; + continue; + } + } else if (t->posn == 'k') { /* Drop & Kick */ + Trajectory *n; /* First (drop) trajectory. */ + Trajectory *o; /* Second (rest) trajectory */ + Trajectory *m; /* Third (kick) trajectory */ + const int td = t->start + 2*THROW_CATCH_INTERVAL; /* Drop time */ + const int tk = t->balllink->start - 5*THROW_CATCH_INTERVAL; /* Kick */ + double dt, dy; + + { /* Fall to ground */ + n = new_predictor(t, t->start, td, t->angle); + if(n == NULL) return False; + dt = n->finish - n->start; + /* Ball spin rate 4, no flight club turns */ + n->spin = spinrate(t->object->type, t, 0.0, dt, 4, 0, + t->balllink->angle - n->angle); + t->dx = (t->balllink->x - t->x) / dt; + t->dy = (yf - t->y)/dt - sp->Gr/2*dt; + makeParabola(n, t->x, t->dx, t->y, t->dy, sp->Gr); + } + + { /* Rest on ground */ + o = new_predictor(t, n->finish, tk, end_spin(n)); + if(o == NULL) return False; + o->spin = 0; + makeParabola(o, t->balllink->x, 0.0, (double) yf, 0.0, 0.0); + } + + /* Kick up */ + { + m = new_predictor(t, o->finish, t->balllink->start, end_spin(o)); + if(m == NULL) return False; + dt = m->finish - m->start; + /* Match receiving hand, ball rate 4, one flight club turn */ + m->spin = spinrate(t->object->type, t->balllink->handlink, 0.0, dt, + 4, 1, t->balllink->angle - m->angle); + match_spins_on_catch(t, m); + dy = (t->balllink->y - yf)/dt - sp->Gr/2 * dt; + makeParabola(m, t->balllink->x, 0.0, (double) yf, dy, sp->Gr); + } + + t->status = BPREDICTOR; + continue; + } + + /* Regular flight, no bounce */ + { /* ball follows parabola */ + double dt; + Trajectory *n = new_predictor(t, t->start, + t->balllink->start, t->angle); + if(n == NULL) return False; + dt = t->balllink->start - t->start; + /* Regular spin */ + n->spin = spinrate(t->object->type, t, 0.0, dt, t->height, t->height/2, + t->balllink->angle - n->angle); + match_spins_on_catch(t, n); + t->dx = (t->balllink->x - t->x) / dt; + t->dy = (t->balllink->y - t->y) / dt - sp->Gr/2 * dt; + makeParabola(n, t->x, t->dx, t->y, t->dy, sp->Gr); + } + + t->status = BPREDICTOR; + } + } + return True; +} + +/* Turn abstract hand motions into cubic splines. */ +static void +hands(jugglestruct *sp) +{ + Trajectory *t, *u, *v; + + for (t = sp->head->next; t != sp->head; t = t->next) { + /* no throw => no velocity */ + if (t->status != BPREDICTOR) { + continue; + } + + u = t->handlink; + if (u == NULL) { /* no next catch */ + continue; + } + v = u->handlink; + if (v == NULL) { /* no next throw */ + continue; + } + + /* double spline takes hand from throw, thru catch, to + next throw */ + + t->finish = u->start; + t->status = PREDICTOR; + + u->finish = v->start; + u->status = PREDICTOR; + + + /* FIXME: These adjustments leave a small glitch when alternating + balls and clubs. Just hope no-one notices. :-) */ + + /* make sure empty hand spin matches the thrown object in case it + had a handle */ + + t->spin = ((t->hand == LEFT)? -1 : 1 ) * + fabs((u->angle - t->angle)/(u->start - t->start)); + + u->spin = ((v->hand == LEFT) ^ (v->posn == '+')? -1 : 1 ) * + fabs((v->angle - u->angle)/(v->start - u->start)); + + (void) makeSplinePair(&t->xp, &u->xp, + t->x, t->dx, t->start, + u->x, u->start, + v->x, v->dx, v->start); + (void) makeSplinePair(&t->yp, &u->yp, + t->y, t->dy, t->start, + u->y, u->start, + v->y, v->dy, v->start); + + t->status = PREDICTOR; + } +} + +/* Given target x, y find_elbow puts hand at target if possible, + * otherwise makes hand point to the target */ +static void +find_elbow(int armlength, DXPoint *h, DXPoint *e, DXPoint *p, DXPoint *s, + int z) +{ + double r, h2, t; + double x = p->x - s->x; + double y = p->y - s->y; + h2 = x*x + y*y + z*z; + if (h2 > 4 * armlength * armlength) { + t = armlength/sqrt(h2); + e->x = t*x + s->x; + e->y = t*y + s->y; + h->x = 2 * t * x + s->x; + h->y = 2 * t * y + s->y; + } else { + r = sqrt((double)(x*x + z*z)); + t = sqrt(4 * armlength * armlength / h2 - 1); + e->x = x*(1 + y*t/r)/2 + s->x; + e->y = (y - r*t)/2 + s->y; + h->x = x + s->x; + h->y = y + s->y; + } +} + + +/* NOTE: returned x, y adjusted for arm reach */ +static void +reach_arm(ModeInfo * mi, Hand side, DXPoint *p) +{ + jugglestruct *sp = &juggles[MI_SCREEN(mi)]; + DXPoint h, e; + find_elbow(40, &h, &e, p, &sp->arm[1][side][SHOULDER], 25); + *p = sp->arm[1][side][HAND] = h; + sp->arm[1][side][ELBOW] = e; +} + +#if DEBUG +/* dumps a human-readable rendition of the current state of the juggle + pipeline to stderr for debugging */ +static void +dump(jugglestruct *sp) +{ + Trajectory *t; + for (t = sp->head->next; t != sp->head; t = t->next) { + switch (t->status) { + case ATCH: + (void) fprintf(stderr, "%p a %c%d\n", (void*)t, t->posn, t->adam); + break; + case THRATCH: + (void) fprintf(stderr, "%p T %c%d %s\n", (void*)t, t->posn, t->height, + t->pattern == NULL?"":t->pattern); + break; + case ACTION: + if (t->action == CATCH) + (void) fprintf(stderr, "%p A %c%cC\n", + (void*)t, t->posn, + t->hand ? 'R' : 'L'); + else + (void) fprintf(stderr, "%p A %c%c%c%d\n", + (void*)t, t->posn, + t->hand ? 'R' : 'L', + (t->action == THROW)?'T':'N', + t->height); + break; + case LINKEDACTION: + (void) fprintf(stderr, "%p L %c%c%c%d %d %p %p\n", + (void*)t, t->posn, + t->hand?'R':'L', + (t->action == THROW)?'T':(t->action == CATCH?'C':'N'), + t->height, t->object == NULL?0:t->object->color, + (void*)t->handlink, (void*)t->balllink); + break; + case PTHRATCH: + (void) fprintf(stderr, "%p O %c%c%c%d %d %2d %6lu %6lu\n", + (void*)t, t->posn, + t->hand?'R':'L', + (t->action == THROW)?'T':(t->action == CATCH?'C':'N'), + t->height, t->type, t->object == NULL?0:t->object->color, + t->start, t->finish); + break; + case BPREDICTOR: + (void) fprintf(stderr, "%p B %c %2d %6lu %6lu %g\n", + (void*)t, t->type == Ball?'b':t->type == Empty?'e':'f', + t->object == NULL?0:t->object->color, + t->start, t->finish, t->yp.c); + break; + case PREDICTOR: + (void) fprintf(stderr, "%p P %c %2d %6lu %6lu %g\n", + (void*)t, t->type == Ball?'b':t->type == Empty?'e':'f', + t->object == NULL?0:t->object->color, + t->start, t->finish, t->yp.c); + break; + default: + (void) fprintf(stderr, "%p: status %d not implemented\n", + (void*)t, t->status); + break; + } + } + (void) fprintf(stderr, "---\n"); +} +#endif + +static int get_num_balls(const char *j) +{ + int balls = 0; + const char *p; + int h = 0; + if (!j) abort(); + for (p = j; *p; p++) { + if (*p >= '0' && *p <='9') { /* digit */ + h = 10*h + (*p - '0'); + } else { + if (h > balls) { + balls = h; + } + h = 0; + } + } + return balls; +} + +#ifdef __cplusplus +extern "C" { +#endif + +static int +compare_num_balls(const void *p1, const void *p2) +{ + int i, j; + i = get_num_balls(((patternstruct*)p1)->pattern); + j = get_num_balls(((patternstruct*)p2)->pattern); + if (i > j) { + return (1); + } else if (i < j) { + return (-1); + } else { + return (0); + } +} + +#ifdef __cplusplus +} +#endif + + +/************************************************************************** + * Rendering Functions * + * * + **************************************************************************/ + +static void +show_arms(ModeInfo * mi, unsigned long color) +{ + jugglestruct *sp = &juggles[MI_SCREEN(mi)]; + unsigned int i, j; + Hand side; + XPoint a[XtNumber(sp->arm[0][0])]; + if(color == MI_BLACK_PIXEL(mi)) { + j = 0; + } else { + j = 1; + } + XSetLineAttributes(MI_DISPLAY(mi), MI_GC(mi), + ARMWIDTH, LineSolid, CapRound, JoinRound); + XSetForeground(MI_DISPLAY(mi), MI_GC(mi), color); + for(side = LEFT; side <= RIGHT; side = (Hand)((int)side + 1)) { + /* Translate into device coords */ + for(i = 0; i < XtNumber(a); i++) { + a[i].x = (short)(MI_WIDTH(mi)/2 + sp->arm[j][side][i].x*sp->scale); + a[i].y = (short)(MI_HEIGHT(mi) - sp->arm[j][side][i].y*sp->scale); + if(j == 1) + sp->arm[0][side][i] = sp->arm[1][side][i]; + } + XDrawLines(MI_DISPLAY(mi), MI_WINDOW(mi), MI_GC(mi), + a, XtNumber(a), CoordModeOrigin); + } +} + +static void +show_figure(ModeInfo * mi, unsigned long color, Bool init) +{ + jugglestruct *sp = &juggles[MI_SCREEN(mi)]; + XPoint p[7]; + unsigned int i; + + /* +-----+ 9 + | 6 | + 10 +--+--+ + 2 +---+---+ 3 + \ 5 / + \ / + \ / + 1 + + / \ + / \ + 0 +-----+ 4 + | | + | | + | | + 7 + + 8 + */ + + static const XPoint figure[] = { + { 15, 70}, /* 0 Left Hip */ + { 0, 90}, /* 1 Waist */ + { SX, 130}, /* 2 Left Shoulder */ + {-SX, 130}, /* 3 Right Shoulder */ + {-15, 70}, /* 4 Right Hip */ + { 0, 130}, /* 5 Neck */ + { 0, 140}, /* 6 Chin */ + { SX, 0}, /* 7 Left Foot */ + {-SX, 0}, /* 8 Right Foot */ + {-17, 174}, /* 9 Head1 */ + { 17, 140}, /* 10 Head2 */ + }; + XPoint a[XtNumber(figure)]; + + /* Translate into device coords */ + for(i = 0; i < XtNumber(figure); i++) { + a[i].x = (short)(MI_WIDTH(mi)/2 + (sp->cx + figure[i].x)*sp->scale); + a[i].y = (short)(MI_HEIGHT(mi) - figure[i].y*sp->scale); + } + + XSetLineAttributes(MI_DISPLAY(mi), MI_GC(mi), + ARMWIDTH, LineSolid, CapRound, JoinRound); + XSetForeground(MI_DISPLAY(mi), MI_GC(mi), color); + + i = 0; /* Body */ + p[i++] = a[0]; p[i++] = a[1]; p[i++] = a[2]; + p[i++] = a[3]; p[i++] = a[1]; p[i++] = a[4]; + XDrawLines(MI_DISPLAY(mi), MI_WINDOW(mi), MI_GC(mi), + p, i, CoordModeOrigin); + + i = 0; /* Legs */ + p[i++] = a[7]; p[i++] = a[0]; p[i++] = a[4]; p[i++] = a[8]; + XDrawLines(MI_DISPLAY(mi), MI_WINDOW(mi), MI_GC(mi), + p, i, CoordModeOrigin); + + i = 0; /* Neck */ + p[i++] = a[5]; p[i++] = a[6]; + XDrawLines(MI_DISPLAY(mi), MI_WINDOW(mi), MI_GC(mi), + p, i, CoordModeOrigin); + + /* Head */ + XDrawArc(MI_DISPLAY(mi), MI_WINDOW(mi), MI_GC(mi), + a[9].x, a[9].y, + a[10].x - a[9].x, a[10].y - a[9].y, 0, 64*360); + sp->arm[1][LEFT][SHOULDER].x = sp->cx + figure[2].x; + sp->arm[1][RIGHT][SHOULDER].x = sp->cx + figure[3].x; + if(init) { + /* Initialise arms */ + unsigned int i; + for(i = 0; i < 2; i++){ + sp->arm[i][LEFT][SHOULDER].y = figure[2].y; + sp->arm[i][LEFT][ELBOW].x = figure[2].x; + sp->arm[i][LEFT][ELBOW].y = figure[1].y; + sp->arm[i][LEFT][HAND].x = figure[0].x; + sp->arm[i][LEFT][HAND].y = figure[1].y; + sp->arm[i][RIGHT][SHOULDER].y = figure[3].y; + sp->arm[i][RIGHT][ELBOW].x = figure[3].x; + sp->arm[i][RIGHT][ELBOW].y = figure[1].y; + sp->arm[i][RIGHT][HAND].x = figure[4].x; + sp->arm[i][RIGHT][HAND].y = figure[1].y; + } + } +} + +static void +show_ball(ModeInfo *mi, unsigned long color, Trace *s) +{ + jugglestruct *sp = &juggles[MI_SCREEN(mi)]; + int offset = (int)(s->angle*64*180/M_PI); + short x = (short)(MI_WIDTH(mi)/2 + s->x * sp->scale); + short y = (short)(MI_HEIGHT(mi) - s->y * sp->scale); + + /* Avoid wrapping */ + if(s->y*sp->scale > MI_HEIGHT(mi) * 2) return; + + XSetForeground(MI_DISPLAY(mi), MI_GC(mi), color); + if (s->divisions == 0 || color == MI_BLACK_PIXEL(mi)) { + XFillArc(MI_DISPLAY(mi), MI_WINDOW(mi), MI_GC(mi), + x - BALLRADIUS, y - BALLRADIUS, + 2*BALLRADIUS, 2*BALLRADIUS, + 0, 23040); + } else if (s->divisions == 4) { /* 90 degree divisions */ + XFillArc(MI_DISPLAY(mi), MI_WINDOW(mi), MI_GC(mi), + x - BALLRADIUS, y - BALLRADIUS, + 2*BALLRADIUS, 2*BALLRADIUS, + offset % 23040, 5760); + XFillArc(MI_DISPLAY(mi), MI_WINDOW(mi), MI_GC(mi), + x - BALLRADIUS, y - BALLRADIUS, + 2*BALLRADIUS, 2*BALLRADIUS, + (offset + 11520) % 23040, 5760); + + XSetForeground(MI_DISPLAY(mi), MI_GC(mi), MI_WHITE_PIXEL(mi)); + XFillArc(MI_DISPLAY(mi), MI_WINDOW(mi), MI_GC(mi), + x - BALLRADIUS, y - BALLRADIUS, + 2*BALLRADIUS, 2*BALLRADIUS, + (offset + 5760) % 23040, 5760); + XFillArc(MI_DISPLAY(mi), MI_WINDOW(mi), MI_GC(mi), + x - BALLRADIUS, y - BALLRADIUS, + 2*BALLRADIUS, 2*BALLRADIUS, + (offset + 17280) % 23040, 5760); + } else if (s->divisions == 2) { /* 180 degree divisions */ + XFillArc(MI_DISPLAY(mi), MI_WINDOW(mi), MI_GC(mi), + x - BALLRADIUS, y - BALLRADIUS, + 2*BALLRADIUS, 2*BALLRADIUS, + offset % 23040, 11520); + + XSetForeground(MI_DISPLAY(mi), MI_GC(mi), MI_WHITE_PIXEL(mi)); + XFillArc(MI_DISPLAY(mi), MI_WINDOW(mi), MI_GC(mi), + x - BALLRADIUS, y - BALLRADIUS, + 2*BALLRADIUS, 2*BALLRADIUS, + (offset + 11520) % 23040, 11520); + } else { + (void) fprintf(stderr, "juggle[%d]: unexpected divisions: %d\n", + MI_SCREEN(mi), s->divisions); + } +} + +static void +show_europeanclub(ModeInfo *mi, unsigned long color, Trace *s) +{ + jugglestruct *sp = &juggles[MI_SCREEN(mi)]; + XPoint p[4]; + const double sa = sin(s->angle); + const double ca = cos(s->angle); + unsigned int i; + + /* 6 6 + +-+ + / \ + 4 +-----+ 7 + ////////\ + 3 +---------+ 8 + 2 +---------+ 9 + |///////| + 1 +-------+ 10 + | | + | | + | | + | | + | | + | | + +-+ + 0 11 */ + + static const XPoint club[] = { + {-24, 2}, /* 0 */ + {-10, 3}, /* 1 */ + { 1, 6}, /* 2 */ + { 8, 6}, /* 3 */ + { 14, 4}, /* 4 */ + { 16, 3}, /* 5 */ + { 16,-3}, /* 6 */ + { 14,-4}, /* 7 */ + { 8,-6}, /* 8 */ + { 1,-6}, /* 9 */ + {-10,-3}, /* 10 */ + {-24,-2}, /* 11 */ + {-24, 2}, /* 0 close boundary */ + }; + XPoint a[XtNumber(club)]; + + /* Avoid wrapping */ + if(s->y*sp->scale > MI_HEIGHT(mi) * 2) return; + + /* Translate and fake perspective */ + for(i = 0; i < XtNumber(club); i++) { + a[i].x = (short)(MI_WIDTH(mi)/2 + + (s->x + club[i].x*PERSPEC*sa)*sp->scale - + club[i].y*sqrt(sp->scale)*ca); + a[i].y = (short)(MI_HEIGHT(mi) - (s->y - club[i].x*ca)*sp->scale + + club[i].y*sa*sqrt(sp->scale)); + } + + if(color != MI_BLACK_PIXEL(mi)) { + /* Outline in black */ + XSetForeground(MI_DISPLAY(mi), MI_GC(mi), MI_BLACK_PIXEL(mi)); + XSetLineAttributes(MI_DISPLAY(mi), MI_GC(mi), 2, + LineSolid, CapRound, JoinRound); + XDrawLines(MI_DISPLAY(mi), MI_WINDOW(mi), MI_GC(mi), + a, XtNumber(a), CoordModeOrigin); + } + + XSetForeground(MI_DISPLAY(mi), MI_GC(mi), color); + + /* Don't be tempted to optimize erase by drawing all the black in + one X operation. It must use the same ops as the colours to + guarantee a clean erase. */ + + i = 0; /* Colored stripes */ + p[i++] = a[1]; p[i++] = a[2]; + p[i++] = a[9]; p[i++] = a[10]; + XFillPolygon(MI_DISPLAY(mi), MI_WINDOW(mi), MI_GC(mi), + p, i, Convex, CoordModeOrigin); + i = 0; + p[i++] = a[3]; p[i++] = a[4]; + p[i++] = a[7]; p[i++] = a[8]; + XFillPolygon(MI_DISPLAY(mi), MI_WINDOW(mi), MI_GC(mi), + p, i, Convex, CoordModeOrigin); + + if(color != MI_BLACK_PIXEL(mi)) { + XSetForeground(MI_DISPLAY(mi), MI_GC(mi), MI_WHITE_PIXEL(mi)); + } + + i = 0; /* White center band */ + p[i++] = a[2]; p[i++] = a[3]; p[i++] = a[8]; p[i++] = a[9]; + XFillPolygon(MI_DISPLAY(mi), MI_WINDOW(mi), MI_GC(mi), + p, i, Convex, CoordModeOrigin); + + i = 0; /* White handle */ + p[i++] = a[0]; p[i++] = a[1]; p[i++] = a[10]; p[i++] = a[11]; + XFillPolygon(MI_DISPLAY(mi), MI_WINDOW(mi), MI_GC(mi), + p, i, Convex, CoordModeOrigin); + + i = 0; /* White tip */ + p[i++] = a[4]; p[i++] = a[5]; p[i++] = a[6]; p[i++] = a[7]; + XFillPolygon(MI_DISPLAY(mi), MI_WINDOW(mi), MI_GC(mi), + p, i, Convex, CoordModeOrigin); +} + +#if 0 +static void +show_jugglebugclub(ModeInfo *mi, unsigned long color, Trace *s) +{ + jugglestruct *sp = &juggles[MI_SCREEN(mi)]; + XPoint p[6]; + const double sa = sin(s->angle); + const double ca = cos(s->angle); + unsigned int i; + + /* 4 5 + +-+ + / \ + 3 +-----+ 6 + ////////\ + 2 +/////////+ 7 + |///////| + 1 +-------+ 8 + | | + | | + | | + | | + | | + | | + +-+ + 0 9 */ + + static const XPoint club[] = { + {-24, 2}, /* 0 */ + { -9, 3}, /* 1 */ + { 5, 6}, /* 2 */ + { 11, 4}, /* 3 */ + { 16, 3}, /* 4 */ + { 16,-3}, /* 5 */ + { 11,-4}, /* 6 */ + { 5,-6}, /* 7 */ + { -9,-3}, /* 8 */ + {-24,-2}, /* 9 */ + {-24, 2}, /* 0 close boundary */ + }; + XPoint a[XtNumber(club)]; + + /* Avoid wrapping */ + if(s->y*sp->scale > MI_HEIGHT(mi) * 2) return; + + /* Translate and fake perspective */ + for(i = 0; i < XtNumber(club); i++) { + a[i].x = (short)(MI_WIDTH(mi)/2 + + (s->x + club[i].x*PERSPEC*sa)*sp->scale - + club[i].y*sqrt(sp->scale)*ca); + a[i].y = (short)(MI_HEIGHT(mi) - (s->y - club[i].x*ca)*sp->scale + + club[i].y*sa*sqrt(sp->scale)); + } + + if(color != MI_BLACK_PIXEL(mi)) { + /* Outline in black */ + XSetForeground(MI_DISPLAY(mi), MI_GC(mi), MI_BLACK_PIXEL(mi)); + XSetLineAttributes(MI_DISPLAY(mi), MI_GC(mi), 2, + LineSolid, CapRound, JoinRound); + XDrawLines(MI_DISPLAY(mi), MI_WINDOW(mi), MI_GC(mi), + a, XtNumber(a), CoordModeOrigin); + } + + XSetForeground(MI_DISPLAY(mi), MI_GC(mi), color); + + /* Don't be tempted to optimize erase by drawing all the black in + one X operation. It must use the same ops as the colours to + guarantee a clean erase. */ + + i = 0; /* Coloured center band */ + p[i++] = a[1]; p[i++] = a[2]; p[i++] = a[3]; + p[i++] = a[6]; p[i++] = a[7]; p[i++] = a[8]; + XFillPolygon(MI_DISPLAY(mi), MI_WINDOW(mi), MI_GC(mi), + p, i, Convex, CoordModeOrigin); + + if(color != MI_BLACK_PIXEL(mi)) { + XSetForeground(MI_DISPLAY(mi), MI_GC(mi), MI_WHITE_PIXEL(mi)); + } + + i = 0; /* White handle */ + p[i++] = a[0]; p[i++] = a[1]; p[i++] = a[8]; p[i++] = a[9]; + XFillPolygon(MI_DISPLAY(mi), MI_WINDOW(mi), MI_GC(mi), + p, i, Convex, CoordModeOrigin); + + i = 0; /* White tip */ + p[i++] = a[3]; p[i++] = a[4]; p[i++] = a[5]; p[i++] = a[6]; + XFillPolygon(MI_DISPLAY(mi), MI_WINDOW(mi), MI_GC(mi), + p, i, Convex, CoordModeOrigin); +} +#endif + +static void +show_torch(ModeInfo *mi, unsigned long color, Trace *s) +{ + jugglestruct *sp = &juggles[MI_SCREEN(mi)]; + XPoint head, tail, last; + DXPoint dhead, dlast; + const double sa = sin(s->angle); + const double ca = cos(s->angle); + + const double TailLen = -24; + const double HeadLen = 16; + const short Width = (short)(5 * sqrt(sp->scale)); + + /* + +///+ head + last | + | + | + | + | + + tail + */ + + dhead.x = s->x + HeadLen * PERSPEC * sa; + dhead.y = s->y - HeadLen * ca; + + if(color == MI_BLACK_PIXEL(mi)) { /* Use 'last' when erasing */ + dlast = s->dlast; + } else { /* Store 'last' so we can use it later when s->prev has + gone */ + if(s->prev != s->next) { + dlast.x = s->prev->x + HeadLen * PERSPEC * sin(s->prev->angle); + dlast.y = s->prev->y - HeadLen * cos(s->prev->angle); + } else { + dlast = dhead; + } + s->dlast = dlast; + } + + /* Avoid wrapping (after last is stored) */ + if(s->y*sp->scale > MI_HEIGHT(mi) * 2) return; + + head.x = (short)(MI_WIDTH(mi)/2 + dhead.x*sp->scale); + head.y = (short)(MI_HEIGHT(mi) - dhead.y*sp->scale); + + last.x = (short)(MI_WIDTH(mi)/2 + dlast.x*sp->scale); + last.y = (short)(MI_HEIGHT(mi) - dlast.y*sp->scale); + + tail.x = (short)(MI_WIDTH(mi)/2 + + (s->x + TailLen * PERSPEC * sa)*sp->scale ); + tail.y = (short)(MI_HEIGHT(mi) - (s->y - TailLen * ca)*sp->scale ); + + if(color != MI_BLACK_PIXEL(mi)) { + XSetForeground(MI_DISPLAY(mi), MI_GC(mi), MI_BLACK_PIXEL(mi)); + XSetLineAttributes(MI_DISPLAY(mi), MI_GC(mi), + Width, LineSolid, CapRound, JoinRound); + XDrawLine(MI_DISPLAY(mi), MI_WINDOW(mi), MI_GC(mi), + head.x, head.y, tail.x, tail.y); + } + XSetForeground(MI_DISPLAY(mi), MI_GC(mi), color); + XSetLineAttributes(MI_DISPLAY(mi), MI_GC(mi), + Width * 2, LineSolid, CapRound, JoinRound); + + XDrawLine(MI_DISPLAY(mi), MI_WINDOW(mi), MI_GC(mi), + head.x, head.y, last.x, last.y); + +} + +static void +show_knife(ModeInfo *mi, unsigned long color, Trace *s) +{ + jugglestruct *sp = &juggles[MI_SCREEN(mi)]; + unsigned int i; + const double sa = sin(s->angle); + const double ca = cos(s->angle); + + /* + 2 + + |+ 3 + || + 1 +++ 5 + |4| + | | + + 0 + */ + static const XPoint knife[] = { + {-24, 0}, /* 0 */ + { -5,-3}, /* 1 */ + { 16,-3}, /* 2 */ + { 12, 0}, /* 3 */ + { -5, 0}, /* 4 */ + { -5, 3}, /* 5 */ + }; + XPoint a[XtNumber(knife)], p[5]; + + /* Avoid wrapping */ + if(s->y*sp->scale > MI_HEIGHT(mi) * 2) return; + + /* Translate and fake perspective */ + for(i = 0; i < XtNumber(knife); i++) { + a[i].x = (short)(MI_WIDTH(mi)/2 + + (s->x + knife[i].x*PERSPEC*sa)*sp->scale - + knife[i].y*sqrt(sp->scale)*ca*PERSPEC); + a[i].y = (short)(MI_HEIGHT(mi) - (s->y - knife[i].x*ca)*sp->scale + + knife[i].y*sa*sqrt(sp->scale)); + } + + /* Handle */ + XSetForeground(MI_DISPLAY(mi), MI_GC(mi), color); + XSetLineAttributes(MI_DISPLAY(mi), MI_GC(mi), (short)(4*sqrt(sp->scale)), + LineSolid, CapRound, JoinRound); + XDrawLine(MI_DISPLAY(mi), MI_WINDOW(mi), MI_GC(mi), + a[0].x, a[0].y, a[4].x, a[4].y); + + /* Blade */ + if(color != MI_BLACK_PIXEL(mi)) { + XSetForeground(MI_DISPLAY(mi), MI_GC(mi), MI_WHITE_PIXEL(mi)); + } + i = 0; + p[i++] = a[1]; p[i++] = a[2]; p[i++] = a[3]; p[i++] = a[5]; + XFillPolygon(MI_DISPLAY(mi), MI_WINDOW(mi), MI_GC(mi), + p, i, Convex, CoordModeOrigin); +} + +static void +show_ring(ModeInfo *mi, unsigned long color, Trace *s) +{ + jugglestruct *sp = &juggles[MI_SCREEN(mi)]; + short x = (short)(MI_WIDTH(mi)/2 + s->x * sp->scale); + short y = (short)(MI_HEIGHT(mi) - s->y * sp->scale); + double radius = 15 * sp->scale; + short thickness = (short)(8 * sqrt(sp->scale)); + + /* Avoid wrapping */ + if(s->y*sp->scale > MI_HEIGHT(mi) * 2) return; + + XSetForeground(MI_DISPLAY(mi), MI_GC(mi), color); + XSetLineAttributes(MI_DISPLAY(mi), MI_GC(mi), + thickness, LineSolid, CapRound, JoinRound); + + XDrawArc(MI_DISPLAY(mi), MI_WINDOW(mi), MI_GC(mi), + (short)(x - radius*PERSPEC), (short)(y - radius), + (short)(2*radius*PERSPEC), (short)(2*radius), + 0, 23040); +} + + +static void +show_bball(ModeInfo *mi, unsigned long color, Trace *s) +{ + jugglestruct *sp = &juggles[MI_SCREEN(mi)]; + short x = (short)(MI_WIDTH(mi)/2 + s->x * sp->scale); + short y = (short)(MI_HEIGHT(mi) - s->y * sp->scale); + double radius = 12 * sp->scale; + int offset = (int)(s->angle*64*180/M_PI); + int holesize = (int)(3.0*sqrt(sp->scale)); + + /* Avoid wrapping */ + if(s->y*sp->scale > MI_HEIGHT(mi) * 2) return; + + XSetForeground(MI_DISPLAY(mi), MI_GC(mi), MI_BLACK_PIXEL(mi)); + XFillArc(MI_DISPLAY(mi), MI_WINDOW(mi), MI_GC(mi), + (short)(x - radius), (short)(y - radius), + (short)(2*radius), (short)(2*radius), + 0, 23040); + XSetForeground(MI_DISPLAY(mi), MI_GC(mi), color); + XSetLineAttributes(MI_DISPLAY(mi), MI_GC(mi), 2, + LineSolid, CapRound, JoinRound); + XDrawArc(MI_DISPLAY(mi), MI_WINDOW(mi), MI_GC(mi), + (short)(x - radius), (short)(y - radius), + (short)(2*radius), (short)(2*radius), + 0, 23040); + + /* Draw finger holes */ + XSetLineAttributes(MI_DISPLAY(mi), MI_GC(mi), holesize, + LineSolid, CapRound, JoinRound); + + XDrawArc(MI_DISPLAY(mi), MI_WINDOW(mi), MI_GC(mi), + (short)(x - radius*0.5), (short)(y - radius*0.5), + (short)(2*radius*0.5), (short)(2*radius*0.5), + (offset + 960) % 23040, 0); + XDrawArc(MI_DISPLAY(mi), MI_WINDOW(mi), MI_GC(mi), + (short)(x - radius*0.7), (short)(y - radius*0.7), + (short)(2*radius*0.7), (short)(2*radius*0.7), + (offset + 1920) % 23040, 0); + XDrawArc(MI_DISPLAY(mi), MI_WINDOW(mi), MI_GC(mi), + (short)(x - radius*0.7), (short)(y - radius*0.7), + (short)(2*radius*0.7), (short)(2*radius*0.7), + offset % 23040, 0); +} + +/************************************************************************** + * Public Functions * + * * + **************************************************************************/ + + +ENTRYPOINT void +release_juggle (ModeInfo * mi) +{ + if (juggles != NULL) { + int screen; + + for (screen = 0; screen < MI_NUM_SCREENS(mi); screen++) + free_juggle(&juggles[screen]); + free(juggles); + juggles = (jugglestruct *) NULL; + } +} + +/* FIXME: refill_juggle currently just appends new throws to the + * programme. This is fine if the programme is empty, but if there + * are still some trajectories left then it really should take these + * into account */ + +static void +refill_juggle(ModeInfo * mi) +{ + jugglestruct *sp = NULL; + int i; + + if (juggles == NULL) + return; + sp = &juggles[MI_SCREEN(mi)]; + + /* generate pattern */ + if (pattern == NULL) { + +#define MAXPAT 10 +#define MAXREPEAT 300 +#define CHANGE_BIAS 8 /* larger makes num_ball changes less likely */ +#define POSITION_BIAS 20 /* larger makes hand movements less likely */ + + int count = 0; + while (count < MI_CYCLES(mi)) { + char buf[MAXPAT * 3 + 3], *b = buf; + int maxseen = 0; + int l = NRAND(MAXPAT) + 1; + int t = NRAND(MIN(MAXREPEAT, (MI_CYCLES(mi) - count))) + 1; + + { /* vary number of balls */ + int new_balls = sp->num_balls; + int change; + + if (new_balls == 2) /* Do not juggle 2 that often */ + change = NRAND(2 + CHANGE_BIAS / 4); + else + change = NRAND(2 + CHANGE_BIAS); + switch (change) { + case 0: + new_balls++; + break; + case 1: + new_balls--; + break; + default: + break; /* NO-OP */ + } + if (new_balls < sp->patternindex.minballs) { + new_balls += 2; + } + if (new_balls > sp->patternindex.maxballs) { + new_balls -= 2; + } + if (new_balls < sp->num_balls) { + if (!program(mi, "[*]", NULL, 1)) /* lose ball */ + return; + } + sp->num_balls = new_balls; + } + + count += t; + if (NRAND(2) && sp->patternindex.index[sp->num_balls].number) { + /* Pick from PortFolio */ + int p = sp->patternindex.index[sp->num_balls].start + + NRAND(sp->patternindex.index[sp->num_balls].number); + if (!program(mi, portfolio[p].pattern, portfolio[p].name, t)) + return; + } else { + /* Invent a new pattern */ + *b++='['; + for(i = 0; i < l; i++){ + int n, m; + do { /* Triangular Distribution => high values more likely */ + m = NRAND(sp->num_balls + 1); + n = NRAND(sp->num_balls + 1); + } while(m >= n); + if (n == sp->num_balls) { + maxseen = 1; + } + switch(NRAND(5 + POSITION_BIAS)){ + case 0: /* Outside throw */ + *b++ = '+'; break; + case 1: /* Cross throw */ + *b++ = '='; break; + case 2: /* Cross catch */ + *b++ = '&'; break; + case 3: /* Cross throw and catch */ + *b++ = 'x'; break; + case 4: /* Bounce */ + *b++ = '_'; break; + default: + break; /* Inside throw (default) */ + } + + *b++ = n + '0'; + *b++ = ' '; + } + *b++ = ']'; + *b = '\0'; + if (maxseen) { + if (!program(mi, buf, NULL, t)) + return; + } + } + } + } else { /* pattern supplied in height or 'a' notation */ + if (!program(mi, pattern, NULL, MI_CYCLES(mi))) + return; + } + + adam(sp); + + name(sp); + + if (!part(sp)) + return; + + lob(mi); + + clap(sp); + + positions(sp); + + if (!projectile(sp)) { + free_juggle(sp); + return; + } + + hands(sp); +#ifdef DEBUG + if(MI_IS_DEBUG(mi)) dump(sp); +#endif +} + +static void +change_juggle(ModeInfo * mi) +{ + jugglestruct *sp = NULL; + Trajectory *t; + + if (juggles == NULL) + return; + sp = &juggles[MI_SCREEN(mi)]; + + /* Strip pending trajectories */ + for (t = sp->head->next; t != sp->head; t = t->next) { + if(t->start > sp->time || t->finish < sp->time) { + Trajectory *n = t; + t=t->prev; + trajectory_destroy(n); + } + } + + /* Pick the current object theme */ + sp->objtypes = choose_object(); + + refill_juggle(mi); + + /* Clean up the Screen. Don't use MI_CLEARWINDOW(mi), since we + don't all those special effects. */ + XClearWindow(MI_DISPLAY(mi), MI_WINDOW(mi)); + + show_figure(mi, MI_WHITE_PIXEL(mi), True); + +} + +ENTRYPOINT void +init_juggle (ModeInfo * mi) +{ + jugglestruct *sp = 0; + int i; + + if (juggles == NULL) { /* First-time initialisation */ + + /* allocate jugglestruct */ + if ((juggles = + (jugglestruct *)calloc(MI_NUM_SCREENS(mi), + sizeof (jugglestruct))) == NULL) { + release_juggle(mi); + return; + } + } + + sp = &juggles[MI_SCREEN(mi)]; + + if (only && *only && strcmp(only, " ")) { + balls = clubs = torches = knives = rings = bballs = False; + if (!strcasecmp (only, "balls")) balls = True; + else if (!strcasecmp (only, "clubs")) clubs = True; + else if (!strcasecmp (only, "torches")) torches = True; + else if (!strcasecmp (only, "knives")) knives = True; + else if (!strcasecmp (only, "rings")) rings = True; + else if (!strcasecmp (only, "bballs")) bballs = True; + else { + (void) fprintf (stderr, + "Juggle: -only must be one of: balls, clubs, torches, knives,\n" + "\t rings, or bballs (not \"%s\")\n", only); +#ifdef STANDALONE /* xlock mustn't exit merely because of a bad argument */ + exit (1); +#endif + } + } + + if (sp->head == 0) { /* first time initializing this juggler */ + + sp->count = ABS(MI_COUNT(mi)); + if (sp->count == 0) + sp->count = 200; + + /* record start time */ + sp->begintime = time(NULL); + if(sp->patternindex.maxballs > 0) { + sp->num_balls = sp->patternindex.minballs + + NRAND(sp->patternindex.maxballs - sp->patternindex.minballs); + } + + show_figure(mi, MI_WHITE_PIXEL(mi), True); /* Draw figure. Also discovers + information about the juggler's + proportions */ + + /* "7" should be about three times the height of the juggler's + shoulders */ + sp->Gr = -GRAVITY(3 * sp->arm[0][RIGHT][SHOULDER].y, + 7 * THROW_CATCH_INTERVAL); + + if(!balls && !clubs && !torches && !knives && !rings && !bballs) + balls = True; /* Have to juggle something! */ + + /* create circular trajectory list */ + ADD_ELEMENT(Trajectory, sp->head, sp->head); + if(sp->head == NULL){ + free_juggle(sp); + return; + } + + /* create circular object list */ + ADD_ELEMENT(Object, sp->objects, sp->objects); + if(sp->objects == NULL){ + free_juggle(sp); + return; + } + + /* create circular wander list */ + ADD_ELEMENT(Wander, sp->wander, sp->wander); + if(sp->wander == NULL){ + free_juggle(sp); + return; + } + (void)wander(sp, 0); /* Initialize wander */ + + sp->pattern = strdup(""); /* Initialise saved pattern with + free-able memory */ + } + + sp = &juggles[MI_SCREEN(mi)]; + + if (pattern && + (!*pattern || + !strcasecmp (pattern, ".") || + !strcasecmp (pattern, "random"))) + pattern = NULL; + + if (pattern == NULL && sp->patternindex.maxballs == 0) { + /* pattern list needs indexing */ + int nelements = XtNumber(portfolio); + int numpat = 0; + + /* sort according to number of balls */ + qsort((void*)portfolio, nelements, + sizeof(portfolio[1]), compare_num_balls); + + /* last pattern has most balls */ + sp->patternindex.maxballs = get_num_balls(portfolio[nelements - 1].pattern); + /* run through sorted list, indexing start of each group + and number in group */ + sp->patternindex.maxballs = 1; + for (i = 0; i < nelements; i++) { + int b = get_num_balls(portfolio[i].pattern); + if (b > sp->patternindex.maxballs) { + sp->patternindex.index[sp->patternindex.maxballs].number = numpat; + if(numpat == 0) sp->patternindex.minballs = b; + sp->patternindex.maxballs = b; + numpat = 1; + sp->patternindex.index[sp->patternindex.maxballs].start = i; + } else { + numpat++; + } + } + sp->patternindex.index[sp->patternindex.maxballs].number = numpat; + } + + /* Set up programme */ + change_juggle(mi); + + /* Clean up the Screen. Don't use MI_CLEARWINDOW(mi), since we may + only be resizing and then we won't all those special effects. */ + XClearWindow(MI_DISPLAY(mi), MI_WINDOW(mi)); + + /* Only put things here that won't interrupt the programme during + a window resize */ + + /* Use MIN so that users can resize in interesting ways, eg + narrow windows for tall patterns, etc */ + sp->scale = MIN(MI_HEIGHT(mi)/480.0, MI_WIDTH(mi)/160.0); + + if(describe && !sp->mode_font) { /* Check to see if there's room to describe patterns. */ + char *font = get_string_resource (MI_DISPLAY(mi), "font", "Font"); + sp->mode_font = XLoadQueryFont(MI_DISPLAY(mi), font); + } +} + +ENTRYPOINT void +reshape_juggle (ModeInfo * mi, int width, int height) +{ + init_juggle(mi); +} + +ENTRYPOINT void +draw_juggle (ModeInfo * mi) +{ + Trajectory *traj = NULL; + Object *o = NULL; + unsigned long future = 0; + jugglestruct *sp = NULL; + char *pattern = NULL; + double cx; + + if (juggles == NULL) + return; + sp = &juggles[MI_SCREEN(mi)]; + + MI_IS_DRAWN(mi) = True; + +#ifdef HAVE_COCOA + /* Don't worry about flicker, trust Quartz's double-buffering. + This is a fast fix for the pixel-turds I can't track down... + */ + XClearWindow(MI_DISPLAY(mi), MI_WINDOW(mi)); +#endif + + /* Update timer */ + if (real) { + struct timeval tv; + (void)gettimeofday(&tv, NULL); + sp->time = (int) ((tv.tv_sec - sp->begintime)*1000 + tv.tv_usec/1000); + } else { + sp->time += MI_DELAY(mi) / 1000; + } + + /* First pass: Move arms and strip out expired elements */ + for (traj = sp->head->next; traj != sp->head; traj = traj->next) { + if (traj->status != PREDICTOR) { + /* Skip any elements that need further processing */ + /* We could remove them, but there shoudn't be many and they + would be needed if we ever got the pattern refiller + working */ + continue; + } + if (traj->start > future) { /* Lookahead to the end of the show */ + future = traj->start; + } + if (sp->time < traj->start) { /* early */ + continue; + } else if (sp->time < traj->finish) { /* working */ + + /* Look for pattern name */ + if(traj->pattern != NULL) { + pattern=traj->pattern; + } + + if (traj->type == Empty || traj->type == Full) { + /* Only interested in hands on this pass */ + double angle = traj->angle + traj->spin * (sp->time - traj->start); + double xd = 0, yd = 0; + DXPoint p; + + /* Find the catching offset */ + if(traj->object != NULL) { + if(ObjectDefs[traj->object->type].handle > 0) { + /* Handles Need to be oriented */ + xd = ObjectDefs[traj->object->type].handle * + PERSPEC * sin(angle); + yd = ObjectDefs[traj->object->type].handle * + cos(angle); + } else { + /* Balls are always caught at the bottom */ + xd = 0; + yd = -4; + } + } + p.x = (CUBIC(traj->xp, sp->time) - xd); + p.y = (CUBIC(traj->yp, sp->time) + yd); + reach_arm(mi, traj->hand, &p); + + /* Store updated hand position */ + traj->x = p.x + xd; + traj->y = p.y - yd; + } + if (traj->type == Ball || traj->type == Full) { + /* Only interested in objects on this pass */ + double x, y; + Trace *s; + + if(traj->type == Full) { + /* Adjusted these in the first pass */ + x = traj->x; + y = traj->y; + } else { + x = CUBIC(traj->xp, sp->time); + y = CUBIC(traj->yp, sp->time); + } + + ADD_ELEMENT(Trace, s, traj->object->trace->prev); + s->x = x; + s->y = y; + s->angle = traj->angle + traj->spin * (sp->time - traj->start); + s->divisions = traj->divisions; + traj->object->tracelen++; + traj->object->active = True; + } + } else { /* expired */ + Trajectory *n = traj; + traj=traj->prev; + trajectory_destroy(n); + } + } + + /* Erase end of trails */ + for (o = sp->objects->next; o != sp->objects; o = o->next) { + Trace *s; + for (s = o->trace->next; + o->trace->next != o->trace && + (o->count == 0 || o->tracelen > o->tail); + s = o->trace->next) { + ObjectDefs[o->type].draw(mi, MI_BLACK_PIXEL(mi), s); + REMOVE(s); + o->tracelen--; + if(o->count <= 0 && o->tracelen <= 0) { + /* Object no longer in use and trail gone */ + Object *n = o; + o = o->prev; + object_destroy(n); + } + if(o->count <= 0) break; /* Allow loop for catch-up, but not clean-up */ + } + } + + show_arms(mi, MI_BLACK_PIXEL(mi)); + cx = wander(sp, sp->time); + /* Reduce flicker by only permitting movements of more than a pixel */ + if(fabs((sp->cx - cx))*sp->scale >= 2.0 ) { + show_figure(mi, MI_BLACK_PIXEL(mi), False); + sp->cx = cx; + } + + show_figure(mi, MI_WHITE_PIXEL(mi), False); + + show_arms(mi, MI_WHITE_PIXEL(mi)); + + /* Draw Objects */ + for (o = sp->objects->next; o != sp->objects; o = o->next) { + if(o->active) { + ObjectDefs[o->type].draw(mi,MI_PIXEL(mi, o->color), o->trace->prev); + o->active = False; + } + } + + + /* Save pattern name so we can erase it when it changes */ + if(pattern != NULL && strcmp(sp->pattern, pattern) != 0 ) { + /* Erase old name */ + XSetForeground(MI_DISPLAY(mi), MI_GC(mi), MI_BLACK_PIXEL(mi)); +# if 0 + XDrawString(MI_DISPLAY(mi), MI_WINDOW(mi), MI_GC(mi), + 0, 20, sp->pattern, strlen(sp->pattern)); +# else + XFillRectangle(MI_DISPLAY(mi), MI_WINDOW(mi), MI_GC(mi), + 0, 0, MI_WIDTH(mi), 25); +# endif + free(sp->pattern); + sp->pattern = strdup(pattern); + + if (MI_IS_VERBOSE(mi)) { + (void) fprintf(stderr, "Juggle[%d]: Running: %s\n", + MI_SCREEN(mi), sp->pattern); + } + } + if(sp->mode_font != None && + XTextWidth(sp->mode_font, sp->pattern, strlen(sp->pattern)) < MI_WIDTH(mi)) { + /* Redraw once a cycle, in case it's obscured or it changed */ + XSetForeground(MI_DISPLAY(mi), MI_GC(mi), MI_WHITE_PIXEL(mi)); + XDrawImageString(MI_DISPLAY(mi), MI_WINDOW(mi), MI_GC(mi), + 0, 20, sp->pattern, strlen(sp->pattern)); + } + +#ifdef MEMTEST + if((int)(sp->time/10) % 1000 == 0) + (void) fprintf(stderr, "sbrk: %d\n", (int)sbrk(0)); +#endif + + if (future < sp->time + 100 * THROW_CATCH_INTERVAL) { + refill_juggle(mi); + } else if (sp->time > 1<<30) { /* Hard Reset before the clock wraps */ + release_juggle(mi); + init_juggle(mi); + } +} + +XSCREENSAVER_MODULE ("Juggle", juggle) + +#endif /* MODE_juggle */ diff --git a/hacks/juggle.man b/hacks/juggle.man new file mode 100644 index 00000000..17ea20b4 --- /dev/null +++ b/hacks/juggle.man @@ -0,0 +1,181 @@ +'\" t +.\" ** The above line should force tbl to be used as a preprocessor ** +.TH XScreenSaver 1 "" "X Version 11" +.SH NAME +juggle - juggling man screen saver. +.SH SYNOPSIS +.B juggle +[\-display host:display.screen ] +[\-root ] +[\-window ] +[\-mono ] +[\-install | \-noinstall ] +[\-visual visual ] +[\-window\-id id ] +[\-pattern pattern ] +[\-tail number ] +[\-real | \-no\-real ] +[\-describe | \-no\-describe ] +[\-balls | \-no\-balls ] +[\-clubs | \-no\-clubs ] +[\-torches | \-no\-torches ] +[\-knives | \-no\-knives ] +[\-rings | \-no\-rings ] +[\-bballs | \-no\-bballs ] +[\-count count ] +[\-cycles cycles ] +[\-delay delay ] +[\-ncolors ncolors ] +[\-fps] +.SH DESCRIPTION +Draws a stick-man juggling various collections of objects. +.SH OPTIONS +.I juggle +accepts the following options: +.TP 8 +.B \-display host:display.screen +X11 display to use. Overrides +.B DISPLAY +environment variable. +.TP 8 +.B \-root +Draw on the root window. +.TP 8 +.B \-window +Draw on a newly-created X window. This is the default. +.TP 8 +.B \-mono +Draw in monochrome. +.TP 8 +.B \-install | \-noinstall +Turn on/off installing colormap. +.TP 8 +.B \-visual visual +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\-id id +Draw on an already existing X window. +.TP 8 +.B \-pattern\ \(dq pattern \(dq +Specify juggling pattern in annotated +.B site-swap +notation. In +.B site-swap +notation, the "height" of each throw is given. E.g., "3" is the height +needed to juggle a 3\-Cascade. Note that these sequences need to be +chosen carefully, to avoid collisions. + +Annotations indicate relative hand movements or tricks: +.TS +cb l. +\&\- Inside throw (default) ++ Outside throw +\&= Cross Throw +& Cross Catch +x Cross Throw and Catch +\&_ Bounce +.TE +.TP 8 +.B \-pattern\ \(dq[ pattern ]\(dq +Specify juggling pattern in annotated +.B Adam +notation. Adam notation is a little harder to visualize. Each +integer +.B n +represents a cyclic permutation of (0...n). The equivalent +.B site-swap +value is determined by calculating how many of the permutations it +takes to get back to the identity. The largest number used is the +same as the number of objects in the pattern. The advantage of Adam +notation is that these sequences do not need to be chosen carefully, +since all possible sequences are juggle-able. Annotations are the same +as in +.B site-swap +notation. + +For example, both of these describe a 3\-Shower: +.IP +.B \-pattern\ "+5 1" +.IP +.B \-pattern\ "[+3 1]" + +For further examples, see the +.B portfolio +list in the source code. +.TP 8 +.B \-tail number +Minimum Trail Length. 0 \- 100. Default: 1. Objects may override +this, for example flaming torches always leave a trail. +.TP 8 +.BR \-real | \-no\-real +Turn on/off real-time juggling. +.B Deprecated. +There should be no need to turn off real-time juggling, even on slow +systems. Adjust speed using +.B \-count +above. +.TP 8 +.BR \-describe | \-no\-describe +Turn on/off pattern descriptions. +.TP 8 +.BR \-balls | \-no\-balls +Turn on/off Balls. +.TP 8 +.BR \-clubs | \-no\-clubs +Turn on/off Clubs. +.TP 8 +.BR \-torches | \-no\-torches +Turn on/off Flaming Torches. +.TP 8 +.BR \-knives | \-no\-knives +Turn on/off Knives. +.TP 8 +.BR \-rings | \-no\-rings +Turn on/off Rings. +.TP 8 +.BR \-bballs | \-no\-bballs +Turn on/off Bowling Balls. +.TP 8 +.B \-count number +Speed. 50 \- 1000. Default: 200. This determines the expected time +interval between a throw and the next catch, in milliseconds. +.TP 8 +.B \-cycles number +Performance Length. 50 \- 1000. Default: 1000. Setting this smaller +will force the juggler to switch patterns (and objects) more often. +.TP 8 +.B \-delay delay +Additional delay between frames, in microseconds. Default: 10000. +.B Deprecated. +Adjust speed using +.BR \-count . +.TP 8 +.B \-ncolors ncolors +Maximum number of colors to use. Default: 32. +.TP 8 +.B \-fps +Display the current frame rate and CPU load. +.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 1996,2000,2002,2004 by Tim Auckland. 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 +Tim Auckland. diff --git a/hacks/julia.c b/hacks/julia.c new file mode 100644 index 00000000..fe7ad436 --- /dev/null +++ b/hacks/julia.c @@ -0,0 +1,456 @@ +/* -*- Mode: C; tab-width: 4 -*- + * julia --- continuously varying Julia set. + */ +#if 0 +static const char sccsid[] = "@(#)julia.c 4.03 97/04/10 xlockmore"; +#endif + +/* Copyright (c) 1995 Sean McCullough . + * + * Permission to use, copy, modify, and distribute this software and its + * documentation for any purpose and without fee is hereby granted, + * provided that the above copyright notice appear in all copies and that + * both that copyright notice and this permission notice appear in + * supporting documentation. + * + * This file is provided AS IS with no warranties of any kind. The author + * shall have no liability with respect to the infringement of copyrights, + * trade secrets or any patents by this file or any part thereof. In no + * event will the author be liable for any lost revenue or profits or + * other special, indirect and consequential damages. + * + * Revision History: + * 10-Jun-06: j.grahl@ucl.ac.uk: tweaked functions for parameter of Julia set + * 28-May-97: jwz@jwz.org: added interactive frobbing with the mouse. + * 10-May-97: jwz@jwz.org: turned into a standalone program. + * 02-Dec-95: snagged boilerplate from hop.c + * used ifs {w0 = sqrt(x-c), w1 = -sqrt(x-c)} with random iteration + * to plot the julia set, and sinusoidially varied parameter for set + * and plotted parameter with a circle. + */ + +/*- + * One thing to note is that batchcount is the *depth* of the search tree, + * so the number of points computed is 2^batchcount - 1. I use 8 or 9 + * on a dx266 and it looks okay. The sinusoidal variation of the parameter + * might not be as interesting as it could, but it still gives an idea of + * the effect of the parameter. + */ + +#ifdef STANDALONE +# define DEFAULTS "*count: 1000 \n" \ + "*cycles: 20 \n" \ + "*delay: 10000 \n" \ + "*ncolors: 200 \n" \ + "*fpsSolid: true \n" \ + +# define UNIFORM_COLORS +# include "xlockmore.h" /* in xscreensaver distribution */ +#else /* !STANDALONE */ +# include "xlock.h" /* in xlockmore distribution */ +#endif /* !STANDALONE */ + + +#define DEF_MOUSE "False" + +ENTRYPOINT ModeSpecOpt julia_opts = { 0, }; + + +#define numpoints ((0x2<depth)-1) + +typedef struct { + int centerx; + int centery; /* center of the screen */ + double cr; + double ci; /* julia params */ + int depth; + int inc; + int circsize; + int erase; + int pix; + long itree; + int buffer; + int nbuffers; + int redrawing, redrawpos; + Pixmap pixmap; +#ifndef HAVE_COCOA + Cursor cursor; +#endif + GC stippledGC; + XPoint **pointBuffer; /* pointer for XDrawPoints */ + Bool button_down_p; + int mouse_x, mouse_y; + +} juliastruct; + +static juliastruct *julias = NULL; + +/* How many segments to draw per cycle when redrawing */ +#define REDRAWSTEP 3 + +static void +apply(juliastruct * jp, register double xr, register double xi, int d) +{ + double theta, r; + + jp->pointBuffer[jp->buffer][jp->itree].x = + (int) (0.5 * xr * jp->centerx + jp->centerx); + jp->pointBuffer[jp->buffer][jp->itree].y = + (int) (0.5 * xi * jp->centery + jp->centery); + jp->itree++; + + if (d > 0) { + xi -= jp->ci; + xr -= jp->cr; + +/* Avoid atan2: DOMAIN error message */ + if (xi == 0.0 && xr == 0.0) + theta = 0.0; + else + theta = atan2(xi, xr) / 2.0; + + /*r = pow(xi * xi + xr * xr, 0.25); */ + r = sqrt(sqrt(xi * xi + xr * xr)); /* 3 times faster */ + + xr = r * cos(theta); + xi = r * sin(theta); + + d--; + apply(jp, xr, xi, d); + apply(jp, -xr, -xi, d); + } +} + +static void +incr(ModeInfo * mi, juliastruct * jp) +{ + if (jp->button_down_p) + { + jp->cr = ((double) (jp->mouse_x + 2 - jp->centerx)) * 2 / jp->centerx; + jp->ci = ((double) (jp->mouse_y + 2 - jp->centery)) * 2 / jp->centery; + } + else + { +#if 0 + jp->cr = 1.5 * (sin(M_PI * (jp->inc / 300.0)) * + sin(jp->inc * M_PI / 200.0)); + jp->ci = 1.5 * (cos(M_PI * (jp->inc / 300.0)) * + cos(jp->inc * M_PI / 200.0)); + + jp->cr += 0.5 * cos(M_PI * jp->inc / 400.0); + jp->ci += 0.5 * sin(M_PI * jp->inc / 400.0); +#else + jp->cr = 1.5 * (sin(M_PI * (jp->inc / 290.0)) * + sin(jp->inc * M_PI / 210.0)); + jp->ci = 1.5 * (cos(M_PI * (jp->inc / 310.0)) * + cos(jp->inc * M_PI / 190.0)); + + jp->cr += 0.5 * cos(M_PI * jp->inc / 395.0); + jp->ci += 0.5 * sin(M_PI * jp->inc / 410.0); +#endif + } +} + +ENTRYPOINT void +init_julia(ModeInfo * mi) +{ + Display *display = MI_DISPLAY(mi); + Window window = MI_WINDOW(mi); + juliastruct *jp; + XGCValues gcv; + int i; + + if (julias == NULL) { + if ((julias = (juliastruct *) calloc(MI_NUM_SCREENS(mi), + sizeof (juliastruct))) == NULL) + return; + } + jp = &julias[MI_SCREEN(mi)]; + + jp->centerx = MI_WIN_WIDTH(mi) / 2; + jp->centery = MI_WIN_HEIGHT(mi) / 2; + + jp->depth = MI_BATCHCOUNT(mi); + if (jp->depth > 10) + jp->depth = 10; + + +#ifndef HAVE_COCOA + if (jp->button_down_p && !jp->cursor && !jp->cursor) + { + Pixmap bit; + XColor black; + black.red = black.green = black.blue = 0; + black.flags = DoRed|DoGreen|DoBlue; + bit = XCreatePixmapFromBitmapData (display, window, "\000", 1, 1, + MI_WIN_BLACK_PIXEL(mi), + MI_WIN_BLACK_PIXEL(mi), 1); + jp->cursor = XCreatePixmapCursor (display, bit, bit, &black, &black, + 0, 0); + XFreePixmap (display, bit); + } +#endif /* HAVE_COCOA */ + + if (jp->pixmap != None && + jp->circsize != (MIN(jp->centerx, jp->centery) / 60) * 2 + 1) { + XFreePixmap(display, jp->pixmap); + jp->pixmap = None; + } + if (jp->pixmap == None) { + GC fg_gc = None, bg_gc = None; + + jp->circsize = MAX(8, (MIN(jp->centerx, jp->centery) / 96) * 2 + 1); + jp->pixmap = XCreatePixmap(display, window, jp->circsize, jp->circsize, 1); + gcv.foreground = 1; + fg_gc = XCreateGC(display, jp->pixmap, GCForeground, &gcv); + gcv.foreground = 0; + bg_gc = XCreateGC(display, jp->pixmap, GCForeground, &gcv); + XFillRectangle(display, jp->pixmap, bg_gc, + 0, 0, jp->circsize, jp->circsize); + if (jp->circsize < 2) + XDrawPoint(display, jp->pixmap, fg_gc, 0, 0); + else + XFillArc(display, jp->pixmap, fg_gc, + 0, 0, jp->circsize, jp->circsize, 0, 23040); + if (fg_gc != None) + XFreeGC(display, fg_gc); + if (bg_gc != None) + XFreeGC(display, bg_gc); + } + +#ifndef HAVE_COCOA + if (MI_WIN_IS_INROOT(mi)) + ; + else if (jp->circsize > 0) + XDefineCursor (display, window, jp->cursor); + else + XUndefineCursor (display, window); +#endif /* HAVE_COCOA */ + + if (!jp->stippledGC) { + gcv.foreground = MI_WIN_BLACK_PIXEL(mi); + gcv.background = MI_WIN_BLACK_PIXEL(mi); + if ((jp->stippledGC = XCreateGC(display, window, + GCForeground | GCBackground, &gcv)) == None) + return; + } + if (MI_NPIXELS(mi) > 2) + jp->pix = NRAND(MI_NPIXELS(mi)); + jp->inc = ((LRAND() & 1) * 2 - 1) * NRAND(200); + jp->nbuffers = (MI_CYCLES(mi) + 1); + if (!jp->pointBuffer) + jp->pointBuffer = (XPoint **) calloc(jp->nbuffers, sizeof (XPoint *)); + for (i = 0; i < jp->nbuffers; ++i) + if (jp->pointBuffer[i]) + (void) memset((char *) jp->pointBuffer[i], 0, + numpoints * sizeof (XPoint)); + else + jp->pointBuffer[i] = (XPoint *) calloc(numpoints, sizeof (XPoint)); + jp->buffer = 0; + jp->redrawing = 0; + jp->erase = 0; + XClearWindow(display, window); +} + + +static void +reshape_julia (ModeInfo *mi, int w, int h) +{ + init_julia (mi); +} + + +ENTRYPOINT Bool +julia_handle_event (ModeInfo *mi, XEvent *event) +{ + juliastruct *jp = &julias[MI_SCREEN(mi)]; + + if (event->xany.type == ButtonPress && + event->xbutton.button == Button1) + { + jp->button_down_p = True; + jp->mouse_x = event->xbutton.x; + jp->mouse_y = event->xbutton.y; + return True; + } + else if (event->xany.type == ButtonRelease && + event->xbutton.button == Button1) + { + jp->button_down_p = False; + return True; + } + else if (event->xany.type == MotionNotify && jp->button_down_p) + { + jp->mouse_x = event->xmotion.x; + jp->mouse_y = event->xmotion.y; + return True; + } + + return False; +} + + + +/* hack: moved here by jwz. */ +#define ERASE_IMAGE(d,w,g,x,y,xl,yl,xs,ys) \ +if (yly) \ +(y>yl-ys)?XFillRectangle(d,w,g,xl,y+ys,xs,yl-y): \ +XFillRectangle(d,w,g,xl,yl,xs,ys); \ +if (xlx) \ +(x>xl-xs)?XFillRectangle(d,w,g,x+xs,yl,xl-x,ys): \ +XFillRectangle(d,w,g,xl,yl,xs,ys) + + +ENTRYPOINT void +draw_julia (ModeInfo * mi) +{ + Display *display = MI_DISPLAY(mi); + Window window = MI_WINDOW(mi); + GC gc = MI_GC(mi); + juliastruct *jp = &julias[MI_SCREEN(mi)]; + double r, theta; + register double xr = 0.0, xi = 0.0; + int k = 64, rnd = 0, i, j; + XPoint *xp = jp->pointBuffer[jp->buffer], old_circle, new_circle; + + old_circle.x = (int) (jp->centerx * jp->cr / 2) + jp->centerx - 2; + old_circle.y = (int) (jp->centery * jp->ci / 2) + jp->centery - 2; + incr(mi, jp); + new_circle.x = (int) (jp->centerx * jp->cr / 2) + jp->centerx - 2; + new_circle.y = (int) (jp->centery * jp->ci / 2) + jp->centery - 2; + XSetForeground(display, gc, MI_WIN_BLACK_PIXEL(mi)); + XFillArc(display, window, gc, + old_circle.x-jp->circsize/2-2, + old_circle.y-jp->circsize/2-2, + jp->circsize+4, jp->circsize+4, + 0, 360*64); + /* draw a circle at the c-parameter so you can see it's effect on the + structure of the julia set */ + XSetForeground(display, jp->stippledGC, MI_WIN_WHITE_PIXEL(mi)); +#ifndef HAVE_COCOA + XSetTSOrigin(display, jp->stippledGC, new_circle.x, new_circle.y); + XSetStipple(display, jp->stippledGC, jp->pixmap); + XSetFillStyle(display, jp->stippledGC, FillOpaqueStippled); +#endif /* HAVE_COCOA */ + XDrawArc(display, window, jp->stippledGC, + new_circle.x-jp->circsize/2, + new_circle.y-jp->circsize/2, + jp->circsize, jp->circsize, + 0, 360*64); + + if (jp->erase == 1) { + XDrawPoints(display, window, gc, + jp->pointBuffer[jp->buffer], numpoints, CoordModeOrigin); + } + jp->inc++; + if (MI_NPIXELS(mi) > 2) { + XSetForeground(display, gc, MI_PIXEL(mi, jp->pix)); + if (++jp->pix >= MI_NPIXELS(mi)) + jp->pix = 0; + } else + XSetForeground(display, gc, MI_WIN_WHITE_PIXEL(mi)); + while (k--) { + + /* save calls to LRAND by using bit shifts over and over on the same + int for 32 iterations, then get a new random int */ + if (!(k % 32)) + rnd = LRAND(); + + /* complex sqrt: x^0.5 = radius^0.5*(cos(theta/2) + i*sin(theta/2)) */ + + xi -= jp->ci; + xr -= jp->cr; + + /* Avoid atan2: DOMAIN error message */ + if (xi == 0.0 && xr == 0.0) + theta = 0.0; + else + theta = atan2(xi, xr) / 2.0; + + /*r = pow(xi * xi + xr * xr, 0.25); */ + r = sqrt(sqrt(xi * xi + xr * xr)); /* 3 times faster */ + + xr = r * cos(theta); + xi = r * sin(theta); + + if ((rnd >> (k % 32)) & 0x1) { + xi = -xi; + xr = -xr; + } + xp->x = jp->centerx + (int) ((jp->centerx >> 1) * xr); + xp->y = jp->centery + (int) ((jp->centery >> 1) * xi); + xp++; + } + + jp->itree = 0; + apply(jp, xr, xi, jp->depth); + + XDrawPoints(display, window, gc, + jp->pointBuffer[jp->buffer], numpoints, CoordModeOrigin); + + jp->buffer++; + if (jp->buffer > jp->nbuffers - 1) { + jp->buffer -= jp->nbuffers; + jp->erase = 1; + } + if (jp->redrawing) { + for (i = 0; i < REDRAWSTEP; i++) { + j = (jp->buffer - jp->redrawpos + jp->nbuffers) % jp->nbuffers; + XDrawPoints(display, window, gc, + jp->pointBuffer[j], numpoints, CoordModeOrigin); + + if (++(jp->redrawpos) >= jp->nbuffers) { + jp->redrawing = 0; + break; + } + } + } +} + +ENTRYPOINT void +release_julia (ModeInfo * mi) +{ + if (julias != NULL) { + int screen; + + for (screen = 0; screen < MI_NUM_SCREENS(mi); screen++) { + Display *display = MI_DISPLAY(mi); + juliastruct *jp = &julias[screen]; + int buffer; + + if (jp->pointBuffer) { + for (buffer = 0; buffer < jp->nbuffers; buffer++) + if (jp->pointBuffer[buffer]) + (void) free((void *) jp->pointBuffer[buffer]); + (void) free((void *) jp->pointBuffer); + } + if (jp->stippledGC != None) + XFreeGC(display, jp->stippledGC); + if (jp->pixmap != None) + XFreePixmap(display, jp->pixmap); +#ifndef HAVE_COCOA + if (jp->cursor) + XFreeCursor (display, jp->cursor); +#endif + } + (void) free((void *) julias); + julias = NULL; + } +} + +ENTRYPOINT void +refresh_julia (ModeInfo * mi) +{ + juliastruct *jp = &julias[MI_SCREEN(mi)]; + + jp->redrawing = 1; + jp->redrawpos = 0; +} + +XSCREENSAVER_MODULE ("Julia", julia) diff --git a/hacks/julia.man b/hacks/julia.man new file mode 100644 index 00000000..4e0f2e82 --- /dev/null +++ b/hacks/julia.man @@ -0,0 +1,81 @@ +.TH XScreenSaver 1 "28-May-97" "X Version 11" +.SH NAME +julia - draws spinning, animating julia-set fractals +.SH SYNOPSIS +.B julia +[\-display \fIhost:display.screen\fP] [\-foreground \fIcolor\fP] [\-background \fIcolor\fP] [\-window] [\-root] [\-mono] [\-install] [\-visual \fIvisual\fP] [\-ncolors \fIinteger\fP] [\-delay \fImicroseconds\fP] [\-cycles \fIinteger\fP] [\-count \fIinteger\fP] + +[\-fps] +.SH DESCRIPTION +The \fIjulia\fP program draws spinning, animating julia-set fractals. + +It uses ifs {w0 = sqrt(x-c), w1 = -sqrt(x-c)} with random iteration +to plot the julia set, and sinusoidially varied parameters for the set, +and plots parameters with a circle. + +One thing to note is that count is the \fIdepth\fP of the search tree, +so the number of points computed is (2^count)-1. I use 8 or 9 on a +dx266 and it looks okay. The sinusoidal variation of the parameter +might not be as interesting as it could, but it still gives an idea +of the effect of the parameter. + +Dragging the mouse in the window uses the mouse's position as the +control point for the generation of ths set. +.SH OPTIONS +.I julia +accepts the following options: +.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 \-mono +If on a color display, pretend we're on a monochrome display. +.TP 8 +.B \-install +Install a private colormap for the window. +.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 \-ncolors \fIinteger\fP +How many colors should be used (if possible). Default 200. +The colors used cycle through the hue, making N stops around +the color wheel. +.TP 8 +.B \-cycles \fIinteger\fP + +.TP 8 +.B \-count \fIinteger\fP +.TP 8 +.B \-fps +Display the current frame rate and CPU load. +.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), +.BR xlock (1) +.SH COPYRIGHT +Copyright \(co 1995 by Sean McCullough. + +Permission to use, copy, modify, and distribute this software and its +documentation for any purpose and without fee is hereby granted, +provided that the above copyright notice appear in all copies and that +both that copyright notice and this permission notice appear in +supporting documentation. +.SH AUTHOR +Sean McCullough , 1995. + +Ability to run standalone or with \fIxscreensaver\fP added by +Jamie Zawinski , 10-May-97. diff --git a/hacks/kaleidescope.c b/hacks/kaleidescope.c new file mode 100644 index 00000000..8c3f80b9 --- /dev/null +++ b/hacks/kaleidescope.c @@ -0,0 +1,487 @@ +/* kaleidescope, Copyright (c) 1997, 2006 Ron Tapia + * + * 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. + */ + +/* + * The above, for lack of a better copyright statement in easy reach + * was just lifted from the xscreensaver source. + * + * One of the odd things about this hack is that the radial motion of the + * segments depends on roundoff error alone. + * + * I tried to make the source easy to add other shapes. So far, I've + * only messed with elipses and I couldn't do much with them that looked + * cool. A nice addition would be to add some sort of spline based shapes. + * Maybe rectangles would look nice. + * + */ + +#include +#include +#include +#include "screenhack.h" +#include "spline.h" + +#define NEWX(x,y) ((x*g->costheta) + (y*g->sintheta)) +#define NEWY(x,y) ((y*g->costheta) - (x*g->sintheta)) + + +typedef struct state GLOBAL; +typedef struct Obj OBJECT; +struct Obj { + int type; + int time; + void (*propigate) (GLOBAL *, OBJECT *); + void (*draw) (GLOBAL *, OBJECT *); + void (*init) (GLOBAL *, OBJECT *); + void *cur; +}; + +typedef struct KSEGMENT { + struct KSEGMENT *next; + XColor color; + int drawn; + short int x1,y1,x2,y2; /* these are in the natural coordinate system */ + XSegment *xsegments; /* these are in the X coordinate system */ +} Ksegment; + +struct state { + int xoff, yoff; /* offset of origin xmax/2, ymax/2 */ + int xmax, ymax; /* width, height of window */ + float costheta, sintheta; + int symmetry; + int ntrails; + int nsegments; + int narcs; + int nobjects; + int local_rotation; + int global_rotation; + int spring_constant; + Colormap cmap; + GC draw_gc; + GC erase_gc; + unsigned int default_fg_pixel; + Display *dpy; + Window window; + unsigned long delay; + unsigned short redmin,redrange,greenmin,greenrange,bluemin,bluerange; + int color_mode; + + OBJECT *objects; + int counter; + + int done_once; +}; + + +static const char *kaleidescope_defaults [] = { + ".background: black", + ".foreground: white", + "*fpsSolid: true", + "*color_mode: nice", + "*symmetry: 11", + "*ntrails: 100", + "*nsegments: 7", + "*narcs: 0", + "*local_rotation: -59", + "*global_rotation: 1", + "*spring_constant: 5", + "*delay: 20000", + "*redmin: 30000", + "*redrange: 20000", + "*greenmin: 30000", + "*greenrange: 20000", + "*bluemin: 30000", + "*bluerange: 20000", + 0 +}; + +static XrmOptionDescRec kaleidescope_options [] = { + { "-color_mode", ".color_mode", XrmoptionSepArg, 0 }, + { "-symmetry", ".symmetry", XrmoptionSepArg, 0 }, + { "-nsegments", ".nsegments", XrmoptionSepArg, 0 }, + { "-ntrails", ".ntrails", XrmoptionSepArg, 0 }, + { "-local_rotation", ".local_rotation", XrmoptionSepArg, 0 }, + { "-global_rotation", ".global_rotation", XrmoptionSepArg, 0 }, + { "-delay", ".delay", XrmoptionSepArg, 0 }, + { "-spring_constant", ".spring_constant", XrmoptionSepArg, 0 }, + { "-redmin", ".redmin", XrmoptionSepArg, 0 }, + { "-redrange", ".redrange", XrmoptionSepArg, 0 }, + { "-bluemin", ".bluemin", XrmoptionSepArg, 0 }, + { "-bluerange", ".bluerange", XrmoptionSepArg, 0 }, + { "-greenmin", ".greenmin", XrmoptionSepArg, 0 }, + { "-greenrange", ".greenrange", XrmoptionSepArg, 0 }, + { 0, 0, 0, 0 } +}; + +/* END global variables */ + +static void +krandom_color(GLOBAL *g, XColor *color) +{ + if((g->color_mode == 0) || (g->color_mode == 1)) { + + color->blue = (random() % g->bluerange) + g->bluemin; + color->green = (random() % g->greenrange) + g->greenmin; + color->red = (random() % g->redrange) + g->redmin; + + if(!XAllocColor(g->dpy, g->cmap, color)) { + color->pixel = g->default_fg_pixel; + } + return; + } else { + color->pixel = g->default_fg_pixel; + return; + } +} + + +static void +kcopy_color(XColor *to, XColor *from) +{ + to->red = from->red; + to->green = from->green; + to->blue = from->blue; + to->pixel = from->pixel; +} + +static void +kcycle_color(GLOBAL *g, + XColor *color, + unsigned short redstep, + unsigned short greenstep, + unsigned short bluestep) +{ + unsigned short red,green,blue; + + if (! g->color_mode) { + XColor copy; + color->flags = DoRed|DoGreen|DoBlue; + color->red = (red = color->red) - redstep; + color->green = (green = color->green) - greenstep; + color->blue = (blue = color->blue) - bluestep; + copy = *color; + + if(!XAllocColor(g->dpy, g->cmap, color)) { + /* printf("couldn't alloc color...\n"); */ + color->pixel = g->default_fg_pixel; + } + copy.pixel = color->pixel; + *color = copy; + + color->red = red - redstep; + color->green = green- greenstep; + color->blue = blue - bluestep; + return; + } +} + + +static Ksegment * +create_ksegment (GLOBAL *g) +{ + Ksegment *seg, *prev; + XColor new_color; + int i; + unsigned short redstep,bluestep,greenstep; + + krandom_color(g, &new_color); + + redstep = new_color.red/(2 * g->ntrails); + greenstep = new_color.green/(2 * g->ntrails); + bluestep = new_color.blue/(2 * g->ntrails); + + seg = (Ksegment *) malloc(sizeof(Ksegment)); + seg->xsegments = (XSegment *) malloc(g->symmetry * sizeof(XSegment)); + + prev = seg; + for(i=0; i< (g->ntrails - 1); i++) { + + kcycle_color(g, &new_color,redstep,greenstep,bluestep); + + kcopy_color(&(prev->color), &new_color); + + prev->next = (Ksegment*)malloc(sizeof(Ksegment)); + (prev->next)->xsegments = (XSegment*)malloc(g->symmetry * sizeof(XSegment)); + prev->drawn = 0; + prev = (prev->next); + } + + prev->drawn = 0; + prev->next = seg; + kcopy_color(&(prev->color), &new_color); + + return seg; +} + +static void +init_ksegment (GLOBAL *g, OBJECT *obj) +{ + + /* Give the segment some random values */ + ((Ksegment *)obj->cur)->x1 = (g->xoff ? random() % g->xoff : 0); + ((Ksegment *)obj->cur)->y1 = (g->yoff ? random() % g->yoff : 0); + ((Ksegment *)obj->cur)->x2 = (g->xoff ? random() % g->xoff : 0); + ((Ksegment *)obj->cur)->y2 = (g->yoff ? random() % g->yoff : 0); +} + + +static void +draw_ksegment (GLOBAL *g, OBJECT *obj) +{ + register short x1, y1, x2, y2; + int dx, dy; + int i; + + g->counter++; + + x1 = ((Ksegment *)obj->cur)->x1; /* in the natural coordinate system */ + y1 = ((Ksegment *)obj->cur)->y1; + x2 = ((Ksegment *)obj->cur)->x2; + y2 = ((Ksegment *)obj->cur)->y2; + + dx = x2 - x1; + dy = y2 - y1; + + /* maybe throw away values and start over */ + if( ((dx*dx) + (dy * dy)) < 100) { + init_ksegment (g, obj); + x1 = ((Ksegment *)obj->cur)->x1; /* in the natural coordinate system */ + y1 = ((Ksegment *)obj->cur)->y1; + x2 = ((Ksegment *)obj->cur)->x2; + y2 = ((Ksegment *)obj->cur)->y2; + } + + for (i=0; isymmetry; i++) { + (((Ksegment *)obj->cur)->xsegments)[i].x1 = NEWX(x1,y1); + (((Ksegment *)obj->cur)->xsegments)[i].y1 = NEWY(x1,y1); + (((Ksegment *)obj->cur)->xsegments)[i].x2 = NEWX(x2,y2); + (((Ksegment *)obj->cur)->xsegments)[i].y2 = NEWY(x2,y2); + + (((Ksegment *)obj->cur)->xsegments)[i].x1 = (x1 = (((Ksegment *)obj->cur)->xsegments)[i].x1) + g->xoff; + (((Ksegment *)obj->cur)->xsegments)[i].y1 = (y1 = (((Ksegment *)obj->cur)->xsegments)[i].y1) + g->yoff; + (((Ksegment *)obj->cur)->xsegments)[i].x2 = (x2 = (((Ksegment *)obj->cur)->xsegments)[i].x2) + g->xoff; + (((Ksegment *)obj->cur)->xsegments)[i].y2 = (y2 = (((Ksegment *)obj->cur)->xsegments)[i].y2) + g->yoff; + } + + XSetForeground(g->dpy, g->draw_gc, (((Ksegment *)obj->cur)->color).pixel); + + XDrawSegments(g->dpy, g->window, g->draw_gc, ((Ksegment *)obj->cur)->xsegments, g->symmetry); + ((Ksegment *)obj->cur)->drawn = 1; + + if (((((Ksegment *)obj->cur)->next)->drawn) != 0) { + XDrawSegments(g->dpy, g->window, g->erase_gc, ((Ksegment *)obj->cur)->next->xsegments, g->symmetry); + } +} + +static void +propigate_ksegment(GLOBAL *g, OBJECT *obj) +{ + int t; + short int x1,y1,x2,y2; + short int midx,midy,nmidx,nmidy; + float lsin, lcos, gsin, gcos; + + lsin = sin((2*M_PI/10000)*g->local_rotation); + lcos = cos((2*M_PI/10000)*g->local_rotation); + gsin = sin((2*M_PI/10000)*g->global_rotation); + gcos = cos((2*M_PI/10000)*g->global_rotation); + + t=obj->time; + obj->time = t + 1; + + x1 = ((Ksegment *) obj->cur)->x1; + y1 = ((Ksegment *) obj->cur)->y1; + x2 = ((Ksegment *) obj->cur)->x2; + y2 = ((Ksegment *) obj->cur)->y2; + + midx = (x1 + x2)/2; + midy = (y1 + y2)/2; + + nmidx = midx*gcos + midy*gsin; + nmidy = midy*gcos - midx*gsin; + + x1 = x1 - midx; + x2 = x2 - midx; + y1 = y1 - midy; + y2 = y2 - midy; + + + /* This is where we move to the next ksegment... */ + obj->cur = ((Ksegment *)obj->cur)->next; + + ((Ksegment *)obj->cur)->x1 = ((x1*lcos) + (y1*lsin)) + nmidx; + ((Ksegment *)obj->cur)->y1 = ((y1*lcos) - (x1*lsin)) + nmidy; + ((Ksegment *)obj->cur)->x2 = ((x2*lcos) + (y2*lsin)) + nmidx; + ((Ksegment *)obj->cur)->y2 = ((y2*lcos) - (x2*lsin)) + nmidy; + + return ; +} + +static void +init_objects (GLOBAL *g) +{ + int i; + for (i=0; inobjects; i++) { + (g->objects[i].init)(g, g->objects + i); + } +} + +static void +create_objects (GLOBAL *g) +{ + int i; + + g->objects = (OBJECT *) malloc(g->nobjects * sizeof(OBJECT)); + + for (i=0; i< g->nsegments; i++) { + g->objects[i].cur = create_ksegment(g); + g->objects[i].type = 1; + g->objects[i].time = 0; + g->objects[i].propigate = propigate_ksegment; + g->objects[i].draw = draw_ksegment; + g->objects[i].init = init_ksegment; + } + + /* Here we can add creation functions for other object types. */ +} + + +static void +propigate_objects (GLOBAL *g) +{ + int i; + + for(i=0; inobjects; i++) { + g->objects[i].propigate(g, g->objects + i); + } +} + +static void +draw_objects (GLOBAL *g) +{ + int i; + + for(i=0; inobjects; i++) { + g->objects[i].draw(g, g->objects + i); + } +} + +static void +init_g (GLOBAL *g) +{ + XWindowAttributes xgwa; + XGCValues gcv; + char *color_mode_str; + + g->symmetry = get_integer_resource(g->dpy, "symmetry", "Integer"); + g->ntrails = get_integer_resource(g->dpy, "ntrails" , "Integer"); + g->nsegments = get_integer_resource(g->dpy, "nsegments", "Integer"); + g->narcs = get_integer_resource(g->dpy, "narcs", "Integer"); + g->local_rotation = get_integer_resource(g->dpy, "local_rotation", "Integer"); + g->global_rotation = get_integer_resource(g->dpy, "global_rotation", "Integer"); + g->spring_constant = get_integer_resource(g->dpy, "spring_constant", "Integer"); + g->delay = get_integer_resource(g->dpy, "delay", "Integer"); + g->nobjects = g->nsegments + g->narcs; + + color_mode_str = get_string_resource(g->dpy, "color_mode", "color_mode"); + + /* make into an enum... */ + if(!color_mode_str) { + g->color_mode = 0; + } else if (!strcmp(color_mode_str, "greedy")) { + g->color_mode = 0; + } else if (!strcmp(color_mode_str, "nice")) { + g->color_mode = 1; + } else { + g->color_mode = 2; + } + + XGetWindowAttributes (g->dpy, g->window, &xgwa); + g->xmax = xgwa.width; + g->ymax = xgwa.height; + g->xoff = g->xmax/2; + g->yoff = g->ymax/2; + g->costheta = cos(2*M_PI/g->symmetry); + g->sintheta = sin(2*M_PI/g->symmetry); + g->cmap = xgwa.colormap; + + g->redmin = get_integer_resource(g->dpy, "redmin", "Integer"); + g->redrange = get_integer_resource(g->dpy, "redrange", "Integer"); + g->greenmin = get_integer_resource(g->dpy, "greenmin", "Integer"); + g->greenrange = get_integer_resource(g->dpy, "greenrange", "Integer"); + g->bluemin = get_integer_resource(g->dpy, "bluemin", "Integer"); + g->bluerange = get_integer_resource(g->dpy, "bluerange", "Integer"); + + gcv.line_width = 1; + gcv.cap_style = CapRound; + gcv.foreground = g->default_fg_pixel = get_pixel_resource (g->dpy, g->cmap, "foreground", "Foreground"); + g->draw_gc = XCreateGC (g->dpy, g->window, GCForeground|GCLineWidth|GCCapStyle, &gcv); + + gcv.foreground = get_pixel_resource (g->dpy, g->cmap, "background", "Background"); + g->erase_gc = XCreateGC (g->dpy, g->window, GCForeground|GCLineWidth|GCCapStyle,&gcv); + +# ifdef HAVE_COCOA + jwxyz_XSetAntiAliasing (g->dpy, g->draw_gc, False); + jwxyz_XSetAntiAliasing (g->dpy, g->erase_gc, False); +# endif + + +} + +static void * +kaleidescope_init (Display *dpy, Window window) +{ + GLOBAL *g = (GLOBAL *) calloc (1, sizeof(*g)); + g->dpy = dpy; + g->window = window; + init_g (g); + create_objects(g); + init_objects (g); + return g; +} + +static unsigned long +kaleidescope_draw (Display *dpy, Window window, void *closure) +{ + GLOBAL *g = (GLOBAL *) closure; + if (g->done_once) + propigate_objects(g); + else + g->done_once = 1; + draw_objects (g); + return g->delay; +} + +static void +kaleidescope_reshape (Display *dpy, Window window, void *closure, + unsigned int w, unsigned int h) +{ + GLOBAL *g = (GLOBAL *) closure; + g->xmax = w; + g->ymax = h; + g->xoff = g->xmax/2; + g->yoff = g->ymax/2; +} + +static Bool +kaleidescope_event (Display *dpy, Window window, void *closure, XEvent *event) +{ + return False; +} + +static void +kaleidescope_free (Display *dpy, Window window, void *closure) +{ + GLOBAL *g = (GLOBAL *) closure; + free (g); +} + +XSCREENSAVER_MODULE ("Kaleidescope", kaleidescope) diff --git a/hacks/kaleidescope.man b/hacks/kaleidescope.man new file mode 100644 index 00000000..2c9ba2b7 --- /dev/null +++ b/hacks/kaleidescope.man @@ -0,0 +1,89 @@ +.de EX \"Begin example +.ne 5 +.if n .sp 1 +.if t .sp .5 +.nf +.in +.5i +.. +.de EE +.fi +.in -.5i +.if n .sp 1 +.if t .sp .5 +.. +.TH Kaleidescpe 1 "14-Dec-95" "X Version 11" +.SH NAME +Kaleidescope - rotating line segments +.SH SYNOPSIS +.B kaleidescope +[\-display \fIhost:display.screen\fP] [\-foreground \fIcolor\fP] [\-background \fIcolor\fP] [\-window] [\-root] [\-install] [\-visual \fIvisual\fP] [\-color_mode \fImono | nice | greedy\fP] [-nsegments \fIint\fP] [\-ntrails \fIint\fP] [\-local_rotation \fIint\fP] [\-global_rotation \fIint\fP] [\-delay \fIusecs\fP] [\-redmin \fIint\fP] [\-greenmin \fIint\fP] [\-bluemin \fIint\fP] [\-redrange \fIint\fP] [\-greenrange \fIint\fP] [\-bluerange \fIint\fP] +[\-fps] +.SH DESCRIPTION +The \fIkaleidescope\fP program draws line segments in a symmetric pattern +that evolves over time. +.SH OPTIONS +.I kaleidescope +accepts the following options: +.TP 8 +.B \-root +Draw on the root window. +.TP 8 +.B \-color_mode "mono | nice | greedy" +Specify how kaleidescope uses colors. Mono uses +just the default foreground and background colors. Nice uses one +color for each segment (specified by nsegments). Greedy uses (ntrails * nsegments) + 1 colors. +.TP 8 +.B \-install +Install a private colormap for the window. +.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 \-nsegments integer +The number of segments to draw. Default is 7. +.TP 8 +.B \-ntrails integer +The number of trails to draw. Default is 100. +.TP 8 +.B \-local_rotation integer +The rate at which segments rotate around their center. Default is -59. +.TP 8 +.B \-global_rotation integer +The rate at which segments rotate around the center of the window. +Default is 1. +.TP 8 +.B \-redmin, \-greenmin, \-bluemin, \-redrange, \-greenrange, \-bluerange +All take an integer argument. When colors are randomly chosen, they +are chosen from the interval min to min plus range. The minimums default +to 30000. The ranges default to 20000. +.TP 8 +.B \-delay microseconds +How much of a delay should be introduced between steps of the animation. +Default is 20000, or about 5 frames a second. +.TP 8 +.B \-fps +Display the current frame rate and CPU load. +.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 kaleidescope (MANSUFFIX) +.SH COPYRIGHT +Copyright \(co 1997 by Ron Tapia. 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 +Ron Tapia , 20-Mar-97. + diff --git a/hacks/kumppa.c b/hacks/kumppa.c new file mode 100644 index 00000000..b835f5bf --- /dev/null +++ b/hacks/kumppa.c @@ -0,0 +1,533 @@ +/* + +Copyright (C) Teemu Suutari (temisu@utu.fi) Feb 1998 + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be included +in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR +OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of the X Consortium shall +not be used in advertising or otherwise to promote the sale, use or +other dealings in this Software without prior written authorization +from the X Consortium. + +*/ + + + + +/* + +*** This is contest-version. Don't look any further, code is *very* ugly. + +*/ + +#include +#include "screenhack.h" + +#ifdef HAVE_DOUBLE_BUFFER_EXTENSION +# include "xdbe.h" +#endif /* HAVE_DOUBLE_BUFFER_EXTENSION */ + +#undef countof +#define countof(x) (sizeof((x))/sizeof((*x))) + +static const char *kumppa_defaults [] ={ + ".background: black", + "*fpsSolid: true", + "*speed: 0.1", + "*delay: 10000", + "*random: True", + /* leave this off by default, since it slows things down. -- jwz. */ + "*useDBE: False", + 0 +}; + +static XrmOptionDescRec kumppa_options [] = { + {"-delay", ".delay", XrmoptionSepArg, 0 }, + {"-speed", ".speed", XrmoptionSepArg, 0 }, + {"-random", ".random", XrmoptionNoArg, "True" }, + {"-no-random", ".random", XrmoptionNoArg, "False" }, + {"-db", ".useDBE", XrmoptionNoArg, "True" }, + {"-no-db", ".useDBE", XrmoptionNoArg, "False" }, + {0,0,0,0} +}; + +static const unsigned char colors[96]= + {0,0,255, 0,51,255, 0,102,255, 0,153,255, 0,204,255, + 0,255,255,0,255,204, 0,255,153, 0,255,102, 0,255,51, + 0,255,0, 51,255,0, 102,255,0, 153,255,0, 204,255,0, + 255,255,0, 255,204,0, 255,153,0, 255,102,0, 255,51,0, + 255,0,0, 255,0,51, 255,0,102, 255,0,153, 255,0,204, + 255,0,255, 219,0,255, 182,0,255, 146,0,255, 109,0,255, + 73,0,255, 37,0,255}; +static const float cosinus[8][6]= + {{-0.07,0.12,-0.06,32,25,37},{0.08,-0.03,0.05,51,46,32},{0.12,0.07,-0.13,27,45,36}, + {0.05,-0.04,-0.07,36,27,39},{-0.02,-0.07,0.1,21,43,42},{-0.11,0.06,0.02,51,25,34},{0.04,-0.15,0.02,42,32,25}, + {-0.02,-0.04,-0.13,34,20,15}}; + + +struct state { + Display *dpy; + Window win[2]; + + float acosinus[8][3]; + int coords[8]; + int ocoords[8]; + + GC fgc[33]; + GC cgc; + int sizx,sizy; + int midx,midy; + unsigned long delay; + Bool cosilines; + + int *Xrotations; + int *Yrotations; + int *Xrottable; + int *Yrottable; + + int *rotateX; + int *rotateY; + + int rotsizeX,rotsizeY; + int stateX,stateY; + + int rx,ry; + +#ifdef HAVE_DOUBLE_BUFFER_EXTENSION + XdbeSwapInfo xdswp; + Bool usedouble; +#endif /* HAVE_DOUBLE_BUFFER_EXTENSION */ + + int draw_count; +}; + + +static int Satnum(int maxi) +{ + return (int)(maxi*frand(1)); +} + + +static void palaRotate(struct state *st, int x,int y) +{ + int ax,ay,bx,by,cx,cy; + + ax=st->rotateX[x]; + ay=st->rotateY[y]; + bx=st->rotateX[x+1]+2; + by=st->rotateY[y+1]+2; + cx=st->rotateX[x]-(y-st->ry)+x-st->rx; + cy=st->rotateY[y]+(x-st->rx)+y-st->ry; + if (cx<0) + { + ax-=cx; + cx=0; + } + if (cy<0) + { + ay-=cy; + cy=0; + } + if (cx+bx-ax>st->sizx) bx=ax-cx+st->sizx; + if (cy+by-ay>st->sizy) by=ay-cy+st->sizy; + if (axdpy,st->win[0],st->win[1],st->cgc,ax,ay,bx-ax,by-ay,cx,cy); +} + + +static void rotate(struct state *st) +{ + int x,y; + int dx,dy; + + st->rx=st->Xrottable[st->stateX+1]-st->Xrottable[st->stateX]; + st->ry=st->Yrottable[st->stateY+1]-st->Yrottable[st->stateY]; + + + for (x=0;x<=st->rx;x++) + st->rotateX[x]=(x)?st->midx-1-st->Xrotations[st->Xrottable[st->stateX+1]-x]:0; + for (x=0;x<=st->rx;x++) + st->rotateX[x+st->rx+1]=(x==st->rx)?st->sizx-1:st->midx+st->Xrotations[st->Xrottable[st->stateX]+x]; + for (y=0;y<=st->ry;y++) + st->rotateY[y]=(y)?st->midy-1-st->Yrotations[st->Yrottable[st->stateY+1]-y]:0; + for (y=0;y<=st->ry;y++) + st->rotateY[y+st->ry+1]=(y==st->ry)?st->sizy-1:st->midy+st->Yrotations[st->Yrottable[st->stateY]+y]; + + x=(st->rx>st->ry)?st->rx:st->ry; + for (dy=0;dy<(x+1)<<1;dy++) + for (dx=0;dx<(x+1)<<1;dx++) + { + y=(st->rx>st->ry)?st->ry-st->rx:0; + if (dy+y>=0 && dy<(st->ry+1)<<1 && dx<(st->rx+1)<<1) + if (dy+y+dx<=st->ry+st->rx && dy+y-dx<=st->ry-st->rx) + { + palaRotate(st, (st->rx<<1)+1-dx,dy+y); + palaRotate(st, dx,(st->ry<<1)+1-dy-y); + } + y=(st->ry>st->rx)?st->rx-st->ry:0; + if (dy+y>=0 && dx<(st->ry+1)<<1 && dy<(st->rx+1)<<1) + if (dy+y+dx<=st->ry+st->rx && dx-dy-y>=st->ry-st->rx) + { + palaRotate(st, dy+y,dx); + palaRotate(st, (st->rx<<1)+1-dy-y,(st->ry<<1)+1-dx); + } + } + st->stateX++; + if (st->stateX==st->rotsizeX) st->stateX=0; + st->stateY++; + if (st->stateY==st->rotsizeY) st->stateY=0; +} + + + +static Bool make_rots(struct state *st, double xspeed,double yspeed) +{ + int a,b,c,f,g,j,k=0,l; + double m,om,ok; + double d,ix,iy; + int maxi; + + Bool *chks; + + st->rotsizeX=(int)(2/xspeed+1); + ix=(double)(st->midx+1)/(double)(st->rotsizeX); + st->rotsizeY=(int)(2/yspeed+1); + iy=(double)(st->midy+1)/(double)(st->rotsizeY); + + st->Xrotations=malloc((st->midx+2)*sizeof(unsigned int)); + st->Xrottable=malloc((st->rotsizeX+1)*sizeof(unsigned int)); + st->Yrotations=malloc((st->midy+2)*sizeof(unsigned int)); + st->Yrottable=malloc((st->rotsizeY+1)*sizeof(unsigned int)); + chks=malloc(((st->midx>st->midy)?st->midx:st->midy)*sizeof(Bool)); + if (!st->Xrottable || !st->Yrottable || !st->Xrotations || !st->Yrotations || !chks) return False; + + + maxi=0; + c=0; + d=0; + g=0; + for (a=0;amidx;a++) chks[a]=True; + for (a=0;arotsizeX;a++) + { + st->Xrottable[a]=c; + f=(int)(d+ix)-g; /*viivojen lkm.*/ + g+=f; + if (g>st->midx) + { + f-=g-st->midx; + g=st->midx; + } + for (b=0;bmidx;j++) /*testi*/ + { + if (chks[j]) + { + om=0; + ok=1; + l=0; + while (j+lmidx && om+12*ok>m) + { + if (j-l>=0) if (chks[j-l]) om+=ok; + else; else if (chks[l-j]) om+=ok; + if (chks[j+l]) om+=ok; + ok/=1.5; + l++; + } + if (om>=m) + { + k=j; + m=om; + } + } + } + chks[k]=False; + l=c; + while (l>=st->Xrottable[a]) + { + if (l!=st->Xrottable[a]) st->Xrotations[l]=st->Xrotations[l-1]; + if (k>st->Xrotations[l] || l==st->Xrottable[a]) + { + st->Xrotations[l]=k; + c++; + l=st->Xrottable[a]; + } + l--; + } + } + d+=ix; + if (maxiXrottable[a]) maxi=c-st->Xrottable[a]; + } + st->Xrottable[a]=c; + st->rotateX=malloc((maxi+2)*sizeof(int)<<1); + if (!st->rotateX) return False; + + maxi=0; + c=0; + d=0; + g=0; + for (a=0;amidy;a++) chks[a]=True; + for (a=0;arotsizeY;a++) + { + st->Yrottable[a]=c; + f=(int)(d+iy)-g; /*viivojen lkm.*/ + g+=f; + if (g>st->midy) + { + f-=g-st->midy; + g=st->midy; + } + for (b=0;bmidy;j++) /*testi*/ + { + if (chks[j]) + { + om=0; + ok=1; + l=0; + while (j+lmidy && om+12*ok>m) + { + if (j-l>=0) if (chks[j-l]) om+=ok; + else; else if (chks[l-j]) om+=ok; + if (chks[j+l]) om+=ok; + ok/=1.5; + l++; + } + if (om>=m) + { + k=j; + m=om; + } + } + } + chks[k]=False; + l=c; + while (l>=st->Yrottable[a]) + { + if (l!=st->Yrottable[a]) st->Yrotations[l]=st->Yrotations[l-1]; + if (k>st->Yrotations[l] || l==st->Yrottable[a]) + { + st->Yrotations[l]=k; + c++; + l=st->Yrottable[a]; + } + l--; + } + + } + d+=iy; + if (maxiYrottable[a]) maxi=c-st->Yrottable[a]; + } + st->Yrottable[a]=c; + st->rotateY=malloc((maxi+2)*sizeof(int)<<1); + if (!st->rotateY) return False; + + free(chks); + return (True); +} + + +static Bool InitializeAll(struct state *st) +{ + XGCValues xgcv; + XWindowAttributes xgwa; +/* XSetWindowAttributes xswa;*/ + Colormap cmap; + XColor color; + int n,i; + double rspeed; + + st->cosilines = True; + + XGetWindowAttributes(st->dpy,st->win[0],&xgwa); + cmap=xgwa.colormap; +/* xswa.backing_store=Always; + XChangeWindowAttributes(st->dpy,st->win[0],CWBackingStore,&xswa);*/ + xgcv.function=GXcopy; + + xgcv.foreground=get_pixel_resource (st->dpy, cmap, "background", "Background"); + st->fgc[32]=XCreateGC(st->dpy,st->win[0],GCForeground|GCFunction,&xgcv); + + n=0; + if (mono_p) + { + st->fgc[0]=st->fgc[32]; + xgcv.foreground=get_pixel_resource (st->dpy, cmap, "foreground", "Foreground"); + st->fgc[1]=XCreateGC(st->dpy,st->win[0],GCForeground|GCFunction,&xgcv); + for (i=0;i<32;i+=2) st->fgc[i]=st->fgc[0]; + for (i=1;i<32;i+=2) st->fgc[i]=st->fgc[1]; + } else + for (i=0;i<32;i++) + { + color.red=colors[n++]<<8; + color.green=colors[n++]<<8; + color.blue=colors[n++]<<8; + color.flags=DoRed|DoGreen|DoBlue; + XAllocColor(st->dpy,cmap,&color); + xgcv.foreground=color.pixel; + st->fgc[i]=XCreateGC(st->dpy,st->win[0],GCForeground|GCFunction,&xgcv); + } + st->cgc=XCreateGC(st->dpy,st->win[0],GCForeground|GCFunction,&xgcv); + XSetGraphicsExposures(st->dpy,st->cgc,False); + + st->cosilines = get_boolean_resource(st->dpy, "random","Boolean"); + +#ifdef HAVE_DOUBLE_BUFFER_EXTENSION + if (get_boolean_resource (st->dpy, "useDBE", "Boolean")) + st->usedouble = True; + st->win[1] = xdbe_get_backbuffer (st->dpy, st->win[0], XdbeUndefined); + if (!st->win[1]) + { + st->usedouble = False; + st->win[1] = st->win[0]; + } +#endif /* HAVE_DOUBLE_BUFFER_EXTENSION */ + + st->delay=get_integer_resource(st->dpy, "delay","Integer"); + rspeed=get_float_resource(st->dpy, "speed","Float"); + if (rspeed<0.0001 || rspeed>0.2) + { + fprintf(stderr,"Speed not in valid range! (0.0001 - 0.2), using 0.1 \n"); + rspeed=0.1; + } + + st->sizx=xgwa.width; + st->sizy=xgwa.height; + st->midx=st->sizx>>1; + st->midy=st->sizy>>1; + st->stateX=0; + st->stateY=0; + + if (!make_rots(st,rspeed,rspeed)) + { + fprintf(stderr,"Not enough memory for tables!\n"); + return False; + } + return True; +} + +static void * +kumppa_init (Display *d, Window w) +{ + struct state *st = (struct state *) calloc (1, sizeof(*st)); + st->dpy=d; + st->win[0]=w; + if (!InitializeAll(st)) abort(); + +#ifdef HAVE_DOUBLE_BUFFER_EXTENSION + if (st->usedouble) + { + st->xdswp.swap_action=XdbeUndefined; + st->xdswp.swap_window=st->win[0]; + } + else +#endif /* HAVE_DOUBLE_BUFFER_EXTENSION */ + st->win[1]=st->win[0]; + + return st; +} + +static unsigned long +kumppa_draw (Display *d, Window w, void *closure) +{ + struct state *st = (struct state *) closure; + if (st->cosilines) + { + int a; + st->draw_count++; + for (a=0;a<8;a++) + { + float f=0; + int b; + for (b=0;b<3;b++) + { + st->acosinus[a][b]+=cosinus[a][b]; + f+=cosinus[a][b+3]*sin((double)st->acosinus[a][b]); + } + st->coords[a]=(int)f; + } + for (a=0;a<4;a++) + { + XDrawLine(st->dpy,st->win[0],(mono_p)?st->fgc[1]:st->fgc[((a<<2)+st->draw_count)&31],st->midx+st->ocoords[a<<1],st->midy+st->ocoords[(a<<1)+1] + ,st->midx+st->coords[a<<1],st->midy+st->coords[(a<<1)+1]); + st->ocoords[a<<1]=st->coords[a<<1]; + st->ocoords[(a<<1)+1]=st->coords[(a<<1)+1]; + } + + } else { + int e; + for (e=0;e<8;e++) + { + int a=Satnum(50); + int b; + if (a>=32) a=32; + b=Satnum(32)-16+st->midx; + st->draw_count=Satnum(32)-16+st->midy; + XFillRectangle(st->dpy,st->win[0],st->fgc[a],b,st->draw_count,2,2); + } + } + XFillRectangle(st->dpy,st->win[0],st->fgc[32],st->midx-2,st->midy-2,4,4); + rotate(st); +#ifdef HAVE_DOUBLE_BUFFER_EXTENSION + if (st->usedouble) XdbeSwapBuffers(st->dpy,&st->xdswp,1); +#endif /* HAVE_DOUBLE_BUFFER_EXTENSION */ + + return st->delay; +} + + +static void +kumppa_reshape (Display *dpy, Window window, void *closure, + unsigned int w, unsigned int h) +{ + struct state *st = (struct state *) closure; + st->sizx=w; + st->sizy=w; + st->midx=st->sizx>>1; + st->midy=st->sizy>>1; + st->stateX=0; + st->stateY=0; +} + +static Bool +kumppa_event (Display *dpy, Window window, void *closure, XEvent *event) +{ + return False; +} + +static void +kumppa_free (Display *dpy, Window window, void *closure) +{ + struct state *st = (struct state *) closure; + int i; + for (i = 0; i < countof(st->fgc); i++) + if (st->fgc[i]) XFreeGC (dpy, st->fgc[i]); + XFreeGC (dpy, st->cgc); + free (st->Xrotations); + free (st->Yrotations); + free (st->Xrottable); + free (st->Yrottable); + free (st); +} + +XSCREENSAVER_MODULE ("Kumppa", kumppa) diff --git a/hacks/kumppa.man b/hacks/kumppa.man new file mode 100644 index 00000000..ed31a82e --- /dev/null +++ b/hacks/kumppa.man @@ -0,0 +1,65 @@ +.TH XScreenSaver 1 "" "X Version 11" +.SH NAME +kumppa - spiraling, spinning, splashes of color rush toward the screen. +.SH SYNOPSIS +.B kumppa +[\-display \fIhost:display.screen\fP] +[\-visual \fIvisual\fP] +[\-window] +[\-root] +[\-delay \fInumber\fP] +[\-speed \fInumber\fP] +[\-random] +[\-dbuf] +[\-fps] +.SH DESCRIPTION +Spiraling, spinning, and very, very fast splashes of color rush toward the +screen. +.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: 10000 (0.01 seconds.). +.TP 8 +.B \-speed \fInumber\fP +Density. 0.0001 - 0.2. Default: 0.1. +.TP 8 +.B \-random | \-no-random +Whether to randomize. +.TP 8 +.B \-dbuf | \-no-dbuf +Whether to double buffer. +.TP 8 +.B \-fps +Display the current frame rate and CPU load. +.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 2002 by Teemu Suutari. 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 +Teemu Suutari. diff --git a/hacks/laser.c b/hacks/laser.c new file mode 100644 index 00000000..e681f99d --- /dev/null +++ b/hacks/laser.c @@ -0,0 +1,366 @@ +/* -*- Mode: C; tab-width: 4 -*- */ +/* laser --- spinning lasers */ + +#if 0 +static const char sccsid[] = "@(#)laser.c 5.00 2000/11/01 xlockmore"; +#endif + +/*- + * Copyright (c) 1995 Pascal Pensa + * + * Permission to use, copy, modify, and distribute this software and its + * documentation for any purpose and without fee is hereby granted, + * provided that the above copyright notice appear in all copies and that + * both that copyright notice and this permission notice appear in + * supporting documentation. + * + * This file is provided AS IS with no warranties of any kind. The author + * shall have no liability with respect to the infringement of copyrights, + * trade secrets or any patents by this file or any part thereof. In no + * event will the author be liable for any lost revenue or profits or + * other special, indirect and consequential damages. + * + * Revision History: + * 01-Nov-2000: Allocation checks + * 10-May-1997: Compatible with xscreensaver + * 1995: Written. + */ + +#ifdef STANDALONE +# define MODE_laser +# define DEFAULTS "*delay: 40000 \n" \ + "*count: 10 \n" \ + "*cycles: 200 \n" \ + "*ncolors: 64 \n" \ + "*fpsSolid: true \n" \ + +# define BRIGHT_COLORS +# define reshape_laser 0 +# define laser_handle_event 0 +# include "xlockmore.h" /* in xscreensaver distribution */ +#else /* STANDALONE */ +# include "xlock.h" /* in xlockmore distribution */ +#endif /* STANDALONE */ + +#ifdef MODE_laser + +ENTRYPOINT ModeSpecOpt laser_opts = +{0, (XrmOptionDescRec *) NULL, 0, (argtype *) NULL, (OptionStruct *) NULL}; + +#ifdef USE_MODULES +ModStruct laser_description = +{"laser", "init_laser", "draw_laser", "release_laser", + "refresh_laser", "init_laser", (char *) NULL, &laser_opts, + 20000, -10, 200, 1, 64, 1.0, "", + "Shows spinning lasers", 0, NULL}; + +#endif + +#define MINREDRAW 3 /* Number of redrawn on each frame */ +#define MAXREDRAW 8 + +#define MINLASER 1 /* Laser number */ + +#define MINWIDTH 2 /* Laser ray width range */ +#define MAXWIDTH 40 + +#define MINSPEED 2 /* Speed range */ +#define MAXSPEED 17 + +#define MINDIST 10 /* Minimal distance from edges */ + +#define COLORSTEP 2 /* Laser color step */ + +#define RANGE_RAND(min,max) (int) ((min) + LRAND() % ((max) - (min))) + +typedef enum { + TOP, RIGHT, BOTTOM, LEFT +} border; + +typedef struct { + int bx; /* border x */ + int by; /* border y */ + border bn; /* active border */ + int dir; /* direction */ + int speed; /* laser velocity from MINSPEED to MAXSPEED */ + int sx[MAXWIDTH]; /* x stack */ + int sy[MAXWIDTH]; /* x stack */ + XGCValues gcv; /* for color */ +} laserstruct; + +typedef struct { + int width; + int height; + int cx; /* center x */ + int cy; /* center y */ + int lw; /* laser width */ + int ln; /* laser number */ + int lr; /* laser redraw */ + int sw; /* stack width */ + int so; /* stack offset */ + int time; /* up time */ + GC stippledGC; + XGCValues gcv_black; /* for black color */ + laserstruct *laser; +} lasersstruct; + +static lasersstruct *lasers = (lasersstruct *) NULL; + +static void +free_laser(Display *display, lasersstruct *lp) +{ + if (lp->laser != NULL) { + (void) free((void *) lp->laser); + lp->laser = (laserstruct *) NULL; + } + if (lp->stippledGC != None) { + XFreeGC(display, lp->stippledGC); + lp->stippledGC = None; + } +} + +ENTRYPOINT void +init_laser(ModeInfo * mi) +{ + Display *display = MI_DISPLAY(mi); + int i, c = 0; + lasersstruct *lp; + + if (lasers == NULL) { + if ((lasers = (lasersstruct *) calloc(MI_NUM_SCREENS(mi), + sizeof (lasersstruct))) == NULL) + return; + } + lp = &lasers[MI_SCREEN(mi)]; + + lp->width = MI_WIDTH(mi); + lp->height = MI_HEIGHT(mi); + lp->time = 0; + + lp->ln = MI_COUNT(mi); + if (lp->ln < -MINLASER) { + /* if lp->ln is random ... the size can change */ + if (lp->laser != NULL) { + (void) free((void *) lp->laser); + lp->laser = (laserstruct *) NULL; + } + lp->ln = NRAND(-lp->ln - MINLASER + 1) + MINLASER; + } else if (lp->ln < MINLASER) + lp->ln = MINLASER; + + if (lp->laser == NULL) { + if ((lp->laser = (laserstruct *) malloc(lp->ln * + sizeof (laserstruct))) == NULL) { + free_laser(display, lp); + return; + } + } + if (lp->stippledGC == None) { + XGCValues gcv; + + gcv.foreground = MI_WHITE_PIXEL(mi); + gcv.background = MI_BLACK_PIXEL(mi); + lp->gcv_black.foreground = MI_BLACK_PIXEL(mi); + if ((lp->stippledGC = XCreateGC(display, MI_WINDOW(mi), + GCForeground | GCBackground, &gcv)) == None) { + free_laser(display, lp); + return; + } +# ifdef HAVE_COCOA + jwxyz_XSetAntiAliasing (MI_DISPLAY(mi), lp->stippledGC, False); +# endif + } + MI_CLEARWINDOW(mi); + + if (MINDIST < lp->width - MINDIST) + lp->cx = RANGE_RAND(MINDIST, lp->width - MINDIST); + else + lp->cx = RANGE_RAND(0, lp->width); + if (MINDIST < lp->height - MINDIST) + lp->cy = RANGE_RAND(MINDIST, lp->height - MINDIST); + else + lp->cy = RANGE_RAND(0, lp->height); + lp->lw = RANGE_RAND(MINWIDTH, MAXWIDTH); + lp->lr = RANGE_RAND(MINREDRAW, MAXREDRAW); + lp->sw = 0; + lp->so = 0; + + if (MI_NPIXELS(mi) > 2) + c = NRAND(MI_NPIXELS(mi)); + + for (i = 0; i < lp->ln; i++) { + laserstruct *l = &lp->laser[i]; + + l->bn = (border) NRAND(4); + + switch (l->bn) { + case TOP: + l->bx = NRAND(lp->width); + l->by = 0; + break; + case RIGHT: + l->bx = lp->width; + l->by = NRAND(lp->height); + break; + case BOTTOM: + l->bx = NRAND(lp->width); + l->by = lp->height; + break; + case LEFT: + l->bx = 0; + l->by = NRAND(lp->height); + } + + l->dir = (int) (LRAND() & 1); + l->speed = ((RANGE_RAND(MINSPEED, MAXSPEED) * lp->width) / 1000) + 1; + if (MI_NPIXELS(mi) > 2) { + l->gcv.foreground = MI_PIXEL(mi, c); + c = (c + COLORSTEP) % MI_NPIXELS(mi); + } else + l->gcv.foreground = MI_WHITE_PIXEL(mi); + } +} + +static void +draw_laser_once(ModeInfo * mi) +{ + Display *display = MI_DISPLAY(mi); + lasersstruct *lp = &lasers[MI_SCREEN(mi)]; + int i; + + for (i = 0; i < lp->ln; i++) { + laserstruct *l = &lp->laser[i]; + + if (lp->sw >= lp->lw) { + XChangeGC(display, lp->stippledGC, GCForeground, &(lp->gcv_black)); + XDrawLine(display, MI_WINDOW(mi), lp->stippledGC, + lp->cx, lp->cy, + l->sx[lp->so], l->sy[lp->so]); + } + if (l->dir) { + switch (l->bn) { + case TOP: + l->bx -= l->speed; + if (l->bx < 0) { + l->by = -l->bx; + l->bx = 0; + l->bn = LEFT; + } + break; + case RIGHT: + l->by -= l->speed; + if (l->by < 0) { + l->bx = lp->width + l->by; + l->by = 0; + l->bn = TOP; + } + break; + case BOTTOM: + l->bx += l->speed; + if (l->bx >= lp->width) { + l->by = lp->height - l->bx % lp->width; + l->bx = lp->width; + l->bn = RIGHT; + } + break; + case LEFT: + l->by += l->speed; + if (l->by >= lp->height) { + l->bx = l->by % lp->height; + l->by = lp->height; + l->bn = BOTTOM; + } + } + } else { + switch (l->bn) { + case TOP: + l->bx += l->speed; + if (l->bx >= lp->width) { + l->by = l->bx % lp->width; + l->bx = lp->width; + l->bn = RIGHT; + } + break; + case RIGHT: + l->by += l->speed; + if (l->by >= lp->height) { + l->bx = lp->width - l->by % lp->height; + l->by = lp->height; + l->bn = BOTTOM; + } + break; + case BOTTOM: + l->bx -= l->speed; + if (l->bx < 0) { + l->by = lp->height + l->bx; + l->bx = 0; + l->bn = LEFT; + } + break; + case LEFT: + l->by -= l->speed; + if (l->by < 0) { + l->bx = -l->bx; + l->by = 0; + l->bn = TOP; + } + } + } + + XChangeGC(display, lp->stippledGC, GCForeground, &l->gcv); + XDrawLine(display, MI_WINDOW(mi), lp->stippledGC, + lp->cx, lp->cy, l->bx, l->by); + + l->sx[lp->so] = l->bx; + l->sy[lp->so] = l->by; + + } + + if (lp->sw < lp->lw) + ++lp->sw; + + lp->so = (lp->so + 1) % lp->lw; +} + +ENTRYPOINT void +draw_laser(ModeInfo * mi) +{ + int i; + lasersstruct *lp; + + if (lasers == NULL) + return; + lp = &lasers[MI_SCREEN(mi)]; + if (lp->laser == NULL) + return; + + MI_IS_DRAWN(mi) = True; + for (i = 0; i < lp->lr; i++) + draw_laser_once(mi); + + if (++lp->time > MI_CYCLES(mi)) + init_laser(mi); +} + +ENTRYPOINT void +release_laser(ModeInfo * mi) +{ + if (lasers != NULL) { + int screen; + + for (screen = 0; screen < MI_NUM_SCREENS(mi); screen++) + free_laser(MI_DISPLAY(mi), &lasers[screen]); + (void) free((void *) lasers); + lasers = (lasersstruct *) NULL; + } +} + +ENTRYPOINT void +refresh_laser(ModeInfo * mi) +{ + MI_CLEARWINDOW(mi); +} + +XSCREENSAVER_MODULE ("Laser", laser) + +#endif /* MODE_laser */ diff --git a/hacks/laser.man b/hacks/laser.man new file mode 100644 index 00000000..77367afe --- /dev/null +++ b/hacks/laser.man @@ -0,0 +1,68 @@ +.TH XScreenSaver 1 "10-May-97" "X Version 11" +.SH NAME +laser - draws vaguely laser-like moving lines +.SH SYNOPSIS +.B laser +[\-display \fIhost:display.screen\fP] [\-foreground \fIcolor\fP] [\-background \fIcolor\fP] [\-window] [\-root] [\-mono] [\-install] [\-visual \fIvisual\fP] [\-ncolors \fIinteger\fP] [\-delay \fImicroseconds\fP] [\-cycles \fIinteger\fP] [\-count \fIinteger\fP] + +[\-fps] +.SH DESCRIPTION +The \fIlaser\fP program draws vaguely laser-like moving lines +.SH OPTIONS +.I laser +accepts the following options: +.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 \-mono +If on a color display, pretend we're on a monochrome display. +.TP 8 +.B \-install +Install a private colormap for the window. +.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 \-ncolors \fIinteger\fP +How many colors should be used (if possible). Default 64. +The colors used cycle through the hue, making N stops around the color wheel. +.TP 8 +.B \-cycles \fIinteger\fP +Default 200. +.TP 8 +.B \-count \fIinteger\fP +Default 10. +.TP 8 +.B \-fps +Display the current frame rate and CPU load. +.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), +.BR xlock (1) +.SH COPYRIGHT +Copyright \(co 1995 by Pascal Pensa. + +Permission to use, copy, modify, and distribute this software and its +documentation for any purpose and without fee is hereby granted, +provided that the above copyright notice appear in all copies and that +both that copyright notice and this permission notice appear in +supporting documentation. +.SH AUTHOR +Pascal Pensa , 1995. + +Ability to run standalone or with \fIxscreensaver\fP added by +Jamie Zawinski , 10-May-97. diff --git a/hacks/lcdscrub.c b/hacks/lcdscrub.c new file mode 100644 index 00000000..d82bd95f --- /dev/null +++ b/hacks/lcdscrub.c @@ -0,0 +1,204 @@ +/* xscreensaver, Copyright (c) 2008 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. + * + * Draws repetitive patterns that should undo burned in LCD screens. + * Concept shamelessly cloned from + * http://toastycode.com/blog/2008/02/05/lcd-scrub/ + */ + +#include "screenhack.h" + +struct state { + Display *dpy; + Window window; + XWindowAttributes xgwa; + enum { HORIZ_W, HORIZ_B, + VERT_W, VERT_B, + DIAG_W, DIAG_B, + WHITE, BLACK, + END } mode; + unsigned int enabled_mask; + int count; + GC fg, bg; + int delay; + int spread; + int cycles; +}; + + +static void +pick_mode (struct state *st) +{ + st->count = 0; + while (1) + { + if (++st->mode == END) + st->mode = 0; + if (st->enabled_mask & (1 << st->mode)) + break; + } +} + +static void * +lcdscrub_init (Display *dpy, Window window) +{ + struct state *st = (struct state *) calloc (1, sizeof(*st)); + XGCValues gcv; + st->dpy = dpy; + st->window = window; + st->delay = get_integer_resource (st->dpy, "delay", "Integer"); + st->spread = get_integer_resource (st->dpy, "spread", "Integer"); + st->cycles = get_integer_resource (st->dpy, "cycles", "Integer"); + + XGetWindowAttributes (st->dpy, st->window, &st->xgwa); + gcv.foreground = BlackPixelOfScreen (st->xgwa.screen); + gcv.background = WhitePixelOfScreen (st->xgwa.screen); + st->bg = XCreateGC (st->dpy, st->window, GCForeground, &gcv); + gcv.foreground = WhitePixelOfScreen (st->xgwa.screen); + gcv.background = BlackPixelOfScreen (st->xgwa.screen); + st->fg = XCreateGC (st->dpy, st->window, GCForeground, &gcv); + +#ifdef HAVE_COCOA + jwxyz_XSetAntiAliasing (st->dpy, st->fg, False); + jwxyz_XSetAntiAliasing (st->dpy, st->bg, False); +#endif + + st->enabled_mask = 0; +# define PREF(R,F) \ + if (get_boolean_resource (st->dpy, R, "Mode")) st->enabled_mask |= (1 << F) + PREF("modeHW", HORIZ_W); + PREF("modeHB", HORIZ_B); + PREF("modeVW", VERT_W); + PREF("modeVB", VERT_B); + PREF("modeDW", DIAG_W); + PREF("modeDB", DIAG_B); + PREF("modeW", WHITE); + PREF("modeB", BLACK); +# undef PREF + if (! st->enabled_mask) + { + fprintf (stderr, "%s: no modes enabled\n", progname); + exit (1); + } + + pick_mode (st); + + return st; +} + +static unsigned long +lcdscrub_draw (Display *dpy, Window window, void *closure) +{ + struct state *st = (struct state *) closure; + int count = st->count % st->spread; + int i; + GC fg = (st->mode & 1 ? st->fg : st->bg); + GC bg = (st->mode & 1 ? st->bg : st->fg); + + switch (st->mode) { + case HORIZ_W: + case HORIZ_B: + XFillRectangle (st->dpy, st->window, bg, 0, 0, + st->xgwa.width, st->xgwa.height); + for (i = count; i < st->xgwa.height; i += st->spread) + XDrawLine (st->dpy, st->window, fg, 0, i, st->xgwa.width, i); + break; + case VERT_W: + case VERT_B: + XFillRectangle (st->dpy, st->window, bg, 0, 0, + st->xgwa.width, st->xgwa.height); + for (i = count; i < st->xgwa.width; i += st->spread) + XDrawLine (st->dpy, st->window, fg, i, 0, i, st->xgwa.height); + break; + case DIAG_W: + case DIAG_B: + XFillRectangle (st->dpy, st->window, bg, 0, 0, + st->xgwa.width, st->xgwa.height); + for (i = count; i < st->xgwa.width; i += st->spread) + XDrawLine (st->dpy, st->window, fg, i, 0, + i + st->xgwa.width, st->xgwa.width); + for (i = -count; i < st->xgwa.height; i += st->spread) + XDrawLine (st->dpy, st->window, fg, 0, i, + st->xgwa.height, i + st->xgwa.height); + break; + case WHITE: + case BLACK: + XFillRectangle (st->dpy, st->window, bg, 0, 0, + st->xgwa.width, st->xgwa.height); + break; + default: + abort(); + break; + } + + st->count++; + + if (st->count > st->spread * st->cycles) + pick_mode (st); + + return st->delay; +} + +static void +lcdscrub_reshape (Display *dpy, Window window, void *closure, + unsigned int w, unsigned int h) +{ +} + +static Bool +lcdscrub_event (Display *dpy, Window window, void *closure, XEvent *event) +{ + return False; +} + +static void +lcdscrub_free (Display *dpy, Window window, void *closure) +{ + struct state *st = (struct state *) closure; + XFreeGC (dpy, st->fg); + XFreeGC (dpy, st->bg); + free (st); +} + + +static const char *lcdscrub_defaults [] = { + ".background: black", + ".foreground: white", + "*delay: 100000", + "*spread: 8", + "*cycles: 60", + "*modeHW: True", + "*modeHB: True", + "*modeVW: True", + "*modeVB: True", + "*modeDW: True", + "*modeDB: True", + "*modeW: True", + "*modeB: True", + 0 +}; + +static XrmOptionDescRec lcdscrub_options [] = { + { "-delay", ".delay", XrmoptionSepArg, 0 }, + { "-spread", ".spread", XrmoptionSepArg, 0 }, + { "-cycles", ".cycles", XrmoptionSepArg, 0 }, + { "-no-hw", ".modeHW", XrmoptionNoArg, "False" }, + { "-no-hb", ".modeHB", XrmoptionNoArg, "False" }, + { "-no-vw", ".modeVW", XrmoptionNoArg, "False" }, + { "-no-vb", ".modeVB", XrmoptionNoArg, "False" }, + { "-no-dw", ".modeDW", XrmoptionNoArg, "False" }, + { "-no-db", ".modeDB", XrmoptionNoArg, "False" }, + { "-no-w", ".modeW", XrmoptionNoArg, "False" }, + { "-no-b", ".modeB", XrmoptionNoArg, "False" }, + { 0, 0, 0, 0 } +}; + + +XSCREENSAVER_MODULE ("LCDscrub", lcdscrub) diff --git a/hacks/lcdscrub.man b/hacks/lcdscrub.man new file mode 100644 index 00000000..04e0d721 --- /dev/null +++ b/hacks/lcdscrub.man @@ -0,0 +1,73 @@ +.TH XScreenSaver 1 "" "X Version 11" +.SH NAME +lcdscrub - attempt to repair burn-in on LCD screens +.SH SYNOPSIS +.B lcdscrub +[\-display \fIhost:display.screen\fP] +[\-visual \fIvisual\fP] +[\-window] +[\-root] +[\-delay \fInumber\fP] +[\-spread \fInumber\fP] +[\-cycles \fInumber\fP] +[\-fps] +.SH DESCRIPTION +This screen saver is not meant to look pretty, but rather, to +repair burn-in on LCD monitors. + +Believe it or not, screen burn is not a thing of the past. +It can happen to LCD screens pretty easily, even in this modern age. +However, leaving the screen on and displaying high contrast images +can often repair the damage. That's what this screen saver does. + +See also: + + http://docs.info.apple.com/article.html?artnum=88343 + http://toastycode.com/blog/2008/02/05/lcd-scrub/ +.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: 1000000 (1 second.). +.TP 8 +.B \-spread \fInumber\fP +Distance between lines. Default 8. +.TP 8 +.B \-cycles \fInumber\fP +Steps before switching display mode. Default 60. +.TP 8 +.B \-fps +Display the current frame rate and CPU load. +.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 2008 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 +Inspired by the like-named program by Daniel Sandler. + +Written by Jamie Zawinski. diff --git a/hacks/lightning.c b/hacks/lightning.c new file mode 100644 index 00000000..e7d9f06e --- /dev/null +++ b/hacks/lightning.c @@ -0,0 +1,614 @@ +/* -*- Mode: C; tab-width: 4 -*- */ +/* lightning --- fractal lightning bolds */ + +#if 0 +static const char sccsid[] = "@(#)lightning.c 5.00 2000/11/01 xlockmore"; +#endif + +/*- + * Copyright (c) 1996 by Keith Romberg + * + * Permission to use, copy, modify, and distribute this software and its + * documentation for any purpose and without fee is hereby granted, + * provided that the above copyright notice appear in all copies and that + * both that copyright notice and this permission notice appear in + * supporting documentation. + * + * This file is provided AS IS with no warranties of any kind. The author + * shall have no liability with respect to the infringement of copyrights, + * trade secrets or any patents by this file or any part thereof. In no + * event will the author be liable for any lost revenue or profits or + * other special, indirect and consequential damages. + * + * Revision History: + * 01-Nov-2000: Allocation checks + * 10-May-1997: Compatible with xscreensaver + * 14-Jul-1996: Cleaned up code. + * 27-Jun-1996: Written and submitted by Keith Romberg . + */ + +#ifdef STANDALONE +# define MODE_lightning +# define DEFAULTS "*delay: 10000 \n" \ + "*ncolors: 64 \n" + +# define BRIGHT_COLORS +# define reshape_lightning 0 +# define lightning_handle_event 0 +# include "xlockmore.h" /* in xscreensaver distribution */ +#else /* STANDALONE */ +# include "xlock.h" /* in xlockmore distribution */ +#endif /* STANDALONE */ + +#ifdef MODE_lightning + +ENTRYPOINT ModeSpecOpt lightning_opts = +{0, (XrmOptionDescRec *) NULL, 0, (argtype *) NULL, (OptionStruct *) NULL}; + +#ifdef USE_MODULES +ModStruct lightning_description = +{"lightning", "init_lightning", "draw_lightning", "release_lightning", + "refresh_lightning", "init_lightning", (char *) NULL, &lightning_opts, + 10000, 1, 1, 1, 64, 0.6, "", + "Shows Keith's fractal lightning bolts", 0, NULL}; + +#endif + +#define BOLT_NUMBER 4 +#define BOLT_ITERATION 4 +#define LONG_FORK_ITERATION 3 +#define MEDIUM_FORK_ITERATION 2 +#define SMALL_FORK_ITERATION 1 + +#define WIDTH_VARIATION 30 +#define HEIGHT_VARIATION 15 + +#define DELAY_TIME_AMOUNT 15 +#define MULTI_DELAY_TIME_BASE 5 + +#define MAX_WIGGLES 16 +#define WIGGLE_BASE 8 +#define WIGGLE_AMOUNT 14 + +#define RANDOM_FORK_PROBILITY 4 + +#define FIRST_LEVEL_STRIKE 0 +#define LEVEL_ONE_STRIKE 1 +#define LEVEL_TWO_STRIKE 2 + +#define BOLT_VERTICIES ((1<= 51) && (multi_prob < 75)) + result = 2; + else if ((multi_prob >= 76) && (multi_prob < 92)) + result = 3; + else + result = BOLT_NUMBER; /* 4 */ + + return (result); +} + +/*-------------------------------------------------------------------------*/ + +static int +flashing_strike(void) +{ + int tmp = NRAND(FLASH_PROBILITY); + + if (tmp <= FLASH_PROBILITY) + return (1); + return (0); +} + +/*-------------------------------------------------------------------------*/ + +static void +flash_duration(int *start, int *end, int total_duration) +{ + int mid, d; + + mid = total_duration / MAX_FLASH_AMOUNT; + d = NRAND(total_duration / MAX_FLASH_AMOUNT) / 2; + *start = mid - d; + *end = mid + d; +} + +/*-------------------------------------------------------------------------*/ + +static void +random_storm(Storm * st) +{ + int i, j, tmp; + XPoint p; + + for (i = 0; i < st->multi_strike; i++) { + st->bolts[i].end1.x = NRAND(st->scr_width); + st->bolts[i].end1.y = 0; + st->bolts[i].end2.x = NRAND(st->scr_width); + st->bolts[i].end2.y = st->scr_height; + st->bolts[i].wiggle_number = WIGGLE_BASE + NRAND(MAX_WIGGLES); + if ((st->bolts[i].flash = flashing_strike())) + flash_duration(&(st->bolts[i].flash_begin), &(st->bolts[i].flash_stop), + st->bolts[i].wiggle_number); + else + st->bolts[i].flash_begin = st->bolts[i].flash_stop = 0; + st->bolts[i].wiggle_amount = WIGGLE_AMOUNT; + if (i == 0) + st->bolts[i].delay_time = NRAND(DELAY_TIME_AMOUNT); + else + st->bolts[i].delay_time = NRAND(DELAY_TIME_AMOUNT) + + (MULTI_DELAY_TIME_BASE * i); + st->bolts[i].strike_level = FIRST_LEVEL_STRIKE; + tmp = 0; + generate(st->bolts[i].end1, st->bolts[i].end2, BOLT_ITERATION, + st->bolts[i].middle, &tmp); + st->bolts[i].fork_number = 0; + st->bolts[i].visible = 0; + for (j = 0; j < BOLT_VERTICIES; j++) { + if (st->bolts[i].fork_number >= 2) + break; + if (NRAND(100) < RANDOM_FORK_PROBILITY) { + p.x = NRAND(st->scr_width); + p.y = st->scr_height; + st->bolts[i].forks_start[st->bolts[i].fork_number] = j; + create_fork(&(st->bolts[i].branch[st->bolts[i].fork_number]), + st->bolts[i].middle[j], p, j); + st->bolts[i].fork_number++; + } + } + } +} + +static void +generate(XPoint A, XPoint B, int iter, XPoint * verts, int *vert_index) +{ + XPoint mid; + + mid.x = (A.x + B.x) / 2 + NRAND(WIDTH_VARIATION) - WIDTH_VARIATION / 2; + mid.y = (A.y + B.y) / 2 + NRAND(HEIGHT_VARIATION) - HEIGHT_VARIATION / 2; + + if (!iter) { + verts[*vert_index].x = mid.x; + verts[*vert_index].y = mid.y; + (*vert_index)++; + return; + } + generate(A, mid, iter - 1, verts, vert_index); + generate(mid, B, iter - 1, verts, vert_index); +} + +/*------------------------------------------------------------------------*/ + +static void +create_fork(Fork * f, XPoint start, XPoint end, int level) +{ + int tmp = 1; + + f->ForkVerticies[0].x = start.x; + f->ForkVerticies[0].y = start.y; + + if (level <= 6) { + generate(start, end, LONG_FORK_ITERATION, f->ForkVerticies, &tmp); + f->num_used = 9; + } else if ((level > 6) && (level <= 11)) { + generate(start, end, MEDIUM_FORK_ITERATION, f->ForkVerticies, &tmp); + f->num_used = 5; + } else { + if (distance(start, end) > 100) { + generate(start, end, MEDIUM_FORK_ITERATION, f->ForkVerticies, &tmp); + f->num_used = 5; + } else { + generate(start, end, SMALL_FORK_ITERATION, f->ForkVerticies, &tmp); + f->num_used = 3; + } + } + + f->ForkVerticies[f->num_used - 1].x = end.x; + f->ForkVerticies[f->num_used - 1].y = end.y; +} + +/*------------------------------------------------------------------------*/ + +static void +update_bolt(Lightning * bolt, int time_now) +{ + wiggle_bolt(bolt); + if ((bolt->wiggle_amount == 0) && (bolt->wiggle_number > 2)) + bolt->wiggle_number = 0; + if (((time_now % 3) == 0)) + bolt->wiggle_amount++; + + if (((time_now >= bolt->delay_time) && (time_now < bolt->flash_begin)) || + (time_now > bolt->flash_stop)) + bolt->visible = 1; + else + bolt->visible = 0; + + if (time_now == bolt->delay_time) + bolt->strike_level = FIRST_LEVEL_STRIKE; + else if (time_now == (bolt->delay_time + 1)) + bolt->strike_level = LEVEL_ONE_STRIKE; + else if ((time_now > (bolt->delay_time + 1)) && + (time_now <= (bolt->delay_time + bolt->flash_begin - 2))) + bolt->strike_level = LEVEL_TWO_STRIKE; + else if (time_now == (bolt->delay_time + bolt->flash_begin - 1)) + bolt->strike_level = LEVEL_ONE_STRIKE; + else if (time_now == (bolt->delay_time + bolt->flash_stop + 1)) + bolt->strike_level = LEVEL_ONE_STRIKE; + else + bolt->strike_level = LEVEL_TWO_STRIKE; +} + +/*------------------------------------------------------------------------*/ + +static void +draw_bolt(Lightning * bolt, ModeInfo * mi) +{ + if (bolt->visible) { + if (bolt->strike_level == FIRST_LEVEL_STRIKE) + first_strike(*bolt, mi); + else if (bolt->strike_level == LEVEL_ONE_STRIKE) + level1_strike(*bolt, mi); + else + level2_strike(*bolt, mi); + } +} + +/*------------------------------------------------------------------------*/ + +static void +first_strike(Lightning bolt, ModeInfo * mi) +{ + Display *display = MI_DISPLAY(mi); + Window window = MI_WINDOW(mi); + GC gc = MI_GC(mi); + int i; + + XSetForeground(display, gc, MI_WHITE_PIXEL(mi)); + XDrawLine(display, window, gc, + bolt.end1.x, bolt.end1.y, bolt.middle[0].x, bolt.middle[0].y); + draw_line(mi, bolt.middle, BOLT_VERTICIES, gc, 0); + XDrawLine(display, window, gc, + bolt.middle[BOLT_VERTICIES - 1].x, bolt.middle[BOLT_VERTICIES - 1].y, + bolt.end2.x, bolt.end2.y); + + for (i = 0; i < bolt.fork_number; i++) + draw_line(mi, bolt.branch[i].ForkVerticies, bolt.branch[i].num_used, + gc, 0); +} + +/*------------------------------------------------------------------------*/ + +static void +draw_line(ModeInfo * mi, XPoint * points, int number, GC to_use, int offset) +{ + int i; + + for (i = 0; i < number - 1; i++) { + if (points[i].y <= points[i + 1].y) + XDrawLine(MI_DISPLAY(mi), MI_WINDOW(mi), to_use, points[i].x + offset, + points[i].y, points[i + 1].x + offset, points[i + 1].y); + else { + if (points[i].x < points[i + 1].x) + XDrawLine(MI_DISPLAY(mi), MI_WINDOW(mi), to_use, points[i].x + + offset, points[i].y + offset, points[i + 1].x + offset, + points[i + 1].y + offset); + else + XDrawLine(MI_DISPLAY(mi), MI_WINDOW(mi), to_use, points[i].x - + offset, points[i].y + offset, points[i + 1].x - offset, + points[i + 1].y + offset); + } + } +} + +/*------------------------------------------------------------------------*/ + +static void +level1_strike(Lightning bolt, ModeInfo * mi) +{ + Display *display = MI_DISPLAY(mi); + Window window = MI_WINDOW(mi); + Storm *st = &Helga[MI_SCREEN(mi)]; + GC gc = MI_GC(mi); + int i; + + if (MI_NPIXELS(mi) > 2) /* color */ + XSetForeground(display, gc, MI_PIXEL(mi, st->color)); + else + XSetForeground(display, gc, MI_WHITE_PIXEL(mi)); + XDrawLine(display, window, gc, + bolt.end1.x - 1, bolt.end1.y, bolt.middle[0].x - 1, bolt.middle[0].y); + draw_line(mi, bolt.middle, BOLT_VERTICIES, gc, -1); + XDrawLine(display, window, gc, + bolt.middle[BOLT_VERTICIES - 1].x - 1, + bolt.middle[BOLT_VERTICIES - 1].y, bolt.end2.x - 1, bolt.end2.y); + XDrawLine(display, window, gc, + bolt.end1.x + 1, bolt.end1.y, bolt.middle[0].x + 1, bolt.middle[0].y); + draw_line(mi, bolt.middle, BOLT_VERTICIES, gc, 1); + XDrawLine(display, window, gc, + bolt.middle[BOLT_VERTICIES - 1].x + 1, + bolt.middle[BOLT_VERTICIES - 1].y, bolt.end2.x + 1, bolt.end2.y); + + for (i = 0; i < bolt.fork_number; i++) { + draw_line(mi, bolt.branch[i].ForkVerticies, bolt.branch[i].num_used, + gc, -1); + draw_line(mi, bolt.branch[i].ForkVerticies, bolt.branch[i].num_used, + gc, 1); + } + first_strike(bolt, mi); +} + +/*------------------------------------------------------------------------*/ + +static int +distance(XPoint a, XPoint b) +{ + return ((int) sqrt((double) (a.x - b.x) * (a.x - b.x) + (a.y - b.y) * (a.y - b.y))); +} + +/*------------------------------------------------------------------------*/ + +static void +level2_strike(Lightning bolt, ModeInfo * mi) +{ + Display *display = MI_DISPLAY(mi); + Window window = MI_WINDOW(mi); + Storm *st = &Helga[MI_SCREEN(mi)]; + GC gc = MI_GC(mi); + int i; + + /* This was originally designed to be a little darker then the + level1 strike. This was changed to get it to work on + multiscreens and to add more color variety. I tried + stippling but it did not look good. */ + if (MI_NPIXELS(mi) > 2) + XSetForeground(display, gc, MI_PIXEL(mi, st->color)); + else + XSetForeground(display, gc, MI_WHITE_PIXEL(mi)); + XDrawLine(display, window, gc, + bolt.end1.x - 2, bolt.end1.y, bolt.middle[0].x - 2, bolt.middle[0].y); + draw_line(mi, bolt.middle, BOLT_VERTICIES, gc, -2); + XDrawLine(display, window, gc, + bolt.middle[BOLT_VERTICIES - 1].x - 2, + bolt.middle[BOLT_VERTICIES - 1].y, bolt.end2.x - 2, bolt.end2.y); + + XDrawLine(display, window, gc, + bolt.end1.x + 2, bolt.end1.y, bolt.middle[0].x + 2, bolt.middle[0].y); + draw_line(mi, bolt.middle, BOLT_VERTICIES, gc, 2); + XDrawLine(display, window, gc, + bolt.middle[BOLT_VERTICIES - 1].x + 2, + bolt.middle[BOLT_VERTICIES - 1].y, bolt.end2.x + 2, bolt.end2.y); + + for (i = 0; i < bolt.fork_number; i++) { + draw_line(mi, bolt.branch[i].ForkVerticies, bolt.branch[i].num_used, + gc, -2); + draw_line(mi, bolt.branch[i].ForkVerticies, bolt.branch[i].num_used, + gc, 2); + } + level1_strike(bolt, mi); +} + +/*------------------------------------------------------------------------*/ + +static int +storm_active(Storm * st) +{ + int i, atleast_1 = 0; + + for (i = 0; i < st->multi_strike; i++) + if (st->bolts[i].wiggle_number > 0) + atleast_1++; + + return (atleast_1); +} + +/*------------------------------------------------------------------------*/ + +static void +wiggle_bolt(Lightning * bolt) +{ + int i; + + wiggle_line(bolt->middle, BOLT_VERTICIES, bolt->wiggle_amount); + bolt->end2.x += NRAND(bolt->wiggle_amount) - bolt->wiggle_amount / 2; + bolt->end2.y += NRAND(bolt->wiggle_amount) - bolt->wiggle_amount / 2; + + for (i = 0; i < bolt->fork_number; i++) { + wiggle_line(bolt->branch[i].ForkVerticies, bolt->branch[i].num_used, + bolt->wiggle_amount); + bolt->branch[i].ForkVerticies[0].x = bolt->middle[bolt->forks_start[i]].x; + bolt->branch[i].ForkVerticies[0].y = bolt->middle[bolt->forks_start[i]].y; + } + + if (bolt->wiggle_amount > 1) + bolt->wiggle_amount -= 1; + else + bolt->wiggle_amount = 0; +} + +/*------------------------------------------------------------------------*/ + +static void +wiggle_line(XPoint * p, int number, int amount) +{ + int i; + + for (i = 0; i < number; i++) { + p[i].x += NRAND(amount) - amount / 2; + p[i].y += NRAND(amount) - amount / 2; + } +} + +/*------------------------------------------------------------------------*/ + +ENTRYPOINT void +init_lightning (ModeInfo * mi) +{ + Storm *st; + + if (Helga == NULL) { + if ((Helga = (Storm *) calloc(MI_NUM_SCREENS(mi), + sizeof (Storm))) == NULL) + return; + } + st = &Helga[MI_SCREEN(mi)]; + + st->scr_width = MI_WIDTH(mi); + st->scr_height = MI_HEIGHT(mi); + + st->multi_strike = setup_multi_strike(); + random_storm(st); + st->stage = 0; +} + +/*------------------------------------------------------------------------*/ + +ENTRYPOINT void +draw_lightning (ModeInfo * mi) +{ + int i; + Storm *st; + + if (Helga == NULL) + return; + st = &Helga[MI_SCREEN(mi)]; + MI_IS_DRAWN(mi) = True; + switch (st->stage) { + case 0: + MI_IS_DRAWN(mi) = False; + MI_CLEARWINDOW(mi); + MI_IS_DRAWN(mi) = True; + + st->color = NRAND(MI_NPIXELS(mi)); + st->draw_time = 0; + if (storm_active(st)) + st->stage++; + else + st->stage = 4; + break; + case 1: + for (i = 0; i < st->multi_strike; i++) { + if (st->bolts[i].visible) + draw_bolt(&(st->bolts[i]), mi); + update_bolt(&(st->bolts[i]), st->draw_time); + } + st->draw_time++; + st->stage++; + st->busyLoop = 0; + break; + case 2: + if (++st->busyLoop > 6) { + st->stage++; + st->busyLoop = 0; + } + break; + case 3: + MI_IS_DRAWN(mi) = False; + MI_CLEARWINDOW(mi); + MI_IS_DRAWN(mi) = True; + + if (storm_active(st)) + st->stage = 1; + else + st->stage++; + break; + case 4: + if (++st->busyLoop > 100) { + st->busyLoop = 0; + } + init_lightning(mi); + break; + } +} + +ENTRYPOINT void +release_lightning(ModeInfo * mi) +{ + if (Helga != NULL) { + (void) free((void *) Helga); + Helga = (Storm *) NULL; + } +} + +ENTRYPOINT void +refresh_lightning(ModeInfo * mi) +{ + /* Do nothing, it will refresh by itself */ +} + +XSCREENSAVER_MODULE ("Lightning", lightning) + + +#endif /* MODE_lightning */ diff --git a/hacks/lightning.man b/hacks/lightning.man new file mode 100644 index 00000000..65386d39 --- /dev/null +++ b/hacks/lightning.man @@ -0,0 +1,62 @@ +.TH XScreenSaver 1 "10-May-97" "X Version 11" +.SH NAME +lightning - draws fractal lightning bolts +.SH SYNOPSIS +.B lightning +[\-display \fIhost:display.screen\fP] [\-foreground \fIcolor\fP] [\-background \fIcolor\fP] [\-window] [\-root] [\-mono] [\-install] [\-visual \fIvisual\fP] [\-ncolors \fIinteger\fP] [\-delay \fImicroseconds\fP] + +[\-fps] +.SH DESCRIPTION +The \fIlightning\fP program draws fractal lightning bolts +.SH OPTIONS +.I lightning +accepts the following options: +.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 \-mono +If on a color display, pretend we're on a monochrome display. +.TP 8 +.B \-install +Install a private colormap for the window. +.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 \-ncolors \fIinteger\fP +How many colors should be used (if possible). Default 64. +The colors are chosen randomly. +.TP 8 +.B \-fps +Display the current frame rate and CPU load. +.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), +.BR xlock (1) +.SH COPYRIGHT +Copyright \(co 1996 by Keith Romberg. + +Permission to use, copy, modify, and distribute this software and its +documentation for any purpose and without fee is hereby granted, +provided that the above copyright notice appear in all copies and that +both that copyright notice and this permission notice appear in +supporting documentation. +.SH AUTHOR +Keith Romberg , 27-Jun-96. + +Ability to run standalone or with \fIxscreensaver\fP added by +Jamie Zawinski , 10-May-97. diff --git a/hacks/link_axp.com b/hacks/link_axp.com new file mode 100644 index 00000000..203affc2 --- /dev/null +++ b/hacks/link_axp.com @@ -0,0 +1,107 @@ +$! We fisrt test the version of DECW/Motif ; if 1.2 we need to link with new +$! X11R5 libraries +$@sys$update:decw$get_image_version sys$share:decw$xlibshr.exe decw$version +$ if f$extract(4,3,decw$version).eqs."1.2" +$ then +$! DECW/Motif 1.2 : link with X11R5 libraries +$ link/exe=attraction.exe screenhack,attraction,vms_axp_12.opt/opt +$ link/exe=blitspin.exe screenhack,blitspin,vms_axp_12.opt/opt +$ link/exe=bouboule.exe screenhack-xlock,bouboule,xlockmore,vms_axp_12.opt/opt +$ link/exe=braid.exe screenhack-xlock,braid,xlockmore,vms_axp_12.opt/opt +$ link/exe=bubbles.exe screenhack,bubbles,bubbles_default,vms_axp_12.opt/opt +$ link/exe=coral.exe screenhack,coral,vms_axp_12.opt/opt +$ link/exe=decayscreen.exe screenhack,decayscreen,vms_axp_12.opt/opt +$ link/exe=deco.exe screenhack,deco,vms_axp_12.opt/opt +$ link/exe=drift.exe screenhack-xlock,drift,xlockmore,vms_axp_12.opt/opt +$ link/exe=fadeplot.exe screenhack-xlock,fadeplot,xlockmore,vms_axp_12.opt/opt +$ link/exe=flag.exe screenhack-xlock,flag,xlockmore,vms_axp_12.opt/opt +$ link/exe=flame.exe screenhack,flame,vms_axp_12.opt/opt +$ link/exe=forest.exe screenhack-xlock,forest,xlockmore,vms_axp_12.opt/opt +$ link/exe=vines.exe screenhack-xlock,vines,xlockmore,vms_axp_12.opt/opt +$ link/exe=galaxy.exe screenhack-xlock,galaxy,xlockmore,vms_axp_12.opt/opt +$ link/exe=grav.exe screenhack-xlock,grav,xlockmore,vms_axp_12.opt/opt +$ link/exe=greynetic screenhack,greynetic,vms_axp_12.opt/opt +$ link/exe=halo.exe screenhack,halo,vms_axp_12.opt/opt +$ link/exe=helix.exe screenhack,helix,vms_axp_12.opt/opt +$ link/exe=hop.exe screenhack-xlock,hop,xlockmore,vms_axp_12.opt/opt +$ link/exe=hypercube.exe screenhack,hypercube,vms_axp_12.opt/opt +$ link/exe=ifs.exe screenhack-xlock,ifs,xlockmore,vms_axp_12.opt/opt +$ link/exe=imsmap.exe screenhack,imsmap,vms_axp_12.opt/opt +$ link/exe=julia.exe screenhack-xlock,julia,xlockmore,vms_axp_12.opt/opt +$ link/exe=kaleidescope.exe screenhack,kaleidescope,vms_axp_12.opt/opt +$ link/exe=laser.exe screenhack-xlock,laser,xlockmore,vms_axp_12.opt/opt +$ link/exe=lightning.exe screenhack-xlock,lightning,xlockmore,vms_axp_12.opt/opt +$ link/exe=lisa.exe screenhack-xlock,lisa,xlockmore,vms_axp_12.opt/opt +$ link/exe=lmorph.exe screenhack,lmorph,vms_axp_12.opt/opt +$ link/exe=maze.exe screenhack,maze,vms_axp_12.opt/opt +$ link/exe=moire.exe screenhack,moire,vms_axp_12.opt/opt +$ link/exe=noseguy.exe screenhack,noseguy,vms_axp_12.opt/opt +$ link/exe=pedal.exe screenhack,pedal,vms_axp_12.opt/opt +$ link/exe=penrose.exe screenhack-xlock,penrose,xlockmore,vms_axp_12.opt/opt +$ link/exe=pyro.exe screenhack,pyro,vms_axp_12.opt/opt +$ link/exe=qix.exe screenhack,qix,vms_axp_12.opt/opt +$ link/exe=rd-bomb.exe screenhack,rd-bomb,vms_axp_12.opt/opt +$ link/exe=rocks.exe screenhack,rocks,vms_axp_12.opt/opt +$ link/exe=rorschach.exe screenhack,rorschach,vms_axp_12.opt/opt +$ link/exe=sierpinski.exe screenhack-xlock,sierpinski,xlockmore,vms_axp_12.opt/opt +$ link/exe=slidescreen.exe screenhack,slidescreen,vms_axp_12.opt/opt +$ link/exe=slip.exe screenhack-xlock,slip,xlockmore,vms_axp_12.opt/opt +$ link/exe=sphere.exe screenhack-xlock,sphere,xlockmore,vms_axp_12.opt/opt +$ link/exe=spiral.exe screenhack-xlock,spiral,xlockmore,vms_axp_12.opt/opt +$ link/exe=strange.exe screenhack-xlock,strange,xlockmore,vms_axp_12.opt/opt +$ link/exe=swirl.exe screenhack-xlock,swirl,xlockmore,vms_axp_12.opt/opt +$ link/exe=goop.exe screenhack,goop,vms_axp_12.opt/opt +$ link/exe=starfish.exe screenhack,starfish,vms_axp_12.opt/opt +$ link/exe=munch.exe screenhack,munch,vms_axp_12.opt/opt +$ else +$! Else, link with X11R4 libraries +$ link/exe=attraction.exe screenhack,attraction,vms_axp.opt/opt +$ link/exe=blitspin.exe screenhack,blitspin,vms_axp.opt/opt +$ link/exe=bouboule.exe screenhack-xlock,bouboule,xlockmore,vms_axp.opt/opt +$ link/exe=braid.exe screenhack-xlock,braid,xlockmore,vms_axp.opt/opt +$ link/exe=bubbles.exe screenhack,bubbles,bubbles_default,vms_axp.opt/opt +$ link/exe=coral.exe screenhack,coral,vms_axp.opt/opt +$ link/exe=decayscreen.exe screenhack,decayscreen,vms_axp.opt/opt +$ link/exe=deco.exe screenhack,deco,vms_axp.opt/opt +$ link/exe=drift.exe screenhack-xlock,drift,xlockmore,vms_axp.opt/opt +$ link/exe=fadeplot.exe screenhack-xlock,fadeplot,xlockmore,vms_axp.opt/opt +$ link/exe=flag.exe screenhack-xlock,flag,xlockmore,vms_axp.opt/opt +$ link/exe=flame.exe screenhack,flame,vms_axp.opt/opt +$ link/exe=forest.exe screenhack-xlock,forest,xlockmore,vms_axp.opt/opt +$ link/exe=vines.exe screenhack-xlock,vines,xlockmore,vms_axp.opt/opt +$ link/exe=galaxy.exe screenhack-xlock,galaxy,xlockmore,vms_axp.opt/opt +$ link/exe=grav.exe screenhack-xlock,grav,xlockmore,vms_axp.opt/opt +$ link/exe=greynetic screenhack,greynetic,vms_axp.opt/opt +$ link/exe=halo.exe screenhack,halo,vms_axp.opt/opt +$ link/exe=helix.exe screenhack,helix,vms_axp.opt/opt +$ link/exe=hop.exe screenhack-xlock,hop,xlockmore,vms_axp.opt/opt +$ link/exe=hypercube.exe screenhack,hypercube,vms_axp.opt/opt +$ link/exe=ifs.exe screenhack-xlock,ifs,xlockmore,vms_axp.opt/opt +$ link/exe=imsmap.exe screenhack,imsmap,vms_axp.opt/opt +$ link/exe=julia.exe screenhack-xlock,julia,xlockmore,vms_axp.opt/opt +$ link/exe=kaleidescope.exe screenhack,kaleidescope,vms_axp.opt/opt +$ link/exe=laser.exe screenhack-xlock,laser,xlockmore,vms_axp.opt/opt +$ link/exe=lightning.exe screenhack-xlock,lightning,xlockmore,vms_axp.opt/opt +$ link/exe=lisa.exe screenhack-xlock,lisa,xlockmore,vms_axp.opt/opt +$ link/exe=lmorph.exe screenhack,lmorph,vms_axp.opt/opt +$ link/exe=maze.exe screenhack,maze,vms_axp.opt/opt +$ link/exe=moire.exe screenhack,moire,vms_axp.opt/opt +$ link/exe=noseguy.exe screenhack,noseguy,vms_axp.opt/opt +$ link/exe=pedal.exe screenhack,pedal,vms_axp.opt/opt +$ link/exe=penrose.exe screenhack-xlock,penrose,xlockmore,vms_axp.opt/opt +$ link/exe=pyro.exe screenhack,pyro,vms_axp.opt/opt +$ link/exe=qix.exe screenhack,qix,vms_axp.opt/opt +$ link/exe=rd-bomb.exe screenhack,rd-bomb,vms_axp.opt/opt +$ link/exe=rocks.exe screenhack,rocks,vms_axp.opt/opt +$ link/exe=rorschach.exe screenhack,rorschach,vms_axp.opt/opt +$ link/exe=sierpinski.exe screenhack-xlock,sierpinski,xlockmore,vms_axp.opt/opt +$ link/exe=slidescreen.exe screenhack,slidescreen,vms_axp.opt/opt +$ link/exe=slip.exe screenhack-xlock,slip,xlockmore,vms_axp.opt/opt +$ link/exe=sphere.exe screenhack-xlock,sphere,xlockmore,vms_axp.opt/opt +$ link/exe=spiral.exe screenhack-xlock,spiral,xlockmore,vms_axp.opt/opt +$ link/exe=strange.exe screenhack-xlock,strange,xlockmore,vms_axp.opt/opt +$ link/exe=swirl.exe screenhack-xlock,swirl,xlockmore,vms_axp.opt/opt +$ link/exe=goop.exe screenhack,goop,vms_axp.opt/opt +$ link/exe=starfish.exe screenhack,starfish,vms_axp.opt/opt +$ link/exe=munch.exe screenhack,munch,vms_axp.opt/opt +$ endif diff --git a/hacks/link_decc.com b/hacks/link_decc.com new file mode 100644 index 00000000..571c4f81 --- /dev/null +++ b/hacks/link_decc.com @@ -0,0 +1,107 @@ +$! We fisrt test the version of DECW/Motif ; if 1.2 we need to link with new +$! X11R5 libraries +$@sys$update:decw$get_image_version sys$share:decw$xlibshr.exe decw$version +$ if f$extract(4,3,decw$version).eqs."1.2" +$ then +$! DECW/Motif 1.2 : link with X11R5 libraries +$ link/exe=attraction.exe screenhack,attraction,vms_decc_12.opt/opt +$ link/exe=blitspin.exe screenhack,blitspin,vms_decc_12.opt/opt +$ link/exe=bouboule.exe screenhack-xlock,bouboule,xlockmore,vms_decc_12.opt/opt +$ link/exe=braid.exe screenhack-xlock,braid,xlockmore,vms_decc_12.opt/opt +$ link/exe=bubbles.exe screenhack,bubbles,bubbles_default,vms_decc_12.opt/opt +$ link/exe=coral.exe screenhack,coral,vms_decc_12.opt/opt +$ link/exe=decayscreen.exe screenhack,decayscreen,vms_decc_12.opt/opt +$ link/exe=deco.exe screenhack,deco,vms_decc_12.opt/opt +$ link/exe=drift.exe screenhack-xlock,drift,xlockmore,vms_decc_12.opt/opt +$ link/exe=fadeplot.exe screenhack-xlock,fadeplot,xlockmore,vms_decc_12.opt/opt +$ link/exe=flag.exe screenhack-xlock,flag,xlockmore,vms_decc_12.opt/opt +$ link/exe=flame.exe screenhack,flame,vms_decc_12.opt/opt +$ link/exe=forest.exe screenhack-xlock,forest,xlockmore,vms_decc_12.opt/opt +$ link/exe=vines.exe screenhack-xlock,vines,xlockmore,vms_decc_12.opt/opt +$ link/exe=galaxy.exe screenhack-xlock,galaxy,xlockmore,vms_decc_12.opt/opt +$ link/exe=grav.exe screenhack-xlock,grav,xlockmore,vms_decc_12.opt/opt +$ link/exe=greynetic screenhack,greynetic,vms_decc_12.opt/opt +$ link/exe=halo.exe screenhack,halo,vms_decc_12.opt/opt +$ link/exe=helix.exe screenhack,helix,vms_decc_12.opt/opt +$ link/exe=hop.exe screenhack-xlock,hop,xlockmore,vms_decc_12.opt/opt +$ link/exe=hypercube.exe screenhack,hypercube,vms_decc_12.opt/opt +$ link/exe=ifs.exe screenhack-xlock,ifs,xlockmore,vms_decc_12.opt/opt +$ link/exe=imsmap.exe screenhack,imsmap,vms_decc_12.opt/opt +$ link/exe=julia.exe screenhack-xlock,julia,xlockmore,vms_decc_12.opt/opt +$ link/exe=kaleidescope.exe screenhack,kaleidescope,vms_decc_12.opt/opt +$ link/exe=laser.exe screenhack-xlock,laser,xlockmore,vms_decc_12.opt/opt +$ link/exe=lightning.exe screenhack-xlock,lightning,xlockmore,vms_decc_12.opt/opt +$ link/exe=lisa.exe screenhack-xlock,lisa,xlockmore,vms_decc_12.opt/opt +$ link/exe=lmorph.exe screenhack,lmorph,vms_decc_12.opt/opt +$ link/exe=maze.exe screenhack,maze,vms_decc_12.opt/opt +$ link/exe=moire.exe screenhack,moire,vms_decc_12.opt/opt +$ link/exe=noseguy.exe screenhack,noseguy,vms_decc_12.opt/opt +$ link/exe=pedal.exe screenhack,pedal,vms_decc_12.opt/opt +$ link/exe=penrose.exe screenhack-xlock,penrose,xlockmore,vms_decc_12.opt/opt +$ link/exe=pyro.exe screenhack,pyro,vms_decc_12.opt/opt +$ link/exe=qix.exe screenhack,qix,vms_decc_12.opt/opt +$ link/exe=rd-bomb.exe screenhack,rd-bomb,vms_decc_12.opt/opt +$ link/exe=rocks.exe screenhack,rocks,vms_decc_12.opt/opt +$ link/exe=rorschach.exe screenhack,rorschach,vms_decc_12.opt/opt +$ link/exe=sierpinski.exe screenhack-xlock,sierpinski,xlockmore,vms_decc_12.opt/opt +$ link/exe=slidescreen.exe screenhack,slidescreen,vms_decc_12.opt/opt +$ link/exe=slip.exe screenhack-xlock,slip,xlockmore,vms_decc_12.opt/opt +$ link/exe=sphere.exe screenhack-xlock,sphere,xlockmore,vms_decc_12.opt/opt +$ link/exe=spiral.exe screenhack-xlock,spiral,xlockmore,vms_decc_12.opt/opt +$ link/exe=strange.exe screenhack-xlock,strange,xlockmore,vms_decc_12.opt/opt +$ link/exe=swirl.exe screenhack-xlock,swirl,xlockmore,vms_decc_12.opt/opt +$ link/exe=goop.exe screenhack,goop,vms_decc_12.opt/opt +$ link/exe=starfish.exe screenhack,starfish,vms_decc_12.opt/opt +$ link/exe=munch.exe screenhack,munch,vms_decc_12.opt/opt +$ else +$! Else, link with X11R4 libraries +$ link/exe=attraction.exe screenhack,attraction,vms_decc.opt/opt +$ link/exe=blitspin.exe screenhack,blitspin,vms_decc.opt/opt +$ link/exe=bouboule.exe screenhack-xlock,bouboule,xlockmore,vms_decc.opt/opt +$ link/exe=braid.exe screenhack-xlock,braid,xlockmore,vms_decc.opt/opt +$ link/exe=bubbles.exe screenhack,bubbles,bubbles_default,vms_decc.opt/opt +$ link/exe=coral.exe screenhack,coral,vms_decc.opt/opt +$ link/exe=decayscreen.exe screenhack,decayscreen,vms_decc.opt/opt +$ link/exe=deco.exe screenhack,deco,vms_decc.opt/opt +$ link/exe=drift.exe screenhack-xlock,drift,xlockmore,vms_decc.opt/opt +$ link/exe=fadeplot.exe screenhack-xlock,fadeplot,xlockmore,vms_decc.opt/opt +$ link/exe=flag.exe screenhack-xlock,flag,xlockmore,vms_decc.opt/opt +$ link/exe=flame.exe screenhack,flame,vms_decc.opt/opt +$ link/exe=forest.exe screenhack-xlock,forest,xlockmore,vms_decc.opt/opt +$ link/exe=vines.exe screenhack-xlock,vines,xlockmore,vms_decc.opt/opt +$ link/exe=galaxy.exe screenhack-xlock,galaxy,xlockmore,vms_decc.opt/opt +$ link/exe=grav.exe screenhack-xlock,grav,xlockmore,vms_decc.opt/opt +$ link/exe=greynetic screenhack,greynetic,vms_decc.opt/opt +$ link/exe=halo.exe screenhack,halo,vms_decc.opt/opt +$ link/exe=helix.exe screenhack,helix,vms_decc.opt/opt +$ link/exe=hop.exe screenhack-xlock,hop,xlockmore,vms_decc.opt/opt +$ link/exe=hypercube.exe screenhack,hypercube,vms_decc.opt/opt +$ link/exe=ifs.exe screenhack-xlock,ifs,xlockmore,vms_decc.opt/opt +$ link/exe=imsmap.exe screenhack,imsmap,vms_decc.opt/opt +$ link/exe=julia.exe screenhack-xlock,julia,xlockmore,vms_decc.opt/opt +$ link/exe=kaleidescope.exe screenhack,kaleidescope,vms_decc.opt/opt +$ link/exe=laser.exe screenhack-xlock,laser,xlockmore,vms_decc.opt/opt +$ link/exe=lightning.exe screenhack-xlock,lightning,xlockmore,vms_decc.opt/opt +$ link/exe=lisa.exe screenhack-xlock,lisa,xlockmore,vms_decc.opt/opt +$ link/exe=lmorph.exe screenhack,lmorph,vms_decc.opt/opt +$ link/exe=maze.exe screenhack,maze,vms_decc.opt/opt +$ link/exe=moire.exe screenhack,moire,vms_decc.opt/opt +$ link/exe=noseguy.exe screenhack,noseguy,vms_decc.opt/opt +$ link/exe=pedal.exe screenhack,pedal,vms_decc.opt/opt +$ link/exe=penrose.exe screenhack-xlock,penrose,xlockmore,vms_decc.opt/opt +$ link/exe=pyro.exe screenhack,pyro,vms_decc.opt/opt +$ link/exe=qix.exe screenhack,qix,vms_decc.opt/opt +$ link/exe=rd-bomb.exe screenhack,rd-bomb,vms_decc.opt/opt +$ link/exe=rocks.exe screenhack,rocks,vms_decc.opt/opt +$ link/exe=rorschach.exe screenhack,rorschach,vms_decc.opt/opt +$ link/exe=sierpinski.exe screenhack-xlock,sierpinski,xlockmore,vms_decc.opt/opt +$ link/exe=slidescreen.exe screenhack,slidescreen,vms_decc.opt/opt +$ link/exe=slip.exe screenhack-xlock,slip,xlockmore,vms_decc.opt/opt +$ link/exe=sphere.exe screenhack-xlock,sphere,xlockmore,vms_decc.opt/opt +$ link/exe=spiral.exe screenhack-xlock,spiral,xlockmore,vms_decc.opt/opt +$ link/exe=strange.exe screenhack-xlock,strange,xlockmore,vms_decc.opt/opt +$ link/exe=swirl.exe screenhack-xlock,swirl,xlockmore,vms_decc.opt/opt +$ link/exe=goop.exe screenhack,goop,vms_decc.opt/opt +$ link/exe=starfish.exe screenhack,starfish,vms_decc.opt/opt +$ link/exe=munch.exe screenhack,munch,vms_decc.opt/opt +$ endif diff --git a/hacks/lisa.c b/hacks/lisa.c new file mode 100644 index 00000000..bc022bf3 --- /dev/null +++ b/hacks/lisa.c @@ -0,0 +1,751 @@ +/* -*- Mode: C; tab-width: 4 -*- */ +/* lisa --- animated full-loop lissajous figures */ + +#if 0 +static const char sccsid[] = "@(#)lisa.c 5.00 2000/11/01 xlockmore"; +#endif + +/*- + * Copyright (c) 1997, 2006 by Caleb Cullen. + * + * Permission to use, copy, modify, and distribute this software and its + * documentation for any purpose and without fee is hereby granted, + * provided that the above copyright notice appear in all copies and that + * both that copyright notice and this permission notice appear in + * supporting documentation. + * + * This file is provided AS IS with no warranties of any kind. The author + * shall have no liability with respect to the infringement of copyrights, + * trade secrets or any patents by this file or any part thereof. In no + * event will the author be liable for any lost revenue or profits or + * other special, indirect and consequential damages. + * + * Revision History: + * 23-Feb-2006: fixed color-cycling issues + * 01-Nov-2000: Allocation checks + * 10-May-1997: Compatible with xscreensaver + * + * The inspiration for this program, Lasp, was written by Adam B. Roach + * in 1990, assisted by me, Caleb Cullen. It was written first in C, then + * in assembly, and used pre-calculated data tables to graph lissajous + * figures on 386 machines and lower. This version bears only superficial + * resemblances to the original Lasp. + * + * The `lissie' module's source code was studied as an example of how + * to incorporate a new module into xlock. Resemblances to it are + * expected, but not intended to be plaigiaristic. + * + * February, 2006: 21st Century Update for Lisa + * + fixed color-mapping: the 'beginning' of the loop always uses the + * same (starting) pixel value, causing the loop's coloration to + * appear solid rather than flickering as in the previous version + * + all lines/points in a single color are drawn at once using XDrawLines() + * or XDrawPoints(); the artifacting evident in the previous version + * has been masked by the use of CapNotLast to separate individual drawn + * areas with intentional "whitespace" (typically black) + * + added many new elements to the Function[] array + * + randomized selection of next function + * + introduced concept of "rarely-chosen" functions + * + cleaned up code somewhat, standardized capitalization, commented all + * #directives with block labels + */ + +#ifdef STANDALONE +# define MODE_lisa +# define DEFAULTS "*delay: 17000 \n" \ + "*count: 1 \n" \ + "*cycles: 768 \n" \ + "*size: 500 \n" \ + "*ncolors: 64 \n" \ + "*fpsSolid: true \n" \ + +# define UNIFORM_COLORS +# define reshape_lisa 0 +# define lisa_handle_event 0 +# include "xlockmore.h" /* in xscreensaver distribution */ +#else /* STANDALONE */ +#include "xlock.h" /* in xlockmore distribution */ + +#endif /* STANDALONE */ + +#ifdef MODE_lisa + +#define DEF_ADDITIVE "True" + +static Bool additive; + +static XrmOptionDescRec opts[] = +{ + {"-additive", ".lisa.additive", XrmoptionNoArg, "True"}, + {"+additive", ".lisa.additive", XrmoptionNoArg, "False"} +}; + +static argtype vars[] = +{ + {&additive, "additive", "Additive", DEF_ADDITIVE, t_Bool} +}; + +static OptionStruct desc[] = +{ + {"-/+additive", "turn on/off additive functions mode"} +}; + +ENTRYPOINT ModeSpecOpt lisa_opts = +{sizeof opts / sizeof opts[0], opts, sizeof vars / sizeof vars[0], vars, desc}; + +#ifdef USE_MODULES +ModStruct lisa_description = +{"lisa", "init_lisa", "draw_lisa", "release_lisa", + "refresh_lisa", "change_lisa", (char *) NULL, &lisa_opts, + 17000, 1, 768, -1, 64, 1.0, "", + "Shows animated lissajous figures", 0, NULL}; + +#endif + +#define DRAWLINES 1 +/* #define FOLLOW_FUNC_ORDER 1 */ +#define TWOLOOPS 1 +#define XVMAX 10 /* Maximum velocities */ +#define YVMAX 10 +#define LISAMAXFUNCS 2 +#define NUMSTDFUNCS 28 +#define RAREFUNCMIN 25 +#define RAREFUNCODDS 4 /* 1:n chance a rare function will be re-randomized */ +#define MAXCYCLES 3 +#define MINLISAS 1 +#define STARTCOLOR 0 +#define STARTFUNC 24 /* if negative, is upper-bound on randomization */ +#define LINEWIDTH -8 /* if negative, is upper-bound on randomization */ +#define LINESTYLE LineSolid /* an insane man might have fun with this :) */ +#define LINECAP CapNotLast /* anything else looks pretty crappy */ +#define LINEJOIN JoinBevel /* this ought to be fastest */ +#define SET_COLOR() \ + if (MI_NPIXELS(mi) > 2) { \ + XSetForeground(MI_DISPLAY(mi), MI_GC(mi), MI_PIXEL(mi, loop->color)); \ + if (loop->cstep \ + && pctr % loop->cstep == 0 \ + && ++(loop->color) >= (unsigned) MI_NPIXELS(mi)) \ + { loop->color=STARTCOLOR; } \ + } else { XSetForeground(MI_DISPLAY(mi), MI_GC(mi), MI_WHITE_PIXEL(mi)); } +#define GET_RADIUS(context) \ + ((context->width > context->height)?context->height:context->width) * 3 / 8 +#define CHECK_RADIUS(loop, context) \ + if ((context->height / 2 > MI_SIZE(mi)) && (context->width / 2 > MI_SIZE(mi))) \ + loop->radius = MI_SIZE(mi); \ + if ((loop->radius < 0) || \ + (loop->radius > loop->center.x) || \ + (loop->radius > loop->center.y)) loop->radius = GET_RADIUS(context) +#define PRINT_FUNC(funcptr) \ + printf("new function -- #%d:\n\tx = sin(%gs) * sin(%gs)\n\ty = sin(%gt) * sin(%gt)\n", \ + funcptr->index, \ + funcptr->xcoeff[0], funcptr->xcoeff[1], \ + funcptr->ycoeff[0], funcptr->ycoeff[1]) + + +typedef struct lisafunc_struct { + double xcoeff[2], ycoeff[2]; + int nx, ny; + int index; +} lisafuncs; + +typedef struct lisa_struct { + unsigned long color; + int radius, dx, dy, nsteps, nfuncs, melting, cstep; + double pistep, phi, theta; + XPoint center, *lastpoint; + lisafuncs *function[LISAMAXFUNCS]; + int linewidth; +} lisas; + +typedef struct lisacontext_struct { + lisas *lissajous; + int width, height, nlissajous, loopcount; + int maxcycles; + Bool painted; +} lisacons; + +static lisacons *Lisa = (lisacons *) NULL; + +static lisafuncs Function[NUMSTDFUNCS] = + { + { + {1.0, 2.0}, + {1.0, 2.0}, 2, 2, 0}, + { + {1.0, 2.0}, + {1.0, 1.0}, 2, 2, 1}, + { + {1.0, 3.0}, + {1.0, 2.0}, 2, 2, 2}, + { + {1.0, 3.0}, + {1.0, 3.0}, 2, 2, 3}, + { + {2.0, 4.0}, + {1.0, 2.0}, 2, 2, 4}, + { + {1.0, 4.0}, + {1.0, 3.0}, 2, 2, 5}, + { + {1.0, 4.0}, + {1.0, 4.0}, 2, 2, 6}, + { + {1.0, 5.0}, + {1.0, 5.0}, 2, 2, 7}, + { + {2.0, 5.0}, + {2.0, 5.0}, 2, 2, 8}, + { + {1.0, 2.0}, + {2.0, 5.0}, 2, 2, 9}, + { + {1.0, 2.0}, + {3.0, 5.0}, 2, 2, 10}, + { + {1.0, 2.0}, + {2.0, 3.0}, 2, 2, 11}, + { + {1.0, 3.0}, + {2.0, 3.0}, 2, 2, 12}, + { + {2.0, 3.0}, + {1.0, 3.0}, 2, 2, 13}, + { + {2.0, 4.0}, + {1.0, 3.0}, 2, 2, 14}, + { + {1.0, 4.0}, + {2.0, 3.0}, 2, 2, 15}, + { + {2.0, 4.0}, + {2.0, 3.0}, 2, 2, 16}, + { + {1.0, 5.0}, + {2.0, 3.0}, 2, 2, 17}, + { + {2.0, 5.0}, + {2.0, 3.0}, 2, 2, 18}, + { + {1.0, 5.0}, + {2.0, 5.0}, 2, 2, 19}, + { + {1.0, 3.0}, + {2.0, 7.0}, 2, 2, 20}, + { + {2.0, 3.0}, + {5.0, 7.0}, 2, 2, 21}, + { + {1.0, 2.0}, + {3.0, 7.0}, 2, 2, 22}, + { + {2.0, 5.0}, + {5.0, 7.0}, 2, 2, 23}, + { + {5.0, 7.0}, + {5.0, 7.0}, 2, 2, 24}, + { /* functions past here are 'rare' and won't */ + {2.0, 7.0}, /* show up as often. tweak the #defines above */ + {1.0, 7.0}, 2, 2, 25}, /* to see them more frequently */ + { + {2.0, 9.0}, + {1.0, 7.0}, 2, 2, 26}, + { + {5.0, 11.0}, + {2.0, 9.0}, 2, 2, 27} +}; + +int xMaxLines; + +static void +free_lisa(lisacons *lc) +{ + while (lc->lissajous) { + int lctr; + + for (lctr = 0; lctr < lc->nlissajous; lctr++) { + (void) free((void *) lc->lissajous[lctr].lastpoint); + } + (void) free((void *) lc->lissajous); + lc->lissajous = (lisas *) NULL; + } +} + +static Bool +drawlisa(ModeInfo * mi, lisas * loop) +{ + XPoint *np; + XPoint *lp = loop->lastpoint; + lisacons *lc = &Lisa[MI_SCREEN(mi)]; + lisafuncs **lf = loop->function; + int phase = lc->loopcount % loop->nsteps; + int pctr, fctr, xctr, yctr, extra_points; + double xprod, yprod, xsum, ysum; + + /* why carry this around in the struct when we can calculate it on demand? */ + extra_points = loop->cstep - (loop->nsteps % loop->cstep); + + /* Allocate the np (new point) array (with padding) */ + if ((np = (XPoint *) calloc(loop->nsteps+extra_points, sizeof (XPoint))) == NULL) { + free_lisa(lc); + return False; + } + + /* Update the center */ + loop->center.x += loop->dx; + loop->center.y += loop->dy; + CHECK_RADIUS(loop, lc); + + /* check for overlaps -- where the figure might go off the screen */ + + if ((loop->center.x - loop->radius) <= 0) { + loop->center.x = loop->radius; + loop->dx = NRAND(XVMAX); + } else if ((loop->center.x + loop->radius) >= lc->width) { + loop->center.x = lc->width - loop->radius; + loop->dx = -NRAND(XVMAX); + }; + if ((loop->center.y - loop->radius) <= 0) { + loop->center.y = loop->radius; + loop->dy = NRAND(YVMAX); + } else if ((loop->center.y + loop->radius) >= lc->height) { + loop->center.y = lc->height - loop->radius; + loop->dy = -NRAND(YVMAX); + }; + + /* Now draw the points, and erase the ones from the last cycle */ + + for (pctr = 0; pctr < loop->nsteps; pctr++) { + fctr = loop->nfuncs; + loop->phi = (double) (pctr - phase) * loop->pistep; + loop->theta = (double) (pctr + phase) * loop->pistep; + xsum = ysum = 0; + while (fctr--) { + xctr = lf[fctr]->nx; + yctr = lf[fctr]->ny; + if (additive) { + xprod = yprod = 0.0; + while (xctr--) + xprod += sin(lf[fctr]->xcoeff[xctr] * loop->theta); + while (yctr--) + yprod += sin(lf[fctr]->ycoeff[yctr] * loop->phi); + if (loop->melting) { + if (fctr) { + xsum += xprod * (double) (loop->nsteps - loop->melting) / + (double) loop->nsteps; + ysum += yprod * (double) (loop->nsteps - loop->melting) / + (double) loop->nsteps; + } else { + xsum += xprod * (double) loop->melting / (double) loop->nsteps; + ysum += yprod * (double) loop->melting / (double) loop->nsteps; + } + } else { + xsum = xprod; + ysum = yprod; + } + if (!fctr) { + xsum = xsum * (double) loop->radius / (double) lf[fctr]->nx; + ysum = ysum * (double) loop->radius / (double) lf[fctr]->ny; + } + } else { + if (loop->melting) { + if (fctr) { + yprod = xprod = (double) loop->radius * + (double) (loop->nsteps - loop->melting) / + (double) (loop->nsteps); + } else { + yprod = xprod = (double) loop->radius * + (double) (loop->melting) / (double) (loop->nsteps); + } + } else { + xprod = yprod = (double) loop->radius; + } + while (xctr--) + xprod *= sin(lf[fctr]->xcoeff[xctr] * loop->theta); + while (yctr--) + yprod *= sin(lf[fctr]->ycoeff[yctr] * loop->phi); + xsum += xprod; + ysum += yprod; + } + } + if ((loop->nfuncs > 1) && (!loop->melting)) { + xsum /= (double) loop->nfuncs; + ysum /= (double) loop->nfuncs; + } + xsum += (double) loop->center.x; + ysum += (double) loop->center.y; + + np[pctr].x = (int) ceil(xsum); + np[pctr].y = (int) ceil(ysum); + } + /* fill in extra points */ + for (pctr=loop->nsteps; pctr < loop->nsteps+extra_points; pctr++) { + np[pctr].x = np[pctr - loop->nsteps].x; + np[pctr].y = np[pctr - loop->nsteps].y; + } + if (loop->melting) { + if (!--loop->melting) { + loop->nfuncs = 1; + loop->function[0] = loop->function[1]; + } + } + + /* reset starting color each time to prevent ass-like appearance */ + loop->color = STARTCOLOR; + + if (loop->cstep < xMaxLines) { + /* printf("Drawing dashes\n"); */ + for (pctr = 0; pctr < loop->nsteps; pctr+=loop->cstep) { +#if defined DRAWLINES + XSetLineAttributes(MI_DISPLAY(mi), MI_GC(mi), loop->linewidth, + LINESTYLE, LINECAP, LINEJOIN); + /* erase the last cycle's point */ + XSetForeground(MI_DISPLAY(mi), MI_GC(mi), MI_BLACK_PIXEL(mi)); + XDrawLines(MI_DISPLAY(mi), MI_WINDOW(mi), MI_GC(mi), &lp[pctr], + loop->cstep, CoordModeOrigin); + + /* Set the new color */ + SET_COLOR(); + + /* plot this cycle's point */ + XDrawLines(MI_DISPLAY(mi), MI_WINDOW(mi), MI_GC(mi), + &np[pctr], loop->cstep, CoordModeOrigin); + XSetLineAttributes(MI_DISPLAY(mi), MI_GC(mi), 1, + LINESTYLE, LINECAP, LINEJOIN); +#else + /* erase the last cycle's point */ + XSetForeground(MI_DISPLAY(mi), MI_GC(mi), MI_BLACK_PIXEL(mi)); + XDrawPoints(MI_DISPLAY(mi), MI_WINDOW(mi), MI_GC(mi), + &lp[pctr], loop->cstep, CoordModeOrigin); + + /* Set the new color */ + SET_COLOR(); + + /* plot this cycle's point */ + XDrawPoints(MI_DISPLAY(mi), MI_WINDOW(mi), + MI_GC(mi), &np[pctr], loop->cstep, CoordModeOrigin); +#endif + } + } else { /* on my system, cstep is larger than 65532/2 if we get here */ + for (pctr = 0; pctr < loop->nsteps; pctr++) { +#if defined DRAWLINES + XSetLineAttributes(MI_DISPLAY(mi), MI_GC(mi), loop->linewidth, + LINESTYLE, LINECAP, LINEJOIN); + /* erase the last cycle's point */ + XSetForeground(MI_DISPLAY(mi), MI_GC(mi), MI_BLACK_PIXEL(mi)); + XDrawLine(MI_DISPLAY(mi), MI_WINDOW(mi), + MI_GC(mi), lp[pctr].x, lp[pctr].y, + lp[(pctr + 1) % loop->nsteps].x, + lp[(pctr + 1) % loop->nsteps].y); + + /* Set the new color */ + SET_COLOR(); + + /* plot this cycle's point */ + XDrawLine(MI_DISPLAY(mi), MI_WINDOW(mi), + MI_GC(mi), np[pctr].x, np[pctr].y, + np[(pctr + 1) % loop->nsteps].x, + np[(pctr + 1) % loop->nsteps].y); + XSetLineAttributes(MI_DISPLAY(mi), MI_GC(mi), 1, + LINESTYLE, LINECAP, LINEJOIN); +#else /* DRAWLINES */ + /* erase the last cycle's point */ + XSetForeground(MI_DISPLAY(mi), MI_GC(mi), MI_BLACK_PIXEL(mi)); + XDrawPoint(MI_DISPLAY(mi), MI_WINDOW(mi), + MI_GC(mi), lp[pctr].x, lp[pctr].y); + + /* Set the new color */ + SET_COLOR(); + + /* plot this cycle's point */ + XDrawPoint(MI_DISPLAY(mi), MI_WINDOW(mi), + MI_GC(mi), np[pctr].x, np[pctr].y); +#endif /* DRAWLINES */ + } + } + (void) free((void *) lp); + loop->lastpoint = np; + return True; +} + +static Bool +initlisa(ModeInfo * mi, lisas * loop) +{ + lisacons *lc = &Lisa[MI_SCREEN(mi)]; + lisafuncs **lf = loop->function; + XPoint *lp; + int phase, pctr, fctr, xctr, yctr, extra_points; + double xprod, yprod, xsum, ysum; + + xMaxLines = (XMaxRequestSize(MI_DISPLAY(mi))-3)/2; + /* printf("Got xMaxLines = %d\n", xMaxLines); */ + loop->nsteps = MI_CYCLES(mi); + if (loop->nsteps == 0) + loop->nsteps = 1; + if (MI_NPIXELS(mi) > 2) { + loop->color = STARTCOLOR; + loop->cstep = (loop->nsteps > MI_NPIXELS(mi)) ? loop->nsteps / MI_NPIXELS(mi) : 1; + } else { + loop->color = MI_WHITE_PIXEL(mi); + loop->cstep = 0; + } + extra_points = loop->cstep - (loop->nsteps % loop->cstep); + lc->maxcycles = (MAXCYCLES * loop->nsteps) - 1; + loop->cstep = ( loop->nsteps > MI_NPIXELS(mi) ) ? loop->nsteps / MI_NPIXELS(mi) : 1; + /* printf("Got cstep = %d\n", loop->cstep); */ + loop->melting = 0; + loop->nfuncs = 1; + loop->pistep = 2.0 * M_PI / (double) loop->nsteps; + loop->center.x = lc->width / 2; + loop->center.y = lc->height / 2; + loop->radius = (int) MI_SIZE(mi); + CHECK_RADIUS(loop, lc); + loop->dx = NRAND(XVMAX); + loop->dy = NRAND(YVMAX); + loop->dx++; + loop->dy++; +#if defined STARTFUNC + lf[0] = &Function[STARTFUNC]; +#else /* STARTFUNC */ + lf[0] = &Function[NRAND(NUMSTDFUNCS)]; +#endif /* STARTFUNC */ + + if ((lp = loop->lastpoint = (XPoint *) + calloc(loop->nsteps+extra_points, sizeof (XPoint))) == NULL) { + free_lisa(lc); + return False; + } + phase = lc->loopcount % loop->nsteps; + +#if defined DEBUG + printf( "nsteps = %d\tcstep = %d\tmrs = %d\textra_points = %d\n", + loop->nsteps, loop->cstep, xMaxLines, extra_points ); + PRINT_FUNC(lf[0]); +#endif /* DEBUG */ + + for (pctr = 0; pctr < loop->nsteps; pctr++) { + loop->phi = (double) (pctr - phase) * loop->pistep; + loop->theta = (double) (pctr + phase) * loop->pistep; + fctr = loop->nfuncs; + xsum = ysum = 0.0; + while (fctr--) { + xprod = yprod = (double) loop->radius; + xctr = lf[fctr]->nx; + yctr = lf[fctr]->ny; + while (xctr--) + xprod *= sin(lf[fctr]->xcoeff[xctr] * loop->theta); + while (yctr--) + yprod *= sin(lf[fctr]->ycoeff[yctr] * loop->phi); + xsum += xprod; + ysum += yprod; + } + if (loop->nfuncs > 1) { + xsum /= 2.0; + ysum /= 2.0; + } + xsum += (double) loop->center.x; + ysum += (double) loop->center.y; + + lp[pctr].x = (int) ceil(xsum); + lp[pctr].y = (int) ceil(ysum); + } + /* this fills in the extra points, so we can use segment-drawing calls */ + for (pctr = loop->nsteps; pctr < loop->nsteps + extra_points; pctr++) { + lp[pctr].x=lp[pctr - loop->nsteps].x; + lp[pctr].y=lp[pctr - loop->nsteps].y; + } +#if defined DRAWLINES + loop->linewidth = LINEWIDTH; /* #### make this a resource */ + + if (loop->linewidth == 0) + loop->linewidth = 1; + if (loop->linewidth < 0) + loop->linewidth = NRAND(-loop->linewidth) + 1; + XSetLineAttributes(MI_DISPLAY(mi), MI_GC(mi), loop->linewidth, + LINESTYLE, LINECAP, LINEJOIN); +#endif /* DRAWLINES */ + + if ( loop->cstep < xMaxLines ) { + /* we can send each color segment in a single request + * because the max request length is long enough + * and because we have padded out the array to have extra elements + * to support calls which would otherwise fall off the end*/ + for (pctr = 0; pctr < loop->nsteps; pctr+=loop->cstep) { + /* Set the color */ + SET_COLOR(); + +#if defined DRAWLINES + XDrawLines(MI_DISPLAY(mi), MI_WINDOW(mi), + MI_GC(mi), &lp[pctr], loop->cstep, CoordModeOrigin ); +#else /* DRAWLINES */ + XDrawPoints(MI_DISPLAY(mi), MI_WINDOW(mi), MI_GC(mi), + &lp[pctr], loop->cstep, CoordModeOrigin ); +#endif /* DRAWLINES */ + } + } else { /* do it one by one as before */ + for (pctr = 0; pctr < loop->nsteps; pctr++ ) { + SET_COLOR(); + +#if defined DRAWLINES + XDrawLine(MI_DISPLAY(mi), MI_WINDOW(mi), MI_GC(mi), + lp[pctr].x, lp[pctr].y, + lp[pctr+1 % loop->nsteps].x, lp[pctr+1 % loop->nsteps].y); +#else /* DRAWLINES */ + XDrawPoint(MI_DISPLAY(mi), MI_WINDOW(mi), MI_GC(mi), + lp[pctr].x, lp[pctr].y); +#endif /* DRAWLINES */ + } + } + +#if defined DRAWLINES + XSetLineAttributes(MI_DISPLAY(mi), MI_GC(mi), 1, + LINESTYLE, LINECAP, LINEJOIN); +#endif /* DRAWLINES */ + return True; +} + +static void +refreshlisa(ModeInfo * mi) +{ + lisacons *lc = &Lisa[MI_SCREEN(mi)]; + int lctr; + + for (lctr = 0; lctr < lc->nlissajous; lctr++) { + if (!drawlisa(mi, &lc->lissajous[lctr])) + return; + } +} + +ENTRYPOINT void +refresh_lisa(ModeInfo * mi) +{ + lisacons *lc; + + if (Lisa == NULL) + return; + lc = &Lisa[MI_SCREEN(mi)]; + if (lc->lissajous == NULL) + return; + + if (lc->painted) { + lc->painted = False; + MI_CLEARWINDOW(mi); + refreshlisa(mi); + } +} + +static void +change_lisa(ModeInfo * mi) +{ + lisas *loop; + int lctr, newfunc; + lisacons *lc; + + if (Lisa == NULL) + return; + lc = &Lisa[MI_SCREEN(mi)]; + if (lc->lissajous == NULL) + return; + + lc->loopcount = 0; + for (lctr = 0; lctr < lc->nlissajous; lctr++) { + loop = &lc->lissajous[lctr]; /* count through the loops we're drawing */ + newfunc = NRAND(NUMSTDFUNCS); /* choose a new function at random */ +#if defined FOLLOW_FUNC_ORDER + loop->function[1] = + &Function[(loop->function[0]->index + 1) % NUMSTDFUNCS]; +#else /* FOLLOW_FUNC_ORDER */ + if (newfunc == loop->function[0]->index) { + ++newfunc; + newfunc %= NUMSTDFUNCS; /* take the next if we got the one we have */ + } + if (newfunc >= RAREFUNCMIN \ + && !(random() % RAREFUNCODDS) \ + && (newfunc = NRAND(NUMSTDFUNCS)) == loop->function[0]->index) { + ++newfunc; + newfunc %= NUMSTDFUNCS; + } + loop->function[1] = /* set 2nd function pointer on the loop */ + &Function[newfunc]; /* to the new function we just chose */ +#endif /* FOLLOW_FUNC_ORDER */ +#if defined DEBUG + PRINT_FUNC(loop->function[1]); +#endif /* DEBUG */ + loop->melting = loop->nsteps - 1; /* melt the two functions together */ + loop->nfuncs = 2; /* simultaneously for a full cycle */ + } +} + +ENTRYPOINT void +init_lisa (ModeInfo * mi) +{ + int lctr; + lisacons *lc; + + if (Lisa == NULL) { + if ((Lisa = (lisacons *) calloc(MI_NUM_SCREENS(mi), + sizeof (lisacons))) == NULL) + return; + } + lc = &Lisa[MI_SCREEN(mi)]; + lc->width = MI_WIDTH(mi); + lc->height = MI_HEIGHT(mi); + lc->loopcount = 0; + lc->nlissajous = MI_COUNT(mi); + if (lc->nlissajous <= 0) + lc->nlissajous = 1; + MI_CLEARWINDOW(mi); + lc->painted = False; + + if (lc->lissajous == NULL) { + if ((lc->lissajous = (lisas *) calloc(lc->nlissajous, + sizeof (lisas))) == NULL) + return; + for (lctr = 0; lctr < lc->nlissajous; lctr++) { + if (!initlisa(mi, &lc->lissajous[lctr])) + return; + lc->loopcount++; + } + } else { + refreshlisa(mi); + } +} + +ENTRYPOINT void +draw_lisa (ModeInfo * mi) +{ + lisacons *lc; + + if (Lisa == NULL) + return; + lc = &Lisa[MI_SCREEN(mi)]; + if (lc->lissajous == NULL) + return; + +#ifdef HAVE_COCOA /* Don't second-guess Quartz's double-buffering */ + XClearWindow (MI_DISPLAY(mi), MI_WINDOW(mi)); +#endif + + MI_IS_DRAWN(mi) = True; + lc->painted = True; + if (++lc->loopcount > lc->maxcycles) { + change_lisa(mi); + } + refreshlisa(mi); +} + +ENTRYPOINT void +release_lisa (ModeInfo * mi) +{ + if (Lisa) { + int screen; + + for (screen = 0; screen < MI_NUM_SCREENS(mi); screen++) + free_lisa(&Lisa[screen]); + (void) free(Lisa); + Lisa = (lisacons *) NULL; + } +} + +XSCREENSAVER_MODULE ("Lisa", lisa) + +#endif /* MODE_lisa */ diff --git a/hacks/lisa.man b/hacks/lisa.man new file mode 100644 index 00000000..2bfd7f45 --- /dev/null +++ b/hacks/lisa.man @@ -0,0 +1,71 @@ +.TH XScreenSaver 1 "27-May-97" "X Version 11" +.SH NAME +lisa - draws animated full-loop lissajous figures +.SH SYNOPSIS +.B lisa +[\-display \fIhost:display.screen\fP] [\-foreground \fIcolor\fP] [\-background \fIcolor\fP] [\-window] [\-root] [\-mono] [\-install] [\-visual \fIvisual\fP] [\-ncolors \fIinteger\fP] [\-delay \fImicroseconds\fP] [\-cycles \fIinteger\fP] [\-count \fIinteger\fP] [\-size \fIinteger\fP] + +[\-fps] +.SH DESCRIPTION +The \fIlisa\fP program draws animated full-loop lissajous figures. +.SH OPTIONS +.I lisa +accepts the following options: +.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 \-mono +If on a color display, pretend we're on a monochrome display. +.TP 8 +.B \-install +Install a private colormap for the window. +.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 \-ncolors \fIinteger\fP +How many colors should be used (if possible). Default 200. +The colors are chosen randomly. +.TP 8 +.B \-cycles \fIinteger\fP + +.TP 8 +.B \-count \fIinteger\fP + +.TP 8 +.B \-size \fIinteger\fP + +.TP 8 +.B \-fps +Display the current frame rate and CPU load. +.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), +.BR xlock (1) +.SH COPYRIGHT +Copyright \(co 1997 by Caleb Cullen. + +Permission to use, copy, modify, and distribute this software and its +documentation for any purpose and without fee is hereby granted, +provided that the above copyright notice appear in all copies and that +both that copyright notice and this permission notice appear in +supporting documentation. +.SH AUTHOR +Caleb Cullen, 1997. + +Ability to run standalone or with \fIxscreensaver\fP added by +Jamie Zawinski , 27-May-97. diff --git a/hacks/lissie.c b/hacks/lissie.c new file mode 100644 index 00000000..ac18c52f --- /dev/null +++ b/hacks/lissie.c @@ -0,0 +1,329 @@ +/* -*- Mode: C; tab-width: 4 -*- */ +/* lissie --- the Lissajous worm */ + +#if 0 +static const char sccsid[] = "@(#)lissie.c 5.00 2000/11/01 xlockmore"; +#endif + +/*- + * lissie.c - The Lissajous worm for xlock, the X Window System + * lockscreen. + * + * Copyright (c) 1996 by Alexander Jolk + * + * Permission to use, copy, modify, and distribute this software and its + * documentation for any purpose and without fee is hereby granted, + * provided that the above copyright notice appear in all copies and that + * both that copyright notice and this permission notice appear in + * supporting documentation. + * + * This file is provided AS IS with no warranties of any kind. The author + * shall have no liability with respect to the infringement of copyrights, + * trade secrets or any patents by this file or any part thereof. In no + * event will the author be liable for any lost revenue or profits or + * other special, indirect and consequential damages. + * + * Revision History: + * 01-Nov-2000: Allocation checks + * 10-May-1997: Compatible with xscreensaver + * 18-Aug-1996: added refresh-hook. + * 01-May-1996: written. + */ + +#ifdef STANDALONE +# define MODE_lissie +# define DEFAULTS "*delay: 10000 \n" \ + "*count: 1 \n" \ + "*cycles: 20000 \n" \ + "*size: -200 \n" \ + "*ncolors: 200 \n" \ + "*fpsSolid: true \n" \ + +# define SMOOTH_COLORS +# define reshape_lissie 0 +# define lissie_handle_event 0 +# include "xlockmore.h" /* in xscreensaver distribution */ +#else /* STANDALONE */ +# include "xlock.h" /* in xlockmore distribution */ +#endif /* STANDALONE */ + +#ifdef MODE_lissie + +ENTRYPOINT ModeSpecOpt lissie_opts = +{0, (XrmOptionDescRec *) NULL, 0, (argtype *) NULL, (OptionStruct *) NULL}; + +#ifdef USE_MODULES +ModStruct lissie_description = +{"lissie", "init_lissie", "draw_lissie", "release_lissie", + "refresh_lissie", "init_lissie", (char *) NULL, &lissie_opts, + 10000, 1, 2000, -200, 64, 0.6, "", + "Shows lissajous worms", 0, NULL}; + +#endif + +#define MINSIZE 1 + +#define Lissie(n)\ + if (lissie->loc[(n)].x > 0 && lissie->loc[(n)].y > 0 &&\ + lissie->loc[(n)].x <= lp->width && lissie->loc[(n)].y <= lp->height) {\ + if (lissie->ri < 2)\ + XDrawPoint(display, MI_WINDOW(mi),\ + gc, lissie->loc[(n)].x, lissie->loc[(n)].y);\ + else\ + XDrawArc(display, MI_WINDOW(mi), gc,\ + lissie->loc[(n)].x - lissie->ri / 2,\ + lissie->loc[(n)].y - lissie->ri / 2,\ + lissie->ri, lissie->ri, 0, 23040);\ + } + +#define FLOATRAND(min,max) ((min)+(LRAND()/MAXRAND)*((max)-(min))) +#define INTRAND(min,max) ((min)+NRAND((max)-(min)+1)) + +#define MINDT 0.01 +#define MAXDT 0.15 + +#define MAXLISSIELEN 100 +#define MINLISSIELEN 10 +#define MINLISSIES 1 + +/* How many segments to draw per cycle when redrawing */ +#define REDRAWSTEP 3 + +typedef struct { + double tx, ty, dtx, dty; + int xi, yi, ri, rx, ry, len, pos; + int redrawing, redrawpos; + XPoint loc[MAXLISSIELEN]; + unsigned long color; +} lissiestruct; + +typedef struct { + Bool painted; + int width, height; + int nlissies; + lissiestruct *lissie; + int loopcount; +} lissstruct; + +static lissstruct *lisses = (lissstruct *) NULL; + + +static void +drawlissie(ModeInfo * mi, lissiestruct * lissie) +{ + Display *display = MI_DISPLAY(mi); + GC gc = MI_GC(mi); + lissstruct *lp = &lisses[MI_SCREEN(mi)]; + int p = (++lissie->pos) % MAXLISSIELEN; + int oldp = (lissie->pos - lissie->len + MAXLISSIELEN) % MAXLISSIELEN; + + /* Let time go by ... */ + lissie->tx += lissie->dtx; + lissie->ty += lissie->dty; + if (lissie->tx > 2 * M_PI) + lissie->tx -= 2 * M_PI; + if (lissie->ty > 2 * M_PI) + lissie->ty -= 2 * M_PI; + + /* vary both (x/y) speeds by max. 1% */ + lissie->dtx *= FLOATRAND(0.99, 1.01); + lissie->dty *= FLOATRAND(0.99, 1.01); + if (lissie->dtx < MINDT) + lissie->dtx = MINDT; + else if (lissie->dtx > MAXDT) + lissie->dtx = MAXDT; + if (lissie->dty < MINDT) + lissie->dty = MINDT; + else if (lissie->dty > MAXDT) + lissie->dty = MAXDT; + + lissie->loc[p].x = lissie->xi + (int) (sin(lissie->tx) * lissie->rx); + lissie->loc[p].y = lissie->yi + (int) (sin(lissie->ty) * lissie->ry); + + /* Mask */ + XSetForeground(display, gc, MI_BLACK_PIXEL(mi)); + Lissie(oldp); + + /* Redraw */ + if (MI_NPIXELS(mi) > 2) { + XSetForeground(display, gc, MI_PIXEL(mi, lissie->color)); + if (++lissie->color >= (unsigned) MI_NPIXELS(mi)) + lissie->color = 0; + } else + XSetForeground(display, gc, MI_WHITE_PIXEL(mi)); + Lissie(p); + if (lissie->redrawing) { + int i; + + lissie->redrawpos++; + /* This compensates for the changed p + since the last callback. */ + + for (i = 0; i < REDRAWSTEP; i++) { + Lissie((p - lissie->redrawpos + MAXLISSIELEN) % MAXLISSIELEN); + if (++(lissie->redrawpos) >= lissie->len) { + lissie->redrawing = 0; + break; + } + } + } +} + +static void +initlissie(ModeInfo * mi, lissiestruct * lissie) +{ + lissstruct *lp = &lisses[MI_SCREEN(mi)]; + int size = MI_SIZE(mi); + int i; + + if (MI_NPIXELS(mi) > 2) + lissie->color = NRAND(MI_NPIXELS(mi)); + else + lissie->color = MI_WHITE_PIXEL(mi); + /* Initialize parameters */ + if (size < -MINSIZE) + lissie->ri = NRAND(MIN(-size, MAX(MINSIZE, + MIN(lp->width, lp->height) / 4)) - MINSIZE + 1) + MINSIZE; + else if (size < MINSIZE) { + if (!size) + lissie->ri = MAX(MINSIZE, MIN(lp->width, lp->height) / 4); + else + lissie->ri = MINSIZE; + } else + lissie->ri = MIN(size, MAX(MINSIZE, MIN(lp->width, lp->height) / 4)); + lissie->xi = INTRAND(lp->width / 4 + lissie->ri, + lp->width * 3 / 4 - lissie->ri); + lissie->yi = INTRAND(lp->height / 4 + lissie->ri, + lp->height * 3 / 4 - lissie->ri); + lissie->rx = INTRAND(lp->width / 4, + MIN(lp->width - lissie->xi, lissie->xi)) - 2 * lissie->ri; + lissie->ry = INTRAND(lp->height / 4, + MIN(lp->height - lissie->yi, lissie->yi)) - 2 * lissie->ri; + lissie->len = INTRAND(MINLISSIELEN, MAXLISSIELEN - 1); + lissie->pos = 0; + + lissie->redrawing = 0; + + lissie->tx = FLOATRAND(0, 2 * M_PI); + lissie->ty = FLOATRAND(0, 2 * M_PI); + lissie->dtx = FLOATRAND(MINDT, MAXDT); + lissie->dty = FLOATRAND(MINDT, MAXDT); + + for (i = 0; i < MAXLISSIELEN; i++) + lissie->loc[i].x = lissie->loc[i].y = 0; + /* Draw lissie */ + drawlissie(mi, lissie); +} + +ENTRYPOINT void +init_lissie (ModeInfo * mi) +{ + lissstruct *lp; + unsigned char ball; + + if (lisses == NULL) { + if ((lisses = (lissstruct *) calloc(MI_NUM_SCREENS(mi), + sizeof (lissstruct))) == NULL) + return; + } + lp = &lisses[MI_SCREEN(mi)]; + + lp->width = MI_WIDTH(mi); + +#ifdef HAVE_COCOA + jwxyz_XSetAntiAliasing (MI_DISPLAY(mi), MI_GC(mi), False); +#endif + + lp->height = MI_HEIGHT(mi); + + lp->nlissies = MI_COUNT(mi); + if (lp->nlissies < -MINLISSIES) { + if (lp->lissie) { + (void) free((void *) lp->lissie); + lp->lissie = (lissiestruct *) NULL; + } + lp->nlissies = NRAND(-lp->nlissies - MINLISSIES + 1) + MINLISSIES; + } else if (lp->nlissies < MINLISSIES) + lp->nlissies = MINLISSIES; + + lp->loopcount = 0; + + if (lp->lissie == NULL) + if ((lp->lissie = (lissiestruct *) calloc(lp->nlissies, + sizeof (lissiestruct))) == NULL) + return; + + MI_CLEARWINDOW(mi); + lp->painted = False; + + for (ball = 0; ball < (unsigned char) lp->nlissies; ball++) + initlissie(mi, &lp->lissie[ball]); + +} + +ENTRYPOINT void +draw_lissie (ModeInfo * mi) +{ + register unsigned char ball; + lissstruct *lp; + + if (lisses == NULL) + return; + lp = &lisses[MI_SCREEN(mi)]; + if (lp->lissie == NULL) + return; + + MI_IS_DRAWN(mi) = True; + + if (++lp->loopcount > MI_CYCLES(mi)) { + init_lissie(mi); + } else { + lp->painted = True; + for (ball = 0; ball < (unsigned char) lp->nlissies; ball++) + drawlissie(mi, &lp->lissie[ball]); + } +} + +ENTRYPOINT void +release_lissie (ModeInfo * mi) +{ + if (lisses != NULL) { + int screen; + + for (screen = 0; screen < MI_NUM_SCREENS(mi); screen++) { + lissstruct *lp = &lisses[screen]; + + if (lp->lissie != NULL) { + (void) free((void *) lp->lissie); + /* lp->lissie = NULL; */ + } + } + (void) free((void *) lisses); + lisses = (lissstruct *) NULL; + } +} + +ENTRYPOINT void +refresh_lissie(ModeInfo * mi) +{ + int i; + lissstruct *lp; + + if (lisses == NULL) + return; + lp = &lisses[MI_SCREEN(mi)]; + if (lp->lissie == NULL) + return; + + if (lp->painted) { + MI_CLEARWINDOW(mi); + for (i = 0; i < lp->nlissies; i++) { + lp->lissie[i].redrawing = 1; + lp->lissie[i].redrawpos = 0; + } + } +} + +XSCREENSAVER_MODULE ("Lissie", lissie) + +#endif /* MODE_lissie */ diff --git a/hacks/lissie.man b/hacks/lissie.man new file mode 100644 index 00000000..43123b20 --- /dev/null +++ b/hacks/lissie.man @@ -0,0 +1,69 @@ +.TH XScreenSaver 1 "" "X Version 11" +.SH NAME +lissie - lissajous figure. +.SH SYNOPSIS +.B lissie +[\-display \fIhost:display.screen\fP] +[\-visual \fIvisual\fP] +[\-window] +[\-root] +[\-count \fInumber\fP] +[\-cycles \fInumber\fP] +[\-delay \fInumber\fP] +[\-ncolors \fInumber\fP] +[\-size \fInumber\fP] +[\-fps] +.SH DESCRIPTION +Another Lissajous figure. This one draws the progress of circular shapes +along a path. +.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 \-count \fInumber\fP +Count. 0 - 20. Default: 1. +.TP 8 +.B \-cycles \fInumber\fP +Timeout. Default: 20000. +.TP 8 +.B \-delay \fInumber\fP +Per-frame delay, in microseconds. Default: 10000 (0.01 seconds.). +.TP 8 +.B \-ncolors \fInumber\fP +Number of Colors. Default: 200. +.TP 8 +.B \-size \fInumber\fP +Size. -500 to +500. Default: -200. +.TP 8 +.B \-fps +Display the current frame rate and CPU load. +.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 2002 by Alexander Jolk. 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 +Alexander Jolk. diff --git a/hacks/ljlatest b/hacks/ljlatest new file mode 100755 index 00000000..a9623380 --- /dev/null +++ b/hacks/ljlatest @@ -0,0 +1,18 @@ +#!/bin/sh +# Copyright © 2003, 2004, 2005 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. +# +# Created: 30-Aug-2003. +# +# Spits out the text of the most recent public posts on livejournal.com. +# This works as the "-program" argument to phosphor, starwars, etc. + +exec xscreensaver-text \ + --url http://www.livejournal.com/stats/latest-rss.bml "$@" diff --git a/hacks/ljlatest.man b/hacks/ljlatest.man new file mode 100644 index 00000000..21fe4500 --- /dev/null +++ b/hacks/ljlatest.man @@ -0,0 +1,61 @@ +.de EX \"Begin example +.ne 5 +.if n .sp 1 +.if t .sp .5 +.nf +.in +.5i +.. +.de EE +.fi +.in -.5i +.if n .sp 1 +.if t .sp .5 +.. +.TH XScreenSaver 1 "20-Mar-2005" "X Version 11" +.SH NAME +ljlatest - prints the most recent public posts on livejournal.com. +.SH SYNOPSIS +.B ljlatest +[\--verbose] +[\--columns \fIN\fP] +.SH DESCRIPTION +The \fIljlatest\fP script reads the most recent public posts made to +livejournal.com, and prints them on stdout, after doing a rudimentary +conversion of HTML to plain text. + +This script is just a wrapper around +.EX +xscreensaver-text \\ + --url http://www.livejournal.com/stats/latest-rss.bml +.EE +As of XScreenSaver 4.21, you can just use use above URL +in the "Text URL" field on the "Advanced" tab in +.BR xscreensaver-demo (1). +.SH BUGS +This program makes it seem like morons have invaded your screen saver. + +The output is always ISO-8859-1, regardless of locale. +.SH SEE ALSO +.I http://www.livejournal.com/, +.BR xscreensaver (1), +.BR xscreensaver-text (1), +.BR fortune (1), +.BR phosphor (MANSUFFIX), +.BR apple2 (MANSUFFIX), +.BR starwars (MANSUFFIX), +.BR fontglide (MANSUFFIX), +.BR dadadodo (1), +.BR webcollage (MANSUFFIX), +.BR driftnet (1) +.BR EtherPEG , +.BR EtherPeek +.SH COPYRIGHT +Copyright \(co 2003, 2005 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 , 30-Aug-2003. diff --git a/hacks/lmorph.c b/hacks/lmorph.c new file mode 100644 index 00000000..9468a72a --- /dev/null +++ b/hacks/lmorph.c @@ -0,0 +1,568 @@ +/* lmorph, Copyright (c) 1993-1999 Sverre H. Huseby and Glenn T. Lines + * + * 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. + */ + +/*------------------------------------------------------------------------ + | + | FILE lmorph.c + | MODULE OF xscreensaver + | + | DESCRIPTION Smooth and non-linear morphing between 1D curves. + | + | WRITTEN BY Sverre H. Huseby Glenn T. Lines + | Kurvn. 30 Østgaardsgt. 5 + | N-0495 Oslo N-0474 Oslo + | Norway Norway + | + | Phone: +47 901 63 579 Phone: +47 22 04 67 28 + | E-mail: sverrehu@online.no E-mail: glennli@ifi.uio.no + | URL: http://home.sol.no/~sverrehu/ + | + | The original idea, and the bilinear interpolation + | mathematics used, emerged in the head of the wise + | Glenn T. Lines. + | + | MODIFICATIONS october 1999 (shh) + | * Removed option to use integer arithmetic. + | * Increased default number of points, and brightened + | the foreground color a little bit. + | * Minor code cleanup (very minor, that is). + | * Default number of steps is no longer random. + | * Added -linewidth option (and resource). + | + | october 1999 (gtl) + | * Added cubic interpolation between shapes + | * Added non-linear transformation speed + | + | june 1998 (shh) + | * Minor code cleanup. + | + | january 1997 (shh) + | * Some code reformatting. + | * Added possibility to use float arithmetic. + | * Added -figtype option. + | * Made color blue default. + | + | december 1995 (jwz) + | * Function headers converted from ANSI to K&R. + | * Added posibility for random number of steps, and + | made this the default. + | + | march 1995 (shh) + | * Converted from an MS-Windows program to X Window. + | + | november 1993 (gtl, shh, lots of beer) + | * Original Windows version (we didn't know better). + +----------------------------------------------------------------------*/ + +#include +#include "screenhack.h" + +/*-----------------------------------------------------------------------+ +| PRIVATE DATA | ++-----------------------------------------------------------------------*/ + +/* define MARGINS to make some space around the figure. */ +#define MARGINS + +#define MAXFIGS 20 +#define TWO_PI (2.0 * M_PI) +#define RND(x) (random() % (x)) + +#define FT_OPEN 1 +#define FT_CLOSED 2 +#define FT_ALL (FT_OPEN | FT_CLOSED) + +struct state { + Display *dpy; + Window window; + + int numFigs; /* number of figure arrays. */ + int numPoints; /* number of points in each array. */ + int nWork; /* current work array number. */ + int nFrom; /* current from array number. */ + int nTo; /* current to array number. */ + int nNext; /* current next array number (after to).*/ + int shift; /* shifts the starting point of a figure */ + int figType; + + long delay; /* usecs to wait between updates. */ + + XPoint *aWork[2]; /* working arrays. */ + XPoint *a[MAXFIGS]; /* the figure arrays. */ + XPoint *aTmp; /* used as source when interrupting morph */ + XPoint *aPrev; /* previous points displayed. */ + XPoint *aCurr; /* the current points displayed. */ + XPoint *aFrom; /* figure converting from. */ + XPoint *aTo; /* figure converting to. */ + XPoint *aNext; /* figure converting to next time. */ + XPoint *aSlopeFrom; /* slope at start of morph */ + XPoint *aSlopeTo; /* slope at end of morph */ + + int scrWidth, scrHeight; + double currGamma, maxGamma, deltaGamma; + GC gcDraw, gcClear; +}; + + +/*-----------------------------------------------------------------------+ +| PUBLIC DATA | ++-----------------------------------------------------------------------*/ + +static const char *lmorph_defaults [] = { + ".background: black", + ".foreground: #4444FF", + "*points: 200", + "*steps: 150", + "*delay: 70000", + "*figtype: all", + "*linewidth: 5", + 0 +}; + +static XrmOptionDescRec lmorph_options [] = { + { "-points", ".points", XrmoptionSepArg, 0 }, + { "-steps", ".steps", XrmoptionSepArg, 0 }, + { "-delay", ".delay", XrmoptionSepArg, 0 }, + { "-figtype", ".figtype", XrmoptionSepArg, 0 }, + { "-linewidth", ".linewidth", XrmoptionSepArg, 0 }, + { 0, 0, 0, 0 } +}; + +/*-----------------------------------------------------------------------+ +| PRIVATE FUNCTIONS | ++-----------------------------------------------------------------------*/ + +static void * +xmalloc(size_t size) +{ + void *ret; + + if ((ret = malloc(size)) == NULL) { + fprintf(stderr, "lmorph: out of memory\n"); + exit(1); + } + return ret; +} + +static void +initPointArrays(struct state *st) +{ + int q, w; + int mx, my; /* max screen coordinates. */ + int mp; /* max point number. */ + int s, rx, ry; + int marginx, marginy; + double scalex, scaley; + + mx = st->scrWidth - 1; + my = st->scrHeight - 1; + mp = st->numPoints - 1; + + st->aWork[0] = (XPoint *) xmalloc(st->numPoints * sizeof(XPoint)); + st->aWork[1] = (XPoint *) xmalloc(st->numPoints * sizeof(XPoint)); + st->aTmp = (XPoint *) xmalloc(st->numPoints * sizeof(XPoint)); + + if (st->figType & FT_CLOSED) { + /* rectangle */ + st->a[st->numFigs] = (XPoint *) xmalloc(st->numPoints * sizeof(XPoint)); + s = st->numPoints / 4; + for (q = 0; q < s; q++) { + st->a[st->numFigs][q].x = ((double) q / s) * mx; + st->a[st->numFigs][q].y = 0; + st->a[st->numFigs][s + q].x = mx; + st->a[st->numFigs][s + q].y = ((double) q / s) * my; + st->a[st->numFigs][2 * s + q].x = mx - ((double) q / s) * mx; + st->a[st->numFigs][2 * s + q].y = my; + st->a[st->numFigs][3 * s + q].x = 0; + st->a[st->numFigs][3 * s + q].y = my - ((double) q / s) * my; + } + for (q = 4 * s; q < st->numPoints; q++) + st->a[st->numFigs][q].x = st->a[st->numFigs][q].y = 0; + st->a[st->numFigs][mp].x = st->a[st->numFigs][0].x; + st->a[st->numFigs][mp].y = st->a[st->numFigs][0].y; + ++st->numFigs; + + /* */ + st->a[st->numFigs] = (XPoint *) xmalloc(st->numPoints * sizeof(XPoint)); + rx = mx / 2; + ry = my / 2; + for (q = 0; q < st->numPoints; q++) { + st->a[st->numFigs][q].x = mx / 2 + rx * sin(1 * TWO_PI * (double) q / mp); + st->a[st->numFigs][q].y = my / 2 + ry * cos(3 * TWO_PI * (double) q / mp); + } + st->a[st->numFigs][mp].x = st->a[st->numFigs][0].x; + st->a[st->numFigs][mp].y = st->a[st->numFigs][0].y; + ++st->numFigs; + + /* */ + st->a[st->numFigs] = (XPoint *) xmalloc(st->numPoints * sizeof(XPoint)); + rx = mx / 2; + ry = my / 2; + for (q = 0; q < st->numPoints; q++) { + st->a[st->numFigs][q].x = mx / 2 + ry * sin(3 * TWO_PI * (double) q / mp); + st->a[st->numFigs][q].y = my / 2 + ry * cos(1 * TWO_PI * (double) q / mp); + } + st->a[st->numFigs][mp].x = st->a[st->numFigs][0].x; + st->a[st->numFigs][mp].y = st->a[st->numFigs][0].y; + ++st->numFigs; + + /* */ + st->a[st->numFigs] = (XPoint *) xmalloc(st->numPoints * sizeof(XPoint)); + rx = mx / 2; + ry = my / 2; + for (q = 0; q < st->numPoints; q++) { + st->a[st->numFigs][q].x = mx / 2 + ry + * (0.8 - 0.2 * sin(30 * TWO_PI * q / mp)) + * sin(TWO_PI * (double) q / mp); + st->a[st->numFigs][q].y = my / 2 + ry + * (0.8 - 0.2 * sin(30 * TWO_PI * q / mp)) + * cos(TWO_PI * (double) q / mp); + } + st->a[st->numFigs][mp].x = st->a[st->numFigs][0].x; + st->a[st->numFigs][mp].y = st->a[st->numFigs][0].y; + ++st->numFigs; + + + /* */ + st->a[st->numFigs] = (XPoint *) xmalloc(st->numPoints * sizeof(XPoint)); + rx = mx / 2; + ry = my / 2; + for (q = 0; q < st->numPoints; q++) { + st->a[st->numFigs][q].x = mx / 2 + ry * sin(TWO_PI * (double) q / mp); + st->a[st->numFigs][q].y = my / 2 + ry * cos(TWO_PI * (double) q / mp); + } + st->a[st->numFigs][mp].x = st->a[st->numFigs][0].x; + st->a[st->numFigs][mp].y = st->a[st->numFigs][0].y; + ++st->numFigs; + + + /* */ + st->a[st->numFigs] = (XPoint *) xmalloc(st->numPoints * sizeof(XPoint)); + rx = mx / 2; + ry = my / 2; + for (q = 0; q < st->numPoints; q++) { + st->a[st->numFigs][q].x = mx / 2 + rx * cos(TWO_PI * (double) q / mp); + st->a[st->numFigs][q].y = my / 2 + ry * sin(TWO_PI * (double) q / mp); + } + st->a[st->numFigs][mp].x = st->a[st->numFigs][0].x; + st->a[st->numFigs][mp].y = st->a[st->numFigs][0].y; + ++st->numFigs; + + /* */ + st->a[st->numFigs] = (XPoint *) xmalloc(st->numPoints * sizeof(XPoint)); + rx = mx / 2; + ry = my / 2; + for (q = 0; q < st->numPoints; q++) { + st->a[st->numFigs][q].x = mx / 2 + rx * sin(2 * TWO_PI * (double) q / mp); + st->a[st->numFigs][q].y = my / 2 + ry * cos(3 * TWO_PI * (double) q / mp); + } + st->a[st->numFigs][mp].x = st->a[st->numFigs][0].x; + st->a[st->numFigs][mp].y = st->a[st->numFigs][0].y; + ++st->numFigs; + } + + if (st->figType & FT_OPEN) { + /* sine wave, one period */ + st->a[st->numFigs] = (XPoint *) xmalloc(st->numPoints * sizeof(XPoint)); + for (q = 0; q < st->numPoints; q++) { + st->a[st->numFigs][q].x = ((double) q / st->numPoints) * mx; + st->a[st->numFigs][q].y = (1.0 - sin(((double) q / mp) * TWO_PI)) + * my / 2.0; + } + ++st->numFigs; + + /* */ + st->a[st->numFigs] = (XPoint *) xmalloc(st->numPoints * sizeof(XPoint)); + for (q = 0; q < st->numPoints; q++) { + st->a[st->numFigs][q].x = ((double) q / mp) * mx; + st->a[st->numFigs][q].y = (1.0 - cos(((double) q / mp) * 3 * TWO_PI)) + * my / 2.0; + } + ++st->numFigs; + + /* spiral, one endpoint at bottom */ + st->a[st->numFigs] = (XPoint *) xmalloc(st->numPoints * sizeof(XPoint)); + rx = mx / 2; + ry = my / 2; + for (q = 0; q < st->numPoints; q++) { + st->a[st->numFigs][q].x = mx / 2 + ry * sin(5 * TWO_PI * (double) q / mp) + * ((double) q / mp); + st->a[st->numFigs][q].y = my / 2 + ry * cos(5 * TWO_PI * (double) q / mp) + * ((double) q / mp); + } + ++st->numFigs; + + /* spiral, one endpoint at top */ + st->a[st->numFigs] = (XPoint *) xmalloc(st->numPoints * sizeof(XPoint)); + rx = mx / 2; + ry = my / 2; + for (q = 0; q < st->numPoints; q++) { + st->a[st->numFigs][q].x = mx / 2 + ry * sin(6 * TWO_PI * (double) q / mp) + * ((double) q / mp); + st->a[st->numFigs][q].y = my / 2 - ry * cos(6 * TWO_PI * (double) q / mp) + * ((double) q / mp); + } + ++st->numFigs; + + /* */ + st->a[st->numFigs] = (XPoint *) xmalloc(st->numPoints * sizeof(XPoint)); + for (q = 0; q < st->numPoints; q++) { + st->a[st->numFigs][q].x = ((double) q / mp) * mx; + st->a[st->numFigs][q].y = (1.0 - sin(((double) q / mp) * 5 * TWO_PI)) + * my / 2.0; + } + ++st->numFigs; + } + +#ifdef MARGINS + /* make some space around the figures. */ + marginx = (mx + 1) / 10; + marginy = (my + 1) / 10; + scalex = (double) ((mx + 1) - 2.0 * marginx) / (mx + 1.0); + scaley = (double) ((my + 1) - 2.0 * marginy) / (my + 1.0); + for (q = 0; q < st->numFigs; q++) + for (w = 0; w < st->numPoints; w++) { + st->a[q][w].x = marginx + st->a[q][w].x * scalex; + st->a[q][w].y = marginy + st->a[q][w].y * scaley; + } +#endif +} + +static void +initLMorph(struct state *st) +{ + int steps; + XGCValues gcv; + XWindowAttributes wa; + Colormap cmap; + char *ft; + int i; + + st->maxGamma = 1.0; + st->numPoints = get_integer_resource(st->dpy, "points", "Integer"); + steps = get_integer_resource(st->dpy, "steps", "Integer"); + st->delay = get_integer_resource(st->dpy, "delay", "Integer"); + ft = get_string_resource(st->dpy, "figtype", "String"); + + if (strcmp(ft, "all") == 0) + st->figType = FT_ALL; + else if (strcmp(ft, "open") == 0) + st->figType = FT_OPEN; + else if (strcmp(ft, "closed") == 0) + st->figType = FT_CLOSED; + else { + fprintf(stderr, "figtype should be `all', `open' or `closed'.\n"); + st->figType = FT_ALL; + } + + if (steps <= 0) + steps = (random() % 400) + 100; + + st->deltaGamma = 1.0 / steps; + XGetWindowAttributes(st->dpy, st->window, &wa); + st->scrWidth = wa.width; + st->scrHeight = wa.height; + cmap = wa.colormap; + gcv.foreground = get_pixel_resource(st->dpy, cmap, "foreground", "Foreground"); + st->gcDraw = XCreateGC(st->dpy, st->window, GCForeground, &gcv); + XSetForeground(st->dpy, st->gcDraw, gcv.foreground); + gcv.foreground = get_pixel_resource(st->dpy, cmap, "background", "Background"); + st->gcClear = XCreateGC(st->dpy, st->window, GCForeground, &gcv); + XClearWindow(st->dpy, st->window); + + initPointArrays(st); + st->aCurr = st->aWork[st->nWork = 0]; + st->aPrev = NULL; + st->currGamma = st->maxGamma + 1.0; /* force creation of new figure at startup */ + st->nTo = RND(st->numFigs); + do { + st->nNext = RND(st->numFigs); + } while (st->nNext == st->nTo); + + st->aSlopeTo = (XPoint *) xmalloc(st->numPoints * sizeof(XPoint)); + st->aSlopeFrom = (XPoint *) xmalloc(st->numPoints * sizeof(XPoint)); + st->aNext = (XPoint *) xmalloc(st->numPoints * sizeof(XPoint)); + + for (i = 0; i < st->numPoints ; i++) { + st->aSlopeTo[i].x = 0.0; + st->aSlopeTo[i].y = 0.0; + } + + { /* jwz for version 2.11 */ + /* int width = random() % 10;*/ + int width = get_integer_resource(st->dpy, "linewidth", "Integer"); + int style = LineSolid; + int cap = (width > 1 ? CapRound : CapButt); + int join = (width > 1 ? JoinRound : JoinBevel); + if (width == 1) + width = 0; + XSetLineAttributes(st->dpy, st->gcDraw, width, style, cap, join); + XSetLineAttributes(st->dpy, st->gcClear, width, style, cap, join); + } +} + +/* 55% of execution time */ +static void +createPoints(struct state *st) +{ + int q; + XPoint *pa = st->aCurr, *pa1 = st->aFrom, *pa2 = st->aTo; + XPoint *qa1 = st->aSlopeFrom, *qa2 = st->aSlopeTo; + float fg, f1g; + float speed; + + fg = st->currGamma; + f1g = 1.0 - st->currGamma; + for (q = st->numPoints; q; q--) { + speed = 0.45 * sin(TWO_PI * (double) (q + st->shift) / (st->numPoints - 1)); + fg = st->currGamma + 1.67 * speed + * exp(-200.0 * (st->currGamma - 0.5 + 0.7 * speed) + * (st->currGamma - 0.5 + 0.7 * speed)); + + f1g = 1.0 - fg; + pa->x = (short) (f1g * f1g * f1g * pa1->x + f1g * f1g * fg + * (3 * pa1->x + qa1->x) + f1g * fg * fg + * (3 * pa2->x - qa2->x) + fg * fg * fg * pa2->x); + pa->y = (short) (f1g * f1g * f1g * pa1->y + f1g * f1g * fg + * (3 * pa1->y + qa1->y) + f1g * fg * fg + * (3 * pa2->y - qa2->y) + fg * fg * fg * pa2->y); + + ++pa; + ++pa1; + ++pa2; + ++qa1; + ++qa2; + } +} + +/* 36% of execution time */ +static void +drawImage(struct state *st) +{ +#if 0 + int q; + XPoint *old0, *old1, *new0, *new1; + + /* Problem: update the window without too much flickering. I do + * this by handling each linesegment separately. First remove a + * line, then draw the new line. The problem is that this leaves + * small black pixels on the figure. To fix this, we draw the + * entire figure using XDrawLines() afterwards. */ + if (st->aPrev) { + old0 = st->aPrev; + old1 = st->aPrev + 1; + new0 = st->aCurr; + new1 = st->aCurr + 1; + for (q = st->numPoints - 1; q; q--) { + XDrawLine(st->dpy, st->window, st->gcClear, + old0->x, old0->y, old1->x, old1->y); + XDrawLine(st->dpy, st->window, st->gcDraw, + new0->x, new0->y, new1->x, new1->y); + ++old0; + ++old1; + ++new0; + ++new1; + } + } +#else + XClearWindow(st->dpy,st->window); +#endif + XDrawLines(st->dpy, st->window, st->gcDraw, st->aCurr, st->numPoints, CoordModeOrigin); +} + +/* neglectible % of execution time */ +static void +animateLMorph(struct state *st) +{ + int i; + if (st->currGamma > st->maxGamma) { + st->currGamma = 0.0; + st->nFrom = st->nTo; + st->nTo = st->nNext; + st->aFrom = st->a[st->nFrom]; + st->aTo = st->a[st->nTo]; + do { + st->nNext = RND(st->numFigs); + } while (st->nNext == st->nTo); + st->aNext = st->a[st->nNext]; + + st->shift = RND(st->numPoints); + if (RND(2)) { + /* reverse the array to get more variation. */ + int i1, i2; + XPoint p; + + for (i1 = 0, i2 = st->numPoints - 1; i1 < st->numPoints / 2; i1++, i2--) { + p = st->aNext[i1]; + st->aNext[i1] = st->aNext[i2]; + st->aNext[i2] = p; + } + } + + /* calculate the slopes */ + for (i = 0; i < st->numPoints ; i++) { + st->aSlopeFrom[i].x = st->aSlopeTo[i].x; + st->aSlopeFrom[i].y = st->aSlopeTo[i].y; + st->aSlopeTo[i].x = st->aNext[i].x - st->aTo[i].x; + st->aSlopeTo[i].y = (st->aNext[i].y - st->aTo[i].y); + } + } + + createPoints(st); + drawImage(st); + st->aPrev = st->aCurr; + st->aCurr = st->aWork[st->nWork ^= 1]; + + st->currGamma += st->deltaGamma; +} + +/*-----------------------------------------------------------------------+ +| PUBLIC FUNCTIONS | ++-----------------------------------------------------------------------*/ + +static void * +lmorph_init (Display *d, Window w) +{ + struct state *st = (struct state *) calloc (1, sizeof(*st)); + st->dpy = d; + st->window = w; + initLMorph(st); + return st; +} + +static unsigned long +lmorph_draw (Display *dpy, Window window, void *closure) +{ + struct state *st = (struct state *) closure; + animateLMorph(st); + return st->delay; +} + +static void +lmorph_reshape (Display *dpy, Window window, void *closure, + unsigned int w, unsigned int h) +{ +} + +static Bool +lmorph_event (Display *dpy, Window window, void *closure, XEvent *event) +{ + return False; +} + +static void +lmorph_free (Display *dpy, Window window, void *closure) +{ + struct state *st = (struct state *) closure; + free (st); +} + +XSCREENSAVER_MODULE ("LMorph", lmorph) diff --git a/hacks/lmorph.man b/hacks/lmorph.man new file mode 100644 index 00000000..be8e19ee --- /dev/null +++ b/hacks/lmorph.man @@ -0,0 +1,65 @@ +.TH LMORPH 1 "xscreensaver hack" +.SH NAME +lmorph \- morphing lines +.SH SYNOPSIS +.B lmorph +[\-display \fIhost:display.screen\fP] [\-foreground \fIcolor\fP] [\-background \fIcolor\fP] [\-window] [\-root] [\-mono] [\-install] [\-visual \fIvisual\fP] [\-points \fIint\fP] [\-steps \fIint\fP] [\-delay \fIusecs\fP] [\-figtype \fItype\fP] +[\-fps] +.SH DESCRIPTION +The \fIlmorph\fP program generates random spline-ish line drawings and +morphs between them. +.SH OPTIONS +.I lmorph +accepts the following options: +.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 \-mono +If on a color display, pretend we're on a monochrome display. +.TP 8 +.B \-install +Install a private colormap for the window. +.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 \-points \fIinteger\fP +Number of points in each line drawing. Default is 200 points. +.TP 8 +.B \-steps \fIinteger\fP +Interpolation steps from one drawing to the next. Default is 150. You +may specify 0, to get a random number between 100 and 500. +.TP 8 +.B \-delay \fImicroseconds\fP +How much of a delay should be introduced between steps of the animation. +Default 70000. +.TP 8 +.B \-figtype \fItype\fP +Limit the figures to only open or closed figures. Possible types are +"all" (default), "open" and "closed". +.TP 8 +.B \-linewidth \fIinteger\fP +Width of lines. Default is 5 pixels. +.TP 8 +.B \-fps +Display the current frame rate and CPU load. +.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 AUTHOR +Sverre H. Huseby and Glenn T. Lines , +built on top of the screen saver routines by Jamie Zawinski . diff --git a/hacks/loop.c b/hacks/loop.c new file mode 100644 index 00000000..7a998738 --- /dev/null +++ b/hacks/loop.c @@ -0,0 +1,1703 @@ +/* -*- Mode: C; tab-width: 4 -*- */ +/* loop --- Chris Langton's self-producing loops */ + +#if 0 +static const char sccsid[] = "@(#)loop.c 5.01 2000/03/15 xlockmore"; +#endif + +/*- + * Copyright (c) 1996 by David Bagley. + * + * Permission to use, copy, modify, and distribute this software and its + * documentation for any purpose and without fee is hereby granted, + * provided that the above copyright notice appear in all copies and that + * both that copyright notice and this permission notice appear in + * supporting documentation. + * + * This file is provided AS IS with no warranties of any kind. The author + * shall have no liability with respect to the infringement of copyrights, + * trade secrets or any patents by this file or any part thereof. In no + * event will the author be liable for any lost revenue or profits or + * other special, indirect and consequential damages. + * + * Revision History: + * 15-Mar-2001: Added some flaws, random blue wall spots, to liven it up. + * This mod seems to expose a bug where hexagons are erased + * for no apparent reason. + * 01-Nov-2000: Allocation checks + * 16-Jun-2000: Fully coded the hexagonal rules. (Rules that end up in + * state zero were not bothered with since a calloc was used + * to set non-explicit rules to zero. This allows the + * compile-time option RAND_RULES to work here (at least to + * generation 540).) + * Also added compile-time option DELAYDEBUGLOOP for debugging + * life form. This also turns off the random initial direction + * of the loop. Set DELAYDEBUGLOOP to be 10 and use with + * something like this: + * xlock -mode loop -neighbors 6 -size 5 -delay 1 -count 540 -nolock + * 18-Oct-1998: Started creating a hexagon version. + * It proved not that difficult because I used Langton's Loop + * as a guide, hexagons have more neighbors so there is more + * freedom to program, and the loop will has six sides to + * store its genes (data). + * (Soon after this a triangular version with neighbors = 6 + * was attempted but was unsuccessful). + * 10-May-1997: Compatible with xscreensaver + * 15-Nov-1995: Coded from Chris Langton's Self-Reproduction in Cellular + * Automata Physica 10D 135-144 1984, also used wire.c as a + * guide. + */ + +/*- + Grid Number of Neighbors + ---- ------------------ + Square 4 + Hexagon 6 (currently in development) +*/ + +/*- + * From Steven Levy's Artificial Life + * Chris Langton's cellular automata "loops" reproduce in the spirit of life. + * Beginning from a single organism, the loops from a colony. As the loops + * on the outer fringes reproduce, the inner loops -- blocked by their + * daughters -- can no longer produce offspring. These dead progenitors + * provide a base for future generations' expansion, much like the formation + * of a coral reef. This self-organizing behavior emerges spontaneously, + * from the bottom up -- a key characteristic of artificial life. + */ + +/*- + Don't Panic -- When the artificial life tries to leave its petri + dish (ie. the screen) it will (usually) die... + The loops are short of "real" life because a general purpose Turing + machine is not contained in the loop. This is a simplification of + von Neumann and Codd's self-producing Turing machine. + The data spinning around could be viewed as both its DNA and its internal + clock. The program can be initalized to have the loop spin both ways... + but only one way around will work for a given rule. An open question (at + least to me): Is handedness a requirement for (artificial) life? Here + there is handedness at both the initial condition and the transition rule. + */ + +#ifndef HAVE_COCOA +# define DO_STIPPLE +#endif + +#ifdef STANDALONE +# define MODE_loop +# define DEFAULTS "*delay: 100000 \n" \ + "*count: -5 \n" \ + "*cycles: 1600 \n" \ + "*size: -12 \n" \ + "*ncolors: 15 \n" \ + "*fpsSolid: true \n" \ + +# define UNIFORM_COLORS +# define loop_handle_event 0 +# include "xlockmore.h" /* in xscreensaver distribution */ +#else /* STANDALONE */ +# include "xlock.h" /* in xlockmore distribution */ +#endif /* STANDALONE */ +#include "automata.h" + +#ifdef MODE_loop + +/*- + * neighbors of 0 randomizes between 4 and 6. + */ +#define DEF_NEIGHBORS "0" /* choose random value */ + +static int neighbors; + +static XrmOptionDescRec opts[] = +{ + {"-neighbors", ".loop.neighbors", XrmoptionSepArg, 0} +}; + +static argtype vars[] = +{ + {&neighbors, "neighbors", "Neighbors", DEF_NEIGHBORS, t_Int} +}; + +static OptionStruct desc[] = +{ + {"-neighbors num", "squares 4 or hexagons 6"} +}; + +ENTRYPOINT ModeSpecOpt loop_opts = +{sizeof opts / sizeof opts[0], opts, sizeof vars / sizeof vars[0], vars, desc}; + + +#ifdef USE_MODULES +ModStruct loop_description = +{"loop", "init_loop", "draw_loop", "release_loop", + "refresh_loop", "init_loop", (char *) NULL, &loop_opts, + 100000, 5, 1600, -12, 64, 1.0, "", + "Shows Langton's self-producing loops", 0, NULL}; + +#endif + +#define LOOPBITS(n,w,h)\ + if ((lp->pixmaps[lp->init_bits]=\ + XCreatePixmapFromBitmapData(display,window,(char *)n,w,h,1,0,1))==None){\ + free_loop(display,lp); return;} else {lp->init_bits++;} + +static int local_neighbors = 0; + +#if 0 +/* Used to fast forward to troubled generations, mainly used for debugging. + -delay 1 -count 170 -neighbors 6 # divisions starts + 540 first cell collision + 1111 mutant being born from 2 parents + 1156 mutant born + */ +#define DELAYDEBUGLOOP 10 +#endif + +#define COLORS 8 +#define REALCOLORS (COLORS-2) +#define MINLOOPS 1 +#define REDRAWSTEP 2000 /* How many cells to draw per cycle */ +#define ADAM_SIZE 8 /* MIN 5 */ +#if 1 +#define ADAM_LOOPX (ADAM_SIZE+2) +#define ADAM_LOOPY (ADAM_SIZE+2) +#else +#define ADAM_LOOPX 16 +#define ADAM_LOOPY 10 +#endif +#define MINGRIDSIZE (3*ADAM_LOOPX) +#if 0 +/* TRIA stuff was an attempt to make a triangular lifeform on a + hexagonal grid but I got bored. You may need an additional 7th + state for a coherent step by step process of cell separation and + initial stem development. + */ +#define TRIA 1 +#endif +#ifdef TRIA +#define HEX_ADAM_SIZE 3 /* MIN 3 */ +#else +#define HEX_ADAM_SIZE 5 /* MIN 3 */ +#endif +#if 1 +#define HEX_ADAM_LOOPX (2*HEX_ADAM_SIZE+1) +#define HEX_ADAM_LOOPY (2*HEX_ADAM_SIZE+1) +#else +#define HEX_ADAM_LOOPX 3 +#define HEX_ADAM_LOOPY 7 +#endif +#define HEX_MINGRIDSIZE (6*HEX_ADAM_LOOPX) +#define MINSIZE ((MI_NPIXELS(mi)>=COLORS)?1:(2+(local_neighbors==6))) +#define NEIGHBORKINDS 2 +#define ANGLES 360 +#define MAXNEIGHBORS 6 + +/* Singly linked list */ +typedef struct _CellList { + XPoint pt; + struct _CellList *next; +} CellList; + +typedef struct { + int init_bits; + int generation; + int xs, ys; + int xb, yb; + int nrows, ncols; + int bx, by, bnrows, bncols; + int mincol, minrow, maxcol, maxrow; + int width, height; + int redrawing, redrawpos; + Bool dead, clockwise; + unsigned char *newcells, *oldcells; + int ncells[COLORS]; + CellList *cellList[COLORS]; + unsigned long colors[COLORS]; + GC stippledGC; + Pixmap pixmaps[COLORS]; + union { + XPoint hexagon[6]; + } shape; +} loopstruct; + +static loopstruct *loops = (loopstruct *) NULL; + +#define TRANSITION(TT,V) V=TT&7;TT>>=3 +#define FINALTRANSITION(TT,V) V=TT&7 +#define TABLE(R,T,L,B) (table[((B)<<9)|((L)<<6)|((T)<<3)|(R)]) +#define HEX_TABLE(R,T,t,l,b,B) (table[((B)<<15)|((b)<<12)|((l)<<9)|((t)<<6)|((T)<<3)|(R)]) + +#if 0 +/* Instead of setting "unused" state rules to zero it randomizes them. + These rules take over when something unexpected happens... like when a + cell hits a wall (the end of the screen). + */ +#define RAND_RULES +#endif + +#ifdef RAND_RULES +#define TABLE_IN(C,R,T,L,B,I) (TABLE(R,T,L,B)&=~(7<<((C)*3)));\ +(TABLE(R,T,L,B)|=((I)<<((C)*3))) +#define HEX_TABLE_IN(C,R,T,t,l,b,B,I) (HEX_TABLE(R,T,t,l,b,B)&=~(7<<((C)*3)));\ +(HEX_TABLE(R,T,t,l,b,B)|=((I)<<((C)*3))) +#else +#define TABLE_IN(C,R,T,L,B,I) (TABLE(R,T,L,B)|=((I)<<((C)*3))) +#define HEX_TABLE_IN(C,R,T,t,l,b,B,I) (HEX_TABLE(R,T,t,l,b,B)|=((I)<<((C)*3))) +#endif +#define TABLE_OUT(C,R,T,L,B) ((TABLE(R,T,L,B)>>((C)*3))&7) +#define HEX_TABLE_OUT(C,R,T,t,l,b,B) ((HEX_TABLE(R,T,t,l,b,B)>>((C)*3))&7) + +static unsigned int *table = (unsigned int *) NULL; + /* square: 8*8*8*8 = 2^12 = 2^3^4 = 4096 */ + /* hexagon: 8*8*8*8*8*8 = 2^18 = 2^3^6 = 262144 = too big? */ + +static char plots[NEIGHBORKINDS] = +{ + 4, 6 /* Neighborhoods */ +}; + +static unsigned int transition_table[] = +{ /* Octal CBLTR->I */ + /* CBLTRI CBLTRI CBLTRI CBLTRI CBLTRI */ + 0000000, 0025271, 0113221, 0202422, 0301021, + 0000012, 0100011, 0122244, 0202452, 0301220, + 0000020, 0100061, 0122277, 0202520, 0302511, + 0000030, 0100077, 0122434, 0202552, 0401120, + 0000050, 0100111, 0122547, 0202622, 0401220, + 0000063, 0100121, 0123244, 0202722, 0401250, + 0000071, 0100211, 0123277, 0203122, 0402120, + 0000112, 0100244, 0124255, 0203216, 0402221, + 0000122, 0100277, 0124267, 0203226, 0402326, + 0000132, 0100511, 0125275, 0203422, 0402520, + 0000212, 0101011, 0200012, 0204222, 0403221, + 0000220, 0101111, 0200022, 0205122, 0500022, + 0000230, 0101244, 0200042, 0205212, 0500215, + 0000262, 0101277, 0200071, 0205222, 0500225, + 0000272, 0102026, 0200122, 0205521, 0500232, + 0000320, 0102121, 0200152, 0205725, 0500272, + 0000525, 0102211, 0200212, 0206222, 0500520, + 0000622, 0102244, 0200222, 0206722, 0502022, + 0000722, 0102263, 0200232, 0207122, 0502122, + 0001022, 0102277, 0200242, 0207222, 0502152, + 0001120, 0102327, 0200250, 0207422, 0502220, + 0002020, 0102424, 0200262, 0207722, 0502244, + 0002030, 0102626, 0200272, 0211222, 0502722, + 0002050, 0102644, 0200326, 0211261, 0512122, + 0002125, 0102677, 0200423, 0212222, 0512220, + 0002220, 0102710, 0200517, 0212242, 0512422, + 0002322, 0102727, 0200522, 0212262, 0512722, + 0005222, 0105427, 0200575, 0212272, 0600011, + 0012321, 0111121, 0200722, 0214222, 0600021, + 0012421, 0111221, 0201022, 0215222, 0602120, + 0012525, 0111244, 0201122, 0216222, 0612125, + 0012621, 0111251, 0201222, 0217222, 0612131, + 0012721, 0111261, 0201422, 0222272, 0612225, + 0012751, 0111277, 0201722, 0222442, 0700077, + 0014221, 0111522, 0202022, 0222462, 0701120, + 0014321, 0112121, 0202032, 0222762, 0701220, + 0014421, 0112221, 0202052, 0222772, 0701250, + 0014721, 0112244, 0202073, 0300013, 0702120, + 0016251, 0112251, 0202122, 0300022, 0702221, + 0017221, 0112277, 0202152, 0300041, 0702251, + 0017255, 0112321, 0202212, 0300076, 0702321, + 0017521, 0112424, 0202222, 0300123, 0702525, + 0017621, 0112621, 0202272, 0300421, 0702720, + 0017721, 0112727, 0202321, 0300622 +}; + +static unsigned int hex_transition_table[] = +{ /* Octal CBbltTR->I */ + /* CBbltTRI CBbltTRI CBbltTRI CBbltTRI CBbltTRI */ + +#ifdef TRIA + 000000000, 000000020, 000000220, 000002220, 000022220, + 011122121, 011121221, 011122221, 011221221, + 011222221, 011112121, 011112221, + 020021122, 020002122, 020211222, 021111222, + 020221122, 020027122, 020020722, 020021022, + 001127221, + 011122727, 011227227, 010122121, 010222211, + 021117222, 020112272, + 070221220, + 001227221, + 010221121, 011721221, 011222277, + 020111222, 020221172, + 070211220, + 001217221, + 010212277, 010221221, + 020122112, + 070122220, + 001722221, + 010221271, + 020002022, 021122172, + 070121220, + 011122277, 011172121, + 010212177, 011212277, + 070112220, + 001772221, + 021221772, + 070121270, 070721220, + 000112721, 000272211, + 010022211, 012222277, + 020072272, 020227122, 020217222, + 010211121, + 020002727, + 070222220, + 001727721, + 020021072, 020070722, + 070002072, 070007022, + 001772721, + 070002022, + 000000070, 000000770, 000072220, 000000270, + 020110222, 020220272, 020220722, + 070007071, 070002072, 070007022, + 000000012, 000000122, 000000212, 001277721, + 020122072, 020202212, + 010002121, + 020001122, 020002112, + 020021722, + 020122022, 020027022, 020070122, 020020122, + 010227027, + 020101222, + 010227227, 010227277, + 021722172, + 001727221, + 010222277, + 020702272, + 070122020, + 000172721, + 010022277, 010202177, 010227127, + + 001214221, + 010202244, + 020024122, 020020422, + 040122220, + 001422221, + 010221241, 010224224, + 021122142, + 040121220, + 001124221, + 010224274, + 020112242, 021422172, + 040221220, + 001224221, 001427221, + 010222244, + 020227042, + 040122020, + 000142721, + 010022244, 010202144, 010224124, + 040112220, + 001442221, + 021221442, + 040121240, 040421220, + 000242211, 000112421, + 020042242, 020214222, 020021422, 020220242, 020024022, + 011224224, + 020224122, + 020220422, + 012222244, + 020002424, + 040222220, + 001244421, 000000420, 000000440, 000000240, 000000040, + 020040121, 020021042, + 040004022, 040004042, 040002042, + 010021121, + 020011122, 020002112, + 001424421, + 020040422, + 001442421, + 040002022, + 001724221, + 010227247, + 020224072, 021417222, + 000172421, + 010021721, + 020017022, + 020120212, + 020271727, + 070207072, 070701220, + 000001222, + 020110122, + 001277221, + 001777721, + 020021222, 020202272, 020120222, 020221722, + 020027227, + 070070222, + 000007220, + 020101272, 020272172, 020721422, 020721722, + 020011222, 020202242, +#if 0 + {2,2,0,0,2,7,0}, + {2,0,2,0,2,0,2}, + {2,4,1,2,2,1,2}, + {2,1,2,1,2,1,2}, + {2,0,2,2,1,1,2}, + {2,7,1,1,1,1,2}, + {0,2,2,2,2,2,2}, + {2,2,0,0,7,7,0}, + {2,1,2,0,2,0,7}, + {2,0,1,2,2,1,2}, + {2,4,2,1,2,1,2}, + {2,1,2,2,1,1,2}, + {2,0,7,1,1,1,2}, + {0,2,2,2,2,2,2}, +#endif +#else + 000000000, 000000020, 000000220, 000002220, + 011212121, 011212221, 011221221, 011222221, + 020002122, 020021122, 020211122, + + 010221221, 010222121, + 020002022, 020021022, 020020122, 020112022, + + 010202121, + 020102022, 020202112, + + 000000012, 000000122, 000000212, + 010002121, + 020001122, 020002112, 020011122, + + + 001227221, 001272221, 001272721, + 012212277, 011222727, 011212727, + 020021722, 020027122, 020020722, 020027022, + 020211722, 020202172, 020120272, + 020271122, 020202172, 020207122, 020217122, + 020120272, 020210722, 020270722, + 070212220, 070221220, 070212120, + + + 012222277, + 020002727, + 070222220, + + 001277721, 000000070, 000000270, 000000720, 000000770, + 020070122, 020021072, + 070002072, 070007022, 070007071, + + 020070722, + 070002022, + + 010227227, 010222727, 010202727, + 020172022, 020202712, + + 001224221, 001242221, 001242421, + 012212244, 011222424, 011212424, + 020021422, 020024122, 020020422, 020024022, + 020211422, 020202142, 020120242, + 020241122, 020202142, 020204122, 020214122, + 020120242, 020210422, 020240422, + 040212220, 040221220, 040212120, + + + 012222244, + 020002424, + 040222220, + + 001244421, 000000040, 000000240, 000000420, 000000440, + 020040122, 020021042, + 040002042, + 040004021, 040004042, + + 020040422, + 040002022, + + 010224224, 010222424, 010202424, + 020142022, 020202412, + 020011722, 020112072, 020172072, 020142072, + + + + 000210225, 000022015, 000022522, + 011225521, + 020120525, 020020152, 020005122, 020214255, 020021152, + 020255242, + 050215222, 050225121, + + 000225220, 001254222, + 010221250, 011221251, 011225221, + 020025122, 020152152, 020211252, 020214522, 020511125, + 050212241, 05221120, + 040521225, + + 000000250, 000000520, 000150220, 000220520, 000222210, + 001224251, + 010022152, 010251221, 010522121, 011212151, 011221251, + 011215221, + 020000220, 020002152, 020020220, 020022152, + 020021422, 020022152, 020022522, 020025425, 020050422, + 020051022, 020051122, 020211122, 020211222, 020215222, + 020245122, + 050021125, 050021025, 050011125, 051242221, + 041225220, + + 000220250, 000220520, 001227521, 001275221, + 011257227, 011522727, + 020002052, 020002752, 020021052, 020057125, + 050020722, 050027125, + 070215220, + + 070212255, + 071225220, + 020275122, + 051272521, + 020055725, + 020021552, + 012252277, + 050002521, + 020005725, + + 050011022, + 000000155, + 020050722, + 001227250, + 010512727, + 010002151, + 020027112, + 001227251, + 012227257, + 050002125, + 020517122, + 050002025, + 020050102, + 050002725, + 020570722, + 001252721, + 020007051, + 020102052, + 020271072, + 050001122, + 010002151, + 011227257, + 020051722, + 020057022, + 020050122, + + + 020051422, + 011224254, + 012224254, + + 020054022, + 050002425, + 040252220, + 020002454, + + + 000000540, + 001254425, + 050004024, + 040004051, + + 000000142, + 040001522, + 010002547, + 020045122, + 051221240, + 020002512, + 020021522, + + + 020020022, + 021125522, + 020521122, + 020025022, + 020025522, + 020020522, + + 020202222, + 020212222, + 021212222, + 021222722, + 021222422, + 020002222, + 020021222, + 020022122, + 020212122, + 020027222, + 020024222, + 020212722, + 020212422, + 020202122, + 001222221, + 020002522, + + 020017125, + 010022722, + 020212052, + + 020205052, + 070221250, + + 000000050, 000005220, 000002270, 070252220, + 000000450, 000007220, + 000220220, 000202220, 000022020, 000020220, + + 000222040, + 000220440, + 000022040, + 000040220, + + 000252220, + 050221120, 010221520, + 002222220, + + 000070220, 000220720, + 000020520, 000070250, 000222070, 000027020, + 000022070, 000202270, 000024020, 000220420, + 000220270, 000220240, 000072020, 000042020, + 000002020, 000002070, 000020270, 000020250, + 000270270, 000007020, 000040270, + + /* Collision starts (gen 540), not sure to have rules to save it + or depend on calloc to intialize remaining rules to 0 so that + the mutant will be born + */ + 000050220, +#endif +}; + + +/*- +Neighborhoods are read as follows (rotations are not listed): + T + L C R ==> I + B + + t T + l C R ==> I + b B + */ + +static unsigned char self_reproducing_loop[ADAM_LOOPY][ADAM_LOOPX] = +{ +/* 10x10 */ + {0, 2, 2, 2, 2, 2, 2, 2, 2, 0}, + {2, 4, 0, 1, 4, 0, 1, 1, 1, 2}, + {2, 1, 2, 2, 2, 2, 2, 2, 1, 2}, + {2, 0, 2, 0, 0, 0, 0, 2, 1, 2}, + {2, 7, 2, 0, 0, 0, 0, 2, 7, 2}, + {2, 1, 2, 0, 0, 0, 0, 2, 0, 2}, + {2, 0, 2, 0, 0, 0, 0, 2, 1, 2}, + {2, 7, 2, 2, 2, 2, 2, 2, 7, 2}, + {2, 1, 0, 6, 1, 0, 7, 1, 0, 2}, + {0, 2, 2, 2, 2, 2, 2, 2, 2, 0} +}; + +static unsigned char hex_self_reproducing_loop[HEX_ADAM_LOOPY][HEX_ADAM_LOOPX] = +{ +#if 0 +/* Experimental TRIA5:7x7 */ + {2,2,0,0,0,0,0}, + {2,1,2,0,2,2,0}, + {2,0,4,2,2,0,2}, + {2,7,2,0,2,0,2}, + {2,1,2,2,1,1,2}, + {2,0,7,1,0,7,2}, + {0,2,2,2,2,2,2}, + /* Stem cells, only "5" will fully reproduce itself */ +/* 3:12x7 */ + {2,2,2,2,0,0,0,0,0,0,0,0}, + {2,1,1,1,2,0,0,0,0,0,0,0}, + {2,1,2,2,1,2,2,2,2,2,2,0}, + {2,1,2,0,2,7,1,1,1,1,1,2}, + {0,2,1,2,2,0,2,2,2,2,2,2}, + {0,0,2,0,4,1,2,0,0,0,0,0}, + {0,0,0,2,2,2,2,0,0,0,0,0} +/* 4:14x9 */ + {2,2,2,2,2,0,0,0,0,0,0,0,0,0}, + {2,1,1,1,1,2,0,0,0,0,0,0,0,0}, + {2,1,2,2,2,1,2,0,0,0,0,0,0,0}, + {2,1,2,0,0,2,1,2,2,2,2,2,2,0}, + {2,1,2,0,0,0,2,7,1,1,1,1,1,2}, + {0,2,1,2,0,0,2,0,2,2,2,2,2,2}, + {0,0,2,0,2,2,2,1,2,0,0,0,0,0}, + {0,0,0,2,4,1,0,7,2,0,0,0,0,0}, + {0,0,0,0,2,2,2,2,2,0,0,0,0,0} +/* 5:16x11 */ + {2,2,2,2,2,2,0,0,0,0,0,0,0,0,0,0}, + {2,1,1,1,1,1,2,0,0,0,0,0,0,0,0,0}, + {2,1,2,2,2,2,1,2,0,0,0,0,0,0,0,0}, + {2,1,2,0,0,0,2,1,2,0,0,0,0,0,0,0}, + {2,1,2,0,0,0,0,2,1,2,2,2,2,2,2,0}, + {2,1,2,0,0,0,0,0,2,7,1,1,1,1,1,2}, + {0,2,1,2,0,0,0,0,2,0,2,2,2,2,2,2}, + {0,0,2,0,2,0,0,0,2,1,2,0,0,0,0,0}, + {0,0,0,2,4,2,2,2,2,7,2,0,0,0,0,0}, + {0,0,0,0,2,1,0,7,1,0,2,0,0,0,0,0}, + {0,0,0,0,0,2,2,2,2,2,2,0,0,0,0,0} +/* test:3x7 (0,4) is blank ... very strange. + init_adam seems ok something after that I guess */ + {2,2,0}, + {2,0,2}, + {0,2,2}, + {0,0,0}, + {2,2,0}, + {2,1,2}, + {0,2,2}, +#else /* this might be better for hexagons, spacewise efficient... */ +#ifdef TRIA +/* Experimental TRIA5:7x7 */ + {2,2,0,0,2,2,0}, + {2,4,2,0,2,7,2}, + {2,1,0,2,2,0,2}, + {2,0,2,1,2,1,2}, + {2,7,2,2,7,7,2}, + {2,1,0,7,1,0,2}, + {0,2,2,2,2,2,2}, +#else +/* 5:11x11 */ + {2,2,2,2,2,2,0,0,0,0,0}, + {2,1,1,7,0,1,2,0,0,0,0}, + {2,1,2,2,2,2,7,2,0,0,0}, + {2,1,2,0,0,0,2,0,2,0,0}, + {2,1,2,0,0,0,0,2,1,2,0}, + {2,1,2,0,0,0,0,0,2,7,2}, + {0,2,1,2,0,0,0,0,2,0,2}, + {0,0,2,1,2,0,0,0,2,1,2}, + {0,0,0,2,1,2,2,2,2,4,2}, + {0,0,0,0,2,1,1,1,1,5,2}, + {0,0,0,0,0,2,2,2,2,2,2} +#endif +#endif +}; + +static void +position_of_neighbor(int dir, int *pcol, int *prow) +{ + int col = *pcol, row = *prow; + + /* NO WRAPING */ + + if (local_neighbors == 6) { + switch (dir) { + case 0: + col++; + break; + case 60: + col += (row & 1); + row--; + break; + case 120: + col -= !(row & 1); + row--; + break; + case 180: + col--; + break; + case 240: + col -= !(row & 1); + row++; + break; + case 300: + col += (row & 1); + row++; + break; + default: + (void) fprintf(stderr, "wrong direction %d\n", dir); + } + } else { + switch (dir) { + case 0: + col++; + break; + case 90: + row--; + break; + case 180: + col--; + break; + case 270: + row++; + break; + default: + (void) fprintf(stderr, "wrong direction %d\n", dir); + } + } + *pcol = col; + *prow = row; +} + +static Bool +withinBounds(loopstruct * lp, int col, int row) +{ + return (row >= 1 && row < lp->bnrows - 1 && + col >= 1 && col < lp->bncols - 1 - (local_neighbors == 6 && (row % 2))); +} + +static void +fillcell(ModeInfo * mi, GC gc, int col, int row) +{ + loopstruct *lp = &loops[MI_SCREEN(mi)]; + + if (local_neighbors == 6) { + int ccol = 2 * col + !(row & 1), crow = 2 * row; + + lp->shape.hexagon[0].x = lp->xb + ccol * lp->xs; + lp->shape.hexagon[0].y = lp->yb + crow * lp->ys; + if (lp->xs == 1 && lp->ys == 1) + XDrawPoint(MI_DISPLAY(mi), MI_WINDOW(mi), gc, + lp->shape.hexagon[0].x, lp->shape.hexagon[0].y); + else + XFillPolygon(MI_DISPLAY(mi), MI_WINDOW(mi), gc, + lp->shape.hexagon, 6, Convex, CoordModePrevious); + } else { + XFillRectangle(MI_DISPLAY(mi), MI_WINDOW(mi), gc, + lp->xb + lp->xs * col, lp->yb + lp->ys * row, + lp->xs - (lp->xs > 3), lp->ys - (lp->ys > 3)); + } +} + +static void +drawcell(ModeInfo * mi, int col, int row, int state) +{ + loopstruct *lp = &loops[MI_SCREEN(mi)]; + XGCValues gcv; + GC gc; + + if (MI_NPIXELS(mi) >= COLORS) { + gc = MI_GC(mi); + XSetForeground(MI_DISPLAY(mi), gc, lp->colors[state]); + } else { +#ifdef DO_STIPPLE + gcv.stipple = lp->pixmaps[state]; +#endif /* DO_STIPPLE */ + gcv.foreground = MI_WHITE_PIXEL(mi); + gcv.background = MI_BLACK_PIXEL(mi); + XChangeGC(MI_DISPLAY(mi), lp->stippledGC, +#ifdef DO_STIPPLE + GCStipple | +#endif /* DO_STIPPLE */ + GCForeground | GCBackground, &gcv); + gc = lp->stippledGC; + } + fillcell(mi, gc, col, row); +} + +#ifdef DEBUG +static void +print_state(ModeInfo * mi, int state) +{ + loopstruct *lp = &loops[MI_SCREEN(mi)]; + CellList *locallist = lp->cellList[state]; + int i = 0; + + (void) printf("state %d\n", state); + while (locallist) { + (void) printf("%d x %d, y %d\n", i, + locallist->pt.x, locallist->pt.y); + locallist = locallist->next; + i++; + } +} + +#endif + +static void +free_state(loopstruct * lp, int state) +{ + CellList *current; + + while (lp->cellList[state]) { + current = lp->cellList[state]; + lp->cellList[state] = lp->cellList[state]->next; + (void) free((void *) current); + } + lp->ncells[state] = 0; +} + +static void +free_list(loopstruct * lp) +{ + int state; + + for (state = 0; state < COLORS; state++) + free_state(lp, state); +} + +static void +free_loop(Display *display, loopstruct * lp) +{ + int shade; + + for (shade = 0; shade < lp->init_bits; shade++) + if (lp->pixmaps[shade] != None) { + XFreePixmap(display, lp->pixmaps[shade]); + lp->pixmaps[shade] = None; + } + if (lp->stippledGC != None) { + XFreeGC(display, lp->stippledGC); + lp->stippledGC = None; + } + if (lp->oldcells != NULL) { + (void) free((void *) lp->oldcells); + lp->oldcells = (unsigned char *) NULL; + } + if (lp->newcells != NULL) { + (void) free((void *) lp->newcells); + lp->newcells = (unsigned char *) NULL; + } + free_list(lp); +} + +static Bool +addtolist(ModeInfo * mi, int col, int row, unsigned char state) +{ + loopstruct *lp = &loops[MI_SCREEN(mi)]; + CellList *current = lp->cellList[state]; + + if ((lp->cellList[state] = (CellList *) malloc(sizeof (CellList))) == + NULL) { + lp->cellList[state] = current; + free_loop(MI_DISPLAY(mi), lp); + return False; + } + lp->cellList[state]->pt.x = col; + lp->cellList[state]->pt.y = row; + lp->cellList[state]->next = current; + lp->ncells[state]++; + return True; +} + +static Bool +draw_state(ModeInfo * mi, int state) +{ + loopstruct *lp = &loops[MI_SCREEN(mi)]; + Display *display = MI_DISPLAY(mi); + GC gc; + XGCValues gcv; + CellList *current = lp->cellList[state]; + + if (MI_NPIXELS(mi) >= COLORS) { + gc = MI_GC(mi); + XSetForeground(display, gc, lp->colors[state]); + } else { +#ifdef DO_STIPPLE + gcv.stipple = lp->pixmaps[state]; +#endif /* DO_STIPPLE */ + gcv.foreground = MI_WHITE_PIXEL(mi); + gcv.background = MI_BLACK_PIXEL(mi); + XChangeGC(display, lp->stippledGC, +#ifdef DO_STIPPLE + GCStipple | +#endif /* DO_STIPPLE */ + GCForeground | GCBackground, &gcv); + gc = lp->stippledGC; + } + + if (local_neighbors == 6) { /* Draw right away, slow */ + while (current) { + int col, row, ccol, crow; + + col = current->pt.x; + row = current->pt.y; + ccol = 2 * col + !(row & 1), crow = 2 * row; + lp->shape.hexagon[0].x = lp->xb + ccol * lp->xs; + lp->shape.hexagon[0].y = lp->yb + crow * lp->ys; + if (lp->xs == 1 && lp->ys == 1) + XDrawPoint(display, MI_WINDOW(mi), gc, + lp->shape.hexagon[0].x, lp->shape.hexagon[0].y); + else + XFillPolygon(display, MI_WINDOW(mi), gc, + lp->shape.hexagon, 6, Convex, CoordModePrevious); + current = current->next; + } + } else { + /* Take advantage of XFillRectangles */ + XRectangle *rects; + int nrects = 0; + + /* Create Rectangle list from part of the cellList */ + if ((rects = (XRectangle *) malloc(lp->ncells[state] * + sizeof (XRectangle))) == NULL) { + return False; + } + + while (current) { + rects[nrects].x = lp->xb + current->pt.x * lp->xs; + rects[nrects].y = lp->yb + current->pt.y * lp->ys; + rects[nrects].width = lp->xs - (lp->xs > 3); + rects[nrects].height = lp->ys - (lp->ys > 3); + current = current->next; + nrects++; + } + /* Finally get to draw */ + XFillRectangles(display, MI_WINDOW(mi), gc, rects, nrects); + /* Free up rects list and the appropriate part of the cellList */ + (void) free((void *) rects); + } + free_state(lp, state); + return True; +} + +static Bool +init_table(void) +{ + if (table == NULL) { + int mult = 1; + unsigned int tt, c, n[MAXNEIGHBORS], i; + int j, k; + int size_transition_table = sizeof (transition_table) / + sizeof (unsigned int); + int size_hex_transition_table = sizeof (hex_transition_table) / + sizeof (unsigned int); + + for (j = 0; j < local_neighbors; j++) + mult *= 8; + + if ((table = (unsigned int *) calloc(mult, sizeof (unsigned int))) == NULL) { + return False; + } + + +#ifdef RAND_RULES + /* Here I was interested to see what happens when it hits a wall.... + Rules not normally used take over... takes too much time though */ + /* Each state = 3 bits */ + if (MAXRAND < 16777216.0) { + for (j = 0; j < mult; j++) { + table[j] = (unsigned int) ((NRAND(4096) << 12) & NRAND(4096)); + } + } else { + for (j = 0; j < mult; j++) { + table[j] = (unsigned int) (NRAND(16777216)); + } + } +#endif + if (local_neighbors == 6) { + for (j = 0; j < size_hex_transition_table; j++) { + tt = hex_transition_table[j]; + TRANSITION(tt, i); + for (k = 0; k < local_neighbors; k++) { + TRANSITION(tt, n[k]); + } + FINALTRANSITION(tt, c); + HEX_TABLE_IN(c, n[0], n[1], n[2], n[3], n[4], n[5], i); + HEX_TABLE_IN(c, n[1], n[2], n[3], n[4], n[5], n[0], i); + HEX_TABLE_IN(c, n[2], n[3], n[4], n[5], n[0], n[1], i); + HEX_TABLE_IN(c, n[3], n[4], n[5], n[0], n[1], n[2], i); + HEX_TABLE_IN(c, n[4], n[5], n[0], n[1], n[2], n[3], i); + HEX_TABLE_IN(c, n[5], n[0], n[1], n[2], n[3], n[4], i); + } + } else { + for (j = 0; j < size_transition_table; j++) { + tt = transition_table[j]; + TRANSITION(tt, i); + for (k = 0; k < local_neighbors; k++) { + TRANSITION(tt, n[k]); + } + FINALTRANSITION(tt, c); + TABLE_IN(c, n[0], n[1], n[2], n[3], i); + TABLE_IN(c, n[1], n[2], n[3], n[0], i); + TABLE_IN(c, n[2], n[3], n[0], n[1], i); + TABLE_IN(c, n[3], n[0], n[1], n[2], i); + } + } + } + return True; +} + +static void +init_flaw(ModeInfo * mi) +{ + loopstruct *lp = &loops[MI_SCREEN(mi)]; + int a, b; + +#define BLUE 2 + if (lp->bncols <= 3 || lp->bnrows <= 3) + return; + a = MIN(lp->bncols - 3, 2 * ((local_neighbors == 6) ? + HEX_MINGRIDSIZE : MINGRIDSIZE)); + a = NRAND(a) + (lp->bncols - a) / 2; + b = MIN(lp->bnrows - 3, 2 * ((local_neighbors == 6) ? + HEX_MINGRIDSIZE : MINGRIDSIZE)); + b = NRAND(b) + (lp->bnrows - b) / 2; + if (lp->mincol > a) + lp->mincol = a; + if (lp->minrow > b) + lp->minrow = b; + if (lp->maxcol < a + 2) + lp->maxcol = a + 2; + if (lp->maxrow < b + 2) + lp->maxrow = b + 2; + + if (local_neighbors == 6) { + lp->newcells[b * lp->bncols + a + !(b % 2) ] = BLUE; + lp->newcells[b * lp->bncols + a + 1 + !(b % 2)] = BLUE; + lp->newcells[(b + 1) * lp->bncols + a] = BLUE; + lp->newcells[(b + 1) * lp->bncols + a + 2] = BLUE; + lp->newcells[(b + 2) * lp->bncols + a + !(b % 2)] = BLUE; + lp->newcells[(b + 2) * lp->bncols + a + 1 + !(b % 2)] = BLUE; + } else { + int orient = NRAND(4); + lp->newcells[lp->bncols * (b + 1) + a + 1] = BLUE; + if (orient == 0 || orient == 1) { + lp->newcells[lp->bncols * b + a + 1] = BLUE; + } + if (orient == 1 || orient == 2) { + lp->newcells[lp->bncols * (b + 1) + a + 2] = BLUE; + } + if (orient == 2 || orient == 3) { + lp->newcells[lp->bncols * (b + 2) + a + 1] = BLUE; + } + if (orient == 3 || orient == 0) { + lp->newcells[lp->bncols * (b + 1) + a] = BLUE; + } + } +} + +static void +init_adam(ModeInfo * mi) +{ + loopstruct *lp = &loops[MI_SCREEN(mi)]; + XPoint start = { 0, 0 }, dirx = { 0, 0 }, diry = { 0, 0 }; + int i, j, dir; + +#ifdef DELAYDEBUGLOOP + lp->clockwise = 0; + if (!MI_COUNT(mi)) /* Probably doing testing so do not confuse */ +#endif + lp->clockwise = (Bool) (LRAND() & 1); +#ifdef DELAYDEBUGLOOP + dir = 0; + if (!MI_COUNT(mi)) /* Probably doing testing so do not confuse */ +#endif + dir = NRAND(local_neighbors); + if (local_neighbors == 6) { + int k; + + switch (dir) { + case 0: + start.x = (lp->bncols - HEX_ADAM_LOOPX / 2) / 2; + start.y = (lp->bnrows - HEX_ADAM_LOOPY) / 2; + if (lp->mincol > start.x - 2) + lp->mincol = start.x - 2; + if (lp->minrow > start.y - 1) + lp->minrow = start.y - 1; + if (lp->maxcol < start.x + HEX_ADAM_LOOPX + 1) + lp->maxcol = start.x + HEX_ADAM_LOOPX + 1; + if (lp->maxrow < start.y + HEX_ADAM_LOOPY + 1) + lp->maxrow = start.y + HEX_ADAM_LOOPY + 1; + for (j = 0; j < HEX_ADAM_LOOPY; j++) { + for (i = 0; i < HEX_ADAM_LOOPX; i++) { + k = (((lp->bnrows / 2 + HEX_ADAM_LOOPY / 2) % 2) ? -j / 2 : -(j + 1) / 2); + lp->newcells[(start.y + j) * lp->bncols + start.x + i + k] = + (lp->clockwise) ? + hex_self_reproducing_loop[i][j] : + hex_self_reproducing_loop[j][i]; + } + } + break; + case 1: + start.x = (lp->bncols - (HEX_ADAM_LOOPX + HEX_ADAM_LOOPY) / 2) / 2; + start.y = (lp->bnrows - HEX_ADAM_LOOPX + HEX_ADAM_LOOPY) / 2; + if (lp->mincol > start.x - 1) + lp->mincol = start.x - 1; + if (lp->minrow > start.y - HEX_ADAM_LOOPX) + lp->minrow = start.y - HEX_ADAM_LOOPX; + if (lp->maxcol < start.x + (HEX_ADAM_LOOPX + HEX_ADAM_LOOPY) / 2 + 1) + lp->maxcol = start.x + (HEX_ADAM_LOOPX + HEX_ADAM_LOOPY) / 2 + 1; + if (lp->maxrow < start.y + HEX_ADAM_LOOPY + 1) + lp->maxrow = start.y + HEX_ADAM_LOOPY + 1; + for (j = 0; j < HEX_ADAM_LOOPY; j++) { + for (i = 0; i < HEX_ADAM_LOOPX; i++) { + k = (((lp->bnrows / 2 + (HEX_ADAM_LOOPX + HEX_ADAM_LOOPY) / 2) % 2) + ? -(i + j + 1) / 2 : -(i + j) / 2); + lp->newcells[(start.y + j - i) * lp->bncols + start.x + i + j + k] = + (lp->clockwise) ? + hex_self_reproducing_loop[i][j] : + hex_self_reproducing_loop[j][i]; + } + } + break; + case 2: + start.x = (lp->bncols - HEX_ADAM_LOOPY / 2) / 2; + start.y = (lp->bnrows - HEX_ADAM_LOOPX) / 2; + if (lp->mincol > start.x - 2) + lp->mincol = start.x - 2; + if (lp->minrow > start.y - 1) + lp->minrow = start.y - 1; + if (lp->maxcol < start.x + HEX_ADAM_LOOPX + 1) + lp->maxcol = start.x + HEX_ADAM_LOOPX + 1; + if (lp->maxrow < start.y + HEX_ADAM_LOOPY + 1) + lp->maxrow = start.y + HEX_ADAM_LOOPY + 1; + for (j = 0; j < HEX_ADAM_LOOPX; j++) { + for (i = 0; i < HEX_ADAM_LOOPY; i++) { + k = (((lp->bnrows / 2 + HEX_ADAM_LOOPX / 2) % 2) ? -(HEX_ADAM_LOOPX - j - 1) / 2 : -(HEX_ADAM_LOOPX - j) / 2); + lp->newcells[(start.y + j) * lp->bncols + start.x + i + k] = + (lp->clockwise) ? + hex_self_reproducing_loop[j][HEX_ADAM_LOOPX - i - 1] : + hex_self_reproducing_loop[i][HEX_ADAM_LOOPY - j - 1]; + } + } + break; + case 3: + start.x = (lp->bncols - HEX_ADAM_LOOPX / 2) / 2; + start.y = (lp->bnrows - HEX_ADAM_LOOPY) / 2; + if (lp->mincol > start.x - 1) + lp->mincol = start.x - 1; + if (lp->minrow > start.y - 1) + lp->minrow = start.y - 1; + if (lp->maxcol < start.x + HEX_ADAM_LOOPX + 1) + lp->maxcol = start.x + HEX_ADAM_LOOPX + 1; + if (lp->maxrow < start.y + HEX_ADAM_LOOPY + 1) + lp->maxrow = start.y + HEX_ADAM_LOOPY + 1; + for (j = 0; j < HEX_ADAM_LOOPY; j++) { + for (i = 0; i < HEX_ADAM_LOOPX; i++) { + k = (((lp->bnrows / 2 + HEX_ADAM_LOOPY / 2) % 2) ? -j / 2 : -(j + 1) / 2); + lp->newcells[(start.y + j) * lp->bncols + start.x + i + k] = + (lp->clockwise) ? + hex_self_reproducing_loop[HEX_ADAM_LOOPX - i - 1][HEX_ADAM_LOOPY - j - 1] : + hex_self_reproducing_loop[HEX_ADAM_LOOPY - j - 1][HEX_ADAM_LOOPX - i - 1]; + } + } + break; + case 4: + start.x = (lp->bncols - (HEX_ADAM_LOOPX + HEX_ADAM_LOOPY) / 2) / 2; + start.y = (lp->bnrows - HEX_ADAM_LOOPX + HEX_ADAM_LOOPY) / 2; + if (lp->mincol > start.x - 1) + lp->mincol = start.x - 1; + if (lp->minrow > start.y - HEX_ADAM_LOOPX) + lp->minrow = start.y - HEX_ADAM_LOOPX; + if (lp->maxcol < start.x + (HEX_ADAM_LOOPX + HEX_ADAM_LOOPY) / 2 + 1) + lp->maxcol = start.x + (HEX_ADAM_LOOPX + HEX_ADAM_LOOPY) / 2 + 1; + if (lp->maxrow < start.y + HEX_ADAM_LOOPY + 1) + lp->maxrow = start.y + HEX_ADAM_LOOPY + 1; + for (j = 0; j < HEX_ADAM_LOOPY; j++) { + for (i = 0; i < HEX_ADAM_LOOPX; i++) { + k = (((lp->bnrows / 2 + (HEX_ADAM_LOOPX + HEX_ADAM_LOOPY) / 2) % 2) + ? -(i + j + 1) / 2 : -(i + j) / 2); + lp->newcells[(start.y + j - i) * lp->bncols + start.x + i + j + k] = + (lp->clockwise) ? + hex_self_reproducing_loop[HEX_ADAM_LOOPX - i - 1][HEX_ADAM_LOOPY - j - 1] : + hex_self_reproducing_loop[HEX_ADAM_LOOPY - j - 1][HEX_ADAM_LOOPX - i - 1]; + } + } + break; + case 5: + start.x = (lp->bncols - HEX_ADAM_LOOPY / 2) / 2; + start.y = (lp->bnrows - HEX_ADAM_LOOPX) / 2; + if (lp->mincol > start.x - 2) + lp->mincol = start.x - 2; + if (lp->minrow > start.y - 1) + lp->minrow = start.y - 1; + if (lp->maxcol < start.x + HEX_ADAM_LOOPY + 1) + lp->maxcol = start.x + HEX_ADAM_LOOPY + 1; + if (lp->maxrow < start.y + HEX_ADAM_LOOPX + 1) + lp->maxrow = start.y + HEX_ADAM_LOOPX + 1; + for (j = 0; j < HEX_ADAM_LOOPX; j++) { + for (i = 0; i < HEX_ADAM_LOOPY; i++) { + k = (((lp->bnrows / 2 + HEX_ADAM_LOOPX / 2) % 2) ? -(HEX_ADAM_LOOPX - j - 1) / 2 : -(HEX_ADAM_LOOPX - j) / 2); + lp->newcells[(start.y + j) * lp->bncols + start.x + i + k] = + (lp->clockwise) ? + hex_self_reproducing_loop[HEX_ADAM_LOOPY - j - 1][i] : + hex_self_reproducing_loop[HEX_ADAM_LOOPX - i - 1][j]; + } + } + break; + } +#if DEBUGTEST + /* (void) printf ("s %d s %d \n", start.x, start.y); */ + (void) printf ("%d %d %d %d %d\n", + start.x + i + ((lp->bnrows / 2 % 2) ? -j / 2 : -(j + 1) / 2) - lp->bx, + start.y + j - lp->by, i, j, hex_self_reproducing_loop[j][i]); + /* Draw right away */ + drawcell(mi, start.x + i + ((lp->bnrows / 2 % 2) ? -j / 2 : -(j + 1) / 2) - lp->bx, + start.y + j - lp->by, + hex_self_reproducing_loop[j][i]); +#endif + } else { + switch (dir) { + case 0: + start.x = (lp->bncols - ADAM_LOOPX) / 2; + start.y = (lp->bnrows - ADAM_LOOPY) / 2; + dirx.x = 1, dirx.y = 0; + diry.x = 0, diry.y = 1; + if (lp->mincol > start.x) + lp->mincol = start.x; + if (lp->minrow > start.y) + lp->minrow = start.y; + if (lp->maxcol < start.x + ADAM_LOOPX) + lp->maxcol = start.x + ADAM_LOOPX; + if (lp->maxrow < start.y + ADAM_LOOPY) + lp->maxrow = start.y + ADAM_LOOPY; + break; + case 1: + start.x = (lp->bncols + ADAM_LOOPY) / 2; + start.y = (lp->bnrows - ADAM_LOOPX) / 2; + dirx.x = 0, dirx.y = 1; + diry.x = -1, diry.y = 0; + if (lp->mincol > start.x - ADAM_LOOPY) + lp->mincol = start.x - ADAM_LOOPY; + if (lp->minrow > start.y) + lp->minrow = start.y; + if (lp->maxcol < start.x) + lp->maxcol = start.x; + if (lp->maxrow < start.y + ADAM_LOOPX) + lp->maxrow = start.y + ADAM_LOOPX; + break; + case 2: + start.x = (lp->bncols + ADAM_LOOPX) / 2; + start.y = (lp->bnrows + ADAM_LOOPY) / 2; + dirx.x = -1, dirx.y = 0; + diry.x = 0, diry.y = -1; + if (lp->mincol > start.x - ADAM_LOOPX) + lp->mincol = start.x - ADAM_LOOPX; + if (lp->minrow > start.y - ADAM_LOOPY) + lp->minrow = start.y - ADAM_LOOPY; + if (lp->maxcol < start.x) + lp->maxcol = start.x; + if (lp->maxrow < start.y) + lp->maxrow = start.y; + break; + case 3: + start.x = (lp->bncols - ADAM_LOOPY) / 2; + start.y = (lp->bnrows + ADAM_LOOPX) / 2; + dirx.x = 0, dirx.y = -1; + diry.x = 1, diry.y = 0; + if (lp->mincol > start.x) + lp->mincol = start.x; + if (lp->minrow > start.y - ADAM_LOOPX) + lp->minrow = start.y - ADAM_LOOPX; + if (lp->maxcol < start.x + ADAM_LOOPX) + lp->maxcol = start.x + ADAM_LOOPX; + if (lp->maxrow < start.y) + lp->maxrow = start.y; + break; + } + for (j = 0; j < ADAM_LOOPY; j++) + for (i = 0; i < ADAM_LOOPX; i++) + lp->newcells[lp->bncols * (start.y + dirx.y * i + diry.y * j) + + start.x + dirx.x * i + diry.x * j] = + (lp->clockwise) ? + self_reproducing_loop[j][ADAM_LOOPX - i - 1] : + self_reproducing_loop[j][i]; +#if DEBUG + /* Draw right away */ + drawcell(mi, start.x + dirx.x * i + diry.x * j - lp->bx, + start.y + dirx.y * i + diry.y * j - lp->by, + (lp->clockwise) ? self_reproducing_loop[j][ADAM_LOOPX - i - i] : self_reproducing_loop[j][i]); +#endif + } +} + + +static void +do_gen(loopstruct * lp) +{ + int i, j, k; + unsigned char *z; + unsigned int n[MAXNEIGHBORS]; + unsigned int c; + +#define LOC(X, Y) (*(lp->oldcells + (X) + ((Y) * lp->bncols))) + + for (j = lp->minrow; j <= lp->maxrow; j++) { + for (i = lp->mincol; i <= lp->maxcol; i++) { + z = lp->newcells + i + j * lp->bncols; + c = LOC(i, j); + for (k = 0; k < local_neighbors; k++) { + int newi = i, newj = j; + + position_of_neighbor(k * ANGLES / local_neighbors, &newi, &newj); + n[k] = 0; + if (withinBounds(lp, newi, newj)) { + n[k] = LOC(newi, newj); + } + } + if (local_neighbors == 6) { + *z = (lp->clockwise) ? + HEX_TABLE_OUT(c, n[5], n[4], n[3], n[2], n[1], n[0]) : + HEX_TABLE_OUT(c, n[0], n[1], n[2], n[3], n[4], n[5]); + } else { + *z = (lp->clockwise) ? + TABLE_OUT(c, n[3], n[2], n[1], n[0]) : + TABLE_OUT(c, n[0], n[1], n[2], n[3]); + } + } + } +} + +ENTRYPOINT void +release_loop (ModeInfo * mi) +{ + if (loops != NULL) { + int screen; + + for (screen = 0; screen < MI_NUM_SCREENS(mi); screen++) + free_loop(MI_DISPLAY(mi), &loops[screen]); + (void) free((void *) loops); + loops = (loopstruct *) NULL; + } + if (table != NULL) { + (void) free((void *) table); + table = (unsigned int *) NULL; + } +} + +static void *stop_warning_about_triangleUnit_already; + + +ENTRYPOINT void +init_loop (ModeInfo * mi) +{ + Display *display = MI_DISPLAY(mi); + int i, size = MI_SIZE(mi); + loopstruct *lp; + + stop_warning_about_triangleUnit_already = (void *) &triangleUnit; + + if (loops == NULL) { + if ((loops = (loopstruct *) calloc(MI_NUM_SCREENS(mi), + sizeof (loopstruct))) == NULL) + return; + } + lp = &loops[MI_SCREEN(mi)]; + + lp->redrawing = 0; + +#ifdef DO_STIPPLE + if ((MI_NPIXELS(mi) < COLORS) && (lp->init_bits == 0)) { + Window window = MI_WINDOW(mi); + XGCValues gcv; + if (lp->stippledGC == None) { + gcv.fill_style = FillOpaqueStippled; + if ((lp->stippledGC = XCreateGC(display, window, + GCFillStyle, &gcv)) == None) { + free_loop(display, lp); + return; + } + } + LOOPBITS(stipples[0], STIPPLESIZE, STIPPLESIZE); + LOOPBITS(stipples[2], STIPPLESIZE, STIPPLESIZE); + LOOPBITS(stipples[3], STIPPLESIZE, STIPPLESIZE); + LOOPBITS(stipples[4], STIPPLESIZE, STIPPLESIZE); + LOOPBITS(stipples[6], STIPPLESIZE, STIPPLESIZE); + LOOPBITS(stipples[7], STIPPLESIZE, STIPPLESIZE); + LOOPBITS(stipples[8], STIPPLESIZE, STIPPLESIZE); + LOOPBITS(stipples[10], STIPPLESIZE, STIPPLESIZE); + } +#endif /* DO_STIPPLE */ + if (MI_NPIXELS(mi) >= COLORS) { + /* Maybe these colors should be randomized */ + lp->colors[0] = MI_BLACK_PIXEL(mi); + lp->colors[1] = MI_PIXEL(mi, 0); /* RED */ + lp->colors[5] = MI_PIXEL(mi, MI_NPIXELS(mi) / REALCOLORS); /* YELLOW */ + lp->colors[4] = MI_PIXEL(mi, 2 * MI_NPIXELS(mi) / REALCOLORS); /* GREEN */ + lp->colors[6] = MI_PIXEL(mi, 3 * MI_NPIXELS(mi) / REALCOLORS); /* CYAN */ + lp->colors[2] = MI_PIXEL(mi, 4 * MI_NPIXELS(mi) / REALCOLORS); /* BLUE */ + lp->colors[3] = MI_PIXEL(mi, 5 * MI_NPIXELS(mi) / REALCOLORS); /* MAGENTA */ + lp->colors[7] = MI_WHITE_PIXEL(mi); + } + free_list(lp); + lp->generation = 0; + lp->width = MI_WIDTH(mi); + lp->height = MI_HEIGHT(mi); + + if (!local_neighbors) { + for (i = 0; i < NEIGHBORKINDS; i++) { + if (neighbors == plots[i]) { + local_neighbors = neighbors; + break; + } + if (i == NEIGHBORKINDS - 1) { +#if 1 + local_neighbors = plots[NRAND(NEIGHBORKINDS)]; +#else + local_neighbors = 4; +#endif + break; + } + } + } + + + if (local_neighbors == 6) { + int nccols, ncrows; + + if (lp->width < 8) + lp->width = 8; + if (lp->height < 8) + lp->height = 8; + if (size < -MINSIZE) { + lp->ys = NRAND(MIN(-size, MAX(MINSIZE, MIN(lp->width, lp->height) / + HEX_MINGRIDSIZE)) - MINSIZE + 1) + MINSIZE; + } else if (size < MINSIZE) { + if (!size) + lp->ys = MAX(MINSIZE, MIN(lp->width, lp->height) / HEX_MINGRIDSIZE); + else + lp->ys = MINSIZE; + } else + lp->ys = MIN(size, MAX(MINSIZE, MIN(lp->width, lp->height) / + HEX_MINGRIDSIZE)); + lp->xs = lp->ys; + nccols = MAX(lp->width / lp->xs - 2, HEX_MINGRIDSIZE); + ncrows = MAX(lp->height / lp->ys - 1, HEX_MINGRIDSIZE); + lp->ncols = nccols / 2; + lp->nrows = ncrows / 2; + lp->nrows -= !(lp->nrows & 1); /* Must be odd */ + lp->xb = (lp->width - lp->xs * nccols) / 2 + lp->xs; + lp->yb = (lp->height - lp->ys * ncrows) / 2 + lp->ys; + for (i = 0; i < 6; i++) { + lp->shape.hexagon[i].x = (lp->xs - 1) * hexagonUnit[i].x; + lp->shape.hexagon[i].y = ((lp->ys - 1) * hexagonUnit[i].y / 2) * 4 / 3; + } + } else { + if (size < -MINSIZE) + lp->ys = NRAND(MIN(-size, MAX(MINSIZE, MIN(lp->width, lp->height) / + MINGRIDSIZE)) - MINSIZE + 1) + MINSIZE; + else if (size < MINSIZE) { + if (!size) + lp->ys = MAX(MINSIZE, MIN(lp->width, lp->height) / MINGRIDSIZE); + else + lp->ys = MINSIZE; + } else + lp->ys = MIN(size, MAX(MINSIZE, MIN(lp->width, lp->height) / + MINGRIDSIZE)); + lp->xs = lp->ys; + lp->ncols = MAX(lp->width / lp->xs, ADAM_LOOPX + 1); + lp->nrows = MAX(lp->height / lp->ys, ADAM_LOOPX + 1); + lp->xb = (lp->width - lp->xs * lp->ncols) / 2; + lp->yb = (lp->height - lp->ys * lp->nrows) / 2; + } + lp->bx = 1; + lp->by = 1; + lp->bncols = lp->ncols + 2 * lp->bx; + lp->bnrows = lp->nrows + 2 * lp->by; + + MI_CLEARWINDOW(mi); + + if (lp->oldcells != NULL) { + (void) free((void *) lp->oldcells); + lp->oldcells = (unsigned char *) NULL; + } + if ((lp->oldcells = (unsigned char *) calloc(lp->bncols * lp->bnrows, + sizeof (unsigned char))) == NULL) { + free_loop(display, lp); + return; + } + if (lp->newcells != NULL) { + (void) free((void *) lp->newcells); + lp->newcells = (unsigned char *) NULL; + } + if ((lp->newcells = (unsigned char *) calloc(lp->bncols * lp->bnrows, + sizeof (unsigned char))) == NULL) { + free_loop(display, lp); + return; + } + if (!init_table()) { + release_loop(mi); + return; + } + lp->mincol = lp->bncols - 1; + lp->minrow = lp->bnrows - 1; + lp->maxcol = 0; + lp->maxrow = 0; +#ifndef DELAYDEBUGLOOP + { + int flaws = MI_COUNT(mi); + + if (flaws < 0) + flaws = NRAND(-MI_COUNT(mi) + 1); + for (i = 0; i < flaws; i++) { + init_flaw(mi); + } + /* actual flaws might be less since the adam loop done next */ + } +#endif + init_adam(mi); +} + +ENTRYPOINT void +draw_loop (ModeInfo * mi) +{ + int offset, i, j; + unsigned char *z, *znew; + loopstruct *lp; + + if (loops == NULL) + return; + lp = &loops[MI_SCREEN(mi)]; + if (lp->newcells == NULL) + return; + + MI_IS_DRAWN(mi) = True; + lp->dead = True; +#ifdef DELAYDEBUGLOOP + if (MI_COUNT(mi) && lp->generation > MI_COUNT(mi)) { + (void) sleep(DELAYDEBUGLOOP); + } +#endif + + for (j = lp->minrow; j <= lp->maxrow; j++) { + for (i = lp->mincol; i <= lp->maxcol; i++) { + offset = j * lp->bncols + i; + z = lp->oldcells + offset; + znew = lp->newcells + offset; + if (*z != *znew) { + lp->dead = False; + *z = *znew; + if (!addtolist(mi, i - lp->bx, j - lp->by, *znew)) + return; + if (i == lp->mincol && i > lp->bx) + lp->mincol--; + if (j == lp->minrow && j > lp->by) + lp->minrow--; + if (i == lp->maxcol && i < lp->bncols - 2 * lp->bx) + lp->maxcol++; + if (j == lp->maxrow && j < lp->bnrows - 2 * lp->by) + lp->maxrow++; + } + } + } + for (i = 0; i < COLORS; i++) + if (!draw_state(mi, i)) { + free_loop(MI_DISPLAY(mi), lp); + return; + } + if (++lp->generation > MI_CYCLES(mi) || lp->dead) { + init_loop(mi); + return; + } else + do_gen(lp); + + if (lp->redrawing) { + for (i = 0; i < REDRAWSTEP; i++) { + if ((*(lp->oldcells + lp->redrawpos))) { + drawcell(mi, lp->redrawpos % lp->bncols - lp->bx, + lp->redrawpos / lp->bncols - lp->by, + *(lp->oldcells + lp->redrawpos)); + } + if (++(lp->redrawpos) >= lp->bncols * (lp->bnrows - lp->bx)) { + lp->redrawing = 0; + break; + } + } + } +} + +ENTRYPOINT void +reshape_loop(ModeInfo * mi, int width, int height) +{ + XClearWindow (MI_DISPLAY (mi), MI_WINDOW(mi)); + init_loop (mi); +} + +ENTRYPOINT void +refresh_loop (ModeInfo * mi) +{ + loopstruct *lp; + + if (loops == NULL) + return; + lp = &loops[MI_SCREEN(mi)]; + + MI_CLEARWINDOW(mi); + lp->redrawing = 1; + lp->redrawpos = lp->by * lp->ncols + lp->bx; +} + +XSCREENSAVER_MODULE ("Loop", loop) + +#endif /* MODE_loop */ diff --git a/hacks/loop.man b/hacks/loop.man new file mode 100644 index 00000000..37fb9705 --- /dev/null +++ b/hacks/loop.man @@ -0,0 +1,65 @@ +.TH XScreenSaver 1 "" "X Version 11" +.SH NAME +loop - cellular automaton. +.SH SYNOPSIS +.B loop +[\-display \fIhost:display.screen\fP] +[\-visual \fIvisual\fP] +[\-window] +[\-root] +[\-cycles \fInumber\fP] +[\-delay \fInumber\fP] +[\-ncolors \fInumber\fP] +[\-size \fInumber\fP] +[\-fps] +.SH DESCRIPTION +Another cellular automaton. +This one produces loop-shaped colonies that spawn, age, and eventually die. +.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 \-cycles \fInumber\fP +Timeout. 0 - 8000. Default: 1600. +.TP 8 +.B \-delay \fInumber\fP +Per-frame delay, in microseconds. Default: 100000 (0.10 seconds.). +.TP 8 +.B \-ncolors \fInumber\fP +Number of Colors. Default: 15. +.TP 8 +.B \-size \fInumber\fP +Size. -50 - 50. Default: -12. +.TP 8 +.B \-fps +Display the current frame rate and CPU load. +.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 2002 by David Bagley. 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 Bagley. diff --git a/hacks/m6502.c b/hacks/m6502.c new file mode 100644 index 00000000..11a78743 --- /dev/null +++ b/hacks/m6502.c @@ -0,0 +1,290 @@ +/* -*- indent-tabs-mode:nil -*- + * Copyright (c) 2007 Jeremy English + * + * 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. + * + * Created: 07-May-2007 + */ + +#include +#include +#include "screenhack.h" +#include "analogtv.h" +#include "asm6502.h" + +# ifdef __GNUC__ + __extension__ /* don't warn about "string length is greater than the length + ISO C89 compilers are required to support" when includng + the following data file... */ +# endif +static const char * const demo_files[] = { +# include "m6502.h" +}; + + +#ifndef USE_IPHONE +# define READ_FILES +#endif + + +/* We want to paint on a 32 by 32 grid of pixels. We will needed to + divided the screen up into chuncks */ +enum { + SCREEN_W = ANALOGTV_VIS_LEN, + SCREEN_H = ANALOGTV_VISLINES, + NUM_PROGS = 9 +}; + +struct state { + Display *dpy; + Window window; + + Bit8 pixels[32][32]; + + machine_6502 *machine; + + analogtv *tv; + analogtv_input *inp; + analogtv_reception reception; + int pixw; /* pixel width */ + int pixh;/* pixel height */ + int topb;/* top boarder */ + int field_ntsc[4];/* used for clearing the screen*/ + int dt;/* how long to wait before changing the demo*/ + int which;/* the program to run*/ + int demos;/* number of demos included */ + struct timeval start_time; +}; + +static void +plot6502(Bit8 x, Bit8 y, Bit8 color, void *closure) +{ + struct state *st = (struct state *) closure; + st->pixels[x][y] = color; +} + +#undef countof +#define countof(x) (sizeof((x))/sizeof((*x))) + + +static void +start_rand_bin_prog(machine_6502 *machine, struct state *st){ + int n = st->which; + while(n == st->which) + n = random() % st->demos; + st->which = n; + m6502_start_eval_string(machine, demo_files[st->which], plot6502, st); +} + + +/* + * get_time () + * + * returns the total time elapsed since the beginning of the demo + */ +static double get_time(struct state *st) { + struct timeval t; + float f; +#if GETTIMEOFDAY_TWO_ARGS + gettimeofday(&t, NULL); +#else + gettimeofday(&t); +#endif + t.tv_sec -= st->start_time.tv_sec; + f = ((double)t.tv_sec) + t.tv_usec*1e-6; + return f; +} + +/* + * init_time () + * + * initialises the timing structures + */ +static void init_time(struct state *st) { +#if GETTIMEOFDAY_TWO_ARGS + gettimeofday(&st->start_time, NULL); +#else + gettimeofday(&st->start_time); +#endif +} + +static void * +m6502_init (Display *dpy, Window window) +{ + struct state *st = (struct state *) calloc (1, sizeof(*st)); + unsigned int x, y; + int n = get_integer_resource(dpy, "displaytime", "Displaytime"); + int dh; + st->demos = countof(demo_files); + st->which = random() % st->demos; + st->dt = n; + st->dpy = dpy; + st->window = window; + st->tv=analogtv_allocate(st->dpy, st->window); + analogtv_set_defaults(st->tv, ""); + + st->machine = m6502_build(); + st->inp=analogtv_input_allocate(); + analogtv_setup_sync(st->inp, 1, 0); + + st->reception.input = st->inp; + st->reception.level = 2.0; + st->reception.ofs=0; + + st->reception.multipath=0.0; + st->pixw = SCREEN_W / 32; + st->pixh = SCREEN_H / 32; + dh = SCREEN_H % 32; + st->topb = dh / 2; + + init_time(st); + + { +#ifdef READ_FILES + char *s = get_string_resource (dpy, "file", "File"); + if (strlen(s) > 0) + m6502_start_eval_file(st->machine,s, plot6502, st); + else +#endif + start_rand_bin_prog(st->machine,st); + } + + analogtv_lcp_to_ntsc(ANALOGTV_BLACK_LEVEL, 0.0, 0.0, st->field_ntsc); + + analogtv_draw_solid(st->inp, + ANALOGTV_VIS_START, ANALOGTV_VIS_END, + ANALOGTV_TOP, ANALOGTV_BOT, + st->field_ntsc); + + for(x = 0; x < 32; x++) + for(y = 0; y < 32; y++) + st->pixels[x][y] = 0; + + return st; +} + +static void +paint_pixel(struct state *st, int x, int y, int idx) +{ + double clr_tbl[16][3] = { + { 0, 0, 0}, + {255, 255, 255}, + {136, 0, 0}, + {170, 255, 238}, + {204, 68, 204}, + { 0, 204, 85}, + { 0, 0, 170}, + {238, 238, 119}, + {221, 136, 85}, + {102, 68, 0}, + {255, 119, 119}, + { 51, 51, 51}, + {119, 119, 119}, + {170, 255, 102}, + { 0, 136, 255}, + {187, 187, 187} + }; + int ntsc[4], i; + int rawy,rawi,rawq; + /* RGB conversion taken from analogtv draw xpm */ + rawy=( 5*clr_tbl[idx][0] + 11*clr_tbl[idx][1] + 2*clr_tbl[idx][2]) / 64; + rawi=(10*clr_tbl[idx][0] - 4*clr_tbl[idx][1] - 5*clr_tbl[idx][2]) / 64; + rawq=( 3*clr_tbl[idx][0] - 8*clr_tbl[idx][1] + 5*clr_tbl[idx][2]) / 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]pixw; + y *= st->pixh; + y += st->topb; + analogtv_draw_solid(st->inp, + ANALOGTV_VIS_START + x, ANALOGTV_VIS_START + x + st->pixw, + ANALOGTV_TOP + y, ANALOGTV_TOP + y + st->pixh, ntsc); +} + +static unsigned long +m6502_draw (Display *dpy, Window window, void *closure) +{ + struct state *st = (struct state *) closure; + unsigned int x = 0, y = 0; + double te; + + m6502_next_eval(st->machine,500); + + for (x = 0; x < 32; x++) + for (y = 0; y < 32; y++) + paint_pixel(st,x,y,st->pixels[x][y]); + + analogtv_init_signal(st->tv, 0.04); + analogtv_reception_update(&st->reception); + analogtv_add_signal(st->tv, &st->reception); + analogtv_draw(st->tv); + te = get_time(st); + + if (te > st->dt){ /* do something more interesting here XXX */ + for(x = 0; x < 32; x++) + for(y = 0; y < 32; y++) + st->pixels[x][y] = 0; + init_time(st); + start_rand_bin_prog(st->machine,st); + } + + return 10000; +} + + + + +static const char *m6502_defaults [] = { + ".background: black", + ".foreground: white", + "*file:", + "*displaytime: 20", + ANALOGTV_DEFAULTS + 0 +}; + +static XrmOptionDescRec m6502_options [] = { + { "-file", ".file", XrmoptionSepArg, 0 }, + { "-displaytime", ".displaytime", XrmoptionSepArg, 0}, + ANALOGTV_OPTIONS + { 0, 0, 0, 0 } +}; + +static void +m6502_reshape (Display *dpy, Window window, void *closure, + unsigned int w, unsigned int h) +{ + struct state *st = (struct state *) closure; + analogtv_reconfigure (st->tv); +} + +static Bool +m6502_event (Display *dpy, Window window, void *closure, XEvent *event) +{ + return False; +} + +static void +m6502_free (Display *dpy, Window window, void *closure) +{ + struct state *st = (struct state *) closure; + analogtv_release(st->tv); + free (st); +} + +XSCREENSAVER_MODULE ("m6502", m6502) diff --git a/hacks/m6502.sh b/hacks/m6502.sh new file mode 100755 index 00000000..f592111d --- /dev/null +++ b/hacks/m6502.sh @@ -0,0 +1,25 @@ +#!/bin/sh + +TARGET=$1 +shift +SRCS=$* + +TMP1=m6502.h.1.$$ +TMP2=m6502.h.2.$$ +rm -f $TMP1 $TMP2 + +if [ -z "$UTILS_SRC" ]; then UTILS_SRC="../utils"; fi + +for f in $SRCS ; do + sed 's/[ ]*;.*$//' < "$f" > $TMP1 # lose comments + sh "$UTILS_SRC/ad2c" $TMP1 | + sed 's/",$/\\n"/' >> $TMP2 + echo ',' >> $TMP2 +done +rm $TMP1 +if cmp -s $TMP2 $TARGET ; then + rm $TMP2 +else + mv $TMP2 $TARGET +fi + diff --git a/hacks/maze.c b/hacks/maze.c new file mode 100644 index 00000000..8576386b --- /dev/null +++ b/hacks/maze.c @@ -0,0 +1,1650 @@ +/****************************************************************************** + * [ maze ] ... + * + * modified: [ 13-08-08 ] Jamie Zawinski + * Removed the bridge option: it didn't look good, and it made + * the code a lot harder to understand. + * Made the maze stay out of the area used for the -fps display. + * Cleaned up and commented. + * + * modified: [ 1-04-00 ] Johannes Keukelaar + * Added -ignorant option (not the default) to remove knowlege + * of the direction in which the exit lies. + * + * modified: [ 6-28-98 ] Zack Weinberg + * + * Made the maze-solver somewhat more intelligent. There are + * three optimizations: + * + * - Straight-line lookahead: the solver does not enter dead-end + * corridors. This is a win with all maze generators. + * + * - First order direction choice: the solver knows where the + * exit is in relation to itself, and will try paths leading in + * that direction first. This is a major win on maze generator 1 + * which tends to offer direct routes to the exit. + * + * - Dead region elimination: the solver already has a map of + * all squares visited. Whenever it starts to backtrack, it + * consults this map and marks off all squares that cannot be + * reached from the exit without crossing a square already + * visited. Those squares can never contribute to the path to + * the exit, so it doesn't bother checking them. This helps a + * lot with maze generator 2 and somewhat less with generator 1. + * + * Further improvements would require knowledge of the wall map + * as well as the position of the exit and the squares visited. + * I would consider that to be cheating. Generator 0 makes + * mazes which are remarkably difficult to solve mechanically -- + * even with these optimizations the solver generally must visit + * at least two-thirds of the squares. This is partially + * because generator 0's mazes have longer paths to the exit. + * + * modified: [ 4-10-97 ] Johannes Keukelaar + * Added multiple maze creators. Robustified solver. + * Added bridge option. + * modified: [ 8-11-95 ] Ed James + * added fill of dead-end box to solve_maze while loop. + * modified: [ 3-7-93 ] Jamie Zawinski + * added the XRoger logo, cleaned up resources, made + * grid size a parameter. + * modified: [ 3-3-93 ] Jim Randell + * Added the colour stuff and integrated it with jwz's + * screenhack stuff. There's still some work that could + * be done on this, particularly allowing a resource to + * specify how big the squares are. + * modified: [ 10-4-88 ] Richard Hess ...!uunet!cimshop!rhess + * [ Revised primary execution loop within main()... + * [ Extended X event handler, check_events()... + * modified: [ 1-29-88 ] Dave Lemke lemke@sun.com + * [ Hacked for X11... + * [ Note the word "hacked" -- this is extremely ugly, but at + * [ least it does the job. NOT a good programming example + * [ for X. + * original: [ 6/21/85 ] Martin Weiss Sun Microsystems [ SunView ] + * + ****************************************************************************** + Copyright 1988 by Sun Microsystems, Inc. Mountain View, CA. + + All Rights Reserved + + Permission to use, copy, modify, and distribute this software and its + documentation for any purpose and without fee is hereby granted, + provided that the above copyright notice appear in all copies and that + both that copyright notice and this permission notice appear in + supporting documentation, and that the names of Sun or MIT not be + used in advertising or publicity pertaining to distribution of the + software without specific prior written permission. Sun and M.I.T. + make no representations about the suitability of this software for + any purpose. It is provided "as is" without any express or implied warranty. + + SUN DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING + ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + PURPOSE. IN NO EVENT SHALL SUN BE LIABLE FOR ANY SPECIAL, INDIRECT + OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS + OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE + OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE + OR PERFORMANCE OF THIS SOFTWARE. + *****************************************************************************/ + +#include "screenhack.h" +#include "erase.h" + +#include + +/* #include */ +#define gray1_width 2 +#define gray1_height 2 +static const char gray1_bits[] = { 0x01, 0x02 }; + + +#define MAX_MAZE_SIZE_X 1000 +#define MAX_MAZE_SIZE_Y 1000 + +#define MOVE_LIST_SIZE (MAX_MAZE_SIZE_X * MAX_MAZE_SIZE_Y) + +#define NOT_DEAD 0x8000 +#define SOLVER_VISIT 0x4000 +#define START_SQUARE 0x2000 +#define END_SQUARE 0x1000 + +#define WALL_TOP 0x8 +#define WALL_RIGHT 0x4 +#define WALL_BOTTOM 0x2 +#define WALL_LEFT 0x1 +#define WALL_ANY 0xF + +#define DOOR_IN_TOP 0x800 +#define DOOR_IN_RIGHT 0x400 +#define DOOR_IN_BOTTOM 0x200 +#define DOOR_IN_LEFT 0x100 +#define DOOR_IN_ANY 0xF00 + +#define DOOR_OUT_TOP 0x80 +#define DOOR_OUT_RIGHT 0x40 +#define DOOR_OUT_BOTTOM 0x20 +#define DOOR_OUT_LEFT 0x10 + + +#define border_x (0) +#define border_y (0) + +#define get_random(x) (random() % (x)) + + +struct move_list_struct { + unsigned short x; + unsigned short y; + unsigned char dir, ways; +}; + +struct solve_state { + int running; + int i, x, y, bt; +}; + + +struct state { + Display *dpy; + Window window; + + GC gc, cgc, tgc, sgc, ugc, logo_gc, erase_gc; + Pixmap logo_map; + + int logo_x, logo_y; /* in grid cells (or -1) */ + int logo_width, logo_height; /* in pixels */ + int fps_width, fps_height; /* in pixels */ + + int solve_delay, pre_solve_delay, post_solve_delay; + + unsigned short maze[MAX_MAZE_SIZE_X][MAX_MAZE_SIZE_Y]; + + struct move_list_struct move_list[MOVE_LIST_SIZE]; + struct move_list_struct save_path[MOVE_LIST_SIZE]; + struct move_list_struct path[MOVE_LIST_SIZE]; + + int maze_size_x, maze_size_y; + int sqnum, cur_sq_x, cur_sq_y, path_length; + int start_x, start_y, start_dir, end_x, end_y, end_dir; + int grid_width, grid_height; + int bw; + + int x, y, restart, stop, state, max_length; + int sync_p, sync_tick; + int ignorant_p; + + struct solve_state *solve_state; + + int *sets; /* The sets that our squares are in. */ + int *hedges; /* The `list' of hedges. */ + + int this_gen; + int erase_window; + eraser_state *eraser; + + int ifrandom; + int ifinit; + +}; + + +static void draw_wall (struct state *, int, int, int, GC); +static void draw_solid_square (struct state *, int, int, int, GC); +static void build_wall (struct state *, int, int, int); + + +static void +set_maze_sizes (struct state *st, int width, int height) +{ + st->maze_size_x = width / st->grid_width; + st->maze_size_y = height / st->grid_height; + + if (st->maze_size_x < 4) st->maze_size_x = 4; + if (st->maze_size_y < 4) st->maze_size_y = 4; +} + + +/* Resets the maze grid, picks the starting and ending points, + and the position of the logo, if any. + */ +static void +initialize_maze (struct state *st) +{ + int retry_count = 0; + int i, j, wall; + int logow = 1 + st->logo_width / st->grid_width; + int logoh = 1 + st->logo_height / st->grid_height; + + AGAIN: + + /* This can happen if the window is really small. Let's not sweat it. */ + if (++retry_count > 100) return; + + + /* initialize all squares */ + for ( i=0; imaze_size_x; i++) { + for ( j=0; jmaze_size_y; j++) { + st->maze[i][j] = 0; + } + } + + /* top wall */ + for ( i=0; imaze_size_x; i++ ) { + st->maze[i][0] |= WALL_TOP; + } + + /* right wall */ + for ( j=0; jmaze_size_y; j++ ) { + st->maze[st->maze_size_x-1][j] |= WALL_RIGHT; + } + + /* bottom wall */ + for ( i=0; imaze_size_x; i++ ) { + st->maze[i][st->maze_size_y-1] |= WALL_BOTTOM; + } + + /* left wall */ + for ( j=0; jmaze_size_y; j++ ) { + st->maze[0][j] |= WALL_LEFT; + } + + /* set start square */ + wall = get_random(4); + switch (wall) { + case 0: + i = get_random(st->maze_size_x); + j = 0; + break; + case 1: + i = st->maze_size_x - 1; + j = get_random(st->maze_size_y); + break; + case 2: + i = get_random(st->maze_size_x); + j = st->maze_size_y - 1; + break; + case 3: + i = 0; + j = get_random(st->maze_size_y); + break; + } + st->maze[i][j] |= START_SQUARE; + st->maze[i][j] |= ( DOOR_IN_TOP >> wall ); + st->maze[i][j] &= ~( WALL_TOP >> wall ); + st->cur_sq_x = i; + st->cur_sq_y = j; + st->start_x = i; + st->start_y = j; + st->start_dir = wall; + st->sqnum = 0; + + /* set end square */ + wall = (wall + 2)%4; + switch (wall) { + case 0: + i = get_random(st->maze_size_x); + j = 0; + break; + case 1: + i = st->maze_size_x - 1; + j = get_random(st->maze_size_y); + break; + case 2: + i = get_random(st->maze_size_x); + j = st->maze_size_y - 1; + break; + case 3: + i = 0; + j = get_random(st->maze_size_y); + break; + } + st->maze[i][j] |= END_SQUARE; + st->maze[i][j] |= ( DOOR_OUT_TOP >> wall ); + st->maze[i][j] &= ~( WALL_TOP >> wall ); + st->end_x = i; + st->end_y = j; + st->end_dir = wall; + + /* set logo */ + if ((st->maze_size_x-logow >= 6) && (st->maze_size_y-logoh >= 6)) + { + /* not closer than 3 grid units from a wall, to ensure that it + won't overlap the entrance or exit. */ + st->logo_x = get_random (st->maze_size_x - logow - 5) + 3; + st->logo_y = get_random (st->maze_size_y - logoh - 5) + 3; + for (i=0; imaze[st->logo_x + i][st->logo_y + j] |= DOOR_IN_ANY; + } + else + st->logo_y = st->logo_x = -1; + + /* mask out the fps area */ + if (st->fps_width > 0) + { + int fpsw = 1 + st->fps_width / st->grid_width; + int fpsh = 1 + st->fps_height / st->grid_width; + + /* if the chosen logo position overlapped the fps area, try again! */ + if (st->logo_x < fpsw+3 && st->logo_y+logoh > st->maze_size_y-fpsh-4) + goto AGAIN; + + /* if the start or end point is inside the fps area, try again! */ + if ((st->start_x <= fpsw && st->start_y >= st->maze_size_y-fpsh-1) || + (st->end_x <= fpsw && st->end_y >= st->maze_size_y-fpsh-1)) + goto AGAIN; + + for (i=0; imaze[i][st->maze_size_y - j - 1] |= DOOR_IN_ANY|SOLVER_VISIT; + /* take off left/bottom wall or the FPS text overlaps it */ + st->maze[i][st->maze_size_y - j - 1] &= ~(WALL_BOTTOM|WALL_LEFT); + } + } +} + + +/**************************************************************************** + Generator 2: Set-based maze generator. + + Put each square in the maze in a separate set. Also, make a list of all the + hedges. Randomize that list. Walk through the list. If, for a certain + hedge, the two squares on both sides of it are in different sets, union the + sets and remove the hedge. Continue until all hedges have been processed or + only one set remains. + + This is essentially the "Kruskal" algorithm. + + ****************************************************************************/ + +static void mask_out_set_rect(struct state *st, int x, int y, int w, int h); + +/* Initialise the sets. */ +static void +init_sets(struct state *st) +{ + int i, t, r; + + if(st->sets) + free(st->sets); + st->sets = (int *)malloc(st->maze_size_x*st->maze_size_y*sizeof(int)); + if(!st->sets) + abort(); + for(i = 0; i < st->maze_size_x*st->maze_size_y; i++) + { + st->sets[i] = i; + } + + if(st->hedges) + free(st->hedges); + st->hedges = (int *)malloc(st->maze_size_x*st->maze_size_y*2*sizeof(int)); + if(!st->hedges) + abort(); + for(i = 0; i < st->maze_size_x*st->maze_size_y*2; i++) + { + st->hedges[i] = i; + } + /* Mask out outside walls. */ + for(i = 0; i < st->maze_size_y; i++) + { + st->hedges[2*((st->maze_size_x)*i+st->maze_size_x-1)+1] = -1; + } + for(i = 0; i < st->maze_size_x; i++) + { + st->hedges[2*((st->maze_size_y-1)*st->maze_size_x+i)] = -1; + } + + /* Mask out the logo area. */ + if(st->logo_x!=-1) + { + int logow = 1 + st->logo_width / st->grid_width; + int logoh = 1 + st->logo_height / st->grid_height; + mask_out_set_rect(st, st->logo_x, st->logo_y, logow, logoh); + } + + /* Mask out the FPS area. */ + if(st->fps_width > 0) + { + int fpsw = 1 + st->fps_width / st->grid_width; + int fpsh = 1 + st->fps_height / st->grid_height; + mask_out_set_rect(st, 0, st->maze_size_y-fpsh, fpsw, fpsh); + } + + for(i = 0; i < st->maze_size_x*st->maze_size_y*2; i++) + { + t = st->hedges[i]; + r = random()%(st->maze_size_x*st->maze_size_y*2); + st->hedges[i] = st->hedges[r]; + st->hedges[r] = t; + } +} + +/* Get the representative of a set. */ +static int +get_set(struct state *st, int num) +{ + int s; + + if(st->sets[num]==num) + return num; + else + { + s = get_set(st, st->sets[num]); + st->sets[num] = s; + return s; + } +} + +/* Join two sets together. */ +static void +join_sets(struct state *st, int num1, int num2) +{ + int s1, s2; + + s1 = get_set(st, num1); + s2 = get_set(st, num2); + + if(s1sets[s2] = s1; + else + st->sets[s1] = s2; +} + +/* Exitialise the sets. */ +static void +exit_sets(struct state *st) +{ + if(st->hedges) + free(st->hedges); + st->hedges = 0; + if(st->sets) + free(st->sets); + st->sets = 0; +} + + +static void +set_create_maze(struct state *st) +{ + int i, h, xx, yy, dir, v, w; + + /* Do almost all the setup. */ + init_sets(st); + + /* Start running through the hedges. */ + for(i = 0; i < 2*st->maze_size_x*st->maze_size_y; i++) + { + h = st->hedges[i]; + + /* This one is in the logo or outside border. */ + if(h==-1) + continue; + + dir = h%2?1:2; + xx = (h>>1)%st->maze_size_x; + yy = (h>>1)/st->maze_size_x; + + v = xx; + w = yy; + switch(dir) + { + case 1: + v++; + break; + case 2: + w++; + break; + } + + if(get_set(st, xx+yy*st->maze_size_x)!=get_set(st, v+w*st->maze_size_x)) + { + join_sets(st, xx+yy*st->maze_size_x, v+w*st->maze_size_x); + /* Don't draw the wall. */ + } + else + { + /* Don't join the sets. */ + build_wall(st, xx, yy, dir); + } + } + + /* Free some memory. */ + exit_sets(st); +} + +/* mark a rectangle as being unavailable for usage in the maze */ +static void +mask_out_set_rect(struct state *st, int x, int y, int w, int h) +{ + int xx, yy; + for(xx = x; xx < x+w; xx++) + for(yy = y; yy < y+h; yy++) + { + st->hedges[2*(xx+st->maze_size_x*yy)+1] = -1; + st->hedges[2*(xx+st->maze_size_x*yy)] = -1; + } + for(xx = x; xx < x+w; xx++) + { + build_wall(st, xx, y, 0); + build_wall(st, xx, y+h, 0); + st->hedges[2*(xx+st->maze_size_x*(y-1))] = -1; + } + for(yy = y; yy < y+h; yy++) + { + build_wall(st, x, yy, 3); + build_wall(st, x+w, yy, 3); + st->hedges[2*(x-1+st->maze_size_x*yy)+1] = -1; + } +} + + +/**************************************************************************** + Generator 1: Wall-building maze generator. + + Pick a random, empty corner in the maze. Pick a random direction. Draw a + wall in that direction, from that corner until we hit a wall. Option: Only + draw the wall if it's going to be shorter than a certain length. Otherwise + we get lots of long walls. + + This is essentially the "Prim" algorithm. + ****************************************************************************/ + +static void alt_mask_out_rect(struct state *st, char *corners, + int x, int y, int w, int h); + +static void +alt_create_maze(struct state *st) +{ + char *corners; + int *c_idx; + int i, j, height, width, open_corners, k, dir, xx, yy; + + height = st->maze_size_y+1; + width = st->maze_size_x+1; + + /* Allocate and clear some mem. */ + corners = (char *)calloc(height*width, 1); + if(!corners) + return; + + /* Set up the indexing array. */ + c_idx = (int *)malloc(sizeof(int)*height*width); + if(!c_idx) + { + free(corners); + return; + } + for(i = 0; i < height*width; i++) + c_idx[i] = i; + for(i = 0; i < height*width; i++) + { + j = c_idx[i]; + k = random()%(height*width); + c_idx[i] = c_idx[k]; + c_idx[k] = j; + } + + /* Set up some initial walls. */ + /* Outside walls. */ + for(i = 0; i < width; i++) + { + corners[i] = 1; + corners[i+width*(height-1)] = 1; + } + for(i = 0; i < height; i++) + { + corners[i*width] = 1; + corners[i*width+width-1] = 1; + } + + /* mask out the logo area */ + if(st->logo_x!=-1) + { + int logow = 1 + st->logo_width / st->grid_width; + int logoh = 1 + st->logo_height / st->grid_height; + alt_mask_out_rect (st, corners, st->logo_x, st->logo_y, logow, logoh); + } + + /* mask out the FPS area */ + if(st->fps_width>0) + { + int fpsw = 1 + st->fps_width / st->grid_width; + int fpsh = 1 + st->fps_height / st->grid_height; + alt_mask_out_rect (st, corners, 0, st->maze_size_y-fpsh, fpsw, fpsh); + } + + /* Count open gridpoints. */ + open_corners = 0; + for(i = 0; i < width; i++) + for(j = 0; j < height; j++) + if(!corners[i+width*j]) + open_corners++; + + /* Now do actual maze generation. */ + while(open_corners>0) + { + for(i = 0; i < width*height; i++) + { + if(!corners[c_idx[i]]) + { + xx = c_idx[i]%width; + yy = c_idx[i]/width; + /* Choose a random direction. */ + dir = random()%4; + + k = 0; + /* Measure the length of the wall we'd draw. */ + while(!corners[xx+width*yy]) + { + k++; + switch(dir) + { + case 0: + yy--; + break; + case 1: + xx++; + break; + case 2: + yy++; + break; + case 3: + xx--; + break; + } + } + + if(k<=st->max_length) + { + xx = c_idx[i]%width; + yy = c_idx[i]/width; + + /* Draw a wall until we hit something. */ + while(!corners[xx+width*yy]) + { + open_corners--; + corners[xx+width*yy] = 1; + switch(dir) + { + case 0: + build_wall(st, xx-1, yy-1, 1); + yy--; + break; + case 1: + build_wall(st, xx, yy, 0); + xx++; + break; + case 2: + build_wall(st, xx, yy, 3); + yy++; + break; + case 3: + build_wall(st, xx-1, yy-1, 2); + xx--; + break; + } + } + } + } + } + } + + /* Free some memory we used. */ + free(corners); + free(c_idx); +} + + +/* mark a rectangle as being unavailable for usage in the maze */ +static void +alt_mask_out_rect(struct state *st, char *corners, int x, int y, int w, int h) +{ + int i, j, xx, yy; + int mazew = st->maze_size_x+1; + + for(i = x; i <= x+w; i++) + for(j = y; j <= y+h; j++) + corners[i+mazew*j] = 1; + + for(xx = x; xx < x+w; xx++) + { + build_wall(st, xx, y, 0); + if (y+h < st->maze_size_y) + build_wall(st, xx, y+h, 0); + } + for(yy = y; yy < y+h; yy++) + { + if (x > 0) + build_wall(st, x, yy, 3); + build_wall(st, x+w, yy, 3); + } +} + + +/**************************************************************************** + Generator 0: The original maze generator. + + Start somewhere. Take a step in a random direction. Keep doing this until + we hit a wall. Then, backtrack until we find a point where we can go in + another direction. + + This is essentially the "depth-first recursive backtracker" algorithm. + ****************************************************************************/ + +static int choose_door (struct state *st); +static int backup (struct state *st); + +static void +create_maze (struct state *st) /* create a maze layout given the initialized maze */ +{ + int i, newdoor = 0; + + do { + st->move_list[st->sqnum].x = st->cur_sq_x; + st->move_list[st->sqnum].y = st->cur_sq_y; + st->move_list[st->sqnum].dir = newdoor; + while ( ( newdoor = choose_door(st) ) == -1 ) { /* pick a door */ + if ( backup(st) == -1 ) { /* no more doors ... backup */ + return; /* done ... return */ + } + } + + /* mark the out door */ + st->maze[st->cur_sq_x][st->cur_sq_y] |= ( DOOR_OUT_TOP >> newdoor ); + + switch (newdoor) { + case 0: st->cur_sq_y--; + break; + case 1: st->cur_sq_x++; + break; + case 2: st->cur_sq_y++; + break; + case 3: st->cur_sq_x--; + break; + } + st->sqnum++; + + /* mark the in door */ + st->maze[st->cur_sq_x][st->cur_sq_y] |= ( DOOR_IN_TOP >> ((newdoor+2)%4) ); + + /* if end square set path length and save path */ + if ( st->maze[st->cur_sq_x][st->cur_sq_y] & END_SQUARE ) { + st->path_length = st->sqnum; + for ( i=0; ipath_length; i++) { + st->save_path[i].x = st->move_list[i].x; + st->save_path[i].y = st->move_list[i].y; + st->save_path[i].dir = st->move_list[i].dir; + } + } + + } while (1); + +} + + +static int +choose_door (struct state *st) /* pick a new path */ +{ + int candidates[3]; + int num_candidates; + + num_candidates = 0; + + /* top wall */ + if ( st->maze[st->cur_sq_x][st->cur_sq_y] & DOOR_IN_TOP ) + goto rightwall; + if ( st->maze[st->cur_sq_x][st->cur_sq_y] & DOOR_OUT_TOP ) + goto rightwall; + if ( st->maze[st->cur_sq_x][st->cur_sq_y] & WALL_TOP ) + goto rightwall; + if ( st->maze[st->cur_sq_x][st->cur_sq_y - 1] & DOOR_IN_ANY ) { + st->maze[st->cur_sq_x][st->cur_sq_y] |= WALL_TOP; + st->maze[st->cur_sq_x][st->cur_sq_y - 1] |= WALL_BOTTOM; + draw_wall(st, st->cur_sq_x, st->cur_sq_y, 0, st->gc); + goto rightwall; + } + candidates[num_candidates++] = 0; + + rightwall: + /* right wall */ + if ( st->maze[st->cur_sq_x][st->cur_sq_y] & DOOR_IN_RIGHT ) + goto bottomwall; + if ( st->maze[st->cur_sq_x][st->cur_sq_y] & DOOR_OUT_RIGHT ) + goto bottomwall; + if ( st->maze[st->cur_sq_x][st->cur_sq_y] & WALL_RIGHT ) + goto bottomwall; + if ( st->maze[st->cur_sq_x + 1][st->cur_sq_y] & DOOR_IN_ANY ) { + st->maze[st->cur_sq_x][st->cur_sq_y] |= WALL_RIGHT; + st->maze[st->cur_sq_x + 1][st->cur_sq_y] |= WALL_LEFT; + draw_wall(st, st->cur_sq_x, st->cur_sq_y, 1, st->gc); + goto bottomwall; + } + candidates[num_candidates++] = 1; + + bottomwall: + /* bottom wall */ + if ( st->maze[st->cur_sq_x][st->cur_sq_y] & DOOR_IN_BOTTOM ) + goto leftwall; + if ( st->maze[st->cur_sq_x][st->cur_sq_y] & DOOR_OUT_BOTTOM ) + goto leftwall; + if ( st->maze[st->cur_sq_x][st->cur_sq_y] & WALL_BOTTOM ) + goto leftwall; + if ( st->maze[st->cur_sq_x][st->cur_sq_y + 1] & DOOR_IN_ANY ) { + st->maze[st->cur_sq_x][st->cur_sq_y] |= WALL_BOTTOM; + st->maze[st->cur_sq_x][st->cur_sq_y + 1] |= WALL_TOP; + draw_wall(st, st->cur_sq_x, st->cur_sq_y, 2, st->gc); + goto leftwall; + } + candidates[num_candidates++] = 2; + + leftwall: + /* left wall */ + if ( st->maze[st->cur_sq_x][st->cur_sq_y] & DOOR_IN_LEFT ) + goto donewall; + if ( st->maze[st->cur_sq_x][st->cur_sq_y] & DOOR_OUT_LEFT ) + goto donewall; + if ( st->maze[st->cur_sq_x][st->cur_sq_y] & WALL_LEFT ) + goto donewall; + if ( st->maze[st->cur_sq_x - 1][st->cur_sq_y] & DOOR_IN_ANY ) { + st->maze[st->cur_sq_x][st->cur_sq_y] |= WALL_LEFT; + st->maze[st->cur_sq_x - 1][st->cur_sq_y] |= WALL_RIGHT; + draw_wall(st, st->cur_sq_x, st->cur_sq_y, 3, st->gc); + goto donewall; + } + candidates[num_candidates++] = 3; + + donewall: + if (num_candidates == 0) + return ( -1 ); + if (num_candidates == 1) + return ( candidates[0] ); + return ( candidates[ get_random(num_candidates) ] ); + +} + + +static int +backup (struct state *st) /* back up a move */ +{ + st->sqnum--; + st->cur_sq_x = st->move_list[st->sqnum].x; + st->cur_sq_y = st->move_list[st->sqnum].y; + return ( st->sqnum ); +} + + +/**************************************************************************** + Drawing the maze + ****************************************************************************/ + +/* draws the maze outline, and the logo */ +static void +draw_maze_border (struct state *st) +{ + int i, j; + + for ( i=0; imaze_size_x; i++) { + if ( st->maze[i][0] & WALL_TOP ) { + XDrawLine(st->dpy, st->window, st->gc, + border_x + st->grid_width * i, + border_y, + border_x + st->grid_width * (i+1) - 1, + border_y); + } + if ((st->maze[i][st->maze_size_y - 1] & WALL_BOTTOM)) { + XDrawLine(st->dpy, st->window, st->gc, + border_x + st->grid_width * i, + border_y + st->grid_height * (st->maze_size_y) - 1, + border_x + st->grid_width * (i+1) - 1, + border_y + st->grid_height * (st->maze_size_y) - 1); + } + } + for ( j=0; jmaze_size_y; j++) { + if ( st->maze[st->maze_size_x - 1][j] & WALL_RIGHT ) { + XDrawLine(st->dpy, st->window, st->gc, + border_x + st->grid_width * st->maze_size_x - 1, + border_y + st->grid_height * j, + border_x + st->grid_width * st->maze_size_x - 1, + border_y + st->grid_height * (j+1) - 1); + } + if ( st->maze[0][j] & WALL_LEFT ) { + XDrawLine(st->dpy, st->window, st->gc, + border_x, + border_y + st->grid_height * j, + border_x, + border_y + st->grid_height * (j+1) - 1); + } + } + + if (st->logo_x != -1) + { + Window r; + int xx, yy; + unsigned int w, h, bbw, d; + + /* round up to grid size */ + int ww = ((st->logo_width / st->grid_width) + 1) * st->grid_width; + int hh = ((st->logo_height / st->grid_height) + 1) * st->grid_height; + int lx, ly; + + XGetGeometry (st->dpy, st->logo_map, &r, &xx, &yy, &w, &h, &bbw, &d); + + /* kludge: if the logo "hole" is around the same size as the logo, + don't center it (since the xscreensaver logo image is a little + off center... But do center it if the hole/gridsize is large. */ + if (ww < st->logo_width + 5) ww = w; + if (hh < st->logo_height + 5) hh = h; + + + lx = border_x + 3 + st->grid_width * st->logo_x + ((ww - w) / 2); + ly = border_y + 3 + st->grid_height * st->logo_y + ((hh - h) / 2); + + /* Fill the background of the logo box with the "unreachable" color */ + XFillRectangle (st->dpy, st->window, st->ugc, + border_x + 3 + st->grid_width * st->logo_x, + border_y + 3 + st->grid_height * st->logo_y, + ww, hh); + + XSetClipOrigin (st->dpy, st->logo_gc, lx, ly); + if (d == 1) + XCopyPlane (st->dpy, st->logo_map, st->window, st->logo_gc, + 0, 0, w, h, lx, ly, 1); + else + XCopyArea (st->dpy, st->logo_map, st->window, st->logo_gc, + 0, 0, w, h, lx, ly); + } + draw_solid_square (st, st->start_x, st->start_y, WALL_TOP >> st->start_dir, st->tgc); + draw_solid_square (st, st->end_x, st->end_y, WALL_TOP >> st->end_dir, st->tgc); +} + + +/* Mark the maze grid as having a wall at the given coordinate, + and draw that wall on the screen. */ +static void +build_wall(struct state *st, int i, int j, int dir) +{ + /* Draw it on the screen. */ + draw_wall(st, i, j, dir, st->gc); + /* Put it in the maze. */ + switch(dir) + { + case 0: + st->maze[i][j] |= WALL_TOP; + if(j>0) + st->maze[i][j-1] |= WALL_BOTTOM; + break; + case 1: + st->maze[i][j] |= WALL_RIGHT; + if(imaze_size_x-1) + st->maze[i+1][j] |= WALL_LEFT; + break; + case 2: + st->maze[i][j] |= WALL_BOTTOM; + if(jmaze_size_y-1) + st->maze[i][j+1] |= WALL_TOP; + break; + case 3: + st->maze[i][j] |= WALL_LEFT; + if(i>0) + st->maze[i-1][j] |= WALL_RIGHT; + break; + } +} + + +static void +draw_wall(struct state *st, int i, int j, int dir, GC with_gc) /* draw a single wall */ +{ + switch (dir) { + case 0: + XDrawLine(st->dpy, st->window, with_gc, + border_x + st->grid_width * i, + border_y + st->grid_height * j, + border_x + st->grid_width * (i+1), + border_y + st->grid_height * j); + break; + case 1: + XDrawLine(st->dpy, st->window, with_gc, + border_x + st->grid_width * (i+1), + border_y + st->grid_height * j, + border_x + st->grid_width * (i+1), + border_y + st->grid_height * (j+1)); + break; + case 2: + XDrawLine(st->dpy, st->window, with_gc, + border_x + st->grid_width * i, + border_y + st->grid_height * (j+1), + border_x + st->grid_width * (i+1), + border_y + st->grid_height * (j+1)); + break; + case 3: + XDrawLine(st->dpy, st->window, with_gc, + border_x + st->grid_width * i, + border_y + st->grid_height * j, + border_x + st->grid_width * i, + border_y + st->grid_height * (j+1)); + break; + } + + if(st->sync_p) { + /* too slow if we sync on every wall, so only sync about ten times + during the maze-creation process. + */ + st->sync_tick--; + if (st->sync_tick <= 0) { + XSync(st->dpy, False); + st->sync_tick = st->maze_size_x * st->maze_size_x / 10; + } + } +} + + +static void +draw_solid_square(struct state *st, + int i, int j, + int dir, GC with_gc) +{ + switch (dir) { + case WALL_TOP: + XFillRectangle(st->dpy, st->window, with_gc, + border_x + st->bw+(st->bw==0?1:0) + st->grid_width * i, + border_y - st->bw-(st->bw==0?1:0) + st->grid_height * j, + st->grid_width - (st->bw+st->bw+(st->bw==0?1:0)), st->grid_height); + break; + case WALL_RIGHT: + XFillRectangle(st->dpy, st->window, with_gc, + border_x + st->bw+(st->bw==0?1:0) + st->grid_width * i, + border_y + st->bw+(st->bw==0?1:0) + st->grid_height * j, + st->grid_width, st->grid_height - (st->bw+st->bw+(st->bw==0?1:0))); + break; + case WALL_BOTTOM: + XFillRectangle(st->dpy, st->window, with_gc, + border_x + st->bw+(st->bw==0?1:0) + st->grid_width * i, + border_y + st->bw+(st->bw==0?1:0) + st->grid_height * j, + st->grid_width - (st->bw+st->bw+(st->bw==0?1:0)), st->grid_height); + break; + case WALL_LEFT: + XFillRectangle(st->dpy, st->window, with_gc, + border_x - st->bw-(st->bw==0?1:0) + st->grid_width * i, + border_y + st->bw+(st->bw==0?1:0) + st->grid_height * j, + st->grid_width, st->grid_height - (st->bw+st->bw+(st->bw==0?1:0))); + break; + } +} + +/**************************************************************************** + Solving the maze + ****************************************************************************/ + +static int +longdeadend_p(struct state *st, int x1, int y1, int x2, int y2, int endwall) +{ + int dx = x2 - x1, dy = y2 - y1; + int sidewalls; + + sidewalls = endwall | (endwall >> 2 | endwall << 2); + sidewalls = ~sidewalls & WALL_ANY; + + while((st->maze[x2][y2] & WALL_ANY) == sidewalls) + { + if (x2 + dx < 0 || x2 + dx >= st->maze_size_x || + y2 + dy < 0 || y2 + dy >= st->maze_size_y) + break; + x2 += dx; + y2 += dy; + } + + if((st->maze[x2][y2] & WALL_ANY) == (sidewalls | endwall)) + { + endwall = (endwall >> 2 | endwall << 2) & WALL_ANY; + while(x1 != x2 || y1 != y2) + { + x1 += dx; + y1 += dy; + draw_solid_square(st, x1, y1, endwall, st->sgc); + st->maze[x1][y1] |= SOLVER_VISIT; + } + return 1; + } + else + return 0; +} + +/* Find all dead regions -- areas from which the goal cannot be reached -- + and mark them visited. */ +static void +find_dead_regions(struct state *st) +{ + int xx, yy, flipped; + + /* Find all not SOLVER_VISIT squares bordering NOT_DEAD squares + and mark them NOT_DEAD also. Repeat until no more such squares. */ + st->maze[st->start_x][st->start_y] |= NOT_DEAD; + + do + { + flipped = 0; + for(xx = 0; xx < st->maze_size_x; xx++) + for(yy = 0; yy < st->maze_size_y; yy++) + if(!(st->maze[xx][yy] & (SOLVER_VISIT | NOT_DEAD)) + && ( (xx && (st->maze[xx-1][yy] & NOT_DEAD)) + || (yy && (st->maze[xx][yy-1] & NOT_DEAD)))) + { + flipped = 1; + st->maze[xx][yy] |= NOT_DEAD; + } + for(xx = st->maze_size_x-1; xx >= 0; xx--) + for(yy = st->maze_size_y-1; yy >= 0; yy--) + if(!(st->maze[xx][yy] & (SOLVER_VISIT | NOT_DEAD)) + && ( (xx != st->maze_size_x-1 && (st->maze[xx+1][yy] & NOT_DEAD)) + || (yy != st->maze_size_y-1 && (st->maze[xx][yy+1] & NOT_DEAD)))) + { + flipped = 1; + st->maze[xx][yy] |= NOT_DEAD; + } + } + while(flipped); + + for (yy = 0; yy < st->maze_size_y; yy++) + for (xx = 0; xx < st->maze_size_x; xx++) + { + if (st->maze[xx][yy] & NOT_DEAD) + st->maze[xx][yy] &= ~NOT_DEAD; + else if (!(st->maze[xx][yy] & SOLVER_VISIT)) + { + st->maze[xx][yy] |= SOLVER_VISIT; + if((xx < st->logo_x || xx > st->logo_x + st->logo_width / st->grid_width) || + (yy < st->logo_y || yy > st->logo_y + st->logo_height / st->grid_height)) + { + /* if we are completely surrounded by walls, just draw the + inside part */ + if ((st->maze[xx][yy] & WALL_ANY) == WALL_ANY) + XFillRectangle(st->dpy, st->window, st->ugc, + border_x + st->bw + st->grid_width * xx, + border_y + st->bw + st->grid_height * yy, + st->grid_width - (st->bw+st->bw), st->grid_height - (st->bw+st->bw)); + else + { + if (! (st->maze[xx][yy] & WALL_LEFT)) + draw_solid_square(st, xx, yy, WALL_LEFT, st->ugc); + if (! (st->maze[xx][yy] & WALL_RIGHT)) + draw_solid_square(st, xx, yy, WALL_RIGHT, st->ugc); + if (! (st->maze[xx][yy] & WALL_TOP)) + draw_solid_square(st, xx, yy, WALL_TOP, st->ugc); + if (! (st->maze[xx][yy] & WALL_BOTTOM)) + draw_solid_square(st, xx, yy, WALL_BOTTOM, st->ugc); + } + } + } + } +} + +/* solve the maze by one more tick */ +static int +solve_maze (struct state *st) +{ + struct solve_state *ss = st->solve_state; + if (!ss) + ss = st->solve_state = (struct solve_state *) calloc (1, sizeof(*ss)); + + if (!ss->running) { + /* plug up the surrounding wall */ + st->maze[st->end_x][st->end_y] |= (WALL_TOP >> st->end_dir); + + /* initialize search path */ + ss->i = 0; + st->path[ss->i].x = st->end_x; + st->path[ss->i].y = st->end_y; + st->path[ss->i].dir = 0; + st->maze[st->end_x][st->end_y] |= SOLVER_VISIT; + + ss->running = 1; + } + + /* do it */ + /* while (1) */ + { + int dir, from, ways; + + if ( st->maze[st->path[ss->i].x][st->path[ss->i].y] & START_SQUARE ) + { + ss->running = 0; + return 1; + } + + if(!st->path[ss->i].dir) + { + ways = 0; + /* First visit this square. Which adjacent squares are open? */ + for(dir = WALL_TOP; dir & WALL_ANY; dir >>= 1) + { + if(st->maze[st->path[ss->i].x][st->path[ss->i].y] & dir) + continue; + + ss->y = st->path[ss->i].y - !!(dir & WALL_TOP) + !!(dir & WALL_BOTTOM); + ss->x = st->path[ss->i].x + !!(dir & WALL_RIGHT) - !!(dir & WALL_LEFT); + + if(st->maze[ss->x][ss->y] & SOLVER_VISIT) + continue; + + from = (dir << 2 & WALL_ANY) | (dir >> 2 & WALL_ANY); + /* don't enter obvious dead ends */ + if(((st->maze[ss->x][ss->y] & WALL_ANY) | from) != WALL_ANY) + { + if(!longdeadend_p(st, st->path[ss->i].x, st->path[ss->i].y, ss->x, ss->y, dir)) + ways |= dir; + } + else + { + draw_solid_square(st, ss->x, ss->y, from, st->sgc); + st->maze[ss->x][ss->y] |= SOLVER_VISIT; + } + } + } + else + ways = st->path[ss->i].ways; + /* ways now has a bitmask of open paths. */ + + if(!ways) + goto backtrack; + + if (!st->ignorant_p) + { + ss->x = st->path[ss->i].x - st->start_x; + ss->y = st->path[ss->i].y - st->start_y; + /* choice one */ + if(abs(ss->y) <= abs(ss->x)) + dir = (ss->x > 0) ? WALL_LEFT : WALL_RIGHT; + else + dir = (ss->y > 0) ? WALL_TOP : WALL_BOTTOM; + + if(dir & ways) + goto found; + + /* choice two */ + switch(dir) + { + case WALL_LEFT: + case WALL_RIGHT: + dir = (ss->y > 0) ? WALL_TOP : WALL_BOTTOM; break; + case WALL_TOP: + case WALL_BOTTOM: + dir = (ss->x > 0) ? WALL_LEFT : WALL_RIGHT; + } + + if(dir & ways) + goto found; + + /* choice three */ + + dir = (dir << 2 & WALL_ANY) | (dir >> 2 & WALL_ANY); + if(dir & ways) + goto found; + + /* choice four */ + dir = ways; + if(!dir) + goto backtrack; + + found: ; + } + else + { + if(ways&WALL_TOP) + dir = WALL_TOP; + else if(ways&WALL_LEFT) + dir = WALL_LEFT; + else if(ways&WALL_BOTTOM) + dir = WALL_BOTTOM; + else if(ways&WALL_RIGHT) + dir = WALL_RIGHT; + else + goto backtrack; + } + ss->bt = 0; + ways &= ~dir; /* tried this one */ + + ss->y = st->path[ss->i].y - !!(dir & WALL_TOP) + !!(dir & WALL_BOTTOM); + ss->x = st->path[ss->i].x + !!(dir & WALL_RIGHT) - !!(dir & WALL_LEFT); + + /* advance in direction dir */ + st->path[ss->i].dir = dir; + st->path[ss->i].ways = ways; + draw_solid_square(st, st->path[ss->i].x, st->path[ss->i].y, dir, st->tgc); + + ss->i++; + st->path[ss->i].dir = 0; + st->path[ss->i].ways = 0; + st->path[ss->i].x = ss->x; + st->path[ss->i].y = ss->y; + st->maze[ss->x][ss->y] |= SOLVER_VISIT; + return 0; + /* continue; */ + + backtrack: + if(ss->i == 0) + { + printf("Unsolvable maze.\n"); + ss->running = 0; + return 1; + } + + if(!ss->bt && !st->ignorant_p) + find_dead_regions(st); + ss->bt = 1; + from = st->path[ss->i-1].dir; + from = (from << 2 & WALL_ANY) | (from >> 2 & WALL_ANY); + + draw_solid_square(st, st->path[ss->i].x, st->path[ss->i].y, from, st->cgc); + ss->i--; + } + + return 0; +} + + +/**************************************************************************** + XScreenSaver boilerplate: resources, command line options, and main loop. + ****************************************************************************/ + +static const char *maze_defaults[] = { + ".background: black", + ".foreground: white", + "*fpsSolid: true", + "*gridSize: 0", + "*generator: -1", + "*maxLength: 5", + "*ignorant: False", + + "*solveDelay: 10000", + "*preDelay: 2000000", + "*postDelay: 4000000", + + "*liveColor: #00FF00", + "*deadColor: #880000", + "*skipColor: #8B5A00", + "*surroundColor: #220055", + + 0 +}; + +static XrmOptionDescRec maze_options[] = { + { "-ignorant", ".ignorant", XrmoptionNoArg, "True" }, + { "-no-ignorant", ".ignorant", XrmoptionNoArg, "False" }, + { "-grid-size", ".gridSize", XrmoptionSepArg, 0 }, + { "-solve-delay", ".solveDelay", XrmoptionSepArg, 0 }, + { "-pre-delay", ".preDelay", XrmoptionSepArg, 0 }, + { "-post-delay", ".postDelay", XrmoptionSepArg, 0 }, + { "-bg-color", ".background", XrmoptionSepArg, 0 }, + { "-fg-color", ".foreground", XrmoptionSepArg, 0 }, + { "-live-color", ".liveColor", XrmoptionSepArg, 0 }, + { "-dead-color", ".deadColor", XrmoptionSepArg, 0 }, + { "-skip-color", ".skipColor", XrmoptionSepArg, 0 }, + { "-surround-color", ".surroundColor",XrmoptionSepArg, 0 }, + { "-generator", ".generator", XrmoptionSepArg, 0 }, + { "-max-length", ".maxLength", XrmoptionSepArg, 0 }, + { 0, 0, 0, 0 } +}; + +static int generator = 0; + +static void * +maze_init (Display *dpy_arg, Window window_arg) +{ + struct state *st = (struct state *) calloc (1, sizeof(*st)); + int size; + XWindowAttributes xgwa; + unsigned long bg, fg, pfg, pbg, sfg, ufg; + + st->dpy = dpy_arg; + st->window = window_arg; + + st->stop = 0; + st->state = 1; + st->restart = 1; + + st->ifrandom = 0; + st->ifinit = 1; + + size = get_integer_resource (st->dpy, "gridSize", "Dimension"); + st->solve_delay = get_integer_resource (st->dpy, "solveDelay", "Integer"); + st->pre_solve_delay = get_integer_resource (st->dpy, "preDelay", "Integer"); + st->post_solve_delay = get_integer_resource (st->dpy, "postDelay", "Integer"); + generator = get_integer_resource(st->dpy, "generator", "Integer"); + st->max_length = get_integer_resource(st->dpy, "maxLength", "Integer"); + st->ignorant_p = get_boolean_resource(st->dpy, "ignorant", "Boolean"); + + if (get_boolean_resource (st->dpy, "doFPS", "DoFPS")) + { + /* Just guess, rather than loading and measuring the "fpsFont"... */ + st->fps_width = 210; + st->fps_height = 62; + } + + if (!size) st->ifrandom = 1; + + if (size < 2) size = 7 + (random () % 30); + st->grid_width = st->grid_height = size; + st->bw = (size > 6 ? 3 : (size-1)/2); + + XGetWindowAttributes (st->dpy, st->window, &xgwa); + + st->x = 0; + st->y = 0; + + set_maze_sizes (st, xgwa.width, xgwa.height); + + st->gc = XCreateGC(st->dpy, st->window, 0, 0); + st->cgc = XCreateGC(st->dpy, st->window, 0, 0); + st->tgc = XCreateGC(st->dpy, st->window, 0, 0); + st->sgc = XCreateGC(st->dpy, st->window, 0, 0); + st->ugc = XCreateGC(st->dpy, st->window, 0, 0); + st->logo_gc = XCreateGC(st->dpy, st->window, 0, 0); + st->erase_gc = XCreateGC(st->dpy, st->window, 0, 0); + + bg = get_pixel_resource (st->dpy, xgwa.colormap, "background","Background"); + fg = get_pixel_resource (st->dpy, xgwa.colormap, "foreground","Foreground"); + pfg = get_pixel_resource (st->dpy, xgwa.colormap, "liveColor", "Foreground"); + pbg = get_pixel_resource (st->dpy, xgwa.colormap, "deadColor", "Foreground"); + sfg = get_pixel_resource (st->dpy, xgwa.colormap, "skipColor", "Foreground"); + ufg = get_pixel_resource (st->dpy, xgwa.colormap, "surroundColor", "Foreground"); + + XSetForeground (st->dpy, st->gc, fg); + XSetBackground (st->dpy, st->gc, bg); + XSetForeground (st->dpy, st->cgc, pbg); + XSetBackground (st->dpy, st->cgc, bg); + XSetForeground (st->dpy, st->tgc, pfg); + XSetBackground (st->dpy, st->tgc, bg); + XSetForeground (st->dpy, st->sgc, sfg); + XSetBackground (st->dpy, st->sgc, bg); + XSetForeground (st->dpy, st->ugc, ufg); + XSetBackground (st->dpy, st->ugc, bg); + XSetForeground (st->dpy, st->logo_gc, fg); + XSetBackground (st->dpy, st->logo_gc, bg); + XSetForeground (st->dpy, st->erase_gc, bg); + XSetBackground (st->dpy, st->erase_gc, bg); + + { + Window r; + int x, y; + unsigned int w, h, bbw, d; + unsigned long *pixels; + int npixels; + Pixmap logo_mask = 0; + st->logo_map = xscreensaver_logo (xgwa.screen, xgwa.visual, st->window, + xgwa.colormap, bg, + &pixels, &npixels, &logo_mask, + xgwa.width > 800 || xgwa.height > 800); + if (logo_mask) { + XSetClipMask (st->dpy, st->logo_gc, logo_mask); + XFreePixmap (st->dpy, logo_mask); + } + if (pixels) free (pixels); + XGetGeometry (st->dpy, st->logo_map, &r, &x, &y, &w, &h, &bbw, &d); + st->logo_width = w; + st->logo_height = h; + } + + + st->restart = 0; + st->sync_p = 1; + + return st; +} + + +static void +maze_reshape (Display *dpy, Window window, void *closure, + unsigned int w, unsigned int h) +{ + struct state *st = (struct state *) closure; + st->restart = 1; +} + + +static unsigned long +maze_draw (Display *dpy, Window window, void *closure) +{ + struct state *st = (struct state *) closure; + int this_delay = st->solve_delay; + + if (st->eraser || st->erase_window) + { + st->erase_window = 0; + st->eraser = erase_window (st->dpy, st->window, st->eraser); + if (st->eraser) + this_delay = 10000; + else { + this_delay = 1000000; + if (this_delay > st->pre_solve_delay) + this_delay = st->pre_solve_delay; + } + goto END; + } + + if (st->restart || st->stop) goto pop; + switch (st->state) { + case 1: + initialize_maze(st); + if (st->ifrandom && st->ifinit) + { + int size; + size = 7 + (random () % 30); + st->grid_width = st->grid_height = size; + st->bw = (size > 6 ? 3 : (size-1)/2); + st->ifinit = 0; + st->restart = 1; + } + break; + case 2: + XClearWindow(st->dpy, st->window); + draw_maze_border(st); + break; + case 3: + st->this_gen = generator; + if(st->this_gen<0 || st->this_gen>2) + st->this_gen = random()%3; + + switch(st->this_gen) + { + case 0: + create_maze(st); + break; + case 1: + alt_create_maze(st); + break; + case 2: + set_create_maze(st); + break; + } + break; + case 4: + this_delay = st->pre_solve_delay; + break; + case 5: + if (! solve_maze(st)) + --st->state; /* stay in state 5 */ + break; + case 6: + st->erase_window = 1; + this_delay = st->post_solve_delay; + st->state = 0 ; + st->ifinit = 1; + break; + default: + abort (); + } + ++st->state; + pop: + if (st->restart) + { + XWindowAttributes xgwa; + int size; + + st->restart = 0; + st->stop = 0; + st->state = 1; + + st->sync_p = ((random() % 4) != 0); + + size = get_integer_resource (st->dpy, "gridSize", "Dimension"); + if (size < 2) size = 7 + (random () % 30); + st->grid_width = st->grid_height = size; + st->bw = (size > 6 ? 3 : (size-1)/2); + + XGetWindowAttributes (st->dpy, st->window, &xgwa); + set_maze_sizes (st, xgwa.width, xgwa.height); + } + + END: + return this_delay; +} + + +static Bool +maze_event (Display *dpy, Window window, void *closure, XEvent *event) +{ + struct state *st = (struct state *) closure; + switch (event->type) + { + case ButtonPress: + switch (event->xbutton.button) + { + case 2: + st->stop = !st->stop ; + if (st->state == 5) st->state = 4 ; + else { + st->restart = 1; + st->stop = 0; + } + return True; + + default: + st->restart = 1 ; + st->stop = 0 ; + return True; + } + break; + + case Expose: + st->restart = 1; + break; + + default: + break; + } + return False; +} + + +static void +maze_free (Display *dpy, Window window, void *closure) +{ + struct state *st = (struct state *) closure; + free (st); +} + +XSCREENSAVER_MODULE ("Maze", maze) diff --git a/hacks/maze.man b/hacks/maze.man new file mode 100644 index 00000000..c827da86 --- /dev/null +++ b/hacks/maze.man @@ -0,0 +1,148 @@ +.TH XScreenSaver 1 "7-mar-93" "X Version 11" +.SH NAME +maze \- an automated X11 demo repeatedly creating and solving a random maze +.SH SYNOPSIS +.B maze +[\-display \fIhost:display.screen\fP] [\-foreground \fIcolor\fP] [\-background \fIcolor\fP] [\-window] [\-root] [\-install] [\-visual \fIvisual\fP] [\-grid\-size \fIpixels\fP] [\-live\-color \fIcolor\fP] [\-dead\-color \fIcolor\fP] [\-solve\-delay \fIusecs\fP] [\-pre\-delay \fIusecs\fP] [\-post\-delay \fIusecs\fP] [\-generator \fIinteger\fP] [\-max\-length \fIinteger\fP] +[\-fps] +.SH DESCRIPTION +The \fImaze\fP program creates a "random" maze and then solves it with +graphical feedback. +.SH OPTIONS +.I maze +accepts the following options: +.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 \-install +Install a private colormap for the window. +.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 \-grid\-size \fIpixels\fP +The size of each block of the maze, in pixels; default is 0, meaning +pick a random grid size. Minimum meaningful value is 2. +.TP 8 +.B \-live\-color \fIcolor\fP +The color of the path. +.TP 8 +.B \-dead\-color \fIcolor\fP +The color of the failed path (it is also stippled with a 50% pattern.) +.TP 8 +.B \-skip\-color \fIcolor\fP +The maze solver will choose to not go down a path if it can "see" (in a +straight line) that it is a dead end. This is the color to use for paths +that are skipped for this reason. +.TP 8 +.B \-surround\-color \fIcolor\fP +If the maze solver ever completely encloses an area within the maze, then +it knows that the exit is not in there (and in fact the interior of that +area might not even be reachable.) It will mark out those cells using this +color. +.TP 8 +.B \-solve\-delay \fIinteger\fP +Delay (in microseconds) between each step of the solution path. +Default 5000, or about 1/200th second. +.TP 8 +.B \-pre\-delay \fIinteger\fP +Delay (in microseconds) between generating a maze and starting to solve it. +Default 2000000 (2 seconds.) +.TP 8 +.B \-post\-delay \fIinteger\fP +Delay (in microseconds) after solving a maze and before generating a new one. +Default 4000000 (4 seconds.) +.TP 8 +.B \-generator \fInum\fP +Sets the algorithm that will be used to generate the mazes. The +default is \-1, which randomly selects an algorithm for each maze that +is generated. Generator 0 is the original one, and works by walking +around randomly until we hit a place we've been before, then +backtracking and trying a new direction somewhere. Generator 1 picks a +random spot in the maze, then draws a straight wall from that spot in +a random direction until it hits another wall (and continues until the +maze is complete). Generator 2 is based on sets. Initially all cells +are in different sets. Then two neighboring cells are chosen and if +they are in different sets, their sets are joined. If they were in the +same set, a wall is built between them. This continues until the maze is +complete. + +All generators generate mazes with a certain 'characteristic'. See if you +can spot them! + +The three algorithms are essentially Kruskal, Prim, and a depth-first +recursive backtracker. +.TP 8 +.B \-max\-length \fInum\fP +Controls the maximum length of walls drawn in one go by generator 1. +.PP +Clicking the mouse in the maze window controls it. +.TP 16 +.B "LeftButton +Clears the window and restarts maze. +.TP 16 +.B MiddleButton +Pause or unpause the program. +.TP 16 +.B RightButton +Exit. +.TP 8 +.B \-fps +Display the current frame rate and CPU load. +.SH BUGS +Expose events force a restart of maze. + +Mouse actions are based on "raw" values (Button1, Button2 and Button3) +instead of using the pointer map. +.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 +.PP +Copyright \(co 1988 by Sun Microsystems, Inc. Mountain View, CA. +.PP +All Rights Reserved +.PP +Permission to use, copy, modify, and distribute this software and its +documentation for any purpose and without fee is hereby granted, provided that +the above copyright notice appear in all copies and that both that copyright +notice and this permission notice appear in supporting documentation, and that +the names of Sun or MIT not be used in advertising or publicity pertaining to +distribution of the software without specific prior written permission. Sun +and M.I.T. make no representations about the suitability of this software for +any purpose. It is provided "as is" without any express or implied warranty. +.PP +SUN DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. IN +NO EVENT SHALL SUN BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL +DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, +WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING +OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +.SH AUTHOR(s) +.nf +Zack Weinberg [ Smarter maze-solver ] zack@rabi.phys.columbia.edu +Johannes Keukelaar [ Generators 1 and 2 ] johannes@nada.kth.se + Royal Institute of Technology, Stockholm, Sweden +Jim Randell [ XScreenSaver version ] jmr@mddjmr.fc.hp.com + HPLabs, Bristol +Richard Hess [ X11 extensions ] {...}!uunet!cimshop!rhess + Consilium, Mountain View, CA +Dave Lemke [ X11 version ] lemke@sun.COM + Sun MicroSystems, Mountain View, CA +Martin Weiss [ SunView version ] + Sun MicroSystems, Mountain View, CA +.fi diff --git a/hacks/memscroller.c b/hacks/memscroller.c new file mode 100644 index 00000000..afaed3c9 --- /dev/null +++ b/hacks/memscroller.c @@ -0,0 +1,653 @@ +/* xscreensaver, Copyright (c) 2002-2012 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. + * + * Memscroller -- scrolls a dump of its own RAM across the screen. + */ + +#include "screenhack.h" +#include + +#ifdef HAVE_XSHM_EXTENSION +#include "xshm.h" +#endif + +#undef countof +#define countof(x) (sizeof(x)/sizeof(*(x))) + +#ifndef USE_IPHONE +# define READ_FILES +#endif + +typedef struct { + int which; + XRectangle rect; + XImage *image; + int rez; + int speed; + int scroll_tick; + unsigned int value; + unsigned char *data; + int count_zero; +} scroller; + +typedef struct { + Display *dpy; + Window window; + XWindowAttributes xgwa; + GC draw_gc, erase_gc, text_gc; + XFontStruct *fonts[6]; + int border; + + enum { SEED_RAM, SEED_RANDOM, SEED_FILE } seed_mode; + enum { DRAW_COLOR, DRAW_MONO } draw_mode; + + char *filename; + FILE *in; + + int nscrollers; + scroller *scrollers; + +# ifdef HAVE_XSHM_EXTENSION + Bool shm_p; + XShmSegmentInfo shm_info; +# endif + + int delay; + +} state; + + +static void reshape_memscroller (state *st); + + +static void * +memscroller_init (Display *dpy, Window window) +{ + int i; + XGCValues gcv; + state *st = (state *) calloc (1, sizeof (*st)); + char *s; + st->dpy = dpy; + st->window = window; + st->delay = get_integer_resource (dpy, "delay", "Integer"); + + XGetWindowAttributes (st->dpy, st->window, &st->xgwa); + + /* Fill up the colormap with random colors. + We don't actually use these explicitly, but in 8-bit mode, + they will be used implicitly by the random image bits. */ + { + int ncolors = 255; + XColor colors[256]; + make_random_colormap (st->dpy, st->xgwa.visual, st->xgwa.colormap, + colors, &ncolors, True, True, 0, False); + } + + st->border = get_integer_resource (dpy, "borderSize", "BorderSize"); + + { + int i; + int nfonts = countof (st->fonts); + for (i = nfonts-1; i >= 0; i--) + { + char *fontname; + char res[20]; + sprintf (res, "font%d", i+1); + fontname = get_string_resource (dpy, res, "Font"); + /* Each resource can be a comma-separated list of font names. + We use the first one that exists. */ + if (fontname && *fontname) + { + char *f2 = strdup(fontname); + char *f, *token = f2; + while ((f = strtok(token, ",")) && !st->fonts[i]) + { + token = 0; + while (*f == ' ' || *f == '\t') f++; + st->fonts[i] = XLoadQueryFont (dpy, f); + } + free (f2); + if (!st->fonts[i] && i < nfonts-1) + { + fprintf (stderr, "%s: unable to load font: \"%s\"\n", + progname, fontname); + st->fonts[i] = st->fonts[i+1]; + } + } + } + + if (!st->fonts[0]) + st->fonts[0] = XLoadQueryFont (dpy, "fixed"); + + if (!st->fonts[0]) + { + fprintf (stderr, "%s: unable to load any fonts!", progname); + exit (1); + } + } + + gcv.line_width = st->border; + + gcv.background = get_pixel_resource(st->dpy, st->xgwa.colormap, + "background", "Background"); + gcv.foreground = get_pixel_resource(st->dpy, st->xgwa.colormap, + "textColor", "Foreground"); + st->text_gc = XCreateGC (st->dpy, st->window, + GCForeground|GCBackground, &gcv); + + gcv.foreground = get_pixel_resource(st->dpy, st->xgwa.colormap, + "foreground", "Foreground"); + st->draw_gc = XCreateGC (st->dpy, st->window, + GCForeground|GCBackground|GCLineWidth, + &gcv); + gcv.foreground = gcv.background; + st->erase_gc = XCreateGC (st->dpy, st->window, + GCForeground|GCBackground, &gcv); + + + s = get_string_resource (dpy, "drawMode", "DrawMode"); + if (!s || !*s || !strcasecmp (s, "color")) + st->draw_mode = DRAW_COLOR; + else if (!strcasecmp (s, "mono")) + st->draw_mode = DRAW_MONO; + else + { + fprintf (stderr, "%s: drawMode must be 'mono' or 'color', not '%s'\n", + progname, s); + exit (1); + } + if (s) free (s); + s = 0; + + +# ifdef READ_FILES + st->filename = get_string_resource (dpy, "filename", "Filename"); +# endif + + if (!st->filename || + !*st->filename || + !strcasecmp (st->filename, "(ram)") || + !strcasecmp (st->filename, "(mem)") || + !strcasecmp (st->filename, "(memory)")) + st->seed_mode = SEED_RAM; +# ifdef READ_FILES + else if (st->filename && + (!strcasecmp (st->filename, "(rand)") || + !strcasecmp (st->filename, "(random)"))) + st->seed_mode = SEED_RANDOM; + else + st->seed_mode = SEED_FILE; +# else + st->seed_mode = SEED_RANDOM; +# endif + + st->nscrollers = 3; + st->scrollers = (scroller *) calloc (st->nscrollers, sizeof(scroller)); + + for (i = 0; i < st->nscrollers; i++) + { + scroller *sc = &st->scrollers[i]; + int max_height = 4096; + + sc->which = i; + sc->speed = i+1; + + sc->image = 0; +# ifdef HAVE_XSHM_EXTENSION + st->shm_p = get_boolean_resource (dpy, "useSHM", "Boolean"); + if (st->shm_p) + { + sc->image = create_xshm_image (st->dpy, st->xgwa.visual, + st->xgwa.depth, + ZPixmap, 0, &st->shm_info, + 1, max_height); + if (! sc->image) + st->shm_p = False; + } +# endif /* HAVE_XSHM_EXTENSION */ + + if (!sc->image) + sc->image = XCreateImage (st->dpy, st->xgwa.visual, st->xgwa.depth, + ZPixmap, 0, 0, 1, max_height, 8, 0); + + if (sc->image && !sc->image->data) + sc->image->data = (char *) + malloc (sc->image->bytes_per_line * sc->image->height + 1); + + if (!sc->image || !sc->image->data) + { + fprintf (stderr, "%s: out of memory (allocating 1x%d image)\n", + progname, sc->image->height); + exit (1); + } + } + + reshape_memscroller (st); + return st; +} + + +static void +reshape_memscroller (state *st) +{ + int i; + + XGetWindowAttributes (st->dpy, st->window, &st->xgwa); + + for (i = 0; i < st->nscrollers; i++) + { + scroller *sc = &st->scrollers[i]; + + if (i == 0) + { + sc->rez = 6; /* #### */ + + sc->rect.width = (((int) (st->xgwa.width * 0.8) + / sc->rez) * sc->rez); + sc->rect.height = (((int) (st->xgwa.height * 0.3) + / sc->rez) * sc->rez); + + sc->rect.x = (st->xgwa.width - sc->rect.width) / 2; + sc->rect.y = (st->xgwa.height - sc->rect.height) / 2; + } + else + { + scroller *sc0 = &st->scrollers[i-1]; + sc->rez = sc0->rez * 1.8; + + sc->rect.x = sc0->rect.x; + sc->rect.y = (sc0->rect.y + sc0->rect.height + st->border + + (st->border + 2) * 7); + sc->rect.width = sc0->rect.width; + sc->rect.height = (((int) (st->xgwa.height * 0.1) + / sc->rez) * sc->rez); + } + + XDrawRectangle (st->dpy, st->window, st->draw_gc, + sc->rect.x - st->border*2, + sc->rect.y - st->border*2, + sc->rect.width + st->border*4, + sc->rect.height + st->border*4); + } +} + + + +# ifdef READ_FILES +static void +open_file (state *st) +{ + if (st->in) + { + fclose (st->in); + st->in = 0; + } + + st->in = fopen (st->filename, "r"); + if (!st->in) + { + char buf[1024]; + sprintf (buf, "%s: %s", progname, st->filename); + perror (buf); + exit (1); + } +} +#endif + + +static unsigned int +more_bits (state *st, scroller *sc) +{ + static unsigned char *lomem = 0; + static unsigned char *himem = 0; + unsigned char r, g, b; + + /* vv: Each incoming byte rolls through all 4 bytes of this (it is sc->value) + This is the number displayed at the top. + pv: the pixel color value. incoming bytes land in R,G,B, or maybe just G. + */ + unsigned int vv, pv; + + unsigned int rmsk = st->scrollers[0].image->red_mask; + unsigned int gmsk = st->scrollers[0].image->green_mask; + unsigned int bmsk = st->scrollers[0].image->blue_mask; + unsigned int amsk = ~(rmsk | gmsk | bmsk); + + vv = sc->value; + + /* Pack RGB into a pixel according to the XImage component masks; + set the remaining bits to 1 for the benefit of HAVE_COCOA alpha. + */ +# undef PACK +# define PACK() ((((r << 24) | (r << 16) | (r << 8) | r) & rmsk) | \ + (((g << 24) | (g << 16) | (g << 8) | g) & gmsk) | \ + (((b << 24) | (b << 16) | (b << 8) | b) & bmsk) | \ + amsk) + + switch (st->seed_mode) + { + case SEED_RAM: + if (himem == 0) + { + lomem = (unsigned char *) progname; /* not first malloc, but early */ + himem = (unsigned char *) /* not last malloc, but late */ + st->scrollers[st->nscrollers-1].image->data; + } + + if (sc->data < lomem) + sc->data = lomem; + +# ifdef HAVE_SBRK /* re-get it each time through */ + /* "The brk and sbrk functions are historical curiosities left over + from earlier days before the advent of virtual memory management." + -- sbrk(2) man page on MacOS + */ + himem = ((unsigned char *) sbrk(0)) - (2 * sizeof(void *)); +# endif + + if (!lomem || !himem) + { + /* bad craziness! give up! */ + st->seed_mode = SEED_RANDOM; + return 0; + } + + /* I don't understand what's going on there, but on MacOS X, we're + getting insane values for lomem and himem (both Xlib and HAVE_COCOA). + Does malloc() draw from more than one heap? */ + if ((unsigned long) himem - (unsigned long) lomem > 0x0FFFFFFF) { +# if 0 + fprintf (stderr, "%s: wonky: 0x%08x - 0x%08x = 0x%08x\n", progname, + (unsigned int) himem, (unsigned int) lomem, + (unsigned int) himem - (unsigned int) lomem); +# endif + himem = lomem + 0xFFFF; + } + + if (lomem >= himem) abort(); + + RETRY: + if (sc->data >= himem) + sc->data = lomem; + + switch (st->draw_mode) + { + case DRAW_COLOR: + r = *sc->data++; + g = *sc->data++; + b = *sc->data++; + vv = (vv << 24) | (r << 16) | (g << 8) | b; + break; + case DRAW_MONO: + r = 0; + g = *sc->data++; + b = 0; + vv = (vv << 8) | g; + break; + default: + abort(); + } + + pv = PACK(); + + /* avoid having many seconds of blackness: truncate zeros at 24K. + */ + if (vv == 0) + sc->count_zero++; + else + sc->count_zero = 0; + if (sc->count_zero > 1024 * (st->draw_mode == DRAW_COLOR ? 24 : 8)) + goto RETRY; + + break; + + case SEED_RANDOM: + vv = random(); + switch (st->draw_mode) + { + case DRAW_COLOR: + r = (vv >> 16) & 0xFF; + g = (vv >> 8) & 0xFF; + b = (vv ) & 0xFF; + break; + case DRAW_MONO: + r = 0; + g = vv & 0xFF; + b = 0; + break; + default: + abort(); + } + pv = PACK(); + break; + +# ifdef READ_FILES + case SEED_FILE: + { + int i; + + /* this one returns only bytes from the file */ +# define GETC(V) \ + do { \ + i = fgetc (st->in); \ + } while (i == EOF \ + ? (open_file (st), 1) \ + : 0); \ + V = i + + /* this one returns a null at EOF -- else we hang on zero-length files */ +# undef GETC +# define GETC(V) \ + i = fgetc (st->in); \ + if (i == EOF) { i = 0; open_file (st); } \ + V = i + + if (!st->in) + open_file (st); + + switch (st->draw_mode) + { + case DRAW_COLOR: + GETC(r); + GETC(g); + GETC(b); + vv = (vv << 24) | (r << 16) | (g << 8) | b; + break; + case DRAW_MONO: + r = 0; + GETC(g); + b = 0; + vv = (vv << 8) | g; + break; + default: + abort(); + } +# undef GETC + pv = PACK(); + } + break; +# endif /* READ_FILES */ + + default: + abort(); + } + +# undef PACK + + sc->value = vv; + return pv; +} + + +static void +draw_string (state *st) +{ + char buf[40]; + int direction, ascent, descent; + int bot = st->scrollers[0].rect.y; + const char *fmt = "%08X"; + int i; + + /* Draw the first font that fits. + */ + for (i = 0; i < countof (st->fonts); i++) + { + XCharStruct overall; + int x, y, w, h; + + if (! st->fonts[i]) continue; + + sprintf (buf, fmt, 0); + XTextExtents (st->fonts[i], buf, strlen(buf), + &direction, &ascent, &descent, &overall); + sprintf (buf, "%08X", st->scrollers[0].value); + + w = overall.width; + h = ascent + descent + 1; + x = (st->xgwa.width - w) / 2; + y = (bot - h) / 2; + + if (y + h + 10 <= bot && x > -10) + { + XSetFont (st->dpy, st->text_gc, st->fonts[i]->fid); + XFillRectangle (st->dpy, st->window, st->erase_gc, + x-w, y, w*3, h); + XDrawString (st->dpy, st->window, st->text_gc, + x, y + ascent, buf, strlen(buf)); + break; + } + } +} + + +static unsigned long +memscroller_draw (Display *dpy, Window window, void *closure) +{ + state *st = (state *) closure; + int i; + draw_string (st); + + for (i = 0; i < st->nscrollers; i++) + { + scroller *sc = &st->scrollers[i]; + int j; + + XCopyArea (st->dpy, st->window, st->window, st->draw_gc, + sc->rect.x + sc->speed, sc->rect.y, + sc->rect.width - sc->speed, sc->rect.height, + sc->rect.x, sc->rect.y); + + if (sc->scroll_tick == 0) + { + int top = ((sc->image->bytes_per_line * sc->rect.height) / + (4 * sc->rez)); + unsigned int *out = (unsigned int *) sc->image->data; + for (j = 0; j < top; j++) + { + unsigned int v = more_bits(st, sc); + int k; + for (k = 0; k < sc->rez; k++) + *out++ = v; + } + } + + sc->scroll_tick++; + if (sc->scroll_tick * sc->speed >= sc->rez) + sc->scroll_tick = 0; + + for (j = 0; j < sc->speed; j++) + { +# ifdef HAVE_XSHM_EXTENSION + if (st->shm_p) + XShmPutImage (st->dpy, st->window, st->draw_gc, sc->image, + 0, 0, + sc->rect.x + sc->rect.width - sc->image->width - j, + sc->rect.y, + sc->rect.width, sc->rect.height, + False); + else +# endif /* HAVE_XSHM_EXTENSION */ + XPutImage (st->dpy, st->window, st->draw_gc, sc->image, + 0, 0, + sc->rect.x + sc->rect.width - sc->image->width - j, + sc->rect.y, + sc->rect.width, sc->rect.height); + } + } + + return st->delay; +} + + +static void +memscroller_reshape (Display *dpy, Window window, void *closure, + unsigned int w, unsigned int h) +{ + state *st = (state *) closure; + XClearWindow (st->dpy, st->window); + reshape_memscroller (st); +} + +static Bool +memscroller_event (Display *dpy, Window window, void *closure, XEvent *event) +{ + return False; +} + + +static void +memscroller_free (Display *dpy, Window window, void *closure) +{ +} + + +static const char *memscroller_defaults [] = { + ".background: black", + "*drawMode: color", + "*fpsSolid: true", + "*fpsTop: true", + "*filename: (RAM)", + ".textColor: #00FF00", + ".foreground: #00FF00", + "*borderSize: 2", + +#if defined(HAVE_COCOA) && !defined(USE_IPHONE) + ".font1: OCR A Std 192, Lucida Console 192", + ".font2: OCR A Std 144, Lucida Console 144", + ".font3: OCR A Std 128, Lucida Console 128", + ".font4: OCR A Std 96, Lucida Console 96", + ".font5: OCR A Std 48, Lucida Console 48", + ".font6: OCR A Std 24, Lucida Console 24", +#else /* !HAVE_COCOA */ + ".font1: -*-courier-bold-r-*-*-*-1440-*-*-m-*-*-*", + ".font2: -*-courier-bold-r-*-*-*-960-*-*-m-*-*-*", + ".font3: -*-courier-bold-r-*-*-*-480-*-*-m-*-*-*", + ".font4: -*-courier-bold-r-*-*-*-320-*-*-m-*-*-*", + ".font5: -*-courier-bold-r-*-*-*-180-*-*-m-*-*-*", + ".font6: fixed", +#endif /* !HAVE_COCOA */ + + "*delay: 10000", + "*offset: 0", + 0 +}; + +static XrmOptionDescRec memscroller_options [] = { + { "-delay", ".delay", XrmoptionSepArg, 0 }, + { "-font", ".font", XrmoptionSepArg, 0 }, + { "-filename", ".filename", XrmoptionSepArg, 0 }, + { "-color", ".drawMode", XrmoptionNoArg, "color" }, + { "-mono", ".drawMode", XrmoptionNoArg, "mono" }, + { "-ram", ".filename", XrmoptionNoArg, "(RAM)" }, + { "-random", ".filename", XrmoptionNoArg, "(RANDOM)" }, + { 0, 0, 0, 0 } +}; + +XSCREENSAVER_MODULE ("MemScroller", memscroller) diff --git a/hacks/memscroller.man b/hacks/memscroller.man new file mode 100644 index 00000000..33754a2e --- /dev/null +++ b/hacks/memscroller.man @@ -0,0 +1,78 @@ +.TH XScreenSaver 1 "14-Aug-2004" "X Version 11" +.SH NAME +memscroller - scrolls a dump of its own RAM across the screen +.SH SYNOPSIS +.B memscroller +[\-display \fIhost:display.screen\fP] +[\-window] [\-root] [\-mono] [\-install] [\-visual \fIvisual\fP] +[\-font \fIfont\fP] +[\-delay \fIint\fP] +[\-mono | -color] +[\-ram | -random | \-filename \fIfile\fP] +[\-fps] +.SH DESCRIPTION +The \fImemscroller\fP program scrolls a dump of its own process memory +across the screen in three windows at three different rates. +.SH OPTIONS +.I memscroller +accepts the following options: +.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 \-install +Install a private colormap for the window. +.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 \-color +Render each three bytes of memory as R, G, B. This is the default. +.TP 8 +.B \-mono +Render each byte of memory in shades of green. +.TP 8 +.B \-ram +Read from the process's address space. This is the default. +.TP 8 +.B \-random +Instead of reading from memory, generate random numbers. +.TP 8 +.B \-filename \fIfile\fP +Instead of reading from memory, read from the given file until EOF, then +re-open it. If you have permission, /dev/mem is an interesting choice here. +(Note that /dev/null won't ever display anything, because it returns EOF +without ever returning any data.) +.TP 8 +.B \-delay \fImicroseconds\fP +How much of a delay should be introduced between steps of the animation. +Default 10000. +.TP 8 +.B \-fps +Display the current frame rate and CPU load. +.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 2004 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 , 14-Aug-2004. diff --git a/hacks/metaballs.c b/hacks/metaballs.c new file mode 100644 index 00000000..02d418ba --- /dev/null +++ b/hacks/metaballs.c @@ -0,0 +1,429 @@ +/* MetaBalls, Copyright (c) 2002-2003 W.P. van Paassen + * + * 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. + * + * Module - "metaballs.c" + * + * [01/24/03] - W.P. van Paassen: Additional features + * [12/29/02] - W.P. van Paassen: Port to X for use with XScreenSaver, the shadebob hack by Shane Smit was used as a template + * [12/26/02] - W.P. van Paassen: Creation for the Demo Effects Collection (http://demo-effects.sourceforge.net) + */ + +#include +#include "screenhack.h" + +/*#define VERBOSE*/ + +/*blob structure*/ +typedef struct +{ + short xpos,ypos; +} BLOB; + +struct state { + Display *dpy; + Window window; + + unsigned short iWinWidth, iWinHeight; + char *sColor; + + unsigned int nBlobCount; + unsigned char radius; + unsigned char delta; + unsigned char dradius; + unsigned short sradius; + unsigned char **blob; + BLOB *blobs; + unsigned char **blub; + + int delay, cycles; + signed short iColorCount; + unsigned long *aiColorVals; + XImage *pImage; + GC gc; + int draw_i; +}; + + +#undef BELLRAND +#define BELLRAND(n) ((frand((n)) + frand((n)) + frand((n))) / 3) + +static void init_blob(struct state *st, BLOB *blob) +{ + blob->xpos = st->iWinWidth/4 + BELLRAND(st->iWinWidth/2) - st->radius; + blob->ypos = st->iWinHeight/4 + BELLRAND(st->iWinHeight/2) - st->radius; +} + +static void Execute( struct state *st ) +{ + int i, j, k; + + /* clear st->blub array */ + for (i = 0; i < st->iWinHeight; ++i) + memset(st->blub[i], 0, st->iWinWidth * sizeof(unsigned char)); + + /* move st->blobs */ + for (i = 0; i < st->nBlobCount; i++) + { + st->blobs[i].xpos += -st->delta + (int)((st->delta + .5f) * frand(2.0)); + st->blobs[i].ypos += -st->delta + (int)((st->delta + .5f) * frand(2.0)); + } + + /* draw st->blobs to st->blub array */ + for (k = 0; k < st->nBlobCount; ++k) + { + if (st->blobs[k].ypos > -st->dradius && st->blobs[k].xpos > -st->dradius && st->blobs[k].ypos < st->iWinHeight && st->blobs[k].xpos < st->iWinWidth) + { + for (i = 0; i < st->dradius; ++i) + { + if (st->blobs[k].ypos + i >= 0 && st->blobs[k].ypos + i < st->iWinHeight) + { + for (j = 0; j < st->dradius; ++j) + { + if (st->blobs[k].xpos + j >= 0 && st->blobs[k].xpos + j < st->iWinWidth) + { + if (st->blub[st->blobs[k].ypos + i][st->blobs[k].xpos + j] < st->iColorCount-1) + { + if (st->blub[st->blobs[k].ypos + i][st->blobs[k].xpos + j] + st->blob[i][j] > st->iColorCount-1) + st->blub[st->blobs[k].ypos + i][st->blobs[k].xpos + j] = st->iColorCount-1; + else + st->blub[st->blobs[k].ypos + i][st->blobs[k].xpos + j] += st->blob[i][j]; + } + } + } + } + } + } + else + init_blob(st, st->blobs + k); + } + + memset( st->pImage->data, 0, st->pImage->bytes_per_line * st->pImage->height); + + /* draw st->blub array to screen */ + for (i = 0; i < st->iWinHeight; ++i) + { + for (j = 0; j < st->iWinWidth; ++j) + { + if (st->aiColorVals[st->blub[i][j]] > 0) + XPutPixel( st->pImage, j, i, st->aiColorVals[st->blub[i][j]] ); + } + } + + XPutImage( st->dpy, st->window, st->gc, st->pImage, + 0, 0, 0, 0, st->iWinWidth, st->iWinHeight ); +} + +static unsigned long * SetPalette(struct state *st ) +{ + XWindowAttributes XWinAttribs; + XColor Color, *aColors; + signed short iColor; + float nHalfColors; + + XGetWindowAttributes( st->dpy, st->window, &XWinAttribs ); + + Color.red = random() % 0xFFFF; + Color.green = random() % 0xFFFF; + Color.blue = random() % 0xFFFF; + + if( strcasecmp( st->sColor, "random" ) && !XParseColor( st->dpy, XWinAttribs.colormap, st->sColor, &Color ) ) + fprintf( stderr, "%s: color %s not found in database. Choosing to random...\n", progname, st->sColor ); + +#ifdef VERBOSE + printf( "%s: Base color (RGB): <%d, %d, %d>\n", progname, Color.red, Color.green, Color.blue ); +#endif /* VERBOSE */ + + st->iColorCount = get_integer_resource(st->dpy, "ncolors", "Integer" ); + if( st->iColorCount < 2 ) st->iColorCount = 2; + if( st->iColorCount > 255 ) st->iColorCount = 255; + + aColors = calloc( st->iColorCount, sizeof(XColor) ); + st->aiColorVals = calloc( st->iColorCount, sizeof(unsigned long) ); + + for( iColor=0; iColor < st->iColorCount; iColor++ ) + { + nHalfColors = st->iColorCount / 2.0F; + /* Black -> Base Color */ + if( iColor < (st->iColorCount/2) ) + { + aColors[ iColor ].red = ( Color.red / nHalfColors ) * iColor; + aColors[ iColor ].green = ( Color.green / nHalfColors ) * iColor; + aColors[ iColor ].blue = ( Color.blue / nHalfColors ) * iColor; + } + /* Base Color -> White */ + else + { + aColors[ iColor ].red = ( ( ( 0xFFFF - Color.red ) / nHalfColors ) * ( iColor - nHalfColors ) ) + Color.red; + aColors[ iColor ].green = ( ( ( 0xFFFF - Color.green ) / nHalfColors ) * ( iColor - nHalfColors ) ) + Color.green; + aColors[ iColor ].blue = ( ( ( 0xFFFF - Color.blue ) / nHalfColors ) * ( iColor - nHalfColors ) ) + Color.blue; + } + + if( !XAllocColor( st->dpy, XWinAttribs.colormap, &aColors[ iColor ] ) ) + { + /* start all over with less colors */ + XFreeColors( st->dpy, XWinAttribs.colormap, st->aiColorVals, iColor, 0 ); + free( aColors ); + free( st->aiColorVals ); + (st->iColorCount)--; + + if (st->iColorCount < 6) + { + fprintf (stderr, "%s: insufficient colors!\n", + progname); + exit (1); + } + + aColors = calloc( st->iColorCount, sizeof(XColor) ); + st->aiColorVals = calloc( st->iColorCount, sizeof(unsigned long) ); + iColor = -1; + } + else + st->aiColorVals[ iColor ] = aColors[ iColor ].pixel; + } + + free( aColors ); + + XSetWindowBackground( st->dpy, st->window, st->aiColorVals[ 0 ] ); + + return st->aiColorVals; +} + + +static void Initialize( struct state *st ) +{ + XGCValues gcValues; + XWindowAttributes XWinAttribs; + int /*iBitsPerPixel,*/ i, j; + unsigned int distance_squared; + float fraction; + + /* Create the Image for drawing */ + XGetWindowAttributes( st->dpy, st->window, &XWinAttribs ); + + /* Find the preferred bits-per-pixel. (jwz) */ +#if 0 + { + int pfvc = 0; + XPixmapFormatValues *pfv = XListPixmapFormats( st->dpy, &pfvc ); + for( i=0; igc = XCreateGC( st->dpy, st->window, 0, &gcValues ); + + st->pImage = XCreateImage( st->dpy, XWinAttribs.visual, XWinAttribs.depth, ZPixmap, 0, NULL, + XWinAttribs.width, XWinAttribs.height, BitmapPad( st->dpy ), 0 ); + (st->pImage)->data = calloc((st->pImage)->bytes_per_line, (st->pImage)->height); + + st->iWinWidth = XWinAttribs.width; + st->iWinHeight = XWinAttribs.height; + + /* Get the base color. */ + st->sColor = get_string_resource(st->dpy, "color", "Color" ); + + /* Get the st->delta. */ + st->delta = get_integer_resource(st->dpy, "delta", "Integer" ); + if (st->delta < 1) + st->delta = 1; + else if (st->delta > 20) + st->delta = 20; + + /* Get the st->radius. */ + st->radius = get_integer_resource(st->dpy, "radius", "Integer" ); + if (st->radius < 2) + st->radius = 2; + if (st->radius > 100) + st->radius = 100; + + st->radius = (st->radius / 100.0) * (st->iWinHeight >> 3); + if (st->radius >= 128) /* should use UCHAR_MAX? */ + st->radius = 127; /* st->dradius should fit in u_char */ + + st->dradius = st->radius * 2; + st->sradius = st->radius * st->radius; + + /* create st->blob */ + st->blob = malloc ( st->dradius * sizeof(unsigned char*)); + for (i = 0; i < st->dradius; ++i) + st->blob[i] = malloc( st->dradius * sizeof(unsigned char)); + + /* create st->blub array */ + st->blub = malloc( st->iWinHeight * sizeof(unsigned char*)); + for (i = 0; i < st->iWinHeight; ++i) + st->blub[i] = malloc( st->iWinWidth * sizeof(unsigned char)); + + /* create st->blob */ + for (i = -st->radius; i < st->radius; ++i) + { + for (j = -st->radius; j < st->radius; ++j) + { + distance_squared = i * i + j * j; + if (distance_squared <= st->sradius) + { + /* compute density */ + fraction = (float)distance_squared / (float)st->sradius; + st->blob[i + st->radius][j + st->radius] = pow((1.0 - (fraction * fraction)),4.0) * 255.0; + } + else + { + st->blob[i + st->radius][j + st->radius] = 0; + } + } + } + + for (i = 0; i < st->nBlobCount; i++) + { + init_blob(st, st->blobs + i); + } +} + +static void * +metaballs_init (Display *dpy, Window window) +{ + struct state *st = (struct state *) calloc (1, sizeof(*st)); +#ifdef VERBOSE + time_t nTime = time( NULL ); + unsigned short iFrame = 0; +#endif /* VERBOSE */ + + st->dpy = dpy; + st->window = window; + + st->nBlobCount = get_integer_resource(st->dpy, "count", "Integer" ); + if( st->nBlobCount > 255 ) st->nBlobCount = 255; + if( st->nBlobCount < 2 ) st->nBlobCount = 2; + + if( ( st->blobs = calloc( st->nBlobCount, sizeof(BLOB) ) ) == NULL ) + { + fprintf( stderr, "%s: Could not allocate %d Blobs\n", progname, st->nBlobCount ); + abort(); + } +#ifdef VERBOSE + printf( "%s: Allocated %d Blobs\n", progname, st->nBlobCount ); +#endif /* VERBOSE */ + + Initialize( st ); + + st->delay = get_integer_resource(st->dpy, "delay", "Integer" ); + st->cycles = get_integer_resource(st->dpy, "cycles", "Integer" ); + + st->draw_i = -1; + return st; +} + + + +static unsigned long +metaballs_draw (Display *dpy, Window window, void *closure) +{ + struct state *st = (struct state *) closure; + + if( st->draw_i < 0 || st->draw_i++ >= st->cycles ) + { + int i; + XWindowAttributes XWinAttribs; + XGetWindowAttributes( st->dpy, st->window, &XWinAttribs ); + + memset( st->pImage->data, 0, st->pImage->bytes_per_line * st->pImage->height ); + XFreeColors( st->dpy, XWinAttribs.colormap, st->aiColorVals, st->iColorCount, 0 ); + free( st->aiColorVals ); + st->aiColorVals = SetPalette( st ); + XClearWindow( st->dpy, st->window ); + for (i = 0; i < st->nBlobCount; i++) + { + init_blob(st, st->blobs + i); + } + st->draw_i = 0; + } + + Execute( st ); + +#ifdef VERBOSE + iFrame++; + if( nTime - time( NULL ) ) + { + printf( "%s: %d FPS\n", progname, iFrame ); + nTime = time( NULL ); + iFrame = 0; + } +#endif /* VERBOSE */ + + return st->delay; +} + + +static void +metaballs_reshape (Display *dpy, Window window, void *closure, + unsigned int w, unsigned int h) +{ +} + +static Bool +metaballs_event (Display *dpy, Window window, void *closure, XEvent *event) +{ + return False; +} + +static void +metaballs_free (Display *dpy, Window window, void *closure) +{ +#if 0 + struct state *st = (struct state *) closure; + free( st->pImage->data ); + XDestroyImage( st->pImage ); + free( st->aiColorVals ); + free( st->blobs ); + for (i = 0; i < st->iWinHeight; ++i) + free( st->blub[i] ); + free( st->blub ); + for (i = 0; i < st->dradius; ++i) + free( st->blob[i] ); + free( st->blob ); +#endif +} + + +static const char *metaballs_defaults [] = { + ".background: black", + ".foreground: white", + "*color: random", + "*count: 10", + "*cycles: 1000", + "*ncolors: 256", + "*delay: 10000", + "*radius: 100", + "*delta: 3", + 0 +}; + +static XrmOptionDescRec metaballs_options [] = { + { "-color", ".color", XrmoptionSepArg, 0 }, + { "-ncolors", ".ncolors", XrmoptionSepArg, 0 }, + { "-count", ".count", XrmoptionSepArg, 0 }, + { "-delay", ".delay", XrmoptionSepArg, 0 }, + { "-cycles", ".cycles", XrmoptionSepArg, 0 }, + { "-radius", ".radius", XrmoptionSepArg, 0 }, + { "-delta", ".delta", XrmoptionSepArg, 0 }, + { 0, 0, 0, 0 } +}; + + +XSCREENSAVER_MODULE ("MetaBalls", metaballs) + +/* End of Module - "metaballs.c" */ + diff --git a/hacks/metaballs.man b/hacks/metaballs.man new file mode 100644 index 00000000..e9ba541a --- /dev/null +++ b/hacks/metaballs.man @@ -0,0 +1,73 @@ +.TH XScreenSaver 1 "" "X Version 11" +.SH NAME +MetaBalls - draws 2D metaballs +.SH SYNOPSIS +.B MetaBalls +[\-display \fIhost:display.screen\fP] +[\-visual \fIvisual\fP] +[\-window] +[\-root] +[\-ncolors \fInumber\fP] +[\-count \fInumber\fP] +[\-delay \fInumber\fP] +[\-cycles \fInumber\fP] +[\-radius \fInumber\fP] +[\-delta \fInumber\fP] +[\-fps] +.SH DESCRIPTION +This hack draws 2D metaballs to the screen by calculating the sum of the colors of all metaballs covering a pixel. +Ported from the demo effects collection (http://demo-effects.sourceforge.net) +.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 \-ncolors \fInumber\fP +Number of Colors. Default: 256. +.TP 8 +.B \-count \fInumber\fP +Number of MetaBalls. 2 - 255. Default: 10. +.TP 8 +.B \-delay \fInumber\fP +Per-frame delay, in microseconds. Default: 5000 (0.005 seconds.). +.TP 8 +.B \-cycles \fInumber\fP +Duration. 100 - 3000. Default: 1000. +.TP 8 +.B \-radius \fInumber\fP +MetaBall Radius. 2 - 100. Default: 100. +.TP 8 +.B \-delta \fInumber\fP +MetaBall Movement. 1 - 20. Default: 3. +.TP 8 +.B \-fps +Display the current frame rate and CPU load. +.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 2002-2003 by W.P. van Paassen. 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 +W.P. van Paassen diff --git a/hacks/moire.c b/hacks/moire.c new file mode 100644 index 00000000..10797a5f --- /dev/null +++ b/hacks/moire.c @@ -0,0 +1,294 @@ +/* xscreensaver, Copyright (c) 1997-2008 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. + * + * Concept snarfed from Michael D. Bayne in + * http://www.go2net.com/internet/deep/1997/04/16/body.html + */ + +#include "screenhack.h" + +#undef HAVE_XSHM_EXTENSION /* this is broken here at the moment */ + + +#ifdef HAVE_XSHM_EXTENSION +# include "xshm.h" +#endif /* HAVE_XSHM_EXTENSION */ + +struct state { + Display *dpy; + Window window; +#ifdef HAVE_XSHM_EXTENSION + Bool use_shm; + XShmSegmentInfo shm_info; +#endif /* HAVE_XSHM_EXTENSION */ + + int delay; + int offset; + XColor *colors; + int ncolors; + GC gc; + unsigned long fg_pixel; + unsigned long bg_pixel; + int depth; + + int draw_y, draw_xo, draw_yo; + int draw_factor; + XImage *draw_image; + XWindowAttributes xgwa; +}; + +static void +moire_init_1 (struct state *st) +{ + int oncolors; + int i; + int fgh, bgh; + double fgs, fgv, bgs, bgv; + XWindowAttributes xgwa; + XColor fgc, bgc; + XGCValues gcv; + + XGetWindowAttributes (st->dpy, st->window, &xgwa); + + st->delay = get_integer_resource (st->dpy, "delay", "Integer"); + st->offset = get_integer_resource (st->dpy, "offset", "Integer"); + if (st->offset < 2) st->offset = 2; + +#ifdef HAVE_XSHM_EXTENSION + st->use_shm = get_boolean_resource(st->dpy, "useSHM", "Boolean"); +#endif /* HAVE_XSHM_EXTENSION */ + + MONO: + if (st->colors) + { + for (i = 0; i < st->ncolors; i++) + XFreeColors (st->dpy, xgwa.colormap, &st->colors[i].pixel, 1, 0); + free(st->colors); + st->colors = 0; + } + + if (mono_p) + { + st->fg_pixel = WhitePixelOfScreen (DefaultScreenOfDisplay(st->dpy)); + st->bg_pixel = BlackPixelOfScreen (DefaultScreenOfDisplay(st->dpy)); + } + else + { + st->fg_pixel = get_pixel_resource (st->dpy, + xgwa.colormap, "foreground", "Foreground"); + st->bg_pixel = get_pixel_resource (st->dpy, + xgwa.colormap, "background", "Background"); + } + + if (mono_p) + { + st->offset *= 20; /* compensate for lack of shading */ + gcv.foreground = st->fg_pixel; + } + else + { + st->ncolors = get_integer_resource (st->dpy, "ncolors", "Integer"); + if (st->ncolors < 2) st->ncolors = 2; + oncolors = st->ncolors; + + fgc.flags = bgc.flags = DoRed|DoGreen|DoBlue; + if (get_boolean_resource(st->dpy, "random","Boolean")) + { + fgc.red = random() & 0xFFFF; + fgc.green = random() & 0xFFFF; + fgc.blue = random() & 0xFFFF; + bgc.red = random() & 0xFFFF; + bgc.green = random() & 0xFFFF; + bgc.blue = random() & 0xFFFF; + } + else + { + fgc.pixel = st->fg_pixel; + bgc.pixel = st->bg_pixel; + XQueryColor (st->dpy, xgwa.colormap, &fgc); + XQueryColor (st->dpy, xgwa.colormap, &bgc); + } + rgb_to_hsv (fgc.red, fgc.green, fgc.blue, &fgh, &fgs, &fgv); + rgb_to_hsv (bgc.red, bgc.green, bgc.blue, &bgh, &bgs, &bgv); + + st->colors = (XColor *) malloc (sizeof (XColor) * (st->ncolors+2)); + memset(st->colors, 0, (sizeof (XColor) * (st->ncolors+2))); + make_color_ramp (st->dpy, xgwa.colormap, + fgh, fgs, fgv, bgh, bgs, bgv, + st->colors, &st->ncolors, + True, True, False); + if (st->ncolors != oncolors) + fprintf(stderr, "%s: got %d of %d requested colors.\n", + progname, st->ncolors, oncolors); + + if (st->ncolors <= 2) + { + mono_p = True; + goto MONO; + } + + gcv.foreground = st->colors[0].pixel; + } + st->gc = XCreateGC (st->dpy, st->window, GCForeground, &gcv); +} + + +static void * +moire_init (Display *dpy, Window window) +{ + struct state *st = (struct state *) calloc (1, sizeof(*st)); + st->dpy = dpy; + st->window = window; + moire_init_1 (st); + return st; +} + + +static unsigned long +moire_draw (Display *dpy, Window window, void *closure) +{ + struct state *st = (struct state *) closure; + XGCValues gcv; + int chunk_size = 20, ii; + + if (st->draw_y == 0) + { + moire_init_1 (st); + + XGetWindowAttributes (st->dpy, st->window, &st->xgwa); + + st->draw_xo = (random() % st->xgwa.width) - st->xgwa.width/2; + st->draw_yo = (random() % st->xgwa.height) - st->xgwa.height/2; + st->draw_factor = (random() % st->offset) + 1; + + st->depth = visual_depth(DefaultScreenOfDisplay(st->dpy), st->xgwa.visual); + +# ifdef HAVE_XSHM_EXTENSION + if (st->use_shm) + { + st->draw_image = create_xshm_image(st->dpy, st->xgwa.visual, + st->depth, ZPixmap, 0, + &st->shm_info, st->xgwa.width, 1); + if (!st->draw_image) + st->use_shm = False; + } +# endif /* HAVE_XSHM_EXTENSION */ + + if (!st->draw_image) + { + st->draw_image = XCreateImage (st->dpy, st->xgwa.visual, + st->depth, ZPixmap, 0, /* depth, format, offset */ + 0, st->xgwa.width, 1, 8, 0); /* data, w, h, pad, bpl */ + st->draw_image->data = (char *) calloc(st->draw_image->height, st->draw_image->bytes_per_line); + } + } + + /* for (y = 0; y < st->xgwa.height; y++) */ + for (ii = 0; ii < chunk_size; ii++) + { + int x; + for (x = 0; x < st->xgwa.width; x++) + { + double xx = x + st->draw_xo; + double yy = st->draw_y + st->draw_yo; + double i = ((xx * xx) + (yy * yy)) / (double) st->draw_factor; + if (mono_p) + gcv.foreground = ((((long) i) & 1) ? st->fg_pixel : st->bg_pixel); + else + gcv.foreground = st->colors[((long) i) % st->ncolors].pixel; + XPutPixel (st->draw_image, x, 0, gcv.foreground); + } + +# ifdef HAVE_XSHM_EXTENSION + if (st->use_shm) + XShmPutImage(st->dpy, st->window, st->gc, st->draw_image, 0, 0, 0, st->draw_y, st->xgwa.width, 1, False); + else +# endif /* HAVE_XSHM_EXTENSION */ + XPutImage (st->dpy, st->window, st->gc, st->draw_image, 0, 0, 0, st->draw_y, st->xgwa.width, 1); + + st->draw_y++; + if (st->draw_y >= st->xgwa.height) + break; + } + + + if (st->draw_y >= st->xgwa.height) + { + st->draw_y = 0; + +# ifdef HAVE_XSHM_EXTENSION + if (!st->use_shm) +# endif /* HAVE_XSHM_EXTENSION */ + if (st->draw_image->data) + { + free(st->draw_image->data); + st->draw_image->data = 0; + } + +# ifdef HAVE_XSHM_EXTENSION + if (st->use_shm) + destroy_xshm_image (st->dpy, st->draw_image, &st->shm_info); + else +# endif /* HAVE_XSHM_EXTENSION */ + XDestroyImage (st->draw_image); + st->draw_image = 0; + + return st->delay * 1000000; + } + + return st->delay * 10000; +} + + +static const char *moire_defaults [] = { + ".background: blue", + ".foreground: red", + "*fpsSolid: true", + "*random: true", + "*delay: 5", + "*ncolors: 64", + "*offset: 50", +#ifdef HAVE_XSHM_EXTENSION + "*useSHM: True", +#else + "*useSHM: False", +#endif + 0 +}; + +static XrmOptionDescRec moire_options [] = { + { "-random", ".random", XrmoptionNoArg, "True" }, + { "-no-random", ".random", XrmoptionNoArg, "False" }, + { "-delay", ".delay", XrmoptionSepArg, 0 }, + { "-ncolors", ".ncolors", XrmoptionSepArg, 0 }, + { "-offset", ".offset", XrmoptionSepArg, 0 }, + { "-shm", ".useSHM", XrmoptionNoArg, "True" }, + { "-no-shm", ".useSHM", XrmoptionNoArg, "False" }, + { 0, 0, 0, 0 } +}; + +static void +moire_reshape (Display *dpy, Window window, void *closure, + unsigned int w, unsigned int h) +{ +} + +static Bool +moire_event (Display *dpy, Window window, void *closure, XEvent *event) +{ + return False; +} + +static void +moire_free (Display *dpy, Window window, void *closure) +{ +} + +XSCREENSAVER_MODULE ("Moire", moire) diff --git a/hacks/moire.man b/hacks/moire.man new file mode 100644 index 00000000..b38d3430 --- /dev/null +++ b/hacks/moire.man @@ -0,0 +1,68 @@ +.TH XScreenSaver 1 "27-Apr-97" "X Version 11" +.SH NAME +moire - draw circular interference patterns +.SH SYNOPSIS +.B moire +[\-display \fIhost:display.screen\fP] [\-foreground \fIcolor\fP] [\-background \fIcolor\fP] [\-window] [\-root] [\-mono] [\-install] [\-visual \fIvisual\fP] [\-delay \fIseconds\fP] [\-random \fIboolean\fP] [\-ncolors \fIint\fP] [\-offset \fIint\fP] +[\-fps] +.SH DESCRIPTION +The \fImoire\fP program draws cool circular interference patterns. +.SH OPTIONS +.I moire +accepts the following options: +.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 \-mono +If on a color display, pretend we're on a monochrome display. +.TP 8 +.B \-install +Install a private colormap for the window. +.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 \-delay \fIseconds\fP +How long to wait before starting over. Default 5 seconds. +.TP 8 +.B \-random \fIboolean\fP +Whether to ignore the foreground/background colors, and pick them randomly +instead. +.TP 8 +.B \-offset \fIinteger\fP +The maximum random radius increment to use. +.TP 8 +.B \-ncolors \fIinteger\fP +How many colors should be allocated in the color ramp (note that this +value interacts with \fIoffset\fP.) +.TP 8 +.B \-fps +Display the current frame rate and CPU load. +.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 1997 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 , 27-Apr-97, based on code by +Michael D. Bayne . diff --git a/hacks/moire2.c b/hacks/moire2.c new file mode 100644 index 00000000..441a3713 --- /dev/null +++ b/hacks/moire2.c @@ -0,0 +1,351 @@ +/* xscreensaver, Copyright (c) 1997, 1998, 2006 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. + */ + +#include "screenhack.h" + +#ifdef HAVE_DOUBLE_BUFFER_EXTENSION +# include "xdbe.h" +#endif /* HAVE_DOUBLE_BUFFER_EXTENSION */ + +struct state { + Display *dpy; + Window window; + + int ncolors; + XColor *colors; + int fg_pixel, bg_pixel; + Pixmap p0, p1, p2, p3; + GC copy_gc, erase_gc, window_gc; + int width, height, size; + int x1, x2, y1, y2, x3, y3; + int dx1, dx2, dx3, dy1, dy2, dy3; + int othickness, thickness; + Bool do_three; +#ifdef HAVE_DOUBLE_BUFFER_EXTENSION + XdbeBackBuffer back_buf; +#endif /* HAVE_DOUBLE_BUFFER_EXTENSION */ + + Bool flip_a, flip_b; + int pix; + int delay, color_shift; + + int reset; + int iterations, iteration; +}; + +static void +moire2_init_1 (struct state *st) +{ + XWindowAttributes xgwa; + XGetWindowAttributes (st->dpy, st->window, &xgwa); + + st->othickness = get_integer_resource(st->dpy, "thickness", "Thickness"); + + if (mono_p) + st->ncolors = 2; + else + st->ncolors = get_integer_resource (st->dpy, "colors", "Colors"); + if (st->ncolors < 2) st->ncolors = 2; + if (st->ncolors <= 2) mono_p = True; + + if (mono_p) + st->colors = 0; + else + st->colors = (XColor *) malloc(sizeof(*st->colors) * (st->ncolors+1)); + + if (mono_p) + ; + else + make_smooth_colormap (st->dpy, xgwa.visual, xgwa.colormap, st->colors, &st->ncolors, + True, 0, True); + + st->bg_pixel = get_pixel_resource(st->dpy, + xgwa.colormap, "background", "Background"); + st->fg_pixel = get_pixel_resource(st->dpy, + xgwa.colormap, "foreground", "Foreground"); + +#ifdef HAVE_DOUBLE_BUFFER_EXTENSION + st->back_buf = xdbe_get_backbuffer (st->dpy, st->window, XdbeUndefined); +#endif /* HAVE_DOUBLE_BUFFER_EXTENSION */ +} + + +static void +reset_moire2 (struct state *st) +{ + GC gc; + XWindowAttributes xgwa; + XGCValues gcv; + Bool xor; + XGetWindowAttributes (st->dpy, st->window, &xgwa); + + st->do_three = (0 == (random() % 3)); + + st->width = xgwa.width; + st->height = xgwa.height; + st->size = st->width > st->height ? st->width : st->height; + + if (st->p0) XFreePixmap(st->dpy, st->p0); + if (st->p1) XFreePixmap(st->dpy, st->p1); + if (st->p2) XFreePixmap(st->dpy, st->p2); + if (st->p3) XFreePixmap(st->dpy, st->p3); + + st->p0 = XCreatePixmap(st->dpy, st->window, st->width, st->height, 1); + st->p1 = XCreatePixmap(st->dpy, st->window, st->width*2, st->height*2, 1); + st->p2 = XCreatePixmap(st->dpy, st->window, st->width*2, st->height*2, 1); + if (st->do_three) + st->p3 = XCreatePixmap(st->dpy, st->window, st->width*2, st->height*2, 1); + else + st->p3 = 0; + + st->thickness = (st->othickness > 0 ? st->othickness : (1 + (random() % 4))); + + gcv.foreground = 0; + gcv.line_width = (st->thickness == 1 ? 0 : st->thickness); + gc = XCreateGC (st->dpy, st->p1, GCForeground|GCLineWidth, &gcv); + + XFillRectangle(st->dpy, st->p1, gc, 0, 0, st->width*2, st->height*2); + XFillRectangle(st->dpy, st->p2, gc, 0, 0, st->width*2, st->height*2); + if (st->do_three) + XFillRectangle(st->dpy, st->p3, gc, 0, 0, st->width*2, st->height*2); + + XSetForeground(st->dpy, gc, 1); + + xor = (st->do_three || (st->thickness == 1) || (random() & 1)); + + { + int i, ii, maxx, maxy; + +#define FROB(P) do { \ + maxx = (st->size*4); \ + maxy = (st->size*4); \ + if (0 == (random() % 5)) { \ + float f = 1.0 + frand(0.05); \ + if (random() & 1) maxx *= f; \ + else maxy *= f; \ + } \ + ii = (st->thickness + 1 + (xor ? 0 : 1) + (random() % (4 * st->thickness))); \ + for (i = 0; i < (st->size*2); i += ii) \ + XDrawArc(st->dpy, (P), gc, i-st->size, i-st->size, maxx-i-i, maxy-i-i, 0, 360*64); \ + if (0 == (random() % 5)) \ + { \ + XSetFunction(st->dpy, gc, GXxor); \ + XFillRectangle(st->dpy, (P), gc, 0, 0, st->width*2, st->height*2); \ + XSetFunction(st->dpy, gc, GXcopy); \ + } \ + } while(0) + + FROB(st->p1); + FROB(st->p2); + if (st->do_three) + FROB(st->p3); +#undef FROB + } + + XFreeGC(st->dpy, gc); + + if (st->copy_gc) XFreeGC(st->dpy, st->copy_gc); + gcv.function = (xor ? GXxor : GXor); + gcv.foreground = 1; + gcv.background = 0; + + st->copy_gc = XCreateGC (st->dpy, st->p0, GCFunction|GCForeground|GCBackground, &gcv); + + gcv.foreground = 0; + if (st->erase_gc) XFreeGC(st->dpy, st->erase_gc); + st->erase_gc = XCreateGC (st->dpy, st->p0, GCForeground, &gcv); + + gcv.foreground = st->fg_pixel; + gcv.background = st->bg_pixel; + if (st->window_gc) XFreeGC(st->dpy, st->window_gc); + st->window_gc = XCreateGC (st->dpy, st->window, GCForeground|GCBackground, &gcv); + +#define FROB(N,DN,MAX) \ + N = (MAX/2) + (random() % MAX); \ + DN = ((1 + (random() % (7*st->thickness))) * ((random() & 1) ? 1 : -1)) + + FROB(st->x1,st->dx1,st->width); + FROB(st->x2,st->dx2,st->width); + FROB(st->x3,st->dx3,st->width); + FROB(st->y1,st->dy1,st->height); + FROB(st->y2,st->dy2,st->height); + FROB(st->y3,st->dy3,st->height); +#undef FROB +} + + + +static void +moire2 (struct state *st) +{ +#define FROB(N,DN,MAX) \ + N += DN; \ + if (N <= 0) N = 0, DN = -DN; \ + else if (N >= MAX) N = MAX, DN = -DN; \ + else if (0 == (random() % 100)) DN = -DN; \ + else if (0 == (random() % 50)) \ + DN += (DN <= -20 ? 1 : (DN >= 20 ? -1 : ((random() & 1) ? 1 : -1))) + + FROB(st->x1,st->dx1,st->width); + FROB(st->x2,st->dx2,st->width); + FROB(st->x3,st->dx3,st->width); + FROB(st->y1,st->dy1,st->height); + FROB(st->y2,st->dy2,st->height); + FROB(st->y3,st->dy3,st->height); +#undef FROB + + XFillRectangle(st->dpy, st->p0, st->erase_gc, 0, 0, st->width, st->height); + XCopyArea(st->dpy, st->p1, st->p0, st->copy_gc, st->x1, st->y1, st->width, st->height, 0, 0); + XCopyArea(st->dpy, st->p2, st->p0, st->copy_gc, st->x2, st->y2, st->width, st->height, 0, 0); + if (st->do_three) + XCopyArea(st->dpy, st->p3, st->p0, st->copy_gc, st->x3, st->y3, st->width, st->height, 0, 0); + +#ifdef HAVE_DOUBLE_BUFFER_EXTENSION + if (st->back_buf) + { + XdbeSwapInfo info[1]; + info[0].swap_window = st->window; + info[0].swap_action = XdbeUndefined; + XCopyPlane (st->dpy, st->p0, st->back_buf, st->window_gc, 0, 0, st->width, st->height, 0, 0, 1L); + XdbeSwapBuffers (st->dpy, info, 1); + } + else +#endif /* HAVE_DOUBLE_BUFFER_EXTENSION */ + XCopyPlane (st->dpy, st->p0, st->window, st->window_gc, 0, 0, st->width, st->height, 0, 0, 1L); + +#if 0 + XCopyPlane(st->dpy, st->p1, st->window, st->window_gc, (st->width*2)/3, (st->height*2)/3, + st->width/2, st->height/2, + 0, st->height/2, 1L); + XCopyPlane(st->dpy, st->p2, st->window, st->window_gc, (st->width*2)/3, (st->height*2)/3, + st->width/2, st->height/2, + st->width/2, st->height/2, 1L); +#endif +} + + + +static void * +moire2_init (Display *dpy, Window window) +{ + struct state *st = (struct state *) calloc (1, sizeof(*st)); + st->dpy = dpy; + st->window = window; + st->reset = 1; + + st->delay = get_integer_resource (st->dpy, "delay", "Integer"); + st->color_shift = get_integer_resource (st->dpy, "colorShift", "Integer"); + + if (st->color_shift <= 0) st->color_shift = 1; + moire2_init_1 (st); + return st; +} + +static unsigned long +moire2_draw (Display *dpy, Window window, void *closure) +{ + struct state *st = (struct state *) closure; + + if (st->reset) + { + st->reset = 0; + + st->iteration = 0; + st->iterations = 30 + (random() % 70) + (random() % 70); + reset_moire2 (st); + + st->flip_a = mono_p ? False : (random() & 1); + st->flip_b = mono_p ? False : (random() & 1); + + if (st->flip_b) + { + XSetForeground(st->dpy, st->window_gc, st->bg_pixel); + XSetBackground(st->dpy, st->window_gc, st->fg_pixel); + } + else + { + XSetForeground(st->dpy, st->window_gc, st->fg_pixel); + XSetBackground(st->dpy, st->window_gc, st->bg_pixel); + } + } + + if (!mono_p) + { + st->pix++; + st->pix = st->pix % st->ncolors; + + if (st->flip_a) + XSetBackground(st->dpy, st->window_gc, st->colors[st->pix].pixel); + else + XSetForeground(st->dpy, st->window_gc, st->colors[st->pix].pixel); + } + + + moire2 (st); + st->iteration++; + if (st->iteration >= st->color_shift) + { + st->iteration = 0; + st->iterations--; + if (st->iterations <= 0) + st->reset = 1; + } + + return st->delay; +} + +static void +moire2_reshape (Display *dpy, Window window, void *closure, + unsigned int w, unsigned int h) +{ + struct state *st = (struct state *) closure; + st->reset = 1; +} + +static Bool +moire2_event (Display *dpy, Window window, void *closure, XEvent *event) +{ + return False; +} + +static void +moire2_free (Display *dpy, Window window, void *closure) +{ +} + +static const char *moire2_defaults [] = { + ".background: black", + ".foreground: white", + "*delay: 50000", + "*thickness: 0", + "*colors: 150", + "*colorShift: 5", + +#ifdef HAVE_DOUBLE_BUFFER_EXTENSION + /* Off by default, since it slows it down a lot, and the flicker isn't really + all that bad without it... Or rather, it flickers just as badly with it. + The XFree86 implementation of the XDBE extension totally blows! There is + just *no* excuse for the "swap buffers" operation to flicker like it does. + */ + "*useDBE: False", +#endif /* HAVE_DOUBLE_BUFFER_EXTENSION */ + + 0 +}; + +static XrmOptionDescRec moire2_options [] = { + { "-delay", ".delay", XrmoptionSepArg, 0 }, + { "-ncolors", ".colors", XrmoptionSepArg, 0 }, + { "-thickness", ".thickness", XrmoptionSepArg, 0 }, + { 0, 0, 0, 0 } +}; + +XSCREENSAVER_MODULE ("Moire2", moire2) diff --git a/hacks/moire2.man b/hacks/moire2.man new file mode 100644 index 00000000..b57c4857 --- /dev/null +++ b/hacks/moire2.man @@ -0,0 +1,63 @@ +.TH XScreenSaver 1 "" "X Version 11" +.SH NAME +moire2 - circular interference patterns. +.SH SYNOPSIS +.B moire2 +[\-display \fIhost:display.screen\fP] +[\-visual \fIvisual\fP] +[\-window] +[\-root] +[\-delay \fInumber\fP] +[\-ncolors \fInumber\fP] +[\-thickness \fInumber\fP] +[\-fps] +.SH DESCRIPTION +Another example of the fun you can have with moire interference patterns; +this hack generates fields of concentric circles or ovals, and combines the +planes with various operations. The planes are moving independently of one +another, causing the interference lines to ``spray.'' +.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: 50000 (0.05 seconds.). +.TP 8 +.B \-ncolors \fInumber\fP +Number of Colors. Default: 150. +.TP 8 +.B \-thickness \fInumber\fP +Thickness of lines, in pixels. Default: 0. +.TP 8 +.B \-fps +Display the current frame rate and CPU load. +.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 2002 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/mountain.c b/hacks/mountain.c new file mode 100644 index 00000000..82d5fce7 --- /dev/null +++ b/hacks/mountain.c @@ -0,0 +1,298 @@ +/* -*- Mode: C; tab-width: 4 -*- */ +/* mountain -- square grid mountains */ + +#if 0 +static const char sccsid[] = "@(#)mountain.c 5.00 2000/11/01 xlockmore"; +#endif + +/*- + * Copyright (c) 1995 Pascal Pensa + * + * Permission to use, copy, modify, and distribute this software and its + * documentation for any purpose and without fee is hereby granted, + * provided that the above copyright notice appear in all copies and that + * both that copyright notice and this permission notice appear in + * supporting documentation. + * + * This file is provided AS IS with no warranties of any kind. The author + * shall have no liability with respect to the infringement of copyrights, + * trade secrets or any patents by this file or any part thereof. In no + * event will the author be liable for any lost revenue or profits or + * other special, indirect and consequential damages. + * + * Revision History: + * 01-Nov-2000: Allocation checks + * 10-May-1997: Compatible with xscreensaver + * 1995: Written + */ + +#ifdef STANDALONE +# define MODE_mountain +#define DEFAULTS "*delay: 20000 \n" \ + "*count: 30 \n" \ + "*cycles: 4000 \n" \ + "*ncolors: 64 \n" \ + "*fpsSolid: true \n" \ + +# define SMOOTH_COLORS +# define mountain_handle_event 0 +# include "xlockmore.h" /* in xscreensaver distribution */ +#else /* STANDALONE */ +# include "xlock.h" /* in xlockmore distribution */ +#endif /* STANDALONE */ + +#ifdef MODE_mountain + +ENTRYPOINT ModeSpecOpt mountain_opts = +{0, (XrmOptionDescRec *) NULL, 0, (argtype *) NULL, (OptionStruct *) NULL}; + +#ifdef USE_MODULES +ModStruct mountain_description = +{"mountain", "init_mountain", "draw_mountain", "release_mountain", + "refresh_mountain", "init_mountain", (char *) NULL, &mountain_opts, + 1000, 30, 4000, 1, 64, 1.0, "", + "Shows Papo's mountain range", 0, NULL}; + +#endif + +/* ~ 5000 Max mountain height (1000 - 10000) */ +#define MAXHEIGHT (3 * (mp->width + mp->height)) + +#define WORLDWIDTH 50 /* World size x * y */ + +#define RANGE_RAND(min,max) ((min) + NRAND((max) - (min))) + +typedef struct { + int pixelmode; + int width; + int height; + int x, y; + int offset; + int stage; + int h[WORLDWIDTH][WORLDWIDTH]; + long time; /* up time */ + Bool wireframe; + Bool joke; + GC stippledGC; +} mountainstruct; + +static mountainstruct *mountains = (mountainstruct *) NULL; + +static void +spread(int (*m)[50], int x, int y) +{ + int x2, y2; + int h = m[x][y]; + + for (y2 = y - 1; y2 <= y + 1; y2++) + for (x2 = x - 1; x2 <= x + 1; x2++) + if (x2 >= 0 && y2 >= 0 && x2 < WORLDWIDTH && y2 < WORLDWIDTH) + m[x2][y2] = (m[x2][y2] + h) / 2; +} + +static void +drawamountain(ModeInfo * mi) +{ + Display *display = MI_DISPLAY(mi); + Window window = MI_WINDOW(mi); + GC gc = MI_GC(mi); + mountainstruct *mp = &mountains[MI_SCREEN(mi)]; + int x2, y2, x3, y3, y4, y5, c = 0; + XPoint p[5]; + + if (MI_NPIXELS(mi) > 2) { + c = (mp->h[mp->x][mp->y] + mp->h[mp->x + 1][mp->y] + + mp->h[mp->x][mp->y + 1] + mp->h[mp->x + 1][mp->y + 1]) / 4; + c = (c / 10 + mp->offset) % MI_NPIXELS(mi); + } + x2 = mp->x * (2 * mp->width) / (3 * WORLDWIDTH); + y2 = mp->y * (2 * mp->height) / (3 * WORLDWIDTH); + p[0].x = (x2 - y2 / 2) + (mp->width / 4); + p[0].y = (y2 - mp->h[mp->x][mp->y]) + mp->height / 4; + + x3 = (mp->x + 1) * (2 * mp->width) / (3 * WORLDWIDTH); + y3 = mp->y * (2 * mp->height) / (3 * WORLDWIDTH); + p[1].x = (x3 - y3 / 2) + (mp->width / 4); + p[1].y = (y3 - mp->h[mp->x + 1][mp->y]) + mp->height / 4; + + y4 = (mp->y + 1) * (2 * mp->height) / (3 * WORLDWIDTH); + p[2].x = (x3 - y4 / 2) + (mp->width / 4); + p[2].y = (y4 - mp->h[mp->x + 1][mp->y + 1]) + mp->height / 4; + + y5 = (mp->y + 1) * (2 * mp->height) / (3 * WORLDWIDTH); + p[3].x = (x2 - y5 / 2) + (mp->width / 4); + p[3].y = (y5 - mp->h[mp->x][mp->y + 1]) + mp->height / 4; + + p[4].x = p[0].x; + p[4].y = p[0].y; + + if (MI_NPIXELS(mi) > 2) + XSetForeground(display, gc, MI_PIXEL(mi, c)); + else + XSetForeground(display, gc, MI_WHITE_PIXEL(mi)); + + if (mp->joke) { + if ((Bool) (LRAND() & 1)) + XDrawLines(display, window, gc, p, 5, CoordModeOrigin); + else { + XFillPolygon(display, window, gc, p, 4, Complex, CoordModeOrigin); + if (!mp->pixelmode) { + XSetForeground(display, gc, MI_BLACK_PIXEL(mi)); + XDrawLines(display, window, gc, p, 5, CoordModeOrigin); + } + } + } else { + if (mp->wireframe) { + XDrawLines(display, window, gc, p, 5, CoordModeOrigin); + } else { + XFillPolygon(display, window, gc, p, 4, Complex, CoordModeOrigin); + + if (!mp->pixelmode) { + XSetForeground(display, gc, MI_BLACK_PIXEL(mi)); + XDrawLines(display, window, gc, p, 5, CoordModeOrigin); + } + } + } + mp->x++; + if (mp->x == WORLDWIDTH - 1) { + mp->y++; + mp->x = 0; + } + if (mp->y == WORLDWIDTH - 1) + mp->stage++; +} + +ENTRYPOINT void +init_mountain (ModeInfo * mi) +{ + int i, j, x, y; + XGCValues gcv; + mountainstruct *mp; + + if (mountains == NULL) { + if ((mountains = (mountainstruct *) calloc(MI_NUM_SCREENS(mi), + sizeof (mountainstruct))) == NULL) + return; + } + mp = &mountains[MI_SCREEN(mi)]; + + mp->width = MI_WIDTH(mi); + mp->height = MI_HEIGHT(mi); + mp->pixelmode = (mp->width + mp->height < 200); + mp->stage = 0; + mp->time = 0; + mp->x = mp->y = 0; + if (MI_IS_FULLRANDOM(mi)) { + mp->joke = (Bool) (NRAND(10) == 0); + mp->wireframe = (Bool) (LRAND() & 1); + } else { + mp->joke = False; + mp->wireframe = MI_IS_WIREFRAME(mi); + } + + if (mp->stippledGC == None) { + gcv.foreground = MI_WHITE_PIXEL(mi); + gcv.background = MI_BLACK_PIXEL(mi); + if ((mp->stippledGC = XCreateGC(MI_DISPLAY(mi), MI_WINDOW(mi), + GCForeground | GCBackground, &gcv)) == None) + return; + } + MI_CLEARWINDOW(mi); + + for (y = 0; y < (int) WORLDWIDTH; y++) + for (x = 0; x < (int) WORLDWIDTH; x++) + mp->h[x][y] = 0; + + j = MI_COUNT(mi); + if (j < 0) + j = NRAND(-j) + 1; + for (i = 0; i < j; i++) + mp->h[RANGE_RAND(1, WORLDWIDTH - 1)][RANGE_RAND(1, WORLDWIDTH - 1)] = + NRAND(MAXHEIGHT); + + for (y = 0; y < WORLDWIDTH; y++) + for (x = 0; x < WORLDWIDTH; x++) + spread(mp->h, x, y); + + for (y = 0; y < WORLDWIDTH; y++) + for (x = 0; x < WORLDWIDTH; x++) { + mp->h[x][y] = mp->h[x][y] + NRAND(10) - 5; + if (mp->h[x][y] < 10) + mp->h[x][y] = 0; + } + + if (MI_NPIXELS(mi) > 2) + mp->offset = NRAND(MI_NPIXELS(mi)); + else + mp->offset = 0; +} + +ENTRYPOINT void +draw_mountain (ModeInfo * mi) +{ + mountainstruct *mp; + + if (mountains == NULL) + return; + mp = &mountains[MI_SCREEN(mi)]; + if (mp->stippledGC == NULL) + return; + + MI_IS_DRAWN(mi) = True; + + switch (mp->stage) { + case 0: + drawamountain(mi); + break; + case 1: + if (++mp->time > MI_CYCLES(mi)) + mp->stage++; + break; + case 2: + init_mountain(mi); + break; + } +} + +ENTRYPOINT void +reshape_mountain(ModeInfo * mi, int width, int height) +{ + XClearWindow (MI_DISPLAY (mi), MI_WINDOW(mi)); + init_mountain (mi); +} + + +ENTRYPOINT void +release_mountain (ModeInfo * mi) +{ + if (mountains != NULL) { + int screen; + + for (screen = 0; screen < MI_NUM_SCREENS(mi); screen++) { + mountainstruct *mp = &mountains[screen]; + + if (mp->stippledGC) + XFreeGC(MI_DISPLAY(mi), mp->stippledGC); + } + (void) free((void *) mountains); + mountains = (mountainstruct *) NULL; + } +} + +ENTRYPOINT void +refresh_mountain(ModeInfo * mi) +{ + mountainstruct *mp; + + if (mountains == NULL) + return; + mp = &mountains[MI_SCREEN(mi)]; + + MI_CLEARWINDOW(mi); + mp->x = 0; + mp->y = 0; +} + +XSCREENSAVER_MODULE ("Mountain", mountain) + +#endif /* MODE_mountain */ diff --git a/hacks/mountain.man b/hacks/mountain.man new file mode 100644 index 00000000..692eb479 --- /dev/null +++ b/hacks/mountain.man @@ -0,0 +1,60 @@ +.TH XScreenSaver 1 "" "X Version 11" +.SH NAME +mountain - random 3D plots that look vaguely mountainous. +.SH SYNOPSIS +.B mountain +[\-display \fIhost:display.screen\fP] +[\-visual \fIvisual\fP] +[\-window] +[\-root] +[\-count \fInumber\fP] +[\-delay \fInumber\fP] +[\-ncolors \fInumber\fP] +[\-fps] +.SH DESCRIPTION +Generates random 3d plots that look vaguely mountainous. +.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 \-count \fInumber\fP +Count. 0 - 100. Default: 30. +.TP 8 +.B \-delay \fInumber\fP +Per-frame delay, in microseconds. Default: 1000 (0.001 seconds.). +.TP 8 +.B \-ncolors \fInumber\fP +Number of colors. Default: 64. +.TP 8 +.B \-fps +Display the current frame rate and CPU load. +.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 2002 by Pascal Pensa. 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 +Pascal Pensa. diff --git a/hacks/munch.c b/hacks/munch.c new file mode 100644 index 00000000..2636375e --- /dev/null +++ b/hacks/munch.c @@ -0,0 +1,456 @@ +/* Munching Squares and Mismunch + * + * Portions copyright 1992-2008 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. + * + * Portions Copyright 1997, Tim Showalter + * + * Permission is granted to copy, modify, and use this as long + * as this notice remains intact. No warranties are expressed or + * implied. CMU Sucks. + * + * Portions Copyright 2004 Steven Hazel + * + * (The "mismunch" part). + * + * "munch.c" and "mismunch.c" merged by jwz, 29-Aug-2008. + * + * + * + *********************************************************************** + * + * HAKMEM + * + * MIT AI Memo 239, Feb. 29, 1972. + * Beeler, M., Gosper, R.W., and Schroeppel, R. + * + * http://www.inwap.com/pdp10/hbaker/hakmem/hacks.html#item146 + * + *********************************************************************** + * + * ITEM 146: MUNCHING SQUARES + * + * Another simple display program. It is thought that this was + * discovered by Jackson Wright on the RLE PDP-1 circa 1962. + * + * DATAI 2 + * ADDB 1,2 + * ROTC 2,-22 + * XOR 1,2 + * JRST .-4 + * + * 2=X, 3=Y. Try things like 1001002 in data switches. This also + * does * interesting things with operations other than XOR, and + * rotations * other than -22. (Try IOR; AND; TSC; FADR; FDV(!); + * ROT * -14, -9, -20, * ...) + * + * ITEM 147 (Schroeppel): + * + * Munching squares is just views of the graph Y = X XOR T for + * consecutive values of T = time. + * + * ITEM 147 (Cohen, Beeler): + * + * A modification to munching squares which reveals them in frozen + * states through opening and closing curtains: insert FADR 2,1 + * before the XOR. Try data switches = + * + * 4000,,4 1000,,2002 2000,,4 0,,1002 + * + * (Notation: ,,) + * Also try the FADR after the XOR, switches = 1001,,1. + * + *********************************************************************** + */ + +#include +#include "screenhack.h" + +typedef struct _muncher { + int mismunch; + int width; + int atX, atY; + int kX, kT, kY; + int grav; + XColor fgc; + int yshadow, xshadow; + int x, y, t; + int doom; + int done; +} muncher; + + +struct state { + Display *dpy; + Window window; + + GC gc; + int delay, simul, clear, xor; + int logminwidth, logmaxwidth; + int restart, window_width, window_height; + + int draw_n; /* number of squares before we have to clear */ + int draw_i; + int mismunch; + + muncher **munchers; +}; + + +/* + * dumb way to get # of digits in number. Probably faster than actually + * doing a log and a division, maybe. + */ +static int dumb_log_2(int k) +{ + int r = -1; + while (k > 0) { + k >>= 1; r++; + } + return r; +} + + +static void calc_logwidths (struct state *st) +{ + /* Choose a range of square sizes based on the window size. We want + a power of 2 for the square width or the munch doesn't fill up. + Also, if a square doesn't fit inside an area 20% smaller than the + window, it's too big. Mismunched squares that big make things + look too noisy. */ + + if (st->window_height < st->window_width) { + st->logmaxwidth = (int)dumb_log_2(st->window_height * 0.8); + } else { + st->logmaxwidth = (int)dumb_log_2(st->window_width * 0.8); + } + + if (st->logmaxwidth < 2) { + st->logmaxwidth = 2; + } + + /* we always want three sizes of squares */ + st->logminwidth = st->logmaxwidth - 2; + + if (st->logminwidth < 2) { + st->logminwidth = 2; + } +} + + + +static muncher *make_muncher (struct state *st) +{ + int logwidth; + XWindowAttributes xgwa; + muncher *m = (muncher *) malloc(sizeof(muncher)); + + XGetWindowAttributes(st->dpy, st->window, &xgwa); + + m->mismunch = st->mismunch; + + /* choose size -- power of two */ + logwidth = (st->logminwidth + + (random() % (1 + st->logmaxwidth - st->logminwidth))); + + m->width = 1 << logwidth; + + /* draw at this location */ + m->atX = (random() % (xgwa.width <= m->width ? 1 + : xgwa.width - m->width)); + m->atY = (random() % (xgwa.height <= m->width ? 1 + : xgwa.width - m->width)); + + /* wrap-around by these values; no need to % as we end up doing that + later anyway */ + m->kX = ((random() % 2) + ? (random() % m->width) : 0); + m->kT = ((random() % 2) + ? (random() % m->width) : 0); + m->kY = ((random() % 2) + ? (random() % m->width) : 0); + + /* set the gravity of the munch, or rather, which direction we draw + stuff in. */ + m->grav = random() % 2; + + /* I like this color scheme better than random colors. */ + switch (random() % 4) { + case 0: + m->fgc.red = random() % 65536; + m->fgc.blue = random() % 32768; + m->fgc.green = random() % 16384; + break; + + case 1: + m->fgc.red = 0; + m->fgc.blue = random() % 65536; + m->fgc.green = random() % 16384; + break; + + case 2: + m->fgc.red = random() % 8192; + m->fgc.blue = random() % 8192; + m->fgc.green = random() % 49152; + break; + + case 3: + m->fgc.red = random() % 65536; + m->fgc.green = m->fgc.red; + m->fgc.blue = m->fgc.red; + break; + } + + /* Sometimes draw a mostly-overlapping copy of the square. This + generates all kinds of neat blocky graphics when drawing in xor + mode. */ + if (!m->mismunch || (random() % 4)) { + m->xshadow = 0; + m->yshadow = 0; + } else { + m->xshadow = (random() % (m->width/3)) - (m->width/6); + m->yshadow = (random() % (m->width/3)) - (m->width/6); + } + + /* Start with a random y value -- this sort of controls the type of + deformities seen in the squares. */ + m->y = random() % 256; + + m->t = 0; + + /* + Doom each square to be aborted at some random point. + (When doom == (width - 1), the entire square will be drawn.) + */ + m->doom = (m->mismunch ? (random() % m->width) : (m->width - 1)); + m->done = 0; + + return m; +} + + +static void munch (struct state *st, muncher *m) +{ + int drawX, drawY; + XWindowAttributes xgwa; + + if (m->done) { + return; + } + + XGetWindowAttributes(st->dpy, st->window, &xgwa); + + if (!mono_p) { + /* XXX there are probably bugs with this. */ + if (XAllocColor(st->dpy, xgwa.colormap, &m->fgc)) { + XSetForeground(st->dpy, st->gc, m->fgc.pixel); + } + } + + /* Finally draw this pass of the munching error. */ + + for(m->x = 0; m->x < m->width; m->x++) { + /* figure out the next point */ + + /* + The ordinary Munching Squares calculation is: + m->y = ((m->x ^ ((m->t + m->kT) % m->width)) + m->kY) % m->width; + + We create some feedback by plugging in y in place of x, and + make a couple of values negative so that some parts of some + squares get drawn in the wrong place. + */ + if (m->mismunch) + m->y = ((-m->y ^ ((-m->t + m->kT) % m->width)) + m->kY) % m->width; + else + m->y = ((m->x ^ ((m->t + m->kT) % m->width)) + m->kY) % m->width; + + drawX = ((m->x + m->kX) % m->width) + m->atX; + drawY = (m->grav ? m->y + m->atY : m->atY + m->width - 1 - m->y); + + XDrawPoint(st->dpy, st->window, st->gc, drawX, drawY); + if ((m->xshadow != 0) || (m->yshadow != 0)) { + /* draw the corresponding shadow point */ + XDrawPoint(st->dpy, st->window, st->gc, drawX + m->xshadow, drawY + m->yshadow); + } + /* XXX may want to change this to XDrawPoints, + but it's fast enough without it for the moment. */ + + } + + m->t++; + if (m->t > m->doom) { + m->done = 1; + } +} + + +static void * +munch_init (Display *dpy, Window w) +{ + struct state *st = (struct state *) calloc (1, sizeof(*st)); + XWindowAttributes xgwa; + XGCValues gcv; + int i; + char *mm; + + st->dpy = dpy; + st->window = w; + st->restart = 0; + + /* get the dimensions of the window */ + XGetWindowAttributes(st->dpy, w, &xgwa); + + /* create the gc */ + gcv.foreground= get_pixel_resource(st->dpy, xgwa.colormap, + "foreground","Foreground"); + gcv.background= get_pixel_resource(st->dpy, xgwa.colormap, + "background","Background"); + + st->gc = XCreateGC(st->dpy, w, GCForeground|GCBackground, &gcv); + + st->delay = get_integer_resource(st->dpy, "delay", "Integer"); + if (st->delay < 0) st->delay = 0; + + st->simul = get_integer_resource(st->dpy, "simul", "Integer"); + if (st->simul < 1) st->simul = 1; + + st->clear = get_integer_resource(st->dpy, "clear", "Integer"); + if (st->clear < 0) st->clear = 0; + + st->xor = get_boolean_resource(st->dpy, "xor", "Boolean"); + + mm = get_string_resource (st->dpy, "mismunch", "Mismunch"); + if (!mm || !*mm || !strcmp(mm, "random")) + st->mismunch = random() & 1; + else + st->mismunch = get_boolean_resource (st->dpy, "mismunch", "Mismunch"); + + st->window_width = xgwa.width; + st->window_height = xgwa.height; + + calc_logwidths(st); + + /* always draw xor on mono. */ + if (mono_p || st->xor) { + XSetFunction(st->dpy, st->gc, GXxor); + } + + st->munchers = (muncher **) calloc(st->simul, sizeof(muncher *)); + for (i = 0; i < st->simul; i++) { + st->munchers[i] = make_muncher(st); + } + + return st; +} + +static unsigned long +munch_draw (Display *dpy, Window w, void *closure) +{ + struct state *st = (struct state *) closure; + int i; + + for (i = 0; i < 5; i++) { + + /* for (draw_i = 0; draw_i < simul; draw_i++) */ + { + munch(st, st->munchers[st->draw_i]); + + if (st->munchers[st->draw_i]->done) { + st->draw_n++; + + free(st->munchers[st->draw_i]); + st->munchers[st->draw_i] = make_muncher(st); + } + } + + st->draw_i++; + if (st->draw_i >= st->simul) { + int i = 0; + st->draw_i = 0; + if (st->restart || (st->clear && st->draw_n >= st->clear)) { + + char *mm = get_string_resource (st->dpy, "mismunch", "Mismunch"); + if (!mm || !*mm || !strcmp(mm, "random")) + st->mismunch = random() & 1; + + for (i = 0; i < st->simul; i++) { + free(st->munchers[i]); + st->munchers[i] = make_muncher(st); + } + + XClearWindow(st->dpy, w); + st->draw_n = 0; + st->restart = 0; + } + } + + } + + return st->delay; +} + + +static void +munch_reshape (Display *dpy, Window window, void *closure, + unsigned int w, unsigned int h) +{ + struct state *st = (struct state *) closure; + if (w != st->window_width || + h != st->window_height) { + st->window_width = w; + st->window_height = h; + calc_logwidths(st); + st->restart = 1; + st->draw_i = 0; + } +} + +static Bool +munch_event (Display *dpy, Window window, void *closure, XEvent *event) +{ + return False; +} + +static void +munch_free (Display *dpy, Window window, void *closure) +{ + struct state *st = (struct state *) closure; + free (st); +} + + +static const char *munch_defaults [] = { + ".background: black", + ".foreground: white", + "*fpsSolid: true", + "*delay: 10000", + "*mismunch: random", + "*simul: 5", + "*clear: 65", + "*xor: True", + 0 +}; + +static XrmOptionDescRec munch_options [] = { + { "-delay", ".delay", XrmoptionSepArg, 0 }, + { "-simul", ".simul", XrmoptionSepArg, 0 }, + { "-clear", ".clear", XrmoptionSepArg, "true" }, + { "-xor", ".xor", XrmoptionNoArg, "true" }, + { "-no-xor", ".xor", XrmoptionNoArg, "false" }, + { "-classic", ".mismunch", XrmoptionNoArg, "false" }, + { "-mismunch", ".mismunch", XrmoptionNoArg, "true" }, + { "-random", ".mismunch", XrmoptionNoArg, "random" }, + { 0, 0, 0, 0 } +}; + + +XSCREENSAVER_MODULE ("Munch", munch) diff --git a/hacks/munch.man b/hacks/munch.man new file mode 100644 index 00000000..d5423c98 --- /dev/null +++ b/hacks/munch.man @@ -0,0 +1,153 @@ +.de EX \"Begin example +.ne 5 +.if n .sp 1 +.if t .sp .5 +.nf +.in +.5i +.. +.de EE +.fi +.in -.5i +.if n .sp 1 +.if t .sp .5 +.. +.TH XScreenSaver 1 "29-Aug-2008" "X Version 11" +.SH NAME +munch - munching squares +.SH SYNOPSIS +.B munch +[\-display \fIhost:display.screen\fP] [\-foreground \fIcolor\fP] +[\-background \fIcolor\fP] [\-window] [\-root] [\-mono] [\-install] +[\-visual \fIvisual\fP] [\-delay \fIusecs\fP] [\-xor] [\-noxor] +[\-clear \fInumber\fP] [\-simul \fInumber\fP] +[\-classic | \-mismunch | \-random] +[\-fps] +.SH DESCRIPTION +The +.I munch +program performs the munching squares hack. It picks square +size, position, and gravity randomly. It also displays a +creatively broken misimplementation of the classic algorithm. + +The munching squares hack consists of drawing Y = X XOR T for a range of X +and T over and over until all the possible combinations of X and T have +come up. It was reportedly discovered by Jackson Wright in 1962 and took 5 +instructions of PDP-6 code. +.SH OPTIONS +.I munch +accepts the following options: +.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 \-mono +If on a color display, pretend we're on a monochrome display. +.TP 8 +.B \-install +Install a private colormap for the window. +.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 \-delay \fIusecs\fP +The delay between steps of the animation, in microseconds. Default: 2500. +.TP 8 +.B \-xor +Use the XOR drawing function. This is the default. +.TP 8 +.B \-no\-xor +Don't use the XOR drawing function. +.TP 8 +.B \-clear \fInumber\fP +Number of squares to misdraw before clearing the display. Default: 65. +.TP 8 +.B \-simul \fInumber\fP +Number of squares to misdraw simultaneously. Default: 5. +.TP 8 +.B \-classic +Draw classic munching squares only. +.TP 8 +.B \-mismunch +Draw "mismunch" only. +.TP 8 +.B \-random +Do one or the other. +.TP 8 +.B \-fps +Display the current frame rate and CPU load. +.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), +.RS 0 +.BR http://www.inwap.com/pdp10/hbaker/hakmem/hakmem.html +.SH HISTORY +HAKMEM: MIT AI Memo 239, Feb. 29, 1972. +.RS 8 +Beeler, M., Gosper, R.W., and Schroeppel, R. + +"Unless otherwise stated, all computer programs are in PDP-6/10 +assembly language." +.TP 4 +ITEM 146: MUNCHING SQUARES + +Another simple display program. It is thought that this was discovered by +Jackson Wright on the RLE PDP-1 circa 1962. + +.EX + DATAI 2 + ADDB 1,2 + ROTC 2,-22 + XOR 1,2 + JRST .-4 +.EE +.RS 4 +2=X, 3=Y. Try things like 1001002 in data switches. This also does +interesting things with operations other than XOR, and rotations other +than -22. (Try IOR; AND; TSC; FADR; FDV(!); ROT -14, -9, -20, ...) +.RE +.TP 4 +ITEM 147 (Schroeppel): + +Munching squares is just views of the graph Y = X XOR T for consecutive +values of T = time. +.TP 4 +ITEM 148 (Cohen, Beeler): + +A modification to munching squares which reveals them in frozen states +through opening and closing curtains: insert FADR 2,1 before the XOR. Try +data switches = + +.EX + 4000,,4 1000,,2002 2000,,4 0,,1002 +.EE +.RS 4 +(Notation: ,,) +.RS 0 +Also try the FADR after the XOR, switches = 1001,,1. +.SH COPYRIGHT +Copyright 1997 Tim Showalter. +.RS 0 +Copyright 2004 Steven Hazel. +.RS 0 +Copyright 1992-2008 Jamie Zawinski. +.PP +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. diff --git a/hacks/munge-ad.pl b/hacks/munge-ad.pl new file mode 100755 index 00000000..77232143 --- /dev/null +++ b/hacks/munge-ad.pl @@ -0,0 +1,243 @@ +#!/usr/bin/perl -w +# Copyright © 2008-2012 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. +# +# This updates driver/XScreenSaver.ad.in with the current list of savers. +# +# Created: 3-Aug-2008. + +require 5; +use diagnostics; +use strict; + +my $progname = $0; $progname =~ s@.*/@@g; +my $version = q{ $Revision: 1.8 $ }; $version =~ s/^[^\d]+([\d.]+).*/$1/; + +my $verbose = 0; + +# 1 means disabled: marked with "-" by default in the .ad file. +# 2 means retired: not mentioned in .ad at all. +# +my %disable = ( + 'abstractile' => 1, + 'antinspect' => 1, + 'antmaze' => 1, + 'antspotlight' => 1, + 'braid' => 1, + 'crystal' => 1, + 'demon' => 1, + 'dnalogo' => 1, + 'fadeplot' => 1, + 'glblur' => 1, + 'glplanet' => 1, + 'glslideshow' => 1, + 'jigglypuff' => 1, + 'juggle' => 2, + 'kaleidescope' => 1, + 'lcdscrub' => 1, + 'loop' => 1, + 'mismunch' => 2, + 'nerverot' => 1, + 'noseguy' => 1, + 'polyominoes' => 1, + 'providence' => 1, + 'pyro' => 1, + 'rdbomb' => 2, # alternate name + 'rocks' => 1, + 'sballs' => 1, + 'sierpinski' => 1, + 'thornbird' => 1, + 'vidwhacker' => 1, + 'webcollage' => 1, + 'xsublim' => 2, + ); + + +# Parse the RETIRED_EXES variable from the Makefiles to populate %disable. +# +sub parse_makefiles() { + foreach my $mf ( "Makefile.in", "glx/Makefile.in" ) { + my $body = ''; + local *IN; + open (IN, "<$mf") || error ("$mf: $!"); + while () { $body .= $_; } + close IN; + + $body =~ s/\\\n//gs; + my ($var) = ($body =~ m/^RETIRED_EXES\s*=\s*(.*)$/mi); + my ($var2) = ($body =~ m/^RETIRED_GL_EXES\s*=\s*(.*)$/mi); + error ("no RETIRED_EXES in $mf") unless $var; + $var .= " $var2" if $var2; + foreach my $hack (split (/\s+/, $var)) { + $disable{$hack} = 2; + } + } +} + + +sub munge_ad($) { + my ($file) = @_; + + parse_makefiles(); + + my $body = ''; + local *IN; + open (IN, "<$file") || error ("$file: $!"); + while () { $body .= $_; } + close IN; + my $obody = $body; + + my ($top, $mid, $bot) = ($body =~ m/^(.*?\n)(\*hacks\..*?\n)(\n.*)$/s); + + my $mid2 = ''; + + my %hacks; + + # Update the "*hacks.foo.name" section of the file based on the contents + # of config/*.xml. + # + my $dir = $file; + $dir =~ s@/[^/]*$@@s; + my @counts = (0,0,0,0,0,0,0,0,0,0); + foreach my $xml (sort (glob ("$dir/../hacks/config/*.xml"))) { + my $b = ''; + open (IN, "<$xml") || error ("$xml: $!"); + while () { $b .= $_; } + close IN; + my ($name) = ($b =~ m@]*\b_label=\"([^<>\"]+)\"@s); + error ("$xml: no name") unless $name; + + my $name2 = lc($name); + $name2 =~ s/^((x|gl)?[a-z])/\U$1/s; # what prefs.c (make_hack_name) does + + $xml =~ s@^.*/([^/]+)\.xml$@$1@s; + if ($name ne $name2) { + my $s = sprintf("*hacks.%s.name:", $xml); + $mid2 .= sprintf ("%-28s%s\n", $s, $name); + $counts[9]++; + } + + # Grab the year. + my ($year) = + ($b =~ m/<_description>.*Written by.*?;\s+(19[6-9]\d|20\d\d)\b/si); + error ("no year in $xml.xml") unless $year; + $hacks{$xml} = $year; + } + + # Splice in new names. + $body = $top . $mid2 . $bot; + + + # Replace the "programs" section. + # Sort hacks by creation date, but put the OpenGL ones at the end. + # + my $segregate_p = 0; # whether to put the GL hacks at the end. + my $xhacks = ''; + my $ghacks = ''; + foreach my $hack (sort { $hacks{$a} == $hacks{$b} + ? $a cmp $b + : $hacks{$a} <=> $hacks{$b}} + (keys(%hacks))) { + my $cmd = "$hack -root"; + my $ts = (length($cmd) / 8) * 8; + while ($ts < 40) { $cmd .= "\t"; $ts += 8; } + + my $dis = $disable{$hack} || 0; + + my $glp; + my $glep = ($hack eq 'extrusion'); + if (-f "$hack.c" || -f "$hack") { $glp = 0; } + elsif (-f "glx/$hack.c") { $glp = 1; } + elsif ($hack eq 'companioncube') { $glp = 1; } # kludge + elsif ($dis != 2) { error ("is $hack X or GL?"); } + + $counts[($disable{$hack} || 0)]++; + if ($glp) { + $counts[6+($disable{$hack} || 0)]++; + } else { + $counts[3+($disable{$hack} || 0)]++; + } + + next if ($dis == 2); + + $dis = ($dis ? '-' : ''); + my $vis = ($glp + ? (($dis ? '' : $glep ? '@GLE_KLUDGE@' : '@GL_KLUDGE@') . + ' GL: ') + : ''); + $cmd = "$dis$vis\t\t\t\t$cmd \\n\\\n"; + + if ($glp) { + ($segregate_p ? $ghacks : $xhacks) .= $cmd; + } else { + $xhacks .= $cmd; + } + } + + # Splice in new programs list. + # + $mid2 = ($xhacks . + ($segregate_p ? "\t\t\t\t\t\t\t\t\t \\\n" : "") . + $ghacks); + $mid2 =~ s@\\$@@s; + ($top, $mid, $bot) = + ($body =~ m/^(.*?\n\*programs:\s+\\\n)(.*?\n)(\n.*)$/s); + error ("unparsable") unless $mid; + $body = $top . $mid2 . $bot; + + print STDERR "$progname: " . + "Total: $counts[0]+$counts[1]+$counts[2]; " . + "X11: $counts[3]+$counts[4]+$counts[5]; " . + "GL: $counts[6]+$counts[7]+$counts[8]; " . + "Names: $counts[9]\n" + if ($verbose); + + # Write file if changed. + # + if ($body ne $obody) { + local *OUT; + open (OUT, ">$file") || error ("$file: $!"); + print OUT $body; + close OUT; + print STDERR "$progname: wrote $file\n"; + } elsif ($verbose) { + print STDERR "$progname: $file unchanged\n"; + } +} + + +sub error($) { + my ($err) = @_; + print STDERR "$progname: $err\n"; + exit 1; +} + +sub usage() { + print STDERR "usage: $progname [--verbose] ad-file\n"; + exit 1; +} + +sub main() { + my $file; + while ($#ARGV >= 0) { + $_ = shift @ARGV; + if (m/^--?verbose$/) { $verbose++; } + elsif (m/^-v+$/) { $verbose += length($_)-1; } + elsif (m/^-./) { usage; } + elsif (!$file) { $file = $_; } + else { usage; } + } + + usage unless ($file); + munge_ad ($file); +} + +main(); +exit 0; diff --git a/hacks/nerverot.c b/hacks/nerverot.c new file mode 100644 index 00000000..d0de73c9 --- /dev/null +++ b/hacks/nerverot.c @@ -0,0 +1,1350 @@ +/* nerverot, nervous rotation of random thingies, v1.4 + * by Dan Bornstein, danfuzz@milk.com + * Copyright (c) 2000-2001 Dan Bornstein. All rights reserved. + * + * 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. + * + * The goal of this screensaver is to be interesting and compelling to + * watch, yet induce a state of nervous edginess in the viewer. + * + * See the included man page for more details. + */ + +#include +#include "screenhack.h" + +#define FLOAT double + +/* random float in the range (-1..1) */ +#define RAND_FLOAT_PM1 \ + (((FLOAT) ((random() >> 8) & 0xffff)) / ((FLOAT) 0x10000) * 2 - 1) + +/* random float in the range (0..1) */ +#define RAND_FLOAT_01 \ + (((FLOAT) ((random() >> 8) & 0xffff)) / ((FLOAT) 0x10000)) + + +/* structure of the model */ + +/* each point-like thingy to draw is represented as a blot */ +typedef struct blot_s +{ + FLOAT x; /* 3d x position (-1..1) */ + FLOAT y; /* 3d y position (-1..1) */ + FLOAT z; /* 3d z position (-1..1) */ + FLOAT xoff[3][3]; /* display x offset per drawn point (-1..1) */ + FLOAT yoff[3][3]; /* display x offset per drawn point (-1..1) */ +} Blot; + +/* each drawn line is represented as a LineSegment */ +typedef struct linesegment_s +{ + GC gc; + int x1; + int y1; + int x2; + int y2; +} LineSegment; + +/* each blot draws as a simple 2d shape with each coordinate as an int + * in the range (-1..1); this is the base shape */ +static const XPoint blotShape[] = { { 0, 0}, { 1, 0}, { 1, 1}, + { 0, 1}, {-1, 1}, {-1, 0}, + {-1,-1}, { 0,-1}, { 1,-1} }; +static int blotShapeCount = sizeof (blotShape) / sizeof (XPoint); + + + + + +struct state { + Display *dpy; + Window window; + + int requestedBlotCount; /* number of blots */ + int delay; /* delay (usec) between iterations */ + int maxIters; /* max iterations per model */ + FLOAT nervousness; /* variability of xoff/yoff per iteration (0..1) */ + FLOAT maxNerveRadius; /* max nervousness radius (0..1) */ + FLOAT eventChance; /* chance per iteration that an event will happen */ + FLOAT iterAmt; /* fraction (0..1) towards rotation target or scale target to move each * iteration */ + FLOAT minScale; /* min and max scale for drawing, as fraction of baseScale */ + FLOAT maxScale; + int minRadius; /* min and max radius of blot drawing */ + int maxRadius; + int colorCount; /* the number of colors to use */ + + int lineWidth; /* width of lines */ + + Bool doubleBuffer; /* whether or not to do double-buffering */ + + + int baseScale; /* base scale factor for drawing, calculated as max(screenWidth,screenHeight) */ + + + int windowWidth; /* width and height of the window */ + int windowHeight; + + int centerX; /* center position of the window */ + int centerY; + + Drawable drawable; /* the thing to directly draw on */ + GC *gcs; /* array of gcs, one per color used */ + + Blot *blots; /* array of the blots in the model */ + int blotCount; + + int segCount; /* two arrays of line segments; one for the ones to erase, and one for the ones to draw */ + + LineSegment *segsToDraw; + LineSegment *segsToErase; + + + FLOAT xRot; /* current rotation values per axis, scale factor, and light position */ + + FLOAT yRot; + FLOAT zRot; + FLOAT curScale; + FLOAT lightX; + FLOAT lightY; + FLOAT lightZ; + + FLOAT xRotTarget; /* target rotation values per axis, scale factor, and light position */ + + FLOAT yRotTarget; + FLOAT zRotTarget; + FLOAT scaleTarget; + FLOAT lightXTarget; + FLOAT lightYTarget; + FLOAT lightZTarget; + + int centerXOff; /* current absolute offsets from the center */ + int centerYOff; + + int itersTillNext; /* iterations until the model changes */ +}; + + +/* + * generic blot setup and manipulation + */ + +/* initialize a blot with the given coordinates and random display offsets */ +static void initBlot (Blot *b, FLOAT x, FLOAT y, FLOAT z) +{ + int i, j; + + b->x = x; + b->y = y; + b->z = z; + + for (i = 0; i < 3; i++) + { + for (j = 0; j < 3; j++) + { + b->xoff[i][j] = RAND_FLOAT_PM1; + b->yoff[i][j] = RAND_FLOAT_PM1; + } + } +} + +/* scale the blots to have a max distance of 1 from the center */ +static void scaleBlotsToRadius1 (struct state *st) +{ + FLOAT max = 0.0; + int n; + + for (n = 0; n < st->blotCount; n++) + { + FLOAT distSquare = + st->blots[n].x * st->blots[n].x + + st->blots[n].y * st->blots[n].y + + st->blots[n].z * st->blots[n].z; + if (distSquare > max) + { + max = distSquare; + } + } + + if (max == 0.0) + { + return; + } + + max = sqrt (max); + + for (n = 0; n < st->blotCount; n++) + { + st->blots[n].x /= max; + st->blots[n].y /= max; + st->blots[n].z /= max; + } +} + +/* randomly reorder the blots */ +static void randomlyReorderBlots (struct state *st) +{ + int n; + + for (n = 0; n < st->blotCount; n++) + { + int m = RAND_FLOAT_01 * (st->blotCount - n) + n; + Blot tmpBlot = st->blots[n]; + st->blots[n] = st->blots[m]; + st->blots[m] = tmpBlot; + } +} + +/* randomly rotate the blots around the origin */ +static void randomlyRotateBlots (struct state *st) +{ + int n; + + /* random amounts to rotate about each axis */ + FLOAT xRot = RAND_FLOAT_PM1 * M_PI; + FLOAT yRot = RAND_FLOAT_PM1 * M_PI; + FLOAT zRot = RAND_FLOAT_PM1 * M_PI; + + /* rotation factors */ + FLOAT sinX = sin (xRot); + FLOAT cosX = cos (xRot); + FLOAT sinY = sin (yRot); + FLOAT cosY = cos (yRot); + FLOAT sinZ = sin (zRot); + FLOAT cosZ = cos (zRot); + + for (n = 0; n < st->blotCount; n++) + { + FLOAT x1 = st->blots[n].x; + FLOAT y1 = st->blots[n].y; + FLOAT z1 = st->blots[n].z; + FLOAT x2, y2, z2; + + /* rotate on z axis */ + x2 = x1 * cosZ - y1 * sinZ; + y2 = x1 * sinZ + y1 * cosZ; + z2 = z1; + + /* rotate on x axis */ + y1 = y2 * cosX - z2 * sinX; + z1 = y2 * sinX + z2 * cosX; + x1 = x2; + + /* rotate on y axis */ + z2 = z1 * cosY - x1 * sinY; + x2 = z1 * sinY + x1 * cosY; + y2 = y1; + + st->blots[n].x = x2; + st->blots[n].y = y2; + st->blots[n].z = z2; + } +} + + + +/* + * blot configurations + */ + +/* set up the initial array of blots to be a at the edge of a sphere */ +static void setupBlotsSphere (struct state *st) +{ + int n; + + st->blotCount = st->requestedBlotCount; + st->blots = calloc (sizeof (Blot), st->blotCount); + + for (n = 0; n < st->blotCount; n++) + { + /* pick a spot, but reject if its radius is < 0.2 or > 1 to + * avoid scaling problems */ + FLOAT x, y, z, radius; + + for (;;) + { + x = RAND_FLOAT_PM1; + y = RAND_FLOAT_PM1; + z = RAND_FLOAT_PM1; + + radius = sqrt (x * x + y * y + z * z); + if ((radius >= 0.2) && (radius <= 1.0)) + { + break; + } + } + + x /= radius; + y /= radius; + z /= radius; + + initBlot (&st->blots[n], x, y, z); + } +} + +/* set up the initial array of blots to be a simple cube */ +static void setupBlotsCube (struct state *st) +{ + int i, j, k, n; + + /* derive blotsPerEdge from blotCount, but then do the reverse + * since roundoff may have changed blotCount */ + int blotsPerEdge = ((st->requestedBlotCount - 8) / 12) + 2; + FLOAT distBetween; + + if (blotsPerEdge < 2) + { + blotsPerEdge = 2; + } + + distBetween = 2.0 / (blotsPerEdge - 1.0); + + st->blotCount = 8 + (blotsPerEdge - 2) * 12; + st->blots = calloc (sizeof (Blot), st->blotCount); + n = 0; + + /* define the corners */ + for (i = -1; i < 2; i += 2) + { + for (j = -1; j < 2; j += 2) + { + for (k = -1; k < 2; k += 2) + { + initBlot (&st->blots[n], i, j, k); + n++; + } + } + } + + /* define the edges */ + for (i = 1; i < (blotsPerEdge - 1); i++) + { + FLOAT varEdge = distBetween * i - 1; + initBlot (&st->blots[n++], varEdge, -1, -1); + initBlot (&st->blots[n++], varEdge, 1, -1); + initBlot (&st->blots[n++], varEdge, -1, 1); + initBlot (&st->blots[n++], varEdge, 1, 1); + initBlot (&st->blots[n++], -1, varEdge, -1); + initBlot (&st->blots[n++], 1, varEdge, -1); + initBlot (&st->blots[n++], -1, varEdge, 1); + initBlot (&st->blots[n++], 1, varEdge, 1); + initBlot (&st->blots[n++], -1, -1, varEdge); + initBlot (&st->blots[n++], 1, -1, varEdge); + initBlot (&st->blots[n++], -1, 1, varEdge); + initBlot (&st->blots[n++], 1, 1, varEdge); + } + + scaleBlotsToRadius1 (st); + randomlyReorderBlots (st); + randomlyRotateBlots (st); +} + +/* set up the initial array of blots to be a cylinder */ +static void setupBlotsCylinder (struct state *st) +{ + int i, j, n; + FLOAT distBetween; + + /* derive blotsPerEdge and blotsPerRing from blotCount, but then do the + * reverse since roundoff may have changed blotCount */ + FLOAT reqRoot = sqrt ((FLOAT) st->requestedBlotCount); + int blotsPerRing = ceil (RAND_FLOAT_PM1 * reqRoot) / 2 + reqRoot; + int blotsPerEdge = st->requestedBlotCount / blotsPerRing; + + if (blotsPerRing < 2) + { + blotsPerRing = 2; + } + + if (blotsPerEdge < 2) + { + blotsPerEdge = 2; + } + + distBetween = 2.0 / (blotsPerEdge - 1); + + st->blotCount = blotsPerEdge * blotsPerRing; + st->blots = calloc (sizeof (Blot), st->blotCount); + n = 0; + + /* define the edges */ + for (i = 0; i < blotsPerRing; i++) + { + FLOAT x = sin (2 * M_PI / blotsPerRing * i); + FLOAT y = cos (2 * M_PI / blotsPerRing * i); + for (j = 0; j < blotsPerEdge; j++) + { + initBlot (&st->blots[n], x, y, j * distBetween - 1); + n++; + } + } + + scaleBlotsToRadius1 (st); + randomlyReorderBlots (st); + randomlyRotateBlots (st); +} + +/* set up the initial array of blots to be a squiggle */ +static void setupBlotsSquiggle (struct state *st) +{ + FLOAT x, y, z, xv, yv, zv, len; + int minCoor, maxCoor; + int n; + + st->blotCount = st->requestedBlotCount; + st->blots = calloc (sizeof (Blot), st->blotCount); + + maxCoor = (int) (RAND_FLOAT_01 * 5) + 1; + minCoor = -maxCoor; + + x = RAND_FLOAT_PM1; + y = RAND_FLOAT_PM1; + z = RAND_FLOAT_PM1; + + xv = RAND_FLOAT_PM1; + yv = RAND_FLOAT_PM1; + zv = RAND_FLOAT_PM1; + len = sqrt (xv * xv + yv * yv + zv * zv); + xv /= len; + yv /= len; + zv /= len; + + for (n = 0; n < st->blotCount; n++) + { + FLOAT newx, newy, newz; + initBlot (&st->blots[n], x, y, z); + + for (;;) + { + xv += RAND_FLOAT_PM1 * 0.1; + yv += RAND_FLOAT_PM1 * 0.1; + zv += RAND_FLOAT_PM1 * 0.1; + len = sqrt (xv * xv + yv * yv + zv * zv); + xv /= len; + yv /= len; + zv /= len; + + newx = x + xv * 0.1; + newy = y + yv * 0.1; + newz = z + zv * 0.1; + + if ( (newx >= minCoor) && (newx <= maxCoor) + && (newy >= minCoor) && (newy <= maxCoor) + && (newz >= minCoor) && (newz <= maxCoor)) + { + break; + } + } + + x = newx; + y = newy; + z = newz; + } + + scaleBlotsToRadius1 (st); + randomlyReorderBlots (st); +} + +/* set up the initial array of blots to be near the corners of a + * cube, distributed slightly */ +static void setupBlotsCubeCorners (struct state *st) +{ + int n; + + st->blotCount = st->requestedBlotCount; + st->blots = calloc (sizeof (Blot), st->blotCount); + + for (n = 0; n < st->blotCount; n++) + { + FLOAT x = rint (RAND_FLOAT_01) * 2 - 1; + FLOAT y = rint (RAND_FLOAT_01) * 2 - 1; + FLOAT z = rint (RAND_FLOAT_01) * 2 - 1; + + x += RAND_FLOAT_PM1 * 0.3; + y += RAND_FLOAT_PM1 * 0.3; + z += RAND_FLOAT_PM1 * 0.3; + + initBlot (&st->blots[n], x, y, z); + } + + scaleBlotsToRadius1 (st); + randomlyRotateBlots (st); +} + +/* set up the initial array of blots to be randomly distributed + * on the surface of a tetrahedron */ +static void setupBlotsTetrahedron (struct state *st) +{ + /* table of corners of the tetrahedron */ + static const FLOAT cor[4][3] = { { 0.0, 1.0, 0.0 }, + { -0.75, -0.5, -0.433013 }, + { 0.0, -0.5, 0.866025 }, + { 0.75, -0.5, -0.433013 } }; + + int n, c; + + /* derive blotsPerSurface from blotCount, but then do the reverse + * since roundoff may have changed blotCount */ + int blotsPerSurface = st->requestedBlotCount / 4; + + st->blotCount = blotsPerSurface * 4; + st->blots = calloc (sizeof (Blot), st->blotCount); + + for (n = 0; n < st->blotCount; n += 4) + { + /* pick a random point on a unit right triangle */ + FLOAT rawx = RAND_FLOAT_01; + FLOAT rawy = RAND_FLOAT_01; + + if ((rawx + rawy) > 1) + { + /* swap coords into place */ + FLOAT t = 1.0 - rawx; + rawx = 1.0 - rawy; + rawy = t; + } + + /* translate the point to be on each of the surfaces */ + for (c = 0; c < 4; c++) + { + FLOAT x, y, z; + + int c1 = (c + 1) % 4; + int c2 = (c + 2) % 4; + + x = (cor[c1][0] - cor[c][0]) * rawx + + (cor[c2][0] - cor[c][0]) * rawy + + cor[c][0]; + + y = (cor[c1][1] - cor[c][1]) * rawx + + (cor[c2][1] - cor[c][1]) * rawy + + cor[c][1]; + + z = (cor[c1][2] - cor[c][2]) * rawx + + (cor[c2][2] - cor[c][2]) * rawy + + cor[c][2]; + + initBlot (&st->blots[n + c], x, y, z); + } + } + + randomlyRotateBlots (st); +} + +/* set up the initial array of blots to be an almost-evenly-distributed + * square sheet */ +static void setupBlotsSheet (struct state *st) +{ + int x, y; + + int blotsPerDimension = floor (sqrt (st->requestedBlotCount)); + FLOAT spaceBetween; + + if (blotsPerDimension < 2) + { + blotsPerDimension = 2; + } + + spaceBetween = 2.0 / (blotsPerDimension - 1); + + st->blotCount = blotsPerDimension * blotsPerDimension; + st->blots = calloc (sizeof (Blot), st->blotCount); + + for (x = 0; x < blotsPerDimension; x++) + { + for (y = 0; y < blotsPerDimension; y++) + { + FLOAT x1 = x * spaceBetween - 1.0; + FLOAT y1 = y * spaceBetween - 1.0; + FLOAT z1 = 0.0; + + x1 += RAND_FLOAT_PM1 * spaceBetween / 3; + y1 += RAND_FLOAT_PM1 * spaceBetween / 3; + z1 += RAND_FLOAT_PM1 * spaceBetween / 2; + + initBlot (&st->blots[x + y * blotsPerDimension], x1, y1, z1); + } + } + + scaleBlotsToRadius1 (st); + randomlyReorderBlots (st); + randomlyRotateBlots (st); +} + +/* set up the initial array of blots to be a swirlycone */ +static void setupBlotsSwirlyCone (struct state *st) +{ + FLOAT radSpace = 1.0 / (st->requestedBlotCount - 1); + FLOAT zSpace = radSpace * 2; + FLOAT rotAmt = RAND_FLOAT_PM1 * M_PI / 10; + + int n; + FLOAT rot = 0.0; + + st->blotCount = st->requestedBlotCount; + st->blots = calloc (sizeof (Blot), st->blotCount); + + for (n = 0; n < st->blotCount; n++) + { + FLOAT radius = n * radSpace; + FLOAT x = cos (rot) * radius; + FLOAT y = sin (rot) * radius; + FLOAT z = n * zSpace - 1.0; + + rot += rotAmt; + initBlot (&st->blots[n], x, y, z); + } + + scaleBlotsToRadius1 (st); + randomlyReorderBlots (st); + randomlyRotateBlots (st); +} + +/* forward declaration for recursive use immediately below */ +static void setupBlots (struct state *st); + +/* set up the blots to be two of the other choices, placed next to + * each other */ +static void setupBlotsDuo (struct state *st) +{ + int origRequest = st->requestedBlotCount; + FLOAT tx, ty, tz, radius; + Blot *blots1, *blots2; + int count1, count2; + int n; + + if (st->requestedBlotCount < 15) + { + /* special case bottom-out */ + setupBlotsSphere (st); + return; + } + + tx = RAND_FLOAT_PM1; + ty = RAND_FLOAT_PM1; + tz = RAND_FLOAT_PM1; + radius = sqrt (tx * tx + ty * ty + tz * tz); + tx /= radius; + ty /= radius; + tz /= radius; + + /* recursive call to setup set 1 */ + st->requestedBlotCount = origRequest / 2; + setupBlots (st); + + if (st->blotCount >= origRequest) + { + /* return immediately if this satisfies the original count request */ + st->requestedBlotCount = origRequest; + return; + } + + blots1 = st->blots; + count1 = st->blotCount; + st->blots = NULL; + st->blotCount = 0; + + /* translate to new position */ + for (n = 0; n < count1; n++) + { + blots1[n].x += tx; + blots1[n].y += ty; + blots1[n].z += tz; + } + + /* recursive call to setup set 2 */ + st->requestedBlotCount = origRequest - count1; + setupBlots (st); + blots2 = st->blots; + count2 = st->blotCount; + + /* translate to new position */ + for (n = 0; n < count2; n++) + { + blots2[n].x -= tx; + blots2[n].y -= ty; + blots2[n].z -= tz; + } + + /* combine the two arrays */ + st->blotCount = count1 + count2; + st->blots = calloc (sizeof (Blot), st->blotCount); + memcpy (&st->blots[0], blots1, sizeof (Blot) * count1); + memcpy (&st->blots[count1], blots2, sizeof (Blot) * count2); + free (blots1); + free (blots2); + + scaleBlotsToRadius1 (st); + randomlyReorderBlots (st); + + /* restore the original requested count, for future iterations */ + st->requestedBlotCount = origRequest; +} + + + +/* + * main blot setup + */ + +/* free the blots, in preparation for a new shape */ +static void freeBlots (struct state *st) +{ + if (st->blots != NULL) + { + free (st->blots); + st->blots = NULL; + } + + if (st->segsToErase != NULL) + { + free (st->segsToErase); + st->segsToErase = NULL; + } + + if (st->segsToDraw != NULL) + { + free (st->segsToDraw); + st->segsToDraw = NULL; + } +} + +/* set up the initial arrays of blots */ +static void setupBlots (struct state *st) +{ + int which = RAND_FLOAT_01 * 11; + + freeBlots (st); + + switch (which) + { + case 0: + setupBlotsCube (st); + break; + case 1: + setupBlotsSphere (st); + break; + case 2: + setupBlotsCylinder (st); + break; + case 3: + setupBlotsSquiggle (st); + break; + case 4: + setupBlotsCubeCorners (st); + break; + case 5: + setupBlotsTetrahedron (st); + break; + case 6: + setupBlotsSheet (st); + break; + case 7: + setupBlotsSwirlyCone (st); + break; + case 8: + case 9: + case 10: + setupBlotsDuo (st); + break; + } +} + +/* set up the segments arrays */ +static void setupSegs (struct state *st) +{ + /* there are blotShapeCount - 1 line segments per blot */ + st->segCount = st->blotCount * (blotShapeCount - 1); + st->segsToErase = calloc (sizeof (LineSegment), st->segCount); + st->segsToDraw = calloc (sizeof (LineSegment), st->segCount); +} + + + +/* + * color setup stuff + */ + +/* set up the colormap */ +static void setupColormap (struct state *st, XWindowAttributes *xgwa) +{ + int n; + XGCValues gcv; + XColor *colors = (XColor *) calloc (sizeof (XColor), st->colorCount + 1); + + unsigned short r, g, b; + int h1, h2; + double s1, s2, v1, v2; + + r = RAND_FLOAT_01 * 0x10000; + g = RAND_FLOAT_01 * 0x10000; + b = RAND_FLOAT_01 * 0x10000; + rgb_to_hsv (r, g, b, &h1, &s1, &v1); + v1 = 1.0; + s1 = 1.0; + + r = RAND_FLOAT_01 * 0x10000; + g = RAND_FLOAT_01 * 0x10000; + b = RAND_FLOAT_01 * 0x10000; + rgb_to_hsv (r, g, b, &h2, &s2, &v2); + s2 = 0.7; + v2 = 0.7; + + colors[0].pixel = get_pixel_resource (st->dpy, xgwa->colormap, + "background", "Background"); + + make_color_ramp (st->dpy, xgwa->colormap, h1, s1, v1, h2, s2, v2, + colors + 1, &st->colorCount, False, True, False); + + if (st->colorCount < 1) + { + fprintf (stderr, "%s: couldn't allocate any colors\n", progname); + exit (-1); + } + + st->gcs = (GC *) calloc (sizeof (GC), st->colorCount + 1); + + for (n = 0; n <= st->colorCount; n++) + { + gcv.foreground = colors[n].pixel; + gcv.line_width = st->lineWidth; + st->gcs[n] = XCreateGC (st->dpy, st->window, GCForeground | GCLineWidth, &gcv); + } + + free (colors); +} + + + +/* + * overall setup stuff + */ + +/* set up the system */ +static void setup (struct state *st) +{ + XWindowAttributes xgwa; + + XGetWindowAttributes (st->dpy, st->window, &xgwa); + + st->windowWidth = xgwa.width; + st->windowHeight = xgwa.height; + st->centerX = st->windowWidth / 2; + st->centerY = st->windowHeight / 2; + st->baseScale = (xgwa.height < xgwa.width) ? xgwa.height : xgwa.width; + + if (st->doubleBuffer) + { + st->drawable = XCreatePixmap (st->dpy, st->window, xgwa.width, xgwa.height, + xgwa.depth); + } + else + { + st->drawable = st->window; + } + + setupColormap (st, &xgwa); + setupBlots (st); + setupSegs (st); + + /* set up the initial rotation, scale, and light values as random, but + * with the targets equal to where it is */ + st->xRot = st->xRotTarget = RAND_FLOAT_01 * M_PI; + st->yRot = st->yRotTarget = RAND_FLOAT_01 * M_PI; + st->zRot = st->zRotTarget = RAND_FLOAT_01 * M_PI; + st->curScale = st->scaleTarget = RAND_FLOAT_01 * (st->maxScale - st->minScale) + st->minScale; + st->lightX = st->lightXTarget = RAND_FLOAT_PM1; + st->lightY = st->lightYTarget = RAND_FLOAT_PM1; + st->lightZ = st->lightZTarget = RAND_FLOAT_PM1; + + st->itersTillNext = RAND_FLOAT_01 * st->maxIters; +} + + + +/* + * the simulation + */ + +/* "render" the blots into segsToDraw, with the current rotation factors */ +static void renderSegs (struct state *st) +{ + int n; + int m = 0; + + /* rotation factors */ + FLOAT sinX = sin (st->xRot); + FLOAT cosX = cos (st->xRot); + FLOAT sinY = sin (st->yRot); + FLOAT cosY = cos (st->yRot); + FLOAT sinZ = sin (st->zRot); + FLOAT cosZ = cos (st->zRot); + + for (n = 0; n < st->blotCount; n++) + { + Blot *b = &st->blots[n]; + int i, j; + int baseX, baseY; + FLOAT radius; + int x[3][3]; + int y[3][3]; + int color; + + FLOAT x1 = st->blots[n].x; + FLOAT y1 = st->blots[n].y; + FLOAT z1 = st->blots[n].z; + FLOAT x2, y2, z2; + + /* rotate on z axis */ + x2 = x1 * cosZ - y1 * sinZ; + y2 = x1 * sinZ + y1 * cosZ; + z2 = z1; + + /* rotate on x axis */ + y1 = y2 * cosX - z2 * sinX; + z1 = y2 * sinX + z2 * cosX; + x1 = x2; + + /* rotate on y axis */ + z2 = z1 * cosY - x1 * sinY; + x2 = z1 * sinY + x1 * cosY; + y2 = y1; + + /* the color to draw is based on the distance from the light of + * the post-rotation blot */ + x1 = x2 - st->lightX; + y1 = y2 - st->lightY; + z1 = z2 - st->lightZ; + color = 1 + (x1 * x1 + y1 * y1 + z1 * z1) / 4 * st->colorCount; + if (color > st->colorCount) + { + color = st->colorCount; + } + + /* set up the base screen coordinates for drawing */ + baseX = x2 / 2 * st->baseScale * st->curScale + st->centerX + st->centerXOff; + baseY = y2 / 2 * st->baseScale * st->curScale + st->centerY + st->centerYOff; + + radius = (z2 + 1) / 2 * (st->maxRadius - st->minRadius) + st->minRadius; + + for (i = 0; i < 3; i++) + { + for (j = 0; j < 3; j++) + { + x[i][j] = baseX + + ((i - 1) + (b->xoff[i][j] * st->maxNerveRadius)) * radius; + y[i][j] = baseY + + ((j - 1) + (b->yoff[i][j] * st->maxNerveRadius)) * radius; + } + } + + for (i = 1; i < blotShapeCount; i++) + { + st->segsToDraw[m].gc = st->gcs[color]; + st->segsToDraw[m].x1 = x[blotShape[i-1].x + 1][blotShape[i-1].y + 1]; + st->segsToDraw[m].y1 = y[blotShape[i-1].x + 1][blotShape[i-1].y + 1]; + st->segsToDraw[m].x2 = x[blotShape[i].x + 1][blotShape[i].y + 1]; + st->segsToDraw[m].y2 = y[blotShape[i].x + 1][blotShape[i].y + 1]; + m++; + } + } +} + +/* update blots, adjusting the offsets and rotation factors. */ +static void updateWithFeeling (struct state *st) +{ + int n, i, j; + + /* pick a new model if the time is right */ + st->itersTillNext--; + if (st->itersTillNext < 0) + { + st->itersTillNext = RAND_FLOAT_01 * st->maxIters; + setupBlots (st); + setupSegs (st); + renderSegs (st); + } + + /* update the rotation factors by moving them a bit toward the targets */ + st->xRot = st->xRot + (st->xRotTarget - st->xRot) * st->iterAmt; + st->yRot = st->yRot + (st->yRotTarget - st->yRot) * st->iterAmt; + st->zRot = st->zRot + (st->zRotTarget - st->zRot) * st->iterAmt; + + /* similarly the scale factor */ + st->curScale = st->curScale + (st->scaleTarget - st->curScale) * st->iterAmt; + + /* and similarly the light position */ + st->lightX = st->lightX + (st->lightXTarget - st->lightX) * st->iterAmt; + st->lightY = st->lightY + (st->lightYTarget - st->lightY) * st->iterAmt; + st->lightZ = st->lightZ + (st->lightZTarget - st->lightZ) * st->iterAmt; + + /* for each blot... */ + for (n = 0; n < st->blotCount; n++) + { + /* add a bit of random jitter to xoff/yoff */ + for (i = 0; i < 3; i++) + { + for (j = 0; j < 3; j++) + { + FLOAT newOff; + + newOff = st->blots[n].xoff[i][j] + RAND_FLOAT_PM1 * st->nervousness; + if (newOff < -1) newOff = -(newOff + 1) - 1; + else if (newOff > 1) newOff = -(newOff - 1) + 1; + st->blots[n].xoff[i][j] = newOff; + + newOff = st->blots[n].yoff[i][j] + RAND_FLOAT_PM1 * st->nervousness; + if (newOff < -1) newOff = -(newOff + 1) - 1; + else if (newOff > 1) newOff = -(newOff - 1) + 1; + st->blots[n].yoff[i][j] = newOff; + } + } + } + + /* depending on random chance, update one or more factors */ + if (RAND_FLOAT_01 <= st->eventChance) + { + int which = RAND_FLOAT_01 * 14; + switch (which) + { + case 0: + { + st->xRotTarget = RAND_FLOAT_PM1 * M_PI * 2; + break; + } + case 1: + { + st->yRotTarget = RAND_FLOAT_PM1 * M_PI * 2; + break; + } + case 2: + { + st->zRotTarget = RAND_FLOAT_PM1 * M_PI * 2; + break; + } + case 3: + { + st->xRotTarget = RAND_FLOAT_PM1 * M_PI * 2; + st->yRotTarget = RAND_FLOAT_PM1 * M_PI * 2; + break; + } + case 4: + { + st->xRotTarget = RAND_FLOAT_PM1 * M_PI * 2; + st->zRotTarget = RAND_FLOAT_PM1 * M_PI * 2; + break; + } + case 5: + { + st->yRotTarget = RAND_FLOAT_PM1 * M_PI * 2; + st->zRotTarget = RAND_FLOAT_PM1 * M_PI * 2; + break; + } + case 6: + { + st->xRotTarget = RAND_FLOAT_PM1 * M_PI * 2; + st->yRotTarget = RAND_FLOAT_PM1 * M_PI * 2; + st->zRotTarget = RAND_FLOAT_PM1 * M_PI * 2; + break; + } + case 7: + { + st->centerXOff = RAND_FLOAT_PM1 * st->maxRadius; + break; + } + case 8: + { + st->centerYOff = RAND_FLOAT_PM1 * st->maxRadius; + break; + } + case 9: + { + st->centerXOff = RAND_FLOAT_PM1 * st->maxRadius; + st->centerYOff = RAND_FLOAT_PM1 * st->maxRadius; + break; + } + case 10: + { + st->scaleTarget = + RAND_FLOAT_01 * (st->maxScale - st->minScale) + st->minScale; + break; + } + case 11: + { + st->curScale = + RAND_FLOAT_01 * (st->maxScale - st->minScale) + st->minScale; + break; + } + case 12: + { + st->lightX = RAND_FLOAT_PM1; + st->lightY = RAND_FLOAT_PM1; + st->lightZ = RAND_FLOAT_PM1; + break; + } + case 13: + { + st->lightXTarget = RAND_FLOAT_PM1; + st->lightYTarget = RAND_FLOAT_PM1; + st->lightZTarget = RAND_FLOAT_PM1; + break; + } + } + } +} + +/* erase segsToErase and draw segsToDraw */ +static void eraseAndDraw (struct state *st) +{ + int n; + + if (st->doubleBuffer) + XFillRectangle (st->dpy, st->drawable, st->gcs[0], 0, 0, + st->windowWidth, st->windowHeight); + else + XClearWindow (st->dpy, st->drawable); + + for (n = 0; n < st->segCount; n++) + { + LineSegment *seg = &st->segsToErase[n]; +#ifdef HAVE_COCOA /* Don't second-guess Quartz's double-buffering */ + XDrawLine (st->dpy, st->drawable, st->gcs[0], + seg->x1, seg->y1, seg->x2, seg->y2); +#endif + seg = &st->segsToDraw[n]; + XDrawLine (st->dpy, st->drawable, seg->gc, + seg->x1, seg->y1, seg->x2, seg->y2); + } + + if (st->doubleBuffer) + { + XCopyArea (st->dpy, st->drawable, st->window, st->gcs[0], 0, 0, + st->windowWidth, st->windowHeight, 0, 0); + } +} + +/* do one iteration */ +static unsigned long +nerverot_draw (Display *dpy, Window win, void *closure) +{ + struct state *st = (struct state *) closure; + /* switch segsToErase and segsToDraw */ + LineSegment *temp = st->segsToDraw; + st->segsToDraw = st->segsToErase; + st->segsToErase = temp; + + /* update the model */ + updateWithFeeling (st); + + /* render new segments */ + renderSegs (st); + + /* erase old segments and draw new ones */ + eraseAndDraw (st); + + return st->delay; +} + +/* initialize the user-specifiable params */ +static void initParams (struct state *st) +{ + int problems = 0; + + st->delay = get_integer_resource (st->dpy, "delay", "Delay"); + if (st->delay < 0) + { + fprintf (stderr, "error: delay must be at least 0\n"); + problems = 1; + } + + st->maxIters = get_integer_resource (st->dpy, "maxIters", "Integer"); + if (st->maxIters < 0) + { + fprintf (stderr, "error: maxIters must be at least 0\n"); + problems = 1; + } + + st->doubleBuffer = get_boolean_resource (st->dpy, "doubleBuffer", "Boolean"); + +# ifdef HAVE_COCOA /* Don't second-guess Quartz's double-buffering */ + st->doubleBuffer = False; +# endif + + st->requestedBlotCount = get_integer_resource (st->dpy, "count", "Count"); + if (st->requestedBlotCount <= 0) + { + fprintf (stderr, "error: count must be at least 0\n"); + problems = 1; + } + + st->colorCount = get_integer_resource (st->dpy, "colors", "Colors"); + if (st->colorCount <= 0) + { + fprintf (stderr, "error: colors must be at least 1\n"); + problems = 1; + } + + st->lineWidth = get_integer_resource (st->dpy, "lineWidth", "LineWidth"); + if (st->lineWidth < 0) + { + fprintf (stderr, "error: line width must be at least 0\n"); + problems = 1; + } + + st->nervousness = get_float_resource (st->dpy, "nervousness", "Float"); + if ((st->nervousness < 0) || (st->nervousness > 1)) + { + fprintf (stderr, "error: nervousness must be in the range 0..1\n"); + problems = 1; + } + + st->maxNerveRadius = get_float_resource (st->dpy, "maxNerveRadius", "Float"); + if ((st->maxNerveRadius < 0) || (st->maxNerveRadius > 1)) + { + fprintf (stderr, "error: maxNerveRadius must be in the range 0..1\n"); + problems = 1; + } + + st->eventChance = get_float_resource (st->dpy, "eventChance", "Float"); + if ((st->eventChance < 0) || (st->eventChance > 1)) + { + fprintf (stderr, "error: eventChance must be in the range 0..1\n"); + problems = 1; + } + + st->iterAmt = get_float_resource (st->dpy, "iterAmt", "Float"); + if ((st->iterAmt < 0) || (st->iterAmt > 1)) + { + fprintf (stderr, "error: iterAmt must be in the range 0..1\n"); + problems = 1; + } + + st->minScale = get_float_resource (st->dpy, "minScale", "Float"); + if ((st->minScale < 0) || (st->minScale > 10)) + { + fprintf (stderr, "error: minScale must be in the range 0..10\n"); + problems = 1; + } + + st->maxScale = get_float_resource (st->dpy, "maxScale", "Float"); + if ((st->maxScale < 0) || (st->maxScale > 10)) + { + fprintf (stderr, "error: maxScale must be in the range 0..10\n"); + problems = 1; + } + + if (st->maxScale < st->minScale) + { + fprintf (stderr, "error: maxScale must be >= minScale\n"); + problems = 1; + } + + st->minRadius = get_integer_resource (st->dpy, "minRadius", "Integer"); + if ((st->minRadius < 1) || (st->minRadius > 100)) + { + fprintf (stderr, "error: minRadius must be in the range 1..100\n"); + problems = 1; + } + + st->maxRadius = get_integer_resource (st->dpy, "maxRadius", "Integer"); + if ((st->maxRadius < 1) || (st->maxRadius > 100)) + { + fprintf (stderr, "error: maxRadius must be in the range 1..100\n"); + problems = 1; + } + + if (st->maxRadius < st->minRadius) + { + fprintf (stderr, "error: maxRadius must be >= minRadius\n"); + problems = 1; + } + + if (problems) + { + exit (1); + } +} + +static void * +nerverot_init (Display *dpy, Window window) +{ + struct state *st = (struct state *) calloc (1, sizeof(*st)); + st->dpy = dpy; + st->window = window; + + initParams (st); + setup (st); + + /* make a valid set to erase at first */ + renderSegs (st); + return st; +} + +static void +nerverot_reshape (Display *dpy, Window window, void *closure, + unsigned int w, unsigned int h) +{ +} + +static Bool +nerverot_event (Display *dpy, Window window, void *closure, XEvent *event) +{ + return False; +} + +static void +nerverot_free (Display *dpy, Window window, void *closure) +{ + struct state *st = (struct state *) closure; + freeBlots (st); + free (st); +} + + +static const char *nerverot_defaults [] = { + ".background: black", + ".foreground: white", + "*count: 250", + "*colors: 4", + "*delay: 10000", + "*maxIters: 1200", + "*doubleBuffer: false", + "*eventChance: 0.2", + "*iterAmt: 0.01", + "*lineWidth: 0", + "*minScale: 0.6", + "*maxScale: 1.75", + "*minRadius: 3", + "*maxRadius: 25", + "*maxNerveRadius: 0.7", + "*nervousness: 0.3", + 0 +}; + +static XrmOptionDescRec nerverot_options [] = { + { "-count", ".count", XrmoptionSepArg, 0 }, + { "-colors", ".colors", XrmoptionSepArg, 0 }, + { "-delay", ".delay", XrmoptionSepArg, 0 }, + { "-max-iters", ".maxIters", XrmoptionSepArg, 0 }, + { "-db", ".doubleBuffer", XrmoptionNoArg, "true" }, + { "-no-db", ".doubleBuffer", XrmoptionNoArg, "false" }, + { "-event-chance", ".eventChance", XrmoptionSepArg, 0 }, + { "-iter-amt", ".iterAmt", XrmoptionSepArg, 0 }, + { "-line-width", ".lineWidth", XrmoptionSepArg, 0 }, + { "-min-scale", ".minScale", XrmoptionSepArg, 0 }, + { "-max-scale", ".maxScale", XrmoptionSepArg, 0 }, + { "-min-radius", ".minRadius", XrmoptionSepArg, 0 }, + { "-max-radius", ".maxRadius", XrmoptionSepArg, 0 }, + { "-max-nerve-radius", ".maxNerveRadius", XrmoptionSepArg, 0 }, + { "-nervousness", ".nervousness", XrmoptionSepArg, 0 }, + { 0, 0, 0, 0 } +}; + + +XSCREENSAVER_MODULE ("NerveRot", nerverot) diff --git a/hacks/nerverot.man b/hacks/nerverot.man new file mode 100644 index 00000000..2c474b68 --- /dev/null +++ b/hacks/nerverot.man @@ -0,0 +1,132 @@ +.TH XScreenSaver 1 "20-Mar-2001" "X Version 11" +.SH NAME +nerverot - induces edginess in the viewer +.SH SYNOPSIS +.B nerverot +[\-display \fIhost:display.screen\fP] [\-foreground \fIcolor\fP] [\-background \fIcolor\fP] [\-window] [\-root] [\-mono] [\-install] [\-visual \fIvisual\fP] [\-db] [\-no\-db] [\-colors \fIinteger\fP] [\-delay \fImicroseconds\fP] [\-count \fIinteger\fP] [\-line\-width \fIinteger\fP] [\-event\-chance \fIfraction\fP] [\-iter\-amt \fIfraction\fP] [\-nervousness \fIfraction\fP] [\-max\-nerve\-radius \fIfraction\fP] [\-min\-radius \fIinteger\fP] [\-max\-radius \fIinteger\fP] [\-min\-scale \fIfraction\fP] [\-max\-scale \fIfraction\fP] +[\-fps] +.SH DESCRIPTION +The goal of \fInerverot\fP is to be interesting and compelling to +watch, yet induce a state of nervous edginess in the viewer. This manpage +describes v1.3 of the program. +.SH OPTIONS +.I nerverot +accepts the following options: +.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 \-mono +If on a color display, pretend we're on a monochrome display. +.TP 8 +.B \-install +Install a private colormap for the window. +.TP 8 +.B \-visual \fIvisual\fP +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 \-db +.B \-no\-db +Use double-buffering (or not, respectively). Double-buffering may make +things look better for larger line widths and/or larger numbers of +blots, but "better" may equate to yielding less of the desired edginess +effect. You'll be calmer after watching the double-buffered variant; +you're more likely to go into epileptic fits with it off. Hence, it +is off (false) by default, resource \fIdoubleBuffer\fP. +.TP 8 +.B \-colors \fIinteger\fP +How many colors should be used (if possible). The colors +form a smooth ramp between two randomly-chosen colors. Defaults to 4, +resource \fIcolors\fP. +.TP 8 +.B \-delay \fImicroseconds\fP +The interframe delay, in microseconds. Defaults to 10000, resource +\fIdelay\fP. +.TP 8 +.B \-max\-iters \fIinteger\fP +The maximum number of iterations (frames) before a new model is +generated. The actual number of iterations per model is a random number +between 1 and this value. Defaults to 1200, resource +\fImaxIters\fP. +.TP 8 +.B \-count \fIinteger\fP +How many "blots" to draw at a time. This number may be rounded down to +fit the particularly chosen model, and has a fixed minimum per-model. +Defaults to 250, resource \fIcount\fP. +.TP 8 +.B \-line\-width \fIinteger\fP +The width of the lines to draw. 0 means an optimized pixel-thick line. +Defaults to 0, resource \fIlineWidth\fP. +.TP 8 +.B \-event\-chance \fIfraction\fP +The chance, per iteration, for a life-altering event to occur (such as +picking a new rotation target), in the range 0..1. Defaults to 0.2, +resource \fIeventChance\fP. +.TP 8 +.B \-iter\-amt \fIfraction\fP +The fraction of movement towards a target (such as rotation angle or scale) +that happens per iteration, in the range 0..1. Defaults to 0.01, +resource \fIiterAmt\fP. +.TP 8 +.B \-nervousness \fIfraction\fP +How nervous the drawing is, in the range 0..1. This is how jumpy the points +on each blot are. Defaults to 0.3, resource \fInervousness\fP. +.TP 8 +.B \-max\-nerve\-radius \fIfraction\fP +The maximum radius of blot nervousness, as a fraction of the radius of the +blot, in the range 0..1. Defaults to 0.7, resource \fImaxNerveRadius\fP. +.TP 8 +.B \-min\-radius \fIinteger\fP +The minimum radius for a blot, in the range 1..100. Defaults to 3, +resource \fIminRadius\fP. +.TP 8 +.B \-max\-radius \fIinteger\fP +The maximum radius for a blot, in the range 1..100. Defaults to 25, +resource \fImaxRadius\fP. +.TP 8 +.B \-min\-scale \fIfraction\fP +The minimum overall scale of drawing, as a fraction of +\fImin(windowHeight,windowWidth)\fP, in the range 0..10. Defaults to 0.6, +resource \fIminScale\fP. +.TP 8 +.B \-max\-scale \fIfraction\fP +The maximum overall scale of drawing, as a fraction of +\fImin(windowHeight,windowWidth)\fP, in the range 0..10. Defaults to 1.75, +resource \fImaxScale\fP. +.TP 8 +.B \-fps +Display the current frame rate and CPU load. +.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 X RESOURCES +There are resource equivalents for each option, noted above. +.SH BUGS +.I nerverot +should have more models. +.TP 8 +XDBE should be detected and used, if available. +.SH SEE ALSO +.BR xscreensaver (1) +.SH COPYRIGHT +Copyright \(co 2000-2001 by Dan Bornstein. All rights reserved. + +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 +Dan Bornstein . diff --git a/hacks/noseguy.c b/hacks/noseguy.c new file mode 100644 index 00000000..32b09e25 --- /dev/null +++ b/hacks/noseguy.c @@ -0,0 +1,622 @@ +/* xscreensaver, Copyright (c) 1992-2012 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. + */ + +/* Make a little guy with a big nose and a hat wanter around the screen, + spewing out messages. Derived from xnlock by + Dan Heller . + */ + +#include "screenhack.h" +#include "xpm-pixmap.h" +#include "textclient.h" + +#ifdef HAVE_COCOA +# define HAVE_XPM +#endif + +#define font_height(font) (font->ascent + font->descent) + + +struct state { + Display *dpy; + Window window; + int Width, Height; + GC fg_gc, bg_gc, text_fg_gc, text_bg_gc; + int x, y; + XFontStruct *font; + + unsigned long interval; + Pixmap left1, left2, right1, right2; + Pixmap left_front, right_front, front, down; + + char *program; + text_data *tc; + + int state; /* indicates states: walking or getting passwd */ + int first_time; + + void (*next_fn) (struct state *); + + int move_length, move_dir; + + int walk_lastdir; + int walk_up; + Pixmap walk_frame; + + int X, Y, talking; + + struct { + int x, y, width, height; + } s_rect; + + char words[10240]; + int lines; +}; + +static void fill_words (struct state *); +static void walk (struct state *, int dir); +static void talk (struct state *, int erase); +static void talk_1 (struct state *); +static int think (struct state *); +static unsigned long look (struct state *); + +#define IS_MOVING 1 + +#if defined(HAVE_GDK_PIXBUF) || defined(HAVE_XPM) +# include "images/noseguy/nose-f1.xpm" +# include "images/noseguy/nose-f2.xpm" +# include "images/noseguy/nose-f3.xpm" +# include "images/noseguy/nose-f4.xpm" +# include "images/noseguy/nose-l1.xpm" +# include "images/noseguy/nose-l2.xpm" +# include "images/noseguy/nose-r1.xpm" +# include "images/noseguy/nose-r2.xpm" +#else +# include "images/noseguy/nose-f1.xbm" +# include "images/noseguy/nose-f2.xbm" +# include "images/noseguy/nose-f3.xbm" +# include "images/noseguy/nose-f4.xbm" +# include "images/noseguy/nose-l1.xbm" +# include "images/noseguy/nose-l2.xbm" +# include "images/noseguy/nose-r1.xbm" +# include "images/noseguy/nose-r2.xbm" +#endif + +static void +init_images (struct state *st) +{ + Pixmap *images[8]; +#if defined(HAVE_GDK_PIXBUF) || defined(HAVE_XPM) + char **bits[8]; +#else + unsigned char *bits[8]; +#endif + + int i = 0; + images[i++] = &st->left1; + images[i++] = &st->left2; + images[i++] = &st->right1; + images[i++] = &st->right2; + images[i++] = &st->left_front; + images[i++] = &st->right_front; + images[i++] = &st->front; + images[i] = &st->down; + +#if defined(HAVE_GDK_PIXBUF) || defined(HAVE_XPM) + + i = 0; + bits[i++] = nose_l1_xpm; + bits[i++] = nose_l2_xpm; + bits[i++] = nose_r1_xpm; + bits[i++] = nose_r2_xpm; + bits[i++] = nose_f2_xpm; + bits[i++] = nose_f3_xpm; + bits[i++] = nose_f1_xpm; + bits[i] = nose_f4_xpm; + + for (i = 0; i < sizeof (images) / sizeof(*images); i++) + { + Pixmap pixmap = xpm_data_to_pixmap (st->dpy, st->window, bits[i], + 0, 0, 0); + if (!pixmap) + { + fprintf (stderr, "%s: Can't load nose images\n", progname); + exit (1); + } + *images[i] = pixmap; + } +#else + i = 0; + bits[i++] = nose_l1_bits; + bits[i++] = nose_l2_bits; + bits[i++] = nose_r1_bits; + bits[i++] = nose_r2_bits; + bits[i++] = nose_f2_bits; + bits[i++] = nose_f3_bits; + bits[i++] = nose_f1_bits; + bits[i++] = nose_f4_bits; + + for (i = 0; i < sizeof (images) / sizeof(*images); i++) + if (!(*images[i] = + XCreatePixmapFromBitmapData(st->dpy, st->window, + (char *) bits[i], 64, 64, 1, 0, 1))) + { + fprintf (stderr, "%s: Can't load nose images\n", progname); + exit (1); + } +#endif +} + +#define LEFT 001 +#define RIGHT 002 +#define DOWN 004 +#define UP 010 +#define FRONT 020 +#define X_INCR 3 +#define Y_INCR 2 + +static void +move (struct state *st) +{ + if (!st->move_length) + { + register int tries = 0; + st->move_dir = 0; + if ((random() & 1) && think(st)) + { + talk(st, 0); /* sets timeout to itself */ + return; + } + if (!(random() % 3) && (st->interval = look(st))) + { + st->next_fn = move; + return; + } + st->interval = 20 + random() % 100; + do + { + if (!tries) + st->move_length = st->Width / 100 + random() % 90, tries = 8; + else + tries--; + /* There maybe the case that we won't be able to exit from + this routine (especially when the geometry is too small)!! + + Ensure that we can exit from this routine. + */ +#if 1 + if (!tries && (st->move_length <= 1)) { + st->move_length = 1; + break; + } +#endif + switch (random() % 8) + { + case 0: + if (st->x - X_INCR * st->move_length >= 5) + st->move_dir = LEFT; + break; + case 1: + if (st->x + X_INCR * st->move_length <= st->Width - 70) + st->move_dir = RIGHT; + break; + case 2: + if (st->y - (Y_INCR * st->move_length) >= 5) + st->move_dir = UP, st->interval = 40; + break; + case 3: + if (st->y + Y_INCR * st->move_length <= st->Height - 70) + st->move_dir = DOWN, st->interval = 20; + break; + case 4: + if (st->x - X_INCR * st->move_length >= 5 && st->y - (Y_INCR * st->move_length) >= 5) + st->move_dir = (LEFT | UP); + break; + case 5: + if (st->x + X_INCR * st->move_length <= st->Width - 70 && + st->y - Y_INCR * st->move_length >= 5) + st->move_dir = (RIGHT | UP); + break; + case 6: + if (st->x - X_INCR * st->move_length >= 5 && + st->y + Y_INCR * st->move_length <= st->Height - 70) + st->move_dir = (LEFT | DOWN); + break; + case 7: + if (st->x + X_INCR * st->move_length <= st->Width - 70 && + st->y + Y_INCR * st->move_length <= st->Height - 70) + st->move_dir = (RIGHT | DOWN); + break; + default: + /* No Defaults */ + break; + } + } while (!st->move_dir); + } + if (st->move_dir) + walk(st, st->move_dir); + --st->move_length; + st->next_fn = move; +} + +#ifdef HAVE_XPM +# define COPY(dpy,frame,window,gc,x,y,w,h,x2,y2) \ + XCopyArea (dpy,frame,window,gc,x,y,w,h,x2,y2) +#else +# define COPY(dpy,frame,window,gc,x,y,w,h,x2,y2) \ + XCopyPlane(dpy,frame,window,gc,x,y,w,h,x2,y2,1L) +#endif + +static void +walk (struct state *st, int dir) +{ + register int incr = 0; + + if (dir & (LEFT | RIGHT)) + { /* left/right movement (mabye up/st->down too) */ + st->walk_up = -st->walk_up; /* bouncing effect (even if hit a wall) */ + if (dir & LEFT) + { + incr = X_INCR; + st->walk_frame = (st->walk_up < 0) ? st->left1 : st->left2; + } + else + { + incr = -X_INCR; + st->walk_frame = (st->walk_up < 0) ? st->right1 : st->right2; + } + if ((st->walk_lastdir == FRONT || st->walk_lastdir == DOWN) && dir & UP) + { + + /* + * workaround silly bug that leaves screen dust when guy is + * facing forward or st->down and moves up-left/right. + */ + COPY(st->dpy, st->walk_frame, st->window, st->fg_gc, 0, 0, 64, 64, st->x, st->y); + } + /* note that maybe neither UP nor DOWN is set! */ + if (dir & UP && st->y > Y_INCR) + st->y -= Y_INCR; + else if (dir & DOWN && st->y < st->Height - 64) + st->y += Y_INCR; + } + /* Explicit up/st->down movement only (no left/right) */ + else if (dir == UP) + COPY(st->dpy, st->front, st->window, st->fg_gc, 0, 0, 64, 64, st->x, st->y -= Y_INCR); + else if (dir == DOWN) + COPY(st->dpy, st->down, st->window, st->fg_gc, 0, 0, 64, 64, st->x, st->y += Y_INCR); + else if (dir == FRONT && st->walk_frame != st->front) + { + if (st->walk_up > 0) + st->walk_up = -st->walk_up; + if (st->walk_lastdir & LEFT) + st->walk_frame = st->left_front; + else if (st->walk_lastdir & RIGHT) + st->walk_frame = st->right_front; + else + st->walk_frame = st->front; + COPY(st->dpy, st->walk_frame, st->window, st->fg_gc, 0, 0, 64, 64, st->x, st->y); + } + if (dir & LEFT) + while (--incr >= 0) + { + COPY(st->dpy, st->walk_frame, st->window, st->fg_gc, 0, 0, 64, 64, --st->x, st->y + st->walk_up); + } + else if (dir & RIGHT) + while (++incr <= 0) + { + COPY(st->dpy, st->walk_frame, st->window, st->fg_gc, 0, 0, 64, 64, ++st->x, st->y + st->walk_up); + } + st->walk_lastdir = dir; +} + +static int +think (struct state *st) +{ + if (random() & 1) + walk(st, FRONT); + if (random() & 1) + return 1; + return 0; +} + +#define MAXLINES 10 + +static void +talk (struct state *st, int force_erase) +{ + int width = 0, + height, + Z, + total = 0; + register char *p, + *p2; + char args[MAXLINES][256]; + + /* clear what we've written */ + if (st->talking || force_erase) + { + if (!st->talking) + return; + XFillRectangle(st->dpy, st->window, st->bg_gc, st->s_rect.x - 5, st->s_rect.y - 5, + st->s_rect.width + 10, st->s_rect.height + 10); + st->talking = 0; + if (!force_erase) + st->next_fn = move; + st->interval = 0; + { + /* might as well check the st->window for size changes now... */ + XWindowAttributes xgwa; + XGetWindowAttributes (st->dpy, st->window, &xgwa); + st->Width = xgwa.width + 2; + st->Height = xgwa.height + 2; + } + return; + } + st->talking = 1; + walk(st, FRONT); + p = st->words; + + for (p2 = p; *p2; p2++) + if (*p2 == '\t') *p2 = ' '; + + if (!(p2 = strchr(p, '\n')) || !p2[1]) + { + total = strlen (st->words); + strcpy (args[0], st->words); + width = XTextWidth(st->font, st->words, total); + height = 0; + } + else + /* p2 now points to the first '\n' */ + for (height = 0; p; height++) + { + int w; + *p2 = 0; + if ((w = XTextWidth(st->font, p, p2 - p)) > width) + width = w; + total += p2 - p; /* total chars; count to determine reading + * time */ + (void) strcpy(args[height], p); + if (height == MAXLINES - 1) + { + /* puts("Message too long!"); */ + break; + } + p = p2 + 1; + if (!(p2 = strchr(p, '\n'))) + break; + } + height++; + + /* + * Figure out the height and width in pixels (height, width) extend the + * new box by 15 pixels on the sides (30 total) top and bottom. + */ + st->s_rect.width = width + 30; + st->s_rect.height = height * font_height(st->font) + 30; + if (st->x - st->s_rect.width - 10 < 5) + st->s_rect.x = 5; + else if ((st->s_rect.x = st->x + 32 - (st->s_rect.width + 15) / 2) + + st->s_rect.width + 15 > st->Width - 5) + st->s_rect.x = st->Width - 15 - st->s_rect.width; + if (st->y - st->s_rect.height - 10 < 5) + st->s_rect.y = st->y + 64 + 5; + else + st->s_rect.y = st->y - 5 - st->s_rect.height; + + XFillRectangle(st->dpy, st->window, st->text_bg_gc, + st->s_rect.x, st->s_rect.y, st->s_rect.width, st->s_rect.height); + + /* make a box that's 5 pixels thick. Then add a thin box inside it */ + XSetLineAttributes(st->dpy, st->text_fg_gc, 5, 0, 0, 0); + XDrawRectangle(st->dpy, st->window, st->text_fg_gc, + st->s_rect.x, st->s_rect.y, st->s_rect.width - 1, st->s_rect.height - 1); + XSetLineAttributes(st->dpy, st->text_fg_gc, 0, 0, 0, 0); + XDrawRectangle(st->dpy, st->window, st->text_fg_gc, + st->s_rect.x + 7, st->s_rect.y + 7, st->s_rect.width - 15, st->s_rect.height - 15); + + st->X = 15; + st->Y = 15 + font_height(st->font); + + /* now print each string in reverse order (start at bottom of box) */ + for (Z = 0; Z < height; Z++) + { + int L = strlen(args[Z]); + if (args[Z][L-1] == '\r' || args[Z][L-1] == '\n') + args[Z][--L] = 0; + XDrawString(st->dpy, st->window, st->text_fg_gc, st->s_rect.x + st->X, st->s_rect.y + st->Y, + args[Z], L); + st->Y += font_height(st->font); + } + st->interval = (total / 15) * 1000; + if (st->interval < 2000) st->interval = 2000; + st->next_fn = talk_1; + *st->words = 0; + st->lines = 0; +} + +static void +talk_1 (struct state *st) +{ + talk(st, 0); +} + + +static unsigned long +look (struct state *st) +{ + if (random() % 3) + { + COPY(st->dpy, (random() & 1) ? st->down : st->front, st->window, st->fg_gc, + 0, 0, 64, 64, st->x, st->y); + return 1000L; + } + if (!(random() % 5)) + return 0; + if (random() % 3) + { + COPY(st->dpy, (random() & 1) ? st->left_front : st->right_front, + st->window, st->fg_gc, 0, 0, 64, 64, st->x, st->y); + return 1000L; + } + if (!(random() % 5)) + return 0; + COPY(st->dpy, (random() & 1) ? st->left1 : st->right1, st->window, st->fg_gc, + 0, 0, 64, 64, st->x, st->y); + return 1000L; +} + + +static void +fill_words (struct state *st) +{ + char *p = st->words + strlen(st->words); + while (p < st->words + sizeof(st->words) - 1 && + st->lines < MAXLINES) + { + char c = textclient_getc (st->tc); + if (c == '\n') + st->lines++; + if (c > 0) + *p++ = c; + else + break; + } + *p = 0; +} + + + +static const char *noseguy_defaults [] = { + ".background: black", + ".foreground: #CCCCCC", + "*textForeground: black", + "*textBackground: #CCCCCC", + "*fpsSolid: true", + "*program: xscreensaver-text --cols 40 | head -n15", + "*usePty: False", + ".font: -*-new century schoolbook-*-r-*-*-*-180-*-*-*-*-*-*", + 0 +}; + +static XrmOptionDescRec noseguy_options [] = { + { "-program", ".program", XrmoptionSepArg, 0 }, + { "-font", ".font", XrmoptionSepArg, 0 }, + { "-text-foreground", ".textForeground", XrmoptionSepArg, 0 }, + { "-text-background", ".textBackground", XrmoptionSepArg, 0 }, + { 0, 0, 0, 0 } +}; + + +static void * +noseguy_init (Display *d, Window w) +{ + struct state *st = (struct state *) calloc (1, sizeof(*st)); + unsigned long fg, bg, text_fg, text_bg; + XWindowAttributes xgwa; + Colormap cmap; + char *fontname; + XGCValues gcvalues; + st->dpy = d; + st->window = w; + st->first_time = 1; + + fontname = get_string_resource (st->dpy, "font", "Font"); + XGetWindowAttributes (st->dpy, st->window, &xgwa); + st->Width = xgwa.width + 2; + st->Height = xgwa.height + 2; + cmap = xgwa.colormap; + + st->program = get_string_resource (st->dpy, "program", "Program"); + st->tc = textclient_open (st->dpy); + init_images(st); + + if (!fontname || !*fontname) + fprintf (stderr, "%s: no font specified.\n", progname); + st->font = XLoadQueryFont(st->dpy, fontname); + if (!st->font) { + fprintf (stderr, "%s: could not load font %s.\n", progname, fontname); + exit(1); + } + + fg = get_pixel_resource (st->dpy, cmap, "foreground", "Foreground"); + bg = get_pixel_resource (st->dpy, cmap, "background", "Background"); + text_fg = get_pixel_resource (st->dpy, cmap, "textForeground", "Foreground"); + text_bg = get_pixel_resource (st->dpy, cmap, "textBackground", "Background"); + /* notice when unspecified */ + if (! get_string_resource (st->dpy, "textForeground", "Foreground")) + text_fg = bg; + if (! get_string_resource (st->dpy, "textBackground", "Background")) + text_bg = fg; + + gcvalues.font = st->font->fid; + gcvalues.foreground = fg; + gcvalues.background = bg; + st->fg_gc = XCreateGC (st->dpy, st->window, + GCForeground|GCBackground|GCFont, + &gcvalues); + gcvalues.foreground = bg; + gcvalues.background = fg; + st->bg_gc = XCreateGC (st->dpy, st->window, + GCForeground|GCBackground|GCFont, + &gcvalues); + gcvalues.foreground = text_fg; + gcvalues.background = text_bg; + st->text_fg_gc = XCreateGC (st->dpy, st->window, + GCForeground|GCBackground|GCFont, + &gcvalues); + gcvalues.foreground = text_bg; + gcvalues.background = text_fg; + st->text_bg_gc = XCreateGC (st->dpy, st->window, + GCForeground|GCBackground|GCFont, + &gcvalues); + st->x = st->Width / 2; + st->y = st->Height / 2; + st->state = IS_MOVING; + st->next_fn = move; + st->walk_up = 1; + return st; +} + +static unsigned long +noseguy_draw (Display *dpy, Window window, void *closure) +{ + struct state *st = (struct state *) closure; + fill_words(st); + st->next_fn(st); + return (st->interval * 1000); +} + +static void +noseguy_reshape (Display *dpy, Window window, void *closure, + unsigned int w, unsigned int h) +{ + struct state *st = (struct state *) closure; + st->Width = w + 2; + st->Height = h + 2; +} + +static Bool +noseguy_event (Display *dpy, Window window, void *closure, XEvent *event) +{ + return False; +} + +static void +noseguy_free (Display *dpy, Window window, void *closure) +{ + struct state *st = (struct state *) closure; + textclient_close (st->tc); + free (st); +} + +XSCREENSAVER_MODULE ("NoseGuy", noseguy) diff --git a/hacks/noseguy.man b/hacks/noseguy.man new file mode 100644 index 00000000..3d98ea0b --- /dev/null +++ b/hacks/noseguy.man @@ -0,0 +1,84 @@ +.TH XScreenSaver 1 "13-aug-92" "X Version 11" +.SH NAME +noseguy - a little guy with a big nose wanders around being witty +.SH SYNOPSIS +.B noseguy +[\-display \fIhost:display.screen\fP] +[\-foreground \fIcolor\fP] +[\-background \fIcolor\fP] +[\-text-foreground \fIcolor\fP] +[\-text-background \fIcolor\fP] +[\-font \fIfont\fP] +[\-window] +[\-root] +[\-install] +[\-visual \fIvisual\fP] +[\-mode \fImode\fP] +[\-program \fIprogram\fP] +[\-filename \fIfile\fP] +[\-text \fItext\fP] +[\-fps] +.SH DESCRIPTION +A little man with a big nose and a hat runs around spewing out messages to +the screen. This code (and its bitmaps) were extracted from the \fIxnlock\fP +program. +.SH OPTIONS +.I noseguy +accepts the following options: +.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 \-install +Install a private colormap for the window. +.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 \-font \fIfont\fP +The font used for the messages. +.TP 8 +.B \-program \fIprogram\fP +This program will be run periodically, and its output will be the text +of the messages. Default: + + xscreensaver-text --cols 40 | head -n15 + +You can configure the text printed through the "Advanced" tab of +.BR xscreensaver\-demo (1), +or by editing your ~/.xscreensaver file. +.TP 8 +.B \-filename \fIfile\fP +If \fImode\fP is \fIfile\fP, then the contents of this file will be used +for all messages. +.TP 8 +.B \-text \fIstring\fP +If \fImode\fP is \fIstring\fP, then this text will be used for all messages. +.TP 8 +.B \-fps +Display the current frame rate and CPU load. +.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), +.BR xscreensaver-text (1), +.BR xnlock (1) +.SH COPYRIGHT +Copyright 1985, 1990 by Dan Heller . +.SH AUTHOR +Dan Heller , 1985. + +Ability to run standalone or with \fIxscreensaver\fP added by +Jamie Zawinski , 13-aug-92. diff --git a/hacks/pacman.c b/hacks/pacman.c new file mode 100644 index 00000000..23fb3a1d --- /dev/null +++ b/hacks/pacman.c @@ -0,0 +1,1802 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* pacman --- Mr. Pacman and his ghost friends */ + +#if !defined( lint ) && !defined( SABER ) +static const char sccsid[] = "@(#)pacman.c 5.00 2000/11/01 xlockmore"; + +#endif + +/*- + * Copyright (c) 2002 by Edwin de Jong . + * + * Permission to use, copy, modify, and distribute this software and its + * documentation for any purpose and without fee is hereby granted, + * provided that the above copyright notice appear in all copies and that + * both that copyright notice and this permission notice appear in + * supporting documentation. + * + * This file is provided AS IS with no warranties of any kind. The author + * shall have no liability with respect to the infringement of copyrights, + * trade secrets or any patents by this file or any part thereof. In no + * event will the author be liable for any lost revenue or profits or + * other special, indirect and consequential damages. + * + * Revision History: + * 25-Feb-2005: Added bonus dots. I am using a recursive back track algorithm + * to help the ghost find there way home. This also means that + * they do not know the shorts path. + * Jeremy English jhe@jeremyenglish.org + * 15-Aug-2004: Added support for pixmap pacman. + * Jeremy English jhe@jeremyenglish.org + * 11-Aug-2004: Added support for pixmap ghost. + * Jeremy English jhe@jeremyenglish.org + * 13-May-2002: Added -trackmouse feature thanks to code from 'maze.c'. + * splitted up code into several files. Retouched AI code, cleaned + * up code. + * 3-May-2002: Added AI to pacman and ghosts, slowed down ghosts. + * 26-Nov-2001: Random level generator added + * 01-Nov-2000: Allocation checks + * 04-Jun-1997: Compatible with xscreensaver + * + */ + +/* TODO: + 1. think of a better level generation algorithm +*/ + +#define DEF_TRACKMOUSE "False" + +#ifdef STANDALONE +# define MODE_pacman +# define DEFAULTS "*delay: 10000 \n" \ + "*size: 0 \n" \ + "*ncolors: 6 \n" \ + "*fpsTop: true \n" \ + "*fpsSolid: true \n" \ + +# define UNIFORM_COLORS +# define BRIGHT_COLORS +# define pacman_handle_event 0 +# include "xlockmore.h" /* in xscreensaver distribution */ +# include +#else /* STANDALONE */ +# include "xlock.h" /* in xlockmore distribution */ +#endif /* STANDALONE */ + +#ifdef MODE_pacman + +#include "pacman.h" +#include "pacman_ai.h" +#include "pacman_level.h" + +#if defined(USE_PIXMAP) /* computed in pacman.h */ +# include "images/pacman/ghost-u1.xpm" +# include "images/pacman/ghost-u2.xpm" +# include "images/pacman/ghost-r1.xpm" +# include "images/pacman/ghost-r2.xpm" +# include "images/pacman/ghost-l1.xpm" +# include "images/pacman/ghost-l2.xpm" +# include "images/pacman/ghost-d1.xpm" +# include "images/pacman/ghost-d2.xpm" +/* Used to clean up the dust left by wag. */ +# include "images/pacman/ghost-mask.xpm" +# include "images/pacman/pacman-u1.xpm" +# include "images/pacman/pacman-u2.xpm" +# include "images/pacman/pacman-r1.xpm" +# include "images/pacman/pacman-r2.xpm" +# include "images/pacman/pacman-l1.xpm" +# include "images/pacman/pacman-l2.xpm" +# include "images/pacman/pacman-d1.xpm" +# include "images/pacman/pacman-d2.xpm" +# include "images/pacman/pacman-0.xpm" +# include "images/pacman/ghost-s1.xpm" +# include "images/pacman/ghost-s2.xpm" +# include "images/pacman/ghost-sf1.xpm" +# include "images/pacman/ghost-sf2.xpm" +# include "images/pacman/eyes-l.xpm" +# include "images/pacman/eyes-r.xpm" +# include "images/pacman/eyes-u.xpm" +# include "images/pacman/eyes-d.xpm" +# include "images/pacman/pacman-ds1.xpm" +# include "images/pacman/pacman-ds2.xpm" +# include "images/pacman/pacman-ds3.xpm" +# include "images/pacman/pacman-ds4.xpm" +# include "images/pacman/pacman-ds5.xpm" +# include "images/pacman/pacman-ds6.xpm" +# include "images/pacman/pacman-ds7.xpm" +# include "images/pacman/pacman-ds8.xpm" +#endif + +static const struct +{ + int dx, dy; +} dirvecs[DIRVECS] = { { -1, 0}, + { 0, 1}, + { 1, 0}, + { 0, -1}}; + +#ifdef DISABLE_INTERACTIVE +ENTRYPOINT ModeSpecOpt pacman_opts = { + 0, + (XrmOptionDescRec *) NULL, + 0, + (argtype *) NULL, + (OptionStruct *) NULL +}; +#else +static XrmOptionDescRec opts[] = { + {"-trackmouse", ".pacman.trackmouse", XrmoptionNoArg, "on"}, + {"+trackmouse", ".pacman.trackmouse", XrmoptionNoArg, "off"} +}; + +static argtype vars[] = { + {&pacman_trackmouse, "trackmouse", "TrackMouse", DEF_TRACKMOUSE, t_Bool} +}; + +static OptionStruct desc[] = { + {"-/+trackmouse", "turn on/off the tracking of the mouse"} +}; + +ENTRYPOINT ModeSpecOpt pacman_opts = + { sizeof opts / sizeof opts[0], opts, sizeof vars / sizeof vars[0], vars, +desc }; +#endif + +#ifdef USE_MODULES +ModStruct pacman_description = { + "pacman", /* *cmdline_arg; */ + "init_pacman", /* *init_name; */ + "draw_pacman", /* *callback_name; */ + "release_pacman", /* *release_name; */ + "refresh_pacman", /* *refresh_name; */ + "change_pacman", /* *change_name; */ + (char *) NULL, /* *unused_name; */ + &pacman_opts, /* *msopts */ + 10000, 4, 1, 0, 64, 1.0, "", "Shows Pacman(tm)", 0, NULL +}; + +#endif + +Bool pacman_trackmouse; +pacmangamestruct *pacman_games = (pacmangamestruct *) NULL; + +static void repopulate (ModeInfo * mi); +static void drawlevel (ModeInfo * mi); + + +static void +free_pacman (Display * display, pacmangamestruct * pp) +{ + int dir, mouth, i, j, k; + + if (pp->ghosts != NULL) { + free (pp->ghosts); + pp->ghosts = (ghoststruct *) NULL; + } + if (pp->stippledGC != None) { + XFreeGC (display, pp->stippledGC); + pp->stippledGC = None; + } + for (i = 0; i < 4; i++) { + for (j = 0; j < MAXGDIR; j++) { + for (k = 0; k < MAXGWAG; k++) { + if (pp->ghostPixmap[i][j][k] != None) { + XFreePixmap (display, pp->ghostPixmap[i][j][k]); + pp->ghostPixmap[i][j][k] = None; + } + } + } + } + for (dir = 0; dir < 4; dir++) + for (mouth = 0; mouth < MAXMOUTH; mouth++) + if (pp->pacmanPixmap[dir][mouth] != None) { + XFreePixmap (display, pp->pacmanPixmap[dir][mouth]); + pp->pacmanPixmap[dir][mouth] = None; + } +} + +/* set pacman and the ghost in there starting positions, but don't draw a new + level */ +static void +reset_level (ModeInfo * mi, int n, int pac_init) +{ + pacmangamestruct *pp = &pacman_games[MI_SCREEN (mi)]; + unsigned int ghost; + + MI_CLEARWINDOW (mi); + drawlevel (mi); + + pp->gamestate = GHOST_DANGER; + + if ( pac_init ){ + pp->pacman.row = (LEVHEIGHT + JAILHEIGHT) / 2 - n; + pp->pacman.init_row = pp->pacman.row; + } + else{ + pp->pacman.row = pp->pacman.init_row; + } + pp->pacman.col = (LEVWIDTH / 2); + pp->pacman.nextrow = NOWHERE; + pp->pacman.nextcol = NOWHERE; + pp->pacman.cf = NOWHERE; + pp->pacman.rf = NOWHERE; + pp->pacman.oldcf = NOWHERE; + pp->pacman.oldrf = NOWHERE; + pp->pacman.oldlx = NOWHERE; + pp->pacman.oldly = NOWHERE; + pp->pacman.aistate = ps_eating; + pp->pacman.cur_trace = 0; + pp->pacman.roundscore = 0; + pp->pacman.speed = 4; + pp->pacman.lastturn = 0; + pp->pacman.delta.x = 0; + pp->pacman.delta.y = 0; + + for (ghost = 0; ghost < pp->nghosts; ghost++) { + pp->ghosts[ghost].col = (LEVWIDTH / 2); + pp->ghosts[ghost].row = (LEVHEIGHT / 2); + pp->ghosts[ghost].nextcol = NOWHERE; + pp->ghosts[ghost].nextrow = NOWHERE; + pp->ghosts[ghost].dead = 0; + pp->ghosts[ghost].lastbox = START; + pp->ghosts[ghost].cf = NOWHERE; + pp->ghosts[ghost].rf = NOWHERE; + pp->ghosts[ghost].oldcf = NOWHERE; + pp->ghosts[ghost].oldrf = NOWHERE; + pp->ghosts[ghost].aistate = inbox; + pp->ghosts[ghost].timeleft = ghost * 20; + pp->ghosts[ghost].speed = 3; + pp->ghosts[ghost].delta.x = 0; + pp->ghosts[ghost].delta.y = 0; + pp->ghosts[ghost].flash_scared = False; + pp->ghosts[ghost].wait_pos = False; + pacman_ghost_update (pp, &(pp->ghosts[ghost])); + } + pacman_update (mi, pp, &(pp->pacman)); +} + +static int +pacman_ghost_collision(unsigned int ghost, pacmangamestruct * pp) +{ + return (((pp->ghosts[ghost].nextrow == pp->pacman.nextrow) && + (pp->ghosts[ghost].nextcol == pp->pacman.nextcol)) || + ((pp->ghosts[ghost].nextrow == pp->pacman.row) && + (pp->ghosts[ghost].nextcol == pp->pacman.col) && + (pp->ghosts[ghost].row == pp->pacman.nextrow) && + (pp->ghosts[ghost].col == pp->pacman.nextcol))); +} + + +/* Checks for death of any ghosts/pacman and updates. It also makes a new + level if all ghosts are dead or all dots are eaten. */ +static void +check_death (ModeInfo * mi, pacmangamestruct * pp) +{ + Display *display = MI_DISPLAY (mi); + Window window = MI_WINDOW (mi); + unsigned int ghost; + + if (pp->pacman.aistate == ps_dieing) return; + + for (ghost = 0; ghost < pp->nghosts; ghost++) { + + /* The ghost have to be scared before you can kill them */ + if ( pacman_ghost_collision ( ghost, pp ) ) { + if (pp->ghosts[ghost].aistate == goingin) continue; + + if (pp->ghosts[ghost].aistate == hiding) { + pp->ghosts[ghost].dead = 1; + pp->ghosts[ghost].aistate = goingin; + pp->ghosts[ghost].wait_pos = True; + XSetForeground (display, pp->stippledGC, MI_BLACK_PIXEL (mi)); + XFillRectangle (display, window, + pp->stippledGC, + pp->ghosts[ghost].cf, + pp->ghosts[ghost].rf, + pp->spritexs, pp->spriteys); + } + /* DIE PACMAN... */ + else { + pp->pacman.deaths++; + pp->pacman.aistate = ps_dieing; + + } + continue; + } + } +} + +/* Resets state of ghosts + pacman. Creates a new level, draws that level. */ +static void +repopulate (ModeInfo * mi) +{ + pacmangamestruct *pp = &pacman_games[MI_SCREEN (mi)]; + pp->pacman.deaths = 0; + reset_level (mi, pacman_createnewlevel (pp), True); + check_death (mi, pp); +} + +/* Sets the color to the color of a wall. */ +static void +setwallcolor (ModeInfo * mi) +{ + Display *display = MI_DISPLAY (mi); + pacmangamestruct *pp = &pacman_games[MI_SCREEN (mi)]; + + if (MI_NPIXELS (mi) > 2) + XSetForeground (display, pp->stippledGC, MI_PIXEL (mi, BLUE)); + else + XSetForeground (display, pp->stippledGC, MI_WHITE_PIXEL (mi)); +} + +/* Sets the color to the color of a dot. */ +static void +setdotcolor (ModeInfo * mi) +{ + Display *display = MI_DISPLAY (mi); + pacmangamestruct *pp = &pacman_games[MI_SCREEN (mi)]; + + XSetForeground (display, pp->stippledGC, MI_WHITE_PIXEL (mi)); +} + +static void +cleardotcolor (ModeInfo * mi) +{ + Display *display = MI_DISPLAY (mi); + pacmangamestruct *pp = &pacman_games[MI_SCREEN (mi)]; + + XSetForeground (display, pp->stippledGC, MI_BLACK_PIXEL (mi)); +} + +#if 0 +static void +draw_position (ModeInfo * mi, int x, int y, int color) +{ + Display *display = MI_DISPLAY (mi); + Window window = MI_WINDOW (mi); + pacmangamestruct *pp = &pacman_games[MI_SCREEN (mi)]; + XFontStruct *font = NULL; + char *f_name = "-*-utopia-*-r-*-*-*-600-*-*-p-*-*-*"; + char *s = NULL; + + font = XLoadQueryFont (display, f_name); + assert (font != NULL); + + s = (char *) malloc (256); + assert (s != NULL); + sprintf (s, "(%d,%d)", x, y); + XSetForeground (display, pp->stippledGC, color); + XDrawString (display, window, pp->stippledGC, x, y, s, strlen (s)); + free (s); + free (font); +} +#endif +#if 0 +static void +draw_number (ModeInfo * mi, int x, int y, int num, int color) +{ + Display *display = MI_DISPLAY (mi); + Window window = MI_WINDOW (mi); + pacmangamestruct *pp = &pacman_games[MI_SCREEN (mi)]; + XFontStruct *font = NULL; + char *f_name = "-*-utopia-*-r-*-*-*-600-*-*-p-*-*-*"; + char *s = NULL; + + font = XLoadQueryFont (display, f_name); + assert (font != NULL); + + s = (char *) malloc (256); + assert (s != NULL); + sprintf (s, "%d", num); + XSetForeground (display, pp->stippledGC, color); + XDrawString (display, window, pp->stippledGC, x, y, s, strlen (s)); + free (s); + free (font); +} +#endif + +#if 0 +/* draw_grid - draws a grid on top of the playing field. + * Used so that I can determine if I'm converting from rows and columns to x and y + * coordinates correctly. + */ +static void +draw_grid (ModeInfo * mi) +{ + Display *display = MI_DISPLAY (mi); + Window window = MI_WINDOW (mi); + pacmangamestruct *pp = &pacman_games[MI_SCREEN (mi)]; + int h = MI_HEIGHT (mi); + int w = MI_WIDTH (mi); + int y = 0; + int x = 0; + XSetForeground (display, pp->stippledGC, 0xff0000); + while (y < h) { + while (x < w) { + XDrawLine (display, window, pp->stippledGC, x, 0, x, h); + x += 10; + } + x = 0; + XDrawLine (display, window, pp->stippledGC, 0, y, w, y); + y += 10; + } +} +#endif + +#if 0 +static void +draw_string (ModeInfo * mi, int x, int y, char *s, int color) +{ + Display *display = MI_DISPLAY (mi); + Window window = MI_WINDOW (mi); + pacmangamestruct *pp = &pacman_games[MI_SCREEN (mi)]; + XFontStruct *font = NULL; + char *f_name = "-*-utopia-*-r-*-*-*-600-*-*-p-*-*-*"; + + font = XLoadQueryFont (display, f_name); + assert (font != NULL); + + assert (s != NULL); + XSetForeground (display, pp->stippledGC, color); + XDrawString (display, window, pp->stippledGC, x, y, s, strlen (s)); + free (font); +} + +/* I think this function has a memory leak. Be careful if you enable it. */ +/* I only used it briefly to help me debug the ghost's aistate. It prints */ +/* the state of each ghost on the left hand side of the screen */ +static void +print_ghost_stats (ModeInfo *mi, ghoststruct *g , int ghost_num) +{ + char s[1024]; + + sprintf (s, "GHOST: %d", ghost_num ); + switch (g->aistate){ + case inbox: + sprintf (s, "%s inbox", s); + break; + case goingout: + sprintf (s, "%s goingout", s); + break; + case randdir: + sprintf (s, "%s randdir", s); + break; + case chasing: + sprintf (s, "%s chasing", s); + break; + case hiding: + sprintf (s, "%s hiding", s); + break; + case goingin: + sprintf (s, "%s goingin",s); + break; + } + draw_string (mi, 0, (ghost_num *3) *10+50, g->last_stat, 0x000000); + draw_string (mi, 0, (ghost_num *3) *10+50, s, 0xff0000); + strcpy(g->last_stat,s); +} + +/* prints the number of times pacman has died and his aistate on the left hand */ +/* side of the screen */ +static void +print_pac_stats ( ModeInfo *mi, pacmanstruct *pac ) +{ + pacmangamestruct *pp = &pacman_games[MI_SCREEN (mi)]; + char s[1024]; + sprintf (s, "Pacman, Deaths: %d", pac->deaths ); + switch ( pac->aistate ){ + case ps_eating: + sprintf(s, "%s ps_eating",s ); + break; + case ps_chasing: + sprintf(s, "%s ps_chasing",s ); + break; + case ps_hiding: + sprintf(s, "%s ps_hiding",s ); + break; + case ps_random: + sprintf(s, "%s ps_random",s ); + break; + case ps_dieing: + sprintf(s, "%s ps_dieing",s ); + break; + } + draw_string ( mi, 0, 200, pp->last_pac_stat, 0x000000); + draw_string ( mi, 0, 200, s, 0xff0000); + strcpy(pp->last_pac_stat, s ); +} + +#endif + +/*Ok, yeah whatever?*/ +/*dot_rc_to_pixel - magic that converts row and columns into + *the x and y coordinates of the screen. + */ +static void +dot_rc_to_pixel (ModeInfo * mi, int *x, int *y) +{ + pacmangamestruct *pp = &pacman_games[MI_SCREEN (mi)]; + *x = (pp->xs * *x) + + (pp->xs / 2) - (pp->xs > 32 ? (pp->xs / 16) : 1) + pp->xb; + *y = (pp->ys * *y) + + (pp->ys / 2) - (pp->ys > 32 ? (pp->ys / 16) : 1) + pp->yb; +} + +/* dot_width_height - magic used to get the width and height of + * a dot. This dot can also be scaled by a value. + */ +static void +dot_width_height (ModeInfo *mi, int *w, int *h) +{ + pacmangamestruct *pp = &pacman_games[MI_SCREEN (mi)]; + if (pp->xs > 32){ + *w = *h = (pp->xs / 32 ); + }else { + *w = *h = 1; + } +} + +static void +bonus_dot_width_height (ModeInfo *mi, int *w, int *h ) +{ + *w = *h = MI_HEIGHT (mi) / 65; +} + + + +static void +draw_dot (ModeInfo * mi, pacmangamestruct * pp, int x, int y, + void (*width_height)(ModeInfo * mi, int *w, int *h), + int (*arc_func) (Display * display, Drawable d, GC gc, + int x, int y, unsigned int width, + unsigned int height, int angle1, + int angle2)) +{ + Display *display = MI_DISPLAY (mi); + Window window = MI_WINDOW (mi); + int w, h; + dot_rc_to_pixel (mi, &x, &y); + width_height(mi, &w, &h); + (void) arc_func (display, window, pp->stippledGC, + x, y, w, h, 0, 23040); +} + +static void +draw_bonus_dot (ModeInfo * mi, pacmangamestruct * pp, int x, int y) +{ + int x2 = x; + int y2 = y; + setdotcolor (mi); + draw_dot (mi, pp, x, y, bonus_dot_width_height, XFillArc); + dot_rc_to_pixel (mi, &x2, &y2); +#if 0 + draw_position (mi, x2, y2, 0xff0000); +#endif +} + +static void +clear_bonus_dot (ModeInfo * mi, pacmangamestruct * pp, int x, int y) +{ + cleardotcolor (mi); + draw_dot (mi, pp, x, y, bonus_dot_width_height, XFillArc); +} + +static void +draw_regular_dot (ModeInfo * mi, pacmangamestruct * pp, int x, int y) +{ + setdotcolor (mi); + draw_dot (mi, pp, x, y, dot_width_height, XDrawArc); +} + +/* Draws a block in the level at the specified x and y locations. */ +static void +drawlevelblock (ModeInfo * mi, pacmangamestruct * pp, + const unsigned x, const unsigned y) +{ + Display *display = MI_DISPLAY (mi); + Window window = MI_WINDOW (mi); + int dx = 0, dy = 0; + + if (pp->xs % 2 == 1) + dx = -1; + if (pp->ys % 2 == 1) + dy = -1; + +#ifndef HAVE_COCOA + XSetFillStyle (display, pp->stippledGC, FillSolid); +#endif /* !HAVE_COCOA */ + XSetLineAttributes (display, pp->stippledGC, pp->wallwidth, + LineSolid, CapRound, JoinMiter); + + if (pp->xs < 2 || pp->ys < 2) { + switch (pp->level[y * LEVWIDTH + x]) { + case ' ': + case '=': + break; + case '.': + setdotcolor (mi); + (void) XDrawPoint (display, window, + pp->stippledGC, + x * pp->xs + pp->xb, y * pp->ys + pp->yb); + break; + default: + setwallcolor (mi); + (void) XDrawPoint (display, window, + pp->stippledGC, + x * pp->xs + pp->xb, y * pp->ys + pp->yb); + } + + return; + } + + switch (pp->level[y * LEVWIDTH + x]) { + case ' ': + case '=': + break; + + case '.': + setdotcolor (mi); + if (pp->xs < 8 || pp->ys < 8) { + (void) XDrawPoint (display, window, + pp->stippledGC, + x * pp->xs + pp->xb + + pp->xs / 2, y * pp->ys + pp->yb + pp->ys / 2); + break; + } + + draw_regular_dot (mi, pp, x, y); + break; + /* What we will probably want to do here is have the pp->level store a 'o' for + * the bonus dots. The we can use the drawing routine above just with a bigger + * radius. + */ + case 'o': + draw_bonus_dot (mi, pp, x, y); + break; + + + case '-': + setwallcolor (mi); + (void) XDrawLine (display, window, pp->stippledGC, + (pp->xs * x) + pp->xb, + (pp->ys * y) + (pp->ys / 2) + pp->yb, + (pp->xs * (x + 1)) + pp->xb, + (pp->ys * y) + (pp->ys / 2) + pp->yb); + break; + + case '|': + setwallcolor (mi); + (void) XDrawLine (display, window, pp->stippledGC, + (pp->xs * x) + (pp->xs / 2) + pp->xb, + (pp->ys * y) + pp->yb, + (pp->xs * x) + (pp->xs / 2) + pp->xb, + (pp->ys * (y + 1)) + pp->yb); + break; + + case '_': + setwallcolor (mi); + (void) XDrawArc (display, window, pp->stippledGC, + (pp->xs * x) - (pp->ys / 2) + pp->xb + dx, + (pp->ys * y) + (pp->ys / 2) + pp->yb, + pp->xs, pp->ys, 0 * 64, 90 * 64); + break; + + case ',': + setwallcolor (mi); + (void) XDrawArc (display, window, pp->stippledGC, + (pp->xs * x) + (pp->ys / 2) + pp->xb, + (pp->ys * y) + (pp->ys / 2) + pp->yb, + pp->xs, pp->ys, 90 * 64, 90 * 64); + break; + + case '`': + setwallcolor (mi); + (void) XDrawArc (display, window, pp->stippledGC, + (pp->xs * x) + (pp->ys / 2) + pp->xb, + (pp->ys * y) - (pp->ys / 2) + pp->yb + dy, + pp->xs, pp->ys, 180 * 64, 90 * 64); + break; + + case '\'': + setwallcolor (mi); + (void) XDrawArc (display, window, pp->stippledGC, + (pp->xs * x) - (pp->ys / 2) + pp->xb + dx, + (pp->ys * y) - (pp->ys / 2) + pp->yb + dy, + pp->xs, pp->ys, 270 * 64, 90 * 64); + break; + + } +} + +/* Draws a complete level. */ +static void +drawlevel (ModeInfo * mi) +{ + pacmangamestruct *pp = &pacman_games[MI_SCREEN (mi)]; + unsigned int x, y; + + for (y = 0; y < LEVHEIGHT; y++) + for (x = 0; x < LEVWIDTH; x++) + drawlevelblock (mi, pp, x, y); +} + +/* There is some overlap so it can be made more efficient */ +#define ERASE_IMAGE(d,w,g,x,y,xl,yl,xs,ys) \ + if (yly) \ + (y>(yl-(ys)))?XFillRectangle(d,w,g,xl,y+ys,xs,yl-(y)): \ + XFillRectangle(d,w,g,xl,yl,xs,ys); \ + if (xlx) \ + (x>(xl-(xs)))?XFillRectangle(d,w,g,x+xs,yl,xl-(x),ys): \ + XFillRectangle(d,w,g,xl,yl,xs,ys) + + +/* Draws the pacman sprite, removing the previous location. */ +#if defined(USE_PIXMAP) + +static void +draw_pacman_sprite (ModeInfo * mi) +{ + Display *display = MI_DISPLAY (mi); + Window window = MI_WINDOW (mi); + pacmangamestruct *pp = &pacman_games[MI_SCREEN (mi)]; + unsigned int dir = 0; + int old_mask_dir = 0; + int old_mask_mouth = 0; + Pixmap old_mask, new_mask; + Pixmap pacman; + +#define MAX_MOUTH_DELAY 2 +#define MAX_DEATH_DELAY 20 + + if (pp->pacman.aistate == ps_dieing){ + pp->pacman.cf = pp->pacman.oldcf; + pp->pacman.rf = pp->pacman.oldrf; + } + else { + pp->pacman.cf = pp->pacman.col * pp->xs + pp->pacman.delta.x * + pp->pacman.cfactor + pp->xb + pp->spritedx; + pp->pacman.rf = pp->pacman.row * pp->ys + pp->pacman.delta.y * + pp->pacman.rfactor + pp->yb + pp->spritedy; + } + + dir = (ABS (pp->pacman.cfactor) * (2 - pp->pacman.cfactor) + + ABS (pp->pacman.rfactor) * (1 + pp->pacman.rfactor)) % 4; + + if (pp->pm_mouth_delay == MAX_MOUTH_DELAY) { + if (pp->pm_mouth == (MAXMOUTH - 1) || pp->pm_mouth == 0) { + pp->pm_open_mouth = !pp->pm_open_mouth; + } + pp->pm_open_mouth ? pp->pm_mouth++ : pp->pm_mouth--; + pp->pm_mouth_delay = 0; + } + else { + pp->pm_mouth_delay++; + } + + if (pp->pacman.aistate == ps_dieing){ + if (pp->pm_death_frame >= PAC_DEATH_FRAMES) { + pp->pacman.aistate = ps_eating; + pp->pm_death_frame = 0; + pp->pm_death_delay = 0; + reset_level (mi, 0, False); + return; + } + else { + old_mask = pp->pacmanMask[0][0]; + new_mask = pp->pacmanMask[0][0]; + pacman = pp->pacman_ds[pp->pm_death_frame]; + if (pp->pm_death_delay == MAX_DEATH_DELAY){ + pp->pm_death_frame++; + pp->pm_death_delay = 0; + } + else{ + pp->pm_death_delay++; + } + } + } + else{ + old_mask = pp->pacmanMask[old_mask_dir][old_mask_mouth]; + new_mask = pp->pacmanMask[dir][pp->pm_mouth]; + pacman = pp->pacmanPixmap[dir][pp->pm_mouth]; + } + + XSetForeground (display, pp->stippledGC, MI_BLACK_PIXEL (mi)); + + XSetClipMask (display, pp->stippledGC, old_mask); + + XSetClipOrigin (display, pp->stippledGC, pp->pacman.oldcf, + pp->pacman.oldrf); + XFillRectangle (display, window, pp->stippledGC, pp->pacman.oldcf, + pp->pacman.oldrf, pp->spritexs, pp->spriteys); + XSetClipMask (display, pp->stippledGC, new_mask); + XSetClipOrigin (display, pp->stippledGC, pp->pacman.cf, pp->pacman.rf); + XCopyArea (display, pacman, window, + pp->stippledGC, 0, 0, pp->spritexs, pp->spriteys, + pp->pacman.cf, pp->pacman.rf); + XSetClipMask (display, pp->stippledGC, None); + if (pp->pacman.aistate != ps_dieing){ + pp->pacman.oldcf = pp->pacman.cf; + pp->pacman.oldrf = pp->pacman.rf; + } +} + +#if 0 +static void +draw_ghost_position (ModeInfo * mi, ghoststruct * ghost) +{ + draw_position (mi, ghost->oldcf, ghost->oldrf, MI_BLACK_PIXEL (mi)); + draw_position (mi, ghost->cf, ghost->rf, 0x00ff00); +} +#endif +#if 0 +static void +draw_ghost_ndirs ( ModeInfo *mi, ghoststruct * ghost) +{ + draw_number (mi, ghost->oldcf, ghost->oldrf, ghost->oldndirs, MI_BLACK_PIXEL (mi)); + ghost->oldndirs = ghost->ndirs; + draw_number (mi, ghost->cf, ghost->rf, ghost->ndirs, 0x00ff00); +} + +#endif + +static void +draw_ghost_sprite (ModeInfo * mi, const unsigned ghost) +{ + Display *display = MI_DISPLAY (mi); + Window window = MI_WINDOW (mi); + pacmangamestruct *pp = &pacman_games[MI_SCREEN (mi)]; +#define MAX_WAG_COUNT 50 + unsigned int dir = 0; + unsigned int fs = 0; /*flash scared*/ + Pixmap g_pix; /*ghost pixmap*/ + + + dir = (ABS (pp->ghosts[ghost].cfactor) * (2 - pp->ghosts[ghost].cfactor) + + ABS (pp->ghosts[ghost].rfactor) * (1 + pp->ghosts[ghost].rfactor)) % 4; + + + fs = pp->ghosts[ghost].flash_scared; + assert (fs == 0 || fs == 1); + + /* Choose the pixmap */ + switch (pp->ghosts[ghost].aistate){ + case hiding: + g_pix = pp->s_ghostPixmap[fs][pp->gh_wag]; + break; + case goingin: + g_pix = pp->ghostEyes[dir]; +#if 1 + { + int i = 0; + while ( i < pp->ghosts[ghost].trace_idx ){ + XFillRectangle (display, + window, + pp->stippledGC, + pp->ghosts[ghost].trace[i].vx, + pp->ghosts[ghost].trace[i].vy, + pp->spritexs, pp->spriteys); + + i++; + } + } +#endif + + break; + default: + g_pix = pp->ghostPixmap[ghost][dir][pp->gh_wag]; + } + + pp->ghosts[ghost].cf = + pp->ghosts[ghost].col * pp->xs + pp->ghosts[ghost].delta.x * + pp->ghosts[ghost].cfactor + pp->xb + pp->spritedx; + pp->ghosts[ghost].rf = + pp->ghosts[ghost].row * pp->ys + pp->ghosts[ghost].delta.y * + pp->ghosts[ghost].rfactor + pp->yb + pp->spritedy; + + XSetForeground (display, pp->stippledGC, MI_BLACK_PIXEL (mi)); + + XSetClipMask (display, pp->stippledGC, pp->ghostMask); + XSetClipOrigin (display, pp->stippledGC, + pp->ghosts[ghost].oldcf, pp->ghosts[ghost].oldrf); + XFillRectangle (display, + window, + pp->stippledGC, + pp->ghosts[ghost].oldcf, + pp->ghosts[ghost].oldrf, pp->spritexs, pp->spriteys); + + + if (pp->pacman.aistate != ps_dieing) { + drawlevelblock (mi, pp, + (unsigned int) pp->ghosts[ghost].col, + (unsigned int) pp->ghosts[ghost].row); + + + + XSetClipOrigin (display, pp->stippledGC, + pp->ghosts[ghost].cf, pp->ghosts[ghost].rf); + + XCopyArea (display, g_pix, window, pp->stippledGC, 0, 0, + pp->spritexs, pp->spriteys, pp->ghosts[ghost].cf, + pp->ghosts[ghost].rf); + } + XSetClipMask (display, pp->stippledGC, None); + +#if 0 + draw_ghost_position (mi, &(pp->ghosts[ghost])); +#endif + +#if 0 + draw_ghost_ndirs ( mi, &(pp->ghosts[ghost])); +#endif + + if (pp->pacman.aistate != ps_dieing) { + pp->ghosts[ghost].oldcf = pp->ghosts[ghost].cf; + pp->ghosts[ghost].oldrf = pp->ghosts[ghost].rf; + if (pp->gh_wag_count++ == MAX_WAG_COUNT) { + pp->gh_wag = !pp->gh_wag; + pp->gh_wag_count = 0; + } + } +} + +#else /* USE_PIXMAP */ + +/* Draws the pacman sprite, removing the previous location. */ +static void +draw_pacman_sprite (ModeInfo * mi) +{ + Display *display = MI_DISPLAY (mi); + Window window = MI_WINDOW (mi); + pacmangamestruct *pp = &pacman_games[MI_SCREEN (mi)]; + unsigned int dir; + + pp->pacman.cf = pp->pacman.col * pp->xs + pp->pacman.delta.x * + pp->pacman.cfactor + pp->xb + pp->spritedx; + pp->pacman.rf = pp->pacman.row * pp->ys + pp->pacman.delta.y * + pp->pacman.rfactor + pp->yb + pp->spritedy; + + dir = (ABS (pp->pacman.cfactor) * (2 - pp->pacman.cfactor) + + ABS (pp->pacman.rfactor) * (1 + pp->pacman.rfactor)) % 4; + + XSetForeground (display, pp->stippledGC, MI_BLACK_PIXEL (mi)); + if (pp->pacman.oldcf != NOWHERE && pp->pacman.oldrf != NOWHERE) { + + ERASE_IMAGE (display, window, pp->stippledGC, + pp->pacman.cf, pp->pacman.rf, + pp->pacman.oldcf, pp->pacman.oldrf, + pp->spritexs, pp->spriteys); + } + + if (MI_NPIXELS (mi) > 2) + XSetForeground (display, pp->stippledGC, MI_PIXEL (mi, YELLOW)); + else + XSetForeground (display, pp->stippledGC, MI_WHITE_PIXEL (mi)); + + XSetFillStyle (display, pp->stippledGC, FillOpaqueStippled); + + if (pp->xs < 2 || pp->ys < 2) + XDrawPoint (display, window, pp->stippledGC, + pp->pacman.cf, pp->pacman.rf); + else + XFillRectangle (display, window, pp->stippledGC, + pp->pacman.cf, pp->pacman.rf, + pp->spritexs, pp->spriteys); + pp->pacman.mouthstage += pp->pacman.mouthdirection; + if ((pp->pacman.mouthstage >= MAXMOUTH) || (pp->pacman.mouthstage < 0)) { + pp->pacman.mouthdirection *= -1; + pp->pacman.mouthstage += pp->pacman.mouthdirection * 2; + } + pp->pacman.oldcf = pp->pacman.cf; + pp->pacman.oldrf = pp->pacman.rf; +} + +/* Draws a ghost sprite, removing the previous sprite and restores the level. */ +static void +draw_ghost_sprite (ModeInfo * mi, const unsigned ghost) +{ + Display *display = MI_DISPLAY (mi); + Window window = MI_WINDOW (mi); + pacmangamestruct *pp = &pacman_games[MI_SCREEN (mi)]; + + pp->ghosts[ghost].cf = + pp->ghosts[ghost].col * pp->xs + pp->ghosts[ghost].delta.x * + pp->ghosts[ghost].cfactor + pp->xb + pp->spritedx; + pp->ghosts[ghost].rf = + pp->ghosts[ghost].row * pp->ys + pp->ghosts[ghost].delta.y * + pp->ghosts[ghost].rfactor + pp->yb + pp->spritedy; + + XSetForeground (display, pp->stippledGC, MI_BLACK_PIXEL (mi)); + XFillRectangle (display, + window, + pp->stippledGC, + pp->ghosts[ghost].cf, + pp->ghosts[ghost].rf, pp->spritexs, pp->spriteys); + + if (pp->ghosts[ghost].oldcf != NOWHERE || + pp->ghosts[ghost].oldrf != NOWHERE) { + + ERASE_IMAGE (display, window, pp->stippledGC, + pp->ghosts[ghost].cf, pp->ghosts[ghost].rf, + pp->ghosts[ghost].oldcf, pp->ghosts[ghost].oldrf, + pp->spritexs, pp->spriteys); + } + + drawlevelblock (mi, pp, + (unsigned int) pp->ghosts[ghost].col, + (unsigned int) pp->ghosts[ghost].row); + + if (MI_NPIXELS (mi) > 2) + XSetForeground (display, pp->stippledGC, MI_PIXEL (mi, GREEN)); + else + XSetForeground (display, pp->stippledGC, MI_WHITE_PIXEL (mi)); + + XSetFillStyle (display, pp->stippledGC, FillOpaqueStippled); + + if (pp->xs < 2 || pp->ys < 2) + XDrawPoint (display, window, pp->stippledGC, + pp->ghosts[ghost].cf, pp->ghosts[ghost].rf); + else + XFillRectangle (display, + window, + pp->stippledGC, + pp->ghosts[ghost].cf, + pp->ghosts[ghost].rf, pp->spritexs, pp->spriteys); + + pp->ghosts[ghost].oldcf = pp->ghosts[ghost].cf; + pp->ghosts[ghost].oldrf = pp->ghosts[ghost].rf; +} +#endif /* USE_PIXMAP */ + +static int +ghost_over (ModeInfo * mi, int x, int y) +{ + int ghost = 0; + int ret = False; + pacmangamestruct *pp = &pacman_games[MI_SCREEN (mi)]; + dot_rc_to_pixel (mi, &x, &y); + for (ghost = 0; ghost < pp->nghosts; ghost++) { + if ((pp->ghosts[ghost].cf <= x + && x <= pp->ghosts[ghost].cf + pp->spritexs) + && (pp->ghosts[ghost].rf <= y + && y <= pp->ghosts[ghost].rf + pp->spriteys)) { + ret = True; + break; + } + } + return ret; +} + + +static void +flash_bonus_dots (ModeInfo * mi) +{ +#define MAX_FLASH_COUNT 25 + pacmangamestruct *pp = &pacman_games[MI_SCREEN (mi)]; + int i, x, y; + for (i = 0; i < NUM_BONUS_DOTS; i++) { + if (!pacman_bonus_dot_eaten (pp, i)) { + pacman_bonus_dot_pos (pp, i, &x, &y); + if (ghost_over (mi, x, y)) + continue; + if (pp->bd_on) + draw_bonus_dot (mi, pp, x, y); + else + clear_bonus_dot (mi, pp, x, y); + } + } + if (pp->bd_flash_count-- == 0) { + pp->bd_flash_count = MAX_FLASH_COUNT; + pp->bd_on = !pp->bd_on; + } +} + +static unsigned int +ate_bonus_dot (ModeInfo * mi) +{ + /*Check pacman's position. If it is over a bonus dot and that dot + *has not been eaten, then return true + */ + unsigned int ret = 0; + int idx = 0; + pacmangamestruct *pp = &pacman_games[MI_SCREEN (mi)]; + if (pacman_is_bonus_dot (pp, pp->pacman.col, pp->pacman.row, &idx)) { + ret = !pacman_bonus_dot_eaten (pp, idx); + pacman_eat_bonus_dot (pp, idx); + } + return ret; +} + +static void +ghost_scared (ModeInfo * mi) +{ + unsigned int ghost; + pacmangamestruct *pp = &pacman_games[MI_SCREEN (mi)]; + for (ghost = 0; ghost < pp->nghosts; ghost++) { + if (pp->ghosts[ghost].aistate == goingin || + pp->ghosts[ghost].aistate == goingout || + pp->ghosts[ghost].aistate == inbox ) continue; + pp->ghosts[ghost].aistate = hiding; + pp->ghosts[ghost].flash_scared = 0; + if (pp->pacman.aistate != ps_dieing) + pp->pacman.aistate = ps_chasing; + } +} + +static void +ghost_not_scared (ModeInfo * mi) +{ + unsigned int ghost; + pacmangamestruct *pp = &pacman_games[MI_SCREEN (mi)]; + for (ghost = 0; ghost < pp->nghosts; ghost++){ + if (pp->ghosts[ghost].aistate == goingin || + pp->ghosts[ghost].aistate == goingout || + pp->ghosts[ghost].aistate == inbox ) continue; + pp->ghosts[ghost].aistate = chasing; + } + if (pp->pacman.aistate != ps_dieing) + pp->pacman.aistate = ps_eating; + +} + +static void +ghost_flash_scared (ModeInfo * mi) +{ + unsigned int ghost; + pacmangamestruct *pp = &pacman_games[MI_SCREEN (mi)]; + for (ghost = 0; ghost < pp->nghosts; ghost++) + pp->ghosts[ghost].flash_scared = !pp->ghosts[ghost].flash_scared; +} + +/* Does all drawing of moving sprites in the level. */ +static void +pacman_tick (ModeInfo * mi) +{ +#define DEFAULT_SCARED_TIME 500 +#define START_FLASH 200 +#define FLASH_COUNT 25 + + pacmangamestruct *pp = &pacman_games[MI_SCREEN (mi)]; + unsigned int ghost; +#if 0 + draw_grid (mi); +#endif + for (ghost = 0; ghost < pp->nghosts; ghost++) { + draw_ghost_sprite (mi, ghost); +#if 0 + print_ghost_stats (mi, &(pp->ghosts[ghost]), ghost); +#endif + } +#if 0 + print_pac_stats (mi, &(pp->pacman)); +#endif + draw_pacman_sprite (mi); + flash_bonus_dots (mi); + if (ate_bonus_dot (mi)) { + pp->ghost_scared_timer = (random () % 100) + DEFAULT_SCARED_TIME; + ghost_scared (mi); + } + + if (pp->ghost_scared_timer > 0) { + if (--pp->ghost_scared_timer == 0) + ghost_not_scared (mi); + else if (pp->ghost_scared_timer <= START_FLASH) { + if (pp->flash_timer <= 0) { + pp->flash_timer = FLASH_COUNT; + ghost_flash_scared (mi); + } + pp->flash_timer--; + } + } + + /* + We don't want to miss the last death sequence. So if pacman has died three times + we wait for his state to change from dieing to something else before we repopulate + the level. If pacman ate all of the dots then we just repopulate. + */ + + if (pp->dotsleft == 0 ) + repopulate (mi); + else if (pp->pacman.deaths >= 3){ + if (pp->old_pac_state == ps_dieing && pp->pacman.aistate != ps_dieing) + repopulate (mi); + } + + pp->old_pac_state = pp->pacman.aistate; +} + + +/* CODE TO LOAD AND SCALE THE PIXMAPS + */ + +#if defined(USE_PIXMAP) +/* Grabbed the scaling routine off of usenet. + * Changed it so that the information specific + * to the source pixmap does not have to be a parameter. + * + * There is probably a better way to scale pixmaps. + * From: Chris Fiddyment (cxf@itd.dsto.gov.au) + * Subject: Scaling Pixmap Algorithm. + * Newsgroups: comp.graphics.algorithms + * Date: 1994-07-06 18:51:38 PST + * -jeremy + */ + +static Pixmap +scale_pixmap (Display ** dpy, GC gc, Pixmap source, int dwidth, int dheight) +{ + Pixmap temp, dest; + int j, end; + float i; + float xscale, yscale; + unsigned int swidth, sheight; + Window window; + int x, y; + unsigned border_width_return, depth; + XGetGeometry (*dpy, source, &window, &x, &y, &swidth, &sheight, + &border_width_return, &depth); + + xscale = (float) swidth / (float) dwidth; /* Scaling factors */ + yscale = (float) sheight / (float) dheight; + + dest = XCreatePixmap (*dpy, window, dwidth, dheight, depth); + if (!dest) { + fprintf (stderr, "%s Could not scale image", progname); + } + temp = XCreatePixmap (*dpy, window, dwidth, sheight, depth); + if (!temp) { + fprintf (stderr, "%s Could not scale image", progname); + } + + j = 0; + end = dwidth * xscale; + /* Scale width of source into temp pixmap */ + for (i = 0; i <= end; i += xscale) + XCopyArea (*dpy, source, temp, gc, i, 0, 1, sheight, j++, 0); + + j = 0; + end = dheight * yscale; + /* Scale height of temp into dest pixmap */ + for (i = 0; i <= end; i += yscale) + XCopyArea (*dpy, temp, dest, gc, 0, i, swidth, 1, 0, j++); + + XFreePixmap (*dpy, temp); + return (Pixmap) dest; +} + +static void +pacman_fail (char *s) +{ + fprintf (stderr, "%s: %s\n", progname, s); + exit (1); +} + +/* Load the ghost pixmaps and their mask. */ +static void +load_ghost_pixmaps (Display ** dpy, Window window, pacmangamestruct ** ps) +{ + pacmangamestruct *pp = *ps; + Display *display = *dpy; + char *colors[] = { + ". c #FF0000", /*Red */ + ". c #00FFDE", /*Blue */ + ". c #FFB847", /*Orange */ + ". c #FFB8DE", /*Pink */ + }; + + char **bits[] = { + ghost_u1_xpm, ghost_u2_xpm, ghost_r1_xpm, ghost_r2_xpm, + ghost_d1_xpm, ghost_d2_xpm, ghost_l1_xpm, ghost_l2_xpm + }; + char * const *s_bits[] = { + ghost_s1_xpm, ghost_s2_xpm, + ghost_sf1_xpm, ghost_sf2_xpm + }; + char * const *e_bits[] = { + eyes_u_xpm, eyes_r_xpm, eyes_d_xpm, eyes_l_xpm + }; + + int i, j, k, m; + int w = pp->spritexs; + int h = pp->spriteys; + GC gc = 0; + Pixmap temp; + + for (i = 0; i < 4; i++) { + m = 0; + for (j = 0; j < MAXGDIR; j++) { + for (k = 0; k < MAXGWAG; k++) { + bits[m][2] = colors[i]; + pp->ghostPixmap[i][j][k] = + xpm_data_to_pixmap (display, window, bits[m], &w, &h, + &pp->ghostMask); + + if (!pp->ghostPixmap[i][j][k]) + pacman_fail ("Cannot load ghost images"); + + pp->ghostPixmap[i][j][k] = + scale_pixmap (&display, pp->stippledGC, + pp->ghostPixmap[i][j][k], pp->spritexs, + pp->spriteys); + + if (!pp->ghostPixmap[i][j][k]) + pacman_fail ("Cannot scale ghost images"); + m++; + } + } + } + /* load the scared ghost */ + m = 0; + for (i = 0; i < MAXGFLASH; i++) { + for (j = 0; j < MAXGWAG; j++) { + pp->s_ghostPixmap[i][j] = + xpm_data_to_pixmap (display, window, s_bits[m++], &w, &h, + &pp->ghostMask); + + if (!pp->s_ghostPixmap[i][j]) + pacman_fail ("Cannot Scare Ghost images"); + pp->s_ghostPixmap[i][j] = scale_pixmap (&display, pp->stippledGC, + pp->s_ghostPixmap[i][j], + pp->spritexs, + pp->spriteys); + + if (!pp->s_ghostPixmap[i][j]) + pacman_fail ("Cannot scale Scared Ghost images"); + } + } + /* load the ghost eyes */ + for (i = 0; i < MAXGDIR; i++) { + pp->ghostEyes[i] = + xpm_data_to_pixmap (display, window, e_bits[i], &w, &h, + &pp->ghostMask); + + if (!pp->ghostEyes[i]) + pacman_fail ("Cannot open ghost eye images"); + + pp->ghostEyes[i] = scale_pixmap (&display, pp->stippledGC, + pp->ghostEyes[i], + pp->spritexs, + pp->spriteys); + + if (!pp->ghostEyes[i]) + pacman_fail ("Cannot open ghost eye images"); + } + + + + /* We really only need a single mask. This saves the headache of getting the + * bottom of the ghost to clip just right. What we'll do is mask + * the top portion of the ghost, but the bottom of the ghost will be solid. + * I did this by setting the pixels between the fringe of their sheets + * to black instead of none. -jeremy + */ + temp = xpm_data_to_pixmap (display, window, ghost_mask_xpm, + &w, &h, &pp->ghostMask); + + if (!temp) + pacman_fail ("Cannot load temporary ghost image"); + + temp = scale_pixmap (&display, pp->stippledGC, + temp, pp->spritexs, pp->spriteys); + + if (!temp) + pacman_fail ("Cannot scale temporary ghost image"); + + gc = XCreateGC (display, pp->ghostMask, 0, 0); + + pp->ghostMask = scale_pixmap (&display, gc, pp->ghostMask, + pp->spritexs, pp->spriteys); + XFreePixmap (display, temp); +} + +/* Load the pacman pixmaps and their mask. */ +static void +load_pacman_pixmaps (Display ** dpy, Window window, pacmangamestruct ** ps) +{ + pacmangamestruct *pp = *ps; + Display *display = *dpy; + + char **bits[] = { + pacman_0_xpm, pacman_u1_xpm, pacman_u2_xpm, + pacman_0_xpm, pacman_r1_xpm, pacman_r2_xpm, + pacman_0_xpm, pacman_d1_xpm, pacman_d2_xpm, + pacman_0_xpm, pacman_l1_xpm, pacman_l2_xpm + }; + + char * const *ds_bits[] = { + pacman_ds1_xpm, pacman_ds2_xpm, pacman_ds3_xpm, pacman_ds4_xpm, + pacman_ds5_xpm, pacman_ds6_xpm, pacman_ds7_xpm, pacman_ds8_xpm + }; + + int i, j, m; + int w = pp->spritexs; + int h = pp->spriteys; + GC gc = 0; + + m = 0; + for (i = 0; i < 4; i++) { + for (j = 0; j < MAXMOUTH; j++) { + pp->pacmanPixmap[i][j] = + xpm_data_to_pixmap (display, window, bits[m++], &w, &h, + &pp->pacmanMask[i][j]); + + if (!pp->pacmanPixmap[i][j]) + pacman_fail ("Cannot load pacman pixmap."); + + pp->pacmanPixmap[i][j] = scale_pixmap (&display, pp->stippledGC, + pp->pacmanPixmap[i][j], + pp->spritexs, + pp->spriteys); + + if (!pp->pacmanPixmap[i][j]) + pacman_fail ("Cannot scale pacman pixmap."); + + if (!gc) + gc = XCreateGC (display, pp->pacmanMask[i][j], 0, 0); + + pp->pacmanMask[i][j] = + scale_pixmap (&display, gc, pp->pacmanMask[i][j], + pp->spritexs, pp->spriteys); + } + } + + /* Load pacman death sequence */ + for ( i = 0; i < PAC_DEATH_FRAMES; i++ ){ + pp->pacman_ds[i] = + xpm_data_to_pixmap (display, window, ds_bits[i], &w, &h, + &pp->pacman_ds_mask[i]); + + if (!pp->pacman_ds[i]) + pacman_fail ("Cannot load pacman death frame."); + + pp->pacman_ds[i] = scale_pixmap ( &display, pp->stippledGC, + pp->pacman_ds[i], + pp->spritexs, + pp->spriteys); + + if (!pp->pacman_ds[i]) + pacman_fail ("Cannot scale pixmap."); + + if (!gc) + gc = XCreateGC (display, pp->pacman_ds_mask[i], 0, 0); + + pp->pacman_ds_mask[i] = + scale_pixmap (&display, gc, pp->pacman_ds_mask[i], + pp->spritexs, pp->spriteys); + } + +} +#endif /* USE_PIXMAP */ + +/* Hook function, sets state to initial position. */ +ENTRYPOINT void +init_pacman (ModeInfo * mi) +{ + Display *display = MI_DISPLAY (mi); + Window window = MI_WINDOW (mi); + int size = MI_SIZE (mi); + pacmangamestruct *pp; + XGCValues gcv; + int i, j, k; + +#if (! defined( USE_PIXMAP )) + GC fg_gc, bg_gc; + XPoint points[9]; + int dir, mouth; +#endif + + if (pacman_games == NULL) { + if ((pacman_games = (pacmangamestruct *) + calloc ((size_t) MI_NUM_SCREENS (mi), + sizeof (pacmangamestruct))) == NULL) + return; + } + pp = &pacman_games[MI_SCREEN (mi)]; + + pp->width = (unsigned short) MI_WIDTH (mi); + pp->height = (unsigned short) MI_HEIGHT (mi); + for (i = 0; i < 4; i++) { + for (j = 0; j < MAXGDIR; j++) { + for (k = 0; k < MAXGWAG; k++) { + if (pp->ghostPixmap[i][j][k] != None) { + XFreePixmap (display, pp->ghostPixmap[i][j][k]); + pp->ghostPixmap[i][j][k] = None; + pp->graphics_format = 0 /*IS_NONE */ ; + } + } + } + } + + for (i = 0; i < MAXGFLASH; i++) { + for (j = 0; j < MAXGWAG; j++) { + if (pp->s_ghostPixmap[i][j] != None) { + XFreePixmap (display, pp->s_ghostPixmap[i][j]); + pp->s_ghostPixmap[i][j] = None; + } + } + } + + if (size == 0 || + MINGRIDSIZE * size > (int) pp->width || + MINGRIDSIZE * size > (int) pp->height) { + + pp->ys = pp->xs = MAX (MIN (pp->width / LEVWIDTH, + pp->height / LEVHEIGHT), 1); + } + else { + if (size < -MINSIZE) + pp->ys = (short) (NRAND (MIN (-size, MAX (MINSIZE, + MIN (pp->width, + pp->height) / + MINGRIDSIZE)) + - MINSIZE + 1) + MINSIZE); + else if (size < MINSIZE) + pp->ys = MINSIZE; + else + pp->ys = (short) (MIN (size, + MAX (MINSIZE, MIN (pp->width, pp->height) / + MINGRIDSIZE))); + pp->xs = pp->ys; + } + + pp->wallwidth = (unsigned int) (pp->xs + pp->ys) >> 4; + if (pp->wallwidth < 1) + pp->wallwidth = 1; + pp->incx = (pp->xs >> 3) + 1; + pp->incy = (pp->ys >> 3) + 1; + pp->ncols = (unsigned short) MAX (LEVWIDTH, 2); + pp->nrows = (unsigned short) MAX (LEVHEIGHT, 2); + pp->xb = (pp->width - pp->ncols * pp->xs) >> 1; + pp->yb = (pp->height - pp->nrows * pp->ys) >> 1; + pp->spritexs = MAX (pp->xs + (pp->xs >> 1) - 1, 1); + pp->spriteys = MAX (pp->ys + (pp->ys >> 1) - 1, 1); + pp->spritedx = (pp->xs - pp->spritexs) >> 1; + pp->spritedy = (pp->ys - pp->spriteys) >> 1; + pp->old_pac_state = ps_chasing; + + if (!pp->stippledGC) { + gcv.foreground = MI_BLACK_PIXEL (mi); + gcv.background = MI_BLACK_PIXEL (mi); + if ((pp->stippledGC = XCreateGC (display, window, + GCForeground | GCBackground, + &gcv)) == None) { + free_pacman (display, pp); + return; + } + } + +#ifdef HAVE_COCOA + jwxyz_XSetAntiAliasing (display, pp->stippledGC, False); +#endif + +#if defined(USE_PIXMAP) + load_ghost_pixmaps (&display, window, &pp); + load_pacman_pixmaps (&display, window, &pp); +#else + if ((pp->ghostPixmap[0][0][0] = XCreatePixmap (display, window, + pp->spritexs, pp->spriteys, + 1)) == None) { + free_pacman (display, pp); + return; + } + + gcv.foreground = 0; + gcv.background = 1; + if ((bg_gc = XCreateGC (display, pp->ghostPixmap[0][0][0], + GCForeground | GCBackground, &gcv)) == None) { + free_pacman (display, pp); + return; + } + + gcv.foreground = 1; + gcv.background = 0; + if ((fg_gc = XCreateGC (display, pp->ghostPixmap[0][0][0], + GCForeground | GCBackground, &gcv)) == None) { + XFreeGC (display, bg_gc); + free_pacman (display, pp); + return; + } + +#define SETPOINT(p, xp, yp) p.x = xp; p.y = yp + + /* draw the triangles on the bottom (scalable) */ + SETPOINT (points[0], 1, pp->spriteys * 5 / 6); + SETPOINT (points[1], pp->spritexs / 6, pp->spriteys); + SETPOINT (points[2], pp->spritexs / 3, pp->spriteys * 5 / 6); + SETPOINT (points[3], pp->spritexs / 2, pp->spriteys); + SETPOINT (points[4], pp->spritexs * 2 / 3, pp->spriteys * 5 / 6); + SETPOINT (points[5], pp->spritexs * 5 / 6, pp->spriteys); + SETPOINT (points[6], pp->spritexs, pp->spriteys * 5 / 6); + SETPOINT (points[7], pp->spritexs, pp->spriteys / 2); + SETPOINT (points[8], 1, pp->spriteys / 2); + + XFillRectangle (display, pp->ghostPixmap[0][0][0], bg_gc, + 0, 0, pp->spritexs, pp->spriteys); + XFillArc (display, pp->ghostPixmap[0][0][0], fg_gc, + 0, 0, pp->spritexs, pp->spriteys, 0, 11520); + XFillPolygon (display, pp->ghostPixmap[0][0][0], fg_gc, + points, 9, Nonconvex, CoordModeOrigin); + XFreeGC (display, bg_gc); + XFreeGC (display, fg_gc); + + + if (pp->pacmanPixmap[0][0] != None) + for (dir = 0; dir < 4; dir++) + for (mouth = 0; mouth < MAXMOUTH; mouth++) + XFreePixmap (display, pp->pacmanPixmap[dir] + [mouth]); + + for (dir = 0; dir < 4; dir++) + for (mouth = 0; mouth < MAXMOUTH; mouth++) { + if ((pp->pacmanPixmap[dir][mouth] = + XCreatePixmap (display, MI_WINDOW (mi), pp->spritexs, + pp->spriteys, 1)) == None) { + free_pacman (display, pp); + return; + } + gcv.foreground = 1; + gcv.background = 0; + if ((fg_gc = XCreateGC (display, pp->pacmanPixmap[dir][mouth], + GCForeground | GCBackground, + &gcv)) == None) { + free_pacman (display, pp); + return; + } + gcv.foreground = 0; + gcv.background = 0; + if ((bg_gc = XCreateGC (display, + pp->pacmanPixmap[dir][mouth], + GCForeground | + GCBackground, &gcv)) == None) { + XFreeGC (display, fg_gc); + free_pacman (display, pp); + return; + } + XFillRectangle (display, + pp->pacmanPixmap[dir][mouth], bg_gc, + 0, 0, pp->spritexs, pp->spriteys); + if (pp->spritexs == 1 && pp->spriteys == 1) + XFillRectangle (display, + pp->pacmanPixmap[dir][mouth], + fg_gc, 0, 0, pp->spritexs, pp->spriteys); + else + XFillArc (display, + pp->pacmanPixmap[dir][mouth], + fg_gc, + 0, 0, pp->spritexs, pp->spriteys, + ((90 - dir * 90) + mouth * 5) * 64, + (360 + (-2 * mouth * 5)) * 64); + XFreeGC (display, fg_gc); + XFreeGC (display, bg_gc); + } +#endif /* USE_PIXMAP */ + + pp->pacman.lastbox = START; + pp->pacman.mouthdirection = 1; + pp->pacman.nextcol = NOWHERE; + pp->pacman.nextrow = NOWHERE; + + if (pp->ghosts != NULL) { + free (pp->ghosts); + pp->ghosts = (ghoststruct *) NULL; + } + pp->nghosts = GHOSTS; + + if (!pp->ghosts) + if ((pp->ghosts = (ghoststruct *) calloc ((size_t) pp->nghosts, + sizeof (ghoststruct))) == + NULL) { + free_pacman (display, pp); + return; + } + + pp->pacman.mouthstage = MAXMOUTH - 1; + + MI_CLEARWINDOW (mi); + repopulate (mi); +} + +/* Callback function called for each tick. This is the complete machinery of + everything that moves. */ +ENTRYPOINT void +draw_pacman (ModeInfo * mi) +{ + unsigned int g; + pacmangamestruct *pp; + + if (pacman_games == NULL) + return; + pp = &pacman_games[MI_SCREEN (mi)]; + if (pp->ghosts == NULL) + return; + + pp->pacman.err.x = (pp->pacman.err.x + 1) % pp->pacman.speed; + pp->pacman.err.y = (pp->pacman.err.y + 1) % pp->pacman.speed; + pp->pacman.delta.x += pp->pacman.err.x != 0 ? pp->incx : 0; + pp->pacman.delta.y += pp->pacman.err.y != 0 ? pp->incy : 0; + + if (pp->pacman.delta.x >= pp->xs && pp->pacman.delta.y >= pp->ys) { + pacman_update (mi, pp, &(pp->pacman)); + check_death (mi, pp); + pp->pacman.delta.x = pp->incx; + pp->pacman.delta.y = pp->incy; + } + + if (pp->pacman.delta.x > pp->xs + pp->incx) + pp->pacman.delta.x = pp->xs + pp->incx; + if (pp->pacman.delta.y > pp->ys + pp->incy) + pp->pacman.delta.y = pp->ys + pp->incy; + + for (g = 0; g < pp->nghosts; g++) { + pp->ghosts[g].err.x = (pp->ghosts[g].err.x + 1) % pp->ghosts[g].speed; + pp->ghosts[g].err.y = (pp->ghosts[g].err.y + 1) % pp->ghosts[g].speed; + pp->ghosts[g].delta.x += pp->ghosts[g].err.x != 0 ? pp->incx : 0; + pp->ghosts[g].delta.y += pp->ghosts[g].err.y != 0 ? pp->incy : 0; + + if (pp->ghosts[g].delta.x >= pp->xs && + pp->ghosts[g].delta.y >= pp->ys) { + pacman_ghost_update (pp, &(pp->ghosts[g])); + pp->ghosts[g].delta.x = pp->incx; + pp->ghosts[g].delta.y = pp->incy; + } + + if (pp->ghosts[g].delta.x > pp->xs + pp->incx) + pp->ghosts[g].delta.x = pp->xs + pp->incx; + if (pp->ghosts[g].delta.y > pp->ys + pp->incy) + pp->ghosts[g].delta.y = pp->ys + pp->incy; + } + pacman_tick (mi); +} + +/* Releases resources. */ +ENTRYPOINT void +release_pacman (ModeInfo * mi) +{ + if (pacman_games != NULL) { + int screen; + + for (screen = 0; screen < MI_NUM_SCREENS (mi); screen++) + free_pacman (MI_DISPLAY (mi), &pacman_games[screen]); + free (pacman_games); + pacman_games = (pacmangamestruct *) NULL; + } +} + +/* Refresh current level. */ +ENTRYPOINT void +refresh_pacman (ModeInfo * mi) +{ + drawlevel (mi); + pacman_tick (mi); +} + +ENTRYPOINT void +reshape_pacman(ModeInfo * mi, int width, int height) +{ + pacmangamestruct *pp = &pacman_games[MI_SCREEN (mi)]; + pp->width = width; + pp->height = height; + MI_CLEARWINDOW (mi); + /* repopulate (mi); */ + drawlevel (mi); +} + +#ifndef STANDALONE +/* Callback to change level. */ +ENTRYPOINT void +change_pacman (ModeInfo * mi) +{ + MI_CLEARWINDOW (mi); + repopulate (mi); +} +#endif /* !STANDALONE */ + + +XSCREENSAVER_MODULE ("Pacman", pacman) + +#endif /* MODE_pacman */ diff --git a/hacks/pacman.h b/hacks/pacman.h new file mode 100644 index 00000000..652ee314 --- /dev/null +++ b/hacks/pacman.h @@ -0,0 +1,231 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/*- + * Copyright (c) 2002 by Edwin de Jong . + * + * Permission to use, copy, modify, and distribute this software and its + * documentation for any purpose and without fee is hereby granted, + * provided that the above copyright notice appear in all copies and that + * both that copyright notice and this permission notice appear in + * supporting documentation. + * + * This file is provided AS IS with no warranties of any kind. The author + * shall have no liability with respect to the infringement of copyrights, + * trade secrets or any patents by this file or any part thereof. In no + * event will the author be liable for any lost revenue or profits or + * other special, indirect and consequential damages. + * + * Revision History: + * 3-May-2002: Added AI to pacman and ghosts, slowed down ghosts. + * 26-Nov-2001: Random level generator added + * 01-Nov-2000: Allocation checks + * 04-Jun-1997: Compatible with xscreensaver + * + */ + +#ifndef __PACMAN_H__ +#define __PACMAN_H__ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include "xlockmoreI.h" + +#if defined(HAVE_GDK_PIXBUF) || defined(HAVE_XPM) || defined(HAVE_COCOA) +# define USE_PIXMAP +#include "xpm-pixmap.h" +# else +# if defined(USE_PIXMAP) +# undef USE_PIXMAP +# endif +#endif + +#define LEVHEIGHT 32U +#define LEVWIDTH 40U + +#define TILEWIDTH 5U +#define TILEHEIGHT 5U + +#define GETNB(n) ((1 << (n)) - 1) +#define TESTNB(v, n) (((1 << (n)) & v) != 0x00) +#define SNB(v, n) ((v) |= (1 << (n))) +#define UNSNB(v, n) ((v) &= ~(1 << (n))) +#define GHOSTS 4U +#if defined(USE_PIXMAP) +#define MAXMOUTH 3 +#else +#define MAXMOUTH 11 +#endif +#define MAXGPOS 2 +#define MAXGDIR 4 +#define MAXGWAG 2 +#define MAXGFLASH 2 +#define MINGRIDSIZE 4 +#define MINSIZE 3 +#define NOWHERE 16383 +#define START ((LRAND() & 1) ? 1 : 3) +#define MINDOTPERC 10 + +#define YELLOW (MI_NPIXELS(mi) / 6) +#define GREEN (23 * MI_NPIXELS(mi) / 64) +#define BLUE (45 * MI_NPIXELS(mi) / 64) +#define WHITE (MI_NPIXELS(mi)) + +#define LINEWIDTH 4 +#define HLINEWIDTH 1 +#define JAILHEIGHT 7 +#define JAILWIDTH 8 + +#define GETFACTOR(x, y) ((x) > (y) ? 1 : ((x) < (y) ? -1 : 0)) +#define SIGN(x) GETFACTOR((x), 0) +#define TRACEVECS 40 +#define PAC_DEATH_FRAMES 8 + +#define GHOST_TRACE ( LEVWIDTH * LEVHEIGHT ) + +#define DIRVECS 4 +#define NUM_BONUS_DOTS 4 + +typedef struct +{ + int vx, vy; +} tracevec_struct; + +typedef enum + { inbox = 0, goingout, randdir, chasing, hiding, goingin } GhostState; +typedef enum + { ps_eating = 0, ps_chasing, ps_hiding, ps_random, ps_dieing } PacmanState; +typedef enum +{ GHOST_DANGER, GHOST_EATEN } GameState; + +typedef struct +{ + volatile unsigned int col, row; + unsigned int lastbox, nextcol, nextrow; + int dead; + int cfactor, rfactor; + int cf, rf; + int oldcf, oldrf; + volatile int timeleft; + GhostState aistate; + int speed; + XPoint delta; + XPoint err; + int flash_scared; + int trace_idx; + tracevec_struct trace[GHOST_TRACE]; + int home_idx; + volatile int home_count; + tracevec_struct way_home[GHOST_TRACE]; + volatile int wait_pos; /* a cycle before calculating the position */ +#if 0 /* Used for debugging */ + int ndirs; + int oldndirs; +#endif + +#if 0 /* Used for debugging */ + char last_stat[1024]; +#endif + +} ghoststruct; + +typedef struct +{ + unsigned int col, row; + unsigned int lastbox, nextcol, nextrow; + int mouthstage, mouthdirection; + int cfactor, rfactor; + int cf, rf; + int oldcf, oldrf; + int oldlx, oldly; + int justate; + PacmanState aistate; + tracevec_struct trace[TRACEVECS]; + int cur_trace; + int state_change; + int roundscore; + int speed; + int lastturn; + XPoint delta; + XPoint err; + int deaths; + int init_row; +} pacmanstruct; + + +typedef struct +{ + unsigned int x, y; + int eaten; +} bonus_dot; + + +/* This are tiles which can be placed to create a level. */ +struct tiles { + char block[TILEWIDTH * TILEHEIGHT + 1]; + unsigned dirvec[4]; + unsigned ndirs; + unsigned simular_to; +}; + +typedef struct +{ + unsigned short width, height; + unsigned short nrows, ncols; + short xs, ys, xb, yb; + short incx, incy; + GC stippledGC; + int graphics_format; + pacmanstruct pacman; + ghoststruct *ghosts; + unsigned int nghosts; + Pixmap pacmanPixmap[4][MAXMOUTH]; + Pixmap pacmanMask[4][MAXMOUTH]; + Pixmap pacman_ds[PAC_DEATH_FRAMES]; /* pacman death sequence */ + Pixmap pacman_ds_mask[PAC_DEATH_FRAMES]; + Pixmap ghostPixmap[4][MAXGDIR][MAXGWAG]; + Pixmap ghostMask; + Pixmap s_ghostPixmap[MAXGFLASH][MAXGWAG]; /* Scared ghost Pixmaps */ + Pixmap ghostEyes[MAXGDIR]; + char level[LEVHEIGHT * LEVWIDTH]; + unsigned int wallwidth; + unsigned int dotsleft; + int spritexs, spriteys, spritedx, spritedy; + + GameState gamestate; + unsigned int timeleft; + + char last_pac_stat[1024]; + + /* draw_pacman_sprite */ + int pm_mouth; + int pm_mouth_delay; + int pm_open_mouth; + int pm_death_frame; + int pm_death_delay; + + /* draw_ghost_sprite */ + int gh_wag; + int gh_wag_count; + + /* flash_bonus_dots */ + int bd_flash_count; + int bd_on; + + /* pacman_tick */ + int ghost_scared_timer; + int flash_timer; + PacmanState old_pac_state; + + /* pacman_level.c */ + bonus_dot bonus_dots[NUM_BONUS_DOTS]; + struct tiles *tiles; + +} pacmangamestruct; + +extern pacmangamestruct *pacman_games; +extern Bool pacman_trackmouse; + +typedef char lev_t[LEVHEIGHT][LEVWIDTH + 1]; + +#endif /* __PACMAN_H__ */ diff --git a/hacks/pacman.man b/hacks/pacman.man new file mode 100644 index 00000000..ba19a560 --- /dev/null +++ b/hacks/pacman.man @@ -0,0 +1,67 @@ +.TH XScreenSaver 1 "12-Feb-2004" "X Version 11" +.SH NAME +pacman - simulates a game of Pac-Man on a randomly-created level. +.SH SYNOPSIS +.B pacman +[\-display \fIhost:display.screen\fP] +[\-window] +[\-root] +[\-mono] +[\-install] +[\-visual \fIvisual\fP] +[\-ncolors \fIinteger\fP] +[\-delay \fImicroseconds\fP] +[\-size \fIpixels\fP] +[\-fps] +.SH DESCRIPTION +Simulates a game of Pac-Man on a randomly-created level. +.SH OPTIONS +.I pacman +accepts the following options: +.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 \-mono +If on a color display, pretend we're on a monochrome display. +.TP 8 +.B \-install +Install a private colormap for the window. +.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 \-ncolors \fIinteger\fP +How many colors should be used (if possible). Default 6. +.TP 8 +.B \-size \fIinteger\fP +How big to make Pac-Man and the ghosts. 0 means "default." +.TP 8 +.B \-fps +Display the current frame rate and CPU load. +.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 2000 Edwin de Jong. + +Permission to use, copy, modify, and distribute this software and its +documentation for any purpose and without fee is hereby granted, +provided that the above copyright notice appear in all copies and that +both that copyright notice and this permission notice appear in +supporting documentation. +.SH AUTHOR +Edwin de Jong . diff --git a/hacks/pacman_ai.c b/hacks/pacman_ai.c new file mode 100644 index 00000000..b85bd96e --- /dev/null +++ b/hacks/pacman_ai.c @@ -0,0 +1,876 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/*- + * Copyright (c) 2002 by Edwin de Jong . + * + * Permission to use, copy, modify, and distribute this software and its + * documentation for any purpose and without fee is hereby granted, + * provided that the above copyright notice appear in all copies and that + * both that copyright notice and this permission notice appear in + * supporting documentation. + * + * This file is provided AS IS with no warranties of any kind. The author + * shall have no liability with respect to the infringement of copyrights, + * trade secrets or any patents by this file or any part thereof. In no + * event will the author be liable for any lost revenue or profits or + * other special, indirect and consequential damages. + */ + +/* this file handles the AI of the ghosts and the pacman. */ + +#include +#include +#include "pacman.h" +#include "pacman_ai.h" +#include "pacman_level.h" + +#define MI_DISPLAY(MI) ((MI)->dpy) +#define MI_WINDOW(MI) ((MI)->window) +#define MI_WIDTH(MI) ((MI)->xgwa.width) +#define MI_HEIGHT(MI) ((MI)->xgwa.height) + +#define DIRVECS 4 +static const struct +{ + int dx, dy; +} dirvecs[DIRVECS] = { { +-1, 0}, { +0, 1}, { +1, 0}, { +0, -1}}; + +/* positions that match the dirvecs */ +typedef enum {pos_none = -1, pos_left = 0, pos_up = 1, pos_right = 2, pos_down = 3} pos; + + +/* fills array of DIRVECS size with possible directions, returns number of + directions. 'posdirs' points to a possibly undefined array of four + integers. The vector will contain booleans wether the direction is + a possible direction or not. Reverse directions are deleted. */ +static int +ghost_get_posdirs (pacmangamestruct * pp, int *posdirs, ghoststruct * g) +{ + unsigned int i, nrdirs = 0; + unsigned int can_go_in = 0; + + /* bit of black magic here */ + for (i = 0; i < DIRVECS; i++) { + /* remove opposite */ + if (g->lastbox != NOWHERE && i == (g->lastbox + 2) % DIRVECS + && (g->aistate != goingout )) { + posdirs[i] = 0; + continue; + } + if (g->aistate == goingout && i == 1) { + posdirs[i] = 0; + continue; + } + /* check if possible direction */ + can_go_in = (g->aistate == goingout || g->aistate == goingin); + if ((posdirs[i] = + pacman_check_pos (pp, g->row + dirvecs[i].dy, + g->col + dirvecs[i].dx, + can_go_in)) == True) { + nrdirs++; + } + } + + return nrdirs; +} + +/* Directs ghost to a random direction, exluding opposite (except in the + impossible situation that there is only one valid direction). */ +static void +ghost_random (pacmangamestruct * pp, ghoststruct * g) +{ + int posdirs[DIRVECS], nrdirs = 0, i, dir = 0; + + nrdirs = ghost_get_posdirs (pp, posdirs, g); +#if 0 + g->ndirs = nrdirs; +#endif + for (i = 0; i < DIRVECS; i++) + if (posdirs[i] == True) + dir = i; + + if (nrdirs == 0) + dir = (g->lastbox + 2) % DIRVECS; + else if (nrdirs > 1) + for (i = 0; i < DIRVECS; i++) { + if (posdirs[i] == True && NRAND (nrdirs) == 0) { + dir = i; + break; + } + } + + g->nextrow = g->row + dirvecs[dir].dy; + g->nextcol = g->col + dirvecs[dir].dx; + g->lastbox = dir; +} + +/* Determines best direction to chase the pacman and goes that direction. */ +static void +ghost_chasing (pacmangamestruct * pp, ghoststruct * g) +{ + int posdirs[DIRVECS], nrdirs = 0, i, dir = 0, highest = -100000, + thisvecx, thisvecy, thisvec; + + nrdirs = ghost_get_posdirs (pp, posdirs, g); +#if 0 + g->ndirs = nrdirs; +#endif + for (i = 0; i < DIRVECS; i++) + if (posdirs[i] == True) + dir = i; + + if (nrdirs == 0) + dir = (g->lastbox + 2) % DIRVECS; + else if (nrdirs > 1) + for (i = 0; i < DIRVECS; i++) { + if (posdirs[i] == False) + continue; + thisvecx = (pp->pacman.col - g->col) * dirvecs[i].dx; + thisvecy = (pp->pacman.row - g->row) * dirvecs[i].dy; + thisvec = thisvecx + thisvecy; + if (thisvec >= highest) { + dir = i; + highest = thisvec; + } + } + + g->nextrow = g->row + dirvecs[dir].dy; + g->nextcol = g->col + dirvecs[dir].dx; + g->lastbox = dir; +} + +/* Determines the best direction to go away from the pacman, and goes that + direction. */ +static void +ghost_hiding (pacmangamestruct * pp, ghoststruct * g) +{ + int posdirs[DIRVECS], nrdirs = 0, i, dir = 0, highest = -100000, + thisvecx, thisvecy, thisvec; + + nrdirs = ghost_get_posdirs (pp, posdirs, g); +#if 0 + g->ndirs = nrdirs; +#endif + for (i = 0; i < DIRVECS; i++) + if (posdirs[i] == True) + dir = i; + + if (nrdirs == 0) + dir = (g->lastbox + 2) % DIRVECS; + else if (nrdirs > 1) + for (i = 0; i < DIRVECS; i++) { + if (posdirs[i] == False) + continue; + thisvecx = (g->col - pp->pacman.col) * dirvecs[i].dx; + thisvecy = (g->row - pp->pacman.row) * dirvecs[i].dy; + thisvec = thisvecx + thisvecy; + if (thisvec >= highest) + dir = i; + } + + g->nextrow = g->row + dirvecs[dir].dy; + g->nextcol = g->col + dirvecs[dir].dx; + g->lastbox = dir; +} + +#if 1 +static void +clear_trace(ghoststruct *g) +{ + int i = 0; + g->trace_idx = 0; + while (i < GHOST_TRACE){ + g->trace[i].vx = -1; + g->trace[i++].vy = -1; + } +} + + +static void +save_position (ghoststruct *g, int x, int y) +{ + int i = g->trace_idx; + assert ( 0 <= i && i < GHOST_TRACE ); + g->trace[i].vx = x; + g->trace[i].vy = y; + g->trace_idx++; +} + +static int +already_tried (ghoststruct *g, int x, int y) +{ + int i = 0; + if (! ( 0 <= g->trace_idx && g->trace_idx < GHOST_TRACE ) ){ + fprintf(stderr, "FOUND TRACE ERROR. DUMPING TRACE.\n"); + fprintf(stderr, "%d\n", g->trace_idx ); + for ( i = 0; i < GHOST_TRACE; i++ ){ + fprintf(stderr, "( %d, %d )\n", g->trace[i].vx, g->trace[i].vy ); + } + assert ( False ); + } + while (i < g->trace_idx){ + if ( x == g->trace[i].vx && y == g->trace[i].vy ){ + /* fprintf ( stderr, "Match FOUND (%d, %d)\n", x, y); */ + return 1; + } + i++; + } + return 0; +} +#endif + +static void +store_dir ( ghoststruct *g, pos ps ){ + int i = g->home_count; + assert ( 0 <= i && i < GHOST_TRACE ); + g->way_home[i].vx = dirvecs[ps].dx; + g->way_home[i].vy = dirvecs[ps].dy; + g->home_count++; +} + +static void +clear_dir ( ghoststruct *g ){ + int i = 0; + g->home_count = 0; + g->home_idx = 0; + while (i < GHOST_TRACE){ + g->way_home[i].vx = -1; + g->way_home[i++].vy = -1; + } +} + +static int +found_jail ( int col, int row ){ + int cx, cy; + pacman_get_jail_opening ( &cx, &cy ); + cy += 1; + if (row == cy && col == cx ) + return 1; + else + return 0; +} + +static int +move_ghost ( pacmangamestruct * pp, + int row, int col, + pos ps, + int *new_row, int *new_col){ + int idx = (int)ps; + int tr = row + dirvecs[idx].dx; + int tc = col + dirvecs[idx].dy; + if ( pacman_check_pos ( pp, tr, tc, True )){ + *new_row = tr; + *new_col = tc; + return True; + } + else { + return False; + } +} + +static int +recur_back_track ( pacmangamestruct * pp, ghoststruct *g, int row, int col ){ + int new_row, new_col; + + if ( already_tried ( g, col, row ) ) + return False; + + if ( found_jail ( col, row ) ) + return True; + + save_position ( g, col, row ); + + if ( move_ghost ( pp, row, col, pos_left, &new_row, &new_col )) + if ( recur_back_track ( pp, g, new_row, new_col )){ + store_dir ( g, pos_left ); + return True; + } + + if ( move_ghost ( pp, row, col, pos_up, &new_row, &new_col )) + if ( recur_back_track ( pp, g, new_row, new_col )){ + store_dir ( g, pos_up ); + return True; + } + + if ( move_ghost ( pp, row, col, pos_down, &new_row, &new_col )) + if ( recur_back_track ( pp, g, new_row, new_col )){ + store_dir ( g, pos_down ); + return True; + } + + if ( move_ghost ( pp, row, col, pos_right, &new_row, &new_col )) + if ( recur_back_track ( pp, g, new_row, new_col )){ + store_dir ( g, pos_right ); + return True; + } + + return False; +} + +static void +find_home ( pacmangamestruct *pp, ghoststruct *g ){ + int i; + int r,c; + int cx, cy; + ghoststruct *tmp_ghost; + tmp_ghost = (ghoststruct*)malloc(sizeof ( ghoststruct )); + if ( tmp_ghost == NULL ){ + fprintf(stderr, "find_home : Could not allocate memory."); + exit ( 1 ); + } + tmp_ghost = memmove(tmp_ghost, g, sizeof ( ghoststruct )); + if ( tmp_ghost == NULL ){ + fprintf(stderr, "find_home : Could not copy memory."); + exit ( 1 ); + } + clear_trace ( tmp_ghost ); + clear_dir ( tmp_ghost ); + r = tmp_ghost->row; + c = tmp_ghost->col; + if ( ! recur_back_track ( pp, tmp_ghost, r, c ) ){ + fprintf(stderr, "Could not find way home.#@$?\n"); + pacman_get_jail_opening ( &cx, &cy); + fprintf(stderr, "Jail was at (%d%d)\n", cx,cy); + } + for ( i = 0; i < GHOST_TRACE; i++ ){ + g->way_home[i].vx = tmp_ghost->way_home[i].vx; + g->way_home[i].vy = tmp_ghost->way_home[i].vy; + } + g->home_count = tmp_ghost->home_count; + g->home_idx = tmp_ghost->home_count; + free(tmp_ghost); +} + +/* Make the ghost go back to the inbox */ +static void +ghost_goingin (pacmangamestruct * pp, ghoststruct * g) +{ + g->home_idx--; + if (g->home_idx < 0){ g->aistate = goingout; return;} + /* row == vx ? wtf... Don't Ask */ + g->nextrow = g->row + g->way_home[g->home_idx].vx; + g->nextcol = g->col + g->way_home[g->home_idx].vy; +} + + +/* Determines a vector from the pacman position, towards all dots. The vector + is inversely proportional to the square of the distance of each dot. + (so, close dots attract more than far away dots). */ +static void +pac_dot_vec (pacmangamestruct * pp, pacmanstruct * p, long *vx, long *vy) +{ + int x, y, bx = 0, by = 0, ex = LEVWIDTH, ey = LEVHEIGHT; + long dx, dy, dist, top = 0; + +#if 0 + int rnr = NRAND (50); + /* determine begin and end vectors */ + + switch (rnr) { + case 0: + ex = LEVHEIGHT / 2; + break; + case 1: + bx = LEVHEIGHT / 2; + break; + case 2: + ey = LEVHEIGHT / 2; + break; + case 3: + by = LEVHEIGHT / 2; + break; + } +#endif + *vx = *vy = 0; + + for (y = by; y < ey; y++) + for (x = bx; x < ex; x++) + if (pacman_check_dot (pp, x, y) == 1) { + dx = (long) x - (long) (p->col); + dy = (long) y - (long) (p->row); + dist = dx * dx + dy * dy; + if (dist > top) + top = dist; + *vx += (dx * ((long) LEVWIDTH * (long) LEVHEIGHT)) + / dist; + *vy += (dy * ((long) LEVWIDTH * (long) LEVHEIGHT)) + / dist; + } +} + +/* Determine a vector towards the closest ghost (in one loop, so we spare a + couple of cycles which we can spoil somewhere else just as fast). */ +static int +pac_ghost_prox_and_vector (pacmangamestruct * pp, pacmanstruct * p, + int *vx, int *vy) +{ + int dx, dy, dist, closest = 100000; + unsigned int g; + + if (vx != NULL) + *vx = *vy = 0; + + for (g = 0; g < pp->nghosts; g++) { + if (pp->ghosts[g].dead == True || + pp->ghosts[g].aistate == inbox || + pp->ghosts[g].aistate == goingout) + continue; + dx = pp->ghosts[g].col + /*dirvecs[pp->ghosts[g].lastbox].dx */ - + p->col; + dy = pp->ghosts[g].row + /*dirvecs[pp->ghosts[g].lastbox].dy */ - + p->row; + dist = dx * dx + dy * dy; + if (dist < closest) { + closest = dist; + if (vx != NULL) { + *vx = dx; + *vy = dy; + } + } + } + return closest; +} + +/* fills array of DIRVECS size with possible directions, returns number of + directions. posdirs should point to an array of 4 integers. */ +static int +pac_get_posdirs (pacmangamestruct * pp, pacmanstruct * p, int *posdirs) +{ + int nrdirs = 0; + unsigned int i; + + for (i = 0; i < DIRVECS; i++) { + /* if we just ate, or we are in a statechange, it is allowed + * to go the opposite direction */ + if (p->justate == 0 && + p->state_change == 0 && + p->lastbox != NOWHERE && i == (p->lastbox + 2) % DIRVECS) { + posdirs[i] = 0; + } + else if ((posdirs[i] = + pacman_check_pos (pp, p->row + dirvecs[i].dy, + p->col + dirvecs[i].dx, 0)) == 1) + nrdirs++; + } + p->state_change = 0; + + return nrdirs; +} + +/* Clears the trace of vectors. */ +void +pacman_clear_trace (pacmanstruct * p) +{ + int i; + + for (i = 0; i < TRACEVECS; i++) { + p->trace[i].vx = NOWHERE; + p->trace[i].vy = NOWHERE; + } + p->cur_trace = 0; +} + +/* Adds a new vector to the trace. */ +static void +pac_save_trace (pacmanstruct * p, const int vx, const int vy) +{ + if (!(vx == NOWHERE && vy == NOWHERE)) { + p->trace[p->cur_trace].vx = vx; + p->trace[p->cur_trace].vy = vy; + p->cur_trace = (p->cur_trace + 1) % TRACEVECS; + } +} + +/* Check if a vector can be found in the trace. */ +static int +pac_check_trace (const pacmanstruct * p, const int vx, const int vy) +{ + int i, curel; + + for (i = 1; i < TRACEVECS; i++) { + curel = (p->cur_trace - i + TRACEVECS) % TRACEVECS; + if (p->trace[curel].vx == NOWHERE && p->trace[curel].vy == NOWHERE) + continue; + if (p->trace[curel].vx == vx && p->trace[curel].vy == vy) + return 1; + } + + + return 0; +} + +/* AI mode "Eating" for pacman. Tries to eat as many dots as possible, goes + to "hiding" if too close to a ghost. If in state "hiding" the vectors + of the ghosts are also taken into account (thus not running towards them + is the general idea). */ +static void +pac_eating (pacmangamestruct * pp, pacmanstruct * p) +{ + int posdirs[DIRVECS], nrdirs, i, highest = -(1 << 16), + score, dir = 0, dotfound = 0, prox, worst = 0; + int vx, vy; + + if ((prox = pac_ghost_prox_and_vector (pp, p, &vx, &vy)) < + 4 * 4 && p->aistate == ps_eating) { + p->aistate = ps_hiding; + p->state_change = 1; + pacman_clear_trace (p); + } + + if (prox > 6 * 6 && p->aistate == ps_hiding) { + p->aistate = ps_eating; + if (p->justate == 0) + p->state_change = 1; + pacman_clear_trace (p); + } + + if (prox < 3 * 3) + p->state_change = 1; + + nrdirs = pac_get_posdirs (pp, p, posdirs); + + /* remove directions which lead to ghosts */ + if (p->aistate == ps_hiding) { + for (i = 0; i < DIRVECS; i++) { + if (posdirs[i] == 0) + continue; + score = vx * dirvecs[i].dx + vy * dirvecs[i].dy; + if (score > highest) { + worst = i; + highest = score; + } + dir = i; + } + nrdirs--; + posdirs[worst] = 0; + highest = -(1 << 16); + } + + /* get last possible direction if all else fails */ + for (i = 0; i < DIRVECS; i++) + if (posdirs[i] != 0) + dir = i; + + { + long lvx = vx; + long lvy = vy; + pac_dot_vec (pp, p, &lvx, &lvy); + vx = lvx; + vy = lvy; + } + + if (vx != NOWHERE && vy != NOWHERE && pac_check_trace (p, vx, vy) > 0) { + p->roundscore++; + if (p->roundscore >= 12) { + p->roundscore = 0; + p->aistate = ps_random; + pacman_clear_trace (p); + } + } + else + p->roundscore = 0; + + if (p->justate == 0) + pac_save_trace (p, vx, vy); + + for (i = 0; i < DIRVECS; i++) { + if (posdirs[i] == 0) + continue; + score = dirvecs[i].dx * vx + dirvecs[i].dy * vy; + if (pacman_check_dot (pp, p->col + dirvecs[i].dx, + p->row + dirvecs[i].dy) == 1) { + if (dotfound == 0) { + highest = score; + dir = i; + dotfound = 1; + } + else if (score > highest) { + highest = score; + dir = i; + } + } + else if (score > highest && dotfound == 0) { + dir = i; + highest = score; + } + } + + p->nextrow = p->row + dirvecs[dir].dy; + p->nextcol = p->col + dirvecs[dir].dx; + p->lastbox = dir; +} + +#if 1 +/* Tries to catch the ghosts. */ +static void +pac_chasing (pacmangamestruct * pp, pacmanstruct * p) +{ + int posdirs[DIRVECS], nrdirs, i, highest = -(1 << 16), + score, dir = 0, worst = 0; + int vx = 0, vy = 0; + + nrdirs = pac_get_posdirs (pp, p, posdirs); + + /* keep directions which lead to ghosts */ + for (i = 0; i < DIRVECS; i++) { + if (posdirs[i] == 0) + continue; + score = vx * dirvecs[i].dx + vy * dirvecs[i].dy; + if (score < highest) { + worst = i; + highest = score; + } + dir = i; + } + nrdirs--; + posdirs[worst] = 0; + + + /* get last possible direction if all else fails */ + for (i = 0; i < DIRVECS; i++) + if (posdirs[i] != 0) + dir = i; + + { + long lvx = vx; + long lvy = vy; + pac_dot_vec (pp, p, &lvx, &lvy); + vx = lvx; + vy = lvy; + } + + if (vx != NOWHERE && vy != NOWHERE && pac_check_trace (p, vx, vy) > 0) { + p->roundscore++; + if (p->roundscore >= 12) { + p->roundscore = 0; + p->aistate = ps_random; + pacman_clear_trace (p); + } + } + else + p->roundscore = 0; + + + p->nextrow = p->row + dirvecs[dir].dy; + p->nextcol = p->col + dirvecs[dir].dx; + p->lastbox = dir; +} +#endif + +/* Goes completely random, but not in the opposite direction. Used when a + loop is detected. */ +static void +pac_random (pacmangamestruct * pp, pacmanstruct * p) +{ + int posdirs[DIRVECS], nrdirs, i, dir = -1, lastdir = 0; + + if (pac_ghost_prox_and_vector (pp, p, NULL, NULL) < 5 * 5) { + p->aistate = ps_hiding; + p->state_change = 1; + } + if (NRAND (20) == 0) { + p->aistate = ps_eating; + p->state_change = 1; + pacman_clear_trace (p); + } + + nrdirs = pac_get_posdirs (pp, p, posdirs); + + for (i = 0; i < DIRVECS; i++) { + if (posdirs[i] == 0) + continue; + lastdir = i; + if (pacman_check_dot (pp, p->col + dirvecs[i].dx, + p->row + dirvecs[i].dy) == 1) { + dir = i; + p->aistate = ps_eating; + p->state_change = 1; + pacman_clear_trace (p); + break; + } + else if (NRAND (nrdirs) == 0) + dir = i; + } + + if (dir == -1) + dir = lastdir; + + p->nextrow = p->row + dirvecs[dir].dy; + p->nextcol = p->col + dirvecs[dir].dx; + p->lastbox = dir; +} + +static int +pac_get_vector_screen (pacmangamestruct * pp, pacmanstruct * p, + const int x, const int y, int *vx, int *vy) +{ + int lx, ly; + + lx = (x - pp->xb) / pp->xs; + ly = (y - pp->yb) / pp->ys; + + if (lx < 0) + lx = 0; + else if ((unsigned int) lx > LEVWIDTH) + lx = LEVWIDTH - 1; + + if (ly < 0) + ly = 0; + else if ((unsigned int) ly > LEVHEIGHT) + ly = LEVHEIGHT - 1; + + *vx = lx - p->col; + *vy = ly - p->row; + + if (lx == p->oldlx && ly == p->oldly) + return 0; + p->oldlx = lx; + p->oldly = ly; + return 1; +} + +static int +pac_trackmouse (ModeInfo * mi, pacmangamestruct * pp, pacmanstruct * p) +{ + int dx, dy, cx, cy, vx, vy; + unsigned int m; + int posdirs[DIRVECS], i, dir = -1, highest = -(2 << 16), score; + Window r, c; + + (void) XQueryPointer (MI_DISPLAY (mi), MI_WINDOW (mi), + &r, &c, &dx, &dy, &cx, &cy, &m); + + if (cx <= 0 || cy <= 0 || + cx >= MI_WIDTH (mi) - 1 || cy >= MI_HEIGHT (mi) - 1) + return 0; + /* get vector */ + p->state_change = pac_get_vector_screen (pp, p, cx, cy, &vx, &vy); + + (void) pac_get_posdirs (pp, p, posdirs); + + for (i = 0; i < DIRVECS; i++) { + if (posdirs[i] == 0) + continue; + score = dirvecs[i].dx * vx + dirvecs[i].dy * vy; + if (score > highest) { + highest = score; + dir = i; + } + } + + p->nextrow = p->row + dirvecs[dir].dy; + p->nextcol = p->col + dirvecs[dir].dx; + p->lastbox = dir; + return 1; +} + +/* Calls correct state function, and changes between states. */ +void +pacman_ghost_update (pacmangamestruct * pp, ghoststruct * g) +{ + + if (!(g->nextrow == NOWHERE && g->nextcol == NOWHERE)) { + g->row = g->nextrow; + g->col = g->nextcol; + } + + if ((g->aistate == randdir || g->aistate == chasing) && NRAND (10) == 0) { + switch (NRAND (3)) { + case 0: + g->aistate = randdir; + break; + case 1: + g->aistate = chasing; + break; + case 2: + g->aistate = chasing; + break; + } + + } + else if (g->aistate == inbox) { + if (g->timeleft < 0) + g->aistate = goingout; + else + g->timeleft--; + + } + else if (g->aistate == goingout) { + if (g->col < LEVWIDTH / 2 - JAILWIDTH / 2 || + g->col > LEVWIDTH / 2 + JAILWIDTH / 2 || + g->row < LEVHEIGHT / 2 - JAILHEIGHT / 2 || + g->row > LEVHEIGHT / 2 + JAILHEIGHT / 2) + g->aistate = randdir; + } + + switch (g->aistate) { + case inbox: + case goingout: + case randdir: + ghost_random (pp, g); + break; + case chasing: + ghost_chasing (pp, g); + break; + case hiding: + ghost_hiding (pp, g); + break; + case goingin: + if ( g->wait_pos ){ + find_home(pp, g); + g->wait_pos = False; + } + ghost_goingin (pp, g); + break; + } + + g->cfactor = GETFACTOR (g->nextcol, g->col); + g->rfactor = GETFACTOR (g->nextrow, g->row); +} + +/* Calls correct pacman state function. */ +void +pacman_update (ModeInfo * mi, pacmangamestruct * pp, pacmanstruct * p) +{ + if (!(p->nextrow == NOWHERE && p->nextcol == NOWHERE)) { + p->row = p->nextrow; + p->col = p->nextcol; + } + + if (pp->level[p->row * LEVWIDTH + p->col] == '.' || + pp->level[p->row * LEVWIDTH + p->col] == 'o') { + pp->level[p->row * LEVWIDTH + p->col] = ' '; + if (!pacman_trackmouse) + p->justate = 1; + pp->dotsleft--; + } + else if (!pacman_trackmouse) { + p->justate = 0; + } + + if (!(pacman_trackmouse && pac_trackmouse (mi, pp, p))) { + /* update pacman */ + switch (p->aistate) { + case ps_eating: + pac_eating (pp, p); + break; + case ps_hiding: + pac_eating (pp, p); + break; + case ps_random: + pac_random (pp, p); + break; + case ps_chasing: + pac_chasing (pp, p); + break; + case ps_dieing: + break; /* Don't move */ + } + } + + p->cfactor = GETFACTOR (p->nextcol, p->col); + p->rfactor = GETFACTOR (p->nextrow, p->row); +} diff --git a/hacks/pacman_ai.h b/hacks/pacman_ai.h new file mode 100644 index 00000000..2488600a --- /dev/null +++ b/hacks/pacman_ai.h @@ -0,0 +1,32 @@ +/*- + * Copyright (c) 2002 by Edwin de Jong . + * + * Permission to use, copy, modify, and distribute this software and its + * documentation for any purpose and without fee is hereby granted, + * provided that the above copyright notice appear in all copies and that + * both that copyright notice and this permission notice appear in + * supporting documentation. + * + * This file is provided AS IS with no warranties of any kind. The author + * shall have no liability with respect to the infringement of copyrights, + * trade secrets or any patents by this file or any part thereof. In no + * event will the author be liable for any lost revenue or profits or + * other special, indirect and consequential damages. + * + * Revision History: + * 3-May-2002: Added AI to pacman and ghosts, slowed down ghosts. + * 26-Nov-2001: Random level generator added + * 01-Nov-2000: Allocation checks + * 04-Jun-1997: Compatible with xscreensaver + * + */ + +#ifndef __PACMAN_AI_H__ +#define __PACMAN_AI_H__ + +extern void pacman_ghost_update (pacmangamestruct * pp, ghoststruct * g); +extern void pacman_clear_trace (pacmanstruct * p); +extern void pacman_update (ModeInfo * mi, pacmangamestruct * pp, + pacmanstruct * p); + +#endif /* __PACMAN_AI_H__ */ diff --git a/hacks/pacman_level.c b/hacks/pacman_level.c new file mode 100644 index 00000000..d617942c --- /dev/null +++ b/hacks/pacman_level.c @@ -0,0 +1,772 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/*- + * Copyright (c) 2002 by Edwin de Jong . + * + * Permission to use, copy, modify, and distribute this software and its + * documentation for any purpose and without fee is hereby granted, + * provided that the above copyright notice appear in all copies and that + * both that copyright notice and this permission notice appear in + * supporting documentation. + * + * This file is provided AS IS with no warranties of any kind. The author + * shall have no liability with respect to the infringement of copyrights, + * trade secrets or any patents by this file or any part thereof. In no + * event will the author be liable for any lost revenue or profits or + * other special, indirect and consequential damages. + */ + +#include +#include "pacman.h" +#include "pacman_level.h" + + +#define NONE 0x0000 +#define LT 0x1000 +#define RT 0x0001 +#define RB 0x0010 +#define LB 0x0100 +#define ALL 0x1111 + +#define BLOCK_EMPTY ' ' +#define BLOCK_DOT_1 '`' +#define BLOCK_DOT_2 '.' +#define BLOCK_WALL '#' +#define BLOCK_GHOST_ONLY '=' +#define BLOCK_WALL_TL '\'' +#define BLOCK_WALL_TR '`' +#define BLOCK_WALL_BR ',' +#define BLOCK_WALL_BL '_' +#define BLOCK_WALL_HO '-' +#define BLOCK_WALL_VE '|' +#define BLOCK_DOT_BONUS 'o' + +/* This is more or less the standard pacman level (without the left-right + tunnel. */ +static const lev_t stdlevel = { + "########################################", + "########################################", + "#######````````````##````````````#######", + "#######`####`#####`##`#####`####`#######", + "#######`####`#####`##`#####`####`#######", + "#######`####`#####`##`#####`####`#######", + "#######``````````````````````````#######", + "#######`####`##`########`##`####`#######", + "#######`####`##`########`##`####`#######", + "#######``````##````##````##``````#######", + "############`#####`##`#####`############", + "############`#####`##`#####`############", + "############`##``````````##`############", + "############`##`###==###`##`############", + "############`##`########`##`############", + "############````########````############", + "############`##`########`##`############", + "############`##`########`##`############", + "############`##``````````##`############", + "############`##`########`##`############", + "############`##`########`##`############", + "#######````````````##````````````#######", + "#######`####`#####`##`#####`####`#######", + "#######`####`#####`##`#####`####`#######", + "#######```##````````````````##```#######", + "#########`##`##`########`##`##`#########", + "#########`##`##`########`##`##`#########", + "#######``````##````##````##``````#######", + "#######`##########`##`##########`#######", + "#######`##########`##`##########`#######", + "#######``````````````````````````#######", + "########################################" +}; + +#define TILES_COUNT 11U + +#define GO_UP 0x0001U +#define GO_LEFT 0x0002U +#define GO_RIGHT 0x0004U +#define GO_DOWN 0x0008U + +static const struct tiles def_tiles[TILES_COUNT] = { +/* + * ' ' == dont care == BLOCK_EMPTY + * '#' == set wall, and not clear == BLOCK_WALL + * '`' == clear == BLOCK_DOT_1 + * middle position is always set as cleardef + */ + { + " # " " # " " ``` " " # " " # ", { + GO_LEFT, GO_RIGHT, 0, 0}, 2, + (unsigned) (1 << 0 | 1 << 6 | 1 << 8 | 1 << 10)}, { + " " " ` " "##`##" " ` " " ", { + GO_UP, GO_DOWN, 0, 0}, 2, + (unsigned) (1 << 1 | 1 << 7 | 1 << 9 | 1 << 10)}, { + " ##" "##`##" "##`` " "#### " "#### ", { + GO_UP, GO_RIGHT, 0, 0}, 2, + (unsigned) (1 << 2 | 1 << 6 | 1 << 7 | 1 << 10)}, { + "#### " "#### " "##`` " "##`##" " ##", { + GO_RIGHT, GO_DOWN, 0, 0}, 2, + (unsigned) (1 << 3 | 1 << 7 | 1 << 8 | 1 << 10)}, { + " ###" " ###" " ``##" "##` " "## ", { + GO_LEFT, GO_DOWN, 0, 0}, 2, + (unsigned) (1 << 4 | 1 << 8 | 1 << 9 | 1 << 10)}, { + "## " "##`##" " ``##" " ####" " ####", { + GO_LEFT, GO_UP, 0, 0}, 2, + (unsigned) (1 << 5 | 1 << 6 | 1 << 9 | 1 << 10)}, { + "##`##" "##`##" "`````" " ### " " ### ", { + GO_LEFT, GO_UP, GO_RIGHT, 0}, 3, (unsigned) 1 << 6}, { + " `##" "##`##" "##```" "##`##" " `##", { + GO_UP, GO_RIGHT, GO_DOWN, 0}, 3, (unsigned) (1 << 7)}, { + " ### " " ### " "`````" "##`##" "##`##", { + GO_LEFT, GO_RIGHT, GO_DOWN, 0}, 3, (unsigned) (1 << 8)}, { + "##` " "##`##" "```##" "##`##" "##` ", { + GO_UP, GO_DOWN, GO_LEFT, 0}, 3, (unsigned) (1 << 9)}, { + "##`##" "##`##" "`````" "##`##" "##`##", { + GO_UP, GO_DOWN, GO_LEFT, GO_RIGHT}, 4, (unsigned) (1 << 10)} +}; + +/* probability array for each of the tiles */ +#define MAXTILEPROB 22 +static const unsigned tileprob[MAXTILEPROB] = + { 0, 0, 0, 1, 1, 2, 3, 4, 5, 6, 6, 6, 7, 7, 8, 8, 8, 9, 9, 10, 10, 10 }; + + +static int creatlevelblock (pacmangamestruct *pp, + lev_t * level, const unsigned x, + const unsigned y); + + +enum +{ TOP_LEFT, TOP_RIGHT, BOTTOM_LEFT, BOTTOM_RIGHT }; + +/* Sets a block in the level to a certain state. */ +static void +setblockto (lev_t * level, const unsigned x, const unsigned y, const char c) +{ + if (!(x < LEVWIDTH && y < LEVHEIGHT)) + return; + (*level)[y][x] = c; +} + +/* check if a block is set */ +static int +checkset (lev_t * level, const unsigned x, const unsigned y) +{ + if (!(x < LEVWIDTH && y < LEVHEIGHT) || + (*level)[y][x] == BLOCK_WALL || (*level)[y][x] == BLOCK_GHOST_ONLY) + return True; + return False; +} + +/* Check if a block is not set */ +static int +checksetout (lev_t * level, const unsigned x, const unsigned y) +{ + if (!(x < LEVWIDTH && y < LEVHEIGHT) || checkset (level, x, y) != 0) + return True; + + return False; +} + +/* Check if a block cannot be set */ +static int +checkunsetdef (lev_t * level, const unsigned x, const unsigned y) +{ + if (!(x < LEVWIDTH && y < LEVHEIGHT)) + return False; + if ((*level)[y][x] == BLOCK_DOT_1) + return True; + return False; +} + +/* Initializes a level to empty state. */ +static void +clearlevel (lev_t * level) +{ + unsigned x, y; + + for (y = 0; y < LEVHEIGHT; y++) + for (x = 0; x < LEVWIDTH; x++) + (*level)[y][x] = BLOCK_EMPTY; +} + +/* Changes a level from the level creation structure ((array to array) to + array. */ +static void +copylevel (char *dest, lev_t * level) +{ + unsigned x, y; + + for (y = 0; y < LEVHEIGHT; y++) + for (x = 0; x < LEVWIDTH; x++) + dest[y * LEVWIDTH + x] = (*level)[y][x]; +} + +/* Creates a jail to work around, so we can finish it later. */ +static void +createjail (lev_t * level, const unsigned width, const unsigned height) +{ + unsigned x, y, xstart, xend, ystart, yend; + + if (LEVWIDTH < width || LEVHEIGHT < height) + return; + + xstart = LEVWIDTH / 2 - width / 2; + xend = LEVWIDTH / 2 + width / 2; + ystart = LEVHEIGHT / 2 - height / 2; + yend = LEVHEIGHT / 2 + height / 2; + + for (y = ystart - 1; y < yend + 1; y++) + for (x = xstart - 1; x < xend + 1; x++) + setblockto (level, x, y, BLOCK_DOT_1); + + for (y = ystart; y < yend; y++) + for (x = xstart; x < xend; x++) + setblockto (level, x, y, BLOCK_WALL); +} + +void +pacman_get_jail_opening ( int *x, int *y) +{ + int xstart = LEVWIDTH / 2 - JAILWIDTH / 2; + int ystart = LEVHEIGHT / 2 - JAILHEIGHT / 2; + *x = xstart + JAILWIDTH / 2; + *y = ystart; +} + +/* Finishes a jail so it is empty and the ghostpass is on top. */ +static void +finishjail (lev_t * level, const unsigned width, const unsigned height) +{ + unsigned x, y, xstart, xend, ystart, yend; + + xstart = LEVWIDTH / 2 - width / 2; + xend = LEVWIDTH / 2 + width / 2; + ystart = LEVHEIGHT / 2 - height / 2; + yend = LEVHEIGHT / 2 + height / 2; + + for (y = ystart + 1; y < yend - 1; y++) + for (x = xstart + 1; x < xend - 1; x++) + setblockto (level, x, y, BLOCK_EMPTY); + + for (x = xstart - 1; x < xend + 1; x++) { + setblockto (level, x, ystart - 1, BLOCK_EMPTY); + setblockto (level, x, yend, BLOCK_EMPTY); + } + + for (y = ystart - 1; y < yend + 1; y++) { + setblockto (level, xstart - 1, y, BLOCK_EMPTY); + setblockto (level, xend, y, BLOCK_EMPTY); + } + + setblockto (level, xstart + width / 2 - 1, ystart, BLOCK_GHOST_ONLY); + setblockto (level, xstart + width / 2, ystart, BLOCK_GHOST_ONLY); +} + +/* Tries to set a block at a certain position. Returns true if possible, + and leaves level in new state (plus block), or False if not possible, + and leaves level in unpredictable state. */ +static int +tryset (lev_t * level, const unsigned xpos, const unsigned ypos, + const char *block) +{ + register unsigned x, y; + register char locchar; + int xstart, ystart; + unsigned xend, yend; + + if ((*level)[ypos][xpos] == BLOCK_DOT_1) + return False; + + xstart = xpos - 2; + ystart = ypos - 2; + + for (y = 0; y < TILEHEIGHT; y++) + for (x = 0; x < TILEWIDTH; x++) { + locchar = block[y * TILEWIDTH + x]; + if (locchar == BLOCK_EMPTY) + continue; + if (locchar == BLOCK_DOT_1 && + (xstart + x < 1 || + xstart + x >= LEVWIDTH - 1 || + ystart + y < 1 || + ystart + y >= LEVHEIGHT - 1 || + checkset (level, xstart + x, ystart + y) != 0)) + return False; + else if (locchar == BLOCK_WALL && + (xstart + x > 1 && + xstart + x < LEVWIDTH && + ystart + y > 1 && + ystart + y < LEVHEIGHT - 1) && + checkunsetdef (level, + (unsigned) (xstart + x), + (unsigned) (ystart + y)) != 0) + return False; + } + + /* and set the block in place */ + + xend = (xstart + TILEWIDTH < LEVWIDTH - 1) ? + TILEWIDTH : LEVWIDTH - xstart - 2; + yend = (ystart + TILEHEIGHT < LEVHEIGHT - 1) ? + TILEHEIGHT : LEVHEIGHT - ystart - 2; + + for (y = (ystart < 1) ? (unsigned) (1 - ystart) : 0U; y < yend; y++) + for (x = (xstart < 1) ? (unsigned) (1 - xstart) : 0U; x < xend; x++) { + locchar = block[y * TILEWIDTH + x]; + if ((locchar == BLOCK_WALL) && + ((*level)[ystart + y][xstart + x] == BLOCK_EMPTY)) { + (*level)[ystart + y][xstart + x] = BLOCK_WALL; + (*level)[ystart + y] + [LEVWIDTH - (xstart + x + 1)] = BLOCK_WALL; + } + } + + (*level)[ypos][xpos] = BLOCK_DOT_1; + (*level)[ypos][LEVWIDTH - xpos - 1] = BLOCK_DOT_1; + + return True; +} + +/* Tries certain combinations of blocks in the level recursively. */ +static unsigned +nextstep (pacmangamestruct *pp, + lev_t * level, const unsigned x, const unsigned y, + unsigned dirvec[], unsigned ndirs) +{ + unsigned dirpos, curdir, inc = 0; + int ret = 0; + + while (ndirs > 0) { + ndirs--; + if (ndirs == 0) { + curdir = dirvec[0]; + } + else { + dirpos = NRAND (ndirs); + curdir = dirvec[dirpos]; + /* nope, no bufoverflow, but ndirs - 1 + 1 */ + dirvec[dirpos] = dirvec[ndirs]; + dirvec[ndirs] = curdir; + } + + switch (curdir) { + case GO_UP: + if (y < 1 || (ret = creatlevelblock (pp, level, x, y - 1)) + == 0) + return 0; + break; + case GO_RIGHT: + if (x > LEVWIDTH - 2 || (ret = creatlevelblock (pp, level, x + 1, y)) + == 0) + return 0; + break; + case GO_DOWN: + if (y > LEVHEIGHT - 2 || (ret = creatlevelblock (pp, level, x, y + 1)) + == 0) + return 0; + break; + case GO_LEFT: + if (x < 1 || (ret = creatlevelblock (pp, level, x - 1, y)) + == 0) + return 0; + } + if (ret != -1) + inc += (unsigned) ret; + } + if (inc == 0) + inc = 1; + return inc; +} + +static int +creatlevelblock (pacmangamestruct *pp, + lev_t * level, const unsigned x, const unsigned y) +{ + unsigned tried = GETNB (TILES_COUNT); + unsigned tilenr; + unsigned ret; + lev_t savedlev; + + if (!pp->tiles) { + pp->tiles = (struct tiles *) malloc (sizeof (def_tiles)); + memcpy (pp->tiles, def_tiles, sizeof (def_tiles)); + } + + if (!((x < LEVWIDTH) && (y < LEVHEIGHT))) + return 0; + + if (checkunsetdef (level, x, y) != 0) + return -1; + + if (x == 0) + tried &= ~(1 << 0); + else if (x == 1) + tried &= ~(1 << 4 | 1 << 5 | 1 << 6 | 1 << 8 | 1 << 9 | 1 << 10); + else if (x == LEVWIDTH - 1) + tried &= ~(1 << 0); + else if (x == LEVWIDTH - 2) + tried &= ~(1 << 2 | 1 << 3 | 1 << 6 | 1 << 7 | 1 << 8 | 1 << 10); + + if (y == 1) + tried &= ~(1 << 2 | 1 << 5 | 1 << 6 | 1 << 7 | 1 << 9 | 1 << 10); + else if (y == 0) + tried &= ~(1 << 1); + else if (y == LEVHEIGHT - 1) + tried &= ~(1 << 1); + else if (y == LEVHEIGHT - 2) + tried &= ~(1 << 3 | 1 << 4 | 1 << 7 | 1 << 8 | 1 << 9 | 1 << 10); + + /* make a copy of the current level, so we can go back on the stack */ + (void) memcpy (&savedlev, level, sizeof (lev_t)); + + /* while there are still some blocks left to try */ + while (tried != 0x00) { + tilenr = tileprob[NRAND (MAXTILEPROB)]; + + if (!TESTNB (tried, tilenr)) + continue; + + if (tryset (level, x, y, pp->tiles[tilenr].block) != 0) { + if ((ret = nextstep (pp, level, x, y, pp->tiles[tilenr].dirvec, + pp->tiles[tilenr].ndirs)) != 0) { + return ret + 1; + } + (void) memcpy (level, &savedlev, sizeof (lev_t)); + } + tried &= ~(pp->tiles[tilenr].simular_to); + } + return 0; +} + +/* Fills up all empty space so there is wall everywhere. */ +static void +filllevel (lev_t * level) +{ + unsigned x, y; + + for (y = 0; y < LEVHEIGHT; y++) + for (x = 0; x < LEVWIDTH; x++) + if ((*level)[y][x] == BLOCK_EMPTY) + (*level)[y][x] = BLOCK_WALL; +} + + +/* Check to see if the x and y value are in the corners. + * we could probable compute these values once and avoid + * go through the loops every time. + */ +static void +top_left (lev_t * level, unsigned int *passed_x, unsigned int *passed_y) +{ + int x, y; + for (y = 0; y < LEVHEIGHT; y++) + for (x = 0; x < LEVWIDTH; x++) { + if (checkset (level, x, y) == 0) { + *passed_x = x; + *passed_y = y; + return; + } + } +} + + +static void +bottom_left (lev_t * level, unsigned int *passed_x, unsigned int *passed_y) +{ + int x, y; + for (y = LEVHEIGHT; y > -1; y--) + for (x = 0; x < LEVWIDTH; x++) { + if (checkset (level, x, y) == 0) { + *passed_x = x; + *passed_y = y; + return; + } + } +} + +static void +top_right (lev_t * level, unsigned int *passed_x, unsigned int *passed_y) +{ + int x, y; + + for (y = 0; y < LEVHEIGHT; y++) + for (x = LEVWIDTH; x >= 0; x--) { + if (checkset (level, x, y) == 0) { + *passed_x = x; + *passed_y = y; + return; + } + } +} + +static void +bottom_right (lev_t * level, unsigned int *passed_x, unsigned int *passed_y) +{ + int x, y; + + for (y = LEVHEIGHT; y >= 0; y--) + for (x = LEVWIDTH; x >= 0; x--) { + if (checkset (level, x, y) == 0) { + *passed_x = x; + *passed_y = y; + return; + } + } +} + +static void +init_bonus_dots (pacmangamestruct *pp, lev_t * level) +{ + unsigned int x = 0, y = 0; + top_left (level, &x, &y); + pp->bonus_dots[TOP_LEFT].x = x; + pp->bonus_dots[TOP_LEFT].y = y; + pp->bonus_dots[TOP_LEFT].eaten = False; + top_right (level, &x, &y); + pp->bonus_dots[TOP_RIGHT].x = x; + pp->bonus_dots[TOP_RIGHT].y = y; + pp->bonus_dots[TOP_RIGHT].eaten = False; + bottom_left (level, &x, &y); + pp->bonus_dots[BOTTOM_LEFT].x = x; + pp->bonus_dots[BOTTOM_LEFT].y = y; + pp->bonus_dots[BOTTOM_LEFT].eaten = False; + bottom_right (level, &x, &y); + pp->bonus_dots[BOTTOM_RIGHT].x = x; + pp->bonus_dots[BOTTOM_RIGHT].y = y; + pp->bonus_dots[BOTTOM_RIGHT].eaten = False; +} + +int +pacman_is_bonus_dot (pacmangamestruct *pp, int x, int y, int *idx) +{ + int ret = False; + int i; + for (i = 0; i <= NUM_BONUS_DOTS; i++) { +/* fprintf(stderr,"is bonus: passed x (%d, %d) bonus (%d, %d)\n",x,y,bonus_dots[i].x, bonus_dots[i].y); */ + if (x == pp->bonus_dots[i].x && y == pp->bonus_dots[i].y) { + ret = True; + *idx = i; + break; + } + } + return ret; +} + +static void +check_bonus_idx (int idx) +{ + assert (0 <= idx && idx <= NUM_BONUS_DOTS); +} + +int +pacman_bonus_dot_eaten (pacmangamestruct *pp, int idx) +{ + check_bonus_idx (idx); + return pp->bonus_dots[idx].eaten; +} + +void +pacman_eat_bonus_dot (pacmangamestruct *pp, int idx) +{ + check_bonus_idx (idx); + pp->bonus_dots[idx].eaten = True; +} + +void +pacman_bonus_dot_pos (pacmangamestruct *pp, int idx, int *x, int *y) +{ + check_bonus_idx (idx); + *x = pp->bonus_dots[idx].x; + *y = pp->bonus_dots[idx].y; +} + +/* Changes a level from a simple wall/nowall to a wall with rounded corners + and such. Stupid algorithm, could be done better! */ +static void +frmtlevel (pacmangamestruct *pp, lev_t * level) +{ + lev_t frmtlev; + int x, y; + int idx; + register unsigned poscond; + register unsigned poscond2; + + clearlevel (&frmtlev); + init_bonus_dots (pp, level); + for (y = 0; y < LEVHEIGHT; y++) + for (x = 0; x < LEVWIDTH; x++) { + + if (checkset (level, x, y) == 0) { + if (pacman_is_bonus_dot (pp, x, y, &idx)) { + frmtlev[y][x] = BLOCK_DOT_BONUS; + } + else { + frmtlev[y][x] = BLOCK_DOT_2; + } + continue; + } + + if ((*level)[y][x] == BLOCK_GHOST_ONLY) { + frmtlev[y][x] = BLOCK_GHOST_ONLY; + continue; + } + + poscond = + (checksetout (level, x - 1, y - 1) != 0 ? + 0x01U : 0U) | + (checksetout (level, x + 1, y - 1) != 0 ? + 0x02U : 0U) | + (checksetout (level, x + 1, y + 1) != 0 ? + 0x04U : 0U) | + (checksetout (level, x - 1, y + 1) != 0 ? 0x08U : 0U); + + poscond2 = + (checksetout (level, x - 1, y) != 0 ? + 0x01U : 0) | + (checksetout (level, x, y - 1) != 0 ? + 0x02U : 0) | + (checksetout (level, x + 1, y) != 0 ? + 0x04U : 0) | + (checksetout (level, x, y + 1) != 0 ? 0x08U : 0); + + switch (poscond) { + /* completely filled */ + case 0x01U | 0x02U | 0x04U | 0x08U: + frmtlev[y][x] = BLOCK_EMPTY; + continue; + + /* left to top corner */ + case 0x01U: + frmtlev[y][x] = BLOCK_WALL_TL; + continue; + /* top to right corner */ + case 0x02U: + frmtlev[y][x] = BLOCK_WALL_TR; + continue; + /* right to bottom corner */ + case 0x04U: + frmtlev[y][x] = BLOCK_WALL_BR; + continue; + /* bottom to left corner */ + case 0x08U: + frmtlev[y][x] = BLOCK_WALL_BL; + continue; + } + + switch (poscond2) { + case 0x01U | 0x04U: + case 0x01U | 0x04U | 0x08U: + case 0x01U | 0x04U | 0x02U: + frmtlev[y][x] = BLOCK_WALL_HO; + continue; + case 0x02U | 0x08U: + case 0x02U | 0x08U | 0x01U: + case 0x02U | 0x08U | 0x04U: + frmtlev[y][x] = BLOCK_WALL_VE; + continue; + case 0x01U | 0x02U: + frmtlev[y][x] = BLOCK_WALL_TL; + continue; + case 0x02U | 0x04U: + frmtlev[y][x] = BLOCK_WALL_TR; + continue; + case 0x04U | 0x08U: + frmtlev[y][x] = BLOCK_WALL_BR; + continue; + case 0x08U | 0x01U: + frmtlev[y][x] = BLOCK_WALL_BL; + continue; + } + switch (poscond) { + case 0x02U | 0x04U | 0x08U: + frmtlev[y][x] = BLOCK_WALL_TL; + continue; + case 0x01U | 0x04U | 0x08U: + frmtlev[y][x] = BLOCK_WALL_TR; + continue; + case 0x01U | 0x02U | 0x08U: + frmtlev[y][x] = BLOCK_WALL_BR; + continue; + case 0x01U | 0x02U | 0x04U: + frmtlev[y][x] = BLOCK_WALL_BL; + continue; + } + frmtlev[y][x] = BLOCK_EMPTY; + } + (void) memcpy ((lev_t *) level, (lev_t *) & frmtlev, sizeof (lev_t)); +} + +/* Counts the number of dots in the level, and returns that number. */ +static unsigned +countdots (pacmangamestruct *pp) +{ + unsigned i, count = 0; + + for (i = 0; i < LEVWIDTH * LEVHEIGHT; i++) + if (pp->level[i] == BLOCK_DOT_2 || pp->level[i] == BLOCK_DOT_BONUS) + count++; + + return count; +} + +/* Creates a new level, and places that in the pacmangamestruct. */ +int +pacman_createnewlevel (pacmangamestruct *pp) +{ + lev_t *level; + unsigned dirvec[1] = { GO_UP }; + unsigned ret = 0, i = 0; + + if ((level = (lev_t *) calloc (1, sizeof (lev_t))) == NULL) + return i; + + if (NRAND (2) == 0) { + + do { + clearlevel (level); + createjail (level, JAILWIDTH, JAILHEIGHT); + if ((ret = nextstep (pp, level, LEVWIDTH / 2 - 1, + LEVHEIGHT / 2 - JAILHEIGHT / 2 - 3, + dirvec, 1)) == 0) { + (void) free ((void *) level); + return i; + } + } while (ret * 100 < (LEVWIDTH * LEVHEIGHT * MINDOTPERC)); + + filllevel (level); + frmtlevel (pp, level); + finishjail (level, JAILWIDTH, JAILHEIGHT); + } + else { + (void) memcpy (level, stdlevel, sizeof (lev_t)); + frmtlevel (pp, level); + i = 1; + } + copylevel (pp->level, level); + pp->dotsleft = countdots (pp); + + (void) free ((void *) level); + return i; +} + +/* Checks if a position is allowable for ghosts/pacs to enter. */ +int +pacman_check_pos (pacmangamestruct * pp, int y, int x, int ghostpass) +{ + if ((pp->level[y * LEVWIDTH + x] == BLOCK_DOT_2) || + (pp->level[y * LEVWIDTH + x] == BLOCK_EMPTY) || + (pp->level[y * LEVWIDTH + x] == BLOCK_DOT_BONUS) || + ((pp->level[y * LEVWIDTH + x] == BLOCK_GHOST_ONLY) && ghostpass)) { + return 1; + } + return 0; +} + +/* Checks if there is a dot on the specified position in the level. */ +int +pacman_check_dot (pacmangamestruct * pp, unsigned int x, unsigned int y) +{ + if (x >= LEVWIDTH || y >= LEVHEIGHT) + return 0; + if (pp->level[y * LEVWIDTH + x] == BLOCK_DOT_2) + return 1; + return 0; +} diff --git a/hacks/pacman_level.h b/hacks/pacman_level.h new file mode 100644 index 00000000..0eccc338 --- /dev/null +++ b/hacks/pacman_level.h @@ -0,0 +1,33 @@ +/*- + * Copyright (c) 2002 by Edwin de Jong . + * + * Permission to use, copy, modify, and distribute this software and its + * documentation for any purpose and without fee is hereby granted, + * provided that the above copyright notice appear in all copies and that + * both that copyright notice and this permission notice appear in + * supporting documentation. + * + * This file is provided AS IS with no warranties of any kind. The author + * shall have no liability with respect to the infringement of copyrights, + * trade secrets or any patents by this file or any part thereof. In no + * event will the author be liable for any lost revenue or profits or + * other special, indirect and consequential damages. + */ + +#ifndef __PACMAN_LEVEL_H__ +#define __PACMAN_LEVEL_H__ + +/* typedef struct { */ +/* int x, y; */ +/* } XY; */ + +extern int pacman_createnewlevel (pacmangamestruct *); +extern int pacman_check_pos (pacmangamestruct *, int y, int x, int ghostpass); +extern int pacman_check_dot (pacmangamestruct *, + unsigned int x, unsigned int y); +extern int pacman_is_bonus_dot (pacmangamestruct *, int x, int y, int *idx); +extern int pacman_bonus_dot_eaten (pacmangamestruct *, int idx); +extern void pacman_eat_bonus_dot (pacmangamestruct *, int idx); +extern void pacman_bonus_dot_pos (pacmangamestruct *, int idx, int *x, int *y); +extern void pacman_get_jail_opening (int *x, int *y); +#endif /* __PACMAN_LEVEL_H__ */ diff --git a/hacks/pedal.c b/hacks/pedal.c new file mode 100644 index 00000000..7495aaeb --- /dev/null +++ b/hacks/pedal.c @@ -0,0 +1,326 @@ +/* + * pedal + * + * Based on a program for some old PDP-11 Graphics Display Processors + * at CMU. + * + * X version by + * + * Dale Moore + * 24-Jun-1994 + * + * Copyright (c) 1994, by Carnegie Mellon University. Permission to use, + * copy, modify, distribute, and sell this software and its documentation + * for any purpose is hereby granted without fee, provided fnord 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 fnord this software + * for any purpose. It is provided "as is" without express or implied + * warranty. + */ + +#include +#include +#include "screenhack.h" +#include "erase.h" + +/* If MAXLINES is too big, we might not be able to get it + * to the X server in the 2byte length field. Must be less + * than 16k + */ +#define MAXLINES (16 * 1024) +#define MAXPOINTS MAXLINES + +/* + * If the pedal has only this many lines, it must be ugly and we dont + * want to see it. + */ +#define MINLINES 7 + + +struct state { + Display *dpy; + Window window; + + XPoint *points; + + int sizex, sizey; + int delay; + int maxlines; + GC gc; + XColor foreground, background; + Colormap cmap; + + eraser_state *eraser; + int erase_p; +}; + + +/* + * Routine (Macro actually) + * mysin + * Description: + * Assume that degrees is .. oh 360... meaning that + * there are 360 degress in a circle. Then this function + * would return the sin of the angle in degrees. But lets + * say that they are really big degrees, with 4 big degrees + * the same as one regular degree. Then this routine + * would be called mysin(t, 90) and would return sin(t degrees * 4) + */ +#define mysin(t, degrees) sin(t * 2 * M_PI / (degrees)) +#define mycos(t, degrees) cos(t * 2 * M_PI / (degrees)) + +/* + * Macro: + * rand_range + * Description: + * Return a random number between a inclusive and b exclusive. + * rand (3, 6) returns 3 or 4 or 5, but not 6. + */ +#define rand_range(a, b) (a + random() % (b - a)) + + +static int +gcd(int m, int n) /* Greatest Common Divisor (also Greates common factor). */ +{ + int r; + + for (;;) { + r = m % n; + if (r == 0) return (n); + m = n; + n = r; + } +} + +static int numlines (int a, int b, int d) +/* + * Description: + * + * Given parameters a and b, how many lines will we have to draw? + * + * Algorithm: + * + * This algorithm assumes that r = sin (theta * a), where we + * evaluate theta on multiples of b. + * + * LCM (i, j) = i * j / GCD (i, j); + * + * So, at LCM (b, 360) we start over again. But since we + * got to LCM (b, 360) by steps of b, the number of lines is + * LCM (b, 360) / b. + * + * If a is odd, then at 180 we cross over and start the + * negative. Someone should write up an elegant way of proving + * this. Why? Because I'm not convinced of it myself. + * + */ +{ +#define odd(x) (x & 1) +#define even(x) (!odd(x)) + if ( odd(a) && odd(b) && even(d)) d /= 2; + return (d / gcd (d, b)); +#undef odd +} + +static int +compute_pedal(struct state *st, XPoint *points, int maxpoints) +/* + * Description: + * + * Basically, it's combination spirograph and string art. + * Instead of doing lines, we just use a complex polygon, + * and use an even/odd rule for filling in between. + * + * The spirograph, in mathematical terms is a polar + * plot of the form r = sin (theta * c); + * The string art of this is that we evaluate that + * function only on certain multiples of theta. That is + * we let theta advance in some random increment. And then + * we draw a straight line between those two adjacent points. + * + * Eventually, the lines will start repeating themselves + * if we've evaluated theta on some rational portion of the + * whole. + * + * The number of lines generated is limited to the + * ratio of the increment we put on theta to the whole. + * If we say that there are 360 degrees in a circle, then we + * will never have more than 360 lines. + * + * Return: + * + * The number of points. + * + */ +{ + int a, b, d; /* These describe a unique pedal */ + + double r; + int theta = 0; + XPoint *pp = st->points; + int count; + int numpoints; + + /* Just to make sure that this division is not done inside the loop */ + int h_width = st->sizex / 2, h_height = st->sizey / 2 ; + + for (;;) { + d = rand_range (MINLINES, st->maxlines); + + a = rand_range (1, d); + b = rand_range (1, d); + numpoints = numlines(a, b, d); + if (numpoints > MINLINES) break; + } + + /* it might be nice to try to move as much sin and cos computing + * (or at least the argument computing) out of the loop. + */ + for (count = numpoints; count-- ; ) + { + r = mysin (theta * a, d); + + /* Convert from polar to cartesian coordinates */ + /* We could round the results, but coercing seems just fine */ + pp->x = mysin (theta, d) * r * h_width + h_width; + pp->y = mycos (theta, d) * r * h_height + h_height; + + /* Advance index into array */ + pp++; + + /* Advance theta */ + theta += b; + theta %= d; + } + + return(numpoints); +} + +static void * +pedal_init (Display *dpy, Window window) +{ + struct state *st = (struct state *) calloc (1, sizeof(*st)); + XGCValues gcv; + XWindowAttributes xgwa; + + st->dpy = dpy; + st->window = window; + + st->delay = get_integer_resource (st->dpy, "delay", "Integer"); + if (st->delay < 0) st->delay = 0; + + st->maxlines = get_integer_resource (st->dpy, "maxlines", "Integer"); + if (st->maxlines < MINLINES) st->maxlines = MINLINES; + else if (st->maxlines > MAXLINES) st->maxlines = MAXLINES; + + st->points = (XPoint *)malloc(sizeof(XPoint) * st->maxlines); + + XGetWindowAttributes (st->dpy, st->window, &xgwa); + st->sizex = xgwa.width; + st->sizey = xgwa.height; + + st->cmap = xgwa.colormap; + + gcv.function = GXcopy; + gcv.foreground = get_pixel_resource (st->dpy, st->cmap, "foreground", "Foreground"); + gcv.background = get_pixel_resource (st->dpy, st->cmap, "background", "Background"); + st->gc = XCreateGC (st->dpy, st->window, GCForeground | GCBackground |GCFunction, &gcv); + + return st; +} + +/* + * Since the XFillPolygon doesn't require that the last + * point == first point, the number of points is the same + * as the number of lines. We just let XFillPolygon supply + * the line from the last point to the first point. + * + */ +static unsigned long +pedal_draw (Display *dpy, Window window, void *closure) +{ + struct state *st = (struct state *) closure; + int numpoints; + int erase_delay = 10000; + int long_delay = 1000000 * st->delay; + + if (st->erase_p || st->eraser) { + st->eraser = erase_window (dpy, window, st->eraser); + st->erase_p = 0; + return (st->eraser ? erase_delay : 1000000); + } + + numpoints = compute_pedal(st, st->points, st->maxlines); + + /* Pick a new foreground color (added by jwz) */ + if (! mono_p) + { + XColor color; + hsv_to_rgb (random()%360, 1.0, 1.0, + &color.red, &color.green, &color.blue); + if (XAllocColor (st->dpy, st->cmap, &color)) + { + XSetForeground (st->dpy, st->gc, color.pixel); + XFreeColors (st->dpy, st->cmap, &st->foreground.pixel, 1, 0); + st->foreground.red = color.red; + st->foreground.green = color.green; + st->foreground.blue = color.blue; + st->foreground.pixel = color.pixel; + } + } + + XFillPolygon (st->dpy, st->window, st->gc, st->points, numpoints, + Complex, CoordModeOrigin); + + st->erase_p = 1; + return long_delay; +} + +static void +pedal_reshape (Display *dpy, Window window, void *closure, + unsigned int w, unsigned int h) +{ + struct state *st = (struct state *) closure; + st->sizex = w; + st->sizey = h; +} + +static Bool +pedal_event (Display *dpy, Window window, void *closure, XEvent *event) +{ + return False; +} + +static void +pedal_free (Display *dpy, Window window, void *closure) +{ + struct state *st = (struct state *) closure; + free (st); +} + + + + +/* + * If we are trying to save the screen, the background + * should be dark. + */ +static const char *pedal_defaults [] = { + ".background: black", + ".foreground: white", + "*fpsSolid: true", + "*delay: 5", + "*maxlines: 1000", + 0 +}; + +static XrmOptionDescRec pedal_options [] = { + { "-delay", ".delay", XrmoptionSepArg, 0 }, + { "-maxlines", ".maxlines", XrmoptionSepArg, 0 }, + { "-foreground", ".foreground", XrmoptionSepArg, 0 }, + { "-background", ".background", XrmoptionSepArg, 0 }, + { 0, 0, 0, 0 } +}; + +XSCREENSAVER_MODULE ("Pedal", pedal) diff --git a/hacks/pedal.man b/hacks/pedal.man new file mode 100644 index 00000000..79d0d0cc --- /dev/null +++ b/hacks/pedal.man @@ -0,0 +1,60 @@ +.TH XScreenSaver 1 "24-Jun-94" "X Version 11" +.SH NAME +pedal - pretty geometric picture program +.SH SYNOPSIS +.B pedal +[\-display \fIhost:display.screen\fP] [\-foreground \fIcolor\fP] [\-background \fIcolor\fP] [\-window] [\-root] [\-delay \fIseconds\fP] [-maxlines \fInumber\fP] [-mono] [\-install] [\-visual \fIvisual\fP] +[\-fps] +.SH DESCRIPTION +The \fIpedal\fP program displays pretty geometric pictures. +.SH OPTIONS +.I pedal +accepts the following options: +.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 \-foreground \fIcolor\fP +The color for the foreground. Default is white. +.TP 8 +.B \-background \fIcolor\fP +The color for the background. Default is black. +.TP 8 +.B \-delay \fIseconds\fP +The number of seconds to pause between each picture. +.TP 8 +.B \-maxlines \fInumber\fP +The maximum number of lines in the drawing. Good values are +between 20 and 2000. Maximum value is 16K. +.PP +To make your X server grunt under load, and to impress your +friends, try \fIpedal -mono -delay 0 -maxlines 100\fp. +.TP 8 +.B \-fps +Display the current frame rate and CPU load. +.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 1994, by Carnegie Mellon University. Permission to use, +copy, modify, distribute, and sell this software and its documentation +for any purpose is hereby granted without fee, provided fnord 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 fnord this software +for any purpose. It is provided "as is" without express or implied +warranty. +.SH AUTHOR +Dale Moore , 24-Jun-1994. diff --git a/hacks/penetrate.c b/hacks/penetrate.c new file mode 100644 index 00000000..0707422b --- /dev/null +++ b/hacks/penetrate.c @@ -0,0 +1,988 @@ +/* Copyright (c) 1999 Adam Miller adum@aya.yale.edu + * + * 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. + + * penetrate simulates the arcade classic with the cities and the stuff + * shooting down from the sky and stuff. The computer plays against itself, + * desperately defending the forces of good against those thingies raining + * down. Bonus cities are awarded at ever-increasing intervals. Every five + * levels appears a bonus round. The computer player gets progressively + * more intelligent as the game progresses. Better aim, more economical with + * ammo, and better target selection. Points are in the bottom right, and + * high score is in the bottom left. Start with -smart to have the computer + * player skip the learning process. + + Version: 0.2 + -- fixed an AI bug that was keeping the computer player a tad weak + Version: 0.1 + -- first release + + */ + +#include "screenhack.h" + +#define kSleepTime 10000 + +#define font_height(font) (font->ascent + font->descent) + +#define kCityPause 500000 +#define kLevelPause 1 +#define SCORE_MISSILE 100 +#define kFirstBonus 5000 +#define kMinRate 30 +#define kMaxRadius 100 + +typedef struct { + int alive; + int x, y; + int startx, starty; + int endx, endy; + int dcity; + float pos; + int enemies; + int jenis; + int splits; + XColor color; +} Missile; + +typedef struct { + int alive; + int x, y, rad, oflaser; + int max, outgoing; + XColor color; +} Boom; + +typedef struct { + int alive; + int x; + XColor color; +} City; + +typedef struct { + int alive; + int x, y; + int startx, starty; + int endx, endy; + int oldx, oldy; + int oldx2, oldy2; + float velx, vely, fposx, fposy; + float lenMul; + XColor color; + int target; +} Laser; + +#define kMaxMissiles 256 +#define kMaxBooms 512 +#define kMaxLasers 128 +#define kBoomRad 40 +#define kNumCities 5 + +#define kLaserLength 12 + +#define kMissileSpeed 0.003 +#define kLaserSpeed (kMissileSpeed * 6) + + +struct state { + Display *dpy; + Window window; + + XFontStruct *font, *scoreFont; + GC draw_gc, erase_gc, level_gc; + unsigned int default_fg_pixel; + XColor scoreColor; + + int bgrowth; + int lrate, startlrate; + long loop; + long score, highscore; + long nextBonus; + int numBonus; + int bround; + long lastLaser; + int gamez; + int aim; + int econpersen; + int choosypersen; + int carefulpersen; + int smart; + Colormap cmap; + + Missile missile[kMaxMissiles]; + Boom boom[kMaxBooms]; + City city[kNumCities]; + Laser laser[kMaxLasers]; + int blive[kNumCities]; + + int level, levMissiles, levFreq; + + int draw_xlim, draw_ylim; + int draw_reset; +}; + + +static void Explode(struct state *st, int x, int y, int max, XColor color, int oflaser) +{ + int i; + Boom *m = 0; + for (i=0;iboom[i].alive) { + m = &st->boom[i]; + break; + } + if (!m) + return; + + m->alive = 1; + m->x = x; + m->y = y; + m->rad = 0; + if (max > kMaxRadius) + max = kMaxRadius; + m->max = max; + m->outgoing = 1; + m->color = color; + m->oflaser = oflaser; +} + +static void launch (struct state *st, int xlim, int ylim, int src) +{ + int i; + Missile *m = 0, *msrc; + for (i=0;imissile[i].alive) { + m = &st->missile[i]; + break; + } + if (!m) + return; + + m->alive = 1; + m->startx = (random() % xlim); + m->starty = 0; + m->endy = ylim; + m->pos = 0.0; + m->jenis = random() % 360; + m->splits = 0; + if (m->jenis < 50) { + int j = ylim * 0.4; + if (j) + m->splits = random() % j; + if (m->splits < ylim * 0.08) + m->splits = 0; + } + + /* special if we're from another missile */ + if (src >= 0) { + int dc = random() % (kNumCities - 1); + msrc = &st->missile[src]; + if (dc == msrc->dcity) + dc++; + m->dcity = dc; + m->startx = msrc->x; + m->starty = msrc->y; + if (m->starty > ylim * 0.4 || m->splits <= m->starty) + m->splits = 0; /* too far down already */ + m->jenis = msrc->jenis; + } + else + m->dcity = random() % kNumCities; + m->endx = st->city[m->dcity].x + (random() % 20) - 10; + m->x = m->startx; + m->y = m->starty; + m->enemies = 0; + + if (!mono_p) { + hsv_to_rgb (m->jenis, 1.0, 1.0, + &m->color.red, &m->color.green, &m->color.blue); + m->color.flags = DoRed | DoGreen | DoBlue; + if (!XAllocColor (st->dpy, st->cmap, &m->color)) { + m->color.pixel = WhitePixel (st->dpy, DefaultScreen (st->dpy)); + m->color.red = m->color.green = m->color.blue = 0xFFFF; + } + } +} + +#define kExpHelp 0.2 +#define kSpeedDiff 3.5 +#define kMaxToGround 0.75 +static int fire(struct state *st, int xlim, int ylim) +{ + int i, j, cnt = 0; + int dcity; + long dx, dy, ex, ey; + Missile *mis = 0; + Laser *m = 0; + int untargeted = 0; + int choosy = 0, economic = 0, careful = 0; + int suitor[kMaxMissiles]; + int livecity = 0; + int ytargetmin = ylim * 0.75; + int deepest = 0; + int misnum = 0; + + choosy = (random() % 100) < st->choosypersen; + economic = (random() % 100) < st->econpersen; + careful = (random() % 100) < st->carefulpersen; + + /* count our cities */ + for (i=0;icity[i].alive; + if (livecity == 0) + return 1; /* no guns */ + + for (i=0;ilaser[i].alive) { + m = &st->laser[i]; + break; + } + if (!m) + return 1; + + /* if no missiles on target, no need to be choosy */ + if (choosy) { + int choo = 0; + for (j=0;jmissile[j]; + if (!mis->alive || (mis->y > ytargetmin)) + continue; + if (st->city[mis->dcity].alive) + choo++; + } + if (choo == 0) + choosy = 0; + } + + for (j=0;jmissile[j]; + suitor[j] = 0; + if (!mis->alive || (mis->y > ytargetmin)) + continue; + if (choosy && (st->city[mis->dcity].alive == 0)) + continue; + ey = mis->starty + ((float) (mis->endy - mis->starty)) * (mis->pos + kExpHelp + (1.0 - mis->pos) / kSpeedDiff); + if (ey > ylim * kMaxToGround) + continue; /* too far down */ + cnt++; + suitor[j] = 1; + } + + /* count missiles that are on target and not being targeted */ + if (choosy && economic) + for (j=0;jmissile[j].enemies == 0) + untargeted++; + + if (economic) + for (j=0;j 1) + if (st->missile[j].enemies > 0) + if (st->missile[j].enemies > 1 || untargeted == 0) { + suitor[j] = 0; + cnt--; + } + /* who's closest? biggest threat */ + if (suitor[j] && st->missile[j].y > deepest) + deepest = st->missile[j].y; + } + + if (deepest > 0 && careful) { + /* only target deepest missile */ + cnt = 1; + for (j=0;jmissile[j].y != deepest) + suitor[j] = 0; + } + + if (cnt == 0) + return 1; /* no targets available */ + cnt = random() % cnt; + for (j=0;jmissile[j]; + misnum = j; + break; + } + + if (mis == 0) + return 1; /* shouldn't happen */ + + dcity = random() % livecity; + for (j=0;jcity[j].alive) + if (dcity-- == 0) { + dcity = j; + break; + } + m->startx = st->city[dcity].x; + m->starty = ylim; + ex = mis->startx + ((float) (mis->endx - mis->startx)) * (mis->pos + kExpHelp + (1.0 - mis->pos) / kSpeedDiff); + ey = mis->starty + ((float) (mis->endy - mis->starty)) * (mis->pos + kExpHelp + (1.0 - mis->pos) / kSpeedDiff); + m->endx = ex + random() % 16 - 8 + (random() % st->aim) - st->aim / 2; + m->endy = ey + random() % 16 - 8 + (random() % st->aim) - st->aim / 2; + if (ey > ylim * kMaxToGround) + return 0; /* too far down */ + mis->enemies++; + m->target = misnum; + m->x = m->startx; + m->y = m->starty; + m->oldx = -1; + m->oldy = -1; + m->oldx2 = -1; + m->oldy2 = -1; + m->fposx = m->x; + m->fposy = m->y; + dx = (m->endx - m->x); + dy = (m->endy - m->y); + m->velx = dx / 100.0; + m->vely = dy / 100.0; + m->alive = 1; + /* m->lenMul = (kLaserLength * kLaserLength) / (m->velx * m->velx + m->vely * m->vely); */ + m->lenMul = -(kLaserLength / m->vely); + + if (!mono_p) { + m->color.blue = 0x0000; + m->color.green = 0xFFFF; + m->color.red = 0xFFFF; + m->color.flags = DoRed | DoGreen | DoBlue; + if (!XAllocColor (st->dpy, st->cmap, &m->color)) { + m->color.pixel = WhitePixel (st->dpy, DefaultScreen (st->dpy)); + m->color.red = m->color.green = m->color.blue = 0xFFFF; + } + } + return 1; +} + +static void * +penetrate_init (Display *dpy, Window window) +{ + struct state *st = (struct state *) calloc (1, sizeof(*st)); + int i; + const char *levelfont = "-*-courier-*-r-*-*-*-380-*-*-*-*-*-*"; + const char *scorefont = "-*-helvetica-*-r-*-*-*-180-*-*-*-*-*-*"; + XGCValues gcv; + XWindowAttributes xgwa; + + st->dpy = dpy; + st->window = window; + + XGetWindowAttributes (st->dpy, st->window, &xgwa); + st->cmap = xgwa.colormap; + + st->lrate = 80; + st->nextBonus = kFirstBonus; + st->aim = 180; + + st->smart = get_boolean_resource(st->dpy, "smart","Boolean"); + st->bgrowth = get_integer_resource (st->dpy, "bgrowth", "Integer"); + st->lrate = get_integer_resource (st->dpy, "lrate", "Integer"); + if (st->bgrowth < 0) st->bgrowth = 2; + if (st->lrate < 0) st->lrate = 2; + st->startlrate = st->lrate; + + st->font = XLoadQueryFont(st->dpy, levelfont); + if (!st->font) { + fprintf (stderr, "%s: could not load font %s.\n", progname, levelfont); + st->font = XLoadQueryFont(st->dpy, scorefont); + if (! st->font) + st->font = XLoadQueryFont(st->dpy, "fixed"); + if (! st->font) abort(); + } + + st->scoreFont = XLoadQueryFont(st->dpy, scorefont); + if (!st->scoreFont) { + fprintf (stderr, "%s: could not load font %s.\n", progname, scorefont); + st->scoreFont = XLoadQueryFont(st->dpy, levelfont); + if (! st->scoreFont) + st->scoreFont = XLoadQueryFont(st->dpy, "fixed"); + if (! st->scoreFont) abort(); + } + + for (i = 0; i < kMaxMissiles; i++) + st->missile[i].alive = 0; + + for (i = 0; i < kMaxLasers; i++) + st->laser[i].alive = 0; + + for (i = 0; i < kMaxBooms; i++) + st->boom[i].alive = 0; + + for (i = 0; i < kNumCities; i++) { + City *m = &st->city[i]; + m->alive = 1; + m->color.red = m->color.green = m->color.blue = 0xFFFF; + m->color.blue = 0x1111; m->color.green = 0x8888; + m->color.flags = DoRed | DoGreen | DoBlue; + if (!XAllocColor (st->dpy, st->cmap, &m->color)) { + m->color.pixel = WhitePixel (st->dpy, DefaultScreen (st->dpy)); + m->color.red = m->color.green = m->color.blue = 0xFFFF; + } + } + + gcv.foreground = st->default_fg_pixel = + get_pixel_resource(st->dpy, st->cmap, "foreground", "Foreground"); + gcv.font = st->scoreFont->fid; + st->draw_gc = XCreateGC(st->dpy, st->window, GCForeground | GCFont, &gcv); + gcv.font = st->font->fid; + st->level_gc = XCreateGC(st->dpy, st->window, GCForeground | GCFont, &gcv); + XSetForeground (st->dpy, st->level_gc, st->city[0].color.pixel); + gcv.foreground = get_pixel_resource(st->dpy, st->cmap, "background", "Background"); + st->erase_gc = XCreateGC(st->dpy, st->window, GCForeground, &gcv); + +# ifdef HAVE_COCOA + jwxyz_XSetAntiAliasing (st->dpy, st->erase_gc, False); + jwxyz_XSetAntiAliasing (st->dpy, st->draw_gc, False); +# endif + + + /* make a gray color for score */ + if (!mono_p) { + st->scoreColor.red = st->scoreColor.green = st->scoreColor.blue = 0xAAAA; + st->scoreColor.flags = DoRed | DoGreen | DoBlue; + if (!XAllocColor (st->dpy, st->cmap, &st->scoreColor)) { + st->scoreColor.pixel = WhitePixel (st->dpy, DefaultScreen (st->dpy)); + st->scoreColor.red = st->scoreColor.green = st->scoreColor.blue = 0xFFFF; + } + } + + XClearWindow(st->dpy, st->window); + return st; +} + +static void DrawScore(struct state *st, int xlim, int ylim) +{ + char buf[16]; + int width, height; + sprintf(buf, "%ld", st->score); + width = XTextWidth(st->scoreFont, buf, strlen(buf)); + height = font_height(st->scoreFont); + XSetForeground (st->dpy, st->draw_gc, st->scoreColor.pixel); + XFillRectangle(st->dpy, st->window, st->erase_gc, + xlim - width - 6, ylim - height - 2, width + 6, height + 2); + XDrawString(st->dpy, st->window, st->draw_gc, xlim - width - 2, ylim - 2, + buf, strlen(buf)); + + sprintf(buf, "%ld", st->highscore); + width = XTextWidth(st->scoreFont, buf, strlen(buf)); + XFillRectangle(st->dpy, st->window, st->erase_gc, + 4, ylim - height - 2, width + 4, height + 2); + XDrawString(st->dpy, st->window, st->draw_gc, 4, ylim - 2, + buf, strlen(buf)); +} + +static void AddScore(struct state *st, int xlim, int ylim, long dif) +{ + int i, sumlive = 0; + for (i=0;icity[i].alive; + if (sumlive == 0) + return; /* no cities, not possible to score */ + + st->score += dif; + if (st->score > st->highscore) + st->highscore = st->score; + DrawScore(st, xlim, ylim); +} + +static void DrawCity(struct state *st, int x, int y, XColor col) +{ + XSetForeground (st->dpy, st->draw_gc, col.pixel); + XFillRectangle(st->dpy, st->window, st->draw_gc, + x - 30, y - 40, 60, 40); + XFillRectangle(st->dpy, st->window, st->draw_gc, + x - 20, y - 50, 10, 10); + XFillRectangle(st->dpy, st->window, st->draw_gc, + x + 10, y - 50, 10, 10); +} + +static void DrawCities(struct state *st, int xlim, int ylim) +{ + int i, x; + for (i = 0; i < kNumCities; i++) { + City *m = &st->city[i]; + if (!m->alive) + continue; + x = (i + 1) * (xlim / (kNumCities + 1)); + m->x = x; + + DrawCity(st, x, ylim, m->color); + } +} + +static void LoopMissiles(struct state *st, int xlim, int ylim) +{ + int i, j, max = 0; + for (i = 0; i < kMaxMissiles; i++) { + int old_x, old_y; + Missile *m = &st->missile[i]; + if (!m->alive) + continue; + old_x = m->x; + old_y = m->y; + m->pos += kMissileSpeed; + m->x = m->startx + ((float) (m->endx - m->startx)) * m->pos; + m->y = m->starty + ((float) (m->endy - m->starty)) * m->pos; + + /* erase old one */ + + XSetLineAttributes(st->dpy, st->draw_gc, 4, 0,0,0); + XSetForeground (st->dpy, st->draw_gc, m->color.pixel); + XDrawLine(st->dpy, st->window, st->draw_gc, + old_x, old_y, m->x, m->y); + + /* maybe split off a new missile? */ + if (m->splits && (m->y > m->splits)) { + m->splits = 0; + launch(st, xlim, ylim, i); + } + + if (m->y >= ylim) { + m->alive = 0; + if (st->city[m->dcity].alive) { + st->city[m->dcity].alive = 0; + Explode(st, m->x, m->y, kBoomRad * 2, m->color, 0); + } + } + + /* check hitting explosions */ + for (j=0;jboom[j]; + if (!b->alive) + continue; + else { + int dx = abs(m->x - b->x); + int dy = abs(m->y - b->y); + int r = b->rad + 2; + if ((dx < r) && (dy < r)) + if (dx * dx + dy * dy < r * r) { + m->alive = 0; + max = b->max + st->bgrowth - kBoomRad; + AddScore(st, xlim, ylim, SCORE_MISSILE); + } + } + } + + if (m->alive == 0) { + float my_pos; + /* we just died */ + Explode(st, m->x, m->y, kBoomRad + max, m->color, 0); + XSetLineAttributes(st->dpy, st->erase_gc, 4, 0,0,0); + /* In a perfect world, we could simply erase a line from + (m->startx, m->starty) to (m->x, m->y). This is not a + perfect world. */ + old_x = m->startx; + old_y = m->starty; + my_pos = kMissileSpeed; + while (my_pos <= m->pos) { + m->x = m->startx + ((float) (m->endx - m->startx)) * my_pos; + m->y = m->starty + ((float) (m->endy - m->starty)) * my_pos; + XDrawLine(st->dpy, st->window, st->erase_gc, old_x, old_y, m->x, m->y); + old_x = m->x; + old_y = m->y; + my_pos += kMissileSpeed; + } + } + } +} + +static void LoopLasers(struct state *st, int xlim, int ylim) +{ + int i, j, miny = ylim * 0.8; + int x, y; + for (i = 0; i < kMaxLasers; i++) { + Laser *m = &st->laser[i]; + if (!m->alive) + continue; + + if (m->oldx != -1) { + XSetLineAttributes(st->dpy, st->erase_gc, 2, 0,0,0); + XDrawLine(st->dpy, st->window, st->erase_gc, + m->oldx2, m->oldy2, m->oldx, m->oldy); + } + + m->fposx += m->velx; + m->fposy += m->vely; + m->x = m->fposx; + m->y = m->fposy; + + x = m->fposx + (-m->velx * m->lenMul); + y = m->fposy + (-m->vely * m->lenMul); + + m->oldx = x; + m->oldy = y; + + XSetLineAttributes(st->dpy, st->draw_gc, 2, 0,0,0); + XSetForeground (st->dpy, st->draw_gc, m->color.pixel); + XDrawLine(st->dpy, st->window, st->draw_gc, + m->x, m->y, x, y); + + m->oldx2 = m->x; + m->oldy2 = m->y; + m->oldx = x; + m->oldy = y; + + if (m->y < m->endy) { + m->alive = 0; + } + + /* check hitting explosions */ + if (m->y < miny) + for (j=0;jboom[j]; + if (!b->alive) + continue; + else { + int dx = abs(m->x - b->x); + int dy = abs(m->y - b->y); + int r = b->rad + 2; + if (b->oflaser) + continue; + if ((dx < r) && (dy < r)) + if (dx * dx + dy * dy < r * r) { + m->alive = 0; + /* one less enemy on this missile -- it probably didn't make it */ + if (st->missile[m->target].alive) + st->missile[m->target].enemies--; + } + } + } + + if (m->alive == 0) { + /* we just died */ + XDrawLine(st->dpy, st->window, st->erase_gc, + m->x, m->y, x, y); + Explode(st, m->x, m->y, kBoomRad, m->color, 1); + } + } +} + +static void LoopBooms(struct state *st, int xlim, int ylim) +{ + int i; + for (i = 0; i < kMaxBooms; i++) { + Boom *m = &st->boom[i]; + if (!m->alive) + continue; + + if (st->loop & 1) { + if (m->outgoing) { + m->rad++; + if (m->rad >= m->max) + m->outgoing = 0; + XSetLineAttributes(st->dpy, st->draw_gc, 1, 0,0,0); + XSetForeground (st->dpy, st->draw_gc, m->color.pixel); + XDrawArc(st->dpy, st->window, st->draw_gc, m->x - m->rad, m->y - m->rad, m->rad * 2, m->rad * 2, 0, 360 * 64); + } + else { + XSetLineAttributes(st->dpy, st->erase_gc, 1, 0,0,0); + XDrawArc(st->dpy, st->window, st->erase_gc, m->x - m->rad, m->y - m->rad, m->rad * 2, m->rad * 2, 0, 360 * 64); + m->rad--; + if (m->rad <= 0) + m->alive = 0; + } + } + } +} + + +/* after they die, let's change a few things */ +static void Improve(struct state *st) +{ + if (st->smart) + return; + if (st->level > 20) + return; /* no need, really */ + st->aim -= 4; + if (st->level <= 2) st->aim -= 8; + if (st->level <= 5) st->aim -= 6; + if (st->gamez < 3) + st->aim -= 10; + st->carefulpersen += 6; + st->choosypersen += 4; + if (st->level <= 5) st->choosypersen += 3; + st->econpersen += 4; + st->lrate -= 2; + if (st->startlrate < kMinRate) { + if (st->lrate < st->startlrate) + st->lrate = st->startlrate; + } + else { + if (st->lrate < kMinRate) + st->lrate = kMinRate; + } + if (st->level <= 5) st->econpersen += 3; + if (st->aim < 1) st->aim = 1; + if (st->choosypersen > 100) st->choosypersen = 100; + if (st->carefulpersen > 100) st->carefulpersen = 100; + if (st->econpersen > 100) st->econpersen = 100; +} + +static void NewLevel(struct state *st, int xlim, int ylim) +{ + char buf[32]; + int width, i, sumlive = 0; + int liv[kNumCities]; + int freecity = 0; + + if (st->level == 0) { + st->level++; + goto END_LEVEL; + } + + /* check for a free city */ + if (st->score >= st->nextBonus) { + st->numBonus++; + st->nextBonus += kFirstBonus * st->numBonus; + freecity = 1; + } + + for (i=0;ibround) + st->city[i].alive = st->blive[i]; + liv[i] = st->city[i].alive; + sumlive += liv[i]; + if (!st->bround) + st->city[i].alive = 0; + } + + /* print out screen */ + XFillRectangle(st->dpy, st->window, st->erase_gc, + 0, 0, xlim, ylim); + if (st->bround) + sprintf(buf, "Bonus Round Over"); + else { + if (sumlive || freecity) + sprintf(buf, "Level %d Cleared", st->level); + else + sprintf(buf, "GAME OVER"); + } + if (st->level > 0) { + width = XTextWidth(st->font, buf, strlen(buf)); + XDrawString(st->dpy, st->window, st->level_gc, xlim / 2 - width / 2, ylim / 2 - font_height(st->font) / 2, + buf, strlen(buf)); + XSync(st->dpy, False); + usleep(1000000); + } + + if (!st->bround) { + if (sumlive || freecity) { + int sumwidth; + /* draw live cities */ + XFillRectangle(st->dpy, st->window, st->erase_gc, + 0, ylim - 100, xlim, 100); + + sprintf(buf, "X %ld", st->level * 100L); + /* how much they get */ + sumwidth = XTextWidth(st->font, buf, strlen(buf)); + /* add width of city */ + sumwidth += 60; + /* add spacer */ + sumwidth += 40; + DrawCity(st, xlim / 2 - sumwidth / 2 + 30, ylim * 0.70, st->city[0].color); + XDrawString(st->dpy, st->window, st->level_gc, xlim / 2 - sumwidth / 2 + 40 + 60, ylim * 0.7, buf, strlen(buf)); + for (i=0;icity[i].alive = 1; + AddScore(st, xlim, ylim, 100 * st->level); + DrawCities(st, xlim, ylim); + XSync(st->dpy, False); + usleep(kCityPause); + } + } + } + else { + /* we're dead */ + usleep(3000000); + + /* start new */ + st->gamez++; + Improve(st); + for (i=0;icity[i].alive = 1; + st->level = 0; + st->loop = 1; + st->score = 0; + st->nextBonus = kFirstBonus; + st->numBonus = 0; + DrawCities(st, xlim, ylim); + } + } + + /* do free city part */ + if (freecity && sumlive < 5) { + int ncnt = random() % (5 - sumlive) + 1; + for (i=0;icity[i].alive) + if (!--ncnt) + st->city[i].alive = 1; + strcpy(buf, "Bonus City"); + width = XTextWidth(st->font, buf, strlen(buf)); + XDrawString(st->dpy, st->window, st->level_gc, xlim / 2 - width / 2, ylim / 4, buf, strlen(buf)); + DrawCities(st, xlim, ylim); + XSync(st->dpy, False); + usleep(1000000); + } + + XFillRectangle(st->dpy, st->window, st->erase_gc, + 0, 0, xlim, ylim - 100); + + if (!st->bround) + st->level++; + if (st->level == 1) { + st->nextBonus = kFirstBonus; + } + + if (st->level > 3 && (st->level % 5 == 1)) { + if (st->bround) { + st->bround = 0; + DrawCities(st, xlim, ylim); + } + else { + /* bonus round */ + st->bround = 1; + st->levMissiles = 20 + st->level * 10; + st->levFreq = 10; + for (i=0;iblive[i] = st->city[i].alive; + sprintf(buf, "Bonus Round"); + width = XTextWidth(st->font, buf, strlen(buf)); + XDrawString(st->dpy, st->window, st->level_gc, xlim / 2 - width / 2, ylim / 2 - font_height(st->font) / 2, buf, strlen(buf)); + XSync(st->dpy, False); + usleep(1000000); + XFillRectangle(st->dpy, st->window, st->erase_gc, + 0, 0, xlim, ylim - 100); + } + } + + END_LEVEL: ; + + if (!st->bround) { + st->levMissiles = 5 + st->level * 3; + if (st->level > 5) + st->levMissiles += st->level * 5; + /* levMissiles = 2; */ + st->levFreq = 120 - st->level * 5; + if (st->levFreq < 30) + st->levFreq = 30; + } + + /* ready to fire */ + st->lastLaser = 0; +} + + +static unsigned long +penetrate_draw (Display *dpy, Window window, void *closure) +{ + struct state *st = (struct state *) closure; + XWindowAttributes xgwa; + + if (st->draw_reset) + { + st->draw_reset = 0; + DrawCities(st, st->draw_xlim, st->draw_ylim); + } + + XGetWindowAttributes(st->dpy, st->window, &xgwa); + st->draw_xlim = xgwa.width; + st->draw_ylim = xgwa.height; + + /* see if just started */ + if (st->loop == 0) { + if (st->smart) { + st->choosypersen = st->econpersen = st->carefulpersen = 100; + st->lrate = kMinRate; st->aim = 1; + } + NewLevel(st, st->draw_xlim, st->draw_ylim); + DrawScore(st, st->draw_xlim, st->draw_ylim); + } + + st->loop++; + + if (st->levMissiles == 0) { + /* see if anything's still on the screen, to know when to end level */ + int i; + for (i=0;imissile[i].alive) + goto END_CHECK; + for (i=0;iboom[i].alive) + goto END_CHECK; + for (i=0;ilaser[i].alive) + goto END_CHECK; + /* okay, nothing's alive, start end of level countdown */ + usleep(kLevelPause*1000000); + NewLevel(st, st->draw_xlim, st->draw_ylim); + goto END; + END_CHECK: ; + } + else if ((random() % st->levFreq) == 0) { + launch(st, st->draw_xlim, st->draw_ylim, -1); + st->levMissiles--; + } + + if (st->loop - st->lastLaser >= st->lrate) { + if (fire(st, st->draw_xlim, st->draw_ylim)) + st->lastLaser = st->loop; + } + + if ((st->loop & 7) == 0) + st->draw_reset = 1; + + LoopMissiles(st, st->draw_xlim, st->draw_ylim); + LoopLasers(st, st->draw_xlim, st->draw_ylim); + LoopBooms(st, st->draw_xlim, st->draw_ylim); + + END: + return kSleepTime; +} + +static void +penetrate_reshape (Display *dpy, Window window, void *closure, + unsigned int w, unsigned int h) +{ + XClearWindow (dpy, window); +} + +static Bool +penetrate_event (Display *dpy, Window window, void *closure, XEvent *event) +{ + return False; +} + +static void +penetrate_free (Display *dpy, Window window, void *closure) +{ + struct state *st = (struct state *) closure; + free (st); +} + + +static const char *penetrate_defaults [] = { + ".background: black", + ".foreground: white", + "*fpsTop: true", + "*fpsSolid: true", + "*bgrowth: 5", + "*lrate: 80", + "*smart: False", + "*geometry: 800x500", + 0 +}; + +static XrmOptionDescRec penetrate_options [] = { + { "-bgrowth", ".bgrowth", XrmoptionSepArg, 0 }, + { "-lrate", ".lrate", XrmoptionSepArg, 0 }, + {"-smart", ".smart", XrmoptionNoArg, "True" }, + { 0, 0, 0, 0 } +}; + +XSCREENSAVER_MODULE ("Penetrate", penetrate) diff --git a/hacks/penetrate.man b/hacks/penetrate.man new file mode 100644 index 00000000..15e8d01a --- /dev/null +++ b/hacks/penetrate.man @@ -0,0 +1,98 @@ +.de EX \"Begin example +.ne 5 +.if n .sp 1 +.if t .sp .5 +.nf +.in +.5i +.. +.de EE +.fi +.in -.5i +.if n .sp 1 +.if t .sp .5 +.. +.TH XScreenSaver 1 "18-Jun-01" "X Version 11" +.SH NAME +penetrate - simulates a classic arcade shooting game +.SH SYNOPSIS +.B penetrate +[\-display \fIhost:display.screen\fP] [\-root] [\-window] +[\-install] [\-noinstall] [\-visual \fIvisual\fP] +[\-bgrowth \fImicroseconds\fP] [\-lrate \fInumber\fP] [\-smart \fInumber\fP] +[\-fps] +.SH DESCRIPTION +.PP +\fIPenetrate\fP simulates the arcade classic with the cities and the stuff +shooting down from the sky and stuff. The computer plays against itself, +desperately defending the forces of good against those thingies raining +down. Bonus cities are awarded at ever-increasing intervals. Every five +levels appears a bonus round. The computer player gets progressively +more intelligent as the game progresses. Better aim, more economical with +ammo, and better target selection. Points are in the bottom right, and +high score is in the bottom left. Start with -smart to have the computer +player skip the learning process. +.SH OPTIONS +.TP 8 +.B \-display \fIhost:display.screen\fP +Specifies which X display we should use. +.TP 8 +.B \-root +Draw on the root window. +.TP 8 +.B \-window +Draw on a newly-created window. This is the default. +.TP 8 +.B \-install +Install a private colormap for the window. +.TP 8 +.B \-noinstall +Don't install a private colormap for the window. +.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. +Possible choices include + +.RS +default, best, mono, monochrome, gray, grey, color, staticgray, staticcolor, +truecolor, grayscale, greyscale, pseudocolor, directcolor, \fInumber\fP + +If a decimal or hexadecimal number is used, +.BR XGetVisualInfo (3X) +is consulted to obtain the required visual. +.RE +.TP 8 +.B \-foreground \fIcolor\fP +Specifies the default foreground color. +.TP 8 +.B \-background \fIcolor\fP +Specifies the default background color. +.TP 8 +.B \-bgrowth \fIinteger\fP +Specifies the growth rate of the bomb explosions. +.TP 8 +.B \-lrate \fIinteger\fP +Set the initial rate of laser fire. +.TP 8 +.B -smart +Have the computer player skip the learning process. +.TP 8 +.B \-fps +Display the current frame rate and CPU load. +.SH BUGS +The layout of the screen isn't quite the same as the game this program +tries to emulate. In this this program, the missiles come out of the +cities; when really, there are supposed to be three missile bases on +hills, with the cities in the valleys between them. + +See http://www.mame.net/ for details. +.SH COPYRIGHT +Copyright \(co 1999 Adam Miller. 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 +Adam Miller , 1999. diff --git a/hacks/penrose.c b/hacks/penrose.c new file mode 100644 index 00000000..6b07d8ca --- /dev/null +++ b/hacks/penrose.c @@ -0,0 +1,1355 @@ +/* -*- Mode: C; tab-width: 4 -*- */ +/* penrose --- quasiperiodic tilings */ + +/* As reported in News of the Weird: + + In April, Sir Roger Penrose, a British math professor who has worked + with Stephen Hawking on such topics as relativity, black holes, and + whether time has a beginning, filed a copyright-infringement lawsuit + against the Kimberly-Clark Corporation, which Penrose said copied a + pattern he created (a pattern demonstrating that "a nonrepeating + pattern could exist in nature") for its Kleenex quilted toilet paper. + Penrose said he doesn't like litigation but, "When it comes to the + population of Great Britain being invited by a multinational to wipe + their bottoms on what appears to be the work of a Knight of the + Realm, then a last stand must be taken." + + NOTW #491, 4-jul-1997, by Chuck Shepherd. + http://www.nine.org/notw/notw.html + */ + +#if 0 +static const char sccsid[] = "@(#)penrose.c 5.00 2000/11/01 xlockmore"; +#endif + +/*- + * Copyright (c) 1996 by Timo Korvola + * + * Permission to use, copy, modify, and distribute this software and its + * documentation for any purpose and without fee is hereby granted, + * provided that the above copyright notice appear in all copies and that + * both that copyright notice and this permission notice appear in + * supporting documentation. + * + * This file is provided AS IS with no warranties of any kind. The author + * shall have no liability with respect to the infringement of copyrights, + * trade secrets or any patents by this file or any part thereof. In no + * event will the author be liable for any lost revenue or profits or + * other special, indirect and consequential damages. + * + * Revision History: + * 01-Nov-2000: Allocation checks + * 10-May-1997: Jamie Zawinski compatible with xscreensaver + * 09-Sep-1996: Written. + */ + +/*- +Be careful, this probably still has a few bugs (many of which may only +appear with a very low probability). These are seen with -verbose . +If one of these are hit penrose will reinitialize. +*/ + +/*- + * See Onoda, Steinhardt, DiVincenzo and Socolar in + * Phys. Rev. Lett. 60, #25, 1988 or + * Strandburg in Computers in Physics, Sep/Oct 1991. + * + * This implementation uses the simpler version of the growth + * algorithm, i.e., if there are no forced vertices, a randomly chosen + * tile is added to a randomly chosen vertex (no preference for those + * 108 degree angles). + * + * There are two essential differences to the algorithm presented in + * the literature: First, we do not allow the tiling to enclose an + * untiled area. Whenever this is in danger of happening, we just + * do not add the tile, hoping for a better random choice the next + * time. Second, when choosing a vertex randomly, we will take + * one that lies within the viewport if available. If this seems to + * cause enclosures in the forced rule case, we will allow invisible + * vertices to be chosen. + * + * Tiling is restarted whenever one of the following happens: there + * are no incomplete vertices within the viewport or the tiling has + * extended a window's length beyond the edge of the window + * horizontally or vertically or forced rule choice has failed 100 + * times due to areas about to become enclosed. + * + * Introductory info: + * Science News March 23 1985 Vol 127, No. 12 + * Science News July 16 1988 Vol 134, No. 3 + * The Economist Sept 17 1988 pg. 100 + * + */ + +#ifdef STANDALONE +#define MODE_penrose +#define DEFAULTS "*delay: 10000 \n" \ + "*size: 40 \n" \ + "*ncolors: 64 \n" \ + "*fpsSolid: true \n" \ + +# define refresh_penrose 0 +# define penrose_handle_event 0 +# include "xlockmore.h" /* from the xscreensaver distribution */ +#else /* !STANDALONE */ +# include "xlock.h" /* from the xlockmore distribution */ +#endif /* !STANDALONE */ + +#ifdef MODE_penrose + +#define DEF_AMMANN "False" + +static Bool ammann; + +static XrmOptionDescRec opts[] = +{ + {"-ammann", ".penrose.ammann", XrmoptionNoArg, "on"}, + {"+ammann", ".penrose.ammann", XrmoptionNoArg, "off"} +}; +static argtype vars[] = +{ + {&ammann, "ammann", "Ammann", DEF_AMMANN, t_Bool} +}; +static OptionStruct desc[] = +{ + {"-/+ammann", "turn on/off Ammann lines"} +}; + +ENTRYPOINT ModeSpecOpt penrose_opts = +{sizeof opts / sizeof opts[0], opts, sizeof vars / sizeof vars[0], vars, desc}; + +#ifdef USE_MODULES +ModStruct penrose_description = +{"penrose", "init_penrose", "draw_penrose", "release_penrose", + "init_penrose", "init_penrose", (char *) NULL, &penrose_opts, + 10000, 1, 1, -40, 64, 1.0, "", + "Shows Penrose's quasiperiodic tilings", 0, NULL}; + +#endif + +/*- + * Annoyingly the ANSI C library people have reserved all identifiers + * ending with _t for future use. Hence we use _c as a suffix for + * typedefs (c for class, although this is not C++). + */ + +#define MINSIZE 5 + +/*- + * In theory one could fit 10 tiles to a single vertex. However, the + * vertex rules only allow at most seven tiles to meet at a vertex. + */ + +#define CELEBRATE 31415 /* This causes a pause, an error occurred. */ +#define COMPLETION 3141 /* This causes a pause, tiles filled up screen. */ + +#define MAX_TILES_PER_VERTEX 7 +#define N_VERTEX_RULES 8 +#define ALLOC_NODE(type) (type *)malloc(sizeof (type)) + +/*- + * These are used to specify directions. They can also be used in bit + * masks to specify a combination of directions. + */ +#define S_LEFT 1 +#define S_RIGHT 2 + + +/*- + * We do not actually maintain objects corresponding to the tiles since + * we do not really need them and they would only consume memory and + * cause additional bookkeeping. Instead we only have vertices, and + * each vertex lists the type of each adjacent tile as well as the + * position of the vertex on the tile (hereafter refered to as + * "corner"). These positions are numbered in counterclockwise order + * so that 0 is where two double arrows meet (see one of the + * articles). The tile type and vertex number are stored in a single + * integer (we use char, and even most of it remains unused). + * + * The primary use of tile objects would be draw traversal, but we do + * not currently do redraws at all (we just start over). + */ +#define VT_CORNER_MASK 0x3 +#define VT_TYPE_MASK 0x4 +#define VT_THIN 0 +#define VT_THICK 0x4 +#define VT_BITS 3 +#define VT_TOTAL_MASK 0x7 + +typedef unsigned char vertex_type_c; + +/*- + * These allow one to compute the types of the other corners of the tile. If + * you are standing at a vertex of type vt looking towards the middle of the + * tile, VT_LEFT( vt) is the vertex on your left etc. + */ +#define VT_LEFT( vt) ((((vt) - 1) & VT_CORNER_MASK) | (((vt) & VT_TYPE_MASK))) +#define VT_RIGHT( vt) ((((vt) + 1) & VT_CORNER_MASK) | (((vt) & VT_TYPE_MASK))) +#define VT_FAR( vt) ((vt) ^ 2) + + +/*- + * Since we do not do redraws, we only store the vertices we need. These are + * the ones with still some empty space around them for the growth algorithm + * to fill. + * + * Here we use a doubly chained ring-like structure as vertices often need + * to be removed or inserted (they are kept in geometrical order + * circling the tiled area counterclockwise). The ring is refered to by + * a pointer to one more or less random node. When deleting nodes one + * must make sure that this pointer continues to refer to a valid + * node. A vertex count is maintained to make it easier to pick + * vertices randomly. + */ +typedef struct forced_node forced_node_c; + +typedef struct fringe_node { + struct fringe_node *prev; + struct fringe_node *next; + /* These are numbered counterclockwise. The gap, if any, lies + between the last and first tiles. */ + vertex_type_c tiles[MAX_TILES_PER_VERTEX]; + int n_tiles; + /* A bit mask used to indicate vertex rules that are still applicable for + completing this vertex. Initialize this to (1 << N_VERTEX_RULES) - 1, + i.e., all ones, and the rule matching functions will automatically mask + out rules that no longer match. */ + unsigned char rule_mask; + /* If the vertex is on the forced vertex list, this points to the + pointer to the appropriate node in the list. To remove the + vertex from the list just set *list_ptr to the next node, + deallocate and decrement node count. */ + struct forced_node **list_ptr; + /* Screen coordinates. */ + XPoint loc; + /* We also keep track of 5D coordinates to avoid rounding errors. + These are in units of edge length. */ + int fived[5]; + /* This is used to quickly check if a vertex is visible. */ + unsigned char off_screen; +} fringe_node_c; + +typedef struct { + fringe_node_c *nodes; + /* This does not count off-screen nodes. */ + int n_nodes; +} fringe_c; + + +/*- + * The forced vertex pool contains vertices where at least one + * side of the tiled region can only be extended in one way. Note + * that this does not necessarily mean that there would only be one + * applicable rule. forced_sides are specified using S_LEFT and + * S_RIGHT as if looking at the untiled region from the vertex. + */ +struct forced_node { + fringe_node_c *vertex; + unsigned forced_sides; + struct forced_node *next; +}; + +typedef struct { + forced_node_c *first; + int n_nodes, n_visible; +} forced_pool_c; + + +/* The tiles are listed in counterclockwise order. */ +typedef struct { + vertex_type_c tiles[MAX_TILES_PER_VERTEX]; + int n_tiles; +} vertex_rule_c; + +static vertex_rule_c vertex_rules[N_VERTEX_RULES] = +{ + { + {VT_THICK | 2, VT_THICK | 2, VT_THICK | 2, VT_THICK | 2, VT_THICK | 2}, 5}, + { + {VT_THICK | 0, VT_THICK | 0, VT_THICK | 0, VT_THICK | 0, VT_THICK | 0}, 5}, + { + {VT_THICK | 0, VT_THICK | 0, VT_THICK | 0, VT_THIN | 0}, 4}, + { + {VT_THICK | 2, VT_THICK | 2, VT_THIN | 1, VT_THIN | 3, VT_THICK | 2, + VT_THIN | 1, VT_THIN | 3}, 7}, + { + {VT_THICK | 2, VT_THICK | 2, VT_THICK | 2, VT_THICK | 2, + VT_THIN | 1, VT_THIN | 3}, 6}, + { + {VT_THICK | 1, VT_THICK | 3, VT_THIN | 2}, 3}, + { + {VT_THICK | 0, VT_THIN | 0, VT_THIN | 0}, 3}, + { + {VT_THICK | 2, VT_THIN | 1, VT_THICK | 3, VT_THICK | 1, VT_THIN | 3}, 5} +}; + + +/* Match information returned by match_rules. */ +typedef struct { + int rule; + int pos; +} rule_match_c; + + +/* Occasionally floating point coordinates are needed. */ +typedef struct { + float x, y; +} fcoord_c; + + +/* All angles are measured in multiples of 36 degrees. */ +typedef int angle_c; + +static angle_c vtype_angles[] = +{4, 1, 4, 1, 2, 3, 2, 3}; + +#define vtype_angle( v) (vtype_angles[ v]) + + +/* This is the data related to the tiling of one screen. */ +typedef struct { + int width, height; + XPoint origin; + int edge_length; + fringe_c fringe; + forced_pool_c forced; + int done, failures; + unsigned long thick_color, thin_color; + int busyLoop; + Bool ammann; + float ammann_r; + fcoord_c fived_table[5]; +} tiling_c; + +static tiling_c *tilings = (tiling_c *) NULL; + + + +/* Direction angle of an edge. */ +static angle_c +vertex_dir(ModeInfo * mi, fringe_node_c * vertex, unsigned side) +{ + tiling_c *tp = &tilings[MI_SCREEN(mi)]; + fringe_node_c *v2 = + (side == S_LEFT ? vertex->next : vertex->prev); + register int i; + + for (i = 0; i < 5; i++) + switch (v2->fived[i] - vertex->fived[i]) { + case 1: + return 2 * i; + case -1: + return (2 * i + 5) % 10; + } + tp->done = True; + if (MI_IS_VERBOSE(mi)) { + (void) fprintf(stderr, + "Weirdness in vertex_dir (this has been reported)\n"); + for (i = 0; i < 5; i++) + (void) fprintf(stderr, "v2->fived[%d]=%d, vertex->fived[%d]=%d\n", + i, v2->fived[i], i, vertex->fived[i]); + } + tp->busyLoop = CELEBRATE; + return 0; +} + + +/* Move one step to a given direction. */ +static void +add_unit_vec(angle_c dir, int *fived) +{ + static const int dir2i[] = {0, 3, 1, 4, 2}; + + while (dir < 0) + dir += 10; + fived[dir2i[dir % 5]] += (dir % 2 ? -1 : 1); +} + + +/* For comparing coordinates. */ +#define fived_equal( f1, f2) (!memcmp( (f1), (f2), 5 * sizeof( int))) + + +/*- + * This computes screen coordinates from 5D representation. Note that X + * uses left-handed coordinates (y increases downwards). + */ +static void +fived_to_loc(int fived[], tiling_c * tp, XPoint *pt) +{ + float fifth = 8 * atan(1.) / 5; + register int i; + register float r; + register fcoord_c offset; + + *pt = tp->origin; + offset.x = 0.0; + offset.y = 0.0; + if (tp->fived_table[0].x == .0) + for (i = 0; i < 5; i++) { + tp->fived_table[i].x = cos(fifth * i); + tp->fived_table[i].y = sin(fifth * i); + } + for (i = 0; i < 5; i++) { + r = fived[i] * tp->edge_length; + offset.x += r * tp->fived_table[i].x; + offset.y -= r * tp->fived_table[i].y; + } + (*pt).x += (int) (offset.x + .5); + (*pt).y += (int) (offset.y + .5); +} + + +/* Mop up dynamic data for one screen. */ +static void +free_penrose(tiling_c * tp) +{ + register fringe_node_c *fp1, *fp2; + register forced_node_c *lp1, *lp2; + + if (tp->fringe.nodes == NULL) + return; + fp1 = tp->fringe.nodes; + do { + fp2 = fp1; + fp1 = fp1->next; + (void) free((void *) fp2); + } while (fp1 != tp->fringe.nodes); + tp->fringe.nodes = (fringe_node_c *) NULL; + for (lp1 = tp->forced.first; lp1 != 0;) { + lp2 = lp1; + lp1 = lp1->next; + (void) free((void *) lp2); + } + tp->forced.first = 0; +} + + +/* Called to init the mode. */ +ENTRYPOINT void +init_penrose(ModeInfo * mi) +{ + tiling_c *tp; + fringe_node_c *fp; + int i, size; + + if (tilings == NULL) { + if ((tilings = (tiling_c *) calloc(MI_NUM_SCREENS(mi), + sizeof (tiling_c))) == NULL) + return; + } + tp = &tilings[MI_SCREEN(mi)]; + +#if 0 /* if you do this, then the -ammann and -no-ammann options don't work. + -- jwz */ + if (MI_IS_FULLRANDOM(mi)) + tp->ammann = (Bool) (LRAND() & 1); + else +#endif /* 0 */ + tp->ammann = ammann; + + tp->done = False; + tp->busyLoop = 0; + tp->failures = 0; + tp->width = MI_WIDTH(mi); + tp->height = MI_HEIGHT(mi); + if (MI_NPIXELS(mi) > 2) { + tp->thick_color = NRAND(MI_NPIXELS(mi)); + /* Insure good contrast */ + tp->thin_color = (NRAND(2 * MI_NPIXELS(mi) / 3) + tp->thick_color + + MI_NPIXELS(mi) / 6) % MI_NPIXELS(mi); + } + size = MI_SIZE(mi); + if (size < -MINSIZE) + tp->edge_length = NRAND(MIN(-size, MAX(MINSIZE, + MIN(tp->width, tp->height) / 2)) - MINSIZE + 1) + MINSIZE; + else if (size < MINSIZE) { + if (!size) + tp->edge_length = MAX(MINSIZE, MIN(tp->width, tp->height) / 2); + else + tp->edge_length = MINSIZE; + } else + tp->edge_length = MIN(size, MAX(MINSIZE, + MIN(tp->width, tp->height) / 2)); + tp->origin.x = (tp->width / 2 + NRAND(tp->width)) / 2; + tp->origin.y = (tp->height / 2 + NRAND(tp->height)) / 2; + tp->fringe.n_nodes = 2; + if (tp->fringe.nodes != NULL) + free_penrose(tp); + if (tp->fringe.nodes != NULL || tp->forced.first != 0) { + if (MI_IS_VERBOSE(mi)) { + (void) fprintf(stderr, "Weirdness in init_penrose()\n"); + (void) fprintf(stderr, "tp->fringe.nodes = NULL && tp->forced.first = 0\n"); + } + free_penrose(tp); /* Try again */ + tp->done = True; + } + tp->forced.n_nodes = tp->forced.n_visible = 0; + if ((fp = tp->fringe.nodes = ALLOC_NODE(fringe_node_c)) == NULL) { + free_penrose(tp); + return; + } + if (fp == 0) { + if (MI_IS_VERBOSE(mi)) { + (void) fprintf(stderr, "Weirdness in init_penrose()\n"); + (void) fprintf(stderr, "fp = 0\n"); + } + if ((fp = tp->fringe.nodes = ALLOC_NODE(fringe_node_c)) == NULL) { + free_penrose(tp); + return; + } + tp->done = True; + } + /* First vertex. */ + fp->rule_mask = (1 << N_VERTEX_RULES) - 1; + fp->list_ptr = 0; + if ((fp->prev = fp->next = ALLOC_NODE(fringe_node_c)) == NULL) { + free_penrose(tp); + return; + } + if (fp->next == 0) { + if (MI_IS_VERBOSE(mi)) { + (void) fprintf(stderr, "Weirdness in init_penrose()\n"); + (void) fprintf(stderr, "fp->next = 0\n"); + } + if ((fp->prev = fp->next = ALLOC_NODE(fringe_node_c)) == NULL) { + free_penrose(tp); + return; + } + tp->done = True; + } + fp->n_tiles = 0; + fp->loc = tp->origin; + fp->off_screen = False; + for (i = 0; i < 5; i++) + fp->fived[i] = 0; + + /* Second vertex. */ + *(fp->next) = *fp; + fp->next->prev = fp->next->next = fp; + fp = fp->next; + i = NRAND(5); + fp->fived[i] = 2 * NRAND(2) - 1; + fived_to_loc(fp->fived, tp, &(fp->loc)); + /* That's it! We have created our first edge. */ +} + +/*- + * This attempts to match the configuration of vertex with the vertex + * rules. The return value is a total match count. If matches is + * non-null, it will be used to store information about the matches + * and must be large enough to contain it. To play it absolutely + * safe, allocate room for MAX_TILES_PER_VERTEX * N_VERTEX_RULES + * entries when searching all matches. The rule mask of vertex will + * be applied and rules masked out will not be searched. Only strict + * subsequences match. If first_only is true, the search stops when + * the first match is found. Otherwise all matches will be found and + * the rule_mask of vertex will be updated, which also happens in + * single-match mode if no match is found. + */ +static int +match_rules(fringe_node_c * vertex, rule_match_c * matches, int first_only) +{ + /* I will assume that I can fit all the relevant bits in vertex->tiles + into one unsigned long. With 3 bits per element and at most 7 + elements this means 21 bits, which should leave plenty of room. + After packing the bits the rest is just integer comparisons and + some bit shuffling. This is essentially Rabin-Karp without + congruence arithmetic. */ + register int i, j; + int hits = 0, good_rules[N_VERTEX_RULES], n_good = 0; + unsigned long + vertex_hash = 0, lower_bits_mask = ~(VT_TOTAL_MASK << VT_BITS * (vertex->n_tiles - 1)); + unsigned new_rule_mask = 0; + + for (i = 0; i < N_VERTEX_RULES; i++) + if (vertex->n_tiles >= vertex_rules[i].n_tiles) + vertex->rule_mask &= ~(1 << i); + else if (vertex->rule_mask & 1 << i) + good_rules[n_good++] = i; + for (i = 0; i < vertex->n_tiles; i++) + vertex_hash |= (unsigned long) vertex->tiles[i] << (VT_BITS * i); + + for (j = 0; j < n_good; j++) { + unsigned long rule_hash = 0; + vertex_rule_c *vr = vertex_rules + good_rules[j]; + + for (i = 0; i < vertex->n_tiles; i++) + rule_hash |= (unsigned long) vr->tiles[i] << (VT_BITS * i); + if (rule_hash == vertex_hash) { + if (matches != 0) { + matches[hits].rule = good_rules[j]; + matches[hits].pos = 0; + } + hits++; + if (first_only) + return hits; + else + new_rule_mask |= 1 << good_rules[j]; + } + for (i = vr->n_tiles - 1; i > 0; i--) { + rule_hash = vr->tiles[i] | (rule_hash & lower_bits_mask) << VT_BITS; + if (vertex_hash == rule_hash) { + if (matches != 0) { + matches[hits].rule = good_rules[j]; + matches[hits].pos = i; + } + hits++; + if (first_only) + return hits; + else + new_rule_mask |= 1 << good_rules[j]; + } + } + } + vertex->rule_mask = new_rule_mask; + return hits; +} + + +/*- + * find_completions finds the possible ways to add a tile to a vertex. + * The return values is the number of such possibilities. You must + * first call match_rules to produce matches and n_matches. sides + * specifies which side of the vertex to extend and can be S_LEFT or + * S_RIGHT. If results is non-null, it should point to an array large + * enough to contain the results, which will be stored there. + * MAX_COMPL elements will always suffice. If first_only is true we + * stop as soon as we find one possibility (NOT USED). + */ +#define MAX_COMPL 2 + +static int +find_completions(fringe_node_c * vertex, rule_match_c * matches, int n_matches, + unsigned side, vertex_type_c * results /*, int first_only */ ) +{ + int n_res = 0, cont; + register int i, j; + vertex_type_c buf[MAX_COMPL]; + + if (results == 0) + results = buf; + if (n_matches <= 0) + return 0; + for (i = 0; i < n_matches; i++) { + vertex_rule_c *rule = vertex_rules + matches[i].rule; + int pos = (matches[i].pos + + (side == S_RIGHT ? vertex->n_tiles : rule->n_tiles - 1)) + % rule->n_tiles; + vertex_type_c vtype = rule->tiles[pos]; + + cont = 1; + for (j = 0; j < n_res; j++) + if (vtype == results[j]) { + cont = 0; + break; + } + if (cont) + results[n_res++] = vtype; + } + return n_res; +} + + +/*- + * Draw a tile on the display. Vertices must be given in a + * counterclockwise order. vtype is the vertex type of v1 (and thus + * also gives the tile type). + */ +static void +draw_tile(fringe_node_c * v1, fringe_node_c * v2, + fringe_node_c * v3, fringe_node_c * v4, + vertex_type_c vtype, ModeInfo * mi) +{ + Display *display = MI_DISPLAY(mi); + Window window = MI_WINDOW(mi); + GC gc = MI_GC(mi); + tiling_c *tp = &tilings[MI_SCREEN(mi)]; + XPoint pts[5]; + vertex_type_c corner = vtype & VT_CORNER_MASK; + + if (v1->off_screen && v2->off_screen && v3->off_screen && v4->off_screen) + return; + pts[corner] = v1->loc; + pts[VT_RIGHT(corner)] = v2->loc; + pts[VT_FAR(corner)] = v3->loc; + pts[VT_LEFT(corner)] = v4->loc; + pts[4] = pts[0]; + if (MI_NPIXELS(mi) > 2) { + if ((vtype & VT_TYPE_MASK) == VT_THICK) + XSetForeground(display, gc, MI_PIXEL(mi, tp->thick_color)); + else + XSetForeground(display, gc, MI_PIXEL(mi, tp->thin_color)); + } else + XSetForeground(display, gc, MI_WHITE_PIXEL(mi)); + XFillPolygon(display, window, gc, pts, 4, Convex, CoordModeOrigin); + XSetForeground(display, gc, MI_BLACK_PIXEL(mi)); + XDrawLines(display, window, gc, pts, 5, CoordModeOrigin); + + if (tp->ammann) { + /* Draw some Ammann lines for debugging purposes. This will probably + fail miserably on a b&w display. */ + + if ((vtype & VT_TYPE_MASK) == VT_THICK) { + + if (tp->ammann_r == .0) { + float pi10 = 2 * atan(1.) / 5; + + tp->ammann_r = 1 - sin(pi10) / (2 * sin(3 * pi10)); + } + if (MI_NPIXELS(mi) > 2) + XSetForeground(display, gc, MI_PIXEL(mi, tp->thin_color)); + else { + XSetForeground(display, gc, MI_BLACK_PIXEL(mi)); + XSetLineAttributes(display, gc, 1, LineOnOffDash, CapNotLast, JoinMiter); + } + XDrawLine(display, window, gc, + (int) (tp->ammann_r * pts[3].x + (1 - tp->ammann_r) * pts[0].x + .5), + (int) (tp->ammann_r * pts[3].y + (1 - tp->ammann_r) * pts[0].y + .5), + (int) (tp->ammann_r * pts[1].x + (1 - tp->ammann_r) * pts[0].x + .5), + (int) (tp->ammann_r * pts[1].y + (1 - tp->ammann_r) * pts[0].y + .5)); + if (MI_NPIXELS(mi) <= 2) + XSetLineAttributes(display, gc, 1, LineSolid, CapNotLast, JoinMiter); + } else { + if (MI_NPIXELS(mi) > 2) + XSetForeground(display, gc, MI_PIXEL(mi, tp->thick_color)); + else { + XSetForeground(display, gc, MI_BLACK_PIXEL(mi)); + XSetLineAttributes(display, gc, 1, LineOnOffDash, CapNotLast, JoinMiter); + } + XDrawLine(display, window, gc, + (int) ((pts[3].x + pts[2].x) / 2 + .5), + (int) ((pts[3].y + pts[2].y) / 2 + .5), + (int) ((pts[1].x + pts[2].x) / 2 + .5), + (int) ((pts[1].y + pts[2].y) / 2 + .5)); + if (MI_NPIXELS(mi) <= 2) + XSetLineAttributes(display, gc, 1, LineSolid, CapNotLast, JoinMiter); + } + } +} + +/*- + * Update the status of this vertex on the forced vertex queue. If + * the vertex has become untileable set tp->done. This is supposed + * to detect dislocations -- never call this routine with a completely + * tiled vertex. + * + * Check for untileable vertices in check_vertex and stop tiling as + * soon as one finds one. I don't know if it is possible to run out + * of forced vertices while untileable vertices exist (or will + * cavities inevitably appear). If this can happen, add_random_tile + * might get called with an untileable vertex, causing ( n <= 1). + * (This is what the tp->done checks for). + * + * A delayLoop celebrates the dislocation. + */ +static void +check_vertex(ModeInfo * mi, fringe_node_c * vertex, tiling_c * tp) +{ + rule_match_c hits[MAX_TILES_PER_VERTEX * N_VERTEX_RULES]; + int n_hits = match_rules(vertex, hits, False); + unsigned forced_sides = 0; + + if (vertex->rule_mask == 0) { + tp->done = True; + if (MI_IS_VERBOSE(mi)) { + (void) fprintf(stderr, "Dislocation occurred!\n"); + } + tp->busyLoop = CELEBRATE; /* Should be able to recover */ + } + if (1 == find_completions(vertex, hits, n_hits, S_LEFT, 0 /*, False */ )) + forced_sides |= S_LEFT; + if (1 == find_completions(vertex, hits, n_hits, S_RIGHT, 0 /*, False */ )) + forced_sides |= S_RIGHT; + if (forced_sides == 0) { + if (vertex->list_ptr != 0) { + forced_node_c *node = *vertex->list_ptr; + + *vertex->list_ptr = node->next; + if (node->next != 0) + node->next->vertex->list_ptr = vertex->list_ptr; + (void) free((void *) node); + tp->forced.n_nodes--; + if (!vertex->off_screen) + tp->forced.n_visible--; + vertex->list_ptr = 0; + } + } else { + forced_node_c *node; + + if (vertex->list_ptr == 0) { + if ((node = ALLOC_NODE(forced_node_c)) == NULL) + return; + node->vertex = vertex; + node->next = tp->forced.first; + if (tp->forced.first != 0) + tp->forced.first->vertex->list_ptr = &(node->next); + tp->forced.first = node; + vertex->list_ptr = &(tp->forced.first); + tp->forced.n_nodes++; + if (!vertex->off_screen) + tp->forced.n_visible++; + } else + node = *vertex->list_ptr; + node->forced_sides = forced_sides; + } +} + + +/*- + * Delete this vertex. If the vertex is a member of the forced vertex queue, + * also remove that entry. We assume that the vertex is no longer + * connected to the fringe. Note that tp->fringe.nodes must not point to + * the vertex being deleted. + */ +static void +delete_vertex(ModeInfo * mi, fringe_node_c * vertex, tiling_c * tp) +{ + if (tp->fringe.nodes == vertex) { + tp->done = True; + if (MI_IS_VERBOSE(mi)) { + (void) fprintf(stderr, "Weirdness in delete_penrose()\n"); + (void) fprintf(stderr, "tp->fringe.nodes == vertex\n"); + } + tp->busyLoop = CELEBRATE; + } + if (vertex->list_ptr != 0) { + forced_node_c *node = *vertex->list_ptr; + + *vertex->list_ptr = node->next; + if (node->next != 0) + node->next->vertex->list_ptr = vertex->list_ptr; + (void) free((void *) node); + tp->forced.n_nodes--; + if (!vertex->off_screen) + tp->forced.n_visible--; + } + if (!vertex->off_screen) + tp->fringe.n_nodes--; + (void) free((void *) vertex); +} + + +/*- + * Check whether the addition of a tile of type vtype would completely fill + * the space available at vertex. + */ +static int +fills_vertex(ModeInfo * mi, vertex_type_c vtype, fringe_node_c * vertex) +{ + return + (vertex_dir(mi, vertex, S_LEFT) - vertex_dir(mi, vertex, S_RIGHT) + - vtype_angle(vtype)) % 10 == 0; +} + + +/*- + * If you were to add a tile of type vtype to a specified side of + * vertex, fringe_changes tells you which other vertices it would + * attach to. The addresses of these vertices will be stored in the + * last three arguments. Null is stored if the corresponding vertex + * would need to be allocated. + * + * The function also analyzes which vertices would be swallowed by the tiling + * and thus cut off from the fringe. The result is returned as a bit pattern. + */ +#define FC_BAG 1 /* Total enclosure. Should never occur. */ +#define FC_NEW_RIGHT 2 +#define FC_NEW_FAR 4 +#define FC_NEW_LEFT 8 +#define FC_NEW_MASK 0xe +#define FC_CUT_THIS 0x10 +#define FC_CUT_RIGHT 0x20 +#define FC_CUT_FAR 0x40 +#define FC_CUT_LEFT 0x80 +#define FC_CUT_MASK 0xf0 +#define FC_TOTAL_MASK 0xff + +static unsigned +fringe_changes(ModeInfo * mi, fringe_node_c * vertex, + unsigned side, vertex_type_c vtype, + fringe_node_c ** right, fringe_node_c ** far, + fringe_node_c ** left) +{ + fringe_node_c *v, *f = (fringe_node_c *) NULL; + unsigned result = FC_NEW_FAR; /* We clear this later if necessary. */ + + if (far) + *far = 0; + if (fills_vertex(mi, vtype, vertex)) { + result |= FC_CUT_THIS; + } else if (side == S_LEFT) { + result |= FC_NEW_RIGHT; + if (right) + *right = 0; + } else { + result |= FC_NEW_LEFT; + if (left) + *left = 0; + } + + if (!(result & FC_NEW_LEFT)) { + v = vertex->next; + if (left) + *left = v; + if (fills_vertex(mi, VT_LEFT(vtype), v)) { + result = (result & ~FC_NEW_FAR) | FC_CUT_LEFT; + f = v->next; + if (far) + *far = f; + } + } + if (!(result & FC_NEW_RIGHT)) { + v = vertex->prev; + if (right) + *right = v; + if (fills_vertex(mi, VT_RIGHT(vtype), v)) { + result = (result & ~FC_NEW_FAR) | FC_CUT_RIGHT; + f = v->prev; + if (far) + *far = f; + } + } + if (!(result & FC_NEW_FAR) + && fills_vertex(mi, VT_FAR(vtype), f)) { + result |= FC_CUT_FAR; + result &= (~FC_NEW_LEFT & ~FC_NEW_RIGHT); + if (right && (result & FC_CUT_LEFT)) + *right = f->next; + if (left && (result & FC_CUT_RIGHT)) + *left = f->prev; + } + if (((result & FC_CUT_LEFT) && (result & FC_CUT_RIGHT)) + || ((result & FC_CUT_THIS) && (result & FC_CUT_FAR))) + result |= FC_BAG; + return result; +} + + +/* A couple of lesser helper functions for add_tile. */ +static void +add_vtype(fringe_node_c * vertex, unsigned side, vertex_type_c vtype) +{ + if (side == S_RIGHT) + vertex->tiles[vertex->n_tiles++] = vtype; + else { + register int i; + + for (i = vertex->n_tiles; i > 0; i--) + vertex->tiles[i] = vertex->tiles[i - 1]; + vertex->tiles[0] = vtype; + vertex->n_tiles++; + } +} + +static fringe_node_c * +alloc_vertex(ModeInfo * mi, angle_c dir, fringe_node_c * from, tiling_c * tp) +{ + fringe_node_c *v; + + if ((v = ALLOC_NODE(fringe_node_c)) == NULL) { + tp->done = True; + if (MI_IS_VERBOSE(mi)) { + (void) fprintf(stderr, "No memory in alloc_vertex()\n"); + } + tp->busyLoop = CELEBRATE; + return v; + } + *v = *from; + add_unit_vec(dir, v->fived); + fived_to_loc(v->fived, tp, &(v->loc)); + if (v->loc.x < 0 || v->loc.y < 0 + || v->loc.x >= tp->width || v->loc.y >= tp->height) { + v->off_screen = True; + if (v->loc.x < -tp->width || v->loc.y < -tp->height + || v->loc.x >= 2 * tp->width || v->loc.y >= 2 * tp->height) + tp->done = True; + } else { + v->off_screen = False; + tp->fringe.n_nodes++; + } + v->n_tiles = 0; + v->rule_mask = (1 << N_VERTEX_RULES) - 1; + v->list_ptr = 0; + return v; +} + +/*- + * Add a tile described by vtype to the side of vertex. This must be + * allowed by the rules -- we do not check it here. New vertices are + * allocated as necessary. The fringe and the forced vertex pool are updated. + * The new tile is drawn on the display. + * + * One thing we do check here is whether the new tile causes an untiled + * area to become enclosed by the tiling. If this would happen, the tile + * is not added. The return value is true iff a tile was added. + */ +static int +add_tile(ModeInfo * mi, + fringe_node_c * vertex, unsigned side, vertex_type_c vtype) +{ + tiling_c *tp = &tilings[MI_SCREEN(mi)]; + + fringe_node_c + *left = (fringe_node_c *) NULL, + *right = (fringe_node_c *) NULL, + *far = (fringe_node_c *) NULL, + *node; + unsigned fc = fringe_changes(mi, vertex, side, vtype, &right, &far, &left); + + vertex_type_c + ltype = VT_LEFT(vtype), + rtype = VT_RIGHT(vtype), + ftype = VT_FAR(vtype); + + /* By our conventions vertex->next lies to the left of vertex and + vertex->prev to the right. */ + + /* This should never occur. */ + if (fc & FC_BAG) { + tp->done = True; + if (MI_IS_VERBOSE(mi)) { + (void) fprintf(stderr, "Weirdness in add_tile()\n"); + (void) fprintf(stderr, "fc = %d, FC_BAG = %d\n", fc, FC_BAG); + } + } + if (side == S_LEFT) { + if (right == NULL) + if ((right = alloc_vertex(mi, vertex_dir(mi, vertex, S_LEFT) - + vtype_angle(vtype), vertex, tp)) == NULL) + return False; + if (far == NULL) + if ((far = alloc_vertex(mi, vertex_dir(mi, left, S_RIGHT) + + vtype_angle(ltype), left, tp)) == NULL) + return False; + } else { + if (left == NULL) + if ((left = alloc_vertex(mi, vertex_dir(mi, vertex, S_RIGHT) + + vtype_angle(vtype), vertex, tp)) == NULL) + return False; + if (far == NULL) + if ((far = alloc_vertex(mi, vertex_dir(mi, right, S_LEFT) - + vtype_angle(rtype), right, tp)) == NULL) + return False; + } + + /* Having allocated the new vertices, but before joining them with + the rest of the fringe, check if vertices with same coordinates + already exist. If any such are found, give up. */ + node = tp->fringe.nodes; + do { + if (((fc & FC_NEW_LEFT) && fived_equal(node->fived, left->fived)) + || ((fc & FC_NEW_RIGHT) && fived_equal(node->fived, right->fived)) + || ((fc & FC_NEW_FAR) && fived_equal(node->fived, far->fived))) { + /* Better luck next time. */ + if (fc & FC_NEW_LEFT) + delete_vertex(mi, left, tp); + if (fc & FC_NEW_RIGHT) + delete_vertex(mi, right, tp); + if (fc & FC_NEW_FAR) + delete_vertex(mi, far, tp); + return False; + } + node = node->next; + } while (node != tp->fringe.nodes); + + /* Rechain. */ + if (!(fc & FC_CUT_THIS)) { + if (side == S_LEFT) { + vertex->next = right; + right->prev = vertex; + } else { + vertex->prev = left; + left->next = vertex; + } + } + if (!(fc & FC_CUT_FAR)) { + if (!(fc & FC_CUT_LEFT)) { + far->next = left; + left->prev = far; + } + if (!(fc & FC_CUT_RIGHT)) { + far->prev = right; + right->next = far; + } + } + draw_tile(vertex, right, far, left, vtype, mi); + + /* Delete vertices that are no longer on the fringe. Check the others. */ + if (fc & FC_CUT_THIS) { + tp->fringe.nodes = far; + delete_vertex(mi, vertex, tp); + } else { + add_vtype(vertex, side, vtype); + check_vertex(mi, vertex, tp); + tp->fringe.nodes = vertex; + } + if (fc & FC_CUT_FAR) + delete_vertex(mi, far, tp); + else { + add_vtype(far, fc & FC_CUT_RIGHT ? S_LEFT : S_RIGHT, ftype); + check_vertex(mi, far, tp); + } + if (fc & FC_CUT_LEFT) + delete_vertex(mi, left, tp); + else { + add_vtype(left, fc & FC_CUT_FAR ? S_LEFT : S_RIGHT, ltype); + check_vertex(mi, left, tp); + } + if (fc & FC_CUT_RIGHT) + delete_vertex(mi, right, tp); + else { + add_vtype(right, fc & FC_CUT_FAR ? S_RIGHT : S_LEFT, rtype); + check_vertex(mi, right, tp); + } + return True; +} + + +/*- + * Add a forced tile to a given forced vertex. Basically an easy job, + * since we know what to add. But it might fail if adding the tile + * would cause some untiled area to become enclosed. There is also another + * more exotic culprit: we might have a dislocation. Fortunately, they + * are very rare (the PRL article reported that perfect tilings of over + * 2^50 tiles had been generated). There is a version of the algorithm + * that doesn't produce dislocations, but it's a lot hairier than the + * simpler version I used. + */ +static int +add_forced_tile(ModeInfo * mi, forced_node_c * node) +{ + tiling_c *tp = &tilings[MI_SCREEN(mi)]; + unsigned side; + vertex_type_c vtype; + rule_match_c hits[MAX_TILES_PER_VERTEX * N_VERTEX_RULES]; + int n; + + if (node->forced_sides == (S_LEFT | S_RIGHT)) + side = NRAND(2) ? S_LEFT : S_RIGHT; + else + side = node->forced_sides; + n = match_rules(node->vertex, hits, True); + n = find_completions(node->vertex, hits, n, side, &vtype /*, True */ ); + if (n <= 0) { + tp->done = True; + if (MI_IS_VERBOSE(mi)) { + (void) fprintf(stderr, "Weirdness in add_forced_tile()\n"); + (void) fprintf(stderr, "n = %d\n", n); + } + } + return add_tile(mi, node->vertex, side, vtype); +} + + +/*- + * Whether the addition of a tile of vtype on the given side of vertex + * would conform to the rules. The efficient way to do this would be + * to add the new tile and then use the same type of search as in + * match_rules. However, this function is not a performance + * bottleneck (only needed for random tile additions, which are + * relatively infrequent), so I will settle for a simpler implementation. + */ +static int +legal_move(fringe_node_c * vertex, unsigned side, vertex_type_c vtype) +{ + rule_match_c hits[MAX_TILES_PER_VERTEX * N_VERTEX_RULES]; + vertex_type_c legal_vt[MAX_COMPL]; + int n_hits, n_legal, i; + + n_hits = match_rules(vertex, hits, False); + n_legal = find_completions(vertex, hits, n_hits, side, legal_vt /*, False */ ); + for (i = 0; i < n_legal; i++) + if (legal_vt[i] == vtype) + return True; + return False; +} + + +/*- + * Add a randomly chosen tile to a given vertex. This requires more checking + * as we must make sure the new tile conforms to the vertex rules at every + * vertex it touches. */ +static void +add_random_tile(fringe_node_c * vertex, ModeInfo * mi) +{ + fringe_node_c *right, *left, *far; + int i, j, n, n_hits, n_good; + unsigned side, fc, no_good, s; + vertex_type_c vtypes[MAX_COMPL]; + rule_match_c hits[MAX_TILES_PER_VERTEX * N_VERTEX_RULES]; + tiling_c *tp = &tilings[MI_SCREEN(mi)]; + + if (MI_NPIXELS(mi) > 2) { + tp->thick_color = NRAND(MI_NPIXELS(mi)); + /* Insure good contrast */ + tp->thin_color = (NRAND(2 * MI_NPIXELS(mi) / 3) + tp->thick_color + + MI_NPIXELS(mi) / 6) % MI_NPIXELS(mi); + } else + tp->thick_color = tp->thin_color = MI_WHITE_PIXEL(mi); + n_hits = match_rules(vertex, hits, False); + side = NRAND(2) ? S_LEFT : S_RIGHT; + n = find_completions(vertex, hits, n_hits, side, vtypes /*, False */ ); + /* One answer would mean a forced tile. */ + if (n <= 0) { + tp->done = True; + if (MI_IS_VERBOSE(mi)) { + (void) fprintf(stderr, "Weirdness in add_random_tile()\n"); + (void) fprintf(stderr, "n = %d\n", n); + } + } + no_good = 0; + n_good = n; + for (i = 0; i < n; i++) { + fc = fringe_changes(mi, vertex, side, vtypes[i], &right, &far, &left); + if (fc & FC_BAG) { + tp->done = True; + if (MI_IS_VERBOSE(mi)) { + (void) fprintf(stderr, "Weirdness in add_random_tile()\n"); + (void) fprintf(stderr, "fc = %d, FC_BAG = %d\n", fc, FC_BAG); + } + } + if (right) { + s = (((fc & FC_CUT_FAR) && (fc & FC_CUT_LEFT)) ? S_RIGHT : S_LEFT); + if (!legal_move(right, s, VT_RIGHT(vtypes[i]))) { + no_good |= (1 << i); + n_good--; + continue; + } + } + if (left) { + s = (((fc & FC_CUT_FAR) && (fc & FC_CUT_RIGHT)) ? S_LEFT : S_RIGHT); + if (!legal_move(left, s, VT_LEFT(vtypes[i]))) { + no_good |= (1 << i); + n_good--; + continue; + } + } + if (far) { + s = ((fc & FC_CUT_LEFT) ? S_RIGHT : S_LEFT); + if (!legal_move(far, s, VT_FAR(vtypes[i]))) { + no_good |= (1 << i); + n_good--; + } + } + } + if (n_good <= 0) { + tp->done = True; + if (MI_IS_VERBOSE(mi)) { + (void) fprintf(stderr, "Weirdness in add_random_tile()\n"); + (void) fprintf(stderr, "n_good = %d\n", n_good); + } + } + n = NRAND(n_good); + for (i = j = 0; i <= n; i++, j++) + while (no_good & (1 << j)) + j++; + + if (!add_tile(mi, vertex, side, vtypes[j - 1])) { + tp->done = True; + if (MI_IS_VERBOSE(mi)) { + (void) fprintf(stderr, "Weirdness in add_random_tile()\n"); + } + free_penrose(tp); + } +} + +/* One step of the growth algorithm. */ +ENTRYPOINT void +draw_penrose(ModeInfo * mi) +{ + int i = 0, n; + forced_node_c *p; + tiling_c *tp; + + if (tilings == NULL) + return; + tp = &tilings[MI_SCREEN(mi)]; + if (tp->fringe.nodes == NULL) + return; + + MI_IS_DRAWN(mi) = True; + p = tp->forced.first; + if (tp->busyLoop > 0) { + tp->busyLoop--; + return; + } + if (tp->done || tp->failures >= 100) { + init_penrose(mi); + return; + } + /* Check for the initial "2-gon". */ + if (tp->fringe.nodes->prev == tp->fringe.nodes->next) { + vertex_type_c vtype = (unsigned char) (VT_TOTAL_MASK & LRAND()); + + MI_CLEARWINDOW(mi); + + if (!add_tile(mi, tp->fringe.nodes, S_LEFT, vtype)) + free_penrose(tp); + return; + } + /* No visible nodes left. */ + if (tp->fringe.n_nodes == 0) { + tp->done = True; + tp->busyLoop = COMPLETION; /* Just finished drawing */ + return; + } + if (tp->forced.n_visible > 0 && tp->failures < 10) { + n = NRAND(tp->forced.n_visible); + for (;;) { + while (p->vertex->off_screen) + p = p->next; + if (i++ < n) + p = p->next; + else + break; + } + } else if (tp->forced.n_nodes > 0) { + n = NRAND(tp->forced.n_nodes); + while (i++ < n) + p = p->next; + } else { + fringe_node_c *fringe_p = tp->fringe.nodes; + + n = NRAND(tp->fringe.n_nodes); + i = 0; + for (; i <= n; i++) + do { + fringe_p = fringe_p->next; + } while (fringe_p->off_screen); + add_random_tile(fringe_p, mi); + tp->failures = 0; + return; + } + if (add_forced_tile(mi, p)) + tp->failures = 0; + else + tp->failures++; +} + + +ENTRYPOINT void +reshape_penrose(ModeInfo * mi, int width, int height) +{ + tiling_c *tp = &tilings[MI_SCREEN(mi)]; + tp->width = width; + tp->height = height; +} + +/* Total clean-up. */ +ENTRYPOINT void +release_penrose(ModeInfo * mi) +{ + if (tilings != NULL) { + int screen; + + for (screen = 0; screen < MI_NUM_SCREENS(mi); screen++) + free_penrose(&tilings[screen]); + (void) free((void *) tilings); + tilings = (tiling_c *) NULL; + } +} + +XSCREENSAVER_MODULE ("Penrose", penrose) + +#endif /* MODE_penrose */ diff --git a/hacks/penrose.man b/hacks/penrose.man new file mode 100644 index 00000000..8c6d4ee4 --- /dev/null +++ b/hacks/penrose.man @@ -0,0 +1,106 @@ +.TH XScreenSaver 1 "10-May-97" "X Version 11" +.SH NAME +penrose - draws quasiperiodic tilings +.SH SYNOPSIS +.B penrose +[\-display \fIhost:display.screen\fP] [\-foreground \fIcolor\fP] [\-background \fIcolor\fP] [\-window] [\-root] [\-mono] [\-install] [\-visual \fIvisual\fP] [\-ncolors \fIinteger\fP] [\-delay \fImicroseconds\fP] [\-size \fIinteger\fP] [\-ammann] [\-no\-ammann] + +[\-fps] +.SH DESCRIPTION +The \fIpenrose\fP program draws quasiperiodic tilings. + +See Onoda, Steinhardt, DiVincenzo and Socolar in +Phys. Rev. Lett. 60, #25, 1988 or +Strandburg in Computers in Physics, Sep/Oct 1991. + +This implementation uses the simpler version of the growth +algorithm, i.e., if there are no forced vertices, a randomly chosen +tile is added to a randomly chosen vertex (no preference for those +108 degree angles). + +There are two essential differences to the algorithm presented in +the literature: First, we do not allow the tiling to enclose an +untiled area. Whenever this is in danger of happening, we just +do not add the tile, hoping for a better random choice the next +time. Second, when choosing a vertex randomly, we will take +one that lies withing the viewport if available. If this seems to +cause enclosures in the forced rule case, we will allow invisible +vertices to be chosen. + +Tiling is restarted whenever one of the following happens: there +are no incomplete vertices within the viewport or the tiling has +extended a window's length beyond the edge of the window +horizontally or vertically or forced rule choice has failed 100 +times due to areas about to become enclosed. + +Although quasiperiodic tilings are produced, the tiles themselves are +not penrose tiles (darts and kites). In contrast to penrose tiles, +these tiles can be arranged to form a periodic tiling. + +.SH OPTIONS +.I penrose +accepts the following options: +.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 \-mono +If on a color display, pretend we're on a monochrome display. +.TP 8 +.B \-install +Install a private colormap for the window. +.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 \-ncolors \fIinteger\fP +How many colors should be used (if possible). Default 64. +The colors are chosen randomly. +.TP 8 +.B \-size \fIinteger\fP +How big the tiles should be. Default 40 pixels. + +.TP 8 +.B \-delay \fImilliseconds\fP +How long (in 1/1,000,000'ths of a second) to wait between drawing each +tile. Default 10,000 or .01 seconds. + +.TP 8 +.B \-ammann +.TP 8 +.B \-no\-ammann +Whether Ammann lines should be added. + +.TP 8 +.B \-fps +Display the current frame rate and CPU load. +.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), +.BR xlock (1) +.SH COPYRIGHT +Copyright \(co 1996 by Timo Korvola. + +Permission to use, copy, modify, and distribute this software and its +documentation for any purpose and without fee is hereby granted, +provided that the above copyright notice appear in all copies and that +both that copyright notice and this permission notice appear in +supporting documentation. +.SH AUTHOR +Timo Korvola , 1996. + +Ability to run standalone or with \fIxscreensaver\fP added by +Jamie Zawinski , 10-May-97. diff --git a/hacks/petri.c b/hacks/petri.c new file mode 100644 index 00000000..860d0349 --- /dev/null +++ b/hacks/petri.c @@ -0,0 +1,758 @@ +/* petri, simulate mold in a petri dish. v2.7 + * by Dan Bornstein, danfuzz@milk.com + * with help from Jamie Zawinski, jwz@jwz.org + * Copyright (c) 1992-1999 Dan Bornstein. + * + * 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. + * + * + * Brief description of options/resources: + * + * delay: the delay in microseconds between iterations + * size: the size of a cell in pixels + * count: the number of different kinds of mold (minimum: 2) + * diaglim: the age limit for diagonal growth as a multiplier of orthogonal + * growth (minimum: 1, maximum 2). 1 means square growth, 1.414 + * (i.e., sqrt(2)) means approximately circular growth, 2 means diamond + * growth. + * anychan: the chance (fraction, between 0 and 1) that at each iteration, + * any new cell will be born + * minorchan: the chance (fraction, between 0 and 1) that, given that new + * cells will be added, that only two will be added (a minor cell birth + * event) + * instantdeathchan: the chance (fraction, between 0 and 1) that, given + * that death and destruction will happen, that instead of using plague + * cells, death will be instantaneous + * minlifespan: the minimum lifespan of a colony (before black death ensues) + * maxlifespan: the maximum lifespan of a colony (before black death ensues) + * minlifespeed: the minimum speed for living cells as a fraction of the + * maximum possible speed (fraction, between 0 and 1) + * maxlifespeed: the maximum speed for living cells as a fraction of the + * maximum possible speed (fraction, between 0 and 1) + * mindeathspeed: the minimum speed for black death cells as a fraction of the + * maximum possible speed (fraction, between 0 and 1) + * maxdeathspeed: the maximum speed for black death cells as a fraction of the + * maximum possible speed (fraction, between 0 and 1) + * originalcolors: if true, count must be 8 or less and the colors are a + * fixed set of primary and secondary colors (the artist's original choices) + * + * Interesting settings: + * + * petri -originalcolors -size 8 + * petri -size 2 + * petri -size 8 -diaglim 1.8 + * petri -diaglim 1.1 + * + * petri -count 4 -anychan 0.01 -minorchan 1 \ + * -minlifespan 2000 -maxlifespan 5000 + * + * petri -count 3 -anychan 1 -minlifespan 100000 \ + * -instantdeathchan 0 + * + * petri -minlifespeed 0.02 -maxlifespeed 0.03 -minlifespan 1 \ + * -maxlifespan 1 -instantdeathchan 0 -minorchan 0 \ + * -anychan 0.3 -delay 4000 + */ + +#include +#include "screenhack.h" +#include "spline.h" + +#define FLOAT float +#define RAND_FLOAT (((FLOAT) (random() & 0xffff)) / ((FLOAT) 0x10000)) + +typedef struct cell_s +{ + unsigned char col; /* 0 */ + unsigned char isnext; /* 1 */ + unsigned char nextcol; /* 2 */ + /* 3 */ + struct cell_s *next; /* 4 */ + struct cell_s *prev; /* 8 - */ + FLOAT speed; /* 12 */ + FLOAT growth; /* 16 20 - */ + FLOAT nextspeed; /* 20 28 */ + /* 24 36 - */ +} cell; + +struct state { + Display *dpy; + Window window; + + int arr_width; + int arr_height; + int count; + + cell *arr; + cell *head; + cell *tail; + int blastcount; + + GC *coloredGCs; + + int windowWidth; + int windowHeight; + int xOffset; + int yOffset; + int xSize; + int ySize; + + FLOAT orthlim; + FLOAT diaglim; + FLOAT anychan; + FLOAT minorchan; + FLOAT instantdeathchan; + int minlifespan; + int maxlifespan; + FLOAT minlifespeed; + FLOAT maxlifespeed; + FLOAT mindeathspeed; + FLOAT maxdeathspeed; + Bool originalcolors; + + int warned; + int delay; +}; + + +#define cell_x(c) (st->arr_width ? ((c) - st->arr) % st->arr_width : 0) +#define cell_y(c) (st->arr_width ? ((c) - st->arr) / st->arr_width : 0) + + +static int random_life_value (struct state *st) +{ + return (int) ((RAND_FLOAT * (st->maxlifespan - st->minlifespan)) + st->minlifespan); +} + +static void setup_random_colormap (struct state *st, XWindowAttributes *xgwa) +{ + XGCValues gcv; + int lose = 0; + int ncolors = st->count - 1; + int n; + XColor *colors = (XColor *) calloc (sizeof(*colors), st->count*2); + + colors[0].pixel = get_pixel_resource (st->dpy, xgwa->colormap, + "background", "Background"); + + make_random_colormap (st->dpy, xgwa->visual, xgwa->colormap, + colors+1, &ncolors, True, True, 0, True); + if (ncolors < 1) + { + fprintf (stderr, "%s: couldn't allocate any colors\n", progname); + exit (-1); + } + + ncolors++; + st->count = ncolors; + + memcpy (colors + st->count, colors, st->count * sizeof(*colors)); + colors[st->count].pixel = get_pixel_resource (st->dpy, xgwa->colormap, + "foreground", "Foreground"); + + for (n = 1; n < st->count; n++) + { + int m = n + st->count; + colors[n].red = colors[m].red / 2; + colors[n].green = colors[m].green / 2; + colors[n].blue = colors[m].blue / 2; + + if (!XAllocColor (st->dpy, xgwa->colormap, &colors[n])) + { + lose++; + colors[n] = colors[m]; + } + } + + if (lose) + { + fprintf (stderr, + "%s: unable to allocate %d half-intensity colors.\n", + progname, lose); + } + + for (n = 0; n < st->count*2; n++) + { + gcv.foreground = colors[n].pixel; + st->coloredGCs[n] = XCreateGC (st->dpy, st->window, GCForeground, &gcv); + } + + free (colors); +} + +static void setup_original_colormap (struct state *st, XWindowAttributes *xgwa) +{ + XGCValues gcv; + int lose = 0; + int n; + XColor *colors = (XColor *) calloc (sizeof(*colors), st->count*2); + + colors[0].pixel = get_pixel_resource (st->dpy, xgwa->colormap, + "background", "Background"); + + colors[st->count].pixel = get_pixel_resource (st->dpy, xgwa->colormap, + "foreground", "Foreground"); + + for (n = 1; n < st->count; n++) + { + int m = n + st->count; + colors[n].red = ((n & 0x01) != 0) * 0x8000; + colors[n].green = ((n & 0x02) != 0) * 0x8000; + colors[n].blue = ((n & 0x04) != 0) * 0x8000; + + if (!XAllocColor (st->dpy, xgwa->colormap, &colors[n])) + { + lose++; + colors[n] = colors[0]; + } + + colors[m].red = colors[n].red + 0x4000; + colors[m].green = colors[n].green + 0x4000; + colors[m].blue = colors[n].blue + 0x4000; + + if (!XAllocColor (st->dpy, xgwa->colormap, &colors[m])) + { + lose++; + colors[m] = colors[st->count]; + } + } + + if (lose) + { + fprintf (stderr, + "%s: unable to allocate %d colors.\n", + progname, lose); + } + + for (n = 0; n < st->count*2; n++) + { + gcv.foreground = colors[n].pixel; + st->coloredGCs[n] = XCreateGC (st->dpy, st->window, GCForeground, &gcv); + } + + free (colors); +} + +static void +setup_display (struct state *st) +{ + XWindowAttributes xgwa; + + int cell_size = get_integer_resource (st->dpy, "size", "Integer"); + int osize, alloc_size, oalloc; + int mem_throttle = 0; + char *s; + + if (cell_size < 1) cell_size = 1; + + osize = cell_size; + + s = get_string_resource (st->dpy, "memThrottle", "MemThrottle"); + if (s) + { + int n; + char c; + if (1 == sscanf (s, " %d M %c", &n, &c) || + 1 == sscanf (s, " %d m %c", &n, &c)) + mem_throttle = n * (1 << 20); + else if (1 == sscanf (s, " %d K %c", &n, &c) || + 1 == sscanf (s, " %d k %c", &n, &c)) + mem_throttle = n * (1 << 10); + else if (1 == sscanf (s, " %d %c", &n, &c)) + mem_throttle = n; + else + { + fprintf (stderr, "%s: invalid memThrottle \"%s\" (try \"10M\")\n", + progname, s); + exit (1); + } + + free (s); + } + + XGetWindowAttributes (st->dpy, st->window, &xgwa); + + st->originalcolors = get_boolean_resource (st->dpy, "originalcolors", "Boolean"); + + st->count = get_integer_resource (st->dpy, "count", "Integer"); + if (st->count < 2) st->count = 2; + + /* number of colors can't be greater than the half depth of the screen. */ + if (st->count > (unsigned int) (1L << (xgwa.depth-1))) + st->count = (unsigned int) (1L << (xgwa.depth-1)); + + /* Actually, since cell->col is of type char, this has to be small. */ + if (st->count >= (unsigned int) (1L << ((sizeof(st->arr[0].col) * 8) - 1))) + st->count = (unsigned int) (1L << ((sizeof(st->arr[0].col) * 8) - 1)); + + + if (st->originalcolors && (st->count > 8)) + { + st->count = 8; + } + + st->coloredGCs = (GC *) calloc (sizeof(GC), st->count * 2); + + st->diaglim = get_float_resource (st->dpy, "diaglim", "Float"); + if (st->diaglim < 1.0) + { + st->diaglim = 1.0; + } + else if (st->diaglim > 2.0) + { + st->diaglim = 2.0; + } + st->diaglim *= st->orthlim; + + st->anychan = get_float_resource (st->dpy, "anychan", "Float"); + if (st->anychan < 0.0) + { + st->anychan = 0.0; + } + else if (st->anychan > 1.0) + { + st->anychan = 1.0; + } + + st->minorchan = get_float_resource (st->dpy, "minorchan","Float"); + if (st->minorchan < 0.0) + { + st->minorchan = 0.0; + } + else if (st->minorchan > 1.0) + { + st->minorchan = 1.0; + } + + st->instantdeathchan = get_float_resource (st->dpy, "instantdeathchan","Float"); + if (st->instantdeathchan < 0.0) + { + st->instantdeathchan = 0.0; + } + else if (st->instantdeathchan > 1.0) + { + st->instantdeathchan = 1.0; + } + + st->minlifespan = get_integer_resource (st->dpy, "minlifespan", "Integer"); + if (st->minlifespan < 1) + { + st->minlifespan = 1; + } + + st->maxlifespan = get_integer_resource (st->dpy, "maxlifespan", "Integer"); + if (st->maxlifespan < st->minlifespan) + { + st->maxlifespan = st->minlifespan; + } + + st->minlifespeed = get_float_resource (st->dpy, "minlifespeed", "Float"); + if (st->minlifespeed < 0.0) + { + st->minlifespeed = 0.0; + } + else if (st->minlifespeed > 1.0) + { + st->minlifespeed = 1.0; + } + + st->maxlifespeed = get_float_resource (st->dpy, "maxlifespeed", "Float"); + if (st->maxlifespeed < st->minlifespeed) + { + st->maxlifespeed = st->minlifespeed; + } + else if (st->maxlifespeed > 1.0) + { + st->maxlifespeed = 1.0; + } + + st->mindeathspeed = get_float_resource (st->dpy, "mindeathspeed", "Float"); + if (st->mindeathspeed < 0.0) + { + st->mindeathspeed = 0.0; + } + else if (st->mindeathspeed > 1.0) + { + st->mindeathspeed = 1.0; + } + + st->maxdeathspeed = get_float_resource (st->dpy, "maxdeathspeed", "Float"); + if (st->maxdeathspeed < st->mindeathspeed) + { + st->maxdeathspeed = st->mindeathspeed; + } + else if (st->maxdeathspeed > 1.0) + { + st->maxdeathspeed = 1.0; + } + + st->minlifespeed *= st->diaglim; + st->maxlifespeed *= st->diaglim; + st->mindeathspeed *= st->diaglim; + st->maxdeathspeed *= st->diaglim; + + st->windowWidth = xgwa.width; + st->windowHeight = xgwa.height; + + st->arr_width = st->windowWidth / cell_size; + st->arr_height = st->windowHeight / cell_size; + + alloc_size = sizeof(cell) * st->arr_width * st->arr_height; + oalloc = alloc_size; + + if (mem_throttle > 0) + while (cell_size < st->windowWidth/10 && + cell_size < st->windowHeight/10 && + alloc_size > mem_throttle) + { + cell_size++; + st->arr_width = st->windowWidth / cell_size; + st->arr_height = st->windowHeight / cell_size; + alloc_size = sizeof(cell) * st->arr_width * st->arr_height; + } + + if (osize != cell_size) + { + if (!st->warned) + { + fprintf (stderr, + "%s: throttling cell size from %d to %d because of %dM limit.\n", + progname, osize, cell_size, mem_throttle / (1 << 20)); + fprintf (stderr, "%s: %dx%dx%d = %.1fM, %dx%dx%d = %.1fM.\n", + progname, + st->windowWidth, st->windowHeight, osize, + ((float) oalloc) / (1 << 20), + st->windowWidth, st->windowHeight, cell_size, + ((float) alloc_size) / (1 << 20)); + st->warned = 1; + } + } + + st->xSize = st->arr_width ? st->windowWidth / st->arr_width : 0; + st->ySize = st->arr_height ? st->windowHeight / st->arr_height : 0; + if (st->xSize > st->ySize) + { + st->xSize = st->ySize; + } + else + { + st->ySize = st->xSize; + } + + st->xOffset = (st->windowWidth - (st->arr_width * st->xSize)) / 2; + st->yOffset = (st->windowHeight - (st->arr_height * st->ySize)) / 2; + + if (st->originalcolors) + { + setup_original_colormap (st, &xgwa); + } + else + { + setup_random_colormap (st, &xgwa); + } +} + +static void drawblock (struct state *st, int x, int y, unsigned char c) +{ + if (st->xSize == 1 && st->ySize == 1) + XDrawPoint (st->dpy, st->window, st->coloredGCs[c], x + st->xOffset, y + st->yOffset); + else + XFillRectangle (st->dpy, st->window, st->coloredGCs[c], + x * st->xSize + st->xOffset, y * st->ySize + st->yOffset, + st->xSize, st->ySize); +} + +static void setup_arr (struct state *st) +{ + int x, y; + + if (st->arr != NULL) + { + free (st->arr); + } + + XFillRectangle (st->dpy, st->window, st->coloredGCs[0], 0, 0, + st->windowWidth, st->windowHeight); + + if (!st->arr_width) st->arr_width = 1; + if (!st->arr_height) st->arr_height = 1; + + st->arr = (cell *) calloc (sizeof(cell), st->arr_width * st->arr_height); + if (!st->arr) + { + fprintf (stderr, "%s: out of memory allocating %dx%d grid\n", + progname, st->arr_width, st->arr_height); + exit (1); + } + + for (y = 0; y < st->arr_height; y++) + { + int row = y * st->arr_width; + for (x = 0; x < st->arr_width; x++) + { + st->arr[row+x].speed = 0.0; + st->arr[row+x].growth = 0.0; + st->arr[row+x].col = 0; + st->arr[row+x].isnext = 0; + st->arr[row+x].next = 0; + st->arr[row+x].prev = 0; + } + } + + if (st->head == NULL) + { + st->head = (cell *) malloc (sizeof (cell)); + } + + if (st->tail == NULL) + { + st->tail = (cell *) malloc (sizeof (cell)); + } + + st->head->next = st->tail; + st->head->prev = st->head; + st->tail->next = st->tail; + st->tail->prev = st->head; + + st->blastcount = random_life_value (st); +} + +static void newcell (struct state *st, cell *c, unsigned char col, FLOAT sp) +{ + if (! c) return; + + if (c->col == col) return; + + c->nextcol = col; + c->nextspeed = sp; + c->isnext = 1; + + if (c->prev == 0) { + c->next = st->head->next; + c->prev = st->head; + st->head->next = c; + c->next->prev = c; + } +} + +static void killcell (struct state *st, cell *c) +{ + c->prev->next = c->next; + c->next->prev = c->prev; + c->prev = 0; + c->speed = 0.0; + drawblock (st, cell_x(c), cell_y(c), c->col); +} + + +static void randblip (struct state *st, int doit) +{ + int n; + int b = 0; + if (!doit + && (st->blastcount-- >= 0) + && (RAND_FLOAT > st->anychan)) + { + return; + } + + if (st->blastcount < 0) + { + b = 1; + n = 2; + st->blastcount = random_life_value (st); + if (RAND_FLOAT < st->instantdeathchan) + { + /* clear everything every so often to keep from getting into a + * rut */ + setup_arr (st); + b = 0; + } + } + else if (RAND_FLOAT <= st->minorchan) + { + n = 2; + } + else + { + n = random () % 3 + 3; + } + + while (n--) + { + int x = st->arr_width ? random () % st->arr_width : 0; + int y = st->arr_height ? random () % st->arr_height : 0; + int c; + FLOAT s; + if (b) + { + c = 0; + s = RAND_FLOAT * (st->maxdeathspeed - st->mindeathspeed) + st->mindeathspeed; + } + else + { + c = ((st->count - 1) ? random () % (st->count-1) : 0) + 1; + s = RAND_FLOAT * (st->maxlifespeed - st->minlifespeed) + st->minlifespeed; + } + newcell (st, &st->arr[y * st->arr_width + x], c, s); + } +} + +static void update (struct state *st) +{ + cell *a; + + for (a = st->head->next; a != st->tail; a = a->next) + { + static const XPoint all_coords[] = {{-1, -1}, {-1, 1}, {1, -1}, {1, 1}, + {-1, 0}, { 1, 0}, {0, -1}, {0, 1}, + {99, 99}}; + + const XPoint *coords = 0; + + if (a->speed == 0) continue; + a->growth += a->speed; + + if (a->growth >= st->diaglim) + { + coords = all_coords; + } + else if (a->growth >= st->orthlim) + { + coords = &all_coords[4]; + } + else + { + continue; + } + + while (coords->x != 99) + { + int x = cell_x(a) + coords->x; + int y = cell_y(a) + coords->y; + coords++; + + if (x < 0) x = st->arr_width - 1; + else if (x >= st->arr_width) x = 0; + + if (y < 0) y = st->arr_height - 1; + else if (y >= st->arr_height) y = 0; + + newcell (st, &st->arr[y * st->arr_width + x], a->col, a->speed); + } + + if (a->growth >= st->diaglim) + killcell (st, a); + } + + randblip (st, (st->head->next) == st->tail); + + for (a = st->head->next; a != st->tail; a = a->next) + { + if (a->isnext) + { + a->isnext = 0; + a->speed = a->nextspeed; + a->growth = 0.0; + a->col = a->nextcol; + drawblock (st, cell_x(a), cell_y(a), a->col + st->count); + } + } +} + +static void * +petri_init (Display *dpy, Window win) +{ + struct state *st = (struct state *) calloc (1, sizeof(*st)); + st->dpy = dpy; + st->window = win; + + st->delay = get_integer_resource (st->dpy, "delay", "Delay"); + st->orthlim = 1; + + setup_display (st); + setup_arr (st); + randblip (st, 1); + + return st; +} + +static unsigned long +petri_draw (Display *dpy, Window window, void *closure) +{ + struct state *st = (struct state *) closure; + update (st); + return st->delay; +} + +static void +petri_reshape (Display *dpy, Window window, void *closure, + unsigned int w, unsigned int h) +{ +} + +static Bool +petri_event (Display *dpy, Window window, void *closure, XEvent *event) +{ + return False; +} + +static void +petri_free (Display *dpy, Window window, void *closure) +{ + struct state *st = (struct state *) closure; + free (st); +} + + + +static const char *petri_defaults [] = { + ".background: black", + ".foreground: white", + "*fpsSolid: true", + "*delay: 10000", + "*count: 20", + "*size: 2", + "*diaglim: 1.414", + "*anychan: 0.0015", + "*minorchan: 0.5", + "*instantdeathchan: 0.2", + "*minlifespan: 500", + "*maxlifespan: 1500", + "*minlifespeed: 0.04", + "*maxlifespeed: 0.13", + "*mindeathspeed: 0.42", + "*maxdeathspeed: 0.46", + "*originalcolors: false", + "*memThrottle: 22M", /* don't malloc more than this much. + Scale the pixels up if necessary. */ + 0 +}; + +static XrmOptionDescRec petri_options [] = { + { "-delay", ".delay", XrmoptionSepArg, 0 }, + { "-size", ".size", XrmoptionSepArg, 0 }, + { "-count", ".count", XrmoptionSepArg, 0 }, + { "-diaglim", ".diaglim", XrmoptionSepArg, 0 }, + { "-anychan", ".anychan", XrmoptionSepArg, 0 }, + { "-minorchan", ".minorchan", XrmoptionSepArg, 0 }, + { "-instantdeathchan", ".instantdeathchan", XrmoptionSepArg, 0 }, + { "-minlifespan", ".minlifespan", XrmoptionSepArg, 0 }, + { "-maxlifespan", ".maxlifespan", XrmoptionSepArg, 0 }, + { "-minlifespeed", ".minlifespeed", XrmoptionSepArg, 0 }, + { "-maxlifespeed", ".maxlifespeed", XrmoptionSepArg, 0 }, + { "-mindeathspeed", ".mindeathspeed", XrmoptionSepArg, 0 }, + { "-maxdeathspeed", ".maxdeathspeed", XrmoptionSepArg, 0 }, + { "-originalcolors", ".originalcolors", XrmoptionNoArg, "true" }, + { "-mem-throttle", ".memThrottle", XrmoptionSepArg, 0 }, + { 0, 0, 0, 0 } +}; + + +XSCREENSAVER_MODULE ("Petri", petri) diff --git a/hacks/petri.man b/hacks/petri.man new file mode 100644 index 00000000..b89230aa --- /dev/null +++ b/hacks/petri.man @@ -0,0 +1,129 @@ +.TH XScreenSaver 1 "06-Jul-2000" "X Version 11" +.SH NAME +petri - simulates mold growing in a petri dish +.SH SYNOPSIS +.B petri +[\-display \fIhost:display.screen\fP] [\-foreground \fIcolor\fP] [\-background \fIcolor\fP] [\-window] [\-root] [\-mono] [\-install] [\-visual \fIvisual\fP] [\-delay \fImicroseconds\fP] [\-size \fIinteger\fP] [\-mem-throttle \fIamount\fP] [\-count \fIinteger\fP] [\-originalcolors] [\-diaglim \fIreal\fP] [\-anychan \fIreal\fP] [\-minorchan \fIreal\fP] [\-instantdeathchan \fIreal\fP] [\-minlifespeed \fIreal\fP] [\-maxlifespeed \fIreal\fP] [\-mindeathspeed \fIreal\fP] [\-maxdeathspeed \fIreal\fP] [\-minlifespan \fIinteger\fP] [\-maxlifespan \fIinteger\fP] +[\-fps] +.SH DESCRIPTION +\fIpetri\fP simulates mold growing in a petri dish via a state-heavy grid +of automata (vaguely like Conway's Life, only with much more state per +cell). +.SH OPTIONS +.I petri +accepts the following options: +.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 \-mono +If on a color display, pretend we're on a monochrome display. +.TP 8 +.B \-install +Install a private colormap for the window. +.TP 8 +.B \-visual \fIvisual\fP +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 \-delay \fImicroseconds\fP +The interframe delay, in microseconds. Defaults to 10000, resource +\fIdelay\fP. +.TP 8 +.B \-size \fIinteger\fP +The size of a cell in pixels. Defaults to 4, resource \fIsize\fP. +.TP 8 +.B \-mem-throttle \fIamount\fP +The maximum amount of memory to consume, specified either in megabytes +(suffix "M"), kilobytes (suffix "K"), or bytes (sans suffix). In order +to meet the memory requirement, the cell size may be increased. +Defaults to 22M, resource \fImemThrottle\fP. +.TP 8 +.B \-count \fIinteger\fP +How many different varieties of mold to grow (including Black Death). +Defaults to 8, resource \fIcount\fP. +.TP 8 +.B \-originalcolors +If specified, indicates that the colors used should be the artist's +original choices (a fixed set of primary and secondary colors). In this +case, count must be 8 or less. Defaults to not specified (i.e., false), +resource \fIoriginalcolors\fP. +.TP 8 +.B \-diaglim \fIreal\fP +The age limit for diagonal growth as a multiplier of +orthogonal growth (range 1..2). 1 means square growth, 1.414 +(i.e., \fIsqrt(2)\fP) means approximately circular growth, 2 means +diamond growth. Defaults to 1.414, resource \fIdiaglim\fP. +.TP 8 +.B \-anychan \fIreal\fP +The chance (range 0..1) that at each iteration, one or more +new cells will be born. Defaults to 0.0015, resource \fIanychan\fP. +.TP 8 +.B \-minorchan \fIreal\fP +The chance (range 0..1) that, given that new cells will be born, that only +two will be added (hence being a minor cell birth event). +Defaults to 0.5, resource \fIminorchan\fP. +.TP 8 +.B \-instantdeathchan \fIreal\fP +The chance (range 0..1) that, given that death and destruction will happen, +that instead of using Black Death cells, death will come instantaneously. +Defaults to 0.2, resource \fIinstantdeathchan\fP. +.TP 8 +.B \-minlifespeed \fIreal\fP +The minimum speed for living cells as a fraction of the maximum possible +speed (range 0..1). Defaults to 0.04, resource \fIminlifespeed\fP. +.TP 8 +.B \-maxlifespeed \fIreal\fP +The maximum speed for living cells as a fraction of the maximum possible +speed (range 0..1). Defaults to 0.13, resource \fImaxlifespeed\fP. +.TP 8 +.B \-mindeathspeed \fIreal\fP +The minimum speed for Black Death cells as a fraction of the maximum possible +speed (range 0..1). Defaults to 0.42, resource \fImindeathspeed\fP. +.TP 8 +.B \-maxdeathspeed \fIreal\fP +The maximum speed for Black Death cells as a fraction of the maximum possible +speed (range 0..1). Defaults to 0.46, resource \fImaxdeathspeed\fP. +.TP 8 +.B \-minlifespan \fIinteger\fP +The minimum lifespan for a colony, in iterations, before Black Death +comes. Defaults to 500, resource \fIminlifespan\fP. +.TP 8 +.B \-maxlifespan \fIinteger\fP +The maximum lifespan for a colony, in iterations, before Black Death +comes. Defaults to 1500, resource \fImaxlifespan\fP. +.TP 8 +.B \-fps +Display the current frame rate and CPU load. +.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 X RESOURCES +There are resource equivalents for each option, noted above. +.SH BUGS +There are no known bugs in +.I petri +as of this writing. +.SH SEE ALSO +.BR xscreensaver (1) +.SH COPYRIGHT +Copyright \(co 1992-2000 by Dan Bornstein. + +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 +Dan Bornstein , 06-Jul-2000. diff --git a/hacks/phosphor.c b/hacks/phosphor.c new file mode 100644 index 00000000..b7ec5407 --- /dev/null +++ b/hacks/phosphor.c @@ -0,0 +1,1261 @@ +/* xscreensaver, Copyright (c) 1999-2012 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. + * + * Phosphor -- simulate a glass tty with long-sustain phosphor. + * Written by Jamie Zawinski + * Pty and vt100 emulation by Fredrik Tolf + */ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif /* HAVE_CONFIG_H */ + +#ifndef HAVE_COCOA +# include +#endif + +#include "screenhack.h" +#include "textclient.h" + +#define FUZZY_BORDER + +#define MAX(a,b) ((a)>(b)?(a):(b)) +#define MIN(a,b) ((a)<(b)?(a):(b)) + +#define BLANK 0 +#define FLARE 1 +#define NORMAL 2 +#define FADE 3 +#define STATE_MAX FADE + +#define CURSOR_INDEX 128 + +#define NPAR 16 + +#define BUILTIN_FONT + +#ifdef BUILTIN_FONT +# include "images/6x10font.xbm" +#endif /* BUILTIN_FONT */ + +typedef struct { + unsigned char name; + int width, height; + Pixmap pixmap; +#ifdef FUZZY_BORDER + Pixmap pixmap2; +#endif /* FUZZY_BORDER */ + Bool blank_p; +} p_char; + +typedef struct { + p_char *p_char; + int state; + Bool changed; +} p_cell; + +typedef struct { + Display *dpy; + Window window; + XWindowAttributes xgwa; + XFontStruct *font; + const char *program; + int grid_width, grid_height; + int char_width, char_height; + int saved_x, saved_y; + int scale; + int ticks; + int mode; + int escstate; + int csiparam[NPAR]; + int curparam; + p_char **chars; + p_cell *cells; + XGCValues gcv; + GC gc0; + GC gc1; +#ifdef FUZZY_BORDER + GC gc2; +#endif /* FUZZY_BORDER */ + GC *gcs; + XImage *font_bits; + + int cursor_x, cursor_y; + XtIntervalId cursor_timer; + Time cursor_blink; + int delay; + Bool pty_p; + + text_data *tc; + + char last_c; + int bk; + +} p_state; + + +static void capture_font_bits (p_state *state); +static p_char *make_character (p_state *state, int c); +static void char_to_pixmap (p_state *state, p_char *pc, int c); + + +/* About font metrics: + + "lbearing" is the distance from the leftmost pixel of a character to + the logical origin of that character. That is, it is the number of + pixels of the character which are to the left of its logical origin. + + "rbearing" is the distance from the logical origin of a character to + the rightmost pixel of a character. That is, it is the number of + pixels of the character to the right of its logical origin. + + "descent" is the distance from the bottommost pixel of a character to + the logical baseline. That is, it is the number of pixels of the + character which are below the baseline. + + "ascent" is the distance from the logical baseline to the topmost pixel. + That is, it is the number of pixels of the character above the baseline. + + Therefore, the bounding box of the "ink" of a character is + lbearing + rbearing by ascent + descent; + + "width" is the distance from the logical origin of this character to + the position where the logical orgin of the next character should be + placed. + + For our purposes, we're only interested in the part of the character + lying inside the "width" box. If the characters have ink outside of + that box (the "charcell" box) then we're going to lose it. Alas. + */ + + +static void clear (p_state *); +static void set_cursor (p_state *, Bool on); + +static void * +phosphor_init (Display *dpy, Window window) +{ + int i; + unsigned long flags; + p_state *state = (p_state *) calloc (sizeof(*state), 1); + char *fontname = get_string_resource (dpy, "font", "Font"); + XFontStruct *font; + + state->dpy = dpy; + state->window = window; + + XGetWindowAttributes (dpy, window, &state->xgwa); +/* XSelectInput (dpy, window, state->xgwa.your_event_mask | ExposureMask);*/ + + state->delay = get_integer_resource (dpy, "delay", "Integer"); + state->pty_p = get_boolean_resource (dpy, "usePty", "UsePty"); + + if (!strcasecmp (fontname, "builtin") || + !strcasecmp (fontname, "(builtin)")) + { +#ifndef BUILTIN_FONT + fprintf (stderr, "%s: no builtin font\n", progname); + state->font = XLoadQueryFont (dpy, "fixed"); +#endif /* !BUILTIN_FONT */ + } + else + { + state->font = XLoadQueryFont (dpy, fontname); + + if (!state->font) + { + fprintf(stderr, "couldn't load font \"%s\"\n", fontname); + state->font = XLoadQueryFont (dpy, "fixed"); + } + if (!state->font) + { + fprintf(stderr, "couldn't load font \"fixed\""); + exit(1); + } + } + + font = state->font; + state->scale = get_integer_resource (dpy, "scale", "Integer"); + state->ticks = STATE_MAX + get_integer_resource (dpy, "ticks", "Integer"); + state->escstate = 0; + + + state->cursor_blink = get_integer_resource (dpy, "cursor", "Time"); + +# ifdef BUILTIN_FONT + if (! font) + { + state->char_width = (font6x10_width / 256) - 1; + state->char_height = font6x10_height; + } + else +# endif /* BUILTIN_FONT */ + { + state->char_width = font->max_bounds.width; + state->char_height = font->max_bounds.ascent + font->max_bounds.descent; + } + + state->grid_width = state->xgwa.width / (state->char_width * state->scale); + state->grid_height = state->xgwa.height /(state->char_height * state->scale); + state->cells = (p_cell *) calloc (sizeof(p_cell), + state->grid_width * state->grid_height); + state->chars = (p_char **) calloc (sizeof(p_char *), 256); + + state->gcs = (GC *) calloc (sizeof(GC), state->ticks + 1); + + { + int ncolors = MAX (0, state->ticks - 3); + XColor *colors = (XColor *) calloc (ncolors, sizeof(XColor)); + int h1, h2; + double s1, s2, v1, v2; + + unsigned long fg = get_pixel_resource (state->dpy, state->xgwa.colormap, + "foreground", "Foreground"); + unsigned long bg = get_pixel_resource (state->dpy, state->xgwa.colormap, + "background", "Background"); + unsigned long flare = get_pixel_resource (state->dpy,state->xgwa.colormap, + "flareForeground", "Foreground"); + unsigned long fade = get_pixel_resource (state->dpy,state->xgwa.colormap, + "fadeForeground", "Foreground"); + + XColor start, end; + + start.pixel = fade; + XQueryColor (state->dpy, state->xgwa.colormap, &start); + + end.pixel = bg; + XQueryColor (state->dpy, state->xgwa.colormap, &end); + + /* Now allocate a ramp of colors from the main color to the background. */ + rgb_to_hsv (start.red, start.green, start.blue, &h1, &s1, &v1); + rgb_to_hsv (end.red, end.green, end.blue, &h2, &s2, &v2); + make_color_ramp (state->dpy, state->xgwa.colormap, + h1, s1, v1, + h2, s2, v2, + colors, &ncolors, + False, True, False); + + /* Adjust to the number of colors we actually got. */ + state->ticks = ncolors + STATE_MAX; + + /* Now, GCs all around. + */ + state->gcv.font = (font ? font->fid : 0); + state->gcv.cap_style = CapRound; +#ifdef FUZZY_BORDER + state->gcv.line_width = (int) (((long) state->scale) * 1.3); + if (state->gcv.line_width == state->scale) + state->gcv.line_width++; +#else /* !FUZZY_BORDER */ + state->gcv.line_width = (int) (((long) state->scale) * 0.9); + if (state->gcv.line_width >= state->scale) + state->gcv.line_width = state->scale - 1; + if (state->gcv.line_width < 1) + state->gcv.line_width = 1; +#endif /* !FUZZY_BORDER */ + + flags = (GCForeground | GCBackground | GCCapStyle | GCLineWidth); + + state->gcv.background = bg; + state->gcv.foreground = bg; + state->gcs[BLANK] = XCreateGC (state->dpy, state->window, flags, + &state->gcv); + + state->gcv.foreground = flare; + state->gcs[FLARE] = XCreateGC (state->dpy, state->window, flags, + &state->gcv); + + state->gcv.foreground = fg; + state->gcs[NORMAL] = XCreateGC (state->dpy, state->window, flags, + &state->gcv); + + for (i = 0; i < ncolors; i++) + { + state->gcv.foreground = colors[i].pixel; + state->gcs[STATE_MAX + i] = XCreateGC (state->dpy, state->window, + flags, &state->gcv); + } + } + + capture_font_bits (state); + + set_cursor (state, True); + +/* clear (state);*/ + + state->tc = textclient_open (dpy); + textclient_reshape (state->tc, + state->xgwa.width, + state->xgwa.height, + state->grid_width - 1, + state->grid_height - 1); + + return state; +} + + +/* Re-query the window size and update the internal character grid if changed. + */ +static Bool +resize_grid (p_state *state) +{ + int ow = state->grid_width; + int oh = state->grid_height; + p_cell *ocells = state->cells; + int x, y; + + XGetWindowAttributes (state->dpy, state->window, &state->xgwa); + + state->grid_width = state->xgwa.width /(state->char_width * state->scale); + state->grid_height = state->xgwa.height /(state->char_height * state->scale); + + if (ow == state->grid_width && + oh == state->grid_height) + return False; + + state->cells = (p_cell *) calloc (sizeof(p_cell), + state->grid_width * state->grid_height); + + for (y = 0; y < state->grid_height; y++) + { + for (x = 0; x < state->grid_width; x++) + { + p_cell *ncell = &state->cells [state->grid_width * y + x]; + if (x < ow && y < oh) + *ncell = ocells [ow * y + x]; + ncell->changed = True; + } + } + + if (state->cursor_x >= state->grid_width) + state->cursor_x = state->grid_width-1; + if (state->cursor_y >= state->grid_height) + state->cursor_y = state->grid_height-1; + + free (ocells); + return True; +} + + +static void +capture_font_bits (p_state *state) +{ + XFontStruct *font = state->font; + int safe_width, height; + unsigned char string[257]; + int i; + Pixmap p; + +# ifdef BUILTIN_FONT + Pixmap p2 = 0; + + if (!font) + { + safe_width = state->char_width + 1; + height = state->char_height; + p2 = XCreatePixmapFromBitmapData (state->dpy, state->window, + (char *) font6x10_bits, + font6x10_width, + font6x10_height, + 1, 0, 1); + } + else +# endif /* BUILTIN_FONT */ + { + safe_width = font->max_bounds.rbearing - font->min_bounds.lbearing; + height = state->char_height; + } + + p = XCreatePixmap (state->dpy, state->window, + (safe_width * 256), height, 1); + + for (i = 0; i < 256; i++) + string[i] = (unsigned char) i; + string[256] = 0; + + state->gcv.foreground = 0; + state->gcv.background = 0; + state->gc0 = XCreateGC (state->dpy, p, + (GCForeground | GCBackground), + &state->gcv); + + state->gcv.foreground = 1; + state->gc1 = XCreateGC (state->dpy, p, + ((font ? GCFont : 0) | + GCForeground | GCBackground | + GCCapStyle | GCLineWidth), + &state->gcv); + +#ifdef HAVE_COCOA + jwxyz_XSetAntiAliasing (state->dpy, state->gc0, False); + jwxyz_XSetAntiAliasing (state->dpy, state->gc1, False); +#endif + +#ifdef FUZZY_BORDER + { + state->gcv.line_width = (int) (((long) state->scale) * 0.8); + if (state->gcv.line_width >= state->scale) + state->gcv.line_width = state->scale - 1; + if (state->gcv.line_width < 1) + state->gcv.line_width = 1; + state->gc2 = XCreateGC (state->dpy, p, + ((font ? GCFont : 0) | + GCForeground | GCBackground | + GCCapStyle | GCLineWidth), + &state->gcv); + } +#endif /* FUZZY_BORDER */ + + XFillRectangle (state->dpy, p, state->gc0, 0, 0, (safe_width * 256), height); + +# ifdef BUILTIN_FONT + if (p2) + { + XCopyPlane (state->dpy, p2, p, state->gc1, + 0, 0, font6x10_width, font6x10_height, + 0, 0, 1); + XFreePixmap (state->dpy, p2); + } + else +# endif /* BUILTIN_FONT */ + { + for (i = 0; i < 256; i++) + { + if (string[i] < font->min_char_or_byte2 || + string[i] > font->max_char_or_byte2) + continue; + XDrawString (state->dpy, p, state->gc1, + i * safe_width, font->ascent, + (char *) (string + i), 1); + } + } + + /* Draw the cursor. */ + XFillRectangle (state->dpy, p, state->gc1, + (CURSOR_INDEX * safe_width), 1, + (font + ? (font->per_char + ? font->per_char['n'-font->min_char_or_byte2].width + : font->max_bounds.width) + : state->char_width), + (font + ? font->ascent - 1 + : state->char_height)); + + state->font_bits = XGetImage (state->dpy, p, 0, 0, + (safe_width * 256), height, ~0L, XYPixmap); + XFreePixmap (state->dpy, p); + + for (i = 0; i < 256; i++) + state->chars[i] = make_character (state, i); + state->chars[CURSOR_INDEX] = make_character (state, CURSOR_INDEX); +} + + +static p_char * +make_character (p_state *state, int c) +{ + p_char *pc = (p_char *) malloc (sizeof (*pc)); + pc->name = (unsigned char) c; + pc->width = state->scale * state->char_width; + pc->height = state->scale * state->char_height; + char_to_pixmap (state, pc, c); + return pc; +} + + +static void +char_to_pixmap (p_state *state, p_char *pc, int c) +{ + Pixmap p = 0; + GC gc; +#ifdef FUZZY_BORDER + Pixmap p2 = 0; + GC gc2; +#endif /* FUZZY_BORDER */ + int from, to; + int x1, y; + + XFontStruct *font = state->font; + int safe_width = (font + ? font->max_bounds.rbearing - font->min_bounds.lbearing + : state->char_width + 1); + + int width = state->scale * state->char_width; + int height = state->scale * state->char_height; + + if (font && (c < font->min_char_or_byte2 || + c > font->max_char_or_byte2)) + goto DONE; + + gc = state->gc1; + p = XCreatePixmap (state->dpy, state->window, width, height, 1); + XFillRectangle (state->dpy, p, state->gc0, 0, 0, width, height); +#ifdef FUZZY_BORDER + gc2 = state->gc2; + p2 = XCreatePixmap (state->dpy, state->window, width, height, 1); + XFillRectangle (state->dpy, p2, state->gc0, 0, 0, width, height); +#endif /* FUZZY_BORDER */ + + from = safe_width * c; + to = safe_width * (c + 1); + +#if 0 + if (c > 75 && c < 150) + { + printf ("\n=========== %d (%c)\n", c, c); + for (y = 0; y < state->char_height; y++) + { + for (x1 = from; x1 < to; x1++) + printf (XGetPixel (state->font_bits, x1, y) ? "* " : ". "); + printf ("\n"); + } + } +#endif + + pc->blank_p = True; + for (y = 0; y < state->char_height; y++) + for (x1 = from; x1 < to; x1++) + if (XGetPixel (state->font_bits, x1, y)) + { + int xoff = state->scale / 2; + int x2; + for (x2 = x1; x2 < to; x2++) + if (!XGetPixel (state->font_bits, x2, y)) + break; + x2--; + XDrawLine (state->dpy, p, gc, + (x1 - from) * state->scale + xoff, y * state->scale, + (x2 - from) * state->scale + xoff, y * state->scale); +#ifdef FUZZY_BORDER + XDrawLine (state->dpy, p2, gc2, + (x1 - from) * state->scale + xoff, y * state->scale, + (x2 - from) * state->scale + xoff, y * state->scale); +#endif /* FUZZY_BORDER */ + x1 = x2; + pc->blank_p = False; + } + + /* if (pc->blank_p && c == CURSOR_INDEX) + abort();*/ + + DONE: + pc->pixmap = p; +#ifdef FUZZY_BORDER + pc->pixmap2 = p2; +#endif /* FUZZY_BORDER */ +} + + +/* Managing the display. + */ + +static void cursor_on_timer (XtPointer closure, XtIntervalId *id); +static void cursor_off_timer (XtPointer closure, XtIntervalId *id); + +static Bool +set_cursor_1 (p_state *state, Bool on) +{ + p_cell *cell = &state->cells[state->grid_width * state->cursor_y + + state->cursor_x]; + p_char *cursor = state->chars[CURSOR_INDEX]; + int new_state = (on ? NORMAL : FADE); + + if (cell->p_char != cursor) + cell->changed = True; + + if (cell->state != new_state) + cell->changed = True; + + cell->p_char = cursor; + cell->state = new_state; + return cell->changed; +} + +static void +set_cursor (p_state *state, Bool on) +{ + if (set_cursor_1 (state, on)) + { + if (state->cursor_timer) + XtRemoveTimeOut (state->cursor_timer); + state->cursor_timer = 0; + cursor_on_timer (state, 0); + } +} + + +static void +cursor_off_timer (XtPointer closure, XtIntervalId *id) +{ + p_state *state = (p_state *) closure; + XtAppContext app = XtDisplayToApplicationContext (state->dpy); + set_cursor_1 (state, False); + state->cursor_timer = XtAppAddTimeOut (app, state->cursor_blink, + cursor_on_timer, closure); +} + +static void +cursor_on_timer (XtPointer closure, XtIntervalId *id) +{ + p_state *state = (p_state *) closure; + XtAppContext app = XtDisplayToApplicationContext (state->dpy); + set_cursor_1 (state, True); + state->cursor_timer = XtAppAddTimeOut (app, 2 * state->cursor_blink, + cursor_off_timer, closure); +} + + +static void +clear (p_state *state) +{ + int x, y; + state->cursor_x = 0; + state->cursor_y = 0; + for (y = 0; y < state->grid_height; y++) + for (x = 0; x < state->grid_width; x++) + { + p_cell *cell = &state->cells[state->grid_width * y + x]; + if (cell->state == FLARE || cell->state == NORMAL) + { + cell->state = FADE; + cell->changed = True; + } + } + set_cursor (state, True); +} + + +static void +decay (p_state *state) +{ + int x, y; + for (y = 0; y < state->grid_height; y++) + for (x = 0; x < state->grid_width; x++) + { + p_cell *cell = &state->cells[state->grid_width * y + x]; + if (cell->state == FLARE) + { + cell->state = NORMAL; + cell->changed = True; + } + else if (cell->state >= FADE) + { + cell->state++; + if (cell->state >= state->ticks) + cell->state = BLANK; + cell->changed = True; + } + } +} + + +static void +scroll (p_state *state) +{ + int x, y; + + for (x = 0; x < state->grid_width; x++) + { + p_cell *from = 0, *to = 0; + for (y = 1; y < state->grid_height; y++) + { + from = &state->cells[state->grid_width * y + x]; + to = &state->cells[state->grid_width * (y-1) + x]; + + if ((from->state == FLARE || from->state == NORMAL) && + !from->p_char->blank_p) + { + *to = *from; + to->state = NORMAL; /* should be FLARE? Looks bad... */ + } + else + { + if (to->state == FLARE || to->state == NORMAL) + to->state = FADE; + } + + to->changed = True; + } + + to = from; + if (to && (to->state == FLARE || to->state == NORMAL)) + { + to->state = FADE; + to->changed = True; + } + } + set_cursor (state, True); +} + + +static void +print_char (p_state *state, int c) +{ + p_cell *cell = &state->cells[state->grid_width * state->cursor_y + + state->cursor_x]; + + /* Start the cursor fading (in case we don't end up overwriting it.) */ + if (cell->state == FLARE || cell->state == NORMAL) + { + cell->state = FADE; + cell->changed = True; + } + +#ifdef HAVE_FORKPTY + if (state->pty_p) /* Only interpret VT100 sequences if running in pty-mode. + It would be nice if we could just interpret them all + the time, but that would require subprocesses to send + CRLF line endings instead of bare LF, so that's no good. + */ + { + int i, start, end; + switch (state->escstate) + { + case 0: + switch (c) + { + case 7: /* BEL */ + /* Dummy case - we don't want the screensaver to beep */ + /* #### But maybe this should flash the screen? */ + break; + case 8: /* BS */ + if (state->cursor_x > 0) + state->cursor_x--; + break; + case 9: /* HT */ + if (state->cursor_x < state->grid_width - 8) + { + state->cursor_x = (state->cursor_x & ~7) + 8; + } + else + { + state->cursor_x = 0; + if (state->cursor_y < state->grid_height - 1) + state->cursor_y++; + else + scroll (state); + } + break; + case 10: /* LF */ + case 11: /* VT */ + case 12: /* FF */ + if(state->last_c == 13) + { + cell->state = NORMAL; + cell->p_char = state->chars[state->bk]; + cell->changed = True; + } + if (state->cursor_y < state->grid_height - 1) + state->cursor_y++; + else + scroll (state); + break; + case 13: /* CR */ + state->cursor_x = 0; + cell = &state->cells[state->grid_width * state->cursor_y]; + if((cell->p_char == NULL) || (cell->p_char->name == CURSOR_INDEX)) + state->bk = ' '; + else + state->bk = cell->p_char->name; + break; + case 14: /* SO */ + case 15: /* SI */ + /* Dummy case - I don't want to load several fonts for + the maybe two programs world-wide that use that */ + break; + case 24: /* CAN */ + case 26: /* SUB */ + /* Dummy case - these interrupt escape sequences, so + they don't do anything in this state */ + break; + case 27: /* ESC */ + state->escstate = 1; + break; + case 127: /* DEL */ + /* Dummy case - this is supposed to be ignored */ + break; + case 155: /* CSI */ + state->escstate = 2; + for(i = 0; i < NPAR; i++) + state->csiparam[i] = 0; + state->curparam = 0; + break; + default: + cell->state = FLARE; + cell->p_char = state->chars[c]; + cell->changed = True; + state->cursor_x++; + + if (c != ' ' && cell->p_char->blank_p) + cell->p_char = state->chars[CURSOR_INDEX]; + + if (state->cursor_x >= state->grid_width - 1) + { + state->cursor_x = 0; + if (state->cursor_y >= state->grid_height - 1) + scroll (state); + else + state->cursor_y++; + } + break; + } + break; + case 1: + switch (c) + { + case 24: /* CAN */ + case 26: /* SUB */ + state->escstate = 0; + break; + case 'c': /* Reset */ + clear (state); + state->escstate = 0; + break; + case 'D': /* Linefeed */ + if (state->cursor_y < state->grid_height - 1) + state->cursor_y++; + else + scroll (state); + state->escstate = 0; + break; + case 'E': /* Newline */ + state->cursor_x = 0; + state->escstate = 0; + break; + case 'M': /* Reverse newline */ + if (state->cursor_y > 0) + state->cursor_y--; + state->escstate = 0; + break; + case '7': /* Save state */ + state->saved_x = state->cursor_x; + state->saved_y = state->cursor_y; + state->escstate = 0; + break; + case '8': /* Restore state */ + state->cursor_x = state->saved_x; + state->cursor_y = state->saved_y; + state->escstate = 0; + break; + case '[': /* CSI */ + state->escstate = 2; + for(i = 0; i < NPAR; i++) + state->csiparam[i] = 0; + state->curparam = 0; + break; + case '%': /* Select charset */ + /* No, I don't support UTF-8, since the phosphor font + isn't even Unicode anyway. We must still catch the + last byte, though. */ + case '(': + case ')': + /* I don't support different fonts either - see above + for SO and SI */ + state->escstate = 3; + break; + default: + /* Escape sequences not supported: + * + * H - Set tab stop + * Z - Terminal identification + * > - Keypad change + * = - Other keypad change + * ] - OS command + */ + state->escstate = 0; + break; + } + break; + case 2: + switch (c) + { + case 24: /* CAN */ + case 26: /* SUB */ + state->escstate = 0; + break; + case '0': case '1': case '2': case '3': case '4': + case '5': case '6': case '7': case '8': case '9': + if (state->curparam < NPAR) + state->csiparam[state->curparam] = (state->csiparam[state->curparam] * 10) + (c - '0'); + break; + case ';': + state->csiparam[++state->curparam] = 0; + break; + case '[': + state->escstate = 3; + break; + case '@': + for (i = 0; i < state->csiparam[0]; i++) + { + if(++state->cursor_x > state->grid_width) + { + state->cursor_x = 0; + if (state->cursor_y < state->grid_height - 1) + state->cursor_y++; + else + scroll (state); + } + cell = &state->cells[state->grid_width * state->cursor_y + state->cursor_x]; + if (cell->state == FLARE || cell->state == NORMAL) + { + cell->state = FADE; + cell->changed = True; + } + } + state->escstate = 0; + break; + case 'F': + state->cursor_x = 0; + case 'A': + if (state->csiparam[0] == 0) + state->csiparam[0] = 1; + if ((state->cursor_y -= state->csiparam[0]) < 0) + state->cursor_y = 0; + state->escstate = 0; + break; + case 'E': + state->cursor_x = 0; + case 'e': + case 'B': + if (state->csiparam[0] == 0) + state->csiparam[0] = 1; + if ((state->cursor_y += state->csiparam[0]) >= state->grid_height - 1) + state->cursor_y = state->grid_height - 1; + state->escstate = 0; + break; + case 'a': + case 'C': + if (state->csiparam[0] == 0) + state->csiparam[0] = 1; + if ((state->cursor_x += state->csiparam[0]) >= state->grid_width - 1) + state->cursor_x = state->grid_width - 1; + state->escstate = 0; + break; + case 'D': + if (state->csiparam[0] == 0) + state->csiparam[0] = 1; + if ((state->cursor_x -= state->csiparam[0]) < 0) + state->cursor_x = 0; + state->escstate = 0; + break; + case 'd': + if ((state->cursor_y = (state->csiparam[0] - 1)) >= state->grid_height - 1) + state->cursor_y = state->grid_height - 1; + state->escstate = 0; + break; + case '`': + case 'G': + if ((state->cursor_x = (state->csiparam[0] - 1)) >= state->grid_width - 1) + state->cursor_x = state->grid_width - 1; + state->escstate = 0; + break; + case 'f': + case 'H': + if ((state->cursor_y = (state->csiparam[0] - 1)) >= state->grid_height - 1) + state->cursor_y = state->grid_height - 1; + if ((state->cursor_x = (state->csiparam[1] - 1)) >= state->grid_width - 1) + state->cursor_x = state->grid_width - 1; + if(state->cursor_y < 0) + state->cursor_y = 0; + if(state->cursor_x < 0) + state->cursor_x = 0; + state->escstate = 0; + break; + case 'J': + start = 0; + end = state->grid_height * state->grid_width; + if (state->csiparam[0] == 0) + start = state->grid_width * state->cursor_y + state->cursor_x; + if (state->csiparam[0] == 1) + end = state->grid_width * state->cursor_y + state->cursor_x; + for (i = start; i < end; i++) + { + cell = &state->cells[i]; + if (cell->state == FLARE || cell->state == NORMAL) + { + cell->state = FADE; + cell->changed = True; + } + } + set_cursor (state, True); + state->escstate = 0; + break; + case 'K': + start = 0; + end = state->grid_width; + if (state->csiparam[0] == 0) + start = state->cursor_x; + if (state->csiparam[1] == 1) + end = state->cursor_x; + for (i = start; i < end; i++) + { + if (cell->state == FLARE || cell->state == NORMAL) + { + cell->state = FADE; + cell->changed = True; + } + cell++; + } + state->escstate = 0; + break; + case 's': /* Save position */ + state->saved_x = state->cursor_x; + state->saved_y = state->cursor_y; + state->escstate = 0; + break; + case 'u': /* Restore position */ + state->cursor_x = state->saved_x; + state->cursor_y = state->saved_y; + state->escstate = 0; + break; + case '?': /* DEC Private modes */ + if ((state->curparam != 0) || (state->csiparam[0] != 0)) + state->escstate = 0; + break; + default: + /* Known unsupported CSIs: + * + * L - Insert blank lines + * M - Delete lines (I don't know what this means...) + * P - Delete characters + * X - Erase characters (difference with P being...?) + * c - Terminal identification + * g - Clear tab stop(s) + * h - Set mode (Mainly due to its complexity and lack of good + docs) + * l - Clear mode + * m - Set mode (Phosphor is, per defenition, green on black) + * n - Status report + * q - Set keyboard LEDs + * r - Set scrolling region (too exhausting - noone uses this, + right?) + */ + state->escstate = 0; + break; + } + break; + case 3: + state->escstate = 0; + break; + } + set_cursor (state, True); + } + else +#endif /* HAVE_FORKPTY */ + { + if (c == '\t') c = ' '; /* blah. */ + + if (c == '\r' || c == '\n') /* handle CR, LF, or CRLF as "new line". */ + { + if (c == '\n' && state->last_c == '\r') + ; /* CRLF -- do nothing */ + else + { + state->cursor_x = 0; + if (state->cursor_y == state->grid_height - 1) + scroll (state); + else + state->cursor_y++; + } + } + else if (c == '\014') + { + clear (state); + } + else + { + cell->state = FLARE; + cell->p_char = state->chars[c]; + cell->changed = True; + state->cursor_x++; + + if (c != ' ' && cell->p_char->blank_p) + cell->p_char = state->chars[CURSOR_INDEX]; + + if (state->cursor_x >= state->grid_width - 1) + { + state->cursor_x = 0; + if (state->cursor_y >= state->grid_height - 1) + scroll (state); + else + state->cursor_y++; + } + } + set_cursor (state, True); + } + + state->last_c = c; +} + + +static void +update_display (p_state *state, Bool changed_only) +{ + int x, y; + + for (y = 0; y < state->grid_height; y++) + for (x = 0; x < state->grid_width; x++) + { + p_cell *cell = &state->cells[state->grid_width * y + x]; + int width, height, tx, ty; + + if (changed_only && !cell->changed) + continue; + + width = state->char_width * state->scale; + height = state->char_height * state->scale; + tx = x * width; + ty = y * height; + + if (cell->state == BLANK || cell->p_char->blank_p) + { + XFillRectangle (state->dpy, state->window, state->gcs[BLANK], + tx, ty, width, height); + } + else + { +#ifdef FUZZY_BORDER + GC gc1 = state->gcs[cell->state]; + GC gc2 = ((cell->state + 2) < state->ticks + ? state->gcs[cell->state + 2] + : 0); + GC gc3 = (gc2 ? gc2 : gc1); + if (gc3) + XCopyPlane (state->dpy, cell->p_char->pixmap, state->window, gc3, + 0, 0, width, height, tx, ty, 1L); + if (gc2) + { + XSetClipMask (state->dpy, gc1, cell->p_char->pixmap2); + XSetClipOrigin (state->dpy, gc1, tx, ty); + XFillRectangle (state->dpy, state->window, gc1, + tx, ty, width, height); + XSetClipMask (state->dpy, gc1, None); + } +#else /* !FUZZY_BORDER */ + + XCopyPlane (state->dpy, + cell->p_char->pixmap, state->window, + state->gcs[cell->state], + 0, 0, width, height, tx, ty, 1L); + +#endif /* !FUZZY_BORDER */ + } + + cell->changed = False; + } +} + + +static unsigned long +phosphor_draw (Display *dpy, Window window, void *closure) +{ + p_state *state = (p_state *) closure; + int c; + update_display (state, True); + decay (state); + + c = textclient_getc (state->tc); + if (c > 0) + print_char (state, c); + + return state->delay; +} + + +static void +phosphor_reshape (Display *dpy, Window window, void *closure, + unsigned int w, unsigned int h) +{ + p_state *state = (p_state *) closure; + Bool changed_p = resize_grid (state); + + if (! changed_p) return; + + textclient_reshape (state->tc, w, h, + state->grid_width - 1, + state->grid_height - 1); +} + + +static Bool +phosphor_event (Display *dpy, Window window, void *closure, XEvent *event) +{ + p_state *state = (p_state *) closure; + + if (event->xany.type == Expose) + update_display (state, False); + else if (event->xany.type == KeyPress) + return textclient_putc (state->tc, &event->xkey); + return False; +} + +static void +phosphor_free (Display *dpy, Window window, void *closure) +{ + p_state *state = (p_state *) closure; + + textclient_close (state->tc); + if (state->cursor_timer) + XtRemoveTimeOut (state->cursor_timer); + + /* #### there's more to free here */ + + free (state); +} + + + +static const char *phosphor_defaults [] = { + ".background: Black", + ".foreground: #00FF00", + "*fpsSolid: true", + "*fadeForeground: #006400", + "*flareForeground: #FFFFFF", +#if defined(BUILTIN_FONT) + "*font: (builtin)", +#elif defined(HAVE_COCOA) + "*font: Monaco 15", +#else + "*font: fixed", +#endif + "*scale: 6", + "*ticks: 20", + "*delay: 50000", + "*cursor: 333", + "*program: xscreensaver-text", + "*relaunch: 5", + "*metaSendsESC: True", + "*swapBSDEL: True", +#ifdef HAVE_FORKPTY + "*usePty: True", +#else /* !HAVE_FORKPTY */ + "*usePty: False", +#endif /* !HAVE_FORKPTY */ + 0 +}; + +static XrmOptionDescRec phosphor_options [] = { + { "-font", ".font", XrmoptionSepArg, 0 }, + { "-scale", ".scale", XrmoptionSepArg, 0 }, + { "-ticks", ".ticks", XrmoptionSepArg, 0 }, + { "-delay", ".delay", XrmoptionSepArg, 0 }, + { "-program", ".program", XrmoptionSepArg, 0 }, + { "-pipe", ".usePty", XrmoptionNoArg, "False" }, + { "-pty", ".usePty", XrmoptionNoArg, "True" }, + { "-meta", ".metaSendsESC", XrmoptionNoArg, "False" }, + { "-esc", ".metaSendsESC", XrmoptionNoArg, "True" }, + { "-bs", ".swapBSDEL", XrmoptionNoArg, "False" }, + { "-del", ".swapBSDEL", XrmoptionNoArg, "True" }, + { 0, 0, 0, 0 } +}; + + +XSCREENSAVER_MODULE ("Phosphor", phosphor) diff --git a/hacks/phosphor.man b/hacks/phosphor.man new file mode 100644 index 00000000..154599c5 --- /dev/null +++ b/hacks/phosphor.man @@ -0,0 +1,173 @@ +.de EX \"Begin example +.ne 5 +.if n .sp 1 +.if t .sp .5 +.nf +.in +.5i +.. +.de EE +.fi +.in -.5i +.if n .sp 1 +.if t .sp .5 +.. +.TH XScreenSaver 1 "5-May-2004" "X Version 11" +.SH NAME +phosphor - simulates an old terminal with long-sustain phosphor +.SH SYNOPSIS +.B phosphor +[\-display \fIhost:display.screen\fP] [\-window] [\-root] [\-install] +[\-visual \fIvisual\fP] [\-font \fIfont\fP] [\-scale \fIint\fP] +[\-ticks \fIint\fP] [\-delay \fIusecs\fP] [\-program \fIcommand\fP] +[\-meta] [\-esc] [\-bs] [\-del] +[\-fps] +.SH DESCRIPTION +The \fIphosphor\fP program draws text on the screen in a very large +pixelated font that looks like an old low resolution dumb tty. The +pixels flare and fade out as if the phosphor was very +long-sustain. It is also a fully functional vt100 terminal emulator. +.SH OPTIONS +.I phosphor +accepts the following options: +.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 \-install +Install a private colormap for the window. +.TP 8 +.B \-visual \fIvisual\fP\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 \-font \fIfont-name\fP +The X font to use. Phosphor can take any font and scale it up to pixelate +it. The default is \fIfixed\fP. +.TP 8 +.B \-scale \fIint\fP +How much to scale the font up: in other words, the size in real pixels of +the simulated pixels. Default 6. +.TP 8 +.B \-ticks \fIint\fP +The number of colors to use when fading to black. Default 20. +.TP 8 +.B \-delay \fIusecs\fP +The speed of the terminal: how long to wait between drawing each character. +Default 50000, or about 1/20th second. +.TP 8 +.B \-pty +Launch the sub-program under a PTY, so that it can address the screen +directly. This is the default. +.TP 8 +.B \-pipe +Launch the sub-program at the end of a pipe: do not let it address the +screen directly. +.TP 8 +.B \-program \fIsh-command\fP +The command to run to generate the text to display. This option may +be any string acceptable to /bin/sh. The program will be run at the +end of a pty or pipe, and any characters that it prints to \fIstdout\fP +will be printed on phosphor's window. The characters will be printed +artificially slowly, as per the \fI\-delay\fP option above. If the +program exits, it will be launched again after 5 seconds. + +For example: +.EX +phosphor -program 'cat /usr/src/linux*/README' +phosphor -program 'ping localhost' +phosphor -program 'ps -e' +phosphor -program 'od -txC -w6 /dev/random' +phosphor -program 'cat /dev/random' +phosphor -scale 2 -geom =1280x1024 -program 'top' +phosphor -scale 4 -geom =1280x1024 \\ + -program 'mtr www.kernel.org' +phosphor -program 'xemacs -nw -q -f life' +phosphor -scale 5 -geom =1280x1024 \\ + -program 'xemacs -nw -q --eval "(hanoi 5)"' +.EE +If you have the +.BR festival (1) +text-to-speech system installed, you can have it read the screen as +phosphor prints it: +.EX +phosphor -program \\ + 'xscreensaver-text | tee /dev/stderr | festival --tts' +.EE +You can also use \fIphosphor\fP as a lo-fi replacement for the +.BR xterm (1) +and +.BR gnome-terminal (1) +terminal emulators: +.EX +phosphor -delay 0 -program tcsh +.EE +.TP 8 +.B \-esc +When the user types a key with the Alt or Meta keys held down, send an +ESC character first. This is the default. +.TP 8 +.B \-meta +When Meta or Alt are held down, set the high bit on the character instead. +.TP 8 +.B \-del +Swap Backspace and Delete. This is the default. +.TP 8 +.B \-bs +Do not swap Backspace and Delete. +.TP 8 +.B \-fps +Display the current frame rate and CPU load. +.SH TERMINAL EMULATION +By default, \fIphosphor\fP allocates a pseudo-tty for the sub-process to +run under. This has the desirable side effect that the program will be +able to use +.BR ioctl (2) +to fetch information about terminal parameters and window size, which +many programs (such as +.BR top (1)) +need to run properly. \fIphosphor\fP will also set the environment +variable \fITERM\fP to \fIvt100\fP in the child process. + +Any characters typed on the phosphor window will be passed along to +the sub-process. (Note that this only works when running in "window" +mode, not when running in \fI\-root\fP mode under xscreensaver.) +.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. +.TP 8 +.B TERM +to inform the sub-process of the type of terminal emulation. +.SH SEE ALSO +.BR xscreensaver (1), +.BR xscreensaver-text (1), +.BR fortune (1), +.BR apple2 (MANSUFFIX), +.BR starwars (MANSUFFIX), +.BR fontglide (MANSUFFIX), +.BR ljlatest (MANSUFFIX), +.BR dadadodo (1), +.BR webcollage (MANSUFFIX), +.BR driftnet (1) +.BR EtherPEG , +.BR EtherPeek , +.BR console_codes (4). +.SH COPYRIGHT +Copyright \(co 1999 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 , 27-Apr-99. +Pty and vt100 emulation by Fredrik Tolf . diff --git a/hacks/piecewise.c b/hacks/piecewise.c new file mode 100644 index 00000000..af01a99d --- /dev/null +++ b/hacks/piecewise.c @@ -0,0 +1,997 @@ +/* piecewise, 21jan2003 + * Geoffrey Irving + * + * 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. + */ + +#include +#include +#include "screenhack.h" + +#ifdef HAVE_DOUBLE_BUFFER_EXTENSION +# include "xdbe.h" +#endif /* HAVE_DOUBLE_BUFFER_EXTENSION */ + +#if !defined( __GNUC__ ) && !defined(__cplusplus) && !defined(c_plusplus) +#undef inline +#define inline /* */ +#endif + +#define X_PI (180 * 64) + +#define START 0 +#define CROSS 1 +#define FINISH 2 + +#define ARC_BUFFER_SIZE 256 + + +typedef struct _tree { + struct _tree *l, *r; /* left and right children */ + /* extra stuff would go here */ + } tree; + + +struct _fringe; + +typedef struct _circle { + int r; /* radius */ + double x, y; /* position */ + double dx, dy; /* velocity */ + + int visible; /* default visibility */ + struct _fringe *lo, *hi; /* lo and hi fringes */ + + int ni; /* number of intersections */ + int *i; /* sorted intersection list */ + } circle; + +typedef struct _fringe { + struct _fringe *l, *r; /* left and right children for splay trees */ + + circle *c; /* associated circle */ + int side; /* 0 for lo, 1 for hi */ + + int mni; /* size of intersection array */ + int ni; /* number of intersections */ + int *i; /* sorted intersection list */ + } fringe; + + +typedef struct _event { + struct _event *l, *r; /* left and right children for splay tree */ + + int kind; /* type of event */ + double x, y; /* position */ + fringe *lo, *hi; /* fringes */ + } event; + + +struct state { + Display *dpy; + Window window; + + double event_cut_y; + + double fringe_start_cut_x; + double fringe_start_cut_y; + + double fringe_double_cut_x; + double fringe_double_cut_y; + fringe *fringe_double_cut_lo; + fringe *fringe_double_cut_hi; + + int arc_buffer_count; + XArc arc_buffer[ARC_BUFFER_SIZE]; + + Bool dbuf; + XColor *colors; + XGCValues gcv; + GC erase_gc, draw_gc; + XWindowAttributes xgwa; + Pixmap b, ba, bb; /* double-buffering pixmap */ + +#ifdef HAVE_DOUBLE_BUFFER_EXTENSION + XdbeBackBuffer backb; +#endif /* HAVE_DOUBLE_BUFFER_EXTENSION */ + + int count, delay, ncolors, colorspeed, color_index, flags, iterations; + int color_iterations; + circle *circles; +}; + +typedef int (*cut)(struct state *, tree*); /* cut x is <, =, or > 0 given a <, =, or > x for some a */ + + + +/******** splaying code */ + +/* Top-down splay routine. Reference: + * "Self-adjusting Binary Search Trees", Sleator and Tarjan, + * JACM Volume 32, No 3, July 1985, pp 652-686. + * See page 668 for specific splay transformations */ + +static tree *splay(struct state *st, cut c, tree *t) +{ + int v, vv; + tree *l, *r; + tree **lr, **rl; + tree *x, *y, *z; + + if (!t) + return 0; + + /* initialization */ + x = t; + l = r = 0; + lr = &l; + rl = &r; + + /* top-down splaying loop */ + for (;;) { + v = c(st, x); + if (v == 0) + break; /*** success ***/ + else if (v < 0) { + y = x->l; + if (!y) + break; /*** trivial ***/ + else { + vv = c(st, y); + if (vv == 0) { + *rl = x; /*** zig ***/ + rl = &x->l; + x = y; + break; + } + else if (vv < 0) { + z = y->l; + if (!z) { + *rl = x; /*** zig ***/ + rl = &x->l; + x = y; + break; + } + else { + x->l = y->r; /*** zig-zig ***/ + y->r = x; + *rl = y; + rl = &y->l; + x = z; + } + } + else { /* vv > 0 */ + z = y->r; + if (!z) { + *rl = x; /*** zig ***/ + rl = &x->l; + x = y; + break; + } + else { /*** zig-zag ***/ + *lr = y; + lr = &y->r; + *rl = x; + rl = &x->l; + x = z; + } + } + } + } + else { /* v > 0 */ + y = x->r; + if (!y) + break; /*** trivial ***/ + else { + vv = c(st, y); + if (vv == 0) { + *lr = x; /*** zig ***/ + lr = &x->r; + x = y; + break; + } + else if (vv > 0) { + z = y->r; + if (!z) { + *lr = x; /*** zig ***/ + lr = &x->r; + x = y; + break; + } + else { + x->r = y->l; /*** zig-zig ***/ + y->l = x; + *lr = y; + lr = &y->r; + x = z; + } + } + else { /* vv < 0 */ + z = y->l; + if (!z) { + *lr = x; /*** zig ***/ + lr = &x->r; + x = y; + break; + } + else { /*** zig-zag ***/ + *rl = y; + rl = &y->l; + *lr = x; + lr = &x->r; + x = z; + } + } + } + } + } + + /* completion */ + *lr = x->l; + x->l = l; + *rl = x->r; + x->r = r; + return x; + } + +static tree *splay_min(tree *t) +{ + tree *r, **rl; + tree *x, *y, *z; + + if (!t) + return 0; + + x = t; + r = 0; + rl = &r; + + for (;;) { + y = x->l; + if (!y) + break; /*** trivial ***/ + else { + z = y->l; + if (!z) { + *rl = x; /*** zig ***/ + rl = &x->l; + x = y; + break; + } + else { + x->l = y->r; /*** zig-zig ***/ + y->r = x; + *rl = y; + rl = &y->l; + x = z; + } + } + } + + x->l = 0; + *rl = x->r; + x->r = r; + return x; + } + +static tree *splay_max(tree *t) +{ + tree *l, **lr; + tree *x, *y, *z; + + if (!t) + return 0; + + x = t; + l = 0; + lr = &l; + + for (;;) { + y = x->r; + if (!y) + break; /*** trivial ***/ + else { + z = y->r; + if (!z) { + *lr = x; /*** zig ***/ + lr = &x->r; + x = y; + break; + } + else { + x->r = y->l; /*** zig-zig ***/ + y->l = x; + *lr = y; + lr = &y->r; + x = z; + } + } + } + + *lr = x->l; + x->l = l; + x->r = 0; + return x; + } + +/******** circles and fringe */ + +static inline double fringe_x(fringe *f, double y) +{ + double dy, d; + dy = f->c->y - y; + d = sqrt(f->c->r * f->c->r - dy * dy); + return f->side ? f->c->x + d : f->c->x - d; + } + +static inline void fringe_add_intersection(fringe *f, double x, double y) +{ + f->ni++; + if (f->mni < f->ni) { + f->mni += 2; + f->i = realloc(f->i, sizeof(int) * f->mni); + } + f->i[f->ni-1] = rint(atan2(y - f->c->y, x - f->c->x) * X_PI / M_PI); + } + +static circle *init_circles(struct state *st, int n, int w, int h) +{ + int i, r0, dr, speed; + double v, a; + double minradius, maxradius; + fringe *s = malloc(sizeof(fringe) * n * 2); /* never freed */ + circle *c = malloc(sizeof(circle) * n); + + speed = get_integer_resource(st->dpy, "speed", "Speed"); + minradius = get_float_resource(st->dpy, "minradius", "Float"); + maxradius = get_float_resource(st->dpy, "maxradius", "Float"); + if (maxradius < minradius) + maxradius = minradius; + + r0 = ceil(minradius * h); + dr = floor(maxradius * h) - r0 + 1; + + for (i=0;i 0) ? random() % dr : 0); + c[i].x = c[i].r + frand(w - 1 - 2 * c[i].r); + c[i].y = c[i].r + frand(h - 1 - 2 * c[i].r); + c[i].visible = random() & 1; + + c[i].ni = 0; + c[i].i = 0; + + a = frand(2 * M_PI); + v = (1 + frand(0.5)) * speed / 10.0; + c[i].dx = v * cos(a); + c[i].dy = v * sin(a); + + c[i].lo = s+i+i; + c[i].hi = s+i+i+1; + c[i].lo->c = c[i].hi->c = c+i; + c[i].lo->side = 0; + c[i].hi->side = 1; + c[i].lo->mni = c[i].lo->ni = c[i].hi->mni = c[i].hi->ni = 0; + c[i].lo->i = c[i].hi->i = 0; + } + + return c; + } + +/* this is a hack, but I guess that's what I writing anyways */ +static void tweak_circle(circle *c) +{ + c->x += frand(2) - 1; + c->y += frand(1) + 0.1; + } + +static void move_circle(circle *c, int w, int h) +{ + c->x += c->dx; + if (c->x < c->r) { + c->x = c->r; + c->dx = -c->dx; + } + else if (c->x >= w - c->r) { + c->x = w - 1 - c->r; + c->dx = -c->dx; + } + c->y += c->dy; + if (c->y < c->r) { + c->y = c->r; + c->dy = -c->dy; + } + else if (c->y >= h - c->r) { + c->y = h - 1 - c->r; + c->dy = -c->dy; + } + } + +/******** event queue */ + +static int event_cut(struct state *st, event *e) +{ + return st->event_cut_y == e->y ? 0 : st->event_cut_y < e->y ? -1 : 1; + } + +static void event_insert(struct state *st, event **eq, event *e) +{ + if (!*eq) { + e->l = e->r = 0; + *eq = e; + return; /* avoid leak */ + } + + st->event_cut_y = e->y; + *eq = (event*)splay(st, (cut)event_cut, (tree*)*eq); + + if (e->y == (*eq)->y) { + if (!((e->lo == (*eq)->lo && e->hi == (*eq)->hi) || (e->lo == (*eq)->hi && e->hi == (*eq)->lo))) { + e->l = (*eq)->l; + e->r = 0; /* doing this instead of dying might be dangerous */ + (*eq)->l = e; + } + else + free(e); /* don't leak! */ + } + else if (e->y < (*eq)->y) { + e->l = (*eq)->l; + e->r = *eq; + (*eq)->l = 0; + *eq = e; + } + else { + e->l = *eq; + e->r = (*eq)->r; + (*eq)->r = 0; + *eq = e; + } + } + +static void circle_start_event(struct state *st, event **eq, circle *c) +{ + event *s; + s = malloc(sizeof(event)); + s->kind = START; + s->x = c->x; + s->y = c->y - c->r; + s->lo = c->lo; + s->hi = c->hi; + event_insert(st, eq, s); + } + +static void circle_finish_event(struct state *st, event **eq, circle *c) +{ + event *f; + f = malloc(sizeof(event)); + f->kind = FINISH; + f->x = c->x; + f->y = c->y + c->r; + f->lo = c->lo; + f->hi = c->hi; + event_insert(st, eq, f); + } + +static event *event_next(event **eq) +{ + event *e; + if (!*eq) + return 0; + else { + e = (event*)splay_min((tree*)*eq); + *eq = e->r; + return e; + } + } + +static void event_shred(event *e) +{ + if (e) { + event_shred(e->l); + event_shred(e->r); + free(e); + } + } + +/******** fringe intersection */ + +static inline int check_fringe_intersection(double ye, fringe *lo, fringe *hi, double x, double y) +{ + return ye <= y && ((x < lo->c->x) ^ lo->side) && ((x < hi->c->x) ^ hi->side); + } + +static void fringe_intersect(struct state *st, event **eq, double y, fringe *lo, fringe *hi) +{ + event *e; + double dx, dy, sd, rs, rd, d, sx, sy, rp, sqd; + double x1, y1, x2, y2; + + if (lo->c == hi->c) + return; + + dx = hi->c->x - lo->c->x; + dy = hi->c->y - lo->c->y; + sd = dx * dx + dy * dy; + + if (sd == 0) + return; + + rs = hi->c->r + lo->c->r; + rd = hi->c->r - lo->c->r; + d = (rd * rd - sd) * (sd - rs * rs); + + if (d <= 0) + return; + + sd = 0.5 / sd; + rp = rs * rd; + sqd = sqrt(d); + sx = (lo->c->x + hi->c->x) / 2; + sy = (lo->c->y + hi->c->y) / 2; + x1 = sx + sd * (dy * sqd - dx * rp); + y1 = sy - sd * (dx * sqd + dy * rp); + x2 = sx - sd * (dy * sqd + dx * rp); + y2 = sy + sd * (dx * sqd - dy * rp); + + #define CHECK(xi, yi) (y <= yi && ((xi < lo->c->x) ^ lo->side) && ((xi < hi->c->x) ^ hi->side)) + + #define ADD_CROSS(xi, yi, ilo, ihi) { \ + e = malloc(sizeof(event)); /* #### LEAK */ \ + e->kind = CROSS; \ + e->x = xi; e->y = yi; \ + e->lo = ilo; e->hi = ihi; \ + event_insert(st, eq, e); \ + } + + if (CHECK(x1, y1)) { + if (CHECK(x2, y2)) { + if (y1 < y2) { + ADD_CROSS(x1, y1, lo, hi); + ADD_CROSS(x2, y2, hi, lo); + } + else { + ADD_CROSS(x1, y1, hi, lo); + ADD_CROSS(x2, y2, lo, hi); + } + } + else + ADD_CROSS(x1, y1, lo, hi); + } + else if (CHECK(x2, y2)) + ADD_CROSS(x2, y2, lo, hi); + + return; + } + +/******** fringe trees and event handling */ + +#define PANIC ((fringe*)1) /* by alignment, no fringe should every be 1 */ + +static fringe *check_lo(struct state *st, event **eq, double y, fringe *f, fringe *hi) +{ + if (f) { + f = (fringe*)splay_max((tree*)f); + fringe_intersect(st, eq, y, f, hi); + } + return f; + } + +static fringe *check_hi(struct state *st, event **eq, double y, fringe *lo, fringe *f) +{ + if (f) { + f = (fringe*)splay_min((tree*)f); + fringe_intersect(st, eq, y, lo, f); + } + return f; + } + +static int fringe_start_cut(struct state *st, fringe *f) +{ + double x = fringe_x(f, st->fringe_start_cut_y); + return st->fringe_start_cut_x == x ? 0 : st->fringe_start_cut_x < x ? -1 : 1; + } + +static fringe *fringe_start(struct state *st, event **eq, fringe *f, double x, double y, fringe *lo, fringe *hi) +{ + double sx; + + if (!f) { + circle_finish_event(st, eq, lo->c); + lo->l = 0; + lo->r = hi; + hi->l = hi->r = 0; + return lo; + } + + st->fringe_start_cut_x = x; + st->fringe_start_cut_y = y; + f = (fringe*)splay(st, (cut)fringe_start_cut, (tree*)f); + + sx = fringe_x(f, y); + if (x == sx) { /* time to cheat my way out of handling degeneracies */ + tweak_circle(lo->c); + circle_start_event(st, eq, lo->c); + return f; + } + else if (x < sx) { + circle_finish_event(st, eq, lo->c); + f->l = check_lo(st, eq, y, f->l, lo); + fringe_intersect(st, eq, y, hi, f); + lo->l = f->l; + lo->r = f; + f->l = hi; + hi->l = hi->r = 0; + return lo; + } + else { + circle_finish_event(st, eq, lo->c); + fringe_intersect(st, eq, y, f, lo); + f->r = check_hi(st, eq, y, hi, f->r); + hi->r = f->r; + hi->l = f; + f->r = lo; + lo->l = lo->r = 0; + return hi; + } + } + +static int fringe_double_cut(struct state *st, fringe *f) +{ + double x; + if (f == st->fringe_double_cut_lo || f == st->fringe_double_cut_hi) + return 0; + x = fringe_x(f, st->fringe_double_cut_y); + return st->fringe_double_cut_x == x ? 0 : st->fringe_double_cut_x < x ? -1 : 1; + } + +static int fringe_double_splay(struct state *st, fringe *f, double x, double y, fringe *lo, fringe *hi) +{ + st->fringe_double_cut_x = x; + st->fringe_double_cut_y = y; + st->fringe_double_cut_lo = lo; + st->fringe_double_cut_hi = hi; + f = (fringe*)splay(st, (cut)fringe_double_cut, (tree*)f); + + if (f == lo) + return (f->r = (fringe*)splay_min((tree*)f->r)) == hi; + else if (f == hi) + return (f->l = (fringe*)splay_max((tree*)f->l)) == lo; + else + return 0; + } + +static fringe *fringe_cross(struct state *st, event **eq, fringe *f, double x, double y, fringe *lo, fringe *hi) +{ + fringe *l, *r; + if (!fringe_double_splay(st, f, x, y, lo, hi)) + return PANIC; + l = check_lo(st, eq, y, lo->l, hi); + r = check_hi(st, eq, y, lo, hi->r); + lo->l = hi; + lo->r = r; + hi->l = l; + hi->r = 0; + return lo; + } + +static fringe *fringe_finish(struct state *st, event **eq, fringe *f, double x, double y, fringe *lo, fringe *hi) +{ + if (!fringe_double_splay(st, f, x, y, lo, hi)) + return PANIC; + else if (!lo->l) + return hi->r; + else if (!hi->r) + return lo->l; + else { + lo->l = (fringe*)splay_max((tree*)lo->l); + hi->r = (fringe*)splay_min((tree*)hi->r); + fringe_intersect(st, eq, y, lo->l, hi->r); + lo->l->r = hi->r; + hi->r->l = 0; + return lo->l; + } + } + +/******** plane sweep */ + +static void sweep(struct state *st, int n, circle *c) +{ + int i; + event *eq, *e; + fringe *f; + + RESTART: + #define CHECK_PANIC() \ + if (f == PANIC) { \ + free(e); \ + event_shred(eq); \ + for (i=0;ini = c[i].hi->ni = 0; \ + } \ + goto RESTART; \ + } + + eq = 0; + for (i=0;ikind) { + case START: + f = fringe_start(st, &eq, f, e->x, e->y, e->lo, e->hi); + break; + case CROSS: + f = fringe_cross(st, &eq, f, e->x, e->y, e->lo, e->hi); + CHECK_PANIC(); + fringe_add_intersection(e->lo, e->x, e->y); + fringe_add_intersection(e->hi, e->x, e->y); + break; + case FINISH: + f = fringe_finish(st, &eq, f, e->x, e->y, e->lo, e->hi); + CHECK_PANIC(); + break; + } + free(e); + } + } + +/******** circle drawing */ + +static void adjust_circle_visibility(circle *c) +{ + int i, j, n, a; + int *in; + n = c->lo->ni + c->hi->ni; + in = malloc(sizeof(int) * n); + for (i=0;ihi->ni;i++) + in[i] = c->hi->i[i]; + for (i=c->lo->ni-1;i>=0;i--) + in[n-i-1] = c->lo->i[i] > 0 ? c->lo->i[i] : c->lo->i[i] + 2 * X_PI; + c->lo->ni = c->hi->ni = 0; + + i = j = 0; + a = 0; + while (i < n && j < c->ni) /* whee */ + a = (in[i] < c->i[j] ? in[i++] : c->i[j++]) - a; + while (i < n) + a = in[i++] - a; + while (j < c->ni) + a = c->i[j++] - a; + + if (a > X_PI) + c->visible = !c->visible; + free(c->i); + c->ni = n; + c->i = in; + } + +static void flush_arc_buffer(struct state *st, Drawable w, GC gc) +{ + if (st->arc_buffer_count) { + XDrawArcs(st->dpy, w, gc, st->arc_buffer, st->arc_buffer_count); + st->arc_buffer_count = 0; + } + } + +static void draw_circle(struct state *st, Drawable w, GC gc, circle *c) +{ + int i, xi, yi, di; + adjust_circle_visibility(c); + + xi = rint(c->x - c->r); + yi = rint(c->y - c->r); + di = c->r << 1; + + #define ARC(p, a1, a2) { \ + if (((p) & 1) ^ c->visible) { \ + st->arc_buffer[st->arc_buffer_count].x = xi; \ + st->arc_buffer[st->arc_buffer_count].y = yi; \ + st->arc_buffer[st->arc_buffer_count].width = di; \ + st->arc_buffer[st->arc_buffer_count].height = di; \ + st->arc_buffer[st->arc_buffer_count].angle1 = -(a1); \ + st->arc_buffer[st->arc_buffer_count].angle2 = (a1) - (a2); \ + st->arc_buffer_count++; \ + if (st->arc_buffer_count == ARC_BUFFER_SIZE) \ + flush_arc_buffer(st, w, gc); \ + } \ + } + + if (!c->ni) + ARC(0, 0, 2 * X_PI) + else + ARC(0, c->i[c->ni-1], c->i[0] + 2 * X_PI) + for (i=1;ini;i++) + ARC(i, c->i[i-1], c->i[i]) + } + +/******** toplevel */ + +static void +check_for_leaks (void) +{ +#ifdef HAVE_SBRK + static unsigned long early_brk = 0; + unsigned long max = 30 * 1024 * 1024; /* 30 MB */ + int b = (unsigned long) sbrk(0); + if (early_brk == 0) + early_brk = b; + else if (b > early_brk + max) + { + fprintf (stderr, "%s: leaked %lu MB -- aborting!\n", + progname, ((b - early_brk) >> 20)); + exit (1); + } +#endif /* HAVE_SBRK */ +} + +static void * +piecewise_init (Display *dd, Window ww) +{ + struct state *st = (struct state *) calloc (1, sizeof(*st)); + st->dpy = dd; + st->window = ww; + + st->count = get_integer_resource(st->dpy, "count", "Integer"); + st->delay = get_integer_resource(st->dpy, "delay", "Integer"); + st->ncolors = get_integer_resource(st->dpy, "ncolors", "Integer"); + st->colorspeed = get_integer_resource(st->dpy, "colorspeed", "Integer"); + st->dbuf = get_boolean_resource(st->dpy, "doubleBuffer", "Boolean"); + +# ifdef HAVE_COCOA /* Don't second-guess Quartz's double-buffering */ + st->dbuf = False; +# endif + + st->color_iterations = st->colorspeed ? 100 / st->colorspeed : 100000; + if (!st->color_iterations) + st->color_iterations = 1; + + XGetWindowAttributes(st->dpy, st->window, &st->xgwa); + st->colors = calloc(sizeof(XColor), st->ncolors); + + if (get_boolean_resource(st->dpy, "mono", "Boolean")) { + MONO: + st->ncolors = 1; + st->colors[0].pixel = get_pixel_resource(st->dpy, st->xgwa.colormap, "foreground", "Foreground"); + } + else { + make_color_loop(st->dpy, st->xgwa.colormap, 0, 1, 1, 120, 1, 1, 240, 1, 1, st->colors, &st->ncolors, True, False); + if (st->ncolors < 2) + goto MONO; + } + + if (st->dbuf) { +#ifdef HAVE_DOUBLE_BUFFER_EXTENSION + st->b = st->backb = xdbe_get_backbuffer(st->dpy, st->window, XdbeUndefined); +#endif /* HAVE_DOUBLE_BUFFER_EXTENSION */ + + if (!st->b) { + st->ba = XCreatePixmap(st->dpy, st->window, st->xgwa.width, st->xgwa.height,st->xgwa.depth); + st->bb = XCreatePixmap(st->dpy, st->window, st->xgwa.width, st->xgwa.height,st->xgwa.depth); + st->b = st->ba; + } + } + else + st->b = st->window; + + /* erasure gc */ + st->gcv.foreground = get_pixel_resource(st->dpy, st->xgwa.colormap, "background", "Background"); + st->erase_gc = XCreateGC (st->dpy, st->b, GCForeground, &st->gcv); + + /* drawing gc */ + st->flags = GCForeground; + st->color_index = random() % st->ncolors; + st->gcv.foreground = st->colors[st->color_index].pixel; + st->draw_gc = XCreateGC(st->dpy, st->b, st->flags, &st->gcv); + + /* initialize circles */ + st->circles = init_circles(st, st->count, st->xgwa.width, st->xgwa.height); + + st->iterations = 0; + + return st; +} + +static unsigned long +piecewise_draw (Display *dpy, Window window, void *closure) +{ + struct state *st = (struct state *) closure; + int i; + + XFillRectangle (st->dpy, st->b, st->erase_gc, 0, 0, st->xgwa.width, st->xgwa.height); + + sweep(st, st->count, st->circles); + for (i=0;icount;i++) { + draw_circle(st, st->b, st->draw_gc, st->circles+i); + move_circle(st->circles+i, st->xgwa.width, st->xgwa.height); + } + flush_arc_buffer(st, st->b, st->draw_gc); + + if (++st->iterations % st->color_iterations == 0) { + st->color_index = (st->color_index + 1) % st->ncolors; + XSetForeground(st->dpy, st->draw_gc, st->colors[st->color_index].pixel); + } + +#ifdef HAVE_DOUBLE_BUFFER_EXTENSION + if (st->backb) { + XdbeSwapInfo info[1]; + info[0].swap_window = st->window; + info[0].swap_action = XdbeUndefined; + XdbeSwapBuffers (st->dpy, info, 1); + } + else +#endif /* HAVE_DOUBLE_BUFFER_EXTENSION */ + if (st->dbuf) { + XCopyArea (st->dpy, st->b, st->window, st->erase_gc, 0, 0, st->xgwa.width, st->xgwa.height, 0, 0); + st->b = (st->b == st->ba ? st->bb : st->ba); + } + + check_for_leaks(); + return st->delay; +} + +static void +piecewise_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 +piecewise_event (Display *dpy, Window window, void *closure, XEvent *event) +{ + return False; +} + +static void +piecewise_free (Display *dpy, Window window, void *closure) +{ + struct state *st = (struct state *) closure; + free (st); +} + + + +static const char *piecewise_defaults [] = { + ".background: black", + ".foreground: white", + "*delay: 10000", + "*speed: 15", + "*ncolors: 256", + ".colorspeed: 10", + + ".count: 32", + ".minradius: 0.05", + ".maxradius: 0.2", + + "*doubleBuffer: True", +#ifdef HAVE_DOUBLE_BUFFER_EXTENSION + "*useDBE: True", +#endif /* HAVE_DOUBLE_BUFFER_EXTENSION */ + 0 + }; + +static XrmOptionDescRec piecewise_options [] = { + { "-delay", ".delay", XrmoptionSepArg, 0 }, + { "-ncolors", ".ncolors", XrmoptionSepArg, 0 }, + { "-speed", ".speed", XrmoptionSepArg, 0 }, + { "-colorspeed", ".colorspeed", XrmoptionSepArg, 0 }, + + { "-count", ".count", XrmoptionSepArg, 0 }, + { "-minradius", ".minradius", XrmoptionSepArg, 0 }, + { "-maxradius", ".maxradius", XrmoptionSepArg, 0 }, + + { "-db", ".doubleBuffer", XrmoptionNoArg, "True" }, + { "-no-db", ".doubleBuffer", XrmoptionNoArg, "False" }, + { 0, 0, 0, 0 } + }; + + +XSCREENSAVER_MODULE ("Piecewise", piecewise) diff --git a/hacks/piecewise.man b/hacks/piecewise.man new file mode 100644 index 00000000..1d313bfa --- /dev/null +++ b/hacks/piecewise.man @@ -0,0 +1,77 @@ +.TH XScreenSaver 1 "" "X Version 11" +.SH NAME +piecewise - lots of moving circles intersecting in interesting ways. +.SH SYNOPSIS +.B piecewise +[\-display \fIhost:display.screen\fP] +[\-visual \fIvisual\fP] +[\-window] +[\-root] +[\-delay \fInumber\fP] +[\-count \fInumber\fP] +[\-ncolors \fInumber\fP] +[\-colorspeed \fInumber\fP] +[\-minradius \fInumber\fP] +[\-maxradius \fInumber\fP] +[\-no-db] +[\-fps] +.SH DESCRIPTION +This draws a bunch of moving circles which switch from visibility to invisibility +when they intersect. +.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: 5000 (0.01 seconds.). +.TP 8 +.B \-count \fInumber\fP +Number of circles. Default: 32. +.TP 8 +.B \-ncolors \fInumber\fP +Number of colors, only one of which is used at a time. Default: 256. +.TP 8 +.B \-colorspeed \fInumber\fP +How fast the color changes (0 - 100). Default: 10. +.TP 8 +.B \-minradius \fInumber\fP +Minimum circle radius (as a proportion of screen height). Default: 0.05. +.TP 8 +.B \-maxradius \fInumber\fP +Maximum circle radius (as a proportion of screen height). Default: 0.2. +.TP 8 +.B \-db | \-no-db +Whether to double buffer. +.TP 8 +.B \-fps +Display the current frame rate and CPU load. +.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 2003 by Geoffrey Irving. 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 +Geoffrey Irving. diff --git a/hacks/polyominoes.c b/hacks/polyominoes.c new file mode 100644 index 00000000..c7b84a74 --- /dev/null +++ b/hacks/polyominoes.c @@ -0,0 +1,2381 @@ +/* -*- Mode: C; tab-width: 4 -*- */ +/* polyominoes --- Shows attempts to place polyominoes into a rectangle */ + +#if 0 +static const char sccsid[] = "@(#)polyominoes.c 5.01 2000/12/18 xlockmore"; +#endif + +/* + * Copyright (c) 2000 by Stephen Montgomery-Smith + * + * Permission to use, copy, modify, and distribute this software and its + * documentation for any purpose and without fee is hereby granted, + * provided that the above copyright notice appear in all copies and that + * both that copyright notice and this permission notice appear in + * supporting documentation. + * + * This file is provided AS IS with no warranties of any kind. The author + * shall have no liability with respect to the infringement of copyrights, + * trade secrets or any patents by this file or any part thereof. In no + * event will the author be liable for any lost revenue or profits or + * other special, indirect and consequential damages. + * + * Revision History: + * 07-Jan-2001: Made improvement to the search algorithm for the puzzles + * involving identical polyominoes (via the variable + * reason_to_not_attach). By Stephen Montgomery-Smith. + * 20-Dec-2000: Added more puzzles at David Bagley's request. + * 27-Nov-2000: Adapted from euler2d.c Copyright (c) 2000 by Stephen + * Montgomery-Smith + * 05-Jun-2000: Adapted from flow.c Copyright (c) 1996 by Tim Auckland + * 18-Jul-1996: Adapted from swarm.c Copyright (c) 1991 by Patrick J. Naughton. + * 31-Aug-1990: Adapted from xswarm by Jeff Butterworth. (butterwo@ncsc.org) + */ + +#ifdef STANDALONE +# define MODE_polyominoes +#define DEFAULTS "*delay: 10000 \n" \ + "*cycles: 2000 \n" \ + "*ncolors: 64 \n" \ + "*fpsSolid: true \n" \ + +# define polyominoes_handle_event 0 +# define SMOOTH_COLORS +# include "xlockmore.h" /* in xscreensaver distribution */ +# include "erase.h" +#else /* STANDALONE */ +# include "xlock.h" /* in xlockmore distribution */ +#endif /* STANDALONE */ + +#ifdef MODE_polyominoes +#define DEF_IDENTICAL "False" +#define DEF_PLAIN "False" + +static Bool identical; +static Bool plain; + +static XrmOptionDescRec opts[] = +{ + {"-identical", ".polyominoes.identical", XrmoptionNoArg, "on"}, + {"+identical", ".polyominoes.identical", XrmoptionNoArg, "off"}, + {"-plain", ".polyominoes.plain", XrmoptionNoArg, "on"}, + {"+plain", ".polyominoes.plain", XrmoptionNoArg, "off"} +}; +static argtype vars[] = +{ + {&identical, "identical", "Identical", DEF_IDENTICAL, t_Bool}, + {&plain, "plain", "Plain", DEF_PLAIN, t_Bool} +}; +static OptionStruct desc[] = +{ + {"-/+identical", "turn on/off puzzles where the polyomino pieces are identical"}, + {"-/+plain", "turn on/off plain pieces"} +}; + +ENTRYPOINT ModeSpecOpt polyominoes_opts = +{sizeof opts / sizeof opts[0], opts, + sizeof vars / sizeof vars[0], vars, desc}; + +#ifdef USE_MODULES +ModStruct polyominoes_description = { + "polyominoes", "init_polyominoes", "draw_polyominoes", "release_polyominoes", + "refresh_polyominoes", "init_polyominoes", (char *) NULL, &polyominoes_opts, + 6000, 1, 8192, 1, 64, 1.0, "", + "Shows attempts to place polyominoes into a rectangle", 0, NULL +}; + +#endif + +/* Each polyomino is described by several quantities: + len: the number of squares in the polyomino; + point: the list of points; + tranform_len: the number of items in transform_list; + transform_list: a list of transformations that need to be done in order + to get all rotations and reflections (see the function + transform below); + max_white: the maximum number of white squares covered if polyomino + is placed on a chess board; + color: it's display color; + attached: whether it is currently attached to the rectangle; + attach_point: point on rectangle where attached; + point_no: the number of the point where it is attached; + transform_index: which element of transform_list is currently being used. +*/ + +typedef struct {int x,y;} point_type; + +typedef struct {int len; point_type *point; + int transform_len, transform_list[8], max_white; + unsigned long color; + int attached; + point_type attach_point; + int point_no, transform_index;} polyomino_type; + + +typedef struct _polyominoesstruct{ + int wait; + + int width, height; + unsigned border_color; + int mono; + + polyomino_type *polyomino; + int nr_polyominoes; + Bool identical, use3D; + int *attach_list; + int nr_attached; + +/* The array that tells where the polyominoes are attached. */ + int *array, *changed_array; + +/* These specify the dimensions of how things appear on the screen. */ + int box, x_margin, y_margin; + +/* These booleans decide in which way to try to attach the polyominoes. */ + int left_right, top_bottom; + +/* Bitmaps for display purposes. */ + int use_bitmaps; + XImage *bitmaps[256]; + +/* Structures used for display purposes if there is not enough memory + to allocate bitmaps (or if the screen is small). */ + XSegment *lines; + XRectangle *rectangles; + +/* A procedure that may be used to see if certain configurations + are permissible. */ + int (*check_ok)(struct _polyominoesstruct *sp); + +/* Tells program that solutions are invariant under 180 degree + rotation. */ + int rot180; + +/* This is a variable used in the case that all the polyominoes are identical + that will further prune the search tree. Essentially it will be + int reason_to_not_attach[nr_polynominoes][nr_polynominoes]; + Let me first explain the effect it is trying to overcome. Often + in the search process, the computer will first try to fit shapes into + a region (call it A), and then into another region (call it B) that is + essentially disjoint from A. But it may be that it just is not possible + to fit shapes into region B. So it fits something into A, and then + tries to fit something into B. Failing it fits something else into A, + and then tried again to fit something into B. Thus the program is trying + again and again to fit something into B, when it should have figured out + the first time that it was impossible. + + To overcome this, everytime we try to attach a piece, we collect the reasons + why it cannot be attached (a boolean for each piece that got in the way). + If we see that a piece cannot be attached, we detach the other pieces until + we have detached at least one piece for which the boolean reason_to_not_attach + is set. +*/ + int *reason_to_not_attach; + + int counter; + +#ifdef STANDALONE + eraser_state *eraser; +#endif +} polyominoesstruct; + +#define ARRAY(x,y) (sp->array[(x)*sp->height+(y)]) +#define CHANGED_ARRAY(x,y) (sp->changed_array[(x)*sp->height+(y)]) +#define ARRAY_P(p) (sp->array[(p).x*sp->height+(p).y]) +#define CHANGED_ARRAY_P(p) (sp->changed_array[(p).x*sp->height+(p).y]) +#define ARR(x,y) (((x)<0||(x)>=sp->width||(y)<0||(y)>=sp->height)?-2:ARRAY(x,y)) + +#define REASON_TO_NOT_ATTACH(x,y) (sp->reason_to_not_attach[(x)*sp->nr_polyominoes+(y)]) + +#define ROUND8(n) ((((n)+7)/8)*8) + +/* Defines to index the bitmaps. A set bit indicates that an edge or + corner is required. */ +#define LEFT (1<<0) +#define RIGHT (1<<1) +#define UP (1<<2) +#define DOWN (1<<3) +#define LEFT_UP (1<<4) +#define LEFT_DOWN (1<<5) +#define RIGHT_UP (1<<6) +#define RIGHT_DOWN (1<<7) +#define IS_LEFT(n) ((n) & LEFT) +#define IS_RIGHT(n) ((n) & RIGHT) +#define IS_UP(n) ((n) & UP) +#define IS_DOWN(n) ((n) & DOWN) +#define IS_LEFT_UP(n) ((n) & LEFT_UP) +#define IS_LEFT_DOWN(n) ((n) & LEFT_DOWN) +#define IS_RIGHT_UP(n) ((n) & RIGHT_UP) +#define IS_RIGHT_DOWN(n) ((n) & RIGHT_DOWN) + +/* Defines to access the bitmaps. */ +#define BITNO(x,y) ((x)+(y)*ROUND8(sp->box)) +#define SETBIT(n,x,y) {data[BITNO(x,y)/8] |= 1<<(BITNO(x,y)%8);} +#define RESBIT(n,x,y) {data[BITNO(x,y)/8] &= ~(1<<(BITNO(x,y)%8));} +#define TWOTHIRDSBIT(n,x,y) {if ((x+y-1)%3) SETBIT(n,x,y) else RESBIT(n,x,y)} +#define HALFBIT(n,x,y) {if ((x-y)%2) SETBIT(n,x,y) else RESBIT(n,x,y)} +#define THIRDBIT(n,x,y) {if (!((x-y-1)%3)) SETBIT(n,x,y) else RESBIT(n,x,y)} +#define THREEQUARTERSBIT(n,x,y) \ + {if ((y%2)||((x+2+y/2+1)%2)) SETBIT(n,x,y) else RESBIT(n,x,y)} +#define NOTHALFBIT(n,x,y) {if ((x-y)%2) RESBIT(n,x,y) else SETBIT(n,x,y)} + +/* Parameters for bitmaps. */ +#define G ((sp->box/45)+1) /* 1/2 of gap between polyominoes. */ +#define T ((sp->box<=12)?1:(G*2)) /* Thickness of walls of polyominoes. */ +#define R ((sp->box<=12)?1:(G*6)) /* Amount of rounding. */ +#define RT ((sp->box<=12)?1:(G*3)) /* Thickness of wall of rounded parts. + Here 3 is an approximation to 2 sqrt(2). */ +#define RR 0 /* Roof ridge thickness */ + +#if 0 +/* A list of those bitmaps we need to create to display any pentomino. */ +/* (not used right now because it does not seem to work for hexonimoes.) */ + +static int bitmaps_needed[] = +{ + LEFT_UP|LEFT_DOWN|RIGHT_UP|RIGHT_DOWN, + + LEFT|RIGHT_UP|RIGHT_DOWN, + RIGHT|LEFT_UP|LEFT_DOWN, + UP|LEFT_DOWN|RIGHT_DOWN, + DOWN|LEFT_UP|RIGHT_UP, + LEFT|RIGHT_UP, + RIGHT|LEFT_UP, + UP|LEFT_DOWN, + DOWN|LEFT_UP, + LEFT|RIGHT_DOWN, + RIGHT|LEFT_DOWN, + UP|RIGHT_DOWN, + DOWN|RIGHT_UP, + +/* These needed for hexonimoes*/ + LEFT, + RIGHT, + UP, + DOWN, + LEFT_DOWN|RIGHT_UP|RIGHT_DOWN, + LEFT_UP|RIGHT_UP|RIGHT_DOWN, + LEFT_UP|LEFT_DOWN|RIGHT_DOWN, + LEFT_UP|LEFT_DOWN|RIGHT_UP, + + LEFT|UP|RIGHT_DOWN, + LEFT|DOWN|RIGHT_UP, + RIGHT|UP|LEFT_DOWN, + RIGHT|DOWN|LEFT_UP, + LEFT|UP, + LEFT|DOWN, + RIGHT|UP, + RIGHT|DOWN, + + LEFT|RIGHT, + UP|DOWN, + + RIGHT|UP|DOWN, + LEFT|UP|DOWN, + LEFT|RIGHT|DOWN, + LEFT|RIGHT|UP, + + -1 +}; + +static int bitmap_needed(int n) +{ + int i; + + for (i=0;bitmaps_needed[i]!=-1;i++) + if (n == bitmaps_needed[i]) + return 1; + return 0; +} + +#endif + +/* Some debugging routines. + +static void print_board(polyominoesstruct *sp) +{ + int x,y; + for (y=0;yheight;y++) { + for (x=0;xwidth;x++) + if (ARRAY(x,y) == -1) + fprintf(stderr," "); + else + fprintf(stderr,"%c",'a'+ARRAY(x,y)); + fprintf(stderr,"\n"); + } + fprintf(stderr,"\n"); +} + +static void print_points(point_type *point, int len) +{ + int i; + + for (i=0;ix=in.x-offset.x+attach_point.x; + out->y=in.y-offset.y+attach_point.y; + break; + case 1: out->x=-(in.y-offset.y)+attach_point.x; + out->y=in.x-offset.x+attach_point.y; + break; + case 2: out->x=-(in.x-offset.x)+attach_point.x; + out->y=-(in.y-offset.y)+attach_point.y; + break; + case 3: out->x=in.y-offset.y+attach_point.x; + out->y=-(in.x-offset.x)+attach_point.y; + break; + case 4: out->x=-(in.x-offset.x)+attach_point.x; + out->y=in.y-offset.y+attach_point.y; + break; + case 5: out->x=in.y-offset.y+attach_point.x; + out->y=in.x-offset.x+attach_point.y; + break; + case 6: out->x=in.x-offset.x+attach_point.x; + out->y=-(in.y-offset.y)+attach_point.y; + break; + case 7: out->x=-(in.y-offset.y)+attach_point.x; + out->y=-(in.x-offset.x)+attach_point.y; + break; + } +} + +static int first_poly_no(polyominoesstruct *sp) +{ + int poly_no; + + poly_no = 0; + while(poly_nonr_polyominoes && sp->polyomino[poly_no].attached) + poly_no++; + return poly_no; +} + +static void next_poly_no(polyominoesstruct *sp, int *poly_no) +{ + + if (sp->identical) { + *poly_no = sp->nr_polyominoes; + } else { + do { + (*poly_no)++; + } while (*poly_nonr_polyominoes && sp->polyomino[*poly_no].attached); + } +} + +/* check_all_regions_multiple_of looks for connected regions of + blank spaces, and returns 0 if it finds a connected region containing + a number of blanks that is not a multiple of n. +*/ + +static void count_adjacent_blanks(polyominoesstruct *sp, int *count, int x, int y, int blank_mark) +{ + + if (ARRAY(x,y) == -1) { + (*count)++; + ARRAY(x,y) = blank_mark; + if (x>=1) count_adjacent_blanks(sp, count,x-1,y,blank_mark); + if (xwidth-1) count_adjacent_blanks(sp, count,x+1,y,blank_mark); + if (y>=1) count_adjacent_blanks(sp, count,x,y-1,blank_mark); + if (yheight-1) count_adjacent_blanks(sp, count,x,y+1,blank_mark); + } +} + +static int check_all_regions_multiple_of(polyominoesstruct *sp, int n) +{ + int x,y,count,good = 1; + + for (x=0;xwidth && good;x++) for (y=0;yheight && good;y++) { + count = 0; + count_adjacent_blanks(sp, &count,x,y,-2); + good = count%n == 0; + } + + for (x=0;xwidth;x++) for (y=0;yheight;y++) + if (ARRAY(x,y) == -2) + ARRAY(x,y) = -1; + + return good; +} + +static int check_all_regions_positive_combination_of(polyominoesstruct *sp, int m, int n) +{ + int x,y,count,good = 1; + + for (x=0;xwidth && good;x++) for (y=0;yheight && good;y++) { + count = 0; + count_adjacent_blanks(sp, &count,x,y,-2); + good = 0; + for (;count>=0 && !good;count-=m) + good = count%n == 0; + } + + for (x=0;xwidth;x++) for (y=0;yheight;y++) + if (ARRAY(x,y) == -2) + ARRAY(x,y) = -1; + + return good; +} + +static int find_smallest_blank_component(polyominoesstruct *sp) +{ + int x,y,size,smallest_size,blank_mark,smallest_mark; + + smallest_mark = blank_mark = -10; + smallest_size = 1000000000; + for (x=0;xwidth;x++) for (y=0;yheight;y++) if (ARRAY(x,y) == -1) { + size = 0; + count_adjacent_blanks(sp, &size,x,y,blank_mark); + if (sizewidth;x++) for (y=0;yheight;y++) { + if (ARRAY(x,y) == -1 && (x+y)%2) whites++; + if (ARRAY(x,y) == -1 && (x+y+1)%2) blacks++; + } + for (poly_no=0;poly_nonr_polyominoes;poly_no++) if (!sp->polyomino[poly_no].attached) { + max_white += sp->polyomino[poly_no].max_white; + min_white += sp->polyomino[poly_no].len - sp->polyomino[poly_no].max_white; + } + return (min_white <= blacks && min_white <= whites + && blacks <= max_white && whites <= max_white); +} + +/* This routine looks at the point (x,y) and sees how many polyominoes + and all their various transforms may be attached there. +*/ + +static int +score_point(polyominoesstruct *sp, int x, int y, int min_score_so_far) +{ + int poly_no, point_no, transform_index, i, attachable; + point_type attach_point, target_point; + int score = 0; + + if (x>=1 && xwidth-1 && y>=1 && yheight-1 && + ARRAY(x-1,y-1)<0 && ARRAY(x-1,y)<0 && ARRAY(x-1,y+1)<0 && + ARRAY(x+1,y-1)<0 && ARRAY(x+1,y)<0 && ARRAY(x+1,y+1)<0 && + ARRAY(x,y-1)<0 && ARRAY(x,y+1)<0) + return 10000; + + attach_point.x = x; + attach_point.y = y; + for (poly_no=first_poly_no(sp);poly_nonr_polyominoes;next_poly_no(sp,&poly_no)) + if (!sp->polyomino[poly_no].attached) { + for (point_no=0;point_nopolyomino[poly_no].len;point_no++) + for (transform_index=0;transform_indexpolyomino[poly_no].transform_len;transform_index++) { + attachable = 1; + for (i=0;ipolyomino[poly_no].len;i++) { + transform(sp->polyomino[poly_no].point[i], + sp->polyomino[poly_no].point[point_no], + sp->polyomino[poly_no].transform_list[transform_index], + attach_point, &target_point); + if ( ! ((target_point.x>=0) && (target_point.xwidth) + && (target_point.y>=0) && (target_point.yheight) + && (ARRAY_P(target_point)<0))) { + attachable = 0; + break; + } + } + if (attachable) { + score++; + if (score>=min_score_so_far) + return score; + } + } + } + + return score; +} + +static void find_blank(polyominoesstruct *sp, point_type *point) +{ + int score, worst_score; + int x, y; + int blank_mark; + + blank_mark = find_smallest_blank_component(sp); + + worst_score = 1000000; + for (x=0;xwidth;x++) for (y=0;yheight;y++) if (ARRAY(x,y)==blank_mark) { + score = 100*score_point(sp,x,y,worst_score); + if (score>0) { + if (sp->left_right) score += 10*x; + else score += 10*(sp->width-1-x); + if (sp->top_bottom) score += y; + else score += (sp->height-1-y); + } + if (scorex = x; + point->y = y; + worst_score = score; + } + } + + for (x=0;xwidth;x++) for (y=0;yheight;y++) + if (ARRAY(x,y)<0) ARRAY(x,y) = -1; +} + +/* Detaches the most recently attached polyomino. */ + +static +void detach(polyominoesstruct *sp, int *poly_no, int *point_no, int *transform_index, point_type *attach_point, int rot180) +{ + int i; + point_type target_point; + + if (sp->nr_attached == 0) return; + sp->nr_attached--; + *poly_no = sp->attach_list[sp->nr_attached]; + *point_no = sp->polyomino[*poly_no].point_no; + *transform_index = sp->polyomino[*poly_no].transform_index; + *attach_point = sp->polyomino[*poly_no].attach_point; + for (i=0;ipolyomino[*poly_no].len;i++) { + transform(sp->polyomino[*poly_no].point[i], + sp->polyomino[*poly_no].point[*point_no], + sp->polyomino[*poly_no].transform_list[*transform_index]^(rot180<<1), + *attach_point, &target_point); + ARRAY_P(target_point) = -1; + CHANGED_ARRAY_P(target_point) = 1; + } + + sp->polyomino[*poly_no].attached = 0; +} + +/* Attempts to attach a polyomino at point (x,y) at the + point_no-th point of that polyomino, using the transform + transform_no. Returns 1 if successful. +*/ + +static +int attach(polyominoesstruct *sp, int poly_no, int point_no, int transform_index, point_type attach_point, int rot180, + int *reason_to_not_attach) { + point_type target_point; + int i; + int attachable = 1, worst_reason_not_to_attach = 1000000000; + + if (rot180) { + attach_point.x = sp->width-1-attach_point.x; + attach_point.y = sp->height-1-attach_point.y; + } + + if (sp->polyomino[poly_no].attached) + return 0; + + for (i=0;ipolyomino[poly_no].len;i++) { + transform(sp->polyomino[poly_no].point[i], + sp->polyomino[poly_no].point[point_no], + sp->polyomino[poly_no].transform_list[transform_index]^(rot180<<1), + attach_point, &target_point); + if ( ! ((target_point.x>=0) && (target_point.xwidth) + && (target_point.y>=0) && (target_point.yheight) + && (ARRAY_P(target_point) == -1))) { + if (sp->identical) { + attachable = 0; + if ((target_point.x>=0) && (target_point.xwidth) + && (target_point.y>=0) && (target_point.yheight) + && (ARRAY_P(target_point) >= 0) + && (ARRAY_P(target_point)identical && !attachable) { + if (worst_reason_not_to_attach < 1000000000) + reason_to_not_attach[worst_reason_not_to_attach] = 1; + return 0; + } + + for (i=0;ipolyomino[poly_no].len;i++) { + transform(sp->polyomino[poly_no].point[i], + sp->polyomino[poly_no].point[point_no], + sp->polyomino[poly_no].transform_list[transform_index]^(rot180<<1), + attach_point, &target_point); + ARRAY_P(target_point) = poly_no; + CHANGED_ARRAY_P(target_point) = 1; + } + + sp->attach_list[sp->nr_attached] = poly_no; + sp->nr_attached++; + + sp->polyomino[poly_no].attached = 1; + sp->polyomino[poly_no].point_no = point_no; + sp->polyomino[poly_no].attach_point = attach_point; + sp->polyomino[poly_no].transform_index = transform_index; + + if (!sp->check_ok(sp)) { + detach(sp,&poly_no,&point_no,&transform_index,&attach_point,rot180); + return 0; + } + + return 1; +} + +static +int next_attach_try(polyominoesstruct *sp, int *poly_no, int *point_no, int *transform_index) +{ + + (*transform_index)++; + if (*transform_index>=sp->polyomino[*poly_no].transform_len) { + *transform_index = 0; + (*point_no)++; + if (*point_no>=sp->polyomino[*poly_no].len) { + *point_no = 0; + next_poly_no(sp,poly_no); + if (*poly_no>=sp->nr_polyominoes) { + *poly_no = first_poly_no(sp); + return 0; + } + } + } + return 1; +} + + +/******************************************************* +Display routines. +*******************************************************/ + +static void +draw_without_bitmaps(ModeInfo * mi, polyominoesstruct *sp) +{ + Display *display = MI_DISPLAY(mi); + Window window = MI_WINDOW(mi); + GC gc = MI_GC(mi); + int x,y,poly_no,nr_lines,nr_rectangles; + + XSetLineAttributes(display,gc,sp->box/10+1,LineSolid,CapRound,JoinRound); + + for (poly_no=-1;poly_nonr_polyominoes;poly_no++) { + nr_rectangles = 0; + for (x=0;xwidth;x++) for (y=0;yheight;y++) + if (CHANGED_ARRAY(x,y) && ARRAY(x,y) == poly_no) { + sp->rectangles[nr_rectangles].x = sp->x_margin + sp->box*x; + sp->rectangles[nr_rectangles].y = sp->y_margin + sp->box*y; + sp->rectangles[nr_rectangles].width = sp->box; + sp->rectangles[nr_rectangles].height = sp->box; + nr_rectangles++; + } + if (poly_no == -1) + XSetForeground(display, gc, MI_BLACK_PIXEL(mi)); + else + XSetForeground(display, gc, sp->polyomino[poly_no].color); + XFillRectangles(display, window, gc, sp->rectangles, nr_rectangles); + } + + XSetForeground(display, gc, MI_BLACK_PIXEL(mi)); + + nr_lines = 0; + for (x=0;xwidth-1;x++) for (y=0;yheight;y++) { + if (ARRAY(x,y) == -1 && ARRAY(x+1,y) == -1 + && (CHANGED_ARRAY(x,y) || CHANGED_ARRAY(x+1,y))) { + sp->lines[nr_lines].x1 = sp->x_margin + sp->box*(x+1); + sp->lines[nr_lines].y1 = sp->y_margin + sp->box*y; + sp->lines[nr_lines].x2 = sp->x_margin + sp->box*(x+1); + sp->lines[nr_lines].y2 = sp->y_margin + sp->box*(y+1); + nr_lines++; + } + } + XDrawSegments(display, window, gc, sp->lines, nr_lines); + + nr_lines = 0; + for (x=0;xwidth;x++) for (y=0;yheight-1;y++) { + if (ARRAY(x,y) == -1 && ARRAY(x,y+1) == -1 + && (CHANGED_ARRAY(x,y) || CHANGED_ARRAY(x,y+1))) { + sp->lines[nr_lines].x1 = sp->x_margin + sp->box*x; + sp->lines[nr_lines].y1 = sp->y_margin + sp->box*(y+1); + sp->lines[nr_lines].x2 = sp->x_margin + sp->box*(x+1); + sp->lines[nr_lines].y2 = sp->y_margin + sp->box*(y+1); + nr_lines++; + } + } + XDrawSegments(display, window, gc, sp->lines, nr_lines); + + XSetForeground(display, gc, MI_WHITE_PIXEL(mi)); + XDrawRectangle(display, window, gc, sp->x_margin, sp->y_margin, sp->box*sp->width, sp->box*sp->height); + + XSetForeground(display, gc, MI_WHITE_PIXEL(mi)); + + nr_lines = 0; + for (x=0;xwidth-1;x++) for (y=0;yheight;y++) { + if (ARRAY(x+1,y) != ARRAY(x,y)) { + sp->lines[nr_lines].x1 = sp->x_margin + sp->box*(x+1); + sp->lines[nr_lines].y1 = sp->y_margin + sp->box*y; + sp->lines[nr_lines].x2 = sp->x_margin + sp->box*(x+1); + sp->lines[nr_lines].y2 = sp->y_margin + sp->box*(y+1); + nr_lines++; + } + } + XDrawSegments(display, window, gc, sp->lines, nr_lines); + + nr_lines = 0; + for (x=0;xwidth;x++) for (y=0;yheight-1;y++) { + if (ARRAY(x,y+1) != ARRAY(x,y)) { + sp->lines[nr_lines].x1 = sp->x_margin + sp->box*x; + sp->lines[nr_lines].y1 = sp->y_margin + sp->box*(y+1); + sp->lines[nr_lines].x2 = sp->x_margin + sp->box*(x+1); + sp->lines[nr_lines].y2 = sp->y_margin + sp->box*(y+1); + nr_lines++; + } + } + XDrawSegments(display, window, gc, sp->lines, nr_lines); + XSetLineAttributes(display,gc,1,LineSolid,CapRound,JoinRound); +} + +static void create_bitmaps(ModeInfo * mi, polyominoesstruct *sp) +{ + int x,y,n; + char *data; + + for (n=0;n<256;n++) { + +/* Avoid duplication of identical bitmaps. */ + if (IS_LEFT_UP(n) && (IS_LEFT(n) || IS_UP(n))) + sp->bitmaps[n] = sp->bitmaps[n & ~LEFT_UP]; + else if (IS_LEFT_DOWN(n) && (IS_LEFT(n) || IS_DOWN(n))) + sp->bitmaps[n] = sp->bitmaps[n & ~LEFT_DOWN]; + else if (IS_RIGHT_UP(n) && (IS_RIGHT(n) || IS_UP(n))) + sp->bitmaps[n] = sp->bitmaps[n & ~RIGHT_UP]; + else if (IS_RIGHT_DOWN(n) && (IS_RIGHT(n) || IS_DOWN(n))) + sp->bitmaps[n] = sp->bitmaps[n & ~RIGHT_DOWN]; + + else /* if (bitmap_needed(n)) */ { + data = (char *) malloc(sizeof(char)*(sp->box*ROUND8(sp->box)/8)); + if (data == NULL) { + sp->use_bitmaps = 0; + return; + } + + for (y=0;ybox;y++) for (x=0;xbox;x++) { + if (!sp->use3D) { +#ifdef SMALL_BELLYBUTTON + if (x >= sp->box / 2 && x <= sp->box / 2 + 1 && + y >= sp->box / 2 && y <= sp->box / 2 + 1) + NOTHALFBIT(n,x,y) + else +#endif + HALFBIT(n,x,y) + } else if ((x>=y && x<=sp->box-y-1 && IS_UP(n)) + || (x<=y && x<=sp->box-y-1 && ybox/2 && !IS_LEFT(n)) + || (x>=y && x>=sp->box-y-1 && ybox/2 && !IS_RIGHT(n))) + SETBIT(n,x,y) + else if ((x<=y && x<=sp->box-y-1 && IS_LEFT(n)) + || (x>=y && x<=sp->box-y-1 && xbox/2 && !IS_UP(n)) + || (x<=y && x>=sp->box-y-1 && xbox/2 && !IS_DOWN(n))) + TWOTHIRDSBIT(n,x,y) + else if ((x>=y && x>=sp->box-y-1 && IS_RIGHT(n)) + || (x>=y && x<=sp->box-y-1 && x>=sp->box/2 && !IS_UP(n)) + || (x<=y && x>=sp->box-y-1 && x>=sp->box/2 && !IS_DOWN(n))) + HALFBIT(n,x,y) + else if ((x<=y && x>=sp->box-y-1 && IS_DOWN(n)) + || (x<=y && x<=sp->box-y-1 && y>=sp->box/2 && !IS_LEFT(n)) + || (x>=y && x>=sp->box-y-1 && y>=sp->box/2 && !IS_RIGHT(n))) + THIRDBIT(n,x,y) + } + + if (IS_LEFT(n)) + for (y=0;ybox;y++) for (x=G;xbox;y++) for (x=G;xbox-1-x,y) + if (IS_UP(n)) + for (x=0;xbox;x++) for (y=G;ybox;x++) for (y=G;ybox-1-y) + if (IS_LEFT(n)) + for (y=0;ybox;y++) for (x=0;xbox;y++) for (x=0;xbox-1-x,y) + if (IS_UP(n)) + for (x=0;xbox;x++) for (y=0;ybox;x++) for (y=0;ybox-1-y) + + if (IS_LEFT(n) && IS_UP(n)) + for (x=G;x<=G+R;x++) + for (y=G;y<=R+2*G-x;y++) { + if (x+y>R+2*G-RT) + SETBIT(n,x,y) + else + RESBIT(n,x,y) + } + if (IS_LEFT(n) && IS_DOWN(n)) + for (x=G;x<=G+R;x++) + for (y=G;y<=R+2*G-x;y++) { + if (x+y>R+2*G-RT) + SETBIT(n,x,sp->box-1-y) + else + RESBIT(n,x,sp->box-1-y) + } + if (IS_RIGHT(n) && IS_UP(n)) + for (x=G;x<=G+R;x++) + for (y=G;y<=R+2*G-x;y++) { + if (x+y>R+2*G-RT) + SETBIT(n,sp->box-1-x,y) + else + RESBIT(n,sp->box-1-x,y) + } + if (IS_RIGHT(n) && IS_DOWN(n)) + for (x=G;x<=G+R;x++) + for (y=G;y<=R+2*G-x;y++) { + if (x+y>R+2*G-RT) + SETBIT(n,sp->box-1-x,sp->box-1-y) + else + RESBIT(n,sp->box-1-x,sp->box-1-y) + } + + if (!IS_LEFT(n) && !IS_UP(n) && IS_LEFT_UP(n)) { + for (x=0;xbox-1-y) + for (x=G;xbox-1-y) + for (x=0;xbox-1-y) + } + if (!IS_RIGHT(n) && !IS_UP(n) && IS_RIGHT_UP(n)) { + for (x=0;xbox-1-x,y) + for (x=G;xbox-1-x,y) + for (x=0;xbox-1-x,y) + } + if (!IS_RIGHT(n) && !IS_DOWN(n) && IS_RIGHT_DOWN(n)) { + for (x=0;xbox-1-x,sp->box-1-y) + for (x=G;xbox-1-x,sp->box-1-y) + for (x=0;xbox-1-x,sp->box-1-y) + } + +#ifdef LARGE_BELLYBUTTON + if (!sp->use3D) { + if (!IS_LEFT(n) && !IS_UP(n) && !IS_LEFT_UP(n)) + for (x=0;xbox-G-T;ybox;y++) + SETBIT(n,x,y) + if (!IS_RIGHT(n) && !IS_UP(n) && !IS_RIGHT_UP(n)) + for (x=sp->box-G-T;xbox;x++) for(y=0;ybox-G-T;xbox;x++) for(y=sp->box-G-T;ybox;y++) + SETBIT(n,x,y) + } else +#else + if (sp->use3D) +#endif + { + if (!IS_LEFT(n) && !IS_UP(n) && !IS_LEFT_UP(n)) + for (x=0;xbox/2-RR;x++) for(y=0;ybox/2-RR;y++) + THREEQUARTERSBIT(n,x,y) + if (!IS_LEFT(n) && !IS_DOWN(n) && !IS_LEFT_DOWN(n)) + for (x=0;xbox/2-RR;x++) for(y=sp->box/2+RR;ybox;y++) + THREEQUARTERSBIT(n,x,y) + if (!IS_RIGHT(n) && !IS_UP(n) && !IS_RIGHT_UP(n)) + for (x=sp->box/2+RR;xbox;x++) for(y=0;ybox/2-RR;y++) + THREEQUARTERSBIT(n,x,y) + if (!IS_RIGHT(n) && !IS_DOWN(n) && !IS_RIGHT_DOWN(n)) + for (x=sp->box/2+RR;xbox;x++) for(y=sp->box/2+RR;ybox;y++) + THREEQUARTERSBIT(n,x,y) + } + + sp->bitmaps[n] = XCreateImage(MI_DISPLAY(mi), MI_VISUAL(mi), 1, XYBitmap, + 0, data, sp->box, sp->box, 8, 0); + if (sp->bitmaps[n] == None) { + free(data); + sp->use_bitmaps = 0; + return; + } + sp->bitmaps[n]->byte_order = MSBFirst; + sp->bitmaps[n]->bitmap_unit = 8; + sp->bitmaps[n]->bitmap_bit_order = LSBFirst; + } + } + + sp->use_bitmaps = 1; +} + +static void draw_with_bitmaps(ModeInfo * mi, polyominoesstruct *sp) +{ + Display *display = MI_DISPLAY(mi); + Window window = MI_WINDOW(mi); + GC gc = MI_GC(mi); + int x,y,t,bitmap_index; + + for (x=0;xwidth;x++) for (y=0;yheight;y++) { + if (ARRAY(x,y) == -1) { + if (CHANGED_ARRAY(x,y)) { + XSetForeground(display, gc, MI_BLACK_PIXEL(mi)); + XFillRectangle(display,window,gc, + sp->x_margin + sp->box*x, + sp->y_margin + sp->box*y, + sp->box,sp->box); + } + } + else { + XSetForeground(display, gc, sp->polyomino[ARRAY(x,y)].color); + bitmap_index = 0; + if (ARR(x,y) != ARR(x-1,y)) bitmap_index |= LEFT; + if (ARR(x,y) != ARR(x+1,y)) bitmap_index |= RIGHT; + if (ARR(x,y) != ARR(x,y-1)) bitmap_index |= UP; + if (ARR(x,y) != ARR(x,y+1)) bitmap_index |= DOWN; + if (ARR(x,y) != ARR(x-1,y-1)) bitmap_index |= LEFT_UP; + if (ARR(x,y) != ARR(x-1,y+1)) bitmap_index |= LEFT_DOWN; + if (ARR(x,y) != ARR(x+1,y-1)) bitmap_index |= RIGHT_UP; + if (ARR(x,y) != ARR(x+1,y+1)) bitmap_index |= RIGHT_DOWN; + (void) XPutImage(display,window,gc, + sp->bitmaps[bitmap_index], + 0,0, + sp->x_margin + sp->box*x, + sp->y_margin + sp->box*y, + sp->box,sp->box); + } + } + + XSetForeground(display, gc, sp->border_color); + for (t=G;tx_margin-t-1,sp->y_margin-t-1, + sp->box*sp->width+1+2*t, sp->box*sp->height+1+2*t); +} + + +/*************************************************** +Routines to initialise and close down polyominoes. +***************************************************/ + +static void free_bitmaps(polyominoesstruct *sp) +{ + int n; + + for (n=0;n<256;n++) +/* Don't bother to free duplicates */ + if (IS_LEFT_UP(n) && (IS_LEFT(n) || IS_UP(n))) + sp->bitmaps[n] = None; + else if (IS_LEFT_DOWN(n) && (IS_LEFT(n) || IS_DOWN(n))) + sp->bitmaps[n] = None; + else if (IS_RIGHT_UP(n) && (IS_RIGHT(n) || IS_UP(n))) + sp->bitmaps[n] = None; + else if (IS_RIGHT_DOWN(n) && (IS_RIGHT(n) || IS_DOWN(n))) + sp->bitmaps[n] = None; + + else if (sp->bitmaps[n] != None) { + XDestroyImage(sp->bitmaps[n]); + sp->bitmaps[n] = None; + } +} + +#define deallocate(p,t) if ((p)!=NULL) {free(p); p=(t*)NULL;} + +static void free_polyominoes(polyominoesstruct *sp) +{ + int n; + + for (n=0;nnr_polyominoes;n++) { + deallocate(sp->polyomino[n].point, point_type); + } + + deallocate(sp->polyomino, polyomino_type); + deallocate(sp->attach_list, int); + deallocate(sp->rectangles, XRectangle); + deallocate(sp->lines, XSegment); + deallocate(sp->reason_to_not_attach, int); + deallocate(sp->array, int); + deallocate(sp->changed_array, int); + + free_bitmaps(sp); +} + +#define set_allocate(p,type,size) p = (type *) malloc(size); \ + if ((p)==NULL) {free_polyominoes(sp);return 0;} + +#define copy_polyomino(dst,src,new_rand) \ + (dst).len=(src).len; \ + (dst).max_white = (src).max_white; \ + set_allocate((dst).point,point_type,sizeof(point_type)*(src).len); \ + (dst).len = (src).len; \ + if (new_rand) \ + random_permutation((src).len,perm_point); \ + for (i=0;i<(src).len;i++) \ + (dst).point[i] = (src).point[perm_point[i]]; \ + (dst).transform_len = (src).transform_len; \ + if (new_rand) \ + random_permutation((src).transform_len,perm_transform); \ + for (i=0;i<(src).transform_len;i++) \ + (dst).transform_list[i] = (src).transform_list[perm_transform[i]]; \ + (dst).attached = 0 + + +/*************************************************** +Puzzle specific initialization routines. +***************************************************/ + +static +int check_pentomino_puzzle(polyominoesstruct *sp) +{ + return check_all_regions_multiple_of(sp, 5) && whites_ok(sp); +} + +static +int check_hexomino_puzzle(polyominoesstruct *sp) +{ + return check_all_regions_multiple_of(sp, 6) && whites_ok(sp); +} + +static +int check_tetr_pentomino_puzzle(polyominoesstruct *sp) +{ + return check_all_regions_positive_combination_of(sp, 5, 4) && whites_ok(sp); +} + +static +int check_pent_hexomino_puzzle(polyominoesstruct *sp) +{ + return check_all_regions_positive_combination_of(sp, 6, 5) && whites_ok(sp); +} + +static +int check_heptomino_puzzle(polyominoesstruct *sp) +{ + return check_all_regions_multiple_of(sp, 7) && whites_ok(sp); +} + +static +int check_octomino_puzzle(polyominoesstruct *sp) +{ + return check_all_regions_multiple_of(sp, 8) && whites_ok(sp); +} + +static +int check_dekomino_puzzle(polyominoesstruct *sp) +{ + return check_all_regions_multiple_of(sp, 10) && whites_ok(sp); +} + +static +int check_elevenomino_puzzle(polyominoesstruct *sp) +{ + return check_all_regions_multiple_of(sp, 11) && whites_ok(sp); +} + +static struct {int len; point_type point[4]; + int transform_len, transform_list[8], max_white;} tetromino[5] = +{ +/* +xxxx +*/ + {4, {{0,0}, {1,0}, {2,0}, {3,0}}, + 2, {0, 1, -1, -1, -1, -1, -1, -1}, 2}, +/* +xxx + x +*/ + {4, {{0,0}, {1,0}, {2,0}, {2,1}}, + 8, {0, 1, 2, 3, 4, 5, 6, 7}, 2}, +/* +xxx + x +*/ + {4, {{0,0}, {1,0}, {1,1}, {2,0}}, + 4, {0, 1, 2, 3, -1, -1, -1, -1}, 3}, +/* +xx + xx +*/ + {4, {{0,0}, {1,0}, {1,1}, {2,1}}, + 4, {0, 1, 4, 5, -1, -1, -1, -1}, 2}, +/* +xx +xx +*/ + {4, {{0,0}, {0,1}, {1,0}, {1,1}}, + 1, {0, -1, -1, -1, -1, -1, -1, -1}, 2}}; + + +static struct pentomino_struct {int len; point_type point[5]; + int transform_len, transform_list[8], max_white;} + pentomino[12] = +{ +/* +xxxxx +*/ + {5, {{0,0}, {1,0}, {2,0}, {3,0}, {4,0}}, + 2, {0, 1, -1, -1, -1, -1, -1, -1}, 3}, +/* +xxxx + x +*/ + {5, {{0,0}, {1,0}, {2,0}, {3,0}, {3,1}}, + 8, {0, 1, 2, 3, 4, 5, 6, 7}, 3}, +/* +xxxx + x +*/ + {5, {{0,0}, {1,0}, {2,0}, {2,1}, {3,0}}, + 8, {0, 1, 2, 3, 4, 5, 6, 7}, 3}, +/* + x +xxx + x +*/ + {5, {{0,0}, {1,0}, {2,-1}, {2,0}, {2,1}}, + 4, {0, 1, 2, 3, -1, -1, -1, -1}, 3}, +/* +xxx + xx +*/ + {5, {{0,0}, {1,0}, {2,0}, {2,1}, {3,1}}, + 8, {0, 1, 2, 3, 4, 5, 6, 7}, 3}, +/* +xxx + xx +*/ + {5, {{0,0}, {1,0}, {1,1}, {2,0}, {2,1}}, + 8, {0, 1, 2, 3, 4, 5, 6, 7}, 3}, +/* +xxx + x + x +*/ + {5, {{0,0}, {1,0}, {2,0}, {2,1}, {2,2}}, + 4, {0, 1, 2, 3, -1, -1, -1, -1}, 3}, +/* + x +xxx + x +*/ + {5, {{0,0}, {1,-1}, {1,0}, {2,0}, {2,1}}, + 8, {0, 1, 2, 3, 4, 5, 6, 7}, 3}, +/* +xxx +x x +*/ + {5, {{0,0}, {0,1}, {1,0}, {2,0}, {2,1}}, + 4, {0, 1, 2, 3, -1, -1, -1, -1}, 3}, +/* + x +xxx +x +*/ + {5, {{0,0}, {0,1}, {1,0}, {2,-1}, {2,0}}, + 4, {0, 1, 4, 5, -1, -1, -1, -1}, 3}, +/* + x +xxx + x +*/ + {5, {{0,0}, {1,-1}, {1,0}, {1,1}, {2,0}}, + 1, {0, -1, -1, -1, -1, -1, -1, -1}, 4}, +/* +xx + xx + x +*/ + {5, {{0,0}, {1,0}, {1,1}, {2,1}, {2,2}}, + 4, {0, 1, 2, 3, -1, -1, -1, -1}, 3}}; + + +static struct hexomino_struct {int len; point_type point[6]; + int transform_len, transform_list[8], max_white;} + hexomino[35] = +{ +/* +xxxxxx +*/ + {6, {{0,0}, {1,0}, {2,0}, {3,0}, {4,0}, {5,0}}, + 2, {0, 1, -1, -1, -1, -1, -1, -1}, 3}, +/* +xxxxx + x +*/ + {6, {{0,0}, {1,0}, {2,0}, {3,0}, {4,0}, {4,1}}, + 8, {0, 1, 2, 3, 4, 5, 6, 7}, 3}, +/* +xxxxx + x +*/ + {6, {{0,0}, {1,0}, {2,0}, {3,0}, {3,1}, {4,0}}, + 8, {0, 1, 2, 3, 4, 5, 6, 7}, 4}, +/* +xxxxx + x +*/ + {6, {{0,0}, {1,0}, {2,0}, {2,1}, {3,0}, {4,0}}, + 4, {0, 1, 2, 3, -1, -1, -1, -1}, 3}, +/* + x +xxxx + x +*/ + {6, {{0,0}, {1,0}, {2,0}, {3,-1}, {3,0}, {3,1}}, + 4, {0, 1, 2, 3, -1, -1, -1, -1}, 4}, +/* +xxxx + xx +*/ + {6, {{0,0}, {1,0}, {2,0}, {3,0}, {3,1}, {4,1}}, + 8, {0, 1, 2, 3, 4, 5, 6, 7}, 3}, +/* +xxxx + xx +*/ + {6, {{0,0}, {1,0}, {2,0}, {2,1}, {3,0}, {3,1}}, + 8, {0, 1, 2, 3, 4, 5, 6, 7}, 3}, +/* +xxxx + x + x +*/ + {6, {{0,0}, {1,0}, {2,0}, {3,0}, {3,1}, {3,2}}, + 8, {0, 1, 2, 3, 4, 5, 6, 7}, 3}, +/* + x +xxxx + x +*/ + {6, {{0,0}, {1,0}, {2,-1}, {2,0}, {3,0}, {3,1}}, + 8, {0, 1, 2, 3, 4, 5, 6, 7}, 3}, +/* +xxxx + x x +*/ + {6, {{0,0}, {1,0}, {1,1}, {2,0}, {3,0}, {3,1}}, + 8, {0, 1, 2, 3, 4, 5, 6, 7}, 4}, +/* + x +xxxx + x +*/ + {6, {{0,0}, {1,-1}, {1,0}, {2,0}, {3,0}, {3,1}}, + 8, {0, 1, 2, 3, 4, 5, 6, 7}, 4}, +/* +xxxx +x x +*/ + {6, {{0,0}, {0,1}, {1,0}, {2,0}, {3,0}, {3,1}}, + 4, {0, 1, 2, 3, -1, -1, -1, -1}, 3}, +/* + x +xxxx +x +*/ + {6, {{0,0}, {0,1}, {1,0}, {2,0}, {3,-1}, {3,0}}, + 4, {0, 1, 4, 5, -1, -1, -1, -1}, 3}, +/* + x +xxxx + x +*/ + {6, {{0,0}, {1,0}, {2,-1}, {2,0}, {2,1}, {3,0}}, + 4, {0, 1, 2, 3, -1, -1, -1, -1}, 4}, +/* +xxxx + xx +*/ + {6, {{0,0}, {1,0}, {1,1}, {2,0}, {2,1}, {3,0}}, + 4, {0, 1, 2, 3, -1, -1, -1, -1}, 3}, +/* +xxxx + x + x +*/ + {6, {{0,0}, {1,0}, {2,0}, {2,1}, {2,2}, {3,0}}, + 8, {0, 1, 2, 3, 4, 5, 6, 7}, 3}, +/* + x +xxxx + x +*/ + {6, {{0,0}, {1,-1}, {1,0}, {2,0}, {2,1}, {3,0}}, + 4, {0, 1, 4, 5, -1, -1, -1, -1}, 3}, +/* + xx +xxx + x +*/ + {6, {{0,0}, {1,0}, {2,-1}, {2,0}, {2,1}, {3,-1}}, + 8, {0, 1, 2, 3, 4, 5, 6, 7}, 3}, +/* + xx +xxx + x +*/ + {6, {{0,0}, {1,-1}, {1,0}, {2,-1}, {2,0}, {2,1}}, + 8, {0, 1, 2, 3, 4, 5, 6, 7}, 3}, +/* + x +xxx +x x +*/ + {6, {{0,0}, {0,1}, {1,0}, {2,-1}, {2,0}, {2,1}}, + 8, {0, 1, 2, 3, 4, 5, 6, 7}, 4}, +/* +xxx + xxx +*/ + {6, {{0,0}, {1,0}, {2,0}, {2,1}, {3,1}, {4,1}}, + 4, {0, 1, 4, 5, -1, -1, -1, -1}, 3}, +/* +xxx + xx + x +*/ + {6, {{0,0}, {1,0}, {2,0}, {2,1}, {3,1}, {3,2}}, + 8, {0, 1, 2, 3, 4, 5, 6, 7}, 3}, +/* +xxx + xxx +*/ + {6, {{0,0}, {1,0}, {1,1}, {2,0}, {2,1}, {3,1}}, + 4, {0, 1, 4, 5, -1, -1, -1, -1}, 4}, +/* +xxx + xx + x +*/ + {6, {{0,0}, {1,0}, {2,0}, {2,1}, {2,2}, {3,1}}, + 8, {0, 1, 2, 3, 4, 5, 6, 7}, 4}, +/* + x +xxx + xx +*/ + {6, {{0,0}, {1,-1}, {1,0}, {2,0}, {2,1}, {3,1}}, + 8, {0, 1, 2, 3, 4, 5, 6, 7}, 4}, +/* +xxx +x xx +*/ + {6, {{0,0}, {0,1}, {1,0}, {2,0}, {2,1}, {3,1}}, + 8, {0, 1, 2, 3, 4, 5, 6, 7}, 3}, +/* +xxx + xx + x +*/ + {6, {{0,0}, {1,0}, {1,1}, {2,0}, {2,1}, {2,2}}, + 4, {0, 1, 2, 3, -1, -1, -1, -1}, 4}, +/* + x +xxx + xx +*/ + {6, {{0,0}, {1,-1}, {1,0}, {1,1}, {2,0}, {2,1}}, + 4, {0, 1, 2, 3, -1, -1, -1, -1}, 4}, +/* +xxx +xxx +*/ + {6, {{0,0}, {0,1}, {1,0}, {1,1}, {2,0}, {2,1}}, + 2, {0, 1, -1, -1, -1, -1, -1, -1}, 3}, +/* +xxx + x + xx +*/ + {6, {{0,0}, {1,0}, {2,0}, {2,1}, {2,2}, {3,2}}, + 8, {0, 1, 2, 3, 4, 5, 6, 7}, 3}, +/* +xxx + x + xx +*/ + {6, {{0,0}, {1,0}, {1,2}, {2,0}, {2,1}, {2,2}}, + 8, {0, 1, 2, 3, 4, 5, 6, 7}, 3}, +/* + x +xxx +x x +*/ + {6, {{0,0}, {0,1}, {1,-1}, {1,0}, {2,0}, {2,1}}, + 4, {0, 1, 2, 3, -1, -1, -1, -1}, 3}, +/* + xx +xxx +x +*/ + {6, {{0,0}, {0,1}, {1,0}, {2,-1}, {2,0}, {3,-1}}, + 8, {0, 1, 2, 3, 4, 5, 6, 7}, 3}, +/* + xx +xxx +x +*/ + {6, {{0,0}, {0,1}, {1,-1}, {1,0}, {2,-1}, {2,0}}, + 8, {0, 1, 2, 3, 4, 5, 6, 7}, 3}, +/* +xx + xx + xx +*/ + {6, {{0,0}, {1,0}, {1,1}, {2,1}, {2,2}, {3,2}}, + 4, {0, 1, 4, 5, -1, -1, -1, -1}, 3}}; + +static struct pentomino_struct one_sided_pentomino[60]; + +static void make_one_sided_pentomino(void) +{ + int i,j,t,u; + + j=0; + for (i=0;i<18;i++) { + one_sided_pentomino[j] = pentomino[i]; + for (t=0;t<8;t++) + if (one_sided_pentomino[j].transform_list[t]>=4) { + one_sided_pentomino[j].transform_len = t; + j++; + one_sided_pentomino[j] = pentomino[i]; + for (u=t;u<8;u++) one_sided_pentomino[j].transform_list[u-t] = one_sided_pentomino[j].transform_list[u]; + one_sided_pentomino[j].transform_len -= t; + break; + } + j++; + } +} + +static struct hexomino_struct one_sided_hexomino[60]; + +static void make_one_sided_hexomino(void) +{ + int i,j,t,u; + + j=0; + for (i=0;i<35;i++) { + one_sided_hexomino[j] = hexomino[i]; + for (t=0;t<8;t++) + if (one_sided_hexomino[j].transform_list[t]>=4) { + one_sided_hexomino[j].transform_len = t; + j++; + one_sided_hexomino[j] = hexomino[i]; + for (u=t;u<8;u++) one_sided_hexomino[j].transform_list[u-t] = one_sided_hexomino[j].transform_list[u]; + one_sided_hexomino[j].transform_len -= t; + break; + } + j++; + } +} + +/* +Find all the ways of placing all twelve pentominoes +into a rectangle whose size is 20x3, 15x4, 12x5 or 10x6. +*/ + +static +int set_pentomino_puzzle(polyominoesstruct *sp) +{ + int perm_poly[12], perm_point[5], perm_transform[8], i, p; + + switch (NRAND(4)) { + case 0: + sp->width = 20; + sp->height = 3; + break; + case 1: + sp->width = 15; + sp->height = 4; + break; + case 2: + sp->width = 12; + sp->height = 5; + break; + case 3: + sp->width = 10; + sp->height = 6; + break; + } + + sp->nr_polyominoes = 12; + set_allocate(sp->polyomino,polyomino_type,12*sizeof(polyomino_type)); + random_permutation(12,perm_poly); + for (p=0;p<12;p++) { + copy_polyomino(sp->polyomino[p],pentomino[perm_poly[p]],1); + } + + sp->check_ok = check_pentomino_puzzle; + + return 1; +} + +/* +Many of the following puzzles are inspired by +http://www.xs4all.nl/~gp/PolyominoSolver/Polyomino.html +*/ + +/* +Find all the ways of placing all eighteen one-sided pentominoes +into a rectangle. +*/ + +static +int set_one_sided_pentomino_puzzle(polyominoesstruct *sp) +{ + int perm_poly[18], perm_point[5], perm_transform[8], i, p; + + make_one_sided_pentomino(); + + switch (NRAND(4)) { + case 0: + sp->width = 30; + sp->height = 3; + break; + case 1: + sp->width = 18; + sp->height = 5; + break; + case 2: + sp->width = 15; + sp->height = 6; + break; + case 3: + sp->width = 10; + sp->height = 9; + break; + } + + sp->nr_polyominoes = 18; + set_allocate(sp->polyomino,polyomino_type,18*sizeof(polyomino_type)); + random_permutation(18,perm_poly); + for (p=0;p<18;p++) { + copy_polyomino(sp->polyomino[p],one_sided_pentomino[perm_poly[p]],1); + } + + sp->check_ok = check_pentomino_puzzle; + + return 1; +} + +/* +Find all the ways of placing all sixty one-sided hexominoes +into a rectangle. +*/ + +static +int set_one_sided_hexomino_puzzle(polyominoesstruct *sp) +{ + int perm_poly[60], perm_point[6], perm_transform[8], i, p; + + make_one_sided_hexomino(); + + switch (NRAND(8)) { + case 0: + sp->width = 20; + sp->height = 18; + break; + case 1: + sp->width = 24; + sp->height = 15; + break; + case 2: + sp->width = 30; + sp->height = 12; + break; + case 3: + sp->width = 36; + sp->height = 10; + break; + case 4: + sp->width = 40; + sp->height = 9; + break; + case 5: + sp->width = 45; + sp->height = 8; + break; + case 6: + sp->width = 60; + sp->height = 6; + break; + case 7: + sp->width = 72; + sp->height = 5; + break; + } + + sp->nr_polyominoes = 60; + set_allocate(sp->polyomino,polyomino_type,60*sizeof(polyomino_type)); + random_permutation(60,perm_poly); + for (p=0;p<60;p++) { + copy_polyomino(sp->polyomino[p],one_sided_hexomino[perm_poly[p]],1); + } + + sp->check_ok = check_hexomino_puzzle; + + return 1; +} + +/* +Find all the ways of placing all five tetrominoes and all twelve +pentominoes into a rectangle. +*/ + +static +int set_tetr_pentomino_puzzle(polyominoesstruct *sp) +{ + int perm_poly[17], perm_point[5], perm_transform[8], i, p; + + switch (NRAND(3)) { + case 0: + sp->width = 20; + sp->height = 4; + break; + case 1: + sp->width = 16; + sp->height = 5; + break; + case 2: + sp->width = 10; + sp->height = 8; + break; + } + + sp->nr_polyominoes = 17; + set_allocate(sp->polyomino,polyomino_type,17*sizeof(polyomino_type)); + random_permutation(17,perm_poly); + for (p=0;p<5;p++) { + copy_polyomino(sp->polyomino[perm_poly[p]],tetromino[p],1); + } + for (p=0;p<12;p++) { + copy_polyomino(sp->polyomino[perm_poly[p+5]],pentomino[p],1); + } + + sp->check_ok = check_tetr_pentomino_puzzle; + + return 1; +} +/* +Find all the ways of placing all twelve pentominoes and all thirty five +hexominoes into a rectangle whose size is 18x15. +*/ + +static +int set_pent_hexomino_puzzle(polyominoesstruct *sp) +{ + int perm_poly[47], perm_point[6], perm_transform[8], i, p; + + switch (NRAND(5)) { + case 0: + sp->width = 54; + sp->height = 5; + break; + case 1: + sp->width = 45; + sp->height = 6; + break; + case 2: + sp->width = 30; + sp->height = 9; + break; + case 3: + sp->width = 27; + sp->height = 10; + break; + case 4: + sp->width = 18; + sp->height = 15; + break; + } + + sp->nr_polyominoes = 47; + set_allocate(sp->polyomino,polyomino_type,47*sizeof(polyomino_type)); + random_permutation(47,perm_poly); + for (p=0;p<12;p++) { + copy_polyomino(sp->polyomino[perm_poly[p]],pentomino[p],1); + } + for (p=0;p<35;p++) { + copy_polyomino(sp->polyomino[perm_poly[p+12]],hexomino[p],1); + } + + sp->check_ok = check_pent_hexomino_puzzle; + + return 1; +} + +/* +Other puzzles: + +Science News September 20, 1986 Vol 130, No 12 +Science News November 14, 1987 Vol 132, Pg 310 +*/ + +/* + + * +**** fills a 10x5 rectangle + +*/ + +static struct {int len; point_type point[5]; + int transform_len, transform_list[8], max_white;} pentomino1 = + {5, {{0,0}, {1,0}, {2,0}, {3,0}, {1,1}}, + 8, {0, 1, 2, 3, 4, 5, 6, 7}, 3}; + +static +int set_pentomino_puzzle1(polyominoesstruct *sp) +{ + int perm_point[5], perm_transform[8], i, p; + + sp->width = 10; + sp->height =5; + + sp->nr_polyominoes = 10; + set_allocate(sp->polyomino,polyomino_type,10*sizeof(polyomino_type)); + for (p=0;p<10;p++) { + copy_polyomino(sp->polyomino[p],pentomino1,1); + } + + sp->check_ok = check_pentomino_puzzle; + + return 1; +} + +/* + + * +***** fills a 24x23 rectangle + +*/ + +static struct {int len; point_type point[6]; + int transform_len, transform_list[8], max_white;} hexomino1 = + {6, {{0,0}, {1,0}, {2,0}, {3,0}, {4,0}, {1,1}}, + 8, {0, 1, 2, 3, 4, 5, 6, 7}, 4}; + +static +int set_hexomino_puzzle1(polyominoesstruct *sp) +{ + int perm_point[6], perm_transform[8], i, p; + + sp->width = 24; + sp->height =23; + + sp->nr_polyominoes = 92; + set_allocate(sp->polyomino,polyomino_type,92*sizeof(polyomino_type)); + for (p=0;p<92;p++) { + copy_polyomino(sp->polyomino[p],hexomino1,1); + } + + sp->check_ok = check_hexomino_puzzle; + + return 1; +} + +/* + + ** +***** fills a 21x26 rectangle + +(All solutions have 180 degree rotational symmetry) + +*/ + +static struct {int len; point_type point[7]; + int transform_len, transform_list[8], max_white;} heptomino1 = + {7, {{0,0}, {1,0}, {2,0}, {3,0}, {4,0}, {1,1}, {2,1}}, + 8, {0, 1, 2, 3, 4, 5, 6, 7}, 4}; + +static +int set_heptomino_puzzle1(polyominoesstruct *sp) +{ + int perm_point[7], perm_transform[8], i, p; + + sp->rot180 = 1; + + sp->width = 26; + sp->height =21; + + sp->nr_polyominoes = 78; + set_allocate(sp->polyomino,polyomino_type,78*sizeof(polyomino_type)); + for (p=0;p<78;p+=2) { + copy_polyomino(sp->polyomino[p],heptomino1,1); + copy_polyomino(sp->polyomino[p+1],heptomino1,0); + } + + sp->check_ok = check_heptomino_puzzle; + + return 1; +} + +/* The following puzzles from +Polyominoes Puzzles, Patterns, Problems, and Packings Revised (2nd) Edition +by Solomon W. Golomb Princeton University Press 1994 +*/ + +/* + + ** +***** fills a 28x19 rectangle + +*/ +static +int set_heptomino_puzzle2(polyominoesstruct *sp) +{ + int perm_point[7], perm_transform[8], i, p; + + sp->width = 28; + sp->height =19; + + sp->nr_polyominoes = 76; + set_allocate(sp->polyomino,polyomino_type,76*sizeof(polyomino_type)); + for (p=0;p<76;p++) { + copy_polyomino(sp->polyomino[p],heptomino1,1); + } + + sp->check_ok = check_heptomino_puzzle; + + return 1; +} + +/* + +*** +**** fills a 25x22 rectangle +**** + +*/ + +static struct {int len; point_type point[11]; + int transform_len, transform_list[8], max_white;} elevenomino1 = + {11, {{0,0}, {1,0}, {2,0}, + {0,1}, {1,1}, {2,1}, {3,1}, + {0,2}, {1,2}, {2,2}, {3,2}}, + 8, {0, 1, 2, 3, 4, 5, 6, 7}, 6}; + +static +int set_elevenomino_puzzle1(polyominoesstruct *sp) +{ + int perm_point[11], perm_transform[8], i, p; + + sp->rot180 = 1; + + sp->width = 25; + sp->height =22; + + sp->nr_polyominoes = 50; + set_allocate(sp->polyomino,polyomino_type,50*sizeof(polyomino_type)); + for (p=0;p<50;p+=2) { + copy_polyomino(sp->polyomino[p],elevenomino1,1); + copy_polyomino(sp->polyomino[p+1],elevenomino1,0); + } + + sp->check_ok = check_elevenomino_puzzle; + + return 1; +} + +/* + + * + * +**** fills 32 x 30 rectangle +**** + +*/ + +static struct {int len; point_type point[10]; + int transform_len, transform_list[8], max_white;} dekomino1 = + {10, { {1,-1}, + {1,0}, + {0,1}, {1,1}, {2,1}, {3,1}, + {0,2}, {1,2}, {2,2}, {3,2}}, + 8, {0, 1, 2, 3, 4, 5, 6, 7}, 5}; + +static +int set_dekomino_puzzle1(polyominoesstruct *sp) +{ + int perm_point[10], perm_transform[8], i, p; + + sp->width = 32; + sp->height =30; + + sp->nr_polyominoes = 96; + set_allocate(sp->polyomino,polyomino_type,96*sizeof(polyomino_type)); + for (p=0;p<96;p++) { + copy_polyomino(sp->polyomino[p],dekomino1,1); + } + + sp->check_ok = check_dekomino_puzzle; + + return 1; +} + +/* + + * +*** fills 96 x 26 rectangle +**** + +*/ + +static struct {int len; point_type point[10]; + int transform_len, transform_list[8], max_white;} octomino1 = + {8, { {1,0}, + {0,1}, {1,1}, {2,1}, + {0,2}, {1,2}, {2,2}, {3,2}}, + 8, {0, 1, 2, 3, 4, 5, 6, 7}, 5}; + +static +int set_octomino_puzzle1(polyominoesstruct *sp) +{ + int perm_point[8], perm_transform[8], i, p; + + sp->width = 96; + sp->height =26; + + sp->nr_polyominoes = 312; + set_allocate(sp->polyomino,polyomino_type,312*sizeof(polyomino_type)); + for (p=0;p<312;p++) { + copy_polyomino(sp->polyomino[p],octomino1,1); + } + + sp->check_ok = check_octomino_puzzle; + + return 1; +} + +/* + + * fills 15 x 15 rectangle +**** + +*/ + +static +int set_pentomino_puzzle2(polyominoesstruct *sp) +{ + int perm_point[5], perm_transform[8], i, p; + + sp->width = 15; + sp->height =15; + + sp->nr_polyominoes = 45; + set_allocate(sp->polyomino,polyomino_type,45*sizeof(polyomino_type)); + for (p=0;p<45;p++) { + copy_polyomino(sp->polyomino[p],pentomino1,1); + } + + sp->check_ok = check_pentomino_puzzle; + + return 1; +} + +/* + +*** +**** fills a 47x33 rectangle +**** + +*/ + +static +int set_elevenomino_puzzle2(polyominoesstruct *sp) +{ + int perm_point[11], perm_transform[8], i, p; + + sp->width = 47; + sp->height =33; + + sp->nr_polyominoes = 141; + set_allocate(sp->polyomino,polyomino_type,141*sizeof(polyomino_type)); + for (p=0;p<141;p++) { + copy_polyomino(sp->polyomino[p],elevenomino1,1); + } + + sp->check_ok = check_elevenomino_puzzle; + + return 1; +} + +/************************************************** +The main functions. +**************************************************/ + +#define allocate(p,type,size) p = (type *) malloc(size); if ((p)==NULL) {free_polyominoes(sp); return;} + +ENTRYPOINT void +init_polyominoes (ModeInfo * mi) +{ + polyominoesstruct *sp; + int i,x,y, start; + int box1, box2; + int *perm; + + if (polyominoeses == NULL) { + if ((polyominoeses + = (polyominoesstruct *) calloc(MI_NUM_SCREENS(mi),sizeof (polyominoesstruct))) + == NULL) + return; + } + sp = &polyominoeses[MI_SCREEN(mi)]; + + free_polyominoes(sp); + + sp->rot180 = 0; + sp->counter = 0; + + if (MI_IS_FULLRANDOM(mi)) { + sp->identical = (Bool) (LRAND() & 1); + sp->use3D = (Bool) (NRAND(4)); + } else { + sp->identical = identical; + sp->use3D = !plain; + } + if (sp->identical) { + switch (NRAND(9)) { + case 0: + if (!set_pentomino_puzzle1(sp)) + return; + break; + case 1: + if (!set_hexomino_puzzle1(sp)) + return; + break; + case 2: + if (!set_heptomino_puzzle1(sp)) + return; + break; + case 3: + if (!set_heptomino_puzzle2(sp)) + return; + break; + case 4: + if (!set_elevenomino_puzzle1(sp)) + return; + break; + case 5: + if (!set_dekomino_puzzle1(sp)) + return; + break; + case 6: + if (!set_octomino_puzzle1(sp)) + return; + break; + case 7: + if (!set_pentomino_puzzle2(sp)) + return; + break; + case 8: + if (!set_elevenomino_puzzle2(sp)) + return; + break; + } + } else { + switch (NRAND(5)) { + case 0: + if (!set_pentomino_puzzle(sp)) + return; + break; + case 1: + if (!set_one_sided_pentomino_puzzle(sp)) + return; + break; + case 2: + if (!set_one_sided_hexomino_puzzle(sp)) + return; + break; + case 3: + if (!set_pent_hexomino_puzzle(sp)) + return; + break; + case 4: + if (!set_tetr_pentomino_puzzle(sp)) + return; + break; + } + } + + allocate(sp->attach_list,int,sp->nr_polyominoes*sizeof(int)); + sp->nr_attached = 0; + + if (sp->identical) { + allocate(sp->reason_to_not_attach,int,sp->nr_polyominoes*sp->nr_polyominoes*sizeof(int)); + } + + allocate(sp->array,int,sp->width*sp->height*sizeof(int)); + allocate(sp->changed_array,int,sp->width*sp->height*sizeof(int)); + for (x=0;xwidth;x++) for (y=0;yheight;y++) ARRAY(x,y) = -1; + + sp->left_right = NRAND(2); + sp->top_bottom = NRAND(2); + + box1 = MI_WIDTH(mi)/(sp->width+2); + box2 = MI_HEIGHT(mi)/(sp->height+2); + if (box1box = box1; + else + sp->box = box2; + + if (sp->box >= 12) { + sp->box = (sp->box/12)*12; + create_bitmaps(mi,sp); + if (!sp->use_bitmaps) + free_bitmaps(sp); + } + else + sp->use_bitmaps = 0; + + if (!sp->use_bitmaps) { + allocate(sp->rectangles,XRectangle,sp->width*sp->height*sizeof(XRectangle)); + allocate(sp->lines,XSegment,sp->width*sp->height*sizeof(XSegment)); + } + + allocate(perm,int,sp->nr_polyominoes*sizeof(int)); + random_permutation(sp->nr_polyominoes, perm); + sp->mono = MI_NPIXELS(mi) < 12; + start = NRAND(MI_NPIXELS(mi)); + for (i=0;inr_polyominoes;i++) + if (!sp->mono) { + sp->polyomino[i].color = MI_PIXEL(mi,(perm[i]*MI_NPIXELS(mi) / sp->nr_polyominoes + start) % MI_NPIXELS(mi)); + if (sp->rot180) { + sp->polyomino[i+1].color = sp->polyomino[i].color; + i++; + } + } + else + if(sp->use_bitmaps) + sp->polyomino[i].color = MI_WHITE_PIXEL(mi); + else + sp->polyomino[i].color = MI_BLACK_PIXEL(mi); + free(perm); + + if (sp->use_bitmaps) { + if (sp->mono) + sp->border_color = MI_WHITE_PIXEL(mi); + else + sp->border_color = MI_PIXEL(mi,NRAND(MI_NPIXELS(mi))); + } + + sp->x_margin = (MI_WIDTH(mi)-sp->box*sp->width)/2; + sp->y_margin = (MI_HEIGHT(mi)-sp->box*sp->height)/2; + + sp->wait = 0; + +#ifndef STANDALONE + /* Clear the background. */ + MI_CLEARWINDOW(mi); +#endif + +} + +ENTRYPOINT void +draw_polyominoes (ModeInfo * mi) +{ + polyominoesstruct *sp; + int poly_no,point_no,transform_index,done,another_attachment_try; + point_type attach_point; + int i,detach_until; + + if (polyominoeses == NULL) + return; + sp = &polyominoeses[MI_SCREEN(mi)]; + +#ifdef STANDALONE + if (sp->eraser) { + sp->eraser = erase_window (MI_DISPLAY(mi), MI_WINDOW(mi), sp->eraser); + return; + } +#endif + + if (MI_CYCLES(mi) != 0) { + if (++sp->counter > MI_CYCLES(mi)) { +#ifdef STANDALONE + sp->eraser = erase_window (MI_DISPLAY(mi), MI_WINDOW(mi), sp->eraser); +#endif /* STANDALONE */ + init_polyominoes(mi); + return; + } + } + + if (sp->box == 0) { +#ifdef STANDALONE + sp->eraser = erase_window (MI_DISPLAY(mi), MI_WINDOW(mi), sp->eraser); +#endif /* STANDALONE */ + init_polyominoes(mi); + return; + } + + MI_IS_DRAWN(mi) = True; + sp->wait--; + if (sp->wait>0) return; + + memset(sp->changed_array,0,sp->width*sp->height*sizeof(int)); + + poly_no = first_poly_no(sp); + point_no = 0; + transform_index = 0; + done = 0; + another_attachment_try = 1; + find_blank(sp,&attach_point); + if (sp->identical && sp->nr_attached < sp->nr_polyominoes) + memset(&REASON_TO_NOT_ATTACH(sp->nr_attached,0),0,sp->nr_polyominoes*sizeof(int)); + while(!done) { + if (sp->nr_attached < sp->nr_polyominoes) { + while (!done && another_attachment_try) { + done = attach(sp,poly_no,point_no,transform_index,attach_point,0,&REASON_TO_NOT_ATTACH(sp->nr_attached,0)); + if (done && sp->rot180) { + poly_no = first_poly_no(sp); + done = attach(sp,poly_no,point_no,transform_index,attach_point,1,&REASON_TO_NOT_ATTACH(sp->nr_attached-1,0)); + if (!done) + detach(sp,&poly_no,&point_no,&transform_index,&attach_point,0); + } + if (!done) + another_attachment_try = next_attach_try(sp,&poly_no,&point_no,&transform_index); + } + } + + if (sp->identical) { + if (!done) { + if (sp->nr_attached == 0) + done = 1; + else { + detach_until=sp->nr_attached-1; + if (sp->nr_attached < sp->nr_polyominoes) + while (detach_until>0 && REASON_TO_NOT_ATTACH(sp->nr_attached,detach_until)==0) + detach_until--; + while (sp->nr_attached>detach_until) { + if (sp->rot180) + detach(sp,&poly_no,&point_no,&transform_index,&attach_point,1); + detach(sp,&poly_no,&point_no,&transform_index,&attach_point,0); + if (sp->nr_attached+1+sp->rot180 < sp->nr_polyominoes) + for (i=0;inr_polyominoes;i++) + REASON_TO_NOT_ATTACH(sp->nr_attached,i) |= REASON_TO_NOT_ATTACH(sp->nr_attached+1+sp->rot180,i); + } + another_attachment_try = next_attach_try(sp,&poly_no,&point_no,&transform_index); + } + } + } + else { + if (!done) { + if (sp->nr_attached == 0) + done = 1; + else { + if (sp->rot180) + detach(sp,&poly_no,&point_no,&transform_index,&attach_point,1); + detach(sp,&poly_no,&point_no,&transform_index,&attach_point,0); + } + another_attachment_try = next_attach_try(sp,&poly_no,&point_no,&transform_index); + } + } + } + + if (sp->use_bitmaps) + draw_with_bitmaps(mi,sp); + else + draw_without_bitmaps(mi,sp); + + if (sp->nr_attached == sp->nr_polyominoes) + sp->wait = 100; + else + sp->wait = 0; +} + +ENTRYPOINT void +reshape_polyominoes(ModeInfo * mi, int width, int height) +{ + XClearWindow (MI_DISPLAY (mi), MI_WINDOW(mi)); + init_polyominoes (mi); +} + +ENTRYPOINT void +release_polyominoes(ModeInfo * mi) +{ + int screen; + + if (polyominoeses != NULL) { + for (screen=0;screen + * A pong screen saver + * + * Modified by Brian Sawicki to fix a small bug. + * Before this fix after a certain point the paddles would be too + * small for the program to effectively hit the ball. The score would + * then skyrocket as the paddles missed most every time. Added a max + * so that once a paddle gets 10 the entire game restarts. Special + * thanks to Scott Zager for some help on this. + * + * Modified by Trevor Blackwell to use analogtv.[ch] display. + * Also added gradual acceleration of the ball, shrinking of paddles, and + * scorekeeping. + * + * Modified by Gereon Steffens to add -clock and -noise + * options. See http://www.burovormkrijgers.nl (ugly flash site, + * navigate to Portfolio/Browse/Misc/Pong Clock) for the hardware implementation + * that gave me the idea. In clock mode, the score reflects the current time, and + * the paddles simply stop moving when it's time for the other side to score. This + * means that the display is only updated a few seconds *after* the minute actually + * changes, but I think this fuzzyness fits well with the display, and since we're + * not displaying seconds, who cares. While I was at it, I added a -noise option + * to control the noisyness of the display. + * + * 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. + */ + +/* + * TLB sez: I haven't actually seen a pong game since I was about 9. Can + * someone who has one make this look more realistic? Issues: + * + * - the font for scores is wrong. For example '0' was square. + * - was there some kind of screen display when someone won? + * - did the ball move smoothly, or was the X or Y position quantized? + * + * It could also use better player logic: moving the paddle even when the ball + * is going away, and making mistakes instead of just not keeping up with the + * speeding ball. + * + * There is some info at http://www.mameworld.net/discrete/Atari/Atari.htm#Pong + * + * It says that the original Pong game did not have a microprocessor, or even a + * custom integrated circuit. It was all discrete logic. + * + */ + +#include "screenhack.h" +#include "analogtv.h" +/* #define OUTPUT_POS */ + +typedef struct _paddle { + int x; + int y; + int w; + int h; + int wait; + int lock; + int score; +} Paddle; + +typedef struct _ball { + int x; + int y; + int w; + int h; +} Ball; + +struct state { + Display *dpy; + Window window; + + int clock; + + Paddle l_paddle; + Paddle r_paddle; + Ball ball; + int bx,by; + int m_unit; + int paddle_rate; + double noise; + + analogtv *tv; + analogtv_input *inp; + analogtv_reception reception; + + int paddle_ntsc[4]; + int field_ntsc[4]; + int ball_ntsc[4]; + int score_ntsc[4]; + int net_ntsc[4]; + + analogtv_font score_font; +}; + + +enum { + PONG_W = ANALOGTV_VIS_LEN, + PONG_H = ANALOGTV_VISLINES, + PONG_TMARG = 10 +}; + +static void +hit_top_bottom(struct state *st) +{ + if ( (st->ball.y <= PONG_TMARG) || + (st->ball.y+st->ball.h >= PONG_H) ) + st->by=-st->by; +} + +static void +reset_score(struct state * st) +{ + if (st->clock) + { + /* init score to current time */ + time_t now = time(0); + struct tm* now_tm = localtime(&now); + + st->r_paddle.score = now_tm->tm_hour; + st->l_paddle.score = now_tm->tm_min; + } + else + { + st->r_paddle.score = 0; + st->l_paddle.score = 0; + } +} + +static void +new_game(struct state *st) +{ + /* Starts a Whole New Game*/ + st->ball.x = PONG_W/2; + st->ball.y = PONG_H/2; + st->bx = st->m_unit; + st->by = st->m_unit; + + /* jwz: perhaps not totally accurate, but randomize things a little bit + so that games on multiple screens are not identical. */ + if (random() & 1) st->by = -st->by; + st->ball.y += (random() % (PONG_H/6))-(PONG_H/3); + + st->l_paddle.wait = 1; + st->l_paddle.lock = 0; + st->r_paddle.wait = 0; + st->r_paddle.lock = 0; + st->paddle_rate = st->m_unit-1; + reset_score(st); + + st->l_paddle.h = PONG_H/4; + st->r_paddle.h = PONG_H/4; +} + +static void +start_game(struct state *st) +{ + /*Init the ball*/ + st->ball.x = PONG_W/2; + st->ball.y = PONG_H/2; + st->bx = st->m_unit; + st->by = st->m_unit; + + /* jwz: perhaps not totally accurate, but randomize things a little bit + so that games on multiple screens are not identical. */ + if (random() & 1) st->by = -st->by; + st->ball.y += (random() % (PONG_H/6))-(PONG_H/3); + + st->l_paddle.wait = 1; + st->l_paddle.lock = 0; + st->r_paddle.wait = 0; + st->r_paddle.lock = 0; + st->paddle_rate = st->m_unit-1; + + if (st->l_paddle.h > 10) st->l_paddle.h= st->l_paddle.h*19/20; + if (st->r_paddle.h > 10) st->r_paddle.h= st->r_paddle.h*19/20; +} + +static void +hit_paddle(struct state *st) +{ + if ( st->ball.x + st->ball.w >= st->r_paddle.x && + st->bx > 0 ) /*we are traveling to the right*/ + { + if ((st->ball.y + st->ball.h > st->r_paddle.y) && + (st->ball.y < st->r_paddle.y + st->r_paddle.h)) + { + st->bx=-st->bx; + st->l_paddle.wait = 0; + st->r_paddle.wait = 1; + st->r_paddle.lock = 0; + st->l_paddle.lock = 0; + } + else + { + if (st->clock) + { + reset_score(st); + } + else + { + st->r_paddle.score++; + if (st->r_paddle.score >=10) + new_game(st); + else + start_game(st); + } + } + } + + if (st->ball.x <= st->l_paddle.x + st->l_paddle.w && + st->bx < 0 ) /*we are traveling to the left*/ + { + if ( st->ball.y + st->ball.h > st->l_paddle.y && + st->ball.y < st->l_paddle.y + st->l_paddle.h) + { + st->bx=-st->bx; + st->l_paddle.wait = 1; + st->r_paddle.wait = 0; + st->r_paddle.lock = 0; + st->l_paddle.lock = 0; + } + else + { + if (st->clock) + { + reset_score(st); + } + else + { + st->l_paddle.score++; + if (st->l_paddle.score >= 10) + new_game(st); + else + start_game(st); + } + } + } +} + +static void * +pong_init (Display *dpy, Window window) +{ + struct state *st = (struct state *) calloc (1, sizeof(*st)); + + int i; + struct { + int w, h; + char *s[10]; + } fonts[2] = { + { /* regular pong font */ + /* If you think we haven't learned anything since the early 70s, + look at this font for a while */ + 4, 6, + { + "****" + "* *" + "* *" + "* *" + "* *" + "****", + + " *" + " *" + " *" + " *" + " *" + " *", + + "****" + " *" + "****" + "* " + "* " + "****", + + "****" + " *" + "****" + " *" + " *" + "****", + + "* *" + "* *" + "****" + " *" + " *" + " *", + + "****" + "* " + "****" + " *" + " *" + "****", + + "****" + "* " + "****" + "* *" + "* *" + "****", + + "****" + " *" + " *" + " *" + " *" + " *", + + "****" + "* *" + "****" + "* *" + "* *" + "****", + + "****" + "* *" + "****" + " *" + " *" + " *" + } + }, + { /* pong clock font - hand-crafted double size looks better */ + 8, 12, + { + "####### " + "####### " + "## ## " + "## ## " + "## ## " + "## ## " + "## ## " + "## ## " + "## ## " + "####### " + "####### ", + + " ## " + " ## " + " ## " + " ## " + " ## " + " ## " + " ## " + " ## " + " ## " + " ## " + " ## ", + + "####### " + "####### " + " ## " + " ## " + "####### " + "####### " + "## " + "## " + "## " + "####### " + "####### ", + + "####### " + "####### " + " ## " + " ## " + "####### " + "####### " + " ## " + " ## " + " ## " + "####### " + "####### ", + + "## ## " + "## ## " + "## ## " + "## ## " + "####### " + "####### " + " ## " + " ## " + " ## " + " ## " + " ## ", + + "####### " + "####### " + "## " + "## " + "####### " + "####### " + " ## " + " ## " + " ## " + "####### " + "####### ", + + "####### " + "####### " + "## " + "## " + "####### " + "####### " + "## ## " + "## ## " + "## ## " + "####### " + "####### ", + + "####### " + "####### " + " ## " + " ## " + " ## " + " ## " + " ## " + " ## " + " ## " + " ## " + " ## ", + + "####### " + "####### " + "## ## " + "## ## " + "####### " + "####### " + "## ## " + "## ## " + "## ## " + "####### " + "####### ", + + "####### " + "####### " + "## ## " + "## ## " + "####### " + "####### " + " ## " + " ## " + " ## " + "####### " + "####### " + + } + } + }; + + st->dpy = dpy; + st->window = window; + st->tv=analogtv_allocate(st->dpy, st->window); + analogtv_set_defaults(st->tv, ""); + + + st->clock = get_boolean_resource(st->dpy, "clock", "Boolean"); + + analogtv_make_font(st->dpy, st->window, &st->score_font, + fonts[st->clock].w, fonts[st->clock].h, NULL); + + for (i=0; i<10; ++i) + { + analogtv_font_set_char(&st->score_font, '0'+i, fonts[st->clock].s[i]); + } + +#ifdef OUTPUT_POS + printf("screen(%d,%d,%d,%d)\n",0,0,PONG_W,PONG_H); +#endif + + st->inp=analogtv_input_allocate(); + analogtv_setup_sync(st->inp, 0, 0); + + st->reception.input = st->inp; + st->reception.level = 2.0; + st->reception.ofs=0; +#if 0 + if (random()) { + st->reception.multipath = frand(1.0); + } else { +#endif + st->reception.multipath=0.0; +#if 0 + } +#endif + + /*Init the paddles*/ + st->l_paddle.x = 8; + st->l_paddle.y = 100; + st->l_paddle.w = 16; + st->l_paddle.h = PONG_H/4; + st->l_paddle.wait = 1; + st->l_paddle.lock = 0; + st->r_paddle = st->l_paddle; + st->r_paddle.x = PONG_W - 8 - st->r_paddle.w; + st->r_paddle.wait = 0; + /*Init the ball*/ + st->ball.x = PONG_W/2; + st->ball.y = PONG_H/2; + st->ball.w = 16; + st->ball.h = 8; + + st->m_unit = get_integer_resource (st->dpy, "speed", "Integer"); + st->noise = get_float_resource(st->dpy, "noise", "Float"); + st->clock = get_boolean_resource(st->dpy, "clock", "Boolean"); + + if (!st->clock) + { + st->score_font.y_mult *= 2; + st->score_font.x_mult *= 2; + } + + reset_score(st); + + start_game(st); + + analogtv_lcp_to_ntsc(ANALOGTV_BLACK_LEVEL, 0.0, 0.0, st->field_ntsc); + analogtv_lcp_to_ntsc(100.0, 0.0, 0.0, st->ball_ntsc); + analogtv_lcp_to_ntsc(100.0, 0.0, 0.0, st->paddle_ntsc); + analogtv_lcp_to_ntsc(100.0, 0.0, 0.0, st->score_ntsc); + analogtv_lcp_to_ntsc(100.0, 0.0, 0.0, st->net_ntsc); + + analogtv_draw_solid(st->inp, + ANALOGTV_VIS_START, ANALOGTV_VIS_END, + ANALOGTV_TOP, ANALOGTV_BOT, + st->field_ntsc); + + return st; +} + +static void +p_logic(struct state *st, Paddle *p) +{ + int targ; + if (st->bx > 0) { + targ = st->ball.y + st->by * (st->r_paddle.x-st->ball.x) / st->bx; + } + else if (st->bx < 0) { + targ = st->ball.y - st->by * (st->ball.x - st->l_paddle.x - st->l_paddle.w) / st->bx; + } + else { + targ = st->ball.y; + } + if (targ > PONG_H) targ=PONG_H; + if (targ < 0) targ=0; + + if (targ < p->y && !p->lock) + { + p->y -= st->paddle_rate; + } + else if (targ > (p->y + p->h) && !p->lock) + { + p->y += st->paddle_rate; + } + else + { + int move=targ - (p->y + p->h/2); + if (move>st->paddle_rate) move=st->paddle_rate; + if (move<-st->paddle_rate) move=-st->paddle_rate; + p->y += move; + p->lock = 1; + } +} + +static void +p_hit_top_bottom(Paddle *p) +{ + if(p->y <= PONG_TMARG) + { + p->y = PONG_TMARG; + } + if((p->y + p->h) >= PONG_H) + { + p->y = PONG_H - p->h; + } +} + +/* + XFillRectangle (dpy, window, gc, p->x, p->y, p->w, p->h); + if (old_v > p->y) + { + XClearArea(dpy,window, p->x, p->y + p->h, + p->w, (old_v + p->h) - (p->y + p->h), 0); + } + else if (old_v < p->y) + { + XClearArea(dpy,window, p->x, old_v, p->w, p->y - old_v, 0); + } +*/ +static void +paint_paddle(struct state *st, Paddle *p) +{ + analogtv_draw_solid(st->inp, + ANALOGTV_VIS_START + p->x, ANALOGTV_VIS_START + p->x + p->w, + ANALOGTV_TOP, ANALOGTV_BOT, + st->field_ntsc); + + analogtv_draw_solid(st->inp, + ANALOGTV_VIS_START + p->x, ANALOGTV_VIS_START + p->x + p->w, + ANALOGTV_TOP + p->y, ANALOGTV_TOP + p->y + p->h, + st->paddle_ntsc); +} + +/* + XClearArea(dpy,window, old_ballx, old_bally, st->ball.d, st->ball.d, 0); + XFillRectangle (dpy, window, gc, st->ball.x, st->ball.y, st->ball.d, st->ball.d); + XFillRectangle (dpy, window, gc, xgwa.width / 2, 0, st->ball.d, xgwa.height); +*/ + +static void +erase_ball(struct state *st) +{ + analogtv_draw_solid(st->inp, + ANALOGTV_VIS_START + st->ball.x, ANALOGTV_VIS_START + st->ball.x + st->ball.w, + ANALOGTV_TOP + st->ball.y, ANALOGTV_TOP + st->ball.y + st->ball.h, + st->field_ntsc); +} + +static void +paint_ball(struct state *st) +{ + analogtv_draw_solid(st->inp, + ANALOGTV_VIS_START + st->ball.x, ANALOGTV_VIS_START + st->ball.x + st->ball.w, + ANALOGTV_TOP + st->ball.y, ANALOGTV_TOP + st->ball.y + st->ball.h, + st->ball_ntsc); +} + +static void +paint_score(struct state *st) +{ + char buf[256]; + + char* fmt = (st->clock ? "%02d" : "%d"); + + analogtv_draw_solid(st->inp, + ANALOGTV_VIS_START, ANALOGTV_VIS_END, + ANALOGTV_TOP, ANALOGTV_TOP + 10+ st->score_font.char_h * st->score_font.y_mult, + st->field_ntsc); + + + sprintf(buf, fmt ,st->r_paddle.score%256); + analogtv_draw_string(st->inp, &st->score_font, buf, + ANALOGTV_VIS_START + 130, ANALOGTV_TOP + 8, + st->score_ntsc); + + sprintf(buf, fmt, st->l_paddle.score%256); + analogtv_draw_string(st->inp, &st->score_font, buf, + ANALOGTV_VIS_END - 200, ANALOGTV_TOP + 8, + st->score_ntsc); + +} + +static void +paint_net(struct state *st) +{ + int x,y; + + x=(ANALOGTV_VIS_START + ANALOGTV_VIS_END)/2; + + for (y=ANALOGTV_TOP; yinp, x-2, x+2, y, y+3, + st->net_ntsc); + analogtv_draw_solid(st->inp, x-2, x+2, y+3, y+6, + st->field_ntsc); + + } +} + +static unsigned long +pong_draw (Display *dpy, Window window, void *closure) +{ + struct state *st = (struct state *) closure; + + if (st->clock) + { + time_t now = time(0); + struct tm* tm_now = localtime(&now); + + if (st->r_paddle.score != tm_now->tm_hour) + { + /* l paddle must score */ + st->r_paddle.wait = 1; + } + else if (st->l_paddle.score != tm_now->tm_min) + { + /* r paddle must score */ + st->l_paddle.wait = 1; + } + } + erase_ball(st); + + st->ball.x += st->bx; + st->ball.y += st->by; + + if (!st->clock) + { + /* in non-clock mode, occasionally increase ball speed */ + if ((random()%40)==0) { + if (st->bx>0) st->bx++; else st->bx--; + } + } + + if (!st->r_paddle.wait) + { + p_logic(st, &st->r_paddle); + } + if (!st->l_paddle.wait) + { + p_logic(st, &st->l_paddle); + } + + p_hit_top_bottom(&st->r_paddle); + p_hit_top_bottom(&st->l_paddle); + + hit_top_bottom(st); + hit_paddle(st); + + #ifdef OUTPUT_POS + printf("(%d,%d,%d,%d)\n",st->ball.x,st->ball.y,st->ball.w,st->ball.h); + #endif + + paint_score(st); + + paint_net(st); + + if (1) { + paint_paddle(st, &st->r_paddle); + paint_paddle(st, &st->l_paddle); + } + if (1) paint_ball(st); + + analogtv_init_signal(st->tv, st->noise); + analogtv_reception_update(&st->reception); + analogtv_add_signal(st->tv, &st->reception); + analogtv_draw(st->tv); + + return 10000; +} + + + +static const char *pong_defaults [] = { + ".background: black", + ".foreground: white", + "*speed: 6", + "*noise: 0.04", + "*clock: false", + ANALOGTV_DEFAULTS + 0 +}; + +static XrmOptionDescRec pong_options [] = { + { "-speed", ".speed", XrmoptionSepArg, 0 }, + { "-noise", ".noise", XrmoptionSepArg, 0 }, + { "-clock", ".clock", XrmoptionNoArg, "true" }, + ANALOGTV_OPTIONS + { 0, 0, 0, 0 } +}; + +static void +pong_reshape (Display *dpy, Window window, void *closure, + unsigned int w, unsigned int h) +{ + struct state *st = (struct state *) closure; + analogtv_reconfigure (st->tv); +} + +static Bool +pong_event (Display *dpy, Window window, void *closure, XEvent *event) +{ + return False; +} + +static void +pong_free (Display *dpy, Window window, void *closure) +{ + struct state *st = (struct state *) closure; + analogtv_release(st->tv); + free (st); +} + +XSCREENSAVER_MODULE ("Pong", pong) diff --git a/hacks/pong.man b/hacks/pong.man new file mode 100644 index 00000000..d9d7f4ac --- /dev/null +++ b/hacks/pong.man @@ -0,0 +1,82 @@ +.TH XScreenSaver 1 "5-May-2004" "X Version 11" +.SH NAME +pong - Pong Home Video Game Emulator +.SH SYNOPSIS +.B pong +[\-display \fIhost:display.screen\fP] [\-foreground \fIcolor\fP] +[\-background \fIcolor\fP] [\-window] [\-root] [\-mono] [\-install] +[\-visual \fIvisual\fP] +[\-clock \fIfloat\fP] +[\-noise] +[\-fps] +.SH DESCRIPTION +The +.I pong +program simulates an ancient Pong home video game, as well as various +artifacts from displaying it on a color TV set. +.SH OPTIONS +.I pong +accepts the following options: +.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 \-mono +If on a color display, pretend we're on a monochrome display. +.TP 8 +.B \-install +Install a private colormap for the window. +.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 \-clock +The score of the game will be the current time. +.TP 8 +.B \-noise \fIfloat\fP +How noisy the video signal should be (between 0.0 and 4.0 or so). +.TP 8 +.B \-fps +Display the current frame rate and CPU load. +.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 X RESOURCES +Notable X resources supported include the following which correspond +to standard TV controls: +.BR analogTVTint , +.BR analogTVColor , +.BR analogTVBrightness , +and +.BR analogTVContrast . +They range from 0 to 100, except for tint which is an angle +between -180 and +180. +.SH TRADEMARKS +Pong may be a trademark. + +.SH SEE ALSO +.BR X (1), +.BR xscreensaver (1), +.BR xanalogtv (MANSUFFIX), +.BR apple2 (MANSUFFIX) +.SH COPYRIGHT +2003 by Jeremy English. 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 +Original Pong program by Jeremy English . Scoring +and television emulation by Trevor Blackwell . diff --git a/hacks/popsquares.c b/hacks/popsquares.c new file mode 100644 index 00000000..15cb61b4 --- /dev/null +++ b/hacks/popsquares.c @@ -0,0 +1,267 @@ +/* Copyright (c) 2003 Levi Burton + * + * 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. + */ + +#include "screenhack.h" +#include "colors.h" + +#ifdef HAVE_DOUBLE_BUFFER_EXTENSION +# include "xdbe.h" +#endif /* HAVE_DOUBLE_BUFFER_EXTENSION */ + +typedef struct _square { + int x, y, w, h; + int color; +} square; + +static void +randomize_square_colors(square *squares, int nsquares, int ncolors) +{ + int i; + square *s = squares; + for (i = 0; i < nsquares; i++) + s[i].color = random() % ncolors; +} + + +struct state { + Display *dpy; + Window window; + + int delay, subdivision, border, ncolors, twitch, dbuf; + XWindowAttributes xgwa; + GC gc; + XColor *colors; + int sw, sh, gw, gh, nsquares; + square *squares; + Pixmap b, ba, bb; +#ifdef HAVE_DOUBLE_BUFFER_EXTENSION + XdbeBackBuffer backb; +#endif /* HAVE_DOUBLE_BUFFER_EXTENSION */ +}; + +static void * +popsquares_init (Display *dpy, Window window) +{ + struct state *st = (struct state *) calloc (1, sizeof(*st)); + int x, y; + double s1, v1, s2, v2 = 0; + int h1, h2 = 0; + /* Not sure how to use DBEClear */ + /* Bool dbeclear_p = get_boolean_resource(dpy, "useDBEClear", "Boolean"); */ + XColor fg, bg; + XGCValues gcv; + + st->dpy = dpy; + st->window = window; + + st->delay = get_integer_resource (st->dpy, "delay", "Integer"); + st->subdivision = get_integer_resource(st->dpy, "subdivision", "Integer"); + st->border = get_integer_resource(st->dpy, "border", "Integer"); + st->ncolors = get_integer_resource(st->dpy, "ncolors", "Integer"); + st->twitch = get_boolean_resource(st->dpy, "twitch", "Boolean"); + st->dbuf = get_boolean_resource(st->dpy, "doubleBuffer", "Boolean"); + +# ifdef HAVE_COCOA /* Don't second-guess Quartz's double-buffering */ + st->dbuf = False; +# endif + + XGetWindowAttributes (st->dpy, st->window, &st->xgwa); + + fg.pixel = get_pixel_resource (st->dpy, st->xgwa.colormap, "foreground", "Foreground"); + bg.pixel = get_pixel_resource (st->dpy, st->xgwa.colormap, "background", "Background"); + + XQueryColor (st->dpy, st->xgwa.colormap, &fg); + XQueryColor (st->dpy, st->xgwa.colormap, &bg); + + st->sw = st->xgwa.width / st->subdivision; + st->sh = st->xgwa.height / st->subdivision; + st->gw = st->sw ? st->xgwa.width / st->sw : 0; + st->gh = st->sh ? st->xgwa.height / st->sh : 0; + st->nsquares = st->gw * st->gh; + + gcv.foreground = fg.pixel; + gcv.background = bg.pixel; + st->gc = XCreateGC (st->dpy, st->window, GCForeground|GCBackground, &gcv); + + st->colors = (XColor *) calloc (st->ncolors, sizeof(XColor)); + st->squares = (square *) calloc (st->nsquares, sizeof(square)); + + rgb_to_hsv (fg.red, fg.green, fg.blue, &h1, &s1, &v1); + rgb_to_hsv (bg.red, bg.green, bg.blue, &h2, &s2, &v2); + make_color_ramp (st->dpy, st->xgwa.colormap, + h1, s1, v1, + h2, s2, v2, + st->colors, &st->ncolors, /* would this be considered a value-result argument? */ + True, True, False); + if (st->ncolors < 2) + { + fprintf (stderr, "%s: insufficient colors!\n", progname); + exit (1); + } + + for (y = 0; y < st->gh; y++) + for (x = 0; x < st->gw; x++) + { + square *s = (square *) &st->squares[st->gw * y + x]; + s->w = st->sw; + s->h = st->sh; + s->x = x * st->sw; + s->y = y * st->sh; + } + + randomize_square_colors(st->squares, st->nsquares, st->ncolors); + + if (st->dbuf) + { +#ifdef HAVE_DOUBLE_BUFFER_EXTENSION + st->b = xdbe_get_backbuffer (st->dpy, st->window, XdbeUndefined); + st->backb = st->b; +#endif /* HAVE_DOUBLE_BUFFER_EXTENSION */ + if (!st->b) + { + st->ba = XCreatePixmap (st->dpy, st->window, st->xgwa.width, st->xgwa.height, st->xgwa.depth); + st->bb = XCreatePixmap (st->dpy, st->window, st->xgwa.width, st->xgwa.height, st->xgwa.depth); + st->b = st->ba; + } + } + else + { + st->b = st->window; + } + + return st; +} + +static unsigned long +popsquares_draw (Display *dpy, Window window, void *closure) +{ + struct state *st = (struct state *) closure; + int x, y; + for (y = 0; y < st->gh; y++) + for (x = 0; x < st->gw; x++) + { + square *s = (square *) &st->squares[st->gw * y + x]; + XSetForeground (st->dpy, st->gc, st->colors[s->color].pixel); + XFillRectangle (st->dpy, st->b, st->gc, s->x, s->y, + st->border ? s->w - st->border : s->w, + st->border ? s->h - st->border : s->h); + s->color++; + if (s->color == st->ncolors) + { + if (st->twitch && ((random() % 4) == 0)) + randomize_square_colors (st->squares, st->nsquares, st->ncolors); + else + s->color = random() % st->ncolors; + } + } +#ifdef HAVE_DOUBLE_BUFFER_EXTENSION + if (st->backb) + { + XdbeSwapInfo info[1]; + info[0].swap_window = st->window; + info[0].swap_action = XdbeUndefined; + XdbeSwapBuffers (st->dpy, info, 1); + } + else +#endif /* HAVE_DOUBLE_BUFFER_EXTENSION */ + if (st->dbuf) + { + XCopyArea (st->dpy, st->b, st->window, st->gc, 0, 0, + st->xgwa.width, st->xgwa.height, 0, 0); + st->b = (st->b == st->ba ? st->bb : st->ba); + } + + return st->delay; +} + + +static void +popsquares_reshape (Display *dpy, Window window, void *closure, + unsigned int w, unsigned int h) +{ + struct state *st = (struct state *) closure; + int x, y; + XGetWindowAttributes (st->dpy, st->window, &st->xgwa); + st->sw = st->xgwa.width / st->subdivision; + st->sh = st->xgwa.height / st->subdivision; + st->gw = st->sw ? st->xgwa.width / st->sw : 0; + st->gh = st->sh ? st->xgwa.height / st->sh : 0; + st->nsquares = st->gw * st->gh; + free (st->squares); + st->squares = (square *) calloc (st->nsquares, sizeof(square)); + + for (y = 0; y < st->gh; y++) + for (x = 0; x < st->gw; x++) + { + square *s = (square *) &st->squares[st->gw * y + x]; + s->w = st->sw; + s->h = st->sh; + s->x = x * st->sw; + s->y = y * st->sh; + } + + randomize_square_colors(st->squares, st->nsquares, st->ncolors); + + if (st->dbuf) { + XFreePixmap (dpy, st->ba); + XFreePixmap (dpy, st->bb); + st->ba = XCreatePixmap (st->dpy, st->window, st->xgwa.width, st->xgwa.height, st->xgwa.depth); + st->bb = XCreatePixmap (st->dpy, st->window, st->xgwa.width, st->xgwa.height, st->xgwa.depth); + st->b = st->ba; + } +} + +static Bool +popsquares_event (Display *dpy, Window window, void *closure, XEvent *event) +{ + return False; +} + +static void +popsquares_free (Display *dpy, Window window, void *closure) +{ + struct state *st = (struct state *) closure; + free (st); +} + + +static const char *popsquares_defaults [] = { + ".background: #0000FF", + ".foreground: #00008B", + "*delay: 25000", + "*subdivision: 5", + "*border: 1", + "*ncolors: 128", + "*twitch: False", + "*doubleBuffer: False", +#ifdef HAVE_DOUBLE_BUFFER_EXTENSION + "*useDBE: True", + "*useDBEClear: True", +#endif /* HAVE_DOUBLE_BUFFER_EXTENSION */ + 0 +}; + +static XrmOptionDescRec popsquares_options [] = { + { "-fg", ".foreground", XrmoptionSepArg, 0}, + { "-bg", ".background", XrmoptionSepArg, 0}, + { "-delay", ".delay", XrmoptionSepArg, 0 }, + { "-subdivision", ".subdivision", XrmoptionSepArg, 0 }, + { "-border", ".border", XrmoptionSepArg, 0}, + { "-ncolors", ".ncolors", XrmoptionSepArg, 0 }, + { "-twitch", ".twitch", XrmoptionNoArg, "True" }, + { "-no-twitch", ".twitch", XrmoptionNoArg, "False" }, + { "-db", ".doubleBuffer", XrmoptionNoArg, "True" }, + { "-no-db", ".doubleBuffer", XrmoptionNoArg, "False" }, + { 0, 0, 0, 0 } +}; + + +XSCREENSAVER_MODULE ("PopSquares", popsquares) diff --git a/hacks/pyro.c b/hacks/pyro.c new file mode 100644 index 00000000..ca540f72 --- /dev/null +++ b/hacks/pyro.c @@ -0,0 +1,368 @@ +/* xscreensaver, Copyright (c) 1992-2008 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. + */ + +/* Draw some fireworks. Inspired from TI Explorer Lisp code by + John S. Pezaris + */ + +#include +#include "screenhack.h" + +struct projectile { + int x, y; /* position */ + int dx, dy; /* velocity */ + int decay; + int size; + int fuse; + Bool primary; + Bool dead; + XColor color; + struct projectile *next_free; +}; + +#define PI_2000 6284 + + +struct state { + Display *dpy; + Window window; + + struct projectile *projectiles, *free_projectiles; + struct projectile **sorted_projectiles; + + GC draw_gc, erase_gc; + unsigned int default_fg_pixel; + Colormap cmap; + + int how_many, frequency, scatter, delay; + + int sin_cache[PI_2000]; + int cos_cache[PI_2000]; + + int draw_xlim, draw_ylim, real_draw_xlim, real_draw_ylim; + + unsigned long last_pixel; +}; + + + +/* Slightly whacked, for better explosions + */ + +static void +cache(struct state *st) +{ /*needs to be run once. Could easily be */ + int i; /*reimplemented to run and cache at compile-time,*/ + double dA; /*saving on init_pyro time */ + for (i=0; icos_cache[i]=(int) (cos(((double)i)/1000.0)*dA*2500.0); + st->sin_cache[i]=(int) (sin(((double)i)/1000.0)*dA*2500.0); + } +} + + +static struct projectile * +get_projectile (struct state *st) +{ + struct projectile *p; + if (st->free_projectiles) + { + p = st->free_projectiles; + st->free_projectiles = p->next_free; + p->next_free = 0; + p->dead = False; + return p; + } + else + return 0; +} + +static void +free_projectile (struct state *st, struct projectile *p) +{ + p->next_free = st->free_projectiles; + st->free_projectiles = p; + p->dead = True; +} + +static void +launch (struct state *st, + int xlim, int ylim, int g) +{ + struct projectile *p = get_projectile (st); + int x, dx, xxx; + if (! p) return; + + do { + x = (random () % xlim); + dx = 30000 - (random () % 60000); + xxx = x + (dx * 200); + } while (xxx <= 0 || xxx >= xlim); + + p->x = x; + p->y = ylim; + p->dx = dx; + p->size = 8000; + p->decay = 0; + p->dy = (random () % 4000) - 13000; + p->fuse = ((((random () % 500) + 500) * abs (p->dy / g)) / 1000); + p->primary = True; + + /* cope with small windows -- those constants assume big windows. */ + { + int dd = 1000000 / ylim; + if (dd > 1) + p->fuse /= dd; + } + + if (! mono_p) + { + hsv_to_rgb (random () % 360, 1.0, 1.0, + &p->color.red, &p->color.green, &p->color.blue); + p->color.flags = DoRed | DoGreen | DoBlue; + if (!XAllocColor (st->dpy, st->cmap, &p->color)) + { + p->color.pixel = WhitePixel (st->dpy, DefaultScreen (st->dpy)); + p->color.red = p->color.green = p->color.blue = 0xFFFF; + } + } +} + +static struct projectile * +shrapnel (struct state *st, struct projectile *parent) +{ + struct projectile *p = get_projectile (st); + int v; + if (! p) return 0; + p->x = parent->x; + p->y = parent->y; + v=random () % PI_2000; + p->dx =(st->sin_cache[v]) + parent->dx; + p->dy =(st->cos_cache[v]) + parent->dy; + p->decay = (random () % 50) - 60; + p->size = (parent->size * 2) / 3; + p->fuse = 0; + p->primary = False; + + p->color = parent->color; + if (! mono_p) + XAllocColor (st->dpy, st->cmap, &p->color); /* dup the lock */ + + return p; +} + +static void * +pyro_init (Display *dpy, Window window) +{ + struct state *st = (struct state *) calloc (1, sizeof(*st)); + int i; + XGCValues gcv; + XWindowAttributes xgwa; + st->dpy = dpy; + st->window = window; + XGetWindowAttributes (st->dpy, st->window, &xgwa); + st->last_pixel = ~0; + st->cmap = xgwa.colormap; + st->delay = get_integer_resource (st->dpy, "delay", "Integer"); + st->how_many = get_integer_resource (st->dpy, "count", "Integer"); + st->frequency = get_integer_resource (st->dpy, "frequency", "Integer"); + st->scatter = get_integer_resource (st->dpy, "scatter", "Integer"); + if (st->how_many <= 0) st->how_many = 100; + if (st->frequency <= 0) st->frequency = 30; + if (st->scatter <= 0) st->scatter = 20; + st->projectiles = 0; + st->free_projectiles = 0; + st->projectiles = (struct projectile *) + calloc (st->how_many, sizeof (*st->projectiles)); + st->sorted_projectiles = (struct projectile **) + calloc (st->how_many, sizeof (*st->sorted_projectiles)); + for (i = 0; i < st->how_many; i++) + free_projectile (st, &st->projectiles [i]); + for (i = 0; i < st->how_many; i++) + st->sorted_projectiles[i] = &st->projectiles[i]; + gcv.foreground = st->default_fg_pixel = + get_pixel_resource (st->dpy, st->cmap, "foreground", "Foreground"); + st->draw_gc = XCreateGC (st->dpy, st->window, GCForeground, &gcv); + gcv.foreground = get_pixel_resource (st->dpy, st->cmap, "background", "Background"); + st->erase_gc = XCreateGC (st->dpy, st->window, GCForeground, &gcv); + XClearWindow (st->dpy, st->window); + cache(st); + + return st; +} + + +static int +projectile_pixel_sorter (const void *a, const void *b) +{ + struct projectile *pa = *(struct projectile **) a; + struct projectile *pb = *(struct projectile **) b; + if (pa->color.pixel == pb->color.pixel) return 0; + else if (pa->color.pixel < pb->color.pixel) return -1; + else return 1; +} + +static void +sort_by_pixel (struct state *st, int length) +{ + qsort ((void *) st->sorted_projectiles, + length, + sizeof(*st->sorted_projectiles), + projectile_pixel_sorter); +} + + +static unsigned long +pyro_draw (Display *dpy, Window window, void *closure) +{ + struct state *st = (struct state *) closure; + XWindowAttributes xgwa; + int g = 100; + int resort = 0; + int i; + + for (i = 0; i < st->how_many; i++) + { + struct projectile *p = st->sorted_projectiles [i]; + int old_x, old_y, old_size; + int size, x, y; + if (p->dead) continue; + old_x = p->x >> 10; + old_y = p->y >> 10; + old_size = p->size >> 10; + size = (p->size += p->decay) >> 10; + x = (p->x += p->dx) >> 10; + y = (p->y += p->dy) >> 10; + p->dy += (p->size >> 6); + if (p->primary) p->fuse--; + + /* erase old one */ + if (old_size > 0) + { + if (old_size == 1) + XDrawPoint (st->dpy, st->window, st->erase_gc, old_x, old_y); + else + XFillRectangle (st->dpy, st->window, st->erase_gc, old_x, old_y, + old_size, old_size); + } + + if ((p->primary ? (p->fuse > 0) : (p->size > 0)) && + x < st->real_draw_xlim && + y < st->real_draw_ylim && + x > 0 && + y > 0) + { + if (size > 0) + { + unsigned long pixel; + + if (mono_p || p->primary) + pixel = st->default_fg_pixel; + else + pixel = p->color.pixel; + + if (pixel != st->last_pixel) + { + st->last_pixel = pixel; + XSetForeground (st->dpy, st->draw_gc, pixel); + } + + if (size == 1) + XDrawPoint (st->dpy, st->window, st->draw_gc, x, y); + else if (size < 4) + XFillRectangle (st->dpy, st->window, st->draw_gc, x, y, size, size); + else + XFillArc (st->dpy, st->window, st->draw_gc, x, y, size, size, 0, 360*64); + } + } + else + { + free_projectile (st, p); + if (! mono_p) + if (p->color.pixel != WhitePixel (st->dpy, DefaultScreen (st->dpy))) + XFreeColors (st->dpy, st->cmap, &p->color.pixel, 1, 0); + } + + if (p->primary && p->fuse <= 0) + { + int j = (random () % st->scatter) + (st->scatter/2); + while (j--) + shrapnel (st, p); + resort = 1; + } + } + + if ((random () % st->frequency) == 0) + { + XGetWindowAttributes (st->dpy, st->window, &xgwa); + st->real_draw_xlim = xgwa.width; + st->real_draw_ylim = xgwa.height; + st->draw_xlim = st->real_draw_xlim * 1000; + st->draw_ylim = st->real_draw_ylim * 1000; + launch (st, st->draw_xlim, st->draw_ylim, g); + resort = 1; + } + + /* being sorted lets us avoid changing the GC's foreground color as often. */ + if (resort) + sort_by_pixel (st, st->how_many); + + return st->delay; +} + +static void +pyro_reshape (Display *dpy, Window window, void *closure, + unsigned int w, unsigned int h) +{ +} + +static Bool +pyro_event (Display *dpy, Window window, void *closure, XEvent *event) +{ + return False; +} + +static void +pyro_free (Display *dpy, Window window, void *closure) +{ + struct state *st = (struct state *) closure; + free (st); +} + + + +static const char *pyro_defaults [] = { + ".background: black", + ".foreground: white", + "*fpsSolid: true", + "*count: 600", + "*delay: 10000", + "*frequency: 30", + "*scatter: 100", + "*geometry: 800x500", + 0 +}; + +static XrmOptionDescRec pyro_options [] = { + { "-delay", ".delay", XrmoptionSepArg, 0 }, + { "-count", ".count", XrmoptionSepArg, 0 }, + { "-frequency", ".frequency", XrmoptionSepArg, 0 }, + { "-scatter", ".scatter", XrmoptionSepArg, 0 }, + { 0, 0, 0, 0 } +}; + +XSCREENSAVER_MODULE ("Pyro", pyro) diff --git a/hacks/pyro.man b/hacks/pyro.man new file mode 100644 index 00000000..914fad77 --- /dev/null +++ b/hacks/pyro.man @@ -0,0 +1,64 @@ +.TH XScreenSaver 1 "13-aug-92" "X Version 11" +.SH NAME +pyro - simulate fireworks +.SH SYNOPSIS +.B pyro +[\-display \fIhost:display.screen\fP] [\-foreground \fIcolor\fP] [\-background \fIcolor\fP] [\-window] [\-root] [\-mono] [\-install] [\-visual \fIvisual\fP] [\-count \fIinteger\fP] [\-frequency \fIinteger\fP] [\-scatter \fIinteger\fP] +[\-fps] +.SH DESCRIPTION +The \fIpyro\fP program simulates fireworks, in a way similar to a Macintosh +program of the same name. +.SH OPTIONS +.I pyro +accepts the following options: +.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 \-mono +If on a color display, pretend we're on a monochrome display. +.TP 8 +.B \-install +Install a private colormap for the window. +.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 \-count \fIinteger\fP +How many particles should be allowed on the screen at once. Default 600. +.TP 8 +.B \-frequency \fIinteger\fP +How often new missiles should launch. Default 30. +.TP 8 +.B \-scatter \fIinteger\fP +How many particles should appear when a missile explodes. Default 100. +The actual number used is between \fIN\fP and \fIN+(N/2)\fP. +.TP 8 +.B \-fps +Display the current frame rate and CPU load. +.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 1992 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 , 13-aug-92. diff --git a/hacks/qix.c b/hacks/qix.c new file mode 100644 index 00000000..ad1e26e7 --- /dev/null +++ b/hacks/qix.c @@ -0,0 +1,621 @@ +/* xscreensaver, Copyright (c) 1992-2008 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. + */ + +#include "screenhack.h" +#include "alpha.h" +#include + +#define MAXPOLY 16 +#define SCALE 6 + +struct qpoint { + int x, y; + int dx, dy; +}; + +struct qline { + struct qpoint *p; + XColor color; + Bool dead; +}; + +struct qix { + int id; + int fp; + int nlines; + int npoly; + struct qline *lines; +}; + +struct state { + Display *dpy; + Window window; + + GC draw_gc, erase_gc; + unsigned int default_fg_pixel; + long maxx, maxy, max_spread, max_size; + int color_shift; + Bool random_p, solid_p, xor_p, transparent_p, gravity_p; + int delay; + int count; + Colormap cmap; + int npoly; + Bool additive_p; + Bool cmap_p; + + GC *gcs[2]; + + int gtick; + + struct qix **qixes; +}; + + +static void +get_geom (struct state *st) +{ + XWindowAttributes xgwa; + XGetWindowAttributes (st->dpy, st->window, &xgwa); + st->maxx = ((long)(xgwa.width+1)<maxy = ((long)(xgwa.height+1)<nlines = nlines; + qix->lines = (struct qline *) calloc (qix->nlines, sizeof (struct qline)); + qix->npoly = st->npoly; + for (i = 0; i < qix->nlines; i++) + qix->lines[i].p = (struct qpoint *) + calloc(qix->npoly, sizeof(struct qpoint)); + +# ifndef HAVE_COCOA + if (!mono_p && !st->transparent_p) +# endif + { + hsv_to_rgb (random () % 360, frand (1.0), frand (0.5) + 0.5, + &qix->lines[0].color.red, &qix->lines[0].color.green, + &qix->lines[0].color.blue); + if (!XAllocColor (st->dpy, st->cmap, &qix->lines[0].color)) + { + qix->lines[0].color.pixel = st->default_fg_pixel; + XQueryColor (st->dpy, st->cmap, &qix->lines[0].color); + if (!XAllocColor (st->dpy, st->cmap, &qix->lines[0].color)) + abort (); + } + } + + if (st->max_size == 0) + { + for (i = 0; i < qix->npoly; i++) + { + qix->lines[0].p[i].x = random () % st->maxx; + qix->lines[0].p[i].y = random () % st->maxy; + } + } + else + { + /*assert(qix->npoly == 2);*/ + qix->lines[0].p[0].x = random () % st->maxx; + qix->lines[0].p[0].y = random () % st->maxy; + qix->lines[0].p[1].x = qix->lines[0].p[0].x + (random () % (st->max_size/2)); + qix->lines[0].p[1].y = qix->lines[0].p[0].y + (random () % (st->max_size/2)); + if (qix->lines[0].p[1].x > st->maxx) qix->lines[0].p[1].x = st->maxx; + if (qix->lines[0].p[1].y > st->maxy) qix->lines[0].p[1].y = st->maxy; + } + + for (i = 0; i < qix->npoly; i++) + { + qix->lines[0].p[i].dx = (random () % (st->max_spread + 1)) - (st->max_spread /2); + qix->lines[0].p[i].dy = (random () % (st->max_spread + 1)) - (st->max_spread /2); + } + qix->lines[0].dead = True; + + for (i = 1; i < qix->nlines; i++) + { + for(j=0; jnpoly; j++) + qix->lines[i].p[j] = qix->lines[0].p[j]; + qix->lines[i].color = qix->lines[0].color; + qix->lines[i].dead = qix->lines[0].dead; + +# ifndef HAVE_COCOA + if (!mono_p && !st->transparent_p) +# endif + if (!XAllocColor (st->dpy, st->cmap, &qix->lines[i].color)) + abort (); + } + return qix; +} + + + + +static void * +qix_init (Display *dpy, Window window) +{ + struct state *st = (struct state *) calloc (1, sizeof(*st)); + int nlines; + XGCValues gcv; + XWindowAttributes xgwa; + st->dpy = dpy; + st->window = window; + XGetWindowAttributes (st->dpy, st->window, &xgwa); + st->cmap = xgwa.colormap; + st->count = get_integer_resource (st->dpy, "count", "Integer"); + if (st->count <= 0) st->count = 1; + nlines = get_integer_resource (st->dpy, "segments", "Integer"); + if (nlines <= 0) nlines = 20; + st->npoly = get_integer_resource(st->dpy, "poly", "Integer"); + if (st->npoly <= 2) st->npoly = 2; + if (st->npoly > MAXPOLY) st->npoly = MAXPOLY; + get_geom (st); + st->max_spread = get_integer_resource (st->dpy, "spread", "Integer"); + if (st->max_spread <= 0) st->max_spread = 10; + st->max_spread <<= SCALE; + st->max_size = get_integer_resource (st->dpy, "size", "Integer"); + if (st->max_size < 0) st->max_size = 0; + st->max_size <<= SCALE; + st->random_p = get_boolean_resource (st->dpy, "random", "Boolean"); + st->solid_p = get_boolean_resource (st->dpy, "solid", "Boolean"); + st->xor_p = get_boolean_resource (st->dpy, "xor", "Boolean"); + st->transparent_p = get_boolean_resource (st->dpy, "transparent", "Boolean"); + st->gravity_p = get_boolean_resource(st->dpy, "gravity", "Boolean"); + st->delay = get_integer_resource (st->dpy, "delay", "Integer"); + st->color_shift = get_integer_resource (st->dpy, "colorShift", "Integer"); + if (st->color_shift < 0 || st->color_shift >= 360) st->color_shift = 5; + if (st->delay < 0) st->delay = 0; + + /* Clear up ambiguities regarding npoly */ + if (st->solid_p) + { + if (st->npoly != 2) + fprintf(stderr, "%s: Can't have -solid and -poly; using -poly 2\n", + progname); + st->npoly = 2; + } + if (st->npoly > 2) + { + if (st->max_size) + fprintf(stderr, "%s: Can't have -poly and -size; using -size 0\n", + progname); + st->max_size = 0; + } + + if (st->count == 1 && st->transparent_p) + st->transparent_p = False; /* it's a no-op */ + + if (st->transparent_p && CellsOfScreen (DefaultScreenOfDisplay (st->dpy)) <= 2) + { + fprintf (stderr, "%s: -transparent only works on color displays.\n", + progname); + st->transparent_p = False; + } + + if (st->xor_p && !st->transparent_p) + mono_p = True; + + st->gcs[0] = st->gcs[1] = 0; + gcv.foreground = st->default_fg_pixel = + get_pixel_resource (st->dpy, st->cmap, "foreground", "Foreground"); + + st->additive_p = get_boolean_resource (st->dpy, "additive", "Boolean"); + st->cmap_p = has_writable_cells (xgwa.screen, xgwa.visual); + +# ifndef HAVE_COCOA + if (st->transparent_p) + { + unsigned long *plane_masks = 0; + unsigned long base_pixel; + int nplanes = st->count; + int i; + + allocate_alpha_colors (xgwa.screen, xgwa.visual, st->cmap, + &nplanes, st->additive_p, &plane_masks, + &base_pixel); + + if (nplanes <= 1) + { + fprintf (stderr, + "%s: couldn't allocate any color planes; turning -transparent off.\n", + progname); + st->transparent_p = False; + if (st->xor_p) + goto NON_TRANSPARENT_XOR; + else + goto NON_TRANSPARENT; + } + else if (nplanes != st->count) + { + fprintf (stderr, + "%s: only allocated %d color planes (instead of %d).\n", + progname, nplanes, st->count); + st->count = nplanes; + } + + st->gcs[0] = (GC *) malloc (st->count * sizeof (GC)); + st->gcs[1] = (st->xor_p + ? st->gcs[0] + : (GC *) malloc (st->count * sizeof (GC))); + + for (i = 0; i < st->count; i++) + { + gcv.plane_mask = plane_masks [i]; + gcv.foreground = ~0; + +/* argh, I'm not sure how to make "-subtractive" work in truecolor... + if (!cmap_p && !additive_p) + gcv.function = GXclear; + */ + + if (st->xor_p) + { + gcv.function = GXxor; + st->gcs [0][i] = XCreateGC (st->dpy, st->window, + GCForeground|GCFunction|GCPlaneMask, + &gcv); + } + else + { + st->gcs [0][i] = XCreateGC (st->dpy, st->window, + GCForeground|GCPlaneMask, + &gcv); + gcv.foreground = 0; + st->gcs [1][i] = XCreateGC (st->dpy, st->window, + GCForeground|GCPlaneMask, + &gcv); +# ifdef HAVE_COCOA + /* jwxyz_XSetAntiAliasing (st->dpy, st->gcs [0][i], False); + jwxyz_XSetAntiAliasing (st->dpy, st->gcs [1][i], False); */ + if (st->transparent_p) + { + jwxyz_XSetAlphaAllowed (dpy, st->gcs [0][i], True); + jwxyz_XSetAlphaAllowed (dpy, st->gcs [1][i], True); + } +# endif /* HAVE_COCOA */ + } + } + + if (plane_masks) + free (plane_masks); + + XSetWindowBackground (st->dpy, st->window, base_pixel); + XClearWindow (st->dpy, st->window); + } + else +#endif /* !HAVE_COCOA */ + if (st->xor_p) + { +#ifndef HAVE_COCOA + NON_TRANSPARENT_XOR: +#endif + gcv.function = GXxor; + gcv.foreground = + (st->default_fg_pixel /* ^ get_pixel_resource (st->dpy, st->cmap, + "background", "Background")*/); + st->draw_gc = st->erase_gc = XCreateGC(st->dpy,st->window,GCForeground|GCFunction,&gcv); + } + else + { +#ifndef HAVE_COCOA + NON_TRANSPARENT: +#endif + st->draw_gc = XCreateGC (st->dpy, st->window, GCForeground, &gcv); + gcv.foreground = get_pixel_resource (st->dpy, st->cmap, + "background", "Background"); + st->erase_gc = XCreateGC (st->dpy, st->window, GCForeground, &gcv); + } + +#ifdef HAVE_COCOA + if (st->transparent_p) + jwxyz_XSetAlphaAllowed (dpy, st->draw_gc, True); +#endif + + st->qixes = (struct qix **) malloc ((st->count + 1) * sizeof (struct qix *)); + st->qixes [st->count] = 0; + while (st->count--) + { + st->qixes [st->count] = init_one_qix (st, nlines); + st->qixes [st->count]->id = st->count; + } + +# ifdef HAVE_COCOA + /* line-mode leaves turds without this. */ + jwxyz_XSetAntiAliasing (st->dpy, st->erase_gc, False); + jwxyz_XSetAntiAliasing (st->dpy, st->draw_gc, False); +# endif + + return st; +} + +static void +free_qline (struct state *st, + struct qline *qline, + struct qline *prev, + struct qix *qix) +{ + int i; + if (qline->dead || !prev) + ; + else if (st->solid_p) + { + XPoint points [4]; + /*assert(qix->npoly == 2);*/ + points [0].x = qline->p[0].x >> SCALE; + points [0].y = qline->p[0].y >> SCALE; + points [1].x = qline->p[1].x >> SCALE; + points [1].y = qline->p[1].y >> SCALE; + points [2].x = prev->p[1].x >> SCALE; + points [2].y = prev->p[1].y >> SCALE; + points [3].x = prev->p[0].x >> SCALE; + points [3].y = prev->p[0].y >> SCALE; + XFillPolygon (st->dpy, st->window, + (st->transparent_p && st->gcs[1] + ? st->gcs[1][qix->id] + : st->erase_gc), + points, 4, Complex, CoordModeOrigin); + } + else + { + /* XDrawLine (dpy, window, (transparent_p ? gcs[1][qix->id] : erase_gc), + qline->p1.x, qline->p1.y, qline->p2.x, qline->p2.y);*/ + XPoint points[MAXPOLY+1]; + for(i = 0; i < qix->npoly; i++) + { + points[i].x = qline->p[i].x >> SCALE; + points[i].y = qline->p[i].y >> SCALE; + } + points[qix->npoly] = points[0]; + XDrawLines(st->dpy, st->window, + (st->transparent_p && st->gcs[1] + ? st->gcs[1][qix->id] + : st->erase_gc), + points, qix->npoly+1, CoordModeOrigin); + } + + if (!mono_p && !st->transparent_p) + XFreeColors (st->dpy, st->cmap, &qline->color.pixel, 1, 0); + + qline->dead = True; +} + +static void +add_qline (struct state *st, + struct qline *qline, + struct qline *prev_qline, + struct qix *qix) +{ + int i; + + for(i=0; inpoly; i++) + qline->p[i] = prev_qline->p[i]; + qline->color = prev_qline->color; + qline->dead = prev_qline->dead; + +#define wiggle(point,delta,max) \ + if (st->random_p) delta += (random () % (1 << (SCALE+1))) - (1 << SCALE); \ + if (delta > st->max_spread) delta = st->max_spread; \ + else if (delta < -st->max_spread) delta = -st->max_spread; \ + point += delta; \ + if (point < 0) point = 0, delta = -delta, point += delta<<1; \ + else if (point > max) point = max, delta = -delta, point += delta<<1; + + if (st->gravity_p) + for(i=0; inpoly; i++) + qline->p[i].dy += 3; + + for (i = 0; i < qix->npoly; i++) + { + wiggle (qline->p[i].x, qline->p[i].dx, st->maxx); + wiggle (qline->p[i].y, qline->p[i].dy, st->maxy); + } + + if (st->max_size) + { + /*assert(qix->npoly == 2);*/ + if (qline->p[0].x - qline->p[1].x > st->max_size) + qline->p[0].x = qline->p[1].x + st->max_size + - (st->random_p ? random() % st->max_spread : 0); + else if (qline->p[1].x - qline->p[0].x > st->max_size) + qline->p[1].x = qline->p[0].x + st->max_size + - (st->random_p ? random() % st->max_spread : 0); + if (qline->p[0].y - qline->p[1].y > st->max_size) + qline->p[0].y = qline->p[1].y + st->max_size + - (st->random_p ? random() % st->max_spread : 0); + else if (qline->p[1].y - qline->p[0].y > st->max_size) + qline->p[1].y = qline->p[0].y + st->max_size + - (st->random_p ? random() % st->max_spread : 0); + } + +#ifndef HAVE_COCOA + if (!mono_p && !st->transparent_p) +#endif + { + XColor desired; + + int h; + double s, v; + rgb_to_hsv (qline->color.red, qline->color.green, qline->color.blue, + &h, &s, &v); + h = (h + st->color_shift) % 360; + hsv_to_rgb (h, s, v, + &qline->color.red, &qline->color.green, &qline->color.blue); + + qline->color.flags = DoRed | DoGreen | DoBlue; + desired = qline->color; + if (XAllocColor (st->dpy, st->cmap, &qline->color)) + { + /* XAllocColor returns the actual RGB that the hardware let us + allocate. Restore the requested values into the XColor struct + so that limited-resolution hardware doesn't cause the cycle to + get "stuck". */ + qline->color.red = desired.red; + qline->color.green = desired.green; + qline->color.blue = desired.blue; + } + else + { + qline->color = prev_qline->color; + if (!XAllocColor (st->dpy, st->cmap, &qline->color)) + abort (); /* same color should work */ + } + +# ifdef HAVE_COCOA + if (st->transparent_p) + { + /* give a non-opaque alpha to the color */ + unsigned long pixel = qline->color.pixel; + unsigned long amask = BlackPixelOfScreen (0); + unsigned long a = (0xBBBBBBBB & amask); + pixel = (pixel & (~amask)) | a; + qline->color.pixel = pixel; + } +# endif /* HAVE_COCOA */ + + XSetForeground (st->dpy, st->draw_gc, qline->color.pixel); + } + if (! st->solid_p) + { + /* XDrawLine (dpy, window, (transparent_p ? gcs[0][qix->id] : draw_gc), + qline->p1.x, qline->p1.y, qline->p2.x, qline->p2.y);*/ + XPoint points[MAXPOLY+1]; + for (i = 0; i < qix->npoly; i++) + { + points[i].x = qline->p[i].x >> SCALE; + points[i].y = qline->p[i].y >> SCALE; + } + points[qix->npoly] = points[0]; + XDrawLines(st->dpy, st->window, + (st->transparent_p && st->gcs[0] + ? st->gcs[0][qix->id] + : st->draw_gc), + points, qix->npoly+1, CoordModeOrigin); + } + else if (!prev_qline->dead) + { + XPoint points [4]; + points [0].x = qline->p[0].x >> SCALE; + points [0].y = qline->p[0].y >> SCALE; + points [1].x = qline->p[1].x >> SCALE; + points [1].y = qline->p[1].y >> SCALE; + points [2].x = prev_qline->p[1].x >> SCALE; + points [2].y = prev_qline->p[1].y >> SCALE; + points [3].x = prev_qline->p[0].x >> SCALE; + points [3].y = prev_qline->p[0].y >> SCALE; + XFillPolygon (st->dpy, st->window, + (st->transparent_p && st->gcs[0] + ? st->gcs[0][qix->id] + : st->draw_gc), + points, 4, Complex, CoordModeOrigin); + } + + qline->dead = False; +} + +static void +qix1 (struct state *st, struct qix *qix) +{ + int ofp = qix->fp - 1; + if (ofp < 0) ofp = qix->nlines - 1; + if (st->gtick++ == 500) + get_geom (st), st->gtick = 0; + free_qline (st, &qix->lines [qix->fp], + &qix->lines[(qix->fp + 1) % qix->nlines], qix); + add_qline (st, &qix->lines[qix->fp], &qix->lines[ofp], qix); + if ((++qix->fp) >= qix->nlines) + qix->fp = 0; +} + + +static unsigned long +qix_draw (Display *dpy, Window window, void *closure) +{ + struct state *st = (struct state *) closure; + struct qix **q1 = st->qixes; + struct qix **qn; + for (qn = q1; *qn; qn++) + qix1 (st, *qn); + return st->delay; +} + +static void +qix_reshape (Display *dpy, Window window, void *closure, + unsigned int w, unsigned int h) +{ + struct state *st = (struct state *) closure; + get_geom (st); +} + +static Bool +qix_event (Display *dpy, Window window, void *closure, XEvent *event) +{ + return False; +} + +static void +qix_free (Display *dpy, Window window, void *closure) +{ + struct state *st = (struct state *) closure; + if (st->gcs[0]) + free (st->gcs[0]); + if (st->gcs[1] && st->gcs[0] != st->gcs[1]) + free (st->gcs[1]); + free (st->qixes); + free (st); +} + + +static const char *qix_defaults [] = { + ".background: black", + ".foreground: white", + "*fpsSolid: true", + "*count: 4", + "*segments: 250", + "*poly: 2", + "*spread: 8", + "*size: 200", + "*colorShift: 3", + "*solid: true", + "*delay: 10000", + "*random: false", + "*xor: false", + "*transparent:true", + "*gravity: false", + "*additive: true", + 0 +}; + +static XrmOptionDescRec qix_options [] = { + { "-count", ".count", XrmoptionSepArg, 0 }, + { "-segments", ".segments", XrmoptionSepArg, 0 }, + { "-poly", ".poly", XrmoptionSepArg, 0 }, + { "-spread", ".spread", XrmoptionSepArg, 0 }, + { "-size", ".size", XrmoptionSepArg, 0 }, + { "-delay", ".delay", XrmoptionSepArg, 0 }, + { "-color-shift", ".colorShift", XrmoptionSepArg, 0 }, + { "-random", ".random", XrmoptionNoArg, "true" }, + { "-linear", ".random", XrmoptionNoArg, "false" }, + { "-solid", ".solid", XrmoptionNoArg, "true" }, + { "-hollow", ".solid", XrmoptionNoArg, "false" }, + { "-xor", ".xor", XrmoptionNoArg, "true" }, + { "-no-xor", ".xor", XrmoptionNoArg, "false" }, + { "-transparent", ".transparent", XrmoptionNoArg, "true" }, + { "-non-transparent", ".transparent", XrmoptionNoArg, "false" }, + { "-gravity", ".gravity", XrmoptionNoArg, "true" }, + { "-no-gravity", ".gravity", XrmoptionNoArg, "false" }, + { "-additive", ".additive", XrmoptionNoArg, "true" }, + { "-subtractive", ".additive", XrmoptionNoArg, "false" }, + { 0, 0, 0, 0 } +}; + +XSCREENSAVER_MODULE ("Qix", qix) diff --git a/hacks/qix.man b/hacks/qix.man new file mode 100644 index 00000000..f5a09305 --- /dev/null +++ b/hacks/qix.man @@ -0,0 +1,132 @@ +.TH XScreenSaver 1 "27-Apr-97" "X Version 11" +.SH NAME +qix - bounce colored lines around a window +.SH SYNOPSIS +.B qix +[\-display \fIhost:display.screen\fP] [\-foreground \fIcolor\fP] [\-background \fIcolor\fP] [\-window] [\-root] [\-mono] [\-install] [\-visual \fIvisual\fP] [\-segments \fIint\fP] [\-spread \fIpixels\fP] [\-size \fIpixels\fP] [\-count \fIint\fP] [\-color-shift \fIdegrees\fP] [\-delay \fIusecs\fP] [\-random] [\-linear] [\-solid] [\-hollow] [\-xor] [\-no\-xor] [\-transparent] [\-non\-transparent] [\-additive] [\-subtractive] [\-poly \fIint\fP] [\-gravity] [\-no\-gravity] +[\-fps] +.SH DESCRIPTION +The \fIqix\fP program bounces a series of line segments around its window. +This is truly the swiss army chainsaw of qix programs. If you know of one +with more display modes, I want to know about it. +.SH OPTIONS +.I qix +accepts the following options: +.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 \-mono +If on a color display, pretend we're on a monochrome display. +.TP 8 +.B \-install +Install a private colormap for the window. +.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 \-segments \fIinteger\fP +How many line segments should be drawn. Default 50. +.TP 8 +.B \-spread \fIinteger\fP +How far apart the endpoints of one segment should be from the next. +Default 8. +.TP 8 +.B \-size \fIinteger\fP +The maximum distance one endpoint of a segment is allowed to be from +the opposite end of that segment. Default 0, meaning unlimited. +.TP 8 +.B \-count \fIinteger\fP +How many qixes to draw. Default 1. +.TP 8 +.B \-color\-shift \fIdegrees\fP +If on a color display, the color of the line segments will cycle through +the spectrum. This specifies how far the hue of each segment should be +from the next, in degrees on the HSV wheel. Default 3. +.TP 8 +.B \-delay \fImicroseconds\fP +How much of a delay should be introduced between steps of the animation. +Default 10000, or about 0.01 seconds. +.TP 8 +.B \-random +The \fIqix\fP will wander around the screen semi-randomly. This is the +default. +.TP 8 +.B \-linear +The opposite of \fI\-random\fP: the \fIqix\fP will travel in straight lines +until it reaches a wall, and then it will bounce. +.TP 8 +.B \-solid +If this is specified, then the area between the line segments will be filled +in with the appropriate color, instead of the \fIqix\fP simply being composed +of one-pixel-wide line segments. This option looks really good in color. +.TP 8 +.B \-hollow +The opposite of \fI\-solid\fP; this is the default. +.TP 8 +.B \-xor +If this is specified, then qix segments will be drawn and erased with xor, +instead of being drawn in some color and erased in the background color. +This implies \fI\-mono\fP, in that only two colors can be used. +.TP 8 +.B \-transparent +If this is specified, and \fI\-count\fP is greater than 1, then each qix +will be drawn in one color, and when they overlap, the colors will be mixed. +This looks best in conjunction with \fI\-solid\fP. +.TP 8 +.B \-non\-transparent +Turns off \fI\-transparent\fP. +.TP 8 +.B \-additive +If \fI\-transparent\fP is specified, then this option means that the colors +will be mixed using an additive color model, as if the qixes were projected +light. This is the default. +.TP 8 +.B \-subtractive +If \fI\-transparent\fP is specified, then this option means that the +colors will be mixed using a subtractive color model, as if the qixes were +translucent filters. +.TP 8 +.B \-poly \fIint\fP +How many vertices each qix-line should have: the default is 2, meaning the +traditional qix line shape. Three will yield triangles, and so on. +.TP 8 +.B \-gravity +.TP 8 +.B \-no\-gravity +Whether there should be downward attraction. For example, the +options +.B \-gravity \-linear +will make everything move in nice smooth parabolas. +Gravity is off by default. +.TP 8 +.B \-fps +Display the current frame rate and CPU load. +.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 1992 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 , 13-aug-92. + +Thanks to Ariel Scolnicov for the \-poly and \-gravity options. diff --git a/hacks/rd-bomb.c b/hacks/rd-bomb.c new file mode 100644 index 00000000..0c074ea4 --- /dev/null +++ b/hacks/rd-bomb.c @@ -0,0 +1,590 @@ +/* xscreensaver, Copyright (c) 1992-2008 Jamie Zawinski + * + * reaction/diffusion textures + * Copyright (c) 1997 Scott Draves spot@transmeta.com + * this code is derived from Bomb + * see http://www.cs.cmu.edu/~spot/bomb.html + * + * 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. + * + * And remember: X Windows is to graphics hacking as roman numerals are to + * the square root of pi. + */ + +#include + +#include "screenhack.h" + +#ifdef HAVE_XSHM_EXTENSION +# include "xshm.h" +#endif /* HAVE_XSHM_EXTENSION */ + +/* costs ~6% speed */ +#define dither_when_mapped 1 + +struct state { + Display *dpy; + Window window; + + int ncolors; + XColor *colors; + Visual *visual; +#if dither_when_mapped + unsigned char *mc; +#endif + Colormap cmap; + int mapped; + int pdepth; + + int frame, epoch_time; + unsigned short *r1, *r2, *r1b, *r2b; + int width, height, npix; + int radius; + int reaction; + int diffusion; + + char *pd; + int array_width, array_height; + +#ifdef HAVE_XSHM_EXTENSION + Bool use_shm; + XShmSegmentInfo shm_info; +#endif + + GC gc; + XImage *image; + double array_x, array_y; + double array_dx, array_dy; + XWindowAttributes xgwa; + int delay; +}; + +static void random_colors(struct state *st); + +/* ----------------------------------------------------------- + pixel hack, 8-bit pixel grid, first/next frame interface + + pixack_init(int *size_h, int *size_v) + pixack_frame(char *pix_buf) + */ + + +#define bps 16 +#define mx ((1<<16)-1) + +/* you can replace integer mults wish shift/adds with these, + but it doesn't help on my 586 */ +#define x5(n) ((n<<2)+n) +#define x7(n) ((n<<3)-n) + +/* why strip bit? */ +#define R (random()&((1<<30)-1)) +#define BELLRAND(x) (((random()%(x)) + (random()%(x)) + (random()%(x)))/3) + +/* returns number of pixels that the pixack produces. called once. */ +static void +pixack_init(struct state *st, int *size_h, int *size_v) +{ + st->width = get_integer_resource (st->dpy, "width", "Integer"); + st->height = get_integer_resource (st->dpy, "height", "Integer"); + + if (st->width <= 0 && st->height <= 0 && (R & 1)) + st->width = st->height = 48 + BELLRAND(256); + + if (st->width <= 0) st->width = 48 + BELLRAND(256); + if (st->height <= 0) st->height = 48 + BELLRAND(256); + + /* jwz: when (and only when) XSHM is in use on an SGI 8-bit visual, + we get shear unless st->width is a multiple of 4. I don't understand + why. This is undoubtedly the wrong fix... */ + if (visual_depth (st->xgwa.screen, st->xgwa.visual) == 8) + st->width &= ~0x7; + + /* don't go there */ + if (st->width < 10) st->width = 10; + if (st->height < 10) st->height = 10; + st->epoch_time = get_integer_resource (st->dpy, "epoch", "Integer"); + st->npix = (st->width + 2) * (st->height + 2); + st->r1 = (unsigned short *) malloc(sizeof(unsigned short) * st->npix); + st->r2 = (unsigned short *) malloc(sizeof(unsigned short) * st->npix); + st->r1b = (unsigned short *) malloc(sizeof(unsigned short) * st->npix); + st->r2b = (unsigned short *) malloc(sizeof(unsigned short) * st->npix); + + if (!st->r1 || !st->r2 || !st->r1b || !st->r2b) { + fprintf(stderr, "not enough memory for %d pixels.\n", st->npix); + exit(1); + } + + *size_h = st->width; + *size_v = st->height; +} + +#define test_pattern_hyper 0 + + +/* returns the pixels. called many times. */ +static void +pixack_frame(struct state *st, char *pix_buf) +{ + int i, j; + int w2 = st->width + 2; + unsigned short *t; +#if test_pattern_hyper + if (st->frame&0x100) + sleep(1); +#endif + + if (!(st->frame%st->epoch_time)) { + int s; + if (0 != st->frame) { + int tt = st->epoch_time / 500; + if (tt > 15) + tt = 15; + /*sleep(tt);*/ + } + + for (i = 0; i < st->npix; i++) { + /* equilibrium */ + st->r1[i] = 65500; + st->r2[i] = 11; + } + + random_colors(st); + + XSetWindowBackground(st->dpy, st->window, st->colors[255 % st->ncolors].pixel); + XClearWindow(st->dpy, st->window); + + s = w2 * (st->height/2) + st->width/2; + st->radius = get_integer_resource (st->dpy, "radius", "Integer"); + { + int maxr = st->width/2-2; + int maxr2 = st->height/2-2; + if (maxr2 < maxr) maxr = maxr2; + + if (st->radius < 0) + st->radius = 1 + ((R%10) ? (R%5) : (R % maxr)); + if (st->radius > maxr) st->radius = maxr; + } + for (i = -st->radius; i < (st->radius+1); i++) + for (j = -st->radius; j < (st->radius+1); j++) + st->r2[s + i + j*w2] = mx - (R&63); + st->reaction = get_integer_resource (st->dpy, "reaction", "Integer"); + if (st->reaction < 0 || st->reaction > 2) st->reaction = R&1; + st->diffusion = get_integer_resource (st->dpy, "diffusion", "Integer"); + if (st->diffusion < 0 || st->diffusion > 2) + st->diffusion = (R%5) ? ((R%3)?0:1) : 2; + if (2 == st->reaction && 2 == st->diffusion) + st->reaction = st->diffusion = 0; + } + for (i = 0; i <= st->width+1; i++) { + st->r1[i] = st->r1[i + w2 * st->height]; + st->r2[i] = st->r2[i + w2 * st->height]; + st->r1[i + w2 * (st->height + 1)] = st->r1[i + w2]; + st->r2[i + w2 * (st->height + 1)] = st->r2[i + w2]; + } + for (i = 0; i <= st->height+1; i++) { + st->r1[w2 * i] = st->r1[st->width + w2 * i]; + st->r2[w2 * i] = st->r2[st->width + w2 * i]; + st->r1[w2 * i + st->width + 1] = st->r1[w2 * i + 1]; + st->r2[w2 * i + st->width + 1] = st->r2[w2 * i + 1]; + } + for (i = 0; i < st->height; i++) { + int ii = i + 1; + char *q = pix_buf + st->width * i; + short *qq = ((short *) pix_buf) + st->width * i; +/* long *qqq = ((long *) pix_buf) + st->width * i; -- crashes on Alpha */ + int *qqq = ((int *) pix_buf) + st->width * i; + unsigned short *i1 = st->r1 + 1 + w2 * ii; + unsigned short *i2 = st->r2 + 1 + w2 * ii; + unsigned short *o1 = st->r1b + 1 + w2 * ii; + unsigned short *o2 = st->r2b + 1 + w2 * ii; + for (j = 0; j < st->width; j++) { +#if test_pattern_hyper + int r1 = (i * j + (st->frame&127)*frame)&65535; +#else + int uvv, r1 = 0, r2 = 0; + switch (st->diffusion) { + case 0: + r1 = i1[j] + i1[j+1] + i1[j-1] + i1[j+w2] + i1[j-w2]; + r1 = r1 / 5; + r2 = (i2[j]<<3) + i2[j+1] + i2[j-1] + i2[j+w2] + i2[j-w2]; + r2 = r2 / 12; + break; + case 1: + r1 = i1[j+1] + i1[j-1] + i1[j+w2] + i1[j-w2]; + r1 = r1 >> 2; + r2 = (i2[j]<<2) + i2[j+1] + i2[j-1] + i2[j+w2] + i2[j-w2]; + r2 = r2 >> 3; + break; + case 2: + r1 = (i1[j]<<1) + (i1[j+1]<<1) + (i1[j-1]<<1) + i1[j+w2] + i1[j-w2]; + r1 = r1 >> 3; + r2 = (i2[j]<<2) + i2[j+1] + i2[j-1] + i2[j+w2] + i2[j-w2]; + r2 = r2 >> 3; + break; + } + + /* John E. Pearson "Complex Patterns in a Simple System" + Science, July 1993 */ + + uvv = (((r1 * r2) >> bps) * r2) >> bps; + switch (st->reaction) { /* costs 4% */ + case 0: + r1 += 4 * (((28 * (mx-r1)) >> 10) - uvv); + r2 += 4 * (uvv - ((80 * r2) >> 10)); + break; + case 1: + r1 += 3 * (((27 * (mx-r1)) >> 10) - uvv); + r2 += 3 * (uvv - ((80 * r2) >> 10)); + break; + case 2: + r1 += 2 * (((28 * (mx-r1)) >> 10) - uvv); + r2 += 3 * (uvv - ((80 * r2) >> 10)); + break; + } + if (r1 > mx) r1 = mx; + if (r2 > mx) r2 = mx; + if (r1 < 0) r1 = 0; + if (r2 < 0) r2 = 0; + o1[j] = r1; + o2[j] = r2; +#endif + + /* this is terrible. here i want to assume ncolors = 256. + should lose double indirection */ + + if (st->mapped) +#if dither_when_mapped + q[j] = st->colors[st->mc[r1] % st->ncolors].pixel; +#else + q[j] = st->colors[(r1>>8) % st->ncolors].pixel; +#endif + else if (st->pdepth == 8) + q[j] = st->colors[(r1>>8) % st->ncolors].pixel; + else if (st->pdepth == 16) +#if dither_when_mapped + qq[j] = st->colors[st->mc[r1] % st->ncolors].pixel; +#else + qq[j] = st->colors[(r1>>8) % st->ncolors].pixel; +#endif + else if (st->pdepth == 32) +#if dither_when_mapped + qqq[j] = st->colors[st->mc[r1] % st->ncolors].pixel; +#else + qqq[j] = st->colors[(r1>>8) % st->ncolors].pixel; +#endif + else + abort(); + } + } + t = st->r1; st->r1 = st->r1b; st->r1b = t; + t = st->r2; st->r2 = st->r2b; st->r2b = t; +} + + +/* ------------- xscreensaver rendering -------------- */ + +static const char *rd_defaults [] = { + ".background: black", + ".foreground: white", + "*fpsSolid: true", + "*width: 0", /* tried to use -1 but it complained */ + "*height: 0", + "*epoch: 40000", + "*reaction: -1", + "*diffusion: -1", + "*radius: -1", + "*speed: 0.0", + "*size: 1.0", + "*delay: 30000", + "*colors: 255", +#ifdef HAVE_XSHM_EXTENSION + "*useSHM: True", +#else + "*useSHM: False", +#endif + 0 +}; + +static XrmOptionDescRec rd_options [] = { + { "-width", ".width", XrmoptionSepArg, 0 }, + { "-height", ".height", XrmoptionSepArg, 0 }, + { "-epoch", ".epoch", XrmoptionSepArg, 0 }, + { "-reaction", ".reaction", XrmoptionSepArg, 0 }, + { "-diffusion", ".diffusion", XrmoptionSepArg, 0 }, + { "-radius", ".radius", XrmoptionSepArg, 0 }, + { "-speed", ".speed", XrmoptionSepArg, 0 }, + { "-size", ".size", XrmoptionSepArg, 0 }, + { "-delay", ".delay", XrmoptionSepArg, 0 }, + { "-ncolors", ".colors", XrmoptionSepArg, 0 }, + { "-shm", ".useSHM", XrmoptionNoArg, "True" }, + { "-no-shm", ".useSHM", XrmoptionNoArg, "False" }, + { 0, 0, 0, 0 } +}; + + +static void +random_colors(struct state *st) +{ + memset(st->colors, 0, st->ncolors*sizeof(*st->colors)); + make_smooth_colormap (st->dpy, st->visual, st->cmap, st->colors, &st->ncolors, + True, 0, True); + if (st->ncolors <= 2) { + mono_p = True; + st->ncolors = 2; + st->colors[0].flags = DoRed|DoGreen|DoBlue; + st->colors[0].red = st->colors[0].green = st->colors[0].blue = 0; + XAllocColor(st->dpy, st->cmap, &st->colors[0]); + st->colors[1].flags = DoRed|DoGreen|DoBlue; + st->colors[1].red = st->colors[1].green = st->colors[1].blue = 0xFFFF; + XAllocColor(st->dpy, st->cmap, &st->colors[1]); + } + + /* Scale it up so that there are exactly 255 colors -- that keeps the + animation speed consistent, even when there aren't many allocatable + colors, and prevents the -mono mode from looking like static. */ + if (st->ncolors != 255) { + int i, n = 255; + double scale = (double) st->ncolors / (double) (n+1); + XColor *c2 = (XColor *) malloc(sizeof(*c2) * (n+1)); + for (i = 0; i < n; i++) + c2[i] = st->colors[(int) (i * scale)]; + free(st->colors); + st->colors = c2; + st->ncolors = n; + } + +} + + +/* should factor into RD-specfic and compute-every-pixel general */ +static void * +rd_init (Display *dpy, Window win) +{ + struct state *st = (struct state *) calloc (1, sizeof(*st)); + XGCValues gcv; + int w2; + int vdepth; + + st->dpy = dpy; + st->window = win; + + st->delay = get_integer_resource (st->dpy, "delay", "Float"); + +#ifdef HAVE_XSHM_EXTENSION + st->use_shm = get_boolean_resource(st->dpy, "useSHM", "Boolean"); +#endif + + XGetWindowAttributes (st->dpy, win, &st->xgwa); + st->visual = st->xgwa.visual; + pixack_init(st, &st->width, &st->height); + { + double s = get_float_resource (st->dpy, "size", "Float"); + double p = get_float_resource (st->dpy, "speed", "Float"); + if (s < 0.0 || s > 1.0) + s = 1.0; + s = sqrt(s); + st->array_width = st->xgwa.width * s; + st->array_height = st->xgwa.height * s; + if (s < 0.99) { + st->array_width = (st->array_width / st->width) * st->width; + st->array_height = (st->array_height / st->height) * st->height; + } + if (st->array_width < st->width) st->array_width = st->width; + if (st->array_height < st->height) st->array_height = st->height; + st->array_x = (st->xgwa.width - st->array_width)/2; + st->array_y = (st->xgwa.height - st->array_height)/2; + st->array_dx = p; + st->array_dy = .31415926 * p; + + /* start in a random direction */ + if (random() & 1) st->array_dx = -st->array_dx; + if (random() & 1) st->array_dy = -st->array_dy; + + } + st->npix = (st->width + 2) * (st->height + 2); + w2 = st->width + 2; +/* gcv.function = GXcopy;*/ + st->gc = XCreateGC(st->dpy, win, 0 /*GCFunction*/, &gcv); + vdepth = visual_depth(DefaultScreenOfDisplay(st->dpy), st->xgwa.visual); + + /* This code only deals with pixmap depths of 1, 8, 16, and 32. + Therefore, we assume that those depths will be supported by the + coresponding visual depths (that depth-24 dpys accept depth-32 + pixmaps, and that depth-12 dpys accept depth-16 pixmaps.) */ + st->pdepth = (vdepth == 1 ? 1 : + vdepth <= 8 ? 8 : + vdepth <= 16 ? 16 : + 32); + + /* Ok, this like, sucks and stuff. There are some XFree86 systems + that have depth-24 visuals, that do not accept depth-32 XImages! + Which if you ask me is just absurd, since all it would take is + for the server to truncate the bits in that case. So, this crap + here detects the specific case of: we have chosen depth 32; + and the server does not support depth 32. In that case, we + try and use depth 16 instead. + + The real fix would be to rewrite this program to deal with + depth 24 directly (or even better, arbitrary depths, but that + would mean going through the XImage routines instead of messing + with the XImage->data directly.) + + jwz, 18-Mar-99: well, the X servers I have access to these days do + support 32-deep images on deep visuals, so I no longer have the + ability to test this code -- but it was causing problems on the + visuals that I do have, and I think that's because I mistakenly + wrote `pfv[i].depth' when I meant to write `pfv[i].bits_per_pixel'. + The symptom I was seeing was that the grid was 64x64, but the + images were being drawn 32x32 -- so there was a black stripe on + every other row. Wow, this code sucks so much. + */ + if (st->pdepth == 32) + { + int i, pfvc = 0; + Bool ok = False; + XPixmapFormatValues *pfv = XListPixmapFormats (st->dpy, &pfvc); + for (i = 0; i < pfvc; i++) + if (pfv[i].bits_per_pixel == st->pdepth) + ok = True; + if (!ok) + st->pdepth = 16; + } + + st->cmap = st->xgwa.colormap; + st->ncolors = get_integer_resource (st->dpy, "colors", "Integer"); + + if (st->ncolors <= 0 || st->ncolors >= 255) { + if (vdepth > 8) + st->ncolors = 2047; + else + st->ncolors = 255; + } + + if (mono_p || st->ncolors < 2) st->ncolors = 2; + if (st->ncolors <= 2) mono_p = True; + st->colors = (XColor *) malloc(sizeof(*st->colors) * (st->ncolors+1)); + + st->mapped = (vdepth <= 8 && + has_writable_cells(st->xgwa.screen, st->xgwa.visual)); + + { + int i, di; + st->mc = (unsigned char *) malloc(1<<16); + for (i = 0; i < (1<<16); i++) { + di = (i + (random()&255))>>8; + if (di > 255) di = 255; + st->mc[i] = di; + } + } + + st->pd = malloc(st->npix * (st->pdepth == 1 ? 1 : (st->pdepth / 8))); + if (!st->pd) { + fprintf(stderr, "not enough memory for %d pixels.\n", st->npix); + exit(1); + } + + st->image = 0; + +#ifdef HAVE_XSHM_EXTENSION + if (st->use_shm) + { + st->image = create_xshm_image(st->dpy, st->xgwa.visual, vdepth, + ZPixmap, 0, &st->shm_info, st->width, st->height); + if (!st->image) + st->use_shm = False; + else + { + free(st->pd); + st->pd = st->image->data; + } + } +#endif /* HAVE_XSHM_EXTENSION */ + + if (!st->image) + { + st->image = XCreateImage(st->dpy, st->xgwa.visual, vdepth, + ZPixmap, 0, st->pd, + st->width, st->height, 8, 0); + } + + return st; +} + +static unsigned long +rd_draw (Display *dpy, Window win, void *closure) +{ + struct state *st = (struct state *) closure; + Bool bump = False; + + int i, j; + pixack_frame(st, st->pd); + for (i = 0; i < st->array_width; i += st->width) + for (j = 0; j < st->array_height; j += st->height) +#ifdef HAVE_XSHM_EXTENSION + if (st->use_shm) + XShmPutImage(st->dpy, st->window, st->gc, st->image, 0, 0, i+st->array_x, j+st->array_y, + st->width, st->height, False); + else +#endif + XPutImage(st->dpy, win, st->gc, st->image, 0, 0, i+st->array_x, j+st->array_y, + st->width, st->height); + + st->array_x += st->array_dx; + st->array_y += st->array_dy; + if (st->array_x < 0) { + st->array_x = 0; + st->array_dx = -st->array_dx; + bump = True; + } else if (st->array_x > (st->xgwa.width - st->array_width)) { + st->array_x = (st->xgwa.width - st->array_width); + st->array_dx = -st->array_dx; + bump = True; + } + if (st->array_y < 0) { + st->array_y = 0; + st->array_dy = -st->array_dy; + bump = True; + } else if (st->array_y > (st->xgwa.height - st->array_height)) { + st->array_y = (st->xgwa.height - st->array_height); + st->array_dy = -st->array_dy; + bump = True; + } + + if (bump) { + if (random() & 1) { + double swap = st->array_dx; + st->array_dx = st->array_dy; + st->array_dy = swap; + } + } + + st->frame++; + + return st->delay; +} + +static void +rd_reshape (Display *dpy, Window window, void *closure, + unsigned int w, unsigned int h) +{ +} + +static Bool +rd_event (Display *dpy, Window window, void *closure, XEvent *event) +{ + return False; +} + +static void +rd_free (Display *dpy, Window window, void *closure) +{ +} + +XSCREENSAVER_MODULE_2 ("RDbomb", rdbomb, rd) diff --git a/hacks/rd-bomb.man b/hacks/rd-bomb.man new file mode 100644 index 00000000..4022a432 --- /dev/null +++ b/hacks/rd-bomb.man @@ -0,0 +1,100 @@ +.TH XScreenSaver 1 "10-May-97" "X Version 11" +.SH NAME +rd-bomb - reaction/diffusion textures +.SH SYNOPSIS +.B rd-bomb +[\-display \fIhost:display.screen\fP] [\-foreground \fIcolor\fP] +[\-background \fIcolor\fP] [\-window] [\-root] [\-install] +[\-visual \fIvisual\fP] [\-width \fIn\fP] [\-height \fIn\fP] +[\-reaction \fIn\fP] [\-diffusion \fIn\fP] +[\-size \fIf\fP] [\-speed \fIf\fP] [\-delay \fImillisecs\fP] +[\-fps] +.SH DESCRIPTION + +The \fIrd-bomb\fP program draws reaction/diffusion textures. The code +is derived from the 'd' mode of the "bomb" visual musical instrument +(see http://www.cs.cmu.edu/~spot/bomb.html). I got the equations from +xmorphia (http://www.ccsf.caltech.edu/ismap/image.html), which is +based on a version of the Gray-Scott model taken from: + John E. Pearson "Complex Patterns in a Simple System" + Science, 261,189, 9 July 1993. + +If the frame-rate is too low, consider decreasing the width and height +of the tile, or decreasing the size of the active part of the screen. + +.SH OPTIONS + +If one of the reaction, diffusion, radius, and palette options is set +to a negative value, then that option will be set to a random +appropriate value. + +Be sure to try "-speed 1 -size 0.1 -epoch 3000". + +.I rd-bomb +accepts the following options: +.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 \-install +Install a private colormap for the window. +.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 \-width \fIn\fP +.TP 8 +.B \-height \fIn\fP +Specify the size of the tile, in pixels. +.TP 8 +.B \-reaction \fIn\fP +.TP 8 +.B \-diffusion \fIn\fP +These are constants in the equations that effect its visual nature. +Each may be one of 0, 1, or 2. Default is -1: these constants are +chosen randomly. +.TP 8 +.B \-radius \fIn\fP +Size of the seed. +.TP 8 +.B \-size \fIf\fP +What fraction of the window is actively drawn, a floating point number +between 0 (exclusive) and 1 (inclusive). Default is 1.0. +.TP 8 +.B \-speed \fIf\fP +When a fraction of the screen is active, the active area moves at this +rate (a floating point number). Default is zero. Suggested value: 1.0. +.TP 8 +.B \-delay \fImillisecs\fP +How many milliseconds to delay between frames; default 1, or +about 1/1000th of a second. +.TP 8 +.B \-fps +Display the current frame rate and CPU load. +.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), +.BR xlock (1) +.SH COPYRIGHT +Copyright \(co 1997 by Scott Draves. + +Permission to use, copy, modify, and distribute this software and its +documentation for any purpose and without fee is hereby granted, +provided that the above copyright notice appear in all copies and that +both that copyright notice and this permission notice appear in +supporting documentation. +.SH AUTHOR +Scott Draves , 9/97 diff --git a/hacks/ripples.c b/hacks/ripples.c new file mode 100644 index 00000000..e030b1cd --- /dev/null +++ b/hacks/ripples.c @@ -0,0 +1,1131 @@ +/* ripples, Copyright (c) 1999 Ian McConnell + * + * 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. + */ + +/* + * "Water" ripples that can cross and interfere with each other. + * + * I can't remember where I got this idea from, but it's been around for a + * while in various demos. Some inspiration from + * water.txt by Tom Hammersley,tomh@globalnet.co.uk + * + * Options + * -delay usleep every iteration + * -rate Add one drop every "rate" iterations + * -box Add big square splash every "box" iters (not very good) + * -water Ripples on a grabbed background image + * -foreground Interpolate ripples between these two colors + * -background + * -oily Psychedelic colours like man + * -stir Add a regular pattern of drops + * -fluidity Between 0 and 16. 16 = big drops + * -light Hack to add lighting effect + * + * Code mainly hacked from xflame and decayscreen. + */ + +/* Version history: + * 13 Oct 1999: Initial hack + * 30 Oct 1999: Speeded up graphics with dirty buffer. Returned to using + * putpixel for greater portability + * Added a variety of methods for splashing screen. + * 31 Oct 1999: Added in lighting hack + * 13 Nov 1999: Speed up tweaks + * Adjust "light" for different bits per colour (-water only) + * + */ + +#include +#include "screenhack.h" + +typedef enum {ripple_drop, ripple_blob, ripple_box, ripple_stir} ripple_mode; + +#ifdef HAVE_XSHM_EXTENSION +#include "xshm.h" +#endif /* HAVE_XSHM_EXTENSION */ + +#define TABLE 256 + +struct state { + Display *dpy; + Window window; + GC gc; + Visual *visual; + + XImage *orig_map, *buffer_map; + int ctab[256]; + Colormap colormap; + int ncolors; + int light; + + int width, height; /* ripple size */ + int bigwidth, bigheight; /* screen size */ + + Bool transparent; + short *bufferA, *bufferB, *temp; + char *dirty_buffer; + + double cos_tab[TABLE]; + + Bool grayscale_p; + + unsigned long rmask; /* This builds on the warp effect by adding */ + unsigned long gmask; /* in a lighting effect: brighten pixels by an */ + unsigned long bmask; /* amount corresponding to the vertical gradient */ + + int rshift; + int gshift; + int bshift; + + double stir_ang; + + int draw_toggle; + int draw_count; + + int iterations, delay, rate, box, oily, stir, fluidity; + int duration; + time_t start_time; + + void (*draw_transparent) (struct state *st, short *src); + + async_load_state *img_loader; + +#ifdef HAVE_XSHM_EXTENSION + Bool use_shm; + XShmSegmentInfo shm_info; +#endif /* HAVE_XSHM_EXTENSION */ +}; + + +/* Distribution of drops: many little ones and a few big ones. */ +static const double drop_dist[] = + {0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.2, 0.6}; + + +/* How hard to hit the water */ +#define SPLASH 512 +#undef MIN +#define MIN(x, y) ((x) < (y) ? (x) : (y)) +#undef MAX +#define MAX(x, y) ((x) > (y) ? (x) : (y)) +#undef DIRTY +#define DIRTY 3 /* dirty >= 2, 1 = restore original pixel, 0 = leave alone */ + +/* From fortune(6) */ +/* -- really weird C code to count the number of bits in a word */ +#define BITCOUNT(x) (((BX_(x)+(BX_(x)>>4)) & 0x0F0F0F0F) % 255) +#define BX_(x) ((x) - (((x)>>1)&0x77777777) \ + - (((x)>>2)&0x33333333) \ + - (((x)>>3)&0x11111111)) + + +static unsigned long grayscale(struct state *st, unsigned long color); + +/* ------------------------------------------- */ + + +static int +map_color(struct state *st, int grey) +{ + /* Clip it */ + grey = st->ncolors * abs(grey) / (SPLASH/4); + if (grey > st->ncolors) + grey = st->ncolors; + + /* Display it */ + return st->ctab[grey]; +} + + +static void +draw_ripple(struct state *st, short *src) +{ + int across, down; + char *dirty = st->dirty_buffer; + + for (down = 0; down < st->height - 1; down++, src += 1, dirty += 1) + for (across = 0; across < st->width - 1; across++, src++, dirty++) { + int v1, v2, v3, v4; + v1 = (int)*src; + v2 = (int)*(src + 1); + v3 = (int)*(src + st->width); + v4 = (int)*(src + st->width + 1); + if ((v1 == 0 && v2 == 0 && v3 == 0 && v4 == 0)) { + if (*dirty > 0) + (*dirty)--; + } else + *dirty = DIRTY; + + if (*dirty > 0) { + int dx; + if (st->light > 0) { + dx = ((v3 - v1) + (v4 - v2)) << st->light; /* light from top */ + } else + dx = 0; + XPutPixel(st->buffer_map,(across<<1), (down<<1), map_color(st, dx + v1)); + XPutPixel(st->buffer_map,(across<<1)+1,(down<<1), map_color(st, dx + ((v1 + v2) >> 1))); + XPutPixel(st->buffer_map,(across<<1), (down<<1)+1,map_color(st, dx + ((v1 + v3) >> 1))); + XPutPixel(st->buffer_map,(across<<1)+1,(down<<1)+1,map_color(st, dx + ((v1 + v4) >> 1))); + } + } +} + + +/* ------------------------------------------- */ + + +/* Uses the horizontal gradient as an offset to create a warp effect */ +static void +draw_transparent_vanilla(struct state *st, short *src) +{ + int across, down, pixel; + char *dirty = st->dirty_buffer; + + pixel = 0; + for (down = 0; down < st->height - 2; down++, pixel += 2) + for (across = 0; across < st->width-2; across++, pixel++) { + int gradx, grady, gradx1, grady1; + int x0, x1, x2, y1, y2; + + x0 = src[pixel]; + x1 = src[pixel + 1]; + x2 = src[pixel + 2]; + y1 = src[pixel + st->width]; + y2 = src[pixel + 2*st->width]; + + gradx = (x1 - x0); + grady = (y1 - x0); + gradx1= (x2 - x1); + grady1= (y2 - y1); + gradx1 = 1 + (gradx + gradx1) / 2; + grady1 = 1 + (grady + grady1) / 2; + + if ((2*across+MIN(gradx,gradx1) < 0) || + (2*across+MAX(gradx,gradx1) >= st->bigwidth)) { + gradx = 0; + gradx1= 1; + } + if ((2*down+MIN(grady,grady1) < 0) || + (2*down+MAX(grady,grady1) >= st->bigheight)) { + grady = 0; + grady1 = 1; + } + + if ((gradx == 0 && gradx1 == 1 && grady == 0 && grady1 == 1)) { + if (dirty[pixel] > 0) + dirty[pixel]--; + } else + dirty[pixel] = DIRTY; + + if (dirty[pixel] > 0) { + XPutPixel(st->buffer_map, (across<<1), (down<<1), + grayscale(st, XGetPixel(st->orig_map, (across<<1) + gradx, (down<<1) + grady))); + XPutPixel(st->buffer_map, (across<<1)+1,(down<<1), + grayscale(st, XGetPixel(st->orig_map, (across<<1) + gradx1,(down<<1) + grady))); + XPutPixel(st->buffer_map, (across<<1), (down<<1)+1, + grayscale(st, XGetPixel(st->orig_map, (across<<1) + gradx, (down<<1) + grady1))); + XPutPixel(st->buffer_map, (across<<1)+1,(down<<1)+1, + grayscale(st, XGetPixel(st->orig_map, (across<<1) + gradx1,(down<<1) + grady1))); + } + } +} + + +/* ------------------------------------------- */ + + +static void +set_mask(unsigned long color, unsigned long *mask, int *shift) +{ + *shift = 0; + while (color != 0 && (color & 1) == 0) { + (*shift)++; + color >>= 1; + } + *mask = color; +} + + +static unsigned long +cadd(unsigned long color, int dx, unsigned long mask, int shift) +{ + int x; + color >>= shift; + x = (color & mask); + x += dx; + if (x < 0) x = 0; + else if (x > (int)mask) x = mask; + color = x; + return color << shift; +} + + +static unsigned long +bright(struct state *st, int dx, unsigned long color) +{ + return (cadd(color, dx, st->rmask, st->rshift) | + cadd(color, dx, st->gmask, st->gshift) | + cadd(color, dx, st->bmask, st->bshift)); +} + + +static unsigned long +grayscale(struct state *st, unsigned long color) +{ + int red; + int green; + int blue; + int total; + int gray_r; + int gray_g; + int gray_b; + + if (!st->grayscale_p) + return color; + if (!st->transparent) + return color; + if ((st->rmask == 0) || (st->gmask == 0) || (st->bmask == 0)) + return color; + + red = ((color >> st->rshift) & st->rmask); + green = ((color >> st->gshift) & st->gmask); + blue = ((color >> st->bshift) & st->bmask); + total = red * st->gmask * st->bmask + green * st->rmask * st->bmask + blue * st->rmask * st->gmask; + + gray_r = total / (3 * st->gmask * st->bmask); + if (gray_r < 0) + gray_r = 0; + if (gray_r > st->rmask) + gray_r = st->rmask; + + gray_g = total / (3 * st->rmask * st->bmask); + if (gray_g < 0) + gray_g = 0; + if (gray_g > st->gmask) + gray_g = st->gmask; + + gray_b = total / (3 * st->rmask * st->gmask); + if (gray_b < 0) + gray_b = 0; + if (gray_b > st->bmask) + gray_b = st->bmask; + + return ((unsigned long) + ((gray_r << st->rshift) | (gray_g << st->gshift) | (gray_b << st->bshift))); +} + + +static void +draw_transparent_light(struct state *st, short *src) +{ + int across, down, pixel; + char *dirty = st->dirty_buffer; + + pixel = 0; + for (down = 0; down < st->height - 2; down++, pixel += 2) + for (across = 0; across < st->width-2; across++, pixel++) { + int gradx, grady, gradx1, grady1; + int x0, x1, x2, y1, y2; + + x0 = src[pixel]; + x1 = src[pixel + 1]; + x2 = src[pixel + 2]; + y1 = src[pixel + st->width]; + y2 = src[pixel + 2*st->width]; + + gradx = (x1 - x0); + grady = (y1 - x0); + gradx1= (x2 - x1); + grady1= (y2 - y1); + gradx1 = 1 + (gradx + gradx1) / 2; + grady1 = 1 + (grady + grady1) / 2; + + if ((2*across+MIN(gradx,gradx1) < 0) || + (2*across+MAX(gradx,gradx1) >= st->bigwidth)) { + gradx = 0; + gradx1= 1; + } + if ((2*down+MIN(grady,grady1) < 0) || + (2*down+MAX(grady,grady1) >= st->bigheight)) { + grady = 0; + grady1 = 1; + } + + if ((gradx == 0 && gradx1 == 1 && grady == 0 && grady1 == 1)) { + if (dirty[pixel] > 0) + dirty[pixel]--; + } else + dirty[pixel] = DIRTY; + + if (dirty[pixel] > 0) { + int dx; + + /* light from top */ + if (4-st->light >= 0) + dx = (grady + (src[pixel+st->width+1]-x1)) >> (4-st->light); + else + dx = (grady + (src[pixel+st->width+1]-x1)) << (st->light-4); + + if (dx != 0) { + XPutPixel(st->buffer_map, (across<<1), (down<<1), + bright(st, dx, grayscale(st, XGetPixel(st->orig_map, (across<<1) + gradx, (down<<1) + grady)))); + XPutPixel(st->buffer_map, (across<<1)+1,(down<<1), + bright(st, dx, grayscale(st, XGetPixel(st->orig_map, (across<<1) + gradx1,(down<<1) + grady)))); + XPutPixel(st->buffer_map, (across<<1), (down<<1)+1, + bright(st, dx, grayscale(st, XGetPixel(st->orig_map, (across<<1) + gradx, (down<<1) + grady1)))); + XPutPixel(st->buffer_map, (across<<1)+1,(down<<1)+1, + bright(st, dx, grayscale(st, XGetPixel(st->orig_map, (across<<1) + gradx1,(down<<1) + grady1)))); + } else { + /* Could use XCopyArea, but XPutPixel is faster */ + XPutPixel(st->buffer_map, (across<<1), (down<<1), + grayscale(st, XGetPixel(st->orig_map, (across<<1) + gradx, (down<<1) + grady))); + XPutPixel(st->buffer_map, (across<<1)+1,(down<<1), + grayscale(st, XGetPixel(st->orig_map, (across<<1) + gradx1,(down<<1) + grady))); + XPutPixel(st->buffer_map, (across<<1), (down<<1)+1, + grayscale(st, XGetPixel(st->orig_map, (across<<1) + gradx, (down<<1) + grady1))); + XPutPixel(st->buffer_map, (across<<1)+1,(down<<1)+1, + grayscale(st, XGetPixel(st->orig_map, (across<<1) + gradx1,(down<<1) + grady1))); + } + } + } +} + + +/* ------------------------------------------- */ + + +#if 0 +/* Doesn't go any faster and doesn't work at all colour depths */ +static void +draw_transparent16l(short *src) +{ + int across, down, bigpix, pixel; + char *dirty = st->dirty_buffer; + unsigned short *buffer, *orig; + + buffer = (unsigned short *) st->buffer_map->data; + orig = (unsigned short *) st->orig_map->data; + + for (pixel = bigpix = down = 0; + down < st->height - 2; + down++, pixel += 2, bigpix += st->bigwidth+4) + for (across = 0; across < st->width-2; across++, pixel++, bigpix+=2) { + int gradx, grady, gradx1, grady1; + int x0, x1, x2, y1, y2; + + x0 = src[pixel]; + x1 = src[pixel + 1]; + x2 = src[pixel + 2]; + y1 = src[pixel + st->width]; + y2 = src[pixel + 2*st->width]; + + gradx = (x1 - x0); + grady = (y1 - x0); + gradx1= (x2 - x1); + grady1= (y2 - y1); + gradx1 = 1 + (gradx + gradx1) / 2; + grady1 = 1 + (grady + grady1) / 2; + + if ((2*across+MIN(gradx,gradx1) < 0) || + (2*across+MAX(gradx,gradx1) >= st->bigwidth)) { + gradx = 0; + gradx1= 1; + } + if ((2*down+MIN(grady,grady1) < 0) || + (2*down+MAX(grady,grady1) >= st->bigheight)) { + grady = 0; + grady1 = 1; + } + + if ((gradx == 0 && gradx1 == 1 && grady == 0 && grady1 == 1)) { + if (dirty[pixel] > 0) + dirty[pixel]--; + } else + dirty[pixel] = DIRTY; + + if (dirty[pixel] > 0) { + unsigned short *dest = buffer + bigpix; + unsigned short *image = orig + bigpix; + int dx; + + /* light from top */ + if (4-st->light >= 0) + dx = (grady + (src[pixel+st->width+1]-x1)) >> (4-st->light); + else + dx = (grady + (src[pixel+st->width+1]-x1)) << (st->light-4); + + grady *= st->bigwidth; + grady1*= st->bigwidth; + + if (dx != 0) { + *dest++ = dobright(dx, *(image + gradx + grady)); + *dest = dobright(dx, *(image + gradx1 + grady)); + dest += st->bigwidth - 1; + *dest++ = dobright(dx, *(image + gradx + grady1)); + *dest = dobright(dx, *(image + gradx1 + grady1)); + } else { + *dest++ = *(image + gradx + grady); + *dest = *(image + gradx1 + grady); + dest += st->bigwidth - 1; + *dest++ = *(image + gradx + grady1); + *dest = *(image + gradx1 + grady1); + } + } + } +} +#endif + + +/* ------------------------------------------- */ + + +static void +setup_X(struct state *st) +{ + XWindowAttributes xgwa; + int depth; + + XGetWindowAttributes(st->dpy, st->window, &xgwa); + depth = xgwa.depth; + st->colormap = xgwa.colormap; + st->bigwidth = xgwa.width; + st->bigheight = xgwa.height; + st->visual = xgwa.visual; + + + /* This causes buffer_map to be 1 pixel taller and wider than orig_map, + which can cause the two XImages to have different bytes-per-line, + which causes stair-stepping. So this better not be necessary... + -jwz, 23-Nov-01 + */ +#if 0 /* I'm not entirely sure if I need this */ + if (st->bigwidth % 2) + st->bigwidth++; + if (st->bigheight % 2) + st->bigheight++; +#endif + + + st->width = st->bigwidth / 2; + st->height = st->bigheight / 2; + + if (st->transparent) { + XGCValues gcv; + long gcflags; + + gcv.function = GXcopy; + gcv.subwindow_mode = IncludeInferiors; + + gcflags = GCFunction; + if (use_subwindow_mode_p(xgwa.screen, st->window)) /* see grabscreen.c */ + gcflags |= GCSubwindowMode; + + st->gc = XCreateGC(st->dpy, st->window, gcflags, &gcv); + + st->img_loader = load_image_async_simple (0, xgwa.screen, st->window, + st->window, 0, 0); + st->start_time = time ((time_t) 0); + } else { + XGCValues gcv; + + st->gc = XCreateGC(st->dpy, st->window, 0, &gcv); + st->orig_map = 0; + } + + if (!st->gc) { + fprintf(stderr, "XCreateGC failed\n"); + exit(1); + } + + st->buffer_map = 0; + +#ifdef HAVE_XSHM_EXTENSION + if (st->use_shm) { + st->buffer_map = create_xshm_image(st->dpy, xgwa.visual, depth, + ZPixmap, 0, &st->shm_info, st->bigwidth, st->bigheight); + if (!st->buffer_map) { + st->use_shm = False; + fprintf(stderr, "create_xshm_image failed\n"); + } + } +#endif /* HAVE_XSHM_EXTENSION */ + + if (!st->buffer_map) { + st->buffer_map = XCreateImage(st->dpy, xgwa.visual, + depth, ZPixmap, 0, 0, + st->bigwidth, st->bigheight, 8, 0); + st->buffer_map->data = (char *) + calloc(st->buffer_map->height, st->buffer_map->bytes_per_line); + } +} + + +static void +DisplayImage(struct state *st) +{ +#ifdef HAVE_XSHM_EXTENSION + if (st->use_shm) + XShmPutImage(st->dpy, st->window, st->gc, st->buffer_map, 0, 0, 0, 0, + st->bigwidth, st->bigheight, False); + else +#endif /* HAVE_XSHM_EXTENSION */ + XPutImage(st->dpy, st->window, st->gc, st->buffer_map, 0, 0, 0, 0, + st->bigwidth, st->bigheight); +} + + +/* ------------------------------------------- */ + + +static int +cinterp(double a, int bg, int fg) +{ + int result; + result = (int)((1-a) * bg + a * fg + 0.5); + if (result < 0) result = 0; + if (result > 255) result = 255; + return result; +} + + +/* Interpolate the ripple colours between the background colour and + foreground colour */ +static void +init_linear_colors(struct state *st) +{ + int i, j, red, green, blue, bred, bgreen, bblue; + XColor fg, bg; + + if (st->ncolors < 2 || mono_p) + st->ncolors = 2; + if (st->ncolors <= 2) + mono_p = True; + + /* Make it possible to set the color of the ripples, + Based on work by Raymond Medeiros and jwz. + */ + fg.pixel = get_pixel_resource(st->dpy, st->colormap, "foreground", "Foreground"); + XQueryColor(st->dpy, st->colormap, &fg); + red = (fg.red >> 8); + green = (fg.green >> 8); + blue = (fg.blue >> 8); + + bg.pixel = get_pixel_resource(st->dpy, st->colormap, "background", "Background"); + XQueryColor(st->dpy, st->colormap, &bg); + bred = (bg.red >> 8); + bgreen = (bg.green >> 8); + bblue = (bg.blue >> 8); + + j = 0; + for (i = 0; i < st->ncolors+1; i++) { + XColor xcl; + double a = (double)i / st->ncolors; + int r = cinterp(a, bred, red); + int g = cinterp(a, bgreen, green); + int b = cinterp(a, bblue, blue); + + xcl.red = (unsigned short) ((r << 8) | r); + xcl.green = (unsigned short) ((g << 8) | g); + xcl.blue = (unsigned short) ((b << 8) | b); + xcl.flags = DoRed | DoGreen | DoBlue; + + XAllocColor(st->dpy, st->colormap, &xcl); + + st->ctab[j++] = (int) xcl.pixel; + } +} + + +static void +init_oily_colors(struct state *st) +{ + XColor *colors = NULL; + + if (st->ncolors < 2 || mono_p) + st->ncolors = 2; + if (st->ncolors <= 2) + mono_p = True; + colors = 0; + + if (!mono_p) { + colors = (XColor *)malloc(sizeof(*colors) * (st->ncolors+1)); + make_smooth_colormap(st->dpy, st->visual, st->colormap, colors, &st->ncolors, + True, /* allocate */ + False, /* not writable */ + True); /* verbose (complain about failure) */ + if (st->ncolors <= 2) { + if (colors) + free (colors); + colors = 0; + mono_p = True; + } + } + if (!mono_p) { + int i, j = 0; + for (i = 0; i < st->ncolors+1; i++) { + XAllocColor(st->dpy, st->colormap, colors+i); + st->ctab[j++] = (int) colors[i].pixel; + } + free (colors); + } else { + st->ncolors = 2; + st->ctab[1] = get_pixel_resource(st->dpy, st->colormap, "foreground", "Foreground"); + st->ctab[0] = get_pixel_resource(st->dpy, st->colormap, "background", "Background"); + } +} + + +/* ------------------------------------------- */ + + +static void +init_cos_tab(struct state *st) +{ + int i; + for (i = 0; i < TABLE; i++) + st->cos_tab[i] = cos(i * M_PI/2 / TABLE); +} + + +/* Shape of drop to add */ +static double +sinc(struct state *st, double x) +{ +#if 1 + /* cosine hump */ + int i; + i = (int)(x * TABLE + 0.5); + if (i >= TABLE) i = (TABLE-1) - (i-(TABLE-1)); + if (i < 0) return 0.; + return st->cos_tab[i]; +#elif 0 + return cos(x * M_PI/2); +#else + if (fabs(x) < 0.1) + return 1 - x*x; + else + return sin(x) / x; +#endif +} + + +static void +add_circle_drop(struct state *st, int x, int y, int radius, int dheight) +{ + int r, r2, cx, cy; + short *buf = (random()&1) ? st->bufferA : st->bufferB; + + r2 = radius * radius; + + + for (cy = -radius; cy <= radius; cy++) + for (cx = -radius; cx <= radius; cx++) { + int xx = x+cx; + int yy = y+cy; + if (xx < 0 || yy < 0 || xx >= st->width || yy >= st->height) {break;} + r = cx*cx + cy*cy; + if (r > r2) break; + buf[xx + yy*st->width] = + (short)(dheight * sinc(st, (radius > 0) ? sqrt(r)/radius : 0)); + } +} + + +static void +add_drop(struct state *st, ripple_mode mode, int drop) +{ + int newx, newy, dheight; + int radius = MIN(st->width, st->height) / 50; + /* Don't put drops too near the edge of the screen or they get stuck */ + int border = 8; + + switch (mode) { + default: + case ripple_drop: { + int x; + + dheight = 1 + (random() % drop); + newx = border + (random() % (st->width - 2*border)); + newy = border + (random() % (st->height - 2*border)); + x = newy * st->width + newx; + st->bufferA[x + 1] = st->bufferA[x] = st->bufferA[x + st->width] = st->bufferA[x + st->width + 1] = + st->bufferB[x + 1] = st->bufferB[x] = st->bufferB[x + st->width] = st->bufferB[x + st->width + 1] = + dheight; + } + break; + case ripple_blob: { + double power; + + int tmp_i, tmp_j; + power = drop_dist[random() % (sizeof(drop_dist)/sizeof(drop_dist[0]))]; /* clumsy */ + dheight = (int)(drop * (power + 0.01)); + tmp_i = (int)(st->width - 2*border - 2*radius*power); + tmp_j = (int)(st->height - 2*border - 2*radius*power); + newx = radius + border + ((tmp_i > 0) ? random() % tmp_i : 0); + newy = radius + border + ((tmp_j > 0) ? random() % tmp_j : 0); + add_circle_drop(st, newx, newy, radius, dheight); + } + break; + /* Adding too many boxes too quickly (-box 1) doesn't give the waves time + to disperse and the waves build up (and overflow) */ + case ripple_box: { + int x; + int cx, cy; + short *buf = (random()&1) ? st->bufferA : st->bufferB; + int tmp_i, tmp_j; + + radius = (1 + (random() % 5)) * (1 + (random() % 5)); + dheight = drop / 128; + if (random() & 1) dheight = -dheight; + tmp_i = st->width - 2*border - 2*radius; + tmp_j = st->height - 2*border - 2*radius; + newx = radius + border + ((tmp_i > 0) ? random() % tmp_i : 0); + newy = radius + border + ((tmp_j > 0) ? random() % tmp_j : 0); + x = newy * st->width + newx; + for (cy = -radius; cy <= radius; cy++) + for (cx = -radius; cx <= radius; cx++) + buf[x + cx + cy*st->width] = (short)(dheight); + } + break; + case ripple_stir: { + border += radius; + newx = border + (int)((st->width-2*border) * (1+cos(3*st->stir_ang)) / 2); + newy = border + (int)((st->height-2*border) * (1+sin(2*st->stir_ang)) / 2); + add_circle_drop(st, newx, newy, radius, drop / 10); + st->stir_ang += 0.02; + if (st->stir_ang > 12*M_PI) st->stir_ang = 0; + } + break; + } +} + + +static void +init_ripples(struct state *st, int ndrops, int splash) +{ + int i; + + st->bufferA = (short *)calloc(st->width * st->height, sizeof(*st->bufferA)); + st->bufferB = (short *)calloc(st->width * st->height, sizeof(*st->bufferB)); + st->temp = (short *)calloc(st->width * st->height, sizeof(*st->temp)); + + st->dirty_buffer = (char *)calloc(st->width * st->height, sizeof(*st->dirty_buffer)); + + for (i = 0; i < ndrops; i++) + add_drop(st, ripple_blob, splash); + + if (st->transparent) { + if (st->grayscale_p) + { + int across, down; + for (down = 0; down < st->bigheight; down++) + for (across = 0; across < st->bigwidth; across++) + XPutPixel(st->buffer_map, across, down, + grayscale(st, XGetPixel(st->orig_map, across, down))); + } + else + { + /* There's got to be a better way of doing this XCopyArea? */ + memcpy(st->buffer_map->data, st->orig_map->data, + st->bigheight * st->buffer_map->bytes_per_line); + } + } else { + int across, down, color; + + color = map_color(st, 0); /* background colour */ + for (down = 0; down < st->bigheight; down++) + for (across = 0; across < st->bigwidth; across++) + XPutPixel(st->buffer_map,across, down, color); + } + + DisplayImage(st); +} + + +/* + Explanation from hq_water.zip (Arturo R Montesinos (ARM) arami@fi.upm.es) + + Differential equation is: u = a ( u + u ) + tt xx yy + + Where a = tension * gravity / surface_density. + + Approximating second derivatives by central differences: + + [ u(t+1)-2u(t)+u(t-1) ] / dt = a [ u(x+1)+u(x-1)+u(y+1)+u(y-1)-4u ] / h + + where dt = time step squared, h = dx*dy = mesh resolution squared. + + From where u(t+1) may be calculated as: + + dt | 1 | dt + u(t+1) = a -- | 1 0 1 |u - u(t-1) + (2-4a --)u + h | 1 | h + + When a*dt/h = 1/2 last term vanishes, giving: + + 1 | 1 | + u(t+1) = - | 1 0 1 |u - u(t-1) + 2 | 1 | + + (note that u(t-1,x,y) is only used to calculate u(t+1,x,y) so + we can use the same array for both t-1 and t+1, needing only + two arrays, U[0] and U[1]) + + Dampening is simulated by subtracting 1/2^n of result. + n=4 gives best-looking result + n<4 (eg 2 or 3) thicker consistency, waves die out immediately + n>4 (eg 8 or 12) more fluid, waves die out slowly + */ + +static void +ripple(struct state *st) +{ + int across, down, pixel; + short *src, *dest; + + if (st->draw_toggle == 0) { + src = st->bufferA; + dest = st->bufferB; + st->draw_toggle = 1; + } else { + src = st->bufferB; + dest = st->bufferA; + st->draw_toggle = 0; + } + + switch (st->draw_count) { + case 0: case 1: + pixel = 1 * st->width + 1; + for (down = 1; down < st->height - 1; down++, pixel += 2 * 1) + for (across = 1; across < st->width - 1; across++, pixel++) { + st->temp[pixel] = + (((src[pixel - 1] + src[pixel + 1] + + src[pixel - st->width] + src[pixel + st->width]) / 2)) - dest[pixel]; + } + + /* Smooth the output */ + pixel = 1 * st->width + 1; + for (down = 1; down < st->height - 1; down++, pixel += 2 * 1) + for (across = 1; across < st->width - 1; across++, pixel++) { + if (st->temp[pixel] != 0) { /* Close enough for government work */ + int damp = + (st->temp[pixel - 1] + st->temp[pixel + 1] + + st->temp[pixel - st->width] + st->temp[pixel + st->width] + + st->temp[pixel - st->width - 1] + st->temp[pixel - st->width + 1] + + st->temp[pixel + st->width - 1] + st->temp[pixel + st->width + 1] + + st->temp[pixel]) / 9; + dest[pixel] = damp - (damp >> st->fluidity); + } else + dest[pixel] = 0; + } + break; + case 2: case 3: + pixel = 1 * st->width + 1; + for (down = 1; down < st->height - 1; down++, pixel += 2 * 1) + for (across = 1; across < st->width - 1; across++, pixel++) { + int damp = + (((src[pixel - 1] + src[pixel + 1] + + src[pixel - st->width] + src[pixel + st->width]) / 2)) - dest[pixel]; + dest[pixel] = damp - (damp >> st->fluidity); + } + break; + } + if (++st->draw_count > 3) st->draw_count = 0; + + if (st->transparent) + st->draw_transparent(st, dest); + else + draw_ripple(st, dest); +} + + +/* ------------------------------------------- */ + +static void * +ripples_init (Display *disp, Window win) +{ + struct state *st = (struct state *) calloc (1, sizeof(*st)); + st->dpy = disp; + st->window = win; + st->iterations = 0; + st->delay = get_integer_resource(disp, "delay", "Integer"); + st->duration = get_integer_resource (st->dpy, "duration", "Seconds"); + st->rate = get_integer_resource(disp, "rate", "Integer"); + st->box = get_integer_resource(disp, "box", "Integer"); + st->oily = get_boolean_resource(disp, "oily", "Boolean"); + st->stir = get_boolean_resource(disp, "stir", "Boolean"); + st->fluidity = get_integer_resource(disp, "fluidity", "Integer"); + st->transparent = get_boolean_resource(disp, "water", "Boolean"); + st->grayscale_p = get_boolean_resource(disp, "grayscale", "Boolean"); +#ifdef HAVE_XSHM_EXTENSION + st->use_shm = get_boolean_resource(disp, "useSHM", "Boolean"); +#endif /* HAVE_XSHM_EXTENSION */ + st->light = get_integer_resource(disp, "light", "Integer"); + + if (st->delay < 0) st->delay = 0; + if (st->duration < 1) st->duration = 1; + if (st->fluidity <= 1) st->fluidity = 1; + if (st->fluidity > 16) st->fluidity = 16; /* 16 = sizeof(short) */ + if (st->light < 0) st->light = 0; + + init_cos_tab(st); + setup_X(st); + + st->ncolors = get_integer_resource (disp, "colors", "Colors"); + if (0 == st->ncolors) /* English spelling? */ + st->ncolors = get_integer_resource (disp, "colours", "Colors"); + + if (st->ncolors > sizeof(st->ctab)/sizeof(*st->ctab)) + st->ncolors = sizeof(st->ctab)/sizeof(*st->ctab); + + if (st->oily) + init_oily_colors(st); + else + init_linear_colors(st); + + if (st->transparent && st->light > 0) { + int maxbits; + st->draw_transparent = draw_transparent_light; + set_mask(st->visual->red_mask, &st->rmask, &st->rshift); + set_mask(st->visual->green_mask, &st->gmask, &st->gshift); + set_mask(st->visual->blue_mask, &st->bmask, &st->bshift); + if (st->rmask == 0) st->draw_transparent = draw_transparent_vanilla; + + /* Adjust the shift value "light" when we don't have 8 bits per colour */ + maxbits = MIN(MIN(BITCOUNT(st->rmask), BITCOUNT(st->gmask)), BITCOUNT(st->bmask)); + st->light -= 8-maxbits; + if (st->light < 0) st->light = 0; + } else { + if (st->grayscale_p) + { + set_mask(st->visual->red_mask, &st->rmask, &st->rshift); + set_mask(st->visual->green_mask, &st->gmask, &st->gshift); + set_mask(st->visual->blue_mask, &st->bmask, &st->bshift); + } + st->draw_transparent = draw_transparent_vanilla; + } + + if (!st->transparent) + init_ripples(st, 0, -SPLASH); /* Start off without any drops */ + + return st; +} + +static unsigned long +ripples_draw (Display *dpy, Window window, void *closure) +{ + struct state *st = (struct state *) closure; + + if (st->img_loader) /* still loading */ + { + st->img_loader = load_image_async_simple (st->img_loader, 0, 0, 0, 0, 0); + if (! st->img_loader) { /* just finished */ + XWindowAttributes xgwa; + XGetWindowAttributes(st->dpy, st->window, &xgwa); + st->start_time = time ((time_t) 0); + st->orig_map = XGetImage (st->dpy, st->window, 0, 0, + xgwa.width, xgwa.height, + ~0L, ZPixmap); + init_ripples(st, 0, -SPLASH); /* Start off without any drops */ + } + return st->delay; + } + + if (!st->img_loader && + st->start_time + st->duration < time ((time_t) 0)) { + XWindowAttributes xgwa; + XGetWindowAttributes(st->dpy, st->window, &xgwa); + st->img_loader = load_image_async_simple (0, xgwa.screen, st->window, + st->window, 0, 0); + st->start_time = time ((time_t) 0); + return st->delay; + } + + if (st->rate > 0 && (st->iterations % st->rate) == 0) + add_drop(st, ripple_blob, -SPLASH); + if (st->stir) + add_drop(st, ripple_stir, -SPLASH); + if (st->box > 0 && (random() % st->box) == 0) + add_drop(st, ripple_box, -SPLASH); + + ripple(st); + DisplayImage(st); + + st->iterations++; + + return st->delay; +} + + +static void +ripples_reshape (Display *dpy, Window window, void *closure, + unsigned int w, unsigned int h) +{ +} + +static Bool +ripples_event (Display *dpy, Window window, void *closure, XEvent *event) +{ + return False; +} + +static void +ripples_free (Display *dpy, Window window, void *closure) +{ + struct state *st = (struct state *) closure; + free (st); +} + +static const char *ripples_defaults[] = +{ + ".background: black", + ".foreground: #FFAF5F", + "*colors: 200", + "*dontClearRoot: True", + "*delay: 50000", + "*duration: 120", + "*rate: 5", + "*box: 0", + "*water: True", + "*oily: False", + "*stir: False", + "*fluidity: 6", + "*light: 4", + "*grayscale: False", +#ifdef HAVE_XSHM_EXTENSION + "*useSHM: True", +#else + "*useSHM: False", +#endif + 0 +}; + +static XrmOptionDescRec ripples_options[] = +{ + { "-colors", ".colors", XrmoptionSepArg, 0}, + { "-colours", ".colors", XrmoptionSepArg, 0}, + {"-delay", ".delay", XrmoptionSepArg, 0}, + {"-duration", ".duration", XrmoptionSepArg, 0 }, + {"-rate", ".rate", XrmoptionSepArg, 0}, + {"-box", ".box", XrmoptionSepArg, 0}, + {"-water", ".water", XrmoptionNoArg, "True"}, + {"-oily", ".oily", XrmoptionNoArg, "True"}, + {"-stir", ".stir", XrmoptionNoArg, "True"}, + {"-fluidity", ".fluidity", XrmoptionSepArg, 0}, + {"-light", ".light", XrmoptionSepArg, 0}, + {"-grayscale", ".grayscale", XrmoptionNoArg, "True"}, + {"-shm", ".useSHM", XrmoptionNoArg, "True"}, + {"-no-shm", ".useSHM", XrmoptionNoArg, "False"}, + {0, 0, 0, 0} +}; + + +XSCREENSAVER_MODULE ("Ripples", ripples) diff --git a/hacks/ripples.man b/hacks/ripples.man new file mode 100644 index 00000000..f016683a --- /dev/null +++ b/hacks/ripples.man @@ -0,0 +1,96 @@ +.TH XScreenSaver 1 "" "X Version 11" +.SH NAME +ripples - interference patterns. +.SH SYNOPSIS +.B ripples +[\-display \fIhost:display.screen\fP] +[\-visual \fIvisual\fP] +[\-window] +[\-root] +[\-delay \fInumber\fP] +[\-duration \fIsecs\fP] +[\-rate \fInumber\fP] +[\-fluidity \fInumber\fP] +[\-light \fInumber\fP] +[\-water] +[\-stir] +[\-oily] +[\-grayscale] +[\-colors \fInumber\fP] +[\-no-shm] +[\-fps] +.SH DESCRIPTION +This draws rippling interference patterns like splashing water. With the +-water option, it manipulates your desktop image to look like something is +dripping into it. +.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: 50000 (0.05 seconds.). +.TP 8 +.B \-duration \fIseconds\fP +How long to run before loading a new image. Default 120 seconds. +.TP 8 +.B \-rate \fInumber\fP +Drizzle. 1 - 100. Default: 5. +.TP 8 +.B \-fluidity \fInumber\fP +Small Drops. 0 - 16. Default: 6. +.TP 8 +.B \-light \fInumber\fP +Lighting Effect. 0 - 8. Default: 0. +.TP 8 +.B \-water | \-no-water +Grab Screen Image. Boolean. +.TP 8 +.B \-stir | \-no-stir +Moving Splashes. Boolean. +.TP 8 +.B \-oily | \-no-oily +Psychedelic Colors. Boolean. +.TP 8 +.B \-grayscale +Convert the screen image to grayscale. +Ignored if we don't grab the screen image or if our screen doesn't have +enough color depth. +.TP 8 +.B \-colors \fInumber\fP +Colors Two. Default: 200. +.TP 8 +.B \-shm | \-no-shm +Use Shared Memory. Boolean. +.TP 8 +.B \-fps +Display the current frame rate and CPU load. +.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 2002 by Tom Hammersley. 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 +Tom Hammersley. diff --git a/hacks/rocks.c b/hacks/rocks.c new file mode 100644 index 00000000..f1c60633 --- /dev/null +++ b/hacks/rocks.c @@ -0,0 +1,545 @@ +/* xscreensaver, Copyright (c) 1992-2008 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. + */ + +/* 18-Sep-97: Johannes Keukelaar : Added some color. + * Using -mono gives the old behaviour. (Modified by jwz.) + */ +/* Flying through an asteroid field. Based on TI Explorer Lisp code by + John Nguyen + */ + +#include +#include +#include "screenhack.h" + +#define MIN_ROCKS 1 +#define MIN_DEPTH 2 /* rocks disappear when they get this close */ +#define MAX_DEPTH 60 /* this is where rocks appear */ +#define MIN_SIZE 3 /* how small where pixmaps are not used */ +#define MAX_SIZE 200 /* how big (in pixels) rocks are at depth 1 */ +#define DEPTH_SCALE 100 /* how many ticks there are between depths */ +#define SIN_RESOLUTION 1000 + +#define MAX_DEP 0.3 /* how far the displacement can be (percent) */ +#define DIRECTION_CHANGE_RATE 60 +#define MAX_DEP_SPEED 5 /* Maximum speed for movement */ +#define MOVE_STYLE 0 /* Only 0 and 1. Distinguishes the fact that + these are the rocks that are moving (1) + or the rocks source (0). */ + +/* there's not much point in the above being user-customizable, but those + numbers might want to be tweaked for displays with an order of magnitude + higher resolution or compute power. + */ + +struct state { + Display *dpy; + Window window; + + double sins [SIN_RESOLUTION]; + double coss [SIN_RESOLUTION]; + double depths [(MAX_DEPTH + 1) * DEPTH_SCALE]; + + int width, height, midx, midy; + int dep_x, dep_y; + int ncolors; + XColor *colors; + float max_dep; + GC erase_gc; + GC *draw_gcs; + Bool rotate_p; + Bool move_p; + int speed; + Bool threed; + GC threed_left_gc, threed_right_gc; + double threed_delta; + + struct rock *rocks; + int nrocks; + Pixmap pixmaps [MAX_SIZE]; + int delay; + + int move_current_dep[2]; + int move_speed[2]; + short move_direction[2]; + int move_limit[2]; + + int current_delta; /* observer Z rotation */ + int new_delta; + int dchange_tick; +}; + + + +#define GETZDIFF(z) \ + (st->threed_delta * 40.0 * \ + (1.0 - ((MAX_DEPTH * DEPTH_SCALE / 2) / \ + ((z) + 20.0 * DEPTH_SCALE)))) + +struct rock { + int real_size; + int r; + int theta; + int depth; + int size, x, y; + int diff; + int color; +}; + +static void rock_compute (struct state *, struct rock *); +static void rock_draw (struct state *, struct rock *, Bool draw_p); + +static void +rock_reset (struct state *st, struct rock *rock) +{ + rock->real_size = MAX_SIZE; + rock->r = (SIN_RESOLUTION * 0.7) + (random () % (30 * SIN_RESOLUTION)); + rock->theta = random () % SIN_RESOLUTION; + rock->depth = MAX_DEPTH * DEPTH_SCALE; + rock->color = random() % st->ncolors; + rock_compute (st, rock); + rock_draw (st, rock, True); +} + +static void +rock_tick (struct state *st, struct rock *rock, int d) +{ + if (rock->depth > 0) + { + rock_draw (st, rock, False); + rock->depth -= st->speed; + if (st->rotate_p) + { + rock->theta = (rock->theta + d) % SIN_RESOLUTION; + } + while (rock->theta < 0) + rock->theta += SIN_RESOLUTION; + if (rock->depth < (MIN_DEPTH * DEPTH_SCALE)) + rock->depth = 0; + else + { + rock_compute (st, rock); + rock_draw (st, rock, True); + } + } + else if ((random () % 40) == 0) + rock_reset (st, rock); +} + +static void +rock_compute (struct state *st, struct rock *rock) +{ + double factor = st->depths [rock->depth]; + double rsize = rock->real_size * factor; + + rock->size = (int) (rsize + 0.5); + rock->diff = (int) GETZDIFF(rock->depth); + rock->x = st->midx + (st->coss [rock->theta] * rock->r * factor); + rock->y = st->midy + (st->sins [rock->theta] * rock->r * factor); + + if (st->move_p) + { + double move_factor = (((double) MOVE_STYLE) - + (((double) rock->depth) / + (((double) (MAX_DEPTH + 1)) * + ((double) DEPTH_SCALE)))); + /* move_factor is 0 when the rock is close, 1 when far */ + rock->x += (((double) st->dep_x) * move_factor); + rock->y += (((double) st->dep_y) * move_factor); + } +} + +static void +rock_draw (struct state *st, struct rock *rock, Bool draw_p) +{ + GC gc = (draw_p + ? (st->threed ? st->erase_gc : st->draw_gcs[rock->color]) + : st->erase_gc); + + if (rock->x <= 0 || rock->y <= 0 || rock->x >= st->width || rock->y >= st->height) + { + /* this means that if a rock were to go off the screen at 12:00, but + would have been visible at 3:00, it won't come back once the observer + rotates around so that the rock would have been visible again. + Oh well. + */ + if (!st->move_p) + rock->depth = 0; + return; + } + if (rock->size <= 1) + { + if (st->threed) + { + if (draw_p) gc = st->threed_left_gc; + XDrawPoint (st->dpy, st->window, gc, rock->x - rock->diff, rock->y); + if (draw_p) gc = st->threed_right_gc; + XDrawPoint (st->dpy, st->window, gc, rock->x + rock->diff, rock->y); + } + else + { + XDrawPoint (st->dpy, st->window, gc, rock->x, rock->y); + } + } + else if (rock->size <= MIN_SIZE || !draw_p) + { + if (st->threed) + { + if (draw_p) gc = st->threed_left_gc; + XFillRectangle(st->dpy, st->window, gc, + rock->x - rock->size / 2 - rock->diff, + rock->y - rock->size / 2, + rock->size, rock->size); + if (draw_p) gc = st->threed_right_gc; + XFillRectangle(st->dpy, st->window, gc, + rock->x - rock->size / 2 + rock->diff, + rock->y - rock->size / 2, + rock->size, rock->size); + } + else + { + XFillRectangle (st->dpy, st->window, gc, + rock->x - rock->size/2, rock->y - rock->size/2, + rock->size, rock->size); + } + } + else if (rock->size < MAX_SIZE) + { + if (st->threed) + { + gc = st->threed_left_gc; + XCopyPlane(st->dpy, st->pixmaps[rock->size], st->window, gc, + 0, 0, rock->size, rock->size, + rock->x - rock->size / 2 - rock->diff, + rock->y - rock->size / 2, 1L); + gc = st->threed_right_gc; + XCopyPlane(st->dpy, st->pixmaps[rock->size], st->window, gc, + 0, 0, rock->size, rock->size, + rock->x - rock->size / 2 + rock->diff, + rock->y - rock->size / 2, 1L); + } + else + { + XCopyPlane (st->dpy, st->pixmaps [rock->size], st->window, gc, + 0, 0, rock->size, rock->size, + rock->x - rock->size/2, rock->y - rock->size/2, + 1L); + } + } +} + + +static void +init_pixmaps (struct state *st) +{ + int i; + XGCValues gcv; + GC fg_gc = 0, bg_gc = 0; + st->pixmaps [0] = st->pixmaps [1] = 0; + for (i = MIN_DEPTH; i < MAX_SIZE; i++) + { + int w = (1+(i/32))<<5; /* server might be faster if word-aligned */ + int h = i; + Pixmap p = XCreatePixmap (st->dpy, st->window, w, h, 1); + XPoint points [7]; + st->pixmaps [i] = p; + if (! p) + { + fprintf (stderr, "%s: couldn't allocate pixmaps", progname); + exit (1); + } + if (! fg_gc) + { /* must use drawable of pixmap, not window (fmh) */ + gcv.foreground = 1; + fg_gc = XCreateGC (st->dpy, p, GCForeground, &gcv); + gcv.foreground = 0; + bg_gc = XCreateGC (st->dpy, p, GCForeground, &gcv); + } + XFillRectangle (st->dpy, p, bg_gc, 0, 0, w, h); + points [0].x = i * 0.15; points [0].y = i * 0.85; + points [1].x = i * 0.00; points [1].y = i * 0.20; + points [2].x = i * 0.30; points [2].y = i * 0.00; + points [3].x = i * 0.40; points [3].y = i * 0.10; + points [4].x = i * 0.90; points [4].y = i * 0.10; + points [5].x = i * 1.00; points [5].y = i * 0.55; + points [6].x = i * 0.45; points [6].y = i * 1.00; + XFillPolygon (st->dpy, p, fg_gc, points, 7, Nonconvex, CoordModeOrigin); + } + XFreeGC (st->dpy, fg_gc); + XFreeGC (st->dpy, bg_gc); +} + + +static int +compute_move(struct state *st, int axe) /* 0 for x, 1 for y */ +{ + int change = 0; + + st->move_limit[0] = st->midx; + st->move_limit[1] = st->midy; + + st->move_current_dep[axe] += st->move_speed[axe]; /* We adjust the displacement */ + + if (st->move_current_dep[axe] > (int) (st->move_limit[axe] * st->max_dep)) + { + if (st->move_current_dep[axe] > st->move_limit[axe]) + st->move_current_dep[axe] = st->move_limit[axe]; + st->move_direction[axe] = -1; + } /* This is when we reach the upper screen limit */ + if (st->move_current_dep[axe] < (int) (-st->move_limit[axe] * st->max_dep)) + { + if (st->move_current_dep[axe] < -st->move_limit[axe]) + st->move_current_dep[axe] = -st->move_limit[axe]; + st->move_direction[axe] = 1; + } /* This is when we reach the lower screen limit */ + if (st->move_direction[axe] == 1) /* We adjust the speed */ + st->move_speed[axe] += 1; + else if (st->move_direction[axe] == -1) + st->move_speed[axe] -= 1; + + if (st->move_speed[axe] > MAX_DEP_SPEED) + st->move_speed[axe] = MAX_DEP_SPEED; + else if (st->move_speed[axe] < -MAX_DEP_SPEED) + st->move_speed[axe] = -MAX_DEP_SPEED; + + if (st->move_p && !(random() % DIRECTION_CHANGE_RATE)) + { + /* We change direction */ + change = random() & 1; + if (change != 1) + { + if (st->move_direction[axe] == 0) + st->move_direction[axe] = change - 1; /* 0 becomes either 1 or -1 */ + else + st->move_direction[axe] = 0; /* -1 or 1 become 0 */ + } + } + return (st->move_current_dep[axe]); +} + +static void +tick_rocks (struct state *st, int d) +{ + int i; + + if (st->move_p) + { + st->dep_x = compute_move(st, 0); + st->dep_y = compute_move(st, 1); + } + + for (i = 0; i < st->nrocks; i++) + rock_tick (st, &st->rocks [i], d); +} + + +static unsigned long +rocks_draw (Display *dpy, Window window, void *closure) +{ + struct state *st = (struct state *) closure; + if (st->current_delta != st->new_delta) + { + if (st->dchange_tick++ == 5) + { + st->dchange_tick = 0; + if (st->current_delta < st->new_delta) + st->current_delta++; + else + st->current_delta--; + } + } + else + { + if (! (random() % 50)) + { + st->new_delta = ((random() % 11) - 5); + if (! (random() % 10)) + st->new_delta *= 5; + } + } + tick_rocks (st, st->current_delta); + + return st->delay; +} + +static void * +rocks_init (Display *d, Window w) +{ + struct state *st = (struct state *) calloc (1, sizeof(*st)); + int i; + XGCValues gcv; + Colormap cmap; + XWindowAttributes xgwa; + unsigned int bg; + st->dpy = d; + st->window = w; + XGetWindowAttributes (st->dpy, st->window, &xgwa); + + st->width = xgwa.width; + st->height = xgwa.height; + st->midx = st->width/2; + st->midy = st->height/2; + + cmap = xgwa.colormap; + st->delay = get_integer_resource (st->dpy, "delay", "Integer"); + if (st->delay < 0) st->delay = 0; + st->speed = get_integer_resource (st->dpy, "speed", "Integer"); + if (st->speed < 1) st->speed = 1; + if (st->speed > 100) st->speed = 100; + st->rotate_p = get_boolean_resource (st->dpy, "rotate", "Boolean"); + st->move_p = get_boolean_resource (st->dpy, "move", "Boolean"); + if (mono_p) + st->ncolors = 2; + else + st->ncolors = get_integer_resource (st->dpy, "colors", "Colors"); + + if (st->ncolors < 2) + { + st->ncolors = 2; + mono_p = True; + } + + st->colors = (XColor *) malloc(st->ncolors * sizeof(*st->colors)); + st->draw_gcs = (GC *) malloc(st->ncolors * sizeof(*st->draw_gcs)); + + bg = get_pixel_resource (st->dpy, cmap, "background", "Background"); + st->colors[0].pixel = bg; + st->colors[0].flags = DoRed|DoGreen|DoBlue; + XQueryColor(st->dpy, cmap, &st->colors[0]); + + st->ncolors--; + make_random_colormap(st->dpy, xgwa.visual, cmap, st->colors+1, &st->ncolors, True, + True, 0, True); + st->ncolors++; + + if (st->ncolors < 2) + { + st->ncolors = 2; + mono_p = True; + } + + if (mono_p) + { + unsigned int fg = get_pixel_resource(st->dpy, cmap, "foreground", "Foreground"); + st->colors[1].pixel = fg; + st->colors[1].flags = DoRed|DoGreen|DoBlue; + XQueryColor(st->dpy, cmap, &st->colors[1]); + gcv.foreground = fg; + gcv.background = bg; + st->draw_gcs[0] = XCreateGC (st->dpy, st->window, GCForeground|GCBackground, &gcv); + st->draw_gcs[1] = st->draw_gcs[0]; + } + else + for( i = 0; i < st->ncolors; i++ ) + { + gcv.foreground = st->colors[i].pixel; + gcv.background = bg; + st->draw_gcs[i] = XCreateGC (st->dpy, st->window, GCForeground|GCBackground, &gcv); + } + + gcv.foreground = bg; + st->erase_gc = XCreateGC (st->dpy, st->window, GCForeground|GCBackground, &gcv); + + st->max_dep = (st->move_p ? MAX_DEP : 0); + + for (i = 0; i < SIN_RESOLUTION; i++) + { + st->sins [i] = sin ((((double) i) / (SIN_RESOLUTION / 2)) * M_PI); + st->coss [i] = cos ((((double) i) / (SIN_RESOLUTION / 2)) * M_PI); + } + /* we actually only need i/speed of these, but wtf */ + for (i = 1; i < (sizeof (st->depths) / sizeof (st->depths[0])); i++) + st->depths [i] = atan (((double) 0.5) / (((double) i) / DEPTH_SCALE)); + st->depths [0] = M_PI/2; /* avoid division by 0 */ + + st->threed = get_boolean_resource(st->dpy, "use3d", "Boolean"); + if (st->threed) + { + gcv.background = bg; + gcv.foreground = get_pixel_resource (st->dpy, cmap, "left3d", "Foreground"); + st->threed_left_gc = XCreateGC (st->dpy, st->window, GCForeground|GCBackground,&gcv); + gcv.foreground = get_pixel_resource (st->dpy, cmap, "right3d", "Foreground"); + st->threed_right_gc = XCreateGC (st->dpy, st->window,GCForeground|GCBackground,&gcv); + st->threed_delta = get_float_resource(st->dpy, "delta3d", "Integer"); + } + + /* don't want any exposure events from XCopyPlane */ + for( i = 0; i < st->ncolors; i++) + XSetGraphicsExposures (st->dpy, st->draw_gcs[i], False); + XSetGraphicsExposures (st->dpy, st->erase_gc, False); + + st->nrocks = get_integer_resource (st->dpy, "count", "Count"); + if (st->nrocks < 1) st->nrocks = 1; + st->rocks = (struct rock *) calloc (st->nrocks, sizeof (struct rock)); + init_pixmaps (st); + XClearWindow (st->dpy, st->window); + return st; +} + +static void +rocks_reshape (Display *dpy, Window window, void *closure, + unsigned int w, unsigned int h) +{ + struct state *st = (struct state *) closure; + st->width = w; + st->height = h; + st->midx = st->width/2; + st->midy = st->height/2; +} + +static Bool +rocks_event (Display *dpy, Window window, void *closure, XEvent *event) +{ + return False; +} + +static void +rocks_free (Display *dpy, Window window, void *closure) +{ +} + + + +static const char *rocks_defaults [] = { + ".background: Black", + ".foreground: #E9967A", + "*fpsSolid: true", + "*colors: 5", + "*count: 100", + "*delay: 50000", + "*speed: 100", + "*rotate: true", + "*move: true", + "*use3d: False", + "*left3d: Blue", + "*right3d: Red", + "*delta3d: 1.5", + 0 +}; + +static XrmOptionDescRec rocks_options [] = { + { "-count", ".count", XrmoptionSepArg, 0 }, + { "-rotate", ".rotate", XrmoptionNoArg, "true" }, + { "-no-rotate", ".rotate", XrmoptionNoArg, "false" }, + { "-move", ".move", XrmoptionNoArg, "true" }, + { "-no-move", ".move", XrmoptionNoArg, "false" }, + { "-delay", ".delay", XrmoptionSepArg, 0 }, + { "-speed", ".speed", XrmoptionSepArg, 0 }, + {"-3d", ".use3d", XrmoptionNoArg, "True"}, + {"-no-3d", ".use3d", XrmoptionNoArg, "False"}, + {"-left3d", ".left3d", XrmoptionSepArg, 0 }, + {"-right3d", ".right3d", XrmoptionSepArg, 0 }, + {"-delta3d", ".delta3d", XrmoptionSepArg, 0 }, + { "-colors", ".colors", XrmoptionSepArg, 0 }, + { 0, 0, 0, 0 } +}; + +XSCREENSAVER_MODULE ("Rocks", rocks) diff --git a/hacks/rocks.man b/hacks/rocks.man new file mode 100644 index 00000000..b5751d99 --- /dev/null +++ b/hacks/rocks.man @@ -0,0 +1,90 @@ +.TH XScreenSaver 1 "13-aug-92" "X Version 11" +.SH NAME +rocks - animation of flying through an asteroid field +.SH SYNOPSIS +.B rocks +[\-display \fIhost:display.screen\fP] [\-foreground \fIcolor\fP] [\-background \fIcolor\fP] [\-window] [\-root] [\-mono] [\-ncolors \fIn\fP] [\-install] [\-visual \fIvisual\fP] [\-count \fIinteger\fP] [\-delay \fIusecs\fP] [\-speed \fIinteger\fP] [\-norotate] [\-nomove] [\-3d] +[\-fps] +.SH DESCRIPTION +The \fIrocks\fP program draws an animation of an asteroid field moving past +the observer (or vice versa). Sometimes the observer picks up spin on Z axis. +.SH OPTIONS +.I rocks +accepts the following options: +.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 \-mono +Make all the rocks the same color. +.TP 8 +.B \-ncolors colors +How many different colors to use. Default 5. Colors are chosen randomly. +.TP 8 +.B \-install +Install a private colormap for the window. +.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 \-count \fIinteger\fP +Maximum number of rocks to draw on the screen at once. Default 100. +.TP 8 +.B \-speed \fIinteger\fP +A measure of the speed with which the observer and the rocks pass each other, +from 1 to 100. Default 100, meaning ``very fast.'' If you're on a slow +display connection (the animation looks jerky) then try making this number +smaller, and/or decreasing the number of rocks. +.TP 8 +.B \-delay \fImicroseconds\fP +Number of microseconds to delay between each frame. Default 50000, meaning +about 1/20th second. Compare and contrast with \fI\-speed\fP, above. +.TP 8 +.B \-norotate +Don't rotate the observer; just fly through the field on the level. +.TP 8 +.B \-nomove +Don't turn the observer; just fly straight ahead through the field. +.TP 8 +.B \-3d +Do red/blue 3d separations: if you look at the screen with 3d glasses, +the rocks will be \fIjumping\fP right \fIout\fP at you. Oooooh, scaaary! +.TP 8 +.B \-fps +Display the current frame rate and CPU load. +.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 BUGS +There should be an option to display doppler shift (a gravity rainbow.) + +Speed of rotation should be settable. + +Default speed of rotation should be relative to forward velocity. +.SH COPYRIGHT +Copyright \(co 1992 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 +Based on Lisp Machine code copyright 1988 John Nguyen . + +Ported to C and X by Jamie Zawinski , 13-aug-92. + +Steering code by Jeremie Petit; 3D code by theiling@coli.uni-sb.de. diff --git a/hacks/rorschach.c b/hacks/rorschach.c new file mode 100644 index 00000000..b4f4aa89 --- /dev/null +++ b/hacks/rorschach.c @@ -0,0 +1,205 @@ +/* xscreensaver, Copyright (c) 1992-2008 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. + * + * 19971004: Johannes Keukelaar : Use helix screen + * eraser. + */ + +#include "screenhack.h" +#include "erase.h" + +struct state { + GC draw_gc; + unsigned int default_fg_pixel; + int iterations, offset; + Bool xsym, ysym; + int sleep_time; + int xlim, ylim; + XColor color; + int current_x, current_y, remaining_iterations; + eraser_state *eraser; +}; + + +static void * +rorschach_init (Display *dpy, Window window) +{ + struct state *st = (struct state *) calloc (1, sizeof(*st)); + XGCValues gcv; + Colormap cmap; + XWindowAttributes xgwa; + XGetWindowAttributes (dpy, window, &xgwa); + cmap = xgwa.colormap; + gcv.foreground = st->default_fg_pixel = + get_pixel_resource (dpy, cmap, "foreground", "Foreground"); + st->draw_gc = XCreateGC (dpy, window, GCForeground, &gcv); + gcv.foreground = get_pixel_resource (dpy, cmap, "background", "Background"); + st->iterations = get_integer_resource (dpy, "iterations", "Integer"); + st->offset = get_integer_resource (dpy, "offset", "Integer"); + if (st->offset <= 0) st->offset = 3; + if (st->iterations < 10) st->iterations = 10; + st->sleep_time = get_integer_resource (dpy, "delay", "Delay"); + st->xsym = get_boolean_resource (dpy, "xsymmetry", "Symmetry"); + st->ysym = get_boolean_resource (dpy, "ysymmetry", "Symmetry"); + st->remaining_iterations = -1; + st->color.pixel = 0; + return st; +} + +static void +rorschach_reshape (Display *dpy, Window window, void *closure, + unsigned int width, unsigned int height) +{ + struct state *st = (struct state *) closure; + st->xlim = width; + st->ylim = height; +} + + +static void +rorschach_draw_start (Display *dpy, Window window, struct state *st) +{ + Colormap cmap; + XWindowAttributes xgwa; + + XGetWindowAttributes (dpy, window, &xgwa); + st->xlim = xgwa.width; + st->ylim = xgwa.height; + cmap = xgwa.colormap; + + if (st->color.pixel) XFreeColors (dpy, cmap, &st->color.pixel, 1, 0); + + if (! mono_p) + hsv_to_rgb (random()%360, 1.0, 1.0, &st->color.red, &st->color.green, &st->color.blue); + if ((!mono_p) && XAllocColor (dpy, cmap, &st->color)) + XSetForeground (dpy, st->draw_gc, st->color.pixel); + else + XSetForeground (dpy, st->draw_gc, st->default_fg_pixel); + + st->current_x = st->xlim/2; + st->current_y = st->ylim/2; + st->remaining_iterations = st->iterations; +} + + +static void +rorschach_draw_step (Display *dpy, Window window, struct state *st) +{ +# define ITER_CHUNK 300 + XPoint points [4 * ITER_CHUNK]; + int x = st->current_x; + int y = st->current_y; + int i, j = 0; + + int this_iterations = ITER_CHUNK; + if (this_iterations > st->remaining_iterations) + this_iterations = st->remaining_iterations; + + for (i = 0; i < this_iterations; i++) + { + x += ((random () % (1 + (st->offset << 1))) - st->offset); + y += ((random () % (1 + (st->offset << 1))) - st->offset); + points [j].x = x; + points [j].y = y; + j++; + if (st->xsym) + { + points [j].x = st->xlim - x; + points [j].y = y; + j++; + } + if (st->ysym) + { + points [j].x = x; + points [j].y = st->ylim - y; + j++; + } + if (st->xsym && st->ysym) + { + points [j].x = st->xlim - x; + points [j].y = st->ylim - y; + j++; + } + } + XDrawPoints (dpy, window, st->draw_gc, points, j, CoordModeOrigin); + st->remaining_iterations -= this_iterations; + if (st->remaining_iterations < 0) st->remaining_iterations = 0; + st->current_x = x; + st->current_y = y; +} + + +static unsigned long +rorschach_draw (Display *dpy, Window window, void *closure) +{ + struct state *st = (struct state *) closure; + unsigned long delay = 20000; + + if (st->eraser) { + st->eraser = erase_window (dpy, window, st->eraser); + goto END; + } + + if (st->remaining_iterations > 0) + { + rorschach_draw_step (dpy, window, st); + if (st->remaining_iterations == 0) + delay = st->sleep_time * 1000000; + } + else + { + if (st->remaining_iterations == 0) + st->eraser = erase_window (dpy, window, st->eraser); + + rorschach_draw_start (dpy, window, st); + } + END: + return delay; +} + + +static Bool +rorschach_event (Display *dpy, Window window, void *closure, XEvent *event) +{ + return False; +} + +static void +rorschach_free (Display *dpy, Window window, void *closure) +{ + struct state *st = (struct state *) closure; + free (st); +} + + +static const char *rorschach_defaults [] = { + ".background: black", + ".foreground: white", + "*fpsSolid: true", + "*xsymmetry: true", + "*ysymmetry: false", + "*iterations: 4000", + "*offset: 7", + "*delay: 5", + 0 +}; + +static XrmOptionDescRec rorschach_options [] = { + { "-iterations", ".iterations", XrmoptionSepArg, 0 }, + { "-offset", ".offset", XrmoptionSepArg, 0 }, + { "-xsymmetry", ".xsymmetry", XrmoptionNoArg, "true" }, + { "-ysymmetry", ".ysymmetry", XrmoptionNoArg, "true" }, + { "-no-xsymmetry", ".xsymmetry", XrmoptionNoArg, "false" }, + { "-no-ysymmetry", ".ysymmetry", XrmoptionNoArg, "false" }, + { "-delay", ".delay", XrmoptionSepArg, 0 }, + { 0, 0, 0, 0 } +}; + +XSCREENSAVER_MODULE ("Rorschach", rorschach) diff --git a/hacks/rorschach.man b/hacks/rorschach.man new file mode 100644 index 00000000..5a28cf65 --- /dev/null +++ b/hacks/rorschach.man @@ -0,0 +1,75 @@ +.TH XScreenSaver 1 "13-aug-92" "X Version 11" +.SH NAME +rorschach - simulate ink-blot patterns +.SH SYNOPSIS +.B rorschach +[\-display \fIhost:display.screen\fP] [\-foreground \fIcolor\fP] [\-background \fIcolor\fP] [\-window] [\-root] [\-mono] [\-install] [\-visual \fIvisual\fP] [\-iterations \fIinteger\fP] [\-offset \fIinteger\fP] [\-xsymmetry] [\-ysymmetry] [\-erase\-speed \fIusecs\fP] [\-delay \fIsecs\fP] +[\-fps] +.SH DESCRIPTION +The \fIrorschach\fP program draws random patterns reminiscent of the +psychological test of same name. +.SH OPTIONS +.I rorschach +accepts the following options: +.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 \-mono +If on a color display, pretend we're on a monochrome display. +.TP 8 +.B \-install +Install a private colormap for the window. +.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 \-iterations \fIinteger\fP +How many dots should be drawn each time. Default 4000. +.TP 8 +.B \-offset \fIinteger\fP +How far apart the dots should be. Default 4 pixels. +.TP 8 +.B \-xsymmetry +Whether the images should be horizontally symmetrical. Default true. +.TP 8 +.B \-ysymmetry +Whether the images should be vertically symmetrical. Default false. +.TP 8 +.B \-erase\-speed \fIusecs\fP +This controls the speed at which the screen will be erased. (Delay between +erasing of individual lines.) +.TP 8 +.B \-delay \fIseconds\fP +This sets the number of seconds that the figure will be on the screen. +.TP 8 +.B \-fps +Display the current frame rate and CPU load. +.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 BUGS +May call your sanity into question. +.SH SEE ALSO +.BR X (1), +.BR xscreensaver (1) +.SH COPYRIGHT +Copyright \(co 1992 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 , 13-aug-92. diff --git a/hacks/rotor.c b/hacks/rotor.c new file mode 100644 index 00000000..eb1a0b78 --- /dev/null +++ b/hacks/rotor.c @@ -0,0 +1,401 @@ +/* -*- Mode: C; tab-width: 4 -*- */ +/* rotor --- a swirly rotor */ + +#if 0 +static const char sccsid[] = "@(#)rotor.c 5.00 2000/11/01 xlockmore"; +#endif + +/*- + * Copyright (c) 1991 by Patrick J. Naughton. + * + * Permission to use, copy, modify, and distribute this software and its + * documentation for any purpose and without fee is hereby granted, + * provided that the above copyright notice appear in all copies and that + * both that copyright notice and this permission notice appear in + * supporting documentation. + * + * This file is provided AS IS with no warranties of any kind. The author + * shall have no liability with respect to the infringement of copyrights, + * trade secrets or any patents by this file or any part thereof. In no + * event will the author be liable for any lost revenue or profits or + * other special, indirect and consequential damages. + * + * Revision History: + * 01-Nov-2000: Allocation checks + * 10-May-1997: Compatible with xscreensaver + * 08-Mar-1995: CAT stuff for ## was tripping up some C compilers. Removed. + * 01-Dec-1993: added patch for AIXV3 from Tom McConnell + * + * 11-Nov-1990: put into xlock by Steve Zellers + * 16-Oct-1990: Received from Tom Lawrence (tcl@cs.brown.edu: 'flight' + * simulator) + */ + +#ifdef STANDALONE +#define MODE_rotor +#define DEFAULTS "*delay: 10000 \n" \ + "*count: 4 \n" \ + "*cycles: 20 \n" \ + "*size: -6 \n" \ + "*ncolors: 200 \n" \ + "*fpsSolid: true \n" \ + +# define SMOOTH_COLORS +# define reshape_rotor 0 +# define rotor_handle_event 0 +# include "xlockmore.h" /* in xscreensaver distribution */ +#else /* STANDALONE */ +# include "xlock.h" /* in xlockmore distribution */ +#endif /* STANDALONE */ + +#ifdef MODE_rotor + +ENTRYPOINT ModeSpecOpt rotor_opts = +{0, (XrmOptionDescRec *) NULL, 0, (argtype *) NULL, (OptionStruct *) NULL}; + +#ifdef USE_MODULES +ModStruct rotor_description = +{"rotor", "init_rotor", "draw_rotor", "release_rotor", + "refresh_rotor", "init_rotor", (char *) NULL, &rotor_opts, + 100, 4, 100, -6, 64, 0.3, "", + "Shows Tom's Roto-Rooter", 0, NULL}; + +#endif + +/*- + * A 'batchcount' of 3 or 4 works best! + */ + +#define MAXANGLE 3000.0 /* irrectangular (was 10000.0) */ + +/* How many segments to draw per cycle when redrawing */ +#define REDRAWSTEP 3 + +typedef struct { + float angle; + float radius; + float start_radius; + float end_radius; + float radius_drift_max; + float radius_drift_now; + + float ratio; + float start_ratio; + float end_ratio; + float ratio_drift_max; + float ratio_drift_now; +} elem; + +typedef struct { + int pix; + int lastx, lasty; + int num, rotor, prev; + int nsave; + float angle; + int centerx, centery; + int prevcenterx, prevcentery; + unsigned char firsttime; + unsigned char iconifiedscreen; /* for iconified view */ + unsigned char forward; + unsigned char unused; + elem *elements; + XPoint *save; + int redrawing, redrawpos; + int linewidth; +} rotorstruct; + +static rotorstruct *rotors = (rotorstruct *) NULL; + +static void +free_rotor(rotorstruct *rp) +{ + if (rp->elements != NULL) { + (void) free((void *) rp->elements); + rp->elements = (elem *) NULL; + } + if (rp->save != NULL) { + (void) free((void *) rp->save); + rp->save = (XPoint *) NULL; + } +} + +ENTRYPOINT void +init_rotor (ModeInfo * mi) +{ + int x; + elem *pelem; + unsigned char wasiconified; + rotorstruct *rp; + + if (rotors == NULL) { + if ((rotors = (rotorstruct *) calloc(MI_NUM_SCREENS(mi), + sizeof (rotorstruct))) == NULL) + return; + } + rp = &rotors[MI_SCREEN(mi)]; + +#ifdef HAVE_COCOA + jwxyz_XSetAntiAliasing (MI_DISPLAY(mi), MI_GC(mi), False); +#endif + + rp->prevcenterx = rp->centerx; + rp->prevcentery = rp->centery; + + rp->centerx = MI_WIDTH(mi) / 2; + rp->centery = MI_HEIGHT(mi) / 2; + + rp->redrawing = 0; + /* + * sometimes, you go into iconified view, only to see a really whizzy pattern + * that you would like to look more closely at. Normally, clicking in the + * icon reinitializes everything - but I don't, cuz I'm that kind of guy. + * HENCE, the wasiconified stuff you see here. + */ + + wasiconified = rp->iconifiedscreen; + rp->iconifiedscreen = MI_IS_ICONIC(mi); + + if (wasiconified && !rp->iconifiedscreen) + rp->firsttime = True; + else { + + /* This is a fudge is needed since prevcenter may not be set when it comes + from the the random mode and return is pressed (and its not the first + mode that was running). This assumes that the size of the lock screen + window / size of the icon window = 12 */ + if (!rp->prevcenterx) + rp->prevcenterx = rp->centerx * 12; + if (!rp->prevcentery) + rp->prevcentery = rp->centery * 12; + + rp->num = MI_COUNT(mi); + if (rp->num < 0) { + rp->num = NRAND(-rp->num) + 1; + if (rp->elements != NULL) { + (void) free((void *) rp->elements); + rp->elements = (elem *) NULL; + } + } + if (rp->elements == NULL) + if ((rp->elements = (elem *) calloc(rp->num, + sizeof (elem))) == NULL) { + free_rotor(rp); + return; + } + rp->nsave = MI_CYCLES(mi); + if (rp->nsave <= 1) + rp->nsave = 2; + if (rp->save == NULL) + if ((rp->save = (XPoint *) malloc(rp->nsave * + sizeof (XPoint))) == NULL) { + free_rotor(rp); + return; + } + for (x = 0; x < rp->nsave; x++) { + rp->save[x].x = rp->centerx; + rp->save[x].y = rp->centery; + } + + pelem = rp->elements; + + for (x = rp->num; --x >= 0; pelem++) { + pelem->radius_drift_max = 1.0; + pelem->radius_drift_now = 1.0; + + pelem->end_radius = 100.0; + + pelem->ratio_drift_max = 1.0; + pelem->ratio_drift_now = 1.0; + pelem->end_ratio = 10.0; + } + if (MI_NPIXELS(mi) > 2) + rp->pix = NRAND(MI_NPIXELS(mi)); + + rp->rotor = 0; + rp->prev = 1; + rp->lastx = rp->centerx; + rp->lasty = rp->centery; + rp->angle = (float) NRAND((long) MAXANGLE) / 3.0; + rp->forward = rp->firsttime = True; + } + rp->linewidth = MI_SIZE(mi); + + if (rp->linewidth == 0) + rp->linewidth = 1; + if (rp->linewidth < 0) + rp->linewidth = NRAND(-rp->linewidth) + 1; + + MI_CLEARWINDOW(mi); +} + +ENTRYPOINT void +draw_rotor (ModeInfo * mi) +{ + Display *display = MI_DISPLAY(mi); + GC gc = MI_GC(mi); + register elem *pelem; + int thisx, thisy; + int i; + int x_1, y_1, x_2, y_2; + rotorstruct *rp; + + if (rotors == NULL) + return; + rp = &rotors[MI_SCREEN(mi)]; + if (rp->elements == NULL) + return; + + MI_IS_DRAWN(mi) = True; + if (!rp->iconifiedscreen) { + thisx = rp->centerx; + thisy = rp->centery; + } else { + thisx = rp->prevcenterx; + thisy = rp->prevcentery; + } + XSetLineAttributes(MI_DISPLAY(mi), MI_GC(mi), rp->linewidth, + LineSolid, CapButt, JoinMiter); + for (i = rp->num, pelem = rp->elements; --i >= 0; pelem++) { + if (pelem->radius_drift_max <= pelem->radius_drift_now) { + pelem->start_radius = pelem->end_radius; + pelem->end_radius = (float) NRAND(40000) / 100.0 - 200.0; + pelem->radius_drift_max = (float) NRAND(100000) + 10000.0; + pelem->radius_drift_now = 0.0; + } + if (pelem->ratio_drift_max <= pelem->ratio_drift_now) { + pelem->start_ratio = pelem->end_ratio; + pelem->end_ratio = (float) NRAND(2000) / 100.0 - 10.0; + pelem->ratio_drift_max = (float) NRAND(100000) + 10000.0; + pelem->ratio_drift_now = 0.0; + } + pelem->ratio = pelem->start_ratio + + (pelem->end_ratio - pelem->start_ratio) / + pelem->ratio_drift_max * pelem->ratio_drift_now; + pelem->angle = rp->angle * pelem->ratio; + pelem->radius = pelem->start_radius + + (pelem->end_radius - pelem->start_radius) / + pelem->radius_drift_max * pelem->radius_drift_now; + + thisx += (int) (COSF(pelem->angle) * pelem->radius); + thisy += (int) (SINF(pelem->angle) * pelem->radius); + + pelem->ratio_drift_now += 1.0; + pelem->radius_drift_now += 1.0; + } + if (rp->firsttime) + rp->firsttime = False; + else { + XSetForeground(display, gc, MI_BLACK_PIXEL(mi)); + + x_1 = (int) rp->save[rp->rotor].x; + y_1 = (int) rp->save[rp->rotor].y; + x_2 = (int) rp->save[rp->prev].x; + y_2 = (int) rp->save[rp->prev].y; + + if (rp->iconifiedscreen) { + x_1 = x_1 * rp->centerx / rp->prevcenterx; + x_2 = x_2 * rp->centerx / rp->prevcenterx; + y_1 = y_1 * rp->centery / rp->prevcentery; + y_2 = y_2 * rp->centery / rp->prevcentery; + } + XDrawLine(display, MI_WINDOW(mi), gc, x_1, y_1, x_2, y_2); + + if (MI_NPIXELS(mi) > 2) { + XSetForeground(display, gc, MI_PIXEL(mi, rp->pix)); + if (++rp->pix >= MI_NPIXELS(mi)) + rp->pix = 0; + } else + XSetForeground(display, gc, MI_WHITE_PIXEL(mi)); + + x_1 = rp->lastx; + y_1 = rp->lasty; + x_2 = thisx; + y_2 = thisy; + + if (rp->iconifiedscreen) { + x_1 = x_1 * rp->centerx / rp->prevcenterx; + x_2 = x_2 * rp->centerx / rp->prevcenterx; + y_1 = y_1 * rp->centery / rp->prevcentery; + y_2 = y_2 * rp->centery / rp->prevcentery; + } + XDrawLine(display, MI_WINDOW(mi), gc, x_1, y_1, x_2, y_2); + } + rp->save[rp->rotor].x = rp->lastx = thisx; + rp->save[rp->rotor].y = rp->lasty = thisy; + + ++rp->rotor; + rp->rotor %= rp->nsave; + ++rp->prev; + rp->prev %= rp->nsave; + if (rp->forward) { + rp->angle += 0.01; + if (rp->angle >= MAXANGLE) { + rp->angle = MAXANGLE; + rp->forward = False; + } + } else { + rp->angle -= 0.1; + if (rp->angle <= 0) { + rp->angle = 0.0; + rp->forward = True; + } + } + if (rp->redrawing) { + int j; + + for (i = 0; i < REDRAWSTEP; i++) { + j = (rp->rotor - rp->redrawpos + rp->nsave) % rp->nsave; + + x_1 = (int) rp->save[j].x; + y_1 = (int) rp->save[j].y; + x_2 = (int) rp->save[(j - 1 + rp->nsave) % rp->nsave].x; + y_2 = (int) rp->save[(j - 1 + rp->nsave) % rp->nsave].y; + + if (rp->iconifiedscreen) { + x_1 = x_1 * rp->centerx / rp->prevcenterx; + x_2 = x_2 * rp->centerx / rp->prevcenterx; + y_1 = y_1 * rp->centery / rp->prevcentery; + y_2 = y_2 * rp->centery / rp->prevcentery; + } + XDrawLine(display, MI_WINDOW(mi), gc, x_1, y_1, x_2, y_2); + + if (++(rp->redrawpos) >= rp->nsave) { + rp->redrawing = 0; + break; + } + } + } + XSetLineAttributes(MI_DISPLAY(mi), MI_GC(mi), 1, + LineSolid, CapButt, JoinMiter); +} + +ENTRYPOINT void +release_rotor (ModeInfo * mi) +{ + if (rotors != NULL) { + int screen; + + for (screen = 0; screen < MI_NUM_SCREENS(mi); screen++) + free_rotor(&rotors[screen]); + (void) free((void *) rotors); + rotors = (rotorstruct *) NULL; + } +} + +ENTRYPOINT void +refresh_rotor (ModeInfo * mi) +{ + rotorstruct *rp; + + if (rotors == NULL) + return; + rp = &rotors[MI_SCREEN(mi)]; + + MI_CLEARWINDOW(mi); + rp->redrawing = 1; + rp->redrawpos = 1; +} + +XSCREENSAVER_MODULE ("Rotor", rotor) + +#endif /* MODE_rotor */ diff --git a/hacks/rotor.man b/hacks/rotor.man new file mode 100644 index 00000000..58590ed5 --- /dev/null +++ b/hacks/rotor.man @@ -0,0 +1,68 @@ +.TH XScreenSaver 1 "" "X Version 11" +.SH NAME +rotor - screen saver. +.SH SYNOPSIS +.B rotor +[\-display \fIhost:display.screen\fP] +[\-visual \fIvisual\fP] +[\-window] +[\-root] +[\-count \fInumber\fP] +[\-cycles \fInumber\fP] +[\-delay \fInumber\fP] +[\-ncolors \fInumber\fP] +[\-size \fInumber\fP] +[\-fps] +.SH DESCRIPTION +This draws a line segment moving along a complex spiraling curve. +.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 \-count \fInumber\fP +Count. 0 - 20. Default: 4. +.TP 8 +.B \-cycles \fInumber\fP +Length. 2 - 100. Default: 20. +.TP 8 +.B \-delay \fInumber\fP +Per-frame delay, in microseconds. Default: 10000 (0.01 seconds.). +.TP 8 +.B \-ncolors \fInumber\fP +Number of Colors. Default: 200. +.TP 8 +.B \-size \fInumber\fP +Size. -50 - 50. Default: -6. +.TP 8 +.B \-fps +Display the current frame rate and CPU load. +.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 2002 by Tom Lawrence. 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 +Tom Lawrence. diff --git a/hacks/rotzoomer.c b/hacks/rotzoomer.c new file mode 100644 index 00000000..610b9520 --- /dev/null +++ b/hacks/rotzoomer.c @@ -0,0 +1,483 @@ +/* rotzoomer - creates a collage of rotated and scaled portions of the screen + * Copyright (C) 2001 Claudio Matsuoka + * + * 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. + */ + +/* + * Options: + * + * -shm enable MIT shared memory extension + * -no-shm disable MIT shared memory extension + * -n number of zoomboxes + * -move enable mobile zoomboxes + * -sweep enable sweep mode + * -anim enable snapshot mode + * -no-anim enable snapshot mode + * -delay delay in milliseconds + */ + +#include +#include "screenhack.h" + +#ifdef HAVE_XSHM_EXTENSION +#include "xshm.h" +#endif + +struct zoom_area { + int w, h; /* rectangle width and height */ + int inc1, inc2; /* rotation and zoom angle increments */ + int dx, dy; /* translation increments */ + int a1, a2; /* rotation and zoom angular variables */ + int ox, oy; /* origin in the background copy */ + int xx, yy; /* left-upper corner position (* 256) */ + int x, y; /* left-upper corner position */ + int ww, hh; /* valid area to place left-upper corner */ + int n; /* number of iteractions */ + int count; /* current iteraction */ +}; + +struct state { + Display *dpy; + Window window; + + GC gc; + Visual *visual; + XImage *orig_map, *buffer_map; + Colormap colormap; + + int width, height; + struct zoom_area **zoom_box; + int num_zoom; + int move; + int sweep; + int delay; + int anim; + int duration; + time_t start_time; + + async_load_state *img_loader; + +#ifdef HAVE_XSHM_EXTENSION + Bool use_shm; + XShmSegmentInfo shm_info; +#endif +}; + + +static void +rotzoom (struct state *st, struct zoom_area *za) +{ + int x, y, c, s, zoom, z; + int x2 = za->x + za->w - 1, y2 = za->y + za->h - 1; + int ox = 0, oy = 0; + + z = 8100 * sin (M_PI * za->a2 / 8192); + zoom = 8192 + z; + + c = zoom * cos (M_PI * za->a1 / 8192); + s = zoom * sin (M_PI * za->a1 / 8192); + for (y = za->y; y <= y2; y++) { + for (x = za->x; x <= x2; x++) { + ox = (x * c + y * s) >> 13; + oy = (-x * s + y * c) >> 13; + + while (ox < 0) + ox += st->width; + while (oy < 0) + oy += st->height; + while (ox >= st->width) + ox -= st->width; + while (oy >= st->height) + oy -= st->height; + + XPutPixel (st->buffer_map, x, y, XGetPixel (st->orig_map, ox, oy)); + } + } + + za->a1 += za->inc1; /* Rotation angle */ + za->a1 &= 0x3fff;; + + za->a2 += za->inc2; /* Zoom */ + za->a2 &= 0x3fff; + + za->ox = ox; /* Save state for next iteration */ + za->oy = oy; + + za->count++; +} + + +static void +reset_zoom (struct state *st, struct zoom_area *za) +{ + if (st->sweep) { + int speed = random () % 100 + 100; + switch (random () % 4) { + case 0: + za->w = st->width; + za->h = 10; + za->x = 0; + za->y = 0; + za->dx = 0; + za->dy = speed; + za->n = (st->height - 10) * 256 / speed; + break; + case 1: + za->w = 10; + za->h = st->height; + za->x = st->width - 10; + za->y = 0; + za->dx = -speed; + za->dy = 0; + za->n = (st->width - 10) * 256 / speed; + break; + case 2: + za->w = st->width; + za->h = 10; + za->x = 0; + za->y = st->height - 10; + za->dx = 0; + za->dy = -speed; + za->n = (st->height - 10) * 256 / speed; + break; + case 3: + za->w = 10; + za->h = st->height; + za->x = 0; + za->y = 0; + za->dx = speed; + za->dy = 0; + za->n = (st->width - 10) * 256 / speed; + break; + } + za->ww = st->width - za->w; + za->hh = st->height - za->h; + + /* We want smaller angle increments in sweep mode (looks better) */ + + za->a1 = 0; + za->a2 = 0; + za->inc1 = ((2 * (random() & 1)) - 1) * (1 + random () % 7); + za->inc2 = ((2 * (random() & 1)) - 1) * (1 + random () % 7); + } else { + za->w = 50 + random() % 300; + za->h = 50 + random() % 300; + + if (za->w > st->width / 3) + za->w = st->width / 3; + if (za->h > st->height / 3) + za->h = st->height / 3; + + za->ww = st->width - za->w; + za->hh = st->height - za->h; + + za->x = (za->ww ? random() % za->ww : 0); + za->y = (za->hh ? random() % za->hh : 0); + + za->dx = ((2 * (random() & 1)) - 1) * (100 + random() % 300); + za->dy = ((2 * (random() & 1)) - 1) * (100 + random() % 300); + + if (st->anim) { + za->n = 50 + random() % 1000; + za->a1 = 0; + za->a2 = 0; + } else { + za->n = 5 + random() % 10; + za->a1 = random (); + za->a2 = random (); + } + + za->inc1 = ((2 * (random() & 1)) - 1) * (random () % 30); + za->inc2 = ((2 * (random() & 1)) - 1) * (random () % 30); + } + + za->xx = za->x * 256; + za->yy = za->y * 256; + + za->count = 0; +} + + +static struct zoom_area * +create_zoom (struct state *st) +{ + struct zoom_area *za; + + za = malloc (sizeof (struct zoom_area)); + reset_zoom (st, za); + + return za; +} + + +static void +update_position (struct zoom_area *za) +{ + za->xx += za->dx; + za->yy += za->dy; + + za->x = za->xx >> 8; + za->y = za->yy >> 8; + + if (za->x < 0) { + za->x = 0; + za->dx = 100 + random() % 100; + } + + if (za->y < 0) { + za->y = 0; + za->dy = 100 + random() % 100; + } + + if (za->x > za->ww) { + za->x = za->ww; + za->dx = -(100 + random() % 100); + } + + if (za->y > za->hh) { + za->y = za->hh; + za->dy = -(100 + random() % 100); + } +} + + +static void +DisplayImage (struct state *st, int x, int y, int w, int h) +{ +#ifdef HAVE_XSHM_EXTENSION + if (st->use_shm) + XShmPutImage (st->dpy, st->window, st->gc, st->buffer_map, x, y, x, y, + w, h, False); + else +#endif /* HAVE_XSHM_EXTENSION */ + XPutImage(st->dpy, st->window, st->gc, st->buffer_map, x, y, x, y, w, h); +} + + +static void +init_hack (struct state *st) +{ + int i; + + st->start_time = time ((time_t) 0); + st->zoom_box = calloc (st->num_zoom, sizeof (struct zoom_area *)); + for (i = 0; i < st->num_zoom; i++) { + st->zoom_box[i] = create_zoom (st); + } + + if (st->height && st->orig_map->data) + memcpy (st->buffer_map->data, st->orig_map->data, + st->height * st->buffer_map->bytes_per_line); + + DisplayImage(st, 0, 0, st->width, st->height); +} + + +static unsigned long +rotzoomer_draw (Display *disp, Window win, void *closure) +{ + struct state *st = (struct state *) closure; + int delay = st->delay; + int i; + + if (st->img_loader) /* still loading */ + { + st->img_loader = load_image_async_simple (st->img_loader, 0, 0, 0, 0, 0); + if (! st->img_loader) { /* just finished */ + st->orig_map = XGetImage (st->dpy, st->window, 0, 0, + st->width, st->height, ~0L, ZPixmap); + init_hack (st); + } + return st->delay; + } + + if (!st->img_loader && + st->start_time + st->duration < time ((time_t) 0)) { + XWindowAttributes xgwa; + XGetWindowAttributes(st->dpy, st->window, &xgwa); + st->img_loader = load_image_async_simple (0, xgwa.screen, st->window, + st->window, 0, 0); + st->start_time = time ((time_t) 0); + return st->delay; + } + + for (i = 0; i < st->num_zoom; i++) { + if (st->move || st->sweep) + update_position (st->zoom_box[i]); + + if (st->zoom_box[i]->n > 0) { + if (st->anim || st->zoom_box[i]->count == 0) { + rotzoom (st, st->zoom_box[i]); + } else { + delay = 1000000; + } + st->zoom_box[i]->n--; + } else { + reset_zoom (st, st->zoom_box[i]); + } + } + + for (i = 0; i < st->num_zoom; i++) { + DisplayImage(st, st->zoom_box[i]->x, st->zoom_box[i]->y, + st->zoom_box[i]->w, st->zoom_box[i]->h); + } + + return delay; +} + + +static void +setup_X (struct state *st) +{ + XWindowAttributes xgwa; + int depth; + XGCValues gcv; + long gcflags; + + XGetWindowAttributes (st->dpy, st->window, &xgwa); + depth = xgwa.depth; + st->colormap = xgwa.colormap; + st->width = xgwa.width; + st->height = xgwa.height; + st->visual = xgwa.visual; + + if (st->width % 2) + st->width--; + if (st->height % 2) + st->height--; + + gcv.function = GXcopy; + gcv.subwindow_mode = IncludeInferiors; + gcflags = GCFunction; + if (use_subwindow_mode_p (xgwa.screen, st->window)) /* see grabscreen.c */ + gcflags |= GCSubwindowMode; + st->gc = XCreateGC (st->dpy, st->window, gcflags, &gcv); + st->img_loader = load_image_async_simple (0, xgwa.screen, st->window, + st->window, 0, 0); + + st->buffer_map = 0; + +#ifdef HAVE_XSHM_EXTENSION + if (st->use_shm) { + st->buffer_map = create_xshm_image(st->dpy, xgwa.visual, depth, + ZPixmap, 0, &st->shm_info, st->width, st->height); + if (!st->buffer_map) { + st->use_shm = False; + fprintf(stderr, "create_xshm_image failed\n"); + } + } +#endif /* HAVE_XSHM_EXTENSION */ + + if (!st->buffer_map) { + st->buffer_map = XCreateImage(st->dpy, xgwa.visual, + depth, ZPixmap, 0, 0, st->width, st->height, 8, 0); + st->buffer_map->data = (char *)calloc (st->buffer_map->height, + st->buffer_map->bytes_per_line); + } +} + + +static void * +rotzoomer_init (Display *dpy, Window window) +{ + struct state *st = (struct state *) calloc (1, sizeof(*st)); + char *s; + st->dpy = dpy; + st->window = window; +#ifdef HAVE_XSHM_EXTENSION + st->use_shm = get_boolean_resource (st->dpy, "useSHM", "Boolean"); +#endif + st->num_zoom = get_integer_resource (st->dpy, "numboxes", "Integer"); + + s = get_string_resource (dpy, "mode", "Mode"); + if (!s || !*s || !strcasecmp (s, "stationary")) + ; + else if (!strcasecmp (s, "move")) + st->move = True; + else if (!strcasecmp (s, "sweep")) + st->sweep = True; + else + fprintf (stderr, "%s: bogus mode: \"%s\"\n", progname, s); + + st->anim = get_boolean_resource (st->dpy, "anim", "Boolean"); + st->delay = get_integer_resource (st->dpy, "delay", "Integer"); + st->duration = get_integer_resource (st->dpy, "duration", "Seconds"); + if (st->delay < 0) st->delay = 0; + if (st->duration < 1) st->duration = 1; + + /* In sweep or static mode, we want only one box */ + if (st->sweep || !st->anim) + st->num_zoom = 1; + + /* Can't have static sweep mode */ + if (!st->anim) + st->sweep = 0; + + st->start_time = time ((time_t) 0); + + setup_X (st); + + return st; +} + +static void +rotzoomer_reshape (Display *dpy, Window window, void *closure, + unsigned int w, unsigned int h) +{ +} + +static Bool +rotzoomer_event (Display *dpy, Window window, void *closure, XEvent *event) +{ + return False; +} + +static void +rotzoomer_free (Display *dpy, Window window, void *closure) +{ + struct state *st = (struct state *) closure; + free (st); +} + + +static const char *rotzoomer_defaults[] = { + ".background: black", + ".foreground: white", + "*fpsSolid: true", +#ifdef HAVE_XSHM_EXTENSION + "*useSHM: True", +#else + "*useSHM: False", +#endif + "*anim: True", + "*mode: stationary", + "*numboxes: 2", + "*delay: 10000", + "*duration: 120", + 0 +}; + + +static XrmOptionDescRec rotzoomer_options[] = { + { "-shm", ".useSHM", XrmoptionNoArg, "True" }, + { "-no-shm", ".useSHM", XrmoptionNoArg, "False" }, + { "-mode", ".mode", XrmoptionSepArg, 0 }, + { "-move", ".mode", XrmoptionNoArg, "move" }, + { "-sweep", ".mode", XrmoptionNoArg, "sweep" }, + { "-anim", ".anim", XrmoptionNoArg, "True" }, + { "-no-anim", ".anim", XrmoptionNoArg, "False" }, + { "-delay", ".delay", XrmoptionSepArg, 0 }, + {"-duration", ".duration", XrmoptionSepArg, 0 }, + { "-n", ".numboxes", XrmoptionSepArg, 0 }, + { 0, 0, 0, 0 } +}; + + +XSCREENSAVER_MODULE ("RotZoomer", rotzoomer) diff --git a/hacks/rotzoomer.man b/hacks/rotzoomer.man new file mode 100644 index 00000000..0a825509 --- /dev/null +++ b/hacks/rotzoomer.man @@ -0,0 +1,88 @@ +.TH XScreenSaver 1 "14-Mar-01" "X Version 11" +.SH NAME +rotzoomer - animated rotations and scalings of portions of the screen +.SH SYNOPSIS +.B rotzoomer +[\-display \fIhost:display.screen\fP] +[\-move | \-no\-move] +[\-delay \fImillisecs\fP] +[\-duration \fIsecs\fP] +[\-n \fIcount\fP] +[\-shm | \-no\-shm] +[\-window] [\-root] [\-install] [\-visual \fIvisual\fP] +[\-fps] +.SH DESCRIPTION +The \fIrotzoomer\fP program grabs an image, then picks +rectangles and draws scaled and rotated animations of that +section. + +The image that it manipulates will be grabbed from the portion of +the screen underlying the window, or from the system's video input, +or from a random file on disk, as indicated by +the \fIgrabDesktopImages\fP, \fIgrabVideoFrames\fP, +and \fIchooseRandomImages\fP options in the \fI~/.xscreensaver\fP +file; see +.BR xscreensaver-demo (1) +for more details. +.SH OPTIONS +.I rotzoomer +accepts the following options: +.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 \-install +Install a private colormap for the window. +.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 \-delay \fImilliseconds\fP +How much of a delay should be introduced between steps of the animation. +Default 10, or about 1/100th second. +.TP 8 +.B \-duration \fIseconds\fP +How long to run before loading a new image. Default 120 seconds. +.TP 8 +.B \-move +Make the rectangles should wander around the screen. +.TP 8 +.B \-no\-move +Make the rectangles be stationary. This is the default. +.TP 8 +.B \-n \fIcount\fP +How many rectangles to animate simultaneously. Default 2. +.TP 8 +.B \-no\-shm +Disable use of the SHM extension, even if it appears to be available. +.TP 8 +.B \-fps +Display the current frame rate and CPU load. +.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), +.BR xscreensaver\-demo (1), +.BR xscreensaver\-getimage (1) +.SH COPYRIGHT +Copyright \(co 2001 by Claudio Matsuoka. 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 +Claudio Matsuoka diff --git a/hacks/screenhack.c b/hacks/screenhack.c new file mode 100644 index 00000000..52344a35 --- /dev/null +++ b/hacks/screenhack.c @@ -0,0 +1,931 @@ +/* xscreensaver, Copyright (c) 1992-2012 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. + * + * And remember: X Windows is to graphics hacking as roman numerals are to + * the square root of pi. + */ + +/* This file contains simple code to open a window or draw on the root. + The idea being that, when writing a graphics hack, you can just link + with this .o to get all of the uninteresting junk out of the way. + + Create a few static global procedures and variables: + + static void *YOURNAME_init (Display *, Window); + + Return an opaque structure representing your drawing state. + + static unsigned long YOURNAME_draw (Display *, Window, void *closure); + + Draw one frame. + The `closure' arg is your drawing state, that you created in `init'. + Return the number of microseconds to wait until the next frame. + + This should return in some small fraction of a second. + Do not call `usleep' or loop excessively. For long loops, use a + finite state machine. + + static void YOURNAME_reshape (Display *, Window, void *closure, + unsigned int width, unsigned int height); + + Called when the size of the window changes with the new size. + + static Bool YOURNAME_event (Display *, Window, void *closure, + XEvent *event); + + Called when a keyboard or mouse event arrives. + Return True if you handle it in some way, False otherwise. + + static void YOURNAME_free (Display *, Window, void *closure); + + Called when you are done: free everything you've allocated, + including your private `state' structure. + + NOTE: this is called in windowed-mode when the user typed + 'q' or clicks on the window's close box; but when + xscreensaver terminates this screenhack, it does so by + killing the process with SIGSTOP. So this callback is + mostly useless. + + static char YOURNAME_defaults [] = { "...", "...", ... , 0 }; + + This variable is an array of strings, your default resources. + Null-terminate the list. + + static XrmOptionDescRec YOURNAME_options[] = { { ... }, ... { 0,0,0,0 } } + + This variable describes your command-line options. + Null-terminate the list. + + Finally , invoke the XSCREENSAVER_MODULE() macro to tie it all together. + + Additional caveats: + + - Make sure that all functions in your module are static (check this + by running "nm -g" on the .o file). + + - Do not use global variables: all such info must be stored in the + private `state' structure. + + - Do not use static function-local variables, either. Put it in `state'. + + Assume that there are N independent runs of this code going in the + same address space at the same time: they must not affect each other. + + - Don't forget to write an XML file to describe the user interface + of your screen saver module. See .../hacks/config/README for details. + */ + +#define DEBUG_PAIR + +#include +#include +#include +#include +#include +#include +#include + +#ifdef __sgi +# include /* for SgiUseSchemes() */ +#endif /* __sgi */ + +#ifdef HAVE_XMU +# ifndef VMS +# include +# else /* VMS */ +# include +# endif +#else +# include "xmu.h" +#endif + +#include "screenhackI.h" +#include "version.h" +#include "vroot.h" +#include "fps.h" + +#ifndef _XSCREENSAVER_VROOT_H_ +# error Error! You have an old version of vroot.h! Check -I args. +#endif /* _XSCREENSAVER_VROOT_H_ */ + +#ifndef isupper +# define isupper(c) ((c) >= 'A' && (c) <= 'Z') +#endif +#ifndef _tolower +# define _tolower(c) ((c) - 'A' + 'a') +#endif + + +/* This is defined by the SCREENHACK_MAIN() macro via screenhack.h. + */ +extern struct xscreensaver_function_table *xscreensaver_function_table; + + +const char *progname; /* used by hacks in error messages */ +const char *progclass; /* used by ../utils/resources.c */ +Bool mono_p; /* used by hacks */ + + +static XrmOptionDescRec default_options [] = { + { "-root", ".root", XrmoptionNoArg, "True" }, + { "-window", ".root", XrmoptionNoArg, "False" }, + { "-mono", ".mono", XrmoptionNoArg, "True" }, + { "-install", ".installColormap", XrmoptionNoArg, "True" }, + { "-noinstall",".installColormap", XrmoptionNoArg, "False" }, + { "-visual", ".visualID", XrmoptionSepArg, 0 }, + { "-window-id", ".windowID", XrmoptionSepArg, 0 }, + { "-fps", ".doFPS", XrmoptionNoArg, "True" }, + { "-no-fps", ".doFPS", XrmoptionNoArg, "False" }, + +# ifdef DEBUG_PAIR + { "-pair", ".pair", XrmoptionNoArg, "True" }, +# endif /* DEBUG_PAIR */ + { 0, 0, 0, 0 } +}; + +static char *default_defaults[] = { + ".root: false", + "*geometry: 600x480", /* this should be .geometry, but nooooo... */ + "*mono: false", + "*installColormap: false", + "*doFPS: false", + "*multiSample: false", + "*visualID: default", + "*windowID: ", + "*desktopGrabber: xscreensaver-getimage %s", + 0 +}; + +static XrmOptionDescRec *merged_options; +static int merged_options_size; +static char **merged_defaults; + + +static void +merge_options (void) +{ + struct xscreensaver_function_table *ft = xscreensaver_function_table; + + const XrmOptionDescRec *options = ft->options; + const char * const *defaults = ft->defaults; + const char *progclass = ft->progclass; + + int def_opts_size, opts_size; + int def_defaults_size, defaults_size; + + for (def_opts_size = 0; default_options[def_opts_size].option; + def_opts_size++) + ; + for (opts_size = 0; options[opts_size].option; opts_size++) + ; + + merged_options_size = def_opts_size + opts_size; + merged_options = (XrmOptionDescRec *) + malloc ((merged_options_size + 1) * sizeof(*default_options)); + memcpy (merged_options, default_options, + (def_opts_size * sizeof(*default_options))); + memcpy (merged_options + def_opts_size, options, + ((opts_size + 1) * sizeof(*default_options))); + + for (def_defaults_size = 0; default_defaults[def_defaults_size]; + def_defaults_size++) + ; + for (defaults_size = 0; defaults[defaults_size]; defaults_size++) + ; + merged_defaults = (char **) + malloc ((def_defaults_size + defaults_size + 1) * sizeof (*defaults));; + memcpy (merged_defaults, default_defaults, + def_defaults_size * sizeof(*defaults)); + memcpy (merged_defaults + def_defaults_size, defaults, + (defaults_size + 1) * sizeof(*defaults)); + + /* This totally sucks. Xt should behave like this by default. + If the string in `defaults' looks like ".foo", change that + to "Progclass.foo". + */ + { + char **s; + for (s = merged_defaults; *s; s++) + if (**s == '.') + { + const char *oldr = *s; + char *newr = (char *) malloc(strlen(oldr) + strlen(progclass) + 3); + strcpy (newr, progclass); + strcat (newr, oldr); + *s = newr; + } + else + *s = strdup (*s); + } +} + + +/* Make the X errors print out the name of this program, so we have some + clue which one has a bug when they die under the screensaver. + */ + +static int +screenhack_ehandler (Display *dpy, XErrorEvent *error) +{ + fprintf (stderr, "\nX error in %s:\n", progname); + if (XmuPrintDefaultErrorMessage (dpy, error, stderr)) + exit (-1); + else + fprintf (stderr, " (nonfatal.)\n"); + return 0; +} + +static Bool +MapNotify_event_p (Display *dpy, XEvent *event, XPointer window) +{ + return (event->xany.type == MapNotify && + event->xvisibility.window == (Window) window); +} + + +static Atom XA_WM_PROTOCOLS, XA_WM_DELETE_WINDOW; + +/* Dead-trivial event handling: exits if "q" or "ESC" are typed. + Exit if the WM_PROTOCOLS WM_DELETE_WINDOW ClientMessage is received. + Returns False if the screen saver should now terminate. + */ +static Bool +screenhack_handle_event_1 (Display *dpy, XEvent *event) +{ + switch (event->xany.type) + { + case KeyPress: + { + KeySym keysym; + char c = 0; + XLookupString (&event->xkey, &c, 1, &keysym, 0); + if (c == 'q' || + c == 'Q' || + c == 3 || /* ^C */ + c == 27) /* ESC */ + return False; /* exit */ + else if (! (keysym >= XK_Shift_L && keysym <= XK_Hyper_R)) + XBell (dpy, 0); /* beep for non-chord keys */ + } + break; + case ButtonPress: + XBell (dpy, 0); + break; + case ClientMessage: + { + if (event->xclient.message_type != XA_WM_PROTOCOLS) + { + char *s = XGetAtomName(dpy, event->xclient.message_type); + if (!s) s = "(null)"; + fprintf (stderr, "%s: unknown ClientMessage %s received!\n", + progname, s); + } + else if (event->xclient.data.l[0] != XA_WM_DELETE_WINDOW) + { + char *s1 = XGetAtomName(dpy, event->xclient.message_type); + char *s2 = XGetAtomName(dpy, event->xclient.data.l[0]); + if (!s1) s1 = "(null)"; + if (!s2) s2 = "(null)"; + fprintf (stderr, "%s: unknown ClientMessage %s[%s] received!\n", + progname, s1, s2); + } + else + { + return False; /* exit */ + } + } + break; + } + return True; +} + + +static Visual * +pick_visual (Screen *screen) +{ + struct xscreensaver_function_table *ft = xscreensaver_function_table; + + if (ft->pick_visual_hook) + { + Visual *v = ft->pick_visual_hook (screen); + if (v) return v; + } + + return get_visual_resource (screen, "visualID", "VisualID", False); +} + + +/* Notice when the user has requested a different visual or colormap + on a pre-existing window (e.g., "-root -visual truecolor" or + "-window-id 0x2c00001 -install") and complain, since when drawing + on an existing window, we have no choice about these things. + */ +static void +visual_warning (Screen *screen, Window window, Visual *visual, Colormap cmap, + Bool window_p) +{ + struct xscreensaver_function_table *ft = xscreensaver_function_table; + + char *visual_string = get_string_resource (DisplayOfScreen (screen), + "visualID", "VisualID"); + Visual *desired_visual = pick_visual (screen); + char win[100]; + char why[100]; + + if (window == RootWindowOfScreen (screen)) + strcpy (win, "root window"); + else + sprintf (win, "window 0x%lx", (unsigned long) window); + + if (window_p) + sprintf (why, "-window-id 0x%lx", (unsigned long) window); + else + strcpy (why, "-root"); + + if (visual_string && *visual_string) + { + char *s; + for (s = visual_string; *s; s++) + if (isupper (*s)) *s = _tolower (*s); + + if (!strcmp (visual_string, "default") || + !strcmp (visual_string, "default") || + !strcmp (visual_string, "best")) + /* don't warn about these, just silently DWIM. */ + ; + else if (visual != desired_visual) + { + fprintf (stderr, "%s: ignoring `-visual %s' because of `%s'.\n", + progname, visual_string, why); + fprintf (stderr, "%s: using %s's visual 0x%lx.\n", + progname, win, XVisualIDFromVisual (visual)); + } + free (visual_string); + } + + if (visual == DefaultVisualOfScreen (screen) && + has_writable_cells (screen, visual) && + get_boolean_resource (DisplayOfScreen (screen), + "installColormap", "InstallColormap")) + { + fprintf (stderr, "%s: ignoring `-install' because of `%s'.\n", + progname, why); + fprintf (stderr, "%s: using %s's colormap 0x%lx.\n", + progname, win, (unsigned long) cmap); + } + + if (ft->validate_visual_hook) + { + if (! ft->validate_visual_hook (screen, win, visual)) + exit (1); + } +} + + +static void +fix_fds (void) +{ + /* Bad Things Happen if stdin, stdout, and stderr have been closed + (as by the `sh incantation "attraction >&- 2>&-"). When you do + that, the X connection gets allocated to one of these fds, and + then some random library writes to stderr, and random bits get + stuffed down the X pipe, causing "Xlib: sequence lost" errors. + So, we cause the first three file descriptors to be open to + /dev/null if they aren't open to something else already. This + must be done before any other files are opened (or the closing + of that other file will again free up one of the "magic" first + three FDs.) + + We do this by opening /dev/null three times, and then closing + those fds, *unless* any of them got allocated as #0, #1, or #2, + in which case we leave them open. Gag. + + Really, this crap is technically required of *every* X program, + if you want it to be robust in the face of "2>&-". + */ + int fd0 = open ("/dev/null", O_RDWR); + int fd1 = open ("/dev/null", O_RDWR); + int fd2 = open ("/dev/null", O_RDWR); + if (fd0 > 2) close (fd0); + if (fd1 > 2) close (fd1); + if (fd2 > 2) close (fd2); +} + + +static Boolean +screenhack_table_handle_events (Display *dpy, + const struct xscreensaver_function_table *ft, + Window window, void *closure +#ifdef DEBUG_PAIR + , Window window2, void *closure2 +#endif + ) +{ + XtAppContext app = XtDisplayToApplicationContext (dpy); + + if (XtAppPending (app) & (XtIMTimer|XtIMAlternateInput)) + XtAppProcessEvent (app, XtIMTimer|XtIMAlternateInput); + + while (XPending (dpy)) + { + XEvent event; + XNextEvent (dpy, &event); + + if (event.xany.type == ConfigureNotify) + { + if (event.xany.window == window) + ft->reshape_cb (dpy, window, closure, + event.xconfigure.width, event.xconfigure.height); +#ifdef DEBUG_PAIR + if (window2 && event.xany.window == window2) + ft->reshape_cb (dpy, window2, closure2, + event.xconfigure.width, event.xconfigure.height); +#endif + } + else if (event.xany.type == ClientMessage || + (! (event.xany.window == window + ? ft->event_cb (dpy, window, closure, &event) +#ifdef DEBUG_PAIR + : (window2 && event.xany.window == window2) + ? ft->event_cb (dpy, window2, closure2, &event) +#endif + : 0))) + if (! screenhack_handle_event_1 (dpy, &event)) + return False; + + if (XtAppPending (app) & (XtIMTimer|XtIMAlternateInput)) + XtAppProcessEvent (app, XtIMTimer|XtIMAlternateInput); + } + return True; +} + + +static Boolean +usleep_and_process_events (Display *dpy, + const struct xscreensaver_function_table *ft, + Window window, fps_state *fpst, void *closure, + unsigned long delay +#ifdef DEBUG_PAIR + , Window window2, fps_state *fpst2, void *closure2, + unsigned long delay2 +#endif + ) +{ + do { + unsigned long quantum = 100000; /* 1/10th second */ + if (quantum > delay) + quantum = delay; + delay -= quantum; + + XSync (dpy, False); + if (quantum > 0) + { + usleep (quantum); + if (fpst) fps_slept (fpst, quantum); +#ifdef DEBUG_PAIR + if (fpst2) fps_slept (fpst2, quantum); +#endif + } + + if (! screenhack_table_handle_events (dpy, ft, window, closure +#ifdef DEBUG_PAIR + , window2, closure2 +#endif + )) + return False; + } while (delay > 0); + + return True; +} + + +static void +screenhack_do_fps (Display *dpy, Window w, fps_state *fpst, void *closure) +{ + fps_compute (fpst, 0, -1); + fps_draw (fpst); +} + + +static void +run_screenhack_table (Display *dpy, + Window window, +# ifdef DEBUG_PAIR + Window window2, +# endif + const struct xscreensaver_function_table *ft) +{ + + /* Kludge: even though the init_cb functions are declared to take 2 args, + actually call them with 3, for the benefit of xlockmore_init() and + xlockmore_setup(). + */ + void *(*init_cb) (Display *, Window, void *) = + (void *(*) (Display *, Window, void *)) ft->init_cb; + + void (*fps_cb) (Display *, Window, fps_state *, void *) = ft->fps_cb; + + void *closure = init_cb (dpy, window, ft->setup_arg); + fps_state *fpst = fps_init (dpy, window); + +#ifdef DEBUG_PAIR + void *closure2 = 0; + fps_state *fpst2 = 0; + if (window2) closure2 = init_cb (dpy, window2, ft->setup_arg); + if (window2) fpst2 = fps_init (dpy, window2); +#endif + + if (! closure) /* if it returns nothing, it can't possibly be re-entrant. */ + abort(); + + if (! fps_cb) fps_cb = screenhack_do_fps; + + while (1) + { + unsigned long delay = ft->draw_cb (dpy, window, closure); +#ifdef DEBUG_PAIR + unsigned long delay2 = 0; + if (window2) delay2 = ft->draw_cb (dpy, window2, closure2); +#endif + + if (fpst) fps_cb (dpy, window, fpst, closure); +#ifdef DEBUG_PAIR + if (fpst2) fps_cb (dpy, window, fpst2, closure); +#endif + + if (! usleep_and_process_events (dpy, ft, + window, fpst, closure, delay +#ifdef DEBUG_PAIR + , window2, fpst2, closure2, delay2 +#endif + )) + break; + } + + ft->free_cb (dpy, window, closure); + if (fpst) fps_free (fpst); + +#ifdef DEBUG_PAIR + if (window2) ft->free_cb (dpy, window2, closure2); + if (fpst2) fps_free (fpst2); +#endif +} + + +static Widget +make_shell (Screen *screen, Widget toplevel, int width, int height) +{ + Display *dpy = DisplayOfScreen (screen); + Visual *visual = pick_visual (screen); + Boolean def_visual_p = (toplevel && + visual == DefaultVisualOfScreen (screen)); + + if (width <= 0) width = 600; + if (height <= 0) height = 480; + + if (def_visual_p) + { + Window window; + XtVaSetValues (toplevel, + XtNmappedWhenManaged, False, + XtNwidth, width, + XtNheight, height, + XtNinput, True, /* for WM_HINTS */ + NULL); + XtRealizeWidget (toplevel); + window = XtWindow (toplevel); + + if (get_boolean_resource (dpy, "installColormap", "InstallColormap")) + { + Colormap cmap = + XCreateColormap (dpy, window, DefaultVisualOfScreen (screen), + AllocNone); + XSetWindowColormap (dpy, window, cmap); + } + } + else + { + unsigned int bg, bd; + Widget new; + Colormap cmap = XCreateColormap (dpy, VirtualRootWindowOfScreen(screen), + visual, AllocNone); + bg = get_pixel_resource (dpy, cmap, "background", "Background"); + bd = get_pixel_resource (dpy, cmap, "borderColor", "Foreground"); + + new = XtVaAppCreateShell (progname, progclass, + topLevelShellWidgetClass, dpy, + XtNmappedWhenManaged, False, + XtNvisual, visual, + XtNdepth, visual_depth (screen, visual), + XtNwidth, width, + XtNheight, height, + XtNcolormap, cmap, + XtNbackground, (Pixel) bg, + XtNborderColor, (Pixel) bd, + XtNinput, True, /* for WM_HINTS */ + NULL); + + if (!toplevel) /* kludge for the second window in -pair mode... */ + XtVaSetValues (new, XtNx, 0, XtNy, 550, NULL); + + XtRealizeWidget (new); + toplevel = new; + } + + return toplevel; +} + +static void +init_window (Display *dpy, Widget toplevel, const char *title) +{ + Window window; + XWindowAttributes xgwa; + XtPopup (toplevel, XtGrabNone); + XtVaSetValues (toplevel, XtNtitle, title, NULL); + + /* Select KeyPress, and announce that we accept WM_DELETE_WINDOW. + */ + window = XtWindow (toplevel); + XGetWindowAttributes (dpy, window, &xgwa); + XSelectInput (dpy, window, + (xgwa.your_event_mask | KeyPressMask | KeyReleaseMask | + ButtonPressMask | ButtonReleaseMask)); + XChangeProperty (dpy, window, XA_WM_PROTOCOLS, XA_ATOM, 32, + PropModeReplace, + (unsigned char *) &XA_WM_DELETE_WINDOW, 1); +} + + +int +main (int argc, char **argv) +{ + struct xscreensaver_function_table *ft = xscreensaver_function_table; + + XWindowAttributes xgwa; + Widget toplevel; + Display *dpy; + Window window; +# ifdef DEBUG_PAIR + Window window2 = 0; + Widget toplevel2 = 0; +# endif + XtAppContext app; + Bool root_p; + Window on_window = 0; + XEvent event; + Boolean dont_clear; + char version[255]; + + fix_fds(); + + progname = argv[0]; /* reset later */ + progclass = ft->progclass; + + if (ft->setup_cb) + ft->setup_cb (ft, ft->setup_arg); + + merge_options (); + +#ifdef __sgi + /* We have to do this on SGI to prevent the background color from being + overridden by the current desktop color scheme (we'd like our backgrounds + to be black, thanks.) This should be the same as setting the + "*useSchemes: none" resource, but it's not -- if that resource is + present in the `default_defaults' above, it doesn't work, though it + does work when passed as an -xrm arg on the command line. So screw it, + turn them off from C instead. + */ + SgiUseSchemes ("none"); +#endif /* __sgi */ + + toplevel = XtAppInitialize (&app, progclass, merged_options, + merged_options_size, &argc, argv, + merged_defaults, 0, 0); + + dpy = XtDisplay (toplevel); + + XtGetApplicationNameAndClass (dpy, + (char **) &progname, + (char **) &progclass); + + /* half-assed way of avoiding buffer-overrun attacks. */ + if (strlen (progname) >= 100) ((char *) progname)[100] = 0; + + XSetErrorHandler (screenhack_ehandler); + + XA_WM_PROTOCOLS = XInternAtom (dpy, "WM_PROTOCOLS", False); + XA_WM_DELETE_WINDOW = XInternAtom (dpy, "WM_DELETE_WINDOW", False); + + { + char *v = (char *) strdup(strchr(screensaver_id, ' ')); + char *s1, *s2, *s3, *s4; + s1 = (char *) strchr(v, ' '); s1++; + s2 = (char *) strchr(s1, ' '); + s3 = (char *) strchr(v, '('); s3++; + s4 = (char *) strchr(s3, ')'); + *s2 = 0; + *s4 = 0; + sprintf (version, "%s: from the XScreenSaver %s distribution (%s.)", + progclass, s1, s3); + free(v); + } + + if (argc > 1) + { + const char *s; + int i; + int x = 18; + int end = 78; + Bool help_p = (!strcmp(argv[1], "-help") || + !strcmp(argv[1], "--help")); + fprintf (stderr, "%s\n", version); + for (s = progclass; *s; s++) fprintf(stderr, " "); + fprintf (stderr, " http://www.jwz.org/xscreensaver/\n\n"); + + if (!help_p) + fprintf(stderr, "Unrecognised option: %s\n", argv[1]); + fprintf (stderr, "Options include: "); + for (i = 0; i < merged_options_size; i++) + { + char *sw = merged_options [i].option; + Bool argp = (merged_options [i].argKind == XrmoptionSepArg); + int size = strlen (sw) + (argp ? 6 : 0) + 2; + if (x + size >= end) + { + fprintf (stderr, "\n\t\t "); + x = 18; + } + x += size; + fprintf (stderr, "%s", sw); + if (argp) fprintf (stderr, " "); + if (i != merged_options_size - 1) fprintf (stderr, ", "); + } + + fprintf (stderr, ".\n"); + +#if 0 + if (help_p) + { + fprintf (stderr, "\nResources:\n\n"); + for (i = 0; i < merged_options_size; i++) + { + const char *opt = merged_options [i].option; + const char *res = merged_options [i].specifier + 1; + const char *val = merged_options [i].value; + char *s = get_string_resource (dpy, (char *) res, (char *) res); + + if (s) + { + int L = strlen(s); + while (L > 0 && (s[L-1] == ' ' || s[L-1] == '\t')) + s[--L] = 0; + } + + fprintf (stderr, " %-16s %-18s ", opt, res); + if (merged_options [i].argKind == XrmoptionSepArg) + { + fprintf (stderr, "[%s]", (s ? s : "?")); + } + else + { + fprintf (stderr, "%s", (val ? val : "(null)")); + if (val && s && !strcasecmp (val, s)) + fprintf (stderr, " [default]"); + } + fprintf (stderr, "\n"); + } + fprintf (stderr, "\n"); + } +#endif + + exit (help_p ? 0 : 1); + } + + { + char **s; + for (s = merged_defaults; *s; s++) + free(*s); + } + + free (merged_options); + free (merged_defaults); + merged_options = 0; + merged_defaults = 0; + + dont_clear = get_boolean_resource (dpy, "dontClearRoot", "Boolean"); + mono_p = get_boolean_resource (dpy, "mono", "Boolean"); + if (CellsOfScreen (DefaultScreenOfDisplay (dpy)) <= 2) + mono_p = True; + + root_p = get_boolean_resource (dpy, "root", "Boolean"); + + { + char *s = get_string_resource (dpy, "windowID", "WindowID"); + if (s && *s) + on_window = get_integer_resource (dpy, "windowID", "WindowID"); + if (s) free (s); + } + + if (on_window) + { + window = (Window) on_window; + XtDestroyWidget (toplevel); + XGetWindowAttributes (dpy, window, &xgwa); + visual_warning (xgwa.screen, window, xgwa.visual, xgwa.colormap, True); + + /* Select KeyPress and resize events on the external window. + */ + xgwa.your_event_mask |= KeyPressMask | StructureNotifyMask; + XSelectInput (dpy, window, xgwa.your_event_mask); + + /* Select ButtonPress and ButtonRelease events on the external window, + if no other app has already selected them (only one app can select + ButtonPress at a time: BadAccess results.) + */ + if (! (xgwa.all_event_masks & (ButtonPressMask | ButtonReleaseMask))) + XSelectInput (dpy, window, + (xgwa.your_event_mask | + ButtonPressMask | ButtonReleaseMask)); + } + else if (root_p) + { + window = VirtualRootWindowOfScreen (XtScreen (toplevel)); + XtDestroyWidget (toplevel); + XGetWindowAttributes (dpy, window, &xgwa); + /* With RANDR, the root window can resize! */ + XSelectInput (dpy, window, xgwa.your_event_mask | StructureNotifyMask); + visual_warning (xgwa.screen, window, xgwa.visual, xgwa.colormap, False); + } + else + { + Widget new = make_shell (XtScreen (toplevel), toplevel, + toplevel->core.width, + toplevel->core.height); + if (new != toplevel) + { + XtDestroyWidget (toplevel); + toplevel = new; + } + + init_window (dpy, toplevel, version); + window = XtWindow (toplevel); + XGetWindowAttributes (dpy, window, &xgwa); + +# ifdef DEBUG_PAIR + if (get_boolean_resource (dpy, "pair", "Boolean")) + { + toplevel2 = make_shell (xgwa.screen, 0, + toplevel->core.width, + toplevel->core.height); + init_window (dpy, toplevel2, version); + window2 = XtWindow (toplevel2); + } +# endif /* DEBUG_PAIR */ + } + + if (!dont_clear) + { + unsigned int bg = get_pixel_resource (dpy, xgwa.colormap, + "background", "Background"); + XSetWindowBackground (dpy, window, bg); + XClearWindow (dpy, window); +# ifdef DEBUG_PAIR + if (window2) + { + XSetWindowBackground (dpy, window2, bg); + XClearWindow (dpy, window2); + } +# endif + } + + if (!root_p && !on_window) + /* wait for it to be mapped */ + XIfEvent (dpy, &event, MapNotify_event_p, (XPointer) window); + + XSync (dpy, False); + + /* This is the one and only place that the random-number generator is + seeded in any screenhack. You do not need to seed the RNG again, + it is done for you before your code is invoked. */ +# undef ya_rand_init + ya_rand_init (0); + + run_screenhack_table (dpy, window, +# ifdef DEBUG_PAIR + window2, +# endif + ft); + + XtDestroyWidget (toplevel); + XtDestroyApplicationContext (app); + + return 0; +} diff --git a/hacks/screenhack.h b/hacks/screenhack.h new file mode 100644 index 00000000..1f9a561d --- /dev/null +++ b/hacks/screenhack.h @@ -0,0 +1,61 @@ +/* xscreensaver, Copyright (c) 1992-2008 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. + */ + +#ifndef __SCREENHACK_H__ +#define __SCREENHACK_H__ + +#include "screenhackI.h" + +/* In an Xlib world, we define two global symbols here: + a struct in `MODULENAME_xscreensaver_function_table', + and a pointer to that in `xscreensaver_function_table'. + + In a Cocoa world, we only define the prefixed symbol; + the un-prefixed symbol does not exist. + */ +#ifdef HAVE_COCOA +# define XSCREENSAVER_LINK(NAME) +#else +# define XSCREENSAVER_LINK(NAME) \ + struct xscreensaver_function_table *xscreensaver_function_table = &NAME; +#endif + + +#if defined(HAVE_COCOA) && !defined(__XLOCKMORE_INTERNAL_H__) + /* this is one enormous kludge... */ +# undef ya_rand_init + static void + xscreensaver_common_setup(struct xscreensaver_function_table *xsft, void *a) + { ya_rand_init(0); } +#else +# define xscreensaver_common_setup 0 +#endif + + +#define XSCREENSAVER_MODULE_2(CLASS,NAME,PREFIX) \ + struct xscreensaver_function_table \ + NAME ## _xscreensaver_function_table = { \ + CLASS, \ + PREFIX ## _defaults, \ + PREFIX ## _options, \ + xscreensaver_common_setup, 0, \ + PREFIX ## _init, \ + PREFIX ## _draw, \ + PREFIX ## _reshape, \ + PREFIX ## _event, \ + PREFIX ## _free, \ + 0, 0, 0 }; \ + XSCREENSAVER_LINK (NAME ## _xscreensaver_function_table) + +#define XSCREENSAVER_MODULE(CLASS,PREFIX) \ + XSCREENSAVER_MODULE_2(CLASS,PREFIX,PREFIX) + +#endif /* __SCREENHACK_H__ */ diff --git a/hacks/screenhackI.h b/hacks/screenhackI.h new file mode 100644 index 00000000..f25e7ab5 --- /dev/null +++ b/hacks/screenhackI.h @@ -0,0 +1,138 @@ +/* xscreensaver, Copyright (c) 1992-2008 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. + */ + +/* Found in Don Hopkins' .plan file: + * + * The color situation is a total flying circus. The X approach to + * device independence is to treat everything like a MicroVax framebuffer + * on acid. A truely portable X application is required to act like the + * persistent customer in the Monty Python ``Cheese Shop'' sketch. Even + * the simplest applications must answer many difficult questions, like: + * + * WHAT IS YOUR DISPLAY? + * display = XOpenDisplay("unix:0"); + * WHAT IS YOUR ROOT? + * root = RootWindow(display, DefaultScreen(display)); + * AND WHAT IS YOUR WINDOW? + * win = XCreateSimpleWindow(display, root, 0, 0, 256, 256, 1, + * BlackPixel(display, DefaultScreen(display)), + * WhitePixel(display, DefaultScreen(display))) + * OH ALL RIGHT, YOU CAN GO ON. + * + * WHAT IS YOUR DISPLAY? + * display = XOpenDisplay("unix:0"); + * WHAT IS YOUR COLORMAP? + * cmap = DefaultColormap(display, DefaultScreen(display)); + * AND WHAT IS YOUR FAVORITE COLOR? + * favorite_color = 0; / * Black. * / + * / * Whoops! No, I mean: * / + * favorite_color = BlackPixel(display, DefaultScreen(display)); + * / * AAAYYYYEEEEE!! (client dumps core & falls into the chasm) * / + * + * WHAT IS YOUR DISPLAY? + * display = XOpenDisplay("unix:0"); + * WHAT IS YOUR VISUAL? + * struct XVisualInfo vinfo; + * if (XMatchVisualInfo(display, DefaultScreen(display), + * 8, PseudoColor, &vinfo) != 0) + * visual = vinfo.visual; + * AND WHAT IS THE NET SPEED VELOCITY OF AN XConfigureWindow REQUEST? + * / * Is that a SubStructureRedirectMask or a ResizeRedirectMask? * / + * WHAT?! HOW AM I SUPPOSED TO KNOW THAT? + * AAAAUUUGGGHHH!!!! (server dumps core & falls into the chasm) + */ + +#ifndef __SCREENHACK_I_H__ +#define __SCREENHACK_I_H__ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif /* HAVE_CONFIG_H */ + +#include +#include +#include + +#ifdef __hpux + /* Which of the ten billion standards does values.h belong to? + What systems always have it? */ +# include +#endif + +#ifdef HAVE_COCOA +# include "jwxyz.h" +#else /* !HAVE_COCOA -- real X11 */ +# include +# include +# include +# include +#endif /* !HAVE_COCOA */ + +/* M_PI ought to have been defined in math.h, but... */ +#ifndef M_PI +# define M_PI 3.1415926535 +#endif + +#ifndef M_PI_2 +# define M_PI_2 1.5707963267 +#endif + +#ifndef Button6 +# define Button6 6 +# define Button7 7 +#endif + +#include "yarandom.h" +#include "usleep.h" +#include "resources.h" +#include "hsv.h" +#include "colors.h" +#include "grabscreen.h" +#include "visual.h" +#include "fps.h" + +/* Be Posixly correct */ +#undef bzero +#define bzero __ERROR_use_memset_not_bzero_in_xscreensaver__ +#undef bcopy +#define bcopy __ERROR_use_memcpy_not_bcopy_in_xscreensaver__ +#undef ftime +#define ftime __ERROR_use_gettimeofday_not_ftime_in_xscreensaver__ +#undef sleep +#define sleep __ERROR_do_not_sleep_in_xscreensaver__ + +extern Bool mono_p; + +struct xscreensaver_function_table { + + const char *progclass; + const char * const *defaults; + const XrmOptionDescRec *options; + + void (*setup_cb) (struct xscreensaver_function_table *, void *); + void * setup_arg; + + void * (*init_cb) (Display *, Window); + unsigned long (*draw_cb) (Display *, Window, void *); + void (*reshape_cb) (Display *, Window, void *, + unsigned int w, unsigned int h); + Bool (*event_cb) (Display *, Window, void *, XEvent *); + void (*free_cb) (Display *, Window, void *); + void (*fps_cb) (Display *, Window, fps_state *, void *); + + Visual * (*pick_visual_hook) (Screen *); + Bool (*validate_visual_hook) (Screen *, const char *, Visual *); + +}; + +extern const char *progname; + +#endif /* __SCREENHACK_I_H__ */ diff --git a/hacks/shadebobs.c b/hacks/shadebobs.c new file mode 100644 index 00000000..881740c9 --- /dev/null +++ b/hacks/shadebobs.c @@ -0,0 +1,465 @@ +/* shadebobs, Copyright (c) 1999 Shane Smit + * + * 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. + * + * Module - "shadebobs.c" + * + * Description: + * There are two little shading circles (bobs) that zip around the screen. + * one of them shades up towards white, and the other shades down toward + * black. + * This keeps the screen in color balance at a chosen color. + * + * Its kinda like 'The Force' + * There is a light side, a dark side, and it keeps the world in balance. + * + * [05/23/99] - Shane Smit: Creation + * [05/26/99] - Shane Smit: Port to C/screenhack for use with XScreenSaver + * [06/11/99] - Shane Smit: Stopped trying to rape the palette. + * [06/20/99] - jwz: cleaned up ximage handling, gave resoources short names, + * introduced delay, made it restart after N iterations. + * [06/21/99] - Shane Smit: Modified default values slightly, color changes + * on cycle, and the extents of the sinus pattern change in + * real-time. + * [06/22/99] - Shane Smit: Fixed delay to be fast and use little CPU :). + * [09/17/99] - Shane Smit: Made all calculations based on the size of the + * window. Thus, it'll look the same at 100x100 as it does at + * 1600x1200 ( Only smaller :). + * [04/24/00] - Shane Smit: Revamped entire source code: + * Shade Bob movement is calculated very differently. + * Base color can be any color now. + */ + + +#include +#include "screenhack.h" + +/* #define VERBOSE */ + +static const char *shadebobs_defaults [] = { + ".background: black", + ".foreground: white", + "*fpsSolid: true", + "*degrees: 0", /* default: Automatic degree calculation */ + "*color: random", + "*count: 4", + "*cycles: 10", + "*ncolors: 64", /* changing this doesn't work particularly well */ + "*delay: 10000", + 0 +}; + +static XrmOptionDescRec shadebobs_options [] = { + { "-degrees", ".degrees", XrmoptionSepArg, 0 }, + { "-color", ".color", XrmoptionSepArg, 0 }, + { "-ncolors", ".ncolors", XrmoptionSepArg, 0 }, + { "-count", ".count", XrmoptionSepArg, 0 }, + { "-delay", ".delay", XrmoptionSepArg, 0 }, + { "-cycles", ".cycles", XrmoptionSepArg, 0 }, + { 0, 0, 0, 0 } +}; + +/* Ahem. Chocolate is a flavor; not a food. Thank you */ + + +typedef struct +{ + signed char *anDeltaMap; + double nAngle, nAngleDelta, nAngleInc; + double nPosX, nPosY; +} SShadeBob; + +struct state { + Display *dpy; + Window window; + unsigned short iDegreeCount; + double *anSinTable, *anCosTable; + unsigned short iWinWidth, iWinHeight; + unsigned short iWinCenterX, iWinCenterY; + char *sColor; + unsigned char iBobRadius, iBobDiameter; + unsigned char iVelocity; + + unsigned long *aiColorVals; + signed short iColorCount; + int cycles; + XImage *pImage; + unsigned char nShadeBobCount, iShadeBob; + SShadeBob *aShadeBobs; + GC gc; + int delay; + int draw_i; +}; + +#define RANDOM() ((int) (random() & 0X7FFFFFFFL)) + + + +static void ResetShadeBob( struct state *st, SShadeBob *pShadeBob ) +{ + pShadeBob->nPosX = RANDOM() % st->iWinWidth; + pShadeBob->nPosY = RANDOM() % st->iWinHeight; + pShadeBob->nAngle = RANDOM() % st->iDegreeCount; + pShadeBob->nAngleDelta = ( RANDOM() % st->iDegreeCount ) - ( st->iDegreeCount / 2.0F ); + pShadeBob->nAngleInc = pShadeBob->nAngleDelta / 50.0F; + if( pShadeBob->nAngleInc == 0.0F ) + pShadeBob->nAngleInc = ( pShadeBob->nAngleDelta > 0.0F ) ? 0.0001F : -0.0001F; +} + + +static void InitShadeBob( struct state *st, SShadeBob *pShadeBob, Bool bDark ) +{ + double nDelta; + int iWidth, iHeight; + + if( ( pShadeBob->anDeltaMap = calloc( st->iBobDiameter * st->iBobDiameter, sizeof(char) ) ) == NULL ) + { + fprintf( stderr, "%s: Could not allocate Delta Map!\n", progname ); + return; + } + + for( iHeight=-st->iBobRadius; iHeightiBobRadius; iHeight++ ) + for( iWidth=-st->iBobRadius; iWidthiBobRadius; iWidth++ ) + { + nDelta = 9 - ( ( sqrt( pow( iWidth+0.5, 2 ) + pow( iHeight+0.5, 2 ) ) / st->iBobRadius ) * 8 ); + if( nDelta < 0 ) nDelta = 0; + if( bDark ) nDelta = -nDelta; + pShadeBob->anDeltaMap[ ( iWidth + st->iBobRadius ) * st->iBobDiameter + iHeight + st->iBobRadius ] = (char)nDelta; + } + + ResetShadeBob( st, pShadeBob ); +} + + +/* A delta is calculated, and the shadebob turns at an increment. When the delta + * falls to 0, a new delta and increment are calculated. */ +static void MoveShadeBob( struct state *st, SShadeBob *pShadeBob ) +{ + pShadeBob->nAngle += pShadeBob->nAngleInc; + pShadeBob->nAngleDelta -= pShadeBob->nAngleInc; + + if( pShadeBob->nAngle >= st->iDegreeCount ) pShadeBob->nAngle -= st->iDegreeCount; + else if( pShadeBob->nAngle < 0 ) pShadeBob->nAngle += st->iDegreeCount; + + if( ( pShadeBob->nAngleInc>0.0F && pShadeBob->nAngleDeltanAngleInc ) || + ( pShadeBob->nAngleInc<=0.0F && pShadeBob->nAngleDelta>pShadeBob->nAngleInc ) ) + { + pShadeBob->nAngleDelta = ( RANDOM() % st->iDegreeCount ) - ( st->iDegreeCount / 2.0F ); + pShadeBob->nAngleInc = pShadeBob->nAngleDelta / 50.0F; + if( pShadeBob->nAngleInc == 0.0F ) + pShadeBob->nAngleInc = ( pShadeBob->nAngleDelta > 0.0F ) ? 0.0001F : -0.0001F; + } + + pShadeBob->nPosX = ( st->anSinTable[ (int)pShadeBob->nAngle ] * st->iVelocity ) + pShadeBob->nPosX; + pShadeBob->nPosY = ( st->anCosTable[ (int)pShadeBob->nAngle ] * st->iVelocity ) + pShadeBob->nPosY; + + /* This wraps it around the screen. */ + if( pShadeBob->nPosX >= st->iWinWidth ) pShadeBob->nPosX -= st->iWinWidth; + else if( pShadeBob->nPosX < 0 ) pShadeBob->nPosX += st->iWinWidth; + + if( pShadeBob->nPosY >= st->iWinHeight ) pShadeBob->nPosY -= st->iWinHeight; + else if( pShadeBob->nPosY < 0 ) pShadeBob->nPosY += st->iWinHeight; +} + + +static void Execute( struct state *st, SShadeBob *pShadeBob ) +{ + unsigned long iColor; + short iColorVal; + int iPixelX, iPixelY; + unsigned int iWidth, iHeight; + + MoveShadeBob( st, pShadeBob ); + + for( iHeight=0; iHeightiBobDiameter; iHeight++ ) + { + iPixelY = pShadeBob->nPosY + iHeight; + if( iPixelY >= st->iWinHeight ) iPixelY -= st->iWinHeight; + + for( iWidth=0; iWidthiBobDiameter; iWidth++ ) + { + iPixelX = pShadeBob->nPosX + iWidth; + if( iPixelX >= st->iWinWidth ) iPixelX -= st->iWinWidth; + + iColor = XGetPixel( st->pImage, iPixelX, iPixelY ); + + /* FIXME: Here is a loop I'd love to take out. */ + for( iColorVal=0; iColorValiColorCount; iColorVal++ ) + if( st->aiColorVals[ iColorVal ] == iColor ) + break; + + iColorVal += pShadeBob->anDeltaMap[ iWidth * st->iBobDiameter + iHeight ]; + if( iColorVal >= st->iColorCount ) iColorVal = st->iColorCount - 1; + if( iColorVal < 0 ) iColorVal = 0; + + XPutPixel( st->pImage, iPixelX, iPixelY, st->aiColorVals[ iColorVal ] ); + } + } + + /* FIXME: if it's next to the top or left sides of screen this will break. However, it's not noticable. */ + XPutImage( st->dpy, st->window, st->gc, st->pImage, + pShadeBob->nPosX, pShadeBob->nPosY, pShadeBob->nPosX, pShadeBob->nPosY, st->iBobDiameter, st->iBobDiameter ); +} + + +static void CreateTables( struct state *st, unsigned int nDegrees ) +{ + double nRadian; + unsigned int iDegree; + st->anSinTable = calloc( nDegrees, sizeof(double) ); + st->anCosTable = calloc( nDegrees, sizeof(double) ); + + for( iDegree=0; iDegreeanSinTable[ iDegree ] = sin( nRadian ); + st->anCosTable[ iDegree ] = cos( nRadian ); + } +} + + +static unsigned long * SetPalette(struct state *st ) +{ + XWindowAttributes XWinAttribs; + XColor Color, *aColors; + signed short iColor; + float nHalfColors; + + XGetWindowAttributes( st->dpy, st->window, &XWinAttribs ); + + Color.red = RANDOM() % 0xFFFF; + Color.green = RANDOM() % 0xFFFF; + Color.blue = RANDOM() % 0xFFFF; + + if( strcasecmp( st->sColor, "random" ) && !XParseColor( st->dpy, XWinAttribs.colormap, st->sColor, &Color ) ) + fprintf( stderr, "%s: color %s not found in database. Choosing to random...\n", progname, st->sColor ); + +#ifdef VERBOSE + printf( "%s: Base color (RGB): <%d, %d, %d>\n", progname, Color.red, Color.green, Color.blue ); +#endif /* VERBOSE */ + + st->iColorCount = get_integer_resource(st->dpy, "ncolors", "Integer" ); + if( st->iColorCount < 2 ) st->iColorCount = 2; + if( st->iColorCount > 255 ) st->iColorCount = 255; + + aColors = calloc( st->iColorCount, sizeof(XColor) ); + st->aiColorVals = calloc( st->iColorCount, sizeof(unsigned long) ); + + for( iColor=0; iColoriColorCount; iColor++ ) + { + nHalfColors = st->iColorCount / 2.0F; + /* Black -> Base Color */ + if( iColor < (st->iColorCount/2) ) + { + aColors[ iColor ].red = ( Color.red / nHalfColors ) * iColor; + aColors[ iColor ].green = ( Color.green / nHalfColors ) * iColor; + aColors[ iColor ].blue = ( Color.blue / nHalfColors ) * iColor; + } + /* Base Color -> White */ + else + { + aColors[ iColor ].red = ( ( ( 0xFFFF - Color.red ) / nHalfColors ) * ( iColor - nHalfColors ) ) + Color.red; + aColors[ iColor ].green = ( ( ( 0xFFFF - Color.green ) / nHalfColors ) * ( iColor - nHalfColors ) ) + Color.green; + aColors[ iColor ].blue = ( ( ( 0xFFFF - Color.blue ) / nHalfColors ) * ( iColor - nHalfColors ) ) + Color.blue; + } + + if( !XAllocColor( st->dpy, XWinAttribs.colormap, &aColors[ iColor ] ) ) + { + /* start all over with less colors */ + XFreeColors( st->dpy, XWinAttribs.colormap, st->aiColorVals, iColor, 0 ); + free( aColors ); + free( st->aiColorVals ); + st->iColorCount--; + aColors = calloc( st->iColorCount, sizeof(XColor) ); + st->aiColorVals = calloc( st->iColorCount, sizeof(unsigned long) ); + iColor = -1; + } + else + st->aiColorVals[ iColor ] = aColors[ iColor ].pixel; + } + + free( aColors ); + + XSetWindowBackground( st->dpy, st->window, st->aiColorVals[ 0 ] ); + + return st->aiColorVals; +} + + +static void Initialize( struct state *st ) +{ + XGCValues gcValues; + XWindowAttributes XWinAttribs; + /*int iBitsPerPixel;*/ + + /* Create the Image for drawing */ + XGetWindowAttributes( st->dpy, st->window, &XWinAttribs ); + +#if 0 + /* Find the preferred bits-per-pixel. (jwz) */ + { + int i, pfvc = 0; + XPixmapFormatValues *pfv = XListPixmapFormats( st->dpy, &pfvc ); + for( i=0; igc = XCreateGC( st->dpy, st->window, 0, &gcValues ); + + st->pImage = XCreateImage( st->dpy, XWinAttribs.visual, XWinAttribs.depth, ZPixmap, 0, NULL, + XWinAttribs.width, XWinAttribs.height, 8 /*BitmapPad( st->dpy )*/, 0 ); + st->pImage->data = calloc((st->pImage)->bytes_per_line, (st->pImage)->height); + + st->iWinWidth = XWinAttribs.width; + st->iWinHeight = XWinAttribs.height; + + /* These are precalculations used in Execute(). */ + st->iBobDiameter = ( ( st->iWinWidth < st->iWinHeight ) ? st->iWinWidth : st->iWinHeight ) / 25; + st->iBobRadius = st->iBobDiameter / 2; +#ifdef VERBOSE + printf( "%s: Bob Diameter = %d\n", progname, st->iBobDiameter ); +#endif + + st->iWinCenterX = ( XWinAttribs.width / 2 ) - st->iBobRadius; + st->iWinCenterY = ( XWinAttribs.height / 2 ) - st->iBobRadius; + + st->iVelocity = ( ( st->iWinWidth < st->iWinHeight ) ? st->iWinWidth : st->iWinHeight ) / 150; + + /* Create the Sin and Cosine lookup tables. */ + st->iDegreeCount = get_integer_resource(st->dpy, "degrees", "Integer" ); + if( st->iDegreeCount == 0 ) st->iDegreeCount = ( XWinAttribs.width / 6 ) + 400; + else if( st->iDegreeCount < 90 ) st->iDegreeCount = 90; + else if( st->iDegreeCount > 5400 ) st->iDegreeCount = 5400; + CreateTables( st, st->iDegreeCount ); +#ifdef VERBOSE + printf( "%s: Using a %d degree circle.\n", progname, st->iDegreeCount ); +#endif /* VERBOSE */ + + /* Get the base color. */ + st->sColor = get_string_resource(st->dpy, "color", "Color" ); +} + + +static void * +shadebobs_init (Display *dpy, Window window) +{ + struct state *st = (struct state *) calloc (1, sizeof(*st)); + +#ifdef VERBOSE + time_t nTime = time( NULL ); + unsigned short iFrame = 0; +#endif /* VERBOSE */ + + st->dpy = dpy; + st->window = window; + + st->nShadeBobCount = get_integer_resource(st->dpy, "count", "Integer" ); + if( st->nShadeBobCount > 64 ) st->nShadeBobCount = 64; + if( st->nShadeBobCount < 1 ) st->nShadeBobCount = 1; + + if( ( st->aShadeBobs = calloc( st->nShadeBobCount, sizeof(SShadeBob) ) ) == NULL ) + { + fprintf( stderr, "%s: Could not allocate %d ShadeBobs\n", progname, st->nShadeBobCount ); + abort(); + } +#ifdef VERBOSE + printf( "%s: Allocated %d ShadeBobs\n", progname, st->nShadeBobCount ); +#endif /* VERBOSE */ + + Initialize( st ); + + for( st->iShadeBob=0; st->iShadeBobnShadeBobCount; st->iShadeBob++ ) + InitShadeBob( st, &st->aShadeBobs[ st->iShadeBob ], st->iShadeBob % 2 ); + + st->delay = get_integer_resource(st->dpy, "delay", "Integer" ); + st->cycles = get_integer_resource(st->dpy, "cycles", "Integer" ) * st->iDegreeCount; + + st->draw_i = 99999999; + return st; +} + +static unsigned long +shadebobs_draw (Display *dpy, Window window, void *closure) +{ + struct state *st = (struct state *) closure; + + if( st->draw_i++ >= st->cycles ) + { + XWindowAttributes XWinAttribs; + XGetWindowAttributes( st->dpy, st->window, &XWinAttribs ); + + st->draw_i = 0; +#if 0 + memset( st->pImage->data, 0, st->pImage->bytes_per_line * st->pImage->height ); +#else + { + /* fill the image with the actual value of the black pixel, not 0. */ + unsigned long black = BlackPixelOfScreen (XWinAttribs.screen); + int x, y; + for (y = 0; y < XWinAttribs.height; y++) + for (x = 0; x < XWinAttribs.width; x++) + XPutPixel (st->pImage, x, y, black); + } +#endif + + for( st->iShadeBob=0; st->iShadeBobnShadeBobCount; st->iShadeBob++ ) + ResetShadeBob( st, &st->aShadeBobs[ st->iShadeBob ] ); + XFreeColors( st->dpy, XWinAttribs.colormap, st->aiColorVals, st->iColorCount, 0 ); + free( st->aiColorVals ); + st->aiColorVals = SetPalette( st ); + XClearWindow( st->dpy, st->window ); + } + + for( st->iShadeBob=0; st->iShadeBobnShadeBobCount; st->iShadeBob++ ) + Execute( st, &st->aShadeBobs[ st->iShadeBob ] ); + + return st->delay; +} + +static void +shadebobs_reshape (Display *dpy, Window window, void *closure, + unsigned int w, unsigned int h) +{ +} + +static Bool +shadebobs_event (Display *dpy, Window window, void *closure, XEvent *event) +{ + return False; +} + +static void +shadebobs_free (Display *dpy, Window window, void *closure) +{ + struct state *st = (struct state *) closure; + free( st->anSinTable ); + free( st->anCosTable ); + /* free( st->pImage->data ); */ + XDestroyImage( st->pImage ); + for( st->iShadeBob=0; st->iShadeBobnShadeBobCount; st->iShadeBob++ ) + free( st->aShadeBobs[ st->iShadeBob ].anDeltaMap ); + free( st->aShadeBobs ); + free( st->aiColorVals ); +} + + +XSCREENSAVER_MODULE ("ShadeBobs", shadebobs) + +/* End of Module - "shadebobs.c" */ + +/* vim: ts=4 + */ diff --git a/hacks/shadebobs.man b/hacks/shadebobs.man new file mode 100644 index 00000000..e98905eb --- /dev/null +++ b/hacks/shadebobs.man @@ -0,0 +1,65 @@ +.TH XScreenSaver 1 "" "X Version 11" +.SH NAME +shadebobs - oscillating vapor trails. +.SH SYNOPSIS +.B shadebobs +[\-display \fIhost:display.screen\fP] +[\-visual \fIvisual\fP] +[\-window] +[\-root] +[\-ncolors \fInumber\fP] +[\-count \fInumber\fP] +[\-delay \fInumber\fP] +[\-cycles \fInumber\fP] +[\-fps] +.SH DESCRIPTION +This draws smoothly-shaded oscillating oval patterns, that look something +like vapor trails or neon tubes. +.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 \-ncolors \fInumber\fP +Number of Colors. Default: 64. +.TP 8 +.B \-count \fInumber\fP +Count. 0 - 20. Default: 4. +.TP 8 +.B \-delay \fInumber\fP +Per-frame delay, in microseconds. Default: 5000 (0.005 seconds.). +.TP 8 +.B \-cycles \fInumber\fP +Duration. 0 - 100. Default: 10. +.TP 8 +.B \-fps +Display the current frame rate and CPU load. +.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 2002 by Shane Smit. 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 +Shane Smit. diff --git a/hacks/sierpinski.c b/hacks/sierpinski.c new file mode 100644 index 00000000..5e7eedae --- /dev/null +++ b/hacks/sierpinski.c @@ -0,0 +1,230 @@ +/* -*- Mode: C; tab-width: 4 -*- */ +/* sierpinski --- Sierpinski's triangle fractal */ + +#if 0 +static const char sccsid[] = "@(#)sierpinski.c 5.00 2000/11/01 xlockmore"; +#endif + +/*- + * Copyright (c) 1996 by Desmond Daignault + * + * Permission to use, copy, modify, and distribute this software and its + * documentation for any purpose and without fee is hereby granted, + * provided that the above copyright notice appear in all copies and that + * both that copyright notice and this permission notice appear in + * supporting documentation. + * + * This file is provided AS IS with no warranties of any kind. The author + * shall have no liability with respect to the infringement of copyrights, + * trade secrets or any patents by this file or any part thereof. In no + * event will the author be liable for any lost revenue or profits or + * other special, indirect and consequential damages. + * + * Dots initially appear where they "should not". Later they get + * "focused". This is correct behavior. + * + * Revision History: + * 01-Nov-2000: Allocation checks + * 18-Sep-1997: 3D version Antti Kuntsi . + * 20-May-1997: Changed the name tri to sierpinski for more compatiblity + * 10-May-1997: Jamie Zawinski compatible with xscreensaver + * 05-Sep-1996: Desmond Daignault Datatimes Incorporated + * . + */ + +#ifdef STANDALONE +# define MODE_sierpinski +# define DEFAULTS "*delay: 400000 \n" \ + "*count: 2000 \n" \ + "*cycles: 100 \n" \ + "*ncolors: 64 \n" \ + "*fpsSolid: true \n" \ + +# define BRIGHT_COLORS +# define sierpinski_handle_event 0 +# include "xlockmore.h" /* in xscreensaver distribution */ +#else /* STANDALONE */ +# include "xlock.h" /* in xlockmore distribution */ +#endif /* STANDALONE */ + +#ifdef MODE_sierpinski + +ENTRYPOINT ModeSpecOpt sierpinski_opts = +{0, (XrmOptionDescRec *) NULL, 0, (argtype *) NULL, (OptionStruct *) NULL}; + +#ifdef USE_MODULES +ModStruct sierpinski_description = +{"sierpinski", "init_sierpinski", "draw_sierpinski", "release_sierpinski", + "refresh_sierpinski", "init_sierpinski", (char *) NULL, &sierpinski_opts, + 400000, 2000, 100, 1, 64, 1.0, "", + "Shows Sierpinski's triangle", 0, NULL}; + +#endif + +#define MAXCORNERS 4 + +typedef struct { + int width, height; + int time; + int px, py; + int total_npoints; + int corners; + int npoints[MAXCORNERS]; + unsigned long colors[MAXCORNERS]; + XPoint *pointBuffer[MAXCORNERS]; + XPoint vertex[MAXCORNERS]; +} sierpinskistruct; + +static sierpinskistruct *tris = (sierpinskistruct *) NULL; + +static void +startover(ModeInfo * mi) +{ + int j; + sierpinskistruct *sp = &tris[MI_SCREEN(mi)]; + + if (MI_NPIXELS(mi) > 2) { + if (sp->corners == 3) { + sp->colors[0] = (NRAND(MI_NPIXELS(mi))); + sp->colors[1] = (sp->colors[0] + MI_NPIXELS(mi) / 7 + + NRAND(2 * MI_NPIXELS(mi) / 7 + 1)) % MI_NPIXELS(mi); + sp->colors[2] = (sp->colors[0] + 4 * MI_NPIXELS(mi) / 7 + + NRAND(2 * MI_NPIXELS(mi) / 7 + 1)) % MI_NPIXELS(mi); + } else if (sp->corners == 4) { + sp->colors[0] = (NRAND(MI_NPIXELS(mi))); + sp->colors[1] = (sp->colors[0] + MI_NPIXELS(mi) / 7 + + NRAND(MI_NPIXELS(mi) / 7 + 1)) % MI_NPIXELS(mi); + sp->colors[2] = (sp->colors[0] + 3 * MI_NPIXELS(mi) / 7 + + NRAND(MI_NPIXELS(mi) / 7 + 1)) % MI_NPIXELS(mi); + sp->colors[3] = (sp->colors[0] + 5 * MI_NPIXELS(mi) / 7 + + NRAND(MI_NPIXELS(mi) / 7 + 1)) % MI_NPIXELS(mi); + } else { + (void) fprintf(stderr, "colors not set for %d corners\n", sp->corners); + } + } + for (j = 0; j < sp->corners; j++) { + sp->vertex[j].x = NRAND(sp->width); + sp->vertex[j].y = NRAND(sp->height); + } + sp->px = NRAND(sp->width); + sp->py = NRAND(sp->height); + sp->time = 0; + + MI_CLEARWINDOW(mi); +} + +static void +free_sierpinski(sierpinskistruct *sp) +{ + int corner; + + for (corner = 0; corner < MAXCORNERS; corner++) + if (sp->pointBuffer[corner] != NULL) { + (void) free((void *) sp->pointBuffer[corner]); + sp->pointBuffer[corner] = (XPoint *) NULL; + } +} + +ENTRYPOINT void +init_sierpinski(ModeInfo * mi) +{ + int i; + sierpinskistruct *sp; + + if (tris == NULL) { + if ((tris = (sierpinskistruct *) calloc(MI_NUM_SCREENS(mi), + sizeof (sierpinskistruct))) == NULL) + return; + } + sp = &tris[MI_SCREEN(mi)]; + + sp->width = MI_WIDTH(mi); + sp->height = MI_HEIGHT(mi); + + sp->total_npoints = MI_COUNT(mi); + if (sp->total_npoints < 1) + sp->total_npoints = 1; + sp->corners = MI_SIZE(mi); + if (sp->corners < 3 || sp->corners > 4) { + sp->corners = (int) (LRAND() & 1) + 3; + } + for (i = 0; i < sp->corners; i++) { + if (!sp->pointBuffer[i]) + if ((sp->pointBuffer[i] = (XPoint *) malloc(sp->total_npoints * + sizeof (XPoint))) == NULL) { + free_sierpinski(sp); + return; + } + } + startover(mi); +} + +ENTRYPOINT void +draw_sierpinski(ModeInfo * mi) +{ + Display *display = MI_DISPLAY(mi); + GC gc = MI_GC(mi); + XPoint *xp[MAXCORNERS]; + int i, v; + sierpinskistruct *sp; + + if (tris == NULL) + return; + sp = &tris[MI_SCREEN(mi)]; + if (sp->pointBuffer[0] == NULL) + return; + + MI_IS_DRAWN(mi) = True; + if (MI_NPIXELS(mi) <= 2) + XSetForeground(display, gc, MI_WHITE_PIXEL(mi)); + for (i = 0; i < sp->corners; i++) + xp[i] = sp->pointBuffer[i]; + for (i = 0; i < sp->total_npoints; i++) { + v = NRAND(sp->corners); + sp->px = (sp->px + sp->vertex[v].x) / 2; + sp->py = (sp->py + sp->vertex[v].y) / 2; + xp[v]->x = sp->px; + xp[v]->y = sp->py; + xp[v]++; + sp->npoints[v]++; + } + for (i = 0; i < sp->corners; i++) { + if (MI_NPIXELS(mi) > 2) + XSetForeground(display, gc, MI_PIXEL(mi, sp->colors[i])); + XDrawPoints(display, MI_WINDOW(mi), gc, sp->pointBuffer[i], sp->npoints[i], + CoordModeOrigin); + sp->npoints[i] = 0; + } + if (++sp->time >= MI_CYCLES(mi)) + startover(mi); +} + +ENTRYPOINT void +reshape_sierpinski(ModeInfo * mi, int width, int height) +{ + XClearWindow (MI_DISPLAY (mi), MI_WINDOW(mi)); + init_sierpinski (mi); +} + +ENTRYPOINT void +release_sierpinski(ModeInfo * mi) +{ + if (tris != NULL) { + int screen; + + for (screen = 0; screen < MI_NUM_SCREENS(mi); screen++) + free_sierpinski(&tris[screen]); + (void) free((void *) tris); + tris = (sierpinskistruct *) NULL; + } +} + +ENTRYPOINT void +refresh_sierpinski(ModeInfo * mi) +{ + MI_CLEARWINDOW(mi); +} + +XSCREENSAVER_MODULE ("Sierpinski", sierpinski) + +#endif /* MODE_sierpinski */ diff --git a/hacks/sierpinski.man b/hacks/sierpinski.man new file mode 100644 index 00000000..665ecad1 --- /dev/null +++ b/hacks/sierpinski.man @@ -0,0 +1,69 @@ +.TH XScreenSaver 1 "10-May-97" "X Version 11" +.SH NAME +sierpinski - draws Sierpinski triangle fractals +.SH SYNOPSIS +.B sierpinski +[\-display \fIhost:display.screen\fP] [\-foreground \fIcolor\fP] [\-background \fIcolor\fP] [\-window] [\-root] [\-mono] [\-install] [\-visual \fIvisual\fP] [\-ncolors \fIinteger\fP] [\-delay \fImicroseconds\fP] [\-cycles \fIinteger\fP] [\-count \fIinteger\fP] + +[\-fps] +.SH DESCRIPTION +The \fIsierpinski\fP program draws Sierpinski triangle fractals. +.SH OPTIONS +.I sierpinski +accepts the following options: +.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 \-mono +If on a color display, pretend we're on a monochrome display. +.TP 8 +.B \-install +Install a private colormap for the window. +.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 \-ncolors \fIinteger\fP +How many colors should be used (if possible). Default 64. +The colors are chosen randomly. +.TP 8 +.B \-cycles \fIinteger\fP + +.TP 8 +.B \-count \fIinteger\fP + +.TP 8 +.B \-fps +Display the current frame rate and CPU load. +.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), +.BR xlock (1) +.SH COPYRIGHT +Copyright \(co 1996 by Desmond Daignault. + +Permission to use, copy, modify, and distribute this software and its +documentation for any purpose and without fee is hereby granted, +provided that the above copyright notice appear in all copies and that +both that copyright notice and this permission notice appear in +supporting documentation. +.SH AUTHOR +Desmond Daignault , 05-Sep-96. (Original +xlock version was called tri.c.) + +Ability to run standalone or with \fIxscreensaver\fP added by +Jamie Zawinski , 10-May-97. (Renamed to sierpinski.) diff --git a/hacks/slidescreen.c b/hacks/slidescreen.c new file mode 100644 index 00000000..69aa10fc --- /dev/null +++ b/hacks/slidescreen.c @@ -0,0 +1,485 @@ +/* xscreensaver, Copyright (c) 1992-2008 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. + */ + +#include "screenhack.h" + +enum { DOWN = 0, LEFT, UP, RIGHT }; +enum { VERTICAL, HORIZONTAL }; + +struct state { + Display *dpy; + Window window; + + int grid_size; + int pix_inc; + int hole_x, hole_y; + int bitmap_w, bitmap_h; + int xoff, yoff; + int grid_w, grid_h; + int delay, delay2; + int duration; + GC gc; + unsigned long fg, bg; + int max_width, max_height; + int early_i; + + int draw_rnd, draw_i; + int draw_x, draw_y, draw_ix, draw_iy, draw_dx, draw_dy; + int draw_dir, draw_w, draw_h, draw_size, draw_inc; + int draw_last; + int draw_initted; + + time_t start_time; + async_load_state *img_loader; +}; + + +static void * +slidescreen_init (Display *dpy, Window window) +{ + struct state *st = (struct state *) calloc (1, sizeof(*st)); + XWindowAttributes xgwa; + XGCValues gcv; + long gcflags; + + st->dpy = dpy; + st->window = window; + XGetWindowAttributes (st->dpy, st->window, &xgwa); + st->img_loader = load_image_async_simple (0, xgwa.screen, st->window, + st->window, 0, 0); + st->start_time = time ((time_t) 0); + + st->max_width = xgwa.width; + st->max_height = xgwa.height; + + st->delay = get_integer_resource (st->dpy, "delay", "Integer"); + st->delay2 = get_integer_resource (st->dpy, "delay2", "Integer"); + st->duration = get_integer_resource (st->dpy, "duration", "Seconds"); + st->grid_size = get_integer_resource (st->dpy, "gridSize", "Integer"); + st->pix_inc = get_integer_resource (st->dpy, "pixelIncrement", "Integer"); + + /* Don't let the grid be smaller than 5x5 */ + while (st->grid_size > xgwa.width / 5) + st->grid_size /= 2; + while (st->grid_size > xgwa.height / 5) + st->grid_size /= 2; + + if (st->delay < 0) st->delay = 0; + if (st->delay2 < 0) st->delay2 = 0; + if (st->duration < 1) st->duration = 1; + if (st->pix_inc < 1) st->pix_inc = 1; + if (st->grid_size < 1) st->grid_size = 1; + + + { + XColor fgc, bgc; + char *fgs = get_string_resource(st->dpy, "background", "Background"); + char *bgs = get_string_resource(st->dpy, "foreground", "Foreground"); + Bool fg_ok, bg_ok; + if (!XParseColor (st->dpy, xgwa.colormap, fgs, &fgc)) + XParseColor (st->dpy, xgwa.colormap, "black", &bgc); + if (!XParseColor (st->dpy, xgwa.colormap, bgs, &bgc)) + XParseColor (st->dpy, xgwa.colormap, "gray", &fgc); + + fg_ok = XAllocColor (st->dpy, xgwa.colormap, &fgc); + bg_ok = XAllocColor (st->dpy, xgwa.colormap, &bgc); + + /* If we weren't able to allocate the two colors we want from the + colormap (which is likely if the screen has been grabbed on an + 8-bit SGI visual -- don't ask) then just go through the map + and find the closest color to the ones we wanted, and use those + pixels without actually allocating them. + */ + if (fg_ok) + st->fg = fgc.pixel; + else + st->fg = 0; + + if (bg_ok) + st->bg = bgc.pixel; + else + st->bg = 1; + +#ifndef HAVE_COCOA + if (!fg_ok || bg_ok) + { + int i; + unsigned long fgd = ~0; + unsigned long bgd = ~0; + int max = visual_cells (xgwa.screen, xgwa.visual); + XColor *all = (XColor *) calloc(sizeof (*all), max); + for (i = 0; i < max; i++) + { + all[i].flags = DoRed|DoGreen|DoBlue; + all[i].pixel = i; + } + XQueryColors (st->dpy, xgwa.colormap, all, max); + for(i = 0; i < max; i++) + { + long rd, gd, bd; + unsigned long dd; + if (!fg_ok) + { + rd = (all[i].red >> 8) - (fgc.red >> 8); + gd = (all[i].green >> 8) - (fgc.green >> 8); + bd = (all[i].blue >> 8) - (fgc.blue >> 8); + if (rd < 0) rd = -rd; + if (gd < 0) gd = -gd; + if (bd < 0) bd = -bd; + dd = (rd << 1) + (gd << 2) + bd; + if (dd < fgd) + { + fgd = dd; + st->fg = all[i].pixel; + if (dd == 0) + fg_ok = True; + } + } + + if (!bg_ok) + { + rd = (all[i].red >> 8) - (bgc.red >> 8); + gd = (all[i].green >> 8) - (bgc.green >> 8); + bd = (all[i].blue >> 8) - (bgc.blue >> 8); + if (rd < 0) rd = -rd; + if (gd < 0) gd = -gd; + if (bd < 0) bd = -bd; + dd = (rd << 1) + (gd << 2) + bd; + if (dd < bgd) + { + bgd = dd; + st->bg = all[i].pixel; + if (dd == 0) + bg_ok = True; + } + } + + if (fg_ok && bg_ok) + break; + } + XFree(all); + } +#endif /* !HAVE_COCOA */ + } + + gcv.foreground = st->fg; + gcv.function = GXcopy; + gcv.subwindow_mode = IncludeInferiors; + gcflags = GCForeground |GCFunction; + if (use_subwindow_mode_p(xgwa.screen, st->window)) /* see grabscreen.c */ + gcflags |= GCSubwindowMode; + st->gc = XCreateGC (st->dpy, st->window, gcflags, &gcv); + + return st; +} + +static void +draw_grid (struct state *st) +{ + int i; + Drawable d; + int border; + XWindowAttributes xgwa; + + XGetWindowAttributes (st->dpy, st->window, &xgwa); + + border = get_integer_resource (st->dpy, "internalBorderWidth", + "InternalBorderWidth"); + + XGetWindowAttributes (st->dpy, st->window, &xgwa); + st->bitmap_w = xgwa.width; + st->bitmap_h = xgwa.height; + + st->grid_w = st->bitmap_w / st->grid_size; + st->grid_h = st->bitmap_h / st->grid_size; + st->hole_x = random () % st->grid_w; + st->hole_y = random () % st->grid_h; + st->xoff = (st->bitmap_w - (st->grid_w * st->grid_size)) / 2; + st->yoff = (st->bitmap_h - (st->grid_h * st->grid_size)) / 2; + + d = st->window; + + st->early_i = -10; + st->draw_last = -1; + + if (border) + { + int half = border/2; + int half2 = (border & 1 ? half+1 : half); + XSetForeground(st->dpy, st->gc, st->bg); + for (i = 0; i < st->bitmap_w; i += st->grid_size) + { + int j; + for (j = 0; j < st->bitmap_h; j += st->grid_size) + XDrawRectangle (st->dpy, d, st->gc, + st->xoff+i+half2, st->yoff+j+half2, + st->grid_size-border-1, st->grid_size-border-1); + } + + XSetForeground(st->dpy, st->gc, st->fg); + for (i = 0; i <= st->bitmap_w; i += st->grid_size) + XFillRectangle (st->dpy, d, st->gc, st->xoff+i-half, st->yoff, border, st->bitmap_h); + for (i = 0; i <= st->bitmap_h; i += st->grid_size) + XFillRectangle (st->dpy, d, st->gc, st->xoff, st->yoff+i-half, st->bitmap_w, border); + } + + if (st->xoff) + { + XFillRectangle (st->dpy, d, st->gc, 0, 0, st->xoff, st->bitmap_h); + XFillRectangle (st->dpy, d, st->gc, st->bitmap_w - st->xoff, 0, st->xoff, st->bitmap_h); + } + if (st->yoff) + { + XFillRectangle (st->dpy, d, st->gc, 0, 0, st->bitmap_w, st->yoff); + XFillRectangle (st->dpy, d, st->gc, 0, st->bitmap_h - st->yoff, st->bitmap_w, st->yoff); + } +} + + +static int +slidescreen_draw_early (struct state *st) +{ + while (st->early_i < 0) + { + st->early_i++; + return 1; + } + + /* for (early_i = 0; early_i < grid_size; early_i += pix_inc) */ + { + XPoint points [3]; + points[0].x = st->xoff + st->grid_size * st->hole_x; + points[0].y = st->yoff + st->grid_size * st->hole_y; + points[1].x = points[0].x + st->grid_size; + points[1].y = points[0].y; + points[2].x = points[0].x; + points[2].y = points[0].y + st->early_i; + XFillPolygon (st->dpy, st->window, st->gc, points, 3, Convex, CoordModeOrigin); + + points[1].x = points[0].x; + points[1].y = points[0].y + st->grid_size; + points[2].x = points[0].x + st->early_i; + points[2].y = points[0].y + st->grid_size; + XFillPolygon (st->dpy, st->window, st->gc, points, 3, Convex, CoordModeOrigin); + + points[0].x = points[1].x + st->grid_size; + points[0].y = points[1].y; + points[2].x = points[0].x; + points[2].y = points[0].y - st->early_i; + XFillPolygon (st->dpy, st->window, st->gc, points, 3, Convex, CoordModeOrigin); + + points[1].x = points[0].x; + points[1].y = points[0].y - st->grid_size; + points[2].x = points[1].x - st->early_i; + points[2].y = points[1].y; + XFillPolygon (st->dpy, st->window, st->gc, points, 3, Convex, CoordModeOrigin); + } + + st->early_i += st->pix_inc; + if (st->early_i < st->grid_size) + return 1; + + XFillRectangle (st->dpy, st->window, st->gc, + st->xoff + st->grid_size * st->hole_x, + st->yoff + st->grid_size * st->hole_y, + st->grid_size, st->grid_size); + return 0; +} + + +static unsigned long +slidescreen_draw (Display *dpy, Window window, void *closure) +{ + struct state *st = (struct state *) closure; + int this_delay = st->delay; + + /* this code is a total kludge, but who cares, it works... */ + + if (st->img_loader) /* still loading */ + { + st->img_loader = load_image_async_simple (st->img_loader, 0, 0, 0, 0, 0); + if (! st->img_loader) { /* just finished */ + st->start_time = time ((time_t) 0); + draw_grid (st); + } + return st->delay; + } + + if (!st->img_loader && + st->start_time + st->duration < time ((time_t) 0)) { + XWindowAttributes xgwa; + XGetWindowAttributes(st->dpy, st->window, &xgwa); + st->img_loader = load_image_async_simple (0, xgwa.screen, st->window, + st->window, 0, 0); + st->start_time = time ((time_t) 0); + st->draw_initted = 0; + return st->delay; + } + + if (! st->draw_initted) + { + if (!slidescreen_draw_early (st)) + { + st->draw_initted = 1; + return st->delay2; + } + else + return st->delay; + } + + if (st->draw_i == 0) + { + if (st->draw_last == -1) st->draw_last = random () % 2; + + /* alternate between horizontal and vertical slides */ + /* note that draw_dir specifies the direction the _hole_ moves, not the tiles */ + if (st->draw_last == VERTICAL) { + if (((st->grid_w > 1) ? st->draw_rnd = random () % (st->grid_w - 1) : 0) + < st->hole_x) { + st->draw_dx = -1; st->draw_dir = LEFT; st->hole_x -= st->draw_rnd; + } else { + st->draw_dx = 1; st->draw_dir = RIGHT; st->draw_rnd -= st->hole_x; + } + st->draw_dy = 0; st->draw_w = st->draw_size = st->draw_rnd + 1; st->draw_h = 1; + st->draw_last = HORIZONTAL; + } else { + if (((st->grid_h > 1) ? st->draw_rnd = random () % (st->grid_h - 1) : 0) + < st->hole_y) { + st->draw_dy = -1; st->draw_dir = UP; st->hole_y -= st->draw_rnd; + } else { + st->draw_dy = 1; st->draw_dir = DOWN; st->draw_rnd -= st->hole_y; + } + st->draw_dx = 0; st->draw_h = st->draw_size = st->draw_rnd + 1; st->draw_w = 1; + st->draw_last = VERTICAL; + } + + st->draw_ix = st->draw_x = st->xoff + (st->hole_x + st->draw_dx) * st->grid_size; + st->draw_iy = st->draw_y = st->yoff + (st->hole_y + st->draw_dy) * st->grid_size; + st->draw_inc = st->pix_inc; + + } + + /* for (draw_i = 0; draw_i < grid_size; draw_i += draw_inc) */ + { + int fx, fy, tox, toy; + if (st->draw_inc + st->draw_i > st->grid_size) + st->draw_inc = st->grid_size - st->draw_i; + tox = st->draw_x - st->draw_dx * st->draw_inc; + toy = st->draw_y - st->draw_dy * st->draw_inc; + + fx = (st->draw_x < 0 ? 0 : st->draw_x > st->max_width ? st->max_width : st->draw_x); + fy = (st->draw_y < 0 ? 0 : st->draw_y > st->max_height ? st->max_height : st->draw_y); + tox = (tox < 0 ? 0 : tox > st->max_width ? st->max_width : tox); + toy = (toy < 0 ? 0 : toy > st->max_height ? st->max_height : toy); + + XCopyArea (st->dpy, st->window, st->window, st->gc, + fx, fy, + st->grid_size * st->draw_w, st->grid_size * st->draw_h, + tox, toy); + + st->draw_x -= st->draw_dx * st->draw_inc; + st->draw_y -= st->draw_dy * st->draw_inc; + switch (st->draw_dir) + { + case DOWN: XFillRectangle (st->dpy, st->window, st->gc, + st->draw_ix, st->draw_y + st->grid_size * st->draw_h, st->grid_size * st->draw_w, st->draw_iy - st->draw_y); + break; + case LEFT: XFillRectangle (st->dpy, st->window, st->gc, st->draw_ix, st->draw_iy, st->draw_x - st->draw_ix, st->grid_size * st->draw_h); + break; + case UP: XFillRectangle (st->dpy, st->window, st->gc, st->draw_ix, st->draw_iy, st->grid_size * st->draw_w, st->draw_y - st->draw_iy); + break; + case RIGHT: XFillRectangle (st->dpy, st->window, st->gc, + st->draw_x + st->grid_size * st->draw_w, st->draw_iy, st->draw_ix - st->draw_x, st->grid_size * st->draw_h); + break; + } + } + + st->draw_i += st->draw_inc; + if (st->draw_i >= st->grid_size) + { + st->draw_i = 0; + + switch (st->draw_dir) + { + case DOWN: st->hole_y += st->draw_size; break; + case LEFT: st->hole_x--; break; + case UP: st->hole_y--; break; + case RIGHT: st->hole_x += st->draw_size; break; + } + + this_delay = st->delay2; + } + + return this_delay; +} + +static void +slidescreen_reshape (Display *dpy, Window window, void *closure, + unsigned int w, unsigned int h) +{ + struct state *st = (struct state *) closure; + st->max_width = w; + st->max_height = h; + if (! st->img_loader) { + XWindowAttributes xgwa; + XGetWindowAttributes (st->dpy, st->window, &xgwa); + st->img_loader = load_image_async_simple (0, xgwa.screen, st->window, + st->window, 0, 0); + st->start_time = time ((time_t) 0); + } +} + +static Bool +slidescreen_event (Display *dpy, Window window, void *closure, XEvent *event) +{ + return False; +} + +static void +slidescreen_free (Display *dpy, Window window, void *closure) +{ + struct state *st = (struct state *) closure; + XFreeGC (dpy, st->gc); + free (st); +} + + + +static const char *slidescreen_defaults [] = { + "*dontClearRoot: True", + "*fpsSolid: true", + +#ifdef __sgi /* really, HAVE_READ_DISPLAY_EXTENSION */ + "*visualID: Best", +#endif + + ".background: Black", + ".foreground: #BEBEBE", + "*gridSize: 70", + "*pixelIncrement: 10", + "*internalBorderWidth: 4", + "*delay: 50000", + "*delay2: 1000000", + "*duration: 120", + 0 +}; + +static XrmOptionDescRec slidescreen_options [] = { + { "-grid-size", ".gridSize", XrmoptionSepArg, 0 }, + { "-ibw", ".internalBorderWidth", XrmoptionSepArg, 0 }, + { "-increment", ".pixelIncrement", XrmoptionSepArg, 0 }, + { "-delay", ".delay", XrmoptionSepArg, 0 }, + { "-delay2", ".delay2", XrmoptionSepArg, 0 }, + {"-duration", ".duration", XrmoptionSepArg, 0 }, + { 0, 0, 0, 0 } +}; + +XSCREENSAVER_MODULE ("SlideScreen", slidescreen) diff --git a/hacks/slidescreen.man b/hacks/slidescreen.man new file mode 100644 index 00000000..6ab4fde2 --- /dev/null +++ b/hacks/slidescreen.man @@ -0,0 +1,97 @@ +.TH XScreenSaver 1 "24-Nov-97" "X Version 11" +.SH NAME +slidescreen - permute the screen image like an 8-puzzle +.SH SYNOPSIS +.B slidescreen +[\-display \fIhost:display.screen\fP] +[\-background \fIcolor\fP] +[\-grid-size \fIpixels\fP] +[\-ibw \fIpixels\fP] +[\-increment \fIpixels\fP] +[\-delay \fIusecs\fP] +[\-delay2 \fIusecs\fP] +[\-duration \fIsecs\fP] +[\-window] +[\-root] +[\-install] +[\-visual \fIvisual\fP] +[\-fps] +.SH DESCRIPTION +The \fIslidescreen\fP program takes an image, divides it into +a grid, deletes a random square of that grid, and then randomly slides +one of the neighbors of this "hole" into the hole (and repeat.) + +The image that it manipulates will be grabbed from the portion of +the screen underlying the window, or from the system's video input, +or from a random file on disk, as indicated by +the \fIgrabDesktopImages\fP, \fIgrabVideoFrames\fP, +and \fIchooseRandomImages\fP options in the \fI~/.xscreensaver\fP +file; see +.BR xscreensaver-demo (1) +for more details. +.SH OPTIONS +.I slidescreen +accepts the following options: +.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 \-install +Install a private colormap for the window. +.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 \-grid-size \fIpixels\fP +The size of the grid cells. Default 70 pixels. +.TP 8 +.B \-ibw \fIpixels\fP +The size of the "gutter" between grid cells. Default 4 pixel. +.TP 8 +.B \-increment \fIpixels\fP +How many pixels by which a piece should be moved when sliding to a new +location. Default 10 pixels. +.TP 8 +.B \-delay \fImicroseconds\fP +How much of a delay should be introduced between steps of the animation of +the motion of each segment. Default 50000, which is 0.05 seconds. This +is closely related to the \fI\-increment\fP parameter. +.TP 8 +.B \-delay2 \fImicroseconds\fP +How much of a delay should be introduced between the end of the motion of +one segment and the beginning of the motion of another. Default 1000000, +which is one second. +.TP 8 +.B \-duration \fIseconds\fP +How long to run before loading a new image. Default 120 seconds. +.TP 8 +.B \-fps +Display the current frame rate and CPU load. +.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), +.BR xscreensaver\-demo (1), +.BR xscreensaver\-getimage (1) +.SH COPYRIGHT +Copyright \(co 1992 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 , 3-dec-92. diff --git a/hacks/slip.c b/hacks/slip.c new file mode 100644 index 00000000..e0b0ea4f --- /dev/null +++ b/hacks/slip.c @@ -0,0 +1,367 @@ +/* -*- Mode: C; tab-width: 4 -*- */ +/* slip --- lots of slipping blits */ + +#if 0 +static const char sccsid[] = "@(#)slip.c 5.00 2000/11/01 xlockmore"; +#endif + +/*- + * Copyright (c) 1992 by Scott Draves + * + * Permission to use, copy, modify, and distribute this software and its + * documentation for any purpose and without fee is hereby granted, + * provided that the above copyright notice appear in all copies and that + * both that copyright notice and this permission notice appear in + * supporting documentation. + * + * This file is provided AS IS with no warranties of any kind. The author + * shall have no liability with respect to the infringement of copyrights, + * trade secrets or any patents by this file or any part thereof. In no + * event will the author be liable for any lost revenue or profits or + * other special, indirect and consequential damages. + * + * 01-Nov-2000: Allocation checks + * 10-May-1997: Jamie Zawinski compatible with xscreensaver + * 01-Dec-1995: Patched for VMS + */ + +#ifdef STANDALONE +# define MODE_slip +# define DEFAULTS "*delay: 50000 \n" \ + "*count: 35 \n" \ + "*cycles: 50 \n" \ + "*ncolors: 200 \n" \ + "*fpsSolid: true \n" + +# define refresh_slip 0 +# define slip_handle_event 0 +# include "xlockmore.h" /* in xscreensaver distribution */ +#else /* STANDALONE */ +# include "xlock.h" /* in xlockmore distribution */ +#endif /* STANDALONE */ + +#ifdef MODE_slip + +ENTRYPOINT ModeSpecOpt slip_opts = +{0, (XrmOptionDescRec *) NULL, 0, (argtype *) NULL, (OptionStruct *) NULL}; + +#ifdef USE_MODULES +ModStruct slip_description = +{"slip", "init_slip", "draw_slip", "release_slip", + "init_slip", "init_slip", (char *) NULL, &slip_opts, + 50000, 35, 50, 1, 64, 1.0, "", + "Shows slipping blits", 0, NULL}; + +#endif + +typedef struct { + int width, height; + int nblits_remaining; + int blit_width, blit_height; + int mode; + int first_time; + int backwards; + short lasthalf; + int stage; + unsigned long r; + Bool image_loading_p; +} slipstruct; +static slipstruct *slips = (slipstruct *) NULL; + +static short +halfrandom(slipstruct *sp, int mv) +{ + unsigned long r; + + if (sp->lasthalf) { + r = sp->lasthalf; + sp->lasthalf = 0; + } else { + r = LRAND(); + sp->lasthalf = (short) (r >> 16); + } + return r % mv; +} + +static int +erandom(slipstruct *sp, int mv) +{ + int res; + + if (0 == sp->stage) { + sp->r = LRAND(); + sp->stage = 7; + } + res = (int) (sp->r & 0xf); + sp->r = sp->r >> 4; + sp->stage--; + if (res & 8) + return res & mv; + else + return -(res & mv); +} + +#ifdef STANDALONE +static void +image_loaded_cb (Screen *screen, Window w, Drawable d, + const char *name, XRectangle *geom, + void *closure) +{ + ModeInfo *mi = (ModeInfo *) closure; + slipstruct *sp = &slips[MI_SCREEN(mi)]; + Display *dpy = DisplayOfScreen (screen); + XCopyArea (dpy, d, w, mi->gc, 0, 0, + sp->width, sp->height, 0, 0); + XFreePixmap (dpy, d); + sp->image_loading_p = False; +} +#endif /* STANDALONE */ + +static void +prepare_screen(ModeInfo * mi, slipstruct * sp) +{ + + Display *display = MI_DISPLAY(mi); + GC gc = MI_GC(mi); + int i, n, w = sp->width / 20; + int not_solid = halfrandom(sp, 10); + + sp->backwards = (int) (LRAND() & 1); /* jwz: go the other way sometimes */ + + if (sp->first_time || !halfrandom(sp, 10)) { + MI_CLEARWINDOW(mi); + n = 300; + } else { + if (halfrandom(sp, 5)) + return; + if (halfrandom(sp, 5)) + n = 100; + else + n = 2000; + } + + if (MI_NPIXELS(mi) > 2) + XSetForeground(display, gc, MI_PIXEL(mi, halfrandom(sp, MI_NPIXELS(mi)))); + else if (halfrandom(sp, 2)) + XSetForeground(display, gc, MI_WHITE_PIXEL(mi)); + else + XSetForeground(display, gc, MI_BLACK_PIXEL(mi)); + + for (i = 0; i < n; i++) { + int ww = ((w / 2) + halfrandom(sp, MAX(w, 1))); + + if (not_solid) { + if (MI_NPIXELS(mi) > 2) + XSetForeground(display, gc, MI_PIXEL(mi, halfrandom(sp, MI_NPIXELS(mi)))); + else if (halfrandom(sp, 2)) + XSetForeground(display, gc, MI_WHITE_PIXEL(mi)); + else + XSetForeground(display, gc, MI_BLACK_PIXEL(mi)); + } + XFillRectangle(display, MI_WINDOW(mi), gc, + halfrandom(sp, MAX(sp->width - ww, 1)), + halfrandom(sp, MAX(sp->height - ww, 1)), + ww, ww); + } + sp->first_time = 0; + + +#ifdef STANDALONE /* jwz -- sometimes hack the desktop image! */ + if (!sp->image_loading_p && + (1||halfrandom(sp, 2) == 0)) { + /* Load it into a pixmap so that the "Loading" message and checkerboard + don't show up on the window -- we keep running while the image is + in progress... */ + Pixmap p = XCreatePixmap (MI_DISPLAY(mi), MI_WINDOW(mi), + sp->width, sp->height, mi->xgwa.depth); + sp->image_loading_p = True; + load_image_async (ScreenOfDisplay (MI_DISPLAY(mi), 0/*####MI_SCREEN(mi)*/), + MI_WINDOW(mi), p, image_loaded_cb, mi); + } +#endif +} + +static int +quantize(double d) +{ + int i = (int) floor(d); + double f = d - i; + + if ((LRAND() & 0xff) < f * 0xff) + i++; + return i; +} + +ENTRYPOINT void +reshape_slip (ModeInfo * mi, int w, int h) +{ + slipstruct *sp = &slips[MI_SCREEN(mi)]; + sp->width = w; + sp->height = h; + sp->blit_width = sp->width / 25; + sp->blit_height = sp->height / 25; + + sp->mode = 0; + sp->nblits_remaining = 0; +} + +ENTRYPOINT void +init_slip (ModeInfo * mi) +{ + slipstruct *sp; + + if (slips == NULL) { + if ((slips = (slipstruct *) calloc(MI_NUM_SCREENS(mi), + sizeof (slipstruct))) == NULL) + return; + } + sp = &slips[MI_SCREEN(mi)]; + + sp->nblits_remaining = 0; + sp->mode = 0; + sp->first_time = 1; + + /* no "NoExpose" events from XCopyArea wanted */ + XSetGraphicsExposures(MI_DISPLAY(mi), MI_GC(mi), False); + + reshape_slip (mi, MI_WIDTH(mi), MI_HEIGHT(mi)); +} + +ENTRYPOINT void +draw_slip (ModeInfo * mi) +{ + Display *display = MI_DISPLAY(mi); + Window window = MI_WINDOW(mi); + GC gc = MI_GC(mi); + int timer; + slipstruct *sp; + + if (slips == NULL) + return; + sp = &slips[MI_SCREEN(mi)]; + + timer = MI_COUNT(mi) * MI_CYCLES(mi); + + MI_IS_DRAWN(mi) = True; + + while (timer--) { + int xi = halfrandom(sp, MAX(sp->width - sp->blit_width, 1)); + int yi = halfrandom(sp, MAX(sp->height - sp->blit_height, 1)); + double x, y, dx = 0, dy = 0, t, s1, s2; + + if (0 == sp->nblits_remaining--) { + static const int lut[] = {0, 0, 0, 1, 1, 1, 2}; + + prepare_screen(mi, sp); + sp->nblits_remaining = MI_COUNT(mi) * + (2000 + halfrandom(sp, 1000) + halfrandom(sp, 1000)); + if (sp->mode == 2) + sp->mode = halfrandom(sp, 2); + else + sp->mode = lut[halfrandom(sp, 7)]; + } + x = (2 * xi + sp->blit_width) / (double) sp->width - 1; + y = (2 * yi + sp->blit_height) / (double) sp->height - 1; + + /* (x,y) is in biunit square */ + switch (sp->mode) { + case 0: /* rotor */ + dx = x; + dy = y; + + if (dy < 0) { + dy += 0.04; + if (dy > 0) + dy = 0.00; + } + if (dy > 0) { + dy -= 0.04; + if (dy < 0) + dy = 0.00; + } + t = dx * dx + dy * dy + 1e-10; + s1 = 2 * dx * dx / t - 1; + s2 = 2 * dx * dy / t; + dx = s1 * 5; + dy = s2 * 5; + + if (sp->backwards) { /* jwz: go the other way sometimes */ + dx = -dx; + dy = -dy; + } + break; + case 1: /* shuffle */ + dx = erandom(sp, 3); + dy = erandom(sp, 3); + break; + case 2: /* explode */ + dx = x * 3; + dy = y * 3; + break; + } + { + int qx = xi + quantize(dx), qy = yi + quantize(dy); + int wrap; + + if (qx < 0 || qy < 0 || + qx >= sp->width - sp->blit_width || + qy >= sp->height - sp->blit_height) + continue; + +/*- +Seems to cause problems using Exceed +with PseudoColor +X Error of failed request: BadGC (invalid GC parameter) +with TrueColor +X Error of failed request: BadDrawable (invalid Pixmap or Window parameter) + Major opcode of failed request: 62 (X_CopyArea) + */ + XCopyArea(display, window, window, gc, xi, yi, + sp->blit_width, sp->blit_height, + qx, qy); + switch (sp->mode) { + case 0: + /* wrap */ + wrap = sp->width - (2 * sp->blit_width); + if (qx > wrap ) { + XCopyArea(display, window, window, gc, qx, qy, + sp->blit_width, sp->blit_height, + qx - wrap, qy); + } + if (qx < 2 * sp->blit_width) { + XCopyArea(display, window, window, gc, qx, qy, + sp->blit_width, sp->blit_height, + qx + wrap, qy); + } + wrap = sp->height - (2 * sp->blit_height); + if (qy > wrap) { + XCopyArea(display, window, window, gc, qx, qy, + sp->blit_width, sp->blit_height, + qx, qy - wrap); + } + if (qy < 2 * sp->blit_height) { + XCopyArea(display, window, window, gc, qx, qy, + sp->blit_width, sp->blit_height, + qx, qy + wrap); + } + break; + case 1: + case 2: + break; + } + } + } +} + +ENTRYPOINT void +release_slip (ModeInfo * mi) +{ + if (slips != NULL) { + (void) free((void *) slips); + slips = (slipstruct *) NULL; + } +} + +XSCREENSAVER_MODULE ("Slip", slip) + +#endif /* MODE_slip */ diff --git a/hacks/slip.man b/hacks/slip.man new file mode 100644 index 00000000..ce4e1109 --- /dev/null +++ b/hacks/slip.man @@ -0,0 +1,86 @@ +.TH XScreenSaver 1 "24-Nov-97" "X Version 11" +.SH NAME +slip - sucks your screen into a jet engine +.SH SYNOPSIS +.B slip +[\-display \fIhost:display.screen\fP] [\-foreground \fIcolor\fP] +[\-background \fIcolor\fP] [\-window] [\-root] [\-mono] [\-install] +[\-visual \fIvisual\fP] [\-ncolors \fIinteger\fP] +[\-iterations \fIinteger\fP] [\-points \fIinteger\fP] +[\-delay \fImicroseconds\fP] [\-delay2 \fImicroseconds\fP] +[\-fps] +.SH DESCRIPTION +The \fIslip\fP program does lots of blits and chews up an image. + +The image that it manipulates will be grabbed from the portion of +the screen underlying the window, or from the system's video input, +or from a random file on disk, as indicated by +the \fIgrabDesktopImages\fP, \fIgrabVideoFrames\fP, +and \fIchooseRandomImages\fP options in the \fI~/.xscreensaver\fP +file; see +.BR xscreensaver-demo (1) +for more details. +.SH OPTIONS +.I slip +accepts the following options: +.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 \-mono +If on a color display, pretend we're on a monochrome display. +.TP 8 +.B \-install +Install a private colormap for the window. +.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 \-ncolors \fIinteger\fP +How many colors should be used (if possible). Default 200. +The colors used cycle through the hue, making N stops around +the color wheel. +.TP 8 +.B \-count \fIinteger\fP +How many whooziwhatsis to generate. Default 35. +.TP 8 +.B \-cycles \fIinteger\fP +How long to frobnicate. Default 50. +.TP 8 +.B \-delay \fImicroseconds\fP +How long we should wait between drawing each step. Default 50000, +or about 1/20th second. +.TP 8 +.B \-fps +Display the current frame rate and CPU load. +.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), +.BR xscreensaver\-demo (1), +.BR xscreensaver\-getimage (1) +.SH COPYRIGHT +Copyright \(co 1992 by Scott Draves. + +Permission to use, copy, modify, and distribute this software and its +documentation for any purpose and without fee is hereby granted, +provided that the above copyright notice appear in all copies and that +both that copyright notice and this permission notice appear in +supporting documentation. +.SH AUTHOR +Scott Graves . + +Ability to run standalone or with \fIxscreensaver\fP added by +Jamie Zawinski , 18-Oct-93. diff --git a/hacks/speedmine.c b/hacks/speedmine.c new file mode 100644 index 00000000..5c67082d --- /dev/null +++ b/hacks/speedmine.c @@ -0,0 +1,1644 @@ +/* -*- Mode: C; c-basic-offset: 4; tab-width: 4 -*- + * speedmine, Copyright (C) 2001 Conrad Parker + * + * 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. + */ + +/* + * Written mostly over the Easter holiday, 2001. Psychedelic option due to + * a night at Home nightclub, Sydney. Three all-nighters of solid partying + * were involved in the week this hack was written. + * + * Happy Birthday to WierdArms (17 April) and Pat (18 April) + */ + +/* + * Hacking notes + * + * This program generates a rectangular terrain grid and maps this onto + * a semi-circular tunnel. The terrain has length TERRAIN_LENGTH, which + * corresponds to length along the tunnel, and breadth TERRAIN_BREADTH, + * which corresponds to circumference around the tunnel. For each frame, + * the tunnel is perspective mapped onto a set of X and Y screen values. + * + * Throughout this code the following temporary variable names are used: + * + * i iterates along the tunnel in the direction of travel + * j iterates around the tunnel clockwise + * t iterates along the length of the perspective mapped values + * from the furthest to the nearest + * + * Thus, the buffers are used with these iterators: + * + * terrain[i][j] terrain map + * worldx[i][j], worldy[i][j] world coordinates (after wrapping) + * {x,y,z}curvature[i] tunnel curvature + * wideness[i] tunnel wideness + * bonuses[i] bonus values + * + * xvals[t][j], yvals[t][j] screen coordinates + * {min,max}{x,y}[t] bounding boxes of screen coords + */ + +/* Define or undefine NDEBUG to turn assert and abort debugging off or on */ +#define NDEBUG +#include + +#include + +#include "screenhack.h" +#include "erase.h" + +#define MIN(a,b) ((a)<(b)?(a):(b)) +#define MAX(a,b) ((a)>(b)?(a):(b)) + +#define RAND(r) (int)(((r)>0)?(random() % (long)(r)): -(random() % (long)(-r))) + +#define SIGN3(a) ((a)>0?1:((a)<0?-1:0)) + +#define MODULO(a,b) while ((a)<0) (a)+=(b); (a) %= (b); + +/* No. of shades of each color (ground, walls, bonuses) */ +#define MAX_COLORS 32 + +#ifdef NDEBUG +#define DEBUG_FLAG 0 +#else +#define DEBUG_FLAG 1 +#endif + + +#define FORWARDS 1 +#define BACKWARDS -1 +/* Apparently AIX's math.h bogusly defines `nearest' as a function, + in violation of the ANSI C spec. */ +#undef nearest +#define nearest n3arest + +#define wireframe (st->wire_flag||st->wire_bonus>8||st->wire_bonus%2==1) +#define effective_speed (st->direction*(st->speed+st->speed_bonus)) + +/* No. of levels of interpolation, for perspective */ +#define INTERP 32 + +/* These must be powers of 2 */ +#define TERRAIN_LENGTH 256 +#define TERRAIN_BREADTH 32 + +/* total "perspective distance" of terrain */ +#define TERRAIN_PDIST (INTERP*TERRAIN_LENGTH) + +#define ROTS 1024 +#define TB_MUL (ROTS/TERRAIN_BREADTH) + +#define random_elevation() (st->terrain_flag?(random() % 200):0) +#define random_curvature() (st->curviness>0.0?((double)(random() % 40)-20)*st->curviness:0.0) +#define random_twist() (st->twistiness>0.0?((double)(random() % 40)-20)*st->twistiness:0.0) +#define random_wideness() (st->widening_flag?(int)(random() % 1200):0) + +#define STEEL_ELEVATION 300 + +struct state { + Display *dpy; + Window window; + + Pixmap dbuf, stars_mask; + Colormap cmap; + unsigned int default_fg_pixel; + GC draw_gc, erase_gc, tunnelend_gc, stars_gc, stars_erase_gc; + + int ncolors, nr_ground_colors, nr_wall_colors, nr_bonus_colors; + XColor ground_colors[MAX_COLORS], wall_colors[MAX_COLORS]; + XColor bonus_colors[MAX_COLORS]; + GC ground_gcs[MAX_COLORS], wall_gcs[MAX_COLORS], bonus_gcs[MAX_COLORS]; + + int be_wormy; + + int width, height; + int delay; + + int smoothness; + int verbose_flag; + int wire_flag; + int terrain_flag; + int widening_flag; + int bumps_flag; + int bonuses_flag; + int crosshair_flag; + int psychedelic_flag; + + double maxspeed; + + double thrust, gravity; + + double vertigo; + double curviness; + double twistiness; + + double pos; + double speed; + double accel; + double step; + + int direction; + + int pindex, nearest; + int flipped_at; + int xoffset, yoffset; + + int bonus_bright; + int wire_bonus; + + double speed_bonus; + + int spin_bonus; + int backwards_bonus; + + double sintab[ROTS], costab[ROTS]; + + int orientation; + + int terrain[TERRAIN_LENGTH][TERRAIN_BREADTH]; + double xcurvature[TERRAIN_LENGTH]; + double ycurvature[TERRAIN_LENGTH]; + double zcurvature[TERRAIN_LENGTH]; + int wideness[TERRAIN_LENGTH]; + int bonuses[TERRAIN_LENGTH]; + int xvals[TERRAIN_LENGTH][TERRAIN_BREADTH]; + int yvals[TERRAIN_LENGTH][TERRAIN_BREADTH]; + double worldx[TERRAIN_LENGTH][TERRAIN_BREADTH]; + double worldy[TERRAIN_LENGTH][TERRAIN_BREADTH]; + int minx[TERRAIN_LENGTH], maxx[TERRAIN_LENGTH]; + int miny[TERRAIN_LENGTH], maxy[TERRAIN_LENGTH]; + + int total_nframes; + int nframes; + double fps; + double fps_start, fps_end; + struct timeval start_time; + + int rotation_offset; + int jamming; +}; + +/* a forward declaration ... */ +static void change_colors(struct state *st); + + + +/* + * get_time () + * + * returns the total time elapsed since the beginning of the demo + */ +static double get_time(struct state *st) { + struct timeval t; + float f; +#if GETTIMEOFDAY_TWO_ARGS + gettimeofday(&t, NULL); +#else + gettimeofday(&t); +#endif + t.tv_sec -= st->start_time.tv_sec; + f = ((double)t.tv_sec) + t.tv_usec*1e-6; + return f; +} + +/* + * init_time () + * + * initialises the timing structures + */ +static void init_time(struct state *st) { +#if GETTIMEOFDAY_TWO_ARGS + gettimeofday(&st->start_time, NULL); +#else + gettimeofday(&st->start_time); +#endif + st->fps_start = get_time(st); +} + + +/* + * perspective() + * + * perspective map the world coordinates worldx[i][j], worldy[i][j] onto + * screen coordinates xvals[t][j], yvals[t][j] + */ +static void +perspective (struct state *st) +{ + int i, j, jj, t=0, depth, view_pos; + int rotation_bias, r; + double xc=0.0, yc=0.0, zc=0.0; + double xcc=0.0, ycc=0.0, zcc=0.0; + double xx, yy; + double zfactor, zf; + + zf = 8.0*28.0 / (double)(st->width*TERRAIN_LENGTH); + if (st->be_wormy) zf *= 3.0; + + depth = TERRAIN_PDIST - INTERP + st->pindex; + + view_pos = (st->nearest+3*TERRAIN_LENGTH/4)%TERRAIN_LENGTH; + + st->xoffset += - st->xcurvature[view_pos]*st->curviness/8; + st->xoffset /= 2; + + st->yoffset += - st->ycurvature[view_pos]*st->curviness/4; + st->yoffset /= 2; + + st->rotation_offset += (int)((st->zcurvature[view_pos]-st->zcurvature[st->nearest])*ROTS/8); + st->rotation_offset /= 2; + rotation_bias = st->orientation + st->spin_bonus - st->rotation_offset; + + if (st->bumps_flag) { + if (st->be_wormy) { + st->yoffset -= ((st->terrain[view_pos][TERRAIN_BREADTH/4] * st->width /(8*1600))); + rotation_bias += (st->terrain[view_pos][TERRAIN_BREADTH/4+2] - + st->terrain[view_pos][TERRAIN_BREADTH/4-2])/8; + } else { + st->yoffset -= ((st->terrain[view_pos][TERRAIN_BREADTH/4] * st->width /(2*1600))); + rotation_bias += (st->terrain[view_pos][TERRAIN_BREADTH/4+2] - + st->terrain[view_pos][TERRAIN_BREADTH/4-2])/16; + } + } + + MODULO(rotation_bias, ROTS); + + for (t=0; t < TERRAIN_LENGTH; t++) { + i = st->nearest + t; MODULO(i, TERRAIN_LENGTH); + xc += st->xcurvature[i]; yc += st->ycurvature[i]; zc += st->zcurvature[i]; + xcc += xc; ycc += yc; zcc += zc; + st->maxx[i] = st->maxy[i] = 0; + st->minx[i] = st->width; st->miny[i] = st->height; + } + + for (t=0; t < TERRAIN_LENGTH; t++) { + i = st->nearest - 1 - t; MODULO(i, TERRAIN_LENGTH); + + zfactor = (double)depth* (12.0 - TERRAIN_LENGTH/8.0) * zf; + for (j=0; j < TERRAIN_BREADTH; j++) { + jj = st->direction * j; MODULO(jj, TERRAIN_BREADTH); + /* jwz: not totally sure if this is right, but it avoids div0 */ + if (zfactor != 0) { + xx = (st->worldx[i][jj]-(st->vertigo*xcc))/zfactor; + yy = (st->worldy[i][j]-(st->vertigo*ycc))/zfactor; + } else { + xx = 0; + yy = 0; + } + r = rotation_bias + (int)(st->vertigo*zcc); MODULO(r, ROTS); + + st->xvals[t][j] = st->xoffset + (st->width>>1) + + (int)(xx * st->costab[r] - yy * st->sintab[r]); + st->maxx[t] = MAX(st->maxx[t], st->xvals[t][j]); + st->minx[t] = MIN(st->minx[t], st->xvals[t][j]); + + st->yvals[t][j] = st->yoffset + st->height/2 + + (int)(xx * st->sintab[r] + yy * st->costab[r]); + st->maxy[t] = MAX(st->maxy[t], st->yvals[t][j]); + st->miny[t] = MIN(st->miny[t], st->yvals[t][j]); + } + xcc -= xc; ycc -= yc; zcc -= zc; + xc -= st->xcurvature[i]; yc -= st->ycurvature[i]; zc -= st->zcurvature[i]; + depth -= INTERP; + } +} + +/* + * wrap_tunnel (start, end) + * + * wrap the terrain terrain[i][j] around the semi-circular tunnel function + * + * x' = x/2 * cos(theta) - (y-k) * x * sin(theta) + * y' = x/4 * sin(theta) + y * cos(theta) + * + * between i=start and i=end inclusive, producing world coordinates + * worldx[i][j], worldy[i][j] + */ +static void +wrap_tunnel (struct state *st, int start, int end) +{ + int i, j, v; + double x, y; + + assert (start < end); + + for (i=start; i <= end; i++) { + for (j=0; j < TERRAIN_BREADTH; j++) { + x = j * (1.0/TERRAIN_BREADTH); + v = st->terrain[i][j]; + y = (double)(v==STEEL_ELEVATION?200:v) - st->wideness[i] - 1200; + + /* lower road */ + if (j > TERRAIN_BREADTH/8 && j < 3*TERRAIN_BREADTH/8) y -= 300; + + st->worldx[i][j] = x/2 * st->costab[j*TB_MUL] - + (y-st->height/4.0)*x*st->sintab[j*TB_MUL]; + st->worldy[i][j] = x/4 * st->sintab[j*TB_MUL] + + y * st->costab[j*TB_MUL]; + } + } +} + +/* + * flip_direction() + * + * perform the state transitions and terrain transformation for the + * "look backwards/look forwards" bonus + */ +static void +flip_direction (struct state *st) +{ + int i, ip, in, j, t; + + st->direction = -st->direction; + + st->bonus_bright = 20; + + for (i=0; i < TERRAIN_LENGTH; i++) { + in = st->nearest + i; MODULO(in, TERRAIN_BREADTH); + ip = st->nearest - i; MODULO(ip, TERRAIN_BREADTH); + for (j=0; j < TERRAIN_BREADTH; j++) { + t = st->terrain[ip][j]; + st->terrain[ip][j] = st->terrain[in][j]; + st->terrain[in][j] = t; + } + } +} + +/* + * generate_smooth (start, end) + * + * generate smooth terrain between i=start and i=end inclusive + */ +static void +generate_smooth (struct state *st, int start, int end) +{ + int i,j, ii; + + assert (start < end); + + for (i=start; i <= end; i++) { + ii = i; MODULO(ii, TERRAIN_LENGTH); + for (j=0; j < TERRAIN_BREADTH; j++) { + st->terrain[i][j] = STEEL_ELEVATION; + } + } +} + +/* + * generate_straight (start, end) + * + * zero the curvature and wideness between i=start and i=end inclusive + */ +static void +generate_straight (struct state *st, int start, int end) +{ + int i,j, ii; + + assert (start < end); + + for (i=start; i <= end; i++) { + ii = i; MODULO(ii, TERRAIN_LENGTH); + for (j=0; j < TERRAIN_BREADTH; j++) { + st->xcurvature[ii] = 0; + st->ycurvature[ii] = 0; + st->zcurvature[ii] = 0; + st->wideness[ii] = 0; + } + } +} + +/* + * int generate_terrain_value (v1, v2, v3, v4, w) + * + * generate terrain value near the average of v1, v2, v3, v4, with + * perturbation proportional to w + */ +static int +generate_terrain_value (struct state *st, int v1, int v2, int v3, int v4, int w) +{ + int sum, ret; + int rval; + + if (!st->terrain_flag) return 0; + + sum = v1 + v2 + v3 + v4; + + rval = w*sum/st->smoothness; + if (rval == 0) rval = 2; + + ret = (sum/4 -(rval/2) + RAND(rval)); + + if (ret < -400 || ret > 400) { + ret = sum/4; + } + + return ret; +} + +/* + * generate_terrain (start, end, final) + * + * generate terrain[i][j] between i=start and i=end inclusive + * + * This is performed by successive subdivision of the terrain into + * rectangles of decreasing size. Subdivision continues until the + * the minimum width or height of these rectangles is 'final'; ie. + * final=1 indicates to subdivide as far as possible, final=2 indicates + * to stop one subdivision before that (leaving a checkerboard pattern + * uncalculated) etc. + */ +static void +generate_terrain (struct state *st, int start, int end, int final) +{ + int i,j,w,l; + int ip, jp, in, jn; /* prev, next values */ + int diff; + + assert (start < end); + assert (start >= 0 && start < TERRAIN_LENGTH); + assert (end >= 0 && end < TERRAIN_LENGTH); + + diff = end - start + 1; + + st->terrain[end][0] = random_elevation(); + st->terrain[end][TERRAIN_BREADTH/2] = random_elevation(); + + for (w= diff/2, l=TERRAIN_BREADTH/4; + w >= final || l >= final; w /= 2, l /= 2) { + + if (w<1) w=1; if (l<1) l=1; + + for (i=start+w-1; i < end; i += (w*2)) { + ip = i-w; MODULO(ip, TERRAIN_LENGTH); + in = i+w; MODULO(in, TERRAIN_LENGTH); + for (j=l-1; j < TERRAIN_BREADTH; j += (l*2)) { + jp = j-1; MODULO(jp, TERRAIN_BREADTH); + jn = j+1; MODULO(jn, TERRAIN_BREADTH); + st->terrain[i][j] = + generate_terrain_value (st, st->terrain[ip][jp], st->terrain[in][jp], + st->terrain[ip][jn], st->terrain[in][jn], w); + } + } + + for (i=start+(w*2)-1; i < end; i += (w*2)) { + ip = i-w; MODULO(ip, TERRAIN_LENGTH); + in = i+w; MODULO(in, TERRAIN_LENGTH); + for (j=l-1; j < TERRAIN_BREADTH; j += (l*2)) { + jp = j-1; MODULO(jp, TERRAIN_BREADTH); + jn = j+1; MODULO(jn, TERRAIN_BREADTH); + st->terrain[i][j] = + generate_terrain_value (st, st->terrain[ip][j], st->terrain[in][j], + st->terrain[i][jp], st->terrain[i][jn], w); + } + } + + for (i=start+w-1; i < end; i += (w*2)) { + ip = i-w; MODULO(ip, TERRAIN_LENGTH); + in = i+w; MODULO(in, TERRAIN_LENGTH); + for (j=2*l-1; j < TERRAIN_BREADTH; j += (l*2)) { + jp = j-1; MODULO(jp, TERRAIN_BREADTH); + jn = j+1; MODULO(jn, TERRAIN_BREADTH); + st->terrain[i][j] = + generate_terrain_value (st, st->terrain[ip][j], st->terrain[in][j], + st->terrain[i][jp], st->terrain[i][jn], w); + } + } + } +} + +/* + * double generate_curvature_value (v1, v2, w) + * + * generate curvature value near the average of v1 and v2, with perturbation + * proportional to w + */ +static double +generate_curvature_value (double v1, double v2, int w) +{ + double sum, avg, diff, ret; + int rval; + + assert (!isnan(v1) && !isnan(v2)); + + sum = v1+v2; + avg = sum/2.0; + + diff = MIN(v1 - avg, v2 - avg); + + rval = (int)diff * w; + if (rval == 0.0) return avg; + + ret = (avg -((double)rval)/500.0 + ((double)RAND(rval))/1000.0); + + assert (!isnan(ret)); + + return ret; +} + +/* + * generate_curves (start, end) + * + * generate xcurvature[i], ycurvature[i], zcurvature[i] and wideness[i] + * between start and end inclusive + */ +static void +generate_curves (struct state *st, int start, int end) +{ + int i, diff, ii, in, ip, w; + + assert (start < end); + + diff = end - start + 1; MODULO (diff, TERRAIN_LENGTH); + + if (random() % 100 == 0) + st->xcurvature[end] = 30 * random_curvature(); + else if (random() % 10 == 0) + st->xcurvature[end] = 20 * random_curvature(); + else + st->xcurvature[end] = 10 * random_curvature(); + + if (random() % 50 == 0) + st->ycurvature[end] = 20 * random_curvature(); + else if (random() % 25 == 0) + st->ycurvature[end] = 30 * random_curvature(); + else + st->ycurvature[end] = 10 * random_curvature(); + + if (random() % 3 == 0) + st->zcurvature[end] = random_twist(); + else + st->zcurvature[end] = + generate_curvature_value (st->zcurvature[end], random_twist(), 1); + + if (st->be_wormy) + st->wideness[end] = random_wideness(); + else + st->wideness[end] = + generate_curvature_value (st->wideness[end], random_wideness(), 1); + + for (w=diff/2; w >= 1; w /= 2) { + for (i=start+w-1; i < end; i+=(w*2)) { + ii = i; MODULO (ii, TERRAIN_LENGTH); + ip = i-w; MODULO (ip, TERRAIN_LENGTH); + in = i+w; MODULO (in, TERRAIN_LENGTH); + st->xcurvature[ii] = + generate_curvature_value (st->xcurvature[ip], st->xcurvature[in], w); + st->ycurvature[ii] = + generate_curvature_value (st->ycurvature[ip], st->ycurvature[in], w); + st->zcurvature[ii] = + generate_curvature_value (st->zcurvature[ip], st->zcurvature[in], w); + st->wideness[ii] = + generate_curvature_value (st->wideness[ip], st->wideness[in], w); + } + } +} + +/* + * do_bonus () + * + * choose a random bonus and perform its state transition + */ +static void +do_bonus (struct state *st) +{ + st->bonus_bright = 20; + + if (st->jamming > 0) { + st->jamming--; + st->nearest -= 2; MODULO(st->nearest, TERRAIN_LENGTH); + return; + } + + if (st->psychedelic_flag) change_colors(st); + + switch (random() % 7) { + case 0: /* switch to or from wireframe */ + st->wire_bonus = (st->wire_bonus?0:300); + break; + case 1: /* speedup */ + st->speed_bonus = 40.0; + break; + case 2: + st->spin_bonus += ROTS; + break; + case 3: + st->spin_bonus -= ROTS; + break; + case 4: /* look backwards / look forwards */ + st->flipped_at = st->nearest; + flip_direction (st); + st->backwards_bonus = (st->backwards_bonus?0:10); + break; + case 5: + change_colors(st); + break; + case 6: /* jam against the bonus a few times; deja vu! */ + st->nearest -= 2; MODULO(st->nearest, TERRAIN_LENGTH); + st->jamming = 3; + break; + default: + assert(0); + break; + } +} + +/* + * check_bonus () + * + * check if a bonus has been passed in the last frame, and handle it + */ +static void +check_bonuses (struct state *st) +{ + int i, ii, start, end; + + if (!st->bonuses_flag) return; + + if (st->step >= 0.0) { + start = st->nearest; end = st->nearest + (int)floor(st->step); + } else { + end = st->nearest; start = st->nearest + (int)floor(st->step); + } + + if (st->be_wormy) { + start += TERRAIN_LENGTH/4; + end += TERRAIN_LENGTH/4; + } + + for (i=start; i < end; i++) { + ii = i; MODULO(ii, TERRAIN_LENGTH); + if (st->bonuses[ii] == 1) do_bonus (st); + } +} + +/* + * decrement_bonuses (double time_per_frame) + * + * decrement timers associated with bonuses + */ +static void +decrement_bonuses (struct state *st, double time_per_frame) +{ + if (!st->bonuses_flag) return; + + if (st->bonus_bright > 0) st->bonus_bright-=4; + if (st->wire_bonus > 0) st->wire_bonus--; + if (st->speed_bonus > 0) st->speed_bonus -= 2.0; + + if (st->spin_bonus > 10) st->spin_bonus -= (int)(st->step*13.7); + else if (st->spin_bonus < -10) st->spin_bonus += (int)(st->step*11.3); + + if (st->backwards_bonus > 1) st->backwards_bonus--; + else if (st->backwards_bonus == 1) { + st->nearest += 2*(MAX(st->flipped_at, st->nearest) - MIN(st->flipped_at,st->nearest)); + MODULO(st->nearest, TERRAIN_LENGTH); + flip_direction (st); + st->backwards_bonus = 0; + } +} + +/* + * set_bonuses (start, end) + * + * choose if to and where to set a bonus between i=start and i=end inclusive + */ +static void +set_bonuses (struct state *st, int start, int end) +{ + int i, diff, ii; + + if (!st->bonuses_flag) return; + + assert (start < end); + + diff = end - start; + + for (i=start; i <= end; i++) { + ii = i; if (ii>=TERRAIN_LENGTH) ii -= TERRAIN_LENGTH; + st->bonuses[ii] = 0; + } + if (random() % 4 == 0) { + i = start + RAND(diff-3); + ii = i; if (ii>=TERRAIN_LENGTH) ii -= TERRAIN_LENGTH; + st->bonuses[ii] = 2; /* marker */ + ii = i+3; if (ii>=TERRAIN_LENGTH) ii -= TERRAIN_LENGTH; + st->bonuses[ii] = 1; /* real thing */ + } +} + +/* + * regenerate_terrain () + * + * regenerate a portion of the terrain map of length TERRAIN_LENGTH/4 iff + * we just passed between two quarters of the terrain. + * + * choose the kind of terrain to produce, produce it and wrap the tunnel + */ +static void +regenerate_terrain (struct state *st) +{ + int start, end; + int passed; + + passed = st->nearest % (TERRAIN_LENGTH/4); + + if (st->speed == 0.0 || + (st->speed > 0.0 && passed > (int)st->step) || + (st->speed < 0.0 && (TERRAIN_LENGTH/4)-passed > (int)fabs(st->step))) { + + return; + } + + end = st->nearest - passed - 1; MODULO(end, TERRAIN_LENGTH); + start = end - TERRAIN_LENGTH/4 + 1; MODULO(start, TERRAIN_LENGTH); + + if (DEBUG_FLAG) printf ("Regenerating [%d - %d]\n", start, end); + + set_bonuses (st, start, end); + + switch (random() % 64) { + case 0: + case 1: + generate_terrain (st, start, end, 1); + generate_smooth (st, start, + start + TERRAIN_LENGTH/8 + (random() % TERRAIN_LENGTH/8)); + break; + case 2: + generate_smooth (st, start, end); + generate_terrain (st, start, end, 4); break; + case 3: + generate_smooth (st, start, end); + generate_terrain (st, start, end, 2); break; + default: + generate_terrain (st, start, end, 1); + } + + if (random() % 16 == 0) { + generate_straight (st, start, end); + } else { + generate_curves (st, start, end); + } + + wrap_tunnel (st, start, end); +} + +/* + * init_terrain () + * + * initialise the terrain map for the beginning of the demo + */ +static void +init_terrain (struct state *st) +{ + int i, j; + + for (i=0; i < TERRAIN_LENGTH; i++) { + for (j=0; j < TERRAIN_BREADTH; j++) { + st->terrain[i][j] = 0; + } + } + + st->terrain[TERRAIN_LENGTH-1][0] = - (random() % 300); + st->terrain[TERRAIN_LENGTH-1][TERRAIN_BREADTH/2] = - (random() % 300); + + generate_smooth (st, 0, TERRAIN_LENGTH-1); + generate_terrain (st, 0, TERRAIN_LENGTH/4 -1, 4); + generate_terrain (st, TERRAIN_LENGTH/4, TERRAIN_LENGTH/2 -1, 2); + generate_terrain (st, TERRAIN_LENGTH/2, 3*TERRAIN_LENGTH/4 -1, 1); + generate_smooth (st, 3*TERRAIN_LENGTH/4, TERRAIN_LENGTH-1); +} + +/* + * init_curves () + * + * initialise the curvatures and wideness for the beginning of the demo. + */ +static void +init_curves (struct state *st) +{ + int i; + + for (i=0; i < TERRAIN_LENGTH-1; i++) { + st->xcurvature[i] = 0.0; + st->ycurvature[i] = 0.0; + st->zcurvature[i] = 0.0; + } + + st->xcurvature[TERRAIN_LENGTH-1] = random_curvature(); + st->ycurvature[TERRAIN_LENGTH-1] = random_curvature(); + st->zcurvature[TERRAIN_LENGTH-1] = random_twist(); + + generate_straight (st, 0, TERRAIN_LENGTH/4-1); + generate_curves (st, TERRAIN_LENGTH/4, TERRAIN_LENGTH/2-1); + generate_curves (st, TERRAIN_LENGTH/2, 3*TERRAIN_LENGTH/4-1); + generate_straight (st, 3*TERRAIN_LENGTH/4, TERRAIN_LENGTH-1); + +} + +/* + * render_quads (dpy, d, t, dt, i) + * + * renders the quadrilaterals from perspective depth t to t+dt. + * i is passed as a hint, where i corresponds to t as asserted. + */ +static void +render_quads (struct state *st, Drawable d, int t, int dt, int i) +{ + int j, t2, j2, in; + int index; + XPoint points[4]; + GC gc; + + assert (i == (st->nearest - (t + dt) + TERRAIN_LENGTH) % TERRAIN_LENGTH); + + in = i + 1; MODULO(in, TERRAIN_LENGTH); + + for (j=0; j < TERRAIN_BREADTH; j+=dt) { + t2 = t+dt; if (t2 >= TERRAIN_LENGTH) t2 -= TERRAIN_LENGTH; + j2 = j+dt; if (j2 >= TERRAIN_BREADTH) j2 -= TERRAIN_BREADTH; + points[0].x = st->xvals[t][j]; points[0].y = st->yvals[t][j]; + points[1].x = st->xvals[t2][j]; points[1].y = st->yvals[t2][j]; + points[2].x = st->xvals[t2][j2]; points[2].y = st->yvals[t2][j2]; + points[3].x = st->xvals[t][j2]; points[3].y = st->yvals[t][j2]; + + index = st->bonus_bright + st->ncolors/3 + + t*(t*INTERP + st->pindex) * st->ncolors / + (3*TERRAIN_LENGTH*TERRAIN_PDIST); + if (!wireframe) { + index += (int)((points[0].y - points[3].y) / 8); + index += (int)((st->worldx[i][j] - st->worldx[in][j]) / 40); + index += (int)((st->terrain[in][j] - st->terrain[i][j]) / 100); + } + if (st->be_wormy && st->psychedelic_flag) index += st->ncolors/4; + + if (st->ncolors > MAX_COLORS) abort(); + index = MIN (index, st->ncolors-1); + index = MAX (index, 0); + + if (st->bonuses[i]) { + XSetClipMask (st->dpy, st->bonus_gcs[index], None); + } + + if (wireframe) { + if (st->bonuses[i]) gc = st->bonus_gcs[index]; + else gc = st->ground_gcs[index]; + XDrawLines (st->dpy, d, gc, points, 4, CoordModeOrigin); + } else { + if (st->bonuses[i]) + gc = st->bonus_gcs[index]; + else if ((st->direction>0 && j < TERRAIN_BREADTH/8) || + (j > TERRAIN_BREADTH/8 && j < 3*TERRAIN_BREADTH/8-1) || + (st->direction < 0 && j > 3*TERRAIN_BREADTH/8-1 && + j < TERRAIN_BREADTH/2) || + st->terrain[i][j] == STEEL_ELEVATION || + st->wideness[in] - st->wideness[i] > 200) + gc = st->ground_gcs[index]; + else + gc = st->wall_gcs[index]; + + XFillPolygon (st->dpy, d, gc, points, 4, Nonconvex, CoordModeOrigin); + } + } +} + +/* + * render_pentagons (dpy, d, t, dt, i) + * + * renders the pentagons from perspective depth t to t+dt. + * i is passed as a hint, where i corresponds to t as asserted. + */ +static void +render_pentagons (struct state *st, Drawable d, int t, int dt, int i) +{ + int j, t2, j2, j3, in; + int index; + XPoint points[5]; + GC gc; + + assert (i == (st->nearest -t + TERRAIN_LENGTH) % TERRAIN_LENGTH); + + in = i + 1; MODULO(in, TERRAIN_LENGTH); + + for (j=0; j < TERRAIN_BREADTH; j+=dt*2) { + t2 = t+(dt*2); if (t2 >= TERRAIN_LENGTH) t2 -= TERRAIN_LENGTH; + j2 = j+dt; if (j2 >= TERRAIN_BREADTH) j2 -= TERRAIN_BREADTH; + j3 = j+dt+dt; if (j3 >= TERRAIN_BREADTH) j3 -= TERRAIN_BREADTH; + points[0].x = st->xvals[t][j]; points[0].y = st->yvals[t][j]; + points[1].x = st->xvals[t2][j]; points[1].y = st->yvals[t2][j]; + points[2].x = st->xvals[t2][j2]; points[2].y = st->yvals[t2][j2]; + points[3].x = st->xvals[t2][j3]; points[3].y = st->yvals[t2][j3]; + points[4].x = st->xvals[t][j3]; points[4].y = st->yvals[t][j3]; + + index = st->bonus_bright + st->ncolors/3 + + t*(t*INTERP + st->pindex) * st->ncolors / + (3*TERRAIN_LENGTH*TERRAIN_PDIST); + if (!wireframe) { + index += (int)((points[0].y - points[3].y) / 8); + index += (int)((st->worldx[i][j] - st->worldx[in][j]) / 40); + index += (int)((st->terrain[in][j] - st->terrain[i][j]) / 100); + } + if (st->be_wormy && st->psychedelic_flag) index += st->ncolors/4; + + index = MIN (index, st->ncolors-1); + index = MAX (index, 0); + + if (st->bonuses[i]) { + XSetClipMask (st->dpy, st->bonus_gcs[index], None); + } + + if (wireframe) { + if (st->bonuses[i]) gc = st->bonus_gcs[index]; + else gc = st->ground_gcs[index]; + XDrawLines (st->dpy, d, gc, points, 5, CoordModeOrigin); + } else { + if (st->bonuses[i]) + gc = st->bonus_gcs[index]; + else if (j < TERRAIN_BREADTH/8 || + (j > TERRAIN_BREADTH/8 && j < 3*TERRAIN_BREADTH/8-1) || + st->terrain[i][j] == STEEL_ELEVATION || + st->wideness[in] - st->wideness[i] > 200) + gc = st->ground_gcs[index]; + else + gc = st->wall_gcs[index]; + + XFillPolygon (st->dpy, d, gc, points, 5, Complex, CoordModeOrigin); + } + } +} + +/* + * render_block (dpy, d, gc, t) + * + * render a filled polygon at perspective depth t using the given GC + */ +static void +render_block (struct state *st, Drawable d, GC gc, int t) +{ + int i; + + XPoint erase_points[TERRAIN_BREADTH/2]; + + for (i=0; i < TERRAIN_BREADTH/2; i++) { + erase_points[i].x = st->xvals[t][i*2]; + erase_points[i].y = st->yvals[t][i*2]; + } + + XFillPolygon (st->dpy, d, gc, erase_points, + TERRAIN_BREADTH/2, Complex, CoordModeOrigin); +} + +/* + * regenerate_stars_mask (dpy, t) + * + * regenerate the clip mask 'stars_mask' for drawing the bonus stars at + * random positions within the bounding box at depth t + */ +static void +regenerate_stars_mask (struct state *st, int t) +{ + int i, w, h, a, b, l1, l2; + const int lim = st->width*TERRAIN_LENGTH/(300*(TERRAIN_LENGTH-t)); + + w = st->maxx[t] - st->minx[t]; + h = st->maxy[t] - st->miny[t]; + + if (w<6||h<6) return; + + XFillRectangle (st->dpy, st->stars_mask, st->stars_erase_gc, + 0, 0, st->width, st->height); + + l1 = (t>3*TERRAIN_LENGTH/4?2:1); + l2 = (t>7*TERRAIN_LENGTH/8?2:1); + + for (i=0; i < lim; i++) { + a = RAND(w); b = RAND(h); + XDrawLine (st->dpy, st->stars_mask, st->stars_gc, + st->minx[t]+a-l1, st->miny[t]+b, st->minx[t]+a+l1, st->miny[t]+b); + XDrawLine (st->dpy, st->stars_mask, st->stars_gc, + st->minx[t]+a, st->miny[t]+b-l1, st->minx[t]+a, st->miny[t]+b+l1); + } + for (i=0; i < lim; i++) { + a = RAND(w); b = RAND(h); + XDrawLine (st->dpy, st->stars_mask, st->stars_gc, + st->minx[t]+a-l2, st->miny[t]+b, st->minx[t]+a+l2, st->miny[t]+b); + XDrawLine (st->dpy, st->stars_mask, st->stars_gc, + st->minx[t]+a, st->miny[t]+b-l2, st->minx[t]+a, st->miny[t]+b+l2); + } +} + +/* + * render_bonus_block (dpy, d, t, i) + * + * draw the bonus stars at depth t. + * i is passed as a hint, where i corresponds to t as asserted. + */ +static void +render_bonus_block (struct state *st, Drawable d, int t, int i) +{ + int bt; + + assert (i == (st->nearest -t + TERRAIN_LENGTH) % TERRAIN_LENGTH); + + if (!st->bonuses[i] || wireframe) return; + + regenerate_stars_mask (st, t); + + bt = t * st->nr_bonus_colors / (2*TERRAIN_LENGTH); + + XSetClipMask (st->dpy, st->bonus_gcs[bt], st->stars_mask); + + render_block (st, d, st->bonus_gcs[bt], t); +} + +static int +begin_at (struct state *st) +{ + int t; + int max_minx=0, min_maxx=st->width, max_miny=0, min_maxy=st->height; + + for (t=TERRAIN_LENGTH-1; t > 0; t--) { + max_minx = MAX (max_minx, st->minx[t]); + min_maxx = MIN (min_maxx, st->maxx[t]); + max_miny = MAX (max_miny, st->miny[t]); + min_maxy = MIN (min_maxy, st->maxy[t]); + + if (max_miny >= min_maxy || max_minx >= min_maxx) break; + } + + return t; +} + +/* + * render_speedmine (dpy, d) + * + * render the current frame. + */ +static void +render_speedmine (struct state *st, Drawable d) +{ + int t, i=st->nearest, dt=1; + GC gc; + + assert (st->nearest >= 0 && st->nearest < TERRAIN_LENGTH); + + if (st->be_wormy || wireframe) { + XFillRectangle (st->dpy, d, st->erase_gc, 0, 0, st->width, st->height); + + dt=4; + for (t=0; t < TERRAIN_LENGTH/4; t+=dt) { + render_bonus_block (st, d, t, i); + i -= dt; MODULO(i, TERRAIN_LENGTH); + render_quads (st, d, t, dt, i); + } + + assert (t == TERRAIN_LENGTH/4); + } else { + t = MAX(begin_at(st), TERRAIN_LENGTH/4); + /*t = TERRAIN_LENGTH/4; dt = 2; */ + /*dt = (t >= 3*TERRAIN_LENGTH/4 ? 1 : 2);*/ + i = (st->nearest -t + TERRAIN_LENGTH) % TERRAIN_LENGTH; + render_block (st, d, st->tunnelend_gc, t); + } + + dt=2; + + if (t == TERRAIN_LENGTH/4) + render_pentagons (st, d, t, dt, i); + + for (; t < 3*TERRAIN_LENGTH/4; t+=dt) { + render_bonus_block (st, d, t, i); + i -= dt; MODULO(i, TERRAIN_LENGTH); + render_quads (st, d, t, dt, i); + } + + dt=1; + if (st->be_wormy) { + for (; t < TERRAIN_LENGTH-(1+(st->pindexpindexcrosshair_flag) { + gc = (wireframe ? st->bonus_gcs[st->nr_bonus_colors/2] : st->erase_gc); + XFillRectangle (st->dpy, d, gc, + st->width/2+(st->xoffset)-8, st->height/2+(st->yoffset*2)-1, 16, 3); + XFillRectangle (st->dpy, d, gc, + st->width/2+(st->xoffset)-1, st->height/2+(st->yoffset*2)-8, 3, 16); + } + +} + +/* + * move (step) + * + * move to the position for the next frame, and modify the state variables + * st->nearest, pindex, pos, speed + */ +static void +move (struct state *st) +{ + double dpos; + + st->pos += st->step; + dpos = SIGN3(st->pos) * floor(fabs(st->pos)); + + st->pindex += SIGN3(effective_speed) + INTERP; + while (st->pindex >= INTERP) { + st->nearest --; + st->pindex -= INTERP; + } + while (st->pindex < 0) { + st->nearest ++; + st->pindex += INTERP; + } + + st->nearest += dpos; MODULO(st->nearest, TERRAIN_LENGTH); + + st->pos -= dpos; + + st->accel = st->thrust + st->ycurvature[st->nearest] * st->gravity; + st->speed += st->accel; + if (st->speed > st->maxspeed) st->speed = st->maxspeed; + if (st->speed < -st->maxspeed) st->speed = -st->maxspeed; +} + +/* + * speedmine (dpy, window) + * + * do everything required for one frame of the demo + */ +static unsigned long +speedmine_draw (Display *dpy, Window window, void *closure) +{ + struct state *st = (struct state *) closure; + double elapsed, time_per_frame = 0.04; + + regenerate_terrain (st); + + perspective (st); + + render_speedmine (st, st->dbuf); + if (st->dbuf != st->window) + XCopyArea (st->dpy, st->dbuf, st->window, st->draw_gc, 0, 0, st->width, st->height, 0, 0); + + st->fps_end = get_time(st); + st->nframes++; + st->total_nframes++; + + if (st->fps_end > st->fps_start + 0.5) { + elapsed = st->fps_end - st->fps_start; + st->fps_start = get_time(st); + + time_per_frame = elapsed / st->nframes - st->delay*1e-6; + st->fps = st->nframes / elapsed; + if (DEBUG_FLAG) { + printf ("%f s elapsed\t%3f s/frame\t%.1f FPS\n", elapsed, + time_per_frame, st->fps); + } + st->step = effective_speed * elapsed; + + st->nframes = 0; + } + + + move (st); + + decrement_bonuses (st, time_per_frame); + + check_bonuses (st); + + return st->delay; +} + +/* + * speedmine_color_ramp (dpy, gcs, colors, ncolors, s1, s2, v1, v2) + * + * generate a color ramp of up to *ncolors between randomly chosen hues, + * varying from saturation s1 to s2 and value v1 to v2, placing the colors + * in 'colors' and creating corresponding GCs in 'gcs'. + * + * The number of colors actually allocated is returned in ncolors. + */ +static void +speedmine_color_ramp (struct state *st, GC *gcs, XColor * colors, + int *ncolors, double s1, double s2, double v1, double v2) +{ + XGCValues gcv; + int h1, h2; + unsigned long flags; + int i; + + assert (*st->ncolors >= 0); + assert (s1 >= 0.0 && s1 <= 1.0 && v1 >= 0.0 && v2 <= 1.0); + + if (st->psychedelic_flag) { + h1 = RAND(360); h2 = (h1 + 180) % 360; + } else { + h1 = h2 = RAND(360); + } + + make_color_ramp (st->dpy, st->cmap, + h1, s1, v1, h2, s2, v2, + colors, ncolors, False, True, False); + + flags = GCForeground; + for (i=0; i < *ncolors; i++) { + gcv.foreground = colors[i].pixel; + if (gcs[i]) XFreeGC (st->dpy, gcs[i]); + gcs[i] = XCreateGC (st->dpy, st->dbuf, flags, &gcv); + } + +} + +/* + * change_colors () + * + * perform the color changing bonus. New colors are allocated for the + * walls and bonuses, and if the 'psychedelic' option is set then new + * colors are also chosen for the ground. + */ +static void +change_colors (struct state *st) +{ + double s1, s2; + + if (st->psychedelic_flag) { + free_colors (st->dpy, st->cmap, st->bonus_colors, st->nr_bonus_colors); + free_colors (st->dpy, st->cmap, st->wall_colors, st->nr_wall_colors); + free_colors (st->dpy, st->cmap, st->ground_colors, st->nr_ground_colors); + s1 = 0.4; s2 = 0.9; + + st->ncolors = MAX_COLORS; + speedmine_color_ramp (st, st->ground_gcs, st->ground_colors, + &st->ncolors, 0.0, 0.8, 0.0, 0.9); + st->nr_ground_colors = st->ncolors; + } else { + free_colors (st->dpy, st->cmap, st->bonus_colors, st->nr_bonus_colors); + free_colors (st->dpy, st->cmap, st->wall_colors, st->nr_wall_colors); + st->ncolors = st->nr_ground_colors; + + s1 = 0.0; s2 = 0.6; + } + + st->ncolors = MAX_COLORS; + speedmine_color_ramp (st, st->wall_gcs, st->wall_colors, &st->ncolors, + s1, s2, 0.0, 0.9); + st->nr_wall_colors = st->ncolors; + + st->ncolors = MAX_COLORS; + speedmine_color_ramp (st, st->bonus_gcs, st->bonus_colors, &st->ncolors, + 0.6, 0.9, 0.4, 1.0); + st->nr_bonus_colors = st->ncolors; +} + +/* + * init_psychedelic_colors (dpy, window, cmap) + * + * initialise a psychedelic colormap + */ +static void +init_psychedelic_colors (struct state *st) +{ + XGCValues gcv; + + gcv.foreground = get_pixel_resource (st->dpy, st->cmap, "tunnelend", "TunnelEnd"); + st->tunnelend_gc = XCreateGC (st->dpy, st->window, GCForeground, &gcv); + + st->ncolors = MAX_COLORS; + speedmine_color_ramp (st, st->ground_gcs, st->ground_colors, &st->ncolors, + 0.0, 0.8, 0.0, 0.9); + st->nr_ground_colors = st->ncolors; + + st->ncolors = MAX_COLORS; + speedmine_color_ramp (st, st->wall_gcs, st->wall_colors, &st->ncolors, + 0.0, 0.6, 0.0, 0.9); + st->nr_wall_colors = st->ncolors; + + st->ncolors = MAX_COLORS; + speedmine_color_ramp (st, st->bonus_gcs, st->bonus_colors, &st->ncolors, + 0.6, 0.9, 0.4, 1.0); + st->nr_bonus_colors = st->ncolors; +} + +/* + * init_colors (dpy, window, cmap) + * + * initialise a normal colormap + */ +static void +init_colors (struct state *st) +{ + XGCValues gcv; + XColor dark, light; + int h1, h2; + double s1, s2, v1, v2; + unsigned long flags; + int i; + + gcv.foreground = get_pixel_resource (st->dpy, st->cmap, "tunnelend", "TunnelEnd"); + st->tunnelend_gc = XCreateGC (st->dpy, st->window, GCForeground, &gcv); + + st->ncolors = MAX_COLORS; + + dark.pixel = get_pixel_resource (st->dpy, st->cmap, "darkground", "DarkGround"); + XQueryColor (st->dpy, st->cmap, &dark); + + light.pixel = get_pixel_resource (st->dpy, st->cmap, "lightground", "LightGround"); + XQueryColor (st->dpy, st->cmap, &light); + + rgb_to_hsv (dark.red, dark.green, dark.blue, &h1, &s1, &v1); + rgb_to_hsv (light.red, light.green, light.blue, &h2, &s2, &v2); + make_color_ramp (st->dpy, st->cmap, h1, s1, v1, h2, s2, v2, + st->ground_colors, &st->ncolors, False, True, False); + st->nr_ground_colors = st->ncolors; + + flags = GCForeground; + for (i=0; i < st->ncolors; i++) { + gcv.foreground = st->ground_colors[i].pixel; + st->ground_gcs[i] = XCreateGC (st->dpy, st->dbuf, flags, &gcv); + } + + st->ncolors = MAX_COLORS; + speedmine_color_ramp (st, st->wall_gcs, st->wall_colors, &st->ncolors, + 0.0, 0.6, 0.0, 0.9); + st->nr_wall_colors = st->ncolors; + + st->ncolors = MAX_COLORS; + speedmine_color_ramp (st, st->bonus_gcs, st->bonus_colors, &st->ncolors, + 0.6, 0.9, 0.4, 1.0); + st->nr_bonus_colors = st->ncolors; +} + +/* + * print_stats () + * + * print out average FPS stats for the demo + */ +#if 0 +static void +print_stats (struct state *st) +{ + if (st->total_nframes >= 1) + printf ("Rendered %d frames averaging %f FPS\n", st->total_nframes, + st->total_nframes / get_time(st)); +} +#endif + +/* + * init_speedmine (dpy, window) + * + * initialise the demo + */ +static void * +speedmine_init (Display *dpy, Window window) +{ + struct state *st = (struct state *) calloc (1, sizeof(*st)); + XGCValues gcv; + XWindowAttributes xgwa; + int i; + double th; + int wide; + + st->dpy = dpy; + st->window = window; + + st->speed = 1.1; + st->accel = 0.00000001; + st->direction = FORWARDS; + st->orientation = (17*ROTS)/22; + + XGetWindowAttributes (st->dpy, st->window, &xgwa); + st->cmap = xgwa.colormap; + st->width = xgwa.width; + st->height = xgwa.height; + + st->verbose_flag = get_boolean_resource (st->dpy, "verbose", "Boolean"); + +# ifdef HAVE_COCOA /* Don't second-guess Quartz's double-buffering */ + st->dbuf = st->window; +#else + st->dbuf = XCreatePixmap (st->dpy, st->window, st->width, st->height, xgwa.depth); +#endif + st->stars_mask = XCreatePixmap (st->dpy, st->window, st->width, st->height, 1); + + gcv.foreground = st->default_fg_pixel = + get_pixel_resource (st->dpy, st->cmap, "foreground", "Foreground"); + st->draw_gc = XCreateGC (st->dpy, st->window, GCForeground, &gcv); + gcv.foreground = 1; + st->stars_gc = XCreateGC (st->dpy, st->stars_mask, GCForeground, &gcv); + + gcv.foreground = get_pixel_resource (st->dpy, st->cmap, "background", "Background"); + st->erase_gc = XCreateGC (st->dpy, st->dbuf, GCForeground, &gcv); + gcv.foreground = 0; + st->stars_erase_gc = XCreateGC (st->dpy, st->stars_mask, GCForeground, &gcv); + + st->wire_flag = get_boolean_resource (st->dpy, "wire", "Boolean"); + + st->psychedelic_flag = get_boolean_resource (st->dpy, "psychedelic", "Boolean"); + + st->delay = get_integer_resource(st->dpy, "delay", "Integer"); + + st->smoothness = get_integer_resource(st->dpy, "smoothness", "Integer"); + if (st->smoothness < 1) st->smoothness = 1; + + st->maxspeed = get_float_resource(st->dpy, "maxspeed", "Float"); + st->maxspeed *= 0.01; + st->maxspeed = fabs(st->maxspeed); + + st->thrust = get_float_resource(st->dpy, "thrust", "Float"); + st->thrust *= 0.2; + + st->gravity = get_float_resource(st->dpy, "gravity", "Float"); + st->gravity *= 0.002/9.8; + + st->vertigo = get_float_resource(st->dpy, "vertigo", "Float"); + st->vertigo *= 0.2; + + st->curviness = get_float_resource(st->dpy, "curviness", "Float"); + st->curviness *= 0.25; + + st->twistiness = get_float_resource(st->dpy, "twistiness", "Float"); + st->twistiness *= 0.125; + + st->terrain_flag = get_boolean_resource (st->dpy, "terrain", "Boolean"); + st->widening_flag = get_boolean_resource (st->dpy, "widening", "Boolean"); + st->bumps_flag = get_boolean_resource (st->dpy, "bumps", "Boolean"); + st->bonuses_flag = get_boolean_resource (st->dpy, "bonuses", "Boolean"); + st->crosshair_flag = get_boolean_resource (st->dpy, "crosshair", "Boolean"); + + st->be_wormy = get_boolean_resource (st->dpy, "worm", "Boolean"); + if (st->be_wormy) { + st->maxspeed *= 1.43; + st->thrust *= 10; + st->gravity *= 3; + st->vertigo *= 0.5; + st->smoothness *= 2; + st->curviness *= 2; + st->twistiness *= 2; + st->psychedelic_flag = True; + st->crosshair_flag = False; + } + + if (st->psychedelic_flag) init_psychedelic_colors (st); + else init_colors (st); + + for (i=0; icostab[i] = cos(th); + st->sintab[i] = sin(th); + } + + wide = random_wideness(); + + for (i=0; i < TERRAIN_LENGTH; i++) { + st->wideness[i] = wide; + st->bonuses[i] = 0; + } + + init_terrain (st); + init_curves (st); + wrap_tunnel (st, 0, TERRAIN_LENGTH-1); + +#if 0 + if (DEBUG_FLAG || st->verbose_flag) atexit(print_stats); +#endif + + st->step = effective_speed; + + init_time (st); + + return st; +} + + +static void +speedmine_reshape (Display *dpy, Window window, void *closure, + unsigned int w, unsigned int h) +{ + struct state *st = (struct state *) closure; + st->width = w; + st->height = h; + if (st->dbuf != st->window) { + XWindowAttributes xgwa; + XGetWindowAttributes (st->dpy, st->window, &xgwa); + XFreePixmap (dpy, st->dbuf); + st->dbuf = XCreatePixmap (st->dpy, st->window, + st->width, st->height, xgwa.depth); + } +} + +static Bool +speedmine_event (Display *dpy, Window window, void *closure, XEvent *event) +{ + return False; +} + +static void +speedmine_free (Display *dpy, Window window, void *closure) +{ + struct state *st = (struct state *) closure; + free (st); +} + + + +/* + * Down the speedmine, you'll find speed + * to satisfy your moving needs; + * So if you're looking for a blast + * then hit the speedmine, really fast. + */ + +/* + * Speedworm likes to choke and spit + * and chase his tail, and dance a bit + * he really is a funky friend; + * he's made of speed from end to end. + */ + + +static const char *speedmine_defaults [] = { + ".verbose: False", + "*worm: False", + "*wire: False", + ".background: black", + ".foreground: white", + "*darkground: #101010", + "*lightground: #a0a0a0", + "*tunnelend: #000000", + "*delay: 30000", + "*maxspeed: 700", + "*thrust: 1.0", + "*gravity: 9.8", + "*vertigo: 1.0", + "*terrain: True", + "*smoothness: 6", + "*curviness: 1.0", + "*twistiness: 1.0", + "*widening: True", + "*bumps: True", + "*bonuses: True", + "*crosshair: True", + "*psychedelic: False", + 0 +}; + +static XrmOptionDescRec speedmine_options [] = { + { "-verbose", ".verbose", XrmoptionNoArg, "True"}, + { "-worm", ".worm", XrmoptionNoArg, "True"}, + { "-wireframe", ".wire", XrmoptionNoArg, "True"}, + { "-no-wireframe", ".wire", XrmoptionNoArg, "False"}, + { "-darkground", ".darkground", XrmoptionSepArg, 0 }, + { "-lightground", ".lightground", XrmoptionSepArg, 0 }, + { "-tunnelend", ".tunnelend", XrmoptionSepArg, 0 }, + { "-delay", ".delay", XrmoptionSepArg, 0 }, + { "-maxspeed", ".maxspeed", XrmoptionSepArg, 0 }, + { "-thrust", ".thrust", XrmoptionSepArg, 0 }, + { "-gravity", ".gravity", XrmoptionSepArg, 0 }, + { "-vertigo", ".vertigo", XrmoptionSepArg, 0 }, + { "-terrain", ".terrain", XrmoptionNoArg, "True"}, + { "-no-terrain", ".terrain", XrmoptionNoArg, "False"}, + { "-smoothness", ".smoothness", XrmoptionSepArg, 0 }, + { "-curviness", ".curviness", XrmoptionSepArg, 0 }, + { "-twistiness", ".twistiness", XrmoptionSepArg, 0 }, + { "-widening", ".widening", XrmoptionNoArg, "True"}, + { "-no-widening", ".widening", XrmoptionNoArg, "False"}, + { "-bumps", ".bumps", XrmoptionNoArg, "True"}, + { "-no-bumps", ".bumps", XrmoptionNoArg, "False"}, + { "-bonuses", ".bonuses", XrmoptionNoArg, "True"}, + { "-no-bonuses", ".bonuses", XrmoptionNoArg, "False"}, + { "-crosshair", ".crosshair", XrmoptionNoArg, "True"}, + { "-no-crosshair", ".crosshair", XrmoptionNoArg, "False"}, + { "-psychedelic", ".psychedelic", XrmoptionNoArg, "True"}, + { "-no-psychedelic", ".psychedelic", XrmoptionNoArg, "False"}, + { 0, 0, 0, 0 } +}; + + +XSCREENSAVER_MODULE ("SpeedMine", speedmine) + +/* vim: ts=4 + */ diff --git a/hacks/speedmine.man b/hacks/speedmine.man new file mode 100644 index 00000000..c5ce919e --- /dev/null +++ b/hacks/speedmine.man @@ -0,0 +1,246 @@ +.de EX \"Begin example +.ne 5 +.if n .sp 1 +.if t .sp .5 +.nf +.in +.5i +.. +.de EE +.fi +.in -.5i +.if n .sp 1 +.if t .sp .5 +.. +.TH XScreenSaver 1 "23-Apr-01" "X Version 11" +.SH NAME +speedmine - simulates speeding down a rocky mineshaft, or a funky dancing worm +.SH SYNOPSIS +.B speedmine +[\-display \fIhost:display.screen\fP] [\-root] [\-window] +[\-install] [\-noinstall] [\-visual \fIvisual\fP] [\-wire] [\-nowire] +[\-worm] +[\-foreground \fIcolor\fP] [\-background \fIcolor\fP] [\-darkground \fIcolor\fP] [\-lightground \fIcolor\fP] [\-tunnelend \fIcolor\fP] [\-delay \fImicroseconds\fP] [\-maxspeed \fInumber\fP] [\-thrust \fInumber\fP] [\-gravity \fInumber\fP] [\-vertigo \fInumber\fP] [\-terrain] [\-noterrain] [\-smoothness \fInumber\fP] [\-curviness \fInumber\fP] [\-twistiness \fInumber\fP] [\-widening] [\-nowidening] [\-bumps] [\-nobumps] [\-bonuses] [\-crosshair] [\-nocrosshair] [\-psychedelic] [\-nopsychedelic] +[\-fps] +.SH DESCRIPTION +.TP 8 +Speedmine! + +Down the speedmine, you'll find speed + +to satisfy your moving needs; + +So if you're looking for a blast + +then hit the speedmine, really fast. +.PP +Speedworm loves you. + +Speedworm likes to bump and grind + +and chase her tail, and dance around + +she really is a funky friend; + +she's made of speed from end to end. +.PP +You can configure stuff +either with command-line options or X resources. +.SH OPTIONS +.TP 8 +.B \-display \fIhost:display.screen\fP +Specifies which X display we should use (see the section DISPLAY NAMES in +.BR X (1) +for more information about this option). +.TP 8 +.B \-root +Draw on the root window. +.TP 8 +.B \-window +Draw on a newly-created window. This is the default. +.TP 8 +.B \-install +Install a private colormap for the window. +.TP 8 +.B \-noinstall +Don't install a private colormap for the window. +.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. +Possible choices include + +.RS +default, best, mono, monochrome, gray, grey, color, staticgray, staticcolor, +truecolor, grayscale, greyscale, pseudocolor, directcolor, \fInumber\fP + +If a decimal or hexadecimal number is used, +.BR XGetVisualInfo (3X) +is consulted to obtain the required visual. +.RE +.TP 8 +.B \-worm +Be a happy spastic worm instead of a tunnel. +.TP 8 +.B \-wire +Specifies that the tunnel/worm should always be rendered in wireframe style. +.TP 8 +.B \-nowire +Specifies that the tunnel/worm should be rendered normally. Note that +tunnel rendering may still temporarily switch to wireframe style when +a wireframe bonus is hit, if +.B bonuses +are enabled. +.TP 8 +.B \-foreground \fIcolor\fP +Specifies the default foreground color. +.TP 8 +.B \-background \fIcolor\fP +Specifies the default background color. +.TP 8 +.B \-darkground \fIcolor\fP +Specifies the color of the darkest portions of the ground (or the +worm's belly.) The ground/belly is colored by a gradient between +.B darkground +and +.B lightground. +.TP 8 +.B \-lightground \fIcolor\fP +Specifies the color of the lightest portions of the ground/belly. +The ground/belly is colored by a gradient between +.B darkground +and +.B lightground. +.TP 8 +.B \-tunnelend \fIcolor\fP +Specifies the color of the light at the end of the tunnel. +.TP 8 +.B \-delay \fImicroseconds\fP +Specifies the delay between drawing successive frames. If you do not specify +.BR -sync , +some X servers may batch up several drawing operations together, +producing a less smooth effect. This is more likely to happen +in monochrome mode (on monochrome servers or when +.B \-mono +is specified). +.TP 8 +.B -maxspeed \fInumber\fP +Specifies an upper bound on the speed of normal movement. This does not +affect the speed that may be attained when hitting a speed bonus. +.TP 8 +.B -thrust \fInumber\fP +Specifies the thrust constantly applied. Positive numbers indicate a forwards +thrust, negative numbers indicate a backwards thrust. +.TP 8 +.B -gravity \fInumber\fP +Specifies the effect of gravity. Larger numbers will increase acceleration +downhill and decrease acceleration uphill. +.TP 8 +.B -vertigo \fInumber\fP +Specifies to what level the demo should accentuate the curvature and +windiness of the tunnel or worm. +.TP 8 +.B -terrain +Continuously generate a fractal terrain to simulate the rockiness of the +tunnel walls, or the texture of the worm's skin. +.TP 8 +.B -noterrain +Do not generate terrain. When this option is set, all surfaces are flat. +.TP 8 +.B -smoothness \fInumber\fP +When +.BR -terrain +is set, specifies how smooth the walls or skin are. +.TP 8 +.B -curviness \fInumber\fP +Controls how much the generated tunnel (or worm) should curve left +and right, and dip up and down. +.TP 8 +.B -twistiness \fInumber\fP +Controls how much the generated tunnel (or worm) twists around itself. +.TP 8 +.B -widening +Specifies that the generated tunnel (or worm) may vary in width. +.TP 8 +.B -nowidening +Specifies that the average width should be kept constant. +.TP 8 +.B -bumps +Indicates that the simulation should take the bumpiness of the ground into +account and allow the animation to shake and rattle when travelling over +rough ground. Or that the worm should be allowed to bump around and +shake her booty. +.TP 8 +.B -nobumps +Indicates that the bumpiness of the ground should be ignored, such that the +simulation will glide through the tunnel. Or that the worm should calm +down and behave herself. +.TP 8 +.B -bonuses +Indicates that the demo should include bonus events. These include speed +bonuses, spins, and changes of viewpoint and rendering style. +.TP 8 +.B -nobonuses +Indicates that bonuses should not be included in the demo. +.TP 8 +.B -crosshair +Specifies that a gaming style crosshair be drawn on the simulation. This +serves little purpose but may make hardcore gamers feel more comfortable. +.TP 8 +.B -nocrosshair +Specifies that no crosshair be drawn. +.TP 8 +.B -psychedelic +Specifies that a psychedelic colormap should be generated. When this is +set, the walls and ground of the tunnel are drawn in an often changing +rainbow of colours. +.TP 8 +.B -nopsychedelic +Specifies that a normal colormap should be used, with muted walls and a +grey road. +.TP 8 +.B \-fps +Display the current frame rate and CPU load. +.SH RESOURCES +.EX +Option Resource Default Value +------ -------- ------------- +-wire .wire False +-background .background black +-foreground .foreground white +-darkground .darkground #101010 +-lightground .lightground #a0a0a0 +-tunnelend .tunnelend #000000 +-delay .delay 30000 +-maxspeed .maxspeed 700 +-thrust .thrust 1.0 +-gravity .gravity 9.8 +-vertigo .vertigo 1.0 +-terrain .terrain True +-smoothness .smoothness 6 +-curviness .curviness 1.0 +-twistiness .twistiness 1.0 +-widening .widening True +-bumps .bumps True +-bonuses .bonuses True +-crosshair .crosshair False +-psychedelic .psychedelic False +.EE +.SH WARNING +Speedworm is a trained professional. Do not try this at home. + +Prolonged viewing of this demo with +.B maxspeed +and +.B vertigo +above the defaults may have short-term psychological side effects including +hyperactivity and attention deficiency. +.SH COPYRIGHT +Copyright \(co 2001, Conrad Parker. 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 +Conrad Parker , April 2001. diff --git a/hacks/sphere.c b/hacks/sphere.c new file mode 100644 index 00000000..468a648d --- /dev/null +++ b/hacks/sphere.c @@ -0,0 +1,308 @@ +/* -*- Mode: C; tab-width: 4 -*- */ +/* sphere --- a bunch of shaded spheres */ + +#if 0 +static const char sccsid[] = "@(#)sphere.c 5.00 2000/11/01 xlockmore"; +#endif + +/*- + * Copyright (c) 1988 by Sun Microsystems + * + * Permission to use, copy, modify, and distribute this software and its + * documentation for any purpose and without fee is hereby granted, + * provided that the above copyright notice appear in all copies and that + * both that copyright notice and this permission notice appear in + * supporting documentation. + * + * This file is provided AS IS with no warranties of any kind. The author + * shall have no liability with respect to the infringement of copyrights, + * trade secrets or any patents by this file or any part thereof. In no + * event will the author be liable for any lost revenue or profits or + * other special, indirect and consequential damages. + * + * Revision History: + * 01-Nov-2000: Allocation checks + * 30-May-1997: made it go vertically as well as horizontally. + * 27-May-1997: turned into a standalone program. + * 02-Sep-1993: xlock version David Bagley + * 1988: Revised to use SunView canvas instead of gfxsw Sun Microsystems + * 1982: Orignal Algorithm Tom Duff Lucasfilm Ltd. + */ + +/*- + * original copyright + * ************************************************************************** + * Copyright 1988 by Sun Microsystems, Inc. Mountain View, CA. + * + * All Rights Reserved + * + * Permission to use, copy, modify, and distribute this software and its + * documentation for any purpose and without fee is hereby granted, provided + * that the above copyright notice appear in all copies and that both that + * copyright notice and this permission notice appear in supporting + * documentation, and that the names of Sun or MIT not be used in advertising + * or publicity pertaining to distribution of the software without specific + * prior written permission. Sun and M.I.T. make no representations about the + * suitability of this software for any purpose. It is provided "as is" + * without any express or implied warranty. + * + * SUN DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. + * IN NO EVENT SHALL SUN BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS + * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS + * SOFTWARE. + * *************************************************************************** + */ + +#ifdef STANDALONE +# define MODE_sphere +#define DEFAULTS "*delay: 20000 \n" \ + "*cycles: 20 \n" \ + "*size: 0 \n" \ + "*ncolors: 64 \n" \ + "*fpsSolid: true \n" \ + +# define BRIGHT_COLORS +# define reshape_sphere 0 +# define sphere_handle_event 0 +# include "xlockmore.h" /* from the xscreensaver distribution */ +#else /* !STANDALONE */ +# include "xlock.h" /* from the xlockmore distribution */ +#endif /* !STANDALONE */ + +#ifdef MODE_sphere + +ENTRYPOINT ModeSpecOpt sphere_opts = +{0, (XrmOptionDescRec *) NULL, 0, (argtype *) NULL, (OptionStruct *) NULL}; + +#ifdef USE_MODULES +ModStruct sphere_description = +{"sphere", "init_sphere", "draw_sphere", "release_sphere", + "refresh_sphere", "init_sphere", (char *) NULL, &sphere_opts, + 5000, 1, 20, 0, 64, 1.0, "", + "Shows a bunch of shaded spheres", 0, NULL}; + +#endif + +/*- + * (NX, NY, NZ) is the light source vector -- length should be 100 + */ +#define NX 48 +#define NY (-36) +#define NZ 80 +#define NR 100 +#define SQRT(a) ((int)sqrt((double)(a))) + +typedef struct { + int width, height; + int radius; + int x0; /* x center */ + int y0; /* y center */ + int color; + int x, y; + int dirx, diry; + int shadowx, shadowy; + int maxx, maxy; + XPoint *points; +} spherestruct; + +static spherestruct *spheres = (spherestruct *) NULL; + +ENTRYPOINT void +init_sphere(ModeInfo * mi) +{ + spherestruct *sp; + + if (spheres == NULL) { + if ((spheres = (spherestruct *) calloc(MI_NUM_SCREENS(mi), + sizeof (spherestruct))) == NULL) + return; + } + sp = &spheres[MI_SCREEN(mi)]; + + if (sp->points != NULL) { + (void) free((void *) sp->points); + sp->points = (XPoint *) NULL; + } + sp->width = MAX(MI_WIDTH(mi), 4); + sp->height = MAX(MI_HEIGHT(mi), 4); + if ((sp->points = (XPoint *) malloc(MIN(sp->width, sp->height) * + sizeof (XPoint))) == NULL) { + return; + } + + MI_CLEARWINDOW(mi); + + sp->dirx = 1; + sp->x = sp->radius; + sp->shadowx = (LRAND() & 1) ? 1 : -1; + sp->shadowy = (LRAND() & 1) ? 1 : -1; +} + +ENTRYPOINT void +draw_sphere(ModeInfo * mi) +{ + Display *display = MI_DISPLAY(mi); + GC gc = MI_GC(mi); + int sqrd, nd; + register int minx = 0, maxx = 0, miny = 0, maxy = 0, npts = 0; + spherestruct *sp; + + if (spheres == NULL) + return; + sp = &spheres[MI_SCREEN(mi)]; + if (sp->points == NULL) + return; + + MI_IS_DRAWN(mi) = True; + if ((sp->dirx && ABS(sp->x) >= sp->radius) || + (sp->diry && ABS(sp->y) >= sp->radius)) { + sp->radius = NRAND(MIN(sp->width / 2, sp->height / 2) - 1) + 1; + + if (LRAND() & 1) { + sp->dirx = (int) (LRAND() & 1) * 2 - 1; + sp->diry = 0; + } else { + sp->dirx = 0; + sp->diry = (int) (LRAND() & 1) * 2 - 1; + } + sp->x0 = NRAND(sp->width); + sp->y0 = NRAND(sp->height); + + sp->x = -sp->radius * sp->dirx; + sp->y = -sp->radius * sp->diry; + + if (MI_NPIXELS(mi) > 2) + sp->color = NRAND(MI_NPIXELS(mi)); + } + if (sp->dirx == 1) { + if (sp->x0 + sp->x < 0) + sp->x = -sp->x0; + } else if (sp->dirx == -1) { + if (sp->x0 + sp->x >= sp->width) + sp->x = sp->width - sp->x0 - 1; + } + if (sp->diry == 1) { + if (sp->y0 + sp->y < 0) + sp->y = -sp->y0; + } else if (sp->diry == -1) { + if (sp->y0 + sp->y >= sp->height) + sp->y = sp->height - sp->y0 - 1; + } + if (sp->dirx) { + sp->maxy = SQRT(sp->radius * sp->radius - sp->x * sp->x); + miny = -sp->maxy; + if (sp->y0 - sp->maxy < 0) + miny = -sp->y0; + maxy = sp->maxy; + } + if (sp->diry) { + sp->maxx = SQRT(sp->radius * sp->radius - sp->y * sp->y); + minx = -sp->maxx; + if (sp->x0 - sp->maxx < 0) + minx = -sp->x0; + maxx = sp->maxx; + } + if (sp->dirx) { + if (sp->y0 + sp->maxy >= sp->height) + maxy = sp->height - sp->y0; + } + if (sp->diry) { + if (sp->x0 + sp->maxx >= sp->width) + maxx = sp->width - sp->x0; + } + XSetForeground(display, gc, MI_BLACK_PIXEL(mi)); + + if (sp->dirx) + XDrawLine(display, MI_WINDOW(mi), gc, + sp->x0 + sp->x, sp->y0 + miny, sp->x0 + sp->x, sp->y0 + maxy); + if (sp->diry) + XDrawLine(display, MI_WINDOW(mi), gc, + sp->x0 + minx, sp->y0 + sp->y, sp->x0 + maxx, sp->y0 + sp->y); + + if (MI_NPIXELS(mi) > 2) + XSetForeground(display, gc, MI_PIXEL(mi, sp->color)); + else + XSetForeground(display, gc, MI_WHITE_PIXEL(mi)); + + if (sp->dirx) { + sqrd = sp->radius * sp->radius - sp->x * sp->x; + nd = NX * sp->shadowx * sp->x; + for (sp->y = miny; sp->y <= maxy; sp->y++) + if ((NRAND(sp->radius * NR)) <= nd + NY * sp->shadowy * sp->y + + NZ * SQRT(sqrd - sp->y * sp->y)) { + sp->points[npts].x = sp->x + sp->x0; + sp->points[npts].y = sp->y + sp->y0; + npts++; + } + } + if (sp->diry) { + sqrd = sp->radius * sp->radius - sp->y * sp->y; + nd = NY * sp->shadowy * sp->y; + for (sp->x = minx; sp->x <= maxx; sp->x++) + if ((NRAND(sp->radius * NR)) <= NX * sp->shadowx * sp->x + nd + + NZ * SQRT(sqrd - sp->x * sp->x)) { + sp->points[npts].x = sp->x + sp->x0; + sp->points[npts].y = sp->y + sp->y0; + npts++; + } + } + XDrawPoints(display, MI_WINDOW(mi), gc, sp->points, npts, CoordModeOrigin); + if (sp->dirx == 1) { + sp->x++; + if (sp->x0 + sp->x >= sp->width) + sp->x = sp->radius; + } else if (sp->dirx == -1) { + sp->x--; + if (sp->x0 + sp->x < 0) + sp->x = -sp->radius; + } + if (sp->diry == 1) { + sp->y++; + if (sp->y0 + sp->y >= sp->height) + sp->y = sp->radius; + } else if (sp->diry == -1) { + sp->y--; + if (sp->y0 + sp->y < 0) + sp->y = -sp->radius; + } +} + +ENTRYPOINT void +release_sphere(ModeInfo * mi) +{ + if (spheres != NULL) { + int screen; + + for (screen = 0; screen < MI_NUM_SCREENS(mi); screen++) { + spherestruct *sp = &spheres[screen]; + + if (sp->points) { + (void) free((void *) sp->points); + /* sp->points = NULL; */ + } + } + (void) free((void *) spheres); + spheres = (spherestruct *) NULL; + } +} + +ENTRYPOINT void +refresh_sphere(ModeInfo * mi) +{ + spherestruct *sp; + + if (spheres == NULL) + return; + sp = &spheres[MI_SCREEN(mi)]; + + MI_CLEARWINDOW(mi); + + sp->x = -sp->radius; +} + +XSCREENSAVER_MODULE ("Sphere", sphere) + +#endif /* MODE_sphere */ diff --git a/hacks/sphere.man b/hacks/sphere.man new file mode 100644 index 00000000..d44c2fba --- /dev/null +++ b/hacks/sphere.man @@ -0,0 +1,62 @@ +.TH XScreenSaver 1 "27-May-97" "X Version 11" +.SH NAME +sphere - draws shaded spheres +.SH SYNOPSIS +.B sphere +[\-display \fIhost:display.screen\fP] [\-foreground \fIcolor\fP] [\-background \fIcolor\fP] [\-window] [\-root] [\-mono] [\-install] [\-visual \fIvisual\fP] [\-ncolors \fIinteger\fP] [\-delay \fImicroseconds\fP] + +[\-fps] +.SH DESCRIPTION +The \fIsphere\fP program draws shaded spheres. +.SH OPTIONS +.I sphere +accepts the following options: +.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 \-mono +If on a color display, pretend we're on a monochrome display. +.TP 8 +.B \-install +Install a private colormap for the window. +.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 \-ncolors \fIinteger\fP +How many colors should be used (if possible). Default 64. +The colors are chosen randomly. +.TP 8 +.B \-fps +Display the current frame rate and CPU load. +.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), +.BR xlock (1) +.SH COPYRIGHT +Copyright \(co 1988 by Sun Microsystems, Inc. + +Permission to use, copy, modify, and distribute this software and its +documentation for any purpose and without fee is hereby granted, +provided that the above copyright notice appear in all copies and that +both that copyright notice and this permission notice appear in +supporting documentation. +.SH AUTHOR +Sun Microsystems, Inc, 1988. + +Ability to run standalone or with \fIxscreensaver\fP added by +Jamie Zawinski , 27-May-97. diff --git a/hacks/spiral.c b/hacks/spiral.c new file mode 100644 index 00000000..7a2a3029 --- /dev/null +++ b/hacks/spiral.c @@ -0,0 +1,335 @@ +/* -*- Mode: C; tab-width: 4 -*- */ +/* spiral --- spiraling dots */ + +#if 0 +static const char sccsid[] = "@(#)spiral.c 5.00 2000/11/01 xlockmore"; +#endif + +/*- + * Copyright (c) 1994 by Darrick Brown. + * + * Permission to use, copy, modify, and distribute this software and its + * documentation for any purpose and without fee is hereby granted, + * provided that the above copyright notice appear in all copies and that + * both that copyright notice and this permission notice appear in + * supporting documentation. + * + * This file is provided AS IS with no warranties of any kind. The author + * shall have no liability with respect to the infringement of copyrights, + * trade secrets or any patents by this file or any part thereof. In no + * event will the author be liable for any lost revenue or profits or + * other special, indirect and consequential damages. + * + * Revision History: + * 01-Nov-2000: Allocation checks + * 10-May-1997: jwz@jwz.org: turned into a standalone program. + * 24-Jul-1995: Fix to allow cycles not to have an arbitrary value by + * Peter Schmitzberger (schmitz@coma.sbg.ac.at). + * 06-Mar-1995: Finished cleaning up and final testing. + * 03-Mar-1995: Cleaned up code. + * 12-Jul-1994: Written. + * + * Low CPU usage mode. + * Idea based on a graphics demo I saw a *LONG* time ago. + */ + +#ifdef STANDALONE +# define MODE_spiral +#define DEFAULTS "*delay: 50000 \n" \ + "*count: 40 \n" \ + "*cycles: 350 \n" \ + "*ncolors: 64 \n" \ + "*fpsSolid: true \n" \ + +# define SMOOTH_COLORS +# define reshape_spiral 0 +# define spiral_handle_event 0 +# include "xlockmore.h" /* from the xscreensaver distribution */ +#else /* !STANDALONE */ +# include "xlock.h" /* from the xlockmore distribution */ +#endif /* !STANDALONE */ + +#ifdef MODE_spiral + +ENTRYPOINT ModeSpecOpt spiral_opts = +{0, (XrmOptionDescRec *) NULL, 0, (argtype *) NULL, (OptionStruct *) NULL}; + +#ifdef USE_MODULES +ModStruct spiral_description = +{"spiral", "init_spiral", "draw_spiral", "release_spiral", + "refresh_spiral", "init_spiral", (char *) NULL, &spiral_opts, + 5000, -40, 350, 1, 64, 1.0, "", + "Shows a helical locus of points", 0, NULL}; + +#endif + +#define MAXTRAIL 512 /* The length of the trail */ +#define MAXDOTS 40 +#define MINDOTS 1 +#define TWOPI (2.0*M_PI) /* for convienence */ +#define JAGGINESS 4 /* This sets the "Craziness" of the spiral (I like 4) */ +#define SPEED 2.0 + +/* How many segments to draw per cycle when redrawing */ +#define REDRAWSTEP 3 + + +typedef struct { + float hx, hy, ha, hr; +} Traildots; + +typedef struct { + Traildots *traildots; + float cx, cy; + float angle; + float radius; + float dr, da; + float dx, dy; + int erase; + int inc; + float colors; + int width, height; + float top, bottom, left, right; + int dots, nlength; + int redrawing, redrawpos; +} spiralstruct; + +static spiralstruct *spirals = (spiralstruct *) NULL; + +static void draw_dots(ModeInfo * mi, int in); + +#define TFX(sp,x) ((int)((x/sp->right)*(float)sp->width)) +#define TFY(sp,y) ((int)((y/sp->top)*(float)sp->height)) + +static void +draw_dots(ModeInfo * mi, int in) +{ + + float i, inc; + float x, y; + + spiralstruct *sp = &spirals[MI_SCREEN(mi)]; + + inc = TWOPI / (float) sp->dots; + for (i = 0.0; i < TWOPI; i += inc) { + x = sp->traildots[in].hx + COSF(i + sp->traildots[in].ha) * + sp->traildots[in].hr; + y = sp->traildots[in].hy + SINF(i + sp->traildots[in].ha) * + sp->traildots[in].hr; + XDrawPoint(MI_DISPLAY(mi), MI_WINDOW(mi), MI_GC(mi), + TFX(sp, x), TFY(sp, y)); + } +} + +ENTRYPOINT void +init_spiral(ModeInfo * mi) +{ + spiralstruct *sp; + int i; + + if (spirals == NULL) { + if ((spirals = (spiralstruct *) calloc(MI_NUM_SCREENS(mi), + sizeof (spiralstruct))) == NULL) + return; + } + sp = &spirals[MI_SCREEN(mi)]; + +#ifdef HAVE_COCOA + jwxyz_XSetAntiAliasing (MI_DISPLAY(mi), MI_GC(mi), False); +#endif + + sp->width = MI_WIDTH(mi); + sp->height = MI_HEIGHT(mi); + + MI_CLEARWINDOW(mi); + + /* Init */ + sp->nlength = MI_CYCLES(mi); + + if (!sp->traildots) + if ((sp->traildots = (Traildots *) malloc(sp->nlength * + sizeof (Traildots))) == NULL) { + return; + } + + /* initialize the allocated array */ + for (i = 0; i < sp->nlength; i++) { + sp->traildots[i].hx = 0.0; + sp->traildots[i].hy = 0.0; + sp->traildots[i].ha = 0.0; + sp->traildots[i].hr = 0.0; + } + sp->redrawing = 0; + + /* keep the window parameters proportional */ + sp->top = 10000.0; + sp->bottom = 0; + sp->right = (float) (sp->width) / (float) (sp->height) * (10000.0); + sp->left = 0; + + /* assign the initial values */ + sp->cx = (float) (5000.0 - NRAND(2000)) / 10000.0 * sp->right; + sp->cy = (float) (5000.0 - NRAND(2000)); + sp->radius = (float) (NRAND(200) + 200); + sp->angle = 0.0; + sp->dx = (float) (10 - NRAND(20)) * SPEED; + sp->dy = (float) (10 - NRAND(20)) * SPEED; + sp->dr = (float) ((NRAND(10) + 4) * (1 - (LRAND() & 1) * 2)); + sp->da = (float) NRAND(360) / 7200.0 + 0.01; + if (MI_NPIXELS(mi) > 2) + sp->colors = (float) NRAND(MI_NPIXELS(mi)); + sp->erase = 0; + sp->inc = 0; + sp->traildots[sp->inc].hx = sp->cx; + sp->traildots[sp->inc].hy = sp->cy; + sp->traildots[sp->inc].ha = sp->angle; + sp->traildots[sp->inc].hr = sp->radius; + sp->inc++; + + sp->dots = MI_COUNT(mi); + if (sp->dots < -MINDOTS) + sp->dots = NRAND(sp->dots - MINDOTS + 1) + MINDOTS; + /* Absolute minimum */ + if (sp->dots < MINDOTS) + sp->dots = MINDOTS; +} + +ENTRYPOINT void +draw_spiral(ModeInfo * mi) +{ + Display *display = MI_DISPLAY(mi); + GC gc = MI_GC(mi); + int i, j; + spiralstruct *sp; + + if (spirals == NULL) + return; + sp = &spirals[MI_SCREEN(mi)]; + if (sp->traildots == NULL) + return; + + MI_IS_DRAWN(mi) = True; + if (sp->erase == 1) { + XSetForeground(display, gc, MI_BLACK_PIXEL(mi)); + draw_dots(mi, sp->inc); + } + sp->cx += sp->dx; + sp->traildots[sp->inc].hx = sp->cx; + + if ((sp->cx > 9000.0) || (sp->cx < 1000.0)) + sp->dx *= -1.0; + + sp->cy += sp->dy; + sp->traildots[sp->inc].hy = sp->cy; + + if ((sp->cy > 9000.0) || (sp->cy < 1000.0)) + sp->dy *= -1.0; + + sp->radius += sp->dr; + sp->traildots[sp->inc].hr = sp->radius; + + if ((sp->radius > 2500.0) && (sp->dr > 0.0)) + sp->dr *= -1.0; + else if ((sp->radius < 50.0) && (sp->radius < 0.0)) + sp->dr *= -1.0; + + /* Randomly give some variations to: */ + + /* spiral direction (if it is within the boundaries) */ + if ((NRAND(3000) < 1 * JAGGINESS) && + (((sp->cx > 2000.0) && (sp->cx < 8000.0)) && + ((sp->cy > 2000.0) && (sp->cy < 8000.0)))) { + sp->dx = (float) (10 - NRAND(20)) * SPEED; + sp->dy = (float) (10 - NRAND(20)) * SPEED; + } + /* The speed of the change in size of the spiral */ + if (NRAND(3000) < 1 * JAGGINESS) { + if (LRAND() & 1) + sp->dr += (float) (NRAND(3) + 1); + else + sp->dr -= (float) (NRAND(3) + 1); + + /* don't let it get too wild */ + if (sp->dr > 18.0) + sp->dr = 18.0; + else if (sp->dr < 4.0) + sp->dr = 4.0; + } + /* The speed of rotation */ + if (NRAND(3000) < 1 * JAGGINESS) + sp->da = (float) NRAND(360) / 7200.0 + 0.01; + + /* Reverse rotation */ + if (NRAND(3000) < 1 * JAGGINESS) + sp->da *= -1.0; + + sp->angle += sp->da; + sp->traildots[sp->inc].ha = sp->angle; + + if (sp->angle > TWOPI) + sp->angle -= TWOPI; + else if (sp->angle < 0.0) + sp->angle += TWOPI; + + sp->colors += (float) MI_NPIXELS(mi) / ((float) (2 * sp->nlength)); + if (sp->colors >= (float) MI_NPIXELS(mi)) + sp->colors = 0.0; + + if (MI_NPIXELS(mi) > 2) + XSetForeground(display, gc, MI_PIXEL(mi, (int) sp->colors)); + else + XSetForeground(display, gc, MI_WHITE_PIXEL(mi)); + draw_dots(mi, sp->inc); + sp->inc++; + + if (sp->inc > sp->nlength - 1) { + sp->inc -= sp->nlength; + sp->erase = 1; + } + if (sp->redrawing) { + for (i = 0; i < REDRAWSTEP; i++) { + j = (sp->inc - sp->redrawpos + sp->nlength) % sp->nlength; + draw_dots(mi, j); + + if (++(sp->redrawpos) >= sp->nlength) { + sp->redrawing = 0; + break; + } + } + } +} + +ENTRYPOINT void +release_spiral(ModeInfo * mi) +{ + if (spirals != NULL) { + int screen; + + for (screen = 0; screen < MI_NUM_SCREENS(mi); screen++) { + spiralstruct *sp = &spirals[screen]; + + if (sp->traildots) + (void) free((void *) sp->traildots); + } + (void) free((void *) spirals); + spirals = (spiralstruct *) NULL; + } +} + +ENTRYPOINT void +refresh_spiral(ModeInfo * mi) +{ + spiralstruct *sp; + + if (spirals == NULL) + return; + sp = &spirals[MI_SCREEN(mi)]; + + MI_CLEARWINDOW(mi); + sp->redrawing = 1; + sp->redrawpos = 0; +} + +XSCREENSAVER_MODULE ("Spiral", spiral) + +#endif /* MODE_spiral */ diff --git a/hacks/spiral.man b/hacks/spiral.man new file mode 100644 index 00000000..cf9eb6f7 --- /dev/null +++ b/hacks/spiral.man @@ -0,0 +1,71 @@ +.TH XScreenSaver 1 "10-May-97" "X Version 11" +.SH NAME +spiral - draws moving circular spiral patterns +.SH SYNOPSIS +.B spiral +[\-display \fIhost:display.screen\fP] [\-foreground \fIcolor\fP] [\-background \fIcolor\fP] [\-window] [\-root] [\-mono] [\-install] [\-visual \fIvisual\fP] [\-ncolors \fIinteger\fP] [\-delay \fImicroseconds\fP] [\-count \fIinteger\fP] + +[\-fps] +.SH DESCRIPTION +The \fIspiral\fP program draws moving circular spiral patterns +.SH OPTIONS +.I spiral +accepts the following options: +.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 \-mono +If on a color display, pretend we're on a monochrome display. +.TP 8 +.B \-install +Install a private colormap for the window. +.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 \-ncolors \fIinteger\fP +How many colors should be used (if possible). Default 64. +The colors are chosen randomly. +.TP 8 +.B \-count \fIinteger\fP +Default 40. +.TP 8 +.B \-cycles \fIinteger\fP +Default 350. + +.TP 8 +.B \-fps +Display the current frame rate and CPU load. +.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), +.BR xlock (1) +.SH COPYRIGHT +Copyright \(co 1994 by Darrick Brown. + +Permission to use, copy, modify, and distribute this software and its +documentation for any purpose and without fee is hereby granted, +provided that the above copyright notice appear in all copies and that +both that copyright notice and this permission notice appear in +supporting documentation. +.SH AUTHOR +Darrick Brown, 1994. + +Improved by Peter Schmitzberger , 24-Jul-95. + +Ability to run standalone or with \fIxscreensaver\fP added by +Jamie Zawinski , 10-May-97. diff --git a/hacks/spotlight.c b/hacks/spotlight.c new file mode 100644 index 00000000..014fff65 --- /dev/null +++ b/hacks/spotlight.c @@ -0,0 +1,333 @@ +/* + * spotlight - an xscreensaver module + * Copyright (c) 1999, 2001 Rick Schultz + * + * loosely based on the BackSpace module "StefView" by Darcy Brockbank + */ + +/* modified from a module from the xscreensaver distribution */ + +/* + * xscreensaver, Copyright (c) 1992-2006 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. + */ + + +/* #define DEBUG */ +#include +#include "screenhack.h" + +#define MINX 0.0 +#define MINY 0.0 +#define X_PERIOD 15000.0 +#define Y_PERIOD 12000.0 + +struct state { + Display *dpy; + Window window; + Screen *screen; + + int sizex, sizey; /* screen size */ + int delay; + int duration; + time_t start_time; + int first_time; + GC window_gc; +#ifdef DEBUG + GC white_gc; +#endif + GC buffer_gc; /* draw in buffer, then flush to screen + to avoid flicker */ + int radius; /* radius of spotlight in pixels */ + + Pixmap pm; /* pixmap grabbed from screen */ + Pixmap buffer; /* pixmap for the buffer */ + + int x, y, s; /* x & y coords of buffer (upper left corner) */ + /* s is the width of the buffer */ + + int off; /* random offset from currentTimeInMs(), so that + two concurrent copies of spotlight have different + behavior. */ + + int oldx, oldy, max_x_speed, max_y_speed; + /* used to keep the new buffer position + over the old spotlight image to make sure + the old image is completely erased */ + + Bool first_p; + async_load_state *img_loader; +}; + + +/* The path the spotlight follows around the screen is sinusoidal. + This function is fed to sin() to get the x & y coords */ +static long +currentTimeInMs(struct state *st) +{ + struct timeval curTime; +#ifdef GETTIMEOFDAY_TWO_ARGS + struct timezone tz = {0,0}; + gettimeofday(&curTime, &tz); +#else + gettimeofday(&curTime); +#endif + return curTime.tv_sec*1000 + curTime.tv_usec/1000.0; +} + + +static void * +spotlight_init (Display *dpy, Window window) +{ + struct state *st = (struct state *) calloc (1, sizeof(*st)); + XGCValues gcv; + XWindowAttributes xgwa; + long gcflags; + Colormap cmap; + unsigned long bg; + GC clip_gc; + Pixmap clip_pm; + + st->dpy = dpy; + st->window = window; + st->first_p = True; + + XGetWindowAttributes (st->dpy, st->window, &xgwa); + st->screen = xgwa.screen; + st->sizex = xgwa.width; + st->sizey = xgwa.height; + cmap = xgwa.colormap; + bg = get_pixel_resource (st->dpy, cmap, "background", "Background"); + + /* read parameters, keep em sane */ + st->delay = get_integer_resource (st->dpy, "delay", "Integer"); + if (st->delay < 1) st->delay = 1; + st->duration = get_integer_resource (st->dpy, "duration", "Seconds"); + if (st->duration < 1) st->duration = 1; + st->radius = get_integer_resource (st->dpy, "radius", "Integer"); + if (st->radius < 0) st->radius = 125; + + /* Don't let the spotlight be bigger than the window */ + while (st->radius > xgwa.width * 0.45) + st->radius /= 2; + while (st->radius > xgwa.height * 0.45) + st->radius /= 2; + + if (st->radius < 4) + st->radius = 4; + + /* do the dance */ + gcv.function = GXcopy; + gcv.subwindow_mode = IncludeInferiors; + gcflags = GCForeground | GCFunction; + gcv.foreground = bg; + +#ifdef NOPE + if (use_subwindow_mode_p(xgwa.screen, st->window)) /* see grabscreen.c */ + gcflags |= GCSubwindowMode; +#endif + st->window_gc = XCreateGC(st->dpy, st->window, gcflags, &gcv); + + st->pm = XCreatePixmap(st->dpy, st->window, st->sizex, st->sizey, xgwa.depth); + XClearWindow(st->dpy, st->window); + + st->first_time = 1; + + /* create buffer to reduce flicker */ +#ifdef HAVE_COCOA /* Don't second-guess Quartz's double-buffering */ + st->buffer = 0; +#else + st->buffer = XCreatePixmap(st->dpy, st->window, st->sizex, st->sizey, xgwa.depth); +#endif + + st->buffer_gc = XCreateGC(st->dpy, (st->buffer ? st->buffer : window), gcflags, &gcv); + if (st->buffer) + XFillRectangle(st->dpy, st->buffer, st->buffer_gc, 0, 0, st->sizex, st->sizey); + + /* create clip mask (so it's a circle, not a square) */ + clip_pm = XCreatePixmap(st->dpy, st->window, st->radius*4, st->radius*4, 1); + st->img_loader = load_image_async_simple (0, xgwa.screen, st->window, st->pm, + 0, 0); + st->start_time = time ((time_t) 0); + + gcv.foreground = 0L; + clip_gc = XCreateGC(st->dpy, clip_pm, gcflags, &gcv); + XFillRectangle(st->dpy, clip_pm, clip_gc, 0, 0, st->radius*4, st->radius*4); + + XSetForeground(st->dpy, clip_gc, 1L); + XFillArc(st->dpy, clip_pm, clip_gc, st->radius , st->radius, + st->radius*2, st->radius*2, 0, 360*64); + + /* set buffer's clip mask to the one we just made */ + XSetClipMask(st->dpy, st->buffer_gc, clip_pm); + + /* free everything */ + XFreeGC(st->dpy, clip_gc); + XFreePixmap(st->dpy, clip_pm); + + /* avoid remants */ + st->max_x_speed = st->max_y_speed = st->radius; + + st->off = random(); + +#ifdef DEBUG + /* create GC with white fg */ + gcv.foreground = fg; + st->white_gc = XCreateGC(st->dpy, st->window, gcflags, &gcv); +#endif + + /* blank out screen */ + XFillRectangle(st->dpy, st->window, st->window_gc, 0, 0, st->sizex, st->sizey); + + return st; +} + + +/* + * perform one iteration + */ +static void +onestep (struct state *st, Bool first_p) +{ + long now; + + if (st->img_loader) /* still loading */ + { + st->img_loader = load_image_async_simple (st->img_loader, 0, 0, 0, 0, 0); + if (! st->img_loader) { /* just finished */ + st->start_time = time ((time_t) 0); + } + return; + } + + if (!st->img_loader && + st->start_time + st->duration < time ((time_t) 0)) { + st->img_loader = load_image_async_simple (0, st->screen, st->window, + st->pm, 0, 0); + return; + } + +#define nrnd(x) (random() % (x)) + + st->oldx = st->x; + st->oldy = st->y; + + st->s = st->radius *4 ; /* s = width of buffer */ + + now = currentTimeInMs(st) + st->off; + + /* find new x,y */ + st->x = ((1 + sin(((double)now) / X_PERIOD * 2. * M_PI))/2.0) + * (st->sizex - st->s/2) -st->s/4 + MINX; + st->y = ((1 + sin(((double)now) / Y_PERIOD * 2. * M_PI))/2.0) + * (st->sizey - st->s/2) -st->s/4 + MINY; + + if (!st->first_p) + { + /* limit change in x and y to buffer width */ + if ( st->x < (st->oldx - st->max_x_speed) ) st->x = st->oldx - st->max_x_speed; + if ( st->x > (st->oldx + st->max_x_speed) ) st->x = st->oldx + st->max_x_speed; + if ( st->y < (st->oldy - st->max_y_speed) ) st->y = st->oldy - st->max_y_speed; + if ( st->y > (st->oldy + st->max_y_speed) ) st->y = st->oldy + st->max_y_speed; + } + + if (! st->buffer) + { + XClearWindow (st->dpy, st->window); + XSetClipOrigin(st->dpy, st->buffer_gc, st->x,st->y); + XCopyArea(st->dpy, st->pm, st->window, st->buffer_gc, st->x, st->y, st->s, st->s, st->x, st->y); + } + else + { + /* clear buffer */ + XFillRectangle(st->dpy, st->buffer, st->buffer_gc, st->x, st->y, st->s, st->s); + + /* copy area of screen image (pm) to buffer + Clip to a circle */ + XSetClipOrigin(st->dpy, st->buffer_gc, st->x,st->y); + XCopyArea(st->dpy, st->pm, st->buffer, st->buffer_gc, st->x, st->y, st->s, st->s, st->x, st->y); + + if (st->first_time) { + /* blank out screen */ + XFillRectangle(st->dpy, st->window, st->window_gc, 0, 0, st->sizex, st->sizey); + st->first_time = 0; + } + + /* copy buffer to screen (window) */ + XCopyArea(st->dpy, st->buffer, st->window, st->window_gc, st->x , st->y, st->s, st->s, st->x, st->y); + } + +#ifdef DEBUG + /* draw a box around the buffer */ + XDrawRectangle(st->dpy, st->window, st->white_gc, st->x , st->y, st->s, st->s); +#endif + +} + + +static unsigned long +spotlight_draw (Display *dpy, Window window, void *closure) +{ + struct state *st = (struct state *) closure; + onestep(st, st->first_p); + st->first_p = False; + return st->delay; +} + +static void +spotlight_reshape (Display *dpy, Window window, void *closure, + unsigned int w, unsigned int h) +{ +} + +static Bool +spotlight_event (Display *dpy, Window window, void *closure, XEvent *event) +{ + return False; +} + +static void +spotlight_free (Display *dpy, Window window, void *closure) +{ + struct state *st = (struct state *) closure; + XFreeGC (dpy, st->window_gc); + XFreeGC (dpy, st->buffer_gc); + if (st->pm) XFreePixmap (dpy, st->pm); + if (st->buffer) XFreePixmap (dpy, st->buffer); + free (st); +} + + + + +static const char *spotlight_defaults [] = { + ".background: black", + ".foreground: white", + "*dontClearRoot: True", + "*fpsSolid: true", + +#ifdef __sgi /* really, HAVE_READ_DISPLAY_EXTENSION */ + "*visualID: Best", +#endif + + "*delay: 10000", + "*duration: 120", + "*radius: 125", + 0 +}; + +static XrmOptionDescRec spotlight_options [] = { + { "-delay", ".delay", XrmoptionSepArg, 0 }, + { "-duration", ".duration", XrmoptionSepArg, 0 }, + { "-radius", ".radius", XrmoptionSepArg, 0 }, + { 0, 0, 0, 0 } +}; + +XSCREENSAVER_MODULE ("Spotlight", spotlight) diff --git a/hacks/spotlight.man b/hacks/spotlight.man new file mode 100644 index 00000000..770a3e8b --- /dev/null +++ b/hacks/spotlight.man @@ -0,0 +1,80 @@ +.TH XScreenSaver 1 "05-Apr-1999" "X Version 11" +.SH NAME +spotlight - move spotlight around desktop +.SH SYNOPSIS +.B spotlight +[\-display \fIhost:display.screen\fP] [\-foreground \fIcolor\fP] +[\-background \fIcolor\fP] [\-window] [\-root] [\-mono] [\-install] +[\-visual \fIvisual\fP] +[\-delay \fIusecs\fP] +[\-duration \fIsecs\fP] +[\-radius \fIpixels\fP] +[\-fps] +.SH DESCRIPTION +The \fIspotlight\fP program takes an image and exposes small sections +of it as if through a wandering spotlight beam. + +The image that it manipulates will be grabbed from the portion of +the screen underlying the window, or from the system's video input, +or from a random file on disk, as indicated by +the \fIgrabDesktopImages\fP, \fIgrabVideoFrames\fP, +and \fIchooseRandomImages\fP options in the \fI~/.xscreensaver\fP +file; see +.BR xscreensaver-demo (1) +for more details. +.SH OPTIONS +.I spotlight +accepts the following options: +.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 \-mono +If on a color display, pretend we're on a monochrome display. +.TP 8 +.B \-install +Install a private colormap for the window. +.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 \-delay \fImicroseconds\fP +Slow it down. +.TP 8 +.B \-duration \fIseconds\fP +How long to run before loading a new image. Default 120 seconds. +.TP 8 +.B \-radius \fIpixels\fP +Radius of the spotlight in pixels. +.TP 8 +.B \-fps +Display the current frame rate and CPU load. +.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), +.BR xscreensaver\-demo (1), +.BR xscreensaver\-getimage (1) +.SH COPYRIGHT +Copyright \(co 1999 by Rick Schultz. 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 CREDITS +Hacked together by Rick Schultz , based on StefView for +BackSpace by Darcy Brockbank and on several other xscreensaver hacks. diff --git a/hacks/squiral.c b/hacks/squiral.c new file mode 100644 index 00000000..2a0b0fd2 --- /dev/null +++ b/hacks/squiral.c @@ -0,0 +1,278 @@ +/* squiral, by "Jeff Epler" , 18-mar-1999. + * + * 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. + */ + +#include "screenhack.h" +#include "colors.h" +#include "erase.h" +#include "yarandom.h" + +#define R(x) (abs(random())%x) +#define PROB(x) (frand(1.0) < (x)) + +#define NCOLORSMAX 255 +#define STATES 8 + +/* 0- 3 left-winding */ +/* 4- 7 right-winding */ + +struct worm { + int h; + int v; + int s; + int c; + int cc; +}; + + +struct state { + Display *dpy; + Window window; + + int width, height, count, cycle; + double frac, disorder, handedness; + int ncolors; + GC draw_gc, erase_gc; + XColor colors[NCOLORSMAX]; + + int delay; + + int cov; + int dirh[4]; + int dirv[4]; + + int *fill; + + struct worm *worms; + int inclear; +}; + +#define CLEAR1(x,y) (!st->fill[((y)%st->height)*st->width+(x)%st->width]) +#define MOVE1(x,y) (st->fill[((y)%st->height)*st->width+(x)%st->width]=1, XDrawPoint(st->dpy, st->window, st->draw_gc, (x)%st->width,(y)%st->height), st->cov++) + +#define CLEARDXY(x,y,dx,dy) CLEAR1(x+dx, y+dy) && CLEAR1(x+dx+dx, y+dy+dy) +#define MOVEDXY(x,y,dx,dy) MOVE1 (x+dx, y+dy), MOVE1 (x+dx+dx, y+dy+dy) + +#define CLEAR(d) CLEARDXY(w->h,w->v, st->dirh[d],st->dirv[d]) +#define MOVE(d) (XSetForeground(st->dpy, st->draw_gc, st->colors[w->c].pixel), \ + MOVEDXY(w->h,w->v, st->dirh[d],st->dirv[d]), \ + w->h=w->h+st->dirh[d]*2, \ + w->v=w->v+st->dirv[d]*2, dir=d) + +#define RANDOM (void) (w->h = R(st->width), w->v = R(st->height), w->c = R(st->ncolors), \ + type=R(2), dir=R(4), (st->cycle && (w->cc=R(3)+st->ncolors))) + + + +#define SUCC(x) ((x+1)%4) +#define PRED(x) ((x+3)%4) +#define CCW PRED(dir) +#define CW SUCC(dir) +#define REV ((dir+2)%4) +#define STR (dir) +#define TRY(x) if (CLEAR(x)) { MOVE(x); break; } + +static void +do_worm(struct state *st, struct worm *w) +{ + int type = w->s / 4; + int dir = w->s % 4; + + w->c = (w->c+w->cc) % st->ncolors; + + if (PROB(st->disorder)) type=PROB(st->handedness); + switch(type) { + case 0: /* CCW */ + TRY(CCW) + TRY(STR) + TRY(CW) + RANDOM; + break; + case 1: /* CW */ + TRY(CW) + TRY(STR) + TRY(CCW) + RANDOM; + break; + } + w->s = type*4+dir; + w->h = w->h % st->width; + w->v = w->v % st->height; +} + +static void +squiral_init_1 (struct state *st) +{ + int i; + if (st->worms) free (st->worms); + if (st->fill) free (st->fill); + + st->worms=calloc(st->count, sizeof(struct worm)); + st->fill=calloc(st->width*st->height, sizeof(int)); + + st->dirh[0]=0; st->dirh[1]=1; st->dirh[2]=0; st->dirh[3]=st->width-1; + st->dirv[0]=st->height-1; st->dirv[1]=0; st->dirv[2]=1; st->dirv[3]=0; + for(i=0;icount;i++) { + st->worms[i].h=R(st->width); + st->worms[i].v=R(st->height); + st->worms[i].s=R(4)+4*PROB(st->handedness); + st->worms[i].c=R(st->ncolors); + if(st->cycle) { st->worms[i].cc=R(3)+st->ncolors; } + else st->worms[i].cc=0; + } +} + +static void * +squiral_init (Display *dpy, Window window) +{ + struct state *st = (struct state *) calloc (1, sizeof(*st)); + XGCValues gcv; + Colormap cmap; + XWindowAttributes xgwa; + Bool writeable = False; + + st->dpy = dpy; + st->window = window; + + st->delay= get_integer_resource(st->dpy, "delay", "Integer"); + + XClearWindow(st->dpy, st->window); + XGetWindowAttributes(st->dpy, st->window, &xgwa); + st->width = xgwa.width; + st->height = xgwa.height; + + cmap = xgwa.colormap; + gcv.foreground = get_pixel_resource(st->dpy, cmap, "foreground", + "Foreground"); + st->draw_gc = XCreateGC(st->dpy, st->window, GCForeground, &gcv); + gcv.foreground = get_pixel_resource (st->dpy, cmap, "background", "Background"); + st->erase_gc = XCreateGC (st->dpy, st->window, GCForeground, &gcv); + cmap = xgwa.colormap; + if( st->ncolors ) { + free_colors(st->dpy, cmap, st->colors, st->ncolors); + st->ncolors = 0; + } + if( mono_p ) { + st->ncolors=1; + st->colors[0].pixel=get_pixel_resource(st->dpy, cmap, "foreground","Foreground"); + } else { + st->ncolors = get_integer_resource(st->dpy, "ncolors", "Integer"); + if (st->ncolors < 0 || st->ncolors > NCOLORSMAX) + st->ncolors = NCOLORSMAX; + make_uniform_colormap(st->dpy, xgwa.visual, cmap, st->colors, &st->ncolors, True, + &writeable, False); + if (st->ncolors <= 0) { + st->ncolors = 1; + st->colors[0].pixel=get_pixel_resource(st->dpy, cmap, "foreground","Foreground"); + } + } + st->count= get_integer_resource(st->dpy, "count", "Integer"); + st->frac = get_integer_resource(st->dpy, "fill", "Integer")*0.01; + st->cycle= get_boolean_resource(st->dpy, "cycle", "Cycle"); + st->disorder=get_float_resource(st->dpy, "disorder", "Float"); + st->handedness=get_float_resource(st->dpy, "handedness", "Float"); + + if(st->frac<0.01) st->frac=0.01; + if(st->frac>0.99) st->frac=0.99; + if(st->count==0) st->count=st->width/32; + if(st->count<1) st->count=1; + if(st->count>1000) st->count=1000; + + if(st->worms) free(st->worms); + if(st->fill) free(st->fill); + + squiral_init_1 (st); + + return st; +} + +static unsigned long +squiral_draw (Display *dpy, Window window, void *closure) +{ + struct state *st = (struct state *) closure; + int i; + + if(st->inclearheight) { + XDrawLine(st->dpy, st->window, st->erase_gc, 0, st->inclear, st->width-1, st->inclear); + memset(&st->fill[st->inclear*st->width], 0, sizeof(int)*st->width); + XDrawLine(st->dpy, st->window, st->erase_gc, 0, st->height-st->inclear-1, st->width-1, + st->height-st->inclear-1); + memset(&st->fill[(st->height-st->inclear-1)*st->width], 0, sizeof(int)*st->width); + st->inclear++; + XDrawLine(st->dpy, st->window, st->erase_gc, 0, st->inclear, st->width-1, st->inclear); + if (st->inclear < st->height) + memset(&st->fill[st->inclear*st->width], 0, sizeof(int)*st->width); + XDrawLine(st->dpy, st->window, st->erase_gc, 0, st->height-st->inclear-1, st->width-1, + st->height-st->inclear-1); + if (st->height - st->inclear >= 1) + memset(&st->fill[(st->height-st->inclear-1)*st->width], 0, sizeof(int)*st->width); + st->inclear++; + if(st->inclear>st->height/2) st->inclear=st->height; + } + else if(st->cov>(st->frac*st->width*st->height)) { + st->inclear=0; + st->cov=0; + } + for(i=0;icount;i++) do_worm(st, &st->worms[i]); + return st->delay; +} + +static void +squiral_reshape (Display *dpy, Window window, void *closure, + unsigned int w, unsigned int h) +{ + struct state *st = (struct state *) closure; + st->width = w; + st->height = h; + squiral_init_1 (st); + XClearWindow (dpy, window); +} + +static Bool +squiral_event (Display *dpy, Window window, void *closure, XEvent *event) +{ + return False; +} + +static void +squiral_free (Display *dpy, Window window, void *closure) +{ + struct state *st = (struct state *) closure; + free (st); +} + + +static const char *squiral_defaults[] = { + ".background: black", + ".foreground: white", + "*fpsSolid: true", + "*fill: 75", + "*count: 0", + "*ncolors: 100", + "*delay: 10000", + "*disorder: 0.005", + "*cycle: False", + "*handedness: 0.5", + 0 +}; + +static XrmOptionDescRec squiral_options[] = { + {"-fill", ".fill", XrmoptionSepArg, 0}, + {"-count", ".count", XrmoptionSepArg, 0}, + {"-delay", ".delay", XrmoptionSepArg, 0}, + {"-disorder", ".disorder", XrmoptionSepArg, 0}, + {"-handedness", ".handedness", XrmoptionSepArg, 0}, + {"-ncolors", ".ncolors", XrmoptionSepArg, 0}, + {"-cycle", ".cycle", XrmoptionNoArg, "True"}, + {"-no-cycle", ".cycle", XrmoptionNoArg, "False"}, + { 0, 0, 0, 0 } +}; + +XSCREENSAVER_MODULE ("Squiral", squiral) diff --git a/hacks/squiral.man b/hacks/squiral.man new file mode 100644 index 00000000..a34728b7 --- /dev/null +++ b/hacks/squiral.man @@ -0,0 +1,80 @@ +.TH XScreenSaver 1 "18-mar-1999" "X Version 11" +.SH NAME +squiral - square spirals screensaver +.SH SYNOPSIS +.B squiral +[\-display \fIhost:display.screen\fP] [\-foreground \fIcolor\fP] +[\-background \fIcolor\fP] [\-window] [\-root] [\-mono] [\-install] +[\-noinstall] [\-visual \fIvisual\fP] [\-fill \fIpercent\fP] [-count +\fInumber\fP] [-delay \fIusec\fP] [-disorder \fIfraction\fP] [-handedness +\fIfraction\fP] [-cycle] +[\-fps] +.SH DESCRIPTION +The \fIsquiral\fP program displays interacting, spiral-producing automata + +.SH OPTIONS +.I squiral +accepts the following options: +.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 \-mono +If on a color display, pretend we're on a monochrome display. +.TP 8 +.B \-install +Install a private colormap for the window. +.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 \-fill \fIpercent\fP +Specify the percent (0-100) of the screen which must be filled before +the screen is cleared. 60-80 percent are good values. +.TP 8 +.B \-count \fInumber\fP +The number of squiralies. By default, the screen width divided by 32. +.TP 8 +.B \-delay \fIusec\fP +The wait between steps. The default is 1000. +.TP 8 +.B \-disorder \fIfraction\fP +The fraction of the time a squiraly will choose a new direction. +The default is 0.005. +.TP 8 +.B \-handedness \fIfraction\fP +The fraction of the time a squiraly will choose to enter lefthanded +mode. 0.0 means exclusively right-handed behavior, 0.5 (the default) is +a balance between the two, and 1.0 is exclusively left-handed behaviour. +.TP 8 +.B \-fps +Display the current frame rate and CPU load. +.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 BUGS +None known +.SH SEE ALSO +.BR X (1), +.BR xscreensaver (1) +.SH COPYRIGHT +Copyright \(co 1999, by Jeff Epler. Permission to use, copy, modify, +distribute, and sell this software and its documentation for any purpose is +hereby granted without fee, provided fnord 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 fnord this software for any purpose. It is provided "as +is" without express or fnord implied warranty. +.SH AUTHOR +Jeff Epler , 18-mar-1999 + diff --git a/hacks/starfish.c b/hacks/starfish.c new file mode 100644 index 00000000..071dccb6 --- /dev/null +++ b/hacks/starfish.c @@ -0,0 +1,545 @@ +/* xscreensaver, Copyright (c) 1997-2008 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. + */ + +#include +#include "screenhack.h" +#include "spline.h" + +#define SCALE 1000 /* fixed-point math, for sub-pixel motion */ + + +#define RAND(n) ((long) ((random() & 0x7fffffff) % ((long) (n)))) +#define RANDSIGN() ((random() & 1) ? 1 : -1) + +enum starfish_mode { + pulse, + zoom +}; + +struct starfish { + enum starfish_mode mode; + Bool blob_p; + int skip; + long x, y; /* position of midpoint */ + double th; /* angle of rotation */ + double rotv; /* rotational velocity */ + double rota; /* rotational acceleration */ + long elasticity; /* how fast it deforms: radial velocity */ + double rot_max; + long min_r, max_r; /* radius range */ + int npoints; /* control points */ + long *r; /* radii */ + spline *spline; + XPoint *prev; + int n_prev; +}; + + +struct state { + Display *dpy; + Window window; + + Colormap cmap; + XColor *colors; + int ncolors; + int fg_index; + GC gc; + + int delay, delay2, duration, direction, blob_p; + + Bool done_once; + Bool initted; + unsigned long black, white; + + long tick; + time_t start_time; + + struct starfish *starfish; +}; + + +static struct starfish * +make_starfish (struct state *st, int maxx, int maxy, int size) +{ + struct starfish *s = (struct starfish *) calloc(1, sizeof(*s)); + int i; + int mid; + + s->blob_p = st->blob_p; + s->elasticity = SCALE * get_float_resource (st->dpy, "thickness", "Thickness"); + + if (s->elasticity == 0) + /* bell curve from 0-15, avg 7.5 */ + s->elasticity = RAND(5*SCALE) + RAND(5*SCALE) + RAND(5*SCALE); + + s->rotv = get_float_resource (st->dpy, "rotation", "Rotation"); + if (s->rotv == -1) + /* bell curve from 0-12 degrees, avg 6 */ + s->rotv = frand(4) + frand(4) + frand(4); + + s->rotv /= 360; /* convert degrees to ratio */ + + if (s->blob_p) + { + s->elasticity *= 3; + s->rotv *= 3; + } + + s->rot_max = s->rotv * 2; + s->rota = 0.0004 + frand(0.0002); + + + if (! (random() % 20)) + size *= frand(0.35) + frand(0.35) + 0.3; + + { + static const char skips[] = { 2, 2, 2, 2, + 3, 3, 3, + 6, 6, + 12 }; + s->skip = skips[random() % sizeof(skips)]; + } + + if (! (random() % (s->skip == 2 ? 3 : 12))) + s->mode = zoom; + else + s->mode = pulse; + + maxx *= SCALE; + maxy *= SCALE; + size *= SCALE; + + s->max_r = size; + s->min_r = 0; + + if (s->min_r < (5*SCALE)) s->min_r = (5*SCALE); + mid = ((s->min_r + s->max_r) / 2); + + s->x = maxx/2; + s->y = maxy/2; + + s->th = frand(M_PI+M_PI) * RANDSIGN(); + + { + static const char sizes[] = { 3, 3, 3, 3, 3, + 4, 4, 4, 4, + 5, 5, 5, 5, 5, 5, + 8, 8, 8, + 10, + 35 }; + int nsizes = sizeof(sizes); + if (s->skip > 3) + nsizes -= 4; + s->npoints = s->skip * sizes[random() % nsizes]; + } + + s->spline = make_spline (s->npoints); + s->r = (long *) malloc (sizeof(*s->r) * s->npoints); + + for (i = 0; i < s->npoints; i++) + s->r[i] = ((i % s->skip) == 0) ? 0 : size; + + return s; +} + + +static void +free_starfish (struct starfish *s) +{ + if (s->r) free (s->r); + if (s->prev) free (s->prev); + if (s->spline) + { + if (s->spline->control_x) free (s->spline->control_x); + if (s->spline->control_y) free (s->spline->control_y); + if (s->spline->points) free (s->spline->points); + free (s->spline); + } + free (s); +} + + +static void +throb_starfish (struct starfish *s) +{ + int i; + double frac = ((M_PI+M_PI) / s->npoints); + + for (i = 0; i < s->npoints; i++) + { + long r = s->r[i]; + long ra = (r > 0 ? r : -r); + double th = (s->th > 0 ? s->th : -s->th); + long x, y; + long elasticity = s->elasticity; + + /* place control points evenly around perimiter, shifted by theta */ + x = s->x + ra * cos (i * frac + th); + y = s->y + ra * sin (i * frac + th); + + s->spline->control_x[i] = x / SCALE; + s->spline->control_y[i] = y / SCALE; + + if (s->mode == zoom && ((i % s->skip) == 0)) + continue; + + /* Slow down near the end points: move fastest in the middle. */ + { + double ratio = (double)ra / (double)(s->max_r - s->min_r); + if (ratio > 0.5) ratio = 1-ratio; /* flip */ + ratio *= 2; /* normalize */ + ratio = (ratio * 0.9) + 0.1; /* fudge */ + elasticity *= ratio; + } + + + /* Increase/decrease radius by elasticity */ + ra += (r >= 0 ? elasticity : -elasticity); + if ((i % s->skip) == 0) + ra += (elasticity / 2); + + r = ra * (r >= 0 ? 1 : -1); + + /* If we've reached the end (too long or too short) reverse direction. */ + if ((ra > s->max_r && r >= 0) || + (ra < s->min_r && r < 0)) + r = -r; + + s->r[i] = r; + } +} + + +static void +spin_starfish (struct starfish *s) +{ + double th = s->th; + if (th < 0) + th = -(th + s->rotv); + else + th += s->rotv; + + if (th > (M_PI+M_PI)) + th -= (M_PI+M_PI); + else if (th < 0) + th += (M_PI+M_PI); + + s->th = (s->th > 0 ? th : -th); + + s->rotv += s->rota; + + if (s->rotv > s->rot_max || + s->rotv < -s->rot_max) + { + s->rota = -s->rota; + } + /* If it stops, start it going in the other direction. */ + else if (s->rotv < 0) + { + if (random() & 1) + { + /* keep going in the same direction */ + s->rotv = 0; + if (s->rota < 0) + s->rota = -s->rota; + } + else + { + /* reverse gears */ + s->rotv = -s->rotv; + s->rota = -s->rota; + s->th = -s->th; + } + } + + + /* Alter direction of rotational acceleration randomly. */ + if (! (random() % 120)) + s->rota = -s->rota; + + /* Change acceleration very occasionally. */ + if (! (random() % 200)) + { + if (random() & 1) + s->rota *= 1.2; + else + s->rota *= 0.8; + } +} + + +static void +draw_starfish (struct state *st, Drawable drawable, GC this_gc, struct starfish *s, + Bool fill_p) +{ + compute_closed_spline (s->spline); + if (s->prev) + { + XPoint *points = (XPoint *) + malloc (sizeof(XPoint) * (s->n_prev + s->spline->n_points + 2)); + int i = s->spline->n_points; + int j = s->n_prev; + memcpy (points, s->spline->points, (i * sizeof(*points))); + memcpy (points+i, s->prev, (j * sizeof(*points))); + + if (s->blob_p) + XClearWindow (st->dpy, drawable); + XFillPolygon (st->dpy, drawable, this_gc, points, i+j, Complex, CoordModeOrigin); + free (points); + + free (s->prev); + s->prev = 0; + } + + s->prev = (XPoint *) malloc (s->spline->n_points * sizeof(XPoint)); + memcpy (s->prev, s->spline->points, s->spline->n_points * sizeof(XPoint)); + s->n_prev = s->spline->n_points; + +#ifdef DEBUG + if (s->blob_p) + { + int i; + for (i = 0; i < s->npoints; i++) + XDrawLine (st->dpy, drawable, this_gc, s->x/SCALE, s->y/SCALE, + s->spline->control_x[i], s->spline->control_y[i]); + } +#endif +} + + +static struct starfish * +make_window_starfish (struct state *st) +{ + XWindowAttributes xgwa; + int size; + XGetWindowAttributes (st->dpy, st->window, &xgwa); + size = (xgwa.width < xgwa.height ? xgwa.width : xgwa.height); + if (st->blob_p) size /= 2; + else size *= 1.3; + return make_starfish (st, xgwa.width, xgwa.height, size); +} + + +static struct starfish * +reset_starfish (struct state *st) +{ + XGCValues gcv; + unsigned int flags = 0; + XWindowAttributes xgwa; + XGetWindowAttributes (st->dpy, st->window, &xgwa); + + st->cmap = xgwa.colormap; + + if (st->done_once) + { + if (st->colors && st->ncolors) + free_colors (st->dpy, st->cmap, st->colors, st->ncolors); + if (st->colors) + free (st->colors); + st->colors = 0; + XFreeGC (st->dpy, st->gc); + st->gc = 0; + } + + st->ncolors = get_integer_resource (st->dpy, "colors", "Colors"); + if (st->ncolors < 2) st->ncolors = 2; + if (st->ncolors <= 2) mono_p = True; + + if (mono_p) + st->colors = 0; + else + st->colors = (XColor *) malloc(sizeof(*st->colors) * (st->ncolors+1)); + + if (mono_p) + ; + else if (random() % 3) + make_smooth_colormap (st->dpy, xgwa.visual, st->cmap, st->colors, &st->ncolors, + True, 0, True); + else + make_uniform_colormap (st->dpy, xgwa.visual, st->cmap, st->colors, &st->ncolors, + True, 0, True); + + if (st->ncolors < 2) st->ncolors = 2; + if (st->ncolors <= 2) mono_p = True; + + st->fg_index = 0; + + if (!mono_p && !st->blob_p) + { + flags |= GCForeground; + gcv.foreground = st->colors[st->fg_index].pixel; + XSetWindowBackground (st->dpy, st->window, gcv.foreground); + } + + if (!st->done_once) + { + XClearWindow (st->dpy, st->window); + st->done_once = 1; + } + + flags |= GCFillRule; + gcv.fill_rule = EvenOddRule; + st->gc = XCreateGC (st->dpy, st->window, flags, &gcv); + + return make_window_starfish (st); +} + + + +static void +run_starfish (struct state *st, struct starfish *s) +{ + throb_starfish (s); + spin_starfish (s); + draw_starfish (st, st->window, st->gc, s, False); + + if (mono_p) + { + if (!st->initted) + { + st->black = get_pixel_resource (st->dpy, st->cmap, "background", "Background"); + st->white = get_pixel_resource (st->dpy, st->cmap, "foreground", "Foreground"); + st->initted = True; + st->fg_index = st->white; + XSetForeground (st->dpy, st->gc, st->fg_index); + } + else if (!s->blob_p) + { + st->fg_index = (st->fg_index == st->black ? st->white : st->black); + XSetForeground (st->dpy, st->gc, st->fg_index); + } + } + else + { + st->fg_index = (st->fg_index + 1) % st->ncolors; + XSetForeground (st->dpy, st->gc, st->colors [st->fg_index].pixel); + } +} + + +static void * +starfish_init (Display *dpy, Window window) +{ + struct state *st = (struct state *) calloc (1, sizeof(*st)); + char *s; + st->dpy = dpy; + st->window = window; + st->delay = get_integer_resource (st->dpy, "delay", "Delay"); + st->delay2 = get_integer_resource (st->dpy, "delay2", "Delay") * 1000000; +/* st->duration = get_seconds_resource (st->dpy, "duration", "Seconds");*/ + st->duration = get_integer_resource (st->dpy, "duration", "Seconds"); + st->direction = (random() & 1) ? 1 : -1; + + s = get_string_resource (st->dpy, "mode", "Mode"); + if (s && !strcasecmp (s, "blob")) + st->blob_p = True; + else if (s && !strcasecmp (s, "zoom")) + st->blob_p = False; + else if (!s || !*s || !strcasecmp (s, "random")) + st->blob_p = !(random() % 3); + else + fprintf (stderr, "%s: mode must be blob, zoom, or random", progname); + + if (st->blob_p) + st->delay *= 3; + + st->starfish = reset_starfish (st); + return st; +} + +static unsigned long +starfish_draw (Display *dpy, Window window, void *closure) +{ + struct state *st = (struct state *) closure; + struct starfish *s = st->starfish; + time_t now; + + run_starfish (st, s); + + if (st->duration > 0) + { + if (st->start_time == 0) + st->start_time = time ((time_t) 0); + now = time ((time_t) 0); + if (st->start_time + st->duration < now) + { + st->start_time = now; + + free_starfish (s); + + /* Every now and then, pick new colors; otherwise, just build + a new starfish with the current colors. */ + if (! (random () % 10)) + s = reset_starfish (st); + else + s = make_window_starfish (st); + + st->starfish = s; + } + } + + return st->delay; +} + +static void +starfish_reshape (Display *dpy, Window window, void *closure, + unsigned int w, unsigned int h) +{ + struct state *st = (struct state *) closure; + free_starfish (st->starfish); + st->starfish = 0; + st->starfish = reset_starfish (st); +} + +static Bool +starfish_event (Display *dpy, Window window, void *closure, XEvent *event) +{ + return False; +} + +static void +starfish_free (Display *dpy, Window window, void *closure) +{ + struct state *st = (struct state *) closure; + free (st); +} + + + + +static const char *starfish_defaults [] = { + ".background: black", + ".foreground: white", + "*fpsSolid: true", + "*delay: 10000", + "*thickness: 0", /* pixels, 0 = random */ + "*rotation: -1", /* degrees, -1 = "random" */ + "*colors: 200", + "*duration: 30", + "*delay2: 5", + "*mode: random", + 0 +}; + +static XrmOptionDescRec starfish_options [] = { + { "-delay", ".delay", XrmoptionSepArg, 0 }, + { "-delay2", ".delay2", XrmoptionSepArg, 0 }, + { "-thickness", ".thickness", XrmoptionSepArg, 0 }, + { "-rotation", ".rotation", XrmoptionSepArg, 0 }, + { "-colors", ".colors", XrmoptionSepArg, 0 }, + { "-duration", ".duration", XrmoptionSepArg, 0 }, + { "-mode", ".mode", XrmoptionSepArg, 0 }, + { "-blob", ".mode", XrmoptionNoArg, "blob" }, + { "-zoom", ".mode", XrmoptionNoArg, "zoom" }, + { 0, 0, 0, 0 } +}; + +XSCREENSAVER_MODULE ("Starfish", starfish) diff --git a/hacks/starfish.man b/hacks/starfish.man new file mode 100644 index 00000000..306f66c0 --- /dev/null +++ b/hacks/starfish.man @@ -0,0 +1,84 @@ +.TH XScreenSaver 1 "14-Jun-97" "X Version 11" +.SH NAME +starfish - radially-symmetric throbbing colormap-hacking graphics demo +.SH SYNOPSIS +.B starfish +[\-display \fIhost:display.screen\fP] [\-foreground \fIcolor\fP] [\-background \fIcolor\fP] [\-window] [\-root] [\-mono] [\-install] [\-visual \fIvisual\fP] [\-delay \fIusecs\fP] [\-delay2 \fIsecs\fP] [\-thickness \fIpixels\fP] [\-rotation \fIdegrees\fP] [\-duration \fIseconds\fP] [\-colors \fIint\fP] [\-blob] [\-no\-blob] +[\-fps] +.SH DESCRIPTION +The \fIstarfish\fP program draws radially symmetric objects, which expand, +contract, rotate, and turn inside out. It uses these shapes to lay down a +field of smooth colors, and then rotates the colormap. +.SH OPTIONS +.I starfish +accepts the following options: +.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 \-mono +If on a color display, pretend we're on a monochrome display. +.TP 8 +.B \-install +Install a private colormap for the window. +.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 \-delay \fImicroseconds\fP +How much of a delay should be introduced between steps of the animation. +Default 10000, or about 1/100th second. +.TP 8 +.B \-thickness \fIpixels\fP +How wide each color band should be. Default 0, meaning random (the chosen +value will be between 0 and 15.) +.TP 8 +.B \-rotation \fIdegrees\fP +How quickly the objects should rotate at each step. Default 0, meaning +random (the chosen value will be between 0 and 12 degrees.) +.TP 8 +.B \-colors \fIint\fP +How many colors to use. Default 200. The more colors, the smoother the +transitions will be, and the nicer the resultant images. +.TP 8 +.B \-duration \fIseconds\fP +How long to run before choosing a new shape. Default 30 seconds. +.TP 8 +.B \-delay2 \fIseconds\fP +When \fIduration\fP expires, how long to wait before starting a new run. +Default 5 seconds. +.TP 8 +.B \-blob +.TP 8 +.B \-no\-blob +If \fIblob\fP option is specified, then the raw shapes will be shown, +instead of a field of colors generated from them. +.TP 8 +.B \-fps +Display the current frame rate and CPU load. +.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 1997 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 , 14-Jun-97. diff --git a/hacks/strange.c b/hacks/strange.c new file mode 100644 index 00000000..604f471b --- /dev/null +++ b/hacks/strange.c @@ -0,0 +1,701 @@ +/* -*- Mode: C; tab-width: 4 -*- */ +/* strange --- strange attractors */ + +#if 0 +static const char sccsid[] = "@(#)strange.c 5.00 2000/11/01 xlockmore"; +#endif + +/*- +* Copyright (c) 1997 by Massimino Pascal +* +* Permission to use, copy, modify, and distribute this software and its +* documentation for any purpose and without fee is hereby granted, +* provided that the above copyright notice appear in all copies and that +* both that copyright notice and this permission notice appear in +* supporting documentation. +* +* This file is provided AS IS with no warranties of any kind. The author +* shall have no liability with respect to the infringement of copyrights, +* trade secrets or any patents by this file or any part thereof. In no +* event will the author be liable for any lost revenue or profits or +* other special, indirect and consequential damages. +* +* Revision History: +* 01-Nov-2000: Allocation checks +* 10-May-1997: jwz@jwz.org: turned into a standalone program. +* Made it render into an offscreen bitmap and then copy +* that onto the screen, to reduce flicker. +* +* strange attractors are not so hard to find... +*/ + +/* TODO: Bring over tweaks from 3.x version. +* For a good idea of what's missing, diff strange.c.20081107-good2 against strange.c-3.29 +* We forked from the 3.29 series at 20081107, so anything added since then may be missing. +*/ + +#ifdef STANDALONE +# define MODE_strange +# define DEFAULTS "*delay: 10000 \n" \ + "*ncolors: 100 \n" \ + "*fpsSolid: True \n" + +# define SMOOTH_COLORS +# define refresh_strange 0 +# define strange_handle_event 0 +# include "xlockmore.h" /* from the xscreensaver distribution */ +#else /* !STANDALONE */ +# include "xlock.h" /* from the xlockmore distribution */ +#endif /* !STANDALONE */ + +#ifdef MODE_strange +#define DEF_CURVE "10" +#define DEF_POINTS "5500" + +/*static int curve;*/ +static int points; + +static XrmOptionDescRec opts[] = +{ +/* {"-curve", ".strange.curve", XrmoptionSepArg, 0}, */ + {"-points", ".strange.points", XrmoptionSepArg, 0}, +}; +static argtype vars[] = +{ +/* {&curve, "curve", "Curve", DEF_CURVE, t_Int},*/ + {&points, "points", "Points", DEF_POINTS, t_Int}, +}; +static OptionStruct desc[] = +{ +/* {"-curve", "set the curve factor of the attractors"},*/ + {"-points", "change the number of points/iterations each frame"}, +}; +ENTRYPOINT ModeSpecOpt strange_opts = +{sizeof opts / sizeof opts[0], opts, +sizeof vars / sizeof vars[0], vars, desc}; + +#ifdef USE_MODULES +ModStruct strange_description = +{"strange", "init_strange", "draw_strange", "release_strange", +"init_strange", "init_strange", (char *) NULL, &strange_opts, +1000, 1, 1, 1, 64, 1.0, "", +"Shows strange attractors", 0, NULL}; +#endif + +#ifdef HAVE_COCOA +# define NO_DBUF +#endif + +typedef float DBL; +typedef int PRM; + +#define UNIT (1<<12) +#define UNIT2 (1<<14) +/* #define UNIT2 (3140*UNIT/1000) */ + +#define SKIP_FIRST 100 +#define DBL_To_PRM(x) (PRM)( (DBL)(UNIT)*(x) ) + + +#define DO_FOLD(a) (a)<0 ? -A->Fold[ (-(a))&(UNIT2-1) ] : A->Fold[ (a)&(UNIT2-1) ] + +#if 0 +#define DO_FOLD(a) (a)<-UNIT2 ? -A->Fold[(-(a))%UNIT2] : (a)<0 ? -A->Fold[ -(a) ] :\ +(a)>UNIT2 ? A->Fold[ (a)%UNIT2 ] : A->Fold[ (a) ] +#define DO_FOLD(a) DBL_To_PRM( sin( (DBL)(a)/UNIT ) ) +#define DO_FOLD(a) (a)<0 ? DBL_To_PRM( exp( 16.0*(a)/UNIT2 ) )-1.0 : \ +DBL_To_PRM( 1.0-exp( -16.0*(a)/UNIT2 ) ) +#endif + +/* useAccumulator performs two functions: +* If it is defined, then support for the accumulator will be compiled. +* It is also the condition for which the accumulator renderer will engage. +*/ +#define useAccumulator (Root->Max_Pt > 6000) +#define ACC_GAMMA 10.0 +#define NUM_COLS 150 +/* Extra options: */ +#define VARY_SPEED_TO_AVOID_BOREDOM +#define POINTS_HISTORY +#define MERGE_FRAMES 3 + +/******************************************************************/ + +#define MAX_PRM 3*5 + +typedef struct _ATTRACTOR { + DBL Prm1[MAX_PRM], Prm2[MAX_PRM]; + PRM Prm[MAX_PRM], *Fold; + void (*Iterate) (struct _ATTRACTOR *, PRM, PRM, PRM *, PRM *); + XPoint *Buffer1, *Buffer2; + int Cur_Pt, Max_Pt; + int Col, Count, Speed; + int Width, Height; + Pixmap dbuf; /* jwz */ + GC dbuf_gc; + #ifdef useAccumulator + int **accMap; + #endif +} ATTRACTOR; + +static ATTRACTOR *Root = (ATTRACTOR *) NULL; + +#ifdef useAccumulator +static XColor* cols; +#endif + +#ifdef POINTS_HISTORY +static int numOldPoints; +static int* oldPointsX; +static int* oldPointsY; +static int oldPointsIndex; +static int startedClearing; +#endif + +static DBL Amp_Prm[MAX_PRM] = +{ + 1.0, 3.5, 3.5, 2.5, 4.7, + 1.0, 3.5, 3.6, 2.5, 4.7, + 1.0, 1.5, 2.2, 2.1, 3.5 +}; +static DBL Mid_Prm[MAX_PRM] = +{ + 0.0, 1.5, 0.0, .5, 1.5, + 0.0, 1.5, 0.0, .5, 1.5, + 0.0, 1.5, -1.0, -.5, 2.5, +}; + +static DBL +Gauss_Rand(DBL c, DBL A, DBL S) +{ + DBL y; + + y = (DBL) LRAND() / MAXRAND; + y = A * (1.0 - exp(-y * y * S)) / (1.0 - exp(-S)); + if (NRAND(2)) + return (c + y); + else + return (c - y); +} + +static void +Random_Prm(DBL * Prm) +{ + int i; + + for (i = 0; i < MAX_PRM; ++i) + Prm[i] = Gauss_Rand(Mid_Prm[i], Amp_Prm[i], 4.0); +} + +/***************************************************************/ + + /* 2 examples of non-linear map */ + +static void +Iterate_X2(ATTRACTOR * A, PRM x, PRM y, PRM * xo, PRM * yo) +{ + PRM xx, yy, xy, x2y, y2x, Tmp; + + xx = (x * x) / UNIT; + x2y = (xx * y) / UNIT; + yy = (y * y) / UNIT; + y2x = (yy * x) / UNIT; + xy = (x * y) / UNIT; + + Tmp = A->Prm[1] * xx + A->Prm[2] * xy + A->Prm[3] * yy + A->Prm[4] * x2y; + Tmp = A->Prm[0] - y + (Tmp / UNIT); + *xo = DO_FOLD(Tmp); + Tmp = A->Prm[6] * xx + A->Prm[7] * xy + A->Prm[8] * yy + A->Prm[9] * y2x; + Tmp = A->Prm[5] + x + (Tmp / UNIT); + *yo = DO_FOLD(Tmp); +} + +static void +Iterate_X3(ATTRACTOR * A, PRM x, PRM y, PRM * xo, PRM * yo) +{ + PRM xx, yy, xy, x2y, y2x, Tmp_x, Tmp_y, Tmp_z; + + xx = (x * x) / UNIT; + x2y = (xx * y) / UNIT; + yy = (y * y) / UNIT; + y2x = (yy * x) / UNIT; + xy = (x * y) / UNIT; + + Tmp_x = A->Prm[1] * xx + A->Prm[2] * xy + A->Prm[3] * yy + A->Prm[4] * x2y; + Tmp_x = A->Prm[0] - y + (Tmp_x / UNIT); + Tmp_x = DO_FOLD(Tmp_x); + + Tmp_y = A->Prm[6] * xx + A->Prm[7] * xy + A->Prm[8] * yy + A->Prm[9] * y2x; + Tmp_y = A->Prm[5] + x + (Tmp_y / UNIT); + + Tmp_y = DO_FOLD(Tmp_y); + + Tmp_z = A->Prm[11] * xx + A->Prm[12] * xy + A->Prm[13] * yy + A->Prm[14] * y2x; + Tmp_z = A->Prm[10] + x + (Tmp_z / UNIT); + Tmp_z = UNIT + Tmp_z * Tmp_z / UNIT; + + *xo = (Tmp_x * UNIT) / Tmp_z; + *yo = (Tmp_y * UNIT) / Tmp_z; +} + +static void (*Funcs[2]) (ATTRACTOR *, PRM, PRM, PRM *, PRM *) = { + Iterate_X2, Iterate_X3 +}; + +/***************************************************************/ + +static void +free_strange(Display *display, ATTRACTOR *A) +{ + if (A->Buffer1 != NULL) { + (void) free((void *) A->Buffer1); + A->Buffer1 = (XPoint *) NULL; + } + if (A->Buffer2 != NULL) { + (void) free((void *) A->Buffer2); + A->Buffer2 = (XPoint *) NULL; + } + if (A->dbuf) { + XFreePixmap(display, A->dbuf); + A->dbuf = None; + } + if (A->dbuf_gc) { + XFreeGC(display, A->dbuf_gc); + A->dbuf_gc = None; + } + if (A->Fold != NULL) { + (void) free((void *) A->Fold); + A->Fold = (PRM *) NULL; + } +} + +ENTRYPOINT void +draw_strange(ModeInfo * mi) +{ + int i, j, n, Cur_Pt; + PRM x, y, xo, yo; + DBL u; + XPoint *Buf; + Display *display = MI_DISPLAY(mi); + Window window = MI_WINDOW(mi); + GC gc = MI_GC(mi); + DBL Lx, Ly; + void (*Iterate) (ATTRACTOR *, PRM, PRM, PRM *, PRM *); + PRM xmin, xmax, ymin, ymax; + ATTRACTOR *A; + + if (Root == NULL) + return; + A = &Root[MI_SCREEN(mi)]; + if (A->Fold == NULL) + return; + + Cur_Pt = A->Cur_Pt; + Iterate = A->Iterate; + + u = (DBL) (A->Count) / 40000.0; + for (j = MAX_PRM - 1; j >= 0; --j) + A->Prm[j] = DBL_To_PRM((1.0 - u) * A->Prm1[j] + u * A->Prm2[j]); + + /* We collect the accumulation of the orbits in the 2d int array field. */ +#ifndef POINTS_HISTORY + #ifdef useAccumulator + if (useAccumulator) { + for (i=0;iWidth;i++) { + for (j=0;jHeight;j++) { + A->accMap[i][j] = 0; + + } + } + } + #endif +#endif + + x = y = DBL_To_PRM(.0); + for (n = SKIP_FIRST; n; --n) { + (*Iterate) (A, x, y, &xo, &yo); + x = xo + NRAND(8) - 4; + y = yo + NRAND(8) - 4; + } + + xmax = 0; + xmin = UNIT * 4; + ymax = 0; + ymin = UNIT * 4; + A->Cur_Pt = 0; + Buf = A->Buffer2; + Lx = (DBL) A->Width / UNIT / 2.2; + Ly = (DBL) A->Height / UNIT / 2.2; + for (n = A->Max_Pt; n; --n) { + (*Iterate) (A, x, y, &xo, &yo); + #ifdef useAccumulator + if (useAccumulator) { + int mx,my; + mx = (short) ( A->Width*0.1 + A->Width*0.8 * (xo - xmin) / (xmax - xmin) ); + my = (short) ( A->Width*0.1 + (A->Height - A->Width*0.2) * (yo - ymin) / (ymax - ymin) ); + if (mx>=0 && my>=0 && mxWidth && myHeight) { + A->accMap[mx][my]++; + } +#ifdef POINTS_HISTORY + /* #define clearOldPoint(i) { if (startedClearing) { field[oldPoints[i].x][oldPoints[i].y]--; } } + #define saveUnplot(X,Y) { clearOldPoint(oldPointsIndex) oldPoints[oldPointsIndex].x = X; oldPoints[oldPointsIndex].y = Y; oldPointsIndex = (oldPointsIndex + 1) % numOldPoints; if (oldPointsIndex==0) { startedClearing=1; } } + saveUnplot(mx,my) */ + if (startedClearing) { + int oldX = oldPointsX[oldPointsIndex]; + int oldY = oldPointsY[oldPointsIndex]; + if (oldX>=0 && oldY>=0 && oldXWidth && oldYHeight) { + A->accMap[oldX][oldY]--; + } + } + oldPointsX[oldPointsIndex] = mx; + oldPointsY[oldPointsIndex] = my; + oldPointsIndex = (oldPointsIndex + 1) % numOldPoints; + if (oldPointsIndex==0) { startedClearing=1; } +#endif + } else { + #endif + Buf->x = (int) (Lx * (x + DBL_To_PRM(1.1))); + Buf->y = (int) (Ly * (DBL_To_PRM(1.1) - y)); + Buf++; + A->Cur_Pt++; + #ifdef useAccumulator + } + #endif + /* (void) fprintf( stderr, "X,Y: %d %d ", Buf->x, Buf->y ); */ + if (xo > xmax) + xmax = xo; + else if (xo < xmin) + xmin = xo; + if (yo > ymax) + ymax = yo; + else if (yo < ymin) + ymin = yo; + x = xo + NRAND(8) - 4; + y = yo + NRAND(8) - 4; + } + + MI_IS_DRAWN(mi) = True; + + XSetForeground(display, gc, MI_BLACK_PIXEL(mi)); + + #ifdef useAccumulator + if (useAccumulator) { + float colorScale; + int col; + #ifdef VARY_SPEED_TO_AVOID_BOREDOM + int pixelCount = 0; + #endif + colorScale = (A->Width*A->Height/640.0/480.0*800000.0/(float)A->Max_Pt*(float)NUM_COLS/256); + if (A->dbuf != None) { + XSetForeground(display, A->dbuf_gc, 0); + XFillRectangle(display, A->dbuf, A->dbuf_gc, 0, 0, A->Width, A->Height); + } else { + XSetForeground(display, gc, MI_BLACK_PIXEL(mi)); + XFillRectangle(display, window, gc, 0, 0, A->Width, A->Height); + } + for (i=0;iWidth;i++) { + for (j=0;jHeight;j++) { + if (A->accMap[i][j]>0) { + col = (float)A->accMap[i][j] * colorScale; + if (col>NUM_COLS-1) { + col = NUM_COLS-1; + } + #ifdef VARY_SPEED_TO_AVOID_BOREDOM + if (col>0) { + if (colCol % MI_NPIXELS(mi)));*/ + XSetForeground(display, gc, cols[col].pixel); + if (A->dbuf != None) { + XSetForeground(display, A->dbuf_gc, cols[col].pixel); + XDrawPoint(display, A->dbuf, A->dbuf_gc, i, j); + } else { + XSetForeground(display, gc, cols[col].pixel); + XDrawPoint(display, window, gc, i, j); + } + } + } + } + if (A->dbuf != None) { + XCopyArea(display, A->dbuf, window, gc, 0, 0, A->Width, A->Height, 0, 0); + } + #ifdef VARY_SPEED_TO_AVOID_BOREDOM + /* Increaase the rate of change of the parameters if the attractor has become visually boring. */ + if ((xmax - xmin < DBL_To_PRM(.2)) && (ymax - ymin < DBL_To_PRM(.2))) { + A->Speed *= 1.25; + } else if (pixelCount>0 && pixelCountWidth*A->Height/1000) { + A->Speed *= 1.25; /* A->Count = 1000; */ + } else { + A->Speed = 4; /* reset to normal/default */ + } + if (A->Speed > 32) + A->Speed = 32; + A->Count += A->Speed; + if (A->Count >= 1000) { + for (i = MAX_PRM - 1; i >= 0; --i) + A->Prm1[i] = A->Prm2[i]; + Random_Prm(A->Prm2); + A->Count = 0; + } + #endif + } else { + #endif + + if (A->dbuf != None) { /* jwz */ + XSetForeground(display, A->dbuf_gc, 0); +/* XDrawPoints(display, A->dbuf, A->dbuf_gc, A->Buffer1, + Cur_Pt,CoordModeOrigin); */ + XFillRectangle(display, A->dbuf, A->dbuf_gc, 0, 0, A->Width, A->Height); + } else + XDrawPoints(display, window, gc, A->Buffer1, Cur_Pt, CoordModeOrigin); + + if (MI_NPIXELS(mi) < 2) + XSetForeground(display, gc, MI_WHITE_PIXEL(mi)); + else + XSetForeground(display, gc, MI_PIXEL(mi, A->Col % MI_NPIXELS(mi))); + + if (A->dbuf != None) { + XSetForeground(display, A->dbuf_gc, 1); + XDrawPoints(display, A->dbuf, A->dbuf_gc, A->Buffer2, A->Cur_Pt, + CoordModeOrigin); + XCopyPlane(display, A->dbuf, window, gc, 0, 0, A->Width, A->Height, 0, 0, 1); + } else + XDrawPoints(display, window, gc, A->Buffer2, A->Cur_Pt, CoordModeOrigin); + + #ifdef useAccumulator + } + #endif + + Buf = A->Buffer1; + A->Buffer1 = A->Buffer2; + A->Buffer2 = Buf; + + if ((xmax - xmin < DBL_To_PRM(.2)) && (ymax - ymin < DBL_To_PRM(.2))) + A->Count += 4 * A->Speed; + else + A->Count += A->Speed; + if (A->Count >= 1000) { + for (i = MAX_PRM - 1; i >= 0; --i) + A->Prm1[i] = A->Prm2[i]; + Random_Prm(A->Prm2); + A->Count = 0; + } + A->Col++; + mi->recursion_depth = A->Count; +} + + +/***************************************************************/ + +ENTRYPOINT void +init_strange(ModeInfo * mi) +{ + Display *display = MI_DISPLAY(mi); + Window window = MI_WINDOW(mi); +#ifndef NO_DBUF + GC gc = MI_GC(mi); +#endif + ATTRACTOR *Attractor; + +#ifdef POINTS_HISTORY + startedClearing=0; + oldPointsIndex=0; +#endif + + if (Root == NULL) { + if ((Root = (ATTRACTOR *) calloc(MI_NUM_SCREENS(mi), + sizeof (ATTRACTOR))) == NULL) + return; + } + Attractor = &Root[MI_SCREEN(mi)]; + + if (Attractor->Fold == NULL) { + int i; + + if ((Attractor->Fold = (PRM *) calloc(UNIT2 + 1, + sizeof (PRM))) == NULL) { + free_strange(display, Attractor); + return; + } + for (i = 0; i <= UNIT2; ++i) { + DBL x; + + /* x = ( DBL )(i)/UNIT2; */ + /* x = sin( M_PI/2.0*x ); */ + /* x = sqrt( x ); */ + /* x = x*x; */ + /* x = x*(1.0-x)*4.0; */ + x = (DBL) (i) / UNIT; + x = sin(x); + Attractor->Fold[i] = DBL_To_PRM(x); + } + } + + Attractor->Max_Pt = points; + + if (Attractor->Buffer1 == NULL) + if ((Attractor->Buffer1 = (XPoint *) calloc(Attractor->Max_Pt, + sizeof (XPoint))) == NULL) { + free_strange(display, Attractor); + return; + } + if (Attractor->Buffer2 == NULL) + if ((Attractor->Buffer2 = (XPoint *) calloc(Attractor->Max_Pt, + sizeof (XPoint))) == NULL) { + free_strange(display, Attractor); + return; + } + + Attractor->Width = MI_WIDTH(mi); + Attractor->Height = MI_HEIGHT(mi); + Attractor->Cur_Pt = 0; + Attractor->Count = 0; + Attractor->Col = NRAND(MI_NPIXELS(mi)); + Attractor->Speed = 4; + + Attractor->Iterate = Funcs[NRAND(2)]; + Random_Prm(Attractor->Prm1); + Random_Prm(Attractor->Prm2); +#ifndef NO_DBUF + if (Attractor->dbuf != None) + XFreePixmap(display, Attractor->dbuf); +#ifdef useAccumulator +#define colorDepth ( useAccumulator ? MI_DEPTH(mi) : 1 ) +#else +#define colorDepth 1 +#endif + Attractor->dbuf = XCreatePixmap(display, window, + Attractor->Width, Attractor->Height, colorDepth); + /* Allocation checked */ + if (Attractor->dbuf != None) { + XGCValues gcv; + + gcv.foreground = 0; + gcv.background = 0; +#ifndef HAVE_COCOA + gcv.graphics_exposures = False; +#endif /* HAVE_COCOA */ + gcv.function = GXcopy; + + if (Attractor->dbuf_gc != None) + XFreeGC(display, Attractor->dbuf_gc); + + if ((Attractor->dbuf_gc = XCreateGC(display, Attractor->dbuf, +#ifndef HAVE_COCOA + GCGraphicsExposures | +#endif /* HAVE_COCOA */ + GCFunction | GCForeground | GCBackground, + &gcv)) == None) { + XFreePixmap(display, Attractor->dbuf); + Attractor->dbuf = None; + } else { + XFillRectangle(display, Attractor->dbuf, Attractor->dbuf_gc, + 0, 0, Attractor->Width, Attractor->Height); + XSetBackground(display, gc, MI_BLACK_PIXEL(mi)); + XSetFunction(display, gc, GXcopy); + } + } +#endif + + +#ifdef useAccumulator + #define A Attractor + if (useAccumulator) { + XWindowAttributes xgwa; + int i,j; + XGetWindowAttributes (display, window, &xgwa); + /* cmap = xgwa.colormap; */ + /* cmap = XCreateColormap(display, window, MI_VISUAL(mi), AllocAll); */ + Attractor->accMap = (int**)calloc(Attractor->Width,sizeof(int*)); + for (i=0;iWidth;i++) { + Attractor->accMap[i] = (int*)calloc(Attractor->Height,sizeof(int)); + for (j=0;jHeight;j++) { + Attractor->accMap[i][j] = 0; + } + } +#ifdef POINTS_HISTORY + numOldPoints = A->Max_Pt * MERGE_FRAMES; + oldPointsX = (int*)calloc(numOldPoints,sizeof(int)); + oldPointsY = (int*)calloc(numOldPoints,sizeof(int)); +#endif + cols = (XColor*)calloc(NUM_COLS,sizeof(XColor)); + for (i=0;iWidth;i++) { + (void) free((void *) Root->accMap[i]); + } + (void) free((void *) Root->accMap); +#endif +#ifdef POINTS_HISTORY + free(oldPointsX); + free(oldPointsY); +#endif + for (screen = 0; screen < MI_NUM_SCREENS(mi); ++screen) + free_strange(MI_DISPLAY(mi), &Root[screen]); + (void) free((void *) Root); + Root = (ATTRACTOR *) NULL; + } +} + +XSCREENSAVER_MODULE ("Strange", strange) + +#endif /* MODE_strange */ diff --git a/hacks/strange.man b/hacks/strange.man new file mode 100644 index 00000000..318f630c --- /dev/null +++ b/hacks/strange.man @@ -0,0 +1,62 @@ +.TH XScreenSaver 1 "10-May-97" "X Version 11" +.SH NAME +strange - draws strange attractors +.SH SYNOPSIS +.B strange +[\-display \fIhost:display.screen\fP] [\-foreground \fIcolor\fP] [\-background \fIcolor\fP] [\-window] [\-root] [\-mono] [\-install] [\-visual \fIvisual\fP] [\-ncolors \fIinteger\fP] [\-delay \fImicroseconds\fP] + +[\-fps] +.SH DESCRIPTION +The \fIstrange\fP program draws strange attractors +.SH OPTIONS +.I strange +accepts the following options: +.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 \-mono +If on a color display, pretend we're on a monochrome display. +.TP 8 +.B \-install +Install a private colormap for the window. +.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 \-ncolors \fIinteger\fP +How many colors should be used (if possible). Default 100. +The colors are chosen randomly. +.TP 8 +.B \-fps +Display the current frame rate and CPU load. +.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), +.BR xlock (1) +.SH COPYRIGHT +Copyright \(co 1997 by Massimino Pascal. + +Permission to use, copy, modify, and distribute this software and its +documentation for any purpose and without fee is hereby granted, +provided that the above copyright notice appear in all copies and that +both that copyright notice and this permission notice appear in +supporting documentation. +.SH AUTHOR +Massimino Pascal , 1997. + +Ability to run standalone or with \fIxscreensaver\fP added by +Jamie Zawinski , 10-May-97. diff --git a/hacks/substrate.c b/hacks/substrate.c new file mode 100644 index 00000000..517c4977 --- /dev/null +++ b/hacks/substrate.c @@ -0,0 +1,739 @@ +/* + * Substrate (dragorn@kismetwireless.net) + * Directly ported code from complexification.net Substrate art + * http://complexification.net/gallery/machines/substrate/applet_s/substrate_s.pde + * + * Substrate code: + * j.tarbell June, 2004 + * Albuquerque, New Mexico + * complexification.net + * + * CHANGES + * + * 1.1 dragorn Jan 04 2005 Fixed some indenting, typo in errors for parsing + * cmdline args + * 1.1 dagraz Jan 04 2005 Added option for circular cracks (David Agraz) + * Cleaned up issues with timeouts in start_crack (DA) + * 1.0 dragorn Oct 10 2004 First port done + * + * Directly based the hacks of: + * + * xscreensaver, Copyright (c) 1997, 1998, 2002 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. + */ + +#include +#include "screenhack.h" + +/* this program goes faster if some functions are inline. The following is + * borrowed from ifs.c */ +#if !defined( __GNUC__ ) && !defined(__cplusplus) && !defined(c_plusplus) +#undef inline +#define inline /* */ +#endif + +#define STEP 0.42 + +/* Raw colormap extracted from pollockEFF.gif */ +static const char *rgb_colormap[] = { + "#201F21", "#262C2E", "#352626", "#372B27", + "#302C2E", "#392B2D", "#323229", "#3F3229", + "#38322E", "#2E333D", "#333A3D", "#473329", + "#40392C", "#40392E", "#47402C", "#47402E", + "#4E402C", "#4F402E", "#4E4738", "#584037", + "#65472D", "#6D5D3D", "#745530", "#755532", + "#745D32", "#746433", "#7C6C36", "#523152", + "#444842", "#4C5647", "#655D45", "#6D5D44", + "#6C5D4E", "#746C43", "#7C6C42", "#7C6C4B", + "#6B734B", "#73734B", "#7B7B4A", "#6B6C55", + "#696D5E", "#7B6C5D", "#6B7353", "#6A745D", + "#727B52", "#7B7B52", "#57746E", "#687466", + "#9C542B", "#9D5432", "#9D5B35", "#936B36", + "#AA7330", "#C45A27", "#D95223", "#D85A20", + "#DB5A23", "#E57037", "#836C4B", "#8C6B4B", + "#82735C", "#937352", "#817B63", "#817B6D", + "#927B63", "#D9893B", "#E49832", "#DFA133", + "#E5A037", "#F0AB3B", "#8A8A59", "#B29A58", + "#89826B", "#9A8262", "#888B7C", "#909A7A", + "#A28262", "#A18A69", "#A99968", "#99A160", + "#99A168", "#CA8148", "#EB8D43", "#C29160", + "#C29168", "#D1A977", "#C9B97F", "#F0E27B", + "#9F928B", "#C0B999", "#E6B88F", "#C8C187", + "#E0C886", "#F2CC85", "#F5DA83", "#ECDE9D", + "#F5D294", "#F5DA94", "#F4E784", "#F4E18A", + "#F4E193", "#E7D8A7", "#F1D4A5", "#F1DCA5", + "#F4DBAD", "#F1DCAE", "#F4DBB5", "#F5DBBD", + "#F4E2AD", "#F5E9AD", "#F4E3BE", "#F5EABE", + "#F7F0B6", "#D9D1C1", "#E0D0C0", "#E7D8C0", + "#F1DDC6", "#E8E1C0", "#F3EDC7", "#F6ECCE", + "#F8F2C7", "#EFEFD0", 0 +}; + +typedef struct { + /* Synthesis of data from Crack:: and SandPainter:: */ + float x, y; + float t; + float ys, xs, t_inc; /* for curvature calculations */ + + int curved; + + unsigned long sandcolor; + float sandp, sandg; + + float degrees_drawn; + + int crack_num; + +} crack; + +struct field { + unsigned int height; + unsigned int width; + + unsigned int initial_cracks; + + unsigned int num; + unsigned int max_num; + + int grains; /* number of grains in the sand painting */ + + int circle_percent; + + crack *cracks; /* grid of cracks */ + int *cgrid; /* grid of actual crack placement */ + + /* Raw map of pixels we need to keep for alpha blending */ + unsigned long int *off_img; + + /* color parms */ + int numcolors; + unsigned long *parsedcolors; + unsigned long fgcolor; + unsigned long bgcolor; + int visdepth; + + unsigned int cycles; + + unsigned int wireframe; +}; + +struct state { + Display *dpy; + Window window; + + struct field *f; + unsigned int max_cycles; + int growth_delay; + GC fgc; + XWindowAttributes xgwa; + XGCValues gcv; +}; + + +static void +*xrealloc(void *p, size_t size) +{ + void *ret; + if ((ret = realloc(p, size)) == NULL) { + fprintf(stderr, "%s: out of memory\n", progname); + exit(1); + } + return ret; +} + +static struct field +*init_field(void) +{ + struct field *f = xrealloc(NULL, sizeof(struct field)); + f->height = 0; + f->width = 0; + f->initial_cracks = 0; + f->num = 0; + f->max_num = 0; + f->cracks = NULL; + f->cgrid = NULL; + f->off_img = NULL; + f->numcolors = 0; + f->parsedcolors = NULL; + f->cycles = 0; + f->wireframe = 0; + f->fgcolor = 0; + f->bgcolor = 0; + f->visdepth = 0; + f->grains = 0; + f->circle_percent = 0; + return f; +} + +/* Quick references to pixels in the offscreen map and in the crack grid */ +#define ref_pixel(f, x, y) ((f)->off_img[(y) * (f)->width + (x)]) +#define ref_cgrid(f, x, y) ((f)->cgrid[(y) * (f)->width + (x)]) + +static inline void start_crack(struct field *f, crack *cr) +{ + /* synthesis of Crack::findStart() and crack::startCrack() */ + int px = 0; + int py = 0; + int found = 0; + int timeout = 0; + float a; + + /* shift until crack is found */ + while ((!found) && (timeout++ < 10000)) { + px = (int) (random() % f->width); + py = (int) (random() % f->height); + + if (ref_cgrid(f, px, py) < 10000) + found = 1; + } + + if ( !found ) { + /* We timed out. Use our default values */ + px = cr->x; + py = cr->y; + + /* Sanity check needed */ + if (px < 0) px = 0; + if (px >= f->width) px = f->width - 1; + if (py < 0) py = 0; + if (py >= f->height) py = f->height - 1; + + ref_cgrid(f, px, py) = cr->t; + } + + /* start a crack */ + a = ref_cgrid(f, px, py); + + if ((random() % 100) < 50) { + /* conversion of the java int(random(-2, 2.1)) */ + a -= 90 + (frand(4.1) - 2.0); + } else { + a += 90 + (frand(4.1) - 2.0); + } + + if ((random() % 100) < f->circle_percent) { + float r; /* radius */ + float radian_inc; + + cr->curved = 1; + cr->degrees_drawn = 0; + + r = 10 + (random() % ((f->width + f->height) / 2)); + + if ((random() % 100) < 50) { + r *= -1; + } + + /* arc length = r * theta => theta = arc length / r */ + radian_inc = STEP / r; + cr->t_inc = radian_inc * 360 / 2 / M_PI; + + cr->ys = r * sin(radian_inc); + cr->xs = r * ( 1 - cos(radian_inc)); + + } + else { + cr->curved = 0; + } + + /* Condensed from Crack::startCrack */ + cr->x = px + ((float) 0.61 * cos(a * M_PI / 180)); + cr->y = py + ((float) 0.61 * sin(a * M_PI / 180)); + cr->t = a; + +} + +static inline void make_crack(struct field *f) +{ + crack *cr; + + if (f->num < f->max_num) { + /* make a new crack */ + f->cracks = (crack *) xrealloc(f->cracks, sizeof(crack) * (f->num + 1)); + + cr = &(f->cracks[f->num]); + /* assign colors */ + cr->sandp = 0; + cr->sandg = (frand(0.2) - 0.01); + cr->sandcolor = f->parsedcolors[random() % f->numcolors]; + cr->crack_num = f->num; + cr->curved = 0; + cr->degrees_drawn = 0; + + /* We could use these values in the timeout case of start_crack */ + + cr->x = random() % f->width; + cr->y = random() % f->height; + cr->t = random() % 360; + + /* start it */ + start_crack(f, cr); + + f->num++; + } +} + +static inline void point2rgb(int depth, unsigned long c, int *r, int *g, int *b) +{ + switch(depth) { + case 32: + case 24: +#ifdef HAVE_COCOA + /* This program idiotically does not go through a color map, so + we have to hardcode in knowledge of how jwxyz.a packs pixels! + Fix it to go through st->colors[st->ncolors] instead! + */ + *r = (c & 0x00ff0000) >> 16; + *g = (c & 0x0000ffff) >> 8; + *b = (c & 0x000000ff); +#else + *g = (c & 0xff00) >> 8; + *r = (c & 0xff0000) >> 16; + *b = c & 0xff; +#endif + break; + case 16: + *g = ((c >> 5) & 0x3f) << 2; + *r = ((c >> 11) & 0x1f) << 3; + *b = (c & 0x1f) << 3; + break; + case 15: + *g = ((c >> 5) & 0x1f) << 3; + *r = ((c >> 10) & 0x1f) << 3; + *b = (c & 0x1f) << 3; + break; + } +} + +static inline unsigned long rgb2point(int depth, int r, int g, int b) +{ + unsigned long ret = 0; + + switch(depth) { + case 32: + case 24: +#ifdef HAVE_COCOA + /* This program idiotically does not go through a color map, so + we have to hardcode in knowledge of how jwxyz.a packs pixels! + Fix it to go through st->colors[st->ncolors] instead! + */ + ret = 0xFF000000 | (r << 16) | (g << 8) | b; +#else + ret |= (r << 16) | (g << 8) | b; +#endif + break; + case 16: + ret = ((r>>3) << 11) | ((g>>2)<<5) | (b>>3); + break; + case 15: + ret = ((r>>3) << 10) | ((g>>3)<<5) | (b>>3); + break; + } + + return ret; +} + +/* alpha blended point drawing -- this is Not Right and will likely fail on + * non-intel platforms as it is now, needs fixing */ +static inline unsigned long +trans_point(struct state *st, + int x1, int y1, unsigned long myc, float a, + struct field *f) +{ + if ((x1 >= 0) && (x1 < f->width) && (y1 >= 0) && (y1 < f->height)) { + if (a >= 1.0) { + ref_pixel(f, x1, y1) = myc; + } else { + int or = 0, og = 0, ob = 0; + int r = 0, g = 0, b = 0; + int nr, ng, nb; + unsigned long c; + + c = ref_pixel(f, x1, y1); + + point2rgb(f->visdepth, c, &or, &og, &ob); + point2rgb(f->visdepth, myc, &r, &g, &b); + + nr = or + (r - or) * a; + ng = og + (g - og) * a; + nb = ob + (b - ob) * a; + + c = rgb2point(f->visdepth, nr, ng, nb); + + ref_pixel(f, x1, y1) = c; + + return c; + } + } + + return f->bgcolor; +} + +static inline void +region_color(struct state *st, GC fgc, struct field *f, crack *cr) +{ + /* synthesis of Crack::regionColor() and SandPainter::render() */ + + float rx = cr->x; + float ry = cr->y; + int openspace = 1; + int cx, cy; + float maxg; + int grains, i; + float w; + float drawx, drawy; + unsigned long c; + + while (openspace) { + /* move perpendicular to crack */ + rx += (0.81 * sin(cr->t * M_PI/180)); + ry -= (0.81 * cos(cr->t * M_PI/180)); + + cx = (int) rx; + cy = (int) ry; + + if ((cx >= 0) && (cx < f->width) && (cy >= 0) && (cy < f->height)) { + /* safe to check */ + if (f->cgrid[cy * f->width + cx] > 10000) { + /* space is open */ + } else { + openspace = 0; + } + } else { + openspace = 0; + } + } + + /* SandPainter stuff here */ + + /* Modulate gain */ + cr->sandg += (frand(0.1) - 0.050); + maxg = 1.0; + + if (cr->sandg < 0) + cr->sandg = 0; + + if (cr->sandg > maxg) + cr->sandg = maxg; + + grains = f->grains; + + /* Lay down grains of sand */ + w = cr->sandg / (grains - 1); + + for (i = 0; i < grains; i++) { + drawx = (cr->x + (rx - cr->x) * sin(cr->sandp + sin((float) i * w))); + drawy = (cr->y + (ry - cr->y) * sin(cr->sandp + sin((float) i * w))); + + /* Draw sand bit */ + c = trans_point(st, drawx, drawy, cr->sandcolor, (0.1 - i / (grains * 10.0)), f); + + XSetForeground(st->dpy, fgc, c); + XDrawPoint(st->dpy, st->window, fgc, (int) drawx, (int) drawy); + XSetForeground(st->dpy, fgc, f->fgcolor); + } +} + +static void build_substrate(struct field *f) +{ + int tx; + /* int ty; */ + + f->cycles = 0; + + if (f->cgrid) { + free(f->cgrid); + f->cgrid = NULL; + } + + if (f->cracks) { + free(f->cracks); + f->cracks = NULL; + } + + f->num = 0; + + /* erase the crack grid */ + f->cgrid = (int *) xrealloc(f->cgrid, sizeof(int) * f->height * f->width); + memset(f->cgrid, 10001, f->height * f->width * sizeof(int)); + + /* Not necessary now that make_crack ensures we have usable default + * values in start_crack's timeout case + * make random crack seeds * + for (tx = 0; tx < 16; tx++) { + ty = (int) (random() % (f->width * f->height - 1)); + f->cgrid[ty] = (int) random() % 360; + } + */ + + /* make the initial cracks */ + for (tx = 0; tx < f->initial_cracks; tx++) + make_crack(f); +} + + +static inline void +movedrawcrack(struct state *st, GC fgc, struct field *f, int cracknum) +{ + /* Basically Crack::move() */ + + int cx, cy; + crack *cr = &(f->cracks[cracknum]); + + /* continue cracking */ + if ( !cr->curved ) { + cr->x += ((float) STEP * cos(cr->t * M_PI/180)); + cr->y += ((float) STEP * sin(cr->t * M_PI/180)); + } + else { + cr->x += ((float) cr->ys * cos(cr->t * M_PI/180)); + cr->y += ((float) cr->ys * sin(cr->t * M_PI/180)); + + cr->x += ((float) cr->xs * cos(cr->t * M_PI/180 - M_PI / 2)); + cr->y += ((float) cr->xs * sin(cr->t * M_PI/180 - M_PI / 2)); + + cr->t += cr->t_inc; + cr->degrees_drawn += abs(cr->t_inc); + } + + /* bounds check */ + /* modification of random(-0.33,0.33) */ + cx = (int) (cr->x + (frand(0.66) - 0.33)); + cy = (int) (cr->y + (frand(0.66) - 0.33)); + + + if ((cx >= 0) && (cx < f->width) && (cy >= 0) && (cy < f->height)) { + /* draw sand painter if we're not wireframe */ + if (!f->wireframe) + region_color(st, fgc, f, cr); + + /* draw fgcolor crack */ + ref_pixel(f, cx, cy) = f->fgcolor; + XDrawPoint(st->dpy, st->window, fgc, cx, cy); + + if ( cr->curved && (cr->degrees_drawn > 360) ) { + /* completed the circle, stop cracking */ + start_crack(f, cr); /* restart ourselves */ + make_crack(f); /* generate a new crack */ + } + /* safe to check */ + else if ((f->cgrid[cy * f->width + cx] > 10000) || + (abs(f->cgrid[cy * f->width + cx] - cr->t) < 5)) { + /* continue cracking */ + f->cgrid[cy * f->width + cx] = (int) cr->t; + } else if (abs(f->cgrid[cy * f->width + cx] - cr->t) > 2) { + /* crack encountered (not self), stop cracking */ + start_crack(f, cr); /* restart ourselves */ + make_crack(f); /* generate a new crack */ + } + } else { + /* out of bounds, stop cracking */ + + /* need these in case of timeout in start_crack */ + cr->x = random() % f->width; + cr->y = random() % f->height; + cr->t = random() % 360; + + start_crack(f, cr); /* restart ourselves */ + make_crack(f); /* generate a new crack */ + } + +} + + +static void build_img(Display *dpy, Window window, XWindowAttributes xgwa, GC fgc, + struct field *f) +{ + if (f->off_img) { + free(f->off_img); + f->off_img = NULL; + } + + f->off_img = (unsigned long *) xrealloc(f->off_img, sizeof(unsigned long) * + f->width * f->height); + + memset(f->off_img, f->bgcolor, sizeof(unsigned long) * f->width * f->height); +} + + +static void * +substrate_init (Display *dpy, Window window) +{ + struct state *st = (struct state *) calloc (1, sizeof(*st)); + XColor tmpcolor; + + st->dpy = dpy; + st->window = window; + st->f = init_field(); + + st->growth_delay = (get_integer_resource(st->dpy, "growthDelay", "Integer")); + st->max_cycles = (get_integer_resource(st->dpy, "maxCycles", "Integer")); + st->f->initial_cracks = (get_integer_resource(st->dpy, "initialCracks", "Integer")); + st->f->max_num = (get_integer_resource(st->dpy, "maxCracks", "Integer")); + st->f->wireframe = (get_boolean_resource(st->dpy, "wireFrame", "Boolean")); + st->f->grains = (get_integer_resource(st->dpy, "sandGrains", "Integer")); + st->f->circle_percent = (get_integer_resource(st->dpy, "circlePercent", "Integer")); + + if (st->f->initial_cracks <= 2) { + fprintf(stderr, "%s: Initial cracks must be greater than 2\n", progname); + exit (1); + } + + if (st->f->max_num <= 10) { + fprintf(stderr, "%s: Maximum number of cracks must be less than 10\n", + progname); + exit (1); + } + + if (st->f->circle_percent < 0) { + fprintf(stderr, "%s: circle percent must be at least 0\n", progname); + exit (1); + } + + if (st->f->circle_percent > 100) { + fprintf(stderr, "%s: circle percent must be less than 100\n", progname); + exit (1); + } + + XGetWindowAttributes(st->dpy, st->window, &st->xgwa); + + st->f->height = st->xgwa.height; + st->f->width = st->xgwa.width; + st->f->visdepth = st->xgwa.depth; + + /* Count the colors in our map and assign them in a horrifically inefficient + * manner but it only happens once */ + while (rgb_colormap[st->f->numcolors] != NULL) { + st->f->parsedcolors = (unsigned long *) xrealloc(st->f->parsedcolors, + sizeof(unsigned long) * + (st->f->numcolors + 1)); + if (!XParseColor(st->dpy, st->xgwa.colormap, rgb_colormap[st->f->numcolors], &tmpcolor)) { + fprintf(stderr, "%s: couldn't parse color %s\n", progname, + rgb_colormap[st->f->numcolors]); + exit(1); + } + + if (!XAllocColor(st->dpy, st->xgwa.colormap, &tmpcolor)) { + fprintf(stderr, "%s: couldn't allocate color %s\n", progname, + rgb_colormap[st->f->numcolors]); + exit(1); + } + + st->f->parsedcolors[st->f->numcolors] = tmpcolor.pixel; + + st->f->numcolors++; + } + + st->gcv.foreground = get_pixel_resource(st->dpy, st->xgwa.colormap, + "foreground", "Foreground"); + st->gcv.background = get_pixel_resource(st->dpy, st->xgwa.colormap, + "background", "Background"); + st->fgc = XCreateGC(st->dpy, st->window, GCForeground, &st->gcv); + + st->f->fgcolor = st->gcv.foreground; + st->f->bgcolor = st->gcv.background; + + /* Initialize stuff */ + build_img(st->dpy, st->window, st->xgwa, st->fgc, st->f); + build_substrate(st->f); + + return st; +} + +static unsigned long +substrate_draw (Display *dpy, Window window, void *closure) +{ + struct state *st = (struct state *) closure; + int tempx; + + if ((st->f->cycles % 10) == 0) { + + /* Restart if the window size changes */ + XGetWindowAttributes(st->dpy, st->window, &st->xgwa); + + if (st->f->height != st->xgwa.height || st->f->width != st->xgwa.width) { + st->f->height = st->xgwa.height; + st->f->width = st->xgwa.width; + st->f->visdepth = st->xgwa.depth; + + build_substrate(st->f); + build_img(st->dpy, st->window, st->xgwa, st->fgc, st->f); + XSetForeground(st->dpy, st->fgc, st->gcv.background); + XFillRectangle(st->dpy, st->window, st->fgc, 0, 0, st->xgwa.width, st->xgwa.height); + XSetForeground(st->dpy, st->fgc, st->gcv.foreground); + } + } + + for (tempx = 0; tempx < st->f->num; tempx++) { + movedrawcrack(st, st->fgc, st->f, tempx); + } + + st->f->cycles++; + + if (st->f->cycles >= st->max_cycles && st->max_cycles != 0) { + build_substrate(st->f); + build_img(st->dpy, st->window, st->xgwa, st->fgc, st->f); + XSetForeground(st->dpy, st->fgc, st->gcv.background); + XFillRectangle(st->dpy, st->window, st->fgc, 0, 0, st->xgwa.width, st->xgwa.height); + XSetForeground(st->dpy, st->fgc, st->gcv.foreground); + } + + /* #### mi->recursion_depth = st->f->cycles; */ + return st->growth_delay; +} + + +static void +substrate_reshape (Display *dpy, Window window, void *closure, + unsigned int w, unsigned int h) +{ +} + +static Bool +substrate_event (Display *dpy, Window window, void *closure, XEvent *event) +{ + return False; +} + +static void +substrate_free (Display *dpy, Window window, void *closure) +{ + struct state *st = (struct state *) closure; + free (st); +} + +static const char *substrate_defaults[] = { + ".background: white", + ".foreground: black", + "*fpsSolid: true", + "*wireFrame: false", + "*maxCycles: 10000", + "*growthDelay: 18000", + "*initialCracks: 3", + "*maxCracks: 100", + "*sandGrains: 64", + "*circlePercent: 33", + 0 +}; + +static XrmOptionDescRec substrate_options[] = { + {"-background", ".background", XrmoptionSepArg, 0}, + {"-foreground", ".foreground", XrmoptionSepArg, 0}, + {"-wireframe", ".wireFrame", XrmoptionNoArg, "true"}, + {"-max-cycles", ".maxCycles", XrmoptionSepArg, 0}, + {"-growth-delay", ".growthDelay", XrmoptionSepArg, 0}, + {"-initial-cracks", ".initialCracks", XrmoptionSepArg, 0}, + {"-max-cracks", ".maxCracks", XrmoptionSepArg, 0}, + {"-sand-grains", ".sandGrains", XrmoptionSepArg, 0}, + {"-circle-percent", ".circlePercent", XrmoptionSepArg, 0}, + {0, 0, 0, 0} +}; + +XSCREENSAVER_MODULE ("Substrate", substrate) diff --git a/hacks/substrate.man b/hacks/substrate.man new file mode 100644 index 00000000..54de179b --- /dev/null +++ b/hacks/substrate.man @@ -0,0 +1,73 @@ +.TH Substrate 1 "08-Oct-04" "X Version 11" +.SH NAME +substrate - Grow crystal-like lines on a computational substrate +.SH SYNOPSIS +.B substrate +[\-display \fIhost:display.screen\fP] +[\-foreground \fIcolor\fP] +[\-background \fIcolor\fP] +[\-wireframe] +[\-max\-cycles \fIcyclecount\fP] +[\-growth\-delay \fIdelayms\fP] +[\-initial\-cracks \fInuminitial\fP] +[\-max\-cracks \fInummax\fP] +[\-sand\-grains \fInumgrains\fP] +[\-circle\-percent \fIcirclepercent\fP] +[\-fps] +.SH DESCRIPTION +Lines like crystals grow on a computational substrate. A simple +perpendicular growth rule creates intricate city-like structures. Optionally, cracks may also be circular, producing a cityscape more familiar to places for which city planning is a distant, theoretical concern. + +Ported from the code by j.tarbell at http://complexification.net +.SH OPTIONS +.I substrate +accepts the following options: +.TP 8 +.B \-wireframe (Default: \fIFalse\fP) +Don't draw sand-painting colored effects, only make a wireframe. +.TP 8 +.B \-max\-cycles \fIcyclecount\fP (Default: \fI10000\fP) +Maximum number of growth cycles before restarting. The higher this is, +the more complex the art. +.TP 8 +.B \-growth\-delay \fIdelayms\fP (Default: \fI18000\fP) +Delay in ms between growth cycles. More delay, slower (but smoother +and less CPU intensive) +art. +.TP 8 +.B \-initial\-cracks \fInuminitial\fP (Default: \fI3\fP) +Initial number of cracks in the substrate +.TP 8 +.B \-max\-cracks \fInummax\fP (Default: \fI100\fP) +Maximum number of cracks in the substrate at a single time +.TP 8 +.B \-sand\-grains \fInumgrains\fP (Default: \fI64\fP) +Number of sand grains dropped during coloring. More grains cause +a denser colour but use more cpu power. +.TP 8 +.B \-circle-percent \fIcirclepercent\fP (Default: \fI0\fP) +The percentage of the cracks will be circular. +.TP 8 +.B \-fps +Display the current frame rate and CPU load. +.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 2003 by J. Tarbell +(complex@complexification.net, http://www.complexification.net). + +Ported to XScreensaver 2004 by Mike Kershaw (dragorn@kismetwireless.net) +.SH AUTHOR +J. Tarbell , Jun-03 + +Mike Kershaw , Oct-04 diff --git a/hacks/swirl.c b/hacks/swirl.c new file mode 100644 index 00000000..ba959ac6 --- /dev/null +++ b/hacks/swirl.c @@ -0,0 +1,1488 @@ +/* -*- Mode: C; tab-width: 4 -*- + * swirl --- swirly color-cycling patterns. + */ +#if 0 +static const char sccsid[] = "@(#)swirl.c 4.00 97/01/01 xlockmore"; +#endif + +/* Copyright (c) 1994 M.Dobie + * + * Permission to use, copy, modify, and distribute this software and its + * documentation for any purpose and without fee is hereby granted, + * provided that the above copyright notice appear in all copies and that + * both that copyright notice and this permission notice appear in + * supporting documentation. + * + * This file is provided AS IS with no warranties of any kind. The author + * shall have no liability with respect to the infringement of copyrights, + * trade secrets or any patents by this file or any part thereof. In no + * event will the author be liable for any lost revenue or profits or + * other special, indirect and consequential damages. + * + * 13-May-97: jwz@jwz.org: turned into a standalone program. + * 21-Apr-95: improved startup time for TrueColour displays + * (limited to 16bpp to save memory) S.Early + * 09-Jan-95: fixed colour maps (more colourful) and the image now spirals + * outwards from the centre with a fixed number of points drawn + * every iteration. Thanks to M.Dobie . + * 1994: written. Copyright (c) 1994 M.Dobie + * based on original code by R.Taylor + */ + +#ifdef STANDALONE +# define DEFAULTS "*count: 5 \n" \ + "*delay: 10000 \n" \ + "*ncolors: 200 \n" \ + "*useSHM: True \n" \ + "*fpsSolid: true \n" \ + +# define SMOOTH_COLORS +# define WRITABLE_COLORS +# define swirl_handle_event 0 +# include "xlockmore.h" /* from the xscreensaver distribution */ +# ifdef HAVE_XSHM_EXTENSION +# include "xshm.h" +# endif /* HAVE_XSHM_EXTENSION */ +#else /* !STANDALONE */ +# include "xlock.h" /* from the xlockmore distribution */ +# undef HAVE_XSHM_EXTENSION +#endif /* !STANDALONE */ + +ENTRYPOINT ModeSpecOpt swirl_opts = { + 0, NULL, 0, NULL, NULL }; + +#include + +/****************************************************************/ + +#define MASS 4 /* maximum mass of a knot */ +#define MIN_RES 5 /* minimim resolution (>= MIN_RES) */ +#define MAX_RES 1 /* maximum resolution (>0) */ +#define TWO_PLANE_PCNT 30 /* probability for two plane mode (0-100) */ +#define RESTART 2500 /* number of cycles before restart */ +#define BATCH_DRAW 100 /* points to draw per iteration */ + +/* knot types */ +typedef enum { + NONE = 0, + ORBIT = (1 << 0), + WHEEL = (1 << 1), + PICASSO = (1 << 2), + RAY = (1 << 3), + HOOK = (1 << 4), + ALL = (1 << 5) +} KNOT_T; + +/* a knot */ +typedef struct Knot { + int x, y; /* position */ + int m; /* mass */ + KNOT_T t; /* type in the first (or only) plane */ + KNOT_T T; /* type in second plane if there is one */ + int M; /* mass in second plane if there is one */ +} KNOT , *KNOT_P; + +/* a colour specification */ +typedef struct Colour { + unsigned short r, g, b; +} COLOUR , *COLOUR_P; + +/* drawing direction */ +typedef enum { + DRAW_RIGHT, DRAW_DOWN, DRAW_LEFT, DRAW_UP +} DIR_T; + +/****************************************************************/ + +/* data associated with a swirl window */ +typedef struct swirl_data { + /* window paramaters */ + Window win; /* the window */ + int width, height; /* window size */ + int depth; /* depth */ + int rdepth; /* real depth (for XImage) */ + Visual *visual; /* visual */ + + /* swirl drawing parameters */ + int n_knots; /* number of knots */ + KNOT_P knots; /* knot details */ + KNOT_T knot_type; /* general type of knots */ + int resolution; /* drawing resolution, 1..5 */ + int max_resolution; /* maximum resolution, MAX_RES */ + int r; /* pixel step */ + Bool two_plane; /* two plane mode? */ + Bool first_plane; /* doing first plane? */ + int start_again; /* when to restart */ + + /* spiral drawing parameters */ + int x, y; /* current point */ + DIR_T direction; /* current direction */ + int dir_todo, dir_done; /* how many points in current direction? */ + int batch_todo, batch_done; /* how many points in this batch */ + Bool started, drawing; /* are we drawing? */ + + /* image stuff */ + unsigned char *image; /* image data */ + XImage *ximage; + + /* colours stuff */ + int colours; /* how many colours possible */ + int dcolours; /* how many colours for shading */ +#ifndef STANDALONE + Bool fixed_colourmap; /* fixed colourmap? */ +#endif /* !STANDALONE */ + Bool monochrome; /* monochrome? */ + Colormap cmap; /* colour map for the window */ + XColor *rgb_values; /* colour definitions array */ +#ifndef STANDALONE + int current_map; /* current colour map, 0..dcolours-1 */ + unsigned long fg, bg, white, black; /* black and white pixel values */ + int shift; /* colourmap shift */ + int dshift; /* colourmap shift while drawing */ + XColor fgcol, bgcol; /* foreground and background colour specs */ +#endif /* !STANDALONE */ + Bool off_screen; +} SWIRL , *SWIRL_P; + +#define SWIRLCOLOURS 13 + +#ifndef STANDALONE +/* basic colours */ +static COLOUR basic_colours[SWIRLCOLOURS]; +#endif /* !STANDALONE */ + +/* an array of swirls for each screen */ +static SWIRL_P swirls = NULL; + +/* + random_no + + Return a random integer between 0 and n inclusive + + - n is the maximum number + + Returns a random integer */ + +static int +random_no(unsigned int n) +{ + return ((int) ((n + 1) * (double) LRAND() / MAXRAND)); +} + +/****************************************************************/ + +/* + initialise_swirl + + Initialise all the swirl data + + - swirl is the swirl data */ + +static void +initialise_swirl(ModeInfo * mi, SWIRL_P swirl) +{ +#ifndef STANDALONE + Display *display = MI_DISPLAY(mi); +#endif /* !STANDALONE */ + + swirl->width = 0; /* width and height of window */ + swirl->height = 0; + swirl->depth = 1; + swirl->rdepth = 1; + swirl->visual = NULL; + swirl->resolution = MIN_RES + 1; /* current resolution */ + swirl->max_resolution = MAX_RES; /* maximum resolution */ + swirl->n_knots = 0; /* number of knots */ + swirl->knot_type = ALL; /* general type of knots */ + swirl->two_plane = False; /* two plane mode? */ + swirl->first_plane = False; /* doing first plane? */ + swirl->start_again = -1; /* restart counter */ + + /* drawing parameters */ + swirl->x = 0; + swirl->y = 0; + swirl->started = False; + swirl->drawing = False; + + /* image stuff */ + swirl->image = NULL; /* image data */ + swirl->ximage = NULL; + + /* colours stuff */ + swirl->colours = 0; /* how many colours possible */ + swirl->dcolours = 0; /* how many colours for shading */ + swirl->cmap = (Colormap) NULL; + swirl->rgb_values = NULL; /* colour definitions array */ +#ifndef STANDALONE + swirl->current_map = 0; /* current colour map, 0..dcolours-1 */ + + /* set up fg fb colour specs */ + swirl->white = MI_WIN_WHITE_PIXEL(mi); + swirl->black = MI_WIN_BLACK_PIXEL(mi); +#endif /* !STANDALONE */ + + +#ifndef STANDALONE + swirl->fg = MI_FG_COLOR(mi); + swirl->bg = MI_BG_COLOR(mi); + swirl->fgcol.pixel = swirl->fg; + swirl->bgcol.pixel = swirl->bg; + XQueryColor(display, MI_COLORMAP(mi), &(swirl->fgcol)); + XQueryColor(display, MI_COLORMAP(mi), &(swirl->bgcol)); +#endif /* !STANDALONE */ +} + +/****************************************************************/ + +/* + * initialise_image + * + * Initialise the image for drawing to + * + * - swirl is the swirl data + */ +static void +initialise_image(ModeInfo * mi, SWIRL_P swirl) +{ + Display *dpy = MI_DISPLAY(mi); + + if (swirl->ximage != NULL) + XDestroyImage(swirl->ximage); + + swirl->ximage = 0; +#ifdef HAVE_XSHM_EXTENSION + if (mi->use_shm) + { + swirl->ximage = create_xshm_image(dpy, swirl->visual, swirl->rdepth, + ZPixmap, 0, &mi->shm_info, + swirl->width, swirl->height); + if (!swirl->ximage) + mi->use_shm = False; + } +#endif /* HAVE_XSHM_EXTENSION */ + + if (!swirl->ximage) + { + swirl->ximage = XCreateImage(dpy, swirl->visual, swirl->rdepth, ZPixmap, + 0, 0, swirl->width, swirl->height, + 8, 0); + swirl->image = (unsigned char *) + calloc(swirl->height, swirl->ximage->bytes_per_line); + swirl->ximage->data = (char *) swirl->image; + } +} + +/****************************************************************/ + +#ifndef STANDALONE +/* + * initialise_colours + * + * Initialise the list of colours from which the colourmaps are derived + * + * - colours is the array to initialise + * - saturation is the saturation value to use 0->grey, + * 1.0->full saturation + */ +static void +initialise_colours(COLOUR * colours, float saturate) +{ + int i; + + /* start off fully saturated, medium and bright colours */ + colours[0].r = 0xA000; + colours[0].g = 0x0000; + colours[0].b = 0x0000; + colours[1].r = 0xD000; + colours[1].g = 0x0000; + colours[1].b = 0x0000; + colours[2].r = 0x0000; + colours[2].g = 0x6000; + colours[2].b = 0x0000; + colours[3].r = 0x0000; + colours[3].g = 0x9000; + colours[3].b = 0x0000; + colours[4].r = 0x0000; + colours[4].g = 0x0000; + colours[4].b = 0xC000; + colours[5].r = 0x0000; + colours[5].g = 0x0000; + colours[5].b = 0xF000; + colours[6].r = 0xA000; + colours[6].g = 0x6000; + colours[6].b = 0x0000; + colours[7].r = 0xD000; + colours[7].g = 0x9000; + colours[7].b = 0x0000; + colours[8].r = 0xA000; + colours[8].g = 0x0000; + colours[8].b = 0xC000; + colours[9].r = 0xD000; + colours[9].g = 0x0000; + colours[9].b = 0xF000; + colours[10].r = 0x0000; + colours[10].g = 0x6000; + colours[10].b = 0xC000; + colours[11].r = 0x0000; + colours[11].g = 0x9000; + colours[11].b = 0xF000; + colours[12].r = 0xA000; + colours[12].g = 0xA000; + colours[12].b = 0xA000; + + /* add white for low saturation */ + for (i = 0; i < SWIRLCOLOURS - 1; i++) { + unsigned short max_rg, max; + + /* what is the max intensity for this colour? */ + max_rg = (colours[i].r > colours[i].g) ? colours[i].r : colours[i].g; + max = (max_rg > colours[i].b) ? max_rg : colours[i].b; + + /* bring elements up to max as saturation approaches 0.0 */ + colours[i].r += (unsigned short) ((float) (1.0 - saturate) * + ((float) max - colours[i].r)); + colours[i].g += (unsigned short) ((float) (1.0 - saturate) * + ((float) max - colours[i].g)); + colours[i].b += (unsigned short) ((float) (1.0 - saturate) * + ((float) max - colours[i].b)); + } +} +#endif /* !STANDALONE */ + +/****************************************************************/ + +#ifndef STANDALONE +/* + * set_black_and_white + * + * Set the entries for foreground & background pixels and + * WhitePixel & BlackPixel in an array of colour specifications. + * + * - swirl is the swirl data + * - values is the array of specifications + */ +static void +set_black_and_white(SWIRL_P swirl, XColor * values) +{ + unsigned long white, black; + + /* where is black and white? */ + white = swirl->white; + black = swirl->black; + + /* set black and white up */ + values[white].flags = DoRed | DoGreen | DoBlue; + values[white].pixel = white; + values[white].red = 0xFFFF; + values[white].green = 0xFFFF; + values[white].blue = 0xFFFF; + values[black].flags = DoRed | DoGreen | DoBlue; + values[black].pixel = black; + values[black].red = 0; + values[black].green = 0; + values[black].blue = 0; + + /* copy the colour specs from the original entries */ + values[swirl->fg] = swirl->fgcol; + values[swirl->bg] = swirl->bgcol; +} + +/****************************************************************/ + +/* + * set_colour + * + * Set an entry in an array of XColor specifications. The given entry will be + * set to the given colour. If the entry corresponds to the foreground, + * background, WhitePixel, or BlackPixel it is ignored and the given colour + * is is put in the next entry. + * + * Therefore, the given colour may be placed up to four places after the + * specified entry in the array, if foreground, background, white, or black + * intervene. + * + * - swirl is the swirl data + * - value points to a pointer to the array entry. It gets updated to + * point to the next free entry. + * - pixel points to the current pixel number. It gets updated. + * - c points to the colour to add + */ +static void +set_colour(SWIRL_P swirl, XColor ** value, unsigned long *pixel, COLOUR_P c) +{ + Bool done; + unsigned long fg, bg, white, black; + + /* where are foreground, background, white, and black? */ + fg = swirl->fg; + bg = swirl->bg; + white = swirl->white; + black = swirl->black; + + /* haven't set it yet */ + done = False; + + /* try and set the colour */ + while (!done) { + (**value).flags = DoRed | DoGreen | DoBlue; + (**value).pixel = *pixel; + + /* white, black, fg, bg, or a colour? */ + if ((*pixel != fg) && (*pixel != bg) && + (*pixel != white) && (*pixel != black)) { + (**value).red = c->r; + (**value).green = c->g; + (**value).blue = c->b; + + /* now we've done it */ + done = True; + } + /* next pixel */ + (*value)++; + (*pixel)++; + } +} + +/****************************************************************/ + +/* + * get_colour + * + * Get an entry from an array of XColor specifications. The next colour from + * the array will be returned. Foreground, background, WhitePixel, or + * BlackPixel will be ignored. + * + * - swirl is the swirl data + * - value points the array entry. It is updated to point to the entry + * following the one returned. + * - c is set to the colour found + */ +static void +get_colour(SWIRL_P swirl, XColor ** value, COLOUR_P c) +{ + Bool done; + unsigned long fg, bg, white, black; + + /* where is white and black? */ + fg = swirl->fg; + bg = swirl->bg; + white = swirl->white; + black = swirl->black; + + /* haven't set it yet */ + done = False; + + /* try and set the colour */ + while (!done) { + /* black, white or a colour? */ + if (((*value)->pixel != fg) && ((*value)->pixel != bg) && + ((*value)->pixel != white) && ((*value)->pixel != black)) { + c->r = (*value)->red; + c->g = (*value)->green; + c->b = (*value)->blue; + + /* now we've done it */ + done = True; + } + /* next value */ + (*value)++; + } +} +#endif /* !STANDALONE */ + +/****************************************************************/ + +#ifndef STANDALONE +/* + * interpolate + * + * Generate n colours between c1 and c2. n XColors at *value are set up with + * ascending pixel values. + * + * If the pixel range includes BlackPixel or WhitePixel they are set to black + * and white respectively but otherwise ignored. Therefore, up to n+2 colours + * may actually be set by this function. + * + * - swirl is the swirl data + * - values points a pointer to an array of XColors to update + * - pixel points to the pixel number to start at + * - k n is the number of colours to generate + * - c1, c2 are the colours to interpolate between + */ +static void +interpolate(SWIRL_P swirl, XColor ** values, unsigned long *pixel, int n, COLOUR_P c1, COLOUR_P c2) +{ + int i, r, g, b; + COLOUR c; + unsigned short maxv; + + /* maximum value */ + maxv = (255 << 8); + + for (i = 0; i < n / 2 && (int) *pixel < swirl->colours; i++) { + /* work out the colour */ + r = c1->r + 2 * i * ((int) c2->r) / n; + c.r = (r > (int) maxv) ? maxv : r; + g = c1->g + 2 * i * ((int) c2->g) / n; + c.g = (g > (int) maxv) ? maxv : g; + b = c1->b + 2 * i * ((int) c2->b) / n; + c.b = (b > (int) maxv) ? maxv : b; + + /* set it up */ + set_colour(swirl, values, pixel, &c); + } + for (i = n / 2; i >= 0 && (int) *pixel < swirl->colours; i--) { + r = c2->r + 2 * i * ((int) c1->r) / n; + c.r = (r > (int) maxv) ? maxv : r; + g = c2->g + 2 * i * ((int) c1->g) / n; + c.g = (g > (int) maxv) ? maxv : g; + b = c2->b + 2 * i * ((int) c1->b) / n; + c.b = (b > (int) maxv) ? maxv : b; + + /* set it up */ + set_colour(swirl, values, pixel, &c); + } +} + +/****************************************************************/ + +/* + * basic_map + * + * Generate a `random' closed loop colourmap that occupies the whole colour + * map. + * + * - swirl is the swirl data + * - values is the array of colour definitions to set up + */ +static void +basic_map(SWIRL_P swirl, XColor * values) +{ + COLOUR c[3]; + int i; + unsigned short r1, g1, b1, r2, g2, b2, r3, g3, b3; + int L1, L2, L3, L; + unsigned long pixel; + XColor *value; + + /* start at the beginning of the colour map */ + pixel = 0; + value = values; + + /* choose 3 different basic colours at random */ + for (i = 0; i < 3;) { + int j; + Bool same; + + /* choose colour i */ + c[i] = basic_colours[random_no(SWIRLCOLOURS - 1)]; + + /* assume different */ + same = False; + + /* different from the rest? */ + for (j = 0; j < i; j++) + if ((c[i].r == c[j].r) && + (c[i].g == c[j].g) && + (c[i].b == c[j].b)) + same = True; + + /* ready for the next colour? */ + if (!same) + i++; + } + + /* extract components into variables */ + r1 = c[0].r; + g1 = c[0].g; + b1 = c[0].b; + r2 = c[1].r; + g2 = c[1].g; + b2 = c[1].b; + r3 = c[2].r; + g3 = c[2].g; + b3 = c[2].b; + + /* work out the lengths of each side of the triangle */ + L1 = (int) sqrt((((double) r1 - r2) * ((double) r1 - r2) + + ((double) g1 - g2) * ((double) g1 - g2) + + ((double) b1 - b2) * ((double) b1 - b2))); + + L2 = (int) sqrt((((double) r3 - r2) * ((double) r3 - r2) + + ((double) g3 - g2) * ((double) g3 - g2) + + ((double) b3 - b2) * ((double) b3 - b2))); + + L3 = (int) sqrt((((double) r1 - r3) * ((double) r1 - r3) + + ((double) g1 - g3) * ((double) g1 - g3) + + ((double) b1 - b3) * ((double) b1 - b3))); + + L = L1 + L2 + L3; + + /* allocate colours in proportion to the lengths of the sides */ + interpolate(swirl, &value, &pixel, + (int) ((double) swirl->dcolours * ((double) L1 / (double) L)) + 1, c, c + 1); + interpolate(swirl, &value, &pixel, + (int) ((double) swirl->dcolours * ((double) L2 / (double) L)) + 1, c + 1, c + 2); + interpolate(swirl, &value, &pixel, + (int) ((double) swirl->dcolours * ((double) L3 / (double) L)) + 1, c + 2, c); + + /* fill up any remaining slots (due to rounding) */ + while ((int) pixel < swirl->colours) { + /* repeat the last colour */ + set_colour(swirl, &value, &pixel, c); + } + + /* ensure black and white are correct */ + if (!swirl->fixed_colourmap) + set_black_and_white(swirl, values); +} + +/****************************************************************/ + +/* + * pre_rotate + * + * Generate pre-rotated versions of the colour specifications + * + * - swirl is the swirl data + * - values is an array of colour specifications + */ +static void +pre_rotate(SWIRL_P swirl, XColor * values) +{ + int i, j; + XColor *src, *dest; + int dcolours; + unsigned long pixel; + + /* how many colours to display? */ + dcolours = swirl->dcolours; + + /* start at the first map */ + src = values; + dest = values + swirl->colours; + + /* generate dcolours-1 rotated maps */ + for (i = 0; i < dcolours - 1; i++) { + COLOUR first; + + /* start at the first pixel */ + pixel = 0; + + /* remember the first one and skip it */ + get_colour(swirl, &src, &first); + + /* put a rotated version of src at dest */ + for (j = 0; j < dcolours - 1; j++) { + COLOUR c; + + /* get the source colour */ + get_colour(swirl, &src, &c); + + /* set the colour */ + set_colour(swirl, &dest, &pixel, &c); + } + + /* put the first one at the end */ + set_colour(swirl, &dest, &pixel, &first); + + /* NB: src and dest should now be ready for the next table */ + + /* ensure black and white are properly set */ + set_black_and_white(swirl, src); + } +} + +/****************************************************************/ + +/* + * create_colourmap + * + * Create a read/write colourmap to use + * + * - swirl is the swirl data + */ + +static void +create_colourmap(ModeInfo * mi, SWIRL_P swirl) +{ + Display *display = MI_DISPLAY(mi); + int preserve; + int n_rotations; + int i; + Bool truecolor; + unsigned long redmask, greenmask, bluemask; + + swirl->fixed_colourmap = !setupColormap(mi, &(swirl->colours), + &truecolor, &redmask, &greenmask, &bluemask); + preserve = preserveColors(swirl->fg, swirl->bg, swirl->white, swirl->black); + + /* how many colours should we animate? */ + swirl->dcolours = (swirl->colours > preserve + 1) ? + swirl->colours - preserve : swirl->colours; + + if (MI_NPIXELS(mi) < 2) + return; + + /* how fast to shift the colourmap? */ + swirl->shift = (swirl->colours > 64) ? swirl->colours / 64 : 1; + swirl->dshift = (swirl->shift > 1) ? swirl->shift * 2 : 1; + + /* how may colour map rotations are there? */ + n_rotations = (swirl->fixed_colourmap) ? 1 : swirl->dcolours; + + /* allocate space for colour definitions (if not already there) */ + if (swirl->rgb_values == NULL) { + swirl->rgb_values = (XColor *) calloc((swirl->colours + 3) * n_rotations, + sizeof (XColor)); + + /* create a colour map */ + if (!swirl->fixed_colourmap) + swirl->cmap = + XCreateColormap(display, swirl->win, swirl->visual, AllocAll); + } + /* select a set of colours for the colour map */ + basic_map(swirl, swirl->rgb_values); + + /* are we rotating them? */ + if (!swirl->fixed_colourmap) { + /* generate rotations of the colour maps */ + pre_rotate(swirl, swirl->rgb_values); + + /* store the colours in the colour map */ + XStoreColors(display, swirl->cmap, swirl->rgb_values, swirl->colours); + } else { + if (truecolor) { + int rsh, gsh, bsh; + unsigned long int t; + + t = redmask; + for (i = 0; (int) t > 0; i++, t >>= 1); + rsh = 16 - i; + t = greenmask; + for (i = 0; (int) t > 0; i++, t >>= 1); + gsh = 16 - i; + t = bluemask; + for (i = 0; (int) t > 0; i++, t >>= 1); + bsh = 16 - i; + for (i = 0; i < swirl->colours; i++) + swirl->rgb_values[i].pixel = + ((rsh > 0 ? (swirl->rgb_values[i].red) >> rsh : + (swirl->rgb_values[i].red) << (-rsh)) & redmask) | + ((gsh > 0 ? (swirl->rgb_values[i].green) >> gsh : + (swirl->rgb_values[i].green) << (-gsh)) & greenmask) | + ((bsh > 0 ? (swirl->rgb_values[i].blue) >> bsh : + (swirl->rgb_values[i].blue) << (-bsh)) & bluemask); + } else { + /* lookup the colours in the fixed colour map */ + for (i = 0; i < swirl->colours; i++) + (void) XAllocColor(display, MI_COLORMAP(mi), + &(swirl->rgb_values[i])); + } + } +} + +/****************************************************************/ + +/* + * install_map + * + * Install a new set of colours into the colour map + * + * - dpy is the display + * - swirl is the swirl data + * - shift is the amount to rotate the colour map by + */ +static void +install_map(Display * dpy, SWIRL_P swirl, int shift) +{ + if (!swirl->fixed_colourmap) { + /* shift the colour map */ + swirl->current_map = (swirl->current_map + shift) % + swirl->dcolours; + + /* store it */ + XStoreColors(dpy, swirl->cmap, + swirl->rgb_values + + swirl->current_map * swirl->colours, + swirl->colours); + } +} +#endif /* !STANDALONE */ + +/****************************************************************/ + +/* + * create_knots + * + * Initialise the array of knot + * + * swirl is the swirl data + */ +static void +create_knots(SWIRL_P swirl) +{ + int k; + Bool orbit, wheel, picasso, ray, hook; + KNOT_P knot; + + /* create array for knots */ + if (swirl->knots) + (void) free((void *) swirl->knots); + swirl->knots = (KNOT_P) calloc(swirl->n_knots, sizeof (KNOT)); + + /* no knots yet */ + orbit = wheel = picasso = ray = hook = False; + + /* what types do we have? */ + if ((int) swirl->knot_type & (int) ALL) { + orbit = wheel = ray = hook = True; + } else { + if ((int) swirl->knot_type & (int) ORBIT) + orbit = True; + if ((int) swirl->knot_type & (int) WHEEL) + wheel = True; + if ((int) swirl->knot_type & (int) PICASSO) + picasso = True; + if ((int) swirl->knot_type & (int) RAY) + ray = True; + if ((int) swirl->knot_type & (int) HOOK) + hook = True; + } + + /* initialise each knot */ + knot = swirl->knots; + for (k = 0; k < swirl->n_knots; k++) { + /* position */ + knot->x = random_no((unsigned int) swirl->width); + knot->y = random_no((unsigned int) swirl->height); + + /* mass */ + knot->m = random_no(MASS) + 1; + + /* can be negative */ + if (random_no(100) > 50) + knot->m *= -1; + + /* type */ + knot->t = NONE; + while (knot->t == NONE) { + /* choose a random one from the types available */ + switch (random_no(4)) { + case 0: + if (orbit) + knot->t = ORBIT; + break; + case 1: + if (wheel) + knot->t = WHEEL; + break; + case 2: + if (picasso) + knot->t = PICASSO; + break; + case 3: + if (ray) + knot->t = RAY; + break; + case 4: + if (hook) + knot->t = HOOK; + break; + } + } + + /* if two planes, do same for second plane */ + if (swirl->two_plane) { + knot->T = NONE; + while (knot->T == NONE || knot->T == knot->t) { + /* choose a different type */ + switch (random_no(4)) { + case 0: + if (orbit) + knot->T = ORBIT; + break; + case 1: + if (wheel) + knot->T = WHEEL; + break; + case 2: + if (picasso) + knot->T = PICASSO; + break; + case 3: + if (ray) + knot->T = RAY; + break; + case 4: + if (hook) + knot->T = HOOK; + break; + } + } + } + /* next knot */ + knot++; + } +} + +/****************************************************************/ + +/* + * do_point + * + * Work out the pixel value at i, j. Ensure it does not clash with BlackPixel + * or WhitePixel. + * + * - swirl is the swirl data + * - i, j is the point to calculate + * + * Returns the value of the point + */ +static unsigned long +do_point(SWIRL_P swirl, int i, int j) +{ + int tT, k, value, add; + double dx, dy, theta, dist; + int dcolours, qcolours; + double rads; + KNOT_P knot; + + /* how many colours? */ + dcolours = swirl->dcolours; + qcolours = dcolours / 4; + + /* colour step round a circle */ + rads = (double) dcolours / (2.0 * M_PI); + + /* start at zero */ + value = 0; + + /* go through all the knots */ + knot = swirl->knots; + for (k = 0; k < swirl->n_knots; k++) { + dx = i - knot->x; + dy = j - knot->y; + + /* in two_plane mode get the appropriate knot type */ + if (swirl->two_plane) + tT = (int) ((swirl->first_plane) ? knot->t : knot->T); + else + tT = (int) knot->t; + + /* distance from knot */ + dist = sqrt(dx * dx + dy * dy); + + /* nothing to add at first */ + add = 0; + + /* work out the contribution (if close enough) */ + if (dist > 0.1) + switch (tT) { + case ORBIT: + add = (int) (dcolours / (1.0 + 0.01 * abs(knot->m) * dist)); + break; + case WHEEL: + /* Avoid atan2: DOMAIN error message */ + if (dy == 0.0 && dx == 0.0) + theta = 1.0; + else + theta = (atan2(dy, dx) + M_PI) / M_PI; + if (theta < 1.0) + add = (int) (dcolours * theta + + sin(0.1 * knot->m * dist) * + qcolours * exp(-0.01 * dist)); + else + add = (int) (dcolours * (theta - 1.0) + + sin(0.1 * knot->m * dist) * + qcolours * exp(-0.01 * dist)); + break; + case PICASSO: + add = (int) (dcolours * + fabs(cos(0.002 * knot->m * dist))); + break; + case RAY: + /* Avoid atan2: DOMAIN error message */ + if (dy == 0.0 && dx == 0.0) + add = 0; + else + add = (int) (dcolours * fabs(sin(2.0 * atan2(dy, dx)))); + + break; + case HOOK: + /* Avoid atan2: DOMAIN error message */ + if (dy == 0.0 && dx == 0.0) + add = (int) (0.05 * (abs(knot->m) - 1) * dist); + else + add = (int) (rads * atan2(dy, dx) + + 0.05 * (abs(knot->m) - 1) * dist); + break; + } + /* for a +ve mass add on the contribution else take it off */ + if (knot->m > 0) + value += add; + else + value -= add; + + /* next knot */ + knot++; + } + + /* toggle plane */ + swirl->first_plane = (!swirl->first_plane); + + /* make sure we handle -ve values properly */ + if (value >= 0) + value = (value % dcolours) + 2; + else + value = dcolours - (abs(value) % (dcolours - 1)); + +#ifndef STANDALONE + /* if fg and bg are 1 and 0 we should be OK, but just in case */ + while ((dcolours > 2) && + (((value % swirl->colours) == (int) swirl->fg) || + ((value % swirl->colours) == (int) swirl->bg) || + ((value % swirl->colours) == (int) swirl->white) || + ((value % swirl->colours) == (int) swirl->black))) { + value++; + } +#endif /* !STANDALONE */ + + /* definitely make sure it is in range */ + value = value % swirl->colours; + + /* lookup the pixel value if necessary */ +#ifndef STANDALONE + if (swirl->fixed_colourmap && swirl->dcolours > 2) +#endif + value = swirl->rgb_values[value].pixel; + + /* return it */ + return ((unsigned long) value); +} + +/****************************************************************/ + +/* + * draw_block + * + * Draw a square block of points with the same value. + * + * - ximage is the XImage to draw on. + * - x, y is the top left corner + * - s is the length of each side + * - v is the value + */ +static void +draw_block(XImage * ximage, int x, int y, int s, unsigned long v) +{ + int a, b; + + for (a = 0; a < s; a++) + for (b = 0; b < s; b++) { + XPutPixel(ximage, x + b, y + a, v); + } +} + +/****************************************************************/ + +/* + * draw_point Draw the current point in a swirl pattern onto the XImage + * + * - swirl is the swirl + * - win is the window to update + */ +static void +draw_point(ModeInfo * mi, SWIRL_P swirl) +{ + int r; + int x, y; + + /* get current point coordinates and resolution */ + x = swirl->x; + y = swirl->y; + r = swirl->r; + + /* check we are within the window */ + if ((x < 0) || (x > swirl->width - r) || (y < 0) || (y > swirl->height - r)) + return; + + /* what style are we drawing? */ + if (swirl->two_plane) { + int r2; + + /* halve the block size */ + r2 = r / 2; + + /* interleave blocks at half r */ + draw_block(swirl->ximage, x, y, r2, do_point(swirl, x, y)); + draw_block(swirl->ximage, x + r2, y, r2, do_point(swirl, x + r2, y)); + draw_block(swirl->ximage, x + r2, y + r2, r2, do_point(swirl, + x + r2, y + r2)); + draw_block(swirl->ximage, x, y + r2, r2, do_point(swirl, x, y + r2)); + } else + draw_block(swirl->ximage, x, y, r, do_point(swirl, x, y)); + + /* update the screen */ + +#ifdef HAVE_XSHM_EXTENSION + if (mi->use_shm) + XShmPutImage(MI_DISPLAY(mi), MI_WINDOW(mi), MI_GC(mi), swirl->ximage, + x, y, x, y, r, r, False); + else +#endif /* !HAVE_XSHM_EXTENSION */ + /* PURIFY 4.0.1 on SunOS4 and on Solaris 2 reports a 256 byte memory + leak on the next line. */ + XPutImage(MI_DISPLAY(mi), MI_WINDOW(mi), MI_GC(mi), swirl->ximage, + x, y, x, y, r, r); +} + +/****************************************************************/ + +/* + * next_point Move to the next point in the spiral pattern + * - swirl is the swirl + * - win is the window to update + */ +static void +next_point(SWIRL_P swirl) +{ + /* more to do in this direction? */ + if (swirl->dir_done < swirl->dir_todo) { + /* move in the current direction */ + switch (swirl->direction) { + case DRAW_RIGHT: + swirl->x += swirl->r; + break; + case DRAW_DOWN: + swirl->y += swirl->r; + break; + case DRAW_LEFT: + swirl->x -= swirl->r; + break; + case DRAW_UP: + swirl->y -= swirl->r; + break; + } + + /* done another point */ + swirl->dir_done++; + } else { + /* none drawn yet */ + swirl->dir_done = 0; + + /* change direction - check and record if off screen */ + switch (swirl->direction) { + case DRAW_RIGHT: + swirl->direction = DRAW_DOWN; + if (swirl->x > swirl->width - swirl->r) { + /* skip these points */ + swirl->dir_done = swirl->dir_todo; + swirl->y += (swirl->dir_todo * swirl->r); + + /* check for finish */ + if (swirl->off_screen) + swirl->drawing = False; + swirl->off_screen = True; + } else + swirl->off_screen = False; + break; + case DRAW_DOWN: + swirl->direction = DRAW_LEFT; + swirl->dir_todo++; + if (swirl->y > swirl->height - swirl->r) { + /* skip these points */ + swirl->dir_done = swirl->dir_todo; + swirl->x -= (swirl->dir_todo * swirl->r); + + /* check for finish */ + if (swirl->off_screen) + swirl->drawing = False; + swirl->off_screen = True; + } else + swirl->off_screen = False; + break; + case DRAW_LEFT: + swirl->direction = DRAW_UP; + if (swirl->x < 0) { + /* skip these points */ + swirl->dir_done = swirl->dir_todo; + swirl->y -= (swirl->dir_todo * swirl->r); + + /* check for finish */ + if (swirl->off_screen) + swirl->drawing = False; + swirl->off_screen = True; + } else + swirl->off_screen = False; + break; + case DRAW_UP: + swirl->direction = DRAW_RIGHT; + swirl->dir_todo++; + if (swirl->y < 0) { + /* skip these points */ + swirl->dir_done = swirl->dir_todo; + swirl->x += (swirl->dir_todo * swirl->r); + + /* check for finish */ + if (swirl->off_screen) + swirl->drawing = False; + swirl->off_screen = True; + } else + swirl->off_screen = False; + break; + } + } +} + +/****************************************************************/ + +/* + * init_swirl + * + * Initialise things for swirling + * + * - win is the window to draw in + */ +ENTRYPOINT void +init_swirl(ModeInfo * mi) +{ + Display *display = MI_DISPLAY(mi); + Window window = MI_WINDOW(mi); + SWIRL_P swirl; + + /* does the swirls array exist? */ + if (swirls == NULL) { + /* allocate an array, one entry for each screen */ + swirls = (SWIRL_P) calloc(MI_NUM_SCREENS(mi), sizeof (SWIRL)); + } + /* get a pointer to this swirl */ + swirl = &(swirls[MI_SCREEN(mi)]); + initialise_swirl(mi, swirl); + + /* get window parameters */ + swirl->win = window; + swirl->width = MI_WIN_WIDTH(mi); + swirl->height = MI_WIN_HEIGHT(mi); + swirl->depth = MI_WIN_DEPTH(mi); + swirl->rdepth = swirl->depth; + swirl->visual = MI_VISUAL(mi); + + if (swirl->depth > 16) + swirl->depth = 16; + + /* initialise image for speeding up drawing */ + initialise_image(mi, swirl); + + /* clear the window (before setting the colourmap) */ + XClearWindow(display, MI_WINDOW(mi)); + +#ifdef STANDALONE + + swirl->rgb_values = mi->colors; + swirl->colours = mi->npixels; + swirl->dcolours = swirl->colours; +/* swirl->fixed_colourmap = !mi->writable_p;*/ + +#else /* !STANDALONE */ + + /* initialise the colours from which the colourmap is derived */ + initialise_colours(basic_colours, MI_SATURATION(mi)); + + /* set up the colour map */ + create_colourmap(mi, swirl); + + /* attach the colour map to the window (if we have one) */ + if (!swirl->fixed_colourmap) { +#if 1 + setColormap(display, window, swirl->cmap, MI_WIN_IS_INWINDOW(mi)); +#else + XSetWindowColormap(display, window, swirl->cmap); + (void) XSetWMColormapWindows(display, window, &window, 1); + XInstallColormap(display, swirl->cmap); +#endif + } +#endif /* STANDALONE */ + + /* resolution starts off chunky */ + swirl->resolution = MIN_RES + 1; + + /* calculate the pixel step for this resulution */ + swirl->r = (1 << (swirl->resolution - 1)); + + /* how many knots? */ + swirl->n_knots = random_no((unsigned int) MI_BATCHCOUNT(mi) / 2) + + MI_BATCHCOUNT(mi) + 1; + + /* what type of knots? */ + swirl->knot_type = ALL; /* for now */ + + /* use two_plane mode occaisionally */ + if (random_no(100) <= TWO_PLANE_PCNT) { + swirl->two_plane = swirl->first_plane = True; + swirl->max_resolution = 2; + } else + swirl->two_plane = False; + + /* fix the knot values */ + create_knots(swirl); + + /* we are off */ + swirl->started = True; + swirl->drawing = False; +} + +/****************************************************************/ + +/* + * draw_swirl + * + * Draw one iteration of swirling + * + * - win is the window to draw in + */ +ENTRYPOINT void +draw_swirl(ModeInfo * mi) +{ + SWIRL_P swirl = &(swirls[MI_SCREEN(mi)]); + + /* are we going? */ + if (swirl->started) { + /* in the middle of drawing? */ + if (swirl->drawing) { +#ifdef STANDALONE + if (mi->writable_p) + rotate_colors(MI_DISPLAY(mi), MI_COLORMAP(mi), + swirl->rgb_values, swirl->colours, 1); +#else /* !STANDALONE */ + /* rotate the colours */ + install_map(MI_DISPLAY(mi), swirl, swirl->dshift); +#endif /* !STANDALONE */ + + /* draw a batch of points */ + swirl->batch_todo = BATCH_DRAW; + while ((swirl->batch_todo > 0) && swirl->drawing) { + /* draw a point */ + draw_point(mi, swirl); + + /* move to the next point */ + next_point(swirl); + + /* done a point */ + swirl->batch_todo--; + } + } else { +#ifdef STANDALONE + if (mi->writable_p) + rotate_colors(MI_DISPLAY(mi), MI_COLORMAP(mi), + swirl->rgb_values, swirl->colours, 1); +#else /* !STANDALONE */ + /* rotate the colours */ + install_map(MI_DISPLAY(mi), swirl, swirl->shift); +#endif /* !STANDALONE */ + + /* time for a higher resolution? */ + if (swirl->resolution > swirl->max_resolution) { + /* move to higher resolution */ + swirl->resolution--; + + /* calculate the pixel step for this resulution */ + swirl->r = (1 << (swirl->resolution - 1)); + + /* start drawing again */ + swirl->drawing = True; + + /* start in the middle of the screen */ + swirl->x = (swirl->width - swirl->r) / 2; + swirl->y = (swirl->height - swirl->r) / 2; + + /* initialise spiral drawing parameters */ + swirl->direction = DRAW_RIGHT; + swirl->dir_todo = 1; + swirl->dir_done = 0; + } else { + /* all done, decide when to restart */ + if (swirl->start_again == -1) { + /* start the counter */ + swirl->start_again = RESTART; + } else if (swirl->start_again == 0) { + /* reset the counter */ + swirl->start_again = -1; + +#ifdef STANDALONE + /* Pick a new colormap! */ + XClearWindow (MI_DISPLAY(mi), MI_WINDOW(mi)); + free_colors (MI_DISPLAY(mi), MI_COLORMAP(mi), + mi->colors, mi->npixels); + make_smooth_colormap (MI_DISPLAY(mi), + MI_VISUAL(mi), + MI_COLORMAP(mi), + mi->colors, &mi->npixels, True, + &mi->writable_p, True); + swirl->colours = mi->npixels; +#endif /* STANDALONE */ + + /* start again */ + init_swirl(mi); + } else + /* decrement the counter */ + swirl->start_again--; + } + } + } +} + +ENTRYPOINT void +reshape_swirl(ModeInfo * mi, int width, int height) +{ + XClearWindow (MI_DISPLAY (mi), MI_WINDOW(mi)); + init_swirl (mi); +} + +/****************************************************************/ + +ENTRYPOINT void +release_swirl (ModeInfo * mi) +{ + /* does the swirls array exist? */ + if (swirls != NULL) { + int i; + + /* free them all */ + for (i = 0; i < MI_NUM_SCREENS(mi); i++) { + SWIRL_P swirl = &(swirls[i]); + +#ifndef STANDALONE + if (swirl->cmap != (Colormap) NULL) + XFreeColormap(MI_DISPLAY(mi), swirl->cmap); +#endif /* STANDALONE */ +#ifndef STANDALONE + if (swirl->rgb_values != NULL) + XFree((void *) swirl->rgb_values); +#endif /* !STANDALONE */ + if (swirl->ximage != NULL) + XDestroyImage(swirl->ximage); + if (swirl->knots) + (void) free((void *) swirl->knots); + } + /* deallocate an array, one entry for each screen */ + (void) free((void *) swirls); + swirls = NULL; + } +} + +/****************************************************************/ + +ENTRYPOINT void +refresh_swirl (ModeInfo * mi) +{ + SWIRL_P swirl = &(swirls[MI_SCREEN(mi)]); + + if (swirl->started) { + if (swirl->drawing) + swirl->resolution = swirl->resolution + 1; + swirl->drawing = False; + } +} + +XSCREENSAVER_MODULE ("Swirl", swirl) diff --git a/hacks/swirl.man b/hacks/swirl.man new file mode 100644 index 00000000..decbaf08 --- /dev/null +++ b/hacks/swirl.man @@ -0,0 +1,70 @@ +.TH XScreenSaver 1 "13-May-97" "X Version 11" +.SH NAME +swirl - draws swirly color-cycling patterns +.SH SYNOPSIS +.B swirl +[\-display \fIhost:display.screen\fP] [\-foreground \fIcolor\fP] +[\-background \fIcolor\fP] [\-window] [\-root] [\-mono] [\-install] +[\-visual \fIvisual\fP] +[\-ncolors \fIinteger\fP] +[\-delay \fImicroseconds\fP] +[\-count \fIinteger\fP] + +[\-fps] +.SH DESCRIPTION +The \fIswirl\fP program draws swirly color-cycling patterns. +.SH OPTIONS +.I swirl +accepts the following options: +.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 \-mono +If on a color display, pretend we're on a monochrome display. +.TP 8 +.B \-install +Install a private colormap for the window. +.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 \-ncolors \fIinteger\fP +How many colors should be used (if possible). Default 200. +.TP 8 +.B \-count \fIinteger\fP + +.TP 8 +.B \-fps +Display the current frame rate and CPU load. +.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), +.BR xlock (1) +.SH COPYRIGHT +Copyright \(co 1994 M. Dobie. + +Permission to use, copy, modify, and distribute this software and its +documentation for any purpose and without fee is hereby granted, +provided that the above copyright notice appear in all copies and that +both that copyright notice and this permission notice appear in +supporting documentation. + +.SH AUTHOR +M.Dobie , 1994. + +Ability to run standalone or with \fIxscreensaver\fP added by +Jamie Zawinski , 13-May-97. diff --git a/hacks/t3d.c b/hacks/t3d.c new file mode 100644 index 00000000..08df8713 --- /dev/null +++ b/hacks/t3d.c @@ -0,0 +1,970 @@ +/* t3d -- Flying Balls Clock Demo + by Bernd Paysan , paysan@informatik.tu-muenchen.de + + Copy, modify, and distribute T3D either under GPL version 2 or newer, + or under the standard MIT/X license notice. + + partly based on flying balls demo by Georg Acher, + acher@informatik.tu-muenchen.de + (developed on HP9000/720 (55 MIPS,20 MFLOPS) ) + NO warranty at all ! Complaints to /dev/null ! + + 4-Jan-99 jwz@jwz.org -- adapted to xscreensaver framework, to take advantage + of the command-line options provided by screenhack.c. +*/ + +#ifndef HAVE_COCOA +# define FASTDRAW +# define FASTCOPY +#endif /* !HAVE_COCOA */ + +#include +#include +#include /* for localtime() and gettimeofday() */ + +#include "screenhack.h" + + +#define WIDTH 200 +#define HEIGHT 200 +#define norm 20.0 + +#define ROOT 0x1 +#define PI M_PI +#define TWOPI 2*M_PI + +#define MIN(i,j) ((i)<(j)?(i):(j)) + +#define kmax ((st->minutes?60:24)) +/* Anzahl der Kugeln */ +#define sines 52 +/* Werte in der Sinus-Tabelle */ +/*-----------------------------------------------------------------*/ +#define setink(inkcolor) \ + XSetForeground (st->dpy,st->gc,inkcolor) + +#define drawline(xx1,yy1,xx2,yy2) \ + XDrawLine(st->dpy,st->win,st->gc,xx1,yy1,xx2,yy2) + +#define drawseg(segments,nr_segments) \ + XDrawSegments(st->dpy,st->win,st->gc,segments,nr_segments) + + +#define polyfill(ppts,pcount) \ + XFillPolygon(st->dpy,st->win,st->gc,ppts,pcount,Convex,CoordModeOrigin) + + +#define frac(argument) argument-floor(argument) + +#undef ABS +#define ABS(x) ((x)<0.0 ? -(x) : (x)) + +typedef struct { + double x,y,z,r,d,r1; + int x1,y1; +} kugeldat; + +/* Felder fuer 3D */ + + +struct state { + Display *dpy; + Window window; + + int maxk; + int timewait; + + Colormap cmap; + double r,g,b; + double hue,sat,val; + + kugeldat kugeln[100]; + + double a[3],am[3],x[3],y[3],v[3]; + double zoom,speed,zaehler,vspeed; + double vturn; + double sinus[sines]; + double cosinus[sines]; + + int startx,starty; + double mag; + int minutes; + int cycl; + double hsvcycl; + double movef, wobber, cycle; + + XWindowAttributes xgwa; + GC gc; + GC orgc; + GC andgc; + int scrnWidth, scrnHeight; + Pixmap buffer; + int fastch; + + int scrnW2,scrnH2; + XColor colors[64]; + struct tm *zeit; + + int planes; + + Window junk_win,in_win; + int px,py,junk; + unsigned int kb; + + int fastdraw; + int draw_color; + +# ifdef FASTDRAW +# ifdef FASTCOPY +# define sum1ton(a) (((a)*(a)+1)/2) +# define fastcw sum1ton(st->fastch) + Pixmap fastcircles; + Pixmap fastmask; +# else /* !FASTCOPY */ + XImage* fastcircles[maxfast]; + XImage* fastmask[maxfast]; +# endif /* !FASTCOPY */ +# endif /* FASTDRAW */ +}; + + + +#define maxfast 100 + +/* compute time */ + +static double +gettime (struct state *st) +{ + struct timeval time1; + struct tm *zeit; + time_t lt; + +#ifdef GETTIMEOFDAY_TWO_ARGS + struct timezone zone1; + gettimeofday(&time1,&zone1); +#else + gettimeofday(&time1); +#endif + lt = time1.tv_sec; /* avoid type cast lossage */ + zeit=localtime(<); + + return (zeit->tm_sec+60*(zeit->tm_min+60*(zeit->tm_hour)) + + time1.tv_usec*1.0E-6); +} + +/* --------------------COLORMAP---------------------*/ + +static void +hsv2rgb (double h, double s, double v, double *r, double *g, double *b) +{ + h/=360.0; h=6*(h-floor(h)); + + if(s==0.0) + { + *r=*g=*b=v; + } + else + { int i=(int)h; + double t,u,w; + + h=h-floor(h); + + u=v*(s*(1.0-h)); + w=v*(1.0-s); + t=v*(s*h+1.0-s); + + switch(i) + { + case 0: *r=v; *g=t; *b=w; break; + case 1: *r=u; *g=v; *b=w; break; + case 2: *r=w; *g=v; *b=t; break; + case 3: *r=w; *g=u; *b=v; break; + case 4: *r=t; *g=w; *b=v; break; + case 5: *r=v; *g=w; *b=u; break; + } + } +#ifdef PRTDBX + printf("HSV: %f %f %f to\nRGB: %f %f %f\n",h,s,v,*r,*g,*b); +#endif +} + +static void +changeColor (struct state *st, double r, double g, double b) +{ + int n,n1; + + n1=0; + for(n=30;n<64;n+=3) + { + st->colors[n1].red =1023+ n*(int)(1024.*r); + st->colors[n1].blue =1023+ n*(int)(1024.*b); + st->colors[n1].green =1023+ n*(int)(1024.*g); + + n1++; + } + + XStoreColors (st->dpy, st->cmap, st->colors, 12); +} + +static void +initColor (struct state *st, double r, double g, double b) +{ + int n,n1; + unsigned long pixels[12]; + unsigned long dummy; + + st->cmap = st->xgwa.colormap; + + if(st->hsvcycl!=0.0 && XAllocColorCells(st->dpy, st->cmap, 0, &dummy, 0, pixels, 12)) + { + for(n1=0;n1<12;n1++) + { + st->colors[n1].pixel=pixels[n1]; + st->colors[n1].flags=DoRed | DoGreen | DoBlue; + } + + changeColor(st,r,g,b); + } + else + { + n1=0; + for(n=30;n<64;n+=3) + { + st->colors[n1].red =1023+ n*(int)(1024.*r); + st->colors[n1].blue =1023+ n*(int)(1024.*b); + st->colors[n1].green =1023+ n*(int)(1024.*g); + + if (!(XAllocColor (st->dpy, st->cmap, &st->colors[n1]))) { + fprintf (stderr, "Error: Cannot allocate colors\n"); + exit (1); + } + + n1++; + } + } +} + +/* ----------------WINDOW-------------------*/ + +static void +initialize (struct state *st) +{ + XGCValues *xgc; + XGCValues *xorgc; + XGCValues *xandgc; + + st->maxk=34; + st->r = st->g = st->b = 1; + st->hue = st->sat = 0; + st->val = 1; + st->mag = 10; + st->movef = 0.5; + st->wobber = 2; + st->cycle = 6; + st->scrnWidth = WIDTH; + st->scrnHeight = HEIGHT; + + + XGetWindowAttributes (st->dpy, st->window, &st->xgwa); + st->scrnWidth = st->xgwa.width; + st->scrnHeight = st->xgwa.height; + + { + float f = get_float_resource (st->dpy, "cycle", "Float"); + if (f <= 0 || f > 60) f = 6.0; + st->cycle = 60.0 / f; + } + st->movef = get_float_resource (st->dpy, "move", "Float"); + st->wobber = get_float_resource (st->dpy, "wobble", "Float"); + + { + double magfac = get_float_resource (st->dpy, "mag", "Float"); + st->mag *= magfac; + st->fastch=(int)(st->fastch*magfac); + } + + if (get_boolean_resource (st->dpy, "minutes", "Boolean")) { + st->minutes=1; st->maxk+=60-24; + } + + st->timewait = get_integer_resource (st->dpy, "delay", "Integer"); + st->fastch = get_integer_resource (st->dpy, "fast", "Integer"); + st->cycl = get_boolean_resource (st->dpy, "colcycle", "Integer"); + st->hsvcycl = get_float_resource (st->dpy, "hsvcycle", "Integer"); + + { + char *s = get_string_resource (st->dpy, "rgb", "RGB"); + char dummy; + if (s && *s) + { + double rr, gg, bb; + if (3 == sscanf (s, "%lf %lf %lf %c", &rr, &gg, &bb, &dummy)) + st->r = rr, st->g = gg, st->b = bb; + } + if (s) free (s); + + s = get_string_resource (st->dpy, "hsv", "HSV"); + if (s && *s) + { + double hh, ss, vv; + if (3 == sscanf (s, "%lf %lf %lf %c", &hh, &ss, &vv, &dummy)) { + st->hue = hh, st->sat = ss, st->val = vv; + hsv2rgb(st->hue,st->sat,st->val,&st->r,&st->g,&st->b); + } + } + if (s) free (s); + } + + if (st->fastch > maxfast) + st->fastch=maxfast; + + xgc=( XGCValues *) malloc(sizeof(XGCValues) ); + xorgc=( XGCValues *) malloc(sizeof(XGCValues) ); + xandgc=( XGCValues *) malloc(sizeof(XGCValues) ); + + st->planes=st->xgwa.depth; + +#ifdef HAVE_COCOA +# define GXandInverted GXcopy /* #### this can't be right, right? */ +#endif + st->gc = XCreateGC (st->dpy, st->window, 0, xgc); + xorgc->function =GXor; + st->orgc = XCreateGC (st->dpy, st->window, GCFunction, xorgc); + xandgc->function =GXandInverted; + st->andgc = XCreateGC (st->dpy, st->window, GCFunction, xandgc); + + st->buffer = XCreatePixmap (st->dpy, st->window, st->scrnWidth, st->scrnHeight, + st->xgwa.depth); + +#ifdef DEBUG + printf("Time 3D drawing "); +#ifdef FASTDRAW +# ifdef FASTCOPY + puts("fast by Pixmap copy"); +# else + puts("fast by XImage copy"); +# endif +#else + puts("slow"); +#endif +#endif /* DEBUG */ + +#ifdef FASTCOPY + st->fastcircles = XCreatePixmap (st->dpy, st->window, fastcw, st->fastch+1, st->xgwa.depth); + st->fastmask = XCreatePixmap (st->dpy, st->window, fastcw, st->fastch+1, st->xgwa.depth); +#endif + + setink(BlackPixelOfScreen (st->xgwa.screen)); + XFillRectangle (st->dpy, st->buffer , st->gc, 0, 0, st->scrnWidth, st->scrnHeight); + +#ifdef FASTCOPY + + setink(0); + XFillRectangle (st->dpy, st->fastcircles, st->gc, 0, 0, fastcw, st->fastch+1); + XFillRectangle (st->dpy, st->fastmask , st->gc, 0, 0, fastcw, st->fastch+1); + +#endif + +#ifdef PRTDBX + printf("move\t%.2f\nwobber\t%.2f\nmag\t%.2f\ncycle\t%.4f\n", + st->movef,st->wobber,st->mag/10,st->cycle); + printf("fast\t%i\nmarks\t%i\nwait\t%i\n",st->fastch,st->maxk,st->timewait); +#endif + +} + +static void fill_kugel(struct state *st, int i, Pixmap buf, int setcol); + + +/*------------------------------------------------------------------*/ +static void +init_kugel(struct state *st) +{ + +#ifdef FASTDRAW + int i; + + for(i=0; ifastch; i++) + { +# ifdef FASTCOPY + st->kugeln[i].r1=-((double) i)/2 -1; + st->kugeln[i].x1=sum1ton(i); + st->kugeln[i].y1=((double) i)/2 +1; + + fill_kugel(st,i,st->fastcircles,1); + setink((1<xgwa.depth))-1); + fill_kugel(st,i,st->fastmask,0); +# else + st->kugeln[i].r1=-((double) i)/2 -1; + st->kugeln[i].x1=st->kugeln[i].y1=((double) i)/2 +1; + + fill_kugel(i,st->buffer,1); + st->fastcircles[i]=XGetImage(st->dpy,st->buffer,0,0,i+2,i+2,(1<planes)-1,ZPixmap); + + setink((1<xgwa.depth))-1); + fill_kugel(i,st->buffer,0); + st->fastmask[i]=XGetImage(st->dpy,st->buffer,0,0,i+2,i+2,(1<planes)-1,ZPixmap); + + setink(0); + XFillRectangle (st->dpy, st->buffer , st->gc, 0, 0, st->scrnWidth, st->scrnHeight); +# endif + } + st->fastdraw=1; +#endif +} + +/* Zeiger zeichnen */ + +static void +zeiger(struct state *st, double dist,double rad, double z, double sec, int *q) +{ + int i,n; + double gratio=sqrt(2.0/(1.0+sqrt(5.0))); + + n = *q; + + for(i=0;i<3;i++) + { + st->kugeln[n].x=dist*cos(sec); + st->kugeln[n].y=-dist*sin(sec); + st->kugeln[n].z=z; + st->kugeln[n].r=rad; + n++; + + dist += rad; + rad = rad*gratio; + } + *q = n; +} + +/*-----------------------------------------------------------------* + * Uhr zeichnen * + *-----------------------------------------------------------------*/ + +static void +manipulate(struct state *st, double k) +{ + double i,l,/*xs,*/ys,zs,mod; + double /*persec,*/sec,min,hour; + int n; + + sec=TWOPI*modf(k/60,&mod); + min=TWOPI*modf(k/3600,&mod); + hour=TWOPI*modf(k/43200,&mod); + + l=TWOPI*modf(k/300,&mod); + i=0.0; + for (n=0;nkugeln[n].x=4.0*sin(i); + st->kugeln[n].y=4.0*cos(i); + st->kugeln[n].z=st->wobber* /* (sin(floor(2+2*l/(PI))*i)*sin(2*l)); */ + cos((i-sec)*floor(2+5*l/(PI)))*sin(5*l); + if(st->minutes) + { + st->kugeln[n].r=/* (1.0+0.3*cos(floor(2+2*l/(PI))*i)*sin(2*l))* */ + ((n % 5!=0) ? 0.3 : 0.6)* + ((n % 15 ==0) ? 1.25 : .75); + } + else + { + st->kugeln[n].r=/* (1.0+0.3*cos(floor(2+2*l/(PI))*i)*sin(2*l))* */ + ((n & 1) ? 0.5 : 1.0)* + ((n % 6==0) ? 1.25 : .75); + } + i+=TWOPI/kmax; + } + + st->kugeln[n].x=0.0; + st->kugeln[n].y=0.0; + st->kugeln[n].z=0.0; + st->kugeln[n].r=2.0+cos(TWOPI*modf(k,&mod))/2; + n++; + + zeiger(st,2.0,0.75,-2.0,sec,&n); + zeiger(st,1.0,1.0,-1.5,min,&n); + zeiger(st,0.0,1.5,-1.0,hour,&n); + + for(n=0;nmaxk;n++) + { + ys=st->kugeln[n].y*cos(st->movef*sin(st->cycle*sec))+ + st->kugeln[n].z*sin(st->movef*sin(st->cycle*sec)); + zs=-st->kugeln[n].y*sin(st->movef*sin(st->cycle*sec))+ + st->kugeln[n].z*cos(st->movef*sin(st->cycle*sec)); + st->kugeln[n].y=ys; + st->kugeln[n].z=zs; + } +} +/*------------------------------------------------------------------*/ +static void +t3d_sort(struct state *st, int l, int r) +{ + int i,j; + kugeldat ex; + double x; + + i=l;j=r; + x=st->kugeln[(l+r)/2].d; + while(1) + { + while(st->kugeln[i].d>x) i++; + while(x>st->kugeln[j].d) j--; + if (i<=j) + { + ex=st->kugeln[i];st->kugeln[i]=st->kugeln[j];st->kugeln[j]=ex; + i++;j--; + } + if (i>j) break; + } + if (lkugeln[i].r1)*2)); + if (d==0) d=1; + +#ifdef FASTDRAW + if(st->fastdraw && dfastch) + { +# ifdef FASTCOPY + XCopyArea(st->dpy, st->fastmask, buf, st->andgc, sum1ton(d)-(d+1)/2, 1,d,d, + (int)(st->kugeln[i].x1)-d/2, (int)(st->kugeln[i].y1)-d/2); + XCopyArea(st->dpy, st->fastcircles, buf, st->orgc, sum1ton(d)-(d+1)/2, 1,d,d, + (int)(st->kugeln[i].x1)-d/2, (int)(st->kugeln[i].y1)-d/2); +# else + XPutImage(st->dpy, buf, st->andgc, st->fastmask[d-1], 0, 0, + (int)(st->kugeln[i].x1)-d/2, (int)(st->kugeln[i].y1)-d/2, d, d); + XPutImage(st->dpy, buf, st->orgc, st->fastcircles[d-1], 0, 0, + (int)(st->kugeln[i].x1)-d/2, (int)(st->kugeln[i].y1)-d/2, d, d); +# endif + } + else +#endif + { + if(ABS(st->kugeln[i].r1)<6.0) inr=9; + + for (m=0;m<=28;m+=inr) + { + ra=st->kugeln[i].r1*sqrt(1-m*m/(28.0*28.0)); +#ifdef PRTDBX + printf("Radius: %f\n",ra); +#endif + if(-ra< 3.0) inc=14; + else if(-ra< 6.0) inc=8; + else if(-ra<20.0) inc=4; + else if(-ra<40.0) inc=2; + if(setcol) + { + if (m==27) col=33; + else + col=(int)(m); + if (col>33) col=33; col/=3; + setink(st->colors[col].pixel); + } + +#ifdef USE_POLYGON + { + int n, nr; + for (n=0,nr=0;n<=sines-1;n+=inc,nr++) + { + track[nr].x=st->kugeln[i].x1+(int)(ra*st->sinus[n])+(st->kugeln[i].r1-ra)/2; + track[nr].y=st->kugeln[i].y1+(int)(ra*st->cosinus[n])+(st->kugeln[i].r1-ra)/2; + } + XFillPolygon(st->dpy,buf,st->gc,track,nr,Convex,CoordModeOrigin); + } +#else /* Use XFillArc */ + XFillArc(st->dpy, buf, st->gc, + (int)(st->kugeln[i].x1+(st->kugeln[i].r1+ra)/2), + (int)(st->kugeln[i].y1+(st->kugeln[i].r1+ra)/2), + (int)-(2*ra+1), (int)-(2*ra+1), 0, 360*64); +#endif + } + } +} + +/*------------------------------------------------------------------*/ + +static void +init_3d(struct state *st) +{ + double i; + int n=0; + + st->a[0]=0.0; + st->a[1]=0.0; + st->a[2]=-10.0; + + st->x[0]=10.0; + st->x[1]=0.0; + st->x[2]=0.0; + + st->y[0]=0.0; + st->y[1]=10.0; + st->y[2]=0.0; + + + st->zoom=-10.0; + st->speed=.0; + + for (i=0.0;nsinus[n]=sin(i); + st->cosinus[n]=cos(i); + } +} +/*------------------------------------------------------------------*/ + + +static void +vektorprodukt(double feld1[], double feld2[], double feld3[]) +{ + feld3[0]=feld1[1]*feld2[2]-feld1[2]*feld2[1]; + feld3[1]=feld1[2]*feld2[0]-feld1[0]*feld2[2]; + feld3[2]=feld1[0]*feld2[1]-feld1[1]*feld2[0]; +} + + +/*------------------------------------------------------------------*/ +static void +turn(double feld1[], double feld2[], double winkel) +{ + double temp[3]; + double s,ca,sa,sx1,sx2,sx3; + + vektorprodukt(feld1,feld2,temp); + + s=feld1[0]*feld2[0]+feld1[1]*feld2[1]+feld1[2]*feld2[2]; + + sx1=s*feld2[0]; + sx2=s*feld2[1]; + sx3=s*feld2[2]; + sa=sin(winkel);ca=cos(winkel); + feld1[0]=ca*(feld1[0]-sx1)+sa*temp[0]+sx1; + feld1[1]=ca*(feld1[1]-sx2)+sa*temp[1]+sx2; + feld1[2]=ca*(feld1[2]-sx3)+sa*temp[2]+sx3; +} +/*------------------------------------------------------------------*/ + +/* 1: Blickrichtung v;3:Ebenenmittelpunkt m + double feld1[],feld3[]; */ +static void +viewpoint(struct state *st) +{ + st->am[0]=-st->zoom*st->v[0]; + st->am[1]=-st->zoom*st->v[1]; + st->am[2]=-st->zoom*st->v[2]; + + st->zaehler=norm*norm*st->zoom; +} + +/*------------------------------------------------------------------*/ +static void +projektion(struct state *st) +{ + double c1[3],c2[3],k[3],x1,y1; + double cno,cnorm/*,magnit*/; + int i; + + for (i=0;imaxk;i++) + { + c1[0]=st->kugeln[i].x-st->a[0]; + c1[1]=st->kugeln[i].y-st->a[1]; + c1[2]=st->kugeln[i].z-st->a[2]; + cnorm=sqrt(c1[0]*c1[0]+c1[1]*c1[1]+c1[2]*c1[2]); + + c2[0]=c1[0]; + c2[1]=c1[1]; + c2[2]=c1[2]; + + cno=c2[0]*st->v[0]+c2[1]*st->v[1]+c2[2]*st->v[2]; + st->kugeln[i].d=cnorm; + if (cno<0) st->kugeln[i].d=-20.0; + + + st->kugeln[i].r1=(st->mag*st->zoom*st->kugeln[i].r/cnorm); + + c2[0]=st->v[0]/cno; + c2[1]=st->v[1]/cno; + c2[2]=st->v[2]/cno; + + vektorprodukt(c2,c1,k); + + + x1=(st->startx+(st->x[0]*k[0]+st->x[1]*k[1]+st->x[2]*k[2])*st->mag); + y1=(st->starty-(st->y[0]*k[0]+st->y[1]*k[1]+st->y[2]*k[2])*st->mag); + if( (x1>-2000.0) + && (x1scrnWidth+2000.0) + && (y1>-2000.0) + && (y1scrnHeight+2000.0)) + { + st->kugeln[i].x1=(int)x1; + st->kugeln[i].y1=(int)y1; + } + else + { + st->kugeln[i].x1=0; + st->kugeln[i].y1=0; + st->kugeln[i].d=-20.0; + } + } +} + + +static void * +t3d_init (Display *dpy, Window window) +{ + struct state *st = (struct state *) calloc (1, sizeof(*st)); + st->dpy = dpy; + st->window = window; + st->dpy = dpy; + st->window = window; + initialize(st); + + initColor(st,st->r,st->g,st->b); + init_3d(st); + st->zeit=(struct tm *)malloc(sizeof(struct tm)); + init_kugel(st); + + st->startx=st->scrnWidth/2; + st->starty=st->scrnHeight/2; + st->scrnH2=st->startx; + st->scrnW2=st->starty; + st->vspeed=0; + + + vektorprodukt(st->x,st->y,st->v); + viewpoint(st/*m,v*/); + + setink (BlackPixelOfScreen(st->xgwa.screen)); + XFillRectangle (st->dpy, st->window, st->gc, 0, 0, st->scrnWidth, st->scrnHeight); + XQueryPointer (st->dpy, st->window, &st->junk_win, &st->junk_win, &st->junk, &st->junk, + &st->px, &st->py, &st->kb); + + return st; +} + +static unsigned long +t3d_draw (Display *d, Window w, void *closure) +{ + struct state *st = (struct state *) closure; + double dtime; + double vnorm; + + + /*--------------- Zeichenteil --------------*/ + + vektorprodukt(st->x,st->y,st->v); + + vnorm=sqrt(st->v[0]*st->v[0]+st->v[1]*st->v[1]+st->v[2]*st->v[2]); + st->v[0]=st->v[0]*norm/vnorm; + st->v[1]=st->v[1]*norm/vnorm; + st->v[2]=st->v[2]*norm/vnorm; + vnorm=sqrt(st->x[0]*st->x[0]+st->x[1]*st->x[1]+st->x[2]*st->x[2]); + st->x[0]=st->x[0]*norm/vnorm; + st->x[1]=st->x[1]*norm/vnorm; + st->x[2]=st->x[2]*norm/vnorm; + vnorm=sqrt(st->y[0]*st->y[0]+st->y[1]*st->y[1]+st->y[2]*st->y[2]); + st->y[0]=st->y[0]*norm/vnorm; + st->y[1]=st->y[1]*norm/vnorm; + st->y[2]=st->y[2]*norm/vnorm; + + projektion(st); + t3d_sort (st,0,st->maxk-1); + + dtime=gettime(st); + + if(st->cycl) + { + st->draw_color=(int)(64.0*(dtime/60-floor(dtime/60)))-32; + + if(st->draw_color<0) + st->draw_color=-st->draw_color; + + setink(st->colors[st->draw_color/3].pixel); + } + else + setink(BlackPixelOfScreen (st->xgwa.screen)); + + XFillRectangle(st->dpy,st->buffer,st->gc,0,0,st->scrnWidth,st->scrnHeight); + + { + int i; + + manipulate(st,dtime); + + for (i=0;imaxk;i++) + { + if (st->kugeln[i].d>0.0) + fill_kugel(st,i,st->buffer,1); + } + } + + /* manipulate(gettime()); + var+=PI/500; + if (var>=TWOPI) var=PI/500; */ + + if(st->hsvcycl!=0.0) + { + dtime=st->hsvcycl*dtime/10.0+st->hue/360.0; + dtime=360*(dtime-floor(dtime)); + + hsv2rgb(dtime,st->sat,st->val,&st->r,&st->g,&st->b); + changeColor(st,st->r,st->g,st->b); + } + + XCopyArea (st->dpy, st->buffer, st->window, st->gc, 0, 0, st->scrnWidth, st->scrnHeight, 0, 0); + + + /*-------------------------------------------------*/ + + XQueryPointer (st->dpy, st->window, &st->junk_win, &st->in_win, &st->junk, &st->junk, + &st->px, &st->py, &st->kb); + + if ((st->px>0)&&(st->pxscrnWidth)&&(st->py>0)&&(st->pyscrnHeight) ) + { + if ((st->px !=st->startx)&&(st->kb&Button2Mask)) + { + /* printf("y=(%f,%f,%f)",y[0],y[1],y[2]);*/ + turn(st->y,st->x,((double)(st->px-st->startx))/(8000*st->mag)); + /* printf("->(%f,%f,%f)\n",y[0],y[1],y[2]);*/ + } + if ((st->py !=st->starty)&&(st->kb&Button2Mask)) + { + /* printf("x=(%f,%f,%f)",x[0],x[1],x[2]);*/ + turn(st->x,st->y,((double)(st->py-st->starty))/(-8000*st->mag)); + /* printf("->(%f,%f,%f)\n",x[0],x[1],x[2]);*/ + } + if ((st->kb&Button1Mask)) + { + if (st->vturn==0.0) st->vturn=.005; else if (st->vturn<2) st->vturn+=.01; + turn(st->x,st->v,.002*st->vturn); + turn(st->y,st->v,.002*st->vturn); + } + if ((st->kb&Button3Mask)) + { + if (st->vturn==0.0) st->vturn=.005; else if (st->vturn<2) st->vturn+=.01; + turn(st->x,st->v,-.002*st->vturn); + turn(st->y,st->v,-.002*st->vturn); + } + } + if (!(st->kb&Button1Mask)&&!(st->kb&Button3Mask)) + st->vturn=0; + + st->speed=st->speed+st->speed*st->vspeed; + if ((st->speed<0.0000001) &&(st->vspeed>0.000001)) st->speed=0.000001; + st->vspeed=.1*st->vspeed; + if (st->speed>0.01) st->speed=.01; + st->a[0]=st->a[0]+st->speed*st->v[0]; + st->a[1]=st->a[1]+st->speed*st->v[1]; + st->a[2]=st->a[2]+st->speed*st->v[2]; + + return st->timewait; +} + +static void +t3d_reshape (Display *dpy, Window window, void *closure, + unsigned int w, unsigned int h) +{ + struct state *st = (struct state *) closure; + if (w != st->scrnWidth || + h != st->scrnHeight) + { + XFreePixmap (st->dpy, st->buffer); + st->scrnWidth = w; + st->scrnHeight = h; + st->buffer = XCreatePixmap (st->dpy, st->window, st->scrnWidth, st->scrnHeight, st->xgwa.depth); + + st->startx=st->scrnWidth/2; + st->starty=st->scrnHeight/2; + st->scrnH2=st->startx; + st->scrnW2=st->starty; + } +} + +static Bool +t3d_event (Display *dpy, Window window, void *closure, XEvent *event) +{ + struct state *st = (struct state *) closure; + if (event->type == KeyPress) + { + KeySym keysym; + char kpr = 0; + XLookupString (&event->xkey, &kpr, 1, &keysym, 0); + switch (kpr) + { + case 's': case 'S': + st->vspeed = 0.5; + return True; + case 'a': case 'A': + st->vspeed = -0.3; + return True; + case '0': + st->speed = 0; + st->vspeed = 0; + return True; + case 'z': case 'Z': + st->mag *= 1.02; + return True; + case 'x': case 'X': + st->mag /= 1.02; + return True; + default: + break; + } + } + return False; +} + +static void +t3d_free (Display *dpy, Window window, void *closure) +{ +} + + + + +/*-------------------------------------------------*/ + +static const char *t3d_defaults [] = { + ".background: black", + ".foreground: white", + "*move: 0.5", + "*wobble: 2.0", + "*cycle: 10.0", + "*mag: 1.0", + "*minutes: False", + "*delay: 40000", + "*fast: 50", + "*colcycle: False", + "*hsvcycle: 0.0", + "*rgb: ", + "*hsv: ", + 0 +}; + +static XrmOptionDescRec t3d_options [] = { + { "-move", ".move", XrmoptionSepArg, 0 }, + { "-wobble", ".wobble", XrmoptionSepArg, 0 }, + { "-cycle", ".cycle", XrmoptionSepArg, 0 }, + { "-mag", ".mag", XrmoptionSepArg, 0 }, + { "-minutes", ".minutes", XrmoptionNoArg, "True" }, + { "-no-minutes", ".minutes", XrmoptionNoArg, "False" }, + { "-delay", ".delay", XrmoptionSepArg, 0 }, + { "-fast", ".fast", XrmoptionSepArg, 0 }, + { "-colcycle", ".colcycle", XrmoptionSepArg, 0 }, + { "-hsvcycle", ".hsvcycle", XrmoptionSepArg, 0 }, + { "-rgb", ".rgb", XrmoptionSepArg, 0 }, + { "-hsv", ".hsv", XrmoptionSepArg, 0 }, + { 0, 0, 0, 0 } +}; + + +XSCREENSAVER_MODULE ("T3D", t3d) diff --git a/hacks/t3d.man b/hacks/t3d.man new file mode 100644 index 00000000..0db943b8 --- /dev/null +++ b/hacks/t3d.man @@ -0,0 +1,131 @@ +.TH t3d 1 "Version 1.1" "Time 3D" +.SH NAME +t3d \- clock using flying balls to display the time +.SH SYNOPSIS +t3d [ \f2 options\f1 ]... +.SH DESCRIPTION +.PP +Time 3D is a clock. It uses flying balls to display the time. This +balls move and wobble around to give you the impression your +graphic workstation with its many XStones is doing something. +.PP +t3d uses mouse and keyboard to let you fly through the balls. Hit +.B S +to speed up, +.B A +to slow down, +.B Z +to zoom in and +.B X +to zoom out. +Use the +.B left mouse button +to rotate to the left and the +.B right mouse button +to rotate the view to the right. Use the +.B middle mouse button +to change the optical axis and the moving direction. +.B 0 +(zero) will stop you. +.B Q +quits. +.PP +.SH OPTIONS +.TP +.BI "-move " "factor" +Modifies the direction move of t3d. The clock looks 30 degrees* +.I factor +to the left and to the right periodically. +.TP +.BI "-wobble " "factor" +Modifies the wobbling (sounds nice :-) of t3d by multiplying the +default deformation of the clock with +.I factor. +.TP +.B -minutes +Shows one small ball for every minute, instead of one for every 2.5 minutes. +.TP +.BI "-mag " "factor" +Changes the magnification of t3d. By default, t3d draws a 200x200 image. +A .I factor +of 2 means, it will use a 400x400 image. +.TP +.BI "-cycle " "period" +Sets the moving cycle to +.I period +seconds. By default, this value is 10 seconds. +.TP +.BI "-delay " "microsec" +Inserts a wait after drawing one view of the clock. By default, t3d waits +40 ms after each drawing. This helps you to keep the performance loss +small. +.TP +.BI "-fast " "precalc_radius" +t3d uses bitmap copy to draw precalculated balls. You can specify the radius +in pixels up to which t3d should precalculate balls. t3d will set a useful +range by itself using the magnification when it is started. +.TP +.B -colcycle +Draws cyclic the color scale used for the balls in the background instead +of the normal black. +.TP +.BI "-rgb " "red green blue" +Selects the color in RGB color space of the lightning spot on the balls. +All the other colors used for balls or +.B -colcycle +are less intensive colors of the same hue and saturation. All values +in range of 0 to 1. +.TP +.BI "-hsv " "hue saturation value" +Selects the color in HSV color space. +.I hue +is in degrees from 0 to 360, all other values in range from 0 to 1. It gives +nice but rather unpredictable results, if you use a saturation of e.g. 2. +Try it at your own risk. +.TP +.BI "-hsvcycle " "speed" +Rotates the hue axis every 10 seconds* +.I speed. +.TP +.B -help +Prints a short usage message. +.TP 8 +.B \-fps +Display the current frame rate and CPU load. +.PP +.SH AUTHOR +.PP +Bernd Paysan + +Email: bernd.paysan@gmx.de + +Hacked on by jwz@jwz.org for xscreensaver. + +.SH ACKNOWLEDGEMENT +.PP +Acknowledgement to Georg Acher, who wrote the initial program displaying +balls. + +.SH COPYING +.PP +Copy, modify, and distribute T3D either under GPL version 2 or newer, or +under the standard MIT/X license notice. + +.SH DISCLAIMER +.PP +T3D is not related to T3D(tm), the massive parallel Alpha--based +supercomputer from Cray Research. T3D's name was invented in 1991, +years before the project at Cray Research started. There is no +relation from T3D to Cray's T3D, even the balls surrounding T3D on +some posters weren't an inspiration for T3D. I don't know anything +about the other way round. + +The programming style of T3D isn't intended as example of good style, +but as example of how a fast prototyped demo may look like. T3D wasn't +created to be useful, it was created to be nice. + +.SH KNOWN BUGS +.PP +There are no known bugs in T3D. Maybe there are bugs in X. Slight +changes in the T3D sources are known to show these bugs, e.g. if +you remove the (int) casting at the XFillArc x,y,w,h-coordinates... diff --git a/hacks/thornbird.c b/hacks/thornbird.c new file mode 100644 index 00000000..e7bbf6dd --- /dev/null +++ b/hacks/thornbird.c @@ -0,0 +1,281 @@ +/* -*- Mode: C; tab-width: 4 -*- */ +/* thornbird --- continuously varying Thornbird set */ + +#if 0 +static const char sccsid[] = "@(#)thornbird.c 5.00 2000/11/01 xlockmore"; +#endif + +/*- + * Copyright (c) 1996 by Tim Auckland + * + * Permission to use, copy, modify, and distribute this software and its + * documentation for any purpose and without fee is hereby granted, + * provided that the above copyright notice appear in all copies and that + * both that copyright notice and this permission notice appear in + * supporting documentation. + * + * This file is provided AS IS with no warranties of any kind. The author + * shall have no liability with respect to the infringement of copyrights, + * trade secrets or any patents by this file or any part thereof. In no + * event will the author be liable for any lost revenue or profits or + * other special, indirect and consequential damages. + * + * "thornbird" shows a view of the "Bird in a Thornbush" fractal, + * continuously varying the three free parameters. + * + * Revision History: + * 01-Nov-2000: Allocation checks + * 04-Jun-1999: 3D tumble added by Tim Auckland + * 31-Jul-1997: Adapted from discrete.c Copyright (c) 1996 by Tim Auckland + */ + +#ifdef STANDALONE +# define MODE_thornbird +#define DEFAULTS "*delay: 10000 \n" \ + "*count: 100 \n" \ + "*cycles: 400 \n" \ + "*ncolors: 64 \n" \ + "*fpsSolid: true \n" \ + +# define BRIGHT_COLORS +# define thornbird_handle_event 0 +# include "xlockmore.h" /* in xscreensaver distribution */ +#else /* STANDALONE */ +# include "xlock.h" /* in xlockmore distribution */ +#endif /* STANDALONE */ + +#ifdef MODE_thornbird + +ENTRYPOINT ModeSpecOpt thornbird_opts = +{0, (XrmOptionDescRec *) NULL, 0, (argtype *) NULL, (OptionStruct *) NULL}; + +#ifdef USE_MODULES +ModStruct thornbird_description = +{"thornbird", "init_thornbird", "draw_thornbird", "release_thornbird", + "refresh_thornbird", "init_thornbird", (char *) NULL, þbird_opts, + 1000, 800, 16, 1, 64, 1.0, "", + "Shows an animated Bird in a Thorn Bush fractal map", 0, NULL}; + +#endif + +#define balance_rand(v) ((LRAND()/MAXRAND*(v))-((v)/2)) /* random around 0 */ + +typedef struct { + int maxx; + int maxy; /* max of the screen */ + double a; + double b; + double c; + double d; + double e; + double i; + double j; /* thornbird parameters */ + struct { + double f1; + double f2; + } liss; + struct { + double theta; + double dtheta; + double phi; + double dphi; + } tumble; + int inc; + int pix; + int count; + int nbuffers; + XPoint **pointBuffer; /* pointer for XDrawPoints */ +} thornbirdstruct; + +static thornbirdstruct *thornbirds = (thornbirdstruct *) NULL; + +static void +free_thornbird(thornbirdstruct *hp) +{ + if (hp->pointBuffer != NULL) { + int buffer; + + for (buffer = 0; buffer < hp->nbuffers; buffer++) + if (hp->pointBuffer[buffer] != NULL) + (void) free((void *) hp->pointBuffer[buffer]); + (void) free((void *) hp->pointBuffer); + hp->pointBuffer = (XPoint **) NULL; + } +} + +ENTRYPOINT void +init_thornbird (ModeInfo * mi) +{ + thornbirdstruct *hp; + + if (thornbirds == NULL) { + if ((thornbirds = + (thornbirdstruct *) calloc(MI_NUM_SCREENS(mi), + sizeof (thornbirdstruct))) == NULL) + return; + } + hp = þbirds[MI_SCREEN(mi)]; + + + hp->maxx = MI_WIDTH(mi); + hp->maxy = MI_HEIGHT(mi); + + hp->b = 0.1; + hp->i = hp->j = 0.1; + + hp->pix = 0; + hp->inc = 0; + + hp->nbuffers = MI_CYCLES(mi); + + if (hp->pointBuffer == NULL) + if ((hp->pointBuffer = (XPoint **) calloc(MI_CYCLES(mi), + sizeof (XPoint *))) == NULL) { + free_thornbird(hp); + return; + } + + if (hp->pointBuffer[0] == NULL) + if ((hp->pointBuffer[0] = (XPoint *) malloc(MI_COUNT(mi) * + sizeof (XPoint))) == NULL) { + free_thornbird(hp); + return; + } + + /* select frequencies for parameter variation */ + hp->liss.f1 = LRAND() % 5000; + hp->liss.f2 = LRAND() % 2000; + + /* choose random 3D tumbling */ + hp->tumble.theta = 0; + hp->tumble.phi = 0; + hp->tumble.dtheta = balance_rand(0.001); + hp->tumble.dphi = balance_rand(0.005); + + /* Clear the background. */ + MI_CLEARWINDOW(mi); + + hp->count = 0; +} + + +ENTRYPOINT void +draw_thornbird(ModeInfo * mi) +{ + Display *dsp = MI_DISPLAY(mi); + Window win = MI_WINDOW(mi); + double oldj, oldi; + int batchcount = MI_COUNT(mi); + int k; + XPoint *xp; + GC gc = MI_GC(mi); + int erase; + int current; + + double sint, cost, sinp, cosp; + thornbirdstruct *hp; + + if (thornbirds == NULL) + return; + hp = þbirds[MI_SCREEN(mi)]; + if (hp->pointBuffer == NULL) + return; + + erase = (hp->inc + 1) % MI_CYCLES(mi); + current = hp->inc % MI_CYCLES(mi); + k = batchcount; + + + xp = hp->pointBuffer[current]; + + /* vary papameters */ + hp->a = 1.99 + (0.4 * sin(hp->inc / hp->liss.f1) + + 0.05 * cos(hp->inc / hp->liss.f2)); + hp->c = 0.80 + (0.15 * cos(hp->inc / hp->liss.f1) + + 0.05 * sin(hp->inc / hp->liss.f2)); + + /* vary view */ + hp->tumble.theta += hp->tumble.dtheta; + hp->tumble.phi += hp->tumble.dphi; + sint = sin(hp->tumble.theta); + cost = cos(hp->tumble.theta); + sinp = sin(hp->tumble.phi); + cosp = cos(hp->tumble.phi); + + while (k--) { + oldj = hp->j; + oldi = hp->i; + + hp->j = oldi; + hp->i = (1 - hp->c) * cos(M_PI * hp->a * oldj) + hp->c * hp->b; + hp->b = oldj; + + xp->x = (short) + (hp->maxx / 2 * (1 + + sint*hp->j + cost*cosp*hp->i - cost*sinp*hp->b)); + xp->y = (short) + (hp->maxy / 2 * (1 + - cost*hp->j + sint*cosp*hp->i - sint*sinp*hp->b)); + xp++; + } + + MI_IS_DRAWN(mi) = True; + + if (hp->pointBuffer[erase] == NULL) { + if ((hp->pointBuffer[erase] = (XPoint *) malloc(MI_COUNT(mi) * + sizeof (XPoint))) == NULL) { + free_thornbird(hp); + return; + } + } else { + XSetForeground(dsp, gc, MI_BLACK_PIXEL(mi)); + XDrawPoints(dsp, win, gc, hp->pointBuffer[erase], + batchcount, CoordModeOrigin); + } + if (MI_NPIXELS(mi) > 2) { + XSetForeground(dsp, gc, MI_PIXEL(mi, hp->pix)); +#if 0 + if (erase == 0) /* change colours after "cycles" cycles */ +#else + if (!((hp->inc + 1) % (1 + (MI_CYCLES(mi) / 3)))) /* jwz: sooner */ +#endif + if (++hp->pix >= MI_NPIXELS(mi)) + hp->pix = 0; + } else + XSetForeground(dsp, gc, MI_WHITE_PIXEL(mi)); + + XDrawPoints(dsp, win, gc, hp->pointBuffer[current], + batchcount, CoordModeOrigin); + hp->inc++; +} + +ENTRYPOINT void +reshape_thornbird(ModeInfo * mi, int width, int height) +{ + XClearWindow (MI_DISPLAY (mi), MI_WINDOW(mi)); + init_thornbird (mi); +} + +ENTRYPOINT void +release_thornbird(ModeInfo * mi) +{ + if (thornbirds != NULL) { + int screen; + + for (screen = 0; screen < MI_NUM_SCREENS(mi); screen++) + free_thornbird(þbirds[screen]); + (void) free((void *) thornbirds); + thornbirds = (thornbirdstruct *) NULL; + } +} + +ENTRYPOINT void +refresh_thornbird (ModeInfo * mi) +{ + MI_CLEARWINDOW(mi); +} + + +XSCREENSAVER_MODULE ("Thornbird", thornbird) + +#endif /* MODE_thornbird */ diff --git a/hacks/thornbird.man b/hacks/thornbird.man new file mode 100644 index 00000000..e063b1a1 --- /dev/null +++ b/hacks/thornbird.man @@ -0,0 +1,64 @@ +.TH XScreenSaver 1 "" "X Version 11" +.SH NAME +thornbird - Bird in a Thornbush fractal. +.SH SYNOPSIS +.B thornbird +[\-display \fIhost:display.screen\fP] +[\-visual \fIvisual\fP] +[\-window] +[\-root] +[\-count \fInumber\fP] +[\-cycles \fInumber\fP] +[\-delay \fInumber\fP] +[\-ncolors \fInumber\fP] +[\-fps] +.SH DESCRIPTION +Displays a view of the "Bird in a Thornbush" fractal. +.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 \-count \fInumber\fP +Points. 10 - 1000. Default: 800. +.TP 8 +.B \-cycles \fInumber\fP +Thickness. 2 - 500. Default: 16. +.TP 8 +.B \-delay \fInumber\fP +Per-frame delay, in microseconds. Default: 10000 (0.01 seconds.). +.TP 8 +.B \-ncolors \fInumber\fP +Number of Colors. Default: 64. +.TP 8 +.B \-fps +Display the current frame rate and CPU load. +.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 2002 by Tim Auckland. 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 +Tim Auckland. diff --git a/hacks/triangle.c b/hacks/triangle.c new file mode 100644 index 00000000..1a93de25 --- /dev/null +++ b/hacks/triangle.c @@ -0,0 +1,369 @@ +/* -*- Mode: C; tab-width: 4 -*- */ +/* triangle --- create a triangle-mountain */ + +#if 0 +static const char sccsid[] = "@(#)triangle.c 4.04 97/07/28 xlockmore"; +#endif + +/*- + * Copyright (c) 1995 by Tobias Gloth + * + * Permission to use, copy, modify, and distribute this software and its + * documentation for any purpose and without fee is hereby granted, + * provided that the above copyright notice appear in all copies and that + * both that copyright notice and this permission notice appear in + * supporting documentation. + * + * This file is provided AS IS with no warranties of any kind. The author + * shall have no liability with respect to the infringement of copyrights, + * trade secrets or any patents by this file or any part thereof. In no + * event will the author be liable for any lost revenue or profits or + * other special, indirect and consequential damages. + * + * Revision History: + * 10-May-97: Compatible with xscreensaver + * 10-Mar-96: re-arranged and re-formatted the code for appearance and + * to make common subroutines. Simplified. + * Ron Hitchens + * 07-Mar-96: Removed internal delay code, set MI_PAUSE(mi) for inter-scene + * delays. No other delays are needed here. + * Made pause time sensitive to value of cycles (in 10ths of a + * second). Removed (hopefully) all references to globals. + * Ron Hitchens + * 27-Feb-96: Undid the changes listed below. Added ModeInfo argument. + * Implemented delay between scenes using the MI_PAUSE(mi) + * scheme. Ron Hitchens + * 27-Dec-95: Ron Hitchens + * Modified logic of draw_triangle() to provide a delay + * (sensitive to the value of cycles) between each iteration. + * Because this mode is so compute intensive, when the new + * event loop adjusted the delay to compensate, this mode had + * almost no delay time left. This change pauses between each + * new landscape, but could still be done better (it is not + * sensitive to input events while drawing, for example). + * 03-Nov-95: Many changes (hopefully some good ones) by David Bagley + * 01-Oct-95: Written by Tobias Gloth + */ + +#ifdef STANDALONE +# define DEFAULTS "*delay: 10000 \n" \ + "*ncolors: 128 \n" \ + "*fpsSolid: true \n" \ + +# define SMOOTH_COLORS +# define triangle_handle_event 0 +# include "xlockmore.h" /* in xscreensaver distribution */ +#else /* STANDALONE */ +# include "xlock.h" /* in xlockmore distribution */ +#endif /* STANDALONE */ + +ENTRYPOINT ModeSpecOpt triangle_opts = +{0, NULL, 0, NULL, NULL}; + +#define MAX_STEPS 8 +#define MAX_SIZE (1< 2) { /* color */ + int dmax, dmin; + long color; + + dmin = MIN(y_0, y_1); + dmin = MIN(dmin, y_2); + dmax = MAX(y_0, y_1); + dmax = MAX(dmax, y_2); + + if (dmax == 0) { + color = BLUE; + } else { + color = MI_NCOLORS(mi) - + (int) ((double) MI_NCOLORS(mi) / M_PI_2 * atan(dinv * (dmax - dmin))); + } + + XSetForeground(display, gc, mi->colors[color % MI_NCOLORS(mi)].pixel); + XFillPolygon(display, window, gc, p, 3, Convex, CoordModeOrigin); + } else { + /* mono */ +#ifdef BACKFACE_REMOVAL + XSetForeground(display, gc, MI_WIN_BLACK_PIXEL(mi)); + XFillPolygon(display, window, gc, p, 3, Convex, CoordModeOrigin); +#endif + XSetForeground(display, gc, MI_WIN_WHITE_PIXEL(mi)); + XDrawLine(display, window, gc, p[0].x, p[0].y, p[1].x, p[1].y); + XDrawLine(display, window, gc, p[1].x, p[1].y, p[2].x, p[2].y); + XDrawLine(display, window, gc, p[2].x, p[2].y, p[0].x, p[0].y); + } +} + +static +void +calc_points1(trianglestruct * tp, int d, int *y0_p, int *y1_p, int *y2_p, XPoint * p) +{ + *y0_p = tp->level[MAX(tp->h[tp->i][tp->j], 0)]; + *y1_p = tp->level[MAX(tp->h[tp->i + d][tp->j], 0)]; + *y2_p = tp->level[MAX(tp->h[tp->i][tp->j + d], 0)]; + + p[0].x = tp->xpos[2 * tp->i + tp->j]; + p[1].x = tp->xpos[2 * (tp->i + d) + tp->j]; + p[2].x = tp->xpos[2 * tp->i + (tp->j + d)]; + + p[0].y = tp->ypos[tp->j] - *y0_p; + p[1].y = tp->ypos[tp->j] - *y1_p; + p[2].y = tp->ypos[tp->j + d] - *y2_p; +} + +static +void +calc_points2(trianglestruct * tp, int d, int *y0_p, int *y1_p, int *y2_p, XPoint * p) +{ + *y0_p = tp->level[MAX(tp->h[tp->i + d][tp->j], 0)]; + *y1_p = tp->level[MAX(tp->h[tp->i + d][tp->j + d], 0)]; + *y2_p = tp->level[MAX(tp->h[tp->i][tp->j + d], 0)]; + + p[0].x = tp->xpos[2 * (tp->i + d) + tp->j]; + p[1].x = tp->xpos[2 * (tp->i + d) + (tp->j + d)]; + p[2].x = tp->xpos[2 * tp->i + (tp->j + d)]; + + p[0].y = tp->ypos[tp->j] - *y0_p; + p[1].y = tp->ypos[tp->j + d] - *y1_p; + p[2].y = tp->ypos[tp->j + d] - *y2_p; +} + + +static +void +draw_mesh(ModeInfo * mi, trianglestruct * tp, int d, int count) +{ + XPoint p[3]; + int first = 1; + int y_0, y_1, y_2; + double dinv = 0.2 / d; + + if ((tp->j == 0) && (tp->i == 0)) { +#if 0 /* jwz */ + XClearWindow(MI_DISPLAY(mi), MI_WINDOW(mi)); +#else + { + int x = 0; + int y = 0; + int x2 = MI_WIN_WIDTH(mi); + int y2 = tp->ypos[0]; + XSetForeground(MI_DISPLAY(mi), MI_GC(mi), MI_WIN_BLACK_PIXEL(mi)); + XFillRectangle(MI_DISPLAY(mi), MI_WINDOW(mi), MI_GC(mi), + x, y, x2, y2); + } +#endif + } + for (; (tp->j < tp->size) && (count > 0); tp->j += ((count) ? d : 0)) { + for (tp->i = (first) ? tp->i : 0, first = 0; + (tp->i < MAX_SIZE - tp->j) && (count > 0); + tp->i += d, count--) { + if (tp->i + tp->j < tp->size) { + calc_points1(tp, d, &y_0, &y_1, &y_2, p); + draw_atriangle(mi, p, y_0, y_1, y_2, dinv); + } + if (tp->i + tp->j + d < tp->size) { + calc_points2(tp, d, &y_0, &y_1, &y_2, p); + draw_atriangle(mi, p, y_0, y_1, y_2, dinv); + } + } + } + + if (tp->j == tp->size) { + tp->init_now = 1; + } +} + +ENTRYPOINT void +init_triangle (ModeInfo * mi) +{ + trianglestruct *tp; + short *tmp; + int i, dim, one; + + if (triangles == NULL) { + if ((triangles = (trianglestruct *) calloc(MI_NUM_SCREENS(mi), + sizeof (trianglestruct))) == NULL) + return; + } + tp = &triangles[MI_SCREEN(mi)]; + + tp->width = MI_WIN_WIDTH(mi); + tp->height = MI_WIN_HEIGHT(mi); + tp->init_now = 1; + tp->fast = 2; + + XClearWindow(MI_DISPLAY(mi), MI_WINDOW(mi)); + + + + tp->steps = MAX_STEPS; + do { + tp->size = 1 << --tp->steps; + } while (tp->size * 5 > tp->width); + tmp = tp->H; + for (i = 0; i < tp->size + 1; i++) { + tp->h[i] = tmp; + tmp += (tp->size) + 1 - i; + } + + tp->stage = -1; + dim = MIN(tp->width, tp->height); + + for (i = 0; i < 2 * tp->size + 1; i++) { + tp->xpos[i] = (short) ((((double) i) + / ((double) (2 * tp->size)) * (RIGHT - LEFT) + LEFT) + * dim) + (tp->width - dim) / 2; + } + + for (i = 0; i < (tp->size + 1); i++) { + tp->ypos[i] = (short) ((((double) i) + / ((double) tp->size) * (BOTTOM - TOP) + TOP) * dim) + + (tp->height - dim) / 2; + } + + for (i = 0; i < tp->steps; i++) { + tp->delta[i] = ((short) (DELTA * dim)) >> i; + } + + one = tp->delta[0]; + + if (one > 0) + for (i = 0; i < MAX_LEVELS; i++) { + tp->level[i] = (i * i) / one; + } +} + +ENTRYPOINT void +draw_triangle (ModeInfo * mi) +{ + trianglestruct *tp = &triangles[MI_SCREEN(mi)]; + int d, d2, i, j, delta; + + if (!tp->init_now) { + draw_mesh(mi, tp, tp->d / 2, MAX_SIZE / tp->d); + + /* The init_now flag will pop up when the scene is complete. + * Cycles specifies how long to wait, in 1/10 secs. + TODO: This is wrong for multi-screens *** + */ + if (tp->init_now) { +#ifndef STANDALONE + MI_PAUSE(mi) = 2000000; +#else + if (tp->stage == -1) + { + XClearWindow(MI_DISPLAY(mi), MI_WINDOW(mi)); + if (!mono_p) + { + free_colors(mi->dpy, mi->xgwa.colormap, mi->colors, + mi->npixels); + mi->npixels = + get_integer_resource (mi->dpy, "ncolors", "Integer"); + make_smooth_colormap (mi->dpy, + mi->xgwa.visual, mi->xgwa.colormap, + mi->colors, &mi->npixels, + True, &mi->writable_p, True); + } + } +#endif + } + return; + } + if (tp->delta[0] > 0) { + if (!(++tp->stage)) { + tp->h[0][0] = (short int) MAX(0, DISPLACE(0, tp->delta[0])); + tp->h[tp->size][0] = (short int) MAX(0, DISPLACE(0, tp->delta[0])); + tp->h[0][tp->size] = (short int) MAX(0, DISPLACE(0, tp->delta[0])); + } else { + d = 2 << (tp->steps - tp->stage); + d2 = d / 2; + delta = tp->delta[tp->stage - 1]; + + for (i = 0; i < tp->size; i += d) { + for (j = 0; j < (tp->size - i); j += d) { + tp->h[i + d2][j] = (short int) DISPLACE(tp->h[i][j] + + tp->h[i + d][j], delta); + tp->h[i][j + d2] = (short int) DISPLACE(tp->h[i][j] + + tp->h[i][j + d], delta); + tp->h[i + d2][j + d2] = (short int) DISPLACE(tp->h[i + d][j] + + tp->h[i][j + d], delta); + } + + tp->init_now = 0; + tp->i = 0; + tp->j = 0; + tp->d = d; + } + } + } + if (tp->stage == tp->steps) { + tp->stage = -1; + } +} + +ENTRYPOINT void +reshape_triangle(ModeInfo * mi, int width, int height) +{ + XClearWindow (MI_DISPLAY (mi), MI_WINDOW(mi)); + init_triangle (mi); +} + +ENTRYPOINT void +release_triangle(ModeInfo * mi) +{ + if (triangles != NULL) { + (void) free((void *) triangles); + triangles = NULL; + } +} + +ENTRYPOINT void +refresh_triangle (ModeInfo * mi) +{ + /* Do nothing, it will refresh by itself */ +} + +XSCREENSAVER_MODULE ("Triangle", triangle) diff --git a/hacks/triangle.man b/hacks/triangle.man new file mode 100644 index 00000000..ec8eadc8 --- /dev/null +++ b/hacks/triangle.man @@ -0,0 +1,56 @@ +.TH XScreenSaver 1 "" "X Version 11" +.SH NAME +triangle - random mountains using iterative subdivision of triangles. +.SH SYNOPSIS +.B triangle +[\-display \fIhost:display.screen\fP] +[\-visual \fIvisual\fP] +[\-window] +[\-root] +[\-delay \fInumber\fP] +[\-ncolors \fInumber\fP] +[\-fps] +.SH DESCRIPTION +Generates random mountain ranges using iterative subdivision of triangles. +.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: 10000 (0.01 seconds.). +.TP 8 +.B \-ncolors \fInumber\fP +Number of Colors. Default: 128. +.TP 8 +.B \-fps +Display the current frame rate and CPU load. +.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 2002 by Tobias Gloth. 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 +Tobias Gloth. diff --git a/hacks/truchet.c b/hacks/truchet.c new file mode 100644 index 00000000..16836543 --- /dev/null +++ b/hacks/truchet.c @@ -0,0 +1,533 @@ +/* truchet --- curved and straight tilings + * Copyright (c) 1998 Adrian Likins + * + * 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. + */ + +/* This screensaver draws two varieties of truchet patterns, a curved one and + a straight one. There are lots and lots of command line options to play + with. + + If your running remotely or on a slow machine or slow xserver, some of the + settings will be way too much. The default settings should be okay though. + + This screensaver doesnt use anything bizarre or special at all, just a few + standard xlib calls. + + A few suggested commandline combos..All these were tested on a k6-200 + running XFree86 3.3 on a ark2000, so your mileage may vary... + + truchet -delay 200 -no-curves + truchet -delay 500 -no-curves -square -no-erase + truchet -delay 500 -no-erase -square -erase-count 5 + truchet -scroll + truchet -scroll -no-erase -anim-step-size 9 + truchet -delay 200 -no-angles -min-width 36 -max-width 36 + truchet -delay 200 -no-curves -min-width 12 -max-width 12 + truchet -delay 200 -no-curves -min-width 36 -max-width 36 -no-erase + truchet -delay 100 -min-width 256 -max-width 512 -no-erase \ + -min-linewidth 96 -root + truchet -min-width 64 -max-width 128 -no-erase -max-linewidth 4 \ + -root -no-angles + truchet -min-width 64 -max-width 128 -no-erase -max-linewidth 4 \ + -root -no-curves -delay 25 + */ + +#include "screenhack.h" + +#define MAXRATIO 2 + +static const char *truchet_defaults [] = { + "*minWidth: 40", + "*minHeight: 40", + "*max-Width: 150", + "*max-Height: 150", + "*maxLineWidth: 25", + "*minLineWidth: 2", + "*erase: True", + "*eraseCount: 25", + "*square: True", + "*delay: 400000", + "*curves: True", + "*angles: True", + "*scroll: False", + "*scroll-overlap: 400", + "*anim-delay: 100", + "*anim-step-size: 3", + "*randomize: true", + 0 +}; + +/* options passed to this program */ +static XrmOptionDescRec truchet_options [] = { + { "-min-width", ".minWidth", XrmoptionSepArg, 0 }, + { "-max-height", ".max-Height", XrmoptionSepArg, 0 }, + { "-max-width", ".max-Width", XrmoptionSepArg, 0 }, + { "-min-height", ".minHeight", XrmoptionSepArg, 0 }, + { "-max-linewidth", ".maxLineWidth", XrmoptionSepArg, 0 }, + { "-min-linewidth", ".minLineWidth", XrmoptionSepArg, 0 }, + { "-erase", ".erase", XrmoptionNoArg, "True" }, + { "-no-erase", ".erase", XrmoptionNoArg, "False" }, + { "-erase-count", ".eraseCount", XrmoptionSepArg, 0 }, + { "-square", ".square", XrmoptionNoArg, "True" }, + { "-not-square", ".square", XrmoptionNoArg, "False" }, + { "-curves", ".curves", XrmoptionNoArg, "True" }, + { "-angles", ".angles", XrmoptionNoArg, "True" }, + { "-no-angles", ".angles", XrmoptionNoArg, "False" }, + { "-no-curves", ".curves", XrmoptionNoArg, "False" }, + { "-delay", ".delay", XrmoptionSepArg, 0 }, + { "-scroll", ".scroll", XrmoptionNoArg, "True" }, + { "-scroll-overlap", ".scroll-overlap", XrmoptionSepArg, 0 }, + { "-anim-delay", ".anim-delay", XrmoptionSepArg, 0 }, + { "-anim-step-size", ".anim-step-size", XrmoptionSepArg, 0 }, + { "-randomize", ".randomize", XrmoptionNoArg, "True" }, + { 0, 0, 0, 0 } +}; + +struct state { + Display *dpy; + Window window; + + XGCValues gcv; + GC agc, bgc; + int linewidth; + int width, height; + XWindowAttributes xgwa; + Pixmap frame; + int overlap; + + int maxlinewidth; + int minlinewidth; + int minwidth; + int minheight; + int max_height; + int max_width; + int delay; + int count; + int anim_delay; + int anim_step_size; + + Colormap cmap; + XColor fgc; + Bool curves; + Bool square; + Bool angles; + Bool erase; + Bool eraseCount; + Bool scroll; + int scrolling; +}; + +static void draw_truchet(struct state *st); +static void draw_angles(struct state *st); +static void scroll_area(struct state *st, int step_size); + +static void draw_angles(struct state *st) +{ + int cx = 0, cy = 0; + + while((st->xgwa.height+st->overlap) > cy*st->height) + { + while((st->xgwa.width+st->overlap) > cx*st->width) + { + if(random()%2) + { + /* block1 */ + XDrawLine(st->dpy,st->frame,st->agc, + (cx*st->width)+(st->width/2), + (cy*st->height), + (cx*st->width)+(st->width), + (cy*st->height)+(st->height/2)); + XDrawLine(st->dpy,st->frame,st->agc, + (cx*st->width), + (cy*st->height)+(st->height/2), + (cx*st->width)+(st->width/2), + (cy*st->height)+(st->height)); + } + else + { + /* block 2 */ + XDrawLine(st->dpy,st->frame,st->agc, + (cx*st->width)+(st->width/2), + (cy*st->height), + (cx*st->width), + (cy*st->height)+(st->height/2)); + XDrawLine(st->dpy,st->frame,st->agc, + (cx*st->width)+(st->width), + (cy*st->height)+(st->height/2), + (cx*st->width)+(st->width/2), + (cy*st->height)+(st->height)); + } + cx++; + } + cy++; + cx=0; + } +} + + +static void draw_truchet(struct state *st) +{ + int cx = 0, cy = 0; + + while(st->xgwa.height+st->overlap > cy*st->height) + { + while(st->xgwa.width+st->overlap > cx*st->width) + { + if(random()%2) + { + /* block1 */ + XDrawArc(st->dpy, st->frame, st->agc, + ((cx*st->width)-(st->width/2)), + ((cy*st->height)-(st->height/2)), + st->width, + st->height, + 0, -5760); + XDrawArc(st->dpy,st->frame, st->agc, + ((cx*st->width)+(st->width/2)), + ((cy*st->height)+(st->height/2)), + st->width, + st->height, + 11520, + -5760); + } + else + { + /* block 2 */ + XDrawArc(st->dpy,st->frame,st->agc, + ((cx*st->width)+(st->width/2)), + ((cy*st->height)-(st->height/2)), + st->width, + st->height, + 17280, + -5760); + XDrawArc(st->dpy,st->frame,st->agc, + ((cx*st->width)-(st->width/2)), + ((cy*st->height)+(st->height/2)), + st->width, + st->height, + 0, + 5760); + } + cx++; + } + cy++; + cx=0; + } +} + + +static void scroll_area(struct state *st, int step_size) +{ + int scrollcount_x; + int scrollcount_y; + int offset; + int scroll; + int direction; + int progress; + + offset=st->overlap/2; + scroll=st->overlap/4; + + /* This runs in a loop, starting with + * st->scrolling = (scroll / st->anim_step_size) * 4 - 1; + * and going all the way down to st->scrolling = 0. + */ + + /* if anyone knows a good way to generate + * a more random scrolling motion... */ + + direction = st->scrolling / (scroll / st->anim_step_size); + progress = (st->scrolling % (scroll / st->anim_step_size)) * st->anim_step_size; + + if (direction & 1) { + scrollcount_x = progress - scroll; + scrollcount_y = progress; + } else { + scrollcount_x = -progress; + scrollcount_y = progress - scroll; + } + + if (direction & 2) { + scrollcount_x = -scrollcount_x; + scrollcount_y = -scrollcount_y; + } + + XCopyArea(st->dpy, st->frame, st->window, st->agc,scrollcount_x+offset,scrollcount_y+offset, st->xgwa.width, st->xgwa.height, 0,0); +} + + +static void * +truchet_init (Display *dpy, Window window) +{ + struct state *st = (struct state *) calloc (1, sizeof(*st)); + + st->dpy = dpy; + st->window = window; + + st->maxlinewidth = get_integer_resource (st->dpy, "maxLineWidth", "Integer"); + st->minlinewidth = get_integer_resource (st->dpy, "minLineWidth", "Integer"); + st->minwidth = get_integer_resource (st->dpy, "minWidth", "Integer"); + st->minheight = get_integer_resource (st->dpy, "minHeight", "Integer"); + st->max_width = get_integer_resource (st->dpy, "max-Width", "Integer"); + st->max_height = get_integer_resource (st->dpy, "max-Height", "Integer" ); + st->delay = get_integer_resource (st->dpy, "delay", "Integer"); + st->eraseCount = get_integer_resource (st->dpy, "eraseCount", "Integer"); + st->square = get_boolean_resource (st->dpy, "square", "Boolean"); + st->curves = get_boolean_resource (st->dpy, "curves", "Boolean"); + st->angles = get_boolean_resource (st->dpy, "angles", "Boolean"); + st->erase = get_boolean_resource (st->dpy, "erase", "Boolean"); + st->scroll = get_boolean_resource (st->dpy, "scroll", "Boolean"); + st->overlap = get_integer_resource (st->dpy, "scroll-overlap", "Integer"); + st->anim_delay = get_integer_resource (st->dpy, "anim-delay", "Integer"); + st->anim_step_size = get_integer_resource (st->dpy, "anim-step-size", "Integer"); + + if (get_boolean_resource(st->dpy, "randomize", "Randomize")) + { + int i = (random() % 12); + switch(i) { + case 0: + break; + case 1: + st->curves = False; + break; + case 2: + st->curves = False; + st->square = True; + st->erase = False; + break; + case 3: + st->square = True; + st->erase = False; + st->eraseCount = 5; + break; + case 4: + st->scroll = True; + break; + case 5: + st->scroll = True; + st->erase = False; + st->anim_step_size = 9; + break; + case 6: + st->angles = False; + st->minwidth = st->max_width = 36; + break; + case 7: + st->curves = False; + st->minwidth = st->max_width = 12; + break; + case 8: + st->curves = False; + st->erase = False; + st->minwidth = st->max_width = 36; + break; + case 9: + st->erase = False; + st->minwidth = 256; + st->max_width = 512; + st->minlinewidth = 96; + break; + case 10: + st->angles = False; + st->minwidth = 64; + st->max_width = 128; + st->maxlinewidth = 4; + break; + case 11: + st->curves = False; + st->minwidth = 64; + st->max_width = 128; + st->maxlinewidth = 4; + break; + default: + abort(); + break; + } + } + + XGetWindowAttributes (st->dpy, st->window, &st->xgwa); + st->gcv.foreground = BlackPixel(st->dpy,0); + st->gcv.background = WhitePixel(st->dpy,0); + st->gcv.line_width = 25; + st->cmap = st->xgwa.colormap; + + st->gcv.foreground = get_pixel_resource(st->dpy, st->xgwa.colormap, + "background", "Background"); + + st->bgc = XCreateGC (st->dpy, st->window, GCForeground, &st->gcv); + st->agc = XCreateGC(st->dpy, st->window, GCForeground, &st->gcv); + + XFillRectangle(st->dpy, st->window, st->bgc, 0, 0, st->xgwa.width, st->xgwa.height); + + + st->width=60; + st->height=60; + st->linewidth=1; + st->count=0; + XSetForeground(st->dpy, st->agc, st->gcv.background); + + + st->frame = XCreatePixmap(st->dpy,st->window, st->xgwa.width+st->overlap, st->xgwa.height+st->overlap, st->xgwa.depth); + XFillRectangle(st->dpy, st->frame, st->bgc, 0, 0, + st->xgwa.width + st->overlap, + st->xgwa.height + st->overlap); + + return st; +} + +static unsigned long +truchet_draw (Display *dpy, Window window, void *closure) +{ + struct state *st = (struct state *) closure; + + if (st->scrolling) + { + st->scrolling--; + scroll_area(st, st->anim_step_size); + return st->anim_delay*1000; + } + + if (!mono_p) + { + /* XXX there are probably bugs with this. */ + /* could be...I just borrowed this code from munch */ + + st->fgc.red = random() % 65535; + st->fgc.green = random() % 65535; + st->fgc.blue = random() % 65535; + + if (XAllocColor(st->dpy, st->cmap, &st->fgc)) + { + XSetForeground(st->dpy, st->agc, st->fgc.pixel); + } + else + { + /* use white if all else fails */ + XSetForeground(st->dpy,st->agc, st->gcv.background); + } + } + + + + + /* generate a random line width */ + st->linewidth=(random()% st->maxlinewidth); + + /* check for lower bound */ + if(st->linewidth < st->minlinewidth) + st->linewidth = st->minlinewidth; + + /* try to get an odd linewidth as it seem to work a little better */ + if(st->linewidth%2) + st->linewidth++; + + /* grab a random height and width */ + st->width=(random()%st->max_width); + st->height=(random()%st->max_height); + + /* make sure we dont get a 0 height or width */ + if(st->width == 0 || st->height == 0) + { + st->height=st->max_height; + st->width=st->max_width; + } + + + /* check for min height and width */ + if(st->height < st->minheight) + { + st->height=st->minheight; + } + if(st->width < st->minwidth) + { + st->width=st->minwidth; + } + + /* if tiles need to be square, fix it... */ + if(st->square) + st->height=st->width; + + /* check for sane aspect ratios */ + if((st->width/st->height) > MAXRATIO) + st->height=st->width; + if((st->height/st->width) > MAXRATIO) + st->width=st->height; + + /* to avoid linewidths of zero */ + if(st->linewidth == 0 || st->linewidth < st->minlinewidth) + st->linewidth = st->minlinewidth; + + /* try to keep from getting line widths that would be too big */ + if(st->linewidth > 0 && st->linewidth >= (st->height/5)) + st->linewidth = st->height/5; + + XSetLineAttributes(st->dpy, st->agc, st->linewidth, LineSolid, CapRound, JoinRound); + + if(st->erase || (st->count >= st->eraseCount)) + { + /* XClearWindow(dpy,window); */ + XFillRectangle(st->dpy, st->frame, st->bgc, 0, 0, st->xgwa.width+st->overlap, st->xgwa.height+st->overlap); + st->count=0; + } + + if(!st->scroll) + st->overlap=0; + + /* do the fun stuff...*/ + if(st->curves && st->angles) + { + if(random()%2) + draw_truchet(st); + else + draw_angles(st); + } + else if(st->curves && !st->angles) + draw_truchet(st); + else if(!st->curves && st->angles) + draw_angles(st); + + + st->count++; + + if(st->scroll) + { + st->scrolling = ((st->overlap / 4) / st->anim_step_size) * 4; + return 0; + } + + XCopyArea(st->dpy,st->frame,st->window,st->agc,0,0,st->xgwa.width,st->xgwa.height,0,0); + + return st->delay; +} + +static void +truchet_reshape (Display *dpy, Window window, void *closure, + unsigned int w, unsigned int h) +{ + struct state *st = (struct state *) closure; + st->width = w; + st->height = h; + XGetWindowAttributes (st->dpy, st->window, &st->xgwa); +} + +static Bool +truchet_event (Display *dpy, Window window, void *closure, XEvent *event) +{ + return False; +} + +static void +truchet_free (Display *dpy, Window window, void *closure) +{ +} + + +XSCREENSAVER_MODULE ("Truchet", truchet) + diff --git a/hacks/truchet.man b/hacks/truchet.man new file mode 100644 index 00000000..33890e6b --- /dev/null +++ b/hacks/truchet.man @@ -0,0 +1,139 @@ +.TH XScreenSaver 1 "27-May-97" "X Version 11" +.SH NAME +truchet - draws curved or angular Truchet patterns +.SH SYNOPSIS +.B truchet +[\-display \fIhost:display.screen\fP] [\-foreground \fIcolor\fP] [\-background \fIcolor\fP] +[\-window] [\-root] [\-mono] [\-install] [\-visual \fIvisual\fP] [\-delay \fImilliseconds\fP] +[\-min\-width \fIinteger\fP] [\-min-height \fIinteger\fP] [\-max-width \fIinteger\fP] +[\-max-height \fIinteger\fP] [\-max\-linewidth \fIinteger\fP] [\-min-linewidth \fIinteger\fP] +[\-erase] [\-no\-erase] [\-erase\-count \fIinteger\fP] [\-square] [\-not\-square] [\-curves] +[\-no\-curves] [\-angle] [\-no\-angles] [\-scroll] [\-scroll\-overlap \fIinteger\fP] +[\-anim\-delay \fIinteger\fP] [\-anim\-step\-size \fIinteger\fP] + +[\-fps] +.SH DESCRIPTION +The \fItruchet\fP program draws arc and line based Truchet patterns. +.SH OPTIONS +.I truchet +accepts the following options: +.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 \-mono +If on a color display, pretend we're on a monochrome display. +.TP 8 +.B \-install +Install a private colormap for the window. +.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 \-delay \fImilliseconds\fP +How long to wait between drawing each screenful. Default is 1 seconds. + +.TP 8 +.B \-min-width \fIinteger\fP +The minimum width in pixels of each square. Default is 40. + +.TP 8 +.B \-min-height \fIinteger\fP +The minimum height in pixels of each square. Default is 40. + +.TP 8 +.B \-max-width \fIinteger\fP +The maximum width in pixels of each square. Default is 150. + +.TP 8 +.B \-max-height \fIinteger\fP +The maximum height in pixels of each square. Default is 150. + +.TP 8 +.B \-max-linewidth \fIinteger\fP +The maximum width of the lines used to draw. Default is 25. + +.TP 8 +.B \-min-linewidth \fIinteger\fP +The minimum width of the lines used to draw. Default is 2. + +.TP 8 +.B \-erase + +.TP 8 +.B \-no-erase +Whether to clear the screen after each screenful is drawn. Default is True (erase). + +.TP 8 +.B \-erase-count \fIinteger\fP +The number of screenfuls to draw before erasing. Default is 25. + +.TP 8 +.B \-square + +.TP 8 +.B \-not-square +Whether to force the tiles to be square. Default is True (square). + +.TP 8 +.B \-curves + +.TP 8 +.B \-no-curves +Whether to draw the arc based Truchet pattern. Default is True (curves). + +.TP 8 +.B \-angles + +.TP 8 +.B \-no-angles +Whether or not to draw the line based Truchet pattern. Default is True (angles) + +.TP 8 +.B \-scroll +Use the scroll mode. Default is False. + +.TP 8 +.B \-scroll-overlap +The amount to scroll from one side to another. Default is 400. + +.TP 8 +.B \-anim-delay +The time to pause between each animation step. Default is 100. + +.TP 8 +.B \-anim-step-size +The amount of steps to skip between each animation step. Default is 3. + + +.TP 8 +.B \-fps +Display the current frame rate and CPU load. +.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 1998 by Adrian Likins. + +Permission to use, copy, modify, and distribute this software and its +documentation for any purpose and without fee is hereby granted, +provided that the above copyright notice appear in all copies and that +both that copyright notice and this permission notice appear in +supporting documentation. +.SH AUTHOR +Adrian Likins, 1998. + diff --git a/hacks/twang.c b/hacks/twang.c new file mode 100644 index 00000000..7a606b12 --- /dev/null +++ b/hacks/twang.c @@ -0,0 +1,791 @@ +/* twang, twist around screen bits, v1.3 + * by Dan Bornstein, danfuzz@milk.com + * Copyright (c) 2003 Dan Bornstein. All rights reserved. + * + * 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. + * + * See the included man page for more details. + */ + +#include +#include "screenhack.h" + +#ifdef HAVE_XSHM_EXTENSION +#include "xshm.h" +#endif + +#define FLOAT double + +/* random float in the range (-1..1) */ +#define RAND_FLOAT_PM1 \ + (((FLOAT) ((random() >> 8) & 0xffff)) / ((FLOAT) 0x10000) * 2 - 1) + +/* random float in the range (0..1) */ +#define RAND_FLOAT_01 \ + (((FLOAT) ((random() >> 8) & 0xffff)) / ((FLOAT) 0x10000)) + + +typedef struct +{ + int x; /* x coordinate of the center of the tile */ + int y; /* y coordinate of the center of the tile */ + FLOAT angle; /* angle of the tile (-pi..pi) */ + FLOAT zoom; /* log of the zoom of the tile (-1..1) */ + FLOAT vAngle; /* angular velocity (-pi/4..pi/4) */ + FLOAT vZoom; /* zoomular velocity (-0.25..0.25) */ +} +Tile; + + +struct state { + Display *dpy; + Window window; + + int delay; /* delay (usec) between iterations */ + int duration; /* time (sec) before loading new image */ + int maxColumns; /* the maximum number of columns of tiles */ + int maxRows; /* the maximum number of rows of tiles */ + int tileSize; /* the size (width and height) of a tile */ + int borderWidth; /* the width of the border around each tile */ + FLOAT eventChance; /* the chance, per iteration, of an interesting event happening */ + FLOAT friction; /* friction: the fraction (0..1) by which velocity decreased per iteration */ + FLOAT springiness; /* springiness: the fraction (0..1) of the orientation that turns into velocity towards the center */ + FLOAT transference; /* transference: the fraction (0..1) of the orientations of orthogonal neighbors that turns into velocity (in the same direction as the orientation) */ + int windowWidth; /* width and height of the window */ + int windowHeight; + Screen *screen; /* the screen to draw on */ + XImage *sourceImage; /* image source of stuff to draw */ + XImage *workImage; /* work area image, used when rendering */ + XImage *backgroundImage; /* image filled with background pixels */ + + GC backgroundGC; /* GC for the background color */ + GC foregroundGC; /* GC for the foreground color */ + GC borderGC; /* GC for the border color */ + unsigned long backgroundPixel; /* background color as a pixel value */ + unsigned long borderPixel; /* border color as a pixel value */ + + Tile *tiles; /* array of tiles (left->right, top->bottom, row major) */ + int rows; /* number of rows of tiles */ + int columns; /* number of columns of tiles */ + + Tile **sortedTiles; /* array of tile pointers, sorted by zoom */ + int tileCount; /* total number of tiles */ + + time_t start_time; + async_load_state *img_loader; + + Bool useShm; /* whether or not to use xshm */ +#ifdef HAVE_XSHM_EXTENSION + XShmSegmentInfo shmInfo; +#endif +}; + + +#define TILE_AT(col,row) (&st->tiles[(row) * st->columns + (col)]) + +#define MAX_VANGLE (M_PI / 4.0) +#define MAX_VZOOM 0.25 + +#define RAND_ANGLE (RAND_FLOAT_PM1 * M_PI) +#define RAND_ZOOM (RAND_FLOAT_PM1) +#define RAND_VANGLE (RAND_FLOAT_PM1 * MAX_VANGLE) +#define RAND_VZOOM (RAND_FLOAT_PM1 * MAX_VZOOM) + + + +/* + * overall setup stuff + */ + +/* grab the source image */ +static void +grabImage_start (struct state *st, XWindowAttributes *xwa) +{ + XFillRectangle (st->dpy, st->window, st->backgroundGC, 0, 0, + st->windowWidth, st->windowHeight); + st->backgroundImage = + XGetImage (st->dpy, st->window, 0, 0, st->windowWidth, st->windowHeight, + ~0L, ZPixmap); + + st->start_time = time ((time_t) 0); + st->img_loader = load_image_async_simple (0, xwa->screen, st->window, + st->window, 0, 0); +} + +static void +grabImage_done (struct state *st) +{ + XWindowAttributes xwa; + XGetWindowAttributes (st->dpy, st->window, &xwa); + + st->start_time = time ((time_t) 0); + if (st->sourceImage) XDestroyImage (st->sourceImage); + st->sourceImage = XGetImage (st->dpy, st->window, 0, 0, st->windowWidth, st->windowHeight, + ~0L, ZPixmap); + + if (st->workImage) XDestroyImage (st->workImage); + st->workImage = NULL; + +#ifdef HAVE_XSHM_EXTENSION + if (st->useShm) + { + st->workImage = create_xshm_image (st->dpy, xwa.visual, xwa.depth, + ZPixmap, 0, &st->shmInfo, + st->windowWidth, st->windowHeight); + if (!st->workImage) + { + st->useShm = False; + fprintf (stderr, "create_xshm_image failed\n"); + } + } + + if (st->workImage == NULL) +#endif /* HAVE_XSHM_EXTENSION */ + + /* just use XSubImage to acquire the right visual, depth, etc; + * easier than the other alternatives */ + st->workImage = XSubImage (st->sourceImage, 0, 0, st->windowWidth, st->windowHeight); +} + +/* set up the system */ +static void setup (struct state *st) +{ + XWindowAttributes xgwa; + XGCValues gcv; + + XGetWindowAttributes (st->dpy, st->window, &xgwa); + + st->screen = xgwa.screen; + st->windowWidth = xgwa.width; + st->windowHeight = xgwa.height; + + gcv.line_width = st->borderWidth; + gcv.foreground = get_pixel_resource (st->dpy, xgwa.colormap, + "borderColor", "BorderColor"); + st->borderPixel = gcv.foreground; + st->borderGC = XCreateGC (st->dpy, st->window, GCForeground | GCLineWidth, + &gcv); + + gcv.foreground = get_pixel_resource (st->dpy, xgwa.colormap, + "background", "Background"); + st->backgroundPixel = gcv.foreground; + st->backgroundGC = XCreateGC (st->dpy, st->window, GCForeground, &gcv); + + gcv.foreground = get_pixel_resource (st->dpy, xgwa.colormap, + "foreground", "Foreground"); + st->foregroundGC = XCreateGC (st->dpy, st->window, GCForeground, &gcv); + + grabImage_start (st, &xgwa); +} + + + +/* + * the simulation + */ + +/* event: randomize all the angular velocities */ +static void randomizeAllAngularVelocities (struct state *st) +{ + int c; + int r; + + for (r = 0; r < st->rows; r++) + { + for (c = 0; c < st->columns; c++) + { + TILE_AT (c, r)->vAngle = RAND_VANGLE; + } + } +} + +/* event: randomize all the zoomular velocities */ +static void randomizeAllZoomularVelocities (struct state *st) +{ + int c; + int r; + + for (r = 0; r < st->rows; r++) + { + for (c = 0; c < st->columns; c++) + { + TILE_AT (c, r)->vZoom = RAND_VZOOM; + } + } +} + +/* event: randomize all the velocities */ +static void randomizeAllVelocities (struct state *st) +{ + randomizeAllAngularVelocities (st); + randomizeAllZoomularVelocities (st); +} + +/* event: randomize all the angular orientations */ +static void randomizeAllAngularOrientations (struct state *st) +{ + int c; + int r; + + for (r = 0; r < st->rows; r++) + { + for (c = 0; c < st->columns; c++) + { + TILE_AT (c, r)->angle = RAND_ANGLE; + } + } +} + +/* event: randomize all the zoomular orientations */ +static void randomizeAllZoomularOrientations (struct state *st) +{ + int c; + int r; + + for (r = 0; r < st->rows; r++) + { + for (c = 0; c < st->columns; c++) + { + TILE_AT (c, r)->zoom = RAND_ZOOM; + } + } +} + +/* event: randomize all the orientations */ +static void randomizeAllOrientations (struct state *st) +{ + randomizeAllAngularOrientations (st); + randomizeAllZoomularOrientations (st); +} + +/* event: randomize everything */ +static void randomizeEverything (struct state *st) +{ + randomizeAllVelocities (st); + randomizeAllOrientations (st); +} + +/* event: pick one tile and randomize all its stats */ +static void randomizeOneTile (struct state *st) +{ + int c = RAND_FLOAT_01 * st->columns; + int r = RAND_FLOAT_01 * st->rows; + + Tile *t = TILE_AT (c, r); + t->angle = RAND_ANGLE; + t->zoom = RAND_ZOOM; + t->vAngle = RAND_VANGLE; + t->vZoom = RAND_VZOOM; +} + +/* event: pick one row and randomize everything about each of its tiles */ +static void randomizeOneRow (struct state *st) +{ + int c; + int r = RAND_FLOAT_01 * st->rows; + + for (c = 0; c < st->columns; c++) + { + Tile *t = TILE_AT (c, r); + t->angle = RAND_ANGLE; + t->zoom = RAND_ZOOM; + t->vAngle = RAND_VANGLE; + t->vZoom = RAND_VZOOM; + } +} + +/* event: pick one column and randomize everything about each of its tiles */ +static void randomizeOneColumn (struct state *st) +{ + int c = RAND_FLOAT_01 * st->columns; + int r; + + for (r = 0; r < st->rows; r++) + { + Tile *t = TILE_AT (c, r); + t->angle = RAND_ANGLE; + t->zoom = RAND_ZOOM; + t->vAngle = RAND_VANGLE; + t->vZoom = RAND_VZOOM; + } +} + +/* do model event processing */ +static void modelEvents (struct state *st) +{ + int which; + + if (RAND_FLOAT_01 > st->eventChance) + { + return; + } + + which = RAND_FLOAT_01 * 10; + + switch (which) + { + case 0: randomizeAllAngularVelocities (st); break; + case 1: randomizeAllZoomularVelocities (st); break; + case 2: randomizeAllVelocities (st); break; + case 3: randomizeAllAngularOrientations (st); break; + case 4: randomizeAllZoomularOrientations (st); break; + case 5: randomizeAllOrientations (st); break; + case 6: randomizeEverything (st); break; + case 7: randomizeOneTile (st); break; + case 8: randomizeOneColumn (st); break; + case 9: randomizeOneRow (st); break; + } +} + +/* update the model for one iteration */ +static void updateModel (struct state *st) +{ + int r; + int c; + + /* for each tile, decrease its velocities according to the friction, + * and increase them based on its current orientation and the orientations + * of its orthogonal neighbors */ + for (r = 0; r < st->rows; r++) + { + for (c = 0; c < st->columns; c++) + { + Tile *t = TILE_AT (c, r); + FLOAT a = t->angle; + FLOAT z = t->zoom; + FLOAT va = t->vAngle; + FLOAT vz = t->vZoom; + + va -= t->angle * st->springiness; + vz -= t->zoom * st->springiness; + + if (c > 0) + { + Tile *t2 = TILE_AT (c - 1, r); + va += (t2->angle - a) * st->transference; + vz += (t2->zoom - z) * st->transference; + } + + if (c < (st->columns - 1)) + { + Tile *t2 = TILE_AT (c + 1, r); + va += (t2->angle - a) * st->transference; + vz += (t2->zoom - z) * st->transference; + } + + if (r > 0) + { + Tile *t2 = TILE_AT (c, r - 1); + va += (t2->angle - a) * st->transference; + vz += (t2->zoom - z) * st->transference; + } + + if (r < (st->rows - 1)) + { + Tile *t2 = TILE_AT (c, r + 1); + va += (t2->angle - a) * st->transference; + vz += (t2->zoom - z) * st->transference; + } + + va *= (1.0 - st->friction); + vz *= (1.0 - st->friction); + + if (va > MAX_VANGLE) va = MAX_VANGLE; + else if (va < -MAX_VANGLE) va = -MAX_VANGLE; + t->vAngle = va; + + if (vz > MAX_VZOOM) vz = MAX_VZOOM; + else if (vz < -MAX_VZOOM) vz = -MAX_VZOOM; + t->vZoom = vz; + } + } + + /* for each tile, update its orientation based on its velocities */ + for (r = 0; r < st->rows; r++) + { + for (c = 0; c < st->columns; c++) + { + Tile *t = TILE_AT (c, r); + FLOAT a = t->angle + t->vAngle; + FLOAT z = t->zoom + t->vZoom; + + if (a > M_PI) a = M_PI; + else if (a < -M_PI) a = -M_PI; + t->angle = a; + + if (z > 1.0) z = 1.0; + else if (z < -1.0) z = -1.0; + t->zoom = z; + } + } +} + +/* the comparator to us to sort the tiles (used immediately below); it'd + * sure be nice if C allowed inner functions (or jeebus-forbid *real + * closures*!) */ +static int sortTilesComparator (const void *v1, const void *v2) +{ + Tile *t1 = *(Tile **) v1; + Tile *t2 = *(Tile **) v2; + + if (t1->zoom < t2->zoom) + { + return -1; + } + + if (t1->zoom > t2->zoom) + { + return 1; + } + + return 0; +} + +/* sort the tiles in sortedTiles by zoom */ +static void sortTiles (struct state *st) +{ + qsort (st->sortedTiles, st->tileCount, sizeof (Tile *), sortTilesComparator); +} + +/* render the given tile */ +static void renderTile (struct state *st, Tile *t) +{ + /* note: the zoom as stored per tile is log-based (centered on 0, with + * 0 being no zoom, but the range for zoom-as-drawn is 0.4..2.5, + * hence the alteration of t->zoom, below */ + + int x, y; + + int tx = t->x; + int ty = t->y; + + FLOAT zoom = pow (2.5, t->zoom); + FLOAT ang = -t->angle; + FLOAT sinAng = sin (ang); + FLOAT cosAng = cos (ang); + + FLOAT innerBorder = (st->tileSize - st->borderWidth) / 2.0; + FLOAT outerBorder = innerBorder + st->borderWidth; + + int maxCoord = outerBorder * zoom * (fabs (sinAng) + fabs (cosAng)); + int minX = tx - maxCoord; + int maxX = tx + maxCoord; + int minY = ty - maxCoord; + int maxY = ty + maxCoord; + + FLOAT prey; + + if (minX < 0) minX = 0; + if (maxX > st->windowWidth) maxX = st->windowWidth; + if (minY < 0) minY = 0; + if (maxY > st->windowHeight) maxY = st->windowHeight; + + sinAng /= zoom; + cosAng /= zoom; + + for (y = minY, prey = y - ty; y < maxY; y++, prey++) + { + FLOAT prex = minX - tx; + FLOAT srcx = prex * cosAng - prey * sinAng; + FLOAT srcy = prex * sinAng + prey * cosAng; + + for (x = minX; + x < maxX; + x++, srcx += cosAng, srcy += sinAng) + { + if ((srcx < -innerBorder) || (srcx >= innerBorder) || + (srcy < -innerBorder) || (srcy >= innerBorder)) + { + if ((srcx < -outerBorder) || (srcx >= outerBorder) || + (srcy < -outerBorder) || (srcy >= outerBorder)) + { + continue; + } + XPutPixel (st->workImage, x, y, st->borderPixel); + } + else + { + unsigned long p = + XGetPixel (st->sourceImage, srcx + tx, srcy + ty); + XPutPixel (st->workImage, x, y, p); + } + } + } +} + +/* render and display the current model */ +static void renderFrame (struct state *st) +{ + int n; + + memcpy (st->workImage->data, st->backgroundImage->data, + st->workImage->bytes_per_line * st->workImage->height); + + sortTiles (st); + + for (n = 0; n < st->tileCount; n++) + { + renderTile (st, st->sortedTiles[n]); + } + +#ifdef HAVE_XSHM_EXTENSION + if (st->useShm) + XShmPutImage (st->dpy, st->window, st->backgroundGC, st->workImage, 0, 0, 0, 0, + st->windowWidth, st->windowHeight, False); + else +#endif /* HAVE_XSHM_EXTENSION */ + XPutImage (st->dpy, st->window, st->backgroundGC, st->workImage, + 0, 0, 0, 0, st->windowWidth, st->windowHeight); +} + +/* set up the model */ +static void setupModel (struct state *st) +{ + int c; + int r; + + int leftX; /* x of the center of the top-left tile */ + int topY; /* y of the center of the top-left tile */ + + if (st->tileSize > (st->windowWidth / 2)) + { + st->tileSize = st->windowWidth / 2; + } + + if (st->tileSize > (st->windowHeight / 2)) + { + st->tileSize = st->windowHeight / 2; + } + + st->columns = st->tileSize ? st->windowWidth / st->tileSize : 0; + st->rows = st->tileSize ? st->windowHeight / st->tileSize : 0; + + if ((st->maxColumns != 0) && (st->columns > st->maxColumns)) + { + st->columns = st->maxColumns; + } + + if ((st->maxRows != 0) && (st->rows > st->maxRows)) + { + st->rows = st->maxRows; + } + + st->tileCount = st->rows * st->columns; + + leftX = (st->windowWidth - (st->columns * st->tileSize) + st->tileSize) / 2; + topY = (st->windowHeight - (st->rows * st->tileSize) + st->tileSize) / 2; + + st->tiles = calloc (st->tileCount, sizeof (Tile)); + st->sortedTiles = calloc (st->tileCount, sizeof (Tile *)); + + for (r = 0; r < st->rows; r++) + { + for (c = 0; c < st->columns; c++) + { + Tile *t = TILE_AT (c, r); + t->x = leftX + c * st->tileSize; + t->y = topY + r * st->tileSize; + st->sortedTiles[c + r * st->columns] = t; + } + } + + randomizeEverything (st); +} + +/* do one iteration */ + +static unsigned long +twang_draw (Display *dpy, Window window, void *closure) +{ + struct state *st = (struct state *) closure; + + if (st->img_loader) /* still loading */ + { + st->img_loader = load_image_async_simple (st->img_loader, 0, 0, 0, 0, 0); + if (! st->img_loader) { /* just finished */ + grabImage_done (st); + } + return st->delay; + } + + if (!st->img_loader && + st->start_time + st->duration < time ((time_t) 0)) { + XWindowAttributes xgwa; + XGetWindowAttributes (st->dpy, st->window, &xgwa); + grabImage_start (st, &xgwa); + return st->delay; + } + + modelEvents (st); + updateModel (st); + renderFrame (st); + return st->delay; +} + + +static void +twang_reshape (Display *dpy, Window window, void *closure, + unsigned int w, unsigned int h) +{ +} + +static Bool +twang_event (Display *dpy, Window window, void *closure, XEvent *event) +{ + return False; +} + +static void +twang_free (Display *dpy, Window window, void *closure) +{ + struct state *st = (struct state *) closure; + free (st); +} + + + +/* main and options and stuff */ + +/* initialize the user-specifiable params */ +static void initParams (struct state *st) +{ + int problems = 0; + + st->borderWidth = get_integer_resource (st->dpy, "borderWidth", "Integer"); + if (st->borderWidth < 0) + { + fprintf (stderr, "error: border width must be at least 0\n"); + problems = 1; + } + + st->delay = get_integer_resource (st->dpy, "delay", "Delay"); + if (st->delay < 0) + { + fprintf (stderr, "error: delay must be at least 0\n"); + problems = 1; + } + + st->duration = get_integer_resource (st->dpy, "duration", "Seconds"); + if (st->duration < 1) st->duration = 1; + + st->eventChance = get_float_resource (st->dpy, "eventChance", "Double"); + if ((st->eventChance < 0.0) || (st->eventChance > 1.0)) + { + fprintf (stderr, "error: eventChance must be in the range 0..1\n"); + problems = 1; + } + + st->friction = get_float_resource (st->dpy, "friction", "Double"); + if ((st->friction < 0.0) || (st->friction > 1.0)) + { + fprintf (stderr, "error: friction must be in the range 0..1\n"); + problems = 1; + } + + st->maxColumns = get_integer_resource (st->dpy, "maxColumns", "Integer"); + if (st->maxColumns < 0) + { + fprintf (stderr, "error: max columns must be at least 0\n"); + problems = 1; + } + + st->maxRows = get_integer_resource (st->dpy, "maxRows", "Integer"); + if (st->maxRows < 0) + { + fprintf (stderr, "error: max rows must be at least 0\n"); + problems = 1; + } + + st->springiness = get_float_resource (st->dpy, "springiness", "Double"); + if ((st->springiness < 0.0) || (st->springiness > 1.0)) + { + fprintf (stderr, "error: springiness must be in the range 0..1\n"); + problems = 1; + } + + st->tileSize = get_integer_resource (st->dpy, "tileSize", "Integer"); + if (st->tileSize < 1) + { + fprintf (stderr, "error: tile size must be at least 1\n"); + problems = 1; + } + + st->transference = get_float_resource (st->dpy, "transference", "Double"); + if ((st->transference < 0.0) || (st->transference > 1.0)) + { + fprintf (stderr, "error: transference must be in the range 0..1\n"); + problems = 1; + } + +#ifdef HAVE_XSHM_EXTENSION + st->useShm = get_boolean_resource (st->dpy, "useSHM", "Boolean"); +#endif + + if (problems) + { + exit (1); + } +} + +static void * +twang_init (Display *dpy, Window win) +{ + struct state *st = (struct state *) calloc (1, sizeof(*st)); + st->dpy = dpy; + st->window = win; + + initParams (st); + setup (st); + setupModel (st); + + return st; +} + + +static const char *twang_defaults [] = { + ".background: black", + ".foreground: white", + "*borderColor: blue", + "*borderWidth: 3", + "*delay: 10000", + "*duration: 120", + "*eventChance: 0.01", + "*friction: 0.05", + "*maxColumns: 0", + "*maxRows: 0", + "*springiness: 0.1", + "*tileSize: 120", + "*transference: 0.025", +#ifdef HAVE_XSHM_EXTENSION + "*useSHM: True", +#else + "*useSHM: False", +#endif + 0 +}; + +static XrmOptionDescRec twang_options [] = { + { "-border-color", ".borderColor", XrmoptionSepArg, 0 }, + { "-border-width", ".borderWidth", XrmoptionSepArg, 0 }, + { "-delay", ".delay", XrmoptionSepArg, 0 }, + { "-duration", ".duration", XrmoptionSepArg, 0 }, + { "-event-chance", ".eventChance", XrmoptionSepArg, 0 }, + { "-friction", ".friction", XrmoptionSepArg, 0 }, + { "-max-columns", ".maxColumns", XrmoptionSepArg, 0 }, + { "-max-rows", ".maxRows", XrmoptionSepArg, 0 }, + { "-springiness", ".springiness", XrmoptionSepArg, 0 }, + { "-tile-size", ".tileSize", XrmoptionSepArg, 0 }, + { "-transference", ".transference", XrmoptionSepArg, 0 }, + { "-shm", ".useSHM", XrmoptionNoArg, "True" }, + { "-no-shm", ".useSHM", XrmoptionNoArg, "False" }, + { 0, 0, 0, 0 } +}; + + +XSCREENSAVER_MODULE ("Twang", twang) diff --git a/hacks/twang.man b/hacks/twang.man new file mode 100644 index 00000000..3e6b06a5 --- /dev/null +++ b/hacks/twang.man @@ -0,0 +1,132 @@ +.TH XScreenSaver 1 "07-Feb-2002" "X Version 11" +.SH NAME +twang - pluck pieces of the screen +.SH SYNOPSIS +.B twang +[\-display \fIhost:display.screen\fP] +[\-foreground \fIcolor\fP] +[\-background \fIcolor\fP] +[\-window] +[\-root] +[\-mono] +[\-install] +[\-visual \fIvisual\fP] +[\-shm] +[\-no-shm] +[\-delay \fIusecs\fP] +[\-duration \fIsecs\fP] +[\-border-color \fIcolor\fP] +[\-border-width \fIinteger\fP] +[\-event-chance \fIfraction\fP] +[\-friction \fIfraction\fP] +[\-springiness \fIfraction\fP] +[\-tile-size \fIinteger\fP] +[\-transference \fIfraction\fP] +[\-fps] +.SH DESCRIPTION +\fITwang\fP divides the screen into equal-sized tiles, and then plucks +them in various ways. Tiles are affected by their neighbors, so waves +of motion flow through the grid. This manpage +describes v1.3 of the program. +.SH OPTIONS +.I twang +accepts the following options: +.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 \-mono +If on a color display, pretend we're on a monochrome display. +.TP 8 +.B \-install +Install a private colormap for the window. +.TP 8 +.B \-visual \fIvisual\fP +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 \-shm +.TP 8 +.B \-no-shm +Use the shared memory extension (or not, respectively), if available. +This may speed things +up a bit, but probably won't make that much difference. If available, +defaults to true, resource \fIuseSHM\fP. +.TP 8 +.B \-delay \fImicroseconds\fP +The interframe delay, in microseconds. Defaults to 10000, resource +\fIdelay\fP. +.TP 8 +.B \-duration \fIseconds\fP +How long to run before loading a new image. Default 120 seconds. +.TP 8 +.B \-border-color \fIcolor\fP +Color of the border surrounding each tile. Defaults to blue, resource +\fIborderColor\fP. +.TP 8 +.B \-border-width \fIinteger\fP +Width of the border surrounding each tile. Defaults to 3, resource +\fIborderWidth\fP. +.TP 8 +.B \-event-chance \fIfraction\fP +The chance, per iteration, for an event to occur (such as tweaking +the orientation of a tile), in the range 0..1. Defaults to 0.01, +resource \fIeventChance\fP. +.TP 8 +.B \-friction \fIfraction\fP +How much friction there is in the system, in the range 0..1. +This is the amount by which velocities are damped per iteration. +Defaults to 0.05, resource \fIfriction\fP. +.TP 8 +.B \-springiness \fIfraction\fP +How springy the tiles are, in the range 0..1. +This is the fraction of an orientation that gets turned into a velocity +towards the center (resting point). Defaults to 0.1, resource +\fIspringiness\fP. +.TP 8 +.B \-tile-size \fIinteger\fP +Size (width and height) of each tile, not including the outer edge +of the border. Defaults to 120, resource \fItileSize\fP. +.TP 8 +.B \-transference \fIfraction\fP +How much a tile's neighbors affect it, in the range 0..1. +This is the fraction of an orientation of a neighbor that gets turned +into a velocity in the same direction Defaults to 0.025, resource +\fItransference\fP. +.TP 8 +.B \-fps +Display the current frame rate and CPU load. +.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 X RESOURCES +There are resource equivalents for each option, noted above. +.SH BUGS +.I twang +should have more interesting events. +.TP 8 +Ways of speeding it up need to be investigated. It's kinda sluggish, +especially on hugeass displays. +.SH SEE ALSO +.BR xscreensaver (1) +.SH COPYRIGHT +Copyright \(co 2002 by Dan Bornstein. All rights reserved. + +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 +Dan Bornstein . diff --git a/hacks/vermiculate.c b/hacks/vermiculate.c new file mode 100644 index 00000000..d1ef5719 --- /dev/null +++ b/hacks/vermiculate.c @@ -0,0 +1,1219 @@ +/* + * @(#) vermiculate.c + * @(#) Copyright (C) 2001 Tyler Pierce (tyler@alumni.brown.edu) + * The full program, with documentation, is available at: + * http://freshmeat.net/projects/fdm + * + * 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. + */ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include +#include +#include "screenhack.h" + +#define degs 360 +#define degs2 (degs/2) +#define degs4 (degs/4) +#define degs8 (degs/8) +#define dtor 0.0174532925 /* pi / degs2; */ +#define thrmax 120 +#define tailmax (thrmax * 2 + 1) +#define tmodes '7' +#define ymax (st->hei - 1) +#define ymin 0 +#define xmax (st->wid - 1) +#define xmin 0 +#define rlmax 200 +#define SPEEDINC 10 +#define SPEEDMAX 1000 +#define wraparound(VAL,LOWER,UPPER) { \ + if (VAL >= UPPER) \ + VAL -= UPPER - LOWER; \ + else if (VAL < LOWER) \ + VAL += UPPER - LOWER; } +#define arrcpy(DEST,SRC) memcpy (DEST, SRC, sizeof(DEST)) + +typedef double real; +typedef unsigned char banktype[thrmax]; + +typedef struct linedata +{ + int deg, spiturn, turnco, turnsize; + unsigned char col; + Bool dead; + + char orichar; + real x, y; + int tmode, tsc, tslen, tclim, otslen, ctinc, reclen, recpos, circturn, prey, + slice; + int xrec[rlmax + 1], yrec[rlmax + 1]; + int turnseq[50]; + Bool filled, killwalls, vhfollow, + selfbounce, tailfollow, realbounce, little; +} +linedata; + +static const struct stringAndSpeed +{ + char *str; + int speed; +} +sampleStrings[] = +{ +/* { "]]]]]]]]7ces123400-9-8#c123456#s9998880004#ma3#car9ma6#c-#r1", 600} , + { "bmarrrr#c1234#lc5678#lyet]", 600} , */ + { "AEBMN222222223#CAR9CAD4CAOV", 150} , + { "mn333#c23#f1#]]]]]]]]]]]3bc9#r9#c78#f9#ma4#", 600} , + { "AEBMN22222#CAD4CAORc1#f2#c1#r6", 100} , +/* { "mn6666666#c1i#f1#y2#sy2#vyety1#ry13i#l", 40} , */ + { "aebmnrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrr#", 500} , +/* { "bg+++++++++++++++++++++++#mnrrrrrrrrrrrrrrrrrrrrrrr#y1#k", 500}, */ +/* { "BMN22222223#CAD4CAOVYAS", 150}, */ +/* { "aebmnrrrrrrrrrrrrrrrr#yaryakg--#", 100} , */ + { "mn6rrrrrrrrrrrrrrr#by1i#lcalc1#fnyav" , 200 } , + { "mn1rrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrr#by1i#lcalc1#fn", 2000 }, + { "baeMn333333333333333333333333#CerrYerCal", 800 }, + { "baeMn1111111111111111111111111111111111111111111111111111111111#Cer9YesYevYerCal", 1200 }, + { "baMn111111222222333333444444555555#Ct1#lCt2#lCt3#lCt4#lCt5#lCerrYerYet", 1400 }, + { "baMn111111222222333333444444555555#Ct1#lCt2#lCt3#lCt4#lCt5#lCerrYerYetYt1i#lYt1i#sYt1#v", 1400 } +}; + +struct state { + Display *dpy; + Window window; + + GC mygc; + Colormap mycmap; + XWindowAttributes xgwa; + XColor mycolors[tailmax]; + + int hei, wid, speed; + Bool erasing, cleared, autopal; + char *instring; + int max_ticks; + + real sinof[degs], cosof[degs], tanof[degs]; + unsigned char *point; + + linedata thread[thrmax]; + banktype bank; + int bnkt; + int boxw, boxh, curviness, gridden, ogd, bordcorn; + unsigned char bordcol, threads; + char ch, boolop; + + int reset_p; + int cyc; +}; + + + +static void +consume_instring(struct state *st); + +static Bool +wasakeypressed (struct state *st) +{ + if (*st->instring != 0) + return True; + else + return False; +} + +static char +readkey (struct state *st) +{ + char readkey_result; + if (*st->instring == 0) + { + readkey_result = '#'; + } + else + { + readkey_result = *st->instring; + st->instring++; + }; + return toupper (readkey_result); +} + +static unsigned int +random1 (unsigned int i) +{ + return (ya_random () % i); +} + +static unsigned long +waitabit (struct state *st) +{ + int result = 0; + st->cyc += st->threads; + while (st->cyc > st->speed) + { + result += 10000; + st->cyc -= st->speed; + } + return result; +} + +static void +clearscreen (struct state *st) +{ + XClearWindow (st->dpy, st->window); + memset (st->point, 0, st->wid * st->hei); +} + +static void +sp (struct state *st, int x, int y, int c) +{ + XSetForeground (st->dpy, st->mygc, st->mycolors[c].pixel); + XDrawPoint (st->dpy, st->window, st->mygc, x, y); + st->point[(st->wid * y) + x] = c; +} + +static int +gp (struct state *st, int x, int y) +{ + return st->point[(st->wid * y) + x]; +} + +static void +redraw (struct state *st, int x, int y, int width, int height) +{ + int xc, yc; + for (xc = x; xc <= x + width - 1; xc++) + for (yc = y; yc <= y + height - 1; yc++) + if (st->point[st->wid * yc + xc] != 0) + sp (st, xc, yc, st->point[st->wid * yc + xc]); +} + +static void +palupdate (struct state *st, Bool forceUpdate) +{ + if (forceUpdate || *st->instring == 0) + { + redraw (st, xmin, ymin, st->wid, st->hei); + } +} + +static void +randpal (struct state *st) +{ + int ncolors = tailmax - 1; + make_random_colormap (st->dpy, + st->xgwa.visual, + st->mycmap, &st->mycolors[1], &ncolors, True, True, 0, True); + if (ncolors < tailmax - 1) + { + int c; + for (c = 1; c < tailmax; c++) + st->mycolors[c].pixel = WhitePixel (st->dpy, DefaultScreen (st->dpy)); + } +} + +static void +gridupdate (struct state *st, Bool interruptible) +{ + int x, y; + if (st->gridden > 0) + for (x = 0; x <= xmax && !(wasakeypressed (st) && interruptible); x += st->boxw) + for (y = 0; y <= ymax; y += st->boxh) + { + if (random1 (15) < st->gridden) + { +#define lesser(A,B) ( ((A)<(B)) ? (A) : (B) ) + int max = lesser (x + st->boxw, xmax); + int xc; + for (xc = x; xc <= max; xc++) + sp (st, xc, y, 1); + } + if (random1 (15) < st->gridden) + { + int max = lesser (y + st->boxh, ymax); + int yc; + for (yc = y; yc <= max; yc++) + sp (st, x, yc, 1); + } + } +} + +static void +bordupdate (struct state *st) +{ + int xbord, ybord; + + if (st->bordcorn == 0 || st->bordcorn == 1) + ybord = ymin; + else + ybord = ymax; + if (st->bordcorn == 0 || st->bordcorn == 3) + xbord = xmin; + else + xbord = xmax; + { + int x, y; + for (x = xmin; x <= xmax; x++) + sp (st, x, ybord, st->bordcol); + for (y = ymin; y <= ymax; y++) + sp (st, xbord, y, st->bordcol); + } +} + +static Bool +inbank (struct state *st, unsigned char thr) +{ + int c; + if (st->bnkt > 0) + for (c = 1; c <= st->bnkt; c++) + if (st->bank[c - 1] == thr) + return True; + return False; +} + +static void +pickbank (struct state *st) +{ + unsigned char thr = 1; + st->bnkt = 0; + st->ch = '\0'; + do + { + while (inbank (st, thr)) + thr = thr % st->threads + 1; + + palupdate (st, False); + st->ch = readkey (st); + palupdate (st, False); + switch (st->ch) + { + case '+': + case '-': + do + { + if (st->ch == '+') + thr++; + else + thr--; + wraparound (thr, 1, st->threads + 1); + } + while (inbank (st, thr)); + break; + case ' ': + st->bank[++st->bnkt - 1] = thr; + break; + case '1': case '2': case '3': + case '4': case '5': case '6': + case '7': case '8': case '9': + + st->bank[++st->bnkt - 1] = st->ch - '0'; + if (st->bank[st->bnkt - 1] > st->threads) + st->bnkt--; + break; + case 'I': + { + banktype tbank; + int tbankt = 0; + int c; + for (c = 1; c <= st->threads; c++) + if (!inbank (st, c)) + tbank[++tbankt - 1] = c; + st->bnkt = tbankt; + arrcpy (st->bank, tbank); + } + break; + case 'T': + st->ch = readkey (st); + switch (st->ch) + { + case '1': case '2': case '3': + case '4': case '5': case '6': + case '7': case '8': case '9': + + { + int c; + for (c = 1; c <= st->threads; c++) + if (st->thread[c - 1].tmode == st->ch - '0') + st->bank[++st->bnkt - 1] = c; + } + break; + } + break; + case 'A': + for (st->bnkt = 1; st->bnkt <= st->threads; st->bnkt++) + st->bank[st->bnkt - 1] = st->bnkt; + st->bnkt = st->threads; + break; + case 'E': + for (st->bnkt = 1; st->bnkt <= thrmax; st->bnkt++) + st->bank[st->bnkt - 1] = st->bnkt; + st->bnkt = thrmax; + break; + } + } + while (!(st->bnkt >= st->threads || st->ch == 'N' || st->ch == '\15' || st->ch == '#')); + if (st->bnkt == 0 && st->ch != 'N') + { + st->bnkt = 1; + st->bank[0] = thr; + } + palupdate (st, False); +} + +static void +bankmod (char boolop, Bool * Bool_) +{ + switch (boolop) + { + case 'T': + *Bool_ = !*Bool_; + break; + case 'Y': + *Bool_ = True; + break; + case 'N': + *Bool_ = False; + break; + } +} + +static void +newonscreen (struct state *st, unsigned char thr) +{ + linedata *LP = &st->thread[thr - 1]; + LP->filled = False; + LP->dead = False; + LP->reclen = (LP->little) ? + random1 (10) + 5 : random1 (rlmax - 30) + 30; + LP->deg = random1 (degs); + LP->y = random1 (st->hei); + LP->x = random1 (st->wid); + LP->recpos = 0; + LP->turnco = 2; + LP->turnsize = random1 (4) + 2; +} + +static void +firstinit (struct state *st, unsigned char thr) +{ + linedata *LP = &st->thread[thr - 1]; + LP->col = thr + 1; + LP->prey = 0; + LP->tmode = 1; + LP->slice = degs / 3; + LP->orichar = 'R'; + LP->spiturn = 5; + LP->selfbounce = False; + LP->realbounce = False; + LP->vhfollow = False; + LP->tailfollow = False; + LP->killwalls = False; + LP->little = False; + LP->ctinc = random1 (2) * 2 - 1; + LP->circturn = ((thr % 2) * 2 - 1) * ((thr - 1) % 7 + 1); + LP->tsc = 1; + LP->tslen = 6; + LP->turnseq[0] = 6; + LP->turnseq[1] = -6; + LP->turnseq[2] = 6; + LP->turnseq[3] = 6; + LP->turnseq[4] = -6; + LP->turnseq[5] = 6; + LP->tclim = (unsigned char) (((real) degs) / 2 / 12); +} + +static void +maininit (struct state *st) +{ + if (!st->instring) + { + int n = random1 (sizeof (sampleStrings) / sizeof (sampleStrings[0])); + st->instring = sampleStrings[n].str; + st->speed = sampleStrings[n].speed; + } + if (st->speed == 0) + { + st->speed = 200; + } + st->boxh = 10; + st->boxw = 10; + st->gridden = 0; + st->bordcorn = 0; + st->threads = 4; + st->curviness = 30; + st->bordcol = 1; + st->ogd = 8; + st->ch = '\0'; + st->erasing = True; + { + unsigned char thr; + for (thr = 1; thr <= thrmax; thr++) + { + firstinit (st, thr); + newonscreen (st, thr); + } + } + { + int d; + for (d = degs - 1; d >= 0; d--) + { + st->sinof[d] = sin (d * dtor); + st->cosof[d] = cos (d * dtor); + if (d % degs4 == 0) + st->tanof[d] = st->tanof[d + 1]; + else + st->tanof[d] = tan (d * dtor); + } + } + randpal (st); +} + +static Bool +move (struct state *st, unsigned char thr) +{ + linedata *LP = &st->thread[thr - 1]; + if (LP->dead) + return (False); + if (LP->prey == 0) + switch (LP->tmode) + { + case 1: + LP->deg += random1 (2 * LP->turnsize + 1) - LP->turnsize; + break; + case 2: + if (LP->slice == degs || LP->slice == degs2 || LP->slice == degs4) + { + if (LP->orichar == 'D') + { + if (LP->deg % degs4 != degs8) + LP->deg = degs4 * random1 (4) + degs8; + } + else if (LP->orichar == 'V') + if (LP->deg % degs4 != 0) + LP->deg = degs4 * random1 (4); + } + if (random1 (100) == 0) + { + if (LP->slice == 0) + LP->deg = LP->deg - degs4 + random1 (degs2); + else + LP->deg += (random1 (2) * 2 - 1) * LP->slice; + } + break; + case 3: + LP->deg += LP->circturn; + break; + case 4: + if (abs (LP->spiturn) > 11) + LP->spiturn = 5; + else + LP->deg += LP->spiturn; + if (random1 (15 - abs (LP->spiturn)) == 0) + { + LP->spiturn += LP->ctinc; + if (abs (LP->spiturn) > 10) + LP->ctinc *= -1; + } + break; + case 5: + LP->turnco = abs (LP->turnco) - 1; + if (LP->turnco == 0) + { + LP->turnco = st->curviness + random1 (10); + LP->circturn *= -1; + } + LP->deg += LP->circturn; + break; + case 6: + if (abs (LP->turnco) == 1) + LP->turnco *= -1 * (random1 (degs2 / abs (LP->circturn)) + 5); + else if (LP->turnco == 0) + LP->turnco = 2; + else if (LP->turnco > 0) + { + LP->turnco--; + LP->deg += LP->circturn; + } + else + LP->turnco++; + break; + case 7: + LP->turnco++; + if (LP->turnco > LP->tclim) + { + LP->turnco = 1; + LP->tsc = (LP->tsc % LP->tslen) + 1; + } + LP->deg += LP->turnseq[LP->tsc - 1]; + break; + } + else + { + int desdeg; + real dy, dx; + if (LP->tailfollow || LP->prey == thr) + { + dx = st->thread[LP->prey - 1].xrec[st->thread[LP->prey - 1].recpos] - LP->x; + dy = st->thread[LP->prey - 1].yrec[st->thread[LP->prey - 1].recpos] - LP->y; + } + else + { + dx = st->thread[LP->prey - 1].x - LP->x; + dy = st->thread[LP->prey - 1].y - LP->y; + } + desdeg = + (LP->vhfollow) ? + ((fabs (dx) > fabs (dy)) ? + ((dx > 0) ? + 0 * degs4 + : + 2 * degs4) + : + ((dy > 0) ? + 1 * degs4 + : + 3 * degs4)) + : + ((dx > 0) ? + ((dy > 0) ? + 1 * degs8 : 7 * degs8) : ((dy > 0) ? 3 * degs8 : 5 * degs8)); + if (desdeg - desdeg % degs4 != LP->deg - LP->deg % degs4 + || LP->vhfollow) + { + if (!LP->vhfollow) + { + /* Using atan2 here doesn't seem to slow things down: */ + desdeg = atan2 (dy, dx) / dtor; + wraparound (desdeg, 0, degs); + } + if (abs (desdeg - LP->deg) <= abs (LP->circturn)) + LP->deg = desdeg; + else + LP->deg += + (desdeg > LP->deg) ? + ((desdeg - LP->deg > degs2) ? + -abs (LP->circturn) : abs (LP->circturn)) + : ((LP->deg - desdeg > degs2) ? + abs (LP->circturn) : -abs (LP->circturn)); + } + else + LP->deg += + (st->tanof[LP->deg] > + dy / dx) ? -abs (LP->circturn) : abs (LP->circturn); + } + + wraparound (LP->deg, 0, degs); + { + unsigned char oldcol; + real oldy = LP->y, oldx = LP->x; + LP->x += st->cosof[LP->deg]; + wraparound (LP->x, xmin, xmax + 1); + LP->y += st->sinof[LP->deg]; + wraparound (LP->y, ymin, ymax + 1); +#define xi ((int) LP->x) +#define yi ((int) LP->y) + + oldcol = gp (st, xi, yi); + if (oldcol != 0) + { + Bool vertwall = False, horiwall = False; + if (oldcol == 1 && ((LP->killwalls && st->gridden > 0) || LP->realbounce)) + { + vertwall = (gp (st, xi, (int) oldy) == 1); + horiwall = (gp (st, (int) oldx, yi) == 1); + } + if (oldcol == 1 && LP->realbounce && (vertwall || horiwall)) + { + if (vertwall) + LP->deg = -LP->deg + degs2; + else + LP->deg = -LP->deg; + } + else + { + if ((oldcol != LP->col && LP->realbounce) + || (oldcol == LP->col && LP->selfbounce)) + LP->deg += degs4 * (random1 (2) * 2 - 1); + else if (oldcol != LP->col) + LP->deg += degs2; + } + if (LP->killwalls && st->gridden > 0 && oldcol == 1) + { + if (vertwall && xi + 1 <= xmax) + { + int yy; + for (yy = yi - yi % st->boxh; + yy <= yi - yi % st->boxh + st->boxh && yy <= ymax; yy++) + if (gp (st, xi + 1, yy) != 1 || yy == ymax) + sp (st, xi, yy, 0); + } + if (horiwall && yi + 1 <= ymax) + { + int xx; + for (xx = xi - xi % st->boxw; + xx <= xi - xi % st->boxw + st->boxw && xx <= xmax; xx++) + if (gp (st, xx, yi + 1) != 1 || xx == xmax) + sp (st, xx, yi, 0); + } + } + if (oldcol != LP->col || LP->selfbounce) + { + LP->x = oldx; + LP->y = oldy; + } + wraparound (LP->deg, 0, degs); + } + } + + sp (st, xi, yi, LP->col); + if (LP->filled) + { + if (st->erasing) + sp (st, LP->xrec[LP->recpos], LP->yrec[LP->recpos], 0); + else + sp (st, LP->xrec[LP->recpos], LP->yrec[LP->recpos], LP->col + thrmax); + } + LP->yrec[LP->recpos] = yi; + LP->xrec[LP->recpos] = xi; + if (LP->recpos == LP->reclen - 1) + LP->filled = True; + if (LP->filled && !st->erasing) + { + int co = LP->recpos; + LP->dead = True; + do + { + int nextco = co + 1; + wraparound (nextco, 0, LP->reclen); + if (LP->yrec[co] != LP->yrec[nextco] + || LP->xrec[co] != LP->xrec[nextco]) + LP->dead = False; + co = nextco; + } + while (!(!LP->dead || co == LP->recpos)); + } + LP->recpos++; + wraparound (LP->recpos, 0, LP->reclen); + return (!LP->dead); +} + +static unsigned long +vermiculate_draw (Display *dpy, Window window, void *closure) +{ + struct state *st = (struct state *) closure; + int had_instring = (st->instring != 0); + int tick = 0; + int this_delay = 0; + int loop = 0; + + + AGAIN: + if (st->reset_p) + { + st->reset_p = 0; + + clearscreen (st); + { + unsigned char thr; + for (thr = 1; thr <= st->threads; thr++) + newonscreen (st, thr); + } + if (st->autopal) + { + randpal (st); + palupdate (st, False); + } + bordupdate (st); + gridupdate (st, False); + } + + { + Bool alltrap = True; + unsigned char thr; + for (thr = 1; thr <= st->threads; thr++) + if (move (st, thr)) + alltrap = False; + if (alltrap) /* all threads are trapped */ + st->reset_p = True; + if (st->speed != SPEEDMAX) + this_delay = waitabit (st); + } + + if (tick++ > st->max_ticks && !had_instring) + { + tick = 0; + st->instring = 0; + maininit(st); + st->reset_p = True; + st->autopal = False; + } + + if (this_delay == 0 && loop++ < 1000) + goto AGAIN; + + return this_delay; +} + +static void * +vermiculate_init (Display *d, Window w) +{ + struct state *st = (struct state *) calloc (1, sizeof(*st)); + st->dpy = d; + st->window = w; + st->reset_p = 1; + st->instring = get_string_resource (st->dpy, "instring", "Instring"); + if (st->instring && !*st->instring) + st->instring = 0; + + st->max_ticks = get_integer_resource (st->dpy, "ticks", "Integer"); + { + int temp = get_integer_resource (st->dpy, "speed", "Speed"); + if (temp != 0) + st->speed = temp; + } + + st->mycolors[0].pixel = BlackPixel (st->dpy, DefaultScreen (st->dpy)); + + XSetWindowBackground (st->dpy, st->window, + BlackPixel (st->dpy, DefaultScreen (st->dpy))); + { + XGetWindowAttributes (st->dpy, st->window, &st->xgwa); + st->wid = st->xgwa.width; + st->hei = st->xgwa.height; + st->mycmap = st->xgwa.colormap; + } + { + XGCValues mygcv; + st->mygc = XCreateGC (st->dpy, st->window, 0, &mygcv); + } + + st->point = (unsigned char *) calloc (1, st->wid * st->hei); + maininit (st); + palupdate (st, True); + consume_instring(st); + return st; +} + + +static void +vermiculate_reshape (Display *dpy, Window window, void *closure, + unsigned int w, unsigned int h) +{ + struct state *st = (struct state *) closure; + st->wid = w; + st->hei = h; + free (st->point); + st->point = (unsigned char *) calloc (1, st->wid * st->hei); +} + +static Bool +vermiculate_event (Display *dpy, Window window, void *closure, XEvent *event) +{ + return False; +} + +static void +consume_instring(struct state *st) +{ + char boolop; + + while (wasakeypressed (st)) + { + st->ch = readkey (st); + switch (st->ch) + { + case 'M': + st->ch = readkey (st); + switch (st->ch) + { + case 'A': + case 'N': + { + unsigned char othreads = st->threads; + if (st->ch == 'N') + st->threads = 0; + do + { + st->ch = readkey (st); + switch (st->ch) + { + case '1': case '2': case '3': + case '4': case '5': case '6': + case '7': case '8': case '9': + st->thread[++st->threads - 1].tmode = st->ch - '0'; + break; + case 'R': + st->thread[++st->threads - 1].tmode = + random1 (tmodes - '0') + 1; + break; + } + } + while (!(st->ch == '\15' || st->ch == '#' + || st->threads == thrmax)); + if (st->threads == 0) + st->threads = othreads; + st->reset_p = 1; + } + break; + } + break; + case 'C': + pickbank (st); + if (st->bnkt > 0) + { + st->ch = readkey (st); + switch (st->ch) + { + case 'D': + st->ch = readkey (st); + switch (st->ch) + { + case '1': case '2': case '3': + case '4': case '5': case '6': + case '7': case '8': case '9': +/* Careful! The following macro needs to be at the beginning of any +block in which it's invoked, since it declares variables: */ +#define forallinbank(LDP) linedata *LDP; int bankc; \ + for (bankc = 1; \ + (LDP = &st->thread[st->bank[bankc - 1] - 1], \ + bankc <= st->bnkt); bankc++) + { + forallinbank (L) L->slice = degs / (st->ch - '0'); + } + break; + case 'M': + { + forallinbank (L) L->slice = 0; + } + break; + } + break; + case 'S': + { + forallinbank (L) + { + L->otslen = L->tslen; + L->tslen = 0; + } + } + do + { + char oldch = st->ch; + st->ch = readkey (st); + { + forallinbank (L) + { + switch (st->ch) + { + case '0': + case '1': case '2': case '3': + case '4': case '5': case '6': + case '7': case '8': case '9': + L->tslen++; + L->turnseq[L->tslen - 1] = st->ch - '0'; + if (oldch == '-') + L->turnseq[L->tslen - 1] *= -1; + if (bankc % 2 == 0) + L->turnseq[L->tslen - 1] *= -1; + break; + } + } + } + } + while (!(st->ch == '\15' || st->ch == '#' + || st->thread[st->bank[0] - 1].tslen == 50)); + { + forallinbank (L) + { + int seqSum = 0, c; + + if (L->tslen == 0) + L->tslen = L->otslen; + for (c = 1; c <= L->tslen; c++) + seqSum += L->turnseq[c - 1]; + if (seqSum == 0) + L->tclim = 1; + else + L->tclim = + (int) (((real) degs2) / abs (seqSum)); + L->tsc = random1 (L->tslen) + 1; + } + } + break; + case 'T': + { + st->ch = readkey (st); + { + forallinbank (L) + { + switch (st->ch) + { + case '1': case '2': case '3': + case '4': case '5': case '6': + case '7': case '8': case '9': + L->tmode = st->ch - '0'; + break; + case 'R': + L->tmode = random1 (tmodes - '0') + 1; + break; + } + } + } + } + break; + case 'O': + st->ch = readkey (st); + { + forallinbank (L) L->orichar = st->ch; + } + break; + case 'F': + { + banktype fbank; + arrcpy (fbank, st->bank); + { + int fbnkt = st->bnkt; + int bankc; + pickbank (st); + for (bankc = 1; bankc <= fbnkt; bankc++) + { + linedata *L = &st->thread[fbank[bankc - 1] - 1]; + if (st->ch == 'N') + L->prey = 0; + else + L->prey = st->bank[0 + (bankc - 1) % st->bnkt]; + } + } + } + break; + case 'L': + { + forallinbank (L) L->prey = st->bank[bankc % st->bnkt]; + } + break; + case 'R': + st->ch = readkey (st); + { + forallinbank (L) switch (st->ch) + { + case '1': case '2': case '3': + case '4': case '5': case '6': + case '7': case '8': case '9': + L->circturn = 10 - (st->ch - '0'); + break; + case 'R': + L->circturn = random1 (7) + 1; + break; + } + } + break; + } + } + break; + case 'T': + case 'Y': + case 'N': + boolop = st->ch; + pickbank (st); + if (st->bnkt > 0) + { + st->ch = readkey (st); + { + forallinbank (L) + { + switch (st->ch) + { + case 'S': + bankmod (boolop, &L->selfbounce); + break; + case 'V': + bankmod (boolop, &L->vhfollow); + break; + case 'R': + bankmod (boolop, &L->realbounce); + break; + case 'L': + bankmod (boolop, &L->little); + st->cleared = True; + break; + case 'T': + bankmod (boolop, &L->tailfollow); + break; + case 'K': + bankmod (boolop, &L->killwalls); + break; + } + } + } + } + break; + case 'R': + if (st->bordcol == 1) + { + st->bordcol = 0; + bordupdate (st); + st->bordcorn = (st->bordcorn + 1) % 4; + st->bordcol = 1; + bordupdate (st); + } + break; + case '1': case '2': case '3': + case '4': case '5': case '6': + case '7': case '8': case '9': + { + int c; + for (c = 1; c <= thrmax; c++) + st->thread[c - 1].tmode = st->ch - '0'; + } + break; + case '\40': + st->cleared = True; + break; + case 'E': + st->erasing = !st->erasing; + break; + case 'P': + randpal (st); + palupdate (st, True); + break; + case 'G': + { + char dimch = 'B'; + Bool gridchanged = True; + if (st->gridden == 0) + st->gridden = st->ogd; + do + { + int msize = 0; + if (gridchanged) + { + clearscreen (st); + gridupdate (st, True); + } + st->ch = readkey (st); + gridchanged = True; + switch (st->ch) + { + case '+': + msize = 1; + break; + case '-': + msize = -1; + break; + case ']': + if (st->gridden < 15) + st->gridden++; + break; + case '[': + if (st->gridden > 0) + st->gridden--; + break; + case 'O': + st->ogd = st->gridden; + st->gridden = 0; + break; + case 'S': + st->boxw = st->boxh; + case 'W': + case 'H': + case 'B': + dimch = st->ch; + break; + default: + gridchanged = False; + } + if (dimch == 'W' || dimch == 'B') + st->boxw += msize; + if (dimch == 'H' || dimch == 'B') + st->boxh += msize; + if (st->boxw == 0) + st->boxw = 1; + if (st->boxh == 0) + st->boxh = 1; + } + while (!(st->ch == '\15' || st->ch == '#' || st->ch == 'O')); + st->cleared = True; + } + break; + case 'A': + st->autopal = !st->autopal; + break; + case 'B': + st->bordcol = 1 - st->bordcol; + bordupdate (st); + break; + case '-': + st->speed -= SPEEDINC; + if (st->speed < 1) + st->speed = 1; + break; + case '+': + st->speed += SPEEDINC; + if (st->speed > SPEEDMAX) + st->speed = SPEEDMAX; + break; + case '/': + if (st->curviness > 5) + st->curviness -= 5; + break; + case '*': + if (st->curviness < 50) + st->curviness += 5; + break; + case ']': + if (st->threads < thrmax) + newonscreen (st, ++st->threads); + break; + case '[': + if (st->threads > 1) + { + linedata *L = &st->thread[st->threads - 1]; + int lastpos = (L->filled) ? L->reclen - 1 : L->recpos; + int c; + for (c = 0; c <= lastpos; c++) + sp (st, L->xrec[c], L->yrec[c], 0); + st->threads--; + } + break; + } + } +} + +static void +vermiculate_free (Display *dpy, Window window, void *closure) +{ + struct state *st = (struct state *) closure; + + if (st->point) + { + free(st->point); + } + free (st); +} + + +static const char *vermiculate_defaults[] = { + ".background: Black", + "*ticks: 20000", + "*fpsSolid: true", + "*speed: 0", + "*instring: ", + 0 +}; + +static XrmOptionDescRec vermiculate_options[] = { + {"-speed", ".speed", XrmoptionSepArg, 0}, + {"-instring", ".instring", XrmoptionSepArg, 0}, + {0, 0, 0, 0} +}; + + +XSCREENSAVER_MODULE ("Vermiculate", vermiculate) diff --git a/hacks/vermiculate.man b/hacks/vermiculate.man new file mode 100644 index 00000000..cbb9077a --- /dev/null +++ b/hacks/vermiculate.man @@ -0,0 +1,48 @@ +.TH XScreenSaver 1 "" "X Version 11" +.SH NAME +vermiculate - to move in a worm-like manner. +.SH SYNOPSIS +.B vermiculate +[\-display \fIhost:display.screen\fP] +[\-visual \fIvisual\fP] +[\-window] +[\-root] +[\-fps] +.SH DESCRIPTION +Draws squiggly worm-like paths. +.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 \-fps +Display the current frame rate and CPU load. +.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 2002 by Tyler Pierce. 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 +Tyler Pierce. diff --git a/hacks/vidwhacker b/hacks/vidwhacker new file mode 100755 index 00000000..80b16f6f --- /dev/null +++ b/hacks/vidwhacker @@ -0,0 +1,506 @@ +#!/usr/bin/perl -w +# vidwhacker, for xscreensaver. Copyright (c) 1998-2011 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. +# +# This program grabs a frame of video, then uses various pbm filters to +# munge the image in random nefarious ways, then uses xloadimage, xli, or xv +# to put it on the root window. This works out really nicely if you just +# feed some random TV station into it... +# +# Created: 14-Apr-01. + +require 5; +use diagnostics; +use strict; + +my $progname = $0; $progname =~ s@.*/@@g; +my $version = q{ $Revision: 1.32 $ }; $version =~ s/^[^0-9]+([0-9.]+).*$/$1/; + +my $verbose = 0; +my $use_stdin = 0; +my $use_stdout = 0; +my $video_p = 0; +my $file_p = 1; +my $delay = 5; +my $imagedir; + +my $screen_width = -1; + +my $displayer = "xscreensaver-getimage -root -file"; + +sub which($); + +# apparently some versions of netpbm call it "pamoil" instead of "pgmoil"... +# +my $pgmoil = (which("pamoil") ? "pamoil" : "pgmoil"); + + +# List of interesting PPM filter pipelines. +# In this list, the following magic words may be used: +# +# COLORS a randomly-selected pair of RGB foreground/background colors. +# FILE1 the (already-existing) input PPM file (ok to overwrite it). +# FILE2-FILE4 names of other tmp files you can use. +# +# These commands should read from FILE1, and write to stdout. +# All tmp files will be deleted afterward. +# +my @filters = ( + "ppmtopgm FILE1 | pgmedge | pgmtoppm COLORS | ppmnorm", + "ppmtopgm FILE1 | pgmenhance | pgmtoppm COLORS", + "ppmtopgm FILE1 | $pgmoil | pgmtoppm COLORS", + "ppmtopgm FILE1 | pgmbentley | pgmtoppm COLORS", + + "ppmrelief FILE1 | ppmtopgm | pgmedge | ppmrelief | ppmtopgm |" . + " pgmedge | pnminvert | pgmtoppm COLORS", + + "ppmspread 71 FILE1 > FILE2 ; " . + " pnmarith -add FILE1 FILE2 ; ", + + "pnmflip -lr < FILE1 > FILE2 ; " . + " pnmarith -multiply FILE1 FILE2 > FILE3 ; " . + " pnmflip -tb FILE3 | ppmnorm > FILE2 ; " . + " pnmarith -multiply FILE1 FILE2", + + "pnmflip -lr FILE1 > FILE2 ; " . + " pnmarith -difference FILE1 FILE2", + + "pnmflip -tb FILE1 > FILE2 ; " . + " pnmarith -difference FILE1 FILE2", + + "pnmflip -lr FILE1 | pnmflip -tb > FILE2 ; " . + " pnmarith -difference FILE1 FILE2", + + "ppmtopgm < FILE1 | pgmedge > FILE2 ; " . + " pnmarith -difference FILE1 FILE2 > FILE3 ; " . + " cp FILE3 FILE1 ; " . + " ppmtopgm < FILE1 | pgmedge > FILE2 ; " . + " pnmarith -difference FILE1 FILE2 > FILE3 ; " . + " ppmnorm < FILE1", + + "pnmflip -lr < FILE1 > FILE2 ; " . + " pnmarith -multiply FILE1 FILE2 | ppmrelief | ppmnorm | pnminvert", + + "pnmflip -lr FILE1 > FILE2 ; " . + " pnmarith -subtract FILE1 FILE2 | ppmrelief | ppmtopgm | pgmedge", + + "pgmcrater -number 20000 -width WIDTH -height HEIGHT FILE1 | " . + " pgmtoppm COLORS > FILE2 ; " . + " pnmarith -difference FILE1 FILE2 > FILE3 ; " . + " pnmflip -tb FILE3 | ppmnorm > FILE2 ; " . + " pnmarith -multiply FILE1 FILE2", + + "ppmshift 30 FILE1 | ppmtopgm | $pgmoil | pgmedge | " . + " pgmtoppm COLORS > FILE2 ; " . + " pnmarith -difference FILE1 FILE2", + + "ppmpat -madras WIDTH HEIGHT | pnmdepth 255 > FILE2 ; " . + " pnmarith -difference FILE1 FILE2", + + "ppmpat -tartan WIDTH HEIGHT | pnmdepth 255 > FILE2 ; " . + " pnmarith -difference FILE1 FILE2", + + "ppmpat -camo WIDTH HEIGHT | pnmdepth 255 | ppmshift 50 > FILE2 ; " . + " pnmarith -multiply FILE1 FILE2", + + "pgmnoise WIDTH HEIGHT | pgmedge | pgmtoppm COLORS > FILE2 ; " . + " pnmarith -difference FILE1 FILE2 | pnmdepth 255 | pnmsmooth", +); + + +# Any files on this list will be deleted at exit. +# +my @all_tmpfiles = (); + +sub exit_cleanup() { + print STDERR "$progname: delete tmp files\n" if ($verbose); + unlink @all_tmpfiles; +} + +sub signal_cleanup() { + my ($sig) = @_; + print STDERR "$progname: caught SIG$sig\n" if ($verbose); + exit 1; +} + +sub init_signals() { + + $SIG{HUP} = \&signal_cleanup; + $SIG{INT} = \&signal_cleanup; + $SIG{QUIT} = \&signal_cleanup; + $SIG{ABRT} = \&signal_cleanup; + $SIG{KILL} = \&signal_cleanup; + $SIG{TERM} = \&signal_cleanup; + + # Need this so that if giftopnm dies, we don't die. + $SIG{PIPE} = 'IGNORE'; +} + +END { exit_cleanup(); } + + +# returns the full path of the named program, or undef. +# +sub which($) { + my ($prog) = @_; + foreach (split (/:/, $ENV{PATH})) { + if (-x "$_/$prog") { + return $prog; + } + } + return undef; +} + + +# Choose random foreground and background colors +# +sub randcolors() { + return sprintf ("#%02x%02x%02x-#%02x%02x%02x", + int(rand()*60), + int(rand()*60), + int(rand()*60), + 120+int(rand()*135), + 120+int(rand()*135), + 120+int(rand()*135)); +} + + + +sub filter_subst($$$@) { + my ($filter, $width, $height, @tmpfiles) = @_; + my $colors = randcolors(); + $filter =~ s/\bWIDTH\b/$width/g; + $filter =~ s/\bHEIGHT\b/$height/g; + $filter =~ s/\bCOLORS\b/'$colors'/g; + my $i = 1; + foreach my $t (@tmpfiles) { + $filter =~ s/\bFILE$i\b/$t/g; + $i++; + } + if ($filter =~ m/([A-Z]+)/) { + error ("internal error: what is \"$1\"?"); + } + $filter =~ s/ +/ /g; + return $filter; +} + +# Frobnicate the image in some random way. +# +sub frob_ppm($) { + my ($ppm_data) = @_; + $_ = $ppm_data; + + error ("0-length data") if (!defined($ppm_data) || $ppm_data eq ""); + error ("not a PPM file") unless (m/^P\d\n/s); + my ($width, $height) = m/^P\d\n(\d+) (\d+)\n/s; + error ("got a bogus PPM") unless ($width && $height); + + my $tmpdir = $ENV{TMPDIR}; + $tmpdir = "/tmp" unless $tmpdir; + my $fn = sprintf ("%s/vidwhacker-0-%08x", $tmpdir, rand(0xFFFFFFFF)); + my $fn1 = sprintf ("%s/vidwhacker-1-%08x", $tmpdir, rand(0xFFFFFFFF)); + my $fn2 = sprintf ("%s/vidwhacker-2-%08x", $tmpdir, rand(0xFFFFFFFF)); + my $fn3 = sprintf ("%s/vidwhacker-3-%08x", $tmpdir, rand(0xFFFFFFFF)); + my @files = ( "$fn", "$fn1", "$fn2", "$fn3" ); + push @all_tmpfiles, @files; + + my $n = int(rand($#filters+1)); + my $filter = $filters[$n]; + + if ($verbose == 1) { + printf STDERR "$progname: running filter $n\n"; + } elsif ($verbose > 1) { + my $f = $filter; + $f =~ s/ +/ /g; + $f =~ s/^ */\t/; + $f =~ s/ *\|/\n\t|/g; + $f =~ s/ *\; */ ;\n\t/g; + print STDERR "$progname: filter $n:\n\n$f\n\n" if $verbose; + } + + $filter = filter_subst ($filter, $width, $height, @files); + + unlink @files; + + local *OUT; + open (OUT, ">$files[0]") || error ("writing $files[0]: $!"); + print OUT $ppm_data; + close OUT; + + $filter = "( $filter )"; + $filter .= "2>/dev/null" unless ($verbose > 1); + + local *IN; + open (IN, "$filter |") || error ("opening pipe: $!"); + $ppm_data = ""; + while () { $ppm_data .= $_; } + close IN; + + unlink @files; + return $ppm_data; +} + + +sub read_config() { + my $conf = "$ENV{HOME}/.xscreensaver"; + + my $had_dir = defined($imagedir); + + local *IN; + open (IN, "<$conf") || error ("reading $conf: $!"); + while () { + if (!$imagedir && m/^imageDirectory:\s+(.*)\s*$/i) { $imagedir = $1; } + elsif (m/^grabVideoFrames:\s+true\s*$/i) { $video_p = 1; } + elsif (m/^grabVideoFrames:\s+false\s*$/i) { $video_p = 0; } + elsif (m/^chooseRandomImages:\s+true\s*$/i) { $file_p = 1; } + elsif (m/^chooseRandomImages:\s+false\s*$/i) { $file_p = 0; } + } + close IN; + + $file_p = 1 if $had_dir; + + $imagedir = undef unless ($imagedir && $imagedir ne ''); + + if (!$file_p && !$video_p) { +# error ("neither grabVideoFrames nor chooseRandomImages are set\n\t") . +# "in $conf; $progname requires one or both." + $file_p = 1; + } + + if ($file_p) { + error ("no imageDirectory set in $conf") unless $imagedir; + error ("imageDirectory $imagedir doesn't exist") unless (-d $imagedir); + } + + if ($verbose > 1) { + printf STDERR "$progname: grab video: $video_p\n"; + printf STDERR "$progname: grab images: $file_p\n"; + printf STDERR "$progname: directory: $imagedir\n"; + } + +} + + +sub get_ppm() { + if ($use_stdin) { + print STDERR "$progname: reading from stdin\n" if ($verbose > 1); + my $ppm = ""; + while () { $ppm .= $_; } + return $ppm; + + } else { + + my $do_file_p; + + if ($file_p && $video_p) { + $do_file_p = (int(rand(2)) == 0); + print STDERR "$progname: doing " . ($do_file_p ? "files" : "video") ."\n" + if ($verbose); + } + elsif ($file_p) { $do_file_p = 1; } + elsif ($video_p) { $do_file_p = 0; } + else { + error ("internal error: not grabbing files or video?"); + } + + my $v = ($verbose <= 1 ? "" : "-" . ("v" x ($verbose-1))); + my $cmd; + if ($do_file_p) { + $cmd = "xscreensaver-getimage-file $v --name \"$imagedir\""; + } else { + $cmd = "xscreensaver-getimage-video $v --stdout"; + } + + my $ppm; + + if ($do_file_p) { + + print STDERR "$progname: running: $cmd\n" if ($verbose > 1); + my $fn = `$cmd`; + $fn =~ s/\n$//s; + error ("didn't get a file?") if ($fn eq ""); + $fn = "$imagedir/$fn" unless ($fn =~ m@^/@s); + + print STDERR "$progname: selected file $fn\n" if ($verbose > 1); + + if ($fn =~ m/\.gif/i) { $cmd = "giftopnm < \"$fn\""; } + elsif ($fn =~ m/\.jpe?g/i) { $cmd = "djpeg < \"$fn\""; } + elsif ($fn =~ m/\.png/i) { $cmd = "pngtopnm < \"$fn\""; } + elsif ($fn =~ m/\.xpm/i) { $cmd = "xpmtoppm < \"$fn\""; } + elsif ($fn =~ m/\.bmp/i) { $cmd = "bmptoppm < \"$fn\""; } + elsif ($fn =~ m/\.tiff?/i) { $cmd = "tifftopnm < \"$fn\""; } + elsif ($fn =~ m/\.p[bgp]m/i) { return `cat \"$fn\"`; } + else { + print STDERR "$progname: $fn: unrecognized file extension\n"; + # go around the loop and get another + return undef; + } + + print STDERR "$progname: converting with: $cmd\n" if ($verbose > 1); + $cmd .= " 2>/dev/null" unless ($verbose > 1); + $ppm = `$cmd`; + + } else { + + print STDERR "$progname: running: $cmd\n" if ($verbose > 1); + $ppm = `$cmd`; + error ("no data?") if ($ppm eq ""); + error ("not a PPM file") unless ($ppm =~ m/^P\d\n/s); + + $_ = $ppm; + my ($width, $height) = m/^P\d\n(\d+) (\d+)\n/s; + error ("got a bogus PPM") unless ($width && $height); + print STDERR "$progname: grabbed ${width}x$height PPM\n" + if ($verbose > 1); + $_ = 0; + } + + return $ppm; + } +} + +sub dispose_ppm($) { + my ($ppm) = @_; + + error ("0-length data") if (!defined($ppm) || $ppm eq ""); + error ("not a PPM file") unless ($ppm =~ m/^P\d\n/s); + + if ($use_stdout) { + print STDERR "$progname: writing to stdout\n" if ($verbose > 1); + print $ppm; + + } else { + my $tmpdir = $ENV{TMPDIR}; + $tmpdir = "/tmp" unless $tmpdir; + my $fn = sprintf ("%s/vidwhacker-%08x.ppm", $tmpdir, rand(0xFFFFFFFF)); + local *OUT; + unlink $fn; + push @all_tmpfiles, $fn; + open (OUT, ">$fn") || error ("writing $fn: $!"); + print OUT $ppm; + close OUT; + + my @cmd = split (/ +/, $displayer); + push @cmd, $fn; + print STDERR "$progname: executing \"" . join(" ", @cmd) . "\"\n" + if ($verbose); + system (@cmd); + + my $exit_value = $? >> 8; + my $signal_num = $? & 127; + my $dumped_core = $? & 128; + + unlink $fn; + + error ("$cmd[0]: core dumped!") if ($dumped_core); + error ("$cmd[0]: signal $signal_num!") if ($signal_num); + error ("$cmd[0]: exited with $exit_value!") if ($exit_value); + } +} + + +my $stdin_ppm = undef; + +sub vidwhack() { + my $ppm; + if ($use_stdin) { + if (!defined($stdin_ppm)) { + $stdin_ppm = get_ppm(); + } + $ppm = $stdin_ppm; + } else { + my $max_err_count = 20; + my $err_count = 0; + while (!defined($ppm)) { + $ppm = get_ppm(); + $err_count++ if (!defined ($ppm)); + error ("too many errors, too few images!") + if ($err_count > $max_err_count); + } + } + + $ppm = frob_ppm ($ppm); + dispose_ppm ($ppm); + $ppm = undef; +} + + +sub error($) { + my ($err) = @_; + print STDERR "$progname: $err\n"; + exit 1; +} + +sub usage() { + print STDERR "VidWhacker, Copyright (c) 2001 Jamie Zawinski \n"; + print STDERR " http://www.jwz.org/xscreensaver/"; + print STDERR "\n"; + print STDERR "usage: $0 [-display dpy] [-verbose]\n"; + print STDERR "\t\t[-root | -window | -window-id 0xXXXXX ]\n"; + print STDERR "\t\t[-stdin] [-stdout] [-delay secs]\n"; + print STDERR "\t\t[-directory image_directory]\n"; + exit 1; +} + +sub main() { + while ($_ = $ARGV[0]) { + shift @ARGV; + if (m/^--?verbose$/) { $verbose++; } + elsif (m/^-v+$/) { $verbose += length($_)-1; } + elsif (m/^(-display|-disp|-dis|-dpy|-d)$/) { $ENV{DISPLAY} = shift @ARGV; } + elsif (m/^--?stdin$/) { $use_stdin = 1; } + elsif (m/^--?stdout$/) { $use_stdout = 1; } + elsif (m/^--?delay$/) { $delay = shift @ARGV; } + elsif (m/^--?dir(ectory)?$/) { $imagedir = shift @ARGV; } + elsif (m/^--?root$/) { } + elsif (m/^--?window-id$/) { + my $id = shift @ARGV; + error ("unparsable window id: $id") + unless ($id =~ m/^\d+$|^0x[\da-f]+$/i); + $displayer =~ s/--?root\b/$id/ || + error ("unable to munge displayer: $displayer"); + } + elsif (m/^--?window$/) { + print STDERR "$progname: sorry, \"-window\" is unimplemented.\n"; + print STDERR "$progname: use \"-stdout\" and pipe to a displayer.\n"; + exit 1; + } + elsif (m/^-./) { usage; } + else { usage; } + } + + init_signals(); + + read_config; + + # sanity checking - is pbm installed? + # (this is a non-exhaustive but representative list) + foreach ("ppmtopgm", "pgmenhance", "pnminvert", "pnmarith", "pnmdepth") { + which ($_) || error "$_ not found on \$PATH."; + } + + if (!$use_stdout) { + $_ = `xdpyinfo 2>&-`; + ($screen_width) =~ m/ dimensions: +(\d+)x(\d+) pixels/; + $screen_width = 800 unless $screen_width > 0; + } + + if ($use_stdout) { + vidwhack(); + } else { + while (1) { + vidwhack(); + sleep $delay; + } + } +} + +main(); +exit 0; diff --git a/hacks/vidwhacker.man b/hacks/vidwhacker.man new file mode 100644 index 00000000..8c2505bc --- /dev/null +++ b/hacks/vidwhacker.man @@ -0,0 +1,89 @@ +.TH XScreenSaver 1 "17-Jun-99" "X Version 11" +.SH NAME +vidwhacker - grab images and apply random filters to them +.SH SYNOPSIS +.B vidwhacker +[\-display \fIhost:display.screen\fP] [\-root] [\-verbose] +[\-stdin] [\-stdout] [\-delay seconds] +[-directory \fIdirectory\fP] +[\-fps] +.SH DESCRIPTION +The \fIvidwhacker\fP program grabs an image from disk, or from the +system's video input, then applies random image filters to it, and +displays the result. The \fIvidwhacker\fP program does not terminate +until killed. + +It depends heavily on the various PBM tools (e.g., +.BR ppmrelief (1).) + +Selection of random image files is done by running the +.BR xscreensaver-getimage-file (1) +program. Capture of video frames (if requested) is done by running the +.BR xscreensaver-getimage-video (1) +program. The options of whether to do video, and which directory to +search for images, are specified in the \fI~/.xscreensaver\fP file. +.SH OPTIONS +.I vidwhacker +accepts the following options: +.TP 8 +.B \-root +Draw on the root window. This is the default. +.TP 8 +.B \-verbose +Print diagnostics. +.TP 8 +.B \-stdin +Instead of grabbing an image from disk or video, read an image +to manipulate from stdin. This image must be in +.BR ppm (5) +format. The program will still perform repeated random image +transformations, but it will always use this one image as its starting point. +.TP 8 +.B \-delay \fIseconds\fP +How long to sleep between images. Default 5 seconds (the actual +elapsed time is significantly longer, due to processing time.) +.TP 8 +.B \-stdout +Instead of displaying the image on a window or on the root, write the new +image on stdout, and exit. +.TP 8 +.B \-directory \fIdirectory\fP +Use this directory instead of the \fBimageDirectory\fP specified in +the \fI~/.xscreensaver\fP file. +.TP 8 +.B \-fps +Display the current frame rate and CPU load. +.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 BUGS +It's slow. +.SH TO DO +It might be interesting to rewrite this to use +.BR gimp (1) +plugins instead of the pbm tools. It probably wouldn't be any faster, +but there would be a wider variety of effects available. +.SH SEE ALSO +.BR X (1), +.BR xscreensaver (1), +.BR xscreensaver-getimage-file (1), +.BR xscreensaver-getimage-video (1), +.BR xv (1), +.BR ppmtogif (1), +.BR cjpeg (1) +.SH COPYRIGHT +Copyright \(co 1998-2001 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 , 18-Jan-98. diff --git a/hacks/vines.c b/hacks/vines.c new file mode 100644 index 00000000..c2480780 --- /dev/null +++ b/hacks/vines.c @@ -0,0 +1,203 @@ +/* -*- Mode: C; tab-width: 4 -*- */ +/* vines --- vine fractals */ + +#if 0 +static const char sccsid[] = "@(#)vines.c 5.00 2000/11/01 xlockmore"; +#endif + +/*- + * Copyright (c) 1997 by Tracy Camp campt@hurrah.com + * + * Permission to use, copy, modify, and distribute this software and its + * documentation for any purpose and without fee is hereby granted, + * provided that the above copyright notice appear in all copies and that + * both that copyright notice and this permission notice appear in + * supporting documentation. + * + * This file is provided AS IS with no warranties of any kind. The author + * shall have no liability with respect to the infringement of copyrights, + * trade secrets or any patents by this file or any part thereof. In no + * event will the author be liable for any lost revenue or profits or + * other special, indirect and consequential damages. + * + * If you make a modification I would of course appreciate a copy. + * + * Revision History: + * 01-Nov-2000: Allocation checks + * 11-Jul-1997: David Hansen + * Changed names to vines and modified draw loop + * to honor batchcount so vines can be grown or plotted. + * 10-May-1997: Compatible with xscreensaver + * 21-Mar-1997: David Hansen + * Updated mode to draw complete patterns on every + * iteration instead of growing the vine. Also made + * adjustments to randomization and changed variable + * names to make logic easier to follow. + */ + +/*- + * This was modifed from a 'screen saver' that a friend and I + * wrote on our TI-8x calculators in high school physics one day + * Basically another geometric pattern generator, this ones claim + * to fame is a pseudo-fractal looking vine like pattern that creates + * nifty whorls and loops. + */ + +#ifdef STANDALONE +# define MODE_vines +# define DEFAULTS "*delay: 200000 \n" \ + "*count: 0 \n" \ + "*ncolors: 64 \n" \ + "*fpsSolid: true \n" \ + +# include "xlockmore.h" /* in xscreensaver distribution */ +# define reshape_vines 0 +# define vines_handle_event 0 +# include "erase.h" +#else /* STANDALONE */ +# include "xlock.h" /* in xlockmore distribution */ +#endif /* STANDALONE */ + +#ifdef MODE_vines + +ENTRYPOINT ModeSpecOpt vines_opts = +{0, (XrmOptionDescRec *) NULL, 0, (argtype *) NULL, (OptionStruct *) NULL}; + +#ifdef USE_MODULES +ModStruct vines_description = +{"vines", "init_vines", "draw_vines", "release_vines", + "refresh_vines", "init_vines", (char *) NULL, &vines_opts, + 200000, 0, 1, 1, 64, 1.0, "", + "Shows fractals", 0, NULL}; + +#endif + +typedef struct { + int a; + int x1; + int y1; + int x2; + int y2; + int i; + int length; + int iterations; + int constant; + int ang; + int centerx; + int centery; +#ifdef STANDALONE + eraser_state *eraser; +#endif +} vinestruct; + +static vinestruct *vines = (vinestruct *) NULL; + +ENTRYPOINT void +refresh_vines(ModeInfo * mi) +{ + MI_CLEARWINDOW(mi); +} /* refresh_vines */ + +ENTRYPOINT void +init_vines(ModeInfo * mi) +{ + vinestruct *fp; + + if (vines == NULL) { + if ((vines = (vinestruct *) calloc(MI_NUM_SCREENS(mi), + sizeof (vinestruct))) == NULL) { + return; + } + } + fp = &vines[MI_SCREEN(mi)]; + + fp->i = 0; + fp->length = 0; + fp->iterations = 30 + NRAND(100); + +#ifndef STANDALONE + MI_CLEARWINDOW(mi); +#endif +} /* init_vines */ + +ENTRYPOINT void +draw_vines(ModeInfo * mi) +{ + Display *display = MI_DISPLAY(mi); + GC gc = MI_GC(mi); + int count; + vinestruct *fp; + + if (vines == NULL) + return; + fp = &vines[MI_SCREEN(mi)]; + +#ifdef STANDALONE + if (fp->eraser) { + fp->eraser = erase_window (MI_DISPLAY(mi), MI_WINDOW(mi), fp->eraser); + return; + } +#endif + + /* MI_IS_DRAWN(mi) = True; */ + if (fp->i >= fp->length) { + if (--(fp->iterations) == 0) { +#ifdef STANDALONE + fp->eraser = erase_window (MI_DISPLAY(mi), MI_WINDOW(mi), fp->eraser); +#endif /* STANDALONE */ + init_vines(mi); + } + fp->centerx = NRAND(MI_WIDTH(mi)); + fp->centery = NRAND(MI_HEIGHT(mi)); + + fp->ang = 60 + NRAND(720); + fp->length = 100 + NRAND(3000); + fp->constant = fp->length * (10 + NRAND(10)); + + fp->i = 0; + fp->a = 0; + fp->x1 = 0; + fp->y1 = 0; + fp->x2 = 1; + fp->y2 = 0; + + if (MI_NPIXELS(mi) > 2) + XSetForeground(display, gc, MI_PIXEL(mi, NRAND(MI_NPIXELS(mi)))); + else + XSetForeground(display, gc, MI_WHITE_PIXEL(mi)); + } + count = fp->i + MI_COUNT(mi); + if ((count <= fp->i) || (count > fp->length)) + count = fp->length; + + while (fp->i < count) { + XDrawLine(display, MI_WINDOW(mi), gc, + fp->centerx + (fp->x1 / fp->constant), + fp->centery - (fp->y1 / fp->constant), + fp->centerx + (fp->x2 / fp->constant), + fp->centery - (fp->y2 / fp->constant)); + + fp->a += (fp->ang * fp->i); + + fp->x1 = fp->x2; + fp->y1 = fp->y2; + + fp->x2 += (int) (fp->i * (cos((double) fp->a) * 360.0) / (2.0 * M_PI)); + fp->y2 += (int) (fp->i * (sin((double) fp->a) * 360.0) / (2.0 * M_PI)); + fp->i++; + } +} /* draw_vines */ + +ENTRYPOINT void +release_vines(ModeInfo * mi) +{ + if (vines != NULL) { + (void) free((void *) vines); + vines = (vinestruct *) NULL; + } +} /* release_vines */ + + +XSCREENSAVER_MODULE ("Vines", vines) + +#endif /* MODE_vines */ diff --git a/hacks/vines.man b/hacks/vines.man new file mode 100644 index 00000000..45e79852 --- /dev/null +++ b/hacks/vines.man @@ -0,0 +1,66 @@ +.TH XScreenSaver 1 "10-May-97" "X Version 11" +.SH NAME +vines - draws pseudo-fractal geometric patterns +.SH SYNOPSIS +.B vines +[\-display \fIhost:display.screen\fP] [\-foreground \fIcolor\fP] [\-background \fIcolor\fP] [\-window] [\-root] [\-mono] [\-install] [\-visual \fIvisual\fP] [\-ncolors \fIinteger\fP] [\-delay \fImicroseconds\fP] + +[\-fps] +.SH DESCRIPTION +The \fIvines\fP program is yet another geometric pattern generator, this +one's claim to fame being a pseudo-fractal looking vine like pattern that +creates nifty whorls and loops. +.SH OPTIONS +.I vines +accepts the following options: +.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 \-mono +If on a color display, pretend we're on a monochrome display. +.TP 8 +.B \-install +Install a private colormap for the window. +.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 \-ncolors \fIinteger\fP +How many colors should be used (if possible). Default 64. +The colors are chosen randomly. +.TP 8 +.B \-fps +Display the current frame rate and CPU load. +.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), +.BR xlock (1) +.SH COPYRIGHT +Copyright \(co 1997 by Tracy Camp. + +Permission to use, copy, modify, and distribute this software and its +documentation for any purpose and without fee is hereby granted, +provided that the above copyright notice appear in all copies and that +both that copyright notice and this permission notice appear in +supporting documentation. +.SH AUTHOR +Tracy Camp , 1997. + +Tweaked by David Hansen , 21-Mar-97. + +Ability to run standalone or with \fIxscreensaver\fP added by +Jamie Zawinski , 10-May-97. diff --git a/hacks/vms_axp.opt b/hacks/vms_axp.opt new file mode 100644 index 00000000..64461591 --- /dev/null +++ b/hacks/vms_axp.opt @@ -0,0 +1,4 @@ +[-.UTILS]UTILS.OLB_AXP/LIB +SYS$SHARE:DECW$XMULIBSHR.EXE/SHARE +SYS$SHARE:DECW$XTSHR.EXE/SHARE +SYS$SHARE:DECW$XLIBSHR.EXE/SHARE diff --git a/hacks/vms_axp_12.opt b/hacks/vms_axp_12.opt new file mode 100644 index 00000000..10f94267 --- /dev/null +++ b/hacks/vms_axp_12.opt @@ -0,0 +1,4 @@ +[-.UTILS]UTILS.OLB_AXP/LIB +SYS$SHARE:DECW$XMULIBSHRR5.EXE/SHARE +SYS$SHARE:DECW$XTLIBSHRR5.EXE/SHARE +SYS$SHARE:DECW$XLIBSHR.EXE/SHARE diff --git a/hacks/vms_decc.opt b/hacks/vms_decc.opt new file mode 100644 index 00000000..43d6858f --- /dev/null +++ b/hacks/vms_decc.opt @@ -0,0 +1,4 @@ +[-.UTILS]UTILS.OLB_DECC/LIB +SYS$SHARE:DECW$XMULIBSHR.EXE/SHARE +SYS$SHARE:DECW$XTSHR.EXE/SHARE +SYS$SHARE:DECW$XLIBSHR.EXE/SHARE diff --git a/hacks/vms_decc_12.opt b/hacks/vms_decc_12.opt new file mode 100644 index 00000000..dd6d2f37 --- /dev/null +++ b/hacks/vms_decc_12.opt @@ -0,0 +1,4 @@ +[-.UTILS]UTILS.OLB_DECC/LIB +SYS$SHARE:DECW$XMULIBSHRR5.EXE/SHARE +SYS$SHARE:DECW$XTLIBSHRR5.EXE/SHARE +SYS$SHARE:DECW$XLIBSHR.EXE/SHARE diff --git a/hacks/wander.c b/hacks/wander.c new file mode 100644 index 00000000..8fa8995a --- /dev/null +++ b/hacks/wander.c @@ -0,0 +1,260 @@ +/* wander, by Rick Campbell , 19 December 1998. + * + * 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. + */ + +#include + +#include "screenhack.h" +#include "colors.h" +#include "erase.h" + +#define MAXIMUM_COLOR_COUNT (256) + +struct state { + Display *dpy; + Window window; + + unsigned int advance; + Bool circles; + Colormap color_map; + int color_count; + int color_index; + XColor colors [MAXIMUM_COLOR_COUNT]; + GC context; + unsigned int density; + int depth; + int height; + unsigned int length; + unsigned int reset; + unsigned int size; + int width; + int delay; + + int x, y, last_x, last_y, width_1, height_1, length_limit, reset_limit; + unsigned long color; + Pixmap pixmap; + + eraser_state *eraser; +}; + + +static void * +wander_init (Display *dpy, Window window) +{ + struct state *st = (struct state *) calloc (1, sizeof(*st)); + XGCValues values; + XWindowAttributes attributes; + + st->dpy = dpy; + st->window = window; + st->delay = get_integer_resource (st->dpy, "delay", "Integer"); + + XClearWindow (st->dpy, st->window); + XGetWindowAttributes (st->dpy, st->window, &attributes); + st->width = attributes.width; + st->height = attributes.height; + st->depth = attributes.depth; + st->color_map = attributes.colormap; + if (st->color_count) + { + free_colors (st->dpy, st->color_map, st->colors, st->color_count); + st->color_count = 0; + } + st->context = XCreateGC (st->dpy, st->window, 0, &values); + st->color_count = MAXIMUM_COLOR_COUNT; + make_color_loop (st->dpy, st->color_map, + 0, 1, 1, + 120, 1, 1, + 240, 1, 1, + st->colors, &st->color_count, True, False); + if (st->color_count <= 0) + { + st->color_count = 2; + st->colors [0].red = st->colors [0].green = st->colors [0].blue = 0; + st->colors [1].red = st->colors [1].green = st->colors [1].blue = 0xFFFF; + XAllocColor (st->dpy, st->color_map, &st->colors [0]); + XAllocColor (st->dpy, st->color_map, &st->colors [1]); + } + st->color_index = random () % st->color_count; + + st->advance = get_integer_resource (st->dpy, "advance", "Integer"); + st->density = get_integer_resource (st->dpy, "density", "Integer"); + if (st->density < 1) st->density = 1; + st->reset = get_integer_resource (st->dpy, "reset", "Integer"); + if (st->reset < 100) st->reset = 100; + st->circles = get_boolean_resource (st->dpy, "circles", "Boolean"); + st->size = get_integer_resource (st->dpy, "size", "Integer"); + if (st->size < 1) st->size = 1; + st->width = st->width / st->size; + st->height = st->height / st->size; + st->length = get_integer_resource (st->dpy, "length", "Integer"); + if (st->length < 1) st->length = 1; + XSetForeground (st->dpy, st->context, st->colors [st->color_index].pixel); + + + st->x = random () % st->width; + st->y = random () % st->height; + st->last_x = st->x; + st->last_y = st->y; + st->width_1 = st->width - 1; + st->height_1 = st->height - 1; + st->length_limit = st->length; + st->reset_limit = st->reset; + st->color_index = random () % st->color_count; + st->color = st->colors [random () % st->color_count].pixel; + st->pixmap = XCreatePixmap (st->dpy, window, st->size, + st->size, st->depth); + + XSetForeground (st->dpy, st->context, + BlackPixel (st->dpy, DefaultScreen (st->dpy))); + XFillRectangle (st->dpy, st->pixmap, st->context, 0, 0, + st->width * st->size, st->height * st->size); + XSetForeground (st->dpy, st->context, st->color); + XFillArc (st->dpy, st->pixmap, st->context, 0, 0, st->size, st->size, 0, 360*64); + + return st; +} + + +static unsigned long +wander_draw (Display *dpy, Window window, void *closure) +{ + struct state *st = (struct state *) closure; + int i; + + if (st->eraser) { + st->eraser = erase_window (st->dpy, st->window, st->eraser); + goto END; + } + + for (i = 0; i < 2000; i++) + { + if (random () % st->density) + { + st->x = st->last_x; + st->y = st->last_y; + } + else + { + st->last_x = st->x; + st->last_y = st->y; + st->x = (st->x + st->width_1 + (random () % 3)) % st->width; + st->y = (st->y + st->height_1 + (random () % 3)) % st->height; + } + + if ((random () % st->length_limit) == 0) + { + if (st->advance == 0) + { + st->color_index = random () % st->color_count; + } + else + { + st->color_index = (st->color_index + st->advance) % st->color_count; + } + st->color = st->colors [st->color_index].pixel; + XSetForeground (st->dpy, st->context, st->color); + if (st->circles) + { + XFillArc (st->dpy, st->pixmap, st->context, + 0, 0, st->size, st->size, 0, 360 * 64); + } + } + + if ((random () % st->reset_limit) == 0) + { + st->eraser = erase_window (st->dpy, st->window, st->eraser); + st->color = st->colors [random () % st->color_count].pixel; + st->x = random () % st->width; + st->y = random () % st->height; + st->last_x = st->x; + st->last_y = st->y; + if (st->circles) + { + XFillArc (st->dpy, st->pixmap, st->context, 0, 0, st->size, st->size, 0, 360*64); + } + } + + if (st->size == 1) + { + XDrawPoint (st->dpy, st->window, st->context, st->x, st->y); + } + else + { + if (st->circles) + { + XCopyArea (st->dpy, st->pixmap, st->window, st->context, 0, 0, st->size, st->size, + st->x * st->size, st->y * st->size); + } + else + { + XFillRectangle (st->dpy, st->window, st->context, st->x * st->size, st->y * st->size, + st->size, st->size); + } + } + } + + END: + return st->delay; +} + + +static void +wander_reshape (Display *dpy, Window window, void *closure, + unsigned int w, unsigned int h) +{ + struct state *st = (struct state *) closure; + st->width = w / st->size; + st->height = h / st->size; + st->width_1 = st->width - 1; + st->height_1 = st->height - 1; +} + +static Bool +wander_event (Display *dpy, Window window, void *closure, XEvent *event) +{ + return False; +} + +static void +wander_free (Display *dpy, Window window, void *closure) +{ +} + +static const char *wander_defaults [] = +{ + ".background: black", + ".foreground: white", + ".fpsSolid: true", + ".advance: 1", + ".density: 2", + ".length: 25000", + ".delay: 20000", + ".reset: 2500000", + ".circles: False", + ".size: 1", + 0 +}; + +static XrmOptionDescRec wander_options [] = +{ + { "-advance", ".advance", XrmoptionSepArg, 0 }, + { "-circles", ".circles", XrmoptionNoArg, "True" }, + { "-no-circles",".circles", XrmoptionNoArg, "False" }, + { "-density", ".density", XrmoptionSepArg, 0 }, + { "-length", ".length", XrmoptionSepArg, 0 }, + { "-delay", ".delay", XrmoptionSepArg, 0 }, + { "-reset", ".reset", XrmoptionSepArg, 0 }, + { "-size", ".size", XrmoptionSepArg, 0 }, + { 0, 0, 0, 0 } +}; + + +XSCREENSAVER_MODULE ("Wander", wander) diff --git a/hacks/wander.man b/hacks/wander.man new file mode 100644 index 00000000..497d35e6 --- /dev/null +++ b/hacks/wander.man @@ -0,0 +1,76 @@ +.TH XScreenSaver 1 "" "X Version 11" +.SH NAME +wander - colorful random-walk. +.SH SYNOPSIS +.B wander +[\-display \fIhost:display.screen\fP] +[\-visual \fIvisual\fP] +[\-window] +[\-root] +[\-density \fInumber\fP] +[\-reset \fInumber\fP] +[\-length \fInumber\fP] +[\-delay \fInumber\fP] +[\-circles] +[\-size \fInumber\fP] +[\-advance \fInumber\fP] +[\-fps] +.SH DESCRIPTION +Draws a colorful random-walk, in various forms. +.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 \-density \fInumber\fP +Density. 1 - 30. Default: 2. +.TP 8 +.B \-reset \fInumber\fP +Number of frames before resetting. Default: 2500000. +.TP 8 +.B \-length \fInumber\fP +Number of iterations. Default: 25000. +.TP 8 +.B \-delay \fInumber\fP +Sustain. 0 - 60. Default: 1. +.TP 8 +.B \-circles | \-no-circles +Whether to draw spots. +.TP 8 +.B \-size \fInumber\fP +Size. 0 - 100. Default: 1. +.TP 8 +.B \-advance \fInumber\fP +Color Contrast. 1 - 100. Default: 1. +.TP 8 +.B \-fps +Display the current frame rate and CPU load. +.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 2002 by Rick Campbell. 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 +Rick Campbell. diff --git a/hacks/webcollage b/hacks/webcollage new file mode 100755 index 00000000..e9a3aa37 --- /dev/null +++ b/hacks/webcollage @@ -0,0 +1,3886 @@ +#!/usr/bin/perl -w +# +# webcollage, Copyright (c) 1999-2012 by Jamie Zawinski +# This program decorates the screen with random images from the web. +# One satisfied customer described it as "a nonstop pop culture brainbath." +# +# 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. + + +# To run this as a display mode with xscreensaver, add this to `programs': +# +# webcollage -root +# webcollage -root -filter 'vidwhacker -stdin -stdout' +# +# +# You can see this in action at http://www.jwz.org/webcollage/ -- +# it auto-reloads about once a minute. To make a page similar to +# that on your own system, do this: +# +# webcollage -size '800x600' -imagemap $HOME/www/webcollage/index +# +# +# If you have the "driftnet" program installed, webcollage can display a +# collage of images sniffed off your local ethernet, instead of pulled out +# of search engines: in that way, your screensaver can display the images +# that your co-workers are downloading! +# +# Driftnet is available here: http://www.ex-parrot.com/~chris/driftnet/ +# Use it like so: +# +# webcollage -root -driftnet +# +# Driftnet is the Unix implementation of the MacOS "EtherPEG" program. + + +require 5; +use strict; + +# We can't "use diagnostics" here, because that library malfunctions if +# you signal and catch alarms: it says "Uncaught exception from user code" +# and exits, even though I damned well AM catching it! +#use diagnostics; + + +use Socket; +require Time::Local; +require POSIX; +use Fcntl ':flock'; # import LOCK_* constants +use POSIX qw(strftime); + +use bytes; # Larry can take Unicode and shove it up his ass sideways. + # Perl 5.8.0 causes us to start getting incomprehensible + # errors about UTF-8 all over the place without this. + + +my $progname = $0; $progname =~ s@.*/@@g; +my $version = q{ $Revision: 1.159 $ }; $version =~ s/^[^0-9]+([0-9.]+).*$/$1/; +my $copyright = "WebCollage $version, Copyright (c) 1999-2011" . + " Jamie Zawinski \n" . + " http://www.jwz.org/webcollage/\n"; + + + +my @search_methods = ( 26, "googlephotos", \&pick_from_google_image_photos, + 15, "googleimgs", \&pick_from_google_images, + 15, "googlenums", \&pick_from_google_image_numbers, + 17, "flickr_recent", \&pick_from_flickr_recent, + 14, "flickr_random", \&pick_from_flickr_random, +# twitpic went stale. don't have time to fix it right now. +# 10, "twitpic", \&pick_from_twitpic_images, + 9, "livejournal", \&pick_from_livejournal_images, + 4, "yahoorand", \&pick_from_yahoo_random_link, + + # This one doesn't work very well: too many non-img links. + 0, "twitter", \&pick_from_twitter_images, + + # This is a cute way to search for a certain webcams. + # Not included in default methods, since these images + # aren't terribly interesting by themselves. + # See also "SurveillanceSaver". + # + 0, "securitycam", \&pick_from_security_camera, + + # Nonfunctional as of June 2011. + # 0, "altavista", \&pick_from_alta_vista_random_link, + + # In Apr 2002, Google asked me to stop searching them. + # I asked them to add a "random link" url. They said + # "that would be easy, we'll think about it" and then + # never wrote back. Booo Google! Booooo! So, screw + # those turkeys, I've turned Google searching back on. + # I'm sure they can take it. (Jan 2005.) + + # Jan 2005: Yahoo fucked up their search form so that + # it's no longer possible to do "or" searches on news + # images, so we rarely get any hits there any more. + # + # 0, "yahoonews", \&pick_from_yahoo_news_text, + + # Dec 2004: the ircimages guy's server can't take the + # heat, so he started banning the webcollage user agent. + # I tried to convince him to add a lighter-weight page to + # support webcollage better, but he doesn't care. + # + # 0, "ircimages", \&pick_from_ircimages, + + # Dec 2002: Alta Vista has a new "random link" URL now. + # They added it specifically to better support webcollage! + # That was super cool of them. This is how we used to do + # it, before: + # + # 0, "avimages", \&pick_from_alta_vista_images, + # 0, "avtext", \&pick_from_alta_vista_text, + + # This broke in 2004. Eh, Lycos sucks anyway. + # + # 0, "lycos", \&pick_from_lycos_text, + + # This broke in 2003, I think. I suspect Hotbot is + # actually the same search engine data as Lycos. + # + # 0, "hotbot", \&pick_from_hotbot_text, + ); + +# programs we can use to write to the root window (tried in ascending order.) +# +my @root_displayers = ( + "xscreensaver-getimage -root -file", + "chbg -once -xscreensaver -max_size 100", + "xv -root -quit -viewonly +noresetroot -quick24 -rmode 5" . + " -rfg black -rbg black", + "xli -quiet -onroot -center -border black", + "xloadimage -quiet -onroot -center -border black", + +# this lame program wasn't built with vroot.h: +# "xsri -scale -keep-aspect -center-horizontal -center-vertical", +); + + +# Some sites need cookies to work properly. These are they. +# +my %cookies = ( + "www.altavista.com" => "AV_ALL=1", # request uncensored searches + "web.altavista.com" => "AV_ALL=1", + + # log in as "cipherpunk" + "www.nytimes.com" => 'NYT-S=18cHMIlJOn2Y1bu5xvEG3Ufuk6E1oJ.' . + 'FMxWaQV0igaB5Yi/Q/guDnLeoL.pe7i1oakSb' . + '/VqfdUdb2Uo27Vzt1jmPn3cpYRlTw9', + + "ircimages.com" => 'disclaimer=1', +); + + +# If this is set, it's a helper program to use for pasting images together: +# this is a lot faster and more efficient than using PPM pipelines, which is +# what we do if this program doesn't exist. (We check for "webcollage-helper" +# on $PATH at startup, and set this variable appropriately.) +# +my $webcollage_helper = undef; + + +# If we have the webcollage-helper program, then it will paste the images +# together with transparency! 0.0 is invisible, 1.0 is totally opaque. +# +my $opacity = 0.85; + + +# Some sites have managed to poison the search engines. These are they. +# (We auto-detect sites that have poisoned the search engines via excessive +# keywords or dictionary words, but these are ones that slip through +# anyway.) +# +# This can contain full host names, or 2 or 3 component domains. +# +my %poisoners = ( + "die.net" => 1, # 'l33t h4ck3r d00dz. + "genforum.genealogy.com" => 1, # Cluttering avtext with human names. + "rootsweb.com" => 1, # Cluttering avtext with human names. + "akamai.net" => 1, # Lots of sites have their images on Akamai. + "akamaitech.net" => 1, # But those are pretty much all banners. + # Since Akamai is super-expensive, let's + # go out on a limb and assume that all of + # their customers are rich-and-boring. + "bartleby.com" => 1, # Dictionary, cluttering avtext. + "encyclopedia.com" => 1, # Dictionary, cluttering avtext. + "onlinedictionary.datasegment.com" => 1, # Dictionary, cluttering avtext. + "hotlinkpics.com" => 1, # Porn site that has poisoned avimages + # (I don't see how they did it, though!) + "alwayshotels.com" => 1, # Poisoned Lycos pretty heavily. + "nextag.com" => 1, # Poisoned Alta Vista real good. + "ghettodriveby.com" => 1, # Poisoned Google Images. + "crosswordsolver.org" => 1, # Poisoned Google Images. + "xona.com" => 1, # Poisoned Google Images. + "freepatentsonline.com" => 1, # Poisoned Google Images. + "herbdatanz.com" => 1, # Poisoned Google Images. +); + + +# When verbosity is turned on, we warn about sites that we seem to be hitting +# a lot: usually this means some new poisoner has made it into the search +# engines. But sometimes, the warning is just because that site has a lot +# of stuff on it. So these are the sites that are immune to the "frequent +# site" diagnostic message. +# +my %warningless_sites = ( + "home.earthlink.net" => 1, + "www.angelfire.com" => 1, + "members.aol.com" => 1, + "img.photobucket.com" => 1, + "pics.livejournal.com" => 1, + "tinypic.com" => 1, + "flickr.com" => 1, + "pbase.com" => 1, + "blogger.com" => 1, + "multiply.com" => 1, + "wikimedia.org" => 1, + "twitpic.com" => 1, + "amazonaws.com" => 1, + "blogspot.com" => 1, + "photoshelter.com" => 1, + "myspacecdn.com" => 1, + "feedburner.com" => 1, + "wikia.com" => 1, + "ljplus.ru" => 1, + "yandex.ru" => 1, + "imgur.com" => 1, + "yfrog.com" => 1, + + "yimg.com" => 1, # This is where dailynews.yahoo.com stores + "eimg.com" => 1, # its images, so pick_from_yahoo_news_text() + # hits this every time. + + "images.quizfarm.com" => 1, # damn those LJ quizzes... + "images.quizilla.com" => 1, + "images.quizdiva.net" => 1, + + "driftnet" => 1, # builtin... + "local-directory" => 1, # builtin... +); + + +# For decoding HTML-encoded character entities to URLs. +# +my %entity_table = ( + "apos" => '\'', + "quot" => '"', "amp" => '&', "lt" => '<', "gt" => '>', + "nbsp" => ' ', "iexcl" => '¡', "cent" => '¢', "pound" => '£', + "curren" => '¤', "yen" => '¥', "brvbar" => '¦', "sect" => '§', + "uml" => '¨', "copy" => '©', "ordf" => 'ª', "laquo" => '«', + "not" => '¬', "shy" => '­', "reg" => '®', "macr" => '¯', + "deg" => '°', "plusmn" => '±', "sup2" => '²', "sup3" => '³', + "acute" => '´', "micro" => 'µ', "para" => '¶', "middot" => '·', + "cedil" => '¸', "sup1" => '¹', "ordm" => 'º', "raquo" => '»', + "frac14" => '¼', "frac12" => '½', "frac34" => '¾', "iquest" => '¿', + "Agrave" => 'À', "Aacute" => 'Á', "Acirc" => 'Â', "Atilde" => 'Ã', + "Auml" => 'Ä', "Aring" => 'Å', "AElig" => 'Æ', "Ccedil" => 'Ç', + "Egrave" => 'È', "Eacute" => 'É', "Ecirc" => 'Ê', "Euml" => 'Ë', + "Igrave" => 'Ì', "Iacute" => 'Í', "Icirc" => 'Î', "Iuml" => 'Ï', + "ETH" => 'Ð', "Ntilde" => 'Ñ', "Ograve" => 'Ò', "Oacute" => 'Ó', + "Ocirc" => 'Ô', "Otilde" => 'Õ', "Ouml" => 'Ö', "times" => '×', + "Oslash" => 'Ø', "Ugrave" => 'Ù', "Uacute" => 'Ú', "Ucirc" => 'Û', + "Uuml" => 'Ü', "Yacute" => 'Ý', "THORN" => 'Þ', "szlig" => 'ß', + "agrave" => 'à', "aacute" => 'á', "acirc" => 'â', "atilde" => 'ã', + "auml" => 'ä', "aring" => 'å', "aelig" => 'æ', "ccedil" => 'ç', + "egrave" => 'è', "eacute" => 'é', "ecirc" => 'ê', "euml" => 'ë', + "igrave" => 'ì', "iacute" => 'í', "icirc" => 'î', "iuml" => 'ï', + "eth" => 'ð', "ntilde" => 'ñ', "ograve" => 'ò', "oacute" => 'ó', + "ocirc" => 'ô', "otilde" => 'õ', "ouml" => 'ö', "divide" => '÷', + "oslash" => 'ø', "ugrave" => 'ù', "uacute" => 'ú', "ucirc" => 'û', + "uuml" => 'ü', "yacute" => 'ý', "thorn" => 'þ', "yuml" => 'ÿ', + + # HTML 4 entities that do not have 1:1 Latin1 mappings. + "bull" => "*", "hellip"=> "...", "prime" => "'", "Prime" => "\"", + "frasl" => "/", "trade" => "[tm]", "larr" => "<-", "rarr" => "->", + "harr" => "<->", "lArr" => "<=", "rArr" => "=>", "hArr" => "<=>", + "empty" => "Ø", "minus" => "-", "lowast"=> "*", "sim" => "~", + "cong" => "=~", "asymp" => "~", "ne" => "!=", "equiv" => "==", + "le" => "<=", "ge" => ">=", "lang" => "<", "rang" => ">", + "loz" => "<>", "OElig" => "OE", "oelig" => "oe", "Yuml" => "Y", + "circ" => "^", "tilde" => "~", "ensp" => " ", "emsp" => " ", + "thinsp"=> " ", "ndash" => "-", "mdash" => "--", "lsquo" => "`", + "rsquo" => "'", "sbquo" => "'", "ldquo" => "\"", "rdquo" => "\"", + "bdquo" => "\"", "lsaquo"=> "<", "rsaquo"=> ">", +); + + +############################################################################## +# +# Various global flags set by command line parameters, or computed +# +############################################################################## + + +my $current_state = "???"; # for diagnostics +my $load_method; +my $last_search; +my $image_succeeded = -1; +my $suppress_audit = 0; + +my $verbose_imgmap = 0; # print out rectangles and URLs only (stdout) +my $verbose_warnings = 0; # print out warnings when things go wrong +my $verbose_load = 0; # diagnostics about loading of URLs +my $verbose_filter = 0; # diagnostics about page selection/rejection +my $verbose_net = 0; # diagnostics about network I/O +my $verbose_pbm = 0; # diagnostics about PBM pipelines +my $verbose_http = 0; # diagnostics about all HTTP activity +my $verbose_exec = 0; # diagnostics about executing programs + +my $report_performance_interval = 60 * 15; # print some stats every 15 minutes + +my $http_proxy = undef; +my $http_timeout = 20; +my $cvt_timeout = 10; + +my $min_width = 50; +my $min_height = 50; +my $min_ratio = 1/5; + +my $min_gif_area = (120 * 120); + + +my $no_output_p = 0; +my $urls_only_p = 0; +my $cocoa_p = 0; +my $imagemap_base = undef; + +my @pids_to_kill = (); # forked pids we should kill when we exit, if any. + +my $driftnet_magic = 'driftnet'; +my $driftnet_dir = undef; +my $default_driftnet_cmd = "driftnet -a -m 100"; + +my $local_magic = 'local-directory'; +my $local_dir = undef; + +my $wordlist; + +my %rejected_urls; +my @tripwire_words = ("aberrate", "abode", "amorphous", "antioch", + "arrhenius", "arteriole", "blanket", "brainchild", + "burdensome", "carnival", "cherub", "chord", "clever", + "dedicate", "dilogarithm", "dolan", "dryden", + "eggplant"); + + +############################################################################## +# +# Retrieving URLs +# +############################################################################## + +# returns three values: the HTTP response line; the document headers; +# and the document body. +# +sub get_document_1($$$) { + my ($url, $referer, $timeout) = @_; + + if (!defined($timeout)) { $timeout = $http_timeout; } + if ($timeout > $http_timeout) { $timeout = $http_timeout; } + + if ($timeout <= 0) { + LOG (($verbose_net || $verbose_load), "timed out for $url"); + return (); + } + + LOG ($verbose_net, "get_document_1 $url " . ($referer ? $referer : "")); + + if (! ($url =~ m@^http://@i)) { + LOG ($verbose_net, "not an HTTP URL: $url"); + return (); + } + + my ($url_proto, $dummy, $serverstring, $path) = split(/\//, $url, 4); + $path = "" unless $path; + + if (!$url_proto || !$serverstring) { + LOG (($verbose_net || $verbose_load), "unparsable URL: $url"); + return (); + } + + my ($them,$port) = split(/:/, $serverstring); + $port = 80 unless $port; + + my $them2 = $them; + my $port2 = $port; + if ($http_proxy) { + $serverstring = $http_proxy if $http_proxy; + $serverstring =~ s@^[a-z]+://@@; + ($them2,$port2) = split(/:/, $serverstring); + $port2 = 80 unless $port2; + } + + my ($remote, $iaddr, $paddr, $proto, $line); + $remote = $them2; + if ($port2 =~ /\D/) { $port2 = getservbyname($port2, 'tcp') } + if (!$port2) { + LOG (($verbose_net || $verbose_load), "unrecognised port in $url"); + return (); + } + $iaddr = inet_aton($remote); + if (!$iaddr) { + LOG (($verbose_net || $verbose_load), "host not found: $remote"); + return (); + } + $paddr = sockaddr_in($port2, $iaddr); + + + my $head = ""; + my $body = ""; + + @_ = + eval { + local $SIG{ALRM} = sub { + LOG (($verbose_net || $verbose_load), "timed out ($timeout) for $url"); + die "alarm\n"; + }; + alarm $timeout; + + $proto = getprotobyname('tcp'); + if (!socket(S, PF_INET, SOCK_STREAM, $proto)) { + LOG (($verbose_net || $verbose_load), "socket: $!"); + return (); + } + if (!connect(S, $paddr)) { + LOG (($verbose_net || $verbose_load), "connect($serverstring): $!"); + return (); + } + + select(S); $| = 1; select(STDOUT); + + my $cookie = $cookies{$them}; + + my $user_agent = "$progname/$version"; + + if ($url =~ m@^http://www\.altavista\.com/@ || + $url =~ m@^http://random\.yahoo\.com/@ || + $url =~ m@^http://images\.google\.com/@ || + $url =~ m@^http://www\.google\.com/@) { + # block this, you turkeys. + $user_agent = "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.8.1.7)" . + " Gecko/20070914 Firefox/2.0.0.7"; + + # 28-Jun-2007: Google Images now emits the entire page in JS if + # you claim to be Gecko. They also still block "webcollage". + # They serve non-JS for unrecognised agents, so let's try this... + $user_agent = "NoJavascriptPlease/1.0" + if ($url =~ m@^http://[a-z]+\.google\.com/@); + } + + my $hdrs = "GET " . ($http_proxy ? $url : "/$path") . " HTTP/1.0\r\n" . + "Host: $them\r\n" . + "User-Agent: $user_agent\r\n"; + if ($referer) { + $hdrs .= "Referer: $referer\r\n"; + } + if ($cookie) { + my @cc = split(/\r?\n/, $cookie); + $hdrs .= "Cookie: " . join('; ', @cc) . "\r\n"; + } + $hdrs .= "\r\n"; + + foreach (split('\r?\n', $hdrs)) { + LOG ($verbose_http, " ==> $_"); + } + print S $hdrs; + my $http = || ""; + + # Kludge: the Yahoo Random Link is now returning as its first + # line "Status: 301" instead of "HTTP/1.0 301 Found". Fix it... + # + $http =~ s@^Status:\s+(\d+)\b@HTTP/1.0 $1@i; + + $_ = $http; + s/[\r\n]+$//s; + LOG ($verbose_http, " <== $_"); + + while () { + $head .= $_; + s/[\r\n]+$//s; + last if m@^$@; + LOG ($verbose_http, " <== $_"); + + if (m@^Set-cookie:\s*([^;\r\n]+)@i) { + set_cookie($them, $1) + } + } + + my $lines = 0; + while () { + $body .= $_; + $lines++; + } + + LOG ($verbose_http, + " <== [ body ]: $lines lines, " . length($body) . " bytes"); + + close S; + + if (!$http) { + LOG (($verbose_net || $verbose_load), "null response: $url"); + return (); + } + + $SIG{ALRM} = 'DEFAULT'; # seem to be suffering a race? + return ( $http, $head, $body ); + }; + die if ($@ && $@ ne "alarm\n"); # propagate errors + + if ($@ && $@ ne "alarm\n") { + print STDERR blurb() . "DIE " . join(" ", $@) . "\n"; + die; + } + + if ($@) { + # timed out + $head = undef; + $body = undef; + $suppress_audit = 1; + return (); + } else { + # didn't + alarm 0; + return @_; + } +} + + +# returns two values: the document headers; and the document body. +# if the given URL did a redirect, returns the redirected-to document. +# +sub get_document($$;$) { + my ($url, $referer, $timeout) = @_; + my $start = time; + + if (defined($referer) && $referer eq $driftnet_magic) { + return get_driftnet_file ($url); + } + + if (defined($referer) && $referer eq $local_magic) { + return get_local_file ($url); + } + + my $orig_url = $url; + my $loop_count = 0; + my $max_loop_count = 4; + + do { + if (defined($timeout) && $timeout <= 0) { + LOG (($verbose_net || $verbose_load), "timed out for $url"); + $suppress_audit = 1; + return (); + } + + my ( $http, $head, $body ) = get_document_1 ($url, $referer, $timeout); + + if (defined ($timeout)) { + my $now = time; + my $elapsed = $now - $start; + $timeout -= $elapsed; + $start = $now; + } + + return () unless $http; # error message already printed + + $http =~ s/[\r\n]+$//s; + + if ( $http =~ m@^HTTP/[0-9.]+ 30[123]@ ) { + $_ = $head; + + my ( $location ) = m@^location:[ \t]*(.*)$@im; + if ( $location ) { + $location =~ s/[\r\n]$//; + + LOG ($verbose_net, "redirect from $url to $location"); + $referer = $url; + $url = $location; + + if ($url =~ m@^/@) { + $referer =~ m@^(http://[^/]+)@i; + $url = $1 . $url; + } elsif (! ($url =~ m@^[a-z]+:@i)) { + $_ = $referer; + s@[^/]+$@@g if m@^http://[^/]+/@i; + $_ .= "/" if m@^http://[^/]+$@i; + $url = $_ . $url; + } + + } else { + LOG ($verbose_net, "no Location with \"$http\""); + return ( $url, $body ); + } + + if ($loop_count++ > $max_loop_count) { + LOG ($verbose_net, + "too many redirects ($max_loop_count) from $orig_url"); + $body = undef; + return (); + } + + } elsif ( $http =~ m@^HTTP/[0-9.]+ ([4-9][0-9][0-9].*)$@ ) { + + LOG (($verbose_net || $verbose_load), "failed: $1 ($url)"); + + # http errors -- return nothing. + $body = undef; + return (); + + } elsif (!$body) { + + LOG (($verbose_net || $verbose_load), "document contains no data: $url"); + return (); + + } else { + + # ok! + return ( $url, $body ); + } + + } while (1); +} + +# If we already have a cookie defined for this site, and the site is trying +# to overwrite that very same cookie, let it do so. This is because nytimes +# expires its cookies - it lets you upgrade to a new cookie without logging +# in again, but you have to present the old cookie to get the new cookie. +# So, by doing this, the built-in cypherpunks cookie will never go "stale". +# +sub set_cookie($$) { + my ($host, $cookie) = @_; + my $oc = $cookies{$host}; + return unless $oc; + $_ = $oc; + my ($oc_name, $oc_value) = m@^([^= \t\r\n]+)=(.*)$@; + $_ = $cookie; + my ($nc_name, $nc_value) = m@^([^= \t\r\n]+)=(.*)$@; + + if ($oc_name eq $nc_name && + $oc_value ne $nc_value) { + $cookies{$host} = $cookie; + LOG ($verbose_net, "overwrote ${host}'s $oc_name cookie"); + } +} + + +############################################################################ +# +# Extracting image URLs from HTML +# +############################################################################ + +# given a URL and the body text at that URL, selects and returns a random +# image from it. returns () if no suitable images found. +# +sub pick_image_from_body($$) { + my ($url, $body) = @_; + + my $base = $url; + $_ = $url; + + # if there's at least one slash after the host, take off the last + # pathname component + if ( m@^http://[^/]+/@io ) { + $base =~ s@[^/]+$@@go; + } + + # if there are no slashes after the host at all, put one on the end. + if ( m@^http://[^/]+$@io ) { + $base .= "/"; + } + + $_ = $body; + + # strip out newlines, compress whitespace + s/[\r\n\t ]+/ /go; + + # nuke comments + s///go; + + + # There are certain web sites that list huge numbers of dictionary + # words in their bodies or in their tags (surprise! + # Porn sites tend not to be reputable!) + # + # I do not want webcollage to filter on content: I want it to select + # randomly from the set of images on the web. All the logic here for + # rejecting some images is really a set of heuristics for rejecting + # images that are not really images: for rejecting *text* that is in + # GIF/JPEG/PNG form. I don't want text, I want pictures, and I want + # the content of the pictures to be randomly selected from among all + # the available content. + # + # So, filtering out "dirty" pictures by looking for "dirty" keywords + # would be wrong: dirty pictures exist, like it or not, so webcollage + # should be able to select them. + # + # However, picking a random URL is a hard thing to do. The mechanism I'm + # using is to search for a selection of random words. This is not + # perfect, but works ok most of the time. The way it breaks down is when + # some URLs get precedence because their pages list *every word* as + # related -- those URLs come up more often than others. + # + # So, after we've retrieved a URL, if it has too many keywords, reject + # it. We reject it not on the basis of what those keywords are, but on + # the basis that by having so many, the page has gotten an unfair + # advantage against our randomizer. + # + my $trip_count = 0; + foreach my $trip (@tripwire_words) { + $trip_count++ if m/$trip/i; + } + + if ($trip_count >= $#tripwire_words - 2) { + LOG (($verbose_filter || $verbose_load), + "there is probably a dictionary in \"$url\": rejecting."); + $rejected_urls{$url} = -1; + $body = undef; + $_ = undef; + return (); + } + + + my @urls; + my %unique_urls; + + foreach (split(/ * 1000) { + LOG (($verbose_filter || $verbose_load), + "excessive keywords ($L bytes) in $url: rejecting."); + $rejected_urls{$url} = $L; + $body = undef; + $_ = undef; + return (); + } else { + LOG ($verbose_filter, " keywords ($L bytes) in $url (ok)"); + } + + } elsif (m/^ (IMG|A) \b .* (SRC|HREF) \s* = \s* ["']? (.*?) [ "'<>] /six || + m/^ (LINK|META) \b .* (REL|PROPERTY) \s* = \s* + ["']? (image_src|og:image) ["']? /six) { + + my $was_inline = (lc($1) eq 'img'); + my $was_meta = (lc($1) eq 'link' || lc($1) eq 'meta'); + my $link = $3; + + # For + # and + # + if ($was_meta) { + next unless (m/ (HREF|CONTENT) \s* = \s* ["']? (.*?) [ "'<>] /six); + $link = $2; + } + + my ( $width ) = m/width ?=[ \"]*(\d+)/oi; + my ( $height ) = m/height ?=[ \"]*(\d+)/oi; + $_ = $link; + + if ( m@^/@o ) { + my $site; + ( $site = $base ) =~ s@^(http://[^/]*).*@$1@gio; + $_ = "$site$link"; + } elsif ( ! m@^[^/:?]+:@ ) { + $_ = "$base$link"; + s@/\./@/@g; + 1 while (s@/[^/]+/\.\./@/@g); + } + + # skip non-http + if ( ! m@^http://@io ) { + next; + } + + # skip non-image + if ( ! m@[.](gif|jpg|jpeg|pjpg|pjpeg|png)$@io ) { + next; + } + + # skip really short or really narrow images + if ( $width && $width < $min_width) { + if (!$height) { $height = "?"; } + LOG ($verbose_filter, " skip narrow image $_ (${width}x$height)"); + next; + } + + if ( $height && $height < $min_height) { + if (!$width) { $width = "?"; } + LOG ($verbose_filter, " skip short image $_ (${width}x$height)"); + next; + } + + # skip images with ratios that make them look like banners. + if ($min_ratio && $width && $height && + ($width * $min_ratio ) > $height) { + if (!$height) { $height = "?"; } + LOG ($verbose_filter, " skip bad ratio $_ (${width}x$height)"); + next; + } + + # skip GIFs with a small number of pixels -- those usually suck. + if ($width && $height && + m/\.gif$/io && + ($width * $height) < $min_gif_area) { + LOG ($verbose_filter, " skip small GIF $_ (${width}x$height)"); + next; + } + + # skip images with a URL that indicates a Yahoo thumbnail. + if (m@\.yimg\.com/.*/t/@) { + if (!$width) { $width = "?"; } + if (!$height) { $height = "?"; } + LOG ($verbose_filter, " skip yahoo thumb $_ (${width}x$height)"); + next; + } + + my $url = $_; + + if ($unique_urls{$url}) { + LOG ($verbose_filter, " skip duplicate image $_"); + next; + } + + LOG ($verbose_filter, + " image $url" . + ($width && $height ? " (${width}x${height})" : "") . + ($was_meta ? " (meta)" : $was_inline ? " (inline)" : "")); + + + my $weight = 1; + + if ($was_meta) { + $weight = 20; # meta tag images are far preferable to inline images. + } else { + if ($url !~ m@[.](gif|png)$@io ) { + $weight += 2; # JPEGs are preferable to GIFs and PNGs. + } + if (! $was_inline) { + $weight += 4; # pointers to images are preferable to inlined images. + } + } + + $unique_urls{$url}++; + for (my $i = 0; $i < $weight; $i++) { + $urls[++$#urls] = $url; + } + } + } + + my $fsp = ($body =~ m@([^<>]+)@i); + $base = $url unless $base; + + # pick a random element of the table + if (@suitable) { + my $i = int(rand(scalar @suitable)); + my $url = $suitable[$i]; + LOG ($verbose_load, "picked image " .($i+1) . "/" . + ($#suitable+1) . ": $url"); + return ($base, $url); + } + return; +} + + +############################################################################ +# +# Subroutines for getting pages and images out of search engines +# +############################################################################ + + +sub pick_dictionary() { + my @dicts = ("/usr/dict/words", + "/usr/share/dict/words", + "/usr/share/lib/dict/words", + "/usr/share/dict/cracklib-small", + "/usr/share/dict/cracklib-words" + ); + foreach my $f (@dicts) { + if (-f $f) { + $wordlist = $f; + last; + } + } + error ("$dicts[0] does not exist") unless defined($wordlist); +} + +# returns a random word from the dictionary +# +sub random_word() { + + return undef unless open (my $in, '<', $wordlist); + + my $size = (stat($in))[7]; + my $word = undef; + my $count = 0; + + while (1) { + error ("looping ($count) while reading $wordlist") + if (++$count > 100); + + my $pos = int (rand ($size)); + if (seek ($in, $pos, 0)) { + $word = <$in>; # toss partial line + $word = <$in>; # keep next line + } + + next unless ($word); + next if ($word =~ m/^[-\']/); + + $word = lc($word); + $word =~ s/^.*-//s; + $word =~ s/^[^a-z]+//s; + $word =~ s/[^a-z]+$//s; + $word =~ s/\'s$//s; + $word =~ s/ys$/y/s; + $word =~ s/ally$//s; + $word =~ s/ly$//s; + $word =~ s/ies$/y/s; + $word =~ s/ally$/al/s; + $word =~ s/izes$/ize/s; + $word =~ s/esses$/ess/s; + $word =~ s/(.{5})ing$/$1/s; + + next if (length ($word) > 14); + last if ($word); + } + + close ($in); + + if ( $word =~ s/\s/\+/gs ) { # convert intra-word spaces to "+". + $word = "\%22$word\%22"; # And put quotes (%22) around it. + } + + return $word; +} + + +sub random_words($) { + my ($sep) = @_; + return (random_word() . $sep . + random_word() . $sep . + random_word() . $sep . + random_word() . $sep . + random_word()); +} + + +sub url_quote($) { + my ($s) = @_; + $s =~ s|([^-a-zA-Z0-9.\@/_\r\n])|sprintf("%%%02X", ord($1))|ge; + return $s; +} + +sub url_unquote($) { + my ($s) = @_; + $s =~ s/[+]/ /g; + $s =~ s/%([a-z0-9]{2})/chr(hex($1))/ige; + return $s; +} + +sub html_quote($) { + my ($s) = @_; + $s =~ s/&/&/gi; + $s =~ s//>/gi; + $s =~ s/\"/"/gi; + return $s; +} + +sub html_unquote($) { + my ($s) = @_; + $s =~ s/(&([a-z]+);)/{ $entity_table{$2} || $1; }/gexi; # e.g., ' + $s =~ s/(&\#(\d+);)/{ chr($2) }/gexi; # e.g., ' + return $s; +} + + +# Loads the given URL (a search on some search engine) and returns: +# - the total number of hits the search engine claimed it had; +# - a list of URLs from the page that the search engine returned; +# Note that this list contains all kinds of internal search engine +# junk URLs too -- caller must prune them. +# +sub pick_from_search_engine($$$) { + my ( $timeout, $search_url, $words ) = @_; + + $_ = $words; + s/%20/ /g; + + print STDERR "\n\n" if ($verbose_load); + + LOG ($verbose_load, "words: $_"); + LOG ($verbose_load, "URL: $search_url"); + + $last_search = $search_url; # for warnings + + my $start = time; + my ( $base, $body ) = get_document ($search_url, undef, $timeout); + if (defined ($timeout)) { + $timeout -= (time - $start); + if ($timeout <= 0) { + $body = undef; + LOG (($verbose_net || $verbose_load), + "timed out (late) for $search_url"); + $suppress_audit = 1; + return (); + } + } + + return () if (! $body); + + + my @subpages; + + my $search_count = "?"; + if ($body =~ m@found (approximately |about )?()?(\d+)()? image@) { + $search_count = $3; + } elsif ($body =~ m@((\d{1,3})(,\d{3})*) @i) { + $search_count = $1; + } elsif ($body =~ m@found ((\d{1,3})(,\d{3})*|\d+) Web p@) { + $search_count = $1; + } elsif ($body =~ m@found about ((\d{1,3})(,\d{3})*|\d+) results@) { + $search_count = $1; + } elsif ($body =~ m@\b\d+ - \d+ of (\d+)\b@i) { # avimages + $search_count = $1; + } elsif ($body =~ m@About ((\d{1,3})(,\d{3})*) images@i) { # avimages + $search_count = $1; + } elsif ($body =~ m@We found ((\d{1,3})(,\d{3})*|\d+) results@i) { # *vista + $search_count = $1; + } elsif ($body =~ m@ of about ((\d{1,3})(,\d{3})*)<@i) { # googleimages + $search_count = $1; + } elsif ($body =~ m@((\d{1,3})(,\d{3})*) Web sites were found@i) { + $search_count = $1; # lycos + } elsif ($body =~ m@WEB.*?RESULTS.*?\b((\d{1,3})(,\d{3})*)\b.*?Matches@i) { + $search_count = $1; # hotbot + } elsif ($body =~ m@no photos were found containing@i) { # avimages + $search_count = "0"; + } elsif ($body =~ m@found no document matching@i) { # avtext + $search_count = "0"; + } + 1 while ($search_count =~ s/^(\d+)(\d{3})/$1,$2/); + +# if ($search_count eq "?" || $search_count eq "0") { +# my $file = "/tmp/wc.html"; +# open (my $out, '>', $file) || error ("writing $file: $!"); +# print $out $body; +# close $out; +# print STDERR blurb() . "###### wrote $file\n"; +# } + + + my $length = length($body); + my $href_count = 0; + + $_ = $body; + + s/[\r\n\t ]+/ /g; + + + s/(
]+)>@i; + next unless $u; + + if ($u =~ m/^\"([^\"]*)\"/) { $u = $1; } # quoted string + elsif ($u =~ m/^([^\s]*)\s/) { $u = $1; } # or token + + if ( $rejected_urls{$u} ) { + LOG ($verbose_filter, " pre-rejecting candidate: $u"); + next; + } + + LOG ($verbose_http, " HREF: $u"); + + $subpages[++$#subpages] = $u; + } + + if ( $#subpages < 0 ) { + LOG ($verbose_filter, + "found nothing on $base ($length bytes, $href_count links)."); + return (); + } + + LOG ($verbose_filter, "" . $#subpages+1 . " links on $search_url"); + + return ($search_count, @subpages); +} + + +sub depoison(@) { + my (@urls) = @_; + my @urls2 = (); + foreach (@urls) { + my ($h) = m@^http://([^/: \t\r\n]+)@i; + + next unless defined($h); + + if ($poisoners{$h}) { + LOG (($verbose_filter), " rejecting poisoner: $_"); + next; + } + if ($h =~ m@([^.]+\.[^.]+\.[^.]+)$@ && + $poisoners{$1}) { + LOG (($verbose_filter), " rejecting poisoner: $_"); + next; + } + if ($h =~ m@([^.]+\.[^.]+)$@ && + $poisoners{$1}) { + LOG (($verbose_filter), " rejecting poisoner: $_"); + next; + } + + push @urls2, $_; + } + return @urls2; +} + + +# given a list of URLs, picks one at random; loads it; and returns a +# random image from it. +# returns the url of the page loaded; the url of the image chosen. +# +sub pick_image_from_pages($$$$@) { + my ($base, $total_hit_count, $unfiltered_link_count, $timeout, @pages) = @_; + + $total_hit_count = "?" unless defined($total_hit_count); + + @pages = depoison (@pages); + LOG ($verbose_load, + "" . ($#pages+1) . " candidates of $unfiltered_link_count links" . + " ($total_hit_count total)"); + + return () if ($#pages < 0); + + my $i = int(rand($#pages+1)); + my $page = $pages[$i]; + + LOG ($verbose_load, "picked page $page"); + + $suppress_audit = 1; + + my ( $base2, $body2 ) = get_document ($page, $base, $timeout); + + if (!$base2 || !$body2) { + $body2 = undef; + return (); + } + + my $img = pick_image_from_body ($base2, $body2); + $body2 = undef; + + if ($img) { + return ($base2, $img); + } else { + return (); + } +} + + +############################################################################ +# +# Pick images from random pages returned by the Yahoo Random Link +# +############################################################################ + +# yahoorand +my $yahoo_random_link = "http://random.yahoo.com/fast/ryl"; + + +# Picks a random page; picks a random image on that page; +# returns two URLs: the page containing the image, and the image. +# Returns () if nothing found this time. +# +sub pick_from_yahoo_random_link($) { + my ($timeout) = @_; + + print STDERR "\n\n" if ($verbose_load); + LOG ($verbose_load, "URL: $yahoo_random_link"); + + $last_search = $yahoo_random_link; # for warnings + + $suppress_audit = 1; + + my ( $base, $body ) = get_document ($yahoo_random_link, undef, $timeout); + if (!$base || !$body) { + $body = undef; + return; + } + + LOG ($verbose_load, "redirected to: $base"); + + my $img = pick_image_from_body ($base, $body); + $body = undef; + + if ($img) { + return ($base, $img); + } else { + return (); + } +} + + +############################################################################ +# +# Pick images from random pages returned by the Alta Vista Random Link +# Note: this seems to have gotten a *lot* less random lately (2007). +# +############################################################################ + +# altavista +my $alta_vista_random_link = "http://www.altavista.com/image/randomlink"; + + +# Picks a random page; picks a random image on that page; +# returns two URLs: the page containing the image, and the image. +# Returns () if nothing found this time. +# +sub pick_from_alta_vista_random_link($) { + my ($timeout) = @_; + + print STDERR "\n\n" if ($verbose_load); + LOG ($verbose_load, "URL: $alta_vista_random_link"); + + $last_search = $alta_vista_random_link; # for warnings + + $suppress_audit = 1; + + my ( $base, $body ) = get_document ($alta_vista_random_link, + undef, $timeout); + if (!$base || !$body) { + $body = undef; + return; + } + + LOG ($verbose_load, "redirected to: $base"); + + my $img = pick_image_from_body ($base, $body); + $body = undef; + + if ($img) { + return ($base, $img); + } else { + return (); + } +} + + +############################################################################ +# +# Pick images by feeding random words into Alta Vista Image Search +# +############################################################################ + + +my $alta_vista_images_url = "http://www.altavista.com/image/results" . + "?ipht=1" . # photos + "&igrph=1" . # graphics + "&iclr=1" . # color + "&ibw=1" . # b&w + "&micat=1" . # no partner sites + "&sc=on" . # "site collapse" + "&q="; + +# avimages +sub pick_from_alta_vista_images($) { + my ($timeout) = @_; + + my $words = random_word(); + my $page = (int(rand(9)) + 1); + my $search_url = $alta_vista_images_url . $words; + + if ($page > 1) { + $search_url .= "&pgno=" . $page; # page number + $search_url .= "&stq=" . (($page-1) * 12); # first hit result on page + } + + my ($search_hit_count, @subpages) = + pick_from_search_engine ($timeout, $search_url, $words); + + my @candidates = (); + foreach my $u (@subpages) { + + # avimages is encoding their URLs now. + next unless ($u =~ s/^.*\*\*(http%3a.*$)/$1/gsi); + $u = url_unquote($u); + + next unless ($u =~ m@^http://@i); # skip non-HTTP or relative URLs + next if ($u =~ m@[/.]altavista\.com\b@i); # skip altavista builtins + next if ($u =~ m@[/.]yahoo\.com\b@i); # yahoo and av in cahoots? + next if ($u =~ m@[/.]doubleclick\.net\b@i); # you cretins + next if ($u =~ m@[/.]clicktomarket\.com\b@i); # more cretins + + next if ($u =~ m@[/.]viewimages\.com\b@i); # stacked deck + next if ($u =~ m@[/.]gettyimages\.com\b@i); + + LOG ($verbose_filter, " candidate: $u"); + push @candidates, $u; + } + + return pick_image_from_pages ($search_url, $search_hit_count, $#subpages+1, + $timeout, @candidates); +} + + + +############################################################################ +# +# Pick images from Aptix security cameras +# Cribbed liberally from google image search code. +# By Jason Sullivan +# +############################################################################ + +my $aptix_images_url = ("http://www.google.com/search" . + "?q=inurl:%22jpg/image.jpg%3Fr%3D%22"); + +# securitycam +sub pick_from_security_camera($) { + my ($timeout) = @_; + + my $page = (int(rand(9)) + 1); + my $num = 20; # 20 images per page + my $search_url = $aptix_images_url; + + if ($page > 1) { + $search_url .= "&start=" . $page*$num; # page number + $search_url .= "&num=" . $num; #images per page + } + + my ($search_hit_count, @subpages) = + pick_from_search_engine ($timeout, $search_url, ''); + + my @candidates = (); + my %referers; + foreach my $u (@subpages) { + next if ($u =~ m@[/.]google\.com\b@i); # skip google builtins (most links) + next unless ($u =~ m@jpg/image.jpg\?r=@i); # All pics contain this + + LOG ($verbose_filter, " candidate: $u"); + push @candidates, $u; + $referers{$u} = $u; + } + + @candidates = depoison (@candidates); + return () if ($#candidates < 0); + my $i = int(rand($#candidates+1)); + my $img = $candidates[$i]; + my $ref = $referers{$img}; + + LOG ($verbose_load, "picked image " . ($i+1) . ": $img (on $ref)"); + return ($ref, $img); +} + + +############################################################################ +# +# Pick images by feeding random words into Google Image Search. +# By Charles Gales +# +############################################################################ + + +my $google_images_url = "http://images.google.com/images" . + "?site=images" . # photos + "&btnG=Search" . # graphics + "&safe=off" . # no screening + "&imgsafe=off" . + "&q="; + +# googleimgs +sub pick_from_google_images($;$$) { + my ($timeout, $words, $max_page) = @_; + + if (!defined($words)) { + $words = random_word(); # only one word for Google + } + + my $page = (int(rand(9)) + 1); + my $num = 20; # 20 images per page + my $search_url = $google_images_url . $words; + + if ($page > 1) { + $search_url .= "&start=" . $page*$num; # page number + $search_url .= "&num=" . $num; #images per page + } + + my ($search_hit_count, @subpages) = + pick_from_search_engine ($timeout, $search_url, $words); + + my @candidates = (); + my %referers; + foreach my $u (@subpages) { + next unless ($u =~ m@imgres\?imgurl@i); # All pics start with this + next if ($u =~ m@[/.]google\.com\b@i); # skip google builtins + + $u = html_unquote($u); + if ($u =~ m@^/imgres\?imgurl=(.*?)&imgrefurl=(.*?)\&@) { + my $ref = $2; + my $img = $1; + $img = "http://$img" unless ($img =~ m/^http:/i); + + $ref = url_decode($ref); + $img = url_decode($img); + + LOG ($verbose_filter, " candidate: $ref"); + push @candidates, $img; + $referers{$img} = $ref; + } + } + + @candidates = depoison (@candidates); + return () if ($#candidates < 0); + my $i = int(rand($#candidates+1)); + my $img = $candidates[$i]; + my $ref = $referers{$img}; + + LOG ($verbose_load, "picked image " . ($i+1) . ": $img (on $ref)"); + return ($ref, $img); +} + + + +############################################################################ +# +# Pick images by feeding random numbers into Google Image Search. +# By jwz, suggested by Ian O'Donnell. +# +############################################################################ + + +# googlenums +sub pick_from_google_image_numbers($) { + my ($timeout) = @_; + + my $max = 9999; + my $number = int(rand($max)); + + $number = sprintf("%04d", $number) + if (rand() < 0.3); + + pick_from_google_images ($timeout, "$number"); +} + + + +############################################################################ +# +# Pick images by feeding random digital camera file names into +# Google Image Search. +# By jwz, inspired by the excellent Random Personal Picture Finder +# at http://www.diddly.com/random/ +# +############################################################################ + +my @photomakers = ( + # + # Common digital camera file name formats, as described at + # http://www.diddly.com/random/about.html + # + sub { sprintf ("dcp%05d.jpg", int(rand(4000))); }, # Kodak + sub { sprintf ("dsc%05d.jpg", int(rand(4000))); }, # Nikon + sub { sprintf ("dscn%04d.jpg", int(rand(4000))); }, # Nikon + sub { sprintf ("mvc-%03d.jpg", int(rand(999))); }, # Sony Mavica + sub { sprintf ("mvc%05d.jpg", int(rand(9999))); }, # Sony Mavica + sub { sprintf ("P101%04d.jpg", int(rand(9999))); }, # Olympus w/ date=101 + sub { sprintf ("P%x%02d%04d.jpg", # Olympus + int(rand(0xC)), int(rand(30))+1, + rand(9999)); }, + sub { sprintf ("IMG_%03d.jpg", int(rand(999))); }, # ? + sub { sprintf ("IMAG%04d.jpg", int(rand(9999))); }, # RCA and Samsung + sub { my $n = int(rand(9999)); # Canon + sprintf ("1%02d-%04d.jpg", int($n/100), $n); }, + sub { my $n = int(rand(9999)); # Canon + sprintf ("1%02d-%04d_IMG.jpg", + int($n/100), $n); }, + sub { sprintf ("IMG_%04d.jpg", int(rand(9999))); }, # Canon + sub { sprintf ("dscf%04d.jpg", int(rand(9999))); }, # Fuji Finepix + sub { sprintf ("pdrm%04d.jpg", int(rand(9999))); }, # Toshiba PDR + sub { sprintf ("IM%06d.jpg", int(rand(9999))); }, # HP Photosmart + sub { sprintf ("EX%06d.jpg", int(rand(9999))); }, # HP Photosmart +# sub { my $n = int(rand(3)); # Kodak DC-40,50,120 +# sprintf ("DC%04d%s.jpg", int(rand(9999)), +# $n == 0 ? 'S' : $n == 1 ? 'M' : 'L'); }, + sub { sprintf ("pict%04d.jpg", int(rand(9999))); }, # Minolta Dimage + sub { sprintf ("P%07d.jpg", int(rand(9999))); }, # Kodak DC290 +# sub { sprintf ("%02d%02d%04d.jpg", # Casio QV3000, QV4000 +# int(rand(12))+1, int(rand(31))+1, +# int(rand(999))); }, +# sub { sprintf ("%02d%x%02d%04d.jpg", # Casio QV7000 +# int(rand(6)), # year +# int(rand(12))+1, int(rand(31))+1, +# int(rand(999))); }, + sub { sprintf ("IMGP%04d.jpg", int(rand(9999))); }, # Pentax Optio S + sub { sprintf ("PANA%04d.jpg", int(rand(9999))); }, # Panasonic vid still + sub { sprintf ("HPIM%04d.jpg", int(rand(9999))); }, # HP Photosmart + sub { sprintf ("PCDV%04d.jpg", int(rand(9999))); }, # ? + ); + + +# googlephotos +sub pick_from_google_image_photos($) { + my ($timeout) = @_; + + my $i = int(rand($#photomakers + 1)); + my $fn = $photomakers[$i]; + my $file = &$fn; + my $words .= $file . "%20filetype:jpg"; + + pick_from_google_images ($timeout, $words); +} + + + +############################################################################ +# +# Pick images by feeding random words into Alta Vista Text Search +# +############################################################################ + + +my $alta_vista_url = "http://www.altavista.com/web/results" . + "?pg=aq" . + "&aqmode=s" . + "&filetype=html" . + "&sc=on" . # "site collapse" + "&nbq=50" . + "&aqo="; + +# avtext +sub pick_from_alta_vista_text($) { + my ($timeout) = @_; + + my $words = random_words('%20'); + my $page = (int(rand(9)) + 1); + my $search_url = $alta_vista_url . $words; + + if ($page > 1) { + $search_url .= "&pgno=" . $page; + $search_url .= "&stq=" . (($page-1) * 10); + } + + my ($search_hit_count, @subpages) = + pick_from_search_engine ($timeout, $search_url, $words); + + my @candidates = (); + foreach my $u (@subpages) { + + # Those altavista fuckers are playing really nasty redirection games + # these days: the filter your clicks through their site, but use + # onMouseOver to make it look like they're not! Well, it makes it + # easier for us to identify search results... + # + next unless ($u =~ s/^.*\*\*(http%3a.*$)/$1/gsi); + $u = url_unquote($u); + + next unless ($u =~ m@^http://@i); # skip non-HTTP or relative URLs + next if ($u =~ m@[/.]altavista\.com\b@i); # skip altavista builtins + next if ($u =~ m@[/.]yahoo\.com\b@i); # yahoo and av in cahoots? + + LOG ($verbose_filter, " candidate: $u"); + push @candidates, $u; + } + + return pick_image_from_pages ($search_url, $search_hit_count, $#subpages+1, + $timeout, @candidates); +} + + + +############################################################################ +# +# Pick images by feeding random words into Hotbot +# +############################################################################ + +my $hotbot_search_url =("http://hotbot.lycos.com/default.asp" . + "?ca=w" . + "&descriptiontype=0" . + "&imagetoggle=1" . + "&matchmode=any" . + "&nummod=2" . + "&recordcount=50" . + "&sitegroup=1" . + "&stem=1" . + "&cobrand=undefined" . + "&query="); + +sub pick_from_hotbot_text($) { + my ($timeout) = @_; + + $last_search = $hotbot_search_url; # for warnings + + # lycos seems to always give us back dictionaries and word lists if + # we search for more than one word... + # + my $words = random_word(); + + my $start = int(rand(8)) * 10 + 1; + my $search_url = $hotbot_search_url . $words . "&first=$start&page=more"; + + my ($search_hit_count, @subpages) = + pick_from_search_engine ($timeout, $search_url, $words); + + my @candidates = (); + foreach my $u (@subpages) { + + # Hotbot plays redirection games too + # (not any more?) +# next unless ($u =~ m@/director.asp\?.*\btarget=([^&]+)@); +# $u = url_decode($1); + + next unless ($u =~ m@^http://@i); # skip non-HTTP or relative URLs + next if ($u =~ m@[/.]hotbot\.com\b@i); # skip hotbot builtins + next if ($u =~ m@[/.]lycos\.com\b@i); # skip hotbot builtins + next if ($u =~ m@[/.]inktomi\.com\b@i); # skip hotbot builtins + + LOG ($verbose_filter, " candidate: $u"); + push @candidates, $u; + } + + return pick_image_from_pages ($search_url, $search_hit_count, $#subpages+1, + $timeout, @candidates); +} + + + +############################################################################ +# +# Pick images by feeding random words into Lycos +# +############################################################################ + +my $lycos_search_url = "http://search.lycos.com/default.asp" . + "?lpv=1" . + "&loc=searchhp" . + "&tab=web" . + "&query="; + +sub pick_from_lycos_text($) { + my ($timeout) = @_; + + $last_search = $lycos_search_url; # for warnings + + # lycos seems to always give us back dictionaries and word lists if + # we search for more than one word... + # + my $words = random_word(); + + my $start = int(rand(8)) * 10 + 1; + my $search_url = $lycos_search_url . $words . "&first=$start&page=more"; + + my ($search_hit_count, @subpages) = + pick_from_search_engine ($timeout, $search_url, $words); + + my @candidates = (); + foreach my $u (@subpages) { + + # Lycos plays redirection games. + # (not any more?) +# next unless ($u =~ m@^http://click.lycos.com/director.asp +# .* +# \btarget=([^&]+) +# .* +# @x); +# $u = url_decode($1); + + next unless ($u =~ m@^http://@i); # skip non-HTTP or relative URLs + next if ($u =~ m@[/.]hotbot\.com\b@i); # skip lycos builtins + next if ($u =~ m@[/.]lycos\.com\b@i); # skip lycos builtins + next if ($u =~ m@[/.]terralycos\.com\b@i); # skip lycos builtins + next if ($u =~ m@[/.]inktomi\.com\b@i); # skip lycos builtins + + + LOG ($verbose_filter, " candidate: $u"); + push @candidates, $u; + } + + return pick_image_from_pages ($search_url, $search_hit_count, $#subpages+1, + $timeout, @candidates); +} + + + +############################################################################ +# +# Pick images by feeding random words into news.yahoo.com +# +############################################################################ + +my $yahoo_news_url = "http://news.search.yahoo.com/search/news" . + "?c=news_photos" . + "&p="; + +# yahoonews +sub pick_from_yahoo_news_text($) { + my ($timeout) = @_; + + $last_search = $yahoo_news_url; # for warnings + + my $words = random_word(); + my $search_url = $yahoo_news_url . $words; + + my ($search_hit_count, @subpages) = + pick_from_search_engine ($timeout, $search_url, $words); + + my @candidates = (); + foreach my $u (@subpages) { + + # de-redirectize the URLs + $u =~ s@^http://rds\.yahoo\.com/.*-http%3A@http:@s; + + # only accept URLs on Yahoo's news site + next unless ($u =~ m@^http://dailynews\.yahoo\.com/@i || + $u =~ m@^http://story\.news\.yahoo\.com/@i); + next unless ($u =~ m@&u=/@); + + LOG ($verbose_filter, " candidate: $u"); + push @candidates, $u; + } + + return pick_image_from_pages ($search_url, $search_hit_count, $#subpages+1, + $timeout, @candidates); +} + + + +############################################################################ +# +# Pick images from LiveJournal's list of recently-posted images. +# +############################################################################ + +my $livejournal_img_url = "http://www.livejournal.com/stats/latest-img.bml"; + +# With most of our image sources, we get a random page and then select +# from the images on it. However, in the case of LiveJournal, the page +# of images tends to update slowly; so we'll remember the last N entries +# on it and randomly select from those, to get a wider variety each time. + +my $lj_cache_size = 1000; +my @lj_cache = (); # fifo, for ordering by age +my %lj_cache = (); # hash, for detecting dups + +# livejournal +sub pick_from_livejournal_images($) { + my ($timeout) = @_; + + $last_search = $livejournal_img_url; # for warnings + + my ( $base, $body ) = get_document ($livejournal_img_url, undef, $timeout); + return () unless $body; + + $body =~ s/\n/ /gs; + $body =~ s/(= $lj_cache_size) { + my $pairP = shift @lj_cache; + my $img = $pairP->[0]; + delete $lj_cache{$img}; + } + + LOG ($verbose_load, "picked image " .($i+1) . "/$n: $img"); + + return ($page, $img); +} + + +############################################################################ +# +# Pick images from ircimages.com (images that have been in the /topic of +# various IRC channels.) +# +############################################################################ + +my $ircimages_url = "http://ircimages.com/"; + +# ircimages +sub pick_from_ircimages($) { + my ($timeout) = @_; + + $last_search = $ircimages_url; # for warnings + + my $n = int(rand(2900)); + my $search_url = $ircimages_url . "page-$n"; + + my ( $base, $body ) = get_document ($search_url, undef, $timeout); + return () unless $body; + + my @candidates = (); + + $body =~ s/\n/ /gs; + $body =~ s/(]+)>@i; + next unless $u; + + if ($u =~ m/^\"([^\"]*)\"/) { $u = $1; } # quoted string + elsif ($u =~ m/^([^\s]*)\s/) { $u = $1; } # or token + + next unless ($u =~ m/^http:/i); + next if ($u =~ m@^http://(searchirc\.com\|ircimages\.com)@i); + next unless ($u =~ m@[.](gif|jpg|jpeg|pjpg|pjpeg|png)$@i); + + LOG ($verbose_http, " HREF: $u"); + push @candidates, $u; + } + + LOG ($verbose_filter, "" . $#candidates+1 . " links on $search_url"); + + return () if ($#candidates == -1); + + my $i = int(rand($#candidates+1)); + my $img = $candidates[$i]; + + LOG ($verbose_load, "picked image " .($i+1) . "/" . ($#candidates+1) . + ": $img"); + + $search_url = $img; # hmm... + return ($search_url, $img); +} + + +############################################################################ +# +# Pick images from Twitpic's list of recently-posted images. +# +############################################################################ + +my $twitpic_img_url = "http://twitpic.com/public_timeline/feed.rss"; + +# With most of our image sources, we get a random page and then select +# from the images on it. However, in the case of Twitpic, the page +# of images tends to update slowly; so we'll remember the last N entries +# on it and randomly select from those, to get a wider variety each time. + +my $twitpic_cache_size = 1000; +my @twitpic_cache = (); # fifo, for ordering by age +my %twitpic_cache = (); # hash, for detecting dups + +# twitpic +sub pick_from_twitpic_images($) { + my ($timeout) = @_; + + $last_search = $twitpic_img_url; # for warnings + + my ( $base, $body ) = get_document ($twitpic_img_url, undef, $timeout); + + # Update the cache. + + if ($body) { + $body =~ s/\n/ /gs; + $body =~ s/(([^<>]*)@si); + my $page = html_unquote ($1); + + $page =~ s@/$@@s; + $page .= '/full'; + + next if ($twitpic_cache{$page}); # already have it + + LOG ($verbose_filter, " candidate: $page"); + push @twitpic_cache, $page; + $twitpic_cache{$page} = $page; + } + } + + # Pull from the cache. + + return () if ($#twitpic_cache == -1); + + my $n = $#twitpic_cache+1; + my $i = int(rand($n)); + my $page = $twitpic_cache[$i]; + + # delete this one from @twitpic_cache and from %twitpic_cache. + # + @twitpic_cache = ( @twitpic_cache[0 .. $i-1], + @twitpic_cache[$i+1 .. $#twitpic_cache] ); + delete $twitpic_cache{$page}; + + # Keep the size of the cache under the limit by nuking older entries + # + while ($#twitpic_cache >= $twitpic_cache_size) { + my $page = shift @twitpic_cache; + delete $twitpic_cache{$page}; + } + + ( $base, $body ) = get_document ($page, undef, $timeout); + my $img = undef; + $body = '' unless defined($body); + + foreach (split (/= $twitter_cache_size) { + my $page = shift @twitter_cache; + delete $twitter_cache{$page}; + } + + LOG ($verbose_load, "picked page $url"); + + $suppress_audit = 1; + + return ($page, $url); +} + + +############################################################################ +# +# Pick images from Flickr's page of recently-posted photos. +# +############################################################################ + +my $flickr_img_url = "http://www.flickr.com/photos/"; + +# Like LiveJournal, the Flickr page of images tends to update slowly, +# so remember the last N entries on it and randomly select from those. + +# I know that Flickr has an API (http://www.flickr.com/services/api/) +# but it was easy enough to scrape the HTML, so I didn't bother exploring. + +my $flickr_cache_size = 1000; +my @flickr_cache = (); # fifo, for ordering by age +my %flickr_cache = (); # hash, for detecting dups + + +# flickr_recent +sub pick_from_flickr_recent($) { + my ($timeout) = @_; + + my $start = 16 * int(rand(100)); + + $last_search = $flickr_img_url; # for warnings + $last_search .= "?start=$start" if ($start > 0); + + my ( $base, $body ) = get_document ($last_search, undef, $timeout); + return () unless $body; + + $body =~ s/[\r\n]/ /gs; + $body =~ s/(]* \b HREF=\"([^<>\"]+)\" [^<>]* > \s* + ]* \b SRC=\"([^<>\"]+)\" @xsi; + next unless defined ($thumb); + $page = html_unquote ($page); + $thumb = html_unquote ($thumb); + + next unless ($thumb =~ m@^http://farm\d*\.static\.?flickr\.com/@); + + my $base = "http://www.flickr.com/"; + $page =~ s@^/@$base@; + $thumb =~ s@^/@$base@; + + my $img = $thumb; + $img =~ s/_[a-z](\.[a-z\d]+)$/$1/si; # take off "thumb" suffix + + $count++; + next if ($flickr_cache{$img}); # already have it + + my @pair = ($img, $page, $start); + LOG ($verbose_filter, " candidate: $img"); + push @flickr_cache, \@pair; + $flickr_cache{$img} = \@pair; + $count2++; + } + + return () if ($#flickr_cache == -1); + + my $n = $#flickr_cache+1; + my $i = int(rand($n)); + my ($img, $page) = @{$flickr_cache[$i]}; + + # delete this one from @flickr_cache and from %flickr_cache. + # + @flickr_cache = ( @flickr_cache[0 .. $i-1], + @flickr_cache[$i+1 .. $#flickr_cache] ); + delete $flickr_cache{$img}; + + # Keep the size of the cache under the limit by nuking older entries + # + while ($#flickr_cache >= $flickr_cache_size) { + my $pairP = shift @flickr_cache; + my $img = $pairP->[0]; + delete $flickr_cache{$img}; + } + + LOG ($verbose_load, "picked image " .($i+1) . "/$n: $img"); + + return ($page, $img); +} + + +############################################################################ +# +# Pick images from a random RSS feed on Flickr. +# +############################################################################ + +my $flickr_rss_base = ("http://www.flickr.com/services/feeds/photos_public.gne". + "?format=rss_200_enc&tagmode=any&tags="); + +# Picks a random RSS feed; picks a random image from that feed; +# returns 2 URLs: the page containing the image, and the image. +# Mostly by Joe Mcmahon +# +# flickr_random +sub pick_from_flickr_random($) { + my $timeout = shift; + + my $words = random_words(','); + my $rss = $flickr_rss_base . $words; + $last_search = $rss; + + $_ = $words; + s/,/ /g; + + print STDERR "\n\n" if ($verbose_load); + LOG ($verbose_load, "words: $_"); + LOG ($verbose_load, "URL: $last_search"); + + $suppress_audit = 1; + + my ( $base, $body ) = get_document ($last_search, undef, $timeout); + if (!$base || !$body) { + $body = undef; + return; + } + + my $img; + ($base, $img) = pick_image_from_rss ($base, $body); + $body = undef; + return () unless defined ($img); + + LOG ($verbose_load, "redirected to: $base"); + return ($base, $img); +} + + +############################################################################ +# +# Pick images by waiting for driftnet to populate a temp dir with files. +# Requires driftnet version 0.1.5 or later. +# (Driftnet is a program by Chris Lightfoot that sniffs your local ethernet +# for images being downloaded by others.) +# Driftnet/webcollage integration by jwz. +# +############################################################################ + +# driftnet +sub pick_from_driftnet($) { + my ($timeout) = @_; + + my $id = $driftnet_magic; + my $dir = $driftnet_dir; + my $start = time; + my $now; + + error ("\$driftnet_dir unset?") unless ($dir); + $dir =~ s@/+$@@; + + error ("$dir unreadable") unless (-d "$dir/."); + + $timeout = $http_timeout unless ($timeout); + $last_search = $id; + + while ($now = time, $now < $start + $timeout) { + opendir (my $dir, $dir) || error ("$dir: $!"); + while (my $file = readdir($dir)) { + next if ($file =~ m/^\./); + $file = "$dir/$file"; + closedir ($dir); + LOG ($verbose_load, "picked file $file ($id)"); + return ($id, $file); + } + closedir ($dir); + } + LOG (($verbose_net || $verbose_load), "timed out for $id"); + return (); +} + + +sub get_driftnet_file($) { + my ($file) = @_; + + error ("\$driftnet_dir unset?") unless ($driftnet_dir); + + my $id = $driftnet_magic; + error ("$id: $file not in $driftnet_dir?") + unless ($file =~ m@^\Q$driftnet_dir@o); + + open (my $in, '<', $file) || error ("$id: $file: $!"); + my $body = ''; + local $/ = undef; # read entire file + $body = <$in>; + close ($in) || error ("$id: $file: $!"); + unlink ($file) || error ("$id: $file: rm: $!"); + return ($id, $body); +} + + +sub spawn_driftnet($) { + my ($cmd) = @_; + + # make a directory to use. + while (1) { + my $tmp = $ENV{TEMPDIR} || "/tmp"; + $driftnet_dir = sprintf ("$tmp/driftcollage-%08x", rand(0xffffffff)); + LOG ($verbose_exec, "mkdir $driftnet_dir"); + last if mkdir ($driftnet_dir, 0700); + } + + if (! ($cmd =~ m/\s/)) { + # if the command didn't have any arguments in it, then it must be just + # a pointer to the executable. Append the default args to it. + my $dargs = $default_driftnet_cmd; + $dargs =~ s/^[^\s]+//; + $cmd .= $dargs; + } + + # point the driftnet command at our newly-minted private directory. + # + $cmd .= " -d $driftnet_dir"; + $cmd .= ">/dev/null" unless ($verbose_exec); + + my $pid = fork(); + if ($pid < 0) { error ("fork: $!\n"); } + if ($pid) { + # parent fork + push @pids_to_kill, $pid; + LOG ($verbose_exec, "forked for \"$cmd\""); + } else { + # child fork + nontrapping_system ($cmd) || error ("exec: $!"); + } + + # wait a bit, then make sure the process actually started up. + # + sleep (1); + error ("pid $pid failed to start \"$cmd\"") + unless (1 == kill (0, $pid)); +} + +# local-directory +sub pick_from_local_dir($) { + my ($timeout) = @_; + + my $id = $local_magic; + $last_search = $id; + + my $dir = $local_dir; + error ("\$local_dir unset?") unless ($dir); + $dir =~ s@/+$@@; + + error ("$dir unreadable") unless (-d "$dir/."); + + my $v = ($verbose_exec ? "-v" : ""); + my $pick = `xscreensaver-getimage-file $v "$dir"`; + $pick =~ s/\s+$//s; + $pick = "$dir/$pick" unless ($pick =~ m@^/@s); # relative path + + LOG ($verbose_load, "picked file $pick ($id)"); + return ($id, $pick); +} + + +sub get_local_file($) { + my ($file) = @_; + + error ("\$local_dir unset?") unless ($local_dir); + + my $id = $local_magic; + error ("$id: $file not in $local_dir?") + unless ($file =~ m@^\Q$local_dir@o); + + open (my $in, '<', $file) || error ("$id: $file: $!"); + local $/ = undef; # read entire file + my $body = <$in>; + close ($in) || error ("$id: $file: $!"); + return ($id, $body); +} + + + +############################################################################ +# +# Pick a random image in a random way +# +############################################################################ + + +# Picks a random image on a random page, and returns two URLs: +# the page containing the image, and the image. +# Returns () if nothing found this time. +# + +sub pick_image(;$) { + my ($timeout) = @_; + + $current_state = "select"; + $load_method = "none"; + + my $n = int(rand(100)); + my $fn = undef; + my $total = 0; + my @rest = @search_methods; + + while (@rest) { + my $pct = shift @rest; + my $name = shift @rest; + my $tfn = shift @rest; + $total += $pct; + if ($total > $n && !defined($fn)) { + $fn = $tfn; + $current_state = $name; + $load_method = $current_state; + } + } + + if ($total != 100) { + error ("internal error: \@search_methods totals to $total%!"); + } + + record_attempt ($current_state); + return $fn->($timeout); +} + + + +############################################################################ +# +# Statistics and logging +# +############################################################################ + +sub timestr() { + return strftime ("%H:%M:%S: ", localtime); +} + +sub blurb() { + return "$progname: " . timestr() . "$current_state: "; +} + +sub error($) { + my ($err) = @_; + print STDERR blurb() . "$err\n"; + exit 1; +} + +sub stacktrace() { + my $i = 1; + print STDERR "$progname: stack trace:\n"; + while (1) { + my ($package, $filename, $line, $subroutine) = caller($i++); + last unless defined($package); + $filename =~ s@^.*/@@; + print STDERR " $filename#$line, $subroutine\n"; + } +} + + +my $lastlog = ""; + +sub clearlog() { + $lastlog = ""; +} + +sub showlog() { + my $head = "$progname: DEBUG: "; + foreach (split (/\n/, $lastlog)) { + print STDERR "$head$_\n"; + } + $lastlog = ""; +} + +sub LOG($$) { + my ($print, $msg) = @_; + my $blurb = timestr() . "$current_state: "; + $lastlog .= "$blurb$msg\n"; + print STDERR "$progname: $blurb$msg\n" if $print; +} + + +my %stats_attempts; +my %stats_successes; +my %stats_elapsed; + +my $last_state = undef; +sub record_attempt($) { + my ($name) = @_; + + if ($last_state) { + record_failure($last_state) unless ($image_succeeded > 0); + } + $last_state = $name; + + clearlog(); + report_performance(); + + start_timer($name); + $image_succeeded = 0; + $suppress_audit = 0; +} + +sub record_success($$$) { + my ($name, $url, $base) = @_; + if (defined($stats_successes{$name})) { + $stats_successes{$name}++; + } else { + $stats_successes{$name} = 1; + } + + stop_timer ($name, 1); + my $o = $current_state; + $current_state = $name; + save_recent_url ($url, $base); + $current_state = $o; + $image_succeeded = 1; + clearlog(); +} + + +sub record_failure($) { + my ($name) = @_; + + return if $image_succeeded; + + stop_timer ($name, 0); + if ($verbose_load && !$verbose_exec) { + + if ($suppress_audit) { + print STDERR "$progname: " . timestr() . "(audit log suppressed)\n"; + return; + } + + my $o = $current_state; + $current_state = "DEBUG"; + + my $line = "#" x 78; + print STDERR "\n\n\n"; + print STDERR ("#" x 78) . "\n"; + print STDERR blurb() . "failed to get an image. Full audit log:\n"; + print STDERR "\n"; + showlog(); + print STDERR ("-" x 78) . "\n"; + print STDERR "\n\n"; + + $current_state = $o; + } + $image_succeeded = 0; +} + + + +sub stats_of($) { + my ($name) = @_; + my $i = $stats_successes{$name}; + my $j = $stats_attempts{$name}; + $i = 0 unless $i; + $j = 0 unless $j; + return "" . ($j ? int($i * 100 / $j) : "0") . "%"; +} + + +my $current_start_time = 0; + +sub start_timer($) { + my ($name) = @_; + $current_start_time = time; + + if (defined($stats_attempts{$name})) { + $stats_attempts{$name}++; + } else { + $stats_attempts{$name} = 1; + } + if (!defined($stats_elapsed{$name})) { + $stats_elapsed{$name} = 0; + } +} + +sub stop_timer($$) { + my ($name, $success) = @_; + $stats_elapsed{$name} += time - $current_start_time; +} + + +my $last_report_time = 0; +sub report_performance() { + + return unless $verbose_warnings; + + my $now = time; + return unless ($now >= $last_report_time + $report_performance_interval); + my $ot = $last_report_time; + $last_report_time = $now; + + return if ($ot == 0); + + my $blurb = "$progname: " . timestr(); + + print STDERR "\n"; + print STDERR "${blurb}Current standings:\n"; + + foreach my $name (sort keys (%stats_attempts)) { + my $try = $stats_attempts{$name}; + my $suc = $stats_successes{$name} || 0; + my $pct = int($suc * 100 / $try); + my $secs = $stats_elapsed{$name}; + my $secs_link = $secs / $try; + print STDERR sprintf ("$blurb %-14s %4s (%d/%d);" . + " \t %.1f secs/link\n", + "$name:", "$pct%", $suc, $try, $secs_link); + } +} + + + +my $max_recent_images = 400; +my $max_recent_sites = 20; +my @recent_images = (); +my @recent_sites = (); + +sub save_recent_url($$) { + my ($url, $base) = @_; + + return unless ($verbose_warnings); + + $_ = $url; + my ($site) = m@^http://([^ \t\n\r/:]+)@; + return unless defined ($site); + + if ($base eq $driftnet_magic || $base eq $local_magic) { + $site = $base; + @recent_images = (); + } + + my $done = 0; + foreach (@recent_images) { + if ($_ eq $url) { + print STDERR blurb() . "WARNING: recently-duplicated image: $url" . + " (on $base via $last_search)\n"; + $done = 1; + last; + } + } + + # suppress "duplicate site" warning via %warningless_sites. + # + if ($warningless_sites{$site}) { + $done = 1; + } elsif ($site =~ m@([^.]+\.[^.]+\.[^.]+)$@ && + $warningless_sites{$1}) { + $done = 1; + } elsif ($site =~ m@([^.]+\.[^.]+)$@ && + $warningless_sites{$1}) { + $done = 1; + } + + if (!$done) { + foreach (@recent_sites) { + if ($_ eq $site) { + print STDERR blurb() . "WARNING: recently-duplicated site: $site" . + " ($url on $base via $last_search)\n"; + last; + } + } + } + + push @recent_images, $url; + push @recent_sites, $site; + shift @recent_images if ($#recent_images >= $max_recent_images); + shift @recent_sites if ($#recent_sites >= $max_recent_sites); +} + + + +############################################################################## +# +# other utilities +# +############################################################################## + +# Does %-decoding. +# +sub url_decode($) { + ($_) = @_; + tr/+/ /; + s/%([a-fA-F0-9][a-fA-F0-9])/pack("C", hex($1))/eg; + return $_; +} + + +# Given the raw body of a GIF document, returns the dimensions of the image. +# +sub gif_size($) { + my ($body) = @_; + my $type = substr($body, 0, 6); + my $s; + return () unless ($type =~ /GIF8[7,9]a/); + $s = substr ($body, 6, 10); + my ($a,$b,$c,$d) = unpack ("C"x4, $s); + return () unless defined ($d); + return (($b<<8|$a), ($d<<8|$c)); +} + +# Given the raw body of a JPEG document, returns the dimensions of the image. +# +sub jpeg_size($) { + my ($body) = @_; + my $i = 0; + my $L = length($body); + + my $c1 = substr($body, $i, 1); $i++; + my $c2 = substr($body, $i, 1); $i++; + return () unless (ord($c1) == 0xFF && ord($c2) == 0xD8); + + my $ch = "0"; + while (ord($ch) != 0xDA && $i < $L) { + # Find next marker, beginning with 0xFF. + while (ord($ch) != 0xFF) { + return () if (length($body) <= $i); + $ch = substr($body, $i, 1); $i++; + } + # markers can be padded with any number of 0xFF. + while (ord($ch) == 0xFF) { + return () if (length($body) <= $i); + $ch = substr($body, $i, 1); $i++; + } + + # $ch contains the value of the marker. + my $marker = ord($ch); + + if (($marker >= 0xC0) && + ($marker <= 0xCF) && + ($marker != 0xC4) && + ($marker != 0xCC)) { # it's a SOFn marker + $i += 3; + return () if (length($body) <= $i); + my $s = substr($body, $i, 4); $i += 4; + my ($a,$b,$c,$d) = unpack("C"x4, $s); + return (($c<<8|$d), ($a<<8|$b)); + + } else { + # We must skip variables, since FFs in variable names aren't + # valid JPEG markers. + return () if (length($body) <= $i); + my $s = substr($body, $i, 2); $i += 2; + my ($c1, $c2) = unpack ("C"x2, $s); + my $length = ($c1 << 8) | $c2; + return () if ($length < 2); + $i += $length-2; + } + } + return (); +} + +# Given the raw body of a PNG document, returns the dimensions of the image. +# +sub png_size($) { + my ($body) = @_; + return () unless ($body =~ m/^\211PNG\r/); + my ($bits) = ($body =~ m/^.{12}(.{12})/s); + return () unless defined ($bits); + return () unless ($bits =~ /^IHDR/); + my ($ign, $w, $h) = unpack("a4N2", $bits); + return ($w, $h); +} + + +# Given the raw body of a GIF, JPEG, or PNG document, returns the dimensions +# of the image. +# +sub image_size($) { + my ($body) = @_; + my ($w, $h) = gif_size ($body); + if ($w && $h) { return ($w, $h); } + ($w, $h) = jpeg_size ($body); + if ($w && $h) { return ($w, $h); } + return png_size ($body); +} + + +# returns the full path of the named program, or undef. +# +sub which($) { + my ($prog) = @_; + foreach (split (/:/, $ENV{PATH})) { + if (-x "$_/$prog") { + return $prog; + } + } + return undef; +} + + +# Like rand(), but chooses numbers with a bell curve distribution. +sub bellrand(;$) { + ($_) = @_; + $_ = 1.0 unless defined($_); + $_ /= 3.0; + return (rand($_) + rand($_) + rand($_)); +} + + +sub exit_cleanup() { + x_cleanup(); + print STDERR "$progname: exiting\n" if ($verbose_warnings); + if (@pids_to_kill) { + print STDERR blurb() . "killing: " . join(' ', @pids_to_kill) . "\n"; + kill ('TERM', @pids_to_kill); + } +} + +sub signal_cleanup($) { + my ($sig) = @_; + print STDERR blurb() . (defined($sig) + ? "caught signal $sig." + : "exiting.") + . "\n" + if ($verbose_exec || $verbose_warnings); + exit 1; +} + + + +############################################################################## +# +# Generating a list of urls only +# +############################################################################## + +sub url_only_output() { + do { + my ($base, $img) = pick_image; + if ($img) { + $base =~ s/ /%20/g; + $img =~ s/ /%20/g; + print "$img $base\n"; + } + } while (1); +} + +############################################################################## +# +# Running as an xscreensaver module, or as a web page imagemap +# +############################################################################## + +my $image_ppm = sprintf ("%s/webcollage-%08x.ppm", + ($ENV{TMPDIR} ? $ENV{TMPDIR} : "/tmp"), + rand(0xFFFFFFFF)); +my $image_tmp1 = sprintf ("%s/webcollage-1-%08x.ppm", + ($ENV{TMPDIR} ? $ENV{TMPDIR} : "/tmp"), + rand(0xFFFFFFFF)); +my $image_tmp2 = sprintf ("%s/webcollage-2-%08x.ppm", + ($ENV{TMPDIR} ? $ENV{TMPDIR} : "/tmp"), + rand(0xFFFFFFFF)); + +my $filter_cmd = undef; +my $post_filter_cmd = undef; +my $background = undef; + +my @imagemap_areas = (); +my $imagemap_html_tmp = undef; +my $imagemap_jpg_tmp = undef; + + +my $img_width; # size of the image being generated. +my $img_height; + +my $delay = 2; + +sub x_cleanup() { + unlink $image_ppm, $image_tmp1, $image_tmp2; + unlink $imagemap_html_tmp, $imagemap_jpg_tmp + if (defined ($imagemap_html_tmp)); +} + + +# Like system, but prints status about exit codes, and kills this process +# with whatever signal killed the sub-process, if any. +# +sub nontrapping_system(@) { + $! = 0; + + $_ = join(" ", @_); + s/\"[^\"]+\"/\"...\"/g; + + LOG ($verbose_exec, "executing \"$_\""); + + my $rc = system @_; + + if ($rc == 0) { + LOG ($verbose_exec, "subproc exited normally."); + } elsif (($rc & 0xff) == 0) { + $rc >>= 8; + LOG ($verbose_exec, "subproc exited with status $rc."); + } else { + if ($rc & 0x80) { + LOG ($verbose_exec, "subproc dumped core."); + $rc &= ~0x80; + } + LOG ($verbose_exec, "subproc died with signal $rc."); + # die that way ourselves. + kill $rc, $$; + } + + return $rc; +} + + +# Given the URL of a GIF, JPEG, or PNG image, and the body of that image, +# writes a PPM to the given output file. Returns the width/height of the +# image if successful. +# +sub image_to_pnm($$$) { + my ($url, $body, $output) = @_; + my ($cmd, $cmd2, $w, $h); + + if ((@_ = gif_size ($body))) { + ($w, $h) = @_; + $cmd = "giftopnm"; + } elsif ((@_ = jpeg_size ($body))) { + ($w, $h) = @_; + $cmd = "djpeg"; + } elsif ((@_ = png_size ($body))) { + ($w, $h) = @_; + $cmd = "pngtopnm"; + } else { + LOG (($verbose_pbm || $verbose_load), + "not a GIF, JPG, or PNG" . + (($body =~ m@<(base|html|head|body|script|table|a href)\b@i) + ? " (looks like HTML)" : "") . + ": $url"); + $suppress_audit = 1; + return (); + } + + $cmd2 = "exec $cmd"; # yes, this really is necessary. if we don't + # do this, the process doesn't die properly. + if (!$verbose_pbm) { + # + # We get a "giftopnm: got a 'Application Extension' extension" + # warning any time it's an animgif. + # + # Note that "giftopnm: EOF / read error on image data" is not + # always a fatal error -- sometimes the image looks fine anyway. + # + $cmd2 .= " 2>/dev/null"; + } + + # There exist corrupted GIF and JPEG files that can make giftopnm and + # djpeg lose their minds and go into a loop. So this gives those programs + # a small timeout -- if they don't complete in time, kill them. + # + my $pid; + @_ = eval { + my $timed_out; + + local $SIG{ALRM} = sub { + LOG ($verbose_pbm, + "timed out ($cvt_timeout) for $cmd on \"$url\" in pid $pid"); + kill ('TERM', $pid) if ($pid); + $timed_out = 1; + $body = undef; + }; + + if (($pid = open (my $pipe, "| $cmd2 > $output"))) { + $timed_out = 0; + alarm $cvt_timeout; + print $pipe $body; + $body = undef; + close $pipe; + + LOG ($verbose_exec, "awaiting $pid"); + waitpid ($pid, 0); + LOG ($verbose_exec, "$pid completed"); + + my $size = (stat($output))[7]; + $size = -1 unless defined($size); + if ($size < 5) { + LOG ($verbose_pbm, "$cmd on ${w}x$h \"$url\" failed ($size bytes)"); + return (); + } + + LOG ($verbose_pbm, "created ${w}x$h $output ($cmd)"); + return ($w, $h); + } else { + print STDERR blurb() . "$cmd failed: $!\n"; + return (); + } + }; + die if ($@ && $@ ne "alarm\n"); # propagate errors + if ($@) { + # timed out + $body = undef; + return (); + } else { + # didn't + alarm 0; + $body = undef; + return @_; + } +} + + +# Same as the "ppmmake" command: creates a solid-colored PPM. +# Does not understand the rgb.txt color names except "black" and "white". +# +sub ppmmake($$$$) { + my ($outfile, $bgcolor, $w, $h) = @_; + + my ($r, $g, $b); + if ($bgcolor =~ m/^\#?([\dA-F][\dA-F])([\dA-F][\dA-F])([\dA-F][\dA-F])$/i || + $bgcolor =~ m/^\#?([\dA-F])([\dA-F])([\dA-F])$/i) { + ($r, $g, $b) = (hex($1), hex($2), hex($3)); + } elsif ($bgcolor =~ m/^black$/i) { + ($r, $g, $b) = (0, 0, 0); + } elsif ($bgcolor =~ m/^white$/i) { + ($r, $g, $b) = (0xFF, 0xFF, 0xFF); + } else { + error ("unparsable color name: $bgcolor"); + } + + my $pixel = pack('CCC', $r, $g, $b); + my $bits = "P6\n$w $h\n255\n" . ($pixel x ($w * $h)); + + open (my $out, '>', $outfile) || error ("$outfile: $!"); + print $out $bits; + close $out; +} + + +sub pick_root_displayer() { + my @names = (); + + if ($cocoa_p) { + # see "xscreensaver/hacks/webcollage-cocoa.m" + return "echo COCOA LOAD "; + } + + foreach my $cmd (@root_displayers) { + $_ = $cmd; + my ($name) = m/^([^ ]+)/; + push @names, "\"$name\""; + LOG ($verbose_exec, "looking for $name..."); + foreach my $dir (split (/:/, $ENV{PATH})) { + LOG ($verbose_exec, " checking $dir/$name"); + return $cmd if (-x "$dir/$name"); + } + } + + $names[$#names] = "or " . $names[$#names]; + error "none of: " . join (", ", @names) . " were found on \$PATH."; +} + + +my $ppm_to_root_window_cmd = undef; + + +sub x_or_pbm_output($) { + my ($window_id) = @_; + + # Check for our helper program, to see whether we need to use PPM pipelines. + # + $_ = "webcollage-helper"; + if (defined ($webcollage_helper) || which ($_)) { + $webcollage_helper = $_ unless (defined($webcollage_helper)); + LOG ($verbose_pbm, "found \"$webcollage_helper\""); + $webcollage_helper .= " -v"; + } else { + LOG (($verbose_pbm || $verbose_load), "no $_ program"); + } + + if ($cocoa_p && !defined ($webcollage_helper)) { + error ("webcollage-helper not found in Cocoa-mode!"); + } + + + # make sure the various programs we execute exist, right up front. + # + my @progs = (); + + if (!defined($webcollage_helper)) { + # Only need these others if we don't have the helper. + @progs = (@progs, + "giftopnm", "pngtopnm", "djpeg", + "pnmpaste", "pnmscale", "pnmcut"); + } + + foreach (@progs) { + which ($_) || error "$_ not found on \$PATH."; + } + + # find a root-window displayer program. + # + if (!$no_output_p) { + $ppm_to_root_window_cmd = pick_root_displayer(); + } + + if (defined ($window_id)) { + error ("-window-id only works if xscreensaver-getimage is installed") + unless ($ppm_to_root_window_cmd =~ m/^xscreensaver-getimage\b/); + + error ("unparsable window id: $window_id") + unless ($window_id =~ m/^\d+$|^0x[\da-f]+$/i); + $ppm_to_root_window_cmd =~ s/--?root\b/$window_id/ || + error ("unable to munge displayer: $ppm_to_root_window_cmd"); + } + + if (!$img_width || !$img_height) { + + if (!defined ($window_id) && + defined ($ENV{XSCREENSAVER_WINDOW})) { + $window_id = $ENV{XSCREENSAVER_WINDOW}; + } + + if (!defined ($window_id)) { + $_ = "xdpyinfo"; + which ($_) || error "$_ not found on \$PATH."; + $_ = `$_`; + ($img_width, $img_height) = m/dimensions: *(\d+)x(\d+) /; + if (!defined($img_height)) { + error "xdpyinfo failed."; + } + } else { # we have a window id + $_ = "xwininfo"; + which ($_) || error "$_ not found on \$PATH."; + $_ .= " -id $window_id"; + $_ = `$_`; + ($img_width, $img_height) = m/^\s*Width:\s*(\d+)\n\s*Height:\s*(\d+)\n/m; + + if (!defined($img_height)) { + error "xwininfo failed."; + } + } + } + + my $bgcolor = "#000000"; + my $bgimage = undef; + + if ($background) { + if ($background =~ m/^\#[0-9a-f]+$/i) { + $bgcolor = $background; + + } elsif (-r $background) { + $bgimage = $background; + + } elsif (! $background =~ m@^[-a-z0-9 ]+$@i) { + error "not a color or readable file: $background"; + + } else { + # default to assuming it's a color + $bgcolor = $background; + } + } + + # Create the sold-colored base image. + # + LOG ($verbose_pbm, "creating base image: ${img_width}x${img_height}"); + $_ = ppmmake ($image_ppm, $bgcolor, $img_width, $img_height); + + # Paste the default background image in the middle of it. + # + if ($bgimage) { + my ($iw, $ih); + + my $body = ""; + open (my $imgf, '<', $bgimage) || error "couldn't open $bgimage: $!"; + local $/ = undef; # read entire file + $body = <$imgf>; + close ($imgf); + + my $cmd; + if ((@_ = gif_size ($body))) { + ($iw, $ih) = @_; + $cmd = "giftopnm |"; + + } elsif ((@_ = jpeg_size ($body))) { + ($iw, $ih) = @_; + $cmd = "djpeg |"; + + } elsif ((@_ = png_size ($body))) { + ($iw, $ih) = @_; + $cmd = "pngtopnm |"; + + } elsif ($body =~ m/^P\d\n(\d+) (\d+)\n/) { + $iw = $1; + $ih = $2; + $cmd = ""; + + } else { + error "$bgimage is not a GIF, JPEG, PNG, or PPM."; + } + + my $x = int (($img_width - $iw) / 2); + my $y = int (($img_height - $ih) / 2); + LOG ($verbose_pbm, + "pasting $bgimage (${iw}x$ih) into base image at $x,$y"); + + $cmd .= "pnmpaste - $x $y $image_ppm > $image_tmp1"; + open ($imgf, "| $cmd") || error "running $cmd: $!"; + print $imgf $body; + $body = undef; + close ($imgf); + LOG ($verbose_exec, "subproc exited normally."); + rename ($image_tmp1, $image_ppm) || + error "renaming $image_tmp1 to $image_ppm: $!"; + } + + clearlog(); + + while (1) { + my ($base, $img) = pick_image(); + my $source = $current_state; + $current_state = "loadimage"; + if ($img) { + my ($headers, $body) = get_document ($img, $base); + if ($body) { + paste_image ($base, $img, $body, $source); + $body = undef; + } + } + $current_state = "idle"; + $load_method = "none"; + + unlink $image_tmp1, $image_tmp2; + sleep $delay; + } +} + +sub paste_image($$$$) { + my ($base, $img, $body, $source) = @_; + + $current_state = "paste"; + + $suppress_audit = 0; + + LOG ($verbose_pbm, "got $img (" . length($body) . ")"); + + my ($iw, $ih); + + # If we are using the webcollage-helper, then we do not need to convert this + # image to a PPM. But, if we're using a filter command, we still must, since + # that's what the filters expect (webcollage-helper can read PPMs, so that's + # fine.) + # + if (defined ($webcollage_helper) && + !defined ($filter_cmd)) { + + ($iw, $ih) = image_size ($body); + if (!$iw || !$ih) { + LOG (($verbose_pbm || $verbose_load), + "not a GIF, JPG, or PNG" . + (($body =~ m@<(base|html|head|body|script|table|a href)>@i) + ? " (looks like HTML)" : "") . + ": $img"); + $suppress_audit = 1; + $body = undef; + return 0; + } + + open (my $out, '>', $image_tmp1) || error ("writing $image_tmp1: $!"); + (print $out $body) || error ("writing $image_tmp1: $!"); + close ($out) || error ("writing $image_tmp1: $!"); + + } else { + ($iw, $ih) = image_to_pnm ($img, $body, $image_tmp1); + $body = undef; + if (!$iw || !$ih) { + LOG ($verbose_pbm, "unable to make PBM from $img"); + return 0; + } + } + + record_success ($load_method, $img, $base); + + + my $ow = $iw; # used only for error messages + my $oh = $ih; + + # don't just tack this onto the front of the pipeline -- we want it to + # be able to change the size of the input image. + # + if ($filter_cmd) { + LOG ($verbose_pbm, "running $filter_cmd"); + + my $rc = nontrapping_system "($filter_cmd) < $image_tmp1 >$image_tmp2"; + if ($rc != 0) { + LOG(($verbose_pbm || $verbose_load), "failed command: \"$filter_cmd\""); + LOG(($verbose_pbm || $verbose_load), "failed URL: \"$img\" (${ow}x$oh)"); + return; + } + rename ($image_tmp2, $image_tmp1); + + # re-get the width/height in case the filter resized it. + open (my $imgf, '<', $image_tmp1) || return 0; + $_ = <$imgf>; + $_ = <$imgf>; + ($iw, $ih) = m/^(\d+) (\d+)$/; + close ($imgf); + return 0 unless ($iw && $ih); + } + + my $target_w = $img_width; # max rectangle into which the image must fit + my $target_h = $img_height; + + my $cmd = ""; + my $scale = 1.0; + + + # Usually scale the image to fit on the screen -- but sometimes scale it + # to fit on half or a quarter of the screen. (We do this by reducing the + # size of the target rectangle.) Note that the image is not merely scaled + # to fit; we instead cut the image in half repeatedly until it fits in the + # target rectangle -- that gives a wider distribution of sizes. + # + if (rand() < 0.3) { $target_w /= 2; $target_h /= 2; } # reduce target rect + if (rand() < 0.3) { $target_w /= 2; $target_h /= 2; } + + if ($iw > $target_w || $ih > $target_h) { + while ($iw > $target_w || + $ih > $target_h) { + $iw = int($iw / 2); + $ih = int($ih / 2); + $scale /= 2; + } + if ($iw <= 10 || $ih <= 10) { + LOG ($verbose_pbm, "scaling to ${iw}x$ih would have been bogus."); + return 0; + } + + LOG ($verbose_pbm, "scaling to ${iw}x$ih ($scale)"); + + $cmd .= " | pnmscale -xsize $iw -ysize $ih"; + } + + + my $src = $image_tmp1; + + my $crop_x = 0; # the sub-rectangle of the image + my $crop_y = 0; # that we will actually paste. + my $crop_w = $iw; + my $crop_h = $ih; + + # The chance that we will randomly crop out a section of an image starts + # out fairly low, but goes up for images that are very large, or images + # that have ratios that make them look like banners (we try to avoid + # banner images entirely, but they slip through when the IMG tags didn't + # have WIDTH and HEIGHT specified.) + # + my $crop_chance = 0.2; + if ($iw > $img_width * 0.4 || $ih > $img_height * 0.4) { + $crop_chance += 0.2; + } + if ($iw > $img_width * 0.7 || $ih > $img_height * 0.7) { + $crop_chance += 0.2; + } + if ($min_ratio && ($iw * $min_ratio) > $ih) { + $crop_chance += 0.7; + } + + if ($crop_chance > 0.1) { + LOG ($verbose_pbm, "crop chance: $crop_chance"); + } + + if (rand() < $crop_chance) { + + my $ow = $crop_w; + my $oh = $crop_h; + + if ($crop_w > $min_width) { + # if it's a banner, select the width linearly. + # otherwise, select a bell. + my $r = (($min_ratio && ($iw * $min_ratio) > $ih) + ? rand() + : bellrand()); + $crop_w = $min_width + int ($r * ($crop_w - $min_width)); + $crop_x = int (rand() * ($ow - $crop_w)); + } + if ($crop_h > $min_height) { + # height always selects as a bell. + $crop_h = $min_height + int (bellrand() * ($crop_h - $min_height)); + $crop_y = int (rand() * ($oh - $crop_h)); + } + + if ($crop_x != 0 || $crop_y != 0 || + $crop_w != $iw || $crop_h != $ih) { + LOG ($verbose_pbm, + "randomly cropping to ${crop_w}x$crop_h \@ $crop_x,$crop_y"); + } + } + + # Where the image should logically land -- this might be negative. + # + my $x = int((rand() * ($img_width + $crop_w/2)) - $crop_w*3/4); + my $y = int((rand() * ($img_height + $crop_h/2)) - $crop_h*3/4); + + # if we have chosen to paste the image outside of the rectangle of the + # screen, then we need to crop it. + # + if ($x < 0 || + $y < 0 || + $x + $crop_w > $img_width || + $y + $crop_h > $img_height) { + + LOG ($verbose_pbm, + "cropping for effective paste of ${crop_w}x$crop_h \@ $x,$y"); + + if ($x < 0) { $crop_x -= $x; $crop_w += $x; $x = 0; } + if ($y < 0) { $crop_y -= $y; $crop_h += $y; $y = 0; } + + if ($x + $crop_w >= $img_width) { $crop_w = $img_width - $x - 1; } + if ($y + $crop_h >= $img_height) { $crop_h = $img_height - $y - 1; } + } + + # If any cropping needs to happen, add pnmcut. + # + if ($crop_x != 0 || $crop_y != 0 || + $crop_w != $iw || $crop_h != $ih) { + $iw = $crop_w; + $ih = $crop_h; + $cmd .= " | pnmcut $crop_x $crop_y $iw $ih"; + LOG ($verbose_pbm, "cropping to ${crop_w}x$crop_h \@ $crop_x,$crop_y"); + } + + LOG ($verbose_pbm, "pasting ${iw}x$ih \@ $x,$y in $image_ppm"); + + $cmd .= " | pnmpaste - $x $y $image_ppm"; + + $cmd =~ s@^ *\| *@@; + + if (defined ($webcollage_helper)) { + $cmd = "$webcollage_helper $image_tmp1 $image_ppm " . + "$scale $opacity " . + "$crop_x $crop_y $x $y " . + "$iw $ih"; + $_ = $cmd; + + } else { + # use a PPM pipeline + $_ = "($cmd)"; + $_ .= " < $image_tmp1 > $image_tmp2"; + } + + if ($verbose_pbm) { + $_ = "($_) 2>&1 | sed s'/^/" . blurb() . "/'"; + } else { + $_ .= " 2> /dev/null"; + } + + my $rc = nontrapping_system ($_); + + if (defined ($webcollage_helper) && -z $image_ppm) { + LOG (1, "failed command: \"$cmd\""); + print STDERR "\naudit log:\n\n\n"; + print STDERR ("#" x 78) . "\n"; + print STDERR blurb() . "$image_ppm has zero size\n"; + showlog(); + print STDERR "\n\n"; + exit (1); + } + + if ($rc != 0) { + LOG (($verbose_pbm || $verbose_load), "failed command: \"$cmd\""); + LOG (($verbose_pbm || $verbose_load), "failed URL: \"$img\" (${ow}x$oh)"); + return; + } + + if (!defined ($webcollage_helper)) { + rename ($image_tmp2, $image_ppm) || return; + } + + my $target = "$image_ppm"; + + # don't just tack this onto the end of the pipeline -- we don't want it + # to end up in $image_ppm, because we don't want the results to be + # cumulative. + # + if ($post_filter_cmd) { + + my $cmd; + + $target = $image_tmp1; + if (!defined ($webcollage_helper)) { + $cmd = "($post_filter_cmd) < $image_ppm > $target"; + } else { + # Blah, my scripts need the JPEG data, but some other folks need + # the PPM data -- what to do? Ignore the problem, that's what! +# $cmd = "djpeg < $image_ppm | ($post_filter_cmd) > $target"; + $cmd = "($post_filter_cmd) < $image_ppm > $target"; + } + + $rc = nontrapping_system ($cmd); + if ($rc != 0) { + LOG ($verbose_pbm, "filter failed: \"$post_filter_cmd\"\n"); + return; + } + } + + if (!$no_output_p) { + my $tsize = (stat($target))[7]; + if ($tsize > 200) { + $cmd = "$ppm_to_root_window_cmd $target"; + + # xv seems to hate being killed. it tends to forget to clean + # up after itself, and leaves windows around and colors allocated. + # I had this same problem with vidwhacker, and I'm not entirely + # sure what I did to fix it. But, let's try this: launch xv + # in the background, so that killing this process doesn't kill it. + # it will die of its own accord soon enough. So this means we + # start pumping bits to the root window in parallel with starting + # the next network retrieval, which is probably a better thing + # to do anyway. + # + $cmd .= " &" unless ($cocoa_p); + + $rc = nontrapping_system ($cmd); + + if ($rc != 0) { + LOG (($verbose_pbm || $verbose_load), "display failed: \"$cmd\""); + return; + } + + } else { + LOG ($verbose_pbm, "$target size is $tsize"); + } + } + + $source .= "-" . stats_of($source); + print STDOUT "image: ${iw}x${ih} @ $x,$y $base $source\n" + if ($verbose_imgmap); + if ($imagemap_base) { + update_imagemap ($base, $x, $y, $iw, $ih, + $image_ppm, $img_width, $img_height); + } + + clearlog(); + + return 1; +} + + +sub update_imagemap($$$$$$$$) { + my ($url, $x, $y, $w, $h, $image_ppm, $image_width, $image_height) = @_; + + $current_state = "imagemap"; + + my $max_areas = 200; + + $url = html_quote ($url); + my $x2 = $x + $w; + my $y2 = $y + $h; + my $area = ""; + unshift @imagemap_areas, $area; # put one on the front + if ($#imagemap_areas >= $max_areas) { + pop @imagemap_areas; # take one off the back. + } + + LOG ($verbose_pbm, "area: $x,$y,$x2,$y2 (${w}x$h)"); + + my $map_name = $imagemap_base; + $map_name =~ s@^.*/@@; + $map_name = 'collage' if ($map_name eq ''); + + my $imagemap_html = $imagemap_base . ".html"; + my $imagemap_jpg = $imagemap_base . ".jpg"; + + if (!defined ($imagemap_html_tmp)) { + $imagemap_html_tmp = $imagemap_html . sprintf (".%08x", rand(0xffffffff)); + $imagemap_jpg_tmp = $imagemap_jpg . sprintf (".%08x", rand(0xffffffff)); + } + + # Read the imagemap html file (if any) to get a template. + # + my $template_html = ''; + { + if (open (my $in, '<', $imagemap_html)) { + local $/ = undef; # read entire file + $template_html = <$in>; + close $in; + LOG ($verbose_pbm, "read template $imagemap_html"); + } + + if ($template_html =~ m/^\s*$/s) { + $template_html = ("\n" . + "\n"); + LOG ($verbose_pbm, "created dummy template"); + } + } + + # Write the jpg to a tmp file + # + { + my $cmd; + if (defined ($webcollage_helper)) { + $cmd = "cp -p $image_ppm $imagemap_jpg_tmp"; + } else { + $cmd = "cjpeg < $image_ppm > $imagemap_jpg_tmp"; + } + my $rc = nontrapping_system ($cmd); + if ($rc != 0) { + error ("imagemap jpeg failed: \"$cmd\"\n"); + } + } + + # Write the html to a tmp file + # + { + my $body = $template_html; + my $areas = join ("\n\t", @imagemap_areas); + my $map = ("\n\t$areas\n"); + my $img = (""); + $body =~ s@().*?()@$map@is; + $body =~ s@]*\bUSEMAP\b[^<>]*>@$img@is; + + # if there are magic webcollage spans in the html, update those too. + # + { + my @st = stat ($imagemap_jpg_tmp); + my $date = strftime("%d-%b-%Y %l:%M:%S %p %Z", localtime($st[9])); + my $size = int(($st[7] / 1024) + 0.5) . "K"; + $body =~ s@().*?()@$1$date$2@si; + $body =~ s@().*?()@$1$size$2@si; + } + + open (my $out, '>', $imagemap_html_tmp) || error ("$imagemap_html_tmp: $!"); + (print $out $body) || error ("$imagemap_html_tmp: $!"); + close ($out) || error ("$imagemap_html_tmp: $!"); + LOG ($verbose_pbm, "wrote $imagemap_html_tmp"); + } + + # Rename the two tmp files to the real files + # + rename ($imagemap_html_tmp, $imagemap_html) || + error "renaming $imagemap_html_tmp to $imagemap_html"; + LOG ($verbose_pbm, "wrote $imagemap_html"); + rename ($imagemap_jpg_tmp, $imagemap_jpg) || + error "renaming $imagemap_jpg_tmp to $imagemap_jpg"; + LOG ($verbose_pbm, "wrote $imagemap_jpg"); +} + + +# Figure out what the proxy server should be, either from environment +# variables or by parsing the output of the (MacOS) program "scutil", +# which tells us what the system-wide proxy settings are. +# +sub set_proxy() { + + if (! $http_proxy) { + # historical suckage: the environment variable name is lower case. + $http_proxy = $ENV{http_proxy} || $ENV{HTTP_PROXY}; + } + + if (defined ($http_proxy)) { + if ($http_proxy && $http_proxy =~ m@^http://([^/]*)/?$@ ) { + # historical suckage: allow "http://host:port" as well as "host:port". + $http_proxy = $1; + } + + } else { + my $proxy_data = `scutil --proxy 2>/dev/null`; + my ($server) = ($proxy_data =~ m/\bHTTPProxy\s*:\s*([^\s]+)/s); + my ($port) = ($proxy_data =~ m/\bHTTPPort\s*:\s*([^\s]+)/s); + # Note: this ignores the "ExceptionsList". + if ($server) { + $http_proxy = $server; + $http_proxy .= ":$port" if $port; + } + } + + if ($http_proxy) { + LOG ($verbose_net, "proxy server: $http_proxy"); + } +} + + +sub init_signals() { + + $SIG{HUP} = \&signal_cleanup; + $SIG{INT} = \&signal_cleanup; + $SIG{QUIT} = \&signal_cleanup; + $SIG{ABRT} = \&signal_cleanup; + $SIG{KILL} = \&signal_cleanup; + $SIG{TERM} = \&signal_cleanup; + + # Need this so that if giftopnm dies, we don't die. + $SIG{PIPE} = 'IGNORE'; +} + +END { exit_cleanup(); } + + +sub main() { + $| = 1; + srand(time ^ $$); + + my $verbose = 0; + my $dict; + my $driftnet_cmd = 0; + + $current_state = "init"; + $load_method = "none"; + + my $root_p = 0; + my $window_id = undef; + + while ($_ = $ARGV[0]) { + shift @ARGV; + if ($_ eq "-display" || + $_ eq "-displ" || + $_ eq "-disp" || + $_ eq "-dis" || + $_ eq "-dpy" || + $_ eq "-d") { + $ENV{DISPLAY} = shift @ARGV; + } elsif ($_ eq "-root") { + $root_p = 1; + } elsif ($_ eq "-window-id" || $_ eq "--window-id") { + $window_id = shift @ARGV; + $root_p = 1; + } elsif ($_ eq "-no-output") { + $no_output_p = 1; + } elsif ($_ eq "-urls-only") { + $urls_only_p = 1; + $no_output_p = 1; + } elsif ($_ eq "-cocoa") { + $cocoa_p = 1; + } elsif ($_ eq "-imagemap") { + $imagemap_base = shift @ARGV; + $no_output_p = 1; + } elsif ($_ eq "-verbose") { + $verbose++; + } elsif (m/^-v+$/) { + $verbose += length($_)-1; + } elsif ($_ eq "-delay") { + $delay = shift @ARGV; + } elsif ($_ eq "-timeout") { + $http_timeout = shift @ARGV; + } elsif ($_ eq "-filter") { + $filter_cmd = shift @ARGV; + } elsif ($_ eq "-filter2") { + $post_filter_cmd = shift @ARGV; + } elsif ($_ eq "-background" || $_ eq "-bg") { + $background = shift @ARGV; + } elsif ($_ eq "-size") { + $_ = shift @ARGV; + if (m@^(\d+)x(\d+)$@) { + $img_width = $1; + $img_height = $2; + } else { + error "argument to \"-size\" must be of the form \"640x400\""; + } + } elsif ($_ eq "-proxy" || $_ eq "-http-proxy") { + $http_proxy = shift @ARGV; + } elsif ($_ eq "-dictionary" || $_ eq "-dict") { + $dict = shift @ARGV; + } elsif ($_ eq "-opacity") { + $opacity = shift @ARGV; + error ("opacity must be between 0.0 and 1.0") + if ($opacity <= 0 || $opacity > 1); + } elsif ($_ eq "-driftnet" || $_ eq "--driftnet") { + @search_methods = ( 100, "driftnet", \&pick_from_driftnet ); + if (! ($ARGV[0] =~ m/^-/)) { + $driftnet_cmd = shift @ARGV; + } else { + $driftnet_cmd = $default_driftnet_cmd; + } + } elsif ($_ eq "-directory" || $_ eq "--directory") { + @search_methods = ( 100, "local", \&pick_from_local_dir ); + if (! ($ARGV[0] =~ m/^-/)) { + $local_dir = shift @ARGV; + } else { + error ("local directory path must be set") + } + } elsif ($_ eq "-fps") { + # -fps only works on MacOS, via "webcollage-cocoa.m". + # Ignore it if passed to this script in an X11 context. + } elsif ($_ eq "-debug" || $_ eq "--debug") { + my $which = shift @ARGV; + my @rest = @search_methods; + my $ok = 0; + while (@rest) { + my $pct = shift @rest; + my $name = shift @rest; + my $tfn = shift @rest; + + if ($name eq $which) { + @search_methods = (100, $name, $tfn); + $ok = 1; + last; + } + } + error "no such search method as \"$which\"" unless ($ok); + LOG (1, "DEBUG: using only \"$which\""); + + } else { + print STDERR "$copyright\nusage: $progname " . + "[-root] [-display dpy] [-verbose] [-debug which]\n" . + "\t\t [-timeout secs] [-delay secs] [-size WxH]\n" . + "\t\t [-no-output] [-urls-only] [-imagemap filename]\n" . + "\t\t [-background color] [-opacity f]\n" . + "\t\t [-filter cmd] [-filter2 cmd]\n" . + "\t\t [-dictionary dictionary-file] [-http-proxy host[:port]]\n" . + "\t\t [-driftnet [driftnet-program-and-args]]\n" . + "\t\t [-directory local-image-directory]\n" . + "\n"; + exit 1; + } + } + + if (!$root_p && !$no_output_p && !$cocoa_p) { + print STDERR $copyright; + error "the -root argument is mandatory (for now.)"; + } + + if (!$no_output_p && !$cocoa_p && !$ENV{DISPLAY}) { + error "\$DISPLAY is not set."; + } + + + if ($verbose == 1) { + $verbose_imgmap = 1; + $verbose_warnings = 1; + + } elsif ($verbose == 2) { + $verbose_imgmap = 1; + $verbose_warnings = 1; + $verbose_load = 1; + + } elsif ($verbose == 3) { + $verbose_imgmap = 1; + $verbose_warnings = 1; + $verbose_load = 1; + $verbose_filter = 1; + + } elsif ($verbose == 4) { + $verbose_imgmap = 1; + $verbose_warnings = 1; + $verbose_load = 1; + $verbose_filter = 1; + $verbose_net = 1; + + } elsif ($verbose == 5) { + $verbose_imgmap = 1; + $verbose_warnings = 1; + $verbose_load = 1; + $verbose_filter = 1; + $verbose_net = 1; + $verbose_pbm = 1; + + } elsif ($verbose == 6) { + $verbose_imgmap = 1; + $verbose_warnings = 1; + $verbose_load = 1; + $verbose_filter = 1; + $verbose_net = 1; + $verbose_pbm = 1; + $verbose_http = 1; + + } elsif ($verbose >= 7) { + $verbose_imgmap = 1; + $verbose_warnings = 1; + $verbose_load = 1; + $verbose_filter = 1; + $verbose_net = 1; + $verbose_pbm = 1; + $verbose_http = 1; + $verbose_exec = 1; + } + + if ($dict) { + error ("$dict does not exist") unless (-f $dict); + $wordlist = $dict; + } else { + pick_dictionary(); + } + + if ($imagemap_base && !($img_width && $img_height)) { + error ("-size WxH is required with -imagemap"); + } + + if (defined ($local_dir)) { + $_ = "xscreensaver-getimage-file"; + which ($_) || error "$_ not found on \$PATH."; + } + + init_signals(); + set_proxy(); + + spawn_driftnet ($driftnet_cmd) if ($driftnet_cmd); + + if ($urls_only_p) { + url_only_output (); + } else { + x_or_pbm_output ($window_id); + } +} + +main(); +exit (0); diff --git a/hacks/webcollage-cocoa.m b/hacks/webcollage-cocoa.m new file mode 100644 index 00000000..d6505df2 --- /dev/null +++ b/hacks/webcollage-cocoa.m @@ -0,0 +1,420 @@ +/* xscreensaver, Copyright (c) 2006-2011 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. + */ + + /* This is the Cocoa shim for webcollage. + + It runs the webcollage perl script + (in "WebCollage.saver/Contents/Resources/webcollage") + at the end of a pipe; each time that script updates the image file on + disk it prints the file name, and this program loads and displays that + image. + + The script uses "WebCollage.saver/Contents/Resources/webcollage-helper" + to paste the images together in the usual way. + */ + +#include +#include +#include +#include +#import + +#include "screenhack.h" + + +typedef struct { + Display *dpy; + Window window; + XWindowAttributes xgwa; + int delay; + pid_t pid; + FILE *pipe_fd; + XtInputId pipe_id; + Bool verbose_p; +} state; + + +/* Violating the cardinal rule of "don't use global variables", + but we need to get at these from the atexit() handler, and + the callback doesn't take a closure arg. Because apparently + those hadn't been invented yet in the seventies. + */ +static state *all_states[50] = { 0, }; + +static void webcollage_atexit (void); +static void signal_handler (int sig); + + +static void +subproc_cb (XtPointer closure, int *source, XtInputId *id) +{ + /* state *st = (state *) closure; */ + /* st->input_available_p = True; */ +} + + +/* whether there is data available to be read on the file descriptor + */ +static int +input_available_p (int fd) +{ + struct timeval tv = { 0, }; + fd_set fds; +# if 0 + /* This breaks on BSD, which uses bzero() in the definition of FD_ZERO */ + FD_ZERO (&fds); +# else + memset (&fds, 0, sizeof(fds)); +# endif + FD_SET (fd, &fds); + return select (fd+1, &fds, NULL, NULL, &tv); +} + + +static void +display_image (state *st, const char *file) +{ + NSImage *image = [[NSImage alloc] + initWithContentsOfFile: + [NSString stringWithCString: file + encoding: NSUTF8StringEncoding]]; + + if (! image) { + fprintf (stderr, "webcollage: failed to load \"%s\"\n", file); + return; + } + + [image drawAtPoint: NSMakePoint (0, 0) + fromRect: NSMakeRect (0, 0, [image size].width, [image size].height) + operation: NSCompositeCopy + fraction: 1.0]; + [image release]; +} + + +static void +open_pipe (state *st) +{ + /* This mess is because popen() doesn't give us the pid. + */ + + pid_t forked; + int fds [2]; + int in, out; + char buf[1024]; + + char *av[20]; + int ac = 0; + + int timeout = get_integer_resource (st->dpy, "timeout", "Timeout"); + int delay = get_integer_resource (st->dpy, "delay", "Delay"); + float opacity = get_float_resource (st->dpy, "opacity", "Opacity"); + char *filter = get_string_resource (st->dpy, "filter", "Filter"); + char *filter2 = get_string_resource (st->dpy, "filter2", "Filter2"); + + av[ac++] = "webcollage"; + av[ac++] = "-cocoa"; + + av[ac++] = "-size"; + sprintf (buf, "%dx%d", st->xgwa.width, st->xgwa.height); + av[ac++] = strdup (buf); + + av[ac++] = "-timeout"; sprintf (buf, "%d", timeout); + av[ac++] = strdup (buf); + av[ac++] = "-delay"; sprintf (buf, "%d", delay); + av[ac++] = strdup (buf); + av[ac++] = "-opacity"; sprintf (buf, "%.2f", opacity); + av[ac++] = strdup (buf); + + if (filter && *filter) { + av[ac++] = "-filter"; + av[ac++] = filter; + } + if (filter2 && *filter2) { + av[ac++] = "-filter2"; + av[ac++] = filter2; + } + + av[ac] = 0; + + + if (st->verbose_p) { + fprintf (stderr, "webcollage: launching:"); + int i; + for (i = 0; i < ac; i++) + fprintf (stderr, " %s", av[i]); + fprintf (stderr, "\n"); + } + + + if (pipe (fds)) + { + perror ("webcollage: error creating pipe"); + exit (1); + } + + in = fds [0]; + out = fds [1]; + + switch ((int) (forked = fork ())) + { + case -1: + { + perror ("webcollage: couldn't fork"); + exit (1); + } + case 0: + { + int stdout_fd = 1; + + close (in); /* don't need this one */ + + if (dup2 (out, stdout_fd) < 0) /* pipe stdout */ + { + perror ("could not dup() a new stdout:"); + exit (1); + } + + execvp (av[0], av); /* shouldn't return. */ + + if (errno != ENOENT) + { + /* Ignore "no such file or directory" errors, unless verbose. + Issue all other exec errors, though. */ + sprintf (buf, "webcollage: %s", av[0]); + perror (buf); + } + + exit (1); /* exits fork */ + break; + } + default: + { + st->pipe_fd = fdopen (in, "r"); + close (out); /* don't need this one */ + } + } + + if (! st->pipe_fd) abort(); + + st->pid = forked; + st->pipe_id = + XtAppAddInput (XtDisplayToApplicationContext (st->dpy), + fileno (st->pipe_fd), + (XtPointer) (XtInputReadMask | XtInputExceptMask), + subproc_cb, (XtPointer) st); + + if (st->verbose_p) + fprintf (stderr, "webcollage: subprocess pid: %d\n", st->pid); +} + + +static void * +webcollage_init (Display *dpy, Window window) +{ + state *st = (state *) calloc (1, sizeof(*st)); + int i; + st->dpy = dpy; + st->window = window; + XGetWindowAttributes (st->dpy, st->window, &st->xgwa); + + st->delay = 1000000; /* check once a second */ + + // Log to syslog when FPS is turned on. + st->verbose_p = get_boolean_resource (dpy, "doFPS", "DoFPS"); + + + static int done_once = 0; + if (! done_once) { + done_once = 1; + + if (atexit (webcollage_atexit)) { // catch calls to exit() + perror ("webcollage: atexit"); + exit (-1); + } + + int sigs[] = { SIGHUP, SIGINT, SIGQUIT, SIGILL, SIGTRAP, SIGABRT, + SIGFPE, SIGBUS, SIGSEGV, SIGSYS, /*SIGPIPE,*/ + SIGALRM, SIGTERM }; + for (i = 0; i < sizeof(sigs)/sizeof(*sigs); i++) { + if (signal (sigs[i], signal_handler)) { + perror ("webcollage: signal"); + //exit (1); + } + } + } + + + open_pipe (st); + + i = 0; + while (all_states[i]) i++; + all_states[i] = st; + + return st; +} + + +static unsigned long +webcollage_draw (Display *dpy, Window window, void *closure) +{ + state *st = (state *) closure; + + if (! st->pipe_fd) + exit (1); + + if (! input_available_p (fileno (st->pipe_fd))) + return st->delay; + + char buf[10240]; + int n = read (fileno (st->pipe_fd), + (void *) buf, + sizeof(buf) - 1); + if (n <= 0) + { + XtRemoveInput (st->pipe_id); + st->pipe_id = 0; + // #### sometimes hangs -- pclose (st->pipe_fd); + st->pipe_fd = 0; + + if (st->verbose_p) + fprintf (stderr, "webcollage: subprocess has exited: bailing.\n"); + + return st->delay * 10; + } + + buf[n] = 0; + char *s = strchr (buf, '\n'); + if (s) *s = 0; + + const char *target = "COCOA LOAD "; + if (!strncmp (target, buf, strlen(target))) { + const char *file = buf + strlen(target); + display_image (st, file); + } + + return st->delay; +} + + +static void +webcollage_reshape (Display *dpy, Window window, void *closure, + unsigned int w, unsigned int h) +{ +} + + +static Bool +webcollage_event (Display *dpy, Window window, void *closure, XEvent *event) +{ + return False; +} + + +static void +webcollage_atexit (void) +{ + int i = 0; + + if (all_states[0] && all_states[0]->verbose_p) + fprintf (stderr, "webcollage: atexit handler\n"); + + while (all_states[i]) { + state *st = all_states[i]; + if (st->pid) { + if (st->verbose_p) + fprintf (stderr, "webcollage: kill %d\n", st->pid); + if (kill (st->pid, SIGTERM) < 0) { + fprintf (stderr, "webcollage: kill (%d, TERM): ", st->pid); + perror ("webcollage: kill"); + } + st->pid = 0; + } + all_states[i] = 0; + i++; + } +} + + +static void +signal_handler (int sig) +{ + if (all_states[0] && all_states[0]->verbose_p) + fprintf (stderr, "webcollage: signal %d\n", sig); + webcollage_atexit (); + exit (sig); +} + + +/* This is important because OSX doesn't actually kill the screen savers! + It just sends them a [ScreenSaverView stopAnimation] method. Were + they to actually exit, the resultant SIGPIPE should reap the children, + but instead, we need to do it here. + + On top of that, there's an atexit() handler because otherwise the + inferior perl script process was failing to die when SaverTester or + System Preferences exited. I don't pretend to understand. + + It still fails to clean up when I hit the stop button in Xcode. + WTF. + */ +static void +webcollage_free (Display *dpy, Window window, void *closure) +{ + state *st = (state *) closure; + + if (st->verbose_p) + fprintf (stderr, "webcollage: free cb\n"); + + // Dammit dammit dammit! Why won't this shit die when we pclose it! +// killpg (0, SIGTERM); + + webcollage_atexit(); + + if (st->pipe_id) + XtRemoveInput (st->pipe_id); + + if (st->pipe_fd) + fclose (st->pipe_fd); + + // Reap zombies. +# undef sleep + sleep (1); + int wait_status = 0; + waitpid (-1, &wait_status, 0); + + free (st); +} + + +static const char *webcollage_defaults [] = { + ".background: black", + ".foreground: white", + + "*timeout: 30", + "*delay: 2", + "*opacity: 0.85", + "*filter: ", + "*filter2: ", + 0 +}; + +static XrmOptionDescRec webcollage_options [] = { + { "-timeout", ".timeout", XrmoptionSepArg, 0 }, + { "-delay", ".delay", XrmoptionSepArg, 0 }, + { "-opacity", ".opacity", XrmoptionSepArg, 0 }, + { "-filter", ".filter", XrmoptionSepArg, 0 }, + { "-filter2", ".filter2", XrmoptionSepArg, 0 }, + { 0, 0, 0, 0 } +}; + + +XSCREENSAVER_MODULE ("WebCollage", webcollage) diff --git a/hacks/webcollage-helper-cocoa.m b/hacks/webcollage-helper-cocoa.m new file mode 100644 index 00000000..1b5fadfb --- /dev/null +++ b/hacks/webcollage-helper-cocoa.m @@ -0,0 +1,407 @@ +/* webcollage-helper-cocoa --- scales and pastes one image into another + * xscreensaver, Copyright (c) 2002-2009 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. + */ + +/* This is the Cocoa implementation. See webcollage-helper.c for the + GDK + JPEGlib implementation. + */ + +#import +#include +#include +#include +#include + + +#if MAC_OS_X_VERSION_MAX_ALLOWED <= MAC_OS_X_VERSION_10_4 + typedef int NSInteger; + typedef unsigned int NSUInteger; +#endif + + +char *progname; +static int verbose_p = 0; + +static void write_image (NSImage *img, const char *file); + + +/* NSImage can't load PPMs by default... + */ +static NSImage * +load_ppm_image (const char *file) +{ + FILE *in = fopen (file, "r"); + if (! in) return 0; + + char buf[255]; + + char *s = fgets (buf, sizeof(buf)-1, in); /* P6 */ + if (!s || !!strcmp (s, "P6\n")) + return 0; + + s = fgets (buf, sizeof(buf)-1, in); /* W H */ + if (!s) + return 0; + + int w = 0, h = 0, d = 0; + if (2 != sscanf (buf, " %d %d \n", &w, &h)) + return 0; + if (w <= 0 || h <= 0) + return 0; + + s = fgets (buf, sizeof(buf)-1, in); /* 255 */ + if (!s) + return 0; + + if (1 != sscanf (buf, " %d \n", &d)) + return 0; + if (d != 255) + return 0; + + int size = (w * (h+1) * 3); + unsigned char *bits = malloc (size); + if (!bits) return 0; + + int n = read (fileno (in), (void *) bits, size); /* body */ + if (n < 20) return 0; + + fclose (in); + + NSBitmapImageRep *rep = + [[NSBitmapImageRep alloc] + initWithBitmapDataPlanes: &bits + pixelsWide: w + pixelsHigh: h + bitsPerSample: 8 + samplesPerPixel: 3 + hasAlpha: NO + isPlanar: NO + colorSpaceName: NSDeviceRGBColorSpace + bitmapFormat: NSAlphaFirstBitmapFormat + bytesPerRow: w * 3 + bitsPerPixel: 8 * 3]; + + NSImage *image = [[NSImage alloc] initWithSize: NSMakeSize (w, h)]; + [image addRepresentation: rep]; + [rep release]; + + // #### 'bits' is leaked... the NSImageRep doesn't free it when freed. + + return image; +} + + +static NSImage * +load_image (const char *file) +{ + NSImage *image = [[NSImage alloc] + initWithContentsOfFile: + [NSString stringWithCString: file + encoding: kCFStringEncodingUTF8]]; + if (! image) + image = load_ppm_image (file); + + if (! image) { + fprintf (stderr, "%s: unable to load %s\n", progname, file); + exit (1); + } + + return image; +} + + +static void +bevel_image (NSImage *img, int bevel_pct, + int x, int y, int w, int h, double scale) +{ + int small_size = (w > h ? h : w); + + int bevel_size = small_size * (bevel_pct / 100.0); + + bevel_size /= scale; + + /* Use a proportionally larger bevel size for especially small images. */ + if (bevel_size < 20 && small_size > 40) bevel_size = 20; + else if (bevel_size < 10 && small_size > 20) bevel_size = 10; + else if (bevel_size < 5) /* too small to bother bevelling */ + return; + + + NSBitmapImageRep *rep = + [[NSBitmapImageRep alloc] + initWithBitmapDataPlanes: NULL + pixelsWide: w + pixelsHigh: h + bitsPerSample: 8 + samplesPerPixel: 4 + hasAlpha: YES + isPlanar: NO + colorSpaceName: NSDeviceRGBColorSpace + bitmapFormat: NSAlphaFirstBitmapFormat + bytesPerRow: 0 + bitsPerPixel: 0]; + + NSInteger xx, yy; + double *ramp = (double *) malloc (sizeof(*ramp) * (bevel_size + 1)); + + if (!ramp) + { + fprintf (stderr, "%s: out of memory (%d)\n", progname, bevel_size); + exit (1); + } + + for (xx = 0; xx <= bevel_size; xx++) + { +# if 0 /* linear */ + ramp[xx] = xx / (double) bevel_size; + +# else /* sinusoidal */ + double p = (xx / (double) bevel_size); + double s = sin (p * M_PI / 2); + ramp[xx] = s; +# endif + } + + memset ([rep bitmapData], 0xFFFFFFFF, + [rep bytesPerRow] * h); + + for (yy = 0; yy < h; yy++) + { + for (xx = 0; xx < w; xx++) + { + double rx, ry, r; + + if (xx < bevel_size) rx = ramp[xx]; + else if (xx >= w - bevel_size) rx = ramp[w - xx - 1]; + else rx = 1; + + if (yy < bevel_size) ry = ramp[yy]; + else if (yy >= h - bevel_size) ry = ramp[h - yy - 1]; + else ry = 1; + + r = rx * ry; + if (r != 1) + { + NSUInteger p[4]; + p[0] = 0xFF * r; + p[1] = p[2] = p[3] = 0xFF; + [rep setPixel:p atX:xx y:yy]; + } + } + } + + free (ramp); + + NSImage *bevel_img = [[NSImage alloc] + initWithData: [rep TIFFRepresentation]]; + + [img lockFocus]; + y = [img size].height - (y + h); + [bevel_img drawAtPoint: NSMakePoint (x, y) + fromRect: NSMakeRect (0, 0, w, h) + operation: NSCompositeDestinationIn /* Destination image + wherever both images are + opaque, transparent + elsewhere. */ + fraction: 1.0]; + [img unlockFocus]; + + [rep release]; + [bevel_img release]; + + if (verbose_p) + fprintf (stderr, "%s: added %d%% bevel (%d px)\n", progname, + bevel_pct, bevel_size); +} + + +static void +paste (const char *paste_file, + const char *base_file, + double from_scale, + double opacity, int bevel_pct, + int from_x, int from_y, int to_x, int to_y, + int w, int h) +{ + NSImage *paste_img = load_image (paste_file); + NSImage *base_img = load_image (base_file); + + int paste_w = [paste_img size].width; + int paste_h = [paste_img size].height; + + int base_w = [base_img size].width; + int base_h = [base_img size].height; + + if (verbose_p) + { + fprintf (stderr, "%s: loaded %s: %dx%d\n", + progname, base_file, base_w, base_h); + fprintf (stderr, "%s: loaded %s: %dx%d\n", + progname, paste_file, paste_w, paste_h); + } + + if (bevel_pct > 0 && paste_w > 5 && paste_h > 5) + bevel_image (paste_img, bevel_pct, + from_x, from_y, w, h, + from_scale); + + int scaled_w = w * from_scale; + int scaled_h = h * from_scale; + + from_y = paste_h - (from_y + h); // Cocoa flipped coordinate system + to_y = base_h - (to_y + scaled_h); + + [base_img lockFocus]; + [paste_img drawInRect: NSMakeRect (to_x, to_y, scaled_w, scaled_h) + fromRect: NSMakeRect (from_x, from_y, w, h) + operation: NSCompositeSourceOver + fraction: opacity]; + [base_img unlockFocus]; + + if (verbose_p) + fprintf (stderr, "%s: pasted %dx%d (%dx%d) from %d,%d to %d,%d\n", + progname, w, h, scaled_w, scaled_h, from_x, from_y, to_x, to_y); + + [paste_img release]; + write_image (base_img, base_file); + [base_img release]; +} + + +static void +write_image (NSImage *img, const char *file) +{ + float jpeg_quality = .85; + + // Load the NSImage's contents into an NSBitmapImageRep: + NSBitmapImageRep *bit_rep = [NSBitmapImageRep + imageRepWithData:[img TIFFRepresentation]]; + + // Write the bitmapImageRep to a JPEG file. + if (bit_rep == nil) + { + fprintf (stderr, "%s: error converting image?\n", progname); + exit (1); + } + + if (verbose_p) + fprintf (stderr, "%s: writing %s (q=%d%%) ", progname, file, + (int) (jpeg_quality * 100)); + + NSDictionary *props = [NSDictionary + dictionaryWithObject: + [NSNumber numberWithFloat:jpeg_quality] + forKey:NSImageCompressionFactor]; + NSData *jpeg_data = [bit_rep representationUsingType:NSJPEGFileType + properties:props]; + + [jpeg_data writeToFile: + [NSString stringWithCString:file + encoding:NSISOLatin1StringEncoding] + atomically:YES]; + + if (verbose_p) + { + struct stat st; + if (stat (file, &st)) + { + char buf[255]; + sprintf (buf, "%.100s: %.100s", progname, file); + perror (buf); + exit (1); + } + fprintf (stderr, " %luK\n", ((unsigned long) st.st_size + 1023) / 1024); + } +} + + +static void +usage (void) +{ + fprintf (stderr, "usage: %s [-v] paste-file base-file\n" + "\t from-scale opacity\n" + "\t from-x from-y to-x to-y w h\n" + "\n" + "\t Pastes paste-file into base-file.\n" + "\t base-file will be overwritten (with JPEG data.)\n" + "\t scaling is applied first: coordinates apply to scaled image.\n", + progname); + exit (1); +} + + +int +main (int argc, char **argv) +{ + int i; + char *paste_file, *base_file, *s, dummy; + double from_scale, opacity; + int from_x, from_y, to_x, to_y, w, h, bevel_pct; + + i = 0; + progname = argv[i++]; + s = strrchr (progname, '/'); + if (s) progname = s+1; + + if (argc != 11 && argc != 12) usage(); + + if (!strcmp(argv[i], "-v")) + verbose_p++, i++; + + paste_file = argv[i++]; + base_file = argv[i++]; + + if (*paste_file == '-') usage(); + if (*base_file == '-') usage(); + + s = argv[i++]; + if (1 != sscanf (s, " %lf %c", &from_scale, &dummy)) usage(); + if (from_scale <= 0 || from_scale > 100) usage(); + + s = argv[i++]; + if (1 != sscanf (s, " %lf %c", &opacity, &dummy)) usage(); + if (opacity <= 0 || opacity > 1) usage(); + + s = argv[i++]; if (1 != sscanf (s, " %d %c", &from_x, &dummy)) usage(); + s = argv[i++]; if (1 != sscanf (s, " %d %c", &from_y, &dummy)) usage(); + s = argv[i++]; if (1 != sscanf (s, " %d %c", &to_x, &dummy)) usage(); + s = argv[i++]; if (1 != sscanf (s, " %d %c", &to_y, &dummy)) usage(); + s = argv[i++]; if (1 != sscanf (s, " %d %c", &w, &dummy)) usage(); + s = argv[i]; if (1 != sscanf (s, " %d %c", &h, &dummy)) usage(); + + bevel_pct = 10; /* #### */ + + if (w < 0) usage(); + if (h < 0) usage(); + + if (w == 0 || h == 0 || + w > 10240 || h > 10240) { + fprintf (stderr, "%s: absurd size: %d x %d\n", progname, w, h); + exit (1); + } + + + // Much of Cocoa needs one of these to be available. + NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; + + //Need an NSApp instance to make [NSImage TIFFRepresentation] work + NSApp = [NSApplication sharedApplication]; + [NSApp autorelease]; + + paste (paste_file, base_file, + from_scale, opacity, bevel_pct, + from_x, from_y, to_x, to_y, + w, h); + + [pool release]; + + exit (0); +} diff --git a/hacks/webcollage-helper.c b/hacks/webcollage-helper.c new file mode 100644 index 00000000..e6e2da7a --- /dev/null +++ b/hacks/webcollage-helper.c @@ -0,0 +1,504 @@ +/* webcollage-helper --- scales and pastes one image into another + * xscreensaver, Copyright (c) 2002-2005 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. + */ + +/* This is the GDK + JPEGlib implementation. See webcollage-helper-cocoa.m + for the Cocoa implementation. + */ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#if defined(HAVE_GDK_PIXBUF) && defined(HAVE_JPEGLIB) /* whole file */ + +#include +#include +#include +#include +#include +#include +#include + +#undef HAVE_STDLIB_H /* stupid jconfig.h! */ +#include +#include + + +char *progname; +static int verbose_p = 0; + +static void add_jpeg_comment (struct jpeg_compress_struct *cinfo); +static void write_pixbuf (GdkPixbuf *pb, const char *file); + +static GdkPixbuf * +load_pixbuf (const char *file) +{ + GdkPixbuf *pb; +#ifdef HAVE_GTK2 + GError *err = NULL; + + pb = gdk_pixbuf_new_from_file (file, &err); +#else /* !HAVE_GTK2 */ + pb = gdk_pixbuf_new_from_file (file); +#endif /* HAVE_GTK2 */ + + if (!pb) + { +#ifdef HAVE_GTK2 + fprintf (stderr, "%s: %s\n", progname, err->message); + g_error_free (err); +#else /* !HAVE_GTK2 */ + fprintf (stderr, "%s: unable to load %s\n", progname, file); +#endif /* !HAVE_GTK2 */ + exit (1); + } + + return pb; +} + + +static void +bevel_image (GdkPixbuf **pbP, int bevel_pct, + int x, int y, int w, int h) +{ + GdkPixbuf *pb = *pbP; + int small_size = (w > h ? h : w); + + int bevel_size = small_size * (bevel_pct / 100.0); + + /* Use a proportionally larger bevel size for especially small images. */ + if (bevel_size < 20 && small_size > 40) bevel_size = 20; + else if (bevel_size < 10 && small_size > 20) bevel_size = 10; + else if (bevel_size < 5) /* too small to bother bevelling */ + return; + + /* Ensure the pixbuf has an alpha channel. */ + if (! gdk_pixbuf_get_has_alpha (pb)) + { + GdkPixbuf *pb2 = gdk_pixbuf_add_alpha (pb, FALSE, 0, 0, 0); + gdk_pixbuf_unref (pb); + pb = pb2; + } + + { + guchar *data = gdk_pixbuf_get_pixels (pb); + guchar *line; + int rs = gdk_pixbuf_get_rowstride (pb); + int ch = gdk_pixbuf_get_n_channels (pb); + int xx, yy; + double *ramp = (double *) malloc (sizeof(*ramp) * (bevel_size + 1)); + + if (!ramp) + { + fprintf (stderr, "%s: out of memory (%d)\n", progname, bevel_size); + exit (1); + } + + for (xx = 0; xx <= bevel_size; xx++) + { + +# if 0 /* linear */ + ramp[xx] = xx / (double) bevel_size; + +# else /* sinusoidal */ + double p = (xx / (double) bevel_size); + double s = sin (p * M_PI / 2); + ramp[xx] = s; +# endif + } + + line = data + (rs * y); + for (yy = 0; yy < h; yy++) + { + guchar *p = line + (x * ch); + for (xx = 0; xx < w; xx++) + { + double rx, ry, r; + + if (xx < bevel_size) rx = ramp[xx]; + else if (xx >= w - bevel_size) rx = ramp[w - xx - 1]; + else rx = 1; + + if (yy < bevel_size) ry = ramp[yy]; + else if (yy >= h - bevel_size) ry = ramp[h - yy - 1]; + else ry = 1; + + r = rx * ry; + if (r != 1) + p[ch-1] *= r; + + p += ch; + } + line += rs; + } + +#if 0 /* show the ramp */ + line = data + (rs * y); + for (yy = 0; yy < h; yy++) + { + guchar *p = line + (x * ch); + for (xx = 0; xx < w; xx++) + { + int cc = 0; + for (cc = 0; cc < ch-1; cc++) + p[cc] = 255; + p += ch; + } + line += rs; + } +#endif + + free (ramp); + + if (verbose_p) + fprintf (stderr, "%s: added %d%% bevel (%d px)\n", progname, + bevel_pct, bevel_size); + } + + *pbP = pb; +} + + +static void +paste (const char *paste_file, + const char *base_file, + double from_scale, + double opacity, int bevel_pct, + int from_x, int from_y, int to_x, int to_y, + int w, int h) +{ + GdkPixbuf *paste_pb; + GdkPixbuf *base_pb; + + int paste_w, paste_h; + int base_w, base_h; + + paste_pb = load_pixbuf (paste_file); + base_pb = load_pixbuf (base_file); + + paste_w = gdk_pixbuf_get_width (paste_pb); + paste_h = gdk_pixbuf_get_height (paste_pb); + + base_w = gdk_pixbuf_get_width (base_pb); + base_h = gdk_pixbuf_get_height (base_pb); + + if (verbose_p) + { + fprintf (stderr, "%s: loaded %s: %dx%d\n", + progname, base_file, base_w, base_h); + fprintf (stderr, "%s: loaded %s: %dx%d\n", + progname, paste_file, paste_w, paste_h); + } + + if (from_scale != 1.0) + { + int new_w = paste_w * from_scale; + int new_h = paste_h * from_scale; + GdkPixbuf *new_pb = gdk_pixbuf_scale_simple (paste_pb, new_w, new_h, + GDK_INTERP_HYPER); + gdk_pixbuf_unref (paste_pb); + paste_pb = new_pb; + paste_w = gdk_pixbuf_get_width (paste_pb); + paste_h = gdk_pixbuf_get_height (paste_pb); + + if (verbose_p) + fprintf (stderr, "%s: %s: scaled to %dx%d (%.2f)\n", + progname, paste_file, paste_w, paste_h, from_scale); + } + + if (w == 0) w = paste_w - from_x; + if (h == 0) h = paste_h - from_y; + + { + int ofx = from_x; + int ofy = from_y; + int otx = to_x; + int oty = to_y; + int ow = w; + int oh = h; + + int clipped = 0; + + if (from_x < 0) /* from left out of bounds */ + { + w += from_x; + from_x = 0; + clipped = 1; + } + + if (from_y < 0) /* from top out of bounds */ + { + h += from_y; + from_y = 0; + clipped = 1; + } + + if (to_x < 0) /* to left out of bounds */ + { + w += to_x; + from_x -= to_x; + to_x = 0; + clipped = 1; + } + + if (to_y < 0) /* to top out of bounds */ + { + h += to_y; + from_y -= to_y; + to_y = 0; + clipped = 1; + } + + if (from_x + w > paste_w) /* from right out of bounds */ + { + w = paste_w - from_x; + clipped = 1; + } + + if (from_y + h > paste_h) /* from bottom out of bounds */ + { + h = paste_h - from_y; + clipped = 1; + } + + if (to_x + w > base_w) /* to right out of bounds */ + { + w = base_w - to_x; + clipped = 1; + } + + if (to_y + h > base_h) /* to bottom out of bounds */ + { + h = base_h - to_y; + clipped = 1; + } + + + if (clipped && verbose_p) + { + fprintf (stderr, "clipped from: %dx%d %d,%d %d,%d\n", + ow, oh, ofx, ofy, otx, oty); + fprintf (stderr, "clipped to: %dx%d %d,%d %d,%d\n", + w, h, from_x, from_y, to_x, to_y); + } + } + + if (bevel_pct > 0) + bevel_image (&paste_pb, bevel_pct, + from_x, from_y, w, h); + + if (opacity == 1.0 && bevel_pct == 0) + gdk_pixbuf_copy_area (paste_pb, + from_x, from_y, w, h, + base_pb, + to_x, to_y); + else + { + from_x++; /* gdk_pixbuf_composite gets confused about the bevel: */ + from_y++; /* it leaves a stripe on the top and left if we try to */ + to_x++; /* start at 0,0, so pull it right and down by 1 pixel. */ + to_y++; /* (problem seen in gtk2-2.4.14-2.fc3) */ + w--; + h--; + + if (w > 0 && h > 0) + gdk_pixbuf_composite (paste_pb, base_pb, + to_x, to_y, w, h, + to_x - from_x, to_y - from_y, + 1.0, 1.0, + GDK_INTERP_HYPER, + opacity * 255); + } + + if (verbose_p) + fprintf (stderr, "%s: pasted %dx%d from %d,%d to %d,%d\n", + progname, paste_w, paste_h, from_x, from_y, to_x, to_y); + + gdk_pixbuf_unref (paste_pb); + write_pixbuf (base_pb, base_file); + gdk_pixbuf_unref (base_pb); +} + + +static void +write_pixbuf (GdkPixbuf *pb, const char *file) +{ + int jpeg_quality = 85; + + int w = gdk_pixbuf_get_width (pb); + int h = gdk_pixbuf_get_height (pb); + guchar *data = gdk_pixbuf_get_pixels (pb); + int ww = gdk_pixbuf_get_rowstride (pb); + int channels = gdk_pixbuf_get_n_channels (pb); + + struct jpeg_compress_struct cinfo; + struct jpeg_error_mgr jerr; + FILE *out; + + if (channels != 3) + { + fprintf (stderr, "%s: %d channels?\n", progname, channels); + exit (1); + } + + cinfo.err = jpeg_std_error (&jerr); + jpeg_create_compress (&cinfo); + + out = fopen (file, "wb"); + if (!out) + { + char buf[255]; + sprintf (buf, "%.100s: %.100s", progname, file); + perror (buf); + exit (1); + } + else if (verbose_p) + fprintf (stderr, "%s: writing %s...", progname, file); + + jpeg_stdio_dest (&cinfo, out); + + cinfo.image_width = w; + cinfo.image_height = h; + cinfo.input_components = channels; + cinfo.in_color_space = JCS_RGB; + + jpeg_set_defaults (&cinfo); + jpeg_simple_progression (&cinfo); + jpeg_set_quality (&cinfo, jpeg_quality, TRUE); + + jpeg_start_compress (&cinfo, TRUE); + add_jpeg_comment (&cinfo); + + { + guchar *d = data; + guchar *end = d + (ww * h); + while (d < end) + { + jpeg_write_scanlines (&cinfo, &d, 1); + d += ww; + } + } + + jpeg_finish_compress (&cinfo); + jpeg_destroy_compress (&cinfo); + + if (verbose_p) + { + struct stat st; + fflush (out); + if (fstat (fileno (out), &st)) + { + char buf[255]; + sprintf (buf, "%.100s: %.100s", progname, file); + perror (buf); + exit (1); + } + fprintf (stderr, " %luK\n", ((unsigned long) st.st_size + 1023) / 1024); + } + + fclose (out); +} + + +static void +add_jpeg_comment (struct jpeg_compress_struct *cinfo) +{ + time_t now = time ((time_t *) 0); + struct tm *tm = localtime (&now); + const char fmt[] = + "\r\n" + " Generated by WebCollage: Exterminate All Rational Thought. \r\n" + " Copyright (c) 1999-%Y by Jamie Zawinski \r\n" + "\r\n" + " http://www.jwz.org/webcollage/ \r\n" + "\r\n" + " This is what the web looked like on %d %b %Y at %I:%M:%S %p %Z. \r\n" + "\r\n"; + char comment[sizeof(fmt) + 100]; + strftime (comment, sizeof(comment)-1, fmt, tm); + jpeg_write_marker (cinfo, JPEG_COM, + (unsigned char *) comment, + strlen (comment)); +} + + +static void +usage (void) +{ + fprintf (stderr, "usage: %s [-v] paste-file base-file\n" + "\t from-scale opacity\n" + "\t from-x from-y to-x to-y w h\n" + "\n" + "\t Pastes paste-file into base-file.\n" + "\t base-file will be overwritten (with JPEG data.)\n" + "\t scaling is applied first: coordinates apply to scaled image.\n", + progname); + exit (1); +} + + +int +main (int argc, char **argv) +{ + int i; + char *paste_file, *base_file, *s, dummy; + double from_scale, opacity; + int from_x, from_y, to_x, to_y, w, h, bevel_pct; + + i = 0; + progname = argv[i++]; + s = strrchr (progname, '/'); + if (s) progname = s+1; + + if (argc != 11 && argc != 12) usage(); + + if (!strcmp(argv[i], "-v")) + verbose_p++, i++; + + paste_file = argv[i++]; + base_file = argv[i++]; + + if (*paste_file == '-') usage(); + if (*base_file == '-') usage(); + + s = argv[i++]; + if (1 != sscanf (s, " %lf %c", &from_scale, &dummy)) usage(); + if (from_scale <= 0 || from_scale > 100) usage(); + + s = argv[i++]; + if (1 != sscanf (s, " %lf %c", &opacity, &dummy)) usage(); + if (opacity <= 0 || opacity > 1) usage(); + + s = argv[i++]; if (1 != sscanf (s, " %d %c", &from_x, &dummy)) usage(); + s = argv[i++]; if (1 != sscanf (s, " %d %c", &from_y, &dummy)) usage(); + s = argv[i++]; if (1 != sscanf (s, " %d %c", &to_x, &dummy)) usage(); + s = argv[i++]; if (1 != sscanf (s, " %d %c", &to_y, &dummy)) usage(); + s = argv[i++]; if (1 != sscanf (s, " %d %c", &w, &dummy)) usage(); + s = argv[i++]; if (1 != sscanf (s, " %d %c", &h, &dummy)) usage(); + + bevel_pct = 10; /* #### */ + + if (w < 0) usage(); + if (h < 0) usage(); + +#ifdef HAVE_GTK2 + g_type_init (); +#endif /* HAVE_GTK2 */ + + paste (paste_file, base_file, + from_scale, opacity, bevel_pct, + from_x, from_y, to_x, to_y, + w, h); + exit (0); +} + +#endif /* HAVE_GDK_PIXBUF && HAVE_JPEGLIB -- whole file */ diff --git a/hacks/webcollage.man b/hacks/webcollage.man new file mode 100644 index 00000000..5ad66252 --- /dev/null +++ b/hacks/webcollage.man @@ -0,0 +1,247 @@ +.de EX \"Begin example +.ne 5 +.if n .sp 1 +.if t .sp .5 +.nf +.in +.5i +.. +.de EE +.fi +.in -.5i +.if n .sp 1 +.if t .sp .5 +.. +.TH XScreenSaver 1 "17-Jun-99" "X Version 11" +.SH NAME +webcollage - decorate the screen with random images from the web +.SH SYNOPSIS +.B webcollage +[\-display \fIhost:display.screen\fP] +[\-root] +[\-window\-id \fIid\fP] +[\-verbose] +[\-timeout \fIsecs\fP] +[\-delay \fIsecs\fP] +[\-background \fIbg\fP] +[\-no-output] +[\-urls-only] +[\-imagemap \fIfilename-base\fP] +[\-size \fIWxH\fP] +[\-opacity \fIratio\fP] +[\-filter \fIcommand\fP] +[\-filter2 \fIcommand\fP] +[\-http\-proxy host[:port]] +[\-dictionary \fIdictionary-file\fP] +[\-driftnet [\fIcmd\fP]] +[\-directory \fIdir\fP] +[\-fps] +.SH DESCRIPTION +The \fIwebcollage\fP program pulls random image off of the World Wide Web +and scatters them on the root window. One satisfied customer described it +as "a nonstop pop culture brainbath." This program finds its images by +doing random web searches, and extracting images from the returned pages. + +\fIwebcollage\fP is written in +.BR perl (1) +and requires Perl 5. + +It will be an order of magnitude faster if you also have +the \fIwebcollage-helper\fP program installed (a GDK/JPEG image +compositor), but \fIwebcollage\fP works without it as well. + +\fIwebcollage\fP can be used in conjunction with the +.BR driftnet (1) +program (the Unix equivalent of EtherPEG) to snoop images from traffic +on your local subnet, instead of getting images from search engines. +.SH OPTIONS +.I webcollage +accepts the following options: +.TP 8 +.B \-root +Draw on the root window. This option is mandatory, if output is being +produced: drawing to a window other than the root window is not yet +supported. + +Images are placed on the root window by using one of the +.BR xscreensaver-getimage (1), +.BR chbg (1), +.BR xv (1), +.BR xli (1), +or +.BR xloadimage (1) +programs (whichever is available.) +.TP 8 +.B \-window\-id \fIid\fP +Draw to the indicated window instead; this only works if the +.BR xscreensaver-getimage (1) +program is installed. +.TP 8 +.B \-verbose \fRor\fP \-v +Print diagnostics to stderr. Multiple \fI-v\fP switches increase the +amount of output. \fI-v\fP will print out the URLs of the images, +and where they were placed; \fI-vv\fP will print out any warnings, +and all URLs being loaded; \fI-vvv\fP will print information on +what URLs were rejected; and so on. +.TP 8 +.B \-timeout \fIseconds\fP +How long to wait for a URL to complete before giving up on it and +moving on to the next one. +Default 30 seconds. +.TP 8 +.B \-delay \fIseconds\fP +How long to sleep between images. Default 2 seconds. (Remember that +this program probably spends a lot of time waiting for the network.) +.TP 8 +.B \-background \fIcolor-or-ppm\fP +What to use for the background onto which images are pasted. This may be +a color name, a hexadecimal RGB specification in the form '#rrggbb', or +the name of a PPM file. +.TP 8 +.B \-size \fIWxH\fP +Normally, the output image will be made to be the size of the +screen (or target window.) This lets you specify the desired size. +.TP 8 +.B \-opacity \fIratio\fP +How transparently to paste the images together, with 0.0 meaning +"completely transparent" and 1.0 meaning "opaque." Default 0.85. +A value of around 0.3 will produce an interestingly blurry image +after a while. +.TP 8 +.B \-no-output +If this option is specified, then no composite output image will be +generated. This is only useful when used in conjunction +with \fB\-verbose\fP. +.TP 8 +.B \-urls-only +If this option is specified, then no composite output image will be +generated: instead, a list of image URLs will be printed on stdout. +.TP 8 +.B \-imagemap \fIfilename-base\fP +If this option is specified, then instead of writing an image to the +root window, two files will be created: "\fIbase\fP.html" and "\fIbase\fP.jpg". +The JPEG will be the collage; the HTML file will include that image, and +an image-map making the sub-images be linked to the pages on which they +were found (just like \fIhttp://www.jwz.org/webcollage/\fP.) +.TP 8 +.B \-filter \fIcommand\fP +Filter all source images through this command. The command must take +a PPM file on stdin, and write a new PPM file to stdout. One good +choice for a filter would be: +.EX +webcollage -root -filter 'vidwhacker -stdin -stdout' +.EE +.TP 8 +.B \-filter2 \fIcommand\fP +Filter the \fIcomposite\fP image through this command. The \fI-filter\fP +option applies to the sub-images; the \fI-filter2\fP applies to the +final, full-screen image. +.TP 8 +.B \-http\-proxy \fIhost:port\fP +If you must go through a proxy to connect to the web, you can specify it +with this option, or with the \fB$http_proxy\fP or \fB$HTTP_PROXY\fP +environment variables. +.TP 8 +.B \-dictionary \fIfile\fP +Webcollage normally looks at the system's default spell-check dictionary +to generate words to feed into the search engines. You can specify an +alternate dictionary with this option. + +Note that by default, webcollage searches for images using several +different methods, not all of which involve dictionary words, so +using a "topical" dictionary file will not, in itself, be as effective +as you might be hoping. +.TP 8 +.B \-driftnet \fI[ args ]\fP +.BR driftnet (1) +is a program that snoops your local ethernet for packets that look +like they might be image files. It can be used in conjunction +with \fIwebcollage\fP to generate a collage of what other people on +your network are looking at, instead of a search-engine collage. +If you have \fIdriftnet\fP installed on your $PATH, just use +the \fI\-driftnet\fP option. You can also specify the location +of the program like this: +.EX +-driftnet /path/to/driftnet +.EE +or, you can provide extra arguments like this: +.EX +-driftnet '/path/to/driftnet -extra -args' +.EE +Driftnet version 0.1.5 or later is required. Note that +the \fIdriftnet\fP program requires root access, so you'll have +to make \fIdriftnet\fP be setuid-root for this to work. +Please exercise caution. +.TP 8 +.B \-directory \fIdir\fP +Instead of searching the web for images, use the contents of +the given directory. +.TP 8 +.B \-fps +Display the current frame rate and CPU load (MacOS only). +.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. +.TP 8 +.B http_proxy\fR or \fPHTTP_PROXY +to get the default HTTP proxy host and port. +.SH FILES AND URLS +.I /usr/dict/words, +.I /usr/share/lib/dict/words,\fP +or +.I /usr/share/dict/words +to find the random words to feed to certain search engines. + + \fIhttp://www.altavista.com/image/randomlink\fP, + \fIhttp://random.yahoo.com/fast/ryl\fP, + \fIhttp://www.livejournal.com/stats/latest-img.bml\fP, and + \fIhttp://www.google.com/\fP +to find random web pages. +.SH BOOBIES +The Internet being what it is, absolutely anything might show up in the +collage including -- quite possibly -- pornography, or even nudity. +.SH BUGS +Animating GIFs are not supported: only the first frame will be used. +.SH UPGRADES +The latest version of webcollage can be found as a part of +xscreensaver, at +.B http://www.jwz.org/xscreensaver/, +or on the WebCollage page at +.B http://www.jwz.org/webcollage/. + +DriftNet: +.B http://www.ex-parrot.com/~chris/driftnet/ +.SH SEE ALSO +.BR X (1), +.BR xscreensaver (1), +.BR xli (1), +.BR xv (1), +.BR xloadimage (1), +.BR ppmmake (1), +.BR giftopnm (1), +.BR pnmpaste (1), +.BR pnmscale (1), +.BR djpeg (1), +.BR cjpeg (1), +.BR xdpyinfo (1), +.BR perl (1), +.BR vidwhacker (MANSUFFIX), +.BR dadadodo (1), +.BR driftnet (1) +.BR EtherPEG , +.BR EtherPeek +.SH COPYRIGHT +Copyright \(co 1998-2005 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 , 24-May-1998. diff --git a/hacks/whirlwindwarp.c b/hacks/whirlwindwarp.c new file mode 100644 index 00000000..566c4187 --- /dev/null +++ b/hacks/whirlwindwarp.c @@ -0,0 +1,502 @@ +/* xscreensaver, Copyright (c) 2000 Paul "Joey" Clark + * + * 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. + * + * 19971004: Johannes Keukelaar : Use helix screen + * eraser. + */ + +/* WhirlwindWarp: moving stars. Ported from QBasic by Joey. + Version 1.3. Smooth with pretty colours. + + This code adapted from original program by jwz/jk above. + Freely distrubtable. Please keep this tag with + this code, and add your own if you contribute. + I would be delighted to hear if have made use of this code. + If you find this code useful or have any queries, please + contact me: pclark@cs.bris.ac.uk / joeyclark@usa.net + Paul "Joey" Clark, hacking for humanity, Feb 99 + www.cs.bris.ac.uk/~pclark | www.changetheworld.org.uk */ + +/* 15/May/05: Added colour rotation, limit on max FPS, scaling size dots, and smoother drivers. + 4/Mar/01: Star colours are cycled when new colour can not be allocated. + 4/Mar/01: Stars are plotted as squares with size relative to screen. + 28/Nov/00: Submitted to xscreensaver as "whirlwindwarp". + 10/Oct/00: Ported to xscreensaver as "twinkle". + 19/Feb/98: Meters and interaction added for Ivor's birthday "stars11f". + 11/Aug/97: Original QBasic program. */ + +#include + +#include "screenhack.h" +#include "erase.h" +#include "hsv.h" + +/* Maximum number of points, maximum tail length, and the number of forcefields/effects (hard-coded) */ +#define maxps 1000 +#define maxts 50 +#define fs 16 +/* TODO: change ps and ts arrays into pointers, for dynamic allocation at runtime. */ + +struct state { + Display *dpy; + Window window; + + GC draw_gc, erase_gc; + unsigned int default_fg_pixel; + + int scrwid,scrhei; + int starsize; + + float cx[maxps]; /* Current x,y of stars in realspace */ + float cy[maxps]; + int tx[maxps*maxts]; /* Previous x,y plots in pixelspace for removal later */ + int ty[maxps*maxts]; + char *name[fs]; /* The force fields and their parameters */ + + int fon[fs]; /* Is field on or off? */ + float var[fs]; /* Current parameter */ + float op[fs]; /* Optimum (central/mean) value */ + float acc[fs]; + float vel[fs]; + + int ps; /* Number of points and tail length */ + int ts; + + Bool meters; + + int initted; + XWindowAttributes xgwa; + int got_color; + XColor color[maxps]; /* The colour assigned to each star */ + XColor bgcolor; + int p,f,nt, sx,sy, resets,lastresets,cnt; + int colsavailable; + int hue; + + struct timeval lastframe; +}; + + +static void * +whirlwindwarp_init (Display *dpy, Window window) +{ + struct state *st = (struct state *) calloc (1, sizeof(*st)); + XGCValues gcv; + Colormap cmap; + + st->dpy = dpy; + st->window = window; + + st->ps=500; + st->ts=5; + + XGetWindowAttributes (st->dpy, st->window, &st->xgwa); + cmap = st->xgwa.colormap; + gcv.foreground = st->default_fg_pixel = get_pixel_resource (st->dpy, cmap, "foreground", "Foreground"); + st->draw_gc = XCreateGC (st->dpy, st->window, GCForeground, &gcv); + gcv.foreground = get_pixel_resource (st->dpy, cmap, "background", "Background"); + st->erase_gc = XCreateGC (st->dpy, st->window, GCForeground, &gcv); + + st->ps = get_integer_resource (st->dpy, "points", "Integer"); + st->ts = get_integer_resource (st->dpy, "tails", "Integer"); + st->meters = get_boolean_resource (st->dpy, "meters", "Show meters"); + if (st->ps > maxps) st->ps = maxps; + if (st->ts > maxts) st->ts = maxts; + + return st; +} + +static float myrnd(void) +{ /* between -1.0 (inclusive) and +1.0 (exclusive) */ + return 2.0*((float)((random()%10000000)/10000000.0)-0.5); +} + +#if 0 +static float mysgn(float x) +{ + return ( x < 0 ? -1 : + x > 0 ? +1 : + 0 ); +} +#endif + +static void stars_newp(struct state *st, int pp) +{ + st->cx[pp]=myrnd(); + st->cy[pp]=myrnd(); +} + +/* Adjust a variable var about optimum op, + with damp = dampening about op + force = force of random perturbation */ +/* float stars_perturb(float var,float op,float damp,float force) { + return op+damp*(var-op)+force*myrnd()/4.0; + }*/ +#define stars_perturb(var,op,damp,force) \ + ( (op) + (damp)*((var)-(op)) + (force)*myrnd()/4.0 ) + +/* Get pixel coordinates of a star */ +static int stars_scrpos_x(struct state *st, int pp) +{ + return st->scrwid*(st->cx[pp]+1.0)/2.0; +} + +static int stars_scrpos_y(struct state *st, int pp) +{ + return st->scrhei*(st->cy[pp]+1.0)/2.0; +} + +/* Draw a meter of a forcefield's parameter */ +static void stars_draw_meter(struct state *st, int ff) +{ + int x,y,w,h; + x=st->scrwid/2; + y=ff*10; + w=(st->var[ff]-st->op[ff])*st->scrwid*4; + h=7; + if (w<0) { + w=-w; + x=x-w; + } + if (st->fon[ff]) + XFillRectangle(st->dpy,st->window,st->draw_gc,x,y,w,h); + /* else + XDrawRectangle(dpy,window,draw_gc,x,y,w,h); */ +} + +/* Move a star according to acting forcefields */ +static void stars_move(struct state *st, int pp) +{ + float nx,ny; + float x=st->cx[pp]; + float y=st->cy[pp]; + + /* In theory all these if checks are unneccessary, + since each forcefield effect should do nothing when its var = op. + But the if's are good for efficiency because this function + is called once for every point. + + Squirge towards edges (makes a leaf shape, previously split the screen in 4 but now only 1 :) + These ones must go first, to avoid x+1.0 < 0 + */ + if (st->fon[6]) { + /* x = mysgn(x) * pow(fabs(x),var[6]); + y = mysgn(y) * pow(fabs(y),var[6]);*/ + x = -1.0 + 2.0*pow((x + 1.0)/2.0,st->var[6]); + } + if (st->fon[7]) { + y = -1.0 + 2.0*pow((y + 1.0)/2.0,st->var[7]); + } + + /* Warping in/out */ + if (st->fon[1]) { + x = x * st->var[1]; y = y * st->var[1]; + } + + /* Rotation */ + if (st->fon[2]) { + nx=x*cos(1.1*st->var[2])+y*sin(1.1*st->var[2]); + ny=-x*sin(1.1*st->var[2])+y*cos(1.1*st->var[2]); + x=nx; + y=ny; + } + + /* Asymptotes (looks like a plane with a horizon; equivalent to 1D warp) */ + if (st->fon[3]) { /* Horizontal asymptote */ + y=y*st->var[3]; + } + if (st->fon[4]) { /* Vertical asymptote */ + x=x+st->var[4]*x; /* this is the same maths as the last, but with op=0 */ + } + if (st->fon[5]) { /* Vertical asymptote at right of screen */ + x=(x-1.0)*st->var[5]+1.0; + } + + /* Splitting (whirlwind effect): */ + #define num_splits ( 2 + (int) (fabs(st->var[0]) * 1000) ) + /* #define thru ( (float)(pp%num_splits)/(float)(num_splits-1) ) */ + #define thru ( (float)((int)(num_splits*(float)(pp)/(float)(st->ps)))/(float)(num_splits-1) ) + if (st->fon[8]) { + x=x+0.5*st->var[8]*(-1.0+2.0*thru); + } + if (st->fon[9]) { + y=y+0.5*st->var[9]*(-1.0+2.0*thru); + } + + /* Waves */ + if (st->fon[10]) { + y = y + 0.4*st->var[10]*sin(300.0*st->var[12]*x + 600.0*st->var[11]); + } + if (st->fon[13]) { + x = x + 0.4*st->var[13]*sin(300.0*st->var[15]*y + 600.0*st->var[14]); + } + + st->cx[pp]=x; + st->cy[pp]=y; +} + +/* Turns a forcefield on, and ensures its vars are suitable. */ +static void turn_on_field(struct state *st, int ff) +{ + if (!st->fon[ff]) { + /* acc[ff]=0.0; */ + st->acc[ff]=0.02 * myrnd(); + st->vel[ff]=0.0; + st->var[ff]=st->op[ff]; + } + st->fon[ff] = 1; + if (ff == 10) { + turn_on_field(st, 11); + turn_on_field(st, 12); + } + if (ff == 13) { + turn_on_field(st, 14); + turn_on_field(st, 15); + } +} + +static unsigned long +whirlwindwarp_draw (Display *dpy, Window window, void *closure) +{ + struct state *st = (struct state *) closure; + + /* time_t lastframe = time((time_t) 0); */ + + if (!st->initted) { + st->initted = 1; + + XClearWindow (st->dpy, st->window); + XGetWindowAttributes (st->dpy, st->window, &st->xgwa); + st->scrwid = st->xgwa.width; + st->scrhei = st->xgwa.height; + + st->starsize=st->scrhei/480; + if (st->starsize<=0) + st->starsize=1; + + /* Setup colours */ + hsv_to_rgb (0.0, 0.0, 0.0, &st->bgcolor.red, &st->bgcolor.green, &st->bgcolor.blue); + st->got_color = XAllocColor (st->dpy, st->xgwa.colormap, &st->bgcolor); + st->colsavailable=0; + for (st->p=0;st->pps;st->p++) { + if (!mono_p) + hsv_to_rgb (random()%360, .6+.4*myrnd(), .6+.4*myrnd(), &st->color[st->p].red, &st->color[st->p].green, &st->color[st->p].blue); + /* hsv_to_rgb (random()%360, 1.0, 1.0, &color[p].red, &color[p].green, &color[p].blue); for stronger colours! */ + if ((!mono_p) && (st->got_color = XAllocColor (st->dpy, st->xgwa.colormap, &st->color[st->p]))) { + st->colsavailable=st->p; + } else { + if (st->colsavailable>0) /* assign colours from those already allocated */ + st->color[st->p]=st->color[ st->p % st->colsavailable ]; + else + st->color[st->p].pixel=st->default_fg_pixel; + } + } + + /* Set up central (optimal) points for each different forcefield */ + st->op[1] = 1; st->name[1] = "Warp"; + st->op[2] = 0; st->name[2] = "Rotation"; + st->op[3] = 1; st->name[3] = "Horizontal asymptote"; + st->op[4] = 0; st->name[4] = "Vertical asymptote"; + st->op[5] = 1; st->name[5] = "Vertical asymptote right"; + st->op[6] = 1; st->name[6] = "Squirge x"; + st->op[7] = 1; st->name[7] = "Squirge y"; + st->op[0] = 0; st->name[0] = "Split number (inactive)"; + st->op[8] = 0; st->name[8] = "Split velocity x"; + st->op[9] = 0; st->name[9] = "Split velocity y"; + st->op[10] = 0; st->name[10] = "Horizontal wave amplitude"; + st->op[11] = myrnd()*3.141; st->name[11] = "Horizontal wave phase (inactive)"; + st->op[12] = 0.01; st->name[12] = "Horizontal wave frequency (inactive)"; + st->op[13] = 0; st->name[13] = "Vertical wave amplitude"; + st->op[14] = myrnd()*3.141; st->name[14] = "Vertical wave phase (inactive)"; + st->op[15] = 0.01; st->name[15] = "Vertical wave frequency (inactive)"; + + /* Initialise parameters to optimum, all off */ + for (st->f=0;st->ff++) { + st->var[st->f]=st->op[st->f]; + st->fon[st->f]=( myrnd()>0.5 ? 1 : 0 ); + st->acc[st->f]=0.02 * myrnd(); + st->vel[st->f]=0; + } + + /* Initialise stars */ + for (st->p=0;st->pps;st->p++) + stars_newp(st, st->p); + + /* tx[nt],ty[nt] remember earlier screen plots (tails of stars) + which are deleted when nt comes round again */ + st->nt = 0; + st->resets = 0; + + st->hue = 180 + 180*myrnd(); + + gettimeofday(&st->lastframe, NULL); + + } + + + if (myrnd()>0.75) { + /* Change one of the allocated colours to something near the current hue. */ + /* By changing a random colour, we sometimes get a tight colour spread, sometime a diverse one. */ + int pp = st->colsavailable * (0.5+myrnd()/2); + hsv_to_rgb (st->hue, .6+.4*myrnd(), .6+.4*myrnd(), &st->color[pp].red, &st->color[pp].green, &st->color[pp].blue); + if ((!mono_p) && (st->got_color = XAllocColor (st->dpy, st->xgwa.colormap, &st->color[pp]))) { + } + st->hue = st->hue + 0.5 + myrnd()*9.0; + if (st->hue<0) st->hue+=360; + if (st->hue>=360) st->hue-=360; + } + + /* Move current points */ + st->lastresets=st->resets; + st->resets=0; + for (st->p=0;st->pps;st->p++) { + /* Erase old */ + XSetForeground (st->dpy, st->draw_gc, st->bgcolor.pixel); + /* XDrawPoint(dpy,window,draw_gc,tx[nt],ty[nt]); */ + XFillRectangle(st->dpy,st->window,st->draw_gc,st->tx[st->nt],st->ty[st->nt],st->starsize,st->starsize); + + /* Move */ + stars_move(st, st->p); + /* If moved off screen, create a new one */ + if (st->cx[st->p]<=-0.9999 || st->cx[st->p]>=+0.9999 || + st->cy[st->p]<=-0.9999 || st->cy[st->p]>=+0.9999 || + fabs(st->cx[st->p])<.0001 || fabs(st->cy[st->p])<.0001) { + stars_newp(st, st->p); + st->resets++; + } else if (myrnd()>0.99) /* Reset at random */ + stars_newp(st, st->p); + + /* Draw point */ + st->sx=stars_scrpos_x(st, st->p); + st->sy=stars_scrpos_y(st, st->p); + XSetForeground (st->dpy, st->draw_gc, st->color[st->p].pixel); + /* XDrawPoint(dpy,window,draw_gc,sx,sy); */ + XFillRectangle(st->dpy,st->window,st->draw_gc,st->sx,st->sy,st->starsize,st->starsize); + + /* Remember it for removal later */ + st->tx[st->nt]=st->sx; + st->ty[st->nt]=st->sy; + st->nt=(st->nt+1)%(st->ps*st->ts); + } + + /* Adjust force fields */ + st->cnt=0; + for (st->f=0;st->ff++) { + + if (st->meters) { /* Remove meter from display */ + XSetForeground(st->dpy, st->draw_gc, st->bgcolor.pixel); + stars_draw_meter(st,st->f); + } + + /* Adjust forcefield's parameter */ + if (st->fon[st->f]) { + /* This configuration produces var[f]s usually below 0.01 */ + st->acc[st->f]=stars_perturb(st->acc[st->f],0,0.98,0.005); + st->vel[st->f]=stars_perturb(st->vel[st->f]+0.03*st->acc[st->f],0,0.995,0.0); + st->var[st->f]=st->op[st->f]+(st->var[st->f]-st->op[st->f])*0.9995+0.001*st->vel[st->f]; + } + /* fprintf(stderr,"f=%i fon=%i acc=%f vel=%f var=%f\n",f,fon[f],acc[f],vel[f],var[f]); */ + + /* Decide whether to turn this forcefield on or off. */ + /* prob_on makes the "splitting" effects less likely than the rest */ + #define prob_on ( st->f==8 || st->f==9 ? 0.999975 : 0.9999 ) + if ( st->fon[st->f]==0 && myrnd()>prob_on ) { + turn_on_field(st, st->f); + } else if ( st->fon[st->f]!=0 && myrnd()>0.99 && fabs(st->var[st->f]-st->op[st->f])<0.0005 && fabs(st->vel[st->f])<0.005 /* && fabs(acc[f])<0.01 */ ) { + /* We only turn it off if it has gently returned to its optimal (as opposed to rapidly passing through it). */ + st->fon[st->f] = 0; + } + + if (st->meters) { /* Redraw the meter */ + XSetForeground(st->dpy, st->draw_gc, st->color[st->f].pixel); + stars_draw_meter(st,st->f); + } + + if (st->fon[st->f]) + st->cnt++; + } + + /* Ensure at least three forcefields are on. + * BUG: Picking randomly might not be enough since 0,11,12,14 and 15 do nothing! + * But then what's wrong with a rare gentle twinkle?! + */ + if (st->cnt<3) { + st->f=random() % fs; + turn_on_field(st, st->f); + } + + if (st->meters) { + XSetForeground(st->dpy, st->draw_gc, st->bgcolor.pixel); + XDrawRectangle(st->dpy,st->window,st->draw_gc,0,0,st->lastresets*5,3); + XSetForeground(st->dpy, st->draw_gc, st->default_fg_pixel); + XDrawRectangle(st->dpy,st->window,st->draw_gc,0,0,st->resets*5,3); + } + + /* Cap frames per second; do not go above specified fps: */ + { + unsigned long this_delay = 0; + int maxfps = 200; + long utimeperframe = 1000000/maxfps; + struct timeval now; + long timediff; + gettimeofday(&now, NULL); + timediff = now.tv_sec*1000000 + now.tv_usec - st->lastframe.tv_sec*1000000 - st->lastframe.tv_usec; + if (timediff < utimeperframe) { + /* fprintf(stderr,"sleeping for %i\n",utimeperframe-timediff); */ + this_delay = (utimeperframe-timediff); + } + st->lastframe = now; + + return this_delay; + } +} + + +static void +whirlwindwarp_reshape (Display *dpy, Window window, void *closure, + unsigned int w, unsigned int h) +{ + struct state *st = (struct state *) closure; + st->scrwid = w; + st->scrhei = h; +} + +static Bool +whirlwindwarp_event (Display *dpy, Window window, void *closure, XEvent *event) +{ + return False; +} + +static void +whirlwindwarp_free (Display *dpy, Window window, void *closure) +{ + struct state *st = (struct state *) closure; + free (st); +} + + +static const char *whirlwindwarp_defaults [] = { + ".background: black", + ".foreground: white", + "*fpsSolid: true", + "*points: 400", + "*tails: 8", + "*meters: false", + 0 +}; + +static XrmOptionDescRec whirlwindwarp_options [] = { + { "-points", ".points", XrmoptionSepArg, 0 }, + { "-tails", ".tails", XrmoptionSepArg, 0 }, + { "-meters", ".meters", XrmoptionNoArg, "true" }, + { 0, 0, 0, 0 } +}; + +XSCREENSAVER_MODULE ("WhirlWindWarp", whirlwindwarp) diff --git a/hacks/whirlwindwarp.man b/hacks/whirlwindwarp.man new file mode 100644 index 00000000..8cd054fe --- /dev/null +++ b/hacks/whirlwindwarp.man @@ -0,0 +1,64 @@ +.TH XScreenSaver 1 "13-aug-92" "X Version 11" +.SH NAME +whirlwindwarp - crazy moving stars +.SH SYNOPSIS +.B whirlwindwarp +[\-display \fIhost:display.screen\fP] [\-foreground \fIcolor\fP] [\-background \fIcolor\fP] [\-window] [\-root] [\-mono] [\-install] [\-visual \fIvisual\fP] [\-points \fIinteger\fP] [\-tails \fIinteger\fP] +[\-fps] +.SH DESCRIPTION +\fIwhirlwindwarp\fP plots stars moving according to various forcefields +(simple 2D equations). +.SH WARNING! +This screensaver may be \fIdangerous\fP for your eyes. +Please don't watch it for too long! +.SH OPTIONS +.I whirlwindwarp +accepts the following options: +.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 \-mono +If on a color display, pretend we're on a monochrome display. +.TP 8 +.B \-install +Install a private colormap for the window. +.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 \-points \fIinteger\fP +The number of stars plotted (default 400). +.TP 8 +.B \-tails \fIinteger\fP +The length of the tail of each star (default 8). +.TP 8 +.B \-fps +Display the current frame rate and CPU load. +.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 (c) Paul "Joey" Clark. 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 +Paul "Joey" Clark 10-Oct-00 diff --git a/hacks/whirlygig.c b/hacks/whirlygig.c new file mode 100644 index 00000000..e5eb9d55 --- /dev/null +++ b/hacks/whirlygig.c @@ -0,0 +1,733 @@ +/* Whirlygig -- an experiment in X programming + * + * 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. + * + * When I was in trigonometry class as a kid, I remember being fascinated + * by the beauty of the shapes one receives when playing with sine waves + * Here is a little experiment to show that beauty is simple + */ + +#include +#include +#include "screenhack.h" + +#ifdef HAVE_DOUBLE_BUFFER_EXTENSION +# include "xdbe.h" +#endif /* HAVE_DOUBLE_BUFFER_EXTENSION */ + +#define NCOLORS 100 +#define FULL_CYCLE 429496729 +#define START_ARC 0 +#define END_ARC 23040 + +struct info { +/* Bool writable; / * Is the screen writable */ + double xspeed; /* A factor to modify the horizontal movement */ + double yspeed; /* A factor to modify vertical movement */ + double xamplitude; + double yamplitude; + int whirlies; /* How many whirlies per line do you want? */ + int nlines; /* How many lines of whirlies do you want? */ + int half_width; /* 1/2 the width of the screen */ + int half_height; + int speed; + int trail; + int color_modifier; + double xoffset; + double yoffset; + double offset_period; + Bool wrap; +}; + +enum object_mode { + spin_mode, funky_mode, circle_mode, linear_mode, test_mode, fun_mode, innie_mode, lissajous_mode +}; + +struct state { + Display *dpy; + Window window; + + XGCValues gcv; /* The structure to hold the GC data */ + XWindowAttributes xgwa; /* A structure to hold window data */ + Pixmap b, ba; /* double-buffer to reduce flicker */ +#ifdef HAVE_DOUBLE_BUFFER_EXTENSION + Bool dbeclear_p; + XdbeBackBuffer backb; +#endif /* HAVE_DOUBLE_BUFFER_EXTENSION */ + + GC fgc, bgc; + int screen; + Bool dbuf; + + unsigned long int current_time; /* The global int telling the current time */ + unsigned long int start_time; + struct info *info; + char *xmode_str, *ymode_str; /* holds the current mode for x and y computation */ + + /* pos is the current position x,y -- last_x contains one cell of + every x coordinate for every position of every whirly in every + line up to 100 whirlies in 100 lines -- lasy_y and last_size hold + the same information for y and size respectively */ + + int pos[2], last_x[100][100], last_y[100][100], last_size[100][100]; + int current_color; + Bool wrap; + int xmode, ymode; + double modifier; /* for innie */ + + XColor colors[NCOLORS]; + int ncolors; + int explaining; +}; + +static void draw_explain_string(struct state *, int, int, Display *, Window, GC); +static void spin(struct state *, unsigned long int, struct info *, int *, int); +static void funky(struct state *, unsigned long int, struct info *, int *, int); +static void circle(struct state *, unsigned long int, struct info *, int *, int); +static void fun(struct state *, unsigned long int, struct info *, int *, int); +static void linear(struct state *, unsigned long int, struct info *, int *, int); +static void lissajous(struct state *, unsigned long int, struct info *, int *, int); +static void test(struct state *, unsigned long int, struct info *, int *, int); +static void innie(struct state *, unsigned long int, struct info *, int *, int, double); + + + +static const char spin_explanation[] = +"Spin mode is a simple sin/cos with every argument modified"; + +static const char funky_explanation[] = +"Funky mode is me goofing off."; + +static const char circle_explanation[] = +"Circle mode graphs the x and y positions as you trace the edge of a circle over time."; + +static const char linear_explanation[] = +"Linear mode draws a straight line"; + +static const char test_explanation[] = +"Test mode is a mode that I play around with ideas in."; + +static const char fun_explanation[] = +"Fun mode is the coolest."; + +static const char innie_explanation[] = +"Innie mode does something or other. Looks cool, though."; + +static const char lissajous_explanation[] = +"Lissajous mode draws a slightly modified lissajous curve"; + +static void +draw_explain_string(struct state *st, int mode, int offset, Display *dpy, Window window, GC fgc) +{ + switch(mode) { + case spin_mode: + XDrawString(st->dpy, st->window, st->fgc, 50, offset, + (char*) spin_explanation, strlen(spin_explanation)); + break; + case funky_mode: + XDrawString(st->dpy, st->window, st->fgc, 50, offset, + (char*) funky_explanation, strlen(funky_explanation)); + break; + case circle_mode: + XDrawString(st->dpy, st->window, st->fgc, 50, offset, + (char*) circle_explanation, strlen(circle_explanation)); + break; + case linear_mode: + XDrawString(st->dpy, st->window, st->fgc, 50, offset, + (char*) linear_explanation, strlen(linear_explanation)); + break; + case test_mode: + XDrawString(st->dpy, st->window, st->fgc, 50, offset, + (char*) test_explanation, strlen(test_explanation)); + break; + case fun_mode: + XDrawString(st->dpy, st->window, st->fgc, 50, offset, + (char*) fun_explanation, strlen(fun_explanation)); + break; + case innie_mode: + XDrawString(st->dpy, st->window, st->fgc, 50, offset, + (char*) innie_explanation, strlen(innie_explanation)); + break; + case lissajous_mode: + XDrawString(st->dpy, st->window, st->fgc, 50, offset, + (char*) lissajous_explanation, strlen(linear_explanation)); + } +} + +static void +funky(struct state *st, unsigned long int the_time, struct info *info, int pos[], int index) +{ + double new_time = ((the_time % 360 ) / 180.0) * M_PI; + if (index == 0) { + double time_modifier = cos(new_time / 180.0); + double the_cos = cos((new_time * (double)st->info->xspeed) + (time_modifier * 80.0)); + double dist_mod_x = cos(new_time) * (st->info->half_width - 50); + st->pos[index]= st->info->xamplitude * (the_cos * dist_mod_x) + st->info->half_width; + } + else { + double new_time = ((the_time % 360 ) / 180.0) * M_PI; + double time_modifier = sin(new_time / 180.0); + double the_sin = sin((new_time * (double)st->info->yspeed) + (time_modifier * 80.0)); + double dist_mod_y = sin(new_time) * (st->info->half_height - 50); + st->pos[index] = st->info->yamplitude * (the_sin * dist_mod_y) + st->info->half_height; + } +} + +static void +innie(struct state *st, unsigned long int the_time, struct info *info, int pos[], int index, double modifier) +{ + double frequency = 2000000.0 + (st->modifier * cos(((double)the_time / 100.0))); + double arg = (double)the_time / frequency; + double amplitude = 200.0 * cos(arg); + double fun = 150.0 * cos((double)the_time / 2000.0); + int vert_mod, horiz_mod; + if (index == 0) { + horiz_mod = (int)(fun * cos((double)the_time / 100.0)) + st->info->half_width; + st->pos[index] = (amplitude * cos((double)the_time / 100.0 * st->info->xspeed)) + horiz_mod; + } + else { + vert_mod = (int)(fun * sin((double)the_time / 100.0)) + st->info->half_height; + st->pos[index] = (amplitude * sin((double)the_time / 100.0 * st->info->yspeed)) + vert_mod; + } +} + +static void +lissajous(struct state *st, unsigned long int the_time, struct info *info, int pos[], int index) +{ + /* This is a pretty standard lissajous curve + x = a sin(nt + c) + y = b sin(t) + The n and c modifiers are cyclic as well, however... */ + int result; + double time = (double)the_time / 100.0; + double fun = 15.0 * cos((double)the_time / 800.0); + double weird = cos((time / 1100000.0) / 1000.0); + + if (index == 0) { + result = st->info->xamplitude * 200.0 * sin((weird * time) + fun) + st->info->half_width; + } + else { + result = st->info->yamplitude * 200.0 * sin(time) + st->info->half_height; + } + st->pos[index] = result; +} + +static void +circle(struct state *st, unsigned long int the_time, struct info *info, int pos[], int index) +{ + int result; + if (index == 0) { + result = st->info->xamplitude * (cos((double)the_time / 100.0 * st->info->xspeed) * (st->info->half_width / 2)) + st->info->half_width; + } + else { + result = st->info->yamplitude * (sin((double)the_time / 100.0 * st->info->yspeed) * (st->info->half_height / 2)) + st->info->half_height; + } + st->pos[index] = result; +} + +#if 0 +static void +mod(unsigned long int the_time, struct info *info, int pos[], int index) +{ + int amplitude; + int max = st->info->half_width; + if ((the_time % (max * 2)) < max) + amplitude = max - ((the_time % (max * 2)) - max); + else + amplitude = the_time % (max * 2); + amplitude = amplitude - max; +} +#endif + +static void +spin(struct state *st, unsigned long int the_time, struct info *info, int pos[], int index) +{ + double funky = (((the_time % 360) * 1.0) / 180.0) * M_PI; + if (index ==0) { + double the_cos = cos((double)the_time / (180.0 * st->info->xspeed)); + double dist_mod_x = cos((double)funky) * (st->info->half_width - 50); + st->pos[index] = st->info->xamplitude * (the_cos * dist_mod_x) + st->info->half_width; + } + else { + double the_sin = sin((double)the_time / (180.0 * st->info->yspeed)); + double dist_mod_y = sin((double)funky) * (st->info->half_height - 50); + st->pos[index] = st->info->yamplitude * (the_sin * dist_mod_y) + st->info->half_height; + } +} + +static void +fun(struct state *st, unsigned long int the_time, struct info *info, int pos[], int index) +{ + int amplitude; + int max = st->info->half_width; + if ((the_time % (max * 2)) < max) + amplitude = max - ((the_time % (max * 2)) - max); + else + amplitude = the_time % (max * 2); + amplitude = amplitude - max; + if (index ==0) { + st->pos[index] = (amplitude * cos((double)the_time / 100.0 * st->info->xspeed)) + st->info->half_width; + } + else { + st->pos[index] = (amplitude * sin((double)the_time / 100.0 * st->info->yspeed)) + st->info->half_height; + } +} + +static void +linear(struct state *st, unsigned long int the_time, struct info *info, int pos[], int index) +{ + if (index == 0) /* Calculate for the x axis */ + st->pos[index] = ((the_time / 2) % (st->info->half_width * 2)); + else + st->pos[index] = ((the_time / 2) % (st->info->half_height * 2)); +} + +static void +test(struct state *st, unsigned long int the_time, struct info *info, int pos[], int index) +{ + if (index == 0) { + st->pos[index] = st->info->xamplitude * (cos((double)the_time / 100.0 * st->info->xspeed) * (st->info->half_width / 2)) + st->info->half_width; + } + else { + st->pos[index] = st->info->yamplitude * (sin((double)the_time / 100.0 * st->info->yspeed) * (st->info->half_height / 2)) + st->info->half_height; + } +} + +static int preen(int current, int max) { + if (current > max) + current=current-max; + if (current < 0) + current=current+max; + return(current); +} + +#if 0 +static void +smoothen(struct state *st, int x, int lastx, int y, int lasty, int size, int last_color, XColor *colors, Display *dpy, Window window, GC bgc, int screen, struct info *info) +{ + double xdistance = abs((double)x-(double)lastx); + double ydistance = abs((double)y-(double)lasty); + double distance = sqrt(((xdistance * xdistance) + (ydistance * ydistance)) ); + double slope = (((double)y-(double)lasty) / ((double)x-(double)lastx)); + printf("Starting smoothen with values: %f, %f, %f, %f\n", xdistance, ydistance, distance, slope); + if (distance > 2.0) { + int newx = (int)((xdistance / distance) * slope); + int newy = (int)((ydistance / distance) * slope); + if (! st->info->trail) { + XSetForeground(st->dpy, st->bgc, BlackPixel(st->dpy, st->screen)); + XFillArc(st->dpy, st->window, st->bgc, lastx, lasty, size, size, START_ARC, END_ARC); + } + XSetForeground(st->dpy, st->bgc, st->colors[last_color].pixel); + XFillArc(st->dpy, st->window, st->bgc, newx, newy, size, size, START_ARC, END_ARC); + smoothen(st, newx, x, newy, y, size, last_color, st->colors, st->dpy, st->window, st->bgc, st->screen, st->info); + } +} +#endif + + +static void * +whirlygig_init (Display *dpy, Window window) +{ + struct state *st = (struct state *) calloc (1, sizeof(*st)); + st->dpy = dpy; + st->window = window; + + st->ncolors = NCOLORS; + + st->dbuf = get_boolean_resource (st->dpy, "doubleBuffer", "Boolean"); + +# ifdef HAVE_COCOA /* Don't second-guess Quartz's double-buffering */ + st->dbuf = False; +# endif + + st->start_time = st->current_time; + st->info = (struct info *)malloc(sizeof(struct info)); + + st->screen = DefaultScreen(st->dpy); + XGetWindowAttributes (st->dpy, st->window, &st->xgwa); + if (st->dbuf) + { +#ifdef HAVE_DOUBLE_BUFFER_EXTENSION + if (get_boolean_resource(st->dpy,"useDBE","Boolean")) + { + st->dbeclear_p = get_boolean_resource (st->dpy, "useDBEClear", + "Boolean"); + if (st->dbeclear_p) + st->b = xdbe_get_backbuffer (st->dpy, st->window, XdbeBackground); + else + st->b = xdbe_get_backbuffer (st->dpy, st->window, XdbeUndefined); + st->backb = st->b; + } +#endif /* HAVE_DOUBLE_BUFFER_EXTENSION */ + + if (!st->b) + { + st->ba = XCreatePixmap (st->dpy, st->window, st->xgwa.width, st->xgwa.height,st->xgwa.depth); + st->b = st->ba; + } + } + else + { + st->b = st->window; + } + + st->gcv.foreground = get_pixel_resource(st->dpy, st->xgwa.colormap, "foreground", "Foreground"); + st->fgc = XCreateGC (st->dpy, st->b, GCForeground, &st->gcv); + st->gcv.foreground = get_pixel_resource(st->dpy, st->xgwa.colormap, "background", "Background"); + st->bgc = XCreateGC (st->dpy, st->b, GCForeground, &st->gcv); + +#ifdef HAVE_COCOA /* #### should turn off double-buffering instead */ + jwxyz_XSetAntiAliasing (dpy, st->fgc, False); + jwxyz_XSetAntiAliasing (dpy, st->bgc, False); +#endif + + { + Bool writable_p = False; + make_uniform_colormap (st->dpy, st->xgwa.visual, st->xgwa.colormap, st->colors, &st->ncolors, True, &writable_p, True); + } + + if (st->ba) XFillRectangle (st->dpy, st->ba, st->bgc, 0, 0, st->xgwa.width, st->xgwa.height); + + /* info is a structure holding all the random pieces of information I may want to + pass to my baby functions -- much of it I may never use, but it is nice to + have around just in case I want it to make a funky function funkier */ +/* info->writable = get_boolean_resource (dpy, "cycle", "Boolean"); */ + st->info->xspeed = get_float_resource(st->dpy, "xspeed" , "Float"); + st->info->yspeed = get_float_resource(st->dpy, "yspeed" , "Float"); + st->info->xamplitude = get_float_resource(st->dpy, "xamplitude", "Float"); + st->info->yamplitude = get_float_resource(st->dpy, "yamplitude", "Float"); + st->info->offset_period = get_float_resource(st->dpy, "offset_period", "Float"); + st->info->whirlies = get_integer_resource(st->dpy, "whirlies", "Integer"); + st->info->nlines = get_integer_resource(st->dpy, "nlines", "Integer"); + st->info->half_width = st->xgwa.width / 2; + st->info->half_height = st->xgwa.height / 2; + st->info->speed = get_integer_resource(st->dpy, "speed" , "Integer"); + st->info->trail = get_boolean_resource(st->dpy, "trail", "Integer"); + st->info->color_modifier = get_integer_resource(st->dpy, "color_modifier", "Integer"); + st->info->xoffset = get_float_resource(st->dpy, "xoffset", "Float"); + st->info->yoffset = get_float_resource(st->dpy, "yoffset", "Float"); + st->xmode_str = get_string_resource(st->dpy, "xmode", "Mode"); + st->ymode_str = get_string_resource(st->dpy, "ymode", "Mode"); + st->wrap = get_boolean_resource(st->dpy, "wrap", "Boolean"); + st->modifier = 3000.0 + frand(1500.0); + if (! st->xmode_str) st->xmode = spin_mode; + else if (! strcmp (st->xmode_str, "spin")) st->xmode = spin_mode; + else if (! strcmp (st->xmode_str, "funky")) st->xmode = funky_mode; + else if (! strcmp (st->xmode_str, "circle")) st->xmode = circle_mode; + else if (! strcmp (st->xmode_str, "linear")) st->xmode = linear_mode; + else if (! strcmp (st->xmode_str, "test")) st->xmode = test_mode; + else if (! strcmp (st->xmode_str, "fun")) st->xmode = fun_mode; + else if (! strcmp (st->xmode_str, "innie")) st->xmode = innie_mode; + else if (! strcmp (st->xmode_str, "lissajous")) st->xmode = lissajous_mode; + else { + st->xmode = random() % (int) lissajous_mode; + } + if (! st->ymode_str) st->ymode = spin_mode; + else if (! strcmp (st->ymode_str, "spin")) st->ymode = spin_mode; + else if (! strcmp (st->ymode_str, "funky")) st->ymode = funky_mode; + else if (! strcmp (st->ymode_str, "circle")) st->ymode = circle_mode; + else if (! strcmp (st->ymode_str, "linear")) st->ymode = linear_mode; + else if (! strcmp (st->ymode_str, "test")) st->ymode = test_mode; + else if (! strcmp (st->ymode_str, "fun")) st->ymode = fun_mode; + else if (! strcmp (st->ymode_str, "innie")) st->ymode = innie_mode; + else if (! strcmp (st->ymode_str, "lissajous")) st->ymode = lissajous_mode; + else { + st->ymode = random() % (int) lissajous_mode; + } + + if (get_integer_resource(st->dpy, "start_time", "Integer") == -1) + st->current_time = (unsigned long int)(random()); + else + st->current_time = get_integer_resource(st->dpy, "start_time", "Integer"); + if (st->info->whirlies == -1) + st->info->whirlies = 1 + (random() % 15); + if (st->info->nlines == -1) + st->info->nlines = 1 + (random() % 5); + if (st->info->color_modifier == -1) + st->info->color_modifier = 1 + (random() % 25); + if (get_boolean_resource(st->dpy, "explain", "Integer")) + st->explaining = 1; + st->current_color = 1 + (random() % NCOLORS); + + return st; +} + +static unsigned long +whirlygig_draw (Display *dpy, Window window, void *closure) +{ + struct state *st = (struct state *) closure; + int wcount; /* wcount is a counter incremented for every whirly take note of + internal_time before you mess with it */ + int change_time = 4000; + + if (st->explaining == 1) { + XClearWindow (st->dpy, st->window); + draw_explain_string(st, st->xmode, st->info->half_height-100, + st->dpy, st->window, st->fgc); + st->explaining++; + return 3000000; + } else if (st->explaining == 2) { + XClearWindow (st->dpy, st->window); + st->explaining = 0; + } + + if (! strcmp (st->xmode_str, "change") && ! strcmp (st->ymode_str, "change")) { + if ((st->current_time - st->start_time) > change_time) { + st->start_time = st->current_time; + st->xmode = 1 + (random() % 4); + st->ymode = 1 + (random() % 4); + } + } + else if (! strcmp (st->xmode_str, "change")) { + if ((st->current_time - st->start_time) > change_time) { + st->start_time = st->current_time; + st->xmode = 1 + (random() % 4); + } + } + else if (! strcmp (st->ymode_str, "change")) { + if ((st->current_time - st->start_time) > change_time) { + st->start_time = st->current_time; + st->ymode = 1 + (random() % 3); + printf("Changing ymode to %d\n", st->ymode); + } + } + if (++st->current_color >= NCOLORS) + st->current_color = 0; + for (wcount = 0; wcount < st->info->whirlies; wcount++) { + int lcount; /* lcount is a counter for every line -- take note of the offsets changing */ + int internal_time = st->current_time; + int color_offset = (st->current_color + (st->info->color_modifier * wcount)) % NCOLORS; + if (st->current_time == 0) + internal_time = 0; + else + /* I want the distance between whirlies to increase more each whirly */ + internal_time = st->current_time + (10 * wcount) + (wcount * wcount); + switch (st->xmode) { + /* All these functions expect an int time, the struct info, + a pointer to an array of positions, and the index that the + the function will fill of the array */ + case spin_mode: + spin(st, internal_time, st->info, st->pos, 0); + break; + case funky_mode: + funky(st, internal_time, st->info, st->pos, 0); + break; + case circle_mode: + circle(st, internal_time, st->info, st->pos, 0); + break; + case linear_mode: + linear(st, internal_time, st->info, st->pos, 0); + break; + case fun_mode: + fun(st, internal_time, st->info, st->pos, 0); + break; + case test_mode: + test(st, internal_time, st->info, st->pos, 0); + break; + case innie_mode: + innie(st, internal_time, st->info, st->pos, 0, st->modifier); + break; + case lissajous_mode: + lissajous(st, internal_time, st->info, st->pos, 0); + break; + default: + spin(st, internal_time, st->info, st->pos, 0); + break; + } /* End of the switch for the x position*/ + switch (st->ymode) { + case spin_mode: + spin(st, internal_time, st->info, st->pos, 1); + break; + case funky_mode: + funky(st, internal_time, st->info, st->pos, 1); + break; + case circle_mode: + circle(st, internal_time, st->info, st->pos, 1); + break; + case linear_mode: + linear(st, internal_time, st->info, st->pos, 1); + break; + case fun_mode: + fun(st, internal_time, st->info, st->pos, 1); + break; + case test_mode: + test(st, internal_time, st->info, st->pos, 1); + break; + case innie_mode: + innie(st, internal_time, st->info, st->pos, 1, st->modifier); + break; + case lissajous_mode: + lissajous(st, internal_time, st->info, st->pos, 1); + break; + default: + spin(st, internal_time, st->info, st->pos, 1); + break; + } /* End of the switch for the y position*/ + for (lcount = 0; lcount < st->info->nlines; lcount++) { + double arg = (double)((internal_time * st->info->offset_period) / 90.0); + double line_offset = 20.0 * (double)lcount * sin(arg); + int size; + size = (int)(15.0 + 5.0 * sin((double)internal_time / 180.0)); + /* First delete the old circle... */ + if (!st->info->trail +#ifdef HAVE_DOUBLE_BUFFER_EXTENSION + && ( !st->dbeclear_p || !st->backb) +#endif /* HAVE_DOUBLE_BUFFER_EXTENSION */ + ) { + XSetForeground(st->dpy, st->bgc, BlackPixel(st->dpy, st->screen)); + XFillArc(st->dpy, st->b, st->bgc, st->last_x[wcount][lcount], st->last_y[wcount][lcount], st->last_size[wcount][lcount], st->last_size[wcount][lcount], START_ARC, END_ARC); + } + /* Now, lets draw in the new circle */ + { /* Starting new scope for local x_pos and y_pos */ + int xpos, ypos; + if (st->wrap) { + xpos = preen((int)(st->info->xoffset*line_offset)+st->pos[0], st->info->half_width * 2); + ypos = preen((int)(st->info->yoffset*line_offset)+st->pos[1], st->info->half_height * 2); + } + else { + xpos = (int)(st->info->xoffset*line_offset)+st->pos[0]; + ypos = (int)(st->info->yoffset*line_offset)+st->pos[1]; + } + if (st->start_time == st->current_time) { + /* smoothen should move from one mode to another prettily... */ + + /* Note: smoothen has not been modified to take the double + buffering code into account, and needs to be hacked on + before uncommenting. + */ + /* + smoothen(xpos, last_x[wcount][lcount], ypos, last_y[wcount][lcount], size, color_offset, colors, dpy, window, bgc, screen, info); + */ + } + st->last_x[wcount][lcount] = xpos; + st->last_y[wcount][lcount] = ypos; + st->last_size[wcount][lcount] = size; + XSetForeground(st->dpy, st->bgc, st->colors[color_offset].pixel); + XFillArc(st->dpy, st->b, st->bgc, xpos, ypos, size, size, START_ARC, END_ARC); + } /* End of my temporary scope for xpos and ypos */ + } /* End of the for each line in nlines */ + } /* End of the for each whirly in whirlies */ + + +#ifdef HAVE_DOUBLE_BUFFER_EXTENSION + if (st->backb) + { + XdbeSwapInfo info[1]; + info[0].swap_window = st->window; + info[0].swap_action = (st->dbeclear_p ? XdbeBackground : XdbeUndefined); + XdbeSwapBuffers (st->dpy, info, 1); + } + else +#endif /* HAVE_DOUBLE_BUFFER_EXTENSION */ + if (st->dbuf) + { + XCopyArea (st->dpy, st->b, st->window, st->bgc, 0, 0, + st->xgwa.width, st->xgwa.height, 0, 0); + } + + if (st->current_time == FULL_CYCLE) + st->current_time = 1; + else + st->current_time = st->current_time + st->info->speed; + + return 10000; +} + + +static void +whirlygig_reshape (Display *dpy, Window window, void *closure, + unsigned int w, unsigned int h) +{ +} + +static Bool +whirlygig_event (Display *dpy, Window window, void *closure, XEvent *event) +{ + return False; +} + +static void +whirlygig_free (Display *dpy, Window window, void *closure) +{ +} + + +static const char *whirlygig_defaults [] = { + ".background: black", + ".foreground: white", + "*fpsSolid: true", + "*xspeed: 1.0", + "*yspeed: 1.0", + "*xamplitude: 1.0", + "*yamplitude: 1.0", + "*whirlies: -1", + "*nlines: -1", + "*xmode: change", + "*ymode: change", + "*speed: 1", + "*trail: false", + "*color_modifier: -1", + "*start_time: -1", + "*explain: False", + "*xoffset: 1.0", + "*yoffset: 1.0", + "*offset_period: 1", + "*wrap: False", + "*doubleBuffer: True", +#ifdef HAVE_DOUBLE_BUFFER_EXTENSION + "*useDBEClear: True", + "*useDBE: True", +#endif /* HAVE_DOUBLE_BUFFER_EXTENSION */ + 0 +}; + +static XrmOptionDescRec whirlygig_options [] = { + { "-xspeed", ".xspeed", XrmoptionSepArg, 0 }, + /* xspeed is a modifier of the argument to cos -- changing it thus + changes the frequency of cos */ + { "-yspeed", ".yspeed", XrmoptionSepArg, 0 }, + /* Similiarly, yspeed changes the frequency of sin */ + { "-xamplitude", ".xamplitude", XrmoptionSepArg, 0 }, + /* A factor by which to increase/decrease the amplitude of the sin */ + { "-yamplitude", ".yamplitude", XrmoptionSepArg, 0 }, + /* A factor by which to increase/decrease the amplitude of the cos */ + { "-whirlies", ".whirlies",XrmoptionSepArg, 0 }, + /* whirlies defines the number of circles to draw per line */ + { "-nlines", ".nlines",XrmoptionSepArg, 0 }, + /* nlines is the number of lines of whirlies to draw */ + { "-xmode", ".xmode", XrmoptionSepArg, 0 }, + /* There are a few different modes that I have written -- each mode + is in theory a different experiment with the possible modifiers to sin/cos */ + { "-ymode", ".ymode", XrmoptionSepArg, 0 }, + { "-speed", ".speed", XrmoptionSepArg, 0 }, + /* This will modify how often it should draw, changing it will probably suck */ + { "-trail", ".trail", XrmoptionNoArg, "True" }, + /* Control whether or not you want the old circles to be erased */ + { "-color_modifier", ".color_modifier", XrmoptionSepArg, 0 }, + /* How many colors away from the current should the next whirly be? */ + { "-start_time", ".start_time", XrmoptionSepArg, 0 }, + /* Specify exactly at what time to start graphing... */ + { "-xoffset", ".xoffset", XrmoptionSepArg, 0 }, + /* Tell the whirlies to be offset by this factor of a sin */ + { "-yoffset", ".yoffset", XrmoptionSepArg, 0 }, + /* Tell the whirlies to be offset by this factor of a cos */ + { "-offset_period", ".offset_period", XrmoptionSepArg, 0 }, + /* Change the period of an offset cycle */ + { "-explain", ".explain", XrmoptionNoArg, "True" }, + /* Specify whether or not to print an explanation of the function used. */ + { "-wrap", ".wrap", XrmoptionNoArg, "True" }, + { "-no-wrap", ".wrap", XrmoptionNoArg, "False" }, + /* Specify if you want whirlies which are out of the boundary of the screen to be + wrapped around to the other side */ + { "-db", ".doubleBuffer", XrmoptionNoArg, "True" }, + { "-no-db", ".doubleBuffer", XrmoptionNoArg, "False" }, + { 0, 0, 0, 0 } +}; + +XSCREENSAVER_MODULE ("Whirlygig", whirlygig) diff --git a/hacks/whirlygig.man b/hacks/whirlygig.man new file mode 100644 index 00000000..9a60ef33 --- /dev/null +++ b/hacks/whirlygig.man @@ -0,0 +1,137 @@ +.TH XScreenSaver 1 "31-Mar-01" "X Version 11" +.SH NAME +whirlygig -- zooming chains of sinusoidal spots +.SH SYNOPSIS +.B whirlygig +[\-display \fIhost:display.screen\fP] [\-window] [\-root] [\-mono] +[\-install] [\-noinstall] [\-visual arg] [\-window-id arg] +[\-xspeed arg] [\-yspeed arg] [\-whirlies arg] [\-nlines arg] +[\-xmode arg] [\-ymode arg] [\-speed arg] [\-trail 1|0] +[\-color_modifier arg] [\-start_time arg] [\-explain 1|0] +[\-wrap 1|0] [\-db] [\-no-db] + +[\-fps] +.SH DESCRIPTION +The \fIwhirlygig\fP program draws a series of circles on your screen. +They then move about in a cyclic pattern +.SH OPTIONS +.I whirlygig +accepts the following options: +.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 \-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 \-xspeed \fIspeed\fP +Specify how fast the dots should cycle horizontally. +Try out values from .01 to 4000. Defaults to 1.0. +.TP 8 +.B \-yspeed \fIspeed\fP +Specify how fast the dots should cycle vertically. +Try out values from .01 to 4000. Defaults to 1.0. +.TP 8 +.B \-xamplitude \fIfactor\fP +Specify the horizontal amplitude. +Try out values from .01 to 10. Defaults to 1.0. +.TP 8 +.B \-yamplitude \fIfactor\fP +Specify the horizontal amplitude. +Try out values from .01 to 10. Defaults to 1.0. +.TP 8 +.B \-whirlies \fIa number\fP +Specify how many whirlies you want (per line). Defaults +to a random number. +.TP 8 +.B \-nlines \fInumber of lines\fP +Specify how many lines of whirlies you want. Defaults to a +random number. +.TP 8 +.B \-xmode \fImode\fP +.TP 8 +.B \-ymode \fImode\fP +Specify which mode to use for calculating the x and y positions of the +whirlies. Can be any of spin, funky, circle, linear, test, fun, innie +or lissajous. Defaults to 'change' mode, which randomly selects a new +mode for x and y every now an then. Unrecognized options default to spin. +.TP 8 +.B \-explain +Prints some strings to the window explaining what the initially +selected modes are, before displaying the whirlies. Off by default. +.TP 8 +.B \-trail \fI1 or 0\fP +Trail mode fails to erase the whirlies as they move, so they leave a +multicoloured trail behind. Doesn't work if the doubled buffered mode +is using the X server's double buffer extension, and the useDBEclear +resource is true (which it is by default). +.TP 8 +.B \-speed \fIint\fP +Specifies how fast to cycle through the internal time. Values 1,2 and +3 look ok, up to 10 is not too bad, but beyond ends up +flickery. Adjust xspeed and yspeed instead. +.TP 8 +.B \-start_time \fIint\fP +Where in the internal time cycle to start. Ranges from 1 to 429496729, +Defaults to a random value. +.TP 8 +.B \-xoffset \fIfactor\fP +Tell the whirlies to be offset by this factor of a sin. +Defaults to 1.0 +.TP 8 +.B \-yoffset \fIfactor\fP +Tell the whirlies to be offset by this factor of a cos. +Defaults to 1.0 +.TP 8 +.B \-offset_period \fIfactor\fP +Change the period of an offset cycle +Defaults to 1 +.TP 8 +.B \-color_modifier \fIint\fP +How many colors away from the current should the next whirly be? +.TP 8 +.B \-wrap \fI1|0\fP +Causes whirlies that fall off the edge of the screen to wrap over to +the other end of the screen. Otherwise they disappear and new ones +to materialize on the other side of the screen. The difference is +subtle, but it is different. Try it. On by default. +.TP 8 +.B \-db +.TP 8 +.B \-no-db +Use double buffering to reduce flicker. This uses the double buffering +extension if your X server supports it, otherwise it draws to it's own +pixmap buffer and copies that to the window, which works almost as +well. If the resource 'useDBEClear' is true, whirlies are not +individually erased, so the -trail option won't work, and running +multiple instances on the root window will flicker. + +.TP 8 +.B \-fps +Display the current frame rate and CPU load. +.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 2001 by Ashton Trey Belew. 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 +Ashton Trey Belew , 31-Mar-01 diff --git a/hacks/worm.c b/hacks/worm.c new file mode 100644 index 00000000..1afd5c85 --- /dev/null +++ b/hacks/worm.c @@ -0,0 +1,442 @@ + +/* -*- Mode: C; tab-width: 4 -*- */ +/* worm --- draw wiggly worms */ + +#if 0 +static const char sccsid[] = "@(#)worm.c 4.04 97/07/28 xlockmore"; +#endif + +/*- + * Copyright (c) 1991 by Patrick J. Naughton. + * + * Permission to use, copy, modify, and distribute this software and its + * documentation for any purpose and without fee is hereby granted, + * provided that the above copyright notice appear in all copies and that + * both that copyright notice and this permission notice appear in + * supporting documentation. + * + * This file is provided AS IS with no warranties of any kind. The author + * shall have no liability with respect to the infringement of copyrights, + * trade secrets or any patents by this file or any part thereof. In no + * event will the author be liable for any lost revenue or profits or + * other special, indirect and consequential damages. + * + * Revision History: + * 10-May-97: Compatible with xscreensaver + * 03-Sep-96: fixed bug in allocation of space for worms, added 3d support + * Henrik Theiling + * 27-Sep-95: put back malloc + * 23-Sep-93: got rid of "rint". (David Bagley) + * 27-Sep-91: got rid of all malloc calls since there were no calls to free(). + * 25-Sep-91: Integrated into X11R5 contrib xlock. + * + * Adapted from a concept in the Dec 87 issue of Scientific American p. 142. + * + * SunView version: Brad Taylor + * X11 version: Dave Lemke + * xlock version: Boris Putanec + */ + +#ifdef STANDALONE +# define DEFAULTS "*delay: 17000 \n" \ + "*count: -20 \n" \ + "*cycles: 10 \n" \ + "*size: -3 \n" \ + "*ncolors: 150 \n" \ + "*use3d: False \n" \ + "*delta3d: 1.5 \n" \ + "*right3d: red \n" \ + "*left3d: blue \n" \ + "*both3d: magenta \n" \ + "*none3d: black \n" \ + "*fpsSolid: true \n" \ + +# define SMOOTH_COLORS +# define reshape_worm 0 +# define worm_handle_event 0 +# include "xlockmore.h" /* in xscreensaver distribution */ +#else /* STANDALONE */ +# include "xlock.h" /* in xlockmore distribution */ +#endif /* STANDALONE */ + +ENTRYPOINT ModeSpecOpt worm_opts = +{0, NULL, 0, NULL, NULL}; + +#define MINSIZE 1 + +#define SEGMENTS 36 +#define MINWORMS 1 + +#define MAXZ 750 +#define MINZ 100 +#define SCREENZ 200 +#define GETZDIFF(z) (MI_DELTA3D(mi)*20.0*(1.0-(SCREENZ)/((float)(z)+MINZ))) +#define IRINT(x) ((int)(((x)>0.0)?(x)+0.5:(x)-0.5)) + +/* How many segments to draw per cycle when redrawing */ +#define REDRAWSTEP 3 + +typedef struct { + XPoint *circ; + int *diffcirc; + int dir, dir2; + int tail; + int x, y, z; + int redrawing, redrawpos; +} wormstuff; + +typedef struct { + int xsize, ysize, zsize; + int wormlength; + int nc; + int nw; + int circsize; + wormstuff *worm; + XRectangle *rects; /* [NUMCOLORS * batchcount/NUMCOLORS+1] */ + int maxsize; + int *size; + unsigned int chromo; +} wormstruct; + +static float sintab[SEGMENTS]; +static float costab[SEGMENTS]; +static int init_table = 0; + +static wormstruct *worms = NULL; + +static void +worm_doit(ModeInfo * mi, int which, unsigned long color) +{ + Display *display = MI_DISPLAY(mi); + Window window = MI_WINDOW(mi); + GC gc = MI_GC(mi); + wormstruct *wp = &worms[MI_SCREEN(mi)]; + wormstuff *ws = &wp->worm[which]; + int x, y, z; + int diff; + + ws->tail++; + if (ws->tail == wp->wormlength) + ws->tail = 0; + + x = ws->circ[ws->tail].x; + y = ws->circ[ws->tail].y; + + if (MI_WIN_IS_USE3D(mi)) { + diff = ws->diffcirc[ws->tail]; + if (MI_WIN_IS_INSTALL(mi)) { + XSetForeground(display, gc, MI_NONE_COLOR(mi)); + XFillRectangle(display, window, gc, x - diff, y, + wp->circsize, wp->circsize); + XFillRectangle(display, window, gc, x + diff, y, + wp->circsize, wp->circsize); + } else { + XClearArea(display, window, x - diff, y, + wp->circsize, wp->circsize, False); + XClearArea(display, window, x + diff, y, + wp->circsize, wp->circsize, False); + } + } else + XClearArea(display, window, x, y, wp->circsize, wp->circsize, False); + + if (LRAND() & 1) + ws->dir = (ws->dir + 1) % SEGMENTS; + else + ws->dir = (ws->dir + SEGMENTS - 1) % SEGMENTS; + + x = (ws->x + IRINT((float) wp->circsize * costab[ws->dir]) + + wp->xsize) % wp->xsize; + y = (ws->y + IRINT((float) wp->circsize * sintab[ws->dir]) + + wp->ysize) % wp->ysize; + + ws->circ[ws->tail].x = x; + ws->circ[ws->tail].y = y; + ws->x = x; + ws->y = y; + + if (MI_WIN_IS_USE3D(mi)) { + if (LRAND() & 1) + ws->dir2 = (ws->dir2 + 1) % SEGMENTS; + else + ws->dir2 = (ws->dir2 + SEGMENTS - 1) % SEGMENTS; + /* for the z-axis the wrap-around looks bad, so worms should just turn around. */ + z = (int) (ws->z + wp->circsize * sintab[ws->dir2]); + if (z < 0 || z >= wp->zsize) + z = (int) (ws->z - wp->circsize * sintab[ws->dir2]); + + diff = (int) (GETZDIFF(z) + 0.5); /* ROUND */ + ws->diffcirc[ws->tail] = diff; + + ws->z = z; + + /* right eye */ + color = 0; + wp->rects[color * wp->maxsize + wp->size[color]].x = x + diff; + wp->rects[color * wp->maxsize + wp->size[color]].y = y; + wp->size[color]++; + + /* left eye */ + color = 1; + wp->rects[color * wp->maxsize + wp->size[color]].x = x - diff; + wp->rects[color * wp->maxsize + wp->size[color]].y = y; + wp->size[color]++; + +#if 0 + if (ws->redrawing) { /* Too hard for now */ + int j; + + for (j = 0; j < REDRAWSTEP; j++) { + int k = (ws->tail - ws->redrawpos + wp->wormlength) + % wp->wormlength; + + color = 0; + wp->rects[color * wp->maxsize + wp->size[color]].x = + ws->circ[k].x + ws->diffcirc[k]; + wp->rects[color * wp->maxsize + wp->size[color]].y = + ws->circ[k].y; + wp->size[color]++; + + color = 1; + wp->rects[color * wp->maxsize + wp->size[color]].x = + ws->circ[k].x - ws->diffcirc[k]; + wp->rects[color * wp->maxsize + wp->size[color]].y = + ws->circ[k].y; + wp->size[color]++; + + if (++(ws->redrawpos) >= wp->wormlength) { + ws->redrawing = 0; + break; + } + } + } +#endif + + } else { + + wp->rects[color * wp->maxsize + wp->size[color]].x = x; + wp->rects[color * wp->maxsize + wp->size[color]].y = y; + wp->size[color]++; + if (ws->redrawing) { + int j; + + ws->redrawpos++; + /* Compensates for the changed ws->tail + since the last callback. */ + + for (j = 0; j < REDRAWSTEP; j++) { + int k = (ws->tail - ws->redrawpos + wp->wormlength) + % wp->wormlength; + + wp->rects[color * wp->maxsize + wp->size[color]].x = ws->circ[k].x; + wp->rects[color * wp->maxsize + wp->size[color]].y = ws->circ[k].y; + wp->size[color]++; + + if (++(ws->redrawpos) >= wp->wormlength) { + ws->redrawing = 0; + break; + } + } + } + } +} + +static void +free_worms(wormstruct * wp) +{ + int wn; + + if (wp->worm) { + for (wn = 0; wn < wp->nw; wn++) { + if (wp->worm[wn].circ) + (void) free((void *) wp->worm[wn].circ); + if (wp->worm[wn].diffcirc) + (void) free((void *) wp->worm[wn].diffcirc); + } + (void) free((void *) wp->worm); + wp->worm = NULL; + } + if (wp->rects) { + (void) free((void *) wp->rects); + wp->rects = NULL; + } + if (wp->size) { + (void) free((void *) wp->size); + wp->size = NULL; + } +} + +ENTRYPOINT void +init_worm (ModeInfo * mi) +{ + wormstruct *wp; + int size = MI_SIZE(mi); + int i, j; + + if (worms == NULL) { + if ((worms = (wormstruct *) calloc(MI_NUM_SCREENS(mi), + sizeof (wormstruct))) == NULL) + return; + } + wp = &worms[MI_SCREEN(mi)]; + if (MI_NPIXELS(mi) <= 2 || MI_WIN_IS_USE3D(mi)) + wp->nc = 2; + else + wp->nc = MI_NPIXELS(mi); + if (wp->nc > NUMCOLORS) + wp->nc = NUMCOLORS; + + free_worms(wp); + wp->nw = MI_BATCHCOUNT(mi); + if (wp->nw < -MINWORMS) + wp->nw = NRAND(-wp->nw - MINWORMS + 1) + MINWORMS; + else if (wp->nw < MINWORMS) + wp->nw = MINWORMS; + if (!wp->worm) + wp->worm = (wormstuff *) malloc(wp->nw * sizeof (wormstuff)); + + if (!wp->size) + wp->size = (int *) malloc(NUMCOLORS * sizeof (int)); + + wp->maxsize = (REDRAWSTEP + 1) * wp->nw; /* / wp->nc + 1; */ + if (!wp->rects) + wp->rects = + (XRectangle *) malloc(wp->maxsize * NUMCOLORS * sizeof (XRectangle)); + + + if (!init_table) { + init_table = 1; + for (i = 0; i < SEGMENTS; i++) { + sintab[i] = SINF(i * 2.0 * M_PI / SEGMENTS); + costab[i] = COSF(i * 2.0 * M_PI / SEGMENTS); + } + } + wp->xsize = MI_WIN_WIDTH(mi); + wp->ysize = MI_WIN_HEIGHT(mi); + wp->zsize = MAXZ - MINZ + 1; + if (MI_NPIXELS(mi) > 2) + wp->chromo = NRAND(MI_NPIXELS(mi)); + + if (size < -MINSIZE) + wp->circsize = NRAND(-size - MINSIZE + 1) + MINSIZE; + else if (size < MINSIZE) + wp->circsize = MINSIZE; + else + wp->circsize = size; + + for (i = 0; i < wp->nc; i++) { + for (j = 0; j < wp->maxsize; j++) { + wp->rects[i * wp->maxsize + j].width = wp->circsize; + wp->rects[i * wp->maxsize + j].height = wp->circsize; + + } + } + (void) memset((char *) wp->size, 0, wp->nc * sizeof (int)); + + wp->wormlength = (int) sqrt(wp->xsize + wp->ysize) * + MI_CYCLES(mi) / 8; /* Fudge this to something reasonable */ + for (i = 0; i < wp->nw; i++) { + wp->worm[i].circ = (XPoint *) malloc(wp->wormlength * sizeof (XPoint)); + wp->worm[i].diffcirc = (int *) malloc(wp->wormlength * sizeof (int)); + + for (j = 0; j < wp->wormlength; j++) { + wp->worm[i].circ[j].x = wp->xsize / 2; + wp->worm[i].circ[j].y = wp->ysize / 2; + if (MI_WIN_IS_USE3D(mi)) + wp->worm[i].diffcirc[j] = 0; + } + wp->worm[i].dir = NRAND(SEGMENTS); + wp->worm[i].dir2 = NRAND(SEGMENTS); + wp->worm[i].tail = 0; + wp->worm[i].x = wp->xsize / 2; + wp->worm[i].y = wp->ysize / 2; + wp->worm[i].z = SCREENZ - MINZ; + wp->worm[i].redrawing = 0; + } + + if (MI_WIN_IS_INSTALL(mi) && MI_WIN_IS_USE3D(mi)) { + XSetForeground(MI_DISPLAY(mi), MI_GC(mi), MI_NONE_COLOR(mi)); + XFillRectangle(MI_DISPLAY(mi), MI_WINDOW(mi), MI_GC(mi), + 0, 0, wp->xsize, wp->ysize); + } else + XClearWindow(MI_DISPLAY(mi), MI_WINDOW(mi)); +} + +ENTRYPOINT void +draw_worm (ModeInfo * mi) +{ + Display *display = MI_DISPLAY(mi); + Window window = MI_WINDOW(mi); + GC gc = MI_GC(mi); + wormstruct *wp = &worms[MI_SCREEN(mi)]; + unsigned long wcolor; + int i; + + (void) memset((char *) wp->size, 0, wp->nc * sizeof (int)); + + for (i = 0; i < wp->nw; i++) { + if (MI_NPIXELS(mi) > 2) { + wcolor = (i + wp->chromo) % wp->nc; + + worm_doit(mi, i, wcolor); + } else + worm_doit(mi, i, (unsigned long) 0); + } + + if (MI_WIN_IS_USE3D(mi)) { + if (MI_WIN_IS_INSTALL(mi)) + XSetFunction(display, gc, GXor); + XSetForeground(display, gc, MI_RIGHT_COLOR(mi)); + XFillRectangles(display, window, gc, &(wp->rects[0]), wp->size[0]); + + XSetForeground(display, gc, MI_LEFT_COLOR(mi)); + XFillRectangles(display, window, gc, &(wp->rects[wp->maxsize]), wp->size[1]); + if (MI_WIN_IS_INSTALL(mi)) + XSetFunction(display, gc, GXcopy); + } else if (MI_NPIXELS(mi) > 2) { + for (i = 0; i < wp->nc; i++) { + XSetForeground(display, gc, MI_PIXEL(mi, i)); + XFillRectangles(display, window, gc, &(wp->rects[i * wp->maxsize]), wp->size[i]); + } + } else { + XSetForeground(display, gc, MI_WIN_WHITE_PIXEL(mi)); + XFillRectangles(display, window, gc, + &(wp->rects[0]), wp->size[0]); + } + + if (++wp->chromo == (unsigned long) wp->nc) + wp->chromo = 0; +} + +ENTRYPOINT void +release_worm(ModeInfo * mi) +{ + if (worms != NULL) { + int screen; + + for (screen = 0; screen < MI_NUM_SCREENS(mi); screen++) + free_worms(&worms[screen]); + (void) free((void *) worms); + worms = NULL; + } +} + +ENTRYPOINT void +refresh_worm (ModeInfo * mi) +{ + if (MI_WIN_IS_USE3D(mi)) + /* The 3D code does drawing&clearing by XORing. We do not + want to go to too much trouble here to make it redraw + correctly. */ + XClearWindow(MI_DISPLAY(mi), MI_WINDOW(mi)); + else if (worms != NULL) { + wormstruct *wp = &worms[MI_SCREEN(mi)]; + int i; + + for (i = 0; i < wp->nw; i++) { + wp->worm[i].redrawing = 1; + wp->worm[i].redrawpos = 0; + } + } +} + +XSCREENSAVER_MODULE ("Worm", worm) diff --git a/hacks/worm.man b/hacks/worm.man new file mode 100644 index 00000000..d9698b56 --- /dev/null +++ b/hacks/worm.man @@ -0,0 +1,65 @@ +.TH XScreenSaver 1 "" "X Version 11" +.SH NAME +worm - multicolored worms that crawl around the screen. +.SH SYNOPSIS +.B worm +[\-display \fIhost:display.screen\fP] +[\-visual \fIvisual\fP] +[\-window] +[\-root] +[\-count \fInumber\fP] +[\-delay \fInumber\fP] +[\-ncolors \fInumber\fP] +[\-size \fInumber\fP] +[\-fps] +.SH DESCRIPTION +An ancient hack that draws multicolored worms that crawl around the screen. +.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 \-count \fInumber\fP +Count. -100 - 100. Default: -20. +.TP 8 +.B \-delay \fInumber\fP +Per-frame delay, in microseconds. Default: 17000 (0.017 seconds.). +.TP 8 +.B \-ncolors \fInumber\fP +Number of Colors. Default: 150. +.TP 8 +.B \-size \fInumber\fP +Size. -20 - 20. Default: -3. +.TP 8 +.B \-fps +Display the current frame rate and CPU load. +.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 2002 by Brad Taylor, Dave Lemke, Boris Putanec, and +Henrik Theiling. 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 +Brad Taylor, Dave Lemke, Boris Putanec, and Henrik Theiling. diff --git a/hacks/wormhole.c b/hacks/wormhole.c new file mode 100644 index 00000000..86a6dcd5 --- /dev/null +++ b/hacks/wormhole.c @@ -0,0 +1,721 @@ +/* xscreensaver, Copyright (c) 1992-2011 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. + */ + +/* wormhole: + * Animation of moving through a wormhole. Based on my own code written + * a few years ago. + * author: Jon Rafkind + * date: 1/19/04 + */ + +#include +#include "screenhack.h" + +#ifndef debug +#define debug printf("File:%s Line:%d\n", __FILE__, __LINE__ ); +#endif + +typedef struct STAR{ + int x, y; + int calc_x, calc_y; + int Z; + int center_x, center_y; +} star; + +typedef struct STARLINE{ + star begin, end; +} starline; + +/* +typedef struct RGBHANDLE{ + XColor mine; + unsigned short rwant, gwant, bwant; +} RGBHandle; +*/ + +typedef struct COLORCHANGER{ + XColor * shade; + int min, max; + int shade_use; + int shade_max; + int min_want; + /* RGBHandle handle_begin, handle_end; */ +} color_changer; + +typedef struct WORMHOLE{ + int diameter; + int diameter_change; + int actualx, actualy; + double virtualx, virtualy; + double speed; + int ang; + int want_ang; + int want_x, want_y; + int max_Z; + int addStar; + int spiral; + color_changer changer; + starline ** stars; + int num_stars; /* top of array we are using */ + XColor black; + Pixmap work; +} wormhole; + +struct state { + Display *dpy; + Window window; + + int SCREEN_X, SCREEN_Y; + int z_speed; + int make_stars; + + int delay; + wormhole worm; + GC gc; + Colormap cmap; +}; + + +/*inline*/ static int rnd( int q ) +{ + if (q < 1) q = 1; + return random() % q; + +} + +static int gang( int x1, int y1, int x2, int y2 ) +{ + + int tang = 0; + if ( x1 == x2 ) { + if ( y1 < y2 ) + tang = 90; + else + tang = 270; + } else if ( y1 == y2 ) { + + if ( x1 < x2 ) + tang = 0; + else + tang = 180; + + } else { + tang = (int)(0.5+atan2( -(y2-y1), x2 - x1 ) * 180.0 / M_PI ); + } + + while ( tang < 0 ) + tang += 360; + return tang % 360; + +} + +static void blend_palette( XColor * pal, int max, XColor * sc, XColor * ec ) +{ + + int q; + + int sc_r = sc->red; + int sc_g = sc->green; + int sc_b = sc->blue; + + int ec_r = ec->red; + int ec_g = ec->green; + int ec_b = ec->blue; + + for ( q = 0; q < max; q++ ) { + float j = (float)( q ) / (float)( max ); + int f_r = (int)( 0.5 + (float)( sc_r ) + (float)( ec_r-sc_r ) * j ); + int f_g = (int)( 0.5 + (float)( sc_g ) + (float)( ec_g-sc_g ) * j ); + int f_b = (int)( 0.5 + (float)( sc_b ) + (float)( ec_b-sc_b ) * j ); + /* pal[q] = makecol( f_r, f_g, f_b ); */ + pal[q].red = f_r; + pal[q].blue = f_b; + pal[q].green = f_g; + } + +} + + +/* +static void initHandle( RGBHandle * handle ) +{ + + handle->mine.red = rnd( 65536 ); + handle->mine.green = rnd( 65536 ); + handle->mine.blue = rnd( 65536 ); + handle->rwant = rnd( 65536 ); + handle->gwant = rnd( 65536 ); + handle->bwant = rnd( 65536 ); + +} +*/ + +static void initXColor( XColor * color ) +{ + color->red = rnd( 50000 ) + 10000; + color->blue = rnd( 50000 ) + 10000; + color->green = rnd( 50000 ) + 10000; +} + +static void initColorChanger( struct state *st, color_changer * ch ) +{ + + int q; + XColor old_color, new_color; + + ch->shade_max = 2048; + ch->shade_use = 128; + ch->min = 0; + ch->max = ch->shade_use; + ch->min_want = rnd( ch->shade_max - ch->shade_use ); + ch->shade = (XColor *)malloc( sizeof(XColor) * ch->shade_max ); + memset( ch->shade, 0, sizeof(XColor) * ch->shade_max ); + + initXColor( &old_color ); + initXColor( &new_color ); + + for ( q = 0; q < ch->shade_max; q += ch->shade_use ){ + blend_palette( ch->shade + q, ch->shade_use, &old_color, &new_color ); + old_color = new_color; + + initXColor( &new_color ); + } + + for ( q = 0; q < ch->shade_max; q++ ) + XAllocColor( st->dpy, st->cmap, &( ch->shade[q] ) ); + + /* + initHandle( &(ch->handle_begin) ); + initHandle( &(ch->handle_end) ); + ch->shade = (XColor *)malloc( sizeof(XColor) * MAX_COLORS ); + ch->max = MAX_COLORS; + memset( ch->shade, 0, sizeof(XColor) * ch->max ); + + blend_palette( ch->shade, ch->max, &(ch->handle_begin.mine), &(ch->handle_end.mine) ); + for ( q = 0; q < ch->max; q++ ) + XAllocColor( st->dpy, *cmap, &( ch->shade[q] ) ); + */ + +} + +/* +static void changeColor( unsigned short * col, unsigned short * change, int min, int max ) +{ + int RGB_GO_BLACK = 30; + if ( *col < *change ) *col++; + if ( *col > *change ) *col--; + if ( *col == *change ){ + if ( rnd( RGB_GO_BLACK ) == rnd( RGB_GO_BLACK ) ) + *change = 0; + else *change = rnd(max-min) + min; + } +} +*/ + +/* +static void moveRGBHandle( RGBHandle * handle, int min, int max ) +{ + + unsigned short * want[ 3 ]; + int q; + int cy = 0; + want[0] = &(handle->rwant); + want[1] = &(handle->gwant); + want[2] = &(handle->bwant); + + for ( q = 0; q < 10; q++ ){ + changeColor( &( handle->mine.red ), &handle->rwant, min, max ); + changeColor( &( handle->mine.green ), &handle->gwant, min, max ); + changeColor( &( handle->mine.blue ), &handle->bwant, min, max ); + } + + for ( q = 0; q < 3; q++ ) + cy = cy || (*(want[q]) >= min && *(want[q]) <= max); + if ( !cy ) *(want[rnd(3)]) = rnd(max-min)+min; + cy = 1; + for ( q = 0; q < 3; q++ ) + cy = cy && *(want[q]) == 0; + if ( cy ) *(want[rnd(3)]) = rnd(max-min)+min; + + if ( rnd( 30 ) == rnd( 30 ) ) + *(want[rnd(3)]) = rnd(max-min)+min; + +} +*/ + +static void moveColorChanger( color_changer * ch ) +{ + + /* int q; */ + + if ( ch->min < ch->min_want ){ + ch->min++; + ch->max++; + } + if ( ch->min > ch->min_want ) { + ch->min--; + ch->max--; + } + if ( ch->min == ch->min_want ) + ch->min_want = rnd( ch->shade_max - ch->shade_use ); + + /* + for ( q = 0; q < ch->max; q++ ) + XFreeColors( st->dpy, *cmap, &( ch->shade[q].pixel ), 1, 0 ); + + moveRGBHandle( &( ch->handle_begin ), 5000, 65500 ); + moveRGBHandle( &( ch->handle_end ), 5000, 65500 ); + + blend_palette( ch->shade, ch->max, &(ch->handle_begin.mine), &(ch->handle_end.mine) ); + for ( q = 0; q < ch->max; q++ ) + XAllocColor( st->dpy, *cmap, &( ch->shade[q] ) ); + */ + +} + +#if 0 +static void destroyColorChanger( color_changer * ch ) +{ + int q; + for ( q = 0; q < ch->max; q++ ) + XFreeColors( st->dpy, *cmap, &( ch->shade[q].pixel ), 1, 0 ); + free( ch->shade ); +} +#endif + +static void resizeWormhole( struct state *st, wormhole * worm ) +{ + + XWindowAttributes attr; + + XGetWindowAttributes( st->dpy, st->window, &attr ); + + st->cmap = attr.colormap; + + st->SCREEN_X = attr.width; + st->SCREEN_Y = attr.height; + +# ifndef HAVE_COCOA /* Don't second-guess Quartz's double-buffering */ + XFreePixmap( st->dpy, worm->work ); + worm->work = XCreatePixmap( st->dpy, st->window, st->SCREEN_X, st->SCREEN_Y, attr.depth ); +# endif + +} + +static void initWormhole( struct state *st, wormhole * worm, Display * display, Window win ) +{ + + int i; + XWindowAttributes attr; + + XGetWindowAttributes( st->dpy, st->window, &attr ); + + st->cmap = attr.colormap; + + st->SCREEN_X = attr.width; + st->SCREEN_Y = attr.height; + +# ifdef HAVE_COCOA /* Don't second-guess Quartz's double-buffering */ + worm->work = st->window; +# else + worm->work = XCreatePixmap( st->dpy, st->window, st->SCREEN_X, st->SCREEN_Y, attr.depth ); +# endif + + worm->diameter = rnd( 10 ) + 15; + worm->diameter_change = rnd( 10 ) + 15; + /* worm->actualx = rnd( attr.width ); + worm->actualy = rnd( attr.height ); */ + worm->actualx = attr.width / 2; + worm->actualy = attr.height / 2; + worm->virtualx = worm->actualx; + worm->virtualy = worm->actualy; + worm->speed = (float)st->SCREEN_X / 180.0; + /* z_speed = SCREEN_X / 120; */ + worm->spiral = 0; + worm->addStar = st->make_stars; + worm->want_x = rnd( attr.width - 50 ) + 25; + worm->want_y = rnd( attr.height - 50 ) + 25; + worm->want_ang = gang( worm->actualx, worm->actualy, worm->want_x, worm->want_y ); + worm->ang = worm->want_ang; + worm->max_Z = 600; + worm->black.red = 0; + worm->black.green = 0; + worm->black.blue = 0; + XAllocColor( st->dpy, st->cmap, &worm->black ); + initColorChanger( st, &(worm->changer) ); + + worm->num_stars = 64; + worm->stars = (starline **)malloc( sizeof(starline *) * worm->num_stars ); + for ( i = 0; i < worm->num_stars; i++ ) + worm->stars[i] = NULL; + +} + +#if 0 +static void destroyWormhole( wormhole * worm ) +{ + destroyColorChanger( &(worm->changer), st->dpy, cmap ); + if (work->work != st->window) + XFreePixmap( st->dpy, worm->work ); + free( worm->stars ); +} +#endif + +static double Cos( int a ) +{ + return cos( a * 180.0 / M_PI ); +} + +static double Sine( int a ) +{ + return sin( a * 180.0 / M_PI ); +} + + + +static void calcStar( star * st ) +{ + if ( st->center_x == 0 || st->center_y == 0 ){ + st->Z = 0; + return; + } + if ( st->Z <= 0 ){ + st->calc_x = (st->x << 10) / st->center_x; + st->calc_y = (st->y << 10) / st->center_y; + } else { + st->calc_x = (st->x << 10 ) / st->Z + st->center_x; + st->calc_y = (st->y << 10 ) / st->Z + st->center_y; + } +} + +static void initStar( star * st, int Z, int ang, wormhole * worm ) +{ + + st->x = Cos( ang ) * worm->diameter; + st->y = Sine( ang ) * worm->diameter; + st->center_x = worm->actualx; + st->center_y = worm->actualy; + st->Z = Z; + calcStar( st ); + +} + +static void addStar( wormhole * worm ) +{ + + starline * star_new; + starline ** xstars; + int old_stars; + int q; + int ang; + star_new = (starline *)malloc( sizeof( starline ) ); + ang = rnd( 360 ); + initStar( &star_new->begin, worm->max_Z, ang, worm ); + initStar( &star_new->end, worm->max_Z+rnd(6)+4, ang, worm ); + + for ( q = 0; q < worm->num_stars; q++ ){ + if ( worm->stars[q] == NULL ){ + worm->stars[q] = star_new; + return; + } + } + + old_stars = worm->num_stars; + worm->num_stars = worm->num_stars << 1; + xstars = (starline **)malloc( sizeof(starline *) * worm->num_stars ); + for ( q = 0; q < worm->num_stars; q++ ) + xstars[q] = NULL; + + for ( q = 0; q < old_stars; q++ ) + if ( worm->stars[q] != NULL ) xstars[q] = worm->stars[q]; + free( worm->stars ); + worm->stars = xstars; + + worm->stars[ old_stars ] = star_new; + +} + +static int moveStar( struct state *st, starline * stl ) +{ + + stl->begin.Z -= st->z_speed; + stl->end.Z -= st->z_speed; + + calcStar( &stl->begin ); + calcStar( &stl->end ); + + return ( stl->begin.Z <= 0 || stl->end.Z <= 0 ); + +} + +static int dist( int x1, int y1, int x2, int y2 ) +{ + int xs, ys; + xs = x1-x2; + ys = y1-y2; + return (int)sqrt( xs*xs + ys*ys ); +} + +static void moveWormhole( struct state *st, wormhole * worm ) +{ + + int q; + double dx, dy; + /* int x1, y1, x2, y2; */ + int min_dist = 100; + int find = 0; + dx = Cos( worm->ang ) * worm->speed; + dy = Sine( worm->ang ) * worm->speed; + + worm->virtualx += dx; + worm->virtualy += dy; + worm->actualx = (int)worm->virtualx; + worm->actualy = (int)worm->virtualy; + + if ( worm->spiral ){ + + if ( worm->spiral % 5 == 0 ) + worm->ang = (worm->ang + 1 ) % 360; + worm->spiral--; + if ( worm->spiral <= 0 ) find = 1; + + } else { + + if ( dist( worm->actualx, worm->actualy, worm->want_x, worm->want_y ) < 20 ) + find = 1; + + if ( rnd( 20 ) == rnd( 20 ) ) + find = 1; + + if ( worm->actualx < min_dist ){ + worm->actualx = min_dist; + worm->virtualx = worm->actualx; + find = 1; + } + if ( worm->actualy < min_dist ){ + worm->actualy = min_dist; + worm->virtualy = worm->actualy; + find = 1; + } + if ( worm->actualx > st->SCREEN_X - min_dist ){ + worm->actualx = st->SCREEN_X - min_dist; + worm->virtualx = worm->actualx; + find = 1; + } + if ( worm->actualy > st->SCREEN_Y - min_dist ){ + worm->actualy = st->SCREEN_Y - min_dist; + worm->virtualy = worm->actualy; + find = 1; + } + + if ( rnd( 500 ) == rnd( 500 ) ) worm->spiral = rnd( 30 ) + 50; + } + + if ( find ){ + worm->want_x = rnd( st->SCREEN_X - min_dist * 2 ) + min_dist; + worm->want_y = rnd( st->SCREEN_Y - min_dist * 2 ) + min_dist; + worm->ang = gang( worm->actualx, worm->actualy, worm->want_x, worm->want_y ); + } + + + /* worm->ang = ( worm->ang + 360 + rnd( 30 ) - 15 ) % 360; */ + + /* + if ( worm->ang < worm->want_ang ) worm->ang++; + if ( worm->ang > worm->want_ang ) worm->ang--; + if ( worm->ang == worm->want_ang && rnd( 3 ) == rnd( 3 ) ) worm->want_ang = rnd( 360 ); + */ + + /* + if ( rnd( 25 ) == rnd( 25 ) ){ + x1 = worm->actualx; + y1 = worm->actualy; + x2 = SCREEN_X / 2 + rnd( 20 ) - 10; + y2 = SCREEN_Y / 2 + rnd( 20 ) - 10; + worm->want_ang = gang(x1,y1,x2,y2); + } + */ + + /* + if ( worm->actualx < min_dist || worm->actualx > SCREEN_X - min_dist || worm->actualy < min_dist || worm->actualy > SCREEN_Y - min_dist ){ + x1 = worm->actualx; + y1 = worm->actualy; + x2 = SCREEN_X / 2 + rnd( 20 ) - 10; + y2 = SCREEN_Y / 2 + rnd( 20 ) - 10; + / * worm->ang = gang( worm->actualx, worm->actualy, SCREEN_X/2+rnd(20)-10, SCREEN_Y/2+rnd(20)-10 ); * / + worm->ang = gang( x1, y1, x2, y2 ); + worm->want_ang = worm->ang; + / * printf("Angle = %d\n", worm->ang ); * / + + if ( worm->actualx < min_dist ) + worm->actualx = min_dist; + if ( worm->actualx > SCREEN_X - min_dist ) + worm->actualx = SCREEN_X - min_dist; + if ( worm->actualy < min_dist ) + worm->actualy = min_dist; + if ( worm->actualy > SCREEN_Y - min_dist ) + worm->actualy = SCREEN_Y - min_dist; + worm->virtualx = worm->actualx; + worm->virtualy = worm->actualy; + } + */ + + for ( q = 0; q < worm->num_stars; q++ ){ + if ( worm->stars[q] != NULL ){ + if ( moveStar( st, worm->stars[q] ) ){ + free( worm->stars[q] ); + worm->stars[q] = NULL; + } + } + } + + moveColorChanger( &worm->changer ); + + if ( worm->diameter < worm->diameter_change ) + worm->diameter++; + if ( worm->diameter > worm->diameter_change ) + worm->diameter--; + if ( rnd( 30 ) == rnd( 30 ) ) + worm->diameter_change = rnd( 35 ) + 5; + + for ( q = 0; q < worm->addStar; q++ ) + addStar( worm ); + +} + +static XColor * getColorShade( color_changer * ch ) +{ + return ch->shade + ch->min; +} + +static void drawWormhole( struct state *st, wormhole * worm ) +{ + + int i; + int color; + int z; + starline * current; + XColor * xcol; + XColor * shade; + + XSetForeground( st->dpy, st->gc, worm->black.pixel ); + XFillRectangle( st->dpy, worm->work, st->gc, 0, 0, st->SCREEN_X, st->SCREEN_Y ); + + for ( i = 0; i < worm->num_stars; i++ ) + if ( worm->stars[i] != NULL ){ + + current = worm->stars[i]; + z = current->begin.Z; + + color = z * worm->changer.shade_use / worm->max_Z; + shade = getColorShade( &worm->changer ); + /* xcol = &worm->changer.shade[ color ]; */ + xcol = &shade[ color ]; + + XSetForeground( st->dpy, st->gc, xcol->pixel ); + /* XDrawLine( st->dpy, st->window, *gc, current->begin.calc_x, current->begin.calc_y, current->end.calc_x, current->end.calc_y ); */ + XDrawLine( st->dpy, worm->work, st->gc, current->begin.calc_x, current->begin.calc_y, current->end.calc_x, current->end.calc_y ); + + } + if (worm->work != st->window) + XCopyArea( st->dpy, worm->work, st->window, st->gc, 0, 0, st->SCREEN_X, st->SCREEN_Y, 0, 0 ); +} + +/* +static void eraseWormhole( Display * display, Window * st->window, wormhole * worm ){ + starline * current; + int i; + XColor * xcol; + for ( i = 0; i < worm->num_stars; i++ ) + if ( worm->stars[i] != NULL ){ + xcol = &worm->black; + current = worm->stars[i]; + XSetForeground( st->dpy, *gc, xcol->pixel ); + XDrawLine( st->dpy, st->window, *gc, current->begin.calc_x, current->begin.calc_y, current->end.calc_x, current->end.calc_y ); + } +} +*/ + + + +static void * +wormhole_init (Display *dpy, Window window) +{ + struct state *st = (struct state *) calloc (1, sizeof(*st)); + XGCValues gcv; + XWindowAttributes attr; + + st->dpy = dpy; + st->window = window; + st->delay = get_integer_resource(st->dpy, "delay", "Integer" ); + st->make_stars = get_integer_resource(st->dpy, "stars", "Integer" ); + st->z_speed = get_integer_resource(st->dpy, "zspeed", "Integer" ); + + initWormhole( st, &st->worm, st->dpy, st->window ); + + st->gc = XCreateGC( st->dpy, st->window, 0, &gcv ); + XGetWindowAttributes( st->dpy, st->window, &attr ); + st->cmap = attr.colormap; + + return st; +} + +static unsigned long +wormhole_draw (Display *dpy, Window window, void *closure) +{ + struct state *st = (struct state *) closure; + + moveWormhole( st, &st->worm ); + drawWormhole( st, &st->worm ); + return st->delay; +} + +static void +wormhole_reshape (Display *dpy, Window window, void *closure, + unsigned int w, unsigned int h) +{ + struct state *st = (struct state *) closure; + resizeWormhole( st, &st->worm ); +} + +static Bool +wormhole_event (Display *dpy, Window window, void *closure, XEvent *event) +{ + return False; +} + +static void +wormhole_free (Display *dpy, Window window, void *closure) +{ + struct state *st = (struct state *) closure; + free (st); +} + + + + +static const char *wormhole_defaults [] = { + ".background: Black", + ".foreground: #E9967A", + "*delay: 10000", + "*zspeed: 10", + "*stars: 20", + 0 +}; + +static XrmOptionDescRec wormhole_options [] = { + { "-delay", ".delay", XrmoptionSepArg, 0 }, + { "-zspeed", ".zspeed", XrmoptionSepArg, 0 }, + { "-stars", ".stars", XrmoptionSepArg, 0 }, + { 0, 0, 0, 0 } +}; + +XSCREENSAVER_MODULE ("Wormhole", wormhole) diff --git a/hacks/wormhole.man b/hacks/wormhole.man new file mode 100644 index 00000000..f3287fae --- /dev/null +++ b/hacks/wormhole.man @@ -0,0 +1,69 @@ +.TH XScreenSaver 1 "11-feb-04" "X Version 11" +.SH NAME +wormhole - animation of flying through a wormhole +.SH SYNOPSIS +.B wormhole +[\-display \fIhost:display.screen\fP] +[\-window] +[\-visual \fIvisual\fP] +[\-root] +[\-stars \fIn\fP] +[\-delay \fIusecs\fP] +[\-zspeed \fIn\fP] +[\-fps] +.SH DESCRIPTION +The \fIwormhole\fP program shows an animation of flying through a tunnel surrounded by streaks of light. +.SH OPTIONS +.I wormhole +accepts the following options: +.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 \-mono +Make all the rocks the same color. +.TP 8 +.B \-install +Install a private colormap for the window. +.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 \-stars \fIinteger\fP +Number of stars to create every animation loop. +.TP 8 +.B \-zspeed \fIinteger\fP +Speed light streaks fly by. +.TP 8 +.B \-delay \fImicroseconds\fP +Number of microseconds to delay between each frame. Default 10000, meaning +about 1/100th second. Compare and contrast with \fI\-zspeed\fP, above. +.TP 8 +.B \-fps +Display the current frame rate and CPU load. +.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 2004 by Jon Rafkind. 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 +Jon Rafkind diff --git a/hacks/xanalogtv.c b/hacks/xanalogtv.c new file mode 100644 index 00000000..589d475c --- /dev/null +++ b/hacks/xanalogtv.c @@ -0,0 +1,617 @@ +/* xanalogtv, Copyright (c) 2003 Trevor Blackwell + * + * 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 test patterns on an analog TV. Concept similar to xteevee + * in this distribution, but a totally different implementation based + * on the simulation of an analog TV set in utils/analogtv.c. Much + * more realistic, but needs more video card bandwidth. + * + * It flips around through simulated channels 2 through 13. Some show + * 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 "config.h" +#endif /* HAVE_CONFIG_H */ + +#include + +#ifdef HAVE_UNISTD_H +# include +#endif + +#ifndef HAVE_COCOA +# include /* for XtDatabase in hack_resources() */ +#endif + +#include "screenhack.h" +#include "xpm-pixmap.h" +#include "analogtv.h" + +#include "images/logo-50.xpm" + +/* #define DEBUG 1 */ +/* #define USE_TEST_PATTERNS */ + +#define countof(x) (sizeof((x))/sizeof((*x))) + +enum { + N_CHANNELS=12, /* Channels 2 through 13 on VHF */ + MAX_MULTICHAN=2, + MAX_STATIONS=6 +}; + +typedef struct chansetting_s { + + analogtv_reception recs[MAX_MULTICHAN]; + double noise_level; + Bool image_loaded_p; +/* char *filename; was only used for diagnostics */ + int dur; +} chansetting; + + +struct state { + Display *dpy; + Window window; + analogtv *tv; + analogtv_font ugly_font; + struct timeval basetime; + + int n_stations; + analogtv_input *stations[MAX_STATIONS]; + Bool image_loading_p; + + int curinputi; + int change_ticks; + chansetting chansettings[N_CHANNELS]; + chansetting *cs; + + int change_now; + +}; + + +static void +update_smpte_colorbars(analogtv_input *input) +{ + struct state *st = (struct state *) input->client_data; + int col; + int xpos, ypos; + int black_ntsc[4]; + + /* + SMPTE is the society of motion picture and television engineers, and + these are the standard color bars in the US. Following the partial spec + at http://broadcastengineering.com/ar/broadcasting_inside_color_bars/ + These are luma, chroma, and phase numbers for each of the 7 bars. + */ + double top_cb_table[7][3]={ + {75, 0, 0.0}, /* gray */ + {69, 31, 167.0}, /* yellow */ + {56, 44, 283.5}, /* cyan */ + {48, 41, 240.5}, /* green */ + {36, 41, 60.5}, /* magenta */ + {28, 44, 103.5}, /* red */ + {15, 31, 347.0} /* blue */ + }; + double mid_cb_table[7][3]={ + {15, 31, 347.0}, /* blue */ + {7, 0, 0}, /* black */ + {36, 41, 60.5}, /* magenta */ + {7, 0, 0}, /* black */ + {56, 44, 283.5}, /* cyan */ + {7, 0, 0}, /* black */ + {75, 0, 0.0} /* gray */ + }; + + analogtv_lcp_to_ntsc(0.0, 0.0, 0.0, black_ntsc); + + analogtv_setup_sync(input, 1, 0); + analogtv_setup_teletext(input); + + for (col=0; col<7; col++) { + analogtv_draw_solid_rel_lcp(input, col*(1.0/7.0), (col+1)*(1.0/7.0), 0.00, 0.68, + top_cb_table[col][0], + top_cb_table[col][1], top_cb_table[col][2]); + + analogtv_draw_solid_rel_lcp(input, col*(1.0/7.0), (col+1)*(1.0/7.0), 0.68, 0.75, + mid_cb_table[col][0], + mid_cb_table[col][1], mid_cb_table[col][2]); + } + + analogtv_draw_solid_rel_lcp(input, 0.0, 1.0/6.0, + 0.75, 1.00, 7, 40, 303); /* -I */ + analogtv_draw_solid_rel_lcp(input, 1.0/6.0, 2.0/6.0, + 0.75, 1.00, 100, 0, 0); /* white */ + analogtv_draw_solid_rel_lcp(input, 2.0/6.0, 3.0/6.0, + 0.75, 1.00, 7, 40, 33); /* +Q */ + analogtv_draw_solid_rel_lcp(input, 3.0/6.0, 4.0/6.0, + 0.75, 1.00, 7, 0, 0); /* black */ + analogtv_draw_solid_rel_lcp(input, 12.0/18.0, 13.0/18.0, + 0.75, 1.00, 3, 0, 0); /* black -4 */ + analogtv_draw_solid_rel_lcp(input, 13.0/18.0, 14.0/18.0, + 0.75, 1.00, 7, 0, 0); /* black */ + analogtv_draw_solid_rel_lcp(input, 14.0/18.0, 15.0/18.0, + 0.75, 1.00, 11, 0, 0); /* black +4 */ + analogtv_draw_solid_rel_lcp(input, 5.0/6.0, 6.0/6.0, + 0.75, 1.00, 7, 0, 0); /* black */ + + + ypos=ANALOGTV_V/5; + xpos=ANALOGTV_VIS_START + ANALOGTV_VIS_LEN/2; + + { + char localname[256]; + if (gethostname (localname, sizeof (localname))==0) { + localname[sizeof(localname)-1]=0; /* "The returned name is null- + terminated unless insufficient + space is provided" */ + localname[24]=0; /* limit length */ + + analogtv_draw_string_centered(input, &st->ugly_font, localname, + xpos, ypos, black_ntsc); + } + } + ypos += st->ugly_font.char_h*5/2; + + analogtv_draw_xpm(st->tv, input, + logo_50_xpm, xpos - 100, ypos); + + ypos += 58; + +#if 0 + analogtv_draw_string_centered(input, &st->ugly_font, + "Please Stand By", xpos, ypos); + ypos += st->ugly_font.char_h*4; +#endif + + { + char timestamp[256]; + time_t t = time ((time_t *) 0); + struct tm *tm = localtime (&t); + + /* Y2K: It is OK for this to use a 2-digit year because it's simulating a + TV display and is purely decorative. */ + strftime(timestamp, sizeof(timestamp)-1, "%y.%m.%d %H:%M:%S ", tm); + analogtv_draw_string_centered(input, &st->ugly_font, timestamp, + xpos, ypos, black_ntsc); + } + + + 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_COCOA */ + "*chooseRandomImages: True", /* HAVE_COCOA */ + ANALOGTV_DEFAULTS + 0, +}; + +static XrmOptionDescRec xanalogtv_options [] = { + { "-delay", ".delay", XrmoptionSepArg, 0 }, + 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) +{ + struct timeval tv; + gettimeofday(&tv,NULL); + return ((tv.tv_sec - st->basetime.tv_sec)*1000 + + (tv.tv_usec - st->basetime.tv_usec)/1000); +} + + +/* The first time we grab an image, do it the default way. + The second and subsequent times, add "-no-desktop" to the command. + That way we don't have to watch the window un-map 5+ times in a row. + Also, we end up with the desktop on only one channel, and pictures + on all the others (or colorbars, if no imageDirectory is set.) + */ +static void +hack_resources (Display *dpy) +{ +#ifndef HAVE_COCOA + static int count = -1; + count++; + + if (count == 0) + return; + else if (count == 1) + { + XrmDatabase db = XtDatabase (dpy); + char *res = "desktopGrabber"; + char *val = get_string_resource (dpy, res, "DesktopGrabber"); + char buf1[255]; + char buf2[255]; + XrmValue value; + sprintf (buf1, "%.100s.%.100s", progname, res); + sprintf (buf2, "%.200s -no-desktop", val); + value.addr = buf2; + value.size = strlen(buf2); + XrmPutResource (&db, buf1, "String", &value); + } +#endif /* HAVE_COCOA */ +} + + +static void analogtv_load_random_image(struct state *); + + +static void image_loaded_cb (Screen *screen, Window window, Drawable pixmap, + const char *name, XRectangle *geometry, + void *closure) +{ + /* When an image has just been loaded, store it into the first available + channel. If there are other unloaded channels, then start loading + another image. + */ + struct state *st = (struct state *) closure; + int i; + int this = -1; + int next = -1; + + if (!st->image_loading_p) abort(); /* only one at a time... */ + st->image_loading_p = False; + + for (i = 0; i < MAX_STATIONS; i++) { + if (! st->chansettings[i].image_loaded_p) { + if (this == -1) this = i; + else if (next == -1) next = i; + } + } + if (this == -1) abort(); /* no unloaded stations? */ + + /* Load this image into the next channel. */ + { + analogtv_input *input = st->stations[this]; + int width=ANALOGTV_PIC_LEN; + int height=width*3/4; + XImage *image = XGetImage (st->dpy, pixmap, 0, 0, + width, height, ~0L, ZPixmap); + XFreePixmap(st->dpy, pixmap); + + analogtv_setup_sync(input, 1, (random()%20)==0); + analogtv_load_ximage(st->tv, input, image); + if (image) XDestroyImage(image); + st->chansettings[this].image_loaded_p = True; +#if 0 + if (name) { + const char *s = strrchr (name, '/'); + if (s) s++; + else s = name; + st->chansettings[this].filename = strdup (s); + } + fprintf(stderr, "%s: loaded channel %d, %s\n", progname, this, + st->chansettings[this].filename); +#endif + } + + /* If there are still unloaded stations, fire off another loader. */ + if (next != -1) + analogtv_load_random_image (st); +} + + +/* Queues a single image for loading. Only load one at a time. + The image is done loading when st->img_loader is null and + it->loaded_image is a pixmap. + */ +static void +analogtv_load_random_image(struct state *st) +{ + int width=ANALOGTV_PIC_LEN; + int height=width*3/4; + Pixmap p; + + if (st->image_loading_p) /* a load is already in progress */ + return; + + st->image_loading_p = True; + p = XCreatePixmap(st->dpy, st->window, width, height, st->tv->visdepth); + hack_resources(st->dpy); + load_image_async (st->tv->xgwa.screen, st->window, p, image_loaded_cb, st); +} + + +#if 0 +static int +analogtv_load_xpm(analogtv *it, analogtv_input *input, char **xpm) +{ + Pixmap pixmap; + XImage *image; + int width,height; + int rc; + + pixmap=xpm_data_to_pixmap (it->dpy, it->window, xpm, + &width, &height, NULL); + image = XGetImage(it->dpy, pixmap, 0, 0, width, height, ~0L, ZPixmap); + XFreePixmap(it->dpy, pixmap); + rc=analogtv_load_ximage(it, input, image); + if (image) XDestroyImage(image); + return rc; +} +#endif + + +static void add_stations(struct state *st) +{ + while (st->n_stations < MAX_STATIONS) { + analogtv_input *input=analogtv_input_allocate(); + st->stations[st->n_stations++]=input; + input->client_data = st; + } +} + + +static void load_station_images(struct state *st) +{ + int i; + for (i = 0; i < MAX_STATIONS; i++) { + analogtv_input *input = st->stations[i]; + + st->chansettings[i].image_loaded_p = True; + if (i == 0) { /* station 0 is always colorbars */ + input->updater = update_smpte_colorbars; + input->do_teletext=1; + } +#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]); + analogtv_setup_teletext(input); + } +#endif + else { + analogtv_load_random_image(st); + input->do_teletext=1; + st->chansettings[i].image_loaded_p = False; + } + } +} + + +static void * +xanalogtv_init (Display *dpy, Window window) +{ + struct state *st = (struct state *) calloc (1, sizeof(*st)); + 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"); + + st->dpy = dpy; + st->window = window; + st->tv=analogtv_allocate(dpy, window); + + add_stations(st); + + analogtv_set_defaults(st->tv, ""); + st->tv->need_clear=1; + + if (random()%4==0) { + st->tv->tint_control += pow(frand(2.0)-1.0, 7) * 180.0; + } + if (1) { + st->tv->color_control += frand(0.3); + } + + for (i=0; ichansettings[i], 0, sizeof(chansetting)); + + st->chansettings[i].noise_level = 0.06; + st->chansettings[i].dur = 1000*delay; + + if (random()%6==0) { + st->chansettings[i].dur=600; + } + else { + int stati; + for (stati=0; statichansettings[i].recs[stati]; + int station; + while (1) { + station=random()%st->n_stations; + if (station!=last_station) break; + if ((random()%10)==0) break; + } + last_station=station; + rec->input = st->stations[station]; + rec->level = pow(frand(1.0), 3.0) * 2.0 + 0.05; + rec->ofs=random()%ANALOGTV_SIGNAL_LEN; + if (random()%3) { + rec->multipath = frand(1.0); + } else { + rec->multipath=0.0; + } + if (stati) { + /* We only set a frequency error for ghosting stations, + because it doesn't matter otherwise */ + rec->freqerr = (frand(2.0)-1.0) * 3.0; + } + + if (rec->level > 0.3) break; + if (random()%4) break; + } + } + } + + gettimeofday(&st->basetime,NULL); + + st->curinputi=0; + st->cs = &st->chansettings[st->curinputi]; + st->change_ticks = st->cs->dur + 1500; + + st->tv->powerup=0.0; + + load_station_images(st); + + return st; +} + +static unsigned long +xanalogtv_draw (Display *dpy, Window window, void *closure) +{ + struct state *st = (struct state *) closure; + int i; + + int curticks=getticks(st); + double curtime=curticks*0.001; + + if (st->change_now || + (curticks >= st->change_ticks && st->tv->powerup > 10.0)) { + st->change_now = 0; + st->curinputi=(st->curinputi+1)%N_CHANNELS; + st->cs = &st->chansettings[st->curinputi]; +#if 0 + fprintf (stderr, "%s: channel %d, %s\n", progname, st->curinputi, + st->cs->filename); +#endif + st->change_ticks = curticks + st->cs->dur; + /* Set channel change noise flag */ + st->tv->channel_change_cycles=200000; + } + + for (i=0; ics->recs[i]; + analogtv_input *inp=rec->input; + if (!inp) continue; + + if (inp->updater) { + inp->next_update_time = curtime; + (inp->updater)(inp); + } + rec->ofs += rec->freqerr; + } + + st->tv->powerup=curtime; + + analogtv_init_signal(st->tv, st->cs->noise_level); + for (i=0; ics->recs[i]; + analogtv_input *inp=rec->input; + if (!inp) continue; + + analogtv_reception_update(rec); + analogtv_add_signal(st->tv, rec); + } + analogtv_draw(st->tv); + return 10000; +} + +static void +xanalogtv_reshape (Display *dpy, Window window, void *closure, + unsigned int w, unsigned int h) +{ + struct state *st = (struct state *) closure; + analogtv_reconfigure(st->tv); +} + +static Bool +xanalogtv_event (Display *dpy, Window window, void *closure, XEvent *event) +{ + struct state *st = (struct state *) closure; + + if (event->type == ButtonPress) + { + st->change_now = 1; + return True; + } + else if (event->type == KeyPress) + { + KeySym keysym; + char c = 0; + XLookupString (&event->xkey, &c, 1, &keysym, 0); + if (c == ' ' || c == '\t' || c == '\r' || c == '\n') + { + st->change_now = 1; + return True; + } + } + + return False; +} + +static void +xanalogtv_free (Display *dpy, Window window, void *closure) +{ + struct state *st = (struct state *) closure; + analogtv_release(st->tv); + free (st); +} + + +XSCREENSAVER_MODULE ("XAnalogTV", xanalogtv) diff --git a/hacks/xanalogtv.man b/hacks/xanalogtv.man new file mode 100644 index 00000000..79ac57b5 --- /dev/null +++ b/hacks/xanalogtv.man @@ -0,0 +1,84 @@ +.TH XScreenSaver 1 "10-Oct-03" "X Version 11" +.SH NAME +xanalogtv - Simulate reception on an old analog TV set +.SH SYNOPSIS +.B xanalogtv +[\-display \fIhost:display.screen\fP] [\-window] [\-root] [\-install] +[\-visual \fIvisual\fP] +[\-cycle] [\-no-cycle] +[\-fps] +.SH DESCRIPTION +.I xanalogtv +shows a simulation of an old TV set showing test patterns and any +other images you have provided. It reproduces a wide range of TV +reception bummage: snow, bloom, ghosting, and loss of vertical and +horizontal sync. It also simulates the TV warming up. It will cycle +through 12 channels, some with images you give it, and some with color +bars or nothing but static. +.PP +The images that it uses will be grabbed from the portion of the screen +underlying the window, or from the system's video input, or from a +random file on disk, as indicated by the \fIgrabDesktopImages\fP, +\fIgrabVideoFrames\fP, and \fIchooseRandomImages\fP options in the +\fI~/.xscreensaver\fP file; see +.BR xscreensaver-demo (1) +for more details. It looks best with a video input or +your digital photo collection. +.PP +.SH OPTIONS +.I xanalogtv +accepts the following options: +.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 \-install +Install a private colormap for the window. +.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 \-fps +Display the current frame rate and CPU load. +.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 X RESOURCES +Notable X resources supported include the following which correspond +to standard TV controls: +.BR analogTVTint , +.BR analogTVColor , +.BR analogTVBrightness , +and +.BR analogTVContrast . +They range from 0 to 100, except for tint which is an angle +between -180 and +180. + +.SH SEE ALSO +.BR X (1), +.BR xteevee (MANSUFFIX), +.BR apple2 (MANSUFFIX), +.BR bsod (MANSUFFIX), +.BR xscreensaver (1), +.BR xscreensaver\-demo (1), +.BR xscreensaver\-getimage (1) +.SH COPYRIGHT +Copyright \(co 2003 by Trevor Blackwell. 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 +Trevor Blackwell diff --git a/hacks/xflame.c b/hacks/xflame.c new file mode 100644 index 00000000..2785fb81 --- /dev/null +++ b/hacks/xflame.c @@ -0,0 +1,816 @@ +/* xflame, Copyright (c) 1996-2002 Carsten Haitzler + * + * 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. + */ + +/* Version history as near as I (jwz) can piece together: + + * Carsten Haitzler wrote the first version in 1996. + + * Rahul Jain added support for TrueColor displays. + + * Someone did a rough port of it to use the xscreensaver utility routines + instead of creating its own window by hand. + + * Someone (probably Raster) came up with a subsequent version that had + a Red Hat logo hardcoded into it. + + * Daniel Zahn found that version in 1998, and + hacked it to be able to load a different logo from a PGM (P5) file, + with a single hardcoded pathname. + + * Jamie Zawinski found several versions of xflame in + March 1999, and pieced them together. Changes: + + - Correct and fault-tolerant use of the Shared Memory extension; + previous versions of xflame did not work when $DISPLAY was remote. + + - Replaced PGM-reading code with code that can read arbitrary XBM + and XPM files (color ones will be converted to grayscale.) + + - Command-line options all around -- no hardcoded pathnames or + behavioral constants. + + - General cleanup and portability tweaks. + + * 4-Oct-99, jwz: added support for packed-24bpp (versus 32bpp.) + * 16-Jan-2002, jwz: added gdk_pixbuf support. + + */ + +/* portions by Daniel Zahn */ + + +#include "screenhack.h" +#include "xpm-pixmap.h" +#include + +#undef countof +#define countof(x) (sizeof((x))/sizeof((*x))) + +#ifdef HAVE_XSHM_EXTENSION +# include "xshm.h" +#endif /* HAVE_XSHM_EXTENSION */ + +#include "images/bob.xbm" + +#define MAX_VAL 255 + +struct state { + Display *dpy; + Window window; + int depth; + int width; + int height; + Colormap colormap; + Visual *visual; + Screen *screen; + Bool shared; + Bool bloom; + XImage *xim; +#ifdef HAVE_XSHM_EXTENSION + XShmSegmentInfo shminfo; +#endif /* HAVE_XSHM_EXTENSION */ + GC gc; + int ctab[256]; + + unsigned char *flame; + unsigned char *theim; + int fwidth; + int fheight; + int top; + int hspread; + int vspread; + int residual; + + int ihspread; + int ivspread; + int iresidual; + int variance; + int vartrend; + + int delay; + int baseline; + int theimx, theimy; +}; + +static void +GetXInfo(struct state *st) +{ + XWindowAttributes xwa; + + XGetWindowAttributes(st->dpy,st->window,&xwa); + + st->colormap = xwa.colormap; + st->depth = xwa.depth; + st->visual = xwa.visual; + st->screen = xwa.screen; + st->width = xwa.width; + st->height = xwa.height; + + if (st->width%2) + st->width++; + if (st->height%2) + st->height++; +} + +static void +MakeImage(struct state *st) +{ + XGCValues gcv; + +#ifdef HAVE_XSHM_EXTENSION + st->shared = True; + st->xim = create_xshm_image (st->dpy, st->visual, st->depth, ZPixmap, NULL, + &st->shminfo, st->width, st->height); +#else /* !HAVE_XSHM_EXTENSION */ + st->xim = 0; +#endif /* !HAVE_XSHM_EXTENSION */ + + if (!st->xim) + { + st->shared = False; + st->xim = XCreateImage (st->dpy, st->visual, st->depth, ZPixmap, 0, NULL, + st->width, st->height, 32, 0); + if (st->xim) + st->xim->data = (char *) calloc(st->xim->height, st->xim->bytes_per_line); + if (!st->xim || !st->xim->data) + { + fprintf(stderr,"%s: out of memory.\n", progname); + exit(1); + } + } + + st->gc = XCreateGC(st->dpy,st->window,0,&gcv); + if (!st->gc) exit (1); +} + + +static void +InitColors(struct state *st) +{ + int i = 0, j = 0, red = 0, green = 0, blue = 0; + XColor fg; + + /* Make it possible to set the color of the flames, + by Raymond Medeiros and jwz. + */ + fg.pixel = get_pixel_resource (st->dpy, st->colormap, + "foreground", "Foreground"); + XQueryColor (st->dpy, st->colormap, &fg); + + red = 255 - (fg.red >> 8); + green = 255 - (fg.green >> 8); + blue = 255 - (fg.blue >> 8); + + + for (i = 0; i < 256 * 2; i += 2) + { + XColor xcl; + int r = (i - red) * 3; + int g = (i - green) * 3; + int b = (i - blue) * 3; + + if (r < 0) r = 0; + if (r > 255) r = 255; + if (g < 0) g = 0; + if (g > 255) g = 255; + if (b < 0) b = 0; + if (b > 255) b = 255; + + xcl.red = (unsigned short)((r << 8) | r); + xcl.green = (unsigned short)((g << 8) | g); + xcl.blue = (unsigned short)((b << 8) | b); + xcl.flags = DoRed | DoGreen | DoBlue; + + XAllocColor(st->dpy,st->colormap,&xcl); + + st->ctab[j++] = (int)xcl.pixel; + } +} + + +static void +DisplayImage(struct state *st) +{ +#ifdef HAVE_XSHM_EXTENSION + if (st->shared) + XShmPutImage(st->dpy, st->window, st->gc, st->xim, 0,(st->top - 1) << 1, 0, + (st->top - 1) << 1, st->width, st->height - ((st->top - 1) << 1), False); + else +#endif /* HAVE_XSHM_EXTENSION */ + XPutImage(st->dpy, st->window, st->gc, st->xim, 0, (st->top - 1) << 1, 0, + (st->top - 1) << 1, st->width, st->height - ((st->top - 1) << 1)); +} + + +static void +InitFlame(struct state *st) +{ + st->fwidth = st->width / 2; + st->fheight = st->height / 2; + st->flame = (unsigned char *) malloc((st->fwidth + 2) * (st->fheight + 2) + * sizeof(unsigned char)); + + if (!st->flame) + { + fprintf(stderr,"%s: out of memory\n", progname); + exit(1); + } + + st->top = 1; + st->ihspread = get_integer_resource(st->dpy, "hspread", "Integer"); + st->ivspread = get_integer_resource(st->dpy, "vspread", "Integer"); + st->iresidual = get_integer_resource(st->dpy, "residual", "Integer"); + st->variance = get_integer_resource(st->dpy, "variance", "Integer"); + st->vartrend = get_integer_resource(st->dpy, "vartrend", "Integer"); + st->bloom = get_boolean_resource(st->dpy, "bloom", "Boolean"); + +# define THROTTLE(VAR,NAME) \ + if (VAR < 0 || VAR > 255) { \ + fprintf(stderr, "%s: %s must be in the range 0-255 (not %d).\n", \ + progname, NAME, VAR); \ + exit(1); } + THROTTLE (st->ihspread, "hspread"); + THROTTLE (st->ivspread, "vspread"); + THROTTLE (st->iresidual,"residual"); + THROTTLE (st->variance, "variance"); + THROTTLE (st->vartrend, "vartrend"); +# undef THROTTLE + + + + st->hspread = st->ihspread; + st->vspread = st->ivspread; + st->residual = st->iresidual; +} + + +static void +Flame2Image16(struct state *st) +{ + int x,y; + unsigned short *ptr; + unsigned char *ptr1; + int v1,v2,v3,v4; + + ptr = (unsigned short *)st->xim->data; + ptr += (st->top << 1) * st->width; + ptr1 = st->flame + 1 + (st->top * (st->fwidth + 2)); + + for(y = st->top; y < st->fheight; y++) + { + for( x = 0; x < st->fwidth; x++) + { + v1 = (int)*ptr1; + v2 = (int)*(ptr1 + 1); + v3 = (int)*(ptr1 + st->fwidth + 2); + v4 = (int)*(ptr1 + st->fwidth + 2 + 1); + ptr1++; + *ptr++ = (unsigned short)st->ctab[v1]; + *ptr = (unsigned short)st->ctab[(v1 + v2) >> 1]; + ptr += st->width - 1; + *ptr++ = (unsigned short)st->ctab[(v1 + v3) >> 1]; + *ptr = (unsigned short)st->ctab[(v1 + v4) >> 1]; + ptr -= st->width - 1; + } + ptr += st->width; + ptr1 += 2; + } +} + +static void +Flame2Image32(struct state *st) +{ + int x,y; + unsigned int *ptr; + unsigned char *ptr1; + int v1,v2,v3,v4; + + ptr = (unsigned int *)st->xim->data; + ptr += (st->top << 1) * st->width; + ptr1 = st->flame + 1 + (st->top * (st->fwidth + 2)); + + for( y = st->top; y < st->fheight; y++) + { + for( x = 0; x < st->fwidth; x++) + { + v1 = (int)*ptr1; + v2 = (int)*(ptr1 + 1); + v3 = (int)*(ptr1 + st->fwidth + 2); + v4 = (int)*(ptr1 + st->fwidth + 2 + 1); + ptr1++; + *ptr++ = (unsigned int)st->ctab[v1]; + *ptr = (unsigned int)st->ctab[(v1 + v2) >> 1]; + ptr += st->width - 1; + *ptr++ = (unsigned int)st->ctab[(v1 + v3) >> 1]; + *ptr = (unsigned int)st->ctab[(v1 + v4) >> 1]; + ptr -= st->width - 1; + } + ptr += st->width; + ptr1 += 2; + } +} + +static void +Flame2Image24(struct state *st) +{ + int x,y; + unsigned char *ptr; + unsigned char *ptr1; + int v1,v2,v3,v4; + + ptr = (unsigned char *)st->xim->data; + ptr += (st->top << 1) * st->xim->bytes_per_line; + ptr1 = st->flame + 1 + (st->top * (st->fwidth + 2)); + + for( y = st->top; y < st->fheight; y++) + { + unsigned char *last_ptr = ptr; + for( x = 0; x < st->fwidth; x++) + { + v1 = (int)*ptr1; + v2 = (int)*(ptr1 + 1); + v3 = (int)*(ptr1 + st->fwidth + 2); + v4 = (int)*(ptr1 + st->fwidth + 2 + 1); + ptr1++; + + ptr[2] = ((unsigned int)st->ctab[v1] & 0x00FF0000) >> 16; + ptr[1] = ((unsigned int)st->ctab[v1] & 0x0000FF00) >> 8; + ptr[0] = ((unsigned int)st->ctab[v1] & 0x000000FF); + ptr += 3; + + ptr[2] = ((unsigned int)st->ctab[(v1 + v2) >> 1] & 0x00FF0000) >> 16; + ptr[1] = ((unsigned int)st->ctab[(v1 + v2) >> 1] & 0x0000FF00) >> 8; + ptr[0] = ((unsigned int)st->ctab[(v1 + v2) >> 1] & 0x000000FF); + ptr += ((st->width - 1) * 3); + + ptr[2] = ((unsigned int)st->ctab[(v1 + v3) >> 1] & 0x00FF0000) >> 16; + ptr[1] = ((unsigned int)st->ctab[(v1 + v3) >> 1] & 0x0000FF00) >> 8; + ptr[0] = ((unsigned int)st->ctab[(v1 + v3) >> 1] & 0x000000FF); + ptr += 3; + + ptr[2] = ((unsigned int)st->ctab[(v1 + v4) >> 1] & 0x00FF0000) >> 16; + ptr[1] = ((unsigned int)st->ctab[(v1 + v4) >> 1] & 0x0000FF00) >> 8; + ptr[0] = ((unsigned int)st->ctab[(v1 + v4) >> 1] & 0x000000FF); + ptr -= ((st->width - 1) * 3); + } + + ptr = last_ptr + (st->xim->bytes_per_line << 1); + ptr1 += 2; + } +} + +static void +Flame2Image8(struct state *st) +{ + int x,y; + unsigned char *ptr; + unsigned char *ptr1; + int v1,v2,v3,v4; + + ptr = (unsigned char *)st->xim->data; + ptr += (st->top << 1) * st->width; + ptr1 = st->flame + 1 + (st->top * (st->fwidth + 2)); + + for(y=st->top;yfheight;y++) + { + for(x=0;xfwidth;x++) + { + v1 = (int)*ptr1; + v2 = (int)*(ptr1 + 1); + v3 = (int)*(ptr1 + st->fwidth + 2); + v4 = (int)*(ptr1 + st->fwidth + 2 + 1); + ptr1++; + *ptr++ = (unsigned char)st->ctab[v1]; + *ptr = (unsigned char)st->ctab[(v1 + v2) >> 1]; + ptr += st->width - 1; + *ptr++ = (unsigned char)st->ctab[(v1 + v3) >> 1]; + *ptr = (unsigned char)st->ctab[(v1 + v4) >> 1]; + ptr -= st->width - 1; + } + ptr += st->width; + ptr1 += 2; + } +} + +static void +Flame2Image1234567(struct state *st) +{ + int x,y; + unsigned char *ptr1; + int v1,v2,v3,v4; + + ptr1 = st->flame + 1 + (st->top * (st->fwidth + 2)); + + for( y = st->top; y < st->fheight; y++) + { + for( x = 0; x < st->fwidth; x++) + { + v1 = (int)*ptr1; + v2 = (int)*(ptr1 + 1); + v3 = (int)*(ptr1 + st->fwidth + 2); + v4 = (int)*(ptr1 + st->fwidth + 2 + 1); + ptr1++; + XPutPixel(st->xim,(x << 1), (y << 1), st->ctab[v1]); + XPutPixel(st->xim,(x << 1) + 1,(y << 1), st->ctab[(v1 + v2) >> 1]); + XPutPixel(st->xim,(x << 1), (y << 1) + 1,st->ctab[(v1 + v3) >> 1]); + XPutPixel(st->xim,(x << 1) + 1,(y << 1) + 1,st->ctab[(v1 + v4) >> 1]); + } + } +} + +static void +Flame2Image(struct state *st) +{ + switch (st->xim->bits_per_pixel) + { + case 32: Flame2Image32(st); break; + case 24: Flame2Image24(st); break; + case 16: Flame2Image16(st); break; + case 8: Flame2Image8(st); break; + default: + if (st->xim->bits_per_pixel <= 7) + Flame2Image1234567(st); + else + abort(); + break; + } +} + + +static void +FlameActive(struct state *st) +{ + int x,v1; + unsigned char *ptr1; + + ptr1 = st->flame + ((st->fheight + 1) * (st->fwidth + 2)); + + for (x = 0; x < st->fwidth + 2; x++) + { + v1 = *ptr1; + v1 += ((random() % st->variance) - st->vartrend); + *ptr1++ = v1 % 255; + } + + if (st->bloom) + { + v1= (random() % 100); + if (v1 == 10) + st->residual += (random()%10); + else if (v1 == 20) + st->hspread += (random()%15); + else if (v1 == 30) + st->vspread += (random()%20); + } + + st->residual = ((st->iresidual* 10) + (st->residual *90)) / 100; + st->hspread = ((st->ihspread * 10) + (st->hspread *90)) / 100; + st->vspread = ((st->ivspread * 10) + (st->vspread *90)) / 100; +} + + +static void +FlameAdvance(struct state *st) +{ + int x,y; + unsigned char *ptr2; + int newtop = st->top; + + for (y = st->fheight + 1; y >= st->top; y--) + { + int used = 0; + unsigned char *ptr1 = st->flame + 1 + (y * (st->fwidth + 2)); + for (x = 0; x < st->fwidth; x++) + { + int v1 = (int)*ptr1; + int v2, v3; + if (v1 > 0) + { + used = 1; + ptr2 = ptr1 - st->fwidth - 2; + v3 = (v1 * st->vspread) >> 8; + v2 = (int)*(ptr2); + v2 += v3; + if (v2 > MAX_VAL) + v2 = MAX_VAL; + + *(ptr2) = (unsigned char)v2; + v3 = (v1 * st->hspread) >> 8; + v2 = (int)*(ptr2 + 1); + v2 += v3; + if (v2 > MAX_VAL) + v2 = MAX_VAL; + + *(ptr2 + 1) = (unsigned char)v2; + v2 = (int)*(ptr2 - 1); + v2 += v3; + if (v2 > MAX_VAL) + v2 = MAX_VAL; + + *(ptr2 - 1) = (unsigned char)v2; + + if (y < st->fheight + 1) + { + v1 = (v1 * st->residual) >> 8; + *ptr1 = (unsigned char)v1; + } + } + ptr1++; + if (used) + newtop = y - 1; + } + + /* clean up the right gutter */ + { + int v1 = (int)*ptr1; + v1 = (v1 * st->residual) >> 8; + *ptr1 = (unsigned char)v1; + } + } + + st->top = newtop - 1; + + if (st->top < 1) + st->top = 1; +} + + +static void +FlameFill(struct state *st, int val) +{ + int x, y; + for (y = 0; y < st->fheight + 1; y++) + { + unsigned char *ptr1 = st->flame + 1 + (y * (st->fwidth + 2)); + for (x = 0; x < st->fwidth; x++) + { + *ptr1 = val; + ptr1++; + } + } +} + + +static void +FlamePasteData(struct state *st, + unsigned char *d, int xx, int yy, int w, int h) +{ + unsigned char *ptr1,*ptr2; + ptr2 = d; + + if (xx < 0) xx = 0; + if (yy < 0) yy = 0; + + if ((xx >= 0) && + (yy >= 0) && + (xx + w <= st->fwidth) && + (yy + h <= st->fheight)) + { + int x, y; + for (y = 0; y < h; y++) + { + ptr1 = st->flame + 1 + xx + ((yy + y) * (st->fwidth + 2)); + for (x = 0; x < w; x++) + { + if (*ptr2 / 24) + *ptr1 += random() % (*ptr2 / 24); + + ptr1++; + ptr2++; + } + } + } + else + { + static Bool warned = False; + if (!warned) + { + fprintf (stderr, "%s: st->window is %dx%d; image must be " + "smaller than %dx%d (not %dx%d).\n", + progname, st->width, st->height, st->fwidth, st->fheight, w, h); + warned = True; + } + } +} + + +static unsigned char * +loadBitmap(struct state *st, int *w, int *h) +{ + char *bitmap_name = get_string_resource (st->dpy, "bitmap", "Bitmap"); + +#ifdef HAVE_COCOA + bitmap_name = "(default)"; /* #### always use builtin */ +#endif /* HAVE_COCOA */ + + if (!bitmap_name || + !*bitmap_name || + !strcmp(bitmap_name, "none")) + ; + else if (!strcmp(bitmap_name, "(default)")) /* use the builtin */ + { + XImage *ximage; + unsigned char *result, *o; + char *bits = (char *) malloc (sizeof(bob_bits)); + int x, y; + int scale = ((st->width > bob_width * 11) ? 2 : 1); + + memcpy (bits, bob_bits, sizeof(bob_bits)); + ximage = XCreateImage (st->dpy, st->visual, 1, XYBitmap, 0, bits, + bob_width, bob_height, 8, 0); + ximage->byte_order = LSBFirst; + ximage->bitmap_bit_order = LSBFirst; + *w = ximage->width * scale; + *h = ximage->height * scale; + o = result = (unsigned char *) malloc ((*w * scale) * (*h * scale)); + for (y = 0; y < *h; y++) + for (x = 0; x < *w; x++) + *o++ = (XGetPixel(ximage, x/scale, y/scale) ? 255 : 0); + + return result; + } + else /* load a bitmap file */ +#ifdef HAVE_COCOA + abort(); /* #### fix me */ +#else + { + Pixmap pixmap = + xpm_file_to_pixmap (st->dpy, st->window, bitmap_name, &st->width, &st->height, 0); + XImage *image; + int x, y; + unsigned char *result, *o; + XColor colors[256]; + Bool cmap_p = has_writable_cells (st->screen, st->visual); + + 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, st->width, st->height, ~0L, ZPixmap); + XFreePixmap(st->dpy, pixmap); + + result = (unsigned char *) malloc (st->width * st->height); + o = result; + for (y = 0; y < st->height; y++) + for (x = 0; x < st->width; x++) + { + int rgba = XGetPixel (image, x, y); + int gray; + if (cmap_p) + gray = ((200 - ((((colors[rgba].red >> 8) & 0xFF) + + ((colors[rgba].green >> 8) & 0xFF) + + ((colors[rgba].blue >> 8) & 0xFF)) + >> 1)) + & 0xFF); + else + /* This is *so* not handling all the cases... */ + gray = (image->depth > 16 + ? ((((rgba >> 24) & 0xFF) + + ((rgba >> 16) & 0xFF) + + ((rgba >> 8) & 0xFF) + + ((rgba ) & 0xFF)) >> 2) + : ((((rgba >> 12) & 0x0F) + + ((rgba >> 8) & 0x0F) + + ((rgba >> 4) & 0x0F) + + ((rgba ) & 0x0F)) >> 1)); + + *o++ = 255 - gray; + } + + XFree (image->data); + image->data = 0; + XDestroyImage (image); + + *w = st->width; + *h = st->height; + return result; + } +#endif /* !HAVE_COCOA */ + + *w = 0; + *h = 0; + return 0; + +} + +static void * +xflame_init (Display *dpy, Window win) +{ + struct state *st = (struct state *) calloc (1, sizeof(*st)); + st->dpy = dpy; + st->window = win; + st->baseline = get_integer_resource (dpy, "bitmapBaseline", "Integer"); + st->delay = get_integer_resource (dpy, "delay", "Integer"); + st->xim = NULL; + st->top = 1; + st->flame = NULL; + + GetXInfo(st); + InitColors(st); + st->theim = loadBitmap(st, &st->theimx, &st->theimy); + + /* utils/xshm.c doesn't provide a way to free the shared-memory image, which + makes it hard for us to react to window resizing. So, punt for now. The + size of the window at startup is the size it will stay. + */ + GetXInfo(st); + + MakeImage(st); + InitFlame(st); + FlameFill(st,0); + + return st; +} + +static unsigned long +xflame_draw (Display *dpy, Window win, void *closure) +{ + struct state *st = (struct state *) closure; + FlameActive(st); + + if (st->theim) + FlamePasteData(st, st->theim, (st->fwidth - st->theimx) / 2, + st->fheight - st->theimy - st->baseline, st->theimx, st->theimy); + + FlameAdvance(st); + Flame2Image(st); + DisplayImage(st); + + return st->delay; +} + +static void +xflame_reshape (Display *dpy, Window window, void *closure, + unsigned int w, unsigned int h) +{ +} + +static Bool +xflame_event (Display *dpy, Window window, void *closure, XEvent *event) +{ + return False; +} + +static void +xflame_free (Display *dpy, Window window, void *closure) +{ +} + + + + +static const char *xflame_defaults [] = { + ".background: black", + ".foreground: #FFAF5F", + "*fpsTop: true", + "*fpsSolid: true", + "*bitmap: (default)", + "*bitmapBaseline: 20", + "*delay: 10000", + "*hspread: 30", + "*vspread: 97", + "*residual: 99", + "*variance: 50", + "*vartrend: 20", + "*bloom: True", + +#ifdef HAVE_XSHM_EXTENSION + "*useSHM: False", /* xshm turns out not to help. */ +#endif /* HAVE_XSHM_EXTENSION */ + 0 +}; + +static XrmOptionDescRec xflame_options [] = { + { "-foreground",".foreground", XrmoptionSepArg, 0 }, + { "-fg", ".foreground", XrmoptionSepArg, 0 }, + { "-delay", ".delay", XrmoptionSepArg, 0 }, + { "-bitmap", ".bitmap", XrmoptionSepArg, 0 }, + { "-baseline", ".bitmapBaseline", XrmoptionSepArg, 0 }, + { "-hspread", ".hspread", XrmoptionSepArg, 0 }, + { "-vspread", ".vspread", XrmoptionSepArg, 0 }, + { "-residual", ".residual", XrmoptionSepArg, 0 }, + { "-variance", ".variance", XrmoptionSepArg, 0 }, + { "-vartrend", ".vartrend", XrmoptionSepArg, 0 }, + { "-bloom", ".bloom", XrmoptionNoArg, "True" }, + { "-no-bloom", ".bloom", XrmoptionNoArg, "False" }, +#ifdef HAVE_XSHM_EXTENSION + { "-shm", ".useSHM", XrmoptionNoArg, "True" }, + { "-no-shm", ".useSHM", XrmoptionNoArg, "False" }, +#endif /* HAVE_XSHM_EXTENSION */ + { 0, 0, 0, 0 } +}; + + +XSCREENSAVER_MODULE ("XFlame", xflame) diff --git a/hacks/xflame.man b/hacks/xflame.man new file mode 100644 index 00000000..faba0af8 --- /dev/null +++ b/hacks/xflame.man @@ -0,0 +1,72 @@ +.TH XScreenSaver 1 "27-Feb-00" "X Version 11" +.SH NAME +xflame - draws animated flames +.SH SYNOPSIS +.B xflame +[\-display \fIhost:display.screen\fP] [\-window] [\-root] [\-install] +[\-visual \fIvisual\fP] +[\-foreground \fIcolor\fP] +[\-hspread \fIint\fP] [\-vspread \fIint\fP] +[\-residual \fIint\fP] [\-variance \fIint\fP] [\-vartrend \fIint\fP] +[\-bloom \| \-no\-bloom] +[\-bitmap \fIxbm\-file\fP] [\-baseline \fIint\fP] +[\-fps] +.SH DESCRIPTION +The \fIxflame\fP program draws animated flames across the bottom of the +screen. The flames occasionally flare up. If a bitmap is specified, +that image will float above the flames, burning. +.SH OPTIONS +.I xflame +accepts the following options: +.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 \-install +Install a private colormap for the window. +.TP 8 +.B \-visual \fIvisual\fP\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 \-foreground \fIcolor\fP\fP or \fB\-fg\fP \fIcolor\fP\fP +The color of the flames; default red. (The background color is always black.) +.TP 8 +.B \-bitmap \fIfilename\fP\fP +Specifies the bitmap file to use (a monochrome XBM file.) +The name "none" means not to use a bitmap at all. +If unspecified, a built-in image will be used. +.PP +The other options are arcane. If someone would care to document them, +that would be great. +.TP 8 +.B \-fps +Display the current frame rate and CPU load. +.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 1996-1999 by Carsten Haitzler. 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 +Primarily written by Carsten Haitzler . +Modified over the years by Rahul Jain , +Daniel Zahn , and Jamie Zawinski . diff --git a/hacks/xjack.c b/hacks/xjack.c new file mode 100644 index 00000000..1765243c --- /dev/null +++ b/hacks/xjack.c @@ -0,0 +1,484 @@ +/* xscreensaver, Copyright (c) 1997-2012 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. + * + * Wendy, let me explain something to you. Whenever you come in here and + * interrupt me, you're BREAKING my CONCENTRATION. You're DISTRACTING me! + * And it will then take me time to get back to where I was. You understand? + * Now, we're going to make a new rule. When you come in here and you hear + * me typing, or whether you DON'T hear me typing, or whatever the FUCK you + * hear me doing; when I'm in here, it means that I am working, THAT means + * don't come in! Now, do you think you can handle that? + */ + +#include +#include "screenhack.h" + +static const char *source = "All work and no play makes Jack a dull boy. "; +/* If you're here because you're thinking about making the above string be + customizable, then you don't get the joke. You loser. */ + +struct state { + Display *dpy; + Window window; + XWindowAttributes xgwa; + XFontStruct *font; + GC gc; + + const char *s; + int columns, rows; /* characters */ + int left, right; /* characters */ + int char_width, line_height; /* pixels */ + int x, y; /* characters */ + int mode; + int hspace; /* pixels */ + int vspace; /* pixels */ + Bool break_para; + Bool caps; + int sentences; + int paras; + int scrolling; + int subscrolling; + int pining; + + int delay; +}; + + +static void +xjack_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); + st->columns = (st->xgwa.width - st->hspace - st->hspace) / st->char_width; + st->rows = (st->xgwa.height - st->vspace - st->vspace) / st->line_height; + st->rows--; + st->columns--; + + /* If the window is stupidly small, just truncate. */ + if (st->rows < 4) st->rows = 4; + if (st->columns < 12) st->columns = 12; + + if (st->y > st->rows) st->y = st->rows-1; + if (st->x > st->columns) st->x = st->columns-2; + + if (st->right > st->columns) st->right = st->columns; + if (st->left > st->columns-20) st->left = st->columns-20; + if (st->left < 0) st->left = 0; + + XClearWindow (st->dpy, st->window); +} + + +static void * +xjack_init (Display *dpy, Window window) +{ + struct state *st = (struct state *) calloc (1, sizeof(*st)); + XGCValues gcv; + char *fontname; + + st->dpy = dpy; + st->window = window; + st->s = source; + st->delay = get_integer_resource (st->dpy, "delay", "Integer"); + fontname = get_string_resource (st->dpy, "font", "Font"); + + XGetWindowAttributes (st->dpy, st->window, &st->xgwa); + + if (st->xgwa.width <= 480) + fontname = "-*-courier-medium-r-*-*-*-180-*-*-m-*-*-*"; + + st->font = XLoadQueryFont (st->dpy, fontname); + + if (!st->font) + st->font = XLoadQueryFont (st->dpy, "-*-*-medium-r-*-*-*-240-*-*-m-*-*-*"); + if (!st->font) + st->font = XLoadQueryFont (st->dpy, + "-*-courier-medium-r-*-*-*-180-*-*-m-*-*-*"); + if (!st->font) + st->font = XLoadQueryFont (st->dpy, "-*-*-*-r-*-*-*-240-*-*-m-*-*-*"); + if (!st->font) + { + fprintf(stderr, "no big fixed-width font like \"%s\"\n", fontname); + exit(1); + } + + gcv.font = st->font->fid; + gcv.foreground = get_pixel_resource (st->dpy, st->xgwa.colormap, + "foreground", "Foreground"); + gcv.background = get_pixel_resource (st->dpy, st->xgwa.colormap, + "background", "Background"); + st->gc = XCreateGC (st->dpy, st->window, + (GCFont | GCForeground | GCBackground), &gcv); + + st->char_width = + (st->font->per_char + ? st->font->per_char['n'-st->font->min_char_or_byte2].rbearing + : st->font->min_bounds.rbearing); + st->line_height = st->font->ascent + st->font->descent + 1; + + xjack_reshape (dpy, window, st, st->xgwa.width, st->xgwa.height); + + if (st->columns >= 21) + { + st->left = 0xFF & (random() % ((st->columns / 2)+1)); + st->right = st->left + (0xFF & (random() % (st->columns - st->left - 10) + + 10)); + } + st->x = 0; + st->y = 0; + + if (st->xgwa.width > 200 && st->xgwa.height > 200) + st->hspace = st->vspace = 40; + + return st; +} + +static unsigned long +xjack_scroll (struct state *st) +{ + st->break_para = 0; + if (st->subscrolling) + { + int inc = st->line_height / 7; + XCopyArea (st->dpy, st->window, st->window, st->gc, + 0, inc, + st->xgwa.width, st->xgwa.height - inc, + 0, 0); + + /* See? It's OK. He saw it on the television. */ + XClearArea (st->dpy, st->window, + 0, st->xgwa.height - inc, st->xgwa.width, inc, + False); + + st->subscrolling -= inc; + if (st->subscrolling <= 0) + st->subscrolling = 0; + if (st->subscrolling == 0) + { + if (st->scrolling > 0) + st->scrolling--; + st->y--; + } + return st->delay / 1000; + } + else if (st->scrolling) + st->subscrolling = st->line_height; + + if (st->y < 0) + st->y = 0; + else if (st->y >= st->rows-1) + st->y = st->rows-1; + + return st->delay; +} + +static unsigned long +xjack_pine (struct state *st) +{ + /* See also http://catalog.com/hopkins/unix-haters/login.html */ + const char *n1 = "NFS server overlook not responding, still trying..."; + const char *n2 = "NFS server overlook ok."; + int prev = st->pining; + + if (!st->pining) + st->pining = 1 + (random() % 3); + + if (prev) + while (*n2) + { + XDrawString (st->dpy, st->window, st->gc, + (st->x * st->char_width) + st->hspace, + ((st->y * st->line_height) + st->vspace + + st->font->ascent), + (char *) n2, 1); + st->x++; + if (st->x >= st->columns) st->x = 0, st->y++; + n2++; + } + st->y++; + st->x = 0; + st->pining--; + + if (st->pining) + while (*n1) + { + XDrawString (st->dpy, st->window, st->gc, + (st->x * st->char_width) + st->hspace, + ((st->y * st->line_height) + st->vspace + + st->font->ascent), + (char *) n1, 1); + st->x++; + if (st->x >= st->columns) st->x = 0, st->y++; + n1++; + } + + return 5000000; +} + + +static unsigned long +xjack_draw (Display *dpy, Window window, void *closure) +{ + struct state *st = (struct state *) closure; + int this_delay = st->delay; + int word_length = 0; + const char *s2; + + if (st->scrolling) + return xjack_scroll (st); + if (st->pining) + return xjack_pine (st); + + for (s2 = st->s; *s2 && *s2 != ' '; s2++) + word_length++; + + if (st->break_para || + (*st->s != ' ' && + (st->x + word_length) >= st->right)) + { + st->x = st->left; + st->y++; + + if (st->break_para) + st->y++; + + if (st->mode == 1 || st->mode == 2) + { + /* 1 = left margin goes southwest; 2 = southeast */ + st->left += (st->mode == 1 ? 1 : -1); + if (st->left >= st->right - 10) + { + if ((st->right < (st->columns - 10)) && (random() & 1)) + st->right += (0xFF & (random() % (st->columns - st->right))); + else + st->mode = 2; + } + else if (st->left <= 0) + { + st->left = 0; + st->mode = 1; + } + } + else if (st->mode == 3 || st->mode == 4) + { + /* 3 = right margin goes southeast; 4 = southwest */ + st->right += (st->mode == 3 ? 1 : -1); + if (st->right >= st->columns) + { + st->right = st->columns; + st->mode = 4; + } + else if (st->right <= st->left + 10) + st->mode = 3; + } + + if (st->y >= st->rows-1) /* bottom of page */ + { + /* scroll by 1-5 lines */ + st->scrolling = (random() % 5 ? 0 : (0xFF & (random() % 5))) + 1; + if (st->break_para) + st->scrolling++; + + /* but sometimes scroll by a whole page */ + if (0 == (random() % 100)) + st->scrolling += st->rows; + + return xjack_scroll (st); + } + } + + if (*st->s != ' ') + { + char c = *st->s; + int xshift = 0, yshift = 0; + if (0 == random() % 50) + { + xshift = random() % ((st->char_width / 3) + 1); /* mis-strike */ + yshift = random() % ((st->line_height / 6) + 1); + if (0 == (random() % 3)) + yshift *= 2; + if (random() & 1) + xshift = -xshift; + if (random() & 1) + yshift = -yshift; + } + + if (0 == (random() % 250)) /* introduce adjascent-key typo */ + { + static const char * const typo[] = { + "asqw", "ASQW", "bgvhn", "cxdfv", "dserfcx", "ewsdrf", + "Jhuikmn", "kjiol,m", "lkop;.,", "mnjk,", "nbhjm", "oiklp09", + "pol;(-0", "redft54", "sawedxz", "uyhji87", "wqase32", + "yuhgt67", ".,l;/", 0 }; + int i = 0; + while (typo[i] && typo[i][0] != c) + i++; + if (typo[i]) + c = typo[i][0xFF & ((random() % strlen(typo[i]+1)) + 1)]; + } + + /* caps typo */ + if (c >= 'a' && c <= 'z' && (st->caps || 0 == (random() % 350))) + { + c -= ('a'-'A'); + if (c == 'O' && random() & 1) + c = '0'; + } + + OVERSTRIKE: + XDrawString (st->dpy, st->window, st->gc, + (st->x * st->char_width) + st->hspace + xshift, + ((st->y * st->line_height) + st->vspace + st->font->ascent + + yshift), + &c, 1); + if (xshift == 0 && yshift == 0 && (0 == (random() & 3000))) + { + if (random() & 1) + xshift--; + else + yshift--; + goto OVERSTRIKE; + } + + if ((tolower(c) != tolower(*st->s)) + ? (0 == (random() % 10)) /* backup to correct */ + : (0 == (random() % 400))) /* fail to advance */ + { + st->x--; + st->s--; + if (st->delay) + st->delay += (0xFFFF & (st->delay + + (random() % (st->delay * 10)))); + } + } + + st->x++; + st->s++; + + if (0 == random() % 200) + { + if (random() & 1 && st->s != source) + st->s--; /* duplicate character */ + else if (*st->s) + st->s++; /* skip character */ + } + + if (*st->s == 0) + { + st->sentences++; + st->caps = (0 == random() % 40); /* capitalize sentence */ + + if (0 == (random() % 10) || /* randomly break paragraph */ + (st->mode == 0 && + ((0 == (random() % 10)) || st->sentences > 20))) + { + st->break_para = True; + st->sentences = 0; + st->paras++; + + if (random() & 1) /* mode=0 50% of the time */ + st->mode = 0; + else + st->mode = (0xFF & (random() % 5)); + + if (0 == (random() % 2)) /* re-pick margins */ + { + st->left = 0xFF & (random() % (st->columns / 3)); + st->right = (st->columns - + (0xFF & (random() % (st->columns / 3)))); + + if (0 == random() % 3) /* sometimes be wide */ + st->right = st->left + ((st->right - st->left) / 2); + } + + if (st->right - st->left <= 10) /* introduce sanity */ + { + st->left = 0; + st->right = st->columns; + } + + if (st->right - st->left > 50) /* if wide, shrink and move */ + { + st->left += (0xFF & (random() % ((st->columns - 50) + 1))); + st->right = st->left + (0xFF & ((random() % 40) + 10)); + } + + /* oh, gag. */ + if (st->mode == 0 && + st->right - st->left < 25 && + st->columns > 40) + { + st->right += 20; + if (st->right > st->columns) + st->left -= (st->right - st->columns); + } + } + st->s = source; + } + + if (st->delay) + { + if (0 == random() % 3) + this_delay += (0xFFFFFF & ((random() % (st->delay * 5)) + 1)); + + if (st->break_para) + this_delay += (0xFFFFFF & ((random() % (st->delay * 15)) + 1)); + } + + if (st->paras > 5 && + (0 == (random() % 1000)) && + st->y < st->rows-2) + return xjack_pine (st); + + return this_delay; +} + +static Bool +xjack_event (Display *dpy, Window window, void *closure, XEvent *event) +{ + struct state *st = (struct state *) closure; + if (event->xany.type == ButtonPress) + { + st->scrolling++; + return True; + } + + return False; +} + +static void +xjack_free (Display *dpy, Window window, void *closure) +{ + struct state *st = (struct state *) closure; + free (st); +} + + +static const char *xjack_defaults [] = { + ".background: #FFF0B4", + ".foreground: #000000", + "*fpsSolid: true", +#ifdef HAVE_COCOA + ".font: American Typewriter 24", +#else + ".font: -*-courier-medium-r-*-*-*-240-*-*-m-*-*-*", +#endif + "*delay: 50000", + 0 +}; + +static XrmOptionDescRec xjack_options [] = { + { "-delay", ".delay", XrmoptionSepArg, 0 }, + { "-font", ".font", XrmoptionSepArg, 0 }, + { 0, 0, 0, 0 } +}; + +XSCREENSAVER_MODULE ("XJack", xjack) diff --git a/hacks/xjack.man b/hacks/xjack.man new file mode 100644 index 00000000..894f9eac --- /dev/null +++ b/hacks/xjack.man @@ -0,0 +1,52 @@ +.TH XScreenSaver 1 "18-sep-97" "X Version 11" +.SH NAME +xjack - all work and no play makes jack a dull boy +.SH SYNOPSIS +.B xjack +[\-display \fIhost:display.screen\fP] [\-foreground \fIcolor\fP] [\-background \fIcolor\fP] [\-window] [\-root] [\-delay \fIusecs\fP] +[\-fps] +.SH DESCRIPTION +All work and no play makes jack a dull boy. All work and no play makes jack +a dull boy. All work and no play makes jack a dull boy. All work and no +play makes jack a dull boy. All work and no play makes jack a dull boy. +All work and no play makes jack a dull boy. +.PP +.RS 8 +All work and no play makes jack a dull boy. All work and no play makes jack +a dull boy. All work and no play makes jack a dull boy. All work and no +play makes jack a dull boy. All work and no play makes jack a dull boy. +All work and no play makes jack a dull boy. +.PP +All work and no play makes jack a dull boy. All work and no play makes jack +a dull boy. All work and no play makes jack a dull boy. All work and no +play makes jack a dull boy. All work and no play makes jack a dull boy. All +work and no play makes jack a dull boy. All work and no play makes jack a +dull boy. All work and no play makes jack a dull boy. +.PP +.RE +All work and no play makes jack a dull boy. +All work and no play makes jack a dull boy. All work and no play makes jack +a dull boy. All work and no play makes jack a dull boy. All work and no +play makes jack a dull boy. All work and no play makes jack a dull boy. +All work and no play makes jack a dull boy. All work and no play makes jack +a dull boy. +.SH ENVIRONMENT +.PP +.TP 8 +.B DISPLAY +All work and no play makes jack a dull boy. +.TP 8 +.B XENVIRONMENT +All work and no play makes jack a dull boy. All work and no play makes jack +a dull boy. +.SH SEE ALSO +.BR X (1), +.BR xscreensaver (1) +.SH COPYRIGHT +Copyright \(co 1997 by Jamie Zawinski. All work and no play makes jack a +dull boy. All work and no play makes jack a dull boy. All work and no play +makes jack a dull boy. All work and no play makes jack a dull boy. All work +and no play makes jack a fnord dull boy. All work and no play makes jack a +dull boy. +.SH AUTHOR +Jamie Zawinski , 15-Nov-97. diff --git a/hacks/xlockmore.c b/hacks/xlockmore.c new file mode 100644 index 00000000..0c0b2c92 --- /dev/null +++ b/hacks/xlockmore.c @@ -0,0 +1,557 @@ +/* xlockmore.c --- xscreensaver compatibility layer for xlockmore modules. + * xscreensaver, Copyright (c) 1997-2011 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. + * + * This file, along with xlockmore.h, make it possible to compile an xlockmore + * module into a standalone program, and thus use it with xscreensaver. + * By Jamie Zawinski on 10-May-97; based on the ideas + * in the older xlock.h by Charles Hannum . (I had + * to redo it, since xlockmore has diverged so far from xlock...) + */ + +#include "xlockmoreI.h" +#include "screenhack.h" + +#ifndef HAVE_COCOA +# include +#endif /* !HAVE_COCOA */ + +#define countof(x) (sizeof((x))/sizeof(*(x))) + +#define MAX_COLORS (1L<<13) + +extern struct xscreensaver_function_table *xscreensaver_function_table; + +extern const char *progclass; + +extern struct xlockmore_function_table xlockmore_function_table; + +static void *xlockmore_init (Display *, Window, + struct xlockmore_function_table *); +static unsigned long xlockmore_draw (Display *, Window, void *); +static void xlockmore_reshape (Display *, Window, void *, + unsigned int w, unsigned int h); +static Bool xlockmore_event (Display *, Window, void *, XEvent *); +static void xlockmore_free (Display *, Window, void *); + + +void +xlockmore_setup (struct xscreensaver_function_table *xsft, void *arg) +{ + struct xlockmore_function_table *xlmft = + (struct xlockmore_function_table *) arg; + int i, j; + char *s; + XrmOptionDescRec *new_options; + char **new_defaults; + const char *xlockmore_defaults; + ModeSpecOpt *xlockmore_opts = xlmft->opts; + +# undef ya_rand_init + ya_rand_init (0); + + xsft->init_cb = (void *(*) (Display *, Window)) xlockmore_init; + xsft->draw_cb = xlockmore_draw; + xsft->reshape_cb = xlockmore_reshape; + xsft->event_cb = xlockmore_event; + xsft->free_cb = xlockmore_free; + + progclass = xlmft->progclass; + xlockmore_defaults = xlmft->defaults; + + /* Translate the xlockmore `opts[]' argument to a form that + screenhack.c expects. + */ + new_options = (XrmOptionDescRec *) + calloc (xlockmore_opts->numopts*3 + 100, sizeof (*new_options)); + + for (i = 0; i < xlockmore_opts->numopts; i++) + { + XrmOptionDescRec *old = &xlockmore_opts->opts[i]; + XrmOptionDescRec *new = &new_options[i]; + + if (old->option[0] == '-') + new->option = old->option; + else + { + /* Convert "+foo" to "-no-foo". */ + new->option = (char *) malloc (strlen(old->option) + 5); + strcpy (new->option, "-no-"); + strcat (new->option, old->option + 1); + } + + new->specifier = strrchr (old->specifier, '.'); + if (!new->specifier) abort(); + + new->argKind = old->argKind; + new->value = old->value; + } + + /* Add extra args, if they're mentioned in the defaults... */ + { + char *args[] = { "-count", "-cycles", "-delay", "-ncolors", + "-size", "-font", "-wireframe", "-use3d", "-useSHM" }; + for (j = 0; j < countof(args); j++) + if (strstr(xlockmore_defaults, args[j]+1)) + { + XrmOptionDescRec *new = &new_options[i++]; + new->option = args[j]; + new->specifier = strdup(args[j]); + new->specifier[0] = '.'; + if (!strcmp(new->option, "-wireframe")) + { + new->argKind = XrmoptionNoArg; + new->value = "True"; + new = &new_options[i++]; + new->option = "-no-wireframe"; + new->specifier = new_options[i-2].specifier; + new->argKind = XrmoptionNoArg; + new->value = "False"; + } + else if (!strcmp(new->option, "-use3d")) + { + new->option = "-3d"; + new->argKind = XrmoptionNoArg; + new->value = "True"; + new = &new_options[i++]; + new->option = "-no-3d"; + new->specifier = new_options[i-2].specifier; + new->argKind = XrmoptionNoArg; + new->value = "False"; + } + else if (!strcmp(new->option, "-useSHM")) + { + new->option = "-shm"; + new->argKind = XrmoptionNoArg; + new->value = "True"; + new = &new_options[i++]; + new->option = "-no-shm"; + new->specifier = new_options[i-2].specifier; + new->argKind = XrmoptionNoArg; + new->value = "False"; + } + else + { + new->argKind = XrmoptionSepArg; + new->value = 0; + } + } + } + + + + /* Construct the kind of `defaults' that screenhack.c expects from + the xlockmore `vars[]' argument. + */ + i = 0; + + new_defaults = (char **) calloc (1, xlockmore_opts->numvarsdesc * 10 + 1000); + + /* Put on the PROGCLASS.background/foreground resources. */ + s = (char *) malloc(50); + *s = 0; +# ifndef HAVE_COCOA + strcpy (s, progclass); +# endif + strcat (s, ".background: black"); + new_defaults [i++] = s; + + s = (char *) malloc(50); + *s = 0; +# ifndef HAVE_COCOA + strcpy (s, progclass); +# endif + strcat (s, ".foreground: white"); + new_defaults [i++] = s; + + /* Copy the lines out of the `xlockmore_defaults' var and into this array. */ + s = strdup (xlockmore_defaults); + while (s && *s) + { + new_defaults [i++] = s; + s = strchr(s, '\n'); + if (s) + *s++ = 0; + } + + /* Copy the defaults out of the `xlockmore_opts->' variable. */ + for (j = 0; j < xlockmore_opts->numvarsdesc; j++) + { + const char *def = xlockmore_opts->vars[j].def; + + if (!def) abort(); + if (!*def) abort(); + if (strlen(def) > 1000) abort(); + + s = (char *) malloc (strlen (xlockmore_opts->vars[j].name) + + strlen (def) + 10); + strcpy (s, "*"); + strcat (s, xlockmore_opts->vars[j].name); + strcat (s, ": "); + strcat (s, def); + new_defaults [i++] = s; + + /* Go through the list of resources and print a warning if there + are any duplicates. + */ + { + char *onew = strdup (xlockmore_opts->vars[j].name); + const char *new = onew; + int k; + if ((s = strrchr (new, '.'))) new = s+1; + if ((s = strrchr (new, '*'))) new = s+1; + for (k = 0; k < i-1; k++) + { + char *oold = strdup (new_defaults[k]); + const char *old = oold; + if ((s = strchr (oold, ':'))) *s = 0; + if ((s = strrchr (old, '.'))) old = s+1; + if ((s = strrchr (old, '*'))) old = s+1; + if (!strcasecmp (old, new)) + { + fprintf (stderr, + "%s: duplicate resource \"%s\": " + "set in both DEFAULTS and vars[]\n", + progname, old); + } + free (oold); + } + free (onew); + } + } + + new_defaults [i] = 0; + + xsft->progclass = progclass; + xsft->options = new_options; + xsft->defaults = (const char * const *) new_defaults; +} + + +static void +xlockmore_read_resources (ModeInfo *mi) +{ + Display *dpy = mi->dpy; + ModeSpecOpt *xlockmore_opts = mi->xlmft->opts; + int i; + for (i = 0; i < xlockmore_opts->numvarsdesc; i++) + { + void *var = xlockmore_opts->vars[i].var; + Bool *var_b = (Bool *) var; + char **var_c = (char **) var; + int *var_i = (int *) var; + float *var_f = (float *) var; + + switch (xlockmore_opts->vars[i].type) + { + case t_String: + *var_c = get_string_resource (dpy, xlockmore_opts->vars[i].name, + xlockmore_opts->vars[i].classname); + break; + case t_Float: + *var_f = get_float_resource (dpy, xlockmore_opts->vars[i].name, + xlockmore_opts->vars[i].classname); + break; + case t_Int: + *var_i = get_integer_resource (dpy, xlockmore_opts->vars[i].name, + xlockmore_opts->vars[i].classname); + break; + case t_Bool: + *var_b = get_boolean_resource (dpy, xlockmore_opts->vars[i].name, + xlockmore_opts->vars[i].classname); + break; + default: + abort (); + } + } +} + + +static void * +xlockmore_init (Display *dpy, Window window, + struct xlockmore_function_table *xlmft) +{ + ModeInfo *mi = (ModeInfo *) calloc (1, sizeof(*mi)); + XGCValues gcv; + XColor color; + int i; + Bool root_p; + + if (! xlmft) + abort(); + mi->xlmft = xlmft; + + mi->dpy = dpy; + mi->window = window; + XGetWindowAttributes (dpy, window, &mi->xgwa); + +#ifdef HAVE_COCOA + + /* In Cocoa-based xscreensaver, all hacks run in the same address space, + so each one needs to get its own screen number. We just use a global + counter for that, instead of actually trying to figure out which + monitor each window is on. Also, the embedded "preview" view counts + as a screen as well. + + Note that the screen number will increase each time the saver is + restarted (e.g., each time preferences are changed!) So we just + keep pushing the num_screens number up as needed, and assume that + no more than 10 simultanious copies will be running at once... + */ + { + static int screen_tick = 0; + mi->num_screens = 10; + mi->screen_number = screen_tick++; + if (screen_tick >= mi->num_screens) + mi->num_screens += 10; + } + + root_p = True; +#else /* !HAVE_COCOA -- real Xlib */ + + /* In Xlib-based xscreensaver, each hack runs in its own address space, + so each one only needs to be aware of one screen. + */ + mi->num_screens = 1; + mi->screen_number = 0; + + { /* kludge for DEBUG_PAIR */ + static int screen_tick = 0; + mi->num_screens++; + if (screen_tick) + mi->screen_number++; + screen_tick++; + } + + root_p = (window == RootWindowOfScreen (mi->xgwa.screen)); + + /* Everybody gets motion events, just in case. */ + XSelectInput (dpy, window, (mi->xgwa.your_event_mask | PointerMotionMask)); + +#endif /* !HAVE_COCOA */ + + color.flags = DoRed|DoGreen|DoBlue; + color.red = color.green = color.blue = 0; + if (!XAllocColor(dpy, mi->xgwa.colormap, &color)) + abort(); + mi->black = color.pixel; + color.red = color.green = color.blue = 0xFFFF; + if (!XAllocColor(dpy, mi->xgwa.colormap, &color)) + abort(); + mi->white = color.pixel; + + if (mono_p) + { + static unsigned long pixels[2]; + static XColor colors[2]; + MONO: + mi->npixels = 2; + if (! mi->pixels) + mi->pixels = (unsigned long *) + calloc (mi->npixels, sizeof (*mi->pixels)); + if (!mi->colors) + mi->colors = (XColor *) + calloc (mi->npixels, sizeof (*mi->colors)); + pixels[0] = mi->black; + pixels[1] = mi->white; + colors[0].flags = DoRed|DoGreen|DoBlue; + colors[1].flags = DoRed|DoGreen|DoBlue; + colors[0].red = colors[0].green = colors[0].blue = 0; + colors[1].red = colors[1].green = colors[1].blue = 0xFFFF; + mi->writable_p = False; + } + else + { + mi->npixels = get_integer_resource (dpy, "ncolors", "Integer"); + if (mi->npixels <= 0) + mi->npixels = 64; + else if (mi->npixels > MAX_COLORS) + mi->npixels = MAX_COLORS; + + mi->colors = (XColor *) calloc (mi->npixels, sizeof (*mi->colors)); + + mi->writable_p = mi->xlmft->want_writable_colors; + + switch (mi->xlmft->desired_color_scheme) + { + case color_scheme_uniform: + make_uniform_colormap (dpy, mi->xgwa.visual, mi->xgwa.colormap, + mi->colors, &mi->npixels, + True, &mi->writable_p, True); + break; + case color_scheme_smooth: + make_smooth_colormap (dpy, mi->xgwa.visual, mi->xgwa.colormap, + mi->colors, &mi->npixels, + True, &mi->writable_p, True); + break; + case color_scheme_bright: + case color_scheme_default: + make_random_colormap (dpy, mi->xgwa.visual, mi->xgwa.colormap, + mi->colors, &mi->npixels, + (mi->xlmft->desired_color_scheme == + color_scheme_bright), + True, &mi->writable_p, True); + break; + default: + abort(); + } + + if (mi->npixels <= 2) + goto MONO; + else + { + mi->pixels = (unsigned long *) + calloc (mi->npixels, sizeof (*mi->pixels)); + for (i = 0; i < mi->npixels; i++) + mi->pixels[i] = mi->colors[i].pixel; + } + } + + gcv.foreground = mi->white; + gcv.background = mi->black; + mi->gc = XCreateGC (dpy, window, GCForeground|GCBackground, &gcv); + + mi->fullrandom = True; + + mi->pause = get_integer_resource (dpy, "delay", "Usecs"); + + mi->cycles = get_integer_resource (dpy, "cycles", "Int"); + mi->batchcount = get_integer_resource (dpy, "count", "Int"); + mi->size = get_integer_resource (dpy, "size", "Int"); + + mi->threed = get_boolean_resource (dpy, "use3d", "Boolean"); + mi->threed_delta = get_float_resource (dpy, "delta3d", "Float"); + mi->threed_right_color = get_pixel_resource (dpy, + mi->xgwa.colormap, "right3d", "Color"); + mi->threed_left_color = get_pixel_resource (dpy, + mi->xgwa.colormap, "left3d", "Color"); + mi->threed_both_color = get_pixel_resource (dpy, + mi->xgwa.colormap, "both3d", "Color"); + mi->threed_none_color = get_pixel_resource (dpy, + mi->xgwa.colormap, "none3d", "Color"); + + mi->wireframe_p = get_boolean_resource (dpy, "wireframe", "Boolean"); + mi->root_p = root_p; +#ifdef HAVE_XSHM_EXTENSION + mi->use_shm = get_boolean_resource (dpy, "useSHM", "Boolean"); +#endif /* !HAVE_XSHM_EXTENSION */ + mi->fps_p = get_boolean_resource (dpy, "doFPS", "DoFPS"); + mi->recursion_depth = -1; /* see fps.c */ + + if (mi->pause < 0) + mi->pause = 0; + else if (mi->pause > 100000000) + mi->pause = 100000000; + + /* If this hack uses fonts (meaning, mentioned "font" in DEFAULTS) + then load it. */ + { + char *name = get_string_resource (dpy, "font", "Font"); + if (name) + { + XFontStruct *f = XLoadQueryFont (dpy, name); + const char *def1 = "-*-helvetica-bold-r-normal-*-180-*"; + const char *def2 = "fixed"; + if (!f) + { + fprintf (stderr, "%s: font %s does not exist, using %s\n", + progname, name, def1); + f = XLoadQueryFont (dpy, def1); + } + if (!f) + { + fprintf (stderr, "%s: font %s does not exist, using %s\n", + progname, def1, def2); + f = XLoadQueryFont (dpy, def2); + } + if (f) XSetFont (dpy, mi->gc, f->fid); + if (f) XFreeFont (dpy, f); + free (name); + } + } + + xlockmore_read_resources (mi); + + XClearWindow (dpy, window); + + mi->xlmft->hack_init (mi); + + return mi; +} + +static unsigned long +xlockmore_draw (Display *dpy, Window window, void *closure) +{ + ModeInfo *mi = (ModeInfo *) closure; + + unsigned long orig_pause = mi->pause; + unsigned long this_pause; + + mi->xlmft->hack_draw (mi); + + this_pause = mi->pause; + mi->pause = orig_pause; + return this_pause; +} + + +static void +xlockmore_reshape (Display *dpy, Window window, void *closure, + unsigned int w, unsigned int h) +{ + ModeInfo *mi = (ModeInfo *) closure; + if (mi && mi->xlmft->hack_reshape) + { + XGetWindowAttributes (dpy, window, &mi->xgwa); + mi->xlmft->hack_reshape (mi, mi->xgwa.width, mi->xgwa.height); + } +} + +static Bool +xlockmore_event (Display *dpy, Window window, void *closure, XEvent *event) +{ + ModeInfo *mi = (ModeInfo *) closure; + if (mi && mi->xlmft->hack_handle_events) + return mi->xlmft->hack_handle_events (mi, event); + else + return False; +} + +void +xlockmore_do_fps (Display *dpy, Window w, fps_state *fpst, void *closure) +{ + ModeInfo *mi = (ModeInfo *) closure; + fps_compute (fpst, 0, mi ? mi->recursion_depth : -1); + fps_draw (fpst); +} + + +static void +xlockmore_free (Display *dpy, Window window, void *closure) +{ + /* Most of the xlockmore/GL hacks don't have `free' functions, and of + those that do have them, they're incomplete or buggy. So, fuck it. + Under X11, we're about to exit anyway, and it doesn't matter. + On OSX, we'll leak a little. Beats crashing. + */ +#if 0 + ModeInfo *mi = (ModeInfo *) closure; + if (mi->xlmft->hack_free) + mi->xlmft->hack_free (mi); + + XFreeGC (dpy, mi->gc); + free_colors (dpy, mi->xgwa.colormap, mi->colors, mi->npixels); + free (mi->colors); + free (mi->pixels); + + free (mi); +#endif +} + diff --git a/hacks/xlockmore.h b/hacks/xlockmore.h new file mode 100644 index 00000000..3eeae789 --- /dev/null +++ b/hacks/xlockmore.h @@ -0,0 +1,198 @@ +/* xlockmore.h --- xscreensaver compatibility layer for xlockmore modules. + * xscreensaver, Copyright (c) 1997-2012 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. + * + * The definitions in this file make it possible to compile an xlockmore + * module into a standalone program, and thus use it with xscreensaver. + * By Jamie Zawinski on 10-May-97; based on the ideas + * in the older xlock.h by Charles Hannum . (I had + * to redo it, since xlockmore has diverged so far from xlock...) + */ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif /* HAVE_CONFIG_H */ + +#ifndef __STDC__ +ERROR! Sorry, xlockmore.h requires ANSI C (gcc, for example.) + /* (The ansi dependency is that we use string concatenation, + and cpp-based stringification of tokens.) */ +#endif + +#include "screenhackI.h" +#include "xlockmoreI.h" + +# define ENTRYPOINT static + +/* Accessor macros for the ModeInfo structure + */ +#define MI_DISPLAY(MI) ((MI)->dpy) +#define MI_WINDOW(MI) ((MI)->window) +#define MI_NUM_SCREENS(MI) ((MI)->num_screens) +#define MI_SCREEN(MI) ((MI)->screen_number) +#define MI_WIN_WHITE_PIXEL(MI) ((MI)->white) +#define MI_WIN_BLACK_PIXEL(MI) ((MI)->black) +#define MI_NPIXELS(MI) ((MI)->npixels) +#define MI_PIXEL(MI,N) ((MI)->pixels[(N)]) +#define MI_WIN_WIDTH(MI) ((MI)->xgwa.width) +#define MI_WIN_HEIGHT(MI) ((MI)->xgwa.height) +#define MI_WIN_DEPTH(MI) ((MI)->xgwa.depth) +#define MI_DEPTH(MI) ((MI)->xgwa.depth) +#define MI_WIN_COLORMAP(MI) ((MI)->xgwa.colormap) +#define MI_VISUAL(MI) ((MI)->xgwa.visual) +#define MI_GC(MI) ((MI)->gc) +#define MI_PAUSE(MI) ((MI)->pause) +#define MI_DELAY(MI) ((MI)->pause) +#define MI_WIN_IS_FULLRANDOM(MI)((MI)->fullrandom) +#define MI_WIN_IS_VERBOSE(MI) (False) +#define MI_WIN_IS_INSTALL(MI) (True) +#define MI_WIN_IS_MONO(MI) (mono_p) +#define MI_WIN_IS_INROOT(MI) ((MI)->root_p) +#define MI_WIN_IS_INWINDOW(MI) (!(MI)->root_p) +#define MI_WIN_IS_ICONIC(MI) (False) +#define MI_WIN_IS_WIREFRAME(MI) ((MI)->wireframe_p) +#define MI_WIN_IS_USE3D(MI) ((MI)->threed) +#define MI_LEFT_COLOR(MI) ((MI)->threed_left_color) +#define MI_RIGHT_COLOR(MI) ((MI)->threed_right_color) +#define MI_BOTH_COLOR(MI) ((MI)->threed_both_color) +#define MI_NONE_COLOR(MI) ((MI)->threed_none_color) +#define MI_DELTA3D(MI) ((MI)->threed_delta) +#define MI_CYCLES(MI) ((MI)->cycles) +#define MI_BATCHCOUNT(MI) ((MI)->batchcount) +#define MI_SIZE(MI) ((MI)->size) +#define MI_IS_DRAWN(MI) ((MI)->is_drawn) +#define MI_IS_FPS(MI) ((MI)->fps_p) +#define MI_NCOLORS(MI) ((MI)->npixels) +#define MI_NAME(MI) (progname) + +#define MI_COLORMAP(MI) (MI_WIN_COLORMAP((MI))) +#define MI_WIDTH(MI) (MI_WIN_WIDTH((MI))) +#define MI_HEIGHT(MI) (MI_WIN_HEIGHT((MI))) +#define MI_IS_ICONIC(MI) (MI_WIN_IS_ICONIC((MI))) +#define MI_IS_WIREFRAME(MI) (MI_WIN_IS_WIREFRAME((MI))) +#define MI_IS_MONO(MI) (MI_WIN_IS_MONO((MI))) +#define MI_COUNT(MI) (MI_BATCHCOUNT((MI))) +#define MI_BLACK_PIXEL(MI) (MI_WIN_BLACK_PIXEL(MI)) +#define MI_WHITE_PIXEL(MI) (MI_WIN_WHITE_PIXEL(MI)) +#define MI_IS_FULLRANDOM(MI) (MI_WIN_IS_FULLRANDOM(MI)) +#define MI_IS_VERBOSE(MI) (MI_WIN_IS_VERBOSE(MI)) +#define MI_IS_INSTALL(MI) (MI_WIN_IS_INSTALL(MI)) +#define MI_IS_DEBUG(MI) (False) +#define MI_IS_MOUSE(MI) (False) + +#define MI_CLEARWINDOW(mi) XClearWindow(MI_DISPLAY(mi), MI_WINDOW(mi)) + +#define FreeAllGL(dpy) /* */ + +/* Some other utility macros. + */ +#define SINF(n) ((float)sin((double)(n))) +#define COSF(n) ((float)cos((double)(n))) +#define FABSF(n) ((float)fabs((double)(n))) + +#undef MAX +#undef MIN +#undef ABS +#define MAX(a,b)((a)>(b)?(a):(b)) +#define MIN(a,b)((a)<(b)?(a):(b)) +#define ABS(a)((a)<0 ? -(a) : (a)) + +/* Maximum possible number of colors (*not* default number of colors.) */ +#define NUMCOLORS 256 + + +/* In an Xlib world, we define two global symbols here: + a struct in `MODULENAME_xscreensaver_function_table', + and a pointer to that in `xscreensaver_function_table'. + + In a Cocoa world, we only define the prefixed symbol; + the un-prefixed symbol does not exist. + */ +#ifdef HAVE_COCOA +# define XSCREENSAVER_LINK(NAME) +#else +# define XSCREENSAVER_LINK(NAME) \ + struct xscreensaver_function_table *xscreensaver_function_table = &NAME; +#endif + + +# if !defined(USE_GL) || defined(HAVE_COCOA) +# define xlockmore_pick_gl_visual 0 +# define xlockmore_validate_gl_visual 0 +# endif /* !USE_GL || HAVE_COCOA */ + +# ifdef USE_GL +# define XLOCKMORE_FPS xlockmore_gl_compute_fps +# else +# define XLOCKMORE_FPS xlockmore_do_fps +# endif + +#ifdef WRITABLE_COLORS +# undef WRITABLE_COLORS +# define WRITABLE_COLORS 1 +#else +# define WRITABLE_COLORS 0 +#endif + +#if defined(UNIFORM_COLORS) +# define XLOCKMORE_COLOR_SCHEME color_scheme_uniform +#elif defined(SMOOTH_COLORS) +# define XLOCKMORE_COLOR_SCHEME color_scheme_smooth +#elif defined(BRIGHT_COLORS) +# define XLOCKMORE_COLOR_SCHEME color_scheme_bright +#else +# define XLOCKMORE_COLOR_SCHEME color_scheme_default +#endif + +/* This is the macro that links this program in with the rest of + xscreensaver. For example: + + XSCREENSAVER_MODULE ("Atlantis", atlantis) + XSCREENSAVER_MODULE_2 ("GLMatrix", glmatrix, matrix) + + CLASS: a string, the class name for resources. + NAME: a token, the name of the executable. Should be the same + as CLASS, but downcased. + PREFIX: the symbol used in the function names, e.g., `draw_atlantis'. + + NAME and PREFIX are usually the same. If they are not, use + XSCREENSAVER_MODULE_2() instead of XSCREENSAVER_MODULE(). + */ +#define XSCREENSAVER_MODULE_2(CLASS,NAME,PREFIX) \ + \ + static struct xlockmore_function_table \ + NAME ## _xlockmore_function_table = { \ + CLASS, \ + DEFAULTS, \ + WRITABLE_COLORS, \ + XLOCKMORE_COLOR_SCHEME, \ + init_ ## PREFIX, \ + draw_ ## PREFIX, \ + reshape_ ## PREFIX, \ + refresh_ ## PREFIX, \ + release_ ## PREFIX, \ + PREFIX ## _handle_event, \ + & PREFIX ## _opts \ + }; \ + \ + struct xscreensaver_function_table \ + NAME ## _xscreensaver_function_table = { \ + 0, 0, 0, \ + xlockmore_setup, \ + & NAME ## _xlockmore_function_table, \ + 0, 0, 0, 0, 0, \ + XLOCKMORE_FPS, \ + xlockmore_pick_gl_visual, \ + xlockmore_validate_gl_visual }; \ + \ + XSCREENSAVER_LINK (NAME ## _xscreensaver_function_table) + +#define XSCREENSAVER_MODULE(CLASS,PREFIX) \ + XSCREENSAVER_MODULE_2(CLASS,PREFIX,PREFIX) diff --git a/hacks/xlockmoreI.h b/hacks/xlockmoreI.h new file mode 100644 index 00000000..ecf93094 --- /dev/null +++ b/hacks/xlockmoreI.h @@ -0,0 +1,170 @@ +/* xlockmore.h --- xscreensaver compatibility layer for xlockmore modules. + * xscreensaver, Copyright (c) 1997-2012 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. + * + * See xlockmore.h and xlockmore.c. + */ + +#ifndef __XLOCKMORE_INTERNAL_H__ +#define __XLOCKMORE_INTERNAL_H__ + +#include + +#include "screenhackI.h" + +#ifdef HAVE_XSHM_EXTENSION +# include "xshm.h" +#endif /* HAVE_XSHM_EXTENSION */ + + +typedef struct ModeInfo ModeInfo; + +#ifdef USE_GL + +/* I'm told that the Sun version of OpenGL needs to have the constant + SUN_OGL_NO_VERTEX_MACROS defined in order for morph3d to compile + (the number of arguments to the glNormal3f macro changes...) + Verified with gcc 2.7.2.2 and Sun cc 4.2 with OpenGL 1.1.1 dev 4 + on Solaris 2.5.1. + */ +# ifndef HAVE_MESA_GL +# if defined(__sun) && defined(__SVR4) /* Solaris */ +# define SUN_OGL_NO_VERTEX_MACROS 1 +# endif /* Solaris */ +# endif /* !HAVE_MESA_GL */ + +# ifdef HAVE_COCOA +# ifndef USE_IPHONE +# include +# include +# endif +# else +# include +# include +# include +# endif + +# ifdef HAVE_JWZGLES +# include "jwzgles.h" +# endif /* HAVE_JWZGLES */ + + + extern GLXContext *init_GL (ModeInfo *); + extern void xlockmore_reset_gl_state(void); + extern void clear_gl_error (void); + extern void check_gl_error (const char *type); + + extern Visual *xlockmore_pick_gl_visual (Screen *); + extern Bool xlockmore_validate_gl_visual (Screen *, const char *, Visual *); + +#endif /* !USE_GL */ + +/* These are only used in GL mode, but I don't understand why XCode + isn't seeing the prototypes for them in glx/fps-gl.c... */ +extern void do_fps (ModeInfo *); +extern void xlockmore_gl_compute_fps (Display *, Window, fps_state *, void *); +extern void xlockmore_gl_draw_fps (ModeInfo *); +# define do_fps xlockmore_gl_draw_fps + + +extern void xlockmore_setup (struct xscreensaver_function_table *, void *); +extern void xlockmore_do_fps (Display *, Window, fps_state *, void *); + + +/* Compatibility with the xlockmore RNG API + (note that the xlockmore hacks never expect negative numbers.) + */ +#define LRAND() ((long) (random() & 0x7fffffff)) +#define NRAND(n) ((int) (LRAND() % (n))) +#define MAXRAND (2147483648.0) /* unsigned 1<<31 as a float */ +#define SRAND(n) /* already seeded by screenhack.c */ + + +struct ModeInfo { + struct xlockmore_function_table *xlmft; + Display *dpy; + Window window; + Bool root_p; + int num_screens; + int screen_number; + int npixels; + unsigned long *pixels; + XColor *colors; + Bool writable_p; + unsigned long white; + unsigned long black; + XWindowAttributes xgwa; + GC gc; + long pause; + Bool fullrandom; + long cycles; + long batchcount; + long size; + Bool threed; + long threed_left_color; + long threed_right_color; + long threed_both_color; + long threed_none_color; + long threed_delta; + Bool wireframe_p; + Bool is_drawn; + + /* Used only by OpenGL programs, since FPS is tricky there. */ + fps_state *fpst; + Bool fps_p; + unsigned long polygon_count; /* These values are for -fps display only */ + double recursion_depth; + +#ifdef HAVE_XSHM_EXTENSION + Bool use_shm; + XShmSegmentInfo shm_info; +#endif +}; + +typedef enum { t_String, t_Float, t_Int, t_Bool } xlockmore_type; + +typedef struct { + void *var; + char *name; + char *classname; + char *def; + xlockmore_type type; +} argtype; + +typedef struct { + char *opt; + char *desc; +} OptionStruct; + +typedef struct { + int numopts; + XrmOptionDescRec *opts; + int numvarsdesc; + argtype *vars; + OptionStruct *desc; +} ModeSpecOpt; + +struct xlockmore_function_table { + const char *progclass; + const char *defaults; + Bool want_writable_colors; + enum { color_scheme_default, color_scheme_uniform, + color_scheme_smooth, color_scheme_bright } + desired_color_scheme; + void (*hack_init) (ModeInfo *); + void (*hack_draw) (ModeInfo *); + void (*hack_reshape) (ModeInfo *, int, int); + void (*hack_refresh) (ModeInfo *); + void (*hack_free) (ModeInfo *); + Bool (*hack_handle_events) (ModeInfo *, XEvent *); + ModeSpecOpt *opts; +}; + +#endif /* __XLOCKMORE_INTERNAL_H__ */ diff --git a/hacks/xlyap.c b/hacks/xlyap.c new file mode 100644 index 00000000..02587f00 --- /dev/null +++ b/hacks/xlyap.c @@ -0,0 +1,1918 @@ +/* Lyap - calculate and display Lyapunov exponents */ + +/* Written by Ron Record (rr@sco) 03 Sep 1991 */ + +/* The idea here is to calculate the Lyapunov exponent for a periodically + * forced logistic map (later i added several other nonlinear maps of the unit + * interval). In order to turn the 1-dimensional parameter space of the + * logistic map into a 2-dimensional parameter space, select two parameter + * values ('a' and 'b') then alternate the iterations of the logistic map using + * first 'a' then 'b' as the parameter. This program accepts an argument to + * specify a forcing function, so instead of just alternating 'a' and 'b', you + * can use 'a' as the parameter for say 6 iterations, then 'b' for 6 iterations + * and so on. An interesting forcing function to look at is abbabaab (the + * Morse-Thue sequence, an aperiodic self-similar, self-generating sequence). + * Anyway, step through all the values of 'a' and 'b' in the ranges you want, + * calculating the Lyapunov exponent for each pair of values. The exponent + * is calculated by iterating out a ways (specified by the variable "settle") + * then on subsequent iterations calculating an average of the logarithm of + * the absolute value of the derivative at that point. Points in parameter + * space with a negative Lyapunov exponent are colored one way (using the + * value of the exponent to index into a color map) while points with a + * non-negative exponent are colored differently. + * + * The algorithm was taken from the September 1991 Scientific American article + * by A. K. Dewdney who gives credit to Mario Markus of the Max Planck + * Institute for its creation. Additional information and ideas were gleaned + * from the discussion on alt.fractals involving Stephen Hall, Ed Kubaitis, + * Dave Platt and Baback Moghaddam. Assistance with colormaps and spinning + * color wheels and X was gleaned from Hiram Clawson. Rubber banding code was + * adapted from an existing Mandelbrot program written by Stacey Campbell. + */ + +#define LYAP_PATCHLEVEL 4 +#define LYAP_VERSION "#(@) lyap 2.3 2/20/92" + +#include +#include + +#include "screenhack.h" +#include "yarandom.h" +#include "hsv.h" + +#undef countof +#define countof(x) (sizeof((x))/sizeof((*x))) + +#ifndef HAVE_COCOA +# include +#endif + +static const char *xlyap_defaults [] = { + ".background: black", + ".foreground: white", + "*fpsSolid: true", + "*randomize: true", + "*builtin: -1", + "*minColor: 1", + "*maxColor: 256", + "*dwell: 50", + "*useLog: false", + "*colorExponent: 1.0", + "*colorOffset: 0", + "*randomForce: ", /* 0.5 */ + "*settle: 50", + "*minA: 2.0", + "*minB: 2.0", + "*wheels: 7", + "*function: 10101010", + "*forcingFunction: abbabaab", + "*bRange: ", /* 2.0 */ + "*startX: 0.65", + "*mapIndex: ", /* 0 */ + "*outputFile: ", + "*beNegative: false", + "*rgbMax: 65000", + "*spinLength: 256", + "*show: false", + "*aRange: ", /* 2.0 */ + "*delay: 10000", + "*linger: 5", + "*colors: 200", + 0 +}; + +static XrmOptionDescRec xlyap_options [] = { + { "-randomize", ".randomize", XrmoptionNoArg, "true" }, + { "-builtin", ".builtin", XrmoptionSepArg, 0 }, + { "-C", ".minColor", XrmoptionSepArg, 0 }, /* n */ + { "-D", ".dwell", XrmoptionSepArg, 0 }, /* n */ + { "-L", ".useLog", XrmoptionNoArg, "true" }, + { "-M", ".colorExponent", XrmoptionSepArg, 0 }, /* r */ + { "-O", ".colorOffset", XrmoptionSepArg, 0 }, /* n */ + { "-R", ".randomForce", XrmoptionSepArg, 0 }, /* p */ + { "-S", ".settle", XrmoptionSepArg, 0 }, /* n */ + { "-a", ".minA", XrmoptionSepArg, 0 }, /* r */ + { "-b", ".minB", XrmoptionSepArg, 0 }, /* n */ + { "-c", ".wheels", XrmoptionSepArg, 0 }, /* n */ + { "-F", ".function", XrmoptionSepArg, 0 }, /* 10101010 */ + { "-f", ".forcingFunction", XrmoptionSepArg, 0 }, /* abbabaab */ + { "-h", ".bRange", XrmoptionSepArg, 0 }, /* r */ + { "-i", ".startX", XrmoptionSepArg, 0 }, /* r */ + { "-m", ".mapIndex", XrmoptionSepArg, 0 }, /* n */ + { "-o", ".outputFile", XrmoptionSepArg, 0 }, /* filename */ + { "-p", ".beNegative", XrmoptionNoArg, "true" }, + { "-r", ".rgbMax", XrmoptionSepArg, 0 }, /* n */ + { "-s", ".spinLength", XrmoptionSepArg, 0 }, /* n */ + { "-v", ".show", XrmoptionNoArg, "true" }, + { "-w", ".aRange", XrmoptionSepArg, 0 }, /* r */ + { "-delay", ".delay", XrmoptionSepArg, 0 }, /* delay */ + { "-linger", ".linger", XrmoptionSepArg, 0 }, /* linger */ + { 0, 0, 0, 0 } +}; + + +#define ABS(a) (((a)<0) ? (0-(a)) : (a) ) +#define Min(x,y) ((x < y)?x:y) +#define Max(x,y) ((x > y)?x:y) + +#ifdef SIXTEEN_COLORS +# define MAXPOINTS 128 +# ifdef BIGMEM +# define MAXFRAMES 4 +# else /* !BIGMEM */ +# define MAXFRAMES 2 +# endif /* !BIGMEM */ +# define MAXCOLOR 16 +#else /* !SIXTEEN_COLORS */ +# define MAXPOINTS 256 +# ifdef BIGMEM +# define MAXFRAMES 8 +# else /* !BIGMEM */ +# define MAXFRAMES 2 +# endif /* !BIGMEM */ +# define MAXCOLOR 256 +#endif /* !SIXTEEN_COLORS */ + + +#define MAXINDEX 64 +#define FUNCMAXINDEX 16 +#define MAXWHEELS 7 +#define NUMMAPS 5 +#define NBUILTINS 22 + +#ifndef TRUE +# define TRUE 1 +# define FALSE 0 +#endif + + +typedef struct { + int x, y; +} xy_t; + +#if 0 +typedef struct { + int start_x, start_y; + int last_x, last_y; +} rubber_band_data_t; +#endif + +typedef struct { +# ifndef HAVE_COCOA + Cursor band_cursor; +# endif + double p_min, p_max, q_min, q_max; +/* rubber_band_data_t rubber_band;*/ +} image_data_t; + +typedef struct points_t { + XPoint data[MAXCOLOR][MAXPOINTS]; + int npoints[MAXCOLOR]; +} points_t; + + +typedef double (*PFD)(double,double); + +/* #### What was this for? Everything was drawn twice, to the window and + to this, and this was never displayed! */ +/*#define BACKING_PIXMAP*/ + +struct state { + int screen; + Display *dpy; + Visual *visual; + Colormap cmap; + + unsigned long foreground, background; + + Window canvas; + int delay, linger; + + unsigned int maxcolor, startcolor, mincolindex; + int color_offset; + int dwell, settle; + int width, height, xposition, yposition; + + points_t Points; +/* image_data_t rubber_data;*/ + + GC Data_GC[MAXCOLOR]/*, RubberGC*/; + PFD map, deriv; + + int aflag, bflag, wflag, hflag, Rflag; + + int maxindex; + int funcmaxindex; + double min_a, min_b, a_range, b_range, minlyap; + double max_a, max_b; + double start_x, lyapunov, a_inc, b_inc, a, b; + int numcolors, numfreecols, lowrange; + xy_t point; +#ifdef BACKING_PIXMAP + Pixmap pixmap; +#endif +/* XColor Colors[MAXCOLOR];*/ + double *exponents[MAXFRAMES]; + double a_minimums[MAXFRAMES], b_minimums[MAXFRAMES]; + double a_maximums[MAXFRAMES], b_maximums[MAXFRAMES]; + double minexp, maxexp, prob; + int expind[MAXFRAMES], resized[MAXFRAMES]; + int numwheels, force, Force, negative; + int rgb_max, nostart, stripe_interval; + int save, show, useprod, spinlength; + int maxframe, frame, dorecalc, mapindex, run; + char *outname; + + int sendpoint_index; + + int forcing[MAXINDEX]; + int Forcing[FUNCMAXINDEX]; + + int reset_countdown; + + int ncolors; + XColor colors[MAXCOLOR]; +}; + + +static const double pmins[NUMMAPS] = { 2.0, 0.0, 0.0, 0.0, 0.0 }; +static const double pmaxs[NUMMAPS] = { 4.0, 1.0, 6.75, 6.75, 16.0 }; +static const double amins[NUMMAPS] = { 2.0, 0.0, 0.0, 0.0, 0.0 }; +static const double aranges[NUMMAPS] = { 2.0, 1.0, 6.75, 6.75, 16.0 }; +static const double bmins[NUMMAPS] = { 2.0, 0.0, 0.0, 0.0, 0.0 }; +static const double branges[NUMMAPS] = { 2.0, 1.0, 6.75, 6.75, 16.0 }; + +/****************************************************************************/ + +/* callback function declarations + */ + +static double logistic(double,double); +static double circle(double,double); +static double leftlog(double,double); +static double rightlog(double,double); +static double doublelog(double,double); +static double dlogistic(double,double); +static double dcircle(double,double); +static double dleftlog(double,double); +static double drightlog(double,double); +static double ddoublelog(double,double); + +static const PFD Maps[NUMMAPS] = { logistic, circle, leftlog, rightlog, + doublelog }; +static const PFD Derivs[NUMMAPS] = { dlogistic, dcircle, dleftlog, + drightlog, ddoublelog }; + + +/****************************************************************************/ + +/* other function declarations + */ + +static void resize(struct state *); +/*static void Spin(struct state *);*/ +static void show_defaults(struct state *); +/*static void StartRubberBand(struct state *, image_data_t *, XEvent *); +static void TrackRubberBand(struct state *, image_data_t *, XEvent *); +static void EndRubberBand(struct state *, image_data_t *, XEvent *);*/ +/*static void CreateXorGC(struct state *);*/ +static void InitBuffer(struct state *); +static void BufferPoint(struct state *, int color, int x, int y); +static void FlushBuffer(struct state *); +static void init_data(struct state *); +static void init_color(struct state *); +static void parseargs(struct state *); +static void Clear(struct state *); +static void setupmem(struct state *); +static int complyap(struct state *); +static Bool Getkey(struct state *, XKeyEvent *); +static int sendpoint(struct state *, double expo); +/*static void save_to_file(struct state *);*/ +static void setforcing(struct state *); +static void check_params(struct state *, int mapnum, int parnum); +static void usage(struct state *); +static void Destroy_frame(struct state *); +static void freemem(struct state *); +static void Redraw(struct state *); +static void redraw(struct state *, double *exparray, int index, int cont); +static void recalc(struct state *); +/*static void SetupCorners(XPoint *, image_data_t *); +static void set_new_params(struct state *, image_data_t *);*/ +static void go_down(struct state *); +static void go_back(struct state *); +static void go_init(struct state *); +static void jumpwin(struct state *); +static void print_help(struct state *); +static void print_values(struct state *); + + +/****************************************************************************/ + + +/* complyap() is the guts of the program. This is where the Lyapunov exponent + * is calculated. For each iteration (past some large number of iterations) + * calculate the logarithm of the absolute value of the derivative at that + * point. Then average them over some large number of iterations. Some small + * speed up is achieved by utilizing the fact that log(a*b) = log(a) + log(b). + */ +static int +complyap(struct state *st) +{ + int i, bindex; + double total, prod, x, dx, r; + + if (st->maxcolor > MAXCOLOR) + abort(); + + if (!st->run) + return TRUE; + st->a += st->a_inc; + if (st->a >= st->max_a) { + if (sendpoint(st, st->lyapunov) == TRUE) + return FALSE; + else { + FlushBuffer(st); + /* if (savefile) + save_to_file(); */ + return TRUE; + } + } + if (st->b >= st->max_b) { + FlushBuffer(st); + /* if (savefile) + save_to_file();*/ + return TRUE; + } + prod = 1.0; + total = 0.0; + bindex = 0; + x = st->start_x; + r = (st->forcing[bindex]) ? st->b : st->a; +#ifdef MAPS + findex = 0; + map = Maps[st->Forcing[findex]]; +#endif + for (i=0;isettle;i++) { /* Here's where we let the thing */ + x = st->map (x, r); /* "settle down". There is usually */ + if (++bindex >= st->maxindex) { /* some initial "noise" in the */ + bindex = 0; /* iterations. How can we optimize */ + if (st->Rflag) /* the value of settle ??? */ + setforcing(st); + } + r = (st->forcing[bindex]) ? st->b : st->a; +#ifdef MAPS + if (++findex >= funcmaxindex) + findex = 0; + map = Maps[st->Forcing[findex]]; +#endif + } +#ifdef MAPS + deriv = Derivs[st->Forcing[findex]]; +#endif + if (st->useprod) { /* using log(a*b) */ + for (i=0;idwell;i++) { + x = st->map (x, r); + dx = st->deriv (x, r); /* ABS is a macro, so don't be fancy */ + dx = ABS(dx); + if (dx == 0.0) /* log(0) is nasty so break out. */ + { + i++; + break; + } + prod *= dx; + /* we need to prevent overflow and underflow */ + if ((prod > 1.0e12) || (prod < 1.0e-12)) { + total += log(prod); + prod = 1.0; + } + if (++bindex >= st->maxindex) { + bindex = 0; + if (st->Rflag) + setforcing(st); + } + r = (st->forcing[bindex]) ? st->b : st->a; +#ifdef MAPS + if (++findex >= funcmaxindex) + findex = 0; + map = Maps[st->Forcing[findex]]; + deriv = Derivs[st->Forcing[findex]]; +#endif + } + total += log(prod); + st->lyapunov = (total * M_LOG2E) / (double)i; + } + else { /* use log(a) + log(b) */ + for (i=0;idwell;i++) { + x = st->map (x, r); + dx = st->deriv (x, r); /* ABS is a macro, so don't be fancy */ + dx = ABS(dx); + if (x == 0.0) /* log(0) check */ + { + i++; + break; + } + total += log(dx); + if (++bindex >= st->maxindex) { + bindex = 0; + if (st->Rflag) + setforcing(st); + } + r = (st->forcing[bindex]) ? st->b : st->a; +#ifdef MAPS + if (++findex >= funcmaxindex) + findex = 0; + map = Maps[st->Forcing[findex]]; + deriv = Derivs[st->Forcing[findex]]; +#endif + } + st->lyapunov = (total * M_LOG2E) / (double)i; + } + + if (sendpoint(st, st->lyapunov) == TRUE) + return FALSE; + else { + FlushBuffer(st); + /* if (savefile) + save_to_file();*/ + return TRUE; + } +} + +static double +logistic(double x, double r) /* the familiar logistic map */ +{ + return(r * x * (1.0 - x)); +} + +static double +dlogistic(double x, double r) /* the derivative of logistic map */ +{ + return(r - (2.0 * r * x)); +} + +static double +circle(double x, double r) /* sin() hump or sorta like the circle map */ +{ + return(r * sin(M_PI * x)); +} + +static double +dcircle(double x, double r) /* derivative of the "sin() hump" */ +{ + return(r * M_PI * cos(M_PI * x)); +} + +static double +leftlog(double x, double r) /* left skewed logistic */ +{ + double d; + + d = 1.0 - x; + return(r * x * d * d); +} + +static double +dleftlog(double x, double r) /* derivative of the left skewed logistic */ +{ + return(r * (1.0 - (4.0 * x) + (3.0 * x * x))); +} + +static double +rightlog(double x, double r) /* right skewed logistic */ +{ + return(r * x * x * (1.0 - x)); +} + +static double +drightlog(double x, double r) /* derivative of the right skewed logistic */ +{ + return(r * ((2.0 * x) - (3.0 * x * x))); +} + +static double +doublelog(double x, double r) /* double logistic */ +{ + double d; + + d = 1.0 - x; + return(r * x * x * d * d); +} + +static double +ddoublelog(double x, double r) /* derivative of the double logistic */ +{ + double d; + + d = x * x; + return(r * ((2.0 * x) - (6.0 * d) + (4.0 * x * d))); +} + +static void +init_data(struct state *st) +{ + st->numcolors = get_integer_resource (st->dpy, "colors", "Integer"); + if (st->numcolors < 2) + st->numcolors = 2; + if (st->numcolors > st->maxcolor) + st->numcolors = st->maxcolor; + st->numfreecols = st->numcolors - st->mincolindex; + st->lowrange = st->mincolindex - st->startcolor; + st->a_inc = st->a_range / (double)st->width; + st->b_inc = st->b_range / (double)st->height; + st->point.x = -1; + st->point.y = 0; + st->a = /*st->rubber_data.p_min = */st->min_a; + st->b = /*st->rubber_data.q_min = */st->min_b; +/* st->rubber_data.p_max = st->max_a; + st->rubber_data.q_max = st->max_b;*/ + if (st->show) + show_defaults(st); + InitBuffer(st); +} + +#if 0 +static void +hls2rgb(int hue_light_sat[3], + int rgb[3]) /* Each in range [0..65535] */ +{ + unsigned short r, g, b; + hsv_to_rgb((int) (hue_light_sat[0] / 10), /* 0-3600 -> 0-360 */ + (int) ((hue_light_sat[2]/1000.0) * 64435), /* 0-1000 -> 0-65535 */ + (int) ((hue_light_sat[1]/1000.0) * 64435), /* 0-1000 -> 0-65535 */ + &r, &g, &b); + rgb[0] = r; + rgb[1] = g; + rgb[2] = b; +} +#endif /* 0 */ + + +static void +init_color(struct state *st) +{ + int i; + if (st->ncolors) + free_colors (st->dpy, st->cmap, st->colors, st->ncolors); + st->ncolors = st->maxcolor; + make_smooth_colormap(st->dpy, st->visual, st->cmap, + st->colors, &st->ncolors, True, NULL, True); + + for (i = 0; i < st->maxcolor; i++) { + if (! st->Data_GC[i]) { + XGCValues gcv; + gcv.background = BlackPixel(st->dpy, st->screen); + st->Data_GC[i] = XCreateGC(st->dpy, st->canvas, GCBackground, &gcv); + } + XSetForeground(st->dpy, st->Data_GC[i], + st->colors[((int) ((i / ((float)st->maxcolor)) * + st->ncolors))].pixel); + } +} + + +static void +parseargs(struct state *st) +{ + int i; + int bindex=0, findex; + char *s, *ch; + + st->map = Maps[0]; + st->deriv = Derivs[0]; + st->maxexp=st->minlyap; st->minexp= -1.0 * st->minlyap; + + st->mincolindex = get_integer_resource(st->dpy, "minColor", "Integer"); + st->dwell = get_integer_resource(st->dpy, "dwell", "Integer"); +#ifdef MAPS + { + char *optarg = get_string_resource(st->dpy, "function", "String"); + funcmaxindex = strlen(optarg); + if (funcmaxindex > FUNCMAXINDEX) + usage(); + ch = optarg; + st->Force++; + for (findex=0;findexForcing[findex] = (int)(*ch++ - '0');; + if (st->Forcing[findex] >= NUMMAPS) + usage(); + } + } +#endif + if (get_boolean_resource(st->dpy, "useLog", "Boolean")) + st->useprod=0; + + st->minlyap=ABS(get_float_resource(st->dpy, "colorExponent", "Float")); + st->maxexp=st->minlyap; + st->minexp= -1.0 * st->minlyap; + + st->color_offset = get_integer_resource(st->dpy, "colorOffset", "Integer"); + + st->maxcolor=ABS(get_integer_resource(st->dpy, "maxColor", "Integer")); + if ((st->maxcolor - st->startcolor) <= 0) + st->startcolor = get_pixel_resource(st->dpy, st->cmap, + "background", "Background"); + if ((st->maxcolor - st->mincolindex) <= 0) { + st->mincolindex = 1; + st->color_offset = 0; + } + + s = get_string_resource(st->dpy, "randomForce", "Float"); + if (s && *s) { + st->prob=atof(s); st->Rflag++; setforcing(st); + } + + st->settle = get_integer_resource(st->dpy, "settle", "Integer"); + +#if 0 + s = get_string_resource(st->dpy, "minA", "Float"); + if (s && *s) { + st->min_a = atof(s); + st->aflag++; + } + + s = get_string_resource(st->dpy, "minB", "Float"); + if (s && *s) { + st->min_b=atof(s); st->bflag++; + } +#else + st->min_a = get_float_resource (st->dpy, "minA", "Float"); + st->aflag++; + st->min_b = get_float_resource (st->dpy, "minB", "Float"); + st->bflag++; +#endif + + + st->numwheels = get_integer_resource(st->dpy, "wheels", "Integer"); + + s = get_string_resource(st->dpy, "forcingFunction", "String"); + if (s && *s) { + st->maxindex = strlen(s); + if (st->maxindex > MAXINDEX) + usage(st); + ch = s; + st->force++; + while (bindex < st->maxindex) { + if (*ch == 'a') + st->forcing[bindex++] = 0; + else if (*ch == 'b') + st->forcing[bindex++] = 1; + else + usage(st); + ch++; + } + } + + s = get_string_resource(st->dpy, "bRange", "Float"); + if (s && *s) { + st->b_range = atof(s); + st->hflag++; + } + + st->start_x = get_float_resource(st->dpy, "startX", "Float"); + + s = get_string_resource(st->dpy, "mapIndex", "Integer"); + if (s && *s) { + st->mapindex=atoi(s); + if ((st->mapindex >= NUMMAPS) || (st->mapindex < 0)) + usage(st); + st->map = Maps[st->mapindex]; + st->deriv = Derivs[st->mapindex]; + if (!st->aflag) + st->min_a = amins[st->mapindex]; + if (!st->wflag) + st->a_range = aranges[st->mapindex]; + if (!st->bflag) + st->min_b = bmins[st->mapindex]; + if (!st->hflag) + st->b_range = branges[st->mapindex]; + if (!st->Force) + for (i=0;iForcing[i] = st->mapindex; + } + + st->outname = get_string_resource(st->dpy, "outputFile", "Integer"); + + if (get_boolean_resource(st->dpy, "beNegative", "Boolean")) + st->negative--; + + st->rgb_max = get_integer_resource(st->dpy, "rgbMax", "Integer"); + st->spinlength = get_integer_resource(st->dpy, "spinLength", "Integer"); + st->show = get_boolean_resource(st->dpy, "show", "Boolean"); + + s = get_string_resource(st->dpy, "aRange", "Float"); + if (s && *s) { + st->a_range = atof(s); st->wflag++; + } + + st->max_a = st->min_a + st->a_range; + st->max_b = st->min_b + st->b_range; + + st->a_minimums[0] = st->min_a; st->b_minimums[0] = st->min_b; + st->a_maximums[0] = st->max_a; st->b_maximums[0] = st->max_b; + + if (st->Force) + if (st->maxindex == st->funcmaxindex) + for (findex=0;findexfuncmaxindex;findex++) + check_params(st, st->Forcing[findex],st->forcing[findex]); + else + fprintf(stderr, "Warning! Unable to check parameters\n"); + else + check_params(st, st->mapindex,2); +} + +static void +check_params(struct state *st, int mapnum, int parnum) +{ + + if (parnum != 1) { + if ((st->max_a > pmaxs[mapnum]) || (st->min_a < pmins[mapnum])) { + fprintf(stderr, "Warning! Parameter 'a' out of range.\n"); + fprintf(stderr, "You have requested a range of (%f,%f).\n", + st->min_a,st->max_a); + fprintf(stderr, "Valid range is (%f,%f).\n", + pmins[mapnum],pmaxs[mapnum]); + } + } + if (parnum != 0) { + if ((st->max_b > pmaxs[mapnum]) || (st->min_b < pmins[mapnum])) { + fprintf(stderr, "Warning! Parameter 'b' out of range.\n"); + fprintf(stderr, "You have requested a range of (%f,%f).\n", + st->min_b,st->max_b); + fprintf(stderr, "Valid range is (%f,%f).\n", + pmins[mapnum],pmaxs[mapnum]); + } + } +} + +static void +usage(struct state *st) +{ + fprintf(stderr,"lyap [-BLs][-W#][-H#][-a#][-b#][-w#][-h#][-x xstart]\n"); + fprintf(stderr,"\t[-M#][-S#][-D#][-f string][-r#][-O#][-C#][-c#][-m#]\n"); +#ifdef MAPS + fprintf(stderr,"\t[-F string]\n"); +#endif + fprintf(stderr,"\tWhere: -C# specifies the minimum color index\n"); + fprintf(stderr,"\t -r# specifies the maxzimum rgb value\n"); + fprintf(stderr,"\t -u displays this message\n"); + fprintf(stderr,"\t -a# specifies the minimum horizontal parameter\n"); + fprintf(stderr,"\t -b# specifies the minimum vertical parameter\n"); + fprintf(stderr,"\t -w# specifies the horizontal parameter range\n"); + fprintf(stderr,"\t -h# specifies the vertical parameter range\n"); + fprintf(stderr,"\t -D# specifies the dwell\n"); + fprintf(stderr,"\t -S# specifies the settle\n"); + fprintf(stderr,"\t -H# specifies the initial window height\n"); + fprintf(stderr,"\t -W# specifies the initial window width\n"); + fprintf(stderr,"\t -O# specifies the color offset\n"); + fprintf(stderr,"\t -c# specifies the desired color wheel\n"); + fprintf(stderr,"\t -m# specifies the desired map (0-4)\n"); + fprintf(stderr,"\t -f aabbb specifies a forcing function of 00111\n"); +#ifdef MAPS + fprintf(stderr,"\t -F 00111 specifies the function forcing function\n"); +#endif + fprintf(stderr,"\t -L indicates use log(x)+log(y) rather than log(xy)\n"); + fprintf(stderr,"\tDuring display :\n"); + fprintf(stderr,"\t Use the mouse to zoom in on an area\n"); + fprintf(stderr,"\t e or E recalculates color indices\n"); + fprintf(stderr,"\t f or F saves exponents to a file\n"); + fprintf(stderr,"\t KJmn increase/decrease minimum negative exponent\n"); + fprintf(stderr,"\t r or R redraws\n"); + fprintf(stderr,"\t s or S spins the colorwheel\n"); + fprintf(stderr,"\t w or W changes the color wheel\n"); + fprintf(stderr,"\t x or X clears the window\n"); + fprintf(stderr,"\t q or Q exits\n"); + exit(1); +} + +static void +Cycle_frames(struct state *st) +{ + int i; + for (i=0;i<=st->maxframe;i++) + redraw(st, st->exponents[i], st->expind[i], 1); +} + +#if 0 +static void +Spin(struct state *st) +{ + int i, j; + long tmpxcolor; + + if (!mono_p) { + for (j=0;jspinlength;j++) { + tmpxcolor = st->Colors[st->mincolindex].pixel; + for (i=st->mincolindex;inumcolors-1;i++) + st->Colors[i].pixel = st->Colors[i+1].pixel; + st->Colors[st->numcolors-1].pixel = tmpxcolor; + XStoreColors(st->dpy, st->cmap, st->Colors, st->numcolors); + } + for (j=0;jspinlength;j++) { + tmpxcolor = st->Colors[st->numcolors-1].pixel; + for (i=st->numcolors-1;i>st->mincolindex;i--) + st->Colors[i].pixel = st->Colors[i-1].pixel; + st->Colors[st->mincolindex].pixel = tmpxcolor; + XStoreColors(st->dpy, st->cmap, st->Colors, st->numcolors); + } + } +} +#endif + +static Bool +Getkey(struct state *st, XKeyEvent *event) +{ + unsigned char key; + int i; + if (XLookupString(event, (char *)&key, sizeof(key), (KeySym *)0, + (XComposeStatus *) 0) > 0) + + if (st->reset_countdown) + st->reset_countdown = st->linger; + + switch (key) { + case '<': st->dwell /= 2; if (st->dwell < 1) st->dwell = 1; return True; + case '>': st->dwell *= 2; return True; + case '[': st->settle /= 2; if (st->settle < 1) st->settle = 1; return True; + case ']': st->settle *= 2; return True; + case 'd': go_down(st); return True; + case 'D': FlushBuffer(st); return True; + case 'e': + case 'E': FlushBuffer(st); + st->dorecalc = (!st->dorecalc); + if (st->dorecalc) + recalc(st); + else { + st->maxexp = st->minlyap; st->minexp = -1.0 * st->minlyap; + } + redraw(st, st->exponents[st->frame], st->expind[st->frame], 1); + return True; + case 'f': + /* case 'F': save_to_file(); return True;*/ + case 'i': if (st->stripe_interval > 0) { + st->stripe_interval--; + if (!mono_p) { + init_color(st); + } + } + return True; + case 'I': st->stripe_interval++; + if (!mono_p) { + init_color(st); + } + return True; + case 'K': if (st->minlyap > 0.05) + st->minlyap -= 0.05; + return True; + case 'J': st->minlyap += 0.05; + return True; + case 'm': st->mapindex++; + if (st->mapindex >= NUMMAPS) + st->mapindex=0; + st->map = Maps[st->mapindex]; + st->deriv = Derivs[st->mapindex]; + if (!st->aflag) + st->min_a = amins[st->mapindex]; + if (!st->wflag) + st->a_range = aranges[st->mapindex]; + if (!st->bflag) + st->min_b = bmins[st->mapindex]; + if (!st->hflag) + st->b_range = branges[st->mapindex]; + if (!st->Force) + for (i=0;iForcing[i] = st->mapindex; + st->max_a = st->min_a + st->a_range; + st->max_b = st->min_b + st->b_range; + st->a_minimums[0] = st->min_a; st->b_minimums[0] = st->min_b; + st->a_maximums[0] = st->max_a; st->b_maximums[0] = st->max_b; + st->a_inc = st->a_range / (double)st->width; + st->b_inc = st->b_range / (double)st->height; + st->point.x = -1; + st->point.y = 0; + st->a = /*st->rubber_data.p_min = */st->min_a; + st->b = /*st->rubber_data.q_min = */st->min_b; +/* st->rubber_data.p_max = st->max_a; + st->rubber_data.q_max = st->max_b;*/ + Clear(st); + return True; + case 'M': if (st->minlyap > 0.005) + st->minlyap -= 0.005; + return True; + case 'N': st->minlyap += 0.005; + return True; + case 'p': + case 'P': st->negative = (!st->negative); + FlushBuffer(st); redraw(st, st->exponents[st->frame], + st->expind[st->frame], 1); + return True; + case 'r': FlushBuffer(st); redraw(st, st->exponents[st->frame], + st->expind[st->frame], 1); + return True; + case 'R': FlushBuffer(st); Redraw(st); return True; + case 's': + st->spinlength=st->spinlength/2; +#if 0 + case 'S': if (!mono_p) + Spin(st); + st->spinlength=st->spinlength*2; return True; +#endif + case 'u': go_back(st); return True; + case 'U': go_init(st); return True; + case 'v': + case 'V': print_values(st); return True; + case 'W': if (st->numwheels < MAXWHEELS) + st->numwheels++; + else + st->numwheels = 0; + if (!mono_p) { + init_color(st); + } + return True; + case 'w': if (st->numwheels > 0) + st->numwheels--; + else + st->numwheels = MAXWHEELS; + if (!mono_p) { + init_color(st); + } + return True; + case 'x': Clear(st); return True; + case 'X': Destroy_frame(st); return True; + case 'z': Cycle_frames(st); redraw(st, st->exponents[st->frame], + st->expind[st->frame], 1); + return True; +#if 0 + case 'Z': while (!XPending(st->dpy)) Cycle_frames(st); + redraw(st, st->exponents[st->frame], st->expind[st->frame], 1); + return True; +#endif + case 'q': + case 'Q': exit(0); return True; + case '?': + case 'h': + case 'H': print_help(st); return True; + default: return False; + } + + return False; +} + +/* Here's where we index into a color map. After the Lyapunov exponent is + * calculated, it is used to determine what color to use for that point. I + * suppose there are a lot of ways to do this. I used the following : if it's + * non-negative then there's a reserved area at the lower range of the color + * map that i index into. The ratio of some "minimum exponent value" and the + * calculated value is used as a ratio of how high to index into this reserved + * range. Usually these colors are dark red (see init_color). If the exponent + * is negative, the same ratio (expo/minlyap) is used to index into the + * remaining portion of the colormap (which is usually some light shades of + * color or a rainbow wheel). The coloring scheme can actually make a great + * deal of difference in the quality of the picture. Different colormaps bring + * out different details of the dynamics while different indexing algorithms + * also greatly effect what details are seen. Play around with this. + */ +static int +sendpoint(struct state *st, double expo) +{ + double tmpexpo; + + if (st->maxcolor > MAXCOLOR) + abort(); + +#if 0 + /* The relationship st->minexp <= expo <= maxexp should always be true. This + test enforces that. But maybe not enforcing it makes better pictures. */ + if (expo < st->minexp) + expo = st->minexp; + else if (expo > maxexp) + expo = maxexp; +#endif + + st->point.x++; + tmpexpo = (st->negative) ? expo : -1.0 * expo; + if (tmpexpo > 0) { + if (!mono_p) { + st->sendpoint_index = (int)(tmpexpo*st->lowrange/st->maxexp); + st->sendpoint_index = ((st->sendpoint_index % st->lowrange) + + st->startcolor); + } + else + st->sendpoint_index = 0; + } + else { + if (!mono_p) { + st->sendpoint_index = (int)(tmpexpo*st->numfreecols/st->minexp); + st->sendpoint_index = ((st->sendpoint_index % st->numfreecols) + + st->mincolindex); + } + else + st->sendpoint_index = 1; + } + BufferPoint(st, st->sendpoint_index, st->point.x, st->point.y); + if (st->save) { + if (st->frame > MAXFRAMES) + abort(); + st->exponents[st->frame][st->expind[st->frame]++] = expo; + } + if (st->point.x >= st->width) { + st->point.y++; + st->point.x = 0; + if (st->save) { + st->b += st->b_inc; + st->a = st->min_a; + } + if (st->point.y >= st->height) + return FALSE; + else + return TRUE; + } + return TRUE; +} + + +static void +resize(struct state *st) +{ + Window r; + int n, x, y; + unsigned int bw, d, new_w, new_h; + + XGetGeometry(st->dpy,st->canvas,&r,&x,&y,&new_w,&new_h,&bw,&d); + if ((new_w == st->width) && (new_h == st->height)) + return; + st->width = new_w; st->height = new_h; + XClearWindow(st->dpy, st->canvas); +#ifdef BACKING_PIXMAP + if (st->pixmap) + XFreePixmap(st->dpy, st->pixmap); + st->pixmap = XCreatePixmap(st->dpy, st->canvas, st->width, st->height, d); +#endif + st->a_inc = st->a_range / (double)st->width; + st->b_inc = st->b_range / (double)st->height; + st->point.x = -1; + st->point.y = 0; + st->run = 1; + st->a = /*st->rubber_data.p_min = */st->min_a; + st->b = /*st->rubber_data.q_min = */st->min_b; +/* st->rubber_data.p_max = st->max_a; + st->rubber_data.q_max = st->max_b;*/ + freemem(st); + setupmem(st); + for (n=0;nmaxframe) && (n != st->frame)) + st->resized[n] = 1; + InitBuffer(st); + Clear(st); + Redraw(st); +} + +static void +redraw(struct state *st, double *exparray, int index, int cont) +{ + int i, x_sav, y_sav; + + x_sav = st->point.x; + y_sav = st->point.y; + + st->point.x = -1; + st->point.y = 0; + + st->save=0; + for (i=0;isave=1; + + if (cont) { + st->point.x = x_sav; + st->point.y = y_sav; + } + else { + st->a = st->point.x * st->a_inc + st->min_a; + st->b = st->point.y * st->b_inc + st->min_b; + } + FlushBuffer(st); +} + +static void +Redraw(struct state *st) +{ + FlushBuffer(st); + st->point.x = -1; + st->point.y = 0; + st->run = 1; + st->a = st->min_a; + st->b = st->min_b; + st->expind[st->frame] = 0; + st->resized[st->frame] = 0; +} + +static void +recalc(struct state *st) +{ + int i; + + st->minexp = st->maxexp = 0.0; + for (i=0;iexpind[st->frame];i++) { + if (st->exponents[st->frame][i] < st->minexp) + st->minexp = st->exponents[st->frame][i]; + if (st->exponents[st->frame][i] > st->maxexp) + st->maxexp = st->exponents[st->frame][i]; + } +} + +static void +Clear(struct state *st) +{ + XClearWindow(st->dpy, st->canvas); +#ifdef BACKING_PIXMAP + XCopyArea(st->dpy, st->canvas, st->pixmap, st->Data_GC[0], + 0, 0, st->width, st->height, 0, 0); +#endif + InitBuffer(st); +} + +static void +show_defaults(struct state *st) +{ + + printf("Width=%d Height=%d numcolors=%d settle=%d dwell=%d\n", + st->width,st->height,st->numcolors,st->settle,st->dwell); + printf("min_a=%f a_range=%f max_a=%f\n", st->min_a,st->a_range,st->max_a); + printf("min_b=%f b_range=%f max_b=%f\n", st->min_b,st->b_range,st->max_b); + printf("minlyap=%f minexp=%f maxexp=%f\n", st->minlyap,st->minexp, + st->maxexp); + exit(0); +} + +#if 0 +static void +CreateXorGC(struct state *st) +{ + XGCValues values; + + values.foreground = st->foreground; + values.function = GXxor; + st->RubberGC = XCreateGC(st->dpy, st->canvas, + GCForeground | GCFunction, &values); +} + +static void +StartRubberBand(struct state *st, image_data_t *data, XEvent *event) +{ + XPoint corners[5]; + + st->nostart = 0; + data->rubber_band.last_x = data->rubber_band.start_x = event->xbutton.x; + data->rubber_band.last_y = data->rubber_band.start_y = event->xbutton.y; + SetupCorners(corners, data); + XDrawLines(st->dpy, st->canvas, st->RubberGC, + corners, sizeof(corners) / sizeof(corners[0]), CoordModeOrigin); +} + +static void +SetupCorners(XPoint *corners, image_data_t *data) +{ + corners[0].x = data->rubber_band.start_x; + corners[0].y = data->rubber_band.start_y; + corners[1].x = data->rubber_band.start_x; + corners[1].y = data->rubber_band.last_y; + corners[2].x = data->rubber_band.last_x; + corners[2].y = data->rubber_band.last_y; + corners[3].x = data->rubber_band.last_x; + corners[3].y = data->rubber_band.start_y; + corners[4] = corners[0]; +} + +static void +TrackRubberBand(struct state *st, image_data_t *data, XEvent *event) +{ + XPoint corners[5]; + int xdiff, ydiff; + + if (st->nostart) + return; + SetupCorners(corners, data); + XDrawLines(st->dpy, st->canvas, st->RubberGC, + corners, sizeof(corners) / sizeof(corners[0]), CoordModeOrigin); + ydiff = event->xbutton.y - data->rubber_band.start_y; + xdiff = event->xbutton.x - data->rubber_band.start_x; + data->rubber_band.last_x = data->rubber_band.start_x + xdiff; + data->rubber_band.last_y = data->rubber_band.start_y + ydiff; + if (data->rubber_band.last_y < data->rubber_band.start_y || + data->rubber_band.last_x < data->rubber_band.start_x) + { + data->rubber_band.last_y = data->rubber_band.start_y; + data->rubber_band.last_x = data->rubber_band.start_x; + } + SetupCorners(corners, data); + XDrawLines(st->dpy, st->canvas, st->RubberGC, + corners, sizeof(corners) / sizeof(corners[0]), CoordModeOrigin); +} + +static void +EndRubberBand(struct state *st, image_data_t *data, XEvent *event) +{ + XPoint corners[5]; + XPoint top, bot; + double delta, diff; + + st->nostart = 1; + SetupCorners(corners, data); + XDrawLines(st->dpy, st->canvas, st->RubberGC, + corners, sizeof(corners) / sizeof(corners[0]), CoordModeOrigin); + if (data->rubber_band.start_x >= data->rubber_band.last_x || + data->rubber_band.start_y >= data->rubber_band.last_y) + return; + top.x = data->rubber_band.start_x; + bot.x = data->rubber_band.last_x; + top.y = data->rubber_band.start_y; + bot.y = data->rubber_band.last_y; + diff = data->q_max - data->q_min; + delta = (double)top.y / (double)st->height; + data->q_min += diff * delta; + delta = (double)(st->height - bot.y) / (double)st->height; + data->q_max -= diff * delta; + diff = data->p_max - data->p_min; + delta = (double)top.x / (double)st->width; + data->p_min += diff * delta; + delta = (double)(st->width - bot.x) / (double)st->width; + data->p_max -= diff * delta; + set_new_params(st, data); +} + +static void +set_new_params(struct state *st, image_data_t *data) +{ + st->frame = (st->maxframe + 1) % MAXFRAMES; + if (st->frame > st->maxframe) + st->maxframe = st->frame; + st->a_range = data->p_max - data->p_min; + st->b_range = data->q_max - data->q_min; + st->a_minimums[st->frame] = st->min_a = data->p_min; + st->b_minimums[st->frame] = st->min_b = data->q_min; + st->a_inc = st->a_range / (double)st->width; + st->b_inc = st->b_range / (double)st->height; + st->point.x = -1; + st->point.y = 0; + st->run = 1; + st->a = st->min_a; + st->b = st->min_b; + st->a_maximums[st->frame] = st->max_a = data->p_max; + st->b_maximums[st->frame] = st->max_b = data->q_max; + st->expind[st->frame] = 0; + Clear(st); +} +#endif + +static void +go_down(struct state *st) +{ + st->frame++; + if (st->frame > st->maxframe) + st->frame = 0; + jumpwin(st); +} + +static void +go_back(struct state *st) +{ + st->frame--; + if (st->frame < 0) + st->frame = st->maxframe; + jumpwin(st); +} + +static void +jumpwin(struct state *st) +{ + /*st->rubber_data.p_min =*/ st->min_a = st->a_minimums[st->frame]; + /*st->rubber_data.q_min =*/ st->min_b = st->b_minimums[st->frame]; + /*st->rubber_data.p_max =*/ st->max_a = st->a_maximums[st->frame]; + /*st->rubber_data.q_max =*/ st->max_b = st->b_maximums[st->frame]; + st->a_range = st->max_a - st->min_a; + st->b_range = st->max_b - st->min_b; + st->a_inc = st->a_range / (double)st->width; + st->b_inc = st->b_range / (double)st->height; + st->point.x = -1; + st->point.y = 0; + st->a = st->min_a; + st->b = st->min_b; + Clear(st); + if (st->resized[st->frame]) + Redraw(st); + else + redraw(st, st->exponents[st->frame], st->expind[st->frame], 0); +} + +static void +go_init(struct state *st) +{ + st->frame = 0; + jumpwin(st); +} + +static void +Destroy_frame(struct state *st) +{ + int i; + + for (i=st->frame; imaxframe; i++) { + st->exponents[st->frame] = st->exponents[st->frame+1]; + st->expind[st->frame] = st->expind[st->frame+1]; + st->a_minimums[st->frame] = st->a_minimums[st->frame+1]; + st->b_minimums[st->frame] = st->b_minimums[st->frame+1]; + st->a_maximums[st->frame] = st->a_maximums[st->frame+1]; + st->b_maximums[st->frame] = st->b_maximums[st->frame+1]; + } + st->maxframe--; + go_back(st); +} + +static void +InitBuffer(struct state *st) +{ + int i; + + for (i = 0 ; i < st->maxcolor; ++i) + st->Points.npoints[i] = 0; +} + +static void +BufferPoint(struct state *st, int color, int x, int y) +{ + if (st->maxcolor > MAXCOLOR) + abort(); + + /* Guard against bogus color values. Shouldn't be necessary but paranoia + is good. */ + if (color < 0) + color = 0; + else if (color >= st->maxcolor) + color = st->maxcolor - 1; + + if (st->Points.npoints[color] == MAXPOINTS) + { + XDrawPoints(st->dpy, st->canvas, st->Data_GC[color], + st->Points.data[color], st->Points.npoints[color], + CoordModeOrigin); +#ifdef BACKING_PIXMAP + XDrawPoints(st->dpy, st->pixmap, st->Data_GC[color], + st->Points.data[color], st->Points.npoints[color], + CoordModeOrigin); +#endif + st->Points.npoints[color] = 0; + } + st->Points.data[color][st->Points.npoints[color]].x = x; + st->Points.data[color][st->Points.npoints[color]].y = y; + ++st->Points.npoints[color]; +} + +static void +FlushBuffer(struct state *st) +{ + int color; + + for (color = 0; color < st->maxcolor; ++color) + if (st->Points.npoints[color]) + { + XDrawPoints(st->dpy, st->canvas, st->Data_GC[color], + st->Points.data[color], st->Points.npoints[color], + CoordModeOrigin); +#ifdef BACKING_PIXMAP + XDrawPoints(st->dpy, st->pixmap, st->Data_GC[color], + st->Points.data[color], st->Points.npoints[color], + CoordModeOrigin); +#endif + st->Points.npoints[color] = 0; + } +} + +static void +print_help(struct state *st) +{ + printf("During run-time, interactive control can be exerted via : \n"); + printf("Mouse buttons allow rubber-banding of a zoom box\n"); + printf("< halves the 'dwell', > doubles the 'dwell'\n"); + printf("[ halves the 'settle', ] doubles the 'settle'\n"); + printf("D flushes the drawing buffer\n"); + printf("e or E recalculates color indices\n"); + printf("f or F saves exponents to a file\n"); + printf("h or H or ? displays this message\n"); + printf("i decrements, I increments the stripe interval\n"); + printf("KJMN increase/decrease minimum negative exponent\n"); + printf("m increments the map index, changing maps\n"); + printf("p or P reverses the colormap for negative/positive exponents\n"); + printf("r redraws without recalculating\n"); + printf("R redraws, recalculating with new dwell and settle values\n"); + printf("s or S spins the colorwheel\n"); + printf("u pops back up to the last zoom\n"); + printf("U pops back up to the first picture\n"); + printf("v or V displays the values of various settings\n"); + printf("w decrements, W increments the color wheel index\n"); + printf("x or X clears the window\n"); + printf("q or Q exits\n"); +} + +static void +print_values(struct state *st) +{ + int i; + printf("\nminlyap=%f minexp=%f maxexp=%f\n", + st->minlyap,st->minexp, st->maxexp); + printf("width=%d height=%d\n",st->width,st->height); + printf("settle=%d dwell=%d st->start_x=%f\n", + st->settle,st->dwell, st->start_x); + printf("min_a=%f a_rng=%f max_a=%f\n", + st->min_a,st->a_range,st->max_a); + printf("min_b=%f b_rng=%f max_b=%f\n", + st->min_b,st->b_range,st->max_b); + if (st->Rflag) + printf("pseudo-random forcing\n"); + else if (st->force) { + printf("periodic forcing="); + for (i=0;imaxindex;i++) + printf("%d",st->forcing[i]); + printf("\n"); + } + else + printf("periodic forcing=01\n"); + if (st->Force) { + printf("function forcing="); + for (i=0;ifuncmaxindex;i++) { + printf("%d",st->Forcing[i]); + } + printf("\n"); + } + printf("numcolors=%d\n",st->numcolors-1); +} + +static void +freemem(struct state *st) +{ + int i; + for (i=0;iexponents[i]); +} + +static void +setupmem(struct state *st) +{ + int i; + for (i=0;iexponents[i]= + (double *)malloc(sizeof(double)*st->width*(st->height+1)))==NULL){ + fprintf(stderr,"Error malloc'ing exponent array.\n"); + exit(-1); + } + } +} + +static void +setforcing(struct state *st) +{ + int i; + for (i=0;iforcing[i] = (random() > st->prob) ? 0 : 1; +} + +/****************************************************************************/ + +static void +do_defaults (struct state *st) +{ + int i; + + memset (st->expind, 0, sizeof(st->expind)); + memset (st->resized, 0, sizeof(st->resized)); + + st->aflag = 0; + st->bflag = 0; + st->hflag = 0; + st->wflag = 0; + st->minexp = 0; + st->mapindex = 0; + +# ifdef SIXTEEN_COLORS + st->maxcolor=16; + st->startcolor=0; + st->color_offset=0; + st->mincolindex=1; + st->dwell=50; + st->settle=25; + st->xposition=128; + st->yposition=128; +# else /* !SIXTEEN_COLORS */ + st->maxcolor=256; + st->startcolor=17; + st->color_offset=96; + st->mincolindex=33; + st->dwell=100; + st->settle=50; +# endif /* !SIXTEEN_COLORS */ + + st->maxindex = MAXINDEX; + st->funcmaxindex = FUNCMAXINDEX; + st->min_a=2.0; + st->min_b=2.0; + st->a_range=2.0; + st->b_range=2.0; + st->minlyap=1.0; + st->max_a=4.0; + st->max_b=4.0; + st->numcolors=16; + st->prob=0.5; + st->numwheels=MAXWHEELS; + st->negative=1; + st->rgb_max=65000; + st->nostart=1; + st->stripe_interval=7; + st->save=1; + st->useprod=1; + st->spinlength=256; + st->run=1; + + for (i = 0; i < countof(st->forcing); i++) + st->forcing[i] = (i & 1) ? 1 : 0; +} + +static void +do_preset (struct state *st, int builtin) +{ + char *ff = 0; + switch (builtin) { + case 0: + st->min_a = 3.75; st->aflag++; + st->min_b = 3.299999; st->bflag++; + st->a_range = 0.05; st->wflag++; + st->b_range = 0.05; st->hflag++; + st->dwell = 200; + st->settle = 100; + ff = "abaabbaaabbb"; + break; + + case 1: + st->min_a = 3.8; st->aflag++; + st->min_b = 3.2; st->bflag++; + st->b_range = .05; st->hflag++; + st->a_range = .05; st->wflag++; + ff = "bbbbbaaaaa"; + break; + + case 2: + st->min_a = 3.4; st->aflag++; + st->min_b = 3.04; st->bflag++; + st->a_range = .5; st->wflag++; + st->b_range = .5; st->hflag++; + ff = "abbbbbbbbb"; + st->settle = 500; + st->dwell = 1000; + break; + + case 3: + st->min_a = 3.5; st->aflag++; + st->min_b = 3.0; st->bflag++; + st->a_range = 0.2; st->wflag++; + st->b_range = 0.2; st->hflag++; + st->dwell = 600; + st->settle = 300; + ff = "aaabbbab"; + break; + + case 4: + st->min_a = 3.55667; st->aflag++; + st->min_b = 3.2; st->bflag++; + st->b_range = .05; st->hflag++; + st->a_range = .05; st->wflag++; + ff = "bbbbbaaaaa"; + break; + + case 5: + st->min_a = 3.79; st->aflag++; + st->min_b = 3.22; st->bflag++; + st->b_range = .02999; st->hflag++; + st->a_range = .02999; st->wflag++; + ff = "bbbbbaaaaa"; + break; + + case 6: + st->min_a = 3.7999; st->aflag++; + st->min_b = 3.299999; st->bflag++; + st->a_range = 0.2; st->wflag++; + st->b_range = 0.2; st->hflag++; + st->dwell = 300; + st->settle = 150; + ff = "abaabbaaabbb"; + break; + + case 7: + st->min_a = 3.89; st->aflag++; + st->min_b = 3.22; st->bflag++; + st->b_range = .028; st->hflag++; + st->a_range = .02999; st->wflag++; + ff = "bbbbbaaaaa"; + st->settle = 600; + st->dwell = 1000; + break; + + case 8: + st->min_a = 3.2; st->aflag++; + st->min_b = 3.7; st->bflag++; + st->a_range = 0.05; st->wflag++; + st->b_range = .005; st->hflag++; + ff = "abbbbaa"; + break; + + case 9: + ff = "aaaaaabbbbbb"; + st->mapindex = 1; + st->dwell = 400; + st->settle = 200; + st->minlyap = st->maxexp = ABS(-0.85); + st->minexp = -1.0 * st->minlyap; + break; + + case 10: + ff = "aaaaaabbbbbb"; + st->mapindex = 1; + st->dwell = 400; + st->settle = 200; + st->minlyap = st->maxexp = ABS(-0.85); + st->minexp = -1.0 * st->minlyap; + break; + + case 11: + st->mapindex = 1; + st->dwell = 400; + st->settle = 200; + st->minlyap = st->maxexp = ABS(-0.85); + st->minexp = -1.0 * st->minlyap; + break; + + case 12: + ff = "abbb"; + st->mapindex = 1; + st->dwell = 400; + st->settle = 200; + st->minlyap = st->maxexp = ABS(-0.85); + st->minexp = -1.0 * st->minlyap; + break; + + case 13: + ff = "abbabaab"; + st->mapindex = 1; + st->dwell = 400; + st->settle = 200; + st->minlyap = st->maxexp = ABS(-0.85); + st->minexp = -1.0 * st->minlyap; + break; + + case 14: + ff = "abbabaab"; + st->dwell = 800; + st->settle = 200; + st->minlyap = st->maxexp = ABS(-0.85); + st->minexp = -1.0 * st->minlyap; + /* #### -x 0.05 */ + st->min_a = 3.91; st->aflag++; + st->a_range = 0.0899999999; st->wflag++; + st->min_b = 3.28; st->bflag++; + st->b_range = 0.35; st->hflag++; + break; + + case 15: + ff = "aaaaaabbbbbb"; + st->dwell = 400; + st->settle = 200; + st->minlyap = st->maxexp = ABS(-0.85); + st->minexp = -1.0 * st->minlyap; + break; + + case 16: + st->dwell = 400; + st->settle = 200; + st->minlyap = st->maxexp = ABS(-0.85); + st->minexp = -1.0 * st->minlyap; + break; + + case 17: + ff = "abbb"; + st->dwell = 400; + st->settle = 200; + st->minlyap = st->maxexp = ABS(-0.85); + st->minexp = -1.0 * st->minlyap; + break; + + case 18: + ff = "abbabaab"; + st->dwell = 400; + st->settle = 200; + st->minlyap = st->maxexp = ABS(-0.85); + st->minexp = -1.0 * st->minlyap; + break; + + case 19: + st->mapindex = 2; + ff = "aaaaaabbbbbb"; + st->dwell = 400; + st->settle = 200; + st->minlyap = st->maxexp = ABS(-0.85); + st->minexp = -1.0 * st->minlyap; + break; + + case 20: + st->mapindex = 2; + st->dwell = 400; + st->settle = 200; + st->minlyap = st->maxexp = ABS(-0.85); + st->minexp = -1.0 * st->minlyap; + break; + + case 21: + st->mapindex = 2; + ff = "abbb"; + st->dwell = 400; + st->settle = 200; + st->minlyap = st->maxexp = ABS(-0.85); + st->minexp = -1.0 * st->minlyap; + break; + + case 22: + st->mapindex = 2; + ff = "abbabaab"; + st->dwell = 400; + st->settle = 200; + st->minlyap = st->maxexp = ABS(-0.85); + st->minexp = -1.0 * st->minlyap; + break; + + default: + abort(); + break; + } + + if (ff) { + char *ch; + int bindex = 0; + st->maxindex = strlen(ff); + if (st->maxindex > MAXINDEX) + usage(st); + ch = ff; + st->force++; + while (bindex < st->maxindex) { + if (*ch == 'a') + st->forcing[bindex++] = 0; + else if (*ch == 'b') + st->forcing[bindex++] = 1; + else + usage(st); + ch++; + } + } +} + + +static void * +xlyap_init (Display *d, Window window) +{ + struct state *st = (struct state *) calloc (1, sizeof(*st)); + XWindowAttributes xgwa; + int builtin = -1; + XGetWindowAttributes (d, window, &xgwa); + st->dpy = d; + st->width = xgwa.width; + st->height = xgwa.height; + st->visual = xgwa.visual; + st->cmap = xgwa.colormap; + + do_defaults(st); + parseargs(st); + + if (get_boolean_resource(st->dpy, "randomize", "Boolean")) + builtin = random() % NBUILTINS; + else { + char *s = get_string_resource(st->dpy, "builtin", "Integer"); + if (s && *s) + builtin = atoi(s); + if (s) free (s); + } + + if (builtin >= 0) + do_preset (st, builtin); + + st->screen = DefaultScreen(st->dpy); + st->background = BlackPixel(st->dpy, st->screen); + setupmem(st); + init_data(st); + if (!mono_p) + st->foreground = st->startcolor; + else + st->foreground = WhitePixel(st->dpy, st->screen); + + /* + * Create the window to display the Lyapunov exponents + */ + st->canvas = window; + init_color(st); + +#ifdef BACKING_PIXMAP + st->pixmap = XCreatePixmap(st->dpy, window, st->width, st->height, + xgwa.depth); +#endif +/* st->rubber_data.band_cursor = XCreateFontCursor(st->dpy, XC_hand2);*/ +/* CreateXorGC(st);*/ + Clear(st); + + st->delay = get_integer_resource(st->dpy, "delay", "Delay"); + st->linger = get_integer_resource(st->dpy, "linger", "Linger"); + if (st->linger < 1) st->linger = 1; + + return st; +} + + +static unsigned long +xlyap_draw (Display *dpy, Window window, void *closure) +{ + struct state *st = (struct state *) closure; + int i; + + if (!st->run && st->reset_countdown) { + st->reset_countdown--; + if (st->reset_countdown) + return 1000000; + else { + do_defaults (st); + do_preset (st, (random() % NBUILTINS)); + Clear (st); + init_data(st); + init_color(st); + resize (st); + st->frame = 0; + st->run = 1; + } + } + + for (i = 0; i < 1000; i++) + if (complyap(st) == TRUE) + { + st->run = 0; + st->reset_countdown = st->linger; + break; + } + return st->delay; +} + +static void +xlyap_reshape (Display *dpy, Window window, void *closure, + unsigned int w, unsigned int h) +{ + struct state *st = (struct state *) closure; + resize(st); +} + +static Bool +xlyap_event (Display *dpy, Window window, void *closure, XEvent *event) +{ + struct state *st = (struct state *) closure; + switch(event->type) + { + case KeyPress: + return Getkey(st, &event->xkey); + return True; +#if 0 + case ButtonPress: + StartRubberBand(st, &st->rubber_data, event); + return True; + case MotionNotify: + TrackRubberBand(st, &st->rubber_data, event); + return True; + case ButtonRelease: + EndRubberBand(st, &st->rubber_data, event); + return True; +#endif + default: + break; + } + return False; +} + +static void +xlyap_free (Display *dpy, Window window, void *closure) +{ + int i; + struct state *st = (struct state *) closure; + + freemem (st); + +#ifdef BACKING_PIXMAP + XFreePixmap (st->dpy, st->pixmap); +#endif +/* XFreeGC (st->dpy, st->RubberGC);*/ + for (i = 0; i < st->maxcolor; i++) + XFreeGC (st->dpy, st->Data_GC[i]); + + free (st); +} + + +XSCREENSAVER_MODULE ("XLyap", xlyap) diff --git a/hacks/xlyap.man b/hacks/xlyap.man new file mode 100644 index 00000000..ddef5406 --- /dev/null +++ b/hacks/xlyap.man @@ -0,0 +1,223 @@ +.TH XLYAP 6X +.SH NAME +xlyap \- display an array of Lyapunov exponents graphically +.SH SYNOPSIS +.in +8n +.ti -8n +\fIxlyap\fR +[-BLps][-W width][-H height][-o filename][-a +\fIn\fR ] +[-b +\fIn\fR ] +[-w +\fIn\fR ] +[-h +\fIn\fR ] +[-i xstart] +[-M +\fIn\fR ] +[-R +\fIp\fR ] +[-S +\fIn\fR ] +[-D +\fIn\fR ] +[-F string][-f string][-r +\fIn\fR ] +[-O +\fIn\fR ] +[-C +\fIn\fR ] +[-c +\fIn\fR ] +[-m +\fIn\fR ] +[-x xpos] +[-y ypos] +.in -8n +[\-fps] +.SH DESCRIPTION +\fIxlyap\fR +generates and graphically displays an array of Lyapunov exponents for a +variety of iterated periodically forced non-linear maps of the unit interval. +.SH OPTIONS +.TP 8 +-random +A good choice for use with xscreensaver: picks random parameters from +a built-in list. +.TP 8 +-C \fIn\fP +Specifies the minimum color index to be used for negative exponents +.TP +-D \fIn\fP +Specifies the "dwell" or number of iterations over which to average in order +to calculate the Lyapunov exponent. Default is 50. +.TP +-H \fIn\fP +Specifies the height of the window. Default is 256. +.TP +-L +Indicates use log(x) + log(y) rather than log(xy). +.TP +-M \fIr\fP +Specifies the real value to compare exponent values to for indexing into +a color wheel. The default value is 1.0. +.TP +-O \fIn\fP +Specifies the minimum color index to be used for positive exponents +.TP +-R \fIp\fP +Specifies pseudo-random forcing with probability \fIp\fP of using parameter +value 'a'. +.TP +-S \fIn\fP +Specifies the "settle" or number of iterations prior to the beginning of +the calculation of the Lyapunov exponent. Default is 50. +.TP +-a \fIr\fP +Specifies the real value to use as the minimum parameter value of the +horizontal axis. Default is 2.0 for the logistic map. +.TP +-b \fIn\fP +Specifies the real value to use as the minimum parameter value of the +vertical axis. Default is 2.0 for the logistic map. +.TP +-c \fIn\fP +Selects one of six different color wheels to use. The default color +wheel is a rainbow palette. +.TP +-F \fI10101010\fP +Specifies the "Function" forcing function to use. The example above would +alternate between iterating the circle and logistic maps. An argument of +"-F 2323" would alternate between left and right logistic maps. The default +is to only use the single specified map (see the description of -m). +.TP +-f \fIabbabaab\fP +Specifies the forcing function to use. The default is to alternate between +the "a" parameter and the "b" parameter. +.TP +-h \fIr\fP +Specifies the real value to be used as the range over which the vertical +parameter values vary. The default is 1.0. +.TP +-i \fIr\fP +Specifies the real value of the initial condition to use. Default is 0.65. +.TP +-m \fIn\fP +Selects between available non-linear maps of the unit interval. A value of +0 specifies the logistic map. A value of 1, the circle map. A value of 2, +the left-logistic. A value of 3, the right-logistic. A value of 4, the +double-logistic. The default is 0, the logistic map. +.TP +-o \fIfilename\fP +Specifies the output filename to be used. If the -o option is given, this +file will automatically be written out at the completion of the drawing. +If it is not specified, a default filename of lyap.out is used and only +written if the 'f' or 'F' keys are pressed during a run. The format of the +output file is PPM for color and PGM for monochrome. The parameters used to +calculate the picture are included as comments at the beginning of the output +file. +.TP +-p +Switches color indices for negative and positive exponents. Generally, +causes negative exponents to be displayed in more detail while darkening +and narrowing the color range for positive exponents. This can be toggled +during runtime by pressing the 'p' key. +.TP +-r \fIn\fP +Specifies the maximum rgb value to be used. Default is 65000. +.TP +-s \fIn\fP +Specifies the length of the color wheel spin. +.TP +-v +Prints out the various values to be used and exits. +.TP +-w \fIr\fP +Specifies the real value to be used as the range over which the horizontal +parameter values vary. The default is 1.0. +.sp 2 +.SH NOTES +.sp +During display, pressing any mouse button allows you to select the area to +be investigated with the mouse. The upper left hand corner of the desired +area is the location of the cursor when the button is pressed. The lower +right hand corner is specified by the cursor when the button is released. +.sp 2 +Use of the keys +\fIbBeEfFkKjJmnrRsSwWxXqQ\fP +indicates: +.sp +.ti 10 +(<) Halve dwell value. +.ti 10 +(>) Double dwell value. +.ti 10 +([) Halve settle value. +.ti 10 +(]) Double settle value. +.ti 10 +(B or b) Toggle button display on/off +.ti 10 +(E or e) Recalculate the indices into the color wheel using a different method +.ti 10 +(F or f) Save current screen to output file (not yet implemented) +.ti 10 +(H or h or ?) Display brief help message +.ti 10 +(i) Decrement the interval between stripes for the striped color map. +.ti 10 +(I) Increment the interval between stripes for the striped color map. +.ti 10 +(K) Decrease value exponents are compared against by 0.05. +.ti 10 +(J) Increase value exponents are compared against by 0.05. +.ti 10 +(M) Decrease value exponents are compared against by 0.005. +.ti 10 +(N) Increase value exponents are compared against by 0.005. +.ti 10 +(m) Increment the map index, changing the map to be iterated. +.ti 10 +(P or p) Toggle positive/negative exponent display. +.ti 10 +(r) Redraw the window using previously calculated exponents. +.ti 10 +(R) Redraw the window using the newly set dwell and/or settle values. +.ti 10 +(S) Spin the color wheel +.ti 10 +(s) Halve the length of the spin and spin the color wheel +.ti 10 +(u) Go up to the window just prior to the most recent zoom. +.ti 10 +(U) Go all the way up to the original window. +.ti 10 +(V or v) Display values of various parameters currently in use +.ti 10 +(W or w) Use next color map. +.ti 10 +(X or x) Clear window +.ti 10 +(Q or q) quit +.sp 2 +.SH AUTHOR +.nf + Ronald Joe Record + The Santa Cruz Operation + P.O. Box 1900 + Santa Cruz, CA 95061 + rr@sco.com +.fi +.sp 2 +.SH ACKNOWLEDGEMENTS +.PP +The algorithm was taken from the September 1991 Scientific American article +by A. K. Dewdney who gives credit to Mario Markus of the Max Planck Institute +for its creation. Additional information and ideas were gleaned from the +discussion on alt.fractals involving Stephen Hall, Ed Kubaitis, Dave Platt +and Baback Moghaddam. Assistance with colormaps and spinning color wheels +and X was gleaned from Hiram Clawson. Rubber banding code was adapted from +an existing Mandelbrot program written by Stacey Campbell. + +Viciously hacked for xscreensaver by Jamie Zawinski, 20-Nov-97. diff --git a/hacks/xmatrix.c b/hacks/xmatrix.c new file mode 100644 index 00000000..ba467049 --- /dev/null +++ b/hacks/xmatrix.c @@ -0,0 +1,1850 @@ +/* xscreensaver, Copyright (c) 1999-2012 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. + * + * Matrix -- simulate the text scrolls from the movie "The Matrix". + * + * The movie people distribute their own Windows/Mac screensaver that does + * a similar thing, so I wrote one for Unix. However, that version (the + * Windows/Mac version at http://www.whatisthematrix.com/) doesn't match + * what the computer screens in the movie looked like, so my `xmatrix' does + * things differently. + * + * See also my `glmatrix' program, which does a 3D rendering of the similar + * effect that appeared in the title sequence of the movies. + * + * + * ========================================================== + * + * NOTE: + * + * People just love to hack on this one. I get sent + * patches to this all the time saying, ``here, I made + * it better!'' Mostly this hasn't been true. + * + * If you've made changes to xmatrix, when you send me + * your patch, please explain, in English, both *what* + * your changes are, and *why* you think those changes + * make this screensaver behave more like the displays + * in the movie did. I'd rather not have to read your + * diffs to try and figure that out for myself... + * + * In particular, note that the characters in the movie + * were, in fact, low resolution and somewhat blurry/ + * washed out. They also definitely scrolled a + * character at a time, not a pixel at a time. + * + * And keep in mind that this program emulates the + * behavior of the computer screens that were visible + * in the movies -- not the behavior of the effects in + * the title sequences. "GLMatrix" does that. + * + * ========================================================== + * + */ + +#ifdef HAVE_UNISTD_H +# include +#endif + +#include "screenhack.h" +#include "textclient.h" +#include "xpm-pixmap.h" +#include +#include + +#ifdef HAVE_COCOA +# define HAVE_XPM +#else +# define DO_XBM /* only do mono bitmaps under real X11 */ +#endif + +#ifndef HAVE_COCOA +# include +#endif + +#if defined(HAVE_GDK_PIXBUF) || defined(HAVE_XPM) +# include "images/matrix1.xpm" +# include "images/matrix2.xpm" +# include "images/matrix1b.xpm" +# include "images/matrix2b.xpm" +#endif + +#ifdef DO_XBM +# include "images/matrix1.xbm" +# include "images/matrix2.xbm" +# include "images/matrix1b.xbm" +# include "images/matrix2b.xbm" +#endif /* DO_XBM */ + +#define CHAR_COLS 16 +#define CHAR_ROWS 13 +#define CHAR_MAPS 3 +#define PLAIN_MAP 1 +#define GLOW_MAP 2 + +typedef struct { + int glow : 8; + unsigned int glyph : 9; /* note: 9 bit characters! */ + unsigned int changed : 1; + unsigned int spinner : 1; +} m_cell; + +typedef struct { + int pipe_loc; + int remaining; + int throttle; + int y; +} m_feeder; + +#define countof(x) (sizeof(x)/sizeof(*(x))) + +static const int matrix_encoding[] = { 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, + 192, 193, 194, 195, 196, 197, 198, 199, + 200, 201, 202, 203, 204, 205, 206, 207 }; +static const int decimal_encoding[] = { 16, 17, 18, 19, 20, 21, 22, 23, 24, 25}; +static const int hex_encoding[] = { 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, + 33, 34, 35, 36, 37, 38 }; +static const int binary_encoding[] = { 16, 17 }; +static const int dna_encoding[] = { 33, 35, 39, 52 }; +static const int ascii_encoding[] = { + 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, 10, 11, 12, 13, 14, 15, + 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, + 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, + 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, + 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, + 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, + 96, 97, 98, 99,100,101,102,103,104,105,106,107,108,109,110,111, + 112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127 +}; +static const unsigned char char_map[256] = { + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, /* 0 */ + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, /* 16 */ + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, /* 32 */ + 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, /* 48 */ + 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, /* 64 */ + 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, /* 80 */ + 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, /* 96 */ + 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, /* 112 */ + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, /* 128 */ + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, /* 144 */ + 96, 97, 98, 99,100,101,102,103,104,105,106,107,108,109,110,111, /* 160 */ + 112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127, /* 176 */ + 128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143, /* 192 */ + 144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159, /* 208 */ + 160,161,162,163,164,165,166,167,168,169,170,171,172,173,174,175, /* 224 */ + 176,177,178,195,180,181,182,183,184,185,186,187,188,189,190,191 /* 240 */ +}; + +#define CURSOR_GLYPH 97 + +/* larger numbers should mean more variability between columns */ +#define BUF_SIZE 200 + +typedef enum { DRAIN_TRACE_A, + TRACE_TEXT_A, /* Call trans opt: received. */ + TRACE_A, /* (31_) 5__-0_9_ */ + TRACE_DONE, + + DRAIN_TRACE_B, + TRACE_TEXT_B, /* Call trans opt: received. */ + TRACE_B, + TRACE_FAIL, /* System Failure */ + + DRAIN_KNOCK, + KNOCK, /* Wake up, Neo... */ + + DRAIN_NMAP, + NMAP, /* Starting nmap V. 2.54BETA25 */ + + DRAIN_MATRIX, + MATRIX, + DNA, + BINARY, + DEC, + HEX, + ASCII } m_mode; + +typedef struct { + Display *dpy; + Window window; + XWindowAttributes xgwa; + GC draw_gc, erase_gc, scratch_gc; + int grid_width, grid_height; + int char_width, char_height; + m_cell *cells; + m_cell *background; + m_feeder *feeders; + int nspinners; + Bool knock_knock_p; + Bool small_p; + Bool insert_top_p, insert_bottom_p; + Bool use_pipe_p; + m_mode mode; + m_mode def_mode; /* Mode to return to after trace etc. */ + + text_data *tc; + char buf [BUF_SIZE*2+1]; /* ring buffer */ + Bool do_fill_buff; + int buf_done; + int buf_pos; + Bool start_reveal_back_p; /* start reveal process for pipe */ + Bool back_text_full_p; /* is the pipe buffer (background) full ? */ + char back_line [BUF_SIZE*2+1]; /* line buffer for background */ + int back_pos; /* background line buffer position */ + int back_y; + + signed char *tracing; + int density; + + const char *typing; + Bool typing_scroll_p; + Bool typing_cursor_p; + Bool typing_bold_p; + Bool typing_stutter_p; + int typing_left_margin; + int typing_char_delay; + int typing_line_delay; + int typing_delay; + + Bool cursor_on; + int cursor_x, cursor_y; + XtIntervalId cursor_timer; + + Pixmap images[CHAR_MAPS]; + int image_width, image_height; + Bool images_flipped_p; + + int nglyphs; + const int *glyph_map; + + unsigned long colors[5]; + int delay; +} m_state; + + +static void +load_images_1 (Display *dpy, m_state *state, int which) +{ +#if defined(HAVE_GDK_PIXBUF) || defined(HAVE_XPM) + if (!get_boolean_resource (dpy, "mono", "Boolean") && + state->xgwa.depth > 1) + { + char **bits = + (which == 1 ? (state->small_p ? matrix1b_xpm : matrix1_xpm) : + (state->small_p ? matrix2b_xpm : matrix2_xpm)); + + state->images[which] = + xpm_data_to_pixmap (state->dpy, state->window, bits, + &state->image_width, &state->image_height, 0); + } + else +#endif /* !HAVE_XPM && !HAVE_GDK_PIXBUF */ + { +#ifdef DO_XBM + unsigned long fg, bg; + state->image_width = (state->small_p ? matrix1b_width :matrix1_width); + state->image_height = (state->small_p ? matrix1b_height:matrix1_height); + fg = get_pixel_resource(state->dpy, state->xgwa.colormap, + "foreground", "Foreground"); + bg = get_pixel_resource(state->dpy, state->xgwa.colormap, + "background", "Background"); + state->images[which] = + XCreatePixmapFromBitmapData (state->dpy, state->window, (char *) + (which == 1 ? (state->small_p ? matrix1b_bits :matrix1_bits) : + (state->small_p ? matrix2b_bits :matrix2_bits)), + state->image_width, state->image_height, + bg, fg, state->xgwa.depth); +#else /* !DO_XBM */ + abort(); +#endif /* !DO_XBM */ + } +} + + +static void +load_images (Display *dpy, m_state *state) +{ + load_images_1 (dpy, state, 1); + load_images_1 (dpy, state, 2); +} + + +static void +flip_images_1 (m_state *state, int which) +{ + XImage *im = XGetImage (state->dpy, state->images[which], 0, 0, + state->image_width, state->image_height, + ~0L, (state->xgwa.depth > 1 ? ZPixmap : XYPixmap)); + int x, y, xx; + int ww = state->char_width; + unsigned long *row = (unsigned long *) malloc (sizeof(*row) * ww); + + for (y = 0; y < state->image_height; y++) + { + for (x = 0; x < CHAR_COLS; x++) + { + for (xx = 0; xx < ww; xx++) + row[xx] = XGetPixel (im, (x * ww) + xx, y); + for (xx = 0; xx < ww; xx++) + XPutPixel (im, (x * ww) + xx, y, row[ww - xx - 1]); + } + } + + XPutImage (state->dpy, state->images[which], state->draw_gc, im, 0, 0, 0, 0, + state->image_width, state->image_height); + XDestroyImage (im); + free (row); +} + +static void +flip_images (m_state *state, Bool flipped_p) +{ + if (flipped_p != state->images_flipped_p) + { + state->images_flipped_p = flipped_p; + flip_images_1 (state, 1); + flip_images_1 (state, 2); + } +} + + +/* When the subprocess has generated some output, this reads as much as it + can into s->buf at s->buf_tail. + */ +static void +fill_input (m_state *s) +{ + int n = 0; + int loadBytes; + if(s->buf_done > s->buf_pos){ + loadBytes = (s->buf_done - s->buf_pos) - 1; + } + else{ + loadBytes = ((BUF_SIZE - s->buf_pos) + s->buf_done) - 1; + } + + if (!s->tc) + return; + + if (loadBytes > 0){ + char c = textclient_getc (s->tc); + n = (c > 0 ? 1 : -1); + s->buf [s->buf_pos] = c; + } + if (n > 0) + { + s->do_fill_buff = False; + s->buf_pos = (s->buf_pos + n); + if(s->buf_pos > BUF_SIZE){ + /* copy to start of buffer */ + /* areas shouldn't overlap, but just in case, use memmove */ + memmove(s->buf,s->buf+BUF_SIZE,s->buf_pos-BUF_SIZE); + } + s->buf_pos = s->buf_pos % BUF_SIZE; + } + else + { + /* Couldn't read anything from the buffer */ + /* Assume EOF has been reached, so start again */ + s->do_fill_buff = True; + } +} + + +static void cursor_on_timer (XtPointer closure, XtIntervalId *id); +static void cursor_off_timer (XtPointer closure, XtIntervalId *id); + +static Bool +set_cursor_1 (m_state *state, Bool on) +{ + Bool changed = (state->cursor_on != on); + state->cursor_on = on; + + if (changed && state->cursor_x >= 0 && state->cursor_y >= 0) + { + m_cell *cell = &state->cells[state->grid_width * state->cursor_y + + state->cursor_x]; + cell->glow = 0; + cell->changed = True; + } + return changed; +} + + +static void +set_cursor (m_state *state, Bool on) +{ + if (set_cursor_1 (state, on)) + { + if (state->cursor_timer) + XtRemoveTimeOut (state->cursor_timer); + state->cursor_timer = 0; + if (on) + cursor_on_timer (state, 0); + } +} + +static void +cursor_off_timer (XtPointer closure, XtIntervalId *id) +{ + m_state *state = (m_state *) closure; + XtAppContext app = XtDisplayToApplicationContext (state->dpy); + set_cursor_1 (state, False); + state->cursor_timer = XtAppAddTimeOut (app, 333, + cursor_on_timer, closure); +} + +static void +cursor_on_timer (XtPointer closure, XtIntervalId *id) +{ + m_state *state = (m_state *) closure; + XtAppContext app = XtDisplayToApplicationContext (state->dpy); + set_cursor_1 (state, True); + state->cursor_timer = XtAppAddTimeOut (app, 666, + cursor_off_timer, closure); +} + + +static void +init_spinners (m_state *state) +{ + int i = state->nspinners; + int x, y; + m_cell *cell; + + for (y = 0; y < state->grid_height; y++) + for (x = 0; x < state->grid_width; x++) + { + cell = &state->cells[state->grid_width * y + x]; + cell->spinner = 0; + } + + while (--i > 0) + { + x = random() % state->grid_width; + y = random() % state->grid_height; + cell = &state->cells[state->grid_width * y + x]; + cell->spinner = 1; + } +} + + +static void +clear_spinners (m_state *state) +{ + int i; + for (i = 0; i < state->grid_width * state->grid_height; i++) + if (state->cells[i].spinner) + { + state->cells[i].spinner = 0; + state->cells[i].changed = 1; + } +} + + +static void set_mode (m_state *, m_mode); + + +static void +init_trace (m_state *state) +{ + char *s = get_string_resource (state->dpy, "tracePhone", "TracePhone"); + char *s2, *s3; + int i; + if (!s) + goto FAIL; + + state->tracing = (signed char *) malloc (strlen (s) + 1); + s3 = (char *) state->tracing; + + for (s2 = s; *s2; s2++) + if (*s2 >= '0' && *s2 <= '9') + *s3++ = *s2; + *s3 = 0; + + if (s3 == (char *) state->tracing) + goto FAIL; + + for (i = 0; i < strlen((char *) state->tracing); i++) + state->tracing[i] = -state->tracing[i]; + + state->glyph_map = decimal_encoding; + state->nglyphs = countof(decimal_encoding); + + return; + + FAIL: + fprintf (stderr, "%s: bad phone number: \"%s\".\n", + progname, s ? s : "(null)"); + + if (s) free (s); + if (state->tracing) free (state->tracing); + state->tracing = 0; + set_mode (state, MATRIX); +} + + +static void +init_drain (m_state *state) +{ + int i; + + set_cursor (state, False); + state->cursor_x = -1; + state->cursor_y = -1; + + /* Fill the top row with empty top-feeders, to clear the screen. */ + for (i = 0; i < state->grid_width; i++) + { + m_feeder *f = &state->feeders[i]; + f->y = -1; + f->remaining = 0; + f->throttle = 0; + } + + /* Turn off all the spinners, else they never go away. */ + clear_spinners (state); +} + +static Bool +screen_blank_p (m_state *state) +{ + int i; + for (i = 0; i < state->grid_width * state->grid_height; i++) + if (state->cells[i].glyph) + return False; + return True; +} + + +static void +set_mode (m_state *state, m_mode mode) +{ + if (mode == state->mode) + return; + + state->mode = mode; + state->typing = 0; + + switch (mode) + { + case MATRIX: + state->glyph_map = matrix_encoding; + state->nglyphs = countof(matrix_encoding); + flip_images (state, True); + init_spinners (state); + break; + case DNA: + state->glyph_map = dna_encoding; + state->nglyphs = countof(dna_encoding); + flip_images (state, False); + break; + case BINARY: + state->glyph_map = binary_encoding; + state->nglyphs = countof(binary_encoding); + flip_images (state, False); + break; + case HEX: + state->glyph_map = hex_encoding; + state->nglyphs = countof(hex_encoding); + flip_images (state, False); + break; + case ASCII: + state->glyph_map = ascii_encoding; + state->nglyphs = countof(ascii_encoding); + flip_images (state, False); + break; + case DEC: + case TRACE_A: + case TRACE_B: + case NMAP: + case KNOCK: + state->glyph_map = decimal_encoding; + state->nglyphs = countof(decimal_encoding); + flip_images (state, False); + break; + case TRACE_TEXT_A: + case TRACE_TEXT_B: + flip_images (state, False); + init_trace (state); + break; + case DRAIN_TRACE_A: + case DRAIN_TRACE_B: + case DRAIN_KNOCK: + case DRAIN_NMAP: + case DRAIN_MATRIX: + init_drain (state); + break; + case TRACE_DONE: + case TRACE_FAIL: + break; + default: + abort(); + } +} + + +static void * +xmatrix_init (Display *dpy, Window window) +{ + XGCValues gcv; + char *insert, *mode; + int i; + m_state *state = (m_state *) calloc (sizeof(*state), 1); + + state->dpy = dpy; + state->window = window; + state->delay = get_integer_resource (dpy, "delay", "Integer"); + + XGetWindowAttributes (dpy, window, &state->xgwa); + + state->small_p = (state->xgwa.width < 300); + { + const char *s = get_string_resource (dpy, "matrixFont", "String"); + if (!s || !*s || !strcasecmp(s, "large")) + state->small_p = False; + else if (!strcasecmp(s, "small")) + state->small_p = True; + else + fprintf (stderr, "%s: matrixFont should be 'small' or 'large' not '%s'\n", + progname, s); + } + + load_images (dpy, state); + + gcv.foreground = get_pixel_resource(state->dpy, state->xgwa.colormap, + "foreground", "Foreground"); + gcv.background = get_pixel_resource(state->dpy, state->xgwa.colormap, + "background", "Background"); + state->draw_gc = XCreateGC (state->dpy, state->window, + GCForeground|GCBackground, &gcv); + gcv.foreground = gcv.background; + state->erase_gc = XCreateGC (state->dpy, state->window, + GCForeground|GCBackground, &gcv); + + state->scratch_gc = XCreateGC (state->dpy, state->window, 0, &gcv); + + /* Allocate colors for SYSTEM FAILURE box */ + { + XColor boxcolors[] = { + { 0, 0x0808, 0x1E1E, 0x0808, DoRed|DoGreen|DoBlue, 0 }, + { 0, 0x5A5A, 0xD2D2, 0x5A5A, DoRed|DoGreen|DoBlue, 0 }, + { 0, 0xE0E0, 0xF7F7, 0xE0E0, DoRed|DoGreen|DoBlue, 0 }, + { 0, 0x5A5A, 0xD2D2, 0x5A5A, DoRed|DoGreen|DoBlue, 0 }, + { 0, 0x0808, 0x1E1E, 0x0808, DoRed|DoGreen|DoBlue, 0 }, + }; + for (i = 0; i < countof(boxcolors); i++) + { + if (XAllocColor (state->dpy, state->xgwa.colormap, &boxcolors[i])) + state->colors[i] = boxcolors[i].pixel; + else + state->colors[i] = gcv.foreground; /* default black */ + } + } + + state->char_width = state->image_width / CHAR_COLS; + state->char_height = state->image_height / CHAR_ROWS; + + state->grid_width = state->xgwa.width / state->char_width; + state->grid_height = state->xgwa.height / state->char_height; + state->grid_width++; + state->grid_height++; + if (state->grid_width < 5) state->grid_width = 5; + if (state->grid_height < 5) state->grid_height = 5; + + state->glyph_map = matrix_encoding; + state->nglyphs = countof(matrix_encoding); + + state->cells = (m_cell *) + calloc (sizeof(m_cell), state->grid_width * state->grid_height); + state->background = (m_cell *) + calloc (sizeof(m_cell), state->grid_width * state->grid_height); + state->feeders = (m_feeder *) calloc (sizeof(m_feeder), state->grid_width); + + state->density = get_integer_resource (dpy, "density", "Integer"); + + insert = get_string_resource(dpy, "insert", "Insert"); + if (insert && !strcmp(insert, "top")) + { + state->insert_top_p = True; + state->insert_bottom_p = False; + } + else if (insert && !strcmp(insert, "bottom")) + { + state->insert_top_p = False; + state->insert_bottom_p = True; + } + else if (insert && !strcmp(insert, "both")) + { + state->insert_top_p = True; + state->insert_bottom_p = True; + } + else + { + if (insert && *insert) + fprintf (stderr, + "%s: `insert' must be `top', `bottom', or `both', not `%s'\n", + progname, insert); + state->insert_top_p = False; + state->insert_bottom_p = True; + } + + state->nspinners = get_integer_resource (dpy, "spinners", "Integer"); + + if (insert) + free (insert); + + state->knock_knock_p = get_boolean_resource (dpy, "knockKnock", "KnockKnock"); + + state->use_pipe_p = get_boolean_resource (dpy, "usePipe", "Boolean"); + state->buf_pos = 1; + state->buf[0] = ' '; /* spacer byte in buffer (space) */ + state->buf_done = 0; + state->do_fill_buff = True; + state->start_reveal_back_p = False; + state->back_text_full_p = False; + state->back_y = 0; + state->back_pos = 0; + + state->mode = -1; + state->def_mode = MATRIX; + mode = get_string_resource (dpy, "mode", "Mode"); + if (mode && !strcasecmp(mode, "trace")) + set_mode (state, ((random() % 3) ? TRACE_TEXT_A : TRACE_TEXT_B)); + else if (mode && !strcasecmp(mode, "crack")) + set_mode (state, DRAIN_NMAP); + else if (mode && !strcasecmp(mode, "dna")){ + set_mode (state, DNA); + state->def_mode = DNA; + } + else if (mode && (!strcasecmp(mode, "bin") || + !strcasecmp(mode, "binary"))){ + set_mode (state, BINARY); + state->def_mode = BINARY; + } + else if (mode && (!strcasecmp(mode, "hex") || + !strcasecmp(mode, "hexadecimal"))){ + set_mode (state, HEX); + state->def_mode = HEX; + } + else if (mode && (!strcasecmp(mode, "dec") || + !strcasecmp(mode, "decimal"))){ + set_mode (state, DEC); + state->def_mode = DEC; + } + else if (mode && (!strcasecmp(mode, "asc") || + !strcasecmp(mode, "ascii"))){ + set_mode (state, ASCII); + state->def_mode = ASCII; + } + else if (mode && !strcasecmp(mode, "pipe")) + { + set_mode (state, ASCII); + state->def_mode = ASCII; + state->use_pipe_p = True; + state->tc = textclient_open (dpy); + } + else if (!mode || !*mode || !strcasecmp(mode, "matrix")) + set_mode (state, MATRIX); + else + { + fprintf (stderr, "%s: `mode' must be ",progname); + fprintf (stderr, "matrix, trace, dna, binary, ascii, hex, or pipe: "); + fprintf (stderr, "not `%s'\n", mode); + set_mode (state, MATRIX); + } + + if (state->mode == MATRIX && get_boolean_resource (dpy, "trace", "Boolean")) + set_mode (state, ((random() % 3) ? TRACE_TEXT_A : TRACE_TEXT_B)); + + state->cursor_x = -1; + state->cursor_y = -1; + + return state; +} + + +static void +insert_glyph (m_state *state, int glyph, int x, int y) +{ + Bool bottom_feeder_p = (y >= 0); + m_cell *from, *to; + if (y >= state->grid_height) + return; + + if (bottom_feeder_p) + { + to = &state->cells[state->grid_width * y + x]; + } + else + { + for (y = state->grid_height-1; y > 0; y--) + { + from = &state->cells[state->grid_width * (y-1) + x]; + to = &state->cells[state->grid_width * y + x]; + to->glyph = from->glyph; + to->glow = from->glow; + to->changed = 1; + } + to = &state->cells[x]; + } + + to->glyph = glyph; + to->changed = 1; + + if (!to->glyph) + ; + else if (bottom_feeder_p) + to->glow = 1 + (random() % (state->tracing ? 4 : 2)); + else + to->glow = 0; +} + + +static void +place_back_char (m_state *state, char textc, int x, int y){ + if((x>=0) && (y>=0) && + (x < state->grid_width) && (y < state->grid_height)){ + m_cell *celltmp = &state->background[state->grid_width * y + x]; + celltmp -> glyph = char_map[(unsigned char)textc] + 1; + if(!celltmp->glyph || (celltmp->glyph == 3)){ + celltmp -> glyph = char_map[32] + 1; + } + celltmp -> changed = 1; + } +} + +static void +place_back_text (m_state *state, char *text, int x, int y){ + int i; + for(i=0; iback_line[state->back_pos] = textc; + if(textc == '\n'){ + state->back_line[state->back_pos] = '\0'; + new_line = True; + } + else if ((state->back_pos > (state->grid_width - 4)) || + (state->back_pos >= BUF_SIZE)){ /* off by 1? */ + state->back_line[++state->back_pos] = '\0'; + new_line = True; + } + else{ + state->back_pos++; + } + if(new_line){ + int startx = (state->grid_width >> 1) - + (strlen(state->back_line) >> 1); + place_back_text(state, state->back_line, + startx, state->back_y); + state->back_pos = 0; + state->back_y++; + if(state->back_y >= (state->grid_height - 1)){ + state->back_y = 1; + state->back_text_full_p = True; + state->start_reveal_back_p = True; + } + } +} + +static void +feed_matrix (m_state *state) +{ + int x; + + switch (state->mode) + { + case TRACE_A: + { + int L = strlen((char *) state->tracing); + int count = 0; + int i; + + for (i = 0; i < strlen((char *) state->tracing); i++) + if (state->tracing[i] > 0) + count++; + + if (count >= L) + { + set_mode (state, TRACE_DONE); + state->typing_delay = 1000000; + return; + } + else + { + i = 5 + (30 / (count+1)); /* how fast numbers are discovered */ + + if ((random() % i) == 0) + { + i = random() % L; + if (state->tracing[i] < 0) + state->tracing[i] = -state->tracing[i]; + } + } + } + break; + + case TRACE_B: + if ((random() % 40) == 0) + { + set_mode (state, TRACE_FAIL); + return; + } + break; + + case MATRIX: case DNA: case BINARY: case DEC: case HEX: case ASCII: + case DRAIN_TRACE_A: + case DRAIN_TRACE_B: + case DRAIN_KNOCK: + case DRAIN_NMAP: + case DRAIN_MATRIX: + break; + + default: + abort(); + } + + /*get input*/ + if((state->use_pipe_p) && (!state->back_text_full_p)){ + place_back_pipe(state, state->buf[state->buf_done]); + state->buf_done = (state->buf_done + 1) % BUF_SIZE; + if(state->buf_done == (state->buf_pos - 1)){ + state->do_fill_buff = True; + } + } + if(state->buf_done == (state->buf_pos + 1)){ + state->do_fill_buff = False; + } + else{ + state->do_fill_buff = True; + fill_input(state); + } + + /* Update according to current feeders. */ + for (x = 0; x < state->grid_width; x++) + { + m_feeder *f = &state->feeders[x]; + + if (f->throttle) /* this is a delay tick, synced to frame. */ + { + f->throttle--; + } + else if (f->remaining > 0) /* how many items are in the pipe */ + { + int g; + long rval; + if((state->use_pipe_p) && (!state->back_text_full_p)){ + rval = (int) state->buf[f->pipe_loc]; + if(++f->pipe_loc > (BUF_SIZE-1)){ + f->pipe_loc = 0; + /*fill_input(state);*/ + } + rval = (rval % state->nglyphs); + } + else{ + rval = (random() % state->nglyphs); + } + g = state->glyph_map[rval] + 1; + insert_glyph (state, g, x, f->y); + f->remaining--; + if (f->y >= 0) /* bottom_feeder_p */ + f->y++; + } + else /* if pipe is empty, insert spaces */ + { + insert_glyph (state, 0, x, f->y); + if (f->y >= 0) /* bottom_feeder_p */ + f->y++; + } + + if ((random() % 10) == 0) /* randomly change throttle speed */ + { + f->throttle = ((random() % 5) + (random() % 5)); + } + } +} + + +static void +redraw_cells (m_state *state, Bool active) +{ + int x, y; + int count = 0; + Bool use_back_p = False; + + for (y = 0; y < state->grid_height; y++) + for (x = 0; x < state->grid_width; x++) + { + m_cell *cell = &state->cells[state->grid_width * y + x]; + m_cell *back = &state->background[state->grid_width * y + x]; + Bool cursor_p = (state->cursor_on && + x == state->cursor_x && + y == state->cursor_y); + + if (cell->glyph) + count++; + else { + if((state->start_reveal_back_p) && + (back->glyph) && !(state->mode == TRACE_A || + state->mode == TRACE_B || + state->mode == TRACE_DONE)){ + use_back_p = True; + cell = back; + } + } + + /* In trace-mode, the state of each cell is random unless we have + a match for this digit. */ + if (active && (state->mode == TRACE_A || + state->mode == TRACE_B || + state->mode == TRACE_DONE)) + { + int xx = x % strlen((char *) state->tracing); + Bool dead_p = state->tracing[xx] > 0; + + if (y == 0 && x == xx && !use_back_p) + cell->glyph = (dead_p + ? state->glyph_map[state->tracing[xx]-'0'] + 1 + : 0); + else if (y == 0 && !use_back_p) + cell->glyph = 0; + else if (!use_back_p) + cell->glyph = (dead_p ? 0 : + (state->glyph_map[(random()%state->nglyphs)] + + 1)); + if (!use_back_p) + cell->changed = 1; + } + + if (!cell->changed) + continue; + + + if (cell->glyph == 0 && !cursor_p && !use_back_p) + XFillRectangle (state->dpy, state->window, state->erase_gc, + x * state->char_width, + y * state->char_height, + state->char_width, + state->char_height); + else + { + int g = (cursor_p ? CURSOR_GLYPH : cell->glyph); + int cx = (g - 1) % CHAR_COLS; + int cy = (g - 1) / CHAR_COLS; + int map = ((cell->glow != 0 || cell->spinner) ? GLOW_MAP : + PLAIN_MAP); + + XCopyArea (state->dpy, state->images[map], + state->window, state->draw_gc, + cx * state->char_width, + cy * state->char_height, + state->char_width, + state->char_height, + x * state->char_width, + y * state->char_height); + } + if (!use_back_p) + cell->changed = 0; + + if (cell->glow > 0 && state->mode != NMAP && !use_back_p) + { + cell->glow--; + cell->changed = 1; + } + else if (cell->glow < 0) + abort(); + + if (cell->spinner && active && !use_back_p) + { + cell->glyph = (state->glyph_map[(random()%state->nglyphs)] + 1); + cell->changed = 1; + } + } +} + + +static int +densitizer (m_state *state) +{ + /* Horrid kludge that converts percentages (density of screen coverage) + to the parameter that actually controls this. I got this mapping + empirically, on a 1024x768 screen. Sue me. */ + if (state->density < 10) return 85; + else if (state->density < 15) return 60; + else if (state->density < 20) return 45; + else if (state->density < 25) return 25; + else if (state->density < 30) return 20; + else if (state->density < 35) return 15; + else if (state->density < 45) return 10; + else if (state->density < 50) return 8; + else if (state->density < 55) return 7; + else if (state->density < 65) return 5; + else if (state->density < 80) return 3; + else if (state->density < 90) return 2; + else return 1; +} + + +static void +hack_text (m_state *state) +{ + if (!state->typing) + { + set_cursor (state, False); + state->cursor_x = 0; + state->cursor_y = 0; + state->typing_scroll_p = False; + state->typing_bold_p = False; + state->typing_cursor_p = True; + state->typing_stutter_p = False; + state->typing_char_delay = 10000; + state->typing_line_delay = 1500000; + + switch (state->mode) + { + case TRACE_TEXT_A: + case TRACE_TEXT_B: + clear_spinners (state); + if (state->mode == TRACE_TEXT_A) + { + if (state->grid_width >= 52) + state->typing = + ("Call trans opt: received. 2-19-98 13:24:18 REC:Log>\n" + "Trace program: running\n"); + else + state->typing = + ("Call trans opt: received.\n2-19-98 13:24:18 REC:Log>\n" + "Trace program: running\n"); + } + else + { + if (state->grid_width >= 52) + state->typing = + ("Call trans opt: received. 9-18-99 14:32:21 REC:Log>\n" + "WARNING: carrier anomaly\n" + "Trace program: running\n"); + else + state->typing = + ("Call trans opt: received.\n9-18-99 14:32:21 REC:Log>\n" + "WARNING: carrier anomaly\n" + "Trace program: running\n"); + } + break; + + case TRACE_FAIL: + { + const char *s = "SYSTEM FAILURE\n"; + int i; + float cx = (state->grid_width - strlen(s) - 1) / 2 - 0.5; + float cy = (state->grid_height / 2) - 1.3; + + if (cy < 0) cy = 0; + if (cx < 0) cx = 0; + + XFillRectangle (state->dpy, state->window, state->erase_gc, + cx * state->char_width, + cy * state->char_height, + strlen(s) * state->char_width, + state->char_height * 1.6); + + for (i = -2; i < 3; i++) + { + XGCValues gcv; + gcv.foreground = state->colors[i + 2]; + XChangeGC (state->dpy, state->scratch_gc, GCForeground, &gcv); + XDrawRectangle (state->dpy, state->window, state->scratch_gc, + cx * state->char_width - i, + cy * state->char_height - i, + strlen(s) * state->char_width + (2 * i), + (state->char_height * 1.6) + (2 * i)); + } + + /* If we don't clear these, part of the box may get overwritten */ + for (i = 0; i < state->grid_height * state->grid_width; i++) + { + m_cell *cell = &state->cells[i]; + cell->changed = 0; + } + + state->cursor_x = (state->grid_width - strlen(s) - 1) / 2; + state->cursor_y = (state->grid_height / 2) - 1; + if (state->cursor_x < 0) state->cursor_x = 0; + if (state->cursor_y < 0) state->cursor_y = 0; + + state->typing = s; + state->typing_char_delay = 0; + state->typing_cursor_p = False; + } + break; + + case KNOCK: + { + clear_spinners (state); + state->typing = ("\001Wake up, Neo...\n" + "\001The Matrix has you...\n" + "\001Follow the white rabbit.\n" + "\n" + "Knock, knock, Neo.\n"); + + state->cursor_x = 4; + state->cursor_y = 2; + state->typing_char_delay = 0; + state->typing_line_delay = 2000000; + } + break; + + case NMAP: + { + /* Note that what Trinity is using here is moderately accurate: + She runs nmap (http://www.insecure.org/nmap/) then breaks in + with a (hypothetical) program called "sshnuke" that exploits + the (very real) SSHv1 CRC32 compensation attack detector bug + (http://staff.washington.edu/dittrich/misc/ssh-analysis.txt). + + The command syntax of the power grid control software looks a + lot like Cisco IOS to me. (IOS is a descendant of VMS.) + */ + + clear_spinners (state); + state->typing = +# ifdef __GNUC__ + __extension__ /* don't warn about "string length is greater than + the length ISO C89 compilers are required to + support"... */ + +# endif + ("# " + "\010\010\010\010" + "\001nmap -v -sS -O 10.2.2.2\n" + "Starting nmap V. 2.54BETA25\n" + "\010\010\010\010\010\010\010\010\010\010" + "Insufficient responses for TCP sequencing (3), OS detection" + " may be less accurate\n" + "Interesting ports on 10.2.2.2:\n" + "(The 1539 ports scanned but not shown below are in state:" + " closed)\n" + "Port state service\n" + "22/tcp open ssh\n" + "\n" + "No exact OS matches for host\n" + "\n" + "Nmap run completed -- 1 IP address (1 host up) scanned\n" + "# " + + "\010\010\010\010" + "\001sshnuke 10.2.2.2 -rootpw=\"Z1ON0101\"\n" + "Connecting to 10.2.2.2:ssh ... " + "\010\010" + "successful.\n" + "Attempting to exploit SSHv1 CRC32 ... " + "\010\010\010\010" + "successful.\n" + "Resetting root password to \"Z1ON0101\".\n" + "\010\010" + "System open: Access Level <9>\n" + + "# " + "\010\010" + + "\001ssh 10.2.2.2 -l root\n" + "\010\010" + "root@10.2.2.2's password: " + "\010\010\n" + "\010\010\n" + "RRF-CONTROL> " + + "\010\010" + "\001disable grid nodes 21 - 48\n" + "\n" + "\002Warning: Disabling nodes 21-48 will disconnect sector 11" + " (28 nodes)\n" + "\n" + "\002 ARE YOU SURE? (y/n) " + + "\010\010" + "\001y\n" + "\n" + "\n" + "\010\002Grid Node 21 offline...\n" + "\010\002Grid Node 22 offline...\n" + "\010\002Grid Node 23 offline...\n" + "\010\002Grid Node 24 offline...\n" + "\010\002Grid Node 25 offline...\n" + "\010\002Grid Node 26 offline...\n" + "\010\002Grid Node 27 offline...\n" + "\010\002Grid Node 28 offline...\n" + "\010\002Grid Node 29 offline...\n" + "\010\002Grid Node 30 offline...\n" + "\010\002Grid Node 31 offline...\n" + "\010\002Grid Node 32 offline...\n" + "\010\002Grid Node 33 offline...\n" + "\010\002Grid Node 34 offline...\n" + "\010\002Grid Node 35 offline...\n" + "\010\002Grid Node 36 offline...\n" + "\010\002Grid Node 37 offline...\n" + "\010\002Grid Node 38 offline...\n" + "\010\002Grid Node 39 offline...\n" + "\010\002Grid Node 40 offline...\n" + "\010\002Grid Node 41 offline...\n" + "\010\002Grid Node 42 offline...\n" + "\010\002Grid Node 43 offline...\n" + "\010\002Grid Node 44 offline...\n" + "\010\002Grid Node 45 offline...\n" + "\010\002Grid Node 46 offline...\n" + "\010\002Grid Node 47 offline...\n" + "\010\002Grid Node 48 offline...\n" + "\010\010" + "\nRRF-CONTROL> " + "\010\010\010\010\010\010\010\010" + ); + + state->cursor_x = 0; + state->cursor_y = state->grid_height - 3; + state->typing_scroll_p = True; + state->typing_char_delay = 0; + state->typing_line_delay = 20000; + } + break; + + default: + abort(); + break; + } + + state->typing_left_margin = state->cursor_x; + state->typing_delay = state->typing_char_delay; + if (state->typing_cursor_p) + set_cursor (state, True); + } + else + { + Bool scrolled_p = False; + unsigned char c, c1; + int x = state->cursor_x; + int y = state->cursor_y; + + AGAIN: + c = ((unsigned char *) state->typing)[0]; + c1 = ((unsigned char *) state->typing)[1]; + + state->typing_delay = (!c || c1 == '\n' + ? state->typing_line_delay + : state->typing_char_delay); + if (! c) + { + state->typing_delay = 0; + state->typing = 0; + return; + } + + if (state->typing_scroll_p && + (c == '\n' || + x >= state->grid_width - 1)) + { + set_cursor (state, False); + x = 0; + y++; + + if (y >= state->grid_height-1) + { + int xx, yy; + for (yy = 0; yy < state->grid_height-2; yy++) + for (xx = 0; xx < state->grid_width; xx++) + { + int ii = yy * state->grid_width + xx; + int jj = (yy+1) * state->grid_width + xx; + state->cells[ii] = state->cells[jj]; + state->cells[ii].changed = 1; + } + /* clear bottom row */ + for (xx = 0; xx < state->grid_width; xx++) + { + int ii = yy * state->grid_width + xx; + state->cells[ii].glyph = 0; + state->cells[ii].changed = 1; + } + y--; /* move back up to bottom line */ + scrolled_p = True; + } + } + + if (c == '\n') + { + if (!state->typing_scroll_p) + { + int i, j; + set_cursor (state, False); + x = state->typing_left_margin; + + /* clear the line */ + i = state->grid_width * y; + j = i + state->grid_width; + for (; i < j; i++) + { + state->cells[i].glyph = 0; + state->cells[i].changed = 1; + } + } + state->typing_bold_p = False; + state->typing_stutter_p = False; + scrolled_p = True; + } + + else if (c == '\010') + state->typing_delay += 500000; + + else if (c == '\001') + { + state->typing_stutter_p = True; + state->typing_bold_p = False; + } + else if (c == '\002') + state->typing_bold_p = True; + + else if (x < state->grid_width-1) + { + m_cell *cell = &state->cells[state->grid_width * y + x]; + cell->glyph = char_map[c] + 1; + if (c == ' ' || c == '\t') cell->glyph = 0; + cell->changed = 1; + cell->glow = (state->typing_bold_p ? 127 : 0); + } + + if (c >= ' ') + x++; + + if (x >= state->grid_width-1) + x = state->grid_width-1; + + state->typing++; + + if (state->typing_stutter_p) + { + if (state->typing_delay == 0) + state->typing_delay = 20000; + if (random() % 3) + state->typing_delay += (0xFFFFFF & ((random() % 200000) + 1)); + } + + /* If there's no delay after this character, just keep going. */ + if (state->typing_delay == 0) + goto AGAIN; + + if (scrolled_p || x != state->cursor_x || y != state->cursor_y) + { + set_cursor (state, False); + state->cursor_x = x; + state->cursor_y = y; + if (state->typing_cursor_p) + set_cursor (state, True); + } + } +} + + +static void +hack_matrix (m_state *state) +{ + int x; + + switch (state->mode) + { + case TRACE_DONE: case TRACE_FAIL: + return; + case TRACE_A: case TRACE_B: + case MATRIX: case DNA: case BINARY: case DEC: case HEX: case ASCII: + break; + default: + abort(); break; + } + + /* Glow some characters. */ + if (!state->insert_bottom_p) + { + int i = random() % (state->grid_width / 2); + while (--i > 0) + { + int yy = random() % state->grid_height; + int xx = random() % state->grid_width; + m_cell *cell = &state->cells[state->grid_width * yy + xx]; + if (cell->glyph && cell->glow == 0) + { + cell->glow = random() % 10; + cell->changed = 1; + } + } + } + + /* Change some of the feeders. */ + for (x = 0; x < state->grid_width; x++) + { + m_feeder *f = &state->feeders[x]; + Bool bottom_feeder_p; + + if (f->remaining > 0) /* never change if pipe isn't empty */ + continue; + + if ((random() % densitizer(state)) != 0) /* then change N% of the time */ + continue; + + f->remaining = 3 + (random() % state->grid_height); + f->throttle = ((random() % 5) + (random() % 5)); + + if ((random() % 4) != 0) + f->remaining = 0; + + if (state->mode == TRACE_A || state->mode == TRACE_B) + bottom_feeder_p = True; + else if (state->insert_top_p && state->insert_bottom_p) + bottom_feeder_p = (random() & 1); + else + bottom_feeder_p = state->insert_bottom_p; + + if (bottom_feeder_p) + f->y = random() % (state->grid_height / 2); + else + f->y = -1; + } + + if (state->mode == MATRIX && (! (random() % 500))) + init_spinners (state); +} + + +static unsigned long +xmatrix_draw (Display *dpy, Window window, void *closure) +{ + m_state *state = (m_state *) closure; + + if (state->typing_delay > 0) + { + state->typing_delay -= state->delay; + if (state->typing_delay < 0) + state->typing_delay = 0; + redraw_cells (state, False); + return state->delay; + } + + switch (state->mode) + { + case MATRIX: case DNA: case BINARY: case DEC: case HEX: case ASCII: + case TRACE_A: case TRACE_B: + feed_matrix (state); + hack_matrix (state); + break; + + case DRAIN_TRACE_A: + case DRAIN_TRACE_B: + case DRAIN_KNOCK: + case DRAIN_NMAP: + case DRAIN_MATRIX: + feed_matrix (state); + if (screen_blank_p (state)) + { + state->typing_delay = 500000; + if(state->start_reveal_back_p){ + m_cell *back, *to; + int x,y; + state->typing_delay = 5000000; + state->start_reveal_back_p = False; + state->back_text_full_p = False; + /* for loop to move background to foreground */ + for (y = 0; y < state->grid_height; y++){ + for (x = 0; x < state->grid_width; x++){ + to = &state->cells[state->grid_width * y + x]; + back = &state->background[state->grid_width * y + x]; + to->glyph = back->glyph; + to->changed = back->changed; + back->glyph = 0; + back->changed = 0; + } + } + } + switch (state->mode) + { + case DRAIN_TRACE_A: set_mode (state, TRACE_TEXT_A); break; + case DRAIN_TRACE_B: set_mode (state, TRACE_TEXT_B); break; + case DRAIN_KNOCK: set_mode (state, KNOCK); break; + case DRAIN_NMAP: set_mode (state, NMAP); break; + case DRAIN_MATRIX: set_mode (state, state->def_mode); break; + default: abort(); break; + } + } + break; + + case TRACE_DONE: + set_mode (state, state->def_mode); + break; + + case TRACE_TEXT_A: + case TRACE_TEXT_B: + case TRACE_FAIL: + case KNOCK: + case NMAP: + hack_text (state); + + if (! state->typing) /* done typing */ + { + set_cursor (state, False); + switch (state->mode) + { + case TRACE_TEXT_A: set_mode (state, TRACE_A); break; + case TRACE_TEXT_B: set_mode (state, TRACE_B); break; + case TRACE_FAIL: set_mode (state, state->def_mode); break; + case KNOCK: set_mode (state, state->def_mode); break; + case NMAP: set_mode (state, state->def_mode); break; + default: abort(); break; + } + } + break; + + default: + abort(); + } + if (state->start_reveal_back_p){ + set_mode (state, DRAIN_MATRIX); + } + if (state->mode == MATRIX && + state->knock_knock_p && + (! (random() % 10000))) + { + if (! (random() % 5)) + set_mode (state, DRAIN_NMAP); + else + set_mode (state, DRAIN_KNOCK); + } + + redraw_cells (state, True); + +#if 0 + { + static int i = 0; + static int ndens = 0; + static int tdens = 0; + i++; + if (i > 50) + { + int dens = (100.0 * + (((double)count) / + ((double) (state->grid_width * state->grid_height)))); + tdens += dens; + ndens++; + printf ("density: %d%% (%d%%)\n", dens, (tdens / ndens)); + i = 0; + } + } +#endif + + return state->delay; +} + + +static void +xmatrix_reshape (Display *dpy, Window window, void *closure, + unsigned int w, unsigned int h) +{ + m_state *state = (m_state *) closure; + int ow = state->grid_width; + int oh = state->grid_height; + XGetWindowAttributes (state->dpy, state->window, &state->xgwa); + state->grid_width = state->xgwa.width / state->char_width; + state->grid_height = state->xgwa.height / state->char_height; + state->grid_width++; + state->grid_height++; + if (state->grid_width < 5) state->grid_width = 5; + if (state->grid_height < 5) state->grid_height = 5; + + if (ow != state->grid_width || + oh != state->grid_height) + { + m_cell *ncells = (m_cell *) + calloc (sizeof(m_cell), state->grid_width * state->grid_height); + m_cell *nbackground = (m_cell *) + calloc (sizeof(m_cell), state->grid_width * state->grid_height); + m_feeder *nfeeders = (m_feeder *) + calloc (sizeof(m_feeder), state->grid_width); + int x, y, i; + + /* fprintf(stderr, "resize: %d x %d ==> %d x %d\n", + ow, oh, state->grid_width, state->grid_height); */ + + for (y = 0; y < oh; y++) + for (x = 0; x < ow; x++) + if (x < ow && x < state->grid_width && + y < oh && y < state->grid_height){ + ncells[y * state->grid_width + x] = + state->cells[y * ow + x]; + nbackground[y * state->grid_width + x] = + state->background[y * ow + x]; + } + free (state->cells); + free (state->background); + state->cells = ncells; + state->background = nbackground; + + x = (ow < state->grid_width ? ow : state->grid_width); + for (i = 0; i < x; i++) + nfeeders[i] = state->feeders[i]; + free (state->feeders); + state->feeders = nfeeders; + } + if (state->tc) + textclient_reshape (state->tc, + state->xgwa.width, + state->xgwa.height, + state->grid_width - 2, + state->grid_height - 1); +} + +static Bool +xmatrix_event (Display *dpy, Window window, void *closure, XEvent *event) +{ + m_state *state = (m_state *) closure; + + if (event->xany.type == KeyPress) + { + KeySym keysym; + char c = 0; + XLookupString (&event->xkey, &c, 1, &keysym, 0); + switch (c) + { + case '0': + /*set_mode (state, DRAIN_MATRIX);*/ + state->back_y = 1; + state->back_text_full_p = True; + state->start_reveal_back_p = True; + return True; + + case '+': case '=': case '>': case '.': + state->density += 10; + if (state->density > 100) + state->density = 100; + else + return True; + break; + + case '-': case '_': case '<': case ',': + state->density -= 10; + if (state->density < 0) + state->density = 0; + else + return True; + break; + + case '[': case '(': case '{': + state->insert_top_p = True; + state->insert_bottom_p = False; + return True; + + case ']': case ')': case '}': + state->insert_top_p = False; + state->insert_bottom_p = True; + return True; + + case '\\': case '|': + state->insert_top_p = True; + state->insert_bottom_p = True; + return True; + + case 't': + set_mode (state, DRAIN_TRACE_A); + return True; + + case 'T': + set_mode (state, DRAIN_TRACE_B); + return True; + + case 'k': + set_mode (state, DRAIN_KNOCK); + return True; + + case 'c': + set_mode (state, DRAIN_NMAP); + return True; + + default: + return False; + } + } + + return False; +} + +static void +xmatrix_free (Display *dpy, Window window, void *closure) +{ + m_state *state = (m_state *) closure; + if (state->tc) + textclient_close (state->tc); + if (state->cursor_timer) + XtRemoveTimeOut (state->cursor_timer); + + /* #### there's more to free here */ + + free (state); +} + +static const char *xmatrix_defaults [] = { + ".background: black", + ".foreground: #00AA00", + "*fpsSolid: true", + "*matrixFont: large", + "*delay: 10000", + "*insert: both", + "*mode: Matrix", + "*tracePhone: (312) 555-0690", + "*spinners: 5", + "*density: 75", + "*trace: True", + "*knockKnock: True", + "*usePipe: False", + "*usePty: False", + "*program: xscreensaver-text", + "*geometry: 800x600", + 0 +}; + +static XrmOptionDescRec xmatrix_options [] = { + { "-small", ".matrixFont", XrmoptionNoArg, "Small" }, + { "-large", ".matrixFont", XrmoptionNoArg, "Large" }, + { "-delay", ".delay", XrmoptionSepArg, 0 }, + { "-insert", ".insert", XrmoptionSepArg, 0 }, + { "-top", ".insert", XrmoptionNoArg, "top" }, + { "-bottom", ".insert", XrmoptionNoArg, "bottom" }, + { "-both", ".insert", XrmoptionNoArg, "both" }, + { "-density", ".density", XrmoptionSepArg, 0 }, + { "-trace", ".trace", XrmoptionNoArg, "True" }, + { "-no-trace", ".trace", XrmoptionNoArg, "False" }, + { "-crack", ".mode", XrmoptionNoArg, "crack"}, + { "-phone", ".tracePhone", XrmoptionSepArg, 0 }, + { "-mode", ".mode", XrmoptionSepArg, 0 }, + { "-dna", ".mode", XrmoptionNoArg, "DNA" }, + { "-binary", ".mode", XrmoptionNoArg, "binary" }, + { "-hexadecimal", ".mode", XrmoptionNoArg, "hexadecimal"}, + { "-decimal", ".mode", XrmoptionNoArg, "decimal"}, + { "-knock-knock", ".knockKnock", XrmoptionNoArg, "True" }, + { "-no-knock-knock", ".knockKnock", XrmoptionNoArg, "False" }, + { "-ascii", ".mode", XrmoptionNoArg, "ascii"}, + { "-pipe", ".usePipe", XrmoptionNoArg, "True" }, + { "-no-pipe", ".usePipe", XrmoptionNoArg, "False" }, + { "-program", ".program", XrmoptionSepArg, 0 }, + { 0, 0, 0, 0 } +}; + +XSCREENSAVER_MODULE ("XMatrix", xmatrix) diff --git a/hacks/xmatrix.man b/hacks/xmatrix.man new file mode 100644 index 00000000..f3aaf68a --- /dev/null +++ b/hacks/xmatrix.man @@ -0,0 +1,146 @@ +.de EX \"Begin example +.ne 5 +.if n .sp 1 +.if t .sp .5 +.nf +.in +.5i +.. +.de EE +.fi +.in -.5i +.if n .sp 1 +.if t .sp .5 +.. +.TH XScreenSaver 1 "30-Oct-99" "X Version 11" +.SH NAME +xmatrix - simulates the computer displays from the movie +.SH SYNOPSIS +.B xmatrix +[\-display \fIhost:display.screen\fP] [\-window] [\-root] [\-install] +[\-visual \fIvisual\fP] +[\-delay \fIusecs\fP] +[\-density \fIpercentage\fP] +[\-top | \-bottom | \-both] +[\-small | \-large] +[\-trace] +[\-mode \fImode\fP] +[\-phone \fInumber\fP] +[\-fps] +.SH DESCRIPTION +The \fIxmatrix\fP program draws the 2D "digital rain" effect, as seen on +the computer monitors in the Wachowski brothers' film, "The Matrix". + +Also see +.BR glmatrix (MANSUFFIX) +for a 3D rendering of the similar effect that appeared in the title +sequence of the movie. +.SH OPTIONS +.I xmatrix +accepts the following options: +.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 \-install +Install a private colormap for the window. +.TP 8 +.B \-visual \fIvisual\fP\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 \-delay \fIusecs\fP +The delay between steps of the animation, in microseconds: default 10000. +.TP 8 +.B \-density \fIpercentage\fP +The approximate percentage of the screen that should be filled with +characters at any given time. Default 75%. + +When running in a window, typing \fB+\fP will increase the density and +typing \fB-\fP will decrease it. Typing \fB0\fP will momentarily +drain the screen. +.TP 8 +.B \-top\fP | \fB\-bottom\fP | \fB\-both +If \fB\-top\fP is specified, the characters will only drop in from the +top of the screen as sliding columns of characters. If \fB\-bottom\fP +is specified, then instead of sliding columns, the characters will appear +as columns that grow downwards and are erased from above. If \fB\-both\fP +is specified, then a mixture of both styles will be used. The default +is \fB\-both\fP. + +When running in a window, typing \fB[\fP will switch to top-mode, +typing \fB\]\fP will switch to bottom-mode, and typing \fB\\\fP will +switch to both-mode. +.TP 8 +.B \-small\fP | \fB\-large +These options specify the sizes of the characters. The default +is \fB\-large\fP. +.TP 8 +.B \-mode trace +Start off with a representation of a phone number being traced. +When the number is finally found, display The Matrix as usual. +This is the default. +.TP 8 +.B \-phone\fP \fInumber\fP +The phone number to trace, if \fB\-trace\fP is specified. +.TP 8 +.B \-mode crack +Start off by shutting down the power grid. +.TP 8 +.B \-mode binary +Instead of displaying Matrix glyphs, only display ones and zeros. +.TP 8 +.B \-mode hexadecimal +Instead of displaying Matrix glyphs, display hexadecimal digits. +.TP 8 +.B \-mode dna +Instead of displaying Matrix glyphs, display genetic code +(guanine, adenine, thymine, and cytosine.) +.TP 8 +.B \-mode ascii +Instead of displaying Matrix glyphs, display random ASCII characters. +.TP 8 +.B \-mode pipe +Instead of displaying random characters, display the output of a subprocess, +as ASCII. +.TP 8 +.B \-program \fIsh-command\fP +The command to run to generate the text to display. This option may +be any string acceptable to /bin/sh. The program will be run at the +end of a pty or pipe, and any characters that it prints to +\fIstdout\fP will be placed in the feeders for xmatrix. If the program +exits, it will be launched again after xmatrix has processed all the +text it produced. + +For example: +.EX +xmatrix -program 'echo Hello World' +xmatrix -ascii -program 'ps -eo comm | rev' +xmatrix -program 'od -txC -w6 /dev/random' +xmatrix -program 'cat /dev/random' +.EE +.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 glmatrix (MANSUFFIX), +.BR X (1), +.BR xscreensaver (1) +.SH COPYRIGHT +Copyright \(co 1999-2003 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 , 25-Apr-99. diff --git a/hacks/xml2man.pl b/hacks/xml2man.pl new file mode 100755 index 00000000..2e2ba162 --- /dev/null +++ b/hacks/xml2man.pl @@ -0,0 +1,250 @@ +#!/usr/bin/perl -w +# Copyright © 2002, 2005 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. +# +# Created: 30-May-2002. +# +# This creates man pages from the XML program descriptions in +# xscreensaver/hacks/config/. +# +# They aren't necessarily the most accurate or well-written man pages, +# but at least they exist. + +require 5; +use diagnostics; +use strict; + +use Text::Wrap; + +my $progname = $0; $progname =~ s@.*/@@g; +my $version = q{ $Revision: 1.3 $ }; $version =~ s/^[^0-9]+([0-9.]+).*$/$1/; + +my $verbose = 0; + +my $default_args = ("[\\-display \\fIhost:display.screen\\fP]\n" . + "[\\-visual \\fIvisual\\fP]\n" . + "[\\-window]\n" . + "[\\-root]\n"); +my $default_options = (".TP 8\n" . + ".B \\-visual \\fIvisual\\fP\n" . + "Specify which visual to use. Legal values " . + "are the name of a visual class,\n" . + "or the id number (decimal or hex) of a " . + "specific visual.\n" . + ".TP 8\n" . + ".B \\-window\n" . + "Draw on a newly-created window. " . + "This is the default.\n" . + ".TP 8\n" . + ".B \\-root\n" . + "Draw on the root window.\n"); + +my $man_suffix = (".SH ENVIRONMENT\n" . + ".PP\n" . + ".TP 8\n" . + ".B DISPLAY\n" . + "to get the default host and display number.\n" . + ".TP 8\n" . + ".B XENVIRONMENT\n" . + "to get the name of a resource file that overrides " . + "the global resources\n" . + "stored in the RESOURCE_MANAGER property.\n" . + ".SH SEE ALSO\n" . + ".BR X (1),\n" . + ".BR xscreensaver (1)\n" . + ".SH COPYRIGHT\n" . + "Copyright \\(co 2002 by %AUTHOR%. " . + "Permission to use, copy, modify, \n" . + "distribute, and sell this software and its " . + "documentation for any purpose is \n" . + "hereby granted without fee, provided that " . + "the above copyright notice appear \n" . + "in all copies and that both that copyright " . + "notice and this permission notice\n" . + "appear in supporting documentation. No " . + "representations are made about the \n" . + "suitability of this software for any purpose. " . + "It is provided \"as is\" without\n" . + "express or implied warranty.\n" . + ".SH AUTHOR\n" . + "%AUTHOR%.\n"); + +sub xml2man($) { + my ($exe) = @_; + my $cfgdir = (-d "config" ? "config" : "../config"); + my $xml = "$cfgdir/$exe.xml"; + my $man = "$exe.man"; + + error ("$exe does not exist") if (! -f $exe); + error ("$xml does not exist") if (! -f $xml); + error ("$man already exists") if (-f $man); + + local *IN; + open (IN, "<$xml") || error ("$xml: $!"); + my $xmltxt = ""; + while () { $xmltxt .= $_; } + close IN; + + my $args = ""; + my $body = ""; + my $desc; + + $xmltxt =~ s/\s+/ /gs; + $xmltxt =~ s///g; + $xmltxt =~ s@(<[^/])@\n$1@gs; + + foreach (split ('\n', $xmltxt)) { + next if m/^$/; + next if m/^<\?xml\b/; + next if m/^= 10000) { + $label = "Per-frame delay, in microseconds."; + $def = sprintf ("%d (%0.2f seconds.)", $def, ($def/1000000.0)); + $low = $hi = undef; + } elsif ($boolp) { + $label .= ". Boolean."; + } elsif ($label) { + $label .= "."; + } + + if (m/^<(number|boolean|option)/) { + + next if (!$arg && m/